diff --git a/.github/assets/bolt-logo-wm-dark.png b/.github/assets/bolt-logo-wm-dark.png deleted file mode 100644 index ed152e36e..000000000 Binary files a/.github/assets/bolt-logo-wm-dark.png and /dev/null differ diff --git a/.github/assets/bolt-logo-wm-light.png b/.github/assets/bolt-logo-wm-light.png deleted file mode 100644 index e6e366c26..000000000 Binary files a/.github/assets/bolt-logo-wm-light.png and /dev/null differ diff --git a/.github/workflows/sidecar_ci.yml b/.github/workflows/sidecar_ci.yml deleted file mode 100644 index 87ee18fdb..000000000 --- a/.github/workflows/sidecar_ci.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Bolt-sidecar CI - -on: [push, pull_request] - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - cargo-tests: - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - - - name: Cache cargo registry - uses: Swatinem/rust-cache@v2 - with: - cache-on-failure: true - - - name: Install cargo-nextest - uses: baptiste0928/cargo-install@v1 - with: - crate: cargo-nextest - args: --locked - - - name: Run all tests - run: cd bolt-sidecar && cargo nextest run --workspace --retries 3 - env: - RPC_URL: ${{ secrets.RPC_URL }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 39d24fd76..000000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*_dump.log diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 7fe3b3345..000000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "bolt-contracts/lib/forge-std"] - path = bolt-contracts/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "bolt-contracts/lib/openzeppelin-contracts"] - path = bolt-contracts/lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "bolt-contracts/lib/relic-sdk"] - path = bolt-contracts/lib/relic-sdk - url = https://github.com/Relic-Protocol/relic-sdk diff --git a/Justfile b/Justfile deleted file mode 100644 index 3e7104df6..000000000 --- a/Justfile +++ /dev/null @@ -1,171 +0,0 @@ -# default recipe to display help information -default: - @just --list --unsorted - -# run the web demo locally -demo: - chmod +x ./scripts/start-demo.sh - ./scripts/start-demo.sh - -# spin up the bolt devnet -up: - chmod +x ./scripts/start-devnet.sh - ./scripts/start-devnet.sh - -# turn down the bolt devnet and remove the enclave -down: - kurtosis enclave rm -f bolt-devnet - -# remove all kurtosis data and stop the engine -clean: - kurtosis clean --all - kurtosis engine stop - -# restart the bolt devnet with updated docker images -restart: - @just down - @just build-images - @just up - -_restart-sidecar: - @just down - @just _build-sidecar - @just up - -# show the running containers and port mappings for the bolt devnet -inspect: - kurtosis enclave inspect bolt-devnet - -# show the logs for the bolt devnet relay -relay-logs: - @id=$(docker ps -n 100 | grep mev-relay-api | awk -F' ' '{print $1}') && \ - docker logs -f $id - -# show the logs for the bolt devnet builder -builder-logs: - @id=$(docker ps -n 100 | grep bolt-builder | awk -F' ' '{print $1}') && \ - docker logs -f $id - -# show the logs for the bolt devnet mev-boost sidecar -boost-logs: - @id=$(docker ps -n 100 | grep bolt-mev-boost | awk -F' ' '{print $1}') && \ - docker logs -f $id - -# show the logs for the bolt devnet bolt-sidecar -sidecar-logs: - @id=$(docker ps -n 100 | grep sidecar | awk -F' ' '{print $1}') && \ - docker logs -f $id - -# show the logs for the bolt devnet for beacon node -beacon-logs: - @id=$(docker ps -n 100 | grep 'cl-1-lighthouse-geth' | awk -F' ' '{print $1}') && \ - docker logs -f $id - -# show the logs for the bolt devnet for beacon node -beacon-dump: - @id=$(docker ps -n 100 | grep 'cl-1-lighthouse-geth' | awk -F' ' '{print $1}') && \ - docker logs $id 2>&1 | tee beacon_dump.log - -# show the logs for the bolt devnet relay -relay-dump: - @id=$(docker ps -n 100 | grep mev-relay-api | awk -F' ' '{print $1}') && \ - docker logs $id 2>&1 | tee relay_dump.log - -# show the logs for the bolt devnet builder -builder-dump: - @id=$(docker ps -n 100 | grep bolt-builder | awk -F' ' '{print $1}') && \ - docker logs $id 2>&1 | tee builder_dump.log - -# show the logs for the bolt devnet mev-boost sidecar -boost-dump: - @id=$(docker ps -n 100 | grep bolt-mev-boost | awk -F' ' '{print $1}') && \ - docker logs $id 2>&1 | tee boost_dump.log - -# show the logs for the bolt devnet bolt-sidecar -sidecar-dump: - @id=$(docker ps -n 100 | grep sidecar | awk -F' ' '{print $1}') && \ - docker logs $id 2>&1 | tee sidecar_dump.log - - -# show the logs for the bolt devnet builder -kill-builder: - @id=$(docker ps -n 100 | grep bolt-builder | awk -F' ' '{print $1}') && \ - docker stop $id - -# show the dora explorer in the browser. NOTE: works only for Linux and MacOS at the moment -dora: - @url=$(just inspect | grep 'dora\s*http' | awk -F'-> ' '{print $2}' | awk '{print $1}') && \ - if [ "$(uname)" = "Darwin" ]; then \ - open "$url"; \ - else \ - xdg-open "$url"; \ - fi - -# manually send a preconfirmation to the bolt devnet -send-preconf count='1': - cd bolt-kurtosis-client && RUST_LOG=info cargo run -- \ - --provider-url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \ - --beacon-client-url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \ - --bolt-sidecar-url http://$(kurtosis port print bolt-devnet mev-sidecar-api api) \ - --private-key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \ - --slot head \ - --count {{count}} - -# manually send a blob preconfirmation to the bolt devnet -send-blob-preconf count='1': - cd bolt-kurtosis-client && RUST_LOG=info cargo run -- \ - --provider-url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \ - --beacon-client-url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \ - --bolt-sidecar-url http://$(kurtosis port print bolt-devnet mev-sidecar-api api) \ - --private-key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \ - --slot head \ - --blob \ - --count {{count}} \ - -# build all the docker images locally -build-images: - @just _build-builder - @just _build-relay - @just _build-sidecar - @just _build-mevboost - -# build the docker image for the bolt builder -_build-builder: - cd builder && docker buildx build -t ghcr.io/chainbound/bolt-builder:0.1.0 . --load - -# build the docker image for the bolt relay -_build-relay: - cd mev-boost-relay && docker buildx build -t ghcr.io/chainbound/bolt-relay:0.1.0 . --load - -# build the docker image for the bolt sidecar -_build-sidecar: - cd bolt-sidecar && docker buildx build -t ghcr.io/chainbound/bolt-sidecar:0.1.0 . --load - -# build the docker image for the bolt mev-boost sidecar -_build-mevboost: - cd mev-boost && docker buildx build -t ghcr.io/chainbound/bolt-mev-boost:0.1.0 . --load - -# deploy the bolt sidecar to the dev server -deploy-sidecar-dev: - chmod +x ./scripts/deploy_bolt_sidecar.sh && ./scripts/deploy_bolt_sidecar.sh - -# Check the status of the sidecar service on the dev server -status-sidecar-dev: - ssh shared@remotebeast "sudo systemctl status bolt_sidecar" | less - -# Tail the logs of the service on the dev server -logs-sidecar-dev: - ssh shared@remotebeast "journalctl -qu bolt_sidecar -f" - -# Stop the service on the dev server -stop-sidecar-dev: - ssh shared@remotebeast "sudo systemctl stop bolt_sidecar" - - -# build and push the docker images to the github container registry with the provided tag -[confirm("are you sure? this will build and push new images on ghcr.io")] -release tag: - cd bolt-sidecar && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-sidecar:{{tag}} --push . - cd mev-boost-relay && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-relay:{{tag}} --push . - cd builder && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-builder:{{tag}} --push . - cd mev-boost && docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/chainbound/bolt-mev-boost:{{tag}} --push . diff --git a/LICENSE b/LICENSE deleted file mode 100644 index c385ee418..000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Chainbound - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 48e3b1978..000000000 --- a/README.md +++ /dev/null @@ -1,188 +0,0 @@ -
- - - - BOLT - -
- -
- -[![Docs](https://img.shields.io/badge/Docs-7B36ED?style=for-the-badge&logo=gitbook&logoColor=white)][docs] -[![Twitter](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white)][twitter] -[![Discord](https://img.shields.io/badge/Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)][discord] - -
- -> [!IMPORTANT] -> Bolt is an implementation of _permissionless proposer commitments through -> PBS_. In its essence, it consists in a light fork of the current MEV-Boost -> stack that allows users to request **preconfirmations** from proposers, and -> then adds a way for proposers to commit to transaction inclusion in a way that -> is easily verifiable. - - - -- [How it works](#how-it-works) -- [Scope of this repository](#scope-of-this-repository) -- [Devnet and demo app](#devnet-and-demo-app) - - [Requirements and setup](#requirements-and-setup) - - [Running the devnet and demo](#running-the-devnet-and-demo) - - [Stopping the devnet and demo](#stopping-the-devnet-and-demo) - - - -## How it works - -The flow of Bolt can be summarized in the following steps: - -1. Users submit transactions to an RPC endpoint that will forward them to the - proposer opted-in to Bolt in the consensus lookahead window. -2. The proposer can accept this request and turn it into a "constraint" on the block - that it is going to propose. This constraint acts as guarantee of inclusion of - the transaction in the block, also known as a _preconfirmation_. -3. Builders subscribe to proposer constraints in real time through a new relay - streaming endpoint to keep informed about the preconfirmations. -4. Builders build valid blocks that adhere to all constraints, and append inclusion - proofs together with the bids to the relay. -5. When it's time to propose a block, the proposer will fetch the best valid bid - from the relay, and verify its inclusion proofs locally before signing the header. -6. If the constraints are respected, the proposer can propose the payload as usual - by sending the signed header back to the relay. If not, the proposer can self-build - a payload and propose it directly instead. - -The following diagram illustrates the flow: - -```mermaid -sequenceDiagram - participant Beacon Node as beacon node - participant Bolt Sidecar as bolt-sidecar - participant MEV-Boost as mev-boost - participant PBS Relay as pbs relay - - Beacon Node->>Bolt Sidecar: /eth/v1/builder/header - Note over Beacon Node, Bolt Sidecar: when it's time, the proposer's beacon node will ask for an externally built payload - - Bolt Sidecar->>MEV-Boost: /eth/v1/builder/header - MEV-Boost->>PBS Relay: /eth/v1/builder/header_with_proofs - PBS Relay->>MEV-Boost: ExecutionPayloadHeader + InclusionProofs - MEV-Boost->>Bolt Sidecar: ExecutionPayloadHeader + InclusionProofs - - alt Inclusion proofs sent by the relay are VALID - Bolt Sidecar->>Beacon Node: ExecutionPayloadHeader - Bolt Sidecar->>MEV-Boost: /eth/v1/builder/blinded-blocks - MEV-Boost->>PBS Relay: /eth/v1/builder/blinded-blocks - Note over MEV-Boost, PBS Relay: the relay can now broadcast the full payload. - else Inclusion proofs sent by the relay are INVALID - PBS Relay->>MEV-Boost: nil response - Bolt Sidecar->>Beacon Node: bolt-sidecar will generate a fallback ExecutionPayload that follows all constraints committed to by the proposer. - Bolt Sidecar->>MEV-Boost: /eth/v1/builder/blinded-blocks - MEV-Boost->>PBS Relay: /eth/v1/builder/blinded-blocks - PBS Relay->>Beacon Node: ExecutionPayload - Note over Beacon Node, Bolt Sidecar: after receiving the payload, the beacon node will broadcast it to the beacon chain p2p network. - end -``` - -## Scope of this repository - -This repository contains all the necessary components to illustrate the flow -described above. It can be thought of a reference implementation. -In particular, the core components are: - -- [**Bolt Sidecar**](./bolt-sidecar/): New validator software (akin to [mev-boost][fb-mev-boost]) - that handles the receipt of preconfirmation requests from users, translates them - into constraints, and forwards them to relays. Additionally, it handles the - fallback logic to produce a block locally when relays send invalid inclusion proofs. -- [**Builder**](./builder/): A fork of the [Flashbots builder][fb-builder] that - subscribes to new constraints from relays, builds blocks that respect them, and - includes the necessary proofs of inclusion in the bid submitted to relays. -- [**Relay**](./mev-boost-relay/): A fork of the [Flashbots relay][fb-relay] that - receives constraints from proposers, and forwards them to builders. It also - receives bids with proofs of inclusion from builders, verifies them and forwards - the best bid to proposers for block proposal. -- [**MEV-Boost**](./mev-boost/): A fork of the [Flashbots MEV-Boost][fb-mev-boost] sidecar - that includes new API endpoints to proxy requests from the Bolt Sidecar to the connected relays. -- [**Bolt Contracts**](./bolt-contracts/): A set of smart contracts for peripheral functionality - such as proposer registration and permissionless dispute resolution for attributable faults. - -Additionally, this repository contains the necessary scripts to spin up a [Kurtosis][kurtosis] devnet -with all the components running, and a simple [web demo](./bolt-web-demo/) to showcase the preconfirmation flow. - -## Devnet and demo app - -We are using a full [Kurtosis][kurtosis] devnet stack, with custom Docker images -for the core components outlined above. The exact version of the Ethereum-package used -in our devnet can be seen [here](https://github.com/chainbound/ethereum-package). - -### Requirements and setup - -8GB of RAM and a modern laptop CPU are recommended to run the devnet efficiently, -but it should work on most machines. Please [Open an issue][new-issue] if you encounter any problems. - -Make sure you have the following requirements on your machine: - -- [Docker engine](https://docs.docker.com/engine/install/) installed and running -- [Just](https://github.com/casey/just) installed -- [Kurtosis CLI](https://docs.kurtosis.com/install/) installed -- [Foundry](https://book.getfoundry.sh/getting-started/installation) installed - -> [!WARNING] -> The Kurtosis CLI version tested is `0.88.16`. Some issues may arise if you are -> using a different version. Please make sure to install the correct version. - -Then, clone this repository and navigate to the root directory of the project: - -```shell -git clone git@github.com:chainbound/bolt.git && cd bolt -``` - -### Running the devnet and demo - -Running the devnet and demo is straightforward once you have the requirements -installed. Just run the following commands in your terminal: - -```shell -# build all necessary docker images locally first -just build-images - -# spin up the kurtosis devnet on your machine -just up - -# run the web demo servers. -just demo -``` - -The web demo will be available on your browser at [`http://localhost:3000`](http://localhost:3000). - -### Stopping the devnet and demo - -The demo app will remain open until you press `Ctrl+C` in the terminal where -you ran the `just demo` command. - -To stop the devnet, run the following command: - -```shell -# if you want to simply stop all running containers -just down - -# if you want to remove all the data and stop the Kurtosis engine -just clean -``` - -> [!WARNING] -> Remember to shut down the devnet environment when you are done with it, as it -> consumes significant resources (CPU & RAM) on your machine. - - - -[twitter]: https://twitter.com/chainbound_ -[discord]: https://discord.gg/pK8GgjxYQS -[docs]: https://chainbound.github.io/bolt-docs/ -[new-issue]: https://github.com/chainbound/bolt/issues/new -[fb-mev-boost]: https://github.com/flashbots/mev-boost -[fb-relay]: https://github.com/flashbots/mev-boost-relay -[fb-builder]: https://github.com/flashbots/builder -[kurtosis]: https://www.kurtosis.com/ - -## License -MIT. Forked repositories have their own licenses. diff --git a/bolt-client/.gitignore b/bolt-client/.gitignore deleted file mode 100644 index 5f32e705c..000000000 --- a/bolt-client/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target/ -.env \ No newline at end of file diff --git a/bolt-client/Cargo.lock b/bolt-client/Cargo.lock deleted file mode 100644 index 0a8fe5832..000000000 --- a/bolt-client/Cargo.lock +++ /dev/null @@ -1,4747 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "alloy" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45855eb65e9cc70294ebea1279f6d8ee0636bf2ed3897683ebbae2739975ae8c" -dependencies = [ - "alloy-consensus", - "alloy-contract", - "alloy-core", - "alloy-eips", - "alloy-genesis", - "alloy-network", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", -] - -[[package]] -name = "alloy-chains" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1752d7d62e2665da650a36d84abbf239f812534475d51f072a49a533513b7cdd" -dependencies = [ - "num_enum", - "strum", -] - -[[package]] -name = "alloy-consensus" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58047cc851e58c26224521d1ecda466e3d746ebca0274cd5427aa660a88c353" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "c-kzg", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5d42d9f87896536234b0fac1a84ad9d9dc7a4b27839cac35d0899e64ddf083" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network", - "alloy-primitives", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-types-eth", - "alloy-sol-types", - "alloy-transport", - "futures", - "futures-util", - "thiserror", -] - -[[package]] -name = "alloy-core" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529fc6310dc1126c8de51c376cbc59c79c7f662bd742be7dc67055d5421a81b4" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", -] - -[[package]] -name = "alloy-dyn-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "const-hex", - "itoa", - "serde", - "serde_json", - "winnow 0.6.15", -] - -[[package]] -name = "alloy-eips" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a3e14fa0d152d00bd8daf605eb74ad397efb0f54bd7155585823dddb4401e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "c-kzg", - "derive_more", - "k256 0.13.3", - "once_cell", - "serde", - "sha2 0.10.8", -] - -[[package]] -name = "alloy-genesis" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cb76c8a3913f2466c5488f3a915e3a15d15596bdc935558c1a9be75e9ec508" -dependencies = [ - "alloy-primitives", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-json-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a9feec2352c78545d1a37415699817bae8dc41654bd1bfe57d6cdd5433bd" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3223d71dc78f464b2743418d0be8b5c894313e272105a6206ad5e867d67b3ce2" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", - "async-trait", - "auto_impl", - "futures-utils-wasm", - "thiserror", -] - -[[package]] -name = "alloy-primitives" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "hex-literal", - "itoa", - "k256 0.13.3", - "keccak-asm", - "proptest", - "rand 0.8.5", - "ruint", - "serde", - "tiny-keccak", -] - -[[package]] -name = "alloy-provider" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29da7457d853cb8199ec04b227d5d2ef598be3e59fc2bbad70c8be213292f32" -dependencies = [ - "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-primitives", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types-eth", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "futures", - "futures-utils-wasm", - "lru", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "alloy-pubsub" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64acfec654ade392cecfa9bba0408eb2a337d55f1b857925da79970cb70f3d6" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "bimap", - "futures", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9e609524fa31c2c70eb24c0da60796809193ad4787a6dfe6d0db0d3ac112d" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-pubsub", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "futures", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5d76f1e8b22f48b7b8f985782b68e7eb3938780e50e8b646a53e41a598cdf5" -dependencies = [ - "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-engine" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73445fbc5c02258e3d0d977835c92366a4d91545fd456c3fc8601c61810bc9f6" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", - "jsonwebtoken", - "rand 0.8.5", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605fa8462732bb8fd0645a9941e12961e079d45ae6a44634c826f8229c187bdf" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-sol-types", - "itertools 0.13.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c5b9057acc02aee1b8aac2b5a0729cb0f73d080082c111313e5d1f92a96630" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-signer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37f10592696f4ab8b687d5a8ab55e998a14ea0ca5f8eb20ad74a96ad671bb54a" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "elliptic-curve 0.13.8", - "k256 0.13.3", - "thiserror", -] - -[[package]] -name = "alloy-signer-local" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b537f3e55f30753578f4623d5f66ddad8fa582af3fa6b15bad23dd1b9775228" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "k256 0.13.3", - "rand 0.8.5", - "thiserror", -] - -[[package]] -name = "alloy-sol-macro" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" -dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "alloy-sol-macro-expander" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" -dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", - "const-hex", - "heck", - "indexmap 2.2.6", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.72", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-macro-input" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.72", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" -dependencies = [ - "serde", - "winnow 0.6.15", -] - -[[package]] -name = "alloy-sol-types" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "const-hex", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b44b0f6f4a2593b258fa7b6cae8968e6a4c404d9ef4f5bc74401f2d04fa23fa" -dependencies = [ - "alloy-json-rpc", - "base64 0.22.1", - "futures-util", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-http" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8f1eefa8cb9e7550740ee330feba4fed303a77ad3085707546f9152a88c380" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest 0.12.5", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-ipc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31007c56dc65bd81392112dda4a14c20ac7e30bb4cb2e9176192e8d9fab1983f" -dependencies = [ - "alloy-json-rpc", - "alloy-pubsub", - "alloy-transport", - "bytes", - "futures", - "interprocess", - "pin-project", - "serde_json", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "alloy-transport-ws" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ccc1c8f8ae415e93ec0e7851bd4cdf4afdd48793d13a91b860317da1f36104" -dependencies = [ - "alloy-pubsub", - "alloy-transport", - "futures", - "http 1.1.0", - "rustls", - "serde_json", - "tokio", - "tokio-tungstenite", - "tracing", - "ws_stream_wasm", -] - -[[package]] -name = "anstream" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" - -[[package]] -name = "anstyle-parse" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "arrayref" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-sse" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6fa871e4334a622afd6bb2f611635e8083a6f5e2936c0f90f37c7ef9856298" -dependencies = [ - "async-channel", - "futures-lite", - "http-types", - "log", - "memchr", - "pin-project-lite", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "async-trait" -version = "0.1.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "beacon-api-client" -version = "0.1.0" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "clap", - "ethereum-consensus", - "http 0.2.12", - "itertools 0.10.5", - "mev-share-sse", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blst" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "bolt-rpc-client" -version = "0.1.0" -dependencies = [ - "alloy", - "beacon-api-client", - "clap", - "dotenvy", - "eyre", - "rand 0.8.5", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - -[[package]] -name = "cc" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "num-traits", -] - -[[package]] -name = "clap" -version = "4.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6b81fb3c84f5563d509c59b5a48d935f689e993afa90fe39047f05adef9142" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca6706fd5224857d9ac5eb9355f6683563cc0541c7cd9d014043b57cbec78ac" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "clap_lex" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" - -[[package]] -name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-hex" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 2.0.72", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "doctest-file" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.9", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.0", - "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.3", - "subtle", - "zeroize", -] - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enr" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" -dependencies = [ - "base64 0.13.1", - "bs58", - "bytes", - "hex", - "k256 0.11.6", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-consensus" -version = "0.1.1" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "blst", - "bs58", - "c-kzg", - "enr", - "hex", - "integer-sqrt", - "multiaddr", - "multihash", - "rand 0.8.5", - "serde", - "serde_json", - "serde_yaml", - "sha2 0.10.8", - "ssz_rs", - "thiserror", - "tokio", - "tokio-stream", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve 0.13.8", - "ethabi", - "generic-array", - "k256 0.13.3", - "num_enum", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel", - "base64 0.13.1", - "futures-lite", - "infer", - "pin-project-lite", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.30", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" -dependencies = [ - "num-traits", -] - -[[package]] -name = "interprocess" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f4e4a06d42fab3e85ab1b419ad32b09eab58b901d40c57935ff92db3287a13" -dependencies = [ - "doctest-file", - "futures-core", - "libc", - "recvmsg", - "tokio", - "widestring", - "windows-sys 0.52.0", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" -dependencies = [ - "base64 0.21.7", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "once_cell", - "sha2 0.10.8", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mev-share-sse" -version = "0.1.6" -source = "git+https://github.com/paradigmxyz/mev-share-rs?rev=9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8#9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8" -dependencies = [ - "async-sse", - "bytes", - "ethers-core", - "futures-util", - "http-types", - "pin-project-lite", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multihash" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" -dependencies = [ - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" -dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "object" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.9", - "spki 0.7.3", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.6.0", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "recvmsg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-rustls", - "hyper-tls 0.6.0", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 2.1.2", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.52.0", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ruint" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.23", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" - -[[package]] -name = "rustls-webpki" -version = "0.102.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scale-info" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - -[[package]] -name = "serde" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" -dependencies = [ - "cc", - "cfg-if", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.9", -] - -[[package]] -name = "ssz_rs" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "alloy-primitives", - "bitvec", - "serde", - "sha2 0.9.9", - "ssz_rs_derive", -] - -[[package]] -name = "ssz_rs_derive" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.72", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn-solidity" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand 2.1.0", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" -dependencies = [ - "futures-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "nu-ansi-term", - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.8.5", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unsigned-varint" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.72", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "wasm-streams" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557404e450152cd6795bb558bca69e43c585055f4606e3bcae5894fc6dac9ba0" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] diff --git a/bolt-client/Cargo.toml b/bolt-client/Cargo.toml deleted file mode 100644 index 0b671c321..000000000 --- a/bolt-client/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "bolt-rpc-client" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -tokio = { version = "1.37.0", features = ["full"] } - -alloy = { version = "0.2.0", features = ["full"] } -beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } - -clap = { version = "4.5.4", features = ["derive", "env"] } -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.115" -eyre = "0.6.12" -rand = "0.8.5" -url = "2.5.2" -dotenvy = "0.15.7" -reqwest = "0.12.3" - -tracing = "0.1.40" -tracing-subscriber = "0.3.18" diff --git a/bolt-client/README.md b/bolt-client/README.md deleted file mode 100644 index 2566a78b3..000000000 --- a/bolt-client/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Bolt CLI client - -This is a simple CLI tool to interact with Bolt. - -## Requirements - -- [Rust toolchain & Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed -- A wallet with some funds to send transactions - -## How to use - -Bolt Client offers different ways to send commitment requests. Here's how to use them: - -### Use the default Bolt RPC - -For regular usage, you can use the default Bolt RPC server to automatically fetch the -lookahead data from the beacon chain and send the transaction to the next Bolt sidecar in line. - -To do this, prepare the environment variables (either in a `.env` file, or as CLI arguments): - -- `BOLT_PRIVATE_KEY` or `--private-key`: the private key of the account to send transactions from -- `--blob`: bool flag to send a blob-carrying transaction (default: false) -- `--count`: the number of transactions to send in a single request (default: 1) - -Run the CLI tool: - -```shell - cargo run -``` - -### Use your own beacon node and registry contract - -If you don't want to use the default RPC server, you can send transactions manually. -To do this, you need to provide the following environment variables (either in a `.env` file, or as CLI arguments): - -- `--use-registry`: bool flag to fetch data from a local node instead of the RPC_URL (default: false) -- `BOLT_RPC_URL` or `--rpc-url`: the URL of an execution client (e.g. Geth)'s RPC server (default: Chainbound's RPC) -- `BOLT_NONCE_OFFSET` or `--nonce-offset`: the offset to add to the account's nonce (default: 0) -- `BOLT_REGISTRY_ADDRESS` or `--registry-address`: the address of the bolt-registry smart contract -- `BOLT_BEACON_CLIENT_URL` or `--beacon-client-url`: the URL of the beacon client's HTTP server - -Run the CLI tool with the desired command and arguments, if any. - -```shell - cargo run -- [options] -``` diff --git a/bolt-client/rustfmt.toml b/bolt-client/rustfmt.toml deleted file mode 100644 index 68c3c9303..000000000 --- a/bolt-client/rustfmt.toml +++ /dev/null @@ -1,11 +0,0 @@ -reorder_imports = true -imports_granularity = "Crate" -use_small_heuristics = "Max" -comment_width = 100 -wrap_comments = true -binop_separator = "Back" -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true -format_code_in_doc_comments = true -doc_comment_code_block_width = 100 diff --git a/bolt-client/src/main.rs b/bolt-client/src/main.rs deleted file mode 100644 index 53b41af63..000000000 --- a/bolt-client/src/main.rs +++ /dev/null @@ -1,167 +0,0 @@ -use alloy::{ - eips::eip2718::Encodable2718, - hex, - network::{EthereumWallet, TransactionBuilder}, - primitives::{address, Address, B256}, - providers::{Provider, ProviderBuilder}, - signers::local::PrivateKeySigner, -}; -use beacon_api_client::mainnet::Client as BeaconApiClient; -use clap::Parser; -use eyre::{bail, Result}; -use serde_json::{json, Value}; -use tracing::info; -use url::Url; - -mod registry; -use registry::BoltRegistry; - -mod utils; -use utils::*; - -// Default Bolt RPC URL (on Helder) -pub const DEFAULT_RPC_URL: &str = "https://bolt.chainbound.io/rpc"; - -// Default Bolt-Registry address (on Helder) -pub const DEFAULT_REGISTRY: Address = address!("dF11D829eeC4C192774F3Ec171D822f6Cb4C14d9"); - -#[derive(Parser)] -struct Opts { - /// Bolt RPC URL to send requests to - #[clap(long, default_value = DEFAULT_RPC_URL, env = "BOLT_RPC_URL")] - rpc_url: Url, - /// Private key to sign transactions with - #[clap(short = 'k', long, env = "BOLT_PRIVATE_KEY")] - private_key: String, - /// Optional nonce offset to use for the transaction - #[clap(long, default_value_t = 0, env = "BOLT_NONCE_OFFSET")] - nonce_offset: u64, - /// Flag for generating a blob tx instead of a regular tx - #[clap(long, default_value_t = false)] - blob: bool, - /// Number of transactions to send in a sequence - #[clap(long, default_value_t = 1)] - count: u64, - /// Flag for sending all "count" transactions in a single bundle - #[clap(long, default_value_t = false)] - bundle: bool, - - /// Flag for using the registry to fetch the lookahead - #[clap(long, default_value_t = false, requires_ifs([("true", "registry_address"), ("true", "beacon_client_url")]))] - use_registry: bool, - /// URL of the beacon client to use for fetching the lookahead - /// (only used with the "use-registry" flag) - #[clap(short = 'b', long, env = "BOLT_BEACON_CLIENT_URL")] - beacon_client_url: Option, - /// Address of the registry contract to read bolt sidecars from - /// (only used with the "use-registry" flag) - #[clap(long, env = "BOLT_REGISTRY_ADDRESS", default_value_t = DEFAULT_REGISTRY)] - registry_address: Address, -} - -#[tokio::main] -async fn main() -> Result<()> { - tracing_subscriber::fmt::init(); - info!("starting bolt-client"); - - let _ = dotenvy::dotenv(); - let mut opts = Opts::parse(); - - let wallet: PrivateKeySigner = opts.private_key.parse().expect("invalid private key"); - let transaction_signer: EthereumWallet = wallet.clone().into(); - let provider = ProviderBuilder::new().on_http(opts.rpc_url.clone()); - let sender = wallet.address(); - - let (target_sidecar_url, target_slot) = if opts.use_registry { - // Fetch the next preconfer slot from the registry and use it - let beacon_api_client = BeaconApiClient::new(opts.beacon_client_url.unwrap()); - let registry = BoltRegistry::new(opts.rpc_url, opts.registry_address); - let curr_slot = get_current_slot(&beacon_api_client).await?; - let duties = get_proposer_duties(&beacon_api_client, curr_slot, curr_slot / 32).await?; - match registry.next_preconfer_from_registry(duties).await { - Ok(Some((endpoint, slot))) => (Url::parse(&endpoint)?, slot), - Ok(None) => bail!("no next preconfer slot found, try again later"), - Err(e) => bail!("error fetching next preconfer slot from registry: {:?}", e), - } - } else { - let url = opts.rpc_url.join("proposers/lookahead?activeOnly=true&futureOnly=true")?; - let lookahead_response = reqwest::get(url).await?.json::().await?; - if lookahead_response.as_array().unwrap_or(&vec![]).is_empty() { - bail!("no bolt proposer found in lookahead, try again later 🥲"); - } - let next_preconfer_slot = lookahead_response[0].get("slot").unwrap().as_u64().unwrap(); - (opts.rpc_url, next_preconfer_slot) - }; - - let mut txs_rlp = Vec::with_capacity(opts.count as usize); - let mut tx_hashes = Vec::with_capacity(opts.count as usize); - for _ in 0..opts.count { - let mut tx = if opts.blob { generate_random_blob_tx() } else { generate_random_tx() }; - tx.set_from(sender); - tx.set_chain_id(provider.get_chain_id().await?); - tx.set_nonce(provider.get_transaction_count(sender).await? + opts.nonce_offset); - - // Set the nonce offset for the next transaction - opts.nonce_offset += 1; - - let tx_signed = tx.build(&transaction_signer).await?; - let tx_hash = tx_signed.tx_hash(); - let tx_rlp = hex::encode(tx_signed.encoded_2718()); - - if opts.bundle { - // store transactions in a bundle to send them all at once - txs_rlp.push(tx_rlp); - tx_hashes.push(*tx_hash); - } else { - // Send rpc requests singularly for each transaction - send_rpc_request( - vec![tx_rlp], - vec![*tx_hash], - target_slot, - target_sidecar_url.clone(), - &wallet, - ) - .await?; - } - } - - if opts.bundle { - send_rpc_request(txs_rlp, tx_hashes, target_slot, target_sidecar_url, &wallet).await?; - } - - Ok(()) -} - -async fn send_rpc_request( - txs_rlp: Vec, - tx_hashes: Vec, - target_slot: u64, - target_sidecar_url: Url, - wallet: &PrivateKeySigner, -) -> Result<()> { - let request = prepare_rpc_request( - "bolt_requestInclusion", - json!({ - "slot": target_slot, - "txs": txs_rlp, - }), - ); - - info!(?tx_hashes, target_slot, %target_sidecar_url); - let signature = sign_request(tx_hashes, target_slot, wallet).await?; - - let response = reqwest::Client::new() - .post(target_sidecar_url) - .header("content-type", "application/json") - .header("x-bolt-signature", signature) - .body(serde_json::to_string(&request)?) - .send() - .await?; - - let response = response.text().await?; - - // strip out long series of zeros in the response (to avoid spamming blob contents) - let response = response.replace(&"0".repeat(32), ".").replace(&".".repeat(4), ""); - info!("Response: {:?}", response); - Ok(()) -} diff --git a/bolt-client/src/registry.rs b/bolt-client/src/registry.rs deleted file mode 100644 index 429389de6..000000000 --- a/bolt-client/src/registry.rs +++ /dev/null @@ -1,241 +0,0 @@ -use std::str::FromStr; - -use alloy::{ - contract::{Error as ContractError, Result as ContractResult}, - primitives::{Address, Bytes}, - providers::{ProviderBuilder, RootProvider}, - sol, - sol_types::{Error as SolError, SolInterface}, - transports::{http::Http, TransportError}, -}; -use beacon_api_client::ProposerDuty; -use reqwest::Client; -use tracing::info; -use url::Url; -use BoltRegistryContract::{BoltRegistryContractErrors, BoltRegistryContractInstance, Registrant}; - -#[derive(Debug, Clone)] -pub struct BoltRegistry(BoltRegistryContractInstance, RootProvider>>); - -impl BoltRegistry { - pub fn new>(execution_client_url: U, registry_address: Address) -> Self { - let provider = ProviderBuilder::new().on_http(execution_client_url.into()); - let registry = BoltRegistryContract::new(registry_address, provider); - - Self(registry) - } - - /// Gets the sidecar RPC URL for a given validator index. - /// - /// Returns Ok(None) if the operator is not found in the registry. - #[allow(unused)] - pub async fn get_sidecar_rpc_url_for_validator( - &self, - validator_index: u64, - ) -> ContractResult> { - let registrant = self.get_registrant_for_validator(validator_index).await?; - Ok(registrant.map(|r| r.metadata.rpc)) - } - - /// Gets the operator for a given validator index. - /// - /// Returns Ok(None) if the operator is not found in the registry. - pub async fn get_registrant_for_validator( - &self, - validator_index: u64, - ) -> ContractResult> { - let returndata = self.0.getOperatorForValidator(validator_index).call().await; - - // TODO: clean this after https://github.com/alloy-rs/alloy/issues/787 is merged - let error = match returndata.map(|data| data._0) { - Ok(registrant) => return Ok(Some(registrant)), - Err(error) => match error { - ContractError::TransportError(TransportError::ErrorResp(err)) => { - let data = err.data.unwrap_or_default(); - let data = data.get().trim_matches('"'); - let data = Bytes::from_str(data).unwrap_or_default(); - - BoltRegistryContractErrors::abi_decode(&data, true)? - } - e => return Err(e), - }, - }; - - if matches!(error, BoltRegistryContractErrors::NotFound(_)) { - Ok(None) - } else { - Err(SolError::custom(format!( - "unexpected Solidity error selector: {:?}", - error.selector() - )) - .into()) - } - } - - /// Gets the next pre-confirmation slot and proposer RPC URL from the registry contract - /// - /// Returns Ok(None) if no registered validators are found in the lookahead - pub async fn next_preconfer_from_registry( - &self, - proposer_duties: Vec, - ) -> ContractResult> { - let mut next_preconfer_slot = 0; - let mut proposer_rpc = String::new(); - - for duty in proposer_duties { - let res = self.get_registrant_for_validator(duty.validator_index as u64).await; - match res { - Ok(Some(token_raw)) => { - next_preconfer_slot = duty.slot; - proposer_rpc = token_raw.metadata.rpc; - info!( - "pre-confirmation will be sent for slot {} to validator with index {} at url {}", - duty.slot, - duty.validator_index, - proposer_rpc, - ); - break; - } - Ok(None) => { - // Handle the case where the result is Ok but contains None. - // You might want to continue to the next iteration, log something, or handle it - // in another way. - info!("No registrant found for validator index {}", duty.validator_index); - continue; - } - Err(e) => { - return Err(e); - } - } - } - - if next_preconfer_slot == 0 { - return Ok(None); - }; - - Ok(Some((proposer_rpc, next_preconfer_slot))) - } -} - -sol! { - #[sol(rpc)] - interface BoltRegistryContract { - #[derive(Debug, Default)] - struct Registrant { - address operator; - uint64[] validatorIndexes; - uint256 enteredAt; - uint256 exitInitiatedAt; - uint256 balance; - Status status; - MetaData metadata; - } - - #[derive(Debug, Default)] - enum Status { - #[default] - INACTIVE, - ACTIVE, - FROZEN, - EXITING - } - - #[derive(Debug, Default)] - struct MetaData { - string rpc; - bytes extra; - } - - function getOperatorForValidator(uint64 _validatorIndex) external view returns (Registrant memory); - - error NotFound(); - error Unauthorized(); - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use alloy::{primitives::U256, sol_types::SolCall}; - use beacon_api_client::ProposerDuty; - use BoltRegistryContract::{MetaData, Status}; - - use super::*; - - #[test] - fn test_abigen() { - assert_eq!(BoltRegistryContract::getOperatorForValidatorCall::SELECTOR, [238, 124, 139, 77]) - } - - #[tokio::test] - async fn test_get_operators_helder() -> eyre::Result<()> { - let registry = BoltRegistry::new( - Url::parse("http://remotebeast:4485")?, - Address::from_str("0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9")?, - ); - - let registrant = registry.get_registrant_for_validator(0).await; - assert!(matches!(registrant, Ok(None))); - - let registrant = match registry.get_registrant_for_validator(2150).await { - Ok(Some(registrant)) => registrant, - e => panic!("unexpected error reading from registry: {:?}", e), - }; - - let expected = Registrant { - operator: Address::from_str("0xad3cd1b81c80f4a495d6552ae6423508492a27f8")?, - validatorIndexes: (2145..2245).collect(), - enteredAt: U256::from(1720183620), - exitInitiatedAt: U256::from(0), - balance: U256::from(10000000000000000000u128), - status: Status::ACTIVE, - metadata: MetaData { - rpc: "http://135.181.191.125:8000".to_string(), - extra: Bytes::from_str("0x")?, - }, - }; - - assert_eq!(registrant.metadata.rpc, expected.metadata.rpc); - assert_eq!(registrant.metadata.extra, expected.metadata.extra); - assert_eq!(registrant.operator, expected.operator); - assert_eq!(registrant.validatorIndexes, expected.validatorIndexes); - assert_eq!(registrant.enteredAt, expected.enteredAt); - assert_eq!(registrant.exitInitiatedAt, expected.exitInitiatedAt); - assert_eq!(registrant.balance, expected.balance); - - Ok(()) - } - - #[tokio::test] - async fn test_next_preconfer_from_registry() -> eyre::Result<()> { - let registry = BoltRegistry::new( - Url::parse("http://remotebeast:4485")?, - Address::from_str("0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9")?, - ); - - // Mock proposer duties - let proposer_duties = vec![ - ProposerDuty { public_key: Default::default(), validator_index: 2145, slot: 12345 }, - ProposerDuty { public_key: Default::default(), validator_index: 2150, slot: 12346 }, - ]; - - // Calling the next_preconfer_from_registry function - let result = registry.next_preconfer_from_registry(proposer_duties).await?; - - // Expected result - let expected_rpc = "http://135.181.191.125:8000".to_string(); - let expected_slot = 12345; - - // Asserting the result - match result { - Some((rpc, slot)) => { - assert_eq!(rpc, expected_rpc); - assert_eq!(slot, expected_slot); - } - None => panic!("Expected some value but got None"), - } - - Ok(()) - } -} diff --git a/bolt-client/src/utils.rs b/bolt-client/src/utils.rs deleted file mode 100644 index 6863b851f..000000000 --- a/bolt-client/src/utils.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::str::FromStr; - -use alloy::{ - consensus::{BlobTransactionSidecar, SidecarBuilder, SimpleCoder}, - hex, - network::TransactionBuilder, - primitives::{keccak256, Address, B256, U256}, - rpc::types::TransactionRequest, - signers::{local::PrivateKeySigner, Signer}, -}; -use beacon_api_client::{mainnet::Client as BeaconApiClient, BlockId, ProposerDuty}; -use rand::{thread_rng, Rng}; -use serde_json::Value; - -pub const NOICE_GAS_PRICE: u128 = 69_420_000u128; -pub const DEAD_ADDRESS: &str = "0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD"; - -/// Generates random ETH transfer to `DEAD_ADDRESS` with a random payload. -pub fn generate_random_tx() -> TransactionRequest { - TransactionRequest::default() - .with_to(Address::from_str(DEAD_ADDRESS).unwrap()) - .with_value(U256::from(thread_rng().gen_range(1..100))) - .with_gas_limit(1000000u128) - .with_gas_price(NOICE_GAS_PRICE) -} - -/// Generate random transaction with blob (eip4844) -pub fn generate_random_blob_tx() -> TransactionRequest { - let sidecar: SidecarBuilder = SidecarBuilder::from_slice(b"Blobs are fun!"); - let sidecar: BlobTransactionSidecar = sidecar.build().unwrap(); - - TransactionRequest::default() - .with_to(Address::from_str(DEAD_ADDRESS).unwrap()) - .with_value(U256::from(100)) - .with_max_fee_per_blob_gas(100u128) - .max_fee_per_gas(100u128) - .max_priority_fee_per_gas(50u128) - .with_gas_limit(1_000_000u128) - .with_blob_sidecar(sidecar) -} - -pub fn prepare_rpc_request(method: &str, params: Value) -> Value { - serde_json::json!({ - "id": "1", - "jsonrpc": "2.0", - "method": method, - "params": vec![params], - }) -} - -/// Returns the current slot from the beacon client -pub async fn get_current_slot(beacon_api_client: &BeaconApiClient) -> eyre::Result { - Ok(beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot) -} - -pub async fn get_proposer_duties( - beacon_api_client: &BeaconApiClient, - current_slot: u64, - current_epoch: u64, -) -> eyre::Result> { - Ok(beacon_api_client - .get_proposer_duties(current_epoch) - .await? - .1 - .into_iter() - .filter(|duty| duty.slot > current_slot) - .collect::>()) -} - -pub async fn sign_request( - tx_hashes: Vec, - target_slot: u64, - wallet: &PrivateKeySigner, -) -> eyre::Result { - let digest = { - let mut data = Vec::new(); - let hashes = tx_hashes.iter().map(|hash| hash.as_slice()).collect::>().concat(); - data.extend_from_slice(&hashes); - data.extend_from_slice(target_slot.to_le_bytes().as_slice()); - keccak256(data) - }; - - let signature = hex::encode(wallet.sign_hash(&digest).await?.as_bytes()); - - Ok(format!("{}:0x{}", wallet.address(), signature)) -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use alloy::{ - primitives::{keccak256, Signature, B256}, - signers::local::PrivateKeySigner, - }; - - use crate::sign_request; - - #[tokio::test] - async fn test_sign_request() -> eyre::Result<()> { - let wallet = PrivateKeySigner::random(); - let tx_hash = - B256::from_str("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")?; - let target_slot = 42; - - let signature = sign_request(vec![tx_hash], target_slot, &wallet).await?; - let parts: Vec<&str> = signature.split(':').collect(); - - assert_eq!(parts.len(), 2); - assert_eq!(parts[0], wallet.address().to_string()); - assert_eq!(parts[1].len(), 130); - Ok(()) - } - - #[tokio::test] - async fn test_verify_signature() -> eyre::Result<()> { - // Randomly generated private key - let private_key = "0xfa4c3c87627a58684fb519f7b01a31ef31e56f414e8aa56a15f574381a5a7a9c"; - let tx_hash = "0x6938dbd0649ce26af79b0cca677b493257bd87c17d25ff717feba33c8b3920b3"; - let expected_signature = "0x10386a2aF29854954645C9710A038AcF4B2F1752:0x8db9bbcc1db5257c80138bd1df0185305918dbc8a607f63458ea885a6ccce5177a73417d693953b9f5c017a927e9c8acbf24c05b09a55f1f3fa83db57931ed9e1c"; - let target_slot = 254464; - - let wallet = PrivateKeySigner::from_str(private_key)?; - let tx_hash = B256::from_str(tx_hash)?; - - let signature = sign_request(vec![tx_hash], target_slot, &wallet).await?; - - assert_eq!(signature, expected_signature); - - let expected_signer = expected_signature.split(':').next().unwrap(); - let expected_sig = expected_signature.split(':').last().unwrap(); - let sig = Signature::from_str(expected_sig)?; - - // recompute the prehash again - let digest = { - let mut data = Vec::new(); - data.extend_from_slice(tx_hash.as_slice()); - data.extend_from_slice(target_slot.to_le_bytes().as_slice()); - keccak256(data) - }; - - let recovered_address = sig.recover_address_from_prehash(&digest)?; - assert_eq!(recovered_address, wallet.address()); - assert_eq!(recovered_address.to_string(), expected_signer); - - Ok(()) - } -} diff --git a/bolt-contracts/.gitignore b/bolt-contracts/.gitignore deleted file mode 100644 index ccb098322..000000000 --- a/bolt-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -cache/ -out/ -broadcast/ diff --git a/bolt-contracts/README.md b/bolt-contracts/README.md deleted file mode 100644 index 0b75ab5c8..000000000 --- a/bolt-contracts/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Bolt Contracts - -## Registry -[`BoltRegistry.sol`](./src/contracts/BoltRegistry.sol) keeps track of registered proposers and operators. It allows an operator -to register by providing a list of validator indexes and depositing some collateral. It also exposes some view methods for off-chain actors to read. - -### Registration - -```js -function register( - uint64[] calldata validatorIndexes, - string calldata rpc, - bytes calldata extra -) external payable; - -``` -Besides validatorIndexes, `register` also registers an RPC endpoint and some optional other information in `extra`. - -### Exiting -The exit process is a 2-step process. The first step is triggering the exit, which will put the registrant into an `EXITING` status after which the registrant should be considered inactive. After the `EXIT_COOLDOWN` of 1 day, the exit can be confirmed and the deposit will be returned. - -```js -function startExit() external; - -function confirmExit(address payable recipient) external; -``` - -### View Methods -```js -function isActiveOperator(address _operator) external view returns (bool); - -function getOperatorStatus( - address _operator -) external view returns (Status); - -function getOperatorForValidator( - uint64 _validatorIndex -) external view returns (Registrant memory); -``` - -## Challenger -WIP - -## Deploying -```bash -# Example for Helder devnet. Set PRIVATE_KEY to your hex-encoded private key. -PRIVATE_KEY=$PRIVATE_KEY forge script script/DeployRegistry.s.sol --rpc-url https://rpc.helder-devnets.xyz --broadcast --legacy -``` - -## Registering -```bash -# Example for Helder devnet. Set PRIVATE_KEY to your hex-encoded private key. -export PRIVATE_KEY="0x..." -export RPC_ADDR="http://test.com" -export VALIDATOR_INDEXES="1,2,3,4" -forge script script/RegisterValidators.s.sol --rpc-url https://rpc.helder-devnets.xyz --broadcast --legacy -``` - -## Deployments -| Contract | Network | Address | -| -------- | ------- | ------- | -| `BoltRegistry.sol` | Helder (7014190335) | 0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9 | \ No newline at end of file diff --git a/bolt-contracts/foundry.toml b/bolt-contracts/foundry.toml deleted file mode 100644 index 25b918f9c..000000000 --- a/bolt-contracts/foundry.toml +++ /dev/null @@ -1,6 +0,0 @@ -[profile.default] -src = "src" -out = "out" -libs = ["lib"] - -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/bolt-contracts/lib/forge-std b/bolt-contracts/lib/forge-std deleted file mode 160000 index bb4ceea94..000000000 --- a/bolt-contracts/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef diff --git a/bolt-contracts/lib/openzeppelin-contracts b/bolt-contracts/lib/openzeppelin-contracts deleted file mode 160000 index dbb6104ce..000000000 --- a/bolt-contracts/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dbb6104ce834628e473d2173bbc9d47f81a9eec3 diff --git a/bolt-contracts/lib/relic-sdk b/bolt-contracts/lib/relic-sdk deleted file mode 160000 index 8d6c88e44..000000000 --- a/bolt-contracts/lib/relic-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8d6c88e4437eade19a08aca6457d6bd14b06e454 diff --git a/bolt-contracts/script/DeployRegistry.s.sol b/bolt-contracts/script/DeployRegistry.s.sol deleted file mode 100644 index 28a31ffe8..000000000 --- a/bolt-contracts/script/DeployRegistry.s.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; - -import {BoltRegistry} from "../src/contracts/BoltRegistry.sol"; -import {BoltChallenger} from "../src/contracts/BoltChallenger.sol"; - -contract DeployRegistry is Script { - uint256 public signerKey; - - function run() public { - signerKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(signerKey); - - BoltRegistry registry = new BoltRegistry(10 ether); - console.log("BoltRegistry deployed at", address(registry)); - - vm.stopBroadcast(); - } -} diff --git a/bolt-contracts/script/ReadRegistry.s.sol b/bolt-contracts/script/ReadRegistry.s.sol deleted file mode 100644 index 0e26d204e..000000000 --- a/bolt-contracts/script/ReadRegistry.s.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; - -import {BoltRegistry, IBoltRegistry} from "../src/contracts/BoltRegistry.sol"; - -contract ReadRegistry is Script { - address public registryAddress = 0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9; - - function run() public view { - console.log("Bolt registry address:", registryAddress); - BoltRegistry registry = BoltRegistry(registryAddress); - - console.log( - "Bolt registry minimum collateral:", - registry.MINIMUM_COLLATERAL() - ); - - for (uint64 i = 0; i < 2000; i++) { - try registry.getOperatorForValidator(i) returns ( - IBoltRegistry.Registrant memory operator - ) { - console.log( - "Operator for validator found", - i, - ":", - operator.operator - ); - console.log("Operator RPC:", operator.metadata.rpc); - } catch { - // console.log("No operator for validator", i); - } - } - } -} diff --git a/bolt-contracts/script/RegisterValidators.s.sol b/bolt-contracts/script/RegisterValidators.s.sol deleted file mode 100644 index e4554fd88..000000000 --- a/bolt-contracts/script/RegisterValidators.s.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; - -import {BoltRegistry} from "../src/contracts/BoltRegistry.sol"; - -contract RegisterValidators is Script { - uint256 public signerKey; - uint64[] public validatorIndexes; - address public registryAddress = 0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9; - - function run() public { - signerKey = vm.envUint("PRIVATE_KEY"); - string memory rpc = vm.envString("RPC_ADDR"); - vm.startBroadcast(signerKey); - - string memory validatorIndexesEnv = vm.envString("VALIDATOR_INDEXES"); - uint256[] memory indexes = StringToUintArrayLib.fromStr(validatorIndexesEnv); - for (uint256 i = 0; i < indexes.length; i++) { - validatorIndexes.push(uint64(indexes[i])); - } - - console.log("Bolt registry address:", registryAddress); - BoltRegistry registry = BoltRegistry(registryAddress); - - console.log( - "Bolt registry minimum collateral:", - registry.MINIMUM_COLLATERAL() - ); - - address sender = vm.addr(signerKey); - - console.log("Sender address:", sender); - console.log("Sender balance:", sender.balance); - - if (sender.balance < registry.MINIMUM_COLLATERAL()) { - revert("Insufficient balance"); - } - - // Register with minimal collateral - registry.register{value: registry.MINIMUM_COLLATERAL()}( - validatorIndexes, - rpc, - "" - ); - - vm.stopBroadcast(); - } -} - -library StringToUintArrayLib { - // Maximum number of validators parsed in a single function call - uint256 constant MAX_VALIDATORS = 256; - - function fromStr(string memory s) internal pure returns (uint256[] memory) { - bytes memory strBytes = bytes(s); - uint256[] memory vec = new uint256[](MAX_VALIDATORS); // Initial allocation, will resize later - uint256 vecIndex = 0; - uint256 tempNum; - bool parsingRange = false; - uint256 rangeStart; - - for (uint256 i = 0; i < strBytes.length; i++) { - if (strBytes[i] == ',') { - if (parsingRange) { - // Handle end of range - for (uint256 j = rangeStart; j <= tempNum; j++) { - vec[vecIndex] = j; - vecIndex++; - } - parsingRange = false; - } else { - // Handle single number - vec[vecIndex] = tempNum; - vecIndex++; - } - tempNum = 0; - } else if (strBytes[i] == '.') { - if (i + 1 < strBytes.length && strBytes[i + 1] == '.') { - // Handle start of range - parsingRange = true; - rangeStart = tempNum; - tempNum = 0; - i++; // Skip next dot - } - } else if (strBytes[i] >= '0' && strBytes[i] <= '9') { - tempNum = tempNum * 10 + (uint8(strBytes[i]) - 48); // Convert ASCII to integer - } - } - - // Handle the last part after the final comma (or single number/range end) - if (parsingRange) { - for (uint256 j = rangeStart; j <= tempNum; j++) { - vec[vecIndex] = j; - vecIndex++; - } - } else { - vec[vecIndex] = tempNum; - vecIndex++; - } - - // Resize array to actual size - uint256[] memory result = new uint256[](vecIndex); - for (uint256 i = 0; i < vecIndex; i++) { - result[i] = vec[i]; - } - - return result; - } -} \ No newline at end of file diff --git a/bolt-contracts/src/contracts/BoltChallenger.sol b/bolt-contracts/src/contracts/BoltChallenger.sol deleted file mode 100644 index d66784cc9..000000000 --- a/bolt-contracts/src/contracts/BoltChallenger.sol +++ /dev/null @@ -1,413 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {IProver} from "relic-sdk/packages/contracts/interfaces/IProver.sol"; -import {IReliquary} from "relic-sdk/packages/contracts/interfaces/IReliquary.sol"; -import {Facts, Fact, FactSignature} from "relic-sdk/packages/contracts/lib/Facts.sol"; -import {FactSigs} from "relic-sdk/packages/contracts/lib/FactSigs.sol"; -import {CoreTypes} from "relic-sdk/packages/contracts/lib/CoreTypes.sol"; - -import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; - -import {IBoltRegistry} from "../interfaces/IBoltRegistry.sol"; -import {IBoltChallenger} from "../interfaces/IBoltChallenger.sol"; - -import {SSZ} from "../lib/SSZ.sol"; -import {SSZContainers} from "../lib/SSZContainers.sol"; -import {BeaconChainUtils} from "../lib/BeaconChainUtils.sol"; - -contract BoltChallenger is IBoltChallenger { - /// @notice The max duration of a challenge, after which it is considered resolved - /// even if no one has provided a valid proof for it. - uint256 public constant MAX_CHALLENGE_DURATION = 7 days; - - /// @notice The bond required to open a challenge. This is to avoid spamming - /// and DOS attacks on proposers. If a challenge is successful, the bond is - /// returned to the challenger, otherwise it is sent to the based proposer. - uint256 public constant CHALLENGE_BOND = 1 ether; - - /// @notice The max number of slots that can pass after which a challenge cannot - /// be opened anymore. This corresponds to about 1 day. - /// @dev This is a limitation of the `BEACON_ROOTS` contract (see EIP-4788 for more info). - uint256 internal constant CHALLENGE_RETROACTIVE_TARGET_SLOT_WINDOW = 8190; - - /// @notice The address of the BoltRegistry contract - IBoltRegistry public immutable boltRegistry; - - /// @notice The address of the Relic Reliquary contract - IReliquary public immutable reliquary; - - /// @notice The address of the block header prover contract - IProver public immutable blockHeaderProver; - - /// @notice The address of the account info prover contract - IProver public immutable accountInfoProver; - - // Struct to hold all challenge details in stoage - struct Challenge { - // The address of the based proposer being challenged - address basedProposer; - // The signed commitment that the proposer supposedly failed to honor - SignedCommitment signedCommitment; - // The address of the challenger - address challenger; - // The beacon root object of the target slot's block header. - // This is directly fetched from the on-chain BEACON_ROOTS oracle. - bytes32 targetSlotBeaconRoot; - // The status of the challenge - ChallengeStatus status; - // The timestamp at which the challenge was opened - uint256 openTimestamp; - } - - /// @notice The struct to hold the inclusion commitment, including the proposer's signature - /// @dev there can be different kinds of commitments, this is just an example - struct SignedCommitment { - uint256 slot; - uint256 nonce; - uint256 gasUsed; - bytes32 transactionHash; - bytes signedRawTransaction; - bytes signature; - } - - /// @notice The mapping of challenges, indexed by the unique ID of their inclusion commitment - mapping(bytes32 => Challenge) public challenges; - - /// @notice Constructor - /// @param _boltRegistry The address of the BoltRegistry contract - /// @param _reliquary The address of the Relic Reliquary contract - /// @param _blockHeaderProver The address of the Relic block header prover contract - constructor( - address _boltRegistry, - address _reliquary, - address _blockHeaderProver, - address _accountInfoProver - ) { - boltRegistry = IBoltRegistry(_boltRegistry); - reliquary = IReliquary(_reliquary); - - // Check if the provided provers are valid - // TODO: readd this for mainnet deployment (currently disabled for testing) - // reliquary.checkProver(reliquary.provers(_blockHeaderProver)); - // reliquary.checkProver(reliquary.provers(_accountInfoProver)); - - blockHeaderProver = IProver(_blockHeaderProver); - accountInfoProver = IProver(_accountInfoProver); - } - - /// @notice Challenge a proposer if it hasn't honored a preconfirmation. - /// @notice A challenge requires a bond to be transferred to this contract to avoid spamming. - /// @param _basedProposer The address of the proposer to challenge - /// @param _signedCommitment The signed commitment that the proposer is getting challenged for - function challengeProposer( - address _basedProposer, - SignedCommitment calldata _signedCommitment - ) public payable { - // First sanity checks - if (_basedProposer == address(0) || _signedCommitment.slot == 0) { - revert InvalidChallenge(); - } - - // Check if there is a sufficient bond attached to the transaction - if (msg.value < CHALLENGE_BOND) { - revert InsufficientBond(); - } else if (msg.value > CHALLENGE_BOND) { - // Refund the excess bond - payable(msg.sender).transfer(msg.value - CHALLENGE_BOND); - } - - // Check if the target slot is not too far in the past - if ( - BeaconChainUtils._getSlotFromTimestamp(block.timestamp) - - _signedCommitment.slot > - CHALLENGE_RETROACTIVE_TARGET_SLOT_WINDOW - ) { - // Challenges cannot be opened for slots that are too far in the past, because we rely - // on the BEACON_ROOTS ring buffer to be available for the challenge to be resolved. - revert TargetSlotTooFarInThePast(); - } - - // Check if the proposer is an active based proposer - if (!boltRegistry.isActiveOperator(_basedProposer)) { - revert InvalidProposerAddress(); - } - - bytes32 commitmentID = _getCommitmentID(_signedCommitment); - - // Check if a challenge already exists for the given commitment - // Challenge duplicates are not allowed - if (challenges[commitmentID].basedProposer != address(0)) { - revert ChallengeAlreadyExists(); - } - - // Check if the signed commitment was made by the challenged based proposer - if ( - _recoverCommitmentSigner( - commitmentID, - _signedCommitment.signature - ) != _basedProposer - ) { - revert InvalidCommitmentSigner(); - } - - // Note: we don't check if the based proposer was actually scheduled for proposal at their - // target slot. Proposers are expected to not preconfirm if they are not the scheduled proposer, - // as they would be penalized for it. - - // Get the beacon block root for the target slot. We store it in the Challenge so that - // it can be used even after 8192 slots have passed (the limit of the BEACON_ROOTS contract) - bytes32 beaconBlockRoot = BeaconChainUtils._getBeaconBlockRoot( - _signedCommitment.slot - ); - - // ==== Create a new challenge ==== - - challenges[commitmentID] = Challenge({ - basedProposer: _basedProposer, - challenger: msg.sender, - signedCommitment: _signedCommitment, - targetSlotBeaconRoot: beaconBlockRoot, - status: ChallengeStatus.Pending, - openTimestamp: block.timestamp - }); - - emit NewChallenge(_basedProposer, commitmentID, _signedCommitment.slot); - } - - /// @notice Resolve a challenge by providing a valid proof for the preconfirmation. - /// @param _challengeID The unique ID of the challenge to resolve - /// @param _blockHeaderProof The proof of the block header of the target slot - /// @param _accountDataProof The proof of the account data of the preconfirmed sender - /// @param _transactionIndex The index of the transaction in the block - /// @param _inclusionProof The Merkle proof of the transaction's inclusion in the block - /// @dev anyone can call this function on a pending challenge, but only the challenged based proposer - /// @dev will be able to provide a valid proof to counter it. If the challenge expires or the proof is invalid, - /// @dev the challenger will be rewarded with the bond + a portion of the slashed amount. - function resolveChallenge( - bytes32 _challengeID, - bytes calldata _blockHeaderProof, - bytes calldata _accountDataProof, - uint256 _transactionIndex, - bytes32[] calldata _inclusionProof - ) public { - Challenge memory challenge = challenges[_challengeID]; - - // Check if the challenge exists - if (challenge.basedProposer == address(0)) { - revert ChallengeNotFound(); - } - - // Check if the challenge is still pending - if (challenge.status != ChallengeStatus.Pending) { - revert ChallengeAlreadyResolved(); - } - - // Check if the challenge has expired. - // This means that the validator failed to honor the commitment and will get slashed. - if ( - block.timestamp - challenge.openTimestamp > MAX_CHALLENGE_DURATION - ) { - // Part of the slashed amount will also be returned to the challenger as a reward. - // This is the reason we don't have access control in this function. - // TODO: slash the based proposer. - _onChallengeSuccess(_challengeID); - return; - } - - // From here on, we assume the function was called by the based proposer - if (msg.sender != challenge.basedProposer) { - revert Unauthorized(); - } - - // Derive the block header data of the target block from the block header proof - CoreTypes.BlockHeaderData - memory verifiedHeader = _deriveBlockHeaderInfo(_blockHeaderProof); - - // Derive the preconfirmed sender's account data from the account data proof - CoreTypes.AccountData memory verifiedAccount = _deriveAccountData( - _accountDataProof, - verifiedHeader.Number - ); - - // Check that the nonce of the preconfirmed sender is valid (not too low) - // at the time of the based proposer's slot. - if (verifiedAccount.Nonce > challenge.signedCommitment.nonce) { - // consider the challenge unsuccessful: the user sent a transaction before - // the proposer could include it, as such it is not at fault. - _onChallengeFailure(_challengeID); - return; - } - - // Check that the balance of the preconfirmed sender is enough to cover the base fee - // of the block. - if ( - verifiedAccount.Balance < - challenge.signedCommitment.gasUsed * verifiedHeader.BaseFee - ) { - // consider the challenge unsuccessful: the user doesn't have enough balance to cover the gas - // thus invalidating the preconfirmation: the proposer is not at fault. - _onChallengeFailure(_challengeID); - return; - } - - // TODO: we could use the beacon root oracle to check that the based proposer proposed a block - // at the target slot or if it was reorged. This could be useful to differentiate between a - // safety vs liveness fault. - - // Check if the block header timestamp is UP TO the challenge's target slot. - // It can be earlier, in case the transaction was included before the based proposer's slot. - if ( - verifiedHeader.Time > - BeaconChainUtils._getTimestampFromSlot( - challenge.signedCommitment.slot - ) - ) { - // The block header timestamp is after the target slot, so the proposer didn't - // honor the preconfirmation and the challenge is successful. - // TODO: slash the based proposer - _onChallengeSuccess(_challengeID); - return; - } - - bool isValid = _verifyInclusionProof( - verifiedHeader.TxHash, - _transactionIndex, - _inclusionProof, - challenge.signedCommitment.signedRawTransaction - ); - - if (!isValid) { - // The challenge was successful: the proposer failed to honor the preconfirmation - // TODO: slash the based proposer - _onChallengeSuccess(_challengeID); - } else { - // The challenge was unsuccessful: the proposer honored the preconfirmation - _onChallengeFailure(_challengeID); - } - } - - /// @notice Handle the success of a challenge - /// @param _challengeID The unique ID of the challenge - function _onChallengeSuccess(bytes32 _challengeID) internal { - Challenge storage challenge = challenges[_challengeID]; - challenge.status = ChallengeStatus.Resolved; - payable(challenge.challenger).transfer(CHALLENGE_BOND); - emit ChallengeResolved(_challengeID, ChallengeResult.Success); - } - - /// @notice Handle the failure of a challenge - /// @param _challengeID The unique ID of the challenge - function _onChallengeFailure(bytes32 _challengeID) internal { - Challenge storage challenge = challenges[_challengeID]; - challenge.status = ChallengeStatus.Resolved; - payable(challenge.basedProposer).transfer(CHALLENGE_BOND); - emit ChallengeResolved(_challengeID, ChallengeResult.Failure); - } - - /// @notice Fetch trustlessly valid block header data - /// @param _proof The ABI-encoded proof of the block header - /// @return header The block header data - function _deriveBlockHeaderInfo( - bytes calldata _proof - ) internal returns (CoreTypes.BlockHeaderData memory header) { - // TODO: handle fee for proving. make payable? - - Fact memory fact = blockHeaderProver.prove(_proof, false); - header = abi.decode(fact.data, (CoreTypes.BlockHeaderData)); - - if ( - FactSignature.unwrap(fact.sig) != - FactSignature.unwrap(FactSigs.blockHeaderSig(header.Number)) - ) { - revert UnexpectedFactSignature(); - } - } - - /// @notice Fetch trustlessly valid account data at a given block number - /// @param _proof The ABI-encoded proof of the account data - /// @param _blockNumber The block number for which the account data is being proven - /// @return account The account data - function _deriveAccountData( - bytes calldata _proof, - uint256 _blockNumber - ) internal returns (CoreTypes.AccountData memory account) { - // TODO: handle fee for proving. make payable? - - Fact memory fact = accountInfoProver.prove(_proof, false); - account = abi.decode(fact.data, (CoreTypes.AccountData)); - - // verify that the account data proof was provided for the correct block - if ( - FactSignature.unwrap(fact.sig) != - FactSignature.unwrap(FactSigs.accountFactSig(_blockNumber)) - ) { - revert UnexpectedFactSignature(); - } - } - - /// @notice Verify the inclusion proof of a transaction in a block - /// @param _transactionsRoot The transactions root of the block - /// @param _transactionIndex The index of the transaction in the block - /// @param _inclusionProof The Merkle proof of the transaction's inclusion in the block - /// @param _signedRawTransaction The signed raw transaction being proven - /// @return isValid true if the proof is valid, false otherwise - function _verifyInclusionProof( - bytes32 _transactionsRoot, - uint256 _transactionIndex, - bytes32[] calldata _inclusionProof, - bytes memory _signedRawTransaction - ) internal view returns (bool isValid) { - // Check if the transactions root matches the signed commitment - - // The genelized index is the index of the merkle tree generated by the merkleization - // process of a SSZ list of transactions. Since this list is dynamic and can be of maximum - // length of 2^21 = 2_097_152, the merkleization process fills the tree with empty hashes, - // therefore this number is an offset from where transactions hash tree root starts. - // To read more, check out https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization - uint256 generalizedIndex = 2_097_152 + _transactionIndex; - - bytes32 leaf = SSZContainers._transactionHashTreeRoot( - _signedRawTransaction - ); - - isValid = SSZ._verifyProof( - _inclusionProof, - _transactionsRoot, - leaf, - generalizedIndex - ); - } - - /// @notice Recover the signer of a commitment - /// @param _commitmentSignature The signature of the commitment - /// @param _commitmentHash The keccak hash of an unsigned message - function _recoverCommitmentSigner( - bytes32 _commitmentHash, - bytes calldata _commitmentSignature - ) internal pure returns (address) { - (address signer, ECDSA.RecoverError err, ) = ECDSA.tryRecover( - _commitmentHash, - _commitmentSignature - ); - if (err != ECDSA.RecoverError.NoError || signer == address(0)) { - revert InvalidCommitmentSignature(); - } - - return signer; - } - - /// @notice Hashes the inclusion commitment to a unique ID to index the challenge - function _getCommitmentID( - SignedCommitment memory _commitment - ) internal pure returns (bytes32) { - return - keccak256( - abi.encodePacked( - _commitment.slot, - _commitment.transactionHash, - _commitment.signedRawTransaction - ) - ); - } -} diff --git a/bolt-contracts/src/contracts/BoltRegistry.sol b/bolt-contracts/src/contracts/BoltRegistry.sol deleted file mode 100644 index c064eda8d..000000000 --- a/bolt-contracts/src/contracts/BoltRegistry.sol +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {IBoltRegistry} from "../interfaces/IBoltRegistry.sol"; - -contract BoltRegistry is IBoltRegistry { - // Cooldown period after which a based proposer can complete the exit process - uint256 public constant EXIT_COOLDOWN = 1 days; - - // Minimum collateral per operator - uint256 public immutable MINIMUM_COLLATERAL; - - // Mapping to hold the registrants - mapping(address => Registrant) public registrants; - - // Array to hold operator addresses - address[] public operators; - - // Mapping that holds the relationship between validator index and operator address - mapping(uint64 => address) public delegations; - - /// @notice Constructor which can set the minimum collateral required to register - constructor(uint256 _minimumCollateral) { - MINIMUM_COLLATERAL = _minimumCollateral; - } - - /// @notice Allows a based proposer to opt-in to the protocol - function register( - uint64[] calldata validatorIndexes, - string calldata rpc, - bytes calldata extra - ) external payable { - if (msg.value < MINIMUM_COLLATERAL) { - revert InsufficientCollateral(); - } - - if (registrants[msg.sender].operator != address(0)) { - revert AlreadyOptedIn(); - } - - MetaData memory metadata = MetaData(rpc, extra); - - registrants[msg.sender] = Registrant( - msg.sender, - validatorIndexes, - block.timestamp, - 0, - msg.value, - Status.ACTIVE, - metadata - ); - - operators.push(msg.sender); - - // Set the delegations - for (uint256 i = 0; i < validatorIndexes.length; i++) { - delegations[validatorIndexes[i]] = msg.sender; - } - - emit Registered(msg.sender, validatorIndexes, metadata); - } - - /// @notice Allows a based proposer to exit out of the protocol. - /// @dev Requires a second transaction after the cooldown period to complete the exit process. - function startExit() external { - Registrant storage registrant = registrants[msg.sender]; - - if (registrant.operator != msg.sender) { - revert BasedProposerDoesNotExist(); - } - - if (registrant.status == Status.EXITING) { - revert InvalidStatusChange(); - } - - registrant.exitInitiatedAt = block.timestamp; - - emit StatusChange(msg.sender, Status.EXITING); - } - - /// @notice Completes the exit process for a based proposer - /// and sends the funds back to the `recipient` address. - function confirmExit(address payable recipient) external { - Registrant storage registrant = registrants[msg.sender]; - - if (registrant.operator != msg.sender) { - revert BasedProposerDoesNotExist(); - } - if (registrant.exitInitiatedAt == 0) { - revert InvalidStatusChange(); - } - if (registrant.status == Status.INACTIVE) { - revert InvalidStatusChange(); - } - - if (block.timestamp < registrant.exitInitiatedAt + EXIT_COOLDOWN) { - revert CooldownNotElapsed(); - } - - // Remove operator from the operators array - for (uint256 i = 0; i < operators.length; i++) { - if (operators[i] == msg.sender) { - operators[i] = operators[operators.length - 1]; - operators.pop(); - break; - } - } - - delete registrants[msg.sender]; - - for (uint256 i = 0; i < registrant.validatorIndexes.length; i++) { - delete delegations[registrant.validatorIndexes[i]]; - } - - recipient.transfer(registrant.balance); - - emit StatusChange(msg.sender, Status.INACTIVE); - } - - /// @notice Check if an address is a based proposer opted into the protocol - /// @param _operator The address to check - /// @return True if the address is an active based proposer, false otherwise - function isActiveOperator(address _operator) public view returns (bool) { - return registrants[_operator].status == Status.ACTIVE; - } - - /// @notice Get the status of a based proposer - /// @param _operator The address of the operator - /// @return The status of the based proposer - function getOperatorStatus( - address _operator - ) external view returns (Status) { - // Will return INACTIVE if the operator is not registered - return registrants[_operator].status; - } - - function getOperatorForValidator( - uint64 _validatorIndex - ) external view returns (Registrant memory) { - if (delegations[_validatorIndex] != address(0)) { - return registrants[delegations[_validatorIndex]]; - } - - revert NotFound(); - } - - function getAllRegistrants() external view returns (Registrant[] memory) { - uint256 activeCount = 0; - for (uint256 i = 0; i < operators.length; i++) { - if (isActiveOperator(operators[i])) { - activeCount++; - } - } - - Registrant[] memory _registrants = new Registrant[](activeCount); - uint256 index = 0; - for (uint256 i = 0; i < operators.length; i++) { - if (isActiveOperator(operators[i])) { - _registrants[index] = registrants[operators[i]]; - index++; - } - } - - return _registrants; - } -} diff --git a/bolt-contracts/src/interfaces/IBoltChallenger.sol b/bolt-contracts/src/interfaces/IBoltChallenger.sol deleted file mode 100644 index aba98cc89..000000000 --- a/bolt-contracts/src/interfaces/IBoltChallenger.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -interface IBoltChallenger { - enum ChallengeStatus { - // The challenge is open and waiting for a resolution - Pending, - // The challenge has been resolved - Resolved - } - - enum ChallengeResult { - // The challenge was successful: the proposer failed to honor the preconfirmation - Success, - // The challenge was unsuccessful: the proposer honored the preconfirmation - Failure - } - - // Bolt challenge errors - error ChallengeAlreadyExists(); - error InsufficientBond(); - error InvalidProposerAddress(); - error Unauthorized(); - error InvalidChallenge(); - error ChallengeNotFound(); - error ChallengeAlreadyResolved(); - error TargetSlotTooFarInThePast(); - error InvalidCommitmentSignature(); - error InvalidCommitmentSigner(); - - // Relic related errors - error UnexpectedFactSignature(); - error WrongBlockHeader(); - - /// @notice Event emitted when a new challenge is opened - event NewChallenge(address indexed basedProposer, bytes32 indexed commitmentID, uint256 targetSlot); - - /// @notice Event emitted when a challenge is resolved - event ChallengeResolved(bytes32 indexed challengeID, ChallengeResult result); -} diff --git a/bolt-contracts/src/interfaces/IBoltRegistry.sol b/bolt-contracts/src/interfaces/IBoltRegistry.sol deleted file mode 100644 index 283f8f505..000000000 --- a/bolt-contracts/src/interfaces/IBoltRegistry.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -interface IBoltRegistry { - /// @notice Struct to hold opted-in proposer information - struct Registrant { - // The address of the operator - address operator; - // The validator indexes this registrant is responsible for - uint64[] validatorIndexes; - uint256 enteredAt; - uint256 exitInitiatedAt; - uint256 balance; - Status status; - MetaData metadata; - } - - struct MetaData { - string rpc; - bytes extra; - } - - /// @notice Enum to hold the status of the based proposers - enum Status { - // Default INACTIVE - INACTIVE, - ACTIVE, - FROZEN, - EXITING - } - - // Error messages - error AlreadyOptedIn(); - error InsufficientCollateral(); - error BasedProposerDoesNotExist(); - error InvalidStatusChange(); - error CooldownNotElapsed(); - error Unauthorized(); - error NotFound(); - - /// @notice Event to log the status change of a based proposer - event StatusChange(address indexed operator, Status status); - - event Registered( - address indexed operator, - uint64[] validatorIndexes, - MetaData metadata - ); - - function register( - uint64[] calldata validatorIndexes, - string calldata rpc, - bytes calldata extra - ) external payable; - - function isActiveOperator(address _operator) external view returns (bool); - - function getOperatorStatus( - address _operator - ) external view returns (Status); - - function getOperatorForValidator( - uint64 _validatorIndex - ) external view returns (Registrant memory); - - function startExit() external; - - function confirmExit(address payable recipient) external; -} diff --git a/bolt-contracts/src/lib/BeaconChainUtils.sol b/bolt-contracts/src/lib/BeaconChainUtils.sol deleted file mode 100644 index 3664e3ce5..000000000 --- a/bolt-contracts/src/lib/BeaconChainUtils.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -library BeaconChainUtils { - /// @notice The address of the BeaconRoots contract - /// @dev See EIP-4788 for more info - address internal constant BEACON_ROOTS_CONTRACT = 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02; - - /// @notice The duration of a slot in seconds - uint256 internal constant SLOT_TIME = 12; - - /// @notice The timestamp of the genesis of the eth2 chain - uint256 internal constant ETH2_GENESIS_TIMESTAMP = 1606824023; - - /// @notice Error emitted when a beacon block root is not found - error BeaconRootNotFound(); - - /// @notice Get the slot number from a given timestamp - /// @param _timestamp The timestamp - /// @return The slot number - function _getSlotFromTimestamp(uint256 _timestamp) internal pure returns (uint256) { - return (_timestamp - ETH2_GENESIS_TIMESTAMP) / SLOT_TIME; - } - - /// @notice Get the timestamp from a given slot - /// @param _slot The slot number - /// @return The timestamp - function _getTimestampFromSlot(uint256 _slot) internal pure returns (uint256) { - return ETH2_GENESIS_TIMESTAMP + _slot * SLOT_TIME; - } - - /// @notice Get the beacon block root for a given slot - /// @param _slot The slot number - /// @return The beacon block root - function _getBeaconBlockRoot(uint256 _slot) internal view returns (bytes32) { - uint256 slotTimestamp = ETH2_GENESIS_TIMESTAMP + _slot * SLOT_TIME; - - (bool success, bytes memory data) = BEACON_ROOTS_CONTRACT.staticcall(abi.encode(slotTimestamp)); - - if (!success || data.length == 0) { - revert BeaconRootNotFound(); - } - - return abi.decode(data, (bytes32)); - } -} diff --git a/bolt-contracts/src/lib/SSZ.sol b/bolt-contracts/src/lib/SSZ.sol deleted file mode 100644 index 057fbc4f9..000000000 --- a/bolt-contracts/src/lib/SSZ.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -/// @title SSZ library -/// @dev inspired by https://github.com/succinctlabs/telepathy-contracts/blob/main/src/libraries/SimpleSerialize.sol -/// @dev and https://github.com/madlabman/eip-4788-proof/blob/master/src/SSZ.sol -library SSZ { - /// @notice sha256 precompile address. - uint256 public constant SHA256_PRECOMPILE = 0x02; - - error BranchHasMissingItem(); - error BranchHasExtraItem(); - error Log2Undefined(); - - /// @notice Modified version of `verify` from `MerkleProofLib` to support generalized indices and sha256 precompile. - /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. - /// @dev from https://github.com/madlabman/eip-4788-proof/blob/master/src/SSZ.sol - function _verifyProof(bytes32[] calldata proof, bytes32 root, bytes32 leaf, uint256 index) - internal - view - returns (bool isValid) - { - /// @solidity memory-safe-assembly - assembly { - if proof.length { - // Left shift by 5 is equivalent to multiplying by 0x20. - let end := add(proof.offset, shl(5, proof.length)) - // Initialize `offset` to the offset of `proof` in the calldata. - let offset := proof.offset - // Iterate over proof elements to compute root hash. - for {} 1 {} { - // Slot of `leaf` in scratch space. - // If the condition is true: 0x20, otherwise: 0x00. - let scratch := shl(5, and(index, 1)) - index := shr(1, index) - if iszero(index) { - // revert BranchHasExtraItem() - mstore(0x00, 0x5849603f) - revert(0x1c, 0x04) - } - // Store elements to hash contiguously in scratch space. - // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. - mstore(scratch, leaf) - mstore(xor(scratch, 0x20), calldataload(offset)) - - // Call sha256 precompile - let result := staticcall(gas(), SHA256_PRECOMPILE, 0x00, 0x40, 0x00, 0x20) - - if eq(result, 0) { revert(0, 0) } - - // Reuse `leaf` to store the hash to reduce stack operations. - leaf := mload(0x00) - offset := add(offset, 0x20) - if iszero(lt(offset, end)) { break } - } - } - // index != 1 - if gt(sub(index, 1), 0) { - // revert BranchHasMissingItem() - mstore(0x00, 0x1b6661c3) - revert(0x1c, 0x04) - } - isValid := eq(leaf, root) - } - } - - function _hashTreeRoot(bytes32[] memory chunks, uint8 count) internal view returns (bytes32 root) { - /// @solidity memory-safe-assembly - assembly { - // Loop over levels - for {} 1 {} { - // Loop over chunks at the given depth - - // Initialize `offset` to the offset of `proof` elements in memory. - let target := chunks - let source := chunks - let end := add(source, shl(5, count)) - - for {} 1 {} { - // Read next two hashes to hash - mstore(0x00, mload(source)) - mstore(0x20, mload(add(source, 0x20))) - - // Call sha256 precompile - let result := staticcall(gas(), SHA256_PRECOMPILE, 0x00, 0x40, 0x00, 0x20) - - if eq(result, 0) { revert(0, 0) } - - // Store the resulting hash at the target location - mstore(target, mload(0x00)) - - // Advance the pointers - target := add(target, 0x20) - source := add(source, 0x40) - - if iszero(lt(source, end)) { break } - } - - count := shr(1, count) - if eq(count, 1) { - root := mload(0x00) - break - } - } - } - } - - /// @notice Converts a value to a little-endian byte array - /// @dev from https://github.com/succinctlabs/telepathy-contracts/blob/main/src/libraries/SimpleSerialize.sol - function _toLittleEndian(uint256 v) internal pure returns (bytes32) { - v = ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8) - | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); - v = ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16) - | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); - v = ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32) - | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); - v = ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64) - | ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64); - v = (v >> 128) | (v << 128); - return bytes32(v); - } - - /// @notice Converts a boolean to a little-endian byte array - function _toLittleEndian(bool v) internal pure returns (bytes32) { - return bytes32(v ? 1 << 248 : 0); - } - - /// @notice Log base 2 of a number - /// @dev From solady FixedPointMath - /// @dev Equivalent to computing the index of the most significant bit (MSB) of `x`. - function _log2(uint256 x) internal pure returns (uint256 r) { - /// @solidity memory-safe-assembly - assembly { - if iszero(x) { - // Store the function selector of `Log2Undefined()`. - mstore(0x00, 0x5be3aa5c) - // Revert with (offset, size). - revert(0x1c, 0x04) - } - - r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) - r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) - r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) - - // For the remaining 32 bits, use a De Bruijn lookup. - // See: https://graphics.stanford.edu/~seander/bithacks.html - x := shr(r, x) - x := or(x, shr(1, x)) - x := or(x, shr(2, x)) - x := or(x, shr(4, x)) - x := or(x, shr(8, x)) - x := or(x, shr(16, x)) - - // forgefmt: disable-next-item - r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), - 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)) - } - } -} diff --git a/bolt-contracts/src/lib/SSZContainers.sol b/bolt-contracts/src/lib/SSZContainers.sol deleted file mode 100644 index d87742965..000000000 --- a/bolt-contracts/src/lib/SSZContainers.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {SSZ} from "./SSZ.sol"; - -library SSZContainers { - /// @notice a Validator SSZ container - /// @dev As defined in https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator - struct Validator { - bytes pubkey; - bytes32 withdrawalCredentials; - uint64 effectiveBalance; - bool slashed; - uint64 activationEligibilityEpoch; - uint64 activationEpoch; - uint64 exitEpoch; - uint64 withdrawableEpoch; - } - - /// @notice a Beacon block header SSZ container - /// @dev As defined in https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader - struct BeaconBlockHeader { - uint64 slot; - uint64 proposerIndex; - bytes32 parentRoot; - bytes32 stateRoot; - bytes32 bodyRoot; - } - - /// @notice Computes the hash tree root of a validator SSZ container - function _validatorHashTreeRoot(Validator memory validator) internal view returns (bytes32) { - bytes32 pubkeyRoot; - uint256 _sha256 = SSZ.SHA256_PRECOMPILE; - - assembly { - // Dynamic data types such as bytes are stored at the specified offset. - let offset := mload(validator) - // Call sha256 precompile with the pubkey pointer - let result := staticcall(gas(), _sha256, add(offset, 32), 0x40, 0x00, 0x20) - // Precompile returns no data on OutOfGas error. - if eq(result, 0) { revert(0, 0) } - - pubkeyRoot := mload(0x00) - } - - bytes32[] memory nodes = new bytes32[](8); - nodes[0] = pubkeyRoot; - nodes[1] = validator.withdrawalCredentials; - nodes[2] = SSZ._toLittleEndian(validator.effectiveBalance); - nodes[3] = SSZ._toLittleEndian(validator.slashed); - nodes[4] = SSZ._toLittleEndian(validator.activationEligibilityEpoch); - nodes[5] = SSZ._toLittleEndian(validator.activationEpoch); - nodes[6] = SSZ._toLittleEndian(validator.exitEpoch); - nodes[7] = SSZ._toLittleEndian(validator.withdrawableEpoch); - - return SSZ._hashTreeRoot(nodes, 8); - } - - /// @notice Computes the hash tree root of a beacon block header SSZ container - function _beaconHeaderHashTreeRoot(BeaconBlockHeader memory header) internal view returns (bytes32) { - bytes32[] memory nodes = new bytes32[](8); - nodes[0] = SSZ._toLittleEndian(header.slot); - nodes[1] = SSZ._toLittleEndian(header.proposerIndex); - nodes[2] = header.parentRoot; - nodes[3] = header.stateRoot; - nodes[4] = header.bodyRoot; - nodes[5] = bytes32(0); - nodes[6] = bytes32(0); - nodes[7] = bytes32(0); - - return SSZ._hashTreeRoot(nodes, 8); - } - - /// @notice Computes the hash tree root of an RLP-encoded signed transaction (raw bytes) - function _transactionHashTreeRoot(bytes memory transaction) internal view returns (bytes32) { - uint256 chunkCount = (transaction.length + 31) / 32; - bytes32[] memory nodes = new bytes32[](chunkCount); - - // TODO: this is most likely wrong, needs fix according to ssz specs - for (uint256 i = 0; i < chunkCount; i++) { - uint256 start = i * 32; - uint256 end = start + 32; - if (end > transaction.length) { - end = transaction.length; - } - bytes memory chunk = new bytes(32); - for (uint256 j = start; j < end; j++) { - chunk[j - start] = transaction[j]; - } - nodes[i] = keccak256(chunk); - } - - return SSZ._hashTreeRoot(nodes, uint8(chunkCount)); - } -} diff --git a/bolt-contracts/test/BoltChallenger.t.sol b/bolt-contracts/test/BoltChallenger.t.sol deleted file mode 100644 index 6a8718eef..000000000 --- a/bolt-contracts/test/BoltChallenger.t.sol +++ /dev/null @@ -1,114 +0,0 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.13; - -// import {Test, console} from "forge-std/Test.sol"; -// import {BoltRegistry} from "../src/contracts/BoltRegistry.sol"; -// import {BoltChallenger} from "../src/contracts/BoltChallenger.sol"; -// import {IBoltChallenger} from "../src/interfaces/IBoltChallenger.sol"; -// import {BeaconChainUtils} from "../src/lib/BeaconChainUtils.sol"; - -// contract BoltChallengerTest is Test { -// BoltRegistry public registry; -// BoltChallenger public challenger; - -// // Relic protocol contracts -// address relicReliquary = 0x5E4DE6Bb8c6824f29c44Bd3473d44da120387d08; -// address relicBlockHeaderProver = 0x9f9A1eb0CF9340538297c853915DCc06Eb6D72c4; -// address relicAccountInfoProver = 0xf74105AE736Ca0C4B171a2EC4F1D4B0b6EBB99ae; -// address beaconRootsContract = 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02; - -// address public alice; -// address public bob; - -// uint256 public alicePk; -// uint256 public bobPk; - -// function setUp() public { -// // Set up mainnet forking -// vm.createSelectFork("https://cloudflare-eth.com", 19932764); -// assertEq(block.number, 19932764); - -// (alice, alicePk) = makeAddrAndKey("alice"); -// (bob, bobPk) = makeAddrAndKey("bob"); - -// registry = new BoltRegistry(); -// challenger = -// new BoltChallenger(address(registry), relicReliquary, relicBlockHeaderProver, relicAccountInfoProver); - -// vm.deal(alice, 10 ether); -// vm.deal(bob, 10 ether); -// } - -// function testOpenChallengeConditions() public { -// uint256 latestSlot = BeaconChainUtils._getSlotFromTimestamp(block.timestamp); - -// BoltChallenger.SignedCommitment memory sc = BoltChallenger.SignedCommitment({ -// slot: 1, -// nonce: 1, -// gasUsed: 21000, -// transactionHash: bytes32("0x123"), -// signedRawTransaction: "0x456", -// signature: "0x789" -// }); - -// // TEST: bond is less than 1 ether -// vm.expectRevert(IBoltChallenger.InsufficientBond.selector); -// vm.prank(alice); -// challenger.challengeProposer{value: 0.5 ether}(bob, sc); - -// // TEST: challenge opened too late -// vm.expectRevert(IBoltChallenger.TargetSlotTooFarInThePast.selector); -// vm.prank(alice); -// challenger.challengeProposer{value: 1 ether}(bob, sc); - -// sc.slot = latestSlot; - -// // TEST: proposer address is authorized in the registry -// vm.expectRevert(IBoltChallenger.InvalidProposerAddress.selector); -// vm.prank(alice); -// challenger.challengeProposer{value: 1 ether}(bob, sc); - -// vm.prank(bob); -// registry.optIn(); - -// // TEST: mocked commitment signature -// vm.expectRevert(IBoltChallenger.InvalidCommitmentSignature.selector); -// vm.prank(alice); -// challenger.challengeProposer{value: 1 ether}(bob, sc); -// } - -// function testOpenChallengeSignature() public { -// uint256 latestSlot = BeaconChainUtils._getSlotFromTimestamp(block.timestamp); - -// vm.prank(bob); -// registry.optIn(); - -// bytes32 txHash = 0xbe162ae10f376ad2bcf0934233493c7b353836fc1d27c5cb6785ce68d45914ea; -// bytes memory signedRawTx = -// hex"02f87101830f45b3808504acefa159825208944675c7e5baafbffbca748158becba61ef3b0a26387cb62154da95e6480c080a0101d7785433fd38e12fccd911bf9e61a941c88543f372877f07901dacf066b0aa016a75077103f7e175b61b5509e20ef5e8364d322f2ecaade5922717efeb892cd"; - -// bytes32 commitmentDigest = keccak256(abi.encodePacked(latestSlot, txHash, signedRawTx)); -// (uint8 v, bytes32 r, bytes32 s) = vm.sign(bobPk, commitmentDigest); -// bytes memory commitmentSignature = abi.encodePacked(r, s, v); - -// BoltChallenger.SignedCommitment memory sc = BoltChallenger.SignedCommitment({ -// slot: latestSlot, -// nonce: vm.getNonce(0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5), -// gasUsed: 21000, -// transactionHash: txHash, -// signedRawTransaction: signedRawTx, -// signature: commitmentSignature -// }); - -// // mock the beacon root for the target slot (todo: fix this) -// bytes32 timestampIdx = bytes32(uint256(block.timestamp % 8191)); -// vm.store(beaconRootsContract, timestampIdx, bytes32(block.timestamp)); -// vm.store(beaconRootsContract, bytes32(uint256(timestampIdx) + 8191), bytes32(uint256(123))); - -// // TEST: challenge opened successfully -// // Ignore beacon root verification for now as EIP-4788 is out of scope for this test -// vm.expectRevert(BeaconChainUtils.BeaconRootNotFound.selector); -// vm.prank(alice); -// challenger.challengeProposer{value: 1 ether}(bob, sc); -// } -// } diff --git a/bolt-contracts/test/BoltRegistry.t.sol b/bolt-contracts/test/BoltRegistry.t.sol deleted file mode 100644 index 9280a2c67..000000000 --- a/bolt-contracts/test/BoltRegistry.t.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {BoltRegistry} from "../src/contracts/BoltRegistry.sol"; -import {IBoltRegistry} from "../src/interfaces/IBoltRegistry.sol"; - -contract BoltRegistryTest is Test { - BoltRegistry public registry; - - uint64[] public validatorIndexes; - - address alice = address(0x1); - address bob = address(0x2); - - function setUp() public { - registry = new BoltRegistry(10 ether); - vm.deal(alice, 20 ether); - } - - function testRegistration() public { - vm.prank(alice); - - validatorIndexes.push(1); - validatorIndexes.push(2); - validatorIndexes.push(3); - - registry.register{value: 10 ether}(validatorIndexes, "rpc", ""); - - assertEq( - uint8(registry.getOperatorStatus(alice)), - uint8(IBoltRegistry.Status.ACTIVE) - ); - - assertEq(registry.isActiveOperator(alice), true); - - assertEq(registry.getOperatorForValidator(1).operator, alice); - assertEq(registry.getOperatorForValidator(1).metadata.rpc, "rpc"); - } - - // function testOptOut() public { - // assertEq(registry.isActiveBasedProposer(alice), false); - // vm.expectRevert(IBoltRegistry.BasedProposerDoesNotExist.selector); - // registry.getBasedProposerStatus(alice); - - // vm.prank(alice); - // registry.optIn(); - // assertEq(registry.isActiveBasedProposer(alice), true); - // assertEq( - // uint8(registry.getBasedProposerStatus(alice)), - // uint8(IBoltRegistry.BoltStatus.Active) - // ); - - // vm.prank(alice); - // registry.beginOptOut(); - - // assertEq(registry.isActiveBasedProposer(alice), true); - // assertEq( - // uint8(registry.getBasedProposerStatus(alice)), - // uint8(IBoltRegistry.BoltStatus.Active) - // ); - - // // check that confirmation can't be done immediately - // vm.expectRevert(IBoltRegistry.CooldownNotElapsed.selector); - // vm.prank(alice); - // registry.confirmOptOut(); - - // // wait 1 day - // vm.warp(block.timestamp + 1 days); - - // // check that opt out can be confirmed - // vm.prank(alice); - // vm.expectEmit(address(registry)); - // emit IBoltRegistry.BasedProposerStatusChanged( - // alice, - // IBoltRegistry.BoltStatus.Inactive - // ); - // registry.confirmOptOut(); - - // assertEq(registry.isActiveBasedProposer(alice), false); - // assertEq( - // uint8(registry.getBasedProposerStatus(alice)), - // uint8(IBoltRegistry.BoltStatus.Inactive) - // ); - - // // check that opt out can't be confirmed again - // vm.expectRevert(IBoltRegistry.InvalidStatusChange.selector); - // vm.prank(alice); - // registry.confirmOptOut(); - // } -} diff --git a/bolt-contracts/test/StringToUintArrayLib.t.sol b/bolt-contracts/test/StringToUintArrayLib.t.sol deleted file mode 100644 index aaae88073..000000000 --- a/bolt-contracts/test/StringToUintArrayLib.t.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "forge-std/Test.sol"; -import "../script/RegisterValidators.s.sol"; - -contract StringToUintArrayTest is Test { - - function setUp() public {} - - function testParseValidatorIndexes1() public pure { - uint256[] memory indexes = StringToUintArrayLib.fromStr("1,2,3,4"); - uint256[4] memory expected; - expected[0] = 1; - expected[1] = 2; - expected[2] = 3; - expected[3] = 4; - - assertEq(indexes.length, expected.length); - for (uint256 i = 0; i < indexes.length; i++) { - assertEq(indexes[i], expected[i]); - } - } - - function testParseValidatorIndexes2() public pure { - uint256[] memory indexes = StringToUintArrayLib.fromStr("1..4"); - uint256[4] memory expected; - expected[0] = 1; - expected[1] = 2; - expected[2] = 3; - expected[3] = 4; - - assertEq(indexes.length, expected.length); - for (uint256 i = 0; i < indexes.length; i++) { - assertEq(indexes[i], expected[i]); - } - } - - function testParseValidatorIndexes3() public pure { - uint256[] memory indexes = StringToUintArrayLib.fromStr("1..4,6..8"); - uint256[7] memory expected; - expected[0] = 1; - expected[1] = 2; - expected[2] = 3; - expected[3] = 4; - expected[4] = 6; - expected[5] = 7; - expected[6] = 8; - - assertEq(indexes.length, expected.length); - for (uint256 i = 0; i < indexes.length; i++) { - assertEq(indexes[i], expected[i]); - } - } - - function testParseValidatorIndexes4() public pure { - uint256[] memory indexes = StringToUintArrayLib.fromStr("1,2..4,6..8"); - uint256[7] memory expected; - expected[0] = 1; - expected[1] = 2; - expected[2] = 3; - expected[3] = 4; - expected[4] = 6; - expected[5] = 7; - expected[6] = 8; - - assertEq(indexes.length, expected.length); - for (uint256 i = 0; i < indexes.length; i++) { - assertEq(indexes[i], expected[i]); - } - } - - function testParse100Indexes() public pure { - string memory input = "1..100"; - - uint256[] memory indexes = StringToUintArrayLib.fromStr(input); - assertEq(indexes.length, 100); - for (uint256 i = 0; i < indexes.length; i++) { - assertEq(indexes[i], i + 1); - } - } -} \ No newline at end of file diff --git a/bolt-kurtosis-client/.gitignore b/bolt-kurtosis-client/.gitignore deleted file mode 100644 index 14ee5009d..000000000 --- a/bolt-kurtosis-client/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target/ -.env diff --git a/bolt-kurtosis-client/Cargo.lock b/bolt-kurtosis-client/Cargo.lock deleted file mode 100644 index e6bafb7c9..000000000 --- a/bolt-kurtosis-client/Cargo.lock +++ /dev/null @@ -1,4747 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "alloy" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45855eb65e9cc70294ebea1279f6d8ee0636bf2ed3897683ebbae2739975ae8c" -dependencies = [ - "alloy-consensus", - "alloy-contract", - "alloy-core", - "alloy-eips", - "alloy-genesis", - "alloy-network", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", -] - -[[package]] -name = "alloy-chains" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1752d7d62e2665da650a36d84abbf239f812534475d51f072a49a533513b7cdd" -dependencies = [ - "num_enum", - "strum", -] - -[[package]] -name = "alloy-consensus" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58047cc851e58c26224521d1ecda466e3d746ebca0274cd5427aa660a88c353" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "c-kzg", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5d42d9f87896536234b0fac1a84ad9d9dc7a4b27839cac35d0899e64ddf083" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network", - "alloy-primitives", - "alloy-provider", - "alloy-pubsub", - "alloy-rpc-types-eth", - "alloy-sol-types", - "alloy-transport", - "futures", - "futures-util", - "thiserror", -] - -[[package]] -name = "alloy-core" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529fc6310dc1126c8de51c376cbc59c79c7f662bd742be7dc67055d5421a81b4" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", -] - -[[package]] -name = "alloy-dyn-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "const-hex", - "itoa", - "serde", - "serde_json", - "winnow 0.6.13", -] - -[[package]] -name = "alloy-eips" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a3e14fa0d152d00bd8daf605eb74ad397efb0f54bd7155585823dddb4401e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "c-kzg", - "derive_more", - "k256 0.13.3", - "once_cell", - "serde", - "sha2 0.10.8", -] - -[[package]] -name = "alloy-genesis" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cb76c8a3913f2466c5488f3a915e3a15d15596bdc935558c1a9be75e9ec508" -dependencies = [ - "alloy-primitives", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-json-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a9feec2352c78545d1a37415699817bae8dc41654bd1bfe57d6cdd5433bd" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3223d71dc78f464b2743418d0be8b5c894313e272105a6206ad5e867d67b3ce2" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", - "async-trait", - "auto_impl", - "futures-utils-wasm", - "thiserror", -] - -[[package]] -name = "alloy-primitives" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "hex-literal", - "itoa", - "k256 0.13.3", - "keccak-asm", - "proptest", - "rand 0.8.5", - "ruint", - "serde", - "tiny-keccak", -] - -[[package]] -name = "alloy-provider" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29da7457d853cb8199ec04b227d5d2ef598be3e59fc2bbad70c8be213292f32" -dependencies = [ - "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-primitives", - "alloy-pubsub", - "alloy-rpc-client", - "alloy-rpc-types-eth", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "futures", - "futures-utils-wasm", - "lru", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "alloy-pubsub" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64acfec654ade392cecfa9bba0408eb2a337d55f1b857925da79970cb70f3d6" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "bimap", - "futures", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9e609524fa31c2c70eb24c0da60796809193ad4787a6dfe6d0db0d3ac112d" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-pubsub", - "alloy-transport", - "alloy-transport-http", - "alloy-transport-ipc", - "alloy-transport-ws", - "futures", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5d76f1e8b22f48b7b8f985782b68e7eb3938780e50e8b646a53e41a598cdf5" -dependencies = [ - "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-engine" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73445fbc5c02258e3d0d977835c92366a4d91545fd456c3fc8601c61810bc9f6" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", - "jsonwebtoken", - "rand 0.8.5", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605fa8462732bb8fd0645a9941e12961e079d45ae6a44634c826f8229c187bdf" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-sol-types", - "itertools 0.13.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c5b9057acc02aee1b8aac2b5a0729cb0f73d080082c111313e5d1f92a96630" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-signer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37f10592696f4ab8b687d5a8ab55e998a14ea0ca5f8eb20ad74a96ad671bb54a" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "elliptic-curve 0.13.8", - "k256 0.13.3", - "thiserror", -] - -[[package]] -name = "alloy-signer-local" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b537f3e55f30753578f4623d5f66ddad8fa582af3fa6b15bad23dd1b9775228" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "k256 0.13.3", - "rand 0.8.5", - "thiserror", -] - -[[package]] -name = "alloy-sol-macro" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" -dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "alloy-sol-macro-expander" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" -dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", - "const-hex", - "heck", - "indexmap 2.2.6", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.71", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-macro-input" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.71", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" -dependencies = [ - "serde", - "winnow 0.6.13", -] - -[[package]] -name = "alloy-sol-types" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "const-hex", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b44b0f6f4a2593b258fa7b6cae8968e6a4c404d9ef4f5bc74401f2d04fa23fa" -dependencies = [ - "alloy-json-rpc", - "base64 0.22.1", - "futures-util", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-http" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8f1eefa8cb9e7550740ee330feba4fed303a77ad3085707546f9152a88c380" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest 0.12.5", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-ipc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31007c56dc65bd81392112dda4a14c20ac7e30bb4cb2e9176192e8d9fab1983f" -dependencies = [ - "alloy-json-rpc", - "alloy-pubsub", - "alloy-transport", - "bytes", - "futures", - "interprocess", - "pin-project", - "serde_json", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "alloy-transport-ws" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ccc1c8f8ae415e93ec0e7851bd4cdf4afdd48793d13a91b860317da1f36104" -dependencies = [ - "alloy-pubsub", - "alloy-transport", - "futures", - "http 1.1.0", - "rustls", - "serde_json", - "tokio", - "tokio-tungstenite", - "tracing", - "ws_stream_wasm", -] - -[[package]] -name = "anstream" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" - -[[package]] -name = "anstyle-parse" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-sse" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6fa871e4334a622afd6bb2f611635e8083a6f5e2936c0f90f37c7ef9856298" -dependencies = [ - "async-channel", - "futures-lite", - "http-types", - "log", - "memchr", - "pin-project-lite", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "async-trait" -version = "0.1.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "beacon-api-client" -version = "0.1.0" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "clap", - "ethereum-consensus", - "http 0.2.12", - "itertools 0.10.5", - "mev-share-sse", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blst" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "bolt-spammer" -version = "0.1.0" -dependencies = [ - "alloy", - "beacon-api-client", - "clap", - "dotenvy", - "eyre", - "rand 0.8.5", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-subscriber", - "url", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - -[[package]] -name = "cc" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "num-traits", -] - -[[package]] -name = "clap" -version = "4.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "clap_lex" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" - -[[package]] -name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-hex" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 2.0.71", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "doctest-file" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.9", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.0", - "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.3", - "subtle", - "zeroize", -] - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enr" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" -dependencies = [ - "base64 0.13.1", - "bs58", - "bytes", - "hex", - "k256 0.11.6", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-consensus" -version = "0.1.1" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "blst", - "bs58", - "c-kzg", - "enr", - "hex", - "integer-sqrt", - "multiaddr", - "multihash", - "rand 0.8.5", - "serde", - "serde_json", - "serde_yaml", - "sha2 0.10.8", - "ssz_rs", - "thiserror", - "tokio", - "tokio-stream", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve 0.13.8", - "ethabi", - "generic-array", - "k256 0.13.3", - "num_enum", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "pin-project-lite", -] - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel", - "base64 0.13.1", - "futures-lite", - "infer", - "pin-project-lite", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.30", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.4.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" -dependencies = [ - "num-traits", -] - -[[package]] -name = "interprocess" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bafc2f5dbdad79a6d925649758d5472647b416028099f0b829d1b67fdd47d3" -dependencies = [ - "doctest-file", - "futures-core", - "libc", - "recvmsg", - "tokio", - "widestring", - "windows-sys 0.52.0", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" -dependencies = [ - "base64 0.21.7", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "once_cell", - "sha2 0.10.8", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mev-share-sse" -version = "0.1.6" -source = "git+https://github.com/paradigmxyz/mev-share-rs?rev=9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8#9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8" -dependencies = [ - "async-sse", - "bytes", - "ethers-core", - "futures-util", - "http-types", - "pin-project-lite", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multihash" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" -dependencies = [ - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" -dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "object" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.9", - "spki 0.7.3", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.6.0", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "recvmsg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-rustls", - "hyper-tls 0.6.0", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 2.1.2", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.52.0", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ruint" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.23", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" - -[[package]] -name = "rustls-webpki" -version = "0.102.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scale-info" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - -[[package]] -name = "serde" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.204" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" -dependencies = [ - "cc", - "cfg-if", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.9", -] - -[[package]] -name = "ssz_rs" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "alloy-primitives", - "bitvec", - "serde", - "sha2 0.9.9", - "ssz_rs_derive", -] - -[[package]] -name = "ssz_rs_derive" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.71", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn-solidity" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand 2.1.0", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "thiserror" -version = "1.0.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.38.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" -dependencies = [ - "futures-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "nu-ansi-term", - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.8.5", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unsigned-varint" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.71", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "wasm-streams" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] diff --git a/bolt-kurtosis-client/Cargo.toml b/bolt-kurtosis-client/Cargo.toml deleted file mode 100644 index 538305403..000000000 --- a/bolt-kurtosis-client/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "bolt-spammer" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -tokio = { version = "1.37.0", features = ["full"] } -eyre = "0.6.12" -rand = "0.8.5" -clap = { version = "4.5.4", features = ["derive", "env"] } -tracing = "0.1.40" -tracing-subscriber = "0.3.18" -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.115" -reqwest = "0.12.3" -beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } -dotenvy = "0.15.7" -alloy = { version = "0.2.0", features = ["full"] } -url = "2.5.2" diff --git a/bolt-kurtosis-client/README.md b/bolt-kurtosis-client/README.md deleted file mode 100644 index 98aa01d91..000000000 --- a/bolt-kurtosis-client/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## A pre-confirmation spammer for the Helder testnet - -To run the spammer, make sure to set the following environment variables in a `.env` file: - -```text -EL_PROVIDER_URL=https://rpc.helder-devnets.xyz -BEACON_CLIENT_URL= -REGISTRY_ADDRESS=0xdF11D829eeC4C192774F3Ec171D822f6Cb4C14d9 -PRIVATE_KEY= -REGISTRY_ABI_PATH=./registry_abi.json -``` - -This template can be found in the `env.example` file. - -Then, just run the spammer with `cargo run`. It will fetch all the validators of the current epoch, -and try to send a pre-confirmation to the first one registered on the Bolt registry. -If no validators are found, the program will gracefully exit. Please try again in the next epoch! diff --git a/bolt-kurtosis-client/rustfmt.toml b/bolt-kurtosis-client/rustfmt.toml deleted file mode 100644 index 68c3c9303..000000000 --- a/bolt-kurtosis-client/rustfmt.toml +++ /dev/null @@ -1,11 +0,0 @@ -reorder_imports = true -imports_granularity = "Crate" -use_small_heuristics = "Max" -comment_width = 100 -wrap_comments = true -binop_separator = "Back" -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true -format_code_in_doc_comments = true -doc_comment_code_block_width = 100 diff --git a/bolt-kurtosis-client/src/constants.rs b/bolt-kurtosis-client/src/constants.rs deleted file mode 100644 index a741f8ef7..000000000 --- a/bolt-kurtosis-client/src/constants.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub const SLOTS_PER_EPOCH: u64 = 32; -pub const NOICE_GAS_PRICE: u128 = 69_420_000u128; -pub const DEAD_ADDRESS: &str = "0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD"; -pub const KURTOSIS_CHAIN_ID: u64 = 3151908; diff --git a/bolt-kurtosis-client/src/main.rs b/bolt-kurtosis-client/src/main.rs deleted file mode 100644 index 5c2c925fd..000000000 --- a/bolt-kurtosis-client/src/main.rs +++ /dev/null @@ -1,102 +0,0 @@ -use alloy::{ - eips::eip2718::Encodable2718, - hex, - network::{EthereumWallet, TransactionBuilder}, - primitives::keccak256, - providers::{Provider, ProviderBuilder}, - signers::{local::PrivateKeySigner, Signer}, -}; -use beacon_api_client::mainnet::Client as BeaconApiClient; -use clap::Parser; -use eyre::Result; -use reqwest::Url; -use tracing::info; - -pub mod constants; -pub mod utils; - -use utils::{current_slot, generate_random_blob_tx, generate_random_tx, prepare_rpc_request}; - -#[derive(Parser)] -struct Opts { - #[clap(short = 'p', long, default_value = "http://localhost:8545")] - provider_url: Url, - #[clap(short = 'c', long, default_value = "http://localhost:4000")] - beacon_client_url: Url, - #[clap(short = 'b', long)] - bolt_sidecar_url: String, - #[clap(short = 'k', long)] - private_key: String, - #[clap(short = 'n', long)] - nonce: Option, - #[clap(short = 'B', long, default_value_t = false)] - blob: bool, - #[clap(short = 's', long, default_value = "head")] - slot: String, - #[clap(short = 'C', long, default_value_t = 1)] - count: u64, -} - -#[tokio::main] -async fn main() -> Result<()> { - tracing_subscriber::fmt::init(); - info!("starting bolt-spammer"); - - let opts = Opts::parse(); - - let wallet: PrivateKeySigner = opts.private_key.parse().expect("should parse private key"); - - let sender = wallet.address(); - let transaction_signer: EthereumWallet = wallet.clone().into(); - let provider = ProviderBuilder::new().on_http(opts.provider_url); - - let beacon_api_client = BeaconApiClient::new(opts.beacon_client_url); - - let current_slot = current_slot(&beacon_api_client).await?; - let target_slot = if opts.slot == "head" { current_slot + 2 } else { opts.slot.parse()? }; - - for i in 0..opts.count { - let mut tx = if opts.blob { generate_random_blob_tx() } else { generate_random_tx() }; - tx.set_from(sender); - tx.set_nonce(provider.get_transaction_count(sender).await? + i); - - let tx_signed = tx.build(&transaction_signer).await?; - let tx_hash = tx_signed.tx_hash(); - let tx_rlp = hex::encode(tx_signed.encoded_2718()); - - let message_digest = { - let mut data = Vec::new(); - data.extend_from_slice(tx_hash.as_slice()); - data.extend_from_slice(&target_slot.to_le_bytes()); - keccak256(data) - }; - - let signature = wallet.sign_hash(&message_digest).await?; - let signature = hex::encode(signature.as_bytes()); - let signature_header = format!("{}:0x{}", wallet.address(), &signature); - - let request = prepare_rpc_request( - "bolt_requestInclusion", - vec![serde_json::json!({ - "slot": target_slot, - "txs": vec![tx_rlp], - })], - ); - - info!("Transaction hash: {}", tx_hash); - info!("body: {}", serde_json::to_string(&request)?); - - let client = reqwest::Client::new(); - let response = client - .post(&opts.bolt_sidecar_url) - .header("content-type", "application/json") - .header("x-bolt-signature", signature_header) - .body(serde_json::to_string(&request)?) - .send() - .await?; - - info!("Response: {:?}", response.text().await?); - } - - Ok(()) -} diff --git a/bolt-kurtosis-client/src/utils.rs b/bolt-kurtosis-client/src/utils.rs deleted file mode 100644 index 89edf80bc..000000000 --- a/bolt-kurtosis-client/src/utils.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::str::FromStr; - -use alloy::{ - consensus::{BlobTransactionSidecar, SidecarBuilder, SimpleCoder}, - network::TransactionBuilder, - primitives::{Address, U256}, - rpc::types::TransactionRequest, -}; -use beacon_api_client::{mainnet::Client as BeaconApiClient, BlockId}; -use eyre::Result; -use rand::{thread_rng, Rng}; -use serde_json::Value; - -use crate::constants::{DEAD_ADDRESS, KURTOSIS_CHAIN_ID, NOICE_GAS_PRICE}; - -/// Generates random ETH transfer to `DEAD_ADDRESS` with a random payload. -pub fn generate_random_tx() -> TransactionRequest { - TransactionRequest::default() - .with_to(Address::from_str(DEAD_ADDRESS).unwrap()) - .with_chain_id(KURTOSIS_CHAIN_ID) - .with_value(U256::from(thread_rng().gen_range(1..100))) - .with_gas_limit(21_000u128) - .with_gas_price(NOICE_GAS_PRICE) -} - -/// Generate random transaction with blob (eip4844) -pub fn generate_random_blob_tx() -> TransactionRequest { - let random_bytes = thread_rng().gen::<[u8; 32]>(); - let sidecar: SidecarBuilder = SidecarBuilder::from_slice(random_bytes.as_slice()); - let sidecar: BlobTransactionSidecar = sidecar.build().unwrap(); - - let dead_address = Address::from_str(DEAD_ADDRESS).unwrap(); - - TransactionRequest::default() - .with_to(dead_address) - .with_chain_id(KURTOSIS_CHAIN_ID) - .with_value(U256::from(100)) - .with_max_fee_per_blob_gas(100u128) - .max_fee_per_gas(NOICE_GAS_PRICE) - .max_priority_fee_per_gas(NOICE_GAS_PRICE / 10) - .with_gas_limit(42_000u128) - .with_blob_sidecar(sidecar) - .with_input(random_bytes) -} - -pub fn prepare_rpc_request(method: &str, params: Vec) -> Value { - serde_json::json!({ - "id": "1", - "jsonrpc": "2.0", - "method": method, - "params": params, - }) -} - -/// Returns the current slot -pub async fn current_slot(beacon_api_client: &BeaconApiClient) -> Result { - let current_slot = - beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot; - Ok(current_slot) -} diff --git a/bolt-sidecar/.env.example b/bolt-sidecar/.env.example deleted file mode 100644 index 7c8f3957a..000000000 --- a/bolt-sidecar/.env.example +++ /dev/null @@ -1,26 +0,0 @@ - -# node + PBS URLs -BOLT_SIDECAR_EXECUTION_API_URL=http://localhost:4485 -BOLT_SIDECAR_BEACON_API_URL=http://localhost:4400 -BOLT_SIDECAR_ENGINE_API_URL=http://localhost:4451 -BOLT_SIDECAR_MEVBOOST_URL=http://localhost:19550 - -# server ports -BOLT_SIDECAR_PORT=8000 -BOLT_SIDECAR_MEVBOOST_PROXY_PORT=18551 - -# commitment limits -BOLT_SIDECAR_MAX_COMMITMENTS=128 -BOLT_SIDECAR_MAX_COMMITTED_GAS=10000000 - -# chain configs -BOLT_SIDECAR_CHAIN=helder -BOLT_SIDECAR_COMMITMENT_DEADLINE=8000 -BOLT_SIDECAR_SLOT_TIME=12 - -# sidecar security configs -BOLT_SIDECAR_VALIDATOR_INDEXES= -BOLT_SIDECAR_JWT_HEX= -BOLT_SIDECAR_FEE_RECIPIENT= -BOLT_SIDECAR_BUILDER_PRIVATE_KEY= -BOLT_SIDECAR_PRIVATE_KEY= diff --git a/bolt-sidecar/.gitignore b/bolt-sidecar/.gitignore deleted file mode 100644 index 8f74f83de..000000000 --- a/bolt-sidecar/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target/ -.env -.env.dev diff --git a/bolt-sidecar/Cargo.lock b/bolt-sidecar/Cargo.lock deleted file mode 100644 index 181afdf38..000000000 --- a/bolt-sidecar/Cargo.lock +++ /dev/null @@ -1,6366 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - -[[package]] -name = "alloy" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45855eb65e9cc70294ebea1279f6d8ee0636bf2ed3897683ebbae2739975ae8c" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-contract", - "alloy-core", - "alloy-eips 0.2.0", - "alloy-genesis 0.2.0", - "alloy-network 0.2.0", - "alloy-provider 0.2.0", - "alloy-pubsub", - "alloy-rpc-client 0.2.0", - "alloy-rpc-types 0.2.0", - "alloy-serde 0.2.0", - "alloy-signer 0.2.0", - "alloy-signer-local", - "alloy-transport 0.2.0", - "alloy-transport-http 0.2.0", - "alloy-transport-ipc", - "alloy-transport-ws", -] - -[[package]] -name = "alloy-chains" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9a1892803b02f53e25bea3e414ddd0501f12d97456c9d5ade4edf88f9516f" -dependencies = [ - "num_enum", - "serde", - "strum", -] - -[[package]] -name = "alloy-consensus" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-eips 0.1.0", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.0", - "c-kzg", - "serde", -] - -[[package]] -name = "alloy-consensus" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a016bfa21193744d4c38b3f3ab845462284d129e5e23c7cc0fafca7e92d9db37" -dependencies = [ - "alloy-eips 0.1.2", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.2", - "c-kzg", - "serde", -] - -[[package]] -name = "alloy-consensus" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58047cc851e58c26224521d1ecda466e3d746ebca0274cd5427aa660a88c353" -dependencies = [ - "alloy-eips 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.2.0", - "c-kzg", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa5d42d9f87896536234b0fac1a84ad9d9dc7a4b27839cac35d0899e64ddf083" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network 0.2.0", - "alloy-primitives", - "alloy-provider 0.2.0", - "alloy-pubsub", - "alloy-rpc-types-eth 0.2.0", - "alloy-sol-types", - "alloy-transport 0.2.0", - "futures", - "futures-util", - "thiserror", -] - -[[package]] -name = "alloy-core" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529fc6310dc1126c8de51c376cbc59c79c7f662bd742be7dc67055d5421a81b4" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-types", -] - -[[package]] -name = "alloy-dyn-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "const-hex", - "itoa", - "serde", - "serde_json", - "winnow 0.6.13", -] - -[[package]] -name = "alloy-eips" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.0", - "c-kzg", - "once_cell", - "serde", - "sha2 0.10.8", -] - -[[package]] -name = "alloy-eips" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d6d8118b83b0489cfb7e6435106948add2b35217f4a5004ef895f613f60299" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.2", - "c-kzg", - "once_cell", - "serde", - "sha2 0.10.8", -] - -[[package]] -name = "alloy-eips" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a3e14fa0d152d00bd8daf605eb74ad397efb0f54bd7155585823dddb4401e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.2.0", - "c-kzg", - "derive_more", - "k256 0.13.3", - "once_cell", - "serde", - "sha2 0.10.8", -] - -[[package]] -name = "alloy-genesis" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-primitives", - "alloy-serde 0.1.0", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-genesis" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cb76c8a3913f2466c5488f3a915e3a15d15596bdc935558c1a9be75e9ec508" -dependencies = [ - "alloy-primitives", - "alloy-serde 0.2.0", - "serde", -] - -[[package]] -name = "alloy-json-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f0ae6e93b885cc70fe8dae449e7fd629751dbee8f59767eaaa7285333c5727" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-json-rpc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a9feec2352c78545d1a37415699817bae8dc41654bd1bfe57d6cdd5433bd" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc122cbee2b8523854cc11d87bcd5773741602c553d2d2d106d82eeb9c16924a" -dependencies = [ - "alloy-consensus 0.1.2", - "alloy-eips 0.1.2", - "alloy-json-rpc 0.1.2", - "alloy-primitives", - "alloy-rpc-types-eth 0.1.2", - "alloy-serde 0.1.2", - "alloy-signer 0.1.2", - "alloy-sol-types", - "async-trait", - "auto_impl", - "futures-utils-wasm", - "thiserror", -] - -[[package]] -name = "alloy-network" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3223d71dc78f464b2743418d0be8b5c894313e272105a6206ad5e867d67b3ce2" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-json-rpc 0.2.0", - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0", - "alloy-serde 0.2.0", - "alloy-signer 0.2.0", - "alloy-sol-types", - "async-trait", - "auto_impl", - "futures-utils-wasm", - "thiserror", -] - -[[package]] -name = "alloy-node-bindings" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a2864b3470d3c74bf50a70f4a5f3e87a7359870878a268be829d7caff42f13" -dependencies = [ - "alloy-genesis 0.2.0", - "alloy-primitives", - "k256 0.13.3", - "serde_json", - "tempfile", - "thiserror", - "tracing", - "url", -] - -[[package]] -name = "alloy-primitives" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "ethereum_ssz", - "getrandom 0.2.15", - "hex-literal", - "itoa", - "k256 0.13.3", - "keccak-asm", - "proptest", - "rand 0.8.5", - "ruint", - "serde", - "tiny-keccak", -] - -[[package]] -name = "alloy-provider" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d5af289798fe8783acd0c5f10644d9d26f54a12bc52a083e4f3b31718e9bf92" -dependencies = [ - "alloy-chains", - "alloy-consensus 0.1.2", - "alloy-eips 0.1.2", - "alloy-json-rpc 0.1.2", - "alloy-network 0.1.2", - "alloy-primitives", - "alloy-rpc-client 0.1.2", - "alloy-rpc-types-eth 0.1.2", - "alloy-transport 0.1.2", - "alloy-transport-http 0.1.2", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "futures", - "futures-utils-wasm", - "lru", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "alloy-provider" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29da7457d853cb8199ec04b227d5d2ef598be3e59fc2bbad70c8be213292f32" -dependencies = [ - "alloy-chains", - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-json-rpc 0.2.0", - "alloy-network 0.2.0", - "alloy-primitives", - "alloy-pubsub", - "alloy-rpc-client 0.2.0", - "alloy-rpc-types-engine 0.2.0", - "alloy-rpc-types-eth 0.2.0", - "alloy-rpc-types-trace", - "alloy-transport 0.2.0", - "alloy-transport-http 0.2.0", - "alloy-transport-ipc", - "alloy-transport-ws", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "futures", - "futures-utils-wasm", - "lru", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "alloy-pubsub" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64acfec654ade392cecfa9bba0408eb2a337d55f1b857925da79970cb70f3d6" -dependencies = [ - "alloy-json-rpc 0.2.0", - "alloy-primitives", - "alloy-transport 0.2.0", - "bimap", - "futures", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40fcb53b2a9d0a78a4968b2eca8805a4b7011b9ee3fdfa2acaf137c5128f36b" -dependencies = [ - "alloy-json-rpc 0.1.2", - "alloy-transport 0.1.2", - "alloy-transport-http 0.1.2", - "futures", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-client" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9e609524fa31c2c70eb24c0da60796809193ad4787a6dfe6d0db0d3ac112d" -dependencies = [ - "alloy-json-rpc 0.2.0", - "alloy-primitives", - "alloy-pubsub", - "alloy-transport 0.2.0", - "alloy-transport-http 0.2.0", - "alloy-transport-ipc", - "alloy-transport-ws", - "futures", - "pin-project", - "reqwest 0.12.5", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-consensus 0.1.0", - "alloy-eips 0.1.0", - "alloy-genesis 0.1.0", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.0", - "alloy-sol-types", - "itertools 0.12.1", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f2fbe956a3e0f0975c798f488dc6be96b669544df3737e18f4a325b42f4c86" -dependencies = [ - "alloy-rpc-types-eth 0.1.2", - "alloy-serde 0.1.2", -] - -[[package]] -name = "alloy-rpc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5d76f1e8b22f48b7b8f985782b68e7eb3938780e50e8b646a53e41a598cdf5" -dependencies = [ - "alloy-rpc-types-beacon 0.2.0", - "alloy-rpc-types-engine 0.2.0", - "alloy-rpc-types-eth 0.2.0", - "alloy-rpc-types-trace", - "alloy-serde 0.2.0", - "serde", -] - -[[package]] -name = "alloy-rpc-types-beacon" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-eips 0.1.0", - "alloy-primitives", - "alloy-rpc-types-engine 0.1.0", - "serde", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-beacon" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b47dcc8e3bebea57b1c9495a7e6f3313e99d355c0f5b80473cfbdfcbdd6ebea" -dependencies = [ - "alloy-eips 0.2.0", - "alloy-primitives", - "alloy-rpc-types-engine 0.2.0", - "serde", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-engine" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-consensus 0.1.0", - "alloy-eips 0.1.0", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types 0.1.0", - "alloy-serde 0.1.0", - "jsonwebtoken", - "rand 0.8.5", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-engine" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73445fbc5c02258e3d0d977835c92366a4d91545fd456c3fc8601c61810bc9f6" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth 0.2.0", - "alloy-serde 0.2.0", - "jsonwebtoken", - "rand 0.8.5", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083f443a83b9313373817236a8f4bea09cca862618e9177d822aee579640a5d6" -dependencies = [ - "alloy-consensus 0.1.2", - "alloy-eips 0.1.2", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.2", - "alloy-sol-types", - "itertools 0.13.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605fa8462732bb8fd0645a9941e12961e079d45ae6a44634c826f8229c187bdf" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.2.0", - "alloy-sol-types", - "itertools 0.13.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-rpc-types-trace" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f561a8cdd377b6ac3beab805b9df5ec2c7d99bb6139aab23c317f26df6fb346" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth 0.2.0", - "alloy-serde 0.2.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-serde" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-serde" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d94da1c0c4e27cc344b05626fe22a89dc6b8b531b9475f3b7691dbf6913e4109" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c5b9057acc02aee1b8aac2b5a0729cb0f73d080082c111313e5d1f92a96630" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-signer" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d876be3afd8b78979540084ff63995292a26aa527ad0d44276405780aa0ffd" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "elliptic-curve 0.13.8", - "k256 0.13.3", - "thiserror", -] - -[[package]] -name = "alloy-signer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37f10592696f4ab8b687d5a8ab55e998a14ea0ca5f8eb20ad74a96ad671bb54a" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "elliptic-curve 0.13.8", - "k256 0.13.3", - "thiserror", -] - -[[package]] -name = "alloy-signer-local" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b537f3e55f30753578f4623d5f66ddad8fa582af3fa6b15bad23dd1b9775228" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-network 0.2.0", - "alloy-primitives", - "alloy-signer 0.2.0", - "async-trait", - "k256 0.13.3", - "rand 0.8.5", - "thiserror", -] - -[[package]] -name = "alloy-sol-macro" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" -dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "alloy-sol-macro-expander" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" -dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", - "const-hex", - "heck 0.5.0", - "indexmap 2.2.6", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.67", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-macro-input" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck 0.5.0", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.67", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" -dependencies = [ - "serde", - "winnow 0.6.13", -] - -[[package]] -name = "alloy-sol-types" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "const-hex", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245af9541f0a0dbd5258669c80dfe3af118164cacec978a520041fc130550deb" -dependencies = [ - "alloy-json-rpc 0.1.2", - "base64 0.22.1", - "futures-util", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "url", -] - -[[package]] -name = "alloy-transport" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b44b0f6f4a2593b258fa7b6cae8968e6a4c404d9ef4f5bc74401f2d04fa23fa" -dependencies = [ - "alloy-json-rpc 0.2.0", - "base64 0.22.1", - "futures-util", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-http" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5619c017e1fdaa1db87f9182f4f0ed97c53d674957f4902fba655e972d359c6c" -dependencies = [ - "alloy-json-rpc 0.1.2", - "alloy-transport 0.1.2", - "reqwest 0.12.5", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-http" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d8f1eefa8cb9e7550740ee330feba4fed303a77ad3085707546f9152a88c380" -dependencies = [ - "alloy-json-rpc 0.2.0", - "alloy-transport 0.2.0", - "reqwest 0.12.5", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-transport-ipc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31007c56dc65bd81392112dda4a14c20ac7e30bb4cb2e9176192e8d9fab1983f" -dependencies = [ - "alloy-json-rpc 0.2.0", - "alloy-pubsub", - "alloy-transport 0.2.0", - "bytes", - "futures", - "interprocess", - "pin-project", - "serde_json", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "alloy-transport-ws" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ccc1c8f8ae415e93ec0e7851bd4cdf4afdd48793d13a91b860317da1f36104" -dependencies = [ - "alloy-pubsub", - "alloy-transport 0.2.0", - "futures", - "http 1.1.0", - "rustls", - "serde_json", - "tokio", - "tokio-tungstenite 0.23.1", - "tracing", - "ws_stream_wasm", -] - -[[package]] -name = "alloy-trie" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03704f265cbbb943b117ecb5055fd46e8f41e7dc8a58b1aed20bcd40ace38c15" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "derive_more", - "hashbrown 0.14.5", - "nybbles", - "serde", - "smallvec", - "tracing", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" - -[[package]] -name = "anstyle-parse" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-sse" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6fa871e4334a622afd6bb2f611635e8083a6f5e2936c0f90f37c7ef9856298" -dependencies = [ - "async-channel", - "futures-lite", - "http-types", - "log", - "memchr", - "pin-project-lite", -] - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "async-trait" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "axum" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" -dependencies = [ - "async-trait", - "axum-core", - "axum-macros", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "hyper 1.3.1", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper 0.1.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-extra" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" -dependencies = [ - "axum", - "axum-core", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "mime", - "pin-project-lite", - "serde", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "beacon-api-client" -version = "0.1.0" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "clap", - "ethereum-consensus", - "http 0.2.12", - "itertools 0.10.5", - "mev-share-sse", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - -[[package]] -name = "bimap" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -dependencies = [ - "serde", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "serde", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bls12_381" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" -dependencies = [ - "ff 0.13.0", - "group 0.13.0", - "pairing", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "blst" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "bolt-sidecar" -version = "0.1.3-alpha" -dependencies = [ - "alloy", - "alloy-node-bindings", - "async-trait", - "axum", - "axum-extra", - "beacon-api-client", - "blst", - "bytes", - "cb-common", - "cb-crypto", - "clap", - "dotenvy", - "ethereum-consensus", - "eyre", - "futures", - "hex", - "lru", - "parking_lot", - "partial-mpt", - "rand 0.8.5", - "regex", - "reqwest 0.12.5", - "reth-primitives", - "reth-rpc-layer", - "secp256k1", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", - "tree_hash", - "tree_hash_derive", - "warp", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "bytemuck" -version = "1.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - -[[package]] -name = "cb-common" -version = "0.0.1" -source = "git+https://github.com/Commit-Boost/commit-boost-client#4c482605195d22cc797886d082e5cd6a90160ba9" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-beacon 0.1.0", - "blst", - "ethereum_ssz", - "ethereum_ssz_derive", - "rand 0.8.5", - "serde", - "serde_json", - "toml 0.8.14", - "tracing", - "tracing-subscriber", - "tree_hash", - "tree_hash_derive", - "url", -] - -[[package]] -name = "cb-crypto" -version = "0.0.1" -source = "git+https://github.com/Commit-Boost/commit-boost-client#4c482605195d22cc797886d082e5cd6a90160ba9" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-beacon 0.1.0", - "axum", - "blst", - "cb-common", - "ethereum_ssz", - "ethereum_ssz_derive", - "eyre", - "rand 0.8.5", - "serde", - "thiserror", - "tokio", - "tracing", - "tree_hash", - "tree_hash_derive", - "uuid", -] - -[[package]] -name = "cc" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" -dependencies = [ - "jobserver", - "libc", - "once_cell", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "windows-targets 0.52.5", -] - -[[package]] -name = "clap" -version = "4.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim 0.11.1", -] - -[[package]] -name = "clap_derive" -version = "4.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "clap_lex" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" - -[[package]] -name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-hex" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" -dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.11.1", - "syn 2.0.67", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" -dependencies = [ - "darling_core 0.20.9", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 2.0.67", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "doctest-file" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.9", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "either" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.0", - "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.3", - "subtle", - "zeroize", -] - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enr" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" -dependencies = [ - "base64 0.13.1", - "bs58", - "bytes", - "hex", - "k256 0.11.6", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - -[[package]] -name = "enumn" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-consensus" -version = "0.1.1" -source = "git+https://github.com/ralexstokes/ethereum-consensus?rev=cf3c404#cf3c404043230559660810bc0c9d6d5a8498d819" -dependencies = [ - "blst", - "bs58", - "c-kzg", - "enr", - "hex", - "integer-sqrt", - "multiaddr", - "multihash", - "rand 0.8.5", - "serde", - "serde_json", - "serde_yaml 0.8.26", - "sha2 0.10.8", - "ssz_rs", - "thiserror", - "tokio", - "tokio-stream", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethereum_hashing" -version = "1.0.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233dc6f434ce680dbabf4451ee3380cec46cb3c45d66660445a435619710dd35" -dependencies = [ - "cpufeatures", - "lazy_static", - "ring 0.16.20", - "sha2 0.10.8", -] - -[[package]] -name = "ethereum_ssz" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" -dependencies = [ - "ethereum-types", - "itertools 0.10.5", - "smallvec", -] - -[[package]] -name = "ethereum_ssz_derive" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eccd5378ec34a07edd3d9b48088cbc63309d0367d14ba10b0cdb1d1791080ea" -dependencies = [ - "darling 0.13.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve 0.13.8", - "ethabi", - "generic-array", - "k256 0.13.3", - "num_enum", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "bitvec", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", - "serde", -] - -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http 1.1.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "pin-project-lite", -] - -[[package]] -name = "http-types" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" -dependencies = [ - "anyhow", - "async-channel", - "base64 0.13.1", - "futures-lite", - "infer", - "pin-project-lite", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs", - "serde_urlencoded", - "url", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.3.1", - "hyper-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.29", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.3.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" -dependencies = [ - "num-traits", -] - -[[package]] -name = "interprocess" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bafc2f5dbdad79a6d925649758d5472647b416028099f0b829d1b67fdd47d3" -dependencies = [ - "doctest-file", - "futures-core", - "libc", - "recvmsg", - "tokio", - "widestring", - "windows-sys 0.52.0", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonrpsee-core" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21545a9445fbd582840ff5160a9a3e12b8e6da582151cdb07bde9a1970ba3a24" -dependencies = [ - "anyhow", - "async-trait", - "beef", - "bytes", - "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "jsonrpsee-types", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "jsonrpsee-http-client" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb25cab482c8512c4f3323a5c90b95a3b8f7c90681a87bf7a68b942d52f08933" -dependencies = [ - "async-trait", - "base64 0.22.1", - "http-body 1.0.0", - "hyper 1.3.1", - "hyper-rustls", - "hyper-util", - "jsonrpsee-core", - "jsonrpsee-types", - "rustls", - "rustls-platform-verifier", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f511b714bca46f9a3e97c0e0eb21d2c112e83e444d2db535b5ec7093f5836d73" -dependencies = [ - "beef", - "http 1.1.0", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" -dependencies = [ - "base64 0.21.7", - "js-sys", - "pem", - "ring 0.17.8", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", - "once_cell", - "sha2 0.10.8", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "kzg-rs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9920cd4460ce3cbca19c62f3bb9a9611562478a4dc9d2c556f4a7d049c5b6b" -dependencies = [ - "bls12_381", - "glob", - "hex", - "once_cell", - "serde", - "serde_derive", - "serde_yaml 0.9.34+deprecated", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mev-share-sse" -version = "0.1.6" -source = "git+https://github.com/paradigmxyz/mev-share-rs?rev=9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8#9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8" -dependencies = [ - "async-sse", - "bytes", - "ethers-core", - "futures-util", - "http-types", - "pin-project-lite", - "reqwest 0.11.27", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "modular-bitfield" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" -dependencies = [ - "modular-bitfield-impl", - "static_assertions", -] - -[[package]] -name = "modular-bitfield-impl" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "multer" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 0.2.12", - "httparse", - "log", - "memchr", - "mime", - "spin 0.9.8", - "version_check", -] - -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multihash" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" -dependencies = [ - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.8", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" -dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "nybbles" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" -dependencies = [ - "alloy-rlp", - "const-hex", - "proptest", - "serde", - "smallvec", -] - -[[package]] -name = "object" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "pairing" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" -dependencies = [ - "group 0.13.0", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", -] - -[[package]] -name = "partial-mpt" -version = "0.1.0" -source = "git+https://github.com/chainbound/partial-mpt?branch=feat/alloy#f806996d7f854908c810f9de1b9901972a23eefa" -dependencies = [ - "alloy-eips 0.1.2", - "alloy-primitives", - "alloy-provider 0.1.2", - "alloy-rlp", - "alloy-rpc-types 0.1.2", - "alloy-transport-http 0.1.2", - "dotenvy", - "rlp", - "tokio", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pem" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.9", - "spki 0.7.3", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml 0.5.11", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.6.0", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "recvmsg" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" - -[[package]] -name = "redox_syscall" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg 0.50.0", -] - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.4.5", - "http 1.1.0", - "http-body 1.0.0", - "http-body-util", - "hyper 1.3.1", - "hyper-rustls", - "hyper-tls 0.6.0", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 2.1.2", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.52.0", -] - -[[package]] -name = "reth-codecs" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-genesis 0.2.0", - "alloy-primitives", - "alloy-trie", - "bytes", - "modular-bitfield", - "reth-codecs-derive", - "serde", -] - -[[package]] -name = "reth-codecs-derive" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "convert_case 0.6.0", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "reth-ethereum-forks" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-chains", - "alloy-primitives", - "alloy-rlp", - "auto_impl", - "crc", - "dyn-clone", - "once_cell", - "rustc-hash", - "serde", - "thiserror-no-std", -] - -[[package]] -name = "reth-primitives" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-eips 0.2.0", - "alloy-genesis 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types 0.2.0", - "bytes", - "c-kzg", - "derive_more", - "modular-bitfield", - "once_cell", - "rayon", - "reth-codecs", - "reth-ethereum-forks", - "reth-primitives-traits", - "reth-static-file-types", - "reth-trie-common", - "revm-primitives", - "secp256k1", - "serde", - "tempfile", - "thiserror-no-std", - "zstd", -] - -[[package]] -name = "reth-primitives-traits" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-eips 0.2.0", - "alloy-genesis 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-eth 0.2.0", - "byteorder", - "bytes", - "derive_more", - "modular-bitfield", - "reth-codecs", - "revm-primitives", - "roaring", - "serde", - "thiserror-no-std", -] - -[[package]] -name = "reth-rpc-layer" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-rpc-types-engine 0.2.0", - "http 1.1.0", - "jsonrpsee-http-client", - "pin-project", - "tower", - "tracing", -] - -[[package]] -name = "reth-static-file-types" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-primitives", - "derive_more", - "serde", - "strum", -] - -[[package]] -name = "reth-trie-common" -version = "1.0.2" -source = "git+https://github.com/paradigmxyz/reth#f55d43c25a61654d839ea0183fa63c40f0a0b7ec" -dependencies = [ - "alloy-consensus 0.2.0", - "alloy-genesis 0.2.0", - "alloy-primitives", - "alloy-rlp", - "alloy-trie", - "bytes", - "derive_more", - "itertools 0.13.0", - "nybbles", - "reth-codecs", - "reth-primitives-traits", - "revm-primitives", - "serde", -] - -[[package]] -name = "revm-primitives" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc4311037ee093ec50ec734e1424fcb3e12d535c6cef683b75d1c064639630c" -dependencies = [ - "alloy-eips 0.2.0", - "alloy-primitives", - "auto_impl", - "bitflags 2.6.0", - "bitvec", - "c-kzg", - "cfg-if", - "derive_more", - "dyn-clone", - "enumn", - "hashbrown 0.14.5", - "hex", - "kzg-rs", - "once_cell", - "serde", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "roaring" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7699249cc2c7d71939f30868f47e9d7add0bdc030d90ee10bfd16887ff8bb1c8" -dependencies = [ - "bytemuck", - "byteorder", -] - -[[package]] -name = "ruint" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "ethereum_ssz", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.23", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" -dependencies = [ - "log", - "once_cell", - "ring 0.17.8", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" -dependencies = [ - "openssl-probe", - "rustls-pemfile 2.1.2", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" - -[[package]] -name = "rustls-platform-verifier" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5f0d26fa1ce3c790f9590868f0109289a044acb954525f933e2aa3b871c157d" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-roots", - "winapi", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e217e7fdc8466b5b35d30f8c0a30febd29173df4a3a0c2115d306b9c4117ad" - -[[package]] -name = "rustls-webpki" -version = "0.102.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" -dependencies = [ - "ring 0.17.8", - "rustls-pki-types", - "untrusted 0.9.0", -] - -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scale-info" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.9", - "generic-array", - "pkcs8 0.10.2", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" -dependencies = [ - "rand 0.8.5", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" -dependencies = [ - "cc", -] - -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "num-bigint", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - -[[package]] -name = "serde" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "serde_json" -version = "1.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" -dependencies = [ - "itoa", - "serde", -] - -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", -] - -[[package]] -name = "serde_spanned" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.2.6", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" -dependencies = [ - "darling 0.20.9", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.2.6", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "sha3-asm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" -dependencies = [ - "cc", - "cfg-if", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.9", -] - -[[package]] -name = "ssz_rs" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "alloy-primitives", - "bitvec", - "serde", - "sha2 0.9.9", - "ssz_rs_derive", -] - -[[package]] -name = "ssz_rs_derive" -version = "0.9.0" -source = "git+https://github.com/ralexstokes/ssz-rs?rev=84ef2b71aa004f6767420badb42c902ad56b8b72#84ef2b71aa004f6767420badb42c902ad56b8b72" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.67", -] - -[[package]] -name = "subtle" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn-solidity" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand 2.1.0", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "thiserror" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "thiserror-impl-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e6318948b519ba6dc2b442a6d0b904ebfb8d411a3ad3e07843615a72249758" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "thiserror-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ad459d94dd517257cc96add8a43190ee620011bb6e6cdc82dafd97dfafafea" -dependencies = [ - "thiserror-impl-no-std", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.21.0", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" -dependencies = [ - "futures-util", - "log", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite 0.23.0", - "webpki-roots", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.14", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" -dependencies = [ - "indexmap 2.2.6", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.13", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "nu-ansi-term", - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tree_hash" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c998ac5fe2b07c025444bdd522e6258110b63861c6698eedc610c071980238d" -dependencies = [ - "ethereum-types", - "ethereum_hashing", - "smallvec", -] - -[[package]] -name = "tree_hash_derive" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84303a9c7cda5f085a3ed9cd241d1e95e04d88aab1d679b02f212e653537ba86" -dependencies = [ - "darling 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.8.5", - "sha1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.1.0", - "httparse", - "log", - "rand 0.8.5", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "unsigned-varint" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" -dependencies = [ - "getrandom 0.2.15", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "warp" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http 0.2.12", - "hyper 0.14.29", - "log", - "mime", - "mime_guess", - "multer", - "percent-encoding", - "pin-project", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-tungstenite 0.21.0", - "tokio-util", - "tower-service", - "tracing", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.67", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "wasm-streams" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "zerocopy" -version = "0.7.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.67", -] - -[[package]] -name = "zstd" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.11+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/bolt-sidecar/Cargo.toml b/bolt-sidecar/Cargo.toml deleted file mode 100644 index bddd6aa04..000000000 --- a/bolt-sidecar/Cargo.toml +++ /dev/null @@ -1,73 +0,0 @@ -[package] -name = "bolt-sidecar" -version = "0.1.3-alpha" -edition = "2021" -default-run = "bolt-sidecar" - -[dependencies] -# core -clap = { version = "4.5.4", features = ["derive", "env"] } -tokio = { version = "1", features = ["full"] } -axum = { version = "0.7", features = ["macros"] } -axum-extra = "0.9.3" -warp = "0.3.7" -futures = "0.3" - -# crypto -blst = "0.3.12" -tree_hash = "0.5" -tree_hash_derive = "0.5" -secp256k1 = { version = "0.29.0", features = ["rand"] } - -# alloy -alloy = { version = "0.2.0", features = [ - "full", - "provider-trace-api", - "rpc-types-beacon", - "rpc-types-engine", -] } - -# alloy-rpc-types = { git = "https://github.com/chainbound/alloy", branch = "fix/account-override-serialize" } - - -# reth -reth-primitives = { git = "https://github.com/paradigmxyz/reth", version = "1.0.2" } -reth-rpc-layer = { git = "https://github.com/paradigmxyz/reth", version = "1.0.2" } -# reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "71c404d" } - -reqwest = "0.12" -ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } -beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } - -# types -partial-mpt = { git = "https://github.com/chainbound/partial-mpt", branch = "feat/alloy" } -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.115" -parking_lot = "0.12.1" -async-trait = "0.1.79" -bytes = "1.6.0" -lru = "0.12.3" -hex = "0.4.3" - -# utils -eyre = "0.6.12" -thiserror = "1.0" -rand = "0.8.5" -dotenvy = "0.15.7" -regex = "1.10.5" - -# tracing -tracing = "0.1.40" -tracing-subscriber = "0.3.18" - -# commit-boost -cb-crypto = { git = "https://github.com/Commit-Boost/commit-boost-client" } -cb-common = { git = "https://github.com/Commit-Boost/commit-boost-client" } - -[dev-dependencies] -alloy-node-bindings = "0.2.0" - - -[[bin]] -name = "bolt-sidecar" -path = "bin/sidecar.rs" diff --git a/bolt-sidecar/Dockerfile b/bolt-sidecar/Dockerfile deleted file mode 100644 index 7eb73069e..000000000 --- a/bolt-sidecar/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM rust:slim-bullseye AS compiler - -RUN cargo install cargo-chef - -WORKDIR /app - -FROM compiler AS planner -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM compiler AS builder -COPY --from=planner /app/recipe.json recipe.json -RUN apt-get update && apt-get install pkg-config libssl-dev -y -RUN cargo chef cook --release --recipe-path recipe.json -COPY . . -RUN cargo build --release - -FROM debian:bullseye-slim -WORKDIR /usr/local/bin -COPY --from=builder /app/target/release/bolt-sidecar / -RUN apt-get update && apt-get install -y libssl-dev ca-certificates && rm -rf /var/lib/apt/lists/* - -ENTRYPOINT ["/bolt-sidecar"] diff --git a/bolt-sidecar/README.md b/bolt-sidecar/README.md deleted file mode 100644 index 1fa54f3ab..000000000 --- a/bolt-sidecar/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# `bolt-sidecar` - -The Bolt sidecar is the main entrypoint for proposers to issue proposer commitments. Proposers should point their `builder-api` to the Bolt sidecar API in order to enable it. - -## Functionality - -The sidecar is responsible for: - -1. Registering the preferences of the proposer -2. Accepting (or rejecting) commitment requests -3. Implementing pricing strategies -4. Building a block template & simulation -5. Communicating constraints to the downstream PBS pipeline -6. Verifying any incoming builder bids from mev-boost -7. Dealing with PBS failures by falling back to the local template - -### Local Block Template - -The local block template serves 3 purposes: - -1. Building a fallback block in case the PBS pipeline fails -2. Maintaining intermediate state to simulate commitment requests on -3. Syncing with Ethereum state and invalidating stale commitments - -_What do we simulate?_ -We only simulate in order to verify the validity of the transaction according to protocol rules. This means: - -1. The transaction sender should be able to pay for it: `balance >= value + fee` -2. The transaction nonce should be higher than any previously known nonce -3. The base fee should be able to cover the maximum base fee the target block can have: `max_base_fee = current_base_fee * 1.125^block_diff` - -_Building strategy_ -The block template is built and simulated on in FIFO order. - -_Updating state_ -We store a list of commitment addresses along with their account state. For each new block, we should update that state and check if we have to invalidate any commitments. This is critical as we don't want to return an invalid block -in case a fallback block is required. - -## Running - -- We require Anvil to be installed in the $PATH for running tests diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs deleted file mode 100644 index 07f9a932e..000000000 --- a/bolt-sidecar/bin/sidecar.rs +++ /dev/null @@ -1,22 +0,0 @@ -use bolt_sidecar::{Config, SidecarDriver}; -use eyre::{bail, Result}; -use tracing::info; - -#[tokio::main] -async fn main() -> Result<()> { - // TODO: improve telemetry setup (#116) - tracing_subscriber::fmt::init(); - - let config = match Config::parse_from_cli() { - Ok(config) => config, - Err(err) => bail!("Failed to parse CLI arguments: {:?}", err), - }; - - info!(chain = config.chain.name(), "Starting Bolt sidecar"); - match SidecarDriver::new(config).await { - Ok(driver) => driver.run_forever().await, - Err(err) => bail!("Failed to initialize the sidecar driver: {:?}", err), - }; - - Ok(()) -} diff --git a/bolt-sidecar/rustfmt.toml b/bolt-sidecar/rustfmt.toml deleted file mode 100644 index 68c3c9303..000000000 --- a/bolt-sidecar/rustfmt.toml +++ /dev/null @@ -1,11 +0,0 @@ -reorder_imports = true -imports_granularity = "Crate" -use_small_heuristics = "Max" -comment_width = 100 -wrap_comments = true -binop_separator = "Back" -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true -format_code_in_doc_comments = true -doc_comment_code_block_width = 100 diff --git a/bolt-sidecar/src/api/builder.rs b/bolt-sidecar/src/api/builder.rs deleted file mode 100644 index b80fe726d..000000000 --- a/bolt-sidecar/src/api/builder.rs +++ /dev/null @@ -1,400 +0,0 @@ -use axum::{ - body::{self, Body}, - extract::{Path, Request, State}, - http::StatusCode, - response::Html, - routing::{get, post}, - Json, Router, -}; -use beacon_api_client::VersionedValue; -use ethereum_consensus::{ - builder::SignedValidatorRegistration, - deneb::mainnet::SignedBlindedBeaconBlock, - primitives::{BlsPublicKey, Hash32}, - Fork, -}; -use parking_lot::Mutex; -use reqwest::Url; -use serde::Deserialize; -use std::{sync::Arc, time::Duration}; -use thiserror::Error; -use tokio::net::TcpListener; -use tracing::{debug, error, info, warn}; - -use super::spec::{ - BuilderApiError, ConstraintsApi, GET_HEADER_PATH, GET_PAYLOAD_PATH, REGISTER_VALIDATORS_PATH, - STATUS_PATH, -}; -use crate::{ - client::mevboost::MevBoostClient, - primitives::{GetPayloadResponse, PayloadFetcher, SignedBuilderBid}, -}; - -const MAX_BLINDED_BLOCK_LENGTH: usize = 1024 * 1024; - -/// TODO: determine value -const GET_HEADER_WITH_PROOFS_TIMEOUT: Duration = Duration::from_millis(500); - -/// A proxy server for the builder API. -/// Forwards all requests to the target after interception. -pub struct BuilderProxyServer { - proxy_target: T, - /// INVARIANT: This will be `Some` IFF we have signed a local header for the latest slot. - local_payload: Mutex>, - /// The payload fetcher to get locally built payloads. - payload_fetcher: P, -} - -#[derive(Debug, Deserialize)] -pub struct GetHeaderParams { - pub slot: u64, - pub parent_hash: Hash32, - #[serde(rename = "pubkey")] - pub public_key: BlsPublicKey, -} - -impl BuilderProxyServer -where - T: ConstraintsApi, - P: PayloadFetcher + Send + Sync, -{ - pub fn new(proxy_target: T, payload_fetcher: P) -> Self { - Self { proxy_target, local_payload: Mutex::new(None), payload_fetcher } - } - - /// Gets the status. Just forwards the request to mev-boost and returns the status. - pub async fn status(State(server): State>>) -> StatusCode { - let start = std::time::Instant::now(); - debug!("Received status request"); - - let status = match server.proxy_target.status().await { - Ok(status) => status, - Err(error) => { - error!(%error, "Failed to get status from mev-boost"); - StatusCode::INTERNAL_SERVER_ERROR - } - }; - - let elapsed = start.elapsed(); - debug!(?elapsed, "Returning status: {:?}", status); - - status - } - - /// Registers the validators. Just forwards the request to mev-boost - /// and returns the status. - /// - /// TODO: intercept this to register Bolt validators on-chain as well. - pub async fn register_validators( - State(server): State>>, - Json(registrations): Json>, - ) -> Result { - let start = std::time::Instant::now(); - debug!("Received register validators request"); - - let response = server.proxy_target.register_validators(registrations).await; - - let elapsed = start.elapsed(); - debug!(?elapsed, "Returning response: {:?}", response); - - response.map(|_| StatusCode::OK) - } - - /// Gets the header. NOTE: converts this request to a get_header_with_proofs - /// request to the modified mev-boost. - /// - /// In case of a builder or relay failure, we return the locally built block header - /// and store the actual payload so we can return it later. - pub async fn get_header( - State(server): State>>, - Path(params): Path, - ) -> Result>, BuilderApiError> { - let start = std::time::Instant::now(); - - debug!("Received get_header request"); - let slot = params.slot; - - let err = match tokio::time::timeout( - GET_HEADER_WITH_PROOFS_TIMEOUT, - server.proxy_target.get_header_with_proofs(params), - ) - .await - { - Ok(res) => match res { - Err(builder_err) => builder_err, - Ok(header) => { - // Clear the local payload cache if we have a successful response - // By definition of `server.local_payload`, this will be `Some` IFF we have - // signed a local header - let mut local_payload = server.local_payload.lock(); - *local_payload = None; - - debug!(elapsed = ?start.elapsed(), "Returning signed builder bid"); - return Ok(Json(header)); - } - }, - Err(err) => BuilderApiError::Timeout(err), - }; - - // On ANY error, we fall back to locally built block - warn!(slot, elapsed = ?start.elapsed(), err = ?err, "Proxy error, fetching local payload instead"); - - let Some(payload_and_bid) = server.payload_fetcher.fetch_payload(slot).await else { - // TODO: handle failure? In this case, we don't have a fallback block - // which means we haven't made any commitments. This means the EL should - // fallback to local block building. - debug!("No local payload with commitments produced for slot {slot}"); - return Err(BuilderApiError::FailedToFetchLocalPayload(slot)); - }; - - let hash = payload_and_bid.bid.message.header.block_hash.clone(); - let number = payload_and_bid.bid.message.header.block_number; - info!(elapsed = ?start.elapsed(), %hash, "Fetched local payload for slot {slot}"); - - { - // Since we've signed a local header, set the payload for - // the following `get_payload` request. - let mut local_payload = server.local_payload.lock(); - *local_payload = Some(payload_and_bid.payload); - } - - let versioned_bid = VersionedValue:: { - version: Fork::Deneb, - data: payload_and_bid.bid, - meta: Default::default(), - }; - - info!(elapsed = ?start.elapsed(), %hash, number, ?versioned_bid, "Returning locally built header"); - Ok(Json(versioned_bid)) - } - - pub async fn get_payload( - State(server): State>>, - req: Request, - ) -> Result, BuilderApiError> { - let start = std::time::Instant::now(); - debug!("Received get_payload request"); - - let body_bytes = - body::to_bytes(req.into_body(), MAX_BLINDED_BLOCK_LENGTH).await.map_err(|e| { - error!(error = %e, "Failed to read request body"); - e - })?; - - // Convert to signed blinded beacon block - let signed_blinded_block = serde_json::from_slice::(&body_bytes) - .map_err(|e| { - error!(error = %e, "Failed to parse signed blinded block"); - e - })?; - - // If we have a locally built payload, it means we signed a local header. - // Return it and clear the cache. - if let Some(local_payload) = server.local_payload.lock().take() { - check_locally_built_payload_integrity(&signed_blinded_block, &local_payload)?; - - debug!("Valid local block found, returning: {local_payload:?}"); - return Ok(Json(local_payload)); - } - - // TODO: how do we deal with failures here? What if we submit the signed blinded block but - // don't get a response? should we ignore the error or proceed with a local block - // (highly risky -> equivocation risk) - let payload = server - .proxy_target - .get_payload(signed_blinded_block) - .await - .map(Json) - .map_err(|e| { - error!(elapsed = ?start.elapsed(), error = %e, "Failed to get payload from mev-boost"); - e - })?; - - debug!(elapsed = ?start.elapsed(), "Returning payload"); - - Ok(payload) - } -} - -/// Configuration for the builder proxy. -#[derive(Debug, Clone)] -pub struct BuilderProxyConfig { - /// The URL of the target mev-boost server. - pub mevboost_url: Url, - /// The port on which the builder proxy should listen. - pub server_port: u16, -} - -/// Start the builder proxy with the given payload fetcher and configuration. -pub async fn start_builder_proxy_server

( - payload_fetcher: P, - config: BuilderProxyConfig, -) -> eyre::Result<()> -where - P: PayloadFetcher + Send + Sync + 'static, -{ - info!( - port = config.server_port, - target = config.mevboost_url.to_string(), - "Starting builder proxy..." - ); - - let mev_boost = MevBoostClient::new(config.mevboost_url); - let server = Arc::new(BuilderProxyServer::new(mev_boost, payload_fetcher)); - - let router = Router::new() - .route("/", get(index)) - .route(STATUS_PATH, get(BuilderProxyServer::status)) - .route(REGISTER_VALIDATORS_PATH, post(BuilderProxyServer::register_validators)) - .route(GET_HEADER_PATH, get(BuilderProxyServer::get_header)) - .route(GET_PAYLOAD_PATH, post(BuilderProxyServer::get_payload)) - .with_state(server); - - let addr = format!("0.0.0.0:{}", config.server_port); - let listener = TcpListener::bind(addr).await?; - axum::serve(listener, router).await?; - - Ok(()) -} - -async fn index() -> Html<&'static str> { - Html("Hello") -} - -#[derive(Error, Debug, Clone)] -pub enum LocalPayloadIntegrityError { - #[error( - "Locally built payload does not match signed header. - {field_name} mismatch: expected {expected}, have {have}" - )] - FieldMismatch { field_name: String, expected: String, have: String }, -} - -/// Helper macro to compare fields of the signed header and the local block. -macro_rules! assert_payload_fields_eq { - ($expected:expr, $have:expr, $field_name:ident) => { - if $expected != $have { - error!( - field_name = stringify!($field_name), - expected = %$expected, - have = %$have, - "Local block does not match signed header" - ); - return Err(LocalPayloadIntegrityError::FieldMismatch { - field_name: stringify!($field_name).to_string(), - expected: $expected.to_string(), - have: $have.to_string(), - }); - } - }; -} - -/// Perform some integrity checks on the locally built payload. -/// This is to ensure that the beacon node will accept the header that was signed -/// when we submit the full payload. -#[inline] -fn check_locally_built_payload_integrity( - signed_blinded_block: &SignedBlindedBeaconBlock, - local_payload: &GetPayloadResponse, -) -> Result<(), LocalPayloadIntegrityError> { - let header_signed_by_cl = &signed_blinded_block.message.body.execution_payload_header; - let local_execution_payload = local_payload.execution_payload(); - - assert_payload_fields_eq!( - &header_signed_by_cl.block_hash, - local_execution_payload.block_hash(), - BlockHash - ); - - assert_payload_fields_eq!( - header_signed_by_cl.block_number, - local_execution_payload.block_number(), - BlockNumber - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.state_root, - local_execution_payload.state_root(), - StateRoot - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.receipts_root, - local_execution_payload.receipts_root(), - ReceiptsRoot - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.prev_randao, - local_execution_payload.prev_randao(), - PrevRandao - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.gas_limit, - &local_execution_payload.gas_limit(), - GasLimit - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.gas_used, - &local_execution_payload.gas_used(), - GasUsed - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.timestamp, - &local_execution_payload.timestamp(), - Timestamp - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.extra_data, - local_execution_payload.extra_data(), - ExtraData - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.base_fee_per_gas, - local_execution_payload.base_fee_per_gas(), - BaseFeePerGas - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.parent_hash, - local_execution_payload.parent_hash(), - ParentHash - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.fee_recipient, - local_execution_payload.fee_recipient(), - FeeRecipient - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.logs_bloom, - local_execution_payload.logs_bloom(), - LogsBloom - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.blob_gas_used, - &local_execution_payload.blob_gas_used().unwrap_or_default(), - BlobGasUsed - ); - - assert_payload_fields_eq!( - &header_signed_by_cl.excess_blob_gas, - &local_execution_payload.excess_blob_gas().unwrap_or_default(), - ExcessBlobGas - ); - - // TODO: Sanity check: recalculate transactions and withdrawals roots - // and assert them against the header - - // TODO: Sanity check: verify the validator signature - // signed_blinded_block.verify_signature()?; - - Ok(()) -} diff --git a/bolt-sidecar/src/api/commitments/jsonrpc.rs b/bolt-sidecar/src/api/commitments/jsonrpc.rs deleted file mode 100644 index e15461c46..000000000 --- a/bolt-sidecar/src/api/commitments/jsonrpc.rs +++ /dev/null @@ -1,48 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde_json::Value; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct JsonPayload { - /// The JSON-RPC version string. MUST be "2.0". - pub jsonrpc: String, - /// The method string. - pub method: String, - /// Optional ID. - pub id: Option, - /// The parameters object. - pub params: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct JsonResponse { - pub jsonrpc: String, - /// Optional ID. Must be serialized as `null` if not present. - pub id: Option, - #[serde(skip_serializing_if = "Value::is_null", default)] - pub result: Value, - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, -} - -impl Default for JsonResponse { - fn default() -> Self { - Self { jsonrpc: "2.0".to_string(), id: None, result: Value::Null, error: None } - } -} - -impl JsonResponse { - pub fn from_error(code: i32, message: String) -> Self { - Self { - jsonrpc: "2.0".to_string(), - id: None, - result: Value::Null, - error: Some(JsonError { code, message }), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct JsonError { - pub code: i32, - pub message: String, -} diff --git a/bolt-sidecar/src/api/commitments/mod.rs b/bolt-sidecar/src/api/commitments/mod.rs deleted file mode 100644 index a139aaeb2..000000000 --- a/bolt-sidecar/src/api/commitments/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -/// JSON-RPC helper types and functions. -mod jsonrpc; -/// The commitments-API JSON-RPC server implementation. -pub mod server; -/// The commitments-API specification and errors. -pub mod spec; diff --git a/bolt-sidecar/src/api/commitments/server.rs b/bolt-sidecar/src/api/commitments/server.rs deleted file mode 100644 index 3894cfe69..000000000 --- a/bolt-sidecar/src/api/commitments/server.rs +++ /dev/null @@ -1,377 +0,0 @@ -use std::{ - collections::HashSet, - fmt, - future::Future, - net::{SocketAddr, ToSocketAddrs}, - pin::Pin, - str::FromStr, - sync::Arc, -}; - -use alloy::primitives::{Address, Signature}; -use axum::{extract::State, http::HeaderMap, routing::post, Json, Router}; -use axum_extra::extract::WithRejection; -use serde_json::Value; -use tokio::{ - net::TcpListener, - sync::{mpsc, oneshot}, -}; -use tracing::{debug, error, info, instrument}; - -use crate::{ - common::CARGO_PKG_VERSION, - primitives::{ - commitment::{InclusionCommitment, SignedCommitment}, - CommitmentRequest, InclusionRequest, - }, -}; - -use super::{ - jsonrpc::{JsonPayload, JsonResponse}, - spec::{ - CommitmentsApi, Error, RejectionError, GET_VERSION_METHOD, REQUEST_INCLUSION_METHOD, - SIGNATURE_HEADER, - }, -}; - -/// Event type emitted by the commitments API. -#[derive(Debug)] -pub struct Event { - /// The request to process. - pub request: CommitmentRequest, - /// The response channel. - pub response: oneshot::Sender>, -} - -/// The inner commitments-API handler that implements the [CommitmentsApi] spec. -/// Should be wrapped by a [CommitmentsApiServer] JSON-RPC server to handle requests. -#[derive(Debug)] -pub struct CommitmentsApiInner { - /// Event notification channel - events: mpsc::Sender, - /// Optional whitelist of ECDSA public keys - #[allow(unused)] - whitelist: Option>, -} - -impl CommitmentsApiInner { - /// Create a new API server with an optional whitelist of ECDSA public keys. - pub fn new(events: mpsc::Sender) -> Self { - Self { events, whitelist: None } - } -} - -#[async_trait::async_trait] -impl CommitmentsApi for CommitmentsApiInner { - async fn request_inclusion( - &self, - inclusion_request: InclusionRequest, - ) -> Result { - let (response_tx, response_rx) = oneshot::channel(); - - let event = Event { - request: CommitmentRequest::Inclusion(inclusion_request), - response: response_tx, - }; - - self.events.send(event).await.unwrap(); - - response_rx.await.map_err(|_| Error::Internal)?.map(|c| c.into()) - } -} - -/// The outer commitments-API JSON-RPC server that wraps the [CommitmentsApiInner] handler. -pub struct CommitmentsApiServer { - /// The address to bind the server to. This will be updated - /// with the actual address after the server is started. - addr: SocketAddr, - /// The shutdown signal. - signal: Option + Send>>>, -} - -impl fmt::Debug for CommitmentsApiServer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CommitmentsApiServer").field("addr", &self.addr).finish() - } -} - -impl CommitmentsApiServer { - /// Creates the server with the given address and default shutdown signal (CTRL+C). - pub fn new(addr: A) -> Self { - Self { - addr: addr.to_socket_addrs().unwrap().next().unwrap(), - signal: Some(Box::pin(async { - let _ = tokio::signal::ctrl_c().await; - })), - } - } - - /// Creates the server with the given address and shutdown signal. - pub fn with_shutdown(self, addr: A, signal: S) -> Self - where - A: ToSocketAddrs, - S: Future + Send + 'static, - { - Self { - addr: addr.to_socket_addrs().unwrap().next().unwrap(), - signal: Some(Box::pin(signal)), - } - } - - /// Runs the JSON-RPC server, sending events to the provided channel. - pub async fn run(&mut self, events_tx: mpsc::Sender) { - let api = Arc::new(CommitmentsApiInner::new(events_tx)); - - let router = Router::new().route("/", post(Self::handle_rpc)).with_state(api); - - let listener = match TcpListener::bind(self.addr).await { - Ok(listener) => listener, - Err(err) => { - error!(?err, "Failed to bind Commitments API server"); - panic!("Failed to bind Commitments API server"); - } - }; - - let addr = listener.local_addr().expect("Failed to get local address"); - self.addr = addr; - - info!("Commitments RPC server bound to {addr}"); - - let signal = self.signal.take().expect("Signal not set"); - - tokio::spawn(async move { - if let Err(err) = axum::serve(listener, router).with_graceful_shutdown(signal).await { - error!(?err, "Commitments API Server error"); - } - }); - } - - /// Returns the local addr the server is listening on (or configured with). - pub fn local_addr(&self) -> SocketAddr { - self.addr - } - - /// Handler function for the root JSON-RPC path. - #[instrument(skip_all, name = "RPC", fields(method = %payload.method))] - async fn handle_rpc( - headers: HeaderMap, - State(api): State>, - WithRejection(Json(payload), _): WithRejection, Error>, - ) -> Result, Error> { - debug!("Received new request"); - - let (signer, signature) = auth_from_headers(&headers).inspect_err(|e| { - error!("Failed to extract signature from headers: {:?}", e); - })?; - - match payload.method.as_str() { - GET_VERSION_METHOD => { - let version_string = format!("bolt-sidecar-v{CARGO_PKG_VERSION}"); - Ok(Json(JsonResponse { - id: payload.id, - result: Value::String(version_string), - ..Default::default() - })) - } - - REQUEST_INCLUSION_METHOD => { - let Some(request_json) = payload.params.first().cloned() else { - return Err(RejectionError::ValidationFailed("Bad params".to_string()).into()); - }; - - // Parse the inclusion request from the parameters - let mut inclusion_request: InclusionRequest = serde_json::from_value(request_json) - .map_err(|e| RejectionError::ValidationFailed(e.to_string()))?; - - // Set the signature here for later processing - inclusion_request.set_signature(signature); - - let digest = inclusion_request.digest(); - let recovered_signer = signature.recover_address_from_prehash(&digest)?; - - if recovered_signer != signer { - error!( - ?recovered_signer, - ?signer, - "Recovered signer does not match the provided signer" - ); - - return Err(Error::InvalidSignature(crate::primitives::SignatureError)); - } - - // Set the request signer - inclusion_request.set_signer(recovered_signer); - - info!(signer = ?recovered_signer, %digest, "New valid inclusion request received"); - let inclusion_commitment = api.request_inclusion(inclusion_request).await?; - - // Create the JSON-RPC response - let response = JsonResponse { - id: payload.id, - result: serde_json::to_value(inclusion_commitment).unwrap(), - ..Default::default() - }; - - Ok(Json(response)) - } - other => { - error!("Unknown method: {}", other); - Err(Error::UnknownMethod) - } - } - } -} - -/// Extracts the signature ([SIGNATURE_HEADER]) from the HTTP headers. -#[inline] -fn auth_from_headers(headers: &HeaderMap) -> Result<(Address, Signature), Error> { - let auth = headers.get(SIGNATURE_HEADER).ok_or(Error::NoSignature)?; - - // Remove the "0x" prefix - let auth = auth.to_str().map_err(|_| Error::MalformedHeader)?; - - let mut split = auth.split(':'); - - let address = split.next().ok_or(Error::MalformedHeader)?; - let address = Address::from_str(address).map_err(|_| Error::MalformedHeader)?; - - let sig = split.next().ok_or(Error::MalformedHeader)?; - let sig = Signature::from_str(sig) - .map_err(|_| Error::InvalidSignature(crate::primitives::SignatureError))?; - - Ok((address, sig)) -} - -#[cfg(test)] -mod test { - use alloy::{ - primitives::TxHash, - signers::{k256::SecretKey, local::PrivateKeySigner, Signer}, - }; - use serde_json::json; - - use crate::{ - primitives::commitment::ECDSASignatureExt, - test_util::{create_signed_commitment_request, default_test_transaction}, - }; - - use super::*; - - #[tokio::test] - async fn test_signature_from_headers() { - let mut headers = HeaderMap::new(); - let hash = TxHash::random(); - let signer = PrivateKeySigner::random(); - let addr = signer.address(); - - let expected_sig = signer.sign_hash(&hash).await.unwrap(); - headers - .insert(SIGNATURE_HEADER, format!("{addr}:{}", expected_sig.to_hex()).parse().unwrap()); - - let (address, signature) = auth_from_headers(&headers).unwrap(); - assert_eq!(signature, expected_sig); - assert_eq!(address, addr); - } - - #[tokio::test] - async fn test_request_unauthorized() { - let _ = tracing_subscriber::fmt::try_init(); - - let mut server = CommitmentsApiServer::new("0.0.0.0:0"); - - let (events_tx, _) = mpsc::channel(1); - - server.run(events_tx).await; - let addr = server.local_addr(); - - let sk = SecretKey::random(&mut rand::thread_rng()); - let signer = PrivateKeySigner::from(sk.clone()); - let tx = default_test_transaction(signer.address(), None); - let req = create_signed_commitment_request(&[tx], &sk, 12).await.unwrap(); - - let payload = json!({ - "jsonrpc": "2.0", - "id": 1, - "method": "bolt_requestInclusion", - "params": [req] - }); - - let url = format!("http://{addr}"); - - let client = reqwest::Client::new(); - // client.post(url).header("content-type", "application/json").body(payload) - - let response = client - .post(url) - .json(&payload) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - - // Assert unauthorized because of missing signature - assert_eq!(response.error.unwrap().code, -32003); - } - - #[tokio::test] - async fn test_request_success() { - let _ = tracing_subscriber::fmt::try_init(); - - let mut server = CommitmentsApiServer::new("0.0.0.0:0"); - - let (events_tx, mut events) = mpsc::channel(1); - - server.run(events_tx).await; - let addr = server.local_addr(); - - let sk = SecretKey::random(&mut rand::thread_rng()); - let signer = PrivateKeySigner::from(sk.clone()); - let tx = default_test_transaction(signer.address(), None); - let req = create_signed_commitment_request(&[tx], &sk, 12).await.unwrap(); - - let sig = req.signature().unwrap().to_hex(); - - let payload = json!({ - "jsonrpc": "2.0", - "id": 1, - "method": "bolt_requestInclusion", - "params": [req] - }); - - let url = format!("http://{addr}"); - - let client = reqwest::Client::new(); - // client.post(url).header("content-type", "application/json").body(payload) - - let (tx, rx) = oneshot::channel(); - - tokio::spawn(async move { - let response = client - .post(url) - .header(SIGNATURE_HEADER, format!("{}:{}", signer.address(), sig)) - .json(&payload) - .send() - .await - .unwrap(); - - let json = response.json::().await.unwrap(); - - // Assert unauthorized because of missing signature - assert!(json.error.is_none()); - - let _ = tx.send(()); - }); - - let Event { request, response } = events.recv().await.unwrap(); - - let commitment_signer = PrivateKeySigner::random(); - - let commitment = request.commit_and_sign(&commitment_signer).await.unwrap(); - - response.send(Ok(commitment)).unwrap(); - - rx.await.unwrap(); - } -} diff --git a/bolt-sidecar/src/api/commitments/spec.rs b/bolt-sidecar/src/api/commitments/spec.rs deleted file mode 100644 index 0de3ff777..000000000 --- a/bolt-sidecar/src/api/commitments/spec.rs +++ /dev/null @@ -1,126 +0,0 @@ -use alloy::primitives::SignatureError; -use axum::{extract::rejection::JsonRejection, http::StatusCode, response::IntoResponse, Json}; -use thiserror::Error; - -use crate::{ - primitives::{commitment::InclusionCommitment, InclusionRequest}, - state::{consensus::ConsensusError, ValidationError}, -}; - -use super::jsonrpc::JsonResponse; - -pub(super) const SIGNATURE_HEADER: &str = "x-bolt-signature"; - -pub(super) const GET_VERSION_METHOD: &str = "bolt_getVersion"; - -pub(super) const REQUEST_INCLUSION_METHOD: &str = "bolt_requestInclusion"; - -/// Error type for the commitments API. -#[derive(Debug, Error)] -pub enum Error { - /// Request rejected. - #[error("Request rejected: {0}")] - Rejected(#[from] RejectionError), - /// Consensus validation failed. - #[error("Consensus validation error: {0}")] - Consensus(#[from] ConsensusError), - /// Request validation failed. - #[error("Validation failed: {0}")] - Validation(#[from] ValidationError), - /// Duplicate request. - #[error("Duplicate request")] - Duplicate, - /// Internal server error. - #[error("Internal server error")] - Internal, - /// Missing signature. - #[error("Missing '{SIGNATURE_HEADER}' header")] - NoSignature, - /// Invalid signature. - #[error(transparent)] - InvalidSignature(#[from] crate::primitives::SignatureError), - /// Malformed authentication header. - #[error("Malformed authentication header")] - MalformedHeader, - /// Signature error. - #[error(transparent)] - Signature(#[from] SignatureError), - /// Unknown method. - #[error("Unknown method")] - UnknownMethod, - /// Invalid JSON. - #[error(transparent)] - InvalidJson(#[from] JsonRejection), -} - -impl IntoResponse for Error { - fn into_response(self) -> axum::http::Response { - match self { - Error::Rejected(err) => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32000, err.to_string()))) - .into_response() - } - Error::Duplicate => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32001, self.to_string()))) - .into_response() - } - Error::Internal => ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(JsonResponse::from_error(-32002, self.to_string())), - ) - .into_response(), - Error::NoSignature => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32003, self.to_string()))) - .into_response() - } - Error::InvalidSignature(err) => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32004, err.to_string()))) - .into_response() - } - Error::Signature(err) => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32005, err.to_string()))) - .into_response() - } - Error::Consensus(err) => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32006, err.to_string()))) - .into_response() - } - Error::Validation(err) => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32006, err.to_string()))) - .into_response() - } - Error::MalformedHeader => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32007, self.to_string()))) - .into_response() - } - Error::UnknownMethod => { - (StatusCode::BAD_REQUEST, Json(JsonResponse::from_error(-32601, self.to_string()))) - .into_response() - } - Error::InvalidJson(err) => ( - StatusCode::BAD_REQUEST, - Json(JsonResponse::from_error(-32600, format!("Invalid request: {err}"))), - ) - .into_response(), - } - } -} - -/// Error indicating the rejection of a commitment request. This should -/// be returned to the user. -#[derive(Debug, Error)] -pub enum RejectionError { - /// State validation failed for this request. - #[error("Validation failed: {0}")] - ValidationFailed(String), -} - -/// Implements the commitments-API: -#[async_trait::async_trait] -pub trait CommitmentsApi { - /// Implements: - async fn request_inclusion( - &self, - inclusion_request: InclusionRequest, - ) -> Result; -} diff --git a/bolt-sidecar/src/api/mod.rs b/bolt-sidecar/src/api/mod.rs deleted file mode 100644 index ea01a5263..000000000 --- a/bolt-sidecar/src/api/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -/// Builder API endpoints -/// Reference: -pub mod builder; - -/// Sidecar API spec and error handling -pub mod spec; - -/// Commitments-API spec and errors. -pub mod commitments; diff --git a/bolt-sidecar/src/api/spec.rs b/bolt-sidecar/src/api/spec.rs deleted file mode 100644 index 373f292ec..000000000 --- a/bolt-sidecar/src/api/spec.rs +++ /dev/null @@ -1,156 +0,0 @@ -use axum::{ - http::StatusCode, - response::{IntoResponse, Response}, - Json, -}; -use beacon_api_client::VersionedValue; -use ethereum_consensus::{ - builder::SignedValidatorRegistration, deneb::mainnet::SignedBlindedBeaconBlock, -}; -use serde::{Deserialize, Serialize, Serializer}; - -use crate::primitives::{BatchedSignedConstraints, GetPayloadResponse, SignedBuilderBid}; - -use super::builder::GetHeaderParams; - -/// The path to the builder API status endpoint. -pub const STATUS_PATH: &str = "/eth/v1/builder/status"; -/// The path to the builder API register validators endpoint. -pub const REGISTER_VALIDATORS_PATH: &str = "/eth/v1/builder/validators"; -/// The path to the builder API get header endpoint. -pub const GET_HEADER_PATH: &str = "/eth/v1/builder/header/:slot/:parent_hash/:pubkey"; -/// The path to the builder API get payload endpoint. -pub const GET_PAYLOAD_PATH: &str = "/eth/v1/builder/blinded_blocks"; -/// The path to the constraints API submit constraints endpoint. -pub const CONSTRAINTS_PATH: &str = "/eth/v1/builder/constraints"; - -/// A response object for errors. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ErrorResponse { - #[serde(serialize_with = "serialize_status_code")] - code: u16, - message: String, -} - -/// Helper to serialize a status code as a string using the provided serializer. -pub fn serialize_status_code(value: &u16, serializer: S) -> Result -where - S: Serializer, -{ - serializer.serialize_str(&value.to_string()) -} - -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -#[non_exhaustive] -pub enum BuilderApiError { - #[error("No validators could be registered: {0:?}")] - FailedRegisteringValidators(ErrorResponse), - #[error("Failed getting header: {0:?}")] - FailedGettingHeader(ErrorResponse), - #[error("Failed getting payload: {0:?}")] - FailedGettingPayload(ErrorResponse), - #[error("Failed submitting constraints: {0:?}")] - FailedSubmittingConstraints(ErrorResponse), - #[error("Failed to fetch local payload for slot {0}")] - FailedToFetchLocalPayload(u64), - #[error("Axum error: {0:?}")] - AxumError(#[from] axum::Error), - #[error("Json error: {0:?}")] - JsonError(#[from] serde_json::Error), - #[error("Reqwest error: {0:?}")] - ReqwestError(#[from] reqwest::Error), - #[error("API request timed out : {0:?}")] - Timeout(#[from] tokio::time::error::Elapsed), - #[error("Invalid fork: {0}")] - InvalidFork(String), - #[error("Locally-built payload does not match expected signed header")] - LocalPayloadIntegrity(#[from] super::builder::LocalPayloadIntegrityError), - #[error("Generic error: {0}")] - Generic(String), -} - -impl IntoResponse for BuilderApiError { - fn into_response(self) -> Response { - match self { - BuilderApiError::FailedRegisteringValidators(error) => { - (StatusCode::from_u16(error.code).unwrap(), Json(error)).into_response() - } - BuilderApiError::FailedGettingHeader(error) => { - (StatusCode::from_u16(error.code).unwrap(), Json(error)).into_response() - } - BuilderApiError::FailedGettingPayload(error) => { - (StatusCode::from_u16(error.code).unwrap(), Json(error)).into_response() - } - BuilderApiError::FailedSubmittingConstraints(error) => { - (StatusCode::from_u16(error.code).unwrap(), Json(error)).into_response() - } - BuilderApiError::AxumError(err) => { - (StatusCode::BAD_REQUEST, err.to_string()).into_response() - } - BuilderApiError::JsonError(err) => { - (StatusCode::BAD_REQUEST, err.to_string()).into_response() - } - BuilderApiError::FailedToFetchLocalPayload(_) => { - (StatusCode::NO_CONTENT, self.to_string()).into_response() - } - BuilderApiError::ReqwestError(_) => ( - StatusCode::INTERNAL_SERVER_ERROR, - StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap(), - ) - .into_response(), - BuilderApiError::Timeout(_) => ( - StatusCode::GATEWAY_TIMEOUT, - StatusCode::GATEWAY_TIMEOUT.canonical_reason().unwrap(), - ) - .into_response(), - BuilderApiError::InvalidFork(err) => { - (StatusCode::BAD_REQUEST, Json(err)).into_response() - } - BuilderApiError::LocalPayloadIntegrity(err) => { - (StatusCode::BAD_REQUEST, err.to_string()).into_response() - } - BuilderApiError::Generic(err) => { - (StatusCode::INTERNAL_SERVER_ERROR, Json(err)).into_response() - } - } - } -} - -#[async_trait::async_trait] -/// Implements the builder API as defines in -pub trait BuilderApi { - /// Implements: - async fn status(&self) -> Result; - /// Implements: - async fn register_validators( - &self, - registrations: Vec, - ) -> Result<(), BuilderApiError>; - /// Implements: - async fn get_header( - &self, - params: GetHeaderParams, - ) -> Result; - /// Implements: - async fn get_payload( - &self, - signed_block: SignedBlindedBeaconBlock, - ) -> Result; -} - -#[async_trait::async_trait] -/// Implements the constraints API as defines in -pub trait ConstraintsApi: BuilderApi { - /// Implements: - async fn submit_constraints( - &self, - constraints: &BatchedSignedConstraints, - ) -> Result<(), BuilderApiError>; - - /// Implements: - async fn get_header_with_proofs( - &self, - params: GetHeaderParams, - ) -> Result, BuilderApiError>; -} diff --git a/bolt-sidecar/src/builder/compat.rs b/bolt-sidecar/src/builder/compat.rs deleted file mode 100644 index 1278bfe10..000000000 --- a/bolt-sidecar/src/builder/compat.rs +++ /dev/null @@ -1,200 +0,0 @@ -use alloy::{ - eips::eip4895::Withdrawal, - primitives::{Address, Bloom, B256, U256}, - rpc::types::engine::{ - ExecutionPayload as AlloyExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, - ExecutionPayloadV3, - }, -}; -use ethereum_consensus::{ - bellatrix::mainnet::Transaction, - capella::spec, - deneb::{ - mainnet::{ - ExecutionPayloadHeader as ConsensusExecutionPayloadHeader, - Withdrawal as ConsensusWithdrawal, MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - }, - ExecutionAddress, ExecutionPayload as DenebExecutionPayload, - }, - ssz::prelude::{ssz_rs, ByteList, ByteVector, HashTreeRoot, List}, - types::mainnet::ExecutionPayload as ConsensusExecutionPayload, -}; -use reth_primitives::{SealedBlock, TransactionSigned, Withdrawals}; - -/// Compatibility: convert a sealed header into an ethereum-consensus execution payload header. -/// This requires recalculating the withdrals and transactions roots as SSZ instead of MPT roots. -pub(crate) fn to_execution_payload_header( - sealed_block: &SealedBlock, - transactions: Vec, -) -> ConsensusExecutionPayloadHeader { - // Transactions and withdrawals are treated as opaque byte arrays in consensus types - let transactions_bytes = transactions.iter().map(|t| t.envelope_encoded()).collect::>(); - - let mut transactions_ssz: List = List::default(); - - for tx in transactions_bytes { - transactions_ssz.push(Transaction::try_from(tx.as_ref()).unwrap()); - } - - let transactions_root = transactions_ssz.hash_tree_root().expect("valid transactions root"); - - let mut withdrawals_ssz: List = - List::default(); - - if let Some(withdrawals) = sealed_block.withdrawals.as_ref() { - for w in withdrawals.iter() { - withdrawals_ssz.push(to_consensus_withdrawal(w)); - } - } - - let withdrawals_root = withdrawals_ssz.hash_tree_root().expect("valid withdrawals root"); - - let header = &sealed_block.header; - - ConsensusExecutionPayloadHeader { - parent_hash: to_bytes32(header.parent_hash), - fee_recipient: to_bytes20(header.beneficiary), - state_root: to_bytes32(header.state_root), - receipts_root: to_bytes32(header.receipts_root), - logs_bloom: to_byte_vector(header.logs_bloom), - prev_randao: to_bytes32(header.mix_hash), - block_number: header.number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: ByteList::try_from(header.extra_data.as_ref()).unwrap(), - base_fee_per_gas: ssz_rs::U256::from(header.base_fee_per_gas.unwrap_or_default()), - block_hash: to_bytes32(header.hash()), - blob_gas_used: header.blob_gas_used.unwrap_or_default(), - excess_blob_gas: header.excess_blob_gas.unwrap_or_default(), - transactions_root, - withdrawals_root, - } -} - -/// Compatibility: convert a sealed block into an Alloy execution payload -pub(crate) fn to_alloy_execution_payload( - block: &SealedBlock, - block_hash: B256, -) -> AlloyExecutionPayload { - let alloy_withdrawals = block - .withdrawals - .as_ref() - .map(|withdrawals| { - withdrawals - .iter() - .map(|w| Withdrawal { - index: w.index, - validator_index: w.validator_index, - address: w.address, - amount: w.amount, - }) - .collect::>() - }) - .unwrap_or_default(); - - AlloyExecutionPayload::V3(ExecutionPayloadV3 { - blob_gas_used: block.blob_gas_used(), - excess_blob_gas: block.excess_blob_gas.unwrap_or_default(), - payload_inner: ExecutionPayloadV2 { - payload_inner: ExecutionPayloadV1 { - base_fee_per_gas: U256::from(block.base_fee_per_gas.unwrap_or_default()), - block_hash, - block_number: block.number, - extra_data: block.extra_data.clone(), - transactions: block.raw_transactions(), - fee_recipient: block.header.beneficiary, - gas_limit: block.gas_limit, - gas_used: block.gas_used, - logs_bloom: block.logs_bloom, - parent_hash: block.parent_hash, - prev_randao: block.mix_hash, - receipts_root: block.receipts_root, - state_root: block.state_root, - timestamp: block.timestamp, - }, - withdrawals: alloy_withdrawals, - }, - }) -} - -/// Compatibility: convert a sealed block into an ethereum-consensus execution payload -pub(crate) fn to_consensus_execution_payload(value: &SealedBlock) -> ConsensusExecutionPayload { - let hash = value.hash(); - let header = &value.header; - let transactions = &value.body; - let withdrawals = &value.withdrawals; - let transactions = transactions - .iter() - .map(|t| spec::Transaction::try_from(t.envelope_encoded().as_ref()).unwrap()) - .collect::>(); - let withdrawals = withdrawals - .as_ref() - .unwrap_or(&Withdrawals::default()) - .iter() - .map(|w| spec::Withdrawal { - index: w.index as usize, - validator_index: w.validator_index as usize, - address: to_bytes20(w.address), - amount: w.amount, - }) - .collect::>(); - - let payload = DenebExecutionPayload { - parent_hash: to_bytes32(header.parent_hash), - fee_recipient: to_bytes20(header.beneficiary), - state_root: to_bytes32(header.state_root), - receipts_root: to_bytes32(header.receipts_root), - logs_bloom: to_byte_vector(header.logs_bloom), - prev_randao: to_bytes32(header.mix_hash), - block_number: header.number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: ByteList::try_from(header.extra_data.as_ref()).unwrap(), - base_fee_per_gas: ssz_rs::U256::from(header.base_fee_per_gas.unwrap_or_default()), - block_hash: to_bytes32(hash), - transactions: TryFrom::try_from(transactions).unwrap(), - withdrawals: TryFrom::try_from(withdrawals).unwrap(), - blob_gas_used: value.blob_gas_used(), - excess_blob_gas: value.excess_blob_gas.unwrap_or_default(), - }; - ConsensusExecutionPayload::Deneb(payload) -} - -/// Compatibility: convert a withdrawal from ethereum-consensus to a Reth withdrawal -pub(crate) fn to_reth_withdrawal( - value: ethereum_consensus::capella::Withdrawal, -) -> reth_primitives::Withdrawal { - reth_primitives::Withdrawal { - index: value.index as u64, - validator_index: value.validator_index as u64, - address: Address::from_slice(value.address.as_ref()), - amount: value.amount, - } -} - -/// Compatibility: convert a withdrawal from Reth to ethereum-consensus -pub(crate) fn to_consensus_withdrawal( - value: &reth_primitives::Withdrawal, -) -> ethereum_consensus::capella::Withdrawal { - ethereum_consensus::capella::Withdrawal { - index: value.index as usize, - validator_index: value.validator_index as usize, - address: ExecutionAddress::try_from(value.address.as_ref()).unwrap(), - amount: value.amount, - } -} - -pub(crate) fn to_bytes32(value: B256) -> spec::Bytes32 { - spec::Bytes32::try_from(value.as_ref()).unwrap() -} - -pub(crate) fn to_bytes20(value: Address) -> spec::ExecutionAddress { - spec::ExecutionAddress::try_from(value.as_ref()).unwrap() -} - -pub(crate) fn to_byte_vector(value: Bloom) -> ByteVector<256> { - ByteVector::<256>::try_from(value.as_ref()).unwrap() -} diff --git a/bolt-sidecar/src/builder/mod.rs b/bolt-sidecar/src/builder/mod.rs deleted file mode 100644 index 6d77ea761..000000000 --- a/bolt-sidecar/src/builder/mod.rs +++ /dev/null @@ -1,155 +0,0 @@ -use alloy::primitives::U256; -use blst::min_pk::SecretKey; -use ethereum_consensus::{ - crypto::{KzgCommitment, PublicKey}, - deneb::mainnet::ExecutionPayloadHeader, - ssz::prelude::{List, MerkleizationError}, -}; -use payload_builder::FallbackPayloadBuilder; -use signature::sign_builder_message; - -use crate::{ - primitives::{ - BuilderBid, GetPayloadResponse, PayloadAndBid, PayloadAndBlobs, SignedBuilderBid, - }, - ChainConfig, Config, -}; - -/// Basic block template handler that can keep track of -/// the local commitments according to protocol validity rules. -pub mod template; -pub use template::BlockTemplate; - -/// Builder payload signing utilities -pub mod signature; - -/// Compatibility types and utilities between Alloy, Reth, -/// Ethereum-consensus and other crates. -#[doc(hidden)] -mod compat; - -/// Fallback Payload builder agent that leverages the engine API's -/// `engine_newPayloadV3` response error to produce a valid payload. -pub mod payload_builder; - -#[derive(Debug, thiserror::Error)] -#[non_exhaustive] -#[allow(missing_docs)] -pub enum BuilderError { - #[error("Failed to parse from integer: {0}")] - Parse(#[from] std::num::ParseIntError), - #[error("Failed to de/serialize JSON: {0}")] - Json(#[from] serde_json::Error), - #[error("Failed to decode hex: {0}")] - Hex(#[from] hex::FromHexError), - #[error("Invalid JWT: {0}")] - Jwt(#[from] reth_rpc_layer::JwtError), - #[error("Failed HTTP request: {0}")] - Reqwest(#[from] reqwest::Error), - #[error("Failed while fetching from RPC: {0}")] - Transport(#[from] alloy::transports::TransportError), - #[error("Failed in SSZ merkleization: {0}")] - Merkleization(#[from] MerkleizationError), - #[error("Failed while interacting with beacon client: {0}")] - BeaconApi(#[from] beacon_api_client::Error), - #[error("Failed to parse hint from engine response: {0}")] - InvalidEngineHint(String), - #[error("Failed to build payload: {0}")] - Custom(String), -} - -/// Local builder instance that can ingest a sealed header and -/// create the corresponding builder bid ready for the Builder API. -#[derive(Debug)] -pub struct LocalBuilder { - /// BLS credentials for the local builder. We use this to sign the - /// payload bid submissions built by the sidecar. - secret_key: SecretKey, - /// Chain configuration - /// (necessary for signing messages with the correct domain) - chain: ChainConfig, - /// Async fallback payload builder to generate valid payloads with - /// the engine API's `engine_newPayloadV3` response error. - fallback_builder: FallbackPayloadBuilder, - /// The last payload and bid that was built by the local builder. - payload_and_bid: Option, -} - -impl LocalBuilder { - /// Create a new local builder with the given secret key. - pub fn new(config: &Config) -> Self { - Self { - payload_and_bid: None, - fallback_builder: FallbackPayloadBuilder::new(config), - secret_key: config.builder_private_key.clone(), - chain: config.chain.clone(), - } - } - - /// Build a new payload with the given transactions. This method will - /// cache the payload in the local builder instance, and make it available - pub async fn build_new_local_payload( - &mut self, - template: &BlockTemplate, - ) -> Result<(), BuilderError> { - let transactions = template.as_signed_transactions(); - let blobs_bundle = template.as_blobs_bundle(); - let kzg_commitments = blobs_bundle.commitments.clone(); - - // 1. build a fallback payload with the given transactions, on top of - // the current head of the chain - let sealed_block = self.fallback_builder.build_fallback_payload(&transactions).await?; - - // NOTE: we use a big value for the bid to ensure it gets chosen by mev-boost. - // the client has no way to actually verify this, and we don't need to trust - // an external relay as this block is self-built, so the fake bid value is fine. - // - // NOTE: we don't strictly need this. The validator & beacon nodes have options - // to ALWAYS prefer PBS blocks. This is a safety measure that doesn't hurt to keep. - let value = U256::from(1_000_000_000_000_000_000u128); - - let eth_payload = compat::to_consensus_execution_payload(&sealed_block); - let payload_and_blobs = PayloadAndBlobs { execution_payload: eth_payload, blobs_bundle }; - - // 2. create a signed builder bid with the sealed block header we just created - let eth_header = compat::to_execution_payload_header(&sealed_block, transactions); - - // 3. sign the bid with the local builder's BLS key - let signed_bid = self.create_signed_builder_bid(value, eth_header, kzg_commitments)?; - - // 4. prepare a get_payload response for when the beacon node will ask for it - let get_payload_response = GetPayloadResponse::from(payload_and_blobs); - - self.payload_and_bid = - Some(PayloadAndBid { bid: signed_bid, payload: get_payload_response }); - - Ok(()) - } - - /// Get the cached payload and bid from the local builder, consuming the value. - #[inline] - pub fn get_cached_payload(&mut self) -> Option { - self.payload_and_bid.take() - } - - /// transform a sealed header into a signed builder bid using - /// the local builder's BLS key. - fn create_signed_builder_bid( - &self, - value: U256, - header: ExecutionPayloadHeader, - blob_kzg_commitments: Vec, - ) -> Result { - // compat: convert from blst to ethereum consensus types - let pubkey = self.secret_key.sk_to_pk().to_bytes(); - let consensus_pubkey = PublicKey::try_from(pubkey.as_slice()).expect("valid pubkey bytes"); - let blob_kzg_commitments = List::try_from(blob_kzg_commitments).expect("valid list"); - - let message = - BuilderBid { header, blob_kzg_commitments, public_key: consensus_pubkey, value }; - - let signature = sign_builder_message(&self.chain, &self.secret_key, &message)?; - - Ok(SignedBuilderBid { message, signature }) - } -} diff --git a/bolt-sidecar/src/builder/payload_builder.rs b/bolt-sidecar/src/builder/payload_builder.rs deleted file mode 100644 index a904605c3..000000000 --- a/bolt-sidecar/src/builder/payload_builder.rs +++ /dev/null @@ -1,449 +0,0 @@ -use std::fmt; - -use alloy::{ - eips::{calc_excess_blob_gas, calc_next_block_base_fee, eip1559::BaseFeeParams}, - primitives::{Address, Bytes, B256, U256}, - rpc::types::{engine::ExecutionPayload as AlloyExecutionPayload, Block}, -}; -use beacon_api_client::{BlockId, StateId}; -use hex::FromHex; -use regex::Regex; -use reqwest::Url; -use reth_primitives::{ - constants::BEACON_NONCE, proofs, BlockBody, Bloom, Header, SealedBlock, TransactionSigned, - Withdrawals, EMPTY_OMMER_ROOT_HASH, -}; -use reth_rpc_layer::{secret_to_bearer_header, JwtSecret}; -use serde_json::Value; -use tracing::{debug, info, trace, warn}; - -use super::{ - compat::{to_alloy_execution_payload, to_reth_withdrawal}, - BuilderError, -}; -use crate::{BeaconClient, Config, RpcClient}; - -/// Extra-data payload field used for locally built blocks, decoded in UTF-8. -/// -/// Corresponds to the string "Self-built with Bolt". It can be max 32 bytes -const DEFAULT_EXTRA_DATA: [u8; 20] = [ - 0x53, 0x65, 0x6c, 0x66, 0x2d, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x42, 0x6f, 0x6c, 0x74, -]; - -/// The fallback payload builder is responsible for assembling a valid -/// sealed block from a set of transactions. It (ab)uses the engine API -/// to fetch "hints" for missing header values, such as the block hash, -/// gas used, state root, etc. -/// -/// The builder will keep querying the engine API until it has all the -/// necessary values to seal the block. This is a temporary solution -/// until the engine API is able to provide a full sealed block. -/// -/// Find more information about this process & its reasoning here: -/// -pub struct FallbackPayloadBuilder { - extra_data: Bytes, - fee_recipient: Address, - beacon_api_client: BeaconClient, - execution_rpc_client: RpcClient, - engine_hinter: EngineHinter, - slot_time_in_seconds: u64, -} - -impl FallbackPayloadBuilder { - /// Create a new fallback payload builder - pub fn new(config: &Config) -> Self { - let engine_hinter = EngineHinter { - client: reqwest::Client::new(), - jwt_hex: config.jwt_hex.to_string(), - engine_rpc_url: config.engine_api_url.clone(), - }; - - Self { - engine_hinter, - extra_data: DEFAULT_EXTRA_DATA.into(), - fee_recipient: config.fee_recipient, - beacon_api_client: BeaconClient::new(config.beacon_api_url.clone()), - execution_rpc_client: RpcClient::new(config.execution_api_url.clone()), - slot_time_in_seconds: config.chain.slot_time(), - } - } -} - -/// Lightweight context struct to hold the necessary values for -/// building a sealed block. Some of this data is fetched from the -/// beacon chain, while others are calculated locally or from the -/// transactions themselves. -#[derive(Debug, Default)] -struct Context { - extra_data: Bytes, - base_fee: u64, - blob_gas_used: u64, - excess_blob_gas: u64, - prev_randao: B256, - fee_recipient: Address, - transactions_root: B256, - withdrawals_root: B256, - parent_beacon_block_root: B256, - slot_time_in_seconds: u64, -} - -#[derive(Debug, Default)] -struct Hints { - pub gas_used: Option, - pub receipts_root: Option, - pub logs_bloom: Option, - pub state_root: Option, - pub block_hash: Option, -} - -impl FallbackPayloadBuilder { - /// Build a minimal payload to be used as a fallback in case PBS relays fail - /// to provide a valid payload that fulfills the commitments made by Bolt. - pub async fn build_fallback_payload( - &self, - transactions: &[TransactionSigned], - ) -> Result { - // TODO: what if the latest block ends up being reorged out? - let latest_block = self.execution_rpc_client.get_block(None, true).await?; - debug!(num = ?latest_block.header.number, "got latest block"); - - let withdrawals = self - .beacon_api_client - // Slot: Defaults to the slot after the parent state if not specified. - .get_expected_withdrawals(StateId::Head, None) - .await? - .into_iter() - .map(to_reth_withdrawal) - .collect::>(); - - debug!(amount = ?withdrawals.len(), "got withdrawals"); - - // let prev_randao = self - // .beacon_api_client - // .get_randao(StateId::Head, None) - // .await?; - // let prev_randao = B256::from_slice(&prev_randao); - - // NOTE: for some reason, this call fails with an ApiResult deserialization error - // when using the beacon_api_client crate directly, so we use reqwest temporarily. - // this is to be refactored. - let prev_randao = reqwest::Client::new() - .get(self.beacon_api_client.endpoint.join("/eth/v1/beacon/states/head/randao").unwrap()) - .send() - .await - .unwrap() - .json::() - .await - .unwrap(); - let prev_randao = prev_randao.pointer("/data/randao").unwrap().as_str().unwrap(); - let prev_randao = B256::from_hex(prev_randao).unwrap(); - debug!("got prev_randao"); - - let parent_beacon_block_root = - self.beacon_api_client.get_beacon_block_root(BlockId::Head).await?; - debug!(parent = ?parent_beacon_block_root, "got parent_beacon_block_root"); - - let versioned_hashes = transactions - .iter() - .flat_map(|tx| tx.blob_versioned_hashes()) - .flatten() - .collect::>(); - info!(amount = ?versioned_hashes.len(), "got versioned_hashes"); - - let base_fee = calc_next_block_base_fee( - latest_block.header.gas_used, - latest_block.header.gas_limit, - latest_block.header.base_fee_per_gas.unwrap_or_default(), - BaseFeeParams::ethereum(), - ) as u64; - - let excess_blob_gas = calc_excess_blob_gas( - latest_block.header.excess_blob_gas.unwrap_or_default(), - latest_block.header.blob_gas_used.unwrap_or_default(), - ) as u64; - - let blob_gas_used = - transactions.iter().fold(0, |acc, tx| acc + tx.blob_gas_used().unwrap_or_default()); - - let ctx = Context { - base_fee, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - prev_randao, - extra_data: self.extra_data.clone(), - fee_recipient: self.fee_recipient, - transactions_root: proofs::calculate_transaction_root(transactions), - withdrawals_root: proofs::calculate_withdrawals_root(&withdrawals), - slot_time_in_seconds: self.slot_time_in_seconds, - }; - - let body = BlockBody { - ommers: Vec::new(), - transactions: transactions.to_vec(), - withdrawals: Some(Withdrawals::new(withdrawals)), - requests: None, - }; - - let mut hints = Hints::default(); - let max_iterations = 20; - let mut i = 0; - loop { - let header = build_header_with_hints_and_context(&latest_block, &hints, &ctx); - - let sealed_header = header.seal_slow(); - let sealed_block = SealedBlock::new(sealed_header, body.clone()); - - let block_hash = hints.block_hash.unwrap_or(sealed_block.hash()); - - let exec_payload = to_alloy_execution_payload(&sealed_block, block_hash); - - let engine_hint = self - .engine_hinter - .fetch_next_payload_hint(&exec_payload, &versioned_hashes, parent_beacon_block_root) - .await?; - - debug!("engine_hint: {:?}", engine_hint); - - match engine_hint { - EngineApiHint::BlockHash(hash) => { - warn!("Should not receive block hash hint {:?}", hash); - hints.block_hash = Some(hash) - } - - EngineApiHint::GasUsed(gas) => { - hints.gas_used = Some(gas); - hints.block_hash = None; - } - EngineApiHint::StateRoot(hash) => { - hints.state_root = Some(hash); - hints.block_hash = None - } - EngineApiHint::ReceiptsRoot(hash) => { - hints.receipts_root = Some(hash); - hints.block_hash = None - } - EngineApiHint::LogsBloom(bloom) => { - hints.logs_bloom = Some(bloom); - hints.block_hash = None - } - - EngineApiHint::ValidPayload => return Ok(sealed_block), - } - - if i > max_iterations { - return Err(BuilderError::Custom( - "Too many iterations: Failed to fetch all missing header values from geth error messages" - .to_string(), - )); - } - - i += 1; - } - } -} - -/// Engine API hint values that can be fetched from the engine API -/// to complete the sealed block. These hints are used to fill in -/// missing values in the block header. -#[derive(Debug)] -#[allow(clippy::large_enum_variant)] -pub(crate) enum EngineApiHint { - BlockHash(B256), - GasUsed(u64), - StateRoot(B256), - ReceiptsRoot(B256), - LogsBloom(Bloom), - ValidPayload, -} - -/// Engine hinter struct that is responsible for fetching hints from the -/// engine API to complete the sealed block. This struct is used by the -/// fallback payload builder to fetch missing header values. -#[derive(Debug)] -pub(crate) struct EngineHinter { - client: reqwest::Client, - jwt_hex: String, - engine_rpc_url: Url, -} - -impl EngineHinter { - /// Fetch the next payload hint from the engine API to complete the sealed block. - pub async fn fetch_next_payload_hint( - &self, - exec_payload: &AlloyExecutionPayload, - versioned_hashes: &[B256], - parent_beacon_root: B256, - ) -> Result { - let auth_jwt = secret_to_bearer_header(&JwtSecret::from_hex(&self.jwt_hex)?); - - let body = format!( - r#"{{"id":1,"jsonrpc":"2.0","method":"engine_newPayloadV3","params":[{}, {}, "{:?}"]}}"#, - serde_json::to_string(&exec_payload)?, - serde_json::to_string(&versioned_hashes)?, - parent_beacon_root - ); - - let raw_hint = self - .client - .post(self.engine_rpc_url.as_str()) - .header("Content-Type", "application/json") - .header("Authorization", auth_jwt.clone()) - .body(body) - .send() - .await? - .text() - .await?; - - let Some(hint_value) = parse_geth_response(&raw_hint) else { - // If the hint is not found, it means that we likely got a VALID - // payload response or an error message that we can't parse. - if raw_hint.contains("\"status\":\"VALID\"") { - return Ok(EngineApiHint::ValidPayload); - } else { - return Err(BuilderError::InvalidEngineHint(raw_hint)); - } - }; - - trace!("raw hint: {:?}", raw_hint); - - // Match the hint value to the corresponding header field and return it - if raw_hint.contains("blockhash mismatch") { - return Ok(EngineApiHint::BlockHash(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid gas used") { - return Ok(EngineApiHint::GasUsed(hint_value.parse()?)); - } else if raw_hint.contains("invalid merkle root") { - return Ok(EngineApiHint::StateRoot(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid receipt root hash") { - return Ok(EngineApiHint::ReceiptsRoot(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid bloom") { - return Ok(EngineApiHint::LogsBloom(Bloom::from_hex(&hint_value)?)); - }; - - Err(BuilderError::Custom( - "Unexpected: failed to parse any hint from engine response".to_string(), - )) - } -} - -/// Parse the hint value from the engine response. -/// An example error message from the engine API looks like this: -/// ```text -/// {"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"local: blockhash mismatch: got 0x... expected 0x..."}} -/// ``` -/// -/// Geth Reference: -/// - [ValidateState]() -/// - [Blockhash Mismatch]() -pub(crate) fn parse_geth_response(error: &str) -> Option { - // Capture either the "local" or "got" value from the error message - let re = Regex::new(r"(?:local:|got) ([0-9a-zA-Z]+)").expect("valid regex"); - - re.captures(error) - .and_then(|capture| capture.get(1).map(|matched| matched.as_str().to_string())) -} - -/// Build a header with the given hints and context values. -fn build_header_with_hints_and_context( - latest_block: &Block, - hints: &Hints, - context: &Context, -) -> Header { - // Use the available hints, or default to an empty value if not present. - let gas_used = hints.gas_used.unwrap_or_default(); - let receipts_root = hints.receipts_root.unwrap_or_default(); - let logs_bloom = hints.logs_bloom.unwrap_or_default(); - let state_root = hints.state_root.unwrap_or_default(); - - Header { - parent_hash: latest_block.header.hash.unwrap_or_default(), - ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: context.fee_recipient, - state_root, - transactions_root: context.transactions_root, - receipts_root, - withdrawals_root: Some(context.withdrawals_root), - logs_bloom, - difficulty: U256::ZERO, - number: latest_block.header.number.unwrap_or_default() + 1, - gas_limit: latest_block.header.gas_limit as u64, - gas_used, - timestamp: latest_block.header.timestamp + context.slot_time_in_seconds, - mix_hash: context.prev_randao, - nonce: BEACON_NONCE, - base_fee_per_gas: Some(context.base_fee), - blob_gas_used: Some(context.blob_gas_used), - excess_blob_gas: Some(context.excess_blob_gas), - parent_beacon_block_root: Some(context.parent_beacon_block_root), - requests_root: None, - extra_data: context.extra_data.clone(), - } -} - -impl fmt::Debug for FallbackPayloadBuilder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FallbackPayloadBuilder") - .field("extra_data", &self.extra_data) - .field("fee_recipient", &self.fee_recipient) - .field("engine_hinter", &self.engine_hinter) - .field("slot_time_in_seconds", &self.slot_time_in_seconds) - .finish() - } -} - -#[cfg(test)] -mod tests { - use alloy::{ - eips::eip2718::Encodable2718, - network::{EthereumWallet, TransactionBuilder}, - primitives::{hex, Address}, - signers::{k256::ecdsa::SigningKey, local::PrivateKeySigner}, - }; - use reth_primitives::TransactionSigned; - use tracing::warn; - - use crate::{ - builder::payload_builder::FallbackPayloadBuilder, - test_util::{default_test_transaction, get_test_config}, - }; - - #[tokio::test] - async fn test_build_fallback_payload() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let Some(cfg) = get_test_config().await else { - warn!("Skipping test: missing test config"); - return Ok(()); - }; - - let raw_sk = std::env::var("PRIVATE_KEY")?; - - let builder = FallbackPayloadBuilder::new(&cfg); - - let sk = SigningKey::from_slice(hex::decode(raw_sk)?.as_slice())?; - let signer = PrivateKeySigner::from_signing_key(sk.clone()); - let wallet = EthereumWallet::from(signer); - - let addy = Address::from_private_key(&sk); - let tx = default_test_transaction(addy, Some(1)).with_chain_id(1); - let tx_signed = tx.build(&wallet).await?; - let raw_encoded = tx_signed.encoded_2718(); - let tx_signed_reth = TransactionSigned::decode_enveloped(&mut raw_encoded.as_slice())?; - - let block = builder.build_fallback_payload(&[tx_signed_reth]).await?; - assert_eq!(block.body.len(), 1); - - Ok(()) - } - - #[test] - fn test_empty_el_withdrawals_root() { - // Withdrawal root in the execution layer header is MPT. - assert_eq!( - reth_primitives::proofs::calculate_withdrawals_root(&Vec::new()), - reth_primitives::constants::EMPTY_WITHDRAWALS - ); - } -} diff --git a/bolt-sidecar/src/builder/signature.rs b/bolt-sidecar/src/builder/signature.rs deleted file mode 100644 index 107326fa0..000000000 --- a/bolt-sidecar/src/builder/signature.rs +++ /dev/null @@ -1,138 +0,0 @@ -use alloy::rpc::types::beacon::{constants::BLS_DST_SIG, BlsSignature}; -use blst::{ - min_pk::{PublicKey, SecretKey}, - BLST_ERROR, -}; -use ethereum_consensus::{ - crypto::Signature, - deneb::{compute_fork_data_root, Domain, DomainType, Root}, - ssz::prelude::{HashTreeRoot, MerkleizationError}, -}; -use tree_hash::TreeHash; -use tree_hash_derive::TreeHash; - -use crate::ChainConfig; - -/// Sign a SSZ object with a BLS secret key, using the Application Builder domain -/// for signing arbitrary builder-api messages in the out-of-protocol specifications. -/// -/// Fun Note: we use a `blst` secret key to sign a message, and produce an `alloy` signature, -/// which is then converted to an `ethereum-consensus` signature. -pub fn sign_builder_message( - chain: &ChainConfig, - sk: &SecretKey, - msg: &T, -) -> Result { - let domain = chain.builder_domain(); - let object_root = msg.hash_tree_root()?.0; - let signing_root = compute_signing_root(object_root, domain); - - let alloy_signature = sign_message(sk, &signing_root); - let consensus_signature = - Signature::try_from(alloy_signature.as_slice()).expect("valid signature bytes"); - - Ok(consensus_signature) -} - -/// Verify a SSZ object signed with a BLS public key, using the Application Builder domain -/// for signing arbitrary builder-api messages in the out-of-protocol specifications. -pub fn verify_signed_builder_message( - chain: &ChainConfig, - pubkey: &PublicKey, - msg: &T, - signature: &BlsSignature, -) -> Result<(), ethereum_consensus::Error> { - let domain = chain.builder_domain(); - let object_root = msg.hash_tree_root()?.0; - let signing_root = compute_signing_root(object_root, domain); - - verify_signature(pubkey, &signing_root, signature).map_err(|_| { - ethereum_consensus::Error::Bls(ethereum_consensus::crypto::BlsError::InvalidSignature) - }) -} - -/// Verify a BLS signature for a given message and public key. -pub fn verify_signature( - pubkey: &PublicKey, - msg: &[u8], - signature: &BlsSignature, -) -> Result<(), blst::BLST_ERROR> { - let sig = blst::min_pk::Signature::from_bytes(&signature.0).expect("valid signature bytes"); - - let res = sig.verify(true, msg, BLS_DST_SIG, &[], pubkey, true); - if res == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(res) - } -} - -/// Sign arbitrary bytes with a BLS secret key, using the BLS DST signature domain, -/// as defined in the Ethereum 2.0 specification. It stands for "Domain Separation Tag -/// for hash_to_point in Ethereum beacon chain BLS12-381 signatures". -pub fn sign_message(secret_key: &SecretKey, msg: &[u8]) -> BlsSignature { - let signature = secret_key.sign(msg, BLS_DST_SIG, &[]).to_bytes(); - BlsSignature::from_slice(&signature) -} - -/// Helper struct to compute the signing root for a given object -/// root and signing domain as defined in the Ethereum 2.0 specification. -#[derive(Default, Debug, TreeHash)] -struct SigningData { - object_root: [u8; 32], - signing_domain: [u8; 32], -} - -/// Compute the signing root for a given object root and signing domain. -pub fn compute_signing_root(object_root: [u8; 32], signing_domain: [u8; 32]) -> [u8; 32] { - let signing_data = SigningData { object_root, signing_domain }; - signing_data.tree_hash_root().0 -} - -/// Compute the Application Builder domain for signing arbitrary -/// builder-api messages in the out-of-protocol specifications -/// -/// Docs: -#[allow(dead_code)] -pub fn compute_builder_domain( - fork_version: [u8; 4], - genesis_validators_root: Option<[u8; 32]>, -) -> [u8; 32] { - // The builder-specs require the genesis_validators_root to be 0x00 - // for any out-of-protocol message. Here we leave the option to set - // it to a custom value if any devnet violates this rule. - let root = genesis_validators_root.map_or(Root::default(), |root| Root::from_slice(&root)); - - let fork_data_root = compute_fork_data_root(fork_version, root).expect("valid fork data"); - - // Also known as `DOMAIN_APPLICATION_BUILDER` in the specs - let domain_type = DomainType::ApplicationBuilder; - - let mut domain = Domain::default(); - domain[..4].copy_from_slice(&domain_type.as_bytes()); - domain[4..].copy_from_slice(&fork_data_root[..28]); - domain -} - -#[cfg(test)] -mod tests { - use crate::{builder::signature::compute_builder_domain, ChainConfig}; - - #[test] - fn test_compute_builder_domain() { - let mainnet = ChainConfig::mainnet(); - assert_eq!(compute_builder_domain(mainnet.fork_version(), None), mainnet.builder_domain()); - - let holesky = ChainConfig::holesky(); - assert_eq!(compute_builder_domain(holesky.fork_version(), None), holesky.builder_domain()); - - let kurtosis = ChainConfig::kurtosis(0, 0); - assert_eq!( - compute_builder_domain(kurtosis.fork_version(), None), - kurtosis.builder_domain() - ); - - let helder = ChainConfig::helder(); - assert_eq!(compute_builder_domain(helder.fork_version(), None), helder.builder_domain()); - } -} diff --git a/bolt-sidecar/src/builder/template.rs b/bolt-sidecar/src/builder/template.rs deleted file mode 100644 index 4b396081b..000000000 --- a/bolt-sidecar/src/builder/template.rs +++ /dev/null @@ -1,220 +0,0 @@ -//! Package `template` contains the functionality for building local block templates that can -//! be used as a fallback. It's also used to keep any intermediary state that is needed to simulate -//! new commitment requests. - -// Should this be a trait? - -use std::collections::HashMap; - -use alloy::primitives::{Address, U256}; -use ethereum_consensus::{ - crypto::{KzgCommitment, KzgProof}, - deneb::mainnet::{Blob, BlobsBundle}, -}; -use reth_primitives::TransactionSigned; -use tracing::warn; - -use crate::{ - common::max_transaction_cost, - primitives::{ - constraint::Constraint, AccountState, FullTransaction, SignedConstraints, TransactionExt, - }, -}; - -/// A block template that serves as a fallback block, but is also used -/// to keep intermediary state for new commitment requests. -/// -/// # Roles -/// - Fallback block template. -/// - Intermediary state for new commitment requests. -/// - Simulate new commitment requests. -/// - Update state every block, to invalidate old commitments. -/// - Make sure we DO NOT accept invalid commitments in any circumstances. -#[derive(Debug, Default)] -pub struct BlockTemplate { - /// The state diffs per address given the list of commitments. - pub(crate) state_diff: StateDiff, - /// The signed constraints associated to the block - pub signed_constraints_list: Vec, -} - -impl BlockTemplate { - /// Return the state diff of the block template. - pub fn get_diff(&self, address: &Address) -> Option<(u64, U256)> { - self.state_diff.get_diff(address) - } - - /// Returns the cloned list of transactions from the constraints. - #[inline] - pub fn transactions(&self) -> Vec { - self.signed_constraints_list - .iter() - .flat_map(|sc| sc.message.constraints.iter().map(|c| c.transaction.clone())) - .collect() - } - - /// Converts the list of signed constraints into a list of signed transactions. Use this when - /// building a local execution payload. - #[inline] - pub fn as_signed_transactions(&self) -> Vec { - self.signed_constraints_list - .iter() - .flat_map(|sc| { - sc.message - .constraints - .iter() - .map(|c| c.transaction.clone().into_inner().into_transaction()) - }) - .collect() - } - - /// Converts the list of signed constraints into a list of all blobs in all transactions - /// in the constraints. Use this when building a local execution payload. - #[inline] - pub fn as_blobs_bundle(&self) -> BlobsBundle { - let (commitments, proofs, blobs) = - self.signed_constraints_list - .iter() - .flat_map(|sc| sc.message.constraints.iter()) - .filter_map(|c| c.transaction.blob_sidecar()) - .fold( - (Vec::new(), Vec::new(), Vec::new()), - |(mut commitments, mut proofs, mut blobs), bs| { - commitments.extend(bs.commitments.iter().map(|c| { - KzgCommitment::try_from(c.as_slice()).expect("both are 48 bytes") - })); - proofs.extend( - bs.proofs.iter().map(|p| { - KzgProof::try_from(p.as_slice()).expect("both are 48 bytes") - }), - ); - blobs.extend(bs.blobs.iter().map(|b| { - Blob::try_from(b.as_slice()).expect("both are 131_072 bytes") - })); - (commitments, proofs, blobs) - }, - ); - - BlobsBundle { commitments, proofs, blobs } - } - - /// Returns the length of the transactions in the block template. - #[inline] - pub fn transactions_len(&self) -> usize { - self.signed_constraints_list.iter().fold(0, |acc, sc| acc + sc.message.constraints.len()) - } - - /// Returns the committed gas in the block template. - #[inline] - pub fn committed_gas(&self) -> u64 { - self.signed_constraints_list.iter().fold(0, |acc, sc| { - acc + sc.message.constraints.iter().fold(0, |acc, c| acc + c.transaction.gas_limit()) - }) - } - - /// Returns the blob count of the block template. - #[inline] - pub fn blob_count(&self) -> usize { - self.signed_constraints_list.iter().fold(0, |mut acc, sc| { - acc += sc.message.constraints.iter().fold(0, |acc, c| { - acc + c - .transaction - .as_eip4844() - .map(|tx| tx.blob_versioned_hashes.len()) - .unwrap_or(0) - }); - - acc - }) - } - - /// Adds a list of constraints to the block template and updates the state diff. - pub fn add_constraints(&mut self, constraints: SignedConstraints) { - for constraint in constraints.message.constraints.iter() { - let max_cost = max_transaction_cost(&constraint.transaction); - self.state_diff - .diffs - .entry(constraint.sender()) - .and_modify(|(nonce, balance)| { - *nonce += 1; - *balance += max_cost; - }) - .or_insert((1, max_cost)); - } - - self.signed_constraints_list.push(constraints); - } - - /// Remove all signed constraints at the specified index and updates the state diff - fn remove_constraints_at_index(&mut self, index: usize) { - let constraints = self.signed_constraints_list.remove(index); - - for constraint in constraints.message.constraints.iter() { - self.state_diff - .diffs - .entry(constraint.transaction.sender().expect("Recovered sender")) - .and_modify(|(nonce, balance)| { - *nonce = nonce.saturating_sub(1); - *balance -= max_transaction_cost(&constraint.transaction); - }); - } - } - - /// Retain removes any transactions that conflict with the given account state. - pub fn retain(&mut self, address: Address, state: AccountState) { - let mut indexes: Vec = Vec::new(); - - // The preconfirmations made by such address, and the indexes of the signed constraints - // in which they appear - let constraints_with_address: Vec<(usize, Vec<&Constraint>)> = self - .signed_constraints_list - .iter() - .enumerate() - .map(|(idx, c)| (idx, &c.message.constraints)) - .filter(|(_idx, c)| c.iter().any(|c| c.sender() == address)) - .map(|(idx, c)| (idx, c.iter().filter(|c| c.sender() == address).collect())) - .collect(); - - // For every preconfirmation, gather the max total balance cost, - // and find the one with the lowest nonce - let (max_total_cost, min_nonce) = constraints_with_address - .iter() - .flat_map(|c| c.1.clone()) - .fold((U256::ZERO, u64::MAX), |(total_cost, min_nonce), c| { - ( - total_cost + max_transaction_cost(&c.transaction), - min_nonce.min(c.transaction.nonce()), - ) - }); - - if state.balance < max_total_cost || state.transaction_count > min_nonce { - // Remove invalidated constraints due to balance / nonce of chain state - warn!( - %address, - "Removing invalidated constraints for address" - ); - indexes = constraints_with_address.iter().map(|(i, _)| *i).collect(); - } - - for index in indexes.into_iter().rev() { - self.remove_constraints_at_index(index); - } - } -} - -/// StateDiff tracks the intermediate changes to the state according to the block template. -#[derive(Debug, Default)] -pub struct StateDiff { - /// Map of diffs per address. Each diff is a tuple of the nonce and balance diff - /// that should be applied to the current state. - pub(crate) diffs: HashMap, -} - -impl StateDiff { - /// Returns a tuple of the nonce and balance diff for the given address. - /// The nonce diff should be added to the current nonce, the balance diff should be subtracted - /// from the current balance. - pub fn get_diff(&self, address: &Address) -> Option<(u64, U256)> { - self.diffs.get(address).copied() - } -} diff --git a/bolt-sidecar/src/client/commit_boost.rs b/bolt-sidecar/src/client/commit_boost.rs deleted file mode 100644 index 42168b4a9..000000000 --- a/bolt-sidecar/src/client/commit_boost.rs +++ /dev/null @@ -1,132 +0,0 @@ -use std::sync::Arc; - -use alloy::rpc::types::beacon::{BlsPublicKey, BlsSignature}; -use cb_common::pbs::{COMMIT_BOOST_API, PUBKEYS_PATH, SIGN_REQUEST_PATH}; -use cb_crypto::types::SignRequest; -use ethereum_consensus::ssz::prelude::ssz_rs; -use parking_lot::RwLock; -use thiserror::Error; -use tracing::{debug, error, info}; - -use crate::crypto::bls::SignerBLSAsync; - -const SIGN_REQUEST_ID: &str = "bolt"; - -#[derive(Debug, Clone)] -pub struct CommitBoostClient { - base_url: String, - client: reqwest::Client, - pubkeys: Arc>>, -} - -#[derive(Debug, Error)] -pub enum CommitBoostError { - #[error(transparent)] - Reqwest(#[from] reqwest::Error), - #[error(transparent)] - Deserialize(#[from] serde_json::Error), - #[error("failed to compute hash tree root for constraint {0:?}")] - HashTreeRoot(#[from] ssz_rs::MerkleizationError), - #[error("failed to sign constraint: {0}")] - NoSignature(String), -} - -#[allow(unused)] -impl CommitBoostClient { - /// Create a new [CommitBoostClient] instance - pub async fn new(base_url: impl Into) -> Result { - let client = Self { - base_url: base_url.into(), - client: reqwest::Client::new(), - pubkeys: Arc::new(RwLock::new(Vec::new())), - }; - - let mut this = client.clone(); - tokio::spawn(async move { - this.load_pubkeys().await.expect("failed to load pubkeys"); - }); - - Ok(client) - } - - /// Load public keys from the remote commit-boost client and store them locally - async fn load_pubkeys(&mut self) -> Result<(), CommitBoostError> { - loop { - let url = self.url_from_path(PUBKEYS_PATH); - - info!(url, "Loading public keys from commit-boost"); - - let response = match self.client.get(url).send().await { - Ok(res) => res, - Err(e) => { - error!(err = ?e, "failed to get public keys from commit-boost, retrying..."); - tokio::time::sleep(std::time::Duration::from_secs(5)).await; - continue; - } - }; - - let status = response.status(); - let response_bytes = response.bytes().await?; - - if !status.is_success() { - let err = String::from_utf8_lossy(&response_bytes).into_owned(); - error!(err, ?status, "failed to get public keys, retrying..."); - tokio::time::sleep(std::time::Duration::from_secs(5)).await; - continue; - } - - let pubkeys: Vec = serde_json::from_slice(&response_bytes)?; - - { - let mut pk = self.pubkeys.write(); - *pk = pubkeys; - return Ok(()); - } // drop write lock - } - } - - #[inline] - fn url_from_path(&self, path: &str) -> String { - format!("{}{COMMIT_BOOST_API}{path}", self.base_url) - } -} - -#[async_trait::async_trait] -impl SignerBLSAsync for CommitBoostClient { - async fn sign(&self, data: &[u8]) -> eyre::Result { - let root = if data.len() == 32 { - let mut root = [0u8; 32]; - root.copy_from_slice(data); - Ok(root) - } else { - Err(CommitBoostError::NoSignature(format!( - "invalid data length. Expected 32 bytes, found {} bytes", - data.len() - ))) - }?; - - let request = SignRequest::builder( - SIGN_REQUEST_ID, - *self.pubkeys.read().first().expect("pubkeys loaded"), - ) - .with_root(root); - - let url = self.url_from_path(SIGN_REQUEST_PATH); - - debug!(url, ?request, "Requesting signature from commit_boost"); - - let response = reqwest::Client::new().post(url).json(&request).send().await?; - - let status = response.status(); - let response_bytes = response.bytes().await?; - - if !status.is_success() { - let err = String::from_utf8_lossy(&response_bytes).into_owned(); - error!(err, "failed to get signature"); - return Err(eyre::eyre!(CommitBoostError::NoSignature(err))); - } - - let sig = serde_json::from_slice(&response_bytes)?; - Ok(sig) - } -} diff --git a/bolt-sidecar/src/client/mevboost.rs b/bolt-sidecar/src/client/mevboost.rs deleted file mode 100644 index ae7ce070e..000000000 --- a/bolt-sidecar/src/client/mevboost.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! Module for interacting with the MEV-Boost API via its Builder API interface. -//! The Bolt sidecar's main purpose is to sit between the beacon node and MEV-Boost, -//! so most requests are simply proxied to its API. - -use axum::http::StatusCode; -use beacon_api_client::VersionedValue; -use ethereum_consensus::{ - builder::SignedValidatorRegistration, deneb::mainnet::SignedBlindedBeaconBlock, Fork, -}; -use reqwest::Url; -use tracing::error; - -use crate::{ - api::{ - builder::GetHeaderParams, - spec::{ - BuilderApi, BuilderApiError, ConstraintsApi, ErrorResponse, CONSTRAINTS_PATH, - GET_PAYLOAD_PATH, REGISTER_VALIDATORS_PATH, STATUS_PATH, - }, - }, - primitives::{BatchedSignedConstraints, GetPayloadResponse, SignedBuilderBid}, -}; - -/// A client for interacting with the MEV-Boost API. -#[derive(Debug, Clone)] -pub struct MevBoostClient { - url: Url, - client: reqwest::Client, -} - -impl MevBoostClient { - /// Creates a new MEV-Boost client with the given URL. - pub fn new>(url: U) -> Self { - Self { - url: url.into(), - client: reqwest::ClientBuilder::new().user_agent("bolt-sidecar").build().unwrap(), - } - } - - fn endpoint(&self, path: &str) -> Url { - self.url.join(path).unwrap_or_else(|e| { - error!(err = ?e, "Failed to join path: {} with url: {}", path, self.url); - self.url.clone() - }) - } -} - -#[async_trait::async_trait] -impl BuilderApi for MevBoostClient { - /// Implements: - async fn status(&self) -> Result { - Ok(self - .client - .get(self.endpoint(STATUS_PATH)) - .header("content-type", "application/json") - .send() - .await? - .status()) - } - - /// Implements: - async fn register_validators( - &self, - registrations: Vec, - ) -> Result<(), BuilderApiError> { - let response = self - .client - .post(self.endpoint(REGISTER_VALIDATORS_PATH)) - .header("content-type", "application/json") - .body(serde_json::to_vec(®istrations)?) - .send() - .await?; - - if response.status() != StatusCode::OK { - let error = response.json::().await?; - return Err(BuilderApiError::FailedRegisteringValidators(error)); - } - - Ok(()) - } - - /// Implements: - async fn get_header( - &self, - params: GetHeaderParams, - ) -> Result { - let parent_hash = format!("0x{}", hex::encode(params.parent_hash.as_ref())); - let public_key = format!("0x{}", hex::encode(params.public_key.as_ref())); - - let response = self - .client - .get(self.endpoint(&format!( - "/eth/v1/builder/header/{}/{}/{}", - params.slot, parent_hash, public_key - ))) - .header("content-type", "application/json") - .send() - .await?; - - if response.status() != StatusCode::OK { - let error = response.json::().await?; - return Err(BuilderApiError::FailedGettingHeader(error)); - } - - let header = response.json::().await?; - - Ok(header) - } - - /// Implements: - async fn get_payload( - &self, - signed_block: SignedBlindedBeaconBlock, - ) -> Result { - let response = self - .client - .post(self.endpoint(GET_PAYLOAD_PATH)) - .header("content-type", "application/json") - .body(serde_json::to_vec(&signed_block)?) - .send() - .await?; - - if response.status() != StatusCode::OK { - let error = response.json::().await?; - return Err(BuilderApiError::FailedGettingPayload(error)); - } - - let payload = response.json().await?; - - Ok(payload) - } -} - -#[async_trait::async_trait] -impl ConstraintsApi for MevBoostClient { - async fn submit_constraints( - &self, - constraints: &BatchedSignedConstraints, - ) -> Result<(), BuilderApiError> { - let response = self - .client - .post(self.endpoint(CONSTRAINTS_PATH)) - .header("content-type", "application/json") - .body(serde_json::to_vec(&constraints)?) - .send() - .await?; - - if response.status() != StatusCode::OK { - let error = response.json::().await?; - return Err(BuilderApiError::FailedSubmittingConstraints(error)); - } - - Ok(()) - } - - async fn get_header_with_proofs( - &self, - params: GetHeaderParams, - ) -> Result, BuilderApiError> { - let parent_hash = format!("0x{}", hex::encode(params.parent_hash.as_ref())); - let public_key = format!("0x{}", hex::encode(params.public_key.as_ref())); - - let response = self - .client - .get(self.endpoint(&format!( - "/eth/v1/builder/header_with_proofs/{}/{}/{}", - params.slot, parent_hash, public_key, - ))) - .header("content-type", "application/json") - .send() - .await?; - - if response.status() != StatusCode::OK { - let error = response.json::().await?; - return Err(BuilderApiError::FailedGettingHeader(error)); - } - - let header = response.json::>().await?; - - if !matches!(header.version, Fork::Deneb) { - return Err(BuilderApiError::InvalidFork(header.version.to_string())); - }; - - // TODO: verify proofs here? - - Ok(header) - } -} - -#[cfg(test)] -mod tests { - use reqwest::Url; - - use crate::MevBoostClient; - - #[test] - fn test_join_endpoints() { - let client = MevBoostClient::new(Url::parse("http://localhost:8080/").unwrap()); - assert_eq!( - client.endpoint("/eth/v1/builder/header/1/0x123/0x456"), - Url::parse("http://localhost:8080/eth/v1/builder/header/1/0x123/0x456").unwrap() - ); - - assert_eq!( - client.endpoint("eth/v1/builder/validators"), - Url::parse("http://localhost:8080/eth/v1/builder/validators").unwrap() - ); - } -} diff --git a/bolt-sidecar/src/client/mod.rs b/bolt-sidecar/src/client/mod.rs deleted file mode 100644 index 314286660..000000000 --- a/bolt-sidecar/src/client/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub mod commit_boost; -pub mod mevboost; -pub mod pubsub; -pub mod rpc; - -// Re-export the beacon_api_client -pub use beacon_api_client::mainnet::Client as BeaconClient; - -#[cfg(test)] -mod test_util; diff --git a/bolt-sidecar/src/client/pubsub.rs b/bolt-sidecar/src/client/pubsub.rs deleted file mode 100644 index 45d127d2b..000000000 --- a/bolt-sidecar/src/client/pubsub.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::{ - ops::{Deref, DerefMut}, - str::FromStr, -}; - -use alloy::{ - pubsub::PubSubFrontend, - rpc::client::{self as alloyClient, ClientBuilder, WsConnect}, - transports::{RpcError, TransportError}, -}; - -use reqwest::Url; - -/// Wrapper around an [`alloy::RpcClient`] that uses WS as the transport. Supports batching -/// JSON-RPC requests. -pub struct PubsubClient(alloyClient::RpcClient); - -#[allow(unused)] -impl PubsubClient { - /// Create a new `PubsubClient` with the given URL. - pub async fn new(url: &str) -> Result> { - let url = Url::from_str(url).unwrap(); - - let client = ClientBuilder::default().ws(WsConnect::new(url)).await?; - - Ok(Self(client)) - } -} - -impl Deref for PubsubClient { - type Target = alloyClient::RpcClient; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for PubsubClient { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs deleted file mode 100644 index fe0011196..000000000 --- a/bolt-sidecar/src/client/rpc.rs +++ /dev/null @@ -1,250 +0,0 @@ -//! This module contains the `RpcClient` struct, which is a wrapper around the `alloy_rpc_client`. -//! It provides a simple interface to interact with the Execution layer JSON-RPC API. - -use futures::future::join_all; -use std::{ - collections::HashSet, - ops::{Deref, DerefMut}, -}; - -use alloy::{ - eips::BlockNumberOrTag, - primitives::{Address, Bytes, B256, U256, U64}, - rpc::{ - client::{self as alloyClient, ClientBuilder, Waiter}, - types::{ - trace::{ - geth::{GethDebugTracingCallOptions, GethTrace}, - parity::{TraceResults, TraceType}, - }, - Block, EIP1186AccountProofResponse, FeeHistory, TransactionRequest, - }, - }, - transports::{http::Http, TransportErrorKind, TransportResult}, -}; - -use reqwest::{Client, Url}; - -use crate::primitives::AccountState; - -/// An HTTP-based JSON-RPC client that supports batching. -/// Implements all methods that are relevant to Bolt state. -#[derive(Clone, Debug)] -pub struct RpcClient(alloyClient::RpcClient>); - -impl RpcClient { - /// Create a new `RpcClient` with the given URL. - pub fn new>(url: U) -> Self { - let client = ClientBuilder::default().http(url.into()); - - Self(client) - } - - /// Get the chain ID. - pub async fn get_chain_id(&self) -> TransportResult { - let chain_id: String = self.0.request("eth_chainId", ()).await?; - let chain_id = chain_id - .get(2..) - .ok_or(TransportErrorKind::Custom("not hex prefixed result".into()))?; - - let decoded = u64::from_str_radix(chain_id, 16).map_err(|e| { - TransportErrorKind::Custom( - format!("could not decode {} into u64: {}", chain_id, e).into(), - ) - })?; - Ok(decoded) - } - - /// Get the basefee of the latest block. - pub async fn get_basefee(&self, block_number: Option) -> TransportResult { - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - - let fee_history: FeeHistory = - self.0.request("eth_feeHistory", (U64::from(1), tag, &[] as &[f64])).await?; - - Ok(fee_history.latest_block_base_fee().unwrap()) - } - - /// Get the blob basefee of the latest block. - /// - /// Reference: https://github.com/ethereum/execution-apis/blob/main/src/eth/fee_market.yaml - pub async fn get_blob_basefee(&self, block_number: Option) -> TransportResult { - let block_count = U64::from(1); - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - let reward_percentiles: Vec = vec![]; - let fee_history: FeeHistory = - self.0.request("eth_feeHistory", (block_count, tag, &reward_percentiles)).await?; - - Ok(fee_history.latest_block_blob_base_fee().unwrap_or(0)) - } - - /// Get the latest block number - pub async fn get_head(&self) -> TransportResult { - let result: U64 = self.0.request("eth_blockNumber", ()).await?; - - Ok(result.to()) - } - - /// Gets the latest account state for the given address - pub async fn get_account_state( - &self, - address: &Address, - block_number: Option, - ) -> TransportResult { - let mut batch = self.0.new_batch(); - - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - - let balance = - batch.add_call("eth_getBalance", &(address, tag)).expect("Correct parameters"); - - let tx_count = - batch.add_call("eth_getTransactionCount", &(address, tag)).expect("Correct parameters"); - - let code = batch.add_call("eth_getCode", &(address, tag)).expect("Correct parameters"); - - // After the batch is complete, we can get the results. - // Note that requests may error separately! - batch.send().await?; - - let tx_count: U64 = tx_count.await?; - let balance: U256 = balance.await?; - let code: Bytes = code.await?; - - Ok(AccountState { balance, transaction_count: tx_count.to(), has_code: !code.is_empty() }) - } - - /// Get the block with the given number. If `None`, the latest block is returned. - pub async fn get_block(&self, block_number: Option, full: bool) -> TransportResult { - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - - self.0.request("eth_getBlockByNumber", (tag, full)).await - } - - /// Returns the account and storage values of the specified account including the Merkle-proof. - /// If the block number is `None`, the latest block is used. - pub async fn get_proof( - &self, - address: Address, - storage_keys: Vec, - block_number: Option, - ) -> TransportResult { - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - let params = (address, storage_keys, tag); - - self.0.request("eth_getProof", params).await - } - - /// Perform multiple `eth_getProof` calls in a single batch. - pub async fn get_proof_batched( - &self, - opts: Vec<(Address, Vec, BlockNumberOrTag)>, - ) -> TransportResult> { - let mut batch = self.0.new_batch(); - - let mut proofs: Vec> = Vec::new(); - - for params in opts { - proofs.push(batch.add_call("eth_getProof", ¶ms).expect("Correct parameters")); - } - - batch.send().await?; - - // Important: join_all will preserve the order of the proofs - join_all(proofs).await.into_iter().collect::, _>>() - } - - /// Performs multiple call traces on top of the same block. i.e. transaction n will be executed - /// on top of a pending block with all n-1 transactions applied (traced) first. - /// - /// Note: Allows tracing dependent transactions, hence all transactions are traced in sequence - pub async fn trace_call_many( - &self, - calls: Vec<(TransactionRequest, HashSet)>, - block_number: Option, - ) -> TransportResult> { - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - let params = (calls, tag); - - self.0.request("trace_callMany", params).await - } - - /// Performs the `debug_traceCall` JSON-RPC method. - pub async fn debug_trace_call( - &self, - tx: TransactionRequest, - block_number: Option, - opts: Option, - ) -> TransportResult { - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - let params = (tx, tag, opts); - - self.0.request("debug_traceCall", params).await - } - - /// Send a raw transaction to the network. - pub async fn send_raw_transaction(&self, raw: Bytes) -> TransportResult { - self.0.request("eth_sendRawTransaction", [raw]).await - } -} - -impl Deref for RpcClient { - type Target = alloyClient::RpcClient>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for RpcClient { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use alloy::{ - consensus::constants::ETH_TO_WEI, - primitives::{uint, Uint}, - }; - use dotenvy::dotenv; - - use crate::test_util::launch_anvil; - - use super::*; - - #[tokio::test] - async fn test_rpc_client() { - let anvil = launch_anvil(); - let anvil_url = Url::from_str(&anvil.endpoint()).unwrap(); - let client = RpcClient::new(anvil_url); - - let addr = anvil.addresses().first().unwrap(); - - let account_state = client.get_account_state(addr, None).await.unwrap(); - - // Accounts in Anvil start with 10_000 ETH - assert_eq!(account_state.balance, uint!(10_000U256 * Uint::from(ETH_TO_WEI))); - - assert_eq!(account_state.transaction_count, 0); - } - - #[tokio::test] - #[ignore] - async fn test_smart_contract_code() -> eyre::Result<()> { - dotenv().ok(); - let rpc_url = Url::parse(std::env::var("RPC_URL").unwrap().as_str())?; - let rpc_client = RpcClient::new(rpc_url); - - // random deployed smart contract address - let addr = Address::from_str("0xBA12222222228d8Ba445958a75a0704d566BF2C8")?; - let account = rpc_client.get_account_state(&addr, None).await?; - - assert!(account.has_code); - - Ok(()) - } -} diff --git a/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json b/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json deleted file mode 100644 index abf2dbc5c..000000000 --- a/bolt-sidecar/src/client/test_util/deneb_get_payload_response.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "deneb", - "data": { - "execution_payload": { - "parent_hash": "0xaa37d684b11d0fa6ec387322e036d2724d22e1570d8a56f5f33192bc5a6071af", - "fee_recipient": "0x614561D2d143621E126e87831AEF287678B442b8", - "state_root": "0x8be14a13156d04c96a91d44289c26e8947430a80ff70811b9802b71a63ca4587", - "receipts_root": "0x9595d62192ec5d8c9282e38f738641938d55be51fa3987f1d5a4de9f0f2a402e", - "logs_bloom": "0x00200000000000000000020080000000000000000000000000000000004000000000000000202000000000000080200080000000000000004002000040200000000080000000000000040008000008201000000000000000000000000800000000000200000000200000140000000000080400000000000080000010000000000000000000000100000000000000000000002000200010080000004000000000020000000000200000000000001004040000200000000000000000000000000000000002000001000000000000000000020400000800001000000000400000000010000000000000000000000000000000008000000000200000000000000000", - "prev_randao": "0x5c5e6cbe95e5aca976d839b8d22aecc14a9373e2e02dfc719010e54fbd1b0a59", - "block_number": "139277", - "gas_limit": "30000000", - "gas_used": "419268", - "timestamp": "1720775112", - "extra_data": "0x426f6c74204275696c646572", - "base_fee_per_gas": "7", - "block_hash": "0x7cccf27d4db8a513dc49836c1a86cd46cdff7a7fcc9f6fea3d8313624871bbef", - "transactions": [ - "0x02f87f8501a2140cff82b58385012a05f20085012a05f20e8304119094fd5f85f5ff7c61b57e404ad29f33a6fd31200f24872386f26fc1000084579f8d2ac080a05d7fed7571ff64f39cf4e48eaf56379ae5c717269455d30051851e4d41fc660fa03b1dc40f862127a8ef69bafe88336bcd04902d79b8f5711f4dfb265a6eb21d94", - "0x02f9017b8501a2140cff8303dec685012a05f2008512a05f2000830249f094843669e5220036eddbaca89d8c8b5b82268a0fc580b901040cc7326300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000022006292538e66f0000000000000000000000005ba38f2c245618e39f6fa067bf1dec304e73ff3c00000000000000000000000092f0ee29e6e1bf0f7c668317ada78f5774a6cb7f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003fac6482aee49bf58515be2d3fb58378a8497cc9000000000000000000000000c6cc140787b02ae479a10e41169607000c0d44f6c080a00cf74c45dbe9ee1fb923118ec5ce9db8f88cd651196ed3f9d4f8f2a65827e611a04a6bc1d49a7e18b7c92e8f3614cae116b1832ceb311c81d54b2c87de1545f68f", - "0x03f902e58501a2140cff82301985012a05f2008501a13b8600832dc6c094f70f745d5d86ae14d1be5a99954870361166ec6c8477359400b90244ef16e8450000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001670100000000000000000000000000000010001302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004115896cebbb4cf09200bcbe8d104ff241313a6eede040b5f2c3899e9e7afa92a25a549d5bb6b7c211983262a5d3ca8ca57c50693b1fa04559a0e6c5bab9cf8c121b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a0019101fb28118ceccaabca22a47e35b9c3f12eb2dcb25e5c543d5b75e6cd841f01a01930332dabfdb3d1104fca86c86eeb664f68c897e9b44dda2d3ccbd024ec69eea03733b5d0b2505367077f5c2324fbead4e34aa540d5d5b8b7afee7e0c70b01c07", - "0x02f8708501a2140cff82012f800782520894b6c402298fcb88039bbfde70f5ace791f18cfac88707131d70870dc880c080a03aab1b17ecf28f85de43c7733611759b87d25ba885babacb6b4c625d715415eea03fb52cb7744ccb885906e42f6b9cf82e74b47a4b4b4072af2aa52a8dc472236e" - ], - "withdrawals": [ - { - "index": "572698", - "validator_index": "2131", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "3645" - }, - { - "index": "572699", - "validator_index": "2135", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "3645" - }, - { - "index": "572700", - "validator_index": "2139", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "3645" - }, - { - "index": "572701", - "validator_index": "2143", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "3645" - }, - { - "index": "572702", - "validator_index": "2144", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "3645" - }, - { - "index": "572703", - "validator_index": "1612", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572704", - "validator_index": "1621", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572705", - "validator_index": "1623", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572706", - "validator_index": "1626", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572707", - "validator_index": "1955", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572708", - "validator_index": "1959", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572709", - "validator_index": "1961", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572710", - "validator_index": "1966", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572711", - "validator_index": "1979", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572712", - "validator_index": "1994", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - }, - { - "index": "572713", - "validator_index": "1999", - "address": "0xd4bb555d3b0d7ff17c606161b44e372689c14f4b", - "amount": "2430" - } - ], - "blob_gas_used": "131072", - "excess_blob_gas": "0" - }, - "blobs_bundle": { - "commitments": [ - "0xa20c71d1985996098aa63e8b5dc7b7fedb70de31478fe309dad3ac0e9b6d28d82be8e5e543021a0203dc785742e94b2f" - ], - "proofs": [ - "0xa2acaae116dc9dea269577cc750c4de598a387992943b18be092856c90eaa372a360aad98aa1ff88eb76423b544fca35" - ], - "blobs": [ - "0x000000000d789c3a00080000ffff00c100c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - ] - } - } -} diff --git a/bolt-sidecar/src/client/test_util/mod.rs b/bolt-sidecar/src/client/test_util/mod.rs deleted file mode 100644 index 00215de52..000000000 --- a/bolt-sidecar/src/client/test_util/mod.rs +++ /dev/null @@ -1,105 +0,0 @@ -#![allow(unused)] - -use beacon_api_client::VersionedValue; -use ethereum_consensus::{ - builder::SignedValidatorRegistration, - deneb::{ - self, - mainnet::{BlobsBundle, SignedBlindedBeaconBlock}, - }, - types::mainnet::ExecutionPayload, -}; -use reqwest::StatusCode; -use serde_json::Value; -use tokio::sync::watch; - -use crate::{ - api::{builder::GetHeaderParams, spec::BuilderApiError}, - primitives::{BatchedSignedConstraints, GetPayloadResponse, PayloadAndBlobs, SignedBuilderBid}, - BuilderApi, ConstraintsApi, -}; - -/// Create a `GetPayloadResponse` with a default `Deneb` execution payload. -pub fn make_get_payload_response() -> GetPayloadResponse { - let execution_payload = ExecutionPayload::Deneb(deneb::ExecutionPayload::default()); - - let blobs_bundle = BlobsBundle::default(); - - GetPayloadResponse::Deneb(PayloadAndBlobs { execution_payload, blobs_bundle }) -} - -pub struct MockMevBoost { - pub response_rx: watch::Receiver, -} - -impl MockMevBoost { - pub fn new() -> (Self, watch::Sender) { - let (response_tx, response_rx) = watch::channel(Value::Null); - (Self { response_rx }, response_tx) - } -} - -#[async_trait::async_trait] -impl BuilderApi for MockMevBoost { - async fn status(&self) -> Result { - Err(BuilderApiError::Generic("MockMevBoost does not support getting status".to_string())) - } - - async fn register_validators( - &self, - _registrations: Vec, - ) -> Result<(), BuilderApiError> { - Err(BuilderApiError::Generic( - "MockMevBoost does not support registering validators".to_string(), - )) - } - - async fn get_header( - &self, - _params: GetHeaderParams, - ) -> Result { - let response = self.response_rx.borrow().clone(); - let bid = serde_json::from_value(response)?; - Ok(bid) - } - - async fn get_payload( - &self, - _signed_block: SignedBlindedBeaconBlock, - ) -> Result { - let response = self.response_rx.borrow().clone(); - let payload = serde_json::from_value(response)?; - Ok(payload) - } -} - -#[async_trait::async_trait] -impl ConstraintsApi for MockMevBoost { - async fn submit_constraints( - &self, - _constraints: &BatchedSignedConstraints, - ) -> Result<(), BuilderApiError> { - Err(BuilderApiError::Generic( - "MockMevBoost does not support submitting constraints".to_string(), - )) - } - - async fn get_header_with_proofs( - &self, - _params: GetHeaderParams, - ) -> Result, BuilderApiError> { - let response = self.response_rx.borrow().clone(); - let bid = serde_json::from_value(response)?; - Ok(bid) - } -} - -#[test] -fn test_decode_get_payload_response() { - let stringified = - std::fs::read_to_string("./src/client/test_util/deneb_get_payload_response.json") - .expect("failed to read get payload response file"); - - let parsed_response: GetPayloadResponse = - serde_json::from_str(&stringified).expect("failed to parse get payload response"); -} diff --git a/bolt-sidecar/src/common.rs b/bolt-sidecar/src/common.rs deleted file mode 100644 index ee60c0d05..000000000 --- a/bolt-sidecar/src/common.rs +++ /dev/null @@ -1,101 +0,0 @@ -use alloy::primitives::U256; -use reth_primitives::PooledTransactionsElement; - -use crate::{ - primitives::{AccountState, TransactionExt}, - state::ValidationError, -}; - -/// The version of the Bolt sidecar binary. -pub const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); - -/// Calculates the max_basefee `slot_diff` blocks in the future given a current basefee (in gwei). -/// Returns None if an overflow would occur. -/// Cfr. https://github.com/flashbots/ethers-provider-flashbots-bundle/blob/7ddaf2c9d7662bef400151e0bfc89f5b13e72b4c/src/index.ts#L308 -pub fn calculate_max_basefee(current: u128, block_diff: u64) -> Option { - // Define the multiplier and divisor for fixed-point arithmetic - let multiplier: u128 = 1125; // Represents 112.5% - let divisor: u128 = 1000; - let mut max_basefee = current; - - for _ in 0..block_diff { - // Check for potential overflow when multiplying - if max_basefee > u128::MAX / multiplier { - return None; // Overflow would occur - } - - // Perform the multiplication and division (and add 1 to round up) - max_basefee = max_basefee * multiplier / divisor + 1; - } - - Some(max_basefee) -} - -/// Calculates the max transaction cost (gas + value) in wei. -/// -/// - For EIP-1559 transactions: `max_fee_per_gas * gas_limit + tx_value`. -/// - For legacy transactions: `gas_price * gas_limit + tx_value`. -/// - For EIP-4844 blob transactions: `max_fee_per_gas * gas_limit + tx_value + max_blob_fee_per_gas -/// * blob_gas_used`. -pub fn max_transaction_cost(transaction: &PooledTransactionsElement) -> U256 { - let gas_limit = transaction.gas_limit() as u128; - - let mut fee_cap = transaction.max_fee_per_gas(); - fee_cap += transaction.max_priority_fee_per_gas().unwrap_or(0); - - if let Some(eip4844) = transaction.as_eip4844() { - fee_cap += eip4844.max_fee_per_blob_gas + eip4844.blob_gas() as u128; - } - - U256::from(gas_limit * fee_cap) + transaction.value() -} - -/// This function validates a transaction against an account state. It checks 2 things: -/// 1. The nonce of the transaction must be higher than the account's nonce, but not higher than -/// current + 1. -/// 2. The balance of the account must be higher than the transaction's max cost. -pub fn validate_transaction( - account_state: &AccountState, - transaction: &PooledTransactionsElement, -) -> Result<(), ValidationError> { - // Check if the nonce is correct (should be the same as the transaction count) - if transaction.nonce() < account_state.transaction_count { - return Err(ValidationError::NonceTooLow( - account_state.transaction_count, - transaction.nonce(), - )); - } - - if transaction.nonce() > account_state.transaction_count { - return Err(ValidationError::NonceTooHigh( - account_state.transaction_count, - transaction.nonce(), - )); - } - - // Check if the balance is enough - if max_transaction_cost(transaction) > account_state.balance { - return Err(ValidationError::InsufficientBalance); - } - - // Check if the account has code (i.e. is a smart contract) - if account_state.has_code { - return Err(ValidationError::AccountHasCode); - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_calculate_max_basefee() { - let current = 10_000_000_000; // 10 gwei - let slot_diff = 9; // 9 full blocks in the future - - let result = calculate_max_basefee(current, slot_diff); - assert_eq!(result, Some(28865075793)) - } -} diff --git a/bolt-sidecar/src/config/chain.rs b/bolt-sidecar/src/config/chain.rs deleted file mode 100644 index a260a1bdd..000000000 --- a/bolt-sidecar/src/config/chain.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::time::Duration; - -use alloy::primitives::b256; -use clap::{Args, ValueEnum}; - -/// Default commitment deadline duration. -/// -/// The sidecar will stop accepting new commitments for the next block -/// after this deadline has passed. This is to ensure that builders and -/// relays have enough time to build valid payloads. -pub const DEFAULT_COMMITMENT_DEADLINE_IN_MILLIS: u64 = 8_000; - -/// Default slot time duration in seconds. -pub const DEFAULT_SLOT_TIME_IN_SECONDS: u64 = 12; - -/// Builder domain for signing messages on Ethereum Mainnet. -const BUILDER_DOMAIN_MAINNET: [u8; 32] = - b256!("00000001f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a9").0; - -/// Builder domain for signing messages on Holesky. -const BUILDER_DOMAIN_HOLESKY: [u8; 32] = - b256!("000000015b83a23759c560b2d0c64576e1dcfc34ea94c4988f3e0d9f77f05387").0; - -/// Builder domain for signing messages on stock Kurtosis devnets. -const BUILDER_DOMAIN_KURTOSIS: [u8; 32] = - b256!("000000010b41be4cdb34d183dddca5398337626dcdcfaf1720c1202d3b95f84e").0; - -/// Builder domain for signing messages on Helder. -const BUILDER_DOMAIN_HELDER: [u8; 32] = - b256!("0000000194c41af484fff7964969e0bdd922f82dff0f4be87a60d0664cc9d1ff").0; - -/// Configuration for the chain the sidecar is running on. -/// This allows to customize the slot time for custom Kurtosis devnets. -#[derive(Debug, Clone, Args)] -pub struct ChainConfig { - /// Chain on which the sidecar is running - #[clap(long, env = "BOLT_SIDECAR_CHAIN", default_value = "mainnet")] - chain: Chain, - /// The deadline in the slot at which the sidecar will stop accepting - /// new commitments for the next block (parsed as milliseconds). - #[clap( - long, - env = "BOLT_SIDECAR_COMMITMENT_DEADLINE", - default_value_t = DEFAULT_COMMITMENT_DEADLINE_IN_MILLIS - )] - commitment_deadline: u64, - /// The slot time duration in seconds. If provided, - /// it overrides the default for the selected [Chain]. - #[clap( - long, - env = "BOLT_SIDECAR_SLOT_TIME", - default_value_t = DEFAULT_SLOT_TIME_IN_SECONDS - )] - slot_time: u64, -} - -impl Default for ChainConfig { - fn default() -> Self { - Self { - chain: Chain::Mainnet, - commitment_deadline: DEFAULT_COMMITMENT_DEADLINE_IN_MILLIS, - slot_time: DEFAULT_SLOT_TIME_IN_SECONDS, - } - } -} - -/// Supported chains for the sidecar -#[derive(Debug, Clone, ValueEnum)] -#[clap(rename_all = "kebab_case")] -#[allow(missing_docs)] -pub enum Chain { - Mainnet, - Holesky, - Helder, - Kurtosis, -} - -impl ChainConfig { - /// Get the chain ID for the given chain. - pub fn chain_id(&self) -> u64 { - match self.chain { - Chain::Mainnet => 1, - Chain::Holesky => 17000, - Chain::Helder => 7014190335, - Chain::Kurtosis => 3151908, - } - } - - /// Get the chain name for the given chain. - pub fn name(&self) -> &'static str { - match self.chain { - Chain::Mainnet => "mainnet", - Chain::Holesky => "holesky", - Chain::Helder => "helder", - Chain::Kurtosis => "kurtosis", - } - } - - /// Get the slot time for the given chain in seconds. - pub fn slot_time(&self) -> u64 { - self.slot_time - } - - /// Get the domain for signing messages on the given chain. - pub fn builder_domain(&self) -> [u8; 32] { - match self.chain { - Chain::Mainnet => BUILDER_DOMAIN_MAINNET, - Chain::Holesky => BUILDER_DOMAIN_HOLESKY, - Chain::Helder => BUILDER_DOMAIN_HELDER, - Chain::Kurtosis => BUILDER_DOMAIN_KURTOSIS, - } - } - - /// Get the fork version for the given chain. - pub fn fork_version(&self) -> [u8; 4] { - match self.chain { - Chain::Mainnet => [0u8; 4], - Chain::Holesky => [1, 1, 112, 0], - Chain::Helder => [16, 0, 0, 0], - Chain::Kurtosis => [16, 0, 0, 56], - } - } - - /// Get the commitment deadline duration for the given chain. - pub fn commitment_deadline(&self) -> Duration { - Duration::from_millis(self.commitment_deadline) - } -} - -#[cfg(test)] -impl ChainConfig { - pub fn mainnet() -> Self { - Self { chain: Chain::Mainnet, ..Default::default() } - } - - pub fn holesky() -> Self { - Self { chain: Chain::Holesky, ..Default::default() } - } - - pub fn helder() -> Self { - Self { chain: Chain::Helder, ..Default::default() } - } - - pub fn kurtosis(slot_time_in_seconds: u64, commitment_deadline: u64) -> Self { - Self { chain: Chain::Kurtosis, slot_time: slot_time_in_seconds, commitment_deadline } - } -} diff --git a/bolt-sidecar/src/config/mod.rs b/bolt-sidecar/src/config/mod.rs deleted file mode 100644 index 7951aaa14..000000000 --- a/bolt-sidecar/src/config/mod.rs +++ /dev/null @@ -1,234 +0,0 @@ -use std::{fs::read_to_string, path::Path, str::FromStr}; - -use alloy::primitives::Address; -use blst::min_pk::SecretKey; -use clap::Parser; -use eyre::{bail, eyre, Report, Result}; -use reqwest::Url; -use std::num::NonZero; -use tracing::info; - -use crate::crypto::bls::random_bls_secret; - -pub mod validator_indexes; -pub use validator_indexes::ValidatorIndexes; - -pub mod chain; -pub use chain::ChainConfig; - -pub mod signing; -pub use signing::SigningOpts; - -/// Default port for the JSON-RPC server exposed by the sidecar. -pub const DEFAULT_RPC_PORT: u16 = 8000; - -/// Default port for the MEV-Boost proxy server. -pub const DEFAULT_MEV_BOOST_PROXY_PORT: u16 = 18551; - -/// Command-line options for the Bolt sidecar -#[derive(Parser, Debug)] -pub struct Opts { - /// Port to listen on for incoming JSON-RPC requests - #[clap(long, env = "BOLT_SIDECAR_PORT")] - pub(super) port: Option, - /// URL for the beacon client - #[clap(long, env = "BOLT_SIDECAR_BEACON_API_URL")] - pub(super) beacon_api_url: String, - /// URL for the MEV-Boost sidecar client to use - #[clap(long, env = "BOLT_SIDECAR_MEVBOOST_URL")] - pub(super) mevboost_url: String, - /// Execution client API URL - #[clap(long, env = "BOLT_SIDECAR_EXECUTION_API_URL")] - pub(super) execution_api_url: String, - /// Execution client Engine API URL - #[clap(long, env = "BOLT_SIDECAR_ENGINE_API_URL")] - pub(super) engine_api_url: String, - /// MEV-Boost proxy server port to use - #[clap(long, env = "BOLT_SIDECAR_MEVBOOST_PROXY_PORT")] - pub(super) mevboost_proxy_port: u16, - /// Max number of commitments to accept per block - #[clap(long, env = "BOLT_SIDECAR_MAX_COMMITMENTS")] - pub(super) max_commitments: Option>, - /// Max committed gas per slot - #[clap(long, env = "BOLT_SIDECAR_MAX_COMMITTED_GAS")] - pub(super) max_committed_gas: Option>, - /// Validator indexes of connected validators that the sidecar - /// should accept commitments on behalf of. Accepted values: - /// - a comma-separated list of indexes (e.g. "1,2,3,4") - /// - a contiguous range of indexes (e.g. "1..4") - /// - a mix of the above (e.g. "1,2..4,6..8") - #[clap(long, value_parser = ValidatorIndexes::from_str, env = "BOLT_SIDECAR_VALIDATOR_INDEXES")] - pub(super) validator_indexes: ValidatorIndexes, - /// The JWT secret token to authenticate calls to the engine API. - /// - /// It can either be a hex-encoded string or a file path to a file - /// containing the hex-encoded secret. - #[clap(long, env = "BOLT_SIDECAR_JWT_HEX")] - pub(super) jwt_hex: String, - /// The fee recipient address for fallback blocks - #[clap(long, env = "BOLT_SIDECAR_FEE_RECIPIENT")] - pub(super) fee_recipient: Address, - /// Secret BLS key to sign fallback payloads with - /// (If not provided, a random key will be used) - #[clap(long, env = "BOLT_SIDECAR_BUILDER_PRIVATE_KEY")] - pub(super) builder_private_key: Option, - /// Chain config for the chain on which the sidecar is running - #[clap(flatten)] - pub(super) chain: ChainConfig, - /// Commitment signing options. - #[clap(flatten)] - pub(super) signing: SigningOpts, -} - -/// Configuration options for the sidecar. These are parsed from -/// command-line options in the form of [`Opts`]. -#[derive(Debug, Clone)] -pub struct Config { - /// Port to listen on for incoming JSON-RPC requests - pub rpc_port: u16, - /// The MEV-Boost proxy server port to listen on - pub mevboost_proxy_port: u16, - /// URL for the MEV-Boost sidecar client to use - pub mevboost_url: Url, - /// URL for the beacon client API URL - pub beacon_api_url: Url, - /// The execution API url - pub execution_api_url: Url, - /// The engine API url - pub engine_api_url: Url, - /// URL for the commit-boost sidecar - pub commit_boost_url: Option, - /// Private key to use for signing preconfirmation requests - pub private_key: Option, - /// The jwt.hex secret to authenticate calls to the engine API - pub jwt_hex: String, - /// The fee recipient address for fallback blocks - pub fee_recipient: Address, - /// Operating limits for the sidecar - pub limits: Limits, - /// Validator indexes of connected validators that the - /// sidecar should accept commitments on behalf of - pub validator_indexes: ValidatorIndexes, - /// Local bulider private key for signing fallback payloads. - /// If not provided, a random key will be used. - pub builder_private_key: SecretKey, - /// The chain on which the sidecar is running - pub chain: ChainConfig, -} - -impl Default for Config { - fn default() -> Self { - Self { - rpc_port: DEFAULT_RPC_PORT, - mevboost_proxy_port: DEFAULT_MEV_BOOST_PROXY_PORT, - commit_boost_url: None, - mevboost_url: "http://localhost:3030".parse().expect("Valid URL"), - beacon_api_url: "http://localhost:5052".parse().expect("Valid URL"), - execution_api_url: "http://localhost:8545".parse().expect("Valid URL"), - engine_api_url: "http://localhost:8551".parse().expect("Valid URL"), - private_key: Some(random_bls_secret()), - jwt_hex: String::new(), - fee_recipient: Address::ZERO, - builder_private_key: random_bls_secret(), - limits: Limits::default(), - validator_indexes: ValidatorIndexes::default(), - chain: ChainConfig::default(), - } - } -} - -/// Limits for the sidecar. -#[derive(Debug, Clone, Copy)] -pub struct Limits { - /// Maximum number of commitments to accept per block - pub max_commitments_per_slot: NonZero, - pub max_committed_gas_per_slot: NonZero, -} - -impl Default for Limits { - fn default() -> Self { - Self { - max_commitments_per_slot: NonZero::new(128).expect("Valid non-zero"), - max_committed_gas_per_slot: NonZero::new(10_000_000).expect("Valid non-zero"), - } - } -} - -impl Config { - /// Parse the command-line options and return a new [`Config`] instance - pub fn parse_from_cli() -> Result { - let opts = Opts::parse(); - Self::try_from(opts) - } -} - -impl TryFrom for Config { - type Error = Report; - - fn try_from(opts: Opts) -> Result { - let mut config = Config::default(); - - if let Some(port) = opts.port { - config.rpc_port = port; - } - - if let Some(max_commitments) = opts.max_commitments { - config.limits.max_commitments_per_slot = max_commitments; - } - - if let Some(max_committed_gas) = opts.max_committed_gas { - config.limits.max_committed_gas_per_slot = max_committed_gas; - } - - config.commit_boost_url = - opts.signing.commit_boost_url.as_ref().map(|url| Url::parse(url)).transpose()?; - - config.private_key = if let Some(sk) = opts.signing.private_key { - let hex_sk = sk.strip_prefix("0x").unwrap_or(&sk); - let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?) - .map_err(|e| eyre!("Failed decoding BLS signer secret key: {:?}", e))?; - Some(sk) - } else { - None - }; - - if let Some(builder_sk) = opts.builder_private_key { - let hex_sk = builder_sk.strip_prefix("0x").unwrap_or(&builder_sk); - let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?) - .map_err(|e| eyre!("Failed decoding BLS builder secret key: {:?}", e))?; - config.builder_private_key = sk; - } - - config.jwt_hex = if opts.jwt_hex.starts_with("0x") { - opts.jwt_hex.trim_start_matches("0x").to_string() - } else if Path::new(&opts.jwt_hex).exists() { - read_to_string(opts.jwt_hex) - .map_err(|e| eyre!("Failed reading JWT secret file: {:?}", e))? - .trim_start_matches("0x") - .to_string() - } else { - opts.jwt_hex - }; - - // Validate the JWT secret - if config.jwt_hex.len() != 64 { - bail!("Engine JWT secret must be a 32 byte hex string"); - } else { - info!("Engine JWT secret loaded successfully"); - } - - config.mevboost_proxy_port = opts.mevboost_proxy_port; - config.engine_api_url = opts.engine_api_url.parse()?; - config.execution_api_url = opts.execution_api_url.parse()?; - config.beacon_api_url = opts.beacon_api_url.parse()?; - config.mevboost_url = opts.mevboost_url.parse()?; - - config.fee_recipient = opts.fee_recipient; - - config.validator_indexes = opts.validator_indexes; - - config.chain = opts.chain; - - Ok(config) - } -} diff --git a/bolt-sidecar/src/config/signing.rs b/bolt-sidecar/src/config/signing.rs deleted file mode 100644 index 2d5321268..000000000 --- a/bolt-sidecar/src/config/signing.rs +++ /dev/null @@ -1,16 +0,0 @@ -use clap::{ArgGroup, Args}; - -/// Command-line options for signing -#[derive(Debug, Clone, Args)] -#[clap( - group = ArgGroup::new("signing-opts").required(true) - .args(&["private_key", "commit_boost_url"]) -)] -pub struct SigningOpts { - /// Private key to use for signing preconfirmation requests - #[clap(long, env = "BOLT_SIDECAR_PRIVATE_KEY", conflicts_with("commit_boost_url"))] - pub(super) private_key: Option, - /// URL for the commit-boost sidecar - #[clap(long, env = "BOLT_SIDECAR_COMMIT_BOOST_URL", conflicts_with("private_key"))] - pub(super) commit_boost_url: Option, -} diff --git a/bolt-sidecar/src/config/validator_indexes.rs b/bolt-sidecar/src/config/validator_indexes.rs deleted file mode 100644 index 54321f907..000000000 --- a/bolt-sidecar/src/config/validator_indexes.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::str::FromStr; - -#[derive(Debug, Clone, Default)] -pub struct ValidatorIndexes(Vec); - -impl ValidatorIndexes { - pub fn contains(&self, index: u64) -> bool { - self.0.contains(&index) - } -} - -impl FromStr for ValidatorIndexes { - type Err = eyre::Report; - - /// Parse an array of validator indexes. Accepted values: - /// - a single index (e.g. "1") - /// - a comma-separated list of indexes (e.g. "1,2,3,4") - /// - a contiguous range of indexes (e.g. "1..4") - /// - a mix of the above (e.g. "1,2..4,6..8") - /// - /// TODO: add parsing from a directory path, using the format of - /// validator definitions - fn from_str(s: &str) -> Result { - let s = s.trim(); - let mut vec = Vec::new(); - - for comma_separated_part in s.split(',') { - if comma_separated_part.contains("..") { - let mut parts = comma_separated_part.split(".."); - - let start = parts.next().ok_or_else(|| eyre::eyre!("Invalid range"))?; - let start = start.parse::()?; - - let end = parts.next().ok_or_else(|| eyre::eyre!("Invalid range"))?; - let end = end.parse::()?; - - vec.extend(start..=end); - } else { - let index = comma_separated_part.parse::()?; - vec.push(index); - } - } - - Ok(Self(vec)) - } -} - -impl From> for ValidatorIndexes { - fn from(vec: Vec) -> Self { - Self(vec) - } -} - -#[cfg(test)] -mod tests { - #[test] - fn test_parse_validator_indexes() { - use super::ValidatorIndexes; - use std::str::FromStr; - - let indexes = ValidatorIndexes::from_str("1").unwrap(); - assert_eq!(indexes.0, vec![1]); - - let indexes = ValidatorIndexes::from_str("1,2,3,4").unwrap(); - assert_eq!(indexes.0, vec![1, 2, 3, 4]); - - let indexes = ValidatorIndexes::from_str("1..4").unwrap(); - assert_eq!(indexes.0, vec![1, 2, 3, 4]); - - let indexes = ValidatorIndexes::from_str("1..4,6..8").unwrap(); - assert_eq!(indexes.0, vec![1, 2, 3, 4, 6, 7, 8]); - - let indexes = ValidatorIndexes::from_str("1,2..4,6..8").unwrap(); - assert_eq!(indexes.0, vec![1, 2, 3, 4, 6, 7, 8]); - } -} diff --git a/bolt-sidecar/src/crypto/bls.rs b/bolt-sidecar/src/crypto/bls.rs deleted file mode 100644 index d6cfb1f97..000000000 --- a/bolt-sidecar/src/crypto/bls.rs +++ /dev/null @@ -1,134 +0,0 @@ -use alloy::primitives::FixedBytes; -use blst::{min_pk::Signature, BLST_ERROR}; -use rand::RngCore; - -pub use blst::min_pk::{PublicKey as BlsPublicKey, SecretKey as BlsSecretKey}; -pub use ethereum_consensus::deneb::BlsSignature; - -/// The BLS Domain Separator used in Ethereum 2.0. -pub const BLS_DST_PREFIX: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; - -/// A fixed-size byte array for BLS signatures. -pub type BLSSig = FixedBytes<96>; - -/// Trait for any types that can be signed and verified with BLS. -/// This trait is used to abstract over the signing and verification of different types. -pub trait SignableBLS { - /// Create a digest of the object that can be signed. - /// This API doesn't enforce a specific hash or encoding method. - fn digest(&self) -> Vec; - - /// Sign the object with the given key. Returns the signature. - /// - /// Note: The default implementation should be used where possible. - #[allow(dead_code)] - fn sign(&self, key: &BlsSecretKey) -> Signature { - sign_with_prefix(key, &self.digest()) - } - - /// Verify the signature of the object with the given public key. - /// - /// Note: The default implementation should be used where possible. - fn verify(&self, signature: &Signature, pubkey: &BlsPublicKey) -> bool { - signature.verify(false, &self.digest(), BLS_DST_PREFIX, &[], pubkey, true) == - BLST_ERROR::BLST_SUCCESS - } -} - -/// A generic signing trait to generate BLS signatures. -#[allow(dead_code)] -pub trait SignerBLS { - /// Sign the given data and return the signature. - fn sign(&self, data: &[u8]) -> eyre::Result; -} - -/// A generic signing trait to generate BLS signatures asynchronously. -#[async_trait::async_trait] -pub trait SignerBLSAsync: Send + Sync { - /// Sign the given data and return the signature. - async fn sign(&self, data: &[u8]) -> eyre::Result; -} - -/// A BLS signer that can sign any type that implements the `Signable` trait. -#[derive(Debug, Clone)] -pub struct Signer { - key: BlsSecretKey, -} - -impl Signer { - /// Create a new signer with the given BLS secret key. - pub fn new(key: BlsSecretKey) -> Self { - Self { key } - } - - /// Create a signer with a random BLS key. - pub fn random() -> Self { - Self { key: random_bls_secret() } - } - - /// Verify the signature of the object with the given public key. - #[allow(dead_code)] - pub fn verify( - &self, - obj: &T, - signature: &Signature, - pubkey: &BlsPublicKey, - ) -> bool { - obj.verify(signature, pubkey) - } -} - -impl SignerBLS for Signer { - fn sign(&self, data: &[u8]) -> eyre::Result { - let sig = sign_with_prefix(&self.key, data); - Ok(BLSSig::from(sig.to_bytes())) - } -} - -#[async_trait::async_trait] -impl SignerBLSAsync for Signer { - async fn sign(&self, data: &[u8]) -> eyre::Result { - let sig = sign_with_prefix(&self.key, data); - Ok(BLSSig::from(sig.to_bytes())) - } -} - -/// Compatibility between ethereum_consensus and blst -pub fn from_bls_signature_to_consensus_signature(sig_bytes: impl AsRef<[u8]>) -> BlsSignature { - BlsSignature::try_from(sig_bytes.as_ref()).unwrap() -} - -/// Generate a random BLS secret key. -pub fn random_bls_secret() -> BlsSecretKey { - let mut rng = rand::thread_rng(); - let mut ikm = [0u8; 32]; - rng.fill_bytes(&mut ikm); - BlsSecretKey::key_gen(&ikm, &[]).unwrap() -} - -/// Sign the given data with the given BLS secret key. -#[inline] -fn sign_with_prefix(key: &BlsSecretKey, data: &[u8]) -> Signature { - key.sign(data, BLS_DST_PREFIX, &[]) -} - -#[cfg(test)] -mod tests { - use crate::{ - crypto::bls::{SignableBLS, Signer, SignerBLS}, - test_util::{test_bls_secret_key, TestSignableData}, - }; - - #[test] - fn test_bls_signer() { - let key = test_bls_secret_key(); - let pubkey = key.sk_to_pk(); - let signer = Signer::new(key); - - let msg = TestSignableData { data: vec![1, 2, 3, 4] }; - - let signature = SignerBLS::sign(&signer, &msg.digest()).unwrap(); - let sig = blst::min_pk::Signature::from_bytes(signature.as_ref()).unwrap(); - assert!(signer.verify(&msg, &sig, &pubkey)); - } -} diff --git a/bolt-sidecar/src/crypto/ecdsa.rs b/bolt-sidecar/src/crypto/ecdsa.rs deleted file mode 100644 index 85e118e06..000000000 --- a/bolt-sidecar/src/crypto/ecdsa.rs +++ /dev/null @@ -1,73 +0,0 @@ -use secp256k1::{ecdsa::Signature, Message, PublicKey, SecretKey}; - -/// Trait for any types that can be signed and verified with ECDSA. -/// This trait is used to abstract over the signing and verification of different types. -pub trait SignableECDSA { - /// Create a digest of the object that can be signed. - /// This API doesn't enforce a specific hash or encoding method. - fn digest(&self) -> Message; - - /// Sign the object with the given key. Returns the signature. - /// - /// Note: The default implementation should be used where possible. - fn sign(&self, key: &SecretKey) -> Signature { - secp256k1::Secp256k1::new().sign_ecdsa(&self.digest(), key) - } - - /// Verify the signature of the object with the given public key. - /// - /// Note: The default implementation should be used where possible. - fn verify(&self, signature: &Signature, pubkey: &PublicKey) -> bool { - secp256k1::Secp256k1::new().verify_ecdsa(&self.digest(), signature, pubkey).is_ok() - } -} - -/// A signer that can sign any type that implements `Signable{curve}` trait. -#[derive(Clone, Debug)] -pub struct ECDSASigner { - secp256k1_key: SecretKey, -} - -impl ECDSASigner { - /// Create a new signer with the given SECP256K1 secret key. - pub fn new(secp256k1_key: SecretKey) -> Self { - Self { secp256k1_key } - } - - /// Sign the given object with the SECP256K1 key and ECDSA algorithm. - pub fn sign_ecdsa(&self, obj: &T) -> Signature { - obj.sign(&self.secp256k1_key) - } - - /// Verify the given object with the SECP256K1 key and ECDSA algorithm. - #[allow(dead_code)] - pub fn verify_ecdsa( - &self, - obj: &T, - sig: &Signature, - pubkey: &PublicKey, - ) -> bool { - obj.verify(sig, pubkey) - } -} - -#[cfg(test)] -mod tests { - use crate::test_util::TestSignableData; - - use super::ECDSASigner; - use secp256k1::{PublicKey, SecretKey}; - - #[test] - fn test_ecdsa_signer() { - let secp256k1_key = SecretKey::from_slice(&[1; 32]).unwrap(); - let signer = ECDSASigner::new(secp256k1_key); - - let message = TestSignableData { data: vec![1, 2, 3, 4] }; - - let signature = signer.sign_ecdsa(&message); - let pubkey = PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &secp256k1_key); - - assert!(signer.verify_ecdsa(&message, &signature, &pubkey)); - } -} diff --git a/bolt-sidecar/src/crypto/mod.rs b/bolt-sidecar/src/crypto/mod.rs deleted file mode 100644 index 99de2a11f..000000000 --- a/bolt-sidecar/src/crypto/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -/// BLS12_381 signatures and verification functions. -pub mod bls; -pub use bls::{SignableBLS, SignerBLS, SignerBLSAsync}; - -/// ECDSA signatures and verification functions. -pub mod ecdsa; diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs deleted file mode 100644 index 0bdc60411..000000000 --- a/bolt-sidecar/src/driver.rs +++ /dev/null @@ -1,250 +0,0 @@ -use std::time::{Duration, Instant}; - -use alloy::{ - rpc::types::beacon::events::HeadEvent, - signers::{local::PrivateKeySigner, Signer as SignerECDSA}, -}; -use beacon_api_client::mainnet::Client as BeaconClient; -use tokio::sync::mpsc; -use tracing::{debug, error, info, warn}; - -use crate::{ - commitments::{ - server::{CommitmentsApiServer, Event as CommitmentEvent}, - spec::Error as CommitmentError, - }, - crypto::{bls::Signer as BlsSigner, SignableBLS, SignerBLS}, - primitives::{ - CommitmentRequest, ConstraintsMessage, FetchPayloadRequest, LocalPayloadFetcher, - SignedConstraints, - }, - start_builder_proxy_server, - state::{fetcher::StateFetcher, ConsensusState, ExecutionState, HeadTracker, StateClient}, - BuilderProxyConfig, Config, ConstraintsApi, LocalBuilder, MevBoostClient, -}; - -/// The driver for the sidecar, responsible for managing the main event loop. -#[derive(Debug)] -pub struct SidecarDriver { - head_tracker: HeadTracker, - execution: ExecutionState, - consensus: ConsensusState, - constraint_signer: BLS, - commitment_signer: ECDSA, - local_builder: LocalBuilder, - mevboost_client: MevBoostClient, - api_events_rx: mpsc::Receiver, - payload_requests_rx: mpsc::Receiver, -} - -impl SidecarDriver { - /// Create a new sidecar driver with the given [Config] and default components. - pub async fn new(cfg: Config) -> eyre::Result { - // The default state client simply uses the execution API URL to fetch state updates. - let state_client = StateClient::new(cfg.execution_api_url.clone()); - - // Constraints are signed with a BLS private key, for now this is provided - // via CLI argument but this is expected to change soon. - let constraint_signer = BlsSigner::new(cfg.private_key.clone().unwrap()); - - // Commitment responses are signed with a regular Ethereum wallet private key. - // This is now generated randomly because slashing is not yet implemented. - let commitment_signer = PrivateKeySigner::random(); - - Self::from_components(cfg, constraint_signer, commitment_signer, state_client).await - } -} - -impl SidecarDriver { - /// Create a new sidecar driver with the given components - pub async fn from_components( - cfg: Config, - constraint_signer: BLS, - commitment_signer: ECDSA, - fetcher: C, - ) -> eyre::Result { - let mevboost_client = MevBoostClient::new(cfg.mevboost_url.clone()); - let execution = ExecutionState::new(fetcher, cfg.limits).await?; - let local_builder = LocalBuilder::new(&cfg); - - let beacon_client = BeaconClient::new(cfg.beacon_api_url.clone()); - - // start the commitments api server - let api_addr = format!("0.0.0.0:{}", cfg.rpc_port); - let (api_events_tx, api_events_rx) = mpsc::channel(1024); - CommitmentsApiServer::new(api_addr).run(api_events_tx).await; - - let consensus = ConsensusState::new( - beacon_client.clone(), - cfg.validator_indexes.clone(), - cfg.chain.commitment_deadline(), - ); - - // TODO: this can be replaced with ethereum_consensus::clock::from_system_time() - // but using beacon node events is easier to work on a custom devnet for now - // (as we don't need to specify genesis time and slot duration) - let head_tracker = HeadTracker::start(beacon_client); - - let builder_proxy_cfg = BuilderProxyConfig { - mevboost_url: cfg.mevboost_url.clone(), - server_port: cfg.mevboost_proxy_port, - }; - - let (payload_requests_tx, payload_requests_rx) = mpsc::channel(16); - - // start the builder api proxy server - tokio::spawn(async move { - let payload_fetcher = LocalPayloadFetcher::new(payload_requests_tx); - if let Err(err) = start_builder_proxy_server(payload_fetcher, builder_proxy_cfg).await { - error!(?err, "Builder API proxy server failed"); - } - }); - - Ok(SidecarDriver { - head_tracker, - execution, - consensus, - constraint_signer, - commitment_signer, - local_builder, - mevboost_client, - api_events_rx, - payload_requests_rx, - }) - } - - /// Run the main event loop endlessly for the sidecar driver. - /// - /// Any errors encountered are contained to the specific `handler` in which - /// they occurred, and the driver will continue to run as long as possible. - pub async fn run_forever(mut self) -> ! { - loop { - tokio::select! { - Some(api_event) = self.api_events_rx.recv() => { - self.handle_incoming_api_event(api_event).await; - } - Ok(head_event) = self.head_tracker.next_head() => { - self.handle_new_head_event(head_event).await; - } - Some(slot) = self.consensus.commitment_deadline.wait() => { - self.handle_commitment_deadline(slot); - } - Some(payload_request) = self.payload_requests_rx.recv() => { - self.handle_fetch_payload_request(payload_request); - } - } - } - } - - /// Handle an incoming API event, validating the request and responding with a commitment. - async fn handle_incoming_api_event(&mut self, event: CommitmentEvent) { - let CommitmentEvent { mut request, response } = event; - info!("Received new commitment request: {:?}", request); - let start = Instant::now(); - - let validator_index = match self.consensus.validate_request(&request) { - Ok(index) => index, - Err(err) => { - error!(?err, "Consensus: failed to validate request"); - let _ = response.send(Err(CommitmentError::Consensus(err))); - return; - } - }; - - if let Err(err) = self.execution.validate_request(&mut request).await { - error!(?err, "Execution: failed to commit request"); - let _ = response.send(Err(CommitmentError::Validation(err))); - return; - } - - // TODO: match when we have more request types - let CommitmentRequest::Inclusion(inclusion_request) = request.clone(); - let target_slot = inclusion_request.slot; - - info!( - target_slot, - elapsed = ?start.elapsed(), - "Validation against execution state passed" - ); - - // parse the request into constraints and sign them - let slot = inclusion_request.slot; - let message = ConstraintsMessage::build(validator_index, inclusion_request); - let signed_constraints = match self.constraint_signer.sign(&message.digest()) { - Ok(signature) => SignedConstraints { message, signature }, - Err(err) => { - error!(?err, "Failed to sign constraints"); - let _ = response.send(Err(CommitmentError::Internal)); - return; - } - }; - - self.execution.add_constraint(slot, signed_constraints); - - // Create a commitment by signing the request - match request.commit_and_sign(&self.commitment_signer).await { - Ok(commitment) => response.send(Ok(commitment)).ok(), - Err(err) => { - error!(?err, "Failed to sign commitment"); - response.send(Err(CommitmentError::Internal)).ok() - } - }; - } - - /// Handle a new head event, updating the execution and consensus state. - async fn handle_new_head_event(&mut self, head_event: HeadEvent) { - let slot = head_event.slot; - info!(slot, "Received new head event"); - - // We use None to signal that we want to fetch the latest EL head - if let Err(e) = self.execution.update_head(None, slot).await { - error!(err = ?e, "Failed to update execution state head"); - } - - if let Err(e) = self.consensus.update_head(slot).await { - error!(err = ?e, "Failed to update consensus state head"); - } - } - - /// Handle a commitment deadline event, submitting constraints to the MEV-Boost service. - fn handle_commitment_deadline(&mut self, slot: u64) { - debug!(slot, "Commitment deadline reached, building local block"); - - let Some(template) = self.execution.get_block_template(slot) else { - warn!("No block template found for slot {slot} when requested"); - return; - }; - - // TODO: fix retry logic, and move this to separate task in the mevboost client itself - let constraints = template.signed_constraints_list.clone(); - let mevboost = self.mevboost_client.clone(); - tokio::spawn(async move { - let max_retries = 5; - let mut i = 0; - while let Err(e) = mevboost.submit_constraints(&constraints).await { - error!(err = ?e, "Error submitting constraints to mev-boost, retrying..."); - tokio::time::sleep(Duration::from_millis(100)).await; - i += 1; - if i >= max_retries { - error!("Max retries reached while submitting to MEV-Boost"); - break; - } - } - }); - } - - /// Handle a fetch payload request, responding with the local payload if available. - fn handle_fetch_payload_request(&mut self, request: FetchPayloadRequest) { - info!(slot = request.slot, "Received local payload request"); - - let Some(payload_and_bid) = self.local_builder.get_cached_payload() else { - warn!(slot = request.slot, "No local payload found"); - let _ = request.response_tx.send(None); - return; - }; - - if let Err(e) = request.response_tx.send(Some(payload_and_bid)) { - error!(err = ?e, "Failed to send payload and bid in response channel"); - } - } -} diff --git a/bolt-sidecar/src/lib.rs b/bolt-sidecar/src/lib.rs deleted file mode 100644 index ec8209087..000000000 --- a/bolt-sidecar/src/lib.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![doc = include_str!("../README.md")] -#![warn(missing_debug_implementations, missing_docs, rustdoc::all)] -#![deny(unused_must_use, rust_2018_idioms)] -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] - -/// All APIs in use by the sidecar. -mod api; -pub use api::{ - builder::{start_builder_proxy_server, BuilderProxyConfig}, - commitments, - spec::{BuilderApi, ConstraintsApi}, -}; - -mod client; -pub use client::{mevboost::MevBoostClient, rpc::RpcClient, BeaconClient}; - -/// Common types and compatibility utilities -/// (To be refactored) -mod common; - -/// Driver for the sidecar, which manages the main event loop -pub mod driver; -pub use driver::SidecarDriver; - -/// Functionality for building local block templates that can -/// be used as a fallback for proposers. It's also used to keep -/// any intermediary state that is needed to simulate EVM execution -pub mod builder; -pub use builder::LocalBuilder; - -/// Configuration and command-line argument parsing -mod config; -pub use config::{ChainConfig, Config, Opts}; - -/// Crypto utilities, including BLS and ECDSA -pub mod crypto; - -/// Primitive types and utilities -pub mod primitives; - -/// State management and fetching for EVM simulation -pub mod state; - -/// Utilities for testing -#[cfg(test)] -mod test_util; diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs deleted file mode 100644 index 7e03211a8..000000000 --- a/bolt-sidecar/src/primitives/commitment.rs +++ /dev/null @@ -1,284 +0,0 @@ -use serde::{de, Deserialize, Deserializer, Serialize}; -use std::str::FromStr; - -use alloy::{ - primitives::{keccak256, Address, Signature, B256}, - signers::{Error, Signer}, -}; - -use super::{FullTransaction, SignatureError, TransactionExt}; - -/// Commitment requests sent by users or RPC proxies to the sidecar. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(untagged)] -pub enum CommitmentRequest { - /// Request of inclusion of a transaction at a specific slot. - Inclusion(InclusionRequest), -} - -/// A signed commitment with a generic signature. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(untagged)] -pub enum SignedCommitment { - Inclusion(InclusionCommitment), -} - -/// A signed inclusion commitment with a generic signature. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct InclusionCommitment { - #[serde(flatten)] - request: InclusionRequest, - #[serde(deserialize_with = "deserialize_sig", serialize_with = "serialize_sig")] - signature: Signature, -} - -impl From for InclusionCommitment { - fn from(commitment: SignedCommitment) -> Self { - match commitment { - SignedCommitment::Inclusion(inclusion) => inclusion, - } - } -} - -impl CommitmentRequest { - /// Returns a reference to the inner request if this is an inclusion request, otherwise `None`. - pub fn as_inclusion_request(&self) -> Option<&InclusionRequest> { - match self { - CommitmentRequest::Inclusion(req) => Some(req), - // TODO: remove this when we have more request types - #[allow(unreachable_patterns)] - _ => None, - } - } - - /// Commits and signs the request with the provided signer. Returns a [SignedCommitment]. - pub async fn commit_and_sign(self, signer: &S) -> Result { - match self { - CommitmentRequest::Inclusion(req) => { - let digest = req.digest(); - let signature = signer.sign_hash(&digest).await?; - Ok(SignedCommitment::Inclusion(InclusionCommitment { request: req, signature })) - } - } - } - - /// Returns the signature (if signed). - pub fn signature(&self) -> Option<&Signature> { - match self { - CommitmentRequest::Inclusion(req) => req.signature.as_ref(), - } - } -} - -/// Request to include a transaction at a specific slot. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct InclusionRequest { - /// The consensus slot number at which the transaction should be included. - pub slot: u64, - /// The transaction to be included. - pub txs: Vec, - /// The signature over the "slot" and "tx" fields by the user. - /// A valid signature is the only proof that the user actually requested - /// this specific commitment to be included at the given slot. - #[serde(skip)] - pub signature: Option, - #[serde(skip)] - pub signer: Option

, -} - -impl InclusionRequest { - /// Validates the transaction fees against a minimum basefee. - /// Returns true if the fee is greater than or equal to the min, false otherwise. - pub fn validate_basefee(&self, min: u128) -> bool { - for tx in &self.txs { - if tx.max_fee_per_gas() < min { - return false; - } - } - - true - } - - /// Validates the transaction chain id against the provided chain id. - /// Returns true if the chain id matches, false otherwise. Will always return true - /// for pre-EIP155 transactions. - pub fn validate_chain_id(&self, chain_id: u64) -> bool { - for tx in &self.txs { - // Check if pre-EIP155 transaction - if let Some(id) = tx.chain_id() { - if id != chain_id { - return false; - } - } - } - - true - } - - /// Validates the tx size limit. - pub fn validate_tx_size_limit(&self, limit: usize) -> bool { - for tx in &self.txs { - if tx.size() > limit { - return false; - } - } - - true - } - - /// Validates the init code limit. - pub fn validate_init_code_limit(&self, limit: usize) -> bool { - for tx in &self.txs { - if tx.tx_kind().is_create() && tx.input().len() > limit { - return false; - } - } - - true - } - - pub fn validate_priority_fee(&self) -> bool { - for tx in &self.txs { - if tx - .max_priority_fee_per_gas() - .is_some_and(|max_priority_fee| max_priority_fee > tx.max_fee_per_gas()) - { - return false; - } - } - - true - } - - /// Returns the total gas limit of all transactions in this request. - pub fn gas_limit(&self) -> u64 { - self.txs.iter().map(|tx| tx.gas_limit()).sum() - } - - /// Returns the transaction signer. - pub fn signer(&self) -> Option
{ - self.signer - } - - /// Sets the signature. - pub fn set_signature(&mut self, signature: Signature) { - self.signature = Some(signature); - } - - /// Sets the signer. - pub fn set_signer(&mut self, signer: Address) { - self.signer = Some(signer); - } - - pub fn recover_signers(&mut self) -> Result<(), SignatureError> { - for tx in &mut self.txs { - let signer = tx.recover_signer().ok_or(SignatureError)?; - tx.sender = Some(signer); - } - - Ok(()) - } -} - -fn deserialize_sig<'de, D, T>(deserializer: D) -> Result -where - D: Deserializer<'de>, - T: FromStr, - T::Err: std::fmt::Display, -{ - let s = String::deserialize(deserializer)?; - T::from_str(s.trim_start_matches("0x")).map_err(de::Error::custom) -} - -fn serialize_sig(sig: &Signature, serializer: S) -> Result { - let parity = sig.v(); - // As bytes encodes the parity as 27/28, need to change that. - let mut bytes = sig.as_bytes(); - bytes[bytes.len() - 1] = if parity.y_parity() { 1 } else { 0 }; - serializer.serialize_str(&format!("0x{}", hex::encode(bytes))) -} - -impl InclusionRequest { - /// Returns the digest of the request. - /// digest = keccak256(bytes(tx_hash1) | bytes(tx_hash2) | ... | le_bytes(target_slot)) - pub fn digest(&self) -> B256 { - let mut data = Vec::new(); - // First field is the concatenation of all the transaction hashes - data.extend_from_slice( - &self.txs.iter().map(|tx| tx.hash().as_slice()).collect::>().concat(), - ); - - // Second field is the little endian encoding of the target slot - data.extend_from_slice(&self.slot.to_le_bytes()); - - keccak256(&data) - } -} - -impl From for CommitmentRequest { - fn from(req: InclusionRequest) -> Self { - CommitmentRequest::Inclusion(req) - } -} - -pub trait ECDSASignatureExt { - /// Returns the ECDSA signature as bytes with the correct parity bit. - fn as_bytes_with_parity(&self) -> [u8; 65]; - /// Rethrns the ECDSA signature as a 0x-prefixed hex string with the correct parity bit. - fn to_hex(&self) -> String; -} - -impl ECDSASignatureExt for Signature { - fn as_bytes_with_parity(&self) -> [u8; 65] { - let parity = self.v(); - // As bytes encodes the parity as 27/28, need to change that. - let mut bytes = self.as_bytes(); - bytes[bytes.len() - 1] = if parity.y_parity() { 1 } else { 0 }; - - bytes - } - - fn to_hex(&self) -> String { - format!("0x{}", hex::encode(self.as_bytes_with_parity())) - } -} - -#[cfg(test)] -mod tests { - use super::{CommitmentRequest, InclusionRequest}; - - #[test] - fn test_deserialize_inclusion_request() { - let json_req = r#"{ - "slot": 10, - "txs": ["0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4"] - }"#; - - let req: InclusionRequest = serde_json::from_str(json_req).unwrap(); - assert_eq!(req.slot, 10); - - let deser = serde_json::to_string(&req).unwrap(); - - assert_eq!( - deser.parse::().unwrap(), - json_req.parse::().unwrap() - ); - } - - #[test] - fn test_deserialize_commitment_request() { - let json_req = r#"{ - "slot": 10, - "txs": ["0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4"] - }"#; - - let req: CommitmentRequest = serde_json::from_str(json_req).unwrap(); - - #[allow(irrefutable_let_patterns)] - if let CommitmentRequest::Inclusion(req) = req { - assert_eq!(req.slot, 10); - } else { - panic!("Expected Inclusion request"); - } - } -} diff --git a/bolt-sidecar/src/primitives/constraint.rs b/bolt-sidecar/src/primitives/constraint.rs deleted file mode 100644 index 644d83dc8..000000000 --- a/bolt-sidecar/src/primitives/constraint.rs +++ /dev/null @@ -1,111 +0,0 @@ -use alloy::primitives::{keccak256, Address}; -use secp256k1::Message; -use serde::Serialize; - -use crate::crypto::{bls::BLSSig, ecdsa::SignableECDSA, SignableBLS}; - -use super::{FullTransaction, InclusionRequest}; - -/// What the proposer sidecar will need to sign to confirm the inclusion request. -impl SignableECDSA for ConstraintsMessage { - fn digest(&self) -> Message { - let mut data = Vec::new(); - data.extend_from_slice(&self.validator_index.to_le_bytes()); - data.extend_from_slice(&self.slot.to_le_bytes()); - - let mut constraint_bytes = Vec::new(); - for constraint in &self.constraints { - constraint_bytes.extend_from_slice(&constraint.as_bytes()); - } - data.extend_from_slice(&constraint_bytes); - - let hash = keccak256(data).0; - Message::from_digest_slice(&hash).expect("digest") - } -} - -/// The inclusion request transformed into an explicit list of signed constraints -/// that need to be forwarded to the PBS pipeline to inform block production. -pub type BatchedSignedConstraints = Vec; - -/// A container for a list of constraints and the signature of the proposer sidecar. -/// -/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints -#[derive(Serialize, Default, Debug, Clone, PartialEq)] -pub struct SignedConstraints { - /// The constraints that need to be signed. - pub message: ConstraintsMessage, - /// The signature of the proposer sidecar. - pub signature: BLSSig, -} - -/// A message that contains the constraints that need to be signed by the proposer sidecar. -/// -/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints -#[derive(Serialize, Debug, Clone, PartialEq, Default)] -pub struct ConstraintsMessage { - /// The validator index of the proposer sidecar. - pub validator_index: u64, - /// The consensus slot at which the constraints are valid - pub slot: u64, - /// The constraints that need to be signed. - pub constraints: Vec, -} - -impl ConstraintsMessage { - /// Builds a constraints message from an inclusion request and metadata - pub fn build(validator_index: u64, request: InclusionRequest) -> Self { - let constraints = - request.txs.into_iter().map(|tx| Constraint::from_transaction(tx, None)).collect(); - - Self { validator_index, slot: request.slot, constraints } - } -} - -impl SignableBLS for ConstraintsMessage { - fn digest(&self) -> Vec { - let mut data = Vec::new(); - data.extend_from_slice(&self.validator_index.to_le_bytes()); - data.extend_from_slice(&self.slot.to_le_bytes()); - - let mut constraint_bytes = Vec::new(); - for constraint in &self.constraints { - constraint_bytes.extend_from_slice(&constraint.as_bytes()); - } - data.extend_from_slice(&constraint_bytes); - - keccak256(data).0.to_vec() - } -} - -/// A general constraint on block building. -/// -/// Reference: https://chainbound.github.io/bolt-docs/api/builder-api#ethv1builderconstraints -#[derive(Serialize, Debug, Clone, PartialEq)] -pub struct Constraint { - /// The optional index at which the transaction needs to be included in the block - pub index: Option, - /// The transaction to be included in the block, in hex format - #[serde(rename(serialize = "tx"))] - pub(crate) transaction: FullTransaction, -} - -impl Constraint { - /// Builds a constraint from a transaction, with an optional index - pub fn from_transaction(transaction: FullTransaction, index: Option) -> Self { - Self { transaction, index } - } - - /// Converts the constraint to a byte representation useful for signing - /// TODO: remove if we go with SSZ - pub fn as_bytes(&self) -> Vec { - let mut data = Vec::new(); - self.transaction.encode_enveloped(&mut data); - data.extend_from_slice(&self.index.unwrap_or(0).to_le_bytes()); - data - } - - pub fn sender(&self) -> Address { - self.transaction.sender().expect("Recovered sender") - } -} diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs deleted file mode 100644 index 990f3936f..000000000 --- a/bolt-sidecar/src/primitives/mod.rs +++ /dev/null @@ -1,394 +0,0 @@ -// TODO: add docs -#![allow(missing_docs)] - -use std::sync::{atomic::AtomicU64, Arc}; - -use alloy::primitives::{Address, U256}; -use ethereum_consensus::{ - crypto::KzgCommitment, - deneb::{ - self, - mainnet::{BlobsBundle, MAX_BLOB_COMMITMENTS_PER_BLOCK}, - presets::mainnet::ExecutionPayloadHeader, - Hash32, - }, - serde::as_str, - ssz::prelude::*, - types::mainnet::ExecutionPayload, - Fork, -}; -use reth_primitives::{BlobTransactionSidecar, Bytes, PooledTransactionsElement, TxKind, TxType}; -use serde::de; -use tokio::sync::{mpsc, oneshot}; - -pub use ethereum_consensus::crypto::{PublicKey as BlsPublicKey, Signature as BlsSignature}; - -/// Commitment types, received by users wishing to receive preconfirmations. -pub mod commitment; -pub use commitment::{CommitmentRequest, InclusionRequest}; - -/// Constraint types, signed by proposers and sent along the PBS pipeline -/// for validation. -pub mod constraint; -pub use constraint::{BatchedSignedConstraints, ConstraintsMessage, SignedConstraints}; -use tracing::{error, info}; - -/// An alias for a Beacon Chain slot number -pub type Slot = u64; - -/// Minimal account state needed for commitment validation. -#[derive(Debug, Clone, Copy, Default)] -pub struct AccountState { - /// The nonce of the account. This is the number of transactions sent from this account - pub transaction_count: u64, - /// The balance of the account in wei - pub balance: U256, - /// Flag to indicate if the account is a smart contract or an EOA - pub has_code: bool, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct BuilderBid { - pub header: ExecutionPayloadHeader, - pub blob_kzg_commitments: List, - #[serde(with = "as_str")] - pub value: U256, - #[serde(rename = "pubkey")] - pub public_key: BlsPublicKey, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct SignedBuilderBid { - pub message: BuilderBid, - pub signature: BlsSignature, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct SignedBuilderBidWithProofs { - pub bid: SignedBuilderBid, - pub proofs: List, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct ConstraintProof { - #[serde(rename = "txHash")] - tx_hash: Hash32, - #[serde(rename = "merkleProof")] - merkle_proof: MerkleProof, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct MerkleProof { - index: u64, - // TODO: for now, max 1000 - hashes: List, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct MerkleMultiProof { - // We use List here for SSZ, TODO: choose max - transaction_hashes: List, - generalized_indexes: List, - merkle_hashes: List, -} - -#[derive(Debug)] -pub struct FetchPayloadRequest { - pub slot: u64, - pub response_tx: oneshot::Sender>, -} - -#[derive(Debug)] -pub struct PayloadAndBid { - pub bid: SignedBuilderBid, - pub payload: GetPayloadResponse, -} - -#[derive(Debug, Clone)] -pub struct LocalPayloadFetcher { - tx: mpsc::Sender, -} - -impl LocalPayloadFetcher { - pub fn new(tx: mpsc::Sender) -> Self { - Self { tx } - } -} - -#[async_trait::async_trait] -impl PayloadFetcher for LocalPayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option { - let (response_tx, response_rx) = oneshot::channel(); - - let fetch_params = FetchPayloadRequest { response_tx, slot }; - self.tx.send(fetch_params).await.ok()?; - - match response_rx.await { - Ok(res) => res, - Err(e) => { - error!(err = ?e, "Failed to fetch payload"); - None - } - } - } -} - -#[async_trait::async_trait] -pub trait PayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option; -} - -#[derive(Debug)] -pub struct NoopPayloadFetcher; - -#[async_trait::async_trait] -impl PayloadFetcher for NoopPayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option { - info!(slot, "Fetch payload called"); - None - } -} - -/// TODO: implement SSZ -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct PayloadAndBlobs { - pub execution_payload: ExecutionPayload, - pub blobs_bundle: BlobsBundle, -} - -impl Default for PayloadAndBlobs { - fn default() -> Self { - Self { - execution_payload: ExecutionPayload::Deneb(deneb::ExecutionPayload::default()), - blobs_bundle: BlobsBundle::default(), - } - } -} - -#[derive(Debug, serde::Serialize, serde::Deserialize)] -#[serde(tag = "version", content = "data")] -pub enum GetPayloadResponse { - #[serde(rename = "bellatrix")] - Bellatrix(ExecutionPayload), - #[serde(rename = "capella")] - Capella(ExecutionPayload), - #[serde(rename = "deneb")] - Deneb(PayloadAndBlobs), - #[serde(rename = "electra")] - Electra(PayloadAndBlobs), -} - -impl GetPayloadResponse { - pub fn block_hash(&self) -> &Hash32 { - match self { - GetPayloadResponse::Capella(payload) => payload.block_hash(), - GetPayloadResponse::Bellatrix(payload) => payload.block_hash(), - GetPayloadResponse::Deneb(payload) => payload.execution_payload.block_hash(), - GetPayloadResponse::Electra(payload) => payload.execution_payload.block_hash(), - } - } - - pub fn execution_payload(&self) -> &ExecutionPayload { - match self { - GetPayloadResponse::Capella(payload) => payload, - GetPayloadResponse::Bellatrix(payload) => payload, - GetPayloadResponse::Deneb(payload) => &payload.execution_payload, - GetPayloadResponse::Electra(payload) => &payload.execution_payload, - } - } -} - -impl From for GetPayloadResponse { - fn from(payload_and_blobs: PayloadAndBlobs) -> Self { - match payload_and_blobs.execution_payload.version() { - Fork::Phase0 => GetPayloadResponse::Capella(payload_and_blobs.execution_payload), - Fork::Altair => GetPayloadResponse::Capella(payload_and_blobs.execution_payload), - Fork::Capella => GetPayloadResponse::Capella(payload_and_blobs.execution_payload), - Fork::Bellatrix => GetPayloadResponse::Bellatrix(payload_and_blobs.execution_payload), - Fork::Deneb => GetPayloadResponse::Deneb(payload_and_blobs), - Fork::Electra => GetPayloadResponse::Electra(payload_and_blobs), - } - } -} - -/// A struct representing the current chain head. -#[derive(Debug, Clone)] -pub struct ChainHead { - /// The current slot number. - pub slot: Arc, - /// The current block number. - pub block: Arc, -} - -impl ChainHead { - /// Create a new ChainHead instance. - pub fn new(slot: u64, block: u64) -> Self { - Self { slot: Arc::new(AtomicU64::new(slot)), block: Arc::new(AtomicU64::new(block)) } - } - - /// Get the slot number (consensus layer). - pub fn slot(&self) -> u64 { - self.slot.load(std::sync::atomic::Ordering::SeqCst) - } - - /// Get the block number (execution layer). - pub fn block(&self) -> u64 { - self.block.load(std::sync::atomic::Ordering::SeqCst) - } -} - -/// Trait that exposes additional information on transaction types that don't already do it -/// by themselves (e.g. [`PooledTransactionsElement`]). -pub trait TransactionExt { - fn gas_limit(&self) -> u64; - fn value(&self) -> U256; - fn tx_type(&self) -> TxType; - fn tx_kind(&self) -> TxKind; - fn input(&self) -> &Bytes; - fn chain_id(&self) -> Option; - fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar>; - fn size(&self) -> usize; -} - -impl TransactionExt for PooledTransactionsElement { - fn gas_limit(&self) -> u64 { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.gas_limit, - PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.gas_limit, - PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.gas_limit, - PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.gas_limit, - _ => unimplemented!(), - } - } - - fn value(&self) -> U256 { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.value, - PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.value, - PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.value, - PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.value, - _ => unimplemented!(), - } - } - - fn tx_type(&self) -> TxType { - match self { - PooledTransactionsElement::Legacy { .. } => TxType::Legacy, - PooledTransactionsElement::Eip2930 { .. } => TxType::Eip2930, - PooledTransactionsElement::Eip1559 { .. } => TxType::Eip1559, - PooledTransactionsElement::BlobTransaction(_) => TxType::Eip4844, - _ => unimplemented!(), - } - } - - fn tx_kind(&self) -> TxKind { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.to, - PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.to, - PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.to, - PooledTransactionsElement::BlobTransaction(blob_tx) => { - TxKind::Call(blob_tx.transaction.to) - } - _ => unimplemented!(), - } - } - - fn input(&self) -> &Bytes { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => &transaction.input, - PooledTransactionsElement::Eip2930 { transaction, .. } => &transaction.input, - PooledTransactionsElement::Eip1559 { transaction, .. } => &transaction.input, - PooledTransactionsElement::BlobTransaction(blob_tx) => &blob_tx.transaction.input, - _ => unimplemented!(), - } - } - - fn chain_id(&self) -> Option { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.chain_id, - PooledTransactionsElement::Eip2930 { transaction, .. } => Some(transaction.chain_id), - PooledTransactionsElement::Eip1559 { transaction, .. } => Some(transaction.chain_id), - PooledTransactionsElement::BlobTransaction(blob_tx) => { - Some(blob_tx.transaction.chain_id) - } - _ => unimplemented!(), - } - } - - fn blob_sidecar(&self) -> Option<&BlobTransactionSidecar> { - match self { - PooledTransactionsElement::BlobTransaction(blob_tx) => Some(&blob_tx.sidecar), - _ => None, - } - } - - fn size(&self) -> usize { - match self { - PooledTransactionsElement::Legacy { transaction, .. } => transaction.size(), - PooledTransactionsElement::Eip2930 { transaction, .. } => transaction.size(), - PooledTransactionsElement::Eip1559 { transaction, .. } => transaction.size(), - PooledTransactionsElement::BlobTransaction(blob_tx) => blob_tx.transaction.size(), - _ => unimplemented!(), - } - } -} - -/// A wrapper type for a full, complete transaction (i.e. with blob sidecars attached). -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FullTransaction { - tx: PooledTransactionsElement, - sender: Option
, -} - -impl From for FullTransaction { - fn from(tx: PooledTransactionsElement) -> Self { - Self { tx, sender: None } - } -} - -impl std::ops::Deref for FullTransaction { - type Target = PooledTransactionsElement; - - fn deref(&self) -> &Self::Target { - &self.tx - } -} - -impl std::ops::DerefMut for FullTransaction { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.tx - } -} - -impl FullTransaction { - pub fn into_inner(self) -> PooledTransactionsElement { - self.tx - } - - /// Returns the sender of the transaction, if recovered. - pub fn sender(&self) -> Option
{ - self.sender - } -} - -impl serde::Serialize for FullTransaction { - fn serialize(&self, serializer: S) -> Result { - let mut data = Vec::new(); - self.tx.encode_enveloped(&mut data); - serializer.serialize_str(&format!("0x{}", hex::encode(&data))) - } -} - -impl<'de> serde::Deserialize<'de> for FullTransaction { - fn deserialize>(deserializer: D) -> Result { - let s = String::deserialize(deserializer)?; - let data = hex::decode(s.trim_start_matches("0x")).map_err(de::Error::custom)?; - PooledTransactionsElement::decode_enveloped(&mut data.as_slice()) - .map_err(de::Error::custom) - .map(|tx| FullTransaction { tx, sender: None }) - } -} - -#[derive(Debug, thiserror::Error)] -#[error("Invalid signature")] -pub struct SignatureError; diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs deleted file mode 100644 index 7a20625d6..000000000 --- a/bolt-sidecar/src/state/consensus.rs +++ /dev/null @@ -1,210 +0,0 @@ -use std::{ - fmt, - time::{Duration, Instant}, -}; - -use beacon_api_client::{mainnet::Client, BlockId, ProposerDuty}; -use ethereum_consensus::{deneb::BeaconBlockHeader, phase0::mainnet::SLOTS_PER_EPOCH}; - -use super::CommitmentDeadline; -use crate::{ - config::ValidatorIndexes, - primitives::{CommitmentRequest, Slot}, - BeaconClient, -}; - -/// Consensus-related errors -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -#[non_exhaustive] -pub enum ConsensusError { - #[error("Beacon API error: {0}")] - BeaconApiError(#[from] beacon_api_client::Error), - #[error("Invalid slot: {0}")] - InvalidSlot(Slot), - #[error("Inclusion deadline exceeded")] - DeadlineExceeded, - #[error("Validator not found in the slot")] - ValidatorNotFound, -} - -/// Represents an epoch in the beacon chain. -#[derive(Debug, Default)] -#[allow(missing_docs)] -pub struct Epoch { - pub value: u64, - pub start_slot: Slot, - pub proposer_duties: Vec, -} - -/// Represents the consensus state container for the sidecar. -#[allow(missing_debug_implementations)] -pub struct ConsensusState { - beacon_api_client: Client, - header: BeaconBlockHeader, - epoch: Epoch, - validator_indexes: ValidatorIndexes, - // Timestamp of when the latest slot was received - latest_slot_timestamp: Instant, - // The latest slot received - latest_slot: Slot, - /// The deadline (expressed in seconds) in the slot for which to - /// stop accepting commitments. - /// - /// This is used to prevent the sidecar from accepting commitments - /// which won't have time to be included by the PBS pipeline. - // commitment_deadline: u64, - pub commitment_deadline: CommitmentDeadline, - /// The duration of the commitment deadline. - commitment_deadline_duration: Duration, -} - -impl fmt::Debug for ConsensusState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ConsensusState") - .field("header", &self.header) - .field("epoch", &self.epoch) - .field("latest_slot", &self.latest_slot) - .field("latest_slot_timestamp", &self.latest_slot_timestamp) - .field("commitment_deadline", &self.commitment_deadline) - .finish() - } -} - -impl ConsensusState { - /// Create a new `ConsensusState` with the given configuration. - pub fn new( - beacon_api_client: BeaconClient, - validator_indexes: ValidatorIndexes, - commitment_deadline_duration: Duration, - ) -> Self { - ConsensusState { - beacon_api_client, - validator_indexes, - header: BeaconBlockHeader::default(), - epoch: Epoch::default(), - latest_slot: Default::default(), - latest_slot_timestamp: Instant::now(), - commitment_deadline: CommitmentDeadline::new(0, commitment_deadline_duration), - commitment_deadline_duration, - } - } - - /// This function validates the state of the chain against a block. It checks 2 things: - /// 1. The target slot is one of our proposer slots. (TODO) - /// 2. The request hasn't passed the slot deadline. - /// - /// TODO: Integrate with the registry to check if we are registered. - pub fn validate_request(&self, request: &CommitmentRequest) -> Result { - let CommitmentRequest::Inclusion(req) = request; - - // Check if the slot is in the current epoch - if req.slot < self.epoch.start_slot || req.slot >= self.epoch.start_slot + SLOTS_PER_EPOCH { - return Err(ConsensusError::InvalidSlot(req.slot)); - } - - // If the request is for the next slot, check if it's within the commitment deadline - if req.slot == self.latest_slot + 1 && - self.latest_slot_timestamp + self.commitment_deadline_duration < Instant::now() - { - return Err(ConsensusError::DeadlineExceeded); - } - - // Find the validator index for the given slot - let validator_index = self.find_validator_index_for_slot(req.slot)?; - - Ok(validator_index) - } - - /// Update the latest head and fetch the relevant data from the beacon chain. - pub async fn update_head(&mut self, head: u64) -> Result<(), ConsensusError> { - // Reset the commitment deadline to start counting for the next slot. - self.commitment_deadline = - CommitmentDeadline::new(head + 1, self.commitment_deadline_duration); - - let update = self.beacon_api_client.get_beacon_header(BlockId::Slot(head)).await?; - - self.header = update.header.message; - - // Update the timestamp with current time - self.latest_slot_timestamp = Instant::now(); - self.latest_slot = head; - - // Get the current value of slot and epoch - let slot = self.header.slot; - let epoch = slot / SLOTS_PER_EPOCH; - - // If the epoch has changed, update the proposer duties - if epoch != self.epoch.value { - self.epoch.value = epoch; - self.epoch.start_slot = epoch * SLOTS_PER_EPOCH; - - self.fetch_proposer_duties(epoch).await?; - } - - Ok(()) - } - - /// Fetch proposer duties for the given epoch. - async fn fetch_proposer_duties(&mut self, epoch: u64) -> Result<(), ConsensusError> { - let duties = self.beacon_api_client.get_proposer_duties(epoch).await?; - - self.epoch.proposer_duties = duties.1; - Ok(()) - } - - /// Filters the proposer duties and returns the validator index for a given slot - /// if it doesn't exists then returns error. - fn find_validator_index_for_slot(&self, slot: u64) -> Result { - self.epoch - .proposer_duties - .iter() - .find(|&duty| { - duty.slot == slot && self.validator_indexes.contains(duty.validator_index as u64) - }) - .map(|duty| duty.validator_index as u64) - .ok_or(ConsensusError::ValidatorNotFound) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use beacon_api_client::ProposerDuty; - use reqwest::Url; - - #[tokio::test] - async fn test_find_validator_index_for_slot() { - // Sample proposer duties - let proposer_duties = vec![ - ProposerDuty { public_key: Default::default(), slot: 1, validator_index: 100 }, - ProposerDuty { public_key: Default::default(), slot: 2, validator_index: 101 }, - ProposerDuty { public_key: Default::default(), slot: 3, validator_index: 102 }, - ]; - - // Validator indexes that we are interested in - let validator_indexes = ValidatorIndexes::from(vec![100, 102]); - - // Create a ConsensusState with the sample proposer duties and validator indexes - let state = ConsensusState { - beacon_api_client: Client::new(Url::parse("http://localhost").unwrap()), - header: BeaconBlockHeader::default(), - epoch: Epoch { value: 0, start_slot: 0, proposer_duties }, - latest_slot_timestamp: Instant::now(), - commitment_deadline: CommitmentDeadline::new(0, Duration::from_secs(1)), - validator_indexes, - commitment_deadline_duration: Duration::from_secs(1), - latest_slot: 0, - }; - - // Test finding a valid slot - assert_eq!(state.find_validator_index_for_slot(1).unwrap(), 100); - assert_eq!(state.find_validator_index_for_slot(3).unwrap(), 102); - - // Test finding an invalid slot (not in proposer duties) - assert!(matches!( - state.find_validator_index_for_slot(4), - Err(ConsensusError::ValidatorNotFound) - )); - } -} diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs deleted file mode 100644 index 3c3b60b59..000000000 --- a/bolt-sidecar/src/state/execution.rs +++ /dev/null @@ -1,1011 +0,0 @@ -use alloy::{ - eips::eip4844::MAX_BLOBS_PER_BLOCK, - primitives::{Address, U256}, - transports::TransportError, -}; -use reth_primitives::{ - revm_primitives::EnvKzgSettings, BlobTransactionValidationError, PooledTransactionsElement, -}; -use std::{collections::HashMap, ops::Deref}; -use thiserror::Error; -use tracing::{debug, trace}; - -use crate::{ - builder::BlockTemplate, - common::{calculate_max_basefee, max_transaction_cost, validate_transaction}, - config::Limits, - primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, -}; - -use super::fetcher::StateFetcher; - -/// Possible commitment validation errors. -#[derive(Debug, Error)] -pub enum ValidationError { - /// The transaction fee is too low to cover the maximum base fee. - #[error("Transaction fee is too low, need {0} gwei to cover the maximum basefee")] - BaseFeeTooLow(u128), - /// The transaction blob fee is too low to cover the maximum blob base fee. - #[error("Transaction blob fee is too low, need {0} gwei to cover the maximum blob basefee")] - BlobBaseFeeTooLow(u128), - /// The transaction blob is invalid. - #[error(transparent)] - BlobValidation(#[from] BlobTransactionValidationError), - /// The max basefee calculation incurred an overflow error. - #[error("Invalid max basefee calculation: overflow")] - MaxBaseFeeCalcOverflow, - /// The transaction nonce is too low. - #[error("Transaction nonce too low. Expected {0}, got {1}")] - NonceTooLow(u64, u64), - /// The transaction nonce is too high. - #[error("Transaction nonce too high. Expected {0}, got {1}")] - NonceTooHigh(u64, u64), - /// The sender account is a smart contract and has code. - #[error("Account has code")] - AccountHasCode, - /// The gas limit is too high. - #[error("Gas limit too high")] - GasLimitTooHigh, - /// The transaction input size is too high. - #[error("Transaction input size too high")] - TransactionSizeTooHigh, - /// Max priority fee per gas is greater than max fee per gas. - #[error("Max priority fee per gas is greater than max fee per gas")] - MaxPriorityFeePerGasTooHigh, - /// The sender does not have enough balance to pay for the transaction. - #[error("Not enough balance to pay for value + maximum fee")] - InsufficientBalance, - /// There are too many EIP-4844 transactions in the target block. - #[error("Too many EIP-4844 transactions in target block")] - Eip4844Limit, - /// The maximum commitments have been reached for the slot. - #[error("Already requested a preconfirmation for slot {0}. Slot must be >= {0}")] - SlotTooLow(u64), - /// The maximum commitments have been reached for the slot. - #[error("Max commitments reached for slot {0}: {1}")] - MaxCommitmentsReachedForSlot(u64, usize), - /// The maximum committed gas has been reached for the slot. - #[error("Max committed gas reached for slot {0}: {1}")] - MaxCommittedGasReachedForSlot(u64, u64), - /// The signature is invalid. - #[error("Invalid signature")] - Signature(#[from] crate::primitives::SignatureError), - /// Could not recover signature, - #[error("Could not recover signer")] - RecoverSigner, - /// The transaction chain ID does not match the expected chain ID. - #[error("Chain ID mismatch")] - ChainIdMismatch, - /// NOTE: this should not be exposed to the user. - #[error("Internal error: {0}")] - Internal(String), -} - -impl ValidationError { - /// Returns true if the error is internal. - pub fn is_internal(&self) -> bool { - matches!(self, Self::Internal(_)) - } -} - -/// The minimal state of the execution layer at some block number (`head`). -/// This is the state that is needed to simulate commitments. -/// It contains per-address nonces and balances, as well as the minimum basefee. -/// It also contains the block template which can be used to simulate new commitments -/// and as a fallback block in case of faults. -/// -/// # Updating & Invalidation -/// The state can be updated with a new head block number. This will fetch the state -/// update from the client and apply it to the state. It will also invalidate any commitments -/// that conflict with the new state so that we NEVER propose an invalid block. -#[derive(Debug)] -pub struct ExecutionState { - /// The latest block number. - block_number: u64, - /// The latest slot number. - slot: u64, - /// The basefee at the head block. - basefee: u128, - /// The blob basefee at the head block. - blob_basefee: u128, - /// The cached account states. This should never be read directly. - /// These only contain the canonical account states at the head block, - /// not the intermediate states. - account_states: HashMap, - /// The block templates by target SLOT NUMBER. - /// We have multiple block templates because in rare cases we might have multiple - /// proposal duties for a single lookahead. - block_templates: HashMap, - /// The chain ID of the chain (constant). - chain_id: u64, - /// The limits set for the sidecar. - limits: Limits, - /// The KZG settings for validating blobs. - kzg_settings: EnvKzgSettings, - /// The state fetcher client. - client: C, - /// Other values used for validation - validation_params: ValidationParams, -} - -/// Other values used for validation. -#[derive(Debug)] -pub struct ValidationParams { - block_gas_limit: u64, - max_tx_input_bytes: usize, - max_init_code_byte_size: usize, -} - -impl Default for ValidationParams { - fn default() -> Self { - Self { - block_gas_limit: 30_000_000, - max_tx_input_bytes: 4 * 32 * 1024, - max_init_code_byte_size: 2 * 24576, - } - } -} - -impl ExecutionState { - /// Creates a new state with the given client, initializing the - /// basefee and head block number. - pub async fn new(client: C, limits: Limits) -> Result { - let (basefee, blob_basefee, block_number, chain_id) = tokio::try_join!( - client.get_basefee(None), - client.get_blob_basefee(None), - client.get_head(), - client.get_chain_id() - )?; - - Ok(Self { - basefee, - blob_basefee, - block_number, - chain_id, - limits, - client, - slot: 0, - account_states: HashMap::new(), - block_templates: HashMap::new(), - // Load the default KZG settings - kzg_settings: EnvKzgSettings::default(), - // TODO: add a way to configure these values from CLI - validation_params: ValidationParams::default(), - }) - } - - /// Returns the current base fee in gwei - pub fn basefee(&self) -> u128 { - self.basefee - } - - /// Validates the commitment request against state (historical + intermediate). - /// - /// NOTE: This function only simulates against execution state, it does not consider - /// timing or proposer slot targets. - /// - /// If the commitment is invalid because of nonce, basefee or balance errors, it will return an - /// error. If the commitment is valid, its account state - /// will be cached. If this is succesful, any callers can be sure that the commitment is valid - /// and SHOULD sign it and respond to the requester. - /// - /// TODO: should also validate everything in https://github.com/paradigmxyz/reth/blob/9aa44e1a90b262c472b14cd4df53264c649befc2/crates/transaction-pool/src/validate/eth.rs#L153 - pub async fn validate_request( - &mut self, - request: &mut CommitmentRequest, - ) -> Result<(), ValidationError> { - let CommitmentRequest::Inclusion(req) = request; - - let signer = req.signer().expect("Set signer"); - req.recover_signers()?; - - let target_slot = req.slot; - - // Validate the chain ID - if !req.validate_chain_id(self.chain_id) { - return Err(ValidationError::ChainIdMismatch); - } - - // Check if there is room for more commitments - if let Some(template) = self.get_block_template(target_slot) { - if template.transactions_len() >= self.limits.max_commitments_per_slot.get() { - return Err(ValidationError::MaxCommitmentsReachedForSlot( - self.slot, - self.limits.max_commitments_per_slot.get(), - )); - } - } - - // Check if the committed gas exceeds the maximum - let template_committed_gas = - self.get_block_template(target_slot).map(|t| t.committed_gas()).unwrap_or(0); - - if template_committed_gas + req.gas_limit() >= self.limits.max_committed_gas_per_slot.get() - { - return Err(ValidationError::MaxCommittedGasReachedForSlot( - self.slot, - self.limits.max_committed_gas_per_slot.get(), - )); - } - - // Check if the transaction size exceeds the maximum - if !req.validate_tx_size_limit(self.validation_params.max_tx_input_bytes) { - return Err(ValidationError::TransactionSizeTooHigh); - } - - // Check if the transaction is a contract creation and the init code size exceeds the - // maximum - if !req.validate_init_code_limit(self.validation_params.max_init_code_byte_size) { - return Err(ValidationError::TransactionSizeTooHigh); - } - - // Check if the gas limit is higher than the maximum block gas limit - if req.gas_limit() > self.validation_params.block_gas_limit { - return Err(ValidationError::GasLimitTooHigh); - } - - // Ensure max_priority_fee_per_gas is less than max_fee_per_gas - if !req.validate_priority_fee() { - return Err(ValidationError::MaxPriorityFeePerGasTooHigh); - } - - // Check if the max_fee_per_gas would cover the maximum possible basefee. - let slot_diff = target_slot.saturating_sub(self.slot); - - // Calculate the max possible basefee given the slot diff - let max_basefee = calculate_max_basefee(self.basefee, slot_diff) - .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?; - - debug!(%slot_diff, basefee = self.basefee, %max_basefee, "Validating basefee"); - - // Validate the base fee - if !req.validate_basefee(max_basefee) { - return Err(ValidationError::BaseFeeTooLow(max_basefee)); - } - - if target_slot < self.slot { - debug!(%target_slot, %self.slot, "Target slot lower than current slot"); - return Err(ValidationError::SlotTooLow(self.slot)); - } - - // Validate each transaction in the request against the account state, - // keeping track of the nonce and balance diffs, including: - // - any existing state in the account trie - // - any previously committed transactions - // - any previous transaction in the same request - // - // NOTE: it's also possible for a request to contain multiple transactions - // from different senders, in this case each sender will have its own nonce - // and balance diffs that will be applied to the account state. - let mut bundle_nonce_diff_map = HashMap::new(); - let mut bundle_balance_diff_map = HashMap::new(); - for tx in req.txs.iter() { - let sender = tx.sender().expect("Recovered sender"); - - // From previous preconfirmations requests retrieve - // - the nonce difference from the account state. - // - the balance difference from the account state. - // - the highest slot number for which the user has requested a preconfirmation. - // - // If the templates do not exist, or this is the first request for this sender, - // its diffs will be zero. - let (nonce_diff, balance_diff, highest_slot_for_account) = - self.block_templates.iter().fold( - (0, U256::ZERO, 0), - |(nonce_diff_acc, balance_diff_acc, highest_slot), (slot, block_template)| { - let (nonce_diff, balance_diff, slot) = block_template - .get_diff(&sender) - .map(|(nonce, balance)| (nonce, balance, *slot)) - .unwrap_or((0, U256::ZERO, 0)); - - ( - nonce_diff_acc + nonce_diff, - balance_diff_acc.saturating_add(balance_diff), - u64::max(highest_slot, slot), - ) - }, - ); - - if target_slot < highest_slot_for_account { - debug!(%target_slot, %highest_slot_for_account, "There is a request for a higher slot"); - return Err(ValidationError::SlotTooLow(highest_slot_for_account)); - } - - trace!(?signer, nonce_diff, %balance_diff, "Applying diffs to account state"); - - let account_state = match self.account_state(&sender).copied() { - Some(account) => account, - None => { - // Fetch the account state from the client if it does not exist - let account = match self.client.get_account_state(&sender, None).await { - Ok(account) => account, - Err(err) => { - return Err(ValidationError::Internal(format!( - "Error fetching account state: {:?}", - err - ))) - } - }; - - self.account_states.insert(sender, account); - account - } - }; - - debug!(?account_state, ?nonce_diff, ?balance_diff, "Validating transaction"); - - let sender_nonce_diff = bundle_nonce_diff_map.entry(sender).or_insert(0); - let sender_balance_diff = bundle_balance_diff_map.entry(sender).or_insert(U256::ZERO); - - // Apply the diffs to this account according to the info fetched from the templates - // and the current bundle diffs for this sender. - let account_state_with_diffs = AccountState { - transaction_count: account_state - .transaction_count - .saturating_add(nonce_diff) - .saturating_add(*sender_nonce_diff), - - balance: account_state - .balance - .saturating_sub(balance_diff) - .saturating_sub(*sender_balance_diff), - - has_code: account_state.has_code, - }; - - // Validate the transaction against the account state with existing diffs - validate_transaction(&account_state_with_diffs, tx)?; - - // Check EIP-4844-specific limits - if let Some(transaction) = tx.as_eip4844() { - if let Some(template) = self.block_templates.get(&target_slot) { - if template.blob_count() >= MAX_BLOBS_PER_BLOCK { - return Err(ValidationError::Eip4844Limit); - } - } - - let PooledTransactionsElement::BlobTransaction(ref blob_transaction) = tx.deref() - else { - unreachable!("EIP-4844 transaction should be a blob transaction") - }; - - // Calculate max possible increase in blob basefee - let max_blob_basefee = calculate_max_basefee(self.blob_basefee, slot_diff) - .ok_or(ValidationError::MaxBaseFeeCalcOverflow)?; - - debug!(%max_blob_basefee, blob_basefee = blob_transaction.transaction.max_fee_per_blob_gas, "Validating blob basefee"); - if blob_transaction.transaction.max_fee_per_blob_gas < max_blob_basefee { - return Err(ValidationError::BlobBaseFeeTooLow(max_blob_basefee)); - } - - // Validate blob against KZG settings - transaction.validate_blob(&blob_transaction.sidecar, self.kzg_settings.get())?; - } - - // Increase the bundle nonce and balance diffs for this sender for the next iteration - *sender_nonce_diff += 1; - *sender_balance_diff += max_transaction_cost(tx); - } - - Ok(()) - } - - /// Commits the transaction to the target block. Initializes a new block template - /// if one does not exist for said block number. - /// TODO: remove `pub` modifier once `try_commit` is fully implemented. - pub fn add_constraint(&mut self, target_slot: u64, signed_constraints: SignedConstraints) { - if let Some(template) = self.block_templates.get_mut(&target_slot) { - template.add_constraints(signed_constraints); - } else { - let mut template = BlockTemplate::default(); - template.add_constraints(signed_constraints); - self.block_templates.insert(target_slot, template); - } - } - - /// Updates the state corresponding to the provided block number and slot. - /// If the block number is not provided, the state will be updated to - /// the latest head from the EL. - pub async fn update_head( - &mut self, - block_number: Option, - slot: u64, - ) -> Result<(), TransportError> { - self.slot = slot; - - let accounts = self.account_states.keys().collect::>(); - let update = self.client.get_state_update(accounts, block_number).await?; - trace!(%slot, ?update, "Applying execution state update"); - - self.apply_state_update(update); - - // Remove any block templates that are no longer valid - self.remove_block_template(slot); - - Ok(()) - } - - fn apply_state_update(&mut self, update: StateUpdate) { - // Update head and basefee - self.block_number = update.block_number; - self.basefee = update.min_basefee; - - // `extend` will overwrite existing values. This is what we want. - self.account_states.extend(update.account_states); - - self.refresh_templates(); - } - - /// Refreshes the block templates with the latest account states and removes any invalid - /// transactions by checking the nonce and balance of the account after applying the state - /// diffs. - fn refresh_templates(&mut self) { - for (address, account_state) in self.account_states.iter_mut() { - trace!(%address, ?account_state, "Refreshing template..."); - // Iterate over all block templates and apply the state diff - for (_, template) in self.block_templates.iter_mut() { - // Retain only signed constraints where transactions are still valid based on the - // canonical account states. - template.retain(*address, *account_state); - - // Update the account state with the remaining state diff for the next iteration. - if let Some((nonce_diff, balance_diff)) = template.get_diff(address) { - // Nonce will always be increased - account_state.transaction_count += nonce_diff; - // Balance will always be decreased - account_state.balance -= balance_diff; - } - } - } - } - - /// Returns the cached account state for the given address - fn account_state(&self, address: &Address) -> Option<&AccountState> { - self.account_states.get(address) - } - - /// Gets the block template for the given slot number. - pub fn get_block_template(&mut self, slot: u64) -> Option<&BlockTemplate> { - self.block_templates.get(&slot) - } - - /// Gets the block template for the given slot number and removes it from the cache. - /// This should be called when we need to propose a block for the given slot, - /// or when a new head comes in which makes an older block template useless. - pub fn remove_block_template(&mut self, slot: u64) -> Option { - self.block_templates.remove(&slot) - } -} - -#[derive(Debug, Clone)] -pub struct StateUpdate { - pub account_states: HashMap, - pub min_basefee: u128, - pub min_blob_basefee: u128, - pub block_number: u64, -} - -#[cfg(test)] -mod tests { - use crate::builder::template::StateDiff; - use std::{num::NonZero, str::FromStr, time::Duration}; - - use alloy::{ - consensus::constants::ETH_TO_WEI, - eips::eip2718::Encodable2718, - network::EthereumWallet, - primitives::{uint, Uint}, - providers::{network::TransactionBuilder, Provider, ProviderBuilder}, - signers::local::PrivateKeySigner, - }; - use fetcher::{StateClient, StateFetcher}; - - use crate::{ - crypto::{bls::Signer, SignableBLS, SignerBLS}, - primitives::{ConstraintsMessage, SignedConstraints}, - state::fetcher, - test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, - }; - - use super::*; - - #[tokio::test] - async fn test_valid_inclusion_request() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(state.validate_request(&mut request).await.is_ok()); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_slot() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a nonce that is too high - let tx = default_test_transaction(*sender, Some(1)); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - // Insert a constraint diff for slot 11 - let mut diffs = HashMap::new(); - diffs.insert(*sender, (1, U256::ZERO)); - state.block_templates.insert( - 11, - BlockTemplate { state_diff: StateDiff { diffs }, signed_constraints_list: vec![] }, - ); - state.update_head(None, 11).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::SlotTooLow(11)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_nonce() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Insert a constraint diff for slot 9 to simulate nonce increment - let mut diffs = HashMap::new(); - diffs.insert(*sender, (1, U256::ZERO)); - state.block_templates.insert( - 9, - BlockTemplate { state_diff: StateDiff { diffs }, signed_constraints_list: vec![] }, - ); - - // Create a transaction with a nonce that is too low - let tx = default_test_transaction(*sender, Some(0)); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::NonceTooLow(1, 0)) - )); - - assert!(state.account_states.get(sender).unwrap().transaction_count == 0); - - // Create a transaction with a nonce that is too high - let tx = default_test_transaction(*sender, Some(2)); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::NonceTooHigh(1, 2)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_balance() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a value that is too high - let tx = default_test_transaction(*sender, None) - .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::InsufficientBalance) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_balance_multiple() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - let signer = Signer::random(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Set the sender balance to just enough to pay for 1 transaction - let balance = U256::from_str("500000000000000").unwrap(); // leave just 0.0005 ETH - let sender_account = client.get_account_state(sender, None).await.unwrap(); - let balance_to_burn = sender_account.balance - balance; - - // burn the balance - let tx = default_test_transaction(*sender, Some(0)).with_value(uint!(balance_to_burn)); - let request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - let tx_bytes = - request.as_inclusion_request().unwrap().txs.first().unwrap().envelope_encoded(); - let _ = client.inner().send_raw_transaction(tx_bytes).await?; - - // wait for the transaction to be included to update the sender balance - tokio::time::sleep(Duration::from_secs(2)).await; - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // create a new transaction and request a preconfirmation for it - let tx = default_test_transaction(*sender, Some(1)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(state.validate_request(&mut request).await.is_ok()); - - let message = ConstraintsMessage::build(0, request.as_inclusion_request().unwrap().clone()); - let signature = signer.sign(&message.digest())?; - let signed_constraints = SignedConstraints { message, signature }; - state.add_constraint(10, signed_constraints); - - // create a new transaction and request a preconfirmation for it - let tx = default_test_transaction(*sender, Some(2)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - // this should fail because the balance is insufficient as we spent - // all of it on the previous preconfirmation - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::InsufficientBalance) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_basefee() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let basefee = state.basefee(); - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - // Create a transaction with a basefee that is too low - let tx = default_test_transaction(*sender, None) - .with_max_fee_per_gas(basefee - 1) - .with_max_priority_fee_per_gas(basefee / 2); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::BaseFeeTooLow(_)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_inclusion_request_with_excess_gas() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let limits: Limits = Limits { - max_commitments_per_slot: NonZero::new(10).unwrap(), - max_committed_gas_per_slot: NonZero::new(5_000_000).unwrap(), - }; - let mut state = ExecutionState::new(client.clone(), limits).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None).with_gas_limit(6_000_000); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::MaxCommittedGasReachedForSlot(_, 5_000_000)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalidate_inclusion_request() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - let provider = ProviderBuilder::new().on_http(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - // build the signed transaction for submission later - let wallet: PrivateKeySigner = anvil.keys()[0].clone().into(); - let signer: EthereumWallet = wallet.into(); - let signed = tx.clone().build(&signer).await?; - - let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); - - assert!(state.validate_request(&mut request).await.is_ok()); - - let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request); - let signature = bls_signer.sign(&message.digest()).unwrap(); - let signed_constraints = SignedConstraints { message, signature }; - - state.add_constraint(target_slot, signed_constraints); - - assert!(state.get_block_template(target_slot).unwrap().transactions_len() == 1); - - let notif = provider.send_raw_transaction(&signed.encoded_2718()).await?; - - // Wait for confirmation - let receipt = notif.get_receipt().await?; - - // Update the head, which should invalidate the transaction due to a nonce conflict - state.update_head(receipt.block_number, receipt.block_number.unwrap()).await?; - - let transactions_len = state.get_block_template(target_slot).unwrap().transactions_len(); - - assert!(transactions_len == 0); - - Ok(()) - } - - #[tokio::test] - async fn test_invalidate_stale_template() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None); - - let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); - - assert!(state.validate_request(&mut request).await.is_ok()); - - let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request); - let signature = bls_signer.sign(&message.digest()).unwrap(); - let signed_constraints = SignedConstraints { message, signature }; - - state.add_constraint(target_slot, signed_constraints); - - assert!(state.get_block_template(target_slot).unwrap().transactions_len() == 1); - - // fast-forward the head to the target slot, which should invalidate the entire template - // because it's now stale. - state.update_head(None, target_slot).await?; - - assert!(state.get_block_template(target_slot).is_none()); - - Ok(()) - } - - #[tokio::test] - async fn test_invalidate_inclusion_request_with_excess_gas() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let limits: Limits = Limits { - max_commitments_per_slot: NonZero::new(10).unwrap(), - max_committed_gas_per_slot: NonZero::new(5_000_000).unwrap(), - }; - let mut state = ExecutionState::new(client.clone(), limits).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx = default_test_transaction(*sender, None).with_gas_limit(4_999_999); - - let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); - - assert!(state.validate_request(&mut request).await.is_ok()); - - let bls_signer = Signer::random(); - let message = ConstraintsMessage::build(0, inclusion_request); - let signature = bls_signer.sign(&message.digest()).unwrap(); - let signed_constraints = SignedConstraints { message, signature }; - - state.add_constraint(target_slot, signed_constraints); - - assert!(state.get_block_template(target_slot).unwrap().transactions_len() == 1); - - // This tx will exceed the committed gas limit - let tx = default_test_transaction(*sender, Some(1)); - - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::MaxCommittedGasReachedForSlot(_, 5_000_000)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_valid_bundle_inclusion_request() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx1 = default_test_transaction(*sender, Some(0)); - let tx2 = default_test_transaction(*sender, Some(1)); - let tx3 = default_test_transaction(*sender, Some(2)); - - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; - - assert!(state.validate_request(&mut request).await.is_ok()); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_bundle_inclusion_request_nonce() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx1 = default_test_transaction(*sender, Some(0)); - let tx2 = default_test_transaction(*sender, Some(1)); - let tx3 = default_test_transaction(*sender, Some(3)); // wrong nonce, should be 2 - - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::NonceTooHigh(2, 3)) - )); - - Ok(()) - } - - #[tokio::test] - async fn test_invalid_bundle_inclusion_request_balance() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let anvil = launch_anvil(); - let client = StateClient::new(anvil.endpoint_url()); - - let mut state = ExecutionState::new(client.clone(), Limits::default()).await?; - - let sender = anvil.addresses().first().unwrap(); - let sender_pk = anvil.keys().first().unwrap(); - - // initialize the state by updating the head once - let slot = client.get_head().await?; - state.update_head(None, slot).await?; - - let tx1 = default_test_transaction(*sender, Some(0)); - let tx2 = default_test_transaction(*sender, Some(1)); - let tx3 = default_test_transaction(*sender, Some(2)) - .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; - - assert!(matches!( - state.validate_request(&mut request).await, - Err(ValidationError::InsufficientBalance) - )); - - Ok(()) - } -} diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs deleted file mode 100644 index 4576296c0..000000000 --- a/bolt-sidecar/src/state/fetcher.rs +++ /dev/null @@ -1,241 +0,0 @@ -#![allow(missing_docs)] -#![allow(unused_variables)] -#![allow(missing_debug_implementations)] - -use std::{collections::HashMap, time::Duration}; - -use alloy::{ - eips::BlockNumberOrTag, - primitives::{Address, Bytes, U256, U64}, - transports::TransportError, -}; -use futures::{stream::FuturesOrdered, StreamExt}; -use reqwest::Url; -use tracing::error; - -use crate::{client::rpc::RpcClient, primitives::AccountState}; - -use super::execution::StateUpdate; - -/// Maximum retries for RPC requests. -const MAX_RETRIES: u32 = 8; - -/// The retry backoff in milliseconds. -const RETRY_BACKOFF_MS: u64 = 200; - -/// A trait for fetching state updates. -#[async_trait::async_trait] -pub trait StateFetcher { - async fn get_state_update( - &self, - addresses: Vec<&Address>, - head: Option, - ) -> Result; - - async fn get_head(&self) -> Result; - - async fn get_basefee(&self, block_number: Option) -> Result; - - async fn get_blob_basefee(&self, block_number: Option) -> Result; - - async fn get_account_state( - &self, - address: &Address, - block_number: Option, - ) -> Result; - - async fn get_chain_id(&self) -> Result; -} - -/// A basic state fetcher that uses an RPC client to fetch state updates. -#[derive(Clone, Debug)] -pub struct StateClient { - client: RpcClient, - retry_backoff: Duration, -} - -impl StateClient { - /// Create a new `StateClient` with the given URL and maximum retries. - pub fn new>(url: U) -> Self { - Self { client: RpcClient::new(url), retry_backoff: Duration::from_millis(RETRY_BACKOFF_MS) } - } -} - -/// Get state updates for the specified block number or latest block if not provided. -#[async_trait::async_trait] -impl StateFetcher for StateClient { - async fn get_state_update( - &self, - addresses: Vec<&Address>, - block_number: Option, - ) -> Result { - // Create a new batch - let mut batch = self.client.new_batch(); - - let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - - let mut account_states = HashMap::with_capacity(addresses.len()); - - let mut nonce_futs = FuturesOrdered::new(); - let mut balance_futs = FuturesOrdered::new(); - let mut code_futs = FuturesOrdered::new(); - - let block_number = if let Some(block_number) = block_number { - block_number - } else { - self.client.get_head().await? - }; - - // TODO: add block number in params - for addr in &addresses { - // We can use expect here since the only error is related to invalid parameters - let nonce = batch - .add_call("eth_getTransactionCount", &(addr, tag)) - .expect("Invalid parameters"); - let balance = - batch.add_call("eth_getBalance", &(addr, tag)).expect("Invalid parameters"); - let code = batch.add_call("eth_getCode", &(addr, tag)).expect("Invalid parameters"); - - // Push the futures onto ordered list - nonce_futs.push_back(nonce); - balance_futs.push_back(balance); - code_futs.push_back(code); - } - - // Make sure to send the batch! - - // After the batch is complete, we can get the results. - // Note that requests may error separately! - batch.send().await?; - - let basefee = self.client.get_basefee(None); - let blob_basefee = self.client.get_blob_basefee(None); - - // Collect the results - let (nonce_vec, balance_vec, code_vec, basefee, blob_basefee) = tokio::join!( - nonce_futs.collect::>(), - balance_futs.collect::>(), - code_futs.collect::>(), - basefee, - blob_basefee, - ); - - // Insert the results - for (addr, nonce) in addresses.iter().zip(nonce_vec) { - let nonce: U64 = nonce?; - - account_states - .entry(**addr) - .and_modify(|s: &mut AccountState| { - s.transaction_count = nonce.to(); - }) - .or_insert(AccountState { - transaction_count: nonce.to(), - balance: U256::ZERO, - has_code: false, - }); - } - - for (addr, balance) in addresses.iter().zip(balance_vec) { - let balance = balance?; - - account_states - .entry(**addr) - .and_modify(|s: &mut AccountState| { - s.balance = balance; - }) - .or_insert(AccountState { transaction_count: 0, balance, has_code: false }); - } - - for (addr, code) in addresses.iter().zip(code_vec) { - let code: Bytes = code?; - - account_states - .entry(**addr) - .and_modify(|s: &mut AccountState| { - s.has_code = !code.is_empty(); - }) - .or_insert(AccountState { - transaction_count: 0, - balance: U256::ZERO, - has_code: !code.is_empty(), - }); - } - - Ok(StateUpdate { - account_states, - min_basefee: basefee?, - min_blob_basefee: blob_basefee?, - block_number, - }) - } - - async fn get_head(&self) -> Result { - self.client.get_head().await - } - - async fn get_basefee(&self, block_number: Option) -> Result { - self.client.get_basefee(block_number).await - } - - async fn get_blob_basefee(&self, block_number: Option) -> Result { - self.client.get_blob_basefee(block_number).await - } - - async fn get_account_state( - &self, - address: &Address, - block_number: Option, - ) -> Result { - let mut retries = 0; - - loop { - match self.client.get_account_state(address, block_number).await { - Ok(state) => return Ok(state), - Err(e) => { - retries += 1; - if retries >= MAX_RETRIES { - return Err(e); - } - - error!(error = ?e, "Error getting account state, retrying..."); - tokio::time::sleep(self.retry_backoff).await; - } - } - } - } - - async fn get_chain_id(&self) -> Result { - self.client.get_chain_id().await - } -} - -#[cfg(test)] -impl StateClient { - pub fn inner(&self) -> &RpcClient { - &self.client - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_util::launch_anvil; - - #[tokio::test] - async fn test_state_client() { - let anvil = launch_anvil(); - let client = StateClient::new(Url::parse(&anvil.endpoint()).unwrap()); - - let address = anvil.addresses().first().unwrap(); - let state = client.get_account_state(address, None).await.unwrap(); - assert_eq!(state.balance, U256::from(10000000000000000000000u128)); - assert_eq!(state.transaction_count, 0); - - let head = client.get_head().await.unwrap(); - assert_eq!(head, 0); - - let basefee = client.get_basefee(None).await.unwrap(); - assert_eq!(basefee, 1_000_000_000); - } -} diff --git a/bolt-sidecar/src/state/head_tracker.rs b/bolt-sidecar/src/state/head_tracker.rs deleted file mode 100644 index 3ca48ff50..000000000 --- a/bolt-sidecar/src/state/head_tracker.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::time::Duration; - -use alloy::rpc::types::beacon::events::HeadEvent; -use beacon_api_client::Topic; -use futures::StreamExt; -use tokio::{sync::broadcast, task::AbortHandle}; -use tracing::warn; - -use crate::BeaconClient; - -/// Simple actor to keep track of the most recent head of the beacon chain -/// and broadcast updates to its subscribers. -/// -/// Durability: the tracker will always attempt to reconnect to the provided -/// beacon client URL in case of disconnection or other errors. -#[derive(Debug)] -pub struct HeadTracker { - /// Channel to receive updates of the "Head" beacon topic - new_heads_rx: broadcast::Receiver, - /// Handle to the background task that listens for new head events. - /// Kept to allow for graceful shutdown. - quit: AbortHandle, -} - -/// A topic for subscribing to new head events -#[derive(Debug)] -pub struct NewHeadsTopic; - -impl Topic for NewHeadsTopic { - const NAME: &'static str = "head"; - - type Data = HeadEvent; -} - -impl HeadTracker { - /// Create a new `HeadTracker` with the given beacon client HTTP URL and - /// start listening for new head events in the background - pub fn start(beacon_client: BeaconClient) -> Self { - let (new_heads_tx, new_heads_rx) = broadcast::channel(32); - - let task = tokio::spawn(async move { - loop { - let mut event_stream = match beacon_client.get_events::().await { - Ok(events) => events, - Err(err) => { - warn!(?err, "failed to subscribe to new heads topic, retrying..."); - tokio::time::sleep(Duration::from_secs(1)).await; - continue; - } - }; - - let event = match event_stream.next().await { - Some(Ok(event)) => event, - Some(Err(err)) => { - warn!(?err, "error reading new head event stream, retrying..."); - tokio::time::sleep(Duration::from_secs(1)).await; - continue; - } - None => { - warn!("new head event stream ended, retrying..."); - tokio::time::sleep(Duration::from_secs(1)).await; - continue; - } - }; - - if let Err(err) = new_heads_tx.send(event) { - warn!(?err, "failed to broadcast new head event to subscribers"); - } - } - }); - - Self { new_heads_rx, quit: task.abort_handle() } - } - - /// Stop the tracker and cleanup resources - pub fn stop(self) { - self.quit.abort(); - } - - /// Get the next head event from the tracker - pub async fn next_head(&mut self) -> Result { - self.new_heads_rx.recv().await - } - - /// Subscribe to new head events from the tracker - /// - /// The returned channel will NOT contain any previously emitted events cached in - /// the tracker, but only new ones received after the call to this method - pub fn subscribe_new_heads(&self) -> broadcast::Receiver { - self.new_heads_rx.resubscribe() - } -} - -#[cfg(test)] -mod tests { - use reqwest::Url; - use tracing::warn; - - use crate::{ - state::head_tracker::HeadTracker, test_util::try_get_beacon_api_url, BeaconClient, - }; - - #[tokio::test] - async fn test_fetch_next_beacon_head() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let Some(url) = try_get_beacon_api_url().await else { - warn!("skipping test: beacon API URL is not reachable"); - return Ok(()); - }; - - let beacon_client = BeaconClient::new(Url::parse(url).unwrap()); - let mut tracker = HeadTracker::start(beacon_client); - - let head = tracker.next_head().await?; - - assert!(head.slot > 0); - assert!(!head.block.is_empty()); - - Ok(()) - } -} diff --git a/bolt-sidecar/src/state/mod.rs b/bolt-sidecar/src/state/mod.rs deleted file mode 100644 index 373f3d13d..000000000 --- a/bolt-sidecar/src/state/mod.rs +++ /dev/null @@ -1,89 +0,0 @@ -//! The `state` module is responsible for keeping a local copy of relevant state that is needed -//! to simulate commitments against. It is updated on every block. It has both execution state and -//! consensus state. - -use std::{ - pin::Pin, - task::{Context, Poll}, - time::Duration, -}; - -use futures::{future::poll_fn, Future, FutureExt}; -use tokio::time::Sleep; - -mod execution; -pub use execution::{ExecutionState, ValidationError}; - -/// Module to fetch state from the Execution layer. -pub mod fetcher; -pub use fetcher::StateClient; - -/// Module to track the consensus state. -pub mod consensus; -pub use consensus::ConsensusState; - -/// Module to track the head of the chain. -pub mod head_tracker; -pub use head_tracker::HeadTracker; - -/// The deadline for a which a commitment is considered valid. -#[derive(Debug)] -pub struct CommitmentDeadline { - slot: u64, - sleep: Option>>, -} - -impl CommitmentDeadline { - /// Create a new deadline for a given slot and duration. - pub fn new(slot: u64, duration: Duration) -> Self { - let sleep = Some(Box::pin(tokio::time::sleep(duration))); - Self { slot, sleep } - } - - /// Poll the deadline until it is reached. - pub async fn wait(&mut self) -> Option { - let slot = poll_fn(|cx| self.poll_unpin(cx)).await; - self.sleep = None; - slot - } -} - -/// Poll the deadline until it is reached. -/// -/// - If already reached, the future will return `None` immediately. -/// - If not reached, the future will return `Some(slot)` when the deadline is reached. -impl Future for CommitmentDeadline { - type Output = Option; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let Some(ref mut sleep) = self.sleep else { - return Poll::Ready(None); - }; - - match sleep.as_mut().poll(cx) { - Poll::Ready(_) => Poll::Ready(Some(self.slot)), - Poll::Pending => Poll::Pending, - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[tokio::test] - async fn test_commitment_deadline() { - let time = std::time::Instant::now(); - let mut deadline = CommitmentDeadline::new(0, Duration::from_secs(1)); - - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, Some(0)); - - let time = std::time::Instant::now(); - let slot = deadline.wait().await; - println!("Deadline reached. Passed {:?}", time.elapsed()); - assert_eq!(slot, None); - } -} diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs deleted file mode 100644 index 59660ab7c..000000000 --- a/bolt-sidecar/src/test_util.rs +++ /dev/null @@ -1,172 +0,0 @@ -use alloy::{ - eips::eip2718::Encodable2718, - network::{EthereumWallet, TransactionBuilder}, - primitives::{Address, U256}, - rpc::types::TransactionRequest, - signers::{ - k256::{ecdsa::SigningKey as K256SigningKey, SecretKey as K256SecretKey}, - local::PrivateKeySigner, - Signer, - }, -}; -use alloy_node_bindings::{Anvil, AnvilInstance}; -use blst::min_pk::SecretKey; -use reth_primitives::PooledTransactionsElement; -use secp256k1::Message; -use tracing::warn; - -use crate::{ - crypto::{ecdsa::SignableECDSA, SignableBLS}, - primitives::{CommitmentRequest, FullTransaction, InclusionRequest}, - Config, -}; - -/// The URL of the test execution client HTTP API. -/// -/// NOTE: this DNS is only available through the Chainbound Tailnet -const EXECUTION_API_URL: &str = "http://remotebeast:8545"; - -/// The URL of the test beacon client HTTP API. -/// -/// NOTE: this DNS is only available through the Chainbound Tailnet -const BEACON_API_URL: &str = "http://remotebeast:3500"; - -/// The URL of the test engine client HTTP API. -/// -/// NOTE: this DNS is only available through the Chainbound Tailnet -const ENGINE_API_URL: &str = "http://remotebeast:8551"; - -/// Check if the test execution client is reachable by sending a GET request to it. -pub(crate) async fn try_get_execution_api_url() -> Option<&'static str> { - if reqwest::get(EXECUTION_API_URL).await.is_ok() { - Some(EXECUTION_API_URL) - } else { - None - } -} - -/// Check if the test engine client is reachable by sending a GET request to it. -pub(crate) async fn try_get_engine_api_url() -> Option<&'static str> { - if reqwest::get(ENGINE_API_URL).await.is_ok() { - Some(ENGINE_API_URL) - } else { - None - } -} - -/// Check if the test beacon client is reachable by sending a GET request to it. -pub(crate) async fn try_get_beacon_api_url() -> Option<&'static str> { - if reqwest::get(BEACON_API_URL).await.is_ok() { - Some(BEACON_API_URL) - } else { - None - } -} - -/// Return a mock configuration for testing purposes. Contains: -/// - The URL of the test execution client HTTP API. -/// - The URL of the test engine client HTTP API. -/// - The URL of the test beacon client HTTP API. -/// - The JWT token used to authenticate with the test engine API -/// - The default values for the remaining configuration fields. -/// -/// If any of the above values can't be found, the function will return `None`. -pub(crate) async fn get_test_config() -> Option { - let _ = dotenvy::dotenv(); - - let Some(jwt) = std::env::var("ENGINE_JWT").ok() else { - warn!("ENGINE_JWT not found in environment variables"); - return None; - }; - - let execution = try_get_execution_api_url().await?; - let beacon = try_get_beacon_api_url().await?; - let engine = try_get_engine_api_url().await?; - - Some(Config { - execution_api_url: execution.parse().ok()?, - engine_api_url: engine.parse().ok()?, - beacon_api_url: beacon.parse().ok()?, - jwt_hex: jwt, - ..Default::default() - }) -} - -/// Launch a local instance of the Anvil test chain. -pub(crate) fn launch_anvil() -> AnvilInstance { - Anvil::new().block_time(1).chain_id(1337).spawn() -} - -/// Create a default transaction template to use for tests -pub(crate) fn default_test_transaction(sender: Address, nonce: Option) -> TransactionRequest { - TransactionRequest::default() - .with_from(sender) - // Burn it - .with_to(Address::ZERO) - .with_chain_id(1337) - .with_nonce(nonce.unwrap_or(0)) - .with_value(U256::from(100)) - .with_gas_limit(21_000) - .with_max_priority_fee_per_gas(1_000_000_000) - .with_max_fee_per_gas(20_000_000_000) -} - -/// Create a default BLS secret key -pub(crate) fn test_bls_secret_key() -> SecretKey { - SecretKey::key_gen(&[0u8; 32], &[]).unwrap() -} - -/// Arbitrary bytes that can be signed with both ECDSA and BLS keys -pub(crate) struct TestSignableData { - pub data: Vec, -} - -impl SignableBLS for TestSignableData { - fn digest(&self) -> Vec { - self.data.clone() - } -} - -impl SignableECDSA for TestSignableData { - fn digest(&self) -> Message { - // pad the data to 32 bytes - let as_32 = if self.data.len() < 32 { - let mut padded = vec![0; 32]; - padded[..self.data.len()].copy_from_slice(&self.data); - padded - } else { - self.data.clone() - }; - - Message::from_digest_slice(as_32.as_slice()).expect("valid message") - } -} - -/// Create a valid signed commitment request for testing purposes -/// from the given transaction, private key of the sender, and slot. -pub(crate) async fn create_signed_commitment_request( - txs: &[TransactionRequest], - sk: &K256SecretKey, - slot: u64, -) -> eyre::Result { - let sk = K256SigningKey::from_slice(sk.to_bytes().as_slice())?; - let signer = PrivateKeySigner::from_signing_key(sk.clone()); - let wallet = EthereumWallet::from(signer.clone()); - - let mut full_txs = Vec::with_capacity(txs.len()); - for tx in txs { - let tx_signed = tx.clone().build(&wallet).await?; - let raw_encoded = tx_signed.encoded_2718(); - let tx_pooled = PooledTransactionsElement::decode_enveloped(&mut raw_encoded.as_slice())?; - full_txs.push(FullTransaction::from(tx_pooled)); - } - let mut request = InclusionRequest { txs: full_txs, slot, signature: None, signer: None }; - - request.recover_signers()?; - - let signature = signer.sign_hash(&request.digest()).await?; - request.set_signature(signature); - request.set_signer(signer.address()); - - Ok(CommitmentRequest::Inclusion(request)) -} diff --git a/bolt-web-demo/README.md b/bolt-web-demo/README.md deleted file mode 100644 index aaaa86f42..000000000 --- a/bolt-web-demo/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# BOLT web demo - -This is a simple full-stack example of BOLT preconfirmations. It's a simple web app that -allows users to send transactions and get a fast preconfirmation response. - -A list of event logs show the pipeline of the transaction, from the moment the user sends it -to the moment it gets included on-chain. - -## Usage - -```shell -cd frontend && yarn && yarn dev - -cd backend && yarn && yarn dev -``` diff --git a/bolt-web-demo/backend/.gitignore b/bolt-web-demo/backend/.gitignore deleted file mode 100644 index 40b878db5..000000000 --- a/bolt-web-demo/backend/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ \ No newline at end of file diff --git a/bolt-web-demo/backend/package.json b/bolt-web-demo/backend/package.json deleted file mode 100644 index dae7bb174..000000000 --- a/bolt-web-demo/backend/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "backend", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "dev": "ts-node-dev --respawn --transpile-only src/server.ts", - "start": "ts-node src/server.ts" - }, - "dependencies": { - "@types/express": "^4.17.21", - "@types/morgan": "^1.9.9", - "body-parser": "^1.20.2", - "cors": "^2.8.5", - "express": "^4.19.2", - "morgan": "^1.10.0", - "socket.io": "^4.7.5", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", - "typescript": "^5.4.5" - } -} diff --git a/bolt-web-demo/backend/src/devnet.ts b/bolt-web-demo/backend/src/devnet.ts deleted file mode 100644 index eaec771ca..000000000 --- a/bolt-web-demo/backend/src/devnet.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { logger } from "./logger"; -import { io } from "./server"; -import { EventType } from "./types"; -import { spawn } from "child_process"; - -// In-memory cache for devnet endpoints. Each time the devnet is restarted, -// endpoints will change according to kurtosis random port assignments. -export let DEVNET_ENDPOINTS: { [key: string]: string } = {}; - -export async function waitForPort( - kurtosisArgs: string[], - eventType: EventType -) { - const waitTimeMs = 2000; - let attemptsDone = 0; - const maxAttempts = 20; - let shouldTryAgain = true; - - while (shouldTryAgain && attemptsDone < maxAttempts) { - logger.debug( - `Attempts done for ${eventType}: ${attemptsDone}; maxAttempts: ${maxAttempts}` - ); - try { - const kurtosisPort = spawn("kurtosis", [ - "port", - "print", - "bolt-devnet", - ...kurtosisArgs, - ]); - - kurtosisPort.stdout.on("data", (data) => { - logger.info(`Event ${eventType} occurred: ${data}`); - if (data.toString().includes("WARN")) { - logger.debug("skipping warn message from kurtosis"); - return; - } - - DEVNET_ENDPOINTS[eventType] = data.toString().replace(/\n/g, ""); - - io.emit("new-event", { - type: eventType, - message: data.toString().replace(/\n/g, ""), - timestamp: new Date().toISOString(), - }); - shouldTryAgain = false; - }); - - kurtosisPort.stderr.on("data", (data) => { - if (attemptsDone === maxAttempts - 1) { - logger.error(`stderr: ${data}`); - } - }); - - kurtosisPort.on("close", (code) => { - logger.debug(`child process exited with code ${code}`); - }); - } catch (e) { - logger.error(`Error while trying to get the port: ${e}`); - } - - attemptsDone++; - await new Promise((resolve) => setTimeout(resolve, waitTimeMs)); - } -} - -export async function getSlot(beaconClientUrl: string): Promise { - const slotResponse = await fetch( - `${beaconClientUrl}/eth/v1/beacon/headers/head`, - { mode: "no-cors" } - ).then((response) => response.json()); - - return Number(slotResponse.data.header.message.slot); -} diff --git a/bolt-web-demo/backend/src/logger.ts b/bolt-web-demo/backend/src/logger.ts deleted file mode 100644 index 58b1dcdf5..000000000 --- a/bolt-web-demo/backend/src/logger.ts +++ /dev/null @@ -1,62 +0,0 @@ -export type LogLevel = "info" | "debug" | "error" | "warn" | "success" | "none"; - -export default class Logger { - constructor(private logLevel: LogLevel, private namespace: string) {} - - private log(message: string, level: LogLevel, color: Colors) { - if (this.logLevel !== "none") { - console.log( - color, - `[${ - this.namespace - }] [${new Date().toLocaleString()}] [${level}] ${message}`, - Colors.Reset - ); - } - } - - public info(message: string) { - this.log(message, "info", Colors.Blue); - } - - public debug(message: string) { - this.log(message, "debug", Colors.Dim); - } - - public error(message: string) { - this.log(message, "error", Colors.Red); - } - - public warn(message: string) { - this.log(message, "warn", Colors.Yellow); - } - - public success(message: string) { - this.log(message, "success", Colors.Green); - } -} - -enum Colors { - Black = "\x1b[30m", - Red = "\x1b[31m", - Green = "\x1b[32m", - Yellow = "\x1b[33m", - Blue = "\x1b[34m", - Magenta = "\x1b[35m", - Cyan = "\x1b[36m", - White = "\x1b[37m", - Gray = "\x1b[90m", - - Reset = "\x1b[0m", - Bright = "\x1b[1m", - Dim = "\x1b[2m", - Underscore = "\x1b[4m", - Blink = "\x1b[5m", - Reverse = "\x1b[7m", - Hidden = "\x1b[8m", -} - -export const logger = new Logger( - (process.env.LOG_LEVEL as LogLevel) || "info", - "BOLT" -); diff --git a/bolt-web-demo/backend/src/server.ts b/bolt-web-demo/backend/src/server.ts deleted file mode 100644 index a799f9aa8..000000000 --- a/bolt-web-demo/backend/src/server.ts +++ /dev/null @@ -1,156 +0,0 @@ -import express from "express"; -import morgan from "morgan"; -import cors from "cors"; -import { createServer } from "http"; -import { Server } from "socket.io"; -import { json } from "body-parser"; - -import { DEVNET_ENDPOINTS, getSlot, waitForPort } from "./devnet"; -import { EventType } from "./types"; -import { logger } from "./logger"; - -const SERVER_PORT = 3001; -const EVENTS_SET = new Set(); -let LATEST_SLOT = 0; - -const app = express(); -const server = createServer(app); -export const io = new Server(server, { - cors: { origin: "*", methods: ["GET", "POST"] }, -}); - -app.use(json()); -app.use(morgan("dev")); -app.use(cors({ origin: "*" })); - -// HTTP endpoint for receiving events via POST requests from BOLT components -app.post("/events", (req, res) => { - logger.info(`Received event: ${JSON.stringify(req.body)}`); - const { message } = req.body; - - if (!message) { - console.error("No message provided"); - res.status(400).send("No message provided"); - } else { - // // Remove time measurements from the message - // const messageWithoutMeasurements = message.replace(/ in .+$/g, ""); - // // Deduplicate events - // if (EVENTS_SET.has(messageWithoutMeasurements)) { - // console.warn( - // "Duplicate event received, discarding:", - // messageWithoutMeasurements - // ); - // res.status(200).send("OK"); - // return; - // } - // EVENTS_SET.add(messageWithoutMeasurements); - - // Broadcast the message to all connected WebSocket clients - io.emit("new-event", { message, timestamp: new Date().toISOString() }); - - res.setHeader("Content-Type", "text/plain"); - res.send("OK"); - } -}); - -// Helper endpoint for re-sending port events to the frontend when necessary -app.get("/retry-port-events", (req, res) => { - sendDevnetEvents(); - res.send("OK"); -}); - -app.get("/latest-slot", (req, res) => { - if (!DEVNET_ENDPOINTS[EventType.BEACON_CLIENT_URL_FOUND]) { - res.status(500).send({ message: "No beacon client URL found" }); - return; - } - - getSlot(DEVNET_ENDPOINTS[EventType.BEACON_CLIENT_URL_FOUND]).then((slot) => { - if (slot !== undefined) { - res.send({ slot }); - } else { - res.status(500).send("Could not fetch the latest slot"); - } - }); -}); - -// Endpoint to send a signed preconfirmation transaction to the BOLT MEV sidecar -app.post("/preconfirmation", async (req, res) => { - const beaconClientUrl = DEVNET_ENDPOINTS[EventType.BEACON_CLIENT_URL_FOUND]; - const mevSidecarUrl = DEVNET_ENDPOINTS[EventType.MEV_SIDECAR_URL_FOUND]; - const providerUrl = DEVNET_ENDPOINTS[EventType.JSONRPC_PROVIDER_URL_FOUND]; - if (!mevSidecarUrl || !providerUrl || !beaconClientUrl) { - res - .status(500) - .send("No MEV sidecar or beacon client or provider URL found"); - return; - } - - const { slot, tx, signature } = req.body; - if (!tx || !signature) { - res.status(400).send("No tx or signature provided"); - return; - } - - const preconfirmationResponse = await fetch(`http://${mevSidecarUrl}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - id: "1", - jsonrpc: "2.0", - method: "bolt_inclusionPreconfirmation", - params: [{ slot, tx, signature }], - }), - }).then((response) => response.json()); - - res.setHeader("Content-Type", "application/json"); - res.send({ result: preconfirmationResponse, slot }); -}); - -server.listen(SERVER_PORT, () => { - logger.info(`Server is running on http://localhost:${SERVER_PORT}`); -}); - -async function sendDevnetEvents() { - waitForPort( - ["cl-1-lighthouse-geth", "http"], - EventType.BEACON_CLIENT_URL_FOUND - ); - - waitForPort( - ["el-1-geth-lighthouse", "rpc"], - EventType.JSONRPC_PROVIDER_URL_FOUND - ); - - waitForPort(["mev-sidecar-api", "api"], EventType.MEV_SIDECAR_URL_FOUND); - - waitForPort(["dora", "http"], EventType.EXPLORER_URL_FOUND); -} - -// Send devnet events after a delay to ensure that the frontend is ready to receive them -// if we start the backend after the frontend. -(async () => { - await new Promise((resolve) => setTimeout(resolve, 2000)); - sendDevnetEvents(); -})(); - -// Poll for the latest slot number -(async () => { - let beaconClientUrl = DEVNET_ENDPOINTS?.[EventType.BEACON_CLIENT_URL_FOUND]; - - while (!beaconClientUrl) { - await new Promise((resolve) => setTimeout(resolve, 1000)); - beaconClientUrl = DEVNET_ENDPOINTS?.[EventType.BEACON_CLIENT_URL_FOUND]; - } - - while (true) { - LATEST_SLOT = await getSlot(beaconClientUrl); - io.emit("new-event", { - type: EventType.NEW_SLOT, - message: LATEST_SLOT, - timestamp: new Date().toISOString(), - }); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - } -})(); diff --git a/bolt-web-demo/backend/src/types.ts b/bolt-web-demo/backend/src/types.ts deleted file mode 100644 index 74c87742d..000000000 --- a/bolt-web-demo/backend/src/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum EventType { - BEACON_CLIENT_URL_FOUND = "BEACON_CLIENT_URL_FOUND", - JSONRPC_PROVIDER_URL_FOUND = "JSONRPC_PROVIDER_URL_FOUND", - MEV_SIDECAR_URL_FOUND = "MEV_SIDECAR_URL_FOUND", - EXPLORER_URL_FOUND = "EXPLORER_URL_FOUND", - NEW_SLOT = "NEW_SLOT", -} diff --git a/bolt-web-demo/backend/tsconfig.json b/bolt-web-demo/backend/tsconfig.json deleted file mode 100644 index e075f973c..000000000 --- a/bolt-web-demo/backend/tsconfig.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/bolt-web-demo/backend/yarn.lock b/bolt-web-demo/backend/yarn.lock deleted file mode 100644 index 4c2b25e25..000000000 --- a/bolt-web-demo/backend/yarn.lock +++ /dev/null @@ -1,1098 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@socket.io/component-emitter@~3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.1.tgz#621270c02c0a5d4f4669eb1caa9723c91cf201de" - integrity sha512-dzJtaDAAoXx4GCOJpbB2eG/Qj8VDpdwkLsWGzGm+0L7E8/434RyMbAHmk9ubXWVAb9nXmc44jUf8GKqVDiKezg== - -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/body-parser@*": - version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== - dependencies: - "@types/node" "*" - -"@types/cookie@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" - integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== - -"@types/cors@^2.8.12": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== - dependencies: - "@types/node" "*" - -"@types/express-serve-static-core@^4.17.33": - version "4.19.0" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz#3ae8ab3767d98d0b682cda063c3339e1e86ccfaa" - integrity sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - -"@types/express@^4.17.21": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/http-errors@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== - -"@types/mime@^1": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" - integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== - -"@types/morgan@^1.9.9": - version "1.9.9" - resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.9.tgz#d60dec3979e16c203a000159daa07d3fb7270d7f" - integrity sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ== - dependencies: - "@types/node" "*" - -"@types/node@*", "@types/node@>=10.0.0": - version "20.12.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" - integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== - dependencies: - undici-types "~5.26.4" - -"@types/qs@*": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== - -"@types/range-parser@*": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" - integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== - -"@types/send@*": - version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/serve-static@*": - version "1.15.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== - dependencies: - "@types/http-errors" "*" - "@types/node" "*" - "@types/send" "*" - -"@types/strip-bom@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" - integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== - -"@types/strip-json-comments@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" - integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== - -accepts@~1.3.4, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-walk@^8.1.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.4.1: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64id@2.0.0, base64id@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" - integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== - -basic-auth@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" - integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== - dependencies: - safe-buffer "5.1.2" - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -body-parser@1.20.2, body-parser@^1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -chokidar@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - -cors@^2.8.5, cors@~2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -depd@2.0.0, depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dynamic-dedupe@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" - integrity sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ== - dependencies: - xtend "^4.0.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -engine.io-parser@~5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" - integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== - -engine.io@~6.5.2: - version "6.5.4" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc" - integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg== - dependencies: - "@types/cookie" "^0.4.1" - "@types/cors" "^2.8.12" - "@types/node" ">=10.0.0" - accepts "~1.3.4" - base64id "2.0.0" - cookie "~0.4.1" - cors "~2.8.5" - debug "~4.3.1" - engine.io-parser "~5.2.1" - ws "~8.11.0" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -express@^4.19.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -hasown@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -morgan@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" - integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== - dependencies: - basic-auth "~2.0.1" - debug "2.6.9" - depd "~2.0.0" - on-finished "~2.3.0" - on-headers "~1.0.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-assign@^4: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -resolve@^1.0.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -rimraf@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -safe-buffer@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -side-channel@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -socket.io-adapter@~2.5.2: - version "2.5.4" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz#4fdb1358667f6d68f25343353bd99bd11ee41006" - integrity sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg== - dependencies: - debug "~4.3.4" - ws "~8.11.0" - -socket.io-parser@~4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" - integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.3.1" - -socket.io@^4.7.5: - version "4.7.5" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" - integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== - dependencies: - accepts "~1.3.4" - base64id "~2.0.0" - cors "~2.8.5" - debug "~4.3.2" - engine.io "~6.5.2" - socket.io-adapter "~2.5.2" - socket.io-parser "~4.2.4" - -source-map-support@^0.5.12: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-node-dev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" - integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== - dependencies: - chokidar "^3.5.1" - dynamic-dedupe "^0.3.0" - minimist "^1.2.6" - mkdirp "^1.0.4" - resolve "^1.0.0" - rimraf "^2.6.1" - source-map-support "^0.5.12" - tree-kill "^1.2.2" - ts-node "^10.4.0" - tsconfig "^7.0.0" - -ts-node@^10.4.0, ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" - integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== - dependencies: - "@types/strip-bom" "^3.0.0" - "@types/strip-json-comments" "0.0.30" - strip-bom "^3.0.0" - strip-json-comments "^2.0.0" - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typescript@^5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/bolt-web-demo/frontend/.eslintrc.json b/bolt-web-demo/frontend/.eslintrc.json deleted file mode 100644 index bffb357a7..000000000 --- a/bolt-web-demo/frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/bolt-web-demo/frontend/.gitignore b/bolt-web-demo/frontend/.gitignore deleted file mode 100644 index 90f05df88..000000000 --- a/bolt-web-demo/frontend/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -node_modules/ -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/bolt-web-demo/frontend/components.json b/bolt-web-demo/frontend/components.json deleted file mode 100644 index 14331d8cb..000000000 --- a/bolt-web-demo/frontend/components.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": true, - "tsx": true, - "tailwind": { - "config": "tailwind.config.ts", - "css": "src/app/globals.css", - "baseColor": "slate", - "cssVariables": true, - "prefix": "" - }, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils" - } -} \ No newline at end of file diff --git a/bolt-web-demo/frontend/next.config.mjs b/bolt-web-demo/frontend/next.config.mjs deleted file mode 100644 index 4678774e6..000000000 --- a/bolt-web-demo/frontend/next.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -export default nextConfig; diff --git a/bolt-web-demo/frontend/package.json b/bolt-web-demo/frontend/package.json deleted file mode 100644 index a956a43a3..000000000 --- a/bolt-web-demo/frontend/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "bolt-frontend", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/react-progress": "^1.0.3", - "@radix-ui/react-scroll-area": "^1.0.5", - "@radix-ui/react-slot": "^1.0.2", - "axios": "^1.6.8", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "ethers": "^6.12.0", - "next": "14.2.2", - "react": "^18", - "react-dom": "^18", - "socket.io-client": "^4.7.5", - "tailwind-merge": "^2.3.0", - "tailwindcss-animate": "^1.0.7" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.2.2", - "postcss": "^8", - "tailwindcss": "^3.4.1", - "typescript": "^5" - } -} diff --git a/bolt-web-demo/frontend/postcss.config.mjs b/bolt-web-demo/frontend/postcss.config.mjs deleted file mode 100644 index 1a69fd2a4..000000000 --- a/bolt-web-demo/frontend/postcss.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('postcss-load-config').Config} */ -const config = { - plugins: { - tailwindcss: {}, - }, -}; - -export default config; diff --git a/bolt-web-demo/frontend/public/bolt-logo.png b/bolt-web-demo/frontend/public/bolt-logo.png deleted file mode 100644 index e6e366c26..000000000 Binary files a/bolt-web-demo/frontend/public/bolt-logo.png and /dev/null differ diff --git a/bolt-web-demo/frontend/public/chainbound-logo.svg b/bolt-web-demo/frontend/public/chainbound-logo.svg deleted file mode 100644 index 60bc93d2d..000000000 --- a/bolt-web-demo/frontend/public/chainbound-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/bolt-web-demo/frontend/public/next.svg b/bolt-web-demo/frontend/public/next.svg deleted file mode 100644 index 5174b28c5..000000000 --- a/bolt-web-demo/frontend/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/bolt-web-demo/frontend/public/vercel.svg b/bolt-web-demo/frontend/public/vercel.svg deleted file mode 100644 index d2f842227..000000000 --- a/bolt-web-demo/frontend/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/bolt-web-demo/frontend/src/app/favicon.ico b/bolt-web-demo/frontend/src/app/favicon.ico deleted file mode 100644 index 25c3c8a16..000000000 Binary files a/bolt-web-demo/frontend/src/app/favicon.ico and /dev/null differ diff --git a/bolt-web-demo/frontend/src/app/globals.css b/bolt-web-demo/frontend/src/app/globals.css deleted file mode 100644 index b0e6fff59..000000000 --- a/bolt-web-demo/frontend/src/app/globals.css +++ /dev/null @@ -1,76 +0,0 @@ -@tailwind base; - @tailwind components; - @tailwind utilities; - - @layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } - } - - @layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } - } \ No newline at end of file diff --git a/bolt-web-demo/frontend/src/app/layout.tsx b/bolt-web-demo/frontend/src/app/layout.tsx deleted file mode 100644 index ba3f1f252..000000000 --- a/bolt-web-demo/frontend/src/app/layout.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import { cn } from "@/lib/utils"; -import "./globals.css"; - -const inter = Inter({ - subsets: ["latin"], - variable: "--font-sans", -}); - -export const metadata: Metadata = { - title: "BOLT", - description: "Your friendly preconfirmation companion.", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - - {children} - - - ); -} diff --git a/bolt-web-demo/frontend/src/app/page.tsx b/bolt-web-demo/frontend/src/app/page.tsx deleted file mode 100644 index d1a2903c7..000000000 --- a/bolt-web-demo/frontend/src/app/page.tsx +++ /dev/null @@ -1,442 +0,0 @@ -"use client"; - -import io from "socket.io-client"; -import Image from "next/image"; -import { useState, useEffect, useMemo, useCallback } from "react"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { Button } from "@/components/ui/button"; -import { createPreconfPayload } from "@/lib/wallet"; -import { EventType } from "@/lib/types"; -import { Progress } from "@/components/ui/progress"; -import { ethers } from "ethers"; -import { PRIVATE_KEY, SERVER_URL } from "@/lib/constants"; - -type Event = { - message: string; - type?: EventType; - timestamp: string; - link?: string; -}; - -export default function Home() { - const [events, setEvents] = useState>([]); - - const [preconfSent, setPreconfSent] = useState(false); - const [preconfSlot, setPreconfSlot] = useState(-1); - const [preconfIncluded, setPreconfIncluded] = useState(false); - const [preconfFinalized, setPreconfFinalized] = useState(false); - - const [preconfTimerActive, setPreconfTimerActive] = useState(false); - const [preconfTime, setPreconfTime] = useState(0); - const [inclusionTimerActive, setInclusionTimerActive] = useState(false); - const [inclusionTime, setInclusionTime] = useState(0); - const [finalizationTimerActive, setFinalizationTimerActive] = useState(false); - const [finalizationTime, setFinalizationTime] = useState(0); - - const [newSlotNumber, setNewSlotNumber] = useState(-1); - const [beaconClientUrl, setBeaconClientUrl] = useState(""); - const [providerUrl, setProviderUrl] = useState(""); - const [explorerUrl, setExplorerUrl] = useState(""); - const [preconfirmationRequests, setPreconfirmationRequests] = useState< - Array<{ slot: number; count: number }> - >([]); - const [nonce, setNonce] = useState(0); - - const wallet = useMemo(() => { - const provider = new ethers.JsonRpcProvider(providerUrl); - const wallet = new ethers.Wallet(PRIVATE_KEY, provider); - return wallet; - }, [providerUrl]); - - useEffect(() => { - fetch(`${SERVER_URL}/retry-port-events`); - fetch(`${SERVER_URL}/latest-slot`) - .then((res) => res.json()) - .then((data) => setNewSlotNumber(data.slot)); - }, []); - - useEffect(() => { - const newSocket = io(SERVER_URL, { autoConnect: true }); - - newSocket.on("new-event", (event: Event) => { - // console.info("Event from server:", event); - - if (event.type === EventType.NEW_SLOT) { - const slot = Number(event.message); - if (slot === preconfSlot + 64) { - setPreconfFinalized(true); - setFinalizationTimerActive(false); - dispatchEvent({ - message: `Preconfirmed transaction finalized at slot ${event.message}`, - timestamp: new Date().toISOString(), - }); - } - - // Drop old requests - setPreconfirmationRequests((prev) => - prev.filter((req) => req.slot >= slot), - ); - - // Update the nonce - wallet.getNonce().then((nonce) => setNonce(nonce)); - } - - // If the event has a special type, handle it differently - switch (event.type) { - case EventType.BEACON_CLIENT_URL_FOUND: - console.info("Beacon client URL found:", event.message); - setBeaconClientUrl(event.message); - return; - case EventType.JSONRPC_PROVIDER_URL_FOUND: - console.info("Provider URL found:", event.message); - setProviderUrl(event.message); - return; - case EventType.EXPLORER_URL_FOUND: - console.info("Explorer URL found:", event.message); - setExplorerUrl(event.message); - case EventType.MEV_SIDECAR_URL_FOUND: - console.info("MEV sidecar URL found:", event.message); - return; - case EventType.NEW_SLOT: - setNewSlotNumber(Number(event.message)); - return; - default: - break; - } - - setEvents((prev) => [event, ...prev]); - - // If the event is a preconfirmation, extract the tx hash and slot number - // and display a message with the explorer URL - if ( - event.message.toLowerCase().includes("verified merkle proof for slot") - ) { - setPreconfIncluded(true); - setInclusionTimerActive(false); - dispatchEvent({ - message: `Preconfirmed transaction included at slot ${preconfSlot}`, - link: `${explorerUrl}/slot/${preconfSlot}`, - timestamp: new Date().toISOString(), - }); - } - }); - - return () => { - newSocket.close(); - }; - }, [explorerUrl, preconfSlot, wallet]); - - useEffect(() => { - let interval: any = null; - - if (preconfTimerActive) { - interval = setInterval(() => { - setPreconfTime((prev) => prev + 2); - }, 2); - } else { - clearInterval(interval); - } - - return () => clearInterval(interval); - }, [preconfTimerActive]); - - useEffect(() => { - let interval: any = null; - - if (inclusionTimerActive) { - interval = setInterval(() => { - setInclusionTime((prev) => prev + 10); - }, 10); - } else { - clearInterval(interval); - } - - return () => clearInterval(interval); - }, [inclusionTimerActive]); - - useEffect(() => { - let interval: any = null; - - if (finalizationTimerActive) { - interval = setInterval(() => { - setFinalizationTime((prev) => prev + 30); - }, 30); - } else { - clearInterval(interval); - } - - return () => clearInterval(interval); - }, [finalizationTimerActive]); - - const sendPreconfirmation = useCallback(async () => { - // Reset state - setEvents([]); - setPreconfSent(true); - setPreconfIncluded(false); - setPreconfFinalized(false); - setPreconfTime(0); - setInclusionTime(0); - setFinalizationTime(0); - - try { - const nonceWithPreconfs = - nonce + - preconfirmationRequests - .map((req) => req.count) - .reduce((acc, c) => acc + c, 0); - - const { payload, txHash } = await createPreconfPayload( - wallet, - nonceWithPreconfs, - ); - - setPreconfirmationRequests((prev) => { - for (let i = 0; i < prev.length; i++) { - if (prev[i].slot === payload.slot) { - prev[i] = { ...prev[i], count: prev[i].count + 1 }; - return [...prev]; - } - } - prev.push({ slot: payload.slot, count: 1 }); - return [...prev]; - }); - - setPreconfSlot(payload.slot); - dispatchEvent({ - message: `Preconfirmation request sent for tx: ${txHash} at slot ${payload.slot} with nonce ${nonceWithPreconfs}`, - timestamp: new Date().toISOString(), - }); - - // 1. POST preconfirmation. - // The preconfirmation is considered valid as soon as the server responds with a 200 status code. - setPreconfTimerActive(true); - setInclusionTimerActive(true); - setFinalizationTimerActive(true); - - const res = await fetch(`${SERVER_URL}/preconfirmation`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(payload), - }); - if (res.status === 200) { - console.log("Preconfirmation response was successful"); - setPreconfTimerActive(false); - } - } catch (e) { - console.error(e); - } - }, [preconfirmationRequests, nonce, wallet]); - - function dispatchEvent(event: Event) { - setEvents((prev) => [event, ...prev]); - } - - const getStatusClass = (status: boolean) => { - const base = "h-4 w-4 border border-gray-800 rounded-full "; - return base + (status ? "bg-green-500" : "bg-yellow-500"); - }; - - return ( -
-
- BOLT - -
-

- Powered by{" "} - - Chainbound - -

- chainbound -

– v0.1.0

-
-
- - {newSlotNumber < 128 ? ( - <> - {newSlotNumber === -1 ? ( -
-

Loading...

-
- ) : ( -
-
-

- MEV Boost is not active yet, please wait -

- - MEV-Boost takes 4 epochs to activate on the Kurtosis devnet. - Please wait a few minutes for it to activate. - - - -
-
- )} - - ) : ( -
- {beaconClientUrl && providerUrl ? ( -
- {preconfSent && ( -
-

Status

-
    -
  • - Transaction preconfirmed: - - {preconfTime}ms -
  • -
  • - - Transaction confirmed (included in a block): - - - {inclusionTime / 1000}s -
  • -
  • - - Transaction finalized (2 epochs after inclusion): - - - {finalizationTime / 1000}s -
  • -
-
- )} - -
-

- Step 1: Send a transaction eligible for preconfirmation -

- - By clicking this button you will create a transaction and send - it as a preconfirmation request to the BOLT sidecar of the - next proposer in line.
- This transaction is crafted from a pre-funded account in the - devnet for demo purposes. -
- -
- -
-
- - {preconfSent && ( - <> -
-

- Step 2: Wait for proposers to issue the preconfirmation - response -

- - The transaction will be processed by BOLT and you will - receive a preconfirmation for inclusion in the next block. - -
- -
-

Event logs

- -
    - {[...events].reverse().map((message, index) => ( -
  • - {parseDateToMs(message.timestamp)} - {" | "} - {message.message.toString()} - {message.link && ( - - {" "} - [link] - - )} -
  • - ))} -
-
-
- - )} -
- ) : ( -
-
-

- Waiting for the devnet servers to start... -

- - This page will automatically update when the servers are - ready. - - -
- -
-
-
- )} -
- )} - -
-
-

Disclaimer

- - This demo application showcases the BOLT protocol happy-case. -
- Real-world deployments should consider the following missing - components and features (which are under development): -
    -
  • Automatic safety & liveness fault detection
  • -
  • On-chain dispute logic to verifiably attribute faults
  • -
  • BOLT RPC server proxy integration
  • -
  • - High network participation (at least 1 proposer opted-in in the - lookahead window) -
  • -
-
-
-
-
- ); -} - -function parseDateToMs(date: any) { - return new Date(date).toISOString().split("T")[1].split("Z")[0]; -} diff --git a/bolt-web-demo/frontend/src/components/ui/button.tsx b/bolt-web-demo/frontend/src/components/ui/button.tsx deleted file mode 100644 index 0270f644a..000000000 --- a/bolt-web-demo/frontend/src/components/ui/button.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: - "bg-primary text-primary-foreground shadow hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", - outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) - -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean -} - -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" - -export { Button, buttonVariants } diff --git a/bolt-web-demo/frontend/src/components/ui/progress.tsx b/bolt-web-demo/frontend/src/components/ui/progress.tsx deleted file mode 100644 index 4fc3b473e..000000000 --- a/bolt-web-demo/frontend/src/components/ui/progress.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client" - -import * as React from "react" -import * as ProgressPrimitive from "@radix-ui/react-progress" - -import { cn } from "@/lib/utils" - -const Progress = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, value, ...props }, ref) => ( - - - -)) -Progress.displayName = ProgressPrimitive.Root.displayName - -export { Progress } diff --git a/bolt-web-demo/frontend/src/components/ui/scroll-area.tsx b/bolt-web-demo/frontend/src/components/ui/scroll-area.tsx deleted file mode 100644 index 0b4a48d87..000000000 --- a/bolt-web-demo/frontend/src/components/ui/scroll-area.tsx +++ /dev/null @@ -1,48 +0,0 @@ -"use client" - -import * as React from "react" -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" - -import { cn } from "@/lib/utils" - -const ScrollArea = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - {children} - - - - -)) -ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName - -const ScrollBar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, orientation = "vertical", ...props }, ref) => ( - - - -)) -ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName - -export { ScrollArea, ScrollBar } diff --git a/bolt-web-demo/frontend/src/lib/constants.ts b/bolt-web-demo/frontend/src/lib/constants.ts deleted file mode 100644 index 12ec9c963..000000000 --- a/bolt-web-demo/frontend/src/lib/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Test private key, for which address[0] holds 1000 ETH in the Kurtosis devnet -export const PRIVATE_KEY = - "39725efee3fb28614de3bacaffe4cc4bd8c436257e2c8bb887c4b5c4be45e76d"; -export const KURTOSIS_CHAIN_ID = 3151908; -export const SERVER_URL = "http://localhost:3001"; diff --git a/bolt-web-demo/frontend/src/lib/types.ts b/bolt-web-demo/frontend/src/lib/types.ts deleted file mode 100644 index 74c87742d..000000000 --- a/bolt-web-demo/frontend/src/lib/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum EventType { - BEACON_CLIENT_URL_FOUND = "BEACON_CLIENT_URL_FOUND", - JSONRPC_PROVIDER_URL_FOUND = "JSONRPC_PROVIDER_URL_FOUND", - MEV_SIDECAR_URL_FOUND = "MEV_SIDECAR_URL_FOUND", - EXPLORER_URL_FOUND = "EXPLORER_URL_FOUND", - NEW_SLOT = "NEW_SLOT", -} diff --git a/bolt-web-demo/frontend/src/lib/utils.ts b/bolt-web-demo/frontend/src/lib/utils.ts deleted file mode 100644 index 365058ceb..000000000 --- a/bolt-web-demo/frontend/src/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type ClassValue, clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} diff --git a/bolt-web-demo/frontend/src/lib/wallet.ts b/bolt-web-demo/frontend/src/lib/wallet.ts deleted file mode 100644 index 4235c8550..000000000 --- a/bolt-web-demo/frontend/src/lib/wallet.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { TransactionRequest, keccak256 } from "ethers"; -import { ethers } from "ethers"; -import { KURTOSIS_CHAIN_ID, SERVER_URL } from "./constants"; - -type InclusionRequestPayload = { - slot: number; - tx: string; - signature: string; -}; - -export async function createPreconfPayload( - wallet: ethers.Wallet, - nonce: number, -): Promise<{ payload: InclusionRequestPayload; txHash: string }> { - // Define the transaction - const tx: TransactionRequest = { - chainId: KURTOSIS_CHAIN_ID, - nonce: nonce, - from: await wallet.getAddress(), - to: "0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD", - value: ethers.parseEther("0.0069420"), - maxFeePerGas: ethers.parseUnits("200", "gwei"), - maxPriorityFeePerGas: ethers.parseUnits("30", "gwei"), - data: "0xdeadbeef", - }; - - const estimatedGas = await wallet.estimateGas(tx); - tx.gasLimit = estimatedGas; - - const populated = await wallet.populateCall(tx); - const signedTx = await wallet.signTransaction(populated); - const txHash = keccak256(signedTx); - const slot = (await getLatestSlot()) + 2; - - // Create a signature over the request fields "slot" and "tx" using the same signer - // to authenticate the preconfirmation request through bolt. - const slotBytes = numberToLittleEndianBytes(slot); - const txHashBytes = hexToBytes(txHash); - const message = new Uint8Array(slotBytes.length + txHashBytes.length); - message.set(slotBytes); - message.set(txHashBytes, slotBytes.length); - - const messageDigest = keccak256(message); - const signature = wallet.signingKey.sign(messageDigest).serialized; - - return { payload: { slot, tx: signedTx, signature }, txHash }; -} - -export async function getLatestSlot(): Promise { - const slotResponse = await fetch(`${SERVER_URL}/latest-slot`).then( - (response) => response.json(), - ); - return Number(slotResponse.slot); -} - -// Function to convert a number to a little-endian byte array -function numberToLittleEndianBytes(num: number): Uint8Array { - const buffer = new ArrayBuffer(8); // Assuming slot_number is a 64-bit integer - const view = new DataView(buffer); - view.setUint32(0, num, true); // true for little-endian - return new Uint8Array(buffer); -} - -// Function to decode a hex string to a byte array -function hexToBytes(hex: string): Uint8Array { - hex = hex.replace(/^0x/, ""); // Remove "0x" prefix if present - const bytes = new Uint8Array(hex.length / 2); - for (let i = 0; i < hex.length; i += 2) { - bytes[i / 2] = parseInt(hex.substr(i, 2), 16); - } - return bytes; -} diff --git a/bolt-web-demo/frontend/tailwind.config.ts b/bolt-web-demo/frontend/tailwind.config.ts deleted file mode 100644 index f1e6a863f..000000000 --- a/bolt-web-demo/frontend/tailwind.config.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Config } from "tailwindcss"; -const { fontFamily } = require("tailwindcss/defaultTheme"); - -const config = { - darkMode: ["class"], - content: [ - "./pages/**/*.{ts,tsx}", - "./components/**/*.{ts,tsx}", - "./app/**/*.{ts,tsx}", - "./src/**/*.{ts,tsx}", - ], - prefix: "", - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - fontFamily: { - sans: ["var(--font-sans)", ...fontFamily.sans], - }, - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, - }, - plugins: [require("tailwindcss-animate")], -} satisfies Config; - -export default config; diff --git a/bolt-web-demo/frontend/tsconfig.json b/bolt-web-demo/frontend/tsconfig.json deleted file mode 100644 index 7b2858930..000000000 --- a/bolt-web-demo/frontend/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/bolt-web-demo/frontend/yarn.lock b/bolt-web-demo/frontend/yarn.lock deleted file mode 100644 index 1c2a5394d..000000000 --- a/bolt-web-demo/frontend/yarn.lock +++ /dev/null @@ -1,3001 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@adraffy/ens-normalize@1.10.1": - version "1.10.1" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" - integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== - -"@alloc/quick-lru@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" - integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== - -"@babel/runtime@^7.13.10", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.1": - version "7.24.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" - integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA== - dependencies: - regenerator-runtime "^0.14.0" - -"@eslint-community/eslint-utils@^4.2.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.24": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@next/env@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.2.tgz#6c36fe0b04a22ea78bd60a645ae77d53cd16d3ca" - integrity sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw== - -"@next/eslint-plugin-next@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.2.tgz#1eaf592ebb961e0b093e4774b0c77298af5e2e0e" - integrity sha512-q+Ec2648JtBpKiu/FSJm8HAsFXlNvioHeBCbTP12T1SGcHYwhqHULSfQgFkPgHDu3kzNp2Kem4J54bK4rPQ5SQ== - dependencies: - glob "10.3.10" - -"@next/swc-darwin-arm64@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.2.tgz#55e395b0db6dd5ea2dc92818260ff3a399f1a056" - integrity sha512-3iPgMhzbalizGwHNFUcGnDhFPSgVBHQ8aqSTAMxB5BvJG0oYrDf1WOJZlbXBgunOEj/8KMVbejEur/FpvFsgFQ== - -"@next/swc-darwin-x64@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.2.tgz#f96fb65510be798c03b0432129792c6ac8885bc8" - integrity sha512-x7Afi/jt0ZBRUZHTi49yyej4o8znfIMHO4RvThuoc0P+uli8Jd99y5GKjxoYunPKsXL09xBXEM1+OQy2xEL0Ag== - -"@next/swc-linux-arm64-gnu@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.2.tgz#443f0d4ab9d1aa4338e40f77ca4e182d60e88448" - integrity sha512-zbfPtkk7L41ODMJwSp5VbmPozPmMMQrzAc0HAUomVeVIIwlDGs/UCqLJvLNDt4jpWgc21SjjyIn762lNGrMaUA== - -"@next/swc-linux-arm64-musl@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.2.tgz#182c00b3d2f3ed4eaacdd385d07b230252c64de9" - integrity sha512-wPbS3pI/JU16rm3XdLvvTmlsmm1nd+sBa2ohXgBZcShX4TgOjD4R+RqHKlI1cjo/jDZKXt6OxmcU0Iys0OC/yg== - -"@next/swc-linux-x64-gnu@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.2.tgz#e826a08085dcc61685ff42884ad4032e71ac154f" - integrity sha512-NqWOHqqq8iC9tuHvZxjQ2tX+jWy2X9y8NX2mcB4sj2bIccuCxbIZrU/ThFPZZPauygajZuVQ6zediejQHwZHwQ== - -"@next/swc-linux-x64-musl@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.2.tgz#42f921ca6d93fdfb2b13de70cd8a44ba5526b318" - integrity sha512-lGepHhwb9sGhCcU7999+iK1ZZT+6rrIoVg40MP7DZski9GIZP80wORSbt5kJzh9v2x2ev2lxC6VgwMQT0PcgTA== - -"@next/swc-win32-arm64-msvc@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.2.tgz#9c8f60da8e3882c4c66f21747abf944a627d05ff" - integrity sha512-TZSh/48SfcLEQ4rD25VVn2kdIgUWmMflRX3OiyPwGNXn3NiyPqhqei/BaqCYXViIQ+6QsG9R0C8LftMqy8JPMA== - -"@next/swc-win32-ia32-msvc@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.2.tgz#fdb0b5f74e6dc0dcb34b7f7d24775ad034d915e8" - integrity sha512-M0tBVNMEBJN2ZNQWlcekMn6pvLria7Sa2Fai5znm7CCJz4pP3lrvlSxhKdkCerk0D9E0bqx5yAo3o2Q7RrD4gA== - -"@next/swc-win32-x64-msvc@14.2.2": - version "14.2.2" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.2.tgz#95cc0dad2c7ac5177fa6eeab070dccfa30532353" - integrity sha512-a/20E/wtTJZ3Ykv3f/8F0l7TtgQa2LWHU2oNB9bsu0VjqGuGGHmm/q6waoUNQYTVPYrrlxxaHjJcDV6aiSTt/w== - -"@noble/curves@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@radix-ui/number@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.1.tgz#644161a3557f46ed38a042acf4a770e826021674" - integrity sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/primitive@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" - integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-compose-refs@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" - integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-context@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" - integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-direction@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b" - integrity sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-icons@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69" - integrity sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw== - -"@radix-ui/react-presence@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" - integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" - -"@radix-ui/react-primitive@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" - integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-slot" "1.0.2" - -"@radix-ui/react-progress@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.0.3.tgz#8380272fdc64f15cbf263a294dea70a7d5d9b4fa" - integrity sha512-5G6Om/tYSxjSeEdrb1VfKkfZfn/1IlPWd731h2RfPuSbIfNUgfqAwbKfJCg/PP6nuUCTrYzalwHSpSinoWoCag== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - -"@radix-ui/react-scroll-area@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz#01160c6893f24a2ddb5aa399ae5b3ba84ad4d3cc" - integrity sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/number" "1.0.1" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-direction" "1.0.1" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" - -"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" - integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - -"@radix-ui/react-use-callback-ref@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" - integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-use-layout-effect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" - integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@rushstack/eslint-patch@^1.3.3": - version "1.10.2" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz#053f1540703faa81dea2966b768ee5581c66aeda" - integrity sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw== - -"@socket.io/component-emitter@~3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.1.tgz#621270c02c0a5d4f4669eb1caa9723c91cf201de" - integrity sha512-dzJtaDAAoXx4GCOJpbB2eG/Qj8VDpdwkLsWGzGm+0L7E8/434RyMbAHmk9ubXWVAb9nXmc44jUf8GKqVDiKezg== - -"@swc/counter@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== - -"@swc/helpers@0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" - integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== - dependencies: - "@swc/counter" "^0.1.3" - tslib "^2.4.0" - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/node@18.15.13": - version "18.15.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" - integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== - -"@types/node@^20": - version "20.12.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384" - integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg== - dependencies: - undici-types "~5.26.4" - -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== - -"@types/react-dom@^18": - version "18.2.25" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.25.tgz#2946a30081f53e7c8d585eb138277245caedc521" - integrity sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18": - version "18.2.79" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.79.tgz#c40efb4f255711f554d47b449f796d1c7756d865" - integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.2.0.tgz#44356312aea8852a3a82deebdacd52ba614ec07a" - integrity sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg== - dependencies: - "@typescript-eslint/scope-manager" "7.2.0" - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/typescript-estree" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da" - integrity sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg== - dependencies: - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - -"@typescript-eslint/types@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f" - integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA== - -"@typescript-eslint/typescript-estree@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556" - integrity sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA== - dependencies: - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/visitor-keys@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e" - integrity sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A== - dependencies: - "@typescript-eslint/types" "7.2.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -aes-js@4.0.0-beta.5: - version "4.0.0-beta.5" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" - integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -any-promise@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== - -anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" - integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-includes@^3.1.6, array-includes@^3.1.7: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlast@^1.2.4: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" - integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.findlastindex@^1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.toreversed@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" - integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" - integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.1.0" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -ast-types-flow@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" - integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== - -axios@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" - integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== - dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase-css@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" - integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== - -caniuse-lite@^1.0.30001579: - version "1.0.30001612" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz#d34248b4ec1f117b70b24ad9ee04c90e0b8a14ae" - integrity sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g== - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chokidar@^3.5.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -class-variance-authority@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522" - integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A== - dependencies: - clsx "2.0.0" - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -clsx@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" - integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== - -clsx@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" - integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -cross-spawn@^7.0.0, cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -damerau-levenshtein@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" - integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== - -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -didyoumean@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" - integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dlv@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" - integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -engine.io-client@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.3.tgz#4cf6fa24845029b238f83c628916d9149c399bc5" - integrity sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.3.1" - engine.io-parser "~5.2.1" - ws "~8.11.0" - xmlhttprequest-ssl "~2.0.0" - -engine.io-parser@~5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" - integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== - -enhanced-resolve@^5.12.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" - integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" - is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: - version "1.0.18" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz#4d3424f46b24df38d064af6fbbc89274e29ea69d" - integrity sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.3" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.2" - safe-array-concat "^1.1.2" - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-next@14.2.2: - version "14.2.2" - resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.2.tgz#c79f935fa63859303056778b88848b2af0d052ab" - integrity sha512-12/uFc0KX+wUs7EDpOUGKMXBXZJiBVGdK5/m/QgXOCg2mQ0bQWoKSWNrCeOg7Vum6Kw1d1TW453W6xh+GbHquw== - dependencies: - "@next/eslint-plugin-next" "14.2.2" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0" - eslint-import-resolver-node "^0.3.6" - eslint-import-resolver-typescript "^3.5.2" - eslint-plugin-import "^2.28.1" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - -eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.5.2: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== - dependencies: - debug "^3.2.7" - -eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-jsx-a11y@^6.7.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== - dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" - array.prototype.flatmap "^1.3.2" - ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" - damerau-levenshtein "^1.0.8" - emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" - jsx-ast-utils "^3.3.5" - language-tags "^1.0.9" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - -"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react@^7.33.2: - version "7.34.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" - integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlast "^1.2.4" - array.prototype.flatmap "^1.3.2" - array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" - doctrine "^2.1.0" - es-iterator-helpers "^1.0.17" - estraverse "^5.3.0" - jsx-ast-utils "^2.4.1 || ^3.0.0" - minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - object.hasown "^1.1.3" - object.values "^1.1.7" - prop-types "^15.8.1" - resolve "^2.0.0-next.5" - semver "^6.3.1" - string.prototype.matchall "^4.0.10" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -ethers@^6.12.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.12.0.tgz#b0c2ce207ae5a3b5125be966e32ffea7c1f2481a" - integrity sha512-zL5NlOTjML239gIvtVJuaSk0N9GQLi1Hom3ZWUszE5lDTQE/IVB62mrPkQ2W1bGcZwVGSLaetQbWNQSvI4rGDQ== - dependencies: - "@adraffy/ens-normalize" "1.10.1" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== - -follow-redirects@^1.15.6: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.5.0: - version "4.7.3" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.3.tgz#0498163d98f7b58484dd4906999c0c9d5f103f83" - integrity sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg== - dependencies: - resolve-pkg-maps "^1.0.0" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - -glob@^10.3.10: - version "10.3.12" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" - integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.6" - minimatch "^9.0.1" - minipass "^7.0.4" - path-scurry "^1.10.2" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.11, graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -ignore@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== - dependencies: - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== - dependencies: - is-typed-array "^1.1.13" - -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== - dependencies: - call-bind "^1.0.2" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== - dependencies: - call-bind "^1.0.7" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== - dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" - -jackspeak@^2.3.5, jackspeak@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jiti@^1.21.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" - integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - object.assign "^4.1.4" - object.values "^1.1.6" - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -language-subtag-registry@^0.3.20: - version "0.3.22" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== - -language-tags@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" - integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== - dependencies: - language-subtag-registry "^0.3.20" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lilconfig@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== - -lilconfig@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" - integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^9.0.1: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" - integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -mz@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nanoid@^3.3.6, nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -next@14.2.2: - version "14.2.2" - resolved "https://registry.yarnpkg.com/next/-/next-14.2.2.tgz#707311b5e4bf973ada2305233f322bdd0cd9d579" - integrity sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg== - dependencies: - "@next/env" "14.2.2" - "@swc/helpers" "0.5.5" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.2.2" - "@next/swc-darwin-x64" "14.2.2" - "@next/swc-linux-arm64-gnu" "14.2.2" - "@next/swc-linux-arm64-musl" "14.2.2" - "@next/swc-linux-x64-gnu" "14.2.2" - "@next/swc-linux-x64-musl" "14.2.2" - "@next/swc-win32-arm64-msvc" "14.2.2" - "@next/swc-win32-ia32-msvc" "14.2.2" - "@next/swc-win32-x64-msvc" "14.2.2" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-assign@^4.0.1, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" - integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.entries@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" - integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -object.fromentries@^2.0.7: - version "2.0.8" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" - integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.groupby@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" - integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - -object.hasown@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" - integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== - dependencies: - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - -object.values@^1.1.6, object.values@^1.1.7: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.10.1, path-scurry@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" - integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pirates@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss-import@^15.1.0: - version "15.1.0" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" - integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== - dependencies: - postcss-value-parser "^4.0.0" - read-cache "^1.0.0" - resolve "^1.1.7" - -postcss-js@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" - integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== - dependencies: - camelcase-css "^2.0.1" - -postcss-load-config@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" - integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== - dependencies: - lilconfig "^3.0.0" - yaml "^2.3.4" - -postcss-nested@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" - integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== - dependencies: - postcss-selector-parser "^6.0.11" - -postcss-selector-parser@^6.0.11: - version "6.0.16" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" - integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-value-parser@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8, postcss@^8.4.23: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prop-types@^15.8.1: - version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" - integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.13.1" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-dom@^18: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-is@^16.13.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@^18: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -read-cache@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" - integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== - dependencies: - pify "^2.3.0" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.1" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.1.7, resolve@^1.22.2, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^2.0.0-next.5: - version "2.0.0-next.5" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" - integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1, set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -socket.io-client@^4.7.5: - version "4.7.5" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.5.tgz#919be76916989758bdc20eec63f7ee0ae45c05b7" - integrity sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.3.2" - engine.io-client "~6.5.2" - socket.io-parser "~4.2.4" - -socket.io-parser@~4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" - integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.3.1" - -source-map-js@^1.0.2, source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.matchall@^4.0.10: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" - set-function-name "^2.0.2" - side-channel "^1.0.6" - -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-object-atoms "^1.0.0" - -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -sucrase@^3.32.0: - version "3.35.0" - resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" - integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== - dependencies: - "@jridgewell/gen-mapping" "^0.3.2" - commander "^4.0.0" - glob "^10.3.10" - lines-and-columns "^1.1.6" - mz "^2.7.0" - pirates "^4.0.1" - ts-interface-checker "^0.1.9" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tailwind-merge@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.3.0.tgz#27d2134fd00a1f77eca22bcaafdd67055917d286" - integrity sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA== - dependencies: - "@babel/runtime" "^7.24.1" - -tailwindcss-animate@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" - integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== - -tailwindcss@^3.4.1: - version "3.4.3" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.3.tgz#be48f5283df77dfced705451319a5dffb8621519" - integrity sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A== - dependencies: - "@alloc/quick-lru" "^5.2.0" - arg "^5.0.2" - chokidar "^3.5.3" - didyoumean "^1.2.2" - dlv "^1.1.3" - fast-glob "^3.3.0" - glob-parent "^6.0.2" - is-glob "^4.0.3" - jiti "^1.21.0" - lilconfig "^2.1.0" - micromatch "^4.0.5" - normalize-path "^3.0.0" - object-hash "^3.0.0" - picocolors "^1.0.0" - postcss "^8.4.23" - postcss-import "^15.1.0" - postcss-js "^4.0.1" - postcss-load-config "^4.0.1" - postcss-nested "^6.0.1" - postcss-selector-parser "^6.0.11" - resolve "^1.22.2" - sucrase "^3.32.0" - -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thenify-all@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== - dependencies: - thenify ">= 3.1.0 < 4" - -"thenify@>= 3.1.0 < 4": - version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" - integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== - dependencies: - any-promise "^1.0.0" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-api-utils@^1.0.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - -ts-interface-checker@^0.1.9: - version "0.1.13" - resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" - integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== - -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tslib@^2.4.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typescript@^5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -util-deprecate@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" - is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" - is-generator-function "^1.0.10" - is-regex "^1.1.4" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - -which-collection@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== - -xmlhttprequest-ssl@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" - integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^2.3.4: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed" - integrity sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/builder/.dockerignore b/builder/.dockerignore deleted file mode 100644 index 0c013d18b..000000000 --- a/builder/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -**/*_test.go - -build/_workspace -build/_bin -tests/testdata diff --git a/builder/.gitattributes b/builder/.gitattributes deleted file mode 100644 index 0269fab9c..000000000 --- a/builder/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto -*.sol linguist-language=Solidity diff --git a/builder/.github/CODEOWNERS b/builder/.github/CODEOWNERS deleted file mode 100644 index 6cf5893f9..000000000 --- a/builder/.github/CODEOWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# These owners will be the default owners for everything in -# the repo. Unless a later match takes precedence, -# they will be requested for review when someone opens a pull request. -* @dvush @Wazzymandias @TymKh @Ruteri @avalonche diff --git a/builder/.github/CONTRIBUTING.md b/builder/.github/CONTRIBUTING.md deleted file mode 100644 index 969b7f8f9..000000000 --- a/builder/.github/CONTRIBUTING.md +++ /dev/null @@ -1,40 +0,0 @@ -# Contributing - -Thank you for considering to help out with the source code! We welcome -contributions from anyone on the internet, and are grateful for even the -smallest of fixes! - -If you'd like to contribute to go-ethereum, please fork, fix, commit and send a -pull request for the maintainers to review and merge into the main code base. If -you wish to submit more complex changes though, please check up with the core -devs first on [our gitter channel](https://gitter.im/ethereum/go-ethereum) to -ensure those changes are in line with the general philosophy of the project -and/or get some early feedback which can make both your efforts much lighter as -well as our review and merge procedures quick and simple. - -## Coding guidelines - -Please make sure your contributions adhere to our coding guidelines: - - * Code must adhere to the official Go -[formatting](https://golang.org/doc/effective_go.html#formatting) guidelines -(i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). - * Code must be documented adhering to the official Go -[commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. - * Pull requests need to be based on and opened against the `master` branch. - * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" - -## Can I have feature X - -Before you submit a feature request, please check and make sure that it isn't -possible through some other means. The JavaScript-enabled console is a powerful -feature in the right hands. Please check our -[Geth documentation page](https://geth.ethereum.org/docs/) for more info -and help. - -## Configuration, dependencies, and tests - -Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide) -for more details on configuring your environment, managing project dependencies -and testing procedures. diff --git a/builder/.github/ISSUE_TEMPLATE/bug.md b/builder/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 45bfd986a..000000000 --- a/builder/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Report a bug -about: Something with go-ethereum is not working as expected -title: '' -labels: 'type:bug' -assignees: '' ---- - -#### System information - -Geth version: `geth version` -CL client & version: e.g. lighthouse/nimbus/prysm@v1.0.0 -OS & Version: Windows/Linux/OSX -Commit hash : (if `develop`) - -#### Expected behaviour - - -#### Actual behaviour - - -#### Steps to reproduce the behaviour - - -#### Backtrace - -```` -[backtrace] -```` - -When submitting logs: please submit them as text and not screenshots. diff --git a/builder/.github/ISSUE_TEMPLATE/feature.md b/builder/.github/ISSUE_TEMPLATE/feature.md deleted file mode 100644 index aacd885f9..000000000 --- a/builder/.github/ISSUE_TEMPLATE/feature.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -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/builder/.github/ISSUE_TEMPLATE/question.md b/builder/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 8f460ab55..000000000 --- a/builder/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: Ask a question -about: Something is unclear -title: '' -labels: 'type:docs' -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. For general questions please use [discord](https://discord.gg/nthXNEv) or the Ethereum stack exchange at https://ethereum.stackexchange.com. diff --git a/builder/.github/no-response.yml b/builder/.github/no-response.yml deleted file mode 100644 index 903d4ce85..000000000 --- a/builder/.github/no-response.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Number of days of inactivity before an Issue is closed for lack of response -daysUntilClose: 30 -# Label requiring a response -responseRequiredLabel: "need:more-information" -# Comment to post when closing an Issue for lack of response. Set to `false` to disable -closeComment: > - This issue has been automatically closed because there has been no response - to our request for more information from the original author. With only the - information that is currently in the issue, we don't have enough information - to take action. Please reach out if you have more relevant information or - answers to our questions so that we can investigate further. diff --git a/builder/.github/pull_request_template.md b/builder/.github/pull_request_template.md deleted file mode 100644 index 15f903e76..000000000 --- a/builder/.github/pull_request_template.md +++ /dev/null @@ -1,11 +0,0 @@ -## 📠Summary - - - -## 📚 References - - - ---- - -* [ ] I have seen and agree to [`CONTRIBUTING.md`](https://github.com/flashbots/builder/blob/main/CONTRIBUTING.md) diff --git a/builder/.github/stale.yml b/builder/.github/stale.yml deleted file mode 100644 index 6d921cc79..000000000 --- a/builder/.github/stale.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 366 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 42 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security -# Label to use when marking an issue as stale -staleLabel: "status:inactive" -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false diff --git a/builder/.github/workflows/go.yml b/builder/.github/workflows/go.yml deleted file mode 100644 index 80d75bd7f..000000000 --- a/builder/.github/workflows/go.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Go - -on: - push: - branches: [ main ] - pull_request: - -env: - CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__" - CGO_CFLAGS: "-O -D__BLST_PORTABLE__" - -jobs: - - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: ^1.21.4 - id: go - - - name: Check out code into the Go module directory - uses: actions/checkout@v2 - - - name: Install golangci-lint - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2 - - - name: Lint - run: make lint - - - name: Ensure go mod tidy runs without changes - run: | - go mod tidy - git diff-index HEAD - git diff-index --quiet HEAD - - build: - name: Build - runs-on: ubuntu-latest - steps: - - - name: Set up Go 1.x - uses: actions/setup-go@v3 - with: - go-version: 1.21.4 - id: go - - - name: Check out code into the Go module directory - uses: actions/checkout@v2 - - - name: Test - run: go test ./core ./miner/... ./internal/ethapi/... ./builder/... ./eth/block-validation/... - - - name: Build - run: make geth diff --git a/builder/.github/workflows/release.yml b/builder/.github/workflows/release.yml deleted file mode 100644 index 3d056e59c..000000000 --- a/builder/.github/workflows/release.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Release - -on: - push: - tags: - - 'v*' - -jobs: - docker-image: - name: Publish Docker Image - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v2 - - - name: Get tag version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - - name: Print version - run: | - echo $RELEASE_VERSION - echo ${{ env.RELEASE_VERSION }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: flashbots/builder - tags: | - type=sha - type=pep440,pattern={{version}} - type=pep440,pattern={{major}}.{{minor}} - type=raw,value=latest - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.FLASHBOTS_DOCKERHUB_USERNAME }} - password: ${{ secrets.FLASHBOTS_DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v3 - with: - context: . - push: true - build-args: | - VERSION=${{ env.RELEASE_VERSION }} - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - github-release: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v2 - - - name: Create release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - draft: true - prerelease: false diff --git a/builder/.gitignore b/builder/.gitignore deleted file mode 100644 index 7b1908dc5..000000000 --- a/builder/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile ~/.gitignore_global - -/tmp -*/**/*un~ -*/**/*.test -*un~ -.DS_Store -*/**/.DS_Store -.ethtest -*/**/*tx_database* -*/**/*dapps* -build/_vendor/pkg - -#* -.#* -*# -*~ -.project -.settings - -# used by the Makefile -/build/_workspace/ -/build/cache/ -/build/bin/ -/geth*.zip - -# travis -profile.tmp -profile.cov - -# IdeaIDE -.idea - -# VS Code -.vscode - -# dashboard -/dashboard/assets/flow-typed -/dashboard/assets/node_modules -/dashboard/assets/stats.json -/dashboard/assets/bundle.js -/dashboard/assets/bundle.js.map -/dashboard/assets/package-lock.json - -**/yarn-error.log -logs/ -/ofac_blacklist.json -/blacklist.json - -tests/spec-tests/ diff --git a/builder/.gitmodules b/builder/.gitmodules deleted file mode 100644 index 241c169c4..000000000 --- a/builder/.gitmodules +++ /dev/null @@ -1,8 +0,0 @@ -[submodule "tests"] - path = tests/testdata - url = https://github.com/ethereum/tests - shallow = true -[submodule "evm-benchmarks"] - path = tests/evm-benchmarks - url = https://github.com/ipsilon/evm-benchmarks - shallow = true diff --git a/builder/.golangci.yml b/builder/.golangci.yml deleted file mode 100644 index 0343c4b4e..000000000 --- a/builder/.golangci.yml +++ /dev/null @@ -1,60 +0,0 @@ -# This file configures github.com/golangci/golangci-lint. - -run: - timeout: 20m - tests: true - # default is true. Enables skipping of directories: - # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ - skip-dirs-use-default: true - skip-files: - - core/genesis_alloc.go - -linters: - disable-all: true - enable: - - goimports - - gosimple - - govet - - ineffassign - - misspell - - unconvert - - typecheck - - unused - - staticcheck - - bidichk - - durationcheck - - exportloopref - - whitespace - - # - structcheck # lots of false positives - # - errcheck #lot of false positives - # - contextcheck - # - errchkjson # lots of false positives - # - errorlint # this check crashes - # - exhaustive # silly check - # - makezero # false positives - # - nilerr # several intentional - -linters-settings: - gofmt: - simplify: true - -issues: - exclude-rules: - - path: crypto/bn256/cloudflare/optate.go - linters: - - deadcode - - staticcheck - - path: internal/build/pgp.go - text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.' - - path: core/vm/contracts.go - text: 'SA1019: "golang.org/x/crypto/ripemd160" is deprecated: RIPEMD-160 is a legacy hash and should not be used for new applications.' - - path: accounts/usbwallet/trezor.go - text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.' - - path: accounts/usbwallet/trezor/ - text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.' - exclude: - - 'SA1019: event.TypeMux is deprecated: use Feed' - - 'SA1019: strings.Title is deprecated' - - 'SA1019: strings.Title has been deprecated since Go 1.18 and an alternative has been available since Go 1.0: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead.' - - 'SA1029: should not use built-in type string as key for value' diff --git a/builder/.mailmap b/builder/.mailmap deleted file mode 100644 index aa074b76d..000000000 --- a/builder/.mailmap +++ /dev/null @@ -1,237 +0,0 @@ -Aaron Buchwald - -Aaron Kumavis - -Abel Nieto -Abel Nieto - -Afri Schoedon <58883403+q9f@users.noreply.github.com> -Afri Schoedon <5chdn@users.noreply.github.com> <58883403+q9f@users.noreply.github.com> - -Alec Perseghin - -Aleksey Smyrnov - -Alex Leverington -Alex Leverington - -Alex Pozhilenkov -Alex Pozhilenkov - -Alexey Akhunov - -Alon Muroch - -Andrey Petrov -Andrey Petrov - -Arkadiy Paronyan - -Armin Braun - -Aron Fischer - -Austin Roberts -Austin Roberts - -Bas van Kervel -Bas van Kervel -Bas van Kervel -Bas van Kervel - -Boqin Qin -Boqin Qin - -Casey Detrio - -Cheng Li - -Chris Ziogas -Chris Ziogas - -Christoph Jentzsch - -Diederik Loerakker - -Dimitry Khokhlov - -Domino Valdano -Domino Valdano - -Edgar Aroutiounian - -Elliot Shepherd - -Enrique Fynn - -Enrique Fynn -Enrique Fynn - -Ernesto del Toro -Ernesto del Toro - -Everton Fraga - -Felix Lange -Felix Lange - -Frank Wang - -Gary Rong - -Gavin Wood - -Gregg Dourgarian - -Guillaume Ballet -Guillaume Ballet <3272758+gballet@users.noreply.github.com> - -Guillaume Nicolas - -Hanjiang Yu -Hanjiang Yu <42531996+de1acr0ix@users.noreply.github.com> - -Heiko Hees - -Henning Diedrich -Henning Diedrich Drake Burroughs - -Hwanjo Heo <34005989+hwanjo@users.noreply.github.com> - -Iskander (Alex) Sharipov -Iskander (Alex) Sharipov - -Jae Kwon - -JanoÅ¡ GuljaÅ¡ -JanoÅ¡ GuljaÅ¡ Janos Guljas - -Jared Wasinger - -Jason Carver -Jason Carver - -Javier Peletier -Javier Peletier - -Jeffrey Wilcke -Jeffrey Wilcke -Jeffrey Wilcke -Jeffrey Wilcke - -Jens Agerberg - -Joseph Chow -Joseph Chow ethers - - -Joseph Goulden - -Justin Drake - -Kenso Trabing -Kenso Trabing - -Liang Ma -Liang Ma - -Louis Holbrook -Louis Holbrook - -Maran Hidskes - -Marian Oancea - -Martin Becze -Martin Becze - -Martin Lundfall - -Matt Garnett <14004106+lightclient@users.noreply.github.com> - -Matthew Halpern -Matthew Halpern - -Michael Riabzev - -Nchinda Nchinda - -Nick Dodson - -Nick Johnson - -Nick Savers - -Nishant Das -Nishant Das - -Olivier Hervieu - -Pascal Dierich -Pascal Dierich - -RJ Catalano -RJ Catalano - -Ralph Caraveo - -Rene Lubov <41963722+renaynay@users.noreply.github.com> - -Robert Zaremba -Robert Zaremba - -Roman Mandeleil - -Sorin Neacsu -Sorin Neacsu - -Sven Ehlert - -Taylor Gerring -Taylor Gerring - -Thomas Bocek - -Tim Cooijmans - -Valentin Wüstholz -Valentin Wüstholz - -Victor Tran - -Viktor Trón - -Ville Sundell - -Vincent G - -Vitalik Buterin - -Vlad Gluhovsky -Vlad Gluhovsky - -Wenshao Zhong -Wenshao Zhong <11510383@mail.sustc.edu.cn> -Wenshao Zhong <374662347@qq.com> - -Will Villanueva - -Xiaobing Jiang - -Xudong Liu <33193253+r1cs@users.noreply.github.com> - -Yohann LeÌon - -Zachinquarantine -Zachinquarantine - -Ziyuan Zhong - -Zsolt Felföldi - -meowsbits -meowsbits <45600330+meowsbits@users.noreply.github.com> - -nedifi <103940716+nedifi@users.noreply.github.com> - -МакÑим ЧуÑовлÑнов diff --git a/builder/.travis.yml b/builder/.travis.yml deleted file mode 100644 index a55583a70..000000000 --- a/builder/.travis.yml +++ /dev/null @@ -1,168 +0,0 @@ -language: go -go_import_path: github.com/ethereum/go-ethereum -sudo: false -jobs: - allow_failures: - - stage: build - os: osx - env: - - azure-osx - - include: - # These builders create the Docker sub-images for multi-arch push and each - # will attempt to push the multi-arch image if they are the last builder - - stage: build - if: type = push - os: linux - arch: amd64 - dist: bionic - go: 1.21.x - env: - - docker - services: - - docker - git: - submodules: false # avoid cloning ethereum/tests - before_install: - - export DOCKER_CLI_EXPERIMENTAL=enabled - script: - - go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go - - - stage: build - if: type = push - os: linux - arch: arm64 - dist: bionic - go: 1.21.x - env: - - docker - services: - - docker - git: - submodules: false # avoid cloning ethereum/tests - before_install: - - export DOCKER_CLI_EXPERIMENTAL=enabled - script: - - go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go - - # This builder does the Linux Azure uploads - - stage: build - if: type = push - os: linux - dist: bionic - sudo: required - go: 1.21.x - env: - - azure-linux - git: - submodules: false # avoid cloning ethereum/tests - addons: - apt: - packages: - - gcc-multilib - script: - # Build for the primary platforms that Trusty can manage - - go run build/ci.go install -dlgo - - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - go run build/ci.go install -dlgo -arch 386 - - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # Switch over GCC to cross compilation (breaks 386, hence why do it here only) - - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross - - sudo ln -s /usr/include/asm-generic /usr/include/asm - - - GOARM=5 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - GOARM=6 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc - - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - GOARM=7 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabihf-gcc - - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # This builder does the OSX Azure uploads - - stage: build - if: type = push - os: osx - osx_image: xcode14.2 - go: 1.21.x - env: - - azure-osx - git: - submodules: false # avoid cloning ethereum/tests - script: - - go run build/ci.go install -dlgo - - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - go run build/ci.go install -dlgo -arch arm64 - - go run build/ci.go archive -arch arm64 -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - - # These builders run the tests - - stage: build - os: linux - arch: amd64 - dist: bionic - go: 1.21.x - script: - - travis_wait 30 go run build/ci.go test $TEST_PACKAGES - - - stage: build - if: type = pull_request - os: linux - arch: arm64 - dist: bionic - go: 1.20.x - script: - - travis_wait 30 go run build/ci.go test $TEST_PACKAGES - - - stage: build - os: linux - dist: bionic - go: 1.20.x - script: - - travis_wait 30 go run build/ci.go test $TEST_PACKAGES - - # This builder does the Ubuntu PPA nightly uploads - - stage: build - if: type = cron || (type = push && tag ~= /^v[0-9]/) - os: linux - dist: bionic - go: 1.21.x - env: - - ubuntu-ppa - git: - submodules: false # avoid cloning ethereum/tests - addons: - apt: - packages: - - devscripts - - debhelper - - dput - - fakeroot - - python-bzrlib - - python-paramiko - script: - - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts - - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " - - # This builder does the Azure archive purges to avoid accumulating junk - - stage: build - if: type = cron - os: linux - dist: bionic - go: 1.21.x - env: - - azure-purge - git: - submodules: false # avoid cloning ethereum/tests - script: - - go run build/ci.go purge -store gethstore/builds -days 14 - - # This builder executes race tests - - stage: build - if: type = cron - os: linux - dist: bionic - go: 1.21.x - script: - - travis_wait 30 go run build/ci.go test -race $TEST_PACKAGES - diff --git a/builder/AUTHORS b/builder/AUTHORS deleted file mode 100644 index 151c85016..000000000 --- a/builder/AUTHORS +++ /dev/null @@ -1,591 +0,0 @@ -# This is the official list of go-ethereum authors for copyright purposes. - -6543 <6543@obermui.de> -a e r t h -Aaron Buchwald -Abel Nieto -Adam Babik -Adam Schmideg -Aditya -Aditya Arora -Adrià Cidre -Afanasii Kurakin -Afri Schoedon <5chdn@users.noreply.github.com> -Agustin Armellini Fischer -Ahyun -Airead -Alan Chen -Alejandro Isaza -Aleksey Smyrnov -Ales Katona -Alex Beregszaszi -Alex Leverington -Alex Mazalov -Alex Pozhilenkov -Alex Prut <1648497+alexprut@users.noreply.github.com> -Alex Wu -Alexander van der Meij -Alexander Yastrebov -Alexandre Van de Sande -Alexey Akhunov -Alexey Shekhirin -alexwang <39109351+dipingxian2@users.noreply.github.com> -Ali Atiia <42751398+aliatiia@users.noreply.github.com> -Ali Hajimirza -am2rican5 -AmitBRD <60668103+AmitBRD@users.noreply.github.com> -Anatole <62328077+a2br@users.noreply.github.com> -Andrea Franz -Andrei Maiboroda -Andrey Petrov -ANOTHEL -Antoine Rondelet -Antoine Toulme -Anton Evangelatov -Antonio Salazar Cardozo -Arba Sasmoyo -Armani Ferrante -Armin Braun -Aron Fischer -atsushi-ishibashi -Austin Roberts -ayeowch -b00ris -b1ackd0t -bailantaotao -baizhenxuan -Balaji Shetty Pachai <32358081+balajipachai@users.noreply.github.com> -Balint Gabor -baptiste-b-pegasys <85155432+baptiste-b-pegasys@users.noreply.github.com> -Bas van Kervel -Benjamin Brent -benma -Benoit Verkindt -Binacs -bloonfield -Bo -Bo Ye -Bob Glickstein -Boqin Qin -Brandon Harden -Brent -Brian Schroeder -Bruno Å kvorc -C. Brown -Caesar Chad -Casey Detrio -CDsigma -Ceelog -Ceyhun Onur -chabashilah -changhong -Chase Wright -Chen Quan -Cheng Li -chenglin <910372762@qq.com> -chenyufeng -Chris Pacia -Chris Ziogas -Christian Muehlhaeuser -Christoph Jentzsch -chuwt -cong -Connor Stein -Corey Lin <514971757@qq.com> -courtier -cpusoft -Crispin Flowerday -croath -cui <523516579@qq.com> -Dan DeGreef -Dan Kinsley -Dan Sosedoff -Daniel A. Nagy -Daniel Perez -Daniel Sloof -Darioush Jalali -Darrel Herbst -Dave Appleton -Dave McGregor -David Cai -David Huie -Denver -Derek Chiang -Derek Gottfrid -Di Peng -Diederik Loerakker -Diego Siqueira -Diep Pham -dipingxian2 <39109351+dipingxian2@users.noreply.github.com> -divergencetech <94644849+divergencetech@users.noreply.github.com> -dm4 -Dmitrij Koniajev -Dmitry Shulyak -Dmitry Zenovich -Domino Valdano -Dragan Milic -dragonvslinux <35779158+dragononcrypto@users.noreply.github.com> -Edgar Aroutiounian -Eduard S -Egon Elbre -Elad -Eli -Elias Naur -Elliot Shepherd -Emil -emile -Emmanuel T Odeke -Eng Zer Jun -Enrique Fynn -Enrique Ortiz -EOS Classic -Erichin -Ernesto del Toro -Ethan Buchman -ethersphere -Eugene Lepeico -Eugene Valeyev -Evangelos Pappas -Everton Fraga -Evgeny -Evgeny Danilenko <6655321@bk.ru> -evgk -Evolution404 <35091674+Evolution404@users.noreply.github.com> -EXEC -Fabian Vogelsteller -Fabio Barone -Fabio Berger -FaceHo -Felipe Strozberg <48066928+FelStroz@users.noreply.github.com> -Felix Lange -Ferenc Szabo -ferhat elmas -Ferran Borreguero -Fiisio -Fire Man <55934298+basdevelop@users.noreply.github.com> -flowerofdream <775654398@qq.com> -fomotrader <82184770+fomotrader@users.noreply.github.com> -ForLina <471133417@qq.com> -Frank Szendzielarz <33515470+FrankSzendzielarz@users.noreply.github.com> -Frank Wang -Franklin -Furkan KAMACI -Fuyang Deng -GagziW -Gary Rong -Gautam Botrel -George Ornbo -Giuseppe Bertone -Greg Colvin -Gregg Dourgarian -Gregory Markou <16929357+GregTheGreek@users.noreply.github.com> -Guifel -Guilherme Salgado -Guillaume Ballet -Guillaume Nicolas -GuiltyMorishita -Guruprasad Kamath <48196632+gurukamath@users.noreply.github.com> -Gus -Gustav Simonsson -Gísli Kristjánsson -Ha ÄANG -HackyMiner -hadv -Hanjiang Yu -Hao Bryan Cheng -Hao Duan -HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> -Harry Dutton -haryu703 <34744512+haryu703@users.noreply.github.com> -Hendrik Hofstadt -Henning Diedrich -henopied <13500516+henopied@users.noreply.github.com> -hero5512 -holisticode -Hongbin Mao -Hsien-Tang Kao -hsyodyssey <47173566+hsyodyssey@users.noreply.github.com> -Husam Ibrahim <39692071+HusamIbrahim@users.noreply.github.com> -Hwanjo Heo <34005989+hwanjo@users.noreply.github.com> -hydai -Hyung-Kyu Hqueue Choi -HÃ¥vard Anda Estensen -Ian Macalinao -Ian Norden -icodezjb -Ikko Ashimine -Ilan Gitter <8359193+gitteri@users.noreply.github.com> -ImanSharaf <78227895+ImanSharaf@users.noreply.github.com> -Isidoro Ghezzi -Iskander (Alex) Sharipov -Ivan Bogatyy -Ivan Daniluk -Ivo Georgiev -jacksoom -Jae Kwon -James Prestwich <10149425+prestwich@users.noreply.github.com> -Jamie Pitts -JanoÅ¡ GuljaÅ¡ -Jared Wasinger -Jason Carver -Javier Peletier -Javier Sagredo -Jay -Jay Guo -Jaynti Kanani -Jeff Prestes -Jeff R. Allen -Jeff Wentworth -Jeffery Robert Walsh -Jeffrey Wilcke -Jens Agerberg -Jeremy McNevin -Jeremy Schlatter -Jerzy Lasyk -Jesse Tane -Jia Chenhui -Jim McDonald -jk-jeongkyun <45347815+jeongkyun-oh@users.noreply.github.com> -jkcomment -JoeGruffins <34998433+JoeGruffins@users.noreply.github.com> -Joel Burget -John C. Vernaleo -John Difool -Johns Beharry -Jonas -Jonathan Brown -Jonathan Chappelow -Jonathan Gimeno -JoranHonig -Jordan Krage -Jorropo -Joseph Chow -Joshua Colvin -Joshua Gutow -jovijovi -jtakalai -JU HYEONG PARK -Julian Y -Justin Clark-Casey -Justin Drake -Justus -Kawashima <91420903+sscodereth@users.noreply.github.com> -ken10100147 -Kenji Siu -Kenso Trabing -Kevin -kevin.xu -KibGzr -kiel barry -kilic -kimmylin <30611210+kimmylin@users.noreply.github.com> -Kitten King <53072918+kittenking@users.noreply.github.com> -knarfeh -Kobi Gurkan -komika -Konrad Feldmeier -Kris Shinn -Kristofer Peterson -Kumar Anirudha -Kurkó Mihály -Kushagra Sharma -Kwuaint <34888408+kwuaint@users.noreply.github.com> -Kyuntae Ethan Kim -Lee Bousfield -Lefteris Karapetsas -Leif Jurvetson -Leo Shklovskii -LeoLiao -Lewis Marshall -lhendre -Li Dongwei -Liang Ma -Liang ZOU -libby kent -libotony -LieutenantRoger -ligi -LioæŽæ¬§ -lmittmann -Lorenzo Manacorda -Louis Holbrook -Luca Zeug -Lucas Hendren -lzhfromustc <43191155+lzhfromustc@users.noreply.github.com> -Magicking -manlio -Maran Hidskes -Marek Kotewicz -Mariano Cortesi -Marius van der Wijden -Mark -Mark Rushakoff -mark.lin -Martin Alex Philip Dawson -Martin Holst Swende -Martin Klepsch -Martin Lundfall -Martin Michlmayr -Martin Redmond <21436+reds@users.noreply.github.com> -Mason Fischer -Mateusz Morusiewicz <11313015+Ruteri@users.noreply.github.com> -Mats Julian Olsen -Matt Garnett <14004106+lightclient@users.noreply.github.com> -Matt K <1036969+mkrump@users.noreply.github.com> -Matthew Di Ferrante -Matthew Halpern -Matthew Wampler-Doty -Max Sistemich -Maxim Zhiburt -Maximilian Meister -me020523 -Melvin Junhee Woo -meowsbits -Micah Zoltu -Michael Forney -Michael Riabzev -Michael Ruminer -michael1011 -Miguel Mota -Mike Burr -Mikhail Mikheev -milesvant -Miro -Miya Chen -Mohanson -mr_franklin -Mudit Gupta -Mymskmkt <1847234666@qq.com> -Nalin Bhardwaj -Natsu Kagami -Nchinda Nchinda -nebojsa94 -necaremus -nedifi <103940716+nedifi@users.noreply.github.com> -needkane <604476380@qq.com> -Nguyen Kien Trung -Nguyen Sy Thanh Son -Nic Jansma -Nick Dodson -Nick Johnson -Nicolas Feignon -Nicolas Guillaume -Nikita Kozhemyakin -Nikola Madjarevic -Nilesh Trivedi -Nimrod Gutman -Nishant Das -njupt-moon <1015041018@njupt.edu.cn> -nkbai -noam-alchemy <76969113+noam-alchemy@users.noreply.github.com> -nobody -Noman -nujabes403 -Nye Liu -Oleg Kovalov -Oli Bye -Oliver Tale-Yazdi -Olivier Hervieu -Or Neeman -Osoro Bironga -Osuke -Pantelis Peslis -Pascal Dierich -Patrick O'Grady -Pau -Paul Berg -Paul Litvak -Paul-Armand Verhaegen -Paulo L F Casaretto -PaweÅ‚ Bylica -Pedro Gomes -Pedro Pombeiro -Peter Broadhurst -peter cresswell -Peter Pratscher -Peter Simard -Petr Mikusek -Philip Schlump -Pierre Neter -Pierre R -piersy -PilkyuJung -Piotr Dyraga -ploui <64719999+ploui@users.noreply.github.com> -Preston Van Loon -Prince Sinha -Péter Szilágyi -qd-ethan <31876119+qdgogogo@users.noreply.github.com> -Qian Bin -Quest Henkart -Rachel Franks -Rafael Matias -Raghav Sood -Ralph Caraveo -Ramesh Nair -rangzen -reinerRubin -Rene Lubov <41963722+renaynay@users.noreply.github.com> -rhaps107 -Ricardo Catalinas Jiménez -Ricardo Domingos -Richard Hart -Rick -RJ Catalano -Rob -Rob Mulholand -Robert Zaremba -Roc Yu -Roman Mazalov <83914728+gopherxyz@users.noreply.github.com> -Ross <9055337+Chadsr@users.noreply.github.com> -Runchao Han -Russ Cox -Ryan Schneider -ryanc414 -Rémy Roy -S. Matthew English -salanfe -Sam <39165351+Xia-Sam@users.noreply.github.com> -Sammy Libre <7374093+sammy007@users.noreply.github.com> -Samuel Marks -sanskarkhare -Sarlor -Sasuke1964 -Satpal <28562234+SatpalSandhu61@users.noreply.github.com> -Saulius Grigaitis -Sean -Serhat Åževki Dinçer -Shane Bammel -shawn <36943337+lxex@users.noreply.github.com> -shigeyuki azuchi -Shihao Xia -Shiming -Shintaro Kaneko -shiqinfeng1 <150627601@qq.com> -Shuai Qi -Shude Li -Shunsuke Watanabe -silence -Simon Jentzsch -Sina Mahmoodi <1591639+s1na@users.noreply.github.com> -sixdays -SjonHortensius -Slava Karpenko -slumber1122 -Smilenator -soc1c -Sorin Neacsu -Sparty -Stein Dekker -Steve Gattuso -Steve Ruckdashel -Steve Waldman -Steven E. Harris -Steven Roose -stompesi -stormpang -sunxiaojun2014 -Suriyaa Sundararuban -Sylvain Laurent -Taeik Lim -tamirms -Tangui Clairet -Tatsuya Shimoda -Taylor Gerring -TColl <38299499+TColl@users.noreply.github.com> -terasum -tgyKomgo <52910426+tgyKomgo@users.noreply.github.com> -Thad Guidry -Thomas Bocek -thomasmodeneis -thumb8432 -Ti Zhou -tia-99 <67107070+tia-99@users.noreply.github.com> -Tim Cooijmans -Tobias Hildebrandt <79341166+tobias-hildebrandt@users.noreply.github.com> -Tosh Camille -tsarpaul -Tyler Chambers <2775339+tylerchambers@users.noreply.github.com> -tzapu -ucwong -uji <49834542+uji@users.noreply.github.com> -ult-bobonovski -Valentin Trinqué -Valentin Wüstholz -Vedhavyas Singareddi -Victor Farazdagi -Victor Tran -Vie -Viktor Trón -Ville Sundell -vim88 -Vincent G -Vincent Serpoul -Vinod Damle -Vitalik Buterin -Vitaly Bogdanov -Vitaly V -Vivek Anand -Vlad Bokov -Vlad Gluhovsky -Ward Bradt -Water <44689567+codeoneline@users.noreply.github.com> -wbt -weimumu <934657014@qq.com> -Wenbiao Zheng -Wenshao Zhong -Will Villanueva -William Morriss -William Setzer -williambannas -wuff1996 <33193253+wuff1996@users.noreply.github.com> -Wuxiang -Xiaobing Jiang -xiekeyang -xincaosu -xinluyin <31590468+xinluyin@users.noreply.github.com> -Xudong Liu <33193253+r1cs@users.noreply.github.com> -xwjack -yahtoo -Yang Hau -YaoZengzeng -YH-Zhou -Yihau Chen -Yohann LeÌon -Yoichi Hirai -Yole <007yuyue@gmail.com> -Yondon Fu -YOSHIDA Masanori -yoza -yumiel yoomee1313 -Yusup -yutianwu -ywzqwwt <39263032+ywzqwwt@users.noreply.github.com> -zaccoding -Zach -Zachinquarantine -zah -Zahoor Mohamed -Zak Cole -zcheng9 -zer0to0ne <36526113+zer0to0ne@users.noreply.github.com> -zgfzgf <48779939+zgfzgf@users.noreply.github.com> -Zhang Zhuo -zhangsoledad <787953403@qq.com> -zhaochonghe <41711151+zhaochonghe@users.noreply.github.com> -Zhenguo Niu -zhiqiangxu <652732310@qq.com> -Zhou Zhiyao -Ziyuan Zhong -Zoe Nolan -Zou Guangxian -Zsolt Felföldi -Åukasz Kurowski -Åukasz Zimnoch -ΞTHΞЯSPHΞЯΞ <{viktor.tron,nagydani,zsfelfoldi}@gmail.com> -МакÑим ЧуÑовлÑнов -大彬 -沉风 -è´ºé¹é£ž -陈佳 -유용환 <33824408+eric-yoo@users.noreply.github.com> diff --git a/builder/CONTRIBUTING.md b/builder/CONTRIBUTING.md deleted file mode 100644 index 4e9f4bb97..000000000 --- a/builder/CONTRIBUTING.md +++ /dev/null @@ -1,39 +0,0 @@ -# Contributing guide - -Welcome to the Flashbots collective! - -Thanks for your help improving the project! We are so happy to have you! We just ask you to be nice when you play with us. - -Please start by reading our [license agreement](#individual-contributor-license-agreement) below, and our [code of conduct](CODE_OF_CONDUCT.md). - -## Code style - -Start by making sure that your code is readable, consistent, and pretty. -Follow the [Clean Code](https://flashbots.notion.site/Clean-Code-13016c5c7ca649fba31ae19d797d7304) recommendations. - -## Send a pull request - -- Your proposed changes should be first described and discussed in an issue. -- Open the branch in a personal fork, not in the team repository. -- Every pull request should be small and represent a single change. If the problem is complicated, split it in multiple issues and pull requests. -- Every pull request should be covered by unit tests. - -We appreciate you, friend <3. - ---- - -# Individual Contributor License Agreement - -This text is adapted from Google's contributors license agreement: https://cla.developers.google.com/about/google-individual - -You accept and agree to the following terms and conditions for Your present and future Contributions submitted to Flashbots. Except for the license granted herein to Flashbots and recipients of software distributed by Flashbots, You reserve all right, title, and interest in and to Your Contributions. -1. Definitions. - * "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with Flashbots. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - * "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to Flashbots for inclusion in, or documentation of, any of the products owned or managed by Flashbots (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to Flashbots or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Flashbots for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." -2. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to Flashbots and to recipients of software distributed by Flashbots a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works, under the terms of the license which the project is using on the Submission Date. -3. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to Flashbots and to recipients of software distributed by Flashbots a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. -4. You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to Flashbots, or that your employer has executed a separate Corporate CLA with Flashbots. -5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions. -6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. -7. Should You wish to submit work that is not Your original creation, You may submit it to Flashbots separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". -8. You agree to notify Flashbots of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. \ No newline at end of file diff --git a/builder/COPYING b/builder/COPYING deleted file mode 100644 index f288702d2..000000000 --- a/builder/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - 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 -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. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -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. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -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. - - 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 -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. - - 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 -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 -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 -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 -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -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/builder/COPYING.LESSER b/builder/COPYING.LESSER deleted file mode 100644 index 65c5ca88a..000000000 --- a/builder/COPYING.LESSER +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/builder/Dockerfile b/builder/Dockerfile deleted file mode 100644 index c808c9d94..000000000 --- a/builder/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# Support setting various labels on the final image -ARG COMMIT="" -ARG VERSION="" -ARG BUILDNUM="" - -# Build Geth in a stock Go builder container -FROM golang:1.22-alpine AS builder - -RUN apk add --no-cache gcc musl-dev linux-headers git - -# Get dependencies - will also be cached if we won't change go.mod/go.sum -COPY go.mod /go-ethereum/ -COPY go.sum /go-ethereum/ -RUN cd /go-ethereum && go mod download - -ADD . /go-ethereum -RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth - -# Pull Geth into a second stage deploy alpine container -FROM alpine:latest - -RUN apk add --no-cache ca-certificates -COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/ - -EXPOSE 8545 8546 30303 30303/udp -ENTRYPOINT ["geth"] - -# Add some metadata labels to help programatic image consumption -ARG COMMIT="" -ARG VERSION="" -ARG BUILDNUM="" - -LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM" diff --git a/builder/Dockerfile.alltools b/builder/Dockerfile.alltools deleted file mode 100644 index ddffb8ee1..000000000 --- a/builder/Dockerfile.alltools +++ /dev/null @@ -1,32 +0,0 @@ -# Support setting various labels on the final image -ARG COMMIT="" -ARG VERSION="" -ARG BUILDNUM="" - -# Build Geth in a stock Go builder container -FROM golang:1.22-alpine AS builder - -RUN apk add --no-cache gcc musl-dev linux-headers git - -# Get dependencies - will also be cached if we won't change go.mod/go.sum -COPY go.mod /go-ethereum/ -COPY go.sum /go-ethereum/ -RUN cd /go-ethereum && go mod download - -ADD . /go-ethereum -RUN cd /go-ethereum && go run build/ci.go install -static - -# Pull all binaries into a second stage deploy alpine container -FROM alpine:latest - -RUN apk add --no-cache ca-certificates -COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/ - -EXPOSE 8545 8546 30303 30303/udp - -# Add some metadata labels to help programatic image consumption -ARG COMMIT="" -ARG VERSION="" -ARG BUILDNUM="" - -LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM" diff --git a/builder/Makefile b/builder/Makefile deleted file mode 100644 index cd6c395b1..000000000 --- a/builder/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# This Makefile is meant to be used by people that do not usually work -# with Go source code. If you know what GOPATH is then you probably -# don't need to bother with make. - -.PHONY: geth android ios evm all test clean - -GOBIN = ./build/bin -GO ?= latest -GORUN = go run - -#? geth: Build geth -geth: - $(GORUN) build/ci.go install ./cmd/geth - @echo "Done building." - @echo "Run \"$(GOBIN)/geth\" to launch geth." - -#? all: Build all packages and executables -all: - $(GORUN) build/ci.go install - -#? test: Run the tests -test: all - $(GORUN) build/ci.go test - -#? lint: Run certain pre-selected linters -lint: ## Run linters. - $(GORUN) build/ci.go lint - -fmt: - go fmt - go mod tidy - -clean: - go clean -cache - rm -fr build/_workspace/pkg/ $(GOBIN)/* - -# The devtools target installs tools required for 'go generate'. -# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'. - -#? devtools: Install recommended developer tools -devtools: - env GOBIN= go install golang.org/x/tools/cmd/stringer@latest - env GOBIN= go install github.com/fjl/gencodec@latest - env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest - env GOBIN= go install ./cmd/abigen - @type "solc" 2> /dev/null || echo 'Please install solc' - @type "protoc" 2> /dev/null || echo 'Please install protoc' - -#? help: Get more info on make commands. -help: Makefile - @echo " Choose a command run in go-ethereum:" - @sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /' -.PHONY: help diff --git a/builder/README.md b/builder/README.md deleted file mode 100644 index 1c8148421..000000000 --- a/builder/README.md +++ /dev/null @@ -1,283 +0,0 @@ -[geth readme](README.original.md) - -# Flashbots Block Builder - -This project implements the Flashbots block builder, based on go-ethereum (geth). - -See also: https://docs.flashbots.net/flashbots-mev-boost/block-builders - -Run on your favorite network, including Mainnet, Goerli, Sepolia and local devnet. Instructions for running a pos local devnet can be found [here](https://github.com/avalonche/eth-pos-devnet). - -You will need to run a modified beacon node that sends a custom rpc call to trigger block building. You can use the modified [prysm fork](https://github.com/flashbots/prysm) for this. - -Test with [mev-boost](https://github.com/flashbots/mev-boost) and [mev-boost test cli](https://github.com/flashbots/mev-boost/tree/main/cmd/test-cli). - -Building `geth` requires both a Go (version 1.19 or later) and a C compiler. You can install -them using your favourite package manager. Once the dependencies are installed, run - -## How it works - -* Builder polls relay for the proposer registrations for the next epoch when block building is triggered -* If both local relay and remote relay are enabled, local relay will overwrite remote relay data. This is only meant for the testnets! - -## Limitations - -* Does not accept external blocks -* Does not have payload cache, only the latest block is available - -# Usage - -Configure geth for your network, it will become the block builder. - -Builder-related options: -``` -$ geth --help - - BUILDER - - --builder (default: false) - Enable the builder - - --builder.algotype value (default: "mev-geth") - Block building algorithm to use [=mev-geth] (mev-geth, greedy, greedy-buckets) - - --builder.beacon_endpoints value (default: "http://127.0.0.1:5052") - Comma separated list of beacon endpoints to connect to for beacon chain data - [$BUILDER_BEACON_ENDPOINTS] - - --builder.bellatrix_fork_version value (default: "0x02000000") - Bellatrix fork version. [$BUILDER_BELLATRIX_FORK_VERSION] - - --builder.blacklist value - Path to file containing blacklisted addresses, json-encoded list of strings. - Builder will ignore transactions that touch mentioned addresses. - - --builder.block_resubmit_interval value (default: "500ms") - Determines the interval at which builder will resubmit block submissions - [$FLASHBOTS_BUILDER_RATE_LIMIT_RESUBMIT_INTERVAL] - - --builder.cancellations (default: false) - Enable cancellations for the builder - - --builder.discard_revertible_tx_on_error (default: false) - When enabled, if a transaction submitted as part of a bundle in a send bundle - request has error on commit, and its hash is specified as one that can revert in - the request body, the builder will discard the hash of the failed transaction - from the submitted bundle.For additional details on the structure of the request - body, see - https://docs.flashbots.net/flashbots-mev-share/searchers/understanding-bundles#bundle-definition - [$FLASHBOTS_BUILDER_DISCARD_REVERTIBLE_TX_ON_ERROR] - - --builder.dry-run (default: false) - Builder only validates blocks without submission to the relay - - --builder.genesis_fork_version value (default: "0x00000000") - Gensis fork version. [$BUILDER_GENESIS_FORK_VERSION] - - --builder.genesis_validators_root value (default: "0x0000000000000000000000000000000000000000000000000000000000000000") - Genesis validators root of the network. [$BUILDER_GENESIS_VALIDATORS_ROOT] - - --builder.ignore_late_payload_attributes (default: false) - Builder will ignore all but the first payload attributes. Use if your CL sends - non-canonical head updates. - - --builder.listen_addr value (default: ":28545") - Listening address for builder endpoint [$BUILDER_LISTEN_ADDR] - - --builder.local_relay (default: false) - Enable the local relay - - --builder.no_bundle_fetcher (default: false) - Disable the bundle fetcher - - --builder.price_cutoff_percent value (default: 50) - flashbots - The minimum effective gas price threshold used for bucketing - transactions by price. For example if the top transaction in a list has an - effective gas price of 1000 wei and price_cutoff_percent is 10 (i.e. 10%), then - the minimum effective gas price included in the same bucket as the top - transaction is (1000 * 10%) = 100 wei. - NOTE: This flag is only used when - builder.algotype=greedy-buckets [$FLASHBOTS_BUILDER_PRICE_CUTOFF_PERCENT] - - --builder.rate_limit_duration value (default: "500ms") - Determines rate limit of events processed by builder. For example, a value of - "500ms" denotes that the builder processes events every 500ms. A duration string - is a possibly signed sequence of decimal numbers, each with optional fraction - and a unit suffix, such as "300ms", "-1.5h" or "2h45m" - [$FLASHBOTS_BUILDER_RATE_LIMIT_DURATION] - - --builder.rate_limit_max_burst value (default: 10) - Determines the maximum number of burst events the builder can accommodate at any - given point in time. [$FLASHBOTS_BUILDER_RATE_LIMIT_MAX_BURST] - - --builder.relay_secret_key value (default: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11") - Builder local relay API key used for signing headers [$BUILDER_RELAY_SECRET_KEY] - - --builder.remote_relay_endpoint value - Relay endpoint to connect to for validator registration data, if not provided - will expose validator registration locally [$BUILDER_REMOTE_RELAY_ENDPOINT] - - --builder.secondary_remote_relay_endpoints value - Comma separated relay endpoints to connect to for validator registration data - missing from the primary remote relay, and to push blocks for registrations - missing from or matching the primary [$BUILDER_SECONDARY_REMOTE_RELAY_ENDPOINTS] - - --builder.seconds_in_slot value (default: 12) - Set the number of seconds in a slot in the local relay - - --builder.secret_key value (default: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11") - Builder key used for signing blocks [$BUILDER_SECRET_KEY] - - --builder.slots_in_epoch value (default: 32) - Set the number of slots in an epoch in the local relay - - --builder.submission_offset value (default: 3s) - Determines the offset from the end of slot time that the builder will submit - blocks. For example, if a slot is 12 seconds long, and the offset is 2 seconds, - the builder will submit blocks at 10 seconds into the slot. - [$FLASHBOTS_BUILDER_SUBMISSION_OFFSET] - - --builder.validation_blacklist value - Path to file containing blacklisted addresses, json-encoded list of strings - - --builder.validation_use_balance_diff (default: false) - Block validation API will use fee recipient balance difference for profit - calculation. - - --builder.validator_checks (default: false) - Enable the validator checks - - MINER - - --miner.algotype value (default: "mev-geth") - [NOTE: Deprecated, please use builder.algotype instead] Block building algorithm - to use [=mev-geth] (mev-geth, greedy, greedy-buckets) - - --miner.blocklist value - [NOTE: Deprecated, please use builder.blacklist] flashbots - Path to JSON file with - list of blocked addresses. Miner will ignore txs that touch mentioned addresses. - - --miner.extradata value - Block extra data set by the miner (default = client version) - - --miner.price_cutoff_percent value (default: 50) - flashbots - The minimum effective gas price threshold used for bucketing - transactions by price. For example if the top transaction in a list has an - effective gas price of 1000 wei and price_cutoff_percent is 10 (i.e. 10%), then - the minimum effective gas price included in the same bucket as the top - transaction is (1000 * 10%) = 100 wei. - NOTE: This flag is only used when - miner.algotype=greedy-buckets - - METRICS - - --metrics.builder value (default: false) - Enable builder metrics collection and reporting -``` - -Environment variables: -``` -BUILDER_TX_SIGNING_KEY - private key of the builder used to sign payment transaction, must be the same as the coinbase address - -FLASHBOTS_BUILDER_RATE_LIMIT_DURATION - determines rate limit of events processed by builder; a duration string is a -possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". - -FLASHBOTS_BUILDER_RATE_LIMIT_MAX_BURST - determines the maximum number of events the builder can accommodate at any point in time - -FLASHBOTS_BUILDER_RATE_LIMIT_RESUBMIT_INTERVAL - determines the interval at which builder will resubmit block submissions -``` - -## Metrics - -To enable metrics on the builder you will need to enable metrics with the flags `--metrics --metrics.addr 127.0.0.1 --metrics.builder` which will run -a metrics server serving at `127.0.0.1:6060/debug/metrics`. This will record performance metrics such as block profit and block building times. -The full list of metrics can be found in `miner/metrics.go`. - -See the [metrics docs](https://geth.ethereum.org/docs/monitoring/metrics) for geth for more documentation. - -## Blacklisting addresses - -If you want to reject transactions interacting with certain addresses, save the addresses in json file with an array of strings. Deciding whether to use such a list, as well as maintaining it, is your own responsibility. - -- for block building and validation, use `--builder.blacklist` - --- - -## Details of the implementation - -There are two parts of the builder. - -1. `./builder` responsible for communicating with the relay -2. `./miner` responsible for producing blocks - -### `builder` module - -Main logic of the builder is in the `builder.go` file. - -Builder is driven by the consensus client SSE events that sends payload attribute events, triggering the `OnPayloadAttribute` call. -After requesting additional validator data from the relay builder starts building job with `runBuildingJob`. -Building job continuously makes a request to the `miner` with the correct parameters and submits produced block. - -* Builder retries build block requests every second on average. -* If the job is running but a new one is submitted for a different slot we cancel previous job. -* All jobs have 12s deadline. -* If new request is submitted for the same slot as before but with different parameters, we run these jobs in parallel. - It is possible to receive multiple requests from CL for the same slot but for different parent blocks if there is a possibility - of a missed block. -* All submissions to the relay are rate limited at 2 req/s -* Only blocks that have more profit than the previous best submissions for the particular job are submitted. - -Additional features of the builder: -* Builder can submit data about build blocks to the database. It stores block data, included bundles, and all considered bundles. - Implemented in `flashbotsextra.IDatabaseService`. -* It's possible to run local relay in the same process -* It can validate blocks instead of submitting them to the relay. (see `--builder.dry-run`) - -### `miner` module - -Miner is responsible for block creation. Request from the `builder` is routed to the `worker.go` where -`generateWork` does the job of creating a block. - -* Coinbase of the block is set to the address of the block proposer, fee recipient of the validator receives its eth - in the last tx in the block. -* We reserve gas for the proposer payment using `proposerTxPrepare` and commit proposer payment after txs are added with - `proposerTxCommit`. We do it in a way so all fees received by the block builder are sent to the fee recipient. -* Transaction insertion is done in `fillTransactionsAlgoWorker` \ `fillTransactions`. Depending on the algorithm selected. - Algo worker (greedy) inserts bundles whenever they belong in the block by effective gas price but default method inserts bundles on top of the block. - (see `--miner.algotype`) -* Worker is also responsible for simulating bundles. Bundles are simulated in parallel and results are cached for the particular parent block. -* `algo_greedy.go` implements logic of the block building. Bundles and transactions are sorted in the order of effective gas price then - we try to insert everything into to block until gas limit is reached. Failing bundles are reverted during the insertion but txs are not. -* Builder can filter transactions touching a particular set of addresses. - If a bundle or transaction touches one of the addresses it is skipped. (see `--builder.blacklist` flag) - -## Bundle Movement - -There are two ways bundles are moved to builders - -1. via API -`sendBundle` -2. via Database - `flashbotsextra.IDatabaseService` - -### `fetcher` service -* Fetcher service is part of `flashbotsextra.IDatabaseService` which is responsible for fetching the bundles from db and pushing into mev bundles queue which will be processed by builder. -* Fetcher is a background process which fetches high priority and low priority bundles from db. -* Fetcher fetches `500` high priority bundles on every head change, and `100` low priority bundles in the interval of every `2 seconds`. - -## Block builder diagram - -![block builder diagram](docs/builder/builder-diagram.png "Block builder diagram") - ---- - -# Security - -If you find a security vulnerability in this project or any other initiative -related to proposer/builder separation in Ethereum, please let us know sending -an email to security@flashbots.net. - ---- - -# License - -The code in this project is free software under the [LGPL License](COPYING.LESSER). - diff --git a/builder/README.original.md b/builder/README.original.md deleted file mode 100644 index 584273e31..000000000 --- a/builder/README.original.md +++ /dev/null @@ -1,380 +0,0 @@ -## Go Ethereum - -Official Golang execution layer implementation of the Ethereum protocol. - -[![API Reference]( -https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 -)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc) -[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum) -[![Travis](https://travis-ci.com/ethereum/go-ethereum.svg?branch=master)](https://travis-ci.com/ethereum/go-ethereum) -[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv) - -Automated builds are available for stable releases and the unstable master branch. Binary -archives are published at https://geth.ethereum.org/downloads/. - -## Building the source - -For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth). - -Building `geth` requires both a Go (version 1.18 or later) and a C compiler. You can install -them using your favourite package manager. Once the dependencies are installed, run - -```shell -make geth -``` - -or, to build the full suite of utilities: - -```shell -make all -``` - -## Executables - -The go-ethereum project comes with several wrappers/executables found in the `cmd` -directory. - -| Command | Description | -| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/interface/command-line-options) for command line options. | -| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. | -| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. | -| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/dapp/native-bindings) page for details. | -| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. | -| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). | -| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). | - -## Running `geth` - -Going through all the possible command line flags is out of scope here (please consult our -[CLI Wiki page](https://geth.ethereum.org/docs/interface/command-line-options)), -but we've enumerated a few common parameter combos to get you up to speed quickly -on how you can run your own `geth` instance. - -### Hardware Requirements - -Minimum: - -* CPU with 2+ cores -* 4GB RAM -* 1TB free storage space to sync the Mainnet -* 8 MBit/sec download Internet service - -Recommended: - -* Fast CPU with 4+ cores -* 16GB+ RAM -* High-performance SSD with at least 1TB of free space -* 25+ MBit/sec download Internet service - -### Full node on the main Ethereum network - -By far the most common scenario is people wanting to simply interact with the Ethereum -network: create accounts; transfer funds; deploy and interact with contracts. For this -particular use case, the user doesn't care about years-old historical data, so we can -sync quickly to the current state of the network. To do so: - -```shell -$ geth console -``` - -This command will: - * Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag), - causing it to download more data in exchange for avoiding processing the entire history - of the Ethereum network, which is very CPU intensive. - * Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interface/javascript-console), - (via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md) - (note: the `web3` version bundled within `geth` is very old, and not up to date with official docs), - as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/rpc/server). - This tool is optional and if you leave it out you can always attach it to an already running - `geth` instance with `geth attach`. - -### A Full node on the Görli test network - -Transitioning towards developers, if you'd like to play around with creating Ethereum -contracts, you almost certainly would like to do that without any real money involved until -you get the hang of the entire system. In other words, instead of attaching to the main -network, you want to join the **test** network with your node, which is fully equivalent to -the main network, but with play-Ether only. - -```shell -$ geth --goerli console -``` - -The `console` subcommand has the same meaning as above and is equally -useful on the testnet too. - -Specifying the `--goerli` flag, however, will reconfigure your `geth` instance a bit: - - * Instead of connecting to the main Ethereum network, the client will connect to the Görli - test network, which uses different P2P bootnodes, different network IDs and genesis - states. - * Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth` - will nest itself one level deeper into a `goerli` subfolder (`~/.ethereum/goerli` on - Linux). Note, on OSX and Linux this also means that attaching to a running testnet node - requires the use of a custom endpoint since `geth attach` will try to attach to a - production node endpoint by default, e.g., - `geth attach /goerli/geth.ipc`. Windows users are not affected by - this. - -*Note: Although some internal protective measures prevent transactions from -crossing over between the main network and test network, you should always -use separate accounts for play and real money. Unless you manually move -accounts, `geth` will by default correctly separate the two networks and will not make any -accounts available between them.* - -### Full node on the Rinkeby test network - -Go Ethereum also supports connecting to the older proof-of-authority based test network -called [*Rinkeby*](https://www.rinkeby.io) which is operated by members of the community. - -```shell -$ geth --rinkeby console -``` - -### Full node on the Ropsten test network - -In addition to Görli and Rinkeby, Geth also supports the ancient Ropsten testnet. The -Ropsten test network is based on the Ethash proof-of-work consensus algorithm. As such, -it has certain extra overhead and is more susceptible to reorganization attacks due to the -network's low difficulty/security. - -```shell -$ geth --ropsten console -``` - -*Note: Older Geth configurations store the Ropsten database in the `testnet` subdirectory.* - -### Configuration - -As an alternative to passing the numerous flags to the `geth` binary, you can also pass a -configuration file via: - -```shell -$ geth --config /path/to/your_config.toml -``` - -To get an idea of how the file should look like you can use the `dumpconfig` subcommand to -export your existing configuration: - -```shell -$ geth --your-favourite-flags dumpconfig -``` - -*Note: This works only with `geth` v1.6.0 and above.* - -#### Docker quick start - -One of the quickest ways to get Ethereum up and running on your machine is by using -Docker: - -```shell -docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \ - -p 8545:8545 -p 30303:30303 \ - ethereum/client-go -``` - -This will start `geth` in snap-sync mode with a DB memory allowance of 1GB, as the -above command does. It will also create a persistent volume in your home directory for -saving your blockchain as well as map the default ports. There is also an `alpine` tag -available for a slim version of the image. - -Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers -and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not -accessible from the outside. - -### Programmatically interfacing `geth` nodes - -As a developer, sooner rather than later you'll want to start interacting with `geth` and the -Ethereum network via your own programs and not manually through the console. To aid -this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/) -and [`geth` specific APIs](https://geth.ethereum.org/docs/rpc/server)). -These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based -platforms, and named pipes on Windows). - -The IPC interface is enabled by default and exposes all the APIs supported by `geth`, -whereas the HTTP and WS interfaces need to manually be enabled and only expose a -subset of APIs due to security reasons. These can be turned on/off and configured as -you'd expect. - -HTTP based JSON-RPC API options: - - * `--http` Enable the HTTP-RPC server - * `--http.addr` HTTP-RPC server listening interface (default: `localhost`) - * `--http.port` HTTP-RPC server listening port (default: `8545`) - * `--http.api` API's offered over the HTTP-RPC interface (default: `eth,net,web3`) - * `--http.corsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced) - * `--ws` Enable the WS-RPC server - * `--ws.addr` WS-RPC server listening interface (default: `localhost`) - * `--ws.port` WS-RPC server listening port (default: `8546`) - * `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`) - * `--ws.origins` Origins from which to accept WebSocket requests - * `--ipcdisable` Disable the IPC-RPC server - * `--ipcapi` API's offered over the IPC-RPC interface (default: `admin,debug,eth,miner,net,personal,txpool,web3`) - * `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it) - -You'll need to use your own programming environments' capabilities (libraries, tools, etc) to -connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll -need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You -can reuse the same connection for multiple requests! - -**Note: Please understand the security implications of opening up an HTTP/WS based -transport before doing so! Hackers on the internet are actively trying to subvert -Ethereum nodes with exposed APIs! Further, all browser tabs can access locally -running web servers, so malicious web pages could try to subvert locally available -APIs!** - -### Operating a private network - -Maintaining your own private network is more involved as a lot of configurations taken for -granted in the official networks need to be manually set up. - -#### Defining the private genesis state - -First, you'll need to create the genesis state of your networks, which all nodes need to be -aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`): - -```json -{ - "config": { - "chainId": , - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "berlinBlock": 0, - "londonBlock": 0 - }, - "alloc": {}, - "coinbase": "0x0000000000000000000000000000000000000000", - "difficulty": "0x20000", - "extraData": "", - "gasLimit": "0x2fefd8", - "nonce": "0x0000000000000042", - "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x00" -} -``` - -The above fields should be fine for most purposes, although we'd recommend changing -the `nonce` to some random value so you prevent unknown remote nodes from being able -to connect to you. If you'd like to pre-fund some accounts for easier testing, create -the accounts and populate the `alloc` field with their addresses. - -```json -"alloc": { - "0x0000000000000000000000000000000000000001": { - "balance": "111111111" - }, - "0x0000000000000000000000000000000000000002": { - "balance": "222222222" - } -} -``` - -With the genesis state defined in the above JSON file, you'll need to initialize **every** -`geth` node with it prior to starting it up to ensure all blockchain parameters are correctly -set: - -```shell -$ geth init path/to/genesis.json -``` - -#### Creating the rendezvous point - -With all nodes that you want to run initialized to the desired genesis state, you'll need to -start a bootstrap node that others can use to find each other in your network and/or over -the internet. The clean way is to configure and run a dedicated bootnode: - -```shell -$ bootnode --genkey=boot.key -$ bootnode --nodekey=boot.key -``` - -With the bootnode online, it will display an [`enode` URL](https://ethereum.org/en/developers/docs/networking-layer/network-addresses/#enode) -that other nodes can use to connect to it and exchange peer information. Make sure to -replace the displayed IP address information (most probably `[::]`) with your externally -accessible IP to get the actual `enode` URL. - -*Note: You could also use a full-fledged `geth` node as a bootnode, but it's the less -recommended way.* - -#### Starting up your member nodes - -With the bootnode operational and externally reachable (you can try -`telnet ` to ensure it's indeed reachable), start every subsequent `geth` -node pointed to the bootnode for peer discovery via the `--bootnodes` flag. It will -probably also be desirable to keep the data directory of your private network separated, so -do also specify a custom `--datadir` flag. - -```shell -$ geth --datadir=path/to/custom/data/folder --bootnodes= -``` - -*Note: Since your network will be completely cut off from the main and test networks, you'll -also need to configure a miner to process transactions and create new blocks for you.* - -#### Running a private miner - - -In a private network setting a single CPU miner instance is more than enough for -practical purposes as it can produce a stable stream of blocks at the correct intervals -without needing heavy resources (consider running on a single thread, no need for multiple -ones either). To start a `geth` instance for mining, run it with all your usual flags, extended -by: - -```shell -$ geth --mine --miner.threads=1 --miner.etherbase=0x0000000000000000000000000000000000000000 -``` - -Which will start mining blocks and transactions on a single CPU thread, crediting all -proceedings to the account specified by `--miner.etherbase`. You can further tune the mining -by changing the default gas limit blocks converge to (`--miner.targetgaslimit`) and the price -transactions are accepted at (`--miner.gasprice`). - -## Contribution - -Thank you for considering helping out with the source code! We welcome contributions -from anyone on the internet, and are grateful for even the smallest of fixes! - -If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request -for the maintainers to review and merge into the main code base. If you wish to submit -more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.gg/invite/nthXNEv) -to ensure those changes are in line with the general philosophy of the project and/or get -some early feedback which can make both your efforts much lighter as well as our review -and merge procedures quick and simple. - -Please make sure your contributions adhere to our coding guidelines: - - * Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) - guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). - * Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) - guidelines. - * Pull requests need to be based on and opened against the `master` branch. - * Commit messages should be prefixed with the package(s) they modify. - * E.g. "eth, rpc: make trace configs optional" - -Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide) -for more details on configuring your environment, managing project dependencies, and -testing procedures. - -### Contributing to geth.ethereum.org - -For contributions to the [go-ethereum website](https://geth.ethereum.org), please checkout and raise pull requests against the `website` branch. -For more detailed instructions please see the `website` branch [README](https://github.com/ethereum/go-ethereum/tree/website#readme) or the -[contributing](https://geth.ethereum.org/docs/developers/geth-developer/contributing) page of the website. - -## License - -The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the -[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html), -also included in our repository in the `COPYING.LESSER` file. - -The go-ethereum binaries (i.e. all code inside of the `cmd` directory) are licensed under the -[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also -included in our repository in the `COPYING` file. \ No newline at end of file diff --git a/builder/SECURITY.md b/builder/SECURITY.md deleted file mode 100644 index 41b900d5e..000000000 --- a/builder/SECURITY.md +++ /dev/null @@ -1,175 +0,0 @@ -# Security Policy - -## Supported Versions - -Please see [Releases](https://github.com/ethereum/go-ethereum/releases). We recommend using the [most recently released version](https://github.com/ethereum/go-ethereum/releases/latest). - -## Audit reports - -Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits - -| Scope | Date | Report Link | -| ------- | ------- | ----------- | -| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) | -| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) | -| `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) | -| `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) | - -## Reporting a Vulnerability - -**Please do not file a public ticket** mentioning the vulnerability. - -To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. Please read the [disclosure page](https://github.com/ethereum/go-ethereum/security/advisories?state=published) for more information about publicly disclosed security vulnerabilities. - -Use the built-in `geth version-check` feature to check whether the software is affected by any known vulnerability. This command will fetch the latest [`vulnerabilities.json`](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json) file which contains known security vulnerabilities concerning `geth`, and cross-check the data against its own version number. - -The following key may be used to communicate sensitive information to developers. - -Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A` - -``` ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: SKS 1.1.6 -Comment: Hostname: pgp.mit.edu - -mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaYneAk3Bp1 -82GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9L8c8yiqry1ZTCmYM -qCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUim+y7buJDtoNf7YILlhDQXN8q -lHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0bfUo9pexOn7LS4SojoJmsm/5dp6AoKlac -48cZU5zwR9AYcq/nvkrfmf2WkObg/xRdEvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/y -PFE335k+ujjZCPOu7OwjzDk7M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXCho -yI8vbfp4dGvCvYqvQAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+F -nQOUgg2Hh8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c -2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZEZCjMXxB -8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQABtDRFdGhlcmV1bSBG -b3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1bS5vcmc+iQIcBBEBCAAGBQJa -FCY6AAoJEHoMA3Q0/nfveH8P+gJBPo9BXZL8isUfbUWjwLi81Yi70hZqIJUnz64SWTqBzg5b -mCZ69Ji5637THsxQetS2ARabz0DybQ779FhD/IWnqV9T3KuBM/9RzJtuhLzKCyMrAINPMo28 -rKWdunHHarpuR4m3tL2zWJkle5QVYb+vkZXJJE98PJw+N4IYeKKeCs2ubeqZu636GA0sMzzB -Jn3m/dRRA2va+/zzbr6F6b51ynzbMxWKTsJnstjC8gs8EeI+Zcd6otSyelLtCUkk3h5sTvpV -Wv67BNSU0BYsMkxyFi9PUyy07Wixgeas89K5jG1oOtDva/FkpRHrTE/WA5OXDRcLrHJM+SwD -CwqcLQqJd09NxwUW1iKeBmPptTiOGu1Gv2o7aEyoaWrHRBO7JuYrQrj6q2B3H1Je0zjAd2qt -09ni2bLwLn4LA+VDpprNTO+eZDprv09s2oFSU6NwziHybovu0y7X4pADGkK2evOM7c86PohX -QRQ1M1T16xLj6wP8/Ykwl6v/LUk7iDPXP3GPILnh4YOkwBR3DsCOPn8098xy7FxEELmupRzt -Cj9oC7YAoweeShgUjBPzb+nGY1m6OcFfbUPBgFyMMfwF6joHbiVIO+39+Ut2g2ysZa7KF+yp -XqVDqyEkYXsOLb25OC7brt8IJEPgBPwcHK5GNag6RfLxnQV+iVZ9KNH1yQgSiQI+BBMBAgAo -AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWglh+gUJBaNgWAAKCRDojTM0+l9qCgQ2 -D/4udJpV4zGIZW1yNaVvtd3vfKsTLi7GIRJLUBqVb2Yx/uhnN8jTl/tAhCVosCQ1pzvi9kMl -s8qO1vu2kw5EWFFkwK96roI8pTql3VIjwhRVQrCkR7oAk/eUd1U/nt2q6J4UTYeVgqbq4dsI -ZZTRyPJMD667YpuAIcaah+w9j/E5xksYQdMeprnDrQkkBCb4FIMqfDzBPKvEa8DcQr949K85 -kxhr6LDq9i5l4Egxt2JdH8DaR4GLca6+oHy0MyPs/bZOsfmZUObfM2oZgPpqYM96JanhzO1j -dpnItyBii2pc+kNx5nMOf4eikE/MBv+WUJ0TttWzApGGmFUzDhtuEvRH9NBjtJ/pMrYspIGu -O/QNY5KKOKQTvVIlwGcm8dTsSkqtBDSUwZyWbfKfKOI1/RhM9dC3gj5/BOY57DYYV4rdTK01 -ZtYjuhdfs2bhuP1uF/cgnSSZlv8azvf7Egh7tHPnYxvLjfq1bJAhCIX0hNg0a81/ndPAEFky -fSko+JPKvdSvsUcSi2QQ4U2HX//jNBjXRfG4F0utgbJnhXzEckz6gqt7wSDZH2oddVuO8Ssc -T7sK+CdXthSKnRyuI+sGUpG+6glpKWIfYkWFKNZWuQ+YUatY3QEDHXTIioycSmV8p4d/g/0S -V6TegidLxY8bXMkbqz+3n6FArRffv5MH7qt3cYkCPgQTAQIAKAUCWCXhOwIbAwUJAeEzgAYL -CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6I0zNPpfagrN/w/+Igp3vtYdNunikw3yHnYf -Jkm0MmaMDUM9mtsaXVN6xb9n25N3Xa3GWCpmdsbYZ8334tI/oQ4/NHq/bEI5WFH5F1aFkMkm -5AJVLuUkipCtmCZ5NkbRPJA9l0uNUUE6uuFXBhf4ddu7jb0jMetRF/kifJHVCCo5fISUNhLp -7bwcWq9qgDQNZNYMOo4s9WX5Tl+5x4gTZdd2/cAYt49h/wnkw+huM+Jm0GojpLqIQ1jZiffm -otf5rF4L+JhIIdW0W4IIh1v9BhHVllXw+z9oj0PALstT5h8/DuKoIiirFJ4DejU85GR1KKAS -DeO19G/lSpWj1rSgFv2N2gAOxq0X+BbQTua2jdcY6JpHR4H1JJ2wzfHsHPgDQcgY1rGlmjVF -aqU73WV4/hzXc/HshK/k4Zd8uD4zypv6rFsZ3UemK0aL2zXLVpV8SPWQ61nS03x675SmDlYr -A80ENfdqvsn00JQuBVIv4Tv0Ub7NfDraDGJCst8rObjBT/0vnBWTBCebb2EsnS2iStIFkWdz -/WXs4L4Yzre1iJwqRjiuqahZR5jHsjAUf2a0O29HVHE7zlFtCFmLPClml2lGQfQOpm5klGZF -rmvus+qZ9rt35UgWHPZezykkwtWrFOwspwuCWaPDto6tgbRJZ4ftitpdYYM3dKW9IGJXBwrt -BQrMsu+lp0vDF+yJAlUEEwEIAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbt -lp5HmwCE8+F/6I0zNPpfagoFAmEAEJwFCQycmLgACgkQ6I0zNPpfagpWoBAAhOcbMAUw6Zt0 -GYzT3sR5/c0iatezPzXEXJf9ebzR8M5uPElXcxcnMx1dvXZmGPXPJKCPa99WCu1NZYy8F+Wj -GTOY9tfIkvSxhys1p/giPAmvid6uQmD+bz7ivktnyzCkDWfMA+l8lsCSEqVlaq6y5T+a6SWB -6TzC2S0MPb/RrC/7DpwyrNYWumvyVJh09adm1Mw/UGgst/sZ8eMaRYEd3X0yyT1CBpX4zp2E -qQj9IEOTizvzv1x2jkHe5ZUeU3+nTBNlhSA+WFHUi0pfBdo2qog3Mv2EC1P2qMKoSdD5tPbA -zql1yKoHHnXOMsqdftGwbiv2sYXWvrYvmaCd3Ys/viOyt3HOy9uV2ZEtBd9Yqo9x/NZj8QMA -nY5k8jjrIXbUC89MqrJsQ6xxWQIg5ikMT7DvY0Ln89ev4oJyVvwIQAwCm4jUzFNm9bZLYDOP -5lGJCV7tF5NYVU7NxNM8vescKc40mVNK/pygS5mxhK9QYOUjZsIv8gddrl1TkqrFMuxFnTyN -WvzE29wFu/n4N1DkF+ZBqS70SlRvB+Hjz5LrDgEzF1Wf1eA/wq1dZbvMjjDVIc2VGlYp8Cp2 -8ob23c1seTtYXTNYgSR5go4EpH+xi+bIWv01bQQ9xGwBbT5sm4WUeWOcmX4QewzLZ3T/wK9+ -N4Ye/hmU9O34FwWJOY58EIe0OUV0aGVyZXVtIEZvdW5kYXRpb24gU2VjdXJpdHkgVGVhbSA8 -c2VjdXJpdHlAZXRoZXJldW0ub3JnPokCHAQRAQgABgUCWhQmOgAKCRB6DAN0NP5372LSEACT -wZk1TASWZj5QF7rmkIM1GEyBxLE+PundNcMgM9Ktj1315ED8SmiukNI4knVS1MY99OIgXhQl -D1foF2GKdTomrwwC4012zTNyUYCY60LnPZ6Z511HG+rZgZtZrbkz0IiUpwAlhGQND77lBqem -J3K+CFX2XpDA/ojui/kqrY4cwMT5P8xPJkwgpRgw/jgdcZyJTsXdHblV9IGU4H1Vd1SgcfAf -Db3YxDUlBtzlp0NkZqxen8irLIXUQvsfuIfRUbUSkWoK/n3U/gOCajAe8ZNF07iX4OWjH4Sw -NDA841WhFWcGE+d8+pfMVfPASU3UPKH72uw86b2VgR46Av6voyMFd1pj+yCA+YAhJuOpV4yL -QaGg2Z0kVOjuNWK/kBzp1F58DWGh4YBatbhE/UyQOqAAtR7lNf0M3QF9AdrHTxX8oZeqVW3V -Fmi2mk0NwCIUv8SSrZr1dTchp04OtyXe5gZBXSfzncCSRQIUDC8OgNWaOzAaUmK299v4bvye -uSCxOysxC7Q1hZtjzFPKdljS81mRlYeUL4fHlJU9R57bg8mriSXLmn7eKrSEDm/EG5T8nRx7 -TgX2MqJs8sWFxD2+bboVEu75yuFmZ//nmCBApAit9Hr2/sCshGIEpa9MQ6xJCYUxyqeJH+Cc -Aja0UfXhnK2uvPClpJLIl4RE3gm4OXeE1IkCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC -AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagr4MQ//cfp3GSbSG8dkqgctW67Fy7cQ -diiTmx3cwxY+tlI3yrNmdjtrIQMzGdqtY6LNz7aN87F8mXNf+DyVHX9+wd1Y8U+E+hVCTzKC -sefUfxTz6unD9TTcGqaoelgIPMn4IiKz1RZE6eKpfDWe6q78W1Y6x1bE0qGNSjqT/QSxpezF -E/OAm/t8RRxVxDtqz8LfH2zLea5zaC+ADj8EqgY9vX9TQa4DyVV8MgOyECCCadJQCD5O5hIA -B2gVDWwrAUw+KBwskXZ7Iq4reJTKLEmt5z9zgtJ/fABwaCFt66ojwg0/RjbO9cNA3ZwHLGwU -C6hkb6bRzIoZoMfYxVS84opiqf/Teq+t/XkBYCxbSXTJDA5MKjcVuw3N6YKWbkGP/EfQThe7 -BfAKFwwIw5YmsWjHK8IQj6R6hBxzTz9rz8y1Lu8EAAFfA7OJKaboI2qbOlauH98OuOUmVtr1 -TczHO+pTcgWVN0ytq2/pX5KBf4vbmULNbg3HFRq+gHx8CW+jyXGkcqjbgU/5FwtDxeqRTdGJ -SyBGNBEU6pBNolyynyaKaaJjJ/biY27pvjymL5rlz95BH3Dn16Z4RRmqwlT6eq/wFYginujg -CCE1icqOSE+Vjl7V8tV8AcgANkXKdbBE+Q8wlKsGI/kS1w4XFAYcaNHFT8qNeS8TSFXFhvU8 -HylYxO79t56JAj4EEwECACgFAlgl3tgCGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMBAh4B -AheAAAoJEOiNMzT6X2oKmUMP/0hnaL6bVyepAq2LIdvIUbHfagt/Oo/KVfZs4bkM+xJOitJR -0kwZV9PTihXFdzhL/YNWc2+LtEBtKItqkJZKmWC0E6OPXGVuU6hfFPebuzVccYJfm0Q3Ej19 -VJI9Uomf59Bpak8HYyEED7WVQjoYn7XVPsonwus/9+LDX+c5vutbrUdbjga3KjHbewD93X4O -wVVoXyHEmU2Plyg8qvzFbNDylCWO7N2McO6SN6+7DitGZGr2+jO+P2R4RT1cnl2V3IRVcWZ0 -OTspPSnRGVr2fFiHN/+v8G/wHPLQcJZFvYPfUGNdcYbTmhWdiY0bEYXFiNrgzCCsyad7eKUR -WN9QmxqmyqLDjUEDJCAh19ES6Vg3tqGwXk+uNUCoF30ga0TxQt6UXZJDEQFAGeASQ/RqE/q1 -EAuLv8IGM8o7IqKO2pWfLuqsY6dTbKBwDzz9YOJt7EOGuPPQbHxaYStTushZmJnm7hi8lhVG -jT7qsEJdE95Il+I/mHWnXsCevaXjZugBiyV9yvOq4Hwwe2s1zKfrnQ4u0cadvGAh2eIqum7M -Y3o6nD47aJ3YmEPX/WnhI56bACa2GmWvUwjI4c0/er3esSPYnuHnM9L8Am4qQwMVSmyU80tC -MI7A9e13Mvv+RRkYFLJ7PVPdNpbW5jqX1doklFpKf6/XM+B+ngYneU+zgCUBiQJVBBMBCAA/ -AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W7ZaeR5sAhPPhf+iNMzT6X2oKBQJh -ABCQBQkMnJi4AAoJEOiNMzT6X2oKAv0P+gJ3twBp5efNWyVLcIg4h4cOo9uD0NPvz8/fm2gX -FoOJL3MeigtPuSVfE9kuTaTuRbArzuFtdvH6G/kcRQvOlO4zyiIRHCk1gDHoIvvtn6RbRhVm -/Xo4uGIsFHst7n4A7BjicwEK5Op6Ih5Hoq19xz83YSBgBVk2fYEJIRyJiKFbyPjH0eSYe8v+ -Ra5/F85ugLx1P6mMVkW+WPzULns89riW7BGTnZmXFHZp8nO2pkUlcI7F3KRG7l4kmlC50ox6 -DiG/6AJCVulbAClky9C68TmJ/R1RazQxU/9IqVywsydq66tbJQbm5Z7GEti0C5jjbSRJL2oT -1xC7Rilr85PMREkPL3vegJdgj5PKlffZ/MocD/0EohiQ7wFpejFD4iTljeh0exRUwCRb6655 -9ib34JSQgU8Hl4JJu+mEgd9v0ZHD0/1mMD6fnAR84zca+O3cdASbnQmzTOKcGzLIrkE8TEnU -+2UZ8Ol7SAAqmBgzY1gKOilUho6dkyCAwNL+QDpvrITDPLEFPsjyB/M2KudZSVEn+Rletju1 -qkMW31qFMNlsbwzMZw+0USeGcs31Cs0B2/WQsro99CExlhS9auUFkmoVjJmYVTIYOM0zuPa4 -OyGspqPhRu5hEsmMDPDWD7Aad5k4GTqogQNnuKyRliZjXXrDZqFD5nfsJSL8Ky/sJGEMuQIN -BFgl3tgBEACbgq6HTN5gEBi0lkD/MafInmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4h -YontkMaKRlCg2Rvgjvk3Zve0PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT1 -9BdeAQRFvcfd+8w8f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj -26bf+2+1DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6 -D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66iPsR99MQ7 -FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A4tGkHl08KZ2N9o6G -rfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8greW8xB4zuf9Mkuou+RHNmo8Pe -bHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0VRxdPImKun+4LOXbfOxArOSkY6i35+gs -gkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/ -bM1ACUtipMiIVeUs2uFiRjpzA1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJa -CWIIBQkFo2BYAAoJEOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg -3IHMGxDMb/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8 -KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0IQ1UKKXvz -ZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0K9lneidcqtBDvlgg -JTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0TNOOE8fXlvu8iuIAMBSDL9ep6 -sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd5MTi0MDRNTij431kn8T/D0LCgmoUmYYM -BgbwFhXr67axPZlKjrqR0z3F/Elv0ZPPcVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1q -Scl9HiMxjt/H6aPastH63/7wcN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4 -/Lih6Z1TlwcFVap+cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1p -M6AOQPpZ85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4iQIl -BBgBAgAPBQJYJd7YAhsMBQkB4TOAAAoJEOiNMzT6X2oKTjgP/1ojCVyGyvHMLUgnX0zwrR5Q -1M5RKFz6kHwKjODVLR3Isp8I935oTQt3DY7yFDI4t0GqbYRQMtxcNEb7maianhK2trCXfhPs -6/L04igjDf5iTcmzamXN6xnh5xkz06hZJJCMuu4MvKxC9MQHCVKAwjswl/9H9JqIBXAY3E2l -LpX5P+5jDZuPxS86p3+k4Rrdp9KTGXjiuEleM3zGlz5BLWydqovOck7C2aKh27ETFpDYY0z3 -yQ5AsPJyk1rAr0wrH6+ywmwWlzuQewavnrLnJ2M8iMFXpIhyHeEIU/f7o8f+dQk72rZ9CGzd -cqig2za/BS3zawZWgbv2vB2elNsIllYLdir45jxBOxx2yvJvEuu4glz78y4oJTCTAYAbMlle -5gVdPkVcGyvvVS9tinnSaiIzuvWrYHKWll1uYPm2Q1CDs06P5I7bUGAXpgQLUh/XQguy/0sX -GWqW3FS5JzP+XgcR/7UASvwBdHylubKbeqEpB7G1s+m+8C67qOrc7EQv3Jmy1YDOkhEyNig1 -rmjplLuir3tC1X+D7dHpn7NJe7nMwFx2b2MpMkLA9jPPAGPp/ekcu5sxCe+E0J/4UF++K+CR -XIxgtzU2UJfp8p9x+ygbx5qHinR0tVRdIzv3ZnGsXrfxnWfSOaB582cU3VRN9INzHHax8ETa -QVDnGO5uQa+FiQI8BBgBCAAmAhsMFiEErpbtlp5HmwCE8+F/6I0zNPpfagoFAmEAELYFCQyc -mN4ACgkQ6I0zNPpfagoqAQ/+MnDjBx8JWMd/XjeFoYKx/Oo0ntkInV+ME61JTBls4PdVk+TB -8PWZdPQHw9SnTvRmykFeznXIRzuxkowjrZYXdPXBxY2b1WyD5V3Ati1TM9vqpaR4osyPs2xy -I4dzDssh9YvUsIRL99O04/65lGiYeBNuACq+yK/7nD/ErzBkDYJHhMCdadbVWUACxvVIDvro -yQeVLKMsHqMCd8BTGD7VDs79NXskPnN77pAFnkzS4Z2b8SNzrlgTc5pUiuZHIXPIpEYmsYzh -ucTU6uI3dN1PbSFHK5tG2pHb4ZrPxY3L20Dgc2Tfu5/SDApZzwvvKTqjdO891MEJ++H+ssOz -i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP -+m+TmXfVtthJred4sHlJMTJNpt+sCcT6wLMmyc3keIEAu33gsJj3LTpkEA2q+V+ZiP6Q8HRB -402ITklABSArrPSE/fQU9L8hZ5qmy0Z96z0iyILgVMLuRCCfQOMWhwl8yQWIIaf1yPI07xur -epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx -PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano= -=arte ------END PGP PUBLIC KEY BLOCK------ -``` diff --git a/builder/accounts/abi/abi.go b/builder/accounts/abi/abi.go deleted file mode 100644 index c7bc2b454..000000000 --- a/builder/accounts/abi/abi.go +++ /dev/null @@ -1,311 +0,0 @@ -// 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 abi - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -// The ABI holds information about a contract's context and available -// invocable methods. It will allow you to type check function calls and -// packs data accordingly. -type ABI struct { - Constructor Method - Methods map[string]Method - Events map[string]Event - Errors map[string]Error - - // Additional "special" functions introduced in solidity v0.6.0. - // It's separated from the original default fallback. Each contract - // can only define one fallback and receive function. - Fallback Method // Note it's also used to represent legacy fallback before v0.6.0 - Receive Method -} - -// JSON returns a parsed ABI interface and error if it failed. -func JSON(reader io.Reader) (ABI, error) { - dec := json.NewDecoder(reader) - - var abi ABI - if err := dec.Decode(&abi); err != nil { - return ABI{}, err - } - return abi, nil -} - -// Pack the given method name to conform the ABI. Method call's data -// will consist of method_id, args0, arg1, ... argN. Method id consists -// of 4 bytes and arguments are all 32 bytes. -// Method ids are created from the first 4 bytes of the hash of the -// methods string signature. (signature = baz(uint32,string32)) -func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { - // Fetch the ABI of the requested method - if name == "" { - // constructor - arguments, err := abi.Constructor.Inputs.Pack(args...) - if err != nil { - return nil, err - } - return arguments, nil - } - method, exist := abi.Methods[name] - if !exist { - return nil, fmt.Errorf("method '%s' not found", name) - } - arguments, err := method.Inputs.Pack(args...) - if err != nil { - return nil, err - } - // Pack up the method ID too if not a constructor and return - return append(method.ID, arguments...), nil -} - -func (abi ABI) getArguments(name string, data []byte) (Arguments, error) { - // since there can't be naming collisions with contracts and events, - // we need to decide whether we're calling a method or an event - var args Arguments - if method, ok := abi.Methods[name]; ok { - if len(data)%32 != 0 { - return nil, fmt.Errorf("abi: improperly formatted output: %q - Bytes: %+v", data, data) - } - args = method.Outputs - } - if event, ok := abi.Events[name]; ok { - args = event.Inputs - } - if args == nil { - return nil, fmt.Errorf("abi: could not locate named method or event: %s", name) - } - return args, nil -} - -// Unpack unpacks the output according to the abi specification. -func (abi ABI) Unpack(name string, data []byte) ([]interface{}, error) { - args, err := abi.getArguments(name, data) - if err != nil { - return nil, err - } - return args.Unpack(data) -} - -// UnpackIntoInterface unpacks the output in v according to the abi specification. -// It performs an additional copy. Please only use, if you want to unpack into a -// structure that does not strictly conform to the abi structure (e.g. has additional arguments) -func (abi ABI) UnpackIntoInterface(v interface{}, name string, data []byte) error { - args, err := abi.getArguments(name, data) - if err != nil { - return err - } - unpacked, err := args.Unpack(data) - if err != nil { - return err - } - return args.Copy(v, unpacked) -} - -// UnpackIntoMap unpacks a log into the provided map[string]interface{}. -func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) { - args, err := abi.getArguments(name, data) - if err != nil { - return err - } - return args.UnpackIntoMap(v, data) -} - -// UnmarshalJSON implements json.Unmarshaler interface. -func (abi *ABI) UnmarshalJSON(data []byte) error { - var fields []struct { - Type string - Name string - Inputs []Argument - Outputs []Argument - - // Status indicator which can be: "pure", "view", - // "nonpayable" or "payable". - StateMutability string - - // Deprecated Status indicators, but removed in v0.6.0. - Constant bool // True if function is either pure or view - Payable bool // True if function is payable - - // Event relevant indicator represents the event is - // declared as anonymous. - Anonymous bool - } - if err := json.Unmarshal(data, &fields); err != nil { - return err - } - abi.Methods = make(map[string]Method) - abi.Events = make(map[string]Event) - abi.Errors = make(map[string]Error) - for _, field := range fields { - switch field.Type { - case "constructor": - abi.Constructor = NewMethod("", "", Constructor, field.StateMutability, field.Constant, field.Payable, field.Inputs, nil) - case "function": - name := ResolveNameConflict(field.Name, func(s string) bool { _, ok := abi.Methods[s]; return ok }) - abi.Methods[name] = NewMethod(name, field.Name, Function, field.StateMutability, field.Constant, field.Payable, field.Inputs, field.Outputs) - case "fallback": - // New introduced function type in v0.6.0, check more detail - // here https://solidity.readthedocs.io/en/v0.6.0/contracts.html#fallback-function - if abi.HasFallback() { - return errors.New("only single fallback is allowed") - } - abi.Fallback = NewMethod("", "", Fallback, field.StateMutability, field.Constant, field.Payable, nil, nil) - case "receive": - // New introduced function type in v0.6.0, check more detail - // here https://solidity.readthedocs.io/en/v0.6.0/contracts.html#fallback-function - if abi.HasReceive() { - return errors.New("only single receive is allowed") - } - if field.StateMutability != "payable" { - return errors.New("the statemutability of receive can only be payable") - } - abi.Receive = NewMethod("", "", Receive, field.StateMutability, field.Constant, field.Payable, nil, nil) - case "event": - name := ResolveNameConflict(field.Name, func(s string) bool { _, ok := abi.Events[s]; return ok }) - abi.Events[name] = NewEvent(name, field.Name, field.Anonymous, field.Inputs) - case "error": - // Errors cannot be overloaded or overridden but are inherited, - // no need to resolve the name conflict here. - abi.Errors[field.Name] = NewError(field.Name, field.Inputs) - default: - return fmt.Errorf("abi: could not recognize type %v of field %v", field.Type, field.Name) - } - } - return nil -} - -// MethodById looks up a method by the 4-byte id, -// returns nil if none found. -func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { - if len(sigdata) < 4 { - return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata)) - } - for _, method := range abi.Methods { - if bytes.Equal(method.ID, sigdata[:4]) { - return &method, nil - } - } - return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) -} - -// EventByID looks an event up by its topic hash in the -// ABI and returns nil if none found. -func (abi *ABI) EventByID(topic common.Hash) (*Event, error) { - for _, event := range abi.Events { - if bytes.Equal(event.ID.Bytes(), topic.Bytes()) { - return &event, nil - } - } - return nil, fmt.Errorf("no event with id: %#x", topic.Hex()) -} - -// ErrorByID looks up an error by the 4-byte id, -// returns nil if none found. -func (abi *ABI) ErrorByID(sigdata [4]byte) (*Error, error) { - for _, errABI := range abi.Errors { - if bytes.Equal(errABI.ID[:4], sigdata[:]) { - return &errABI, nil - } - } - return nil, fmt.Errorf("no error with id: %#x", sigdata[:]) -} - -// HasFallback returns an indicator whether a fallback function is included. -func (abi *ABI) HasFallback() bool { - return abi.Fallback.Type == Fallback -} - -// HasReceive returns an indicator whether a receive function is included. -func (abi *ABI) HasReceive() bool { - return abi.Receive.Type == Receive -} - -// revertSelector is a special function selector for revert reason unpacking. -var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4] - -// panicSelector is a special function selector for panic reason unpacking. -var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4] - -// panicReasons map is for readable panic codes -// see this linkage for the details -// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require -// the reason string list is copied from ether.js -// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218 -var panicReasons = map[uint64]string{ - 0x00: "generic panic", - 0x01: "assert(false)", - 0x11: "arithmetic underflow or overflow", - 0x12: "division or modulo by zero", - 0x21: "enum overflow", - 0x22: "invalid encoded storage byte array accessed", - 0x31: "out-of-bounds array access; popping on an empty array", - 0x32: "out-of-bounds access of an array or bytesN", - 0x41: "out of memory", - 0x51: "uninitialized function", -} - -// UnpackRevert resolves the abi-encoded revert reason. According to the solidity -// spec https://solidity.readthedocs.io/en/latest/control-structures.html#revert, -// the provided revert reason is abi-encoded as if it were a call to function -// `Error(string)` or `Panic(uint256)`. So it's a special tool for it. -func UnpackRevert(data []byte) (string, error) { - if len(data) < 4 { - return "", errors.New("invalid data for unpacking") - } - switch { - case bytes.Equal(data[:4], revertSelector): - typ, err := NewType("string", "", nil) - if err != nil { - return "", err - } - unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:]) - if err != nil { - return "", err - } - return unpacked[0].(string), nil - case bytes.Equal(data[:4], panicSelector): - typ, err := NewType("uint256", "", nil) - if err != nil { - return "", err - } - unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:]) - if err != nil { - return "", err - } - pCode := unpacked[0].(*big.Int) - // uint64 safety check for future - // but the code is not bigger than MAX(uint64) now - if pCode.IsUint64() { - if reason, ok := panicReasons[pCode.Uint64()]; ok { - return reason, nil - } - } - return fmt.Sprintf("unknown panic code: %#x", pCode), nil - default: - return "", errors.New("invalid data for unpacking") - } -} diff --git a/builder/accounts/abi/abi_test.go b/builder/accounts/abi/abi_test.go deleted file mode 100644 index bc76df0dc..000000000 --- a/builder/accounts/abi/abi_test.go +++ /dev/null @@ -1,1220 +0,0 @@ -// 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 abi - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "math/big" - "reflect" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto" -) - -const jsondata = ` -[ - { "type" : "function", "name" : ""}, - { "type" : "function", "name" : "balance", "stateMutability" : "view" }, - { "type" : "function", "name" : "send", "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }, - { "type" : "function", "name" : "test", "inputs" : [ { "name" : "number", "type" : "uint32" } ] }, - { "type" : "function", "name" : "string", "inputs" : [ { "name" : "inputs", "type" : "string" } ] }, - { "type" : "function", "name" : "bool", "inputs" : [ { "name" : "inputs", "type" : "bool" } ] }, - { "type" : "function", "name" : "address", "inputs" : [ { "name" : "inputs", "type" : "address" } ] }, - { "type" : "function", "name" : "uint64[2]", "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] }, - { "type" : "function", "name" : "uint64[]", "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] }, - { "type" : "function", "name" : "int8", "inputs" : [ { "name" : "inputs", "type" : "int8" } ] }, - { "type" : "function", "name" : "bytes32", "inputs" : [ { "name" : "inputs", "type" : "bytes32" } ] }, - { "type" : "function", "name" : "foo", "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] }, - { "type" : "function", "name" : "bar", "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] }, - { "type" : "function", "name" : "slice", "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] }, - { "type" : "function", "name" : "slice256", "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] }, - { "type" : "function", "name" : "sliceAddress", "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] }, - { "type" : "function", "name" : "sliceMultiAddress", "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }, - { "type" : "function", "name" : "nestedArray", "inputs" : [ { "name" : "a", "type" : "uint256[2][2]" }, { "name" : "b", "type" : "address[]" } ] }, - { "type" : "function", "name" : "nestedArray2", "inputs" : [ { "name" : "a", "type" : "uint8[][2]" } ] }, - { "type" : "function", "name" : "nestedSlice", "inputs" : [ { "name" : "a", "type" : "uint8[][]" } ] }, - { "type" : "function", "name" : "receive", "inputs" : [ { "name" : "memo", "type" : "bytes" }], "outputs" : [], "payable" : true, "stateMutability" : "payable" }, - { "type" : "function", "name" : "fixedArrStr", "stateMutability" : "view", "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }, - { "type" : "function", "name" : "fixedArrBytes", "stateMutability" : "view", "inputs" : [ { "name" : "bytes", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }, - { "type" : "function", "name" : "mixedArrStr", "stateMutability" : "view", "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" }, { "name" : "dynArr", "type" : "uint256[]" } ] }, - { "type" : "function", "name" : "doubleFixedArrStr", "stateMutability" : "view", "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type" : "uint256[2]" }, { "name" : "fixedArr2", "type" : "uint256[3]" } ] }, - { "type" : "function", "name" : "multipleMixedArrStr", "stateMutability" : "view", "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type" : "uint256[2]" }, { "name" : "dynArr", "type" : "uint256[]" }, { "name" : "fixedArr2", "type" : "uint256[3]" } ] }, - { "type" : "function", "name" : "overloadedNames", "stateMutability" : "view", "inputs": [ { "components": [ { "internalType": "uint256", "name": "_f", "type": "uint256" }, { "internalType": "uint256", "name": "__f", "type": "uint256"}, { "internalType": "uint256", "name": "f", "type": "uint256"}],"internalType": "struct Overloader.F", "name": "f","type": "tuple"}]} -]` - -var ( - Uint256, _ = NewType("uint256", "", nil) - Uint32, _ = NewType("uint32", "", nil) - Uint16, _ = NewType("uint16", "", nil) - String, _ = NewType("string", "", nil) - Bool, _ = NewType("bool", "", nil) - Bytes, _ = NewType("bytes", "", nil) - Bytes32, _ = NewType("bytes32", "", nil) - Address, _ = NewType("address", "", nil) - Uint64Arr, _ = NewType("uint64[]", "", nil) - AddressArr, _ = NewType("address[]", "", nil) - Int8, _ = NewType("int8", "", nil) - // Special types for testing - Uint32Arr2, _ = NewType("uint32[2]", "", nil) - Uint64Arr2, _ = NewType("uint64[2]", "", nil) - Uint256Arr, _ = NewType("uint256[]", "", nil) - Uint256Arr2, _ = NewType("uint256[2]", "", nil) - Uint256Arr3, _ = NewType("uint256[3]", "", nil) - Uint256ArrNested, _ = NewType("uint256[2][2]", "", nil) - Uint8ArrNested, _ = NewType("uint8[][2]", "", nil) - Uint8SliceNested, _ = NewType("uint8[][]", "", nil) - TupleF, _ = NewType("tuple", "struct Overloader.F", []ArgumentMarshaling{ - {Name: "_f", Type: "uint256"}, - {Name: "__f", Type: "uint256"}, - {Name: "f", Type: "uint256"}}) -) - -var methods = map[string]Method{ - "": NewMethod("", "", Function, "", false, false, nil, nil), - "balance": NewMethod("balance", "balance", Function, "view", false, false, nil, nil), - "send": NewMethod("send", "send", Function, "", false, false, []Argument{{"amount", Uint256, false}}, nil), - "test": NewMethod("test", "test", Function, "", false, false, []Argument{{"number", Uint32, false}}, nil), - "string": NewMethod("string", "string", Function, "", false, false, []Argument{{"inputs", String, false}}, nil), - "bool": NewMethod("bool", "bool", Function, "", false, false, []Argument{{"inputs", Bool, false}}, nil), - "address": NewMethod("address", "address", Function, "", false, false, []Argument{{"inputs", Address, false}}, nil), - "uint64[]": NewMethod("uint64[]", "uint64[]", Function, "", false, false, []Argument{{"inputs", Uint64Arr, false}}, nil), - "uint64[2]": NewMethod("uint64[2]", "uint64[2]", Function, "", false, false, []Argument{{"inputs", Uint64Arr2, false}}, nil), - "int8": NewMethod("int8", "int8", Function, "", false, false, []Argument{{"inputs", Int8, false}}, nil), - "bytes32": NewMethod("bytes32", "bytes32", Function, "", false, false, []Argument{{"inputs", Bytes32, false}}, nil), - "foo": NewMethod("foo", "foo", Function, "", false, false, []Argument{{"inputs", Uint32, false}}, nil), - "bar": NewMethod("bar", "bar", Function, "", false, false, []Argument{{"inputs", Uint32, false}, {"string", Uint16, false}}, nil), - "slice": NewMethod("slice", "slice", Function, "", false, false, []Argument{{"inputs", Uint32Arr2, false}}, nil), - "slice256": NewMethod("slice256", "slice256", Function, "", false, false, []Argument{{"inputs", Uint256Arr2, false}}, nil), - "sliceAddress": NewMethod("sliceAddress", "sliceAddress", Function, "", false, false, []Argument{{"inputs", AddressArr, false}}, nil), - "sliceMultiAddress": NewMethod("sliceMultiAddress", "sliceMultiAddress", Function, "", false, false, []Argument{{"a", AddressArr, false}, {"b", AddressArr, false}}, nil), - "nestedArray": NewMethod("nestedArray", "nestedArray", Function, "", false, false, []Argument{{"a", Uint256ArrNested, false}, {"b", AddressArr, false}}, nil), - "nestedArray2": NewMethod("nestedArray2", "nestedArray2", Function, "", false, false, []Argument{{"a", Uint8ArrNested, false}}, nil), - "nestedSlice": NewMethod("nestedSlice", "nestedSlice", Function, "", false, false, []Argument{{"a", Uint8SliceNested, false}}, nil), - "receive": NewMethod("receive", "receive", Function, "payable", false, true, []Argument{{"memo", Bytes, false}}, []Argument{}), - "fixedArrStr": NewMethod("fixedArrStr", "fixedArrStr", Function, "view", false, false, []Argument{{"str", String, false}, {"fixedArr", Uint256Arr2, false}}, nil), - "fixedArrBytes": NewMethod("fixedArrBytes", "fixedArrBytes", Function, "view", false, false, []Argument{{"bytes", Bytes, false}, {"fixedArr", Uint256Arr2, false}}, nil), - "mixedArrStr": NewMethod("mixedArrStr", "mixedArrStr", Function, "view", false, false, []Argument{{"str", String, false}, {"fixedArr", Uint256Arr2, false}, {"dynArr", Uint256Arr, false}}, nil), - "doubleFixedArrStr": NewMethod("doubleFixedArrStr", "doubleFixedArrStr", Function, "view", false, false, []Argument{{"str", String, false}, {"fixedArr1", Uint256Arr2, false}, {"fixedArr2", Uint256Arr3, false}}, nil), - "multipleMixedArrStr": NewMethod("multipleMixedArrStr", "multipleMixedArrStr", Function, "view", false, false, []Argument{{"str", String, false}, {"fixedArr1", Uint256Arr2, false}, {"dynArr", Uint256Arr, false}, {"fixedArr2", Uint256Arr3, false}}, nil), - "overloadedNames": NewMethod("overloadedNames", "overloadedNames", Function, "view", false, false, []Argument{{"f", TupleF, false}}, nil), -} - -func TestReader(t *testing.T) { - t.Parallel() - abi := ABI{ - Methods: methods, - } - - exp, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Fatal(err) - } - - for name, expM := range exp.Methods { - gotM, exist := abi.Methods[name] - if !exist { - t.Errorf("Missing expected method %v", name) - } - if !reflect.DeepEqual(gotM, expM) { - t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM) - } - } - - for name, gotM := range abi.Methods { - expM, exist := exp.Methods[name] - if !exist { - t.Errorf("Found extra method %v", name) - } - if !reflect.DeepEqual(gotM, expM) { - t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM) - } - } -} - -func TestInvalidABI(t *testing.T) { - t.Parallel() - json := `[{ "type" : "function", "name" : "", "constant" : fals }]` - _, err := JSON(strings.NewReader(json)) - if err == nil { - t.Fatal("invalid json should produce error") - } - json2 := `[{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "typ" : "uint256" } ] }]` - _, err = JSON(strings.NewReader(json2)) - if err == nil { - t.Fatal("invalid json should produce error") - } -} - -// TestConstructor tests a constructor function. -// The test is based on the following contract: -// -// contract TestConstructor { -// constructor(uint256 a, uint256 b) public{} -// } -func TestConstructor(t *testing.T) { - t.Parallel() - json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]` - method := NewMethod("", "", Constructor, "nonpayable", false, false, []Argument{{"a", Uint256, false}, {"b", Uint256, false}}, nil) - // Test from JSON - abi, err := JSON(strings.NewReader(json)) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(abi.Constructor, method) { - t.Error("Missing expected constructor") - } - // Test pack/unpack - packed, err := abi.Pack("", big.NewInt(1), big.NewInt(2)) - if err != nil { - t.Error(err) - } - unpacked, err := abi.Constructor.Inputs.Unpack(packed) - if err != nil { - t.Error(err) - } - - if !reflect.DeepEqual(unpacked[0], big.NewInt(1)) { - t.Error("Unable to pack/unpack from constructor") - } - if !reflect.DeepEqual(unpacked[1], big.NewInt(2)) { - t.Error("Unable to pack/unpack from constructor") - } -} - -func TestTestNumbers(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Fatal(err) - } - - if _, err := abi.Pack("balance"); err != nil { - t.Error(err) - } - - if _, err := abi.Pack("balance", 1); err == nil { - t.Error("expected error for balance(1)") - } - - if _, err := abi.Pack("doesntexist", nil); err == nil { - t.Errorf("doesntexist shouldn't exist") - } - - if _, err := abi.Pack("doesntexist", 1); err == nil { - t.Errorf("doesntexist(1) shouldn't exist") - } - - if _, err := abi.Pack("send", big.NewInt(1000)); err != nil { - t.Error(err) - } - - i := new(int) - *i = 1000 - if _, err := abi.Pack("send", i); err == nil { - t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int") - } - - if _, err := abi.Pack("test", uint32(1000)); err != nil { - t.Error(err) - } -} - -func TestMethodSignature(t *testing.T) { - t.Parallel() - m := NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil) - exp := "foo(string,string)" - if m.Sig != exp { - t.Error("signature mismatch", exp, "!=", m.Sig) - } - - idexp := crypto.Keccak256([]byte(exp))[:4] - if !bytes.Equal(m.ID, idexp) { - t.Errorf("expected ids to match %x != %x", m.ID, idexp) - } - - m = NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", Uint256, false}}, nil) - exp = "foo(uint256)" - if m.Sig != exp { - t.Error("signature mismatch", exp, "!=", m.Sig) - } - - // Method with tuple arguments - s, _ := NewType("tuple", "", []ArgumentMarshaling{ - {Name: "a", Type: "int256"}, - {Name: "b", Type: "int256[]"}, - {Name: "c", Type: "tuple[]", Components: []ArgumentMarshaling{ - {Name: "x", Type: "int256"}, - {Name: "y", Type: "int256"}, - }}, - {Name: "d", Type: "tuple[2]", Components: []ArgumentMarshaling{ - {Name: "x", Type: "int256"}, - {Name: "y", Type: "int256"}, - }}, - }) - m = NewMethod("foo", "foo", Function, "", false, false, []Argument{{"s", s, false}, {"bar", String, false}}, nil) - exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)" - if m.Sig != exp { - t.Error("signature mismatch", exp, "!=", m.Sig) - } -} - -func TestOverloadedMethodSignature(t *testing.T) { - t.Parallel() - json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]` - abi, err := JSON(strings.NewReader(json)) - if err != nil { - t.Fatal(err) - } - check := func(name string, expect string, method bool) { - if method { - if abi.Methods[name].Sig != expect { - t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig) - } - } else { - if abi.Events[name].Sig != expect { - t.Fatalf("The signature of overloaded event mismatch, want %s, have %s", expect, abi.Events[name].Sig) - } - } - } - check("foo", "foo(uint256,uint256)", true) - check("foo0", "foo(uint256)", true) - check("bar", "bar(uint256)", false) - check("bar0", "bar(uint256,uint256)", false) -} - -func TestCustomErrors(t *testing.T) { - t.Parallel() - json := `[{ "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ],"name": "MyError", "type": "error"} ]` - abi, err := JSON(strings.NewReader(json)) - if err != nil { - t.Fatal(err) - } - check := func(name string, expect string) { - if abi.Errors[name].Sig != expect { - t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig) - } - } - check("MyError", "MyError(uint256)") -} - -func TestMultiPack(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Fatal(err) - } - - sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4] - sig = append(sig, make([]byte, 64)...) - sig[35] = 10 - sig[67] = 11 - - packed, err := abi.Pack("bar", uint32(10), uint16(11)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } -} - -func ExampleJSON() { - const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]` - - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - panic(err) - } - out, err := abi.Pack("isBar", common.HexToAddress("01")) - if err != nil { - panic(err) - } - - fmt.Printf("%x\n", out) - // Output: - // 1f2c40920000000000000000000000000000000000000000000000000000000000000001 -} - -func TestInputVariableInputLength(t *testing.T) { - t.Parallel() - const definition = `[ - { "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] }, - { "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] }, - { "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] } - ]` - - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - - // test one string - strin := "hello world" - strpack, err := abi.Pack("strOne", strin) - if err != nil { - t.Error(err) - } - - offset := make([]byte, 32) - offset[31] = 32 - length := make([]byte, 32) - length[31] = byte(len(strin)) - value := common.RightPadBytes([]byte(strin), 32) - exp := append(offset, append(length, value...)...) - - // ignore first 4 bytes of the output. This is the function identifier - strpack = strpack[4:] - if !bytes.Equal(strpack, exp) { - t.Errorf("expected %x, got %x\n", exp, strpack) - } - - // test one bytes - btspack, err := abi.Pack("bytesOne", []byte(strin)) - if err != nil { - t.Error(err) - } - // ignore first 4 bytes of the output. This is the function identifier - btspack = btspack[4:] - if !bytes.Equal(btspack, exp) { - t.Errorf("expected %x, got %x\n", exp, btspack) - } - - // test two strings - str1 := "hello" - str2 := "world" - str2pack, err := abi.Pack("strTwo", str1, str2) - if err != nil { - t.Error(err) - } - - offset1 := make([]byte, 32) - offset1[31] = 64 - length1 := make([]byte, 32) - length1[31] = byte(len(str1)) - value1 := common.RightPadBytes([]byte(str1), 32) - - offset2 := make([]byte, 32) - offset2[31] = 128 - length2 := make([]byte, 32) - length2[31] = byte(len(str2)) - value2 := common.RightPadBytes([]byte(str2), 32) - - exp2 := append(offset1, offset2...) - exp2 = append(exp2, append(length1, value1...)...) - exp2 = append(exp2, append(length2, value2...)...) - - // ignore first 4 bytes of the output. This is the function identifier - str2pack = str2pack[4:] - if !bytes.Equal(str2pack, exp2) { - t.Errorf("expected %x, got %x\n", exp, str2pack) - } - - // test two strings, first > 32, second < 32 - str1 = strings.Repeat("a", 33) - str2pack, err = abi.Pack("strTwo", str1, str2) - if err != nil { - t.Error(err) - } - - offset1 = make([]byte, 32) - offset1[31] = 64 - length1 = make([]byte, 32) - length1[31] = byte(len(str1)) - value1 = common.RightPadBytes([]byte(str1), 64) - offset2[31] = 160 - - exp2 = append(offset1, offset2...) - exp2 = append(exp2, append(length1, value1...)...) - exp2 = append(exp2, append(length2, value2...)...) - - // ignore first 4 bytes of the output. This is the function identifier - str2pack = str2pack[4:] - if !bytes.Equal(str2pack, exp2) { - t.Errorf("expected %x, got %x\n", exp, str2pack) - } - - // test two strings, first > 32, second >32 - str1 = strings.Repeat("a", 33) - str2 = strings.Repeat("a", 33) - str2pack, err = abi.Pack("strTwo", str1, str2) - if err != nil { - t.Error(err) - } - - offset1 = make([]byte, 32) - offset1[31] = 64 - length1 = make([]byte, 32) - length1[31] = byte(len(str1)) - value1 = common.RightPadBytes([]byte(str1), 64) - - offset2 = make([]byte, 32) - offset2[31] = 160 - length2 = make([]byte, 32) - length2[31] = byte(len(str2)) - value2 = common.RightPadBytes([]byte(str2), 64) - - exp2 = append(offset1, offset2...) - exp2 = append(exp2, append(length1, value1...)...) - exp2 = append(exp2, append(length2, value2...)...) - - // ignore first 4 bytes of the output. This is the function identifier - str2pack = str2pack[4:] - if !bytes.Equal(str2pack, exp2) { - t.Errorf("expected %x, got %x\n", exp, str2pack) - } -} - -func TestInputFixedArrayAndVariableInputLength(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Error(err) - } - - // test string, fixed array uint256[2] - strin := "hello world" - arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)} - fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin) - if err != nil { - t.Error(err) - } - - // generate expected output - offset := make([]byte, 32) - offset[31] = 96 - length := make([]byte, 32) - length[31] = byte(len(strin)) - strvalue := common.RightPadBytes([]byte(strin), 32) - arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32) - arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32) - exp := append(offset, arrinvalue1...) - exp = append(exp, arrinvalue2...) - exp = append(exp, append(length, strvalue...)...) - - // ignore first 4 bytes of the output. This is the function identifier - fixedArrStrPack = fixedArrStrPack[4:] - if !bytes.Equal(fixedArrStrPack, exp) { - t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack) - } - - // test byte array, fixed array uint256[2] - bytesin := []byte(strin) - arrin = [2]*big.Int{big.NewInt(1), big.NewInt(2)} - fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin) - if err != nil { - t.Error(err) - } - - // generate expected output - offset = make([]byte, 32) - offset[31] = 96 - length = make([]byte, 32) - length[31] = byte(len(strin)) - strvalue = common.RightPadBytes([]byte(strin), 32) - arrinvalue1 = common.LeftPadBytes(arrin[0].Bytes(), 32) - arrinvalue2 = common.LeftPadBytes(arrin[1].Bytes(), 32) - exp = append(offset, arrinvalue1...) - exp = append(exp, arrinvalue2...) - exp = append(exp, append(length, strvalue...)...) - - // ignore first 4 bytes of the output. This is the function identifier - fixedArrBytesPack = fixedArrBytesPack[4:] - if !bytes.Equal(fixedArrBytesPack, exp) { - t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack) - } - - // test string, fixed array uint256[2], dynamic array uint256[] - strin = "hello world" - fixedarrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)} - dynarrin := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} - mixedArrStrPack, err := abi.Pack("mixedArrStr", strin, fixedarrin, dynarrin) - if err != nil { - t.Error(err) - } - - // generate expected output - stroffset := make([]byte, 32) - stroffset[31] = 128 - strlength := make([]byte, 32) - strlength[31] = byte(len(strin)) - strvalue = common.RightPadBytes([]byte(strin), 32) - fixedarrinvalue1 := common.LeftPadBytes(fixedarrin[0].Bytes(), 32) - fixedarrinvalue2 := common.LeftPadBytes(fixedarrin[1].Bytes(), 32) - dynarroffset := make([]byte, 32) - dynarroffset[31] = byte(160 + ((len(strin)/32)+1)*32) - dynarrlength := make([]byte, 32) - dynarrlength[31] = byte(len(dynarrin)) - dynarrinvalue1 := common.LeftPadBytes(dynarrin[0].Bytes(), 32) - dynarrinvalue2 := common.LeftPadBytes(dynarrin[1].Bytes(), 32) - dynarrinvalue3 := common.LeftPadBytes(dynarrin[2].Bytes(), 32) - exp = append(stroffset, fixedarrinvalue1...) - exp = append(exp, fixedarrinvalue2...) - exp = append(exp, dynarroffset...) - exp = append(exp, append(strlength, strvalue...)...) - dynarrarg := append(dynarrlength, dynarrinvalue1...) - dynarrarg = append(dynarrarg, dynarrinvalue2...) - dynarrarg = append(dynarrarg, dynarrinvalue3...) - exp = append(exp, dynarrarg...) - - // ignore first 4 bytes of the output. This is the function identifier - mixedArrStrPack = mixedArrStrPack[4:] - if !bytes.Equal(mixedArrStrPack, exp) { - t.Errorf("expected %x, got %x\n", exp, mixedArrStrPack) - } - - // test string, fixed array uint256[2], fixed array uint256[3] - strin = "hello world" - fixedarrin1 := [2]*big.Int{big.NewInt(1), big.NewInt(2)} - fixedarrin2 := [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} - doubleFixedArrStrPack, err := abi.Pack("doubleFixedArrStr", strin, fixedarrin1, fixedarrin2) - if err != nil { - t.Error(err) - } - - // generate expected output - stroffset = make([]byte, 32) - stroffset[31] = 192 - strlength = make([]byte, 32) - strlength[31] = byte(len(strin)) - strvalue = common.RightPadBytes([]byte(strin), 32) - fixedarrin1value1 := common.LeftPadBytes(fixedarrin1[0].Bytes(), 32) - fixedarrin1value2 := common.LeftPadBytes(fixedarrin1[1].Bytes(), 32) - fixedarrin2value1 := common.LeftPadBytes(fixedarrin2[0].Bytes(), 32) - fixedarrin2value2 := common.LeftPadBytes(fixedarrin2[1].Bytes(), 32) - fixedarrin2value3 := common.LeftPadBytes(fixedarrin2[2].Bytes(), 32) - exp = append(stroffset, fixedarrin1value1...) - exp = append(exp, fixedarrin1value2...) - exp = append(exp, fixedarrin2value1...) - exp = append(exp, fixedarrin2value2...) - exp = append(exp, fixedarrin2value3...) - exp = append(exp, append(strlength, strvalue...)...) - - // ignore first 4 bytes of the output. This is the function identifier - doubleFixedArrStrPack = doubleFixedArrStrPack[4:] - if !bytes.Equal(doubleFixedArrStrPack, exp) { - t.Errorf("expected %x, got %x\n", exp, doubleFixedArrStrPack) - } - - // test string, fixed array uint256[2], dynamic array uint256[], fixed array uint256[3] - strin = "hello world" - fixedarrin1 = [2]*big.Int{big.NewInt(1), big.NewInt(2)} - dynarrin = []*big.Int{big.NewInt(1), big.NewInt(2)} - fixedarrin2 = [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)} - multipleMixedArrStrPack, err := abi.Pack("multipleMixedArrStr", strin, fixedarrin1, dynarrin, fixedarrin2) - if err != nil { - t.Error(err) - } - - // generate expected output - stroffset = make([]byte, 32) - stroffset[31] = 224 - strlength = make([]byte, 32) - strlength[31] = byte(len(strin)) - strvalue = common.RightPadBytes([]byte(strin), 32) - fixedarrin1value1 = common.LeftPadBytes(fixedarrin1[0].Bytes(), 32) - fixedarrin1value2 = common.LeftPadBytes(fixedarrin1[1].Bytes(), 32) - dynarroffset = math.U256Bytes(big.NewInt(int64(256 + ((len(strin)/32)+1)*32))) - dynarrlength = make([]byte, 32) - dynarrlength[31] = byte(len(dynarrin)) - dynarrinvalue1 = common.LeftPadBytes(dynarrin[0].Bytes(), 32) - dynarrinvalue2 = common.LeftPadBytes(dynarrin[1].Bytes(), 32) - fixedarrin2value1 = common.LeftPadBytes(fixedarrin2[0].Bytes(), 32) - fixedarrin2value2 = common.LeftPadBytes(fixedarrin2[1].Bytes(), 32) - fixedarrin2value3 = common.LeftPadBytes(fixedarrin2[2].Bytes(), 32) - exp = append(stroffset, fixedarrin1value1...) - exp = append(exp, fixedarrin1value2...) - exp = append(exp, dynarroffset...) - exp = append(exp, fixedarrin2value1...) - exp = append(exp, fixedarrin2value2...) - exp = append(exp, fixedarrin2value3...) - exp = append(exp, append(strlength, strvalue...)...) - dynarrarg = append(dynarrlength, dynarrinvalue1...) - dynarrarg = append(dynarrarg, dynarrinvalue2...) - exp = append(exp, dynarrarg...) - - // ignore first 4 bytes of the output. This is the function identifier - multipleMixedArrStrPack = multipleMixedArrStrPack[4:] - if !bytes.Equal(multipleMixedArrStrPack, exp) { - t.Errorf("expected %x, got %x\n", exp, multipleMixedArrStrPack) - } -} - -func TestDefaultFunctionParsing(t *testing.T) { - t.Parallel() - const definition = `[{ "name" : "balance", "type" : "function" }]` - - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - - if _, ok := abi.Methods["balance"]; !ok { - t.Error("expected 'balance' to be present") - } -} - -func TestBareEvents(t *testing.T) { - t.Parallel() - const definition = `[ - { "type" : "event", "name" : "balance" }, - { "type" : "event", "name" : "anon", "anonymous" : true}, - { "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }, - { "type" : "event", "name" : "tuple", "inputs" : [{ "indexed":false, "name":"t", "type":"tuple", "components":[{"name":"a", "type":"uint256"}] }, { "indexed":true, "name":"arg1", "type":"address" }] } - ]` - - tuple, _ := NewType("tuple", "", []ArgumentMarshaling{{Name: "a", Type: "uint256"}}) - - expectedEvents := map[string]struct { - Anonymous bool - Args []Argument - }{ - "balance": {false, nil}, - "anon": {true, nil}, - "args": {false, []Argument{ - {Name: "arg0", Type: Uint256, Indexed: false}, - {Name: "arg1", Type: Address, Indexed: true}, - }}, - "tuple": {false, []Argument{ - {Name: "t", Type: tuple, Indexed: false}, - {Name: "arg1", Type: Address, Indexed: true}, - }}, - } - - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - - if len(abi.Events) != len(expectedEvents) { - t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events)) - } - - for name, exp := range expectedEvents { - got, ok := abi.Events[name] - if !ok { - t.Errorf("could not found event %s", name) - continue - } - if got.Anonymous != exp.Anonymous { - t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous) - } - if len(got.Inputs) != len(exp.Args) { - t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs)) - continue - } - for i, arg := range exp.Args { - if arg.Name != got.Inputs[i].Name { - t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name) - } - if arg.Indexed != got.Inputs[i].Indexed { - t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed) - } - if arg.Type.T != got.Inputs[i].Type.T { - t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T) - } - } - } -} - -// TestUnpackEvent is based on this contract: -// -// contract T { -// event received(address sender, uint amount, bytes memo); -// event receivedAddr(address sender); -// function receive(bytes memo) external payable { -// received(msg.sender, msg.value, memo); -// receivedAddr(msg.sender); -// } -// } -// -// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt: -// -// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]} -func TestUnpackEvent(t *testing.T) { - t.Parallel() - const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]` - abi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - - const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158` - data, err := hex.DecodeString(hexdata) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - - type ReceivedEvent struct { - Sender common.Address - Amount *big.Int - Memo []byte - } - var ev ReceivedEvent - - err = abi.UnpackIntoInterface(&ev, "received", data) - if err != nil { - t.Error(err) - } - - type ReceivedAddrEvent struct { - Sender common.Address - } - var receivedAddrEv ReceivedAddrEvent - err = abi.UnpackIntoInterface(&receivedAddrEv, "receivedAddr", data) - if err != nil { - t.Error(err) - } -} - -func TestUnpackEventIntoMap(t *testing.T) { - t.Parallel() - const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]` - abi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - - const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158` - data, err := hex.DecodeString(hexdata) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - - receivedMap := map[string]interface{}{} - expectedReceivedMap := map[string]interface{}{ - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - if err := abi.UnpackIntoMap(receivedMap, "received", data); err != nil { - t.Error(err) - } - if len(receivedMap) != 3 { - t.Error("unpacked `received` map expected to have length 3") - } - if receivedMap["sender"] != expectedReceivedMap["sender"] { - t.Error("unpacked `received` map does not match expected map") - } - if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { - t.Error("unpacked `received` map does not match expected map") - } - if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { - t.Error("unpacked `received` map does not match expected map") - } - - receivedAddrMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(receivedAddrMap, "receivedAddr", data); err != nil { - t.Error(err) - } - if len(receivedAddrMap) != 1 { - t.Error("unpacked `receivedAddr` map expected to have length 1") - } - if receivedAddrMap["sender"] != expectedReceivedMap["sender"] { - t.Error("unpacked `receivedAddr` map does not match expected map") - } -} - -func TestUnpackMethodIntoMap(t *testing.T) { - t.Parallel() - const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]` - abi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - const hexdata = `00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000158000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000158` - data, err := hex.DecodeString(hexdata) - if err != nil { - t.Fatal(err) - } - if len(data)%32 != 0 { - t.Errorf("len(data) is %d, want a multiple of 32", len(data)) - } - - // Tests a method with no outputs - receiveMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(receiveMap, "receive", data); err != nil { - t.Error(err) - } - if len(receiveMap) > 0 { - t.Error("unpacked `receive` map expected to have length 0") - } - - // Tests a method with only outputs - sendMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(sendMap, "send", data); err != nil { - t.Error(err) - } - if len(sendMap) != 1 { - t.Error("unpacked `send` map expected to have length 1") - } - if sendMap["amount"].(*big.Int).Cmp(big.NewInt(1)) != 0 { - t.Error("unpacked `send` map expected `amount` value of 1") - } - - // Tests a method with outputs and inputs - getMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(getMap, "get", data); err != nil { - t.Error(err) - } - if len(getMap) != 1 { - t.Error("unpacked `get` map expected to have length 1") - } - expectedBytes := []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, 96, 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, 88, 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, 96, 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, 88, 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, 96, 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, 88, 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, 96, 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, 88, 0} - if !bytes.Equal(getMap["hash"].([]byte), expectedBytes) { - t.Errorf("unpacked `get` map expected `hash` value of %v", expectedBytes) - } -} - -func TestUnpackIntoMapNamingConflict(t *testing.T) { - t.Parallel() - // Two methods have the same name - var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]` - abi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - var hexdata = `00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158` - data, err := hex.DecodeString(hexdata) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - getMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(getMap, "get", data); err == nil { - t.Error("naming conflict between two methods; error expected") - } - - // Two events have the same name - abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"received","type":"event"}]` - abi, err = JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158` - data, err = hex.DecodeString(hexdata) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - receivedMap := map[string]interface{}{} - if err = abi.UnpackIntoMap(receivedMap, "received", data); err != nil { - t.Error("naming conflict between two events; no error expected") - } - - // Method and event have the same name - abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"received","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]` - abi, err = JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - if err = abi.UnpackIntoMap(receivedMap, "received", data); err == nil { - t.Error("naming conflict between an event and a method; error expected") - } - - // Conflict is case sensitive - abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"received","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]` - abi, err = JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - if len(data)%32 == 0 { - t.Errorf("len(data) is %d, want a non-multiple of 32", len(data)) - } - expectedReceivedMap := map[string]interface{}{ - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - if err = abi.UnpackIntoMap(receivedMap, "Received", data); err != nil { - t.Error(err) - } - if len(receivedMap) != 3 { - t.Error("unpacked `received` map expected to have length 3") - } - if receivedMap["sender"] != expectedReceivedMap["sender"] { - t.Error("unpacked `received` map does not match expected map") - } - if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 { - t.Error("unpacked `received` map does not match expected map") - } - if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) { - t.Error("unpacked `received` map does not match expected map") - } -} - -func TestABI_MethodById(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Fatal(err) - } - for name, m := range abi.Methods { - a := fmt.Sprintf("%v", m) - m2, err := abi.MethodById(m.ID) - if err != nil { - t.Fatalf("Failed to look up ABI method: %v", err) - } - b := fmt.Sprintf("%v", m2) - if a != b { - t.Errorf("Method %v (id %x) not 'findable' by id in ABI", name, m.ID) - } - } - // test unsuccessful lookups - if _, err = abi.MethodById(crypto.Keccak256()); err == nil { - t.Error("Expected error: no method with this id") - } - // Also test empty - if _, err := abi.MethodById([]byte{0x00}); err == nil { - t.Errorf("Expected error, too short to decode data") - } - if _, err := abi.MethodById([]byte{}); err == nil { - t.Errorf("Expected error, too short to decode data") - } - if _, err := abi.MethodById(nil); err == nil { - t.Errorf("Expected error, nil is short to decode data") - } -} - -func TestABI_EventById(t *testing.T) { - t.Parallel() - tests := []struct { - name string - json string - event string - }{ - { - name: "", - json: `[ - {"type":"event","name":"received","anonymous":false,"inputs":[ - {"indexed":false,"name":"sender","type":"address"}, - {"indexed":false,"name":"amount","type":"uint256"}, - {"indexed":false,"name":"memo","type":"bytes"} - ] - }]`, - event: "received(address,uint256,bytes)", - }, { - name: "", - json: `[ - { "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, - { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "constant": false, "inputs": [ { "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, - { "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "constant": true, "inputs": [ { "name": "_owner", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transfer", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, - { "constant": true, "inputs": [ { "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, - { "payable": true, "stateMutability": "payable", "type": "fallback" }, - { "anonymous": false, "inputs": [ { "indexed": true, "name": "owner", "type": "address" }, { "indexed": true, "name": "spender", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, - { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "address" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" } - ]`, - event: "Transfer(address,address,uint256)", - }, - } - - for testnum, test := range tests { - abi, err := JSON(strings.NewReader(test.json)) - if err != nil { - t.Error(err) - } - - topic := test.event - topicID := crypto.Keccak256Hash([]byte(topic)) - - event, err := abi.EventByID(topicID) - if err != nil { - t.Fatalf("Failed to look up ABI method: %v, test #%d", err, testnum) - } - if event == nil { - t.Errorf("We should find a event for topic %s, test #%d", topicID.Hex(), testnum) - } else if event.ID != topicID { - t.Errorf("Event id %s does not match topic %s, test #%d", event.ID.Hex(), topicID.Hex(), testnum) - } - - unknowntopicID := crypto.Keccak256Hash([]byte("unknownEvent")) - unknownEvent, err := abi.EventByID(unknowntopicID) - if err == nil { - t.Errorf("EventByID should return an error if a topic is not found, test #%d", testnum) - } - if unknownEvent != nil { - t.Errorf("We should not find any event for topic %s, test #%d", unknowntopicID.Hex(), testnum) - } - } -} - -func TestABI_ErrorByID(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(`[ - {"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"}, - {"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"}, - {"inputs":[{"internalType":"uint256[]","name":"x","type":"uint256[]"}],"name":"MyError3","type":"error"} - ]`)) - if err != nil { - t.Fatal(err) - } - for name, m := range abi.Errors { - a := fmt.Sprintf("%v", &m) - var id [4]byte - copy(id[:], m.ID[:4]) - m2, err := abi.ErrorByID(id) - if err != nil { - t.Fatalf("Failed to look up ABI error: %v", err) - } - b := fmt.Sprintf("%v", m2) - if a != b { - t.Errorf("Error %v (id %x) not 'findable' by id in ABI", name, id) - } - } - // test unsuccessful lookups - if _, err = abi.ErrorByID([4]byte{}); err == nil { - t.Error("Expected error: no error with this id") - } -} - -// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name -// conflict and that the second transfer method will be renamed transfer1. -func TestDoubleDuplicateMethodNames(t *testing.T) { - t.Parallel() - abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` - contractAbi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - if _, ok := contractAbi.Methods["transfer"]; !ok { - t.Fatalf("Could not find original method") - } - if _, ok := contractAbi.Methods["transfer0"]; !ok { - t.Fatalf("Could not find duplicate method") - } - if _, ok := contractAbi.Methods["transfer1"]; !ok { - t.Fatalf("Could not find duplicate method") - } - if _, ok := contractAbi.Methods["transfer2"]; ok { - t.Fatalf("Should not have found extra method") - } -} - -// TestDoubleDuplicateEventNames checks that if send0 already exists, there won't be a name -// conflict and that the second send event will be renamed send1. -// The test runs the abi of the following contract. -// -// contract DuplicateEvent { -// event send(uint256 a); -// event send0(); -// event send(); -// } -func TestDoubleDuplicateEventNames(t *testing.T) { - t.Parallel() - abiJSON := `[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "a","type": "uint256"}],"name": "send","type": "event"},{"anonymous": false,"inputs": [],"name": "send0","type": "event"},{ "anonymous": false, "inputs": [],"name": "send","type": "event"}]` - contractAbi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - if _, ok := contractAbi.Events["send"]; !ok { - t.Fatalf("Could not find original event") - } - if _, ok := contractAbi.Events["send0"]; !ok { - t.Fatalf("Could not find duplicate event") - } - if _, ok := contractAbi.Events["send1"]; !ok { - t.Fatalf("Could not find duplicate event") - } - if _, ok := contractAbi.Events["send2"]; ok { - t.Fatalf("Should not have found extra event") - } -} - -// TestUnnamedEventParam checks that an event with unnamed parameters is -// correctly handled. -// The test runs the abi of the following contract. -// -// contract TestEvent { -// event send(uint256, uint256); -// } -func TestUnnamedEventParam(t *testing.T) { - t.Parallel() - abiJSON := `[{ "anonymous": false, "inputs": [{ "indexed": false,"internalType": "uint256", "name": "","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "","type": "uint256"}],"name": "send","type": "event"}]` - contractAbi, err := JSON(strings.NewReader(abiJSON)) - if err != nil { - t.Fatal(err) - } - - event, ok := contractAbi.Events["send"] - if !ok { - t.Fatalf("Could not find event") - } - if event.Inputs[0].Name != "arg0" { - t.Fatalf("Could not find input") - } - if event.Inputs[1].Name != "arg1" { - t.Fatalf("Could not find input") - } -} - -func TestUnpackRevert(t *testing.T) { - t.Parallel() - - var cases = []struct { - input string - expect string - expectErr error - }{ - {"", "", errors.New("invalid data for unpacking")}, - {"08c379a1", "", errors.New("invalid data for unpacking")}, - {"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil}, - {"4e487b710000000000000000000000000000000000000000000000000000000000000000", "generic panic", nil}, - {"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil}, - } - for index, c := range cases { - index, c := index, c - t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) { - t.Parallel() - got, err := UnpackRevert(common.Hex2Bytes(c.input)) - if c.expectErr != nil { - if err == nil { - t.Fatalf("Expected non-nil error") - } - if err.Error() != c.expectErr.Error() { - t.Fatalf("Expected error mismatch, want %v, got %v", c.expectErr, err) - } - return - } - if c.expect != got { - t.Fatalf("Output mismatch, want %v, got %v", c.expect, got) - } - }) - } -} diff --git a/builder/accounts/abi/abifuzzer_test.go b/builder/accounts/abi/abifuzzer_test.go deleted file mode 100644 index dbf6ab6c5..000000000 --- a/builder/accounts/abi/abifuzzer_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// 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 abi - -import ( - "fmt" - "reflect" - "strings" - "testing" - - fuzz "github.com/google/gofuzz" -) - -// TestReplicate can be used to replicate crashers from the fuzzing tests. -// Just replace testString with the data in .quoted -func TestReplicate(t *testing.T) { - t.Parallel() - //t.Skip("Test only useful for reproducing issues") - fuzzAbi([]byte("\x20\x20\x20\x20\x20\x20\x20\x20\x80\x00\x00\x00\x20\x20\x20\x20\x00")) - //fuzzAbi([]byte("asdfasdfkadsf;lasdf;lasd;lfk")) -} - -// FuzzABI is the main entrypoint for fuzzing -func FuzzABI(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - fuzzAbi(data) - }) -} - -var ( - names = []string{"_name", "name", "NAME", "name_", "__", "_name_", "n"} - stateMut = []string{"pure", "view", "payable"} - pays = []string{"true", "false"} - vNames = []string{"a", "b", "c", "d", "e", "f", "g"} - varNames = append(vNames, names...) - varTypes = []string{"bool", "address", "bytes", "string", - "uint8", "int8", "uint8", "int8", "uint16", "int16", - "uint24", "int24", "uint32", "int32", "uint40", "int40", "uint48", "int48", "uint56", "int56", - "uint64", "int64", "uint72", "int72", "uint80", "int80", "uint88", "int88", "uint96", "int96", - "uint104", "int104", "uint112", "int112", "uint120", "int120", "uint128", "int128", "uint136", "int136", - "uint144", "int144", "uint152", "int152", "uint160", "int160", "uint168", "int168", "uint176", "int176", - "uint184", "int184", "uint192", "int192", "uint200", "int200", "uint208", "int208", "uint216", "int216", - "uint224", "int224", "uint232", "int232", "uint240", "int240", "uint248", "int248", "uint256", "int256", - "bytes1", "bytes2", "bytes3", "bytes4", "bytes5", "bytes6", "bytes7", "bytes8", "bytes9", "bytes10", "bytes11", - "bytes12", "bytes13", "bytes14", "bytes15", "bytes16", "bytes17", "bytes18", "bytes19", "bytes20", "bytes21", - "bytes22", "bytes23", "bytes24", "bytes25", "bytes26", "bytes27", "bytes28", "bytes29", "bytes30", "bytes31", - "bytes32", "bytes"} -) - -func unpackPack(abi ABI, method string, input []byte) ([]interface{}, bool) { - if out, err := abi.Unpack(method, input); err == nil { - _, err := abi.Pack(method, out...) - if err != nil { - // We have some false positives as we can unpack these type successfully, but not pack them - if err.Error() == "abi: cannot use []uint8 as type [0]int8 as argument" || - err.Error() == "abi: cannot use uint8 as type int8 as argument" { - return out, false - } - panic(err) - } - return out, true - } - return nil, false -} - -func packUnpack(abi ABI, method string, input *[]interface{}) bool { - if packed, err := abi.Pack(method, input); err == nil { - outptr := reflect.New(reflect.TypeOf(input)) - err := abi.UnpackIntoInterface(outptr.Interface(), method, packed) - if err != nil { - panic(err) - } - out := outptr.Elem().Interface() - if !reflect.DeepEqual(input, out) { - panic(fmt.Sprintf("unpackPack is not equal, \ninput : %x\noutput: %x", input, out)) - } - return true - } - return false -} - -type arg struct { - name string - typ string -} - -func createABI(name string, stateMutability, payable *string, inputs []arg) (ABI, error) { - sig := fmt.Sprintf(`[{ "type" : "function", "name" : "%v" `, name) - if stateMutability != nil { - sig += fmt.Sprintf(`, "stateMutability": "%v" `, *stateMutability) - } - if payable != nil { - sig += fmt.Sprintf(`, "payable": %v `, *payable) - } - if len(inputs) > 0 { - sig += `, "inputs" : [ {` - for i, inp := range inputs { - sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ) - if i+1 < len(inputs) { - sig += "," - } - } - sig += "} ]" - sig += `, "outputs" : [ {` - for i, inp := range inputs { - sig += fmt.Sprintf(`"name" : "%v", "type" : "%v" `, inp.name, inp.typ) - if i+1 < len(inputs) { - sig += "," - } - } - sig += "} ]" - } - sig += `}]` - //fmt.Printf("sig: %s\n", sig) - return JSON(strings.NewReader(sig)) -} - -func fuzzAbi(input []byte) { - var ( - fuzzer = fuzz.NewFromGoFuzz(input) - name = oneOf(fuzzer, names) - stateM = oneOfOrNil(fuzzer, stateMut) - payable = oneOfOrNil(fuzzer, pays) - arguments []arg - ) - for i := 0; i < upTo(fuzzer, 10); i++ { - argName := oneOf(fuzzer, varNames) - argTyp := oneOf(fuzzer, varTypes) - switch upTo(fuzzer, 10) { - case 0: // 10% chance to make it a slice - argTyp += "[]" - case 1: // 10% chance to make it an array - argTyp += fmt.Sprintf("[%d]", 1+upTo(fuzzer, 30)) - default: - } - arguments = append(arguments, arg{name: argName, typ: argTyp}) - } - abi, err := createABI(name, stateM, payable, arguments) - if err != nil { - //fmt.Printf("err: %v\n", err) - panic(err) - } - structs, _ := unpackPack(abi, name, input) - _ = packUnpack(abi, name, &structs) -} - -func upTo(fuzzer *fuzz.Fuzzer, max int) int { - var i int - fuzzer.Fuzz(&i) - if i < 0 { - return (-1 - i) % max - } - return i % max -} - -func oneOf(fuzzer *fuzz.Fuzzer, options []string) string { - return options[upTo(fuzzer, len(options))] -} - -func oneOfOrNil(fuzzer *fuzz.Fuzzer, options []string) *string { - if i := upTo(fuzzer, len(options)+1); i < len(options) { - return &options[i] - } - return nil -} diff --git a/builder/accounts/abi/argument.go b/builder/accounts/abi/argument.go deleted file mode 100644 index fa5461895..000000000 --- a/builder/accounts/abi/argument.go +++ /dev/null @@ -1,273 +0,0 @@ -// 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 abi - -import ( - "encoding/json" - "errors" - "fmt" - "reflect" - "strings" -) - -// Argument holds the name of the argument and the corresponding type. -// Types are used when packing and testing arguments. -type Argument struct { - Name string - Type Type - Indexed bool // indexed is only used by events -} - -type Arguments []Argument - -type ArgumentMarshaling struct { - Name string - Type string - InternalType string - Components []ArgumentMarshaling - Indexed bool -} - -// UnmarshalJSON implements json.Unmarshaler interface. -func (argument *Argument) UnmarshalJSON(data []byte) error { - var arg ArgumentMarshaling - err := json.Unmarshal(data, &arg) - if err != nil { - return fmt.Errorf("argument json err: %v", err) - } - - argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components) - if err != nil { - return err - } - argument.Name = arg.Name - argument.Indexed = arg.Indexed - - return nil -} - -// NonIndexed returns the arguments with indexed arguments filtered out. -func (arguments Arguments) NonIndexed() Arguments { - var ret []Argument - for _, arg := range arguments { - if !arg.Indexed { - ret = append(ret, arg) - } - } - return ret -} - -// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]. -func (arguments Arguments) isTuple() bool { - return len(arguments) > 1 -} - -// Unpack performs the operation hexdata -> Go format. -func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) { - if len(data) == 0 { - if len(arguments.NonIndexed()) != 0 { - return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected") - } - return make([]interface{}, 0), nil - } - return arguments.UnpackValues(data) -} - -// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value. -func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { - // Make sure map is not nil - if v == nil { - return errors.New("abi: cannot unpack into a nil map") - } - if len(data) == 0 { - if len(arguments.NonIndexed()) != 0 { - return errors.New("abi: attempting to unmarshal an empty string while arguments are expected") - } - return nil // Nothing to unmarshal, return - } - marshalledValues, err := arguments.UnpackValues(data) - if err != nil { - return err - } - for i, arg := range arguments.NonIndexed() { - v[arg.Name] = marshalledValues[i] - } - return nil -} - -// Copy performs the operation go format -> provided struct. -func (arguments Arguments) Copy(v interface{}, values []interface{}) error { - // make sure the passed value is arguments pointer - if reflect.Ptr != reflect.ValueOf(v).Kind() { - return fmt.Errorf("abi: Unpack(non-pointer %T)", v) - } - if len(values) == 0 { - if len(arguments.NonIndexed()) != 0 { - return errors.New("abi: attempting to copy no values while arguments are expected") - } - return nil // Nothing to copy, return - } - if arguments.isTuple() { - return arguments.copyTuple(v, values) - } - return arguments.copyAtomic(v, values[0]) -} - -// unpackAtomic unpacks ( hexdata -> go ) a single value -func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error { - dst := reflect.ValueOf(v).Elem() - src := reflect.ValueOf(marshalledValues) - - if dst.Kind() == reflect.Struct { - return set(dst.Field(0), src) - } - return set(dst, src) -} - -// copyTuple copies a batch of values from marshalledValues to v. -func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error { - value := reflect.ValueOf(v).Elem() - nonIndexedArgs := arguments.NonIndexed() - - switch value.Kind() { - case reflect.Struct: - argNames := make([]string, len(nonIndexedArgs)) - for i, arg := range nonIndexedArgs { - argNames[i] = arg.Name - } - var err error - abi2struct, err := mapArgNamesToStructFields(argNames, value) - if err != nil { - return err - } - for i, arg := range nonIndexedArgs { - field := value.FieldByName(abi2struct[arg.Name]) - if !field.IsValid() { - return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name) - } - if err := set(field, reflect.ValueOf(marshalledValues[i])); err != nil { - return err - } - } - case reflect.Slice, reflect.Array: - if value.Len() < len(marshalledValues) { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) - } - for i := range nonIndexedArgs { - if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil { - return err - } - } - default: - return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", value.Type()) - } - return nil -} - -// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification, -// without supplying a struct to unpack into. Instead, this method returns a list containing the -// values. An atomic argument will be a list with one element. -func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { - nonIndexedArgs := arguments.NonIndexed() - retval := make([]interface{}, 0, len(nonIndexedArgs)) - virtualArgs := 0 - for index, arg := range nonIndexedArgs { - marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) - if err != nil { - return nil, err - } - if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) { - // If we have a static array, like [3]uint256, these are coded as - // just like uint256,uint256,uint256. - // This means that we need to add two 'virtual' arguments when - // we count the index from now on. - // - // Array values nested multiple levels deep are also encoded inline: - // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256 - // - // Calculate the full array size to get the correct offset for the next argument. - // Decrement it by 1, as the normal index increment is still applied. - virtualArgs += getTypeSize(arg.Type)/32 - 1 - } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) { - // If we have a static tuple, like (uint256, bool, uint256), these are - // coded as just like uint256,bool,uint256 - virtualArgs += getTypeSize(arg.Type)/32 - 1 - } - retval = append(retval, marshalledValue) - } - return retval, nil -} - -// PackValues performs the operation Go format -> Hexdata. -// It is the semantic opposite of UnpackValues. -func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { - return arguments.Pack(args...) -} - -// Pack performs the operation Go format -> Hexdata. -func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { - // Make sure arguments match up and pack them - abiArgs := arguments - if len(args) != len(abiArgs) { - return nil, fmt.Errorf("argument count mismatch: got %d for %d", len(args), len(abiArgs)) - } - // variable input is the output appended at the end of packed - // output. This is used for strings and bytes types input. - var variableInput []byte - - // input offset is the bytes offset for packed output - inputOffset := 0 - for _, abiArg := range abiArgs { - inputOffset += getTypeSize(abiArg.Type) - } - var ret []byte - for i, a := range args { - input := abiArgs[i] - // pack the input - packed, err := input.Type.pack(reflect.ValueOf(a)) - if err != nil { - return nil, err - } - // check for dynamic types - if isDynamicType(input.Type) { - // set the offset - ret = append(ret, packNum(reflect.ValueOf(inputOffset))...) - // calculate next offset - inputOffset += len(packed) - // append to variable input - variableInput = append(variableInput, packed...) - } else { - // append the packed value to the input - ret = append(ret, packed...) - } - } - // append the variable input at the end of the packed input - ret = append(ret, variableInput...) - - return ret, nil -} - -// ToCamelCase converts an under-score string to a camel-case string -func ToCamelCase(input string) string { - parts := strings.Split(input, "_") - for i, s := range parts { - if len(s) > 0 { - parts[i] = strings.ToUpper(s[:1]) + s[1:] - } - } - return strings.Join(parts, "") -} diff --git a/builder/accounts/abi/bind/auth.go b/builder/accounts/abi/bind/auth.go deleted file mode 100644 index 0740c6951..000000000 --- a/builder/accounts/abi/bind/auth.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2016 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 bind - -import ( - "context" - "crypto/ecdsa" - "errors" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/external" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" -) - -// ErrNoChainID is returned whenever the user failed to specify a chain id. -var ErrNoChainID = errors.New("no chain id specified") - -// ErrNotAuthorized is returned when an account is not properly unlocked. -var ErrNotAuthorized = errors.New("not authorized to sign this account") - -// NewTransactor is a utility method to easily create a transaction signer from -// an encrypted json key stream and the associated passphrase. -// -// Deprecated: Use NewTransactorWithChainID instead. -func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) { - log.Warn("WARNING: NewTransactor has been deprecated in favour of NewTransactorWithChainID") - json, err := io.ReadAll(keyin) - if err != nil { - return nil, err - } - key, err := keystore.DecryptKey(json, passphrase) - if err != nil { - return nil, err - } - return NewKeyedTransactor(key.PrivateKey), nil -} - -// NewKeyStoreTransactor is a utility method to easily create a transaction signer from -// a decrypted key from a keystore. -// -// Deprecated: Use NewKeyStoreTransactorWithChainID instead. -func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) { - log.Warn("WARNING: NewKeyStoreTransactor has been deprecated in favour of NewTransactorWithChainID") - signer := types.HomesteadSigner{} - return &TransactOpts{ - From: account.Address, - Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { - if address != account.Address { - return nil, ErrNotAuthorized - } - signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes()) - if err != nil { - return nil, err - } - return tx.WithSignature(signer, signature) - }, - Context: context.Background(), - }, nil -} - -// NewKeyedTransactor is a utility method to easily create a transaction signer -// from a single private key. -// -// Deprecated: Use NewKeyedTransactorWithChainID instead. -func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts { - log.Warn("WARNING: NewKeyedTransactor has been deprecated in favour of NewKeyedTransactorWithChainID") - keyAddr := crypto.PubkeyToAddress(key.PublicKey) - signer := types.HomesteadSigner{} - return &TransactOpts{ - From: keyAddr, - Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { - if address != keyAddr { - return nil, ErrNotAuthorized - } - signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key) - if err != nil { - return nil, err - } - return tx.WithSignature(signer, signature) - }, - Context: context.Background(), - } -} - -// NewTransactorWithChainID is a utility method to easily create a transaction signer from -// an encrypted json key stream and the associated passphrase. -func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) { - json, err := io.ReadAll(keyin) - if err != nil { - return nil, err - } - key, err := keystore.DecryptKey(json, passphrase) - if err != nil { - return nil, err - } - return NewKeyedTransactorWithChainID(key.PrivateKey, chainID) -} - -// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from -// a decrypted key from a keystore. -func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) { - if chainID == nil { - return nil, ErrNoChainID - } - signer := types.LatestSignerForChainID(chainID) - return &TransactOpts{ - From: account.Address, - Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { - if address != account.Address { - return nil, ErrNotAuthorized - } - signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes()) - if err != nil { - return nil, err - } - return tx.WithSignature(signer, signature) - }, - Context: context.Background(), - }, nil -} - -// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer -// from a single private key. -func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*TransactOpts, error) { - keyAddr := crypto.PubkeyToAddress(key.PublicKey) - if chainID == nil { - return nil, ErrNoChainID - } - signer := types.LatestSignerForChainID(chainID) - return &TransactOpts{ - From: keyAddr, - Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) { - if address != keyAddr { - return nil, ErrNotAuthorized - } - signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key) - if err != nil { - return nil, err - } - return tx.WithSignature(signer, signature) - }, - Context: context.Background(), - }, nil -} - -// NewClefTransactor is a utility method to easily create a transaction signer -// with a clef backend. -func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts { - return &TransactOpts{ - From: account.Address, - Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) { - if address != account.Address { - return nil, ErrNotAuthorized - } - return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id - }, - Context: context.Background(), - } -} diff --git a/builder/accounts/abi/bind/backend.go b/builder/accounts/abi/bind/backend.go deleted file mode 100644 index 38b304697..000000000 --- a/builder/accounts/abi/bind/backend.go +++ /dev/null @@ -1,120 +0,0 @@ -// 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 bind - -import ( - "context" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -var ( - // ErrNoCode is returned by call and transact operations for which the requested - // recipient contract to operate on does not exist in the state db or does not - // have any code associated with it (i.e. self-destructed). - ErrNoCode = errors.New("no contract code at given address") - - // ErrNoPendingState is raised when attempting to perform a pending state action - // on a backend that doesn't implement PendingContractCaller. - ErrNoPendingState = errors.New("backend does not support pending state") - - // ErrNoBlockHashState is raised when attempting to perform a block hash action - // on a backend that doesn't implement BlockHashContractCaller. - ErrNoBlockHashState = errors.New("backend does not support block hash state") - - // ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves - // an empty contract behind. - ErrNoCodeAfterDeploy = errors.New("no contract code after deployment") -) - -// ContractCaller defines the methods needed to allow operating with a contract on a read -// only basis. -type ContractCaller interface { - // CodeAt returns the code of the given account. This is needed to differentiate - // between contract internal errors and the local chain being out of sync. - CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) - - // CallContract executes an Ethereum contract call with the specified data as the - // input. - CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) -} - -// PendingContractCaller defines methods to perform contract calls on the pending state. -// Call will try to discover this interface when access to the pending state is requested. -// If the backend does not support the pending state, Call returns ErrNoPendingState. -type PendingContractCaller interface { - // PendingCodeAt returns the code of the given account in the pending state. - PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) - - // PendingCallContract executes an Ethereum contract call against the pending state. - PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) -} - -// BlockHashContractCaller defines methods to perform contract calls on a specific block hash. -// Call will try to discover this interface when access to a block by hash is requested. -// If the backend does not support the block hash state, Call returns ErrNoBlockHashState. -type BlockHashContractCaller interface { - // CodeAtHash returns the code of the given account in the state at the specified block hash. - CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) - - // CallContractAtHash executes an Ethereum contract call against the state at the specified block hash. - CallContractAtHash(ctx context.Context, call ethereum.CallMsg, blockHash common.Hash) ([]byte, error) -} - -// ContractTransactor defines the methods needed to allow operating with a contract -// on a write only basis. Besides the transacting method, the remainder are helpers -// used when the user does not provide some needed values, but rather leaves it up -// to the transactor to decide. -type ContractTransactor interface { - ethereum.GasEstimator - ethereum.GasPricer - ethereum.GasPricer1559 - ethereum.TransactionSender - - // HeaderByNumber returns a block header from the current canonical chain. If - // number is nil, the latest known header is returned. - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) - - // PendingCodeAt returns the code of the given account in the pending state. - PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) - - // PendingNonceAt retrieves the current pending nonce associated with an account. - PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) -} - -// DeployBackend wraps the operations needed by WaitMined and WaitDeployed. -type DeployBackend interface { - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) -} - -// ContractFilterer defines the methods needed to access log events using one-off -// queries or continuous event subscriptions. -type ContractFilterer interface { - ethereum.LogFilterer -} - -// ContractBackend defines the methods needed to work with contracts on a read-write basis. -type ContractBackend interface { - ContractCaller - ContractTransactor - ContractFilterer -} diff --git a/builder/accounts/abi/bind/backends/simulated.go b/builder/accounts/abi/bind/backends/simulated.go deleted file mode 100644 index dfd929695..000000000 --- a/builder/accounts/abi/bind/backends/simulated.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 backends - -import ( - "context" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient/simulated" -) - -// SimulatedBackend is a simulated blockchain. -// Deprecated: use package github.com/ethereum/go-ethereum/ethclient/simulated instead. -type SimulatedBackend struct { - *simulated.Backend - simulated.Client -} - -// Fork sets the head to a new block, which is based on the provided parentHash. -func (b *SimulatedBackend) Fork(ctx context.Context, parentHash common.Hash) error { - return b.Backend.Fork(parentHash) -} - -// NewSimulatedBackend creates a new binding backend using a simulated blockchain -// for testing purposes. -// -// A simulated backend always uses chainID 1337. -// -// Deprecated: please use simulated.Backend from package -// github.com/ethereum/go-ethereum/ethclient/simulated instead. -func NewSimulatedBackend(alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBackend { - b := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(gasLimit)) - return &SimulatedBackend{ - Backend: b, - Client: b.Client(), - } -} diff --git a/builder/accounts/abi/bind/base.go b/builder/accounts/abi/bind/base.go deleted file mode 100644 index 96d284cdc..000000000 --- a/builder/accounts/abi/bind/base.go +++ /dev/null @@ -1,565 +0,0 @@ -// 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 bind - -import ( - "context" - "errors" - "fmt" - "math/big" - "strings" - "sync" - - "github.com/ethereum/go-ethereum" - "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/crypto" - "github.com/ethereum/go-ethereum/event" -) - -const basefeeWiggleMultiplier = 2 - -var ( - errNoEventSignature = errors.New("no event signature") - errEventSignatureMismatch = errors.New("event signature mismatch") -) - -// SignerFn is a signer function callback when a contract requires a method to -// sign the transaction before submission. -type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error) - -// CallOpts is the collection of options to fine tune a contract call request. -type CallOpts struct { - Pending bool // Whether to operate on the pending state or the last known one - From common.Address // Optional the sender address, otherwise the first account is used - BlockNumber *big.Int // Optional the block number on which the call should be performed - BlockHash common.Hash // Optional the block hash on which the call should be performed - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) -} - -// TransactOpts is the collection of authorization data required to create a -// valid Ethereum transaction. -type TransactOpts struct { - From common.Address // Ethereum account to send the transaction from - Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state) - Signer SignerFn // Method to use for signing the transaction (mandatory) - - Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds) - GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle) - GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle) - GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle) - GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate) - - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) - - NoSend bool // Do all transact steps but do not send the transaction -} - -// FilterOpts is the collection of options to fine tune filtering for events -// within a bound contract. -type FilterOpts struct { - Start uint64 // Start of the queried range - End *uint64 // End of the range (nil = latest) - - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) -} - -// WatchOpts is the collection of options to fine tune subscribing for events -// within a bound contract. -type WatchOpts struct { - Start *uint64 // Start of the queried range (nil = latest) - Context context.Context // Network context to support cancellation and timeouts (nil = no timeout) -} - -// MetaData collects all metadata for a bound contract. -type MetaData struct { - mu sync.Mutex - Sigs map[string]string - Bin string - ABI string - ab *abi.ABI -} - -func (m *MetaData) GetAbi() (*abi.ABI, error) { - m.mu.Lock() - defer m.mu.Unlock() - if m.ab != nil { - return m.ab, nil - } - if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil { - return nil, err - } else { - m.ab = &parsed - } - return m.ab, nil -} - -// BoundContract is the base wrapper object that reflects a contract on the -// Ethereum network. It contains a collection of methods that are used by the -// higher level contract bindings to operate. -type BoundContract struct { - address common.Address // Deployment address of the contract on the Ethereum blockchain - abi abi.ABI // Reflect based ABI to access the correct Ethereum methods - caller ContractCaller // Read interface to interact with the blockchain - transactor ContractTransactor // Write interface to interact with the blockchain - filterer ContractFilterer // Event filtering to interact with the blockchain -} - -// NewBoundContract creates a low level contract interface through which calls -// and transactions may be made through. -func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller, transactor ContractTransactor, filterer ContractFilterer) *BoundContract { - return &BoundContract{ - address: address, - abi: abi, - caller: caller, - transactor: transactor, - filterer: filterer, - } -} - -// DeployContract deploys a contract onto the Ethereum blockchain and binds the -// deployment address with a Go wrapper. -func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) { - // Otherwise try to deploy the contract - c := NewBoundContract(common.Address{}, abi, backend, backend, backend) - - input, err := c.abi.Pack("", params...) - if err != nil { - return common.Address{}, nil, nil, err - } - tx, err := c.transact(opts, nil, append(bytecode, input...)) - if err != nil { - return common.Address{}, nil, nil, err - } - c.address = crypto.CreateAddress(opts.From, tx.Nonce()) - return c.address, tx, c, 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 (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method string, params ...interface{}) error { - // Don't crash on a lazy user - if opts == nil { - opts = new(CallOpts) - } - if results == nil { - results = new([]interface{}) - } - // Pack the input, call and unpack the results - input, err := c.abi.Pack(method, params...) - if err != nil { - return err - } - var ( - msg = ethereum.CallMsg{From: opts.From, To: &c.address, Data: input} - ctx = ensureContext(opts.Context) - code []byte - output []byte - ) - if opts.Pending { - pb, ok := c.caller.(PendingContractCaller) - if !ok { - return ErrNoPendingState - } - output, err = pb.PendingCallContract(ctx, msg) - if err != nil { - return err - } - if len(output) == 0 { - // Make sure we have a contract to operate on, and bail out otherwise. - if code, err = pb.PendingCodeAt(ctx, c.address); err != nil { - return err - } else if len(code) == 0 { - return ErrNoCode - } - } - } else if opts.BlockHash != (common.Hash{}) { - bh, ok := c.caller.(BlockHashContractCaller) - if !ok { - return ErrNoBlockHashState - } - output, err = bh.CallContractAtHash(ctx, msg, opts.BlockHash) - if err != nil { - return err - } - if len(output) == 0 { - // Make sure we have a contract to operate on, and bail out otherwise. - if code, err = bh.CodeAtHash(ctx, c.address, opts.BlockHash); err != nil { - return err - } else if len(code) == 0 { - return ErrNoCode - } - } - } else { - output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber) - if err != nil { - return err - } - if len(output) == 0 { - // Make sure we have a contract to operate on, and bail out otherwise. - if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil { - return err - } else if len(code) == 0 { - return ErrNoCode - } - } - } - - if len(*results) == 0 { - res, err := c.abi.Unpack(method, output) - *results = res - return err - } - res := *results - return c.abi.UnpackIntoInterface(res[0], method, output) -} - -// Transact invokes the (paid) contract method with params as input values. -func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - // Otherwise pack up the parameters and invoke the contract - input, err := c.abi.Pack(method, params...) - if err != nil { - return nil, err - } - // todo(rjl493456442) check whether the method is payable or not, - // reject invalid transaction at the first place - return c.transact(opts, &c.address, input) -} - -// RawTransact initiates a transaction with the given raw calldata as the input. -// It's usually used to initiate transactions for invoking **Fallback** function. -func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) { - // todo(rjl493456442) check whether the method is payable or not, - // reject invalid transaction at the first place - return c.transact(opts, &c.address, calldata) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error) { - // todo(rjl493456442) check the payable fallback or receive is defined - // or not, reject invalid transaction at the first place - return c.transact(opts, &c.address, nil) -} - -func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Address, input []byte, head *types.Header) (*types.Transaction, error) { - // Normalize value - value := opts.Value - if value == nil { - value = new(big.Int) - } - // Estimate TipCap - gasTipCap := opts.GasTipCap - if gasTipCap == nil { - tip, err := c.transactor.SuggestGasTipCap(ensureContext(opts.Context)) - if err != nil { - return nil, err - } - gasTipCap = tip - } - // Estimate FeeCap - gasFeeCap := opts.GasFeeCap - if gasFeeCap == nil { - gasFeeCap = new(big.Int).Add( - gasTipCap, - new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)), - ) - } - if gasFeeCap.Cmp(gasTipCap) < 0 { - return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap) - } - // Estimate GasLimit - gasLimit := opts.GasLimit - if opts.GasLimit == 0 { - var err error - gasLimit, err = c.estimateGasLimit(opts, contract, input, nil, gasTipCap, gasFeeCap, value) - if err != nil { - return nil, err - } - } - // create the transaction - nonce, err := c.getNonce(opts) - if err != nil { - return nil, err - } - baseTx := &types.DynamicFeeTx{ - To: contract, - Nonce: nonce, - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - Gas: gasLimit, - Value: value, - Data: input, - } - return types.NewTx(baseTx), nil -} - -func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) { - if opts.GasFeeCap != nil || opts.GasTipCap != nil { - return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet") - } - // Normalize value - value := opts.Value - if value == nil { - value = new(big.Int) - } - // Estimate GasPrice - gasPrice := opts.GasPrice - if gasPrice == nil { - price, err := c.transactor.SuggestGasPrice(ensureContext(opts.Context)) - if err != nil { - return nil, err - } - gasPrice = price - } - // Estimate GasLimit - gasLimit := opts.GasLimit - if opts.GasLimit == 0 { - var err error - gasLimit, err = c.estimateGasLimit(opts, contract, input, gasPrice, nil, nil, value) - if err != nil { - return nil, err - } - } - // create the transaction - nonce, err := c.getNonce(opts) - if err != nil { - return nil, err - } - baseTx := &types.LegacyTx{ - To: contract, - Nonce: nonce, - GasPrice: gasPrice, - Gas: gasLimit, - Value: value, - Data: input, - } - return types.NewTx(baseTx), nil -} - -func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Address, input []byte, gasPrice, gasTipCap, gasFeeCap, value *big.Int) (uint64, error) { - if contract != nil { - // Gas estimation cannot succeed without code for method invocations. - if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil { - return 0, err - } else if len(code) == 0 { - return 0, ErrNoCode - } - } - msg := ethereum.CallMsg{ - From: opts.From, - To: contract, - GasPrice: gasPrice, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Value: value, - Data: input, - } - return c.transactor.EstimateGas(ensureContext(opts.Context), msg) -} - -func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) { - if opts.Nonce == nil { - return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From) - } else { - return opts.Nonce.Uint64(), nil - } -} - -// transact executes an actual transaction invocation, first deriving any missing -// authorization fields, and then scheduling the transaction for execution. -func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) { - if opts.GasPrice != nil && (opts.GasFeeCap != nil || opts.GasTipCap != nil) { - return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") - } - // Create the transaction - var ( - rawTx *types.Transaction - err error - ) - if opts.GasPrice != nil { - rawTx, err = c.createLegacyTx(opts, contract, input) - } else if opts.GasFeeCap != nil && opts.GasTipCap != nil { - rawTx, err = c.createDynamicTx(opts, contract, input, nil) - } else { - // Only query for basefee if gasPrice not specified - if head, errHead := c.transactor.HeaderByNumber(ensureContext(opts.Context), nil); errHead != nil { - return nil, errHead - } else if head.BaseFee != nil { - rawTx, err = c.createDynamicTx(opts, contract, input, head) - } else { - // Chain is not London ready -> use legacy transaction - rawTx, err = c.createLegacyTx(opts, contract, input) - } - } - if err != nil { - return nil, err - } - // Sign the transaction and schedule it for execution - if opts.Signer == nil { - return nil, errors.New("no signer to authorize the transaction with") - } - signedTx, err := opts.Signer(opts.From, rawTx) - if err != nil { - return nil, err - } - if opts.NoSend { - return signedTx, nil - } - if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil { - return nil, err - } - return signedTx, nil -} - -// FilterLogs filters contract logs for past blocks, returning the necessary -// channels to construct a strongly typed bound iterator on top of them. -func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) { - // Don't crash on a lazy user - if opts == nil { - opts = new(FilterOpts) - } - // Append the event selector to the query parameters and construct the topic set - query = append([][]interface{}{{c.abi.Events[name].ID}}, query...) - - topics, err := abi.MakeTopics(query...) - if err != nil { - return nil, nil, err - } - // Start the background filtering - logs := make(chan types.Log, 128) - - config := ethereum.FilterQuery{ - Addresses: []common.Address{c.address}, - Topics: topics, - FromBlock: new(big.Int).SetUint64(opts.Start), - } - if opts.End != nil { - config.ToBlock = new(big.Int).SetUint64(*opts.End) - } - /* TODO(karalabe): Replace the rest of the method below with this when supported - sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs) - */ - buff, err := c.filterer.FilterLogs(ensureContext(opts.Context), config) - if err != nil { - return nil, nil, err - } - sub, err := event.NewSubscription(func(quit <-chan struct{}) error { - for _, log := range buff { - select { - case logs <- log: - case <-quit: - return nil - } - } - return nil - }), nil - - if err != nil { - return nil, nil, err - } - return logs, sub, nil -} - -// WatchLogs filters subscribes to contract logs for future blocks, returning a -// subscription object that can be used to tear down the watcher. -func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]interface{}) (chan types.Log, event.Subscription, error) { - // Don't crash on a lazy user - if opts == nil { - opts = new(WatchOpts) - } - // Append the event selector to the query parameters and construct the topic set - query = append([][]interface{}{{c.abi.Events[name].ID}}, query...) - - topics, err := abi.MakeTopics(query...) - if err != nil { - return nil, nil, err - } - // Start the background filtering - logs := make(chan types.Log, 128) - - config := ethereum.FilterQuery{ - Addresses: []common.Address{c.address}, - Topics: topics, - } - if opts.Start != nil { - config.FromBlock = new(big.Int).SetUint64(*opts.Start) - } - sub, err := c.filterer.SubscribeFilterLogs(ensureContext(opts.Context), config, logs) - if err != nil { - return nil, nil, err - } - return logs, sub, nil -} - -// UnpackLog unpacks a retrieved log into the provided output structure. -func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error { - // Anonymous events are not supported. - if len(log.Topics) == 0 { - return errNoEventSignature - } - if log.Topics[0] != c.abi.Events[event].ID { - return errEventSignatureMismatch - } - if len(log.Data) > 0 { - if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil { - return err - } - } - var indexed abi.Arguments - for _, arg := range c.abi.Events[event].Inputs { - if arg.Indexed { - indexed = append(indexed, arg) - } - } - return abi.ParseTopics(out, indexed, log.Topics[1:]) -} - -// UnpackLogIntoMap unpacks a retrieved log into the provided map. -func (c *BoundContract) UnpackLogIntoMap(out map[string]interface{}, event string, log types.Log) error { - // Anonymous events are not supported. - if len(log.Topics) == 0 { - return errNoEventSignature - } - if log.Topics[0] != c.abi.Events[event].ID { - return errEventSignatureMismatch - } - if len(log.Data) > 0 { - if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil { - return err - } - } - var indexed abi.Arguments - for _, arg := range c.abi.Events[event].Inputs { - if arg.Indexed { - indexed = append(indexed, arg) - } - } - return abi.ParseTopicsIntoMap(out, indexed, log.Topics[1:]) -} - -// ensureContext is a helper method to ensure a context is not nil, even if the -// user specified it as such. -func ensureContext(ctx context.Context) context.Context { - if ctx == nil { - return context.Background() - } - return ctx -} diff --git a/builder/accounts/abi/bind/base_test.go b/builder/accounts/abi/bind/base_test.go deleted file mode 100644 index f7eb7d14d..000000000 --- a/builder/accounts/abi/bind/base_test.go +++ /dev/null @@ -1,589 +0,0 @@ -// 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 bind_test - -import ( - "context" - "errors" - "math/big" - "reflect" - "strings" - "testing" - - "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/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/stretchr/testify/assert" -) - -func mockSign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return tx, nil } - -type mockTransactor struct { - baseFee *big.Int - gasTipCap *big.Int - gasPrice *big.Int - suggestGasTipCapCalled bool - suggestGasPriceCalled bool -} - -func (mt *mockTransactor) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return &types.Header{BaseFee: mt.baseFee}, nil -} - -func (mt *mockTransactor) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - return []byte{1}, nil -} - -func (mt *mockTransactor) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - return 0, nil -} - -func (mt *mockTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - mt.suggestGasPriceCalled = true - return mt.gasPrice, nil -} - -func (mt *mockTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - mt.suggestGasTipCapCalled = true - return mt.gasTipCap, nil -} - -func (mt *mockTransactor) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { - return 0, nil -} - -func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error { - return nil -} - -type mockCaller struct { - codeAtBlockNumber *big.Int - callContractBlockNumber *big.Int - callContractBytes []byte - callContractErr error - codeAtBytes []byte - codeAtErr error -} - -func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { - mc.codeAtBlockNumber = blockNumber - return mc.codeAtBytes, mc.codeAtErr -} - -func (mc *mockCaller) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - mc.callContractBlockNumber = blockNumber - return mc.callContractBytes, mc.callContractErr -} - -type mockPendingCaller struct { - *mockCaller - pendingCodeAtBytes []byte - pendingCodeAtErr error - pendingCodeAtCalled bool - pendingCallContractCalled bool - pendingCallContractBytes []byte - pendingCallContractErr error -} - -func (mc *mockPendingCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) { - mc.pendingCodeAtCalled = true - return mc.pendingCodeAtBytes, mc.pendingCodeAtErr -} - -func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) { - mc.pendingCallContractCalled = true - return mc.pendingCallContractBytes, mc.pendingCallContractErr -} - -type mockBlockHashCaller struct { - *mockCaller - codeAtHashBytes []byte - codeAtHashErr error - codeAtHashCalled bool - callContractAtHashCalled bool - callContractAtHashBytes []byte - callContractAtHashErr error -} - -func (mc *mockBlockHashCaller) CodeAtHash(ctx context.Context, contract common.Address, hash common.Hash) ([]byte, error) { - mc.codeAtHashCalled = true - return mc.codeAtHashBytes, mc.codeAtHashErr -} - -func (mc *mockBlockHashCaller) CallContractAtHash(ctx context.Context, call ethereum.CallMsg, hash common.Hash) ([]byte, error) { - mc.callContractAtHashCalled = true - return mc.callContractAtHashBytes, mc.callContractAtHashErr -} - -func TestPassingBlockNumber(t *testing.T) { - t.Parallel() - mc := &mockPendingCaller{ - mockCaller: &mockCaller{ - codeAtBytes: []byte{1, 2, 3}, - }, - } - - bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ - Methods: map[string]abi.Method{ - "something": { - Name: "something", - Outputs: abi.Arguments{}, - }, - }, - }, mc, nil, nil) - - blockNumber := big.NewInt(42) - - bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something") - - if mc.callContractBlockNumber != blockNumber { - t.Fatalf("CallContract() was not passed the block number") - } - - if mc.codeAtBlockNumber != blockNumber { - t.Fatalf("CodeAt() was not passed the block number") - } - - bc.Call(&bind.CallOpts{}, nil, "something") - - if mc.callContractBlockNumber != nil { - t.Fatalf("CallContract() was passed a block number when it should not have been") - } - - if mc.codeAtBlockNumber != nil { - t.Fatalf("CodeAt() was passed a block number when it should not have been") - } - - bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something") - - if !mc.pendingCallContractCalled { - t.Fatalf("CallContract() was not passed the block number") - } - - if !mc.pendingCodeAtCalled { - t.Fatalf("CodeAt() was not passed the block number") - } -} - -const hexData = "0x000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158" - -func TestUnpackIndexedStringTyLogIntoMap(t *testing.T) { - t.Parallel() - hash := crypto.Keccak256Hash([]byte("testName")) - topics := []common.Hash{ - crypto.Keccak256Hash([]byte("received(string,address,uint256,bytes)")), - hash, - } - mockLog := newMockLog(topics, common.HexToHash("0x0")) - - abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - expectedReceivedMap := map[string]interface{}{ - "name": hash, - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - unpackAndCheck(t, bc, expectedReceivedMap, mockLog) -} - -func TestUnpackAnonymousLogIntoMap(t *testing.T) { - t.Parallel() - mockLog := newMockLog(nil, common.HexToHash("0x0")) - - abiString := `[{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - var received map[string]interface{} - err := bc.UnpackLogIntoMap(received, "received", mockLog) - if err == nil { - t.Error("unpacking anonymous event is not supported") - } - if err.Error() != "no event signature" { - t.Errorf("expected error 'no event signature', got '%s'", err) - } -} - -func TestUnpackIndexedSliceTyLogIntoMap(t *testing.T) { - t.Parallel() - sliceBytes, err := rlp.EncodeToBytes([]string{"name1", "name2", "name3", "name4"}) - if err != nil { - t.Fatal(err) - } - hash := crypto.Keccak256Hash(sliceBytes) - topics := []common.Hash{ - crypto.Keccak256Hash([]byte("received(string[],address,uint256,bytes)")), - hash, - } - mockLog := newMockLog(topics, common.HexToHash("0x0")) - - abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"names","type":"string[]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - expectedReceivedMap := map[string]interface{}{ - "names": hash, - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - unpackAndCheck(t, bc, expectedReceivedMap, mockLog) -} - -func TestUnpackIndexedArrayTyLogIntoMap(t *testing.T) { - t.Parallel() - arrBytes, err := rlp.EncodeToBytes([2]common.Address{common.HexToAddress("0x0"), common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2")}) - if err != nil { - t.Fatal(err) - } - hash := crypto.Keccak256Hash(arrBytes) - topics := []common.Hash{ - crypto.Keccak256Hash([]byte("received(address[2],address,uint256,bytes)")), - hash, - } - mockLog := newMockLog(topics, common.HexToHash("0x0")) - - abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"addresses","type":"address[2]"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - expectedReceivedMap := map[string]interface{}{ - "addresses": hash, - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - unpackAndCheck(t, bc, expectedReceivedMap, mockLog) -} - -func TestUnpackIndexedFuncTyLogIntoMap(t *testing.T) { - t.Parallel() - mockAddress := common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2") - addrBytes := mockAddress.Bytes() - hash := crypto.Keccak256Hash([]byte("mockFunction(address,uint)")) - functionSelector := hash[:4] - functionTyBytes := append(addrBytes, functionSelector...) - var functionTy [24]byte - copy(functionTy[:], functionTyBytes[0:24]) - topics := []common.Hash{ - crypto.Keccak256Hash([]byte("received(function,address,uint256,bytes)")), - common.BytesToHash(functionTyBytes), - } - mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) - abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"function","type":"function"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - expectedReceivedMap := map[string]interface{}{ - "function": functionTy, - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - unpackAndCheck(t, bc, expectedReceivedMap, mockLog) -} - -func TestUnpackIndexedBytesTyLogIntoMap(t *testing.T) { - t.Parallel() - bytes := []byte{1, 2, 3, 4, 5} - hash := crypto.Keccak256Hash(bytes) - topics := []common.Hash{ - crypto.Keccak256Hash([]byte("received(bytes,address,uint256,bytes)")), - hash, - } - mockLog := newMockLog(topics, common.HexToHash("0x5c698f13940a2153440c6d19660878bc90219d9298fdcf37365aa8d88d40fc42")) - - abiString := `[{"anonymous":false,"inputs":[{"indexed":true,"name":"content","type":"bytes"},{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"}]` - parsedAbi, _ := abi.JSON(strings.NewReader(abiString)) - bc := bind.NewBoundContract(common.HexToAddress("0x0"), parsedAbi, nil, nil, nil) - - expectedReceivedMap := map[string]interface{}{ - "content": hash, - "sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"), - "amount": big.NewInt(1), - "memo": []byte{88}, - } - unpackAndCheck(t, bc, expectedReceivedMap, mockLog) -} - -func TestTransactGasFee(t *testing.T) { - t.Parallel() - assert := assert.New(t) - - // GasTipCap and GasFeeCap - // When opts.GasTipCap and opts.GasFeeCap are nil - mt := &mockTransactor{baseFee: big.NewInt(100), gasTipCap: big.NewInt(5)} - bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) - opts := &bind.TransactOpts{Signer: mockSign} - tx, err := bc.Transact(opts, "") - assert.Nil(err) - assert.Equal(big.NewInt(5), tx.GasTipCap()) - assert.Equal(big.NewInt(205), tx.GasFeeCap()) - assert.Nil(opts.GasTipCap) - assert.Nil(opts.GasFeeCap) - assert.True(mt.suggestGasTipCapCalled) - - // Second call to Transact should use latest suggested GasTipCap - mt.gasTipCap = big.NewInt(6) - mt.suggestGasTipCapCalled = false - tx, err = bc.Transact(opts, "") - assert.Nil(err) - assert.Equal(big.NewInt(6), tx.GasTipCap()) - assert.Equal(big.NewInt(206), tx.GasFeeCap()) - assert.True(mt.suggestGasTipCapCalled) - - // GasPrice - // When opts.GasPrice is nil - mt = &mockTransactor{gasPrice: big.NewInt(5)} - bc = bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil) - opts = &bind.TransactOpts{Signer: mockSign} - tx, err = bc.Transact(opts, "") - assert.Nil(err) - assert.Equal(big.NewInt(5), tx.GasPrice()) - assert.Nil(opts.GasPrice) - assert.True(mt.suggestGasPriceCalled) - - // Second call to Transact should use latest suggested GasPrice - mt.gasPrice = big.NewInt(6) - mt.suggestGasPriceCalled = false - tx, err = bc.Transact(opts, "") - assert.Nil(err) - assert.Equal(big.NewInt(6), tx.GasPrice()) - assert.True(mt.suggestGasPriceCalled) -} - -func unpackAndCheck(t *testing.T, bc *bind.BoundContract, expected map[string]interface{}, mockLog types.Log) { - received := make(map[string]interface{}) - if err := bc.UnpackLogIntoMap(received, "received", mockLog); err != nil { - t.Error(err) - } - - if len(received) != len(expected) { - t.Fatalf("unpacked map length %v not equal expected length of %v", len(received), len(expected)) - } - for name, elem := range expected { - if !reflect.DeepEqual(elem, received[name]) { - t.Errorf("field %v does not match expected, want %v, got %v", name, elem, received[name]) - } - } -} - -func newMockLog(topics []common.Hash, txHash common.Hash) types.Log { - return types.Log{ - Address: common.HexToAddress("0x0"), - Topics: topics, - Data: hexutil.MustDecode(hexData), - BlockNumber: uint64(26), - TxHash: txHash, - TxIndex: 111, - BlockHash: common.BytesToHash([]byte{1, 2, 3, 4, 5}), - Index: 7, - Removed: false, - } -} - -func TestCall(t *testing.T) { - t.Parallel() - var method, methodWithArg = "something", "somethingArrrrg" - tests := []struct { - name, method string - opts *bind.CallOpts - mc bind.ContractCaller - results *[]interface{} - wantErr bool - wantErrExact error - }{{ - name: "ok not pending", - mc: &mockCaller{ - codeAtBytes: []byte{0}, - }, - method: method, - }, { - name: "ok pending", - mc: &mockPendingCaller{ - pendingCodeAtBytes: []byte{0}, - }, - opts: &bind.CallOpts{ - Pending: true, - }, - method: method, - }, { - name: "ok hash", - mc: &mockBlockHashCaller{ - codeAtHashBytes: []byte{0}, - }, - opts: &bind.CallOpts{ - BlockHash: common.Hash{0xaa}, - }, - method: method, - }, { - name: "pack error, no method", - mc: new(mockCaller), - method: "else", - wantErr: true, - }, { - name: "interface error, pending but not a PendingContractCaller", - mc: new(mockCaller), - opts: &bind.CallOpts{ - Pending: true, - }, - method: method, - wantErrExact: bind.ErrNoPendingState, - }, { - name: "interface error, blockHash but not a BlockHashContractCaller", - mc: new(mockCaller), - opts: &bind.CallOpts{ - BlockHash: common.Hash{0xaa}, - }, - method: method, - wantErrExact: bind.ErrNoBlockHashState, - }, { - name: "pending call canceled", - mc: &mockPendingCaller{ - pendingCallContractErr: context.DeadlineExceeded, - }, - opts: &bind.CallOpts{ - Pending: true, - }, - method: method, - wantErrExact: context.DeadlineExceeded, - }, { - name: "pending code at error", - mc: &mockPendingCaller{ - pendingCodeAtErr: errors.New(""), - }, - opts: &bind.CallOpts{ - Pending: true, - }, - method: method, - wantErr: true, - }, { - name: "no pending code at", - mc: new(mockPendingCaller), - opts: &bind.CallOpts{ - Pending: true, - }, - method: method, - wantErrExact: bind.ErrNoCode, - }, { - name: "call contract error", - mc: &mockCaller{ - callContractErr: context.DeadlineExceeded, - }, - method: method, - wantErrExact: context.DeadlineExceeded, - }, { - name: "code at error", - mc: &mockCaller{ - codeAtErr: errors.New(""), - }, - method: method, - wantErr: true, - }, { - name: "no code at", - mc: new(mockCaller), - method: method, - wantErrExact: bind.ErrNoCode, - }, { - name: "call contract at hash error", - mc: &mockBlockHashCaller{ - callContractAtHashErr: context.DeadlineExceeded, - }, - opts: &bind.CallOpts{ - BlockHash: common.Hash{0xaa}, - }, - method: method, - wantErrExact: context.DeadlineExceeded, - }, { - name: "code at error", - mc: &mockBlockHashCaller{ - codeAtHashErr: errors.New(""), - }, - opts: &bind.CallOpts{ - BlockHash: common.Hash{0xaa}, - }, - method: method, - wantErr: true, - }, { - name: "no code at hash", - mc: new(mockBlockHashCaller), - opts: &bind.CallOpts{ - BlockHash: common.Hash{0xaa}, - }, - method: method, - wantErrExact: bind.ErrNoCode, - }, { - name: "unpack error missing arg", - mc: &mockCaller{ - codeAtBytes: []byte{0}, - }, - method: methodWithArg, - wantErr: true, - }, { - name: "interface unpack error", - mc: &mockCaller{ - codeAtBytes: []byte{0}, - }, - method: method, - results: &[]interface{}{0}, - wantErr: true, - }} - for _, test := range tests { - bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ - Methods: map[string]abi.Method{ - method: { - Name: method, - Outputs: abi.Arguments{}, - }, - methodWithArg: { - Name: methodWithArg, - Outputs: abi.Arguments{abi.Argument{}}, - }, - }, - }, test.mc, nil, nil) - err := bc.Call(test.opts, test.results, test.method) - if test.wantErr || test.wantErrExact != nil { - if err == nil { - t.Fatalf("%q expected error", test.name) - } - if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) { - t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err) - } - continue - } - if err != nil { - t.Fatalf("%q unexpected error: %v", test.name, err) - } - } -} - -// TestCrashers contains some strings which previously caused the abi codec to crash. -func TestCrashers(t *testing.T) { - t.Parallel() - abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`)) - abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`)) - abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`)) - abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"foo.Bar"}]}]}]`)) -} diff --git a/builder/accounts/abi/bind/bind.go b/builder/accounts/abi/bind/bind.go deleted file mode 100644 index e902345f0..000000000 --- a/builder/accounts/abi/bind/bind.go +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright 2016 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 bind generates Ethereum contract Go bindings. -// -// Detailed usage document and tutorial available on the go-ethereum Wiki page: -// https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts -package bind - -import ( - "bytes" - "fmt" - "go/format" - "regexp" - "strings" - "text/template" - "unicode" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/log" -) - -// Lang is a target programming language selector to generate bindings for. -type Lang int - -const ( - LangGo Lang = iota -) - -func isKeyWord(arg string) bool { - switch arg { - case "break": - case "case": - case "chan": - case "const": - case "continue": - case "default": - case "defer": - case "else": - case "fallthrough": - case "for": - case "func": - case "go": - case "goto": - case "if": - case "import": - case "interface": - case "iota": - case "map": - case "make": - case "new": - case "package": - case "range": - case "return": - case "select": - case "struct": - case "switch": - case "type": - case "var": - default: - return false - } - - return true -} - -// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant -// to be used as is in client code, but rather as an intermediate struct which -// enforces compile time type safety and naming convention as opposed to having to -// manually maintain hard coded strings that break on runtime. -func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]string, pkg string, lang Lang, libs map[string]string, aliases map[string]string) (string, error) { - var ( - // contracts is the map of each individual contract requested binding - contracts = make(map[string]*tmplContract) - - // structs is the map of all redeclared structs shared by passed contracts. - structs = make(map[string]*tmplStruct) - - // isLib is the map used to flag each encountered library as such - isLib = make(map[string]struct{}) - ) - for i := 0; i < len(types); i++ { - // Parse the actual ABI to generate the binding for - evmABI, err := abi.JSON(strings.NewReader(abis[i])) - if err != nil { - return "", err - } - // Strip any whitespace from the JSON ABI - strippedABI := strings.Map(func(r rune) rune { - if unicode.IsSpace(r) { - return -1 - } - return r - }, abis[i]) - - // Extract the call and transact methods; events, struct definitions; and sort them alphabetically - var ( - calls = make(map[string]*tmplMethod) - transacts = make(map[string]*tmplMethod) - events = make(map[string]*tmplEvent) - fallback *tmplMethod - receive *tmplMethod - - // identifiers are used to detect duplicated identifiers of functions - // and events. For all calls, transacts and events, abigen will generate - // corresponding bindings. However we have to ensure there is no - // identifier collisions in the bindings of these categories. - callIdentifiers = make(map[string]bool) - transactIdentifiers = make(map[string]bool) - eventIdentifiers = make(map[string]bool) - ) - - for _, input := range evmABI.Constructor.Inputs { - if hasStruct(input.Type) { - bindStructType[lang](input.Type, structs) - } - } - - for _, original := range evmABI.Methods { - // Normalize the method for capital cases and non-anonymous inputs/outputs - normalized := original - normalizedName := methodNormalizer[lang](alias(aliases, original.Name)) - // Ensure there is no duplicated identifier - var identifiers = callIdentifiers - if !original.IsConstant() { - identifiers = transactIdentifiers - } - // Name shouldn't start with a digit. It will make the generated code invalid. - if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) { - normalizedName = fmt.Sprintf("M%s", normalizedName) - normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool { - _, ok := identifiers[name] - return ok - }) - } - if identifiers[normalizedName] { - return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName) - } - identifiers[normalizedName] = true - - normalized.Name = normalizedName - normalized.Inputs = make([]abi.Argument, len(original.Inputs)) - copy(normalized.Inputs, original.Inputs) - for j, input := range normalized.Inputs { - if input.Name == "" || isKeyWord(input.Name) { - normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) - } - if hasStruct(input.Type) { - bindStructType[lang](input.Type, structs) - } - } - normalized.Outputs = make([]abi.Argument, len(original.Outputs)) - copy(normalized.Outputs, original.Outputs) - for j, output := range normalized.Outputs { - if output.Name != "" { - normalized.Outputs[j].Name = capitalise(output.Name) - } - if hasStruct(output.Type) { - bindStructType[lang](output.Type, structs) - } - } - // Append the methods to the call or transact lists - if original.IsConstant() { - calls[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)} - } else { - transacts[original.Name] = &tmplMethod{Original: original, Normalized: normalized, Structured: structured(original.Outputs)} - } - } - for _, original := range evmABI.Events { - // Skip anonymous events as they don't support explicit filtering - if original.Anonymous { - continue - } - // Normalize the event for capital cases and non-anonymous outputs - normalized := original - - // Ensure there is no duplicated identifier - normalizedName := methodNormalizer[lang](alias(aliases, original.Name)) - // Name shouldn't start with a digit. It will make the generated code invalid. - if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) { - normalizedName = fmt.Sprintf("E%s", normalizedName) - normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool { - _, ok := eventIdentifiers[name] - return ok - }) - } - if eventIdentifiers[normalizedName] { - return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName) - } - eventIdentifiers[normalizedName] = true - normalized.Name = normalizedName - - used := make(map[string]bool) - normalized.Inputs = make([]abi.Argument, len(original.Inputs)) - copy(normalized.Inputs, original.Inputs) - for j, input := range normalized.Inputs { - if input.Name == "" || isKeyWord(input.Name) { - normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j) - } - // Event is a bit special, we need to define event struct in binding, - // ensure there is no camel-case-style name conflict. - for index := 0; ; index++ { - if !used[capitalise(normalized.Inputs[j].Name)] { - used[capitalise(normalized.Inputs[j].Name)] = true - break - } - normalized.Inputs[j].Name = fmt.Sprintf("%s%d", normalized.Inputs[j].Name, index) - } - if hasStruct(input.Type) { - bindStructType[lang](input.Type, structs) - } - } - // Append the event to the accumulator list - events[original.Name] = &tmplEvent{Original: original, Normalized: normalized} - } - // Add two special fallback functions if they exist - if evmABI.HasFallback() { - fallback = &tmplMethod{Original: evmABI.Fallback} - } - if evmABI.HasReceive() { - receive = &tmplMethod{Original: evmABI.Receive} - } - contracts[types[i]] = &tmplContract{ - Type: capitalise(types[i]), - InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""), - InputBin: strings.TrimPrefix(strings.TrimSpace(bytecodes[i]), "0x"), - Constructor: evmABI.Constructor, - Calls: calls, - Transacts: transacts, - Fallback: fallback, - Receive: receive, - Events: events, - Libraries: make(map[string]string), - } - // Function 4-byte signatures are stored in the same sequence - // as types, if available. - if len(fsigs) > i { - contracts[types[i]].FuncSigs = fsigs[i] - } - // Parse library references. - for pattern, name := range libs { - matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin)) - if err != nil { - log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err) - } - if matched { - contracts[types[i]].Libraries[pattern] = name - // keep track that this type is a library - if _, ok := isLib[name]; !ok { - isLib[name] = struct{}{} - } - } - } - } - // Check if that type has already been identified as a library - for i := 0; i < len(types); i++ { - _, ok := isLib[types[i]] - contracts[types[i]].Library = ok - } - // Generate the contract template data content and render it - data := &tmplData{ - Package: pkg, - Contracts: contracts, - Libraries: libs, - Structs: structs, - } - buffer := new(bytes.Buffer) - - funcs := map[string]interface{}{ - "bindtype": bindType[lang], - "bindtopictype": bindTopicType[lang], - "namedtype": namedType[lang], - "capitalise": capitalise, - "decapitalise": decapitalise, - } - tmpl := template.Must(template.New("").Funcs(funcs).Parse(tmplSource[lang])) - if err := tmpl.Execute(buffer, data); err != nil { - return "", err - } - // For Go bindings pass the code through gofmt to clean it up - if lang == LangGo { - code, err := format.Source(buffer.Bytes()) - if err != nil { - return "", fmt.Errorf("%v\n%s", err, buffer) - } - return string(code), nil - } - // For all others just return as is for now - return buffer.String(), nil -} - -// bindType is a set of type binders that convert Solidity types to some supported -// programming language types. -var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ - LangGo: bindTypeGo, -} - -// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones. -func bindBasicTypeGo(kind abi.Type) string { - switch kind.T { - case abi.AddressTy: - return "common.Address" - case abi.IntTy, abi.UintTy: - parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String()) - switch parts[2] { - case "8", "16", "32", "64": - return fmt.Sprintf("%sint%s", parts[1], parts[2]) - } - return "*big.Int" - case abi.FixedBytesTy: - return fmt.Sprintf("[%d]byte", kind.Size) - case abi.BytesTy: - return "[]byte" - case abi.FunctionTy: - return "[24]byte" - default: - // string, bool types - return kind.String() - } -} - -// bindTypeGo converts solidity types to Go ones. Since there is no clear mapping -// from all Solidity types to Go ones (e.g. uint17), those that cannot be exactly -// mapped will use an upscaled type (e.g. BigDecimal). -func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { - switch kind.T { - case abi.TupleTy: - return structs[kind.TupleRawName+kind.String()].Name - case abi.ArrayTy: - return fmt.Sprintf("[%d]", kind.Size) + bindTypeGo(*kind.Elem, structs) - case abi.SliceTy: - return "[]" + bindTypeGo(*kind.Elem, structs) - default: - return bindBasicTypeGo(kind) - } -} - -// bindTopicType is a set of type binders that convert Solidity types to some -// supported programming language topic types. -var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ - LangGo: bindTopicTypeGo, -} - -// bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same -// functionality as for simple types, but dynamic types get converted to hashes. -func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { - bound := bindTypeGo(kind, structs) - - // todo(rjl493456442) according solidity documentation, indexed event - // parameters that are not value types i.e. arrays and structs are not - // stored directly but instead a keccak256-hash of an encoding is stored. - // - // We only convert strings and bytes to hash, still need to deal with - // array(both fixed-size and dynamic-size) and struct. - if bound == "string" || bound == "[]byte" { - bound = "common.Hash" - } - return bound -} - -// bindStructType is a set of type binders that convert Solidity tuple types to some supported -// programming language struct definition. -var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{ - LangGo: bindStructTypeGo, -} - -// bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping -// in the given map. -// Notably, this function will resolve and record nested struct recursively. -func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { - switch kind.T { - case abi.TupleTy: - // We compose a raw struct name and a canonical parameter expression - // together here. The reason is before solidity v0.5.11, kind.TupleRawName - // is empty, so we use canonical parameter expression to distinguish - // different struct definition. From the consideration of backward - // compatibility, we concat these two together so that if kind.TupleRawName - // is not empty, it can have unique id. - id := kind.TupleRawName + kind.String() - if s, exist := structs[id]; exist { - return s.Name - } - var ( - names = make(map[string]bool) - fields []*tmplField - ) - for i, elem := range kind.TupleElems { - name := capitalise(kind.TupleRawNames[i]) - name = abi.ResolveNameConflict(name, func(s string) bool { return names[s] }) - names[name] = true - fields = append(fields, &tmplField{Type: bindStructTypeGo(*elem, structs), Name: name, SolKind: *elem}) - } - name := kind.TupleRawName - if name == "" { - name = fmt.Sprintf("Struct%d", len(structs)) - } - name = capitalise(name) - - structs[id] = &tmplStruct{ - Name: name, - Fields: fields, - } - return name - case abi.ArrayTy: - return fmt.Sprintf("[%d]", kind.Size) + bindStructTypeGo(*kind.Elem, structs) - case abi.SliceTy: - return "[]" + bindStructTypeGo(*kind.Elem, structs) - default: - return bindBasicTypeGo(kind) - } -} - -// namedType is a set of functions that transform language specific types to -// named versions that may be used inside method names. -var namedType = map[Lang]func(string, abi.Type) string{ - LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") }, -} - -// alias returns an alias of the given string based on the aliasing rules -// or returns itself if no rule is matched. -func alias(aliases map[string]string, n string) string { - if alias, exist := aliases[n]; exist { - return alias - } - return n -} - -// methodNormalizer is a name transformer that modifies Solidity method names to -// conform to target language naming conventions. -var methodNormalizer = map[Lang]func(string) string{ - LangGo: abi.ToCamelCase, -} - -// capitalise makes a camel-case string which starts with an upper case character. -var capitalise = abi.ToCamelCase - -// decapitalise makes a camel-case string which starts with a lower case character. -func decapitalise(input string) string { - if len(input) == 0 { - return input - } - - goForm := abi.ToCamelCase(input) - return strings.ToLower(goForm[:1]) + goForm[1:] -} - -// structured checks whether a list of ABI data types has enough information to -// operate through a proper Go struct or if flat returns are needed. -func structured(args abi.Arguments) bool { - if len(args) < 2 { - return false - } - exists := make(map[string]bool) - for _, out := range args { - // If the name is anonymous, we can't organize into a struct - if out.Name == "" { - return false - } - // If the field name is empty when normalized or collides (var, Var, _var, _Var), - // we can't organize into a struct - field := capitalise(out.Name) - if field == "" || exists[field] { - return false - } - exists[field] = true - } - return true -} - -// hasStruct returns an indicator whether the given type is struct, struct slice -// or struct array. -func hasStruct(t abi.Type) bool { - switch t.T { - case abi.SliceTy: - return hasStruct(*t.Elem) - case abi.ArrayTy: - return hasStruct(*t.Elem) - case abi.TupleTy: - return true - default: - return false - } -} diff --git a/builder/accounts/abi/bind/bind_test.go b/builder/accounts/abi/bind/bind_test.go deleted file mode 100644 index a390a3c47..000000000 --- a/builder/accounts/abi/bind/bind_test.go +++ /dev/null @@ -1,2147 +0,0 @@ -// Copyright 2016 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 bind - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -var bindTests = []struct { - name string - contract string - bytecode []string - abi []string - imports string - tester string - fsigs []map[string]string - libs map[string]string - aliases map[string]string - types []string -}{ - // Test that the binding is available in combined and separate forms too - { - `Empty`, - `contract NilContract {}`, - []string{`606060405260068060106000396000f3606060405200`}, - []string{`[]`}, - `"github.com/ethereum/go-ethereum/common"`, - ` - if b, err := NewEmpty(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("combined binding (%v) nil or error (%v) not nil", b, nil) - } - if b, err := NewEmptyCaller(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("caller binding (%v) nil or error (%v) not nil", b, nil) - } - if b, err := NewEmptyTransactor(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("transactor binding (%v) nil or error (%v) not nil", b, nil) - } - `, - nil, - nil, - nil, - nil, - }, - // Test that all the official sample contracts bind correctly - { - `Token`, - `https://ethereum.org/token`, - []string{`60606040526040516107fd3803806107fd83398101604052805160805160a05160c051929391820192909101600160a060020a0333166000908152600360209081526040822086905581548551838052601f6002600019610100600186161502019093169290920482018390047f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56390810193919290918801908390106100e857805160ff19168380011785555b506101189291505b8082111561017157600081556001016100b4565b50506002805460ff19168317905550505050610658806101a56000396000f35b828001600101855582156100ac579182015b828111156100ac5782518260005055916020019190600101906100fa565b50508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061017557805160ff19168380011785555b506100c89291506100b4565b5090565b82800160010185558215610165579182015b8281111561016557825182600050559160200191906001019061018756606060405236156100775760e060020a600035046306fdde03811461007f57806323b872dd146100dc578063313ce5671461010e57806370a082311461011a57806395d89b4114610132578063a9059cbb1461018e578063cae9ca51146101bd578063dc3080f21461031c578063dd62ed3e14610341575b610365610002565b61036760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b6103d5600435602435604435600160a060020a038316600090815260036020526040812054829010156104f357610002565b6103e760025460ff1681565b6103d560043560036020526000908152604090205481565b610367600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156104eb5780601f106104c0576101008083540402835291602001916104eb565b610365600435602435600160a060020a033316600090815260036020526040902054819010156103f157610002565b60806020604435600481810135601f8101849004909302840160405260608381526103d5948235946024803595606494939101919081908382808284375094965050505050505060006000836004600050600033600160a060020a03168152602001908152602001600020600050600087600160a060020a031681526020019081526020016000206000508190555084905080600160a060020a0316638f4ffcb1338630876040518560e060020a0281526004018085600160a060020a0316815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102f25780820380516001836020036101000a031916815260200191505b50955050505050506000604051808303816000876161da5a03f11561000257505050509392505050565b6005602090815260043560009081526040808220909252602435815220546103d59081565b60046020818152903560009081526040808220909252602435815220546103d59081565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a03821660009081526040902054808201101561041357610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b820191906000526020600020905b8154815290600101906020018083116104ce57829003601f168201915b505050505081565b600160a060020a03831681526040812054808301101561051257610002565b600160a060020a0380851680835260046020908152604080852033949094168086529382528085205492855260058252808520938552929052908220548301111561055c57610002565b816003600050600086600160a060020a03168152602001908152602001600020600082828250540392505081905550816003600050600085600160a060020a03168152602001908152602001600020600082828250540192505081905550816005600050600086600160a060020a03168152602001908152602001600020600050600033600160a060020a0316815260200190815260200160002060008282825054019250508190555082600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3939250505056`}, - []string{`[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"spentAllowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"inputs":[{"name":"initialSupply","type":"uint256"},{"name":"tokenName","type":"string"},{"name":"decimalUnits","type":"uint8"},{"name":"tokenSymbol","type":"string"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]`}, - `"github.com/ethereum/go-ethereum/common"`, - ` - if b, err := NewToken(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", b, nil) - } - `, - nil, - nil, - nil, - nil, - }, - { - `Crowdsale`, - `https://ethereum.org/crowdsale`, - []string{`606060408190526007805460ff1916905560a0806105a883396101006040529051608051915160c05160e05160008054600160a060020a03199081169095178155670de0b6b3a7640000958602600155603c9093024201600355930260045560058054909216909217905561052f90819061007990396000f36060604052361561006c5760e060020a600035046301cb3b20811461008257806329dcb0cf1461014457806338af3eed1461014d5780636e66f6e91461015f5780637a3a0e84146101715780637b3e5e7b1461017a578063a035b1fe14610183578063dc0d3dff1461018c575b61020060075460009060ff161561032357610002565b61020060035460009042106103205760025460015490106103cb576002548154600160a060020a0316908290606082818181858883f150915460025460408051600160a060020a039390931683526020830191909152818101869052517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6945090819003909201919050a15b60405160008054600160a060020a039081169230909116319082818181858883f150506007805460ff1916600117905550505050565b6103a160035481565b6103ab600054600160a060020a031681565b6103ab600554600160a060020a031681565b6103a160015481565b6103a160025481565b6103a160045481565b6103be60043560068054829081101561000257506000526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f8101547ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d409190910154600160a060020a03919091169082565b005b505050815481101561000257906000526020600020906002020160005060008201518160000160006101000a815481600160a060020a030219169083021790555060208201518160010160005055905050806002600082828250540192505081905550600560009054906101000a9004600160a060020a0316600160a060020a031663a9059cbb3360046000505484046040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505060408051600160a060020a03331681526020810184905260018183015290517fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf692509081900360600190a15b50565b5060a0604052336060908152346080819052600680546001810180835592939282908280158290116102025760020281600202836000526020600020918201910161020291905b8082111561039d57805473ffffffffffffffffffffffffffffffffffffffff19168155600060019190910190815561036a565b5090565b6060908152602090f35b600160a060020a03166060908152602090f35b6060918252608052604090f35b5b60065481101561010e576006805482908110156100025760009182526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0190600680549254600160a060020a0316928490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460405190915082818181858883f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf660066000508281548110156100025760008290526002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01548154600160a060020a039190911691908490811015610002576002027ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40015460408051600160a060020a0394909416845260208401919091526000838201525191829003606001919050a16001016103cc56`}, - []string{`[{"constant":false,"inputs":[],"name":"checkGoalReached","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"deadline","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"tokenReward","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"fundingGoal","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"amountRaised","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"price","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"funders","outputs":[{"name":"addr","type":"address"},{"name":"amount","type":"uint256"}],"type":"function"},{"inputs":[{"name":"ifSuccessfulSendTo","type":"address"},{"name":"fundingGoalInEthers","type":"uint256"},{"name":"durationInMinutes","type":"uint256"},{"name":"etherCostOfEachToken","type":"uint256"},{"name":"addressOfTokenUsedAsReward","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"backer","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"isContribution","type":"bool"}],"name":"FundTransfer","type":"event"}]`}, - `"github.com/ethereum/go-ethereum/common"`, - ` - if b, err := NewCrowdsale(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", b, nil) - } - `, - nil, - nil, - nil, - nil, - }, - { - `DAO`, - `https://ethereum.org/dao`, - []string{`606060405260405160808061145f833960e06040529051905160a05160c05160008054600160a060020a03191633179055600184815560028490556003839055600780549182018082558280158290116100b8576003028160030283600052602060002091820191016100b891906101c8565b50506060919091015160029190910155600160a060020a0381166000146100a65760008054600160a060020a031916821790555b505050506111f18061026e6000396000f35b505060408051608081018252600080825260208281018290528351908101845281815292820192909252426060820152600780549194509250811015610002579081527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889050815181546020848101517401000000000000000000000000000000000000000002600160a060020a03199290921690921760a060020a60ff021916178255604083015180516001848101805460008281528690209195600293821615610100026000190190911692909204601f9081018390048201949192919091019083901061023e57805160ff19168380011785555b50610072929150610226565b5050600060028201556001015b8082111561023a578054600160a860020a031916815560018181018054600080835592600290821615610100026000190190911604601f81901061020c57506101bb565b601f0160209004906000526020600020908101906101bb91905b8082111561023a5760008155600101610226565b5090565b828001600101855582156101af579182015b828111156101af57825182600050559160200191906001019061025056606060405236156100b95760e060020a6000350463013cf08b81146100bb578063237e9492146101285780633910682114610281578063400e3949146102995780635daf08ca146102a257806369bd34361461032f5780638160f0b5146103385780638da5cb5b146103415780639644fcbd14610353578063aa02a90f146103be578063b1050da5146103c7578063bcca1fd3146104b5578063d3c0715b146104dc578063eceb29451461058d578063f2fde38b1461067b575b005b61069c6004356004805482908110156100025790600052602060002090600a02016000506005810154815460018301546003840154600485015460068601546007870154600160a060020a03959095169750929560020194919360ff828116946101009093041692919089565b60408051602060248035600481810135601f81018590048502860185019096528585526107759581359591946044949293909201918190840183828082843750949650505050505050600060006004600050848154811015610002575090527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19e600a8402908101547f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b909101904210806101e65750600481015460ff165b8061026757508060000160009054906101000a9004600160a060020a03168160010160005054846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816007016000505414155b8061027757506001546005820154105b1561109257610002565b61077560043560066020526000908152604090205481565b61077560055481565b61078760043560078054829081101561000257506000526003026000805160206111d18339815191528101547fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68a820154600160a060020a0382169260a060020a90920460ff16917fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689019084565b61077560025481565b61077560015481565b610830600054600160a060020a031681565b604080516020604435600481810135601f81018490048402850184019095528484526100b9948135946024803595939460649492939101918190840183828082843750949650505050505050600080548190600160a060020a03908116339091161461084d57610002565b61077560035481565b604080516020604435600481810135601f8101849004840285018401909552848452610775948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024909101945090925082915084018382808284375094965050505050505033600160a060020a031660009081526006602052604081205481908114806104ab5750604081205460078054909190811015610002579082526003026000805160206111d1833981519152015460a060020a900460ff16155b15610ce557610002565b6100b960043560243560443560005433600160a060020a03908116911614610b1857610002565b604080516020604435600481810135601f810184900484028501840190955284845261077594813594602480359593946064949293910191819084018382808284375094965050505050505033600160a060020a031660009081526006602052604081205481908114806105835750604081205460078054909190811015610002579082526003026000805160206111d18339815191520181505460a060020a900460ff16155b15610f1d57610002565b604080516020606435600481810135601f81018490048402850184019095528484526107759481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600460005086815481101561000257908252600a027f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b01815090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160070160005054149150610cdc565b6100b960043560005433600160a060020a03908116911614610f0857610002565b604051808a600160a060020a031681526020018981526020018060200188815260200187815260200186815260200185815260200184815260200183815260200182810382528981815460018160011615610100020316600290048152602001915080546001816001161561010002031660029004801561075e5780601f106107335761010080835404028352916020019161075e565b820191906000526020600020905b81548152906001019060200180831161074157829003601f168201915b50509a505050505050505050505060405180910390f35b60408051918252519081900360200190f35b60408051600160a060020a038616815260208101859052606081018390526080918101828152845460026001821615610100026000190190911604928201839052909160a08301908590801561081e5780601f106107f35761010080835404028352916020019161081e565b820191906000526020600020905b81548152906001019060200180831161080157829003601f168201915b50509550505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b600160a060020a03851660009081526006602052604081205414156108a957604060002060078054918290556001820180825582801582901161095c5760030281600302836000526020600020918201910161095c9190610a4f565b600160a060020a03851660009081526006602052604090205460078054919350908390811015610002575060005250600381026000805160206111d183398151915201805474ff0000000000000000000000000000000000000000191660a060020a85021781555b60408051600160a060020a03871681526020810186905281517f27b022af4a8347100c7a041ce5ccf8e14d644ff05de696315196faae8cd50c9b929181900390910190a15050505050565b505050915081506080604051908101604052808681526020018581526020018481526020014281526020015060076000508381548110156100025790600052602060002090600302016000508151815460208481015160a060020a02600160a060020a03199290921690921774ff00000000000000000000000000000000000000001916178255604083015180516001848101805460008281528690209195600293821615610100026000190190911692909204601f90810183900482019491929190910190839010610ad357805160ff19168380011785555b50610b03929150610abb565b5050600060028201556001015b80821115610acf57805474ffffffffffffffffffffffffffffffffffffffffff1916815560018181018054600080835592600290821615610100026000190190911604601f819010610aa15750610a42565b601f016020900490600052602060002090810190610a4291905b80821115610acf5760008155600101610abb565b5090565b82800160010185558215610a36579182015b82811115610a36578251826000505591602001919060010190610ae5565b50506060919091015160029190910155610911565b600183905560028290556003819055604080518481526020810184905280820183905290517fa439d3fa452be5e0e1e24a8145e715f4fd8b9c08c96a42fd82a855a85e5d57de9181900360600190a1505050565b50508585846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160070160005081905550600260005054603c024201816003016000508190555060008160040160006101000a81548160ff0219169083021790555060008160040160016101000a81548160ff02191690830217905550600081600501600050819055507f646fec02522b41e7125cfc859a64fd4f4cefd5dc3b6237ca0abe251ded1fa881828787876040518085815260200184600160a060020a03168152602001838152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610cc45780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1600182016005555b50949350505050565b6004805460018101808355909190828015829011610d1c57600a0281600a028360005260206000209182019101610d1c9190610db8565b505060048054929450918491508110156100025790600052602060002090600a02016000508054600160a060020a031916871781556001818101879055855160028381018054600082815260209081902096975091959481161561010002600019011691909104601f90810182900484019391890190839010610ed857805160ff19168380011785555b50610b6c929150610abb565b50506001015b80821115610acf578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f819010610e9c57505b5060006003830181905560048301805461ffff191690556005830181905560068301819055600783018190556008830180548282559082526020909120610db2916002028101905b80821115610acf57805474ffffffffffffffffffffffffffffffffffffffffff1916815560018181018054600080835592600290821615610100026000190190911604601f819010610eba57505b5050600101610e44565b601f016020900490600052602060002090810190610dfc9190610abb565b601f016020900490600052602060002090810190610e929190610abb565b82800160010185558215610da6579182015b82811115610da6578251826000505591602001919060010190610eea565b60008054600160a060020a0319168217905550565b600480548690811015610002576000918252600a027f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b01905033600160a060020a0316600090815260098201602052604090205490915060ff1660011415610f8457610002565b33600160a060020a031660009081526009820160205260409020805460ff1916600190811790915560058201805490910190558315610fcd576006810180546001019055610fda565b6006810180546000190190555b7fc34f869b7ff431b034b7b9aea9822dac189a685e0b015c7d1be3add3f89128e8858533866040518085815260200184815260200183600160a060020a03168152602001806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561107a5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1509392505050565b6006810154600354901315611158578060000160009054906101000a9004600160a060020a0316600160a060020a03168160010160005054670de0b6b3a76400000284604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156111225780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f15050505060048101805460ff191660011761ff00191661010017905561116d565b60048101805460ff191660011761ff00191690555b60068101546005820154600483015460408051888152602081019490945283810192909252610100900460ff166060830152517fd220b7272a8b6d0d7d6bcdace67b936a8f175e6d5c1b3ee438b72256b32ab3af9181900360800190a1509291505056a66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688`}, - []string{`[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"},{"name":"description","type":"string"},{"name":"votingDeadline","type":"uint256"},{"name":"executed","type":"bool"},{"name":"proposalPassed","type":"bool"},{"name":"numberOfVotes","type":"uint256"},{"name":"currentResult","type":"int256"},{"name":"proposalHash","type":"bytes32"}],"type":"function"},{"constant":false,"inputs":[{"name":"proposalNumber","type":"uint256"},{"name":"transactionBytecode","type":"bytes"}],"name":"executeProposal","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"memberId","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"numProposals","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"members","outputs":[{"name":"member","type":"address"},{"name":"canVote","type":"bool"},{"name":"name","type":"string"},{"name":"memberSince","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"debatingPeriodInMinutes","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"minimumQuorum","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"targetMember","type":"address"},{"name":"canVote","type":"bool"},{"name":"memberName","type":"string"}],"name":"changeMembership","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"majorityMargin","outputs":[{"name":"","type":"int256"}],"type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"etherAmount","type":"uint256"},{"name":"JobDescription","type":"string"},{"name":"transactionBytecode","type":"bytes"}],"name":"newProposal","outputs":[{"name":"proposalID","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"minimumQuorumForProposals","type":"uint256"},{"name":"minutesForDebate","type":"uint256"},{"name":"marginOfVotesForMajority","type":"int256"}],"name":"changeVotingRules","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"proposalNumber","type":"uint256"},{"name":"supportsProposal","type":"bool"},{"name":"justificationText","type":"string"}],"name":"vote","outputs":[{"name":"voteID","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"proposalNumber","type":"uint256"},{"name":"beneficiary","type":"address"},{"name":"etherAmount","type":"uint256"},{"name":"transactionBytecode","type":"bytes"}],"name":"checkProposalCode","outputs":[{"name":"codeChecksOut","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"type":"function"},{"inputs":[{"name":"minimumQuorumForProposals","type":"uint256"},{"name":"minutesForDebate","type":"uint256"},{"name":"marginOfVotesForMajority","type":"int256"},{"name":"congressLeader","type":"address"}],"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"description","type":"string"}],"name":"ProposalAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"position","type":"bool"},{"indexed":false,"name":"voter","type":"address"},{"indexed":false,"name":"justification","type":"string"}],"name":"Voted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"proposalID","type":"uint256"},{"indexed":false,"name":"result","type":"int256"},{"indexed":false,"name":"quorum","type":"uint256"},{"indexed":false,"name":"active","type":"bool"}],"name":"ProposalTallied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"member","type":"address"},{"indexed":false,"name":"isMember","type":"bool"}],"name":"MembershipChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"minimumQuorum","type":"uint256"},{"indexed":false,"name":"debatingPeriodInMinutes","type":"uint256"},{"indexed":false,"name":"majorityMargin","type":"int256"}],"name":"ChangeOfRules","type":"event"}]`}, - `"github.com/ethereum/go-ethereum/common"`, - ` - if b, err := NewDAO(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", b, nil) - } - `, - nil, - nil, - nil, - nil, - }, - // Test that named and anonymous inputs are handled correctly - { - `InputChecker`, ``, []string{``}, - []string{` - [ - {"type":"function","name":"noInput","constant":true,"inputs":[],"outputs":[]}, - {"type":"function","name":"namedInput","constant":true,"inputs":[{"name":"str","type":"string"}],"outputs":[]}, - {"type":"function","name":"anonInput","constant":true,"inputs":[{"name":"","type":"string"}],"outputs":[]}, - {"type":"function","name":"namedInputs","constant":true,"inputs":[{"name":"str1","type":"string"},{"name":"str2","type":"string"}],"outputs":[]}, - {"type":"function","name":"anonInputs","constant":true,"inputs":[{"name":"","type":"string"},{"name":"","type":"string"}],"outputs":[]}, - {"type":"function","name":"mixedInputs","constant":true,"inputs":[{"name":"","type":"string"},{"name":"str","type":"string"}],"outputs":[]} - ] - `}, - ` - "fmt" - - "github.com/ethereum/go-ethereum/common" - `, - `if b, err := NewInputChecker(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", b, nil) - } else if false { // Don't run, just compile and test types - var err error - - err = b.NoInput(nil) - err = b.NamedInput(nil, "") - err = b.AnonInput(nil, "") - err = b.NamedInputs(nil, "", "") - err = b.AnonInputs(nil, "", "") - err = b.MixedInputs(nil, "", "") - - fmt.Println(err) - }`, - nil, - nil, - nil, - nil, - }, - // Test that named and anonymous outputs are handled correctly - { - `OutputChecker`, ``, []string{``}, - []string{` - [ - {"type":"function","name":"noOutput","constant":true,"inputs":[],"outputs":[]}, - {"type":"function","name":"namedOutput","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"}]}, - {"type":"function","name":"anonOutput","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"}]}, - {"type":"function","name":"namedOutputs","constant":true,"inputs":[],"outputs":[{"name":"str1","type":"string"},{"name":"str2","type":"string"}]}, - {"type":"function","name":"collidingOutputs","constant":true,"inputs":[],"outputs":[{"name":"str","type":"string"},{"name":"Str","type":"string"}]}, - {"type":"function","name":"anonOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"","type":"string"}]}, - {"type":"function","name":"mixedOutputs","constant":true,"inputs":[],"outputs":[{"name":"","type":"string"},{"name":"str","type":"string"}]} - ] - `}, - ` - "fmt" - - "github.com/ethereum/go-ethereum/common" - `, - `if b, err := NewOutputChecker(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", b, nil) - } else if false { // Don't run, just compile and test types - var str1, str2 string - var err error - - err = b.NoOutput(nil) - str1, err = b.NamedOutput(nil) - str1, err = b.AnonOutput(nil) - res, _ := b.NamedOutputs(nil) - str1, str2, err = b.CollidingOutputs(nil) - str1, str2, err = b.AnonOutputs(nil) - str1, str2, err = b.MixedOutputs(nil) - - fmt.Println(str1, str2, res.Str1, res.Str2, err) - }`, - nil, - nil, - nil, - nil, - }, - // Tests that named, anonymous and indexed events are handled correctly - { - `EventChecker`, ``, []string{``}, - []string{` - [ - {"type":"event","name":"empty","inputs":[]}, - {"type":"event","name":"indexed","inputs":[{"name":"addr","type":"address","indexed":true},{"name":"num","type":"int256","indexed":true}]}, - {"type":"event","name":"mixed","inputs":[{"name":"addr","type":"address","indexed":true},{"name":"num","type":"int256"}]}, - {"type":"event","name":"anonymous","anonymous":true,"inputs":[]}, - {"type":"event","name":"dynamic","inputs":[{"name":"idxStr","type":"string","indexed":true},{"name":"idxDat","type":"bytes","indexed":true},{"name":"str","type":"string"},{"name":"dat","type":"bytes"}]}, - {"type":"event","name":"unnamed","inputs":[{"name":"","type":"uint256","indexed": true},{"name":"","type":"uint256","indexed":true}]} - ] - `}, - ` - "fmt" - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/common" - `, - `if e, err := NewEventChecker(common.Address{}, nil); e == nil || err != nil { - t.Fatalf("binding (%v) nil or error (%v) not nil", e, nil) - } else if false { // Don't run, just compile and test types - var ( - err error - res bool - str string - dat []byte - hash common.Hash - ) - _, err = e.FilterEmpty(nil) - _, err = e.FilterIndexed(nil, []common.Address{}, []*big.Int{}) - - mit, err := e.FilterMixed(nil, []common.Address{}) - - res = mit.Next() // Make sure the iterator has a Next method - err = mit.Error() // Make sure the iterator has an Error method - err = mit.Close() // Make sure the iterator has a Close method - - fmt.Println(mit.Event.Raw.BlockHash) // Make sure the raw log is contained within the results - fmt.Println(mit.Event.Num) // Make sure the unpacked non-indexed fields are present - fmt.Println(mit.Event.Addr) // Make sure the reconstructed indexed fields are present - - dit, err := e.FilterDynamic(nil, []string{}, [][]byte{}) - - str = dit.Event.Str // Make sure non-indexed strings retain their type - dat = dit.Event.Dat // Make sure non-indexed bytes retain their type - hash = dit.Event.IdxStr // Make sure indexed strings turn into hashes - hash = dit.Event.IdxDat // Make sure indexed bytes turn into hashes - - sink := make(chan *EventCheckerMixed) - sub, err := e.WatchMixed(nil, sink, []common.Address{}) - defer sub.Unsubscribe() - - event := <-sink - fmt.Println(event.Raw.BlockHash) // Make sure the raw log is contained within the results - fmt.Println(event.Num) // Make sure the unpacked non-indexed fields are present - fmt.Println(event.Addr) // Make sure the reconstructed indexed fields are present - - fmt.Println(res, str, dat, hash, err) - - oit, err := e.FilterUnnamed(nil, []*big.Int{}, []*big.Int{}) - - arg0 := oit.Event.Arg0 // Make sure unnamed arguments are handled correctly - arg1 := oit.Event.Arg1 // Make sure unnamed arguments are handled correctly - fmt.Println(arg0, arg1) - } - // Run a tiny reflection test to ensure disallowed methods don't appear - if _, ok := reflect.TypeOf(&EventChecker{}).MethodByName("FilterAnonymous"); ok { - t.Errorf("binding has disallowed method (FilterAnonymous)") - }`, - nil, - nil, - nil, - nil, - }, - // Test that contract interactions (deploy, transact and call) generate working code - { - `Interactor`, - ` - contract Interactor { - string public deployString; - string public transactString; - - function Interactor(string str) { - deployString = str; - } - - function transact(string str) { - transactString = str; - } - } - `, - []string{`6060604052604051610328380380610328833981016040528051018060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10608d57805160ff19168380011785555b50607c9291505b8082111560ba57838155600101606b565b50505061026a806100be6000396000f35b828001600101855582156064579182015b828111156064578251826000505591602001919060010190609e565b509056606060405260e060020a60003504630d86a0e181146100315780636874e8091461008d578063d736c513146100ea575b005b610190600180546020600282841615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b61019060008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102295780601f106101fe57610100808354040283529160200191610229565b60206004803580820135601f81018490049093026080908101604052606084815261002f946024939192918401918190838280828437509496505050505050508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061023157805160ff19168380011785555b506102619291505b808211156102665760008155830161017d565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101f05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b820191906000526020600020905b81548152906001019060200180831161020c57829003601f168201915b505050505081565b82800160010185558215610175579182015b82811115610175578251826000505591602001919060010190610243565b505050565b509056`}, - []string{`[{"constant":true,"inputs":[],"name":"transactString","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[],"name":"deployString","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"str","type":"string"}],"name":"transact","outputs":[],"type":"function"},{"inputs":[{"name":"str","type":"string"}],"type":"constructor"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy an interaction tester contract and call a transaction on it - _, _, interactor, err := DeployInteractor(auth, sim, "Deploy string") - if err != nil { - t.Fatalf("Failed to deploy interactor contract: %v", err) - } - sim.Commit() - if _, err := interactor.Transact(auth, "Transact string"); err != nil { - t.Fatalf("Failed to transact with interactor contract: %v", err) - } - // Commit all pending transactions in the simulator and check the contract state - sim.Commit() - - if str, err := interactor.DeployString(nil); err != nil { - t.Fatalf("Failed to retrieve deploy string: %v", err) - } else if str != "Deploy string" { - t.Fatalf("Deploy string mismatch: have '%s', want 'Deploy string'", str) - } - if str, err := interactor.TransactString(nil); err != nil { - t.Fatalf("Failed to retrieve transact string: %v", err) - } else if str != "Transact string" { - t.Fatalf("Transact string mismatch: have '%s', want 'Transact string'", str) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that plain values can be properly returned and deserialized - { - `Getter`, - ` - contract Getter { - function getter() constant returns (string, int, bytes32) { - return ("Hi", 1, sha3("")); - } - } - `, - []string{`606060405260dc8060106000396000f3606060405260e060020a6000350463993a04b78114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3`}, - []string{`[{"constant":true,"inputs":[],"name":"getter","outputs":[{"name":"","type":"string"},{"name":"","type":"int256"},{"name":"","type":"bytes32"}],"type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a tuple tester contract and execute a structured call on it - _, _, getter, err := DeployGetter(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy getter contract: %v", err) - } - sim.Commit() - - if str, num, _, err := getter.Getter(nil); err != nil { - t.Fatalf("Failed to call anonymous field retriever: %v", err) - } else if str != "Hi" || num.Cmp(big.NewInt(1)) != 0 { - t.Fatalf("Retrieved value mismatch: have %v/%v, want %v/%v", str, num, "Hi", 1) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that tuples can be properly returned and deserialized - { - `Tupler`, - ` - contract Tupler { - function tuple() constant returns (string a, int b, bytes32 c) { - return ("Hi", 1, sha3("")); - } - } - `, - []string{`606060405260dc8060106000396000f3606060405260e060020a60003504633175aae28114601a575b005b600060605260c0604052600260809081527f486900000000000000000000000000000000000000000000000000000000000060a05260017fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060e0829052610100819052606060c0908152600261012081905281906101409060a09080838184600060046012f1505081517fffff000000000000000000000000000000000000000000000000000000000000169091525050604051610160819003945092505050f3`}, - []string{`[{"constant":true,"inputs":[],"name":"tuple","outputs":[{"name":"a","type":"string"},{"name":"b","type":"int256"},{"name":"c","type":"bytes32"}],"type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a tuple tester contract and execute a structured call on it - _, _, tupler, err := DeployTupler(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy tupler contract: %v", err) - } - sim.Commit() - - if res, err := tupler.Tuple(nil); err != nil { - t.Fatalf("Failed to call structure retriever: %v", err) - } else if res.A != "Hi" || res.B.Cmp(big.NewInt(1)) != 0 { - t.Fatalf("Retrieved value mismatch: have %v/%v, want %v/%v", res.A, res.B, "Hi", 1) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that arrays/slices can be properly returned and deserialized. - // Only addresses are tested, remainder just compiled to keep the test small. - { - `Slicer`, - ` - contract Slicer { - function echoAddresses(address[] input) constant returns (address[] output) { - return input; - } - function echoInts(int[] input) constant returns (int[] output) { - return input; - } - function echoFancyInts(uint24[23] input) constant returns (uint24[23] output) { - return input; - } - function echoBools(bool[] input) constant returns (bool[] output) { - return input; - } - } - `, - []string{`606060405261015c806100126000396000f3606060405260e060020a6000350463be1127a3811461003c578063d88becc014610092578063e15a3db71461003c578063f637e5891461003c575b005b604080516020600480358082013583810285810185019096528085526100ee959294602494909392850192829185019084908082843750949650505050505050604080516020810190915260009052805b919050565b604080516102e0818101909252610138916004916102e491839060179083908390808284375090955050505050506102e0604051908101604052806017905b60008152602001906001900390816100d15790505081905061008d565b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600f02600301f1509050019250505060405180910390f35b60405180826102e0808381846000600461015cf15090500191505060405180910390f3`}, - []string{`[{"constant":true,"inputs":[{"name":"input","type":"address[]"}],"name":"echoAddresses","outputs":[{"name":"output","type":"address[]"}],"type":"function"},{"constant":true,"inputs":[{"name":"input","type":"uint24[23]"}],"name":"echoFancyInts","outputs":[{"name":"output","type":"uint24[23]"}],"type":"function"},{"constant":true,"inputs":[{"name":"input","type":"int256[]"}],"name":"echoInts","outputs":[{"name":"output","type":"int256[]"}],"type":"function"},{"constant":true,"inputs":[{"name":"input","type":"bool[]"}],"name":"echoBools","outputs":[{"name":"output","type":"bool[]"}],"type":"function"}]`}, - ` - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a slice tester contract and execute a n array call on it - _, _, slicer, err := DeploySlicer(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy slicer contract: %v", err) - } - sim.Commit() - - if out, err := slicer.EchoAddresses(nil, []common.Address{auth.From, common.Address{}}); err != nil { - t.Fatalf("Failed to call slice echoer: %v", err) - } else if !reflect.DeepEqual(out, []common.Address{auth.From, common.Address{}}) { - t.Fatalf("Slice return mismatch: have %v, want %v", out, []common.Address{auth.From, common.Address{}}) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that anonymous default methods can be correctly invoked - { - `Defaulter`, - ` - contract Defaulter { - address public caller; - - function() { - caller = msg.sender; - } - } - `, - []string{`6060604052606a8060106000396000f360606040523615601d5760e060020a6000350463fc9c8d3981146040575b605e6000805473ffffffffffffffffffffffffffffffffffffffff191633179055565b606060005473ffffffffffffffffffffffffffffffffffffffff1681565b005b6060908152602090f3`}, - []string{`[{"constant":true,"inputs":[],"name":"caller","outputs":[{"name":"","type":"address"}],"type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a default method invoker contract and execute its default method - _, _, defaulter, err := DeployDefaulter(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy defaulter contract: %v", err) - } - sim.Commit() - if _, err := (&DefaulterRaw{defaulter}).Transfer(auth); err != nil { - t.Fatalf("Failed to invoke default method: %v", err) - } - sim.Commit() - - if caller, err := defaulter.Caller(nil); err != nil { - t.Fatalf("Failed to call address retriever: %v", err) - } else if (caller != auth.From) { - t.Fatalf("Address mismatch: have %v, want %v", caller, auth.From) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that structs are correctly unpacked - { - - `Structs`, - ` - pragma solidity ^0.6.5; - pragma experimental ABIEncoderV2; - contract Structs { - struct A { - bytes32 B; - } - - function F() public view returns (A[] memory a, uint256[] memory c, bool[] memory d) { - A[] memory a = new A[](2); - a[0].B = bytes32(uint256(1234) << 96); - uint256[] memory c; - bool[] memory d; - return (a, c, d); - } - - function G() public view returns (A[] memory a) { - A[] memory a = new A[](2); - a[0].B = bytes32(uint256(1234) << 96); - return a; - } - } - `, - []string{`608060405234801561001057600080fd5b50610278806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806328811f591461003b5780636fecb6231461005b575b600080fd5b610043610070565b604051610052939291906101a0565b60405180910390f35b6100636100d6565b6040516100529190610186565b604080516002808252606082810190935282918291829190816020015b610095610131565b81526020019060019003908161008d575050805190915061026960611b9082906000906100be57fe5b60209081029190910101515293606093508392509050565b6040805160028082526060828101909352829190816020015b6100f7610131565b8152602001906001900390816100ef575050805190915061026960611b90829060009061012057fe5b602090810291909101015152905090565b60408051602081019091526000815290565b815260200190565b6000815180845260208085019450808401835b8381101561017b578151518752958201959082019060010161015e565b509495945050505050565b600060208252610199602083018461014b565b9392505050565b6000606082526101b3606083018661014b565b6020838203818501528186516101c98185610239565b91508288019350845b818110156101f3576101e5838651610143565b9484019492506001016101d2565b505084810360408601528551808252908201925081860190845b8181101561022b57825115158552938301939183019160010161020d565b509298975050505050505050565b9081526020019056fea2646970667358221220eb85327e285def14230424c52893aebecec1e387a50bb6b75fc4fdbed647f45f64736f6c63430006050033`}, - []string{`[{"inputs":[],"name":"F","outputs":[{"components":[{"internalType":"bytes32","name":"B","type":"bytes32"}],"internalType":"structStructs.A[]","name":"a","type":"tuple[]"},{"internalType":"uint256[]","name":"c","type":"uint256[]"},{"internalType":"bool[]","name":"d","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"G","outputs":[{"components":[{"internalType":"bytes32","name":"B","type":"bytes32"}],"internalType":"structStructs.A[]","name":"a","type":"tuple[]"}],"stateMutability":"view","type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a structs method invoker contract and execute its default method - _, _, structs, err := DeployStructs(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy defaulter contract: %v", err) - } - sim.Commit() - opts := bind.CallOpts{} - if _, err := structs.F(&opts); err != nil { - t.Fatalf("Failed to invoke F method: %v", err) - } - if _, err := structs.G(&opts); err != nil { - t.Fatalf("Failed to invoke G method: %v", err) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that non-existent contracts are reported as such (though only simulator test) - { - `NonExistent`, - ` - contract NonExistent { - function String() constant returns(string) { - return "I don't exist"; - } - } - `, - []string{`6060604052609f8060106000396000f3606060405260e060020a6000350463f97a60058114601a575b005b600060605260c0604052600d60809081527f4920646f6e27742065786973740000000000000000000000000000000000000060a052602060c0908152600d60e081905281906101009060a09080838184600060046012f15050815172ffffffffffffffffffffffffffffffffffffff1916909152505060405161012081900392509050f3`}, - []string{`[{"constant":true,"inputs":[],"name":"String","outputs":[{"name":"","type":"string"}],"type":"function"}]`}, - ` - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - `, - ` - // Create a simulator and wrap a non-deployed contract - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{}, uint64(10000000000)) - defer sim.Close() - - nonexistent, err := NewNonExistent(common.Address{}, sim) - if err != nil { - t.Fatalf("Failed to access non-existent contract: %v", err) - } - // Ensure that contract calls fail with the appropriate error - if res, err := nonexistent.String(nil); err == nil { - t.Fatalf("Call succeeded on non-existent contract: %v", res) - } else if (err != bind.ErrNoCode) { - t.Fatalf("Error mismatch: have %v, want %v", err, bind.ErrNoCode) - } - `, - nil, - nil, - nil, - nil, - }, - { - `NonExistentStruct`, - ` - contract NonExistentStruct { - function Struct() public view returns(uint256 a, uint256 b) { - return (10, 10); - } - } - `, - []string{`6080604052348015600f57600080fd5b5060888061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063d5f6622514602d575b600080fd5b6033604c565b6040805192835260208301919091528051918290030190f35b600a809156fea264697066735822beefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef64736f6c6343decafe0033`}, - []string{`[{"inputs":[],"name":"Struct","outputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"stateMutability":"pure","type":"function"}]`}, - ` - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - `, - ` - // Create a simulator and wrap a non-deployed contract - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{}, uint64(10000000000)) - defer sim.Close() - - nonexistent, err := NewNonExistentStruct(common.Address{}, sim) - if err != nil { - t.Fatalf("Failed to access non-existent contract: %v", err) - } - // Ensure that contract calls fail with the appropriate error - if res, err := nonexistent.Struct(nil); err == nil { - t.Fatalf("Call succeeded on non-existent contract: %v", res) - } else if (err != bind.ErrNoCode) { - t.Fatalf("Error mismatch: have %v, want %v", err, bind.ErrNoCode) - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that gas estimation works for contracts with weird gas mechanics too. - { - `FunkyGasPattern`, - ` - contract FunkyGasPattern { - string public field; - - function SetField(string value) { - // This check will screw gas estimation! Good, good! - if (msg.gas < 100000) { - throw; - } - field = value; - } - } - `, - []string{`606060405261021c806100126000396000f3606060405260e060020a600035046323fcf32a81146100265780634f28bf0e1461007b575b005b6040805160206004803580820135601f8101849004840285018401909552848452610024949193602493909291840191908190840183828082843750949650505050505050620186a05a101561014e57610002565b6100db60008054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281529291908301828280156102145780601f106101e957610100808354040283529160200191610214565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b505050565b8060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101b557805160ff19168380011785555b506101499291505b808211156101e557600081556001016101a1565b82800160010185558215610199579182015b828111156101995782518260005055916020019190600101906101c7565b5090565b820191906000526020600020905b8154815290600101906020018083116101f757829003601f168201915b50505050508156`}, - []string{`[{"constant":false,"inputs":[{"name":"value","type":"string"}],"name":"SetField","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"field","outputs":[{"name":"","type":"string"}],"type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a funky gas pattern contract - _, _, limiter, err := DeployFunkyGasPattern(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy funky contract: %v", err) - } - sim.Commit() - - // Set the field with automatic estimation and check that it succeeds - if _, err := limiter.SetField(auth, "automatic"); err != nil { - t.Fatalf("Failed to call automatically gased transaction: %v", err) - } - sim.Commit() - - if field, _ := limiter.Field(nil); field != "automatic" { - t.Fatalf("Field mismatch: have %v, want %v", field, "automatic") - } - `, - nil, - nil, - nil, - nil, - }, - // Test that constant functions can be called from an (optional) specified address - { - `CallFrom`, - ` - contract CallFrom { - function callFrom() constant returns(address) { - return msg.sender; - } - } - `, []string{`6060604052346000575b6086806100176000396000f300606060405263ffffffff60e060020a60003504166349f8e98281146022575b6000565b34600057602c6055565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b335b905600a165627a7a72305820aef6b7685c0fa24ba6027e4870404a57df701473fe4107741805c19f5138417c0029`}, - []string{`[{"constant":true,"inputs":[],"name":"callFrom","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a sender tester contract and execute a structured call on it - _, _, callfrom, err := DeployCallFrom(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy sender contract: %v", err) - } - sim.Commit() - - if res, err := callfrom.CallFrom(nil); err != nil { - t.Errorf("Failed to call constant function: %v", err) - } else if res != (common.Address{}) { - t.Errorf("Invalid address returned, want: %x, got: %x", (common.Address{}), res) - } - - for _, addr := range []common.Address{common.Address{}, common.Address{1}, common.Address{2}} { - if res, err := callfrom.CallFrom(&bind.CallOpts{From: addr}); err != nil { - t.Fatalf("Failed to call constant function: %v", err) - } else if res != addr { - t.Fatalf("Invalid address returned, want: %x, got: %x", addr, res) - } - } - `, - nil, - nil, - nil, - nil, - }, - // Tests that methods and returns with underscores inside work correctly. - { - `Underscorer`, - ` - contract Underscorer { - function UnderscoredOutput() constant returns (int _int, string _string) { - return (314, "pi"); - } - function LowerLowerCollision() constant returns (int _res, int res) { - return (1, 2); - } - function LowerUpperCollision() constant returns (int _res, int Res) { - return (1, 2); - } - function UpperLowerCollision() constant returns (int _Res, int res) { - return (1, 2); - } - function UpperUpperCollision() constant returns (int _Res, int Res) { - return (1, 2); - } - function PurelyUnderscoredOutput() constant returns (int _, int res) { - return (1, 2); - } - function AllPurelyUnderscoredOutput() constant returns (int _, int __) { - return (1, 2); - } - function _under_scored_func() constant returns (int _int) { - return 0; - } - } - `, []string{`6060604052341561000f57600080fd5b6103858061001e6000396000f30060606040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806303a592131461009357806346546dbe146100c357806367e6633d146100ec5780639df4848514610181578063af7486ab146101b1578063b564b34d146101e1578063e02ab24d14610211578063e409ca4514610241575b600080fd5b341561009e57600080fd5b6100a6610271565b604051808381526020018281526020019250505060405180910390f35b34156100ce57600080fd5b6100d6610286565b6040518082815260200191505060405180910390f35b34156100f757600080fd5b6100ff61028e565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561014557808201518184015260208101905061012a565b50505050905090810190601f1680156101725780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561018c57600080fd5b6101946102dc565b604051808381526020018281526020019250505060405180910390f35b34156101bc57600080fd5b6101c46102f1565b604051808381526020018281526020019250505060405180910390f35b34156101ec57600080fd5b6101f4610306565b604051808381526020018281526020019250505060405180910390f35b341561021c57600080fd5b61022461031b565b604051808381526020018281526020019250505060405180910390f35b341561024c57600080fd5b610254610330565b604051808381526020018281526020019250505060405180910390f35b60008060016002819150809050915091509091565b600080905090565b6000610298610345565b61013a8090506040805190810160405280600281526020017f7069000000000000000000000000000000000000000000000000000000000000815250915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b60008060016002819150809050915091509091565b6020604051908101604052806000815250905600a165627a7a72305820d1a53d9de9d1e3d55cb3dc591900b63c4f1ded79114f7b79b332684840e186a40029`}, - []string{`[{"constant":true,"inputs":[],"name":"LowerUpperCollision","outputs":[{"name":"_res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_under_scored_func","outputs":[{"name":"_int","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UnderscoredOutput","outputs":[{"name":"_int","type":"int256"},{"name":"_string","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperLowerCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"AllPurelyUnderscoredOutput","outputs":[{"name":"_","type":"int256"},{"name":"__","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"UpperUpperCollision","outputs":[{"name":"_Res","type":"int256"},{"name":"Res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"LowerLowerCollision","outputs":[{"name":"_res","type":"int256"},{"name":"res","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"}]`}, - ` - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a underscorer tester contract and execute a structured call on it - _, _, underscorer, err := DeployUnderscorer(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy underscorer contract: %v", err) - } - sim.Commit() - - // Verify that underscored return values correctly parse into structs - if res, err := underscorer.UnderscoredOutput(nil); err != nil { - t.Errorf("Failed to call constant function: %v", err) - } else if res.Int.Cmp(big.NewInt(314)) != 0 || res.String != "pi" { - t.Errorf("Invalid result, want: {314, \"pi\"}, got: %+v", res) - } - // Verify that underscored and non-underscored name collisions force tuple outputs - var a, b *big.Int - - a, b, _ = underscorer.LowerLowerCollision(nil) - a, b, _ = underscorer.LowerUpperCollision(nil) - a, b, _ = underscorer.UpperLowerCollision(nil) - a, b, _ = underscorer.UpperUpperCollision(nil) - a, b, _ = underscorer.PurelyUnderscoredOutput(nil) - a, b, _ = underscorer.AllPurelyUnderscoredOutput(nil) - a, _ = underscorer.UnderScoredFunc(nil) - - fmt.Println(a, b, err) - `, - nil, - nil, - nil, - nil, - }, - // Tests that logs can be successfully filtered and decoded. - { - `Eventer`, - ` - contract Eventer { - event SimpleEvent ( - address indexed Addr, - bytes32 indexed Id, - bool indexed Flag, - uint Value - ); - function raiseSimpleEvent(address addr, bytes32 id, bool flag, uint value) { - SimpleEvent(addr, id, flag, value); - } - - event NodataEvent ( - uint indexed Number, - int16 indexed Short, - uint32 indexed Long - ); - function raiseNodataEvent(uint number, int16 short, uint32 long) { - NodataEvent(number, short, long); - } - - event DynamicEvent ( - string indexed IndexedString, - bytes indexed IndexedBytes, - string NonIndexedString, - bytes NonIndexedBytes - ); - function raiseDynamicEvent(string str, bytes blob) { - DynamicEvent(str, blob, str, blob); - } - - event FixedBytesEvent ( - bytes24 indexed IndexedBytes, - bytes24 NonIndexedBytes - ); - function raiseFixedBytesEvent(bytes24 blob) { - FixedBytesEvent(blob, blob); - } - } - `, - []string{`608060405234801561001057600080fd5b5061043f806100206000396000f3006080604052600436106100615763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663528300ff8114610066578063630c31e2146100ff5780636cc6b94014610138578063c7d116dd1461015b575b600080fd5b34801561007257600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526100fd94369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506101829650505050505050565b005b34801561010b57600080fd5b506100fd73ffffffffffffffffffffffffffffffffffffffff60043516602435604435151560643561033c565b34801561014457600080fd5b506100fd67ffffffffffffffff1960043516610394565b34801561016757600080fd5b506100fd60043560243560010b63ffffffff604435166103d6565b806040518082805190602001908083835b602083106101b25780518252601f199092019160209182019101610193565b51815160209384036101000a6000190180199092169116179052604051919093018190038120875190955087945090928392508401908083835b6020831061020b5780518252601f1990920191602091820191016101ec565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f3281fd4f5e152dd3385df49104a3f633706e21c9e80672e88d3bcddf33101f008484604051808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561029c578181015183820152602001610284565b50505050905090810190601f1680156102c95780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156102fc5781810151838201526020016102e4565b50505050905090810190601f1680156103295780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a35050565b60408051828152905183151591859173ffffffffffffffffffffffffffffffffffffffff8816917f1f097de4289df643bd9c11011cc61367aa12983405c021056e706eb5ba1250c8919081900360200190a450505050565b6040805167ffffffffffffffff19831680825291517fcdc4c1b1aed5524ffb4198d7a5839a34712baef5fa06884fac7559f4a5854e0a9181900360200190a250565b8063ffffffff168260010b847f3ca7f3a77e5e6e15e781850bc82e32adfa378a2a609370db24b4d0fae10da2c960405160405180910390a45050505600a165627a7a72305820468b5843bf653145bd924b323c64ef035d3dd922c170644b44d61aa666ea6eee0029`}, - []string{`[{"constant":false,"inputs":[{"name":"str","type":"string"},{"name":"blob","type":"bytes"}],"name":"raiseDynamicEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"id","type":"bytes32"},{"name":"flag","type":"bool"},{"name":"value","type":"uint256"}],"name":"raiseSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"blob","type":"bytes24"}],"name":"raiseFixedBytesEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"number","type":"uint256"},{"name":"short","type":"int16"},{"name":"long","type":"uint32"}],"name":"raiseNodataEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Addr","type":"address"},{"indexed":true,"name":"Id","type":"bytes32"},{"indexed":true,"name":"Flag","type":"bool"},{"indexed":false,"name":"Value","type":"uint256"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"Number","type":"uint256"},{"indexed":true,"name":"Short","type":"int16"},{"indexed":true,"name":"Long","type":"uint32"}],"name":"NodataEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedString","type":"string"},{"indexed":true,"name":"IndexedBytes","type":"bytes"},{"indexed":false,"name":"NonIndexedString","type":"string"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes"}],"name":"DynamicEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"IndexedBytes","type":"bytes24"},{"indexed":false,"name":"NonIndexedBytes","type":"bytes24"}],"name":"FixedBytesEvent","type":"event"}]`}, - ` - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy an eventer contract - _, _, eventer, err := DeployEventer(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy eventer contract: %v", err) - } - sim.Commit() - - // Inject a few events into the contract, gradually more in each block - for i := 1; i <= 3; i++ { - for j := 1; j <= i; j++ { - if _, err := eventer.RaiseSimpleEvent(auth, common.Address{byte(j)}, [32]byte{byte(j)}, true, big.NewInt(int64(10*i+j))); err != nil { - t.Fatalf("block %d, event %d: raise failed: %v", i, j, err) - } - } - sim.Commit() - } - // Test filtering for certain events and ensure they can be found - sit, err := eventer.FilterSimpleEvent(nil, []common.Address{common.Address{1}, common.Address{3}}, [][32]byte{{byte(1)}, {byte(2)}, {byte(3)}}, []bool{true}) - if err != nil { - t.Fatalf("failed to filter for simple events: %v", err) - } - defer sit.Close() - - sit.Next() - if sit.Event.Value.Uint64() != 11 || !sit.Event.Flag { - t.Errorf("simple log content mismatch: have %v, want {11, true}", sit.Event) - } - sit.Next() - if sit.Event.Value.Uint64() != 21 || !sit.Event.Flag { - t.Errorf("simple log content mismatch: have %v, want {21, true}", sit.Event) - } - sit.Next() - if sit.Event.Value.Uint64() != 31 || !sit.Event.Flag { - t.Errorf("simple log content mismatch: have %v, want {31, true}", sit.Event) - } - sit.Next() - if sit.Event.Value.Uint64() != 33 || !sit.Event.Flag { - t.Errorf("simple log content mismatch: have %v, want {33, true}", sit.Event) - } - - if sit.Next() { - t.Errorf("unexpected simple event found: %+v", sit.Event) - } - if err = sit.Error(); err != nil { - t.Fatalf("simple event iteration failed: %v", err) - } - // Test raising and filtering for an event with no data component - if _, err := eventer.RaiseNodataEvent(auth, big.NewInt(314), 141, 271); err != nil { - t.Fatalf("failed to raise nodata event: %v", err) - } - sim.Commit() - - nit, err := eventer.FilterNodataEvent(nil, []*big.Int{big.NewInt(314)}, []int16{140, 141, 142}, []uint32{271}) - if err != nil { - t.Fatalf("failed to filter for nodata events: %v", err) - } - defer nit.Close() - - if !nit.Next() { - t.Fatalf("nodata log not found: %v", nit.Error()) - } - if nit.Event.Number.Uint64() != 314 { - t.Errorf("nodata log content mismatch: have %v, want 314", nit.Event.Number) - } - if nit.Next() { - t.Errorf("unexpected nodata event found: %+v", nit.Event) - } - if err = nit.Error(); err != nil { - t.Fatalf("nodata event iteration failed: %v", err) - } - // Test raising and filtering for events with dynamic indexed components - if _, err := eventer.RaiseDynamicEvent(auth, "Hello", []byte("World")); err != nil { - t.Fatalf("failed to raise dynamic event: %v", err) - } - sim.Commit() - - dit, err := eventer.FilterDynamicEvent(nil, []string{"Hi", "Hello", "Bye"}, [][]byte{[]byte("World")}) - if err != nil { - t.Fatalf("failed to filter for dynamic events: %v", err) - } - defer dit.Close() - - if !dit.Next() { - t.Fatalf("dynamic log not found: %v", dit.Error()) - } - if dit.Event.NonIndexedString != "Hello" || string(dit.Event.NonIndexedBytes) != "World" || dit.Event.IndexedString != common.HexToHash("0x06b3dfaec148fb1bb2b066f10ec285e7c9bf402ab32aa78a5d38e34566810cd2") || dit.Event.IndexedBytes != common.HexToHash("0xf2208c967df089f60420785795c0a9ba8896b0f6f1867fa7f1f12ad6f79c1a18") { - t.Errorf("dynamic log content mismatch: have %v, want {'0x06b3dfaec148fb1bb2b066f10ec285e7c9bf402ab32aa78a5d38e34566810cd2, '0xf2208c967df089f60420785795c0a9ba8896b0f6f1867fa7f1f12ad6f79c1a18', 'Hello', 'World'}", dit.Event) - } - if dit.Next() { - t.Errorf("unexpected dynamic event found: %+v", dit.Event) - } - if err = dit.Error(); err != nil { - t.Fatalf("dynamic event iteration failed: %v", err) - } - // Test raising and filtering for events with fixed bytes components - var fblob [24]byte - copy(fblob[:], []byte("Fixed Bytes")) - - if _, err := eventer.RaiseFixedBytesEvent(auth, fblob); err != nil { - t.Fatalf("failed to raise fixed bytes event: %v", err) - } - sim.Commit() - - fit, err := eventer.FilterFixedBytesEvent(nil, [][24]byte{fblob}) - if err != nil { - t.Fatalf("failed to filter for fixed bytes events: %v", err) - } - defer fit.Close() - - if !fit.Next() { - t.Fatalf("fixed bytes log not found: %v", fit.Error()) - } - if fit.Event.NonIndexedBytes != fblob || fit.Event.IndexedBytes != fblob { - t.Errorf("fixed bytes log content mismatch: have %v, want {'%x', '%x'}", fit.Event, fblob, fblob) - } - if fit.Next() { - t.Errorf("unexpected fixed bytes event found: %+v", fit.Event) - } - if err = fit.Error(); err != nil { - t.Fatalf("fixed bytes event iteration failed: %v", err) - } - // Test subscribing to an event and raising it afterwards - ch := make(chan *EventerSimpleEvent, 16) - sub, err := eventer.WatchSimpleEvent(nil, ch, nil, nil, nil) - if err != nil { - t.Fatalf("failed to subscribe to simple events: %v", err) - } - if _, err := eventer.RaiseSimpleEvent(auth, common.Address{255}, [32]byte{255}, true, big.NewInt(255)); err != nil { - t.Fatalf("failed to raise subscribed simple event: %v", err) - } - sim.Commit() - - select { - case event := <-ch: - if event.Value.Uint64() != 255 { - t.Errorf("simple log content mismatch: have %v, want 255", event) - } - case <-time.After(250 * time.Millisecond): - t.Fatalf("subscribed simple event didn't arrive") - } - // Unsubscribe from the event and make sure we're not delivered more - sub.Unsubscribe() - - if _, err := eventer.RaiseSimpleEvent(auth, common.Address{254}, [32]byte{254}, true, big.NewInt(254)); err != nil { - t.Fatalf("failed to raise subscribed simple event: %v", err) - } - sim.Commit() - - select { - case event := <-ch: - t.Fatalf("unsubscribed simple event arrived: %v", event) - case <-time.After(250 * time.Millisecond): - } - `, - nil, - nil, - nil, - nil, - }, - { - `DeeplyNestedArray`, - ` - contract DeeplyNestedArray { - uint64[3][4][5] public deepUint64Array; - function storeDeepUintArray(uint64[3][4][5] arr) public { - deepUint64Array = arr; - } - function retrieveDeepArray() public view returns (uint64[3][4][5]) { - return deepUint64Array; - } - } - `, - []string{`6060604052341561000f57600080fd5b6106438061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063344248551461005c5780638ed4573a1461011457806398ed1856146101ab575b600080fd5b341561006757600080fd5b610112600480806107800190600580602002604051908101604052809291906000905b828210156101055783826101800201600480602002604051908101604052809291906000905b828210156100f25783826060020160038060200260405190810160405280929190826003602002808284378201915050505050815260200190600101906100b0565b505050508152602001906001019061008a565b5050505091905050610208565b005b341561011f57600080fd5b61012761021d565b604051808260056000925b8184101561019b578284602002015160046000925b8184101561018d5782846020020151600360200280838360005b8381101561017c578082015181840152602081019050610161565b505050509050019260010192610147565b925050509260010192610132565b9250505091505060405180910390f35b34156101b657600080fd5b6101de6004808035906020019091908035906020019091908035906020019091905050610309565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b80600090600561021992919061035f565b5050565b6102256103b0565b6000600580602002604051908101604052809291906000905b8282101561030057838260040201600480602002604051908101604052809291906000905b828210156102ed578382016003806020026040519081016040528092919082600380156102d9576020028201916000905b82829054906101000a900467ffffffffffffffff1667ffffffffffffffff16815260200190600801906020826007010492830192600103820291508084116102945790505b505050505081526020019060010190610263565b505050508152602001906001019061023e565b50505050905090565b60008360058110151561031857fe5b600402018260048110151561032957fe5b018160038110151561033757fe5b6004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b826005600402810192821561039f579160200282015b8281111561039e5782518290600461038e9291906103df565b5091602001919060040190610375565b5b5090506103ac919061042d565b5090565b610780604051908101604052806005905b6103c9610459565b8152602001906001900390816103c15790505090565b826004810192821561041c579160200282015b8281111561041b5782518290600361040b929190610488565b50916020019190600101906103f2565b5b5090506104299190610536565b5090565b61045691905b8082111561045257600081816104499190610562565b50600401610433565b5090565b90565b610180604051908101604052806004905b6104726105a7565b81526020019060019003908161046a5790505090565b82600380016004900481019282156105255791602002820160005b838211156104ef57835183826101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555092602001926008016020816007010492830192600103026104a3565b80156105235782816101000a81549067ffffffffffffffff02191690556008016020816007010492830192600103026104ef565b505b50905061053291906105d9565b5090565b61055f91905b8082111561055b57600081816105529190610610565b5060010161053c565b5090565b90565b50600081816105719190610610565b50600101600081816105839190610610565b50600101600081816105959190610610565b5060010160006105a59190610610565b565b6060604051908101604052806003905b600067ffffffffffffffff168152602001906001900390816105b75790505090565b61060d91905b8082111561060957600081816101000a81549067ffffffffffffffff0219169055506001016105df565b5090565b90565b50600090555600a165627a7a7230582087e5a43f6965ab6ef7a4ff056ab80ed78fd8c15cff57715a1bf34ec76a93661c0029`}, - []string{`[{"constant":false,"inputs":[{"name":"arr","type":"uint64[3][4][5]"}],"name":"storeDeepUintArray","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"retrieveDeepArray","outputs":[{"name":"","type":"uint64[3][4][5]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"deepUint64Array","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - //deploy the test contract - _, _, testContract, err := DeployDeeplyNestedArray(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy test contract: %v", err) - } - - // Finish deploy. - sim.Commit() - - //Create coordinate-filled array, for testing purposes. - testArr := [5][4][3]uint64{} - for i := 0; i < 5; i++ { - testArr[i] = [4][3]uint64{} - for j := 0; j < 4; j++ { - testArr[i][j] = [3]uint64{} - for k := 0; k < 3; k++ { - //pack the coordinates, each array value will be unique, and can be validated easily. - testArr[i][j][k] = uint64(i) << 16 | uint64(j) << 8 | uint64(k) - } - } - } - - if _, err := testContract.StoreDeepUintArray(&bind.TransactOpts{ - From: auth.From, - Signer: auth.Signer, - }, testArr); err != nil { - t.Fatalf("Failed to store nested array in test contract: %v", err) - } - - sim.Commit() - - retrievedArr, err := testContract.RetrieveDeepArray(&bind.CallOpts{ - From: auth.From, - Pending: false, - }) - if err != nil { - t.Fatalf("Failed to retrieve nested array from test contract: %v", err) - } - - //quick check to see if contents were copied - // (See accounts/abi/unpack_test.go for more extensive testing) - if retrievedArr[4][3][2] != testArr[4][3][2] { - t.Fatalf("Retrieved value does not match expected value! got: %d, expected: %d. %v", retrievedArr[4][3][2], testArr[4][3][2], err) - } - `, - nil, - nil, - nil, - nil, - }, - { - `CallbackParam`, - ` - contract FunctionPointerTest { - function test(function(uint256) external callback) external { - callback(1); - } - } - `, - []string{`608060405234801561001057600080fd5b5061015e806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063d7a5aba214610040575b600080fd5b34801561004c57600080fd5b506100be6004803603602081101561006357600080fd5b810190808035806c0100000000000000000000000090049068010000000000000000900463ffffffff1677ffffffffffffffffffffffffffffffffffffffffffffffff169091602001919093929190939291905050506100c0565b005b818160016040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561011657600080fd5b505af115801561012a573d6000803e3d6000fd5b50505050505056fea165627a7a7230582062f87455ff84be90896dbb0c4e4ddb505c600d23089f8e80a512548440d7e2580029`}, - []string{`[ - { - "constant": false, - "inputs": [ - { - "name": "callback", - "type": "function" - } - ], - "name": "test", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ]`}, ` - "strings" - `, - ` - if strings.Compare("test(function)", CallbackParamFuncSigs["d7a5aba2"]) != 0 { - t.Fatalf("") - } - `, - []map[string]string{ - { - "test(function)": "d7a5aba2", - }, - }, - nil, - nil, - nil, - }, { - `Tuple`, - ` - pragma solidity >=0.4.19 <0.6.0; - pragma experimental ABIEncoderV2; - - contract Tuple { - struct S { uint a; uint[] b; T[] c; } - struct T { uint x; uint y; } - struct P { uint8 x; uint8 y; } - struct Q { uint16 x; uint16 y; } - event TupleEvent(S a, T[2][] b, T[][2] c, S[] d, uint[] e); - event TupleEvent2(P[]); - - function func1(S memory a, T[2][] memory b, T[][2] memory c, S[] memory d, uint[] memory e) public pure returns (S memory, T[2][] memory, T[][2] memory, S[] memory, uint[] memory) { - return (a, b, c, d, e); - } - function func2(S memory a, T[2][] memory b, T[][2] memory c, S[] memory d, uint[] memory e) public { - emit TupleEvent(a, b, c, d, e); - } - function func3(Q[] memory) public pure {} // call function, nothing to return - } - `, - []string{`60806040523480156100115760006000fd5b50610017565b6110b2806100266000396000f3fe60806040523480156100115760006000fd5b50600436106100465760003560e01c8063443c79b41461004c578063d0062cdd14610080578063e4d9a43b1461009c57610046565b60006000fd5b610066600480360361006191908101906107b8565b6100b8565b604051610077959493929190610ccb565b60405180910390f35b61009a600480360361009591908101906107b8565b6100ef565b005b6100b660048036036100b19190810190610775565b610136565b005b6100c061013a565b60606100ca61015e565b606060608989898989945094509450945094506100e2565b9550955095509550959050565b7f18d6e66efa53739ca6d13626f35ebc700b31cced3eddb50c70bbe9c082c6cd008585858585604051610126959493929190610ccb565b60405180910390a15b5050505050565b5b50565b60405180606001604052806000815260200160608152602001606081526020015090565b60405180604001604052806002905b606081526020019060019003908161016d57905050905661106e565b600082601f830112151561019d5760006000fd5b81356101b06101ab82610d6f565b610d41565b915081818352602084019350602081019050838560808402820111156101d65760006000fd5b60005b8381101561020757816101ec888261037a565b8452602084019350608083019250505b6001810190506101d9565b5050505092915050565b600082601f83011215156102255760006000fd5b600261023861023382610d98565b610d41565b9150818360005b83811015610270578135860161025588826103f3565b8452602084019350602083019250505b60018101905061023f565b5050505092915050565b600082601f830112151561028e5760006000fd5b81356102a161029c82610dbb565b610d41565b915081818352602084019350602081019050838560408402820111156102c75760006000fd5b60005b838110156102f857816102dd888261058b565b8452602084019350604083019250505b6001810190506102ca565b5050505092915050565b600082601f83011215156103165760006000fd5b813561032961032482610de4565b610d41565b9150818183526020840193506020810190508360005b83811015610370578135860161035588826105d8565b8452602084019350602083019250505b60018101905061033f565b5050505092915050565b600082601f830112151561038e5760006000fd5b60026103a161039c82610e0d565b610d41565b915081838560408402820111156103b85760006000fd5b60005b838110156103e957816103ce88826106fe565b8452602084019350604083019250505b6001810190506103bb565b5050505092915050565b600082601f83011215156104075760006000fd5b813561041a61041582610e30565b610d41565b915081818352602084019350602081019050838560408402820111156104405760006000fd5b60005b83811015610471578161045688826106fe565b8452602084019350604083019250505b600181019050610443565b5050505092915050565b600082601f830112151561048f5760006000fd5b81356104a261049d82610e59565b610d41565b915081818352602084019350602081019050838560208402820111156104c85760006000fd5b60005b838110156104f957816104de8882610760565b8452602084019350602083019250505b6001810190506104cb565b5050505092915050565b600082601f83011215156105175760006000fd5b813561052a61052582610e82565b610d41565b915081818352602084019350602081019050838560208402820111156105505760006000fd5b60005b8381101561058157816105668882610760565b8452602084019350602083019250505b600181019050610553565b5050505092915050565b60006040828403121561059e5760006000fd5b6105a86040610d41565b905060006105b88482850161074b565b60008301525060206105cc8482850161074b565b60208301525092915050565b6000606082840312156105eb5760006000fd5b6105f56060610d41565b9050600061060584828501610760565b600083015250602082013567ffffffffffffffff8111156106265760006000fd5b6106328482850161047b565b602083015250604082013567ffffffffffffffff8111156106535760006000fd5b61065f848285016103f3565b60408301525092915050565b60006060828403121561067e5760006000fd5b6106886060610d41565b9050600061069884828501610760565b600083015250602082013567ffffffffffffffff8111156106b95760006000fd5b6106c58482850161047b565b602083015250604082013567ffffffffffffffff8111156106e65760006000fd5b6106f2848285016103f3565b60408301525092915050565b6000604082840312156107115760006000fd5b61071b6040610d41565b9050600061072b84828501610760565b600083015250602061073f84828501610760565b60208301525092915050565b60008135905061075a8161103a565b92915050565b60008135905061076f81611054565b92915050565b6000602082840312156107885760006000fd5b600082013567ffffffffffffffff8111156107a35760006000fd5b6107af8482850161027a565b91505092915050565b6000600060006000600060a086880312156107d35760006000fd5b600086013567ffffffffffffffff8111156107ee5760006000fd5b6107fa8882890161066b565b955050602086013567ffffffffffffffff8111156108185760006000fd5b61082488828901610189565b945050604086013567ffffffffffffffff8111156108425760006000fd5b61084e88828901610211565b935050606086013567ffffffffffffffff81111561086c5760006000fd5b61087888828901610302565b925050608086013567ffffffffffffffff8111156108965760006000fd5b6108a288828901610503565b9150509295509295909350565b60006108bb8383610a6a565b60808301905092915050565b60006108d38383610ac2565b905092915050565b60006108e78383610c36565b905092915050565b60006108fb8383610c8d565b60408301905092915050565b60006109138383610cbc565b60208301905092915050565b600061092a82610f0f565b6109348185610fb7565b935061093f83610eab565b8060005b8381101561097157815161095788826108af565b975061096283610f5c565b9250505b600181019050610943565b5085935050505092915050565b600061098982610f1a565b6109938185610fc8565b9350836020820285016109a585610ebb565b8060005b858110156109e257848403895281516109c285826108c7565b94506109cd83610f69565b925060208a019950505b6001810190506109a9565b50829750879550505050505092915050565b60006109ff82610f25565b610a098185610fd3565b935083602082028501610a1b85610ec5565b8060005b85811015610a585784840389528151610a3885826108db565b9450610a4383610f76565b925060208a019950505b600181019050610a1f565b50829750879550505050505092915050565b610a7381610f30565b610a7d8184610fe4565b9250610a8882610ed5565b8060005b83811015610aba578151610aa087826108ef565b9650610aab83610f83565b9250505b600181019050610a8c565b505050505050565b6000610acd82610f3b565b610ad78185610fef565b9350610ae283610edf565b8060005b83811015610b14578151610afa88826108ef565b9750610b0583610f90565b9250505b600181019050610ae6565b5085935050505092915050565b6000610b2c82610f51565b610b368185611011565b9350610b4183610eff565b8060005b83811015610b73578151610b598882610907565b9750610b6483610faa565b9250505b600181019050610b45565b5085935050505092915050565b6000610b8b82610f46565b610b958185611000565b9350610ba083610eef565b8060005b83811015610bd2578151610bb88882610907565b9750610bc383610f9d565b9250505b600181019050610ba4565b5085935050505092915050565b6000606083016000830151610bf76000860182610cbc565b5060208301518482036020860152610c0f8282610b80565b91505060408301518482036040860152610c298282610ac2565b9150508091505092915050565b6000606083016000830151610c4e6000860182610cbc565b5060208301518482036020860152610c668282610b80565b91505060408301518482036040860152610c808282610ac2565b9150508091505092915050565b604082016000820151610ca36000850182610cbc565b506020820151610cb66020850182610cbc565b50505050565b610cc581611030565b82525050565b600060a0820190508181036000830152610ce58188610bdf565b90508181036020830152610cf9818761091f565b90508181036040830152610d0d818661097e565b90508181036060830152610d2181856109f4565b90508181036080830152610d358184610b21565b90509695505050505050565b6000604051905081810181811067ffffffffffffffff82111715610d655760006000fd5b8060405250919050565b600067ffffffffffffffff821115610d875760006000fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610db05760006000fd5b602082029050919050565b600067ffffffffffffffff821115610dd35760006000fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610dfc5760006000fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610e255760006000fd5b602082029050919050565b600067ffffffffffffffff821115610e485760006000fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610e715760006000fd5b602082029050602081019050919050565b600067ffffffffffffffff821115610e9a5760006000fd5b602082029050602081019050919050565b6000819050602082019050919050565b6000819050919050565b6000819050602082019050919050565b6000819050919050565b6000819050602082019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600061ffff82169050919050565b6000819050919050565b61104381611022565b811415156110515760006000fd5b50565b61105d81611030565b8114151561106b5760006000fd5b50565bfea365627a7a72315820d78c6ba7ee332581e6c4d9daa5fc07941841230f7ce49edf6e05b1b63853e8746c6578706572696d656e74616cf564736f6c634300050c0040`}, - []string{` -[{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"indexed":false,"internalType":"struct Tuple.S","name":"a","type":"tuple"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"indexed":false,"internalType":"struct Tuple.T[2][]","name":"b","type":"tuple[2][]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"indexed":false,"internalType":"struct Tuple.T[][2]","name":"c","type":"tuple[][2]"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"indexed":false,"internalType":"struct Tuple.S[]","name":"d","type":"tuple[]"},{"indexed":false,"internalType":"uint256[]","name":"e","type":"uint256[]"}],"name":"TupleEvent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"}],"indexed":false,"internalType":"struct Tuple.P[]","name":"","type":"tuple[]"}],"name":"TupleEvent2","type":"event"},{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S","name":"a","type":"tuple"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[2][]","name":"b","type":"tuple[2][]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[][2]","name":"c","type":"tuple[][2]"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S[]","name":"d","type":"tuple[]"},{"internalType":"uint256[]","name":"e","type":"uint256[]"}],"name":"func1","outputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[2][]","name":"","type":"tuple[2][]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[][2]","name":"","type":"tuple[][2]"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S[]","name":"","type":"tuple[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S","name":"a","type":"tuple"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[2][]","name":"b","type":"tuple[2][]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[][2]","name":"c","type":"tuple[][2]"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256[]","name":"b","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Tuple.T[]","name":"c","type":"tuple[]"}],"internalType":"struct Tuple.S[]","name":"d","type":"tuple[]"},{"internalType":"uint256[]","name":"e","type":"uint256[]"}],"name":"func2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"uint16","name":"x","type":"uint16"},{"internalType":"uint16","name":"y","type":"uint16"}],"internalType":"struct Tuple.Q[]","name":"","type":"tuple[]"}],"name":"func3","outputs":[],"payable":false,"stateMutability":"pure","type":"function"}] - `}, - ` - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - - ` - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - _, _, contract, err := DeployTuple(auth, sim) - if err != nil { - t.Fatalf("deploy contract failed %v", err) - } - sim.Commit() - - check := func(a, b interface{}, errMsg string) { - if !reflect.DeepEqual(a, b) { - t.Fatal(errMsg) - } - } - - a := TupleS{ - A: big.NewInt(1), - B: []*big.Int{big.NewInt(2), big.NewInt(3)}, - C: []TupleT{ - { - X: big.NewInt(4), - Y: big.NewInt(5), - }, - { - X: big.NewInt(6), - Y: big.NewInt(7), - }, - }, - } - - b := [][2]TupleT{ - { - { - X: big.NewInt(8), - Y: big.NewInt(9), - }, - { - X: big.NewInt(10), - Y: big.NewInt(11), - }, - }, - } - - c := [2][]TupleT{ - { - { - X: big.NewInt(12), - Y: big.NewInt(13), - }, - { - X: big.NewInt(14), - Y: big.NewInt(15), - }, - }, - { - { - X: big.NewInt(16), - Y: big.NewInt(17), - }, - }, - } - - d := []TupleS{a} - - e := []*big.Int{big.NewInt(18), big.NewInt(19)} - ret1, ret2, ret3, ret4, ret5, err := contract.Func1(nil, a, b, c, d, e) - if err != nil { - t.Fatalf("invoke contract failed, err %v", err) - } - check(ret1, a, "ret1 mismatch") - check(ret2, b, "ret2 mismatch") - check(ret3, c, "ret3 mismatch") - check(ret4, d, "ret4 mismatch") - check(ret5, e, "ret5 mismatch") - - _, err = contract.Func2(auth, a, b, c, d, e) - if err != nil { - t.Fatalf("invoke contract failed, err %v", err) - } - sim.Commit() - - iter, err := contract.FilterTupleEvent(nil) - if err != nil { - t.Fatalf("failed to create event filter, err %v", err) - } - defer iter.Close() - - iter.Next() - check(iter.Event.A, a, "field1 mismatch") - check(iter.Event.B, b, "field2 mismatch") - check(iter.Event.C, c, "field3 mismatch") - check(iter.Event.D, d, "field4 mismatch") - check(iter.Event.E, e, "field5 mismatch") - - err = contract.Func3(nil, nil) - if err != nil { - t.Fatalf("failed to call function which has no return, err %v", err) - } - `, - nil, - nil, - nil, - nil, - }, - { - `UseLibrary`, - ` - library Math { - function add(uint a, uint b) public view returns(uint) { - return a + b; - } - } - - contract UseLibrary { - function add (uint c, uint d) public view returns(uint) { - return Math.add(c,d); - } - } - `, - []string{ - // Bytecode for the UseLibrary contract - `608060405234801561001057600080fd5b5061011d806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063771602f714602d575b600080fd5b604d60048036036040811015604157600080fd5b5080359060200135605f565b60408051918252519081900360200190f35b600073__$b98c933f0a6ececcd167bd4f9d3299b1a0$__63771602f784846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801560b757600080fd5b505af415801560ca573d6000803e3d6000fd5b505050506040513d602081101560df57600080fd5b5051939250505056fea265627a7a72305820eb5c38f42445604cfa43d85e3aa5ecc48b0a646456c902dd48420ae7241d06f664736f6c63430005090032`, - // Bytecode for the Math contract - `60a3610024600b82828239805160001a607314601757fe5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c8063771602f7146038575b600080fd5b605860048036036040811015604c57600080fd5b5080359060200135606a565b60408051918252519081900360200190f35b019056fea265627a7a723058206fc6c05f3078327f9c763edffdb5ab5f8bd212e293a1306c7d0ad05af3ad35f464736f6c63430005090032`, - }, - []string{ - `[{"constant":true,"inputs":[{"name":"c","type":"uint256"},{"name":"d","type":"uint256"}],"name":"add","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]`, - `[{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"add","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]`, - }, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - //deploy the test contract - _, _, testContract, err := DeployUseLibrary(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy test contract: %v", err) - } - - // Finish deploy. - sim.Commit() - - // Check that the library contract has been deployed - // by calling the contract's add function. - res, err := testContract.Add(&bind.CallOpts{ - From: auth.From, - Pending: false, - }, big.NewInt(1), big.NewInt(2)) - if err != nil { - t.Fatalf("Failed to call linked contract: %v", err) - } - if res.Cmp(big.NewInt(3)) != 0 { - t.Fatalf("Add did not return the correct result: %d != %d", res, 3) - } - `, - nil, - map[string]string{ - "b98c933f0a6ececcd167bd4f9d3299b1a0": "Math", - }, - nil, - []string{"UseLibrary", "Math"}, - }, { - "Overload", - ` - pragma solidity ^0.5.10; - - contract overload { - mapping(address => uint256) balances; - - event bar(uint256 i); - event bar(uint256 i, uint256 j); - - function foo(uint256 i) public { - emit bar(i); - } - function foo(uint256 i, uint256 j) public { - emit bar(i, j); - } - } - `, - []string{`608060405234801561001057600080fd5b50610153806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806304bc52f81461003b5780632fbebd3814610073575b600080fd5b6100716004803603604081101561005157600080fd5b8101908080359060200190929190803590602001909291905050506100a1565b005b61009f6004803603602081101561008957600080fd5b81019080803590602001909291905050506100e4565b005b7fae42e9514233792a47a1e4554624e83fe852228e1503f63cd383e8a431f4f46d8282604051808381526020018281526020019250505060405180910390a15050565b7f0423a1321222a0a8716c22b92fac42d85a45a612b696a461784d9fa537c81e5c816040518082815260200191505060405180910390a15056fea265627a7a72305820e22b049858b33291cbe67eeaece0c5f64333e439d27032ea8337d08b1de18fe864736f6c634300050a0032`}, - []string{`[{"constant":false,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`}, - ` - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Initialize test accounts - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // deploy the test contract - _, _, contract, err := DeployOverload(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy contract: %v", err) - } - // Finish deploy. - sim.Commit() - - resCh, stopCh := make(chan uint64), make(chan struct{}) - - go func() { - barSink := make(chan *OverloadBar) - sub, _ := contract.WatchBar(nil, barSink) - defer sub.Unsubscribe() - - bar0Sink := make(chan *OverloadBar0) - sub0, _ := contract.WatchBar0(nil, bar0Sink) - defer sub0.Unsubscribe() - - for { - select { - case ev := <-barSink: - resCh <- ev.I.Uint64() - case ev := <-bar0Sink: - resCh <- ev.I.Uint64() + ev.J.Uint64() - case <-stopCh: - return - } - } - }() - contract.Foo(auth, big.NewInt(1), big.NewInt(2)) - sim.Commit() - select { - case n := <-resCh: - if n != 3 { - t.Fatalf("Invalid bar0 event") - } - case <-time.NewTimer(3 * time.Second).C: - t.Fatalf("Wait bar0 event timeout") - } - - contract.Foo0(auth, big.NewInt(1)) - sim.Commit() - select { - case n := <-resCh: - if n != 1 { - t.Fatalf("Invalid bar event") - } - case <-time.NewTimer(3 * time.Second).C: - t.Fatalf("Wait bar event timeout") - } - close(stopCh) - `, - nil, - nil, - nil, - nil, - }, - { - "IdentifierCollision", - ` - pragma solidity >=0.4.19 <0.6.0; - - contract IdentifierCollision { - uint public _myVar; - - function MyVar() public view returns (uint) { - return _myVar; - } - } - `, - []string{"60806040523480156100115760006000fd5b50610017565b60c3806100256000396000f3fe608060405234801560105760006000fd5b506004361060365760003560e01c806301ad4d8714603c5780634ef1f0ad146058576036565b60006000fd5b60426074565b6040518082815260200191505060405180910390f35b605e607d565b6040518082815260200191505060405180910390f35b60006000505481565b60006000600050549050608b565b9056fea265627a7a7231582067c8d84688b01c4754ba40a2a871cede94ea1f28b5981593ab2a45b46ac43af664736f6c634300050c0032"}, - []string{`[{"constant":true,"inputs":[],"name":"MyVar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_myVar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/core/types" - `, - ` - // Initialize test accounts - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - // Deploy registrar contract - sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - _, _, _, err := DeployIdentifierCollision(transactOpts, sim) - if err != nil { - t.Fatalf("failed to deploy contract: %v", err) - } - `, - nil, - nil, - map[string]string{"_myVar": "pubVar"}, // alias MyVar to PubVar - nil, - }, - { - "MultiContracts", - ` - pragma solidity ^0.5.11; - pragma experimental ABIEncoderV2; - - library ExternalLib { - struct SharedStruct{ - uint256 f1; - bytes32 f2; - } - } - - contract ContractOne { - function foo(ExternalLib.SharedStruct memory s) pure public { - // Do stuff - } - } - - contract ContractTwo { - function bar(ExternalLib.SharedStruct memory s) pure public { - // Do stuff - } - } - `, - []string{ - `60806040523480156100115760006000fd5b50610017565b6101b5806100266000396000f3fe60806040523480156100115760006000fd5b50600436106100305760003560e01c80639d8a8ba81461003657610030565b60006000fd5b610050600480360361004b91908101906100d1565b610052565b005b5b5056610171565b6000813590506100698161013d565b92915050565b6000604082840312156100825760006000fd5b61008c60406100fb565b9050600061009c848285016100bc565b60008301525060206100b08482850161005a565b60208301525092915050565b6000813590506100cb81610157565b92915050565b6000604082840312156100e45760006000fd5b60006100f28482850161006f565b91505092915050565b6000604051905081810181811067ffffffffffffffff8211171561011f5760006000fd5b8060405250919050565b6000819050919050565b6000819050919050565b61014681610129565b811415156101545760006000fd5b50565b61016081610133565b8114151561016e5760006000fd5b50565bfea365627a7a72315820749274eb7f6c01010d5322af4e1668b0a154409eb7968bd6cae5524c7ed669bb6c6578706572696d656e74616cf564736f6c634300050c0040`, - `60806040523480156100115760006000fd5b50610017565b6101b5806100266000396000f3fe60806040523480156100115760006000fd5b50600436106100305760003560e01c8063db8ba08c1461003657610030565b60006000fd5b610050600480360361004b91908101906100d1565b610052565b005b5b5056610171565b6000813590506100698161013d565b92915050565b6000604082840312156100825760006000fd5b61008c60406100fb565b9050600061009c848285016100bc565b60008301525060206100b08482850161005a565b60208301525092915050565b6000813590506100cb81610157565b92915050565b6000604082840312156100e45760006000fd5b60006100f28482850161006f565b91505092915050565b6000604051905081810181811067ffffffffffffffff8211171561011f5760006000fd5b8060405250919050565b6000819050919050565b6000819050919050565b61014681610129565b811415156101545760006000fd5b50565b61016081610133565b8114151561016e5760006000fd5b50565bfea365627a7a723158209bc28ee7ea97c131a13330d77ec73b4493b5c59c648352da81dd288b021192596c6578706572696d656e74616cf564736f6c634300050c0040`, - `606c6026600b82828239805160001a6073141515601857fe5b30600052607381538281f350fe73000000000000000000000000000000000000000030146080604052600436106023575b60006000fdfea365627a7a72315820518f0110144f5b3de95697d05e456a064656890d08e6f9cff47f3be710cc46a36c6578706572696d656e74616cf564736f6c634300050c0040`, - }, - []string{ - `[{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"f1","type":"uint256"},{"internalType":"bytes32","name":"f2","type":"bytes32"}],"internalType":"struct ExternalLib.SharedStruct","name":"s","type":"tuple"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"}]`, - `[{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"f1","type":"uint256"},{"internalType":"bytes32","name":"f2","type":"bytes32"}],"internalType":"struct ExternalLib.SharedStruct","name":"s","type":"tuple"}],"name":"bar","outputs":[],"payable":false,"stateMutability":"pure","type":"function"}]`, - `[]`, - }, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/core/types" - `, - ` - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - // Deploy registrar contract - sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - transactOpts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - _, _, c1, err := DeployContractOne(transactOpts, sim) - if err != nil { - t.Fatal("Failed to deploy contract") - } - sim.Commit() - err = c1.Foo(nil, ExternalLibSharedStruct{ - F1: big.NewInt(100), - F2: [32]byte{0x01, 0x02, 0x03}, - }) - if err != nil { - t.Fatal("Failed to invoke function") - } - _, _, c2, err := DeployContractTwo(transactOpts, sim) - if err != nil { - t.Fatal("Failed to deploy contract") - } - sim.Commit() - err = c2.Bar(nil, ExternalLibSharedStruct{ - F1: big.NewInt(100), - F2: [32]byte{0x01, 0x02, 0x03}, - }) - if err != nil { - t.Fatal("Failed to invoke function") - } - `, - nil, - nil, - nil, - []string{"ContractOne", "ContractTwo", "ExternalLib"}, - }, - // Test the existence of the free retrieval calls - { - `PureAndView`, - `pragma solidity >=0.6.0; - contract PureAndView { - function PureFunc() public pure returns (uint) { - return 42; - } - function ViewFunc() public view returns (uint) { - return block.number; - } - } - `, - []string{`608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806376b5686a146037578063bb38c66c146053575b600080fd5b603d606f565b6040518082815260200191505060405180910390f35b60596077565b6040518082815260200191505060405180910390f35b600043905090565b6000602a90509056fea2646970667358221220d158c2ab7fdfce366a7998ec79ab84edd43b9815630bbaede2c760ea77f29f7f64736f6c63430006000033`}, - []string{`[{"inputs": [],"name": "PureFunc","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "ViewFunc","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - // Generate a new random account and a funded simulator - key, _ := crypto.GenerateKey() - auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000) - defer sim.Close() - - // Deploy a tester contract and execute a structured call on it - _, _, pav, err := DeployPureAndView(auth, sim) - if err != nil { - t.Fatalf("Failed to deploy PureAndView contract: %v", err) - } - sim.Commit() - - // This test the existence of the free retriever call for view and pure functions - if num, err := pav.PureFunc(nil); err != nil { - t.Fatalf("Failed to call anonymous field retriever: %v", err) - } else if num.Cmp(big.NewInt(42)) != 0 { - t.Fatalf("Retrieved value mismatch: have %v, want %v", num, 42) - } - if num, err := pav.ViewFunc(nil); err != nil { - t.Fatalf("Failed to call anonymous field retriever: %v", err) - } else if num.Cmp(big.NewInt(1)) != 0 { - t.Fatalf("Retrieved value mismatch: have %v, want %v", num, 1) - } - `, - nil, - nil, - nil, - nil, - }, - // Test fallback separation introduced in v0.6.0 - { - `NewFallbacks`, - ` - pragma solidity >=0.6.0 <0.7.0; - - contract NewFallbacks { - event Fallback(bytes data); - fallback() external { - emit Fallback(msg.data); - } - - event Received(address addr, uint value); - receive() external payable { - emit Received(msg.sender, msg.value); - } - } - `, - []string{"6080604052348015600f57600080fd5b506101078061001f6000396000f3fe608060405236605f577f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258743334604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1005b348015606a57600080fd5b507f9043988963722edecc2099c75b0af0ff76af14ffca42ed6bce059a20a2a9f98660003660405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a100fea26469706673582212201f994dcfbc53bf610b19176f9a361eafa77b447fd9c796fa2c615dfd0aaf3b8b64736f6c634300060c0033"}, - []string{`[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Fallback","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Received","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]`}, - ` - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - `, - ` - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - sim := backends.NewSimulatedBackend(types.GenesisAlloc{addr: {Balance: big.NewInt(10000000000000000)}}, 1000000) - defer sim.Close() - - opts, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - _, _, c, err := DeployNewFallbacks(opts, sim) - if err != nil { - t.Fatalf("Failed to deploy contract: %v", err) - } - sim.Commit() - - // Test receive function - opts.Value = big.NewInt(100) - c.Receive(opts) - sim.Commit() - - var gotEvent bool - iter, _ := c.FilterReceived(nil) - defer iter.Close() - for iter.Next() { - if iter.Event.Addr != addr { - t.Fatal("Msg.sender mismatch") - } - if iter.Event.Value.Uint64() != 100 { - t.Fatal("Msg.value mismatch") - } - gotEvent = true - break - } - if !gotEvent { - t.Fatal("Expect to receive event emitted by receive") - } - - // Test fallback function - gotEvent = false - opts.Value = nil - calldata := []byte{0x01, 0x02, 0x03} - c.Fallback(opts, calldata) - sim.Commit() - - iter2, _ := c.FilterFallback(nil) - defer iter2.Close() - for iter2.Next() { - if !bytes.Equal(iter2.Event.Data, calldata) { - t.Fatal("calldata mismatch") - } - gotEvent = true - break - } - if !gotEvent { - t.Fatal("Expect to receive event emitted by fallback") - } - `, - nil, - nil, - nil, - nil, - }, - // Test resolving single struct argument - { - `NewSingleStructArgument`, - ` - pragma solidity ^0.8.0; - - contract NewSingleStructArgument { - struct MyStruct{ - uint256 a; - uint256 b; - } - event StructEvent(MyStruct s); - function TestEvent() public { - emit StructEvent(MyStruct({a: 1, b: 2})); - } - } - `, - []string{"608060405234801561001057600080fd5b50610113806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806324ec1d3f14602d575b600080fd5b60336035565b005b7fb4b2ff75e30cb4317eaae16dd8a187dd89978df17565104caa6c2797caae27d460405180604001604052806001815260200160028152506040516078919060ba565b60405180910390a1565b6040820160008201516096600085018260ad565b50602082015160a7602085018260ad565b50505050565b60b48160d3565b82525050565b600060408201905060cd60008301846082565b92915050565b600081905091905056fea26469706673582212208823628796125bf9941ce4eda18da1be3cf2931b231708ab848e1bd7151c0c9a64736f6c63430008070033"}, - []string{`[{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"indexed":false,"internalType":"struct Test.MyStruct","name":"s","type":"tuple"}],"name":"StructEvent","type":"event"},{"inputs":[],"name":"TestEvent","outputs":[],"stateMutability":"nonpayable","type":"function"}]`}, - ` - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - `, - ` - var ( - key, _ = crypto.GenerateKey() - user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil) - ) - defer sim.Close() - - _, _, d, err := DeployNewSingleStructArgument(user, sim) - if err != nil { - t.Fatalf("Failed to deploy contract %v", err) - } - sim.Commit() - - _, err = d.TestEvent(user) - if err != nil { - t.Fatalf("Failed to call contract %v", err) - } - sim.Commit() - - it, err := d.FilterStructEvent(nil) - if err != nil { - t.Fatalf("Failed to filter contract event %v", err) - } - var count int - for it.Next() { - if it.Event.S.A.Cmp(big.NewInt(1)) != 0 { - t.Fatal("Unexpected contract event") - } - if it.Event.S.B.Cmp(big.NewInt(2)) != 0 { - t.Fatal("Unexpected contract event") - } - count += 1 - } - if count != 1 { - t.Fatal("Unexpected contract event number") - } - `, - nil, - nil, - nil, - nil, - }, - // Test errors introduced in v0.8.4 - { - `NewErrors`, - ` - pragma solidity >0.8.4; - - contract NewErrors { - error MyError(uint256); - error MyError1(uint256); - error MyError2(uint256, uint256); - error MyError3(uint256 a, uint256 b, uint256 c); - function Error() public pure { - revert MyError3(1,2,3); - } - } - `, - []string{"0x6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063726c638214602d575b600080fd5b60336035565b005b60405163024876cd60e61b815260016004820152600260248201526003604482015260640160405180910390fdfea264697066735822122093f786a1bc60216540cd999fbb4a6109e0fef20abcff6e9107fb2817ca968f3c64736f6c63430008070033"}, - []string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"},{"inputs":[],"name":"Error","outputs":[],"stateMutability":"pure","type":"function"}]`}, - ` - "context" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - `, - ` - var ( - key, _ = crypto.GenerateKey() - user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil) - ) - defer sim.Close() - - _, tx, contract, err := DeployNewErrors(user, sim) - if err != nil { - t.Fatal(err) - } - sim.Commit() - _, err = bind.WaitDeployed(context.Background(), sim, tx) - if err != nil { - t.Error(err) - } - if err := contract.Error(new(bind.CallOpts)); err == nil { - t.Fatalf("expected contract to throw error") - } - // TODO (MariusVanDerWijden unpack error using abigen - // once that is implemented - `, - nil, - nil, - nil, - nil, - }, - { - name: `ConstructorWithStructParam`, - contract: ` - pragma solidity >=0.8.0 <0.9.0; - - contract ConstructorWithStructParam { - struct StructType { - uint256 field; - } - - constructor(StructType memory st) {} - } - `, - bytecode: []string{`0x608060405234801561001057600080fd5b506040516101c43803806101c48339818101604052810190610032919061014a565b50610177565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6100958261004c565b810181811067ffffffffffffffff821117156100b4576100b361005d565b5b80604052505050565b60006100c7610038565b90506100d3828261008c565b919050565b6000819050919050565b6100eb816100d8565b81146100f657600080fd5b50565b600081519050610108816100e2565b92915050565b60006020828403121561012457610123610047565b5b61012e60206100bd565b9050600061013e848285016100f9565b60008301525092915050565b6000602082840312156101605761015f610042565b5b600061016e8482850161010e565b91505092915050565b603f806101856000396000f3fe6080604052600080fdfea2646970667358221220cdffa667affecefac5561f65f4a4ba914204a8d4eb859d8cd426fb306e5c12a364736f6c634300080a0033`}, - abi: []string{`[{"inputs":[{"components":[{"internalType":"uint256","name":"field","type":"uint256"}],"internalType":"struct ConstructorWithStructParam.StructType","name":"st","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"}]`}, - imports: ` - "context" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - `, - tester: ` - var ( - key, _ = crypto.GenerateKey() - user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil) - ) - defer sim.Close() - - _, tx, _, err := DeployConstructorWithStructParam(user, sim, ConstructorWithStructParamStructType{Field: big.NewInt(42)}) - if err != nil { - t.Fatalf("DeployConstructorWithStructParam() got err %v; want nil err", err) - } - sim.Commit() - - if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil { - t.Logf("Deployment tx: %+v", tx) - t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err) - } - `, - }, - { - name: `NameConflict`, - contract: ` - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.22 <0.9.0; - contract oracle { - struct request { - bytes data; - bytes _data; - } - event log (int msg, int _msg); - function addRequest(request memory req) public pure {} - function getRequest() pure public returns (request memory) { - return request("", ""); - } - } - `, - bytecode: []string{"0x608060405234801561001057600080fd5b5061042b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063c2bb515f1461003b578063cce7b04814610059575b600080fd5b610043610075565b60405161005091906101af565b60405180910390f35b610073600480360381019061006e91906103ac565b6100b5565b005b61007d6100b8565b604051806040016040528060405180602001604052806000815250815260200160405180602001604052806000815250815250905090565b50565b604051806040016040528060608152602001606081525090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561010c5780820151818401526020810190506100f1565b8381111561011b576000848401525b50505050565b6000601f19601f8301169050919050565b600061013d826100d2565b61014781856100dd565b93506101578185602086016100ee565b61016081610121565b840191505092915050565b600060408301600083015184820360008601526101888282610132565b915050602083015184820360208601526101a28282610132565b9150508091505092915050565b600060208201905081810360008301526101c9818461016b565b905092915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61022282610121565b810181811067ffffffffffffffff82111715610241576102406101ea565b5b80604052505050565b60006102546101d1565b90506102608282610219565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff82111561028f5761028e6101ea565b5b61029882610121565b9050602081019050919050565b82818337600083830152505050565b60006102c76102c284610274565b61024a565b9050828152602081018484840111156102e3576102e261026f565b5b6102ee8482856102a5565b509392505050565b600082601f83011261030b5761030a61026a565b5b813561031b8482602086016102b4565b91505092915050565b60006040828403121561033a576103396101e5565b5b610344604061024a565b9050600082013567ffffffffffffffff81111561036457610363610265565b5b610370848285016102f6565b600083015250602082013567ffffffffffffffff81111561039457610393610265565b5b6103a0848285016102f6565b60208301525092915050565b6000602082840312156103c2576103c16101db565b5b600082013567ffffffffffffffff8111156103e0576103df6101e0565b5b6103ec84828501610324565b9150509291505056fea264697066735822122033bca1606af9b6aeba1673f98c52003cec19338539fb44b86690ce82c51483b564736f6c634300080e0033"}, - abi: []string{`[ { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "int256", "name": "msg", "type": "int256" }, { "indexed": false, "internalType": "int256", "name": "_msg", "type": "int256" } ], "name": "log", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "req", "type": "tuple" } ], "name": "addRequest", "outputs": [], "stateMutability": "pure", "type": "function" }, { "inputs": [], "name": "getRequest", "outputs": [ { "components": [ { "internalType": "bytes", "name": "data", "type": "bytes" }, { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "internalType": "struct oracle.request", "name": "", "type": "tuple" } ], "stateMutability": "pure", "type": "function" } ]`}, - imports: ` - "context" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - `, - tester: ` - var ( - key, _ = crypto.GenerateKey() - user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil) - ) - defer sim.Close() - - _, tx, _, err := DeployNameConflict(user, sim) - if err != nil { - t.Fatalf("DeployNameConflict() got err %v; want nil err", err) - } - sim.Commit() - - if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil { - t.Logf("Deployment tx: %+v", tx) - t.Errorf("bind.WaitDeployed(nil, %T, ) got err %v; want nil err", sim, err) - } - `, - }, - { - name: "RangeKeyword", - contract: ` - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.22 <0.9.0; - contract keywordcontract { - function functionWithKeywordParameter(range uint256) public pure {} - } - `, - bytecode: []string{"0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063527a119f14602d575b600080fd5b60436004803603810190603f9190605b565b6045565b005b50565b6000813590506055816092565b92915050565b600060208284031215606e57606d608d565b5b6000607a848285016048565b91505092915050565b6000819050919050565b600080fd5b6099816083565b811460a357600080fd5b5056fea2646970667358221220d4f4525e2615516394055d369fb17df41c359e5e962734f27fd683ea81fd9db164736f6c63430008070033"}, - abi: []string{`[{"inputs":[{"internalType":"uint256","name":"range","type":"uint256"}],"name":"functionWithKeywordParameter","outputs":[],"stateMutability":"pure","type":"function"}]`}, - imports: ` - "context" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - `, - tester: ` - var ( - key, _ = crypto.GenerateKey() - user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil) - ) - _, tx, _, err := DeployRangeKeyword(user, sim) - if err != nil { - t.Fatalf("error deploying contract: %v", err) - } - sim.Commit() - - if _, err = bind.WaitDeployed(context.Background(), sim, tx); err != nil { - t.Errorf("error deploying the contract: %v", err) - } - `, - }, { - name: "NumericMethodName", - contract: ` - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.22 <0.9.0; - - contract NumericMethodName { - event _1TestEvent(address _param); - function _1test() public pure {} - function __1test() public pure {} - function __2test() public pure {} - } - `, - bytecode: []string{"0x6080604052348015600f57600080fd5b5060958061001e6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80639d993132146041578063d02767c7146049578063ffa02795146051575b600080fd5b60476059565b005b604f605b565b005b6057605d565b005b565b565b56fea26469706673582212200382ca602dff96a7e2ba54657985e2b4ac423a56abe4a1f0667bc635c4d4371f64736f6c63430008110033"}, - abi: []string{`[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_param","type":"address"}],"name":"_1TestEvent","type":"event"},{"inputs":[],"name":"_1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__2test","outputs":[],"stateMutability":"pure","type":"function"}]`}, - imports: ` - "github.com/ethereum/go-ethereum/common" - `, - tester: ` - if b, err := NewNumericMethodName(common.Address{}, nil); b == nil || err != nil { - t.Fatalf("combined binding (%v) nil or error (%v) not nil", b, nil) - } -`, - }, -} - -// Tests that packages generated by the binder can be successfully compiled and -// the requested tester run against it. -func TestGolangBindings(t *testing.T) { - t.Parallel() - // Skip the test if no Go command can be found - gocmd := runtime.GOROOT() + "/bin/go" - if !common.FileExist(gocmd) { - t.Skip("go sdk not found for testing") - } - // Create a temporary workspace for the test suite - ws := t.TempDir() - - pkg := filepath.Join(ws, "bindtest") - if err := os.MkdirAll(pkg, 0700); err != nil { - t.Fatalf("failed to create package: %v", err) - } - // Generate the test suite for all the contracts - for i, tt := range bindTests { - t.Run(tt.name, func(t *testing.T) { - var types []string - if tt.types != nil { - types = tt.types - } else { - types = []string{tt.name} - } - // Generate the binding and create a Go source file in the workspace - bind, err := Bind(types, tt.abi, tt.bytecode, tt.fsigs, "bindtest", LangGo, tt.libs, tt.aliases) - if err != nil { - t.Fatalf("test %d: failed to generate binding: %v", i, err) - } - if err = os.WriteFile(filepath.Join(pkg, strings.ToLower(tt.name)+".go"), []byte(bind), 0600); err != nil { - t.Fatalf("test %d: failed to write binding: %v", i, err) - } - // Generate the test file with the injected test code - code := fmt.Sprintf(` - package bindtest - - import ( - "testing" - %s - ) - - func Test%s(t *testing.T) { - %s - } - `, tt.imports, tt.name, tt.tester) - if err := os.WriteFile(filepath.Join(pkg, strings.ToLower(tt.name)+"_test.go"), []byte(code), 0600); err != nil { - t.Fatalf("test %d: failed to write tests: %v", i, err) - } - }) - } - // Convert the package to go modules and use the current source for go-ethereum - moder := exec.Command(gocmd, "mod", "init", "bindtest") - moder.Dir = pkg - if out, err := moder.CombinedOutput(); err != nil { - t.Fatalf("failed to convert binding test to modules: %v\n%s", err, out) - } - pwd, _ := os.Getwd() - replacer := exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/ethereum/go-ethereum@v0.0.0", "-replace", "github.com/ethereum/go-ethereum="+filepath.Join(pwd, "..", "..", "..")) // Repo root - replacer.Dir = pkg - if out, err := replacer.CombinedOutput(); err != nil { - t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out) - } - tidier := exec.Command(gocmd, "mod", "tidy") - tidier.Dir = pkg - if out, err := tidier.CombinedOutput(); err != nil { - t.Fatalf("failed to tidy Go module file: %v\n%s", err, out) - } - // Test the entire package and report any failures - cmd := exec.Command(gocmd, "test", "-v", "-count", "1") - cmd.Dir = pkg - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run binding test: %v\n%s", err, out) - } -} diff --git a/builder/accounts/abi/bind/template.go b/builder/accounts/abi/bind/template.go deleted file mode 100644 index 95dc13cc1..000000000 --- a/builder/accounts/abi/bind/template.go +++ /dev/null @@ -1,571 +0,0 @@ -// Copyright 2016 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 bind - -import "github.com/ethereum/go-ethereum/accounts/abi" - -// tmplData is the data structure required to fill the binding template. -type tmplData struct { - Package string // Name of the package to place the generated file in - Contracts map[string]*tmplContract // List of contracts to generate into this file - Libraries map[string]string // Map the bytecode's link pattern to the library name - Structs map[string]*tmplStruct // Contract struct type definitions -} - -// tmplContract contains the data needed to generate an individual contract binding. -type tmplContract struct { - Type string // Type name of the main contract binding - InputABI string // JSON ABI used as the input to generate the binding from - InputBin string // Optional EVM bytecode used to generate deploy code from - FuncSigs map[string]string // Optional map: string signature -> 4-byte signature - Constructor abi.Method // Contract constructor for deploy parametrization - Calls map[string]*tmplMethod // Contract calls that only read state data - Transacts map[string]*tmplMethod // Contract calls that write state data - Fallback *tmplMethod // Additional special fallback function - Receive *tmplMethod // Additional special receive function - Events map[string]*tmplEvent // Contract events accessors - Libraries map[string]string // Same as tmplData, but filtered to only keep what the contract needs - Library bool // Indicator whether the contract is a library -} - -// tmplMethod is a wrapper around an abi.Method that contains a few preprocessed -// and cached data fields. -type tmplMethod struct { - Original abi.Method // Original method as parsed by the abi package - Normalized abi.Method // Normalized version of the parsed method (capitalized names, non-anonymous args/returns) - Structured bool // Whether the returns should be accumulated into a struct -} - -// tmplEvent is a wrapper around an abi.Event that contains a few preprocessed -// and cached data fields. -type tmplEvent struct { - Original abi.Event // Original event as parsed by the abi package - Normalized abi.Event // Normalized version of the parsed fields -} - -// tmplField is a wrapper around a struct field with binding language -// struct type definition and relative filed name. -type tmplField struct { - Type string // Field type representation depends on target binding language - Name string // Field name converted from the raw user-defined field name - SolKind abi.Type // Raw abi type information -} - -// tmplStruct is a wrapper around an abi.tuple and contains an auto-generated -// struct name. -type tmplStruct struct { - Name string // Auto-generated struct name(before solidity v0.5.11) or raw name. - Fields []*tmplField // Struct fields definition depends on the binding language. -} - -// tmplSource is language to template mapping containing all the supported -// programming languages the package can generate to. -var tmplSource = map[Lang]string{ - LangGo: tmplSourceGo, -} - -// tmplSourceGo is the Go source template that the generated Go contract binding -// is based on. -const tmplSourceGo = ` -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package {{.Package}} - -import ( - "math/big" - "strings" - "errors" - - 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 -) - -{{$structs := .Structs}} -{{range $structs}} - // {{.Name}} is an auto generated low-level Go binding around an user-defined struct. - type {{.Name}} struct { - {{range $field := .Fields}} - {{$field.Name}} {{$field.Type}}{{end}} - } -{{end}} - -{{range $contract := .Contracts}} - // {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract. - var {{.Type}}MetaData = &bind.MetaData{ - ABI: "{{.InputABI}}", - {{if $contract.FuncSigs -}} - Sigs: map[string]string{ - {{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}", - {{end}} - }, - {{end -}} - {{if .InputBin -}} - Bin: "0x{{.InputBin}}", - {{end}} - } - // {{.Type}}ABI is the input ABI used to generate the binding from. - // Deprecated: Use {{.Type}}MetaData.ABI instead. - var {{.Type}}ABI = {{.Type}}MetaData.ABI - - {{if $contract.FuncSigs}} - // Deprecated: Use {{.Type}}MetaData.Sigs instead. - // {{.Type}}FuncSigs maps the 4-byte function signature to its string representation. - var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs - {{end}} - - {{if .InputBin}} - // {{.Type}}Bin is the compiled bytecode used for deploying new contracts. - // Deprecated: Use {{.Type}}MetaData.Bin instead. - var {{.Type}}Bin = {{.Type}}MetaData.Bin - - // Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it. - func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) { - parsed, err := {{.Type}}MetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - {{range $pattern, $name := .Libraries}} - {{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend) - {{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:]) - {{end}} - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}}) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil - } - {{end}} - - // {{.Type}} is an auto generated Go binding around an Ethereum contract. - type {{.Type}} struct { - {{.Type}}Caller // Read-only binding to the contract - {{.Type}}Transactor // Write-only binding to the contract - {{.Type}}Filterer // Log filterer for contract events - } - - // {{.Type}}Caller is an auto generated read-only Go binding around an Ethereum contract. - type {{.Type}}Caller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls - } - - // {{.Type}}Transactor is an auto generated write-only Go binding around an Ethereum contract. - type {{.Type}}Transactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls - } - - // {{.Type}}Filterer is an auto generated log filtering Go binding around an Ethereum contract events. - type {{.Type}}Filterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls - } - - // {{.Type}}Session is an auto generated Go binding around an Ethereum contract, - // with pre-set call and transact options. - type {{.Type}}Session struct { - Contract *{{.Type}} // 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 - } - - // {{.Type}}CallerSession is an auto generated read-only Go binding around an Ethereum contract, - // with pre-set call options. - type {{.Type}}CallerSession struct { - Contract *{{.Type}}Caller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - } - - // {{.Type}}TransactorSession is an auto generated write-only Go binding around an Ethereum contract, - // with pre-set transact options. - type {{.Type}}TransactorSession struct { - Contract *{{.Type}}Transactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session - } - - // {{.Type}}Raw is an auto generated low-level Go binding around an Ethereum contract. - type {{.Type}}Raw struct { - Contract *{{.Type}} // Generic contract binding to access the raw methods on - } - - // {{.Type}}CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. - type {{.Type}}CallerRaw struct { - Contract *{{.Type}}Caller // Generic read-only contract binding to access the raw methods on - } - - // {{.Type}}TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. - type {{.Type}}TransactorRaw struct { - Contract *{{.Type}}Transactor // Generic write-only contract binding to access the raw methods on - } - - // New{{.Type}} creates a new instance of {{.Type}}, bound to a specific deployed contract. - func New{{.Type}}(address common.Address, backend bind.ContractBackend) (*{{.Type}}, error) { - contract, err := bind{{.Type}}(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &{{.Type}}{ {{.Type}}Caller: {{.Type}}Caller{contract: contract}, {{.Type}}Transactor: {{.Type}}Transactor{contract: contract}, {{.Type}}Filterer: {{.Type}}Filterer{contract: contract} }, nil - } - - // New{{.Type}}Caller creates a new read-only instance of {{.Type}}, bound to a specific deployed contract. - func New{{.Type}}Caller(address common.Address, caller bind.ContractCaller) (*{{.Type}}Caller, error) { - contract, err := bind{{.Type}}(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &{{.Type}}Caller{contract: contract}, nil - } - - // New{{.Type}}Transactor creates a new write-only instance of {{.Type}}, bound to a specific deployed contract. - func New{{.Type}}Transactor(address common.Address, transactor bind.ContractTransactor) (*{{.Type}}Transactor, error) { - contract, err := bind{{.Type}}(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &{{.Type}}Transactor{contract: contract}, nil - } - - // New{{.Type}}Filterer creates a new log filterer instance of {{.Type}}, bound to a specific deployed contract. - func New{{.Type}}Filterer(address common.Address, filterer bind.ContractFilterer) (*{{.Type}}Filterer, error) { - contract, err := bind{{.Type}}(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &{{.Type}}Filterer{contract: contract}, nil - } - - // bind{{.Type}} binds a generic wrapper to an already deployed contract. - func bind{{.Type}}(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := {{.Type}}MetaData.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 (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.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 (_{{$contract.Type}} *{{$contract.Type}}Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.contract.Transfer(opts) - } - - // Transact invokes the (paid) contract method with params as input values. - func (_{{$contract.Type}} *{{$contract.Type}}Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.{{$contract.Type}}Transactor.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 (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _{{$contract.Type}}.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 (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.contract.Transfer(opts) - } - - // Transact invokes the (paid) contract method with params as input values. - func (_{{$contract.Type}} *{{$contract.Type}}TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.contract.Transact(opts, method, params...) - } - - {{range .Calls}} - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) { - var out []interface{} - err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}}) - {{if .Structured}} - outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} }) - if err != nil { - return *outstruct, err - } - {{range $i, $t := .Normalized.Outputs}} - outstruct.{{.Name}} = *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}} - - return *outstruct, err - {{else}} - if err != nil { - return {{range $i, $_ := .Normalized.Outputs}}*new({{bindtype .Type $structs}}), {{end}} err - } - {{range $i, $t := .Normalized.Outputs}} - out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}} - - return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err - {{end}} - } - - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) { - return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}}) - } - - // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}CallerSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} }, {{else}} {{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}} {{end}} error) { - return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.CallOpts {{range .Normalized.Inputs}}, {{.Name}}{{end}}) - } - {{end}} - - {{range .Transacts}} - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Transactor) {{.Normalized.Name}}(opts *bind.TransactOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { - return _{{$contract.Type}}.contract.Transact(opts, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}}) - } - - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}}) - } - - // {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) {{.Normalized.Name}}({{range $i, $_ := .Normalized.Inputs}}{{if ne $i 0}},{{end}} {{.Name}} {{bindtype .Type $structs}} {{end}}) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.{{.Normalized.Name}}(&_{{$contract.Type}}.TransactOpts {{range $i, $_ := .Normalized.Inputs}}, {{.Name}}{{end}}) - } - {{end}} - - {{if .Fallback}} - // Fallback is a paid mutator transaction binding the contract fallback function. - // - // Solidity: {{.Fallback.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { - return _{{$contract.Type}}.contract.RawTransact(opts, calldata) - } - - // Fallback is a paid mutator transaction binding the contract fallback function. - // - // Solidity: {{.Fallback.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) Fallback(calldata []byte) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata) - } - - // Fallback is a paid mutator transaction binding the contract fallback function. - // - // Solidity: {{.Fallback.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.Fallback(&_{{$contract.Type}}.TransactOpts, calldata) - } - {{end}} - - {{if .Receive}} - // Receive is a paid mutator transaction binding the contract receive function. - // - // Solidity: {{.Receive.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { - return _{{$contract.Type}}.contract.RawTransact(opts, nil) // calldata is disallowed for receive function - } - - // Receive is a paid mutator transaction binding the contract receive function. - // - // Solidity: {{.Receive.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Session) Receive() (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts) - } - - // Receive is a paid mutator transaction binding the contract receive function. - // - // Solidity: {{.Receive.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}TransactorSession) Receive() (*types.Transaction, error) { - return _{{$contract.Type}}.Contract.Receive(&_{{$contract.Type}}.TransactOpts) - } - {{end}} - - {{range .Events}} - // {{$contract.Type}}{{.Normalized.Name}}Iterator is returned from Filter{{.Normalized.Name}} and is used to iterate over the raw logs and unpacked data for {{.Normalized.Name}} events raised by the {{$contract.Type}} contract. - type {{$contract.Type}}{{.Normalized.Name}}Iterator struct { - Event *{{$contract.Type}}{{.Normalized.Name}} // 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 *{{$contract.Type}}{{.Normalized.Name}}Iterator) 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({{$contract.Type}}{{.Normalized.Name}}) - 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({{$contract.Type}}{{.Normalized.Name}}) - 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 *{{$contract.Type}}{{.Normalized.Name}}Iterator) Error() error { - return it.fail - } - // Close terminates the iteration process, releasing any pending underlying - // resources. - func (it *{{$contract.Type}}{{.Normalized.Name}}Iterator) Close() error { - it.sub.Unsubscribe() - return nil - } - - // {{$contract.Type}}{{.Normalized.Name}} represents a {{.Normalized.Name}} event raised by the {{$contract.Type}} contract. - type {{$contract.Type}}{{.Normalized.Name}} struct { {{range .Normalized.Inputs}} - {{capitalise .Name}} {{if .Indexed}}{{bindtopictype .Type $structs}}{{else}}{{bindtype .Type $structs}}{{end}}; {{end}} - Raw types.Log // Blockchain specific contextual infos - } - - // Filter{{.Normalized.Name}} is a free log retrieval operation binding the contract event 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Filter{{.Normalized.Name}}(opts *bind.FilterOpts{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (*{{$contract.Type}}{{.Normalized.Name}}Iterator, error) { - {{range .Normalized.Inputs}} - {{if .Indexed}}var {{.Name}}Rule []interface{} - for _, {{.Name}}Item := range {{.Name}} { - {{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item) - }{{end}}{{end}} - - logs, sub, err := _{{$contract.Type}}.contract.FilterLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}}) - if err != nil { - return nil, err - } - return &{{$contract.Type}}{{.Normalized.Name}}Iterator{contract: _{{$contract.Type}}.contract, event: "{{.Original.Name}}", logs: logs, sub: sub}, nil - } - - // Watch{{.Normalized.Name}} is a free log subscription operation binding the contract event 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Watch{{.Normalized.Name}}(opts *bind.WatchOpts, sink chan<- *{{$contract.Type}}{{.Normalized.Name}}{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}} []{{bindtype .Type $structs}}{{end}}{{end}}) (event.Subscription, error) { - {{range .Normalized.Inputs}} - {{if .Indexed}}var {{.Name}}Rule []interface{} - for _, {{.Name}}Item := range {{.Name}} { - {{.Name}}Rule = append({{.Name}}Rule, {{.Name}}Item) - }{{end}}{{end}} - - logs, sub, err := _{{$contract.Type}}.contract.WatchLogs(opts, "{{.Original.Name}}"{{range .Normalized.Inputs}}{{if .Indexed}}, {{.Name}}Rule{{end}}{{end}}) - 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({{$contract.Type}}{{.Normalized.Name}}) - if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", 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 - } - - // Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}. - // - // Solidity: {{.Original.String}} - func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) { - event := new({{$contract.Type}}{{.Normalized.Name}}) - if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil - } - - {{end}} -{{end}} -` diff --git a/builder/accounts/abi/bind/util.go b/builder/accounts/abi/bind/util.go deleted file mode 100644 index b931fbb04..000000000 --- a/builder/accounts/abi/bind/util.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2016 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 bind - -import ( - "context" - "errors" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -// WaitMined waits for tx to be mined on the blockchain. -// It stops waiting when the context is canceled. -func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) { - queryTicker := time.NewTicker(time.Second) - defer queryTicker.Stop() - - logger := log.New("hash", tx.Hash()) - for { - receipt, err := b.TransactionReceipt(ctx, tx.Hash()) - if err == nil { - return receipt, nil - } - - if errors.Is(err, ethereum.NotFound) { - logger.Trace("Transaction not yet mined") - } else { - logger.Trace("Receipt retrieval failed", "err", err) - } - - // Wait for the next round. - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-queryTicker.C: - } - } -} - -// WaitDeployed waits for a contract deployment transaction and returns the on-chain -// contract address when it is mined. It stops waiting when ctx is canceled. -func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) { - if tx.To() != nil { - return common.Address{}, errors.New("tx is not contract creation") - } - receipt, err := WaitMined(ctx, b, tx) - if err != nil { - return common.Address{}, err - } - if receipt.ContractAddress == (common.Address{}) { - return common.Address{}, errors.New("zero address") - } - // Check that code has indeed been deployed at the address. - // This matters on pre-Homestead chains: OOG in the constructor - // could leave an empty account behind. - code, err := b.CodeAt(ctx, receipt.ContractAddress, nil) - if err == nil && len(code) == 0 { - err = ErrNoCodeAfterDeploy - } - return receipt.ContractAddress, err -} diff --git a/builder/accounts/abi/bind/util_test.go b/builder/accounts/abi/bind/util_test.go deleted file mode 100644 index 592465f2a..000000000 --- a/builder/accounts/abi/bind/util_test.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2016 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 bind_test - -import ( - "context" - "errors" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/ethereum/go-ethereum/params" -) - -var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - -var waitDeployedTests = map[string]struct { - code string - gas uint64 - wantAddress common.Address - wantErr error -}{ - "successful deploy": { - code: `6060604052600a8060106000396000f360606040526008565b00`, - gas: 3000000, - wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"), - }, - "empty code": { - code: ``, - gas: 300000, - wantErr: bind.ErrNoCodeAfterDeploy, - wantAddress: common.HexToAddress("0x3a220f351252089d385b29beca14e27f204c296a"), - }, -} - -func TestWaitDeployed(t *testing.T) { - t.Parallel() - for name, test := range waitDeployedTests { - backend := simulated.NewBackend( - types.GenesisAlloc{ - crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)}, - }, - ) - defer backend.Close() - - // Create the transaction - head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough - gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei)) - - tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code)) - tx, _ = types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey) - - // Wait for it to get mined in the background. - var ( - err error - address common.Address - mined = make(chan struct{}) - ctx = context.Background() - ) - go func() { - address, err = bind.WaitDeployed(ctx, backend.Client(), tx) - close(mined) - }() - - // Send and mine the transaction. - backend.Client().SendTransaction(ctx, tx) - backend.Commit() - - select { - case <-mined: - if err != test.wantErr { - t.Errorf("test %q: error mismatch: want %q, got %q", name, test.wantErr, err) - } - if address != test.wantAddress { - t.Errorf("test %q: unexpected contract address %s", name, address.Hex()) - } - case <-time.After(2 * time.Second): - t.Errorf("test %q: timeout", name) - } - } -} - -func TestWaitDeployedCornerCases(t *testing.T) { - backend := simulated.NewBackend( - types.GenesisAlloc{ - crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)}, - }, - ) - defer backend.Close() - - head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough - gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) - - // Create a transaction to an account. - code := "6060604052600a8060106000396000f360606040526008565b00" - tx := types.NewTransaction(0, common.HexToAddress("0x01"), big.NewInt(0), 3000000, gasPrice, common.FromHex(code)) - tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - backend.Client().SendTransaction(ctx, tx) - backend.Commit() - notContractCreation := errors.New("tx is not contract creation") - if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != notContractCreation.Error() { - t.Errorf("error mismatch: want %q, got %q, ", notContractCreation, err) - } - - // Create a transaction that is not mined. - tx = types.NewContractCreation(1, big.NewInt(0), 3000000, gasPrice, common.FromHex(code)) - tx, _ = types.SignTx(tx, types.LatestSigner(params.AllDevChainProtocolChanges), testKey) - - go func() { - contextCanceled := errors.New("context canceled") - if _, err := bind.WaitDeployed(ctx, backend.Client(), tx); err.Error() != contextCanceled.Error() { - t.Errorf("error mismatch: want %q, got %q, ", contextCanceled, err) - } - }() - - backend.Client().SendTransaction(ctx, tx) - cancel() -} diff --git a/builder/accounts/abi/doc.go b/builder/accounts/abi/doc.go deleted file mode 100644 index 824206858..000000000 --- a/builder/accounts/abi/doc.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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 abi implements the Ethereum ABI (Application Binary -// Interface). -// -// The Ethereum ABI is strongly typed, known at compile time -// and static. This ABI will handle basic type casting; unsigned -// to signed and visa versa. It does not handle slice casting such -// as unsigned slice to signed slice. Bit size type casting is also -// handled. ints with a bit size of 32 will be properly cast to int256, -// etc. -package abi diff --git a/builder/accounts/abi/error.go b/builder/accounts/abi/error.go deleted file mode 100644 index 8e50112ec..000000000 --- a/builder/accounts/abi/error.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "bytes" - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -type Error struct { - Name string - Inputs Arguments - str string - - // Sig contains the string signature according to the ABI spec. - // e.g. error foo(uint32 a, int b) = "foo(uint32,int256)" - // Please note that "int" is substitute for its canonical representation "int256" - Sig string - - // ID returns the canonical representation of the error's signature used by the - // abi definition to identify event names and types. - ID common.Hash -} - -func NewError(name string, inputs Arguments) Error { - // sanitize inputs to remove inputs without names - // and precompute string and sig representation. - names := make([]string, len(inputs)) - types := make([]string, len(inputs)) - for i, input := range inputs { - if input.Name == "" { - inputs[i] = Argument{ - Name: fmt.Sprintf("arg%d", i), - Indexed: input.Indexed, - Type: input.Type, - } - } else { - inputs[i] = input - } - // string representation - names[i] = fmt.Sprintf("%v %v", input.Type, inputs[i].Name) - if input.Indexed { - names[i] = fmt.Sprintf("%v indexed %v", input.Type, inputs[i].Name) - } - // sig representation - types[i] = input.Type.String() - } - - str := fmt.Sprintf("error %v(%v)", name, strings.Join(names, ", ")) - sig := fmt.Sprintf("%v(%v)", name, strings.Join(types, ",")) - id := common.BytesToHash(crypto.Keccak256([]byte(sig))) - - return Error{ - Name: name, - Inputs: inputs, - str: str, - Sig: sig, - ID: id, - } -} - -func (e Error) String() string { - return e.str -} - -func (e *Error) Unpack(data []byte) (interface{}, error) { - if len(data) < 4 { - return "", fmt.Errorf("insufficient data for unpacking: have %d, want at least 4", len(data)) - } - if !bytes.Equal(data[:4], e.ID[:4]) { - return "", fmt.Errorf("invalid identifier, have %#x want %#x", data[:4], e.ID[:4]) - } - return e.Inputs.Unpack(data[4:]) -} diff --git a/builder/accounts/abi/error_handling.go b/builder/accounts/abi/error_handling.go deleted file mode 100644 index c106e9ac4..000000000 --- a/builder/accounts/abi/error_handling.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "errors" - "fmt" - "reflect" -) - -var ( - errBadBool = errors.New("abi: improperly encoded boolean value") - errBadUint8 = errors.New("abi: improperly encoded uint8 value") - errBadUint16 = errors.New("abi: improperly encoded uint16 value") - errBadUint32 = errors.New("abi: improperly encoded uint32 value") - errBadUint64 = errors.New("abi: improperly encoded uint64 value") - errBadInt8 = errors.New("abi: improperly encoded int8 value") - errBadInt16 = errors.New("abi: improperly encoded int16 value") - errBadInt32 = errors.New("abi: improperly encoded int32 value") - errBadInt64 = errors.New("abi: improperly encoded int64 value") -) - -// formatSliceString formats the reflection kind with the given slice size -// and returns a formatted string representation. -func formatSliceString(kind reflect.Kind, sliceSize int) string { - if sliceSize == -1 { - return fmt.Sprintf("[]%v", kind) - } - return fmt.Sprintf("[%d]%v", sliceSize, kind) -} - -// sliceTypeCheck checks that the given slice can by assigned to the reflection -// type in t. -func sliceTypeCheck(t Type, val reflect.Value) error { - if val.Kind() != reflect.Slice && val.Kind() != reflect.Array { - return typeErr(formatSliceString(t.GetType().Kind(), t.Size), val.Type()) - } - - if t.T == ArrayTy && val.Len() != t.Size { - return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), formatSliceString(val.Type().Elem().Kind(), val.Len())) - } - - if t.Elem.T == SliceTy || t.Elem.T == ArrayTy { - if val.Len() > 0 { - return sliceTypeCheck(*t.Elem, val.Index(0)) - } - } - - if val.Type().Elem().Kind() != t.Elem.GetType().Kind() { - return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type()) - } - return nil -} - -// typeCheck checks that the given reflection value can be assigned to the reflection -// type in t. -func typeCheck(t Type, value reflect.Value) error { - if t.T == SliceTy || t.T == ArrayTy { - return sliceTypeCheck(t, value) - } - - // Check base type validity. Element types will be checked later on. - if t.GetType().Kind() != value.Kind() { - return typeErr(t.GetType().Kind(), value.Kind()) - } else if t.T == FixedBytesTy && t.Size != value.Len() { - return typeErr(t.GetType(), value.Type()) - } else { - return nil - } -} - -// typeErr returns a formatted type casting error. -func typeErr(expected, got interface{}) error { - return fmt.Errorf("abi: cannot use %v as type %v as argument", got, expected) -} diff --git a/builder/accounts/abi/event.go b/builder/accounts/abi/event.go deleted file mode 100644 index f9457b86a..000000000 --- a/builder/accounts/abi/event.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -// Event is an event potentially triggered by the EVM's LOG mechanism. The Event -// holds type information (inputs) about the yielded output. Anonymous events -// don't get the signature canonical representation as the first LOG topic. -type Event struct { - // Name is the event name used for internal representation. It's derived from - // the raw name and a suffix will be added in the case of event overloading. - // - // e.g. - // These are two events that have the same name: - // * foo(int,int) - // * foo(uint,uint) - // The event name of the first one will be resolved as foo while the second one - // will be resolved as foo0. - Name string - - // RawName is the raw event name parsed from ABI. - RawName string - Anonymous bool - Inputs Arguments - str string - - // Sig contains the string signature according to the ABI spec. - // e.g. event foo(uint32 a, int b) = "foo(uint32,int256)" - // Please note that "int" is substitute for its canonical representation "int256" - Sig string - - // ID returns the canonical representation of the event's signature used by the - // abi definition to identify event names and types. - ID common.Hash -} - -// NewEvent creates a new Event. -// It sanitizes the input arguments to remove unnamed arguments. -// It also precomputes the id, signature and string representation -// of the event. -func NewEvent(name, rawName string, anonymous bool, inputs Arguments) Event { - // sanitize inputs to remove inputs without names - // and precompute string and sig representation. - names := make([]string, len(inputs)) - types := make([]string, len(inputs)) - for i, input := range inputs { - if input.Name == "" { - inputs[i] = Argument{ - Name: fmt.Sprintf("arg%d", i), - Indexed: input.Indexed, - Type: input.Type, - } - } else { - inputs[i] = input - } - // string representation - names[i] = fmt.Sprintf("%v %v", input.Type, inputs[i].Name) - if input.Indexed { - names[i] = fmt.Sprintf("%v indexed %v", input.Type, inputs[i].Name) - } - // sig representation - types[i] = input.Type.String() - } - - str := fmt.Sprintf("event %v(%v)", rawName, strings.Join(names, ", ")) - sig := fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ",")) - id := common.BytesToHash(crypto.Keccak256([]byte(sig))) - - return Event{ - Name: name, - RawName: rawName, - Anonymous: anonymous, - Inputs: inputs, - str: str, - Sig: sig, - ID: id, - } -} - -func (e Event) String() string { - return e.str -} diff --git a/builder/accounts/abi/event_test.go b/builder/accounts/abi/event_test.go deleted file mode 100644 index fffe28ea6..000000000 --- a/builder/accounts/abi/event_test.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "math/big" - "reflect" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var jsonEventTransfer = []byte(`{ - "anonymous": false, - "inputs": [ - { - "indexed": true, "name": "from", "type": "address" - }, { - "indexed": true, "name": "to", "type": "address" - }, { - "indexed": false, "name": "value", "type": "uint256" - }], - "name": "Transfer", - "type": "event" -}`) - -var jsonEventPledge = []byte(`{ - "anonymous": false, - "inputs": [{ - "indexed": false, "name": "who", "type": "address" - }, { - "indexed": false, "name": "wad", "type": "uint128" - }, { - "indexed": false, "name": "currency", "type": "bytes3" - }], - "name": "Pledge", - "type": "event" -}`) - -var jsonEventMixedCase = []byte(`{ - "anonymous": false, - "inputs": [{ - "indexed": false, "name": "value", "type": "uint256" - }, { - "indexed": false, "name": "_value", "type": "uint256" - }, { - "indexed": false, "name": "Value", "type": "uint256" - }], - "name": "MixedCase", - "type": "event" - }`) - -// 1000000 -var transferData1 = "00000000000000000000000000000000000000000000000000000000000f4240" - -// "0x00Ce0d46d924CC8437c806721496599FC3FFA268", 2218516807680, "usd" -var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa2680000000000000000000000000000000000000000000000000000020489e800007573640000000000000000000000000000000000000000000000000000000000" - -// 1000000,2218516807680,1000001 -var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241" - -func TestEventId(t *testing.T) { - t.Parallel() - var table = []struct { - definition string - expectations map[string]common.Hash - }{ - { - definition: `[ - { "type" : "event", "name" : "Balance", "inputs": [{ "name" : "in", "type": "uint256" }] }, - { "type" : "event", "name" : "Check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] } - ]`, - expectations: map[string]common.Hash{ - "Balance": crypto.Keccak256Hash([]byte("Balance(uint256)")), - "Check": crypto.Keccak256Hash([]byte("Check(address,uint256)")), - }, - }, - } - - for _, test := range table { - abi, err := JSON(strings.NewReader(test.definition)) - if err != nil { - t.Fatal(err) - } - - for name, event := range abi.Events { - if event.ID != test.expectations[name] { - t.Errorf("expected id to be %x, got %x", test.expectations[name], event.ID) - } - } - } -} - -func TestEventString(t *testing.T) { - t.Parallel() - var table = []struct { - definition string - expectations map[string]string - }{ - { - definition: `[ - { "type" : "event", "name" : "Balance", "inputs": [{ "name" : "in", "type": "uint256" }] }, - { "type" : "event", "name" : "Check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] }, - { "type" : "event", "name" : "Transfer", "inputs": [{ "name": "from", "type": "address", "indexed": true }, { "name": "to", "type": "address", "indexed": true }, { "name": "value", "type": "uint256" }] } - ]`, - expectations: map[string]string{ - "Balance": "event Balance(uint256 in)", - "Check": "event Check(address t, uint256 b)", - "Transfer": "event Transfer(address indexed from, address indexed to, uint256 value)", - }, - }, - } - - for _, test := range table { - abi, err := JSON(strings.NewReader(test.definition)) - if err != nil { - t.Fatal(err) - } - - for name, event := range abi.Events { - if event.String() != test.expectations[name] { - t.Errorf("expected string to be %s, got %s", test.expectations[name], event.String()) - } - } - } -} - -// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array. -func TestEventMultiValueWithArrayUnpack(t *testing.T) { - t.Parallel() - definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` - abi, err := JSON(strings.NewReader(definition)) - require.NoError(t, err) - var b bytes.Buffer - var i uint8 = 1 - for ; i <= 3; i++ { - b.Write(packNum(reflect.ValueOf(i))) - } - unpacked, err := abi.Unpack("test", b.Bytes()) - require.NoError(t, err) - require.Equal(t, [2]uint8{1, 2}, unpacked[0]) - require.Equal(t, uint8(3), unpacked[1]) -} - -func TestEventTupleUnpack(t *testing.T) { - t.Parallel() - type EventTransfer struct { - Value *big.Int - } - - type EventTransferWithTag struct { - // this is valid because `value` is not exportable, - // so value is only unmarshalled into `Value1`. - value *big.Int //lint:ignore U1000 unused field is part of test - Value1 *big.Int `abi:"value"` - } - - type BadEventTransferWithSameFieldAndTag struct { - Value *big.Int - Value1 *big.Int `abi:"value"` - } - - type BadEventTransferWithDuplicatedTag struct { - Value1 *big.Int `abi:"value"` - Value2 *big.Int `abi:"value"` - } - - type BadEventTransferWithEmptyTag struct { - Value *big.Int `abi:""` - } - - type EventPledge struct { - Who common.Address - Wad *big.Int - Currency [3]byte - } - - type BadEventPledge struct { - Who string - Wad int - Currency [3]byte - } - - type EventMixedCase struct { - Value1 *big.Int `abi:"value"` - Value2 *big.Int `abi:"_value"` - Value3 *big.Int `abi:"Value"` - } - - bigint := new(big.Int) - bigintExpected := big.NewInt(1000000) - bigintExpected2 := big.NewInt(2218516807680) - bigintExpected3 := big.NewInt(1000001) - addr := common.HexToAddress("0x00Ce0d46d924CC8437c806721496599FC3FFA268") - var testCases = []struct { - data string - dest interface{} - expected interface{} - jsonLog []byte - error string - name string - }{{ - transferData1, - &EventTransfer{}, - &EventTransfer{Value: bigintExpected}, - jsonEventTransfer, - "", - "Can unpack ERC20 Transfer event into structure", - }, { - transferData1, - &[]interface{}{&bigint}, - &[]interface{}{&bigintExpected}, - jsonEventTransfer, - "", - "Can unpack ERC20 Transfer event into slice", - }, { - transferData1, - &EventTransferWithTag{}, - &EventTransferWithTag{Value1: bigintExpected}, - jsonEventTransfer, - "", - "Can unpack ERC20 Transfer event into structure with abi: tag", - }, { - transferData1, - &BadEventTransferWithDuplicatedTag{}, - &BadEventTransferWithDuplicatedTag{}, - jsonEventTransfer, - "struct: abi tag in 'Value2' already mapped", - "Can not unpack ERC20 Transfer event with duplicated abi tag", - }, { - transferData1, - &BadEventTransferWithSameFieldAndTag{}, - &BadEventTransferWithSameFieldAndTag{}, - jsonEventTransfer, - "abi: multiple variables maps to the same abi field 'value'", - "Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable", - }, { - transferData1, - &BadEventTransferWithEmptyTag{}, - &BadEventTransferWithEmptyTag{}, - jsonEventTransfer, - "struct: abi tag in 'Value' is empty", - "Can not unpack ERC20 Transfer event with an empty tag", - }, { - pledgeData1, - &EventPledge{}, - &EventPledge{ - addr, - bigintExpected2, - [3]byte{'u', 's', 'd'}}, - jsonEventPledge, - "", - "Can unpack Pledge event into structure", - }, { - pledgeData1, - &[]interface{}{&common.Address{}, &bigint, &[3]byte{}}, - &[]interface{}{ - &addr, - &bigintExpected2, - &[3]byte{'u', 's', 'd'}}, - jsonEventPledge, - "", - "Can unpack Pledge event into slice", - }, { - pledgeData1, - &[3]interface{}{&common.Address{}, &bigint, &[3]byte{}}, - &[3]interface{}{ - &addr, - &bigintExpected2, - &[3]byte{'u', 's', 'd'}}, - jsonEventPledge, - "", - "Can unpack Pledge event into an array", - }, { - pledgeData1, - &[]interface{}{new(int), 0, 0}, - &[]interface{}{}, - jsonEventPledge, - "abi: cannot unmarshal common.Address in to int", - "Can not unpack Pledge event into slice with wrong types", - }, { - pledgeData1, - &BadEventPledge{}, - &BadEventPledge{}, - jsonEventPledge, - "abi: cannot unmarshal common.Address in to string", - "Can not unpack Pledge event into struct with wrong filed types", - }, { - pledgeData1, - &[]interface{}{common.Address{}, new(big.Int)}, - &[]interface{}{}, - jsonEventPledge, - "abi: insufficient number of arguments for unpack, want 3, got 2", - "Can not unpack Pledge event into too short slice", - }, { - pledgeData1, - new(map[string]interface{}), - &[]interface{}{}, - jsonEventPledge, - "abi:[2] cannot unmarshal tuple in to map[string]interface {}", - "Can not unpack Pledge event into map", - }, { - mixedCaseData1, - &EventMixedCase{}, - &EventMixedCase{Value1: bigintExpected, Value2: bigintExpected2, Value3: bigintExpected3}, - jsonEventMixedCase, - "", - "Can unpack abi variables with mixed case", - }} - - for _, tc := range testCases { - assert := assert.New(t) - tc := tc - t.Run(tc.name, func(t *testing.T) { - err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert) - if tc.error == "" { - assert.Nil(err, "Should be able to unpack event data.") - assert.Equal(tc.expected, tc.dest, tc.name) - } else { - assert.EqualError(err, tc.error, tc.name) - } - }) - } -} - -func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, assert *assert.Assertions) error { - data, err := hex.DecodeString(hexData) - assert.NoError(err, "Hex data should be a correct hex-string") - var e Event - assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI") - a := ABI{Events: map[string]Event{"e": e}} - return a.UnpackIntoInterface(dest, "e", data) -} - -// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder. -func TestEventUnpackIndexed(t *testing.T) { - t.Parallel() - definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` - type testStruct struct { - Value1 uint8 // indexed - Value2 uint8 - } - abi, err := JSON(strings.NewReader(definition)) - require.NoError(t, err) - var b bytes.Buffer - b.Write(packNum(reflect.ValueOf(uint8(8)))) - var rst testStruct - require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes())) - require.Equal(t, uint8(0), rst.Value1) - require.Equal(t, uint8(8), rst.Value2) -} - -// TestEventIndexedWithArrayUnpack verifies that decoder will not overflow when static array is indexed input. -func TestEventIndexedWithArrayUnpack(t *testing.T) { - t.Parallel() - definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]` - type testStruct struct { - Value1 [2]uint8 // indexed - Value2 string - } - abi, err := JSON(strings.NewReader(definition)) - require.NoError(t, err) - var b bytes.Buffer - stringOut := "abc" - // number of fields that will be encoded * 32 - b.Write(packNum(reflect.ValueOf(32))) - b.Write(packNum(reflect.ValueOf(len(stringOut)))) - b.Write(common.RightPadBytes([]byte(stringOut), 32)) - - var rst testStruct - require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes())) - require.Equal(t, [2]uint8{0, 0}, rst.Value1) - require.Equal(t, stringOut, rst.Value2) -} diff --git a/builder/accounts/abi/method.go b/builder/accounts/abi/method.go deleted file mode 100644 index c5a1a71f4..000000000 --- a/builder/accounts/abi/method.go +++ /dev/null @@ -1,166 +0,0 @@ -// 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 abi - -import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/crypto" -) - -// FunctionType represents different types of functions a contract might have. -type FunctionType int - -const ( - // Constructor represents the constructor of the contract. - // The constructor function is called while deploying a contract. - Constructor FunctionType = iota - // Fallback represents the fallback function. - // This function is executed if no other function matches the given function - // signature and no receive function is specified. - Fallback - // Receive represents the receive function. - // This function is executed on plain Ether transfers. - Receive - // Function represents a normal function. - Function -) - -// Method represents a callable given a `Name` and whether the method is a constant. -// If the method is `Const` no transaction needs to be created for this -// particular Method call. It can easily be simulated using a local VM. -// For example a `Balance()` method only needs to retrieve something -// from the storage and therefore requires no Tx to be sent to the -// network. A method such as `Transact` does require a Tx and thus will -// be flagged `false`. -// Input specifies the required input parameters for this gives method. -type Method struct { - // Name is the method name used for internal representation. It's derived from - // the raw name and a suffix will be added in the case of a function overload. - // - // e.g. - // These are two functions that have the same name: - // * foo(int,int) - // * foo(uint,uint) - // The method name of the first one will be resolved as foo while the second one - // will be resolved as foo0. - Name string - RawName string // RawName is the raw method name parsed from ABI - - // Type indicates whether the method is a - // special fallback introduced in solidity v0.6.0 - Type FunctionType - - // StateMutability indicates the mutability state of method, - // the default value is nonpayable. It can be empty if the abi - // is generated by legacy compiler. - StateMutability string - - // Legacy indicators generated by compiler before v0.6.0 - Constant bool - Payable bool - - Inputs Arguments - Outputs Arguments - str string - // Sig returns the methods string signature according to the ABI spec. - // e.g. function foo(uint32 a, int b) = "foo(uint32,int256)" - // Please note that "int" is substitute for its canonical representation "int256" - Sig string - // ID returns the canonical representation of the method's signature used by the - // abi definition to identify method names and types. - ID []byte -} - -// NewMethod creates a new Method. -// A method should always be created using NewMethod. -// It also precomputes the sig representation and the string representation -// of the method. -func NewMethod(name string, rawName string, funType FunctionType, mutability string, isConst, isPayable bool, inputs Arguments, outputs Arguments) Method { - var ( - types = make([]string, len(inputs)) - inputNames = make([]string, len(inputs)) - outputNames = make([]string, len(outputs)) - ) - for i, input := range inputs { - inputNames[i] = fmt.Sprintf("%v %v", input.Type, input.Name) - types[i] = input.Type.String() - } - for i, output := range outputs { - outputNames[i] = output.Type.String() - if len(output.Name) > 0 { - outputNames[i] += fmt.Sprintf(" %v", output.Name) - } - } - // calculate the signature and method id. Note only function - // has meaningful signature and id. - var ( - sig string - id []byte - ) - if funType == Function { - sig = fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ",")) - id = crypto.Keccak256([]byte(sig))[:4] - } - identity := fmt.Sprintf("function %v", rawName) - switch funType { - case Fallback: - identity = "fallback" - case Receive: - identity = "receive" - case Constructor: - identity = "constructor" - } - var str string - // Extract meaningful state mutability of solidity method. - // If it's empty string or default value "nonpayable", never print it. - if mutability == "" || mutability == "nonpayable" { - str = fmt.Sprintf("%v(%v) returns(%v)", identity, strings.Join(inputNames, ", "), strings.Join(outputNames, ", ")) - } else { - str = fmt.Sprintf("%v(%v) %s returns(%v)", identity, strings.Join(inputNames, ", "), mutability, strings.Join(outputNames, ", ")) - } - - return Method{ - Name: name, - RawName: rawName, - Type: funType, - StateMutability: mutability, - Constant: isConst, - Payable: isPayable, - Inputs: inputs, - Outputs: outputs, - str: str, - Sig: sig, - ID: id, - } -} - -func (method Method) String() string { - return method.str -} - -// IsConstant returns the indicator whether the method is read-only. -func (method Method) IsConstant() bool { - return method.StateMutability == "view" || method.StateMutability == "pure" || method.Constant -} - -// IsPayable returns the indicator whether the method can process -// plain ether transfers. -func (method Method) IsPayable() bool { - return method.StateMutability == "payable" || method.Payable -} diff --git a/builder/accounts/abi/method_test.go b/builder/accounts/abi/method_test.go deleted file mode 100644 index 632217392..000000000 --- a/builder/accounts/abi/method_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2018 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 abi - -import ( - "strings" - "testing" -) - -const methoddata = ` -[ - {"type": "function", "name": "balance", "stateMutability": "view"}, - {"type": "function", "name": "send", "inputs": [{ "name": "amount", "type": "uint256" }]}, - {"type": "function", "name": "transfer", "inputs": [{"name": "from", "type": "address"}, {"name": "to", "type": "address"}, {"name": "value", "type": "uint256"}], "outputs": [{"name": "success", "type": "bool"}]}, - {"constant":false,"inputs":[{"components":[{"name":"x","type":"uint256"},{"name":"y","type":"uint256"}],"name":"a","type":"tuple"}],"name":"tuple","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":false,"inputs":[{"components":[{"name":"x","type":"uint256"},{"name":"y","type":"uint256"}],"name":"a","type":"tuple[]"}],"name":"tupleSlice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":false,"inputs":[{"components":[{"name":"x","type":"uint256"},{"name":"y","type":"uint256"}],"name":"a","type":"tuple[5]"}],"name":"tupleArray","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":false,"inputs":[{"components":[{"name":"x","type":"uint256"},{"name":"y","type":"uint256"}],"name":"a","type":"tuple[5][]"}],"name":"complexTuple","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"stateMutability":"nonpayable","type":"fallback"}, - {"stateMutability":"payable","type":"receive"} -]` - -func TestMethodString(t *testing.T) { - t.Parallel() - var table = []struct { - method string - expectation string - }{ - { - method: "balance", - expectation: "function balance() view returns()", - }, - { - method: "send", - expectation: "function send(uint256 amount) returns()", - }, - { - method: "transfer", - expectation: "function transfer(address from, address to, uint256 value) returns(bool success)", - }, - { - method: "tuple", - expectation: "function tuple((uint256,uint256) a) returns()", - }, - { - method: "tupleArray", - expectation: "function tupleArray((uint256,uint256)[5] a) returns()", - }, - { - method: "tupleSlice", - expectation: "function tupleSlice((uint256,uint256)[] a) returns()", - }, - { - method: "complexTuple", - expectation: "function complexTuple((uint256,uint256)[5][] a) returns()", - }, - { - method: "fallback", - expectation: "fallback() returns()", - }, - { - method: "receive", - expectation: "receive() payable returns()", - }, - } - - abi, err := JSON(strings.NewReader(methoddata)) - if err != nil { - t.Fatal(err) - } - - for _, test := range table { - var got string - switch test.method { - case "fallback": - got = abi.Fallback.String() - case "receive": - got = abi.Receive.String() - default: - got = abi.Methods[test.method].String() - } - if got != test.expectation { - t.Errorf("expected string to be %s, got %s", test.expectation, got) - } - } -} - -func TestMethodSig(t *testing.T) { - t.Parallel() - var cases = []struct { - method string - expect string - }{ - { - method: "balance", - expect: "balance()", - }, - { - method: "send", - expect: "send(uint256)", - }, - { - method: "transfer", - expect: "transfer(address,address,uint256)", - }, - { - method: "tuple", - expect: "tuple((uint256,uint256))", - }, - { - method: "tupleArray", - expect: "tupleArray((uint256,uint256)[5])", - }, - { - method: "tupleSlice", - expect: "tupleSlice((uint256,uint256)[])", - }, - { - method: "complexTuple", - expect: "complexTuple((uint256,uint256)[5][])", - }, - } - abi, err := JSON(strings.NewReader(methoddata)) - if err != nil { - t.Fatal(err) - } - - for _, test := range cases { - got := abi.Methods[test.method].Sig - if got != test.expect { - t.Errorf("expected string to be %s, got %s", test.expect, got) - } - } -} diff --git a/builder/accounts/abi/pack.go b/builder/accounts/abi/pack.go deleted file mode 100644 index beef1fa37..000000000 --- a/builder/accounts/abi/pack.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "errors" - "fmt" - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" -) - -// packBytesSlice packs the given bytes as [L, V] as the canonical representation -// bytes slice. -func packBytesSlice(bytes []byte, l int) []byte { - len := packNum(reflect.ValueOf(l)) - return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...) -} - -// packElement packs the given reflect value according to the abi specification in -// t. -func packElement(t Type, reflectValue reflect.Value) ([]byte, error) { - switch t.T { - case IntTy, UintTy: - return packNum(reflectValue), nil - case StringTy: - return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil - case AddressTy: - if reflectValue.Kind() == reflect.Array { - reflectValue = mustArrayToByteSlice(reflectValue) - } - - return common.LeftPadBytes(reflectValue.Bytes(), 32), nil - case BoolTy: - if reflectValue.Bool() { - return math.PaddedBigBytes(common.Big1, 32), nil - } - return math.PaddedBigBytes(common.Big0, 32), nil - case BytesTy: - if reflectValue.Kind() == reflect.Array { - reflectValue = mustArrayToByteSlice(reflectValue) - } - if reflectValue.Type() != reflect.TypeOf([]byte{}) { - return []byte{}, errors.New("bytes type is neither slice nor array") - } - return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil - case FixedBytesTy, FunctionTy: - if reflectValue.Kind() == reflect.Array { - reflectValue = mustArrayToByteSlice(reflectValue) - } - return common.RightPadBytes(reflectValue.Bytes(), 32), nil - default: - return []byte{}, fmt.Errorf("could not pack element, unknown type: %v", t.T) - } -} - -// packNum packs the given number (using the reflect value) and will cast it to appropriate number representation. -func packNum(value reflect.Value) []byte { - switch kind := value.Kind(); kind { - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return math.U256Bytes(new(big.Int).SetUint64(value.Uint())) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return math.U256Bytes(big.NewInt(value.Int())) - case reflect.Ptr: - return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int))) - default: - panic("abi: fatal error") - } -} diff --git a/builder/accounts/abi/pack_test.go b/builder/accounts/abi/pack_test.go deleted file mode 100644 index 00bdae469..000000000 --- a/builder/accounts/abi/pack_test.go +++ /dev/null @@ -1,216 +0,0 @@ -// 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 abi - -import ( - "bytes" - "encoding/hex" - "fmt" - "math" - "math/big" - "reflect" - "strconv" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -// TestPack tests the general pack/unpack tests in packing_test.go -func TestPack(t *testing.T) { - t.Parallel() - for i, test := range packUnpackTests { - i, test := i, test - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - encb, err := hex.DecodeString(test.packed) - if err != nil { - t.Fatalf("invalid hex %s: %v", test.packed, err) - } - inDef := fmt.Sprintf(`[{ "name" : "method", "type": "function", "inputs": %s}]`, test.def) - inAbi, err := JSON(strings.NewReader(inDef)) - if err != nil { - t.Fatalf("invalid ABI definition %s, %v", inDef, err) - } - var packed []byte - packed, err = inAbi.Pack("method", test.unpacked) - - if err != nil { - t.Fatalf("test %d (%v) failed: %v", i, test.def, err) - } - if !reflect.DeepEqual(packed[4:], encb) { - t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, encb, packed[4:]) - } - }) - } -} - -func TestMethodPack(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(jsondata)) - if err != nil { - t.Fatal(err) - } - - sig := abi.Methods["slice"].ID - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - - packed, err := abi.Pack("slice", []uint32{1, 2}) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - var addrA, addrB = common.Address{1}, common.Address{2} - sig = abi.Methods["sliceAddress"].ID - sig = append(sig, common.LeftPadBytes([]byte{32}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes(addrA[:], 32)...) - sig = append(sig, common.LeftPadBytes(addrB[:], 32)...) - - packed, err = abi.Pack("sliceAddress", []common.Address{addrA, addrB}) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - var addrC, addrD = common.Address{3}, common.Address{4} - sig = abi.Methods["sliceMultiAddress"].ID - sig = append(sig, common.LeftPadBytes([]byte{64}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{160}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes(addrA[:], 32)...) - sig = append(sig, common.LeftPadBytes(addrB[:], 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes(addrC[:], 32)...) - sig = append(sig, common.LeftPadBytes(addrD[:], 32)...) - - packed, err = abi.Pack("sliceMultiAddress", []common.Address{addrA, addrB}, []common.Address{addrC, addrD}) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - sig = abi.Methods["slice256"].ID - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - - packed, err = abi.Pack("slice256", []*big.Int{big.NewInt(1), big.NewInt(2)}) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - a := [2][2]*big.Int{{big.NewInt(1), big.NewInt(1)}, {big.NewInt(2), big.NewInt(0)}} - sig = abi.Methods["nestedArray"].ID - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0xa0}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes(addrC[:], 32)...) - sig = append(sig, common.LeftPadBytes(addrD[:], 32)...) - packed, err = abi.Pack("nestedArray", a, []common.Address{addrC, addrD}) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - sig = abi.Methods["nestedArray2"].ID - sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0x80}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - packed, err = abi.Pack("nestedArray2", [2][]uint8{{1}, {1}}) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } - - sig = abi.Methods["nestedSlice"].ID - sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0x02}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{0xa0}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...) - sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...) - packed, err = abi.Pack("nestedSlice", [][]uint8{{1, 2}, {1, 2}}) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(packed, sig) { - t.Errorf("expected %x got %x", sig, packed) - } -} - -func TestPackNumber(t *testing.T) { - t.Parallel() - tests := []struct { - value reflect.Value - packed []byte - }{ - // Protocol limits - {reflect.ValueOf(0), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")}, - {reflect.ValueOf(1), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")}, - {reflect.ValueOf(-1), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}, - - // Type corner cases - {reflect.ValueOf(uint8(math.MaxUint8)), common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000ff")}, - {reflect.ValueOf(uint16(math.MaxUint16)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000ffff")}, - {reflect.ValueOf(uint32(math.MaxUint32)), common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000ffffffff")}, - {reflect.ValueOf(uint64(math.MaxUint64)), common.Hex2Bytes("000000000000000000000000000000000000000000000000ffffffffffffffff")}, - - {reflect.ValueOf(int8(math.MaxInt8)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000007f")}, - {reflect.ValueOf(int16(math.MaxInt16)), common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000007fff")}, - {reflect.ValueOf(int32(math.MaxInt32)), common.Hex2Bytes("000000000000000000000000000000000000000000000000000000007fffffff")}, - {reflect.ValueOf(int64(math.MaxInt64)), common.Hex2Bytes("0000000000000000000000000000000000000000000000007fffffffffffffff")}, - - {reflect.ValueOf(int8(math.MinInt8)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80")}, - {reflect.ValueOf(int16(math.MinInt16)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000")}, - {reflect.ValueOf(int32(math.MinInt32)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000")}, - {reflect.ValueOf(int64(math.MinInt64)), common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")}, - } - for i, tt := range tests { - packed := packNum(tt.value) - if !bytes.Equal(packed, tt.packed) { - t.Errorf("test %d: pack mismatch: have %x, want %x", i, packed, tt.packed) - } - } -} diff --git a/builder/accounts/abi/packing_test.go b/builder/accounts/abi/packing_test.go deleted file mode 100644 index eae3b0df2..000000000 --- a/builder/accounts/abi/packing_test.go +++ /dev/null @@ -1,990 +0,0 @@ -// 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 abi - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -type packUnpackTest struct { - def string - unpacked interface{} - packed string -} - -var packUnpackTests = []packUnpackTest{ - // Booleans - { - def: `[{ "type": "bool" }]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: true, - }, - { - def: `[{ "type": "bool" }]`, - packed: "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: false, - }, - // Integers - { - def: `[{ "type": "uint8" }]`, - unpacked: uint8(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{ "type": "uint8[]" }]`, - unpacked: []uint8{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{ "type": "uint16" }]`, - unpacked: uint16(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{ "type": "uint16[]" }]`, - unpacked: []uint16{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "uint17"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: big.NewInt(1), - }, - { - def: `[{"type": "uint32"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: uint32(1), - }, - { - def: `[{"type": "uint32[]"}]`, - unpacked: []uint32{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "uint64"}]`, - unpacked: uint64(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "uint64[]"}]`, - unpacked: []uint64{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "uint256"}]`, - unpacked: big.NewInt(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "uint256[]"}]`, - unpacked: []*big.Int{big.NewInt(1), big.NewInt(2)}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int8"}]`, - unpacked: int8(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int8[]"}]`, - unpacked: []int8{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int16"}]`, - unpacked: int16(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int16[]"}]`, - unpacked: []int16{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int17"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: big.NewInt(1), - }, - { - def: `[{"type": "int32"}]`, - unpacked: int32(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int32"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: int32(1), - }, - { - def: `[{"type": "int32[]"}]`, - unpacked: []int32{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int64"}]`, - unpacked: int64(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int64[]"}]`, - unpacked: []int64{1, 2}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int256"}]`, - unpacked: big.NewInt(2), - packed: "0000000000000000000000000000000000000000000000000000000000000002", - }, - { - def: `[{"type": "int256"}]`, - packed: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - unpacked: big.NewInt(-1), - }, - { - def: `[{"type": "int256[]"}]`, - unpacked: []*big.Int{big.NewInt(1), big.NewInt(2)}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - }, - // Address - { - def: `[{"type": "address"}]`, - packed: "0000000000000000000000000100000000000000000000000000000000000000", - unpacked: common.Address{1}, - }, - { - def: `[{"type": "address[]"}]`, - unpacked: []common.Address{{1}, {2}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000100000000000000000000000000000000000000" + - "0000000000000000000000000200000000000000000000000000000000000000", - }, - // Bytes - { - def: `[{"type": "bytes1"}]`, - unpacked: [1]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes2"}]`, - unpacked: [2]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes3"}]`, - unpacked: [3]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes4"}]`, - unpacked: [4]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes5"}]`, - unpacked: [5]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes6"}]`, - unpacked: [6]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes7"}]`, - unpacked: [7]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes8"}]`, - unpacked: [8]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes9"}]`, - unpacked: [9]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes10"}]`, - unpacked: [10]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes11"}]`, - unpacked: [11]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes12"}]`, - unpacked: [12]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes13"}]`, - unpacked: [13]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes14"}]`, - unpacked: [14]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes15"}]`, - unpacked: [15]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes16"}]`, - unpacked: [16]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes17"}]`, - unpacked: [17]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes18"}]`, - unpacked: [18]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes19"}]`, - unpacked: [19]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes20"}]`, - unpacked: [20]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes21"}]`, - unpacked: [21]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes22"}]`, - unpacked: [22]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes23"}]`, - unpacked: [23]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes24"}]`, - unpacked: [24]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes25"}]`, - unpacked: [25]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes26"}]`, - unpacked: [26]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes27"}]`, - unpacked: [27]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes28"}]`, - unpacked: [28]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes29"}]`, - unpacked: [29]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes30"}]`, - unpacked: [30]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes31"}]`, - unpacked: [31]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes32"}]`, - unpacked: [32]byte{1}, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "bytes32"}]`, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - unpacked: [32]byte{1, 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}, - }, - { - def: `[{"type": "bytes"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000020" + - "0100000000000000000000000000000000000000000000000000000000000000", - unpacked: common.Hex2Bytes("0100000000000000000000000000000000000000000000000000000000000000"), - }, - { - def: `[{"type": "bytes32"}]`, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - unpacked: [32]byte{1, 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}, - }, - // Functions - { - def: `[{"type": "function"}]`, - packed: "0100000000000000000000000000000000000000000000000000000000000000", - unpacked: [24]byte{1}, - }, - // Slice and Array - { - def: `[{"type": "uint8[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []uint8{1, 2}, - }, - { - def: `[{"type": "uint8[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: []uint8{}, - }, - { - def: `[{"type": "uint256[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: []*big.Int{}, - }, - { - def: `[{"type": "uint8[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]uint8{1, 2}, - }, - { - def: `[{"type": "int8[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]int8{1, 2}, - }, - { - def: `[{"type": "int16[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []int16{1, 2}, - }, - { - def: `[{"type": "int16[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]int16{1, 2}, - }, - { - def: `[{"type": "int32[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []int32{1, 2}, - }, - { - def: `[{"type": "int32[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]int32{1, 2}, - }, - { - def: `[{"type": "int64[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []int64{1, 2}, - }, - { - def: `[{"type": "int64[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]int64{1, 2}, - }, - { - def: `[{"type": "int256[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []*big.Int{big.NewInt(1), big.NewInt(2)}, - }, - { - def: `[{"type": "int256[3]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003", - unpacked: [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, - }, - // multi dimensional, if these pass, all types that don't require length prefix should pass - { - def: `[{"type": "uint8[][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: [][]uint8{}, - }, - { - def: `[{"type": "uint8[][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "00000000000000000000000000000000000000000000000000000000000000a0" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [][]uint8{{1, 2}, {1, 2}}, - }, - { - def: `[{"type": "uint8[][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "00000000000000000000000000000000000000000000000000000000000000a0" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003", - unpacked: [][]uint8{{1, 2}, {1, 2, 3}}, - }, - { - def: `[{"type": "uint8[2][2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2][2]uint8{{1, 2}, {1, 2}}, - }, - { - def: `[{"type": "uint8[][2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "0000000000000000000000000000000000000000000000000000000000000060" + - "0000000000000000000000000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: [2][]uint8{{}, {}}, - }, - { - def: `[{"type": "uint8[][2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "0000000000000000000000000000000000000000000000000000000000000080" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: [2][]uint8{{1}, {1}}, - }, - { - def: `[{"type": "uint8[2][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000000", - unpacked: [][2]uint8{}, - }, - { - def: `[{"type": "uint8[2][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [][2]uint8{{1, 2}}, - }, - { - def: `[{"type": "uint8[2][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [][2]uint8{{1, 2}, {1, 2}}, - }, - { - def: `[{"type": "uint16[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []uint16{1, 2}, - }, - { - def: `[{"type": "uint16[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]uint16{1, 2}, - }, - { - def: `[{"type": "uint32[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []uint32{1, 2}, - }, - { - def: `[{"type": "uint32[2][3][4]"}]`, - unpacked: [4][3][2]uint32{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}, {{13, 14}, {15, 16}, {17, 18}}, {{19, 20}, {21, 22}, {23, 24}}}, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "0000000000000000000000000000000000000000000000000000000000000004" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006" + - "0000000000000000000000000000000000000000000000000000000000000007" + - "0000000000000000000000000000000000000000000000000000000000000008" + - "0000000000000000000000000000000000000000000000000000000000000009" + - "000000000000000000000000000000000000000000000000000000000000000a" + - "000000000000000000000000000000000000000000000000000000000000000b" + - "000000000000000000000000000000000000000000000000000000000000000c" + - "000000000000000000000000000000000000000000000000000000000000000d" + - "000000000000000000000000000000000000000000000000000000000000000e" + - "000000000000000000000000000000000000000000000000000000000000000f" + - "0000000000000000000000000000000000000000000000000000000000000010" + - "0000000000000000000000000000000000000000000000000000000000000011" + - "0000000000000000000000000000000000000000000000000000000000000012" + - "0000000000000000000000000000000000000000000000000000000000000013" + - "0000000000000000000000000000000000000000000000000000000000000014" + - "0000000000000000000000000000000000000000000000000000000000000015" + - "0000000000000000000000000000000000000000000000000000000000000016" + - "0000000000000000000000000000000000000000000000000000000000000017" + - "0000000000000000000000000000000000000000000000000000000000000018", - }, - - { - def: `[{"type": "bytes32[]"}]`, - unpacked: [][32]byte{{1}, {2}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0100000000000000000000000000000000000000000000000000000000000000" + - "0200000000000000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "uint32[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]uint32{1, 2}, - }, - { - def: `[{"type": "uint64[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []uint64{1, 2}, - }, - { - def: `[{"type": "uint64[2]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: [2]uint64{1, 2}, - }, - { - def: `[{"type": "uint256[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: []*big.Int{big.NewInt(1), big.NewInt(2)}, - }, - { - def: `[{"type": "uint256[3]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003", - unpacked: [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, - }, - { - def: `[{"type": "string[4]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000080" + - "00000000000000000000000000000000000000000000000000000000000000c0" + - "0000000000000000000000000000000000000000000000000000000000000100" + - "0000000000000000000000000000000000000000000000000000000000000140" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "48656c6c6f000000000000000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "576f726c64000000000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000000b" + - "476f2d657468657265756d000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000008" + - "457468657265756d000000000000000000000000000000000000000000000000", - unpacked: [4]string{"Hello", "World", "Go-ethereum", "Ethereum"}, - }, - { - def: `[{"type": "string[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "0000000000000000000000000000000000000000000000000000000000000080" + - "0000000000000000000000000000000000000000000000000000000000000008" + - "457468657265756d000000000000000000000000000000000000000000000000" + - "000000000000000000000000000000000000000000000000000000000000000b" + - "676f2d657468657265756d000000000000000000000000000000000000000000", - unpacked: []string{"Ethereum", "go-ethereum"}, - }, - { - def: `[{"type": "bytes[]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "0000000000000000000000000000000000000000000000000000000000000080" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "f0f0f00000000000000000000000000000000000000000000000000000000000" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "f0f0f00000000000000000000000000000000000000000000000000000000000", - unpacked: [][]byte{{0xf0, 0xf0, 0xf0}, {0xf0, 0xf0, 0xf0}}, - }, - { - def: `[{"type": "uint256[2][][]"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000040" + - "00000000000000000000000000000000000000000000000000000000000000e0" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "00000000000000000000000000000000000000000000000000000000000000c8" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "00000000000000000000000000000000000000000000000000000000000003e8" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "00000000000000000000000000000000000000000000000000000000000000c8" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "00000000000000000000000000000000000000000000000000000000000003e8", - unpacked: [][][2]*big.Int{{{big.NewInt(1), big.NewInt(200)}, {big.NewInt(1), big.NewInt(1000)}}, {{big.NewInt(1), big.NewInt(200)}, {big.NewInt(1), big.NewInt(1000)}}}, - }, - // struct outputs - { - def: `[{"components": [{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}], "type":"tuple"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: struct { - Int1 *big.Int - Int2 *big.Int - }{big.NewInt(1), big.NewInt(2)}, - }, - { - def: `[{"components": [{"name":"int_one","type":"int256"}], "type":"tuple"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"components": [{"name":"int__one","type":"int256"}], "type":"tuple"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"components": [{"name":"int_one_","type":"int256"}], "type":"tuple"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001", - unpacked: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"components": [{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}], "type":"tuple"}]`, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002", - unpacked: struct { - IntOne *big.Int - Intone *big.Int - }{big.NewInt(1), big.NewInt(2)}, - }, - { - def: `[{"type": "string"}]`, - unpacked: "foobar", - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000006" + - "666f6f6261720000000000000000000000000000000000000000000000000000", - }, - { - def: `[{"type": "string[]"}]`, - unpacked: []string{"hello", "foobar"}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2 - "0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i = 0 - "0000000000000000000000000000000000000000000000000000000000000080" + // offset 128 to i = 1 - "0000000000000000000000000000000000000000000000000000000000000005" + // len(str[0]) = 5 - "68656c6c6f000000000000000000000000000000000000000000000000000000" + // str[0] - "0000000000000000000000000000000000000000000000000000000000000006" + // len(str[1]) = 6 - "666f6f6261720000000000000000000000000000000000000000000000000000", // str[1] - }, - { - def: `[{"type": "string[2]"}]`, - unpacked: [2]string{"hello", "foobar"}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000040" + // offset to i = 0 - "0000000000000000000000000000000000000000000000000000000000000080" + // offset to i = 1 - "0000000000000000000000000000000000000000000000000000000000000005" + // len(str[0]) = 5 - "68656c6c6f000000000000000000000000000000000000000000000000000000" + // str[0] - "0000000000000000000000000000000000000000000000000000000000000006" + // len(str[1]) = 6 - "666f6f6261720000000000000000000000000000000000000000000000000000", // str[1] - }, - { - def: `[{"type": "bytes32[][]"}]`, - unpacked: [][][32]byte{{{1}, {2}}, {{3}, {4}, {5}}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2 - "0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i = 0 - "00000000000000000000000000000000000000000000000000000000000000a0" + // offset 160 to i = 1 - "0000000000000000000000000000000000000000000000000000000000000002" + // len(array[0]) = 2 - "0100000000000000000000000000000000000000000000000000000000000000" + // array[0][0] - "0200000000000000000000000000000000000000000000000000000000000000" + // array[0][1] - "0000000000000000000000000000000000000000000000000000000000000003" + // len(array[1]) = 3 - "0300000000000000000000000000000000000000000000000000000000000000" + // array[1][0] - "0400000000000000000000000000000000000000000000000000000000000000" + // array[1][1] - "0500000000000000000000000000000000000000000000000000000000000000", // array[1][2] - }, - { - def: `[{"type": "bytes32[][2]"}]`, - unpacked: [2][][32]byte{{{1}, {2}}, {{3}, {4}, {5}}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i = 0 - "00000000000000000000000000000000000000000000000000000000000000a0" + // offset 160 to i = 1 - "0000000000000000000000000000000000000000000000000000000000000002" + // len(array[0]) = 2 - "0100000000000000000000000000000000000000000000000000000000000000" + // array[0][0] - "0200000000000000000000000000000000000000000000000000000000000000" + // array[0][1] - "0000000000000000000000000000000000000000000000000000000000000003" + // len(array[1]) = 3 - "0300000000000000000000000000000000000000000000000000000000000000" + // array[1][0] - "0400000000000000000000000000000000000000000000000000000000000000" + // array[1][1] - "0500000000000000000000000000000000000000000000000000000000000000", // array[1][2] - }, - { - def: `[{"type": "bytes32[3][2]"}]`, - unpacked: [2][3][32]byte{{{1}, {2}, {3}}, {{3}, {4}, {5}}}, - packed: "0100000000000000000000000000000000000000000000000000000000000000" + // array[0][0] - "0200000000000000000000000000000000000000000000000000000000000000" + // array[0][1] - "0300000000000000000000000000000000000000000000000000000000000000" + // array[0][2] - "0300000000000000000000000000000000000000000000000000000000000000" + // array[1][0] - "0400000000000000000000000000000000000000000000000000000000000000" + // array[1][1] - "0500000000000000000000000000000000000000000000000000000000000000", // array[1][2] - }, - { - // static tuple - def: `[{"components": [{"name":"a","type":"int64"}, - {"name":"b","type":"int256"}, - {"name":"c","type":"int256"}, - {"name":"d","type":"bool"}, - {"name":"e","type":"bytes32[3][2]"}], "type":"tuple"}]`, - unpacked: struct { - A int64 - B *big.Int - C *big.Int - D bool - E [2][3][32]byte - }{1, big.NewInt(1), big.NewInt(-1), true, [2][3][32]byte{{{1}, {2}, {3}}, {{3}, {4}, {5}}}}, - packed: "0000000000000000000000000000000000000000000000000000000000000001" + // struct[a] - "0000000000000000000000000000000000000000000000000000000000000001" + // struct[b] - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // struct[c] - "0000000000000000000000000000000000000000000000000000000000000001" + // struct[d] - "0100000000000000000000000000000000000000000000000000000000000000" + // struct[e] array[0][0] - "0200000000000000000000000000000000000000000000000000000000000000" + // struct[e] array[0][1] - "0300000000000000000000000000000000000000000000000000000000000000" + // struct[e] array[0][2] - "0300000000000000000000000000000000000000000000000000000000000000" + // struct[e] array[1][0] - "0400000000000000000000000000000000000000000000000000000000000000" + // struct[e] array[1][1] - "0500000000000000000000000000000000000000000000000000000000000000", // struct[e] array[1][2] - }, - { - def: `[{"components": [{"name":"a","type":"string"}, - {"name":"b","type":"int64"}, - {"name":"c","type":"bytes"}, - {"name":"d","type":"string[]"}, - {"name":"e","type":"int256[]"}, - {"name":"f","type":"address[]"}], "type":"tuple"}]`, - unpacked: struct { - A string - B int64 - C []byte - D []string - E []*big.Int - F []common.Address - }{"foobar", 1, []byte{1}, []string{"foo", "bar"}, []*big.Int{big.NewInt(1), big.NewInt(-1)}, []common.Address{{1}, {2}}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a - "00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset - "0000000000000000000000000000000000000000000000000000000000000001" + // struct[b] - "0000000000000000000000000000000000000000000000000000000000000100" + // struct[c] offset - "0000000000000000000000000000000000000000000000000000000000000140" + // struct[d] offset - "0000000000000000000000000000000000000000000000000000000000000220" + // struct[e] offset - "0000000000000000000000000000000000000000000000000000000000000280" + // struct[f] offset - "0000000000000000000000000000000000000000000000000000000000000006" + // struct[a] length - "666f6f6261720000000000000000000000000000000000000000000000000000" + // struct[a] "foobar" - "0000000000000000000000000000000000000000000000000000000000000001" + // struct[c] length - "0100000000000000000000000000000000000000000000000000000000000000" + // []byte{1} - "0000000000000000000000000000000000000000000000000000000000000002" + // struct[d] length - "0000000000000000000000000000000000000000000000000000000000000040" + // foo offset - "0000000000000000000000000000000000000000000000000000000000000080" + // bar offset - "0000000000000000000000000000000000000000000000000000000000000003" + // foo length - "666f6f0000000000000000000000000000000000000000000000000000000000" + // foo - "0000000000000000000000000000000000000000000000000000000000000003" + // bar offset - "6261720000000000000000000000000000000000000000000000000000000000" + // bar - "0000000000000000000000000000000000000000000000000000000000000002" + // struct[e] length - "0000000000000000000000000000000000000000000000000000000000000001" + // 1 - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // -1 - "0000000000000000000000000000000000000000000000000000000000000002" + // struct[f] length - "0000000000000000000000000100000000000000000000000000000000000000" + // common.Address{1} - "0000000000000000000000000200000000000000000000000000000000000000", // common.Address{2} - }, - { - def: `[{"components": [{ "type": "tuple","components": [{"name": "a","type": "uint256"}, - {"name": "b","type": "uint256[]"}], - "name": "a","type": "tuple"}, - {"name": "b","type": "uint256[]"}], "type": "tuple"}]`, - unpacked: struct { - A struct { - A *big.Int - B []*big.Int - } - B []*big.Int - }{ - A: struct { - A *big.Int - B []*big.Int - }{big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2)}}, - B: []*big.Int{big.NewInt(1), big.NewInt(2)}}, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a - "0000000000000000000000000000000000000000000000000000000000000040" + // a offset - "00000000000000000000000000000000000000000000000000000000000000e0" + // b offset - "0000000000000000000000000000000000000000000000000000000000000001" + // a.a value - "0000000000000000000000000000000000000000000000000000000000000040" + // a.b offset - "0000000000000000000000000000000000000000000000000000000000000002" + // a.b length - "0000000000000000000000000000000000000000000000000000000000000001" + // a.b[0] value - "0000000000000000000000000000000000000000000000000000000000000002" + // a.b[1] value - "0000000000000000000000000000000000000000000000000000000000000002" + // b length - "0000000000000000000000000000000000000000000000000000000000000001" + // b[0] value - "0000000000000000000000000000000000000000000000000000000000000002", // b[1] value - }, - - { - def: `[{"components": [{"name": "a","type": "int256"}, - {"name": "b","type": "int256[]"}], - "name": "a","type": "tuple[]"}]`, - unpacked: []struct { - A *big.Int - B []*big.Int - }{ - {big.NewInt(-1), []*big.Int{big.NewInt(1), big.NewInt(3)}}, - {big.NewInt(1), []*big.Int{big.NewInt(2), big.NewInt(-1)}}, - }, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple length - "0000000000000000000000000000000000000000000000000000000000000040" + // tuple[0] offset - "00000000000000000000000000000000000000000000000000000000000000e0" + // tuple[1] offset - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // tuple[0].A - "0000000000000000000000000000000000000000000000000000000000000040" + // tuple[0].B offset - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple[0].B length - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[0].B[0] value - "0000000000000000000000000000000000000000000000000000000000000003" + // tuple[0].B[1] value - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[1].A - "0000000000000000000000000000000000000000000000000000000000000040" + // tuple[1].B offset - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple[1].B length - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple[1].B[0] value - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // tuple[1].B[1] value - }, - { - def: `[{"components": [{"name": "a","type": "int256"}, - {"name": "b","type": "int256"}], - "name": "a","type": "tuple[2]"}]`, - unpacked: [2]struct { - A *big.Int - B *big.Int - }{ - {big.NewInt(-1), big.NewInt(1)}, - {big.NewInt(1), big.NewInt(-1)}, - }, - packed: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // tuple[0].a - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[0].b - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[1].a - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // tuple[1].b - }, - { - def: `[{"components": [{"name": "a","type": "int256[]"}], - "name": "a","type": "tuple[2]"}]`, - unpacked: [2]struct { - A []*big.Int - }{ - {[]*big.Int{big.NewInt(-1), big.NewInt(1)}}, - {[]*big.Int{big.NewInt(1), big.NewInt(-1)}}, - }, - packed: "0000000000000000000000000000000000000000000000000000000000000020" + - "0000000000000000000000000000000000000000000000000000000000000040" + // tuple[0] offset - "00000000000000000000000000000000000000000000000000000000000000c0" + // tuple[1] offset - "0000000000000000000000000000000000000000000000000000000000000020" + // tuple[0].A offset - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple[0].A length - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + // tuple[0].A[0] - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[0].A[1] - "0000000000000000000000000000000000000000000000000000000000000020" + // tuple[1].A offset - "0000000000000000000000000000000000000000000000000000000000000002" + // tuple[1].A length - "0000000000000000000000000000000000000000000000000000000000000001" + // tuple[1].A[0] - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // tuple[1].A[1] - }, -} diff --git a/builder/accounts/abi/reflect.go b/builder/accounts/abi/reflect.go deleted file mode 100644 index 1863e5bb7..000000000 --- a/builder/accounts/abi/reflect.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "errors" - "fmt" - "math/big" - "reflect" - "strings" -) - -// ConvertType converts an interface of a runtime type into a interface of the -// given type, e.g. turn this code: -// -// var fields []reflect.StructField -// -// fields = append(fields, reflect.StructField{ -// Name: "X", -// Type: reflect.TypeOf(new(big.Int)), -// Tag: reflect.StructTag("json:\"" + "x" + "\""), -// } -// -// into: -// -// type TupleT struct { X *big.Int } -func ConvertType(in interface{}, proto interface{}) interface{} { - protoType := reflect.TypeOf(proto) - if reflect.TypeOf(in).ConvertibleTo(protoType) { - return reflect.ValueOf(in).Convert(protoType).Interface() - } - // Use set as a last ditch effort - if err := set(reflect.ValueOf(proto), reflect.ValueOf(in)); err != nil { - panic(err) - } - return proto -} - -// indirect recursively dereferences the value until it either gets the value -// or finds a big.Int -func indirect(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) { - return indirect(v.Elem()) - } - return v -} - -// reflectIntType returns the reflect using the given size and -// unsignedness. -func reflectIntType(unsigned bool, size int) reflect.Type { - if unsigned { - switch size { - case 8: - return reflect.TypeOf(uint8(0)) - case 16: - return reflect.TypeOf(uint16(0)) - case 32: - return reflect.TypeOf(uint32(0)) - case 64: - return reflect.TypeOf(uint64(0)) - } - } - switch size { - case 8: - return reflect.TypeOf(int8(0)) - case 16: - return reflect.TypeOf(int16(0)) - case 32: - return reflect.TypeOf(int32(0)) - case 64: - return reflect.TypeOf(int64(0)) - } - return reflect.TypeOf(&big.Int{}) -} - -// mustArrayToByteSlice creates a new byte slice with the exact same size as value -// and copies the bytes in value to the new slice. -func mustArrayToByteSlice(value reflect.Value) reflect.Value { - slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len()) - reflect.Copy(slice, value) - return slice -} - -// set attempts to assign src to dst by either setting, copying or otherwise. -// -// set is a bit more lenient when it comes to assignment and doesn't force an as -// strict ruleset as bare `reflect` does. -func set(dst, src reflect.Value) error { - dstType, srcType := dst.Type(), src.Type() - switch { - case dstType.Kind() == reflect.Interface && dst.Elem().IsValid() && (dst.Elem().Type().Kind() == reflect.Ptr || dst.Elem().CanSet()): - return set(dst.Elem(), src) - case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}): - return set(dst.Elem(), src) - case srcType.AssignableTo(dstType) && dst.CanSet(): - dst.Set(src) - case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet(): - return setSlice(dst, src) - case dstType.Kind() == reflect.Array: - return setArray(dst, src) - case dstType.Kind() == reflect.Struct: - return setStruct(dst, src) - default: - return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) - } - return nil -} - -// setSlice attempts to assign src to dst when slices are not assignable by default -// e.g. src: [][]byte -> dst: [][15]byte -// setSlice ignores if we cannot copy all of src' elements. -func setSlice(dst, src reflect.Value) error { - slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) - for i := 0; i < src.Len(); i++ { - if err := set(slice.Index(i), src.Index(i)); err != nil { - return err - } - } - if dst.CanSet() { - dst.Set(slice) - return nil - } - return errors.New("cannot set slice, destination not settable") -} - -func setArray(dst, src reflect.Value) error { - if src.Kind() == reflect.Ptr { - return set(dst, indirect(src)) - } - array := reflect.New(dst.Type()).Elem() - min := src.Len() - if src.Len() > dst.Len() { - min = dst.Len() - } - for i := 0; i < min; i++ { - if err := set(array.Index(i), src.Index(i)); err != nil { - return err - } - } - if dst.CanSet() { - dst.Set(array) - return nil - } - return errors.New("cannot set array, destination not settable") -} - -func setStruct(dst, src reflect.Value) error { - for i := 0; i < src.NumField(); i++ { - srcField := src.Field(i) - dstField := dst.Field(i) - if !dstField.IsValid() || !srcField.IsValid() { - return fmt.Errorf("could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField) - } - if err := set(dstField, srcField); err != nil { - return err - } - } - return nil -} - -// mapArgNamesToStructFields maps a slice of argument names to struct fields. -// -// first round: for each Exportable field that contains a `abi:""` tag and this field name -// exists in the given argument name list, pair them together. -// -// second round: for each argument name that has not been already linked, find what -// variable is expected to be mapped into, if it exists and has not been used, pair them. -// -// Note this function assumes the given value is a struct value. -func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) { - typ := value.Type() - - abi2struct := make(map[string]string) - struct2abi := make(map[string]string) - - // first round ~~~ - for i := 0; i < typ.NumField(); i++ { - structFieldName := typ.Field(i).Name - - // skip private struct fields. - if structFieldName[:1] != strings.ToUpper(structFieldName[:1]) { - continue - } - // skip fields that have no abi:"" tag. - tagName, ok := typ.Field(i).Tag.Lookup("abi") - if !ok { - continue - } - // check if tag is empty. - if tagName == "" { - return nil, fmt.Errorf("struct: abi tag in '%s' is empty", structFieldName) - } - // check which argument field matches with the abi tag. - found := false - for _, arg := range argNames { - if arg == tagName { - if abi2struct[arg] != "" { - return nil, fmt.Errorf("struct: abi tag in '%s' already mapped", structFieldName) - } - // pair them - abi2struct[arg] = structFieldName - struct2abi[structFieldName] = arg - found = true - } - } - // check if this tag has been mapped. - if !found { - return nil, fmt.Errorf("struct: abi tag '%s' defined but not found in abi", tagName) - } - } - - // second round ~~~ - for _, argName := range argNames { - structFieldName := ToCamelCase(argName) - - if structFieldName == "" { - return nil, errors.New("abi: purely underscored output cannot unpack to struct") - } - - // this abi has already been paired, skip it... unless there exists another, yet unassigned - // struct field with the same field name. If so, raise an error: - // abi: [ { "name": "value" } ] - // struct { Value *big.Int , Value1 *big.Int `abi:"value"`} - if abi2struct[argName] != "" { - if abi2struct[argName] != structFieldName && - struct2abi[structFieldName] == "" && - value.FieldByName(structFieldName).IsValid() { - return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", argName) - } - continue - } - - // return an error if this struct field has already been paired. - if struct2abi[structFieldName] != "" { - return nil, fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", structFieldName) - } - - if value.FieldByName(structFieldName).IsValid() { - // pair them - abi2struct[argName] = structFieldName - struct2abi[structFieldName] = argName - } else { - // not paired, but annotate as used, to detect cases like - // abi : [ { "name": "value" }, { "name": "_value" } ] - // struct { Value *big.Int } - struct2abi[structFieldName] = argName - } - } - return abi2struct, nil -} diff --git a/builder/accounts/abi/reflect_test.go b/builder/accounts/abi/reflect_test.go deleted file mode 100644 index 6c7ae5708..000000000 --- a/builder/accounts/abi/reflect_test.go +++ /dev/null @@ -1,265 +0,0 @@ -// 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 abi - -import ( - "math/big" - "reflect" - "testing" -) - -type reflectTest struct { - name string - args []string - struc interface{} - want map[string]string - err string -} - -var reflectTests = []reflectTest{ - { - name: "OneToOneCorrespondence", - args: []string{"fieldA"}, - struc: struct { - FieldA int `abi:"fieldA"` - }{}, - want: map[string]string{ - "fieldA": "FieldA", - }, - }, - { - name: "MissingFieldsInStruct", - args: []string{"fieldA", "fieldB"}, - struc: struct { - FieldA int `abi:"fieldA"` - }{}, - want: map[string]string{ - "fieldA": "FieldA", - }, - }, - { - name: "MoreFieldsInStructThanArgs", - args: []string{"fieldA"}, - struc: struct { - FieldA int `abi:"fieldA"` - FieldB int - }{}, - want: map[string]string{ - "fieldA": "FieldA", - }, - }, - { - name: "MissingFieldInArgs", - args: []string{"fieldA"}, - struc: struct { - FieldA int `abi:"fieldA"` - FieldB int `abi:"fieldB"` - }{}, - err: "struct: abi tag 'fieldB' defined but not found in abi", - }, - { - name: "NoAbiDescriptor", - args: []string{"fieldA"}, - struc: struct { - FieldA int - }{}, - want: map[string]string{ - "fieldA": "FieldA", - }, - }, - { - name: "NoArgs", - args: []string{}, - struc: struct { - FieldA int `abi:"fieldA"` - }{}, - err: "struct: abi tag 'fieldA' defined but not found in abi", - }, - { - name: "DifferentName", - args: []string{"fieldB"}, - struc: struct { - FieldA int `abi:"fieldB"` - }{}, - want: map[string]string{ - "fieldB": "FieldA", - }, - }, - { - name: "DifferentName", - args: []string{"fieldB"}, - struc: struct { - FieldA int `abi:"fieldB"` - }{}, - want: map[string]string{ - "fieldB": "FieldA", - }, - }, - { - name: "MultipleFields", - args: []string{"fieldA", "fieldB"}, - struc: struct { - FieldA int `abi:"fieldA"` - FieldB int `abi:"fieldB"` - }{}, - want: map[string]string{ - "fieldA": "FieldA", - "fieldB": "FieldB", - }, - }, - { - name: "MultipleFieldsABIMissing", - args: []string{"fieldA", "fieldB"}, - struc: struct { - FieldA int `abi:"fieldA"` - FieldB int - }{}, - want: map[string]string{ - "fieldA": "FieldA", - "fieldB": "FieldB", - }, - }, - { - name: "NameConflict", - args: []string{"fieldB"}, - struc: struct { - FieldA int `abi:"fieldB"` - FieldB int - }{}, - err: "abi: multiple variables maps to the same abi field 'fieldB'", - }, - { - name: "Underscored", - args: []string{"_"}, - struc: struct { - FieldA int - }{}, - err: "abi: purely underscored output cannot unpack to struct", - }, - { - name: "DoubleMapping", - args: []string{"fieldB", "fieldC", "fieldA"}, - struc: struct { - FieldA int `abi:"fieldC"` - FieldB int - }{}, - err: "abi: multiple outputs mapping to the same struct field 'FieldA'", - }, - { - name: "AlreadyMapped", - args: []string{"fieldB", "fieldB"}, - struc: struct { - FieldB int `abi:"fieldB"` - }{}, - err: "struct: abi tag in 'FieldB' already mapped", - }, -} - -func TestReflectNameToStruct(t *testing.T) { - t.Parallel() - for _, test := range reflectTests { - test := test - t.Run(test.name, func(t *testing.T) { - t.Parallel() - m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc)) - if len(test.err) > 0 { - if err == nil || err.Error() != test.err { - t.Fatalf("Invalid error: expected %v, got %v", test.err, err) - } - } else { - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - for fname := range test.want { - if m[fname] != test.want[fname] { - t.Fatalf("Incorrect value for field %s: expected %v, got %v", fname, test.want[fname], m[fname]) - } - } - } - }) - } -} - -func TestConvertType(t *testing.T) { - t.Parallel() - // Test Basic Struct - type T struct { - X *big.Int - Y *big.Int - } - // Create on-the-fly structure - var fields []reflect.StructField - fields = append(fields, reflect.StructField{ - Name: "X", - Type: reflect.TypeOf(new(big.Int)), - Tag: "json:\"" + "x" + "\"", - }) - fields = append(fields, reflect.StructField{ - Name: "Y", - Type: reflect.TypeOf(new(big.Int)), - Tag: "json:\"" + "y" + "\"", - }) - val := reflect.New(reflect.StructOf(fields)) - val.Elem().Field(0).Set(reflect.ValueOf(big.NewInt(1))) - val.Elem().Field(1).Set(reflect.ValueOf(big.NewInt(2))) - // ConvertType - out := *ConvertType(val.Interface(), new(T)).(*T) - if out.X.Cmp(big.NewInt(1)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out.X, big.NewInt(1)) - } - if out.Y.Cmp(big.NewInt(2)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out.Y, big.NewInt(2)) - } - // Slice Type - val2 := reflect.MakeSlice(reflect.SliceOf(reflect.StructOf(fields)), 2, 2) - val2.Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1))) - val2.Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2))) - val2.Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3))) - val2.Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4))) - out2 := *ConvertType(val2.Interface(), new([]T)).(*[]T) - if out2[0].X.Cmp(big.NewInt(1)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1)) - } - if out2[0].Y.Cmp(big.NewInt(2)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2)) - } - if out2[1].X.Cmp(big.NewInt(3)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1)) - } - if out2[1].Y.Cmp(big.NewInt(4)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2)) - } - // Array Type - val3 := reflect.New(reflect.ArrayOf(2, reflect.StructOf(fields))) - val3.Elem().Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1))) - val3.Elem().Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2))) - val3.Elem().Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3))) - val3.Elem().Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4))) - out3 := *ConvertType(val3.Interface(), new([2]T)).(*[2]T) - if out3[0].X.Cmp(big.NewInt(1)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1)) - } - if out3[0].Y.Cmp(big.NewInt(2)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2)) - } - if out3[1].X.Cmp(big.NewInt(3)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1)) - } - if out3[1].Y.Cmp(big.NewInt(4)) != 0 { - t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2)) - } -} diff --git a/builder/accounts/abi/selector_parser.go b/builder/accounts/abi/selector_parser.go deleted file mode 100644 index b8ddd7d65..000000000 --- a/builder/accounts/abi/selector_parser.go +++ /dev/null @@ -1,177 +0,0 @@ -// 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 abi - -import ( - "errors" - "fmt" -) - -type SelectorMarshaling struct { - Name string `json:"name"` - Type string `json:"type"` - Inputs []ArgumentMarshaling `json:"inputs"` -} - -func isDigit(c byte) bool { - return c >= '0' && c <= '9' -} - -func isAlpha(c byte) bool { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') -} - -func isIdentifierSymbol(c byte) bool { - return c == '$' || c == '_' -} - -func parseToken(unescapedSelector string, isIdent bool) (string, string, error) { - if len(unescapedSelector) == 0 { - return "", "", errors.New("empty token") - } - firstChar := unescapedSelector[0] - position := 1 - if !(isAlpha(firstChar) || (isIdent && isIdentifierSymbol(firstChar))) { - return "", "", fmt.Errorf("invalid token start: %c", firstChar) - } - for position < len(unescapedSelector) { - char := unescapedSelector[position] - if !(isAlpha(char) || isDigit(char) || (isIdent && isIdentifierSymbol(char))) { - break - } - position++ - } - return unescapedSelector[:position], unescapedSelector[position:], nil -} - -func parseIdentifier(unescapedSelector string) (string, string, error) { - return parseToken(unescapedSelector, true) -} - -func parseElementaryType(unescapedSelector string) (string, string, error) { - parsedType, rest, err := parseToken(unescapedSelector, false) - if err != nil { - return "", "", fmt.Errorf("failed to parse elementary type: %v", err) - } - // handle arrays - for len(rest) > 0 && rest[0] == '[' { - parsedType = parsedType + string(rest[0]) - rest = rest[1:] - for len(rest) > 0 && isDigit(rest[0]) { - parsedType = parsedType + string(rest[0]) - rest = rest[1:] - } - if len(rest) == 0 || rest[0] != ']' { - return "", "", fmt.Errorf("failed to parse array: expected ']', got %c", unescapedSelector[0]) - } - parsedType = parsedType + string(rest[0]) - rest = rest[1:] - } - return parsedType, rest, nil -} - -func parseCompositeType(unescapedSelector string) ([]interface{}, string, error) { - if len(unescapedSelector) == 0 || unescapedSelector[0] != '(' { - return nil, "", fmt.Errorf("expected '(', got %c", unescapedSelector[0]) - } - parsedType, rest, err := parseType(unescapedSelector[1:]) - if err != nil { - return nil, "", fmt.Errorf("failed to parse type: %v", err) - } - result := []interface{}{parsedType} - for len(rest) > 0 && rest[0] != ')' { - parsedType, rest, err = parseType(rest[1:]) - if err != nil { - return nil, "", fmt.Errorf("failed to parse type: %v", err) - } - result = append(result, parsedType) - } - if len(rest) == 0 || rest[0] != ')' { - return nil, "", fmt.Errorf("expected ')', got '%s'", rest) - } - if len(rest) >= 3 && rest[1] == '[' && rest[2] == ']' { - return append(result, "[]"), rest[3:], nil - } - return result, rest[1:], nil -} - -func parseType(unescapedSelector string) (interface{}, string, error) { - if len(unescapedSelector) == 0 { - return nil, "", errors.New("empty type") - } - if unescapedSelector[0] == '(' { - return parseCompositeType(unescapedSelector) - } else { - return parseElementaryType(unescapedSelector) - } -} - -func assembleArgs(args []interface{}) ([]ArgumentMarshaling, error) { - arguments := make([]ArgumentMarshaling, 0) - for i, arg := range args { - // generate dummy name to avoid unmarshal issues - name := fmt.Sprintf("name%d", i) - if s, ok := arg.(string); ok { - arguments = append(arguments, ArgumentMarshaling{name, s, s, nil, false}) - } else if components, ok := arg.([]interface{}); ok { - subArgs, err := assembleArgs(components) - if err != nil { - return nil, fmt.Errorf("failed to assemble components: %v", err) - } - tupleType := "tuple" - if len(subArgs) != 0 && subArgs[len(subArgs)-1].Type == "[]" { - subArgs = subArgs[:len(subArgs)-1] - tupleType = "tuple[]" - } - arguments = append(arguments, ArgumentMarshaling{name, tupleType, tupleType, subArgs, false}) - } else { - return nil, fmt.Errorf("failed to assemble args: unexpected type %T", arg) - } - } - return arguments, nil -} - -// ParseSelector converts a method selector into a struct that can be JSON encoded -// and consumed by other functions in this package. -// Note, although uppercase letters are not part of the ABI spec, this function -// still accepts it as the general format is valid. -func ParseSelector(unescapedSelector string) (SelectorMarshaling, error) { - name, rest, err := parseIdentifier(unescapedSelector) - if err != nil { - return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err) - } - args := []interface{}{} - if len(rest) >= 2 && rest[0] == '(' && rest[1] == ')' { - rest = rest[2:] - } else { - args, rest, err = parseCompositeType(rest) - if err != nil { - return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err) - } - } - if len(rest) > 0 { - return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': unexpected string '%s'", unescapedSelector, rest) - } - - // Reassemble the fake ABI and construct the JSON - fakeArgs, err := assembleArgs(args) - if err != nil { - return SelectorMarshaling{}, fmt.Errorf("failed to parse selector: %v", err) - } - - return SelectorMarshaling{name, "function", fakeArgs}, nil -} diff --git a/builder/accounts/abi/selector_parser_test.go b/builder/accounts/abi/selector_parser_test.go deleted file mode 100644 index 6cb0ae0e7..000000000 --- a/builder/accounts/abi/selector_parser_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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 abi - -import ( - "fmt" - "log" - "reflect" - "testing" -) - -func TestParseSelector(t *testing.T) { - t.Parallel() - mkType := func(types ...interface{}) []ArgumentMarshaling { - var result []ArgumentMarshaling - for i, typeOrComponents := range types { - name := fmt.Sprintf("name%d", i) - if typeName, ok := typeOrComponents.(string); ok { - result = append(result, ArgumentMarshaling{name, typeName, typeName, nil, false}) - } else if components, ok := typeOrComponents.([]ArgumentMarshaling); ok { - result = append(result, ArgumentMarshaling{name, "tuple", "tuple", components, false}) - } else if components, ok := typeOrComponents.([][]ArgumentMarshaling); ok { - result = append(result, ArgumentMarshaling{name, "tuple[]", "tuple[]", components[0], false}) - } else { - log.Fatalf("unexpected type %T", typeOrComponents) - } - } - return result - } - tests := []struct { - input string - name string - args []ArgumentMarshaling - }{ - {"noargs()", "noargs", []ArgumentMarshaling{}}, - {"simple(uint256,uint256,uint256)", "simple", mkType("uint256", "uint256", "uint256")}, - {"other(uint256,address)", "other", mkType("uint256", "address")}, - {"withArray(uint256[],address[2],uint8[4][][5])", "withArray", mkType("uint256[]", "address[2]", "uint8[4][][5]")}, - {"singleNest(bytes32,uint8,(uint256,uint256),address)", "singleNest", mkType("bytes32", "uint8", mkType("uint256", "uint256"), "address")}, - {"multiNest(address,(uint256[],uint256),((address,bytes32),uint256))", "multiNest", - mkType("address", mkType("uint256[]", "uint256"), mkType(mkType("address", "bytes32"), "uint256"))}, - {"arrayNest((uint256,uint256)[],bytes32)", "arrayNest", mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32")}, - {"multiArrayNest((uint256,uint256)[],(uint256,uint256)[])", "multiArrayNest", - mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, [][]ArgumentMarshaling{mkType("uint256", "uint256")})}, - {"singleArrayNestAndArray((uint256,uint256)[],bytes32[])", "singleArrayNestAndArray", - mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32[]")}, - {"singleArrayNestWithArrayAndArray((uint256[],address[2],uint8[4][][5])[],bytes32[])", "singleArrayNestWithArrayAndArray", - mkType([][]ArgumentMarshaling{mkType("uint256[]", "address[2]", "uint8[4][][5]")}, "bytes32[]")}, - } - for i, tt := range tests { - selector, err := ParseSelector(tt.input) - if err != nil { - t.Errorf("test %d: failed to parse selector '%v': %v", i, tt.input, err) - } - if selector.Name != tt.name { - t.Errorf("test %d: unexpected function name: '%s' != '%s'", i, selector.Name, tt.name) - } - - if selector.Type != "function" { - t.Errorf("test %d: unexpected type: '%s' != '%s'", i, selector.Type, "function") - } - if !reflect.DeepEqual(selector.Inputs, tt.args) { - t.Errorf("test %d: unexpected args: '%v' != '%v'", i, selector.Inputs, tt.args) - } - } -} diff --git a/builder/accounts/abi/topics.go b/builder/accounts/abi/topics.go deleted file mode 100644 index 7ce9b7273..000000000 --- a/builder/accounts/abi/topics.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2018 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 abi - -import ( - "encoding/binary" - "errors" - "fmt" - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto" -) - -// MakeTopics converts a filter query argument list into a filter topic set. -func MakeTopics(query ...[]interface{}) ([][]common.Hash, error) { - topics := make([][]common.Hash, len(query)) - for i, filter := range query { - for _, rule := range filter { - var topic common.Hash - - // Try to generate the topic based on simple types - switch rule := rule.(type) { - case common.Hash: - copy(topic[:], rule[:]) - case common.Address: - copy(topic[common.HashLength-common.AddressLength:], rule[:]) - case *big.Int: - copy(topic[:], math.U256Bytes(rule)) - case bool: - if rule { - topic[common.HashLength-1] = 1 - } - case int8: - copy(topic[:], genIntType(int64(rule), 1)) - case int16: - copy(topic[:], genIntType(int64(rule), 2)) - case int32: - copy(topic[:], genIntType(int64(rule), 4)) - case int64: - copy(topic[:], genIntType(rule, 8)) - case uint8: - blob := new(big.Int).SetUint64(uint64(rule)).Bytes() - copy(topic[common.HashLength-len(blob):], blob) - case uint16: - blob := new(big.Int).SetUint64(uint64(rule)).Bytes() - copy(topic[common.HashLength-len(blob):], blob) - case uint32: - blob := new(big.Int).SetUint64(uint64(rule)).Bytes() - copy(topic[common.HashLength-len(blob):], blob) - case uint64: - blob := new(big.Int).SetUint64(rule).Bytes() - copy(topic[common.HashLength-len(blob):], blob) - case string: - hash := crypto.Keccak256Hash([]byte(rule)) - copy(topic[:], hash[:]) - case []byte: - hash := crypto.Keccak256Hash(rule) - copy(topic[:], hash[:]) - - default: - // todo(rjl493456442) according to solidity documentation, indexed event - // parameters that are not value types i.e. arrays and structs are not - // stored directly but instead a keccak256-hash of an encoding is stored. - // - // We only convert stringS and bytes to hash, still need to deal with - // array(both fixed-size and dynamic-size) and struct. - - // Attempt to generate the topic from funky types - val := reflect.ValueOf(rule) - switch { - // static byte array - case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: - reflect.Copy(reflect.ValueOf(topic[:val.Len()]), val) - default: - return nil, fmt.Errorf("unsupported indexed type: %T", rule) - } - } - topics[i] = append(topics[i], topic) - } - } - return topics, nil -} - -func genIntType(rule int64, size uint) []byte { - var topic [common.HashLength]byte - if rule < 0 { - // if a rule is negative, we need to put it into two's complement. - // extended to common.HashLength bytes. - topic = [common.HashLength]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} - } - for i := uint(0); i < size; i++ { - topic[common.HashLength-i-1] = byte(rule >> (i * 8)) - } - return topic[:] -} - -// ParseTopics converts the indexed topic fields into actual log field values. -func ParseTopics(out interface{}, fields Arguments, topics []common.Hash) error { - return parseTopicWithSetter(fields, topics, - func(arg Argument, reconstr interface{}) { - field := reflect.ValueOf(out).Elem().FieldByName(ToCamelCase(arg.Name)) - field.Set(reflect.ValueOf(reconstr)) - }) -} - -// ParseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs. -func ParseTopicsIntoMap(out map[string]interface{}, fields Arguments, topics []common.Hash) error { - return parseTopicWithSetter(fields, topics, - func(arg Argument, reconstr interface{}) { - out[arg.Name] = reconstr - }) -} - -// parseTopicWithSetter converts the indexed topic field-value pairs and stores them using the -// provided set function. -// -// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256 -// hashes as the topic value! -func parseTopicWithSetter(fields Arguments, topics []common.Hash, setter func(Argument, interface{})) error { - // Sanity check that the fields and topics match up - if len(fields) != len(topics) { - return errors.New("topic/field count mismatch") - } - // Iterate over all the fields and reconstruct them from topics - for i, arg := range fields { - if !arg.Indexed { - return errors.New("non-indexed field in topic reconstruction") - } - var reconstr interface{} - switch arg.Type.T { - case TupleTy: - return errors.New("tuple type in topic reconstruction") - case StringTy, BytesTy, SliceTy, ArrayTy: - // Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash - // whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash - reconstr = topics[i] - case FunctionTy: - if garbage := binary.BigEndian.Uint64(topics[i][0:8]); garbage != 0 { - return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[i].Bytes()) - } - var tmp [24]byte - copy(tmp[:], topics[i][8:32]) - reconstr = tmp - default: - var err error - reconstr, err = toGoType(0, arg.Type, topics[i].Bytes()) - if err != nil { - return err - } - } - // Use the setter function to store the value - setter(arg, reconstr) - } - - return nil -} diff --git a/builder/accounts/abi/topics_test.go b/builder/accounts/abi/topics_test.go deleted file mode 100644 index 9e1efd382..000000000 --- a/builder/accounts/abi/topics_test.go +++ /dev/null @@ -1,409 +0,0 @@ -// 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 abi - -import ( - "math" - "math/big" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -func TestMakeTopics(t *testing.T) { - t.Parallel() - type args struct { - query [][]interface{} - } - tests := []struct { - name string - args args - want [][]common.Hash - wantErr bool - }{ - { - "support fixed byte types, right padded to 32 bytes", - args{[][]interface{}{{[5]byte{1, 2, 3, 4, 5}}}}, - [][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}}, - false, - }, - { - "support common hash types in topics", - args{[][]interface{}{{common.Hash{1, 2, 3, 4, 5}}}}, - [][]common.Hash{{common.Hash{1, 2, 3, 4, 5}}}, - false, - }, - { - "support address types in topics", - args{[][]interface{}{{common.Address{1, 2, 3, 4, 5}}}}, - [][]common.Hash{{common.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5}}}, - false, - }, - { - "support positive *big.Int types in topics", - args{[][]interface{}{ - {big.NewInt(1)}, - {big.NewInt(1).Lsh(big.NewInt(2), 254)}, - }}, - [][]common.Hash{ - {common.HexToHash("0000000000000000000000000000000000000000000000000000000000000001")}, - {common.Hash{128}}, - }, - false, - }, - { - "support negative *big.Int types in topics", - args{[][]interface{}{ - {big.NewInt(-1)}, - {big.NewInt(math.MinInt64)}, - }}, - [][]common.Hash{ - {common.MaxHash}, - {common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000")}, - }, - false, - }, - { - "support boolean types in topics", - args{[][]interface{}{ - {true}, - {false}, - }}, - [][]common.Hash{ - {common.Hash{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}}, - {common.Hash{0}}, - }, - false, - }, - { - "support int/uint(8/16/32/64) types in topics", - args{[][]interface{}{ - {int8(-2)}, - {int16(-3)}, - {int32(-4)}, - {int64(-5)}, - {int8(1)}, - {int16(256)}, - {int32(65536)}, - {int64(4294967296)}, - {uint8(1)}, - {uint16(256)}, - {uint32(65536)}, - {uint64(4294967296)}, - }}, - [][]common.Hash{ - {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254}}, - {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253}}, - {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252}}, - {common.Hash{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 251}}, - {common.Hash{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}}, - {common.Hash{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, 0}}, - {common.Hash{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, 0, 0}}, - {common.Hash{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, 0, 0, 0, 0}}, - {common.Hash{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}}, - {common.Hash{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, 0}}, - {common.Hash{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, 0, 0}}, - {common.Hash{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, 0, 0, 0, 0}}, - }, - false, - }, - { - "support string types in topics", - args{[][]interface{}{{"hello world"}}}, - [][]common.Hash{{crypto.Keccak256Hash([]byte("hello world"))}}, - false, - }, - { - "support byte slice types in topics", - args{[][]interface{}{{[]byte{1, 2, 3}}}}, - [][]common.Hash{{crypto.Keccak256Hash([]byte{1, 2, 3})}}, - false, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got, err := MakeTopics(tt.args.query...) - if (err != nil) != tt.wantErr { - t.Errorf("makeTopics() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("makeTopics() = %v, want %v", got, tt.want) - } - }) - } -} - -type args struct { - createObj func() interface{} - resultObj func() interface{} - resultMap func() map[string]interface{} - fields Arguments - topics []common.Hash -} - -type bytesStruct struct { - StaticBytes [5]byte -} -type int8Struct struct { - Int8Value int8 -} -type int256Struct struct { - Int256Value *big.Int -} - -type hashStruct struct { - HashValue common.Hash -} - -type funcStruct struct { - FuncValue [24]byte -} - -type topicTest struct { - name string - args args - wantErr bool -} - -func setupTopicsTests() []topicTest { - bytesType, _ := NewType("bytes5", "", nil) - int8Type, _ := NewType("int8", "", nil) - int256Type, _ := NewType("int256", "", nil) - tupleType, _ := NewType("tuple(int256,int8)", "", nil) - stringType, _ := NewType("string", "", nil) - funcType, _ := NewType("function", "", nil) - - tests := []topicTest{ - { - name: "support fixed byte types, right padded to 32 bytes", - args: args{ - createObj: func() interface{} { return &bytesStruct{} }, - resultObj: func() interface{} { return &bytesStruct{StaticBytes: [5]byte{1, 2, 3, 4, 5}} }, - resultMap: func() map[string]interface{} { - return map[string]interface{}{"staticBytes": [5]byte{1, 2, 3, 4, 5}} - }, - fields: Arguments{Argument{ - Name: "staticBytes", - Type: bytesType, - Indexed: true, - }}, - topics: []common.Hash{ - {1, 2, 3, 4, 5}, - }, - }, - wantErr: false, - }, - { - name: "int8 with negative value", - args: args{ - createObj: func() interface{} { return &int8Struct{} }, - resultObj: func() interface{} { return &int8Struct{Int8Value: -1} }, - resultMap: func() map[string]interface{} { - return map[string]interface{}{"int8Value": int8(-1)} - }, - fields: Arguments{Argument{ - Name: "int8Value", - Type: int8Type, - Indexed: true, - }}, - topics: []common.Hash{ - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - wantErr: false, - }, - { - name: "int256 with negative value", - args: args{ - createObj: func() interface{} { return &int256Struct{} }, - resultObj: func() interface{} { return &int256Struct{Int256Value: big.NewInt(-1)} }, - resultMap: func() map[string]interface{} { - return map[string]interface{}{"int256Value": big.NewInt(-1)} - }, - fields: Arguments{Argument{ - Name: "int256Value", - Type: int256Type, - Indexed: true, - }}, - topics: []common.Hash{ - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - wantErr: false, - }, - { - name: "hash type", - args: args{ - createObj: func() interface{} { return &hashStruct{} }, - resultObj: func() interface{} { return &hashStruct{crypto.Keccak256Hash([]byte("stringtopic"))} }, - resultMap: func() map[string]interface{} { - return map[string]interface{}{"hashValue": crypto.Keccak256Hash([]byte("stringtopic"))} - }, - fields: Arguments{Argument{ - Name: "hashValue", - Type: stringType, - Indexed: true, - }}, - topics: []common.Hash{ - crypto.Keccak256Hash([]byte("stringtopic")), - }, - }, - wantErr: false, - }, - { - name: "function type", - args: args{ - createObj: func() interface{} { return &funcStruct{} }, - resultObj: func() interface{} { - return &funcStruct{[24]byte{255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}} - }, - resultMap: func() map[string]interface{} { - return map[string]interface{}{"funcValue": [24]byte{255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}} - }, - fields: Arguments{Argument{ - Name: "funcValue", - Type: funcType, - Indexed: true, - }}, - topics: []common.Hash{ - {0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - wantErr: false, - }, - { - name: "error on topic/field count mismatch", - args: args{ - createObj: func() interface{} { return nil }, - resultObj: func() interface{} { return nil }, - resultMap: func() map[string]interface{} { return make(map[string]interface{}) }, - fields: Arguments{Argument{ - Name: "tupletype", - Type: tupleType, - Indexed: true, - }}, - topics: []common.Hash{}, - }, - wantErr: true, - }, - { - name: "error on unindexed arguments", - args: args{ - createObj: func() interface{} { return &int256Struct{} }, - resultObj: func() interface{} { return &int256Struct{} }, - resultMap: func() map[string]interface{} { return make(map[string]interface{}) }, - fields: Arguments{Argument{ - Name: "int256Value", - Type: int256Type, - Indexed: false, - }}, - topics: []common.Hash{ - {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - wantErr: true, - }, - { - name: "error on tuple in topic reconstruction", - args: args{ - createObj: func() interface{} { return &tupleType }, - resultObj: func() interface{} { return &tupleType }, - resultMap: func() map[string]interface{} { return make(map[string]interface{}) }, - fields: Arguments{Argument{ - Name: "tupletype", - Type: tupleType, - Indexed: true, - }}, - topics: []common.Hash{{0}}, - }, - wantErr: true, - }, - { - name: "error on improper encoded function", - args: args{ - createObj: func() interface{} { return &funcStruct{} }, - resultObj: func() interface{} { return &funcStruct{} }, - resultMap: func() map[string]interface{} { - return make(map[string]interface{}) - }, - fields: Arguments{Argument{ - Name: "funcValue", - Type: funcType, - Indexed: true, - }}, - topics: []common.Hash{ - {0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - }, - }, - wantErr: true, - }, - } - - return tests -} - -func TestParseTopics(t *testing.T) { - t.Parallel() - tests := setupTopicsTests() - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - createObj := tt.args.createObj() - if err := ParseTopics(createObj, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr { - t.Errorf("parseTopics() error = %v, wantErr %v", err, tt.wantErr) - } - resultObj := tt.args.resultObj() - if !reflect.DeepEqual(createObj, resultObj) { - t.Errorf("parseTopics() = %v, want %v", createObj, resultObj) - } - }) - } -} - -func TestParseTopicsIntoMap(t *testing.T) { - t.Parallel() - tests := setupTopicsTests() - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - outMap := make(map[string]interface{}) - if err := ParseTopicsIntoMap(outMap, tt.args.fields, tt.args.topics); (err != nil) != tt.wantErr { - t.Errorf("parseTopicsIntoMap() error = %v, wantErr %v", err, tt.wantErr) - } - resultMap := tt.args.resultMap() - if !reflect.DeepEqual(outMap, resultMap) { - t.Errorf("parseTopicsIntoMap() = %v, want %v", outMap, resultMap) - } - }) - } -} diff --git a/builder/accounts/abi/type.go b/builder/accounts/abi/type.go deleted file mode 100644 index 2eee11787..000000000 --- a/builder/accounts/abi/type.go +++ /dev/null @@ -1,426 +0,0 @@ -// 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 abi - -import ( - "errors" - "fmt" - "reflect" - "regexp" - "strconv" - "strings" - "unicode" - "unicode/utf8" - - "github.com/ethereum/go-ethereum/common" -) - -// Type enumerator -const ( - IntTy byte = iota - UintTy - BoolTy - StringTy - SliceTy - ArrayTy - TupleTy - AddressTy - FixedBytesTy - BytesTy - HashTy - FixedPointTy - FunctionTy -) - -// Type is the reflection of the supported argument type. -type Type struct { - Elem *Type - Size int - T byte // Our own type checking - - stringKind string // holds the unparsed string for deriving signatures - - // Tuple relative fields - TupleRawName string // Raw struct name defined in source code, may be empty. - TupleElems []*Type // Type information of all tuple fields - TupleRawNames []string // Raw field name of all tuple fields - TupleType reflect.Type // Underlying struct of the tuple -} - -var ( - // typeRegex parses the abi sub types - typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?") -) - -// NewType creates a new reflection type of abi type given in t. -func NewType(t string, internalType string, components []ArgumentMarshaling) (typ Type, err error) { - // check that array brackets are equal if they exist - if strings.Count(t, "[") != strings.Count(t, "]") { - return Type{}, errors.New("invalid arg type in abi") - } - typ.stringKind = t - - // if there are brackets, get ready to go into slice/array mode and - // recursively create the type - if strings.Count(t, "[") != 0 { - // Note internalType can be empty here. - subInternal := internalType - if i := strings.LastIndex(internalType, "["); i != -1 { - subInternal = subInternal[:i] - } - // recursively embed the type - i := strings.LastIndex(t, "[") - embeddedType, err := NewType(t[:i], subInternal, components) - if err != nil { - return Type{}, err - } - // grab the last cell and create a type from there - sliced := t[i:] - // grab the slice size with regexp - re := regexp.MustCompile("[0-9]+") - intz := re.FindAllString(sliced, -1) - - if len(intz) == 0 { - // is a slice - typ.T = SliceTy - typ.Elem = &embeddedType - typ.stringKind = embeddedType.stringKind + sliced - } else if len(intz) == 1 { - // is an array - typ.T = ArrayTy - typ.Elem = &embeddedType - typ.Size, err = strconv.Atoi(intz[0]) - if err != nil { - return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) - } - typ.stringKind = embeddedType.stringKind + sliced - } else { - return Type{}, errors.New("invalid formatting of array type") - } - return typ, err - } - // parse the type and size of the abi-type. - matches := typeRegex.FindAllStringSubmatch(t, -1) - if len(matches) == 0 { - return Type{}, fmt.Errorf("invalid type '%v'", t) - } - parsedType := matches[0] - - // varSize is the size of the variable - var varSize int - if len(parsedType[3]) > 0 { - var err error - varSize, err = strconv.Atoi(parsedType[2]) - if err != nil { - return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err) - } - } else { - if parsedType[0] == "uint" || parsedType[0] == "int" { - // this should fail because it means that there's something wrong with - // the abi type (the compiler should always format it to the size...always) - return Type{}, fmt.Errorf("unsupported arg type: %s", t) - } - } - // varType is the parsed abi type - switch varType := parsedType[1]; varType { - case "int": - typ.Size = varSize - typ.T = IntTy - case "uint": - typ.Size = varSize - typ.T = UintTy - case "bool": - typ.T = BoolTy - case "address": - typ.Size = 20 - typ.T = AddressTy - case "string": - typ.T = StringTy - case "bytes": - if varSize == 0 { - typ.T = BytesTy - } else { - if varSize > 32 { - return Type{}, fmt.Errorf("unsupported arg type: %s", t) - } - typ.T = FixedBytesTy - typ.Size = varSize - } - case "tuple": - var ( - fields []reflect.StructField - elems []*Type - names []string - expression string // canonical parameter expression - used = make(map[string]bool) - ) - expression += "(" - for idx, c := range components { - cType, err := NewType(c.Type, c.InternalType, c.Components) - if err != nil { - return Type{}, err - } - name := ToCamelCase(c.Name) - if name == "" { - return Type{}, errors.New("abi: purely anonymous or underscored field is not supported") - } - fieldName := ResolveNameConflict(name, func(s string) bool { return used[s] }) - if err != nil { - return Type{}, err - } - used[fieldName] = true - if !isValidFieldName(fieldName) { - return Type{}, fmt.Errorf("field %d has invalid name", idx) - } - fields = append(fields, reflect.StructField{ - Name: fieldName, // reflect.StructOf will panic for any exported field. - Type: cType.GetType(), - Tag: reflect.StructTag("json:\"" + c.Name + "\""), - }) - elems = append(elems, &cType) - names = append(names, c.Name) - expression += cType.stringKind - if idx != len(components)-1 { - expression += "," - } - } - expression += ")" - - typ.TupleType = reflect.StructOf(fields) - typ.TupleElems = elems - typ.TupleRawNames = names - typ.T = TupleTy - typ.stringKind = expression - - const structPrefix = "struct " - // After solidity 0.5.10, a new field of abi "internalType" - // is introduced. From that we can obtain the struct name - // user defined in the source code. - if internalType != "" && strings.HasPrefix(internalType, structPrefix) { - // Foo.Bar type definition is not allowed in golang, - // convert the format to FooBar - typ.TupleRawName = strings.ReplaceAll(internalType[len(structPrefix):], ".", "") - } - - case "function": - typ.T = FunctionTy - typ.Size = 24 - default: - return Type{}, fmt.Errorf("unsupported arg type: %s", t) - } - - return -} - -// GetType returns the reflection type of the ABI type. -func (t Type) GetType() reflect.Type { - switch t.T { - case IntTy: - return reflectIntType(false, t.Size) - case UintTy: - return reflectIntType(true, t.Size) - case BoolTy: - return reflect.TypeOf(false) - case StringTy: - return reflect.TypeOf("") - case SliceTy: - return reflect.SliceOf(t.Elem.GetType()) - case ArrayTy: - return reflect.ArrayOf(t.Size, t.Elem.GetType()) - case TupleTy: - return t.TupleType - case AddressTy: - return reflect.TypeOf(common.Address{}) - case FixedBytesTy: - return reflect.ArrayOf(t.Size, reflect.TypeOf(byte(0))) - case BytesTy: - return reflect.SliceOf(reflect.TypeOf(byte(0))) - case HashTy: - // hashtype currently not used - return reflect.ArrayOf(32, reflect.TypeOf(byte(0))) - case FixedPointTy: - // fixedpoint type currently not used - return reflect.ArrayOf(32, reflect.TypeOf(byte(0))) - case FunctionTy: - return reflect.ArrayOf(24, reflect.TypeOf(byte(0))) - default: - panic("Invalid type") - } -} - -// String implements Stringer. -func (t Type) String() (out string) { - return t.stringKind -} - -func (t Type) pack(v reflect.Value) ([]byte, error) { - // dereference pointer first if it's a pointer - v = indirect(v) - if err := typeCheck(t, v); err != nil { - return nil, err - } - - switch t.T { - case SliceTy, ArrayTy: - var ret []byte - - if t.requiresLengthPrefix() { - // append length - ret = append(ret, packNum(reflect.ValueOf(v.Len()))...) - } - - // calculate offset if any - offset := 0 - offsetReq := isDynamicType(*t.Elem) - if offsetReq { - offset = getTypeSize(*t.Elem) * v.Len() - } - var tail []byte - for i := 0; i < v.Len(); i++ { - val, err := t.Elem.pack(v.Index(i)) - if err != nil { - return nil, err - } - if !offsetReq { - ret = append(ret, val...) - continue - } - ret = append(ret, packNum(reflect.ValueOf(offset))...) - offset += len(val) - tail = append(tail, val...) - } - return append(ret, tail...), nil - case TupleTy: - // (T1,...,Tk) for k >= 0 and any types T1, …, Tk - // enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k)) - // where X = (X(1), ..., X(k)) and head and tail are defined for Ti being a static - // type as - // head(X(i)) = enc(X(i)) and tail(X(i)) = "" (the empty string) - // and as - // head(X(i)) = enc(len(head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)))) - // tail(X(i)) = enc(X(i)) - // otherwise, i.e. if Ti is a dynamic type. - fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, v) - if err != nil { - return nil, err - } - // Calculate prefix occupied size. - offset := 0 - for _, elem := range t.TupleElems { - offset += getTypeSize(*elem) - } - var ret, tail []byte - for i, elem := range t.TupleElems { - field := v.FieldByName(fieldmap[t.TupleRawNames[i]]) - if !field.IsValid() { - return nil, fmt.Errorf("field %s for tuple not found in the given struct", t.TupleRawNames[i]) - } - val, err := elem.pack(field) - if err != nil { - return nil, err - } - if isDynamicType(*elem) { - ret = append(ret, packNum(reflect.ValueOf(offset))...) - tail = append(tail, val...) - offset += len(val) - } else { - ret = append(ret, val...) - } - } - return append(ret, tail...), nil - - default: - return packElement(t, v) - } -} - -// requiresLengthPrefix returns whether the type requires any sort of length -// prefixing. -func (t Type) requiresLengthPrefix() bool { - return t.T == StringTy || t.T == BytesTy || t.T == SliceTy -} - -// isDynamicType returns true if the type is dynamic. -// The following types are called “dynamicâ€: -// * bytes -// * string -// * T[] for any T -// * T[k] for any dynamic T and any k >= 0 -// * (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k -func isDynamicType(t Type) bool { - if t.T == TupleTy { - for _, elem := range t.TupleElems { - if isDynamicType(*elem) { - return true - } - } - return false - } - return t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && isDynamicType(*t.Elem)) -} - -// getTypeSize returns the size that this type needs to occupy. -// We distinguish static and dynamic types. Static types are encoded in-place -// and dynamic types are encoded at a separately allocated location after the -// current block. -// So for a static variable, the size returned represents the size that the -// variable actually occupies. -// For a dynamic variable, the returned size is fixed 32 bytes, which is used -// to store the location reference for actual value storage. -func getTypeSize(t Type) int { - if t.T == ArrayTy && !isDynamicType(*t.Elem) { - // Recursively calculate type size if it is a nested array - if t.Elem.T == ArrayTy || t.Elem.T == TupleTy { - return t.Size * getTypeSize(*t.Elem) - } - return t.Size * 32 - } else if t.T == TupleTy && !isDynamicType(t) { - total := 0 - for _, elem := range t.TupleElems { - total += getTypeSize(*elem) - } - return total - } - return 32 -} - -// isLetter reports whether a given 'rune' is classified as a Letter. -// This method is copied from reflect/type.go -func isLetter(ch rune) bool { - return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch) -} - -// isValidFieldName checks if a string is a valid (struct) field name or not. -// -// According to the language spec, a field name should be an identifier. -// -// identifier = letter { letter | unicode_digit } . -// letter = unicode_letter | "_" . -// This method is copied from reflect/type.go -func isValidFieldName(fieldName string) bool { - for i, c := range fieldName { - if i == 0 && !isLetter(c) { - return false - } - - if !(isLetter(c) || unicode.IsDigit(c)) { - return false - } - } - - return len(fieldName) > 0 -} diff --git a/builder/accounts/abi/type_test.go b/builder/accounts/abi/type_test.go deleted file mode 100644 index ae69872ad..000000000 --- a/builder/accounts/abi/type_test.go +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2016 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 abi - -import ( - "math/big" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/common" -) - -// typeWithoutStringer is a alias for the Type type which simply doesn't implement -// the stringer interface to allow printing type details in the tests below. -type typeWithoutStringer Type - -// Tests that all allowed types get recognized by the type parser. -func TestTypeRegexp(t *testing.T) { - t.Parallel() - tests := []struct { - blob string - components []ArgumentMarshaling - kind Type - }{ - {"bool", nil, Type{T: BoolTy, stringKind: "bool"}}, - {"bool[]", nil, Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}}, - {"bool[2]", nil, Type{Size: 2, T: ArrayTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}}, - {"bool[2][]", nil, Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}}, - {"bool[][]", nil, Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}}, - {"bool[][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}}, - {"bool[2][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}}, - {"bool[2][][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][]"}, stringKind: "bool[2][][2]"}}, - {"bool[2][2][2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[2]"}, stringKind: "bool[2][2]"}, stringKind: "bool[2][2][2]"}}, - {"bool[][][]", nil, Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][]"}, stringKind: "bool[][][]"}}, - {"bool[][2][]", nil, Type{T: SliceTy, Elem: &Type{T: ArrayTy, Size: 2, Elem: &Type{T: SliceTy, Elem: &Type{T: BoolTy, stringKind: "bool"}, stringKind: "bool[]"}, stringKind: "bool[][2]"}, stringKind: "bool[][2][]"}}, - {"int8", nil, Type{Size: 8, T: IntTy, stringKind: "int8"}}, - {"int16", nil, Type{Size: 16, T: IntTy, stringKind: "int16"}}, - {"int32", nil, Type{Size: 32, T: IntTy, stringKind: "int32"}}, - {"int64", nil, Type{Size: 64, T: IntTy, stringKind: "int64"}}, - {"int256", nil, Type{Size: 256, T: IntTy, stringKind: "int256"}}, - {"int8[]", nil, Type{T: SliceTy, Elem: &Type{Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[]"}}, - {"int8[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 8, T: IntTy, stringKind: "int8"}, stringKind: "int8[2]"}}, - {"int16[]", nil, Type{T: SliceTy, Elem: &Type{Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[]"}}, - {"int16[2]", nil, Type{Size: 2, T: ArrayTy, Elem: &Type{Size: 16, T: IntTy, stringKind: "int16"}, stringKind: "int16[2]"}}, - {"int32[]", nil, Type{T: SliceTy, Elem: &Type{Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}}, - {"int32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}}, - {"int64[]", nil, Type{T: SliceTy, Elem: &Type{Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[]"}}, - {"int64[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 64, T: IntTy, stringKind: "int64"}, stringKind: "int64[2]"}}, - {"int256[]", nil, Type{T: SliceTy, Elem: &Type{Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}}, - {"int256[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}}, - {"uint8", nil, Type{Size: 8, T: UintTy, stringKind: "uint8"}}, - {"uint16", nil, Type{Size: 16, T: UintTy, stringKind: "uint16"}}, - {"uint32", nil, Type{Size: 32, T: UintTy, stringKind: "uint32"}}, - {"uint64", nil, Type{Size: 64, T: UintTy, stringKind: "uint64"}}, - {"uint256", nil, Type{Size: 256, T: UintTy, stringKind: "uint256"}}, - {"uint8[]", nil, Type{T: SliceTy, Elem: &Type{Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[]"}}, - {"uint8[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 8, T: UintTy, stringKind: "uint8"}, stringKind: "uint8[2]"}}, - {"uint16[]", nil, Type{T: SliceTy, Elem: &Type{Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[]"}}, - {"uint16[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 16, T: UintTy, stringKind: "uint16"}, stringKind: "uint16[2]"}}, - {"uint32[]", nil, Type{T: SliceTy, Elem: &Type{Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}}, - {"uint32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}}, - {"uint64[]", nil, Type{T: SliceTy, Elem: &Type{Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[]"}}, - {"uint64[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 64, T: UintTy, stringKind: "uint64"}, stringKind: "uint64[2]"}}, - {"uint256[]", nil, Type{T: SliceTy, Elem: &Type{Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}}, - {"uint256[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}}, - {"bytes32", nil, Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}}, - {"bytes[]", nil, Type{T: SliceTy, Elem: &Type{T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}}, - {"bytes[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[2]"}}, - {"bytes32[]", nil, Type{T: SliceTy, Elem: &Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}, stringKind: "bytes32[]"}}, - {"bytes32[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: FixedBytesTy, Size: 32, stringKind: "bytes32"}, stringKind: "bytes32[2]"}}, - {"string", nil, Type{T: StringTy, stringKind: "string"}}, - {"string[]", nil, Type{T: SliceTy, Elem: &Type{T: StringTy, stringKind: "string"}, stringKind: "string[]"}}, - {"string[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{T: StringTy, stringKind: "string"}, stringKind: "string[2]"}}, - {"address", nil, Type{Size: 20, T: AddressTy, stringKind: "address"}}, - {"address[]", nil, Type{T: SliceTy, Elem: &Type{Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}}, - {"address[2]", nil, Type{T: ArrayTy, Size: 2, Elem: &Type{Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}}, - // TODO when fixed types are implemented properly - // {"fixed", nil, Type{}}, - // {"fixed128x128", nil, Type{}}, - // {"fixed[]", nil, Type{}}, - // {"fixed[2]", nil, Type{}}, - // {"fixed128x128[]", nil, Type{}}, - // {"fixed128x128[2]", nil, Type{}}, - {"tuple", []ArgumentMarshaling{{Name: "a", Type: "int64"}}, Type{T: TupleTy, TupleType: reflect.TypeOf(struct { - A int64 `json:"a"` - }{}), stringKind: "(int64)", - TupleElems: []*Type{{T: IntTy, Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"a"}}}, - {"tuple with long name", []ArgumentMarshaling{{Name: "aTypicalParamName", Type: "int64"}}, Type{T: TupleTy, TupleType: reflect.TypeOf(struct { - ATypicalParamName int64 `json:"aTypicalParamName"` - }{}), stringKind: "(int64)", - TupleElems: []*Type{{T: IntTy, Size: 64, stringKind: "int64"}}, TupleRawNames: []string{"aTypicalParamName"}}}, - } - - for _, tt := range tests { - typ, err := NewType(tt.blob, "", tt.components) - if err != nil { - t.Errorf("type %q: failed to parse type string: %v", tt.blob, err) - } - if !reflect.DeepEqual(typ, tt.kind) { - t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", tt.blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(tt.kind))) - } - } -} - -func TestTypeCheck(t *testing.T) { - t.Parallel() - for i, test := range []struct { - typ string - components []ArgumentMarshaling - input interface{} - err string - }{ - {"uint", nil, big.NewInt(1), "unsupported arg type: uint"}, - {"int", nil, big.NewInt(1), "unsupported arg type: int"}, - {"uint256", nil, big.NewInt(1), ""}, - {"uint256[][3][]", nil, [][3][]*big.Int{{{}}}, ""}, - {"uint256[][][3]", nil, [3][][]*big.Int{{{}}}, ""}, - {"uint256[3][][]", nil, [][][3]*big.Int{{{}}}, ""}, - {"uint256[3][3][3]", nil, [3][3][3]*big.Int{{{}}}, ""}, - {"uint8[][]", nil, [][]uint8{}, ""}, - {"int256", nil, big.NewInt(1), ""}, - {"uint8", nil, uint8(1), ""}, - {"uint16", nil, uint16(1), ""}, - {"uint32", nil, uint32(1), ""}, - {"uint64", nil, uint64(1), ""}, - {"int8", nil, int8(1), ""}, - {"int16", nil, int16(1), ""}, - {"int32", nil, int32(1), ""}, - {"int64", nil, int64(1), ""}, - {"uint24", nil, big.NewInt(1), ""}, - {"uint40", nil, big.NewInt(1), ""}, - {"uint48", nil, big.NewInt(1), ""}, - {"uint56", nil, big.NewInt(1), ""}, - {"uint72", nil, big.NewInt(1), ""}, - {"uint80", nil, big.NewInt(1), ""}, - {"uint88", nil, big.NewInt(1), ""}, - {"uint96", nil, big.NewInt(1), ""}, - {"uint104", nil, big.NewInt(1), ""}, - {"uint112", nil, big.NewInt(1), ""}, - {"uint120", nil, big.NewInt(1), ""}, - {"uint128", nil, big.NewInt(1), ""}, - {"uint136", nil, big.NewInt(1), ""}, - {"uint144", nil, big.NewInt(1), ""}, - {"uint152", nil, big.NewInt(1), ""}, - {"uint160", nil, big.NewInt(1), ""}, - {"uint168", nil, big.NewInt(1), ""}, - {"uint176", nil, big.NewInt(1), ""}, - {"uint184", nil, big.NewInt(1), ""}, - {"uint192", nil, big.NewInt(1), ""}, - {"uint200", nil, big.NewInt(1), ""}, - {"uint208", nil, big.NewInt(1), ""}, - {"uint216", nil, big.NewInt(1), ""}, - {"uint224", nil, big.NewInt(1), ""}, - {"uint232", nil, big.NewInt(1), ""}, - {"uint240", nil, big.NewInt(1), ""}, - {"uint248", nil, big.NewInt(1), ""}, - {"int24", nil, big.NewInt(1), ""}, - {"int40", nil, big.NewInt(1), ""}, - {"int48", nil, big.NewInt(1), ""}, - {"int56", nil, big.NewInt(1), ""}, - {"int72", nil, big.NewInt(1), ""}, - {"int80", nil, big.NewInt(1), ""}, - {"int88", nil, big.NewInt(1), ""}, - {"int96", nil, big.NewInt(1), ""}, - {"int104", nil, big.NewInt(1), ""}, - {"int112", nil, big.NewInt(1), ""}, - {"int120", nil, big.NewInt(1), ""}, - {"int128", nil, big.NewInt(1), ""}, - {"int136", nil, big.NewInt(1), ""}, - {"int144", nil, big.NewInt(1), ""}, - {"int152", nil, big.NewInt(1), ""}, - {"int160", nil, big.NewInt(1), ""}, - {"int168", nil, big.NewInt(1), ""}, - {"int176", nil, big.NewInt(1), ""}, - {"int184", nil, big.NewInt(1), ""}, - {"int192", nil, big.NewInt(1), ""}, - {"int200", nil, big.NewInt(1), ""}, - {"int208", nil, big.NewInt(1), ""}, - {"int216", nil, big.NewInt(1), ""}, - {"int224", nil, big.NewInt(1), ""}, - {"int232", nil, big.NewInt(1), ""}, - {"int240", nil, big.NewInt(1), ""}, - {"int248", nil, big.NewInt(1), ""}, - {"uint30", nil, uint8(1), "abi: cannot use uint8 as type ptr as argument"}, - {"uint8", nil, uint16(1), "abi: cannot use uint16 as type uint8 as argument"}, - {"uint8", nil, uint32(1), "abi: cannot use uint32 as type uint8 as argument"}, - {"uint8", nil, uint64(1), "abi: cannot use uint64 as type uint8 as argument"}, - {"uint8", nil, int8(1), "abi: cannot use int8 as type uint8 as argument"}, - {"uint8", nil, int16(1), "abi: cannot use int16 as type uint8 as argument"}, - {"uint8", nil, int32(1), "abi: cannot use int32 as type uint8 as argument"}, - {"uint8", nil, int64(1), "abi: cannot use int64 as type uint8 as argument"}, - {"uint16", nil, uint16(1), ""}, - {"uint16", nil, uint8(1), "abi: cannot use uint8 as type uint16 as argument"}, - {"uint16[]", nil, []uint16{1, 2, 3}, ""}, - {"uint16[]", nil, [3]uint16{1, 2, 3}, ""}, - {"uint16[]", nil, []uint32{1, 2, 3}, "abi: cannot use []uint32 as type [0]uint16 as argument"}, - {"uint16[3]", nil, [3]uint32{1, 2, 3}, "abi: cannot use [3]uint32 as type [3]uint16 as argument"}, - {"uint16[3]", nil, [4]uint16{1, 2, 3}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"}, - {"uint16[3]", nil, []uint16{1, 2, 3}, ""}, - {"uint16[3]", nil, []uint16{1, 2, 3, 4}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"}, - {"address[]", nil, []common.Address{{1}}, ""}, - {"address[1]", nil, []common.Address{{1}}, ""}, - {"address[1]", nil, [1]common.Address{{1}}, ""}, - {"address[2]", nil, [1]common.Address{{1}}, "abi: cannot use [1]array as type [2]array as argument"}, - {"bytes32", nil, [32]byte{}, ""}, - {"bytes31", nil, [31]byte{}, ""}, - {"bytes30", nil, [30]byte{}, ""}, - {"bytes29", nil, [29]byte{}, ""}, - {"bytes28", nil, [28]byte{}, ""}, - {"bytes27", nil, [27]byte{}, ""}, - {"bytes26", nil, [26]byte{}, ""}, - {"bytes25", nil, [25]byte{}, ""}, - {"bytes24", nil, [24]byte{}, ""}, - {"bytes23", nil, [23]byte{}, ""}, - {"bytes22", nil, [22]byte{}, ""}, - {"bytes21", nil, [21]byte{}, ""}, - {"bytes20", nil, [20]byte{}, ""}, - {"bytes19", nil, [19]byte{}, ""}, - {"bytes18", nil, [18]byte{}, ""}, - {"bytes17", nil, [17]byte{}, ""}, - {"bytes16", nil, [16]byte{}, ""}, - {"bytes15", nil, [15]byte{}, ""}, - {"bytes14", nil, [14]byte{}, ""}, - {"bytes13", nil, [13]byte{}, ""}, - {"bytes12", nil, [12]byte{}, ""}, - {"bytes11", nil, [11]byte{}, ""}, - {"bytes10", nil, [10]byte{}, ""}, - {"bytes9", nil, [9]byte{}, ""}, - {"bytes8", nil, [8]byte{}, ""}, - {"bytes7", nil, [7]byte{}, ""}, - {"bytes6", nil, [6]byte{}, ""}, - {"bytes5", nil, [5]byte{}, ""}, - {"bytes4", nil, [4]byte{}, ""}, - {"bytes3", nil, [3]byte{}, ""}, - {"bytes2", nil, [2]byte{}, ""}, - {"bytes1", nil, [1]byte{}, ""}, - {"bytes32", nil, [33]byte{}, "abi: cannot use [33]uint8 as type [32]uint8 as argument"}, - {"bytes32", nil, common.Hash{1}, ""}, - {"bytes31", nil, common.Hash{1}, "abi: cannot use common.Hash as type [31]uint8 as argument"}, - {"bytes31", nil, [32]byte{}, "abi: cannot use [32]uint8 as type [31]uint8 as argument"}, - {"bytes", nil, []byte{0, 1}, ""}, - {"bytes", nil, [2]byte{0, 1}, "abi: cannot use array as type slice as argument"}, - {"bytes", nil, common.Hash{1}, "abi: cannot use array as type slice as argument"}, - {"string", nil, "hello world", ""}, - {"string", nil, "", ""}, - {"string", nil, []byte{}, "abi: cannot use slice as type string as argument"}, - {"bytes32[]", nil, [][32]byte{{}}, ""}, - {"function", nil, [24]byte{}, ""}, - {"bytes20", nil, common.Address{}, ""}, - {"address", nil, [20]byte{}, ""}, - {"address", nil, common.Address{}, ""}, - {"bytes32[]]", nil, "", "invalid arg type in abi"}, - {"invalidType", nil, "", "unsupported arg type: invalidType"}, - {"invalidSlice[]", nil, "", "unsupported arg type: invalidSlice"}, - // simple tuple - {"tuple", []ArgumentMarshaling{{Name: "a", Type: "uint256"}, {Name: "b", Type: "uint256"}}, struct { - A *big.Int - B *big.Int - }{}, ""}, - // tuple slice - {"tuple[]", []ArgumentMarshaling{{Name: "a", Type: "uint256"}, {Name: "b", Type: "uint256"}}, []struct { - A *big.Int - B *big.Int - }{}, ""}, - // tuple array - {"tuple[2]", []ArgumentMarshaling{{Name: "a", Type: "uint256"}, {Name: "b", Type: "uint256"}}, []struct { - A *big.Int - B *big.Int - }{{big.NewInt(0), big.NewInt(0)}, {big.NewInt(0), big.NewInt(0)}}, ""}, - } { - typ, err := NewType(test.typ, "", test.components) - if err != nil && len(test.err) == 0 { - t.Fatal("unexpected parse error:", err) - } else if err != nil && len(test.err) != 0 { - if err.Error() != test.err { - t.Errorf("%d failed. Expected err: '%v' got err: '%v'", i, test.err, err) - } - continue - } - - err = typeCheck(typ, reflect.ValueOf(test.input)) - if err != nil && len(test.err) == 0 { - t.Errorf("%d failed. Expected no err but got: %v", i, err) - continue - } - if err == nil && len(test.err) != 0 { - t.Errorf("%d failed. Expected err: %v but got none", i, test.err) - continue - } - - if err != nil && len(test.err) != 0 && err.Error() != test.err { - t.Errorf("%d failed. Expected err: '%v' got err: '%v'", i, test.err, err) - } - } -} - -func TestInternalType(t *testing.T) { - t.Parallel() - components := []ArgumentMarshaling{{Name: "a", Type: "int64"}} - internalType := "struct a.b[]" - kind := Type{ - T: TupleTy, - TupleType: reflect.TypeOf(struct { - A int64 `json:"a"` - }{}), - stringKind: "(int64)", - TupleRawName: "ab[]", - TupleElems: []*Type{{T: IntTy, Size: 64, stringKind: "int64"}}, - TupleRawNames: []string{"a"}, - } - - blob := "tuple" - typ, err := NewType(blob, internalType, components) - if err != nil { - t.Errorf("type %q: failed to parse type string: %v", blob, err) - } - if !reflect.DeepEqual(typ, kind) { - t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(kind))) - } -} - -func TestGetTypeSize(t *testing.T) { - t.Parallel() - var testCases = []struct { - typ string - components []ArgumentMarshaling - typSize int - }{ - // simple array - {"uint256[2]", nil, 32 * 2}, - {"address[3]", nil, 32 * 3}, - {"bytes32[4]", nil, 32 * 4}, - // array array - {"uint256[2][3][4]", nil, 32 * (2 * 3 * 4)}, - // array tuple - {"tuple[2]", []ArgumentMarshaling{{Name: "x", Type: "bytes32"}, {Name: "y", Type: "bytes32"}}, (32 * 2) * 2}, - // simple tuple - {"tuple", []ArgumentMarshaling{{Name: "x", Type: "uint256"}, {Name: "y", Type: "uint256"}}, 32 * 2}, - // tuple array - {"tuple", []ArgumentMarshaling{{Name: "x", Type: "bytes32[2]"}}, 32 * 2}, - // tuple tuple - {"tuple", []ArgumentMarshaling{{Name: "x", Type: "tuple", Components: []ArgumentMarshaling{{Name: "x", Type: "bytes32"}}}}, 32}, - {"tuple", []ArgumentMarshaling{{Name: "x", Type: "tuple", Components: []ArgumentMarshaling{{Name: "x", Type: "bytes32[2]"}, {Name: "y", Type: "uint256"}}}}, 32 * (2 + 1)}, - } - - for i, data := range testCases { - typ, err := NewType(data.typ, "", data.components) - if err != nil { - t.Errorf("type %q: failed to parse type string: %v", data.typ, err) - } - - result := getTypeSize(typ) - if result != data.typSize { - t.Errorf("case %d type %q: get type size error: actual: %d expected: %d", i, data.typ, result, data.typSize) - } - } -} - -func TestNewFixedBytesOver32(t *testing.T) { - t.Parallel() - _, err := NewType("bytes4096", "", nil) - if err == nil { - t.Errorf("fixed bytes with size over 32 is not spec'd") - } -} diff --git a/builder/accounts/abi/unpack.go b/builder/accounts/abi/unpack.go deleted file mode 100644 index 905b5ce62..000000000 --- a/builder/accounts/abi/unpack.go +++ /dev/null @@ -1,329 +0,0 @@ -// 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 abi - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/common" -) - -var ( - // MaxUint256 is the maximum value that can be represented by a uint256. - MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1) - // MaxInt256 is the maximum value that can be represented by a int256. - MaxInt256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 255), common.Big1) -) - -// ReadInteger reads the integer based on its kind and returns the appropriate value. -func ReadInteger(typ Type, b []byte) (interface{}, error) { - ret := new(big.Int).SetBytes(b) - - if typ.T == UintTy { - u64, isu64 := ret.Uint64(), ret.IsUint64() - switch typ.Size { - case 8: - if !isu64 || u64 > math.MaxUint8 { - return nil, errBadUint8 - } - return byte(u64), nil - case 16: - if !isu64 || u64 > math.MaxUint16 { - return nil, errBadUint16 - } - return uint16(u64), nil - case 32: - if !isu64 || u64 > math.MaxUint32 { - return nil, errBadUint32 - } - return uint32(u64), nil - case 64: - if !isu64 { - return nil, errBadUint64 - } - return u64, nil - default: - // the only case left for unsigned integer is uint256. - return ret, nil - } - } - - // big.SetBytes can't tell if a number is negative or positive in itself. - // On EVM, if the returned number > max int256, it is negative. - // A number is > max int256 if the bit at position 255 is set. - if ret.Bit(255) == 1 { - ret.Add(MaxUint256, new(big.Int).Neg(ret)) - ret.Add(ret, common.Big1) - ret.Neg(ret) - } - i64, isi64 := ret.Int64(), ret.IsInt64() - switch typ.Size { - case 8: - if !isi64 || i64 < math.MinInt8 || i64 > math.MaxInt8 { - return nil, errBadInt8 - } - return int8(i64), nil - case 16: - if !isi64 || i64 < math.MinInt16 || i64 > math.MaxInt16 { - return nil, errBadInt16 - } - return int16(i64), nil - case 32: - if !isi64 || i64 < math.MinInt32 || i64 > math.MaxInt32 { - return nil, errBadInt32 - } - return int32(i64), nil - case 64: - if !isi64 { - return nil, errBadInt64 - } - return i64, nil - default: - // the only case left for integer is int256 - - return ret, nil - } -} - -// readBool reads a bool. -func readBool(word []byte) (bool, error) { - for _, b := range word[:31] { - if b != 0 { - return false, errBadBool - } - } - switch word[31] { - case 0: - return false, nil - case 1: - return true, nil - default: - return false, errBadBool - } -} - -// A function type is simply the address with the function selection signature at the end. -// -// readFunctionType enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes) -func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { - if t.T != FunctionTy { - return [24]byte{}, errors.New("abi: invalid type in call to make function type byte array") - } - if garbage := binary.BigEndian.Uint64(word[24:32]); garbage != 0 { - err = fmt.Errorf("abi: got improperly encoded function type, got %v", word) - } else { - copy(funcTy[:], word[0:24]) - } - return -} - -// ReadFixedBytes uses reflection to create a fixed array to be read from. -func ReadFixedBytes(t Type, word []byte) (interface{}, error) { - if t.T != FixedBytesTy { - return nil, errors.New("abi: invalid type in call to make fixed byte array") - } - // convert - array := reflect.New(t.GetType()).Elem() - - reflect.Copy(array, reflect.ValueOf(word[0:t.Size])) - return array.Interface(), nil -} - -// forEachUnpack iteratively unpack elements. -func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) { - if size < 0 { - return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size) - } - if start+32*size > len(output) { - return nil, fmt.Errorf("abi: cannot marshal into go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size) - } - - // this value will become our slice or our array, depending on the type - var refSlice reflect.Value - - switch t.T { - case SliceTy: - // declare our slice - refSlice = reflect.MakeSlice(t.GetType(), size, size) - case ArrayTy: - // declare our array - refSlice = reflect.New(t.GetType()).Elem() - default: - return nil, errors.New("abi: invalid type in array/slice unpacking stage") - } - - // Arrays have packed elements, resulting in longer unpack steps. - // Slices have just 32 bytes per element (pointing to the contents). - elemSize := getTypeSize(*t.Elem) - - for i, j := start, 0; j < size; i, j = i+elemSize, j+1 { - inter, err := toGoType(i, *t.Elem, output) - if err != nil { - return nil, err - } - - // append the item to our reflect slice - refSlice.Index(j).Set(reflect.ValueOf(inter)) - } - - // return the interface - return refSlice.Interface(), nil -} - -func forTupleUnpack(t Type, output []byte) (interface{}, error) { - retval := reflect.New(t.GetType()).Elem() - virtualArgs := 0 - for index, elem := range t.TupleElems { - marshalledValue, err := toGoType((index+virtualArgs)*32, *elem, output) - if err != nil { - return nil, err - } - if elem.T == ArrayTy && !isDynamicType(*elem) { - // If we have a static array, like [3]uint256, these are coded as - // just like uint256,uint256,uint256. - // This means that we need to add two 'virtual' arguments when - // we count the index from now on. - // - // Array values nested multiple levels deep are also encoded inline: - // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256 - // - // Calculate the full array size to get the correct offset for the next argument. - // Decrement it by 1, as the normal index increment is still applied. - virtualArgs += getTypeSize(*elem)/32 - 1 - } else if elem.T == TupleTy && !isDynamicType(*elem) { - // If we have a static tuple, like (uint256, bool, uint256), these are - // coded as just like uint256,bool,uint256 - virtualArgs += getTypeSize(*elem)/32 - 1 - } - retval.Field(index).Set(reflect.ValueOf(marshalledValue)) - } - return retval.Interface(), nil -} - -// toGoType parses the output bytes and recursively assigns the value of these bytes -// into a go type with accordance with the ABI spec. -func toGoType(index int, t Type, output []byte) (interface{}, error) { - if index+32 > len(output) { - return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32) - } - - var ( - returnOutput []byte - begin, length int - err error - ) - - // if we require a length prefix, find the beginning word and size returned. - if t.requiresLengthPrefix() { - begin, length, err = lengthPrefixPointsTo(index, output) - if err != nil { - return nil, err - } - } else { - returnOutput = output[index : index+32] - } - - switch t.T { - case TupleTy: - if isDynamicType(t) { - begin, err := tuplePointsTo(index, output) - if err != nil { - return nil, err - } - return forTupleUnpack(t, output[begin:]) - } - return forTupleUnpack(t, output[index:]) - case SliceTy: - return forEachUnpack(t, output[begin:], 0, length) - case ArrayTy: - if isDynamicType(*t.Elem) { - offset := binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:]) - if offset > uint64(len(output)) { - return nil, fmt.Errorf("abi: toGoType offset greater than output length: offset: %d, len(output): %d", offset, len(output)) - } - return forEachUnpack(t, output[offset:], 0, t.Size) - } - return forEachUnpack(t, output[index:], 0, t.Size) - case StringTy: // variable arrays are written at the end of the return bytes - return string(output[begin : begin+length]), nil - case IntTy, UintTy: - return ReadInteger(t, returnOutput) - case BoolTy: - return readBool(returnOutput) - case AddressTy: - return common.BytesToAddress(returnOutput), nil - case HashTy: - return common.BytesToHash(returnOutput), nil - case BytesTy: - return output[begin : begin+length], nil - case FixedBytesTy: - return ReadFixedBytes(t, returnOutput) - case FunctionTy: - return readFunctionType(t, returnOutput) - default: - return nil, fmt.Errorf("abi: unknown type %v", t.T) - } -} - -// lengthPrefixPointsTo interprets a 32 byte slice as an offset and then determines which indices to look to decode the type. -func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) { - bigOffsetEnd := new(big.Int).SetBytes(output[index : index+32]) - bigOffsetEnd.Add(bigOffsetEnd, common.Big32) - outputLength := big.NewInt(int64(len(output))) - - if bigOffsetEnd.Cmp(outputLength) > 0 { - return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength) - } - - if bigOffsetEnd.BitLen() > 63 { - return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd) - } - - offsetEnd := int(bigOffsetEnd.Uint64()) - lengthBig := new(big.Int).SetBytes(output[offsetEnd-32 : offsetEnd]) - - totalSize := new(big.Int).Add(bigOffsetEnd, lengthBig) - if totalSize.BitLen() > 63 { - return 0, 0, fmt.Errorf("abi: length larger than int64: %v", totalSize) - } - - if totalSize.Cmp(outputLength) > 0 { - return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize) - } - start = int(bigOffsetEnd.Uint64()) - length = int(lengthBig.Uint64()) - return -} - -// tuplePointsTo resolves the location reference for dynamic tuple. -func tuplePointsTo(index int, output []byte) (start int, err error) { - offset := new(big.Int).SetBytes(output[index : index+32]) - outputLen := big.NewInt(int64(len(output))) - - if offset.Cmp(outputLen) > 0 { - return 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", offset, outputLen) - } - if offset.BitLen() > 63 { - return 0, fmt.Errorf("abi offset larger than int64: %v", offset) - } - return int(offset.Uint64()), nil -} diff --git a/builder/accounts/abi/unpack_test.go b/builder/accounts/abi/unpack_test.go deleted file mode 100644 index 29891ec0a..000000000 --- a/builder/accounts/abi/unpack_test.go +++ /dev/null @@ -1,1119 +0,0 @@ -// 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 abi - -import ( - "bytes" - "encoding/hex" - "fmt" - "math" - "math/big" - "reflect" - "strconv" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" -) - -// TestUnpack tests the general pack/unpack tests in packing_test.go -func TestUnpack(t *testing.T) { - t.Parallel() - for i, test := range packUnpackTests { - t.Run(strconv.Itoa(i)+" "+test.def, func(t *testing.T) { - //Unpack - def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) - abi, err := JSON(strings.NewReader(def)) - if err != nil { - t.Fatalf("invalid ABI definition %s: %v", def, err) - } - encb, err := hex.DecodeString(test.packed) - if err != nil { - t.Fatalf("invalid hex %s: %v", test.packed, err) - } - out, err := abi.Unpack("method", encb) - if err != nil { - t.Errorf("test %d (%v) failed: %v", i, test.def, err) - return - } - if !reflect.DeepEqual(test.unpacked, ConvertType(out[0], test.unpacked)) { - t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.unpacked, out[0]) - } - }) - } -} - -type unpackTest struct { - def string // ABI definition JSON - enc string // evm return data - want interface{} // the expected output - err string // empty or error if expected -} - -func (test unpackTest) checkError(err error) error { - if err != nil { - if len(test.err) == 0 { - return fmt.Errorf("expected no err but got: %v", err) - } else if err.Error() != test.err { - return fmt.Errorf("expected err: '%v' got err: %q", test.err, err) - } - } else if len(test.err) > 0 { - return fmt.Errorf("expected err: %v but got none", test.err) - } - return nil -} - -var unpackTests = []unpackTest{ - // Bools - { - def: `[{ "type": "bool" }]`, - enc: "0000000000000000000000000000000000000000000000000001000000000001", - want: false, - err: "abi: improperly encoded boolean value", - }, - { - def: `[{ "type": "bool" }]`, - enc: "0000000000000000000000000000000000000000000000000000000000000003", - want: false, - err: "abi: improperly encoded boolean value", - }, - // Integers - { - def: `[{"type": "uint32"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000001", - want: uint16(0), - err: "abi: cannot unmarshal uint32 in to uint16", - }, - { - def: `[{"type": "uint17"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000001", - want: uint16(0), - err: "abi: cannot unmarshal *big.Int in to uint16", - }, - { - def: `[{"type": "int32"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000001", - want: int16(0), - err: "abi: cannot unmarshal int32 in to int16", - }, - { - def: `[{"type": "int17"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000001", - want: int16(0), - err: "abi: cannot unmarshal *big.Int in to int16", - }, - { - def: `[{"type": "bytes"}]`, - enc: "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000", - want: [32]byte{1}, - }, - { - def: `[{"type": "bytes32"}]`, - enc: "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200100000000000000000000000000000000000000000000000000000000000000", - want: []byte(nil), - err: "abi: cannot unmarshal [32]uint8 in to []uint8", - }, - { - def: `[{"name":"___","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - IntOne *big.Int - Intone *big.Int - }{IntOne: big.NewInt(1)}, - }, - { - def: `[{"name":"int_one","type":"int256"},{"name":"IntOne","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - Int1 *big.Int - Int2 *big.Int - }{}, - err: "abi: multiple outputs mapping to the same struct field 'IntOne'", - }, - { - def: `[{"name":"int","type":"int256"},{"name":"Int","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - Int1 *big.Int - Int2 *big.Int - }{}, - err: "abi: multiple outputs mapping to the same struct field 'Int'", - }, - { - def: `[{"name":"int","type":"int256"},{"name":"_int","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - Int1 *big.Int - Int2 *big.Int - }{}, - err: "abi: multiple outputs mapping to the same struct field 'Int'", - }, - { - def: `[{"name":"Int","type":"int256"},{"name":"_int","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - Int1 *big.Int - Int2 *big.Int - }{}, - err: "abi: multiple outputs mapping to the same struct field 'Int'", - }, - { - def: `[{"name":"Int","type":"int256"},{"name":"_","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - Int1 *big.Int - Int2 *big.Int - }{}, - err: "abi: purely underscored output cannot unpack to struct", - }, - // Make sure only the first argument is consumed - { - def: `[{"name":"int_one","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"name":"int__one","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"name":"int_one_","type":"int256"}]`, - enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - want: struct { - IntOne *big.Int - }{big.NewInt(1)}, - }, - { - def: `[{"type":"bool"}]`, - enc: "", - want: false, - err: "abi: attempting to unmarshal an empty string while arguments are expected", - }, - { - def: `[{"type":"bytes32","indexed":true},{"type":"uint256","indexed":false}]`, - enc: "", - want: false, - err: "abi: attempting to unmarshal an empty string while arguments are expected", - }, - { - def: `[{"type":"bool","indexed":true},{"type":"uint64","indexed":true}]`, - enc: "", - want: false, - }, -} - -// TestLocalUnpackTests runs test specially designed only for unpacking. -// All test cases that can be used to test packing and unpacking should move to packing_test.go -func TestLocalUnpackTests(t *testing.T) { - t.Parallel() - for i, test := range unpackTests { - t.Run(strconv.Itoa(i), func(t *testing.T) { - //Unpack - def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) - abi, err := JSON(strings.NewReader(def)) - if err != nil { - t.Fatalf("invalid ABI definition %s: %v", def, err) - } - encb, err := hex.DecodeString(test.enc) - if err != nil { - t.Fatalf("invalid hex %s: %v", test.enc, err) - } - outptr := reflect.New(reflect.TypeOf(test.want)) - err = abi.UnpackIntoInterface(outptr.Interface(), "method", encb) - if err := test.checkError(err); err != nil { - t.Errorf("test %d (%v) failed: %v", i, test.def, err) - return - } - out := outptr.Elem().Interface() - if !reflect.DeepEqual(test.want, out) { - t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.want, out) - } - }) - } -} - -func TestUnpackIntoInterfaceSetDynamicArrayOutput(t *testing.T) { - t.Parallel() - abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`)) - if err != nil { - t.Fatal(err) - } - - var ( - marshalledReturn32 = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000230783132333435363738393000000000000000000000000000000000000000003078303938373635343332310000000000000000000000000000000000000000") - marshalledReturn15 = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000230783031323334350000000000000000000000000000000000000000000000003078393837363534000000000000000000000000000000000000000000000000") - - out32 [][32]byte - out15 [][15]byte - ) - - // test 32 - err = abi.UnpackIntoInterface(&out32, "testDynamicFixedBytes32", marshalledReturn32) - if err != nil { - t.Fatal(err) - } - if len(out32) != 2 { - t.Fatalf("expected array with 2 values, got %d", len(out32)) - } - expected := common.Hex2Bytes("3078313233343536373839300000000000000000000000000000000000000000") - if !bytes.Equal(out32[0][:], expected) { - t.Errorf("expected %x, got %x\n", expected, out32[0]) - } - expected = common.Hex2Bytes("3078303938373635343332310000000000000000000000000000000000000000") - if !bytes.Equal(out32[1][:], expected) { - t.Errorf("expected %x, got %x\n", expected, out32[1]) - } - - // test 15 - err = abi.UnpackIntoInterface(&out15, "testDynamicFixedBytes32", marshalledReturn15) - if err != nil { - t.Fatal(err) - } - if len(out15) != 2 { - t.Fatalf("expected array with 2 values, got %d", len(out15)) - } - expected = common.Hex2Bytes("307830313233343500000000000000") - if !bytes.Equal(out15[0][:], expected) { - t.Errorf("expected %x, got %x\n", expected, out15[0]) - } - expected = common.Hex2Bytes("307839383736353400000000000000") - if !bytes.Equal(out15[1][:], expected) { - t.Errorf("expected %x, got %x\n", expected, out15[1]) - } -} - -type methodMultiOutput struct { - Int *big.Int - String string -} - -func methodMultiReturn(require *require.Assertions) (ABI, []byte, methodMultiOutput) { - const definition = `[ - { "name" : "multi", "type": "function", "outputs": [ { "name": "Int", "type": "uint256" }, { "name": "String", "type": "string" } ] }]` - var expected = methodMultiOutput{big.NewInt(1), "hello"} - - abi, err := JSON(strings.NewReader(definition)) - require.NoError(err) - // using buff to make the code readable - buff := new(bytes.Buffer) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000005")) - buff.Write(common.RightPadBytes([]byte(expected.String), 32)) - return abi, buff.Bytes(), expected -} - -func TestMethodMultiReturn(t *testing.T) { - t.Parallel() - type reversed struct { - String string - Int *big.Int - } - - newInterfaceSlice := func(len int) interface{} { - slice := make([]interface{}, len) - return &slice - } - - abi, data, expected := methodMultiReturn(require.New(t)) - bigint := new(big.Int) - var testCases = []struct { - dest interface{} - expected interface{} - error string - name string - }{{ - &methodMultiOutput{}, - &expected, - "", - "Can unpack into structure", - }, { - &reversed{}, - &reversed{expected.String, expected.Int}, - "", - "Can unpack into reversed structure", - }, { - &[]interface{}{&bigint, new(string)}, - &[]interface{}{&expected.Int, &expected.String}, - "", - "Can unpack into a slice", - }, { - &[]interface{}{&bigint, ""}, - &[]interface{}{&expected.Int, expected.String}, - "", - "Can unpack into a slice without indirection", - }, { - &[2]interface{}{&bigint, new(string)}, - &[2]interface{}{&expected.Int, &expected.String}, - "", - "Can unpack into an array", - }, { - &[2]interface{}{}, - &[2]interface{}{expected.Int, expected.String}, - "", - "Can unpack into interface array", - }, { - newInterfaceSlice(2), - &[]interface{}{expected.Int, expected.String}, - "", - "Can unpack into interface slice", - }, { - &[]interface{}{new(int), new(int)}, - &[]interface{}{&expected.Int, &expected.String}, - "abi: cannot unmarshal *big.Int in to int", - "Can not unpack into a slice with wrong types", - }, { - &[]interface{}{new(int)}, - &[]interface{}{}, - "abi: insufficient number of arguments for unpack, want 2, got 1", - "Can not unpack into a slice with wrong types", - }} - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - require := require.New(t) - err := abi.UnpackIntoInterface(tc.dest, "multi", data) - if tc.error == "" { - require.Nil(err, "Should be able to unpack method outputs.") - require.Equal(tc.expected, tc.dest) - } else { - require.EqualError(err, tc.error) - } - }) - } -} - -func TestMultiReturnWithArray(t *testing.T) { - t.Parallel() - const definition = `[{"name" : "multi", "type": "function", "outputs": [{"type": "uint64[3]"}, {"type": "uint64"}]}]` - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000008")) - - ret1, ret1Exp := new([3]uint64), [3]uint64{9, 9, 9} - ret2, ret2Exp := new(uint64), uint64(8) - if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(*ret1, ret1Exp) { - t.Error("array result", *ret1, "!= Expected", ret1Exp) - } - if *ret2 != ret2Exp { - t.Error("int result", *ret2, "!= Expected", ret2Exp) - } -} - -func TestMultiReturnWithStringArray(t *testing.T) { - t.Parallel() - const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "uint256[3]"},{"name": "","type": "address"},{"name": "","type": "string[2]"},{"name": "","type": "bool"}]}]` - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000005c1b78ea0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000001a055690d9db80000000000000000000000000000ab1257528b3782fb40d7ed5f72e624b744dffb2f00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000008457468657265756d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001048656c6c6f2c20457468657265756d2100000000000000000000000000000000")) - temp, _ := new(big.Int).SetString("30000000000000000000", 10) - ret1, ret1Exp := new([3]*big.Int), [3]*big.Int{big.NewInt(1545304298), big.NewInt(6), temp} - ret2, ret2Exp := new(common.Address), common.HexToAddress("ab1257528b3782fb40d7ed5f72e624b744dffb2f") - ret3, ret3Exp := new([2]string), [2]string{"Ethereum", "Hello, Ethereum!"} - ret4, ret4Exp := new(bool), false - if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2, ret3, ret4}, "multi", buff.Bytes()); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(*ret1, ret1Exp) { - t.Error("big.Int array result", *ret1, "!= Expected", ret1Exp) - } - if !reflect.DeepEqual(*ret2, ret2Exp) { - t.Error("address result", *ret2, "!= Expected", ret2Exp) - } - if !reflect.DeepEqual(*ret3, ret3Exp) { - t.Error("string array result", *ret3, "!= Expected", ret3Exp) - } - if !reflect.DeepEqual(*ret4, ret4Exp) { - t.Error("bool result", *ret4, "!= Expected", ret4Exp) - } -} - -func TestMultiReturnWithStringSlice(t *testing.T) { - t.Parallel() - const definition = `[{"name" : "multi", "type": "function", "outputs": [{"name": "","type": "string[]"},{"name": "","type": "uint256[]"}]}]` - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) // output[0] offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000120")) // output[1] offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // output[0] length - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) // output[0][0] offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000080")) // output[0][1] offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000008")) // output[0][0] length - buff.Write(common.Hex2Bytes("657468657265756d000000000000000000000000000000000000000000000000")) // output[0][0] value - buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000b")) // output[0][1] length - buff.Write(common.Hex2Bytes("676f2d657468657265756d000000000000000000000000000000000000000000")) // output[0][1] value - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // output[1] length - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000064")) // output[1][0] value - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000065")) // output[1][1] value - ret1, ret1Exp := new([]string), []string{"ethereum", "go-ethereum"} - ret2, ret2Exp := new([]*big.Int), []*big.Int{big.NewInt(100), big.NewInt(101)} - if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(*ret1, ret1Exp) { - t.Error("string slice result", *ret1, "!= Expected", ret1Exp) - } - if !reflect.DeepEqual(*ret2, ret2Exp) { - t.Error("uint256 slice result", *ret2, "!= Expected", ret2Exp) - } -} - -func TestMultiReturnWithDeeplyNestedArray(t *testing.T) { - t.Parallel() - // Similar to TestMultiReturnWithArray, but with a special case in mind: - // values of nested static arrays count towards the size as well, and any element following - // after such nested array argument should be read with the correct offset, - // so that it does not read content from the previous array argument. - const definition = `[{"name" : "multi", "type": "function", "outputs": [{"type": "uint64[3][2][4]"}, {"type": "uint64"}]}]` - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - // construct the test array, each 3 char element is joined with 61 '0' chars, - // to from the ((3 + 61) * 0.5) = 32 byte elements in the array. - buff.Write(common.Hex2Bytes(strings.Join([]string{ - "", //empty, to apply the 61-char separator to the first element as well. - "111", "112", "113", "121", "122", "123", - "211", "212", "213", "221", "222", "223", - "311", "312", "313", "321", "322", "323", - "411", "412", "413", "421", "422", "423", - }, "0000000000000000000000000000000000000000000000000000000000000"))) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000009876")) - - ret1, ret1Exp := new([4][2][3]uint64), [4][2][3]uint64{ - {{0x111, 0x112, 0x113}, {0x121, 0x122, 0x123}}, - {{0x211, 0x212, 0x213}, {0x221, 0x222, 0x223}}, - {{0x311, 0x312, 0x313}, {0x321, 0x322, 0x323}}, - {{0x411, 0x412, 0x413}, {0x421, 0x422, 0x423}}, - } - ret2, ret2Exp := new(uint64), uint64(0x9876) - if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(*ret1, ret1Exp) { - t.Error("array result", *ret1, "!= Expected", ret1Exp) - } - if *ret2 != ret2Exp { - t.Error("int result", *ret2, "!= Expected", ret2Exp) - } -} - -func TestUnmarshal(t *testing.T) { - t.Parallel() - const definition = `[ - { "name" : "int", "type": "function", "outputs": [ { "type": "uint256" } ] }, - { "name" : "bool", "type": "function", "outputs": [ { "type": "bool" } ] }, - { "name" : "bytes", "type": "function", "outputs": [ { "type": "bytes" } ] }, - { "name" : "fixed", "type": "function", "outputs": [ { "type": "bytes32" } ] }, - { "name" : "multi", "type": "function", "outputs": [ { "type": "bytes" }, { "type": "bytes" } ] }, - { "name" : "intArraySingle", "type": "function", "outputs": [ { "type": "uint256[3]" } ] }, - { "name" : "addressSliceSingle", "type": "function", "outputs": [ { "type": "address[]" } ] }, - { "name" : "addressSliceDouble", "type": "function", "outputs": [ { "name": "a", "type": "address[]" }, { "name": "b", "type": "address[]" } ] }, - { "name" : "mixedBytes", "type": "function", "stateMutability" : "view", "outputs": [ { "name": "a", "type": "bytes" }, { "name": "b", "type": "bytes32" } ] }]` - - abi, err := JSON(strings.NewReader(definition)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - - // marshall mixed bytes (mixedBytes) - p0, p0Exp := []byte{}, common.Hex2Bytes("01020000000000000000") - p1, p1Exp := [32]byte{}, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000ddeeff") - mixedBytes := []interface{}{&p0, &p1} - - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000ddeeff")) - buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000a")) - buff.Write(common.Hex2Bytes("0102000000000000000000000000000000000000000000000000000000000000")) - - err = abi.UnpackIntoInterface(&mixedBytes, "mixedBytes", buff.Bytes()) - if err != nil { - t.Error(err) - } else { - if !bytes.Equal(p0, p0Exp) { - t.Errorf("unexpected value unpacked: want %x, got %x", p0Exp, p0) - } - - if !bytes.Equal(p1[:], p1Exp) { - t.Errorf("unexpected value unpacked: want %x, got %x", p1Exp, p1) - } - } - - // marshal int - var Int *big.Int - err = abi.UnpackIntoInterface(&Int, "int", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) - if err != nil { - t.Error(err) - } - - if Int == nil || Int.Cmp(big.NewInt(1)) != 0 { - t.Error("expected Int to be 1 got", Int) - } - - // marshal bool - var Bool bool - err = abi.UnpackIntoInterface(&Bool, "bool", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) - if err != nil { - t.Error(err) - } - - if !Bool { - t.Error("expected Bool to be true") - } - - // marshal dynamic bytes max length 32 - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - bytesOut := common.RightPadBytes([]byte("hello"), 32) - buff.Write(bytesOut) - - var Bytes []byte - err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes()) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(Bytes, bytesOut) { - t.Errorf("expected %x got %x", bytesOut, Bytes) - } - - // marshall dynamic bytes max length 64 - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) - bytesOut = common.RightPadBytes([]byte("hello"), 64) - buff.Write(bytesOut) - - err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes()) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(Bytes, bytesOut) { - t.Errorf("expected %x got %x", bytesOut, Bytes) - } - - // marshall dynamic bytes max length 64 - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000003f")) - bytesOut = common.RightPadBytes([]byte("hello"), 64) - buff.Write(bytesOut) - - err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes()) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(Bytes, bytesOut[:len(bytesOut)-1]) { - t.Errorf("expected %x got %x", bytesOut[:len(bytesOut)-1], Bytes) - } - - // marshal dynamic bytes output empty - err = abi.UnpackIntoInterface(&Bytes, "bytes", nil) - if err == nil { - t.Error("expected error") - } - - // marshal dynamic bytes length 5 - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000005")) - buff.Write(common.RightPadBytes([]byte("hello"), 32)) - - err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes()) - if err != nil { - t.Error(err) - } - - if !bytes.Equal(Bytes, []byte("hello")) { - t.Errorf("expected %x got %x", bytesOut, Bytes) - } - - // marshal dynamic bytes length 5 - buff.Reset() - buff.Write(common.RightPadBytes([]byte("hello"), 32)) - - var hash common.Hash - err = abi.UnpackIntoInterface(&hash, "fixed", buff.Bytes()) - if err != nil { - t.Error(err) - } - - helloHash := common.BytesToHash(common.RightPadBytes([]byte("hello"), 32)) - if hash != helloHash { - t.Errorf("Expected %x to equal %x", hash, helloHash) - } - - // marshal error - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) - err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes()) - if err == nil { - t.Error("expected error") - } - - err = abi.UnpackIntoInterface(&Bytes, "multi", make([]byte, 64)) - if err == nil { - t.Error("expected error") - } - - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003")) - // marshal int array - var intArray [3]*big.Int - err = abi.UnpackIntoInterface(&intArray, "intArraySingle", buff.Bytes()) - if err != nil { - t.Error(err) - } - var testAgainstIntArray [3]*big.Int - testAgainstIntArray[0] = big.NewInt(1) - testAgainstIntArray[1] = big.NewInt(2) - testAgainstIntArray[2] = big.NewInt(3) - - for i, Int := range intArray { - if Int.Cmp(testAgainstIntArray[i]) != 0 { - t.Errorf("expected %v, got %v", testAgainstIntArray[i], Int) - } - } - // marshal address slice - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) // offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // size - buff.Write(common.Hex2Bytes("0000000000000000000000000100000000000000000000000000000000000000")) - - var outAddr []common.Address - err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes()) - if err != nil { - t.Fatal("didn't expect error:", err) - } - - if len(outAddr) != 1 { - t.Fatal("expected 1 item, got", len(outAddr)) - } - - if outAddr[0] != (common.Address{1}) { - t.Errorf("expected %x, got %x", common.Address{1}, outAddr[0]) - } - - // marshal multiple address slice - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")) // offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000080")) // offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // size - buff.Write(common.Hex2Bytes("0000000000000000000000000100000000000000000000000000000000000000")) - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // size - buff.Write(common.Hex2Bytes("0000000000000000000000000200000000000000000000000000000000000000")) - buff.Write(common.Hex2Bytes("0000000000000000000000000300000000000000000000000000000000000000")) - - var outAddrStruct struct { - A []common.Address - B []common.Address - } - err = abi.UnpackIntoInterface(&outAddrStruct, "addressSliceDouble", buff.Bytes()) - if err != nil { - t.Fatal("didn't expect error:", err) - } - - if len(outAddrStruct.A) != 1 { - t.Fatal("expected 1 item, got", len(outAddrStruct.A)) - } - - if outAddrStruct.A[0] != (common.Address{1}) { - t.Errorf("expected %x, got %x", common.Address{1}, outAddrStruct.A[0]) - } - - if len(outAddrStruct.B) != 2 { - t.Fatal("expected 1 item, got", len(outAddrStruct.B)) - } - - if outAddrStruct.B[0] != (common.Address{2}) { - t.Errorf("expected %x, got %x", common.Address{2}, outAddrStruct.B[0]) - } - if outAddrStruct.B[1] != (common.Address{3}) { - t.Errorf("expected %x, got %x", common.Address{3}, outAddrStruct.B[1]) - } - - // marshal invalid address slice - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000100")) - - err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes()) - if err == nil { - t.Fatal("expected error:", err) - } -} - -func TestUnpackTuple(t *testing.T) { - t.Parallel() - const simpleTuple = `[{"name":"tuple","type":"function","outputs":[{"type":"tuple","name":"ret","components":[{"type":"int256","name":"a"},{"type":"int256","name":"b"}]}]}]` - abi, err := JSON(strings.NewReader(simpleTuple)) - if err != nil { - t.Fatal(err) - } - buff := new(bytes.Buffer) - - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // ret[a] = 1 - buff.Write(common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) // ret[b] = -1 - - // If the result is single tuple, use struct as return value container directly. - type v struct { - A *big.Int - B *big.Int - } - type r struct { - Result v - } - var ret0 = new(r) - err = abi.UnpackIntoInterface(ret0, "tuple", buff.Bytes()) - - if err != nil { - t.Error(err) - } else { - if ret0.Result.A.Cmp(big.NewInt(1)) != 0 { - t.Errorf("unexpected value unpacked: want %x, got %x", 1, ret0.Result.A) - } - if ret0.Result.B.Cmp(big.NewInt(-1)) != 0 { - t.Errorf("unexpected value unpacked: want %x, got %x", -1, ret0.Result.B) - } - } - - // Test nested tuple - const nestedTuple = `[{"name":"tuple","type":"function","outputs":[ - {"type":"tuple","name":"s","components":[{"type":"uint256","name":"a"},{"type":"uint256[]","name":"b"},{"type":"tuple[]","name":"c","components":[{"name":"x", "type":"uint256"},{"name":"y","type":"uint256"}]}]}, - {"type":"tuple","name":"t","components":[{"name":"x", "type":"uint256"},{"name":"y","type":"uint256"}]}, - {"type":"uint256","name":"a"} - ]}]` - - abi, err = JSON(strings.NewReader(nestedTuple)) - if err != nil { - t.Fatal(err) - } - buff.Reset() - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000080")) // s offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")) // t.X = 0 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // t.Y = 1 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // a = 1 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // s.A = 1 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060")) // s.B offset - buff.Write(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000c0")) // s.C offset - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // s.B length - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // s.B[0] = 1 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // s.B[0] = 2 - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // s.C length - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // s.C[0].X - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // s.C[0].Y - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002")) // s.C[1].X - buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) // s.C[1].Y - - type T struct { - X *big.Int `abi:"x"` - Z *big.Int `abi:"y"` // Test whether the abi tag works. - } - - type S struct { - A *big.Int - B []*big.Int - C []T - } - - type Ret struct { - FieldS S `abi:"s"` - FieldT T `abi:"t"` - A *big.Int - } - var ret Ret - var expected = Ret{ - FieldS: S{ - A: big.NewInt(1), - B: []*big.Int{big.NewInt(1), big.NewInt(2)}, - C: []T{ - {big.NewInt(1), big.NewInt(2)}, - {big.NewInt(2), big.NewInt(1)}, - }, - }, - FieldT: T{ - big.NewInt(0), big.NewInt(1), - }, - A: big.NewInt(1), - } - - err = abi.UnpackIntoInterface(&ret, "tuple", buff.Bytes()) - if err != nil { - t.Error(err) - } - if reflect.DeepEqual(ret, expected) { - t.Error("unexpected unpack value") - } -} - -func TestOOMMaliciousInput(t *testing.T) { - t.Parallel() - oomTests := []unpackTest{ - { - def: `[{"type": "uint8[]"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset - "0000000000000000000000000000000000000000000000000000000000000003" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - { // Length larger than 64 bits - def: `[{"type": "uint8[]"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset - "00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - { // Offset very large (over 64 bits) - def: `[{"type": "uint8[]"}]`, - enc: "00ffffffffffffffffffffffffffffffffffffffffffffff0000000000000020" + // offset - "0000000000000000000000000000000000000000000000000000000000000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - { // Offset very large (below 64 bits) - def: `[{"type": "uint8[]"}]`, - enc: "0000000000000000000000000000000000000000000000007ffffffffff00020" + // offset - "0000000000000000000000000000000000000000000000000000000000000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - { // Offset negative (as 64 bit) - def: `[{"type": "uint8[]"}]`, - enc: "000000000000000000000000000000000000000000000000f000000000000020" + // offset - "0000000000000000000000000000000000000000000000000000000000000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - - { // Negative length - def: `[{"type": "uint8[]"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset - "000000000000000000000000000000000000000000000000f000000000000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - { // Very large length - def: `[{"type": "uint8[]"}]`, - enc: "0000000000000000000000000000000000000000000000000000000000000020" + // offset - "0000000000000000000000000000000000000000000000007fffffffff000002" + // num elems - "0000000000000000000000000000000000000000000000000000000000000001" + // elem 1 - "0000000000000000000000000000000000000000000000000000000000000002", // elem 2 - }, - } - for i, test := range oomTests { - def := fmt.Sprintf(`[{ "name" : "method", "type": "function", "outputs": %s}]`, test.def) - abi, err := JSON(strings.NewReader(def)) - if err != nil { - t.Fatalf("invalid ABI definition %s: %v", def, err) - } - encb, err := hex.DecodeString(test.enc) - if err != nil { - t.Fatalf("invalid hex: %s" + test.enc) - } - _, err = abi.Methods["method"].Outputs.UnpackValues(encb) - if err == nil { - t.Fatalf("Expected error on malicious input, test %d", i) - } - } -} - -func TestPackAndUnpackIncompatibleNumber(t *testing.T) { - t.Parallel() - var encodeABI Arguments - uint256Ty, err := NewType("uint256", "", nil) - if err != nil { - panic(err) - } - encodeABI = Arguments{ - {Type: uint256Ty}, - } - - maxU64, ok := new(big.Int).SetString(strconv.FormatUint(math.MaxUint64, 10), 10) - if !ok { - panic("bug") - } - maxU64Plus1 := new(big.Int).Add(maxU64, big.NewInt(1)) - cases := []struct { - decodeType string - inputValue *big.Int - err error - expectValue interface{} - }{ - { - decodeType: "uint8", - inputValue: big.NewInt(math.MaxUint8 + 1), - err: errBadUint8, - }, - { - decodeType: "uint8", - inputValue: big.NewInt(math.MaxUint8), - err: nil, - expectValue: uint8(math.MaxUint8), - }, - { - decodeType: "uint16", - inputValue: big.NewInt(math.MaxUint16 + 1), - err: errBadUint16, - }, - { - decodeType: "uint16", - inputValue: big.NewInt(math.MaxUint16), - err: nil, - expectValue: uint16(math.MaxUint16), - }, - { - decodeType: "uint32", - inputValue: big.NewInt(math.MaxUint32 + 1), - err: errBadUint32, - }, - { - decodeType: "uint32", - inputValue: big.NewInt(math.MaxUint32), - err: nil, - expectValue: uint32(math.MaxUint32), - }, - { - decodeType: "uint64", - inputValue: maxU64Plus1, - err: errBadUint64, - }, - { - decodeType: "uint64", - inputValue: maxU64, - err: nil, - expectValue: uint64(math.MaxUint64), - }, - { - decodeType: "uint256", - inputValue: maxU64Plus1, - err: nil, - expectValue: maxU64Plus1, - }, - { - decodeType: "int8", - inputValue: big.NewInt(math.MaxInt8 + 1), - err: errBadInt8, - }, - { - decodeType: "int8", - inputValue: big.NewInt(math.MinInt8 - 1), - err: errBadInt8, - }, - { - decodeType: "int8", - inputValue: big.NewInt(math.MaxInt8), - err: nil, - expectValue: int8(math.MaxInt8), - }, - { - decodeType: "int16", - inputValue: big.NewInt(math.MaxInt16 + 1), - err: errBadInt16, - }, - { - decodeType: "int16", - inputValue: big.NewInt(math.MinInt16 - 1), - err: errBadInt16, - }, - { - decodeType: "int16", - inputValue: big.NewInt(math.MaxInt16), - err: nil, - expectValue: int16(math.MaxInt16), - }, - { - decodeType: "int32", - inputValue: big.NewInt(math.MaxInt32 + 1), - err: errBadInt32, - }, - { - decodeType: "int32", - inputValue: big.NewInt(math.MinInt32 - 1), - err: errBadInt32, - }, - { - decodeType: "int32", - inputValue: big.NewInt(math.MaxInt32), - err: nil, - expectValue: int32(math.MaxInt32), - }, - { - decodeType: "int64", - inputValue: new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)), - err: errBadInt64, - }, - { - decodeType: "int64", - inputValue: new(big.Int).Sub(big.NewInt(math.MinInt64), big.NewInt(1)), - err: errBadInt64, - }, - { - decodeType: "int64", - inputValue: big.NewInt(math.MaxInt64), - err: nil, - expectValue: int64(math.MaxInt64), - }, - } - for i, testCase := range cases { - packed, err := encodeABI.Pack(testCase.inputValue) - if err != nil { - panic(err) - } - ty, err := NewType(testCase.decodeType, "", nil) - if err != nil { - panic(err) - } - decodeABI := Arguments{ - {Type: ty}, - } - decoded, err := decodeABI.Unpack(packed) - if err != testCase.err { - t.Fatalf("Expected error %v, actual error %v. case %d", testCase.err, err, i) - } - if err != nil { - continue - } - if !reflect.DeepEqual(decoded[0], testCase.expectValue) { - t.Fatalf("Expected value %v, actual value %v", testCase.expectValue, decoded[0]) - } - } -} diff --git a/builder/accounts/abi/utils.go b/builder/accounts/abi/utils.go deleted file mode 100644 index b1537ca58..000000000 --- a/builder/accounts/abi/utils.go +++ /dev/null @@ -1,40 +0,0 @@ -// 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 abi - -import "fmt" - -// ResolveNameConflict returns the next available name for a given thing. -// This helper can be used for lots of purposes: -// -// - In solidity function overloading is supported, this function can fix -// the name conflicts of overloaded functions. -// - In golang binding generation, the parameter(in function, event, error, -// and struct definition) name will be converted to camelcase style which -// may eventually lead to name conflicts. -// -// Name conflicts are mostly resolved by adding number suffix. e.g. if the abi contains -// Methods "send" and "send1", ResolveNameConflict would return "send2" for input "send". -func ResolveNameConflict(rawName string, used func(string) bool) string { - name := rawName - ok := used(name) - for idx := 0; ok; idx++ { - name = fmt.Sprintf("%s%d", rawName, idx) - ok = used(name) - } - return name -} diff --git a/builder/accounts/accounts.go b/builder/accounts/accounts.go deleted file mode 100644 index 6c351a964..000000000 --- a/builder/accounts/accounts.go +++ /dev/null @@ -1,226 +0,0 @@ -// 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 accounts implements high level Ethereum account management. -package accounts - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "golang.org/x/crypto/sha3" -) - -// Account represents an Ethereum account located at a specific location defined -// by the optional URL field. -type Account struct { - Address common.Address `json:"address"` // Ethereum account address derived from the key - URL URL `json:"url"` // Optional resource locator within a backend -} - -const ( - MimetypeDataWithValidator = "data/validator" - MimetypeTypedData = "data/typed" - MimetypeClique = "application/x-clique-header" - MimetypeTextPlain = "text/plain" -) - -// Wallet represents a software or hardware wallet that might contain one or more -// accounts (derived from the same seed). -type Wallet interface { - // URL retrieves the canonical path under which this wallet is reachable. It is - // used by upper layers to define a sorting order over all wallets from multiple - // backends. - URL() URL - - // Status returns a textual status to aid the user in the current state of the - // wallet. It also returns an error indicating any failure the wallet might have - // encountered. - Status() (string, error) - - // Open initializes access to a wallet instance. It is not meant to unlock or - // decrypt account keys, rather simply to establish a connection to hardware - // wallets and/or to access derivation seeds. - // - // The passphrase parameter may or may not be used by the implementation of a - // particular wallet instance. The reason there is no passwordless open method - // is to strive towards a uniform wallet handling, oblivious to the different - // backend providers. - // - // Please note, if you open a wallet, you must close it to release any allocated - // resources (especially important when working with hardware wallets). - Open(passphrase string) error - - // Close releases any resources held by an open wallet instance. - Close() error - - // Accounts retrieves the list of signing accounts the wallet is currently aware - // of. For hierarchical deterministic wallets, the list will not be exhaustive, - // rather only contain the accounts explicitly pinned during account derivation. - Accounts() []Account - - // Contains returns whether an account is part of this particular wallet or not. - Contains(account Account) bool - - // Derive attempts to explicitly derive a hierarchical deterministic account at - // the specified derivation path. If requested, the derived account will be added - // to the wallet's tracked account list. - Derive(path DerivationPath, pin bool) (Account, error) - - // SelfDerive sets a base account derivation path from which the wallet attempts - // to discover non zero accounts and automatically add them to list of tracked - // accounts. - // - // Note, self derivation will increment the last component of the specified path - // opposed to descending into a child path to allow discovering accounts starting - // from non zero components. - // - // Some hardware wallets switched derivation paths through their evolution, so - // this method supports providing multiple bases to discover old user accounts - // too. Only the last base will be used to derive the next empty account. - // - // You can disable automatic account discovery by calling SelfDerive with a nil - // chain state reader. - SelfDerive(bases []DerivationPath, chain ethereum.ChainStateReader) - - // SignData requests the wallet to sign the hash of the given data - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. - // - // If the wallet requires additional authentication to sign the request (e.g. - // a password to decrypt the account, or a PIN code to verify the transaction), - // an AuthNeededError instance will be returned, containing infos for the user - // about which fields or actions are needed. The user may retry by providing - // the needed details via SignDataWithPassphrase, or by other means (e.g. unlock - // the account in a keystore). - SignData(account Account, mimeType string, data []byte) ([]byte, error) - - // SignDataWithPassphrase is identical to SignData, but also takes a password - // NOTE: there's a chance that an erroneous call might mistake the two strings, and - // supply password in the mimetype field, or vice versa. Thus, an implementation - // should never echo the mimetype or return the mimetype in the error-response - SignDataWithPassphrase(account Account, passphrase, mimeType string, data []byte) ([]byte, error) - - // SignText requests the wallet to sign the hash of a given piece of data, prefixed - // by the Ethereum prefix scheme - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. - // - // If the wallet requires additional authentication to sign the request (e.g. - // a password to decrypt the account, or a PIN code to verify the transaction), - // an AuthNeededError instance will be returned, containing infos for the user - // about which fields or actions are needed. The user may retry by providing - // the needed details via SignTextWithPassphrase, or by other means (e.g. unlock - // the account in a keystore). - // - // This method should return the signature in 'canonical' format, with v 0 or 1. - SignText(account Account, text []byte) ([]byte, error) - - // SignTextWithPassphrase is identical to Signtext, but also takes a password - SignTextWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error) - - // SignTx requests the wallet to sign the given transaction. - // - // It looks up the account specified either solely via its address contained within, - // or optionally with the aid of any location metadata from the embedded URL field. - // - // If the wallet requires additional authentication to sign the request (e.g. - // a password to decrypt the account, or a PIN code to verify the transaction), - // an AuthNeededError instance will be returned, containing infos for the user - // about which fields or actions are needed. The user may retry by providing - // the needed details via SignTxWithPassphrase, or by other means (e.g. unlock - // the account in a keystore). - SignTx(account Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) - - // SignTxWithPassphrase is identical to SignTx, but also takes a password - SignTxWithPassphrase(account Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) -} - -// Backend is a "wallet provider" that may contain a batch of accounts they can -// sign transactions with and upon request, do so. -type Backend interface { - // Wallets retrieves the list of wallets the backend is currently aware of. - // - // The returned wallets are not opened by default. For software HD wallets this - // means that no base seeds are decrypted, and for hardware wallets that no actual - // connection is established. - // - // The resulting wallet list will be sorted alphabetically based on its internal - // URL assigned by the backend. Since wallets (especially hardware) may come and - // go, the same wallet might appear at a different positions in the list during - // subsequent retrievals. - Wallets() []Wallet - - // Subscribe creates an async subscription to receive notifications when the - // backend detects the arrival or departure of a wallet. - Subscribe(sink chan<- WalletEvent) event.Subscription -} - -// TextHash is a helper function that calculates a hash for the given message that can be -// safely used to calculate a signature from. -// -// The hash is calculated as -// -// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). -// -// This gives context to the signed message and prevents signing of transactions. -func TextHash(data []byte) []byte { - hash, _ := TextAndHash(data) - return hash -} - -// TextAndHash is a helper function that calculates a hash for the given message that can be -// safely used to calculate a signature from. -// -// The hash is calculated as -// -// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}). -// -// This gives context to the signed message and prevents signing of transactions. -func TextAndHash(data []byte) ([]byte, string) { - msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data)) - hasher := sha3.NewLegacyKeccak256() - hasher.Write([]byte(msg)) - return hasher.Sum(nil), msg -} - -// WalletEventType represents the different event types that can be fired by -// the wallet subscription subsystem. -type WalletEventType int - -const ( - // WalletArrived is fired when a new wallet is detected either via USB or via - // a filesystem event in the keystore. - WalletArrived WalletEventType = iota - - // WalletOpened is fired when a wallet is successfully opened with the purpose - // of starting any background processes such as automatic key derivation. - WalletOpened - - // WalletDropped - WalletDropped -) - -// WalletEvent is an event fired by an account backend when a wallet arrival or -// departure is detected. -type WalletEvent struct { - Wallet Wallet // Wallet instance arrived or departed - Kind WalletEventType // Event type that happened in the system -} diff --git a/builder/accounts/accounts_test.go b/builder/accounts/accounts_test.go deleted file mode 100644 index 2c4138aa7..000000000 --- a/builder/accounts/accounts_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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 accounts - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -func TestTextHash(t *testing.T) { - t.Parallel() - hash := TextHash([]byte("Hello Joe")) - want := hexutil.MustDecode("0xa080337ae51c4e064c189e113edd0ba391df9206e2f49db658bb32cf2911730b") - if !bytes.Equal(hash, want) { - t.Fatalf("wrong hash: %x", hash) - } -} diff --git a/builder/accounts/errors.go b/builder/accounts/errors.go deleted file mode 100644 index 03cb569eb..000000000 --- a/builder/accounts/errors.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 accounts - -import ( - "errors" - "fmt" -) - -// ErrUnknownAccount is returned for any requested operation for which no backend -// provides the specified account. -var ErrUnknownAccount = errors.New("unknown account") - -// ErrUnknownWallet is returned for any requested operation for which no backend -// provides the specified wallet. -var ErrUnknownWallet = errors.New("unknown wallet") - -// ErrNotSupported is returned when an operation is requested from an account -// backend that it does not support. -var ErrNotSupported = errors.New("not supported") - -// ErrInvalidPassphrase is returned when a decryption operation receives a bad -// passphrase. -var ErrInvalidPassphrase = errors.New("invalid password") - -// ErrWalletAlreadyOpen is returned if a wallet is attempted to be opened the -// second time. -var ErrWalletAlreadyOpen = errors.New("wallet already open") - -// ErrWalletClosed is returned if a wallet is offline. -var ErrWalletClosed = errors.New("wallet closed") - -// AuthNeededError is returned by backends for signing requests where the user -// is required to provide further authentication before signing can succeed. -// -// This usually means either that a password needs to be supplied, or perhaps a -// one time PIN code displayed by some hardware device. -type AuthNeededError struct { - Needed string // Extra authentication the user needs to provide -} - -// NewAuthNeededError creates a new authentication error with the extra details -// about the needed fields set. -func NewAuthNeededError(needed string) error { - return &AuthNeededError{ - Needed: needed, - } -} - -// Error implements the standard error interface. -func (err *AuthNeededError) Error() string { - return fmt.Sprintf("authentication needed: %s", err.Needed) -} diff --git a/builder/accounts/external/backend.go b/builder/accounts/external/backend.go deleted file mode 100644 index 6f1581f9b..000000000 --- a/builder/accounts/external/backend.go +++ /dev/null @@ -1,270 +0,0 @@ -// 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 external - -import ( - "errors" - "fmt" - "math/big" - "sync" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/signer/core/apitypes" -) - -type ExternalBackend struct { - signers []accounts.Wallet -} - -func (eb *ExternalBackend) Wallets() []accounts.Wallet { - return eb.signers -} - -func NewExternalBackend(endpoint string) (*ExternalBackend, error) { - signer, err := NewExternalSigner(endpoint) - if err != nil { - return nil, err - } - return &ExternalBackend{ - signers: []accounts.Wallet{signer}, - }, nil -} - -func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { - return event.NewSubscription(func(quit <-chan struct{}) error { - <-quit - return nil - }) -} - -// ExternalSigner provides an API to interact with an external signer (clef) -// It proxies request to the external signer while forwarding relevant -// request headers -type ExternalSigner struct { - client *rpc.Client - endpoint string - status string - cacheMu sync.RWMutex - cache []accounts.Account -} - -func NewExternalSigner(endpoint string) (*ExternalSigner, error) { - client, err := rpc.Dial(endpoint) - if err != nil { - return nil, err - } - extsigner := &ExternalSigner{ - client: client, - endpoint: endpoint, - } - // Check if reachable - version, err := extsigner.pingVersion() - if err != nil { - return nil, err - } - extsigner.status = fmt.Sprintf("ok [version=%v]", version) - return extsigner, nil -} - -func (api *ExternalSigner) URL() accounts.URL { - return accounts.URL{ - Scheme: "extapi", - Path: api.endpoint, - } -} - -func (api *ExternalSigner) Status() (string, error) { - return api.status, nil -} - -func (api *ExternalSigner) Open(passphrase string) error { - return errors.New("operation not supported on external signers") -} - -func (api *ExternalSigner) Close() error { - return errors.New("operation not supported on external signers") -} - -func (api *ExternalSigner) Accounts() []accounts.Account { - var accnts []accounts.Account - res, err := api.listAccounts() - if err != nil { - log.Error("account listing failed", "error", err) - return accnts - } - for _, addr := range res { - accnts = append(accnts, accounts.Account{ - URL: accounts.URL{ - Scheme: "extapi", - Path: api.endpoint, - }, - Address: addr, - }) - } - api.cacheMu.Lock() - api.cache = accnts - api.cacheMu.Unlock() - return accnts -} - -func (api *ExternalSigner) Contains(account accounts.Account) bool { - api.cacheMu.RLock() - defer api.cacheMu.RUnlock() - if api.cache == nil { - // If we haven't already fetched the accounts, it's time to do so now - api.cacheMu.RUnlock() - api.Accounts() - api.cacheMu.RLock() - } - for _, a := range api.cache { - if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) { - return true - } - } - return false -} - -func (api *ExternalSigner) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { - return accounts.Account{}, errors.New("operation not supported on external signers") -} - -func (api *ExternalSigner) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { - log.Error("operation SelfDerive not supported on external signers") -} - -// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed -func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - var res hexutil.Bytes - var signAddress = common.NewMixedcaseAddress(account.Address) - if err := api.client.Call(&res, "account_signData", - mimeType, - &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined - hexutil.Encode(data)); err != nil { - return nil, err - } - // If V is on 27/28-form, convert to 0/1 for Clique - if mimeType == accounts.MimetypeClique && (res[64] == 27 || res[64] == 28) { - res[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use - } - return res, nil -} - -func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) { - var signature hexutil.Bytes - var signAddress = common.NewMixedcaseAddress(account.Address) - if err := api.client.Call(&signature, "account_signData", - accounts.MimetypeTextPlain, - &signAddress, // Need to use the pointer here, because of how MarshalJSON is defined - hexutil.Encode(text)); err != nil { - return nil, err - } - if signature[64] == 27 || signature[64] == 28 { - // If clef is used as a backend, it may already have transformed - // the signature to ethereum-type signature. - signature[64] -= 27 // Transform V from Ethereum-legacy to 0/1 - } - return signature, nil -} - -// signTransactionResult represents the signinig result returned by clef. -type signTransactionResult struct { - Raw hexutil.Bytes `json:"raw"` - Tx *types.Transaction `json:"tx"` -} - -// SignTx sends the transaction to the external signer. -// If chainID is nil, or tx.ChainID is zero, the chain ID will be assigned -// by the external signer. For non-legacy transactions, the chain ID of the -// transaction overrides the chainID parameter. -func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - data := hexutil.Bytes(tx.Data()) - var to *common.MixedcaseAddress - if tx.To() != nil { - t := common.NewMixedcaseAddress(*tx.To()) - to = &t - } - args := &apitypes.SendTxArgs{ - Data: &data, - Nonce: hexutil.Uint64(tx.Nonce()), - Value: hexutil.Big(*tx.Value()), - Gas: hexutil.Uint64(tx.Gas()), - To: to, - From: common.NewMixedcaseAddress(account.Address), - } - switch tx.Type() { - case types.LegacyTxType, types.AccessListTxType: - args.GasPrice = (*hexutil.Big)(tx.GasPrice()) - case types.DynamicFeeTxType: - args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) - args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) - default: - return nil, fmt.Errorf("unsupported tx type %d", tx.Type()) - } - // We should request the default chain id that we're operating with - // (the chain we're executing on) - if chainID != nil && chainID.Sign() != 0 { - args.ChainID = (*hexutil.Big)(chainID) - } - if tx.Type() != types.LegacyTxType { - // However, if the user asked for a particular chain id, then we should - // use that instead. - if tx.ChainId().Sign() != 0 { - args.ChainID = (*hexutil.Big)(tx.ChainId()) - } - accessList := tx.AccessList() - args.AccessList = &accessList - } - var res signTransactionResult - if err := api.client.Call(&res, "account_signTransaction", args); err != nil { - return nil, err - } - return res.Tx, nil -} - -func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { - return []byte{}, errors.New("password-operations not supported on external signers") -} - -func (api *ExternalSigner) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - return nil, errors.New("password-operations not supported on external signers") -} -func (api *ExternalSigner) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { - return nil, errors.New("password-operations not supported on external signers") -} - -func (api *ExternalSigner) listAccounts() ([]common.Address, error) { - var res []common.Address - if err := api.client.Call(&res, "account_list"); err != nil { - return nil, err - } - return res, nil -} - -func (api *ExternalSigner) pingVersion() (string, error) { - var v string - if err := api.client.Call(&v, "account_version"); err != nil { - return "", err - } - return v, nil -} diff --git a/builder/accounts/hd.go b/builder/accounts/hd.go deleted file mode 100644 index daca75ebb..000000000 --- a/builder/accounts/hd.go +++ /dev/null @@ -1,180 +0,0 @@ -// 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 accounts - -import ( - "encoding/json" - "errors" - "fmt" - "math" - "math/big" - "strings" -) - -// DefaultRootDerivationPath is the root path to which custom derivation endpoints -// are appended. As such, the first account will be at m/44'/60'/0'/0, the second -// at m/44'/60'/0'/1, etc. -var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0} - -// DefaultBaseDerivationPath is the base path from which custom derivation endpoints -// are incremented. As such, the first account will be at m/44'/60'/0'/0/0, the second -// at m/44'/60'/0'/0/1, etc. -var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0} - -// LegacyLedgerBaseDerivationPath is the legacy base path from which custom derivation -// endpoints are incremented. As such, the first account will be at m/44'/60'/0'/0, the -// second at m/44'/60'/0'/1, etc. -var LegacyLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0} - -// DerivationPath represents the computer friendly version of a hierarchical -// deterministic wallet account derivation path. -// -// The BIP-32 spec https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -// defines derivation paths to be of the form: -// -// m / purpose' / coin_type' / account' / change / address_index -// -// The BIP-44 spec https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki -// defines that the `purpose` be 44' (or 0x8000002C) for crypto currencies, and -// SLIP-44 https://github.com/satoshilabs/slips/blob/master/slip-0044.md assigns -// the `coin_type` 60' (or 0x8000003C) to Ethereum. -// -// The root path for Ethereum is m/44'/60'/0'/0 according to the specification -// from https://github.com/ethereum/EIPs/issues/84, albeit it's not set in stone -// yet whether accounts should increment the last component or the children of -// that. We will go with the simpler approach of incrementing the last component. -type DerivationPath []uint32 - -// ParseDerivationPath converts a user specified derivation path string to the -// internal binary representation. -// -// Full derivation paths need to start with the `m/` prefix, relative derivation -// paths (which will get appended to the default root path) must not have prefixes -// in front of the first element. Whitespace is ignored. -func ParseDerivationPath(path string) (DerivationPath, error) { - var result DerivationPath - - // Handle absolute or relative paths - components := strings.Split(path, "/") - switch { - case len(components) == 0: - return nil, errors.New("empty derivation path") - - case strings.TrimSpace(components[0]) == "": - return nil, errors.New("ambiguous path: use 'm/' prefix for absolute paths, or no leading '/' for relative ones") - - case strings.TrimSpace(components[0]) == "m": - components = components[1:] - - default: - result = append(result, DefaultRootDerivationPath...) - } - // All remaining components are relative, append one by one - if len(components) == 0 { - return nil, errors.New("empty derivation path") // Empty relative paths - } - for _, component := range components { - // Ignore any user added whitespace - component = strings.TrimSpace(component) - var value uint32 - - // Handle hardened paths - if strings.HasSuffix(component, "'") { - value = 0x80000000 - component = strings.TrimSpace(strings.TrimSuffix(component, "'")) - } - // Handle the non hardened component - bigval, ok := new(big.Int).SetString(component, 0) - if !ok { - return nil, fmt.Errorf("invalid component: %s", component) - } - max := math.MaxUint32 - value - if bigval.Sign() < 0 || bigval.Cmp(big.NewInt(int64(max))) > 0 { - if value == 0 { - return nil, fmt.Errorf("component %v out of allowed range [0, %d]", bigval, max) - } - return nil, fmt.Errorf("component %v out of allowed hardened range [0, %d]", bigval, max) - } - value += uint32(bigval.Uint64()) - - // Append and repeat - result = append(result, value) - } - return result, nil -} - -// String implements the stringer interface, converting a binary derivation path -// to its canonical representation. -func (path DerivationPath) String() string { - result := "m" - for _, component := range path { - var hardened bool - if component >= 0x80000000 { - component -= 0x80000000 - hardened = true - } - result = fmt.Sprintf("%s/%d", result, component) - if hardened { - result += "'" - } - } - return result -} - -// MarshalJSON turns a derivation path into its json-serialized string -func (path DerivationPath) MarshalJSON() ([]byte, error) { - return json.Marshal(path.String()) -} - -// UnmarshalJSON a json-serialized string back into a derivation path -func (path *DerivationPath) UnmarshalJSON(b []byte) error { - var dp string - var err error - if err = json.Unmarshal(b, &dp); err != nil { - return err - } - *path, err = ParseDerivationPath(dp) - return err -} - -// DefaultIterator creates a BIP-32 path iterator, which progresses by increasing the last component: -// i.e. m/44'/60'/0'/0/0, m/44'/60'/0'/0/1, m/44'/60'/0'/0/2, ... m/44'/60'/0'/0/N. -func DefaultIterator(base DerivationPath) func() DerivationPath { - path := make(DerivationPath, len(base)) - copy(path[:], base[:]) - // Set it back by one, so the first call gives the first result - path[len(path)-1]-- - return func() DerivationPath { - path[len(path)-1]++ - return path - } -} - -// LedgerLiveIterator creates a bip44 path iterator for Ledger Live. -// Ledger Live increments the third component rather than the fifth component -// i.e. m/44'/60'/0'/0/0, m/44'/60'/1'/0/0, m/44'/60'/2'/0/0, ... m/44'/60'/N'/0/0. -func LedgerLiveIterator(base DerivationPath) func() DerivationPath { - path := make(DerivationPath, len(base)) - copy(path[:], base[:]) - // Set it back by one, so the first call gives the first result - path[2]-- - return func() DerivationPath { - // ledgerLivePathIterator iterates on the third component - path[2]++ - return path - } -} diff --git a/builder/accounts/hd_test.go b/builder/accounts/hd_test.go deleted file mode 100644 index 118ec5187..000000000 --- a/builder/accounts/hd_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// 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 accounts - -import ( - "fmt" - "reflect" - "testing" -) - -// Tests that HD derivation paths can be correctly parsed into our internal binary -// representation. -func TestHDPathParsing(t *testing.T) { - t.Parallel() - tests := []struct { - input string - output DerivationPath - }{ - // Plain absolute derivation paths - {"m/44'/60'/0'/0", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}}, - {"m/44'/60'/0'/128", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 128}}, - {"m/44'/60'/0'/0'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 0}}, - {"m/44'/60'/0'/128'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 128}}, - {"m/2147483692/2147483708/2147483648/0", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}}, - {"m/2147483692/2147483708/2147483648/2147483648", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 0}}, - - // Plain relative derivation paths - {"0", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}}, - {"128", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 128}}, - {"0'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 0}}, - {"128'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 128}}, - {"2147483648", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 0}}, - - // Hexadecimal absolute derivation paths - {"m/0x2C'/0x3c'/0x00'/0x00", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}}, - {"m/0x2C'/0x3c'/0x00'/0x80", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 128}}, - {"m/0x2C'/0x3c'/0x00'/0x00'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 0}}, - {"m/0x2C'/0x3c'/0x00'/0x80'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 128}}, - {"m/0x8000002C/0x8000003c/0x80000000/0x00", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}}, - {"m/0x8000002C/0x8000003c/0x80000000/0x80000000", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0x80000000 + 0}}, - - // Hexadecimal relative derivation paths - {"0x00", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}}, - {"0x80", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 128}}, - {"0x00'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 0}}, - {"0x80'", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 128}}, - {"0x80000000", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0x80000000 + 0}}, - - // Weird inputs just to ensure they work - {" m / 44 '\n/\n 60 \n\n\t' /\n0 ' /\t\t 0", DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}}, - - // Invalid derivation paths - {"", nil}, // Empty relative derivation path - {"m", nil}, // Empty absolute derivation path - {"m/", nil}, // Missing last derivation component - {"/44'/60'/0'/0", nil}, // Absolute path without m prefix, might be user error - {"m/2147483648'", nil}, // Overflows 32 bit integer - {"m/-1'", nil}, // Cannot contain negative number - } - for i, tt := range tests { - if path, err := ParseDerivationPath(tt.input); !reflect.DeepEqual(path, tt.output) { - t.Errorf("test %d: parse mismatch: have %v (%v), want %v", i, path, err, tt.output) - } else if path == nil && err == nil { - t.Errorf("test %d: nil path and error: %v", i, err) - } - } -} - -func testDerive(t *testing.T, next func() DerivationPath, expected []string) { - t.Helper() - for i, want := range expected { - if have := next(); fmt.Sprintf("%v", have) != want { - t.Errorf("step %d, have %v, want %v", i, have, want) - } - } -} - -func TestHdPathIteration(t *testing.T) { - t.Parallel() - testDerive(t, DefaultIterator(DefaultBaseDerivationPath), - []string{ - "m/44'/60'/0'/0/0", "m/44'/60'/0'/0/1", - "m/44'/60'/0'/0/2", "m/44'/60'/0'/0/3", - "m/44'/60'/0'/0/4", "m/44'/60'/0'/0/5", - "m/44'/60'/0'/0/6", "m/44'/60'/0'/0/7", - "m/44'/60'/0'/0/8", "m/44'/60'/0'/0/9", - }) - - testDerive(t, DefaultIterator(LegacyLedgerBaseDerivationPath), - []string{ - "m/44'/60'/0'/0", "m/44'/60'/0'/1", - "m/44'/60'/0'/2", "m/44'/60'/0'/3", - "m/44'/60'/0'/4", "m/44'/60'/0'/5", - "m/44'/60'/0'/6", "m/44'/60'/0'/7", - "m/44'/60'/0'/8", "m/44'/60'/0'/9", - }) - - testDerive(t, LedgerLiveIterator(DefaultBaseDerivationPath), - []string{ - "m/44'/60'/0'/0/0", "m/44'/60'/1'/0/0", - "m/44'/60'/2'/0/0", "m/44'/60'/3'/0/0", - "m/44'/60'/4'/0/0", "m/44'/60'/5'/0/0", - "m/44'/60'/6'/0/0", "m/44'/60'/7'/0/0", - "m/44'/60'/8'/0/0", "m/44'/60'/9'/0/0", - }) -} diff --git a/builder/accounts/keystore/account_cache.go b/builder/accounts/keystore/account_cache.go deleted file mode 100644 index 4ed143951..000000000 --- a/builder/accounts/keystore/account_cache.go +++ /dev/null @@ -1,308 +0,0 @@ -// 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 keystore - -import ( - "bufio" - "encoding/json" - "fmt" - "os" - "path/filepath" - "sort" - "strings" - "sync" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "golang.org/x/exp/slices" -) - -// Minimum amount of time between cache reloads. This limit applies if the platform does -// not support change notifications. It also applies if the keystore directory does not -// exist yet, the code will attempt to create a watcher at most this often. -const minReloadInterval = 2 * time.Second - -// byURL defines the sorting order for accounts. -func byURL(a, b accounts.Account) int { - return a.URL.Cmp(b.URL) -} - -// AmbiguousAddrError is returned when attempting to unlock -// an address for which more than one file exists. -type AmbiguousAddrError struct { - Addr common.Address - Matches []accounts.Account -} - -func (err *AmbiguousAddrError) Error() string { - files := "" - for i, a := range err.Matches { - files += a.URL.Path - if i < len(err.Matches)-1 { - files += ", " - } - } - return fmt.Sprintf("multiple keys match address (%s)", files) -} - -// accountCache is a live index of all accounts in the keystore. -type accountCache struct { - keydir string - watcher *watcher - mu sync.Mutex - all []accounts.Account - byAddr map[common.Address][]accounts.Account - throttle *time.Timer - notify chan struct{} - fileC fileCache -} - -func newAccountCache(keydir string) (*accountCache, chan struct{}) { - ac := &accountCache{ - keydir: keydir, - byAddr: make(map[common.Address][]accounts.Account), - notify: make(chan struct{}, 1), - fileC: fileCache{all: mapset.NewThreadUnsafeSet[string]()}, - } - ac.watcher = newWatcher(ac) - return ac, ac.notify -} - -func (ac *accountCache) accounts() []accounts.Account { - ac.maybeReload() - ac.mu.Lock() - defer ac.mu.Unlock() - cpy := make([]accounts.Account, len(ac.all)) - copy(cpy, ac.all) - return cpy -} - -func (ac *accountCache) hasAddress(addr common.Address) bool { - ac.maybeReload() - ac.mu.Lock() - defer ac.mu.Unlock() - return len(ac.byAddr[addr]) > 0 -} - -func (ac *accountCache) add(newAccount accounts.Account) { - ac.mu.Lock() - defer ac.mu.Unlock() - - i := sort.Search(len(ac.all), func(i int) bool { return ac.all[i].URL.Cmp(newAccount.URL) >= 0 }) - if i < len(ac.all) && ac.all[i] == newAccount { - return - } - // newAccount is not in the cache. - ac.all = append(ac.all, accounts.Account{}) - copy(ac.all[i+1:], ac.all[i:]) - ac.all[i] = newAccount - ac.byAddr[newAccount.Address] = append(ac.byAddr[newAccount.Address], newAccount) -} - -// note: removed needs to be unique here (i.e. both File and Address must be set). -func (ac *accountCache) delete(removed accounts.Account) { - ac.mu.Lock() - defer ac.mu.Unlock() - - ac.all = removeAccount(ac.all, removed) - if ba := removeAccount(ac.byAddr[removed.Address], removed); len(ba) == 0 { - delete(ac.byAddr, removed.Address) - } else { - ac.byAddr[removed.Address] = ba - } -} - -// deleteByFile removes an account referenced by the given path. -func (ac *accountCache) deleteByFile(path string) { - ac.mu.Lock() - defer ac.mu.Unlock() - i := sort.Search(len(ac.all), func(i int) bool { return ac.all[i].URL.Path >= path }) - - if i < len(ac.all) && ac.all[i].URL.Path == path { - removed := ac.all[i] - ac.all = append(ac.all[:i], ac.all[i+1:]...) - if ba := removeAccount(ac.byAddr[removed.Address], removed); len(ba) == 0 { - delete(ac.byAddr, removed.Address) - } else { - ac.byAddr[removed.Address] = ba - } - } -} - -// watcherStarted returns true if the watcher loop started running (even if it -// has since also ended). -func (ac *accountCache) watcherStarted() bool { - ac.mu.Lock() - defer ac.mu.Unlock() - return ac.watcher.running || ac.watcher.runEnded -} - -func removeAccount(slice []accounts.Account, elem accounts.Account) []accounts.Account { - for i := range slice { - if slice[i] == elem { - return append(slice[:i], slice[i+1:]...) - } - } - return slice -} - -// find returns the cached account for address if there is a unique match. -// The exact matching rules are explained by the documentation of accounts.Account. -// Callers must hold ac.mu. -func (ac *accountCache) find(a accounts.Account) (accounts.Account, error) { - // Limit search to address candidates if possible. - matches := ac.all - if (a.Address != common.Address{}) { - matches = ac.byAddr[a.Address] - } - if a.URL.Path != "" { - // If only the basename is specified, complete the path. - if !strings.ContainsRune(a.URL.Path, filepath.Separator) { - a.URL.Path = filepath.Join(ac.keydir, a.URL.Path) - } - for i := range matches { - if matches[i].URL == a.URL { - return matches[i], nil - } - } - if (a.Address == common.Address{}) { - return accounts.Account{}, ErrNoMatch - } - } - switch len(matches) { - case 1: - return matches[0], nil - case 0: - return accounts.Account{}, ErrNoMatch - default: - err := &AmbiguousAddrError{Addr: a.Address, Matches: make([]accounts.Account, len(matches))} - copy(err.Matches, matches) - slices.SortFunc(err.Matches, byURL) - return accounts.Account{}, err - } -} - -func (ac *accountCache) maybeReload() { - ac.mu.Lock() - - if ac.watcher.running { - ac.mu.Unlock() - return // A watcher is running and will keep the cache up-to-date. - } - if ac.throttle == nil { - ac.throttle = time.NewTimer(0) - } else { - select { - case <-ac.throttle.C: - default: - ac.mu.Unlock() - return // The cache was reloaded recently. - } - } - // No watcher running, start it. - ac.watcher.start() - ac.throttle.Reset(minReloadInterval) - ac.mu.Unlock() - ac.scanAccounts() -} - -func (ac *accountCache) close() { - ac.mu.Lock() - ac.watcher.close() - if ac.throttle != nil { - ac.throttle.Stop() - } - if ac.notify != nil { - close(ac.notify) - ac.notify = nil - } - ac.mu.Unlock() -} - -// scanAccounts checks if any changes have occurred on the filesystem, and -// updates the account cache accordingly -func (ac *accountCache) scanAccounts() error { - // Scan the entire folder metadata for file changes - creates, deletes, updates, err := ac.fileC.scan(ac.keydir) - if err != nil { - log.Debug("Failed to reload keystore contents", "err", err) - return err - } - if creates.Cardinality() == 0 && deletes.Cardinality() == 0 && updates.Cardinality() == 0 { - return nil - } - // Create a helper method to scan the contents of the key files - var ( - buf = new(bufio.Reader) - key struct { - Address string `json:"address"` - } - ) - readAccount := func(path string) *accounts.Account { - fd, err := os.Open(path) - if err != nil { - log.Trace("Failed to open keystore file", "path", path, "err", err) - return nil - } - defer fd.Close() - buf.Reset(fd) - // Parse the address. - key.Address = "" - err = json.NewDecoder(buf).Decode(&key) - addr := common.HexToAddress(key.Address) - switch { - case err != nil: - log.Debug("Failed to decode keystore key", "path", path, "err", err) - case addr == common.Address{}: - log.Debug("Failed to decode keystore key", "path", path, "err", "missing or zero address") - default: - return &accounts.Account{ - Address: addr, - URL: accounts.URL{Scheme: KeyStoreScheme, Path: path}, - } - } - return nil - } - // Process all the file diffs - start := time.Now() - - for _, path := range creates.ToSlice() { - if a := readAccount(path); a != nil { - ac.add(*a) - } - } - for _, path := range deletes.ToSlice() { - ac.deleteByFile(path) - } - for _, path := range updates.ToSlice() { - ac.deleteByFile(path) - if a := readAccount(path); a != nil { - ac.add(*a) - } - } - end := time.Now() - - select { - case ac.notify <- struct{}{}: - default: - } - log.Trace("Handled keystore changes", "time", end.Sub(start)) - return nil -} diff --git a/builder/accounts/keystore/account_cache_test.go b/builder/accounts/keystore/account_cache_test.go deleted file mode 100644 index 48a238048..000000000 --- a/builder/accounts/keystore/account_cache_test.go +++ /dev/null @@ -1,409 +0,0 @@ -// 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 keystore - -import ( - "errors" - "fmt" - "math/rand" - "os" - "path/filepath" - "reflect" - "testing" - "time" - - "github.com/cespare/cp" - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "golang.org/x/exp/slices" -) - -var ( - cachetestDir, _ = filepath.Abs(filepath.Join("testdata", "keystore")) - cachetestAccounts = []accounts.Account{ - { - Address: common.HexToAddress("7ef5a6135f1fd6a02593eedc869c6d41d934aef8"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(cachetestDir, "UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8")}, - }, - { - Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(cachetestDir, "aaa")}, - }, - { - Address: common.HexToAddress("289d485d9771714cce91d3393d764e1311907acc"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(cachetestDir, "zzz")}, - }, - } -) - -// waitWatcherStarts waits up to 1s for the keystore watcher to start. -func waitWatcherStart(ks *KeyStore) bool { - // On systems where file watch is not supported, just return "ok". - if !ks.cache.watcher.enabled() { - return true - } - // The watcher should start, and then exit. - for t0 := time.Now(); time.Since(t0) < 1*time.Second; time.Sleep(100 * time.Millisecond) { - if ks.cache.watcherStarted() { - return true - } - } - return false -} - -func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error { - var list []accounts.Account - for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) { - list = ks.Accounts() - if reflect.DeepEqual(list, wantAccounts) { - // ks should have also received change notifications - select { - case <-ks.changes: - default: - return errors.New("wasn't notified of new accounts") - } - return nil - } - } - return fmt.Errorf("\ngot %v\nwant %v", list, wantAccounts) -} - -func TestWatchNewFile(t *testing.T) { - t.Parallel() - - dir, ks := tmpKeyStore(t, false) - - // Ensure the watcher is started before adding any files. - ks.Accounts() - if !waitWatcherStart(ks) { - t.Fatal("keystore watcher didn't start in time") - } - // Move in the files. - wantAccounts := make([]accounts.Account, len(cachetestAccounts)) - for i := range cachetestAccounts { - wantAccounts[i] = accounts.Account{ - Address: cachetestAccounts[i].Address, - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, filepath.Base(cachetestAccounts[i].URL.Path))}, - } - if err := cp.CopyFile(wantAccounts[i].URL.Path, cachetestAccounts[i].URL.Path); err != nil { - t.Fatal(err) - } - } - - // ks should see the accounts. - if err := waitForAccounts(wantAccounts, ks); err != nil { - t.Error(err) - } -} - -func TestWatchNoDir(t *testing.T) { - t.Parallel() - // Create ks but not the directory that it watches. - dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int())) - ks := NewKeyStore(dir, LightScryptN, LightScryptP) - list := ks.Accounts() - if len(list) > 0 { - t.Error("initial account list not empty:", list) - } - // The watcher should start, and then exit. - if !waitWatcherStart(ks) { - t.Fatal("keystore watcher didn't start in time") - } - // Create the directory and copy a key file into it. - os.MkdirAll(dir, 0700) - defer os.RemoveAll(dir) - file := filepath.Join(dir, "aaa") - if err := cp.CopyFile(file, cachetestAccounts[0].URL.Path); err != nil { - t.Fatal(err) - } - - // ks should see the account. - wantAccounts := []accounts.Account{cachetestAccounts[0]} - wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file} - for d := 200 * time.Millisecond; d < 8*time.Second; d *= 2 { - list = ks.Accounts() - if reflect.DeepEqual(list, wantAccounts) { - // ks should have also received change notifications - select { - case <-ks.changes: - default: - t.Fatalf("wasn't notified of new accounts") - } - return - } - time.Sleep(d) - } - t.Errorf("\ngot %v\nwant %v", list, wantAccounts) -} - -func TestCacheInitialReload(t *testing.T) { - t.Parallel() - cache, _ := newAccountCache(cachetestDir) - accounts := cache.accounts() - if !reflect.DeepEqual(accounts, cachetestAccounts) { - t.Fatalf("got initial accounts: %swant %s", spew.Sdump(accounts), spew.Sdump(cachetestAccounts)) - } -} - -func TestCacheAddDeleteOrder(t *testing.T) { - t.Parallel() - cache, _ := newAccountCache("testdata/no-such-dir") - cache.watcher.running = true // prevent unexpected reloads - - accs := []accounts.Account{ - { - Address: common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "-309830980"}, - }, - { - Address: common.HexToAddress("2cac1adea150210703ba75ed097ddfe24e14f213"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "ggg"}, - }, - { - Address: common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "zzzzzz-the-very-last-one.keyXXX"}, - }, - { - Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "SOMETHING.key"}, - }, - { - Address: common.HexToAddress("7ef5a6135f1fd6a02593eedc869c6d41d934aef8"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8"}, - }, - { - Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "aaa"}, - }, - { - Address: common.HexToAddress("289d485d9771714cce91d3393d764e1311907acc"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: "zzz"}, - }, - } - for _, a := range accs { - cache.add(a) - } - // Add some of them twice to check that they don't get reinserted. - cache.add(accs[0]) - cache.add(accs[2]) - - // Check that the account list is sorted by filename. - wantAccounts := make([]accounts.Account, len(accs)) - copy(wantAccounts, accs) - slices.SortFunc(wantAccounts, byURL) - list := cache.accounts() - if !reflect.DeepEqual(list, wantAccounts) { - t.Fatalf("got accounts: %s\nwant %s", spew.Sdump(accs), spew.Sdump(wantAccounts)) - } - for _, a := range accs { - if !cache.hasAddress(a.Address) { - t.Errorf("expected hasAccount(%x) to return true", a.Address) - } - } - if cache.hasAddress(common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e")) { - t.Errorf("expected hasAccount(%x) to return false", common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e")) - } - - // Delete a few keys from the cache. - for i := 0; i < len(accs); i += 2 { - cache.delete(wantAccounts[i]) - } - cache.delete(accounts.Account{Address: common.HexToAddress("fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e"), URL: accounts.URL{Scheme: KeyStoreScheme, Path: "something"}}) - - // Check content again after deletion. - wantAccountsAfterDelete := []accounts.Account{ - wantAccounts[1], - wantAccounts[3], - wantAccounts[5], - } - list = cache.accounts() - if !reflect.DeepEqual(list, wantAccountsAfterDelete) { - t.Fatalf("got accounts after delete: %s\nwant %s", spew.Sdump(list), spew.Sdump(wantAccountsAfterDelete)) - } - for _, a := range wantAccountsAfterDelete { - if !cache.hasAddress(a.Address) { - t.Errorf("expected hasAccount(%x) to return true", a.Address) - } - } - if cache.hasAddress(wantAccounts[0].Address) { - t.Errorf("expected hasAccount(%x) to return false", wantAccounts[0].Address) - } -} - -func TestCacheFind(t *testing.T) { - t.Parallel() - dir := filepath.Join("testdata", "dir") - cache, _ := newAccountCache(dir) - cache.watcher.running = true // prevent unexpected reloads - - accs := []accounts.Account{ - { - Address: common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, "a.key")}, - }, - { - Address: common.HexToAddress("2cac1adea150210703ba75ed097ddfe24e14f213"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, "b.key")}, - }, - { - Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, "c.key")}, - }, - { - Address: common.HexToAddress("d49ff4eeb0b2686ed89c0fc0f2b6ea533ddbbd5e"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, "c2.key")}, - }, - } - for _, a := range accs { - cache.add(a) - } - - nomatchAccount := accounts.Account{ - Address: common.HexToAddress("f466859ead1932d743d622cb74fc058882e8648a"), - URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Join(dir, "something")}, - } - tests := []struct { - Query accounts.Account - WantResult accounts.Account - WantError error - }{ - // by address - {Query: accounts.Account{Address: accs[0].Address}, WantResult: accs[0]}, - // by file - {Query: accounts.Account{URL: accs[0].URL}, WantResult: accs[0]}, - // by basename - {Query: accounts.Account{URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Base(accs[0].URL.Path)}}, WantResult: accs[0]}, - // by file and address - {Query: accs[0], WantResult: accs[0]}, - // ambiguous address, tie resolved by file - {Query: accs[2], WantResult: accs[2]}, - // ambiguous address error - { - Query: accounts.Account{Address: accs[2].Address}, - WantError: &AmbiguousAddrError{ - Addr: accs[2].Address, - Matches: []accounts.Account{accs[2], accs[3]}, - }, - }, - // no match error - {Query: nomatchAccount, WantError: ErrNoMatch}, - {Query: accounts.Account{URL: nomatchAccount.URL}, WantError: ErrNoMatch}, - {Query: accounts.Account{URL: accounts.URL{Scheme: KeyStoreScheme, Path: filepath.Base(nomatchAccount.URL.Path)}}, WantError: ErrNoMatch}, - {Query: accounts.Account{Address: nomatchAccount.Address}, WantError: ErrNoMatch}, - } - for i, test := range tests { - a, err := cache.find(test.Query) - if !reflect.DeepEqual(err, test.WantError) { - t.Errorf("test %d: error mismatch for query %v\ngot %q\nwant %q", i, test.Query, err, test.WantError) - continue - } - if a != test.WantResult { - t.Errorf("test %d: result mismatch for query %v\ngot %v\nwant %v", i, test.Query, a, test.WantResult) - continue - } - } -} - -// TestUpdatedKeyfileContents tests that updating the contents of a keystore file -// is noticed by the watcher, and the account cache is updated accordingly -func TestUpdatedKeyfileContents(t *testing.T) { - t.Parallel() - - // Create a temporary keystore to test with - dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int())) - ks := NewKeyStore(dir, LightScryptN, LightScryptP) - - list := ks.Accounts() - if len(list) > 0 { - t.Error("initial account list not empty:", list) - } - if !waitWatcherStart(ks) { - t.Fatal("keystore watcher didn't start in time") - } - // Create the directory and copy a key file into it. - os.MkdirAll(dir, 0700) - defer os.RemoveAll(dir) - file := filepath.Join(dir, "aaa") - - // Place one of our testfiles in there - if err := cp.CopyFile(file, cachetestAccounts[0].URL.Path); err != nil { - t.Fatal(err) - } - - // ks should see the account. - wantAccounts := []accounts.Account{cachetestAccounts[0]} - wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file} - if err := waitForAccounts(wantAccounts, ks); err != nil { - t.Error(err) - return - } - // needed so that modTime of `file` is different to its current value after forceCopyFile - os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second)) - - // Now replace file contents - if err := forceCopyFile(file, cachetestAccounts[1].URL.Path); err != nil { - t.Fatal(err) - return - } - wantAccounts = []accounts.Account{cachetestAccounts[1]} - wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file} - if err := waitForAccounts(wantAccounts, ks); err != nil { - t.Errorf("First replacement failed") - t.Error(err) - return - } - - // needed so that modTime of `file` is different to its current value after forceCopyFile - os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second)) - - // Now replace file contents again - if err := forceCopyFile(file, cachetestAccounts[2].URL.Path); err != nil { - t.Fatal(err) - return - } - wantAccounts = []accounts.Account{cachetestAccounts[2]} - wantAccounts[0].URL = accounts.URL{Scheme: KeyStoreScheme, Path: file} - if err := waitForAccounts(wantAccounts, ks); err != nil { - t.Errorf("Second replacement failed") - t.Error(err) - return - } - - // needed so that modTime of `file` is different to its current value after os.WriteFile - os.Chtimes(file, time.Now().Add(-time.Second), time.Now().Add(-time.Second)) - - // Now replace file contents with crap - if err := os.WriteFile(file, []byte("foo"), 0600); err != nil { - t.Fatal(err) - return - } - if err := waitForAccounts([]accounts.Account{}, ks); err != nil { - t.Errorf("Emptying account file failed") - t.Error(err) - return - } -} - -// forceCopyFile is like cp.CopyFile, but doesn't complain if the destination exists. -func forceCopyFile(dst, src string) error { - data, err := os.ReadFile(src) - if err != nil { - return err - } - return os.WriteFile(dst, data, 0644) -} diff --git a/builder/accounts/keystore/file_cache.go b/builder/accounts/keystore/file_cache.go deleted file mode 100644 index 63eb85037..000000000 --- a/builder/accounts/keystore/file_cache.go +++ /dev/null @@ -1,105 +0,0 @@ -// 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 keystore - -import ( - "os" - "path/filepath" - "strings" - "sync" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/log" -) - -// fileCache is a cache of files seen during scan of keystore. -type fileCache struct { - all mapset.Set[string] // Set of all files from the keystore folder - lastMod time.Time // Last time instance when a file was modified - mu sync.Mutex -} - -// scan performs a new scan on the given directory, compares against the already -// cached filenames, and returns file sets: creates, deletes, updates. -func (fc *fileCache) scan(keyDir string) (mapset.Set[string], mapset.Set[string], mapset.Set[string], error) { - t0 := time.Now() - - // List all the files from the keystore folder - files, err := os.ReadDir(keyDir) - if err != nil { - return nil, nil, nil, err - } - t1 := time.Now() - - fc.mu.Lock() - defer fc.mu.Unlock() - - // Iterate all the files and gather their metadata - all := mapset.NewThreadUnsafeSet[string]() - mods := mapset.NewThreadUnsafeSet[string]() - - var newLastMod time.Time - for _, fi := range files { - path := filepath.Join(keyDir, fi.Name()) - // Skip any non-key files from the folder - if nonKeyFile(fi) { - log.Trace("Ignoring file on account scan", "path", path) - continue - } - // Gather the set of all and freshly modified files - all.Add(path) - - info, err := fi.Info() - if err != nil { - return nil, nil, nil, err - } - modified := info.ModTime() - if modified.After(fc.lastMod) { - mods.Add(path) - } - if modified.After(newLastMod) { - newLastMod = modified - } - } - t2 := time.Now() - - // Update the tracked files and return the three sets - deletes := fc.all.Difference(all) // Deletes = previous - current - creates := all.Difference(fc.all) // Creates = current - previous - updates := mods.Difference(creates) // Updates = modified - creates - - fc.all, fc.lastMod = all, newLastMod - t3 := time.Now() - - // Report on the scanning stats and return - log.Debug("FS scan times", "list", t1.Sub(t0), "set", t2.Sub(t1), "diff", t3.Sub(t2)) - return creates, deletes, updates, nil -} - -// nonKeyFile ignores editor backups, hidden files and folders/symlinks. -func nonKeyFile(fi os.DirEntry) bool { - // Skip editor backups and UNIX-style hidden files. - if strings.HasSuffix(fi.Name(), "~") || strings.HasPrefix(fi.Name(), ".") { - return true - } - // Skip misc special files, directories (yes, symlinks too). - if fi.IsDir() || !fi.Type().IsRegular() { - return true - } - return false -} diff --git a/builder/accounts/keystore/key.go b/builder/accounts/keystore/key.go deleted file mode 100644 index 9b2ac1471..000000000 --- a/builder/accounts/keystore/key.go +++ /dev/null @@ -1,237 +0,0 @@ -// 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 keystore - -import ( - "bytes" - "crypto/ecdsa" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" -) - -const ( - version = 3 -) - -type Key struct { - Id uuid.UUID // Version 4 "random" for unique id not derived from key data - // to simplify lookups we also store the address - Address common.Address - // we only store privkey as pubkey/address can be derived from it - // privkey in this struct is always in plaintext - PrivateKey *ecdsa.PrivateKey -} - -type keyStore interface { - // Loads and decrypts the key from disk. - GetKey(addr common.Address, filename string, auth string) (*Key, error) - // Writes and encrypts the key. - StoreKey(filename string, k *Key, auth string) error - // Joins filename with the key directory unless it is already absolute. - JoinPath(filename string) string -} - -type plainKeyJSON struct { - Address string `json:"address"` - PrivateKey string `json:"privatekey"` - Id string `json:"id"` - Version int `json:"version"` -} - -type encryptedKeyJSONV3 struct { - Address string `json:"address"` - Crypto CryptoJSON `json:"crypto"` - Id string `json:"id"` - Version int `json:"version"` -} - -type encryptedKeyJSONV1 struct { - Address string `json:"address"` - Crypto CryptoJSON `json:"crypto"` - Id string `json:"id"` - Version string `json:"version"` -} - -type CryptoJSON struct { - Cipher string `json:"cipher"` - CipherText string `json:"ciphertext"` - CipherParams cipherparamsJSON `json:"cipherparams"` - KDF string `json:"kdf"` - KDFParams map[string]interface{} `json:"kdfparams"` - MAC string `json:"mac"` -} - -type cipherparamsJSON struct { - IV string `json:"iv"` -} - -func (k *Key) MarshalJSON() (j []byte, err error) { - jStruct := plainKeyJSON{ - hex.EncodeToString(k.Address[:]), - hex.EncodeToString(crypto.FromECDSA(k.PrivateKey)), - k.Id.String(), - version, - } - j, err = json.Marshal(jStruct) - return j, err -} - -func (k *Key) UnmarshalJSON(j []byte) (err error) { - keyJSON := new(plainKeyJSON) - err = json.Unmarshal(j, &keyJSON) - if err != nil { - return err - } - - u := new(uuid.UUID) - *u, err = uuid.Parse(keyJSON.Id) - if err != nil { - return err - } - k.Id = *u - addr, err := hex.DecodeString(keyJSON.Address) - if err != nil { - return err - } - privkey, err := crypto.HexToECDSA(keyJSON.PrivateKey) - if err != nil { - return err - } - - k.Address = common.BytesToAddress(addr) - k.PrivateKey = privkey - - return nil -} - -func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key { - id, err := uuid.NewRandom() - if err != nil { - panic(fmt.Sprintf("Could not create random uuid: %v", err)) - } - key := &Key{ - Id: id, - Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey), - PrivateKey: privateKeyECDSA, - } - return key -} - -// NewKeyForDirectICAP generates a key whose address fits into < 155 bits so it can fit -// into the Direct ICAP spec. for simplicity and easier compatibility with other libs, we -// retry until the first byte is 0. -func NewKeyForDirectICAP(rand io.Reader) *Key { - randBytes := make([]byte, 64) - _, err := rand.Read(randBytes) - if err != nil { - panic("key generation: could not read from random source: " + err.Error()) - } - reader := bytes.NewReader(randBytes) - privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), reader) - if err != nil { - panic("key generation: ecdsa.GenerateKey failed: " + err.Error()) - } - key := newKeyFromECDSA(privateKeyECDSA) - if !strings.HasPrefix(key.Address.Hex(), "0x00") { - return NewKeyForDirectICAP(rand) - } - return key -} - -func newKey(rand io.Reader) (*Key, error) { - privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand) - if err != nil { - return nil, err - } - return newKeyFromECDSA(privateKeyECDSA), nil -} - -func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) { - key, err := newKey(rand) - if err != nil { - return nil, accounts.Account{}, err - } - a := accounts.Account{ - Address: key.Address, - URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.JoinPath(keyFileName(key.Address))}, - } - if err := ks.StoreKey(a.URL.Path, key, auth); err != nil { - zeroKey(key.PrivateKey) - return nil, a, err - } - return key, a, err -} - -func writeTemporaryKeyFile(file string, content []byte) (string, error) { - // Create the keystore directory with appropriate permissions - // in case it is not present yet. - const dirPerm = 0700 - if err := os.MkdirAll(filepath.Dir(file), dirPerm); err != nil { - return "", err - } - // Atomic write: create a temporary hidden file first - // then move it into place. TempFile assigns mode 0600. - f, err := os.CreateTemp(filepath.Dir(file), "."+filepath.Base(file)+".tmp") - if err != nil { - return "", err - } - if _, err := f.Write(content); err != nil { - f.Close() - os.Remove(f.Name()) - return "", err - } - f.Close() - return f.Name(), nil -} - -func writeKeyFile(file string, content []byte) error { - name, err := writeTemporaryKeyFile(file, content) - if err != nil { - return err - } - return os.Rename(name, file) -} - -// keyFileName implements the naming convention for keyfiles: -// UTC---
-func keyFileName(keyAddr common.Address) string { - ts := time.Now().UTC() - return fmt.Sprintf("UTC--%s--%s", toISO8601(ts), hex.EncodeToString(keyAddr[:])) -} - -func toISO8601(t time.Time) string { - var tz string - name, offset := t.Zone() - if name == "UTC" { - tz = "Z" - } else { - tz = fmt.Sprintf("%03d00", offset/3600) - } - return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", - t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz) -} diff --git a/builder/accounts/keystore/keystore.go b/builder/accounts/keystore/keystore.go deleted file mode 100644 index 0ffcf376a..000000000 --- a/builder/accounts/keystore/keystore.go +++ /dev/null @@ -1,515 +0,0 @@ -// 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 keystore implements encrypted storage of secp256k1 private keys. -// -// Keys are stored as encrypted JSON files according to the Web3 Secret Storage specification. -// See https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition for more information. -package keystore - -import ( - "crypto/ecdsa" - crand "crypto/rand" - "errors" - "math/big" - "os" - "path/filepath" - "reflect" - "runtime" - "sync" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/event" -) - -var ( - ErrLocked = accounts.NewAuthNeededError("password or unlock") - ErrNoMatch = errors.New("no key for given address or file") - ErrDecrypt = errors.New("could not decrypt key with given password") - - // ErrAccountAlreadyExists is returned if an account attempted to import is - // already present in the keystore. - ErrAccountAlreadyExists = errors.New("account already exists") -) - -// KeyStoreType is the reflect type of a keystore backend. -var KeyStoreType = reflect.TypeOf(&KeyStore{}) - -// KeyStoreScheme is the protocol scheme prefixing account and wallet URLs. -const KeyStoreScheme = "keystore" - -// Maximum time between wallet refreshes (if filesystem notifications don't work). -const walletRefreshCycle = 3 * time.Second - -// KeyStore manages a key storage directory on disk. -type KeyStore struct { - storage keyStore // Storage backend, might be cleartext or encrypted - cache *accountCache // In-memory account cache over the filesystem storage - changes chan struct{} // Channel receiving change notifications from the cache - unlocked map[common.Address]*unlocked // Currently unlocked account (decrypted private keys) - - wallets []accounts.Wallet // Wallet wrappers around the individual key files - updateFeed event.Feed // Event feed to notify wallet additions/removals - updateScope event.SubscriptionScope // Subscription scope tracking current live listeners - updating bool // Whether the event notification loop is running - - mu sync.RWMutex - importMu sync.Mutex // Import Mutex locks the import to prevent two insertions from racing -} - -type unlocked struct { - *Key - abort chan struct{} -} - -// NewKeyStore creates a keystore for the given directory. -func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore { - keydir, _ = filepath.Abs(keydir) - ks := &KeyStore{storage: &keyStorePassphrase{keydir, scryptN, scryptP, false}} - ks.init(keydir) - return ks -} - -// NewPlaintextKeyStore creates a keystore for the given directory. -// Deprecated: Use NewKeyStore. -func NewPlaintextKeyStore(keydir string) *KeyStore { - keydir, _ = filepath.Abs(keydir) - ks := &KeyStore{storage: &keyStorePlain{keydir}} - ks.init(keydir) - return ks -} - -func (ks *KeyStore) init(keydir string) { - // Lock the mutex since the account cache might call back with events - ks.mu.Lock() - defer ks.mu.Unlock() - - // Initialize the set of unlocked keys and the account cache - ks.unlocked = make(map[common.Address]*unlocked) - ks.cache, ks.changes = newAccountCache(keydir) - - // TODO: In order for this finalizer to work, there must be no references - // to ks. addressCache doesn't keep a reference but unlocked keys do, - // so the finalizer will not trigger until all timed unlocks have expired. - runtime.SetFinalizer(ks, func(m *KeyStore) { - m.cache.close() - }) - // Create the initial list of wallets from the cache - accs := ks.cache.accounts() - ks.wallets = make([]accounts.Wallet, len(accs)) - for i := 0; i < len(accs); i++ { - ks.wallets[i] = &keystoreWallet{account: accs[i], keystore: ks} - } -} - -// Wallets implements accounts.Backend, returning all single-key wallets from the -// keystore directory. -func (ks *KeyStore) Wallets() []accounts.Wallet { - // Make sure the list of wallets is in sync with the account cache - ks.refreshWallets() - - ks.mu.RLock() - defer ks.mu.RUnlock() - - cpy := make([]accounts.Wallet, len(ks.wallets)) - copy(cpy, ks.wallets) - return cpy -} - -// refreshWallets retrieves the current account list and based on that does any -// necessary wallet refreshes. -func (ks *KeyStore) refreshWallets() { - // Retrieve the current list of accounts - ks.mu.Lock() - accs := ks.cache.accounts() - - // Transform the current list of wallets into the new one - var ( - wallets = make([]accounts.Wallet, 0, len(accs)) - events []accounts.WalletEvent - ) - - for _, account := range accs { - // Drop wallets while they were in front of the next account - for len(ks.wallets) > 0 && ks.wallets[0].URL().Cmp(account.URL) < 0 { - events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Kind: accounts.WalletDropped}) - ks.wallets = ks.wallets[1:] - } - // If there are no more wallets or the account is before the next, wrap new wallet - if len(ks.wallets) == 0 || ks.wallets[0].URL().Cmp(account.URL) > 0 { - wallet := &keystoreWallet{account: account, keystore: ks} - - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) - wallets = append(wallets, wallet) - continue - } - // If the account is the same as the first wallet, keep it - if ks.wallets[0].Accounts()[0] == account { - wallets = append(wallets, ks.wallets[0]) - ks.wallets = ks.wallets[1:] - continue - } - } - // Drop any leftover wallets and set the new batch - for _, wallet := range ks.wallets { - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) - } - ks.wallets = wallets - ks.mu.Unlock() - - // Fire all wallet events and return - for _, event := range events { - ks.updateFeed.Send(event) - } -} - -// Subscribe implements accounts.Backend, creating an async subscription to -// receive notifications on the addition or removal of keystore wallets. -func (ks *KeyStore) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { - // We need the mutex to reliably start/stop the update loop - ks.mu.Lock() - defer ks.mu.Unlock() - - // Subscribe the caller and track the subscriber count - sub := ks.updateScope.Track(ks.updateFeed.Subscribe(sink)) - - // Subscribers require an active notification loop, start it - if !ks.updating { - ks.updating = true - go ks.updater() - } - return sub -} - -// updater is responsible for maintaining an up-to-date list of wallets stored in -// the keystore, and for firing wallet addition/removal events. It listens for -// account change events from the underlying account cache, and also periodically -// forces a manual refresh (only triggers for systems where the filesystem notifier -// is not running). -func (ks *KeyStore) updater() { - for { - // Wait for an account update or a refresh timeout - select { - case <-ks.changes: - case <-time.After(walletRefreshCycle): - } - // Run the wallet refresher - ks.refreshWallets() - - // If all our subscribers left, stop the updater - ks.mu.Lock() - if ks.updateScope.Count() == 0 { - ks.updating = false - ks.mu.Unlock() - return - } - ks.mu.Unlock() - } -} - -// HasAddress reports whether a key with the given address is present. -func (ks *KeyStore) HasAddress(addr common.Address) bool { - return ks.cache.hasAddress(addr) -} - -// Accounts returns all key files present in the directory. -func (ks *KeyStore) Accounts() []accounts.Account { - return ks.cache.accounts() -} - -// Delete deletes the key matched by account if the passphrase is correct. -// If the account contains no filename, the address must match a unique key. -func (ks *KeyStore) Delete(a accounts.Account, passphrase string) error { - // Decrypting the key isn't really necessary, but we do - // it anyway to check the password and zero out the key - // immediately afterwards. - a, key, err := ks.getDecryptedKey(a, passphrase) - if key != nil { - zeroKey(key.PrivateKey) - } - if err != nil { - return err - } - // The order is crucial here. The key is dropped from the - // cache after the file is gone so that a reload happening in - // between won't insert it into the cache again. - err = os.Remove(a.URL.Path) - if err == nil { - ks.cache.delete(a) - ks.refreshWallets() - } - return err -} - -// SignHash calculates a ECDSA signature for the given hash. The produced -// signature is in the [R || S || V] format where V is 0 or 1. -func (ks *KeyStore) SignHash(a accounts.Account, hash []byte) ([]byte, error) { - // Look up the key to sign with and abort if it cannot be found - ks.mu.RLock() - defer ks.mu.RUnlock() - - unlockedKey, found := ks.unlocked[a.Address] - if !found { - return nil, ErrLocked - } - // Sign the hash using plain ECDSA operations - return crypto.Sign(hash, unlockedKey.PrivateKey) -} - -// SignTx signs the given transaction with the requested account. -func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - // Look up the key to sign with and abort if it cannot be found - ks.mu.RLock() - defer ks.mu.RUnlock() - - unlockedKey, found := ks.unlocked[a.Address] - if !found { - return nil, ErrLocked - } - // Depending on the presence of the chain ID, sign with 2718 or homestead - signer := types.LatestSignerForChainID(chainID) - return types.SignTx(tx, signer, unlockedKey.PrivateKey) -} - -// SignHashWithPassphrase signs hash if the private key matching the given address -// can be decrypted with the given passphrase. The produced signature is in the -// [R || S || V] format where V is 0 or 1. -func (ks *KeyStore) SignHashWithPassphrase(a accounts.Account, passphrase string, hash []byte) (signature []byte, err error) { - _, key, err := ks.getDecryptedKey(a, passphrase) - if err != nil { - return nil, err - } - defer zeroKey(key.PrivateKey) - return crypto.Sign(hash, key.PrivateKey) -} - -// SignTxWithPassphrase signs the transaction if the private key matching the -// given address can be decrypted with the given passphrase. -func (ks *KeyStore) SignTxWithPassphrase(a accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - _, key, err := ks.getDecryptedKey(a, passphrase) - if err != nil { - return nil, err - } - defer zeroKey(key.PrivateKey) - // Depending on the presence of the chain ID, sign with or without replay protection. - signer := types.LatestSignerForChainID(chainID) - return types.SignTx(tx, signer, key.PrivateKey) -} - -// Unlock unlocks the given account indefinitely. -func (ks *KeyStore) Unlock(a accounts.Account, passphrase string) error { - return ks.TimedUnlock(a, passphrase, 0) -} - -// Lock removes the private key with the given address from memory. -func (ks *KeyStore) Lock(addr common.Address) error { - ks.mu.Lock() - if unl, found := ks.unlocked[addr]; found { - ks.mu.Unlock() - ks.expire(addr, unl, time.Duration(0)*time.Nanosecond) - } else { - ks.mu.Unlock() - } - return nil -} - -// TimedUnlock unlocks the given account with the passphrase. The account -// stays unlocked for the duration of timeout. A timeout of 0 unlocks the account -// until the program exits. The account must match a unique key file. -// -// If the account address is already unlocked for a duration, TimedUnlock extends or -// shortens the active unlock timeout. If the address was previously unlocked -// indefinitely the timeout is not altered. -func (ks *KeyStore) TimedUnlock(a accounts.Account, passphrase string, timeout time.Duration) error { - a, key, err := ks.getDecryptedKey(a, passphrase) - if err != nil { - return err - } - - ks.mu.Lock() - defer ks.mu.Unlock() - u, found := ks.unlocked[a.Address] - if found { - if u.abort == nil { - // The address was unlocked indefinitely, so unlocking - // it with a timeout would be confusing. - zeroKey(key.PrivateKey) - return nil - } - // Terminate the expire goroutine and replace it below. - close(u.abort) - } - if timeout > 0 { - u = &unlocked{Key: key, abort: make(chan struct{})} - go ks.expire(a.Address, u, timeout) - } else { - u = &unlocked{Key: key} - } - ks.unlocked[a.Address] = u - return nil -} - -// Find resolves the given account into a unique entry in the keystore. -func (ks *KeyStore) Find(a accounts.Account) (accounts.Account, error) { - ks.cache.maybeReload() - ks.cache.mu.Lock() - a, err := ks.cache.find(a) - ks.cache.mu.Unlock() - return a, err -} - -func (ks *KeyStore) getDecryptedKey(a accounts.Account, auth string) (accounts.Account, *Key, error) { - a, err := ks.Find(a) - if err != nil { - return a, nil, err - } - key, err := ks.storage.GetKey(a.Address, a.URL.Path, auth) - return a, key, err -} - -func (ks *KeyStore) expire(addr common.Address, u *unlocked, timeout time.Duration) { - t := time.NewTimer(timeout) - defer t.Stop() - select { - case <-u.abort: - // just quit - case <-t.C: - ks.mu.Lock() - // only drop if it's still the same key instance that dropLater - // was launched with. we can check that using pointer equality - // because the map stores a new pointer every time the key is - // unlocked. - if ks.unlocked[addr] == u { - zeroKey(u.PrivateKey) - delete(ks.unlocked, addr) - } - ks.mu.Unlock() - } -} - -// NewAccount generates a new key and stores it into the key directory, -// encrypting it with the passphrase. -func (ks *KeyStore) NewAccount(passphrase string) (accounts.Account, error) { - _, account, err := storeNewKey(ks.storage, crand.Reader, passphrase) - if err != nil { - return accounts.Account{}, err - } - // Add the account to the cache immediately rather - // than waiting for file system notifications to pick it up. - ks.cache.add(account) - ks.refreshWallets() - return account, nil -} - -// Export exports as a JSON key, encrypted with newPassphrase. -func (ks *KeyStore) Export(a accounts.Account, passphrase, newPassphrase string) (keyJSON []byte, err error) { - _, key, err := ks.getDecryptedKey(a, passphrase) - if err != nil { - return nil, err - } - var N, P int - if store, ok := ks.storage.(*keyStorePassphrase); ok { - N, P = store.scryptN, store.scryptP - } else { - N, P = StandardScryptN, StandardScryptP - } - return EncryptKey(key, newPassphrase, N, P) -} - -// Import stores the given encrypted JSON key into the key directory. -func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (accounts.Account, error) { - key, err := DecryptKey(keyJSON, passphrase) - if key != nil && key.PrivateKey != nil { - defer zeroKey(key.PrivateKey) - } - if err != nil { - return accounts.Account{}, err - } - ks.importMu.Lock() - defer ks.importMu.Unlock() - - if ks.cache.hasAddress(key.Address) { - return accounts.Account{ - Address: key.Address, - }, ErrAccountAlreadyExists - } - return ks.importKey(key, newPassphrase) -} - -// ImportECDSA stores the given key into the key directory, encrypting it with the passphrase. -func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (accounts.Account, error) { - ks.importMu.Lock() - defer ks.importMu.Unlock() - - key := newKeyFromECDSA(priv) - if ks.cache.hasAddress(key.Address) { - return accounts.Account{ - Address: key.Address, - }, ErrAccountAlreadyExists - } - return ks.importKey(key, passphrase) -} - -func (ks *KeyStore) importKey(key *Key, passphrase string) (accounts.Account, error) { - a := accounts.Account{Address: key.Address, URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.storage.JoinPath(keyFileName(key.Address))}} - if err := ks.storage.StoreKey(a.URL.Path, key, passphrase); err != nil { - return accounts.Account{}, err - } - ks.cache.add(a) - ks.refreshWallets() - return a, nil -} - -// Update changes the passphrase of an existing account. -func (ks *KeyStore) Update(a accounts.Account, passphrase, newPassphrase string) error { - a, key, err := ks.getDecryptedKey(a, passphrase) - if err != nil { - return err - } - return ks.storage.StoreKey(a.URL.Path, key, newPassphrase) -} - -// ImportPreSaleKey decrypts the given Ethereum presale wallet and stores -// a key file in the key directory. The key file is encrypted with the same passphrase. -func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (accounts.Account, error) { - a, _, err := importPreSaleKey(ks.storage, keyJSON, passphrase) - if err != nil { - return a, err - } - ks.cache.add(a) - ks.refreshWallets() - return a, nil -} - -// isUpdating returns whether the event notification loop is running. -// This method is mainly meant for tests. -func (ks *KeyStore) isUpdating() bool { - ks.mu.RLock() - defer ks.mu.RUnlock() - return ks.updating -} - -// zeroKey zeroes a private key in memory. -func zeroKey(k *ecdsa.PrivateKey) { - b := k.D.Bits() - for i := range b { - b[i] = 0 - } -} diff --git a/builder/accounts/keystore/keystore_fuzzing_test.go b/builder/accounts/keystore/keystore_fuzzing_test.go deleted file mode 100644 index 793b46336..000000000 --- a/builder/accounts/keystore/keystore_fuzzing_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2023 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 keystore - -import ( - "testing" -) - -func FuzzPassword(f *testing.F) { - f.Fuzz(func(t *testing.T, password string) { - ks := NewKeyStore(t.TempDir(), LightScryptN, LightScryptP) - a, err := ks.NewAccount(password) - if err != nil { - t.Fatal(err) - } - if err := ks.Unlock(a, password); err != nil { - t.Fatal(err) - } - }) -} diff --git a/builder/accounts/keystore/keystore_test.go b/builder/accounts/keystore/keystore_test.go deleted file mode 100644 index c9a23eddd..000000000 --- a/builder/accounts/keystore/keystore_test.go +++ /dev/null @@ -1,467 +0,0 @@ -// 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 keystore - -import ( - "math/rand" - "os" - "runtime" - "strings" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/event" - "golang.org/x/exp/slices" -) - -var testSigData = make([]byte, 32) - -func TestKeyStore(t *testing.T) { - t.Parallel() - dir, ks := tmpKeyStore(t, true) - - a, err := ks.NewAccount("foo") - if err != nil { - t.Fatal(err) - } - if !strings.HasPrefix(a.URL.Path, dir) { - t.Errorf("account file %s doesn't have dir prefix", a.URL) - } - stat, err := os.Stat(a.URL.Path) - if err != nil { - t.Fatalf("account file %s doesn't exist (%v)", a.URL, err) - } - if runtime.GOOS != "windows" && stat.Mode() != 0600 { - t.Fatalf("account file has wrong mode: got %o, want %o", stat.Mode(), 0600) - } - if !ks.HasAddress(a.Address) { - t.Errorf("HasAccount(%x) should've returned true", a.Address) - } - if err := ks.Update(a, "foo", "bar"); err != nil { - t.Errorf("Update error: %v", err) - } - if err := ks.Delete(a, "bar"); err != nil { - t.Errorf("Delete error: %v", err) - } - if common.FileExist(a.URL.Path) { - t.Errorf("account file %s should be gone after Delete", a.URL) - } - if ks.HasAddress(a.Address) { - t.Errorf("HasAccount(%x) should've returned true after Delete", a.Address) - } -} - -func TestSign(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - - pass := "" // not used but required by API - a1, err := ks.NewAccount(pass) - if err != nil { - t.Fatal(err) - } - if err := ks.Unlock(a1, ""); err != nil { - t.Fatal(err) - } - if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); err != nil { - t.Fatal(err) - } -} - -func TestSignWithPassphrase(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - - pass := "passwd" - acc, err := ks.NewAccount(pass) - if err != nil { - t.Fatal(err) - } - - if _, unlocked := ks.unlocked[acc.Address]; unlocked { - t.Fatal("expected account to be locked") - } - - _, err = ks.SignHashWithPassphrase(acc, pass, testSigData) - if err != nil { - t.Fatal(err) - } - - if _, unlocked := ks.unlocked[acc.Address]; unlocked { - t.Fatal("expected account to be locked") - } - - if _, err = ks.SignHashWithPassphrase(acc, "invalid passwd", testSigData); err == nil { - t.Fatal("expected SignHashWithPassphrase to fail with invalid password") - } -} - -func TestTimedUnlock(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - - pass := "foo" - a1, err := ks.NewAccount(pass) - if err != nil { - t.Fatal(err) - } - - // Signing without passphrase fails because account is locked - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { - t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err) - } - - // Signing with passphrase works - if err = ks.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { - t.Fatal(err) - } - - // Signing without passphrase works because account is temp unlocked - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != nil { - t.Fatal("Signing shouldn't return an error after unlocking, got ", err) - } - - // Signing fails again after automatic locking - time.Sleep(250 * time.Millisecond) - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { - t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) - } -} - -func TestOverrideUnlock(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, false) - - pass := "foo" - a1, err := ks.NewAccount(pass) - if err != nil { - t.Fatal(err) - } - - // Unlock indefinitely. - if err = ks.TimedUnlock(a1, pass, 5*time.Minute); err != nil { - t.Fatal(err) - } - - // Signing without passphrase works because account is temp unlocked - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != nil { - t.Fatal("Signing shouldn't return an error after unlocking, got ", err) - } - - // reset unlock to a shorter period, invalidates the previous unlock - if err = ks.TimedUnlock(a1, pass, 100*time.Millisecond); err != nil { - t.Fatal(err) - } - - // Signing without passphrase still works because account is temp unlocked - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != nil { - t.Fatal("Signing shouldn't return an error after unlocking, got ", err) - } - - // Signing fails again after automatic locking - time.Sleep(250 * time.Millisecond) - _, err = ks.SignHash(accounts.Account{Address: a1.Address}, testSigData) - if err != ErrLocked { - t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err) - } -} - -// This test should fail under -race if signing races the expiration goroutine. -func TestSignRace(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, false) - - // Create a test account. - a1, err := ks.NewAccount("") - if err != nil { - t.Fatal("could not create the test account", err) - } - - if err := ks.TimedUnlock(a1, "", 15*time.Millisecond); err != nil { - t.Fatal("could not unlock the test account", err) - } - end := time.Now().Add(500 * time.Millisecond) - for time.Now().Before(end) { - if _, err := ks.SignHash(accounts.Account{Address: a1.Address}, testSigData); err == ErrLocked { - return - } else if err != nil { - t.Errorf("Sign error: %v", err) - return - } - time.Sleep(1 * time.Millisecond) - } - t.Errorf("Account did not lock within the timeout") -} - -// waitForKsUpdating waits until the updating-status of the ks reaches the -// desired wantStatus. -// It waits for a maximum time of maxTime, and returns false if it does not -// finish in time -func waitForKsUpdating(t *testing.T, ks *KeyStore, wantStatus bool, maxTime time.Duration) bool { - t.Helper() - // Wait max 250 ms, then return false - for t0 := time.Now(); time.Since(t0) < maxTime; { - if ks.isUpdating() == wantStatus { - return true - } - time.Sleep(25 * time.Millisecond) - } - return false -} - -// Tests that the wallet notifier loop starts and stops correctly based on the -// addition and removal of wallet event subscriptions. -func TestWalletNotifierLifecycle(t *testing.T) { - t.Parallel() - // Create a temporary keystore to test with - _, ks := tmpKeyStore(t, false) - - // Ensure that the notification updater is not running yet - time.Sleep(250 * time.Millisecond) - - if ks.isUpdating() { - t.Errorf("wallet notifier running without subscribers") - } - // Subscribe to the wallet feed and ensure the updater boots up - updates := make(chan accounts.WalletEvent) - - subs := make([]event.Subscription, 2) - for i := 0; i < len(subs); i++ { - // Create a new subscription - subs[i] = ks.Subscribe(updates) - if !waitForKsUpdating(t, ks, true, 250*time.Millisecond) { - t.Errorf("sub %d: wallet notifier not running after subscription", i) - } - } - // Close all but one sub - for i := 0; i < len(subs)-1; i++ { - // Close an existing subscription - subs[i].Unsubscribe() - } - // Check that it is still running - time.Sleep(250 * time.Millisecond) - - if !ks.isUpdating() { - t.Fatal("event notifier stopped prematurely") - } - // Unsubscribe the last one and ensure the updater terminates eventually. - subs[len(subs)-1].Unsubscribe() - if !waitForKsUpdating(t, ks, false, 4*time.Second) { - t.Errorf("wallet notifier didn't terminate after unsubscribe") - } -} - -type walletEvent struct { - accounts.WalletEvent - a accounts.Account -} - -// Tests that wallet notifications and correctly fired when accounts are added -// or deleted from the keystore. -func TestWalletNotifications(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, false) - - // Subscribe to the wallet feed and collect events. - var ( - events []walletEvent - updates = make(chan accounts.WalletEvent) - sub = ks.Subscribe(updates) - ) - defer sub.Unsubscribe() - go func() { - for { - select { - case ev := <-updates: - events = append(events, walletEvent{ev, ev.Wallet.Accounts()[0]}) - case <-sub.Err(): - close(updates) - return - } - } - }() - - // Randomly add and remove accounts. - var ( - live = make(map[common.Address]accounts.Account) - wantEvents []walletEvent - ) - for i := 0; i < 1024; i++ { - if create := len(live) == 0 || rand.Int()%4 > 0; create { - // Add a new account and ensure wallet notifications arrives - account, err := ks.NewAccount("") - if err != nil { - t.Fatalf("failed to create test account: %v", err) - } - live[account.Address] = account - wantEvents = append(wantEvents, walletEvent{accounts.WalletEvent{Kind: accounts.WalletArrived}, account}) - } else { - // Delete a random account. - var account accounts.Account - for _, a := range live { - account = a - break - } - if err := ks.Delete(account, ""); err != nil { - t.Fatalf("failed to delete test account: %v", err) - } - delete(live, account.Address) - wantEvents = append(wantEvents, walletEvent{accounts.WalletEvent{Kind: accounts.WalletDropped}, account}) - } - } - - // Shut down the event collector and check events. - sub.Unsubscribe() - for ev := range updates { - events = append(events, walletEvent{ev, ev.Wallet.Accounts()[0]}) - } - checkAccounts(t, live, ks.Wallets()) - checkEvents(t, wantEvents, events) -} - -// TestImportExport tests the import functionality of a keystore. -func TestImportECDSA(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - key, err := crypto.GenerateKey() - if err != nil { - t.Fatalf("failed to generate key: %v", key) - } - if _, err = ks.ImportECDSA(key, "old"); err != nil { - t.Errorf("importing failed: %v", err) - } - if _, err = ks.ImportECDSA(key, "old"); err == nil { - t.Errorf("importing same key twice succeeded") - } - if _, err = ks.ImportECDSA(key, "new"); err == nil { - t.Errorf("importing same key twice succeeded") - } -} - -// TestImportECDSA tests the import and export functionality of a keystore. -func TestImportExport(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - acc, err := ks.NewAccount("old") - if err != nil { - t.Fatalf("failed to create account: %v", acc) - } - json, err := ks.Export(acc, "old", "new") - if err != nil { - t.Fatalf("failed to export account: %v", acc) - } - _, ks2 := tmpKeyStore(t, true) - if _, err = ks2.Import(json, "old", "old"); err == nil { - t.Errorf("importing with invalid password succeeded") - } - acc2, err := ks2.Import(json, "new", "new") - if err != nil { - t.Errorf("importing failed: %v", err) - } - if acc.Address != acc2.Address { - t.Error("imported account does not match exported account") - } - if _, err = ks2.Import(json, "new", "new"); err == nil { - t.Errorf("importing a key twice succeeded") - } -} - -// TestImportRace tests the keystore on races. -// This test should fail under -race if importing races. -func TestImportRace(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStore(t, true) - acc, err := ks.NewAccount("old") - if err != nil { - t.Fatalf("failed to create account: %v", acc) - } - json, err := ks.Export(acc, "old", "new") - if err != nil { - t.Fatalf("failed to export account: %v", acc) - } - _, ks2 := tmpKeyStore(t, true) - var atom atomic.Uint32 - var wg sync.WaitGroup - wg.Add(2) - for i := 0; i < 2; i++ { - go func() { - defer wg.Done() - if _, err := ks2.Import(json, "new", "new"); err != nil { - atom.Add(1) - } - }() - } - wg.Wait() - if atom.Load() != 1 { - t.Errorf("Import is racy") - } -} - -// checkAccounts checks that all known live accounts are present in the wallet list. -func checkAccounts(t *testing.T, live map[common.Address]accounts.Account, wallets []accounts.Wallet) { - if len(live) != len(wallets) { - t.Errorf("wallet list doesn't match required accounts: have %d, want %d", len(wallets), len(live)) - return - } - liveList := make([]accounts.Account, 0, len(live)) - for _, account := range live { - liveList = append(liveList, account) - } - slices.SortFunc(liveList, byURL) - for j, wallet := range wallets { - if accs := wallet.Accounts(); len(accs) != 1 { - t.Errorf("wallet %d: contains invalid number of accounts: have %d, want 1", j, len(accs)) - } else if accs[0] != liveList[j] { - t.Errorf("wallet %d: account mismatch: have %v, want %v", j, accs[0], liveList[j]) - } - } -} - -// checkEvents checks that all events in 'want' are present in 'have'. Events may be present multiple times. -func checkEvents(t *testing.T, want []walletEvent, have []walletEvent) { - for _, wantEv := range want { - nmatch := 0 - for ; len(have) > 0; nmatch++ { - if have[0].Kind != wantEv.Kind || have[0].a != wantEv.a { - break - } - have = have[1:] - } - if nmatch == 0 { - t.Fatalf("can't find event with Kind=%v for %x", wantEv.Kind, wantEv.a.Address) - } - } -} - -func tmpKeyStore(t *testing.T, encrypted bool) (string, *KeyStore) { - d := t.TempDir() - newKs := NewPlaintextKeyStore - if encrypted { - newKs = func(kd string) *KeyStore { return NewKeyStore(kd, veryLightScryptN, veryLightScryptP) } - } - return d, newKs(d) -} diff --git a/builder/accounts/keystore/passphrase.go b/builder/accounts/keystore/passphrase.go deleted file mode 100644 index e7a7f8d0c..000000000 --- a/builder/accounts/keystore/passphrase.go +++ /dev/null @@ -1,368 +0,0 @@ -// 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 . - -/* - -This key store behaves as KeyStorePlain with the difference that -the private key is encrypted and on disk uses another JSON encoding. - -The crypto is documented at https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition - -*/ - -package keystore - -import ( - "bytes" - "crypto/aes" - "crypto/rand" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" - "golang.org/x/crypto/pbkdf2" - "golang.org/x/crypto/scrypt" -) - -const ( - keyHeaderKDF = "scrypt" - - // StandardScryptN is the N parameter of Scrypt encryption algorithm, using 256MB - // memory and taking approximately 1s CPU time on a modern processor. - StandardScryptN = 1 << 18 - - // StandardScryptP is the P parameter of Scrypt encryption algorithm, using 256MB - // memory and taking approximately 1s CPU time on a modern processor. - StandardScryptP = 1 - - // LightScryptN is the N parameter of Scrypt encryption algorithm, using 4MB - // memory and taking approximately 100ms CPU time on a modern processor. - LightScryptN = 1 << 12 - - // LightScryptP is the P parameter of Scrypt encryption algorithm, using 4MB - // memory and taking approximately 100ms CPU time on a modern processor. - LightScryptP = 6 - - scryptR = 8 - scryptDKLen = 32 -) - -type keyStorePassphrase struct { - keysDirPath string - scryptN int - scryptP int - // skipKeyFileVerification disables the security-feature which does - // reads and decrypts any newly created keyfiles. This should be 'false' in all - // cases except tests -- setting this to 'true' is not recommended. - skipKeyFileVerification bool -} - -func (ks keyStorePassphrase) GetKey(addr common.Address, filename, auth string) (*Key, error) { - // Load the key from the keystore and decrypt its contents - keyjson, err := os.ReadFile(filename) - if err != nil { - return nil, err - } - key, err := DecryptKey(keyjson, auth) - if err != nil { - return nil, err - } - // Make sure we're really operating on the requested key (no swap attacks) - if key.Address != addr { - return nil, fmt.Errorf("key content mismatch: have account %x, want %x", key.Address, addr) - } - return key, nil -} - -// StoreKey generates a key, encrypts with 'auth' and stores in the given directory -func StoreKey(dir, auth string, scryptN, scryptP int) (accounts.Account, error) { - _, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP, false}, rand.Reader, auth) - return a, err -} - -func (ks keyStorePassphrase) StoreKey(filename string, key *Key, auth string) error { - keyjson, err := EncryptKey(key, auth, ks.scryptN, ks.scryptP) - if err != nil { - return err - } - // Write into temporary file - tmpName, err := writeTemporaryKeyFile(filename, keyjson) - if err != nil { - return err - } - if !ks.skipKeyFileVerification { - // Verify that we can decrypt the file with the given password. - _, err = ks.GetKey(key.Address, tmpName, auth) - if err != nil { - msg := "An error was encountered when saving and verifying the keystore file. \n" + - "This indicates that the keystore is corrupted. \n" + - "The corrupted file is stored at \n%v\n" + - "Please file a ticket at:\n\n" + - "https://github.com/ethereum/go-ethereum/issues." + - "The error was : %s" - //lint:ignore ST1005 This is a message for the user - return fmt.Errorf(msg, tmpName, err) - } - } - return os.Rename(tmpName, filename) -} - -func (ks keyStorePassphrase) JoinPath(filename string) string { - if filepath.IsAbs(filename) { - return filename - } - return filepath.Join(ks.keysDirPath, filename) -} - -// EncryptDataV3 encrypts the data given as 'data' with the password 'auth'. -func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error) { - salt := make([]byte, 32) - if _, err := io.ReadFull(rand.Reader, salt); err != nil { - panic("reading from crypto/rand failed: " + err.Error()) - } - derivedKey, err := scrypt.Key(auth, salt, scryptN, scryptR, scryptP, scryptDKLen) - if err != nil { - return CryptoJSON{}, err - } - encryptKey := derivedKey[:16] - - iv := make([]byte, aes.BlockSize) // 16 - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - panic("reading from crypto/rand failed: " + err.Error()) - } - cipherText, err := aesCTRXOR(encryptKey, data, iv) - if err != nil { - return CryptoJSON{}, err - } - mac := crypto.Keccak256(derivedKey[16:32], cipherText) - - scryptParamsJSON := make(map[string]interface{}, 5) - scryptParamsJSON["n"] = scryptN - scryptParamsJSON["r"] = scryptR - scryptParamsJSON["p"] = scryptP - scryptParamsJSON["dklen"] = scryptDKLen - scryptParamsJSON["salt"] = hex.EncodeToString(salt) - cipherParamsJSON := cipherparamsJSON{ - IV: hex.EncodeToString(iv), - } - - cryptoStruct := CryptoJSON{ - Cipher: "aes-128-ctr", - CipherText: hex.EncodeToString(cipherText), - CipherParams: cipherParamsJSON, - KDF: keyHeaderKDF, - KDFParams: scryptParamsJSON, - MAC: hex.EncodeToString(mac), - } - return cryptoStruct, nil -} - -// EncryptKey encrypts a key using the specified scrypt parameters into a json -// blob that can be decrypted later on. -func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) { - keyBytes := math.PaddedBigBytes(key.PrivateKey.D, 32) - cryptoStruct, err := EncryptDataV3(keyBytes, []byte(auth), scryptN, scryptP) - if err != nil { - return nil, err - } - encryptedKeyJSONV3 := encryptedKeyJSONV3{ - hex.EncodeToString(key.Address[:]), - cryptoStruct, - key.Id.String(), - version, - } - return json.Marshal(encryptedKeyJSONV3) -} - -// DecryptKey decrypts a key from a json blob, returning the private key itself. -func DecryptKey(keyjson []byte, auth string) (*Key, error) { - // Parse the json into a simple map to fetch the key version - m := make(map[string]interface{}) - if err := json.Unmarshal(keyjson, &m); err != nil { - return nil, err - } - // Depending on the version try to parse one way or another - var ( - keyBytes, keyId []byte - err error - ) - if version, ok := m["version"].(string); ok && version == "1" { - k := new(encryptedKeyJSONV1) - if err := json.Unmarshal(keyjson, k); err != nil { - return nil, err - } - keyBytes, keyId, err = decryptKeyV1(k, auth) - } else { - k := new(encryptedKeyJSONV3) - if err := json.Unmarshal(keyjson, k); err != nil { - return nil, err - } - keyBytes, keyId, err = decryptKeyV3(k, auth) - } - // Handle any decryption errors and return the key - if err != nil { - return nil, err - } - key, err := crypto.ToECDSA(keyBytes) - if err != nil { - return nil, fmt.Errorf("invalid key: %w", err) - } - id, err := uuid.FromBytes(keyId) - if err != nil { - return nil, fmt.Errorf("invalid UUID: %w", err) - } - return &Key{ - Id: id, - Address: crypto.PubkeyToAddress(key.PublicKey), - PrivateKey: key, - }, nil -} - -func DecryptDataV3(cryptoJson CryptoJSON, auth string) ([]byte, error) { - if cryptoJson.Cipher != "aes-128-ctr" { - return nil, fmt.Errorf("cipher not supported: %v", cryptoJson.Cipher) - } - mac, err := hex.DecodeString(cryptoJson.MAC) - if err != nil { - return nil, err - } - - iv, err := hex.DecodeString(cryptoJson.CipherParams.IV) - if err != nil { - return nil, err - } - - cipherText, err := hex.DecodeString(cryptoJson.CipherText) - if err != nil { - return nil, err - } - - derivedKey, err := getKDFKey(cryptoJson, auth) - if err != nil { - return nil, err - } - - calculatedMAC := crypto.Keccak256(derivedKey[16:32], cipherText) - if !bytes.Equal(calculatedMAC, mac) { - return nil, ErrDecrypt - } - - plainText, err := aesCTRXOR(derivedKey[:16], cipherText, iv) - if err != nil { - return nil, err - } - return plainText, err -} - -func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byte, keyId []byte, err error) { - if keyProtected.Version != version { - return nil, nil, fmt.Errorf("version not supported: %v", keyProtected.Version) - } - keyUUID, err := uuid.Parse(keyProtected.Id) - if err != nil { - return nil, nil, err - } - keyId = keyUUID[:] - plainText, err := DecryptDataV3(keyProtected.Crypto, auth) - if err != nil { - return nil, nil, err - } - return plainText, keyId, err -} - -func decryptKeyV1(keyProtected *encryptedKeyJSONV1, auth string) (keyBytes []byte, keyId []byte, err error) { - keyUUID, err := uuid.Parse(keyProtected.Id) - if err != nil { - return nil, nil, err - } - keyId = keyUUID[:] - mac, err := hex.DecodeString(keyProtected.Crypto.MAC) - if err != nil { - return nil, nil, err - } - - iv, err := hex.DecodeString(keyProtected.Crypto.CipherParams.IV) - if err != nil { - return nil, nil, err - } - - cipherText, err := hex.DecodeString(keyProtected.Crypto.CipherText) - if err != nil { - return nil, nil, err - } - - derivedKey, err := getKDFKey(keyProtected.Crypto, auth) - if err != nil { - return nil, nil, err - } - - calculatedMAC := crypto.Keccak256(derivedKey[16:32], cipherText) - if !bytes.Equal(calculatedMAC, mac) { - return nil, nil, ErrDecrypt - } - - plainText, err := aesCBCDecrypt(crypto.Keccak256(derivedKey[:16])[:16], cipherText, iv) - if err != nil { - return nil, nil, err - } - return plainText, keyId, err -} - -func getKDFKey(cryptoJSON CryptoJSON, auth string) ([]byte, error) { - authArray := []byte(auth) - salt, err := hex.DecodeString(cryptoJSON.KDFParams["salt"].(string)) - if err != nil { - return nil, err - } - dkLen := ensureInt(cryptoJSON.KDFParams["dklen"]) - - if cryptoJSON.KDF == keyHeaderKDF { - n := ensureInt(cryptoJSON.KDFParams["n"]) - r := ensureInt(cryptoJSON.KDFParams["r"]) - p := ensureInt(cryptoJSON.KDFParams["p"]) - return scrypt.Key(authArray, salt, n, r, p, dkLen) - } else if cryptoJSON.KDF == "pbkdf2" { - c := ensureInt(cryptoJSON.KDFParams["c"]) - prf := cryptoJSON.KDFParams["prf"].(string) - if prf != "hmac-sha256" { - return nil, fmt.Errorf("unsupported PBKDF2 PRF: %s", prf) - } - key := pbkdf2.Key(authArray, salt, c, dkLen, sha256.New) - return key, nil - } - - return nil, fmt.Errorf("unsupported KDF: %s", cryptoJSON.KDF) -} - -// TODO: can we do without this when unmarshalling dynamic JSON? -// why do integers in KDF params end up as float64 and not int after -// unmarshal? -func ensureInt(x interface{}) int { - res, ok := x.(int) - if !ok { - res = int(x.(float64)) - } - return res -} diff --git a/builder/accounts/keystore/passphrase_test.go b/builder/accounts/keystore/passphrase_test.go deleted file mode 100644 index 20ec0f551..000000000 --- a/builder/accounts/keystore/passphrase_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 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 keystore - -import ( - "os" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -const ( - veryLightScryptN = 2 - veryLightScryptP = 1 -) - -// Tests that a json key file can be decrypted and encrypted in multiple rounds. -func TestKeyEncryptDecrypt(t *testing.T) { - t.Parallel() - keyjson, err := os.ReadFile("testdata/very-light-scrypt.json") - if err != nil { - t.Fatal(err) - } - password := "" - address := common.HexToAddress("45dea0fb0bba44f4fcf290bba71fd57d7117cbb8") - - // Do a few rounds of decryption and encryption - for i := 0; i < 3; i++ { - // Try a bad password first - if _, err := DecryptKey(keyjson, password+"bad"); err == nil { - t.Errorf("test %d: json key decrypted with bad password", i) - } - // Decrypt with the correct password - key, err := DecryptKey(keyjson, password) - if err != nil { - t.Fatalf("test %d: json key failed to decrypt: %v", i, err) - } - if key.Address != address { - t.Errorf("test %d: key address mismatch: have %x, want %x", i, key.Address, address) - } - // Recrypt with a new password and start over - password += "new data appended" // nolint: gosec - if keyjson, err = EncryptKey(key, password, veryLightScryptN, veryLightScryptP); err != nil { - t.Errorf("test %d: failed to re-encrypt key %v", i, err) - } - } -} diff --git a/builder/accounts/keystore/plain.go b/builder/accounts/keystore/plain.go deleted file mode 100644 index f62a133ce..000000000 --- a/builder/accounts/keystore/plain.go +++ /dev/null @@ -1,61 +0,0 @@ -// 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 keystore - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - - "github.com/ethereum/go-ethereum/common" -) - -type keyStorePlain struct { - keysDirPath string -} - -func (ks keyStorePlain) GetKey(addr common.Address, filename, auth string) (*Key, error) { - fd, err := os.Open(filename) - if err != nil { - return nil, err - } - defer fd.Close() - key := new(Key) - if err := json.NewDecoder(fd).Decode(key); err != nil { - return nil, err - } - if key.Address != addr { - return nil, fmt.Errorf("key content mismatch: have address %x, want %x", key.Address, addr) - } - return key, nil -} - -func (ks keyStorePlain) StoreKey(filename string, key *Key, auth string) error { - content, err := json.Marshal(key) - if err != nil { - return err - } - return writeKeyFile(filename, content) -} - -func (ks keyStorePlain) JoinPath(filename string) string { - if filepath.IsAbs(filename) { - return filename - } - return filepath.Join(ks.keysDirPath, filename) -} diff --git a/builder/accounts/keystore/plain_test.go b/builder/accounts/keystore/plain_test.go deleted file mode 100644 index 737eb7fd6..000000000 --- a/builder/accounts/keystore/plain_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// 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 keystore - -import ( - "crypto/rand" - "encoding/hex" - "fmt" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) { - d := t.TempDir() - if encrypted { - ks = &keyStorePassphrase{d, veryLightScryptN, veryLightScryptP, true} - } else { - ks = &keyStorePlain{d} - } - return d, ks -} - -func TestKeyStorePlain(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStoreIface(t, false) - - pass := "" // not used but required by API - k1, account, err := storeNewKey(ks, rand.Reader, pass) - if err != nil { - t.Fatal(err) - } - k2, err := ks.GetKey(k1.Address, account.URL.Path, pass) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(k1.Address, k2.Address) { - t.Fatal(err) - } - if !reflect.DeepEqual(k1.PrivateKey, k2.PrivateKey) { - t.Fatal(err) - } -} - -func TestKeyStorePassphrase(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStoreIface(t, true) - - pass := "foo" - k1, account, err := storeNewKey(ks, rand.Reader, pass) - if err != nil { - t.Fatal(err) - } - k2, err := ks.GetKey(k1.Address, account.URL.Path, pass) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(k1.Address, k2.Address) { - t.Fatal(err) - } - if !reflect.DeepEqual(k1.PrivateKey, k2.PrivateKey) { - t.Fatal(err) - } -} - -func TestKeyStorePassphraseDecryptionFail(t *testing.T) { - t.Parallel() - _, ks := tmpKeyStoreIface(t, true) - - pass := "foo" - k1, account, err := storeNewKey(ks, rand.Reader, pass) - if err != nil { - t.Fatal(err) - } - if _, err = ks.GetKey(k1.Address, account.URL.Path, "bar"); err != ErrDecrypt { - t.Fatalf("wrong error for invalid password\ngot %q\nwant %q", err, ErrDecrypt) - } -} - -func TestImportPreSaleKey(t *testing.T) { - t.Parallel() - dir, ks := tmpKeyStoreIface(t, true) - - // file content of a presale key file generated with: - // python pyethsaletool.py genwallet - // with password "foo" - fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" - pass := "foo" - account, _, err := importPreSaleKey(ks, []byte(fileContent), pass) - if err != nil { - t.Fatal(err) - } - if account.Address != common.HexToAddress("d4584b5f6229b7be90727b0fc8c6b91bb427821f") { - t.Errorf("imported account has wrong address %x", account.Address) - } - if !strings.HasPrefix(account.URL.Path, dir) { - t.Errorf("imported account file not in keystore directory: %q", account.URL) - } -} - -// Test and utils for the key store tests in the Ethereum JSON tests; -// testdataKeyStoreTests/basic_tests.json -type KeyStoreTestV3 struct { - Json encryptedKeyJSONV3 - Password string - Priv string -} - -type KeyStoreTestV1 struct { - Json encryptedKeyJSONV1 - Password string - Priv string -} - -func TestV3_PBKDF2_1(t *testing.T) { - t.Parallel() - tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) - testDecryptV3(tests["wikipage_test_vector_pbkdf2"], t) -} - -var testsSubmodule = filepath.Join("..", "..", "tests", "testdata", "KeyStoreTests") - -func skipIfSubmoduleMissing(t *testing.T) { - if !common.FileExist(testsSubmodule) { - t.Skipf("can't find JSON tests from submodule at %s", testsSubmodule) - } -} - -func TestV3_PBKDF2_2(t *testing.T) { - skipIfSubmoduleMissing(t) - t.Parallel() - tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t) - testDecryptV3(tests["test1"], t) -} - -func TestV3_PBKDF2_3(t *testing.T) { - skipIfSubmoduleMissing(t) - t.Parallel() - tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t) - testDecryptV3(tests["python_generated_test_with_odd_iv"], t) -} - -func TestV3_PBKDF2_4(t *testing.T) { - skipIfSubmoduleMissing(t) - t.Parallel() - tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t) - testDecryptV3(tests["evilnonce"], t) -} - -func TestV3_Scrypt_1(t *testing.T) { - t.Parallel() - tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) - testDecryptV3(tests["wikipage_test_vector_scrypt"], t) -} - -func TestV3_Scrypt_2(t *testing.T) { - skipIfSubmoduleMissing(t) - t.Parallel() - tests := loadKeyStoreTestV3(filepath.Join(testsSubmodule, "basic_tests.json"), t) - testDecryptV3(tests["test2"], t) -} - -func TestV1_1(t *testing.T) { - t.Parallel() - tests := loadKeyStoreTestV1("testdata/v1_test_vector.json", t) - testDecryptV1(tests["test1"], t) -} - -func TestV1_2(t *testing.T) { - t.Parallel() - ks := &keyStorePassphrase{"testdata/v1", LightScryptN, LightScryptP, true} - addr := common.HexToAddress("cb61d5a9c4896fb9658090b597ef0e7be6f7b67e") - file := "testdata/v1/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e" - k, err := ks.GetKey(addr, file, "g") - if err != nil { - t.Fatal(err) - } - privHex := hex.EncodeToString(crypto.FromECDSA(k.PrivateKey)) - expectedHex := "d1b1178d3529626a1a93e073f65028370d14c7eb0936eb42abef05db6f37ad7d" - if privHex != expectedHex { - t.Fatal(fmt.Errorf("Unexpected privkey: %v, expected %v", privHex, expectedHex)) - } -} - -func testDecryptV3(test KeyStoreTestV3, t *testing.T) { - privBytes, _, err := decryptKeyV3(&test.Json, test.Password) - if err != nil { - t.Fatal(err) - } - privHex := hex.EncodeToString(privBytes) - if test.Priv != privHex { - t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex)) - } -} - -func testDecryptV1(test KeyStoreTestV1, t *testing.T) { - privBytes, _, err := decryptKeyV1(&test.Json, test.Password) - if err != nil { - t.Fatal(err) - } - privHex := hex.EncodeToString(privBytes) - if test.Priv != privHex { - t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex)) - } -} - -func loadKeyStoreTestV3(file string, t *testing.T) map[string]KeyStoreTestV3 { - tests := make(map[string]KeyStoreTestV3) - err := common.LoadJSON(file, &tests) - if err != nil { - t.Fatal(err) - } - return tests -} - -func loadKeyStoreTestV1(file string, t *testing.T) map[string]KeyStoreTestV1 { - tests := make(map[string]KeyStoreTestV1) - err := common.LoadJSON(file, &tests) - if err != nil { - t.Fatal(err) - } - return tests -} - -func TestKeyForDirectICAP(t *testing.T) { - t.Parallel() - key := NewKeyForDirectICAP(rand.Reader) - if !strings.HasPrefix(key.Address.Hex(), "0x00") { - t.Errorf("Expected first address byte to be zero, have: %s", key.Address.Hex()) - } -} - -func TestV3_31_Byte_Key(t *testing.T) { - t.Parallel() - tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) - testDecryptV3(tests["31_byte_key"], t) -} - -func TestV3_30_Byte_Key(t *testing.T) { - t.Parallel() - tests := loadKeyStoreTestV3("testdata/v3_test_vector.json", t) - testDecryptV3(tests["30_byte_key"], t) -} diff --git a/builder/accounts/keystore/presale.go b/builder/accounts/keystore/presale.go deleted file mode 100644 index 0664dc2cd..000000000 --- a/builder/accounts/keystore/presale.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2016 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 keystore - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" - "golang.org/x/crypto/pbkdf2" -) - -// creates a Key and stores that in the given KeyStore by decrypting a presale key JSON -func importPreSaleKey(keyStore keyStore, keyJSON []byte, password string) (accounts.Account, *Key, error) { - key, err := decryptPreSaleKey(keyJSON, password) - if err != nil { - return accounts.Account{}, nil, err - } - key.Id, err = uuid.NewRandom() - if err != nil { - return accounts.Account{}, nil, err - } - a := accounts.Account{ - Address: key.Address, - URL: accounts.URL{ - Scheme: KeyStoreScheme, - Path: keyStore.JoinPath(keyFileName(key.Address)), - }, - } - err = keyStore.StoreKey(a.URL.Path, key, password) - return a, key, err -} - -func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error) { - preSaleKeyStruct := struct { - EncSeed string - EthAddr string - Email string - BtcAddr string - }{} - err = json.Unmarshal(fileContent, &preSaleKeyStruct) - if err != nil { - return nil, err - } - encSeedBytes, err := hex.DecodeString(preSaleKeyStruct.EncSeed) - if err != nil { - return nil, errors.New("invalid hex in encSeed") - } - if len(encSeedBytes) < 16 { - return nil, errors.New("invalid encSeed, too short") - } - iv := encSeedBytes[:16] - cipherText := encSeedBytes[16:] - /* - See https://github.com/ethereum/pyethsaletool - - pyethsaletool generates the encryption key from password by - 2000 rounds of PBKDF2 with HMAC-SHA-256 using password as salt (:(). - 16 byte key length within PBKDF2 and resulting key is used as AES key - */ - passBytes := []byte(password) - derivedKey := pbkdf2.Key(passBytes, passBytes, 2000, 16, sha256.New) - plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv) - if err != nil { - return nil, err - } - ethPriv := crypto.Keccak256(plainText) - ecKey := crypto.ToECDSAUnsafe(ethPriv) - - key = &Key{ - Id: uuid.UUID{}, - Address: crypto.PubkeyToAddress(ecKey.PublicKey), - PrivateKey: ecKey, - } - derivedAddr := hex.EncodeToString(key.Address.Bytes()) // needed because .Hex() gives leading "0x" - expectedAddr := preSaleKeyStruct.EthAddr - if derivedAddr != expectedAddr { - err = fmt.Errorf("decrypted addr '%s' not equal to expected addr '%s'", derivedAddr, expectedAddr) - } - return key, err -} - -func aesCTRXOR(key, inText, iv []byte) ([]byte, error) { - // AES-128 is selected due to size of encryptKey. - aesBlock, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - stream := cipher.NewCTR(aesBlock, iv) - outText := make([]byte, len(inText)) - stream.XORKeyStream(outText, inText) - return outText, err -} - -func aesCBCDecrypt(key, cipherText, iv []byte) ([]byte, error) { - aesBlock, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - decrypter := cipher.NewCBCDecrypter(aesBlock, iv) - paddedPlaintext := make([]byte, len(cipherText)) - decrypter.CryptBlocks(paddedPlaintext, cipherText) - plaintext := pkcs7Unpad(paddedPlaintext) - if plaintext == nil { - return nil, ErrDecrypt - } - return plaintext, err -} - -// From https://leanpub.com/gocrypto/read#leanpub-auto-block-cipher-modes -func pkcs7Unpad(in []byte) []byte { - if len(in) == 0 { - return nil - } - - padding := in[len(in)-1] - if int(padding) > len(in) || padding > aes.BlockSize { - return nil - } else if padding == 0 { - return nil - } - - for i := len(in) - 1; i > len(in)-int(padding)-1; i-- { - if in[i] != padding { - return nil - } - } - return in[:len(in)-int(padding)] -} diff --git a/builder/accounts/keystore/testdata/dupes/1 b/builder/accounts/keystore/testdata/dupes/1 deleted file mode 100644 index a3868ec6d..000000000 --- a/builder/accounts/keystore/testdata/dupes/1 +++ /dev/null @@ -1 +0,0 @@ -{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/dupes/2 b/builder/accounts/keystore/testdata/dupes/2 deleted file mode 100644 index a3868ec6d..000000000 --- a/builder/accounts/keystore/testdata/dupes/2 +++ /dev/null @@ -1 +0,0 @@ -{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/dupes/foo b/builder/accounts/keystore/testdata/dupes/foo deleted file mode 100644 index c57060aea..000000000 --- a/builder/accounts/keystore/testdata/dupes/foo +++ /dev/null @@ -1 +0,0 @@ -{"address":"7ef5a6135f1fd6a02593eedc869c6d41d934aef8","crypto":{"cipher":"aes-128-ctr","ciphertext":"1d0839166e7a15b9c1333fc865d69858b22df26815ccf601b28219b6192974e1","cipherparams":{"iv":"8df6caa7ff1b00c4e871f002cb7921ed"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"e5e6ef3f4ea695f496b643ebd3f75c0aa58ef4070e90c80c5d3fb0241bf1595c"},"mac":"6d16dfde774845e4585357f24bce530528bc69f4f84e1e22880d34fa45c273e5"},"id":"950077c7-71e3-4c44-a4a1-143919141ed4","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/.hiddenfile b/builder/accounts/keystore/testdata/keystore/.hiddenfile deleted file mode 100644 index d91faccde..000000000 --- a/builder/accounts/keystore/testdata/keystore/.hiddenfile +++ /dev/null @@ -1 +0,0 @@ -{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} diff --git a/builder/accounts/keystore/testdata/keystore/README b/builder/accounts/keystore/testdata/keystore/README deleted file mode 100644 index 6af9ac3f1..000000000 --- a/builder/accounts/keystore/testdata/keystore/README +++ /dev/null @@ -1,21 +0,0 @@ -This directory contains accounts for testing. -The password that unlocks them is "foobar". - -The "good" key files which are supposed to be loadable are: - -- File: UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 - Address: 0x7ef5a6135f1fd6a02593eedc869c6d41d934aef8 -- File: aaa - Address: 0xf466859ead1932d743d622cb74fc058882e8648a -- File: zzz - Address: 0x289d485d9771714cce91d3393d764e1311907acc - -The other files (including this README) are broken in various ways -and should not be picked up by package accounts: - -- File: no-address (missing address field, otherwise same as "aaa") -- File: garbage (file with random data) -- File: empty (file with no content) -- File: swapfile~ (should be skipped) -- File: .hiddenfile (should be skipped) -- File: foo/... (should be skipped because it is a directory) diff --git a/builder/accounts/keystore/testdata/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 b/builder/accounts/keystore/testdata/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 deleted file mode 100644 index c57060aea..000000000 --- a/builder/accounts/keystore/testdata/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 +++ /dev/null @@ -1 +0,0 @@ -{"address":"7ef5a6135f1fd6a02593eedc869c6d41d934aef8","crypto":{"cipher":"aes-128-ctr","ciphertext":"1d0839166e7a15b9c1333fc865d69858b22df26815ccf601b28219b6192974e1","cipherparams":{"iv":"8df6caa7ff1b00c4e871f002cb7921ed"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"e5e6ef3f4ea695f496b643ebd3f75c0aa58ef4070e90c80c5d3fb0241bf1595c"},"mac":"6d16dfde774845e4585357f24bce530528bc69f4f84e1e22880d34fa45c273e5"},"id":"950077c7-71e3-4c44-a4a1-143919141ed4","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/aaa b/builder/accounts/keystore/testdata/keystore/aaa deleted file mode 100644 index a3868ec6d..000000000 --- a/builder/accounts/keystore/testdata/keystore/aaa +++ /dev/null @@ -1 +0,0 @@ -{"address":"f466859ead1932d743d622cb74fc058882e8648a","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/empty b/builder/accounts/keystore/testdata/keystore/empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/builder/accounts/keystore/testdata/keystore/foo/fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e b/builder/accounts/keystore/testdata/keystore/foo/fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e deleted file mode 100644 index 309841e52..000000000 --- a/builder/accounts/keystore/testdata/keystore/foo/fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e +++ /dev/null @@ -1 +0,0 @@ -{"address":"fd9bd350f08ee3c0c19b85a8e16114a11a60aa4e","crypto":{"cipher":"aes-128-ctr","ciphertext":"8124d5134aa4a927c79fd852989e4b5419397566f04b0936a1eb1d168c7c68a5","cipherparams":{"iv":"e2febe17176414dd2cda28287947eb2f"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"44b415ede89f3bdd6830390a21b78965f571b347a589d1d943029f016c5e8bd5"},"mac":"5e149ff25bfd9dd45746a84bb2bcd2f015f2cbca2b6d25c5de8c29617f71fe5b"},"id":"d6ac5452-2b2c-4d3c-ad80-4bf0327d971c","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/garbage b/builder/accounts/keystore/testdata/keystore/garbage deleted file mode 100644 index ff45091e7..000000000 Binary files a/builder/accounts/keystore/testdata/keystore/garbage and /dev/null differ diff --git a/builder/accounts/keystore/testdata/keystore/no-address b/builder/accounts/keystore/testdata/keystore/no-address deleted file mode 100644 index ad51269ea..000000000 --- a/builder/accounts/keystore/testdata/keystore/no-address +++ /dev/null @@ -1 +0,0 @@ -{"crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/zero b/builder/accounts/keystore/testdata/keystore/zero deleted file mode 100644 index b52617f8a..000000000 --- a/builder/accounts/keystore/testdata/keystore/zero +++ /dev/null @@ -1 +0,0 @@ -{"address":"0000000000000000000000000000000000000000","crypto":{"cipher":"aes-128-ctr","ciphertext":"cb664472deacb41a2e995fa7f96fe29ce744471deb8d146a0e43c7898c9ddd4d","cipherparams":{"iv":"dfd9ee70812add5f4b8f89d0811c9158"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"0d6769bf016d45c479213990d6a08d938469c4adad8a02ce507b4a4e7b7739f1"},"mac":"bac9af994b15a45dd39669fc66f9aa8a3b9dd8c22cb16e4d8d7ea089d0f1a1a9"},"id":"472e8b3d-afb6-45b5-8111-72c89895099a","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/keystore/zzz b/builder/accounts/keystore/testdata/keystore/zzz deleted file mode 100644 index cfd8a4701..000000000 --- a/builder/accounts/keystore/testdata/keystore/zzz +++ /dev/null @@ -1 +0,0 @@ -{"address":"289d485d9771714cce91d3393d764e1311907acc","crypto":{"cipher":"aes-128-ctr","ciphertext":"faf32ca89d286b107f5e6d842802e05263c49b78d46eac74e6109e9a963378ab","cipherparams":{"iv":"558833eec4a665a8c55608d7d503407d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":8,"p":16,"r":8,"salt":"d571fff447ffb24314f9513f5160246f09997b857ac71348b73e785aab40dc04"},"mac":"21edb85ff7d0dab1767b9bf498f2c3cb7be7609490756bd32300bb213b59effe"},"id":"3279afcf-55ba-43ff-8997-02dcc46a6525","version":3} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/v1/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e b/builder/accounts/keystore/testdata/v1/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e deleted file mode 100644 index 498d8131e..000000000 --- a/builder/accounts/keystore/testdata/v1/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e/cb61d5a9c4896fb9658090b597ef0e7be6f7b67e +++ /dev/null @@ -1 +0,0 @@ -{"address":"cb61d5a9c4896fb9658090b597ef0e7be6f7b67e","Crypto":{"cipher":"aes-128-cbc","ciphertext":"6143d3192db8b66eabd693d9c4e414dcfaee52abda451af79ccf474dafb35f1bfc7ea013aa9d2ee35969a1a2e8d752d0","cipherparams":{"iv":"35337770fc2117994ecdcad026bccff4"},"kdf":"scrypt","kdfparams":{"n":262144,"r":8,"p":1,"dklen":32,"salt":"9afcddebca541253a2f4053391c673ff9fe23097cd8555d149d929e4ccf1257f"},"mac":"3f3d5af884b17a100b0b3232c0636c230a54dc2ac8d986227219b0dd89197644","version":"1"},"id":"e25f7c1f-d318-4f29-b62c-687190d4d299","version":"1"} \ No newline at end of file diff --git a/builder/accounts/keystore/testdata/v1_test_vector.json b/builder/accounts/keystore/testdata/v1_test_vector.json deleted file mode 100644 index 3d09b55b5..000000000 --- a/builder/accounts/keystore/testdata/v1_test_vector.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "test1": { - "json": { - "Crypto": { - "cipher": "aes-128-cbc", - "cipherparams": { - "iv": "35337770fc2117994ecdcad026bccff4" - }, - "ciphertext": "6143d3192db8b66eabd693d9c4e414dcfaee52abda451af79ccf474dafb35f1bfc7ea013aa9d2ee35969a1a2e8d752d0", - "kdf": "scrypt", - "kdfparams": { - "dklen": 32, - "n": 262144, - "p": 1, - "r": 8, - "salt": "9afcddebca541253a2f4053391c673ff9fe23097cd8555d149d929e4ccf1257f" - }, - "mac": "3f3d5af884b17a100b0b3232c0636c230a54dc2ac8d986227219b0dd89197644", - "version": "1" - }, - "address": "cb61d5a9c4896fb9658090b597ef0e7be6f7b67e", - "id": "e25f7c1f-d318-4f29-b62c-687190d4d299", - "version": "1" - }, - "password": "g", - "priv": "d1b1178d3529626a1a93e073f65028370d14c7eb0936eb42abef05db6f37ad7d" - } -} diff --git a/builder/accounts/keystore/testdata/v3_test_vector.json b/builder/accounts/keystore/testdata/v3_test_vector.json deleted file mode 100644 index 1e7f790c0..000000000 --- a/builder/accounts/keystore/testdata/v3_test_vector.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "wikipage_test_vector_scrypt": { - "json": { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - }, - "password": "testpassword", - "priv": "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d" - }, - "wikipage_test_vector_pbkdf2": { - "json": { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "6087dab2f9fdbbfaddc31a909735c1e6" - }, - "ciphertext" : "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46", - "kdf" : "pbkdf2", - "kdfparams" : { - "c" : 262144, - "dklen" : 32, - "prf" : "hmac-sha256", - "salt" : "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd" - }, - "mac" : "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - }, - "password": "testpassword", - "priv": "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d" - }, - "31_byte_key": { - "json": { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "e0c41130a323adc1446fc82f724bca2f" - }, - "ciphertext" : "9517cd5bdbe69076f9bf5057248c6c050141e970efa36ce53692d5d59a3984", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 2, - "r" : 8, - "p" : 1, - "salt" : "711f816911c92d649fb4c84b047915679933555030b3552c1212609b38208c63" - }, - "mac" : "d5e116151c6aa71470e67a7d42c9620c75c4d23229847dcc127794f0732b0db5" - }, - "id" : "fecfc4ce-e956-48fd-953b-30f8b52ed66c", - "version" : 3 - }, - "password": "foo", - "priv": "fa7b3db73dc7dfdf8c5fbdb796d741e4488628c41fc4febd9160a866ba0f35" - }, - "30_byte_key": { - "json": { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "3ca92af36ad7c2cd92454c59cea5ef00" - }, - "ciphertext" : "108b7d34f3442fc26ab1ab90ca91476ba6bfa8c00975a49ef9051dc675aa", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 2, - "r" : 8, - "p" : 1, - "salt" : "d0769e608fb86cda848065642a9c6fa046845c928175662b8e356c77f914cd3b" - }, - "mac" : "75d0e6759f7b3cefa319c3be41680ab6beea7d8328653474bd06706d4cc67420" - }, - "id" : "a37e1559-5955-450d-8075-7b8931b392b2", - "version" : 3 - }, - "password": "foo", - "priv": "81c29e8142bb6a81bef5a92bda7a8328a5c85bb2f9542e76f9b0f94fc018" - } -} diff --git a/builder/accounts/keystore/testdata/very-light-scrypt.json b/builder/accounts/keystore/testdata/very-light-scrypt.json deleted file mode 100644 index d23b9b2b9..000000000 --- a/builder/accounts/keystore/testdata/very-light-scrypt.json +++ /dev/null @@ -1 +0,0 @@ -{"address":"45dea0fb0bba44f4fcf290bba71fd57d7117cbb8","crypto":{"cipher":"aes-128-ctr","ciphertext":"b87781948a1befd247bff51ef4063f716cf6c2d3481163e9a8f42e1f9bb74145","cipherparams":{"iv":"dc4926b48a105133d2f16b96833abf1e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":2,"p":1,"r":8,"salt":"004244bbdc51cadda545b1cfa43cff9ed2ae88e08c61f1479dbb45410722f8f0"},"mac":"39990c1684557447940d4c69e06b1b82b2aceacb43f284df65c956daf3046b85"},"id":"ce541d8d-c79b-40f8-9f8c-20f59616faba","version":3} diff --git a/builder/accounts/keystore/wallet.go b/builder/accounts/keystore/wallet.go deleted file mode 100644 index 1066095f6..000000000 --- a/builder/accounts/keystore/wallet.go +++ /dev/null @@ -1,150 +0,0 @@ -// 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 keystore - -import ( - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" -) - -// keystoreWallet implements the accounts.Wallet interface for the original -// keystore. -type keystoreWallet struct { - account accounts.Account // Single account contained in this wallet - keystore *KeyStore // Keystore where the account originates from -} - -// URL implements accounts.Wallet, returning the URL of the account within. -func (w *keystoreWallet) URL() accounts.URL { - return w.account.URL -} - -// Status implements accounts.Wallet, returning whether the account held by the -// keystore wallet is unlocked or not. -func (w *keystoreWallet) Status() (string, error) { - w.keystore.mu.RLock() - defer w.keystore.mu.RUnlock() - - if _, ok := w.keystore.unlocked[w.account.Address]; ok { - return "Unlocked", nil - } - return "Locked", nil -} - -// Open implements accounts.Wallet, but is a noop for plain wallets since there -// is no connection or decryption step necessary to access the list of accounts. -func (w *keystoreWallet) Open(passphrase string) error { return nil } - -// Close implements accounts.Wallet, but is a noop for plain wallets since there -// is no meaningful open operation. -func (w *keystoreWallet) Close() error { return nil } - -// Accounts implements accounts.Wallet, returning an account list consisting of -// a single account that the plain keystore wallet contains. -func (w *keystoreWallet) Accounts() []accounts.Account { - return []accounts.Account{w.account} -} - -// Contains implements accounts.Wallet, returning whether a particular account is -// or is not wrapped by this wallet instance. -func (w *keystoreWallet) Contains(account accounts.Account) bool { - return account.Address == w.account.Address && (account.URL == (accounts.URL{}) || account.URL == w.account.URL) -} - -// Derive implements accounts.Wallet, but is a noop for plain wallets since there -// is no notion of hierarchical account derivation for plain keystore accounts. -func (w *keystoreWallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { - return accounts.Account{}, accounts.ErrNotSupported -} - -// SelfDerive implements accounts.Wallet, but is a noop for plain wallets since -// there is no notion of hierarchical account derivation for plain keystore accounts. -func (w *keystoreWallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { -} - -// signHash attempts to sign the given hash with -// the given account. If the wallet does not wrap this particular account, an -// error is returned to avoid account leakage (even though in theory we may be -// able to sign via our shared keystore backend). -func (w *keystoreWallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignHash(account, hash) -} - -// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed. -func (w *keystoreWallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - return w.signHash(account, crypto.Keccak256(data)) -} - -// SignDataWithPassphrase signs keccak256(data). The mimetype parameter describes the type of data being signed. -func (w *keystoreWallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) -} - -// SignText implements accounts.Wallet, attempting to sign the hash of -// the given text with the given account. -func (w *keystoreWallet) SignText(account accounts.Account, text []byte) ([]byte, error) { - return w.signHash(account, accounts.TextHash(text)) -} - -// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the -// hash of the given text with the given account using passphrase as extra authentication. -func (w *keystoreWallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignHashWithPassphrase(account, passphrase, accounts.TextHash(text)) -} - -// SignTx implements accounts.Wallet, attempting to sign the given transaction -// with the given account. If the wallet does not wrap this particular account, -// an error is returned to avoid account leakage (even though in theory we may -// be able to sign via our shared keystore backend). -func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignTx(account, tx, chainID) -} - -// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given -// transaction with the given account using passphrase as extra authentication. -func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - // Make sure the requested account is contained within - if !w.Contains(account) { - return nil, accounts.ErrUnknownAccount - } - // Account seems valid, request the keystore to sign - return w.keystore.SignTxWithPassphrase(account, passphrase, tx, chainID) -} diff --git a/builder/accounts/keystore/watch.go b/builder/accounts/keystore/watch.go deleted file mode 100644 index 1bef321cd..000000000 --- a/builder/accounts/keystore/watch.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2016 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 . - -//go:build (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris -// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris - -package keystore - -import ( - "os" - "time" - - "github.com/ethereum/go-ethereum/log" - "github.com/fsnotify/fsnotify" -) - -type watcher struct { - ac *accountCache - running bool // set to true when runloop begins - runEnded bool // set to true when runloop ends - starting bool // set to true prior to runloop starting - quit chan struct{} -} - -func newWatcher(ac *accountCache) *watcher { - return &watcher{ - ac: ac, - quit: make(chan struct{}), - } -} - -// enabled returns false on systems not supported. -func (*watcher) enabled() bool { return true } - -// starts the watcher loop in the background. -// Start a watcher in the background if that's not already in progress. -// The caller must hold w.ac.mu. -func (w *watcher) start() { - if w.starting || w.running { - return - } - w.starting = true - go w.loop() -} - -func (w *watcher) close() { - close(w.quit) -} - -func (w *watcher) loop() { - defer func() { - w.ac.mu.Lock() - w.running = false - w.starting = false - w.runEnded = true - w.ac.mu.Unlock() - }() - logger := log.New("path", w.ac.keydir) - - // Create new watcher. - watcher, err := fsnotify.NewWatcher() - if err != nil { - log.Error("Failed to start filesystem watcher", "err", err) - return - } - defer watcher.Close() - if err := watcher.Add(w.ac.keydir); err != nil { - if !os.IsNotExist(err) { - logger.Warn("Failed to watch keystore folder", "err", err) - } - return - } - - logger.Trace("Started watching keystore folder", "folder", w.ac.keydir) - defer logger.Trace("Stopped watching keystore folder") - - w.ac.mu.Lock() - w.running = true - w.ac.mu.Unlock() - - // Wait for file system events and reload. - // When an event occurs, the reload call is delayed a bit so that - // multiple events arriving quickly only cause a single reload. - var ( - debounceDuration = 500 * time.Millisecond - rescanTriggered = false - debounce = time.NewTimer(0) - ) - // Ignore initial trigger - if !debounce.Stop() { - <-debounce.C - } - defer debounce.Stop() - for { - select { - case <-w.quit: - return - case _, ok := <-watcher.Events: - if !ok { - return - } - // Trigger the scan (with delay), if not already triggered - if !rescanTriggered { - debounce.Reset(debounceDuration) - rescanTriggered = true - } - // The fsnotify library does provide more granular event-info, it - // would be possible to refresh individual affected files instead - // of scheduling a full rescan. For most cases though, the - // full rescan is quick and obviously simplest. - case err, ok := <-watcher.Errors: - if !ok { - return - } - log.Info("Filesystem watcher error", "err", err) - case <-debounce.C: - w.ac.scanAccounts() - rescanTriggered = false - } - } -} diff --git a/builder/accounts/keystore/watch_fallback.go b/builder/accounts/keystore/watch_fallback.go deleted file mode 100644 index e3c133b3f..000000000 --- a/builder/accounts/keystore/watch_fallback.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2016 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 . - -//go:build (darwin && !cgo) || ios || (linux && arm64) || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris) -// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris - -// This is the fallback implementation of directory watching. -// It is used on unsupported platforms. - -package keystore - -type watcher struct { - running bool - runEnded bool -} - -func newWatcher(*accountCache) *watcher { return new(watcher) } -func (*watcher) start() {} -func (*watcher) close() {} - -// enabled returns false on systems not supported. -func (*watcher) enabled() bool { return false } diff --git a/builder/accounts/manager.go b/builder/accounts/manager.go deleted file mode 100644 index cbe4f7c79..000000000 --- a/builder/accounts/manager.go +++ /dev/null @@ -1,275 +0,0 @@ -// 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 accounts - -import ( - "reflect" - "sort" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/event" -) - -// managerSubBufferSize determines how many incoming wallet events -// the manager will buffer in its channel. -const managerSubBufferSize = 50 - -// Config contains the settings of the global account manager. -// -// TODO(rjl493456442, karalabe, holiman): Get rid of this when account management -// is removed in favor of Clef. -type Config struct { - InsecureUnlockAllowed bool // Whether account unlocking in insecure environment is allowed -} - -// newBackendEvent lets the manager know it should -// track the given backend for wallet updates. -type newBackendEvent struct { - backend Backend - processed chan struct{} // Informs event emitter that backend has been integrated -} - -// Manager is an overarching account manager that can communicate with various -// backends for signing transactions. -type Manager struct { - config *Config // Global account manager configurations - backends map[reflect.Type][]Backend // Index of backends currently registered - updaters []event.Subscription // Wallet update subscriptions for all backends - updates chan WalletEvent // Subscription sink for backend wallet changes - newBackends chan newBackendEvent // Incoming backends to be tracked by the manager - wallets []Wallet // Cache of all wallets from all registered backends - - feed event.Feed // Wallet feed notifying of arrivals/departures - - quit chan chan error - term chan struct{} // Channel is closed upon termination of the update loop - lock sync.RWMutex -} - -// NewManager creates a generic account manager to sign transaction via various -// supported backends. -func NewManager(config *Config, backends ...Backend) *Manager { - // Retrieve the initial list of wallets from the backends and sort by URL - var wallets []Wallet - for _, backend := range backends { - wallets = merge(wallets, backend.Wallets()...) - } - // Subscribe to wallet notifications from all backends - updates := make(chan WalletEvent, managerSubBufferSize) - - subs := make([]event.Subscription, len(backends)) - for i, backend := range backends { - subs[i] = backend.Subscribe(updates) - } - // Assemble the account manager and return - am := &Manager{ - config: config, - backends: make(map[reflect.Type][]Backend), - updaters: subs, - updates: updates, - newBackends: make(chan newBackendEvent), - wallets: wallets, - quit: make(chan chan error), - term: make(chan struct{}), - } - for _, backend := range backends { - kind := reflect.TypeOf(backend) - am.backends[kind] = append(am.backends[kind], backend) - } - go am.update() - - return am -} - -// Close terminates the account manager's internal notification processes. -func (am *Manager) Close() error { - for _, w := range am.wallets { - w.Close() - } - errc := make(chan error) - am.quit <- errc - return <-errc -} - -// Config returns the configuration of account manager. -func (am *Manager) Config() *Config { - return am.config -} - -// AddBackend starts the tracking of an additional backend for wallet updates. -// cmd/geth assumes once this func returns the backends have been already integrated. -func (am *Manager) AddBackend(backend Backend) { - done := make(chan struct{}) - am.newBackends <- newBackendEvent{backend, done} - <-done -} - -// update is the wallet event loop listening for notifications from the backends -// and updating the cache of wallets. -func (am *Manager) update() { - // Close all subscriptions when the manager terminates - defer func() { - am.lock.Lock() - for _, sub := range am.updaters { - sub.Unsubscribe() - } - am.updaters = nil - am.lock.Unlock() - }() - - // Loop until termination - for { - select { - case event := <-am.updates: - // Wallet event arrived, update local cache - am.lock.Lock() - switch event.Kind { - case WalletArrived: - am.wallets = merge(am.wallets, event.Wallet) - case WalletDropped: - am.wallets = drop(am.wallets, event.Wallet) - } - am.lock.Unlock() - - // Notify any listeners of the event - am.feed.Send(event) - case event := <-am.newBackends: - am.lock.Lock() - // Update caches - backend := event.backend - am.wallets = merge(am.wallets, backend.Wallets()...) - am.updaters = append(am.updaters, backend.Subscribe(am.updates)) - kind := reflect.TypeOf(backend) - am.backends[kind] = append(am.backends[kind], backend) - am.lock.Unlock() - close(event.processed) - case errc := <-am.quit: - // Manager terminating, return - errc <- nil - // Signals event emitters the loop is not receiving values - // to prevent them from getting stuck. - close(am.term) - return - } - } -} - -// Backends retrieves the backend(s) with the given type from the account manager. -func (am *Manager) Backends(kind reflect.Type) []Backend { - am.lock.RLock() - defer am.lock.RUnlock() - - return am.backends[kind] -} - -// Wallets returns all signer accounts registered under this account manager. -func (am *Manager) Wallets() []Wallet { - am.lock.RLock() - defer am.lock.RUnlock() - - return am.walletsNoLock() -} - -// walletsNoLock returns all registered wallets. Callers must hold am.lock. -func (am *Manager) walletsNoLock() []Wallet { - cpy := make([]Wallet, len(am.wallets)) - copy(cpy, am.wallets) - return cpy -} - -// Wallet retrieves the wallet associated with a particular URL. -func (am *Manager) Wallet(url string) (Wallet, error) { - am.lock.RLock() - defer am.lock.RUnlock() - - parsed, err := parseURL(url) - if err != nil { - return nil, err - } - for _, wallet := range am.walletsNoLock() { - if wallet.URL() == parsed { - return wallet, nil - } - } - return nil, ErrUnknownWallet -} - -// Accounts returns all account addresses of all wallets within the account manager -func (am *Manager) Accounts() []common.Address { - am.lock.RLock() - defer am.lock.RUnlock() - - addresses := make([]common.Address, 0) // return [] instead of nil if empty - for _, wallet := range am.wallets { - for _, account := range wallet.Accounts() { - addresses = append(addresses, account.Address) - } - } - return addresses -} - -// Find attempts to locate the wallet corresponding to a specific account. Since -// accounts can be dynamically added to and removed from wallets, this method has -// a linear runtime in the number of wallets. -func (am *Manager) Find(account Account) (Wallet, error) { - am.lock.RLock() - defer am.lock.RUnlock() - - for _, wallet := range am.wallets { - if wallet.Contains(account) { - return wallet, nil - } - } - return nil, ErrUnknownAccount -} - -// Subscribe creates an async subscription to receive notifications when the -// manager detects the arrival or departure of a wallet from any of its backends. -func (am *Manager) Subscribe(sink chan<- WalletEvent) event.Subscription { - return am.feed.Subscribe(sink) -} - -// merge is a sorted analogue of append for wallets, where the ordering of the -// origin list is preserved by inserting new wallets at the correct position. -// -// The original slice is assumed to be already sorted by URL. -func merge(slice []Wallet, wallets ...Wallet) []Wallet { - for _, wallet := range wallets { - n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 }) - if n == len(slice) { - slice = append(slice, wallet) - continue - } - slice = append(slice[:n], append([]Wallet{wallet}, slice[n:]...)...) - } - return slice -} - -// drop is the counterpart of merge, which looks up wallets from within the sorted -// cache and removes the ones specified. -func drop(slice []Wallet, wallets ...Wallet) []Wallet { - for _, wallet := range wallets { - n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 }) - if n == len(slice) { - // Wallet not found, may happen during startup - continue - } - slice = append(slice[:n], slice[n+1:]...) - } - return slice -} diff --git a/builder/accounts/scwallet/README.md b/builder/accounts/scwallet/README.md deleted file mode 100644 index 28079c474..000000000 --- a/builder/accounts/scwallet/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# Using the smartcard wallet - -## Requirements - - * A USB smartcard reader - * A keycard that supports the status app - * PCSCD version 4.3 running on your system **Only version 4.3 is currently supported** - -## Preparing the smartcard - - **WARNING: FOLLOWING THESE INSTRUCTIONS WILL DESTROY THE MASTER KEY ON YOUR CARD. ONLY PROCEED IF NO FUNDS ARE ASSOCIATED WITH THESE ACCOUNTS** - - You can use status' [keycard-cli](https://github.com/status-im/keycard-cli) and you should get _at least_ version 2.1.1 of their [smartcard application](https://github.com/status-im/status-keycard/releases/download/2.2.1/keycard_v2.2.1.cap) - - You also need to make sure that the PCSC daemon is running on your system. - - Then, you can install the application to the card by typing: - - ``` - keycard install -a keycard_v2.2.1.cap && keycard init - ``` - - At the end of this process, you will be provided with a PIN, a PUK and a pairing password. Write them down, you'll need them shortly. - - Start `geth` with the `console` command. You will notice the following warning: - - ``` - WARN [04-09|16:58:38.898] Failed to open wallet url=keycard://044def09 err="smartcard: pairing password needed" - ``` - - Write down the URL (`keycard://044def09` in this example). Then ask `geth` to open the wallet: - - ``` - > personal.openWallet("keycard://044def09", "pairing password") - ``` - - The pairing password has been generated during the card initialization process. - - The process needs to be repeated once more with the PIN: - - ``` - > personal.openWallet("keycard://044def09", "PIN number") - ``` - - If everything goes well, you should see your new account when typing `personal` on the console: - - ``` - > personal - WARN [04-09|17:02:07.330] Smartcard wallet account derivation failed url=keycard://044def09 err="Unexpected response status Cla=0x80, Ins=0xd1, Sw=0x6985" - { - listAccounts: [], - listWallets: [{ - status: "Empty, waiting for initialization", - url: "keycard://044def09" - }], - ... - } - ``` - - So the communication with the card is working, but there is no key associated with this wallet. Let's create it: - - ``` - > personal.initializeWallet("keycard://044def09") - "tilt ... impact" - ``` - - You should get a list of words, this is your seed so write them down. Your wallet should now be initialized: - - ``` - > personal.listWallets - [{ - accounts: [{ - address: "0x678b7cd55c61917defb23546a41803c5bfefbc7a", - url: "keycard://044d/m/44'/60'/0'/0/0" - }], - status: "Online", - url: "keycard://044def09" - }] - ``` - - You're all set! - -## Usage - - 1. Start `geth` with the `console` command - 2. Check the card's URL by checking `personal.listWallets`: - -``` - listWallets: [{ - status: "Online, can derive public keys", - url: "keycard://a4d73015" - }] -``` - - 3. Open the wallet, you will be prompted for your pairing password, then PIN: - -``` -personal.openWallet("keycard://a4d73015") -``` - - 4. Check that creation was successful by typing e.g. `personal`. Then use it like a regular wallet. - -## Known issues - - * Starting geth with a valid card seems to make firefox crash. - * PCSC version 4.4 should work, but is currently untested diff --git a/builder/accounts/scwallet/apdu.go b/builder/accounts/scwallet/apdu.go deleted file mode 100644 index bd3660604..000000000 --- a/builder/accounts/scwallet/apdu.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2018 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 scwallet - -import ( - "bytes" - "encoding/binary" - "fmt" -) - -// commandAPDU represents an application data unit sent to a smartcard. -type commandAPDU struct { - Cla, Ins, P1, P2 uint8 // Class, Instruction, Parameter 1, Parameter 2 - Data []byte // Command data - Le uint8 // Command data length -} - -// serialize serializes a command APDU. -func (ca commandAPDU) serialize() ([]byte, error) { - buf := new(bytes.Buffer) - - if err := binary.Write(buf, binary.BigEndian, ca.Cla); err != nil { - return nil, err - } - if err := binary.Write(buf, binary.BigEndian, ca.Ins); err != nil { - return nil, err - } - if err := binary.Write(buf, binary.BigEndian, ca.P1); err != nil { - return nil, err - } - if err := binary.Write(buf, binary.BigEndian, ca.P2); err != nil { - return nil, err - } - if len(ca.Data) > 0 { - if err := binary.Write(buf, binary.BigEndian, uint8(len(ca.Data))); err != nil { - return nil, err - } - if err := binary.Write(buf, binary.BigEndian, ca.Data); err != nil { - return nil, err - } - } - if err := binary.Write(buf, binary.BigEndian, ca.Le); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// responseAPDU represents an application data unit received from a smart card. -type responseAPDU struct { - Data []byte // response data - Sw1, Sw2 uint8 // status words 1 and 2 -} - -// deserialize deserializes a response APDU. -func (ra *responseAPDU) deserialize(data []byte) error { - if len(data) < 2 { - return fmt.Errorf("can not deserialize data: payload too short (%d < 2)", len(data)) - } - - ra.Data = make([]byte, len(data)-2) - - buf := bytes.NewReader(data) - if err := binary.Read(buf, binary.BigEndian, &ra.Data); err != nil { - return err - } - if err := binary.Read(buf, binary.BigEndian, &ra.Sw1); err != nil { - return err - } - if err := binary.Read(buf, binary.BigEndian, &ra.Sw2); err != nil { - return err - } - return nil -} diff --git a/builder/accounts/scwallet/hub.go b/builder/accounts/scwallet/hub.go deleted file mode 100644 index 5f1f369ca..000000000 --- a/builder/accounts/scwallet/hub.go +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2018 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 . - -// This package implements support for smartcard-based hardware wallets such as -// the one written by Status: https://github.com/status-im/hardware-wallet -// -// This implementation of smartcard wallets have a different interaction process -// to other types of hardware wallet. The process works like this: -// -// 1. (First use with a given client) Establish a pairing between hardware -// wallet and client. This requires a secret value called a 'pairing password'. -// You can pair with an unpaired wallet with `personal.openWallet(URI, pairing password)`. -// 2. (First use only) Initialize the wallet, which generates a keypair, stores -// it on the wallet, and returns it so the user can back it up. You can -// initialize a wallet with `personal.initializeWallet(URI)`. -// 3. Connect to the wallet using the pairing information established in step 1. -// You can connect to a paired wallet with `personal.openWallet(URI, PIN)`. -// 4. Interact with the wallet as normal. - -package scwallet - -import ( - "encoding/json" - "io" - "os" - "path/filepath" - "sort" - "sync" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - pcsc "github.com/gballet/go-libpcsclite" -) - -// Scheme is the URI prefix for smartcard wallets. -const Scheme = "keycard" - -// refreshCycle is the maximum time between wallet refreshes (if USB hotplug -// notifications don't work). -const refreshCycle = time.Second - -// refreshThrottling is the minimum time between wallet refreshes to avoid thrashing. -const refreshThrottling = 500 * time.Millisecond - -// smartcardPairing contains information about a smart card we have paired with -// or might pair with the hub. -type smartcardPairing struct { - PublicKey []byte `json:"publicKey"` - PairingIndex uint8 `json:"pairingIndex"` - PairingKey []byte `json:"pairingKey"` - Accounts map[common.Address]accounts.DerivationPath `json:"accounts"` -} - -// Hub is a accounts.Backend that can find and handle generic PC/SC hardware wallets. -type Hub struct { - scheme string // Protocol scheme prefixing account and wallet URLs. - - context *pcsc.Client - datadir string - pairings map[string]smartcardPairing - - refreshed time.Time // Time instance when the list of wallets was last refreshed - wallets map[string]*Wallet // Mapping from reader names to wallet instances - updateFeed event.Feed // Event feed to notify wallet additions/removals - updateScope event.SubscriptionScope // Subscription scope tracking current live listeners - updating bool // Whether the event notification loop is running - - quit chan chan error - - stateLock sync.RWMutex // Protects the internals of the hub from racey access -} - -func (hub *Hub) readPairings() error { - hub.pairings = make(map[string]smartcardPairing) - pairingFile, err := os.Open(filepath.Join(hub.datadir, "smartcards.json")) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - - pairingData, err := io.ReadAll(pairingFile) - if err != nil { - return err - } - var pairings []smartcardPairing - if err := json.Unmarshal(pairingData, &pairings); err != nil { - return err - } - - for _, pairing := range pairings { - hub.pairings[string(pairing.PublicKey)] = pairing - } - return nil -} - -func (hub *Hub) writePairings() error { - pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - return err - } - defer pairingFile.Close() - - pairings := make([]smartcardPairing, 0, len(hub.pairings)) - for _, pairing := range hub.pairings { - pairings = append(pairings, pairing) - } - - pairingData, err := json.Marshal(pairings) - if err != nil { - return err - } - - if _, err := pairingFile.Write(pairingData); err != nil { - return err - } - - return nil -} - -func (hub *Hub) pairing(wallet *Wallet) *smartcardPairing { - if pairing, ok := hub.pairings[string(wallet.PublicKey)]; ok { - return &pairing - } - return nil -} - -func (hub *Hub) setPairing(wallet *Wallet, pairing *smartcardPairing) error { - if pairing == nil { - delete(hub.pairings, string(wallet.PublicKey)) - } else { - hub.pairings[string(wallet.PublicKey)] = *pairing - } - return hub.writePairings() -} - -// NewHub creates a new hardware wallet manager for smartcards. -func NewHub(daemonPath string, scheme string, datadir string) (*Hub, error) { - context, err := pcsc.EstablishContext(daemonPath, pcsc.ScopeSystem) - if err != nil { - return nil, err - } - hub := &Hub{ - scheme: scheme, - context: context, - datadir: datadir, - wallets: make(map[string]*Wallet), - quit: make(chan chan error), - } - if err := hub.readPairings(); err != nil { - return nil, err - } - hub.refreshWallets() - return hub, nil -} - -// Wallets implements accounts.Backend, returning all the currently tracked smart -// cards that appear to be hardware wallets. -func (hub *Hub) Wallets() []accounts.Wallet { - // Make sure the list of wallets is up to date - hub.refreshWallets() - - hub.stateLock.RLock() - defer hub.stateLock.RUnlock() - - cpy := make([]accounts.Wallet, 0, len(hub.wallets)) - for _, wallet := range hub.wallets { - cpy = append(cpy, wallet) - } - sort.Sort(accounts.WalletsByURL(cpy)) - return cpy -} - -// refreshWallets scans the devices attached to the machine and updates the -// list of wallets based on the found devices. -func (hub *Hub) refreshWallets() { - // Don't scan the USB like crazy it the user fetches wallets in a loop - hub.stateLock.RLock() - elapsed := time.Since(hub.refreshed) - hub.stateLock.RUnlock() - - if elapsed < refreshThrottling { - return - } - // Retrieve all the smart card reader to check for cards - readers, err := hub.context.ListReaders() - if err != nil { - // This is a perverted hack, the scard library returns an error if no card - // readers are present instead of simply returning an empty list. We don't - // want to fill the user's log with errors, so filter those out. - if err.Error() != "scard: Cannot find a smart card reader." { - log.Error("Failed to enumerate smart card readers", "err", err) - return - } - } - // Transform the current list of wallets into the new one - hub.stateLock.Lock() - - events := []accounts.WalletEvent{} - seen := make(map[string]struct{}) - - for _, reader := range readers { - // Mark the reader as present - seen[reader] = struct{}{} - - // If we already know about this card, skip to the next reader, otherwise clean up - if wallet, ok := hub.wallets[reader]; ok { - if err := wallet.ping(); err == nil { - continue - } - wallet.Close() - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) - delete(hub.wallets, reader) - } - // New card detected, try to connect to it - card, err := hub.context.Connect(reader, pcsc.ShareShared, pcsc.ProtocolAny) - if err != nil { - log.Debug("Failed to open smart card", "reader", reader, "err", err) - continue - } - wallet := NewWallet(hub, card) - if err = wallet.connect(); err != nil { - log.Debug("Failed to connect to smart card", "reader", reader, "err", err) - card.Disconnect(pcsc.LeaveCard) - continue - } - // Card connected, start tracking among the wallets - hub.wallets[reader] = wallet - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) - } - // Remove any wallets no longer present - for reader, wallet := range hub.wallets { - if _, ok := seen[reader]; !ok { - wallet.Close() - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) - delete(hub.wallets, reader) - } - } - hub.refreshed = time.Now() - hub.stateLock.Unlock() - - for _, event := range events { - hub.updateFeed.Send(event) - } -} - -// Subscribe implements accounts.Backend, creating an async subscription to -// receive notifications on the addition or removal of smart card wallets. -func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { - // We need the mutex to reliably start/stop the update loop - hub.stateLock.Lock() - defer hub.stateLock.Unlock() - - // Subscribe the caller and track the subscriber count - sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink)) - - // Subscribers require an active notification loop, start it - if !hub.updating { - hub.updating = true - go hub.updater() - } - return sub -} - -// updater is responsible for maintaining an up-to-date list of wallets managed -// by the smart card hub, and for firing wallet addition/removal events. -func (hub *Hub) updater() { - for { - // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout - // <-hub.changes - time.Sleep(refreshCycle) - - // Run the wallet refresher - hub.refreshWallets() - - // If all our subscribers left, stop the updater - hub.stateLock.Lock() - if hub.updateScope.Count() == 0 { - hub.updating = false - hub.stateLock.Unlock() - return - } - hub.stateLock.Unlock() - } -} diff --git a/builder/accounts/scwallet/securechannel.go b/builder/accounts/scwallet/securechannel.go deleted file mode 100644 index bbd8b2264..000000000 --- a/builder/accounts/scwallet/securechannel.go +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2018 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 scwallet - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/elliptic" - "crypto/rand" - "crypto/sha256" - "crypto/sha512" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/crypto" - pcsc "github.com/gballet/go-libpcsclite" - "golang.org/x/crypto/pbkdf2" - "golang.org/x/text/unicode/norm" -) - -const ( - maxPayloadSize = 223 - pairP1FirstStep = 0 - pairP1LastStep = 1 - - scSecretLength = 32 - scBlockSize = 16 - - insOpenSecureChannel = 0x10 - insMutuallyAuthenticate = 0x11 - insPair = 0x12 - insUnpair = 0x13 - - pairingSalt = "Keycard Pairing Password Salt" -) - -// SecureChannelSession enables secure communication with a hardware wallet. -type SecureChannelSession struct { - card *pcsc.Card // A handle to the smartcard for communication - secret []byte // A shared secret generated from our ECDSA keys - publicKey []byte // Our own ephemeral public key - PairingKey []byte // A permanent shared secret for a pairing, if present - sessionEncKey []byte // The current session encryption key - sessionMacKey []byte // The current session MAC key - iv []byte // The current IV - PairingIndex uint8 // The pairing index -} - -// NewSecureChannelSession creates a new secure channel for the given card and public key. -func NewSecureChannelSession(card *pcsc.Card, keyData []byte) (*SecureChannelSession, error) { - // Generate an ECDSA keypair for ourselves - key, err := crypto.GenerateKey() - if err != nil { - return nil, err - } - cardPublic, err := crypto.UnmarshalPubkey(keyData) - if err != nil { - return nil, fmt.Errorf("could not unmarshal public key from card: %v", err) - } - secret, _ := key.Curve.ScalarMult(cardPublic.X, cardPublic.Y, key.D.Bytes()) - return &SecureChannelSession{ - card: card, - secret: secret.Bytes(), - publicKey: elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y), - }, nil -} - -// Pair establishes a new pairing with the smartcard. -func (s *SecureChannelSession) Pair(pairingPassword []byte) error { - secretHash := pbkdf2.Key(norm.NFKD.Bytes(pairingPassword), norm.NFKD.Bytes([]byte(pairingSalt)), 50000, 32, sha256.New) - - challenge := make([]byte, 32) - if _, err := rand.Read(challenge); err != nil { - return err - } - - response, err := s.pair(pairP1FirstStep, challenge) - if err != nil { - return err - } - - md := sha256.New() - md.Write(secretHash[:]) - md.Write(challenge) - - expectedCryptogram := md.Sum(nil) - cardCryptogram := response.Data[:32] - cardChallenge := response.Data[32:64] - - if !bytes.Equal(expectedCryptogram, cardCryptogram) { - return fmt.Errorf("invalid card cryptogram %v != %v", expectedCryptogram, cardCryptogram) - } - - md.Reset() - md.Write(secretHash[:]) - md.Write(cardChallenge) - response, err = s.pair(pairP1LastStep, md.Sum(nil)) - if err != nil { - return err - } - - md.Reset() - md.Write(secretHash[:]) - md.Write(response.Data[1:]) - s.PairingKey = md.Sum(nil) - s.PairingIndex = response.Data[0] - - return nil -} - -// Unpair disestablishes an existing pairing. -func (s *SecureChannelSession) Unpair() error { - if s.PairingKey == nil { - return errors.New("cannot unpair: not paired") - } - - _, err := s.transmitEncrypted(claSCWallet, insUnpair, s.PairingIndex, 0, []byte{}) - if err != nil { - return err - } - s.PairingKey = nil - // Close channel - s.iv = nil - return nil -} - -// Open initializes the secure channel. -func (s *SecureChannelSession) Open() error { - if s.iv != nil { - return errors.New("session already opened") - } - - response, err := s.open() - if err != nil { - return err - } - - // Generate the encryption/mac key by hashing our shared secret, - // pairing key, and the first bytes returned from the Open APDU. - md := sha512.New() - md.Write(s.secret) - md.Write(s.PairingKey) - md.Write(response.Data[:scSecretLength]) - keyData := md.Sum(nil) - s.sessionEncKey = keyData[:scSecretLength] - s.sessionMacKey = keyData[scSecretLength : scSecretLength*2] - - // The IV is the last bytes returned from the Open APDU. - s.iv = response.Data[scSecretLength:] - - return s.mutuallyAuthenticate() -} - -// mutuallyAuthenticate is an internal method to authenticate both ends of the -// connection. -func (s *SecureChannelSession) mutuallyAuthenticate() error { - data := make([]byte, scSecretLength) - if _, err := rand.Read(data); err != nil { - return err - } - - response, err := s.transmitEncrypted(claSCWallet, insMutuallyAuthenticate, 0, 0, data) - if err != nil { - return err - } - if response.Sw1 != 0x90 || response.Sw2 != 0x00 { - return fmt.Errorf("got unexpected response from MUTUALLY_AUTHENTICATE: %#x%x", response.Sw1, response.Sw2) - } - - if len(response.Data) != scSecretLength { - return fmt.Errorf("response from MUTUALLY_AUTHENTICATE was %d bytes, expected %d", len(response.Data), scSecretLength) - } - - return nil -} - -// open is an internal method that sends an open APDU. -func (s *SecureChannelSession) open() (*responseAPDU, error) { - return transmit(s.card, &commandAPDU{ - Cla: claSCWallet, - Ins: insOpenSecureChannel, - P1: s.PairingIndex, - P2: 0, - Data: s.publicKey, - Le: 0, - }) -} - -// pair is an internal method that sends a pair APDU. -func (s *SecureChannelSession) pair(p1 uint8, data []byte) (*responseAPDU, error) { - return transmit(s.card, &commandAPDU{ - Cla: claSCWallet, - Ins: insPair, - P1: p1, - P2: 0, - Data: data, - Le: 0, - }) -} - -// transmitEncrypted sends an encrypted message, and decrypts and returns the response. -func (s *SecureChannelSession) transmitEncrypted(cla, ins, p1, p2 byte, data []byte) (*responseAPDU, error) { - if s.iv == nil { - return nil, errors.New("channel not open") - } - - data, err := s.encryptAPDU(data) - if err != nil { - return nil, err - } - meta := [16]byte{cla, ins, p1, p2, byte(len(data) + scBlockSize)} - if err = s.updateIV(meta[:], data); err != nil { - return nil, err - } - - fulldata := make([]byte, len(s.iv)+len(data)) - copy(fulldata, s.iv) - copy(fulldata[len(s.iv):], data) - - response, err := transmit(s.card, &commandAPDU{ - Cla: cla, - Ins: ins, - P1: p1, - P2: p2, - Data: fulldata, - }) - if err != nil { - return nil, err - } - - rmeta := [16]byte{byte(len(response.Data))} - rmac := response.Data[:len(s.iv)] - rdata := response.Data[len(s.iv):] - plainData, err := s.decryptAPDU(rdata) - if err != nil { - return nil, err - } - - if err = s.updateIV(rmeta[:], rdata); err != nil { - return nil, err - } - if !bytes.Equal(s.iv, rmac) { - return nil, errors.New("invalid MAC in response") - } - - rapdu := &responseAPDU{} - rapdu.deserialize(plainData) - - if rapdu.Sw1 != sw1Ok { - return nil, fmt.Errorf("unexpected response status Cla=%#x, Ins=%#x, Sw=%#x%x", cla, ins, rapdu.Sw1, rapdu.Sw2) - } - - return rapdu, nil -} - -// encryptAPDU is an internal method that serializes and encrypts an APDU. -func (s *SecureChannelSession) encryptAPDU(data []byte) ([]byte, error) { - if len(data) > maxPayloadSize { - return nil, fmt.Errorf("payload of %d bytes exceeds maximum of %d", len(data), maxPayloadSize) - } - data = pad(data, 0x80) - - ret := make([]byte, len(data)) - - a, err := aes.NewCipher(s.sessionEncKey) - if err != nil { - return nil, err - } - crypter := cipher.NewCBCEncrypter(a, s.iv) - crypter.CryptBlocks(ret, data) - return ret, nil -} - -// pad applies message padding to a 16 byte boundary. -func pad(data []byte, terminator byte) []byte { - padded := make([]byte, (len(data)/16+1)*16) - copy(padded, data) - padded[len(data)] = terminator - return padded -} - -// decryptAPDU is an internal method that decrypts and deserializes an APDU. -func (s *SecureChannelSession) decryptAPDU(data []byte) ([]byte, error) { - a, err := aes.NewCipher(s.sessionEncKey) - if err != nil { - return nil, err - } - - ret := make([]byte, len(data)) - - crypter := cipher.NewCBCDecrypter(a, s.iv) - crypter.CryptBlocks(ret, data) - return unpad(ret, 0x80) -} - -// unpad strips padding from a message. -func unpad(data []byte, terminator byte) ([]byte, error) { - for i := 1; i <= 16; i++ { - switch data[len(data)-i] { - case 0: - continue - case terminator: - return data[:len(data)-i], nil - default: - return nil, fmt.Errorf("expected end of padding, got %d", data[len(data)-i]) - } - } - return nil, errors.New("expected end of padding, got 0") -} - -// updateIV is an internal method that updates the initialization vector after -// each message exchanged. -func (s *SecureChannelSession) updateIV(meta, data []byte) error { - data = pad(data, 0) - a, err := aes.NewCipher(s.sessionMacKey) - if err != nil { - return err - } - crypter := cipher.NewCBCEncrypter(a, make([]byte, 16)) - crypter.CryptBlocks(meta, meta) - crypter.CryptBlocks(data, data) - // The first 16 bytes of the last block is the MAC - s.iv = data[len(data)-32 : len(data)-16] - return nil -} diff --git a/builder/accounts/scwallet/wallet.go b/builder/accounts/scwallet/wallet.go deleted file mode 100644 index f0ca9085b..000000000 --- a/builder/accounts/scwallet/wallet.go +++ /dev/null @@ -1,1088 +0,0 @@ -// Copyright 2018 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 scwallet - -import ( - "bytes" - "context" - "crypto/hmac" - "crypto/sha256" - "crypto/sha512" - "encoding/asn1" - "encoding/binary" - "errors" - "fmt" - "math/big" - "regexp" - "sort" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - pcsc "github.com/gballet/go-libpcsclite" - "github.com/status-im/keycard-go/derivationpath" -) - -// ErrPairingPasswordNeeded is returned if opening the smart card requires pairing with a pairing -// password. In this case, the calling application should request user input to enter -// the pairing password and send it back. -var ErrPairingPasswordNeeded = errors.New("smartcard: pairing password needed") - -// ErrPINNeeded is returned if opening the smart card requires a PIN code. In -// this case, the calling application should request user input to enter the PIN -// and send it back. -var ErrPINNeeded = errors.New("smartcard: pin needed") - -// ErrPINUnblockNeeded is returned if opening the smart card requires a PIN code, -// but all PIN attempts have already been exhausted. In this case the calling -// application should request user input for the PUK and a new PIN code to set -// fo the card. -var ErrPINUnblockNeeded = errors.New("smartcard: pin unblock needed") - -// ErrAlreadyOpen is returned if the smart card is attempted to be opened, but -// there is already a paired and unlocked session. -var ErrAlreadyOpen = errors.New("smartcard: already open") - -// ErrPubkeyMismatch is returned if the public key recovered from a signature -// does not match the one expected by the user. -var ErrPubkeyMismatch = errors.New("smartcard: recovered public key mismatch") - -var ( - appletAID = []byte{0xA0, 0x00, 0x00, 0x08, 0x04, 0x00, 0x01, 0x01, 0x01} - // DerivationSignatureHash is used to derive the public key from the signature of this hash - DerivationSignatureHash = sha256.Sum256(common.Hash{}.Bytes()) -) - -// List of APDU command-related constants -const ( - claISO7816 = 0 - claSCWallet = 0x80 - - insSelect = 0xA4 - insGetResponse = 0xC0 - sw1GetResponse = 0x61 - sw1Ok = 0x90 - - insVerifyPin = 0x20 - insUnblockPin = 0x22 - insExportKey = 0xC2 - insSign = 0xC0 - insLoadKey = 0xD0 - insDeriveKey = 0xD1 - insStatus = 0xF2 -) - -// List of ADPU command parameters -const ( - P1DeriveKeyFromMaster = uint8(0x00) - P1DeriveKeyFromParent = uint8(0x01) - P1DeriveKeyFromCurrent = uint8(0x10) - statusP1WalletStatus = uint8(0x00) - statusP1Path = uint8(0x01) - signP1PrecomputedHash = uint8(0x00) - signP2OnlyBlock = uint8(0x00) - exportP1Any = uint8(0x00) - exportP2Pubkey = uint8(0x01) -) - -// Minimum time to wait between self derivation attempts, even it the user is -// requesting accounts like crazy. -const selfDeriveThrottling = time.Second - -// Wallet represents a smartcard wallet instance. -type Wallet struct { - Hub *Hub // A handle to the Hub that instantiated this wallet. - PublicKey []byte // The wallet's public key (used for communication and identification, not signing!) - - lock sync.Mutex // Lock that gates access to struct fields and communication with the card - card *pcsc.Card // A handle to the smartcard interface for the wallet. - session *Session // The secure communication session with the card - log log.Logger // Contextual logger to tag the base with its id - - deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported) - deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported) - deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with - deriveReq chan chan struct{} // Channel to request a self-derivation on - deriveQuit chan chan error // Channel to terminate the self-deriver with -} - -// NewWallet constructs and returns a new Wallet instance. -func NewWallet(hub *Hub, card *pcsc.Card) *Wallet { - wallet := &Wallet{ - Hub: hub, - card: card, - } - return wallet -} - -// transmit sends an APDU to the smartcard and receives and decodes the response. -// It automatically handles requests by the card to fetch the return data separately, -// and returns an error if the response status code is not success. -func transmit(card *pcsc.Card, command *commandAPDU) (*responseAPDU, error) { - data, err := command.serialize() - if err != nil { - return nil, err - } - - responseData, _, err := card.Transmit(data) - if err != nil { - return nil, err - } - - response := new(responseAPDU) - if err = response.deserialize(responseData); err != nil { - return nil, err - } - - // Are we being asked to fetch the response separately? - if response.Sw1 == sw1GetResponse && (command.Cla != claISO7816 || command.Ins != insGetResponse) { - return transmit(card, &commandAPDU{ - Cla: claISO7816, - Ins: insGetResponse, - P1: 0, - P2: 0, - Data: nil, - Le: response.Sw2, - }) - } - - if response.Sw1 != sw1Ok { - return nil, fmt.Errorf("unexpected insecure response status Cla=%#x, Ins=%#x, Sw=%#x%x", command.Cla, command.Ins, response.Sw1, response.Sw2) - } - - return response, nil -} - -// applicationInfo encodes information about the smartcard application - its -// instance UID and public key. -type applicationInfo struct { - InstanceUID []byte `asn1:"tag:15"` - PublicKey []byte `asn1:"tag:0"` -} - -// connect connects to the wallet application and establishes a secure channel with it. -// must be called before any other interaction with the wallet. -func (w *Wallet) connect() error { - w.lock.Lock() - defer w.lock.Unlock() - - appinfo, err := w.doselect() - if err != nil { - return err - } - - channel, err := NewSecureChannelSession(w.card, appinfo.PublicKey) - if err != nil { - return err - } - - w.PublicKey = appinfo.PublicKey - w.log = log.New("url", w.URL()) - w.session = &Session{ - Wallet: w, - Channel: channel, - } - return nil -} - -// doselect is an internal (unlocked) function to send a SELECT APDU to the card. -func (w *Wallet) doselect() (*applicationInfo, error) { - response, err := transmit(w.card, &commandAPDU{ - Cla: claISO7816, - Ins: insSelect, - P1: 4, - P2: 0, - Data: appletAID, - }) - if err != nil { - return nil, err - } - - appinfo := new(applicationInfo) - if _, err := asn1.UnmarshalWithParams(response.Data, appinfo, "tag:4"); err != nil { - return nil, err - } - return appinfo, nil -} - -// ping checks the card's status and returns an error if unsuccessful. -func (w *Wallet) ping() error { - w.lock.Lock() - defer w.lock.Unlock() - - // We can't ping if not paired - if !w.session.paired() { - return nil - } - if _, err := w.session.walletStatus(); err != nil { - return err - } - return nil -} - -// release releases any resources held by an open wallet instance. -func (w *Wallet) release() error { - if w.session != nil { - return w.session.release() - } - return nil -} - -// pair is an internal (unlocked) function for establishing a new pairing -// with the wallet. -func (w *Wallet) pair(puk []byte) error { - if w.session.paired() { - return errors.New("wallet already paired") - } - pairing, err := w.session.pair(puk) - if err != nil { - return err - } - if err = w.Hub.setPairing(w, &pairing); err != nil { - return err - } - return w.session.authenticate(pairing) -} - -// Unpair deletes an existing wallet pairing. -func (w *Wallet) Unpair(pin []byte) error { - w.lock.Lock() - defer w.lock.Unlock() - - if !w.session.paired() { - return fmt.Errorf("wallet %x not paired", w.PublicKey) - } - if err := w.session.verifyPin(pin); err != nil { - return fmt.Errorf("failed to verify pin: %s", err) - } - if err := w.session.unpair(); err != nil { - return fmt.Errorf("failed to unpair: %s", err) - } - if err := w.Hub.setPairing(w, nil); err != nil { - return err - } - return nil -} - -// URL retrieves the canonical path under which this wallet is reachable. It is -// user by upper layers to define a sorting order over all wallets from multiple -// backends. -func (w *Wallet) URL() accounts.URL { - return accounts.URL{ - Scheme: w.Hub.scheme, - Path: fmt.Sprintf("%x", w.PublicKey[1:5]), // Byte #0 isn't unique; 1:5 covers << 64K cards, bump to 1:9 for << 4M - } -} - -// Status returns a textual status to aid the user in the current state of the -// wallet. It also returns an error indicating any failure the wallet might have -// encountered. -func (w *Wallet) Status() (string, error) { - w.lock.Lock() - defer w.lock.Unlock() - - // If the card is not paired, we can only wait - if !w.session.paired() { - return "Unpaired, waiting for pairing password", nil - } - // Yay, we have an encrypted session, retrieve the actual status - status, err := w.session.walletStatus() - if err != nil { - return fmt.Sprintf("Failed: %v", err), err - } - switch { - case !w.session.verified && status.PinRetryCount == 0 && status.PukRetryCount == 0: - return "Bricked, waiting for full wipe", nil - case !w.session.verified && status.PinRetryCount == 0: - return fmt.Sprintf("Blocked, waiting for PUK (%d attempts left) and new PIN", status.PukRetryCount), nil - case !w.session.verified: - return fmt.Sprintf("Locked, waiting for PIN (%d attempts left)", status.PinRetryCount), nil - case !status.Initialized: - return "Empty, waiting for initialization", nil - default: - return "Online", nil - } -} - -// Open initializes access to a wallet instance. It is not meant to unlock or -// decrypt account keys, rather simply to establish a connection to hardware -// wallets and/or to access derivation seeds. -// -// The passphrase parameter may or may not be used by the implementation of a -// particular wallet instance. The reason there is no passwordless open method -// is to strive towards a uniform wallet handling, oblivious to the different -// backend providers. -// -// Please note, if you open a wallet, you must close it to release any allocated -// resources (especially important when working with hardware wallets). -func (w *Wallet) Open(passphrase string) error { - w.lock.Lock() - defer w.lock.Unlock() - - // If the session is already open, bail out - if w.session.verified { - return ErrAlreadyOpen - } - // If the smart card is not yet paired, attempt to do so either from a previous - // pairing key or form the supplied PUK code. - if !w.session.paired() { - // If a previous pairing exists, only ever try to use that - if pairing := w.Hub.pairing(w); pairing != nil { - if err := w.session.authenticate(*pairing); err != nil { - return fmt.Errorf("failed to authenticate card %x: %s", w.PublicKey[:4], err) - } - // Pairing still ok, fall through to PIN checks - } else { - // If no passphrase was supplied, request the PUK from the user - if passphrase == "" { - return ErrPairingPasswordNeeded - } - // Attempt to pair the smart card with the user supplied PUK - if err := w.pair([]byte(passphrase)); err != nil { - return err - } - // Pairing succeeded, fall through to PIN checks. This will of course fail, - // but we can't return ErrPINNeeded directly here because we don't know whether - // a PIN check or a PIN reset is needed. - passphrase = "" - } - } - // The smart card was successfully paired, retrieve its status to check whether - // PIN verification or unblocking is needed. - status, err := w.session.walletStatus() - if err != nil { - return err - } - // Request the appropriate next authentication data, or use the one supplied - switch { - case passphrase == "" && status.PinRetryCount > 0: - return ErrPINNeeded - case passphrase == "": - return ErrPINUnblockNeeded - case status.PinRetryCount > 0: - if !regexp.MustCompile(`^[0-9]{6,}$`).MatchString(passphrase) { - w.log.Error("PIN needs to be at least 6 digits") - return ErrPINNeeded - } - if err := w.session.verifyPin([]byte(passphrase)); err != nil { - return err - } - default: - if !regexp.MustCompile(`^[0-9]{12,}$`).MatchString(passphrase) { - w.log.Error("PUK needs to be at least 12 digits") - return ErrPINUnblockNeeded - } - if err := w.session.unblockPin([]byte(passphrase)); err != nil { - return err - } - } - // Smart card paired and unlocked, initialize and register - w.deriveReq = make(chan chan struct{}) - w.deriveQuit = make(chan chan error) - - go w.selfDerive() - - // Notify anyone listening for wallet events that a new device is accessible - go w.Hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened}) - - return nil -} - -// Close stops and closes the wallet, freeing any resources. -func (w *Wallet) Close() error { - // Ensure the wallet was opened - w.lock.Lock() - dQuit := w.deriveQuit - w.lock.Unlock() - - // Terminate the self-derivations - var derr error - if dQuit != nil { - errc := make(chan error) - dQuit <- errc - derr = <-errc // Save for later, we *must* close the USB - } - // Terminate the device connection - w.lock.Lock() - defer w.lock.Unlock() - - w.deriveQuit = nil - w.deriveReq = nil - - if err := w.release(); err != nil { - return err - } - return derr -} - -// selfDerive is an account derivation loop that upon request attempts to find -// new non-zero accounts. -func (w *Wallet) selfDerive() { - w.log.Debug("Smart card wallet self-derivation started") - defer w.log.Debug("Smart card wallet self-derivation stopped") - - // Execute self-derivations until termination or error - var ( - reqc chan struct{} - errc chan error - err error - ) - for errc == nil && err == nil { - // Wait until either derivation or termination is requested - select { - case errc = <-w.deriveQuit: - // Termination requested - continue - case reqc = <-w.deriveReq: - // Account discovery requested - } - // Derivation needs a chain and device access, skip if either unavailable - w.lock.Lock() - if w.session == nil || w.deriveChain == nil { - w.lock.Unlock() - reqc <- struct{}{} - continue - } - pairing := w.Hub.pairing(w) - - // Device lock obtained, derive the next batch of accounts - var ( - paths []accounts.DerivationPath - nextAcc accounts.Account - - nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...) - nextAddrs = append([]common.Address{}, w.deriveNextAddrs...) - - context = context.Background() - ) - for i := 0; i < len(nextAddrs); i++ { - for empty := false; !empty; { - // Retrieve the next derived Ethereum account - if nextAddrs[i] == (common.Address{}) { - if nextAcc, err = w.session.derive(nextPaths[i]); err != nil { - w.log.Warn("Smartcard wallet account derivation failed", "err", err) - break - } - nextAddrs[i] = nextAcc.Address - } - // Check the account's status against the current chain state - var ( - balance *big.Int - nonce uint64 - ) - balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil) - if err != nil { - w.log.Warn("Smartcard wallet balance retrieval failed", "err", err) - break - } - nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil) - if err != nil { - w.log.Warn("Smartcard wallet nonce retrieval failed", "err", err) - break - } - // If the next account is empty, stop self-derivation, but add for the last base path - if balance.Sign() == 0 && nonce == 0 { - empty = true - if i < len(nextAddrs)-1 { - break - } - } - // We've just self-derived a new account, start tracking it locally - path := make(accounts.DerivationPath, len(nextPaths[i])) - copy(path[:], nextPaths[i][:]) - paths = append(paths, path) - - // Display a log message to the user for new (or previously empty accounts) - if _, known := pairing.Accounts[nextAddrs[i]]; !known || !empty || nextAddrs[i] != w.deriveNextAddrs[i] { - w.log.Info("Smartcard wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce) - } - pairing.Accounts[nextAddrs[i]] = path - - // Fetch the next potential account - if !empty { - nextAddrs[i] = common.Address{} - nextPaths[i][len(nextPaths[i])-1]++ - } - } - } - // If there are new accounts, write them out - if len(paths) > 0 { - err = w.Hub.setPairing(w, pairing) - } - // Shift the self-derivation forward - w.deriveNextAddrs = nextAddrs - w.deriveNextPaths = nextPaths - - // Self derivation complete, release device lock - w.lock.Unlock() - - // Notify the user of termination and loop after a bit of time (to avoid trashing) - reqc <- struct{}{} - if err == nil { - select { - case errc = <-w.deriveQuit: - // Termination requested, abort - case <-time.After(selfDeriveThrottling): - // Waited enough, willing to self-derive again - } - } - } - // In case of error, wait for termination - if err != nil { - w.log.Debug("Smartcard wallet self-derivation failed", "err", err) - errc = <-w.deriveQuit - } - errc <- err -} - -// Accounts retrieves the list of signing accounts the wallet is currently aware -// of. For hierarchical deterministic wallets, the list will not be exhaustive, -// rather only contain the accounts explicitly pinned during account derivation. -func (w *Wallet) Accounts() []accounts.Account { - // Attempt self-derivation if it's running - reqc := make(chan struct{}, 1) - select { - case w.deriveReq <- reqc: - // Self-derivation request accepted, wait for it - <-reqc - default: - // Self-derivation offline, throttled or busy, skip - } - - w.lock.Lock() - defer w.lock.Unlock() - - if pairing := w.Hub.pairing(w); pairing != nil { - ret := make([]accounts.Account, 0, len(pairing.Accounts)) - for address, path := range pairing.Accounts { - ret = append(ret, w.makeAccount(address, path)) - } - sort.Sort(accounts.AccountsByURL(ret)) - return ret - } - return nil -} - -func (w *Wallet) makeAccount(address common.Address, path accounts.DerivationPath) accounts.Account { - return accounts.Account{ - Address: address, - URL: accounts.URL{ - Scheme: w.Hub.scheme, - Path: fmt.Sprintf("%x/%s", w.PublicKey[1:3], path.String()), - }, - } -} - -// Contains returns whether an account is part of this particular wallet or not. -func (w *Wallet) Contains(account accounts.Account) bool { - if pairing := w.Hub.pairing(w); pairing != nil { - _, ok := pairing.Accounts[account.Address] - return ok - } - return false -} - -// Initialize installs a keypair generated from the provided key into the wallet. -func (w *Wallet) Initialize(seed []byte) error { - go w.selfDerive() - // DO NOT lock at this stage, as the initialize - // function relies on Status() - return w.session.initialize(seed) -} - -// Derive attempts to explicitly derive a hierarchical deterministic account at -// the specified derivation path. If requested, the derived account will be added -// to the wallet's tracked account list. -func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { - w.lock.Lock() - defer w.lock.Unlock() - - account, err := w.session.derive(path) - if err != nil { - return accounts.Account{}, err - } - - if pin { - pairing := w.Hub.pairing(w) - pairing.Accounts[account.Address] = path - if err := w.Hub.setPairing(w, pairing); err != nil { - return accounts.Account{}, err - } - } - - return account, nil -} - -// SelfDerive sets a base account derivation path from which the wallet attempts -// to discover non zero accounts and automatically add them to list of tracked -// accounts. -// -// Note, self derivation will increment the last component of the specified path -// opposed to descending into a child path to allow discovering accounts starting -// from non zero components. -// -// Some hardware wallets switched derivation paths through their evolution, so -// this method supports providing multiple bases to discover old user accounts -// too. Only the last base will be used to derive the next empty account. -// -// You can disable automatic account discovery by calling SelfDerive with a nil -// chain state reader. -func (w *Wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { - w.lock.Lock() - defer w.lock.Unlock() - - w.deriveNextPaths = make([]accounts.DerivationPath, len(bases)) - for i, base := range bases { - w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base)) - copy(w.deriveNextPaths[i][:], base[:]) - } - w.deriveNextAddrs = make([]common.Address, len(bases)) - w.deriveChain = chain -} - -// SignData requests the wallet to sign the hash of the given data. -// -// It looks up the account specified either solely via its address contained within, -// or optionally with the aid of any location metadata from the embedded URL field. -// -// If the wallet requires additional authentication to sign the request (e.g. -// a password to decrypt the account, or a PIN code o verify the transaction), -// an AuthNeededError instance will be returned, containing infos for the user -// about which fields or actions are needed. The user may retry by providing -// the needed details via SignDataWithPassphrase, or by other means (e.g. unlock -// the account in a keystore). -func (w *Wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - return w.signHash(account, crypto.Keccak256(data)) -} - -func (w *Wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { - w.lock.Lock() - defer w.lock.Unlock() - - path, err := w.findAccountPath(account) - if err != nil { - return nil, err - } - - return w.session.sign(path, hash) -} - -// SignTx requests the wallet to sign the given transaction. -// -// It looks up the account specified either solely via its address contained within, -// or optionally with the aid of any location metadata from the embedded URL field. -// -// If the wallet requires additional authentication to sign the request (e.g. -// a password to decrypt the account, or a PIN code o verify the transaction), -// an AuthNeededError instance will be returned, containing infos for the user -// about which fields or actions are needed. The user may retry by providing -// the needed details via SignTxWithPassphrase, or by other means (e.g. unlock -// the account in a keystore). -func (w *Wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - signer := types.LatestSignerForChainID(chainID) - hash := signer.Hash(tx) - sig, err := w.signHash(account, hash[:]) - if err != nil { - return nil, err - } - return tx.WithSignature(signer, sig) -} - -// SignDataWithPassphrase requests the wallet to sign the given hash with the -// given passphrase as extra authentication information. -// -// It looks up the account specified either solely via its address contained within, -// or optionally with the aid of any location metadata from the embedded URL field. -func (w *Wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { - return w.signHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) -} - -func (w *Wallet) signHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { - if !w.session.verified { - if err := w.Open(passphrase); err != nil { - return nil, err - } - } - - return w.signHash(account, hash) -} - -// SignText requests the wallet to sign the hash of a given piece of data, prefixed -// by the Ethereum prefix scheme -// It looks up the account specified either solely via its address contained within, -// or optionally with the aid of any location metadata from the embedded URL field. -// -// If the wallet requires additional authentication to sign the request (e.g. -// a password to decrypt the account, or a PIN code o verify the transaction), -// an AuthNeededError instance will be returned, containing infos for the user -// about which fields or actions are needed. The user may retry by providing -// the needed details via SignHashWithPassphrase, or by other means (e.g. unlock -// the account in a keystore). -func (w *Wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { - return w.signHash(account, accounts.TextHash(text)) -} - -// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the -// given hash with the given account using passphrase as extra authentication -func (w *Wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { - return w.signHashWithPassphrase(account, passphrase, crypto.Keccak256(accounts.TextHash(text))) -} - -// SignTxWithPassphrase requests the wallet to sign the given transaction, with the -// given passphrase as extra authentication information. -// -// It looks up the account specified either solely via its address contained within, -// or optionally with the aid of any location metadata from the embedded URL field. -func (w *Wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - if !w.session.verified { - if err := w.Open(passphrase); err != nil { - return nil, err - } - } - return w.SignTx(account, tx, chainID) -} - -// findAccountPath returns the derivation path for the provided account. -// It first checks for the address in the list of pinned accounts, and if it is -// not found, attempts to parse the derivation path from the account's URL. -func (w *Wallet) findAccountPath(account accounts.Account) (accounts.DerivationPath, error) { - pairing := w.Hub.pairing(w) - if path, ok := pairing.Accounts[account.Address]; ok { - return path, nil - } - - // Look for the path in the URL - if account.URL.Scheme != w.Hub.scheme { - return nil, fmt.Errorf("scheme %s does not match wallet scheme %s", account.URL.Scheme, w.Hub.scheme) - } - - url, path, found := strings.Cut(account.URL.Path, "/") - if !found { - return nil, fmt.Errorf("invalid URL format: %s", account.URL) - } - - if url != fmt.Sprintf("%x", w.PublicKey[1:3]) { - return nil, fmt.Errorf("URL %s is not for this wallet", account.URL) - } - - return accounts.ParseDerivationPath(path) -} - -// Session represents a secured communication session with the wallet. -type Session struct { - Wallet *Wallet // A handle to the wallet that opened the session - Channel *SecureChannelSession // A secure channel for encrypted messages - verified bool // Whether the pin has been verified in this session. -} - -// pair establishes a new pairing over this channel, using the provided secret. -func (s *Session) pair(secret []byte) (smartcardPairing, error) { - err := s.Channel.Pair(secret) - if err != nil { - return smartcardPairing{}, err - } - - return smartcardPairing{ - PublicKey: s.Wallet.PublicKey, - PairingIndex: s.Channel.PairingIndex, - PairingKey: s.Channel.PairingKey, - Accounts: make(map[common.Address]accounts.DerivationPath), - }, nil -} - -// unpair deletes an existing pairing. -func (s *Session) unpair() error { - if !s.verified { - return errors.New("unpair requires that the PIN be verified") - } - return s.Channel.Unpair() -} - -// verifyPin unlocks a wallet with the provided pin. -func (s *Session) verifyPin(pin []byte) error { - if _, err := s.Channel.transmitEncrypted(claSCWallet, insVerifyPin, 0, 0, pin); err != nil { - return err - } - s.verified = true - return nil -} - -// unblockPin unblocks a wallet with the provided puk and resets the pin to the -// new one specified. -func (s *Session) unblockPin(pukpin []byte) error { - if _, err := s.Channel.transmitEncrypted(claSCWallet, insUnblockPin, 0, 0, pukpin); err != nil { - return err - } - s.verified = true - return nil -} - -// release releases resources associated with the channel. -func (s *Session) release() error { - return s.Wallet.card.Disconnect(pcsc.LeaveCard) -} - -// paired returns true if a valid pairing exists. -func (s *Session) paired() bool { - return s.Channel.PairingKey != nil -} - -// authenticate uses an existing pairing to establish a secure channel. -func (s *Session) authenticate(pairing smartcardPairing) error { - if !bytes.Equal(s.Wallet.PublicKey, pairing.PublicKey) { - return fmt.Errorf("cannot pair using another wallet's pairing; %x != %x", s.Wallet.PublicKey, pairing.PublicKey) - } - s.Channel.PairingKey = pairing.PairingKey - s.Channel.PairingIndex = pairing.PairingIndex - return s.Channel.Open() -} - -// walletStatus describes a smartcard wallet's status information. -type walletStatus struct { - PinRetryCount int // Number of remaining PIN retries - PukRetryCount int // Number of remaining PUK retries - Initialized bool // Whether the card has been initialized with a private key -} - -// walletStatus fetches the wallet's status from the card. -func (s *Session) walletStatus() (*walletStatus, error) { - response, err := s.Channel.transmitEncrypted(claSCWallet, insStatus, statusP1WalletStatus, 0, nil) - if err != nil { - return nil, err - } - - status := new(walletStatus) - if _, err := asn1.UnmarshalWithParams(response.Data, status, "tag:3"); err != nil { - return nil, err - } - return status, nil -} - -// derivationPath fetches the wallet's current derivation path from the card. -// -//lint:ignore U1000 needs to be added to the console interface -func (s *Session) derivationPath() (accounts.DerivationPath, error) { - response, err := s.Channel.transmitEncrypted(claSCWallet, insStatus, statusP1Path, 0, nil) - if err != nil { - return nil, err - } - buf := bytes.NewReader(response.Data) - path := make(accounts.DerivationPath, len(response.Data)/4) - return path, binary.Read(buf, binary.BigEndian, &path) -} - -// initializeData contains data needed to initialize the smartcard wallet. -type initializeData struct { - PublicKey []byte `asn1:"tag:0"` - PrivateKey []byte `asn1:"tag:1"` - ChainCode []byte `asn1:"tag:2"` -} - -// initialize initializes the card with new key data. -func (s *Session) initialize(seed []byte) error { - // Check that the wallet isn't currently initialized, - // otherwise the key would be overwritten. - status, err := s.Wallet.Status() - if err != nil { - return err - } - if status == "Online" { - return errors.New("card is already initialized, cowardly refusing to proceed") - } - - s.Wallet.lock.Lock() - defer s.Wallet.lock.Unlock() - - // HMAC the seed to produce the private key and chain code - mac := hmac.New(sha512.New, []byte("Bitcoin seed")) - mac.Write(seed) - seed = mac.Sum(nil) - - key, err := crypto.ToECDSA(seed[:32]) - if err != nil { - return err - } - - id := initializeData{} - id.PublicKey = crypto.FromECDSAPub(&key.PublicKey) - id.PrivateKey = seed[:32] - id.ChainCode = seed[32:] - data, err := asn1.Marshal(id) - if err != nil { - return err - } - - // Nasty hack to force the top-level struct tag to be context-specific - data[0] = 0xA1 - - _, err = s.Channel.transmitEncrypted(claSCWallet, insLoadKey, 0x02, 0, data) - return err -} - -// derive derives a new HD key path on the card. -func (s *Session) derive(path accounts.DerivationPath) (accounts.Account, error) { - startingPoint, path, err := derivationpath.Decode(path.String()) - if err != nil { - return accounts.Account{}, err - } - - var p1 uint8 - switch startingPoint { - case derivationpath.StartingPointMaster: - p1 = P1DeriveKeyFromMaster - case derivationpath.StartingPointParent: - p1 = P1DeriveKeyFromParent - case derivationpath.StartingPointCurrent: - p1 = P1DeriveKeyFromCurrent - default: - return accounts.Account{}, fmt.Errorf("invalid startingPoint %d", startingPoint) - } - - data := new(bytes.Buffer) - for _, segment := range path { - if err := binary.Write(data, binary.BigEndian, segment); err != nil { - return accounts.Account{}, err - } - } - - _, err = s.Channel.transmitEncrypted(claSCWallet, insDeriveKey, p1, 0, data.Bytes()) - if err != nil { - return accounts.Account{}, err - } - - response, err := s.Channel.transmitEncrypted(claSCWallet, insSign, 0, 0, DerivationSignatureHash[:]) - if err != nil { - return accounts.Account{}, err - } - - sigdata := new(signatureData) - if _, err := asn1.UnmarshalWithParams(response.Data, sigdata, "tag:0"); err != nil { - return accounts.Account{}, err - } - rbytes, sbytes := sigdata.Signature.R.Bytes(), sigdata.Signature.S.Bytes() - sig := make([]byte, 65) - copy(sig[32-len(rbytes):32], rbytes) - copy(sig[64-len(sbytes):64], sbytes) - - if err := confirmPublicKey(sig, sigdata.PublicKey); err != nil { - return accounts.Account{}, err - } - pub, err := crypto.UnmarshalPubkey(sigdata.PublicKey) - if err != nil { - return accounts.Account{}, err - } - return s.Wallet.makeAccount(crypto.PubkeyToAddress(*pub), path), nil -} - -// keyExport contains information on an exported keypair. -// -//lint:ignore U1000 needs to be added to the console interface -type keyExport struct { - PublicKey []byte `asn1:"tag:0"` - PrivateKey []byte `asn1:"tag:1,optional"` -} - -// publicKey returns the public key for the current derivation path. -// -//lint:ignore U1000 needs to be added to the console interface -func (s *Session) publicKey() ([]byte, error) { - response, err := s.Channel.transmitEncrypted(claSCWallet, insExportKey, exportP1Any, exportP2Pubkey, nil) - if err != nil { - return nil, err - } - keys := new(keyExport) - if _, err := asn1.UnmarshalWithParams(response.Data, keys, "tag:1"); err != nil { - return nil, err - } - return keys.PublicKey, nil -} - -// signatureData contains information on a signature - the signature itself and -// the corresponding public key. -type signatureData struct { - PublicKey []byte `asn1:"tag:0"` - Signature struct { - R *big.Int - S *big.Int - } -} - -// sign asks the card to sign a message, and returns a valid signature after -// recovering the v value. -func (s *Session) sign(path accounts.DerivationPath, hash []byte) ([]byte, error) { - startTime := time.Now() - _, err := s.derive(path) - if err != nil { - return nil, err - } - deriveTime := time.Now() - - response, err := s.Channel.transmitEncrypted(claSCWallet, insSign, signP1PrecomputedHash, signP2OnlyBlock, hash) - if err != nil { - return nil, err - } - sigdata := new(signatureData) - if _, err := asn1.UnmarshalWithParams(response.Data, sigdata, "tag:0"); err != nil { - return nil, err - } - // Serialize the signature - rbytes, sbytes := sigdata.Signature.R.Bytes(), sigdata.Signature.S.Bytes() - sig := make([]byte, 65) - copy(sig[32-len(rbytes):32], rbytes) - copy(sig[64-len(sbytes):64], sbytes) - - // Recover the V value. - sig, err = makeRecoverableSignature(hash, sig, sigdata.PublicKey) - if err != nil { - return nil, err - } - log.Debug("Signed using smartcard", "deriveTime", deriveTime.Sub(startTime), "signingTime", time.Since(deriveTime)) - - return sig, nil -} - -// confirmPublicKey confirms that the given signature belongs to the specified key. -func confirmPublicKey(sig, pubkey []byte) error { - _, err := makeRecoverableSignature(DerivationSignatureHash[:], sig, pubkey) - return err -} - -// makeRecoverableSignature uses a signature and an expected public key to -// recover the v value and produce a recoverable signature. -func makeRecoverableSignature(hash, sig, expectedPubkey []byte) ([]byte, error) { - var libraryError error - for v := 0; v < 2; v++ { - sig[64] = byte(v) - if pubkey, err := crypto.Ecrecover(hash, sig); err == nil { - if bytes.Equal(pubkey, expectedPubkey) { - return sig, nil - } - } else { - libraryError = err - } - } - if libraryError != nil { - return nil, libraryError - } - return nil, ErrPubkeyMismatch -} diff --git a/builder/accounts/sort.go b/builder/accounts/sort.go deleted file mode 100644 index f46762114..000000000 --- a/builder/accounts/sort.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 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 accounts - -// AccountsByURL implements sort.Interface for []Account based on the URL field. -type AccountsByURL []Account - -func (a AccountsByURL) Len() int { return len(a) } -func (a AccountsByURL) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a AccountsByURL) Less(i, j int) bool { return a[i].URL.Cmp(a[j].URL) < 0 } - -// WalletsByURL implements sort.Interface for []Wallet based on the URL field. -type WalletsByURL []Wallet - -func (w WalletsByURL) Len() int { return len(w) } -func (w WalletsByURL) Swap(i, j int) { w[i], w[j] = w[j], w[i] } -func (w WalletsByURL) Less(i, j int) bool { return w[i].URL().Cmp(w[j].URL()) < 0 } diff --git a/builder/accounts/url.go b/builder/accounts/url.go deleted file mode 100644 index 39b00e5b4..000000000 --- a/builder/accounts/url.go +++ /dev/null @@ -1,103 +0,0 @@ -// 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 accounts - -import ( - "encoding/json" - "errors" - "fmt" - "strings" -) - -// URL represents the canonical identification URL of a wallet or account. -// -// It is a simplified version of url.URL, with the important limitations (which -// are considered features here) that it contains value-copyable components only, -// as well as that it doesn't do any URL encoding/decoding of special characters. -// -// The former is important to allow an account to be copied without leaving live -// references to the original version, whereas the latter is important to ensure -// one single canonical form opposed to many allowed ones by the RFC 3986 spec. -// -// As such, these URLs should not be used outside of the scope of an Ethereum -// wallet or account. -type URL struct { - Scheme string // Protocol scheme to identify a capable account backend - Path string // Path for the backend to identify a unique entity -} - -// parseURL converts a user supplied URL into the accounts specific structure. -func parseURL(url string) (URL, error) { - parts := strings.Split(url, "://") - if len(parts) != 2 || parts[0] == "" { - return URL{}, errors.New("protocol scheme missing") - } - return URL{ - Scheme: parts[0], - Path: parts[1], - }, nil -} - -// String implements the stringer interface. -func (u URL) String() string { - if u.Scheme != "" { - return fmt.Sprintf("%s://%s", u.Scheme, u.Path) - } - return u.Path -} - -// TerminalString implements the log.TerminalStringer interface. -func (u URL) TerminalString() string { - url := u.String() - if len(url) > 32 { - return url[:31] + ".." - } - return url -} - -// MarshalJSON implements the json.Marshaller interface. -func (u URL) MarshalJSON() ([]byte, error) { - return json.Marshal(u.String()) -} - -// UnmarshalJSON parses url. -func (u *URL) UnmarshalJSON(input []byte) error { - var textURL string - err := json.Unmarshal(input, &textURL) - if err != nil { - return err - } - url, err := parseURL(textURL) - if err != nil { - return err - } - u.Scheme = url.Scheme - u.Path = url.Path - return nil -} - -// Cmp compares x and y and returns: -// -// -1 if x < y -// 0 if x == y -// +1 if x > y -func (u URL) Cmp(url URL) int { - if u.Scheme == url.Scheme { - return strings.Compare(u.Path, url.Path) - } - return strings.Compare(u.Scheme, url.Scheme) -} diff --git a/builder/accounts/url_test.go b/builder/accounts/url_test.go deleted file mode 100644 index f481a1016..000000000 --- a/builder/accounts/url_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2018 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 accounts - -import ( - "testing" -) - -func TestURLParsing(t *testing.T) { - t.Parallel() - url, err := parseURL("https://ethereum.org") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if url.Scheme != "https" { - t.Errorf("expected: %v, got: %v", "https", url.Scheme) - } - if url.Path != "ethereum.org" { - t.Errorf("expected: %v, got: %v", "ethereum.org", url.Path) - } - - for _, u := range []string{"ethereum.org", ""} { - if _, err = parseURL(u); err == nil { - t.Errorf("input %v, expected err, got: nil", u) - } - } -} - -func TestURLString(t *testing.T) { - t.Parallel() - url := URL{Scheme: "https", Path: "ethereum.org"} - if url.String() != "https://ethereum.org" { - t.Errorf("expected: %v, got: %v", "https://ethereum.org", url.String()) - } - - url = URL{Scheme: "", Path: "ethereum.org"} - if url.String() != "ethereum.org" { - t.Errorf("expected: %v, got: %v", "ethereum.org", url.String()) - } -} - -func TestURLMarshalJSON(t *testing.T) { - t.Parallel() - url := URL{Scheme: "https", Path: "ethereum.org"} - json, err := url.MarshalJSON() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if string(json) != "\"https://ethereum.org\"" { - t.Errorf("expected: %v, got: %v", "\"https://ethereum.org\"", string(json)) - } -} - -func TestURLUnmarshalJSON(t *testing.T) { - t.Parallel() - url := &URL{} - err := url.UnmarshalJSON([]byte("\"https://ethereum.org\"")) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if url.Scheme != "https" { - t.Errorf("expected: %v, got: %v", "https", url.Scheme) - } - if url.Path != "ethereum.org" { - t.Errorf("expected: %v, got: %v", "https", url.Path) - } -} - -func TestURLComparison(t *testing.T) { - t.Parallel() - tests := []struct { - urlA URL - urlB URL - expect int - }{ - {URL{"https", "ethereum.org"}, URL{"https", "ethereum.org"}, 0}, - {URL{"http", "ethereum.org"}, URL{"https", "ethereum.org"}, -1}, - {URL{"https", "ethereum.org/a"}, URL{"https", "ethereum.org"}, 1}, - {URL{"https", "abc.org"}, URL{"https", "ethereum.org"}, -1}, - } - - for i, tt := range tests { - result := tt.urlA.Cmp(tt.urlB) - if result != tt.expect { - t.Errorf("test %d: cmp mismatch: expected: %d, got: %d", i, tt.expect, result) - } - } -} diff --git a/builder/accounts/usbwallet/hub.go b/builder/accounts/usbwallet/hub.go deleted file mode 100644 index e67942dbc..000000000 --- a/builder/accounts/usbwallet/hub.go +++ /dev/null @@ -1,289 +0,0 @@ -// 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 usbwallet - -import ( - "errors" - "runtime" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/karalabe/usb" -) - -// LedgerScheme is the protocol scheme prefixing account and wallet URLs. -const LedgerScheme = "ledger" - -// TrezorScheme is the protocol scheme prefixing account and wallet URLs. -const TrezorScheme = "trezor" - -// refreshCycle is the maximum time between wallet refreshes (if USB hotplug -// notifications don't work). -const refreshCycle = time.Second - -// refreshThrottling is the minimum time between wallet refreshes to avoid USB -// trashing. -const refreshThrottling = 500 * time.Millisecond - -// Hub is a accounts.Backend that can find and handle generic USB hardware wallets. -type Hub struct { - scheme string // Protocol scheme prefixing account and wallet URLs. - vendorID uint16 // USB vendor identifier used for device discovery - productIDs []uint16 // USB product identifiers used for device discovery - usageID uint16 // USB usage page identifier used for macOS device discovery - endpointID int // USB endpoint identifier used for non-macOS device discovery - makeDriver func(log.Logger) driver // Factory method to construct a vendor specific driver - - refreshed time.Time // Time instance when the list of wallets was last refreshed - wallets []accounts.Wallet // List of USB wallet devices currently tracking - updateFeed event.Feed // Event feed to notify wallet additions/removals - updateScope event.SubscriptionScope // Subscription scope tracking current live listeners - updating bool // Whether the event notification loop is running - - quit chan chan error - - stateLock sync.RWMutex // Protects the internals of the hub from racey access - - // TODO(karalabe): remove if hotplug lands on Windows - commsPend int // Number of operations blocking enumeration - commsLock sync.Mutex // Lock protecting the pending counter and enumeration - enumFails atomic.Uint32 // Number of times enumeration has failed -} - -// NewLedgerHub creates a new hardware wallet manager for Ledger devices. -func NewLedgerHub() (*Hub, error) { - return newHub(LedgerScheme, 0x2c97, []uint16{ - - // Device definitions taken from - // https://github.com/LedgerHQ/ledger-live/blob/38012bc8899e0f07149ea9cfe7e64b2c146bc92b/libs/ledgerjs/packages/devices/src/index.ts - - // Original product IDs - 0x0000, /* Ledger Blue */ - 0x0001, /* Ledger Nano S */ - 0x0004, /* Ledger Nano X */ - 0x0005, /* Ledger Nano S Plus */ - 0x0006, /* Ledger Nano FTS */ - - 0x0015, /* HID + U2F + WebUSB Ledger Blue */ - 0x1015, /* HID + U2F + WebUSB Ledger Nano S */ - 0x4015, /* HID + U2F + WebUSB Ledger Nano X */ - 0x5015, /* HID + U2F + WebUSB Ledger Nano S Plus */ - 0x6015, /* HID + U2F + WebUSB Ledger Nano FTS */ - - 0x0011, /* HID + WebUSB Ledger Blue */ - 0x1011, /* HID + WebUSB Ledger Nano S */ - 0x4011, /* HID + WebUSB Ledger Nano X */ - 0x5011, /* HID + WebUSB Ledger Nano S Plus */ - 0x6011, /* HID + WebUSB Ledger Nano FTS */ - }, 0xffa0, 0, newLedgerDriver) -} - -// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices. -func NewTrezorHubWithHID() (*Hub, error) { - return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver) -} - -// NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with -// firmware version > 1.8.0 -func NewTrezorHubWithWebUSB() (*Hub, error) { - return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver) -} - -// newHub creates a new hardware wallet manager for generic USB devices. -func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) { - if !usb.Supported() { - return nil, errors.New("unsupported platform") - } - hub := &Hub{ - scheme: scheme, - vendorID: vendorID, - productIDs: productIDs, - usageID: usageID, - endpointID: endpointID, - makeDriver: makeDriver, - quit: make(chan chan error), - } - hub.refreshWallets() - return hub, nil -} - -// Wallets implements accounts.Backend, returning all the currently tracked USB -// devices that appear to be hardware wallets. -func (hub *Hub) Wallets() []accounts.Wallet { - // Make sure the list of wallets is up to date - hub.refreshWallets() - - hub.stateLock.RLock() - defer hub.stateLock.RUnlock() - - cpy := make([]accounts.Wallet, len(hub.wallets)) - copy(cpy, hub.wallets) - return cpy -} - -// refreshWallets scans the USB devices attached to the machine and updates the -// list of wallets based on the found devices. -func (hub *Hub) refreshWallets() { - // Don't scan the USB like crazy it the user fetches wallets in a loop - hub.stateLock.RLock() - elapsed := time.Since(hub.refreshed) - hub.stateLock.RUnlock() - - if elapsed < refreshThrottling { - return - } - // If USB enumeration is continually failing, don't keep trying indefinitely - if hub.enumFails.Load() > 2 { - return - } - // Retrieve the current list of USB wallet devices - var devices []usb.DeviceInfo - - if runtime.GOOS == "linux" { - // hidapi on Linux opens the device during enumeration to retrieve some infos, - // breaking the Ledger protocol if that is waiting for user confirmation. This - // is a bug acknowledged at Ledger, but it won't be fixed on old devices so we - // need to prevent concurrent comms ourselves. The more elegant solution would - // be to ditch enumeration in favor of hotplug events, but that don't work yet - // on Windows so if we need to hack it anyway, this is more elegant for now. - hub.commsLock.Lock() - if hub.commsPend > 0 { // A confirmation is pending, don't refresh - hub.commsLock.Unlock() - return - } - } - infos, err := usb.Enumerate(hub.vendorID, 0) - if err != nil { - failcount := hub.enumFails.Add(1) - if runtime.GOOS == "linux" { - // See rationale before the enumeration why this is needed and only on Linux. - hub.commsLock.Unlock() - } - log.Error("Failed to enumerate USB devices", "hub", hub.scheme, - "vendor", hub.vendorID, "failcount", failcount, "err", err) - return - } - hub.enumFails.Store(0) - - for _, info := range infos { - for _, id := range hub.productIDs { - // Windows and Macos use UsageID matching, Linux uses Interface matching - if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) { - devices = append(devices, info) - break - } - } - } - if runtime.GOOS == "linux" { - // See rationale before the enumeration why this is needed and only on Linux. - hub.commsLock.Unlock() - } - // Transform the current list of wallets into the new one - hub.stateLock.Lock() - - var ( - wallets = make([]accounts.Wallet, 0, len(devices)) - events []accounts.WalletEvent - ) - - for _, device := range devices { - url := accounts.URL{Scheme: hub.scheme, Path: device.Path} - - // Drop wallets in front of the next device or those that failed for some reason - for len(hub.wallets) > 0 { - // Abort if we're past the current device and found an operational one - _, failure := hub.wallets[0].Status() - if hub.wallets[0].URL().Cmp(url) >= 0 || failure == nil { - break - } - // Drop the stale and failed devices - events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped}) - hub.wallets = hub.wallets[1:] - } - // If there are no more wallets or the device is before the next, wrap new wallet - if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 { - logger := log.New("url", url) - wallet := &wallet{hub: hub, driver: hub.makeDriver(logger), url: &url, info: device, log: logger} - - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived}) - wallets = append(wallets, wallet) - continue - } - // If the device is the same as the first wallet, keep it - if hub.wallets[0].URL().Cmp(url) == 0 { - wallets = append(wallets, hub.wallets[0]) - hub.wallets = hub.wallets[1:] - continue - } - } - // Drop any leftover wallets and set the new batch - for _, wallet := range hub.wallets { - events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped}) - } - hub.refreshed = time.Now() - hub.wallets = wallets - hub.stateLock.Unlock() - - // Fire all wallet events and return - for _, event := range events { - hub.updateFeed.Send(event) - } -} - -// Subscribe implements accounts.Backend, creating an async subscription to -// receive notifications on the addition or removal of USB wallets. -func (hub *Hub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription { - // We need the mutex to reliably start/stop the update loop - hub.stateLock.Lock() - defer hub.stateLock.Unlock() - - // Subscribe the caller and track the subscriber count - sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink)) - - // Subscribers require an active notification loop, start it - if !hub.updating { - hub.updating = true - go hub.updater() - } - return sub -} - -// updater is responsible for maintaining an up-to-date list of wallets managed -// by the USB hub, and for firing wallet addition/removal events. -func (hub *Hub) updater() { - for { - // TODO: Wait for a USB hotplug event (not supported yet) or a refresh timeout - // <-hub.changes - time.Sleep(refreshCycle) - - // Run the wallet refresher - hub.refreshWallets() - - // If all our subscribers left, stop the updater - hub.stateLock.Lock() - if hub.updateScope.Count() == 0 { - hub.updating = false - hub.stateLock.Unlock() - return - } - hub.stateLock.Unlock() - } -} diff --git a/builder/accounts/usbwallet/ledger.go b/builder/accounts/usbwallet/ledger.go deleted file mode 100644 index d0cb93e74..000000000 --- a/builder/accounts/usbwallet/ledger.go +++ /dev/null @@ -1,554 +0,0 @@ -// 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 . - -// This file contains the implementation for interacting with the Ledger hardware -// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo: -// https://raw.githubusercontent.com/LedgerHQ/blue-app-eth/master/doc/ethapp.asc - -package usbwallet - -import ( - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// ledgerOpcode is an enumeration encoding the supported Ledger opcodes. -type ledgerOpcode byte - -// ledgerParam1 is an enumeration encoding the supported Ledger parameters for -// specific opcodes. The same parameter values may be reused between opcodes. -type ledgerParam1 byte - -// ledgerParam2 is an enumeration encoding the supported Ledger parameters for -// specific opcodes. The same parameter values may be reused between opcodes. -type ledgerParam2 byte - -const ( - ledgerOpRetrieveAddress ledgerOpcode = 0x02 // Returns the public key and Ethereum address for a given BIP 32 path - ledgerOpSignTransaction ledgerOpcode = 0x04 // Signs an Ethereum transaction after having the user validate the parameters - ledgerOpGetConfiguration ledgerOpcode = 0x06 // Returns specific wallet application configuration - ledgerOpSignTypedMessage ledgerOpcode = 0x0c // Signs an Ethereum message following the EIP 712 specification - - ledgerP1DirectlyFetchAddress ledgerParam1 = 0x00 // Return address directly from the wallet - ledgerP1InitTypedMessageData ledgerParam1 = 0x00 // First chunk of Typed Message data - ledgerP1InitTransactionData ledgerParam1 = 0x00 // First transaction data block for signing - ledgerP1ContTransactionData ledgerParam1 = 0x80 // Subsequent transaction data block for signing - ledgerP2DiscardAddressChainCode ledgerParam2 = 0x00 // Do not return the chain code along with the address - - ledgerEip155Size int = 3 // Size of the EIP-155 chain_id,r,s in unsigned transactions -) - -// errLedgerReplyInvalidHeader is the error message returned by a Ledger data exchange -// if the device replies with a mismatching header. This usually means the device -// is in browser mode. -var errLedgerReplyInvalidHeader = errors.New("ledger: invalid reply header") - -// errLedgerInvalidVersionReply is the error message returned by a Ledger version retrieval -// when a response does arrive, but it does not contain the expected data. -var errLedgerInvalidVersionReply = errors.New("ledger: invalid version reply") - -// ledgerDriver implements the communication with a Ledger hardware wallet. -type ledgerDriver struct { - device io.ReadWriter // USB device connection to communicate through - version [3]byte // Current version of the Ledger firmware (zero if app is offline) - browser bool // Flag whether the Ledger is in browser mode (reply channel mismatch) - failure error // Any failure that would make the device unusable - log log.Logger // Contextual logger to tag the ledger with its id -} - -// newLedgerDriver creates a new instance of a Ledger USB protocol driver. -func newLedgerDriver(logger log.Logger) driver { - return &ledgerDriver{ - log: logger, - } -} - -// Status implements usbwallet.driver, returning various states the Ledger can -// currently be in. -func (w *ledgerDriver) Status() (string, error) { - if w.failure != nil { - return fmt.Sprintf("Failed: %v", w.failure), w.failure - } - if w.browser { - return "Ethereum app in browser mode", w.failure - } - if w.offline() { - return "Ethereum app offline", w.failure - } - return fmt.Sprintf("Ethereum app v%d.%d.%d online", w.version[0], w.version[1], w.version[2]), w.failure -} - -// offline returns whether the wallet and the Ethereum app is offline or not. -// -// The method assumes that the state lock is held! -func (w *ledgerDriver) offline() bool { - return w.version == [3]byte{0, 0, 0} -} - -// Open implements usbwallet.driver, attempting to initialize the connection to the -// Ledger hardware wallet. The Ledger does not require a user passphrase, so that -// parameter is silently discarded. -func (w *ledgerDriver) Open(device io.ReadWriter, passphrase string) error { - w.device, w.failure = device, nil - - _, err := w.ledgerDerive(accounts.DefaultBaseDerivationPath) - if err != nil { - // Ethereum app is not running or in browser mode, nothing more to do, return - if err == errLedgerReplyInvalidHeader { - w.browser = true - } - return nil - } - // Try to resolve the Ethereum app's version, will fail prior to v1.0.2 - if w.version, err = w.ledgerVersion(); err != nil { - w.version = [3]byte{1, 0, 0} // Assume worst case, can't verify if v1.0.0 or v1.0.1 - } - return nil -} - -// Close implements usbwallet.driver, cleaning up and metadata maintained within -// the Ledger driver. -func (w *ledgerDriver) Close() error { - w.browser, w.version = false, [3]byte{} - return nil -} - -// Heartbeat implements usbwallet.driver, performing a sanity check against the -// Ledger to see if it's still online. -func (w *ledgerDriver) Heartbeat() error { - if _, err := w.ledgerVersion(); err != nil && err != errLedgerInvalidVersionReply { - w.failure = err - return err - } - return nil -} - -// Derive implements usbwallet.driver, sending a derivation request to the Ledger -// and returning the Ethereum address located on that derivation path. -func (w *ledgerDriver) Derive(path accounts.DerivationPath) (common.Address, error) { - return w.ledgerDerive(path) -} - -// SignTx implements usbwallet.driver, sending the transaction to the Ledger and -// waiting for the user to confirm or deny the transaction. -// -// Note, if the version of the Ethereum application running on the Ledger wallet is -// too old to sign EIP-155 transactions, but such is requested nonetheless, an error -// will be returned opposed to silently signing in Homestead mode. -func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { - // If the Ethereum app doesn't run, abort - if w.offline() { - return common.Address{}, nil, accounts.ErrWalletClosed - } - // Ensure the wallet is capable of signing the given transaction - if chainID != nil && w.version[0] <= 1 && w.version[1] <= 0 && w.version[2] <= 2 { - //lint:ignore ST1005 brand name displayed on the console - return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) - } - // All infos gathered and metadata checks out, request signing - return w.ledgerSign(path, tx, chainID) -} - -// SignTypedMessage implements usbwallet.driver, sending the message to the Ledger and -// waiting for the user to sign or deny the transaction. -// -// Note: this was introduced in the ledger 1.5.0 firmware -func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) { - // If the Ethereum app doesn't run, abort - if w.offline() { - return nil, accounts.ErrWalletClosed - } - // Ensure the wallet is capable of signing the given transaction - if w.version[0] < 1 && w.version[1] < 5 { - //lint:ignore ST1005 brand name displayed on the console - return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) - } - // All infos gathered and metadata checks out, request signing - return w.ledgerSignTypedMessage(path, domainHash, messageHash) -} - -// ledgerVersion retrieves the current version of the Ethereum wallet app running -// on the Ledger wallet. -// -// The version retrieval protocol is defined as follows: -// -// CLA | INS | P1 | P2 | Lc | Le -// ----+-----+----+----+----+--- -// E0 | 06 | 00 | 00 | 00 | 04 -// -// With no input data, and the output data being: -// -// Description | Length -// ---------------------------------------------------+-------- -// Flags 01: arbitrary data signature enabled by user | 1 byte -// Application major version | 1 byte -// Application minor version | 1 byte -// Application patch version | 1 byte -func (w *ledgerDriver) ledgerVersion() ([3]byte, error) { - // Send the request and wait for the response - reply, err := w.ledgerExchange(ledgerOpGetConfiguration, 0, 0, nil) - if err != nil { - return [3]byte{}, err - } - if len(reply) != 4 { - return [3]byte{}, errLedgerInvalidVersionReply - } - // Cache the version for future reference - var version [3]byte - copy(version[:], reply[1:]) - return version, nil -} - -// ledgerDerive retrieves the currently active Ethereum address from a Ledger -// wallet at the specified derivation path. -// -// The address derivation protocol is defined as follows: -// -// CLA | INS | P1 | P2 | Lc | Le -// ----+-----+----+----+-----+--- -// E0 | 02 | 00 return address -// 01 display address and confirm before returning -// | 00: do not return the chain code -// | 01: return the chain code -// | var | 00 -// -// Where the input data is: -// -// Description | Length -// -------------------------------------------------+-------- -// Number of BIP 32 derivations to perform (max 10) | 1 byte -// First derivation index (big endian) | 4 bytes -// ... | 4 bytes -// Last derivation index (big endian) | 4 bytes -// -// And the output data is: -// -// Description | Length -// ------------------------+------------------- -// Public Key length | 1 byte -// Uncompressed Public Key | arbitrary -// Ethereum address length | 1 byte -// Ethereum address | 40 bytes hex ascii -// Chain code if requested | 32 bytes -func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, error) { - // Flatten the derivation path into the Ledger request - path := make([]byte, 1+4*len(derivationPath)) - path[0] = byte(len(derivationPath)) - for i, component := range derivationPath { - binary.BigEndian.PutUint32(path[1+4*i:], component) - } - // Send the request and wait for the response - reply, err := w.ledgerExchange(ledgerOpRetrieveAddress, ledgerP1DirectlyFetchAddress, ledgerP2DiscardAddressChainCode, path) - if err != nil { - return common.Address{}, err - } - // Discard the public key, we don't need that for now - if len(reply) < 1 || len(reply) < 1+int(reply[0]) { - return common.Address{}, errors.New("reply lacks public key entry") - } - reply = reply[1+int(reply[0]):] - - // Extract the Ethereum hex address string - if len(reply) < 1 || len(reply) < 1+int(reply[0]) { - return common.Address{}, errors.New("reply lacks address entry") - } - hexstr := reply[1 : 1+int(reply[0])] - - // Decode the hex string into an Ethereum address and return - var address common.Address - if _, err = hex.Decode(address[:], hexstr); err != nil { - return common.Address{}, err - } - return address, nil -} - -// ledgerSign sends the transaction to the Ledger wallet, and waits for the user -// to confirm or deny the transaction. -// -// The transaction signing protocol is defined as follows: -// -// CLA | INS | P1 | P2 | Lc | Le -// ----+-----+----+----+-----+--- -// E0 | 04 | 00: first transaction data block -// 80: subsequent transaction data block -// | 00 | variable | variable -// -// Where the input for the first transaction block (first 255 bytes) is: -// -// Description | Length -// -------------------------------------------------+---------- -// Number of BIP 32 derivations to perform (max 10) | 1 byte -// First derivation index (big endian) | 4 bytes -// ... | 4 bytes -// Last derivation index (big endian) | 4 bytes -// RLP transaction chunk | arbitrary -// -// And the input for subsequent transaction blocks (first 255 bytes) are: -// -// Description | Length -// ----------------------+---------- -// RLP transaction chunk | arbitrary -// -// And the output data is: -// -// Description | Length -// ------------+--------- -// signature V | 1 byte -// signature R | 32 bytes -// signature S | 32 bytes -func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { - // Flatten the derivation path into the Ledger request - path := make([]byte, 1+4*len(derivationPath)) - path[0] = byte(len(derivationPath)) - for i, component := range derivationPath { - binary.BigEndian.PutUint32(path[1+4*i:], component) - } - // Create the transaction RLP based on whether legacy or EIP155 signing was requested - var ( - txrlp []byte - err error - ) - if chainID == nil { - if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil { - return common.Address{}, nil, err - } - } else { - if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil { - return common.Address{}, nil, err - } - } - payload := append(path, txrlp...) - - // Send the request and wait for the response - var ( - op = ledgerP1InitTransactionData - reply []byte - ) - - // Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app. - // https://github.com/LedgerHQ/app-ethereum/issues/409 - chunk := 255 - for ; len(payload)%chunk <= ledgerEip155Size; chunk-- { - } - - for len(payload) > 0 { - // Calculate the size of the next data chunk - if chunk > len(payload) { - chunk = len(payload) - } - // Send the chunk over, ensuring it's processed correctly - reply, err = w.ledgerExchange(ledgerOpSignTransaction, op, 0, payload[:chunk]) - if err != nil { - return common.Address{}, nil, err - } - // Shift the payload and ensure subsequent chunks are marked as such - payload = payload[chunk:] - op = ledgerP1ContTransactionData - } - // Extract the Ethereum signature and do a sanity validation - if len(reply) != crypto.SignatureLength { - return common.Address{}, nil, errors.New("reply lacks signature") - } - signature := append(reply[1:], reply[0]) - - // Create the correct signer and signature transform based on the chain ID - var signer types.Signer - if chainID == nil { - signer = new(types.HomesteadSigner) - } else { - signer = types.NewEIP155Signer(chainID) - signature[64] -= byte(chainID.Uint64()*2 + 35) - } - signed, err := tx.WithSignature(signer, signature) - if err != nil { - return common.Address{}, nil, err - } - sender, err := types.Sender(signer, signed) - if err != nil { - return common.Address{}, nil, err - } - return sender, signed, nil -} - -// ledgerSignTypedMessage sends the transaction to the Ledger wallet, and waits for the user -// to confirm or deny the transaction. -// -// The signing protocol is defined as follows: -// -// CLA | INS | P1 | P2 | Lc | Le -// ----+-----+----+-----------------------------+-----+--- -// E0 | 0C | 00 | implementation version : 00 | variable | variable -// -// Where the input is: -// -// Description | Length -// -------------------------------------------------+---------- -// Number of BIP 32 derivations to perform (max 10) | 1 byte -// First derivation index (big endian) | 4 bytes -// ... | 4 bytes -// Last derivation index (big endian) | 4 bytes -// domain hash | 32 bytes -// message hash | 32 bytes -// -// And the output data is: -// -// Description | Length -// ------------+--------- -// signature V | 1 byte -// signature R | 32 bytes -// signature S | 32 bytes -func (w *ledgerDriver) ledgerSignTypedMessage(derivationPath []uint32, domainHash []byte, messageHash []byte) ([]byte, error) { - // Flatten the derivation path into the Ledger request - path := make([]byte, 1+4*len(derivationPath)) - path[0] = byte(len(derivationPath)) - for i, component := range derivationPath { - binary.BigEndian.PutUint32(path[1+4*i:], component) - } - // Create the 712 message - payload := append(path, domainHash...) - payload = append(payload, messageHash...) - - // Send the request and wait for the response - var ( - op = ledgerP1InitTypedMessageData - reply []byte - err error - ) - - // Send the message over, ensuring it's processed correctly - reply, err = w.ledgerExchange(ledgerOpSignTypedMessage, op, 0, payload) - - if err != nil { - return nil, err - } - - // Extract the Ethereum signature and do a sanity validation - if len(reply) != crypto.SignatureLength { - return nil, errors.New("reply lacks signature") - } - signature := append(reply[1:], reply[0]) - return signature, nil -} - -// ledgerExchange performs a data exchange with the Ledger wallet, sending it a -// message and retrieving the response. -// -// The common transport header is defined as follows: -// -// Description | Length -// --------------------------------------+---------- -// Communication channel ID (big endian) | 2 bytes -// Command tag | 1 byte -// Packet sequence index (big endian) | 2 bytes -// Payload | arbitrary -// -// The Communication channel ID allows commands multiplexing over the same -// physical link. It is not used for the time being, and should be set to 0101 -// to avoid compatibility issues with implementations ignoring a leading 00 byte. -// -// The Command tag describes the message content. Use TAG_APDU (0x05) for standard -// APDU payloads, or TAG_PING (0x02) for a simple link test. -// -// The Packet sequence index describes the current sequence for fragmented payloads. -// The first fragment index is 0x00. -// -// APDU Command payloads are encoded as follows: -// -// Description | Length -// ----------------------------------- -// APDU length (big endian) | 2 bytes -// APDU CLA | 1 byte -// APDU INS | 1 byte -// APDU P1 | 1 byte -// APDU P2 | 1 byte -// APDU length | 1 byte -// Optional APDU data | arbitrary -func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 ledgerParam2, data []byte) ([]byte, error) { - // Construct the message payload, possibly split into multiple chunks - apdu := make([]byte, 2, 7+len(data)) - - binary.BigEndian.PutUint16(apdu, uint16(5+len(data))) - apdu = append(apdu, []byte{0xe0, byte(opcode), byte(p1), byte(p2), byte(len(data))}...) - apdu = append(apdu, data...) - - // Stream all the chunks to the device - header := []byte{0x01, 0x01, 0x05, 0x00, 0x00} // Channel ID and command tag appended - chunk := make([]byte, 64) - space := len(chunk) - len(header) - - for i := 0; len(apdu) > 0; i++ { - // Construct the new message to stream - chunk = append(chunk[:0], header...) - binary.BigEndian.PutUint16(chunk[3:], uint16(i)) - - if len(apdu) > space { - chunk = append(chunk, apdu[:space]...) - apdu = apdu[space:] - } else { - chunk = append(chunk, apdu...) - apdu = nil - } - // Send over to the device - w.log.Trace("Data chunk sent to the Ledger", "chunk", hexutil.Bytes(chunk)) - if _, err := w.device.Write(chunk); err != nil { - return nil, err - } - } - // Stream the reply back from the wallet in 64 byte chunks - var reply []byte - chunk = chunk[:64] // Yeah, we surely have enough space - for { - // Read the next chunk from the Ledger wallet - if _, err := io.ReadFull(w.device, chunk); err != nil { - return nil, err - } - w.log.Trace("Data chunk received from the Ledger", "chunk", hexutil.Bytes(chunk)) - - // Make sure the transport header matches - if chunk[0] != 0x01 || chunk[1] != 0x01 || chunk[2] != 0x05 { - return nil, errLedgerReplyInvalidHeader - } - // If it's the first chunk, retrieve the total message length - var payload []byte - - if chunk[3] == 0x00 && chunk[4] == 0x00 { - reply = make([]byte, 0, int(binary.BigEndian.Uint16(chunk[5:7]))) - payload = chunk[7:] - } else { - payload = chunk[5:] - } - // Append to the reply and stop when filled up - if left := cap(reply) - len(reply); left > len(payload) { - reply = append(reply, payload...) - } else { - reply = append(reply, payload[:left]...) - break - } - } - return reply[:len(reply)-2], nil -} diff --git a/builder/accounts/usbwallet/trezor.go b/builder/accounts/usbwallet/trezor.go deleted file mode 100644 index 9644dc4e0..000000000 --- a/builder/accounts/usbwallet/trezor.go +++ /dev/null @@ -1,371 +0,0 @@ -// 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 . - -// This file contains the implementation for interacting with the Trezor hardware -// wallets. The wire protocol spec can be found on the SatoshiLabs website: -// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html - -package usbwallet - -import ( - "encoding/binary" - "errors" - "fmt" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/usbwallet/trezor" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/golang/protobuf/proto" -) - -// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In -// this case, the calling application should display a pinpad and send back the -// encoded passphrase. -var ErrTrezorPINNeeded = errors.New("trezor: pin needed") - -// ErrTrezorPassphraseNeeded is returned if opening the trezor requires a passphrase -var ErrTrezorPassphraseNeeded = errors.New("trezor: passphrase needed") - -// errTrezorReplyInvalidHeader is the error message returned by a Trezor data exchange -// if the device replies with a mismatching header. This usually means the device -// is in browser mode. -var errTrezorReplyInvalidHeader = errors.New("trezor: invalid reply header") - -// trezorDriver implements the communication with a Trezor hardware wallet. -type trezorDriver struct { - device io.ReadWriter // USB device connection to communicate through - version [3]uint32 // Current version of the Trezor firmware - label string // Current textual label of the Trezor device - pinwait bool // Flags whether the device is waiting for PIN entry - passphrasewait bool // Flags whether the device is waiting for passphrase entry - failure error // Any failure that would make the device unusable - log log.Logger // Contextual logger to tag the trezor with its id -} - -// newTrezorDriver creates a new instance of a Trezor USB protocol driver. -func newTrezorDriver(logger log.Logger) driver { - return &trezorDriver{ - log: logger, - } -} - -// Status implements accounts.Wallet, always whether the Trezor is opened, closed -// or whether the Ethereum app was not started on it. -func (w *trezorDriver) Status() (string, error) { - if w.failure != nil { - return fmt.Sprintf("Failed: %v", w.failure), w.failure - } - if w.device == nil { - return "Closed", w.failure - } - if w.pinwait { - return fmt.Sprintf("Trezor v%d.%d.%d '%s' waiting for PIN", w.version[0], w.version[1], w.version[2], w.label), w.failure - } - return fmt.Sprintf("Trezor v%d.%d.%d '%s' online", w.version[0], w.version[1], w.version[2], w.label), w.failure -} - -// Open implements usbwallet.driver, attempting to initialize the connection to -// the Trezor hardware wallet. Initializing the Trezor is a two or three phase operation: -// - The first phase is to initialize the connection and read the wallet's -// features. This phase is invoked if the provided passphrase is empty. The -// device will display the pinpad as a result and will return an appropriate -// error to notify the user that a second open phase is needed. -// - The second phase is to unlock access to the Trezor, which is done by the -// user actually providing a passphrase mapping a keyboard keypad to the pin -// number of the user (shuffled according to the pinpad displayed). -// - If needed the device will ask for passphrase which will require calling -// open again with the actual passphrase (3rd phase) -func (w *trezorDriver) Open(device io.ReadWriter, passphrase string) error { - w.device, w.failure = device, nil - - // If phase 1 is requested, init the connection and wait for user callback - if passphrase == "" && !w.passphrasewait { - // If we're already waiting for a PIN entry, insta-return - if w.pinwait { - return ErrTrezorPINNeeded - } - // Initialize a connection to the device - features := new(trezor.Features) - if _, err := w.trezorExchange(&trezor.Initialize{}, features); err != nil { - return err - } - w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()} - w.label = features.GetLabel() - - // Do a manual ping, forcing the device to ask for its PIN and Passphrase - askPin := true - askPassphrase := true - res, err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin, PassphraseProtection: &askPassphrase}, new(trezor.PinMatrixRequest), new(trezor.PassphraseRequest), new(trezor.Success)) - if err != nil { - return err - } - // Only return the PIN request if the device wasn't unlocked until now - switch res { - case 0: - w.pinwait = true - return ErrTrezorPINNeeded - case 1: - w.pinwait = false - w.passphrasewait = true - return ErrTrezorPassphraseNeeded - case 2: - return nil // responded with trezor.Success - } - } - // Phase 2 requested with actual PIN entry - if w.pinwait { - w.pinwait = false - res, err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, new(trezor.Success), new(trezor.PassphraseRequest)) - if err != nil { - w.failure = err - return err - } - if res == 1 { - w.passphrasewait = true - return ErrTrezorPassphraseNeeded - } - } else if w.passphrasewait { - w.passphrasewait = false - if _, err := w.trezorExchange(&trezor.PassphraseAck{Passphrase: &passphrase}, new(trezor.Success)); err != nil { - w.failure = err - return err - } - } - - return nil -} - -// Close implements usbwallet.driver, cleaning up and metadata maintained within -// the Trezor driver. -func (w *trezorDriver) Close() error { - w.version, w.label, w.pinwait = [3]uint32{}, "", false - return nil -} - -// Heartbeat implements usbwallet.driver, performing a sanity check against the -// Trezor to see if it's still online. -func (w *trezorDriver) Heartbeat() error { - if _, err := w.trezorExchange(&trezor.Ping{}, new(trezor.Success)); err != nil { - w.failure = err - return err - } - return nil -} - -// Derive implements usbwallet.driver, sending a derivation request to the Trezor -// and returning the Ethereum address located on that derivation path. -func (w *trezorDriver) Derive(path accounts.DerivationPath) (common.Address, error) { - return w.trezorDerive(path) -} - -// SignTx implements usbwallet.driver, sending the transaction to the Trezor and -// waiting for the user to confirm or deny the transaction. -func (w *trezorDriver) SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { - if w.device == nil { - return common.Address{}, nil, accounts.ErrWalletClosed - } - return w.trezorSign(path, tx, chainID) -} - -func (w *trezorDriver) SignTypedMessage(path accounts.DerivationPath, domainHash []byte, messageHash []byte) ([]byte, error) { - return nil, accounts.ErrNotSupported -} - -// trezorDerive sends a derivation request to the Trezor device and returns the -// Ethereum address located on that path. -func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, error) { - address := new(trezor.EthereumAddress) - if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil { - return common.Address{}, err - } - if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary formats - return common.BytesToAddress(addr), nil - } - if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal formats - return common.HexToAddress(addr), nil - } - return common.Address{}, errors.New("missing derived address") -} - -// trezorSign sends the transaction to the Trezor wallet, and waits for the user -// to confirm or deny the transaction. -func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) { - // Create the transaction initiation message - data := tx.Data() - length := uint32(len(data)) - - request := &trezor.EthereumSignTx{ - AddressN: derivationPath, - Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(), - GasPrice: tx.GasPrice().Bytes(), - GasLimit: new(big.Int).SetUint64(tx.Gas()).Bytes(), - Value: tx.Value().Bytes(), - DataLength: &length, - } - if to := tx.To(); to != nil { - // Non contract deploy, set recipient explicitly - hex := to.Hex() - request.ToHex = &hex // Newer firmwares (old will ignore) - request.ToBin = (*to)[:] // Older firmwares (new will ignore) - } - if length > 1024 { // Send the data chunked if that was requested - request.DataInitialChunk, data = data[:1024], data[1024:] - } else { - request.DataInitialChunk, data = data, nil - } - if chainID != nil { // EIP-155 transaction, set chain ID explicitly (only 32 bit is supported!?) - id := uint32(chainID.Int64()) - request.ChainId = &id - } - // Send the initiation message and stream content until a signature is returned - response := new(trezor.EthereumTxRequest) - if _, err := w.trezorExchange(request, response); err != nil { - return common.Address{}, nil, err - } - for response.DataLength != nil && int(*response.DataLength) <= len(data) { - chunk := data[:*response.DataLength] - data = data[*response.DataLength:] - - if _, err := w.trezorExchange(&trezor.EthereumTxAck{DataChunk: chunk}, response); err != nil { - return common.Address{}, nil, err - } - } - // Extract the Ethereum signature and do a sanity validation - if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 || response.GetSignatureV() == 0 { - return common.Address{}, nil, errors.New("reply lacks signature") - } - signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV())) - - // Create the correct signer and signature transform based on the chain ID - var signer types.Signer - if chainID == nil { - signer = new(types.HomesteadSigner) - } else { - // Trezor backend does not support typed transactions yet. - signer = types.NewEIP155Signer(chainID) - signature[64] -= byte(chainID.Uint64()*2 + 35) - } - - // Inject the final signature into the transaction and sanity check the sender - signed, err := tx.WithSignature(signer, signature) - if err != nil { - return common.Address{}, nil, err - } - sender, err := types.Sender(signer, signed) - if err != nil { - return common.Address{}, nil, err - } - return sender, signed, nil -} - -// trezorExchange performs a data exchange with the Trezor wallet, sending it a -// message and retrieving the response. If multiple responses are possible, the -// method will also return the index of the destination object used. -func (w *trezorDriver) trezorExchange(req proto.Message, results ...proto.Message) (int, error) { - // Construct the original message payload to chunk up - data, err := proto.Marshal(req) - if err != nil { - return 0, err - } - payload := make([]byte, 8+len(data)) - copy(payload, []byte{0x23, 0x23}) - binary.BigEndian.PutUint16(payload[2:], trezor.Type(req)) - binary.BigEndian.PutUint32(payload[4:], uint32(len(data))) - copy(payload[8:], data) - - // Stream all the chunks to the device - chunk := make([]byte, 64) - chunk[0] = 0x3f // Report ID magic number - - for len(payload) > 0 { - // Construct the new message to stream, padding with zeroes if needed - if len(payload) > 63 { - copy(chunk[1:], payload[:63]) - payload = payload[63:] - } else { - copy(chunk[1:], payload) - copy(chunk[1+len(payload):], make([]byte, 63-len(payload))) - payload = nil - } - // Send over to the device - w.log.Trace("Data chunk sent to the Trezor", "chunk", hexutil.Bytes(chunk)) - if _, err := w.device.Write(chunk); err != nil { - return 0, err - } - } - // Stream the reply back from the wallet in 64 byte chunks - var ( - kind uint16 - reply []byte - ) - for { - // Read the next chunk from the Trezor wallet - if _, err := io.ReadFull(w.device, chunk); err != nil { - return 0, err - } - w.log.Trace("Data chunk received from the Trezor", "chunk", hexutil.Bytes(chunk)) - - // Make sure the transport header matches - if chunk[0] != 0x3f || (len(reply) == 0 && (chunk[1] != 0x23 || chunk[2] != 0x23)) { - return 0, errTrezorReplyInvalidHeader - } - // If it's the first chunk, retrieve the reply message type and total message length - var payload []byte - - if len(reply) == 0 { - kind = binary.BigEndian.Uint16(chunk[3:5]) - reply = make([]byte, 0, int(binary.BigEndian.Uint32(chunk[5:9]))) - payload = chunk[9:] - } else { - payload = chunk[1:] - } - // Append to the reply and stop when filled up - if left := cap(reply) - len(reply); left > len(payload) { - reply = append(reply, payload...) - } else { - reply = append(reply, payload[:left]...) - break - } - } - // Try to parse the reply into the requested reply message - if kind == uint16(trezor.MessageType_MessageType_Failure) { - // Trezor returned a failure, extract and return the message - failure := new(trezor.Failure) - if err := proto.Unmarshal(reply, failure); err != nil { - return 0, err - } - return 0, errors.New("trezor: " + failure.GetMessage()) - } - if kind == uint16(trezor.MessageType_MessageType_ButtonRequest) { - // Trezor is waiting for user confirmation, ack and wait for the next message - return w.trezorExchange(&trezor.ButtonAck{}, results...) - } - for i, res := range results { - if trezor.Type(res) == kind { - return i, proto.Unmarshal(reply, res) - } - } - expected := make([]string, len(results)) - for i, res := range results { - expected[i] = trezor.Name(trezor.Type(res)) - } - return 0, fmt.Errorf("trezor: expected reply types %s, got %s", expected, trezor.Name(kind)) -} diff --git a/builder/accounts/usbwallet/trezor/messages-common.pb.go b/builder/accounts/usbwallet/trezor/messages-common.pb.go deleted file mode 100644 index b396c6d8b..000000000 --- a/builder/accounts/usbwallet/trezor/messages-common.pb.go +++ /dev/null @@ -1,811 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: messages-common.proto - -package trezor - -import ( - fmt "fmt" - math "math" - - proto "github.com/golang/protobuf/proto" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type Failure_FailureType int32 - -const ( - Failure_Failure_UnexpectedMessage Failure_FailureType = 1 - Failure_Failure_ButtonExpected Failure_FailureType = 2 - Failure_Failure_DataError Failure_FailureType = 3 - Failure_Failure_ActionCancelled Failure_FailureType = 4 - Failure_Failure_PinExpected Failure_FailureType = 5 - Failure_Failure_PinCancelled Failure_FailureType = 6 - Failure_Failure_PinInvalid Failure_FailureType = 7 - Failure_Failure_InvalidSignature Failure_FailureType = 8 - Failure_Failure_ProcessError Failure_FailureType = 9 - Failure_Failure_NotEnoughFunds Failure_FailureType = 10 - Failure_Failure_NotInitialized Failure_FailureType = 11 - Failure_Failure_PinMismatch Failure_FailureType = 12 - Failure_Failure_FirmwareError Failure_FailureType = 99 -) - -var Failure_FailureType_name = map[int32]string{ - 1: "Failure_UnexpectedMessage", - 2: "Failure_ButtonExpected", - 3: "Failure_DataError", - 4: "Failure_ActionCancelled", - 5: "Failure_PinExpected", - 6: "Failure_PinCancelled", - 7: "Failure_PinInvalid", - 8: "Failure_InvalidSignature", - 9: "Failure_ProcessError", - 10: "Failure_NotEnoughFunds", - 11: "Failure_NotInitialized", - 12: "Failure_PinMismatch", - 99: "Failure_FirmwareError", -} - -var Failure_FailureType_value = map[string]int32{ - "Failure_UnexpectedMessage": 1, - "Failure_ButtonExpected": 2, - "Failure_DataError": 3, - "Failure_ActionCancelled": 4, - "Failure_PinExpected": 5, - "Failure_PinCancelled": 6, - "Failure_PinInvalid": 7, - "Failure_InvalidSignature": 8, - "Failure_ProcessError": 9, - "Failure_NotEnoughFunds": 10, - "Failure_NotInitialized": 11, - "Failure_PinMismatch": 12, - "Failure_FirmwareError": 99, -} - -func (x Failure_FailureType) Enum() *Failure_FailureType { - p := new(Failure_FailureType) - *p = x - return p -} - -func (x Failure_FailureType) String() string { - return proto.EnumName(Failure_FailureType_name, int32(x)) -} - -func (x *Failure_FailureType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Failure_FailureType_value, data, "Failure_FailureType") - if err != nil { - return err - } - *x = Failure_FailureType(value) - return nil -} - -func (Failure_FailureType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{1, 0} -} - -// * -// Type of button request -type ButtonRequest_ButtonRequestType int32 - -const ( - ButtonRequest_ButtonRequest_Other ButtonRequest_ButtonRequestType = 1 - ButtonRequest_ButtonRequest_FeeOverThreshold ButtonRequest_ButtonRequestType = 2 - ButtonRequest_ButtonRequest_ConfirmOutput ButtonRequest_ButtonRequestType = 3 - ButtonRequest_ButtonRequest_ResetDevice ButtonRequest_ButtonRequestType = 4 - ButtonRequest_ButtonRequest_ConfirmWord ButtonRequest_ButtonRequestType = 5 - ButtonRequest_ButtonRequest_WipeDevice ButtonRequest_ButtonRequestType = 6 - ButtonRequest_ButtonRequest_ProtectCall ButtonRequest_ButtonRequestType = 7 - ButtonRequest_ButtonRequest_SignTx ButtonRequest_ButtonRequestType = 8 - ButtonRequest_ButtonRequest_FirmwareCheck ButtonRequest_ButtonRequestType = 9 - ButtonRequest_ButtonRequest_Address ButtonRequest_ButtonRequestType = 10 - ButtonRequest_ButtonRequest_PublicKey ButtonRequest_ButtonRequestType = 11 - ButtonRequest_ButtonRequest_MnemonicWordCount ButtonRequest_ButtonRequestType = 12 - ButtonRequest_ButtonRequest_MnemonicInput ButtonRequest_ButtonRequestType = 13 - ButtonRequest_ButtonRequest_PassphraseType ButtonRequest_ButtonRequestType = 14 - ButtonRequest_ButtonRequest_UnknownDerivationPath ButtonRequest_ButtonRequestType = 15 -) - -var ButtonRequest_ButtonRequestType_name = map[int32]string{ - 1: "ButtonRequest_Other", - 2: "ButtonRequest_FeeOverThreshold", - 3: "ButtonRequest_ConfirmOutput", - 4: "ButtonRequest_ResetDevice", - 5: "ButtonRequest_ConfirmWord", - 6: "ButtonRequest_WipeDevice", - 7: "ButtonRequest_ProtectCall", - 8: "ButtonRequest_SignTx", - 9: "ButtonRequest_FirmwareCheck", - 10: "ButtonRequest_Address", - 11: "ButtonRequest_PublicKey", - 12: "ButtonRequest_MnemonicWordCount", - 13: "ButtonRequest_MnemonicInput", - 14: "ButtonRequest_PassphraseType", - 15: "ButtonRequest_UnknownDerivationPath", -} - -var ButtonRequest_ButtonRequestType_value = map[string]int32{ - "ButtonRequest_Other": 1, - "ButtonRequest_FeeOverThreshold": 2, - "ButtonRequest_ConfirmOutput": 3, - "ButtonRequest_ResetDevice": 4, - "ButtonRequest_ConfirmWord": 5, - "ButtonRequest_WipeDevice": 6, - "ButtonRequest_ProtectCall": 7, - "ButtonRequest_SignTx": 8, - "ButtonRequest_FirmwareCheck": 9, - "ButtonRequest_Address": 10, - "ButtonRequest_PublicKey": 11, - "ButtonRequest_MnemonicWordCount": 12, - "ButtonRequest_MnemonicInput": 13, - "ButtonRequest_PassphraseType": 14, - "ButtonRequest_UnknownDerivationPath": 15, -} - -func (x ButtonRequest_ButtonRequestType) Enum() *ButtonRequest_ButtonRequestType { - p := new(ButtonRequest_ButtonRequestType) - *p = x - return p -} - -func (x ButtonRequest_ButtonRequestType) String() string { - return proto.EnumName(ButtonRequest_ButtonRequestType_name, int32(x)) -} - -func (x *ButtonRequest_ButtonRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ButtonRequest_ButtonRequestType_value, data, "ButtonRequest_ButtonRequestType") - if err != nil { - return err - } - *x = ButtonRequest_ButtonRequestType(value) - return nil -} - -func (ButtonRequest_ButtonRequestType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{2, 0} -} - -// * -// Type of PIN request -type PinMatrixRequest_PinMatrixRequestType int32 - -const ( - PinMatrixRequest_PinMatrixRequestType_Current PinMatrixRequest_PinMatrixRequestType = 1 - PinMatrixRequest_PinMatrixRequestType_NewFirst PinMatrixRequest_PinMatrixRequestType = 2 - PinMatrixRequest_PinMatrixRequestType_NewSecond PinMatrixRequest_PinMatrixRequestType = 3 -) - -var PinMatrixRequest_PinMatrixRequestType_name = map[int32]string{ - 1: "PinMatrixRequestType_Current", - 2: "PinMatrixRequestType_NewFirst", - 3: "PinMatrixRequestType_NewSecond", -} - -var PinMatrixRequest_PinMatrixRequestType_value = map[string]int32{ - "PinMatrixRequestType_Current": 1, - "PinMatrixRequestType_NewFirst": 2, - "PinMatrixRequestType_NewSecond": 3, -} - -func (x PinMatrixRequest_PinMatrixRequestType) Enum() *PinMatrixRequest_PinMatrixRequestType { - p := new(PinMatrixRequest_PinMatrixRequestType) - *p = x - return p -} - -func (x PinMatrixRequest_PinMatrixRequestType) String() string { - return proto.EnumName(PinMatrixRequest_PinMatrixRequestType_name, int32(x)) -} - -func (x *PinMatrixRequest_PinMatrixRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PinMatrixRequest_PinMatrixRequestType_value, data, "PinMatrixRequest_PinMatrixRequestType") - if err != nil { - return err - } - *x = PinMatrixRequest_PinMatrixRequestType(value) - return nil -} - -func (PinMatrixRequest_PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{4, 0} -} - -// * -// Response: Success of the previous request -// @end -type Success struct { - Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Success) Reset() { *m = Success{} } -func (m *Success) String() string { return proto.CompactTextString(m) } -func (*Success) ProtoMessage() {} -func (*Success) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{0} -} - -func (m *Success) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Success.Unmarshal(m, b) -} -func (m *Success) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Success.Marshal(b, m, deterministic) -} -func (m *Success) XXX_Merge(src proto.Message) { - xxx_messageInfo_Success.Merge(m, src) -} -func (m *Success) XXX_Size() int { - return xxx_messageInfo_Success.Size(m) -} -func (m *Success) XXX_DiscardUnknown() { - xxx_messageInfo_Success.DiscardUnknown(m) -} - -var xxx_messageInfo_Success proto.InternalMessageInfo - -func (m *Success) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -// * -// Response: Failure of the previous request -// @end -type Failure struct { - Code *Failure_FailureType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.Failure_FailureType" json:"code,omitempty"` - Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Failure) Reset() { *m = Failure{} } -func (m *Failure) String() string { return proto.CompactTextString(m) } -func (*Failure) ProtoMessage() {} -func (*Failure) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{1} -} - -func (m *Failure) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Failure.Unmarshal(m, b) -} -func (m *Failure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Failure.Marshal(b, m, deterministic) -} -func (m *Failure) XXX_Merge(src proto.Message) { - xxx_messageInfo_Failure.Merge(m, src) -} -func (m *Failure) XXX_Size() int { - return xxx_messageInfo_Failure.Size(m) -} -func (m *Failure) XXX_DiscardUnknown() { - xxx_messageInfo_Failure.DiscardUnknown(m) -} - -var xxx_messageInfo_Failure proto.InternalMessageInfo - -func (m *Failure) GetCode() Failure_FailureType { - if m != nil && m.Code != nil { - return *m.Code - } - return Failure_Failure_UnexpectedMessage -} - -func (m *Failure) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -// * -// Response: Device is waiting for HW button press. -// @auxstart -// @next ButtonAck -type ButtonRequest struct { - Code *ButtonRequest_ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.ButtonRequest_ButtonRequestType" json:"code,omitempty"` - Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ButtonRequest) Reset() { *m = ButtonRequest{} } -func (m *ButtonRequest) String() string { return proto.CompactTextString(m) } -func (*ButtonRequest) ProtoMessage() {} -func (*ButtonRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{2} -} - -func (m *ButtonRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ButtonRequest.Unmarshal(m, b) -} -func (m *ButtonRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ButtonRequest.Marshal(b, m, deterministic) -} -func (m *ButtonRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ButtonRequest.Merge(m, src) -} -func (m *ButtonRequest) XXX_Size() int { - return xxx_messageInfo_ButtonRequest.Size(m) -} -func (m *ButtonRequest) XXX_DiscardUnknown() { - xxx_messageInfo_ButtonRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_ButtonRequest proto.InternalMessageInfo - -func (m *ButtonRequest) GetCode() ButtonRequest_ButtonRequestType { - if m != nil && m.Code != nil { - return *m.Code - } - return ButtonRequest_ButtonRequest_Other -} - -func (m *ButtonRequest) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -// * -// Request: Computer agrees to wait for HW button press -// @auxend -type ButtonAck struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ButtonAck) Reset() { *m = ButtonAck{} } -func (m *ButtonAck) String() string { return proto.CompactTextString(m) } -func (*ButtonAck) ProtoMessage() {} -func (*ButtonAck) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{3} -} - -func (m *ButtonAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ButtonAck.Unmarshal(m, b) -} -func (m *ButtonAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ButtonAck.Marshal(b, m, deterministic) -} -func (m *ButtonAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_ButtonAck.Merge(m, src) -} -func (m *ButtonAck) XXX_Size() int { - return xxx_messageInfo_ButtonAck.Size(m) -} -func (m *ButtonAck) XXX_DiscardUnknown() { - xxx_messageInfo_ButtonAck.DiscardUnknown(m) -} - -var xxx_messageInfo_ButtonAck proto.InternalMessageInfo - -// * -// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme -// @auxstart -// @next PinMatrixAck -type PinMatrixRequest struct { - Type *PinMatrixRequest_PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType" json:"type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PinMatrixRequest) Reset() { *m = PinMatrixRequest{} } -func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) } -func (*PinMatrixRequest) ProtoMessage() {} -func (*PinMatrixRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{4} -} - -func (m *PinMatrixRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PinMatrixRequest.Unmarshal(m, b) -} -func (m *PinMatrixRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PinMatrixRequest.Marshal(b, m, deterministic) -} -func (m *PinMatrixRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PinMatrixRequest.Merge(m, src) -} -func (m *PinMatrixRequest) XXX_Size() int { - return xxx_messageInfo_PinMatrixRequest.Size(m) -} -func (m *PinMatrixRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PinMatrixRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PinMatrixRequest proto.InternalMessageInfo - -func (m *PinMatrixRequest) GetType() PinMatrixRequest_PinMatrixRequestType { - if m != nil && m.Type != nil { - return *m.Type - } - return PinMatrixRequest_PinMatrixRequestType_Current -} - -// * -// Request: Computer responds with encoded PIN -// @auxend -type PinMatrixAck struct { - Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PinMatrixAck) Reset() { *m = PinMatrixAck{} } -func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) } -func (*PinMatrixAck) ProtoMessage() {} -func (*PinMatrixAck) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{5} -} - -func (m *PinMatrixAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PinMatrixAck.Unmarshal(m, b) -} -func (m *PinMatrixAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PinMatrixAck.Marshal(b, m, deterministic) -} -func (m *PinMatrixAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_PinMatrixAck.Merge(m, src) -} -func (m *PinMatrixAck) XXX_Size() int { - return xxx_messageInfo_PinMatrixAck.Size(m) -} -func (m *PinMatrixAck) XXX_DiscardUnknown() { - xxx_messageInfo_PinMatrixAck.DiscardUnknown(m) -} - -var xxx_messageInfo_PinMatrixAck proto.InternalMessageInfo - -func (m *PinMatrixAck) GetPin() string { - if m != nil && m.Pin != nil { - return *m.Pin - } - return "" -} - -// * -// Response: Device awaits encryption passphrase -// @auxstart -// @next PassphraseAck -type PassphraseRequest struct { - OnDevice *bool `protobuf:"varint,1,opt,name=on_device,json=onDevice" json:"on_device,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PassphraseRequest) Reset() { *m = PassphraseRequest{} } -func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) } -func (*PassphraseRequest) ProtoMessage() {} -func (*PassphraseRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{6} -} - -func (m *PassphraseRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PassphraseRequest.Unmarshal(m, b) -} -func (m *PassphraseRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PassphraseRequest.Marshal(b, m, deterministic) -} -func (m *PassphraseRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PassphraseRequest.Merge(m, src) -} -func (m *PassphraseRequest) XXX_Size() int { - return xxx_messageInfo_PassphraseRequest.Size(m) -} -func (m *PassphraseRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PassphraseRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PassphraseRequest proto.InternalMessageInfo - -func (m *PassphraseRequest) GetOnDevice() bool { - if m != nil && m.OnDevice != nil { - return *m.OnDevice - } - return false -} - -// * -// Request: Send passphrase back -// @next PassphraseStateRequest -type PassphraseAck struct { - Passphrase *string `protobuf:"bytes,1,opt,name=passphrase" json:"passphrase,omitempty"` - State []byte `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PassphraseAck) Reset() { *m = PassphraseAck{} } -func (m *PassphraseAck) String() string { return proto.CompactTextString(m) } -func (*PassphraseAck) ProtoMessage() {} -func (*PassphraseAck) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{7} -} - -func (m *PassphraseAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PassphraseAck.Unmarshal(m, b) -} -func (m *PassphraseAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PassphraseAck.Marshal(b, m, deterministic) -} -func (m *PassphraseAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_PassphraseAck.Merge(m, src) -} -func (m *PassphraseAck) XXX_Size() int { - return xxx_messageInfo_PassphraseAck.Size(m) -} -func (m *PassphraseAck) XXX_DiscardUnknown() { - xxx_messageInfo_PassphraseAck.DiscardUnknown(m) -} - -var xxx_messageInfo_PassphraseAck proto.InternalMessageInfo - -func (m *PassphraseAck) GetPassphrase() string { - if m != nil && m.Passphrase != nil { - return *m.Passphrase - } - return "" -} - -func (m *PassphraseAck) GetState() []byte { - if m != nil { - return m.State - } - return nil -} - -// * -// Response: Device awaits passphrase state -// @next PassphraseStateAck -type PassphraseStateRequest struct { - State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PassphraseStateRequest) Reset() { *m = PassphraseStateRequest{} } -func (m *PassphraseStateRequest) String() string { return proto.CompactTextString(m) } -func (*PassphraseStateRequest) ProtoMessage() {} -func (*PassphraseStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{8} -} - -func (m *PassphraseStateRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PassphraseStateRequest.Unmarshal(m, b) -} -func (m *PassphraseStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PassphraseStateRequest.Marshal(b, m, deterministic) -} -func (m *PassphraseStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PassphraseStateRequest.Merge(m, src) -} -func (m *PassphraseStateRequest) XXX_Size() int { - return xxx_messageInfo_PassphraseStateRequest.Size(m) -} -func (m *PassphraseStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PassphraseStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PassphraseStateRequest proto.InternalMessageInfo - -func (m *PassphraseStateRequest) GetState() []byte { - if m != nil { - return m.State - } - return nil -} - -// * -// Request: Send passphrase state back -// @auxend -type PassphraseStateAck struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PassphraseStateAck) Reset() { *m = PassphraseStateAck{} } -func (m *PassphraseStateAck) String() string { return proto.CompactTextString(m) } -func (*PassphraseStateAck) ProtoMessage() {} -func (*PassphraseStateAck) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{9} -} - -func (m *PassphraseStateAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PassphraseStateAck.Unmarshal(m, b) -} -func (m *PassphraseStateAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PassphraseStateAck.Marshal(b, m, deterministic) -} -func (m *PassphraseStateAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_PassphraseStateAck.Merge(m, src) -} -func (m *PassphraseStateAck) XXX_Size() int { - return xxx_messageInfo_PassphraseStateAck.Size(m) -} -func (m *PassphraseStateAck) XXX_DiscardUnknown() { - xxx_messageInfo_PassphraseStateAck.DiscardUnknown(m) -} - -var xxx_messageInfo_PassphraseStateAck proto.InternalMessageInfo - -// * -// Structure representing BIP32 (hierarchical deterministic) node -// Used for imports of private key into the device and exporting public key out of device -// @embed -type HDNodeType struct { - Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"` - Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"` - ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"` - ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"` - PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"` - PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *HDNodeType) Reset() { *m = HDNodeType{} } -func (m *HDNodeType) String() string { return proto.CompactTextString(m) } -func (*HDNodeType) ProtoMessage() {} -func (*HDNodeType) Descriptor() ([]byte, []int) { - return fileDescriptor_aaf30d059fdbc38d, []int{10} -} - -func (m *HDNodeType) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_HDNodeType.Unmarshal(m, b) -} -func (m *HDNodeType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_HDNodeType.Marshal(b, m, deterministic) -} -func (m *HDNodeType) XXX_Merge(src proto.Message) { - xxx_messageInfo_HDNodeType.Merge(m, src) -} -func (m *HDNodeType) XXX_Size() int { - return xxx_messageInfo_HDNodeType.Size(m) -} -func (m *HDNodeType) XXX_DiscardUnknown() { - xxx_messageInfo_HDNodeType.DiscardUnknown(m) -} - -var xxx_messageInfo_HDNodeType proto.InternalMessageInfo - -func (m *HDNodeType) GetDepth() uint32 { - if m != nil && m.Depth != nil { - return *m.Depth - } - return 0 -} - -func (m *HDNodeType) GetFingerprint() uint32 { - if m != nil && m.Fingerprint != nil { - return *m.Fingerprint - } - return 0 -} - -func (m *HDNodeType) GetChildNum() uint32 { - if m != nil && m.ChildNum != nil { - return *m.ChildNum - } - return 0 -} - -func (m *HDNodeType) GetChainCode() []byte { - if m != nil { - return m.ChainCode - } - return nil -} - -func (m *HDNodeType) GetPrivateKey() []byte { - if m != nil { - return m.PrivateKey - } - return nil -} - -func (m *HDNodeType) GetPublicKey() []byte { - if m != nil { - return m.PublicKey - } - return nil -} - -func init() { - proto.RegisterEnum("hw.trezor.messages.common.Failure_FailureType", Failure_FailureType_name, Failure_FailureType_value) - proto.RegisterEnum("hw.trezor.messages.common.ButtonRequest_ButtonRequestType", ButtonRequest_ButtonRequestType_name, ButtonRequest_ButtonRequestType_value) - proto.RegisterEnum("hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType", PinMatrixRequest_PinMatrixRequestType_name, PinMatrixRequest_PinMatrixRequestType_value) - proto.RegisterType((*Success)(nil), "hw.trezor.messages.common.Success") - proto.RegisterType((*Failure)(nil), "hw.trezor.messages.common.Failure") - proto.RegisterType((*ButtonRequest)(nil), "hw.trezor.messages.common.ButtonRequest") - proto.RegisterType((*ButtonAck)(nil), "hw.trezor.messages.common.ButtonAck") - proto.RegisterType((*PinMatrixRequest)(nil), "hw.trezor.messages.common.PinMatrixRequest") - proto.RegisterType((*PinMatrixAck)(nil), "hw.trezor.messages.common.PinMatrixAck") - proto.RegisterType((*PassphraseRequest)(nil), "hw.trezor.messages.common.PassphraseRequest") - proto.RegisterType((*PassphraseAck)(nil), "hw.trezor.messages.common.PassphraseAck") - proto.RegisterType((*PassphraseStateRequest)(nil), "hw.trezor.messages.common.PassphraseStateRequest") - proto.RegisterType((*PassphraseStateAck)(nil), "hw.trezor.messages.common.PassphraseStateAck") - proto.RegisterType((*HDNodeType)(nil), "hw.trezor.messages.common.HDNodeType") -} - -func init() { proto.RegisterFile("messages-common.proto", fileDescriptor_aaf30d059fdbc38d) } - -var fileDescriptor_aaf30d059fdbc38d = []byte{ - // 846 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xcd, 0x52, 0x23, 0x37, - 0x10, 0x2e, 0xff, 0x80, 0xed, 0xb6, 0xd9, 0x08, 0xc5, 0x80, 0x09, 0xb0, 0x38, 0xc3, 0x21, 0x5c, - 0xe2, 0x4a, 0xe5, 0x98, 0x53, 0x58, 0x83, 0x2b, 0xd4, 0x16, 0x86, 0x1a, 0xd8, 0xda, 0xa3, 0x4b, - 0xd1, 0xf4, 0x32, 0x2a, 0xcf, 0x48, 0x13, 0x8d, 0x06, 0xf0, 0x5e, 0xf2, 0x6a, 0x79, 0x89, 0xbc, - 0x42, 0xaa, 0x52, 0xb9, 0xe4, 0x11, 0xb6, 0x34, 0x3f, 0x78, 0xc6, 0x66, 0x39, 0xcd, 0xe8, 0xfb, - 0xbe, 0xee, 0x96, 0xba, 0x3f, 0x09, 0x76, 0x42, 0x8c, 0x63, 0x76, 0x8f, 0xf1, 0x8f, 0x5c, 0x85, - 0xa1, 0x92, 0xa3, 0x48, 0x2b, 0xa3, 0xe8, 0xbe, 0xff, 0x38, 0x32, 0x1a, 0x3f, 0x2b, 0x3d, 0x2a, - 0x04, 0xa3, 0x4c, 0xe0, 0x9c, 0x40, 0xeb, 0x36, 0xe1, 0x1c, 0xe3, 0x98, 0x0e, 0xa0, 0x95, 0xb3, - 0x83, 0xda, 0xb0, 0x76, 0xda, 0x71, 0x8b, 0xa5, 0xf3, 0x77, 0x03, 0x5a, 0x13, 0x26, 0x82, 0x44, - 0x23, 0x7d, 0x07, 0x4d, 0xae, 0xbc, 0x4c, 0xf2, 0xe6, 0xe7, 0xd1, 0xe8, 0xab, 0xa9, 0x47, 0x79, - 0x44, 0xf1, 0xbd, 0x5b, 0x44, 0xe8, 0xa6, 0xb1, 0xe5, 0x4a, 0xf5, 0x6a, 0xa5, 0xff, 0xea, 0xd0, - 0x2d, 0xe9, 0xe9, 0x11, 0xec, 0xe7, 0xcb, 0xd9, 0x07, 0x89, 0x4f, 0x11, 0x72, 0x83, 0xde, 0x55, - 0x26, 0x26, 0x35, 0xfa, 0x1d, 0xec, 0x16, 0xf4, 0xbb, 0xc4, 0x18, 0x25, 0x2f, 0x72, 0x09, 0xa9, - 0xd3, 0x1d, 0xd8, 0x2e, 0xb8, 0x73, 0x66, 0xd8, 0x85, 0xd6, 0x4a, 0x93, 0x06, 0x3d, 0x80, 0xbd, - 0x02, 0x3e, 0xe3, 0x46, 0x28, 0x39, 0x66, 0x92, 0x63, 0x10, 0xa0, 0x47, 0x9a, 0x74, 0x0f, 0xbe, - 0x2d, 0xc8, 0x1b, 0xb1, 0x4c, 0xb6, 0x41, 0x07, 0xd0, 0x2f, 0x11, 0xcb, 0x90, 0x4d, 0xba, 0x0b, - 0xb4, 0xc4, 0x5c, 0xca, 0x07, 0x16, 0x08, 0x8f, 0xb4, 0xe8, 0x21, 0x0c, 0x0a, 0x3c, 0x07, 0x6f, - 0xc5, 0xbd, 0x64, 0x26, 0xd1, 0x48, 0xda, 0x95, 0x7c, 0x5a, 0xd9, 0xf6, 0x67, 0xfb, 0xeb, 0x94, - 0x8f, 0x34, 0x55, 0xe6, 0x42, 0xaa, 0xe4, 0xde, 0x9f, 0x24, 0xd2, 0x8b, 0x09, 0xac, 0x70, 0x97, - 0x52, 0x18, 0xc1, 0x02, 0xf1, 0x19, 0x3d, 0xd2, 0x5d, 0xd9, 0xfa, 0x95, 0x88, 0x43, 0x66, 0xb8, - 0x4f, 0x7a, 0x74, 0x1f, 0x76, 0x0a, 0x62, 0x22, 0x74, 0xf8, 0xc8, 0x34, 0x66, 0xb5, 0xb8, 0xf3, - 0x4f, 0x13, 0xb6, 0xb2, 0xbe, 0xb9, 0xf8, 0x47, 0x82, 0xb1, 0xa1, 0xd3, 0xca, 0x74, 0x7f, 0x79, - 0x65, 0xba, 0x95, 0xb8, 0xea, 0xaa, 0x34, 0x69, 0x0a, 0x4d, 0x8f, 0x19, 0x96, 0x8f, 0x39, 0xfd, - 0x77, 0xfe, 0x6f, 0xc0, 0xf6, 0x9a, 0xde, 0xee, 0xbf, 0x02, 0xce, 0xae, 0x8d, 0x8f, 0x9a, 0xd4, - 0xa8, 0x03, 0x6f, 0xab, 0xc4, 0x04, 0xf1, 0xfa, 0x01, 0xf5, 0x9d, 0xaf, 0x31, 0xf6, 0x55, 0x60, - 0x67, 0x7d, 0x0c, 0x07, 0x55, 0xcd, 0x58, 0xc9, 0x4f, 0x42, 0x87, 0xd7, 0x89, 0x89, 0x12, 0x43, - 0x1a, 0xd6, 0x47, 0x55, 0x81, 0x8b, 0x31, 0x9a, 0x73, 0x7c, 0x10, 0x1c, 0x49, 0x73, 0x9d, 0xce, - 0xe3, 0x3f, 0x2a, 0x6d, 0xa7, 0x7f, 0x08, 0x83, 0x2a, 0xfd, 0x51, 0x44, 0x98, 0x07, 0x6f, 0xae, - 0x07, 0xdf, 0x68, 0x65, 0x90, 0x9b, 0x31, 0x0b, 0x02, 0xd2, 0xb2, 0xa3, 0xae, 0xd2, 0xd6, 0x07, - 0x77, 0x4f, 0xa4, 0xbd, 0xbe, 0xeb, 0x62, 0x3e, 0x63, 0x1f, 0xf9, 0x9c, 0x74, 0xec, 0xe8, 0xaa, - 0x82, 0x33, 0xcf, 0xd3, 0x18, 0x5b, 0x2b, 0x1c, 0xc0, 0xde, 0x4a, 0xd1, 0xe4, 0xf7, 0x40, 0xf0, - 0xf7, 0xb8, 0x20, 0x5d, 0x7a, 0x02, 0xc7, 0x55, 0xf2, 0x4a, 0x62, 0xa8, 0xa4, 0xe0, 0xf6, 0x3c, - 0x63, 0x95, 0x48, 0x43, 0x7a, 0xeb, 0xd5, 0x0b, 0xd1, 0xa5, 0xb4, 0x3d, 0xdb, 0xa2, 0x43, 0x38, - 0x5c, 0x29, 0xc1, 0xe2, 0x38, 0xf2, 0x35, 0x8b, 0xd3, 0xbb, 0x49, 0xde, 0xd0, 0x1f, 0xe0, 0xa4, - 0xaa, 0xf8, 0x20, 0xe7, 0x52, 0x3d, 0xca, 0x73, 0xd4, 0xe2, 0x81, 0xd9, 0xcb, 0x75, 0xc3, 0x8c, - 0x4f, 0xbe, 0x71, 0xba, 0xd0, 0xc9, 0x84, 0x67, 0x7c, 0xee, 0xfc, 0x5b, 0x03, 0x62, 0x2d, 0xca, - 0x8c, 0x16, 0x4f, 0x85, 0xf1, 0xee, 0xa0, 0x69, 0x16, 0x51, 0x61, 0xbc, 0x5f, 0x5f, 0x31, 0xde, - 0x6a, 0xe8, 0x1a, 0x90, 0xd9, 0xcf, 0x66, 0x73, 0xfe, 0x84, 0xfe, 0x4b, 0xac, 0x3d, 0xda, 0x4b, - 0xf8, 0x6c, 0x9c, 0x68, 0x8d, 0xd2, 0x90, 0x1a, 0xfd, 0x1e, 0x8e, 0x5e, 0x54, 0x4c, 0xf1, 0x71, - 0x22, 0x74, 0x6c, 0x48, 0xdd, 0x1a, 0xf3, 0x6b, 0x92, 0x5b, 0xe4, 0x4a, 0x7a, 0xa4, 0xe1, 0x0c, - 0xa1, 0xf7, 0xac, 0x39, 0xe3, 0x73, 0x4a, 0xa0, 0x11, 0x09, 0x39, 0xa8, 0x0d, 0xeb, 0xa7, 0x1d, - 0xd7, 0xfe, 0x3a, 0x3f, 0xc1, 0xf6, 0xb2, 0xaf, 0x45, 0x37, 0x0e, 0xa0, 0xa3, 0xe4, 0xcc, 0x4b, - 0x1d, 0x96, 0xb6, 0xa4, 0xed, 0xb6, 0x95, 0xcc, 0x1c, 0xe7, 0x5c, 0xc0, 0xd6, 0x32, 0xc2, 0x26, - 0x7d, 0x0b, 0x10, 0x3d, 0x03, 0xf9, 0xdb, 0x5d, 0x42, 0x68, 0x1f, 0x36, 0x62, 0xc3, 0x4c, 0xf6, - 0xd8, 0xf6, 0xdc, 0x6c, 0xe1, 0x8c, 0x60, 0x77, 0x99, 0xe6, 0xd6, 0x42, 0x45, 0xf5, 0x67, 0x7d, - 0xad, 0xac, 0xef, 0x03, 0x5d, 0xd1, 0xdb, 0x61, 0xfe, 0x55, 0x03, 0xf8, 0xed, 0x7c, 0xaa, 0xbc, - 0xec, 0xbd, 0xee, 0xc3, 0x86, 0x87, 0x91, 0xf1, 0xd3, 0x13, 0x6e, 0xb9, 0xd9, 0x82, 0x0e, 0xa1, - 0xfb, 0x49, 0xc8, 0x7b, 0xd4, 0x91, 0x16, 0xd2, 0x0c, 0xea, 0x29, 0x57, 0x86, 0xec, 0x81, 0xb9, - 0x2f, 0x02, 0x6f, 0x26, 0x93, 0x70, 0xd0, 0x48, 0xf9, 0x76, 0x0a, 0x4c, 0x93, 0x90, 0x1e, 0x01, - 0x70, 0x9f, 0x09, 0x39, 0x4b, 0x9f, 0xa6, 0xe6, 0xb0, 0x7e, 0xda, 0x73, 0x3b, 0x29, 0x32, 0xb6, - 0x6f, 0xcc, 0x31, 0x74, 0xa3, 0xd4, 0x6f, 0x38, 0x9b, 0xe3, 0x62, 0xb0, 0x91, 0x6e, 0x1a, 0x72, - 0xe8, 0x3d, 0x2e, 0x6c, 0x7c, 0x94, 0xde, 0x8e, 0x94, 0xdf, 0x4c, 0xf9, 0x4e, 0x54, 0xdc, 0x97, - 0x2f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x7d, 0x20, 0xa6, 0x35, 0x07, 0x00, 0x00, -} diff --git a/builder/accounts/usbwallet/trezor/messages-common.proto b/builder/accounts/usbwallet/trezor/messages-common.proto deleted file mode 100644 index 75a983b0a..000000000 --- a/builder/accounts/usbwallet/trezor/messages-common.proto +++ /dev/null @@ -1,147 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto -// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. - -syntax = "proto2"; -package hw.trezor.messages.common; - -/** - * Response: Success of the previous request - * @end - */ -message Success { - optional string message = 1; // human readable description of action or request-specific payload -} - -/** - * Response: Failure of the previous request - * @end - */ -message Failure { - optional FailureType code = 1; // computer-readable definition of the error state - optional string message = 2; // human-readable message of the error state - enum FailureType { - Failure_UnexpectedMessage = 1; - Failure_ButtonExpected = 2; - Failure_DataError = 3; - Failure_ActionCancelled = 4; - Failure_PinExpected = 5; - Failure_PinCancelled = 6; - Failure_PinInvalid = 7; - Failure_InvalidSignature = 8; - Failure_ProcessError = 9; - Failure_NotEnoughFunds = 10; - Failure_NotInitialized = 11; - Failure_PinMismatch = 12; - Failure_FirmwareError = 99; - } -} - -/** - * Response: Device is waiting for HW button press. - * @auxstart - * @next ButtonAck - */ -message ButtonRequest { - optional ButtonRequestType code = 1; - optional string data = 2; - /** - * Type of button request - */ - enum ButtonRequestType { - ButtonRequest_Other = 1; - ButtonRequest_FeeOverThreshold = 2; - ButtonRequest_ConfirmOutput = 3; - ButtonRequest_ResetDevice = 4; - ButtonRequest_ConfirmWord = 5; - ButtonRequest_WipeDevice = 6; - ButtonRequest_ProtectCall = 7; - ButtonRequest_SignTx = 8; - ButtonRequest_FirmwareCheck = 9; - ButtonRequest_Address = 10; - ButtonRequest_PublicKey = 11; - ButtonRequest_MnemonicWordCount = 12; - ButtonRequest_MnemonicInput = 13; - ButtonRequest_PassphraseType = 14; - ButtonRequest_UnknownDerivationPath = 15; - } -} - -/** - * Request: Computer agrees to wait for HW button press - * @auxend - */ -message ButtonAck { -} - -/** - * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme - * @auxstart - * @next PinMatrixAck - */ -message PinMatrixRequest { - optional PinMatrixRequestType type = 1; - /** - * Type of PIN request - */ - enum PinMatrixRequestType { - PinMatrixRequestType_Current = 1; - PinMatrixRequestType_NewFirst = 2; - PinMatrixRequestType_NewSecond = 3; - } -} - -/** - * Request: Computer responds with encoded PIN - * @auxend - */ -message PinMatrixAck { - required string pin = 1; // matrix encoded PIN entered by user -} - -/** - * Response: Device awaits encryption passphrase - * @auxstart - * @next PassphraseAck - */ -message PassphraseRequest { - optional bool on_device = 1; // passphrase is being entered on the device -} - -/** - * Request: Send passphrase back - * @next PassphraseStateRequest - */ -message PassphraseAck { - optional string passphrase = 1; - optional bytes state = 2; // expected device state -} - -/** - * Response: Device awaits passphrase state - * @next PassphraseStateAck - */ -message PassphraseStateRequest { - optional bytes state = 1; // actual device state -} - -/** - * Request: Send passphrase state back - * @auxend - */ -message PassphraseStateAck { -} - -/** - * Structure representing BIP32 (hierarchical deterministic) node - * Used for imports of private key into the device and exporting public key out of device - * @embed - */ -message HDNodeType { - required uint32 depth = 1; - required uint32 fingerprint = 2; - required uint32 child_num = 3; - required bytes chain_code = 4; - optional bytes private_key = 5; - optional bytes public_key = 6; -} diff --git a/builder/accounts/usbwallet/trezor/messages-ethereum.pb.go b/builder/accounts/usbwallet/trezor/messages-ethereum.pb.go deleted file mode 100644 index 230a48279..000000000 --- a/builder/accounts/usbwallet/trezor/messages-ethereum.pb.go +++ /dev/null @@ -1,698 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: messages-ethereum.proto - -package trezor - -import ( - fmt "fmt" - math "math" - - proto "github.com/golang/protobuf/proto" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -// * -// Request: Ask device for public key corresponding to address_n path -// @start -// @next EthereumPublicKey -// @next Failure -type EthereumGetPublicKey struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumGetPublicKey) Reset() { *m = EthereumGetPublicKey{} } -func (m *EthereumGetPublicKey) String() string { return proto.CompactTextString(m) } -func (*EthereumGetPublicKey) ProtoMessage() {} -func (*EthereumGetPublicKey) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{0} -} - -func (m *EthereumGetPublicKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumGetPublicKey.Unmarshal(m, b) -} -func (m *EthereumGetPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumGetPublicKey.Marshal(b, m, deterministic) -} -func (m *EthereumGetPublicKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumGetPublicKey.Merge(m, src) -} -func (m *EthereumGetPublicKey) XXX_Size() int { - return xxx_messageInfo_EthereumGetPublicKey.Size(m) -} -func (m *EthereumGetPublicKey) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumGetPublicKey.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumGetPublicKey proto.InternalMessageInfo - -func (m *EthereumGetPublicKey) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumGetPublicKey) GetShowDisplay() bool { - if m != nil && m.ShowDisplay != nil { - return *m.ShowDisplay - } - return false -} - -// * -// Response: Contains public key derived from device private seed -// @end -type EthereumPublicKey struct { - Node *HDNodeType `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"` - Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumPublicKey) Reset() { *m = EthereumPublicKey{} } -func (m *EthereumPublicKey) String() string { return proto.CompactTextString(m) } -func (*EthereumPublicKey) ProtoMessage() {} -func (*EthereumPublicKey) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{1} -} - -func (m *EthereumPublicKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumPublicKey.Unmarshal(m, b) -} -func (m *EthereumPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumPublicKey.Marshal(b, m, deterministic) -} -func (m *EthereumPublicKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumPublicKey.Merge(m, src) -} -func (m *EthereumPublicKey) XXX_Size() int { - return xxx_messageInfo_EthereumPublicKey.Size(m) -} -func (m *EthereumPublicKey) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumPublicKey.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumPublicKey proto.InternalMessageInfo - -func (m *EthereumPublicKey) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *EthereumPublicKey) GetXpub() string { - if m != nil && m.Xpub != nil { - return *m.Xpub - } - return "" -} - -// * -// Request: Ask device for Ethereum address corresponding to address_n path -// @start -// @next EthereumAddress -// @next Failure -type EthereumGetAddress struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumGetAddress) Reset() { *m = EthereumGetAddress{} } -func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) } -func (*EthereumGetAddress) ProtoMessage() {} -func (*EthereumGetAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{2} -} - -func (m *EthereumGetAddress) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumGetAddress.Unmarshal(m, b) -} -func (m *EthereumGetAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumGetAddress.Marshal(b, m, deterministic) -} -func (m *EthereumGetAddress) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumGetAddress.Merge(m, src) -} -func (m *EthereumGetAddress) XXX_Size() int { - return xxx_messageInfo_EthereumGetAddress.Size(m) -} -func (m *EthereumGetAddress) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumGetAddress.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumGetAddress proto.InternalMessageInfo - -func (m *EthereumGetAddress) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumGetAddress) GetShowDisplay() bool { - if m != nil && m.ShowDisplay != nil { - return *m.ShowDisplay - } - return false -} - -// * -// Response: Contains an Ethereum address derived from device private seed -// @end -type EthereumAddress struct { - AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` - AddressHex *string `protobuf:"bytes,2,opt,name=addressHex" json:"addressHex,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumAddress) Reset() { *m = EthereumAddress{} } -func (m *EthereumAddress) String() string { return proto.CompactTextString(m) } -func (*EthereumAddress) ProtoMessage() {} -func (*EthereumAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{3} -} - -func (m *EthereumAddress) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumAddress.Unmarshal(m, b) -} -func (m *EthereumAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumAddress.Marshal(b, m, deterministic) -} -func (m *EthereumAddress) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumAddress.Merge(m, src) -} -func (m *EthereumAddress) XXX_Size() int { - return xxx_messageInfo_EthereumAddress.Size(m) -} -func (m *EthereumAddress) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumAddress.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumAddress proto.InternalMessageInfo - -func (m *EthereumAddress) GetAddressBin() []byte { - if m != nil { - return m.AddressBin - } - return nil -} - -func (m *EthereumAddress) GetAddressHex() string { - if m != nil && m.AddressHex != nil { - return *m.AddressHex - } - return "" -} - -// * -// Request: Ask device to sign transaction -// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. -// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. -// @start -// @next EthereumTxRequest -// @next Failure -type EthereumSignTx struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"` - GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"` - GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"` - ToBin []byte `protobuf:"bytes,5,opt,name=toBin" json:"toBin,omitempty"` - ToHex *string `protobuf:"bytes,11,opt,name=toHex" json:"toHex,omitempty"` - Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"` - DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"` - DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` - ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"` - TxType *uint32 `protobuf:"varint,10,opt,name=tx_type,json=txType" json:"tx_type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumSignTx) Reset() { *m = EthereumSignTx{} } -func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) } -func (*EthereumSignTx) ProtoMessage() {} -func (*EthereumSignTx) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{4} -} - -func (m *EthereumSignTx) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumSignTx.Unmarshal(m, b) -} -func (m *EthereumSignTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumSignTx.Marshal(b, m, deterministic) -} -func (m *EthereumSignTx) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumSignTx.Merge(m, src) -} -func (m *EthereumSignTx) XXX_Size() int { - return xxx_messageInfo_EthereumSignTx.Size(m) -} -func (m *EthereumSignTx) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumSignTx.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumSignTx proto.InternalMessageInfo - -func (m *EthereumSignTx) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumSignTx) GetNonce() []byte { - if m != nil { - return m.Nonce - } - return nil -} - -func (m *EthereumSignTx) GetGasPrice() []byte { - if m != nil { - return m.GasPrice - } - return nil -} - -func (m *EthereumSignTx) GetGasLimit() []byte { - if m != nil { - return m.GasLimit - } - return nil -} - -func (m *EthereumSignTx) GetToBin() []byte { - if m != nil { - return m.ToBin - } - return nil -} - -func (m *EthereumSignTx) GetToHex() string { - if m != nil && m.ToHex != nil { - return *m.ToHex - } - return "" -} - -func (m *EthereumSignTx) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *EthereumSignTx) GetDataInitialChunk() []byte { - if m != nil { - return m.DataInitialChunk - } - return nil -} - -func (m *EthereumSignTx) GetDataLength() uint32 { - if m != nil && m.DataLength != nil { - return *m.DataLength - } - return 0 -} - -func (m *EthereumSignTx) GetChainId() uint32 { - if m != nil && m.ChainId != nil { - return *m.ChainId - } - return 0 -} - -func (m *EthereumSignTx) GetTxType() uint32 { - if m != nil && m.TxType != nil { - return *m.TxType - } - return 0 -} - -// * -// Response: Device asks for more data from transaction payload, or returns the signature. -// If data_length is set, device awaits that many more bytes of payload. -// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. -// @end -// @next EthereumTxAck -type EthereumTxRequest struct { - DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"` - SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"` - SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"` - SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumTxRequest) Reset() { *m = EthereumTxRequest{} } -func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) } -func (*EthereumTxRequest) ProtoMessage() {} -func (*EthereumTxRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{5} -} - -func (m *EthereumTxRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumTxRequest.Unmarshal(m, b) -} -func (m *EthereumTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumTxRequest.Marshal(b, m, deterministic) -} -func (m *EthereumTxRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumTxRequest.Merge(m, src) -} -func (m *EthereumTxRequest) XXX_Size() int { - return xxx_messageInfo_EthereumTxRequest.Size(m) -} -func (m *EthereumTxRequest) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumTxRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumTxRequest proto.InternalMessageInfo - -func (m *EthereumTxRequest) GetDataLength() uint32 { - if m != nil && m.DataLength != nil { - return *m.DataLength - } - return 0 -} - -func (m *EthereumTxRequest) GetSignatureV() uint32 { - if m != nil && m.SignatureV != nil { - return *m.SignatureV - } - return 0 -} - -func (m *EthereumTxRequest) GetSignatureR() []byte { - if m != nil { - return m.SignatureR - } - return nil -} - -func (m *EthereumTxRequest) GetSignatureS() []byte { - if m != nil { - return m.SignatureS - } - return nil -} - -// * -// Request: Transaction payload data. -// @next EthereumTxRequest -type EthereumTxAck struct { - DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumTxAck) Reset() { *m = EthereumTxAck{} } -func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) } -func (*EthereumTxAck) ProtoMessage() {} -func (*EthereumTxAck) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{6} -} - -func (m *EthereumTxAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumTxAck.Unmarshal(m, b) -} -func (m *EthereumTxAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumTxAck.Marshal(b, m, deterministic) -} -func (m *EthereumTxAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumTxAck.Merge(m, src) -} -func (m *EthereumTxAck) XXX_Size() int { - return xxx_messageInfo_EthereumTxAck.Size(m) -} -func (m *EthereumTxAck) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumTxAck.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumTxAck proto.InternalMessageInfo - -func (m *EthereumTxAck) GetDataChunk() []byte { - if m != nil { - return m.DataChunk - } - return nil -} - -// * -// Request: Ask device to sign message -// @start -// @next EthereumMessageSignature -// @next Failure -type EthereumSignMessage struct { - AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"` - Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumSignMessage) Reset() { *m = EthereumSignMessage{} } -func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) } -func (*EthereumSignMessage) ProtoMessage() {} -func (*EthereumSignMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{7} -} - -func (m *EthereumSignMessage) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumSignMessage.Unmarshal(m, b) -} -func (m *EthereumSignMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumSignMessage.Marshal(b, m, deterministic) -} -func (m *EthereumSignMessage) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumSignMessage.Merge(m, src) -} -func (m *EthereumSignMessage) XXX_Size() int { - return xxx_messageInfo_EthereumSignMessage.Size(m) -} -func (m *EthereumSignMessage) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumSignMessage.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumSignMessage proto.InternalMessageInfo - -func (m *EthereumSignMessage) GetAddressN() []uint32 { - if m != nil { - return m.AddressN - } - return nil -} - -func (m *EthereumSignMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -// * -// Response: Signed message -// @end -type EthereumMessageSignature struct { - AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - AddressHex *string `protobuf:"bytes,3,opt,name=addressHex" json:"addressHex,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumMessageSignature) Reset() { *m = EthereumMessageSignature{} } -func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) } -func (*EthereumMessageSignature) ProtoMessage() {} -func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{8} -} - -func (m *EthereumMessageSignature) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumMessageSignature.Unmarshal(m, b) -} -func (m *EthereumMessageSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumMessageSignature.Marshal(b, m, deterministic) -} -func (m *EthereumMessageSignature) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumMessageSignature.Merge(m, src) -} -func (m *EthereumMessageSignature) XXX_Size() int { - return xxx_messageInfo_EthereumMessageSignature.Size(m) -} -func (m *EthereumMessageSignature) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumMessageSignature.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumMessageSignature proto.InternalMessageInfo - -func (m *EthereumMessageSignature) GetAddressBin() []byte { - if m != nil { - return m.AddressBin - } - return nil -} - -func (m *EthereumMessageSignature) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *EthereumMessageSignature) GetAddressHex() string { - if m != nil && m.AddressHex != nil { - return *m.AddressHex - } - return "" -} - -// * -// Request: Ask device to verify message -// @start -// @next Success -// @next Failure -type EthereumVerifyMessage struct { - AddressBin []byte `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` - Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` - AddressHex *string `protobuf:"bytes,4,opt,name=addressHex" json:"addressHex,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EthereumVerifyMessage) Reset() { *m = EthereumVerifyMessage{} } -func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) } -func (*EthereumVerifyMessage) ProtoMessage() {} -func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_cb33f46ba915f15c, []int{9} -} - -func (m *EthereumVerifyMessage) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EthereumVerifyMessage.Unmarshal(m, b) -} -func (m *EthereumVerifyMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EthereumVerifyMessage.Marshal(b, m, deterministic) -} -func (m *EthereumVerifyMessage) XXX_Merge(src proto.Message) { - xxx_messageInfo_EthereumVerifyMessage.Merge(m, src) -} -func (m *EthereumVerifyMessage) XXX_Size() int { - return xxx_messageInfo_EthereumVerifyMessage.Size(m) -} -func (m *EthereumVerifyMessage) XXX_DiscardUnknown() { - xxx_messageInfo_EthereumVerifyMessage.DiscardUnknown(m) -} - -var xxx_messageInfo_EthereumVerifyMessage proto.InternalMessageInfo - -func (m *EthereumVerifyMessage) GetAddressBin() []byte { - if m != nil { - return m.AddressBin - } - return nil -} - -func (m *EthereumVerifyMessage) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *EthereumVerifyMessage) GetMessage() []byte { - if m != nil { - return m.Message - } - return nil -} - -func (m *EthereumVerifyMessage) GetAddressHex() string { - if m != nil && m.AddressHex != nil { - return *m.AddressHex - } - return "" -} - -func init() { - proto.RegisterType((*EthereumGetPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumGetPublicKey") - proto.RegisterType((*EthereumPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumPublicKey") - proto.RegisterType((*EthereumGetAddress)(nil), "hw.trezor.messages.ethereum.EthereumGetAddress") - proto.RegisterType((*EthereumAddress)(nil), "hw.trezor.messages.ethereum.EthereumAddress") - proto.RegisterType((*EthereumSignTx)(nil), "hw.trezor.messages.ethereum.EthereumSignTx") - proto.RegisterType((*EthereumTxRequest)(nil), "hw.trezor.messages.ethereum.EthereumTxRequest") - proto.RegisterType((*EthereumTxAck)(nil), "hw.trezor.messages.ethereum.EthereumTxAck") - proto.RegisterType((*EthereumSignMessage)(nil), "hw.trezor.messages.ethereum.EthereumSignMessage") - proto.RegisterType((*EthereumMessageSignature)(nil), "hw.trezor.messages.ethereum.EthereumMessageSignature") - proto.RegisterType((*EthereumVerifyMessage)(nil), "hw.trezor.messages.ethereum.EthereumVerifyMessage") -} - -func init() { proto.RegisterFile("messages-ethereum.proto", fileDescriptor_cb33f46ba915f15c) } - -var fileDescriptor_cb33f46ba915f15c = []byte{ - // 593 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0x95, 0x9b, 0xb4, 0x49, 0x26, 0x0d, 0x1f, 0xa6, 0x55, 0x17, 0x0a, 0x34, 0x18, 0x21, 0xe5, - 0x00, 0x3e, 0x70, 0x43, 0xe2, 0xd2, 0x52, 0x44, 0x2b, 0x4a, 0x55, 0xdc, 0xa8, 0x57, 0x6b, 0x63, - 0x6f, 0xe3, 0x55, 0x9d, 0xdd, 0xe0, 0x5d, 0xb7, 0x0e, 0x7f, 0x82, 0x23, 0xff, 0x87, 0x5f, 0x86, - 0xf6, 0x2b, 0x71, 0x52, 0x54, 0x0e, 0xbd, 0x65, 0xde, 0xbc, 0x7d, 0xf3, 0x66, 0xf4, 0x62, 0xd8, - 0x99, 0x10, 0x21, 0xf0, 0x98, 0x88, 0x77, 0x44, 0x66, 0xa4, 0x20, 0xe5, 0x24, 0x9c, 0x16, 0x5c, - 0x72, 0x7f, 0x37, 0xbb, 0x09, 0x65, 0x41, 0x7e, 0xf2, 0x22, 0x74, 0x94, 0xd0, 0x51, 0x9e, 0x6d, - 0xcf, 0x5f, 0x25, 0x7c, 0x32, 0xe1, 0xcc, 0xbc, 0x09, 0x2e, 0x60, 0xeb, 0xb3, 0xa5, 0x7c, 0x21, - 0xf2, 0xac, 0x1c, 0xe5, 0x34, 0xf9, 0x4a, 0x66, 0xfe, 0x2e, 0x74, 0x70, 0x9a, 0x16, 0x44, 0x88, - 0x98, 0x21, 0xaf, 0xdf, 0x18, 0xf4, 0xa2, 0xb6, 0x05, 0x4e, 0xfd, 0x57, 0xb0, 0x29, 0x32, 0x7e, - 0x13, 0xa7, 0x54, 0x4c, 0x73, 0x3c, 0x43, 0x6b, 0x7d, 0x6f, 0xd0, 0x8e, 0xba, 0x0a, 0x3b, 0x34, - 0x50, 0x30, 0x82, 0xc7, 0x4e, 0x77, 0x21, 0xfa, 0x01, 0x9a, 0x8c, 0xa7, 0x04, 0x79, 0x7d, 0x6f, - 0xd0, 0x7d, 0xff, 0x26, 0xfc, 0x87, 0x5f, 0x6b, 0xee, 0xe8, 0xf0, 0x94, 0xa7, 0x64, 0x38, 0x9b, - 0x92, 0x48, 0x3f, 0xf1, 0x7d, 0x68, 0x56, 0xd3, 0x72, 0xa4, 0x47, 0x75, 0x22, 0xfd, 0x3b, 0x18, - 0x82, 0x5f, 0xf3, 0xbe, 0x6f, 0xdc, 0xdd, 0xdb, 0xf9, 0x77, 0x78, 0xe8, 0x54, 0x9d, 0xe4, 0x4b, - 0x00, 0xab, 0x70, 0x40, 0x99, 0x76, 0xbf, 0x19, 0xd5, 0x90, 0x5a, 0xff, 0x88, 0x54, 0xd6, 0x62, - 0x0d, 0x09, 0xfe, 0xac, 0xc1, 0x03, 0xa7, 0x79, 0x4e, 0xc7, 0x6c, 0x58, 0xdd, 0xed, 0x72, 0x0b, - 0xd6, 0x19, 0x67, 0x09, 0xd1, 0x52, 0x9b, 0x91, 0x29, 0xd4, 0x93, 0x31, 0x16, 0xf1, 0xb4, 0xa0, - 0x09, 0x41, 0x0d, 0xdd, 0x69, 0x8f, 0xb1, 0x38, 0x53, 0xb5, 0x6b, 0xe6, 0x74, 0x42, 0x25, 0x6a, - 0xce, 0x9b, 0x27, 0xaa, 0x56, 0x7a, 0x92, 0x2b, 0xeb, 0xeb, 0x46, 0x4f, 0x17, 0x06, 0x55, 0x86, - 0xbb, 0xda, 0xb0, 0x29, 0x14, 0x7a, 0x8d, 0xf3, 0x92, 0xa0, 0x0d, 0xc3, 0xd5, 0x85, 0xff, 0x16, - 0xfc, 0x14, 0x4b, 0x1c, 0x53, 0x46, 0x25, 0xc5, 0x79, 0x9c, 0x64, 0x25, 0xbb, 0x42, 0x2d, 0x4d, - 0x79, 0xa4, 0x3a, 0xc7, 0xa6, 0xf1, 0x49, 0xe1, 0xfe, 0x1e, 0x74, 0x35, 0x3b, 0x27, 0x6c, 0x2c, - 0x33, 0xd4, 0xee, 0x7b, 0x83, 0x5e, 0x04, 0x0a, 0x3a, 0xd1, 0x88, 0xff, 0x14, 0xda, 0x49, 0x86, - 0x29, 0x8b, 0x69, 0x8a, 0x3a, 0xba, 0xdb, 0xd2, 0xf5, 0x71, 0xea, 0xef, 0x40, 0x4b, 0x56, 0xb1, - 0x9c, 0x4d, 0x09, 0x02, 0xdd, 0xd9, 0x90, 0x95, 0xca, 0x41, 0xf0, 0xdb, 0x5b, 0x44, 0x6a, 0x58, - 0x45, 0xe4, 0x47, 0x49, 0x84, 0x5c, 0x1d, 0xe5, 0xdd, 0x1a, 0xb5, 0x07, 0x5d, 0x41, 0xc7, 0x0c, - 0xcb, 0xb2, 0x20, 0xf1, 0xb5, 0xbe, 0x68, 0x2f, 0x82, 0x39, 0x74, 0xb1, 0x4c, 0x28, 0xec, 0x61, - 0x17, 0x84, 0x68, 0x99, 0x20, 0xec, 0x71, 0x17, 0x84, 0xf3, 0x20, 0x84, 0xde, 0xc2, 0xd8, 0x7e, - 0x72, 0xe5, 0xbf, 0x00, 0xed, 0xc0, 0x5e, 0xc9, 0xe4, 0xa5, 0xa3, 0x10, 0x7d, 0x9e, 0xe0, 0x04, - 0x9e, 0xd4, 0xd3, 0xf0, 0xcd, 0x64, 0xff, 0xee, 0x48, 0x20, 0x68, 0xd9, 0xff, 0x88, 0x0d, 0x85, - 0x2b, 0x83, 0x0a, 0x90, 0x53, 0xb3, 0x4a, 0xe7, 0xce, 0xda, 0x7f, 0x83, 0xfb, 0x1c, 0x3a, 0xf3, - 0x3d, 0xac, 0xee, 0x02, 0x58, 0x89, 0x75, 0xe3, 0x56, 0xac, 0x7f, 0x79, 0xb0, 0xed, 0x46, 0x5f, - 0x90, 0x82, 0x5e, 0xce, 0xdc, 0x2a, 0xf7, 0x9b, 0x5b, 0xdb, 0xb5, 0xb1, 0xb4, 0xeb, 0x8a, 0xa3, - 0xe6, 0xaa, 0xa3, 0x83, 0x8f, 0xf0, 0x3a, 0xe1, 0x93, 0x50, 0x60, 0xc9, 0x45, 0x46, 0x73, 0x3c, - 0x12, 0xee, 0x03, 0x93, 0xd3, 0x91, 0xf9, 0xe2, 0x8d, 0xca, 0xcb, 0x83, 0xed, 0xa1, 0x06, 0xad, - 0x5b, 0xb7, 0xc2, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8a, 0xce, 0x81, 0xc8, 0x59, 0x05, 0x00, - 0x00, -} diff --git a/builder/accounts/usbwallet/trezor/messages-ethereum.proto b/builder/accounts/usbwallet/trezor/messages-ethereum.proto deleted file mode 100644 index 096bed2e4..000000000 --- a/builder/accounts/usbwallet/trezor/messages-ethereum.proto +++ /dev/null @@ -1,131 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto -// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. - -syntax = "proto2"; -package hw.trezor.messages.ethereum; - -// Sugar for easier handling in Java -option java_package = "com.satoshilabs.trezor.lib.protobuf"; -option java_outer_classname = "TrezorMessageEthereum"; - -import "messages-common.proto"; - - -/** - * Request: Ask device for public key corresponding to address_n path - * @start - * @next EthereumPublicKey - * @next Failure - */ -message EthereumGetPublicKey { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bool show_display = 2; // optionally show on display before sending the result -} - -/** - * Response: Contains public key derived from device private seed - * @end - */ -message EthereumPublicKey { - optional hw.trezor.messages.common.HDNodeType node = 1; // BIP32 public node - optional string xpub = 2; // serialized form of public node -} - -/** - * Request: Ask device for Ethereum address corresponding to address_n path - * @start - * @next EthereumAddress - * @next Failure - */ -message EthereumGetAddress { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bool show_display = 2; // optionally show on display before sending the result -} - -/** - * Response: Contains an Ethereum address derived from device private seed - * @end - */ -message EthereumAddress { - optional bytes addressBin = 1; // Ethereum address as 20 bytes (legacy firmwares) - optional string addressHex = 2; // Ethereum address as hex string (newer firmwares) -} - -/** - * Request: Ask device to sign transaction - * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. - * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. - * @start - * @next EthereumTxRequest - * @next Failure - */ -message EthereumSignTx { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bytes nonce = 2; // <=256 bit unsigned big endian - optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) - optional bytes gas_limit = 4; // <=256 bit unsigned big endian - optional bytes toBin = 5; // recipient address (20 bytes, legacy firmware) - optional string toHex = 11; // recipient address (hex string, newer firmware) - optional bytes value = 6; // <=256 bit unsigned big endian (in wei) - optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) - optional uint32 data_length = 8; // Length of transaction payload - optional uint32 chain_id = 9; // Chain Id for EIP 155 - optional uint32 tx_type = 10; // (only for Wanchain) -} - -/** - * Response: Device asks for more data from transaction payload, or returns the signature. - * If data_length is set, device awaits that many more bytes of payload. - * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. - * @end - * @next EthereumTxAck - */ -message EthereumTxRequest { - optional uint32 data_length = 1; // Number of bytes being requested (<= 1024) - optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28) - optional bytes signature_r = 3; // Computed signature R component (256 bit) - optional bytes signature_s = 4; // Computed signature S component (256 bit) -} - -/** - * Request: Transaction payload data. - * @next EthereumTxRequest - */ -message EthereumTxAck { - optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) -} - -/** - * Request: Ask device to sign message - * @start - * @next EthereumMessageSignature - * @next Failure - */ -message EthereumSignMessage { - repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bytes message = 2; // message to be signed -} - -/** - * Response: Signed message - * @end - */ -message EthereumMessageSignature { - optional bytes addressBin = 1; // address used to sign the message (20 bytes, legacy firmware) - optional bytes signature = 2; // signature of the message - optional string addressHex = 3; // address used to sign the message (hex string, newer firmware) -} - -/** - * Request: Ask device to verify message - * @start - * @next Success - * @next Failure - */ -message EthereumVerifyMessage { - optional bytes addressBin = 1; // address to verify (20 bytes, legacy firmware) - optional bytes signature = 2; // signature to verify - optional bytes message = 3; // message to verify - optional string addressHex = 4; // address to verify (hex string, newer firmware) -} diff --git a/builder/accounts/usbwallet/trezor/messages-management.pb.go b/builder/accounts/usbwallet/trezor/messages-management.pb.go deleted file mode 100644 index 91bfca1e3..000000000 --- a/builder/accounts/usbwallet/trezor/messages-management.pb.go +++ /dev/null @@ -1,1621 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: messages-management.proto - -package trezor - -import ( - fmt "fmt" - math "math" - - proto "github.com/golang/protobuf/proto" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -// * -// Structure representing passphrase source -type ApplySettings_PassphraseSourceType int32 - -const ( - ApplySettings_ASK ApplySettings_PassphraseSourceType = 0 - ApplySettings_DEVICE ApplySettings_PassphraseSourceType = 1 - ApplySettings_HOST ApplySettings_PassphraseSourceType = 2 -) - -var ApplySettings_PassphraseSourceType_name = map[int32]string{ - 0: "ASK", - 1: "DEVICE", - 2: "HOST", -} - -var ApplySettings_PassphraseSourceType_value = map[string]int32{ - "ASK": 0, - "DEVICE": 1, - "HOST": 2, -} - -func (x ApplySettings_PassphraseSourceType) Enum() *ApplySettings_PassphraseSourceType { - p := new(ApplySettings_PassphraseSourceType) - *p = x - return p -} - -func (x ApplySettings_PassphraseSourceType) String() string { - return proto.EnumName(ApplySettings_PassphraseSourceType_name, int32(x)) -} - -func (x *ApplySettings_PassphraseSourceType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ApplySettings_PassphraseSourceType_value, data, "ApplySettings_PassphraseSourceType") - if err != nil { - return err - } - *x = ApplySettings_PassphraseSourceType(value) - return nil -} - -func (ApplySettings_PassphraseSourceType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{4, 0} -} - -// * -// Type of recovery procedure. These should be used as bitmask, e.g., -// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` -// listing every method supported by the host computer. -// -// Note that ScrambledWords must be supported by every implementation -// for backward compatibility; there is no way to not support it. -type RecoveryDevice_RecoveryDeviceType int32 - -const ( - // use powers of two when extending this field - RecoveryDevice_RecoveryDeviceType_ScrambledWords RecoveryDevice_RecoveryDeviceType = 0 - RecoveryDevice_RecoveryDeviceType_Matrix RecoveryDevice_RecoveryDeviceType = 1 -) - -var RecoveryDevice_RecoveryDeviceType_name = map[int32]string{ - 0: "RecoveryDeviceType_ScrambledWords", - 1: "RecoveryDeviceType_Matrix", -} - -var RecoveryDevice_RecoveryDeviceType_value = map[string]int32{ - "RecoveryDeviceType_ScrambledWords": 0, - "RecoveryDeviceType_Matrix": 1, -} - -func (x RecoveryDevice_RecoveryDeviceType) Enum() *RecoveryDevice_RecoveryDeviceType { - p := new(RecoveryDevice_RecoveryDeviceType) - *p = x - return p -} - -func (x RecoveryDevice_RecoveryDeviceType) String() string { - return proto.EnumName(RecoveryDevice_RecoveryDeviceType_name, int32(x)) -} - -func (x *RecoveryDevice_RecoveryDeviceType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RecoveryDevice_RecoveryDeviceType_value, data, "RecoveryDevice_RecoveryDeviceType") - if err != nil { - return err - } - *x = RecoveryDevice_RecoveryDeviceType(value) - return nil -} - -func (RecoveryDevice_RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{17, 0} -} - -// * -// Type of Recovery Word request -type WordRequest_WordRequestType int32 - -const ( - WordRequest_WordRequestType_Plain WordRequest_WordRequestType = 0 - WordRequest_WordRequestType_Matrix9 WordRequest_WordRequestType = 1 - WordRequest_WordRequestType_Matrix6 WordRequest_WordRequestType = 2 -) - -var WordRequest_WordRequestType_name = map[int32]string{ - 0: "WordRequestType_Plain", - 1: "WordRequestType_Matrix9", - 2: "WordRequestType_Matrix6", -} - -var WordRequest_WordRequestType_value = map[string]int32{ - "WordRequestType_Plain": 0, - "WordRequestType_Matrix9": 1, - "WordRequestType_Matrix6": 2, -} - -func (x WordRequest_WordRequestType) Enum() *WordRequest_WordRequestType { - p := new(WordRequest_WordRequestType) - *p = x - return p -} - -func (x WordRequest_WordRequestType) String() string { - return proto.EnumName(WordRequest_WordRequestType_name, int32(x)) -} - -func (x *WordRequest_WordRequestType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(WordRequest_WordRequestType_value, data, "WordRequest_WordRequestType") - if err != nil { - return err - } - *x = WordRequest_WordRequestType(value) - return nil -} - -func (WordRequest_WordRequestType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{18, 0} -} - -// * -// Request: Reset device to default state and ask for device details -// @start -// @next Features -type Initialize struct { - State []byte `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"` - SkipPassphrase *bool `protobuf:"varint,2,opt,name=skip_passphrase,json=skipPassphrase" json:"skip_passphrase,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Initialize) Reset() { *m = Initialize{} } -func (m *Initialize) String() string { return proto.CompactTextString(m) } -func (*Initialize) ProtoMessage() {} -func (*Initialize) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{0} -} - -func (m *Initialize) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Initialize.Unmarshal(m, b) -} -func (m *Initialize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Initialize.Marshal(b, m, deterministic) -} -func (m *Initialize) XXX_Merge(src proto.Message) { - xxx_messageInfo_Initialize.Merge(m, src) -} -func (m *Initialize) XXX_Size() int { - return xxx_messageInfo_Initialize.Size(m) -} -func (m *Initialize) XXX_DiscardUnknown() { - xxx_messageInfo_Initialize.DiscardUnknown(m) -} - -var xxx_messageInfo_Initialize proto.InternalMessageInfo - -func (m *Initialize) GetState() []byte { - if m != nil { - return m.State - } - return nil -} - -func (m *Initialize) GetSkipPassphrase() bool { - if m != nil && m.SkipPassphrase != nil { - return *m.SkipPassphrase - } - return false -} - -// * -// Request: Ask for device details (no device reset) -// @start -// @next Features -type GetFeatures struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetFeatures) Reset() { *m = GetFeatures{} } -func (m *GetFeatures) String() string { return proto.CompactTextString(m) } -func (*GetFeatures) ProtoMessage() {} -func (*GetFeatures) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{1} -} - -func (m *GetFeatures) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetFeatures.Unmarshal(m, b) -} -func (m *GetFeatures) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetFeatures.Marshal(b, m, deterministic) -} -func (m *GetFeatures) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetFeatures.Merge(m, src) -} -func (m *GetFeatures) XXX_Size() int { - return xxx_messageInfo_GetFeatures.Size(m) -} -func (m *GetFeatures) XXX_DiscardUnknown() { - xxx_messageInfo_GetFeatures.DiscardUnknown(m) -} - -var xxx_messageInfo_GetFeatures proto.InternalMessageInfo - -// * -// Response: Reports various information about the device -// @end -type Features struct { - Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"` - MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"` - MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"` - PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"` - BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"` - DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"` - PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"` - Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"` - Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"` - Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"` - BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"` - Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"` - PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"` - PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"` - FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"` - NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"` - Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"` - Model *string `protobuf:"bytes,21,opt,name=model" json:"model,omitempty"` - FwMajor *uint32 `protobuf:"varint,22,opt,name=fw_major,json=fwMajor" json:"fw_major,omitempty"` - FwMinor *uint32 `protobuf:"varint,23,opt,name=fw_minor,json=fwMinor" json:"fw_minor,omitempty"` - FwPatch *uint32 `protobuf:"varint,24,opt,name=fw_patch,json=fwPatch" json:"fw_patch,omitempty"` - FwVendor *string `protobuf:"bytes,25,opt,name=fw_vendor,json=fwVendor" json:"fw_vendor,omitempty"` - FwVendorKeys []byte `protobuf:"bytes,26,opt,name=fw_vendor_keys,json=fwVendorKeys" json:"fw_vendor_keys,omitempty"` - UnfinishedBackup *bool `protobuf:"varint,27,opt,name=unfinished_backup,json=unfinishedBackup" json:"unfinished_backup,omitempty"` - NoBackup *bool `protobuf:"varint,28,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Features) Reset() { *m = Features{} } -func (m *Features) String() string { return proto.CompactTextString(m) } -func (*Features) ProtoMessage() {} -func (*Features) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{2} -} - -func (m *Features) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Features.Unmarshal(m, b) -} -func (m *Features) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Features.Marshal(b, m, deterministic) -} -func (m *Features) XXX_Merge(src proto.Message) { - xxx_messageInfo_Features.Merge(m, src) -} -func (m *Features) XXX_Size() int { - return xxx_messageInfo_Features.Size(m) -} -func (m *Features) XXX_DiscardUnknown() { - xxx_messageInfo_Features.DiscardUnknown(m) -} - -var xxx_messageInfo_Features proto.InternalMessageInfo - -func (m *Features) GetVendor() string { - if m != nil && m.Vendor != nil { - return *m.Vendor - } - return "" -} - -func (m *Features) GetMajorVersion() uint32 { - if m != nil && m.MajorVersion != nil { - return *m.MajorVersion - } - return 0 -} - -func (m *Features) GetMinorVersion() uint32 { - if m != nil && m.MinorVersion != nil { - return *m.MinorVersion - } - return 0 -} - -func (m *Features) GetPatchVersion() uint32 { - if m != nil && m.PatchVersion != nil { - return *m.PatchVersion - } - return 0 -} - -func (m *Features) GetBootloaderMode() bool { - if m != nil && m.BootloaderMode != nil { - return *m.BootloaderMode - } - return false -} - -func (m *Features) GetDeviceId() string { - if m != nil && m.DeviceId != nil { - return *m.DeviceId - } - return "" -} - -func (m *Features) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *Features) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *Features) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return "" -} - -func (m *Features) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *Features) GetInitialized() bool { - if m != nil && m.Initialized != nil { - return *m.Initialized - } - return false -} - -func (m *Features) GetRevision() []byte { - if m != nil { - return m.Revision - } - return nil -} - -func (m *Features) GetBootloaderHash() []byte { - if m != nil { - return m.BootloaderHash - } - return nil -} - -func (m *Features) GetImported() bool { - if m != nil && m.Imported != nil { - return *m.Imported - } - return false -} - -func (m *Features) GetPinCached() bool { - if m != nil && m.PinCached != nil { - return *m.PinCached - } - return false -} - -func (m *Features) GetPassphraseCached() bool { - if m != nil && m.PassphraseCached != nil { - return *m.PassphraseCached - } - return false -} - -func (m *Features) GetFirmwarePresent() bool { - if m != nil && m.FirmwarePresent != nil { - return *m.FirmwarePresent - } - return false -} - -func (m *Features) GetNeedsBackup() bool { - if m != nil && m.NeedsBackup != nil { - return *m.NeedsBackup - } - return false -} - -func (m *Features) GetFlags() uint32 { - if m != nil && m.Flags != nil { - return *m.Flags - } - return 0 -} - -func (m *Features) GetModel() string { - if m != nil && m.Model != nil { - return *m.Model - } - return "" -} - -func (m *Features) GetFwMajor() uint32 { - if m != nil && m.FwMajor != nil { - return *m.FwMajor - } - return 0 -} - -func (m *Features) GetFwMinor() uint32 { - if m != nil && m.FwMinor != nil { - return *m.FwMinor - } - return 0 -} - -func (m *Features) GetFwPatch() uint32 { - if m != nil && m.FwPatch != nil { - return *m.FwPatch - } - return 0 -} - -func (m *Features) GetFwVendor() string { - if m != nil && m.FwVendor != nil { - return *m.FwVendor - } - return "" -} - -func (m *Features) GetFwVendorKeys() []byte { - if m != nil { - return m.FwVendorKeys - } - return nil -} - -func (m *Features) GetUnfinishedBackup() bool { - if m != nil && m.UnfinishedBackup != nil { - return *m.UnfinishedBackup - } - return false -} - -func (m *Features) GetNoBackup() bool { - if m != nil && m.NoBackup != nil { - return *m.NoBackup - } - return false -} - -// * -// Request: clear session (removes cached PIN, passphrase, etc). -// @start -// @next Success -type ClearSession struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ClearSession) Reset() { *m = ClearSession{} } -func (m *ClearSession) String() string { return proto.CompactTextString(m) } -func (*ClearSession) ProtoMessage() {} -func (*ClearSession) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{3} -} - -func (m *ClearSession) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ClearSession.Unmarshal(m, b) -} -func (m *ClearSession) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ClearSession.Marshal(b, m, deterministic) -} -func (m *ClearSession) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClearSession.Merge(m, src) -} -func (m *ClearSession) XXX_Size() int { - return xxx_messageInfo_ClearSession.Size(m) -} -func (m *ClearSession) XXX_DiscardUnknown() { - xxx_messageInfo_ClearSession.DiscardUnknown(m) -} - -var xxx_messageInfo_ClearSession proto.InternalMessageInfo - -// * -// Request: change language and/or label of the device -// @start -// @next Success -// @next Failure -type ApplySettings struct { - Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"` - Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"` - UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"` - Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"` - PassphraseSource *ApplySettings_PassphraseSourceType `protobuf:"varint,5,opt,name=passphrase_source,json=passphraseSource,enum=hw.trezor.messages.management.ApplySettings_PassphraseSourceType" json:"passphrase_source,omitempty"` - AutoLockDelayMs *uint32 `protobuf:"varint,6,opt,name=auto_lock_delay_ms,json=autoLockDelayMs" json:"auto_lock_delay_ms,omitempty"` - DisplayRotation *uint32 `protobuf:"varint,7,opt,name=display_rotation,json=displayRotation" json:"display_rotation,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ApplySettings) Reset() { *m = ApplySettings{} } -func (m *ApplySettings) String() string { return proto.CompactTextString(m) } -func (*ApplySettings) ProtoMessage() {} -func (*ApplySettings) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{4} -} - -func (m *ApplySettings) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ApplySettings.Unmarshal(m, b) -} -func (m *ApplySettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ApplySettings.Marshal(b, m, deterministic) -} -func (m *ApplySettings) XXX_Merge(src proto.Message) { - xxx_messageInfo_ApplySettings.Merge(m, src) -} -func (m *ApplySettings) XXX_Size() int { - return xxx_messageInfo_ApplySettings.Size(m) -} -func (m *ApplySettings) XXX_DiscardUnknown() { - xxx_messageInfo_ApplySettings.DiscardUnknown(m) -} - -var xxx_messageInfo_ApplySettings proto.InternalMessageInfo - -func (m *ApplySettings) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return "" -} - -func (m *ApplySettings) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *ApplySettings) GetUsePassphrase() bool { - if m != nil && m.UsePassphrase != nil { - return *m.UsePassphrase - } - return false -} - -func (m *ApplySettings) GetHomescreen() []byte { - if m != nil { - return m.Homescreen - } - return nil -} - -func (m *ApplySettings) GetPassphraseSource() ApplySettings_PassphraseSourceType { - if m != nil && m.PassphraseSource != nil { - return *m.PassphraseSource - } - return ApplySettings_ASK -} - -func (m *ApplySettings) GetAutoLockDelayMs() uint32 { - if m != nil && m.AutoLockDelayMs != nil { - return *m.AutoLockDelayMs - } - return 0 -} - -func (m *ApplySettings) GetDisplayRotation() uint32 { - if m != nil && m.DisplayRotation != nil { - return *m.DisplayRotation - } - return 0 -} - -// * -// Request: set flags of the device -// @start -// @next Success -// @next Failure -type ApplyFlags struct { - Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ApplyFlags) Reset() { *m = ApplyFlags{} } -func (m *ApplyFlags) String() string { return proto.CompactTextString(m) } -func (*ApplyFlags) ProtoMessage() {} -func (*ApplyFlags) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{5} -} - -func (m *ApplyFlags) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ApplyFlags.Unmarshal(m, b) -} -func (m *ApplyFlags) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ApplyFlags.Marshal(b, m, deterministic) -} -func (m *ApplyFlags) XXX_Merge(src proto.Message) { - xxx_messageInfo_ApplyFlags.Merge(m, src) -} -func (m *ApplyFlags) XXX_Size() int { - return xxx_messageInfo_ApplyFlags.Size(m) -} -func (m *ApplyFlags) XXX_DiscardUnknown() { - xxx_messageInfo_ApplyFlags.DiscardUnknown(m) -} - -var xxx_messageInfo_ApplyFlags proto.InternalMessageInfo - -func (m *ApplyFlags) GetFlags() uint32 { - if m != nil && m.Flags != nil { - return *m.Flags - } - return 0 -} - -// * -// Request: Starts workflow for setting/changing/removing the PIN -// @start -// @next Success -// @next Failure -type ChangePin struct { - Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ChangePin) Reset() { *m = ChangePin{} } -func (m *ChangePin) String() string { return proto.CompactTextString(m) } -func (*ChangePin) ProtoMessage() {} -func (*ChangePin) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{6} -} - -func (m *ChangePin) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ChangePin.Unmarshal(m, b) -} -func (m *ChangePin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ChangePin.Marshal(b, m, deterministic) -} -func (m *ChangePin) XXX_Merge(src proto.Message) { - xxx_messageInfo_ChangePin.Merge(m, src) -} -func (m *ChangePin) XXX_Size() int { - return xxx_messageInfo_ChangePin.Size(m) -} -func (m *ChangePin) XXX_DiscardUnknown() { - xxx_messageInfo_ChangePin.DiscardUnknown(m) -} - -var xxx_messageInfo_ChangePin proto.InternalMessageInfo - -func (m *ChangePin) GetRemove() bool { - if m != nil && m.Remove != nil { - return *m.Remove - } - return false -} - -// * -// Request: Test if the device is alive, device sends back the message in Success response -// @start -// @next Success -type Ping struct { - Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"` - ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"` - PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Ping) Reset() { *m = Ping{} } -func (m *Ping) String() string { return proto.CompactTextString(m) } -func (*Ping) ProtoMessage() {} -func (*Ping) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{7} -} - -func (m *Ping) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Ping.Unmarshal(m, b) -} -func (m *Ping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Ping.Marshal(b, m, deterministic) -} -func (m *Ping) XXX_Merge(src proto.Message) { - xxx_messageInfo_Ping.Merge(m, src) -} -func (m *Ping) XXX_Size() int { - return xxx_messageInfo_Ping.Size(m) -} -func (m *Ping) XXX_DiscardUnknown() { - xxx_messageInfo_Ping.DiscardUnknown(m) -} - -var xxx_messageInfo_Ping proto.InternalMessageInfo - -func (m *Ping) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -func (m *Ping) GetButtonProtection() bool { - if m != nil && m.ButtonProtection != nil { - return *m.ButtonProtection - } - return false -} - -func (m *Ping) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *Ping) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -// * -// Request: Abort last operation that required user interaction -// @start -// @next Failure -type Cancel struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Cancel) Reset() { *m = Cancel{} } -func (m *Cancel) String() string { return proto.CompactTextString(m) } -func (*Cancel) ProtoMessage() {} -func (*Cancel) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{8} -} - -func (m *Cancel) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Cancel.Unmarshal(m, b) -} -func (m *Cancel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Cancel.Marshal(b, m, deterministic) -} -func (m *Cancel) XXX_Merge(src proto.Message) { - xxx_messageInfo_Cancel.Merge(m, src) -} -func (m *Cancel) XXX_Size() int { - return xxx_messageInfo_Cancel.Size(m) -} -func (m *Cancel) XXX_DiscardUnknown() { - xxx_messageInfo_Cancel.DiscardUnknown(m) -} - -var xxx_messageInfo_Cancel proto.InternalMessageInfo - -// * -// Request: Request a sample of random data generated by hardware RNG. May be used for testing. -// @start -// @next Entropy -// @next Failure -type GetEntropy struct { - Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetEntropy) Reset() { *m = GetEntropy{} } -func (m *GetEntropy) String() string { return proto.CompactTextString(m) } -func (*GetEntropy) ProtoMessage() {} -func (*GetEntropy) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{9} -} - -func (m *GetEntropy) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetEntropy.Unmarshal(m, b) -} -func (m *GetEntropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetEntropy.Marshal(b, m, deterministic) -} -func (m *GetEntropy) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetEntropy.Merge(m, src) -} -func (m *GetEntropy) XXX_Size() int { - return xxx_messageInfo_GetEntropy.Size(m) -} -func (m *GetEntropy) XXX_DiscardUnknown() { - xxx_messageInfo_GetEntropy.DiscardUnknown(m) -} - -var xxx_messageInfo_GetEntropy proto.InternalMessageInfo - -func (m *GetEntropy) GetSize() uint32 { - if m != nil && m.Size != nil { - return *m.Size - } - return 0 -} - -// * -// Response: Reply with random data generated by internal RNG -// @end -type Entropy struct { - Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Entropy) Reset() { *m = Entropy{} } -func (m *Entropy) String() string { return proto.CompactTextString(m) } -func (*Entropy) ProtoMessage() {} -func (*Entropy) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{10} -} - -func (m *Entropy) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Entropy.Unmarshal(m, b) -} -func (m *Entropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Entropy.Marshal(b, m, deterministic) -} -func (m *Entropy) XXX_Merge(src proto.Message) { - xxx_messageInfo_Entropy.Merge(m, src) -} -func (m *Entropy) XXX_Size() int { - return xxx_messageInfo_Entropy.Size(m) -} -func (m *Entropy) XXX_DiscardUnknown() { - xxx_messageInfo_Entropy.DiscardUnknown(m) -} - -var xxx_messageInfo_Entropy proto.InternalMessageInfo - -func (m *Entropy) GetEntropy() []byte { - if m != nil { - return m.Entropy - } - return nil -} - -// * -// Request: Request device to wipe all sensitive data and settings -// @start -// @next Success -// @next Failure -type WipeDevice struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *WipeDevice) Reset() { *m = WipeDevice{} } -func (m *WipeDevice) String() string { return proto.CompactTextString(m) } -func (*WipeDevice) ProtoMessage() {} -func (*WipeDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{11} -} - -func (m *WipeDevice) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_WipeDevice.Unmarshal(m, b) -} -func (m *WipeDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_WipeDevice.Marshal(b, m, deterministic) -} -func (m *WipeDevice) XXX_Merge(src proto.Message) { - xxx_messageInfo_WipeDevice.Merge(m, src) -} -func (m *WipeDevice) XXX_Size() int { - return xxx_messageInfo_WipeDevice.Size(m) -} -func (m *WipeDevice) XXX_DiscardUnknown() { - xxx_messageInfo_WipeDevice.DiscardUnknown(m) -} - -var xxx_messageInfo_WipeDevice proto.InternalMessageInfo - -// * -// Request: Load seed and related internal settings from the computer -// @start -// @next Success -// @next Failure -type LoadDevice struct { - Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"` - Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"` - Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"` - PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` - SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"` - U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LoadDevice) Reset() { *m = LoadDevice{} } -func (m *LoadDevice) String() string { return proto.CompactTextString(m) } -func (*LoadDevice) ProtoMessage() {} -func (*LoadDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{12} -} - -func (m *LoadDevice) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LoadDevice.Unmarshal(m, b) -} -func (m *LoadDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LoadDevice.Marshal(b, m, deterministic) -} -func (m *LoadDevice) XXX_Merge(src proto.Message) { - xxx_messageInfo_LoadDevice.Merge(m, src) -} -func (m *LoadDevice) XXX_Size() int { - return xxx_messageInfo_LoadDevice.Size(m) -} -func (m *LoadDevice) XXX_DiscardUnknown() { - xxx_messageInfo_LoadDevice.DiscardUnknown(m) -} - -var xxx_messageInfo_LoadDevice proto.InternalMessageInfo - -const Default_LoadDevice_Language string = "english" - -func (m *LoadDevice) GetMnemonic() string { - if m != nil && m.Mnemonic != nil { - return *m.Mnemonic - } - return "" -} - -func (m *LoadDevice) GetNode() *HDNodeType { - if m != nil { - return m.Node - } - return nil -} - -func (m *LoadDevice) GetPin() string { - if m != nil && m.Pin != nil { - return *m.Pin - } - return "" -} - -func (m *LoadDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *LoadDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_LoadDevice_Language -} - -func (m *LoadDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *LoadDevice) GetSkipChecksum() bool { - if m != nil && m.SkipChecksum != nil { - return *m.SkipChecksum - } - return false -} - -func (m *LoadDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -// * -// Request: Ask device to do initialization involving user interaction -// @start -// @next EntropyRequest -// @next Failure -type ResetDevice struct { - DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"` - Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"` - PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"` - U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"` - NoBackup *bool `protobuf:"varint,9,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ResetDevice) Reset() { *m = ResetDevice{} } -func (m *ResetDevice) String() string { return proto.CompactTextString(m) } -func (*ResetDevice) ProtoMessage() {} -func (*ResetDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{13} -} - -func (m *ResetDevice) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ResetDevice.Unmarshal(m, b) -} -func (m *ResetDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ResetDevice.Marshal(b, m, deterministic) -} -func (m *ResetDevice) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResetDevice.Merge(m, src) -} -func (m *ResetDevice) XXX_Size() int { - return xxx_messageInfo_ResetDevice.Size(m) -} -func (m *ResetDevice) XXX_DiscardUnknown() { - xxx_messageInfo_ResetDevice.DiscardUnknown(m) -} - -var xxx_messageInfo_ResetDevice proto.InternalMessageInfo - -const Default_ResetDevice_Strength uint32 = 256 -const Default_ResetDevice_Language string = "english" - -func (m *ResetDevice) GetDisplayRandom() bool { - if m != nil && m.DisplayRandom != nil { - return *m.DisplayRandom - } - return false -} - -func (m *ResetDevice) GetStrength() uint32 { - if m != nil && m.Strength != nil { - return *m.Strength - } - return Default_ResetDevice_Strength -} - -func (m *ResetDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *ResetDevice) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *ResetDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_ResetDevice_Language -} - -func (m *ResetDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *ResetDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -func (m *ResetDevice) GetSkipBackup() bool { - if m != nil && m.SkipBackup != nil { - return *m.SkipBackup - } - return false -} - -func (m *ResetDevice) GetNoBackup() bool { - if m != nil && m.NoBackup != nil { - return *m.NoBackup - } - return false -} - -// * -// Request: Perform backup of the device seed if not backed up using ResetDevice -// @start -// @next Success -type BackupDevice struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *BackupDevice) Reset() { *m = BackupDevice{} } -func (m *BackupDevice) String() string { return proto.CompactTextString(m) } -func (*BackupDevice) ProtoMessage() {} -func (*BackupDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{14} -} - -func (m *BackupDevice) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_BackupDevice.Unmarshal(m, b) -} -func (m *BackupDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_BackupDevice.Marshal(b, m, deterministic) -} -func (m *BackupDevice) XXX_Merge(src proto.Message) { - xxx_messageInfo_BackupDevice.Merge(m, src) -} -func (m *BackupDevice) XXX_Size() int { - return xxx_messageInfo_BackupDevice.Size(m) -} -func (m *BackupDevice) XXX_DiscardUnknown() { - xxx_messageInfo_BackupDevice.DiscardUnknown(m) -} - -var xxx_messageInfo_BackupDevice proto.InternalMessageInfo - -// * -// Response: Ask for additional entropy from host computer -// @next EntropyAck -type EntropyRequest struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EntropyRequest) Reset() { *m = EntropyRequest{} } -func (m *EntropyRequest) String() string { return proto.CompactTextString(m) } -func (*EntropyRequest) ProtoMessage() {} -func (*EntropyRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{15} -} - -func (m *EntropyRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EntropyRequest.Unmarshal(m, b) -} -func (m *EntropyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EntropyRequest.Marshal(b, m, deterministic) -} -func (m *EntropyRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_EntropyRequest.Merge(m, src) -} -func (m *EntropyRequest) XXX_Size() int { - return xxx_messageInfo_EntropyRequest.Size(m) -} -func (m *EntropyRequest) XXX_DiscardUnknown() { - xxx_messageInfo_EntropyRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_EntropyRequest proto.InternalMessageInfo - -// * -// Request: Provide additional entropy for seed generation function -// @next Success -type EntropyAck struct { - Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EntropyAck) Reset() { *m = EntropyAck{} } -func (m *EntropyAck) String() string { return proto.CompactTextString(m) } -func (*EntropyAck) ProtoMessage() {} -func (*EntropyAck) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{16} -} - -func (m *EntropyAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EntropyAck.Unmarshal(m, b) -} -func (m *EntropyAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EntropyAck.Marshal(b, m, deterministic) -} -func (m *EntropyAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_EntropyAck.Merge(m, src) -} -func (m *EntropyAck) XXX_Size() int { - return xxx_messageInfo_EntropyAck.Size(m) -} -func (m *EntropyAck) XXX_DiscardUnknown() { - xxx_messageInfo_EntropyAck.DiscardUnknown(m) -} - -var xxx_messageInfo_EntropyAck proto.InternalMessageInfo - -func (m *EntropyAck) GetEntropy() []byte { - if m != nil { - return m.Entropy - } - return nil -} - -// * -// Request: Start recovery workflow asking user for specific words of mnemonic -// Used to recovery device safely even on untrusted computer. -// @start -// @next WordRequest -type RecoveryDevice struct { - WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"` - PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"` - PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"` - Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"` - Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"` - EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"` - // 7 reserved for unused recovery method - Type *RecoveryDevice_RecoveryDeviceType `protobuf:"varint,8,opt,name=type,enum=hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType" json:"type,omitempty"` - U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *RecoveryDevice) Reset() { *m = RecoveryDevice{} } -func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) } -func (*RecoveryDevice) ProtoMessage() {} -func (*RecoveryDevice) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{17} -} - -func (m *RecoveryDevice) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RecoveryDevice.Unmarshal(m, b) -} -func (m *RecoveryDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RecoveryDevice.Marshal(b, m, deterministic) -} -func (m *RecoveryDevice) XXX_Merge(src proto.Message) { - xxx_messageInfo_RecoveryDevice.Merge(m, src) -} -func (m *RecoveryDevice) XXX_Size() int { - return xxx_messageInfo_RecoveryDevice.Size(m) -} -func (m *RecoveryDevice) XXX_DiscardUnknown() { - xxx_messageInfo_RecoveryDevice.DiscardUnknown(m) -} - -var xxx_messageInfo_RecoveryDevice proto.InternalMessageInfo - -const Default_RecoveryDevice_Language string = "english" - -func (m *RecoveryDevice) GetWordCount() uint32 { - if m != nil && m.WordCount != nil { - return *m.WordCount - } - return 0 -} - -func (m *RecoveryDevice) GetPassphraseProtection() bool { - if m != nil && m.PassphraseProtection != nil { - return *m.PassphraseProtection - } - return false -} - -func (m *RecoveryDevice) GetPinProtection() bool { - if m != nil && m.PinProtection != nil { - return *m.PinProtection - } - return false -} - -func (m *RecoveryDevice) GetLanguage() string { - if m != nil && m.Language != nil { - return *m.Language - } - return Default_RecoveryDevice_Language -} - -func (m *RecoveryDevice) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *RecoveryDevice) GetEnforceWordlist() bool { - if m != nil && m.EnforceWordlist != nil { - return *m.EnforceWordlist - } - return false -} - -func (m *RecoveryDevice) GetType() RecoveryDevice_RecoveryDeviceType { - if m != nil && m.Type != nil { - return *m.Type - } - return RecoveryDevice_RecoveryDeviceType_ScrambledWords -} - -func (m *RecoveryDevice) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -func (m *RecoveryDevice) GetDryRun() bool { - if m != nil && m.DryRun != nil { - return *m.DryRun - } - return false -} - -// * -// Response: Device is waiting for user to enter word of the mnemonic -// Its position is shown only on device's internal display. -// @next WordAck -type WordRequest struct { - Type *WordRequest_WordRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.management.WordRequest_WordRequestType" json:"type,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *WordRequest) Reset() { *m = WordRequest{} } -func (m *WordRequest) String() string { return proto.CompactTextString(m) } -func (*WordRequest) ProtoMessage() {} -func (*WordRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{18} -} - -func (m *WordRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_WordRequest.Unmarshal(m, b) -} -func (m *WordRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_WordRequest.Marshal(b, m, deterministic) -} -func (m *WordRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_WordRequest.Merge(m, src) -} -func (m *WordRequest) XXX_Size() int { - return xxx_messageInfo_WordRequest.Size(m) -} -func (m *WordRequest) XXX_DiscardUnknown() { - xxx_messageInfo_WordRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_WordRequest proto.InternalMessageInfo - -func (m *WordRequest) GetType() WordRequest_WordRequestType { - if m != nil && m.Type != nil { - return *m.Type - } - return WordRequest_WordRequestType_Plain -} - -// * -// Request: Computer replies with word from the mnemonic -// @next WordRequest -// @next Success -// @next Failure -type WordAck struct { - Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *WordAck) Reset() { *m = WordAck{} } -func (m *WordAck) String() string { return proto.CompactTextString(m) } -func (*WordAck) ProtoMessage() {} -func (*WordAck) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{19} -} - -func (m *WordAck) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_WordAck.Unmarshal(m, b) -} -func (m *WordAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_WordAck.Marshal(b, m, deterministic) -} -func (m *WordAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_WordAck.Merge(m, src) -} -func (m *WordAck) XXX_Size() int { - return xxx_messageInfo_WordAck.Size(m) -} -func (m *WordAck) XXX_DiscardUnknown() { - xxx_messageInfo_WordAck.DiscardUnknown(m) -} - -var xxx_messageInfo_WordAck proto.InternalMessageInfo - -func (m *WordAck) GetWord() string { - if m != nil && m.Word != nil { - return *m.Word - } - return "" -} - -// * -// Request: Set U2F counter -// @start -// @next Success -type SetU2FCounter struct { - U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SetU2FCounter) Reset() { *m = SetU2FCounter{} } -func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) } -func (*SetU2FCounter) ProtoMessage() {} -func (*SetU2FCounter) Descriptor() ([]byte, []int) { - return fileDescriptor_0c720c20d27aa029, []int{20} -} - -func (m *SetU2FCounter) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SetU2FCounter.Unmarshal(m, b) -} -func (m *SetU2FCounter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SetU2FCounter.Marshal(b, m, deterministic) -} -func (m *SetU2FCounter) XXX_Merge(src proto.Message) { - xxx_messageInfo_SetU2FCounter.Merge(m, src) -} -func (m *SetU2FCounter) XXX_Size() int { - return xxx_messageInfo_SetU2FCounter.Size(m) -} -func (m *SetU2FCounter) XXX_DiscardUnknown() { - xxx_messageInfo_SetU2FCounter.DiscardUnknown(m) -} - -var xxx_messageInfo_SetU2FCounter proto.InternalMessageInfo - -func (m *SetU2FCounter) GetU2FCounter() uint32 { - if m != nil && m.U2FCounter != nil { - return *m.U2FCounter - } - return 0 -} - -func init() { - proto.RegisterEnum("hw.trezor.messages.management.ApplySettings_PassphraseSourceType", ApplySettings_PassphraseSourceType_name, ApplySettings_PassphraseSourceType_value) - proto.RegisterEnum("hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType", RecoveryDevice_RecoveryDeviceType_name, RecoveryDevice_RecoveryDeviceType_value) - proto.RegisterEnum("hw.trezor.messages.management.WordRequest_WordRequestType", WordRequest_WordRequestType_name, WordRequest_WordRequestType_value) - proto.RegisterType((*Initialize)(nil), "hw.trezor.messages.management.Initialize") - proto.RegisterType((*GetFeatures)(nil), "hw.trezor.messages.management.GetFeatures") - proto.RegisterType((*Features)(nil), "hw.trezor.messages.management.Features") - proto.RegisterType((*ClearSession)(nil), "hw.trezor.messages.management.ClearSession") - proto.RegisterType((*ApplySettings)(nil), "hw.trezor.messages.management.ApplySettings") - proto.RegisterType((*ApplyFlags)(nil), "hw.trezor.messages.management.ApplyFlags") - proto.RegisterType((*ChangePin)(nil), "hw.trezor.messages.management.ChangePin") - proto.RegisterType((*Ping)(nil), "hw.trezor.messages.management.Ping") - proto.RegisterType((*Cancel)(nil), "hw.trezor.messages.management.Cancel") - proto.RegisterType((*GetEntropy)(nil), "hw.trezor.messages.management.GetEntropy") - proto.RegisterType((*Entropy)(nil), "hw.trezor.messages.management.Entropy") - proto.RegisterType((*WipeDevice)(nil), "hw.trezor.messages.management.WipeDevice") - proto.RegisterType((*LoadDevice)(nil), "hw.trezor.messages.management.LoadDevice") - proto.RegisterType((*ResetDevice)(nil), "hw.trezor.messages.management.ResetDevice") - proto.RegisterType((*BackupDevice)(nil), "hw.trezor.messages.management.BackupDevice") - proto.RegisterType((*EntropyRequest)(nil), "hw.trezor.messages.management.EntropyRequest") - proto.RegisterType((*EntropyAck)(nil), "hw.trezor.messages.management.EntropyAck") - proto.RegisterType((*RecoveryDevice)(nil), "hw.trezor.messages.management.RecoveryDevice") - proto.RegisterType((*WordRequest)(nil), "hw.trezor.messages.management.WordRequest") - proto.RegisterType((*WordAck)(nil), "hw.trezor.messages.management.WordAck") - proto.RegisterType((*SetU2FCounter)(nil), "hw.trezor.messages.management.SetU2FCounter") -} - -func init() { proto.RegisterFile("messages-management.proto", fileDescriptor_0c720c20d27aa029) } - -var fileDescriptor_0c720c20d27aa029 = []byte{ - // 1393 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xdd, 0x6e, 0xdb, 0xc8, - 0x15, 0x8e, 0x7e, 0x62, 0x49, 0xc7, 0xfa, 0xcb, 0xd4, 0x8e, 0xe9, 0xb8, 0x6e, 0x1c, 0xba, 0x6e, - 0x12, 0x04, 0x15, 0x0a, 0x17, 0x09, 0x90, 0x5c, 0x14, 0x75, 0xec, 0xfc, 0x21, 0x71, 0x6a, 0xd0, - 0x6e, 0x02, 0xf4, 0x86, 0x18, 0x91, 0x47, 0xd2, 0xd4, 0xe4, 0x0c, 0xcb, 0x19, 0xda, 0x55, 0x5e, - 0x60, 0x6f, 0xf6, 0x45, 0x16, 0xfb, 0x1c, 0x7b, 0xb5, 0xcf, 0xb0, 0xef, 0xb2, 0x98, 0x19, 0x52, - 0xa2, 0x65, 0x3b, 0x46, 0x76, 0xef, 0xe6, 0x7c, 0xe7, 0xe3, 0x68, 0xce, 0x77, 0xbe, 0x39, 0x63, - 0xc3, 0x7a, 0x8c, 0x52, 0xd2, 0x31, 0xca, 0xbf, 0xc6, 0x94, 0xd3, 0x31, 0xc6, 0xc8, 0xd5, 0x20, - 0x49, 0x85, 0x12, 0x64, 0x73, 0x72, 0x3e, 0x50, 0x29, 0x7e, 0x11, 0xe9, 0xa0, 0x20, 0x0d, 0xe6, - 0xa4, 0x7b, 0xab, 0xb3, 0x2f, 0x03, 0x11, 0xc7, 0x82, 0xdb, 0xaf, 0xdc, 0xf7, 0x00, 0xef, 0x38, - 0x53, 0x8c, 0x46, 0xec, 0x0b, 0x92, 0x15, 0xb8, 0x2d, 0x15, 0x55, 0xe8, 0x54, 0xb6, 0x2a, 0x8f, - 0xda, 0x9e, 0x0d, 0xc8, 0x43, 0xe8, 0xc9, 0x53, 0x96, 0xf8, 0x09, 0x95, 0x32, 0x99, 0xa4, 0x54, - 0xa2, 0x53, 0xdd, 0xaa, 0x3c, 0x6a, 0x7a, 0x5d, 0x0d, 0x1f, 0xcd, 0x50, 0xb7, 0x03, 0xcb, 0x6f, - 0x50, 0xbd, 0x46, 0xaa, 0xb2, 0x14, 0xa5, 0xfb, 0x7d, 0x03, 0x9a, 0x45, 0x40, 0xee, 0xc2, 0xd2, - 0x19, 0xf2, 0x50, 0xa4, 0x66, 0xef, 0x96, 0x97, 0x47, 0x64, 0x1b, 0x3a, 0x31, 0xfd, 0xaf, 0x48, - 0xfd, 0x33, 0x4c, 0x25, 0x13, 0xdc, 0x6c, 0xdd, 0xf1, 0xda, 0x06, 0xfc, 0x64, 0x31, 0x43, 0x62, - 0xbc, 0x44, 0xaa, 0xe5, 0x24, 0x0d, 0x96, 0x48, 0x09, 0x55, 0xc1, 0x64, 0x46, 0xaa, 0x5b, 0x92, - 0x01, 0x0b, 0xd2, 0x43, 0xe8, 0x0d, 0x85, 0x50, 0x91, 0xa0, 0x21, 0xa6, 0x7e, 0x2c, 0x42, 0x74, - 0x6e, 0xdb, 0x5a, 0xe6, 0xf0, 0xa1, 0x08, 0x91, 0x6c, 0x40, 0x2b, 0xc4, 0x33, 0x16, 0xa0, 0xcf, - 0x42, 0x67, 0xc9, 0x1c, 0xb9, 0x69, 0x81, 0x77, 0x21, 0xd9, 0x81, 0x6e, 0xc2, 0xb8, 0xaf, 0x25, - 0xc4, 0x40, 0xe9, 0xdf, 0x6a, 0x98, 0x4d, 0x3a, 0x09, 0xe3, 0x47, 0x33, 0x90, 0xfc, 0x1d, 0x56, - 0xe7, 0x9a, 0x95, 0xd9, 0x4d, 0xc3, 0x5e, 0x99, 0x27, 0x4b, 0x1f, 0xdd, 0x83, 0x66, 0x44, 0xf9, - 0x38, 0xa3, 0x63, 0x74, 0x5a, 0xf6, 0x77, 0x8b, 0x58, 0xf7, 0x27, 0xa2, 0x43, 0x8c, 0x1c, 0x30, - 0x09, 0x1b, 0x90, 0x2d, 0x58, 0x66, 0xb3, 0x1e, 0x86, 0x4e, 0xdb, 0x6c, 0x5e, 0x86, 0xf4, 0x9e, - 0x29, 0x9e, 0x31, 0xa3, 0x4a, 0xc7, 0xb4, 0x76, 0x16, 0x2f, 0x28, 0x32, 0xa1, 0x72, 0xe2, 0x74, - 0x0d, 0xa5, 0xa4, 0xc8, 0x5b, 0x2a, 0x27, 0x7a, 0x13, 0x16, 0x27, 0x22, 0x55, 0x18, 0x3a, 0x3d, - 0xf3, 0x1b, 0xb3, 0x98, 0x6c, 0x02, 0x68, 0x41, 0x02, 0x1a, 0x4c, 0x30, 0x74, 0xfa, 0x26, 0xdb, - 0x4a, 0x18, 0xdf, 0x37, 0x00, 0x79, 0x02, 0x77, 0x4a, 0x42, 0xe4, 0xac, 0x3b, 0x86, 0xd5, 0x9f, - 0x27, 0x72, 0xf2, 0x63, 0xe8, 0x8f, 0x58, 0x1a, 0x9f, 0xd3, 0x54, 0x6b, 0x86, 0x12, 0xb9, 0x72, - 0x88, 0xe1, 0xf6, 0x0a, 0xfc, 0xc8, 0xc2, 0xe4, 0x01, 0xb4, 0x39, 0x62, 0x28, 0xfd, 0x21, 0x0d, - 0x4e, 0xb3, 0xc4, 0xf9, 0x83, 0x2d, 0xdd, 0x60, 0x2f, 0x0d, 0xa4, 0x25, 0x1b, 0x45, 0x74, 0x2c, - 0x9d, 0x15, 0xe3, 0x06, 0x1b, 0x68, 0x54, 0xf7, 0x3e, 0x72, 0x56, 0xad, 0x90, 0x26, 0x20, 0xeb, - 0xd0, 0x1c, 0x9d, 0xfb, 0xc6, 0x79, 0xce, 0x5d, 0x43, 0x6f, 0x8c, 0xce, 0x0f, 0x75, 0x58, 0xa4, - 0xb4, 0xdf, 0x9c, 0xb5, 0x59, 0x4a, 0x87, 0x79, 0xca, 0xb8, 0xcc, 0x71, 0x8a, 0xd4, 0x91, 0x0e, - 0xb5, 0x89, 0x46, 0xe7, 0x7e, 0xee, 0xfb, 0x75, 0xdb, 0xcc, 0xd1, 0xf9, 0x27, 0xeb, 0xfc, 0x3f, - 0x43, 0x77, 0x96, 0xf4, 0x4f, 0x71, 0x2a, 0x9d, 0x7b, 0x46, 0xf7, 0x76, 0xc1, 0x78, 0x8f, 0x53, - 0xa9, 0xa5, 0xcb, 0xf8, 0x88, 0x71, 0x26, 0x27, 0x18, 0x16, 0x75, 0x6e, 0x58, 0xe9, 0xe6, 0x89, - 0xbc, 0xd8, 0x0d, 0x68, 0x71, 0x51, 0x90, 0xfe, 0x68, 0x7b, 0xc4, 0x85, 0x4d, 0xba, 0x5d, 0x68, - 0xef, 0x47, 0x48, 0xd3, 0x63, 0x94, 0xba, 0xf1, 0xee, 0x77, 0x35, 0xe8, 0xec, 0x25, 0x49, 0x34, - 0x3d, 0x46, 0xa5, 0x18, 0x1f, 0xcb, 0x0b, 0xd6, 0xab, 0x5c, 0x67, 0xbd, 0x6a, 0xd9, 0x7a, 0x3b, - 0xd0, 0xcd, 0xb4, 0xb5, 0xe7, 0x93, 0xa1, 0x66, 0x2f, 0x42, 0x26, 0x71, 0x3e, 0x18, 0xc8, 0x9f, - 0x00, 0x26, 0x22, 0x46, 0x19, 0xa4, 0x88, 0xf6, 0x5e, 0xb6, 0xbd, 0x12, 0x42, 0xf8, 0x05, 0x7f, - 0x48, 0x91, 0xa5, 0x81, 0xbd, 0x97, 0xdd, 0xdd, 0xbd, 0xc1, 0x57, 0xe7, 0xda, 0xe0, 0x42, 0x05, - 0x83, 0xf9, 0x6f, 0x1e, 0x9b, 0x4d, 0x4e, 0xa6, 0x09, 0x96, 0x2d, 0x66, 0x51, 0xf2, 0x04, 0x08, - 0xcd, 0x94, 0xf0, 0x23, 0x11, 0x9c, 0xfa, 0x21, 0x46, 0x74, 0xea, 0xc7, 0xd2, 0xdc, 0xf2, 0x8e, - 0xd7, 0xd3, 0x99, 0x0f, 0x22, 0x38, 0x3d, 0xd0, 0xf8, 0xa1, 0xd4, 0x7e, 0x0c, 0x99, 0x4c, 0x34, - 0x29, 0x15, 0x8a, 0xce, 0xae, 0x7b, 0xc7, 0xeb, 0xe5, 0xb8, 0x97, 0xc3, 0xee, 0x53, 0x58, 0xb9, - 0xea, 0x04, 0xa4, 0x01, 0xb5, 0xbd, 0xe3, 0xf7, 0xfd, 0x5b, 0x04, 0x60, 0xe9, 0xe0, 0xd5, 0xa7, - 0x77, 0xfb, 0xaf, 0xfa, 0x15, 0xd2, 0x84, 0xfa, 0xdb, 0x7f, 0x1d, 0x9f, 0xf4, 0xab, 0xae, 0x0b, - 0x60, 0xca, 0x78, 0x5d, 0x78, 0xd3, 0x3a, 0xb6, 0x52, 0x72, 0xac, 0xbb, 0x0d, 0xad, 0xfd, 0x09, - 0xe5, 0x63, 0x3c, 0x62, 0x5c, 0x0f, 0xd3, 0x14, 0x63, 0x71, 0x66, 0xdb, 0xd4, 0xf4, 0xf2, 0xc8, - 0xfd, 0xa1, 0x02, 0xf5, 0x23, 0xc6, 0xc7, 0xc4, 0x81, 0x46, 0x2e, 0x56, 0xde, 0xc8, 0x22, 0xd4, - 0x7e, 0x1a, 0x66, 0x4a, 0x89, 0x0b, 0xd3, 0xcb, 0x8e, 0xf3, 0xbe, 0x4d, 0x94, 0x66, 0xd1, 0xe5, - 0x39, 0x57, 0xfb, 0xa6, 0x39, 0x57, 0xbf, 0x7e, 0xce, 0xb9, 0x4d, 0x58, 0xda, 0xa7, 0x3c, 0xc0, - 0xc8, 0xdd, 0x02, 0x78, 0x83, 0xea, 0x15, 0x57, 0xa9, 0x48, 0xa6, 0x84, 0x40, 0x5d, 0xb2, 0x2f, - 0xfa, 0xdc, 0xd5, 0x47, 0x1d, 0xcf, 0xac, 0xdd, 0x6d, 0x68, 0x14, 0x69, 0x07, 0x1a, 0x68, 0x97, - 0x86, 0xd1, 0xf6, 0x8a, 0xd0, 0x6d, 0x03, 0x7c, 0x66, 0x09, 0x1e, 0x98, 0x21, 0xed, 0xfe, 0x58, - 0x05, 0xf8, 0x20, 0x68, 0x68, 0x43, 0x6d, 0xed, 0x98, 0x63, 0x2c, 0x38, 0x0b, 0x0a, 0x6b, 0x17, - 0x31, 0x79, 0x0e, 0x75, 0xae, 0x1f, 0x02, 0xad, 0xc2, 0xf2, 0xee, 0xce, 0x55, 0x86, 0xcb, 0xdf, - 0xcc, 0xb7, 0x07, 0x1f, 0x45, 0x68, 0x4d, 0x65, 0x3e, 0x21, 0x7d, 0xa8, 0x25, 0xcc, 0xaa, 0xd2, - 0xf2, 0xf4, 0xf2, 0x37, 0x69, 0x41, 0xb6, 0x4b, 0x17, 0x4f, 0xdb, 0xbe, 0xf5, 0xa2, 0x81, 0x7c, - 0x1c, 0x31, 0x39, 0xb9, 0xea, 0x06, 0x2e, 0x95, 0x6f, 0xe0, 0x36, 0x74, 0xcc, 0xe3, 0x1c, 0x4c, - 0x30, 0x38, 0x95, 0x59, 0x9c, 0xbf, 0x44, 0x6d, 0x0d, 0xee, 0xe7, 0x18, 0xb9, 0x0f, 0xcb, 0xd9, - 0xee, 0xc8, 0x0f, 0x44, 0xc6, 0x15, 0xa6, 0xe6, 0xf9, 0xe9, 0x78, 0x90, 0xed, 0x8e, 0xf6, 0x2d, - 0xe2, 0xfe, 0x5c, 0x85, 0x65, 0x0f, 0x25, 0xaa, 0x5c, 0xae, 0x1d, 0xe8, 0xce, 0x3c, 0x4f, 0x79, - 0x28, 0xe2, 0xdc, 0x68, 0x9d, 0xc2, 0xf1, 0x06, 0x24, 0xf7, 0xa1, 0x29, 0x55, 0x8a, 0x7c, 0xac, - 0x26, 0xf6, 0xdd, 0x7e, 0x51, 0xdb, 0x7d, 0xfa, 0xcc, 0x9b, 0x81, 0xd7, 0xab, 0x51, 0xfb, 0x8a, - 0x1a, 0x97, 0x5d, 0x57, 0xbf, 0xca, 0x75, 0xbf, 0x43, 0xb4, 0x05, 0x3d, 0x1a, 0x8b, 0x7a, 0x68, - 0x82, 0x51, 0x35, 0x1f, 0xa5, 0xf6, 0xbd, 0x06, 0x0d, 0x5d, 0x35, 0x69, 0x5b, 0x97, 0x27, 0xad, - 0x5d, 0xe5, 0x5e, 0xec, 0x43, 0x37, 0xb7, 0xaf, 0x87, 0xff, 0xcb, 0x50, 0x2a, 0xf7, 0x2f, 0x00, - 0x39, 0xb2, 0x17, 0x9c, 0x5e, 0xf4, 0x74, 0xa5, 0xec, 0xe9, 0x5f, 0x6a, 0xd0, 0xf5, 0x30, 0x10, - 0x67, 0x98, 0x4e, 0xf3, 0xd6, 0x6c, 0x02, 0x9c, 0x8b, 0x34, 0xb4, 0x87, 0xcf, 0x67, 0x44, 0x4b, - 0x23, 0xe6, 0xec, 0xd7, 0x2b, 0x5e, 0xfd, 0x26, 0xc5, 0x6b, 0x37, 0x29, 0x5e, 0xbf, 0x51, 0xf1, - 0xdb, 0x65, 0xc5, 0x1f, 0x43, 0x1f, 0xf9, 0x48, 0xa4, 0x01, 0xfa, 0xfa, 0xac, 0x11, 0x93, 0xca, - 0xb4, 0xa4, 0xe9, 0xf5, 0x72, 0xfc, 0x73, 0x0e, 0x93, 0x13, 0xa8, 0xab, 0x69, 0x82, 0x46, 0xf4, - 0xee, 0xee, 0x3f, 0x6f, 0x98, 0xff, 0x17, 0xd5, 0x59, 0x08, 0xed, 0x4d, 0xd5, 0xbb, 0x2d, 0xb6, - 0xbc, 0x75, 0xa9, 0xe5, 0x6b, 0xd0, 0x08, 0xd3, 0xa9, 0x9f, 0x66, 0xdc, 0xfc, 0x75, 0xd5, 0xf4, - 0x96, 0xc2, 0x74, 0xea, 0x65, 0xdc, 0xfd, 0x0f, 0x90, 0xcb, 0xbb, 0x92, 0x1d, 0x78, 0x70, 0x19, - 0xf5, 0x8f, 0x83, 0x94, 0xc6, 0xc3, 0x08, 0x43, 0x5d, 0x8d, 0xec, 0xdf, 0x22, 0x9b, 0xb0, 0x7e, - 0x05, 0xed, 0x90, 0xaa, 0x94, 0xfd, 0xbf, 0x5f, 0x71, 0x7f, 0xaa, 0xc0, 0xb2, 0xa6, 0xe6, 0xbe, - 0x20, 0x1f, 0xf3, 0xda, 0x2b, 0xa6, 0xf6, 0x17, 0x37, 0xd4, 0x5e, 0xfa, 0xb2, 0xbc, 0x9e, 0x57, - 0xed, 0x8e, 0xa0, 0xb7, 0x90, 0x20, 0xeb, 0xb0, 0xba, 0x00, 0xf9, 0x47, 0x11, 0x65, 0xbc, 0x7f, - 0x8b, 0x6c, 0xc0, 0xda, 0x62, 0xca, 0x9e, 0xf4, 0x79, 0xbf, 0x72, 0x7d, 0xf2, 0x59, 0xbf, 0xea, - 0x6e, 0x42, 0x43, 0x27, 0xb5, 0x99, 0x09, 0xd4, 0x75, 0x87, 0xcd, 0x74, 0x6e, 0x79, 0x66, 0xed, - 0xfe, 0x0d, 0x3a, 0xc7, 0xa8, 0xfe, 0xbd, 0xfb, 0xba, 0x74, 0xbf, 0xca, 0xdd, 0xa8, 0x2c, 0x76, - 0xe3, 0xe5, 0x3f, 0x60, 0x3b, 0x10, 0xf1, 0x40, 0x52, 0x25, 0xe4, 0x84, 0x45, 0x74, 0x28, 0x0b, - 0x21, 0x22, 0x36, 0xb4, 0xff, 0xbb, 0x0c, 0xb3, 0xd1, 0xcb, 0xb5, 0x13, 0x03, 0x1e, 0x5a, 0x71, - 0x0e, 0x67, 0xd2, 0xfc, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x6e, 0xfc, 0x59, 0x29, 0x0d, 0x00, - 0x00, -} diff --git a/builder/accounts/usbwallet/trezor/messages-management.proto b/builder/accounts/usbwallet/trezor/messages-management.proto deleted file mode 100644 index 0ab825a1b..000000000 --- a/builder/accounts/usbwallet/trezor/messages-management.proto +++ /dev/null @@ -1,289 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto -// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. - -syntax = "proto2"; -package hw.trezor.messages.management; - -// Sugar for easier handling in Java -option java_package = "com.satoshilabs.trezor.lib.protobuf"; -option java_outer_classname = "TrezorMessageManagement"; - -import "messages-common.proto"; - -/** - * Request: Reset device to default state and ask for device details - * @start - * @next Features - */ -message Initialize { - optional bytes state = 1; // assumed device state, clear session if set and different - optional bool skip_passphrase = 2; // this session should always assume empty passphrase -} - -/** - * Request: Ask for device details (no device reset) - * @start - * @next Features - */ -message GetFeatures { -} - -/** - * Response: Reports various information about the device - * @end - */ -message Features { - optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io" - optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1 - optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0 - optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0 - optional bool bootloader_mode = 5; // is device in bootloader mode? - optional string device_id = 6; // device's unique identifier - optional bool pin_protection = 7; // is device protected by PIN? - optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase? - optional string language = 9; // device language - optional string label = 10; // device description label - optional bool initialized = 12; // does device contain seed? - optional bytes revision = 13; // SCM revision of firmware - optional bytes bootloader_hash = 14; // hash of the bootloader - optional bool imported = 15; // was storage imported from an external source? - optional bool pin_cached = 16; // is PIN already cached in session? - optional bool passphrase_cached = 17; // is passphrase already cached in session? - optional bool firmware_present = 18; // is valid firmware loaded? - optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup) - optional uint32 flags = 20; // device flags (equals to Storage.flags) - optional string model = 21; // device hardware model - optional uint32 fw_major = 22; // reported firmware version if in bootloader mode - optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode - optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode - optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode - optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash) - optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup) - optional bool no_backup = 28; // report no backup (equals to Storage.no_backup) -} - -/** - * Request: clear session (removes cached PIN, passphrase, etc). - * @start - * @next Success - */ -message ClearSession { -} - -/** - * Request: change language and/or label of the device - * @start - * @next Success - * @next Failure - */ -message ApplySettings { - optional string language = 1; - optional string label = 2; - optional bool use_passphrase = 3; - optional bytes homescreen = 4; - optional PassphraseSourceType passphrase_source = 5; - optional uint32 auto_lock_delay_ms = 6; - optional uint32 display_rotation = 7; // in degrees from North - /** - * Structure representing passphrase source - */ - enum PassphraseSourceType { - ASK = 0; - DEVICE = 1; - HOST = 2; - } -} - -/** - * Request: set flags of the device - * @start - * @next Success - * @next Failure - */ -message ApplyFlags { - optional uint32 flags = 1; // bitmask, can only set bits, not unset -} - -/** - * Request: Starts workflow for setting/changing/removing the PIN - * @start - * @next Success - * @next Failure - */ -message ChangePin { - optional bool remove = 1; // is PIN removal requested? -} - -/** - * Request: Test if the device is alive, device sends back the message in Success response - * @start - * @next Success - */ -message Ping { - optional string message = 1; // message to send back in Success message - optional bool button_protection = 2; // ask for button press - optional bool pin_protection = 3; // ask for PIN if set in device - optional bool passphrase_protection = 4; // ask for passphrase if set in device -} - -/** - * Request: Abort last operation that required user interaction - * @start - * @next Failure - */ -message Cancel { -} - -/** - * Request: Request a sample of random data generated by hardware RNG. May be used for testing. - * @start - * @next Entropy - * @next Failure - */ -message GetEntropy { - required uint32 size = 1; // size of requested entropy -} - -/** - * Response: Reply with random data generated by internal RNG - * @end - */ -message Entropy { - required bytes entropy = 1; // chunk of random generated bytes -} - -/** - * Request: Request device to wipe all sensitive data and settings - * @start - * @next Success - * @next Failure - */ -message WipeDevice { -} - -/** - * Request: Load seed and related internal settings from the computer - * @start - * @next Success - * @next Failure - */ -message LoadDevice { - optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words) - optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node - optional string pin = 3; // set PIN protection - optional bool passphrase_protection = 4; // enable master node encryption using passphrase - optional string language = 5 [default='english']; // device language - optional string label = 6; // device label - optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum - optional uint32 u2f_counter = 8; // U2F counter -} - -/** - * Request: Ask device to do initialization involving user interaction - * @start - * @next EntropyRequest - * @next Failure - */ -message ResetDevice { - optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy - optional uint32 strength = 2 [default=256]; // strength of seed in bits - optional bool passphrase_protection = 3; // enable master node encryption using passphrase - optional bool pin_protection = 4; // enable PIN protection - optional string language = 5 [default='english']; // device language - optional string label = 6; // device label - optional uint32 u2f_counter = 7; // U2F counter - optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow - optional bool no_backup = 9; // indicate that no backup is going to be made -} - -/** - * Request: Perform backup of the device seed if not backed up using ResetDevice - * @start - * @next Success - */ -message BackupDevice { -} - -/** - * Response: Ask for additional entropy from host computer - * @next EntropyAck - */ -message EntropyRequest { -} - -/** - * Request: Provide additional entropy for seed generation function - * @next Success - */ -message EntropyAck { - optional bytes entropy = 1; // 256 bits (32 bytes) of random data -} - -/** - * Request: Start recovery workflow asking user for specific words of mnemonic - * Used to recovery device safely even on untrusted computer. - * @start - * @next WordRequest - */ -message RecoveryDevice { - optional uint32 word_count = 1; // number of words in BIP-39 mnemonic - optional bool passphrase_protection = 2; // enable master node encryption using passphrase - optional bool pin_protection = 3; // enable PIN protection - optional string language = 4 [default='english']; // device language - optional string label = 5; // device label - optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process - // 7 reserved for unused recovery method - optional RecoveryDeviceType type = 8; // supported recovery type - optional uint32 u2f_counter = 9; // U2F counter - optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation) - /** - * Type of recovery procedure. These should be used as bitmask, e.g., - * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix` - * listing every method supported by the host computer. - * - * Note that ScrambledWords must be supported by every implementation - * for backward compatibility; there is no way to not support it. - */ - enum RecoveryDeviceType { - // use powers of two when extending this field - RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order - RecoveryDeviceType_Matrix = 1; // matrix recovery type - } -} - -/** - * Response: Device is waiting for user to enter word of the mnemonic - * Its position is shown only on device's internal display. - * @next WordAck - */ -message WordRequest { - optional WordRequestType type = 1; - /** - * Type of Recovery Word request - */ - enum WordRequestType { - WordRequestType_Plain = 0; - WordRequestType_Matrix9 = 1; - WordRequestType_Matrix6 = 2; - } -} - -/** - * Request: Computer replies with word from the mnemonic - * @next WordRequest - * @next Success - * @next Failure - */ -message WordAck { - required string word = 1; // one word of mnemonic on asked position -} - -/** - * Request: Set U2F counter - * @start - * @next Success - */ -message SetU2FCounter { - optional uint32 u2f_counter = 1; // counter -} diff --git a/builder/accounts/usbwallet/trezor/messages.pb.go b/builder/accounts/usbwallet/trezor/messages.pb.go deleted file mode 100644 index af0c95714..000000000 --- a/builder/accounts/usbwallet/trezor/messages.pb.go +++ /dev/null @@ -1,889 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: messages.proto - -package trezor - -import ( - fmt "fmt" - math "math" - - proto "github.com/golang/protobuf/proto" - descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -// * -// Mapping between TREZOR wire identifier (uint) and a protobuf message -type MessageType int32 - -const ( - // Management - MessageType_MessageType_Initialize MessageType = 0 - MessageType_MessageType_Ping MessageType = 1 - MessageType_MessageType_Success MessageType = 2 - MessageType_MessageType_Failure MessageType = 3 - MessageType_MessageType_ChangePin MessageType = 4 - MessageType_MessageType_WipeDevice MessageType = 5 - MessageType_MessageType_GetEntropy MessageType = 9 - MessageType_MessageType_Entropy MessageType = 10 - MessageType_MessageType_LoadDevice MessageType = 13 - MessageType_MessageType_ResetDevice MessageType = 14 - MessageType_MessageType_Features MessageType = 17 - MessageType_MessageType_PinMatrixRequest MessageType = 18 - MessageType_MessageType_PinMatrixAck MessageType = 19 - MessageType_MessageType_Cancel MessageType = 20 - MessageType_MessageType_ClearSession MessageType = 24 - MessageType_MessageType_ApplySettings MessageType = 25 - MessageType_MessageType_ButtonRequest MessageType = 26 - MessageType_MessageType_ButtonAck MessageType = 27 - MessageType_MessageType_ApplyFlags MessageType = 28 - MessageType_MessageType_BackupDevice MessageType = 34 - MessageType_MessageType_EntropyRequest MessageType = 35 - MessageType_MessageType_EntropyAck MessageType = 36 - MessageType_MessageType_PassphraseRequest MessageType = 41 - MessageType_MessageType_PassphraseAck MessageType = 42 - MessageType_MessageType_PassphraseStateRequest MessageType = 77 - MessageType_MessageType_PassphraseStateAck MessageType = 78 - MessageType_MessageType_RecoveryDevice MessageType = 45 - MessageType_MessageType_WordRequest MessageType = 46 - MessageType_MessageType_WordAck MessageType = 47 - MessageType_MessageType_GetFeatures MessageType = 55 - MessageType_MessageType_SetU2FCounter MessageType = 63 - // Bootloader - MessageType_MessageType_FirmwareErase MessageType = 6 - MessageType_MessageType_FirmwareUpload MessageType = 7 - MessageType_MessageType_FirmwareRequest MessageType = 8 - MessageType_MessageType_SelfTest MessageType = 32 - // Bitcoin - MessageType_MessageType_GetPublicKey MessageType = 11 - MessageType_MessageType_PublicKey MessageType = 12 - MessageType_MessageType_SignTx MessageType = 15 - MessageType_MessageType_TxRequest MessageType = 21 - MessageType_MessageType_TxAck MessageType = 22 - MessageType_MessageType_GetAddress MessageType = 29 - MessageType_MessageType_Address MessageType = 30 - MessageType_MessageType_SignMessage MessageType = 38 - MessageType_MessageType_VerifyMessage MessageType = 39 - MessageType_MessageType_MessageSignature MessageType = 40 - // Crypto - MessageType_MessageType_CipherKeyValue MessageType = 23 - MessageType_MessageType_CipheredKeyValue MessageType = 48 - MessageType_MessageType_SignIdentity MessageType = 53 - MessageType_MessageType_SignedIdentity MessageType = 54 - MessageType_MessageType_GetECDHSessionKey MessageType = 61 - MessageType_MessageType_ECDHSessionKey MessageType = 62 - MessageType_MessageType_CosiCommit MessageType = 71 - MessageType_MessageType_CosiCommitment MessageType = 72 - MessageType_MessageType_CosiSign MessageType = 73 - MessageType_MessageType_CosiSignature MessageType = 74 - // Debug - MessageType_MessageType_DebugLinkDecision MessageType = 100 - MessageType_MessageType_DebugLinkGetState MessageType = 101 - MessageType_MessageType_DebugLinkState MessageType = 102 - MessageType_MessageType_DebugLinkStop MessageType = 103 - MessageType_MessageType_DebugLinkLog MessageType = 104 - MessageType_MessageType_DebugLinkMemoryRead MessageType = 110 - MessageType_MessageType_DebugLinkMemory MessageType = 111 - MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112 - MessageType_MessageType_DebugLinkFlashErase MessageType = 113 - // Ethereum - MessageType_MessageType_EthereumGetPublicKey MessageType = 450 - MessageType_MessageType_EthereumPublicKey MessageType = 451 - MessageType_MessageType_EthereumGetAddress MessageType = 56 - MessageType_MessageType_EthereumAddress MessageType = 57 - MessageType_MessageType_EthereumSignTx MessageType = 58 - MessageType_MessageType_EthereumTxRequest MessageType = 59 - MessageType_MessageType_EthereumTxAck MessageType = 60 - MessageType_MessageType_EthereumSignMessage MessageType = 64 - MessageType_MessageType_EthereumVerifyMessage MessageType = 65 - MessageType_MessageType_EthereumMessageSignature MessageType = 66 - // NEM - MessageType_MessageType_NEMGetAddress MessageType = 67 - MessageType_MessageType_NEMAddress MessageType = 68 - MessageType_MessageType_NEMSignTx MessageType = 69 - MessageType_MessageType_NEMSignedTx MessageType = 70 - MessageType_MessageType_NEMDecryptMessage MessageType = 75 - MessageType_MessageType_NEMDecryptedMessage MessageType = 76 - // Lisk - MessageType_MessageType_LiskGetAddress MessageType = 114 - MessageType_MessageType_LiskAddress MessageType = 115 - MessageType_MessageType_LiskSignTx MessageType = 116 - MessageType_MessageType_LiskSignedTx MessageType = 117 - MessageType_MessageType_LiskSignMessage MessageType = 118 - MessageType_MessageType_LiskMessageSignature MessageType = 119 - MessageType_MessageType_LiskVerifyMessage MessageType = 120 - MessageType_MessageType_LiskGetPublicKey MessageType = 121 - MessageType_MessageType_LiskPublicKey MessageType = 122 - // Tezos - MessageType_MessageType_TezosGetAddress MessageType = 150 - MessageType_MessageType_TezosAddress MessageType = 151 - MessageType_MessageType_TezosSignTx MessageType = 152 - MessageType_MessageType_TezosSignedTx MessageType = 153 - MessageType_MessageType_TezosGetPublicKey MessageType = 154 - MessageType_MessageType_TezosPublicKey MessageType = 155 - // Stellar - MessageType_MessageType_StellarSignTx MessageType = 202 - MessageType_MessageType_StellarTxOpRequest MessageType = 203 - MessageType_MessageType_StellarGetAddress MessageType = 207 - MessageType_MessageType_StellarAddress MessageType = 208 - MessageType_MessageType_StellarCreateAccountOp MessageType = 210 - MessageType_MessageType_StellarPaymentOp MessageType = 211 - MessageType_MessageType_StellarPathPaymentOp MessageType = 212 - MessageType_MessageType_StellarManageOfferOp MessageType = 213 - MessageType_MessageType_StellarCreatePassiveOfferOp MessageType = 214 - MessageType_MessageType_StellarSetOptionsOp MessageType = 215 - MessageType_MessageType_StellarChangeTrustOp MessageType = 216 - MessageType_MessageType_StellarAllowTrustOp MessageType = 217 - MessageType_MessageType_StellarAccountMergeOp MessageType = 218 - // omitted: StellarInflationOp is not a supported operation, would be 219 - MessageType_MessageType_StellarManageDataOp MessageType = 220 - MessageType_MessageType_StellarBumpSequenceOp MessageType = 221 - MessageType_MessageType_StellarSignedTx MessageType = 230 - // TRON - MessageType_MessageType_TronGetAddress MessageType = 250 - MessageType_MessageType_TronAddress MessageType = 251 - MessageType_MessageType_TronSignTx MessageType = 252 - MessageType_MessageType_TronSignedTx MessageType = 253 - // Cardano - // dropped Sign/VerifyMessage ids 300-302 - MessageType_MessageType_CardanoSignTx MessageType = 303 - MessageType_MessageType_CardanoTxRequest MessageType = 304 - MessageType_MessageType_CardanoGetPublicKey MessageType = 305 - MessageType_MessageType_CardanoPublicKey MessageType = 306 - MessageType_MessageType_CardanoGetAddress MessageType = 307 - MessageType_MessageType_CardanoAddress MessageType = 308 - MessageType_MessageType_CardanoTxAck MessageType = 309 - MessageType_MessageType_CardanoSignedTx MessageType = 310 - // Ontology - MessageType_MessageType_OntologyGetAddress MessageType = 350 - MessageType_MessageType_OntologyAddress MessageType = 351 - MessageType_MessageType_OntologyGetPublicKey MessageType = 352 - MessageType_MessageType_OntologyPublicKey MessageType = 353 - MessageType_MessageType_OntologySignTransfer MessageType = 354 - MessageType_MessageType_OntologySignedTransfer MessageType = 355 - MessageType_MessageType_OntologySignWithdrawOng MessageType = 356 - MessageType_MessageType_OntologySignedWithdrawOng MessageType = 357 - MessageType_MessageType_OntologySignOntIdRegister MessageType = 358 - MessageType_MessageType_OntologySignedOntIdRegister MessageType = 359 - MessageType_MessageType_OntologySignOntIdAddAttributes MessageType = 360 - MessageType_MessageType_OntologySignedOntIdAddAttributes MessageType = 361 - // Ripple - MessageType_MessageType_RippleGetAddress MessageType = 400 - MessageType_MessageType_RippleAddress MessageType = 401 - MessageType_MessageType_RippleSignTx MessageType = 402 - MessageType_MessageType_RippleSignedTx MessageType = 403 - // Monero - MessageType_MessageType_MoneroTransactionInitRequest MessageType = 501 - MessageType_MessageType_MoneroTransactionInitAck MessageType = 502 - MessageType_MessageType_MoneroTransactionSetInputRequest MessageType = 503 - MessageType_MessageType_MoneroTransactionSetInputAck MessageType = 504 - MessageType_MessageType_MoneroTransactionInputsPermutationRequest MessageType = 505 - MessageType_MessageType_MoneroTransactionInputsPermutationAck MessageType = 506 - MessageType_MessageType_MoneroTransactionInputViniRequest MessageType = 507 - MessageType_MessageType_MoneroTransactionInputViniAck MessageType = 508 - MessageType_MessageType_MoneroTransactionAllInputsSetRequest MessageType = 509 - MessageType_MessageType_MoneroTransactionAllInputsSetAck MessageType = 510 - MessageType_MessageType_MoneroTransactionSetOutputRequest MessageType = 511 - MessageType_MessageType_MoneroTransactionSetOutputAck MessageType = 512 - MessageType_MessageType_MoneroTransactionAllOutSetRequest MessageType = 513 - MessageType_MessageType_MoneroTransactionAllOutSetAck MessageType = 514 - MessageType_MessageType_MoneroTransactionSignInputRequest MessageType = 515 - MessageType_MessageType_MoneroTransactionSignInputAck MessageType = 516 - MessageType_MessageType_MoneroTransactionFinalRequest MessageType = 517 - MessageType_MessageType_MoneroTransactionFinalAck MessageType = 518 - MessageType_MessageType_MoneroKeyImageExportInitRequest MessageType = 530 - MessageType_MessageType_MoneroKeyImageExportInitAck MessageType = 531 - MessageType_MessageType_MoneroKeyImageSyncStepRequest MessageType = 532 - MessageType_MessageType_MoneroKeyImageSyncStepAck MessageType = 533 - MessageType_MessageType_MoneroKeyImageSyncFinalRequest MessageType = 534 - MessageType_MessageType_MoneroKeyImageSyncFinalAck MessageType = 535 - MessageType_MessageType_MoneroGetAddress MessageType = 540 - MessageType_MessageType_MoneroAddress MessageType = 541 - MessageType_MessageType_MoneroGetWatchKey MessageType = 542 - MessageType_MessageType_MoneroWatchKey MessageType = 543 - MessageType_MessageType_DebugMoneroDiagRequest MessageType = 546 - MessageType_MessageType_DebugMoneroDiagAck MessageType = 547 - MessageType_MessageType_MoneroGetTxKeyRequest MessageType = 550 - MessageType_MessageType_MoneroGetTxKeyAck MessageType = 551 - MessageType_MessageType_MoneroLiveRefreshStartRequest MessageType = 552 - MessageType_MessageType_MoneroLiveRefreshStartAck MessageType = 553 - MessageType_MessageType_MoneroLiveRefreshStepRequest MessageType = 554 - MessageType_MessageType_MoneroLiveRefreshStepAck MessageType = 555 - MessageType_MessageType_MoneroLiveRefreshFinalRequest MessageType = 556 - MessageType_MessageType_MoneroLiveRefreshFinalAck MessageType = 557 - // EOS - MessageType_MessageType_EosGetPublicKey MessageType = 600 - MessageType_MessageType_EosPublicKey MessageType = 601 - MessageType_MessageType_EosSignTx MessageType = 602 - MessageType_MessageType_EosTxActionRequest MessageType = 603 - MessageType_MessageType_EosTxActionAck MessageType = 604 - MessageType_MessageType_EosSignedTx MessageType = 605 - // Binance - MessageType_MessageType_BinanceGetAddress MessageType = 700 - MessageType_MessageType_BinanceAddress MessageType = 701 - MessageType_MessageType_BinanceGetPublicKey MessageType = 702 - MessageType_MessageType_BinancePublicKey MessageType = 703 - MessageType_MessageType_BinanceSignTx MessageType = 704 - MessageType_MessageType_BinanceTxRequest MessageType = 705 - MessageType_MessageType_BinanceTransferMsg MessageType = 706 - MessageType_MessageType_BinanceOrderMsg MessageType = 707 - MessageType_MessageType_BinanceCancelMsg MessageType = 708 - MessageType_MessageType_BinanceSignedTx MessageType = 709 -) - -var MessageType_name = map[int32]string{ - 0: "MessageType_Initialize", - 1: "MessageType_Ping", - 2: "MessageType_Success", - 3: "MessageType_Failure", - 4: "MessageType_ChangePin", - 5: "MessageType_WipeDevice", - 9: "MessageType_GetEntropy", - 10: "MessageType_Entropy", - 13: "MessageType_LoadDevice", - 14: "MessageType_ResetDevice", - 17: "MessageType_Features", - 18: "MessageType_PinMatrixRequest", - 19: "MessageType_PinMatrixAck", - 20: "MessageType_Cancel", - 24: "MessageType_ClearSession", - 25: "MessageType_ApplySettings", - 26: "MessageType_ButtonRequest", - 27: "MessageType_ButtonAck", - 28: "MessageType_ApplyFlags", - 34: "MessageType_BackupDevice", - 35: "MessageType_EntropyRequest", - 36: "MessageType_EntropyAck", - 41: "MessageType_PassphraseRequest", - 42: "MessageType_PassphraseAck", - 77: "MessageType_PassphraseStateRequest", - 78: "MessageType_PassphraseStateAck", - 45: "MessageType_RecoveryDevice", - 46: "MessageType_WordRequest", - 47: "MessageType_WordAck", - 55: "MessageType_GetFeatures", - 63: "MessageType_SetU2FCounter", - 6: "MessageType_FirmwareErase", - 7: "MessageType_FirmwareUpload", - 8: "MessageType_FirmwareRequest", - 32: "MessageType_SelfTest", - 11: "MessageType_GetPublicKey", - 12: "MessageType_PublicKey", - 15: "MessageType_SignTx", - 21: "MessageType_TxRequest", - 22: "MessageType_TxAck", - 29: "MessageType_GetAddress", - 30: "MessageType_Address", - 38: "MessageType_SignMessage", - 39: "MessageType_VerifyMessage", - 40: "MessageType_MessageSignature", - 23: "MessageType_CipherKeyValue", - 48: "MessageType_CipheredKeyValue", - 53: "MessageType_SignIdentity", - 54: "MessageType_SignedIdentity", - 61: "MessageType_GetECDHSessionKey", - 62: "MessageType_ECDHSessionKey", - 71: "MessageType_CosiCommit", - 72: "MessageType_CosiCommitment", - 73: "MessageType_CosiSign", - 74: "MessageType_CosiSignature", - 100: "MessageType_DebugLinkDecision", - 101: "MessageType_DebugLinkGetState", - 102: "MessageType_DebugLinkState", - 103: "MessageType_DebugLinkStop", - 104: "MessageType_DebugLinkLog", - 110: "MessageType_DebugLinkMemoryRead", - 111: "MessageType_DebugLinkMemory", - 112: "MessageType_DebugLinkMemoryWrite", - 113: "MessageType_DebugLinkFlashErase", - 450: "MessageType_EthereumGetPublicKey", - 451: "MessageType_EthereumPublicKey", - 56: "MessageType_EthereumGetAddress", - 57: "MessageType_EthereumAddress", - 58: "MessageType_EthereumSignTx", - 59: "MessageType_EthereumTxRequest", - 60: "MessageType_EthereumTxAck", - 64: "MessageType_EthereumSignMessage", - 65: "MessageType_EthereumVerifyMessage", - 66: "MessageType_EthereumMessageSignature", - 67: "MessageType_NEMGetAddress", - 68: "MessageType_NEMAddress", - 69: "MessageType_NEMSignTx", - 70: "MessageType_NEMSignedTx", - 75: "MessageType_NEMDecryptMessage", - 76: "MessageType_NEMDecryptedMessage", - 114: "MessageType_LiskGetAddress", - 115: "MessageType_LiskAddress", - 116: "MessageType_LiskSignTx", - 117: "MessageType_LiskSignedTx", - 118: "MessageType_LiskSignMessage", - 119: "MessageType_LiskMessageSignature", - 120: "MessageType_LiskVerifyMessage", - 121: "MessageType_LiskGetPublicKey", - 122: "MessageType_LiskPublicKey", - 150: "MessageType_TezosGetAddress", - 151: "MessageType_TezosAddress", - 152: "MessageType_TezosSignTx", - 153: "MessageType_TezosSignedTx", - 154: "MessageType_TezosGetPublicKey", - 155: "MessageType_TezosPublicKey", - 202: "MessageType_StellarSignTx", - 203: "MessageType_StellarTxOpRequest", - 207: "MessageType_StellarGetAddress", - 208: "MessageType_StellarAddress", - 210: "MessageType_StellarCreateAccountOp", - 211: "MessageType_StellarPaymentOp", - 212: "MessageType_StellarPathPaymentOp", - 213: "MessageType_StellarManageOfferOp", - 214: "MessageType_StellarCreatePassiveOfferOp", - 215: "MessageType_StellarSetOptionsOp", - 216: "MessageType_StellarChangeTrustOp", - 217: "MessageType_StellarAllowTrustOp", - 218: "MessageType_StellarAccountMergeOp", - 220: "MessageType_StellarManageDataOp", - 221: "MessageType_StellarBumpSequenceOp", - 230: "MessageType_StellarSignedTx", - 250: "MessageType_TronGetAddress", - 251: "MessageType_TronAddress", - 252: "MessageType_TronSignTx", - 253: "MessageType_TronSignedTx", - 303: "MessageType_CardanoSignTx", - 304: "MessageType_CardanoTxRequest", - 305: "MessageType_CardanoGetPublicKey", - 306: "MessageType_CardanoPublicKey", - 307: "MessageType_CardanoGetAddress", - 308: "MessageType_CardanoAddress", - 309: "MessageType_CardanoTxAck", - 310: "MessageType_CardanoSignedTx", - 350: "MessageType_OntologyGetAddress", - 351: "MessageType_OntologyAddress", - 352: "MessageType_OntologyGetPublicKey", - 353: "MessageType_OntologyPublicKey", - 354: "MessageType_OntologySignTransfer", - 355: "MessageType_OntologySignedTransfer", - 356: "MessageType_OntologySignWithdrawOng", - 357: "MessageType_OntologySignedWithdrawOng", - 358: "MessageType_OntologySignOntIdRegister", - 359: "MessageType_OntologySignedOntIdRegister", - 360: "MessageType_OntologySignOntIdAddAttributes", - 361: "MessageType_OntologySignedOntIdAddAttributes", - 400: "MessageType_RippleGetAddress", - 401: "MessageType_RippleAddress", - 402: "MessageType_RippleSignTx", - 403: "MessageType_RippleSignedTx", - 501: "MessageType_MoneroTransactionInitRequest", - 502: "MessageType_MoneroTransactionInitAck", - 503: "MessageType_MoneroTransactionSetInputRequest", - 504: "MessageType_MoneroTransactionSetInputAck", - 505: "MessageType_MoneroTransactionInputsPermutationRequest", - 506: "MessageType_MoneroTransactionInputsPermutationAck", - 507: "MessageType_MoneroTransactionInputViniRequest", - 508: "MessageType_MoneroTransactionInputViniAck", - 509: "MessageType_MoneroTransactionAllInputsSetRequest", - 510: "MessageType_MoneroTransactionAllInputsSetAck", - 511: "MessageType_MoneroTransactionSetOutputRequest", - 512: "MessageType_MoneroTransactionSetOutputAck", - 513: "MessageType_MoneroTransactionAllOutSetRequest", - 514: "MessageType_MoneroTransactionAllOutSetAck", - 515: "MessageType_MoneroTransactionSignInputRequest", - 516: "MessageType_MoneroTransactionSignInputAck", - 517: "MessageType_MoneroTransactionFinalRequest", - 518: "MessageType_MoneroTransactionFinalAck", - 530: "MessageType_MoneroKeyImageExportInitRequest", - 531: "MessageType_MoneroKeyImageExportInitAck", - 532: "MessageType_MoneroKeyImageSyncStepRequest", - 533: "MessageType_MoneroKeyImageSyncStepAck", - 534: "MessageType_MoneroKeyImageSyncFinalRequest", - 535: "MessageType_MoneroKeyImageSyncFinalAck", - 540: "MessageType_MoneroGetAddress", - 541: "MessageType_MoneroAddress", - 542: "MessageType_MoneroGetWatchKey", - 543: "MessageType_MoneroWatchKey", - 546: "MessageType_DebugMoneroDiagRequest", - 547: "MessageType_DebugMoneroDiagAck", - 550: "MessageType_MoneroGetTxKeyRequest", - 551: "MessageType_MoneroGetTxKeyAck", - 552: "MessageType_MoneroLiveRefreshStartRequest", - 553: "MessageType_MoneroLiveRefreshStartAck", - 554: "MessageType_MoneroLiveRefreshStepRequest", - 555: "MessageType_MoneroLiveRefreshStepAck", - 556: "MessageType_MoneroLiveRefreshFinalRequest", - 557: "MessageType_MoneroLiveRefreshFinalAck", - 600: "MessageType_EosGetPublicKey", - 601: "MessageType_EosPublicKey", - 602: "MessageType_EosSignTx", - 603: "MessageType_EosTxActionRequest", - 604: "MessageType_EosTxActionAck", - 605: "MessageType_EosSignedTx", - 700: "MessageType_BinanceGetAddress", - 701: "MessageType_BinanceAddress", - 702: "MessageType_BinanceGetPublicKey", - 703: "MessageType_BinancePublicKey", - 704: "MessageType_BinanceSignTx", - 705: "MessageType_BinanceTxRequest", - 706: "MessageType_BinanceTransferMsg", - 707: "MessageType_BinanceOrderMsg", - 708: "MessageType_BinanceCancelMsg", - 709: "MessageType_BinanceSignedTx", -} - -var MessageType_value = map[string]int32{ - "MessageType_Initialize": 0, - "MessageType_Ping": 1, - "MessageType_Success": 2, - "MessageType_Failure": 3, - "MessageType_ChangePin": 4, - "MessageType_WipeDevice": 5, - "MessageType_GetEntropy": 9, - "MessageType_Entropy": 10, - "MessageType_LoadDevice": 13, - "MessageType_ResetDevice": 14, - "MessageType_Features": 17, - "MessageType_PinMatrixRequest": 18, - "MessageType_PinMatrixAck": 19, - "MessageType_Cancel": 20, - "MessageType_ClearSession": 24, - "MessageType_ApplySettings": 25, - "MessageType_ButtonRequest": 26, - "MessageType_ButtonAck": 27, - "MessageType_ApplyFlags": 28, - "MessageType_BackupDevice": 34, - "MessageType_EntropyRequest": 35, - "MessageType_EntropyAck": 36, - "MessageType_PassphraseRequest": 41, - "MessageType_PassphraseAck": 42, - "MessageType_PassphraseStateRequest": 77, - "MessageType_PassphraseStateAck": 78, - "MessageType_RecoveryDevice": 45, - "MessageType_WordRequest": 46, - "MessageType_WordAck": 47, - "MessageType_GetFeatures": 55, - "MessageType_SetU2FCounter": 63, - "MessageType_FirmwareErase": 6, - "MessageType_FirmwareUpload": 7, - "MessageType_FirmwareRequest": 8, - "MessageType_SelfTest": 32, - "MessageType_GetPublicKey": 11, - "MessageType_PublicKey": 12, - "MessageType_SignTx": 15, - "MessageType_TxRequest": 21, - "MessageType_TxAck": 22, - "MessageType_GetAddress": 29, - "MessageType_Address": 30, - "MessageType_SignMessage": 38, - "MessageType_VerifyMessage": 39, - "MessageType_MessageSignature": 40, - "MessageType_CipherKeyValue": 23, - "MessageType_CipheredKeyValue": 48, - "MessageType_SignIdentity": 53, - "MessageType_SignedIdentity": 54, - "MessageType_GetECDHSessionKey": 61, - "MessageType_ECDHSessionKey": 62, - "MessageType_CosiCommit": 71, - "MessageType_CosiCommitment": 72, - "MessageType_CosiSign": 73, - "MessageType_CosiSignature": 74, - "MessageType_DebugLinkDecision": 100, - "MessageType_DebugLinkGetState": 101, - "MessageType_DebugLinkState": 102, - "MessageType_DebugLinkStop": 103, - "MessageType_DebugLinkLog": 104, - "MessageType_DebugLinkMemoryRead": 110, - "MessageType_DebugLinkMemory": 111, - "MessageType_DebugLinkMemoryWrite": 112, - "MessageType_DebugLinkFlashErase": 113, - "MessageType_EthereumGetPublicKey": 450, - "MessageType_EthereumPublicKey": 451, - "MessageType_EthereumGetAddress": 56, - "MessageType_EthereumAddress": 57, - "MessageType_EthereumSignTx": 58, - "MessageType_EthereumTxRequest": 59, - "MessageType_EthereumTxAck": 60, - "MessageType_EthereumSignMessage": 64, - "MessageType_EthereumVerifyMessage": 65, - "MessageType_EthereumMessageSignature": 66, - "MessageType_NEMGetAddress": 67, - "MessageType_NEMAddress": 68, - "MessageType_NEMSignTx": 69, - "MessageType_NEMSignedTx": 70, - "MessageType_NEMDecryptMessage": 75, - "MessageType_NEMDecryptedMessage": 76, - "MessageType_LiskGetAddress": 114, - "MessageType_LiskAddress": 115, - "MessageType_LiskSignTx": 116, - "MessageType_LiskSignedTx": 117, - "MessageType_LiskSignMessage": 118, - "MessageType_LiskMessageSignature": 119, - "MessageType_LiskVerifyMessage": 120, - "MessageType_LiskGetPublicKey": 121, - "MessageType_LiskPublicKey": 122, - "MessageType_TezosGetAddress": 150, - "MessageType_TezosAddress": 151, - "MessageType_TezosSignTx": 152, - "MessageType_TezosSignedTx": 153, - "MessageType_TezosGetPublicKey": 154, - "MessageType_TezosPublicKey": 155, - "MessageType_StellarSignTx": 202, - "MessageType_StellarTxOpRequest": 203, - "MessageType_StellarGetAddress": 207, - "MessageType_StellarAddress": 208, - "MessageType_StellarCreateAccountOp": 210, - "MessageType_StellarPaymentOp": 211, - "MessageType_StellarPathPaymentOp": 212, - "MessageType_StellarManageOfferOp": 213, - "MessageType_StellarCreatePassiveOfferOp": 214, - "MessageType_StellarSetOptionsOp": 215, - "MessageType_StellarChangeTrustOp": 216, - "MessageType_StellarAllowTrustOp": 217, - "MessageType_StellarAccountMergeOp": 218, - "MessageType_StellarManageDataOp": 220, - "MessageType_StellarBumpSequenceOp": 221, - "MessageType_StellarSignedTx": 230, - "MessageType_TronGetAddress": 250, - "MessageType_TronAddress": 251, - "MessageType_TronSignTx": 252, - "MessageType_TronSignedTx": 253, - "MessageType_CardanoSignTx": 303, - "MessageType_CardanoTxRequest": 304, - "MessageType_CardanoGetPublicKey": 305, - "MessageType_CardanoPublicKey": 306, - "MessageType_CardanoGetAddress": 307, - "MessageType_CardanoAddress": 308, - "MessageType_CardanoTxAck": 309, - "MessageType_CardanoSignedTx": 310, - "MessageType_OntologyGetAddress": 350, - "MessageType_OntologyAddress": 351, - "MessageType_OntologyGetPublicKey": 352, - "MessageType_OntologyPublicKey": 353, - "MessageType_OntologySignTransfer": 354, - "MessageType_OntologySignedTransfer": 355, - "MessageType_OntologySignWithdrawOng": 356, - "MessageType_OntologySignedWithdrawOng": 357, - "MessageType_OntologySignOntIdRegister": 358, - "MessageType_OntologySignedOntIdRegister": 359, - "MessageType_OntologySignOntIdAddAttributes": 360, - "MessageType_OntologySignedOntIdAddAttributes": 361, - "MessageType_RippleGetAddress": 400, - "MessageType_RippleAddress": 401, - "MessageType_RippleSignTx": 402, - "MessageType_RippleSignedTx": 403, - "MessageType_MoneroTransactionInitRequest": 501, - "MessageType_MoneroTransactionInitAck": 502, - "MessageType_MoneroTransactionSetInputRequest": 503, - "MessageType_MoneroTransactionSetInputAck": 504, - "MessageType_MoneroTransactionInputsPermutationRequest": 505, - "MessageType_MoneroTransactionInputsPermutationAck": 506, - "MessageType_MoneroTransactionInputViniRequest": 507, - "MessageType_MoneroTransactionInputViniAck": 508, - "MessageType_MoneroTransactionAllInputsSetRequest": 509, - "MessageType_MoneroTransactionAllInputsSetAck": 510, - "MessageType_MoneroTransactionSetOutputRequest": 511, - "MessageType_MoneroTransactionSetOutputAck": 512, - "MessageType_MoneroTransactionAllOutSetRequest": 513, - "MessageType_MoneroTransactionAllOutSetAck": 514, - "MessageType_MoneroTransactionSignInputRequest": 515, - "MessageType_MoneroTransactionSignInputAck": 516, - "MessageType_MoneroTransactionFinalRequest": 517, - "MessageType_MoneroTransactionFinalAck": 518, - "MessageType_MoneroKeyImageExportInitRequest": 530, - "MessageType_MoneroKeyImageExportInitAck": 531, - "MessageType_MoneroKeyImageSyncStepRequest": 532, - "MessageType_MoneroKeyImageSyncStepAck": 533, - "MessageType_MoneroKeyImageSyncFinalRequest": 534, - "MessageType_MoneroKeyImageSyncFinalAck": 535, - "MessageType_MoneroGetAddress": 540, - "MessageType_MoneroAddress": 541, - "MessageType_MoneroGetWatchKey": 542, - "MessageType_MoneroWatchKey": 543, - "MessageType_DebugMoneroDiagRequest": 546, - "MessageType_DebugMoneroDiagAck": 547, - "MessageType_MoneroGetTxKeyRequest": 550, - "MessageType_MoneroGetTxKeyAck": 551, - "MessageType_MoneroLiveRefreshStartRequest": 552, - "MessageType_MoneroLiveRefreshStartAck": 553, - "MessageType_MoneroLiveRefreshStepRequest": 554, - "MessageType_MoneroLiveRefreshStepAck": 555, - "MessageType_MoneroLiveRefreshFinalRequest": 556, - "MessageType_MoneroLiveRefreshFinalAck": 557, - "MessageType_EosGetPublicKey": 600, - "MessageType_EosPublicKey": 601, - "MessageType_EosSignTx": 602, - "MessageType_EosTxActionRequest": 603, - "MessageType_EosTxActionAck": 604, - "MessageType_EosSignedTx": 605, - "MessageType_BinanceGetAddress": 700, - "MessageType_BinanceAddress": 701, - "MessageType_BinanceGetPublicKey": 702, - "MessageType_BinancePublicKey": 703, - "MessageType_BinanceSignTx": 704, - "MessageType_BinanceTxRequest": 705, - "MessageType_BinanceTransferMsg": 706, - "MessageType_BinanceOrderMsg": 707, - "MessageType_BinanceCancelMsg": 708, - "MessageType_BinanceSignedTx": 709, -} - -func (x MessageType) Enum() *MessageType { - p := new(MessageType) - *p = x - return p -} - -func (x MessageType) String() string { - return proto.EnumName(MessageType_name, int32(x)) -} - -func (x *MessageType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType") - if err != nil { - return err - } - *x = MessageType(value) - return nil -} - -func (MessageType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_4dc296cbfe5ffcd5, []int{0} -} - -var E_WireIn = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50002, - Name: "hw.trezor.messages.wire_in", - Tag: "varint,50002,opt,name=wire_in", - Filename: "messages.proto", -} - -var E_WireOut = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50003, - Name: "hw.trezor.messages.wire_out", - Tag: "varint,50003,opt,name=wire_out", - Filename: "messages.proto", -} - -var E_WireDebugIn = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50004, - Name: "hw.trezor.messages.wire_debug_in", - Tag: "varint,50004,opt,name=wire_debug_in", - Filename: "messages.proto", -} - -var E_WireDebugOut = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50005, - Name: "hw.trezor.messages.wire_debug_out", - Tag: "varint,50005,opt,name=wire_debug_out", - Filename: "messages.proto", -} - -var E_WireTiny = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50006, - Name: "hw.trezor.messages.wire_tiny", - Tag: "varint,50006,opt,name=wire_tiny", - Filename: "messages.proto", -} - -var E_WireBootloader = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50007, - Name: "hw.trezor.messages.wire_bootloader", - Tag: "varint,50007,opt,name=wire_bootloader", - Filename: "messages.proto", -} - -var E_WireNoFsm = &proto.ExtensionDesc{ - ExtendedType: (*descriptor.EnumValueOptions)(nil), - ExtensionType: (*bool)(nil), - Field: 50008, - Name: "hw.trezor.messages.wire_no_fsm", - Tag: "varint,50008,opt,name=wire_no_fsm", - Filename: "messages.proto", -} - -func init() { - proto.RegisterEnum("hw.trezor.messages.MessageType", MessageType_name, MessageType_value) - proto.RegisterExtension(E_WireIn) - proto.RegisterExtension(E_WireOut) - proto.RegisterExtension(E_WireDebugIn) - proto.RegisterExtension(E_WireDebugOut) - proto.RegisterExtension(E_WireTiny) - proto.RegisterExtension(E_WireBootloader) - proto.RegisterExtension(E_WireNoFsm) -} - -func init() { proto.RegisterFile("messages.proto", fileDescriptor_4dc296cbfe5ffcd5) } - -var fileDescriptor_4dc296cbfe5ffcd5 = []byte{ - // 2430 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x9a, 0xd9, 0x73, 0x1c, 0xc5, - 0x1d, 0xc7, 0xb3, 0xab, 0x11, 0x88, 0xf6, 0x41, 0x23, 0xb0, 0x2d, 0xaf, 0x2f, 0xf9, 0xc0, 0x96, - 0x2f, 0xd9, 0x10, 0x0c, 0x44, 0x38, 0x60, 0x69, 0xb5, 0x12, 0x8a, 0xb5, 0x5a, 0x97, 0x76, 0xb1, - 0x1f, 0x5d, 0xa3, 0x9d, 0xd6, 0x6e, 0x97, 0x67, 0x67, 0x86, 0x9e, 0x1e, 0x49, 0xeb, 0xa7, 0x9c, - 0x3c, 0x13, 0x48, 0xc0, 0xb9, 0xa9, 0xa4, 0x2a, 0x21, 0x57, 0x85, 0x1c, 0x4e, 0x25, 0x55, 0x39, - 0x08, 0x24, 0x2f, 0xc9, 0x43, 0x52, 0x9c, 0x86, 0x40, 0xee, 0x90, 0xe4, 0x0f, 0xc8, 0xc5, 0x91, - 0xa4, 0x7a, 0xa6, 0xbb, 0xe7, 0xd8, 0xdf, 0xae, 0x36, 0x6f, 0x58, 0xf3, 0xf9, 0x7d, 0x7f, 0x47, - 0xff, 0xfa, 0x37, 0xdd, 0xb3, 0xa0, 0xcd, 0x2d, 0xe2, 0xfb, 0x66, 0x83, 0xf8, 0xe3, 0x1e, 0x73, - 0xb9, 0x3b, 0x3c, 0xdc, 0x5c, 0x1d, 0xe7, 0x8c, 0x5c, 0x76, 0xd9, 0xb8, 0x7a, 0x52, 0x18, 0x6d, - 0xb8, 0x6e, 0xc3, 0x26, 0x27, 0x42, 0x62, 0x29, 0x58, 0x3e, 0x61, 0x11, 0xbf, 0xce, 0xa8, 0xc7, - 0x5d, 0x16, 0x59, 0x1d, 0xf9, 0xfe, 0x7d, 0x68, 0x43, 0x39, 0xc2, 0x6b, 0x6d, 0x8f, 0x0c, 0x1f, - 0x40, 0x5b, 0x13, 0xff, 0xbc, 0x38, 0xe7, 0x50, 0x4e, 0x4d, 0x9b, 0x5e, 0x26, 0xf8, 0x5d, 0x85, - 0xa1, 0x87, 0xaf, 0x8e, 0xe4, 0x9e, 0xba, 0x3a, 0x92, 0x1b, 0x2e, 0x20, 0x9c, 0xa4, 0xce, 0x51, - 0xa7, 0x81, 0x73, 0x05, 0x43, 0x3c, 0x1f, 0xde, 0x85, 0x6e, 0x4e, 0x3e, 0xab, 0x06, 0xf5, 0x3a, - 0xf1, 0x7d, 0x9c, 0x2f, 0x18, 0x57, 0x80, 0xc7, 0x33, 0x26, 0xb5, 0x03, 0x46, 0xf0, 0x80, 0x7c, - 0xbc, 0x07, 0x6d, 0x49, 0x3e, 0x2e, 0x36, 0x4d, 0xa7, 0x41, 0xce, 0x51, 0x07, 0x1b, 0x52, 0x7e, - 0x34, 0x1d, 0xe0, 0x05, 0xea, 0x91, 0x69, 0xb2, 0x42, 0xeb, 0x04, 0x0f, 0xc2, 0xc4, 0x2c, 0xe1, - 0x25, 0x87, 0x33, 0xd7, 0x6b, 0xe3, 0x1b, 0xe0, 0x10, 0xd5, 0x63, 0x24, 0x63, 0xc8, 0x08, 0xcc, - 0xbb, 0xa6, 0x25, 0x5d, 0x6c, 0x92, 0x02, 0x7b, 0xd1, 0xb6, 0x24, 0xb1, 0x48, 0x7c, 0xc2, 0x25, - 0xb2, 0x59, 0x22, 0xbb, 0xd1, 0x2d, 0xa9, 0x3c, 0x89, 0xc9, 0x03, 0x46, 0x7c, 0x7c, 0x93, 0x74, - 0x72, 0x10, 0xed, 0xcc, 0x94, 0xb0, 0x6c, 0x72, 0x46, 0xd7, 0x16, 0xc9, 0x83, 0x01, 0xf1, 0x39, - 0x1e, 0x96, 0xdc, 0x11, 0x34, 0x02, 0x72, 0x93, 0xf5, 0x4b, 0xf8, 0xe6, 0xc2, 0x46, 0xb5, 0x24, - 0x4f, 0x47, 0x81, 0x0f, 0xa7, 0x8a, 0x67, 0x3a, 0x75, 0x62, 0xe3, 0x5b, 0x12, 0x0b, 0xb7, 0x2f, - 0xad, 0x56, 0xb4, 0x89, 0xc9, 0xaa, 0xc4, 0xf7, 0xa9, 0xeb, 0xe0, 0x11, 0x19, 0xf9, 0x7e, 0xb4, - 0x3d, 0xc9, 0x4c, 0x7a, 0x9e, 0xdd, 0xae, 0x12, 0xce, 0xa9, 0xd3, 0xf0, 0xf1, 0x76, 0x18, 0x9a, - 0x0a, 0x38, 0x77, 0x1d, 0x15, 0x7b, 0x41, 0xc6, 0x7e, 0x28, 0xbd, 0x98, 0x11, 0x24, 0x02, 0xdf, - 0xd1, 0x11, 0xf8, 0xd6, 0x0e, 0x97, 0x33, 0xb6, 0xd9, 0xf0, 0xf1, 0x4e, 0xe9, 0x2f, 0x13, 0xf8, - 0x94, 0x59, 0xbf, 0x14, 0x78, 0xb2, 0xe4, 0xfb, 0x24, 0x73, 0x00, 0x15, 0x80, 0x65, 0x55, 0x41, - 0xed, 0x87, 0x57, 0x57, 0x52, 0x22, 0xaa, 0x03, 0x52, 0xe7, 0x10, 0xda, 0x95, 0x2a, 0xb9, 0xe9, - 0xfb, 0x5e, 0x93, 0x99, 0x3e, 0x51, 0x52, 0x87, 0xa5, 0xd4, 0xd1, 0x74, 0x11, 0x62, 0x50, 0xa8, - 0x1d, 0xc9, 0xe4, 0x78, 0x0c, 0xed, 0x83, 0xe1, 0x2a, 0x37, 0xb9, 0x96, 0x2e, 0x4b, 0xe9, 0x93, - 0x68, 0x77, 0x0f, 0x5a, 0xe8, 0x2f, 0x64, 0xf4, 0x33, 0xd9, 0x2f, 0x92, 0xba, 0xbb, 0x42, 0x58, - 0x5b, 0xd6, 0xe8, 0x38, 0xdc, 0xb9, 0x17, 0x5c, 0x66, 0x29, 0xd7, 0xe3, 0xf0, 0x0e, 0x15, 0x88, - 0xf0, 0x77, 0x02, 0x56, 0x98, 0x25, 0x5c, 0xf7, 0xf6, 0x5d, 0x70, 0x73, 0x54, 0x09, 0x7f, 0xe0, - 0xf6, 0x99, 0xa2, 0x1b, 0x38, 0x9c, 0x30, 0x7c, 0x9f, 0xae, 0x72, 0x0a, 0x9a, 0xa1, 0xac, 0xb5, - 0x6a, 0x32, 0x52, 0x12, 0x49, 0xe2, 0xeb, 0xa2, 0x9e, 0xfd, 0x9e, 0x00, 0xc7, 0xd2, 0x89, 0x29, - 0xf0, 0x01, 0xcf, 0x76, 0x4d, 0x0b, 0x5f, 0x9f, 0x20, 0x0f, 0xa3, 0x1d, 0x10, 0xa9, 0x12, 0x1c, - 0x2a, 0x0c, 0x5d, 0x51, 0xe8, 0xbe, 0xf4, 0xf6, 0xac, 0x12, 0x7b, 0xb9, 0x26, 0x98, 0xd1, 0x84, - 0x5c, 0xa6, 0xe7, 0x66, 0x09, 0x3f, 0x17, 0x2c, 0xd9, 0xb4, 0x7e, 0x96, 0xb4, 0xf1, 0x06, 0x99, - 0x45, 0x66, 0x5e, 0xc5, 0xc0, 0x46, 0x59, 0xcd, 0x9d, 0xe9, 0x3d, 0x59, 0xa5, 0x0d, 0xa7, 0xb6, - 0x86, 0x6f, 0x84, 0xcd, 0x6b, 0x7a, 0xfb, 0x6f, 0x91, 0xe6, 0x3b, 0xd0, 0x4d, 0x69, 0x40, 0x2c, - 0xc5, 0xd6, 0xae, 0x93, 0x6e, 0xd2, 0xb2, 0x98, 0x98, 0xb6, 0xbb, 0xe0, 0x49, 0xa7, 0x1e, 0xef, - 0x96, 0xea, 0x99, 0xb5, 0x14, 0xc1, 0xc9, 0x7f, 0xe3, 0x83, 0xf0, 0x5a, 0x9e, 0x27, 0x8c, 0x2e, - 0xb7, 0x15, 0x74, 0x48, 0x42, 0x99, 0x61, 0x26, 0xff, 0x5b, 0xc8, 0x85, 0x9d, 0x81, 0xc7, 0xa4, - 0xbf, 0x4c, 0x8f, 0x16, 0xa9, 0xd7, 0x24, 0xec, 0x2c, 0x69, 0x9f, 0x37, 0xed, 0x80, 0xe0, 0x6d, - 0xb0, 0x5a, 0x44, 0x11, 0x4b, 0x73, 0x27, 0xa5, 0x5a, 0x66, 0x7d, 0x84, 0xbb, 0x39, 0x8b, 0x38, - 0x9c, 0xf2, 0x36, 0x3e, 0x05, 0xcf, 0x04, 0xc1, 0x10, 0x4b, 0x53, 0x77, 0xea, 0x41, 0xb5, 0x2b, - 0xfb, 0xca, 0x28, 0x4e, 0xdf, 0x2f, 0x07, 0xa3, 0x58, 0xcd, 0xf7, 0x76, 0x19, 0x31, 0x69, 0xea, - 0x5e, 0x78, 0xc4, 0x14, 0x5d, 0x9f, 0x16, 0xdd, 0x56, 0x8b, 0x72, 0x3c, 0x0b, 0xeb, 0xc4, 0x44, - 0x8b, 0x38, 0x1c, 0xdf, 0x2f, 0x75, 0x32, 0xef, 0x10, 0x41, 0x89, 0x04, 0xf0, 0x1c, 0xbc, 0x36, - 0xea, 0x79, 0x54, 0xf3, 0xf7, 0x49, 0x91, 0x13, 0xe9, 0xdc, 0xa6, 0xc9, 0x52, 0xd0, 0x98, 0xa7, - 0xce, 0xa5, 0x69, 0x52, 0xa7, 0xe1, 0xdc, 0xb7, 0x0a, 0x1b, 0x9f, 0x48, 0x0e, 0x92, 0xa3, 0x5d, - 0x0c, 0x66, 0x09, 0x0f, 0x87, 0x0f, 0x26, 0x85, 0x21, 0x65, 0x90, 0x4d, 0x44, 0xc3, 0x11, 0xb9, - 0x5c, 0x30, 0x9e, 0x04, 0x02, 0x4d, 0x50, 0xae, 0x87, 0x1b, 0x05, 0xe3, 0x09, 0x60, 0x39, 0x35, - 0x34, 0xef, 0x36, 0x70, 0x53, 0x0a, 0x1d, 0x46, 0x7b, 0x40, 0xa6, 0x4c, 0x5a, 0x2e, 0x6b, 0x2f, - 0x12, 0xd3, 0xc2, 0x8e, 0x94, 0xbb, 0x35, 0x3d, 0x0c, 0x32, 0x28, 0x76, 0xa5, 0xe2, 0x11, 0x34, - 0xda, 0x03, 0xbb, 0xc0, 0x28, 0x27, 0xd8, 0x93, 0x92, 0xdd, 0xbc, 0xcf, 0xd8, 0xa6, 0xdf, 0x8c, - 0x06, 0xd7, 0x83, 0x12, 0x3d, 0x9a, 0x96, 0x2d, 0x71, 0xd1, 0xc2, 0x41, 0x2b, 0x35, 0x43, 0x9e, - 0x19, 0x90, 0xeb, 0x38, 0x96, 0xae, 0xb8, 0x82, 0x63, 0xf2, 0x59, 0x75, 0x3c, 0x1a, 0x4b, 0xbf, - 0x16, 0x12, 0xb2, 0x6a, 0x6b, 0xdf, 0x2d, 0x35, 0x33, 0xe9, 0x2b, 0x52, 0x61, 0xef, 0x81, 0x77, - 0xa4, 0xc2, 0xe4, 0x98, 0x9a, 0x80, 0xdf, 0x88, 0x8a, 0x8a, 0xc7, 0xd5, 0x3d, 0x52, 0x2e, 0xb3, - 0xd0, 0x31, 0x28, 0xc6, 0xd6, 0x69, 0xa9, 0x96, 0x29, 0x63, 0xd2, 0xa7, 0x1a, 0x2c, 0x67, 0x24, - 0x7a, 0x14, 0xed, 0x85, 0xd0, 0xf4, 0x14, 0x9a, 0x94, 0xf0, 0x38, 0x3a, 0x00, 0xc1, 0x1d, 0xd3, - 0x68, 0x0a, 0x0e, 0x76, 0xa1, 0x54, 0x4e, 0xd4, 0xb1, 0x08, 0xcf, 0xd8, 0x85, 0x52, 0x59, 0x11, - 0xd3, 0xf0, 0x91, 0x75, 0xa1, 0x54, 0x96, 0xd5, 0x2b, 0xc1, 0x6f, 0x4c, 0x09, 0x10, 0xab, 0xb6, - 0x86, 0x67, 0xe0, 0x01, 0xb4, 0x50, 0x2a, 0x4f, 0x93, 0x3a, 0x6b, 0x7b, 0x5c, 0xe5, 0x78, 0x16, - 0xae, 0x5d, 0x0c, 0x12, 0x4b, 0xa1, 0xf3, 0xf0, 0xd2, 0xce, 0x53, 0xff, 0x52, 0x22, 0x3f, 0x06, - 0x07, 0x27, 0x28, 0x85, 0xf8, 0x5d, 0xce, 0xc3, 0xd4, 0xbf, 0x24, 0x33, 0xe4, 0xf0, 0xe9, 0x4c, - 0x11, 0x61, 0x8a, 0x81, 0x54, 0xc9, 0x34, 0xa4, 0x62, 0x54, 0xd4, 0x2b, 0x52, 0x2a, 0xb3, 0x1f, - 0x05, 0xd6, 0xb1, 0x80, 0xab, 0x70, 0xd5, 0x04, 0x9b, 0xee, 0x8c, 0x35, 0xf8, 0x8d, 0x22, 0x4b, - 0x11, 0xef, 0xaf, 0x36, 0x3c, 0x50, 0x05, 0x17, 0x43, 0x97, 0xf5, 0xc9, 0x3d, 0x95, 0x48, 0x8d, - 0x5c, 0x76, 0xfd, 0x44, 0x61, 0x1f, 0xcb, 0x69, 0xb1, 0x91, 0x0e, 0x4e, 0x41, 0x8f, 0xe7, 0xf4, - 0x3b, 0x6c, 0x5b, 0x07, 0x24, 0x8b, 0x7b, 0x25, 0xa7, 0x5f, 0x16, 0xdb, 0x41, 0x26, 0x2c, 0xef, - 0x27, 0x72, 0x7a, 0x34, 0xec, 0x82, 0xc2, 0x8a, 0xe3, 0xff, 0x64, 0x4e, 0x8f, 0x86, 0x42, 0x07, - 0x19, 0x63, 0x9f, 0xca, 0xe9, 0xfe, 0x49, 0x9f, 0xe2, 0x38, 0xb1, 0x6d, 0x93, 0xc9, 0xe0, 0x7e, - 0x9e, 0xd3, 0x0d, 0xb9, 0x1b, 0xa0, 0x6a, 0x6b, 0x15, 0x4f, 0xcd, 0x86, 0x5f, 0x74, 0x89, 0x50, - 0xa2, 0x89, 0xd2, 0xfd, 0xb2, 0x4b, 0x84, 0x92, 0x54, 0xd8, 0xaf, 0x94, 0xe0, 0xf1, 0xf4, 0x91, - 0x5a, 0x62, 0x45, 0x46, 0xc2, 0x23, 0x72, 0x5d, 0x1c, 0x38, 0x2b, 0x1e, 0x7e, 0x2e, 0xa7, 0xa7, - 0xd8, 0x4e, 0x00, 0x3f, 0x67, 0xb6, 0xc5, 0x4b, 0xb7, 0xe2, 0xe1, 0xe7, 0x73, 0x7a, 0xea, 0x8c, - 0x82, 0x20, 0x6f, 0xc6, 0xf0, 0x0b, 0xbd, 0xe1, 0xb2, 0xe9, 0x98, 0x0d, 0x52, 0x59, 0x5e, 0x26, - 0xac, 0xe2, 0xe1, 0x17, 0x15, 0x7c, 0x3b, 0x3a, 0xd4, 0x35, 0x62, 0x71, 0xc6, 0xa7, 0x2b, 0xda, - 0xe6, 0xa5, 0x9c, 0xde, 0x11, 0x7b, 0xa0, 0x75, 0x20, 0xbc, 0xe2, 0x71, 0xea, 0x3a, 0x7e, 0xc5, - 0xc3, 0x2f, 0xf7, 0x0e, 0x26, 0xba, 0x45, 0xd7, 0x58, 0xe0, 0x8b, 0xc8, 0xaf, 0xf5, 0x16, 0x9e, - 0xb4, 0x6d, 0x77, 0x55, 0xb1, 0xaf, 0x28, 0xf6, 0x58, 0x7a, 0x10, 0x2b, 0x36, 0x2a, 0x72, 0x99, - 0xb0, 0x06, 0xa9, 0x78, 0xf8, 0xd5, 0xde, 0xca, 0x51, 0x4d, 0xa6, 0x4d, 0x6e, 0x56, 0x3c, 0xfc, - 0x5a, 0x6f, 0xe5, 0xa9, 0xa0, 0xe5, 0x55, 0x45, 0x03, 0x39, 0x75, 0xa1, 0xfc, 0x7a, 0x4e, 0xef, - 0xe4, 0x1d, 0x5d, 0x9a, 0x32, 0xdc, 0x0d, 0x6f, 0xe4, 0xf4, 0xb4, 0x49, 0xf7, 0x38, 0x73, 0x9d, - 0x44, 0xa3, 0xbd, 0x99, 0xd3, 0x83, 0x6b, 0x5b, 0x16, 0x53, 0xcc, 0x5b, 0x39, 0x7d, 0x48, 0xde, - 0x9a, 0x65, 0xe4, 0x26, 0x78, 0xbb, 0xdb, 0x56, 0x97, 0x48, 0x18, 0xd2, 0x3b, 0x5d, 0xf6, 0x53, - 0xd1, 0x64, 0x96, 0xe9, 0xb8, 0x52, 0xea, 0x1b, 0x79, 0xb8, 0x49, 0x25, 0x15, 0xbf, 0x69, 0x9f, - 0xca, 0xeb, 0x0f, 0x03, 0x7b, 0x00, 0x30, 0xb5, 0xe3, 0xbf, 0xd9, 0x5b, 0x34, 0x06, 0xbf, 0x95, - 0x87, 0xb7, 0x68, 0x2c, 0xaa, 0xaa, 0xf2, 0xed, 0x3c, 0xbc, 0x45, 0x25, 0xa9, 0xb0, 0xef, 0xe4, - 0xf5, 0x3b, 0x76, 0x04, 0x4c, 0x47, 0x9c, 0x07, 0xae, 0xe6, 0xe1, 0x45, 0x4d, 0x54, 0x26, 0xac, - 0xe0, 0x77, 0x95, 0x58, 0x66, 0xd6, 0x54, 0x1c, 0xee, 0xda, 0x6e, 0xa3, 0x9d, 0x08, 0xef, 0x37, - 0x5d, 0x24, 0x15, 0xaa, 0xb8, 0xdf, 0xe6, 0xf5, 0x15, 0x7e, 0xb4, 0x8b, 0x64, 0x5c, 0x9d, 0xdf, - 0xe5, 0xe1, 0x73, 0x9a, 0x82, 0x63, 0xf2, 0xf7, 0xeb, 0xc8, 0x86, 0x8b, 0xcd, 0x4c, 0xc7, 0x5f, - 0x26, 0x0c, 0xff, 0x41, 0xc9, 0x66, 0xc6, 0x58, 0x12, 0x26, 0x96, 0xc6, 0xff, 0xa8, 0xb4, 0xc7, - 0xd1, 0xfe, 0x6e, 0xf8, 0x05, 0xca, 0x9b, 0x16, 0x33, 0x57, 0x2b, 0x4e, 0x03, 0xff, 0x49, 0xc9, - 0x9f, 0x44, 0xb7, 0x76, 0x97, 0x4f, 0x5a, 0xfc, 0x39, 0xaf, 0x3f, 0x3e, 0x74, 0xb5, 0xa8, 0x38, - 0x7c, 0xce, 0x5a, 0x24, 0x0d, 0xea, 0x8b, 0xbb, 0xfc, 0x1b, 0x79, 0x78, 0xae, 0xa5, 0x7d, 0xa4, - 0x6d, 0xfe, 0xa2, 0xbc, 0x9c, 0x42, 0x47, 0x7a, 0x7a, 0x99, 0xb4, 0xac, 0x49, 0xce, 0x19, 0x5d, - 0x0a, 0x38, 0xf1, 0xf1, 0x5f, 0x95, 0xab, 0xbb, 0xd0, 0xb1, 0x75, 0x5c, 0xa5, 0x0d, 0xff, 0x96, - 0xd7, 0xa7, 0x85, 0xd4, 0x26, 0x58, 0xa4, 0x9e, 0x67, 0x93, 0x44, 0xef, 0x3c, 0x3c, 0x00, 0xbf, - 0x6f, 0x23, 0x50, 0x51, 0x1f, 0x1d, 0x80, 0x3b, 0x3b, 0xa2, 0xe4, 0x6e, 0x7e, 0x64, 0x00, 0xde, - 0x25, 0x31, 0x14, 0x36, 0xf6, 0xa3, 0x0a, 0x7b, 0x37, 0x1a, 0x4b, 0xdd, 0x9f, 0x5d, 0x87, 0x30, - 0x37, 0x5c, 0x79, 0xb3, 0x2e, 0x66, 0xfc, 0x9c, 0x43, 0xb9, 0x1a, 0x00, 0x7f, 0x1f, 0xd0, 0x17, - 0xbb, 0x03, 0xeb, 0x1a, 0x89, 0x6d, 0xf6, 0x0f, 0x65, 0x90, 0xa9, 0x5c, 0x87, 0x41, 0x95, 0xf0, - 0x39, 0xc7, 0x0b, 0xb4, 0xa7, 0x7f, 0x2a, 0xc3, 0xf5, 0xc2, 0x53, 0x86, 0xc2, 0xdb, 0xbf, 0x94, - 0xd1, 0x19, 0x74, 0x6a, 0x9d, 0xf0, 0xbc, 0x80, 0xfb, 0xe7, 0x08, 0x6b, 0x05, 0xdc, 0x14, 0x7f, - 0x50, 0x6e, 0xff, 0xad, 0x14, 0x4e, 0xa3, 0xdb, 0xfe, 0x3f, 0x05, 0xe1, 0xff, 0x4d, 0x65, 0x7d, - 0x37, 0x3a, 0xbe, 0xbe, 0xf5, 0x79, 0xea, 0x50, 0xe5, 0xf7, 0x2d, 0x65, 0x79, 0x07, 0x3a, 0xdc, - 0x9f, 0xa5, 0xf0, 0xf7, 0xb6, 0xb2, 0xba, 0x07, 0x9d, 0xec, 0x69, 0x35, 0x69, 0xdb, 0x51, 0xc0, - 0x55, 0xa2, 0x2b, 0xfc, 0x4e, 0xbf, 0x4b, 0x93, 0x34, 0x16, 0x5e, 0xff, 0xd3, 0x6f, 0x96, 0xe2, - 0x98, 0x10, 0xf0, 0xc4, 0xa2, 0xfe, 0xb7, 0xdf, 0x2c, 0xb5, 0xa5, 0xf0, 0xf7, 0x7e, 0xa3, 0x4f, - 0x7f, 0x93, 0xb6, 0x5d, 0x09, 0x78, 0x22, 0xc5, 0x0f, 0x18, 0x7d, 0xfa, 0xd3, 0x96, 0xc2, 0xdf, - 0x07, 0xfb, 0xf5, 0x17, 0x7e, 0xf4, 0x49, 0x36, 0xed, 0x87, 0xfa, 0xf5, 0xa7, 0x2d, 0x85, 0xbf, - 0x0f, 0xf7, 0x6b, 0x35, 0x43, 0x1d, 0xd3, 0x56, 0xbe, 0x3e, 0x62, 0xc0, 0x03, 0x13, 0xb6, 0x12, - 0x7e, 0x1e, 0x52, 0x16, 0x77, 0xa2, 0xa3, 0x9d, 0x16, 0x67, 0x49, 0x7b, 0xae, 0x65, 0x36, 0x48, - 0x69, 0xcd, 0x73, 0x19, 0x4f, 0x6e, 0xfa, 0x47, 0x94, 0x5d, 0x66, 0xd0, 0x76, 0xb3, 0x13, 0xbe, - 0x1e, 0xed, 0x99, 0x93, 0xb2, 0xa9, 0xb6, 0x9d, 0x7a, 0x95, 0x13, 0x7d, 0x5a, 0xff, 0x58, 0xcf, - 0x9c, 0xb2, 0x56, 0xc2, 0xcf, 0xc7, 0x0d, 0x78, 0xa0, 0x77, 0x5a, 0xa4, 0x8a, 0xf7, 0x98, 0x32, - 0xbb, 0x0d, 0x1d, 0xec, 0xc3, 0x4c, 0x78, 0x7a, 0xdc, 0x80, 0x47, 0x79, 0x64, 0x92, 0x18, 0xe5, - 0x9f, 0x36, 0xe0, 0x51, 0x1e, 0x81, 0x8a, 0xfa, 0x8c, 0x01, 0x9f, 0x7a, 0xb4, 0xdc, 0x05, 0x93, - 0xd7, 0x9b, 0xe2, 0xbd, 0xfe, 0x59, 0x03, 0x9e, 0xe7, 0x11, 0xa9, 0xb1, 0xcf, 0x19, 0xf0, 0xc5, - 0x24, 0xfc, 0x50, 0x14, 0xb1, 0xd3, 0xd4, 0x6c, 0xa8, 0x0a, 0x7c, 0xde, 0x80, 0xef, 0x50, 0x19, - 0x5c, 0x64, 0xfe, 0x05, 0xa5, 0x9c, 0x39, 0x2d, 0xeb, 0x50, 0x6b, 0x6b, 0x67, 0x89, 0xfe, 0xa9, - 0xe3, 0x8b, 0x06, 0x7c, 0x60, 0x49, 0xd3, 0x42, 0xf7, 0x4b, 0x3d, 0x7b, 0x64, 0x9e, 0xae, 0x90, - 0x45, 0xb2, 0xcc, 0x88, 0xdf, 0xac, 0x72, 0x93, 0xe9, 0x6e, 0x7c, 0xd2, 0x80, 0x8f, 0x16, 0xb0, - 0x95, 0xf0, 0xf3, 0x65, 0xa3, 0xd7, 0xab, 0x24, 0x65, 0x11, 0xb7, 0xe2, 0x57, 0x94, 0x1b, 0xf0, - 0x4d, 0x97, 0x31, 0x12, 0x5e, 0xbe, 0xda, 0x6f, 0x36, 0xa9, 0x46, 0xfc, 0x5a, 0xbf, 0xd9, 0xe8, - 0x3e, 0xfc, 0xba, 0x01, 0x7f, 0x0a, 0x28, 0x65, 0x6e, 0xdc, 0xd7, 0x0c, 0xf8, 0x7e, 0x50, 0x4a, - 0xde, 0xb7, 0x5f, 0x31, 0xf4, 0x67, 0x96, 0x2d, 0x19, 0x48, 0x9e, 0x26, 0x5e, 0xed, 0xd2, 0x27, - 0x25, 0xd7, 0x17, 0x07, 0xe9, 0xe4, 0xbb, 0xf3, 0xd7, 0x06, 0x7c, 0xff, 0x49, 0xa0, 0x22, 0x81, - 0xd7, 0x0c, 0xf8, 0xfe, 0x53, 0x4a, 0x7c, 0x58, 0x78, 0xbd, 0xcb, 0xee, 0x98, 0xa2, 0x8e, 0xe9, - 0xd4, 0x93, 0x07, 0xa7, 0x1f, 0x0c, 0xc2, 0xbb, 0x43, 0x92, 0x0a, 0xfb, 0xe1, 0x20, 0x7c, 0x73, - 0x89, 0x05, 0xe3, 0xa2, 0xfc, 0x68, 0x10, 0xbe, 0xb9, 0x48, 0x36, 0x06, 0x7f, 0x3c, 0x08, 0xdf, - 0xae, 0x24, 0x28, 0x2b, 0xf8, 0x74, 0x6f, 0xb9, 0xf8, 0x76, 0xf5, 0x93, 0x41, 0xf8, 0xaa, 0xa1, - 0x40, 0x79, 0x18, 0x2f, 0xfb, 0x0d, 0xfc, 0xcc, 0x20, 0x7c, 0xd5, 0x90, 0x68, 0x85, 0x59, 0x11, - 0xf7, 0x6c, 0x6f, 0xdf, 0xd1, 0x8f, 0xb4, 0x02, 0xfc, 0x69, 0x6f, 0x41, 0xbd, 0x30, 0x3f, 0x93, - 0x31, 0x4e, 0x9c, 0x46, 0xd7, 0xaf, 0x52, 0x46, 0x2e, 0x52, 0x67, 0x78, 0xef, 0x78, 0xf4, 0x4b, - 0xff, 0xb8, 0xfa, 0xa5, 0x7f, 0xbc, 0xe4, 0x04, 0xad, 0xf0, 0xe7, 0x12, 0xf9, 0x95, 0x60, 0xe4, - 0xb9, 0x87, 0x06, 0x46, 0x73, 0x63, 0x43, 0x8b, 0xd7, 0x09, 0x9b, 0x39, 0x67, 0xe2, 0x5e, 0x34, - 0x14, 0x5a, 0xbb, 0x01, 0xef, 0xc7, 0xfc, 0x79, 0x69, 0x1e, 0xba, 0xac, 0x04, 0x7c, 0x62, 0x16, - 0x6d, 0x0a, 0xed, 0x2d, 0x31, 0xad, 0xfa, 0x8c, 0xe1, 0x05, 0x29, 0xb2, 0x41, 0x58, 0x86, 0x63, - 0x6e, 0xce, 0x99, 0x98, 0x43, 0x9b, 0x13, 0x42, 0x7d, 0x86, 0xf3, 0xa2, 0x54, 0xda, 0xa8, 0x95, - 0x44, 0x4c, 0x67, 0xd0, 0x0d, 0xa1, 0x14, 0xa7, 0x4e, 0xbb, 0x1f, 0x95, 0x97, 0xa4, 0x4a, 0x58, - 0x89, 0x1a, 0x75, 0xda, 0x13, 0xf3, 0xe8, 0xc6, 0x50, 0x61, 0xc9, 0x75, 0xb9, 0xed, 0x9a, 0x16, - 0x61, 0xfd, 0xe8, 0xbc, 0x2c, 0x75, 0xc2, 0x44, 0xa6, 0xb4, 0xe9, 0x44, 0x11, 0x85, 0x99, 0x5e, - 0x74, 0xdc, 0x8b, 0xcb, 0x7e, 0xab, 0x1f, 0xa5, 0x6b, 0x52, 0x29, 0xcc, 0x63, 0xc1, 0x9d, 0xf1, - 0x5b, 0x53, 0x77, 0xa0, 0xfd, 0x75, 0xb7, 0x35, 0xee, 0x9b, 0xdc, 0xf5, 0x9b, 0xd4, 0x36, 0x97, - 0x7c, 0xf5, 0xff, 0x79, 0xd8, 0x74, 0x49, 0x4b, 0x4d, 0x6d, 0xaa, 0x85, 0x7f, 0x94, 0x9d, 0xf3, - 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x69, 0x67, 0x5d, 0x1f, 0x22, 0x00, 0x00, -} diff --git a/builder/accounts/usbwallet/trezor/messages.proto b/builder/accounts/usbwallet/trezor/messages.proto deleted file mode 100644 index 3e0482e34..000000000 --- a/builder/accounts/usbwallet/trezor/messages.proto +++ /dev/null @@ -1,264 +0,0 @@ -// This file originates from the SatoshiLabs Trezor `common` repository at: -// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto -// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9. - -syntax = "proto2"; -package hw.trezor.messages; - -/** - * Messages for TREZOR communication - */ - -// Sugar for easier handling in Java -option java_package = "com.satoshilabs.trezor.lib.protobuf"; -option java_outer_classname = "TrezorMessage"; - -import "google/protobuf/descriptor.proto"; - -/** - * Options for specifying message direction and type of wire (normal/debug) - */ -extend google.protobuf.EnumValueOptions { - optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR - optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC - optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR - optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC - optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode - optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader - optional bool wire_no_fsm = 50008; // message is not handled by TREZOR unless the USB stack is in tiny mode -} - -/** - * Mapping between TREZOR wire identifier (uint) and a protobuf message - */ -enum MessageType { - - // Management - MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = true]; - MessageType_Ping = 1 [(wire_in) = true]; - MessageType_Success = 2 [(wire_out) = true]; - MessageType_Failure = 3 [(wire_out) = true]; - MessageType_ChangePin = 4 [(wire_in) = true]; - MessageType_WipeDevice = 5 [(wire_in) = true]; - MessageType_GetEntropy = 9 [(wire_in) = true]; - MessageType_Entropy = 10 [(wire_out) = true]; - MessageType_LoadDevice = 13 [(wire_in) = true]; - MessageType_ResetDevice = 14 [(wire_in) = true]; - MessageType_Features = 17 [(wire_out) = true]; - MessageType_PinMatrixRequest = 18 [(wire_out) = true]; - MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; - MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true]; - MessageType_ClearSession = 24 [(wire_in) = true]; - MessageType_ApplySettings = 25 [(wire_in) = true]; - MessageType_ButtonRequest = 26 [(wire_out) = true]; - MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; - MessageType_ApplyFlags = 28 [(wire_in) = true]; - MessageType_BackupDevice = 34 [(wire_in) = true]; - MessageType_EntropyRequest = 35 [(wire_out) = true]; - MessageType_EntropyAck = 36 [(wire_in) = true]; - MessageType_PassphraseRequest = 41 [(wire_out) = true]; - MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; - MessageType_PassphraseStateRequest = 77 [(wire_out) = true]; - MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; - MessageType_RecoveryDevice = 45 [(wire_in) = true]; - MessageType_WordRequest = 46 [(wire_out) = true]; - MessageType_WordAck = 47 [(wire_in) = true]; - MessageType_GetFeatures = 55 [(wire_in) = true]; - MessageType_SetU2FCounter = 63 [(wire_in) = true]; - - // Bootloader - MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true]; - MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true]; - MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true]; - MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true]; - - // Bitcoin - MessageType_GetPublicKey = 11 [(wire_in) = true]; - MessageType_PublicKey = 12 [(wire_out) = true]; - MessageType_SignTx = 15 [(wire_in) = true]; - MessageType_TxRequest = 21 [(wire_out) = true]; - MessageType_TxAck = 22 [(wire_in) = true]; - MessageType_GetAddress = 29 [(wire_in) = true]; - MessageType_Address = 30 [(wire_out) = true]; - MessageType_SignMessage = 38 [(wire_in) = true]; - MessageType_VerifyMessage = 39 [(wire_in) = true]; - MessageType_MessageSignature = 40 [(wire_out) = true]; - - // Crypto - MessageType_CipherKeyValue = 23 [(wire_in) = true]; - MessageType_CipheredKeyValue = 48 [(wire_out) = true]; - MessageType_SignIdentity = 53 [(wire_in) = true]; - MessageType_SignedIdentity = 54 [(wire_out) = true]; - MessageType_GetECDHSessionKey = 61 [(wire_in) = true]; - MessageType_ECDHSessionKey = 62 [(wire_out) = true]; - MessageType_CosiCommit = 71 [(wire_in) = true]; - MessageType_CosiCommitment = 72 [(wire_out) = true]; - MessageType_CosiSign = 73 [(wire_in) = true]; - MessageType_CosiSignature = 74 [(wire_out) = true]; - - // Debug - MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true]; - MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = true]; - MessageType_DebugLinkState = 102 [(wire_debug_out) = true]; - MessageType_DebugLinkStop = 103 [(wire_debug_in) = true]; - MessageType_DebugLinkLog = 104 [(wire_debug_out) = true]; - MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true]; - MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true]; - MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true]; - MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true]; - - // Ethereum - MessageType_EthereumGetPublicKey = 450 [(wire_in) = true]; - MessageType_EthereumPublicKey = 451 [(wire_out) = true]; - MessageType_EthereumGetAddress = 56 [(wire_in) = true]; - MessageType_EthereumAddress = 57 [(wire_out) = true]; - MessageType_EthereumSignTx = 58 [(wire_in) = true]; - MessageType_EthereumTxRequest = 59 [(wire_out) = true]; - MessageType_EthereumTxAck = 60 [(wire_in) = true]; - MessageType_EthereumSignMessage = 64 [(wire_in) = true]; - MessageType_EthereumVerifyMessage = 65 [(wire_in) = true]; - MessageType_EthereumMessageSignature = 66 [(wire_out) = true]; - - // NEM - MessageType_NEMGetAddress = 67 [(wire_in) = true]; - MessageType_NEMAddress = 68 [(wire_out) = true]; - MessageType_NEMSignTx = 69 [(wire_in) = true]; - MessageType_NEMSignedTx = 70 [(wire_out) = true]; - MessageType_NEMDecryptMessage = 75 [(wire_in) = true]; - MessageType_NEMDecryptedMessage = 76 [(wire_out) = true]; - - // Lisk - MessageType_LiskGetAddress = 114 [(wire_in) = true]; - MessageType_LiskAddress = 115 [(wire_out) = true]; - MessageType_LiskSignTx = 116 [(wire_in) = true]; - MessageType_LiskSignedTx = 117 [(wire_out) = true]; - MessageType_LiskSignMessage = 118 [(wire_in) = true]; - MessageType_LiskMessageSignature = 119 [(wire_out) = true]; - MessageType_LiskVerifyMessage = 120 [(wire_in) = true]; - MessageType_LiskGetPublicKey = 121 [(wire_in) = true]; - MessageType_LiskPublicKey = 122 [(wire_out) = true]; - - // Tezos - MessageType_TezosGetAddress = 150 [(wire_in) = true]; - MessageType_TezosAddress = 151 [(wire_out) = true]; - MessageType_TezosSignTx = 152 [(wire_in) = true]; - MessageType_TezosSignedTx = 153 [(wire_out) = true]; - MessageType_TezosGetPublicKey = 154 [(wire_in) = true]; - MessageType_TezosPublicKey = 155 [(wire_out) = true]; - - // Stellar - MessageType_StellarSignTx = 202 [(wire_in) = true]; - MessageType_StellarTxOpRequest = 203 [(wire_out) = true]; - MessageType_StellarGetAddress = 207 [(wire_in) = true]; - MessageType_StellarAddress = 208 [(wire_out) = true]; - MessageType_StellarCreateAccountOp = 210 [(wire_in) = true]; - MessageType_StellarPaymentOp = 211 [(wire_in) = true]; - MessageType_StellarPathPaymentOp = 212 [(wire_in) = true]; - MessageType_StellarManageOfferOp = 213 [(wire_in) = true]; - MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true]; - MessageType_StellarSetOptionsOp = 215 [(wire_in) = true]; - MessageType_StellarChangeTrustOp = 216 [(wire_in) = true]; - MessageType_StellarAllowTrustOp = 217 [(wire_in) = true]; - MessageType_StellarAccountMergeOp = 218 [(wire_in) = true]; - // omitted: StellarInflationOp is not a supported operation, would be 219 - MessageType_StellarManageDataOp = 220 [(wire_in) = true]; - MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true]; - MessageType_StellarSignedTx = 230 [(wire_out) = true]; - - // TRON - MessageType_TronGetAddress = 250 [(wire_in) = true]; - MessageType_TronAddress = 251 [(wire_out) = true]; - MessageType_TronSignTx = 252 [(wire_in) = true]; - MessageType_TronSignedTx = 253 [(wire_out) = true]; - - // Cardano - // dropped Sign/VerifyMessage ids 300-302 - MessageType_CardanoSignTx = 303 [(wire_in) = true]; - MessageType_CardanoTxRequest = 304 [(wire_out) = true]; - MessageType_CardanoGetPublicKey = 305 [(wire_in) = true]; - MessageType_CardanoPublicKey = 306 [(wire_out) = true]; - MessageType_CardanoGetAddress = 307 [(wire_in) = true]; - MessageType_CardanoAddress = 308 [(wire_out) = true]; - MessageType_CardanoTxAck = 309 [(wire_in) = true]; - MessageType_CardanoSignedTx = 310 [(wire_out) = true]; - - // Ontology - MessageType_OntologyGetAddress = 350 [(wire_in) = true]; - MessageType_OntologyAddress = 351 [(wire_out) = true]; - MessageType_OntologyGetPublicKey = 352 [(wire_in) = true]; - MessageType_OntologyPublicKey = 353 [(wire_out) = true]; - MessageType_OntologySignTransfer = 354 [(wire_in) = true]; - MessageType_OntologySignedTransfer = 355 [(wire_out) = true]; - MessageType_OntologySignWithdrawOng = 356 [(wire_in) = true]; - MessageType_OntologySignedWithdrawOng = 357 [(wire_out) = true]; - MessageType_OntologySignOntIdRegister = 358 [(wire_in) = true]; - MessageType_OntologySignedOntIdRegister = 359 [(wire_out) = true]; - MessageType_OntologySignOntIdAddAttributes = 360 [(wire_in) = true]; - MessageType_OntologySignedOntIdAddAttributes = 361 [(wire_out) = true]; - - // Ripple - MessageType_RippleGetAddress = 400 [(wire_in) = true]; - MessageType_RippleAddress = 401 [(wire_out) = true]; - MessageType_RippleSignTx = 402 [(wire_in) = true]; - MessageType_RippleSignedTx = 403 [(wire_in) = true]; - - // Monero - MessageType_MoneroTransactionInitRequest = 501 [(wire_out) = true]; - MessageType_MoneroTransactionInitAck = 502 [(wire_out) = true]; - MessageType_MoneroTransactionSetInputRequest = 503 [(wire_out) = true]; - MessageType_MoneroTransactionSetInputAck = 504 [(wire_out) = true]; - MessageType_MoneroTransactionInputsPermutationRequest = 505 [(wire_out) = true]; - MessageType_MoneroTransactionInputsPermutationAck = 506 [(wire_out) = true]; - MessageType_MoneroTransactionInputViniRequest = 507 [(wire_out) = true]; - MessageType_MoneroTransactionInputViniAck = 508 [(wire_out) = true]; - MessageType_MoneroTransactionAllInputsSetRequest = 509 [(wire_out) = true]; - MessageType_MoneroTransactionAllInputsSetAck = 510 [(wire_out) = true]; - MessageType_MoneroTransactionSetOutputRequest = 511 [(wire_out) = true]; - MessageType_MoneroTransactionSetOutputAck = 512 [(wire_out) = true]; - MessageType_MoneroTransactionAllOutSetRequest = 513 [(wire_out) = true]; - MessageType_MoneroTransactionAllOutSetAck = 514 [(wire_out) = true]; - MessageType_MoneroTransactionSignInputRequest = 515 [(wire_out) = true]; - MessageType_MoneroTransactionSignInputAck = 516 [(wire_out) = true]; - MessageType_MoneroTransactionFinalRequest = 517 [(wire_out) = true]; - MessageType_MoneroTransactionFinalAck = 518 [(wire_out) = true]; - MessageType_MoneroKeyImageExportInitRequest = 530 [(wire_out) = true]; - MessageType_MoneroKeyImageExportInitAck = 531 [(wire_out) = true]; - MessageType_MoneroKeyImageSyncStepRequest = 532 [(wire_out) = true]; - MessageType_MoneroKeyImageSyncStepAck = 533 [(wire_out) = true]; - MessageType_MoneroKeyImageSyncFinalRequest = 534 [(wire_out) = true]; - MessageType_MoneroKeyImageSyncFinalAck = 535 [(wire_out) = true]; - MessageType_MoneroGetAddress = 540 [(wire_in) = true]; - MessageType_MoneroAddress = 541 [(wire_out) = true]; - MessageType_MoneroGetWatchKey = 542 [(wire_in) = true]; - MessageType_MoneroWatchKey = 543 [(wire_out) = true]; - MessageType_DebugMoneroDiagRequest = 546 [(wire_in) = true]; - MessageType_DebugMoneroDiagAck = 547 [(wire_out) = true]; - MessageType_MoneroGetTxKeyRequest = 550 [(wire_in) = true]; - MessageType_MoneroGetTxKeyAck = 551 [(wire_out) = true]; - MessageType_MoneroLiveRefreshStartRequest = 552 [(wire_in) = true]; - MessageType_MoneroLiveRefreshStartAck = 553 [(wire_out) = true]; - MessageType_MoneroLiveRefreshStepRequest = 554 [(wire_in) = true]; - MessageType_MoneroLiveRefreshStepAck = 555 [(wire_out) = true]; - MessageType_MoneroLiveRefreshFinalRequest = 556 [(wire_in) = true]; - MessageType_MoneroLiveRefreshFinalAck = 557 [(wire_out) = true]; - - // EOS - MessageType_EosGetPublicKey = 600 [(wire_in) = true]; - MessageType_EosPublicKey = 601 [(wire_out) = true]; - MessageType_EosSignTx = 602 [(wire_in) = true]; - MessageType_EosTxActionRequest = 603 [(wire_out) = true]; - MessageType_EosTxActionAck = 604 [(wire_in) = true]; - MessageType_EosSignedTx = 605 [(wire_out) = true]; - - // Binance - MessageType_BinanceGetAddress = 700 [(wire_in) = true]; - MessageType_BinanceAddress = 701 [(wire_out) = true]; - MessageType_BinanceGetPublicKey = 702 [(wire_in) = true]; - MessageType_BinancePublicKey = 703 [(wire_out) = true]; - MessageType_BinanceSignTx = 704 [(wire_in) = true]; - MessageType_BinanceTxRequest = 705 [(wire_out) = true]; - MessageType_BinanceTransferMsg = 706 [(wire_in) = true]; - MessageType_BinanceOrderMsg = 707 [(wire_in) = true]; - MessageType_BinanceCancelMsg = 708 [(wire_in) = true]; - MessageType_BinanceSignedTx = 709 [(wire_out) = true]; -} diff --git a/builder/accounts/usbwallet/trezor/trezor.go b/builder/accounts/usbwallet/trezor/trezor.go deleted file mode 100644 index cdca6b4e0..000000000 --- a/builder/accounts/usbwallet/trezor/trezor.go +++ /dev/null @@ -1,70 +0,0 @@ -// 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 . - -// This file contains the implementation for interacting with the Trezor hardware -// wallets. The wire protocol spec can be found on the SatoshiLabs website: -// https://docs.trezor.io/trezor-firmware/common/message-workflows.html - -// !!! STAHP !!! -// -// Before you touch the protocol files, you need to be aware of a breaking change -// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10-> -// 2.1.0 (Model T). The Ethereum address representation was changed from the 20 -// byte binary blob to a 42 byte hex string. The upstream protocol buffer files -// only support the new format, so blindly pulling in a new spec will break old -// devices! -// -// The Trezor devs had the foresight to add the string version as a new message -// code instead of replacing the binary one. This means that the proto file can -// actually define both the old and the new versions as optional. Please ensure -// that you add back the old addresses everywhere (to avoid name clash. use the -// addressBin and addressHex names). -// -// If in doubt, reach out to @karalabe. - -// To regenerate the protocol files in this package: -// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases -// - Build with the usual `./configure && make` and ensure it's on your $PATH -// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor -// - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go` -// - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...` - -//go:generate protoc -I/usr/local/include:. --go_out=import_path=trezor:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto - -// Package trezor contains the wire protocol. -package trezor - -import ( - "reflect" - - "github.com/golang/protobuf/proto" -) - -// Type returns the protocol buffer type number of a specific message. If the -// message is nil, this method panics! -func Type(msg proto.Message) uint16 { - return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()]) -} - -// Name returns the friendly message type name of a specific protocol buffer -// type number. -func Name(kind uint16) string { - name := MessageType_name[int32(kind)] - if len(name) < 12 { - return name - } - return name[12:] -} diff --git a/builder/accounts/usbwallet/wallet.go b/builder/accounts/usbwallet/wallet.go deleted file mode 100644 index 69083dc89..000000000 --- a/builder/accounts/usbwallet/wallet.go +++ /dev/null @@ -1,643 +0,0 @@ -// 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 usbwallet implements support for USB hardware wallets. -package usbwallet - -import ( - "context" - "fmt" - "io" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/karalabe/usb" -) - -// Maximum time between wallet health checks to detect USB unplugs. -const heartbeatCycle = time.Second - -// Minimum time to wait between self derivation attempts, even it the user is -// requesting accounts like crazy. -const selfDeriveThrottling = time.Second - -// driver defines the vendor specific functionality hardware wallets instances -// must implement to allow using them with the wallet lifecycle management. -type driver interface { - // Status returns a textual status to aid the user in the current state of the - // wallet. It also returns an error indicating any failure the wallet might have - // encountered. - Status() (string, error) - - // Open initializes access to a wallet instance. The passphrase parameter may - // or may not be used by the implementation of a particular wallet instance. - Open(device io.ReadWriter, passphrase string) error - - // Close releases any resources held by an open wallet instance. - Close() error - - // Heartbeat performs a sanity check against the hardware wallet to see if it - // is still online and healthy. - Heartbeat() error - - // Derive sends a derivation request to the USB device and returns the Ethereum - // address located on that path. - Derive(path accounts.DerivationPath) (common.Address, error) - - // SignTx sends the transaction to the USB device and waits for the user to confirm - // or deny the transaction. - SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) - - SignTypedMessage(path accounts.DerivationPath, messageHash []byte, domainHash []byte) ([]byte, error) -} - -// wallet represents the common functionality shared by all USB hardware -// wallets to prevent reimplementing the same complex maintenance mechanisms -// for different vendors. -type wallet struct { - hub *Hub // USB hub scanning - driver driver // Hardware implementation of the low level device operations - url *accounts.URL // Textual URL uniquely identifying this wallet - - info usb.DeviceInfo // Known USB device infos about the wallet - device usb.Device // USB device advertising itself as a hardware wallet - - accounts []accounts.Account // List of derive accounts pinned on the hardware wallet - paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations - - deriveNextPaths []accounts.DerivationPath // Next derivation paths for account auto-discovery (multiple bases supported) - deriveNextAddrs []common.Address // Next derived account addresses for auto-discovery (multiple bases supported) - deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with - deriveReq chan chan struct{} // Channel to request a self-derivation on - deriveQuit chan chan error // Channel to terminate the self-deriver with - - healthQuit chan chan error - - // Locking a hardware wallet is a bit special. Since hardware devices are lower - // performing, any communication with them might take a non negligible amount of - // time. Worse still, waiting for user confirmation can take arbitrarily long, - // but exclusive communication must be upheld during. Locking the entire wallet - // in the mean time however would stall any parts of the system that don't want - // to communicate, just read some state (e.g. list the accounts). - // - // As such, a hardware wallet needs two locks to function correctly. A state - // lock can be used to protect the wallet's software-side internal state, which - // must not be held exclusively during hardware communication. A communication - // lock can be used to achieve exclusive access to the device itself, this one - // however should allow "skipping" waiting for operations that might want to - // use the device, but can live without too (e.g. account self-derivation). - // - // Since we have two locks, it's important to know how to properly use them: - // - Communication requires the `device` to not change, so obtaining the - // commsLock should be done after having a stateLock. - // - Communication must not disable read access to the wallet state, so it - // must only ever hold a *read* lock to stateLock. - commsLock chan struct{} // Mutex (buf=1) for the USB comms without keeping the state locked - stateLock sync.RWMutex // Protects read and write access to the wallet struct fields - - log log.Logger // Contextual logger to tag the base with its id -} - -// URL implements accounts.Wallet, returning the URL of the USB hardware device. -func (w *wallet) URL() accounts.URL { - return *w.url // Immutable, no need for a lock -} - -// Status implements accounts.Wallet, returning a custom status message from the -// underlying vendor-specific hardware wallet implementation. -func (w *wallet) Status() (string, error) { - w.stateLock.RLock() // No device communication, state lock is enough - defer w.stateLock.RUnlock() - - status, failure := w.driver.Status() - if w.device == nil { - return "Closed", failure - } - return status, failure -} - -// Open implements accounts.Wallet, attempting to open a USB connection to the -// hardware wallet. -func (w *wallet) Open(passphrase string) error { - w.stateLock.Lock() // State lock is enough since there's no connection yet at this point - defer w.stateLock.Unlock() - - // If the device was already opened once, refuse to try again - if w.paths != nil { - return accounts.ErrWalletAlreadyOpen - } - // Make sure the actual device connection is done only once - if w.device == nil { - device, err := w.info.Open() - if err != nil { - return err - } - w.device = device - w.commsLock = make(chan struct{}, 1) - w.commsLock <- struct{}{} // Enable lock - } - // Delegate device initialization to the underlying driver - if err := w.driver.Open(w.device, passphrase); err != nil { - return err - } - // Connection successful, start life-cycle management - w.paths = make(map[common.Address]accounts.DerivationPath) - - w.deriveReq = make(chan chan struct{}) - w.deriveQuit = make(chan chan error) - w.healthQuit = make(chan chan error) - - go w.heartbeat() - go w.selfDerive() - - // Notify anyone listening for wallet events that a new device is accessible - go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened}) - - return nil -} - -// heartbeat is a health check loop for the USB wallets to periodically verify -// whether they are still present or if they malfunctioned. -func (w *wallet) heartbeat() { - w.log.Debug("USB wallet health-check started") - defer w.log.Debug("USB wallet health-check stopped") - - // Execute heartbeat checks until termination or error - var ( - errc chan error - err error - ) - for errc == nil && err == nil { - // Wait until termination is requested or the heartbeat cycle arrives - select { - case errc = <-w.healthQuit: - // Termination requested - continue - case <-time.After(heartbeatCycle): - // Heartbeat time - } - // Execute a tiny data exchange to see responsiveness - w.stateLock.RLock() - if w.device == nil { - // Terminated while waiting for the lock - w.stateLock.RUnlock() - continue - } - <-w.commsLock // Don't lock state while resolving version - err = w.driver.Heartbeat() - w.commsLock <- struct{}{} - w.stateLock.RUnlock() - - if err != nil { - w.stateLock.Lock() // Lock state to tear the wallet down - w.close() - w.stateLock.Unlock() - } - // Ignore non hardware related errors - err = nil - } - // In case of error, wait for termination - if err != nil { - w.log.Debug("USB wallet health-check failed", "err", err) - errc = <-w.healthQuit - } - errc <- err -} - -// Close implements accounts.Wallet, closing the USB connection to the device. -func (w *wallet) Close() error { - // Ensure the wallet was opened - w.stateLock.RLock() - hQuit, dQuit := w.healthQuit, w.deriveQuit - w.stateLock.RUnlock() - - // Terminate the health checks - var herr error - if hQuit != nil { - errc := make(chan error) - hQuit <- errc - herr = <-errc // Save for later, we *must* close the USB - } - // Terminate the self-derivations - var derr error - if dQuit != nil { - errc := make(chan error) - dQuit <- errc - derr = <-errc // Save for later, we *must* close the USB - } - // Terminate the device connection - w.stateLock.Lock() - defer w.stateLock.Unlock() - - w.healthQuit = nil - w.deriveQuit = nil - w.deriveReq = nil - - if err := w.close(); err != nil { - return err - } - if herr != nil { - return herr - } - return derr -} - -// close is the internal wallet closer that terminates the USB connection and -// resets all the fields to their defaults. -// -// Note, close assumes the state lock is held! -func (w *wallet) close() error { - // Allow duplicate closes, especially for health-check failures - if w.device == nil { - return nil - } - // Close the device, clear everything, then return - w.device.Close() - w.device = nil - - w.accounts, w.paths = nil, nil - return w.driver.Close() -} - -// Accounts implements accounts.Wallet, returning the list of accounts pinned to -// the USB hardware wallet. If self-derivation was enabled, the account list is -// periodically expanded based on current chain state. -func (w *wallet) Accounts() []accounts.Account { - // Attempt self-derivation if it's running - reqc := make(chan struct{}, 1) - select { - case w.deriveReq <- reqc: - // Self-derivation request accepted, wait for it - <-reqc - default: - // Self-derivation offline, throttled or busy, skip - } - // Return whatever account list we ended up with - w.stateLock.RLock() - defer w.stateLock.RUnlock() - - cpy := make([]accounts.Account, len(w.accounts)) - copy(cpy, w.accounts) - return cpy -} - -// selfDerive is an account derivation loop that upon request attempts to find -// new non-zero accounts. -func (w *wallet) selfDerive() { - w.log.Debug("USB wallet self-derivation started") - defer w.log.Debug("USB wallet self-derivation stopped") - - // Execute self-derivations until termination or error - var ( - reqc chan struct{} - errc chan error - err error - ) - for errc == nil && err == nil { - // Wait until either derivation or termination is requested - select { - case errc = <-w.deriveQuit: - // Termination requested - continue - case reqc = <-w.deriveReq: - // Account discovery requested - } - // Derivation needs a chain and device access, skip if either unavailable - w.stateLock.RLock() - if w.device == nil || w.deriveChain == nil { - w.stateLock.RUnlock() - reqc <- struct{}{} - continue - } - select { - case <-w.commsLock: - default: - w.stateLock.RUnlock() - reqc <- struct{}{} - continue - } - // Device lock obtained, derive the next batch of accounts - var ( - accs []accounts.Account - paths []accounts.DerivationPath - - nextPaths = append([]accounts.DerivationPath{}, w.deriveNextPaths...) - nextAddrs = append([]common.Address{}, w.deriveNextAddrs...) - - context = context.Background() - ) - for i := 0; i < len(nextAddrs); i++ { - for empty := false; !empty; { - // Retrieve the next derived Ethereum account - if nextAddrs[i] == (common.Address{}) { - if nextAddrs[i], err = w.driver.Derive(nextPaths[i]); err != nil { - w.log.Warn("USB wallet account derivation failed", "err", err) - break - } - } - // Check the account's status against the current chain state - var ( - balance *big.Int - nonce uint64 - ) - balance, err = w.deriveChain.BalanceAt(context, nextAddrs[i], nil) - if err != nil { - w.log.Warn("USB wallet balance retrieval failed", "err", err) - break - } - nonce, err = w.deriveChain.NonceAt(context, nextAddrs[i], nil) - if err != nil { - w.log.Warn("USB wallet nonce retrieval failed", "err", err) - break - } - // We've just self-derived a new account, start tracking it locally - // unless the account was empty. - path := make(accounts.DerivationPath, len(nextPaths[i])) - copy(path[:], nextPaths[i][:]) - if balance.Sign() == 0 && nonce == 0 { - empty = true - // If it indeed was empty, make a log output for it anyway. In the case - // of legacy-ledger, the first account on the legacy-path will - // be shown to the user, even if we don't actively track it - if i < len(nextAddrs)-1 { - w.log.Info("Skipping tracking first account on legacy path, use personal.deriveAccount(,, false) to track", - "path", path, "address", nextAddrs[i]) - break - } - } - paths = append(paths, path) - account := accounts.Account{ - Address: nextAddrs[i], - URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, - } - accs = append(accs, account) - - // Display a log message to the user for new (or previously empty accounts) - if _, known := w.paths[nextAddrs[i]]; !known || (!empty && nextAddrs[i] == w.deriveNextAddrs[i]) { - w.log.Info("USB wallet discovered new account", "address", nextAddrs[i], "path", path, "balance", balance, "nonce", nonce) - } - // Fetch the next potential account - if !empty { - nextAddrs[i] = common.Address{} - nextPaths[i][len(nextPaths[i])-1]++ - } - } - } - // Self derivation complete, release device lock - w.commsLock <- struct{}{} - w.stateLock.RUnlock() - - // Insert any accounts successfully derived - w.stateLock.Lock() - for i := 0; i < len(accs); i++ { - if _, ok := w.paths[accs[i].Address]; !ok { - w.accounts = append(w.accounts, accs[i]) - w.paths[accs[i].Address] = paths[i] - } - } - // Shift the self-derivation forward - // TODO(karalabe): don't overwrite changes from wallet.SelfDerive - w.deriveNextAddrs = nextAddrs - w.deriveNextPaths = nextPaths - w.stateLock.Unlock() - - // Notify the user of termination and loop after a bit of time (to avoid trashing) - reqc <- struct{}{} - if err == nil { - select { - case errc = <-w.deriveQuit: - // Termination requested, abort - case <-time.After(selfDeriveThrottling): - // Waited enough, willing to self-derive again - } - } - } - // In case of error, wait for termination - if err != nil { - w.log.Debug("USB wallet self-derivation failed", "err", err) - errc = <-w.deriveQuit - } - errc <- err -} - -// Contains implements accounts.Wallet, returning whether a particular account is -// or is not pinned into this wallet instance. Although we could attempt to resolve -// unpinned accounts, that would be an non-negligible hardware operation. -func (w *wallet) Contains(account accounts.Account) bool { - w.stateLock.RLock() - defer w.stateLock.RUnlock() - - _, exists := w.paths[account.Address] - return exists -} - -// Derive implements accounts.Wallet, deriving a new account at the specific -// derivation path. If pin is set to true, the account will be added to the list -// of tracked accounts. -func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { - // Try to derive the actual account and update its URL if successful - w.stateLock.RLock() // Avoid device disappearing during derivation - - if w.device == nil { - w.stateLock.RUnlock() - return accounts.Account{}, accounts.ErrWalletClosed - } - <-w.commsLock // Avoid concurrent hardware access - address, err := w.driver.Derive(path) - w.commsLock <- struct{}{} - - w.stateLock.RUnlock() - - // If an error occurred or no pinning was requested, return - if err != nil { - return accounts.Account{}, err - } - account := accounts.Account{ - Address: address, - URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, - } - if !pin { - return account, nil - } - // Pinning needs to modify the state - w.stateLock.Lock() - defer w.stateLock.Unlock() - - if w.device == nil { - return accounts.Account{}, accounts.ErrWalletClosed - } - - if _, ok := w.paths[address]; !ok { - w.accounts = append(w.accounts, account) - w.paths[address] = make(accounts.DerivationPath, len(path)) - copy(w.paths[address], path) - } - return account, nil -} - -// SelfDerive sets a base account derivation path from which the wallet attempts -// to discover non zero accounts and automatically add them to list of tracked -// accounts. -// -// Note, self derivation will increment the last component of the specified path -// opposed to descending into a child path to allow discovering accounts starting -// from non zero components. -// -// Some hardware wallets switched derivation paths through their evolution, so -// this method supports providing multiple bases to discover old user accounts -// too. Only the last base will be used to derive the next empty account. -// -// You can disable automatic account discovery by calling SelfDerive with a nil -// chain state reader. -func (w *wallet) SelfDerive(bases []accounts.DerivationPath, chain ethereum.ChainStateReader) { - w.stateLock.Lock() - defer w.stateLock.Unlock() - - w.deriveNextPaths = make([]accounts.DerivationPath, len(bases)) - for i, base := range bases { - w.deriveNextPaths[i] = make(accounts.DerivationPath, len(base)) - copy(w.deriveNextPaths[i][:], base[:]) - } - w.deriveNextAddrs = make([]common.Address, len(bases)) - w.deriveChain = chain -} - -// signHash implements accounts.Wallet, however signing arbitrary data is not -// supported for hardware wallets, so this method will always return an error. -func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error) { - return nil, accounts.ErrNotSupported -} - -// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed -func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - // Unless we are doing 712 signing, simply dispatch to signHash - if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) { - return w.signHash(account, crypto.Keccak256(data)) - } - - // dispatch to 712 signing if the mimetype is TypedData and the format matches - w.stateLock.RLock() // Comms have own mutex, this is for the state fields - defer w.stateLock.RUnlock() - - // If the wallet is closed, abort - if w.device == nil { - return nil, accounts.ErrWalletClosed - } - // Make sure the requested account is contained within - path, ok := w.paths[account.Address] - if !ok { - return nil, accounts.ErrUnknownAccount - } - // All infos gathered and metadata checks out, request signing - <-w.commsLock - defer func() { w.commsLock <- struct{}{} }() - - // Ensure the device isn't screwed with while user confirmation is pending - // TODO(karalabe): remove if hotplug lands on Windows - w.hub.commsLock.Lock() - w.hub.commsPend++ - w.hub.commsLock.Unlock() - - defer func() { - w.hub.commsLock.Lock() - w.hub.commsPend-- - w.hub.commsLock.Unlock() - }() - // Sign the transaction - signature, err := w.driver.SignTypedMessage(path, data[2:34], data[34:66]) - if err != nil { - return nil, err - } - return signature, nil -} - -// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given -// data with the given account using passphrase as extra authentication. -// Since USB wallets don't rely on passphrases, these are silently ignored. -func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { - return w.SignData(account, mimeType, data) -} - -func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { - return w.signHash(account, accounts.TextHash(text)) -} - -// SignTx implements accounts.Wallet. It sends the transaction over to the Ledger -// wallet to request a confirmation from the user. It returns either the signed -// transaction or a failure if the user denied the transaction. -// -// Note, if the version of the Ethereum application running on the Ledger wallet is -// too old to sign EIP-155 transactions, but such is requested nonetheless, an error -// will be returned opposed to silently signing in Homestead mode. -func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - w.stateLock.RLock() // Comms have own mutex, this is for the state fields - defer w.stateLock.RUnlock() - - // If the wallet is closed, abort - if w.device == nil { - return nil, accounts.ErrWalletClosed - } - // Make sure the requested account is contained within - path, ok := w.paths[account.Address] - if !ok { - return nil, accounts.ErrUnknownAccount - } - // All infos gathered and metadata checks out, request signing - <-w.commsLock - defer func() { w.commsLock <- struct{}{} }() - - // Ensure the device isn't screwed with while user confirmation is pending - // TODO(karalabe): remove if hotplug lands on Windows - w.hub.commsLock.Lock() - w.hub.commsPend++ - w.hub.commsLock.Unlock() - - defer func() { - w.hub.commsLock.Lock() - w.hub.commsPend-- - w.hub.commsLock.Unlock() - }() - // Sign the transaction and verify the sender to avoid hardware fault surprises - sender, signed, err := w.driver.SignTx(path, tx, chainID) - if err != nil { - return nil, err - } - if sender != account.Address { - return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex()) - } - return signed, nil -} - -// SignTextWithPassphrase implements accounts.Wallet, however signing arbitrary -// data is not supported for Ledger wallets, so this method will always return -// an error. -func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { - return w.SignText(account, accounts.TextHash(text)) -} - -// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given -// transaction with the given account using passphrase as extra authentication. -// Since USB wallets don't rely on passphrases, these are silently ignored. -func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { - return w.SignTx(account, tx, chainID) -} diff --git a/builder/appveyor.yml b/builder/appveyor.yml deleted file mode 100644 index 4a8c4b737..000000000 --- a/builder/appveyor.yml +++ /dev/null @@ -1,57 +0,0 @@ -clone_depth: 5 -version: "{branch}.{build}" - -image: - - Ubuntu - - Visual Studio 2019 - -environment: - matrix: - - GETH_ARCH: amd64 - GETH_MINGW: 'C:\msys64\mingw64' - - GETH_ARCH: 386 - GETH_MINGW: 'C:\msys64\mingw32' - -install: - - git submodule update --init --depth 1 --recursive - - go version - -for: - # Linux has its own script without -arch and -cc. - # The linux builder also runs lint. - - matrix: - only: - - image: Ubuntu - build_script: - - go run build/ci.go lint - - go run build/ci.go install -dlgo - test_script: - - go run build/ci.go test -dlgo - - # linux/386 is disabled. - - matrix: - exclude: - - image: Ubuntu - GETH_ARCH: 386 - - # Windows builds for amd64 + 386. - - matrix: - only: - - image: Visual Studio 2019 - environment: - # We use gcc from MSYS2 because it is the most recent compiler version available on - # AppVeyor. Note: gcc.exe only works properly if the corresponding bin/ directory is - # contained in PATH. - GETH_CC: '%GETH_MINGW%\bin\gcc.exe' - PATH: '%GETH_MINGW%\bin;C:\Program Files (x86)\NSIS\;%PATH%' - build_script: - - 'echo %GETH_ARCH%' - - 'echo %GETH_CC%' - - '%GETH_CC% --version' - - go run build/ci.go install -dlgo -arch %GETH_ARCH% -cc %GETH_CC% - after_build: - # Upload builds. Note that ci.go makes this a no-op PR builds. - - go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - - go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - test_script: - - go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short diff --git a/builder/beacon/engine/errors.go b/builder/beacon/engine/errors.go deleted file mode 100644 index 62773a0ea..000000000 --- a/builder/beacon/engine/errors.go +++ /dev/null @@ -1,88 +0,0 @@ -// 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 engine - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rpc" -) - -// EngineAPIError is a standardized error message between consensus and execution -// clients, also containing any custom error message Geth might include. -type EngineAPIError struct { - code int - msg string - err error -} - -func (e *EngineAPIError) ErrorCode() int { return e.code } -func (e *EngineAPIError) Error() string { return e.msg } -func (e *EngineAPIError) ErrorData() interface{} { - if e.err == nil { - return nil - } - return struct { - Error string `json:"err"` - }{e.err.Error()} -} - -// With returns a copy of the error with a new embedded custom data field. -func (e *EngineAPIError) With(err error) *EngineAPIError { - return &EngineAPIError{ - code: e.code, - msg: e.msg, - err: err, - } -} - -var ( - _ rpc.Error = new(EngineAPIError) - _ rpc.DataError = new(EngineAPIError) -) - -var ( - // VALID is returned by the engine API in the following calls: - // - newPayloadV1: if the payload was already known or was just validated and executed - // - forkchoiceUpdateV1: if the chain accepted the reorg (might ignore if it's stale) - VALID = "VALID" - - // INVALID is returned by the engine API in the following calls: - // - newPayloadV1: if the payload failed to execute on top of the local chain - // - forkchoiceUpdateV1: if the new head is unknown, pre-merge, or reorg to it fails - INVALID = "INVALID" - - // SYNCING is returned by the engine API in the following calls: - // - newPayloadV1: if the payload was accepted on top of an active sync - // - forkchoiceUpdateV1: if the new head was seen before, but not part of the chain - SYNCING = "SYNCING" - - // ACCEPTED is returned by the engine API in the following calls: - // - newPayloadV1: if the payload was accepted, but not processed (side chain) - ACCEPTED = "ACCEPTED" - - GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"} - UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"} - InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"} - InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"} - TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"} - InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"} - UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"} - - STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil} - STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil} - INVALID_TERMINAL_BLOCK = PayloadStatusV1{Status: INVALID, LatestValidHash: &common.Hash{}} -) diff --git a/builder/beacon/engine/gen_blockparams.go b/builder/beacon/engine/gen_blockparams.go deleted file mode 100644 index b1f01b50f..000000000 --- a/builder/beacon/engine/gen_blockparams.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package engine - -import ( - "encoding/json" - "errors" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" -) - -var _ = (*payloadAttributesMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (p PayloadAttributes) MarshalJSON() ([]byte, error) { - type PayloadAttributes struct { - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` - } - var enc PayloadAttributes - enc.Timestamp = hexutil.Uint64(p.Timestamp) - enc.Random = p.Random - enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient - enc.Withdrawals = p.Withdrawals - enc.BeaconRoot = p.BeaconRoot - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (p *PayloadAttributes) UnmarshalJSON(input []byte) error { - type PayloadAttributes struct { - Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Random *common.Hash `json:"prevRandao" gencodec:"required"` - SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` - } - var dec PayloadAttributes - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Timestamp == nil { - return errors.New("missing required field 'timestamp' for PayloadAttributes") - } - p.Timestamp = uint64(*dec.Timestamp) - if dec.Random == nil { - return errors.New("missing required field 'prevRandao' for PayloadAttributes") - } - p.Random = *dec.Random - if dec.SuggestedFeeRecipient == nil { - return errors.New("missing required field 'suggestedFeeRecipient' for PayloadAttributes") - } - p.SuggestedFeeRecipient = *dec.SuggestedFeeRecipient - if dec.Withdrawals != nil { - p.Withdrawals = dec.Withdrawals - } - if dec.BeaconRoot != nil { - p.BeaconRoot = dec.BeaconRoot - } - return nil -} diff --git a/builder/beacon/engine/gen_ed.go b/builder/beacon/engine/gen_ed.go deleted file mode 100644 index 6893d64a1..000000000 --- a/builder/beacon/engine/gen_ed.go +++ /dev/null @@ -1,158 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package engine - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" -) - -var _ = (*executableDataMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (e ExecutableData) MarshalJSON() ([]byte, error) { - type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` - } - var enc ExecutableData - enc.ParentHash = e.ParentHash - enc.FeeRecipient = e.FeeRecipient - enc.StateRoot = e.StateRoot - enc.ReceiptsRoot = e.ReceiptsRoot - enc.LogsBloom = e.LogsBloom - enc.Random = e.Random - enc.Number = hexutil.Uint64(e.Number) - enc.GasLimit = hexutil.Uint64(e.GasLimit) - enc.GasUsed = hexutil.Uint64(e.GasUsed) - enc.Timestamp = hexutil.Uint64(e.Timestamp) - enc.ExtraData = e.ExtraData - enc.BaseFeePerGas = (*hexutil.Big)(e.BaseFeePerGas) - enc.BlockHash = e.BlockHash - if e.Transactions != nil { - enc.Transactions = make([]hexutil.Bytes, len(e.Transactions)) - for k, v := range e.Transactions { - enc.Transactions[k] = v - } - } - enc.Withdrawals = e.Withdrawals - enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) - enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (e *ExecutableData) UnmarshalJSON(input []byte) error { - type ExecutableData struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot *common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"` - Random *common.Hash `json:"prevRandao" gencodec:"required"` - Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"` - BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"` - BlockHash *common.Hash `json:"blockHash" gencodec:"required"` - Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` - } - var dec ExecutableData - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.ParentHash == nil { - return errors.New("missing required field 'parentHash' for ExecutableData") - } - e.ParentHash = *dec.ParentHash - if dec.FeeRecipient == nil { - return errors.New("missing required field 'feeRecipient' for ExecutableData") - } - e.FeeRecipient = *dec.FeeRecipient - if dec.StateRoot == nil { - return errors.New("missing required field 'stateRoot' for ExecutableData") - } - e.StateRoot = *dec.StateRoot - if dec.ReceiptsRoot == nil { - return errors.New("missing required field 'receiptsRoot' for ExecutableData") - } - e.ReceiptsRoot = *dec.ReceiptsRoot - if dec.LogsBloom == nil { - return errors.New("missing required field 'logsBloom' for ExecutableData") - } - e.LogsBloom = *dec.LogsBloom - if dec.Random == nil { - return errors.New("missing required field 'prevRandao' for ExecutableData") - } - e.Random = *dec.Random - if dec.Number == nil { - return errors.New("missing required field 'blockNumber' for ExecutableData") - } - e.Number = uint64(*dec.Number) - if dec.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for ExecutableData") - } - e.GasLimit = uint64(*dec.GasLimit) - if dec.GasUsed == nil { - return errors.New("missing required field 'gasUsed' for ExecutableData") - } - e.GasUsed = uint64(*dec.GasUsed) - if dec.Timestamp == nil { - return errors.New("missing required field 'timestamp' for ExecutableData") - } - e.Timestamp = uint64(*dec.Timestamp) - if dec.ExtraData == nil { - return errors.New("missing required field 'extraData' for ExecutableData") - } - e.ExtraData = *dec.ExtraData - if dec.BaseFeePerGas == nil { - return errors.New("missing required field 'baseFeePerGas' for ExecutableData") - } - e.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas) - if dec.BlockHash == nil { - return errors.New("missing required field 'blockHash' for ExecutableData") - } - e.BlockHash = *dec.BlockHash - if dec.Transactions == nil { - return errors.New("missing required field 'transactions' for ExecutableData") - } - e.Transactions = make([][]byte, len(dec.Transactions)) - for k, v := range dec.Transactions { - e.Transactions[k] = v - } - if dec.Withdrawals != nil { - e.Withdrawals = dec.Withdrawals - } - if dec.BlobGasUsed != nil { - e.BlobGasUsed = (*uint64)(dec.BlobGasUsed) - } - if dec.ExcessBlobGas != nil { - e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - return nil -} diff --git a/builder/beacon/engine/gen_epe.go b/builder/beacon/engine/gen_epe.go deleted file mode 100644 index e69f9a595..000000000 --- a/builder/beacon/engine/gen_epe.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package engine - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*executionPayloadEnvelopeMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) { - type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` - BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` - Override bool `json:"shouldOverrideBuilder"` - } - var enc ExecutionPayloadEnvelope - enc.ExecutionPayload = e.ExecutionPayload - enc.BlockValue = (*hexutil.Big)(e.BlockValue) - enc.BlobsBundle = e.BlobsBundle - enc.Override = e.Override - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { - type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` - BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` - Override *bool `json:"shouldOverrideBuilder"` - } - var dec ExecutionPayloadEnvelope - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.ExecutionPayload == nil { - return errors.New("missing required field 'executionPayload' for ExecutionPayloadEnvelope") - } - e.ExecutionPayload = dec.ExecutionPayload - if dec.BlockValue == nil { - return errors.New("missing required field 'blockValue' for ExecutionPayloadEnvelope") - } - e.BlockValue = (*big.Int)(dec.BlockValue) - if dec.BlobsBundle != nil { - e.BlobsBundle = dec.BlobsBundle - } - if dec.Override != nil { - e.Override = *dec.Override - } - return nil -} diff --git a/builder/beacon/engine/types.go b/builder/beacon/engine/types.go deleted file mode 100644 index 97dbaba31..000000000 --- a/builder/beacon/engine/types.go +++ /dev/null @@ -1,452 +0,0 @@ -// 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 engine - -import ( - "crypto/sha256" - "fmt" - "math/big" - - denebapi "github.com/attestantio/go-builder-client/api/deneb" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/trie" -) - -// PayloadVersion denotes the version of PayloadAttributes used to request the -// building of the payload to commence. -type PayloadVersion byte - -var ( - PayloadV1 PayloadVersion = 0x1 - PayloadV2 PayloadVersion = 0x2 - PayloadV3 PayloadVersion = 0x3 -) - -//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go - -// PayloadAttributes describes the environment context in which a block should -// be built. -type PayloadAttributes struct { - Timestamp uint64 `json:"timestamp" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` - GasLimit uint64 - Slot uint64 -} - -// JSON type overrides for PayloadAttributes. -type payloadAttributesMarshaling struct { - Timestamp hexutil.Uint64 -} - -//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go - -// ExecutableData is the data necessary to execute an EL payload. -type ExecutableData struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` - StateRoot common.Hash `json:"stateRoot" gencodec:"required"` - ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"` - LogsBloom []byte `json:"logsBloom" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - Number uint64 `json:"blockNumber" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Timestamp uint64 `json:"timestamp" gencodec:"required"` - ExtraData []byte `json:"extraData" gencodec:"required"` - BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"` - BlockHash common.Hash `json:"blockHash" gencodec:"required"` - Transactions [][]byte `json:"transactions" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - BlobGasUsed *uint64 `json:"blobGasUsed"` - ExcessBlobGas *uint64 `json:"excessBlobGas"` -} - -// JSON type overrides for executableData. -type executableDataMarshaling struct { - Number hexutil.Uint64 - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Timestamp hexutil.Uint64 - BaseFeePerGas *hexutil.Big - ExtraData hexutil.Bytes - LogsBloom hexutil.Bytes - Transactions []hexutil.Bytes - BlobGasUsed *hexutil.Uint64 - ExcessBlobGas *hexutil.Uint64 -} - -//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go - -type ExecutionPayloadEnvelope struct { - ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` - BlockValue *big.Int `json:"blockValue" gencodec:"required"` - BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` - Override bool `json:"shouldOverrideBuilder"` -} - -type BlobsBundleV1 struct { - Commitments []hexutil.Bytes `json:"commitments"` - Proofs []hexutil.Bytes `json:"proofs"` - Blobs []hexutil.Bytes `json:"blobs"` -} - -// JSON type overrides for ExecutionPayloadEnvelope. -type executionPayloadEnvelopeMarshaling struct { - BlockValue *hexutil.Big -} - -type PayloadStatusV1 struct { - Status string `json:"status"` - LatestValidHash *common.Hash `json:"latestValidHash"` - ValidationError *string `json:"validationError"` -} - -type TransitionConfigurationV1 struct { - TerminalTotalDifficulty *hexutil.Big `json:"terminalTotalDifficulty"` - TerminalBlockHash common.Hash `json:"terminalBlockHash"` - TerminalBlockNumber hexutil.Uint64 `json:"terminalBlockNumber"` -} - -// PayloadID is an identifier of the payload build process -type PayloadID [8]byte - -// Version returns the payload version associated with the identifier. -func (b PayloadID) Version() PayloadVersion { - return PayloadVersion(b[0]) -} - -// Is returns whether the identifier matches any of provided payload versions. -func (b PayloadID) Is(versions ...PayloadVersion) bool { - for _, v := range versions { - if v == b.Version() { - return true - } - } - return false -} - -func (b PayloadID) String() string { - return hexutil.Encode(b[:]) -} - -func (b PayloadID) MarshalText() ([]byte, error) { - return hexutil.Bytes(b[:]).MarshalText() -} - -func (b *PayloadID) UnmarshalText(input []byte) error { - err := hexutil.UnmarshalFixedText("PayloadID", input, b[:]) - if err != nil { - return fmt.Errorf("invalid payload id %q: %w", input, err) - } - return nil -} - -type ForkChoiceResponse struct { - PayloadStatus PayloadStatusV1 `json:"payloadStatus"` - PayloadID *PayloadID `json:"payloadId"` -} - -type ForkchoiceStateV1 struct { - HeadBlockHash common.Hash `json:"headBlockHash"` - SafeBlockHash common.Hash `json:"safeBlockHash"` - FinalizedBlockHash common.Hash `json:"finalizedBlockHash"` -} - -func encodeTransactions(txs []*types.Transaction) [][]byte { - var enc = make([][]byte, len(txs)) - for i, tx := range txs { - enc[i], _ = tx.MarshalBinary() - } - return enc -} - -func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { - var txs = make([]*types.Transaction, len(enc)) - for i, encTx := range enc { - var tx types.Transaction - if err := tx.UnmarshalBinary(encTx); err != nil { - return nil, fmt.Errorf("invalid transaction %d: %v", i, err) - } - txs[i] = &tx - } - return txs, nil -} - -// ExecutableDataToBlock constructs a block from executable data. -// It verifies that the following fields: -// -// len(extraData) <= 32 -// uncleHash = emptyUncleHash -// difficulty = 0 -// if versionedHashes != nil, versionedHashes match to blob transactions -// -// and that the blockhash of the constructed block matches the parameters. Nil -// Withdrawals value will propagate through the returned block. Empty -// Withdrawals value must be passed via non-nil, length 0 value in params. -func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) { - txs, err := decodeTransactions(params.Transactions) - if err != nil { - return nil, err - } - if len(params.ExtraData) > 32 { - return nil, fmt.Errorf("invalid extradata length: %v", len(params.ExtraData)) - } - if len(params.LogsBloom) != 256 { - return nil, fmt.Errorf("invalid logsBloom length: %v", len(params.LogsBloom)) - } - // Check that baseFeePerGas is not negative or too big - if params.BaseFeePerGas != nil && (params.BaseFeePerGas.Sign() == -1 || params.BaseFeePerGas.BitLen() > 256) { - return nil, fmt.Errorf("invalid baseFeePerGas: %v", params.BaseFeePerGas) - } - var blobHashes []common.Hash - for _, tx := range txs { - blobHashes = append(blobHashes, tx.BlobHashes()...) - } - if len(blobHashes) != len(versionedHashes) { - return nil, fmt.Errorf("invalid number of versionedHashes: %v blobHashes: %v", versionedHashes, blobHashes) - } - for i := 0; i < len(blobHashes); i++ { - if blobHashes[i] != versionedHashes[i] { - return nil, fmt.Errorf("invalid versionedHash at %v: %v blobHashes: %v", i, versionedHashes, blobHashes) - } - } - // Only set withdrawalsRoot if it is non-nil. This allows CLs to use - // ExecutableData before withdrawals are enabled by marshaling - // Withdrawals as the json null value. - var withdrawalsRoot *common.Hash - if params.Withdrawals != nil { - h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil)) - withdrawalsRoot = &h - } - header := &types.Header{ - ParentHash: params.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: params.FeeRecipient, - Root: params.StateRoot, - TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: params.ReceiptsRoot, - Bloom: types.BytesToBloom(params.LogsBloom), - Difficulty: common.Big0, - Number: new(big.Int).SetUint64(params.Number), - GasLimit: params.GasLimit, - GasUsed: params.GasUsed, - Time: params.Timestamp, - BaseFee: params.BaseFeePerGas, - Extra: params.ExtraData, - MixDigest: params.Random, - WithdrawalsHash: withdrawalsRoot, - ExcessBlobGas: params.ExcessBlobGas, - BlobGasUsed: params.BlobGasUsed, - ParentBeaconRoot: beaconRoot, - } - block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals) - if block.Hash() != params.BlockHash { - return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash()) - } - return block, nil -} - -// BlockToExecutableData constructs the ExecutableData structure by filling the -// fields from the given block. It assumes the given block is post-merge block. -func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope { - data := &ExecutableData{ - BlockHash: block.Hash(), - ParentHash: block.ParentHash(), - FeeRecipient: block.Coinbase(), - StateRoot: block.Root(), - Number: block.NumberU64(), - GasLimit: block.GasLimit(), - GasUsed: block.GasUsed(), - BaseFeePerGas: block.BaseFee(), - Timestamp: block.Time(), - ReceiptsRoot: block.ReceiptHash(), - LogsBloom: block.Bloom().Bytes(), - Transactions: encodeTransactions(block.Transactions()), - Random: block.MixDigest(), - ExtraData: block.Extra(), - Withdrawals: block.Withdrawals(), - BlobGasUsed: block.BlobGasUsed(), - ExcessBlobGas: block.ExcessBlobGas(), - } - bundle := BlobsBundleV1{ - Commitments: make([]hexutil.Bytes, 0), - Blobs: make([]hexutil.Bytes, 0), - Proofs: make([]hexutil.Bytes, 0), - } - for _, sidecar := range sidecars { - for j := range sidecar.Blobs { - bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:])) - bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:])) - bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:])) - } - } - return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false} -} - -// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1 -type ExecutionPayloadBodyV1 struct { - TransactionData []hexutil.Bytes `json:"transactions"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` -} - -func ExecutionPayloadV1ToBlock(payload *bellatrix.ExecutionPayload) (*types.Block, error) { - // base fee per gas is stored little-endian but we need it - // big-endian for big.Int. - var baseFeePerGasBytes [32]byte - for i := 0; i < 32; i++ { - baseFeePerGasBytes[i] = payload.BaseFeePerGas[32-1-i] - } - baseFeePerGas := new(big.Int).SetBytes(baseFeePerGasBytes[:]) - - txs := make([][]byte, len(payload.Transactions)) - for i, txHexBytes := range payload.Transactions { - txs[i] = txHexBytes - } - executableData := ExecutableData{ - ParentHash: common.Hash(payload.ParentHash), - FeeRecipient: common.Address(payload.FeeRecipient), - StateRoot: common.Hash(payload.StateRoot), - ReceiptsRoot: common.Hash(payload.ReceiptsRoot), - LogsBloom: payload.LogsBloom[:], - Random: common.Hash(payload.PrevRandao), - Number: payload.BlockNumber, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: baseFeePerGas, - BlockHash: common.Hash(payload.BlockHash), - Transactions: txs, - } - return ExecutableDataToBlock(executableData, nil, nil) -} - -func ExecutionPayloadV2ToBlock(payload *capella.ExecutionPayload) (*types.Block, error) { - // base fee per gas is stored little-endian but we need it - // big-endian for big.Int. - var baseFeePerGasBytes [32]byte - for i := 0; i < 32; i++ { - baseFeePerGasBytes[i] = payload.BaseFeePerGas[32-1-i] - } - baseFeePerGas := new(big.Int).SetBytes(baseFeePerGasBytes[:]) - - txs := make([][]byte, len(payload.Transactions)) - for i, txHexBytes := range payload.Transactions { - txs[i] = txHexBytes - } - - withdrawals := make([]*types.Withdrawal, len(payload.Withdrawals)) - for i, withdrawal := range payload.Withdrawals { - withdrawals[i] = &types.Withdrawal{ - Index: uint64(withdrawal.Index), - Validator: uint64(withdrawal.ValidatorIndex), - Address: common.Address(withdrawal.Address), - Amount: uint64(withdrawal.Amount), - } - } - executableData := ExecutableData{ - ParentHash: common.Hash(payload.ParentHash), - FeeRecipient: common.Address(payload.FeeRecipient), - StateRoot: common.Hash(payload.StateRoot), - ReceiptsRoot: common.Hash(payload.ReceiptsRoot), - LogsBloom: payload.LogsBloom[:], - Random: common.Hash(payload.PrevRandao), - Number: payload.BlockNumber, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: baseFeePerGas, - BlockHash: common.Hash(payload.BlockHash), - Transactions: txs, - Withdrawals: withdrawals, - } - return ExecutableDataToBlock(executableData, nil, nil) -} - -func ExecutionPayloadV3ToBlock(payload *deneb.ExecutionPayload, blobsBundle *denebapi.BlobsBundle, parentBeaconBlockRoot common.Hash) (*types.Block, error) { - txs := make([][]byte, len(payload.Transactions)) - for i, txHexBytes := range payload.Transactions { - txs[i] = txHexBytes - } - - withdrawals := make([]*types.Withdrawal, len(payload.Withdrawals)) - for i, withdrawal := range payload.Withdrawals { - withdrawals[i] = &types.Withdrawal{ - Index: uint64(withdrawal.Index), - Validator: uint64(withdrawal.ValidatorIndex), - Address: common.Address(withdrawal.Address), - Amount: uint64(withdrawal.Amount), - } - } - - hasher := sha256.New() - versionedHashes := make([]common.Hash, len(blobsBundle.Commitments)) - for i, commitment := range blobsBundle.Commitments { - c := kzg4844.Commitment(commitment) - computed := kzg4844.CalcBlobHashV1(hasher, &c) - versionedHashes[i] = common.Hash(computed) - } - - executableData := ExecutableData{ - ParentHash: common.Hash(payload.ParentHash), - FeeRecipient: common.Address(payload.FeeRecipient), - StateRoot: common.Hash(payload.StateRoot), - ReceiptsRoot: common.Hash(payload.ReceiptsRoot), - LogsBloom: payload.LogsBloom[:], - Random: common.Hash(payload.PrevRandao), - Number: payload.BlockNumber, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: payload.BaseFeePerGas.ToBig(), - BlockHash: common.Hash(payload.BlockHash), - Transactions: txs, - Withdrawals: withdrawals, - BlobGasUsed: &payload.BlobGasUsed, - ExcessBlobGas: &payload.ExcessBlobGas, - } - return ExecutableDataToBlock(executableData, versionedHashes, &parentBeaconBlockRoot) -} - -// Client identifiers to support ClientVersionV1. -const ( - ClientCode = "GE" - ClientName = "go-ethereum" -) - -// ClientVersionV1 contains information which identifies a client implementation. -type ClientVersionV1 struct { - Code string `json:"code"` - Name string `json:"clientName"` - Version string `json:"version"` - Commit string `json:"commit"` -} - -func (v *ClientVersionV1) String() string { - return fmt.Sprintf("%s-%s-%s-%s", v.Code, v.Name, v.Version, v.Commit) -} diff --git a/builder/beacon/light/canonical.go b/builder/beacon/light/canonical.go deleted file mode 100644 index b5371493b..000000000 --- a/builder/beacon/light/canonical.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2023 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 light - -import ( - "encoding/binary" - "fmt" - - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// canonicalStore stores instances of the given type in a database and caches -// them in memory, associated with a continuous range of period numbers. -// Note: canonicalStore is not thread safe and it is the caller's responsibility -// to avoid concurrent access. -type canonicalStore[T any] struct { - keyPrefix []byte - periods periodRange - cache *lru.Cache[uint64, T] -} - -// newCanonicalStore creates a new canonicalStore and loads all keys associated -// with the keyPrefix in order to determine the ranges available in the database. -func newCanonicalStore[T any](db ethdb.Iteratee, keyPrefix []byte) (*canonicalStore[T], error) { - cs := &canonicalStore[T]{ - keyPrefix: keyPrefix, - cache: lru.NewCache[uint64, T](100), - } - var ( - iter = db.NewIterator(keyPrefix, nil) - kl = len(keyPrefix) - first = true - ) - defer iter.Release() - - for iter.Next() { - if len(iter.Key()) != kl+8 { - log.Warn("Invalid key length in the canonical chain database", "key", fmt.Sprintf("%#x", iter.Key())) - continue - } - period := binary.BigEndian.Uint64(iter.Key()[kl : kl+8]) - if first { - cs.periods.Start = period - } else if cs.periods.End != period { - return nil, fmt.Errorf("gap in the canonical chain database between periods %d and %d", cs.periods.End, period-1) - } - first = false - cs.periods.End = period + 1 - } - return cs, nil -} - -// databaseKey returns the database key belonging to the given period. -func (cs *canonicalStore[T]) databaseKey(period uint64) []byte { - return binary.BigEndian.AppendUint64(append([]byte{}, cs.keyPrefix...), period) -} - -// add adds the given item to the database. It also ensures that the range remains -// continuous. Can be used either with a batch or database backend. -func (cs *canonicalStore[T]) add(backend ethdb.KeyValueWriter, period uint64, value T) error { - if !cs.periods.canExpand(period) { - return fmt.Errorf("period expansion is not allowed, first: %d, next: %d, period: %d", cs.periods.Start, cs.periods.End, period) - } - enc, err := rlp.EncodeToBytes(value) - if err != nil { - return err - } - if err := backend.Put(cs.databaseKey(period), enc); err != nil { - return err - } - cs.cache.Add(period, value) - cs.periods.expand(period) - return nil -} - -// deleteFrom removes items starting from the given period. -func (cs *canonicalStore[T]) deleteFrom(db ethdb.KeyValueWriter, fromPeriod uint64) (deleted periodRange) { - keepRange, deleteRange := cs.periods.split(fromPeriod) - deleteRange.each(func(period uint64) { - db.Delete(cs.databaseKey(period)) - cs.cache.Remove(period) - }) - cs.periods = keepRange - return deleteRange -} - -// get returns the item at the given period or the null value of the given type -// if no item is present. -func (cs *canonicalStore[T]) get(backend ethdb.KeyValueReader, period uint64) (T, bool) { - var null, value T - if !cs.periods.contains(period) { - return null, false - } - if value, ok := cs.cache.Get(period); ok { - return value, true - } - enc, err := backend.Get(cs.databaseKey(period)) - if err != nil { - log.Error("Canonical store value not found", "period", period, "start", cs.periods.Start, "end", cs.periods.End) - return null, false - } - if err := rlp.DecodeBytes(enc, &value); err != nil { - log.Error("Error decoding canonical store value", "error", err) - return null, false - } - cs.cache.Add(period, value) - return value, true -} diff --git a/builder/beacon/light/committee_chain.go b/builder/beacon/light/committee_chain.go deleted file mode 100644 index d707f8cc3..000000000 --- a/builder/beacon/light/committee_chain.go +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright 2023 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 light - -import ( - "errors" - "fmt" - "math" - "sync" - "time" - - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -var ( - ErrNeedCommittee = errors.New("sync committee required") - ErrInvalidUpdate = errors.New("invalid committee update") - ErrInvalidPeriod = errors.New("invalid update period") - ErrWrongCommitteeRoot = errors.New("wrong committee root") - ErrCannotReorg = errors.New("can not reorg committee chain") -) - -// CommitteeChain is a passive data structure that can validate, hold and update -// a chain of beacon light sync committees and updates. It requires at least one -// externally set fixed committee root at the beginning of the chain which can -// be set either based on a BootstrapData or a trusted source (a local beacon -// full node). This makes the structure useful for both light client and light -// server setups. -// -// It always maintains the following consistency constraints: -// - a committee can only be present if its root hash matches an existing fixed -// root or if it is proven by an update at the previous period -// - an update can only be present if a committee is present at the same period -// and the update signature is valid and has enough participants. -// The committee at the next period (proven by the update) should also be -// present (note that this means they can only be added together if neither -// is present yet). If a fixed root is present at the next period then the -// update can only be present if it proves the same committee root. -// -// Once synced to the current sync period, CommitteeChain can also validate -// signed beacon headers. -type CommitteeChain struct { - // chainmu guards against concurrent access to the canonicalStore structures - // (updates, committees, fixedCommitteeRoots) and ensures that they stay consistent - // with each other and with committeeCache. - chainmu sync.RWMutex - db ethdb.KeyValueStore - updates *canonicalStore[*types.LightClientUpdate] - committees *canonicalStore[*types.SerializedSyncCommittee] - fixedCommitteeRoots *canonicalStore[common.Hash] - committeeCache *lru.Cache[uint64, syncCommittee] // cache deserialized committees - - clock mclock.Clock // monotonic clock (simulated clock in tests) - unixNano func() int64 // system clock (simulated clock in tests) - sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests) - - config *types.ChainConfig - signerThreshold int - minimumUpdateScore types.UpdateScore - enforceTime bool // enforceTime specifies whether the age of a signed header should be checked -} - -// NewCommitteeChain creates a new CommitteeChain. -func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain { - return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() }) -} - -// newCommitteeChain creates a new CommitteeChain with the option of replacing the -// clock source and signature verification for testing purposes. -func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain { - s := &CommitteeChain{ - committeeCache: lru.NewCache[uint64, syncCommittee](10), - db: db, - sigVerifier: sigVerifier, - clock: clock, - unixNano: unixNano, - config: config, - signerThreshold: signerThreshold, - enforceTime: enforceTime, - minimumUpdateScore: types.UpdateScore{ - SignerCount: uint32(signerThreshold), - SubPeriodIndex: params.SyncPeriodLength / 16, - }, - } - - var err1, err2, err3 error - if s.fixedCommitteeRoots, err1 = newCanonicalStore[common.Hash](db, rawdb.FixedCommitteeRootKey); err1 != nil { - log.Error("Error creating fixed committee root store", "error", err1) - } - if s.committees, err2 = newCanonicalStore[*types.SerializedSyncCommittee](db, rawdb.SyncCommitteeKey); err2 != nil { - log.Error("Error creating committee store", "error", err2) - } - if s.updates, err3 = newCanonicalStore[*types.LightClientUpdate](db, rawdb.BestUpdateKey); err3 != nil { - log.Error("Error creating update store", "error", err3) - } - if err1 != nil || err2 != nil || err3 != nil || !s.checkConstraints() { - log.Info("Resetting invalid committee chain") - s.Reset() - } - // roll back invalid updates (might be necessary if forks have been changed since last time) - for !s.updates.periods.isEmpty() { - update, ok := s.updates.get(s.db, s.updates.periods.End-1) - if !ok { - log.Error("Sync committee update missing", "period", s.updates.periods.End-1) - s.Reset() - break - } - if valid, err := s.verifyUpdate(update); err != nil { - log.Error("Error validating update", "period", s.updates.periods.End-1, "error", err) - } else if valid { - break - } - if err := s.rollback(s.updates.periods.End); err != nil { - log.Error("Error writing batch into chain database", "error", err) - } - } - if !s.committees.periods.isEmpty() { - log.Trace("Sync committee chain loaded", "first period", s.committees.periods.Start, "last period", s.committees.periods.End-1) - } - return s -} - -// checkConstraints checks committee chain validity constraints -func (s *CommitteeChain) checkConstraints() bool { - isNotInFixedCommitteeRootRange := func(r periodRange) bool { - return s.fixedCommitteeRoots.periods.isEmpty() || - r.Start < s.fixedCommitteeRoots.periods.Start || - r.Start >= s.fixedCommitteeRoots.periods.End - } - - valid := true - if !s.updates.periods.isEmpty() { - if isNotInFixedCommitteeRootRange(s.updates.periods) { - log.Error("Start update is not in the fixed roots range") - valid = false - } - if s.committees.periods.Start > s.updates.periods.Start || s.committees.periods.End <= s.updates.periods.End { - log.Error("Missing committees in update range") - valid = false - } - } - if !s.committees.periods.isEmpty() { - if isNotInFixedCommitteeRootRange(s.committees.periods) { - log.Error("Start committee is not in the fixed roots range") - valid = false - } - if s.committees.periods.End > s.fixedCommitteeRoots.periods.End && s.committees.periods.End > s.updates.periods.End+1 { - log.Error("Last committee is neither in the fixed roots range nor proven by updates") - valid = false - } - } - return valid -} - -// Reset resets the committee chain. -func (s *CommitteeChain) Reset() { - s.chainmu.Lock() - defer s.chainmu.Unlock() - - if err := s.rollback(0); err != nil { - log.Error("Error writing batch into chain database", "error", err) - } -} - -// CheckpointInit initializes a CommitteeChain based on the checkpoint. -// Note: if the chain is already initialized and the committees proven by the -// checkpoint do match the existing chain then the chain is retained and the -// new checkpoint becomes fixed. -func (s *CommitteeChain) CheckpointInit(bootstrap *types.BootstrapData) error { - s.chainmu.Lock() - defer s.chainmu.Unlock() - - if err := bootstrap.Validate(); err != nil { - return err - } - - period := bootstrap.Header.SyncPeriod() - if err := s.deleteFixedCommitteeRootsFrom(period + 2); err != nil { - s.Reset() - return err - } - if s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot) != nil { - s.Reset() - if err := s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot); err != nil { - s.Reset() - return err - } - } - if err := s.addFixedCommitteeRoot(period+1, common.Hash(bootstrap.CommitteeBranch[0])); err != nil { - s.Reset() - return err - } - if err := s.addCommittee(period, bootstrap.Committee); err != nil { - s.Reset() - return err - } - return nil -} - -// addFixedCommitteeRoot sets a fixed committee root at the given period. -// Note that the period where the first committee is added has to have a fixed -// root which can either come from a BootstrapData or a trusted source. -func (s *CommitteeChain) addFixedCommitteeRoot(period uint64, root common.Hash) error { - if root == (common.Hash{}) { - return ErrWrongCommitteeRoot - } - - batch := s.db.NewBatch() - oldRoot := s.getCommitteeRoot(period) - if !s.fixedCommitteeRoots.periods.canExpand(period) { - // Note: the fixed committee root range should always be continuous and - // therefore the expected syncing method is to forward sync and optionally - // backward sync periods one by one, starting from a checkpoint. The only - // case when a root that is not adjacent to the already fixed ones can be - // fixed is when the same root has already been proven by an update chain. - // In this case the all roots in between can and should be fixed. - // This scenario makes sense when a new trusted checkpoint is added to an - // existing chain, ensuring that it will not be rolled back (might be - // important in case of low signer participation rate). - if root != oldRoot { - return ErrInvalidPeriod - } - // if the old root exists and matches the new one then it is guaranteed - // that the given period is after the existing fixed range and the roots - // in between can also be fixed. - for p := s.fixedCommitteeRoots.periods.End; p < period; p++ { - if err := s.fixedCommitteeRoots.add(batch, p, s.getCommitteeRoot(p)); err != nil { - return err - } - } - } - if oldRoot != (common.Hash{}) && (oldRoot != root) { - // existing old root was different, we have to reorg the chain - if err := s.rollback(period); err != nil { - return err - } - } - if err := s.fixedCommitteeRoots.add(batch, period, root); err != nil { - return err - } - if err := batch.Write(); err != nil { - log.Error("Error writing batch into chain database", "error", err) - return err - } - return nil -} - -// deleteFixedCommitteeRootsFrom deletes fixed roots starting from the given period. -// It also maintains chain consistency, meaning that it also deletes updates and -// committees if they are no longer supported by a valid update chain. -func (s *CommitteeChain) deleteFixedCommitteeRootsFrom(period uint64) error { - if period >= s.fixedCommitteeRoots.periods.End { - return nil - } - batch := s.db.NewBatch() - s.fixedCommitteeRoots.deleteFrom(batch, period) - if s.updates.periods.isEmpty() || period <= s.updates.periods.Start { - // Note: the first period of the update chain should always be fixed so if - // the fixed root at the first update is removed then the entire update chain - // and the proven committees have to be removed. Earlier committees in the - // remaining fixed root range can stay. - s.updates.deleteFrom(batch, period) - s.deleteCommitteesFrom(batch, period) - } else { - // The update chain stays intact, some previously fixed committee roots might - // get unfixed but are still proven by the update chain. If there were - // committees present after the range proven by updates, those should be - // removed if the belonging fixed roots are also removed. - fromPeriod := s.updates.periods.End + 1 // not proven by updates - if period > fromPeriod { - fromPeriod = period // also not justified by fixed roots - } - s.deleteCommitteesFrom(batch, fromPeriod) - } - if err := batch.Write(); err != nil { - log.Error("Error writing batch into chain database", "error", err) - return err - } - return nil -} - -// deleteCommitteesFrom deletes committees starting from the given period. -func (s *CommitteeChain) deleteCommitteesFrom(batch ethdb.Batch, period uint64) { - deleted := s.committees.deleteFrom(batch, period) - for period := deleted.Start; period < deleted.End; period++ { - s.committeeCache.Remove(period) - } -} - -// addCommittee adds a committee at the given period if possible. -func (s *CommitteeChain) addCommittee(period uint64, committee *types.SerializedSyncCommittee) error { - if !s.committees.periods.canExpand(period) { - return ErrInvalidPeriod - } - root := s.getCommitteeRoot(period) - if root == (common.Hash{}) { - return ErrInvalidPeriod - } - if root != committee.Root() { - return ErrWrongCommitteeRoot - } - if !s.committees.periods.contains(period) { - if err := s.committees.add(s.db, period, committee); err != nil { - return err - } - s.committeeCache.Remove(period) - } - return nil -} - -// InsertUpdate adds a new update if possible. -func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error { - s.chainmu.Lock() - defer s.chainmu.Unlock() - - period := update.AttestedHeader.Header.SyncPeriod() - if !s.updates.periods.canExpand(period) || !s.committees.periods.contains(period) { - return ErrInvalidPeriod - } - if s.minimumUpdateScore.BetterThan(update.Score()) { - return ErrInvalidUpdate - } - oldRoot := s.getCommitteeRoot(period + 1) - reorg := oldRoot != (common.Hash{}) && oldRoot != update.NextSyncCommitteeRoot - if oldUpdate, ok := s.updates.get(s.db, period); ok && !update.Score().BetterThan(oldUpdate.Score()) { - // a better or equal update already exists; no changes, only fail if new one tried to reorg - if reorg { - return ErrCannotReorg - } - return nil - } - if s.fixedCommitteeRoots.periods.contains(period+1) && reorg { - return ErrCannotReorg - } - if ok, err := s.verifyUpdate(update); err != nil { - return err - } else if !ok { - return ErrInvalidUpdate - } - addCommittee := !s.committees.periods.contains(period+1) || reorg - if addCommittee { - if nextCommittee == nil { - return ErrNeedCommittee - } - if nextCommittee.Root() != update.NextSyncCommitteeRoot { - return ErrWrongCommitteeRoot - } - } - if reorg { - if err := s.rollback(period + 1); err != nil { - return err - } - } - batch := s.db.NewBatch() - if addCommittee { - if err := s.committees.add(batch, period+1, nextCommittee); err != nil { - return err - } - s.committeeCache.Remove(period + 1) - } - if err := s.updates.add(batch, period, update); err != nil { - return err - } - if err := batch.Write(); err != nil { - log.Error("Error writing batch into chain database", "error", err) - return err - } - log.Info("Inserted new committee update", "period", period, "next committee root", update.NextSyncCommitteeRoot) - return nil -} - -// NextSyncPeriod returns the next period where an update can be added and also -// whether the chain is initialized at all. -func (s *CommitteeChain) NextSyncPeriod() (uint64, bool) { - s.chainmu.RLock() - defer s.chainmu.RUnlock() - - if s.committees.periods.isEmpty() { - return 0, false - } - if !s.updates.periods.isEmpty() { - return s.updates.periods.End, true - } - return s.committees.periods.End - 1, true -} - -// rollback removes all committees and fixed roots from the given period and updates -// starting from the previous period. -func (s *CommitteeChain) rollback(period uint64) error { - max := s.updates.periods.End + 1 - if s.committees.periods.End > max { - max = s.committees.periods.End - } - if s.fixedCommitteeRoots.periods.End > max { - max = s.fixedCommitteeRoots.periods.End - } - for max > period { - max-- - batch := s.db.NewBatch() - s.deleteCommitteesFrom(batch, max) - s.fixedCommitteeRoots.deleteFrom(batch, max) - if max > 0 { - s.updates.deleteFrom(batch, max-1) - } - if err := batch.Write(); err != nil { - log.Error("Error writing batch into chain database", "error", err) - return err - } - } - return nil -} - -// getCommitteeRoot returns the committee root at the given period, either fixed, -// proven by a previous update or both. It returns an empty hash if the committee -// root is unknown. -func (s *CommitteeChain) getCommitteeRoot(period uint64) common.Hash { - if root, ok := s.fixedCommitteeRoots.get(s.db, period); ok || period == 0 { - return root - } - if update, ok := s.updates.get(s.db, period-1); ok { - return update.NextSyncCommitteeRoot - } - return common.Hash{} -} - -// getSyncCommittee returns the deserialized sync committee at the given period. -func (s *CommitteeChain) getSyncCommittee(period uint64) (syncCommittee, error) { - if c, ok := s.committeeCache.Get(period); ok { - return c, nil - } - if sc, ok := s.committees.get(s.db, period); ok { - c, err := s.sigVerifier.deserializeSyncCommittee(sc) - if err != nil { - return nil, fmt.Errorf("Sync committee #%d deserialization error: %v", period, err) - } - s.committeeCache.Add(period, c) - return c, nil - } - return nil, fmt.Errorf("Missing serialized sync committee #%d", period) -} - -// VerifySignedHeader returns true if the given signed header has a valid signature -// according to the local committee chain. The caller should ensure that the -// committees advertised by the same source where the signed header came from are -// synced before verifying the signature. -// The age of the header is also returned (the time elapsed since the beginning -// of the given slot, according to the local system clock). If enforceTime is -// true then negative age (future) headers are rejected. -func (s *CommitteeChain) VerifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) { - s.chainmu.RLock() - defer s.chainmu.RUnlock() - - return s.verifySignedHeader(head) -} - -func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) { - var age time.Duration - now := s.unixNano() - if head.Header.Slot < (uint64(now-math.MinInt64)/uint64(time.Second)-s.config.GenesisTime)/12 { - age = time.Duration(now - int64(time.Second)*int64(s.config.GenesisTime+head.Header.Slot*12)) - } else { - age = time.Duration(math.MinInt64) - } - if s.enforceTime && age < 0 { - return false, age, nil - } - committee, err := s.getSyncCommittee(types.SyncPeriod(head.SignatureSlot)) - if err != nil { - return false, 0, err - } - if committee == nil { - return false, age, nil - } - if signingRoot, err := s.config.Forks.SigningRoot(head.Header); err == nil { - return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil - } - return false, age, nil -} - -// verifyUpdate checks whether the header signature is correct and the update -// fits into the specified constraints (assumes that the update has been -// successfully validated previously) -func (s *CommitteeChain) verifyUpdate(update *types.LightClientUpdate) (bool, error) { - // Note: SignatureSlot determines the sync period of the committee used for signature - // verification. Though in reality SignatureSlot is always bigger than update.Header.Slot, - // setting them as equal here enforces the rule that they have to be in the same sync - // period in order for the light client update proof to be meaningful. - ok, age, err := s.verifySignedHeader(update.AttestedHeader) - if age < 0 { - log.Warn("Future committee update received", "age", age) - } - return ok, err -} diff --git a/builder/beacon/light/committee_chain_test.go b/builder/beacon/light/committee_chain_test.go deleted file mode 100644 index 60ea2a0ef..000000000 --- a/builder/beacon/light/committee_chain_test.go +++ /dev/null @@ -1,356 +0,0 @@ -// 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 light - -import ( - "crypto/rand" - "testing" - "time" - - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/ethdb/memorydb" -) - -var ( - testGenesis = newTestGenesis() - testGenesis2 = newTestGenesis() - - tfBase = newTestForks(testGenesis, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, - }) - tfAlternative = newTestForks(testGenesis, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, - &types.Fork{Epoch: 0x700, Version: []byte{1}}, - }) - tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{ - &types.Fork{Epoch: 0, Version: []byte{0}}, - }) - - tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false) - tcBaseWithInvalidUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 200, false) // signer count too low - tcBaseWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 440, false) - tcReorgWithWorseUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, false) - tcReorgWithWorseUpdates2 = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 380, false) - tcReorgWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 420, false) - tcReorgWithFinalizedUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, true) - tcFork = newTestCommitteeChain(tcBase, tfAlternative, true, 7, 10, 400, false) - tcAnotherGenesis = newTestCommitteeChain(nil, tfAnotherGenesis, true, 0, 10, 400, false) -) - -func TestCommitteeChainFixedCommitteeRoots(t *testing.T) { - for _, reload := range []bool{false, true} { - c := newCommitteeChainTest(t, tfBase, 300, true) - c.setClockPeriod(7) - c.addFixedCommitteeRoot(tcBase, 4, nil) - c.addFixedCommitteeRoot(tcBase, 5, nil) - c.addFixedCommitteeRoot(tcBase, 6, nil) - c.addFixedCommitteeRoot(tcBase, 8, ErrInvalidPeriod) // range has to be continuous - c.addFixedCommitteeRoot(tcBase, 3, nil) - c.addFixedCommitteeRoot(tcBase, 2, nil) - if reload { - c.reloadChain() - } - c.addCommittee(tcBase, 4, nil) - c.addCommittee(tcBase, 6, ErrInvalidPeriod) // range has to be continuous - c.addCommittee(tcBase, 5, nil) - c.addCommittee(tcBase, 6, nil) - c.addCommittee(tcAnotherGenesis, 3, ErrWrongCommitteeRoot) - c.addCommittee(tcBase, 3, nil) - if reload { - c.reloadChain() - } - c.verifyRange(tcBase, 3, 6) - } -} - -func TestCommitteeChainCheckpointSync(t *testing.T) { - for _, enforceTime := range []bool{false, true} { - for _, reload := range []bool{false, true} { - c := newCommitteeChainTest(t, tfBase, 300, enforceTime) - if enforceTime { - c.setClockPeriod(6) - } - c.insertUpdate(tcBase, 3, true, ErrInvalidPeriod) - c.addFixedCommitteeRoot(tcBase, 3, nil) - c.addFixedCommitteeRoot(tcBase, 4, nil) - c.insertUpdate(tcBase, 4, true, ErrInvalidPeriod) // still no committee - c.addCommittee(tcBase, 3, nil) - c.addCommittee(tcBase, 4, nil) - if reload { - c.reloadChain() - } - c.verifyRange(tcBase, 3, 4) - c.insertUpdate(tcBase, 3, false, nil) // update can be added without committee here - c.insertUpdate(tcBase, 4, false, ErrNeedCommittee) // but not here as committee 5 is not there yet - c.insertUpdate(tcBase, 4, true, nil) - c.verifyRange(tcBase, 3, 5) - c.insertUpdate(tcBaseWithInvalidUpdates, 5, true, ErrInvalidUpdate) // signer count too low - c.insertUpdate(tcBase, 5, true, nil) - if reload { - c.reloadChain() - } - if enforceTime { - c.insertUpdate(tcBase, 6, true, ErrInvalidUpdate) // future update rejected - c.setClockPeriod(7) - } - c.insertUpdate(tcBase, 6, true, nil) // when the time comes it's accepted - if reload { - c.reloadChain() - } - if enforceTime { - c.verifyRange(tcBase, 3, 6) // committee 7 is there but still in the future - c.setClockPeriod(8) - } - c.verifyRange(tcBase, 3, 7) // now period 7 can also be verified - // try reverse syncing an update - c.insertUpdate(tcBase, 2, false, ErrInvalidPeriod) // fixed committee is needed first - c.addFixedCommitteeRoot(tcBase, 2, nil) - c.addCommittee(tcBase, 2, nil) - c.insertUpdate(tcBase, 2, false, nil) - c.verifyRange(tcBase, 2, 7) - } - } -} - -func TestCommitteeChainReorg(t *testing.T) { - for _, reload := range []bool{false, true} { - for _, addBetterUpdates := range []bool{false, true} { - c := newCommitteeChainTest(t, tfBase, 300, true) - c.setClockPeriod(11) - c.addFixedCommitteeRoot(tcBase, 3, nil) - c.addFixedCommitteeRoot(tcBase, 4, nil) - c.addCommittee(tcBase, 3, nil) - for period := uint64(3); period < 10; period++ { - c.insertUpdate(tcBase, period, true, nil) - } - if reload { - c.reloadChain() - } - c.verifyRange(tcBase, 3, 10) - c.insertUpdate(tcReorgWithWorseUpdates, 5, true, ErrCannotReorg) - c.insertUpdate(tcReorgWithWorseUpdates2, 5, true, ErrCannotReorg) - if addBetterUpdates { - // add better updates for the base chain and expect first reorg to fail - // (only add updates as committees should be the same) - for period := uint64(5); period < 10; period++ { - c.insertUpdate(tcBaseWithBetterUpdates, period, false, nil) - } - if reload { - c.reloadChain() - } - c.verifyRange(tcBase, 3, 10) // still on the same chain - c.insertUpdate(tcReorgWithBetterUpdates, 5, true, ErrCannotReorg) - } else { - // reorg with better updates - c.insertUpdate(tcReorgWithBetterUpdates, 5, false, ErrNeedCommittee) - c.verifyRange(tcBase, 3, 10) // no success yet, still on the base chain - c.verifyRange(tcReorgWithBetterUpdates, 3, 5) - c.insertUpdate(tcReorgWithBetterUpdates, 5, true, nil) - // successful reorg, base chain should only match before the reorg period - if reload { - c.reloadChain() - } - c.verifyRange(tcBase, 3, 5) - c.verifyRange(tcReorgWithBetterUpdates, 3, 6) - for period := uint64(6); period < 10; period++ { - c.insertUpdate(tcReorgWithBetterUpdates, period, true, nil) - } - c.verifyRange(tcReorgWithBetterUpdates, 3, 10) - } - // reorg with finalized updates; should succeed even if base chain updates - // have been improved because a finalized update beats everything else - c.insertUpdate(tcReorgWithFinalizedUpdates, 5, false, ErrNeedCommittee) - c.insertUpdate(tcReorgWithFinalizedUpdates, 5, true, nil) - if reload { - c.reloadChain() - } - c.verifyRange(tcReorgWithFinalizedUpdates, 3, 6) - for period := uint64(6); period < 10; period++ { - c.insertUpdate(tcReorgWithFinalizedUpdates, period, true, nil) - } - c.verifyRange(tcReorgWithFinalizedUpdates, 3, 10) - } - } -} - -func TestCommitteeChainFork(t *testing.T) { - c := newCommitteeChainTest(t, tfAlternative, 300, true) - c.setClockPeriod(11) - // trying to sync a chain on an alternative fork with the base chain data - c.addFixedCommitteeRoot(tcBase, 0, nil) - c.addFixedCommitteeRoot(tcBase, 1, nil) - c.addCommittee(tcBase, 0, nil) - // shared section should sync without errors - for period := uint64(0); period < 7; period++ { - c.insertUpdate(tcBase, period, true, nil) - } - c.insertUpdate(tcBase, 7, true, ErrInvalidUpdate) // wrong fork - // committee root #7 is still the same but signatures are already signed with - // a different fork id so period 7 should only verify on the alternative fork - c.verifyRange(tcBase, 0, 6) - c.verifyRange(tcFork, 0, 7) - for period := uint64(7); period < 10; period++ { - c.insertUpdate(tcFork, period, true, nil) - } - c.verifyRange(tcFork, 0, 10) - // reload the chain while switching to the base fork - c.config = tfBase - c.reloadChain() - // updates 7..9 should be rolled back now - c.verifyRange(tcFork, 0, 6) // again, period 7 only verifies on the right fork - c.verifyRange(tcBase, 0, 7) - c.insertUpdate(tcFork, 7, true, ErrInvalidUpdate) // wrong fork - for period := uint64(7); period < 10; period++ { - c.insertUpdate(tcBase, period, true, nil) - } - c.verifyRange(tcBase, 0, 10) -} - -type committeeChainTest struct { - t *testing.T - db *memorydb.Database - clock *mclock.Simulated - config types.ChainConfig - signerThreshold int - enforceTime bool - chain *CommitteeChain -} - -func newCommitteeChainTest(t *testing.T, config types.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest { - c := &committeeChainTest{ - t: t, - db: memorydb.New(), - clock: &mclock.Simulated{}, - config: config, - signerThreshold: signerThreshold, - enforceTime: enforceTime, - } - c.chain = newCommitteeChain(c.db, &config, signerThreshold, enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) }) - return c -} - -func (c *committeeChainTest) reloadChain() { - c.chain = newCommitteeChain(c.db, &c.config, c.signerThreshold, c.enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) }) -} - -func (c *committeeChainTest) setClockPeriod(period float64) { - target := mclock.AbsTime(period * float64(time.Second*12*params.SyncPeriodLength)) - wait := time.Duration(target - c.clock.Now()) - if wait < 0 { - c.t.Fatalf("Invalid setClockPeriod") - } - c.clock.Run(wait) -} - -func (c *committeeChainTest) addFixedCommitteeRoot(tc *testCommitteeChain, period uint64, expErr error) { - if err := c.chain.addFixedCommitteeRoot(period, tc.periods[period].committee.Root()); err != expErr { - c.t.Errorf("Incorrect error output from addFixedCommitteeRoot at period %d (expected %v, got %v)", period, expErr, err) - } -} - -func (c *committeeChainTest) addCommittee(tc *testCommitteeChain, period uint64, expErr error) { - if err := c.chain.addCommittee(period, tc.periods[period].committee); err != expErr { - c.t.Errorf("Incorrect error output from addCommittee at period %d (expected %v, got %v)", period, expErr, err) - } -} - -func (c *committeeChainTest) insertUpdate(tc *testCommitteeChain, period uint64, addCommittee bool, expErr error) { - var committee *types.SerializedSyncCommittee - if addCommittee { - committee = tc.periods[period+1].committee - } - if err := c.chain.InsertUpdate(tc.periods[period].update, committee); err != expErr { - c.t.Errorf("Incorrect error output from InsertUpdate at period %d (expected %v, got %v)", period, expErr, err) - } -} - -func (c *committeeChainTest) verifySignedHeader(tc *testCommitteeChain, period float64, expOk bool) { - slot := uint64(period * float64(params.SyncPeriodLength)) - signedHead := GenerateTestSignedHeader(types.Header{Slot: slot}, &tc.config, tc.periods[types.SyncPeriod(slot)].committee, slot+1, 400) - if ok, _, _ := c.chain.VerifySignedHeader(signedHead); ok != expOk { - c.t.Errorf("Incorrect output from VerifySignedHeader at period %f (expected %v, got %v)", period, expOk, ok) - } -} - -func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint64) { - if begin > 0 { - c.verifySignedHeader(tc, float64(begin)-0.5, false) - } - for period := begin; period <= end; period++ { - c.verifySignedHeader(tc, float64(period)+0.5, true) - } - c.verifySignedHeader(tc, float64(end)+1.5, false) -} - -func newTestGenesis() types.ChainConfig { - var config types.ChainConfig - rand.Read(config.GenesisValidatorsRoot[:]) - return config -} - -func newTestForks(config types.ChainConfig, forks types.Forks) types.ChainConfig { - for _, fork := range forks { - config.AddFork(fork.Name, fork.Epoch, fork.Version) - } - return config -} - -func newTestCommitteeChain(parent *testCommitteeChain, config types.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain { - tc := &testCommitteeChain{ - config: config, - } - if parent != nil { - tc.periods = make([]testPeriod, len(parent.periods)) - copy(tc.periods, parent.periods) - } - if newCommittees { - if begin == 0 { - tc.fillCommittees(begin, end+1) - } else { - tc.fillCommittees(begin+1, end+1) - } - } - tc.fillUpdates(begin, end, signerCount, finalizedHeader) - return tc -} - -type testPeriod struct { - committee *types.SerializedSyncCommittee - update *types.LightClientUpdate -} - -type testCommitteeChain struct { - periods []testPeriod - config types.ChainConfig -} - -func (tc *testCommitteeChain) fillCommittees(begin, end int) { - if len(tc.periods) <= end { - tc.periods = append(tc.periods, make([]testPeriod, end+1-len(tc.periods))...) - } - for i := begin; i <= end; i++ { - tc.periods[i].committee = GenerateTestCommittee() - } -} - -func (tc *testCommitteeChain) fillUpdates(begin, end int, signerCount int, finalizedHeader bool) { - for i := begin; i <= end; i++ { - tc.periods[i].update = GenerateTestUpdate(&tc.config, uint64(i), tc.periods[i].committee, tc.periods[i+1].committee, signerCount, finalizedHeader) - } -} diff --git a/builder/beacon/light/range.go b/builder/beacon/light/range.go deleted file mode 100644 index 76ebe2381..000000000 --- a/builder/beacon/light/range.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2023 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 light - -// periodRange represents a (possibly zero-length) range of integers (sync periods). -type periodRange struct { - Start, End uint64 -} - -// isEmpty returns true if the length of the range is zero. -func (a periodRange) isEmpty() bool { - return a.End == a.Start -} - -// contains returns true if the range includes the given period. -func (a periodRange) contains(period uint64) bool { - return period >= a.Start && period < a.End -} - -// canExpand returns true if the range includes or can be expanded with the given -// period (either the range is empty or the given period is inside, right before or -// right after the range). -func (a periodRange) canExpand(period uint64) bool { - return a.isEmpty() || (period+1 >= a.Start && period <= a.End) -} - -// expand expands the range with the given period. -// This method assumes that canExpand returned true: otherwise this is a no-op. -func (a *periodRange) expand(period uint64) { - if a.isEmpty() { - a.Start, a.End = period, period+1 - return - } - if a.Start == period+1 { - a.Start-- - } - if a.End == period { - a.End++ - } -} - -// split splits the range into two ranges. The 'fromPeriod' will be the first -// element in the second range (if present). -// The original range is unchanged by this operation -func (a *periodRange) split(fromPeriod uint64) (periodRange, periodRange) { - if fromPeriod <= a.Start { - // First range empty, everything in second range, - return periodRange{}, *a - } - if fromPeriod >= a.End { - // Second range empty, everything in first range, - return *a, periodRange{} - } - x := periodRange{a.Start, fromPeriod} - y := periodRange{fromPeriod, a.End} - return x, y -} - -// each invokes the supplied function fn once per period in range -func (a *periodRange) each(fn func(uint64)) { - for p := a.Start; p < a.End; p++ { - fn(p) - } -} diff --git a/builder/beacon/light/test_helpers.go b/builder/beacon/light/test_helpers.go deleted file mode 100644 index f537d963a..000000000 --- a/builder/beacon/light/test_helpers.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2023 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 light - -import ( - "crypto/rand" - "crypto/sha256" - mrand "math/rand" - - "github.com/ethereum/go-ethereum/beacon/merkle" - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/beacon/types" - "github.com/ethereum/go-ethereum/common" -) - -func GenerateTestCommittee() *types.SerializedSyncCommittee { - s := new(types.SerializedSyncCommittee) - rand.Read(s[:32]) - return s -} - -func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate { - update := new(types.LightClientUpdate) - update.NextSyncCommitteeRoot = nextCommittee.Root() - var attestedHeader types.Header - if finalizedHeader { - update.FinalizedHeader = new(types.Header) - *update.FinalizedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+100, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot)) - attestedHeader, update.FinalityBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexFinalBlock, merkle.Value(update.FinalizedHeader.Hash())) - } else { - attestedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+2000, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot)) - } - update.AttestedHeader = GenerateTestSignedHeader(attestedHeader, config, committee, attestedHeader.Slot+1, signerCount) - return update -} - -func GenerateTestSignedHeader(header types.Header, config *types.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader { - bitmask := makeBitmask(signerCount) - signingRoot, _ := config.Forks.SigningRoot(header) - c, _ := dummyVerifier{}.deserializeSyncCommittee(committee) - return types.SignedHeader{ - Header: header, - Signature: types.SyncAggregate{ - Signers: bitmask, - Signature: makeDummySignature(c.(dummySyncCommittee), signingRoot, bitmask), - }, - SignatureSlot: signatureSlot, - } -} - -func GenerateTestCheckpoint(period uint64, committee *types.SerializedSyncCommittee) *types.BootstrapData { - header, branch := makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexSyncCommittee, merkle.Value(committee.Root())) - return &types.BootstrapData{ - Header: header, - Committee: committee, - CommitteeRoot: committee.Root(), - CommitteeBranch: branch, - } -} - -func makeBitmask(signerCount int) (bitmask [params.SyncCommitteeBitmaskSize]byte) { - for i := 0; i < params.SyncCommitteeSize; i++ { - if mrand.Intn(params.SyncCommitteeSize-i) < signerCount { - bitmask[i/8] += byte(1) << (i & 7) - signerCount-- - } - } - return -} - -func makeTestHeaderWithMerkleProof(slot, index uint64, value merkle.Value) (types.Header, merkle.Values) { - var branch merkle.Values - hasher := sha256.New() - for index > 1 { - var proofHash merkle.Value - rand.Read(proofHash[:]) - hasher.Reset() - if index&1 == 0 { - hasher.Write(value[:]) - hasher.Write(proofHash[:]) - } else { - hasher.Write(proofHash[:]) - hasher.Write(value[:]) - } - hasher.Sum(value[:0]) - index >>= 1 - branch = append(branch, proofHash) - } - return types.Header{Slot: slot, StateRoot: common.Hash(value)}, branch -} - -// syncCommittee holds either a blsSyncCommittee or a fake dummySyncCommittee used for testing -type syncCommittee interface{} - -// committeeSigVerifier verifies sync committee signatures (either proper BLS -// signatures or fake signatures used for testing) -type committeeSigVerifier interface { - deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) - verifySignature(committee syncCommittee, signedRoot common.Hash, aggregate *types.SyncAggregate) bool -} - -// blsVerifier implements committeeSigVerifier -type blsVerifier struct{} - -// deserializeSyncCommittee implements committeeSigVerifier -func (blsVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) { - return s.Deserialize() -} - -// verifySignature implements committeeSigVerifier -func (blsVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool { - return committee.(*types.SyncCommittee).VerifySignature(signingRoot, aggregate) -} - -type dummySyncCommittee [32]byte - -// dummyVerifier implements committeeSigVerifier -type dummyVerifier struct{} - -// deserializeSyncCommittee implements committeeSigVerifier -func (dummyVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) { - var sc dummySyncCommittee - copy(sc[:], s[:32]) - return sc, nil -} - -// verifySignature implements committeeSigVerifier -func (dummyVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool { - return aggregate.Signature == makeDummySignature(committee.(dummySyncCommittee), signingRoot, aggregate.Signers) -} - -func makeDummySignature(committee dummySyncCommittee, signingRoot common.Hash, bitmask [params.SyncCommitteeBitmaskSize]byte) (sig [params.BLSSignatureSize]byte) { - for i, b := range committee[:] { - sig[i] = b ^ signingRoot[i] - } - copy(sig[32:], bitmask[:]) - return -} diff --git a/builder/beacon/merkle/merkle.go b/builder/beacon/merkle/merkle.go deleted file mode 100644 index 30896f9b0..000000000 --- a/builder/beacon/merkle/merkle.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 merkle implements proof verifications in binary merkle trees. -package merkle - -import ( - "crypto/sha256" - "errors" - "reflect" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// Value represents either a 32 byte leaf value or hash node in a binary merkle tree/partial proof. -type Value [32]byte - -// Values represent a series of merkle tree leaves/nodes. -type Values []Value - -var valueT = reflect.TypeOf(Value{}) - -// UnmarshalJSON parses a merkle value in hex syntax. -func (m *Value) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(valueT, input, m[:]) -} - -// VerifyProof verifies a Merkle proof branch for a single value in a -// binary Merkle tree (index is a generalized tree index). -func VerifyProof(root common.Hash, index uint64, branch Values, value Value) error { - hasher := sha256.New() - for _, sibling := range branch { - hasher.Reset() - if index&1 == 0 { - hasher.Write(value[:]) - hasher.Write(sibling[:]) - } else { - hasher.Write(sibling[:]) - hasher.Write(value[:]) - } - hasher.Sum(value[:0]) - if index >>= 1; index == 0 { - return errors.New("branch has extra items") - } - } - if index != 1 { - return errors.New("branch is missing items") - } - if common.Hash(value) != root { - return errors.New("root mismatch") - } - return nil -} diff --git a/builder/beacon/params/params.go b/builder/beacon/params/params.go deleted file mode 100644 index ee9feb1ac..000000000 --- a/builder/beacon/params/params.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 params - -const ( - EpochLength = 32 - SyncPeriodLength = 8192 - - BLSSignatureSize = 96 - BLSPubkeySize = 48 - - SyncCommitteeSize = 512 - SyncCommitteeBitmaskSize = SyncCommitteeSize / 8 - SyncCommitteeSupermajority = (SyncCommitteeSize*2 + 2) / 3 -) - -const ( - StateIndexGenesisTime = 32 - StateIndexGenesisValidators = 33 - StateIndexForkVersion = 141 - StateIndexLatestHeader = 36 - StateIndexBlockRoots = 37 - StateIndexStateRoots = 38 - StateIndexHistoricRoots = 39 - StateIndexFinalBlock = 105 - StateIndexSyncCommittee = 54 - StateIndexNextSyncCommittee = 55 - StateIndexExecPayload = 56 - StateIndexExecHead = 908 -) diff --git a/builder/beacon/types/committee.go b/builder/beacon/types/committee.go deleted file mode 100644 index 5f89c2755..000000000 --- a/builder/beacon/types/committee.go +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2023 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 types - -import ( - "crypto/sha256" - "encoding/json" - "fmt" - "math/bits" - - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - bls "github.com/protolambda/bls12-381-util" -) - -// SerializedSyncCommitteeSize is the size of the sync committee plus the -// aggregate public key. -const SerializedSyncCommitteeSize = (params.SyncCommitteeSize + 1) * params.BLSPubkeySize - -// SerializedSyncCommittee is the serialized version of a sync committee -// plus the aggregate public key. -type SerializedSyncCommittee [SerializedSyncCommitteeSize]byte - -// jsonSyncCommittee is the JSON representation of a sync committee. -// -// See data structure definition here: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate -type jsonSyncCommittee struct { - Pubkeys []hexutil.Bytes `json:"pubkeys"` - Aggregate hexutil.Bytes `json:"aggregate_pubkey"` -} - -// MarshalJSON implements json.Marshaler. -func (s *SerializedSyncCommittee) MarshalJSON() ([]byte, error) { - sc := jsonSyncCommittee{Pubkeys: make([]hexutil.Bytes, params.SyncCommitteeSize)} - for i := range sc.Pubkeys { - sc.Pubkeys[i] = make(hexutil.Bytes, params.BLSPubkeySize) - copy(sc.Pubkeys[i][:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize]) - } - sc.Aggregate = make(hexutil.Bytes, params.BLSPubkeySize) - copy(sc.Aggregate[:], s[params.SyncCommitteeSize*params.BLSPubkeySize:]) - return json.Marshal(&sc) -} - -// UnmarshalJSON implements json.Marshaler. -func (s *SerializedSyncCommittee) UnmarshalJSON(input []byte) error { - var sc jsonSyncCommittee - if err := json.Unmarshal(input, &sc); err != nil { - return err - } - if len(sc.Pubkeys) != params.SyncCommitteeSize { - return fmt.Errorf("invalid number of pubkeys %d", len(sc.Pubkeys)) - } - for i, key := range sc.Pubkeys { - if len(key) != params.BLSPubkeySize { - return fmt.Errorf("pubkey %d has invalid size %d", i, len(key)) - } - copy(s[i*params.BLSPubkeySize:], key[:]) - } - if len(sc.Aggregate) != params.BLSPubkeySize { - return fmt.Errorf("invalid aggregate pubkey size %d", len(sc.Aggregate)) - } - copy(s[params.SyncCommitteeSize*params.BLSPubkeySize:], sc.Aggregate[:]) - return nil -} - -// Root calculates the root hash of the binary tree representation of a sync -// committee provided in serialized format. -// -// TODO(zsfelfoldi): Get rid of this when SSZ encoding lands. -func (s *SerializedSyncCommittee) Root() common.Hash { - var ( - hasher = sha256.New() - padding [64 - params.BLSPubkeySize]byte - data [params.SyncCommitteeSize]common.Hash - l = params.SyncCommitteeSize - ) - for i := range data { - hasher.Reset() - hasher.Write(s[i*params.BLSPubkeySize : (i+1)*params.BLSPubkeySize]) - hasher.Write(padding[:]) - hasher.Sum(data[i][:0]) - } - for l > 1 { - for i := 0; i < l/2; i++ { - hasher.Reset() - hasher.Write(data[i*2][:]) - hasher.Write(data[i*2+1][:]) - hasher.Sum(data[i][:0]) - } - l /= 2 - } - hasher.Reset() - hasher.Write(s[SerializedSyncCommitteeSize-params.BLSPubkeySize : SerializedSyncCommitteeSize]) - hasher.Write(padding[:]) - hasher.Sum(data[1][:0]) - hasher.Reset() - hasher.Write(data[0][:]) - hasher.Write(data[1][:]) - hasher.Sum(data[0][:0]) - return data[0] -} - -// Deserialize splits open the pubkeys into proper BLS key types. -func (s *SerializedSyncCommittee) Deserialize() (*SyncCommittee, error) { - sc := new(SyncCommittee) - for i := 0; i <= params.SyncCommitteeSize; i++ { - key := new(bls.Pubkey) - - var bytes [params.BLSPubkeySize]byte - copy(bytes[:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize]) - - if err := key.Deserialize(&bytes); err != nil { - return nil, err - } - if i < params.SyncCommitteeSize { - sc.keys[i] = key - } else { - sc.aggregate = key - } - } - return sc, nil -} - -// SyncCommittee is a set of sync committee signer pubkeys and the aggregate key. -// -// See data structure definition here: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate -type SyncCommittee struct { - keys [params.SyncCommitteeSize]*bls.Pubkey - aggregate *bls.Pubkey -} - -// VerifySignature returns true if the given sync aggregate is a valid signature -// or the given hash. -func (sc *SyncCommittee) VerifySignature(signingRoot common.Hash, signature *SyncAggregate) bool { - var ( - sig bls.Signature - keys = make([]*bls.Pubkey, 0, params.SyncCommitteeSize) - ) - if err := sig.Deserialize(&signature.Signature); err != nil { - return false - } - for i, key := range sc.keys { - if signature.Signers[i/8]&(byte(1)<<(i%8)) != 0 { - keys = append(keys, key) - } - } - return bls.FastAggregateVerify(keys, signingRoot[:], &sig) -} - -//go:generate go run github.com/fjl/gencodec -type SyncAggregate -field-override syncAggregateMarshaling -out gen_syncaggregate_json.go - -// SyncAggregate represents an aggregated BLS signature with Signers referring -// to a subset of the corresponding sync committee. -// -// See data structure definition here: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate -type SyncAggregate struct { - Signers [params.SyncCommitteeBitmaskSize]byte `gencodec:"required" json:"sync_committee_bits"` - Signature [params.BLSSignatureSize]byte `gencodec:"required" json:"sync_committee_signature"` -} - -type syncAggregateMarshaling struct { - Signers hexutil.Bytes - Signature hexutil.Bytes -} - -// SignerCount returns the number of signers in the aggregate signature. -func (s *SyncAggregate) SignerCount() int { - var count int - for _, v := range s.Signers { - count += bits.OnesCount8(v) - } - return count -} diff --git a/builder/beacon/types/config.go b/builder/beacon/types/config.go deleted file mode 100644 index 8cb8808b6..000000000 --- a/builder/beacon/types/config.go +++ /dev/null @@ -1,176 +0,0 @@ -// 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 types - -import ( - "crypto/sha256" - "fmt" - "os" - "sort" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/beacon/merkle" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "gopkg.in/yaml.v3" -) - -// syncCommitteeDomain specifies the signatures specific use to avoid clashes -// across signing different data structures. -const syncCommitteeDomain = 7 - -// Fork describes a single beacon chain fork and also stores the calculated -// signature domain used after this fork. -type Fork struct { - // Name of the fork in the chain config (config.yaml) file{ - Name string - - // Epoch when given fork version is activated - Epoch uint64 - - // Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types - Version []byte - - // calculated by computeDomain, based on fork version and genesis validators root - domain merkle.Value -} - -// computeDomain returns the signature domain based on the given fork version -// and genesis validator set root. -func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) { - var ( - hasher = sha256.New() - forkVersion32 merkle.Value - forkDataRoot merkle.Value - ) - copy(forkVersion32[:], f.Version) - hasher.Write(forkVersion32[:]) - hasher.Write(genesisValidatorsRoot[:]) - hasher.Sum(forkDataRoot[:0]) - - f.domain[0] = syncCommitteeDomain - copy(f.domain[4:], forkDataRoot[:28]) -} - -// Forks is the list of all beacon chain forks in the chain configuration. -type Forks []*Fork - -// domain returns the signature domain for the given epoch (assumes that domains -// have already been calculated). -func (f Forks) domain(epoch uint64) (merkle.Value, error) { - for i := len(f) - 1; i >= 0; i-- { - if epoch >= f[i].Epoch { - return f[i].domain, nil - } - } - return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch) -} - -// SigningRoot calculates the signing root of the given header. -func (f Forks) SigningRoot(header Header) (common.Hash, error) { - domain, err := f.domain(header.Epoch()) - if err != nil { - return common.Hash{}, err - } - var ( - signingRoot common.Hash - headerHash = header.Hash() - hasher = sha256.New() - ) - hasher.Write(headerHash[:]) - hasher.Write(domain[:]) - hasher.Sum(signingRoot[:0]) - - return signingRoot, nil -} - -func (f Forks) Len() int { return len(f) } -func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] } -func (f Forks) Less(i, j int) bool { return f[i].Epoch < f[j].Epoch } - -// ChainConfig contains the beacon chain configuration. -type ChainConfig struct { - GenesisTime uint64 // Unix timestamp of slot 0 - GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation - Forks Forks -} - -// AddFork adds a new item to the list of forks. -func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainConfig { - fork := &Fork{ - Name: name, - Epoch: epoch, - Version: version, - } - fork.computeDomain(c.GenesisValidatorsRoot) - - c.Forks = append(c.Forks, fork) - sort.Sort(c.Forks) - - return c -} - -// LoadForks parses the beacon chain configuration file (config.yaml) and extracts -// the list of forks. -func (c *ChainConfig) LoadForks(path string) error { - file, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read beacon chain config file: %v", err) - } - config := make(map[string]string) - if err := yaml.Unmarshal(file, &config); err != nil { - return fmt.Errorf("failed to parse beacon chain config file: %v", err) - } - var ( - versions = make(map[string][]byte) - epochs = make(map[string]uint64) - ) - epochs["GENESIS"] = 0 - - for key, value := range config { - if strings.HasSuffix(key, "_FORK_VERSION") { - name := key[:len(key)-len("_FORK_VERSION")] - if v, err := hexutil.Decode(value); err == nil { - versions[name] = v - } else { - return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err) - } - } - if strings.HasSuffix(key, "_FORK_EPOCH") { - name := key[:len(key)-len("_FORK_EPOCH")] - if v, err := strconv.ParseUint(value, 10, 64); err == nil { - epochs[name] = v - } else { - return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err) - } - } - } - for name, epoch := range epochs { - if version, ok := versions[name]; ok { - delete(versions, name) - c.AddFork(name, epoch, version) - } else { - return fmt.Errorf("fork id missing for %q in beacon chain config file", name) - } - } - for name := range versions { - return fmt.Errorf("epoch number missing for fork %q in beacon chain config file", name) - } - sort.Sort(c.Forks) - return nil -} diff --git a/builder/beacon/types/gen_header_json.go b/builder/beacon/types/gen_header_json.go deleted file mode 100644 index 9b3ffea06..000000000 --- a/builder/beacon/types/gen_header_json.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - - "github.com/ethereum/go-ethereum/common" -) - -var _ = (*headerMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (h Header) MarshalJSON() ([]byte, error) { - type Header struct { - Slot common.Decimal `gencodec:"required" json:"slot"` - ProposerIndex common.Decimal `gencodec:"required" json:"proposer_index"` - ParentRoot common.Hash `gencodec:"required" json:"parent_root"` - StateRoot common.Hash `gencodec:"required" json:"state_root"` - BodyRoot common.Hash `gencodec:"required" json:"body_root"` - } - var enc Header - enc.Slot = common.Decimal(h.Slot) - enc.ProposerIndex = common.Decimal(h.ProposerIndex) - enc.ParentRoot = h.ParentRoot - enc.StateRoot = h.StateRoot - enc.BodyRoot = h.BodyRoot - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (h *Header) UnmarshalJSON(input []byte) error { - type Header struct { - Slot *common.Decimal `gencodec:"required" json:"slot"` - ProposerIndex *common.Decimal `gencodec:"required" json:"proposer_index"` - ParentRoot *common.Hash `gencodec:"required" json:"parent_root"` - StateRoot *common.Hash `gencodec:"required" json:"state_root"` - BodyRoot *common.Hash `gencodec:"required" json:"body_root"` - } - var dec Header - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Slot == nil { - return errors.New("missing required field 'slot' for Header") - } - h.Slot = uint64(*dec.Slot) - if dec.ProposerIndex == nil { - return errors.New("missing required field 'proposer_index' for Header") - } - h.ProposerIndex = uint64(*dec.ProposerIndex) - if dec.ParentRoot == nil { - return errors.New("missing required field 'parent_root' for Header") - } - h.ParentRoot = *dec.ParentRoot - if dec.StateRoot == nil { - return errors.New("missing required field 'state_root' for Header") - } - h.StateRoot = *dec.StateRoot - if dec.BodyRoot == nil { - return errors.New("missing required field 'body_root' for Header") - } - h.BodyRoot = *dec.BodyRoot - return nil -} diff --git a/builder/beacon/types/gen_syncaggregate_json.go b/builder/beacon/types/gen_syncaggregate_json.go deleted file mode 100644 index 1547ec5f0..000000000 --- a/builder/beacon/types/gen_syncaggregate_json.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*syncAggregateMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (s SyncAggregate) MarshalJSON() ([]byte, error) { - type SyncAggregate struct { - Signers hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"` - Signature hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"` - } - var enc SyncAggregate - enc.Signers = s.Signers[:] - enc.Signature = s.Signature[:] - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (s *SyncAggregate) UnmarshalJSON(input []byte) error { - type SyncAggregate struct { - Signers *hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"` - Signature *hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"` - } - var dec SyncAggregate - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Signers == nil { - return errors.New("missing required field 'sync_committee_bits' for SyncAggregate") - } - if len(*dec.Signers) != len(s.Signers) { - return errors.New("field 'sync_committee_bits' has wrong length, need 64 items") - } - copy(s.Signers[:], *dec.Signers) - if dec.Signature == nil { - return errors.New("missing required field 'sync_committee_signature' for SyncAggregate") - } - if len(*dec.Signature) != len(s.Signature) { - return errors.New("field 'sync_committee_signature' has wrong length, need 96 items") - } - copy(s.Signature[:], *dec.Signature) - return nil -} diff --git a/builder/beacon/types/header.go b/builder/beacon/types/header.go deleted file mode 100644 index 2ddc4575f..000000000 --- a/builder/beacon/types/header.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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 types implements a few types of the beacon chain for light client usage. -package types - -import ( - "crypto/sha256" - "encoding/binary" - - "github.com/ethereum/go-ethereum/beacon/merkle" - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/common" -) - -//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go - -const ( - headerIndexSlot = 8 - headerIndexProposerIndex = 9 - headerIndexParentRoot = 10 - headerIndexStateRoot = 11 - headerIndexBodyRoot = 12 -) - -// Header defines a beacon header. -// -// See data structure definition here: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader -type Header struct { - // Monotonically increasing slot number for the beacon block (may be gapped) - Slot uint64 `gencodec:"required" json:"slot"` - - // Index into the validator table who created the beacon block - ProposerIndex uint64 `gencodec:"required" json:"proposer_index"` - - // SSZ hash of the parent beacon header - ParentRoot common.Hash `gencodec:"required" json:"parent_root"` - - // SSZ hash of the beacon state (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beacon-state) - StateRoot common.Hash `gencodec:"required" json:"state_root"` - - // SSZ hash of the beacon block body (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beaconblockbody) - BodyRoot common.Hash `gencodec:"required" json:"body_root"` -} - -// headerMarshaling is a field type overrides for gencodec. -type headerMarshaling struct { - Slot common.Decimal - ProposerIndex common.Decimal -} - -// Hash calculates the block root of the header. -// -// TODO(zsfelfoldi): Remove this when an SSZ encoder lands. -func (h *Header) Hash() common.Hash { - var values [16]merkle.Value // values corresponding to indices 8 to 15 of the beacon header tree - binary.LittleEndian.PutUint64(values[headerIndexSlot][:8], h.Slot) - binary.LittleEndian.PutUint64(values[headerIndexProposerIndex][:8], h.ProposerIndex) - values[headerIndexParentRoot] = merkle.Value(h.ParentRoot) - values[headerIndexStateRoot] = merkle.Value(h.StateRoot) - values[headerIndexBodyRoot] = merkle.Value(h.BodyRoot) - hasher := sha256.New() - for i := 7; i > 0; i-- { - hasher.Reset() - hasher.Write(values[i*2][:]) - hasher.Write(values[i*2+1][:]) - hasher.Sum(values[i][:0]) - } - return common.Hash(values[1]) -} - -// Epoch returns the epoch the header belongs to. -func (h *Header) Epoch() uint64 { - return h.Slot / params.EpochLength -} - -// SyncPeriod returns the sync period the header belongs to. -func (h *Header) SyncPeriod() uint64 { - return SyncPeriod(h.Slot) -} - -// SyncPeriodStart returns the first slot of the given period. -func SyncPeriodStart(period uint64) uint64 { - return period * params.SyncPeriodLength -} - -// SyncPeriod returns the sync period that the given slot belongs to. -func SyncPeriod(slot uint64) uint64 { - return slot / params.SyncPeriodLength -} - -// SignedHeader represents a beacon header signed by a sync committee. -// -// This structure is created from either an optimistic update or an instant update: -// - https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate -// - https://github.com/zsfelfoldi/beacon-APIs/blob/instant_update/apis/beacon/light_client/instant_update.yaml -type SignedHeader struct { - // Beacon header being signed - Header Header - - // Sync committee BLS signature aggregate - Signature SyncAggregate - - // Slot in which the signature has been created (newer than Header.Slot, - // determines the signing sync committee) - SignatureSlot uint64 -} diff --git a/builder/beacon/types/light_sync.go b/builder/beacon/types/light_sync.go deleted file mode 100644 index 3284081e4..000000000 --- a/builder/beacon/types/light_sync.go +++ /dev/null @@ -1,136 +0,0 @@ -// 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 types - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/beacon/merkle" - "github.com/ethereum/go-ethereum/beacon/params" - "github.com/ethereum/go-ethereum/common" -) - -// BootstrapData contains a sync committee where light sync can be started, -// together with a proof through a beacon header and corresponding state. -// Note: BootstrapData is fetched from a server based on a known checkpoint hash. -type BootstrapData struct { - Header Header - CommitteeRoot common.Hash - Committee *SerializedSyncCommittee `rlp:"-"` - CommitteeBranch merkle.Values -} - -// Validate verifies the proof included in BootstrapData. -func (c *BootstrapData) Validate() error { - if c.CommitteeRoot != c.Committee.Root() { - return errors.New("wrong committee root") - } - return merkle.VerifyProof(c.Header.StateRoot, params.StateIndexSyncCommittee, c.CommitteeBranch, merkle.Value(c.CommitteeRoot)) -} - -// LightClientUpdate is a proof of the next sync committee root based on a header -// signed by the sync committee of the given period. Optionally, the update can -// prove quasi-finality by the signed header referring to a previous, finalized -// header from the same period, and the finalized header referring to the next -// sync committee root. -// -// See data structure definition here: -// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientupdate -type LightClientUpdate struct { - AttestedHeader SignedHeader // Arbitrary header out of the period signed by the sync committee - NextSyncCommitteeRoot common.Hash // Sync committee of the next period advertised in the current one - NextSyncCommitteeBranch merkle.Values // Proof for the next period's sync committee - - FinalizedHeader *Header `rlp:"nil"` // Optional header to announce a point of finality - FinalityBranch merkle.Values // Proof for the announced finality - - score *UpdateScore // Weight of the update to compare between competing ones -} - -// Validate verifies the validity of the update. -func (update *LightClientUpdate) Validate() error { - period := update.AttestedHeader.Header.SyncPeriod() - if SyncPeriod(update.AttestedHeader.SignatureSlot) != period { - return errors.New("signature slot and signed header are from different periods") - } - if update.FinalizedHeader != nil { - if update.FinalizedHeader.SyncPeriod() != period { - return errors.New("finalized header is from different period") - } - if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexFinalBlock, update.FinalityBranch, merkle.Value(update.FinalizedHeader.Hash())); err != nil { - return fmt.Errorf("invalid finalized header proof: %w", err) - } - } - if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexNextSyncCommittee, update.NextSyncCommitteeBranch, merkle.Value(update.NextSyncCommitteeRoot)); err != nil { - return fmt.Errorf("invalid next sync committee proof: %w", err) - } - return nil -} - -// Score returns the UpdateScore describing the proof strength of the update -// Note: thread safety can be ensured by always calling Score on a newly received -// or decoded update before making it potentially available for other threads -func (update *LightClientUpdate) Score() UpdateScore { - if update.score == nil { - update.score = &UpdateScore{ - SignerCount: uint32(update.AttestedHeader.Signature.SignerCount()), - SubPeriodIndex: uint32(update.AttestedHeader.Header.Slot & 0x1fff), - FinalizedHeader: update.FinalizedHeader != nil, - } - } - return *update.score -} - -// UpdateScore allows the comparison between updates at the same period in order -// to find the best update chain that provides the strongest proof of being canonical. -// -// UpdateScores have a tightly packed binary encoding format for efficient p2p -// protocol transmission. Each UpdateScore is encoded in 3 bytes. -// When interpreted as a 24 bit little indian unsigned integer: -// - the lowest 10 bits contain the number of signers in the header signature aggregate -// - the next 13 bits contain the "sub-period index" which is he signed header's -// slot modulo params.SyncPeriodLength (which is correlated with the risk of the chain being -// re-orged before the previous period boundary in case of non-finalized updates) -// - the highest bit is set when the update is finalized (meaning that the finality -// header referenced by the signed header is in the same period as the signed -// header, making reorgs before the period boundary impossible -type UpdateScore struct { - SignerCount uint32 // number of signers in the header signature aggregate - SubPeriodIndex uint32 // signed header's slot modulo params.SyncPeriodLength - FinalizedHeader bool // update is considered finalized if has finalized header from the same period and 2/3 signatures -} - -// finalized returns true if the update has a header signed by at least 2/3 of -// the committee, referring to a finalized header that refers to the next sync -// committee. This condition is a close approximation of the actual finality -// condition that can only be verified by full beacon nodes. -func (u *UpdateScore) finalized() bool { - return u.FinalizedHeader && u.SignerCount >= params.SyncCommitteeSupermajority -} - -// BetterThan returns true if update u is considered better than w. -func (u UpdateScore) BetterThan(w UpdateScore) bool { - var ( - uFinalized = u.finalized() - wFinalized = w.finalized() - ) - if uFinalized != wFinalized { - return uFinalized - } - return u.SignerCount > w.SignerCount -} diff --git a/builder/build/bot/macos-build.sh b/builder/build/bot/macos-build.sh deleted file mode 100644 index f1620bca8..000000000 --- a/builder/build/bot/macos-build.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e -x - -# -- Check XCode version -xcodebuild -version -# xcrun simctl list - -# -- Build for macOS and upload to Azure -go run build/ci.go install -dlgo -go run build/ci.go archive -type tar # -signer OSX_SIGNING_KEY -upload gethstore/builds - -# # -- CocoaPods -# gem uninstall cocoapods -a -x -# gem install cocoapods -# mv ~/.cocoapods/repos/master ~/.cocoapods/repos/master.bak -# sed -i '.bak' 's/repo.join/!repo.join/g' $(dirname `gem which cocoapods`)/cocoapods/sources_manager.rb -# git clone --depth=1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master -# pod setup --verbose - -# # -- Build for iOS and upload to Azure -# go run build/ci.go xcode -signer IOS_SIGNING_KEY -upload gethstore/builds diff --git a/builder/build/bot/ppa-build.sh b/builder/build/bot/ppa-build.sh deleted file mode 100644 index ca04262a2..000000000 --- a/builder/build/bot/ppa-build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -e -x - -# Note: this script is meant to be run in a Debian/Ubuntu docker container, -# as user 'root'. - -# Install the required tools for creating source packages. -apt-get -yq --no-install-suggests --no-install-recommends install\ - devscripts debhelper dput fakeroot - -# Add the SSH key of ppa.launchpad.net to known_hosts. -mkdir -p ~/.ssh -echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts - -# Build the source package and upload. -go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder " diff --git a/builder/build/checksums.txt b/builder/build/checksums.txt deleted file mode 100644 index 03a53946d..000000000 --- a/builder/build/checksums.txt +++ /dev/null @@ -1,65 +0,0 @@ -# This file contains sha256 checksums of optional build dependencies. - -# version:spec-tests 2.1.0 -# https://github.com/ethereum/execution-spec-tests/releases -# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/ -ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz - -# version:golang 1.21.6 -# https://go.dev/dl/ -124926a62e45f78daabbaedb9c011d97633186a33c238ffc1e25320c02046248 go1.21.6.src.tar.gz -31d6ecca09010ab351e51343a5af81d678902061fee871f912bdd5ef4d778850 go1.21.6.darwin-amd64.tar.gz -0ff541fb37c38e5e5c5bcecc8f4f43c5ffd5e3a6c33a5d3e4003ded66fcfb331 go1.21.6.darwin-arm64.tar.gz -a1d1a149b34bf0f53965a237682c6da1140acabb131bf0e597240e4a140b0e5e go1.21.6.freebsd-386.tar.gz -de59e1217e4398b1522eed8dddabab2fa1b97aecbdca3af08e34832b4f0e3f81 go1.21.6.freebsd-amd64.tar.gz -05d09041b5a1193c14e4b2db3f7fcc649b236c567f5eb93305c537851b72dd95 go1.21.6.linux-386.tar.gz -3f934f40ac360b9c01f616a9aa1796d227d8b0328bf64cb045c7b8c4ee9caea4 go1.21.6.linux-amd64.tar.gz -e2e8aa88e1b5170a0d495d7d9c766af2b2b6c6925a8f8956d834ad6b4cacbd9a go1.21.6.linux-arm64.tar.gz -6a8eda6cc6a799ff25e74ce0c13fdc1a76c0983a0bb07c789a2a3454bf6ec9b2 go1.21.6.linux-armv6l.tar.gz -e872b1e9a3f2f08fd4554615a32ca9123a4ba877ab6d19d36abc3424f86bc07f go1.21.6.linux-ppc64le.tar.gz -92894d0f732d3379bc414ffdd617eaadad47e1d72610e10d69a1156db03fc052 go1.21.6.linux-s390x.tar.gz -65b38857135cf45c80e1d267e0ce4f80fe149326c68835217da4f2da9b7943fe go1.21.6.windows-386.zip -27ac9dd6e66fb3fd0acfa6792ff053c86e7d2c055b022f4b5d53bfddec9e3301 go1.21.6.windows-amd64.zip -b93aff8f3c882c764c66a39b7a1483b0460e051e9992bf3435479129e5051bcd go1.21.6.windows-arm64.zip - -# version:golangci 1.55.2 -# https://github.com/golangci/golangci-lint/releases/ -# https://github.com/golangci/golangci-lint/releases/download/v1.55.2/ -632e96e6d5294fbbe7b2c410a49c8fa01c60712a0af85a567de85bcc1623ea21 golangci-lint-1.55.2-darwin-amd64.tar.gz -234463f059249f82045824afdcdd5db5682d0593052f58f6a3039a0a1c3899f6 golangci-lint-1.55.2-darwin-arm64.tar.gz -2bdd105e2d4e003a9058c33a22bb191a1e0f30fa0790acca0d8fbffac1d6247c golangci-lint-1.55.2-freebsd-386.tar.gz -e75056e8b082386676ce23eba455cf893931a792c0d87e1e3743c0aec33c7fb5 golangci-lint-1.55.2-freebsd-amd64.tar.gz -5789b933facaf6136bd23f1d50add67b79bbcf8dfdfc9069a37f729395940a66 golangci-lint-1.55.2-freebsd-armv6.tar.gz -7f21ab1008d05f32c954f99470fc86a83a059e530fe2add1d0b7d8ed4d8992a7 golangci-lint-1.55.2-freebsd-armv7.tar.gz -33ab06139b9219a28251f10821da94423db30285cc2af97494cbb2a281927de9 golangci-lint-1.55.2-illumos-amd64.tar.gz -57ce6f8ce3ad6ee45d7cc3d9a047545a851c2547637834a3fcb086c7b40b1e6b golangci-lint-1.55.2-linux-386.tar.gz -ca21c961a33be3bc15e4292dc40c98c8dcc5463a7b6768a3afc123761630c09c golangci-lint-1.55.2-linux-amd64.tar.gz -8eb0cee9b1dbf0eaa49871798c7f8a5b35f2960c52d776a5f31eb7d886b92746 golangci-lint-1.55.2-linux-arm64.tar.gz -3195f3e0f37d353fd5bd415cabcd4e263f5c29d3d0ffb176c26ff3d2c75eb3bb golangci-lint-1.55.2-linux-armv6.tar.gz -c823ee36eb1a719e171de1f2f5ca3068033dce8d9817232fd10ed71fd6650406 golangci-lint-1.55.2-linux-armv7.tar.gz -758a5d2a356dc494bd13ed4c0d4bf5a54a4dc91267ea5ecdd87b86c7ca0624e7 golangci-lint-1.55.2-linux-loong64.tar.gz -2c7b9abdce7cae802a67d583cd7c6dca520bff6d0e17c8535a918e2f2b437aa0 golangci-lint-1.55.2-linux-mips64.tar.gz -024e0a15b85352cc27271285526e16a4ab66d3e67afbbe446c9808c06cb8dbed golangci-lint-1.55.2-linux-mips64le.tar.gz -6b00f89ba5506c1de1efdd9fa17c54093013a294fefd8b9b31534db626a672ee golangci-lint-1.55.2-linux-ppc64le.tar.gz -0faa0d047d9bf7b703ed3ea65b6117043c93504f9ca1de25ae929d3901c73d4a golangci-lint-1.55.2-linux-riscv64.tar.gz -30dec9b22e7d5bb4e9d5ccea96da20f71cd7db3c8cf30b8ddc7cb9174c4d742a golangci-lint-1.55.2-linux-s390x.tar.gz -5a0ede48f79ad707902fdb29be8cd2abd8302dc122b65ebae3fdfc86751c7698 golangci-lint-1.55.2-netbsd-386.tar.gz -95af20a2e617126dd5b08122ece7819101070e1582a961067ce8c41172f901ad golangci-lint-1.55.2-netbsd-amd64.tar.gz -94fb7dacb7527847cc95d7120904e19a2a0a81a0d50d61766c9e0251da72ab9d golangci-lint-1.55.2-netbsd-armv6.tar.gz -ca906bce5fee9619400e4a321c56476fe4a4efb6ac4fc989d340eb5563348873 golangci-lint-1.55.2-netbsd-armv7.tar.gz -45b442f69fc8915c4500201c0247b7f3f69544dbc9165403a61f9095f2c57355 golangci-lint-1.55.2-windows-386.zip -f57d434d231d43417dfa631587522f8c1991220b43c8ffadb9c7bd279508bf81 golangci-lint-1.55.2-windows-amd64.zip -fd7dc8f4c6829ee6fafb252a4d81d2155cd35da7833665cbb25d53ce7cecd990 golangci-lint-1.55.2-windows-arm64.zip -1892c3c24f9e7ef44b02f6750c703864b6dc350129f3ec39510300007b2376f1 golangci-lint-1.55.2-windows-armv6.zip -a5e68ae73d38748b5269fad36ac7575e3c162a5dc63ef58abdea03cc5da4522a golangci-lint-1.55.2-windows-armv7.zip - -# This is the builder on PPA that will build Go itself (inception-y), don't modify! -# -# This version is fine to be old and full of security holes, we just use it -# to build the latest Go. Don't change it. If it ever becomes insufficient, -# we need to switch over to a recursive builder to jump across supported -# versions. -# -# version:ppa-builder 1.19.6 -# https://go.dev/dl/ -d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz diff --git a/builder/build/ci-notes.md b/builder/build/ci-notes.md deleted file mode 100644 index edd9adc1c..000000000 --- a/builder/build/ci-notes.md +++ /dev/null @@ -1,50 +0,0 @@ -# Debian Packaging - -Tagged releases and develop branch commits are available as installable Debian packages -for Ubuntu. Packages are built for the all Ubuntu versions which are supported by -Canonical. - -Packages of develop branch commits have suffix -unstable and cannot be installed alongside -the stable version. Switching between release streams requires user intervention. - -## Launchpad - -The packages are built and served by launchpad.net. We generate a Debian source package -for each distribution and upload it. Their builder picks up the source package, builds it -and installs the new version into the PPA repository. Launchpad requires a valid signature -by a team member for source package uploads. - -The signing key is stored in an environment variable which Travis CI makes available to -certain builds. Since Travis CI doesn't support FTP, SFTP is used to transfer the -packages. To set this up yourself, you need to create a Launchpad user and add a GPG key -and SSH key to it. Then encode both keys as base64 and configure 'secret' environment -variables `PPA_SIGNING_KEY` and `PPA_SSH_KEY` on Travis. - -We want to build go-ethereum with the most recent version of Go, irrespective of the Go -version that is available in the main Ubuntu repository. In order to make this possible, -we bundle the entire Go sources into our own source archive and start the built job by -compiling Go and then using that to build go-ethereum. On Trusty we have a special case -requiring the `~gophers/ubuntu/archive` PPA since Trusty can't even build Go itself. PPA -deps are set at https://launchpad.net/%7Eethereum/+archive/ubuntu/ethereum/+edit-dependencies - -## Building Packages Locally (for testing) - -You need to run Ubuntu to do test packaging. - -Install any version of Go and Debian packaging tools: - - $ sudo apt-get install build-essential golang-go devscripts debhelper python-bzrlib python-paramiko - -Create the source packages: - - $ go run build/ci.go debsrc -workdir dist - -Then go into the source package directory for your running distribution and build the package: - - $ cd dist/ethereum-unstable-1.9.6+bionic - $ dpkg-buildpackage - -Built packages are placed in the dist/ directory. - - $ cd .. - $ dpkg-deb -c geth-unstable_1.9.6+bionic_amd64.deb diff --git a/builder/build/ci.go b/builder/build/ci.go deleted file mode 100644 index 4d8dba6ce..000000000 --- a/builder/build/ci.go +++ /dev/null @@ -1,1110 +0,0 @@ -// Copyright 2016 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 . - -//go:build none -// +build none - -/* -The ci command is called from Continuous Integration scripts. - -Usage: go run build/ci.go - -Available commands are: - - install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables - test [ -coverage ] [ packages... ] -- runs the tests - lint -- runs certain pre-selected linters - archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts - importkeys -- imports signing keys from env - debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package - nsis -- creates a Windows NSIS installer - purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore - -For all commands, -n prevents execution of external programs (dry run mode). -*/ -package main - -import ( - "bytes" - "encoding/base64" - "flag" - "fmt" - "log" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "strconv" - "strings" - "time" - - "github.com/cespare/cp" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/signify" - "github.com/ethereum/go-ethereum/internal/build" - "github.com/ethereum/go-ethereum/params" -) - -var ( - // Files that end up in the geth*.zip archive. - gethArchiveFiles = []string{ - "COPYING", - executablePath("geth"), - } - - // Files that end up in the geth-alltools*.zip archive. - allToolsArchiveFiles = []string{ - "COPYING", - executablePath("abigen"), - executablePath("bootnode"), - executablePath("evm"), - executablePath("geth"), - executablePath("rlpdump"), - executablePath("clef"), - } - - // A debian package is created for all executables listed here. - debExecutables = []debExecutable{ - { - BinaryName: "abigen", - Description: "Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages.", - }, - { - BinaryName: "bootnode", - Description: "Ethereum bootnode.", - }, - { - BinaryName: "evm", - Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.", - }, - { - BinaryName: "geth", - Description: "Ethereum CLI client.", - }, - { - BinaryName: "rlpdump", - Description: "Developer utility tool that prints RLP structures.", - }, - { - BinaryName: "clef", - Description: "Ethereum account management tool.", - }, - } - - // A debian package is created for all executables listed here. - debEthereum = debPackage{ - Name: "ethereum", - Version: params.Version, - Executables: debExecutables, - } - - // Debian meta packages to build and push to Ubuntu PPA - debPackages = []debPackage{ - debEthereum, - } - - // Distros for which packages are created. - // Note: vivid is unsupported because there is no golang-1.6 package for it. - // Note: the following Ubuntu releases have been officially deprecated on Launchpad: - // wily, yakkety, zesty, artful, cosmic, disco, eoan, groovy, hirsuite, impish, - // kinetic, lunar - debDistroGoBoots = map[string]string{ - "trusty": "golang-1.11", // 14.04, EOL: 04/2024 - "xenial": "golang-go", // 16.04, EOL: 04/2026 - "bionic": "golang-go", // 18.04, EOL: 04/2028 - "focal": "golang-go", // 20.04, EOL: 04/2030 - "jammy": "golang-go", // 22.04, EOL: 04/2032 - "mantic": "golang-go", // 23.10, EOL: 07/2024 - } - - debGoBootPaths = map[string]string{ - "golang-1.11": "/usr/lib/go-1.11", - "golang-go": "/usr/lib/go", - } - - // This is where the tests should be unpacked. - executionSpecTestsDir = "tests/spec-tests" -) - -var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) - -func executablePath(name string) string { - if runtime.GOOS == "windows" { - name += ".exe" - } - return filepath.Join(GOBIN, name) -} - -func main() { - log.SetFlags(log.Lshortfile) - - if !common.FileExist(filepath.Join("build", "ci.go")) { - log.Fatal("this script must be run from the root of the repository") - } - if len(os.Args) < 2 { - log.Fatal("need subcommand as first argument") - } - switch os.Args[1] { - case "install": - doInstall(os.Args[2:]) - case "test": - doTest(os.Args[2:]) - case "lint": - doLint(os.Args[2:]) - case "archive": - doArchive(os.Args[2:]) - case "docker": - doDocker(os.Args[2:]) - case "debsrc": - doDebianSource(os.Args[2:]) - case "nsis": - doWindowsInstaller(os.Args[2:]) - case "purge": - doPurge(os.Args[2:]) - case "sanitycheck": - doSanityCheck() - default: - log.Fatal("unknown command ", os.Args[1]) - } -} - -// Compiling - -func doInstall(cmdline []string) { - var ( - dlgo = flag.Bool("dlgo", false, "Download Go and build with it") - arch = flag.String("arch", "", "Architecture to cross build for") - cc = flag.String("cc", "", "C compiler to cross build with") - staticlink = flag.Bool("static", false, "Create statically-linked executable") - ) - flag.CommandLine.Parse(cmdline) - env := build.Env() - - // Configure the toolchain. - tc := build.GoToolchain{GOARCH: *arch, CC: *cc} - if *dlgo { - csdb := build.MustLoadChecksums("build/checksums.txt") - tc.Root = build.DownloadGo(csdb) - } - // Disable CLI markdown doc generation in release builds. - buildTags := []string{"urfave_cli_no_docs"} - - // Enable linking the CKZG library since we can make it work with additional flags. - if env.UbuntuVersion != "trusty" { - buildTags = append(buildTags, "ckzg") - } - - // Configure the build. - gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...) - - // arm64 CI builders are memory-constrained and can't handle concurrent builds, - // better disable it. This check isn't the best, it should probably - // check for something in env instead. - if env.CI && runtime.GOARCH == "arm64" { - gobuild.Args = append(gobuild.Args, "-p", "1") - } - // We use -trimpath to avoid leaking local paths into the built executables. - gobuild.Args = append(gobuild.Args, "-trimpath") - - // Show packages during build. - gobuild.Args = append(gobuild.Args, "-v") - - // Now we choose what we're even building. - // Default: collect all 'main' packages in cmd/ and build those. - packages := flag.Args() - if len(packages) == 0 { - packages = build.FindMainPackages("./cmd") - } - - // Do the build! - for _, pkg := range packages { - args := make([]string, len(gobuild.Args)) - copy(args, gobuild.Args) - args = append(args, "-o", executablePath(path.Base(pkg))) - args = append(args, pkg) - build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env}) - } -} - -// buildFlags returns the go tool flags for building. -func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) { - var ld []string - if env.Commit != "" { - ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitCommit="+env.Commit) - ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitDate="+env.Date) - } - // Strip DWARF on darwin. This used to be required for certain things, - // and there is no downside to this, so we just keep doing it. - if runtime.GOOS == "darwin" { - ld = append(ld, "-s") - } - if runtime.GOOS == "linux" { - // Enforce the stacksize to 8M, which is the case on most platforms apart from - // alpine Linux. - extld := []string{"-Wl,-z,stack-size=0x800000"} - if staticLinking { - extld = append(extld, "-static") - // Under static linking, use of certain glibc features must be - // disabled to avoid shared library dependencies. - buildTags = append(buildTags, "osusergo", "netgo") - } - ld = append(ld, "-extldflags", "'"+strings.Join(extld, " ")+"'") - } - if len(ld) > 0 { - flags = append(flags, "-ldflags", strings.Join(ld, " ")) - } - if len(buildTags) > 0 { - flags = append(flags, "-tags", strings.Join(buildTags, ",")) - } - return flags -} - -// Running The Tests -// -// "tests" also includes static analysis tools such as vet. - -func doTest(cmdline []string) { - var ( - dlgo = flag.Bool("dlgo", false, "Download Go and build with it") - arch = flag.String("arch", "", "Run tests for given architecture") - cc = flag.String("cc", "", "Sets C compiler binary") - coverage = flag.Bool("coverage", false, "Whether to record code coverage") - verbose = flag.Bool("v", false, "Whether to log verbosely") - race = flag.Bool("race", false, "Execute the race detector") - short = flag.Bool("short", false, "Pass the 'short'-flag to go test") - cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads") - ) - flag.CommandLine.Parse(cmdline) - - // Get test fixtures. - csdb := build.MustLoadChecksums("build/checksums.txt") - downloadSpecTestFixtures(csdb, *cachedir) - - // Configure the toolchain. - tc := build.GoToolchain{GOARCH: *arch, CC: *cc} - if *dlgo { - tc.Root = build.DownloadGo(csdb) - } - gotest := tc.Go("test") - - // CI needs a bit more time for the statetests (default 10m). - gotest.Args = append(gotest.Args, "-timeout=20m") - - // Enable CKZG backend in CI. - gotest.Args = append(gotest.Args, "-tags=ckzg") - - // Enable integration-tests - gotest.Args = append(gotest.Args, "-tags=integrationtests") - - // Test a single package at a time. CI builders are slow - // and some tests run into timeouts under load. - gotest.Args = append(gotest.Args, "-p", "1") - if *coverage { - gotest.Args = append(gotest.Args, "-covermode=atomic", "-cover") - } - if *verbose { - gotest.Args = append(gotest.Args, "-v") - } - if *race { - gotest.Args = append(gotest.Args, "-race") - } - if *short { - gotest.Args = append(gotest.Args, "-short") - } - - packages := []string{"./..."} - if len(flag.CommandLine.Args()) > 0 { - packages = flag.CommandLine.Args() - } - gotest.Args = append(gotest.Args, packages...) - build.MustRun(gotest) -} - -// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures. -func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string { - executionSpecTestsVersion, err := build.Version(csdb, "spec-tests") - if err != nil { - log.Fatal(err) - } - ext := ".tar.gz" - base := "fixtures_develop" // TODO(MariusVanDerWijden) rename once the version becomes part of the filename - url := fmt.Sprintf("https://github.com/ethereum/execution-spec-tests/releases/download/v%s/%s%s", executionSpecTestsVersion, base, ext) - archivePath := filepath.Join(cachedir, base+ext) - if err := csdb.DownloadFile(url, archivePath); err != nil { - log.Fatal(err) - } - if err := build.ExtractArchive(archivePath, executionSpecTestsDir); err != nil { - log.Fatal(err) - } - return filepath.Join(cachedir, base) -} - -// doLint runs golangci-lint on requested packages. -func doLint(cmdline []string) { - var ( - cachedir = flag.String("cachedir", "./build/cache", "directory for caching golangci-lint binary.") - ) - flag.CommandLine.Parse(cmdline) - packages := []string{"./..."} - if len(flag.CommandLine.Args()) > 0 { - packages = flag.CommandLine.Args() - } - - linter := downloadLinter(*cachedir) - lflags := []string{"run", "--config", ".golangci.yml"} - build.MustRunCommandWithOutput(linter, append(lflags, packages...)...) - fmt.Println("You have achieved perfection.") -} - -// downloadLinter downloads and unpacks golangci-lint. -func downloadLinter(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - version, err := build.Version(csdb, "golangci") - if err != nil { - log.Fatal(err) - } - arch := runtime.GOARCH - ext := ".tar.gz" - - if runtime.GOOS == "windows" { - ext = ".zip" - } - if arch == "arm" { - arch += "v" + os.Getenv("GOARM") - } - base := fmt.Sprintf("golangci-lint-%s-%s-%s", version, runtime.GOOS, arch) - url := fmt.Sprintf("https://github.com/golangci/golangci-lint/releases/download/v%s/%s%s", version, base, ext) - archivePath := filepath.Join(cachedir, base+ext) - if err := csdb.DownloadFile(url, archivePath); err != nil { - log.Fatal(err) - } - if err := build.ExtractArchive(archivePath, cachedir); err != nil { - log.Fatal(err) - } - return filepath.Join(cachedir, base, "golangci-lint") -} - -// Release Packaging -func doArchive(cmdline []string) { - var ( - arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging") - atype = flag.String("type", "zip", "Type of archive to write (zip|tar)") - signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`) - signify = flag.String("signify", "", `Environment variable holding the signify key (e.g. LINUX_SIGNIFY_KEY)`) - upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) - ext string - ) - flag.CommandLine.Parse(cmdline) - switch *atype { - case "zip": - ext = ".zip" - case "tar": - ext = ".tar.gz" - default: - log.Fatal("unknown archive type: ", atype) - } - - var ( - env = build.Env() - basegeth = archiveBasename(*arch, params.ArchiveVersion(env.Commit)) - geth = "geth-" + basegeth + ext - alltools = "geth-alltools-" + basegeth + ext - ) - maybeSkipArchive(env) - if err := build.WriteArchive(geth, gethArchiveFiles); err != nil { - log.Fatal(err) - } - if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil { - log.Fatal(err) - } - for _, archive := range []string{geth, alltools} { - if err := archiveUpload(archive, *upload, *signer, *signify); err != nil { - log.Fatal(err) - } - } -} - -func archiveBasename(arch string, archiveVersion string) string { - platform := runtime.GOOS + "-" + arch - if arch == "arm" { - platform += os.Getenv("GOARM") - } - if arch == "android" { - platform = "android-all" - } - if arch == "ios" { - platform = "ios-all" - } - return platform + "-" + archiveVersion -} - -func archiveUpload(archive string, blobstore string, signer string, signifyVar string) error { - // If signing was requested, generate the signature files - if signer != "" { - key := getenvBase64(signer) - if err := build.PGPSignFile(archive, archive+".asc", string(key)); err != nil { - return err - } - } - if signifyVar != "" { - key := os.Getenv(signifyVar) - untrustedComment := "verify with geth-release.pub" - trustedComment := fmt.Sprintf("%s (%s)", archive, time.Now().UTC().Format(time.RFC1123)) - if err := signify.SignFile(archive, archive+".sig", key, untrustedComment, trustedComment); err != nil { - return err - } - } - // If uploading to Azure was requested, push the archive possibly with its signature - if blobstore != "" { - auth := build.AzureBlobstoreConfig{ - Account: strings.Split(blobstore, "/")[0], - Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"), - Container: strings.SplitN(blobstore, "/", 2)[1], - } - if err := build.AzureBlobstoreUpload(archive, filepath.Base(archive), auth); err != nil { - return err - } - if signer != "" { - if err := build.AzureBlobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil { - return err - } - } - if signifyVar != "" { - if err := build.AzureBlobstoreUpload(archive+".sig", filepath.Base(archive+".sig"), auth); err != nil { - return err - } - } - } - return nil -} - -// skips archiving for some build configurations. -func maybeSkipArchive(env build.Environment) { - if env.IsPullRequest { - log.Printf("skipping archive creation because this is a PR build") - os.Exit(0) - } - if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") { - log.Printf("skipping archive creation because branch %q, tag %q is not on the inclusion list", env.Branch, env.Tag) - os.Exit(0) - } -} - -// Builds the docker images and optionally uploads them to Docker Hub. -func doDocker(cmdline []string) { - var ( - image = flag.Bool("image", false, `Whether to build and push an arch specific docker image`) - manifest = flag.String("manifest", "", `Push a multi-arch docker image for the specified architectures (usually "amd64,arm64")`) - upload = flag.String("upload", "", `Where to upload the docker image (usually "ethereum/client-go")`) - ) - flag.CommandLine.Parse(cmdline) - - // Skip building and pushing docker images for PR builds - env := build.Env() - maybeSkipArchive(env) - - // Retrieve the upload credentials and authenticate - user := getenvBase64("DOCKER_HUB_USERNAME") - pass := getenvBase64("DOCKER_HUB_PASSWORD") - - if len(user) > 0 && len(pass) > 0 { - auther := exec.Command("docker", "login", "-u", string(user), "--password-stdin") - auther.Stdin = bytes.NewReader(pass) - build.MustRun(auther) - } - // Retrieve the version infos to build and push to the following paths: - // - ethereum/client-go:latest - Pushes to the master branch, Geth only - // - ethereum/client-go:stable - Version tag publish on GitHub, Geth only - // - ethereum/client-go:alltools-latest - Pushes to the master branch, Geth & tools - // - ethereum/client-go:alltools-stable - Version tag publish on GitHub, Geth & tools - // - ethereum/client-go:release-. - Version tag publish on GitHub, Geth only - // - ethereum/client-go:alltools-release-. - Version tag publish on GitHub, Geth & tools - // - ethereum/client-go:v.. - Version tag publish on GitHub, Geth only - // - ethereum/client-go:alltools-v.. - Version tag publish on GitHub, Geth & tools - var tags []string - - switch { - case env.Branch == "master": - tags = []string{"latest"} - case strings.HasPrefix(env.Tag, "v1."): - tags = []string{"stable", fmt.Sprintf("release-1.%d", params.VersionMinor), "v" + params.Version} - } - // If architecture specific image builds are requested, build and push them - if *image { - build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:TAG", *upload), ".") - build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:alltools-TAG", *upload), "-f", "Dockerfile.alltools", ".") - - // Tag and upload the images to Docker Hub - for _, tag := range tags { - gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, runtime.GOARCH) - toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, runtime.GOARCH) - - // If the image already exists (non version tag), check the build - // number to prevent overwriting a newer commit if concurrent builds - // are running. This is still a tiny bit racey if two published are - // done at the same time, but that's extremely unlikely even on the - // master branch. - for _, img := range []string{gethImage, toolImage} { - if exec.Command("docker", "pull", img).Run() != nil { - continue // Generally the only failure is a missing image, which is good - } - buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput() - if err != nil { - log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum)) - } - buildnum = bytes.TrimSpace(buildnum) - - if len(buildnum) > 0 && len(env.Buildnum) > 0 { - oldnum, err := strconv.Atoi(string(buildnum)) - if err != nil { - log.Fatalf("Failed to parse old image build number: %v", err) - } - newnum, err := strconv.Atoi(env.Buildnum) - if err != nil { - log.Fatalf("Failed to parse current build number: %v", err) - } - if oldnum > newnum { - log.Fatalf("Current build number %d not newer than existing %d", newnum, oldnum) - } else { - log.Printf("Updating %s from build %d to %d", img, oldnum, newnum) - } - } - } - build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:TAG", *upload), gethImage) - build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:alltools-TAG", *upload), toolImage) - build.MustRunCommand("docker", "push", gethImage) - build.MustRunCommand("docker", "push", toolImage) - } - } - // If multi-arch image manifest push is requested, assemble it - if len(*manifest) != 0 { - // Since different architectures are pushed by different builders, wait - // until all required images are updated. - var mismatch bool - for i := 0; i < 2; i++ { // 2 attempts, second is race check - mismatch = false // hope there's no mismatch now - - for _, tag := range tags { - for _, arch := range strings.Split(*manifest, ",") { - gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, arch) - toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, arch) - - for _, img := range []string{gethImage, toolImage} { - if out, err := exec.Command("docker", "pull", img).CombinedOutput(); err != nil { - log.Printf("Required image %s unavailable: %v\nOutput: %s", img, err, out) - mismatch = true - break - } - buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput() - if err != nil { - log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum)) - } - buildnum = bytes.TrimSpace(buildnum) - - if string(buildnum) != env.Buildnum { - log.Printf("Build number mismatch on %s: want %s, have %s", img, env.Buildnum, buildnum) - mismatch = true - break - } - } - if mismatch { - break - } - } - if mismatch { - break - } - } - if mismatch { - // Build numbers mismatching, retry in a short time to - // avoid concurrent fails in both publisher images. If - // however the retry failed too, it means the concurrent - // builder is still crunching, let that do the publish. - if i == 0 { - time.Sleep(30 * time.Second) - } - continue - } - break - } - if mismatch { - log.Println("Relinquishing publish to other builder") - return - } - // Assemble and push the Geth manifest image - for _, tag := range tags { - gethImage := fmt.Sprintf("%s:%s", *upload, tag) - - var gethSubImages []string - for _, arch := range strings.Split(*manifest, ",") { - gethSubImages = append(gethSubImages, gethImage+"-"+arch) - } - build.MustRunCommand("docker", append([]string{"manifest", "create", gethImage}, gethSubImages...)...) - build.MustRunCommand("docker", "manifest", "push", gethImage) - } - // Assemble and push the alltools manifest image - for _, tag := range tags { - toolImage := fmt.Sprintf("%s:alltools-%s", *upload, tag) - - var toolSubImages []string - for _, arch := range strings.Split(*manifest, ",") { - toolSubImages = append(toolSubImages, toolImage+"-"+arch) - } - build.MustRunCommand("docker", append([]string{"manifest", "create", toolImage}, toolSubImages...)...) - build.MustRunCommand("docker", "manifest", "push", toolImage) - } - } -} - -// Debian Packaging -func doDebianSource(cmdline []string) { - var ( - cachedir = flag.String("cachedir", "./build/cache", `Filesystem path to cache the downloaded Go bundles at`) - signer = flag.String("signer", "", `Signing key name, also used as package author`) - upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`) - sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`) - workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) - now = time.Now() - ) - flag.CommandLine.Parse(cmdline) - *workdir = makeWorkdir(*workdir) - env := build.Env() - tc := new(build.GoToolchain) - maybeSkipArchive(env) - - // Import the signing key. - if key := getenvBase64("PPA_SIGNING_KEY"); len(key) > 0 { - gpg := exec.Command("gpg", "--import") - gpg.Stdin = bytes.NewReader(key) - build.MustRun(gpg) - } - // Download and verify the Go source packages. - var ( - gobootbundle = downloadGoBootstrapSources(*cachedir) - gobundle = downloadGoSources(*cachedir) - ) - // Download all the dependencies needed to build the sources and run the ci script - srcdepfetch := tc.Go("mod", "download") - srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath")) - build.MustRun(srcdepfetch) - - cidepfetch := tc.Go("run", "./build/ci.go") - cidepfetch.Env = append(cidepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath")) - cidepfetch.Run() // Command fails, don't care, we only need the deps to start it - - // Create Debian packages and upload them. - for _, pkg := range debPackages { - for distro, goboot := range debDistroGoBoots { - // Prepare the debian package with the go-ethereum sources. - meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables) - pkgdir := stageDebianSource(*workdir, meta) - - // Add bootstrapper Go source code - if err := build.ExtractArchive(gobootbundle, pkgdir); err != nil { - log.Fatalf("Failed to extract bootstrapper Go sources: %v", err) - } - if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".goboot")); err != nil { - log.Fatalf("Failed to rename bootstrapper Go source folder: %v", err) - } - // Add builder Go source code - if err := build.ExtractArchive(gobundle, pkgdir); err != nil { - log.Fatalf("Failed to extract builder Go sources: %v", err) - } - if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil { - log.Fatalf("Failed to rename builder Go source folder: %v", err) - } - // Add all dependency modules in compressed form - os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755) - if err := cp.CopyAll(filepath.Join(pkgdir, ".mod", "cache", "download"), filepath.Join(*workdir, "modgopath", "pkg", "mod", "cache", "download")); err != nil { - log.Fatalf("Failed to copy Go module dependencies: %v", err) - } - // Run the packaging and upload to the PPA - debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc", "-d", "-Zxz", "-nc") - debuild.Dir = pkgdir - build.MustRun(debuild) - - var ( - basename = fmt.Sprintf("%s_%s", meta.Name(), meta.VersionString()) - source = filepath.Join(*workdir, basename+".tar.xz") - dsc = filepath.Join(*workdir, basename+".dsc") - changes = filepath.Join(*workdir, basename+"_source.changes") - buildinfo = filepath.Join(*workdir, basename+"_source.buildinfo") - ) - if *signer != "" { - build.MustRunCommand("debsign", changes) - } - if *upload != "" { - ppaUpload(*workdir, *upload, *sshUser, []string{source, dsc, changes, buildinfo}) - } - } - } -} - -// downloadGoBootstrapSources downloads the Go source tarball that will be used -// to bootstrap the builder Go. -func downloadGoBootstrapSources(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - gobootVersion, err := build.Version(csdb, "ppa-builder") - if err != nil { - log.Fatal(err) - } - file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion) - url := "https://dl.google.com/go/" + file - dst := filepath.Join(cachedir, file) - if err := csdb.DownloadFile(url, dst); err != nil { - log.Fatal(err) - } - return dst -} - -// downloadGoSources downloads the Go source tarball. -func downloadGoSources(cachedir string) string { - csdb := build.MustLoadChecksums("build/checksums.txt") - dlgoVersion, err := build.Version(csdb, "golang") - if err != nil { - log.Fatal(err) - } - file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion) - url := "https://dl.google.com/go/" + file - dst := filepath.Join(cachedir, file) - if err := csdb.DownloadFile(url, dst); err != nil { - log.Fatal(err) - } - return dst -} - -func ppaUpload(workdir, ppa, sshUser string, files []string) { - p := strings.Split(ppa, "/") - if len(p) != 2 { - log.Fatal("-upload PPA name must contain single /") - } - if sshUser == "" { - sshUser = p[0] - } - incomingDir := fmt.Sprintf("~%s/ubuntu/%s", p[0], p[1]) - // Create the SSH identity file if it doesn't exist. - var idfile string - if sshkey := getenvBase64("PPA_SSH_KEY"); len(sshkey) > 0 { - idfile = filepath.Join(workdir, "sshkey") - if !common.FileExist(idfile) { - os.WriteFile(idfile, sshkey, 0600) - } - } - // Upload - dest := sshUser + "@ppa.launchpad.net" - if err := build.UploadSFTP(idfile, dest, incomingDir, files); err != nil { - log.Fatal(err) - } -} - -func getenvBase64(variable string) []byte { - dec, err := base64.StdEncoding.DecodeString(os.Getenv(variable)) - if err != nil { - log.Fatal("invalid base64 " + variable) - } - return []byte(dec) -} - -func makeWorkdir(wdflag string) string { - var err error - if wdflag != "" { - err = os.MkdirAll(wdflag, 0744) - } else { - wdflag, err = os.MkdirTemp("", "geth-build-") - } - if err != nil { - log.Fatal(err) - } - return wdflag -} - -func isUnstableBuild(env build.Environment) bool { - if env.Tag != "" { - return false - } - return true -} - -type debPackage struct { - Name string // the name of the Debian package to produce, e.g. "ethereum" - Version string // the clean version of the debPackage, e.g. 1.8.12, without any metadata - Executables []debExecutable // executables to be included in the package -} - -type debMetadata struct { - Env build.Environment - GoBootPackage string - GoBootPath string - - PackageName string - - // go-ethereum version being built. Note that this - // is not the debian package version. The package version - // is constructed by VersionString. - Version string - - Author string // "name ", also selects signing key - Distro, Time string - Executables []debExecutable -} - -type debExecutable struct { - PackageName string - BinaryName string - Description string -} - -// Package returns the name of the package if present, or -// fallbacks to BinaryName -func (d debExecutable) Package() string { - if d.PackageName != "" { - return d.PackageName - } - return d.BinaryName -} - -func newDebMetadata(distro, goboot, author string, env build.Environment, t time.Time, name string, version string, exes []debExecutable) debMetadata { - if author == "" { - // No signing key, use default author. - author = "Ethereum Builds " - } - return debMetadata{ - GoBootPackage: goboot, - GoBootPath: debGoBootPaths[goboot], - PackageName: name, - Env: env, - Author: author, - Distro: distro, - Version: version, - Time: t.Format(time.RFC1123Z), - Executables: exes, - } -} - -// Name returns the name of the metapackage that depends -// on all executable packages. -func (meta debMetadata) Name() string { - if isUnstableBuild(meta.Env) { - return meta.PackageName + "-unstable" - } - return meta.PackageName -} - -// VersionString returns the debian version of the packages. -func (meta debMetadata) VersionString() string { - vsn := meta.Version - if meta.Env.Buildnum != "" { - vsn += "+build" + meta.Env.Buildnum - } - if meta.Distro != "" { - vsn += "+" + meta.Distro - } - return vsn -} - -// ExeList returns the list of all executable packages. -func (meta debMetadata) ExeList() string { - names := make([]string, len(meta.Executables)) - for i, e := range meta.Executables { - names[i] = meta.ExeName(e) - } - return strings.Join(names, ", ") -} - -// ExeName returns the package name of an executable package. -func (meta debMetadata) ExeName(exe debExecutable) string { - if isUnstableBuild(meta.Env) { - return exe.Package() + "-unstable" - } - return exe.Package() -} - -// ExeConflicts returns the content of the Conflicts field -// for executable packages. -func (meta debMetadata) ExeConflicts(exe debExecutable) string { - if isUnstableBuild(meta.Env) { - // Set up the conflicts list so that the *-unstable packages - // cannot be installed alongside the regular version. - // - // https://www.debian.org/doc/debian-policy/ch-relationships.html - // is very explicit about Conflicts: and says that Breaks: should - // be preferred and the conflicting files should be handled via - // alternates. We might do this eventually but using a conflict is - // easier now. - return "ethereum, " + exe.Package() - } - return "" -} - -func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { - pkg := meta.Name() + "-" + meta.VersionString() - pkgdir = filepath.Join(tmpdir, pkg) - if err := os.Mkdir(pkgdir, 0755); err != nil { - log.Fatal(err) - } - // Copy the source code. - build.MustRunCommand("git", "checkout-index", "-a", "--prefix", pkgdir+string(filepath.Separator)) - - // Put the debian build files in place. - debian := filepath.Join(pkgdir, "debian") - build.Render("build/deb/"+meta.PackageName+"/deb.rules", filepath.Join(debian, "rules"), 0755, meta) - build.Render("build/deb/"+meta.PackageName+"/deb.changelog", filepath.Join(debian, "changelog"), 0644, meta) - build.Render("build/deb/"+meta.PackageName+"/deb.control", filepath.Join(debian, "control"), 0644, meta) - build.Render("build/deb/"+meta.PackageName+"/deb.copyright", filepath.Join(debian, "copyright"), 0644, meta) - build.RenderString("8\n", filepath.Join(debian, "compat"), 0644, meta) - build.RenderString("3.0 (native)\n", filepath.Join(debian, "source/format"), 0644, meta) - for _, exe := range meta.Executables { - install := filepath.Join(debian, meta.ExeName(exe)+".install") - docs := filepath.Join(debian, meta.ExeName(exe)+".docs") - build.Render("build/deb/"+meta.PackageName+"/deb.install", install, 0644, exe) - build.Render("build/deb/"+meta.PackageName+"/deb.docs", docs, 0644, exe) - } - return pkgdir -} - -// Windows installer -func doWindowsInstaller(cmdline []string) { - // Parse the flags and make skip installer generation on PRs - var ( - arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging") - signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`) - signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`) - upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) - workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) - ) - flag.CommandLine.Parse(cmdline) - *workdir = makeWorkdir(*workdir) - env := build.Env() - maybeSkipArchive(env) - - // Aggregate binaries that are included in the installer - var ( - devTools []string - allTools []string - gethTool string - ) - for _, file := range allToolsArchiveFiles { - if file == "COPYING" { // license, copied later - continue - } - allTools = append(allTools, filepath.Base(file)) - if filepath.Base(file) == "geth.exe" { - gethTool = file - } else { - devTools = append(devTools, file) - } - } - - // Render NSIS scripts: Installer NSIS contains two installer sections, - // first section contains the geth binary, second section holds the dev tools. - templateData := map[string]interface{}{ - "License": "COPYING", - "Geth": gethTool, - "DevTools": devTools, - } - build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil) - build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData) - build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools) - build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil) - build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil) - if err := cp.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll"); err != nil { - log.Fatalf("Failed to copy SimpleFC.dll: %v", err) - } - if err := cp.CopyFile(filepath.Join(*workdir, "COPYING"), "COPYING"); err != nil { - log.Fatalf("Failed to copy copyright note: %v", err) - } - // Build the installer. This assumes that all the needed files have been previously - // built (don't mix building and packaging to keep cross compilation complexity to a - // minimum). - version := strings.Split(params.Version, ".") - if env.Commit != "" { - version[2] += "-" + env.Commit[:8] - } - installer, err := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe") - if err != nil { - log.Fatalf("Failed to convert installer file path: %v", err) - } - build.MustRunCommand("makensis.exe", - "/DOUTPUTFILE="+installer, - "/DMAJORVERSION="+version[0], - "/DMINORVERSION="+version[1], - "/DBUILDVERSION="+version[2], - "/DARCH="+*arch, - filepath.Join(*workdir, "geth.nsi"), - ) - // Sign and publish installer. - if err := archiveUpload(installer, *upload, *signer, *signify); err != nil { - log.Fatal(err) - } -} - -// Binary distribution cleanups - -func doPurge(cmdline []string) { - var ( - store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`) - limit = flag.Int("days", 30, `Age threshold above which to delete unstable archives`) - ) - flag.CommandLine.Parse(cmdline) - - if env := build.Env(); !env.IsCronJob { - log.Printf("skipping because not a cron job") - os.Exit(0) - } - // Create the azure authentication and list the current archives - auth := build.AzureBlobstoreConfig{ - Account: strings.Split(*store, "/")[0], - Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"), - Container: strings.SplitN(*store, "/", 2)[1], - } - blobs, err := build.AzureBlobstoreList(auth) - if err != nil { - log.Fatal(err) - } - fmt.Printf("Found %d blobs\n", len(blobs)) - - // Iterate over the blobs, collect and sort all unstable builds - for i := 0; i < len(blobs); i++ { - if !strings.Contains(*blobs[i].Name, "unstable") { - blobs = append(blobs[:i], blobs[i+1:]...) - i-- - } - } - for i := 0; i < len(blobs); i++ { - for j := i + 1; j < len(blobs); j++ { - if blobs[i].Properties.LastModified.After(*blobs[j].Properties.LastModified) { - blobs[i], blobs[j] = blobs[j], blobs[i] - } - } - } - // Filter out all archives more recent that the given threshold - for i, blob := range blobs { - if time.Since(*blob.Properties.LastModified) < time.Duration(*limit)*24*time.Hour { - blobs = blobs[:i] - break - } - } - fmt.Printf("Deleting %d blobs\n", len(blobs)) - // Delete all marked as such and return - if err := build.AzureBlobstoreDelete(auth, blobs); err != nil { - log.Fatal(err) - } -} - -func doSanityCheck() { - build.DownloadAndVerifyChecksums(build.MustLoadChecksums("build/checksums.txt")) -} diff --git a/builder/build/deb/ethereum/completions/bash/geth b/builder/build/deb/ethereum/completions/bash/geth deleted file mode 100755 index a78952793..000000000 --- a/builder/build/deb/ethereum/completions/bash/geth +++ /dev/null @@ -1,16 +0,0 @@ -_geth_bash_autocomplete() { - if [[ "${COMP_WORDS[0]}" != "source" ]]; then - local cur opts base - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - if [[ "$cur" == "-"* ]]; then - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion ) - else - opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) - fi - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - fi -} - -complete -o bashdefault -o default -o nospace -F _geth_bash_autocomplete geth diff --git a/builder/build/deb/ethereum/completions/zsh/_geth b/builder/build/deb/ethereum/completions/zsh/_geth deleted file mode 100644 index 119794c53..000000000 --- a/builder/build/deb/ethereum/completions/zsh/_geth +++ /dev/null @@ -1,18 +0,0 @@ -_geth_zsh_autocomplete() { - local -a opts - local cur - cur=${words[-1]} - if [[ "$cur" == "-"* ]]; then - opts=("${(@f)$(${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}") - else - opts=("${(@f)$(${words[@]:0:#words[@]-1} --generate-bash-completion)}") - fi - - if [[ "${opts[1]}" != "" ]]; then - _describe 'values' opts - else - _files - fi -} - -compdef _geth_zsh_autocomplete geth diff --git a/builder/build/deb/ethereum/deb.changelog b/builder/build/deb/ethereum/deb.changelog deleted file mode 100644 index 83f804a83..000000000 --- a/builder/build/deb/ethereum/deb.changelog +++ /dev/null @@ -1,5 +0,0 @@ -{{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low - - * git build of {{.Env.Commit}} - - -- {{.Author}} {{.Time}} diff --git a/builder/build/deb/ethereum/deb.control b/builder/build/deb/ethereum/deb.control deleted file mode 100644 index 3b759f2d0..000000000 --- a/builder/build/deb/ethereum/deb.control +++ /dev/null @@ -1,25 +0,0 @@ -Source: {{.Name}} -Section: science -Priority: extra -Maintainer: {{.Author}} -Build-Depends: debhelper (>= 8.0.0), {{.GoBootPackage}} -Standards-Version: 3.9.5 -Homepage: https://ethereum.org -Vcs-Git: https://github.com/ethereum/go-ethereum.git -Vcs-Browser: https://github.com/ethereum/go-ethereum - -Package: {{.Name}} -Architecture: any -Depends: ${misc:Depends}, {{.ExeList}} -Description: Meta-package to install geth and other tools - Meta-package to install geth and other tools - -{{range .Executables}} -Package: {{$.ExeName .}} -Conflicts: {{$.ExeConflicts .}} -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Built-Using: ${misc:Built-Using} -Description: {{.Description}} - {{.Description}} -{{end}} diff --git a/builder/build/deb/ethereum/deb.copyright b/builder/build/deb/ethereum/deb.copyright deleted file mode 100644 index fe6e36ad9..000000000 --- a/builder/build/deb/ethereum/deb.copyright +++ /dev/null @@ -1,14 +0,0 @@ -Copyright 2018 The go-ethereum Authors - -go-ethereum 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. - -go-ethereum 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 go-ethereum. If not, see . diff --git a/builder/build/deb/ethereum/deb.docs b/builder/build/deb/ethereum/deb.docs deleted file mode 100644 index 62deb0497..000000000 --- a/builder/build/deb/ethereum/deb.docs +++ /dev/null @@ -1 +0,0 @@ -AUTHORS diff --git a/builder/build/deb/ethereum/deb.install b/builder/build/deb/ethereum/deb.install deleted file mode 100644 index 5a624594b..000000000 --- a/builder/build/deb/ethereum/deb.install +++ /dev/null @@ -1,5 +0,0 @@ -build/bin/{{.BinaryName}} usr/bin -{{- if eq .BinaryName "geth" }} -build/deb/ethereum/completions/bash/geth etc/bash_completion.d -build/deb/ethereum/completions/zsh/_geth usr/share/zsh/vendor-completions -{{end -}} diff --git a/builder/build/deb/ethereum/deb.rules b/builder/build/deb/ethereum/deb.rules deleted file mode 100644 index daca793e5..000000000 --- a/builder/build/deb/ethereum/deb.rules +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -# Launchpad rejects Go's access to $HOME, use custom folders -export GOCACHE=/tmp/go-build -export GOPATH=/tmp/gopath -export GOROOT_BOOTSTRAP={{.GoBootPath}} - -override_dh_auto_clean: - # Don't try to be smart Launchpad, we know our build rules better than you - -override_dh_auto_build: - # We can't download a fresh Go within Launchpad, so we're shipping and building - # one on the fly. However, we can't build it inside the go-ethereum folder as - # bootstrapping clashes with go modules, so build in a sibling folder. - # - # We're also shipping the bootstrapper as of Go 1.20 as it had minimum version - # requirements opposed to older versions of Go. - (mv .goboot ../ && cd ../.goboot/src && ./make.bash) - (mv .go ../ && cd ../.go/src && GOROOT_BOOTSTRAP=`pwd`/../../.goboot ./make.bash) - - # We can't download external go modules within Launchpad, so we're shipping the - # entire dependency source cache with go-ethereum. - mkdir -p $(GOPATH)/pkg - mv .mod $(GOPATH)/pkg/mod - - # A fresh Go was built, all dependency downloads faked, hope build works now - ../.go/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}} -ubuntu {{.Distro}} - -override_dh_auto_test: - -%: - dh $@ diff --git a/builder/build/goimports.sh b/builder/build/goimports.sh deleted file mode 100755 index 1fcace6a4..000000000 --- a/builder/build/goimports.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -find_files() { - find . ! \( \ - \( \ - -path '.github' \ - -o -path './build/_workspace' \ - -o -path './build/bin' \ - -o -path './crypto/bn256' \ - -o -path '*/vendor/*' \ - \) -prune \ - \) -name '*.go' -} - -GOFMT="gofmt -s -w" -GOIMPORTS="goimports -w" -find_files | xargs $GOFMT -find_files | xargs $GOIMPORTS diff --git a/builder/build/nsis.envvarupdate.nsh b/builder/build/nsis.envvarupdate.nsh deleted file mode 100644 index 95c2f1f63..000000000 --- a/builder/build/nsis.envvarupdate.nsh +++ /dev/null @@ -1,327 +0,0 @@ -/** - * EnvVarUpdate.nsh - * : Environmental Variables: append, prepend, and remove entries - * - * WARNING: If you use StrFunc.nsh header then include it before this file - * with all required definitions. This is to avoid conflicts - * - * Usage: - * ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" - * - * Credits: - * Version 1.0 - * * Cal Turney (turnec2) - * * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this - * function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, - * WriteEnvStr, and un.DeleteEnvStr - * * Diego Pedroso (deguix) for StrTok - * * Kevin English (kenglish_hi) for StrContains - * * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry - * (dandaman32) for StrReplace - * - * Version 1.1 (compatibility with StrFunc.nsh) - * * techtonik - * - * http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries - * - */ - - -!ifndef ENVVARUPDATE_FUNCTION -!define ENVVARUPDATE_FUNCTION -!verbose push -!verbose 3 -!include "LogicLib.nsh" -!include "WinMessages.NSH" -!include "StrFunc.nsh" - -; ---- Fix for conflict if StrFunc.nsh is already includes in main file ----------------------- -!macro _IncludeStrFunction StrFuncName - !ifndef ${StrFuncName}_INCLUDED - ${${StrFuncName}} - !endif - !ifndef Un${StrFuncName}_INCLUDED - ${Un${StrFuncName}} - !endif - !define un.${StrFuncName} '${Un${StrFuncName}}' -!macroend - -!insertmacro _IncludeStrFunction StrTok -!insertmacro _IncludeStrFunction StrStr -!insertmacro _IncludeStrFunction StrRep - -; ---------------------------------- Macro Definitions ---------------------------------------- -!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString - Push "${EnvVarName}" - Push "${Action}" - Push "${RegLoc}" - Push "${PathString}" - Call EnvVarUpdate - Pop "${ResultVar}" -!macroend -!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' - -!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString - Push "${EnvVarName}" - Push "${Action}" - Push "${RegLoc}" - Push "${PathString}" - Call un.EnvVarUpdate - Pop "${ResultVar}" -!macroend -!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' -; ---------------------------------- Macro Definitions end------------------------------------- - -;----------------------------------- EnvVarUpdate start---------------------------------------- -!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' -!define hkcu_current_user 'HKCU "Environment"' - -!macro EnvVarUpdate UN - -Function ${UN}EnvVarUpdate - - Push $0 - Exch 4 - Exch $1 - Exch 3 - Exch $2 - Exch 2 - Exch $3 - Exch - Exch $4 - Push $5 - Push $6 - Push $7 - Push $8 - Push $9 - Push $R0 - - /* After this point: - ------------------------- - $0 = ResultVar (returned) - $1 = EnvVarName (input) - $2 = Action (input) - $3 = RegLoc (input) - $4 = PathString (input) - $5 = Orig EnvVar (read from registry) - $6 = Len of $0 (temp) - $7 = tempstr1 (temp) - $8 = Entry counter (temp) - $9 = tempstr2 (temp) - $R0 = tempChar (temp) */ - - ; Step 1: Read contents of EnvVarName from RegLoc - ; - ; Check for empty EnvVarName - ${If} $1 == "" - SetErrors - DetailPrint "ERROR: EnvVarName is blank" - Goto EnvVarUpdate_Restore_Vars - ${EndIf} - - ; Check for valid Action - ${If} $2 != "A" - ${AndIf} $2 != "P" - ${AndIf} $2 != "R" - SetErrors - DetailPrint "ERROR: Invalid Action - must be A, P, or R" - Goto EnvVarUpdate_Restore_Vars - ${EndIf} - - ${If} $3 == HKLM - ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5 - ${ElseIf} $3 == HKCU - ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5 - ${Else} - SetErrors - DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"' - Goto EnvVarUpdate_Restore_Vars - ${EndIf} - - ; Check for empty PathString - ${If} $4 == "" - SetErrors - DetailPrint "ERROR: PathString is blank" - Goto EnvVarUpdate_Restore_Vars - ${EndIf} - - ; Make sure we've got some work to do - ${If} $5 == "" - ${AndIf} $2 == "R" - SetErrors - DetailPrint "$1 is empty - Nothing to remove" - Goto EnvVarUpdate_Restore_Vars - ${EndIf} - - ; Step 2: Scrub EnvVar - ; - StrCpy $0 $5 ; Copy the contents to $0 - ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or - ; after the last one are not removed here but instead in Step 3) - ${If} $0 != "" ; If EnvVar is not empty ... - ${Do} - ${${UN}StrStr} $7 $0 " ;" - ${If} $7 == "" - ${ExitDo} - ${EndIf} - ${${UN}StrRep} $0 $0 " ;" ";" ; Remove ';' - ${Loop} - ${Do} - ${${UN}StrStr} $7 $0 "; " - ${If} $7 == "" - ${ExitDo} - ${EndIf} - ${${UN}StrRep} $0 $0 "; " ";" ; Remove ';' - ${Loop} - ${Do} - ${${UN}StrStr} $7 $0 ";;" - ${If} $7 == "" - ${ExitDo} - ${EndIf} - ${${UN}StrRep} $0 $0 ";;" ";" - ${Loop} - - ; Remove a leading or trailing semicolon from EnvVar - StrCpy $7 $0 1 0 - ${If} $7 == ";" - StrCpy $0 $0 "" 1 ; Change ';' to '' - ${EndIf} - StrLen $6 $0 - IntOp $6 $6 - 1 - StrCpy $7 $0 1 $6 - ${If} $7 == ";" - StrCpy $0 $0 $6 ; Change ';' to '' - ${EndIf} - ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug - ${EndIf} - - /* Step 3. Remove all instances of the target path/string (even if "A" or "P") - $6 = bool flag (1 = found and removed PathString) - $7 = a string (e.g. path) delimited by semicolon(s) - $8 = entry counter starting at 0 - $9 = copy of $0 - $R0 = tempChar */ - - ${If} $5 != "" ; If EnvVar is not empty ... - StrCpy $9 $0 - StrCpy $0 "" - StrCpy $8 0 - StrCpy $6 0 - - ${Do} - ${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter - - ${If} $7 == "" ; If we've run out of entries, - ${ExitDo} ; were done - ${EndIf} ; - - ; Remove leading and trailing spaces from this entry (critical step for Action=Remove) - ${Do} - StrCpy $R0 $7 1 - ${If} $R0 != " " - ${ExitDo} - ${EndIf} - StrCpy $7 $7 "" 1 ; Remove leading space - ${Loop} - ${Do} - StrCpy $R0 $7 1 -1 - ${If} $R0 != " " - ${ExitDo} - ${EndIf} - StrCpy $7 $7 -1 ; Remove trailing space - ${Loop} - ${If} $7 == $4 ; If string matches, remove it by not appending it - StrCpy $6 1 ; Set 'found' flag - ${ElseIf} $7 != $4 ; If string does NOT match - ${AndIf} $0 == "" ; and the 1st string being added to $0, - StrCpy $0 $7 ; copy it to $0 without a prepended semicolon - ${ElseIf} $7 != $4 ; If string does NOT match - ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0, - StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon - ${EndIf} ; - - IntOp $8 $8 + 1 ; Bump counter - ${Loop} ; Check for duplicates until we run out of paths - ${EndIf} - - ; Step 4: Perform the requested Action - ; - ${If} $2 != "R" ; If Append or Prepend - ${If} $6 == 1 ; And if we found the target - DetailPrint "Target is already present in $1. It will be removed and" - ${EndIf} - ${If} $0 == "" ; If EnvVar is (now) empty - StrCpy $0 $4 ; just copy PathString to EnvVar - ${If} $6 == 0 ; If found flag is either 0 - ${OrIf} $6 == "" ; or blank (if EnvVarName is empty) - DetailPrint "$1 was empty and has been updated with the target" - ${EndIf} - ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty), - StrCpy $0 $0;$4 ; append PathString - ${If} $6 == 1 - DetailPrint "appended to $1" - ${Else} - DetailPrint "Target was appended to $1" - ${EndIf} - ${Else} ; If Prepend (and EnvVar is not empty), - StrCpy $0 $4;$0 ; prepend PathString - ${If} $6 == 1 - DetailPrint "prepended to $1" - ${Else} - DetailPrint "Target was prepended to $1" - ${EndIf} - ${EndIf} - ${Else} ; If Action = Remove - ${If} $6 == 1 ; and we found the target - DetailPrint "Target was found and removed from $1" - ${Else} - DetailPrint "Target was NOT found in $1 (nothing to remove)" - ${EndIf} - ${If} $0 == "" - DetailPrint "$1 is now empty" - ${EndIf} - ${EndIf} - - ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change - ; - ClearErrors - ${If} $3 == HKLM - WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section - ${ElseIf} $3 == HKCU - WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section - ${EndIf} - - IfErrors 0 +4 - MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3" - DetailPrint "Could not write updated $1 to $3" - Goto EnvVarUpdate_Restore_Vars - - ; "Export" our change - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - - EnvVarUpdate_Restore_Vars: - ; - ; Restore the user's variables and return ResultVar - Pop $R0 - Pop $9 - Pop $8 - Pop $7 - Pop $6 - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Push $0 ; Push my $0 (ResultVar) - Exch - Pop $0 ; Restore his $0 - -FunctionEnd - -!macroend ; EnvVarUpdate UN -!insertmacro EnvVarUpdate "" -!insertmacro EnvVarUpdate "un." -;----------------------------------- EnvVarUpdate end---------------------------------------- - -!verbose pop -!endif \ No newline at end of file diff --git a/builder/build/nsis.geth.nsi b/builder/build/nsis.geth.nsi deleted file mode 100644 index 03710dd95..000000000 --- a/builder/build/nsis.geth.nsi +++ /dev/null @@ -1,70 +0,0 @@ -# Builds a Windows installer with NSIS. -# It expects the following command line arguments: -# - OUTPUTFILE, filename of the installer (without extension) -# - MAJORVERSION, major build version -# - MINORVERSION, minor build version -# - BUILDVERSION, build id version -# -# The created installer executes the following steps: -# 1. install geth for all users -# 2. install optional development tools such as abigen -# 3. create an uninstaller -# 4. configures the Windows firewall for geth -# 5. create geth, attach and uninstall start menu entries -# 6. configures the registry that allows Windows to manage the package through its platform tools -# 7. adds the environment system wide variable ETHEREUM_SOCKET -# 8. adds the install directory to %PATH% -# -# Requirements: -# - NSIS, http://nsis.sourceforge.net/Main_Page -# - NSIS Large Strings build, http://nsis.sourceforge.net/Special_Builds -# - SFP, http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin (put dll in NSIS\Plugins\x86-ansi) -# -# After installing NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the -# files found in Stub. -# -# based on: http://nsis.sourceforge.net/A_simple_installer_with_start_menu_shortcut_and_uninstaller -# -# TODO: -# - sign installer -CRCCheck on - -!define GROUPNAME "Ethereum" -!define APPNAME "Geth" -!define DESCRIPTION "Official Go implementation of the Ethereum protocol" -!addplugindir .\ - -# Require admin rights on NT6+ (When UAC is turned on) -RequestExecutionLevel admin - -# Use LZMA compression -SetCompressor /SOLID lzma - -!include LogicLib.nsh -!include PathUpdate.nsh -!include EnvVarUpdate.nsh - -!macro VerifyUserIsAdmin -UserInfo::GetAccountType -pop $0 -${If} $0 != "admin" # Require admin rights on NT4+ - messageBox mb_iconstop "Administrator rights required!" - setErrorLevel 740 # ERROR_ELEVATION_REQUIRED - quit -${EndIf} -!macroend - -function .onInit - # make vars are global for all users since geth is installed global - setShellVarContext all - !insertmacro VerifyUserIsAdmin - - ${If} ${ARCH} == "amd64" - StrCpy $InstDir "$PROGRAMFILES64\${APPNAME}" - ${Else} - StrCpy $InstDir "$PROGRAMFILES32\${APPNAME}" - ${Endif} -functionEnd - -!include install.nsh -!include uninstall.nsh diff --git a/builder/build/nsis.install.nsh b/builder/build/nsis.install.nsh deleted file mode 100644 index 9b73148a4..000000000 --- a/builder/build/nsis.install.nsh +++ /dev/null @@ -1,103 +0,0 @@ -Name "geth ${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" # VERSION variables set through command line arguments -InstallDir "$InstDir" -OutFile "${OUTPUTFILE}" # set through command line arguments - -# Links for "Add/Remove Programs" -!define HELPURL "https://github.com/ethereum/go-ethereum/issues" -!define UPDATEURL "https://github.com/ethereum/go-ethereum/releases" -!define ABOUTURL "https://github.com/ethereum/go-ethereum#ethereum-go" -!define /date NOW "%Y%m%d" - -PageEx license - LicenseData {{.License}} -PageExEnd - -# Install geth binary -Section "Geth" GETH_IDX - SetOutPath $INSTDIR - file {{.Geth}} - - # Create start menu launcher - createDirectory "$SMPROGRAMS\${APPNAME}" - createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" - createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach" - createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" - - # Firewall - remove rules (if exists) - SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)" - SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)" - SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)" - - # Firewall - add rules - SimpleFC::AdvAddRule "Geth incoming peers (TCP:30303)" "" 6 1 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" 30303 "" "" "" - SimpleFC::AdvAddRule "Geth outgoing peers (TCP:30303)" "" 6 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" "" - SimpleFC::AdvAddRule "Geth UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" "" - - # Set default IPC endpoint (https://github.com/ethereum/EIPs/issues/147) - ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc" - ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\geth.ipc" - - # Add instdir to PATH - Push "$INSTDIR" - Call AddToPath -SectionEnd - -# Install optional develop tools. -Section /o "Development tools" DEV_TOOLS_IDX - SetOutPath $INSTDIR - {{range .DevTools}}file {{.}} - {{end}} -SectionEnd - -# Return on top of stack the total size (as DWORD) of the selected/installed sections. -Var GetInstalledSize.total -Function GetInstalledSize - StrCpy $GetInstalledSize.total 0 - - ${if} ${SectionIsSelected} ${GETH_IDX} - SectionGetSize ${GETH_IDX} $0 - IntOp $GetInstalledSize.total $GetInstalledSize.total + $0 - ${endif} - - ${if} ${SectionIsSelected} ${DEV_TOOLS_IDX} - SectionGetSize ${DEV_TOOLS_IDX} $0 - IntOp $GetInstalledSize.total $GetInstalledSize.total + $0 - ${endif} - - IntFmt $GetInstalledSize.total "0x%08X" $GetInstalledSize.total - Push $GetInstalledSize.total -FunctionEnd - -# Write registry, Windows uses these values in various tools such as add/remove program. -# PowerShell: Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, InstallLocation, InstallDate | Format-Table –AutoSize -function .onInstSuccess - # Save information in registry in HKEY_LOCAL_MACHINE branch, Windows add/remove functionality depends on this - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayName" "${GROUPNAME} - ${APPNAME} - ${DESCRIPTION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallLocation" "$INSTDIR" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallDate" "${NOW}" - # Wait for Alex - #WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "Publisher" "${GROUPNAME}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "HelpLink" "${HELPURL}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLUpdateInfo" "${UPDATEURL}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLInfoAbout" "${ABOUTURL}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayVersion" "${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMajor" ${MAJORVERSION} - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMinor" ${MINORVERSION} - # There is no option for modifying or repairing the install - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoModify" 1 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoRepair" 1 - - Call GetInstalledSize - Pop $0 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "EstimatedSize" "$0" - - # Create uninstaller - writeUninstaller "$INSTDIR\uninstall.exe" -functionEnd - -Page components -Page directory -Page instfiles diff --git a/builder/build/nsis.pathupdate.nsh b/builder/build/nsis.pathupdate.nsh deleted file mode 100644 index f54b7e3e1..000000000 --- a/builder/build/nsis.pathupdate.nsh +++ /dev/null @@ -1,153 +0,0 @@ -!include "WinMessages.nsh" - -; see https://support.microsoft.com/en-us/kb/104011 -!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' -; HKEY_LOCAL_MACHINE = 0x80000002 - -; AddToPath - Appends dir to PATH -; (does not work on Win9x/ME) -; -; Usage: -; Push "dir" -; Call AddToPath -Function AddToPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - - ; NSIS ReadRegStr returns empty string on string overflow - ; Native calls are used here to check actual length of PATH - ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3) - System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" - IntCmp $4 0 0 done done - - ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) - ; RegCloseKey($3) - System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" - System::Call "advapi32::RegCloseKey(i $3)" - - IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA - DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}" - MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" - Goto done - - IntCmp $4 0 +5 ; $4 != NO_ERROR - IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND - DetailPrint "AddToPath: unexpected error code $4" - Goto done - StrCpy $1 "" - - ; Check if already in PATH - Push "$1;" - Push "$0;" - Call StrStr - Pop $2 - StrCmp $2 "" 0 done - Push "$1;" - Push "$0\;" - Call StrStr - Pop $2 - StrCmp $2 "" 0 done - - ; Prevent NSIS string overflow - StrLen $2 $0 - StrLen $3 $1 - IntOp $2 $2 + $3 - IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";") - IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0 - DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}" - MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." - Goto done - - ; Append dir to PATH - DetailPrint "Add to PATH: $0" - StrCpy $2 $1 1 -1 - StrCmp $2 ";" 0 +2 - StrCpy $1 $1 -1 ; remove trailing ';' - StrCmp $1 "" +2 ; no leading ';' - StrCpy $0 "$1;$0" - - WriteRegExpandStr ${Environ} "PATH" $0 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - -done: - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - - -; RemoveFromPath - Removes dir from PATH -; -; Usage: -; Push "dir" -; Call RemoveFromPath -Function un.RemoveFromPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - Push $6 - - ; NSIS ReadRegStr returns empty string on string overflow - ; Native calls are used here to check actual length of PATH - ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3) - System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" - IntCmp $4 0 0 done done - - ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) - ; RegCloseKey($3) - System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" - System::Call "advapi32::RegCloseKey(i $3)" - - IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA - DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}" - MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" - Goto done - - IntCmp $4 0 +5 ; $4 != NO_ERROR - IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND - DetailPrint "RemoveFromPath: unexpected error code $4" - Goto done - StrCpy $1 "" - - ; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used - ReadRegStr $1 ${Environ} "PATH" - StrCpy $5 $1 1 -1 - StrCmp $5 ";" +2 - StrCpy $1 "$1;" ; ensure trailing ';' - Push $1 - Push "$0;" - Call un.StrStr - Pop $2 ; pos of our dir - StrCmp $2 "" done - - DetailPrint "Remove from PATH: $0" - StrLen $3 "$0;" - StrLen $4 $2 - StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove - StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove - StrCpy $3 "$5$6" - StrCpy $5 $3 1 -1 - StrCmp $5 ";" 0 +2 - StrCpy $3 $3 -1 ; remove trailing ';' - WriteRegExpandStr ${Environ} "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - -done: - Pop $6 - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - - diff --git a/builder/build/nsis.simplefc.dll b/builder/build/nsis.simplefc.dll deleted file mode 100644 index 73b7d9634..000000000 Binary files a/builder/build/nsis.simplefc.dll and /dev/null differ diff --git a/builder/build/nsis.simplefc.source.zip b/builder/build/nsis.simplefc.source.zip deleted file mode 100644 index d7476022a..000000000 Binary files a/builder/build/nsis.simplefc.source.zip and /dev/null differ diff --git a/builder/build/nsis.uninstall.nsh b/builder/build/nsis.uninstall.nsh deleted file mode 100644 index 6358faa74..000000000 --- a/builder/build/nsis.uninstall.nsh +++ /dev/null @@ -1,33 +0,0 @@ -Section "Uninstall" - # uninstall for all users - setShellVarContext all - - # Delete (optionally) installed files - {{range $}}Delete $INSTDIR\{{.}} - {{end}} - Delete $INSTDIR\uninstall.exe - - # Delete install directory - rmDir $INSTDIR - - # Delete start menu launcher - Delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" - Delete "$SMPROGRAMS\${APPNAME}\Attach.lnk" - Delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" - rmDir "$SMPROGRAMS\${APPNAME}" - - # Firewall - remove rules if exists - SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)" - SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)" - SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)" - - # Remove IPC endpoint (https://github.com/ethereum/EIPs/issues/147) - ${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc" - - # Remove install directory from PATH - Push "$INSTDIR" - Call un.RemoveFromPath - - # Cleanup registry (deletes all sub keys) - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" -SectionEnd diff --git a/builder/build/tools/tools.go b/builder/build/tools/tools.go deleted file mode 100644 index 506e26eef..000000000 --- a/builder/build/tools/tools.go +++ /dev/null @@ -1,27 +0,0 @@ -// 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 . - -//go:build tools -// +build tools - -package tools - -import ( - // Tool imports for go:generate. - _ "github.com/fjl/gencodec" - _ "github.com/golang/protobuf/protoc-gen-go" - _ "golang.org/x/tools/cmd/stringer" -) diff --git a/builder/build/travis_keepalive.sh b/builder/build/travis_keepalive.sh deleted file mode 100755 index 77cc623ea..000000000 --- a/builder/build/travis_keepalive.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash - -# travis_keepalive runs the given command and preserves its return value, -# while it forks a child process what periodically produces a log line, -# so that Travis won't abort the build after 10 minutes. - -# Why? -# `t.Log()` in Go holds the buffer until the test does not pass or fail, -# and `-race` can increase the execution time by 2-20x. - -set -euo pipefail - -readonly KEEPALIVE_INTERVAL=300 # seconds => 5m - -main() { - keepalive - $@ -} - -# Keepalive produces a log line in each KEEPALIVE_INTERVAL. -keepalive() { - local child_pid - # Note: We fork here! - repeat "keepalive" & - child_pid=$! - ensureChildOnEXIT "${child_pid}" -} - -repeat() { - local this="$1" - while true; do - echo "${this}" - sleep "${KEEPALIVE_INTERVAL}" - done -} - -# Ensures that the child gets killed on normal program exit. -ensureChildOnEXIT() { - # Note: SIGINT and SIGTERM are forwarded to the child process by Bash - # automatically, so we don't have to deal with signals. - - local child_pid="$1" - trap "kill ${child_pid}" EXIT -} - -main "$@" diff --git a/builder/build/update-license.go b/builder/build/update-license.go deleted file mode 100644 index 70e2de06c..000000000 --- a/builder/build/update-license.go +++ /dev/null @@ -1,427 +0,0 @@ -// Copyright 2018 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 . - -//go:build none -// +build none - -/* -This command generates GPL license headers on top of all source files. -You can run it once per month, before cutting a release or just -whenever you feel like it. - - go run update-license.go - -All authors (people who have contributed code) are listed in the -AUTHORS file. The author names are mapped and deduplicated using the -.mailmap file. You can use .mailmap to set the canonical name and -address for each author. See git-shortlog(1) for an explanation of the -.mailmap format. - -Please review the resulting diff to check whether the correct -copyright assignments are performed. -*/ - -package main - -import ( - "bufio" - "bytes" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "text/template" - "time" - - "golang.org/x/exp/slices" -) - -var ( - // only files with these extensions will be considered - extensions = []string{".go", ".js", ".qml"} - - // paths with any of these prefixes will be skipped - skipPrefixes = []string{ - // boring stuff - "vendor/", "tests/testdata/", "build/", - - // don't relicense vendored sources - "common/bitutil/bitutil", - "common/prque/", - "crypto/blake2b/", - "crypto/bn256/", - "crypto/bls12381/", - "crypto/ecies/", - "graphql/graphiql.go", - "internal/jsre/deps", - "log/", - "metrics/", - "signer/rules/deps", - "internal/reexec", - - // skip special licenses - "crypto/secp256k1", // Relicensed to BSD-3 via https://github.com/ethereum/go-ethereum/pull/17225 - } - - // paths with this prefix are licensed as GPL. all other files are LGPL. - gplPrefixes = []string{"cmd/"} - - // this regexp must match the entire license comment at the - // beginning of each file. - licenseCommentRE = regexp.MustCompile(`^//\s*(Copyright|This file is part of).*?\n(?://.*?\n)*\n*`) - - // this text appears at the start of AUTHORS - authorsFileHeader = "# This is the official list of go-ethereum authors for copyright purposes.\n\n" -) - -// this template generates the license comment. -// its input is an info structure. -var licenseT = template.Must(template.New("").Parse(` -// Copyright {{.Year}} The go-ethereum Authors -// This file is part of {{.Whole false}}. -// -// {{.Whole true}} is free software: you can redistribute it and/or modify -// it under the terms of the GNU {{.License}} as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// {{.Whole true}} 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 {{.License}} for more details. -// -// You should have received a copy of the GNU {{.License}} -// along with {{.Whole false}}. If not, see . - -`[1:])) - -type info struct { - file string - Year int64 -} - -func (i info) License() string { - if i.gpl() { - return "General Public License" - } - return "Lesser General Public License" -} - -func (i info) ShortLicense() string { - if i.gpl() { - return "GPL" - } - return "LGPL" -} - -func (i info) Whole(startOfSentence bool) string { - if i.gpl() { - return "go-ethereum" - } - if startOfSentence { - return "The go-ethereum library" - } - return "the go-ethereum library" -} - -func (i info) gpl() bool { - for _, p := range gplPrefixes { - if strings.HasPrefix(i.file, p) { - return true - } - } - return false -} - -func main() { - var ( - files = getFiles() - filec = make(chan string) - infoc = make(chan *info, 20) - wg sync.WaitGroup - ) - - writeAuthors(files) - - go func() { - for _, f := range files { - filec <- f - } - close(filec) - }() - for i := runtime.NumCPU(); i >= 0; i-- { - // getting file info is slow and needs to be parallel. - // it traverses git history for each file. - wg.Add(1) - go getInfo(filec, infoc, &wg) - } - go func() { - wg.Wait() - close(infoc) - }() - writeLicenses(infoc) -} - -func skipFile(path string) bool { - if strings.Contains(path, "/testdata/") { - return true - } - for _, p := range skipPrefixes { - if strings.HasPrefix(path, p) { - return true - } - } - return false -} - -func getFiles() []string { - cmd := exec.Command("git", "ls-tree", "-r", "--name-only", "HEAD") - var files []string - err := doLines(cmd, func(line string) { - if skipFile(line) { - return - } - ext := filepath.Ext(line) - for _, wantExt := range extensions { - if ext == wantExt { - goto keep - } - } - return - keep: - files = append(files, line) - }) - if err != nil { - log.Fatal("error getting files:", err) - } - return files -} - -var authorRegexp = regexp.MustCompile(`\s*[0-9]+\s*(.*)`) - -func gitAuthors(files []string) []string { - cmds := []string{"shortlog", "-s", "-n", "-e", "HEAD", "--"} - cmds = append(cmds, files...) - cmd := exec.Command("git", cmds...) - var authors []string - err := doLines(cmd, func(line string) { - m := authorRegexp.FindStringSubmatch(line) - if len(m) > 1 { - authors = append(authors, m[1]) - } - }) - if err != nil { - log.Fatalln("error getting authors:", err) - } - return authors -} - -func readAuthors() []string { - content, err := os.ReadFile("AUTHORS") - if err != nil && !os.IsNotExist(err) { - log.Fatalln("error reading AUTHORS:", err) - } - var authors []string - for _, a := range bytes.Split(content, []byte("\n")) { - if len(a) > 0 && a[0] != '#' { - authors = append(authors, string(a)) - } - } - // Retranslate existing authors through .mailmap. - // This should catch email address changes. - authors = mailmapLookup(authors) - return authors -} - -func mailmapLookup(authors []string) []string { - if len(authors) == 0 { - return nil - } - cmds := []string{"check-mailmap", "--"} - cmds = append(cmds, authors...) - cmd := exec.Command("git", cmds...) - var translated []string - err := doLines(cmd, func(line string) { - translated = append(translated, line) - }) - if err != nil { - log.Fatalln("error translating authors:", err) - } - return translated -} - -func writeAuthors(files []string) { - var ( - dedup = make(map[string]bool) - list []string - ) - // Add authors that Git reports as contributors. - // This is the primary source of author information. - for _, a := range gitAuthors(files) { - if la := strings.ToLower(a); !dedup[la] { - list = append(list, a) - dedup[la] = true - } - } - // Add existing authors from the file. This should ensure that we - // never lose authors, even if Git stops listing them. We can also - // add authors manually this way. - for _, a := range readAuthors() { - if la := strings.ToLower(a); !dedup[la] { - list = append(list, a) - dedup[la] = true - } - } - // Write sorted list of authors back to the file. - slices.SortFunc(list, func(a, b string) bool { - return strings.ToLower(a) < strings.ToLower(b) - }) - content := new(bytes.Buffer) - content.WriteString(authorsFileHeader) - for _, a := range list { - content.WriteString(a) - content.WriteString("\n") - } - fmt.Println("writing AUTHORS") - if err := os.WriteFile("AUTHORS", content.Bytes(), 0644); err != nil { - log.Fatalln(err) - } -} - -func getInfo(files <-chan string, out chan<- *info, wg *sync.WaitGroup) { - for file := range files { - stat, err := os.Lstat(file) - if err != nil { - fmt.Printf("ERROR %s: %v\n", file, err) - continue - } - if !stat.Mode().IsRegular() { - continue - } - if isGenerated(file) { - continue - } - info, err := fileInfo(file) - if err != nil { - fmt.Printf("ERROR %s: %v\n", file, err) - continue - } - out <- info - } - wg.Done() -} - -func isGenerated(file string) bool { - fd, err := os.Open(file) - if err != nil { - return false - } - defer fd.Close() - buf := make([]byte, 2048) - n, err := fd.Read(buf) - if err != nil { - return false - } - buf = buf[:n] - for _, l := range bytes.Split(buf, []byte("\n")) { - if bytes.HasPrefix(l, []byte("// Code generated")) { - return true - } - } - return false -} - -// fileInfo finds the lowest year in which the given file was committed. -func fileInfo(file string) (*info, error) { - info := &info{file: file, Year: int64(time.Now().Year())} - cmd := exec.Command("git", "log", "--follow", "--find-renames=80", "--find-copies=80", "--pretty=format:%ai", "--", file) - err := doLines(cmd, func(line string) { - y, err := strconv.ParseInt(line[:4], 10, 64) - if err != nil { - fmt.Printf("cannot parse year: %q", line[:4]) - } - if y < info.Year { - info.Year = y - } - }) - return info, err -} - -func writeLicenses(infos <-chan *info) { - for i := range infos { - writeLicense(i) - } -} - -func writeLicense(info *info) { - fi, err := os.Stat(info.file) - if os.IsNotExist(err) { - fmt.Println("skipping (does not exist)", info.file) - return - } - if err != nil { - log.Fatalf("error stat'ing %s: %v\n", info.file, err) - } - content, err := os.ReadFile(info.file) - if err != nil { - log.Fatalf("error reading %s: %v\n", info.file, err) - } - // Construct new file content. - buf := new(bytes.Buffer) - licenseT.Execute(buf, info) - if m := licenseCommentRE.FindIndex(content); m != nil && m[0] == 0 { - buf.Write(content[:m[0]]) - buf.Write(content[m[1]:]) - } else { - buf.Write(content) - } - // Write it to the file. - if bytes.Equal(content, buf.Bytes()) { - fmt.Println("skipping (no changes)", info.file) - return - } - fmt.Println("writing", info.ShortLicense(), info.file) - if err := os.WriteFile(info.file, buf.Bytes(), fi.Mode()); err != nil { - log.Fatalf("error writing %s: %v", info.file, err) - } -} - -func doLines(cmd *exec.Cmd, f func(string)) error { - stdout, err := cmd.StdoutPipe() - if err != nil { - return err - } - if err := cmd.Start(); err != nil { - return err - } - s := bufio.NewScanner(stdout) - for s.Scan() { - f(s.Text()) - } - if s.Err() != nil { - return s.Err() - } - if err := cmd.Wait(); err != nil { - return fmt.Errorf("%v (for %s)", err, strings.Join(cmd.Args, " ")) - } - return nil -} diff --git a/builder/builder/beacon_client.go b/builder/builder/beacon_client.go deleted file mode 100644 index 1b6cc7b41..000000000 --- a/builder/builder/beacon_client.go +++ /dev/null @@ -1,423 +0,0 @@ -package builder - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "strconv" - "sync" - "time" - - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/r3labs/sse" -) - -type IBeaconClient interface { - isValidator(pubkey PubkeyHex) bool - getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) - SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) - Start() error - Stop() -} - -type testBeaconClient struct { - validator *ValidatorPrivateData - slot uint64 -} - -func (b *testBeaconClient) Stop() {} - -func (b *testBeaconClient) isValidator(pubkey PubkeyHex) bool { - return true -} - -func (b *testBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { - return PubkeyHex(hexutil.Encode(b.validator.Pk)), nil -} - -func (b *testBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { -} - -func (b *testBeaconClient) Start() error { return nil } - -type NilBeaconClient struct{} - -func (b *NilBeaconClient) isValidator(pubkey PubkeyHex) bool { - return false -} - -func (b *NilBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { - return PubkeyHex(""), nil -} - -func (b *NilBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { -} - -func (b *NilBeaconClient) Start() error { return nil } - -func (b *NilBeaconClient) Stop() {} - -type MultiBeaconClient struct { - clients []*BeaconClient - closeCh chan struct{} -} - -func NewMultiBeaconClient(endpoints []string, slotsInEpoch, secondsInSlot uint64) *MultiBeaconClient { - clients := []*BeaconClient{} - for _, endpoint := range endpoints { - client := NewBeaconClient(endpoint, slotsInEpoch, secondsInSlot) - clients = append(clients, client) - } - - return &MultiBeaconClient{ - clients: clients, - closeCh: make(chan struct{}), - } -} - -func (m *MultiBeaconClient) isValidator(pubkey PubkeyHex) bool { - for _, c := range m.clients { - // Pick the first one, always true - return c.isValidator(pubkey) - } - - return false -} - -func (m *MultiBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { - var allErrs error - for _, c := range m.clients { - pk, err := c.getProposerForNextSlot(requestedSlot) - if err != nil { - allErrs = errors.Join(allErrs, err) - continue - } - - return pk, nil - } - return PubkeyHex(""), allErrs -} - -func (m *MultiBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { - for _, c := range m.clients { - go c.SubscribeToPayloadAttributesEvents(payloadAttrC) - } -} - -func (m *MultiBeaconClient) Start() error { - var allErrs error - for _, c := range m.clients { - err := c.Start() - if err != nil { - allErrs = errors.Join(allErrs, err) - } - } - return allErrs -} - -func (m *MultiBeaconClient) Stop() { - for _, c := range m.clients { - c.Stop() - } - - close(m.closeCh) -} - -type BeaconClient struct { - endpoint string - slotsInEpoch uint64 - secondsInSlot uint64 - - mu sync.Mutex - slotProposerMap map[uint64]PubkeyHex - - ctx context.Context - cancelFn context.CancelFunc -} - -func NewBeaconClient(endpoint string, slotsInEpoch, secondsInSlot uint64) *BeaconClient { - ctx, cancelFn := context.WithCancel(context.Background()) - return &BeaconClient{ - endpoint: endpoint, - slotsInEpoch: slotsInEpoch, - secondsInSlot: secondsInSlot, - slotProposerMap: make(map[uint64]PubkeyHex), - ctx: ctx, - cancelFn: cancelFn, - } -} - -func (b *BeaconClient) Stop() { - b.cancelFn() -} - -func (b *BeaconClient) isValidator(pubkey PubkeyHex) bool { - return true -} - -func (b *BeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { - b.mu.Lock() - defer b.mu.Unlock() - - nextSlotProposer, found := b.slotProposerMap[requestedSlot] - if !found { - log.Error("inconsistent proposer mapping", "requestSlot", requestedSlot, "slotProposerMap", b.slotProposerMap) - return PubkeyHex(""), errors.New("inconsistent proposer mapping") - } - return nextSlotProposer, nil -} - -func (b *BeaconClient) Start() error { - go b.UpdateValidatorMapForever() - return nil -} - -func (b *BeaconClient) UpdateValidatorMapForever() { - durationPerSlot := time.Duration(b.secondsInSlot) * time.Second - - prevFetchSlot := uint64(0) - - // fetch current epoch if beacon is online - currentSlot, err := fetchCurrentSlot(b.endpoint) - if err != nil { - log.Error("could not get current slot", "err", err) - } else { - currentEpoch := currentSlot / b.slotsInEpoch - slotProposerMap, err := fetchEpochProposersMap(b.endpoint, currentEpoch) - if err != nil { - log.Error("could not fetch validators map", "epoch", currentEpoch, "err", err) - } else { - b.mu.Lock() - b.slotProposerMap = slotProposerMap - b.mu.Unlock() - } - } - - retryDelay := time.Second - - // Every half epoch request validators map, polling for the slot - // more frequently to avoid missing updates on errors - timer := time.NewTimer(retryDelay) - defer timer.Stop() - for { - select { - case <-b.ctx.Done(): - return - case <-timer.C: - } - - currentSlot, err := fetchCurrentSlot(b.endpoint) - if err != nil { - log.Error("could not get current slot", "err", err) - timer.Reset(retryDelay) - continue - } - - // TODO: should poll after consistent slot within the epoch (slot % slotsInEpoch/2 == 0) - nextFetchSlot := prevFetchSlot + b.slotsInEpoch/2 - if currentSlot < nextFetchSlot { - timer.Reset(time.Duration(nextFetchSlot-currentSlot) * durationPerSlot) - continue - } - - currentEpoch := currentSlot / b.slotsInEpoch - slotProposerMap, err := fetchEpochProposersMap(b.endpoint, currentEpoch+1) - if err != nil { - log.Error("could not fetch validators map", "epoch", currentEpoch+1, "err", err) - timer.Reset(retryDelay) - continue - } - - prevFetchSlot = currentSlot - b.mu.Lock() - // remove previous epoch slots - for k := range b.slotProposerMap { - if k < currentEpoch*b.slotsInEpoch { - delete(b.slotProposerMap, k) - } - } - // update the slot proposer map for next epoch - for k, v := range slotProposerMap { - b.slotProposerMap[k] = v - } - b.mu.Unlock() - - timer.Reset(time.Duration(nextFetchSlot-currentSlot) * durationPerSlot) - } -} - -// PayloadAttributesEvent represents the data of a payload_attributes event -// {"version": "capella", "data": {"proposer_index": "123", "proposal_slot": "10", "parent_block_number": "9", "parent_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "parent_block_hash": "0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "payload_attributes": {"timestamp": "123456", "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "suggested_fee_recipient": "0x0000000000000000000000000000000000000000", "withdrawals": [{"index": "5", "validator_index": "10", "address": "0x0000000000000000000000000000000000000000", "amount": "15640"}]}}} -type PayloadAttributesEvent struct { - Version string `json:"version"` - Data PayloadAttributesEventData `json:"data"` -} - -type PayloadAttributesEventData struct { - ProposalSlot uint64 `json:"proposal_slot,string"` - ParentBlockHash common.Hash `json:"parent_block_hash"` - PayloadAttributes PayloadAttributes `json:"payload_attributes"` -} - -type PayloadAttributes struct { - Timestamp uint64 `json:"timestamp,string"` - PrevRandao common.Hash `json:"prev_randao"` - SuggestedFeeRecipient common.Address `json:"suggested_fee_recipient"` - Withdrawals []*capella.Withdrawal `json:"withdrawals"` - ParentBeaconBlockRoot *common.Hash `json:"parent_beacon_block_root"` -} - -// SubscribeToPayloadAttributesEvents subscribes to payload attributes events to validate fields such as prevrandao and withdrawals -func (b *BeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { - payloadAttributesResp := new(PayloadAttributesEvent) - - eventsURL := fmt.Sprintf("%s/eth/v1/events?topics=payload_attributes", b.endpoint) - log.Info("subscribing to payload_attributes events") - - for { - client := sse.NewClient(eventsURL) - err := client.SubscribeRawWithContext(b.ctx, func(msg *sse.Event) { - err := json.Unmarshal(msg.Data, payloadAttributesResp) - if err != nil { - log.Error("could not unmarshal payload_attributes event", "err", err) - } else { - // convert capella.Withdrawal to types.Withdrawal - var withdrawals []*types.Withdrawal - for _, w := range payloadAttributesResp.Data.PayloadAttributes.Withdrawals { - withdrawals = append(withdrawals, &types.Withdrawal{ - Index: uint64(w.Index), - Validator: uint64(w.ValidatorIndex), - Address: common.Address(w.Address), - Amount: uint64(w.Amount), - }) - } - - data := types.BuilderPayloadAttributes{ - Slot: payloadAttributesResp.Data.ProposalSlot, - HeadHash: payloadAttributesResp.Data.ParentBlockHash, - Timestamp: hexutil.Uint64(payloadAttributesResp.Data.PayloadAttributes.Timestamp), - Random: payloadAttributesResp.Data.PayloadAttributes.PrevRandao, - SuggestedFeeRecipient: payloadAttributesResp.Data.PayloadAttributes.SuggestedFeeRecipient, - Withdrawals: withdrawals, - ParentBeaconBlockRoot: payloadAttributesResp.Data.PayloadAttributes.ParentBeaconBlockRoot, - } - payloadAttrC <- data - } - }) - if err != nil { - log.Error("failed to subscribe to payload_attributes events", "err", err) - time.Sleep(1 * time.Second) - } - log.Warn("beaconclient SubscribeRaw ended, reconnecting") - } -} - -func fetchCurrentSlot(endpoint string) (uint64, error) { - headerRes := &struct { - Data []struct { - Root common.Hash `json:"root"` - Canonical bool `json:"canonical"` - Header struct { - Message struct { - Slot string `json:"slot"` - ProposerIndex string `json:"proposer_index"` - ParentRoot common.Hash `json:"parent_root"` - StateRoot common.Hash `json:"state_root"` - BodyRoot common.Hash `json:"body_root"` - } `json:"message"` - Signature hexutil.Bytes `json:"signature"` - } `json:"header"` - } `json:"data"` - }{} - - err := fetchBeacon(endpoint+"/eth/v1/beacon/headers", headerRes) - if err != nil { - return uint64(0), err - } - - if len(headerRes.Data) != 1 { - return uint64(0), errors.New("invalid response") - } - - slot, err := strconv.Atoi(headerRes.Data[0].Header.Message.Slot) - if err != nil { - log.Error("could not parse slot", "Slot", headerRes.Data[0].Header.Message.Slot, "err", err) - return uint64(0), errors.New("invalid response") - } - return uint64(slot), nil -} - -func fetchEpochProposersMap(endpoint string, epoch uint64) (map[uint64]PubkeyHex, error) { - proposerDutiesResponse := &struct { - Data []struct { - PubkeyHex string `json:"pubkey"` - Slot string `json:"slot"` - } `json:"data"` - }{} - - err := fetchBeacon(fmt.Sprintf("%s/eth/v1/validator/duties/proposer/%d", endpoint, epoch), proposerDutiesResponse) - if err != nil { - return nil, err - } - - proposersMap := make(map[uint64]PubkeyHex) - for _, proposerDuty := range proposerDutiesResponse.Data { - slot, err := strconv.Atoi(proposerDuty.Slot) - if err != nil { - log.Error("could not parse slot", "Slot", proposerDuty.Slot, "err", err) - continue - } - proposersMap[uint64(slot)] = PubkeyHex(proposerDuty.PubkeyHex) - } - return proposersMap, nil -} - -func fetchBeacon(url string, dst any) error { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - log.Error("invalid request", "url", url, "err", err) - return err - } - req.Header.Set("accept", "application/json") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - log.Error("client refused", "url", url, "err", err) - return err - } - defer resp.Body.Close() - - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - log.Error("could not read response body", "url", url, "err", err) - return err - } - - if resp.StatusCode >= 300 { - ec := &struct { - Code int `json:"code"` - Message string `json:"message"` - }{} - if err = json.Unmarshal(bodyBytes, ec); err != nil { - log.Error("Couldn't unmarshal error from beacon node", "url", url, "body", string(bodyBytes)) - return errors.New("could not unmarshal error response from beacon node") - } - return errors.New(ec.Message) - } - - err = json.Unmarshal(bodyBytes, dst) - if err != nil { - log.Error("could not unmarshal response", "url", url, "resp", string(bodyBytes), "dst", dst, "err", err) - return err - } - - log.Info("fetched", "url", url, "res", dst) - return nil -} diff --git a/builder/builder/beacon_client_test.go b/builder/builder/beacon_client_test.go deleted file mode 100644 index 6073488c3..000000000 --- a/builder/builder/beacon_client_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package builder - -import ( - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/gorilla/mux" - "github.com/stretchr/testify/require" -) - -type mockBeaconNode struct { - srv *httptest.Server - - proposerDuties map[int][]byte - forkResp map[int][]byte - headersCode int - headersResp []byte -} - -func newMockBeaconNode() *mockBeaconNode { - r := mux.NewRouter() - srv := httptest.NewServer(r) - - mbn := &mockBeaconNode{ - srv: srv, - - proposerDuties: make(map[int][]byte), - forkResp: make(map[int][]byte), - headersCode: 200, - headersResp: []byte{}, - } - - r.HandleFunc("/eth/v1/validator/duties/proposer/{epoch}", func(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - epochStr, ok := vars["epoch"] - if !ok { - http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) - return - } - epoch, err := strconv.Atoi(epochStr) - if err != nil { - http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) - return - } - - resp, found := mbn.proposerDuties[epoch] - if !found { - http.Error(w, `{ "code": 400, "message": "Invalid epoch" }`, 400) - return - } - - w.Header().Set("Content-Type", "application/json") - w.Write(resp) - }) - - r.HandleFunc("/eth/v1/beacon/headers", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(mbn.headersCode) - w.Write(mbn.headersResp) - }) - - return mbn -} - -func TestFetchBeacon(t *testing.T) { - mbn := newMockBeaconNode() - defer mbn.srv.Close() - - mbn.headersCode = 200 - mbn.headersResp = []byte(`{ "data": [ { "header": { "message": { "slot": "10", "proposer_index": "1" } } } ] }`) - - // Green path - headersResp := struct { - Data []struct { - Header struct { - Message struct { - Slot string `json:"slot"` - } `json:"message"` - } `json:"header"` - } `json:"data"` - }{} - err := fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &headersResp) - require.NoError(t, err) - require.Equal(t, "10", headersResp.Data[0].Header.Message.Slot) - - // Wrong dst - wrongForkResp := struct { - Data []struct { - Slot string `json:"slot"` - } - }{} - err = fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &wrongForkResp) - require.NoError(t, err) - require.Equal(t, wrongForkResp.Data[0].Slot, "") - - mbn.headersCode = 400 - mbn.headersResp = []byte(`{ "code": 400, "message": "Invalid call" }`) - err = fetchBeacon(mbn.srv.URL+"/eth/v1/beacon/headers", &headersResp) - require.EqualError(t, err, "Invalid call") -} - -func TestFetchCurrentSlot(t *testing.T) { - mbn := newMockBeaconNode() - defer mbn.srv.Close() - - mbn.headersResp = []byte(`{ - "execution_optimistic": false, - "data": [ - { - "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "canonical": true, - "header": { - "message": { - "slot": "101", - "proposer_index": "1", - "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" - }, - "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" - } - } - ] -}`) - - slot, err := fetchCurrentSlot(mbn.srv.URL) - require.NoError(t, err) - require.Equal(t, uint64(101), slot) - - mbn.headersResp = []byte(`{ - "execution_optimistic": false, - "data": [ - { - "header": { - "message": { - "slot": "xxx" - } - } - } - ] -}`) - - slot, err = fetchCurrentSlot(mbn.srv.URL) - require.EqualError(t, err, "invalid response") - require.Equal(t, uint64(0), slot) -} - -func TestFetchEpochProposersMap(t *testing.T) { - mbn := newMockBeaconNode() - defer mbn.srv.Close() - - mbn.proposerDuties[10] = []byte(`{ - "dependent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "execution_optimistic": false, - "data": [ - { - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", - "validator_index": "1", - "slot": "1" - }, - { - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b", - "validator_index": "2", - "slot": "2" - } - ] -}`) - - proposersMap, err := fetchEpochProposersMap(mbn.srv.URL, 10) - require.NoError(t, err) - require.Equal(t, 2, len(proposersMap)) - require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"), proposersMap[1]) - require.Equal(t, PubkeyHex("0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74b"), proposersMap[2]) -} diff --git a/builder/builder/builder.go b/builder/builder/builder.go deleted file mode 100644 index d347e01d4..000000000 --- a/builder/builder/builder.go +++ /dev/null @@ -1,893 +0,0 @@ -package builder - -import ( - "bufio" - "compress/gzip" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - "net/http" - _ "os" - "strings" - "sync" - "time" - - builderApi "github.com/attestantio/go-builder-client/api" - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderApiCapella "github.com/attestantio/go-builder-client/api/capella" - builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - builderSpec "github.com/attestantio/go-builder-client/spec" - "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/chainbound/shardmap" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - blockvalidation "github.com/ethereum/go-ethereum/eth/block-validation" - "github.com/ethereum/go-ethereum/flashbotsextra" - "github.com/ethereum/go-ethereum/log" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - boostTypes "github.com/flashbots/go-boost-utils/types" - "github.com/flashbots/go-boost-utils/utils" - "github.com/holiman/uint256" - "golang.org/x/time/rate" - - "github.com/cenkalti/backoff/v4" -) - -const ( - RateLimitIntervalDefault = 500 * time.Millisecond - RateLimitBurstDefault = 10 - BlockResubmitIntervalDefault = 500 * time.Millisecond - - SubmissionOffsetFromEndOfSlotSecondsDefault = 3 * time.Second -) - -const ( - SubscribeConstraintsPath = "/relay/v1/builder/constraints" -) - -type PubkeyHex string - -type ValidatorData struct { - Pubkey PubkeyHex - FeeRecipient bellatrix.ExecutionAddress - GasLimit uint64 -} - -type IRelay interface { - SubmitBlock(msg *builderSpec.VersionedSubmitBlockRequest, vd ValidatorData) error - SubmitBlockWithProofs(msg *common.VersionedSubmitBlockRequestWithProofs, vd ValidatorData) error - GetValidatorForSlot(nextSlot uint64) (ValidatorData, error) - Config() RelayConfig - Start() error - Stop() -} - -type IBuilder interface { - OnPayloadAttribute(attrs *types.BuilderPayloadAttributes) error - Start() error - Stop() error -} - -type Builder struct { - ds flashbotsextra.IDatabaseService - blockConsumer flashbotsextra.BlockConsumer - relay IRelay - eth IEthereumService - dryRun bool - ignoreLatePayloadAttributes bool - validator *blockvalidation.BlockValidationAPI - beaconClient IBeaconClient - builderSecretKey *bls.SecretKey - builderPublicKey phase0.BLSPubKey - builderSigningDomain phase0.Domain - builderResubmitInterval time.Duration - discardRevertibleTxOnErr bool - - // constraintsCache is a map from slot to the decoded constraints made by proposers - constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded] - - limiter *rate.Limiter - submissionOffsetFromEndOfSlot time.Duration - - slotMu sync.Mutex - slotAttrs types.BuilderPayloadAttributes - slotCtx context.Context - slotCtxCancel context.CancelFunc - - stop chan struct{} -} - -// BuilderArgs is a struct that contains all the arguments needed to create a new Builder -type BuilderArgs struct { - boltCCEndpoint string - sk *bls.SecretKey - ds flashbotsextra.IDatabaseService - blockConsumer flashbotsextra.BlockConsumer - relay IRelay - builderSigningDomain phase0.Domain - builderBlockResubmitInterval time.Duration - discardRevertibleTxOnErr bool - eth IEthereumService - dryRun bool - ignoreLatePayloadAttributes bool - validator *blockvalidation.BlockValidationAPI - beaconClient IBeaconClient - submissionOffsetFromEndOfSlot time.Duration - - limiter *rate.Limiter -} - -// SubmitBlockOpts is a struct that contains all the arguments needed to submit a block to the relay -type SubmitBlockOpts struct { - // Block is the block to submit - Block *types.Block - // BlockValue is the block value - BlockValue *big.Int - // BlobSidecars are the blob sidecars - BlobSidecars []*types.BlobTxSidecar - // OrdersClosedAt is the time at which orders were closed - OrdersClosedAt time.Time - // SealedAt is the time at which the block was sealed - SealedAt time.Time - // CommitedBundles are the bundles that were committed - CommitedBundles []types.SimulatedBundle - // AllBundles are all the bundles that were simulated - AllBundles []types.SimulatedBundle - // UsedSbundles are the share bundles that were used - UsedSbundles []types.UsedSBundle - // ProposerPubkey is the proposer's pubkey - ProposerPubkey phase0.BLSPubKey - // ValidatorData is the information about the validator - ValidatorData ValidatorData - // PayloadAttributes are the payload attributes used for block building - PayloadAttributes *types.BuilderPayloadAttributes -} - -func NewBuilder(args BuilderArgs) (*Builder, error) { - blsPk, err := bls.PublicKeyFromSecretKey(args.sk) - if err != nil { - return nil, err - } - pk, err := utils.BlsPublicKeyToPublicKey(blsPk) - if err != nil { - return nil, err - } - - if args.limiter == nil { - args.limiter = rate.NewLimiter(rate.Every(RateLimitIntervalDefault), RateLimitBurstDefault) - } - - if args.builderBlockResubmitInterval == 0 { - args.builderBlockResubmitInterval = BlockResubmitIntervalDefault - } - - if args.submissionOffsetFromEndOfSlot == 0 { - args.submissionOffsetFromEndOfSlot = SubmissionOffsetFromEndOfSlotSecondsDefault - } - - slotCtx, slotCtxCancel := context.WithCancel(context.Background()) - - constraintsCache := shardmap.NewFIFOMap[uint64, types.HashToConstraintDecoded](64, 16, shardmap.HashUint64) - - return &Builder{ - ds: args.ds, - blockConsumer: args.blockConsumer, - relay: args.relay, - eth: args.eth, - dryRun: args.dryRun, - ignoreLatePayloadAttributes: args.ignoreLatePayloadAttributes, - validator: args.validator, - beaconClient: args.beaconClient, - builderSecretKey: args.sk, - builderPublicKey: pk, - builderSigningDomain: args.builderSigningDomain, - builderResubmitInterval: args.builderBlockResubmitInterval, - discardRevertibleTxOnErr: args.discardRevertibleTxOnErr, - submissionOffsetFromEndOfSlot: args.submissionOffsetFromEndOfSlot, - - constraintsCache: constraintsCache, - - limiter: args.limiter, - slotCtx: slotCtx, - slotCtxCancel: slotCtxCancel, - - stop: make(chan struct{}, 1), - }, nil -} - -func (b *Builder) Start() error { - // Start regular payload attributes updates - go func() { - c := make(chan types.BuilderPayloadAttributes) - go b.beaconClient.SubscribeToPayloadAttributesEvents(c) - - currentSlot := uint64(0) - - for { - select { - case <-b.stop: - return - case payloadAttributes := <-c: - // Right now we are building only on a single head. This might change in the future! - if payloadAttributes.Slot < currentSlot { - continue - } else if payloadAttributes.Slot == currentSlot { - // Subsequent sse events should only be canonical! - if !b.ignoreLatePayloadAttributes { - err := b.OnPayloadAttribute(&payloadAttributes) - if err != nil { - log.Error("error with builder processing on payload attribute", - "latestSlot", currentSlot, - "processedSlot", payloadAttributes.Slot, - "headHash", payloadAttributes.HeadHash.String(), - "error", err) - } - } - } else if payloadAttributes.Slot > currentSlot { - currentSlot = payloadAttributes.Slot - err := b.OnPayloadAttribute(&payloadAttributes) - if err != nil { - log.Error("error with builder processing on payload attribute", - "latestSlot", currentSlot, - "processedSlot", payloadAttributes.Slot, - "headHash", payloadAttributes.HeadHash.String(), - "error", err) - } - } - } - } - }() - - if err := b.relay.Start(); err != nil { - return err - } - - return b.SubscribeProposerConstraints() -} - -// SubscribeProposerConstraints subscribes to the constraints made by Bolt proposers -// which the builder pulls from relay(s) using SSE. -func (b *Builder) SubscribeProposerConstraints() error { - // Check if `b.relay` is a RemoteRelayAggregator, if so we need to subscribe to - // the constraints made available by all the relays - relayAggregator, ok := b.relay.(*RemoteRelayAggregator) - if ok { - for _, relay := range relayAggregator.relays { - go b.subscribeToRelayForConstraints(relay.Config().Endpoint) - } - } else { - go b.subscribeToRelayForConstraints(b.relay.Config().Endpoint) - } - return nil -} - -func (b *Builder) subscribeToRelayForConstraints(relayBaseEndpoint string) error { - attempts := 0 - maxAttempts := 60 // Max 10 minutes of retries - retryInterval := 10 * time.Second - - var resp *http.Response - - for { - log.Info("Attempting to subscribe to constraints...") - - if attempts >= maxAttempts { - log.Error(fmt.Sprintf("Failed to subscribe to constraints after %d attempts", maxAttempts)) - return errors.New("failed to subscribe to constraints") - } - - req, err := http.NewRequest(http.MethodGet, relayBaseEndpoint+SubscribeConstraintsPath, nil) - if err != nil { - log.Error(fmt.Sprintf("Failed to create new http request: %v", err)) - return err - } - - client := http.Client{} - - resp, err = client.Do(req) - if err != nil { - log.Error(fmt.Sprintf("Failed to connect to SSE server: %v", err)) - time.Sleep(retryInterval) - attempts++ - continue - } - - if resp.StatusCode != http.StatusOK { - log.Error(fmt.Sprintf("Error subscribing to constraints via SSE: %s, %v", resp.Status, err)) - return err - } - break - } - - defer resp.Body.Close() - log.Info(fmt.Sprintf("Connected to SSE server: %s", relayBaseEndpoint)) - - var reader io.Reader - - // Check if the response is gzipped - if resp.Header.Get("Content-Encoding") == "gzip" { - // Decompress the response body - gzipReader, err := gzip.NewReader(resp.Body) - if err != nil { - return fmt.Errorf("error creating gzip reader: %v", err) - } - defer gzipReader.Close() - reader = gzipReader - } else { - reader = resp.Body - } - - bufReader := bufio.NewReader(reader) - for { - line, err := bufReader.ReadString('\n') - if err != nil { - if err == io.EOF { - log.Info("End of stream") - break - } - log.Error(fmt.Sprintf("Error reading from response body: %v", err)) - continue - } - - if !strings.HasPrefix(line, "data: ") { - continue - } - - data := strings.TrimPrefix(line, "data: ") - - // We assume the data is the JSON representation of the constraints - log.Info(fmt.Sprintf("Received new constraint: %s", data)) - constraintsSigned := make(common.SignedConstraintsList, 0, 8) - if err := json.Unmarshal([]byte(data), &constraintsSigned); err != nil { - log.Warn(fmt.Sprintf("Failed to unmarshal constraints: %v", err)) - continue - } - - if len(constraintsSigned) == 0 { - log.Warn("Received 0 length list of constraints") - continue - } - - for _, constraint := range constraintsSigned { - decodedConstraints, err := DecodeConstraints(constraint) - if err != nil { - log.Error("Failed to decode constraint: ", err) - continue - } - - EmitBoltDemoEvent(fmt.Sprintf("Received constraint from relay for slot %d, stored in cache (path: %s)", constraint.Message.Slot, SubscribeConstraintsPath)) - - // For every constraint, we need to check if it has already been seen for the associated slot - slotConstraints, _ := b.constraintsCache.Get(constraint.Message.Slot) - if len(slotConstraints) == 0 { - // New constraint for this slot, add it in the map and continue with the next constraint - b.constraintsCache.Put(constraint.Message.Slot, decodedConstraints) - continue - } - - for hash := range decodedConstraints { - // Update the slot constraints - slotConstraints[hash] = decodedConstraints[hash] - } - - // Update the slot constraints in the cache - b.constraintsCache.Put(constraint.Message.Slot, slotConstraints) - - } - - } - - return nil -} - -func (b *Builder) Stop() error { - close(b.stop) - return nil -} - -// BOLT: modify to calculate merkle inclusion proofs for preconfirmed transactions -func (b *Builder) onSealedBlock(opts SubmitBlockOpts) error { - executableData := engine.BlockToExecutableData(opts.Block, opts.BlockValue, opts.BlobSidecars) - var dataVersion spec.DataVersion - if b.eth.Config().IsCancun(opts.Block.Number(), opts.Block.Time()) { - dataVersion = spec.DataVersionDeneb - } else if b.eth.Config().IsShanghai(opts.Block.Number(), opts.Block.Time()) { - dataVersion = spec.DataVersionCapella - } else { - dataVersion = spec.DataVersionBellatrix - } - - value, overflow := uint256.FromBig(opts.BlockValue) - if overflow { - err := fmt.Errorf("could not set block value due to value overflow") - log.Error(err.Error()) - return err - } - - blockBidMsg := builderApiV1.BidTrace{ - Slot: opts.PayloadAttributes.Slot, - ParentHash: phase0.Hash32(opts.Block.ParentHash()), - BlockHash: phase0.Hash32(opts.Block.Hash()), - BuilderPubkey: b.builderPublicKey, - ProposerPubkey: opts.ProposerPubkey, - ProposerFeeRecipient: opts.ValidatorData.FeeRecipient, - GasLimit: executableData.ExecutionPayload.GasLimit, - GasUsed: executableData.ExecutionPayload.GasUsed, - Value: value, - } - - versionedBlockRequest, err := b.getBlockRequest(executableData, dataVersion, &blockBidMsg) - if err != nil { - log.Error("could not get block request", "err", err) - return err - } - - var versionedBlockRequestWithPreconfsProofs *common.VersionedSubmitBlockRequestWithProofs - - // BOLT: fetch constraints from the cache, which is automatically updated by the SSE subscription - constraints, _ := b.constraintsCache.Get(opts.PayloadAttributes.Slot) - log.Info(fmt.Sprintf("[BOLT]: Found %d constraints for slot %d", len(constraints), opts.PayloadAttributes.Slot)) - - if len(constraints) > 0 { - message := fmt.Sprintf("sealing block %d with %d constraints", opts.Block.Number(), len(constraints)) - log.Info(message) - EmitBoltDemoEvent(message) - - timeStart := time.Now() - inclusionProof, _, err := CalculateMerkleMultiProofs(opts.Block.Transactions(), constraints) - timeForProofs := time.Since(timeStart) - - if err != nil { - log.Error("[BOLT]: could not calculate merkle multiproofs", "err", err) - return err - } - - // BOLT: send event to web demo - EmitBoltDemoEvent(fmt.Sprintf("created merkle multiproof of %d constraint(s) for block %d in %v", len(constraints), opts.Block.Number(), timeForProofs)) - - versionedBlockRequestWithPreconfsProofs = &common.VersionedSubmitBlockRequestWithProofs{ - Inner: versionedBlockRequest, - Proofs: inclusionProof, - } - } - - if b.dryRun { - switch dataVersion { - case spec.DataVersionBellatrix: - err = b.validator.ValidateBuilderSubmissionV1(&blockvalidation.BuilderBlockValidationRequest{SubmitBlockRequest: *versionedBlockRequest.Bellatrix, RegisteredGasLimit: opts.ValidatorData.GasLimit}) - case spec.DataVersionCapella: - err = b.validator.ValidateBuilderSubmissionV2(&blockvalidation.BuilderBlockValidationRequestV2{SubmitBlockRequest: *versionedBlockRequest.Capella, RegisteredGasLimit: opts.ValidatorData.GasLimit}) - case spec.DataVersionDeneb: - err = b.validator.ValidateBuilderSubmissionV3(&blockvalidation.BuilderBlockValidationRequestV3{SubmitBlockRequest: *versionedBlockRequest.Deneb, RegisteredGasLimit: opts.ValidatorData.GasLimit, ParentBeaconBlockRoot: *opts.Block.BeaconRoot()}) - } - if err != nil { - log.Error("could not validate block", "version", dataVersion.String(), "err", err) - } - } else { - // NOTE: we can ignore preconfs for `processBuiltBlock` - go b.processBuiltBlock(opts.Block, opts.BlockValue, opts.OrdersClosedAt, opts.SealedAt, opts.CommitedBundles, opts.AllBundles, opts.UsedSbundles, &blockBidMsg) - if versionedBlockRequestWithPreconfsProofs != nil { - log.Info(fmt.Sprintf("[BOLT]: Sending sealed block to relay %s", versionedBlockRequestWithPreconfsProofs)) - err = b.relay.SubmitBlockWithProofs(versionedBlockRequestWithPreconfsProofs, opts.ValidatorData) - } else if len(constraints) == 0 { - // If versionedBlockRequestWithPreconfsProofs is nil and no constraints, then we don't have proofs to send - err = b.relay.SubmitBlock(versionedBlockRequest, opts.ValidatorData) - } else { - log.Warn(fmt.Sprintf("[BOLT]: Could not send sealed block this time because we have %d constraints but no proofs", len(constraints))) - return nil - } - if err != nil { - log.Error("could not submit block", "err", err, "verion", dataVersion, "#commitedBundles", len(opts.CommitedBundles)) - return err - } - } - - return nil -} - -func (b *Builder) getBlockRequest(executableData *engine.ExecutionPayloadEnvelope, dataVersion spec.DataVersion, blockBidMsg *builderApiV1.BidTrace) (*builderSpec.VersionedSubmitBlockRequest, error) { - payload, err := executableDataToExecutionPayload(executableData, dataVersion) - if err != nil { - log.Error("could not format execution payload", "err", err) - return nil, err - } - - signature, err := ssz.SignMessage(blockBidMsg, b.builderSigningDomain, b.builderSecretKey) - if err != nil { - log.Error("could not sign builder bid", "err", err) - return nil, err - } - - var versionedBlockRequest builderSpec.VersionedSubmitBlockRequest - switch dataVersion { - case spec.DataVersionBellatrix: - blockSubmitReq := builderApiBellatrix.SubmitBlockRequest{ - Signature: signature, - Message: blockBidMsg, - ExecutionPayload: payload.Bellatrix, - } - versionedBlockRequest = builderSpec.VersionedSubmitBlockRequest{ - Version: spec.DataVersionBellatrix, - Bellatrix: &blockSubmitReq, - } - case spec.DataVersionCapella: - blockSubmitReq := builderApiCapella.SubmitBlockRequest{ - Signature: signature, - Message: blockBidMsg, - ExecutionPayload: payload.Capella, - } - versionedBlockRequest = builderSpec.VersionedSubmitBlockRequest{ - Version: spec.DataVersionCapella, - Capella: &blockSubmitReq, - } - case spec.DataVersionDeneb: - blockSubmitReq := builderApiDeneb.SubmitBlockRequest{ - Signature: signature, - Message: blockBidMsg, - ExecutionPayload: payload.Deneb.ExecutionPayload, - BlobsBundle: payload.Deneb.BlobsBundle, - } - versionedBlockRequest = builderSpec.VersionedSubmitBlockRequest{ - Version: spec.DataVersionDeneb, - Deneb: &blockSubmitReq, - } - } - return &versionedBlockRequest, err -} - -func (b *Builder) processBuiltBlock(block *types.Block, blockValue *big.Int, ordersClosedAt time.Time, sealedAt time.Time, commitedBundles []types.SimulatedBundle, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle, bidTrace *builderApiV1.BidTrace) { - back := backoff.NewExponentialBackOff() - back.MaxInterval = 3 * time.Second - back.MaxElapsedTime = 12 * time.Second - err := backoff.Retry(func() error { - return b.blockConsumer.ConsumeBuiltBlock(block, blockValue, ordersClosedAt, sealedAt, commitedBundles, allBundles, usedSbundles, bidTrace) - }, back) - if err != nil { - log.Error("could not consume built block", "err", err) - } else { - log.Info("successfully relayed block data to consumer") - } -} - -// Called when a new payload event is received from the beacon client SSE -func (b *Builder) OnPayloadAttribute(attrs *types.BuilderPayloadAttributes) error { - if attrs == nil { - return nil - } - - vd, err := b.relay.GetValidatorForSlot(attrs.Slot) - if err != nil { - return fmt.Errorf("could not get validator while submitting block for slot %d - %w", attrs.Slot, err) - } - - parentBlock := b.eth.GetBlockByHash(attrs.HeadHash) - if parentBlock == nil { - return fmt.Errorf("parent block hash not found in block tree given head block hash %s", attrs.HeadHash) - } - - attrs.SuggestedFeeRecipient = [20]byte(vd.FeeRecipient) - attrs.GasLimit = core.CalcGasLimit(parentBlock.GasLimit(), vd.GasLimit) - - proposerPubkey, err := utils.HexToPubkey(string(vd.Pubkey)) - if err != nil { - return fmt.Errorf("could not parse pubkey (%s) - %w", vd.Pubkey, err) - } - - if !b.eth.Synced() { - return errors.New("backend not Synced") - } - - b.slotMu.Lock() - defer b.slotMu.Unlock() - - if attrs.Equal(&b.slotAttrs) { - log.Debug("ignoring known payload attribute", "slot", attrs.Slot, "hash", attrs.HeadHash) - return nil - } - - if b.slotCtxCancel != nil { - b.slotCtxCancel() - } - - slotCtx, slotCtxCancel := context.WithTimeout(context.Background(), 12*time.Second) - b.slotAttrs = *attrs - b.slotCtx = slotCtx - b.slotCtxCancel = slotCtxCancel - - log.Info("[BOLT]: Inside onPayloadAttribute", "slot", attrs.Slot, "parent", attrs.HeadHash, "payloadTimestamp", uint64(attrs.Timestamp)) - - go b.runBuildingJob(b.slotCtx, proposerPubkey, vd, attrs) - return nil -} - -type blockQueueEntry struct { - block *types.Block - blockValue *big.Int - blobSidecars []*types.BlobTxSidecar - ordersCloseTime time.Time - sealedAt time.Time - commitedBundles []types.SimulatedBundle - allBundles []types.SimulatedBundle - usedSbundles []types.UsedSBundle -} - -// Continuously makes a request to the miner module with the correct params and submits the best produced block. -// on average 1 attempt per second is made. -// - Submissions to the relay are rate limited to 2 req/s -func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey phase0.BLSPubKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) { - ctx, cancel := context.WithTimeout(slotCtx, 12*time.Second) - defer cancel() - - // Submission queue for the given payload attributes - // multiple jobs can run for different attributes fot the given slot - // 1. When new block is ready we check if its profit is higher than profit of last best block - // if it is we set queueBest* to values of the new block and notify queueSignal channel. - // 2. Submission goroutine waits for queueSignal and submits queueBest* if its more valuable than - // queueLastSubmittedProfit keeping queueLastSubmittedProfit to be the profit of the last submission. - // Submission goroutine is globally rate limited to have fixed rate of submissions for all jobs. - var ( - queueSignal = make(chan struct{}, 1) - - queueMu sync.Mutex - queueLastSubmittedHash common.Hash - queueBestEntry blockQueueEntry - ) - - log.Debug("runBuildingJob", "slot", attrs.Slot, "parent", attrs.HeadHash, "payloadTimestamp", uint64(attrs.Timestamp)) - - submitBestBlock := func() { - queueMu.Lock() - if queueBestEntry.block.Hash() != queueLastSubmittedHash { - submitBlockOpts := SubmitBlockOpts{ - Block: queueBestEntry.block, - BlockValue: queueBestEntry.blockValue, - BlobSidecars: queueBestEntry.blobSidecars, - OrdersClosedAt: queueBestEntry.ordersCloseTime, - SealedAt: queueBestEntry.sealedAt, - CommitedBundles: queueBestEntry.commitedBundles, - AllBundles: queueBestEntry.allBundles, - UsedSbundles: queueBestEntry.usedSbundles, - ProposerPubkey: proposerPubkey, - ValidatorData: vd, - PayloadAttributes: attrs, - } - err := b.onSealedBlock(submitBlockOpts) - - if err != nil { - log.Error("could not run sealed block hook", "err", err) - } else { - queueLastSubmittedHash = queueBestEntry.block.Hash() - } - } - queueMu.Unlock() - } - - // Avoid submitting early into a given slot. For example if slots have 12 second interval, submissions should - // not begin until 8 seconds into the slot. - slotTime := time.Unix(int64(attrs.Timestamp), 0).UTC() - slotSubmitStartTime := slotTime.Add(-b.submissionOffsetFromEndOfSlot) - - // Empties queue, submits the best block for current job with rate limit (global for all jobs) - go runResubmitLoop(ctx, b.limiter, queueSignal, submitBestBlock, slotSubmitStartTime) - - // Populates queue with submissions that increase block profit - blockHook := func(block *types.Block, blockValue *big.Int, sidecars []*types.BlobTxSidecar, ordersCloseTime time.Time, - committedBundles, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle, - ) { - if ctx.Err() != nil { - return - } - - sealedAt := time.Now() - - queueMu.Lock() - defer queueMu.Unlock() - if block.Hash() != queueLastSubmittedHash { - queueBestEntry = blockQueueEntry{ - block: block, - blockValue: new(big.Int).Set(blockValue), - blobSidecars: sidecars, - ordersCloseTime: ordersCloseTime, - sealedAt: sealedAt, - commitedBundles: committedBundles, - allBundles: allBundles, - usedSbundles: usedSbundles, - } - - select { - case queueSignal <- struct{}{}: - default: - } - } - } - - // resubmits block builder requests every builderBlockResubmitInterval - runRetryLoop(ctx, b.builderResubmitInterval, func() { - log.Debug("retrying BuildBlock", - "slot", attrs.Slot, - "parent", attrs.HeadHash, - "resubmit-interval", b.builderResubmitInterval.String()) - err := b.eth.BuildBlock(attrs, blockHook, b.constraintsCache) - if err != nil { - log.Warn("Failed to build block", "err", err) - } - }) -} - -func executableDataToExecutionPayload(data *engine.ExecutionPayloadEnvelope, version spec.DataVersion) (*builderApi.VersionedSubmitBlindedBlockResponse, error) { - // if version in phase0, altair, unsupported version - if version == spec.DataVersionUnknown || version == spec.DataVersionPhase0 || version == spec.DataVersionAltair { - return nil, fmt.Errorf("unsupported data version %d", version) - } - - payload := data.ExecutionPayload - blobsBundle := data.BlobsBundle - - transactionData := make([]bellatrix.Transaction, len(payload.Transactions)) - for i, tx := range payload.Transactions { - transactionData[i] = bellatrix.Transaction(tx) - } - - baseFeePerGas := new(boostTypes.U256Str) - err := baseFeePerGas.FromBig(payload.BaseFeePerGas) - if err != nil { - return nil, err - } - - if version == spec.DataVersionBellatrix { - return getBellatrixPayload(payload, *baseFeePerGas, transactionData), nil - } - - withdrawalData := make([]*capella.Withdrawal, len(payload.Withdrawals)) - for i, wd := range payload.Withdrawals { - withdrawalData[i] = &capella.Withdrawal{ - Index: capella.WithdrawalIndex(wd.Index), - ValidatorIndex: phase0.ValidatorIndex(wd.Validator), - Address: bellatrix.ExecutionAddress(wd.Address), - Amount: phase0.Gwei(wd.Amount), - } - } - if version == spec.DataVersionCapella { - return getCapellaPayload(payload, *baseFeePerGas, transactionData, withdrawalData), nil - } - - uint256BaseFeePerGas, overflow := uint256.FromBig(payload.BaseFeePerGas) - if overflow { - return nil, fmt.Errorf("base fee per gas overflow") - } - - if len(blobsBundle.Blobs) != len(blobsBundle.Commitments) || len(blobsBundle.Blobs) != len(blobsBundle.Proofs) { - return nil, fmt.Errorf("blobs bundle length mismatch") - } - - if version == spec.DataVersionDeneb { - return getDenebPayload(payload, uint256BaseFeePerGas, transactionData, withdrawalData, blobsBundle), nil - } - - return nil, fmt.Errorf("unsupported data version %d", version) -} - -func getBellatrixPayload( - payload *engine.ExecutableData, - baseFeePerGas [32]byte, - transactions []bellatrix.Transaction, -) *builderApi.VersionedSubmitBlindedBlockResponse { - return &builderApi.VersionedSubmitBlindedBlockResponse{ - Version: spec.DataVersionBellatrix, - Bellatrix: &bellatrix.ExecutionPayload{ - ParentHash: [32]byte(payload.ParentHash), - FeeRecipient: [20]byte(payload.FeeRecipient), - StateRoot: [32]byte(payload.StateRoot), - ReceiptsRoot: [32]byte(payload.ReceiptsRoot), - LogsBloom: types.BytesToBloom(payload.LogsBloom), - PrevRandao: [32]byte(payload.Random), - BlockNumber: payload.Number, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: baseFeePerGas, - BlockHash: [32]byte(payload.BlockHash), - Transactions: transactions, - }, - } -} - -func getCapellaPayload( - payload *engine.ExecutableData, - baseFeePerGas [32]byte, - transactions []bellatrix.Transaction, - withdrawals []*capella.Withdrawal, -) *builderApi.VersionedSubmitBlindedBlockResponse { - return &builderApi.VersionedSubmitBlindedBlockResponse{ - Version: spec.DataVersionCapella, - Capella: &capella.ExecutionPayload{ - ParentHash: [32]byte(payload.ParentHash), - FeeRecipient: [20]byte(payload.FeeRecipient), - StateRoot: [32]byte(payload.StateRoot), - ReceiptsRoot: [32]byte(payload.ReceiptsRoot), - LogsBloom: types.BytesToBloom(payload.LogsBloom), - PrevRandao: [32]byte(payload.Random), - BlockNumber: payload.Number, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: baseFeePerGas, - BlockHash: [32]byte(payload.BlockHash), - Transactions: transactions, - Withdrawals: withdrawals, - }, - } -} - -func getBlobsBundle(blobsBundle *engine.BlobsBundleV1) *builderApiDeneb.BlobsBundle { - commitments := make([]deneb.KZGCommitment, len(blobsBundle.Commitments)) - proofs := make([]deneb.KZGProof, len(blobsBundle.Proofs)) - blobs := make([]deneb.Blob, len(blobsBundle.Blobs)) - - // we assume the lengths for blobs bundle is validated beforehand to be the same - for i := range blobsBundle.Blobs { - var commitment deneb.KZGCommitment - copy(commitment[:], blobsBundle.Commitments[i][:]) - commitments[i] = commitment - - var proof deneb.KZGProof - copy(proof[:], blobsBundle.Proofs[i][:]) - proofs[i] = proof - - var blob deneb.Blob - copy(blob[:], blobsBundle.Blobs[i][:]) - blobs[i] = blob - } - return &builderApiDeneb.BlobsBundle{ - Commitments: commitments, - Proofs: proofs, - Blobs: blobs, - } -} - -func getDenebPayload( - payload *engine.ExecutableData, - baseFeePerGas *uint256.Int, - transactions []bellatrix.Transaction, - withdrawals []*capella.Withdrawal, - blobsBundle *engine.BlobsBundleV1, -) *builderApi.VersionedSubmitBlindedBlockResponse { - return &builderApi.VersionedSubmitBlindedBlockResponse{ - Version: spec.DataVersionDeneb, - Deneb: &builderApiDeneb.ExecutionPayloadAndBlobsBundle{ - ExecutionPayload: &deneb.ExecutionPayload{ - ParentHash: [32]byte(payload.ParentHash), - FeeRecipient: [20]byte(payload.FeeRecipient), - StateRoot: [32]byte(payload.StateRoot), - ReceiptsRoot: [32]byte(payload.ReceiptsRoot), - LogsBloom: types.BytesToBloom(payload.LogsBloom), - PrevRandao: [32]byte(payload.Random), - BlockNumber: payload.Number, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: payload.ExtraData, - BaseFeePerGas: baseFeePerGas, - BlockHash: [32]byte(payload.BlockHash), - Transactions: transactions, - Withdrawals: withdrawals, - BlobGasUsed: *payload.BlobGasUsed, - ExcessBlobGas: *payload.ExcessBlobGas, - }, - BlobsBundle: getBlobsBundle(blobsBundle), - }, - } -} diff --git a/builder/builder/builder_test.go b/builder/builder/builder_test.go deleted file mode 100644 index 2badb9196..000000000 --- a/builder/builder/builder_test.go +++ /dev/null @@ -1,566 +0,0 @@ -package builder - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - "net/http" - "strings" - "testing" - "time" - - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/flashbotsextra" - "github.com/ethereum/go-ethereum/log" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - "github.com/flashbots/go-boost-utils/utils" - "github.com/gorilla/handlers" - "github.com/holiman/uint256" - "github.com/pkg/errors" - "github.com/stretchr/testify/require" -) - -func TestOnPayloadAttributes(t *testing.T) { - const ( - validatorDesiredGasLimit = 30_000_000 - payloadAttributeGasLimit = 0 - parentBlockGasLimit = 29_000_000 - ) - expectedGasLimit := core.CalcGasLimit(parentBlockGasLimit, validatorDesiredGasLimit) - - vsk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x370bb8c1a6e62b2882f6ec76762a67b39609002076b95aae5b023997cf9b2dc9")) - require.NoError(t, err) - validator := &ValidatorPrivateData{ - sk: vsk, - Pk: hexutil.MustDecode("0xb67d2c11bcab8c4394fc2faa9601d0b99c7f4b37e14911101da7d97077917862eed4563203d34b91b5cf0aa44d6cfa05"), - } - - testBeacon := testBeaconClient{ - validator: validator, - slot: 56, - } - - feeRecipient, _ := utils.HexToAddress("0xabcf8e0d4e9587369b2301d0790347320302cc00") - testRelay := testRelay{ - gvsVd: ValidatorData{ - Pubkey: PubkeyHex(testBeacon.validator.Pk.String()), - FeeRecipient: feeRecipient, - GasLimit: validatorDesiredGasLimit, - }, - } - - sk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x31ee185dad1220a8c88ca5275e64cf5a5cb09cb621cb30df52c9bee8fbaaf8d7")) - require.NoError(t, err) - - bDomain := ssz.ComputeDomain(ssz.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, phase0.Root{}) - - testExecutableData := &engine.ExecutableData{ - ParentHash: common.Hash{0x02, 0x03}, - FeeRecipient: common.Address(feeRecipient), - StateRoot: common.Hash{0x07, 0x16}, - ReceiptsRoot: common.Hash{0x08, 0x20}, - LogsBloom: types.Bloom{}.Bytes(), - Number: uint64(10), - GasLimit: expectedGasLimit, - GasUsed: uint64(100), - Timestamp: uint64(105), - ExtraData: hexutil.MustDecode("0x0042fafc"), - - BaseFeePerGas: big.NewInt(16), - - BlockHash: common.HexToHash("0x68e516c8827b589fcb749a9e672aa16b9643437459508c467f66a9ed1de66a6c"), - Transactions: [][]byte{}, - } - - testBlock, err := engine.ExecutableDataToBlock(*testExecutableData, nil, nil) - require.NoError(t, err) - - testPayloadAttributes := &types.BuilderPayloadAttributes{ - Timestamp: hexutil.Uint64(104), - Random: common.Hash{0x05, 0x10}, - SuggestedFeeRecipient: common.Address{0x04, 0x10}, - GasLimit: uint64(payloadAttributeGasLimit), - Slot: uint64(25), - } - - testEthService := &testEthereumService{synced: true, testExecutableData: testExecutableData, testBlock: testBlock, testBlockValue: big.NewInt(10)} - builderArgs := BuilderArgs{ - sk: sk, - ds: flashbotsextra.NilDbService{}, - relay: &testRelay, - builderSigningDomain: bDomain, - eth: testEthService, - dryRun: false, - ignoreLatePayloadAttributes: false, - validator: nil, - beaconClient: &testBeacon, - limiter: nil, - blockConsumer: flashbotsextra.NilDbService{}, - } - builder, err := NewBuilder(builderArgs) - require.NoError(t, err) - builder.Start() - defer builder.Stop() - - err = builder.OnPayloadAttribute(testPayloadAttributes) - require.NoError(t, err) - time.Sleep(time.Second * 3) - - require.NotNil(t, testRelay.submittedMsg) - - expectedProposerPubkey, err := utils.HexToPubkey(testBeacon.validator.Pk.String()) - require.NoError(t, err) - - expectedMessage := builderApiV1.BidTrace{ - Slot: uint64(25), - ParentHash: phase0.Hash32{0x02, 0x03}, - BuilderPubkey: builder.builderPublicKey, - ProposerPubkey: expectedProposerPubkey, - ProposerFeeRecipient: feeRecipient, - GasLimit: expectedGasLimit, - GasUsed: uint64(100), - Value: &uint256.Int{0x0a}, - } - copy(expectedMessage.BlockHash[:], hexutil.MustDecode("0x68e516c8827b589fcb749a9e672aa16b9643437459508c467f66a9ed1de66a6c")[:]) - require.NotNil(t, testRelay.submittedMsg.Bellatrix) - require.Equal(t, expectedMessage, *testRelay.submittedMsg.Bellatrix.Message) - - expectedExecutionPayload := bellatrix.ExecutionPayload{ - ParentHash: [32]byte(testExecutableData.ParentHash), - FeeRecipient: feeRecipient, - StateRoot: [32]byte(testExecutableData.StateRoot), - ReceiptsRoot: [32]byte(testExecutableData.ReceiptsRoot), - LogsBloom: [256]byte{}, - PrevRandao: [32]byte(testExecutableData.Random), - BlockNumber: testExecutableData.Number, - GasLimit: testExecutableData.GasLimit, - GasUsed: testExecutableData.GasUsed, - Timestamp: testExecutableData.Timestamp, - ExtraData: hexutil.MustDecode("0x0042fafc"), - BaseFeePerGas: [32]byte{0x10}, - BlockHash: expectedMessage.BlockHash, - Transactions: []bellatrix.Transaction{}, - } - - require.Equal(t, expectedExecutionPayload, *testRelay.submittedMsg.Bellatrix.ExecutionPayload) - - expectedSignature, err := utils.HexToSignature("0x8d1dc346d469b0678ee72baa559315433af0966d2d05dad0de9ce60ff5e4954d4e28a85643496df279494d105bc4a771034fefcdd83d71df5f1b81c9369942b20d6d574b544a93588f6182ba8b09585eb1cf3e1b6551ccbd9e76a4db8eb579fe") - - require.NoError(t, err) - require.Equal(t, expectedSignature, testRelay.submittedMsg.Bellatrix.Signature) - - require.Equal(t, uint64(25), testRelay.requestedSlot) - - // Clear the submitted message and check that the job will be ran again and but a new message will not be submitted since the hash is the same - testEthService.testBlockValue = big.NewInt(10) - - testRelay.submittedMsg = nil - time.Sleep(2200 * time.Millisecond) - require.Nil(t, testRelay.submittedMsg) - - // Change the hash, expect to get the block - testExecutableData.ExtraData = hexutil.MustDecode("0x0042fafd") - testExecutableData.BlockHash = common.HexToHash("0x6a259b9a148da3cc0bf139eaa89292fa9f7b136cfeddad17f7cb0ae33e0c3df9") - testBlock, err = engine.ExecutableDataToBlock(*testExecutableData, nil, nil) - testEthService.testBlockValue = big.NewInt(10) - require.NoError(t, err) - testEthService.testBlock = testBlock - - time.Sleep(2200 * time.Millisecond) - require.NotNil(t, testRelay.submittedMsg) -} - -func TestBlockWithPreconfs(t *testing.T) { - const ( - validatorDesiredGasLimit = 30_000_000 - payloadAttributeGasLimit = 30_000_000 // Was zero in the other test - parentBlockGasLimit = 29_000_000 - ) - expectedGasLimit := core.CalcGasLimit(parentBlockGasLimit, validatorDesiredGasLimit) - - vsk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x370bb8c1a6e62b2882f6ec76762a67b39609002076b95aae5b023997cf9b2dc9")) - require.NoError(t, err) - validator := &ValidatorPrivateData{ - sk: vsk, - Pk: hexutil.MustDecode("0xb67d2c11bcab8c4394fc2faa9601d0b99c7f4b37e14911101da7d97077917862eed4563203d34b91b5cf0aa44d6cfa05"), - } - - testBeacon := testBeaconClient{ - validator: validator, - slot: 56, - } - - feeRecipient, _ := utils.HexToAddress("0xabcf8e0d4e9587369b2301d0790347320302cc00") - testRelay := testRelay{ - gvsVd: ValidatorData{ - Pubkey: PubkeyHex(testBeacon.validator.Pk.String()), - FeeRecipient: feeRecipient, - GasLimit: validatorDesiredGasLimit, - }, - } - - sk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x31ee185dad1220a8c88ca5275e64cf5a5cb09cb621cb30df52c9bee8fbaaf8d7")) - require.NoError(t, err) - - bDomain := ssz.ComputeDomain(ssz.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, phase0.Root{}) - - // https://etherscan.io/tx/0x9d48b4a021898a605b7ae49bf93ad88fa6bd7050e9448f12dde064c10f22fe9c - // 0x02f87601836384348477359400850517683ba883019a28943678fce4028b6745eb04fa010d9c8e4b36d6288c872b0f1366ad800080c080a0b6b7aba1954160d081b2c8612e039518b9c46cd7df838b405a03f927ad196158a071d2fb6813e5b5184def6bd90fb5f29e0c52671dea433a7decb289560a58416e - preconfTxByte, _ := hex.DecodeString("02f87601836384348477359400850517683ba883019a28943678fce4028b6745eb04fa010d9c8e4b36d6288c872b0f1366ad800080c080a0b6b7aba1954160d081b2c8612e039518b9c46cd7df838b405a03f927ad196158a071d2fb6813e5b5184def6bd90fb5f29e0c52671dea433a7decb289560a58416e") - preconfTx := new(types.Transaction) - err = preconfTx.UnmarshalBinary(preconfTxByte) - require.NoError(t, err) - - // https://etherscan.io/tx/0x15bd881daa1408b33f67fa4bdeb8acfb0a2289d9b4c6f81eef9bb2bb2e52e780 - Blob Tx - // 0x03f9029c01830299f184b2d05e008507aef40a00832dc6c09468d30f47f19c07bccef4ac7fae2dc12fca3e0dc980b90204ef16e845000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000633b68f5d8d3a86593ebb815b4663bcbe0302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004109de8da2a97e37f2e6dc9f7d50a408f9344d7aa1a925ae53daf7fbef43491a571960d76c0cb926190a9da10df7209fb1ba93cd98b1565a3a2368749d505f90c81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a00141e3a338e30c49ed0501e315bcc45e4edefebed43ab1368a1505461d9cf64901a01e8511e06b17683d89eb57b9869b96b8b611f969f7f56cbc0adc2df7c88a2a07a00910deacf91bba0d74e368d285d311dc5884e7cfe219d85aea5741b2b6e3a2fe - preconfTxWithBlobByte, _ := hex.DecodeString("03f9029c01830299f184b2d05e008507aef40a00832dc6c09468d30f47f19c07bccef4ac7fae2dc12fca3e0dc980b90204ef16e845000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000633b68f5d8d3a86593ebb815b4663bcbe0302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004109de8da2a97e37f2e6dc9f7d50a408f9344d7aa1a925ae53daf7fbef43491a571960d76c0cb926190a9da10df7209fb1ba93cd98b1565a3a2368749d505f90c81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a00141e3a338e30c49ed0501e315bcc45e4edefebed43ab1368a1505461d9cf64901a01e8511e06b17683d89eb57b9869b96b8b611f969f7f56cbc0adc2df7c88a2a07a00910deacf91bba0d74e368d285d311dc5884e7cfe219d85aea5741b2b6e3a2fe") - preconfTxWithBlob := new(types.Transaction) - err = preconfTxWithBlob.UnmarshalBinary(preconfTxWithBlobByte) - require.NoError(t, err) - - testExecutableData := &engine.ExecutableData{ - ParentHash: common.Hash{0x02, 0x03}, - FeeRecipient: common.Address(feeRecipient), - StateRoot: common.Hash{0x07, 0x16}, - ReceiptsRoot: common.Hash{0x08, 0x20}, - LogsBloom: types.Bloom{}.Bytes(), - Number: uint64(10), - GasLimit: expectedGasLimit, - GasUsed: uint64(100), - Timestamp: uint64(105), - ExtraData: hexutil.MustDecode("0x0042fafc"), - - BaseFeePerGas: big.NewInt(16), - - BlockHash: common.HexToHash("3cce5d0f5c9a7e188e79c35168256e91bec2d98a1140f6701da6ed3c98ea9d04"), - Transactions: [][]byte{preconfTxByte, preconfTxWithBlobByte}, - } - - testBlock, err := engine.ExecutableDataToBlock(*testExecutableData, preconfTxWithBlob.BlobHashes(), nil) - require.NoError(t, err) - - testPayloadAttributes := &types.BuilderPayloadAttributes{ - Timestamp: hexutil.Uint64(104), - Random: common.Hash{0x05, 0x10}, - SuggestedFeeRecipient: common.Address{0x04, 0x10}, - GasLimit: uint64(payloadAttributeGasLimit), - Slot: uint64(25), - } - - testEthService := &testEthereumService{synced: true, testExecutableData: testExecutableData, testBlock: testBlock, testBlockValue: big.NewInt(10)} - builderArgs := BuilderArgs{ - sk: sk, - ds: flashbotsextra.NilDbService{}, - relay: &testRelay, - builderSigningDomain: bDomain, - eth: testEthService, - dryRun: false, - ignoreLatePayloadAttributes: false, - validator: nil, - beaconClient: &testBeacon, - limiter: nil, - blockConsumer: flashbotsextra.NilDbService{}, - } - builder, err := NewBuilder(builderArgs) - require.NoError(t, err) - - builder.Start() - defer builder.Stop() - - // Add the transaction to the cache directly - builder.constraintsCache.Put(25, map[common.Hash]*types.ConstraintDecoded{ - preconfTx.Hash(): { - Tx: preconfTx, - }, - preconfTxWithBlob.Hash(): { - Tx: preconfTxWithBlob, - }, - }) - - err = builder.OnPayloadAttribute(testPayloadAttributes) - require.NoError(t, err) - time.Sleep(time.Second * 3) - - require.NotNil(t, testRelay.submittedMsgWithPreconf) - - expectedProposerPubkey, err := utils.HexToPubkey(testBeacon.validator.Pk.String()) - require.NoError(t, err) - - expectedMessage := builderApiV1.BidTrace{ - Slot: uint64(25), - ParentHash: phase0.Hash32{0x02, 0x03}, - BuilderPubkey: builder.builderPublicKey, - ProposerPubkey: expectedProposerPubkey, - ProposerFeeRecipient: feeRecipient, - GasLimit: expectedGasLimit, - GasUsed: uint64(100), - Value: &uint256.Int{0x0a}, - } - copy(expectedMessage.BlockHash[:], hexutil.MustDecode("0x3cce5d0f5c9a7e188e79c35168256e91bec2d98a1140f6701da6ed3c98ea9d04")[:]) - require.NotNil(t, testRelay.submittedMsgWithPreconf.Inner.Bellatrix) - require.Equal(t, expectedMessage, *testRelay.submittedMsgWithPreconf.Inner.Bellatrix.Message) - - expectedExecutionPayload := bellatrix.ExecutionPayload{ - ParentHash: [32]byte(testExecutableData.ParentHash), - FeeRecipient: feeRecipient, - StateRoot: [32]byte(testExecutableData.StateRoot), - ReceiptsRoot: [32]byte(testExecutableData.ReceiptsRoot), - LogsBloom: [256]byte{}, - PrevRandao: [32]byte(testExecutableData.Random), - BlockNumber: testExecutableData.Number, - GasLimit: testExecutableData.GasLimit, - GasUsed: testExecutableData.GasUsed, - Timestamp: testExecutableData.Timestamp, - ExtraData: hexutil.MustDecode("0x0042fafc"), - BaseFeePerGas: [32]byte{0x10}, - BlockHash: expectedMessage.BlockHash, - Transactions: []bellatrix.Transaction{preconfTxByte, preconfTxWithBlobByte}, - } - - require.Equal(t, expectedExecutionPayload, *testRelay.submittedMsgWithPreconf.Inner.Bellatrix.ExecutionPayload) - - expectedSignature, err := utils.HexToSignature("0x97db0496dcfd04ed444b87b6fc1c9e3339a0d35f7c01825ac353812601a72e7e35ef94899a9b03f4d23102214701255805efd0f6552073791ea1c3e10003ae435952f8305f6b89e58d4442ced149d3c33a486f5a390b4b8047e6ea4176059755") - - require.NoError(t, err) - require.Equal(t, expectedSignature, testRelay.submittedMsgWithPreconf.Inner.Bellatrix.Signature) - - require.Equal(t, uint64(25), testRelay.requestedSlot) - - // Clear the submitted message and check that the job will be ran again and but a new message will not be submitted since the hash is the same - testEthService.testBlockValue = big.NewInt(10) - - testRelay.submittedMsgWithPreconf = nil - time.Sleep(2200 * time.Millisecond) - require.Nil(t, testRelay.submittedMsgWithPreconf) - - // Change the hash, expect to get the block - testExecutableData.ExtraData = hexutil.MustDecode("0x0042fafd") - testExecutableData.BlockHash = common.HexToHash("0x38456f6f1f5e76cf83c89ebb8606ff2b700bf02a86a165316c6d7a0c4e6a8614") - testBlock, err = engine.ExecutableDataToBlock(*testExecutableData, preconfTxWithBlob.BlobHashes(), nil) - testEthService.testBlockValue = big.NewInt(10) - require.NoError(t, err) - testEthService.testBlock = testBlock - - time.Sleep(2200 * time.Millisecond) - require.NotNil(t, testRelay.submittedMsgWithPreconf) -} - -func TestSubscribeProposerConstraints(t *testing.T) { - // ------------ Start Builder setup ------------- // - const ( - validatorDesiredGasLimit = 30_000_000 - payloadAttributeGasLimit = 0 - parentBlockGasLimit = 29_000_000 - ) - expectedGasLimit := core.CalcGasLimit(parentBlockGasLimit, validatorDesiredGasLimit) - - vsk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x370bb8c1a6e62b2882f6ec76762a67b39609002076b95aae5b023997cf9b2dc9")) - require.NoError(t, err) - validator := &ValidatorPrivateData{ - sk: vsk, - Pk: hexutil.MustDecode("0xb67d2c11bcab8c4394fc2faa9601d0b99c7f4b37e14911101da7d97077917862eed4563203d34b91b5cf0aa44d6cfa05"), - } - - testBeacon := testBeaconClient{ - validator: validator, - slot: 56, - } - - feeRecipient, _ := utils.HexToAddress("0xabcf8e0d4e9587369b2301d0790347320302cc00") - - relayPort := "31245" - relay := NewRemoteRelay(RelayConfig{Endpoint: "http://localhost:" + relayPort}, nil, true) - - sk, err := bls.SecretKeyFromBytes(hexutil.MustDecode("0x31ee185dad1220a8c88ca5275e64cf5a5cb09cb621cb30df52c9bee8fbaaf8d7")) - require.NoError(t, err) - - bDomain := ssz.ComputeDomain(ssz.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, phase0.Root{}) - - testExecutableData := &engine.ExecutableData{ - ParentHash: common.Hash{0x02, 0x03}, - FeeRecipient: common.Address(feeRecipient), - StateRoot: common.Hash{0x07, 0x16}, - ReceiptsRoot: common.Hash{0x08, 0x20}, - LogsBloom: types.Bloom{}.Bytes(), - Number: uint64(10), - GasLimit: expectedGasLimit, - GasUsed: uint64(100), - Timestamp: uint64(105), - ExtraData: hexutil.MustDecode("0x0042fafc"), - - BaseFeePerGas: big.NewInt(16), - - BlockHash: common.HexToHash("0x68e516c8827b589fcb749a9e672aa16b9643437459508c467f66a9ed1de66a6c"), - Transactions: [][]byte{}, - } - - testBlock, err := engine.ExecutableDataToBlock(*testExecutableData, nil, nil) - require.NoError(t, err) - - testEthService := &testEthereumService{synced: true, testExecutableData: testExecutableData, testBlock: testBlock, testBlockValue: big.NewInt(10)} - - builderArgs := BuilderArgs{ - sk: sk, - ds: flashbotsextra.NilDbService{}, - relay: relay, - builderSigningDomain: bDomain, - eth: testEthService, - dryRun: false, - ignoreLatePayloadAttributes: false, - validator: nil, - beaconClient: &testBeacon, - limiter: nil, - blockConsumer: flashbotsextra.NilDbService{}, - } - - builder, err := NewBuilder(builderArgs) - require.NoError(t, err) - - // ------------ End Builder setup ------------- // - - // Attach the sseHandler to the relay port - mux := http.NewServeMux() - mux.HandleFunc(SubscribeConstraintsPath, sseConstraintsHandler) - - // Wrap the mux with the GzipHandler middleware - // NOTE: In this case, we don't need to create a gzip writer in the handlers, - // by default the `http.ResponseWriter` will implement gzip compression - gzipMux := handlers.CompressHandler(mux) - - http.HandleFunc(SubscribeConstraintsPath, sseConstraintsHandler) - go http.ListenAndServe(":"+relayPort, gzipMux) - - // Constraints should not be available yet - _, ok := builder.constraintsCache.Get(0) - require.Equal(t, false, ok) - - builder.subscribeToRelayForConstraints(builder.relay.Config().Endpoint) - // Wait 2 seconds to save all constraints in cache - time.Sleep(2 * time.Second) - - slots := []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - for _, slot := range slots { - cachedConstraints, ok := builder.constraintsCache.Get(slot) - require.Equal(t, true, ok) - - expectedConstraint := generateMockConstraintsForSlot(slot)[0] - decodedConstraint, err := DecodeConstraints(expectedConstraint) - require.NoError(t, err) - - // Compare the keys of the cachedConstraints and decodedConstraint maps - require.Equal(t, len(cachedConstraints), len(decodedConstraint), "The number of keys in both maps should be the same") - for key := range cachedConstraints { - _, ok := decodedConstraint[key] - require.True(t, ok, fmt.Sprintf("Key %s found in cachedConstraints but not in decodedConstraint", key.String())) - require.Equal(t, cachedConstraints[key].Tx.Data(), decodedConstraint[key].Tx.Data(), "The decodedConstraint Tx should be equal to the cachedConstraints Tx") - } - for key := range decodedConstraint { - _, ok := cachedConstraints[key] - require.True(t, ok, fmt.Sprintf("Key %s found in decodedConstraint but not in cachedConstraints", key.String())) - } - } -} - -func sseConstraintsHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Content-Encoding", "gzip") - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming unsupported!", http.StatusInternalServerError) - return - } - - auth := r.Header.Get("Authorization") - _, err := validateConstraintSubscriptionAuth(auth, 0) - if err != nil { - http.Error(w, err.Error(), http.StatusUnauthorized) - return - } - - for i := 0; i < 256; i++ { - // Generate some duplicated constraints - slot := uint64(i) % 32 - constraints := generateMockConstraintsForSlot(slot) - bytes, err := json.Marshal(constraints) - if err != nil { - log.Error(fmt.Sprintf("Error while marshaling constraints: %v", err)) - return - } - fmt.Fprintf(w, "data: %s\n\n", string(bytes)) - flusher.Flush() - } -} - -// generateMockConstraintsForSlot generates a list of constraints for a given slot -func generateMockConstraintsForSlot(slot uint64) common.SignedConstraintsList { - rawTx := new(common.HexBytes) - err := rawTx.UnmarshalJSON([]byte("\"0x02f876018305da308401312d0085041f1196d2825208940c598786c88883ff5e4f461750fad64d3fae54268804b7ec32d7a2000080c080a0086f02eacec72820be3b117e1edd5bd7ed8956964b28b2d903d2cba53dd13560a06d61ec9ccce6acb31bf21878b9a844e7fdac860c5b7d684f7eb5f38a5945357c\"")) - if err != nil { - fmt.Println("Failed to unmarshal rawTx: ", err) - } - - return common.SignedConstraintsList{ - &common.SignedConstraints{ - Message: common.ConstraintMessage{ - Constraints: []*common.Constraint{{Tx: *rawTx}}, ValidatorIndex: 0, Slot: slot, - }, Signature: phase0.BLSSignature{}, - }, - } -} - -// validateConstraintSubscriptionAuth checks the authentication string data from the Builder, -// and returns its BLS public key if the authentication is valid. -func validateConstraintSubscriptionAuth(auth string, headSlot uint64) (phase0.BLSPubKey, error) { - zeroKey := phase0.BLSPubKey{} - if auth == "" { - return zeroKey, errors.New("authorization header missing") - } - // Authorization: - parts := strings.Split(auth, " ") - if len(parts) != 2 { - return zeroKey, errors.New("ill-formed authorization header") - } - if parts[0] != "BOLT" { - return zeroKey, errors.New("not BOLT authentication scheme") - } - // , - parts = strings.SplitN(parts[1], ",", 2) - if len(parts) != 2 { - return zeroKey, errors.New("ill-formed authorization header") - } - - signature := new(phase0.BLSSignature) - if err := signature.UnmarshalJSON([]byte(parts[0])); err != nil { - fmt.Println("Failed to unmarshal authData: ", err) - return zeroKey, errors.New("ill-formed authorization header") - } - - authDataRaw := []byte(parts[1]) - authData := new(common.ConstraintSubscriptionAuth) - if err := json.Unmarshal(authDataRaw, authData); err != nil { - fmt.Println("Failed to unmarshal authData: ", err) - return zeroKey, errors.New("ill-formed authorization header") - } - - if headSlot != authData.Slot { - return zeroKey, errors.New("invalid head slot") - } - - ok, err := bls.VerifySignatureBytes(authDataRaw, signature[:], authData.PublicKey[:]) - if err != nil || !ok { - return zeroKey, errors.New("invalid signature") - } - return authData.PublicKey, nil -} diff --git a/builder/builder/config.go b/builder/builder/config.go deleted file mode 100644 index 71a90812e..000000000 --- a/builder/builder/config.go +++ /dev/null @@ -1,69 +0,0 @@ -package builder - -import "time" - -type Config struct { - Enabled bool `toml:",omitempty"` - EnableValidatorChecks bool `toml:",omitempty"` - EnableLocalRelay bool `toml:",omitempty"` - SlotsInEpoch uint64 `toml:",omitempty"` - SecondsInSlot uint64 `toml:",omitempty"` - DisableBundleFetcher bool `toml:",omitempty"` - DryRun bool `toml:",omitempty"` - IgnoreLatePayloadAttributes bool `toml:",omitempty"` - BuilderSecretKey string `toml:",omitempty"` - RelaySecretKey string `toml:",omitempty"` - ListenAddr string `toml:",omitempty"` - GenesisForkVersion string `toml:",omitempty"` - BellatrixForkVersion string `toml:",omitempty"` - GenesisValidatorsRoot string `toml:",omitempty"` - BeaconEndpoints []string `toml:",omitempty"` - RemoteRelayEndpoint string `toml:",omitempty"` - SecondaryRemoteRelayEndpoints []string `toml:",omitempty"` - ValidationBlocklist string `toml:",omitempty"` - ValidationUseCoinbaseDiff bool `toml:",omitempty"` - ValidationExcludeWithdrawals bool `toml:",omitempty"` - BuilderRateLimitDuration string `toml:",omitempty"` - BuilderRateLimitMaxBurst int `toml:",omitempty"` - BuilderRateLimitResubmitInterval string `toml:",omitempty"` - BuilderSubmissionOffset time.Duration `toml:",omitempty"` - DiscardRevertibleTxOnErr bool `toml:",omitempty"` - EnableCancellations bool `toml:",omitempty"` - BlockProcessorURL string `toml:",omitempty"` - BuilderMevSidecarEndpoint string `toml:",omitempty"` -} - -// DefaultConfig is the default config for the builder. -var DefaultConfig = Config{ - Enabled: false, - EnableValidatorChecks: false, - EnableLocalRelay: false, - SlotsInEpoch: 32, - SecondsInSlot: 12, - DisableBundleFetcher: false, - DryRun: false, - IgnoreLatePayloadAttributes: false, - BuilderSecretKey: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11", - RelaySecretKey: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11", - ListenAddr: ":28545", - GenesisForkVersion: "0x00000000", - BellatrixForkVersion: "0x02000000", - GenesisValidatorsRoot: "0x0000000000000000000000000000000000000000000000000000000000000000", - BeaconEndpoints: []string{"http://127.0.0.1:5052"}, - RemoteRelayEndpoint: "", - SecondaryRemoteRelayEndpoints: nil, - ValidationBlocklist: "", - ValidationUseCoinbaseDiff: false, - ValidationExcludeWithdrawals: false, - BuilderRateLimitDuration: RateLimitIntervalDefault.String(), - BuilderRateLimitMaxBurst: RateLimitBurstDefault, - DiscardRevertibleTxOnErr: false, - EnableCancellations: false, -} - -// RelayConfig is the config for a single remote relay. -type RelayConfig struct { - Endpoint string - SszEnabled bool - GzipEnabled bool -} diff --git a/builder/builder/eth_service.go b/builder/builder/eth_service.go deleted file mode 100644 index 4d692b022..000000000 --- a/builder/builder/eth_service.go +++ /dev/null @@ -1,114 +0,0 @@ -package builder - -import ( - "errors" - "math/big" - "time" - - "github.com/chainbound/shardmap" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/params" -) - -type IEthereumService interface { - BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error - GetBlockByHash(hash common.Hash) *types.Block - Config() *params.ChainConfig - Synced() bool -} - -type testEthereumService struct { - synced bool - testExecutableData *engine.ExecutableData - testBlock *types.Block - testBlockValue *big.Int - testBlobSidecar []*types.BlobTxSidecar - testBundlesMerged []types.SimulatedBundle - testAllBundles []types.SimulatedBundle - testUsedSbundles []types.UsedSBundle - testPreconfs []*types.Transaction -} - -func (t *testEthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error { - sealedBlockCallback(t.testBlock, t.testBlockValue, t.testBlobSidecar, time.Now(), t.testBundlesMerged, t.testAllBundles, t.testUsedSbundles) - return nil -} - -func (t *testEthereumService) GetBlockByHash(hash common.Hash) *types.Block { return t.testBlock } - -func (t *testEthereumService) Config() *params.ChainConfig { return params.TestChainConfig } - -func (t *testEthereumService) Synced() bool { return t.synced } - -type EthereumService struct { - eth *eth.Ethereum -} - -func NewEthereumService(eth *eth.Ethereum) *EthereumService { - return &EthereumService{eth: eth} -} - -// TODO: we should move to a setup similar to catalyst local blocks & payload ids -func (s *EthereumService) BuildBlock(attrs *types.BuilderPayloadAttributes, sealedBlockCallback miner.BlockHookFn, constraintsCache *shardmap.FIFOMap[uint64, types.HashToConstraintDecoded]) error { - // Send a request to generate a full block in the background. - // The result can be obtained via the returned channel. - args := &miner.BuildPayloadArgs{ - Parent: attrs.HeadHash, - Timestamp: uint64(attrs.Timestamp), - FeeRecipient: attrs.SuggestedFeeRecipient, - GasLimit: attrs.GasLimit, - Random: attrs.Random, - Withdrawals: attrs.Withdrawals, - BeaconRoot: attrs.ParentBeaconBlockRoot, - Slot: attrs.Slot, - BlockHook: sealedBlockCallback, - ConstraintsCache: constraintsCache, - } - - payload, err := s.eth.Miner().BuildPayload(args) - if err != nil { - log.Error("Failed to build payload", "err", err) - return err - } - - resCh := make(chan *engine.ExecutionPayloadEnvelope, 1) - go func() { - resCh <- payload.ResolveFull() - }() - - timer := time.NewTimer(4 * time.Second) - defer timer.Stop() - - select { - case payload := <-resCh: - if payload == nil { - return errors.New("received nil payload from sealing work") - } - return nil - case <-timer.C: - payload.Cancel() - log.Error("timeout waiting for block", "parent hash", attrs.HeadHash, "slot", attrs.Slot) - return errors.New("timeout waiting for block result") - } -} - -func (s *EthereumService) GetBlockByHash(hash common.Hash) *types.Block { - return s.eth.BlockChain().GetBlockByHash(hash) -} - -func (s *EthereumService) Config() *params.ChainConfig { - return s.eth.BlockChain().Config() -} - -func (s *EthereumService) Synced() bool { - return s.eth.Synced() -} - -func (s *EthereumService) Ethereum() *eth.Ethereum { - return s.eth -} diff --git a/builder/builder/eth_service_test.go b/builder/builder/eth_service_test.go deleted file mode 100644 index 000a3185a..000000000 --- a/builder/builder/eth_service_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package builder - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/params" - "github.com/stretchr/testify/require" -) - -func generatePreMergeChain(n int) (*core.Genesis, []*types.Block) { - db := rawdb.NewMemoryDatabase() - config := params.AllEthashProtocolChanges - genesis := &core.Genesis{ - Config: config, - Alloc: types.GenesisAlloc{}, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: big.NewInt(0), - } - gblock := genesis.ToBlock() - engine := ethash.NewFaker() - blocks, _ := core.GenerateChain(config, gblock, engine, db, n, nil) - totalDifficulty := big.NewInt(0) - for _, b := range blocks { - totalDifficulty.Add(totalDifficulty, b.Difficulty()) - } - config.TerminalTotalDifficulty = totalDifficulty - return genesis, blocks -} - -// startEthService creates a full node instance for testing. -func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) (*node.Node, *eth.Ethereum) { - t.Helper() - - n, err := node.New(&node.Config{ - P2P: p2p.Config{ - ListenAddr: "0.0.0.0:0", - NoDiscovery: true, - MaxPeers: 25, - }, - }) - if err != nil { - t.Fatal("can't create node:", err) - } - - ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} - ethservice, err := eth.New(n, ethcfg) - if err != nil { - t.Fatal("can't create eth service:", err) - } - if err := n.Start(); err != nil { - t.Fatal("can't start node:", err) - } - if _, err := ethservice.BlockChain().InsertChain(blocks); err != nil { - n.Close() - t.Fatal("can't import test blocks:", err) - } - time.Sleep(500 * time.Millisecond) // give txpool enough time to consume head event - - ethservice.SetSynced() - return n, ethservice -} - -func TestBuildBlock(t *testing.T) { - genesis, blocks := generatePreMergeChain(10) - n, ethservice := startEthService(t, genesis, blocks) - defer n.Close() - - parent := ethservice.BlockChain().CurrentBlock() - - testPayloadAttributes := &types.BuilderPayloadAttributes{ - Timestamp: hexutil.Uint64(parent.Time + 1), - Random: common.Hash{0x05, 0x10}, - SuggestedFeeRecipient: common.Address{0x04, 0x10}, - GasLimit: uint64(4800000), - Slot: uint64(25), - } - - service := NewEthereumService(ethservice) - service.eth.APIBackend.Miner().SetEtherbase(common.Address{0x05, 0x11}) - - err := service.BuildBlock(testPayloadAttributes, func(block *types.Block, blockValue *big.Int, _ []*types.BlobTxSidecar, _ time.Time, _, _ []types.SimulatedBundle, _ []types.UsedSBundle) { - executableData := engine.BlockToExecutableData(block, blockValue, nil) - require.Equal(t, common.Address{0x05, 0x11}, executableData.ExecutionPayload.FeeRecipient) - require.Equal(t, common.Hash{0x05, 0x10}, executableData.ExecutionPayload.Random) - require.Equal(t, parent.Hash(), executableData.ExecutionPayload.ParentHash) - require.Equal(t, parent.Time+1, executableData.ExecutionPayload.Timestamp) - require.Equal(t, block.ParentHash(), parent.Hash()) - require.Equal(t, block.Hash(), executableData.ExecutionPayload.BlockHash) - require.Equal(t, blockValue.Uint64(), uint64(0)) - }, nil) - - require.NoError(t, err) -} diff --git a/builder/builder/index.go b/builder/builder/index.go deleted file mode 100644 index 8a096dab3..000000000 --- a/builder/builder/index.go +++ /dev/null @@ -1,106 +0,0 @@ -package builder - -import ( - "html/template" -) - -func parseIndexTemplate() (*template.Template, error) { - return template.New("index").Parse(` - - - - - - - - Boost Block Builder - - - - - - - - - - - - -
-
-

- -

- Boost Block Builder -

-

- Pubkey {{ .Pubkey }} -

-

-

    -
  • Genesis fork version {{ .GenesisForkVersion }}
  • -
  • Bellatrix fork version {{ .BellatrixForkVersion }}
  • -
  • Genesis validators root {{ .GenesisValidatorsRoot }}
  • -
-

-

-

    -
  • Builder signing domain {{ .BuilderSigningDomain }}
  • -
  • Proposer signing domain {{ .ProposerSigningDomain }}
  • -
-

- -

-

- -

- -
- -

-

- {{ .ValidatorsStats }} -

-

- -
- -

-

- Best Header -

-
{{ .Header }}
-

- -
- -

-

- Best Payload -

-
{{ .Blocks }}
-

- -
-
- - - -`) -} diff --git a/builder/builder/local_relay.go b/builder/builder/local_relay.go deleted file mode 100644 index ea4c8c46f..000000000 --- a/builder/builder/local_relay.go +++ /dev/null @@ -1,462 +0,0 @@ -package builder - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "html/template" - "net/http" - "strconv" - "strings" - "sync" - "time" - - builderApi "github.com/attestantio/go-builder-client/api" - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - builderSpec "github.com/attestantio/go-builder-client/spec" - eth2ApiV1Bellatrix "github.com/attestantio/go-eth2-client/api/v1/bellatrix" - "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - eth2UtilBellatrix "github.com/attestantio/go-eth2-client/util/bellatrix" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/log" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - "github.com/flashbots/go-boost-utils/utils" - "github.com/gorilla/mux" - "github.com/holiman/uint256" -) - -// TODO (deneb): remove local relay - -type ForkData struct { - GenesisForkVersion string - BellatrixForkVersion string - GenesisValidatorsRoot string -} - -type FullValidatorData struct { - ValidatorData - Timestamp uint64 -} - -type LocalRelay struct { - beaconClient IBeaconClient - - relaySecretKey *bls.SecretKey - relayPublicKey phase0.BLSPubKey - serializedRelayPubkey hexutil.Bytes - - builderSigningDomain phase0.Domain - proposerSigningDomain phase0.Domain - - validatorsLock sync.RWMutex - validators map[PubkeyHex]FullValidatorData - - enableBeaconChecks bool - - bestDataLock sync.Mutex - bestHeader *bellatrix.ExecutionPayloadHeader - bestPayload *bellatrix.ExecutionPayload - profit *uint256.Int - - indexTemplate *template.Template - fd ForkData -} - -func NewLocalRelay(sk *bls.SecretKey, beaconClient IBeaconClient, builderSigningDomain, proposerSigningDomain phase0.Domain, fd ForkData, enableBeaconChecks bool) (*LocalRelay, error) { - blsPk, err := bls.PublicKeyFromSecretKey(sk) - if err != nil { - return nil, err - } - pk, err := utils.BlsPublicKeyToPublicKey(blsPk) - if err != nil { - return nil, err - } - - indexTemplate, err := parseIndexTemplate() - if err != nil { - log.Error("could not parse index template", "err", err) - indexTemplate = nil - } - - return &LocalRelay{ - beaconClient: beaconClient, - - relaySecretKey: sk, - relayPublicKey: pk, - - builderSigningDomain: builderSigningDomain, - proposerSigningDomain: proposerSigningDomain, - serializedRelayPubkey: bls.PublicKeyToBytes(blsPk), - - validators: make(map[PubkeyHex]FullValidatorData), - - enableBeaconChecks: enableBeaconChecks, - - indexTemplate: indexTemplate, - fd: fd, - }, nil -} - -func (r *LocalRelay) Start() error { - r.beaconClient.Start() - return nil -} - -func (r *LocalRelay) Stop() { - r.beaconClient.Stop() -} - -func (r *LocalRelay) SubmitBlock(msg *builderSpec.VersionedSubmitBlockRequest, _ ValidatorData) error { - log.Info("submitting block to local relay", "block", msg.Bellatrix.ExecutionPayload.BlockHash.String()) - return r.submitBlock(msg.Bellatrix) -} - -func (r *LocalRelay) SubmitBlockWithProofs(msg *common.VersionedSubmitBlockRequestWithProofs, _ ValidatorData) error { - panic("Not implemented!") -} - -func (r *LocalRelay) Config() RelayConfig { - // local relay does not need config as it is submitting to its own internal endpoint - return RelayConfig{} -} - -func (r *LocalRelay) submitBlock(msg *builderApiBellatrix.SubmitBlockRequest) error { - header, err := PayloadToPayloadHeader(msg.ExecutionPayload) - if err != nil { - log.Error("could not convert payload to header", "err", err) - return err - } - - r.bestDataLock.Lock() - r.bestHeader = header - r.bestPayload = msg.ExecutionPayload - r.profit = msg.Message.Value - r.bestDataLock.Unlock() - - return nil -} - -func (r *LocalRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Request) { - payload := []builderApiV1.SignedValidatorRegistration{} - if err := json.NewDecoder(req.Body).Decode(&payload); err != nil { - log.Error("could not decode payload", "err", err) - respondError(w, http.StatusBadRequest, "invalid payload") - return - } - - for _, registerRequest := range payload { - if len(registerRequest.Message.Pubkey) != 48 { - respondError(w, http.StatusBadRequest, "invalid pubkey") - return - } - - if len(registerRequest.Signature) != 96 { - respondError(w, http.StatusBadRequest, "invalid signature") - return - } - - ok, err := ssz.VerifySignature(registerRequest.Message, r.builderSigningDomain, registerRequest.Message.Pubkey[:], registerRequest.Signature[:]) - if !ok || err != nil { - log.Error("error verifying signature", "err", err) - respondError(w, http.StatusBadRequest, "invalid signature") - return - } - - // Do not check timestamp before signature, as it would leak validator data - if registerRequest.Message.Timestamp.Unix() > time.Now().Add(10*time.Second).Unix() { - log.Error("invalid timestamp", "timestamp", registerRequest.Message.Timestamp) - respondError(w, http.StatusBadRequest, "invalid payload") - return - } - } - - for _, registerRequest := range payload { - pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) - if !r.beaconClient.isValidator(pubkeyHex) { - respondError(w, http.StatusBadRequest, "not a validator") - return - } - } - - r.validatorsLock.Lock() - defer r.validatorsLock.Unlock() - - for _, registerRequest := range payload { - pubkeyHex := PubkeyHex(registerRequest.Message.Pubkey.String()) - if previousValidatorData, ok := r.validators[pubkeyHex]; ok { - if uint64(registerRequest.Message.Timestamp.Unix()) < previousValidatorData.Timestamp { - respondError(w, http.StatusBadRequest, "invalid timestamp") - return - } - - if uint64(registerRequest.Message.Timestamp.Unix()) == previousValidatorData.Timestamp && (registerRequest.Message.FeeRecipient != previousValidatorData.FeeRecipient || registerRequest.Message.GasLimit != previousValidatorData.GasLimit) { - respondError(w, http.StatusBadRequest, "invalid timestamp") - return - } - } - } - - for _, registerRequest := range payload { - pubkeyHex := PubkeyHex(strings.ToLower(registerRequest.Message.Pubkey.String())) - r.validators[pubkeyHex] = FullValidatorData{ - ValidatorData: ValidatorData{ - Pubkey: pubkeyHex, - FeeRecipient: registerRequest.Message.FeeRecipient, - GasLimit: registerRequest.Message.GasLimit, - }, - Timestamp: uint64(registerRequest.Message.Timestamp.Unix()), - } - - log.Info("registered validator", "pubkey", pubkeyHex, "data", r.validators[pubkeyHex]) - } - - w.WriteHeader(http.StatusOK) -} - -func (r *LocalRelay) GetValidatorForSlot(nextSlot uint64) (ValidatorData, error) { - pubkeyHex, err := r.beaconClient.getProposerForNextSlot(nextSlot) - if err != nil { - return ValidatorData{}, err - } - - r.validatorsLock.RLock() - if vd, ok := r.validators[pubkeyHex]; ok { - r.validatorsLock.RUnlock() - return vd.ValidatorData, nil - } - r.validatorsLock.RUnlock() - log.Info("no local entry for validator", "validator", pubkeyHex) - return ValidatorData{}, errors.New("missing validator") -} - -func (r *LocalRelay) handleGetHeader(w http.ResponseWriter, req *http.Request) { - vars := mux.Vars(req) - slot, err := strconv.Atoi(vars["slot"]) - if err != nil { - respondError(w, http.StatusBadRequest, "incorrect slot") - return - } - parentHashHex := vars["parent_hash"] - pubkeyHex := PubkeyHex(strings.ToLower(vars["pubkey"])) - - // Do not validate slot separately, it will create a race between slot update and proposer key - if nextSlotProposer, err := r.beaconClient.getProposerForNextSlot(uint64(slot)); err != nil || nextSlotProposer != pubkeyHex { - log.Error("getHeader requested for public key other than next slots proposer", "requested", pubkeyHex, "expected", nextSlotProposer) - w.WriteHeader(http.StatusNoContent) - return - } - - // Only check if slot is within a couple of the expected one, otherwise will force validators resync - vd, err := r.GetValidatorForSlot(uint64(slot)) - if err != nil { - respondError(w, http.StatusBadRequest, "unknown validator") - return - } - if vd.Pubkey != pubkeyHex { - respondError(w, http.StatusBadRequest, "unknown validator") - return - } - - r.bestDataLock.Lock() - bestHeader := r.bestHeader - profit := r.profit - r.bestDataLock.Unlock() - - if bestHeader == nil || bestHeader.ParentHash.String() != parentHashHex { - respondError(w, http.StatusBadRequest, "unknown payload") - return - } - - bid := builderApiBellatrix.BuilderBid{ - Header: bestHeader, - Value: profit, - Pubkey: r.relayPublicKey, - } - signature, err := ssz.SignMessage(&bid, r.builderSigningDomain, r.relaySecretKey) - if err != nil { - respondError(w, http.StatusInternalServerError, "internal server error") - return - } - - response := &builderSpec.VersionedSignedBuilderBid{ - Version: spec.DataVersionBellatrix, - Bellatrix: &builderApiBellatrix.SignedBuilderBid{Message: &bid, Signature: signature}, - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - if err := json.NewEncoder(w).Encode(response); err != nil { - respondError(w, http.StatusInternalServerError, "internal server error") - return - } -} - -func (r *LocalRelay) handleGetPayload(w http.ResponseWriter, req *http.Request) { - payload := new(eth2ApiV1Bellatrix.SignedBlindedBeaconBlock) - if err := json.NewDecoder(req.Body).Decode(&payload); err != nil { - log.Error("failed to decode payload", "error", err) - respondError(w, http.StatusBadRequest, "invalid payload") - return - } - - if len(payload.Signature) != 96 { - respondError(w, http.StatusBadRequest, "invalid signature") - return - } - - nextSlotProposerPubkeyHex, err := r.beaconClient.getProposerForNextSlot(uint64(payload.Message.Slot)) - if err != nil { - if r.enableBeaconChecks { - respondError(w, http.StatusBadRequest, "unknown validator") - return - } - } - - nextSlotProposerPubkeyBytes, err := hexutil.Decode(string(nextSlotProposerPubkeyHex)) - if err != nil { - if r.enableBeaconChecks { - respondError(w, http.StatusBadRequest, "unknown validator") - return - } - } - - ok, err := ssz.VerifySignature(payload.Message, r.proposerSigningDomain, nextSlotProposerPubkeyBytes[:], payload.Signature[:]) - if !ok || err != nil { - if r.enableBeaconChecks { - respondError(w, http.StatusBadRequest, "invalid signature") - return - } - } - - r.bestDataLock.Lock() - bestHeader := r.bestHeader - bestPayload := r.bestPayload - r.bestDataLock.Unlock() - - log.Info("Received blinded block", "payload", payload, "bestHeader", bestHeader) - - if bestHeader == nil || bestPayload == nil { - respondError(w, http.StatusInternalServerError, "no payloads") - return - } - - if !ExecutionPayloadHeaderEqual(bestHeader, payload.Message.Body.ExecutionPayloadHeader) { - respondError(w, http.StatusBadRequest, "unknown payload") - return - } - - response := &builderApi.VersionedExecutionPayload{ - Version: spec.DataVersionBellatrix, - Bellatrix: bestPayload, - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - if err := json.NewEncoder(w).Encode(response); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - respondError(w, http.StatusInternalServerError, "internal server error") - return - } -} - -func (r *LocalRelay) handleIndex(w http.ResponseWriter, req *http.Request) { - if r.indexTemplate == nil { - http.Error(w, "not available", http.StatusInternalServerError) - } - - r.validatorsLock.RLock() - noValidators := len(r.validators) - r.validatorsLock.RUnlock() - validatorsStats := fmt.Sprint(noValidators) + " validators registered" - - r.bestDataLock.Lock() - header := r.bestHeader - payload := r.bestPayload - r.bestDataLock.Lock() - - headerData, err := json.MarshalIndent(header, "", " ") - if err != nil { - headerData = []byte{} - } - - payloadData, err := json.MarshalIndent(payload, "", " ") - if err != nil { - payloadData = []byte{} - } - - statusData := struct { - Pubkey string - ValidatorsStats string - GenesisForkVersion string - BellatrixForkVersion string - GenesisValidatorsRoot string - BuilderSigningDomain string - ProposerSigningDomain string - Header string - Blocks string - }{hexutil.Encode(r.serializedRelayPubkey), validatorsStats, r.fd.GenesisForkVersion, r.fd.BellatrixForkVersion, r.fd.GenesisValidatorsRoot, hexutil.Encode(r.builderSigningDomain[:]), hexutil.Encode(r.proposerSigningDomain[:]), string(headerData), string(payloadData)} - - if err := r.indexTemplate.Execute(w, statusData); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } -} - -type httpErrorResp struct { - Code int `json:"code"` - Message string `json:"message"` -} - -func respondError(w http.ResponseWriter, code int, message string) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(code) - if err := json.NewEncoder(w).Encode(httpErrorResp{code, message}); err != nil { - http.Error(w, message, code) - } -} - -func (r *LocalRelay) handleStatus(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) -} - -func ExecutionPayloadHeaderEqual(l, r *bellatrix.ExecutionPayloadHeader) bool { - return l.ParentHash == r.ParentHash && l.FeeRecipient == r.FeeRecipient && l.StateRoot == r.StateRoot && l.ReceiptsRoot == r.ReceiptsRoot && l.LogsBloom == r.LogsBloom && l.PrevRandao == r.PrevRandao && l.BlockNumber == r.BlockNumber && l.GasLimit == r.GasLimit && l.GasUsed == r.GasUsed && l.Timestamp == r.Timestamp && l.BaseFeePerGas == r.BaseFeePerGas && bytes.Equal(l.ExtraData, r.ExtraData) && l.BlockHash == r.BlockHash && l.TransactionsRoot == r.TransactionsRoot -} - -// PayloadToPayloadHeader converts an ExecutionPayload to ExecutionPayloadHeader -func PayloadToPayloadHeader(p *bellatrix.ExecutionPayload) (*bellatrix.ExecutionPayloadHeader, error) { - if p == nil { - return nil, errors.New("nil payload") - } - - var txs []bellatrix.Transaction - txs = append(txs, p.Transactions...) - - transactions := eth2UtilBellatrix.ExecutionPayloadTransactions{Transactions: txs} - txroot, err := transactions.HashTreeRoot() - if err != nil { - return nil, err - } - - return &bellatrix.ExecutionPayloadHeader{ - ParentHash: p.ParentHash, - FeeRecipient: p.FeeRecipient, - StateRoot: p.StateRoot, - ReceiptsRoot: p.ReceiptsRoot, - LogsBloom: p.LogsBloom, - PrevRandao: p.PrevRandao, - BlockNumber: p.BlockNumber, - GasLimit: p.GasLimit, - GasUsed: p.GasUsed, - Timestamp: p.Timestamp, - ExtraData: p.ExtraData, - BaseFeePerGas: p.BaseFeePerGas, - BlockHash: p.BlockHash, - TransactionsRoot: txroot, - }, nil -} diff --git a/builder/builder/local_relay_test.go b/builder/builder/local_relay_test.go deleted file mode 100644 index b187dcf00..000000000 --- a/builder/builder/local_relay_test.go +++ /dev/null @@ -1,292 +0,0 @@ -package builder - -import ( - "bytes" - "encoding/json" - "fmt" - "math/big" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/ethereum/go-ethereum/core" - - "github.com/attestantio/go-builder-client/api" - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - builderSpec "github.com/attestantio/go-builder-client/spec" - eth2ApiV1Bellatrix "github.com/attestantio/go-eth2-client/api/v1/bellatrix" - "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/altair" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/flashbotsextra" - "github.com/ethereum/go-ethereum/log" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - "github.com/holiman/uint256" - "github.com/stretchr/testify/require" - "golang.org/x/time/rate" -) - -const ( - testLocalRelayValidatorGasLimit = 15_000_000 -) - -func newTestBackend(t *testing.T, forkchoiceData *engine.ExecutableData, block *types.Block, blockValue *big.Int) (*Builder, *LocalRelay, *ValidatorPrivateData) { - validator := NewRandomValidator() - sk, _ := bls.GenerateRandomSecretKey() - bDomain := ssz.ComputeDomain(ssz.DomainTypeAppBuilder, [4]byte{0x02, 0x0, 0x0, 0x0}, phase0.Root{}) - genesisValidatorsRoot := phase0.Root(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")) - cDomain := ssz.ComputeDomain(ssz.DomainTypeBeaconProposer, [4]byte{0x02, 0x0, 0x0, 0x0}, genesisValidatorsRoot) - beaconClient := &testBeaconClient{validator: validator} - localRelay, _ := NewLocalRelay(sk, beaconClient, bDomain, cDomain, ForkData{}, true) - ethService := &testEthereumService{synced: true, testExecutableData: forkchoiceData, testBlock: block, testBlockValue: blockValue} - builderArgs := BuilderArgs{ - sk: sk, - ds: flashbotsextra.NilDbService{}, - relay: localRelay, - builderSigningDomain: bDomain, - eth: ethService, - dryRun: false, - ignoreLatePayloadAttributes: false, - validator: nil, - beaconClient: beaconClient, - limiter: nil, - blockConsumer: flashbotsextra.NilDbService{}, - } - backend, _ := NewBuilder(builderArgs) - - backend.limiter = rate.NewLimiter(rate.Inf, 0) - - return backend, localRelay, validator -} - -func testRequest(t *testing.T, localRelay *LocalRelay, method, path string, payload any) *httptest.ResponseRecorder { - var req *http.Request - var err error - - if payload == nil { - req, err = http.NewRequest(method, path, nil) - } else { - payloadBytes, err2 := json.Marshal(payload) - require.NoError(t, err2) - req, err = http.NewRequest(method, path, bytes.NewReader(payloadBytes)) - } - - require.NoError(t, err) - rr := httptest.NewRecorder() - getRouter(localRelay).ServeHTTP(rr, req) - return rr -} - -func TestValidatorRegistration(t *testing.T) { - _, relay, _ := newTestBackend(t, nil, nil, nil) - - v := NewRandomValidator() - payload, err := prepareRegistrationMessage(t, relay.builderSigningDomain, v) - require.NoError(t, err) - - rr := testRequest(t, relay, "POST", "/eth/v1/builder/validators", payload) - require.Equal(t, http.StatusOK, rr.Code) - require.Contains(t, relay.validators, PubkeyHex(v.Pk.String())) - require.Equal(t, FullValidatorData{ValidatorData: ValidatorData{Pubkey: PubkeyHex(v.Pk.String()), FeeRecipient: payload[0].Message.FeeRecipient, GasLimit: payload[0].Message.GasLimit}, Timestamp: uint64(payload[0].Message.Timestamp.Unix())}, relay.validators[PubkeyHex(v.Pk.String())]) - - rr = testRequest(t, relay, "POST", "/eth/v1/builder/validators", payload) - require.Equal(t, http.StatusOK, rr.Code) - - payload[0].Message.Timestamp = payload[0].Message.Timestamp.Add(time.Second) - // Invalid signature - payload[0].Signature[len(payload[0].Signature)-1] = 0x00 - rr = testRequest(t, relay, "POST", "/eth/v1/builder/validators", payload) - require.Equal(t, http.StatusBadRequest, rr.Code) - require.Equal(t, `{"code":400,"message":"invalid signature"}`+"\n", rr.Body.String()) - - // TODO: cover all errors -} - -func prepareRegistrationMessage(t *testing.T, domain phase0.Domain, v *ValidatorPrivateData) ([]builderApiV1.SignedValidatorRegistration, error) { - var pubkey phase0.BLSPubKey - copy(pubkey[:], v.Pk) - require.Equal(t, []byte(v.Pk), pubkey[:]) - - msg := builderApiV1.ValidatorRegistration{ - FeeRecipient: bellatrix.ExecutionAddress{0x42}, - GasLimit: testLocalRelayValidatorGasLimit, - Timestamp: time.Now(), - Pubkey: pubkey, - } - - signature, err := v.Sign(&msg, domain) - require.NoError(t, err) - - return []builderApiV1.SignedValidatorRegistration{{ - Message: &msg, - Signature: signature, - }}, nil -} - -func registerValidator(t *testing.T, v *ValidatorPrivateData, relay *LocalRelay) { - payload, err := prepareRegistrationMessage(t, relay.builderSigningDomain, v) - require.NoError(t, err) - - log.Info("Registering", "payload", payload[0].Message) - rr := testRequest(t, relay, "POST", "/eth/v1/builder/validators", payload) - require.Equal(t, http.StatusOK, rr.Code) - require.Contains(t, relay.validators, PubkeyHex(v.Pk.String())) - require.Equal(t, FullValidatorData{ValidatorData: ValidatorData{Pubkey: PubkeyHex(v.Pk.String()), FeeRecipient: payload[0].Message.FeeRecipient, GasLimit: payload[0].Message.GasLimit}, Timestamp: uint64(payload[0].Message.Timestamp.Unix())}, relay.validators[PubkeyHex(v.Pk.String())]) -} - -func TestGetHeader(t *testing.T) { - forkchoiceData := &engine.ExecutableData{ - ParentHash: common.HexToHash("0xafafafa"), - FeeRecipient: common.Address{0x01}, - LogsBloom: types.Bloom{0x00, 0x05, 0x10}.Bytes(), - BlockHash: common.HexToHash("0x64559c793c74678dff3f5d25aa328526cdb6013f13b6d989d491a8e1d9cac77a"), - BaseFeePerGas: big.NewInt(12), - ExtraData: []byte{}, - GasLimit: 10_000_000, - } - - forkchoiceBlock, err := engine.ExecutableDataToBlock(*forkchoiceData, nil, nil) - require.NoError(t, err) - forkchoiceBlockProfit := big.NewInt(10) - - backend, relay, validator := newTestBackend(t, forkchoiceData, forkchoiceBlock, forkchoiceBlockProfit) - - path := fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) - rr := testRequest(t, relay, "GET", path, nil) - require.Equal(t, `{"code":400,"message":"unknown validator"}`+"\n", rr.Body.String()) - - registerValidator(t, validator, relay) - - rr = testRequest(t, relay, "GET", path, nil) - require.Equal(t, `{"code":400,"message":"unknown payload"}`+"\n", rr.Body.String()) - - path = fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), NewRandomValidator().Pk.String()) - rr = testRequest(t, relay, "GET", path, nil) - require.Equal(t, ``, rr.Body.String()) - require.Equal(t, 204, rr.Code) - - attrs := &types.BuilderPayloadAttributes{} - err = backend.OnPayloadAttribute(attrs) - require.NoError(t, err) - - expectedGasLimit := core.CalcGasLimit(forkchoiceData.GasLimit, testLocalRelayValidatorGasLimit) - require.Equal(t, attrs.GasLimit, expectedGasLimit) - - time.Sleep(2 * time.Second) - - path = fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) - rr = testRequest(t, relay, "GET", path, nil) - require.Equal(t, http.StatusOK, rr.Code) - - bid := new(builderSpec.VersionedSignedBuilderBid) - err = json.Unmarshal(rr.Body.Bytes(), bid) - require.NoError(t, err) - - executionPayload, err := executableDataToExecutionPayload(&engine.ExecutionPayloadEnvelope{ExecutionPayload: forkchoiceData}, spec.DataVersionBellatrix) - require.NoError(t, err) - expectedHeader, err := PayloadToPayloadHeader(executionPayload.Bellatrix) - require.NoError(t, err) - expectedValue, ok := uint256.FromBig(forkchoiceBlockProfit) - require.False(t, ok) - require.EqualValues(t, &builderApiBellatrix.BuilderBid{ - Header: expectedHeader, - Value: expectedValue, - Pubkey: backend.builderPublicKey, - }, bid.Bellatrix.Message) - - require.Equal(t, forkchoiceData.ParentHash.Bytes(), bid.Bellatrix.Message.Header.ParentHash[:], "didn't build on expected parent") - ok, err = ssz.VerifySignature(bid.Bellatrix.Message, backend.builderSigningDomain, backend.builderPublicKey[:], bid.Bellatrix.Signature[:]) - - require.NoError(t, err) - require.True(t, ok) -} - -func TestGetPayload(t *testing.T) { - forkchoiceData := &engine.ExecutableData{ - ParentHash: common.HexToHash("0xafafafa"), - FeeRecipient: common.Address{0x01}, - LogsBloom: types.Bloom{}.Bytes(), - BlockHash: common.HexToHash("0xc4a012b67027b3ab6c00acd31aeee24aa1515d6a5d7e81b0ee2e69517fdc387f"), - BaseFeePerGas: big.NewInt(12), - ExtraData: []byte{}, - } - - forkchoiceBlock, err := engine.ExecutableDataToBlock(*forkchoiceData, nil, nil) - require.NoError(t, err) - forkchoiceBlockProfit := big.NewInt(10) - - backend, relay, validator := newTestBackend(t, forkchoiceData, forkchoiceBlock, forkchoiceBlockProfit) - - registerValidator(t, validator, relay) - err = backend.OnPayloadAttribute(&types.BuilderPayloadAttributes{}) - require.NoError(t, err) - time.Sleep(2 * time.Second) - - path := fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", 0, forkchoiceData.ParentHash.Hex(), validator.Pk.String()) - rr := testRequest(t, relay, "GET", path, nil) - require.Equal(t, http.StatusOK, rr.Code) - - bid := new(builderSpec.VersionedSignedBuilderBid) - err = json.Unmarshal(rr.Body.Bytes(), bid) - require.NoError(t, err) - - blockHash := [32]byte{0x06} - syncCommitteeBits := [64]byte{0x07} - - // Create request payload - msg := ð2ApiV1Bellatrix.BlindedBeaconBlock{ - Slot: 1, - ProposerIndex: 2, - ParentRoot: phase0.Root{0x03}, - StateRoot: phase0.Root{0x04}, - Body: ð2ApiV1Bellatrix.BlindedBeaconBlockBody{ - ETH1Data: &phase0.ETH1Data{ - DepositRoot: phase0.Root{0x05}, - DepositCount: 5, - BlockHash: blockHash[:], - }, - ProposerSlashings: []*phase0.ProposerSlashing{}, - AttesterSlashings: []*phase0.AttesterSlashing{}, - Attestations: []*phase0.Attestation{}, - Deposits: []*phase0.Deposit{}, - VoluntaryExits: []*phase0.SignedVoluntaryExit{}, - SyncAggregate: &altair.SyncAggregate{ - SyncCommitteeBits: syncCommitteeBits[:], - SyncCommitteeSignature: phase0.BLSSignature{0x08}, - }, - ExecutionPayloadHeader: bid.Bellatrix.Message.Header, - }, - } - - // TODO: test wrong signing domain - signature, err := validator.Sign(msg, relay.proposerSigningDomain) - require.NoError(t, err) - - // Call getPayload with invalid signature - rr = testRequest(t, relay, "POST", "/eth/v1/builder/blinded_blocks", ð2ApiV1Bellatrix.SignedBlindedBeaconBlock{ - Message: msg, - Signature: phase0.BLSSignature{0x09}, - }) - require.Equal(t, http.StatusBadRequest, rr.Code) - require.Equal(t, `{"code":400,"message":"invalid signature"}`+"\n", rr.Body.String()) - - // Call getPayload with correct signature - rr = testRequest(t, relay, "POST", "/eth/v1/builder/blinded_blocks", ð2ApiV1Bellatrix.SignedBlindedBeaconBlock{ - Message: msg, - Signature: signature, - }) - - // Verify getPayload response - require.Equal(t, http.StatusOK, rr.Code) - getPayloadResponse := new(api.VersionedExecutionPayload) - err = json.Unmarshal(rr.Body.Bytes(), getPayloadResponse) - require.NoError(t, err) - require.Equal(t, bid.Bellatrix.Message.Header.BlockHash, getPayloadResponse.Bellatrix.BlockHash) -} diff --git a/builder/builder/relay.go b/builder/builder/relay.go deleted file mode 100644 index ef002f6b1..000000000 --- a/builder/builder/relay.go +++ /dev/null @@ -1,263 +0,0 @@ -package builder - -import ( - "context" - "errors" - "fmt" - "net/http" - "strings" - "sync" - "time" - - builderSpec "github.com/attestantio/go-builder-client/spec" - "github.com/attestantio/go-eth2-client/spec" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/flashbots/go-boost-utils/utils" -) - -var ErrValidatorNotFound = errors.New("validator not found") - -type RemoteRelay struct { - client http.Client - config RelayConfig - - localRelay *LocalRelay - - cancellationsEnabled bool - - validatorsLock sync.RWMutex - validatorSyncOngoing bool - lastRequestedSlot uint64 - validatorSlotMap map[uint64]ValidatorData -} - -func NewRemoteRelay(config RelayConfig, localRelay *LocalRelay, cancellationsEnabled bool) *RemoteRelay { - r := &RemoteRelay{ - client: http.Client{Timeout: time.Second}, - localRelay: localRelay, - cancellationsEnabled: cancellationsEnabled, - validatorSyncOngoing: false, - lastRequestedSlot: 0, - validatorSlotMap: make(map[uint64]ValidatorData), - config: config, - } - - err := r.updateValidatorsMap(0, 3) - if err != nil { - log.Error("could not connect to remote relay, continuing anyway", "err", err) - } - return r -} - -type GetValidatorRelayResponse []struct { - Slot uint64 `json:"slot,string"` - Entry struct { - Message struct { - FeeRecipient string `json:"fee_recipient"` - GasLimit uint64 `json:"gas_limit,string"` - Timestamp uint64 `json:"timestamp,string"` - Pubkey string `json:"pubkey"` - } `json:"message"` - Signature string `json:"signature"` - } `json:"entry"` -} - -func (r *RemoteRelay) updateValidatorsMap(currentSlot uint64, retries int) error { - r.validatorsLock.Lock() - if r.validatorSyncOngoing { - r.validatorsLock.Unlock() - return errors.New("sync is ongoing") - } - r.validatorSyncOngoing = true - r.validatorsLock.Unlock() - - log.Info("requesting ", "currentSlot", currentSlot) - newMap, err := r.getSlotValidatorMapFromRelay() - for err != nil && retries > 0 { - log.Error("could not get validators map from relay, retrying", "err", err) - time.Sleep(time.Second) - newMap, err = r.getSlotValidatorMapFromRelay() - retries -= 1 - } - r.validatorsLock.Lock() - r.validatorSyncOngoing = false - if err != nil { - r.validatorsLock.Unlock() - log.Error("could not get validators map from relay", "err", err) - return err - } - - r.validatorSlotMap = newMap - r.lastRequestedSlot = currentSlot - r.validatorsLock.Unlock() - - log.Info("Updated validators", "count", len(newMap), "slot", currentSlot) - return nil -} - -func (r *RemoteRelay) GetValidatorForSlot(nextSlot uint64) (ValidatorData, error) { - // next slot is expected to be the actual chain's next slot, not something requested by the user! - // if not sanitized it will force resync of validator data and possibly is a DoS vector - - r.validatorsLock.RLock() - if r.lastRequestedSlot == 0 || nextSlot/32 > r.lastRequestedSlot/32 { - // Every epoch request validators map - go func() { - err := r.updateValidatorsMap(nextSlot, 1) - if err != nil { - log.Error("could not update validators map", "err", err) - } - }() - } - - vd, found := r.validatorSlotMap[nextSlot] - r.validatorsLock.RUnlock() - - if r.localRelay != nil { - localValidator, err := r.localRelay.GetValidatorForSlot(nextSlot) - if err == nil { - log.Info("Validator registration overwritten by local data", "slot", nextSlot, "validator", localValidator) - return localValidator, nil - } - } - - if found { - return vd, nil - } - - return ValidatorData{}, ErrValidatorNotFound -} - -func (r *RemoteRelay) Start() error { - return nil -} - -func (r *RemoteRelay) Stop() {} - -func (r *RemoteRelay) SubmitBlock(msg *builderSpec.VersionedSubmitBlockRequest, _ ValidatorData) error { - log.Info("submitting block to remote relay", "endpoint", r.config.Endpoint) - endpoint := r.config.Endpoint + "/relay/v1/builder/blocks" - if r.cancellationsEnabled { - endpoint = endpoint + "?cancellations=1" - } - - var code int - var err error - if r.config.SszEnabled { - var bodyBytes []byte - switch msg.Version { - case spec.DataVersionBellatrix: - bodyBytes, err = msg.Bellatrix.MarshalSSZ() - case spec.DataVersionCapella: - bodyBytes, err = msg.Capella.MarshalSSZ() - case spec.DataVersionDeneb: - bodyBytes, err = msg.Deneb.MarshalSSZ() - default: - return fmt.Errorf("unknown data version %d", msg.Version) - } - if err != nil { - return fmt.Errorf("error marshaling ssz: %w", err) - } - log.Debug("submitting block to remote relay", "endpoint", r.config.Endpoint) - code, err = SendSSZRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, bodyBytes, r.config.GzipEnabled) - } else { - switch msg.Version { - case spec.DataVersionBellatrix: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg.Bellatrix, nil) - case spec.DataVersionCapella: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg.Capella, nil) - case spec.DataVersionDeneb: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg.Deneb, nil) - default: - return fmt.Errorf("unknown data version %d", msg.Version) - } - } - - if err != nil { - return fmt.Errorf("error sending http request to relay %s. err: %w", r.config.Endpoint, err) - } - if code > 299 { - return fmt.Errorf("non-ok response code %d from relay %s", code, r.config.Endpoint) - } - - return nil -} - -func (r *RemoteRelay) SubmitBlockWithProofs(msg *common.VersionedSubmitBlockRequestWithProofs, _ ValidatorData) error { - log.Info("submitting block with proofs to remote relay", "endpoint", r.config.Endpoint) - endpoint := r.config.Endpoint + "/relay/v1/builder/blocks_with_proofs" - if r.cancellationsEnabled { - endpoint = endpoint + "?cancellations=1" - } - - var code int - var err error - if r.config.SszEnabled { - panic("ssz not supported for preconfs proofs yet") - } else { - - // BOLT: send event to web demo - if len(msg.Proofs.TransactionHashes) > 0 { - number, _ := msg.Inner.BlockNumber() - message := fmt.Sprintf("sending block %d with proofs to relay (path: %s)", number, "/relay/v1/builder/blocks_with_proofs") - log.Info(message) - EmitBoltDemoEvent(message) - } - - switch msg.Inner.Version { - case spec.DataVersionBellatrix: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg, nil) - case spec.DataVersionCapella: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg, nil) - case spec.DataVersionDeneb: - code, err = SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodPost, endpoint, msg, nil) - default: - return fmt.Errorf("unknown data version %d", msg.Inner.Version) - } - } - - if err != nil { - return fmt.Errorf("error sending http request block with proofs to relay %s. err: %w", r.config.Endpoint, err) - } - if code > 299 { - return fmt.Errorf("non-ok response code %d from relay for block with proofs %s", code, r.config.Endpoint) - } - - return nil -} - -func (r *RemoteRelay) getSlotValidatorMapFromRelay() (map[uint64]ValidatorData, error) { - var dst GetValidatorRelayResponse - code, err := SendHTTPRequest(context.TODO(), *http.DefaultClient, http.MethodGet, r.config.Endpoint+"/relay/v1/builder/validators", nil, &dst) - if err != nil { - return nil, err - } - - if code > 299 { - return nil, fmt.Errorf("non-ok response code %d from relay", code) - } - - res := make(map[uint64]ValidatorData) - for _, data := range dst { - feeRecipient, err := utils.HexToAddress(data.Entry.Message.FeeRecipient) - if err != nil { - log.Error("Ill-formatted fee_recipient from relay", "data", data) - continue - } - - pubkeyHex := PubkeyHex(strings.ToLower(data.Entry.Message.Pubkey)) - - res[data.Slot] = ValidatorData{ - Pubkey: pubkeyHex, - FeeRecipient: feeRecipient, - GasLimit: data.Entry.Message.GasLimit, - } - } - - return res, nil -} - -func (r *RemoteRelay) Config() RelayConfig { - return r.config -} diff --git a/builder/builder/relay_aggregator.go b/builder/builder/relay_aggregator.go deleted file mode 100644 index 4655ebe1a..000000000 --- a/builder/builder/relay_aggregator.go +++ /dev/null @@ -1,169 +0,0 @@ -package builder - -import ( - "errors" - "fmt" - "sync" - - builderSpec "github.com/attestantio/go-builder-client/spec" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" -) - -type RemoteRelayAggregator struct { - relays []IRelay // in order of precedence, primary first - - registrationsCacheLock sync.RWMutex - registrationsCacheSlot uint64 - registrationsCache map[ValidatorData][]IRelay -} - -func NewRemoteRelayAggregator(primary IRelay, secondary []IRelay) *RemoteRelayAggregator { - relays := []IRelay{primary} - return &RemoteRelayAggregator{ - relays: append(relays, secondary...), - } -} - -func (r *RemoteRelayAggregator) Start() error { - for _, relay := range r.relays { - err := relay.Start() - if err != nil { - return err - } - } - return nil -} - -func (r *RemoteRelayAggregator) Stop() { - for _, relay := range r.relays { - relay.Stop() - } -} - -func (r *RemoteRelayAggregator) SubmitBlock(msg *builderSpec.VersionedSubmitBlockRequest, registration ValidatorData) error { - r.registrationsCacheLock.RLock() - defer r.registrationsCacheLock.RUnlock() - - relays, found := r.registrationsCache[registration] - if !found { - return fmt.Errorf("no relays for registration %s", registration.Pubkey) - } - for _, relay := range relays { - go func(relay IRelay) { - err := relay.SubmitBlock(msg, registration) - if err != nil { - log.Error("could not submit block", "err", err) - } - }(relay) - } - - return nil -} - -func (r *RemoteRelayAggregator) SubmitBlockWithProofs(msg *common.VersionedSubmitBlockRequestWithProofs, registration ValidatorData) error { - r.registrationsCacheLock.RLock() - defer r.registrationsCacheLock.RUnlock() - - relays, found := r.registrationsCache[registration] - if !found { - return fmt.Errorf("no relays for registration %s", registration.Pubkey) - } - for _, relay := range relays { - go func(relay IRelay) { - err := relay.SubmitBlockWithProofs(msg, registration) - if err != nil { - log.Error("could not submit block with proofs", "err", err) - } - }(relay) - } - - return nil -} - -type RelayValidatorRegistration struct { - vd ValidatorData - relayI int // index into relays array to preserve relative order -} - -func (r *RemoteRelayAggregator) GetValidatorForSlot(nextSlot uint64) (ValidatorData, error) { - registrationsCh := make(chan *RelayValidatorRegistration, len(r.relays)) - for i, relay := range r.relays { - go func(relay IRelay, relayI int) { - vd, err := relay.GetValidatorForSlot(nextSlot) - if err == nil { - registrationsCh <- &RelayValidatorRegistration{vd: vd, relayI: relayI} - } else if errors.Is(err, ErrValidatorNotFound) { - registrationsCh <- nil - } else { - log.Error("could not get validator registration", "err", err) - registrationsCh <- nil - } - }(relay, i) - } - - topRegistrationCh := make(chan ValidatorData, 1) - go r.updateRelayRegistrations(nextSlot, registrationsCh, topRegistrationCh) - - if vd, ok := <-topRegistrationCh; ok { - return vd, nil - } - return ValidatorData{}, ErrValidatorNotFound -} - -func (r *RemoteRelayAggregator) updateRelayRegistrations(nextSlot uint64, registrationsCh chan *RelayValidatorRegistration, topRegistrationCh chan ValidatorData) { - defer close(topRegistrationCh) - - r.registrationsCacheLock.Lock() - defer r.registrationsCacheLock.Unlock() - - if nextSlot < r.registrationsCacheSlot { - // slot is outdated - return - } - - registrations := make([]*RelayValidatorRegistration, 0, len(r.relays)) - bestRelayIndex := len(r.relays) // relay index of the topmost relay that gave us the registration - bestRelayRegistrationIndex := -1 // index into the registrations for the registration returned by topmost relay - for i := 0; i < len(r.relays); i++ { - relayRegistration := <-registrationsCh - if relayRegistration != nil { - registrations = append(registrations, relayRegistration) - // happy path for primary - if relayRegistration.relayI == 0 { - topRegistrationCh <- relayRegistration.vd - } - if relayRegistration.relayI < bestRelayIndex { - bestRelayIndex = relayRegistration.relayI - bestRelayRegistrationIndex = len(registrations) - 1 - } - } - } - - if len(registrations) == 0 { - return - } - - if bestRelayIndex != 0 { - // if bestRelayIndex == 0 it was already sent - topRegistrationCh <- registrations[bestRelayRegistrationIndex].vd - } - - if nextSlot == r.registrationsCacheSlot { - return - } - - if nextSlot > r.registrationsCacheSlot { - // clear the cache - r.registrationsCache = make(map[ValidatorData][]IRelay) - r.registrationsCacheSlot = nextSlot - } - - for _, relayRegistration := range registrations { - r.registrationsCache[relayRegistration.vd] = append(r.registrationsCache[relayRegistration.vd], r.relays[relayRegistration.relayI]) - } -} - -func (r *RemoteRelayAggregator) Config() RelayConfig { - return RelayConfig{} -} diff --git a/builder/builder/relay_aggregator_test.go b/builder/builder/relay_aggregator_test.go deleted file mode 100644 index d6eebed98..000000000 --- a/builder/builder/relay_aggregator_test.go +++ /dev/null @@ -1,243 +0,0 @@ -package builder - -import ( - "errors" - "testing" - "time" - - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderSpec "github.com/attestantio/go-builder-client/spec" - "github.com/attestantio/go-eth2-client/spec" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" -) - -/* - validator ValidatorData - requestedSlot uint64 - submittedMsg *bellatrix.SubmitBlockRequest -*/ - -type testRelay struct { - sbError error - gvsVd ValidatorData - gvsErr error - - requestedSlot uint64 - submittedMsg *builderSpec.VersionedSubmitBlockRequest - submittedMsgWithPreconf *common.VersionedSubmitBlockRequestWithProofs - submittedMsgCh chan *builderSpec.VersionedSubmitBlockRequest - submittedMsgWithPreconfCh chan *common.VersionedSubmitBlockRequestWithProofs -} - -type testRelayAggBackend struct { - relays []*testRelay - ragg *RemoteRelayAggregator -} - -func newTestRelayAggBackend(numRelay int) *testRelayAggBackend { - testRelays := make([]*testRelay, numRelay) - secondaryRelays := make([]IRelay, numRelay-1) - for i := 0; i < numRelay; i++ { - testRelays[i] = &testRelay{} - if i > 0 { - secondaryRelays[i-1] = testRelays[i] - } - } - ragg := NewRemoteRelayAggregator(testRelays[0], secondaryRelays) - return &testRelayAggBackend{testRelays, ragg} -} - -func (r *testRelay) SubmitBlock(msg *builderSpec.VersionedSubmitBlockRequest, registration ValidatorData) error { - if r.submittedMsgCh != nil { - select { - case r.submittedMsgCh <- msg: - default: - } - } - r.submittedMsg = msg - return r.sbError -} - -func (r *testRelay) SubmitBlockWithProofs(msg *common.VersionedSubmitBlockRequestWithProofs, vd ValidatorData) error { - if r.submittedMsgWithPreconfCh != nil { - select { - case r.submittedMsgWithPreconfCh <- msg: - default: - } - } - r.submittedMsgWithPreconf = msg - return r.sbError -} - -func (r *testRelay) GetValidatorForSlot(nextSlot uint64) (ValidatorData, error) { - r.requestedSlot = nextSlot - return r.gvsVd, r.gvsErr -} - -func (r *testRelay) Start() error { - return nil -} - -func (r *testRelay) Stop() {} - -func (r *testRelay) Config() RelayConfig { - return RelayConfig{} -} - -func TestRemoteRelayAggregator(t *testing.T) { - t.Run("should return error if no relays return validator data", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - // make all error out - for _, r := range backend.relays { - r.gvsErr = errors.New("error!") - } - - // Check getting validator slot - should error out if no relays return - _, err := backend.ragg.GetValidatorForSlot(10) - require.Error(t, ErrValidatorNotFound, err) - }) - - t.Run("should return validator if one relay returns validator data", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - - // If primary returns should not error out - backend.relays[1].gvsErr = errors.New("error!") - backend.relays[2].gvsErr = errors.New("error!") - _, err := backend.ragg.GetValidatorForSlot(10) - require.NoError(t, err) - - // If any returns should not error out - backend.relays[0].gvsErr = errors.New("error!") - backend.relays[2].gvsErr = nil - _, err = backend.ragg.GetValidatorForSlot(10) - require.NoError(t, err) - }) - - t.Run("should return the more important (lower index) relay validator data", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - - // Should return the more important relay if primary fails - backend.relays[0].gvsErr = errors.New("error!") - backend.relays[1].gvsVd.GasLimit = 20 - backend.relays[2].gvsVd.GasLimit = 30 - vd, err := backend.ragg.GetValidatorForSlot(10) - require.NoError(t, err) - require.Equal(t, uint64(20), vd.GasLimit) - - // Should return the primary if it returns - backend.relays[0].gvsErr = nil - backend.relays[0].gvsVd.GasLimit = 10 - vd, err = backend.ragg.GetValidatorForSlot(11) - require.NoError(t, err) - require.Equal(t, uint64(10), vd.GasLimit) - }) - - t.Run("should error submitting to unseen validator data", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - - backend.relays[0].gvsVd.GasLimit = 10 - - vd, err := backend.ragg.GetValidatorForSlot(10) - require.NoError(t, err) - require.Equal(t, uint64(10), vd.GasLimit) - - // let the validator registrations finish - // TODO: notify from the test relays - time.Sleep(10 * time.Millisecond) - - // if submitting for unseen VD should error out - msg := &builderApiBellatrix.SubmitBlockRequest{} - request := &builderSpec.VersionedSubmitBlockRequest{Version: spec.DataVersionBellatrix, Bellatrix: msg} - err = backend.ragg.SubmitBlock(request, ValidatorData{GasLimit: 40}) - require.Error(t, err) - }) - - t.Run("should submit to relay with matching validator data", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - - backend.relays[0].gvsVd.GasLimit = 10 - backend.relays[1].gvsVd.GasLimit = 20 - backend.relays[2].gvsVd.GasLimit = 30 - - vd, err := backend.ragg.GetValidatorForSlot(11) - require.NoError(t, err) - require.Equal(t, uint64(10), vd.GasLimit) - - // let the validator registrations finish - // TODO: notify from the test relays - time.Sleep(10 * time.Millisecond) - - // if submitting for unseen VD should error out - msg := &builderApiBellatrix.SubmitBlockRequest{} - request := &builderSpec.VersionedSubmitBlockRequest{Version: spec.DataVersionBellatrix, Bellatrix: msg} - err = backend.ragg.SubmitBlock(request, ValidatorData{GasLimit: 40}) - require.Error(t, err) - - // should submit to the single pirmary if its the only one matching - backend.relays[0].submittedMsgCh = make(chan *builderSpec.VersionedSubmitBlockRequest, 1) - err = backend.ragg.SubmitBlock(request, ValidatorData{GasLimit: 10}) - require.NoError(t, err) - select { - case rsMsg := <-backend.relays[0].submittedMsgCh: - require.Equal(t, request, rsMsg) - case <-time.After(time.Second): - t.Fail() - } - - // no other relay should have been asked - require.Nil(t, backend.relays[1].submittedMsg) - require.Nil(t, backend.relays[2].submittedMsg) - }) - - t.Run("should submit to relays with matching validator data and drop registrations on next slot", func(t *testing.T) { - backend := newTestRelayAggBackend(3) - - backend.relays[0].gvsVd.GasLimit = 10 - backend.relays[1].gvsVd.GasLimit = 20 - backend.relays[2].gvsVd.GasLimit = 30 - - vd, err := backend.ragg.GetValidatorForSlot(11) - require.NoError(t, err) - require.Equal(t, uint64(10), vd.GasLimit) - - // let the validator registrations finish - time.Sleep(10 * time.Millisecond) - - backend.relays[0].gvsVd.GasLimit = 30 - backend.relays[1].gvsVd.GasLimit = 20 - backend.relays[2].gvsVd.GasLimit = 30 - - // should drop registrations if asked for the next slot - vd, err = backend.ragg.GetValidatorForSlot(12) - require.NoError(t, err) - require.Equal(t, uint64(30), vd.GasLimit) - - time.Sleep(10 * time.Millisecond) - - // should submit to multiple matching relays - backend.relays[0].submittedMsgCh = make(chan *builderSpec.VersionedSubmitBlockRequest, 1) - backend.relays[2].submittedMsgCh = make(chan *builderSpec.VersionedSubmitBlockRequest, 1) - msg := &builderApiBellatrix.SubmitBlockRequest{} - request := &builderSpec.VersionedSubmitBlockRequest{Version: spec.DataVersionBellatrix, Bellatrix: msg} - err = backend.ragg.SubmitBlock(request, ValidatorData{GasLimit: 10}) - require.Error(t, err) - - err = backend.ragg.SubmitBlock(request, ValidatorData{GasLimit: 30}) - require.NoError(t, err) - - select { - case rsMsg := <-backend.relays[0].submittedMsgCh: - require.Equal(t, request, rsMsg) - case <-time.After(time.Second): - t.Fail() - } - - select { - case rsMsg := <-backend.relays[2].submittedMsgCh: - require.Equal(t, request, rsMsg) - case <-time.After(time.Second): - t.Fail() - } - }) -} diff --git a/builder/builder/relay_test.go b/builder/builder/relay_test.go deleted file mode 100644 index 6c3665180..000000000 --- a/builder/builder/relay_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package builder - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/gorilla/mux" - "github.com/stretchr/testify/require" -) - -func TestRemoteRelay(t *testing.T) { - r := mux.NewRouter() - var validatorsHandler func(w http.ResponseWriter, r *http.Request) - r.HandleFunc("/relay/v1/builder/validators", func(w http.ResponseWriter, r *http.Request) { validatorsHandler(w, r) }) - - validatorsHandler = func(w http.ResponseWriter, r *http.Request) { - resp := `[{ - "slot": "123", - "entry": { - "message": { - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "gas_limit": "1", - "timestamp": "1", - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" - }, - "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" - }}, { - "slot": "155", - "entry": { - "message": { - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc10", - "gas_limit": "1", - "timestamp": "1", - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" - }, - "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" - } -}]` - - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(resp)) - } - - srv := httptest.NewServer(r) - relay := NewRemoteRelay(RelayConfig{Endpoint: srv.URL, SszEnabled: false, GzipEnabled: false}, nil, false) - relay.validatorsLock.RLock() - vd, found := relay.validatorSlotMap[123] - relay.validatorsLock.RUnlock() - require.True(t, found) - expectedValidator_123 := ValidatorData{ - Pubkey: "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", - FeeRecipient: bellatrix.ExecutionAddress{0xab, 0xcf, 0x8e, 0xd, 0x4e, 0x95, 0x87, 0x36, 0x9b, 0x23, 0x1, 0xd0, 0x79, 0x3, 0x47, 0x32, 0x3, 0x2, 0xcc, 0x9}, - GasLimit: uint64(1), - } - require.Equal(t, expectedValidator_123, vd) - - vd, err := relay.GetValidatorForSlot(123) - require.NoError(t, err) - require.Equal(t, expectedValidator_123, vd) - - vd, err = relay.GetValidatorForSlot(124) - require.Error(t, err) - require.Equal(t, vd, ValidatorData{}) - - validatorsRequested := make(chan struct{}) - validatorsHandler = func(w http.ResponseWriter, r *http.Request) { - resp := `[{ - "slot": "155", - "entry": { - "message": { - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc10", - "gas_limit": "1", - "timestamp": "1", - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" - }, - "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" - }}, { - "slot": "156", - "entry": { - "message": { - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc11", - "gas_limit": "1", - "timestamp": "1", - "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" - }, - "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" - } -}]` - - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(resp)) - validatorsRequested <- struct{}{} - } - - expectedValidator_155 := ValidatorData{ - Pubkey: "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", - FeeRecipient: bellatrix.ExecutionAddress{0xab, 0xcf, 0x8e, 0xd, 0x4e, 0x95, 0x87, 0x36, 0x9b, 0x23, 0x1, 0xd0, 0x79, 0x3, 0x47, 0x32, 0x3, 0x2, 0xcc, 0x10}, - GasLimit: uint64(1), - } - - expectedValidator_156 := ValidatorData{ - Pubkey: "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", - FeeRecipient: bellatrix.ExecutionAddress{0xab, 0xcf, 0x8e, 0xd, 0x4e, 0x95, 0x87, 0x36, 0x9b, 0x23, 0x1, 0xd0, 0x79, 0x3, 0x47, 0x32, 0x3, 0x2, 0xcc, 0x11}, - GasLimit: uint64(1), - } - - vd, err = relay.GetValidatorForSlot(155) - require.NoError(t, err) - require.Equal(t, expectedValidator_155, vd) - - select { - case <-validatorsRequested: - relay.validatorsLock.RLock() - for i := 0; i < 10 && relay.lastRequestedSlot != 155; i++ { - time.Sleep(time.Millisecond) - } - relay.validatorsLock.RUnlock() - case <-time.After(time.Second): - t.Error("timeout waiting for validator registration request") - } - - vd, err = relay.GetValidatorForSlot(156) - require.NoError(t, err) - require.Equal(t, expectedValidator_156, vd) -} diff --git a/builder/builder/resubmit_utils.go b/builder/builder/resubmit_utils.go deleted file mode 100644 index 4819287e6..000000000 --- a/builder/builder/resubmit_utils.go +++ /dev/null @@ -1,94 +0,0 @@ -package builder - -import ( - "context" - "time" - - "github.com/ethereum/go-ethereum/log" - "golang.org/x/time/rate" -) - -// runResubmitLoop checks for update signal and calls submit respecting provided rate limiter and context -func runResubmitLoop(ctx context.Context, limiter *rate.Limiter, updateSignal <-chan struct{}, submit func(), submitTime time.Time) { - if submitTime.IsZero() { - log.Warn("skipping resubmit loop - zero submit time found") - return - } - - waitUntilSubmitTime := func(waitUntil time.Time) (ok bool, err error) { - now := time.Now().UTC() - if waitUntil.UTC().Before(now) { - waitUntil = now - } - sleepTime := waitUntil.UTC().Sub(now.UTC()) - select { - case <-ctx.Done(): - ok = false - case <-time.After(sleepTime): - ok = true - } - return ok && ctx.Err() == nil, ctx.Err() - } - - if canContinue, err := waitUntilSubmitTime(submitTime); !canContinue { - log.Warn("skipping resubmit loop - cannot continue", "error", err) - return - } - - var res *rate.Reservation - for { - select { - case <-ctx.Done(): - return - case <-updateSignal: - // runBuildingJob is example caller that uses updateSignal channel via block hook that sends signal to - // represent submissions that increase block profit - - res = limiter.Reserve() - if !res.OK() { - log.Warn("resubmit loop failed to make limiter reservation") - return - } - - // check if we could make submission before context ctxDeadline - if ctxDeadline, ok := ctx.Deadline(); ok { - delayDeadline := time.Now().Add(res.Delay()) - if delayDeadline.After(ctxDeadline) { - res.Cancel() - return - } - } - - delay := res.Delay() - if delay == 0 { - submit() - continue - } - - t := time.NewTimer(delay) - select { - case <-t.C: - submit() - continue - case <-ctx.Done(): - res.Cancel() - t.Stop() - return - } - } - } -} - -// runRetryLoop calls retry periodically with the provided interval respecting context cancellation -func runRetryLoop(ctx context.Context, interval time.Duration, retry func()) { - t := time.NewTicker(interval) - defer t.Stop() - for { - select { - case <-ctx.Done(): - return - case <-t.C: - retry() - } - } -} diff --git a/builder/builder/resubmit_utils_test.go b/builder/builder/resubmit_utils_test.go deleted file mode 100644 index 602daef99..000000000 --- a/builder/builder/resubmit_utils_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package builder - -import ( - "context" - "math/rand" - "sort" - "sync" - "testing" - "time" - - "golang.org/x/time/rate" -) - -type submission struct { - t time.Time - v int -} - -func TestResubmitUtils(t *testing.T) { - const ( - totalTime = time.Second - rateLimitTime = 100 * time.Millisecond - resubmitInterval = 10 * time.Millisecond - ) - - ctx, cancel := context.WithTimeout(context.Background(), totalTime) - defer cancel() - limiter := rate.NewLimiter(rate.Every(rateLimitTime), 1) - - var ( - signal = make(chan struct{}, 1) - subMu sync.Mutex - subLast int - subBest int - subAll []submission - ) - - go runResubmitLoop(ctx, limiter, signal, func() { - subMu.Lock() - defer subMu.Unlock() - - if subBest > subLast { - subAll = append(subAll, submission{time.Now(), subBest}) - subLast = subBest - } - }, time.Now()) - - runRetryLoop(ctx, resubmitInterval, func() { - subMu.Lock() - defer subMu.Unlock() - - value := rand.Int() - if value > subBest { - subBest = value - - select { - case signal <- struct{}{}: - default: - } - } - }) - - sorted := sort.SliceIsSorted(subAll, func(i, j int) bool { - return subAll[i].v < subAll[j].v - }) - if !sorted { - t.Error("submissions are not sorted") - } - - for i := 0; i < len(subAll)-1; i++ { - interval := subAll[i+1].t.Sub(subAll[i].t) - if interval+10*time.Millisecond < rateLimitTime { - t.Errorf("submissions are not rate limited: interval %s, limit %s", interval, rateLimitTime) - } - } -} diff --git a/builder/builder/service.go b/builder/builder/service.go deleted file mode 100644 index bf9d7b12d..000000000 --- a/builder/builder/service.go +++ /dev/null @@ -1,329 +0,0 @@ -package builder - -import ( - "errors" - "fmt" - "net/http" - "os" - "strconv" - "strings" - "time" - - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - blockvalidation "github.com/ethereum/go-ethereum/eth/block-validation" - "github.com/ethereum/go-ethereum/flashbotsextra" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/rpc" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - "github.com/flashbots/go-utils/httplogger" - "github.com/gorilla/mux" - "golang.org/x/time/rate" -) - -const ( - _PathStatus = "/eth/v1/builder/status" - _PathRegisterValidator = "/eth/v1/builder/validators" - _PathGetHeader = "/eth/v1/builder/header/{slot:[0-9]+}/{parent_hash:0x[a-fA-F0-9]+}/{pubkey:0x[a-fA-F0-9]+}" - _PathGetPayload = "/eth/v1/builder/blinded_blocks" -) - -type Service struct { - srv *http.Server - builder IBuilder -} - -func (s *Service) Start() error { - if s.srv != nil { - log.Info("Service started") - go s.srv.ListenAndServe() - } - - s.builder.Start() - - return nil -} - -func (s *Service) Stop() error { - if s.srv != nil { - s.srv.Close() - } - s.builder.Stop() - return nil -} - -func (s *Service) PayloadAttributes(payloadAttributes *types.BuilderPayloadAttributes) error { - return s.builder.OnPayloadAttribute(payloadAttributes) -} - -func getRouter(localRelay *LocalRelay) http.Handler { - router := mux.NewRouter() - - // Add routes - router.HandleFunc("/", localRelay.handleIndex).Methods(http.MethodGet) - router.HandleFunc(_PathStatus, localRelay.handleStatus).Methods(http.MethodGet) - router.HandleFunc(_PathRegisterValidator, localRelay.handleRegisterValidator).Methods(http.MethodPost) - router.HandleFunc(_PathGetHeader, localRelay.handleGetHeader).Methods(http.MethodGet) - router.HandleFunc(_PathGetPayload, localRelay.handleGetPayload).Methods(http.MethodPost) - - // Add logging and return router - loggedRouter := httplogger.LoggingMiddleware(router) - return loggedRouter -} - -func getRelayConfig(endpoint string) (RelayConfig, error) { - configs := strings.Split(endpoint, ";") - if len(configs) == 0 { - return RelayConfig{}, fmt.Errorf("empty relay endpoint %s", endpoint) - } - relayUrl := configs[0] - // relay endpoint is configurated in the format URL;ssz=;gzip= - // if any of them are missing, we default the config value to false - var sszEnabled, gzipEnabled bool - var err error - - for _, config := range configs { - if strings.HasPrefix(config, "ssz=") { - sszEnabled, err = strconv.ParseBool(config[4:]) - if err != nil { - log.Info("invalid ssz config for relay", "endpoint", endpoint, "err", err) - } - } else if strings.HasPrefix(config, "gzip=") { - gzipEnabled, err = strconv.ParseBool(config[5:]) - if err != nil { - log.Info("invalid gzip config for relay", "endpoint", endpoint, "err", err) - } - } - } - return RelayConfig{ - Endpoint: relayUrl, - SszEnabled: sszEnabled, - GzipEnabled: gzipEnabled, - }, nil -} - -func NewService(listenAddr string, localRelay *LocalRelay, builder IBuilder) *Service { - var srv *http.Server - if localRelay != nil { - srv = &http.Server{ - Addr: listenAddr, - Handler: getRouter(localRelay), - /* - ReadTimeout: - ReadHeaderTimeout: - WriteTimeout: - IdleTimeout: - */ - } - } - - return &Service{ - srv: srv, - builder: builder, - } -} - -func Register(stack *node.Node, backend *eth.Ethereum, cfg *Config) error { - envBuilderSkBytes, err := hexutil.Decode(cfg.BuilderSecretKey) - if err != nil { - return errors.New("incorrect builder API secret key provided") - } - - genesisForkVersionBytes, err := hexutil.Decode(cfg.GenesisForkVersion) - if err != nil { - return fmt.Errorf("invalid genesisForkVersion: %w", err) - } - - var genesisForkVersion [4]byte - copy(genesisForkVersion[:], genesisForkVersionBytes[:4]) - builderSigningDomain := ssz.ComputeDomain(ssz.DomainTypeAppBuilder, genesisForkVersion, phase0.Root{}) - - genesisValidatorsRoot := phase0.Root(common.HexToHash(cfg.GenesisValidatorsRoot)) - bellatrixForkVersionBytes, err := hexutil.Decode(cfg.BellatrixForkVersion) - if err != nil { - return fmt.Errorf("invalid bellatrixForkVersion: %w", err) - } - - var bellatrixForkVersion [4]byte - copy(bellatrixForkVersion[:], bellatrixForkVersionBytes[:4]) - proposerSigningDomain := ssz.ComputeDomain(ssz.DomainTypeBeaconProposer, bellatrixForkVersion, genesisValidatorsRoot) - - var beaconClient IBeaconClient - if len(cfg.BeaconEndpoints) == 0 { - beaconClient = &NilBeaconClient{} - } else if len(cfg.BeaconEndpoints) == 1 { - beaconClient = NewBeaconClient(cfg.BeaconEndpoints[0], cfg.SlotsInEpoch, cfg.SecondsInSlot) - } else { - beaconClient = NewMultiBeaconClient(cfg.BeaconEndpoints, cfg.SlotsInEpoch, cfg.SecondsInSlot) - } - - var localRelay *LocalRelay - if cfg.EnableLocalRelay { - envRelaySkBytes, err := hexutil.Decode(cfg.RelaySecretKey) - if err != nil { - return errors.New("incorrect builder API secret key provided") - } - - relaySk, err := bls.SecretKeyFromBytes(envRelaySkBytes[:]) - if err != nil { - return errors.New("incorrect builder API secret key provided") - } - - localRelay, err = NewLocalRelay(relaySk, beaconClient, builderSigningDomain, proposerSigningDomain, ForkData{cfg.GenesisForkVersion, cfg.BellatrixForkVersion, cfg.GenesisValidatorsRoot}, cfg.EnableValidatorChecks) - if err != nil { - return fmt.Errorf("failed to create local relay: %w", err) - } - } - - var relay IRelay - if cfg.RemoteRelayEndpoint != "" { - relayConfig, err := getRelayConfig(cfg.RemoteRelayEndpoint) - if err != nil { - return fmt.Errorf("invalid remote relay endpoint: %w", err) - } - relay = NewRemoteRelay(relayConfig, localRelay, cfg.EnableCancellations) - } else if localRelay != nil { - relay = localRelay - } else { - return errors.New("neither local nor remote relay specified") - } - - if len(cfg.SecondaryRemoteRelayEndpoints) > 0 && !(len(cfg.SecondaryRemoteRelayEndpoints) == 1 && cfg.SecondaryRemoteRelayEndpoints[0] == "") { - secondaryRelays := make([]IRelay, len(cfg.SecondaryRemoteRelayEndpoints)) - for i, endpoint := range cfg.SecondaryRemoteRelayEndpoints { - relayConfig, err := getRelayConfig(endpoint) - if err != nil { - return fmt.Errorf("invalid secondary remote relay endpoint: %w", err) - } - secondaryRelays[i] = NewRemoteRelay(relayConfig, nil, cfg.EnableCancellations) - } - relay = NewRemoteRelayAggregator(relay, secondaryRelays) - } - - var validator *blockvalidation.BlockValidationAPI - if cfg.DryRun { - var accessVerifier *blockvalidation.AccessVerifier - if cfg.ValidationBlocklist != "" { - accessVerifier, err = blockvalidation.NewAccessVerifierFromFile(cfg.ValidationBlocklist) - if err != nil { - return fmt.Errorf("failed to load validation blocklist %w", err) - } - } - validator = blockvalidation.NewBlockValidationAPI(backend, accessVerifier, cfg.ValidationUseCoinbaseDiff, cfg.ValidationExcludeWithdrawals) - } - - // Set up builder rate limiter based on environment variables or CLI flags. - // Builder rate limit parameters are flags.BuilderRateLimitDuration and flags.BuilderRateLimitMaxBurst - duration, err := time.ParseDuration(cfg.BuilderRateLimitDuration) - if err != nil { - return fmt.Errorf("error parsing builder rate limit duration - %w", err) - } - - // BuilderRateLimitMaxBurst is set to builder.RateLimitBurstDefault by default if not specified - limiter := rate.NewLimiter(rate.Every(duration), cfg.BuilderRateLimitMaxBurst) - - var builderRateLimitInterval time.Duration - if cfg.BuilderRateLimitResubmitInterval != "" { - d, err := time.ParseDuration(cfg.BuilderRateLimitResubmitInterval) - if err != nil { - return fmt.Errorf("error parsing builder rate limit resubmit interval - %v", err) - } - builderRateLimitInterval = d - } else { - builderRateLimitInterval = RateLimitIntervalDefault - } - - var submissionOffset time.Duration - if offset := cfg.BuilderSubmissionOffset; offset != 0 { - if offset < 0 { - return fmt.Errorf("builder submission offset must be positive") - } else if uint64(offset.Seconds()) > cfg.SecondsInSlot { - return fmt.Errorf("builder submission offset must be less than seconds in slot") - } - submissionOffset = offset - } else { - submissionOffset = SubmissionOffsetFromEndOfSlotSecondsDefault - } - - var blockConsumer flashbotsextra.BlockConsumer - rpcURL := cfg.BlockProcessorURL - if rpcURL != "" { - blockConsumer = flashbotsextra.NewRpcBlockClient(rpcURL) - } else { - log.Warn("Block consumer url is empty. Built block data reporting is essentially disabled") - blockConsumer = flashbotsextra.NilDbService{} - } - - // TODO: move to proper flags - var ds flashbotsextra.IDatabaseService - dbDSN := os.Getenv("FLASHBOTS_POSTGRES_DSN") - if dbDSN != "" { - ds, err = flashbotsextra.NewDatabaseService(dbDSN) - if err != nil { - log.Error("could not connect to the DB", "err", err) - ds = flashbotsextra.NilDbService{} - } - } else { - log.Info("db dsn is not provided, starting nil db svc") - ds = flashbotsextra.NilDbService{} - } - - // Bundle fetcher - if !cfg.DisableBundleFetcher { - mevBundleCh := make(chan []types.MevBundle) - blockNumCh := make(chan int64) - bundleFetcher := flashbotsextra.NewBundleFetcher(backend, ds, blockNumCh, mevBundleCh, true) - backend.RegisterBundleFetcher(bundleFetcher) - go bundleFetcher.Run() - } - - ethereumService := NewEthereumService(backend) - - builderSk, err := bls.SecretKeyFromBytes(envBuilderSkBytes[:]) - if err != nil { - return errors.New("incorrect builder API secret key provided") - } - - builderArgs := BuilderArgs{ - boltCCEndpoint: cfg.BuilderMevSidecarEndpoint, - sk: builderSk, - blockConsumer: blockConsumer, - ds: ds, - dryRun: cfg.DryRun, - eth: ethereumService, - relay: relay, - builderSigningDomain: builderSigningDomain, - builderBlockResubmitInterval: builderRateLimitInterval, - submissionOffsetFromEndOfSlot: submissionOffset, - discardRevertibleTxOnErr: cfg.DiscardRevertibleTxOnErr, - ignoreLatePayloadAttributes: cfg.IgnoreLatePayloadAttributes, - validator: validator, - beaconClient: beaconClient, - limiter: limiter, - } - - builderBackend, err := NewBuilder(builderArgs) - if err != nil { - return fmt.Errorf("failed to create builder backend: %w", err) - } - builderService := NewService(cfg.ListenAddr, localRelay, builderBackend) - - stack.RegisterAPIs([]rpc.API{ - { - Namespace: "builder", - Version: "1.0", - Service: builderService, - Public: true, - Authenticated: true, - }, - }) - - stack.RegisterLifecycle(builderService) - - return nil -} diff --git a/builder/builder/transaction_ssz.go b/builder/builder/transaction_ssz.go deleted file mode 100644 index 015be2fad..000000000 --- a/builder/builder/transaction_ssz.go +++ /dev/null @@ -1,52 +0,0 @@ -package builder - -import ( - ssz "github.com/ferranbt/fastssz" -) - -// The maximum length in bytes of a raw RLP-encoded transaction -var MAX_BYTES_PER_TRANSACTION uint64 = 1_073_741_824 // 2**30 - -// Transaction is a wrapper type of byte slice to implement the ssz.HashRoot interface -type Transaction []byte - -// HashTreeRoot calculates the hash tree root of the transaction, which -// is a list of basic types (byte). -// -// Reference: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization -func (tx *Transaction) HashTreeRoot() ([32]byte, error) { - hasher := ssz.NewHasher() - tx.HashTreeRootWith(hasher) - root, err := hasher.HashRoot() - - return root, err -} - -func (tx *Transaction) HashTreeRootWith(hh ssz.HashWalker) error { - var err error - byteLen := uint64(len(*tx)) - - if byteLen > MAX_BYTES_PER_TRANSACTION { - err = ssz.ErrIncorrectListSize - return err - } - - // Load the bytes of the transaction into the hasher - hh.AppendBytes32(*tx) - // Perform `mix_in_length(merkleize(pack(value), limit=chunk_count(type)), len(value))` - // Reference: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization - // - // The `indx` parameters is set to `0` as we need to consider the whole hh.buf buffer for this. - // In an implementation of more complex types, this parameter would be used to indicate the starting - // index of the buffer to be merkleized. It is used a single buffer to do everything for - // optimization purposes. - hh.MerkleizeWithMixin(0, byteLen, (1073741824+31)/32) - - return nil -} - -func (tx *Transaction) GetTree() (*ssz.Node, error) { - w := &ssz.Wrapper{} - tx.HashTreeRootWith(w) - return w.Node(), nil -} diff --git a/builder/builder/utils.go b/builder/builder/utils.go deleted file mode 100644 index 59bd040df..000000000 --- a/builder/builder/utils.go +++ /dev/null @@ -1,223 +0,0 @@ -package builder - -import ( - "bytes" - "compress/gzip" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "math" - "net/http" - "slices" - "strings" - "time" - - "github.com/attestantio/go-eth2-client/spec/bellatrix" - utilbellatrix "github.com/attestantio/go-eth2-client/util/bellatrix" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - ssz "github.com/ferranbt/fastssz" -) - -var errHTTPErrorResponse = errors.New("HTTP error response") - -func DecodeConstraints(constraints *common.SignedConstraints) (types.HashToConstraintDecoded, error) { - decodedConstraints := make(types.HashToConstraintDecoded) - for _, tx := range constraints.Message.Constraints { - decoded := new(types.Transaction) - if err := decoded.UnmarshalBinary(tx.Tx); err != nil { - return nil, err - } - decodedConstraints[decoded.Hash()] = &types.ConstraintDecoded{Index: tx.Index, Tx: decoded} - } - return decodedConstraints, nil -} - -// SendSSZRequest is a request to send SSZ data to a remote relay. -func SendSSZRequest(ctx context.Context, client http.Client, method, url string, payload []byte, useGzip bool) (code int, err error) { - var req *http.Request - - reader := bytes.NewReader(payload) - - if useGzip { - // Create a new gzip writer - var buf bytes.Buffer - gzipWriter := gzip.NewWriter(&buf) - - // Write the payload to the gzip writer - _, err = reader.WriteTo(gzipWriter) - if err != nil { - return 0, fmt.Errorf("error writing payload to gzip writer: %w", err) - } - - // Flush and close the gzip writer to finalize the compressed data - err = gzipWriter.Close() - if err != nil { - return 0, fmt.Errorf("error closing gzip writer: %w", err) - } - - req, err = http.NewRequest(http.MethodPost, url, &buf) - if err != nil { - return 0, fmt.Errorf("error creating request: %w", err) - } - req.Header.Add("Content-Encoding", "gzip") - } else { - req, err = http.NewRequest(http.MethodPost, url, reader) - if err != nil { - return 0, fmt.Errorf("error creating request: %w", err) - } - } - - req.Header.Add("Content-Type", "application/octet-stream") - resp, err := http.DefaultClient.Do(req) - if err != nil { - return 0, fmt.Errorf("error sending request: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode > 299 { - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return resp.StatusCode, fmt.Errorf("could not read error response body for status code %d: %w", resp.StatusCode, err) - } - return resp.StatusCode, fmt.Errorf("HTTP error response: %d / %s", resp.StatusCode, string(bodyBytes)) - } - return resp.StatusCode, nil -} - -// SendHTTPRequest - prepare and send HTTP request, marshaling the payload if any, and decoding the response if dst is set -func SendHTTPRequest(ctx context.Context, client http.Client, method, url string, payload, dst any) (code int, err error) { - var req *http.Request - - if payload == nil { - req, err = http.NewRequestWithContext(ctx, method, url, nil) - } else { - payloadBytes, err2 := json.Marshal(payload) - if err2 != nil { - return 0, fmt.Errorf("could not marshal request: %w", err2) - } - req, err = http.NewRequestWithContext(ctx, method, url, bytes.NewReader(payloadBytes)) - - // Set headers - req.Header.Add("Content-Type", "application/json") - } - if err != nil { - return 0, fmt.Errorf("could not prepare request: %w", err) - } - - // Execute request - resp, err := client.Do(req) - if err != nil { - return 0, err - } - defer resp.Body.Close() - - if resp.StatusCode == http.StatusNoContent { - return resp.StatusCode, nil - } - - if resp.StatusCode > 299 { - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return resp.StatusCode, fmt.Errorf("could not read error response body for status code %d: %w", resp.StatusCode, err) - } - return resp.StatusCode, fmt.Errorf("%w: %d / %s", errHTTPErrorResponse, resp.StatusCode, string(bodyBytes)) - } - - if dst != nil { - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return resp.StatusCode, fmt.Errorf("could not read response body: %w", err) - } - - if err := json.Unmarshal(bodyBytes, dst); err != nil { - return resp.StatusCode, fmt.Errorf("could not unmarshal response %s: %w", string(bodyBytes), err) - } - } - - return resp.StatusCode, nil -} - -// EmitBoltDemoEvent sends a message to the web demo backend to log an event. -// This is only used for demo purposes and should be removed in production. -func EmitBoltDemoEvent(message string) { - event := strings.NewReader(fmt.Sprintf("{ \"message\": \"BOLT-BUILDER: %s\"}", message)) - eventRes, err := http.Post("http://host.docker.internal:3001/events", "application/json", event) - if err != nil { - log.Error("Failed to send web demo event: ", err) - } - if eventRes != nil { - defer eventRes.Body.Close() - } -} - -func CalculateMerkleMultiProofs( - payloadTransactions types.Transactions, - HashToConstraintDecoded types.HashToConstraintDecoded, -) (inclusionProof *common.InclusionProof, rootNode *ssz.Node, err error) { - constraintsOrderedByIndex, constraintsWithoutIndex, _, _ := types.ParseConstraintsDecoded(HashToConstraintDecoded) - constraints := slices.Concat(constraintsOrderedByIndex, constraintsWithoutIndex) - - // BOLT: generate merkle tree from payload transactions (we need raw RLP bytes for this) - rawTxs := make([]bellatrix.Transaction, len(payloadTransactions)) - for i, tx := range payloadTransactions { - raw, err := tx.WithoutBlobTxSidecar().MarshalBinary() - if err != nil { - log.Warn("[BOLT]: could not marshal transaction", "txHash", tx.Hash(), "err", err) - continue - } - rawTxs[i] = bellatrix.Transaction(raw) - } - - log.Info(fmt.Sprintf("[BOLT]: Generated %d raw transactions for merkle tree", len(rawTxs))) - bellatrixPayloadTxs := utilbellatrix.ExecutionPayloadTransactions{Transactions: rawTxs} - - rootNode, err = bellatrixPayloadTxs.GetTree() - if err != nil { - return nil, nil, fmt.Errorf("could not get tree from transactions: %w", err) - } - - // BOLT: Set the value of nodes. This is MANDATORY for the proof calculation - // to output the leaf correctly. This is also never documented in fastssz. -__- - rootNode.Hash() - - // using our gen index formula: 2 * 2^21 + preconfIndex - baseGeneralizedIndex := int(math.Pow(float64(2), float64(21))) - generalizedIndexes := make([]int, len(constraints)) - transactionHashes := make([]common.Hash, len(constraints)) - - for i, constraint := range constraints { - tx := constraint.Tx - // get the index of the preconfirmed transaction in the block - preconfIndex := slices.IndexFunc(payloadTransactions, func(payloadTx *types.Transaction) bool { return payloadTx.Hash() == tx.Hash() }) - if preconfIndex == -1 { - log.Error(fmt.Sprintf("Preconfirmed transaction %s not found in block", tx.Hash())) - log.Error(fmt.Sprintf("block has %v transactions", len(payloadTransactions))) - continue - } - - generalizedIndex := baseGeneralizedIndex + preconfIndex - generalizedIndexes[i] = generalizedIndex - transactionHashes[i] = tx.Hash() - } - - log.Info(fmt.Sprintf("[BOLT]: Calculating merkle multiproof for %d preconfirmed transaction", - len(constraints))) - - timeStart := time.Now() - multiProof, err := rootNode.ProveMulti(generalizedIndexes) - if err != nil { - return nil, nil, fmt.Errorf("could not calculate merkle multiproof for %d preconf: %w", len(constraints), err) - } - - timeForProofs := time.Since(timeStart) - log.Info(fmt.Sprintf("[BOLT]: Calculated merkle multiproof for %d preconf in %s", len(constraints), timeForProofs)) - - inclusionProof = common.InclusionProofFromMultiProof(multiProof) - inclusionProof.TransactionHashes = transactionHashes - - return -} diff --git a/builder/builder/utils_test.go b/builder/builder/utils_test.go deleted file mode 100644 index 76e6cfdf8..000000000 --- a/builder/builder/utils_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package builder - -import ( - "encoding/json" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - fastSsz "github.com/ferranbt/fastssz" - "github.com/stretchr/testify/require" -) - -func TestGenerateMerkleMultiProofs(t *testing.T) { - // https://etherscan.io/tx/0x138a5f8ba7950521d9dec66ee760b101e0c875039e695c9fcfb34f5ef02a881b - // 0x02f873011a8405f5e10085037fcc60e182520894f7eaaf75cb6ec4d0e2b53964ce6733f54f7d3ffc880b6139a7cbd2000080c080a095a7a3cbb7383fc3e7d217054f861b890a935adc1adf4f05e3a2f23688cf2416a00875cdc45f4395257e44d709d04990349b105c22c11034a60d7af749ffea2765 - // https://etherscan.io/tx/0xfb0ee9de8941c8ad50e6a3d2999cd6ef7a541ec9cb1ba5711b76fcfd1662dfa9 - // 0xf8708305dc6885029332e35883019a2894500b0107e172e420561565c8177c28ac0f62017f8810ffb80e6cc327008025a0e9c0b380c68f040ae7affefd11979f5ed18ae82c00e46aa3238857c372a358eca06b26e179dd2f7a7f1601755249f4cff56690c4033553658f0d73e26c36fe7815 - // https://etherscan.io/tx/0x45e7ee9ba1a1d0145de29a764a33bb7fc5620486b686d68ec8cb3182d137bc90 - // 0xf86c0785028fa6ae0082520894098d880c4753d0332ca737aa592332ed2522cd22880d2f09f6558750008026a0963e58027576b3a8930d7d9b4a49253b6e1a2060e259b2102e34a451d375ce87a063f802538d3efed17962c96fcea431388483bbe3860ea9bb3ef01d4781450fbf - // https://etherscan.io/tx/0x9d48b4a021898a605b7ae49bf93ad88fa6bd7050e9448f12dde064c10f22fe9c - // 0x02f87601836384348477359400850517683ba883019a28943678fce4028b6745eb04fa010d9c8e4b36d6288c872b0f1366ad800080c080a0b6b7aba1954160d081b2c8612e039518b9c46cd7df838b405a03f927ad196158a071d2fb6813e5b5184def6bd90fb5f29e0c52671dea433a7decb289560a58416e - // https://etherscan.io/tx/0x15bd881daa1408b33f67fa4bdeb8acfb0a2289d9b4c6f81eef9bb2bb2e52e780 - Blob Tx - // 0x03f9029c01830299f184b2d05e008507aef40a00832dc6c09468d30f47f19c07bccef4ac7fae2dc12fca3e0dc980b90204ef16e845000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000633b68f5d8d3a86593ebb815b4663bcbe0302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004109de8da2a97e37f2e6dc9f7d50a408f9344d7aa1a925ae53daf7fbef43491a571960d76c0cb926190a9da10df7209fb1ba93cd98b1565a3a2368749d505f90c81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a00141e3a338e30c49ed0501e315bcc45e4edefebed43ab1368a1505461d9cf64901a01e8511e06b17683d89eb57b9869b96b8b611f969f7f56cbc0adc2df7c88a2a07a00910deacf91bba0d74e368d285d311dc5884e7cfe219d85aea5741b2b6e3a2fe - - raw := `["0x03f9029c01830299f184b2d05e008507aef40a00832dc6c09468d30f47f19c07bccef4ac7fae2dc12fca3e0dc980b90204ef16e845000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000633b68f5d8d3a86593ebb815b4663bcbe0302e31382e302d64657600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004109de8da2a97e37f2e6dc9f7d50a408f9344d7aa1a925ae53daf7fbef43491a571960d76c0cb926190a9da10df7209fb1ba93cd98b1565a3a2368749d505f90c81c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0843b9aca00e1a00141e3a338e30c49ed0501e315bcc45e4edefebed43ab1368a1505461d9cf64901a01e8511e06b17683d89eb57b9869b96b8b611f969f7f56cbc0adc2df7c88a2a07a00910deacf91bba0d74e368d285d311dc5884e7cfe219d85aea5741b2b6e3a2fe", "0x02f873011a8405f5e10085037fcc60e182520894f7eaaf75cb6ec4d0e2b53964ce6733f54f7d3ffc880b6139a7cbd2000080c080a095a7a3cbb7383fc3e7d217054f861b890a935adc1adf4f05e3a2f23688cf2416a00875cdc45f4395257e44d709d04990349b105c22c11034a60d7af749ffea2765","0xf8708305dc6885029332e35883019a2894500b0107e172e420561565c8177c28ac0f62017f8810ffb80e6cc327008025a0e9c0b380c68f040ae7affefd11979f5ed18ae82c00e46aa3238857c372a358eca06b26e179dd2f7a7f1601755249f4cff56690c4033553658f0d73e26c36fe7815", "0xf86c0785028fa6ae0082520894098d880c4753d0332ca737aa592332ed2522cd22880d2f09f6558750008026a0963e58027576b3a8930d7d9b4a49253b6e1a2060e259b2102e34a451d375ce87a063f802538d3efed17962c96fcea431388483bbe3860ea9bb3ef01d4781450fbf", "0x02f87601836384348477359400850517683ba883019a28943678fce4028b6745eb04fa010d9c8e4b36d6288c872b0f1366ad800080c080a0b6b7aba1954160d081b2c8612e039518b9c46cd7df838b405a03f927ad196158a071d2fb6813e5b5184def6bd90fb5f29e0c52671dea433a7decb289560a58416e"]` - - byteTxs := make([]*common.HexBytes, 0, 5) - err := json.Unmarshal([]byte(raw), &byteTxs) - require.NoError(t, err) - require.Equal(t, len(byteTxs), 5) - - payloadTransactions := common.Map(byteTxs, func(rawTx *common.HexBytes) *types.Transaction { - transaction := new(types.Transaction) - err = transaction.UnmarshalBinary([]byte(*rawTx)) - return transaction - }) - - require.Equal(t, payloadTransactions[0].Type(), uint8(3)) - require.Equal(t, payloadTransactions[1].Type(), uint8(2)) - - // try out all combinations of "constraints": - // e.g. only [0], then [0, 1], then [1] etc... - // and log which ones are failing and which ones are not - for i := 1; i < len(payloadTransactions)+1; i++ { - t.Logf("--- Trying with %d constraints\n", i) - for _, chosenConstraintTransactions := range combinations(payloadTransactions, i) { - // find the index of the chosen constraints inside payload transactions for debugging - payloadIndexes := make([]int, len(chosenConstraintTransactions)) - for i, chosenConstraint := range chosenConstraintTransactions { - for j, payloadTransaction := range payloadTransactions { - if chosenConstraint.Hash() == payloadTransaction.Hash() { - payloadIndexes[i] = j - break - } - } - } - - constraints := make(types.HashToConstraintDecoded) - for _, tx := range chosenConstraintTransactions { - constraints[tx.Hash()] = &types.ConstraintDecoded{Tx: tx} - } - - inclusionProof, root, err := CalculateMerkleMultiProofs(payloadTransactions, constraints) - require.NoError(t, err) - rootHash := root.Hash() - - leaves := make([][]byte, len(constraints)) - - i := 0 - for _, constraint := range constraints { - if constraint == nil || constraint.Tx == nil { - t.Logf("nil constraint or transaction!") - } - - // Compute the hash tree root for the raw preconfirmed transaction - // and use it as "Leaf" in the proof to be verified against - - withoutBlob, err := constraint.Tx.WithoutBlobTxSidecar().MarshalBinary() - if err != nil { - t.Logf("error marshalling transaction without blob tx sidecar: %v", err) - } - - tx := Transaction(withoutBlob) - txHashTreeRoot, err := tx.HashTreeRoot() - if err != nil { - t.Logf("error calculating hash tree root: %v", err) - } - - leaves[i] = txHashTreeRoot[:] - i++ - } - - hashes := make([][]byte, len(inclusionProof.MerkleHashes)) - for i, hash := range inclusionProof.MerkleHashes { - hashes[i] = []byte(*hash) - } - indexes := make([]int, len(inclusionProof.GeneralizedIndexes)) - for i, index := range inclusionProof.GeneralizedIndexes { - indexes[i] = int(index) - } - - ok, err := fastSsz.VerifyMultiproof(rootHash[:], hashes, leaves, indexes) - if err != nil { - t.Logf("error verifying merkle proof: %v", err) - } - - if !ok { - t.Logf("FAIL with txs: %v", payloadIndexes) - } else { - t.Logf("SUCCESS with txs: %v", payloadIndexes) - } - } - } -} - -// Function to generate combinations of a specific length -func combinations[T any](arr []T, k int) [][]T { - var result [][]T - n := len(arr) - data := make([]T, k) - combine(arr, data, 0, n-1, 0, k, &result) - return result -} - -// Helper function to generate combinations -func combine[T any](arr, data []T, start, end, index, k int, result *[][]T) { - if index == k { - tmp := make([]T, k) - copy(tmp, data) - *result = append(*result, tmp) - return - } - - for i := start; i <= end && end-i+1 >= k-index; i++ { - data[index] = arr[i] - combine(arr, data, i+1, end, index+1, k, result) - } -} diff --git a/builder/builder/validator.go b/builder/builder/validator.go deleted file mode 100644 index 66aa4da5c..000000000 --- a/builder/builder/validator.go +++ /dev/null @@ -1,55 +0,0 @@ -package builder - -import ( - "errors" - "time" - - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/ssz" - "github.com/flashbots/go-boost-utils/utils" -) - -type ValidatorPrivateData struct { - sk *bls.SecretKey - Pk hexutil.Bytes -} - -func NewRandomValidator() *ValidatorPrivateData { - sk, pk, err := bls.GenerateNewKeypair() - if err != nil { - return nil - } - return &ValidatorPrivateData{sk, bls.PublicKeyToBytes(pk)} -} - -func (v *ValidatorPrivateData) Sign(msg ssz.ObjWithHashTreeRoot, d phase0.Domain) (phase0.BLSSignature, error) { - return ssz.SignMessage(msg, d, v.sk) -} - -func (v *ValidatorPrivateData) PrepareRegistrationMessage(feeRecipientHex string) (builderApiV1.SignedValidatorRegistration, error) { - address, err := utils.HexToAddress(feeRecipientHex) - if err != nil { - return builderApiV1.SignedValidatorRegistration{}, err - } - - if len(v.Pk) != 48 { - return builderApiV1.SignedValidatorRegistration{}, errors.New("invalid public key") - } - pubkey := phase0.BLSPubKey{} - copy(pubkey[:], v.Pk) - - msg := &builderApiV1.ValidatorRegistration{ - FeeRecipient: address, - GasLimit: 1000, - Timestamp: time.Now(), - Pubkey: pubkey, - } - signature, err := v.Sign(msg, ssz.DomainBuilder) - if err != nil { - return builderApiV1.SignedValidatorRegistration{}, err - } - return builderApiV1.SignedValidatorRegistration{Message: msg, Signature: signature}, nil -} diff --git a/builder/circle.yml b/builder/circle.yml deleted file mode 100644 index 39ff5d83c..000000000 --- a/builder/circle.yml +++ /dev/null @@ -1,32 +0,0 @@ -machine: - services: - - docker - -dependencies: - cache_directories: - - "~/.ethash" # Cache the ethash DAG generated by hive for consecutive builds - - "~/.docker" # Cache all docker images manually to avoid lengthy rebuilds - override: - # Restore all previously cached docker images - - mkdir -p ~/.docker - - for img in `ls ~/.docker`; do docker load -i ~/.docker/$img; done - - # Pull in and hive, restore cached ethash DAGs and do a dry run - - go get -u github.com/karalabe/hive - - (cd ~/.go_workspace/src/github.com/karalabe/hive && mkdir -p workspace/ethash/ ~/.ethash) - - (cd ~/.go_workspace/src/github.com/karalabe/hive && cp -r ~/.ethash/. workspace/ethash/) - - (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6) - - # Cache all the docker images and the ethash DAGs - - for img in `docker images | grep -v "^" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done - - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash - -test: - override: - # Build Geth and move into a known folder - - make geth - - cp ./build/bin/geth $HOME/geth - - # Run hive and move all generated logs into the public artifacts folder - - (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=go-ethereum:local --override=$HOME/geth --test=. --sim=.) - - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS diff --git a/builder/cmd/abidump/main.go b/builder/cmd/abidump/main.go deleted file mode 100644 index ae1ac6413..000000000 --- a/builder/cmd/abidump/main.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/hex" - "flag" - "fmt" - "os" - "strings" - - "github.com/ethereum/go-ethereum/signer/core/apitypes" - "github.com/ethereum/go-ethereum/signer/fourbyte" -) - -func init() { - flag.Usage = func() { - fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "") - flag.PrintDefaults() - fmt.Fprintln(os.Stderr, ` -Parses the given ABI data and tries to interpret it from the fourbyte database.`) - } -} - -func parse(data []byte) { - db, err := fourbyte.New() - if err != nil { - die(err) - } - messages := apitypes.ValidationMessages{} - db.ValidateCallData(nil, data, &messages) - for _, m := range messages.Messages { - fmt.Printf("%v: %v\n", m.Typ, m.Message) - } -} - -// Example -// ./abidump a9059cbb000000000000000000000000ea0e2dc7d65a50e77fc7e84bff3fd2a9e781ff5c0000000000000000000000000000000000000000000000015af1d78b58c40000 -func main() { - flag.Parse() - - switch { - case flag.NArg() == 1: - hexdata := flag.Arg(0) - data, err := hex.DecodeString(strings.TrimPrefix(hexdata, "0x")) - if err != nil { - die(err) - } - parse(data) - default: - fmt.Fprintln(os.Stderr, "Error: one argument needed") - flag.Usage() - os.Exit(2) - } -} - -func die(args ...interface{}) { - fmt.Fprintln(os.Stderr, args...) - os.Exit(1) -} diff --git a/builder/cmd/abigen/main.go b/builder/cmd/abigen/main.go deleted file mode 100644 index 0149dec52..000000000 --- a/builder/cmd/abigen/main.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "fmt" - "io" - "os" - "regexp" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli/v2" -) - -var ( - // Flags needed by abigen - abiFlag = &cli.StringFlag{ - Name: "abi", - Usage: "Path to the Ethereum contract ABI json to bind, - for STDIN", - } - binFlag = &cli.StringFlag{ - Name: "bin", - Usage: "Path to the Ethereum contract bytecode (generate deploy method)", - } - typeFlag = &cli.StringFlag{ - Name: "type", - Usage: "Struct name for the binding (default = package name)", - } - jsonFlag = &cli.StringFlag{ - Name: "combined-json", - Usage: "Path to the combined-json file generated by compiler, - for STDIN", - } - excFlag = &cli.StringFlag{ - Name: "exc", - Usage: "Comma separated types to exclude from binding", - } - pkgFlag = &cli.StringFlag{ - Name: "pkg", - Usage: "Package name to generate the binding into", - } - outFlag = &cli.StringFlag{ - Name: "out", - Usage: "Output file for the generated binding (default = stdout)", - } - langFlag = &cli.StringFlag{ - Name: "lang", - Usage: "Destination language for the bindings (go)", - Value: "go", - } - aliasFlag = &cli.StringFlag{ - Name: "alias", - Usage: "Comma separated aliases for function and event renaming, e.g. original1=alias1, original2=alias2", - } -) - -var app = flags.NewApp("Ethereum ABI wrapper code generator") - -func init() { - app.Name = "abigen" - app.Flags = []cli.Flag{ - abiFlag, - binFlag, - typeFlag, - jsonFlag, - excFlag, - pkgFlag, - outFlag, - langFlag, - aliasFlag, - } - app.Action = abigen -} - -func abigen(c *cli.Context) error { - utils.CheckExclusive(c, abiFlag, jsonFlag) // Only one source can be selected. - - if c.String(pkgFlag.Name) == "" { - utils.Fatalf("No destination package specified (--pkg)") - } - var lang bind.Lang - switch c.String(langFlag.Name) { - case "go": - lang = bind.LangGo - default: - utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.String(langFlag.Name)) - } - // If the entire solidity code was specified, build and bind based on that - var ( - abis []string - bins []string - types []string - sigs []map[string]string - libs = make(map[string]string) - aliases = make(map[string]string) - ) - if c.String(abiFlag.Name) != "" { - // Load up the ABI, optional bytecode and type name from the parameters - var ( - abi []byte - err error - ) - input := c.String(abiFlag.Name) - if input == "-" { - abi, err = io.ReadAll(os.Stdin) - } else { - abi, err = os.ReadFile(input) - } - if err != nil { - utils.Fatalf("Failed to read input ABI: %v", err) - } - abis = append(abis, string(abi)) - - var bin []byte - if binFile := c.String(binFlag.Name); binFile != "" { - if bin, err = os.ReadFile(binFile); err != nil { - utils.Fatalf("Failed to read input bytecode: %v", err) - } - if strings.Contains(string(bin), "//") { - utils.Fatalf("Contract has additional library references, please use other mode(e.g. --combined-json) to catch library infos") - } - } - bins = append(bins, string(bin)) - - kind := c.String(typeFlag.Name) - if kind == "" { - kind = c.String(pkgFlag.Name) - } - types = append(types, kind) - } else { - // Generate the list of types to exclude from binding - var exclude *nameFilter - if c.IsSet(excFlag.Name) { - var err error - if exclude, err = newNameFilter(strings.Split(c.String(excFlag.Name), ",")...); err != nil { - utils.Fatalf("Failed to parse excludes: %v", err) - } - } - var contracts map[string]*compiler.Contract - - if c.IsSet(jsonFlag.Name) { - var ( - input = c.String(jsonFlag.Name) - jsonOutput []byte - err error - ) - if input == "-" { - jsonOutput, err = io.ReadAll(os.Stdin) - } else { - jsonOutput, err = os.ReadFile(input) - } - if err != nil { - utils.Fatalf("Failed to read combined-json: %v", err) - } - contracts, err = compiler.ParseCombinedJSON(jsonOutput, "", "", "", "") - if err != nil { - utils.Fatalf("Failed to read contract information from json output: %v", err) - } - } - // Gather all non-excluded contract for binding - for name, contract := range contracts { - // fully qualified name is of the form : - nameParts := strings.Split(name, ":") - typeName := nameParts[len(nameParts)-1] - if exclude != nil && exclude.Matches(name) { - fmt.Fprintf(os.Stderr, "excluding: %v\n", name) - continue - } - abi, err := json.Marshal(contract.Info.AbiDefinition) // Flatten the compiler parse - if err != nil { - utils.Fatalf("Failed to parse ABIs from compiler output: %v", err) - } - abis = append(abis, string(abi)) - bins = append(bins, contract.Code) - sigs = append(sigs, contract.Hashes) - types = append(types, typeName) - - // Derive the library placeholder which is a 34 character prefix of the - // hex encoding of the keccak256 hash of the fully qualified library name. - // Note that the fully qualified library name is the path of its source - // file and the library name separated by ":". - libPattern := crypto.Keccak256Hash([]byte(name)).String()[2:36] // the first 2 chars are 0x - libs[libPattern] = typeName - } - } - // Extract all aliases from the flags - if c.IsSet(aliasFlag.Name) { - // We support multi-versions for aliasing - // e.g. - // foo=bar,foo2=bar2 - // foo:bar,foo2:bar2 - re := regexp.MustCompile(`(?:(\w+)[:=](\w+))`) - submatches := re.FindAllStringSubmatch(c.String(aliasFlag.Name), -1) - for _, match := range submatches { - aliases[match[1]] = match[2] - } - } - // Generate the contract binding - code, err := bind.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), lang, libs, aliases) - if err != nil { - utils.Fatalf("Failed to generate ABI binding: %v", err) - } - // Either flush it out to a file or display on the standard output - if !c.IsSet(outFlag.Name) { - fmt.Printf("%s\n", code) - return nil - } - if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil { - utils.Fatalf("Failed to write ABI binding: %v", err) - } - return nil -} - -func main() { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true))) - - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/builder/cmd/abigen/namefilter.go b/builder/cmd/abigen/namefilter.go deleted file mode 100644 index eea5c643c..000000000 --- a/builder/cmd/abigen/namefilter.go +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - "fmt" - "strings" -) - -type nameFilter struct { - fulls map[string]bool // path/to/contract.sol:Type - files map[string]bool // path/to/contract.sol:* - types map[string]bool // *:Type -} - -func newNameFilter(patterns ...string) (*nameFilter, error) { - f := &nameFilter{ - fulls: make(map[string]bool), - files: make(map[string]bool), - types: make(map[string]bool), - } - for _, pattern := range patterns { - if err := f.add(pattern); err != nil { - return nil, err - } - } - return f, nil -} - -func (f *nameFilter) add(pattern string) error { - ft := strings.Split(pattern, ":") - if len(ft) != 2 { - // filenames and types must not include ':' symbol - return fmt.Errorf("invalid pattern: %s", pattern) - } - - file, typ := ft[0], ft[1] - if file == "*" { - f.types[typ] = true - return nil - } else if typ == "*" { - f.files[file] = true - return nil - } - f.fulls[pattern] = true - return nil -} - -func (f *nameFilter) Matches(name string) bool { - ft := strings.Split(name, ":") - if len(ft) != 2 { - // If contract names are always of the fully-qualified form - // :, then this case will never happen. - return false - } - - file, typ := ft[0], ft[1] - // full paths > file paths > types - return f.fulls[name] || f.files[file] || f.types[typ] -} diff --git a/builder/cmd/abigen/namefilter_test.go b/builder/cmd/abigen/namefilter_test.go deleted file mode 100644 index ccee71201..000000000 --- a/builder/cmd/abigen/namefilter_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNameFilter(t *testing.T) { - t.Parallel() - _, err := newNameFilter("Foo") - require.Error(t, err) - _, err = newNameFilter("too/many:colons:Foo") - require.Error(t, err) - - f, err := newNameFilter("a/path:A", "*:B", "c/path:*") - require.NoError(t, err) - - for _, tt := range []struct { - name string - match bool - }{ - {"a/path:A", true}, - {"unknown/path:A", false}, - {"a/path:X", false}, - {"unknown/path:X", false}, - {"any/path:B", true}, - {"c/path:X", true}, - {"c/path:foo:B", false}, - } { - match := f.Matches(tt.name) - if tt.match { - assert.True(t, match, "expected match") - } else { - assert.False(t, match, "expected no match") - } - } -} diff --git a/builder/cmd/bootnode/main.go b/builder/cmd/bootnode/main.go deleted file mode 100644 index 350b85df1..000000000 --- a/builder/cmd/bootnode/main.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// bootnode runs a bootstrap node for the Ethereum Discovery Protocol. -package main - -import ( - "crypto/ecdsa" - "flag" - "fmt" - "net" - "os" - "time" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/nat" - "github.com/ethereum/go-ethereum/p2p/netutil" -) - -func main() { - var ( - listenAddr = flag.String("addr", ":30301", "listen address") - genKey = flag.String("genkey", "", "generate a node key") - writeAddr = flag.Bool("writeaddress", false, "write out the node's public key and quit") - nodeKeyFile = flag.String("nodekey", "", "private key filename") - nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)") - natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|pmp:|extip:)") - netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)") - runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode") - verbosity = flag.Int("verbosity", 3, "log verbosity (0-5)") - vmodule = flag.String("vmodule", "", "log verbosity pattern") - - nodeKey *ecdsa.PrivateKey - err error - ) - flag.Parse() - - glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false)) - slogVerbosity := log.FromLegacyLevel(*verbosity) - glogger.Verbosity(slogVerbosity) - glogger.Vmodule(*vmodule) - log.SetDefault(log.NewLogger(glogger)) - - natm, err := nat.Parse(*natdesc) - if err != nil { - utils.Fatalf("-nat: %v", err) - } - switch { - case *genKey != "": - nodeKey, err = crypto.GenerateKey() - if err != nil { - utils.Fatalf("could not generate key: %v", err) - } - if err = crypto.SaveECDSA(*genKey, nodeKey); err != nil { - utils.Fatalf("%v", err) - } - if !*writeAddr { - return - } - case *nodeKeyFile == "" && *nodeKeyHex == "": - utils.Fatalf("Use -nodekey or -nodekeyhex to specify a private key") - case *nodeKeyFile != "" && *nodeKeyHex != "": - utils.Fatalf("Options -nodekey and -nodekeyhex are mutually exclusive") - case *nodeKeyFile != "": - if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil { - utils.Fatalf("-nodekey: %v", err) - } - case *nodeKeyHex != "": - if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil { - utils.Fatalf("-nodekeyhex: %v", err) - } - } - - if *writeAddr { - fmt.Printf("%x\n", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:]) - os.Exit(0) - } - - var restrictList *netutil.Netlist - if *netrestrict != "" { - restrictList, err = netutil.ParseNetlist(*netrestrict) - if err != nil { - utils.Fatalf("-netrestrict: %v", err) - } - } - - addr, err := net.ResolveUDPAddr("udp", *listenAddr) - if err != nil { - utils.Fatalf("-ResolveUDPAddr: %v", err) - } - conn, err := net.ListenUDP("udp", addr) - if err != nil { - utils.Fatalf("-ListenUDP: %v", err) - } - defer conn.Close() - - db, _ := enode.OpenDB("") - ln := enode.NewLocalNode(db, nodeKey) - - listenerAddr := conn.LocalAddr().(*net.UDPAddr) - if natm != nil && !listenerAddr.IP.IsLoopback() { - natAddr := doPortMapping(natm, ln, listenerAddr) - if natAddr != nil { - listenerAddr = natAddr - } - } - - printNotice(&nodeKey.PublicKey, *listenerAddr) - cfg := discover.Config{ - PrivateKey: nodeKey, - NetRestrict: restrictList, - } - if *runv5 { - if _, err := discover.ListenV5(conn, ln, cfg); err != nil { - utils.Fatalf("%v", err) - } - } else { - if _, err := discover.ListenUDP(conn, ln, cfg); err != nil { - utils.Fatalf("%v", err) - } - } - - select {} -} - -func printNotice(nodeKey *ecdsa.PublicKey, addr net.UDPAddr) { - if addr.IP.IsUnspecified() { - addr.IP = net.IP{127, 0, 0, 1} - } - n := enode.NewV4(nodeKey, addr.IP, 0, addr.Port) - fmt.Println(n.URLv4()) - fmt.Println("Note: you're using cmd/bootnode, a developer tool.") - fmt.Println("We recommend using a regular node as bootstrap node for production deployments.") -} - -func doPortMapping(natm nat.Interface, ln *enode.LocalNode, addr *net.UDPAddr) *net.UDPAddr { - const ( - protocol = "udp" - name = "ethereum discovery" - ) - newLogger := func(external int, internal int) log.Logger { - return log.New("proto", protocol, "extport", external, "intport", internal, "interface", natm) - } - - var ( - intport = addr.Port - extaddr = &net.UDPAddr{IP: addr.IP, Port: addr.Port} - mapTimeout = nat.DefaultMapTimeout - log = newLogger(addr.Port, intport) - ) - addMapping := func() { - // Get the external address. - var err error - extaddr.IP, err = natm.ExternalIP() - if err != nil { - log.Debug("Couldn't get external IP", "err", err) - return - } - // Create the mapping. - p, err := natm.AddMapping(protocol, extaddr.Port, intport, name, mapTimeout) - if err != nil { - log.Debug("Couldn't add port mapping", "err", err) - return - } - if p != uint16(extaddr.Port) { - extaddr.Port = int(p) - log = newLogger(extaddr.Port, intport) - log.Info("NAT mapped alternative port") - } else { - log.Info("NAT mapped port") - } - // Update IP/port information of the local node. - ln.SetStaticIP(extaddr.IP) - ln.SetFallbackUDP(extaddr.Port) - } - - // Perform mapping once, synchronously. - log.Info("Attempting port mapping") - addMapping() - - // Refresh the mapping periodically. - go func() { - refresh := time.NewTimer(mapTimeout) - defer refresh.Stop() - for range refresh.C { - addMapping() - refresh.Reset(mapTimeout) - } - }() - - return extaddr -} diff --git a/builder/cmd/clef/README.md b/builder/cmd/clef/README.md deleted file mode 100644 index cf0926513..000000000 --- a/builder/cmd/clef/README.md +++ /dev/null @@ -1,922 +0,0 @@ -# Clef - -Clef can be used to sign transactions and data and is meant as a(n eventual) replacement for Geth's account management. This allows DApps to not depend on Geth's account management. When a DApp wants to sign data (or a transaction), it can send the content to Clef, which will then provide the user with context and asks for permission to sign the content. If the users grants the signing request, Clef will send the signature back to the DApp. - -This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronized with the chain, or is a node that has no built-in (or limited) account management. - -Clef can run as a daemon on the same machine, off a usb-stick like [USB armory](https://inversepath.com/usbarmory), or even a separate VM in a [QubesOS](https://www.qubes-os.org/) type setup. - -Check out the - -* [CLI tutorial](tutorial.md) for some concrete examples on how Clef works. -* [Setup docs](docs/setup.md) for information on how to configure Clef on QubesOS or USB Armory. -* [Data types](datatypes.md) for details on the communication messages between Clef and an external UI. - -## Command line flags - -Clef accepts the following command line options: - -``` -COMMANDS: - init Initialize the signer, generate secret storage - attest Attest that a js-file is to be used - setpw Store a credential for a keystore file - delpw Remove a credential for a keystore file - gendoc Generate documentation about json-rpc format - help Shows a list of commands or help for one command - -GLOBAL OPTIONS: - --loglevel value log level to emit to the screen (default: 4) - --keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore") - --configdir value Directory for Clef configuration (default: "$HOME/.clef") - --chainid value Chain id to use for signing (1=mainnet, 5=Goerli) (default: 1) - --lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength - --nousb Disables monitoring for and managing USB hardware wallets - --pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm") - --http.addr value HTTP-RPC server listening interface (default: "localhost") - --http.vhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost") - --ipcdisable Disable the IPC-RPC server - --ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it) - --http Enable the HTTP-RPC server - --http.port value HTTP-RPC server listening port (default: 8550) - --signersecret value A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash - --4bytedb-custom value File used for writing new 4byte-identifiers submitted via API (default: "./4byte-custom.json") - --auditlog value File used to emit audit logs. Set to "" to disable (default: "audit.log") - --rules value Path to the rule file to auto-authorize requests with - --stdio-ui Use STDIN/STDOUT as a channel for an external UI. This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user interface, and can be used when Clef is started by an external process. - --stdio-ui-test Mechanism to test interface between Clef and UI. Requires 'stdio-ui'. - --advanced If enabled, issues warnings instead of rejections for suspicious requests. Default off - --suppress-bootwarn If set, does not show the warning during boot - --help, -h show help - --version, -v print the version -``` - -Example: - -``` -$ clef -keystore /my/keystore -chainid 4 -``` - -## Security model - -The security model of Clef is as follows: - -* One critical component (the Clef binary / daemon) is responsible for handling cryptographic operations: signing, private keys, encryption/decryption of keystore files. -* Clef has a well-defined 'external' API. -* The 'external' API is considered UNTRUSTED. -* Clef also communicates with whatever process that invoked the binary, via stdin/stdout. - * This channel is considered 'trusted'. Over this channel, approvals and passwords are communicated. - -The general flow for signing a transaction using e.g. Geth is as follows: -![image](sign_flow.png) - -In this case, `geth` would be started with `--signer http://localhost:8550` and would relay requests to `eth.sendTransaction`. - -## TODOs - -Some snags and todos - -* [ ] Clef should take a startup param "--no-change", for UIs that do not contain the capability to perform changes to things, only approve/deny. Such a UI should be able to start the signer in a more secure mode by telling it that it only wants approve/deny capabilities. -* [x] It would be nice if Clef could collect new 4byte-id:s/method selectors, and have a secondary database for those (`4byte_custom.json`). Users could then (optionally) submit their collections for inclusion upstream. -* [ ] It should be possible to configure Clef to check if an account is indeed known to it, before passing on to the UI. The reason it currently does not, is that it would make it possible to enumerate accounts if it immediately returned "unknown account" (side channel attack). -* [x] It should be possible to configure Clef to auto-allow listing (certain) accounts, instead of asking every time. -* [x] Done Upon startup, Clef should spit out some info to the caller (particularly important when executed in `stdio-ui`-mode), invoking methods with the following info: - * [x] Version info about the signer - * [x] Address of API (HTTP/IPC) - * [ ] List of known accounts -* [ ] Have a default timeout on signing operations, so that if the user has not answered within e.g. 60 seconds, the request is rejected. -* [ ] `account_signRawTransaction` -* [ ] `account_bulkSignTransactions([] transactions)` should - * only exist if enabled via config/flag - * only allow non-data-sending transactions - * all txs must use the same `from`-account - * let the user confirm, showing - * the total amount - * the number of unique recipients - -* Geth todos - - The signer should pass the `Origin` header as call-info to the UI. As of right now, the way that info about the request is put together is a bit of a hack into the HTTP server. This could probably be greatly improved. - - Relay: Geth should be started in `geth --signer localhost:8550`. - - Currently, the Geth APIs use `common.Address` in the arguments to transaction submission (e.g `to` field). This type is 20 `bytes`, and is incapable of carrying checksum information. The signer uses `common.MixedcaseAddress`, which retains the original input. - - The Geth API should switch to use the same type, and relay `to`-account verbatim to the external API. -* [x] Storage - * [x] An encrypted key-value storage should be implemented. - * See [rules.md](rules.md) for more info about this. -* Another potential thing to introduce is pairing. - * To prevent spurious requests which users just accept, implement a way to "pair" the caller with the signer (external API). - * Thus Geth/cpp would cryptographically handshake and afterwards the caller would be allowed to make signing requests. - * This feature would make the addition of rules less dangerous. - -* Wallets / accounts. Add API methods for wallets. - -## Communication - -### External API - -Clef listens to HTTP requests on `http.addr`:`http.port` (or to IPC on `ipcpath`), with the same JSON-RPC standard as Geth. The messages are expected to be [JSON-RPC 2.0 standard](https://www.jsonrpc.org/specification). - -Some of these calls can require user interaction. Clients must be aware that responses may be delayed significantly or may never be received if a user decides to ignore the confirmation request. - -The External API is **untrusted**: it does not accept credentials, nor does it expect that requests have any authority. - -### Internal UI API - -Clef has one native console-based UI, for operation without any standalone tools. However, there is also an API to communicate with an external UI. To enable that UI, the signer needs to be executed with the `--stdio-ui` option, which allocates `stdin` / `stdout` for the UI API. - -An example (insecure) proof-of-concept of has been implemented in `pythonsigner.py`. - -The model is as follows: - -* The user starts the UI app (`pythonsigner.py`). -* The UI app starts `clef` with `--stdio-ui`, and listens to the -process output for confirmation-requests. -* `clef` opens the external HTTP API. -* When the `signer` receives requests, it sends a JSON-RPC request via `stdout`. -* The UI app prompts the user accordingly, and responds to `clef`. -* `clef` signs (or not), and responds to the original request. - -## External API - -See the [external API changelog](extapi_changelog.md) for information about changes to this API. - -### Encoding -- number: positive integers that are hex encoded -- data: hex encoded data -- string: ASCII string - -All hex encoded values must be prefixed with `0x`. - -### account_new - -#### Create new password protected account - -The signer will generate a new private key, encrypt it according to [web3 keystore spec](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) and store it in the keystore directory. -The client is responsible for creating a backup of the keystore. If the keystore is lost there is no method of retrieving lost accounts. - -#### Arguments - -None - -#### Result - - address [string]: account address that is derived from the generated key - -#### Sample call -```json -{ - "id": 0, - "jsonrpc": "2.0", - "method": "account_new", - "params": [] -} -``` -Response -```json -{ - "id": 0, - "jsonrpc": "2.0", - "result": "0xbea9183f8f4f03d427f6bcea17388bdff1cab133" -} -``` - -### account_list - -#### List available accounts - List all accounts that this signer currently manages - -#### Arguments - -None - -#### Result - - array with account records: - - account.address [string]: account address that is derived from the generated key - -#### Sample call -```json -{ - "id": 1, - "jsonrpc": "2.0", - "method": "account_list" -} -``` -Response -```json -{ - "id": 1, - "jsonrpc": "2.0", - "result": [ - "0xafb2f771f58513609765698f65d3f2f0224a956f", - "0xbea9183f8f4f03d427f6bcea17388bdff1cab133" - ] -} -``` - -### account_signTransaction - -#### Sign transactions - Signs a transaction and responds with the signed transaction in RLP-encoded and JSON forms. - -#### Arguments - 1. transaction object: - - `from` [address]: account to send the transaction from - - `to` [address]: receiver account. If omitted or `0x`, will cause contract creation. - - `gas` [number]: maximum amount of gas to burn - - `gasPrice` [number]: gas price - - `value` [number:optional]: amount of Wei to send with the transaction - - `data` [data:optional]: input data - - `nonce` [number]: account nonce - 1. method signature [string:optional] - - The method signature, if present, is to aid decoding the calldata. Should consist of `methodname(paramtype,...)`, e.g. `transfer(uint256,address)`. The signer may use this data to parse the supplied calldata, and show the user. The data, however, is considered totally untrusted, and reliability is not expected. - - -#### Result - - raw [data]: signed transaction in RLP encoded form - - tx [json]: signed transaction in JSON form - -#### Sample call -```json -{ - "id": 2, - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", - "gas": "0x55555", - "gasPrice": "0x1234", - "input": "0xabcd", - "nonce": "0x0", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "value": "0x1234" - } - ] -} -``` -Response - -```json -{ - "jsonrpc": "2.0", - "id": 2, - "result": { - "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "tx": { - "nonce": "0x0", - "gasPrice": "0x1234", - "gas": "0x55555", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "value": "0x1234", - "input": "0xabcd", - "v": "0x26", - "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", - "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" - } - } -} -``` -#### Sample call with ABI-data - - -```json -{ - "id": 67, - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from": "0x694267f14675d7e1b9494fd8d72fefe1755710fa", - "gas": "0x333", - "gasPrice": "0x1", - "nonce": "0x0", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "value": "0x0", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - }, - "safeSend(address)" - ] -} -``` -Response - -```json -{ - "jsonrpc": "2.0", - "id": 67, - "result": { - "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "tx": { - "nonce": "0x0", - "gasPrice": "0x1", - "gas": "0x333", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "value": "0x0", - "input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", - "v": "0x26", - "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", - "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" - } - } -} -``` - -Bash example: -```bash -> curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ - -{"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}} -``` - -### account_signData - -#### Sign data - Signs a chunk of data and returns the calculated signature. - -#### Arguments - - content type [string]: type of signed data - - `text/validator`: hex data with custom validator defined in a contract - - `application/clique`: [clique](https://github.com/ethereum/EIPs/issues/225) headers - - `text/plain`: simple hex data validated by `account_ecRecover` - - account [address]: account to sign with - - data [object]: data to sign - -#### Result - - calculated signature [data] - -#### Sample call -```json -{ - "id": 3, - "jsonrpc": "2.0", - "method": "account_signData", - "params": [ - "data/plain", - "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", - "0xaabbccdd" - ] -} -``` -Response - -```json -{ - "id": 3, - "jsonrpc": "2.0", - "result": "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c" -} -``` - -### account_signTypedData - -#### Sign data - Signs a chunk of structured data conformant to [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and returns the calculated signature. - -#### Arguments - - account [address]: account to sign with - - data [object]: data to sign - -#### Result - - calculated signature [data] - -#### Sample call -```json -{ - "id": 68, - "jsonrpc": "2.0", - "method": "account_signTypedData", - "params": [ - "0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826", - { - "types": { - "EIP712Domain": [ - { - "name": "name", - "type": "string" - }, - { - "name": "version", - "type": "string" - }, - { - "name": "chainId", - "type": "uint256" - }, - { - "name": "verifyingContract", - "type": "address" - } - ], - "Person": [ - { - "name": "name", - "type": "string" - }, - { - "name": "wallet", - "type": "address" - } - ], - "Mail": [ - { - "name": "from", - "type": "Person" - }, - { - "name": "to", - "type": "Person" - }, - { - "name": "contents", - "type": "string" - } - ] - }, - "primaryType": "Mail", - "domain": { - "name": "Ether Mail", - "version": "1", - "chainId": 1, - "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" - }, - "message": { - "from": { - "name": "Cow", - "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" - }, - "to": { - "name": "Bob", - "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" - }, - "contents": "Hello, Bob!" - } - } - ] -} -``` -Response - -```json -{ - "id": 1, - "jsonrpc": "2.0", - "result": "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" -} -``` - -### account_ecRecover - -#### Recover the signing address - -Derive the address from the account that was used to sign data with content type `text/plain` and the signature. - -#### Arguments - - data [data]: data that was signed - - signature [data]: the signature to verify - -#### Result - - derived account [address] - -#### Sample call -```json -{ - "id": 4, - "jsonrpc": "2.0", - "method": "account_ecRecover", - "params": [ - "0xaabbccdd", - "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c" - ] -} -``` -Response - -```json -{ - "id": 4, - "jsonrpc": "2.0", - "result": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db" -} -``` - -### account_version - -#### Get external API version - -Get the version of the external API used by Clef. - -#### Arguments - -None - -#### Result - -* external API version [string] - -#### Sample call -```json -{ - "id": 0, - "jsonrpc": "2.0", - "method": "account_version", - "params": [] -} -``` - -Response -```json -{ - "id": 0, - "jsonrpc": "2.0", - "result": "6.0.0" -} -``` - -## UI API - -These methods needs to be implemented by a UI listener. - -By starting the signer with the switch `--stdio-ui-test`, the signer will invoke all known methods, and expect the UI to respond with -denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented. -See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'. - -All methods in this API use object-based parameters, so that there can be no mixup of parameters: each piece of data is accessed by key. - -See the [ui API changelog](intapi_changelog.md) for information about changes to this API. - -OBS! A slight deviation from `json` standard is in place: every request and response should be confined to a single line. -Whereas the `json` specification allows for linebreaks, linebreaks __should not__ be used in this communication channel, to make -things simpler for both parties. - -### ApproveTx / `ui_approveTx` - -Invoked when there's a transaction for approval. - - -#### Sample call - -Here's a method invocation: -```bash - -curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ -``` -Results in the following invocation on the UI: -```json - -{ - "jsonrpc": "2.0", - "id": 1, - "method": "ui_approveTx", - "params": [ - { - "transaction": { - "from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa", - "to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "gas": "0x333", - "gasPrice": "0x1", - "value": "0x0", - "nonce": "0x0", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", - "input": null - }, - "call_info": [ - { - "type": "WARNING", - "message": "Invalid checksum on to-address" - }, - { - "type": "Info", - "message": "safeSend(address: 0x0000000000000000000000000000000000000012)" - } - ], - "meta": { - "remote": "127.0.0.1:48486", - "local": "localhost:8550", - "scheme": "HTTP/1.1" - } - } - ] -} - -``` - -The same method invocation, but with invalid data: -```bash - -curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000002000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ -``` - -```json - -{ - "jsonrpc": "2.0", - "id": 1, - "method": "ui_approveTx", - "params": [ - { - "transaction": { - "from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa", - "to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "gas": "0x333", - "gasPrice": "0x1", - "value": "0x0", - "nonce": "0x0", - "data": "0x4401a6e40000000000000002000000000000000000000000000000000000000000000012", - "input": null - }, - "call_info": [ - { - "type": "WARNING", - "message": "Invalid checksum on to-address" - }, - { - "type": "WARNING", - "message": "Transaction data did not match ABI-interface: WARNING: Supplied data is stuffed with extra data. \nWant 0000000000000002000000000000000000000000000000000000000000000012\nHave 0000000000000000000000000000000000000000000000000000000000000012\nfor method safeSend(address)" - } - ], - "meta": { - "remote": "127.0.0.1:48492", - "local": "localhost:8550", - "scheme": "HTTP/1.1" - } - } - ] -} - - -``` - -One which has missing `to`, but with no `data`: - - -```json - -{ - "jsonrpc": "2.0", - "id": 3, - "method": "ui_approveTx", - "params": [ - { - "transaction": { - "from": "", - "to": null, - "gas": "0x0", - "gasPrice": "0x0", - "value": "0x0", - "nonce": "0x0", - "data": null, - "input": null - }, - "call_info": [ - { - "type": "CRITICAL", - "message": "Tx will create contract with empty code!" - } - ], - "meta": { - "remote": "signer binary", - "local": "main", - "scheme": "in-proc" - } - } - ] -} -``` - -### ApproveListing / `ui_approveListing` - -Invoked when a request for account listing has been made. - -#### Sample call - -```json - -{ - "jsonrpc": "2.0", - "id": 5, - "method": "ui_approveListing", - "params": [ - { - "accounts": [ - { - "url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-20T14-44-54.089682944Z--123409812340981234098123409812deadbeef42", - "address": "0x123409812340981234098123409812deadbeef42" - }, - { - "url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-23T21-59-03.199240693Z--cafebabedeadbeef34098123409812deadbeef42", - "address": "0xcafebabedeadbeef34098123409812deadbeef42" - } - ], - "meta": { - "remote": "signer binary", - "local": "main", - "scheme": "in-proc" - } - } - ] -} - -``` - - -### ApproveSignData / `ui_approveSignData` - -#### Sample call - -```json -{ - "jsonrpc": "2.0", - "id": 4, - "method": "ui_approveSignData", - "params": [ - { - "address": "0x123409812340981234098123409812deadbeef42", - "raw_data": "0x01020304", - "messages": [ - { - "name": "message", - "value": "\u0019Ethereum Signed Message:\n4\u0001\u0002\u0003\u0004", - "type": "text/plain" - } - ], - "hash": "0x7e3a4e7a9d1744bc5c675c25e1234ca8ed9162bd17f78b9085e48047c15ac310", - "meta": { - "remote": "signer binary", - "local": "main", - "scheme": "in-proc" - } - } - ] -} -``` - -### ApproveNewAccount / `ui_approveNewAccount` - -Invoked when a request for creating a new account has been made. - -#### Sample call - -```json -{ - "jsonrpc": "2.0", - "id": 4, - "method": "ui_approveNewAccount", - "params": [ - { - "meta": { - "remote": "signer binary", - "local": "main", - "scheme": "in-proc" - } - } - ] -} -``` - -### ShowInfo / `ui_showInfo` - -The UI should show the info (a single message) to the user. Does not expect response. - -#### Sample call - -```json -{ - "jsonrpc": "2.0", - "id": 9, - "method": "ui_showInfo", - "params": [ - "Tests completed" - ] -} - -``` - -### ShowError / `ui_showError` - -The UI should show the error (a single message) to the user. Does not expect response. - -```json - -{ - "jsonrpc": "2.0", - "id": 2, - "method": "ui_showError", - "params": [ - "Something bad happened!" - ] -} - -``` - -### OnApprovedTx / `ui_onApprovedTx` - -`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions. - -When implementing rate-limited rules, this callback should be used. - -TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`. - -Example call: -```json - -{ - "jsonrpc": "2.0", - "id": 1, - "method": "ui_onApprovedTx", - "params": [ - { - "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "tx": { - "nonce": "0x0", - "gasPrice": "0x1", - "gas": "0x333", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "value": "0x0", - "input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", - "v": "0x26", - "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", - "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", - "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" - } - } - ] -} -``` - -### OnSignerStartup / `ui_onSignerStartup` - -This method provides the UI with information about what API version the signer uses (both internal and external) as well as build-info and external API, -in k/v-form. - -Example call: -```json - -{ - "jsonrpc": "2.0", - "id": 1, - "method": "ui_onSignerStartup", - "params": [ - { - "info": { - "extapi_http": "http://localhost:8550", - "extapi_ipc": null, - "extapi_version": "2.0.0", - "intapi_version": "1.2.0" - } - } - ] -} - -``` - -### OnInputRequired / `ui_onInputRequired` - -Invoked when Clef requires user input (e.g. a password). - -Example call: -```json - -{ - "jsonrpc": "2.0", - "id": 1, - "method": "ui_onInputRequired", - "params": [ - { - "title": "Account password", - "prompt": "Please enter the password for account 0x694267f14675d7e1b9494fd8d72fefe1755710fa", - "isPassword": true - } - ] -} -``` - - -### Rules for UI apis - -A UI should conform to the following rules. - -* A UI MUST NOT load any external resources that were not embedded/part of the UI package. - * For example, not load icons, stylesheets from the internet - * Not load files from the filesystem, unless they reside in the same local directory (e.g. config files) -* A Graphical UI MUST show the blocky-identicon for ethereum addresses. -* A UI MUST warn display appropriate warning if the destination-account is formatted with invalid checksum. -* A UI MUST NOT open any ports or services - * The signer opens the public port -* A UI SHOULD verify the permissions on the signer binary, and refuse to execute or warn if permissions allow non-user write. -* A UI SHOULD inform the user about the `SHA256` or `MD5` hash of the binary being executed -* A UI SHOULD NOT maintain a secondary storage of data, e.g. list of accounts - * The signer provides accounts -* A UI SHOULD, to the best extent possible, use static linking / bundling, so that required libraries are bundled -along with the UI. - - -### UI Implementations - -There are a couple of implementation for a UI. We'll try to keep this list up to date. - -| Name | Repo | UI type| No external resources| Blocky support| Verifies permissions | Hash information | No secondary storage | Statically linked| Can modify parameters| -| ---- | ---- | -------| ---- | ---- | ---- |---- | ---- | ---- | ---- | -| QtSigner| https://github.com/holiman/qtsigner/ | Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)| -| GtkSigner| https://github.com/holiman/gtksigner | Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: | -| Frame | https://github.com/floating/frame/commits/go-signer | Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: | -| Clef UI| https://github.com/ethereum/clef-ui | Golang/QT-based| :+1:| :+1:| :x:| :+1:| :+1:| :x: | :+1: (approve tx only)| diff --git a/builder/cmd/clef/consolecmd_test.go b/builder/cmd/clef/consolecmd_test.go deleted file mode 100644 index c8b37f5b9..000000000 --- a/builder/cmd/clef/consolecmd_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "path/filepath" - "strings" - "testing" -) - -// TestImportRaw tests clef --importraw -func TestImportRaw(t *testing.T) { - t.Parallel() - keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name())) - os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777) - t.Cleanup(func() { os.Remove(keyPath) }) - - t.Run("happy-path", func(t *testing.T) { - t.Parallel() - // Run clef importraw - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath) - clef.input("myverylongpassword").input("myverylongpassword") - if out := string(clef.Output()); !strings.Contains(out, - "Key imported:\n Address 0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6") { - t.Logf("Output\n%v", out) - t.Error("Failure") - } - }) - // tests clef --importraw with mismatched passwords. - t.Run("pw-mismatch", func(t *testing.T) { - t.Parallel() - // Run clef importraw - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath) - clef.input("myverylongpassword1").input("myverylongpassword2").WaitExit() - if have, want := clef.StderrText(), "Passwords do not match\n"; have != want { - t.Errorf("have %q, want %q", have, want) - } - }) - // tests clef --importraw with a too short password. - t.Run("short-pw", func(t *testing.T) { - t.Parallel() - // Run clef importraw - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath) - clef.input("shorty").input("shorty").WaitExit() - if have, want := clef.StderrText(), - "password requirements not met: password too short (<10 characters)\n"; have != want { - t.Errorf("have %q, want %q", have, want) - } - }) -} - -// TestListAccounts tests clef --list-accounts -func TestListAccounts(t *testing.T) { - t.Parallel() - keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name())) - os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777) - t.Cleanup(func() { os.Remove(keyPath) }) - - t.Run("no-accounts", func(t *testing.T) { - t.Parallel() - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-accounts") - if out := string(clef.Output()); !strings.Contains(out, "The keystore is empty.") { - t.Logf("Output\n%v", out) - t.Error("Failure") - } - }) - t.Run("one-account", func(t *testing.T) { - t.Parallel() - // First, we need to import - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath) - clef.input("myverylongpassword").input("myverylongpassword").WaitExit() - // Secondly, do a listing, using the same datadir - clef = runWithKeystore(t, clef.Datadir, "--suppress-bootwarn", "--lightkdf", "list-accounts") - if out := string(clef.Output()); !strings.Contains(out, "0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6 (keystore:") { - t.Logf("Output\n%v", out) - t.Error("Failure") - } - }) -} - -// TestListWallets tests clef --list-wallets -func TestListWallets(t *testing.T) { - t.Parallel() - keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name())) - os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777) - t.Cleanup(func() { os.Remove(keyPath) }) - - t.Run("no-accounts", func(t *testing.T) { - t.Parallel() - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-wallets") - if out := string(clef.Output()); !strings.Contains(out, "There are no wallets.") { - t.Logf("Output\n%v", out) - t.Error("Failure") - } - }) - t.Run("one-account", func(t *testing.T) { - t.Parallel() - // First, we need to import - clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath) - clef.input("myverylongpassword").input("myverylongpassword").WaitExit() - // Secondly, do a listing, using the same datadir - clef = runWithKeystore(t, clef.Datadir, "--suppress-bootwarn", "--lightkdf", "list-wallets") - if out := string(clef.Output()); !strings.Contains(out, "Account 0: 0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6") { - t.Logf("Output\n%v", out) - t.Error("Failure") - } - }) -} diff --git a/builder/cmd/clef/datatypes.md b/builder/cmd/clef/datatypes.md deleted file mode 100644 index 8456edfa3..000000000 --- a/builder/cmd/clef/datatypes.md +++ /dev/null @@ -1,224 +0,0 @@ -## UI Client interface - -These data types are defined in the channel between clef and the UI -### SignDataRequest - -SignDataRequest contains information about a pending request to sign some data. The data to be signed can be of various types, defined by content-type. Clef has done most of the work in canonicalizing and making sense of the data, and it's up to the UI to present the user with the contents of the `message` - -Example: -```json -{ - "content_type": "text/plain", - "address": "0xDEADbEeF000000000000000000000000DeaDbeEf", - "raw_data": "GUV0aGVyZXVtIFNpZ25lZCBNZXNzYWdlOgoxMWhlbGxvIHdvcmxk", - "messages": [ - { - "name": "message", - "value": "\u0019Ethereum Signed Message:\n11hello world", - "type": "text/plain" - } - ], - "hash": "0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68", - "meta": { - "remote": "localhost:9999", - "local": "localhost:8545", - "scheme": "http", - "User-Agent": "Firefox 3.2", - "Origin": "www.malicious.ru" - } -} -``` -### SignDataResponse - approve - -Response to SignDataRequest - -Example: -```json -{ - "approved": true -} -``` -### SignDataResponse - deny - -Response to SignDataRequest - -Example: -```json -{ - "approved": false -} -``` -### SignTxRequest - -SignTxRequest contains information about a pending request to sign a transaction. Aside from the transaction itself, there is also a `call_info`-struct. That struct contains messages of various types, that the user should be informed of. - -As in any request, it's important to consider that the `meta` info also contains untrusted data. - -The `transaction` (on input into clef) can have either `data` or `input` -- if both are set, they must be identical, otherwise an error is generated. However, Clef will always use `data` when passing this struct on (if Clef does otherwise, please file a ticket) - -Example: -```json -{ - "transaction": { - "from": "0xDEADbEeF000000000000000000000000DeaDbeEf", - "to": null, - "gas": "0x3e8", - "gasPrice": "0x5", - "value": "0x6", - "nonce": "0x1", - "data": "0x01020304" - }, - "call_info": [ - { - "type": "Warning", - "message": "Something looks odd, show this message as a warning" - }, - { - "type": "Info", - "message": "User should see this as well" - } - ], - "meta": { - "remote": "localhost:9999", - "local": "localhost:8545", - "scheme": "http", - "User-Agent": "Firefox 3.2", - "Origin": "www.malicious.ru" - } -} -``` -### SignTxResponse - approve - -Response to request to sign a transaction. This response needs to contain the `transaction`, because the UI is free to make modifications to the transaction. - -Example: -```json -{ - "transaction": { - "from": "0xDEADbEeF000000000000000000000000DeaDbeEf", - "to": null, - "gas": "0x3e8", - "gasPrice": "0x5", - "value": "0x6", - "nonce": "0x4", - "data": "0x04030201" - }, - "approved": true -} -``` -### SignTxResponse - deny - -Response to SignTxRequest. When denying a request, there's no need to provide the transaction in return - -Example: -```json -{ - "transaction": { - "from": "0x", - "to": null, - "gas": "0x0", - "gasPrice": "0x0", - "value": "0x0", - "nonce": "0x0", - "data": null - }, - "approved": false -} -``` -### OnApproved - SignTransactionResult - -SignTransactionResult is used in the call `clef` -> `OnApprovedTx(result)` - -This occurs _after_ successful completion of the entire signing procedure, but right before the signed transaction is passed to the external caller. This method (and data) can be used by the UI to signal to the user that the transaction was signed, but it is primarily useful for ruleset implementations. - -A ruleset that implements a rate limitation needs to know what transactions are sent out to the external interface. By hooking into this methods, the ruleset can maintain track of that count. - -**OBS:** Note that if an attacker can restore your `clef` data to a previous point in time (e.g through a backup), the attacker can reset such windows, even if he/she is unable to decrypt the content. - -The `OnApproved` method cannot be responded to, it's purely informative - -Example: -```json -{ - "raw": "0xf85d640101948a8eafb1cf62bfbeb1741769dae1a9dd47996192018026a0716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293a04e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed", - "tx": { - "nonce": "0x64", - "gasPrice": "0x1", - "gas": "0x1", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "value": "0x1", - "input": "0x", - "v": "0x26", - "r": "0x716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293", - "s": "0x4e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed", - "hash": "0x662f6d772692dd692f1b5e8baa77a9ff95bbd909362df3fc3d301aafebde5441" - } -} -``` -### UserInputRequest - -Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free) - -Example: -```json -{ - "prompt": "The question to ask the user", - "title": "The title here", - "isPassword": true -} -``` -### UserInputResponse - -Response to UserInputRequest - -Example: -```json -{ - "text": "The textual response from user" -} -``` -### ListRequest - -Sent when a request has been made to list addresses. The UI is provided with the full `account`s, including local directory names. Note: this information is not passed back to the external caller, who only sees the `address`es. - -Example: -```json -{ - "accounts": [ - { - "address": "0xdeadbeef000000000000000000000000deadbeef", - "url": "keystore:///path/to/keyfile/a" - }, - { - "address": "0x1111111122222222222233333333334444444444", - "url": "keystore:///path/to/keyfile/b" - } - ], - "meta": { - "remote": "localhost:9999", - "local": "localhost:8545", - "scheme": "http", - "User-Agent": "Firefox 3.2", - "Origin": "www.malicious.ru" - } -} -``` -### ListResponse - -Response to list request. The response contains a list of all addresses to show to the caller. Note: the UI is free to respond with any address the caller, regardless of whether it exists or not - -Example: -```json -{ - "accounts": [ - { - "address": "0x0000000000000000000000000000000000000000", - "url": ".. ignored .." - }, - { - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "url": "" - } - ] -} -``` diff --git a/builder/cmd/clef/docs/clef_architecture_pt1.png b/builder/cmd/clef/docs/clef_architecture_pt1.png deleted file mode 100644 index e40e532f3..000000000 Binary files a/builder/cmd/clef/docs/clef_architecture_pt1.png and /dev/null differ diff --git a/builder/cmd/clef/docs/clef_architecture_pt2.png b/builder/cmd/clef/docs/clef_architecture_pt2.png deleted file mode 100644 index f617d755e..000000000 Binary files a/builder/cmd/clef/docs/clef_architecture_pt2.png and /dev/null differ diff --git a/builder/cmd/clef/docs/clef_architecture_pt3.png b/builder/cmd/clef/docs/clef_architecture_pt3.png deleted file mode 100644 index b9d695447..000000000 Binary files a/builder/cmd/clef/docs/clef_architecture_pt3.png and /dev/null differ diff --git a/builder/cmd/clef/docs/clef_architecture_pt4.png b/builder/cmd/clef/docs/clef_architecture_pt4.png deleted file mode 100644 index a6cb3b4df..000000000 Binary files a/builder/cmd/clef/docs/clef_architecture_pt4.png and /dev/null differ diff --git a/builder/cmd/clef/docs/qubes/clef_qubes_http.png b/builder/cmd/clef/docs/qubes/clef_qubes_http.png deleted file mode 100644 index e95ad8da4..000000000 Binary files a/builder/cmd/clef/docs/qubes/clef_qubes_http.png and /dev/null differ diff --git a/builder/cmd/clef/docs/qubes/clef_qubes_qrexec.png b/builder/cmd/clef/docs/qubes/clef_qubes_qrexec.png deleted file mode 100644 index b1814e7c3..000000000 Binary files a/builder/cmd/clef/docs/qubes/clef_qubes_qrexec.png and /dev/null differ diff --git a/builder/cmd/clef/docs/qubes/qrexec-example.png b/builder/cmd/clef/docs/qubes/qrexec-example.png deleted file mode 100644 index fc5d57725..000000000 Binary files a/builder/cmd/clef/docs/qubes/qrexec-example.png and /dev/null differ diff --git a/builder/cmd/clef/docs/qubes/qubes-client.py b/builder/cmd/clef/docs/qubes/qubes-client.py deleted file mode 100644 index 93a74b899..000000000 --- a/builder/cmd/clef/docs/qubes/qubes-client.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -This implements a dispatcher which listens to localhost:8550, and proxies -requests via qrexec to the service qubes.EthSign on a target domain -""" - -import http.server -import socketserver,subprocess - -PORT=8550 -TARGET_DOMAIN= 'debian-work' - -class Dispatcher(http.server.BaseHTTPRequestHandler): - def do_POST(self): - post_data = self.rfile.read(int(self.headers['Content-Length'])) - p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE) - output = p.communicate(post_data)[0] - self.wfile.write(output) - - -with socketserver.TCPServer(("",PORT), Dispatcher) as httpd: - print("Serving at port", PORT) - httpd.serve_forever() - diff --git a/builder/cmd/clef/docs/qubes/qubes.Clefsign b/builder/cmd/clef/docs/qubes/qubes.Clefsign deleted file mode 100644 index 9b5af7b4f..000000000 --- a/builder/cmd/clef/docs/qubes/qubes.Clefsign +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -SIGNER_BIN="/home/user/tools/clef/clef" -SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN" - -# Start clef if not already started -if [ ! -S /home/user/.clef/clef.ipc ]; then - $SIGNER_CMD & - sleep 1 -fi - -# Should be started by now -if [ -S /home/user/.clef/clef.ipc ]; then - # Post incoming request to HTTP channel - curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null -fi diff --git a/builder/cmd/clef/docs/qubes/qubes_newaccount-1.png b/builder/cmd/clef/docs/qubes/qubes_newaccount-1.png deleted file mode 100644 index 3bfc8b5b7..000000000 Binary files a/builder/cmd/clef/docs/qubes/qubes_newaccount-1.png and /dev/null differ diff --git a/builder/cmd/clef/docs/qubes/qubes_newaccount-2.png b/builder/cmd/clef/docs/qubes/qubes_newaccount-2.png deleted file mode 100644 index c6dbd535d..000000000 Binary files a/builder/cmd/clef/docs/qubes/qubes_newaccount-2.png and /dev/null differ diff --git a/builder/cmd/clef/docs/setup.md b/builder/cmd/clef/docs/setup.md deleted file mode 100644 index 6cc7a4120..000000000 --- a/builder/cmd/clef/docs/setup.md +++ /dev/null @@ -1,198 +0,0 @@ -# Setting up Clef - -This document describes how Clef can be used in a more secure manner than executing it from your everyday laptop, -in order to ensure that the keys remain safe in the event that your computer should get compromised. - -## Qubes OS - - -### Background - -The Qubes operating system is based around virtual machines (qubes), where a set of virtual machines are configured, typically for -different purposes such as: - -- personal - - Your personal email, browsing etc -- work - - Work email etc -- vault - - a VM without network access, where gpg-keys and/or keepass credentials are stored. - -A couple of dedicated virtual machines handle externalities: - -- sys-net provides networking to all other (network-enabled) machines -- sys-firewall handles firewall rules -- sys-usb handles USB devices, and can map usb-devices to certain qubes. - -The goal of this document is to describe how we can set up clef to provide secure transaction -signing from a `vault` vm, to another networked qube which runs Dapps. - -### Setup - -There are two ways that this can be achieved: integrated via Qubes or integrated via networking. - - -#### 1. Qubes Integrated - -Qubes provides a facility for inter-qubes communication via `qrexec`. A qube can request to make a cross-qube RPC request -to another qube. The OS then asks the user if the call is permitted. - -![Example](qubes/qrexec-example.png) - -A policy-file can be created to allow such interaction. On the `target` domain, a service is invoked which can read the -`stdin` from the `client` qube. - -This is how [Split GPG](https://www.qubes-os.org/doc/split-gpg/) is implemented. We can set up Clef the same way: - -##### Server - -![Clef via qrexec](qubes/clef_qubes_qrexec.png) - -On the `target` qubes, we need to define the RPC service. - -[qubes.Clefsign](qubes/qubes.Clefsign): - -```bash -#!/bin/bash - -SIGNER_BIN="/home/user/tools/clef/clef" -SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN" - -# Start clef if not already started -if [ ! -S /home/user/.clef/clef.ipc ]; then - $SIGNER_CMD & - sleep 1 -fi - -# Should be started by now -if [ -S /home/user/.clef/clef.ipc ]; then - # Post incoming request to HTTP channel - curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null -fi - -``` -This RPC service is not complete (see notes about HTTP headers below), but works as a proof-of-concept. -It will forward the data received on `stdin` (forwarded by the OS) to Clef's HTTP channel. - -It would have been possible to send data directly to the `/home/user/.clef/.clef.ipc` -socket via e.g `nc -U /home/user/.clef/clef.ipc`, but the reason for sending the request -data over `HTTP` instead of `IPC` is that we want the ability to forward `HTTP` headers. - -To enable the service: - -``` bash -sudo cp qubes.Clefsign /etc/qubes-rpc/ -sudo chmod +x /etc/qubes-rpc/ qubes.Clefsign -``` - -This setup uses [gtksigner](https://github.com/holiman/gtksigner), which is a very minimal GTK-based UI that works well -with minimal requirements. - -##### Client - - -On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it. - - -[qubes-client.py](qubes/qubes-client.py): - -```python - -""" -This implements a dispatcher which listens to localhost:8550, and proxies -requests via qrexec to the service qubes.EthSign on a target domain -""" - -import http.server -import socketserver,subprocess - -PORT=8550 -TARGET_DOMAIN= 'debian-work' - -class Dispatcher(http.server.BaseHTTPRequestHandler): - def do_POST(self): - post_data = self.rfile.read(int(self.headers['Content-Length'])) - p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE) - output = p.communicate(post_data)[0] - self.wfile.write(output) - - -with socketserver.TCPServer(("",PORT), Dispatcher) as httpd: - print("Serving at port", PORT) - httpd.serve_forever() - - -``` - -#### Testing - -To test the flow, if we have set up `debian-work` as the `target`, we can do - -```bash -$ cat newaccnt.json -{ "id": 0, "jsonrpc": "2.0","method": "account_new","params": []} - -$ cat newaccnt.json| qrexec-client-vm debian-work qubes.Clefsign -``` - -A dialog should pop up first to allow the IPC call: - -![one](qubes/qubes_newaccount-1.png) - -Followed by a GTK-dialog to approve the operation: - -![two](qubes/qubes_newaccount-2.png) - -To test the full flow, we use the client wrapper. Start it on the `client` qube: -``` -[user@work qubes]$ python3 qubes-client.py -``` - -Make the request over http (`client` qube): -``` -[user@work clef]$ cat newaccnt.json | curl -X POST -d @- http://localhost:8550 -``` -And it should show the same popups again. - -##### Pros and cons - -The benefits of this setup are: - -- This is the qubes-os intended model for inter-qube communication, -- and thus benefits from qubes-os dialogs and policies for user approval - -However, it comes with a couple of drawbacks: - -- The `qubes-gpg-client` must forward the http request via RPC to the `target` qube. When doing so, the proxy - will either drop important headers, or replace them. - - The `Host` header is most likely `localhost` - - The `Origin` header must be forwarded - - Information about the remote ip must be added as a `X-Forwarded-For`. However, Clef cannot always trust an `XFF` header, - since malicious clients may lie about `XFF` in order to fool the http server into believing it comes from another address. -- Even with a policy in place to allow RPC calls between `caller` and `target`, there will be several popups: - - One qubes-specific where the user specifies the `target` vm - - One clef-specific to approve the transaction - - -#### 2. Network integrated - -The second way to set up Clef on a qubes system is to allow networking, and have Clef listen to a port which is accessible -from other qubes. - -![Clef via http](qubes/clef_qubes_http.png) - - - - -## USBArmory - -The [USB armory](https://inversepath.com/usbarmory) is an open source hardware design with an 800 MHz ARM processor. It is a pocket-size -computer. When inserted into a laptop, it identifies itself as a USB network interface, basically adding another network -to your computer. Over this new network interface, you can SSH into the device. - -Running Clef off a USB armory means that you can use the armory as a very versatile offline computer, which only -ever connects to a local network between your computer and the device itself. - -Needless to say, while this model should be fairly secure against remote attacks, an attacker with physical access -to the USB Armory would trivially be able to extract the contents of the device filesystem. - diff --git a/builder/cmd/clef/extapi_changelog.md b/builder/cmd/clef/extapi_changelog.md deleted file mode 100644 index 31554f079..000000000 --- a/builder/cmd/clef/extapi_changelog.md +++ /dev/null @@ -1,104 +0,0 @@ -## Changelog for external API - -The API uses [semantic versioning](https://semver.org/). - -TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the: - -* MAJOR version when you make incompatible API changes, -* MINOR version when you add functionality in a backwards-compatible manner, and -* PATCH version when you make backwards-compatible bug fixes. - -Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. - -### 6.1.0 - -The API-method `account_signGnosisSafeTx` was added. This method takes two parameters, -`[address, safeTx]`. The latter, `safeTx`, can be copy-pasted from the gnosis relay. For example: - -``` -{ - "jsonrpc": "2.0", - "method": "account_signGnosisSafeTx", - "params": ["0xfd1c4226bfD1c436672092F4eCbfC270145b7256", - { - "safe": "0x25a6c4BBd32B2424A9c99aEB0584Ad12045382B3", - "to": "0xB372a646f7F05Cc1785018dBDA7EBc734a2A20E2", - "value": "20000000000000000", - "data": null, - "operation": 0, - "gasToken": "0x0000000000000000000000000000000000000000", - "safeTxGas": 27845, - "baseGas": 0, - "gasPrice": "0", - "refundReceiver": "0x0000000000000000000000000000000000000000", - "nonce": 2, - "executionDate": null, - "submissionDate": "2020-09-15T21:54:49.617634Z", - "modified": "2020-09-15T21:54:49.617634Z", - "blockNumber": null, - "transactionHash": null, - "safeTxHash": "0x2edfbd5bc113ff18c0631595db32eb17182872d88d9bf8ee4d8c2dd5db6d95e2", - "executor": null, - "isExecuted": false, - "isSuccessful": null, - "ethGasPrice": null, - "gasUsed": null, - "fee": null, - "origin": null, - "dataDecoded": null, - "confirmationsRequired": null, - "confirmations": [ - { - "owner": "0xAd2e180019FCa9e55CADe76E4487F126Fd08DA34", - "submissionDate": "2020-09-15T21:54:49.663299Z", - "transactionHash": null, - "confirmationType": "CONFIRMATION", - "signature": "0x95a7250bb645f831c86defc847350e7faff815b2fb586282568e96cc859e39315876db20a2eed5f7a0412906ec5ab57652a6f645ad4833f345bda059b9da2b821c", - "signatureType": "EOA" - } - ], - "signatures": null - } - ], - "id": 67 -} -``` - -Not all fields are required, though. This method is really just a UX helper, which massages the -input to conform to the `EIP-712` [specification](https://docs.gnosis.io/safe/docs/contracts_tx_execution/#transaction-hash) -for the Gnosis Safe, and making the output be directly importable to by a relay service. - - -### 6.0.0 - -* `New` was changed to deliver only an address, not the full `Account` data -* `Export` was moved from External API to the UI Server API - -#### 5.0.0 - -* The external `account_EcRecover`-method was reimplemented. -* The external method `account_sign(address, data)` was replaced with `account_signData(contentType, address, data)`. -The addition of `contentType` makes it possible to use the method for different types of objects, such as: - * signing data with an intended validator (not yet implemented) - * signing clique headers, - * signing plain personal messages, -* The external method `account_signTypedData` implements [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and makes it possible to sign typed data. - -#### 4.0.0 - -* The external `account_Ecrecover`-method was removed. -* The external `account_Import`-method was removed. - -#### 3.0.0 - -* The external `account_List`-method was changed to not expose `url`, which contained info about the local filesystem. It now returns only a list of addresses. - -#### 2.0.0 - -* Commit `73abaf04b1372fa4c43201fb1b8019fe6b0a6f8d`, move `from` into `transaction` object in `signTransaction`. This -makes the `accounts_signTransaction` identical to the old `eth_signTransaction`. - - -#### 1.0.0 - -Initial release. diff --git a/builder/cmd/clef/intapi_changelog.md b/builder/cmd/clef/intapi_changelog.md deleted file mode 100644 index eaeb2e686..000000000 --- a/builder/cmd/clef/intapi_changelog.md +++ /dev/null @@ -1,191 +0,0 @@ -## Changelog for internal API (ui-api) - -The API uses [semantic versioning](https://semver.org/). - -TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the: - -* MAJOR version when you make incompatible API changes, -* MINOR version when you add functionality in a backwards-compatible manner, and -* PATCH version when you make backwards-compatible bug fixes. - -Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. - -### 7.0.1 - -Added `clef_New` to the internal API callable from a UI. - -> `New` creates a new password protected Account. The private key is protected with -> the given password. Users are responsible to backup the private key that is stored -> in the keystore location that was specified when this API was created. -> This method is the same as New on the external API, the difference being that -> this implementation does not ask for confirmation, since it's initiated by -> the user - -### 7.0.0 - -- The `message` field was renamed to `messages` in all data signing request methods to better reflect that it's a list, not a value. -- The `storage.Put` and `storage.Get` methods in the rule execution engine were lower-cased to `storage.put` and `storage.get` to be consistent with JavaScript call conventions. - -### 6.0.0 - -Removed `password` from responses to operations which require them. This is for two reasons, - -- Consistency between how rulesets operate and how manual processing works. A rule can `Approve` but require the actual password to be stored in the clef storage. -With this change, the same stored password can be used even if rulesets are not enabled, but storage is. -- It also removes the usability-shortcut that a UI might otherwise want to implement; remembering passwords. Since we now will not require the -password on every `Approve`, there's no need for the UI to cache it locally. - - In a future update, we'll likely add `clef_storePassword` to the internal API, so the user can store it via his UI (currently only CLI works). - -Affected datatypes: -- `SignTxResponse` -- `SignDataResponse` -- `NewAccountResponse` - -If `clef` requires a password, the `OnInputRequired` will be used to collect it. - - -### 5.0.0 - -Changed the namespace format to adhere to the legacy ethereum format: `name_methodName`. Changes: - -* `ApproveTx` -> `ui_approveTx` -* `ApproveSignData` -> `ui_approveSignData` -* `ApproveExport` -> `removed` -* `ApproveImport` -> `removed` -* `ApproveListing` -> `ui_approveListing` -* `ApproveNewAccount` -> `ui_approveNewAccount` -* `ShowError` -> `ui_showError` -* `ShowInfo` -> `ui_showInfo` -* `OnApprovedTx` -> `ui_onApprovedTx` -* `OnSignerStartup` -> `ui_onSignerStartup` -* `OnInputRequired` -> `ui_onInputRequired` - - -### 4.0.0 - -* Bidirectional communication implemented, so the UI can query `clef` via the stdin/stdout RPC channel. Methods implemented are: - - `clef_listWallets` - - `clef_listAccounts` - - `clef_listWallets` - - `clef_deriveAccount` - - `clef_importRawKey` - - `clef_openWallet` - - `clef_chainId` - - `clef_setChainId` - - `clef_export` - - `clef_import` - -* The type `Account` was modified (the json-field `type` was removed), to consist of - -```go -type Account struct { - Address common.Address `json:"address"` // Ethereum account address derived from the key - URL URL `json:"url"` // Optional resource locator within a backend -} -``` - - -### 3.2.0 - -* Make `ShowError`, `OnApprovedTx`, `OnSignerStartup` be json-rpc [notifications](https://www.jsonrpc.org/specification#notification): - -> A Notification is a Request object without an "id" member. A Request object that is a Notification signifies the Client's lack of interest in the corresponding Response object, and as such no Response object needs to be returned to the client. The Server MUST NOT reply to a Notification, including those that are within a batch request. -> -> Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params","Internal error" -### 3.1.0 - -* Add `ContentType` `string` to `SignDataRequest` to accommodate the latest EIP-191 and EIP-712 implementations. - -### 3.0.0 - -* Make use of `OnInputRequired(info UserInputRequest)` for obtaining master password during startup - -### 2.1.0 - -* Add `OnInputRequired(info UserInputRequest)` to internal API. This method is used when Clef needs user input, e.g. passwords. - -The following structures are used: - -```go -UserInputRequest struct { - Prompt string `json:"prompt"` - Title string `json:"title"` - IsPassword bool `json:"isPassword"` -} -UserInputResponse struct { - Text string `json:"text"` -} -``` - -### 2.0.0 - -* Modify how `call_info` on a transaction is conveyed. New format: - -``` -{ - "jsonrpc": "2.0", - "id": 2, - "method": "ApproveTx", - "params": [ - { - "transaction": { - "from": "0x82A2A876D39022B3019932D30Cd9c97ad5616813", - "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", - "gas": "0x333", - "gasPrice": "0x123", - "value": "0x10", - "nonce": "0x0", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", - "input": null - }, - "call_info": [ - { - "type": "WARNING", - "message": "Invalid checksum on to-address" - }, - { - "type": "WARNING", - "message": "Tx contains data, but provided ABI signature could not be matched: Did not match: test (0 matches)" - } - ], - "meta": { - "remote": "127.0.0.1:54286", - "local": "localhost:8550", - "scheme": "HTTP/1.1" - } - } - ] -} -``` - -#### 1.2.0 - -* Add `OnStartup` method, to provide the UI with information about what API version -the signer uses (both internal and external) as well as build-info and external api. - -Example call: -```json -{ - "jsonrpc": "2.0", - "id": 1, - "method": "OnSignerStartup", - "params": [ - { - "info": { - "extapi_http": "http://localhost:8550", - "extapi_ipc": null, - "extapi_version": "2.0.0", - "intapi_version": "1.2.0" - } - } - ] -} -``` - -#### 1.1.0 - -* Add `OnApproved` method - -#### 1.0.0 - -Initial release. diff --git a/builder/cmd/clef/main.go b/builder/cmd/clef/main.go deleted file mode 100644 index f9b00e4a1..000000000 --- a/builder/cmd/clef/main.go +++ /dev/null @@ -1,1224 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bufio" - "context" - "crypto/rand" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - "net" - "os" - "os/signal" - "path/filepath" - "runtime" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/signer/core" - "github.com/ethereum/go-ethereum/signer/core/apitypes" - "github.com/ethereum/go-ethereum/signer/fourbyte" - "github.com/ethereum/go-ethereum/signer/rules" - "github.com/ethereum/go-ethereum/signer/storage" - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" - "github.com/urfave/cli/v2" -) - -const legalWarning = ` -WARNING! - -Clef is an account management tool. It may, like any software, contain bugs. - -Please take care to -- backup your keystore files, -- verify that the keystore(s) can be opened with your password. - -Clef 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. -` - -var ( - logLevelFlag = &cli.IntFlag{ - Name: "loglevel", - Value: 3, - Usage: "log level to emit to the screen", - } - advancedMode = &cli.BoolFlag{ - Name: "advanced", - Usage: "If enabled, issues warnings instead of rejections for suspicious requests. Default off", - } - acceptFlag = &cli.BoolFlag{ - Name: "suppress-bootwarn", - Usage: "If set, does not show the warning during boot", - } - keystoreFlag = &cli.StringFlag{ - Name: "keystore", - Value: filepath.Join(node.DefaultDataDir(), "keystore"), - Usage: "Directory for the keystore", - } - configdirFlag = &cli.StringFlag{ - Name: "configdir", - Value: DefaultConfigDir(), - Usage: "Directory for Clef configuration", - } - chainIdFlag = &cli.Int64Flag{ - Name: "chainid", - Value: params.MainnetChainConfig.ChainID.Int64(), - Usage: "Chain id to use for signing (1=mainnet, 5=Goerli)", - } - rpcPortFlag = &cli.IntFlag{ - Name: "http.port", - Usage: "HTTP-RPC server listening port", - Value: node.DefaultHTTPPort + 5, - Category: flags.APICategory, - } - signerSecretFlag = &cli.StringFlag{ - Name: "signersecret", - Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash", - } - customDBFlag = &cli.StringFlag{ - Name: "4bytedb-custom", - Usage: "File used for writing new 4byte-identifiers submitted via API", - Value: "./4byte-custom.json", - } - auditLogFlag = &cli.StringFlag{ - Name: "auditlog", - Usage: "File used to emit audit logs. Set to \"\" to disable", - Value: "audit.log", - } - ruleFlag = &cli.StringFlag{ - Name: "rules", - Usage: "Path to the rule file to auto-authorize requests with", - } - stdiouiFlag = &cli.BoolFlag{ - Name: "stdio-ui", - Usage: "Use STDIN/STDOUT as a channel for an external UI. " + - "This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user " + - "interface, and can be used when Clef is started by an external process.", - } - testFlag = &cli.BoolFlag{ - Name: "stdio-ui-test", - Usage: "Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.", - } - initCommand = &cli.Command{ - Action: initializeSecrets, - Name: "init", - Usage: "Initialize the signer, generate secret storage", - ArgsUsage: "", - Flags: []cli.Flag{ - logLevelFlag, - configdirFlag, - }, - Description: ` -The init command generates a master seed which Clef can use to store credentials and data needed for -the rule-engine to work.`, - } - attestCommand = &cli.Command{ - Action: attestFile, - Name: "attest", - Usage: "Attest that a js-file is to be used", - ArgsUsage: "", - Flags: []cli.Flag{ - logLevelFlag, - configdirFlag, - signerSecretFlag, - }, - Description: ` -The attest command stores the sha256 of the rule.js-file that you want to use for automatic processing of -incoming requests. - -Whenever you make an edit to the rule file, you need to use attestation to tell -Clef that the file is 'safe' to execute.`, - } - setCredentialCommand = &cli.Command{ - Action: setCredential, - Name: "setpw", - Usage: "Store a credential for a keystore file", - ArgsUsage: "
", - Flags: []cli.Flag{ - logLevelFlag, - configdirFlag, - signerSecretFlag, - }, - Description: ` -The setpw command stores a password for a given address (keyfile). -`} - delCredentialCommand = &cli.Command{ - Action: removeCredential, - Name: "delpw", - Usage: "Remove a credential for a keystore file", - ArgsUsage: "
", - Flags: []cli.Flag{ - logLevelFlag, - configdirFlag, - signerSecretFlag, - }, - Description: ` -The delpw command removes a password for a given address (keyfile). -`} - newAccountCommand = &cli.Command{ - Action: newAccount, - Name: "newaccount", - Usage: "Create a new account", - ArgsUsage: "", - Flags: []cli.Flag{ - logLevelFlag, - keystoreFlag, - utils.LightKDFFlag, - acceptFlag, - }, - Description: ` -The newaccount command creates a new keystore-backed account. It is a convenience-method -which can be used in lieu of an external UI. -`} - gendocCommand = &cli.Command{ - Action: GenDoc, - Name: "gendoc", - Usage: "Generate documentation about json-rpc format", - Description: ` -The gendoc generates example structures of the json-rpc communication types. -`} - listAccountsCommand = &cli.Command{ - Action: listAccounts, - Name: "list-accounts", - Usage: "List accounts in the keystore", - Flags: []cli.Flag{ - logLevelFlag, - keystoreFlag, - utils.LightKDFFlag, - acceptFlag, - }, - Description: ` - Lists the accounts in the keystore. - `} - listWalletsCommand = &cli.Command{ - Action: listWallets, - Name: "list-wallets", - Usage: "List wallets known to Clef", - Flags: []cli.Flag{ - logLevelFlag, - keystoreFlag, - utils.LightKDFFlag, - acceptFlag, - }, - Description: ` - Lists the wallets known to Clef. - `} - importRawCommand = &cli.Command{ - Action: accountImport, - Name: "importraw", - Usage: "Import a hex-encoded private key.", - ArgsUsage: "", - Flags: []cli.Flag{ - logLevelFlag, - keystoreFlag, - utils.LightKDFFlag, - acceptFlag, - }, - Description: ` -Imports an unencrypted private key from and creates a new account. -Prints the address. -The keyfile is assumed to contain an unencrypted private key in hexadecimal format. -The account is saved in encrypted format, you are prompted for a password. -`} -) - -var app = flags.NewApp("Manage Ethereum account operations") - -func init() { - app.Name = "Clef" - app.Flags = []cli.Flag{ - logLevelFlag, - keystoreFlag, - configdirFlag, - chainIdFlag, - utils.LightKDFFlag, - utils.NoUSBFlag, - utils.SmartCardDaemonPathFlag, - utils.HTTPListenAddrFlag, - utils.HTTPVirtualHostsFlag, - utils.IPCDisabledFlag, - utils.IPCPathFlag, - utils.HTTPEnabledFlag, - rpcPortFlag, - signerSecretFlag, - customDBFlag, - auditLogFlag, - ruleFlag, - stdiouiFlag, - testFlag, - advancedMode, - acceptFlag, - } - app.Action = signer - app.Commands = []*cli.Command{initCommand, - attestCommand, - setCredentialCommand, - delCredentialCommand, - newAccountCommand, - importRawCommand, - gendocCommand, - listAccountsCommand, - listWalletsCommand, - } -} - -func main() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func initializeSecrets(c *cli.Context) error { - // Get past the legal message - if err := initialize(c); err != nil { - return err - } - // Ensure the master key does not yet exist, we're not willing to overwrite - configDir := c.String(configdirFlag.Name) - if err := os.Mkdir(configDir, 0700); err != nil && !os.IsExist(err) { - return err - } - location := filepath.Join(configDir, "masterseed.json") - if _, err := os.Stat(location); err == nil { - return fmt.Errorf("master key %v already exists, will not overwrite", location) - } - // Key file does not exist yet, generate a new one and encrypt it - masterSeed := make([]byte, 256) - num, err := io.ReadFull(rand.Reader, masterSeed) - if err != nil { - return err - } - if num != len(masterSeed) { - return errors.New("failed to read enough random") - } - n, p := keystore.StandardScryptN, keystore.StandardScryptP - if c.Bool(utils.LightKDFFlag.Name) { - n, p = keystore.LightScryptN, keystore.LightScryptP - } - text := "The master seed of clef will be locked with a password.\nPlease specify a password. Do not forget this password!" - var password string - for { - password = utils.GetPassPhrase(text, true) - if err := core.ValidatePasswordFormat(password); err != nil { - fmt.Printf("invalid password: %v\n", err) - } else { - fmt.Println() - break - } - } - cipherSeed, err := encryptSeed(masterSeed, []byte(password), n, p) - if err != nil { - return fmt.Errorf("failed to encrypt master seed: %v", err) - } - // Double check the master key path to ensure nothing wrote there in between - if err = os.Mkdir(configDir, 0700); err != nil && !os.IsExist(err) { - return err - } - if _, err := os.Stat(location); err == nil { - return fmt.Errorf("master key %v already exists, will not overwrite", location) - } - // Write the file and print the usual warning message - if err = os.WriteFile(location, cipherSeed, 0400); err != nil { - return err - } - fmt.Printf("A master seed has been generated into %s\n", location) - fmt.Printf(` -This is required to be able to store credentials, such as: -* Passwords for keystores (used by rule engine) -* Storage for JavaScript auto-signing rules -* Hash of JavaScript rule-file - -You should treat 'masterseed.json' with utmost secrecy and make a backup of it! -* The password is necessary but not enough, you need to back up the master seed too! -* The master seed does not contain your accounts, those need to be backed up separately! - -`) - return nil -} - -func attestFile(ctx *cli.Context) error { - if ctx.NArg() < 1 { - utils.Fatalf("This command requires an argument.") - } - if err := initialize(ctx); err != nil { - return err - } - - stretchedKey, err := readMasterKey(ctx, nil) - if err != nil { - utils.Fatalf(err.Error()) - } - configDir := ctx.String(configdirFlag.Name) - vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) - confKey := crypto.Keccak256([]byte("config"), stretchedKey) - - // Initialize the encrypted storages - configStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "config.json"), confKey) - val := ctx.Args().First() - configStorage.Put("ruleset_sha256", val) - log.Info("Ruleset attestation updated", "sha256", val) - return nil -} - -func initInternalApi(c *cli.Context) (*core.UIServerAPI, core.UIClientAPI, error) { - if err := initialize(c); err != nil { - return nil, nil, err - } - var ( - ui = core.NewCommandlineUI() - pwStorage storage.Storage = &storage.NoStorage{} - ksLoc = c.String(keystoreFlag.Name) - lightKdf = c.Bool(utils.LightKDFFlag.Name) - ) - am := core.StartClefAccountManager(ksLoc, true, lightKdf, "") - api := core.NewSignerAPI(am, 0, true, ui, nil, false, pwStorage) - internalApi := core.NewUIServerAPI(api) - return internalApi, ui, nil -} - -func setCredential(ctx *cli.Context) error { - if ctx.NArg() < 1 { - utils.Fatalf("This command requires an address to be passed as an argument") - } - if err := initialize(ctx); err != nil { - return err - } - addr := ctx.Args().First() - if !common.IsHexAddress(addr) { - utils.Fatalf("Invalid address specified: %s", addr) - } - address := common.HexToAddress(addr) - password := utils.GetPassPhrase("Please enter a password to store for this address:", true) - fmt.Println() - - stretchedKey, err := readMasterKey(ctx, nil) - if err != nil { - utils.Fatalf(err.Error()) - } - configDir := ctx.String(configdirFlag.Name) - vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) - pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey) - - pwStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey) - pwStorage.Put(address.Hex(), password) - - log.Info("Credential store updated", "set", address) - return nil -} - -func removeCredential(ctx *cli.Context) error { - if ctx.NArg() < 1 { - utils.Fatalf("This command requires an address to be passed as an argument") - } - if err := initialize(ctx); err != nil { - return err - } - addr := ctx.Args().First() - if !common.IsHexAddress(addr) { - utils.Fatalf("Invalid address specified: %s", addr) - } - address := common.HexToAddress(addr) - - stretchedKey, err := readMasterKey(ctx, nil) - if err != nil { - utils.Fatalf(err.Error()) - } - configDir := ctx.String(configdirFlag.Name) - vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) - pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey) - - pwStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey) - pwStorage.Del(address.Hex()) - - log.Info("Credential store updated", "unset", address) - return nil -} - -func initialize(c *cli.Context) error { - // Set up the logger to print everything - logOutput := os.Stdout - if c.Bool(stdiouiFlag.Name) { - logOutput = os.Stderr - // If using the stdioui, we can't do the 'confirm'-flow - if !c.Bool(acceptFlag.Name) { - fmt.Fprint(logOutput, legalWarning) - } - } else if !c.Bool(acceptFlag.Name) { - if !confirm(legalWarning) { - return errors.New("aborted by user") - } - fmt.Println() - } - usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb" - output := io.Writer(logOutput) - if usecolor { - output = colorable.NewColorable(logOutput) - } - verbosity := log.FromLegacyLevel(c.Int(logLevelFlag.Name)) - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(output, verbosity, usecolor))) - - return nil -} - -func newAccount(c *cli.Context) error { - internalApi, _, err := initInternalApi(c) - if err != nil { - return err - } - addr, err := internalApi.New(context.Background()) - if err == nil { - fmt.Printf("Generated account %v\n", addr.String()) - } - return err -} - -func listAccounts(c *cli.Context) error { - internalApi, _, err := initInternalApi(c) - if err != nil { - return err - } - accs, err := internalApi.ListAccounts(context.Background()) - if err != nil { - return err - } - if len(accs) == 0 { - fmt.Println("\nThe keystore is empty.") - } - fmt.Println() - for _, account := range accs { - fmt.Printf("%v (%v)\n", account.Address, account.URL) - } - return err -} - -func listWallets(c *cli.Context) error { - internalApi, _, err := initInternalApi(c) - if err != nil { - return err - } - wallets := internalApi.ListWallets() - if len(wallets) == 0 { - fmt.Println("\nThere are no wallets.") - } - fmt.Println() - for i, wallet := range wallets { - fmt.Printf("- Wallet %d at %v (%v %v)\n", i, wallet.URL, wallet.Status, wallet.Failure) - for j, acc := range wallet.Accounts { - fmt.Printf(" -Account %d: %v (%v)\n", j, acc.Address, acc.URL) - } - fmt.Println() - } - return nil -} - -// accountImport imports a raw hexadecimal private key via CLI. -func accountImport(c *cli.Context) error { - if c.Args().Len() != 1 { - return errors.New(" must be given as first argument.") - } - internalApi, ui, err := initInternalApi(c) - if err != nil { - return err - } - pKey, err := crypto.LoadECDSA(c.Args().First()) - if err != nil { - return err - } - readPw := func(prompt string) (string, error) { - resp, err := ui.OnInputRequired(core.UserInputRequest{ - Title: "Password", - Prompt: prompt, - IsPassword: true, - }) - if err != nil { - return "", err - } - return resp.Text, nil - } - first, err := readPw("Please enter a password for the imported account") - if err != nil { - return err - } - second, err := readPw("Please repeat the password you just entered") - if err != nil { - return err - } - if first != second { - //lint:ignore ST1005 This is a message for the user - return errors.New("Passwords do not match") - } - acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first) - if err != nil { - return err - } - ui.ShowInfo(fmt.Sprintf(`Key imported: - Address %v - Keystore file: %v - -The key is now encrypted; losing the password will result in permanently losing -access to the key and all associated funds! - -Make sure to backup keystore and passwords in a safe location.`, - acc.Address, acc.URL.Path)) - return nil -} - -// ipcEndpoint resolves an IPC endpoint based on a configured value, taking into -// account the set data folders as well as the designated platform we're currently -// running on. -func ipcEndpoint(ipcPath, datadir string) string { - // On windows we can only use plain top-level pipes - if runtime.GOOS == "windows" { - if strings.HasPrefix(ipcPath, `\\.\pipe\`) { - return ipcPath - } - return `\\.\pipe\` + ipcPath - } - // Resolve names into the data directory full paths otherwise - if filepath.Base(ipcPath) == ipcPath { - if datadir == "" { - return filepath.Join(os.TempDir(), ipcPath) - } - return filepath.Join(datadir, ipcPath) - } - return ipcPath -} - -func signer(c *cli.Context) error { - // If we have some unrecognized command, bail out - if c.NArg() > 0 { - return fmt.Errorf("invalid command: %q", c.Args().First()) - } - if err := initialize(c); err != nil { - return err - } - var ( - ui core.UIClientAPI - ) - if c.Bool(stdiouiFlag.Name) { - log.Info("Using stdin/stdout as UI-channel") - ui = core.NewStdIOUI() - } else { - log.Info("Using CLI as UI-channel") - ui = core.NewCommandlineUI() - } - // 4bytedb data - fourByteLocal := c.String(customDBFlag.Name) - db, err := fourbyte.NewWithFile(fourByteLocal) - if err != nil { - utils.Fatalf(err.Error()) - } - embeds, locals := db.Size() - log.Info("Loaded 4byte database", "embeds", embeds, "locals", locals, "local", fourByteLocal) - - var ( - api core.ExternalAPI - pwStorage storage.Storage = &storage.NoStorage{} - ) - configDir := c.String(configdirFlag.Name) - if stretchedKey, err := readMasterKey(c, ui); err != nil { - log.Warn("Failed to open master, rules disabled", "err", err) - } else { - vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) - - // Generate domain specific keys - pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey) - jskey := crypto.Keccak256([]byte("jsstorage"), stretchedKey) - confkey := crypto.Keccak256([]byte("config"), stretchedKey) - - // Initialize the encrypted storages - pwStorage = storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "credentials.json"), pwkey) - jsStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "jsstorage.json"), jskey) - configStorage := storage.NewAESEncryptedStorage(filepath.Join(vaultLocation, "config.json"), confkey) - - // Do we have a rule-file? - if ruleFile := c.String(ruleFlag.Name); ruleFile != "" { - ruleJS, err := os.ReadFile(ruleFile) - if err != nil { - log.Warn("Could not load rules, disabling", "file", ruleFile, "err", err) - } else { - shasum := sha256.Sum256(ruleJS) - foundShaSum := hex.EncodeToString(shasum[:]) - storedShasum, _ := configStorage.Get("ruleset_sha256") - if storedShasum != foundShaSum { - log.Warn("Rule hash not attested, disabling", "hash", foundShaSum, "attested", storedShasum) - } else { - // Initialize rules - ruleEngine, err := rules.NewRuleEvaluator(ui, jsStorage) - if err != nil { - utils.Fatalf(err.Error()) - } - ruleEngine.Init(string(ruleJS)) - ui = ruleEngine - log.Info("Rule engine configured", "file", c.String(ruleFlag.Name)) - } - } - } - } - var ( - chainId = c.Int64(chainIdFlag.Name) - ksLoc = c.String(keystoreFlag.Name) - lightKdf = c.Bool(utils.LightKDFFlag.Name) - advanced = c.Bool(advancedMode.Name) - nousb = c.Bool(utils.NoUSBFlag.Name) - scpath = c.String(utils.SmartCardDaemonPathFlag.Name) - ) - log.Info("Starting signer", "chainid", chainId, "keystore", ksLoc, - "light-kdf", lightKdf, "advanced", advanced) - am := core.StartClefAccountManager(ksLoc, nousb, lightKdf, scpath) - defer am.Close() - apiImpl := core.NewSignerAPI(am, chainId, nousb, ui, db, advanced, pwStorage) - - // Establish the bidirectional communication, by creating a new UI backend and registering - // it with the UI. - ui.RegisterUIServer(core.NewUIServerAPI(apiImpl)) - api = apiImpl - - // Audit logging - if logfile := c.String(auditLogFlag.Name); logfile != "" { - api, err = core.NewAuditLogger(logfile, api) - if err != nil { - utils.Fatalf(err.Error()) - } - log.Info("Audit logs configured", "file", logfile) - } - // register signer API with server - var ( - extapiURL = "n/a" - ipcapiURL = "n/a" - ) - rpcAPI := []rpc.API{ - { - Namespace: "account", - Service: api, - }, - } - if c.Bool(utils.HTTPEnabledFlag.Name) { - vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.Name)) - cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name)) - - srv := rpc.NewServer() - srv.SetBatchLimits(node.DefaultConfig.BatchRequestLimit, node.DefaultConfig.BatchResponseMaxSize) - err := node.RegisterApis(rpcAPI, []string{"account"}, srv) - if err != nil { - utils.Fatalf("Could not register API: %w", err) - } - handler := node.NewHTTPHandlerStack(srv, cors, vhosts, nil) - - // set port - port := c.Int(rpcPortFlag.Name) - - // start http server - httpEndpoint := net.JoinHostPort(c.String(utils.HTTPListenAddrFlag.Name), fmt.Sprintf("%d", port)) - httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler) - if err != nil { - utils.Fatalf("Could not start RPC api: %v", err) - } - extapiURL = fmt.Sprintf("http://%v/", addr) - log.Info("HTTP endpoint opened", "url", extapiURL) - - defer func() { - // Don't bother imposing a timeout here. - httpServer.Shutdown(context.Background()) - log.Info("HTTP endpoint closed", "url", extapiURL) - }() - } - if !c.Bool(utils.IPCDisabledFlag.Name) { - givenPath := c.String(utils.IPCPathFlag.Name) - ipcapiURL = ipcEndpoint(filepath.Join(givenPath, "clef.ipc"), configDir) - listener, _, err := rpc.StartIPCEndpoint(ipcapiURL, rpcAPI) - if err != nil { - utils.Fatalf("Could not start IPC api: %v", err) - } - log.Info("IPC endpoint opened", "url", ipcapiURL) - defer func() { - listener.Close() - log.Info("IPC endpoint closed", "url", ipcapiURL) - }() - } - if c.Bool(testFlag.Name) { - log.Info("Performing UI test") - go testExternalUI(apiImpl) - } - ui.OnSignerStartup(core.StartupInfo{ - Info: map[string]interface{}{ - "intapi_version": core.InternalAPIVersion, - "extapi_version": core.ExternalAPIVersion, - "extapi_http": extapiURL, - "extapi_ipc": ipcapiURL, - }}) - - abortChan := make(chan os.Signal, 1) - signal.Notify(abortChan, os.Interrupt) - - sig := <-abortChan - log.Info("Exiting...", "signal", sig) - - return nil -} - -// DefaultConfigDir is the default config directory to use for the vaults and other -// persistence requirements. -func DefaultConfigDir() string { - // Try to place the data folder in the user's home dir - home := flags.HomeDir() - if home != "" { - if runtime.GOOS == "darwin" { - return filepath.Join(home, "Library", "Signer") - } else if runtime.GOOS == "windows" { - appdata := os.Getenv("APPDATA") - if appdata != "" { - return filepath.Join(appdata, "Signer") - } - return filepath.Join(home, "AppData", "Roaming", "Signer") - } - return filepath.Join(home, ".clef") - } - // As we cannot guess a stable location, return empty and handle later - return "" -} - -func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) { - var ( - file string - configDir = ctx.String(configdirFlag.Name) - ) - if ctx.IsSet(signerSecretFlag.Name) { - file = ctx.String(signerSecretFlag.Name) - } else { - file = filepath.Join(configDir, "masterseed.json") - } - if err := checkFile(file); err != nil { - return nil, err - } - cipherKey, err := os.ReadFile(file) - if err != nil { - return nil, err - } - var password string - // If ui is not nil, get the password from ui. - if ui != nil { - resp, err := ui.OnInputRequired(core.UserInputRequest{ - Title: "Master Password", - Prompt: "Please enter the password to decrypt the master seed", - IsPassword: true}) - if err != nil { - return nil, err - } - password = resp.Text - } else { - password = utils.GetPassPhrase("Decrypt master seed of clef", false) - } - masterSeed, err := decryptSeed(cipherKey, password) - if err != nil { - return nil, errors.New("failed to decrypt the master seed of clef") - } - if len(masterSeed) < 256 { - return nil, fmt.Errorf("master seed of insufficient length, expected >255 bytes, got %d", len(masterSeed)) - } - // Create vault location - vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), masterSeed)[:10])) - err = os.Mkdir(vaultLocation, 0700) - if err != nil && !os.IsExist(err) { - return nil, err - } - return masterSeed, nil -} - -// checkFile is a convenience function to check if a file -// * exists -// * is mode 0400 (unix only) -func checkFile(filename string) error { - info, err := os.Stat(filename) - if err != nil { - return fmt.Errorf("failed stat on %s: %v", filename, err) - } - // Check the unix permission bits - // However, on windows, we cannot use the unix perm-bits, see - // https://github.com/ethereum/go-ethereum/issues/20123 - if runtime.GOOS != "windows" && info.Mode().Perm()&0377 != 0 { - return fmt.Errorf("file (%v) has insecure file permissions (%v)", filename, info.Mode().String()) - } - return nil -} - -// confirm displays a text and asks for user confirmation -func confirm(text string) bool { - fmt.Print(text) - fmt.Printf("\nEnter 'ok' to proceed:\n> ") - - text, err := bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - log.Crit("Failed to read user input", "err", err) - } - if text := strings.TrimSpace(text); text == "ok" { - return true - } - return false -} - -func testExternalUI(api *core.SignerAPI) { - ctx := context.WithValue(context.Background(), "remote", "clef binary") - ctx = context.WithValue(ctx, "scheme", "in-proc") - ctx = context.WithValue(ctx, "local", "main") - errs := make([]string, 0) - - a := common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef") - addErr := func(errStr string) { - log.Info("Test error", "err", errStr) - errs = append(errs, errStr) - } - - queryUser := func(q string) string { - resp, err := api.UI.OnInputRequired(core.UserInputRequest{ - Title: "Testing", - Prompt: q, - }) - if err != nil { - addErr(err.Error()) - } - return resp.Text - } - expectResponse := func(testcase, question, expect string) { - if got := queryUser(question); got != expect { - addErr(fmt.Sprintf("%s: got %v, expected %v", testcase, got, expect)) - } - } - expectApprove := func(testcase string, err error) { - if err == nil || err == accounts.ErrUnknownAccount { - return - } - addErr(fmt.Sprintf("%v: expected no error, got %v", testcase, err.Error())) - } - expectDeny := func(testcase string, err error) { - if err == nil || err != core.ErrRequestDenied { - addErr(fmt.Sprintf("%v: expected ErrRequestDenied, got %v", testcase, err)) - } - } - var delay = 1 * time.Second - // Test display of info and error - { - api.UI.ShowInfo("If you see this message, enter 'yes' to next question") - time.Sleep(delay) - expectResponse("showinfo", "Did you see the message? [yes/no]", "yes") - api.UI.ShowError("If you see this message, enter 'yes' to the next question") - time.Sleep(delay) - expectResponse("showerror", "Did you see the message? [yes/no]", "yes") - } - { // Sign data test - clique header - api.UI.ShowInfo("Please approve the next request for signing a clique header") - time.Sleep(delay) - cliqueHeader := types.Header{ - ParentHash: common.HexToHash("0000H45H"), - UncleHash: common.HexToHash("0000H45H"), - Coinbase: common.HexToAddress("0000H45H"), - Root: common.HexToHash("0000H00H"), - TxHash: common.HexToHash("0000H45H"), - ReceiptHash: common.HexToHash("0000H45H"), - Difficulty: big.NewInt(1337), - Number: big.NewInt(1337), - GasLimit: 1338, - GasUsed: 1338, - Time: 1338, - Extra: []byte("Extra data Extra data Extra data Extra data Extra data Extra data Extra data Extra data"), - MixDigest: common.HexToHash("0x0000H45H"), - } - cliqueRlp, err := rlp.EncodeToBytes(cliqueHeader) - if err != nil { - utils.Fatalf("Should not error: %v", err) - } - addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") - _, err = api.SignData(ctx, accounts.MimetypeClique, *addr, hexutil.Encode(cliqueRlp)) - expectApprove("signdata - clique header", err) - } - { // Sign data test - typed data - api.UI.ShowInfo("Please approve the next request for signing EIP-712 typed data") - time.Sleep(delay) - addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") - data := `{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"test","type":"uint8"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":"1","verifyingContract":"0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","test":"3","wallet":"0xcD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","test":"2"},"contents":"Hello, Bob!"}}` - //_, err := api.SignData(ctx, accounts.MimetypeTypedData, *addr, hexutil.Encode([]byte(data))) - var typedData apitypes.TypedData - json.Unmarshal([]byte(data), &typedData) - _, err := api.SignTypedData(ctx, *addr, typedData) - expectApprove("sign 712 typed data", err) - } - { // Sign data test - plain text - api.UI.ShowInfo("Please approve the next request for signing text") - time.Sleep(delay) - addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") - _, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world"))) - expectApprove("signdata - text", err) - } - { // Sign data test - plain text reject - api.UI.ShowInfo("Please deny the next request for signing text") - time.Sleep(delay) - addr, _ := common.NewMixedcaseAddressFromString("0x0011223344556677889900112233445566778899") - _, err := api.SignData(ctx, accounts.MimetypeTextPlain, *addr, hexutil.Encode([]byte("hello world"))) - expectDeny("signdata - text", err) - } - { // Sign transaction - api.UI.ShowInfo("Please reject next transaction") - time.Sleep(delay) - data := hexutil.Bytes([]byte{}) - to := common.NewMixedcaseAddress(a) - tx := apitypes.SendTxArgs{ - Data: &data, - Nonce: 0x1, - Value: hexutil.Big(*big.NewInt(6)), - From: common.NewMixedcaseAddress(a), - To: &to, - GasPrice: (*hexutil.Big)(big.NewInt(5)), - Gas: 1000, - Input: nil, - } - _, err := api.SignTransaction(ctx, tx, nil) - expectDeny("signtransaction [1]", err) - expectResponse("signtransaction [2]", "Did you see any warnings for the last transaction? (yes/no)", "no") - } - { // Listing - api.UI.ShowInfo("Please reject listing-request") - time.Sleep(delay) - _, err := api.List(ctx) - expectDeny("list", err) - } - { // Import - api.UI.ShowInfo("Please reject new account-request") - time.Sleep(delay) - _, err := api.New(ctx) - expectDeny("newaccount", err) - } - { // Metadata - api.UI.ShowInfo("Please check if you see the Origin in next listing (approve or deny)") - time.Sleep(delay) - api.List(context.WithValue(ctx, "Origin", "origin.com")) - expectResponse("metadata - origin", "Did you see origin (origin.com)? [yes/no] ", "yes") - } - - for _, e := range errs { - log.Error(e) - } - result := fmt.Sprintf("Tests completed. %d errors:\n%s\n", len(errs), strings.Join(errs, "\n")) - api.UI.ShowInfo(result) -} - -type encryptedSeedStorage struct { - Description string `json:"description"` - Version int `json:"version"` - Params keystore.CryptoJSON `json:"params"` -} - -// encryptSeed uses a similar scheme as the keystore uses, but with a different wrapping, -// to encrypt the master seed -func encryptSeed(seed []byte, auth []byte, scryptN, scryptP int) ([]byte, error) { - cryptoStruct, err := keystore.EncryptDataV3(seed, auth, scryptN, scryptP) - if err != nil { - return nil, err - } - return json.Marshal(&encryptedSeedStorage{"Clef seed", 1, cryptoStruct}) -} - -// decryptSeed decrypts the master seed -func decryptSeed(keyjson []byte, auth string) ([]byte, error) { - var encSeed encryptedSeedStorage - if err := json.Unmarshal(keyjson, &encSeed); err != nil { - return nil, err - } - if encSeed.Version != 1 { - log.Warn(fmt.Sprintf("unsupported encryption format of seed: %d, operation will likely fail", encSeed.Version)) - } - seed, err := keystore.DecryptDataV3(encSeed.Params, auth) - if err != nil { - return nil, err - } - return seed, err -} - -// GenDoc outputs examples of all structures used in json-rpc communication -func GenDoc(ctx *cli.Context) error { - var ( - a = common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef") - b = common.HexToAddress("0x1111111122222222222233333333334444444444") - meta = core.Metadata{ - Scheme: "http", - Local: "localhost:8545", - Origin: "www.malicious.ru", - Remote: "localhost:9999", - UserAgent: "Firefox 3.2", - } - output []string - add = func(name, desc string, v interface{}) { - if data, err := json.MarshalIndent(v, "", " "); err == nil { - output = append(output, fmt.Sprintf("### %s\n\n%s\n\nExample:\n```json\n%s\n```", name, desc, data)) - } else { - log.Error("Error generating output", "err", err) - } - } - ) - - { // Sign plain text request - desc := "SignDataRequest contains information about a pending request to sign some data. " + - "The data to be signed can be of various types, defined by content-type. Clef has done most " + - "of the work in canonicalizing and making sense of the data, and it's up to the UI to present" + - "the user with the contents of the `message`" - sighash, msg := accounts.TextAndHash([]byte("hello world")) - messages := []*apitypes.NameValueType{{Name: "message", Value: msg, Typ: accounts.MimetypeTextPlain}} - - add("SignDataRequest", desc, &core.SignDataRequest{ - Address: common.NewMixedcaseAddress(a), - Meta: meta, - ContentType: accounts.MimetypeTextPlain, - Rawdata: []byte(msg), - Messages: messages, - Hash: sighash}) - } - { // Sign plain text response - add("SignDataResponse - approve", "Response to SignDataRequest", - &core.SignDataResponse{Approved: true}) - add("SignDataResponse - deny", "Response to SignDataRequest", - &core.SignDataResponse{}) - } - { // Sign transaction request - desc := "SignTxRequest contains information about a pending request to sign a transaction. " + - "Aside from the transaction itself, there is also a `call_info`-struct. That struct contains " + - "messages of various types, that the user should be informed of." + - "\n\n" + - "As in any request, it's important to consider that the `meta` info also contains untrusted data." + - "\n\n" + - "The `transaction` (on input into clef) can have either `data` or `input` -- if both are set, " + - "they must be identical, otherwise an error is generated. " + - "However, Clef will always use `data` when passing this struct on (if Clef does otherwise, please file a ticket)" - - data := hexutil.Bytes([]byte{0x01, 0x02, 0x03, 0x04}) - add("SignTxRequest", desc, &core.SignTxRequest{ - Meta: meta, - Callinfo: []apitypes.ValidationInfo{ - {Typ: "Warning", Message: "Something looks odd, show this message as a warning"}, - {Typ: "Info", Message: "User should see this as well"}, - }, - Transaction: apitypes.SendTxArgs{ - Data: &data, - Nonce: 0x1, - Value: hexutil.Big(*big.NewInt(6)), - From: common.NewMixedcaseAddress(a), - To: nil, - GasPrice: (*hexutil.Big)(big.NewInt(5)), - Gas: 1000, - Input: nil, - }}) - } - { // Sign tx response - data := hexutil.Bytes([]byte{0x04, 0x03, 0x02, 0x01}) - add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+ - ", because the UI is free to make modifications to the transaction.", - &core.SignTxResponse{Approved: true, - Transaction: apitypes.SendTxArgs{ - Data: &data, - Nonce: 0x4, - Value: hexutil.Big(*big.NewInt(6)), - From: common.NewMixedcaseAddress(a), - To: nil, - GasPrice: (*hexutil.Big)(big.NewInt(5)), - Gas: 1000, - Input: nil, - }}) - add("SignTxResponse - deny", "Response to SignTxRequest. When denying a request, there's no need to "+ - "provide the transaction in return", - &core.SignTxResponse{}) - } - { // WHen a signed tx is ready to go out - desc := "SignTransactionResult is used in the call `clef` -> `OnApprovedTx(result)`" + - "\n\n" + - "This occurs _after_ successful completion of the entire signing procedure, but right before the signed " + - "transaction is passed to the external caller. This method (and data) can be used by the UI to signal " + - "to the user that the transaction was signed, but it is primarily useful for ruleset implementations." + - "\n\n" + - "A ruleset that implements a rate limitation needs to know what transactions are sent out to the external " + - "interface. By hooking into this methods, the ruleset can maintain track of that count." + - "\n\n" + - "**OBS:** Note that if an attacker can restore your `clef` data to a previous point in time" + - " (e.g through a backup), the attacker can reset such windows, even if he/she is unable to decrypt the content. " + - "\n\n" + - "The `OnApproved` method cannot be responded to, it's purely informative" - - rlpdata := common.FromHex("0xf85d640101948a8eafb1cf62bfbeb1741769dae1a9dd47996192018026a0716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293a04e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed") - var tx types.Transaction - tx.UnmarshalBinary(rlpdata) - add("OnApproved - SignTransactionResult", desc, ðapi.SignTransactionResult{Raw: rlpdata, Tx: &tx}) - } - { // User input - add("UserInputRequest", "Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)", - &core.UserInputRequest{IsPassword: true, Title: "The title here", Prompt: "The question to ask the user"}) - add("UserInputResponse", "Response to UserInputRequest", - &core.UserInputResponse{Text: "The textual response from user"}) - } - { // List request - add("ListRequest", "Sent when a request has been made to list addresses. The UI is provided with the "+ - "full `account`s, including local directory names. Note: this information is not passed back to the external caller, "+ - "who only sees the `address`es. ", - &core.ListRequest{ - Meta: meta, - Accounts: []accounts.Account{ - {Address: a, URL: accounts.URL{Scheme: "keystore", Path: "/path/to/keyfile/a"}}, - {Address: b, URL: accounts.URL{Scheme: "keystore", Path: "/path/to/keyfile/b"}}}, - }) - - add("ListResponse", "Response to list request. The response contains a list of all addresses to show to the caller. "+ - "Note: the UI is free to respond with any address the caller, regardless of whether it exists or not", - &core.ListResponse{ - Accounts: []accounts.Account{ - { - Address: common.HexToAddress("0xcowbeef000000cowbeef00000000000000000c0w"), - URL: accounts.URL{Path: ".. ignored .."}, - }, - { - Address: common.MaxAddress, - }, - }}) - } - - fmt.Println(`## UI Client interface - -These data types are defined in the channel between clef and the UI`) - for _, elem := range output { - fmt.Println(elem) - } - return nil -} diff --git a/builder/cmd/clef/pythonsigner.py b/builder/cmd/clef/pythonsigner.py deleted file mode 100644 index 5d0eb18dc..000000000 --- a/builder/cmd/clef/pythonsigner.py +++ /dev/null @@ -1,315 +0,0 @@ -import sys -import subprocess - -from tinyrpc.transports import ServerTransport -from tinyrpc.protocols.jsonrpc import JSONRPCProtocol -from tinyrpc.dispatch import public, RPCDispatcher -from tinyrpc.server import RPCServer - -""" -This is a POC example of how to write a custom UI for Clef. -The UI starts the clef process with the '--stdio-ui' option -and communicates with clef using standard input / output. - -The standard input/output is a relatively secure way to communicate, -as it does not require opening any ports or IPC files. Needless to say, -it does not protect against memory inspection mechanisms -where an attacker can access process memory. - -To make this work install all the requirements: - - pip install -r requirements.txt -""" - -try: - import urllib.parse as urlparse -except ImportError: - import urllib as urlparse - - -class StdIOTransport(ServerTransport): - """Uses std input/output for RPC""" - - def receive_message(self): - return None, urlparse.unquote(sys.stdin.readline()) - - def send_reply(self, context, reply): - print(reply) - - -class PipeTransport(ServerTransport): - """Uses std a pipe for RPC""" - - def __init__(self, input, output): - self.input = input - self.output = output - - def receive_message(self): - data = self.input.readline() - print(">> {}".format(data)) - return None, urlparse.unquote(data) - - def send_reply(self, context, reply): - reply = str(reply, "utf-8") - print("<< {}".format(reply)) - self.output.write("{}\n".format(reply)) - - -def sanitize(txt, limit=100): - return txt[:limit].encode("unicode_escape").decode("utf-8") - - -def metaString(meta): - """ - "meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""} - """ # noqa: E501 - message = ( - "\tRequest context:\n" - "\t\t{remote} -> {scheme} -> {local}\n" - "\tAdditional HTTP header data, provided by the external caller:\n" - "\t\tUser-Agent: {user_agent}\n" - "\t\tOrigin: {origin}\n" - ) - return message.format( - remote=meta.get("remote", ""), - scheme=meta.get("scheme", ""), - local=meta.get("local", ""), - user_agent=sanitize(meta.get("User-Agent"), 200), - origin=sanitize(meta.get("Origin"), 100), - ) - - -class StdIOHandler: - def __init__(self): - pass - - @public - def approveTx(self, req): - """ - Example request: - - {"jsonrpc":"2.0","id":20,"method":"ui_approveTx","params":[{"transaction":{"from":"0xDEADbEeF000000000000000000000000DeaDbeEf","to":"0xDEADbEeF000000000000000000000000DeaDbeEf","gas":"0x3e8","gasPrice":"0x5","maxFeePerGas":null,"maxPriorityFeePerGas":null,"value":"0x6","nonce":"0x1","data":"0x"},"call_info":null,"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]} - - :param transaction: transaction info - :param call_info: info about the call, e.g. if ABI info could not be - :param meta: metadata about the request, e.g. where the call comes from - :return: - """ # noqa: E501 - message = ( - "Sign transaction request:\n" - "\t{meta_string}\n" - "\n" - "\tFrom: {from_}\n" - "\tTo: {to}\n" - "\n" - "\tAuto-rejecting request" - ) - meta = req.get("meta", {}) - transaction = req.get("transaction") - sys.stdout.write( - message.format( - meta_string=metaString(meta), - from_=transaction.get("from", ""), - to=transaction.get("to", ""), - ) - ) - return { - "approved": False, - } - - @public - def approveSignData(self, req): - """ - Example request: - - {"jsonrpc":"2.0","id":8,"method":"ui_approveSignData","params":[{"content_type":"application/x-clique-header","address":"0x0011223344556677889900112233445566778899","raw_data":"+QIRoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIIFOYIFOYIFOoIFOoIFOppFeHRyYSBkYXRhIEV4dHJhIGRhdGEgRXh0cqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAAAAAAAAA==","messages":[{"name":"Clique header","value":"clique header 1337 [0x44381ab449d77774874aca34634cb53bc21bd22aef2d3d4cf40e51176cb585ec]","type":"clique"}],"call_info":null,"hash":"0xa47ab61438a12a06c81420e308c2b7aae44e9cd837a5df70dd021421c0f58643","meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]} - """ # noqa: E501 - message = ( - "Sign data request:\n" - "\t{meta_string}\n" - "\n" - "\tContent-type: {content_type}\n" - "\tAddress: {address}\n" - "\tHash: {hash_}\n" - "\n" - "\tAuto-rejecting request\n" - ) - meta = req.get("meta", {}) - sys.stdout.write( - message.format( - meta_string=metaString(meta), - content_type=req.get("content_type"), - address=req.get("address"), - hash_=req.get("hash"), - ) - ) - - return { - "approved": False, - "password": None, - } - - @public - def approveNewAccount(self, req): - """ - Example request: - - {"jsonrpc":"2.0","id":25,"method":"ui_approveNewAccount","params":[{"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]} - """ # noqa: E501 - message = ( - "Create new account request:\n" - "\t{meta_string}\n" - "\n" - "\tAuto-rejecting request\n" - ) - meta = req.get("meta", {}) - sys.stdout.write(message.format(meta_string=metaString(meta))) - return { - "approved": False, - } - - @public - def showError(self, req): - """ - Example request: - - {"jsonrpc":"2.0","method":"ui_showError","params":[{"text":"If you see this message, enter 'yes' to the next question"}]} - - :param message: to display - :return:nothing - """ # noqa: E501 - message = ( - "## Error\n{text}\n" - "Press enter to continue\n" - ) - text = req.get("text") - sys.stdout.write(message.format(text=text)) - input() - return - - @public - def showInfo(self, req): - """ - Example request: - - {"jsonrpc":"2.0","method":"ui_showInfo","params":[{"text":"If you see this message, enter 'yes' to next question"}]} - - :param message: to display - :return:nothing - """ # noqa: E501 - message = ( - "## Info\n{text}\n" - "Press enter to continue\n" - ) - text = req.get("text") - sys.stdout.write(message.format(text=text)) - input() - return - - @public - def onSignerStartup(self, req): - """ - Example request: - - {"jsonrpc":"2.0", "method":"ui_onSignerStartup", "params":[{"info":{"extapi_http":"n/a","extapi_ipc":"/home/user/.clef/clef.ipc","extapi_version":"6.1.0","intapi_version":"7.0.1"}}]} - """ # noqa: E501 - message = ( - "\n" - "\t\tExt api url: {extapi_http}\n" - "\t\tInt api ipc: {extapi_ipc}\n" - "\t\tExt api ver: {extapi_version}\n" - "\t\tInt api ver: {intapi_version}\n" - ) - info = req.get("info") - sys.stdout.write( - message.format( - extapi_http=info.get("extapi_http"), - extapi_ipc=info.get("extapi_ipc"), - extapi_version=info.get("extapi_version"), - intapi_version=info.get("intapi_version"), - ) - ) - - @public - def approveListing(self, req): - """ - Example request: - - {"jsonrpc":"2.0","id":23,"method":"ui_approveListing","params":[{"accounts":[{"address":... - """ # noqa: E501 - message = ( - "\n" - "## Account listing request\n" - "\t{meta_string}\n" - "\tDo you want to allow listing the following accounts?\n" - "\t-{addrs}\n" - "\n" - "->Auto-answering No\n" - ) - meta = req.get("meta", {}) - accounts = req.get("accounts", []) - addrs = [x.get("address") for x in accounts] - sys.stdout.write( - message.format( - addrs="\n\t-".join(addrs), - meta_string=metaString(meta) - ) - ) - return {} - - @public - def onInputRequired(self, req): - """ - Example request: - - {"jsonrpc":"2.0","id":1,"method":"ui_onInputRequired","params":[{"title":"Master Password","prompt":"Please enter the password to decrypt the master seed","isPassword":true}]} - - :param message: to display - :return:nothing - """ # noqa: E501 - message = ( - "\n" - "## {title}\n" - "\t{prompt}\n" - "\n" - "> " - ) - sys.stdout.write( - message.format( - title=req.get("title"), - prompt=req.get("prompt") - ) - ) - isPassword = req.get("isPassword") - if not isPassword: - return {"text": input()} - - return "" - - -def main(args): - cmd = ["clef", "--stdio-ui"] - if len(args) > 0 and args[0] == "test": - cmd.extend(["--stdio-ui-test"]) - print("cmd: {}".format(" ".join(cmd))) - - dispatcher = RPCDispatcher() - dispatcher.register_instance(StdIOHandler(), "ui_") - - # line buffered - p = subprocess.Popen( - cmd, - bufsize=1, - universal_newlines=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - ) - - rpc_server = RPCServer( - PipeTransport(p.stdout, p.stdin), JSONRPCProtocol(), dispatcher - ) - rpc_server.serve_forever() - - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/builder/cmd/clef/requirements.txt b/builder/cmd/clef/requirements.txt deleted file mode 100644 index 5381862e3..000000000 --- a/builder/cmd/clef/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -tinyrpc==1.1.4 diff --git a/builder/cmd/clef/rules.md b/builder/cmd/clef/rules.md deleted file mode 100644 index 112dae651..000000000 --- a/builder/cmd/clef/rules.md +++ /dev/null @@ -1,234 +0,0 @@ -# Rules - -The `signer` binary contains a ruleset engine, implemented with [OttoVM](https://github.com/robertkrimen/otto) - -It enables usecases like the following: - -* I want to auto-approve transactions with contract `CasinoDapp`, with up to `0.05 ether` in value to maximum `1 ether` per 24h period -* I want to auto-approve transaction to contract `EthAlarmClock` with `data`=`0xdeadbeef`, if `value=0`, `gas < 44k` and `gasPrice < 40Gwei` - -The two main features that are required for this to work well are; - -1. Rule Implementation: how to create, manage and interpret rules in a flexible but secure manner -2. Credential managements and credentials; how to provide auto-unlock without exposing keys unnecessarily. - -The section below deals with both of them - -## Rule Implementation - -A ruleset file is implemented as a `js` file. Under the hood, the ruleset-engine is a `SignerUI`, implementing the same methods as the `json-rpc` methods -defined in the UI protocol. Example: - -```js -function asBig(str) { - if (str.slice(0, 2) == "0x") { - return new BigNumber(str.slice(2), 16) - } - return new BigNumber(str) -} - -// Approve transactions to a certain contract if value is below a certain limit -function ApproveTx(req) { - var limit = big.Newint("0xb1a2bc2ec50000") - var value = asBig(req.transaction.value); - - if (req.transaction.to.toLowerCase() == "0xae967917c465db8578ca9024c205720b1a3651a9") && value.lt(limit)) { - return "Approve" - } - // If we return "Reject", it will be rejected. - // By not returning anything, it will be passed to the next UI, for manual processing -} - -// Approve listings if request made from IPC -function ApproveListing(req){ - if (req.metadata.scheme == "ipc"){ return "Approve"} -} -``` - -Whenever the external API is called (and the ruleset is enabled), the `signer` calls the UI, which is an instance of a ruleset-engine. The ruleset-engine -invokes the corresponding method. In doing so, there are three possible outcomes: - -1. JS returns "Approve" - * Auto-approve request -2. JS returns "Reject" - * Auto-reject request -3. Error occurs, or something else is returned - * Pass on to `next` ui: the regular UI channel. - -A more advanced example can be found below, "Example 1: ruleset for a rate-limited window", using `storage` to `Put` and `Get` `string`s by key. - -* At the time of writing, storage only exists as an ephemeral unencrypted implementation, to be used during testing. - -### Things to note - -The Otto vm has a few [caveats](https://github.com/robertkrimen/otto): - -* "use strict" will parse, but does nothing. -* The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. -* Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. - -Additionally, a few more have been added - -* The rule execution cannot load external javascript files. -* The only preloaded library is [`bignumber.js`](https://github.com/MikeMcl/bignumber.js) version `2.0.3`. This one is fairly old, and is not aligned with the documentation at the github repository. -* Each invocation is made in a fresh virtual machine. This means that you cannot store data in global variables between invocations. This is a deliberate choice -- if you want to store data, use the disk-backed `storage`, since rules should not rely on ephemeral data. -* Javascript API parameters are _always_ an object. This is also a design choice, to ensure that parameters are accessed by _key_ and not by order. This is to prevent mistakes due to missing parameters or parameter changes. -* The JS engine has access to `storage` and `console`. - -#### Security considerations - -##### Security of ruleset - -Some security precautions can be made, such as: - -* Never load `ruleset.js` unless the file is `readonly` (`r-??-??-?`). If the user wishes to modify the ruleset, he must make it writeable and then set back to readonly. - * This is to prevent attacks where files are dropped on the users disk. -* Since we're going to have to have some form of secure storage (not defined in this section), we could also store the `sha3` of the `ruleset.js` file in there. - * If the user wishes to modify the ruleset, he'd then have to perform e.g. `signer --attest /path/to/ruleset --credential ` - -##### Security of implementation - -The drawbacks of this very flexible solution is that the `signer` needs to contain a javascript engine. This is pretty simple to implement, since it's already -implemented for `geth`. There are no known security vulnerabilities in, nor have we had any security-problems with it so far. - -The javascript engine would be an added attack surface; but if the validation of `rulesets` is made good (with hash-based attestation), the actual javascript cannot be considered -an attack surface -- if an attacker can control the ruleset, a much simpler attack would be to implement an "always-approve" rule instead of exploiting the js vm. The only benefit -to be gained from attacking the actual `signer` process from the `js` side would be if it could somehow extract cryptographic keys from memory. - -##### Security in usability - -Javascript is flexible, but also easy to get wrong, especially when users assume that `js` can handle large integers natively. Typical errors -include trying to multiply `gasCost` with `gas` without using `bigint`:s. - -It's unclear whether any other DSL could be more secure; since there's always the possibility of erroneously implementing a rule. - - -## Credential management - -The ability to auto-approve transaction means that the signer needs to have necessary credentials to decrypt keyfiles. These passwords are hereafter called `ksp` (keystore pass). - -### Example implementation - -Upon startup of the signer, the signer is given a switch: `--seed ` -The `seed` contains a blob of bytes, which is the master seed for the `signer`. - -The `signer` uses the `seed` to: - -* Generate the `path` where the settings are stored. - * `./settings/1df094eb-c2b1-4689-90dd-790046d38025/vault.dat` - * `./settings/1df094eb-c2b1-4689-90dd-790046d38025/rules.js` -* Generate the encryption password for `vault.dat`. - -The `vault.dat` would be an encrypted container storing the following information: - -* `ksp` entries -* `sha256` hash of `rules.js` -* Information about pair:ed callers (not yet specified) - -### Security considerations - -This would leave it up to the user to ensure that the `path/to/masterseed` is handled in a secure way. It's difficult to get around this, although one could -imagine leveraging OS-level keychains where supported. The setup is however in general similar to how ssh-keys are stored in `.ssh/`. - - -# Implementation status - -This is now implemented (with ephemeral non-encrypted storage for now, so not yet enabled). - -## Example 1: ruleset for a rate-limited window - - -```js -function big(str) { - if (str.slice(0, 2) == "0x") { - return new BigNumber(str.slice(2), 16) - } - return new BigNumber(str) -} - -// Time window: 1 week -var window = 1000* 3600*24*7; - -// Limit : 1 ether -var limit = new BigNumber("1e18"); - -function isLimitOk(transaction) { - var value = big(transaction.value) - // Start of our window function - var windowstart = new Date().getTime() - window; - - var txs = []; - var stored = storage.get('txs'); - - if (stored != "") { - txs = JSON.parse(stored) - } - // First, remove all that have passed out of the time-window - var newtxs = txs.filter(function(tx){return tx.tstamp > windowstart}); - console.log(txs, newtxs.length); - - // Secondly, aggregate the current sum - sum = new BigNumber(0) - - sum = newtxs.reduce(function(agg, tx){ return big(tx.value).plus(agg)}, sum); - console.log("ApproveTx > Sum so far", sum); - console.log("ApproveTx > Requested", value.toNumber()); - - // Would we exceed weekly limit ? - return sum.plus(value).lt(limit) - -} -function ApproveTx(r) { - if (isLimitOk(r.transaction)) { - return "Approve" - } - return "Nope" -} - -/** -* OnApprovedTx(str) is called when a transaction has been approved and signed. The parameter - * 'response_str' contains the return value that will be sent to the external caller. -* The return value from this method is ignore - the reason for having this callback is to allow the -* ruleset to keep track of approved transactions. -* -* When implementing rate-limited rules, this callback should be used. -* If a rule responds with neither 'Approve' nor 'Reject' - the tx goes to manual processing. If the user -* then accepts the transaction, this method will be called. -* -* TLDR; Use this method to keep track of signed transactions, instead of using the data in ApproveTx. -*/ -function OnApprovedTx(resp) { - var value = big(resp.tx.value) - var txs = [] - // Load stored transactions - var stored = storage.get('txs'); - if (stored != "") { - txs = JSON.parse(stored) - } - // Add this to the storage - txs.push({tstamp: new Date().getTime(), value: value}); - storage.put("txs", JSON.stringify(txs)); -} -``` - -## Example 2: allow destination - -```js -function ApproveTx(r) { - if (r.transaction.from.toLowerCase() == "0x0000000000000000000000000000000000001337") { - return "Approve" - } - if (r.transaction.from.toLowerCase() == "0x000000000000000000000000000000000000dead") { - return "Reject" - } - // Otherwise goes to manual processing -} -``` - -## Example 3: Allow listing - -```js -function ApproveListing() { - return "Approve" -} -``` diff --git a/builder/cmd/clef/run_test.go b/builder/cmd/clef/run_test.go deleted file mode 100644 index 5fa6e02e1..000000000 --- a/builder/cmd/clef/run_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "testing" - - "github.com/ethereum/go-ethereum/internal/cmdtest" - "github.com/ethereum/go-ethereum/internal/reexec" -) - -const registeredName = "clef-test" - -type testproc struct { - *cmdtest.TestCmd - - // template variables for expect - Datadir string - Etherbase string -} - -func init() { - reexec.Register(registeredName, func() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - os.Exit(0) - }) -} - -func TestMain(m *testing.M) { - // check if we have been reexec'd - if reexec.Init() { - return - } - os.Exit(m.Run()) -} - -// runClef spawns clef with the given command line args and adds keystore arg. -// This method creates a temporary keystore folder which will be removed after -// the test exits. -func runClef(t *testing.T, args ...string) *testproc { - ddir, err := os.MkdirTemp("", "cleftest-*") - if err != nil { - return nil - } - t.Cleanup(func() { - os.RemoveAll(ddir) - }) - return runWithKeystore(t, ddir, args...) -} - -// runWithKeystore spawns clef with the given command line args and adds keystore arg. -// This method does _not_ create the keystore folder, but it _does_ add the arg -// to the args. -func runWithKeystore(t *testing.T, keystore string, args ...string) *testproc { - args = append([]string{"--keystore", keystore}, args...) - tt := &testproc{Datadir: keystore} - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - // Boot "clef". This actually runs the test binary but the TestMain - // function will prevent any tests from running. - tt.Run(registeredName, args...) - return tt -} - -func (proc *testproc) input(text string) *testproc { - proc.TestCmd.InputLine(text) - return proc -} - -/* -// waitForEndpoint waits for the rpc endpoint to appear, or -// aborts after 3 seconds. -func (proc *testproc) waitForEndpoint(t *testing.T) *testproc { - t.Helper() - timeout := 3 * time.Second - ipc := filepath.Join(proc.Datadir, "clef.ipc") - - start := time.Now() - for time.Since(start) < timeout { - if _, err := os.Stat(ipc); !errors.Is(err, os.ErrNotExist) { - t.Logf("endpoint %v opened", ipc) - return proc - } - time.Sleep(200 * time.Millisecond) - } - t.Logf("stderr: \n%v", proc.StderrText()) - t.Logf("stdout: \n%v", proc.Output()) - t.Fatal("endpoint", ipc, "did not open within", timeout) - return proc -} -*/ diff --git a/builder/cmd/clef/sign_flow.png b/builder/cmd/clef/sign_flow.png deleted file mode 100644 index e7010ab43..000000000 Binary files a/builder/cmd/clef/sign_flow.png and /dev/null differ diff --git a/builder/cmd/clef/testdata/sign_1559_missing_field_exp_fail.json b/builder/cmd/clef/testdata/sign_1559_missing_field_exp_fail.json deleted file mode 100644 index c5a133686..000000000 --- a/builder/cmd/clef/testdata/sign_1559_missing_field_exp_fail.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "gas": "0x333", - "maxFeePerGas": "0x123", - "nonce": "0x0", - "value": "0x10", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - } - ], - "id": 67 -} diff --git a/builder/cmd/clef/testdata/sign_1559_missing_maxfeepergas_exp_fail.json b/builder/cmd/clef/testdata/sign_1559_missing_maxfeepergas_exp_fail.json deleted file mode 100644 index df69231d7..000000000 --- a/builder/cmd/clef/testdata/sign_1559_missing_maxfeepergas_exp_fail.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "gas": "0x333", - "maxPriorityFeePerGas": "0x123", - "nonce": "0x0", - "value": "0x10", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - } - ], - "id": 67 -} diff --git a/builder/cmd/clef/testdata/sign_1559_tx.json b/builder/cmd/clef/testdata/sign_1559_tx.json deleted file mode 100644 index 29355f6cf..000000000 --- a/builder/cmd/clef/testdata/sign_1559_tx.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "gas": "0x333", - "maxPriorityFeePerGas": "0x123", - "maxFeePerGas": "0x123", - "nonce": "0x0", - "value": "0x10", - "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - } - ], - "id": 67 -} diff --git a/builder/cmd/clef/testdata/sign_bad_checksum_exp_fail.json b/builder/cmd/clef/testdata/sign_bad_checksum_exp_fail.json deleted file mode 100644 index 21ba7b3fc..000000000 --- a/builder/cmd/clef/testdata/sign_bad_checksum_exp_fail.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from":"0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "to":"0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "gas": "0x333", - "gasPrice": "0x123", - "nonce": "0x0", - "value": "0x10", - "data": - "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - } - ], - "id": 67 -} diff --git a/builder/cmd/clef/testdata/sign_normal_exp_ok.json b/builder/cmd/clef/testdata/sign_normal_exp_ok.json deleted file mode 100644 index 7f3a9202a..000000000 --- a/builder/cmd/clef/testdata/sign_normal_exp_ok.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "account_signTransaction", - "params": [ - { - "from":"0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "to":"0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192", - "gas": "0x333", - "gasPrice": "0x123", - "nonce": "0x0", - "value": "0x10", - "data": - "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" - } - ], - "id": 67 -} diff --git a/builder/cmd/clef/tests/testsigner.js b/builder/cmd/clef/tests/testsigner.js deleted file mode 100644 index 258679de5..000000000 --- a/builder/cmd/clef/tests/testsigner.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// This file is a test-utility for testing clef-functionality -// -// Start clef with -// -// build/bin/clef --4bytedb=./cmd/clef/4byte.json --rpc -// -// Start geth with -// -// build/bin/geth --nodiscover --maxpeers 0 --signer http://localhost:8550 console --preload=cmd/clef/tests/testsigner.js -// -// and in the console simply invoke -// -// > test() -// -// You can reload the file via `reload()` - -function reload(){ - loadScript("./cmd/clef/tests/testsigner.js"); -} - -function init(){ - if (typeof accts == 'undefined' || accts.length == 0){ - accts = eth.accounts - console.log("Got accounts ", accts); - } -} -init() -function testTx(){ - if( accts && accts.length > 0) { - var a = accts[0] - var txdata = eth.signTransaction({from: a, to: a, value: 1, nonce: 1, gas: 1, gasPrice: 1}) - var v = parseInt(txdata.tx.v) - console.log("V value: ", v) - if (v == 37 || v == 38){ - console.log("Mainnet 155-protected chainid was used") - } - if (v == 27 || v == 28){ - throw new Error("Mainnet chainid was used, but without replay protection!") - } - } -} -function testSignText(){ - if( accts && accts.length > 0){ - var a = accts[0] - var r = eth.sign(a, "0x68656c6c6f20776f726c64"); //hello world - console.log("signing response", r) - } -} -function testClique(){ - if( accts && accts.length > 0){ - var a = accts[0] - var r = debug.testSignCliqueBlock(a, 0); // Sign genesis - console.log("signing response", r) - if( a != r){ - throw new Error("Requested signing by "+a+ " but got sealer "+r) - } - } -} - -function test(){ - var tests = [ - testTx, - testSignText, - testClique, - ] - for( i in tests){ - try{ - tests[i]() - }catch(err){ - console.log(err) - } - } - } diff --git a/builder/cmd/clef/tutorial.md b/builder/cmd/clef/tutorial.md deleted file mode 100644 index 3ea662b5d..000000000 --- a/builder/cmd/clef/tutorial.md +++ /dev/null @@ -1,353 +0,0 @@ -## Initializing Clef - -First things first, Clef needs to store some data itself. Since that data might be sensitive (passwords, signing rules, accounts), Clef's entire storage is encrypted. To support encrypting data, the first step is to initialize Clef with a random master seed, itself too encrypted with your chosen password: - -```text -$ clef init - -WARNING! - -Clef is an account management tool. It may, like any software, contain bugs. - -Please take care to -- backup your keystore files, -- verify that the keystore(s) can be opened with your password. - -Clef 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. - -Enter 'ok' to proceed: -> ok - -The master seed of clef will be locked with a password. -Please specify a password. Do not forget this password! -Password: -Repeat password: - -A master seed has been generated into /home/martin/.clef/masterseed.json - -This is required to be able to store credentials, such as: -* Passwords for keystores (used by rule engine) -* Storage for JavaScript auto-signing rules -* Hash of JavaScript rule-file - -You should treat 'masterseed.json' with utmost secrecy and make a backup of it! -* The password is necessary but not enough, you need to back up the master seed too! -* The master seed does not contain your accounts, those need to be backed up separately! -``` - -*For readability purposes, we'll remove the WARNING printout, user confirmation and the unlocking of the master seed in the rest of this document.* - -## Remote interactions - -Clef is capable of managing both key-file based accounts as well as hardware wallets. To evaluate clef, we're going to point it to our Rinkeby testnet keystore and specify the Rinkeby chain ID for signing (Clef doesn't have a backing chain, so it doesn't know what network it runs on). - -```text -$ clef --keystore ~/.ethereum/rinkeby/keystore --chainid 4 - -INFO [07-01|11:00:46.385] Starting signer chainid=4 keystore=$HOME/.ethereum/rinkeby/keystore light-kdf=false advanced=false -DEBUG[07-01|11:00:46.389] FS scan times list=3.521941ms set=9.017µs diff=4.112µs -DEBUG[07-01|11:00:46.391] Ledger support enabled -DEBUG[07-01|11:00:46.391] Trezor support enabled via HID -DEBUG[07-01|11:00:46.391] Trezor support enabled via WebUSB -INFO [07-01|11:00:46.391] Audit logs configured file=audit.log -DEBUG[07-01|11:00:46.392] IPC registered namespace=account -INFO [07-01|11:00:46.392] IPC endpoint opened url=$HOME/.clef/clef.ipc -------- Signer info ------- -* intapi_version : 7.0.0 -* extapi_version : 6.0.0 -* extapi_http : n/a -* extapi_ipc : $HOME/.clef/clef.ipc -``` - -By default, Clef starts up in CLI (Command Line Interface) mode. Arbitrary remote processes may *request* account interactions (e.g. sign a transaction), which the user will need to individually *confirm*. - -To test this out, we can *request* Clef to list all account via its *External API endpoint*: - -```text -echo '{"id": 1, "jsonrpc": "2.0", "method": "account_list"}' | nc -U ~/.clef/clef.ipc -``` - -This will prompt the user within the Clef CLI to confirm or deny the request: - -```text --------- List Account request-------------- -A request has been made to list all accounts. -You can select which accounts the caller can see - [x] 0xD9C9Cd5f6779558b6e0eD4e6Acf6b1947E7fA1F3 - URL: keystore://$HOME/.ethereum/rinkeby/keystore/UTC--2017-04-14T15-15-00.327614556Z--d9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3 - [x] 0x086278A6C067775F71d6B2BB1856Db6E28c30418 - URL: keystore://$HOME/.ethereum/rinkeby/keystore/UTC--2018-02-06T22-53-11.211657239Z--086278a6c067775f71d6b2bb1856db6e28c30418 -------------------------------------------- -Request context: - NA -> NA -> NA - -Additional HTTP header data, provided by the external caller: - User-Agent: - Origin: -Approve? [y/N]: -> -``` - -Depending on whether we approve or deny the request, the original NetCat process will get: - -```text -{"jsonrpc":"2.0","id":1,"result":["0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3","0x086278a6c067775f71d6b2bb1856db6e28c30418"]} - -or - -{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"Request denied"}} -``` - -Apart from listing accounts, you can also *request* creating a new account; signing transactions and data; and recovering signatures. You can find the available methods in the Clef [External API Spec](https://github.com/ethereum/go-ethereum/tree/master/cmd/clef#external-api-1) and the [External API Changelog](https://github.com/ethereum/go-ethereum/blob/master/cmd/clef/extapi_changelog.md). - -*Note, the number of things you can do from the External API is deliberately small, since we want to limit the power of remote calls by as much as possible! Clef has an [Internal API](https://github.com/ethereum/go-ethereum/tree/master/cmd/clef#ui-api-1) too for the UI (User Interface) which is much richer and can support custom interfaces on top. But that's out of scope here.* - -## Automatic rules - -For most users, manually confirming every transaction is the way to go. However, there are cases when it makes sense to set up some rules which permit Clef to sign a transaction without prompting the user. One such example would be running a signer on Rinkeby or other PoA networks. - -For starters, we can create a rule file that automatically permits anyone to list our available accounts without user confirmation. The rule file is a tiny JavaScript snippet that you can program however you want: - -```js -function ApproveListing() { - return "Approve" -} -``` - -Of course, Clef isn't going to just accept and run arbitrary scripts you give it, that would be dangerous if someone changes your rule file! Instead, you need to explicitly *attest* the rule file, which entails injecting its hash into Clef's secure store. - -```text -$ sha256sum rules.js -645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c rules.js - -$ clef attest 645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c -Decrypt master seed of clef -Password: -INFO [07-01|13:25:03.290] Ruleset attestation updated sha256=645b58e4f945e24d0221714ff29f6aa8e860382ced43490529db1695f5fcc71c -``` - -At this point, we can start Clef with the rule file: - -```text -$ clef --keystore ~/.ethereum/rinkeby/keystore --chainid 4 --rules rules.js - -INFO [07-01|13:39:49.726] Rule engine configured file=rules.js -INFO [07-01|13:39:49.726] Starting signer chainid=4 keystore=$HOME/.ethereum/rinkeby/keystore light-kdf=false advanced=false -DEBUG[07-01|13:39:49.726] FS scan times list=35.15µs set=4.251µs diff=2.766µs -DEBUG[07-01|13:39:49.727] Ledger support enabled -DEBUG[07-01|13:39:49.727] Trezor support enabled via HID -DEBUG[07-01|13:39:49.727] Trezor support enabled via WebUSB -INFO [07-01|13:39:49.728] Audit logs configured file=audit.log -DEBUG[07-01|13:39:49.728] IPC registered namespace=account -INFO [07-01|13:39:49.728] IPC endpoint opened url=$HOME/.clef/clef.ipc -------- Signer info ------- -* intapi_version : 7.0.0 -* extapi_version : 6.0.0 -* extapi_http : n/a -* extapi_ipc : $HOME/.clef/clef.ipc -``` - -Any account listing *request* will now be auto-approved by the rule file: - -```text -$ echo '{"id": 1, "jsonrpc": "2.0", "method": "account_list"}' | nc -U ~/.clef/clef.ipc -{"jsonrpc":"2.0","id":1,"result":["0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3","0x086278a6c067775f71d6b2bb1856db6e28c30418"]} -``` - -## Under the hood - -While doing the operations above, these files have been created: - -```text -$ ls -laR ~/.clef/ - -$HOME/.clef/: -total 24 -drwxr-x--x 3 user user 4096 Jul 1 13:45 . -drwxr-xr-x 102 user user 12288 Jul 1 13:39 .. -drwx------ 2 user user 4096 Jul 1 13:25 02f90c0603f4f2f60188 --r-------- 1 user user 868 Jun 28 13:55 masterseed.json - -$HOME/.clef/02f90c0603f4f2f60188: -total 12 -drwx------ 2 user user 4096 Jul 1 13:25 . -drwxr-x--x 3 user user 4096 Jul 1 13:45 .. --rw------- 1 user user 159 Jul 1 13:25 config.json - -$ cat ~/.clef/02f90c0603f4f2f60188/config.json -{"ruleset_sha256":{"iv":"SWWEtnl+R+I+wfG7","c":"I3fjmwmamxVcfGax7D0MdUOL29/rBWcs73WBILmYK0o1CrX7wSMc3y37KsmtlZUAjp0oItYq01Ow8VGUOzilG91tDHInB5YHNtm/YkufEbo="}} -``` - -In `$HOME/.clef`, the `masterseed.json` file was created, containing the master seed. This seed was then used to derive a few other things: - -- **Vault location**: in this case `02f90c0603f4f2f60188`. - - If you use a different master seed, a different vault location will be used that does not conflict with each other (e.g. `clef --signersecret /path/to/file`). This allows you to run multiple instances of Clef, each with its own rules (e.g. mainnet + testnet). -- **`config.json`**: the encrypted key/value storage for configuration data, currently only containing the key `ruleset_sha256`, the attested hash of the automatic rules to use. - -## Advanced rules - -In order to make more useful rules - like signing transactions - the signer needs access to the passwords needed to unlock keys from the keystore. You can inject an unlock password via `clef setpw`. - -```text -$ clef setpw 0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3 - -Please enter a password to store for this address: -Password: -Repeat password: - -Decrypt master seed of clef -Password: -INFO [07-01|14:05:56.031] Credential store updated key=0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3 -``` - -Now let's update the rules to make use of the new credentials: - -```js -function ApproveListing() { - return "Approve" -} - -function ApproveSignData(req) { - if (req.address.toLowerCase() == "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3") { - if (req.messages[0].value.indexOf("bazonk") >= 0) { - return "Approve" - } - return "Reject" - } - // Otherwise goes to manual processing -} -``` - -In this example: - -- Any requests to sign data with the account `0xd9c9...` will be: - - Auto-approved if the message contains `bazonk`, - - Auto-rejected if the message does not contain `bazonk`, -- Any other requests will be passed along for manual confirmation. - -*Note, to make this example work, please use you own accounts. You can create a new account either via Clef or the traditional account CLI tools. If the latter was chosen, make sure both Clef and Geth use the same keystore by specifying `--keystore path/to/your/keystore` when running Clef.* - -Attest the new rule file so that Clef will accept loading it: - -```text -$ sha256sum rules.js -f163a1738b649259bb9b369c593fdc4c6b6f86cc87e343c3ba58faee03c2a178 rules.js - -$ clef attest f163a1738b649259bb9b369c593fdc4c6b6f86cc87e343c3ba58faee03c2a178 -Decrypt master seed of clef -Password: -INFO [07-01|14:11:28.509] Ruleset attestation updated sha256=f163a1738b649259bb9b369c593fdc4c6b6f86cc87e343c3ba58faee03c2a178 -``` - -Restart Clef with the new rules in place: - -``` -$ clef --keystore ~/.ethereum/rinkeby/keystore --chainid 4 --rules rules.js - -INFO [07-01|14:12:41.636] Rule engine configured file=rules.js -INFO [07-01|14:12:41.636] Starting signer chainid=4 keystore=$HOME/.ethereum/rinkeby/keystore light-kdf=false advanced=false -DEBUG[07-01|14:12:41.636] FS scan times list=46.722µs set=4.47µs diff=2.157µs -DEBUG[07-01|14:12:41.637] Ledger support enabled -DEBUG[07-01|14:12:41.637] Trezor support enabled via HID -DEBUG[07-01|14:12:41.638] Trezor support enabled via WebUSB -INFO [07-01|14:12:41.638] Audit logs configured file=audit.log -DEBUG[07-01|14:12:41.638] IPC registered namespace=account -INFO [07-01|14:12:41.638] IPC endpoint opened url=$HOME/.clef/clef.ipc -------- Signer info ------- -* intapi_version : 7.0.0 -* extapi_version : 6.0.0 -* extapi_http : n/a -* extapi_ipc : $HOME/.clef/clef.ipc -``` - -Then test signing, once with `bazonk` and once without: - -``` -$ echo '{"id": 1, "jsonrpc":"2.0", "method":"account_signData", "params":["data/plain", "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3", "0x202062617a6f6e6b2062617a2067617a0a"]}' | nc -U ~/.clef/clef.ipc -{"jsonrpc":"2.0","id":1,"result":"0x4f93e3457027f6be99b06b3392d0ebc60615ba448bb7544687ef1248dea4f5317f789002df783979c417d969836b6fda3710f5bffb296b4d51c8aaae6e2ac4831c"} - -$ echo '{"id": 1, "jsonrpc":"2.0", "method":"account_signData", "params":["data/plain", "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3", "0x2020626f6e6b2062617a2067617a0a"]}' | nc -U ~/.clef/clef.ipc -{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"Request denied"}} -``` - -Meanwhile, in the Clef output log you can see: -```text -INFO [02-21|14:42:41] Op approved -INFO [02-21|14:42:56] Op rejected -``` - -The signer also stores all traffic over the external API in a log file. The last 4 lines shows the two requests and their responses: - -```text -$ tail -n 4 audit.log -t=2019-07-01T15:52:14+0300 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"NA\",\"local\":\"NA\",\"scheme\":\"NA\",\"User-Agent\":\"\",\"Origin\":\"\"}" addr="0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3 [chksum INVALID]" data=0x202062617a6f6e6b2062617a2067617a0a content-type=data/plain -t=2019-07-01T15:52:14+0300 lvl=info msg=SignData api=signer type=response data=4f93e3457027f6be99b06b3392d0ebc60615ba448bb7544687ef1248dea4f5317f789002df783979c417d969836b6fda3710f5bffb296b4d51c8aaae6e2ac4831c error=nil -t=2019-07-01T15:52:23+0300 lvl=info msg=SignData api=signer type=request metadata="{\"remote\":\"NA\",\"local\":\"NA\",\"scheme\":\"NA\",\"User-Agent\":\"\",\"Origin\":\"\"}" addr="0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3 [chksum INVALID]" data=0x2020626f6e6b2062617a2067617a0a content-type=data/plain -t=2019-07-01T15:52:23+0300 lvl=info msg=SignData api=signer type=response data= error="Request denied" -``` - -For more details on writing automatic rules, please see the [rules spec](https://github.com/ethereum/go-ethereum/blob/master/cmd/clef/rules.md). - -## Geth integration - -Of course, as awesome as Clef is, it's not feasible to interact with it via JSON RPC by hand. Long term, we're hoping to convince the general Ethereum community to support Clef as a general signer (it's only 3-5 methods), thus allowing your favorite DApp, Metamask, MyCrypto, etc to request signatures directly. - -Until then however, we're trying to pave the way via Geth. Geth v1.9.0 has built in support via `--signer ` for using a local or remote Clef instance as an account backend! - -We can try this by running Clef with our previous rules on Rinkeby (for now it's a good idea to allow auto-listing accounts, since Geth likes to retrieve them once in a while). - -```text -$ clef --keystore ~/.ethereum/rinkeby/keystore --chainid 4 --rules rules.js -``` - -In a different window we can start Geth, list our accounts, even list our wallets to see where the accounts originate from: - -```text -$ geth --rinkeby --signer=~/.clef/clef.ipc console - -> eth.accounts -["0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3", "0x086278a6c067775f71d6b2bb1856db6e28c30418"] - -> personal.listWallets -[{ - accounts: [{ - address: "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3", - url: "extapi://$HOME/.clef/clef.ipc" - }, { - address: "0x086278a6c067775f71d6b2bb1856db6e28c30418", - url: "extapi://$HOME/.clef/clef.ipc" - }], - status: "ok [version=6.0.0]", - url: "extapi://$HOME/.clef/clef.ipc" -}] - -> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[0]}) -``` - -Lastly, when we requested a transaction to be sent, Clef prompted us in the original window to approve it: - -```text ---------- Transaction request------------- -to: 0xD9C9Cd5f6779558b6e0eD4e6Acf6b1947E7fA1F3 -from: 0xD9C9Cd5f6779558b6e0eD4e6Acf6b1947E7fA1F3 [chksum ok] -value: 0 wei -gas: 0x5208 (21000) -gasprice: 1000000000 wei -nonce: 0x2366 (9062) - -Request context: - NA -> NA -> NA - -Additional HTTP header data, provided by the external caller: - User-Agent: - Origin: -------------------------------------------- -Approve? [y/N]: -> y -``` - -:boom: - -*Note, if you enable the external signer backend in Geth, all other account management is disabled. This is because long term we want to remove account management from Geth.* diff --git a/builder/cmd/devp2p/README.md b/builder/cmd/devp2p/README.md deleted file mode 100644 index 284dfe0a4..000000000 --- a/builder/cmd/devp2p/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# The devp2p command - -The devp2p command line tool is a utility for low-level peer-to-peer debugging and -protocol development purposes. It can do many things. - -### ENR Decoding - -Use `devp2p enrdump ` to verify and display an Ethereum Node Record. - -### Node Key Management - -The `devp2p key ...` command family deals with node key files. - -Run `devp2p key generate mynode.key` to create a new node key in the `mynode.key` file. - -Run `devp2p key to-enode mynode.key -ip 127.0.0.1 -tcp 30303` to create an enode:// URL -corresponding to the given node key and address information. - -### Maintaining DNS Discovery Node Lists - -The devp2p command can create and publish DNS discovery node lists. - -Run `devp2p dns sign ` to update the signature of a DNS discovery tree. - -Run `devp2p dns sync ` to download a complete DNS discovery tree. - -Run `devp2p dns to-cloudflare ` to publish a tree to CloudFlare DNS. - -Run `devp2p dns to-route53 ` to publish a tree to Amazon Route53. - -You can find more information about these commands in the [DNS Discovery Setup Guide][dns-tutorial]. - -### Node Set Utilities - -There are several commands for working with JSON node set files. These files are generated -by the discovery crawlers and DNS client commands. Node sets also used as the input of the -DNS deployer commands. - -Run `devp2p nodeset info ` to display statistics of a node set. - -Run `devp2p nodeset filter ` to write a new, filtered node -set to standard output. The following filters are supported: - -- `-limit ` limits the output set to N entries, taking the top N nodes by score -- `-ip ` filters nodes by IP subnet -- `-min-age ` filters nodes by 'first seen' time -- `-eth-network ` filters nodes by "eth" ENR entry -- `-les-server` filters nodes by LES server support -- `-snap` filters nodes by snap protocol support - -For example, given a node set in `nodes.json`, you could create a filtered set containing -up to 20 eth mainnet nodes which also support snap sync using this command: - - devp2p nodeset filter nodes.json -eth-network mainnet -snap -limit 20 - -### Discovery v4 Utilities - -The `devp2p discv4 ...` command family deals with the [Node Discovery v4][discv4] -protocol. - -Run `devp2p discv4 ping ` to ping a node. - -Run `devp2p discv4 resolve ` to find the most recent node record of a node in -the DHT. - -Run `devp2p discv4 crawl ` to create or update a JSON node set. - -### Discovery v5 Utilities - -The `devp2p discv5 ...` command family deals with the [Node Discovery v5][discv5] -protocol. This protocol is currently under active development. - -Run `devp2p discv5 ping ` to ping a node. - -Run `devp2p discv5 resolve ` to find the most recent node record of a node in -the discv5 DHT. - -Run `devp2p discv5 listen` to run a Discovery v5 node. - -Run `devp2p discv5 crawl ` to create or update a JSON node set containing -discv5 nodes. - -### Discovery Test Suites - -The devp2p command also contains interactive test suites for Discovery v4 and Discovery -v5. - -To run these tests against your implementation, you need to set up a networking -environment where two separate UDP listening addresses are available on the same machine. -The two listening addresses must also be routed such that they are able to reach the node -you want to test. - -For example, if you want to run the test on your local host, and the node under test is -also on the local host, you need to assign two IP addresses (or a larger range) to your -loopback interface. On macOS, this can be done by executing the following command: - - sudo ifconfig lo0 add 127.0.0.2 - -You can now run either test suite as follows: Start the node under test first, ensuring -that it won't talk to the Internet (i.e. disable bootstrapping). An easy way to prevent -unintended connections to the global DHT is listening on `127.0.0.1`. - -Now get the ENR of your node and store it in the `NODE` environment variable. - -Start the test by running `devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.0.2 $NODE`. - -### Eth Protocol Test Suite - -The Eth Protocol test suite is a conformance test suite for the [eth protocol][eth]. - -To run the eth protocol test suite against your implementation, the node needs to be initialized -with our test chain. The chain files are located in `./cmd/devp2p/internal/ethtest/testdata`. - -1. initialize the geth node with the `genesis.json` file -2. import blocks from `chain.rlp` -3. run the client using the resulting database. For geth, use a command like the one below: - - geth \ - --datadir \ - --nodiscover \ - --nat=none \ - --networkid 3503995874084926 \ - --verbosity 5 \ - --authrpc.jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365 - -Note that the tests also require access to the engine API. -The test suite can now be executed using the devp2p tool. - - devp2p rlpx eth-test \ - --chain internal/ethtest/testdata \ - --node enode://.... \ - --engineapi http://127.0.0.1:8551 \ - --jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365 - -Repeat the above process (re-initialising the node) in order to run the Eth Protocol test suite again. - - -[eth]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md -[dns-tutorial]: https://geth.ethereum.org/docs/developers/geth-developer/dns-discovery-setup -[discv4]: https://github.com/ethereum/devp2p/tree/master/discv4.md -[discv5]: https://github.com/ethereum/devp2p/tree/master/discv5/discv5.md diff --git a/builder/cmd/devp2p/crawl.go b/builder/cmd/devp2p/crawl.go deleted file mode 100644 index 4288a5feb..000000000 --- a/builder/cmd/devp2p/crawl.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -type crawler struct { - input nodeSet - output nodeSet - disc resolver - iters []enode.Iterator - inputIter enode.Iterator - ch chan *enode.Node - closed chan struct{} - - // settings - revalidateInterval time.Duration - mu sync.RWMutex -} - -const ( - nodeRemoved = iota - nodeSkipRecent - nodeSkipIncompat - nodeAdded - nodeUpdated -) - -type resolver interface { - RequestENR(*enode.Node) (*enode.Node, error) -} - -func newCrawler(input nodeSet, bootnodes []*enode.Node, disc resolver, iters ...enode.Iterator) (*crawler, error) { - if len(input) == 0 { - input.add(bootnodes...) - } - if len(input) == 0 { - return nil, errors.New("no input nodes to start crawling") - } - - c := &crawler{ - input: input, - output: make(nodeSet, len(input)), - disc: disc, - iters: iters, - inputIter: enode.IterNodes(input.nodes()), - ch: make(chan *enode.Node), - closed: make(chan struct{}), - } - c.iters = append(c.iters, c.inputIter) - // Copy input to output initially. Any nodes that fail validation - // will be dropped from output during the run. - for id, n := range input { - c.output[id] = n - } - return c, nil -} - -func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet { - var ( - timeoutTimer = time.NewTimer(timeout) - timeoutCh <-chan time.Time - statusTicker = time.NewTicker(time.Second * 8) - doneCh = make(chan enode.Iterator, len(c.iters)) - liveIters = len(c.iters) - ) - if nthreads < 1 { - nthreads = 1 - } - defer timeoutTimer.Stop() - defer statusTicker.Stop() - for _, it := range c.iters { - go c.runIterator(doneCh, it) - } - var ( - added atomic.Uint64 - updated atomic.Uint64 - skipped atomic.Uint64 - recent atomic.Uint64 - removed atomic.Uint64 - wg sync.WaitGroup - ) - wg.Add(nthreads) - for i := 0; i < nthreads; i++ { - go func() { - defer wg.Done() - for { - select { - case n := <-c.ch: - switch c.updateNode(n) { - case nodeSkipIncompat: - skipped.Add(1) - case nodeSkipRecent: - recent.Add(1) - case nodeRemoved: - removed.Add(1) - case nodeAdded: - added.Add(1) - default: - updated.Add(1) - } - case <-c.closed: - return - } - } - }() - } - -loop: - for { - select { - case it := <-doneCh: - if it == c.inputIter { - // Enable timeout when we're done revalidating the input nodes. - log.Info("Revalidation of input set is done", "len", len(c.input)) - if timeout > 0 { - timeoutCh = timeoutTimer.C - } - } - if liveIters--; liveIters == 0 { - break loop - } - case <-timeoutCh: - break loop - case <-statusTicker.C: - log.Info("Crawling in progress", - "added", added.Load(), - "updated", updated.Load(), - "removed", removed.Load(), - "ignored(recent)", recent.Load(), - "ignored(incompatible)", skipped.Load()) - } - } - - close(c.closed) - for _, it := range c.iters { - it.Close() - } - for ; liveIters > 0; liveIters-- { - <-doneCh - } - wg.Wait() - return c.output -} - -func (c *crawler) runIterator(done chan<- enode.Iterator, it enode.Iterator) { - defer func() { done <- it }() - for it.Next() { - select { - case c.ch <- it.Node(): - case <-c.closed: - return - } - } -} - -// updateNode updates the info about the given node, and returns a status -// about what changed -func (c *crawler) updateNode(n *enode.Node) int { - c.mu.RLock() - node, ok := c.output[n.ID()] - c.mu.RUnlock() - - // Skip validation of recently-seen nodes. - if ok && time.Since(node.LastCheck) < c.revalidateInterval { - return nodeSkipRecent - } - - // Request the node record. - status := nodeUpdated - node.LastCheck = truncNow() - if nn, err := c.disc.RequestENR(n); err != nil { - if node.Score == 0 { - // Node doesn't implement EIP-868. - log.Debug("Skipping node", "id", n.ID()) - return nodeSkipIncompat - } - node.Score /= 2 - } else { - node.N = nn - node.Seq = nn.Seq() - node.Score++ - if node.FirstResponse.IsZero() { - node.FirstResponse = node.LastCheck - status = nodeAdded - } - node.LastResponse = node.LastCheck - } - // Store/update node in output set. - c.mu.Lock() - defer c.mu.Unlock() - if node.Score <= 0 { - log.Debug("Removing node", "id", n.ID()) - delete(c.output, n.ID()) - return nodeRemoved - } - log.Debug("Updating node", "id", n.ID(), "seq", n.Seq(), "score", node.Score) - c.output[n.ID()] = node - return status -} - -func truncNow() time.Time { - return time.Now().UTC().Truncate(1 * time.Second) -} diff --git a/builder/cmd/devp2p/discv4cmd.go b/builder/cmd/devp2p/discv4cmd.go deleted file mode 100644 index 45bcdcd36..000000000 --- a/builder/cmd/devp2p/discv4cmd.go +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "net" - "strconv" - "strings" - "time" - - "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" - "github.com/urfave/cli/v2" -) - -var ( - discv4Command = &cli.Command{ - Name: "discv4", - Usage: "Node Discovery v4 tools", - Subcommands: []*cli.Command{ - discv4PingCommand, - discv4RequestRecordCommand, - discv4ResolveCommand, - discv4ResolveJSONCommand, - discv4CrawlCommand, - discv4TestCommand, - }, - } - discv4PingCommand = &cli.Command{ - Name: "ping", - Usage: "Sends ping to a node", - Action: discv4Ping, - ArgsUsage: "", - Flags: discoveryNodeFlags, - } - discv4RequestRecordCommand = &cli.Command{ - Name: "requestenr", - Usage: "Requests a node record using EIP-868 enrRequest", - Action: discv4RequestRecord, - ArgsUsage: "", - Flags: discoveryNodeFlags, - } - discv4ResolveCommand = &cli.Command{ - Name: "resolve", - Usage: "Finds a node in the DHT", - Action: discv4Resolve, - ArgsUsage: "", - Flags: discoveryNodeFlags, - } - discv4ResolveJSONCommand = &cli.Command{ - Name: "resolve-json", - Usage: "Re-resolves nodes in a nodes.json file", - Action: discv4ResolveJSON, - Flags: discoveryNodeFlags, - ArgsUsage: "", - } - discv4CrawlCommand = &cli.Command{ - Name: "crawl", - Usage: "Updates a nodes.json file with random nodes found in the DHT", - Action: discv4Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}), - } - discv4TestCommand = &cli.Command{ - Name: "test", - Usage: "Runs tests against a node", - Action: discv4Test, - Flags: []cli.Flag{ - remoteEnodeFlag, - testPatternFlag, - testTAPFlag, - testListen1Flag, - testListen2Flag, - }, - } -) - -var ( - bootnodesFlag = &cli.StringFlag{ - Name: "bootnodes", - Usage: "Comma separated nodes used for bootstrapping", - } - nodekeyFlag = &cli.StringFlag{ - Name: "nodekey", - Usage: "Hex-encoded node key", - } - nodedbFlag = &cli.StringFlag{ - Name: "nodedb", - Usage: "Nodes database location", - } - listenAddrFlag = &cli.StringFlag{ - Name: "addr", - Usage: "Listening address", - } - extAddrFlag = &cli.StringFlag{ - Name: "extaddr", - Usage: "UDP endpoint announced in ENR. You can provide a bare IP address or IP:port as the value of this flag.", - } - crawlTimeoutFlag = &cli.DurationFlag{ - Name: "timeout", - Usage: "Time limit for the crawl.", - Value: 30 * time.Minute, - } - crawlParallelismFlag = &cli.IntFlag{ - Name: "parallel", - Usage: "How many parallel discoveries to attempt.", - Value: 16, - } - remoteEnodeFlag = &cli.StringFlag{ - Name: "remote", - Usage: "Enode of the remote node under test", - EnvVars: []string{"REMOTE_ENODE"}, - } -) - -var discoveryNodeFlags = []cli.Flag{ - bootnodesFlag, - nodekeyFlag, - nodedbFlag, - listenAddrFlag, - extAddrFlag, -} - -func discv4Ping(ctx *cli.Context) error { - n := getNodeArg(ctx) - disc, _ := startV4(ctx) - defer disc.Close() - - start := time.Now() - if err := disc.Ping(n); err != nil { - return fmt.Errorf("node didn't respond: %v", err) - } - fmt.Printf("node responded to ping (RTT %v).\n", time.Since(start)) - return nil -} - -func discv4RequestRecord(ctx *cli.Context) error { - n := getNodeArg(ctx) - disc, _ := startV4(ctx) - defer disc.Close() - - respN, err := disc.RequestENR(n) - if err != nil { - return fmt.Errorf("can't retrieve record: %v", err) - } - fmt.Println(respN.String()) - return nil -} - -func discv4Resolve(ctx *cli.Context) error { - n := getNodeArg(ctx) - disc, _ := startV4(ctx) - defer disc.Close() - - fmt.Println(disc.Resolve(n).String()) - return nil -} - -func discv4ResolveJSON(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need nodes file as argument") - } - nodesFile := ctx.Args().Get(0) - inputSet := make(nodeSet) - if common.FileExist(nodesFile) { - inputSet = loadNodesJSON(nodesFile) - } - - // Add extra nodes from command line arguments. - var nodeargs []*enode.Node - for i := 1; i < ctx.NArg(); i++ { - n, err := parseNode(ctx.Args().Get(i)) - if err != nil { - exit(err) - } - nodeargs = append(nodeargs, n) - } - - disc, config := startV4(ctx) - defer disc.Close() - - c, err := newCrawler(inputSet, config.Bootnodes, disc, enode.IterNodes(nodeargs)) - if err != nil { - return err - } - c.revalidateInterval = 0 - output := c.run(0, 1) - writeNodesJSON(nodesFile, output) - return nil -} - -func discv4Crawl(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need nodes file as argument") - } - nodesFile := ctx.Args().First() - inputSet := make(nodeSet) - if common.FileExist(nodesFile) { - inputSet = loadNodesJSON(nodesFile) - } - - disc, config := startV4(ctx) - defer disc.Close() - - c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes()) - if err != nil { - return err - } - c.revalidateInterval = 10 * time.Minute - output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) - writeNodesJSON(nodesFile, output) - return nil -} - -// discv4Test runs the protocol test suite. -func discv4Test(ctx *cli.Context) error { - // Configure test package globals. - if !ctx.IsSet(remoteEnodeFlag.Name) { - return fmt.Errorf("missing -%v", remoteEnodeFlag.Name) - } - v4test.Remote = ctx.String(remoteEnodeFlag.Name) - v4test.Listen1 = ctx.String(testListen1Flag.Name) - v4test.Listen2 = ctx.String(testListen2Flag.Name) - return runTests(ctx, v4test.AllTests) -} - -// startV4 starts an ephemeral discovery V4 node. -func startV4(ctx *cli.Context) (*discover.UDPv4, discover.Config) { - ln, config := makeDiscoveryConfig(ctx) - socket := listen(ctx, ln) - disc, err := discover.ListenV4(socket, ln, config) - if err != nil { - exit(err) - } - return disc, config -} - -func makeDiscoveryConfig(ctx *cli.Context) (*enode.LocalNode, discover.Config) { - var cfg discover.Config - - if ctx.IsSet(nodekeyFlag.Name) { - key, err := crypto.HexToECDSA(ctx.String(nodekeyFlag.Name)) - if err != nil { - exit(fmt.Errorf("-%s: %v", nodekeyFlag.Name, err)) - } - cfg.PrivateKey = key - } else { - cfg.PrivateKey, _ = crypto.GenerateKey() - } - - if commandHasFlag(ctx, bootnodesFlag) { - bn, err := parseBootnodes(ctx) - if err != nil { - exit(err) - } - cfg.Bootnodes = bn - } - - dbpath := ctx.String(nodedbFlag.Name) - db, err := enode.OpenDB(dbpath) - if err != nil { - exit(err) - } - ln := enode.NewLocalNode(db, cfg.PrivateKey) - return ln, cfg -} - -func parseExtAddr(spec string) (ip net.IP, port int, ok bool) { - ip = net.ParseIP(spec) - if ip != nil { - return ip, 0, true - } - host, portstr, err := net.SplitHostPort(spec) - if err != nil { - return nil, 0, false - } - ip = net.ParseIP(host) - if ip == nil { - return nil, 0, false - } - port, err = strconv.Atoi(portstr) - if err != nil { - return nil, 0, false - } - return ip, port, true -} - -func listen(ctx *cli.Context, ln *enode.LocalNode) *net.UDPConn { - addr := ctx.String(listenAddrFlag.Name) - if addr == "" { - addr = "0.0.0.0:0" - } - socket, err := net.ListenPacket("udp4", addr) - if err != nil { - exit(err) - } - - // Configure UDP endpoint in ENR from listener address. - usocket := socket.(*net.UDPConn) - uaddr := socket.LocalAddr().(*net.UDPAddr) - if uaddr.IP.IsUnspecified() { - ln.SetFallbackIP(net.IP{127, 0, 0, 1}) - } else { - ln.SetFallbackIP(uaddr.IP) - } - ln.SetFallbackUDP(uaddr.Port) - - // If an ENR endpoint is set explicitly on the command-line, override - // the information from the listening address. Note this is careful not - // to set the UDP port if the external address doesn't have it. - extAddr := ctx.String(extAddrFlag.Name) - if extAddr != "" { - ip, port, ok := parseExtAddr(extAddr) - if !ok { - exit(fmt.Errorf("-%s: invalid external address %q", extAddrFlag.Name, extAddr)) - } - ln.SetStaticIP(ip) - if port != 0 { - ln.SetFallbackUDP(port) - } - } - - return usocket -} - -func parseBootnodes(ctx *cli.Context) ([]*enode.Node, error) { - s := params.MainnetBootnodes - if ctx.IsSet(bootnodesFlag.Name) { - input := ctx.String(bootnodesFlag.Name) - if input == "" { - return nil, nil - } - s = strings.Split(input, ",") - } - nodes := make([]*enode.Node, len(s)) - var err error - for i, record := range s { - nodes[i], err = parseNode(record) - if err != nil { - return nil, fmt.Errorf("invalid bootstrap node: %v", err) - } - } - return nodes, nil -} diff --git a/builder/cmd/devp2p/discv5cmd.go b/builder/cmd/devp2p/discv5cmd.go deleted file mode 100644 index 0dac94526..000000000 --- a/builder/cmd/devp2p/discv5cmd.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/urfave/cli/v2" -) - -var ( - discv5Command = &cli.Command{ - Name: "discv5", - Usage: "Node Discovery v5 tools", - Subcommands: []*cli.Command{ - discv5PingCommand, - discv5ResolveCommand, - discv5CrawlCommand, - discv5TestCommand, - discv5ListenCommand, - }, - } - discv5PingCommand = &cli.Command{ - Name: "ping", - Usage: "Sends ping to a node", - Action: discv5Ping, - Flags: discoveryNodeFlags, - } - discv5ResolveCommand = &cli.Command{ - Name: "resolve", - Usage: "Finds a node in the DHT", - Action: discv5Resolve, - Flags: discoveryNodeFlags, - } - discv5CrawlCommand = &cli.Command{ - Name: "crawl", - Usage: "Updates a nodes.json file with random nodes found in the DHT", - Action: discv5Crawl, - Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{ - crawlTimeoutFlag, - }), - } - discv5TestCommand = &cli.Command{ - Name: "test", - Usage: "Runs protocol tests against a node", - Action: discv5Test, - Flags: []cli.Flag{ - testPatternFlag, - testTAPFlag, - testListen1Flag, - testListen2Flag, - }, - } - discv5ListenCommand = &cli.Command{ - Name: "listen", - Usage: "Runs a node", - Action: discv5Listen, - Flags: discoveryNodeFlags, - } -) - -func discv5Ping(ctx *cli.Context) error { - n := getNodeArg(ctx) - disc, _ := startV5(ctx) - defer disc.Close() - - fmt.Println(disc.Ping(n)) - return nil -} - -func discv5Resolve(ctx *cli.Context) error { - n := getNodeArg(ctx) - disc, _ := startV5(ctx) - defer disc.Close() - - fmt.Println(disc.Resolve(n)) - return nil -} - -func discv5Crawl(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need nodes file as argument") - } - nodesFile := ctx.Args().First() - inputSet := make(nodeSet) - if common.FileExist(nodesFile) { - inputSet = loadNodesJSON(nodesFile) - } - - disc, config := startV5(ctx) - defer disc.Close() - - c, err := newCrawler(inputSet, config.Bootnodes, disc, disc.RandomNodes()) - if err != nil { - return err - } - c.revalidateInterval = 10 * time.Minute - output := c.run(ctx.Duration(crawlTimeoutFlag.Name), ctx.Int(crawlParallelismFlag.Name)) - writeNodesJSON(nodesFile, output) - return nil -} - -// discv5Test runs the protocol test suite. -func discv5Test(ctx *cli.Context) error { - suite := &v5test.Suite{ - Dest: getNodeArg(ctx), - Listen1: ctx.String(testListen1Flag.Name), - Listen2: ctx.String(testListen2Flag.Name), - } - return runTests(ctx, suite.AllTests()) -} - -func discv5Listen(ctx *cli.Context) error { - disc, _ := startV5(ctx) - defer disc.Close() - - fmt.Println(disc.Self()) - select {} -} - -// startV5 starts an ephemeral discovery v5 node. -func startV5(ctx *cli.Context) (*discover.UDPv5, discover.Config) { - ln, config := makeDiscoveryConfig(ctx) - socket := listen(ctx, ln) - disc, err := discover.ListenV5(socket, ln, config) - if err != nil { - exit(err) - } - return disc, config -} diff --git a/builder/cmd/devp2p/dns_cloudflare.go b/builder/cmd/devp2p/dns_cloudflare.go deleted file mode 100644 index a3cc69cf1..000000000 --- a/builder/cmd/devp2p/dns_cloudflare.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "context" - "errors" - "fmt" - "strings" - - "github.com/cloudflare/cloudflare-go" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/dnsdisc" - "github.com/urfave/cli/v2" -) - -var ( - cloudflareTokenFlag = &cli.StringFlag{ - Name: "token", - Usage: "CloudFlare API token", - EnvVars: []string{"CLOUDFLARE_API_TOKEN"}, - } - cloudflareZoneIDFlag = &cli.StringFlag{ - Name: "zoneid", - Usage: "CloudFlare Zone ID (optional)", - } -) - -type cloudflareClient struct { - *cloudflare.API - zoneID string -} - -// newCloudflareClient sets up a CloudFlare API client from command line flags. -func newCloudflareClient(ctx *cli.Context) *cloudflareClient { - token := ctx.String(cloudflareTokenFlag.Name) - if token == "" { - exit(errors.New("need cloudflare API token to proceed")) - } - api, err := cloudflare.NewWithAPIToken(token) - if err != nil { - exit(fmt.Errorf("can't create Cloudflare client: %v", err)) - } - return &cloudflareClient{ - API: api, - zoneID: ctx.String(cloudflareZoneIDFlag.Name), - } -} - -// deploy uploads the given tree to CloudFlare DNS. -func (c *cloudflareClient) deploy(name string, t *dnsdisc.Tree) error { - if err := c.checkZone(name); err != nil { - return err - } - records := t.ToTXT(name) - return c.uploadRecords(name, records) -} - -// checkZone verifies permissions on the CloudFlare DNS Zone for name. -func (c *cloudflareClient) checkZone(name string) error { - if c.zoneID == "" { - log.Info(fmt.Sprintf("Finding CloudFlare zone ID for %s", name)) - id, err := c.ZoneIDByName(name) - if err != nil { - return err - } - c.zoneID = id - } - log.Info(fmt.Sprintf("Checking Permissions on zone %s", c.zoneID)) - zone, err := c.ZoneDetails(context.Background(), c.zoneID) - if err != nil { - return err - } - if !strings.HasSuffix(name, "."+zone.Name) { - return fmt.Errorf("CloudFlare zone name %q does not match name %q to be deployed", zone.Name, name) - } - needPerms := map[string]bool{"#zone:edit": false, "#zone:read": false} - for _, perm := range zone.Permissions { - if _, ok := needPerms[perm]; ok { - needPerms[perm] = true - } - } - for _, ok := range needPerms { - if !ok { - return fmt.Errorf("wrong permissions on zone %s: %v", c.zoneID, needPerms) - } - } - return nil -} - -// uploadRecords updates the TXT records at a particular subdomain. All non-root records -// will have a TTL of "infinity" and all existing records not in the new map will be -// nuked! -func (c *cloudflareClient) uploadRecords(name string, records map[string]string) error { - // Convert all names to lowercase. - lrecords := make(map[string]string, len(records)) - for name, r := range records { - lrecords[strings.ToLower(name)] = r - } - records = lrecords - - log.Info(fmt.Sprintf("Retrieving existing TXT records on %s", name)) - entries, _, err := c.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), cloudflare.ListDNSRecordsParams{Type: "TXT"}) - if err != nil { - return err - } - existing := make(map[string]cloudflare.DNSRecord) - for _, entry := range entries { - if !strings.HasSuffix(entry.Name, name) { - continue - } - existing[strings.ToLower(entry.Name)] = entry - } - - // Iterate over the new records and inject anything missing. - log.Info("Updating DNS entries") - created := 0 - updated := 0 - skipped := 0 - for path, val := range records { - old, exists := existing[path] - if !exists { - // Entry is unknown, push a new one to Cloudflare. - log.Debug(fmt.Sprintf("Creating %s = %q", path, val)) - created++ - ttl := rootTTL - if path != name { - ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare - } - record := cloudflare.CreateDNSRecordParams{Type: "TXT", Name: path, Content: val, TTL: ttl} - _, err = c.CreateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record) - } else if old.Content != val { - // Entry already exists, only change its content. - log.Info(fmt.Sprintf("Updating %s from %q to %q", path, old.Content, val)) - updated++ - - record := cloudflare.UpdateDNSRecordParams{ - Type: old.Type, - Name: old.Name, - Content: val, - Data: old.Data, - ID: old.ID, - Priority: old.Priority, - TTL: old.TTL, - Proxied: old.Proxied, - Tags: old.Tags, - } - _, err = c.UpdateDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), record) - } else { - skipped++ - log.Debug(fmt.Sprintf("Skipping %s = %q", path, val)) - } - if err != nil { - return fmt.Errorf("failed to publish %s: %v", path, err) - } - } - log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped) - // Iterate over the old records and delete anything stale. - deleted := 0 - log.Info("Deleting stale DNS entries") - for path, entry := range existing { - if _, ok := records[path]; ok { - continue - } - // Stale entry, nuke it. - log.Debug(fmt.Sprintf("Deleting %s = %q", path, entry.Content)) - deleted++ - if err := c.DeleteDNSRecord(context.Background(), cloudflare.ZoneIdentifier(c.zoneID), entry.ID); err != nil { - return fmt.Errorf("failed to delete %s: %v", path, err) - } - } - log.Info("Deleted stale DNS entries", "count", deleted) - return nil -} diff --git a/builder/cmd/devp2p/dns_route53.go b/builder/cmd/devp2p/dns_route53.go deleted file mode 100644 index 21a32f941..000000000 --- a/builder/cmd/devp2p/dns_route53.go +++ /dev/null @@ -1,431 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "context" - "errors" - "fmt" - "strconv" - "strings" - "time" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/credentials" - "github.com/aws/aws-sdk-go-v2/service/route53" - "github.com/aws/aws-sdk-go-v2/service/route53/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/dnsdisc" - "github.com/urfave/cli/v2" - "golang.org/x/exp/slices" -) - -const ( - // Route53 limits change sets to 32k of 'RDATA size'. Change sets are also limited to - // 1000 items. UPSERTs count double. - // https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets - route53ChangeSizeLimit = 32000 - route53ChangeCountLimit = 1000 - maxRetryLimit = 60 -) - -var ( - route53AccessKeyFlag = &cli.StringFlag{ - Name: "access-key-id", - Usage: "AWS Access Key ID", - EnvVars: []string{"AWS_ACCESS_KEY_ID"}, - } - route53AccessSecretFlag = &cli.StringFlag{ - Name: "access-key-secret", - Usage: "AWS Access Key Secret", - EnvVars: []string{"AWS_SECRET_ACCESS_KEY"}, - } - route53ZoneIDFlag = &cli.StringFlag{ - Name: "zone-id", - Usage: "Route53 Zone ID", - } - route53RegionFlag = &cli.StringFlag{ - Name: "aws-region", - Usage: "AWS Region", - Value: "eu-central-1", - } -) - -type route53Client struct { - api *route53.Client - zoneID string -} - -type recordSet struct { - values []string - ttl int64 -} - -// newRoute53Client sets up a Route53 API client from command line flags. -func newRoute53Client(ctx *cli.Context) *route53Client { - akey := ctx.String(route53AccessKeyFlag.Name) - asec := ctx.String(route53AccessSecretFlag.Name) - if akey == "" || asec == "" { - exit(errors.New("need Route53 Access Key ID and secret to proceed")) - } - creds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(akey, asec, "")) - cfg, err := config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(creds)) - if err != nil { - exit(fmt.Errorf("can't initialize AWS configuration: %v", err)) - } - cfg.Region = ctx.String(route53RegionFlag.Name) - return &route53Client{ - api: route53.NewFromConfig(cfg), - zoneID: ctx.String(route53ZoneIDFlag.Name), - } -} - -// deploy uploads the given tree to Route53. -func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error { - if err := c.checkZone(name); err != nil { - return err - } - - // Compute DNS changes. - existing, err := c.collectRecords(name) - if err != nil { - return err - } - log.Info(fmt.Sprintf("Found %d TXT records", len(existing))) - records := t.ToTXT(name) - changes := c.computeChanges(name, records, existing) - - // Submit to API. - comment := fmt.Sprintf("enrtree update of %s at seq %d", name, t.Seq()) - return c.submitChanges(changes, comment) -} - -// deleteDomain removes all TXT records of the given domain. -func (c *route53Client) deleteDomain(name string) error { - if err := c.checkZone(name); err != nil { - return err - } - - // Compute DNS changes. - existing, err := c.collectRecords(name) - if err != nil { - return err - } - log.Info(fmt.Sprintf("Found %d TXT records", len(existing))) - changes := makeDeletionChanges(existing, nil) - - // Submit to API. - comment := "enrtree delete of " + name - return c.submitChanges(changes, comment) -} - -// submitChanges submits the given DNS changes to Route53. -func (c *route53Client) submitChanges(changes []types.Change, comment string) error { - if len(changes) == 0 { - log.Info("No DNS changes needed") - return nil - } - - var err error - batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit) - changesToCheck := make([]*route53.ChangeResourceRecordSetsOutput, len(batches)) - for i, changes := range batches { - log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes))) - batch := &types.ChangeBatch{ - Changes: changes, - Comment: aws.String(fmt.Sprintf("%s (%d/%d)", comment, i+1, len(batches))), - } - req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch} - changesToCheck[i], err = c.api.ChangeResourceRecordSets(context.TODO(), req) - if err != nil { - return err - } - } - - // Wait for all change batches to propagate. - for _, change := range changesToCheck { - log.Info(fmt.Sprintf("Waiting for change request %s", *change.ChangeInfo.Id)) - wreq := &route53.GetChangeInput{Id: change.ChangeInfo.Id} - var count int - for { - wresp, err := c.api.GetChange(context.TODO(), wreq) - if err != nil { - return err - } - - count++ - - if wresp.ChangeInfo.Status == types.ChangeStatusInsync || count >= maxRetryLimit { - break - } - - time.Sleep(30 * time.Second) - } - } - return nil -} - -// checkZone verifies zone information for the given domain. -func (c *route53Client) checkZone(name string) (err error) { - if c.zoneID == "" { - c.zoneID, err = c.findZoneID(name) - } - return err -} - -// findZoneID searches for the Zone ID containing the given domain. -func (c *route53Client) findZoneID(name string) (string, error) { - log.Info(fmt.Sprintf("Finding Route53 Zone ID for %s", name)) - var req route53.ListHostedZonesByNameInput - for { - resp, err := c.api.ListHostedZonesByName(context.TODO(), &req) - if err != nil { - return "", err - } - for _, zone := range resp.HostedZones { - if isSubdomain(name, *zone.Name) { - return *zone.Id, nil - } - } - if !resp.IsTruncated { - break - } - req.DNSName = resp.NextDNSName - req.HostedZoneId = resp.NextHostedZoneId - } - return "", errors.New("can't find zone ID for " + name) -} - -// computeChanges creates DNS changes for the given set of DNS discovery records. -// The 'existing' arg is the set of records that already exist on Route53. -func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []types.Change { - // Convert all names to lowercase. - lrecords := make(map[string]string, len(records)) - for name, r := range records { - lrecords[strings.ToLower(name)] = r - } - records = lrecords - - var ( - changes []types.Change - inserts int - upserts int - skips int - ) - - for path, newValue := range records { - prevRecords, exists := existing[path] - prevValue := strings.Join(prevRecords.values, "") - - // prevValue contains quoted strings, encode newValue to compare. - newValue = splitTXT(newValue) - - // Assign TTL. - ttl := int64(rootTTL) - if path != name { - ttl = int64(treeNodeTTL) - } - - if !exists { - // Entry is unknown, push a new one - log.Debug(fmt.Sprintf("Creating %s = %s", path, newValue)) - changes = append(changes, newTXTChange("CREATE", path, ttl, newValue)) - inserts++ - } else if prevValue != newValue || prevRecords.ttl != ttl { - // Entry already exists, only change its content. - log.Info(fmt.Sprintf("Updating %s from %s to %s", path, prevValue, newValue)) - changes = append(changes, newTXTChange("UPSERT", path, ttl, newValue)) - upserts++ - } else { - log.Debug(fmt.Sprintf("Skipping %s = %s", path, newValue)) - skips++ - } - } - - // Iterate over the old records and delete anything stale. - deletions := makeDeletionChanges(existing, records) - changes = append(changes, deletions...) - - log.Info("Computed DNS changes", - "changes", len(changes), - "inserts", inserts, - "skips", skips, - "deleted", len(deletions), - "upserts", upserts) - // Ensure changes are in the correct order. - sortChanges(changes) - return changes -} - -// makeDeletionChanges creates record changes which delete all records not contained in 'keep'. -func makeDeletionChanges(records map[string]recordSet, keep map[string]string) []types.Change { - var changes []types.Change - for path, set := range records { - if _, ok := keep[path]; ok { - continue - } - log.Debug(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, ""))) - changes = append(changes, newTXTChange("DELETE", path, set.ttl, set.values...)) - } - return changes -} - -// sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order. -func sortChanges(changes []types.Change) { - score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3} - slices.SortFunc(changes, func(a, b types.Change) int { - if a.Action == b.Action { - return strings.Compare(*a.ResourceRecordSet.Name, *b.ResourceRecordSet.Name) - } - if score[string(a.Action)] < score[string(b.Action)] { - return -1 - } - if score[string(a.Action)] > score[string(b.Action)] { - return 1 - } - return 0 - }) -} - -// splitChanges splits up DNS changes such that each change batch -// is smaller than the given RDATA limit. -func splitChanges(changes []types.Change, sizeLimit, countLimit int) [][]types.Change { - var ( - batches [][]types.Change - batchSize int - batchCount int - ) - for _, ch := range changes { - // Start new batch if this change pushes the current one over the limit. - count := changeCount(ch) - size := changeSize(ch) * count - overSize := batchSize+size > sizeLimit - overCount := batchCount+count > countLimit - if len(batches) == 0 || overSize || overCount { - batches = append(batches, nil) - batchSize = 0 - batchCount = 0 - } - batches[len(batches)-1] = append(batches[len(batches)-1], ch) - batchSize += size - batchCount += count - } - return batches -} - -// changeSize returns the RDATA size of a DNS change. -func changeSize(ch types.Change) int { - size := 0 - for _, rr := range ch.ResourceRecordSet.ResourceRecords { - if rr.Value != nil { - size += len(*rr.Value) - } - } - return size -} - -func changeCount(ch types.Change) int { - if ch.Action == types.ChangeActionUpsert { - return 2 - } - return 1 -} - -// collectRecords collects all TXT records below the given name. -func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) { - var req route53.ListResourceRecordSetsInput - req.HostedZoneId = &c.zoneID - existing := make(map[string]recordSet) - log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID) - for page := 0; ; page++ { - log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page) - resp, err := c.api.ListResourceRecordSets(context.TODO(), &req) - if err != nil { - return existing, err - } - for _, set := range resp.ResourceRecordSets { - if !isSubdomain(*set.Name, name) || set.Type != types.RRTypeTxt { - continue - } - s := recordSet{ttl: *set.TTL} - for _, rec := range set.ResourceRecords { - s.values = append(s.values, *rec.Value) - } - name := strings.TrimSuffix(*set.Name, ".") - existing[name] = s - } - - if !resp.IsTruncated { - break - } - // Set the cursor to the next batch. From the AWS docs: - // - // To display the next page of results, get the values of NextRecordName, - // NextRecordType, and NextRecordIdentifier (if any) from the response. Then submit - // another ListResourceRecordSets request, and specify those values for - // StartRecordName, StartRecordType, and StartRecordIdentifier. - req.StartRecordIdentifier = resp.NextRecordIdentifier - req.StartRecordName = resp.NextRecordName - req.StartRecordType = resp.NextRecordType - } - log.Info("Loaded existing TXT records", "name", name, "zone", c.zoneID, "records", len(existing)) - return existing, nil -} - -// newTXTChange creates a change to a TXT record. -func newTXTChange(action, name string, ttl int64, values ...string) types.Change { - r := types.ResourceRecordSet{ - Type: types.RRTypeTxt, - Name: &name, - TTL: &ttl, - } - var rrs []types.ResourceRecord - for _, val := range values { - var rr types.ResourceRecord - rr.Value = aws.String(val) - rrs = append(rrs, rr) - } - - r.ResourceRecords = rrs - - return types.Change{ - Action: types.ChangeAction(action), - ResourceRecordSet: &r, - } -} - -// isSubdomain returns true if name is a subdomain of domain. -func isSubdomain(name, domain string) bool { - domain = strings.TrimSuffix(domain, ".") - name = strings.TrimSuffix(name, ".") - return strings.HasSuffix("."+name, "."+domain) -} - -// splitTXT splits value into a list of quoted 255-character strings. -func splitTXT(value string) string { - var result strings.Builder - for len(value) > 0 { - rlen := len(value) - if rlen > 253 { - rlen = 253 - } - result.WriteString(strconv.Quote(value[:rlen])) - value = value[rlen:] - } - return result.String() -} diff --git a/builder/cmd/devp2p/dns_route53_test.go b/builder/cmd/devp2p/dns_route53_test.go deleted file mode 100644 index af39c70a3..000000000 --- a/builder/cmd/devp2p/dns_route53_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "reflect" - "testing" - - "github.com/aws/aws-sdk-go-v2/service/route53/types" -) - -// This test checks that computeChanges/splitChanges create DNS changes in -// leaf-added -> root-changed -> leaf-deleted order. -func TestRoute53ChangeSort(t *testing.T) { - t.Parallel() - testTree0 := map[string]recordSet{ - "2kfjogvxdqtxxugbh7gs7naaai.n": {ttl: 3333, values: []string{ - `"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`, - }}, - "fdxn3sn67na5dka4j2gok7bvqi.n": {ttl: treeNodeTTL, values: []string{`"enrtree-branch:"`}}, - "n": {ttl: rootTTL, values: []string{`"enrtree-root:v1 e=2KFJOGVXDQTXXUGBH7GS7NAAAI l=FDXN3SN67NA5DKA4J2GOK7BVQI seq=0 sig=v_-J_q_9ICQg5ztExFvLQhDBGMb0lZPJLhe3ts9LAcgqhOhtT3YFJsl8BWNDSwGtamUdR-9xl88_w-X42SVpjwE"`}}, - } - - testTree1 := map[string]string{ - "n": "enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA", - "C7HRFPF3BLGF3YR4DY5KX3SMBE.n": "enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org", - "JWXYDBPXYWG6FX3GMDIBFA6CJ4.n": "enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24", - "2XS2367YHAXJFGLZHVAWLQD4ZY.n": "enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA", - "H4FHT4B454P6UXFD7JCYQ5PWDY.n": "enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI", - "MHTDO6TMUBRIA2XWG5LUDACK24.n": "enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o", - } - - wantChanges := []types.Change{ - { - Action: "CREATE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("2xs2367yhaxjfglzhvawlqd4zy.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - { - Action: "CREATE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("c7hrfpf3blgf3yr4dy5kx3smbe.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - { - Action: "CREATE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("h4fht4b454p6uxfd7jcyq5pwdy.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - { - Action: "CREATE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("jwxydbpxywg6fx3gmdibfa6cj4.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - { - Action: "CREATE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("mhtdo6tmubria2xwg5ludack24.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - { - Action: "UPSERT", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`), - }}, - TTL: ip(rootTTL), - Type: "TXT", - }, - }, - { - Action: "DELETE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("2kfjogvxdqtxxugbh7gs7naaai.n"), - ResourceRecords: []types.ResourceRecord{ - {Value: sp(`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`)}, - }, - TTL: ip(3333), - Type: "TXT", - }, - }, - { - Action: "DELETE", - ResourceRecordSet: &types.ResourceRecordSet{ - Name: sp("fdxn3sn67na5dka4j2gok7bvqi.n"), - ResourceRecords: []types.ResourceRecord{{ - Value: sp(`"enrtree-branch:"`), - }}, - TTL: ip(treeNodeTTL), - Type: "TXT", - }, - }, - } - - var client route53Client - changes := client.computeChanges("n", testTree1, testTree0) - if !reflect.DeepEqual(changes, wantChanges) { - t.Fatalf("wrong changes (got %d, want %d)", len(changes), len(wantChanges)) - } - - // Check splitting according to size. - wantSplit := [][]types.Change{ - wantChanges[:4], - wantChanges[4:6], - wantChanges[6:], - } - split := splitChanges(changes, 600, 4000) - if !reflect.DeepEqual(split, wantSplit) { - t.Fatalf("wrong split batches: got %d, want %d", len(split), len(wantSplit)) - } - - // Check splitting according to count. - wantSplit = [][]types.Change{ - wantChanges[:5], - wantChanges[5:], - } - split = splitChanges(changes, 10000, 6) - if !reflect.DeepEqual(split, wantSplit) { - t.Fatalf("wrong split batches: got %d, want %d", len(split), len(wantSplit)) - } -} - -// This test checks that computeChanges compares the quoted value of the records correctly. -func TestRoute53NoChange(t *testing.T) { - t.Parallel() - // Existing record set. - testTree0 := map[string]recordSet{ - "n": {ttl: rootTTL, values: []string{ - `"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`, - }}, - "2xs2367yhaxjfglzhvawlqd4zy.n": {ttl: treeNodeTTL, values: []string{ - `"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`, - }}, - } - // New set. - testTree1 := map[string]string{ - "n": "enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA", - "2XS2367YHAXJFGLZHVAWLQD4ZY.n": "enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA", - } - - var client route53Client - changes := client.computeChanges("n", testTree1, testTree0) - if len(changes) > 0 { - t.Fatalf("wrong changes (got %d, want 0)", len(changes)) - } -} - -func sp(s string) *string { return &s } -func ip(i int64) *int64 { return &i } diff --git a/builder/cmd/devp2p/dnscmd.go b/builder/cmd/devp2p/dnscmd.go deleted file mode 100644 index 0fce7b103..000000000 --- a/builder/cmd/devp2p/dnscmd.go +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - "time" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/p2p/dnsdisc" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/urfave/cli/v2" -) - -var ( - dnsCommand = &cli.Command{ - Name: "dns", - Usage: "DNS Discovery Commands", - Subcommands: []*cli.Command{ - dnsSyncCommand, - dnsSignCommand, - dnsTXTCommand, - dnsCloudflareCommand, - dnsRoute53Command, - dnsRoute53NukeCommand, - }, - } - dnsSyncCommand = &cli.Command{ - Name: "sync", - Usage: "Download a DNS discovery tree", - ArgsUsage: " [ ]", - Action: dnsSync, - Flags: []cli.Flag{dnsTimeoutFlag}, - } - dnsSignCommand = &cli.Command{ - Name: "sign", - Usage: "Sign a DNS discovery tree", - ArgsUsage: " ", - Action: dnsSign, - Flags: []cli.Flag{dnsDomainFlag, dnsSeqFlag}, - } - dnsTXTCommand = &cli.Command{ - Name: "to-txt", - Usage: "Create a DNS TXT records for a discovery tree", - ArgsUsage: " ", - Action: dnsToTXT, - } - dnsCloudflareCommand = &cli.Command{ - Name: "to-cloudflare", - Usage: "Deploy DNS TXT records to CloudFlare", - ArgsUsage: "", - Action: dnsToCloudflare, - Flags: []cli.Flag{cloudflareTokenFlag, cloudflareZoneIDFlag}, - } - dnsRoute53Command = &cli.Command{ - Name: "to-route53", - Usage: "Deploy DNS TXT records to Amazon Route53", - ArgsUsage: "", - Action: dnsToRoute53, - Flags: []cli.Flag{ - route53AccessKeyFlag, - route53AccessSecretFlag, - route53ZoneIDFlag, - route53RegionFlag, - }, - } - dnsRoute53NukeCommand = &cli.Command{ - Name: "nuke-route53", - Usage: "Deletes DNS TXT records of a subdomain on Amazon Route53", - ArgsUsage: "", - Action: dnsNukeRoute53, - Flags: []cli.Flag{ - route53AccessKeyFlag, - route53AccessSecretFlag, - route53ZoneIDFlag, - route53RegionFlag, - }, - } -) - -var ( - dnsTimeoutFlag = &cli.DurationFlag{ - Name: "timeout", - Usage: "Timeout for DNS lookups", - } - dnsDomainFlag = &cli.StringFlag{ - Name: "domain", - Usage: "Domain name of the tree", - } - dnsSeqFlag = &cli.UintFlag{ - Name: "seq", - Usage: "New sequence number of the tree", - } -) - -const ( - rootTTL = 30 * 60 // 30 min - treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks - treeNodeTTLCloudflare = 24 * 60 * 60 // 1 day -) - -// dnsSync performs dnsSyncCommand. -func dnsSync(ctx *cli.Context) error { - var ( - c = dnsClient(ctx) - url = ctx.Args().Get(0) - outdir = ctx.Args().Get(1) - ) - domain, _, err := dnsdisc.ParseURL(url) - if err != nil { - return err - } - if outdir == "" { - outdir = domain - } - - t, err := c.SyncTree(url) - if err != nil { - return err - } - def := treeToDefinition(url, t) - def.Meta.LastModified = time.Now() - writeTreeMetadata(outdir, def) - writeTreeNodes(outdir, def) - return nil -} - -func dnsSign(ctx *cli.Context) error { - if ctx.NArg() < 2 { - return errors.New("need tree definition directory and key file as arguments") - } - var ( - defdir = ctx.Args().Get(0) - keyfile = ctx.Args().Get(1) - def = loadTreeDefinition(defdir) - domain = directoryName(defdir) - ) - if def.Meta.URL != "" { - d, _, err := dnsdisc.ParseURL(def.Meta.URL) - if err != nil { - return fmt.Errorf("invalid 'url' field: %v", err) - } - domain = d - } - if ctx.IsSet(dnsDomainFlag.Name) { - domain = ctx.String(dnsDomainFlag.Name) - } - if ctx.IsSet(dnsSeqFlag.Name) { - def.Meta.Seq = ctx.Uint(dnsSeqFlag.Name) - } else { - def.Meta.Seq++ // Auto-bump sequence number if not supplied via flag. - } - t, err := dnsdisc.MakeTree(def.Meta.Seq, def.Nodes, def.Meta.Links) - if err != nil { - return err - } - - key := loadSigningKey(keyfile) - url, err := t.Sign(key, domain) - if err != nil { - return fmt.Errorf("can't sign: %v", err) - } - - def = treeToDefinition(url, t) - def.Meta.LastModified = time.Now() - writeTreeMetadata(defdir, def) - return nil -} - -// directoryName returns the directory name of the given path. -// For example, when dir is "foo/bar", it returns "bar". -// When dir is ".", and the working directory is "example/foo", it returns "foo". -func directoryName(dir string) string { - abs, err := filepath.Abs(dir) - if err != nil { - exit(err) - } - return filepath.Base(abs) -} - -// dnsToTXT performs dnsTXTCommand. -func dnsToTXT(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need tree definition directory as argument") - } - output := ctx.Args().Get(1) - if output == "" { - output = "-" // default to stdout - } - domain, t, err := loadTreeDefinitionForExport(ctx.Args().Get(0)) - if err != nil { - return err - } - writeTXTJSON(output, t.ToTXT(domain)) - return nil -} - -// dnsToCloudflare performs dnsCloudflareCommand. -func dnsToCloudflare(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return errors.New("need tree definition directory as argument") - } - domain, t, err := loadTreeDefinitionForExport(ctx.Args().Get(0)) - if err != nil { - return err - } - client := newCloudflareClient(ctx) - return client.deploy(domain, t) -} - -// dnsToRoute53 performs dnsRoute53Command. -func dnsToRoute53(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return errors.New("need tree definition directory as argument") - } - domain, t, err := loadTreeDefinitionForExport(ctx.Args().Get(0)) - if err != nil { - return err - } - client := newRoute53Client(ctx) - return client.deploy(domain, t) -} - -// dnsNukeRoute53 performs dnsRoute53NukeCommand. -func dnsNukeRoute53(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return errors.New("need domain name as argument") - } - client := newRoute53Client(ctx) - return client.deleteDomain(ctx.Args().First()) -} - -// loadSigningKey loads a private key in Ethereum keystore format. -func loadSigningKey(keyfile string) *ecdsa.PrivateKey { - keyjson, err := os.ReadFile(keyfile) - if err != nil { - exit(fmt.Errorf("failed to read the keyfile at '%s': %v", keyfile, err)) - } - password, _ := prompt.Stdin.PromptPassword("Please enter the password for '" + keyfile + "': ") - key, err := keystore.DecryptKey(keyjson, password) - if err != nil { - exit(fmt.Errorf("error decrypting key: %v", err)) - } - return key.PrivateKey -} - -// dnsClient configures the DNS discovery client from command line flags. -func dnsClient(ctx *cli.Context) *dnsdisc.Client { - var cfg dnsdisc.Config - if commandHasFlag(ctx, dnsTimeoutFlag) { - cfg.Timeout = ctx.Duration(dnsTimeoutFlag.Name) - } - return dnsdisc.NewClient(cfg) -} - -// There are two file formats for DNS node trees on disk: -// -// The 'TXT' format is a single JSON file containing DNS TXT records -// as a JSON object where the keys are names and the values are objects -// containing the value of the record. -// -// The 'definition' format is a directory containing two files: -// -// enrtree-info.json -- contains sequence number & links to other trees -// nodes.json -- contains the nodes as a JSON array. -// -// This format exists because it's convenient to edit. nodes.json can be generated -// in multiple ways: it may be written by a DHT crawler or compiled by a human. - -type dnsDefinition struct { - Meta dnsMetaJSON - Nodes []*enode.Node -} - -type dnsMetaJSON struct { - URL string `json:"url,omitempty"` - Seq uint `json:"seq"` - Sig string `json:"signature,omitempty"` - Links []string `json:"links"` - LastModified time.Time `json:"lastModified"` -} - -func treeToDefinition(url string, t *dnsdisc.Tree) *dnsDefinition { - meta := dnsMetaJSON{ - URL: url, - Seq: t.Seq(), - Sig: t.Signature(), - Links: t.Links(), - } - if meta.Links == nil { - meta.Links = []string{} - } - return &dnsDefinition{Meta: meta, Nodes: t.Nodes()} -} - -// loadTreeDefinition loads a directory in 'definition' format. -func loadTreeDefinition(directory string) *dnsDefinition { - metaFile, nodesFile := treeDefinitionFiles(directory) - var def dnsDefinition - err := common.LoadJSON(metaFile, &def.Meta) - if err != nil && !os.IsNotExist(err) { - exit(err) - } - if def.Meta.Links == nil { - def.Meta.Links = []string{} - } - // Check link syntax. - for _, link := range def.Meta.Links { - if _, _, err := dnsdisc.ParseURL(link); err != nil { - exit(fmt.Errorf("invalid link %q: %v", link, err)) - } - } - // Check/convert nodes. - nodes := loadNodesJSON(nodesFile) - if err := nodes.verify(); err != nil { - exit(err) - } - def.Nodes = nodes.nodes() - return &def -} - -// loadTreeDefinitionForExport loads a DNS tree and ensures it is signed. -func loadTreeDefinitionForExport(dir string) (domain string, t *dnsdisc.Tree, err error) { - metaFile, _ := treeDefinitionFiles(dir) - def := loadTreeDefinition(dir) - if def.Meta.URL == "" { - return "", nil, fmt.Errorf("missing 'url' field in %v", metaFile) - } - domain, pubkey, err := dnsdisc.ParseURL(def.Meta.URL) - if err != nil { - return "", nil, fmt.Errorf("invalid 'url' field in %v: %v", metaFile, err) - } - if t, err = dnsdisc.MakeTree(def.Meta.Seq, def.Nodes, def.Meta.Links); err != nil { - return "", nil, err - } - if err := ensureValidTreeSignature(t, pubkey, def.Meta.Sig); err != nil { - return "", nil, err - } - return domain, t, nil -} - -// ensureValidTreeSignature checks that sig is valid for tree and assigns it as the -// tree's signature if valid. -func ensureValidTreeSignature(t *dnsdisc.Tree, pubkey *ecdsa.PublicKey, sig string) error { - if sig == "" { - return errors.New("missing signature, run 'devp2p dns sign' first") - } - if err := t.SetSignature(pubkey, sig); err != nil { - return errors.New("invalid signature on tree, run 'devp2p dns sign' to update it") - } - return nil -} - -// writeTreeMetadata writes a DNS node tree metadata file to the given directory. -func writeTreeMetadata(directory string, def *dnsDefinition) { - metaJSON, err := json.MarshalIndent(&def.Meta, "", jsonIndent) - if err != nil { - exit(err) - } - if err := os.Mkdir(directory, 0744); err != nil && !os.IsExist(err) { - exit(err) - } - metaFile, _ := treeDefinitionFiles(directory) - if err := os.WriteFile(metaFile, metaJSON, 0644); err != nil { - exit(err) - } -} - -func writeTreeNodes(directory string, def *dnsDefinition) { - ns := make(nodeSet, len(def.Nodes)) - ns.add(def.Nodes...) - _, nodesFile := treeDefinitionFiles(directory) - writeNodesJSON(nodesFile, ns) -} - -func treeDefinitionFiles(directory string) (string, string) { - meta := filepath.Join(directory, "enrtree-info.json") - nodes := filepath.Join(directory, "nodes.json") - return meta, nodes -} - -// writeTXTJSON writes TXT records in JSON format. -func writeTXTJSON(file string, txt map[string]string) { - txtJSON, err := json.MarshalIndent(txt, "", jsonIndent) - if err != nil { - exit(err) - } - if file == "-" { - os.Stdout.Write(txtJSON) - fmt.Println() - return - } - if err := os.WriteFile(file, txtJSON, 0644); err != nil { - exit(err) - } -} diff --git a/builder/cmd/devp2p/enrcmd.go b/builder/cmd/devp2p/enrcmd.go deleted file mode 100644 index c5a97c841..000000000 --- a/builder/cmd/devp2p/enrcmd.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "encoding/base64" - "encoding/hex" - "errors" - "fmt" - "io" - "net" - "os" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/rlp" - "github.com/urfave/cli/v2" -) - -var fileFlag = &cli.StringFlag{Name: "file"} - -var enrdumpCommand = &cli.Command{ - Name: "enrdump", - Usage: "Pretty-prints node records", - Action: enrdump, - Flags: []cli.Flag{ - fileFlag, - }, -} - -func enrdump(ctx *cli.Context) error { - var source string - if file := ctx.String(fileFlag.Name); file != "" { - if ctx.NArg() != 0 { - return errors.New("can't dump record from command-line argument in -file mode") - } - var b []byte - var err error - if file == "-" { - b, err = io.ReadAll(os.Stdin) - } else { - b, err = os.ReadFile(file) - } - if err != nil { - return err - } - source = string(b) - } else if ctx.NArg() == 1 { - source = ctx.Args().First() - } else { - return errors.New("need record as argument") - } - - r, err := parseRecord(source) - if err != nil { - return fmt.Errorf("INVALID: %v", err) - } - dumpRecord(os.Stdout, r) - return nil -} - -// dumpRecord creates a human-readable description of the given node record. -func dumpRecord(out io.Writer, r *enr.Record) { - n, err := enode.New(enode.ValidSchemes, r) - if err != nil { - fmt.Fprintf(out, "INVALID: %v\n", err) - } else { - fmt.Fprintf(out, "Node ID: %v\n", n.ID()) - dumpNodeURL(out, n) - } - kv := r.AppendElements(nil)[1:] - fmt.Fprintf(out, "Record has sequence number %d and %d key/value pairs.\n", r.Seq(), len(kv)/2) - fmt.Fprint(out, dumpRecordKV(kv, 2)) -} - -func dumpNodeURL(out io.Writer, n *enode.Node) { - var key enode.Secp256k1 - if n.Load(&key) != nil { - return // no secp256k1 public key - } - fmt.Fprintf(out, "URLv4: %s\n", n.URLv4()) -} - -func dumpRecordKV(kv []interface{}, indent int) string { - // Determine the longest key name for alignment. - var out string - var longestKey = 0 - for i := 0; i < len(kv); i += 2 { - key := kv[i].(string) - if len(key) > longestKey { - longestKey = len(key) - } - } - // Print the keys, invoking formatters for known keys. - for i := 0; i < len(kv); i += 2 { - key := kv[i].(string) - val := kv[i+1].(rlp.RawValue) - pad := longestKey - len(key) - out += strings.Repeat(" ", indent) + strconv.Quote(key) + strings.Repeat(" ", pad+1) - formatter := attrFormatters[key] - if formatter == nil { - formatter = formatAttrRaw - } - fmtval, ok := formatter(val) - if ok { - out += fmtval + "\n" - } else { - out += hex.EncodeToString(val) + " (!)\n" - } - } - return out -} - -// parseNode parses a node record and verifies its signature. -func parseNode(source string) (*enode.Node, error) { - if strings.HasPrefix(source, "enode://") { - return enode.ParseV4(source) - } - r, err := parseRecord(source) - if err != nil { - return nil, err - } - return enode.New(enode.ValidSchemes, r) -} - -// parseRecord parses a node record from hex, base64, or raw binary input. -func parseRecord(source string) (*enr.Record, error) { - bin := []byte(source) - if d, ok := decodeRecordHex(bytes.TrimSpace(bin)); ok { - bin = d - } else if d, ok := decodeRecordBase64(bytes.TrimSpace(bin)); ok { - bin = d - } - var r enr.Record - err := rlp.DecodeBytes(bin, &r) - return &r, err -} - -func decodeRecordHex(b []byte) ([]byte, bool) { - if bytes.HasPrefix(b, []byte("0x")) { - b = b[2:] - } - dec := make([]byte, hex.DecodedLen(len(b))) - _, err := hex.Decode(dec, b) - return dec, err == nil -} - -func decodeRecordBase64(b []byte) ([]byte, bool) { - if bytes.HasPrefix(b, []byte("enr:")) { - b = b[4:] - } - dec := make([]byte, base64.RawURLEncoding.DecodedLen(len(b))) - n, err := base64.RawURLEncoding.Decode(dec, b) - return dec[:n], err == nil -} - -// attrFormatters contains formatting functions for well-known ENR keys. -var attrFormatters = map[string]func(rlp.RawValue) (string, bool){ - "id": formatAttrString, - "ip": formatAttrIP, - "ip6": formatAttrIP, - "tcp": formatAttrUint, - "tcp6": formatAttrUint, - "udp": formatAttrUint, - "udp6": formatAttrUint, -} - -func formatAttrRaw(v rlp.RawValue) (string, bool) { - s := hex.EncodeToString(v) - return s, true -} - -func formatAttrString(v rlp.RawValue) (string, bool) { - content, _, err := rlp.SplitString(v) - return strconv.Quote(string(content)), err == nil -} - -func formatAttrIP(v rlp.RawValue) (string, bool) { - content, _, err := rlp.SplitString(v) - if err != nil || len(content) != 4 && len(content) != 6 { - return "", false - } - return net.IP(content).String(), true -} - -func formatAttrUint(v rlp.RawValue) (string, bool) { - var x uint64 - if err := rlp.DecodeBytes(v, &x); err != nil { - return "", false - } - return strconv.FormatUint(x, 10), true -} diff --git a/builder/cmd/devp2p/internal/ethtest/chain.go b/builder/cmd/devp2p/internal/ethtest/chain.go deleted file mode 100644 index e8b3725b1..000000000 --- a/builder/cmd/devp2p/internal/ethtest/chain.go +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "bytes" - "compress/gzip" - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "io" - "math/big" - "os" - "path" - "sort" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/exp/slices" -) - -// Chain is a lightweight blockchain-like store which can read a hivechain -// created chain. -type Chain struct { - genesis core.Genesis - blocks []*types.Block - state map[common.Address]state.DumpAccount // state of head block - senders map[common.Address]*senderInfo - config *params.ChainConfig -} - -// NewChain takes the given chain.rlp file, and decodes and returns -// the blocks from the file. -func NewChain(dir string) (*Chain, error) { - gen, err := loadGenesis(path.Join(dir, "genesis.json")) - if err != nil { - return nil, err - } - gblock := gen.ToBlock() - - blocks, err := blocksFromFile(path.Join(dir, "chain.rlp"), gblock) - if err != nil { - return nil, err - } - state, err := readState(path.Join(dir, "headstate.json")) - if err != nil { - return nil, err - } - accounts, err := readAccounts(path.Join(dir, "accounts.json")) - if err != nil { - return nil, err - } - return &Chain{ - genesis: gen, - blocks: blocks, - state: state, - senders: accounts, - config: gen.Config, - }, nil -} - -// senderInfo is an account record as output in the "accounts.json" file from -// hivechain. -type senderInfo struct { - Key *ecdsa.PrivateKey `json:"key"` - Nonce uint64 `json:"nonce"` -} - -// Head returns the chain head. -func (c *Chain) Head() *types.Block { - return c.blocks[c.Len()-1] -} - -// AccountsInHashOrder returns all accounts of the head state, ordered by hash of address. -func (c *Chain) AccountsInHashOrder() []state.DumpAccount { - list := make([]state.DumpAccount, len(c.state)) - i := 0 - for addr, acc := range c.state { - addr := addr - list[i] = acc - list[i].Address = &addr - if len(acc.AddressHash) != 32 { - panic(fmt.Errorf("missing/invalid SecureKey in dump account %v", addr)) - } - i++ - } - slices.SortFunc(list, func(x, y state.DumpAccount) int { - return bytes.Compare(x.AddressHash, y.AddressHash) - }) - return list -} - -// CodeHashes returns all bytecode hashes contained in the head state. -func (c *Chain) CodeHashes() []common.Hash { - var hashes []common.Hash - seen := make(map[common.Hash]struct{}) - seen[types.EmptyCodeHash] = struct{}{} - for _, acc := range c.state { - h := common.BytesToHash(acc.CodeHash) - if _, ok := seen[h]; ok { - continue - } - hashes = append(hashes, h) - seen[h] = struct{}{} - } - slices.SortFunc(hashes, (common.Hash).Cmp) - return hashes -} - -// Len returns the length of the chain. -func (c *Chain) Len() int { - return len(c.blocks) -} - -// ForkID gets the fork id of the chain. -func (c *Chain) ForkID() forkid.ID { - return forkid.NewID(c.config, c.blocks[0], uint64(c.Len()), c.blocks[c.Len()-1].Time()) -} - -// TD calculates the total difficulty of the chain at the -// chain head. -func (c *Chain) TD() *big.Int { - sum := new(big.Int) - for _, block := range c.blocks[:c.Len()] { - sum.Add(sum, block.Difficulty()) - } - return sum -} - -// GetBlock returns the block at the specified number. -func (c *Chain) GetBlock(number int) *types.Block { - return c.blocks[number] -} - -// RootAt returns the state root for the block at the given height. -func (c *Chain) RootAt(height int) common.Hash { - if height < c.Len() { - return c.blocks[height].Root() - } - return common.Hash{} -} - -// GetSender returns the address associated with account at the index in the -// pre-funded accounts list. -func (c *Chain) GetSender(idx int) (common.Address, uint64) { - var accounts Addresses - for addr := range c.senders { - accounts = append(accounts, addr) - } - sort.Sort(accounts) - addr := accounts[idx] - return addr, c.senders[addr].Nonce -} - -// IncNonce increases the specified signing account's pending nonce. -func (c *Chain) IncNonce(addr common.Address, amt uint64) { - if _, ok := c.senders[addr]; !ok { - panic("nonce increment for non-signer") - } - c.senders[addr].Nonce += amt -} - -// Balance returns the balance of an account at the head of the chain. -func (c *Chain) Balance(addr common.Address) *big.Int { - bal := new(big.Int) - if acc, ok := c.state[addr]; ok { - bal, _ = bal.SetString(acc.Balance, 10) - } - return bal -} - -// SignTx signs a transaction for the specified from account, so long as that -// account was in the hivechain accounts dump. -func (c *Chain) SignTx(from common.Address, tx *types.Transaction) (*types.Transaction, error) { - signer := types.LatestSigner(c.config) - acc, ok := c.senders[from] - if !ok { - return nil, fmt.Errorf("account not available for signing: %s", from) - } - return types.SignTx(tx, signer, acc.Key) -} - -// GetHeaders returns the headers base on an ethGetPacketHeadersPacket. -func (c *Chain) GetHeaders(req *eth.GetBlockHeadersPacket) ([]*types.Header, error) { - if req.Amount < 1 { - return nil, errors.New("no block headers requested") - } - var ( - headers = make([]*types.Header, req.Amount) - blockNumber uint64 - ) - // Range over blocks to check if our chain has the requested header. - for _, block := range c.blocks { - if block.Hash() == req.Origin.Hash || block.Number().Uint64() == req.Origin.Number { - headers[0] = block.Header() - blockNumber = block.Number().Uint64() - } - } - if headers[0] == nil { - return nil, fmt.Errorf("no headers found for given origin number %v, hash %v", req.Origin.Number, req.Origin.Hash) - } - if req.Reverse { - for i := 1; i < int(req.Amount); i++ { - blockNumber -= (1 - req.Skip) - headers[i] = c.blocks[blockNumber].Header() - } - return headers, nil - } - for i := 1; i < int(req.Amount); i++ { - blockNumber += (1 + req.Skip) - headers[i] = c.blocks[blockNumber].Header() - } - return headers, nil -} - -// Shorten returns a copy chain of a desired height from the imported -func (c *Chain) Shorten(height int) *Chain { - blocks := make([]*types.Block, height) - copy(blocks, c.blocks[:height]) - - config := *c.config - return &Chain{ - blocks: blocks, - config: &config, - } -} - -func loadGenesis(genesisFile string) (core.Genesis, error) { - chainConfig, err := os.ReadFile(genesisFile) - if err != nil { - return core.Genesis{}, err - } - var gen core.Genesis - if err := json.Unmarshal(chainConfig, &gen); err != nil { - return core.Genesis{}, err - } - return gen, nil -} - -type Addresses []common.Address - -func (a Addresses) Len() int { - return len(a) -} - -func (a Addresses) Less(i, j int) bool { - return bytes.Compare(a[i][:], a[j][:]) < 0 -} - -func (a Addresses) Swap(i, j int) { - tmp := a[i] - a[i] = a[j] - a[j] = tmp -} - -func blocksFromFile(chainfile string, gblock *types.Block) ([]*types.Block, error) { - // Load chain.rlp. - fh, err := os.Open(chainfile) - if err != nil { - return nil, err - } - defer fh.Close() - var reader io.Reader = fh - if strings.HasSuffix(chainfile, ".gz") { - if reader, err = gzip.NewReader(reader); err != nil { - return nil, err - } - } - stream := rlp.NewStream(reader, 0) - var blocks = make([]*types.Block, 1) - blocks[0] = gblock - for i := 0; ; i++ { - var b types.Block - if err := stream.Decode(&b); err == io.EOF { - break - } else if err != nil { - return nil, fmt.Errorf("at block index %d: %v", i, err) - } - if b.NumberU64() != uint64(i+1) { - return nil, fmt.Errorf("block at index %d has wrong number %d", i, b.NumberU64()) - } - blocks = append(blocks, &b) - } - return blocks, nil -} - -func readState(file string) (map[common.Address]state.DumpAccount, error) { - f, err := os.ReadFile(file) - if err != nil { - return nil, fmt.Errorf("unable to read state: %v", err) - } - var dump state.Dump - if err := json.Unmarshal(f, &dump); err != nil { - return nil, fmt.Errorf("unable to unmarshal state: %v", err) - } - - state := make(map[common.Address]state.DumpAccount) - for key, acct := range dump.Accounts { - var addr common.Address - if err := addr.UnmarshalText([]byte(key)); err != nil { - return nil, fmt.Errorf("invalid address %q", key) - } - state[addr] = acct - } - return state, nil -} - -func readAccounts(file string) (map[common.Address]*senderInfo, error) { - f, err := os.ReadFile(file) - if err != nil { - return nil, fmt.Errorf("unable to read state: %v", err) - } - type account struct { - Key hexutil.Bytes `json:"key"` - } - keys := make(map[common.Address]account) - if err := json.Unmarshal(f, &keys); err != nil { - return nil, fmt.Errorf("unable to unmarshal accounts: %v", err) - } - accounts := make(map[common.Address]*senderInfo) - for addr, acc := range keys { - pk, err := crypto.HexToECDSA(common.Bytes2Hex(acc.Key)) - if err != nil { - return nil, fmt.Errorf("unable to read private key for %s: %v", err, addr) - } - accounts[addr] = &senderInfo{Key: pk, Nonce: 0} - } - return accounts, nil -} diff --git a/builder/cmd/devp2p/internal/ethtest/chain_test.go b/builder/cmd/devp2p/internal/ethtest/chain_test.go deleted file mode 100644 index 62bd6d26e..000000000 --- a/builder/cmd/devp2p/internal/ethtest/chain_test.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "path/filepath" - "strconv" - "testing" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/p2p" - "github.com/stretchr/testify/assert" -) - -// TestEthProtocolNegotiation tests whether the test suite -// can negotiate the highest eth protocol in a status message exchange -func TestEthProtocolNegotiation(t *testing.T) { - t.Parallel() - var tests = []struct { - conn *Conn - caps []p2p.Cap - expected uint32 - }{ - { - conn: &Conn{ - ourHighestProtoVersion: 65, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "eth", Version: 65}, - }, - expected: uint32(65), - }, - { - conn: &Conn{ - ourHighestProtoVersion: 65, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "eth", Version: 65}, - }, - expected: uint32(65), - }, - { - conn: &Conn{ - ourHighestProtoVersion: 65, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "eth", Version: 65}, - }, - expected: uint32(65), - }, - { - conn: &Conn{ - ourHighestProtoVersion: 64, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "eth", Version: 65}, - }, - expected: 64, - }, - { - conn: &Conn{ - ourHighestProtoVersion: 65, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 0}, - {Name: "eth", Version: 89}, - {Name: "eth", Version: 65}, - }, - expected: uint32(65), - }, - { - conn: &Conn{ - ourHighestProtoVersion: 64, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "wrongProto", Version: 65}, - }, - expected: uint32(64), - }, - { - conn: &Conn{ - ourHighestProtoVersion: 65, - }, - caps: []p2p.Cap{ - {Name: "eth", Version: 63}, - {Name: "eth", Version: 64}, - {Name: "wrongProto", Version: 65}, - }, - expected: uint32(64), - }, - } - - for i, tt := range tests { - t.Run(strconv.Itoa(i), func(t *testing.T) { - tt.conn.negotiateEthProtocol(tt.caps) - assert.Equal(t, tt.expected, uint32(tt.conn.negotiatedProtoVersion)) - }) - } -} - -// TestChainGetHeaders tests whether the test suite can correctly -// respond to a GetBlockHeaders request from a node. -func TestChainGetHeaders(t *testing.T) { - t.Parallel() - - dir, err := filepath.Abs("./testdata") - if err != nil { - t.Fatal(err) - } - chain, err := NewChain(dir) - if err != nil { - t.Fatal(err) - } - - var tests = []struct { - req eth.GetBlockHeadersPacket - expected []*types.Header - }{ - { - req: eth.GetBlockHeadersPacket{ - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{Number: uint64(2)}, - Amount: uint64(5), - Skip: 1, - Reverse: false, - }, - }, - expected: []*types.Header{ - chain.blocks[2].Header(), - chain.blocks[4].Header(), - chain.blocks[6].Header(), - chain.blocks[8].Header(), - chain.blocks[10].Header(), - }, - }, - { - req: eth.GetBlockHeadersPacket{ - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)}, - Amount: uint64(3), - Skip: 0, - Reverse: true, - }, - }, - expected: []*types.Header{ - chain.blocks[chain.Len()-1].Header(), - chain.blocks[chain.Len()-2].Header(), - chain.blocks[chain.Len()-3].Header(), - }, - }, - { - req: eth.GetBlockHeadersPacket{ - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{Hash: chain.Head().Hash()}, - Amount: uint64(1), - Skip: 0, - Reverse: false, - }, - }, - expected: []*types.Header{ - chain.Head().Header(), - }, - }, - } - - for i, tt := range tests { - t.Run(strconv.Itoa(i), func(t *testing.T) { - headers, err := chain.GetHeaders(&tt.req) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, headers, tt.expected) - }) - } -} diff --git a/builder/cmd/devp2p/internal/ethtest/conn.go b/builder/cmd/devp2p/internal/ethtest/conn.go deleted file mode 100644 index ba3c0585f..000000000 --- a/builder/cmd/devp2p/internal/ethtest/conn.go +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "crypto/ecdsa" - "errors" - "fmt" - "net" - "reflect" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/rlpx" - "github.com/ethereum/go-ethereum/rlp" -) - -var ( - pretty = spew.ConfigState{ - Indent: " ", - DisableCapacities: true, - DisablePointerAddresses: true, - SortKeys: true, - } - timeout = 2 * time.Second -) - -// dial attempts to dial the given node and perform a handshake, returning the -// created Conn if successful. -func (s *Suite) dial() (*Conn, error) { - key, _ := crypto.GenerateKey() - return s.dialAs(key) -} - -// dialAs attempts to dial a given node and perform a handshake using the given -// private key. -func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) { - fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP())) - if err != nil { - return nil, err - } - conn := Conn{Conn: rlpx.NewConn(fd, s.Dest.Pubkey())} - conn.ourKey = key - _, err = conn.Handshake(conn.ourKey) - if err != nil { - conn.Close() - return nil, err - } - conn.caps = []p2p.Cap{ - {Name: "eth", Version: 67}, - {Name: "eth", Version: 68}, - } - conn.ourHighestProtoVersion = 68 - return &conn, nil -} - -// dialSnap creates a connection with snap/1 capability. -func (s *Suite) dialSnap() (*Conn, error) { - conn, err := s.dial() - if err != nil { - return nil, fmt.Errorf("dial failed: %v", err) - } - conn.caps = append(conn.caps, p2p.Cap{Name: "snap", Version: 1}) - conn.ourHighestSnapProtoVersion = 1 - return conn, nil -} - -// Conn represents an individual connection with a peer -type Conn struct { - *rlpx.Conn - ourKey *ecdsa.PrivateKey - negotiatedProtoVersion uint - negotiatedSnapProtoVersion uint - ourHighestProtoVersion uint - ourHighestSnapProtoVersion uint - caps []p2p.Cap -} - -// Read reads a packet from the connection. -func (c *Conn) Read() (uint64, []byte, error) { - c.SetReadDeadline(time.Now().Add(timeout)) - code, data, _, err := c.Conn.Read() - if err != nil { - return 0, nil, err - } - return code, data, nil -} - -// ReadMsg attempts to read a devp2p message with a specific code. -func (c *Conn) ReadMsg(proto Proto, code uint64, msg any) error { - c.SetReadDeadline(time.Now().Add(timeout)) - for { - got, data, err := c.Read() - if err != nil { - return err - } - if protoOffset(proto)+code == got { - return rlp.DecodeBytes(data, msg) - } - } -} - -// Write writes a eth packet to the connection. -func (c *Conn) Write(proto Proto, code uint64, msg any) error { - c.SetWriteDeadline(time.Now().Add(timeout)) - payload, err := rlp.EncodeToBytes(msg) - if err != nil { - return err - } - _, err = c.Conn.Write(protoOffset(proto)+code, payload) - return err -} - -// ReadEth reads an Eth sub-protocol wire message. -func (c *Conn) ReadEth() (any, error) { - c.SetReadDeadline(time.Now().Add(timeout)) - for { - code, data, _, err := c.Conn.Read() - if err != nil { - return nil, err - } - if code == pingMsg { - c.Write(baseProto, pongMsg, []byte{}) - continue - } - if getProto(code) != ethProto { - // Read until eth message. - continue - } - code -= baseProtoLen - - var msg any - switch int(code) { - case eth.StatusMsg: - msg = new(eth.StatusPacket) - case eth.GetBlockHeadersMsg: - msg = new(eth.GetBlockHeadersPacket) - case eth.BlockHeadersMsg: - msg = new(eth.BlockHeadersPacket) - case eth.GetBlockBodiesMsg: - msg = new(eth.GetBlockBodiesPacket) - case eth.BlockBodiesMsg: - msg = new(eth.BlockBodiesPacket) - case eth.NewBlockMsg: - msg = new(eth.NewBlockPacket) - case eth.NewBlockHashesMsg: - msg = new(eth.NewBlockHashesPacket) - case eth.TransactionsMsg: - msg = new(eth.TransactionsPacket) - case eth.NewPooledTransactionHashesMsg: - msg = new(eth.NewPooledTransactionHashesPacket) - case eth.GetPooledTransactionsMsg: - msg = new(eth.GetPooledTransactionsPacket) - case eth.PooledTransactionsMsg: - msg = new(eth.PooledTransactionsPacket) - default: - panic(fmt.Sprintf("unhandled eth msg code %d", code)) - } - if err := rlp.DecodeBytes(data, msg); err != nil { - return nil, fmt.Errorf("unable to decode eth msg: %v", err) - } - return msg, nil - } -} - -// ReadSnap reads a snap/1 response with the given id from the connection. -func (c *Conn) ReadSnap() (any, error) { - c.SetReadDeadline(time.Now().Add(timeout)) - for { - code, data, _, err := c.Conn.Read() - if err != nil { - return nil, err - } - if getProto(code) != snapProto { - // Read until snap message. - continue - } - code -= baseProtoLen + ethProtoLen - - var msg any - switch int(code) { - case snap.GetAccountRangeMsg: - msg = new(snap.GetAccountRangePacket) - case snap.AccountRangeMsg: - msg = new(snap.AccountRangePacket) - case snap.GetStorageRangesMsg: - msg = new(snap.GetStorageRangesPacket) - case snap.StorageRangesMsg: - msg = new(snap.StorageRangesPacket) - case snap.GetByteCodesMsg: - msg = new(snap.GetByteCodesPacket) - case snap.ByteCodesMsg: - msg = new(snap.ByteCodesPacket) - case snap.GetTrieNodesMsg: - msg = new(snap.GetTrieNodesPacket) - case snap.TrieNodesMsg: - msg = new(snap.TrieNodesPacket) - default: - panic(fmt.Errorf("unhandled snap code: %d", code)) - } - if err := rlp.DecodeBytes(data, msg); err != nil { - return nil, fmt.Errorf("could not rlp decode message: %v", err) - } - return msg, nil - } -} - -// peer performs both the protocol handshake and the status message -// exchange with the node in order to peer with it. -func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error { - if err := c.handshake(); err != nil { - return fmt.Errorf("handshake failed: %v", err) - } - if err := c.statusExchange(chain, status); err != nil { - return fmt.Errorf("status exchange failed: %v", err) - } - return nil -} - -// handshake performs a protocol handshake with the node. -func (c *Conn) handshake() error { - // Write hello to client. - pub0 := crypto.FromECDSAPub(&c.ourKey.PublicKey)[1:] - ourHandshake := &protoHandshake{ - Version: 5, - Caps: c.caps, - ID: pub0, - } - if err := c.Write(baseProto, handshakeMsg, ourHandshake); err != nil { - return fmt.Errorf("write to connection failed: %v", err) - } - // Read hello from client. - code, data, err := c.Read() - if err != nil { - return fmt.Errorf("erroring reading handshake: %v", err) - } - switch code { - case handshakeMsg: - msg := new(protoHandshake) - if err := rlp.DecodeBytes(data, &msg); err != nil { - return fmt.Errorf("error decoding handshake msg: %v", err) - } - // Set snappy if version is at least 5. - if msg.Version >= 5 { - c.SetSnappy(true) - } - c.negotiateEthProtocol(msg.Caps) - if c.negotiatedProtoVersion == 0 { - return fmt.Errorf("could not negotiate eth protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion) - } - // If we require snap, verify that it was negotiated. - if c.ourHighestSnapProtoVersion != c.negotiatedSnapProtoVersion { - return fmt.Errorf("could not negotiate snap protocol (remote caps: %v, local snap version: %v)", msg.Caps, c.ourHighestSnapProtoVersion) - } - return nil - default: - return fmt.Errorf("bad handshake: got msg code %d", code) - } -} - -// negotiateEthProtocol sets the Conn's eth protocol version to highest -// advertised capability from peer. -func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) { - var highestEthVersion uint - var highestSnapVersion uint - for _, capability := range caps { - switch capability.Name { - case "eth": - if capability.Version > highestEthVersion && capability.Version <= c.ourHighestProtoVersion { - highestEthVersion = capability.Version - } - case "snap": - if capability.Version > highestSnapVersion && capability.Version <= c.ourHighestSnapProtoVersion { - highestSnapVersion = capability.Version - } - } - } - c.negotiatedProtoVersion = highestEthVersion - c.negotiatedSnapProtoVersion = highestSnapVersion -} - -// statusExchange performs a `Status` message exchange with the given node. -func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error { -loop: - for { - code, data, err := c.Read() - if err != nil { - return fmt.Errorf("failed to read from connection: %w", err) - } - switch code { - case eth.StatusMsg + protoOffset(ethProto): - msg := new(eth.StatusPacket) - if err := rlp.DecodeBytes(data, &msg); err != nil { - return fmt.Errorf("error decoding status packet: %w", err) - } - if have, want := msg.Head, chain.blocks[chain.Len()-1].Hash(); have != want { - return fmt.Errorf("wrong head block in status, want: %#x (block %d) have %#x", - want, chain.blocks[chain.Len()-1].NumberU64(), have) - } - if have, want := msg.TD.Cmp(chain.TD()), 0; have != want { - return fmt.Errorf("wrong TD in status: have %v want %v", have, want) - } - if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) { - return fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want) - } - if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) { - return fmt.Errorf("wrong protocol version: have %v, want %v", have, want) - } - break loop - case discMsg: - var msg []p2p.DiscReason - if rlp.DecodeBytes(data, &msg); len(msg) == 0 { - return errors.New("invalid disconnect message") - } - return fmt.Errorf("disconnect received: %v", pretty.Sdump(msg)) - case pingMsg: - // TODO (renaynay): in the future, this should be an error - // (PINGs should not be a response upon fresh connection) - c.Write(baseProto, pongMsg, nil) - default: - return fmt.Errorf("bad status message: code %d", code) - } - } - // make sure eth protocol version is set for negotiation - if c.negotiatedProtoVersion == 0 { - return errors.New("eth protocol version must be set in Conn") - } - if status == nil { - // default status message - status = ð.StatusPacket{ - ProtocolVersion: uint32(c.negotiatedProtoVersion), - NetworkID: chain.config.ChainID.Uint64(), - TD: chain.TD(), - Head: chain.blocks[chain.Len()-1].Hash(), - Genesis: chain.blocks[0].Hash(), - ForkID: chain.ForkID(), - } - } - if err := c.Write(ethProto, eth.StatusMsg, status); err != nil { - return fmt.Errorf("write to connection failed: %v", err) - } - return nil -} diff --git a/builder/cmd/devp2p/internal/ethtest/engine.go b/builder/cmd/devp2p/internal/ethtest/engine.go deleted file mode 100644 index ea4fc76e6..000000000 --- a/builder/cmd/devp2p/internal/ethtest/engine.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "bytes" - "fmt" - "io" - "net/http" - "os" - "path" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/golang-jwt/jwt/v4" -) - -// EngineClient is a wrapper around engine-related data. -type EngineClient struct { - url string - jwt [32]byte - headfcu []byte -} - -// NewEngineClient creates a new engine client. -func NewEngineClient(dir, url, jwt string) (*EngineClient, error) { - headfcu, err := os.ReadFile(path.Join(dir, "headfcu.json")) - if err != nil { - return nil, fmt.Errorf("failed to read headfcu: %w", err) - } - return &EngineClient{url, common.HexToHash(jwt), headfcu}, nil -} - -// token returns the jwt claim token for authorization. -func (ec *EngineClient) token() string { - claims := jwt.RegisteredClaims{IssuedAt: jwt.NewNumericDate(time.Now())} - token, _ := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(ec.jwt[:]) - return token -} - -// sendForkchoiceUpdated sends an fcu for the head of the generated chain. -func (ec *EngineClient) sendForkchoiceUpdated() error { - var ( - req, _ = http.NewRequest(http.MethodPost, ec.url, io.NopCloser(bytes.NewReader(ec.headfcu))) - header = make(http.Header) - ) - // Set header - header.Set("accept", "application/json") - header.Set("content-type", "application/json") - header.Set("Authorization", fmt.Sprintf("Bearer %v", ec.token())) - req.Header = header - - _, err := new(http.Client).Do(req) - return err -} diff --git a/builder/cmd/devp2p/internal/ethtest/mkchain.sh b/builder/cmd/devp2p/internal/ethtest/mkchain.sh deleted file mode 100644 index b9253e8ca..000000000 --- a/builder/cmd/devp2p/internal/ethtest/mkchain.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -hivechain generate \ - --fork-interval 6 \ - --tx-interval 1 \ - --length 500 \ - --outdir testdata \ - --lastfork cancun \ - --outputs accounts,genesis,chain,headstate,txinfo,headblock,headfcu,newpayload,forkenv diff --git a/builder/cmd/devp2p/internal/ethtest/protocol.go b/builder/cmd/devp2p/internal/ethtest/protocol.go deleted file mode 100644 index f5f5f7e48..000000000 --- a/builder/cmd/devp2p/internal/ethtest/protocol.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . -package ethtest - -import ( - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rlp" -) - -// Unexported devp2p message codes from p2p/peer.go. -const ( - handshakeMsg = 0x00 - discMsg = 0x01 - pingMsg = 0x02 - pongMsg = 0x03 -) - -// Unexported devp2p protocol lengths from p2p package. -const ( - baseProtoLen = 16 - ethProtoLen = 17 - snapProtoLen = 8 -) - -// Unexported handshake structure from p2p/peer.go. -type protoHandshake struct { - Version uint64 - Name string - Caps []p2p.Cap - ListenPort uint64 - ID []byte - Rest []rlp.RawValue `rlp:"tail"` -} - -type Hello = protoHandshake - -// Proto is an enum representing devp2p protocol types. -type Proto int - -const ( - baseProto Proto = iota - ethProto - snapProto -) - -// getProto returns the protocol a certain message code is associated with -// (assuming the negotiated capabilities are exactly {eth,snap}) -func getProto(code uint64) Proto { - switch { - case code < baseProtoLen: - return baseProto - case code < baseProtoLen+ethProtoLen: - return ethProto - case code < baseProtoLen+ethProtoLen+snapProtoLen: - return snapProto - default: - panic("unhandled msg code beyond last protocol") - } -} - -// protoOffset will return the offset at which the specified protocol's messages -// begin. -func protoOffset(proto Proto) uint64 { - switch proto { - case baseProto: - return 0 - case ethProto: - return baseProtoLen - case snapProto: - return baseProtoLen + ethProtoLen - default: - panic("unhandled protocol") - } -} diff --git a/builder/cmd/devp2p/internal/ethtest/snap.go b/builder/cmd/devp2p/internal/ethtest/snap.go deleted file mode 100644 index 64e063358..000000000 --- a/builder/cmd/devp2p/internal/ethtest/snap.go +++ /dev/null @@ -1,983 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "math/rand" - "reflect" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "golang.org/x/crypto/sha3" -) - -func (c *Conn) snapRequest(code uint64, msg any) (any, error) { - if err := c.Write(snapProto, code, msg); err != nil { - return nil, fmt.Errorf("could not write to connection: %v", err) - } - return c.ReadSnap() -} - -func (s *Suite) TestSnapStatus(t *utesting.T) { - conn, err := s.dialSnap() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } -} - -type accRangeTest struct { - nBytes uint64 - root common.Hash - startingHash common.Hash - limitHash common.Hash - - expAccounts int - expFirst common.Hash - expLast common.Hash - - desc string -} - -// TestSnapGetAccountRange various forms of GetAccountRange requests. -func (s *Suite) TestSnapGetAccountRange(t *utesting.T) { - var ( - ffHash = common.MaxHash - zero = common.Hash{} - - // test values derived from chain/ account dump - root = s.chain.Head().Root() - headstate = s.chain.AccountsInHashOrder() - firstKey = common.BytesToHash(headstate[0].AddressHash) - secondKey = common.BytesToHash(headstate[1].AddressHash) - storageRoot = findNonEmptyStorageRoot(headstate) - ) - - tests := []accRangeTest{ - // Tests decreasing the number of bytes - { - nBytes: 4000, - root: root, - startingHash: zero, - limitHash: ffHash, - expAccounts: 86, - expFirst: firstKey, - expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"), - desc: "In this test, we request the entire state range, but limit the response to 4000 bytes.", - }, - { - nBytes: 3000, - root: root, - startingHash: zero, - limitHash: ffHash, - expAccounts: 65, - expFirst: firstKey, - expLast: common.HexToHash("0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6"), - desc: "In this test, we request the entire state range, but limit the response to 3000 bytes.", - }, - { - nBytes: 2000, - root: root, - startingHash: zero, - limitHash: ffHash, - expAccounts: 44, - expFirst: firstKey, - expLast: common.HexToHash("0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595"), - desc: "In this test, we request the entire state range, but limit the response to 2000 bytes.", - }, - { - nBytes: 1, - root: root, - startingHash: zero, - limitHash: ffHash, - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `In this test, we request the entire state range, but limit the response to 1 byte. -The server should return the first account of the state.`, - }, - { - nBytes: 0, - root: root, - startingHash: zero, - limitHash: ffHash, - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `Here we request with a responseBytes limit of zero. -The server should return one account.`, - }, - - // Tests variations of the range - { - nBytes: 4000, - root: root, - startingHash: hashAdd(firstKey, -500), - limitHash: hashAdd(firstKey, 1), - expAccounts: 2, - expFirst: firstKey, - expLast: secondKey, - desc: `In this test, we request a range where startingHash is before the first available -account key, and limitHash is after. The server should return the first and second -account of the state (because the second account is the 'next available').`, - }, - - { - nBytes: 4000, - root: root, - startingHash: hashAdd(firstKey, -500), - limitHash: hashAdd(firstKey, -450), - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `Here we request range where both bounds are before the first available account key. -This should return the first account (even though it's out of bounds).`, - }, - - // More range tests: - { - nBytes: 4000, - root: root, - startingHash: zero, - limitHash: zero, - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `In this test, both startingHash and limitHash are zero. -The server should return the first available account.`, - }, - { - nBytes: 4000, - root: root, - startingHash: firstKey, - limitHash: ffHash, - expAccounts: 86, - expFirst: firstKey, - expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"), - desc: `In this test, startingHash is exactly the first available account key. -The server should return the first available account of the state as the first item.`, - }, - { - nBytes: 4000, - root: root, - startingHash: hashAdd(firstKey, 1), - limitHash: ffHash, - expAccounts: 86, - expFirst: secondKey, - expLast: common.HexToHash("0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"), - desc: `In this test, startingHash is after the first available key. -The server should return the second account of the state as the first item.`, - }, - - // Test different root hashes - - { - nBytes: 4000, - root: common.Hash{0x13, 0x37}, - startingHash: zero, - limitHash: ffHash, - expAccounts: 0, - expFirst: zero, - expLast: zero, - desc: `This test requests a non-existent state root.`, - }, - - // The genesis stateroot (we expect it to not be served) - { - nBytes: 4000, - root: s.chain.RootAt(0), - startingHash: zero, - limitHash: ffHash, - expAccounts: 0, - expFirst: zero, - expLast: zero, - desc: `This test requests data at the state root of the genesis block. We expect the -server to return no data because genesis is older than 127 blocks.`, - }, - - { - nBytes: 4000, - root: s.chain.RootAt(int(s.chain.Head().Number().Uint64()) - 127), - startingHash: zero, - limitHash: ffHash, - expAccounts: 84, - expFirst: firstKey, - expLast: common.HexToHash("0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3"), - desc: `This test requests data at a state root that is 127 blocks old. -We expect the server to have this state available.`, - }, - - { - nBytes: 4000, - root: storageRoot, - startingHash: zero, - limitHash: ffHash, - expAccounts: 0, - expFirst: zero, - expLast: zero, - desc: `This test requests data at a state root that is actually the storage root of -an existing account. The server is supposed to ignore this request.`, - }, - - // And some non-sensical requests - - { - nBytes: 4000, - root: root, - startingHash: ffHash, - limitHash: zero, - expAccounts: 0, - expFirst: zero, - expLast: zero, - desc: `In this test, the startingHash is after limitHash (wrong order). The server -should ignore this invalid request.`, - }, - - { - nBytes: 4000, - root: root, - startingHash: firstKey, - limitHash: hashAdd(firstKey, -1), - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `In this test, the startingHash is the first available key, and limitHash is -a key before startingHash (wrong order). The server should return the first available key.`, - }, - - // range from [firstkey, 0], wrong order. Expect to get first key. - { - nBytes: 4000, - root: root, - startingHash: firstKey, - limitHash: zero, - expAccounts: 1, - expFirst: firstKey, - expLast: firstKey, - desc: `In this test, the startingHash is the first available key and limitHash is zero. -(wrong order). The server should return the first available key.`, - }, - } - - for i, tc := range tests { - tc := tc - if i > 0 { - t.Log("\n") - } - t.Logf("-- Test %d", i) - t.Log(tc.desc) - t.Log(" request:") - t.Logf(" root: %x", tc.root) - t.Logf(" range: %#x - %#x", tc.startingHash, tc.limitHash) - t.Logf(" responseBytes: %d", tc.nBytes) - if err := s.snapGetAccountRange(t, &tc); err != nil { - t.Errorf("test %d failed: %v", i, err) - } - } -} - -func hashAdd(h common.Hash, n int64) common.Hash { - hb := h.Big() - return common.BigToHash(hb.Add(hb, big.NewInt(n))) -} - -func findNonEmptyStorageRoot(accounts []state.DumpAccount) common.Hash { - for i := range accounts { - if len(accounts[i].Storage) != 0 { - return common.BytesToHash(accounts[i].Root) - } - } - panic("can't find account with non-empty storage") -} - -type stRangesTest struct { - root common.Hash - accounts []common.Hash - origin []byte - limit []byte - nBytes uint64 - - expSlots [][]*snap.StorageData - - desc string -} - -// TestSnapGetStorageRanges various forms of GetStorageRanges requests. -func (s *Suite) TestSnapGetStorageRanges(t *utesting.T) { - var ( - acct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067") - acctHash = common.BytesToHash(s.chain.state[acct].AddressHash) - ffHash = common.MaxHash - zero = common.Hash{} - blockroot = s.chain.Head().Root() - ) - - // These are the storage slots of the test account, encoded as snap response data. - acctSlots := []*snap.StorageData{ - { - Hash: common.HexToHash("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"), - Body: []byte{0x02}, - }, - { - Hash: common.HexToHash("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"), - Body: []byte{0x01}, - }, - { - Hash: common.HexToHash("0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b"), - Body: []byte{0x03}, - }, - } - - tests := []stRangesTest{ - /* - Some tests against this account: - - "0x8bebc8ba651aee624937e7d897853ac30c95a067": { - "balance": "1", - "nonce": 1, - "root": "0xe318dff15b33aa7f2f12d5567d58628e3e3f2e8859e46b56981a4083b391da17", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - // Note: keys below are hashed!!! - "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace": "02", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "01", - "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "03" - }, - "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099" - } - */ - - { // [:] -> [slot1, slot2, slot3] - desc: `This request has a range of 00..ff. -The server should return all storage slots of the test account.`, - root: blockroot, - accounts: []common.Hash{acctHash}, - origin: zero[:], - limit: ffHash[:], - nBytes: 500, - expSlots: [][]*snap.StorageData{acctSlots}, - }, - - { // [slot1:] -> [slot1, slot2, slot3] - desc: `This test requests slots starting at the first available key. -The server should return all storage slots of the test account.`, - root: blockroot, - accounts: []common.Hash{acctHash}, - origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"), - limit: ffHash[:], - nBytes: 1000, - expSlots: [][]*snap.StorageData{acctSlots}, - }, - - { // [slot1+:] -> [slot2, slot3] - desc: `This test requests slots starting at a key one past the first available key. -The server should return the remaining two slots of the test account.`, - root: blockroot, - accounts: []common.Hash{acctHash}, - origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf"), - limit: ffHash[:], - nBytes: 500, - expSlots: [][]*snap.StorageData{acctSlots[1:]}, - }, - - { // [slot1:slot2] -> [slot1, slot2] - desc: `This test requests a range which is exactly the first and second available key.`, - root: blockroot, - accounts: []common.Hash{acctHash}, - origin: common.FromHex("0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"), - limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"), - nBytes: 500, - expSlots: [][]*snap.StorageData{acctSlots[:2]}, - }, - - { // [slot1+:slot2+] -> [slot2, slot3] - desc: `This test requests a range where limitHash is after the second, but before the third slot -of the test account. The server should return slots [2,3] (i.e. the 'next available' needs to be returned).`, - root: blockroot, - accounts: []common.Hash{acctHash}, - origin: common.FromHex("0x4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - limit: common.FromHex("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7"), - nBytes: 500, - expSlots: [][]*snap.StorageData{acctSlots[1:]}, - }, - } - - for i, tc := range tests { - tc := tc - if i > 0 { - t.Log("\n") - } - t.Logf("-- Test %d", i) - t.Log(tc.desc) - t.Log(" request:") - t.Logf(" root: %x", tc.root) - t.Logf(" accounts: %x", tc.accounts) - t.Logf(" range: %#x - %#x", tc.origin, tc.limit) - t.Logf(" responseBytes: %d", tc.nBytes) - if err := s.snapGetStorageRanges(t, &tc); err != nil { - t.Errorf(" failed: %v", err) - } - } -} - -type byteCodesTest struct { - nBytes uint64 - hashes []common.Hash - - expHashes int - - desc string -} - -// TestSnapGetByteCodes various forms of GetByteCodes requests. -func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { - var ( - allHashes = s.chain.CodeHashes() - headRoot = s.chain.Head().Root() - genesisRoot = s.chain.RootAt(0) - ) - - tests := []byteCodesTest{ - // A few stateroots - { - desc: `Here we request state roots as code hashes. The server should deliver an empty response with no items.`, - nBytes: 10000, - hashes: []common.Hash{genesisRoot, headRoot}, - expHashes: 0, - }, - { - desc: `Here we request the genesis state root (which is not an existing code hash) two times. The server should deliver an empty response with no items.`, - nBytes: 10000, - hashes: []common.Hash{genesisRoot, genesisRoot}, - expHashes: 0, - }, - // Empties - { - desc: `Here we request the empty state root (which is not an existing code hash). The server should deliver an empty response with no items.`, - nBytes: 10000, - hashes: []common.Hash{types.EmptyRootHash}, - expHashes: 0, - }, - { - desc: `Here we request the empty code hash. The server should deliver an empty response item.`, - nBytes: 10000, - hashes: []common.Hash{types.EmptyCodeHash}, - expHashes: 1, - }, - { - desc: `In this test, we request the empty code hash three times. The server should deliver the empty item three times.`, - nBytes: 10000, - hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash}, - expHashes: 3, - }, - // The existing bytecodes - { - desc: `Here we request all available contract codes. The server should deliver them all in one response.`, - nBytes: 100000, - hashes: allHashes, - expHashes: len(allHashes), - }, - // The existing, with limited byte arg - { - desc: `In this test, the request has a bytes limit of one. The server should deliver one item.`, - nBytes: 1, - hashes: allHashes, - expHashes: 1, - }, - { - desc: `In this test, the request has a bytes limit of zero. The server should deliver one item.`, - nBytes: 0, - hashes: allHashes, - expHashes: 1, - }, - // Request the same hash multiple times. - { - desc: `This test requests the same code hash multiple times. The server should deliver it multiple times.`, - nBytes: 1000, - hashes: []common.Hash{allHashes[0], allHashes[0], allHashes[0], allHashes[0]}, - expHashes: 4, - }, - } - - for i, tc := range tests { - tc := tc - if i > 0 { - t.Log("\n") - } - t.Logf("-- Test %d", i) - t.Log(tc.desc) - t.Log(" request:") - t.Logf(" hashes: %x", tc.hashes) - t.Logf(" responseBytes: %d", tc.nBytes) - if err := s.snapGetByteCodes(t, &tc); err != nil { - t.Errorf("failed: %v", err) - } - } -} - -type trieNodesTest struct { - root common.Hash - paths []snap.TrieNodePathSet - nBytes uint64 - - expHashes []common.Hash // expected response - expReject bool // if true, request should be rejected - - desc string -} - -func decodeNibbles(nibbles []byte, bytes []byte) { - for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { - bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] - } -} - -// hasTerm returns whether a hex key has the terminator flag. -func hasTerm(s []byte) bool { - return len(s) > 0 && s[len(s)-1] == 16 -} - -func keybytesToHex(str []byte) []byte { - l := len(str)*2 + 1 - var nibbles = make([]byte, l) - for i, b := range str { - nibbles[i*2] = b / 16 - nibbles[i*2+1] = b % 16 - } - nibbles[l-1] = 16 - return nibbles -} - -func hexToCompact(hex []byte) []byte { - terminator := byte(0) - if hasTerm(hex) { - terminator = 1 - hex = hex[:len(hex)-1] - } - buf := make([]byte, len(hex)/2+1) - buf[0] = terminator << 5 // the flag byte - if len(hex)&1 == 1 { - buf[0] |= 1 << 4 // odd flag - buf[0] |= hex[0] // first nibble is contained in the first byte - hex = hex[1:] - } - decodeNibbles(hex, buf[1:]) - return buf -} - -// TestSnapTrieNodes various forms of GetTrieNodes requests. -func (s *Suite) TestSnapTrieNodes(t *utesting.T) { - var ( - // This is the known address of the snap storage testing contract. - storageAcct = common.HexToAddress("0x8bebc8ba651aee624937e7d897853ac30c95a067") - storageAcctHash = common.BytesToHash(s.chain.state[storageAcct].AddressHash) - // This is the known address of an existing account. - key = common.FromHex("0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9") - empty = types.EmptyCodeHash - accPaths []snap.TrieNodePathSet - ) - for i := 1; i <= 65; i++ { - accPaths = append(accPaths, makeSnapPath(key, i)) - } - - tests := []trieNodesTest{ - { - desc: `In this test, we send an empty request to the node.`, - root: s.chain.Head().Root(), - paths: nil, - nBytes: 500, - expHashes: nil, - }, - - { - desc: `In this test, we send a request containing an empty path-set. -The server should reject the request.`, - root: s.chain.Head().Root(), - paths: []snap.TrieNodePathSet{ - {}, // zero-length pathset should 'abort' and kick us off - {[]byte{0}}, - }, - nBytes: 5000, - expHashes: []common.Hash{}, - expReject: true, - }, - - { - desc: `Here we request the root node of the trie. The server should respond with the root node.`, - root: s.chain.RootAt(int(s.chain.Head().NumberU64() - 1)), - paths: []snap.TrieNodePathSet{ - {[]byte{0}}, - {[]byte{1}, []byte{0}}, - }, - nBytes: 5000, - expHashes: []common.Hash{s.chain.RootAt(int(s.chain.Head().NumberU64() - 1))}, - }, - - { // nonsensically long path - desc: `In this test, we request a very long trie node path. The server should respond with an empty node (keccak256("")).`, - root: s.chain.Head().Root(), - paths: []snap.TrieNodePathSet{ - {[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}}, - }, - nBytes: 5000, - expHashes: []common.Hash{common.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")}, - }, - - { - // The leaf is only a couple of levels down, so the continued trie traversal causes lookup failures. - desc: `Here we request some known accounts from the state.`, - root: s.chain.Head().Root(), - paths: accPaths, - nBytes: 5000, - expHashes: []common.Hash{ - // It's a bit unfortunate these are hard-coded, but the result depends on - // a lot of aspects of the state trie and can't be guessed in a simple - // way. So you'll have to update this when the test chain is changed. - common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"), - common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"), - empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, - empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, - empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, - empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, - empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, - empty, empty, empty}, - }, - - { - desc: `In this test, we request some known accounts in state. The requested paths are NOT in key order.`, - root: s.chain.Head().Root(), - paths: []snap.TrieNodePathSet{ - accPaths[10], accPaths[1], accPaths[0], - }, - nBytes: 5000, - // As with the previous test, this result depends on the whole tree and will have to - // be updated when the test chain is changed. - expHashes: []common.Hash{ - empty, - common.HexToHash("0xd0670d09cdfbf3c6320eb3e92c47c57baa6c226551a2d488c05581091e6b1689"), - common.HexToHash("0x3e963a69401a70224cbfb8c0cc2249b019041a538675d71ccf80c9328d114e2e"), - }, - }, - - // Storage tests. - // These use the known storage test account. - - { - desc: `This test requests the storage root node of a known account.`, - root: s.chain.Head().Root(), - paths: []snap.TrieNodePathSet{ - { - storageAcctHash[:], - []byte{0}, - }, - }, - nBytes: 5000, - expHashes: []common.Hash{ - common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"), - }, - }, - - { - desc: `This test requests multiple storage nodes of a known account.`, - root: s.chain.Head().Root(), - paths: []snap.TrieNodePathSet{ - { - storageAcctHash[:], - []byte{0}, - []byte{0x1b}, - }, - }, - nBytes: 5000, - expHashes: []common.Hash{ - common.HexToHash("0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790"), - common.HexToHash("0xf4984a11f61a2921456141df88de6e1a710d28681b91af794c5a721e47839cd7"), - }, - }, - } - - for i, tc := range tests { - tc := tc - if i > 0 { - t.Log("\n") - } - t.Logf("-- Test %d", i) - t.Log(tc.desc) - t.Log(" request:") - t.Logf(" root: %x", tc.root) - t.Logf(" paths: %x", tc.paths) - t.Logf(" responseBytes: %d", tc.nBytes) - - if err := s.snapGetTrieNodes(t, &tc); err != nil { - t.Errorf(" failed: %v", err) - } - } -} - -func makeSnapPath(key []byte, length int) snap.TrieNodePathSet { - hex := keybytesToHex(key)[:length] - hex[len(hex)-1] = 0 // remove term flag - hKey := hexToCompact(hex) - return snap.TrieNodePathSet{hKey} -} - -func (s *Suite) snapGetAccountRange(t *utesting.T, tc *accRangeTest) error { - conn, err := s.dialSnap() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - // write request - req := &snap.GetAccountRangePacket{ - ID: uint64(rand.Int63()), - Root: tc.root, - Origin: tc.startingHash, - Limit: tc.limitHash, - Bytes: tc.nBytes, - } - msg, err := conn.snapRequest(snap.GetAccountRangeMsg, req) - if err != nil { - return fmt.Errorf("account range request failed: %v", err) - } - res, ok := msg.(*snap.AccountRangePacket) - if !ok { - return fmt.Errorf("account range response wrong: %T %v", msg, msg) - } - if exp, got := tc.expAccounts, len(res.Accounts); exp != got { - return fmt.Errorf("expected %d accounts, got %d", exp, got) - } - // Check that the encoding order is correct - for i := 1; i < len(res.Accounts); i++ { - if bytes.Compare(res.Accounts[i-1].Hash[:], res.Accounts[i].Hash[:]) >= 0 { - return fmt.Errorf("accounts not monotonically increasing: #%d [%x] vs #%d [%x]", i-1, res.Accounts[i-1].Hash[:], i, res.Accounts[i].Hash[:]) - } - } - var ( - hashes []common.Hash - accounts [][]byte - proof = res.Proof - ) - hashes, accounts, err = res.Unpack() - if err != nil { - return err - } - if len(hashes) == 0 && len(accounts) == 0 && len(proof) == 0 { - return nil - } - if len(hashes) > 0 { - if exp, got := tc.expFirst, res.Accounts[0].Hash; exp != got { - return fmt.Errorf("expected first account %#x, got %#x", exp, got) - } - if exp, got := tc.expLast, res.Accounts[len(res.Accounts)-1].Hash; exp != got { - return fmt.Errorf("expected last account %#x, got %#x", exp, got) - } - } - // Reconstruct a partial trie from the response and verify it - keys := make([][]byte, len(hashes)) - for i, key := range hashes { - keys[i] = common.CopyBytes(key[:]) - } - nodes := make(trienode.ProofList, len(proof)) - for i, node := range proof { - nodes[i] = node - } - proofdb := nodes.Set() - - _, err = trie.VerifyRangeProof(tc.root, tc.startingHash[:], keys, accounts, proofdb) - return err -} - -func (s *Suite) snapGetStorageRanges(t *utesting.T, tc *stRangesTest) error { - conn, err := s.dialSnap() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - - // write request - req := &snap.GetStorageRangesPacket{ - ID: uint64(rand.Int63()), - Root: tc.root, - Accounts: tc.accounts, - Origin: tc.origin, - Limit: tc.limit, - Bytes: tc.nBytes, - } - msg, err := conn.snapRequest(snap.GetStorageRangesMsg, req) - if err != nil { - return fmt.Errorf("account range request failed: %v", err) - } - res, ok := msg.(*snap.StorageRangesPacket) - if !ok { - return fmt.Errorf("account range response wrong: %T %v", msg, msg) - } - - // Ensure the ranges are monotonically increasing - for i, slots := range res.Slots { - for j := 1; j < len(slots); j++ { - if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 { - return fmt.Errorf("storage slots not monotonically increasing for account #%d: #%d [%x] vs #%d [%x]", i, j-1, slots[j-1].Hash[:], j, slots[j].Hash[:]) - } - } - } - - // Compute expected slot hashes. - var expHashes [][]common.Hash - for _, acct := range tc.expSlots { - var list []common.Hash - for _, s := range acct { - list = append(list, s.Hash) - } - expHashes = append(expHashes, list) - } - - // Check response. - if !reflect.DeepEqual(res.Slots, tc.expSlots) { - t.Log(" expected slot hashes:", expHashes) - return fmt.Errorf("wrong storage slots in response: %#v", res.Slots) - } - return nil -} - -func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error { - conn, err := s.dialSnap() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - // write request - req := &snap.GetByteCodesPacket{ - ID: uint64(rand.Int63()), - Hashes: tc.hashes, - Bytes: tc.nBytes, - } - msg, err := conn.snapRequest(snap.GetByteCodesMsg, req) - if err != nil { - return fmt.Errorf("getBytecodes request failed: %v", err) - } - res, ok := msg.(*snap.ByteCodesPacket) - if !ok { - return fmt.Errorf("bytecodes response wrong: %T %v", msg, msg) - } - if exp, got := tc.expHashes, len(res.Codes); exp != got { - for i, c := range res.Codes { - t.Logf("%d. %#x\n", i, c) - } - return fmt.Errorf("expected %d bytecodes, got %d", exp, got) - } - // Cross reference the requested bytecodes with the response to find gaps - // that the serving node is missing - var ( - bytecodes = res.Codes - hasher = sha3.NewLegacyKeccak256().(crypto.KeccakState) - hash = make([]byte, 32) - codes = make([][]byte, len(req.Hashes)) - ) - - for i, j := 0, 0; i < len(bytecodes); i++ { - // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - - for j < len(req.Hashes) && !bytes.Equal(hash, req.Hashes[j][:]) { - j++ - } - if j < len(req.Hashes) { - codes[j] = bytecodes[i] - j++ - continue - } - // We've either ran out of hashes, or got unrequested data - return errors.New("unexpected bytecode") - } - - return nil -} - -func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error { - conn, err := s.dialSnap() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - - // write0 request - req := &snap.GetTrieNodesPacket{ - ID: uint64(rand.Int63()), - Root: tc.root, - Paths: tc.paths, - Bytes: tc.nBytes, - } - msg, err := conn.snapRequest(snap.GetTrieNodesMsg, req) - if err != nil { - if tc.expReject { - return nil - } - return fmt.Errorf("trienodes request failed: %v", err) - } - res, ok := msg.(*snap.TrieNodesPacket) - if !ok { - return fmt.Errorf("trienodes response wrong: %T %v", msg, msg) - } - - // Check the correctness - - // Cross reference the requested trienodes with the response to find gaps - // that the serving node is missing - hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) - hash := make([]byte, 32) - trienodes := res.Nodes - if got, want := len(trienodes), len(tc.expHashes); got != want { - return fmt.Errorf("wrong trienode count, got %d, want %d", got, want) - } - for i, trienode := range trienodes { - hasher.Reset() - hasher.Write(trienode) - hasher.Read(hash) - if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) { - t.Logf(" hash %d wrong, got %#x, want %#x\n", i, got, want) - err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want) - } - } - return err -} diff --git a/builder/cmd/devp2p/internal/ethtest/suite.go b/builder/cmd/devp2p/internal/ethtest/suite.go deleted file mode 100644 index d9efe2624..000000000 --- a/builder/cmd/devp2p/internal/ethtest/suite.go +++ /dev/null @@ -1,856 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "crypto/rand" - "math/big" - "reflect" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/holiman/uint256" -) - -// Suite represents a structure used to test a node's conformance -// to the eth protocol. -type Suite struct { - Dest *enode.Node - chain *Chain - engine *EngineClient -} - -// NewSuite creates and returns a new eth-test suite that can -// be used to test the given node against the given blockchain -// data. -func NewSuite(dest *enode.Node, chainDir, engineURL, jwt string) (*Suite, error) { - chain, err := NewChain(chainDir) - if err != nil { - return nil, err - } - engine, err := NewEngineClient(chainDir, engineURL, jwt) - if err != nil { - return nil, err - } - - return &Suite{ - Dest: dest, - chain: chain, - engine: engine, - }, nil -} - -func (s *Suite) EthTests() []utesting.Test { - return []utesting.Test{ - // status - {Name: "Status", Fn: s.TestStatus}, - // get block headers - {Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders}, - {Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests}, - {Name: "SameRequestID", Fn: s.TestSameRequestID}, - {Name: "ZeroRequestID", Fn: s.TestZeroRequestID}, - // get block bodies - {Name: "GetBlockBodies", Fn: s.TestGetBlockBodies}, - // // malicious handshakes + status - {Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake}, - {Name: "MaliciousStatus", Fn: s.TestMaliciousStatus}, - // test transactions - {Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true}, - {Name: "Transaction", Fn: s.TestTransaction}, - {Name: "InvalidTxs", Fn: s.TestInvalidTxs}, - {Name: "NewPooledTxs", Fn: s.TestNewPooledTxs}, - {Name: "BlobViolations", Fn: s.TestBlobViolations}, - } -} - -func (s *Suite) SnapTests() []utesting.Test { - return []utesting.Test{ - {Name: "Status", Fn: s.TestSnapStatus}, - {Name: "AccountRange", Fn: s.TestSnapGetAccountRange}, - {Name: "GetByteCodes", Fn: s.TestSnapGetByteCodes}, - {Name: "GetTrieNodes", Fn: s.TestSnapTrieNodes}, - {Name: "GetStorageRanges", Fn: s.TestSnapGetStorageRanges}, - } -} - -func (s *Suite) TestStatus(t *utesting.T) { - t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } -} - -// headersMatch returns whether the received headers match the given request -func headersMatch(expected []*types.Header, headers []*types.Header) bool { - return reflect.DeepEqual(expected, headers) -} - -func (s *Suite) TestGetBlockHeaders(t *utesting.T) { - t.Log(`This test requests block headers from the node.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - // Send headers request. - req := ð.GetBlockHeadersPacket{ - RequestId: 33, - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()}, - Amount: 2, - Skip: 1, - Reverse: false, - }, - } - // Read headers response. - if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil { - t.Fatalf("could not write to connection: %v", err) - } - headers := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil { - t.Fatalf("error reading msg: %v", err) - } - if got, want := headers.RequestId, req.RequestId; got != want { - t.Fatalf("unexpected request id") - } - // Check for correct headers. - expected, err := s.chain.GetHeaders(req) - if err != nil { - t.Fatalf("failed to get headers for given request: %v", err) - } - if !headersMatch(expected, headers.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers) - } -} - -func (s *Suite) TestSimultaneousRequests(t *utesting.T) { - t.Log(`This test requests blocks headers from the node, performing two requests -concurrently, with different request IDs.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - - // Create two different requests. - req1 := ð.GetBlockHeadersPacket{ - RequestId: uint64(111), - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Hash: s.chain.blocks[1].Hash(), - }, - Amount: 2, - Skip: 1, - Reverse: false, - }, - } - req2 := ð.GetBlockHeadersPacket{ - RequestId: uint64(222), - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Hash: s.chain.blocks[1].Hash(), - }, - Amount: 4, - Skip: 1, - Reverse: false, - }, - } - - // Send both requests. - if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req1); err != nil { - t.Fatalf("failed to write to connection: %v", err) - } - if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req2); err != nil { - t.Fatalf("failed to write to connection: %v", err) - } - - // Wait for responses. - headers1 := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil { - t.Fatalf("error reading block headers msg: %v", err) - } - if got, want := headers1.RequestId, req1.RequestId; got != want { - t.Fatalf("unexpected request id in response: got %d, want %d", got, want) - } - headers2 := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil { - t.Fatalf("error reading block headers msg: %v", err) - } - if got, want := headers2.RequestId, req2.RequestId; got != want { - t.Fatalf("unexpected request id in response: got %d, want %d", got, want) - } - - // Check received headers for accuracy. - if expected, err := s.chain.GetHeaders(req1); err != nil { - t.Fatalf("failed to get expected headers for request 1: %v", err) - } else if !headersMatch(expected, headers1.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1) - } - if expected, err := s.chain.GetHeaders(req2); err != nil { - t.Fatalf("failed to get expected headers for request 2: %v", err) - } else if !headersMatch(expected, headers2.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2) - } -} - -func (s *Suite) TestSameRequestID(t *utesting.T) { - t.Log(`This test requests block headers, performing two concurrent requests with the -same request ID. The node should handle the request by responding to both requests.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - - // Create two different requests with the same ID. - reqID := uint64(1234) - request1 := ð.GetBlockHeadersPacket{ - RequestId: reqID, - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Number: 1, - }, - Amount: 2, - }, - } - request2 := ð.GetBlockHeadersPacket{ - RequestId: reqID, - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Number: 33, - }, - Amount: 2, - }, - } - - // Send the requests. - if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request1); err != nil { - t.Fatalf("failed to write to connection: %v", err) - } - if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request2); err != nil { - t.Fatalf("failed to write to connection: %v", err) - } - - // Wait for the responses. - headers1 := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil { - t.Fatalf("error reading from connection: %v", err) - } - if got, want := headers1.RequestId, request1.RequestId; got != want { - t.Fatalf("unexpected request id: got %d, want %d", got, want) - } - headers2 := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil { - t.Fatalf("error reading from connection: %v", err) - } - if got, want := headers2.RequestId, request2.RequestId; got != want { - t.Fatalf("unexpected request id: got %d, want %d", got, want) - } - - // Check if headers match. - if expected, err := s.chain.GetHeaders(request1); err != nil { - t.Fatalf("failed to get expected block headers: %v", err) - } else if !headersMatch(expected, headers1.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1) - } - if expected, err := s.chain.GetHeaders(request2); err != nil { - t.Fatalf("failed to get expected block headers: %v", err) - } else if !headersMatch(expected, headers2.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2) - } -} - -func (s *Suite) TestZeroRequestID(t *utesting.T) { - t.Log(`This test sends a GetBlockHeaders message with a request-id of zero, -and expects a response.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - req := ð.GetBlockHeadersPacket{ - GetBlockHeadersRequest: ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{Number: 0}, - Amount: 2, - }, - } - // Read headers response. - if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil { - t.Fatalf("could not write to connection: %v", err) - } - headers := new(eth.BlockHeadersPacket) - if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil { - t.Fatalf("error reading msg: %v", err) - } - if got, want := headers.RequestId, req.RequestId; got != want { - t.Fatalf("unexpected request id") - } - if expected, err := s.chain.GetHeaders(req); err != nil { - t.Fatalf("failed to get expected block headers: %v", err) - } else if !headersMatch(expected, headers.BlockHeadersRequest) { - t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers) - } -} - -func (s *Suite) TestGetBlockBodies(t *utesting.T) { - t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - // Create block bodies request. - req := ð.GetBlockBodiesPacket{ - RequestId: 55, - GetBlockBodiesRequest: eth.GetBlockBodiesRequest{ - s.chain.blocks[54].Hash(), - s.chain.blocks[75].Hash(), - }, - } - if err := conn.Write(ethProto, eth.GetBlockBodiesMsg, req); err != nil { - t.Fatalf("could not write to connection: %v", err) - } - // Wait for response. - resp := new(eth.BlockBodiesPacket) - if err := conn.ReadMsg(ethProto, eth.BlockBodiesMsg, &resp); err != nil { - t.Fatalf("error reading block bodies msg: %v", err) - } - if got, want := resp.RequestId, req.RequestId; got != want { - t.Fatalf("unexpected request id in respond", got, want) - } - bodies := resp.BlockBodiesResponse - if len(bodies) != len(req.GetBlockBodiesRequest) { - t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), len(bodies)) - } -} - -// randBuf makes a random buffer size kilobytes large. -func randBuf(size int) []byte { - buf := make([]byte, size*1024) - rand.Read(buf) - return buf -} - -func (s *Suite) TestMaliciousHandshake(t *utesting.T) { - t.Log(`This test tries to send malicious data during the devp2p handshake, in various ways.`) - - // Write hello to client. - var ( - key, _ = crypto.GenerateKey() - pub0 = crypto.FromECDSAPub(&key.PublicKey)[1:] - version = eth.ProtocolVersions[0] - ) - handshakes := []*protoHandshake{ - { - Version: 5, - Caps: []p2p.Cap{ - {Name: string(randBuf(2)), Version: version}, - }, - ID: pub0, - }, - { - Version: 5, - Caps: []p2p.Cap{ - {Name: "eth", Version: version}, - }, - ID: append(pub0, byte(0)), - }, - { - Version: 5, - Caps: []p2p.Cap{ - {Name: "eth", Version: version}, - }, - ID: append(pub0, pub0...), - }, - { - Version: 5, - Caps: []p2p.Cap{ - {Name: "eth", Version: version}, - }, - ID: randBuf(2), - }, - { - Version: 5, - Caps: []p2p.Cap{ - {Name: string(randBuf(2)), Version: version}, - }, - ID: randBuf(2), - }, - } - for _, handshake := range handshakes { - conn, err := s.dialAs(key) - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - - if err := conn.Write(ethProto, handshakeMsg, handshake); err != nil { - t.Fatalf("could not write to connection: %v", err) - } - // Check that the peer disconnected - for i := 0; i < 2; i++ { - code, _, err := conn.Read() - if err != nil { - // Client may have disconnected without sending disconnect msg. - continue - } - switch code { - case discMsg: - case handshakeMsg: - // Discard one hello as Hello's are sent concurrently - continue - default: - t.Fatalf("unexpected msg: code %d", code) - } - } - } -} - -func (s *Suite) TestMaliciousStatus(t *utesting.T) { - t.Log(`This test sends a malicious eth Status message to the node and expects a disconnect.`) - - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err := conn.handshake(); err != nil { - t.Fatalf("handshake failed: %v", err) - } - // Create status with large total difficulty. - status := ð.StatusPacket{ - ProtocolVersion: uint32(conn.negotiatedProtoVersion), - NetworkID: s.chain.config.ChainID.Uint64(), - TD: new(big.Int).SetBytes(randBuf(2048)), - Head: s.chain.Head().Hash(), - Genesis: s.chain.GetBlock(0).Hash(), - ForkID: s.chain.ForkID(), - } - if err := conn.statusExchange(s.chain, status); err != nil { - t.Fatalf("status exchange failed: %v", err) - } - // Wait for disconnect. - code, _, err := conn.Read() - if err != nil { - t.Fatalf("error reading from connection: %v", err) - } - switch code { - case discMsg: - break - default: - t.Fatalf("expected disconnect, got: %d", code) - } -} - -func (s *Suite) TestTransaction(t *utesting.T) { - t.Log(`This test sends a valid transaction to the node and checks if the -transaction gets propagated.`) - - // Nudge client out of syncing mode to accept pending txs. - if err := s.engine.sendForkchoiceUpdated(); err != nil { - t.Fatalf("failed to send next block: %v", err) - } - from, nonce := s.chain.GetSender(0) - inner := &types.DynamicFeeTx{ - ChainID: s.chain.config.ChainID, - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 30000, - To: &common.Address{0xaa}, - Value: common.Big1, - } - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - t.Fatalf("failed to sign tx: %v", err) - } - if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil { - t.Fatal(err) - } - s.chain.IncNonce(from, 1) -} - -func (s *Suite) TestInvalidTxs(t *utesting.T) { - t.Log(`This test sends several kinds of invalid transactions and checks that the node -does not propagate them.`) - - // Nudge client out of syncing mode to accept pending txs. - if err := s.engine.sendForkchoiceUpdated(); err != nil { - t.Fatalf("failed to send next block: %v", err) - } - - from, nonce := s.chain.GetSender(0) - inner := &types.DynamicFeeTx{ - ChainID: s.chain.config.ChainID, - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 30000, - To: &common.Address{0xaa}, - } - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - t.Fatalf("failed to sign tx: %v", err) - } - if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil { - t.Fatalf("failed to send txs: %v", err) - } - s.chain.IncNonce(from, 1) - - inners := []*types.DynamicFeeTx{ - // Nonce already used - { - ChainID: s.chain.config.ChainID, - Nonce: nonce - 1, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 100000, - }, - // Value exceeds balance - { - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 100000, - Value: s.chain.Balance(from), - }, - // Gas limit too low - { - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 1337, - }, - // Code size too large - { - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Data: randBuf(50), - Gas: 1_000_000, - }, - // Data too large - { - Nonce: nonce, - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - To: &common.Address{0xaa}, - Data: randBuf(128), - Gas: 5_000_000, - }, - } - - var txs []*types.Transaction - for _, inner := range inners { - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - t.Fatalf("failed to sign tx: %v", err) - } - txs = append(txs, tx) - } - if err := s.sendInvalidTxs(t, txs); err != nil { - t.Fatalf("failed to send invalid txs: %v", err) - } -} - -func (s *Suite) TestLargeTxRequest(t *utesting.T) { - t.Log(`This test first send ~2000 transactions to the node, then requests them -on another peer connection using GetPooledTransactions.`) - - // Nudge client out of syncing mode to accept pending txs. - if err := s.engine.sendForkchoiceUpdated(); err != nil { - t.Fatalf("failed to send next block: %v", err) - } - - // Generate many transactions to seed target with. - var ( - from, nonce = s.chain.GetSender(1) - count = 2000 - txs []*types.Transaction - hashes []common.Hash - set = make(map[common.Hash]struct{}) - ) - for i := 0; i < count; i++ { - inner := &types.DynamicFeeTx{ - ChainID: s.chain.config.ChainID, - Nonce: nonce + uint64(i), - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 75000, - } - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - t.Fatalf("failed to sign tx: err") - } - txs = append(txs, tx) - set[tx.Hash()] = struct{}{} - hashes = append(hashes, tx.Hash()) - } - s.chain.IncNonce(from, uint64(count)) - - // Send txs. - if err := s.sendTxs(t, txs); err != nil { - t.Fatalf("failed to send txs: %v", err) - } - - // Set up receive connection to ensure node is peered with the receiving - // connection before tx request is sent. - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - // Create and send pooled tx request. - req := ð.GetPooledTransactionsPacket{ - RequestId: 1234, - GetPooledTransactionsRequest: hashes, - } - if err = conn.Write(ethProto, eth.GetPooledTransactionsMsg, req); err != nil { - t.Fatalf("could not write to conn: %v", err) - } - // Check that all received transactions match those that were sent to node. - msg := new(eth.PooledTransactionsPacket) - if err := conn.ReadMsg(ethProto, eth.PooledTransactionsMsg, &msg); err != nil { - t.Fatalf("error reading from connection: %v", err) - } - if got, want := msg.RequestId, req.RequestId; got != want { - t.Fatalf("unexpected request id in response: got %d, want %d", got, want) - } - for _, got := range msg.PooledTransactionsResponse { - if _, exists := set[got.Hash()]; !exists { - t.Fatalf("unexpected tx received: %v", got.Hash()) - } - } -} - -func (s *Suite) TestNewPooledTxs(t *utesting.T) { - t.Log(`This test announces transaction hashes to the node and expects it to fetch -the transactions using a GetPooledTransactions request.`) - - // Nudge client out of syncing mode to accept pending txs. - if err := s.engine.sendForkchoiceUpdated(); err != nil { - t.Fatalf("failed to send next block: %v", err) - } - - var ( - count = 50 - from, nonce = s.chain.GetSender(1) - hashes = make([]common.Hash, count) - txTypes = make([]byte, count) - sizes = make([]uint32, count) - ) - for i := 0; i < count; i++ { - inner := &types.DynamicFeeTx{ - ChainID: s.chain.config.ChainID, - Nonce: nonce + uint64(i), - GasTipCap: common.Big1, - GasFeeCap: s.chain.Head().BaseFee(), - Gas: 75000, - } - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - t.Fatalf("failed to sign tx: err") - } - hashes[i] = tx.Hash() - txTypes[i] = tx.Type() - sizes[i] = uint32(tx.Size()) - } - s.chain.IncNonce(from, uint64(count)) - - // Connect to peer. - conn, err := s.dial() - if err != nil { - t.Fatalf("dial failed: %v", err) - } - defer conn.Close() - if err = conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - - // Send announcement. - ann := eth.NewPooledTransactionHashesPacket{Types: txTypes, Sizes: sizes, Hashes: hashes} - err = conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann) - if err != nil { - t.Fatalf("failed to write to connection: %v", err) - } - - // Wait for GetPooledTxs request. - for { - msg, err := conn.ReadEth() - if err != nil { - t.Fatalf("failed to read eth msg: %v", err) - } - switch msg := msg.(type) { - case *eth.GetPooledTransactionsPacket: - if len(msg.GetPooledTransactionsRequest) != len(hashes) { - t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest)) - } - return - case *eth.NewPooledTransactionHashesPacket: - continue - case *eth.TransactionsPacket: - continue - default: - t.Fatalf("unexpected %s", pretty.Sdump(msg)) - } - } -} - -func makeSidecar(data ...byte) *types.BlobTxSidecar { - var ( - blobs = make([]kzg4844.Blob, len(data)) - commitments []kzg4844.Commitment - proofs []kzg4844.Proof - ) - for i := range blobs { - blobs[i][0] = data[i] - c, _ := kzg4844.BlobToCommitment(blobs[i]) - p, _ := kzg4844.ComputeBlobProof(blobs[i], c) - commitments = append(commitments, c) - proofs = append(proofs, p) - } - return &types.BlobTxSidecar{ - Blobs: blobs, - Commitments: commitments, - Proofs: proofs, - } -} - -func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) { - from, nonce := s.chain.GetSender(5) - for i := 0; i < count; i++ { - // Make blob data, max of 2 blobs per tx. - blobdata := make([]byte, blobs%3) - for i := range blobdata { - blobdata[i] = discriminator - blobs -= 1 - } - inner := &types.BlobTx{ - ChainID: uint256.MustFromBig(s.chain.config.ChainID), - Nonce: nonce + uint64(i), - GasTipCap: uint256.NewInt(1), - GasFeeCap: uint256.MustFromBig(s.chain.Head().BaseFee()), - Gas: 100000, - BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())), - BlobHashes: makeSidecar(blobdata...).BlobHashes(), - Sidecar: makeSidecar(blobdata...), - } - tx, err := s.chain.SignTx(from, types.NewTx(inner)) - if err != nil { - panic("blob tx signing failed") - } - txs = append(txs, tx) - } - return txs -} - -func (s *Suite) TestBlobViolations(t *utesting.T) { - t.Log(`This test sends some invalid blob tx announcements and expects the node to disconnect.`) - - if err := s.engine.sendForkchoiceUpdated(); err != nil { - t.Fatalf("send fcu failed: %v", err) - } - // Create blob txs for each tests with unique tx hashes. - var ( - t1 = s.makeBlobTxs(2, 3, 0x1) - t2 = s.makeBlobTxs(2, 3, 0x2) - ) - for _, test := range []struct { - ann eth.NewPooledTransactionHashesPacket - resp eth.PooledTransactionsResponse - }{ - // Invalid tx size. - { - ann: eth.NewPooledTransactionHashesPacket{ - Types: []byte{types.BlobTxType, types.BlobTxType}, - Sizes: []uint32{uint32(t1[0].Size()), uint32(t1[1].Size() + 10)}, - Hashes: []common.Hash{t1[0].Hash(), t1[1].Hash()}, - }, - resp: eth.PooledTransactionsResponse(t1), - }, - // Wrong tx type. - { - ann: eth.NewPooledTransactionHashesPacket{ - Types: []byte{types.DynamicFeeTxType, types.BlobTxType}, - Sizes: []uint32{uint32(t2[0].Size()), uint32(t2[1].Size())}, - Hashes: []common.Hash{t2[0].Hash(), t2[1].Hash()}, - }, - resp: eth.PooledTransactionsResponse(t2), - }, - } { - conn, err := s.dial() - if err != nil { - t.Fatalf("dial fail: %v", err) - } - if err := conn.peer(s.chain, nil); err != nil { - t.Fatalf("peering failed: %v", err) - } - if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, test.ann); err != nil { - t.Fatalf("sending announcement failed: %v", err) - } - req := new(eth.GetPooledTransactionsPacket) - if err := conn.ReadMsg(ethProto, eth.GetPooledTransactionsMsg, req); err != nil { - t.Fatalf("reading pooled tx request failed: %v", err) - } - resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: test.resp} - if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil { - t.Fatalf("writing pooled tx response failed: %v", err) - } - if code, _, err := conn.Read(); err != nil { - t.Fatalf("expected disconnect on blob violation, got err: %v", err) - } else if code != discMsg { - t.Fatalf("expected disconnect on blob violation, got msg code: %d", code) - } - conn.Close() - } -} diff --git a/builder/cmd/devp2p/internal/ethtest/suite_test.go b/builder/cmd/devp2p/internal/ethtest/suite_test.go deleted file mode 100644 index ad73bc9f9..000000000 --- a/builder/cmd/devp2p/internal/ethtest/suite_test.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - crand "crypto/rand" - "fmt" - "os" - "path" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/catalyst" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" -) - -func makeJWTSecret() (string, [32]byte, error) { - var secret [32]byte - if _, err := crand.Read(secret[:]); err != nil { - return "", secret, fmt.Errorf("failed to create jwt secret: %v", err) - } - jwtPath := path.Join(os.TempDir(), "jwt_secret") - if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil { - return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err) - } - return jwtPath, secret, nil -} - -func TestEthSuite(t *testing.T) { - jwtPath, secret, err := makeJWTSecret() - if err != nil { - t.Fatalf("could not make jwt secret: %v", err) - } - geth, err := runGeth("./testdata", jwtPath) - if err != nil { - t.Fatalf("could not run geth: %v", err) - } - defer geth.Close() - - suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:])) - if err != nil { - t.Fatalf("could not create new test suite: %v", err) - } - for _, test := range suite.EthTests() { - t.Run(test.Name, func(t *testing.T) { - if test.Slow && testing.Short() { - t.Skipf("%s: skipping in -short mode", test.Name) - } - result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) - if result[0].Failed { - t.Fatal() - } - }) - } -} - -func TestSnapSuite(t *testing.T) { - jwtPath, secret, err := makeJWTSecret() - if err != nil { - t.Fatalf("could not make jwt secret: %v", err) - } - geth, err := runGeth("./testdata", jwtPath) - if err != nil { - t.Fatalf("could not run geth: %v", err) - } - defer geth.Close() - - suite, err := NewSuite(geth.Server().Self(), "./testdata", geth.HTTPAuthEndpoint(), common.Bytes2Hex(secret[:])) - if err != nil { - t.Fatalf("could not create new test suite: %v", err) - } - for _, test := range suite.SnapTests() { - t.Run(test.Name, func(t *testing.T) { - result := utesting.RunTests([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) - if result[0].Failed { - t.Fatal() - } - }) - } -} - -// runGeth creates and starts a geth node -func runGeth(dir string, jwtPath string) (*node.Node, error) { - stack, err := node.New(&node.Config{ - AuthAddr: "127.0.0.1", - AuthPort: 0, - P2P: p2p.Config{ - ListenAddr: "127.0.0.1:0", - NoDiscovery: true, - MaxPeers: 10, // in case a test requires multiple connections, can be changed in the future - NoDial: true, - }, - JWTSecret: jwtPath, - }) - if err != nil { - return nil, err - } - - err = setupGeth(stack, dir) - if err != nil { - stack.Close() - return nil, err - } - if err = stack.Start(); err != nil { - stack.Close() - return nil, err - } - return stack, nil -} - -func setupGeth(stack *node.Node, dir string) error { - chain, err := NewChain(dir) - if err != nil { - return err - } - backend, err := eth.New(stack, ðconfig.Config{ - Genesis: &chain.genesis, - NetworkId: chain.genesis.Config.ChainID.Uint64(), // 19763 - DatabaseCache: 10, - TrieCleanCache: 10, - TrieDirtyCache: 16, - TrieTimeout: 60 * time.Minute, - SnapshotCache: 10, - }) - if err != nil { - return err - } - if err := catalyst.Register(stack, backend); err != nil { - return fmt.Errorf("failed to register catalyst service: %v", err) - } - _, err = backend.BlockChain().InsertChain(chain.blocks[1:]) - return err -} diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/accounts.json b/builder/cmd/devp2p/internal/ethtest/testdata/accounts.json deleted file mode 100644 index c9666235a..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/accounts.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "0x0c2c51a0990aee1d73c1228de158688341557508": { - "key": "0xbfcd0e032489319f4e5ca03e643b2025db624be6cf99cbfed90c4502e3754850" - }, - "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": { - "key": "0x457075f6822ac29481154792f65c5f1ec335b4fea9ca20f3fea8fa1d78a12c68" - }, - "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": { - "key": "0x865898edcf43206d138c93f1bbd86311f4657b057658558888aa5ac4309626a6" - }, - "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": { - "key": "0xee7f7875d826d7443ccc5c174e38b2c436095018774248a8074ee92d8914dcdb" - }, - "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": { - "key": "0x25e6ce8611cefb5cd338aeaa9292ed2139714668d123a4fb156cabb42051b5b7" - }, - "0x2d389075be5be9f2246ad654ce152cf05990b209": { - "key": "0x19168cd7767604b3d19b99dc3da1302b9ccb6ee9ad61660859e07acd4a2625dd" - }, - "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": { - "key": "0x71aa7d299c7607dabfc3d0e5213d612b5e4a97455b596c2f642daac43fa5eeaa" - }, - "0x4340ee1b812acb40a1eb561c019c327b243b92df": { - "key": "0x47f666f20e2175606355acec0ea1b37870c15e5797e962340da7ad7972a537e8" - }, - "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": { - "key": "0xa88293fefc623644969e2ce6919fb0dbd0fd64f640293b4bf7e1a81c97e7fc7f" - }, - "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": { - "key": "0x6e1e16a9c15641c73bf6e237f9293ab1d4e7c12b9adf83cfc94bcf969670f72d" - }, - "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": { - "key": "0x41be4e00aac79f7ffbb3455053ec05e971645440d594c047cdcc56a3c7458bd6" - }, - "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": { - "key": "0xc825f31cd8792851e33a290b3d749e553983111fc1f36dfbbdb45f101973f6a9" - }, - "0x717f8aa2b982bee0e29f573d31df288663e1ce16": { - "key": "0x8d0faa04ae0f9bc3cd4c890aa025d5f40916f4729538b19471c0beefe11d9e19" - }, - "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": { - "key": "0x4552dbe6ca4699322b5d923d0c9bcdd24644f5db8bf89a085b67c6c49b8a1b91" - }, - "0x83c7e323d189f18725ac510004fdc2941f8c4a78": { - "key": "0x34391cbbf06956bb506f45ec179cdd84df526aa364e27bbde65db9c15d866d00" - }, - "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": { - "key": "0xf6a8f1603b8368f3ca373292b7310c53bec7b508aecacd442554ebc1c5d0c856" - }, - "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": { - "key": "0x8d56bcbcf2c1b7109e1396a28d7a0234e33544ade74ea32c460ce4a443b239b1" - }, - "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": { - "key": "0xfc39d1c9ddbba176d806ebb42d7460189fe56ca163ad3eb6143bfc6beb6f6f72" - }, - "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": { - "key": "0x9ee3fd550664b246ad7cdba07162dd25530a3b1d51476dd1d85bbc29f0592684" - }, - "0xeda8645ba6948855e3b3cd596bbb07596d59c603": { - "key": "0x14cdde09d1640eb8c3cda063891b0453073f57719583381ff78811efa6d4199f" - } -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/chain.rlp b/builder/cmd/devp2p/internal/ethtest/testdata/chain.rlp deleted file mode 100644 index 2964c02bb..000000000 Binary files a/builder/cmd/devp2p/internal/ethtest/testdata/chain.rlp and /dev/null differ diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/forkenv.json b/builder/cmd/devp2p/internal/ethtest/testdata/forkenv.json deleted file mode 100644 index 86c49e2b9..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/forkenv.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "HIVE_CANCUN_TIMESTAMP": "840", - "HIVE_CHAIN_ID": "3503995874084926", - "HIVE_FORK_ARROW_GLACIER": "60", - "HIVE_FORK_BERLIN": "48", - "HIVE_FORK_BYZANTIUM": "18", - "HIVE_FORK_CONSTANTINOPLE": "24", - "HIVE_FORK_GRAY_GLACIER": "66", - "HIVE_FORK_HOMESTEAD": "0", - "HIVE_FORK_ISTANBUL": "36", - "HIVE_FORK_LONDON": "54", - "HIVE_FORK_MUIR_GLACIER": "42", - "HIVE_FORK_PETERSBURG": "30", - "HIVE_FORK_SPURIOUS": "12", - "HIVE_FORK_TANGERINE": "6", - "HIVE_MERGE_BLOCK_ID": "72", - "HIVE_NETWORK_ID": "3503995874084926", - "HIVE_SHANGHAI_TIMESTAMP": "780", - "HIVE_TERMINAL_TOTAL_DIFFICULTY": "9454784" -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/genesis.json b/builder/cmd/devp2p/internal/ethtest/testdata/genesis.json deleted file mode 100644 index e8bb66bb3..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/genesis.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "config": { - "chainId": 3503995874084926, - "homesteadBlock": 0, - "eip150Block": 6, - "eip155Block": 12, - "eip158Block": 12, - "byzantiumBlock": 18, - "constantinopleBlock": 24, - "petersburgBlock": 30, - "istanbulBlock": 36, - "muirGlacierBlock": 42, - "berlinBlock": 48, - "londonBlock": 54, - "arrowGlacierBlock": 60, - "grayGlacierBlock": 66, - "mergeNetsplitBlock": 72, - "shanghaiTime": 780, - "cancunTime": 840, - "terminalTotalDifficulty": 9454784, - "terminalTotalDifficultyPassed": true, - "ethash": {} - }, - "nonce": "0x0", - "timestamp": "0x0", - "extraData": "0x68697665636861696e", - "gasLimit": "0x23f3e20", - "difficulty": "0x20000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "000f3df6d732807ef1319fb7b8bb8522d0beac02": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", - "balance": "0x2a" - }, - "0c2c51a0990aee1d73c1228de158688341557508": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "14e46043e63d0e3cdcf2530519f4cfaf35058cb2": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "1f5bde34b4afc686f136c7a3cb6ec376f7357759": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "2d389075be5be9f2246ad654ce152cf05990b209": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "4340ee1b812acb40a1eb561c019c327b243b92df": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "4a0f1452281bcec5bd90c3dce6162a5995bfe9df": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "4dde844b71bcdf95512fb4dc94e84fb67b512ed8": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "5f552da00dfb4d3749d9e62dcee3c918855a86a0": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "654aa64f5fbefb84c270ec74211b81ca8c44a72e": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "717f8aa2b982bee0e29f573d31df288663e1ce16": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "83c7e323d189f18725ac510004fdc2941f8c4a78": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "84e75c28348fb86acea1a93a39426d7d60f4cc46": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "8bebc8ba651aee624937e7d897853ac30c95a067": { - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - "balance": "0x1", - "nonce": "0x1" - }, - "c7b99a164efd027a93f147376cc7da7c67c6bbe0": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "d803681e487e6ac18053afc5a6cd813c86ec3e4d": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "e7d13f7aa2a838d24c59b40186a0aca1e21cffcc": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - }, - "eda8645ba6948855e3b3cd596bbb07596d59c603": { - "balance": "0xc097ce7bc90715b34b9f1000000000" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "baseFeePerGas": null, - "excessBlobGas": null, - "blobGasUsed": null -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/headblock.json b/builder/cmd/devp2p/internal/ethtest/testdata/headblock.json deleted file mode 100644 index e84e96b0f..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/headblock.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "miner": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94", - "transactionsRoot": "0xecda39025fc4c609ce778d75eed0aa53b65ce1e3d1373b34bad8578cc31e5b48", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x0", - "number": "0x1f4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1388", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "baseFeePerGas": "0x7", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "blobGasUsed": "0x0", - "excessBlobGas": "0x0", - "parentBeaconBlockRoot": "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c", - "hash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7" -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/headfcu.json b/builder/cmd/devp2p/internal/ethtest/testdata/headfcu.json deleted file mode 100644 index 920212d0c..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/headfcu.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "jsonrpc": "2.0", - "id": "fcu500", - "method": "engine_forkchoiceUpdatedV3", - "params": [ - { - "headBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7", - "safeBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7", - "finalizedBlockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7" - }, - null - ] -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/headstate.json b/builder/cmd/devp2p/internal/ethtest/testdata/headstate.json deleted file mode 100644 index f7b076af6..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/headstate.json +++ /dev/null @@ -1,4204 +0,0 @@ -{ - "root": "ea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94", - "accounts": { - "0x0000000000000000000000000000000000000000": { - "balance": "233437500000029008737", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a" - }, - "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { - "balance": "42", - "nonce": 0, - "root": "0xac3162a8b9dbb4318b84219f3140e7a9ec35126234120297dde10f51b25f6a26", - "codeHash": "0xf57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000348": "0348", - "0x0000000000000000000000000000000000000000000000000000000000000352": "0352", - "0x000000000000000000000000000000000000000000000000000000000000035c": "035c", - "0x0000000000000000000000000000000000000000000000000000000000000366": "0366", - "0x0000000000000000000000000000000000000000000000000000000000000370": "0370", - "0x000000000000000000000000000000000000000000000000000000000000037a": "037a", - "0x0000000000000000000000000000000000000000000000000000000000000384": "0384", - "0x000000000000000000000000000000000000000000000000000000000000038e": "038e", - "0x0000000000000000000000000000000000000000000000000000000000000398": "0398", - "0x00000000000000000000000000000000000000000000000000000000000003a2": "03a2", - "0x00000000000000000000000000000000000000000000000000000000000003ac": "03ac", - "0x00000000000000000000000000000000000000000000000000000000000003b6": "03b6", - "0x00000000000000000000000000000000000000000000000000000000000003c0": "03c0", - "0x00000000000000000000000000000000000000000000000000000000000003ca": "03ca", - "0x00000000000000000000000000000000000000000000000000000000000003d4": "03d4", - "0x00000000000000000000000000000000000000000000000000000000000003de": "03de", - "0x00000000000000000000000000000000000000000000000000000000000003e8": "03e8", - "0x00000000000000000000000000000000000000000000000000000000000003f2": "03f2", - "0x00000000000000000000000000000000000000000000000000000000000003fc": "03fc", - "0x0000000000000000000000000000000000000000000000000000000000000406": "0406", - "0x0000000000000000000000000000000000000000000000000000000000000410": "0410", - "0x000000000000000000000000000000000000000000000000000000000000041a": "041a", - "0x0000000000000000000000000000000000000000000000000000000000000424": "0424", - "0x000000000000000000000000000000000000000000000000000000000000042e": "042e", - "0x0000000000000000000000000000000000000000000000000000000000000438": "0438", - "0x0000000000000000000000000000000000000000000000000000000000000442": "0442", - "0x000000000000000000000000000000000000000000000000000000000000044c": "044c", - "0x0000000000000000000000000000000000000000000000000000000000000456": "0456", - "0x0000000000000000000000000000000000000000000000000000000000000460": "0460", - "0x000000000000000000000000000000000000000000000000000000000000046a": "046a", - "0x0000000000000000000000000000000000000000000000000000000000000474": "0474", - "0x000000000000000000000000000000000000000000000000000000000000047e": "047e", - "0x0000000000000000000000000000000000000000000000000000000000000488": "0488", - "0x0000000000000000000000000000000000000000000000000000000000000492": "0492", - "0x000000000000000000000000000000000000000000000000000000000000049c": "049c", - "0x00000000000000000000000000000000000000000000000000000000000004a6": "04a6", - "0x00000000000000000000000000000000000000000000000000000000000004b0": "04b0", - "0x00000000000000000000000000000000000000000000000000000000000004ba": "04ba", - "0x00000000000000000000000000000000000000000000000000000000000004c4": "04c4", - "0x00000000000000000000000000000000000000000000000000000000000004ce": "04ce", - "0x00000000000000000000000000000000000000000000000000000000000004d8": "04d8", - "0x00000000000000000000000000000000000000000000000000000000000004e2": "04e2", - "0x00000000000000000000000000000000000000000000000000000000000004ec": "04ec", - "0x00000000000000000000000000000000000000000000000000000000000004f6": "04f6", - "0x0000000000000000000000000000000000000000000000000000000000000500": "0500", - "0x000000000000000000000000000000000000000000000000000000000000050a": "050a", - "0x0000000000000000000000000000000000000000000000000000000000000514": "0514", - "0x000000000000000000000000000000000000000000000000000000000000051e": "051e", - "0x0000000000000000000000000000000000000000000000000000000000000528": "0528", - "0x0000000000000000000000000000000000000000000000000000000000000532": "0532", - "0x000000000000000000000000000000000000000000000000000000000000053c": "053c", - "0x0000000000000000000000000000000000000000000000000000000000000546": "0546", - "0x0000000000000000000000000000000000000000000000000000000000000550": "0550", - "0x000000000000000000000000000000000000000000000000000000000000055a": "055a", - "0x0000000000000000000000000000000000000000000000000000000000000564": "0564", - "0x000000000000000000000000000000000000000000000000000000000000056e": "056e", - "0x0000000000000000000000000000000000000000000000000000000000000578": "0578", - "0x0000000000000000000000000000000000000000000000000000000000000582": "0582", - "0x000000000000000000000000000000000000000000000000000000000000058c": "058c", - "0x0000000000000000000000000000000000000000000000000000000000000596": "0596", - "0x00000000000000000000000000000000000000000000000000000000000005a0": "05a0", - "0x00000000000000000000000000000000000000000000000000000000000005aa": "05aa", - "0x00000000000000000000000000000000000000000000000000000000000005b4": "05b4", - "0x00000000000000000000000000000000000000000000000000000000000005be": "05be", - "0x00000000000000000000000000000000000000000000000000000000000005c8": "05c8", - "0x00000000000000000000000000000000000000000000000000000000000005d2": "05d2", - "0x00000000000000000000000000000000000000000000000000000000000005dc": "05dc", - "0x00000000000000000000000000000000000000000000000000000000000005e6": "05e6", - "0x00000000000000000000000000000000000000000000000000000000000005f0": "05f0", - "0x00000000000000000000000000000000000000000000000000000000000005fa": "05fa", - "0x0000000000000000000000000000000000000000000000000000000000000604": "0604", - "0x000000000000000000000000000000000000000000000000000000000000060e": "060e", - "0x0000000000000000000000000000000000000000000000000000000000000618": "0618", - "0x0000000000000000000000000000000000000000000000000000000000000622": "0622", - "0x000000000000000000000000000000000000000000000000000000000000062c": "062c", - "0x0000000000000000000000000000000000000000000000000000000000000636": "0636", - "0x0000000000000000000000000000000000000000000000000000000000000640": "0640", - "0x000000000000000000000000000000000000000000000000000000000000064a": "064a", - "0x0000000000000000000000000000000000000000000000000000000000000654": "0654", - "0x000000000000000000000000000000000000000000000000000000000000065e": "065e", - "0x0000000000000000000000000000000000000000000000000000000000000668": "0668", - "0x0000000000000000000000000000000000000000000000000000000000000672": "0672", - "0x000000000000000000000000000000000000000000000000000000000000067c": "067c", - "0x0000000000000000000000000000000000000000000000000000000000000686": "0686", - "0x0000000000000000000000000000000000000000000000000000000000000690": "0690", - "0x000000000000000000000000000000000000000000000000000000000000069a": "069a", - "0x00000000000000000000000000000000000000000000000000000000000006a4": "06a4", - "0x00000000000000000000000000000000000000000000000000000000000006ae": "06ae", - "0x00000000000000000000000000000000000000000000000000000000000006b8": "06b8", - "0x00000000000000000000000000000000000000000000000000000000000006c2": "06c2", - "0x00000000000000000000000000000000000000000000000000000000000006cc": "06cc", - "0x00000000000000000000000000000000000000000000000000000000000006d6": "06d6", - "0x00000000000000000000000000000000000000000000000000000000000006e0": "06e0", - "0x00000000000000000000000000000000000000000000000000000000000006ea": "06ea", - "0x00000000000000000000000000000000000000000000000000000000000006f4": "06f4", - "0x00000000000000000000000000000000000000000000000000000000000006fe": "06fe", - "0x0000000000000000000000000000000000000000000000000000000000000708": "0708", - "0x0000000000000000000000000000000000000000000000000000000000000712": "0712", - "0x000000000000000000000000000000000000000000000000000000000000071c": "071c", - "0x0000000000000000000000000000000000000000000000000000000000000726": "0726", - "0x0000000000000000000000000000000000000000000000000000000000000730": "0730", - "0x000000000000000000000000000000000000000000000000000000000000073a": "073a", - "0x0000000000000000000000000000000000000000000000000000000000000744": "0744", - "0x000000000000000000000000000000000000000000000000000000000000074e": "074e", - "0x0000000000000000000000000000000000000000000000000000000000000758": "0758", - "0x0000000000000000000000000000000000000000000000000000000000000762": "0762", - "0x000000000000000000000000000000000000000000000000000000000000076c": "076c", - "0x0000000000000000000000000000000000000000000000000000000000000776": "0776", - "0x0000000000000000000000000000000000000000000000000000000000000780": "0780", - "0x000000000000000000000000000000000000000000000000000000000000078a": "078a", - "0x0000000000000000000000000000000000000000000000000000000000000794": "0794", - "0x000000000000000000000000000000000000000000000000000000000000079e": "079e", - "0x00000000000000000000000000000000000000000000000000000000000007a8": "07a8", - "0x00000000000000000000000000000000000000000000000000000000000007b2": "07b2", - "0x00000000000000000000000000000000000000000000000000000000000007bc": "07bc", - "0x00000000000000000000000000000000000000000000000000000000000007c6": "07c6", - "0x00000000000000000000000000000000000000000000000000000000000007d0": "07d0", - "0x00000000000000000000000000000000000000000000000000000000000007da": "07da", - "0x00000000000000000000000000000000000000000000000000000000000007e4": "07e4", - "0x00000000000000000000000000000000000000000000000000000000000007ee": "07ee", - "0x00000000000000000000000000000000000000000000000000000000000007f8": "07f8", - "0x0000000000000000000000000000000000000000000000000000000000000802": "0802", - "0x000000000000000000000000000000000000000000000000000000000000080c": "080c", - "0x0000000000000000000000000000000000000000000000000000000000000816": "0816", - "0x0000000000000000000000000000000000000000000000000000000000000820": "0820", - "0x000000000000000000000000000000000000000000000000000000000000082a": "082a", - "0x0000000000000000000000000000000000000000000000000000000000000834": "0834", - "0x000000000000000000000000000000000000000000000000000000000000083e": "083e", - "0x0000000000000000000000000000000000000000000000000000000000000848": "0848", - "0x0000000000000000000000000000000000000000000000000000000000000852": "0852", - "0x000000000000000000000000000000000000000000000000000000000000085c": "085c", - "0x0000000000000000000000000000000000000000000000000000000000000866": "0866", - "0x0000000000000000000000000000000000000000000000000000000000000870": "0870", - "0x000000000000000000000000000000000000000000000000000000000000087a": "087a", - "0x0000000000000000000000000000000000000000000000000000000000000884": "0884", - "0x000000000000000000000000000000000000000000000000000000000000088e": "088e", - "0x0000000000000000000000000000000000000000000000000000000000000898": "0898", - "0x00000000000000000000000000000000000000000000000000000000000008a2": "08a2", - "0x00000000000000000000000000000000000000000000000000000000000008ac": "08ac", - "0x00000000000000000000000000000000000000000000000000000000000008b6": "08b6", - "0x00000000000000000000000000000000000000000000000000000000000008c0": "08c0", - "0x00000000000000000000000000000000000000000000000000000000000008ca": "08ca", - "0x00000000000000000000000000000000000000000000000000000000000008d4": "08d4", - "0x00000000000000000000000000000000000000000000000000000000000008de": "08de", - "0x00000000000000000000000000000000000000000000000000000000000008e8": "08e8", - "0x00000000000000000000000000000000000000000000000000000000000008f2": "08f2", - "0x00000000000000000000000000000000000000000000000000000000000008fc": "08fc", - "0x0000000000000000000000000000000000000000000000000000000000000906": "0906", - "0x0000000000000000000000000000000000000000000000000000000000000910": "0910", - "0x000000000000000000000000000000000000000000000000000000000000091a": "091a", - "0x0000000000000000000000000000000000000000000000000000000000000924": "0924", - "0x000000000000000000000000000000000000000000000000000000000000092e": "092e", - "0x0000000000000000000000000000000000000000000000000000000000000938": "0938", - "0x0000000000000000000000000000000000000000000000000000000000000942": "0942", - "0x000000000000000000000000000000000000000000000000000000000000094c": "094c", - "0x0000000000000000000000000000000000000000000000000000000000000956": "0956", - "0x0000000000000000000000000000000000000000000000000000000000000960": "0960", - "0x000000000000000000000000000000000000000000000000000000000000096a": "096a", - "0x0000000000000000000000000000000000000000000000000000000000000974": "0974", - "0x000000000000000000000000000000000000000000000000000000000000097e": "097e", - "0x0000000000000000000000000000000000000000000000000000000000000988": "0988", - "0x0000000000000000000000000000000000000000000000000000000000000992": "0992", - "0x000000000000000000000000000000000000000000000000000000000000099c": "099c", - "0x00000000000000000000000000000000000000000000000000000000000009a6": "09a6", - "0x00000000000000000000000000000000000000000000000000000000000009b0": "09b0", - "0x00000000000000000000000000000000000000000000000000000000000009ba": "09ba", - "0x00000000000000000000000000000000000000000000000000000000000009c4": "09c4", - "0x00000000000000000000000000000000000000000000000000000000000009ce": "09ce", - "0x00000000000000000000000000000000000000000000000000000000000009d8": "09d8", - "0x00000000000000000000000000000000000000000000000000000000000009e2": "09e2", - "0x00000000000000000000000000000000000000000000000000000000000009ec": "09ec", - "0x00000000000000000000000000000000000000000000000000000000000009f6": "09f6", - "0x0000000000000000000000000000000000000000000000000000000000000a00": "0a00", - "0x0000000000000000000000000000000000000000000000000000000000000a0a": "0a0a", - "0x0000000000000000000000000000000000000000000000000000000000000a14": "0a14", - "0x0000000000000000000000000000000000000000000000000000000000000a1e": "0a1e", - "0x0000000000000000000000000000000000000000000000000000000000000a28": "0a28", - "0x0000000000000000000000000000000000000000000000000000000000000a32": "0a32", - "0x0000000000000000000000000000000000000000000000000000000000000a3c": "0a3c", - "0x0000000000000000000000000000000000000000000000000000000000000a46": "0a46", - "0x0000000000000000000000000000000000000000000000000000000000000a50": "0a50", - "0x0000000000000000000000000000000000000000000000000000000000000a5a": "0a5a", - "0x0000000000000000000000000000000000000000000000000000000000000a64": "0a64", - "0x0000000000000000000000000000000000000000000000000000000000000a6e": "0a6e", - "0x0000000000000000000000000000000000000000000000000000000000000a78": "0a78", - "0x0000000000000000000000000000000000000000000000000000000000000a82": "0a82", - "0x0000000000000000000000000000000000000000000000000000000000000a8c": "0a8c", - "0x0000000000000000000000000000000000000000000000000000000000000a96": "0a96", - "0x0000000000000000000000000000000000000000000000000000000000000aa0": "0aa0", - "0x0000000000000000000000000000000000000000000000000000000000000aaa": "0aaa", - "0x0000000000000000000000000000000000000000000000000000000000000ab4": "0ab4", - "0x0000000000000000000000000000000000000000000000000000000000000abe": "0abe", - "0x0000000000000000000000000000000000000000000000000000000000000ac8": "0ac8", - "0x0000000000000000000000000000000000000000000000000000000000000ad2": "0ad2", - "0x0000000000000000000000000000000000000000000000000000000000000adc": "0adc", - "0x0000000000000000000000000000000000000000000000000000000000000ae6": "0ae6", - "0x0000000000000000000000000000000000000000000000000000000000000af0": "0af0", - "0x0000000000000000000000000000000000000000000000000000000000000afa": "0afa", - "0x0000000000000000000000000000000000000000000000000000000000000b04": "0b04", - "0x0000000000000000000000000000000000000000000000000000000000000b0e": "0b0e", - "0x0000000000000000000000000000000000000000000000000000000000000b18": "0b18", - "0x0000000000000000000000000000000000000000000000000000000000000b22": "0b22", - "0x0000000000000000000000000000000000000000000000000000000000000b2c": "0b2c", - "0x0000000000000000000000000000000000000000000000000000000000000b36": "0b36", - "0x0000000000000000000000000000000000000000000000000000000000000b40": "0b40", - "0x0000000000000000000000000000000000000000000000000000000000000b4a": "0b4a", - "0x0000000000000000000000000000000000000000000000000000000000000b54": "0b54", - "0x0000000000000000000000000000000000000000000000000000000000000b5e": "0b5e", - "0x0000000000000000000000000000000000000000000000000000000000000b68": "0b68", - "0x0000000000000000000000000000000000000000000000000000000000000b72": "0b72", - "0x0000000000000000000000000000000000000000000000000000000000000b7c": "0b7c", - "0x0000000000000000000000000000000000000000000000000000000000000b86": "0b86", - "0x0000000000000000000000000000000000000000000000000000000000000b90": "0b90", - "0x0000000000000000000000000000000000000000000000000000000000000b9a": "0b9a", - "0x0000000000000000000000000000000000000000000000000000000000000ba4": "0ba4", - "0x0000000000000000000000000000000000000000000000000000000000000bae": "0bae", - "0x0000000000000000000000000000000000000000000000000000000000000bb8": "0bb8", - "0x0000000000000000000000000000000000000000000000000000000000000bc2": "0bc2", - "0x0000000000000000000000000000000000000000000000000000000000000bcc": "0bcc", - "0x0000000000000000000000000000000000000000000000000000000000000bd6": "0bd6", - "0x0000000000000000000000000000000000000000000000000000000000000be0": "0be0", - "0x0000000000000000000000000000000000000000000000000000000000000bea": "0bea", - "0x0000000000000000000000000000000000000000000000000000000000000bf4": "0bf4", - "0x0000000000000000000000000000000000000000000000000000000000000bfe": "0bfe", - "0x0000000000000000000000000000000000000000000000000000000000000c08": "0c08", - "0x0000000000000000000000000000000000000000000000000000000000000c12": "0c12", - "0x0000000000000000000000000000000000000000000000000000000000000c1c": "0c1c", - "0x0000000000000000000000000000000000000000000000000000000000000c26": "0c26", - "0x0000000000000000000000000000000000000000000000000000000000000c30": "0c30", - "0x0000000000000000000000000000000000000000000000000000000000000c3a": "0c3a", - "0x0000000000000000000000000000000000000000000000000000000000000c44": "0c44", - "0x0000000000000000000000000000000000000000000000000000000000000c4e": "0c4e", - "0x0000000000000000000000000000000000000000000000000000000000000c58": "0c58", - "0x0000000000000000000000000000000000000000000000000000000000000c62": "0c62", - "0x0000000000000000000000000000000000000000000000000000000000000c6c": "0c6c", - "0x0000000000000000000000000000000000000000000000000000000000000c76": "0c76", - "0x0000000000000000000000000000000000000000000000000000000000000c80": "0c80", - "0x0000000000000000000000000000000000000000000000000000000000000c8a": "0c8a", - "0x0000000000000000000000000000000000000000000000000000000000000c94": "0c94", - "0x0000000000000000000000000000000000000000000000000000000000000c9e": "0c9e", - "0x0000000000000000000000000000000000000000000000000000000000000ca8": "0ca8", - "0x0000000000000000000000000000000000000000000000000000000000000cb2": "0cb2", - "0x0000000000000000000000000000000000000000000000000000000000000cbc": "0cbc", - "0x0000000000000000000000000000000000000000000000000000000000000cc6": "0cc6", - "0x0000000000000000000000000000000000000000000000000000000000000cd0": "0cd0", - "0x0000000000000000000000000000000000000000000000000000000000000cda": "0cda", - "0x0000000000000000000000000000000000000000000000000000000000000ce4": "0ce4", - "0x0000000000000000000000000000000000000000000000000000000000000cee": "0cee", - "0x0000000000000000000000000000000000000000000000000000000000000cf8": "0cf8", - "0x0000000000000000000000000000000000000000000000000000000000000d02": "0d02", - "0x0000000000000000000000000000000000000000000000000000000000000d0c": "0d0c", - "0x0000000000000000000000000000000000000000000000000000000000000d16": "0d16", - "0x0000000000000000000000000000000000000000000000000000000000000d20": "0d20", - "0x0000000000000000000000000000000000000000000000000000000000000d2a": "0d2a", - "0x0000000000000000000000000000000000000000000000000000000000000d34": "0d34", - "0x0000000000000000000000000000000000000000000000000000000000000d3e": "0d3e", - "0x0000000000000000000000000000000000000000000000000000000000000d48": "0d48", - "0x0000000000000000000000000000000000000000000000000000000000000d52": "0d52", - "0x0000000000000000000000000000000000000000000000000000000000000d5c": "0d5c", - "0x0000000000000000000000000000000000000000000000000000000000000d66": "0d66", - "0x0000000000000000000000000000000000000000000000000000000000000d70": "0d70", - "0x0000000000000000000000000000000000000000000000000000000000000d7a": "0d7a", - "0x0000000000000000000000000000000000000000000000000000000000000d84": "0d84", - "0x0000000000000000000000000000000000000000000000000000000000000d8e": "0d8e", - "0x0000000000000000000000000000000000000000000000000000000000000d98": "0d98", - "0x0000000000000000000000000000000000000000000000000000000000000da2": "0da2", - "0x0000000000000000000000000000000000000000000000000000000000000dac": "0dac", - "0x0000000000000000000000000000000000000000000000000000000000000db6": "0db6", - "0x0000000000000000000000000000000000000000000000000000000000000dc0": "0dc0", - "0x0000000000000000000000000000000000000000000000000000000000000dca": "0dca", - "0x0000000000000000000000000000000000000000000000000000000000000dd4": "0dd4", - "0x0000000000000000000000000000000000000000000000000000000000000dde": "0dde", - "0x0000000000000000000000000000000000000000000000000000000000000de8": "0de8", - "0x0000000000000000000000000000000000000000000000000000000000000df2": "0df2", - "0x0000000000000000000000000000000000000000000000000000000000000dfc": "0dfc", - "0x0000000000000000000000000000000000000000000000000000000000000e06": "0e06", - "0x0000000000000000000000000000000000000000000000000000000000000e10": "0e10", - "0x0000000000000000000000000000000000000000000000000000000000000e1a": "0e1a", - "0x0000000000000000000000000000000000000000000000000000000000000e24": "0e24", - "0x0000000000000000000000000000000000000000000000000000000000000e2e": "0e2e", - "0x0000000000000000000000000000000000000000000000000000000000000e38": "0e38", - "0x0000000000000000000000000000000000000000000000000000000000000e42": "0e42", - "0x0000000000000000000000000000000000000000000000000000000000000e4c": "0e4c", - "0x0000000000000000000000000000000000000000000000000000000000000e56": "0e56", - "0x0000000000000000000000000000000000000000000000000000000000000e60": "0e60", - "0x0000000000000000000000000000000000000000000000000000000000000e6a": "0e6a", - "0x0000000000000000000000000000000000000000000000000000000000000e74": "0e74", - "0x0000000000000000000000000000000000000000000000000000000000000e7e": "0e7e", - "0x0000000000000000000000000000000000000000000000000000000000000e88": "0e88", - "0x0000000000000000000000000000000000000000000000000000000000000e92": "0e92", - "0x0000000000000000000000000000000000000000000000000000000000000e9c": "0e9c", - "0x0000000000000000000000000000000000000000000000000000000000000ea6": "0ea6", - "0x0000000000000000000000000000000000000000000000000000000000000eb0": "0eb0", - "0x0000000000000000000000000000000000000000000000000000000000000eba": "0eba", - "0x0000000000000000000000000000000000000000000000000000000000000ec4": "0ec4", - "0x0000000000000000000000000000000000000000000000000000000000000ece": "0ece", - "0x0000000000000000000000000000000000000000000000000000000000000ed8": "0ed8", - "0x0000000000000000000000000000000000000000000000000000000000000ee2": "0ee2", - "0x0000000000000000000000000000000000000000000000000000000000000eec": "0eec", - "0x0000000000000000000000000000000000000000000000000000000000000ef6": "0ef6", - "0x0000000000000000000000000000000000000000000000000000000000000f00": "0f00", - "0x0000000000000000000000000000000000000000000000000000000000000f0a": "0f0a", - "0x0000000000000000000000000000000000000000000000000000000000000f14": "0f14", - "0x0000000000000000000000000000000000000000000000000000000000000f1e": "0f1e", - "0x0000000000000000000000000000000000000000000000000000000000000f28": "0f28", - "0x0000000000000000000000000000000000000000000000000000000000000f32": "0f32", - "0x0000000000000000000000000000000000000000000000000000000000000f3c": "0f3c", - "0x0000000000000000000000000000000000000000000000000000000000000f46": "0f46", - "0x0000000000000000000000000000000000000000000000000000000000000f50": "0f50", - "0x0000000000000000000000000000000000000000000000000000000000000f5a": "0f5a", - "0x0000000000000000000000000000000000000000000000000000000000000f64": "0f64", - "0x0000000000000000000000000000000000000000000000000000000000000f6e": "0f6e", - "0x0000000000000000000000000000000000000000000000000000000000000f78": "0f78", - "0x0000000000000000000000000000000000000000000000000000000000000f82": "0f82", - "0x0000000000000000000000000000000000000000000000000000000000000f8c": "0f8c", - "0x0000000000000000000000000000000000000000000000000000000000000f96": "0f96", - "0x0000000000000000000000000000000000000000000000000000000000000fa0": "0fa0", - "0x0000000000000000000000000000000000000000000000000000000000000faa": "0faa", - "0x0000000000000000000000000000000000000000000000000000000000000fb4": "0fb4", - "0x0000000000000000000000000000000000000000000000000000000000000fbe": "0fbe", - "0x0000000000000000000000000000000000000000000000000000000000000fc8": "0fc8", - "0x0000000000000000000000000000000000000000000000000000000000000fd2": "0fd2", - "0x0000000000000000000000000000000000000000000000000000000000000fdc": "0fdc", - "0x0000000000000000000000000000000000000000000000000000000000000fe6": "0fe6", - "0x0000000000000000000000000000000000000000000000000000000000000ff0": "0ff0", - "0x0000000000000000000000000000000000000000000000000000000000000ffa": "0ffa", - "0x0000000000000000000000000000000000000000000000000000000000001004": "1004", - "0x000000000000000000000000000000000000000000000000000000000000100e": "100e", - "0x0000000000000000000000000000000000000000000000000000000000001018": "1018", - "0x0000000000000000000000000000000000000000000000000000000000001022": "1022", - "0x000000000000000000000000000000000000000000000000000000000000102c": "102c", - "0x0000000000000000000000000000000000000000000000000000000000001036": "1036", - "0x0000000000000000000000000000000000000000000000000000000000001040": "1040", - "0x000000000000000000000000000000000000000000000000000000000000104a": "104a", - "0x0000000000000000000000000000000000000000000000000000000000001054": "1054", - "0x000000000000000000000000000000000000000000000000000000000000105e": "105e", - "0x0000000000000000000000000000000000000000000000000000000000001068": "1068", - "0x0000000000000000000000000000000000000000000000000000000000001072": "1072", - "0x000000000000000000000000000000000000000000000000000000000000107c": "107c", - "0x0000000000000000000000000000000000000000000000000000000000001086": "1086", - "0x0000000000000000000000000000000000000000000000000000000000001090": "1090", - "0x000000000000000000000000000000000000000000000000000000000000109a": "109a", - "0x00000000000000000000000000000000000000000000000000000000000010a4": "10a4", - "0x00000000000000000000000000000000000000000000000000000000000010ae": "10ae", - "0x00000000000000000000000000000000000000000000000000000000000010b8": "10b8", - "0x00000000000000000000000000000000000000000000000000000000000010c2": "10c2", - "0x00000000000000000000000000000000000000000000000000000000000010cc": "10cc", - "0x00000000000000000000000000000000000000000000000000000000000010d6": "10d6", - "0x00000000000000000000000000000000000000000000000000000000000010e0": "10e0", - "0x00000000000000000000000000000000000000000000000000000000000010ea": "10ea", - "0x00000000000000000000000000000000000000000000000000000000000010f4": "10f4", - "0x00000000000000000000000000000000000000000000000000000000000010fe": "10fe", - "0x0000000000000000000000000000000000000000000000000000000000001108": "1108", - "0x0000000000000000000000000000000000000000000000000000000000001112": "1112", - "0x000000000000000000000000000000000000000000000000000000000000111c": "111c", - "0x0000000000000000000000000000000000000000000000000000000000001126": "1126", - "0x0000000000000000000000000000000000000000000000000000000000001130": "1130", - "0x000000000000000000000000000000000000000000000000000000000000113a": "113a", - "0x0000000000000000000000000000000000000000000000000000000000001144": "1144", - "0x000000000000000000000000000000000000000000000000000000000000114e": "114e", - "0x0000000000000000000000000000000000000000000000000000000000001158": "1158", - "0x0000000000000000000000000000000000000000000000000000000000001162": "1162", - "0x000000000000000000000000000000000000000000000000000000000000116c": "116c", - "0x0000000000000000000000000000000000000000000000000000000000001176": "1176", - "0x0000000000000000000000000000000000000000000000000000000000001180": "1180", - "0x000000000000000000000000000000000000000000000000000000000000118a": "118a", - "0x0000000000000000000000000000000000000000000000000000000000001194": "1194", - "0x000000000000000000000000000000000000000000000000000000000000119e": "119e", - "0x00000000000000000000000000000000000000000000000000000000000011a8": "11a8", - "0x00000000000000000000000000000000000000000000000000000000000011b2": "11b2", - "0x00000000000000000000000000000000000000000000000000000000000011bc": "11bc", - "0x00000000000000000000000000000000000000000000000000000000000011c6": "11c6", - "0x00000000000000000000000000000000000000000000000000000000000011d0": "11d0", - "0x00000000000000000000000000000000000000000000000000000000000011da": "11da", - "0x00000000000000000000000000000000000000000000000000000000000011e4": "11e4", - "0x00000000000000000000000000000000000000000000000000000000000011ee": "11ee", - "0x00000000000000000000000000000000000000000000000000000000000011f8": "11f8", - "0x0000000000000000000000000000000000000000000000000000000000001202": "1202", - "0x000000000000000000000000000000000000000000000000000000000000120c": "120c", - "0x0000000000000000000000000000000000000000000000000000000000001216": "1216", - "0x0000000000000000000000000000000000000000000000000000000000001220": "1220", - "0x000000000000000000000000000000000000000000000000000000000000122a": "122a", - "0x0000000000000000000000000000000000000000000000000000000000001234": "1234", - "0x000000000000000000000000000000000000000000000000000000000000123e": "123e", - "0x0000000000000000000000000000000000000000000000000000000000001248": "1248", - "0x0000000000000000000000000000000000000000000000000000000000001252": "1252", - "0x000000000000000000000000000000000000000000000000000000000000125c": "125c", - "0x0000000000000000000000000000000000000000000000000000000000001266": "1266", - "0x0000000000000000000000000000000000000000000000000000000000001270": "1270", - "0x000000000000000000000000000000000000000000000000000000000000127a": "127a", - "0x0000000000000000000000000000000000000000000000000000000000001284": "1284", - "0x000000000000000000000000000000000000000000000000000000000000128e": "128e", - "0x0000000000000000000000000000000000000000000000000000000000001298": "1298", - "0x00000000000000000000000000000000000000000000000000000000000012a2": "12a2", - "0x00000000000000000000000000000000000000000000000000000000000012ac": "12ac", - "0x00000000000000000000000000000000000000000000000000000000000012b6": "12b6", - "0x00000000000000000000000000000000000000000000000000000000000012c0": "12c0", - "0x00000000000000000000000000000000000000000000000000000000000012ca": "12ca", - "0x00000000000000000000000000000000000000000000000000000000000012d4": "12d4", - "0x00000000000000000000000000000000000000000000000000000000000012de": "12de", - "0x00000000000000000000000000000000000000000000000000000000000012e8": "12e8", - "0x00000000000000000000000000000000000000000000000000000000000012f2": "12f2", - "0x00000000000000000000000000000000000000000000000000000000000012fc": "12fc", - "0x0000000000000000000000000000000000000000000000000000000000001306": "1306", - "0x0000000000000000000000000000000000000000000000000000000000001310": "1310", - "0x000000000000000000000000000000000000000000000000000000000000131a": "131a", - "0x0000000000000000000000000000000000000000000000000000000000001324": "1324", - "0x000000000000000000000000000000000000000000000000000000000000132e": "132e", - "0x0000000000000000000000000000000000000000000000000000000000001338": "1338", - "0x0000000000000000000000000000000000000000000000000000000000001342": "1342", - "0x000000000000000000000000000000000000000000000000000000000000134c": "134c", - "0x0000000000000000000000000000000000000000000000000000000000001356": "1356", - "0x0000000000000000000000000000000000000000000000000000000000001360": "1360", - "0x000000000000000000000000000000000000000000000000000000000000136a": "136a", - "0x0000000000000000000000000000000000000000000000000000000000001374": "1374", - "0x000000000000000000000000000000000000000000000000000000000000137e": "137e", - "0x0000000000000000000000000000000000000000000000000000000000001388": "1388", - "0x0000000000000000000000000000000000000000000000000000000000002347": "83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd", - "0x0000000000000000000000000000000000000000000000000000000000002351": "2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e", - "0x000000000000000000000000000000000000000000000000000000000000235b": "756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67", - "0x0000000000000000000000000000000000000000000000000000000000002365": "4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78", - "0x000000000000000000000000000000000000000000000000000000000000236f": "d0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5", - "0x0000000000000000000000000000000000000000000000000000000000002379": "60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089", - "0x0000000000000000000000000000000000000000000000000000000000002383": "6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca", - "0x000000000000000000000000000000000000000000000000000000000000238d": "36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8", - "0x0000000000000000000000000000000000000000000000000000000000002397": "c13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94", - "0x00000000000000000000000000000000000000000000000000000000000023a1": "8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b", - "0x00000000000000000000000000000000000000000000000000000000000023ab": "e958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629", - "0x00000000000000000000000000000000000000000000000000000000000023b5": "3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e", - "0x00000000000000000000000000000000000000000000000000000000000023bf": "346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad", - "0x00000000000000000000000000000000000000000000000000000000000023c9": "e62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546", - "0x00000000000000000000000000000000000000000000000000000000000023d3": "ffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d", - "0x00000000000000000000000000000000000000000000000000000000000023dd": "23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427", - "0x00000000000000000000000000000000000000000000000000000000000023e7": "47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd", - "0x00000000000000000000000000000000000000000000000000000000000023f1": "6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe", - "0x00000000000000000000000000000000000000000000000000000000000023fb": "efc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547", - "0x0000000000000000000000000000000000000000000000000000000000002405": "3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f", - "0x000000000000000000000000000000000000000000000000000000000000240f": "63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80", - "0x0000000000000000000000000000000000000000000000000000000000002419": "67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c", - "0x0000000000000000000000000000000000000000000000000000000000002423": "7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885", - "0x000000000000000000000000000000000000000000000000000000000000242d": "c8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f", - "0x0000000000000000000000000000000000000000000000000000000000002437": "e40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91", - "0x0000000000000000000000000000000000000000000000000000000000002441": "e82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470", - "0x000000000000000000000000000000000000000000000000000000000000244b": "84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d", - "0x0000000000000000000000000000000000000000000000000000000000002455": "e9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c", - "0x000000000000000000000000000000000000000000000000000000000000245f": "430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4", - "0x0000000000000000000000000000000000000000000000000000000000002469": "f7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf", - "0x0000000000000000000000000000000000000000000000000000000000002473": "e134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb", - "0x000000000000000000000000000000000000000000000000000000000000247d": "9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613", - "0x0000000000000000000000000000000000000000000000000000000000002487": "79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978", - "0x0000000000000000000000000000000000000000000000000000000000002491": "d908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611", - "0x000000000000000000000000000000000000000000000000000000000000249b": "e0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3", - "0x00000000000000000000000000000000000000000000000000000000000024a5": "2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae", - "0x00000000000000000000000000000000000000000000000000000000000024af": "523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc", - "0x00000000000000000000000000000000000000000000000000000000000024b9": "be3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7", - "0x00000000000000000000000000000000000000000000000000000000000024c3": "2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039", - "0x00000000000000000000000000000000000000000000000000000000000024cd": "7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc", - "0x00000000000000000000000000000000000000000000000000000000000024d7": "4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256", - "0x00000000000000000000000000000000000000000000000000000000000024e1": "c5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844", - "0x00000000000000000000000000000000000000000000000000000000000024eb": "0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b", - "0x00000000000000000000000000000000000000000000000000000000000024f5": "7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5", - "0x00000000000000000000000000000000000000000000000000000000000024ff": "2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059", - "0x0000000000000000000000000000000000000000000000000000000000002509": "d4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f", - "0x0000000000000000000000000000000000000000000000000000000000002513": "e651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf", - "0x000000000000000000000000000000000000000000000000000000000000251d": "5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6", - "0x0000000000000000000000000000000000000000000000000000000000002527": "57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa", - "0x0000000000000000000000000000000000000000000000000000000000002531": "217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13", - "0x000000000000000000000000000000000000000000000000000000000000253b": "14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b", - "0x0000000000000000000000000000000000000000000000000000000000002545": "e736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63", - "0x000000000000000000000000000000000000000000000000000000000000254f": "7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e", - "0x0000000000000000000000000000000000000000000000000000000000002559": "28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074", - "0x0000000000000000000000000000000000000000000000000000000000002563": "6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6", - "0x000000000000000000000000000000000000000000000000000000000000256d": "d5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb", - "0x0000000000000000000000000000000000000000000000000000000000002577": "20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b", - "0x0000000000000000000000000000000000000000000000000000000000002581": "91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131", - "0x000000000000000000000000000000000000000000000000000000000000258b": "743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774", - "0x0000000000000000000000000000000000000000000000000000000000002595": "cdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839", - "0x000000000000000000000000000000000000000000000000000000000000259f": "cc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1", - "0x00000000000000000000000000000000000000000000000000000000000025a9": "f67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb", - "0x00000000000000000000000000000000000000000000000000000000000025b3": "e20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579", - "0x00000000000000000000000000000000000000000000000000000000000025bd": "f982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb", - "0x00000000000000000000000000000000000000000000000000000000000025c7": "230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6", - "0x00000000000000000000000000000000000000000000000000000000000025d1": "b7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4", - "0x00000000000000000000000000000000000000000000000000000000000025db": "31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3", - "0x00000000000000000000000000000000000000000000000000000000000025e5": "ded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d", - "0x00000000000000000000000000000000000000000000000000000000000025ef": "a0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6", - "0x00000000000000000000000000000000000000000000000000000000000025f9": "1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f", - "0x0000000000000000000000000000000000000000000000000000000000002603": "34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6", - "0x000000000000000000000000000000000000000000000000000000000000260d": "774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b", - "0x0000000000000000000000000000000000000000000000000000000000002617": "d616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09", - "0x0000000000000000000000000000000000000000000000000000000000002621": "cdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19", - "0x000000000000000000000000000000000000000000000000000000000000262b": "ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b", - "0x0000000000000000000000000000000000000000000000000000000000002635": "cb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af", - "0x000000000000000000000000000000000000000000000000000000000000263f": "6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2", - "0x0000000000000000000000000000000000000000000000000000000000002649": "2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf", - "0x0000000000000000000000000000000000000000000000000000000000002653": "08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500", - "0x000000000000000000000000000000000000000000000000000000000000265d": "e437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69", - "0x0000000000000000000000000000000000000000000000000000000000002667": "89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080", - "0x0000000000000000000000000000000000000000000000000000000000002671": "b15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b", - "0x000000000000000000000000000000000000000000000000000000000000267b": "ad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2", - "0x0000000000000000000000000000000000000000000000000000000000002685": "9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f", - "0x000000000000000000000000000000000000000000000000000000000000268f": "bf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac", - "0x0000000000000000000000000000000000000000000000000000000000002699": "bb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f", - "0x00000000000000000000000000000000000000000000000000000000000026a3": "6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0", - "0x00000000000000000000000000000000000000000000000000000000000026ad": "4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed", - "0x00000000000000000000000000000000000000000000000000000000000026b7": "268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a", - "0x00000000000000000000000000000000000000000000000000000000000026c1": "7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562", - "0x00000000000000000000000000000000000000000000000000000000000026cb": "d59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3", - "0x00000000000000000000000000000000000000000000000000000000000026d5": "551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57", - "0x00000000000000000000000000000000000000000000000000000000000026df": "c1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978", - "0x00000000000000000000000000000000000000000000000000000000000026e9": "9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205", - "0x00000000000000000000000000000000000000000000000000000000000026f3": "a7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886", - "0x00000000000000000000000000000000000000000000000000000000000026fd": "6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165", - "0x0000000000000000000000000000000000000000000000000000000000002707": "8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b", - "0x0000000000000000000000000000000000000000000000000000000000002711": "562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801", - "0x000000000000000000000000000000000000000000000000000000000000271b": "d19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb", - "0x0000000000000000000000000000000000000000000000000000000000002725": "f087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860", - "0x000000000000000000000000000000000000000000000000000000000000272f": "f7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6", - "0x0000000000000000000000000000000000000000000000000000000000002739": "77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435", - "0x0000000000000000000000000000000000000000000000000000000000002743": "e3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c", - "0x000000000000000000000000000000000000000000000000000000000000274d": "c893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194", - "0x0000000000000000000000000000000000000000000000000000000000002757": "39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d", - "0x0000000000000000000000000000000000000000000000000000000000002761": "72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb", - "0x000000000000000000000000000000000000000000000000000000000000276b": "178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03", - "0x0000000000000000000000000000000000000000000000000000000000002775": "f7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946", - "0x000000000000000000000000000000000000000000000000000000000000277f": "16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54", - "0x0000000000000000000000000000000000000000000000000000000000002789": "0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90", - "0x0000000000000000000000000000000000000000000000000000000000002793": "7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2", - "0x000000000000000000000000000000000000000000000000000000000000279d": "6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6", - "0x00000000000000000000000000000000000000000000000000000000000027a7": "91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae", - "0x00000000000000000000000000000000000000000000000000000000000027b1": "a1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3", - "0x00000000000000000000000000000000000000000000000000000000000027bb": "8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf", - "0x00000000000000000000000000000000000000000000000000000000000027c5": "cc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f", - "0x00000000000000000000000000000000000000000000000000000000000027cf": "b0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de", - "0x00000000000000000000000000000000000000000000000000000000000027d9": "92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3", - "0x00000000000000000000000000000000000000000000000000000000000027e3": "f6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53", - "0x00000000000000000000000000000000000000000000000000000000000027ed": "ea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67", - "0x00000000000000000000000000000000000000000000000000000000000027f7": "543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4", - "0x0000000000000000000000000000000000000000000000000000000000002801": "095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2", - "0x000000000000000000000000000000000000000000000000000000000000280b": "144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f", - "0x0000000000000000000000000000000000000000000000000000000000002815": "7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c", - "0x000000000000000000000000000000000000000000000000000000000000281f": "9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4", - "0x0000000000000000000000000000000000000000000000000000000000002829": "fc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9", - "0x0000000000000000000000000000000000000000000000000000000000002833": "5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca", - "0x000000000000000000000000000000000000000000000000000000000000283d": "5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed", - "0x0000000000000000000000000000000000000000000000000000000000002847": "b40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2", - "0x0000000000000000000000000000000000000000000000000000000000002851": "70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7", - "0x000000000000000000000000000000000000000000000000000000000000285b": "43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5", - "0x0000000000000000000000000000000000000000000000000000000000002865": "b50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4", - "0x000000000000000000000000000000000000000000000000000000000000286f": "c14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd", - "0x0000000000000000000000000000000000000000000000000000000000002879": "86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2", - "0x0000000000000000000000000000000000000000000000000000000000002883": "0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5", - "0x000000000000000000000000000000000000000000000000000000000000288d": "a4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6", - "0x0000000000000000000000000000000000000000000000000000000000002897": "2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d", - "0x00000000000000000000000000000000000000000000000000000000000028a1": "fc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b", - "0x00000000000000000000000000000000000000000000000000000000000028ab": "949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35", - "0x00000000000000000000000000000000000000000000000000000000000028b5": "289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e", - "0x00000000000000000000000000000000000000000000000000000000000028bf": "bfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a", - "0x00000000000000000000000000000000000000000000000000000000000028c9": "7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150", - "0x00000000000000000000000000000000000000000000000000000000000028d3": "992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db", - "0x00000000000000000000000000000000000000000000000000000000000028dd": "da6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa", - "0x00000000000000000000000000000000000000000000000000000000000028e7": "65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f", - "0x00000000000000000000000000000000000000000000000000000000000028f1": "cc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6", - "0x00000000000000000000000000000000000000000000000000000000000028fb": "096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290", - "0x0000000000000000000000000000000000000000000000000000000000002905": "0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2", - "0x000000000000000000000000000000000000000000000000000000000000290f": "9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522", - "0x0000000000000000000000000000000000000000000000000000000000002919": "2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26", - "0x0000000000000000000000000000000000000000000000000000000000002923": "2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea", - "0x000000000000000000000000000000000000000000000000000000000000292d": "1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c", - "0x0000000000000000000000000000000000000000000000000000000000002937": "18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598", - "0x0000000000000000000000000000000000000000000000000000000000002941": "700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5", - "0x000000000000000000000000000000000000000000000000000000000000294b": "cad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312", - "0x0000000000000000000000000000000000000000000000000000000000002955": "a85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f", - "0x000000000000000000000000000000000000000000000000000000000000295f": "040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec", - "0x0000000000000000000000000000000000000000000000000000000000002969": "49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04", - "0x0000000000000000000000000000000000000000000000000000000000002973": "810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20", - "0x000000000000000000000000000000000000000000000000000000000000297d": "9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78", - "0x0000000000000000000000000000000000000000000000000000000000002987": "f68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742", - "0x0000000000000000000000000000000000000000000000000000000000002991": "9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4", - "0x000000000000000000000000000000000000000000000000000000000000299b": "d0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097", - "0x00000000000000000000000000000000000000000000000000000000000029a5": "43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe", - "0x00000000000000000000000000000000000000000000000000000000000029af": "54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd", - "0x00000000000000000000000000000000000000000000000000000000000029b9": "9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8", - "0x00000000000000000000000000000000000000000000000000000000000029c3": "4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34", - "0x00000000000000000000000000000000000000000000000000000000000029cd": "215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc", - "0x00000000000000000000000000000000000000000000000000000000000029d7": "d17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e", - "0x00000000000000000000000000000000000000000000000000000000000029e1": "875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637", - "0x00000000000000000000000000000000000000000000000000000000000029eb": "6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f", - "0x00000000000000000000000000000000000000000000000000000000000029f5": "f11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf", - "0x00000000000000000000000000000000000000000000000000000000000029ff": "bbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc", - "0x0000000000000000000000000000000000000000000000000000000000002a09": "71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e", - "0x0000000000000000000000000000000000000000000000000000000000002a13": "b90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea", - "0x0000000000000000000000000000000000000000000000000000000000002a1d": "4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4", - "0x0000000000000000000000000000000000000000000000000000000000002a27": "afb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282", - "0x0000000000000000000000000000000000000000000000000000000000002a31": "d73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95", - "0x0000000000000000000000000000000000000000000000000000000000002a3b": "c26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1", - "0x0000000000000000000000000000000000000000000000000000000000002a45": "fb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d", - "0x0000000000000000000000000000000000000000000000000000000000002a4f": "d08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98", - "0x0000000000000000000000000000000000000000000000000000000000002a59": "df979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd", - "0x0000000000000000000000000000000000000000000000000000000000002a63": "15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba", - "0x0000000000000000000000000000000000000000000000000000000000002a6d": "fd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c", - "0x0000000000000000000000000000000000000000000000000000000000002a77": "edad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572", - "0x0000000000000000000000000000000000000000000000000000000000002a81": "c2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c", - "0x0000000000000000000000000000000000000000000000000000000000002a8b": "5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446", - "0x0000000000000000000000000000000000000000000000000000000000002a95": "0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d", - "0x0000000000000000000000000000000000000000000000000000000000002a9f": "14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961", - "0x0000000000000000000000000000000000000000000000000000000000002aa9": "490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79", - "0x0000000000000000000000000000000000000000000000000000000000002ab3": "4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a", - "0x0000000000000000000000000000000000000000000000000000000000002abd": "133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2", - "0x0000000000000000000000000000000000000000000000000000000000002ac7": "a73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972", - "0x0000000000000000000000000000000000000000000000000000000000002ad1": "9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c", - "0x0000000000000000000000000000000000000000000000000000000000002adb": "ec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8", - "0x0000000000000000000000000000000000000000000000000000000000002ae5": "3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16", - "0x0000000000000000000000000000000000000000000000000000000000002aef": "ccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca", - "0x0000000000000000000000000000000000000000000000000000000000002af9": "74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af", - "0x0000000000000000000000000000000000000000000000000000000000002b03": "f6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7", - "0x0000000000000000000000000000000000000000000000000000000000002b0d": "7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9", - "0x0000000000000000000000000000000000000000000000000000000000002b17": "1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918", - "0x0000000000000000000000000000000000000000000000000000000000002b21": "c564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5", - "0x0000000000000000000000000000000000000000000000000000000000002b2b": "9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e", - "0x0000000000000000000000000000000000000000000000000000000000002b35": "6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045", - "0x0000000000000000000000000000000000000000000000000000000000002b3f": "417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a", - "0x0000000000000000000000000000000000000000000000000000000000002b49": "e910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23", - "0x0000000000000000000000000000000000000000000000000000000000002b53": "8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692", - "0x0000000000000000000000000000000000000000000000000000000000002b5d": "3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1", - "0x0000000000000000000000000000000000000000000000000000000000002b67": "07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637", - "0x0000000000000000000000000000000000000000000000000000000000002b71": "f4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef", - "0x0000000000000000000000000000000000000000000000000000000000002b7b": "5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4", - "0x0000000000000000000000000000000000000000000000000000000000002b85": "e98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b", - "0x0000000000000000000000000000000000000000000000000000000000002b8f": "d62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe", - "0x0000000000000000000000000000000000000000000000000000000000002b99": "4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098", - "0x0000000000000000000000000000000000000000000000000000000000002ba3": "36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a", - "0x0000000000000000000000000000000000000000000000000000000000002bad": "164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a", - "0x0000000000000000000000000000000000000000000000000000000000002bb7": "aa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010", - "0x0000000000000000000000000000000000000000000000000000000000002bc1": "99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5", - "0x0000000000000000000000000000000000000000000000000000000000002bcb": "30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb", - "0x0000000000000000000000000000000000000000000000000000000000002bd5": "a804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7", - "0x0000000000000000000000000000000000000000000000000000000000002bdf": "c554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64", - "0x0000000000000000000000000000000000000000000000000000000000002be9": "c89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203", - "0x0000000000000000000000000000000000000000000000000000000000002bf3": "44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6", - "0x0000000000000000000000000000000000000000000000000000000000002bfd": "ae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8", - "0x0000000000000000000000000000000000000000000000000000000000002c07": "3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1", - "0x0000000000000000000000000000000000000000000000000000000000002c11": "b52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b", - "0x0000000000000000000000000000000000000000000000000000000000002c1b": "ff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f", - "0x0000000000000000000000000000000000000000000000000000000000002c25": "70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52", - "0x0000000000000000000000000000000000000000000000000000000000002c2f": "e3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71", - "0x0000000000000000000000000000000000000000000000000000000000002c39": "2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176", - "0x0000000000000000000000000000000000000000000000000000000000002c43": "06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720", - "0x0000000000000000000000000000000000000000000000000000000000002c4d": "ebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb", - "0x0000000000000000000000000000000000000000000000000000000000002c57": "738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf", - "0x0000000000000000000000000000000000000000000000000000000000002c61": "ae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a", - "0x0000000000000000000000000000000000000000000000000000000000002c6b": "69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97", - "0x0000000000000000000000000000000000000000000000000000000000002c75": "4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4", - "0x0000000000000000000000000000000000000000000000000000000000002c7f": "d3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3", - "0x0000000000000000000000000000000000000000000000000000000000002c89": "d1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c", - "0x0000000000000000000000000000000000000000000000000000000000002c93": "1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e", - "0x0000000000000000000000000000000000000000000000000000000000002c9d": "ccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9", - "0x0000000000000000000000000000000000000000000000000000000000002ca7": "8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84", - "0x0000000000000000000000000000000000000000000000000000000000002cb1": "85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19", - "0x0000000000000000000000000000000000000000000000000000000000002cbb": "0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3", - "0x0000000000000000000000000000000000000000000000000000000000002cc5": "a7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57", - "0x0000000000000000000000000000000000000000000000000000000000002ccf": "da5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82", - "0x0000000000000000000000000000000000000000000000000000000000002cd9": "3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b", - "0x0000000000000000000000000000000000000000000000000000000000002ce3": "273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea", - "0x0000000000000000000000000000000000000000000000000000000000002ced": "7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9", - "0x0000000000000000000000000000000000000000000000000000000000002cf7": "f63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616", - "0x0000000000000000000000000000000000000000000000000000000000002d01": "a68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8", - "0x0000000000000000000000000000000000000000000000000000000000002d0b": "59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f", - "0x0000000000000000000000000000000000000000000000000000000000002d15": "4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43", - "0x0000000000000000000000000000000000000000000000000000000000002d1f": "52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6", - "0x0000000000000000000000000000000000000000000000000000000000002d29": "7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327", - "0x0000000000000000000000000000000000000000000000000000000000002d33": "ef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f", - "0x0000000000000000000000000000000000000000000000000000000000002d3d": "e978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2", - "0x0000000000000000000000000000000000000000000000000000000000002d47": "c3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819", - "0x0000000000000000000000000000000000000000000000000000000000002d51": "bd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351", - "0x0000000000000000000000000000000000000000000000000000000000002d5b": "99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2", - "0x0000000000000000000000000000000000000000000000000000000000002d65": "02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97", - "0x0000000000000000000000000000000000000000000000000000000000002d6f": "627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771", - "0x0000000000000000000000000000000000000000000000000000000000002d79": "c087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7", - "0x0000000000000000000000000000000000000000000000000000000000002d83": "f7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867", - "0x0000000000000000000000000000000000000000000000000000000000002d8d": "1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571", - "0x0000000000000000000000000000000000000000000000000000000000002d97": "72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2", - "0x0000000000000000000000000000000000000000000000000000000000002da1": "e69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91", - "0x0000000000000000000000000000000000000000000000000000000000002dab": "c3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577", - "0x0000000000000000000000000000000000000000000000000000000000002db5": "93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192", - "0x0000000000000000000000000000000000000000000000000000000000002dbf": "b07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558", - "0x0000000000000000000000000000000000000000000000000000000000002dc9": "ec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca", - "0x0000000000000000000000000000000000000000000000000000000000002dd3": "2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1", - "0x0000000000000000000000000000000000000000000000000000000000002ddd": "f4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95", - "0x0000000000000000000000000000000000000000000000000000000000002de7": "8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697", - "0x0000000000000000000000000000000000000000000000000000000000002df1": "a194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c", - "0x0000000000000000000000000000000000000000000000000000000000002dfb": "a255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507", - "0x0000000000000000000000000000000000000000000000000000000000002e05": "7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb", - "0x0000000000000000000000000000000000000000000000000000000000002e0f": "b04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9", - "0x0000000000000000000000000000000000000000000000000000000000002e19": "6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded", - "0x0000000000000000000000000000000000000000000000000000000000002e23": "fcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce", - "0x0000000000000000000000000000000000000000000000000000000000002e2d": "df880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3", - "0x0000000000000000000000000000000000000000000000000000000000002e37": "adfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f", - "0x0000000000000000000000000000000000000000000000000000000000002e41": "b264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31", - "0x0000000000000000000000000000000000000000000000000000000000002e4b": "f2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38", - "0x0000000000000000000000000000000000000000000000000000000000002e55": "41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362", - "0x0000000000000000000000000000000000000000000000000000000000002e5f": "4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2", - "0x0000000000000000000000000000000000000000000000000000000000002e69": "8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315", - "0x0000000000000000000000000000000000000000000000000000000000002e73": "fa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf", - "0x0000000000000000000000000000000000000000000000000000000000002e7d": "da5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3", - "0x0000000000000000000000000000000000000000000000000000000000002e87": "16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547", - "0x0000000000000000000000000000000000000000000000000000000000002e91": "b75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094", - "0x0000000000000000000000000000000000000000000000000000000000002e9b": "d087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d", - "0x0000000000000000000000000000000000000000000000000000000000002ea5": "bc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6", - "0x0000000000000000000000000000000000000000000000000000000000002eaf": "3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3", - "0x0000000000000000000000000000000000000000000000000000000000002eb9": "4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563", - "0x0000000000000000000000000000000000000000000000000000000000002ec3": "f6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0", - "0x0000000000000000000000000000000000000000000000000000000000002ecd": "1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1", - "0x0000000000000000000000000000000000000000000000000000000000002ed7": "c3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57", - "0x0000000000000000000000000000000000000000000000000000000000002ee1": "3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc", - "0x0000000000000000000000000000000000000000000000000000000000002eeb": "cb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb", - "0x0000000000000000000000000000000000000000000000000000000000002ef5": "3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c", - "0x0000000000000000000000000000000000000000000000000000000000002eff": "dd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3", - "0x0000000000000000000000000000000000000000000000000000000000002f09": "ace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4", - "0x0000000000000000000000000000000000000000000000000000000000002f13": "f6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01", - "0x0000000000000000000000000000000000000000000000000000000000002f1d": "a6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb", - "0x0000000000000000000000000000000000000000000000000000000000002f27": "9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8", - "0x0000000000000000000000000000000000000000000000000000000000002f31": "a44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9", - "0x0000000000000000000000000000000000000000000000000000000000002f3b": "ce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0", - "0x0000000000000000000000000000000000000000000000000000000000002f45": "4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894", - "0x0000000000000000000000000000000000000000000000000000000000002f4f": "414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80", - "0x0000000000000000000000000000000000000000000000000000000000002f59": "647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d", - "0x0000000000000000000000000000000000000000000000000000000000002f63": "fa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855", - "0x0000000000000000000000000000000000000000000000000000000000002f6d": "106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6", - "0x0000000000000000000000000000000000000000000000000000000000002f77": "494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a", - "0x0000000000000000000000000000000000000000000000000000000000002f81": "0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795", - "0x0000000000000000000000000000000000000000000000000000000000002f8b": "d860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd", - "0x0000000000000000000000000000000000000000000000000000000000002f95": "9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf", - "0x0000000000000000000000000000000000000000000000000000000000002f9f": "4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8", - "0x0000000000000000000000000000000000000000000000000000000000002fa9": "c56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686", - "0x0000000000000000000000000000000000000000000000000000000000002fb3": "7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2", - "0x0000000000000000000000000000000000000000000000000000000000002fbd": "89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015", - "0x0000000000000000000000000000000000000000000000000000000000002fc7": "5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff", - "0x0000000000000000000000000000000000000000000000000000000000002fd1": "9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8", - "0x0000000000000000000000000000000000000000000000000000000000002fdb": "31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159", - "0x0000000000000000000000000000000000000000000000000000000000002fe5": "828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d", - "0x0000000000000000000000000000000000000000000000000000000000002fef": "7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053", - "0x0000000000000000000000000000000000000000000000000000000000002ff9": "31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1", - "0x0000000000000000000000000000000000000000000000000000000000003003": "e33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0", - "0x000000000000000000000000000000000000000000000000000000000000300d": "78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c", - "0x0000000000000000000000000000000000000000000000000000000000003017": "2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee", - "0x0000000000000000000000000000000000000000000000000000000000003021": "e1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b", - "0x000000000000000000000000000000000000000000000000000000000000302b": "4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b", - "0x0000000000000000000000000000000000000000000000000000000000003035": "156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846", - "0x000000000000000000000000000000000000000000000000000000000000303f": "dfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607", - "0x0000000000000000000000000000000000000000000000000000000000003049": "395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074", - "0x0000000000000000000000000000000000000000000000000000000000003053": "84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f", - "0x000000000000000000000000000000000000000000000000000000000000305d": "f4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586", - "0x0000000000000000000000000000000000000000000000000000000000003067": "0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6", - "0x0000000000000000000000000000000000000000000000000000000000003071": "4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac", - "0x000000000000000000000000000000000000000000000000000000000000307b": "9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f", - "0x0000000000000000000000000000000000000000000000000000000000003085": "473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766", - "0x000000000000000000000000000000000000000000000000000000000000308f": "225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3", - "0x0000000000000000000000000000000000000000000000000000000000003099": "31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa", - "0x00000000000000000000000000000000000000000000000000000000000030a3": "4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a", - "0x00000000000000000000000000000000000000000000000000000000000030ad": "ae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802", - "0x00000000000000000000000000000000000000000000000000000000000030b7": "8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c", - "0x00000000000000000000000000000000000000000000000000000000000030c1": "c22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845", - "0x00000000000000000000000000000000000000000000000000000000000030cb": "7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce", - "0x00000000000000000000000000000000000000000000000000000000000030d5": "943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31", - "0x00000000000000000000000000000000000000000000000000000000000030df": "66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0", - "0x00000000000000000000000000000000000000000000000000000000000030e9": "ac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70", - "0x00000000000000000000000000000000000000000000000000000000000030f3": "2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce", - "0x00000000000000000000000000000000000000000000000000000000000030fd": "823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887", - "0x0000000000000000000000000000000000000000000000000000000000003107": "3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918", - "0x0000000000000000000000000000000000000000000000000000000000003111": "44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85", - "0x000000000000000000000000000000000000000000000000000000000000311b": "6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7", - "0x0000000000000000000000000000000000000000000000000000000000003125": "581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a", - "0x000000000000000000000000000000000000000000000000000000000000312f": "9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526", - "0x0000000000000000000000000000000000000000000000000000000000003139": "54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d", - "0x0000000000000000000000000000000000000000000000000000000000003143": "1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924", - "0x000000000000000000000000000000000000000000000000000000000000314d": "ad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92", - "0x0000000000000000000000000000000000000000000000000000000000003157": "e13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67", - "0x0000000000000000000000000000000000000000000000000000000000003161": "b45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d", - "0x000000000000000000000000000000000000000000000000000000000000316b": "9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707", - "0x0000000000000000000000000000000000000000000000000000000000003175": "5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0", - "0x000000000000000000000000000000000000000000000000000000000000317f": "d6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e", - "0x0000000000000000000000000000000000000000000000000000000000003189": "96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31", - "0x0000000000000000000000000000000000000000000000000000000000003193": "4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412", - "0x000000000000000000000000000000000000000000000000000000000000319d": "c95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea", - "0x00000000000000000000000000000000000000000000000000000000000031a7": "2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079", - "0x00000000000000000000000000000000000000000000000000000000000031b1": "18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490", - "0x00000000000000000000000000000000000000000000000000000000000031bb": "b47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478", - "0x00000000000000000000000000000000000000000000000000000000000031c5": "e4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e", - "0x00000000000000000000000000000000000000000000000000000000000031cf": "fc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659", - "0x00000000000000000000000000000000000000000000000000000000000031d9": "4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a", - "0x00000000000000000000000000000000000000000000000000000000000031e3": "84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b", - "0x00000000000000000000000000000000000000000000000000000000000031ed": "ff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612", - "0x00000000000000000000000000000000000000000000000000000000000031f7": "73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce", - "0x0000000000000000000000000000000000000000000000000000000000003201": "ed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215", - "0x000000000000000000000000000000000000000000000000000000000000320b": "5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4", - "0x0000000000000000000000000000000000000000000000000000000000003215": "867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926", - "0x000000000000000000000000000000000000000000000000000000000000321f": "0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217", - "0x0000000000000000000000000000000000000000000000000000000000003229": "8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075", - "0x0000000000000000000000000000000000000000000000000000000000003233": "4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4", - "0x000000000000000000000000000000000000000000000000000000000000323d": "ec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef", - "0x0000000000000000000000000000000000000000000000000000000000003247": "efdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554", - "0x0000000000000000000000000000000000000000000000000000000000003251": "551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b", - "0x000000000000000000000000000000000000000000000000000000000000325b": "137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a", - "0x0000000000000000000000000000000000000000000000000000000000003265": "fb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78", - "0x000000000000000000000000000000000000000000000000000000000000326f": "96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c", - "0x0000000000000000000000000000000000000000000000000000000000003279": "68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff", - "0x0000000000000000000000000000000000000000000000000000000000003283": "e2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd", - "0x000000000000000000000000000000000000000000000000000000000000328d": "48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288", - "0x0000000000000000000000000000000000000000000000000000000000003297": "5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae", - "0x00000000000000000000000000000000000000000000000000000000000032a1": "204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33", - "0x00000000000000000000000000000000000000000000000000000000000032ab": "b74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5", - "0x00000000000000000000000000000000000000000000000000000000000032b5": "af5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7", - "0x00000000000000000000000000000000000000000000000000000000000032bf": "c657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda", - "0x00000000000000000000000000000000000000000000000000000000000032c9": "a0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b", - "0x00000000000000000000000000000000000000000000000000000000000032d3": "c9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de", - "0x00000000000000000000000000000000000000000000000000000000000032dd": "c74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297", - "0x00000000000000000000000000000000000000000000000000000000000032e7": "1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b", - "0x00000000000000000000000000000000000000000000000000000000000032f1": "6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1", - "0x00000000000000000000000000000000000000000000000000000000000032fb": "60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a", - "0x0000000000000000000000000000000000000000000000000000000000003305": "c50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc", - "0x000000000000000000000000000000000000000000000000000000000000330f": "b860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f", - "0x0000000000000000000000000000000000000000000000000000000000003319": "21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb", - "0x0000000000000000000000000000000000000000000000000000000000003323": "80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7", - "0x000000000000000000000000000000000000000000000000000000000000332d": "a3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675", - "0x0000000000000000000000000000000000000000000000000000000000003337": "e69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0", - "0x0000000000000000000000000000000000000000000000000000000000003341": "221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4", - "0x000000000000000000000000000000000000000000000000000000000000334b": "dcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e", - "0x0000000000000000000000000000000000000000000000000000000000003355": "4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46", - "0x000000000000000000000000000000000000000000000000000000000000335f": "5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f", - "0x0000000000000000000000000000000000000000000000000000000000003369": "9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de", - "0x0000000000000000000000000000000000000000000000000000000000003373": "1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8", - "0x000000000000000000000000000000000000000000000000000000000000337d": "4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51", - "0x0000000000000000000000000000000000000000000000000000000000003387": "f653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c" - }, - "key": "0x37d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42" - }, - "0x00f691ca9e1403d01344ebbaca0201380cacc99c": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7c48e400de1f24b4de94c59068fcd91a028576d13a22f900a7fcbd8f4845bcf4" - }, - "0x0300100f529a704d19736a8714837adbc934db7f": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x97b25febb46f44607c87a3498088c605086df207c7ddcd8ee718836a516a9153" - }, - "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4c310e1f5d2f2e03562c4a5c473ae044b9ee19411f07097ced41e85bd99c3364" - }, - "0x046dc70a4eba21473beb6d9460d880b8cfd66613": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4fd7c8d583447b937576211163a542d945ac8c0a6e22d0c42ac54e2cbaff9281" - }, - "0x04b85539570fb9501f65453dbfad410a467becdd": { - "balance": "0", - "nonce": 1, - "root": "0x9e53f0a2ddb430d27f6fffa0a68b5f75db1d68e24113dcca6e33918cdae80846", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000019": "19", - "0x000000000000000000000000000000000000000000000000000000000000001a": "1a", - "0x000000000000000000000000000000000000000000000000000000000000001b": "1b" - }, - "key": "0xd84f7711be2f8eca69c742153230995afb483855b7c555b08da330139cdb9579" - }, - "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe99460a483f3369006e3edeb356b3653699f246ec71f30568617ebc702058f59" - }, - "0x04d6c0c946716aac894fc1653383543a91faab60": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x98bb9ba48fda7bb8091271ab0e53d7e0022fb1f1fa8fa00814e193c7d4b91eb3" - }, - "0x050c9c302e904c7786b69caa9dd5b27a6e571b72": { - "balance": "0", - "nonce": 1, - "root": "0x818eaf5adb56c6728889ba66b6980cd66b41199f0007cdd905ae739405e3c630", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000077": "77", - "0x0000000000000000000000000000000000000000000000000000000000000078": "78", - "0x0000000000000000000000000000000000000000000000000000000000000079": "79" - }, - "key": "0xc3ac56e9e7f2f2c2c089e966d1b83414951586c3afeb86300531dfa350e38929" - }, - "0x06f647b157b8557a12979ba04cf5ba222b9747cf": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xaf38e0e6a4a4005507b5d3e9470e8ccc0273b74b6971f768cbdf85abeab8a95b" - }, - "0x075198bfe61765d35f990debe90959d438a943ce": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1d38ada74301c31f3fd7d92dd5ce52dc37ae633e82ac29c4ef18dfc141298e26" - }, - "0x075db7ab5778cd5491d3ed7ab64c1ec0818148f3": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf84223f460140ad56af9836cfa6c1c58c1397abf599c214689bc881066020ff7" - }, - "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcd07379b0120ad9a9c7fa47e77190be321ab107670f3115fec485bebb467307d" - }, - "0x087d80f7f182dd44f184aa86ca34488853ebcc04": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x867bc89cf8d5b39f1712fbc77414bbd93012af454c226dcee0fb34ccc0017498" - }, - "0x08d3b23dbfe8ef7965a8b5e4d9c21feddbc11491": { - "balance": "0", - "nonce": 1, - "root": "0x9a4a33f978d84e0aceb3ac3670c2e2df6c8ae27c189a96ed00b806d10ed7b4ee", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001c6": "01c6", - "0x00000000000000000000000000000000000000000000000000000000000001c7": "01c7", - "0x00000000000000000000000000000000000000000000000000000000000001c8": "01c8" - }, - "key": "0x792cc9f20a61c16646d5b6136693e7789549adb7d8e35503d0004130ea6528b0" - }, - "0x09b9c1875399cd724b1017f155a193713cb23732": { - "balance": "0", - "nonce": 1, - "root": "0x47fa48e25d3669a9bb190c59938f4be49de2d083696eb939c3b4072ec67e43b1", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000005e": "5e", - "0x000000000000000000000000000000000000000000000000000000000000005f": "5f", - "0x0000000000000000000000000000000000000000000000000000000000000060": "60" - }, - "key": "0x23ddaac09188c12e5d88009afa4a34041175c5531f45be53f1560a1cbfec4e8a" - }, - "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc7fc033fe9f00d24cb9c479ddc0598e592737c305263d088001d7419d16feffa" - }, - "0x0badc617ca1bcb1cb1d5272f64b168cbf0e8f86f": { - "balance": "0", - "nonce": 1, - "root": "0xca39f5f4ee3c6b33efe7bc485439f97f9dc62f65852c7a1cdf54fab1e3b70429", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000002d": "2d", - "0x000000000000000000000000000000000000000000000000000000000000002e": "2e", - "0x000000000000000000000000000000000000000000000000000000000000002f": "2f" - }, - "key": "0xc250f30c01f4b7910c2eb8cdcd697cf493f6417bb2ed61d637d625a85a400912" - }, - "0x0c2c51a0990aee1d73c1228de158688341557508": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x28f25652ec67d8df6a2e33730e5d0983443e3f759792a0128c06756e8eb6c37f" - }, - "0x0d336bc3778662a1252d29a6f7216055f7a582bf": { - "balance": "0", - "nonce": 1, - "root": "0xa5a91cf9e815fb55df14b3ee8c1325a988cb3b6dd34796c901385c3cc2992073", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000013f": "013f", - "0x0000000000000000000000000000000000000000000000000000000000000140": "0140", - "0x0000000000000000000000000000000000000000000000000000000000000141": "0141" - }, - "key": "0x86a73e3c668eb065ecac3402c6dc912e8eb886788ea147c770f119dcd30780c6" - }, - "0x0e4aea2bbb2ae557728f2661ee3639360f1d787a": { - "balance": "0", - "nonce": 1, - "root": "0x74ed78eb16016d7ff3a173ab1bbcee9daa8e358a9d6c9be5e84ba6f4a34cf96a", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000d1": "d1", - "0x00000000000000000000000000000000000000000000000000000000000000d2": "d2", - "0x00000000000000000000000000000000000000000000000000000000000000d3": "d3" - }, - "key": "0x517bd5fbe28e4368b0b9fcba13d5e81fb51babdf4ed63bd83885235ee67a8fa0" - }, - "0x0ef32dec5f88a96c2eb042126e8ab982406e0267": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x181abdd5e212171007e085fdc284a84d42d5bfc160960d881ccb6a10005ff089" - }, - "0x0ef96a52f4510f82b049ba991c401a8f5eb823e5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025" - }, - "0x0f228c3ba41142e702ee7306859026c99d3d2df5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xedd9b1f966f1dfe50234523b479a45e95a1a8ec4a057ba5bfa7b69a13768197c" - }, - "0x0fdcca8fde6d69ecbc9bfadb056ecf62d1966370": { - "balance": "0", - "nonce": 1, - "root": "0x493f90435402df0907019bffc6dd25a17ce4acd6eb6077ef94c1626f0d77c9f0", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000f9": "f9", - "0x00000000000000000000000000000000000000000000000000000000000000fa": "fa", - "0x00000000000000000000000000000000000000000000000000000000000000fb": "fb" - }, - "key": "0xfb5a31c5cfd33dce2c80a30c5efc28e5f4025624adcc2205a2504a78c57bdd1c" - }, - "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb7d9d175039df1ba52c734547844f8805252893c029f7dbba9a63f8bce3ee306" - }, - "0x0fed138ec52bab88db6c068df9125936c7c3e11b": { - "balance": "0", - "nonce": 1, - "root": "0x66eb16071ba379bf0c632fcb52f9175a656bef62adf0bef5349a7f5a6aad5d88", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000176": "0176", - "0x0000000000000000000000000000000000000000000000000000000000000177": "0177", - "0x0000000000000000000000000000000000000000000000000000000000000178": "0178" - }, - "key": "0x255ec86eac03ba59f6dfcaa02128adbb22c561ae0c49e9e62e4fff363750626e" - }, - "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9d42947ac5e61285567f65d4b400d90343dbd3192534c4c1f9d941c04f48f17c" - }, - "0x1037044fabf0421617c47c74681d7cc9c59f136c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2290ea88cc63f09ab5e8c989a67e2e06613311801e39c84aae3badd8bb38409c" - }, - "0x1042d41ee3def49e70df4e6c2be307b8015111e5": { - "balance": "0", - "nonce": 1, - "root": "0xdf3c1bfab8f7e70a8edf94792f91e4b6b2c2aa61caf687e4f6cb689d180adb80", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000095": "95", - "0x0000000000000000000000000000000000000000000000000000000000000096": "96", - "0x0000000000000000000000000000000000000000000000000000000000000097": "97" - }, - "key": "0xc0ce77c6a355e57b89cca643e70450612c0744c9f0f8bf7dee51d6633dc850b1" - }, - "0x104eb07eb9517a895828ab01a3595d3b94c766d5": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfab4c6889992a3f4e96b005dfd851021e9e1ec2631a7ccd2a001433e35077968" - }, - "0x1219c38638722b91f3a909f930d3acc16e309804": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd63070208c85e91c4c8c942cf52c416f0f3004c392a15f579350168f178dba2e" - }, - "0x132432ce1ce64304f1d145eba1772f6edd6cdd17": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x729953a43ed6c913df957172680a17e5735143ad767bda8f58ac84ec62fbec5e" - }, - "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x99e56541f21039c9b7c63655333841a3415de0d27b79d18ade9ec7ecde7a1139" - }, - "0x14e46043e63d0e3cdcf2530519f4cfaf35058cb2": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9feaf0bd45df0fbf327c964c243b2fbc2f0a3cb48fedfeea1ae87ac1e66bc02f" - }, - "0x1534b43c6dfa3695446aaf2aa07d123132cceceb": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2a248c1755e977920284c8054fceeb20530dc07cd8bbe876f3ce02000818cc3a" - }, - "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5264e880ecf7b80afda6cc2a151bac470601ff8e376af91aaf913a36a30c4009" - }, - "0x16032a66fc011dab75416d2449fe1a3d5f4319d8": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe3c79e424fd3a7e5bf8e0426383abd518604272fda87ecd94e1633d36f55bbb6" - }, - "0x16c57edf7fa9d9525378b0b81bf8a3ced0620c1c": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xda81833ff053aff243d305449775c3fb1bd7f62c4a3c95dc9fb91b85e032faee" - }, - "0x17333b15b4a5afd16cac55a104b554fc63cc8731": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4ceaf2371fcfb54a4d8bc1c804d90b06b3c32c9f17112b57c29b30a25cf8ca12" - }, - "0x17b917f9d79d922b33e41582984712e32b3ad366": { - "balance": "0", - "nonce": 1, - "root": "0x944f095afbd1383e5d0f91ef02895d398f4f76fdb6d86adf4765f25bdc304f5f", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000081": "81", - "0x0000000000000000000000000000000000000000000000000000000000000082": "82", - "0x0000000000000000000000000000000000000000000000000000000000000083": "83" - }, - "key": "0x13cfc46f6bdb7a1c30448d41880d061c3b8d36c55a29f1c0c8d95a8e882b8c25" - }, - "0x18291b5f568e45ef0f16709b20c810e08750791f": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x315ccc15883d06b4e743f8252c999bf1ee994583ff6114d89c0f3ddee828302b" - }, - "0x189f40034be7a199f1fa9891668ee3ab6049f82d": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6225e8f52719d564e8217b5f5260b1d1aac2bcb959e54bc60c5f479116c321b8" - }, - "0x18ac3e7343f016890c510e93f935261169d9e3f5": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xeba984db32038d7f4d71859a9a2fc6e19dde2e23f34b7cedf0c4bf228c319f17" - }, - "0x19041ad672875015bc4041c24b581eafc0869aab": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfc8d513d1615c763865b984ea9c381032c14a983f80e5b2bd90b20b518329ed7" - }, - "0x19129f84d987b13468846f822882dba0c50ca07d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2b8d12301a8af18405b3c826b6edcc60e8e034810f00716ca48bebb84c4ce7ab" - }, - "0x194e49be24c1a94159f127aa9257ded12a0027db": { - "balance": "0", - "nonce": 1, - "root": "0xe0a3d3b839fca0f54745d0c50a048e424c9259f063b7416410a4422eeb7f837e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000180": "0180", - "0x0000000000000000000000000000000000000000000000000000000000000181": "0181", - "0x0000000000000000000000000000000000000000000000000000000000000182": "0182" - }, - "key": "0xd57eafe6d4c5b91fe7114e199318ab640e55d67a1e9e3c7833253808b7dca75f" - }, - "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7bac5af423cb5e417fa6c103c7cb9777e80660ce3735ca830c238b0d41610186" - }, - "0x196d4a4c50eb47562596429fdecb4e3ac6b2a5fd": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4e258aa445a0e2a8704cbc57bbe32b859a502cd6f99190162236300fabd86c4a" - }, - "0x1a0eae9b9214d9269a4cff4982c45a67f4ca63aa": { - "balance": "0", - "nonce": 1, - "root": "0x5622801b1011de8403e44308bbf89a5809b7ad6586268cd72164523587f9b0e4", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000007c": "7c", - "0x000000000000000000000000000000000000000000000000000000000000007d": "7d", - "0x000000000000000000000000000000000000000000000000000000000000007e": "7e" - }, - "key": "0x6a2c8498657ae4f0f7b1a02492c554f7f8a077e454550727890188f7423ba014" - }, - "0x1ae59138ad95812304b117ee7b0d502bcb885af5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf164775805f47d8970d3282188009d4d7a2da1574fe97e5d7bc9836a2eed1d5b" - }, - "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8ee17a1ec4bae15d8650323b996c55d5fa11a14ceec17ff1d77d725183904914" - }, - "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa9fd2e3a6de5a9da5badd719bd6e048acefa6d29399d8a99e19fd9626805b60b" - }, - "0x1c972398125398a3665f212930758ae9518a8c94": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5d97d758e8800d37b6d452a1b1812d0afedba11f3411a17a8d51ee13a38d73f0" - }, - "0x1e345d32d0864f75b16bde837543aa44fac35935": { - "balance": "0", - "nonce": 1, - "root": "0xd91acf305934a60c960a93fb00f927ec79308b8a919d2449faede722c2324cb3", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000153": "0153", - "0x0000000000000000000000000000000000000000000000000000000000000154": "0154", - "0x0000000000000000000000000000000000000000000000000000000000000155": "0155" - }, - "key": "0x961508ac3c93b30ee9a5a34a862c9fe1659e570546ac6c2e35da20f6d2bb5393" - }, - "0x1e8ce8258fb47f55bf2c1473acb89a10074b9d0e": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfb2ab315988de92dcf6ba848e756676265b56e4b84778a2c955fb2b3c848c51c" - }, - "0x1f4924b14f34e24159387c0a4cdbaa32f3ddb0cf": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7963685967117ffb6fd019663dc9e782ebb1234a38501bffc2eb5380f8dc303b" - }, - "0x1f5746736c7741ae3e8fa0c6e947cade81559a86": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4e5bab4ebd077c3bbd8239995455989ea2e95427ddeed47d0618d9773332bb05" - }, - "0x1f5bde34b4afc686f136c7a3cb6ec376f7357759": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc3791fc487a84f3731eb5a8129a7e26f357089971657813b48a821f5582514b3" - }, - "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd9fa858992bc92386a7cebcd748eedd602bf432cb4b31607566bc92b85179624" - }, - "0x2144780b7d04d82239c6570f84ab66376b63dfc9": { - "balance": "0", - "nonce": 1, - "root": "0x59936c15c454933ebc4989afa77e350f7640301b07341aead5f1b2668eeb1dad", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000db": "db", - "0x00000000000000000000000000000000000000000000000000000000000000dc": "dc", - "0x00000000000000000000000000000000000000000000000000000000000000dd": "dd" - }, - "key": "0xd37b6f5e5f0fa6a1b3fd15c9b3cf0fb595ba245ab912ad8059e672fa55f061b8" - }, - "0x22694f8f2d0c62f63a25bd0057a80b89084c3b47": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2369a492b6cddcc0218617a060b40df0e7dda26abe48ba4e4108c532d3f2b84f" - }, - "0x22b3f17adeb5f2ec22135d275fcc6e29f4989401": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa3abdaefbb886078dc6c5c72e4bc8d12e117dbbd588236c3fa7e0c69420eb24a" - }, - "0x23262ad5ae496588bd793910b55ccf178fbd73f9": { - "balance": "0", - "nonce": 1, - "root": "0x3437803101a8040aca273fb734d7965a87f823ff1ef78c7edcaad358eb98dee3", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000171": "0171", - "0x0000000000000000000000000000000000000000000000000000000000000172": "0172", - "0x0000000000000000000000000000000000000000000000000000000000000173": "0173" - }, - "key": "0xd8489fd0ce5e1806b24d1a7ce0e4ba8f0856b87696456539fcbb625a9bed2ccc" - }, - "0x23b17315554bd2928c1f86dd526f7ee065a9607d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x12e394ad62e51261b4b95c431496e46a39055d7ada7dbf243f938b6d79054630" - }, - "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd72e318c1cea7baf503950c9b1bd67cf7caf2f663061fcde48d379047a38d075" - }, - "0x23e6931c964e77b02506b08ebf115bad0e1eca66": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x174f1a19ff1d9ef72d0988653f31074cb59e2cf37cd9d2992c7b0dd3d77d84f9" - }, - "0x24255ef5d941493b9978f3aabb0ed07d084ade19": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7583557e4e3918c95965fb610dc1424976c0eee606151b6dfc13640e69e5cb15" - }, - "0x245843abef9e72e7efac30138a994bf6301e7e1d": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfe6e594c507ec0ac14917f7a8032f83cd0c3c58b461d459b822190290852c0e1" - }, - "0x25261a7e8395b6e798e9b411c962fccc0fb31e38": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1017b10a7cc3732d729fe1f71ced25e5b7bc73dc62ca61309a8c7e5ac0af2f72" - }, - "0x2553ec67bc75f75d7de13db86b14290f0f76e342": { - "balance": "0", - "nonce": 1, - "root": "0x8078f3259d8199b7ca39d51e35d5b58d71ff148606731060386d323c5d19182c", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000185": "0185", - "0x0000000000000000000000000000000000000000000000000000000000000186": "0186", - "0x0000000000000000000000000000000000000000000000000000000000000187": "0187" - }, - "key": "0x0f30822f90f33f1d1ba6d1521a00935630d2c81ab12fa03d4a0f4915033134f3" - }, - "0x2604439a795970de2047e339293a450c0565f625": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8678559b30b321b0f0420a4a3e8cecfde90c6e56766b78c1723062c93c1f041f" - }, - "0x26704bf05b1da795939788ef05c8804dcf4b9009": { - "balance": "0", - "nonce": 1, - "root": "0xd60ee4ad5abbe759622fca5c536109b11e85aa2b48c0be2aebf01df597e74dba", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000015d": "015d", - "0x000000000000000000000000000000000000000000000000000000000000015e": "015e", - "0x000000000000000000000000000000000000000000000000000000000000015f": "015f" - }, - "key": "0xd1691564c6a5ab1391f0495634e749b9782de33756b6a058f4a9536c1b37bca6" - }, - "0x2727d12b98783b2c3641b5672bcfcdf007971d28": { - "balance": "0", - "nonce": 1, - "root": "0x59739ba3b156eb78f8bbb14bbf3dacdebfde95140f586db66f72e3117b94bb67", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000112": "0112", - "0x0000000000000000000000000000000000000000000000000000000000000113": "0113", - "0x0000000000000000000000000000000000000000000000000000000000000114": "0114" - }, - "key": "0x88bf4121c2d189670cb4d0a16e68bdf06246034fd0a59d0d46fb5cec0209831e" - }, - "0x2795044ce0f83f718bc79c5f2add1e52521978df": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xee9186a01e5e1122b61223b0e6acc6a069c9dcdb7307b0a296421272275f821b" - }, - "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0a93a7231976ad485379a3b66c2d8983ba0b2ca87abaf0ca44836b2a06a2b102" - }, - "0x27abdeddfe8503496adeb623466caa47da5f63ab": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x482814ea8f103c39dcf6ba7e75df37145bde813964d82e81e5d7e3747b95303d" - }, - "0x281c93990bac2c69cf372c9a3b66c406c86cca82": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x81c0c51e15c9679ef12d02729c09db84220ba007efe7ced37a57132f6f0e83c9" - }, - "0x2847213288f0988543a76512fab09684131809d9": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe1b86a365b0f1583a07fc014602efc3f7dedfa90c66e738e9850719d34ac194e" - }, - "0x28969cdfa74a12c82f3bad960b0b000aca2ac329": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x96d7104053877823b058fd9248e0bba2a540328e52ffad9bb18805e89ff579dc" - }, - "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5e88e876a3af177e6daafe173b67f186a53f1771a663747f26b278c5acb4c219" - }, - "0x2aac4746638ae1457010747a5b0fd2380a388f4f": { - "balance": "0", - "nonce": 1, - "root": "0x5a82aff126ffebff76002b1e4de03c40ba494b81cb3fbc528f23e4be35a9afe6", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000004b": "4b", - "0x000000000000000000000000000000000000000000000000000000000000004c": "4c", - "0x000000000000000000000000000000000000000000000000000000000000004d": "4d" - }, - "key": "0x96c43ef9dce3410b78df97be69e7ccef8ed40d6e5bfe6582ea4cd7d577aa4569" - }, - "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x303f57a0355c50bf1a0e1cf0fa8f9bdbc8d443b70f2ad93ac1c6b9c1d1fe29a2" - }, - "0x2c0cd3c60f41d56ed7664dbce39630395614bf4b": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x92d0f0954f4ec68bd32163a2bd7bc69f933c7cdbfc6f3d2457e065f841666b1c" - }, - "0x2c1287779024c3a2f0924b54816d79b7e378907d": { - "balance": "0", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x09d6e6745d272389182a510994e2b54d14b731fac96b9c9ef434bc1924315371" - }, - "0x2c582db705c5721bb3ba59f4ec8e44fb4ef6b920": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe02ec497b66cb57679eb01de1bed2ad385a3d18130441a9d337bd14897e85d39" - }, - "0x2d389075be5be9f2246ad654ce152cf05990b209": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa9233a729f0468c9c309c48b82934c99ba1fd18447947b3bc0621adb7a5fc643" - }, - "0x2d711642b726b04401627ca9fbac32f5c8530fb1": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfe2149c5c256a5eb2578c013d33e3af6a87a514965c7ddf4a8131e2d978f09f9" - }, - "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf33a7b66489679fa665dbfb4e6dd4b673495f853850eedc81d5f28bd2f4bd3b5" - }, - "0x2e5f413fd8d378ed081a76e1468dad8cbf6e9ed5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe69f40f00148bf0d4dfa28b3f3f5a0297790555eca01a00e49517c6645096a6c" - }, - "0x2eb6db4e06119ab31a3acf4f406ccbaa85e39c66": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xaeaf19d38b69be4fb41cc89e4888708daa6b9b1c3f519fa28fe9a0da70cd8697" - }, - "0x2f01c1c8c735a9a1b89898d3f14bbf61c91bf0fd": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd2f394b4549b085fb9b9a8b313a874ea660808a4323ab2598ee15ddd1eb7e897" - }, - "0x2fb64110da9389ce8567938a78f21b79222332f9": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x415ded122ff7b6fe5862f5c443ea0375e372862b9001c5fe527d276a3a420280" - }, - "0x2fc7b26c1fd501c57e57db3e876dc6ae7af6979b": { - "balance": "0", - "nonce": 1, - "root": "0x3d20fedd270b3771706fe00a580a155439be57e8d550762def10906e83ed58bb", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000009f": "9f", - "0x00000000000000000000000000000000000000000000000000000000000000a0": "a0", - "0x00000000000000000000000000000000000000000000000000000000000000a1": "a1" - }, - "key": "0xb9cddc73dfdacd009e55f27bdfd1cd37eef022ded5ce686ab0ffe890e6bf311e" - }, - "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe1eb1e18ae510d0066d60db5c2752e8c33604d4da24c38d2bda07c0cb6ad19e4" - }, - "0x30c72b4fb390ff1d387821e210f3ab04fbe86d13": { - "balance": "0", - "nonce": 1, - "root": "0xdf97f94bc47471870606f626fb7a0b42eed2d45fcc84dc1200ce62f7831da990", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000d6": "d6", - "0x00000000000000000000000000000000000000000000000000000000000000d7": "d7", - "0x00000000000000000000000000000000000000000000000000000000000000d8": "d8" - }, - "key": "0x005e94bf632e80cde11add7d3447cd4ca93a5f2205d9874261484ae180718bd6" - }, - "0x311df588ca5f412f970891e4cc3ac23648968ca2": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x974a4800ec4c0e998f581c6ee8c3972530989e97a179c6b2d40b8710c036e7b1" - }, - "0x312e8fca5ac7dfc591031831bff6fede6ecf12a8": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x64bfba8a4688bdee41c4b998e101567b8b56fea53d30ab85393f2d5b70c5da90" - }, - "0x32c417b98c3d9bdd37550c0070310526347b4648": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x80cd4a7b601d4ba0cb09e527a246c2b5dd25b6dbf862ac4e87c6b189bfce82d7" - }, - "0x33afd8244c9c1a37f5bddb3254cd08779a196458": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x210ce6d692a21d75de3764b6c0356c63a51550ebec2c01f56c154c24b1cf8888" - }, - "0x33fc6e8ad066231eb5527d1a39214c1eb390985d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x87e33f70e1dd3c6ff68e3b71757d697fbeb20daae7a3cc8a7b1b3aa894592c50" - }, - "0x360671abc40afd33ae0091e87e589fc320bf9e3d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x12c1bb3dddf0f06f62d70ed5b7f7db7d89b591b3f23a838062631c4809c37196" - }, - "0x3632d1763078069ca77b90e27061147a3b17ddc3": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0463e52cda557221b0b66bd7285b043071df4c2ab146260f4e010970f3a0cccf" - }, - "0x368b766f1e4d7bf437d2a709577a5210a99002b6": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4845aac9f26fcd628b39b83d1ccb5c554450b9666b66f83aa93a1523f4db0ab6" - }, - "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcac96145454c46255fccca35343d9505164dabe319c17d81fda93cf1171e4c6e" - }, - "0x38d0bd409abe8d78f9f0e0a03671e44e81c41c27": { - "balance": "0", - "nonce": 1, - "root": "0x23a888c0a464ce461651fc1be2cfa0cb6ba4d1b125abe5b447eeadf9c5adf1f1", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000167": "0167", - "0x0000000000000000000000000000000000000000000000000000000000000168": "0168", - "0x0000000000000000000000000000000000000000000000000000000000000169": "0169" - }, - "key": "0xb58e67c536550fdf7140c8333ca62128df469a7270b16d528bc778909e0ac9a5" - }, - "0x3ae75c08b4c907eb63a8960c45b86e1e9ab6123c": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x878040f46b1b4a065e6b82abd35421eb69eededc0c9598b82e3587ae47c8a651" - }, - "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb5bca5e9ccef948c2431372315acc3b96e098d0e962b0c99d634a0475b670dc3" - }, - "0x3c204ccddfebae334988367b5cf372387dc49ebd": { - "balance": "0", - "nonce": 1, - "root": "0xc7bf2b34294065afb9a2c15f906cba1f7a1a9f0da34ea9c46603b52cae9028ec", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000194": "0194", - "0x0000000000000000000000000000000000000000000000000000000000000195": "0195", - "0x0000000000000000000000000000000000000000000000000000000000000196": "0196" - }, - "key": "0x5ec55391e89ac4c3cf9e61801cd13609e8757ab6ed08687237b789f666ea781b" - }, - "0x3c2572436de9a5f3c450071e391c8a9410ba517d": { - "balance": "0", - "nonce": 1, - "root": "0xbfba1bc2ac42655f5a97450be62b9430822232f1ce4998eaf5239b0c243b2b84", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000090": "90", - "0x0000000000000000000000000000000000000000000000000000000000000091": "91", - "0x0000000000000000000000000000000000000000000000000000000000000092": "92" - }, - "key": "0x606059a65065e5f41347f38754e6ddb99b2d709fbff259343d399a4f9832b48f" - }, - "0x3c5c4713708c72b519144ba8e595a8865505000d": { - "balance": "0", - "nonce": 1, - "root": "0x52d6d2913ae44bca11b5a116021db97c91a13e385ed48ba06628e74201231dba", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001c1": "01c1", - "0x00000000000000000000000000000000000000000000000000000000000001c2": "01c2", - "0x00000000000000000000000000000000000000000000000000000000000001c3": "01c3" - }, - "key": "0x37ddfcbcb4b2498578f90e0fcfef9965dcde4d4dfabe2f2836d2257faa169947" - }, - "0x3cf2e7052ebd484a8d6fbca579ddb3cf920de9d3": { - "balance": "0", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa95c88d7dc0f2373287c3b2407ba8e7419063833c424b06d8bb3b29181bb632e" - }, - "0x3ee253436fc50e5a136ee01489a318afe2bbd572": { - "balance": "0", - "nonce": 1, - "root": "0xc57604a461c94ecdac12dbb706a52b32913d72253baffb8906e742724ae12449", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001b2": "01b2", - "0x00000000000000000000000000000000000000000000000000000000000001b3": "01b3", - "0x00000000000000000000000000000000000000000000000000000000000001b4": "01b4" - }, - "key": "0xaf7c37d08a73483eff9ef5054477fb5d836a184aa07c3edb4409b9eb22dd56ca" - }, - "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb40cc623b26a22203675787ca05b3be2c2af34b6b565bab95d43e7057e458684" - }, - "0x3f79bb7b435b05321651daefd374cdc681dc06fa": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8c7bfaa19ea367dec5272872114c46802724a27d9b67ea3eed85431df664664e" - }, - "0x3fba9ae304c21d19f50c23db133073f4f9665fc1": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0b564e4a0203cbcec8301709a7449e2e7371910778df64c89f48507390f2d129" - }, - "0x402f57de890877def439a753fcc0c37ac7808ef5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5c20f6ee05edbb60beeab752d87412b2f6e12c8feefa2079e6bd989f814ed4da" - }, - "0x40b7ab67fb92dbcb4ff4e39e1155cad2fa066523": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd352b05571154d9a2061143fe6df190a740a2d321c59eb94a54acb7f3054e489" - }, - "0x414a21e525a759e3ffeb22556be6348a92d5a13e": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x15293aec87177f6c88f58bc51274ba75f1331f5cb94f0c973b1deab8b3524dfe" - }, - "0x417fe11f58b6a2d089826b60722fbed1d2db96dd": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd5e252ab2fba10107258010f154445cf7dffc42b7d8c5476de9a7adb533d73f1" - }, - "0x41b45640640c98c953feef23468e0d275515f82f": { - "balance": "0", - "nonce": 1, - "root": "0x82b326641825378faa11c641c916f2e22c01080f487de0463e30d5e32b960f97", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000013a": "013a", - "0x000000000000000000000000000000000000000000000000000000000000013b": "013b", - "0x000000000000000000000000000000000000000000000000000000000000013c": "013c" - }, - "key": "0xc2406cbd93e511ef493ac81ebe2b6a3fbecd05a3ba52d82a23a88eeb9d8604f0" - }, - "0x426fcdc383c8becb38926ec0569ec4a810105fab": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6bd9fb206b22c76b4f9630248940855b842c684db89adff0eb9371846ea625a9" - }, - "0x4340ee1b812acb40a1eb561c019c327b243b92df": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa13bfef92e05edee891599aa5e447ff2baa1708d9a6473a04ef66ab94f2a11e4" - }, - "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb66092bc3624d84ff94ee42b097e846baf6142197d2c31245734d56a275c8eb9" - }, - "0x452705f08c621987b14d5f729ca81829041f6373": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xac7183ebb421005a660509b070d3d47fc4e134cb7379c31dc35dc03ebd02e1cf" - }, - "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x465311df0bf146d43750ed7d11b0451b5f6d5bfc69b8a216ef2f1c79c93cd848" - }, - "0x45f83d17e10b34fca01eb8f4454dac34a777d940": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6dc09fdec00aa9a30dd8db984406a33e3ca15e35222a74773071207a5e56d2c2" - }, - "0x469542b3ece7ae501372a11c673d7627294a85ca": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6dbe5551f50400859d14228606bf221beff07238bfa3866454304abb572f9512" - }, - "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8b76305d3f00d33f77bd41496b4144fd3d113a2ec032983bd5830a8b73f61cf0" - }, - "0x46b61db0aac95a332cecadad86e52531e578cf1f": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5677600b2af87d21fdab2ac8ed39bd1be2f790c04600de0400c1989040d9879c" - }, - "0x478508483cbb05defd7dcdac355dadf06282a6f2": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5fc13d7452287b5a8e3c3be9e4f9057b5c2dd82aeaff4ed892c96fc944ec31e7" - }, - "0x47ce7195b6d53aaa737ff17d57db20d0d4874ef1": { - "balance": "0", - "nonce": 1, - "root": "0x3d0e2ba537f35941068709450f25fee45aaf4dc6ae2ed22ad12e0743ac7c54a7", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000108": "0108", - "0x0000000000000000000000000000000000000000000000000000000000000109": "0109", - "0x000000000000000000000000000000000000000000000000000000000000010a": "010a" - }, - "key": "0x0579e46a5ed8a88504ac7d579b12eb346fbe4fd7e281bdd226b891f8abed4789" - }, - "0x47dc540c94ceb704a23875c11273e16bb0b8a87a": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x025f478d53bf78add6fa3708d9e061d59bfe14b21329b2a4cf1156d4f81b3d2d" - }, - "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x05f6de281d8c2b5d98e8e01cd529bd76416b248caf11e0552047c5f1d516aab6" - }, - "0x4816ce9dd68c07ab1e12b5ddc4dbef38792751c5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x93843d6fa1fe5709a3035573f61cc06832f0377544d16d3a0725e78a0fa0267c" - }, - "0x48701721ec0115f04bc7404058f6c0f386946e09": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x12be3bf1f9b1dab5f908ca964115bee3bcff5371f84ede45bc60591b21117c51" - }, - "0x494d799e953876ac6022c3f7da5e0f3c04b549be": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x04d9aa4f67f8b24d70a0ffd757e82456d9184113106b7d9e8eb6c3e8a8df27ee" - }, - "0x4a0f1452281bcec5bd90c3dce6162a5995bfe9df": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5c1d92594d6377fe6423257781b382f94dffcde4fadbf571aa328f6eb18f8fcd" - }, - "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf16522fc36907ee1e9948240b0c1d1d105a75cc63b71006f16c20d79ad469bd7" - }, - "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2116ab29b4cb8547af547fe472b7ce30713f234ed49cb1801ea6d3cf9c796d57" - }, - "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x246cc8a2b79a30ec71390d829d0cb37cce1b953e89cb14deae4945526714a71c" - }, - "0x4ba91e785d2361ddb198bcd71d6038305021a9b8": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x99ce1680f73f2adfa8e6bed135baa3360e3d17f185521918f9341fc236526321" - }, - "0x4bfa260a661d68110a7a0a45264d2d43af9727de": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6f358b4e903d31fdd5c05cddaa174296bb30b6b2f72f1ff6410e6c1069198989" - }, - "0x4dde844b71bcdf95512fb4dc94e84fb67b512ed8": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5602444769b5fd1ddfca48e3c38f2ecad326fe2433f22b90f6566a38496bd426" - }, - "0x4f362f9093bb8e7012f466224ff1237c0746d8c8": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcb6f450b4720c6b36d3a12271e35ace27f1d527d46b073771541ad39cc59398d" - }, - "0x4f3e7da249f34e3cc8b261a7dc5b2d8e1cd85b78": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4d79fea6c7fef10cb0b5a8b3d85b66836a131bec0b04d891864e6fdb9794af75" - }, - "0x4fb733bedb74fec8d65bedf056b935189a289e92": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa02abeb418f26179beafd96457bda8c690c6b1f3fbabac392d0920863edddbc6" - }, - "0x4fffb6fbd0372228cb5e4d1f033a29f30cb668c8": { - "balance": "0", - "nonce": 1, - "root": "0xcd3e75299e967d5f88d306be905a134343b224d3fd5a861b1a690de0e2dfe1ba", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000b3": "b3", - "0x00000000000000000000000000000000000000000000000000000000000000b4": "b4", - "0x00000000000000000000000000000000000000000000000000000000000000b5": "b5" - }, - "key": "0xf19ee923ed66b7b9264c2644aa20e5268a251b4914ca81b1dffee96ecb074cb1" - }, - "0x50996999ff63a9a1a07da880af8f8c745a7fe72c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0e57ffa6cc6cbd96c1400150417dd9b30d958c58f63c36230a90a02b076f78b5" - }, - "0x5123198d8a827fe0c788c409e7d2068afde64339": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa15773c9bfabef49e9825460ed95bf67b22b67d7806c840e0eb546d73c424768" - }, - "0x526e1ff4cddb5033849a114c54eb71a176f6440c": { - "balance": "0", - "nonce": 1, - "root": "0x834718111121e2058fdb90a51f448028071857e11fbd55d43256174df56af01a", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000c7": "c7", - "0x00000000000000000000000000000000000000000000000000000000000000c8": "c8", - "0x00000000000000000000000000000000000000000000000000000000000000c9": "c9" - }, - "key": "0xb3a33a7f35ca5d08552516f58e9f76219716f9930a3a11ce9ae5db3e7a81445d" - }, - "0x5371ac01baa0b8aa9cbfcd36a49e0b5f7fb7109d": { - "balance": "0", - "nonce": 1, - "root": "0x385b84d27059a3c78e7ea63a691eeb9c5376f77af11336762f8c18882ff7471a", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000028": "28", - "0x0000000000000000000000000000000000000000000000000000000000000029": "29", - "0x000000000000000000000000000000000000000000000000000000000000002a": "2a" - }, - "key": "0x7a08bb8417e6b18da3ba926568f1022c15553b2b0f1a32f2fd9e5a605469e54f" - }, - "0x54314225e5efd5b8283d6ec2f7a03d5a92106374": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcade985c7fb6d371d0c7f7cb40178e7873d623eadcc37545798ec33a04bb2173" - }, - "0x549abf1ae8db6de0d131a7b2b094c813ec1c6731": { - "balance": "0", - "nonce": 1, - "root": "0x73bffc68a947fa19b7becd45661d22c870fac8dbf2b25703e1bdab5367f29543", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000086": "86", - "0x0000000000000000000000000000000000000000000000000000000000000087": "87", - "0x0000000000000000000000000000000000000000000000000000000000000088": "88" - }, - "key": "0x910fb8b22867289cb57531ad39070ef8dbdbbe7aee941886a0e9f572b63ae9ee" - }, - "0x5502b2da1a3a08ad258aa08c0c6e0312cf047e64": { - "balance": "0", - "nonce": 1, - "root": "0xf73591e791af4c7c5fa039c33dd9d169cab14b1d9b0ca78bcc4e740d553b1acf", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000f4": "f4", - "0x00000000000000000000000000000000000000000000000000000000000000f5": "f5", - "0x00000000000000000000000000000000000000000000000000000000000000f6": "f6" - }, - "key": "0x1d6ee979097e29141ad6b97ae19bb592420652b7000003c55eb52d5225c3307d" - }, - "0x553f68e60e9f8ea74c831449525dc1bc4f6fc58e": { - "balance": "0", - "nonce": 1, - "root": "0x14f9f4b9445c7547d5a4671a38b0b12bbc0e7198c3b2934b82b695c8630d4972", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000126": "0126", - "0x0000000000000000000000000000000000000000000000000000000000000127": "0127", - "0x0000000000000000000000000000000000000000000000000000000000000128": "0128" - }, - "key": "0x6ad3ba011e031431dc057c808b85346d58001b85b32a4b5c90ccccea0f82e170" - }, - "0x56270eccd88bcd5ad8d2b08f82d96cd8dace4eb3": { - "balance": "0", - "nonce": 1, - "root": "0xb0700fe13dbaf94be50bcbec13a7b53e6cba034b29a3daba98fa861f5897213f", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000063": "63", - "0x0000000000000000000000000000000000000000000000000000000000000064": "64", - "0x0000000000000000000000000000000000000000000000000000000000000065": "65" - }, - "key": "0xcd6b3739d4dbce17dafc156790f2a3936eb75ce95e9bba039dd76661f40ea309" - }, - "0x56d3f289b889e65c4268a1b56b3da2d3860d0afb": { - "balance": "0", - "nonce": 0, - "root": "0x207f6c3e450546b0d1f3bc6a6faf5bfa0bff80396c55d567b834cf0e7c760347", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000000a": "0a", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0b", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0c" - }, - "key": "0xdc9ea08bdea052acab7c990edbb85551f2af3e1f1a236356ab345ac5bcc84562" - }, - "0x56dc3a6c5ca1e1b773e5fdfc8a92e9a42feaa6e9": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xdbd66b6a89e01c76ae5f8cb0dcd8a24e787f58f015c9b08972bfabefa2eae0d5" - }, - "0x579ab019e6b461188300c7fb202448d34669e5ff": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x18f4256a59e1b2e01e96ac465e1d14a45d789ce49728f42082289fc25cf32b8d" - }, - "0x5820871100e656b0d84b950f0a557e37419bf17d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa" - }, - "0x58d77a134c11f45f9573d5c105fa6c8ae9b4237a": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd9f987fec216556304eba05bcdae47bb736eea5a4183eb3e2c3a5045734ae8c7" - }, - "0x591317752b32e45c9d44d925a4bcb4898f6b51fb": { - "balance": "0", - "nonce": 1, - "root": "0x89bde89df7f2d83344a503944bb347b847f208df837228bb2cdfd6c3228ca3df", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000011c": "011c", - "0x000000000000000000000000000000000000000000000000000000000000011d": "011d", - "0x000000000000000000000000000000000000000000000000000000000000011e": "011e" - }, - "key": "0x88a5635dabc83e4e021167be484b62cbed0ecdaa9ac282dab2cd9405e97ed602" - }, - "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x3e57e37bc3f588c244ffe4da1f48a360fa540b77c92f0c76919ec4ee22b63599" - }, - "0x5b35d3e1ac7a2c61d247046d38773decf4f2839a": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x55cab9586acb40e66f66147ff3a059cfcbbad785dddd5c0cc31cb43edf98a5d5" - }, - "0x5c019738b38feae2a8944bd644f7acd5e6f40e5c": { - "balance": "0", - "nonce": 1, - "root": "0xea83389383152270104093ed5dfe34ba403c75308133aa1be8f51ad804b3e9ee", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000103": "0103", - "0x0000000000000000000000000000000000000000000000000000000000000104": "0104", - "0x0000000000000000000000000000000000000000000000000000000000000105": "0105" - }, - "key": "0xbccd85b63dba6300f84c561c5f52ce08a240564421e382e6f550ce0c12f2f632" - }, - "0x5c04401b6f6a5e318c7b6f3106a6217d20008427": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6c37093a34016ae687da7aabb18e42009b71edff70a94733c904aea51a4853c1" - }, - "0x5c23d95614dce3317e7be72de3c81479c3172a8a": { - "balance": "0", - "nonce": 1, - "root": "0x4f446329b5ee3d13d4f6b5e5f210ddc2d90fedba384b950e36a1d19af95c5cb1", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000000f": "0f", - "0x0000000000000000000000000000000000000000000000000000000000000010": "10", - "0x0000000000000000000000000000000000000000000000000000000000000011": "11" - }, - "key": "0x34a715e08b77afd68cde30b62e222542f3db90758370400c94d0563959a1d1a0" - }, - "0x5c62e091b8c0565f1bafad0dad5934276143ae2c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1bf7626cec5330a127e439e68e6ee1a1537e73b2de1aa6d6f7e06bc0f1e9d763" - }, - "0x5d6bc8f87dd221a9f8c4144a256391979ff6426b": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcc74930e1ee0e71a8081f247ec47442a3e5d00897966754a5b3ee8beb2c1160c" - }, - "0x5df7504bc193ee4c3deadede1459eccca172e87c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4f458f480644b18c0e8207f405b82da7f75c7b3b5a34fe6771a0ecf644677f33" - }, - "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x3848b7da914222540b71e398081d04e3849d2ee0d328168a3cc173a1cd4e783b" - }, - "0x5f4755a4bd689dc90425fb2fdb64a4b191a7264d": { - "balance": "0", - "nonce": 1, - "root": "0xaf867e6cbae810caa924b8b6ac3d8c0891831491a6906dd0be7ad324dcd1533d", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000016c": "016c", - "0x000000000000000000000000000000000000000000000000000000000000016d": "016d", - "0x000000000000000000000000000000000000000000000000000000000000016e": "016e" - }, - "key": "0x1c3f74249a4892081ba0634a819aec9ed25f34c7653f5719b9098487e65ab595" - }, - "0x5f552da00dfb4d3749d9e62dcee3c918855a86a0": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd52564daf6d32a6ae29470732726859261f5a7409b4858101bd233ed5cc2f662" - }, - "0x5f553e0d115af809cfc1396b4823378b2c7cced5": { - "balance": "0", - "nonce": 1, - "root": "0xcc48f8d1c0dd6ec8ab7bbd792d94f6a74c8876b41bc859cee2228e8dad8207a4", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000ae": "ae", - "0x00000000000000000000000000000000000000000000000000000000000000af": "af", - "0x00000000000000000000000000000000000000000000000000000000000000b0": "b0" - }, - "key": "0xe3c2e12be28e2e36dc852e76dd32e091954f99f2a6480853cd7b9e01ec6cd889" - }, - "0x6096d8459f8e424f514468098e6a0f2a871c815d": { - "balance": "0", - "nonce": 1, - "root": "0xa20e6a21244af8ffccd5442297ad9b7a76ac72d7d8ac9e16f12fcc50e90b734e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000018f": "018f", - "0x0000000000000000000000000000000000000000000000000000000000000190": "0190", - "0x0000000000000000000000000000000000000000000000000000000000000191": "0191" - }, - "key": "0x67cc0bf5341efbb7c8e1bdbf83d812b72170e6edec0263eeebdea6f107bbef0d" - }, - "0x60d0debc5c81432ee294b9a06dcf58964224bbc2": { - "balance": "0", - "nonce": 1, - "root": "0x5446b818f4c669669cd3314726ff134cf18c58a9a536df13c700610705a8b7c8", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000041": "41", - "0x0000000000000000000000000000000000000000000000000000000000000042": "42", - "0x0000000000000000000000000000000000000000000000000000000000000043": "43" - }, - "key": "0x395b92f75f8e06b5378a84ba03379f025d785d8b626b2b6a1c84b718244b9a91" - }, - "0x61774970e93c00a3e206a26c64707d3e33f89972": { - "balance": "0", - "nonce": 1, - "root": "0x869acb929f591c54cb85842a51f296635e7d895798c547a293afe43e7bf7f417", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000006d": "6d", - "0x000000000000000000000000000000000000000000000000000000000000006e": "6e", - "0x000000000000000000000000000000000000000000000000000000000000006f": "6f" - }, - "key": "0x07b49045c401bcc408f983d91a199c908cdf0d646049b5b83629a70b0117e295" - }, - "0x6269e930eee66e89863db1ff8e4744d65e1fb6bf": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x419809ad1512ed1ab3fb570f98ceb2f1d1b5dea39578583cd2b03e9378bbe418" - }, - "0x62b67e1f685b7fef51102005dddd27774be3fee3": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf462aaa112b195c148974ff796a81c0e7f9a972d04e60c178ac109102d593a88" - }, - "0x6325c46e45d96f775754b39a17d733c4920d0038": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7c463797c90e9ba42b45ae061ffaa6bbd0dad48bb4998f761e81859f2a904a49" - }, - "0x63eb2d6ec7c526fd386631f71824bad098f39813": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfdaf2549ea901a469b3e91cd1c4290fab376ef687547046751e10b7b461ff297" - }, - "0x6510225e743d73828aa4f73a3133818490bd8820": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe6d72f72fd2fc8af227f75ab3ab199f12dfb939bdcff5f0acdac06a90084def8" - }, - "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc2c26fbc0b7893d872fa528d6c235caab9164feb5b54c48381ff3d82c8244e77" - }, - "0x654aa64f5fbefb84c270ec74211b81ca8c44a72e": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x00aa781aff39a8284ef43790e3a511b2caa50803613c5096bc782e8de08fa4c5" - }, - "0x65c74c15a686187bb6bbf9958f494fc6b8006803": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x570210539713235b442bbbad50c58bee81b70efd2dad78f99e41a6c462faeb43" - }, - "0x662fb906c0fb671022f9914d6bba12250ea6adfb": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb58e22a9ece8f9b3fdbaa7d17fe5fc92345df11d6863db4159647d64a34ff10b" - }, - "0x66378d2edcc2176820e951f080dd6e9e15a0e695": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa02c8b02efb52fad3056fc96029467937c38c96d922250f6d2c0f77b923c85aa" - }, - "0x670dc376ecca46823e13bab90acab2004fb1706c": { - "balance": "0", - "nonce": 1, - "root": "0xae440143d21e24a931b6756f6b3d50d337eaf0db3e6c34e36ab46fe2d99ef83e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000199": "0199", - "0x000000000000000000000000000000000000000000000000000000000000019a": "019a", - "0x000000000000000000000000000000000000000000000000000000000000019b": "019b" - }, - "key": "0xdcda5b5203c2257997a574bdf85b2bea6d04829e8d7e048a709badc0fb99288c" - }, - "0x6741149452787eb4384ebbd8456643f246217034": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x37e51740ad994839549a56ef8606d71ace79adc5f55c988958d1c450eea5ac2d" - }, - "0x684888c0ebb17f374298b65ee2807526c066094c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb062c716d86a832649bccd53e9b11c77fc8a2a00ef0cc0dd2f561688a69d54f7" - }, - "0x6922e93e3827642ce4b883c756b31abf80036649": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x3be526914a7d688e00adca06a0c47c580cb7aa934115ca26006a1ed5455dd2ce" - }, - "0x6a632187a3abf9bebb66d43368fccd612f631cbc": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9de451c4f48bdb56c6df198ff8e1f5e349a84a4dc11de924707718e6ac897aa6" - }, - "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x099d5081762b8b265e8ba4cd8e43f08be4715d903a0b1d96b3d9c4e811cbfb33" - }, - "0x6b2884fef44bd4288621a2cda9f88ca07b480861": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe6c5edf6a0fbdcff100e5ceafb63cba9aea355ba397a93fdb42a1a67b91375f8" - }, - "0x6c49c19c40a44bbf1cf9d2d8741ec1126e815fc6": { - "balance": "0", - "nonce": 1, - "root": "0xe00c49a65849d05cbf27a4d7788a68bc7b6013ae33411d40bc89282fc064f33d", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001ad": "01ad", - "0x00000000000000000000000000000000000000000000000000000000000001ae": "01ae", - "0x00000000000000000000000000000000000000000000000000000000000001af": "01af" - }, - "key": "0x0304d8eaccf0b942c468074250cbcb625ec5c4688b6b5d17d2a9bdd8dd565d5a" - }, - "0x6ca60a92cbf88c7f527978dc183a22e774755551": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x52d034ca6ebd21c7ba62a2ad3b6359aa4a1cdc88bdaa64bb2271d898777293ab" - }, - "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xaa0ac2f707a3dc131374839d4ee969eeb1cb55adea878f56e7b5b83d187d925c" - }, - "0x6d09a879576c0d941bea7833fb2285051b10d511": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xaa0ffaa57269b865dccce764bf412de1dff3e7bba22ce319ef09e5907317b3e7" - }, - "0x6d8b8f27857e10b21c0ff227110d7533cea03d0e": { - "balance": "0", - "nonce": 1, - "root": "0xd3d9839f87c29fb007fd9928d38bbf84ef089f0cd640c838f4a42631e828c667", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000117": "0117", - "0x0000000000000000000000000000000000000000000000000000000000000118": "0118", - "0x0000000000000000000000000000000000000000000000000000000000000119": "0119" - }, - "key": "0xfdbb8ddca8cecfe275da1ea1c36e494536f581d64ddf0c4f2e6dae9c7d891427" - }, - "0x6e09a59a69b41abca97268b05595c074ad157872": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7a3870cc1ed4fc29e9ab4dd3218dbb239dd32c9bf05bff03e325b7ba68486c47" - }, - "0x6e3d512a9328fa42c7ca1e20064071f88958ed93": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc1a6a0bf60ee7b3228ecf6cb7c9e5491fbf62642a3650d73314e976d9eb9a966" - }, - "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x97f72ff641eb40ee1f1163544931635acb7550a0d44bfb9f4cc3aeae829b6d7d" - }, - "0x6f80f6a318ea88bf0115d693f564139a5fb488f6": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe73b3367629c8cb991f244ac073c0863ad1d8d88c2e180dd582cefda2de4415e" - }, - "0x7021bf21ecdbefcb33d09e4b812a47b273aa1d5c": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb9400acf38453fd206bc18f67ba04f55b807b20e4efc2157909d91d3a9f7bed2" - }, - "0x706be462488699e89b722822dcec9822ad7d05a7": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x78948842ff476b87544c189ce744d4d924ffd0907107a0dbaa4b71d0514f2225" - }, - "0x717f8aa2b982bee0e29f573d31df288663e1ce16": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc3c8e2dc64e67baa83b844263fe31bfe24de17bb72bfed790ab345b97b007816" - }, - "0x7212449475dcc75d408ad62a9acc121d94288f6d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe333845edc60ed469a894c43ed8c06ec807dafd079b3c948077da56e18436290" - }, - "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2fe5767f605b7b821675b223a22e4e5055154f75e7f3041fdffaa02e4787fab8" - }, - "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f": { - "balance": "999999999999999999999518871495454239", - "nonce": 402, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4363d332a0d4df8582a84932729892387c623fe1ec42e2cfcbe85c183ed98e0e" - }, - "0x75b9236dfe7d0e12eb21b6d175276a7c5d4e851d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc54ffffcbaa5b566a7cf37386c4ce5a338d558612343caaa99788343d516aa5f" - }, - "0x77adfc95029e73b173f60e556f915b0cd8850848": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0993fd5b750fe4414f93c7880b89744abb96f7af1171ed5f47026bdf01df1874" - }, - "0x788adf954fc28a524008ea1f2d0e87ae8893afdc": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x903f24b3d3d45bc50c082b2e71c7339c7060f633f868db2065ef611885abe37e" - }, - "0x7a19252e8c9b457eb07f52d0ddbe16820b5b7830": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xab7bdc41a80ae9c8fcb9426ba716d8d47e523f94ffb4b9823512d259c9eca8cd" - }, - "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x71dee9adfef0940a36336903bd6830964865180b98c0506f9bf7ba8f2740fbf9" - }, - "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfcc08928955d4e5e17e17e46d5adbb8011e0a8a74cabbdd3e138c367e89a4428" - }, - "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x55d0609468d8d4147a942e88cfc5f667daff850788d821889fbb03298924767c" - }, - "0x7d80ad47bf8699f49853640b12ee55b1f51691f1": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x65cf42efacdee07ed87a1c2de0752a4e3b959f33f9f9f8c77424ba759e01fcf2" - }, - "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7c3e44534b1398abc786e4591364c329e976dbde3b3ed3a4d55589de84bcb9a6" - }, - "0x7dcef881c305fb208500cc9509db689047ed0967": { - "balance": "0", - "nonce": 1, - "root": "0x6d2b8a074c78a0e5a8095d7a010d4961c639c541cf56fbb7049480cc8f199765", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001bc": "01bc", - "0x00000000000000000000000000000000000000000000000000000000000001bd": "01bd", - "0x00000000000000000000000000000000000000000000000000000000000001be": "01be" - }, - "key": "0x68fc814efedf52ac8032da358ddcb61eab4138cb56b536884b86e229c995689c" - }, - "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe04fdefc4f2eefd22721d5944411b282d0fcb1f9ac218f54793a35bca8199c25" - }, - "0x7f774bb46e7e342a2d9d0514b27cee622012f741": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x720f25b62fc39426f70eb219c9dd481c1621821c8c0fa5367a1df6e59e3edf59" - }, - "0x7fd02a3bb5d5926d4981efbf63b66de2a7b1aa63": { - "balance": "0", - "nonce": 1, - "root": "0x7bf542bdaff5bfe3d33c26a88777773b5e525461093c36acb0dab591a319e509", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000032": "32", - "0x0000000000000000000000000000000000000000000000000000000000000033": "33", - "0x0000000000000000000000000000000000000000000000000000000000000034": "34" - }, - "key": "0xfc3d2e27841c0913d10aa11fc4af4793bf376efe3d90ce8360aa392d0ecefa24" - }, - "0x8074971c7d405ba1e70af34f5af7d564ddc495df": { - "balance": "0", - "nonce": 1, - "root": "0x60fc69100d8e632667c80b94d434008823ed75416b71cbd112b4d0b02f563027", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000a4": "a4", - "0x00000000000000000000000000000000000000000000000000000000000000a5": "a5", - "0x00000000000000000000000000000000000000000000000000000000000000a6": "a6" - }, - "key": "0x0e0e4646090b881949ec9991e48dec768ccd1980896aefd0d51fd56fd5689790" - }, - "0x8120ff763f8283e574fc767702056b57fcc89003": { - "balance": "0", - "nonce": 1, - "root": "0xa2e7084ba9cec179519c7e8950c66ad3cba8586a60cff9f4d60c188dd621522a", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000037": "37", - "0x0000000000000000000000000000000000000000000000000000000000000038": "38", - "0x0000000000000000000000000000000000000000000000000000000000000039": "39" - }, - "key": "0x48e291f8a256ab15da8401c8cae555d5417a992dff3848926fa5b71655740059" - }, - "0x8176caac8654abc74a905b137a37ecf7be2a9e95": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc4bab059ee8f7b36c82ada44d22129671d8f47f254ca6a48fded94a8ff591c88" - }, - "0x81bda6e29da8c3e4806b64dfa1cd32cd9c8fa70e": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd5e5e7be8a61bb5bfa271dfc265aa9744dea85de957b6cffff0ecb403f9697db" - }, - "0x828a91cb304a669deff703bb8506a19eba28e250": { - "balance": "0", - "nonce": 1, - "root": "0x936ac6251848da69a191cc91174e4b7583a12a43d896e243841ea98b65f264ad", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000017b": "017b", - "0x000000000000000000000000000000000000000000000000000000000000017c": "017c", - "0x000000000000000000000000000000000000000000000000000000000000017d": "017d" - }, - "key": "0xea810ea64a420acfa917346a4a02580a50483890cba1d8d1d158d11f1c59ed02" - }, - "0x82c291ed50c5f02d7e15e655c6353c9278e1bbec": { - "balance": "0", - "nonce": 1, - "root": "0x12de4544640fc8a027e1a912d776b90675bebfd50710c2876b2a24ec9eced367", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000cc": "cc", - "0x00000000000000000000000000000000000000000000000000000000000000cd": "cd", - "0x00000000000000000000000000000000000000000000000000000000000000ce": "ce" - }, - "key": "0xa9970b3744a0e46b248aaf080a001441d24175b5534ad80755661d271b976d67" - }, - "0x83c7e323d189f18725ac510004fdc2941f8c4a78": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb17ea61d092bd5d77edd9d5214e9483607689cdcc35a30f7ea49071b3be88c64" - }, - "0x847f88846c35337cbf57e37ffc18316a99ac2f14": { - "balance": "0", - "nonce": 1, - "root": "0x310a2ac83d7e3e4d333102b1f7153bb0416b38427eb2e335dc6632d779a8b4af", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000bd": "bd", - "0x00000000000000000000000000000000000000000000000000000000000000be": "be", - "0x00000000000000000000000000000000000000000000000000000000000000bf": "bf" - }, - "key": "0xbea55c1dc9f4a9fb50cbedc70448a4e162792b9502bb28b936c7e0a2fd7fe41d" - }, - "0x84873854dba02cf6a765a6277a311301b2656a7f": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x3197690074092fe51694bdb96aaab9ae94dac87f129785e498ab171a363d3b40" - }, - "0x84e75c28348fb86acea1a93a39426d7d60f4cc46": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5162f18d40405c59ef279ad71d87fbec2bbfedc57139d56986fbf47daf8bcbf2" - }, - "0x85f97e04d754c81dac21f0ce857adc81170d08c6": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2baa718b760c0cbd0ec40a3c6df7f2948b40ba096e6e4b116b636f0cca023bde" - }, - "0x8642821710100a9a3ab10cd4223278a713318096": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4fbc5fc8df4f0a578c3be3549f1cb3ef135cbcdf75f620c7a1d412462e9b3b94" - }, - "0x8749e96779cd1b9fa62b2a19870d9efc28acae09": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa3d8baf7ae7c96b1020753d12154e28cc7206402037c28c49c332a08cf7c4b51" - }, - "0x87610688d55c08238eacf52864b5a5920a00b764": { - "balance": "0", - "nonce": 1, - "root": "0x2da86eb3d4ffdd895170bc7ef02b69a116fe21ac2ce45a3ed8e0bb8af17cf92b", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000fe": "fe", - "0x00000000000000000000000000000000000000000000000000000000000000ff": "ff", - "0x0000000000000000000000000000000000000000000000000000000000000100": "0100" - }, - "key": "0x80a2c1f38f8e2721079a0de39f187adedcb81b2ab5ae718ec1b8d64e4aa6930e" - }, - "0x878dedd9474cfa24d91bccc8b771e180cf01ac40": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7e1ef9f8d2fa6d4f8e6717c3dcccff352ea9b8b46b57f6106cdbeed109441799" - }, - "0x882e7e5d12617c267a72948e716f231fa79e6d51": { - "balance": "0", - "nonce": 0, - "root": "0x491b2cfba976b2e78bd9be3bc15c9964927205fc34c9954a4d61bbe8170ba533", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000005": "05", - "0x0000000000000000000000000000000000000000000000000000000000000006": "06", - "0x0000000000000000000000000000000000000000000000000000000000000007": "07" - }, - "key": "0xd2501ae11a14bf0c2283a24b7e77c846c00a63e71908c6a5e1caff201bad0762" - }, - "0x88654f0e7be1751967bba901ed70257a3cb79940": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x30ce5b7591126d5464dfb4fc576a970b1368475ce097e244132b06d8cc8ccffe" - }, - "0x892f60b39450a0e770f00a836761c8e964fd7467": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x74614a0c4ba7d7c70b162dad186b6cc77984ab4070534ad9757e04a5b776dcc8" - }, - "0x8a5edab282632443219e051e4ade2d1d5bbc671c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc251a3acb75a90ff0cdca31da1408a27ef7dcaa42f18e648f2be1a28b35eac32" - }, - "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x17984cc4b4aac0492699d37662b53ec2acf8cbe540c968b817061e4ed27026d0" - }, - "0x8a8950f7623663222542c9469c73be3c4c81bbdf": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xaef83ad0ab332330a20e88cd3b5a4bcf6ac6c175ee780ed4183d11340df17833" - }, - "0x8ba7e4a56d8d4a4a2fd7d0c8b9e6f032dc76cefb": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x72e962dfe7e2828809f5906996dedeba50950140555b193fceb94f12fd6f0a22" - }, - "0x8bebc8ba651aee624937e7d897853ac30c95a067": { - "balance": "1", - "nonce": 1, - "root": "0xbe3d75a1729be157e79c3b77f00206db4d54e3ea14375a015451c88ec067c790", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "01", - "0x0000000000000000000000000000000000000000000000000000000000000002": "02", - "0x0000000000000000000000000000000000000000000000000000000000000003": "03" - }, - "key": "0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099" - }, - "0x8cf42eb93b1426f22a30bd22539503bdf838830c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0267c643f67b47cac9efacf6fcf0e4f4e1b273a727ded155db60eb9907939eb6" - }, - "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb8d9b988ed60dbf5dca3e9d169343ca667498605f34fb6c30b45b2ed0f996f1a" - }, - "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc13c19f53ce8b6411d6cdaafd8480dfa462ffdf39e2eb68df90181a128d88992" - }, - "0x8fa24283a8c1cc8a0f76ac69362139a173592567": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xefaff7acc3ad3417517b21a92187d2e63d7a77bc284290ed406d1bc07ab3d885" - }, - "0x8fb778e47caf2df14eca7a389955ca74ac8f4924": { - "balance": "0", - "nonce": 1, - "root": "0xae2e7f1c933c6ca84ce8be811ef411dee773fb69508056d72448048ea1db5c47", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001ee": "01ee", - "0x00000000000000000000000000000000000000000000000000000000000001ef": "01ef", - "0x00000000000000000000000000000000000000000000000000000000000001f0": "01f0" - }, - "key": "0x4973f6aa8cf5b1190fc95379aa01cff99570ee6b670725880217237fb49e4b24" - }, - "0x90fd8e600ae1a7c69fa6ef2c537b533ca77366e8": { - "balance": "0", - "nonce": 1, - "root": "0xee9821621aa5ec9ab7d5878b2a995228adcdcacb710df522d2f91b434d3bdc79", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000c2": "c2", - "0x00000000000000000000000000000000000000000000000000000000000000c3": "c3", - "0x00000000000000000000000000000000000000000000000000000000000000c4": "c4" - }, - "key": "0xbfaac98225451c56b2f9aec858cffc1eb253909615f3d9617627c793b938694f" - }, - "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xcb54add475a18ea02ab1adf9e2e73da7f23ecd3e92c4fa8ca4e8f588258cb5d3" - }, - "0x923f800cf288500f8e53f04e4698c9b885dcf030": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb91824b28183c95881ada12404d5ee8af8123689a98054d41aaf4dd5bec50e90" - }, - "0x9344b07175800259691961298ca11c824e65032d": { - "balance": "0", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0x8e0388ecf64cfa76b3a6af159f77451519a7f9bb862e4cce24175c791fdcb0df", - "code": "0x60004381526020014681526020014181526020014881526020014481526020013281526020013481526020016000f3", - "key": "0x2e6fe1362b3e388184fd7bf08e99e74170b26361624ffd1c5f646da7067b58b6" - }, - "0x93747f73c18356c6b202f527f552436a0e06116a": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x73cd1b7cd355f3f77c570a01100a616757408bb7abb78fe9ee1262b99688fcc4" - }, - "0x9380b994c5738f68312f0e517902da81f63cdcfa": { - "balance": "0", - "nonce": 1, - "root": "0x51b829f0f2c3de9cfbd94e47828a89940c329a49cd59540ca3c6d751a8d214d6", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000135": "0135", - "0x0000000000000000000000000000000000000000000000000000000000000136": "0136", - "0x0000000000000000000000000000000000000000000000000000000000000137": "0137" - }, - "key": "0x50d83ef5194d06752cd5594b57e809b135f24eedd124a51137feaaf049bc2efd" - }, - "0x94d068bff1af651dd9d9c2e75adfb7eec6f66be7": { - "balance": "0", - "nonce": 1, - "root": "0x0754035aa4073381a211342b507de8e775c97c961096e6e2275df0bfcbb3a01c", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000059": "59", - "0x000000000000000000000000000000000000000000000000000000000000005a": "5a", - "0x000000000000000000000000000000000000000000000000000000000000005b": "5b" - }, - "key": "0x0cd2a7c53c76f228ed3aa7a29644b1915fde9ec22e0433808bf5467d914e7c7a" - }, - "0x956062137518b270d730d4753000896de17c100a": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5aa3b4a2ebdd402721c3953b724f4fe90900250bb4ef89ce417ec440da318cd6" - }, - "0x96a1cabb97e1434a6e23e684dd4572e044c243ea": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe7c6828e1fe8c586b263a81aafc9587d313c609c6db8665a42ae1267cd9ade59" - }, - "0x984c16459ded76438d98ce9b608f175c28a910a0": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4b9f335ce0bdffdd77fdb9830961c5bc7090ae94703d0392d3f0ff10e6a4fbab" - }, - "0x99a1c0703485b331fa0302d6077b583082e242ea": { - "balance": "0", - "nonce": 1, - "root": "0x2cf292c1e382bdd0e72e126701d7b02484e6e272f4c0d814f5a6fae233fc7935", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000121": "0121", - "0x0000000000000000000000000000000000000000000000000000000000000122": "0122", - "0x0000000000000000000000000000000000000000000000000000000000000123": "0123" - }, - "key": "0x734ee4981754a3f1403c4e8887d35addfb31717d93de3e00ede78368c230861e" - }, - "0x99d40a710cb552eaaee1599d4040055859b1610d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x946bfb429d90f1b39bb47ada75376a8d90a5778068027d4b8b8514ac13f53eca" - }, - "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd16e029e8c67c3f330cddaa86f82d31f523028404dfccd16d288645d718eb9da" - }, - "0x9ae62b6d840756c238b5ce936b910bb99d565047": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8989651e80c20af78b37fdb693d74ecafc9239426ff1315e1fb7b674dcdbdb75" - }, - "0x9b3cf956056937dfb6f9e3dc02e3979a4e421c0a": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb1b2c1c59637202bb0e0d21255e44e0df719fe990be05f213b1b813e3d8179d7" - }, - "0x9bb981f592bc1f9c31db67f30bbf1ff44b649886": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1ee7e0292fba90d9733f619f976a2655c484adb30135ef0c5153b5a2f32169df" - }, - "0x9bfb328671c108c9ba4d45734d9f4462d8c9a9cb": { - "balance": "0", - "nonce": 1, - "root": "0xc15b43e5f4853ec8da53ebde03de87b94afce42a9c02f648ad8bdb224604c4ad", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001da": "01da", - "0x00000000000000000000000000000000000000000000000000000000000001db": "01db", - "0x00000000000000000000000000000000000000000000000000000000000001dc": "01dc" - }, - "key": "0xa683478d0c949580d5738b490fac8129275bb6e921dfe5eae37292be3ee281b9" - }, - "0x9defb0a9e163278be0e05aa01b312ec78cfa3726": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb31919583a759b75e83c14d00d0a89bb36adc452f73cee2933a346ccebaa8e31" - }, - "0x9e59004e909ff011e5882332e421b6772e68ed10": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x3897cb9b6f68765022f3c74f84a9f2833132858f661f4bc91ccd7a98f4e5b1ee" - }, - "0x9f50ec6c8a595869d71ce8c3b1c17c02599a5cc3": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2705244734f69af78e16c74784e1dc921cb8b6a98fe76f577cc441c831e973bf" - }, - "0xa0794cd73f564baeeda23fa4ce635a3f8ae39621": { - "balance": "0", - "nonce": 1, - "root": "0xfb79021e7fa54b9bd2df64f6db57897d52ae85f7c195af518de48200a1325e2c", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000ef": "ef", - "0x00000000000000000000000000000000000000000000000000000000000000f0": "f0", - "0x00000000000000000000000000000000000000000000000000000000000000f1": "f1" - }, - "key": "0x60535eeb3ffb721c1688b879368c61a54e13f8881bdef6bd4a17b8b92e050e06" - }, - "0xa12b147dd542518f44f821a4d436066c64932b0d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xae88076d02b19c4d09cb13fca14303687417b632444f3e30fc4880c225867be3" - }, - "0xa179dbdd51c56d0988551f92535797bcf47ca0e7": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6d1da4cf1127d654ed731a93105f481b315ecfc2f62b1ccb5f6d2717d6a40f9b" - }, - "0xa1fce4363854ff888cff4b8e7875d600c2682390": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xad99b5bc38016547d5859f96be59bf18f994314116454def33ebfe9a892c508a" - }, - "0xa225fe6df11a4f364234dd6a785a17cd38309acb": { - "balance": "0", - "nonce": 1, - "root": "0xc1686045288a5952ad57de0e971bd25007723c9f749f49f391e715c27bf526c8", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000072": "72", - "0x0000000000000000000000000000000000000000000000000000000000000073": "73", - "0x0000000000000000000000000000000000000000000000000000000000000074": "74" - }, - "key": "0x4e0ab2902f57bf2a250c0f87f088acc325d55f2320f2e33abd8e50ba273c9244" - }, - "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfb9474d0e5538fcd99e8d8d024db335b4e057f4bcd359e85d78f4a5226b33272" - }, - "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6188c4510d25576535a642b15b1dbdb8922fe572b099f504390f923c19799777" - }, - "0xa64f449891f282b87e566036f981023dba4ed477": { - "balance": "0", - "nonce": 1, - "root": "0x61176dbc05a8537d8de85f82a03b8e1049cea7ad0a9f0e5b60ee15fca6fe0d42", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000012b": "012b", - "0x000000000000000000000000000000000000000000000000000000000000012c": "012c", - "0x000000000000000000000000000000000000000000000000000000000000012d": "012d" - }, - "key": "0x7c1edabb98857d64572f03c64ac803e4a14b1698fccffffd51675d99ee3ba217" - }, - "0xa6515a495ec7723416665ebb54fc002bf1e9a873": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xbbdc59572cc62c338fb6e027ab00c57cdeed233c8732680a56a5747141d20c7c" - }, - "0xa6a54695341f038ad15e9e32f1096f5201236512": { - "balance": "0", - "nonce": 1, - "root": "0xe2a72f5bfbeba70fc9ab506237ba27c096a4e96c3968cabf5b1b2fb54431b5cf", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000023": "23", - "0x0000000000000000000000000000000000000000000000000000000000000024": "24", - "0x0000000000000000000000000000000000000000000000000000000000000025": "25" - }, - "key": "0xa87387b50b481431c6ccdb9ae99a54d4dcdd4a3eff75d7b17b4818f7bbfc21e9" - }, - "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x02547b56492bfe767f3d18be2aab96441c449cd945770ef7ef8555acc505b2e4" - }, - "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x913e2a02a28d71d595d7216a12311f6921a4caf40aeabf0f28edf937f1df72b4" - }, - "0xa92bb60b61e305ddd888015189d6591b0eab0233": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xdd1589b1fe1d9b4ca947f98ff324de7887af299d5490ed92ae40e95eec944118" - }, - "0xa956ca63bf28e7da621475d6b077da1ab9812b3a": { - "balance": "0", - "nonce": 1, - "root": "0xa090b66fbca46cb71abd1daa8d419d2c6e291094f52872978dfcb1c31ad7a900", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001e4": "01e4", - "0x00000000000000000000000000000000000000000000000000000000000001e5": "01e5", - "0x00000000000000000000000000000000000000000000000000000000000001e6": "01e6" - }, - "key": "0xaad7b91d085a94c11a2f7e77dc95cfcfc5daf4f509ca4e0c0e493b86c6cbff78" - }, - "0xaa0d6dfdb7588017c80ea088768a5f3d0cdeacdb": { - "balance": "0", - "nonce": 1, - "root": "0x89ecb0ceeea20ccd7d1b18cf1d35b7a2fd7b76ddc8d627f43304ed8b31b01248", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000144": "0144", - "0x0000000000000000000000000000000000000000000000000000000000000145": "0145", - "0x0000000000000000000000000000000000000000000000000000000000000146": "0146" - }, - "key": "0xb990eaca858ea15fda296f3f47baa2939e8aa8bbccc12ca0c3746d9b5d5fb2ae" - }, - "0xaa53ff4bb2334faf9f4447197ef69c39c0bb1379": { - "balance": "0", - "nonce": 1, - "root": "0xe547c0050253075b1be4210608bc639cffe70110194c316481235e738be961e7", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000ea": "ea", - "0x00000000000000000000000000000000000000000000000000000000000000eb": "eb", - "0x00000000000000000000000000000000000000000000000000000000000000ec": "ec" - }, - "key": "0xed263a22f0e8be37bcc1873e589c54fe37fdde92902dc75d656997a7158a9d8c" - }, - "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5a4a3feecfc77b402e938e28df0c4cbb874771cb3c5a92524f303cffb82a2862" - }, - "0xab12a5f97f03edbff03eded9d1a2a1179d2fc69e": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xba1d0afdfee510e8852f24dff964afd824bf36d458cf5f5d45f02f04b7c0b35d" - }, - "0xab557835ab3e5c43bf34ac9b2ab730c5e0bc9967": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc9ea69dc9e84712b1349c9b271956cc0cb9473106be92d7a937b29e78e7e970e" - }, - "0xab9025d4a9f93c65cd4fe978d38526860af0aa62": { - "balance": "0", - "nonce": 1, - "root": "0x4ce79cd9645650f0a00effa86f6fea733cecea9ea26964828ff25cf0577bc974", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000009a": "9a", - "0x000000000000000000000000000000000000000000000000000000000000009b": "9b", - "0x000000000000000000000000000000000000000000000000000000000000009c": "9c" - }, - "key": "0x17350c7adae7f08d7bbb8befcc97234462831638443cd6dfea186cbf5a08b7c7" - }, - "0xabd693b23d55dec7d0d0cba2ecbc9298dc4edf02": { - "balance": "0", - "nonce": 1, - "root": "0xafd54e81f3e415407f0812a678856f1b4068ed64a08b3f3bf5b2190fcfb2322d", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001b7": "01b7", - "0x00000000000000000000000000000000000000000000000000000000000001b8": "01b8", - "0x00000000000000000000000000000000000000000000000000000000000001b9": "01b9" - }, - "key": "0xbe7d987a9265c0e44e9c5736fb2eb38c41973ce96e5e8e6c3c713f9d50a079ff" - }, - "0xabe2b033c497e091c1e494c98c178e8aa06bcb00": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x2374954008440ca3d17b1472d34cc52a6493a94fb490d5fb427184d7d5fd1cbf" - }, - "0xac4d51af4cb7bab4743fa57bc80b144d7a091268": { - "balance": "0", - "nonce": 1, - "root": "0xfb00729a5f4f9a2436b999aa7159497a9cd88d155770f873a818b55052c5f067", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000149": "0149", - "0x000000000000000000000000000000000000000000000000000000000000014a": "014a", - "0x000000000000000000000000000000000000000000000000000000000000014b": "014b" - }, - "key": "0xe42a85d04a1d0d9fe0703020ef98fa89ecdeb241a48de2db73f2feeaa2e49b0f" - }, - "0xac7d8d5f6be7d251ec843ddbc09095150df59965": { - "balance": "0", - "nonce": 1, - "root": "0xa9580109be2f7d35b5360050c2ced74e5d4dea2f82d46e8d266ed89157636004", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000046": "46", - "0x0000000000000000000000000000000000000000000000000000000000000047": "47", - "0x0000000000000000000000000000000000000000000000000000000000000048": "48" - }, - "key": "0x943f42ad91e8019f75695946d491bb95729f0dfc5dbbb953a7239ac73f208943" - }, - "0xac9e61d54eb6967e212c06aab15408292f8558c4": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf2b9bc1163840284f3eb15c539972edad583cda91946f344f4cb57be15af9c8f" - }, - "0xaceac762ff518b4cf93a6eebbc55987e7b79b2ce": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1960414a11f8896c7fc4243aba7ed8179b0bc6979b7c25da7557b17f5dee7bf7" - }, - "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x58e416a0dd96454bd2b1fe3138c3642f5dee52e011305c5c3416d97bc8ba5cf0" - }, - "0xad108e31c9632ad9e20614b3ca40644d32948dbb": { - "balance": "0", - "nonce": 1, - "root": "0x2625f8a23d24a5dff6a79f632b1020593362a6ac622fa5237460bc67b0aa0ed3", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001a3": "01a3", - "0x00000000000000000000000000000000000000000000000000000000000001a4": "01a4", - "0x00000000000000000000000000000000000000000000000000000000000001a5": "01a5" - }, - "key": "0xdce547cc70c79575ef72c061502d6066db1cbce200bd904d5d2b20d4f1cb5963" - }, - "0xae3f4619b0413d70d3004b9131c3752153074e45": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb1b2fd7758f73e25a2f9e72edde82995b2b32ab798bcffd2c7143f2fc8196fd8" - }, - "0xae58b7e08e266680e93e46639a2a7e89fde78a6f": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe09e5f27b8a7bf61805df6e5fefc24eb6894281550c2d06250adecfe1e6581d7" - }, - "0xaf17b30f5ab8e6a4d7a563bdb0194f3e0bd50209": { - "balance": "0", - "nonce": 1, - "root": "0x2434bfc643ec364116cd71519a397662b20c52d1adcff0b830e80a738e19f30e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000b8": "b8", - "0x00000000000000000000000000000000000000000000000000000000000000b9": "b9", - "0x00000000000000000000000000000000000000000000000000000000000000ba": "ba" - }, - "key": "0x26ce7d83dfb0ab0e7f15c42aeb9e8c0c5dba538b07c8e64b35fb64a37267dd96" - }, - "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1a28912018f78f7e754df6b9fcec33bea25e5a232224db622e0c3343cf079eff" - }, - "0xaf2c6f1512d1cabedeaf129e0643863c57419732": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xad6a4a6ebd5166c9b5cc8cfbaec176cced40fa88c73d83c67f0c3ed426121ebc" - }, - "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x053df2c3b574026812b154a99b13b626220af85cd01bb1693b1d42591054bce6" - }, - "0xb0ee91ba61e8a3914a7eab120786e9e61bfe4faf": { - "balance": "0", - "nonce": 1, - "root": "0xa14913d548ac1d3f9962a21a569fe52f1436b6d2f5ea4e36de13ea855ede54e0", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000068": "68", - "0x0000000000000000000000000000000000000000000000000000000000000069": "69", - "0x000000000000000000000000000000000000000000000000000000000000006a": "6a" - }, - "key": "0x4bd8ef9873a5e85d4805dbcb0dbf6810e558ea175167549ef80545a9cafbb0e1" - }, - "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4ccd31891378d2025ef58980481608f11f5b35a988e877652e7cbb0a6127287c" - }, - "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xdef989cb85107747de11222bd7418411f8f3264855e1939ef6bef9447e42076d" - }, - "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb7c2ef96238f635f86f9950700e36368efaaa70e764865dddc43ff6e96f6b346" - }, - "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x92b13a73440c6421da22e848d23f9af80610085ab05662437d850c97a012d8d3" - }, - "0xb55a3d332d267493105927b892545d2cd4c83bd6": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc781c7c3babeb06adfe8f09ecb61dbe0eb671e41f3a1163faac82fdfa2bc83e8" - }, - "0xb609bc528052bd9669595a35f6eb6a4d7a30ac3d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe6388bfcbbd6000e90a10633c72c43b0b0fed7cf38eab785a71e6f0c5b80a26a" - }, - "0xb68176634dde4d9402ecb148265db047d17cb4ab": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf4a1c4554b186a354b3e0c467eef03df9907cd5a5d96086c1a542b9e5160ca78" - }, - "0xb70654fead634e1ede4518ef34872c9d4f083a53": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7f9726a7b2f5f3a501b2d7b18ec726f25f22c86348fae0f459d882ec5fd7d0c7" - }, - "0xb71de80778f2783383f5d5a3028af84eab2f18a4": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x64d0de66ea29cbcf7f237dae1c5f883fa6ff0ba52b90f696bb0348224dbc82ce" - }, - "0xb787c848479278cfdb56950cda545cd45881722d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1098f06082dc467088ecedb143f9464ebb02f19dc10bd7491b03ba68d751ce45" - }, - "0xb911abeead298d03c21c6c5ff397cd80eb375d73": { - "balance": "0", - "nonce": 1, - "root": "0x54abcdbc8b04bc9b70e9bd46cb9db9b8eb08cfd4addba4c941dacc34dd28648e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000054": "54", - "0x0000000000000000000000000000000000000000000000000000000000000055": "55", - "0x0000000000000000000000000000000000000000000000000000000000000056": "56" - }, - "key": "0x873429def7829ff8227e4ef554591291907892fc8f3a1a0667dada3dc2a3eb84" - }, - "0xb917b7f3d49770d3d2f0ad2f497e5bfe0f25dc5f": { - "balance": "0", - "nonce": 1, - "root": "0x11d4eec7df52cd54e74690a487884e56371976c2b8c49ffc4c8f34831166bf4e", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000162": "0162", - "0x0000000000000000000000000000000000000000000000000000000000000163": "0163", - "0x0000000000000000000000000000000000000000000000000000000000000164": "0164" - }, - "key": "0x65e6b6521e4f1f97e80710581f42063392c9b33e0aeea4081a102a32238992ea" - }, - "0xb9b85616fc8ed95979a5e31b8968847e7518b165": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6a5e43139d88da6cfba857e458ae0b5359c3fde36e362b6e5f782a90ce351f14" - }, - "0xbac9d93678c9b032c393a23e4c013e37641ad850": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8a8266874b43f78d4097f27b2842132faed7e7e430469eec7354541eb97c3ea0" - }, - "0xbbeebd879e1dff6918546dc0c179fdde505f2a21": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x170c927130fe8f1db3ae682c22b57f33f54eb987a7902ec251fe5dba358a2b25" - }, - "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe74ac72f03e8c514c2c75f3c4f54ba31e920374ea7744ef1c33937e64c7d54f1" - }, - "0xbc5959f43bc6e47175374b6716e53c9a7d72c594": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfd3a8bacd3b2061cbe54f8d38cf13c5c87a92816937683652886dee936dfae10" - }, - "0xbceef655b5a034911f1c3718ce056531b45ef03b": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6c05d8abc81143ce7c7568c98aadfe6561635c049c07b2b4bce3019cef328cb9" - }, - "0xbd079b0337a29cccd2ec95b395ef5c01e992b6a5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf0877d51b7712e08f2a3c96cddf50ff61b8b90f80b8b9817ea613a8a157b0c45" - }, - "0xbe3eea9a483308cb3134ce068e77b56e7c25af19": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7026c939a9158beedff127a64f07a98b328c3d1770690437afdb21c34560fc57" - }, - "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x72d91596112f9d7e61d09ffa7575f3587ad9636172ae09641882761cc369ecc0" - }, - "0xc18d2be47547904f88a4f46cee75f8f4a94e1807": { - "balance": "0", - "nonce": 1, - "root": "0x9c32ffd5059115bba9aed9174f5ab8b4352e3f51a85dde33000f703c9b9fe7c2", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000018a": "018a", - "0x000000000000000000000000000000000000000000000000000000000000018b": "018b", - "0x000000000000000000000000000000000000000000000000000000000000018c": "018c" - }, - "key": "0xa601eb611972ca80636bc39087a1dae7be5a189b94bda392f84d6ce0d3c866b9" - }, - "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x99dba7e9230d5151cc37ff592fa1592f27c7c81d203760dfaf62ddc9f3a6b8fd" - }, - "0xc305dd6cfc073cfe5e194fc817536c419410a27d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x016d92531f4754834b0502de5b0342ceff21cde5bef386a83d2292f4445782c2" - }, - "0xc337ded6f56c07205fb7b391654d7d463c9e0c72": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7c608293e741d1eb5ae6916c249a87b6540cf0c2369e96d293b1a7b5b9bd8b31" - }, - "0xc57aa6a4279377063b17c554d3e33a3490e67a9a": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc192ea2d2bb89e9bb7f17f3a282ebe8d1dd672355b5555f516b99b91799b01f6" - }, - "0xc5eaec262d853fbdaccca406cdcada6fa6dd0944": { - "balance": "0", - "nonce": 1, - "root": "0x471bf8988ad0d7602d6bd5493c08733096c116ac788b76f22a682bc4558e3aa7", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000158": "0158", - "0x0000000000000000000000000000000000000000000000000000000000000159": "0159", - "0x000000000000000000000000000000000000000000000000000000000000015a": "015a" - }, - "key": "0x580aa878e2f92d113a12c0a3ce3c21972b03dbe80786858d49a72097e2c491a3" - }, - "0xc7a0a19ea8fc63cc6021af2e11ac0584d75c97b7": { - "balance": "0", - "nonce": 1, - "root": "0xe2a164e2c30cf30391c88ff32a0e202194b08f2a61a9cd2927ea5ed6dfbf1056", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000e5": "e5", - "0x00000000000000000000000000000000000000000000000000000000000000e6": "e6", - "0x00000000000000000000000000000000000000000000000000000000000000e7": "e7" - }, - "key": "0x86d03d0f6bed220d046a4712ec4f451583b276df1aed33f96495d22569dc3485" - }, - "0xc7b99a164efd027a93f147376cc7da7c67c6bbe0": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x8e11480987056c309d7064ebbd887f086d815353cdbaadb796891ed25f8dcf61" - }, - "0xc7d4ef05550c226c50cf0d4231ba1566d03fa98d": { - "balance": "0", - "nonce": 1, - "root": "0x3a2985c6ada67e5604b99fa2fc1a302abd0dc241ee7f14c428fa67d476868bb6", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000010d": "010d", - "0x000000000000000000000000000000000000000000000000000000000000010e": "010e", - "0x000000000000000000000000000000000000000000000000000000000000010f": "010f" - }, - "key": "0x5a356862c79afffd6a01af752d950e11490146e4d86dfb8ab1531e9aef4945a1" - }, - "0xca358758f6d27e6cf45272937977a748fd88391d": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xbccd3d2f920dfb8d70a38c9ccd5ed68c2ef6e3372199381767ce222f13f36c87" - }, - "0xca87240ef598bd6e4b8f67b3761af07d5f575514": { - "balance": "0", - "nonce": 1, - "root": "0x11f5d399ca8fb7a9af5ad481be60cf61d45493cd20206c9d0a237ce7d7571e5f", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001f3": "01f3", - "0x00000000000000000000000000000000000000000000000000000000000001f4": "01f4", - "0x00000000000000000000000000000000000000000000000000000000000001f5": "01f5" - }, - "key": "0x4b238e08b80378d0815e109f350a08e5d41ec4094df2cfce7bc8b9e3115bda70" - }, - "0xcb925b74da97bdff2130523c2a788d4beff7b3c3": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe0c5acf66bda927704953fdf7fb4b99e116857121c069eca7fb9bd8acfc25434" - }, - "0xcccc369c5141675a9e9b1925164f30cdd60992dc": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfe2511e8a33ac9973b773aaedcb4daa73ae82481fe5a1bf78b41281924260cf5" - }, - "0xce24f30695b735e48b67467d76f5185ee3c7a0c5": { - "balance": "0", - "nonce": 1, - "root": "0x5442e0279d3f1149de4ce8d9e2d3f01d1854755038ac1a0fae5c48749bf71f20", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001e9": "01e9", - "0x00000000000000000000000000000000000000000000000000000000000001ea": "01ea", - "0x00000000000000000000000000000000000000000000000000000000000001eb": "01eb" - }, - "key": "0x47450e5beefbd5e3a3f80cbbac474bb3db98d5e609aa8d15485c3f0d733dea3a" - }, - "0xd048d242574c45095c72eaf58d2808778117afcb": { - "balance": "0", - "nonce": 1, - "root": "0x7217cb747054306f826e78aa3fc68fe4441299a337ecea1d62582f2da8a7f336", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001a8": "01a8", - "0x00000000000000000000000000000000000000000000000000000000000001a9": "01a9", - "0x00000000000000000000000000000000000000000000000000000000000001aa": "01aa" - }, - "key": "0xa9656c0192bb27f0ef3f93ecc6cc990dd146da97ac11f3d8d0899fba68d5749a" - }, - "0xd0752b60adb148ca0b3b4d2591874e2dabd34637": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x625e5c85d5f4b6385574b572709d0f704b097527a251b7c658c0c4441aef2af6" - }, - "0xd089c853b406be547d8e331d31cbd5c4d472a349": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x389093badcaa24c3a8cbb4461f262fba44c4f178a162664087924e85f3d55710" - }, - "0xd0918e2e24c5ddc0557a61ca11e055d2ac210fe5": { - "balance": "0", - "nonce": 1, - "root": "0x25b42ec5480843a0328c63bc50eff8595d90f1d1b0afcab2f4a19b888c794f37", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000a9": "a9", - "0x00000000000000000000000000000000000000000000000000000000000000aa": "aa", - "0x00000000000000000000000000000000000000000000000000000000000000ab": "ab" - }, - "key": "0xbaae09901e990935de19456ac6a6c8bc1e339d0b80ca129b8622d989b5c79120" - }, - "0xd10b36aa74a59bcf4a88185837f658afaf3646ef": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9fe8b6e43098a4df56e206d479c06480801485dfd8ec3da4ccc3cebf5fba89a1" - }, - "0xd1211001882d2ce16a8553e449b6c8b7f71e6183": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x61088707d2910974000e63c2d1a376f4480ba19dde19c4e6a757aeb3d62d5439" - }, - "0xd1347bfa3d09ec56b821e17c905605cd5225069f": { - "balance": "0", - "nonce": 1, - "root": "0x287acc7869421fb9f49a3549b902fb01b7accc032243bd7e1accd8965d95d915", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000019e": "019e", - "0x000000000000000000000000000000000000000000000000000000000000019f": "019f", - "0x00000000000000000000000000000000000000000000000000000000000001a0": "01a0" - }, - "key": "0x5b90bb05df9514b2d8e3a8feb3d6c8c22526b02398f289b42111426edc4fe6cf" - }, - "0xd20b702303d7d7c8afe50344d66a8a711bae1425": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4d67d989fdb264fa4b2524d306f7b3f70ddce0b723411581d1740407da325462" - }, - "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x0e27113c09de0a0cb0ff268c677aba17d39a3190fe15aec0ff7f54184955cba4" - }, - "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x79afb7a5ffe6ccd537f9adff8287b78f75c37d97ea8a4dd504a08bc09926c3fa" - }, - "0xd39b94587711196640659ec81855bcf397e419ff": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa9de128e7d4347403eb97f45e969cd1882dfe22c1abe8857aab3af6d0f9e9b92" - }, - "0xd48171b7166f5e467abcba12698df579328e637d": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x188111c233bf6516bb9da8b5c4c31809a42e8604cd0158d933435cfd8e06e413" - }, - "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe1068e9986da7636501d8893f67aa94f5d73df849feab36505fd990e2d6240e9" - }, - "0xd803681e487e6ac18053afc5a6cd813c86ec3e4d": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe5302e42ca6111d3515cbbb2225265077da41d997f069a6c492fa3fcb0fdf284" - }, - "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9a1896e612ca43ecb7601990af0c3bc135b9012c50d132769dfb75d0038cc3be" - }, - "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xfc4870c3cd21d694424c88f0f31f75b2426e1530fdea26a14031ccf9baed84c4" - }, - "0xd917458e88a37b9ae35f72d4cc315ef2020b2418": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x4c2765139cace1d217e238cc7ccfbb751ef200e0eae7ec244e77f37e92dfaee5" - }, - "0xdbe726e81a7221a385e007ef9e834a975a4b528c": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x5fcd9b6fce3394ad1d44733056b3e5f6306240974a16f9de8e96ebdd14ae06b1" - }, - "0xdc60d4434411b2608150f68c4c1b818b6208acc2": { - "balance": "0", - "nonce": 1, - "root": "0x27e9b6a54cf0fb188499c508bd96d450946cd6ba1cf76cf5343b5c74450f6690", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001df": "01df", - "0x00000000000000000000000000000000000000000000000000000000000001e0": "01e0", - "0x00000000000000000000000000000000000000000000000000000000000001e1": "01e1" - }, - "key": "0x8510660ad5e3d35a30d4fb7c2615c040f9f698faae2ac48022e366deaeecbe77" - }, - "0xdd1e2826c0124a6d4f7397a5a71f633928926c06": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf0a51b55aadfa3cafdd214b0676816e574931a683f51218207c625375884e785" - }, - "0xdd9ee108e8d5d2e8937e9fd029ec3a6640708af0": { - "balance": "0", - "nonce": 1, - "root": "0x8289b558865f2ca1f54c98b5ff5df95f07c24ec605e247b58c7798605dcd794f", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001cb": "01cb", - "0x00000000000000000000000000000000000000000000000000000000000001cc": "01cc", - "0x00000000000000000000000000000000000000000000000000000000000001cd": "01cd" - }, - "key": "0x2a39afbe88f572c23c90da2d059af3de125f1da5c3753c530dc5619a4857119f" - }, - "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xbb861b82d884a70666afeb78bbf30cab7fdccf838f4d5ce5f4e5ca1be6be61b1" - }, - "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x9966a8b4cd856b175855258fa7e412ffef06d9e92b519050fa7ac06d8952ac84" - }, - "0xdfe052578c96df94fa617102199e66110181ed2c": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x54c12444ede3e2567dd7f4d9a06d4db8c6ab800d5b3863f8ff22a0db6d09bf24" - }, - "0xe3a71b4caf54df7d2480743c5a6770a1a5a9bcda": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe4d9c31cc9b4a9050bbbf77cc08ac26d134253dcb6fd994275c5c3468f5b7810" - }, - "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x70aae390a762a4347a4d167a2431874554edf1d77579213e55fea3ec39a1257c" - }, - "0xe439e4ea04e52cf38d0925f0722d341097378b88": { - "balance": "0", - "nonce": 1, - "root": "0x6c00e091dae3d4226facd6be802c865d5db0f524754d22666406138b54fab0e6", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000008b": "8b", - "0x000000000000000000000000000000000000000000000000000000000000008c": "8c", - "0x000000000000000000000000000000000000000000000000000000000000008d": "8d" - }, - "key": "0x38152bce526b7e1c2bedfc9d297250fcead02818be7806638564377af145103b" - }, - "0xe43ce33cdb88a2efe8a3d652bfb252fd91a950a7": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xc157e0d637d64b90e2c59bc8bed2acd75696ea1ac6b633661c12ce8f2bce0d62" - }, - "0xe52c0f008957444c48eba77467eaf2b7c127e3c5": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb888c9946a84be90a9e77539b5ac68a3c459761950a460f3e671b708bb39c41f" - }, - "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x519abb269c3c5710f1979ca84192e020ba5c838bdd267b2d07436a187f171232" - }, - "0xe6dddbffde545e58030d4b8ca9e00cfb68975b5d": { - "balance": "0", - "nonce": 1, - "root": "0x2afe93e1b0f26e588d2809127e4360ad7e28cf552498b2bc4847d6bcda738cdb", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000130": "0130", - "0x0000000000000000000000000000000000000000000000000000000000000131": "0131", - "0x0000000000000000000000000000000000000000000000000000000000000132": "0132" - }, - "key": "0xa0f5dc2d18608f8e522ffffd86828e3d792b36d924d5505c614383ddff9be2eb" - }, - "0xe75db02929f3d5d7c28ecdb064ece929602c06bd": { - "balance": "0", - "nonce": 1, - "root": "0x9eda8eb6ca03d7c4afe47279acc90a45d1b2ca6a11afd95206f8868d20520d06", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000001e": "1e", - "0x000000000000000000000000000000000000000000000000000000000000001f": "1f", - "0x0000000000000000000000000000000000000000000000000000000000000020": "20" - }, - "key": "0x600a7a5f41a67f6f759dcb664198f1c5d9b657fb51a870ce9e234e686dff008e" - }, - "0xe7b2ceb8674516c4aeb43979808b237656ab3b6b": { - "balance": "0", - "nonce": 1, - "root": "0xcd31ed5d5da79990afed0d993cb725c4e34dd97544b03466ed34212e42c28d68", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000014e": "014e", - "0x000000000000000000000000000000000000000000000000000000000000014f": "014f", - "0x0000000000000000000000000000000000000000000000000000000000000150": "0150" - }, - "key": "0x75d231f57a1a9751f58769d5691f4807ab31ac0e802b1a1f6bfc77f5dff0adbf" - }, - "0xe7d13f7aa2a838d24c59b40186a0aca1e21cffcc": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xec3e92967d10ac66eff64a5697258b8acf87e661962b2938a0edcd78788f360d" - }, - "0xe82c38488eded9fb72a5ed9e039404c537f20b13": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7a2464bc24d90557940e93a3b73308ea354ed7d988be720c545974a17959f93f" - }, - "0xe920ab4e34595482e98b2c0d16be164c49190546": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd623b1845175b206c127c08046281c013e4a3316402a771f1b3b77a9831143f5" - }, - "0xe99c76a6c3b831a926ab623476d2ec14560c09b4": { - "balance": "0", - "nonce": 1, - "root": "0x0fd8e99b1b4ab4eb8c6c2218221ae6978cc67433341ed8a1ad6185d34fa82c61", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000014": "14", - "0x0000000000000000000000000000000000000000000000000000000000000015": "15", - "0x0000000000000000000000000000000000000000000000000000000000000016": "16" - }, - "key": "0x6641e3ed1f264cf275b53bb7012dabecf4c1fca700e3db989e314c24cc167074" - }, - "0xe9b17e54dba3344a23160cb2b64f88024648c53e": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xb4f179efc346197df9c3a1cb3e95ea743ddde97c27b31ad472d352dba09ee1f5" - }, - "0xebe708edc62858621542b7354bb478228eb95577": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7bff1b6b56891e66584ced453d09450c2fed9453b1644e8509bef9f9dd081bbb" - }, - "0xebf37af41b6d7913aed3b9cc650d1e8f58a3d785": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x209b102e507b8dfc6acfe2cf55f4133b9209357af679a6d507e6ee87112bfe10" - }, - "0xeda8645ba6948855e3b3cd596bbb07596d59c603": { - "balance": "1000000000000000000000000000000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xabd8afe9fbf5eaa36c506d7c8a2d48a35d013472f8182816be9c833be35e50da" - }, - "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xce732a5e3b88ae26790aeb390a2bc02c449fdf57665c6d2c2b0dbce338c4377e" - }, - "0xf031efa58744e97a34555ca98621d4e8a52ceb5f": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x00748bacab20da9ae19dd26a33bd10bbf825e28b3de84fc8fe1d15a21645067f" - }, - "0xf068ae4089a66c79afe47d6e513f718838d8f73f": { - "balance": "0", - "nonce": 1, - "root": "0x72c89221daedccdd3fbba66c1b081b3634ce89d5a069be97ff7832778f7b023a", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000003c": "3c", - "0x000000000000000000000000000000000000000000000000000000000000003d": "3d", - "0x000000000000000000000000000000000000000000000000000000000000003e": "3e" - }, - "key": "0x37310559ceaade42e45b3e3f05925aadca9e60aeeb9dd60d824875d9e9e71e26" - }, - "0xf0a279d2276de583ebcd7f69a6532f13349ad656": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x11eb0304c1baa92e67239f6947cb93e485a7db05e2b477e1167a8960458fa8cc" - }, - "0xf0a5f15ef71424b5d543394ec46c46bfd2817747": { - "balance": "0", - "nonce": 1, - "root": "0xbefe55b606a865c3898ec2093bd160b37c3976011516f43736cac2a9a7ecd4ca", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000000e0": "e0", - "0x00000000000000000000000000000000000000000000000000000000000000e1": "e1", - "0x00000000000000000000000000000000000000000000000000000000000000e2": "e2" - }, - "key": "0xdbea1fd70fe1c93dfef412ce5d8565d87d6843aac044d3a015fc3db4d20a351b" - }, - "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xabdc44a9bc7ccf1ce76b942d25cd9d731425cd04989597d7a2e36423e2dac7ee" - }, - "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x728325587fa336e318b54298e1701d246c4f90d6094eb95635d8a47f080f4603" - }, - "0xf1fc98c0060f0d12ae263986be65770e2ae42eae": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xca7ad42d3c4fe14ddb81bf27d4679725a1f6c3f23b688681bb6f24262d63212f" - }, - "0xf4f97c88c409dcf3789b5b518da3f7d266c48806": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x84c7ee50e102d0abf5750e781c1635d60346f20ab0d5e5f9830db1a592c658ff" - }, - "0xf5347043ae5fca9412ca2c72aee17a1d3ba37691": { - "balance": "0", - "nonce": 1, - "root": "0xf390264acaf1433c0ea670b2c094a30076641469524ae24f5fddc44e99c5b032", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000004f": "4f", - "0x0000000000000000000000000000000000000000000000000000000000000050": "50", - "0x0000000000000000000000000000000000000000000000000000000000000051": "51" - }, - "key": "0xa5541b637a896d30688a80b7affda987d9597aac7ccd9799c15999a1d7d094e2" - }, - "0xf57fd44ccea35d9c530ef23f3e55de2f6e5415bf": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x6d4162ce16817e46fa2ddc5e70cee790b80abc3d6f7778cfbaed327c5d2af36c" - }, - "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x7e839d9fd8a767e90a8b2f48a571f111dd2451bc5910cf2bf3ae79963e47e34d" - }, - "0xf61ac2a10b7981a12822e3e48671ebd969bce9c2": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xbfe5dee42bddd2860a8ebbcdd09f9c52a588ba38659cf5e74b07d20f396e04d4" - }, - "0xf7eaadcf76ffcf006a86deb2f17d0b8fe0b211a8": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1dff76635b74ddba16bba3054cc568eed2571ea6becaabd0592b980463f157e2" - }, - "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x662d147a16d7c23a2ba6d3940133e65044a90985e26207501bfca9ae47a2468c" - }, - "0xf8d20e598df20877e4d826246fc31ffb4615cbc0": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa248850a2e0d6fe62259d33fc498203389fa754c3bd098163e86946888e455bd" - }, - "0xf91193b7442e274125c63003ee53f4ce5836f424": { - "balance": "0", - "nonce": 1, - "root": "0xb25f9e4f6f913a4a1e8debf7d4752bfa521d147bb67c69d5855301e76dd80633", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001d5": "01d5", - "0x00000000000000000000000000000000000000000000000000000000000001d6": "01d6", - "0x00000000000000000000000000000000000000000000000000000000000001d7": "01d7" - }, - "key": "0xbfe731f071443795cef55325f32e6e03c8c0d0398671548dfd5bc96b5a6555c0" - }, - "0xf997ed224012b1323eb2a6a0c0044a956c6b8070": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xbcebc35bfc663ecd6d4410ee2363e5b7741ee953c7d3359aa585095e503d20c8" - }, - "0xfb7b49bc3178263f3a205349c0e8060f44584500": { - "balance": "0", - "nonce": 1, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xa03fe040e4264070290e95ffe06bf9da0006556091f17c5df5abaa041de0c2f7" - }, - "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xf63360f8bb23f88b0a564f9e07631c38c73b4074ba4192d6131336ef02ee9cf2" - }, - "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xd3443fa37ee617edc09a9c930be4873c21af2c47c99601d5e20483ce6d01960a" - }, - "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0x1c248f110218eaae2feb51bc82e9dcc2844bf93b88172c52afcb86383d262323" - }, - "0xfde502858306c235a3121e42326b53228b7ef469": { - "balance": "1", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe3d7213321be060ae2e1ff70871131ab3e4c9f4214a17fe9441453745c29365b" - }, - "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6": { - "balance": "100000000000", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "key": "0xe31747e6542bf4351087edfbeb23e225e4217b5fa25d385f33cd024df0c9ae12" - }, - "0xfe96089d9b79f2d10f3e8b0fb9629aeb6cc7cde6": { - "balance": "0", - "nonce": 1, - "root": "0xcf2123d110997f426821d3e541334e43fdd6b5286c3c33252c24b5f8aafc7aa2", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "storage": { - "0x00000000000000000000000000000000000000000000000000000000000001d0": "01d0", - "0x00000000000000000000000000000000000000000000000000000000000001d1": "01d1", - "0x00000000000000000000000000000000000000000000000000000000000001d2": "01d2" - }, - "key": "0xbf632670b6fa18a8ad174a36180202bfef9a92c2eeda55412460491ae0f6a969" - } - } -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/newpayload.json b/builder/cmd/devp2p/internal/ethtest/testdata/newpayload.json deleted file mode 100644 index 7f8c99afa..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/newpayload.json +++ /dev/null @@ -1,13268 +0,0 @@ -[ - { - "jsonrpc": "2.0", - "id": "np72", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0x9e8a444b740df016941ecc815fe9eebeaa04a047db6569855573a52a8cb78cdd", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x74035b613e4ea1072fd029f35d0fa5b26fbfaa54cabebcec88b9ee07cca321ae", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x48", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x2d0", - "extraData": "0x", - "baseFeePerGas": "0x568d2f9", - "blockHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809", - "transactions": [ - "0xf86a39840568d2fa8252089444bd7ae60f478fae1061e11a7739f4b94d1daf9101808718e5bb3abd10a0a050fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125ca04f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np73", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0xf0a50b18d597552b6ad8a711f4ac1f7ab225d59daa74137f689256a16a0ff809", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x18b68edcdfc835d5db51310e7960eaf0c0afcc5a6611282d2085f3282b2f9e3f", - "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x49", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146e8", - "timestamp": "0x2da", - "extraData": "0x", - "baseFeePerGas": "0x4bbd14a", - "blockHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b", - "transactions": [ - "0xf8853a8404bbd14b830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a027748abc264040530bca00d1cc86b199586c1fe26955cd5e250b97e2b9ca3128a050a822d9df3b63e6911766d4ae8c722f5afee7a6c06a7b5eb73772a5b137ca36" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np74", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0x662ab680f6b14375e7642874a16a514d1ecffc9921a9d8e143b5ade129ad554b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6fb7295e0a62bff03ddeba56ba643cd817fab6bc8df11309f8e8a3dbcf7d502e", - "receiptsRoot": "0x7b9d8080a095524251324dc00e77d3ecf4c249c48eebed2e4a5acedc678c70b4", - "logsBloom": "0x000800000000000000000000000000000900000000000000000000000000c0080000000000000010000000020000000000000004100000000480008020100000000000000000000000000000001000200000000000000010000010000000000000000000000000000000000000000000000000000000000200000000000000800001000000000000000000000000000000000004000000000000000800000000008000000000000001000000000002000000000000000000000000000000080000000000000000200404000000000000000000000000000000000000000000000000080100000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4a", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc61", - "timestamp": "0x2e4", - "extraData": "0x", - "baseFeePerGas": "0x424ad37", - "blockHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13", - "transactions": [ - "0xf87c3b840424ad3883011f548080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a050e3677064fe82b08a8fae8cea250fbaf00dbca1b6921cffd311ca17c7979865a051e738138eab4b31f1ba163b8ed2cfd778af98eff583cd5a26fcd9bd673fe027" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np75", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0x9981d4e953d402b0b1554ef62ebbeb7760790a5e53191c9753329b6a3eab3d13", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x65038690e44bf1ee49d47beb6efc7cc84d7f01d2ba645768e3a584a50979b36d", - "receiptsRoot": "0xf5419129ce2f36d1b2206d4723f3e499691ad9aee741223426cda1b22e601a19", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36c", - "timestamp": "0x2ee", - "extraData": "0x", - "baseFeePerGas": "0x3a051bc", - "blockHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61", - "transactions": [ - "0xf8673c8403a051bd83020888808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0dd01417c1ac62f9e593b07848f93c1f5ab729e73a493e22141f6e1c6e8a4f94fa00b9e979c6bae8ab4a90b7b2ba61d590d800e5411bc12be320efc3fb7310506e3" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np76", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0xc5e8361f3f3ba7bfbed66940c015f351d498ed34d48f8de6e020ffffbcbbec61", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3b8d5706f2e3d66bb968de876e2683d75dce76d04118bc0184d6af44fb10196f", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x2f8", - "extraData": "0x", - "baseFeePerGas": "0x32ca5cf", - "blockHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766", - "transactions": [ - "0x02f86d870c72dd9d5e883e3d0184032ca5d08252089472dfcfb0c470ac255cde83fb8fe38de8a128188e0180c080a0116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36a017001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np77", - "method": "engine_newPayloadV1", - "params": [ - { - "parentHash": "0xcb51fdebc936f135546a0ff78a7ce246aee0a5c73b41b7accdc547825bb97766", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3b8d17721b733ce2b6e7607a69fb6bf678dbabcb708f64cb5d211915b3238090", - "receiptsRoot": "0xabc882591cb5b81b276a4e5cd873e1be7e1b4a69f630d2127f06d63c8db5acb2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146e8", - "timestamp": "0x302", - "extraData": "0x", - "baseFeePerGas": "0x2c71f92", - "blockHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e", - "transactions": [ - "0xf8853e8402c71f93830146e88080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00cb7fb1bba811ea1948e035550c66840f0491d29d0ae9a6e4726e77a57ca8058a041523fc7133a6473784720a68d7f7f1d54d8a5a1f868640783a0284fb22f4309" - ], - "withdrawals": null, - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np78", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0x49b74bc0dea88f3125f95f1eb9c0503e90440f7f23b362c4f66269a14a2dcc3e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf21b9b380d6c5833270617a17ea187e1f85a6556f1c1dfaf6bcb0700c88abe24", - "receiptsRoot": "0xb08f0ccb7116304320035e77c514c9234f2d5a916d68de82ba20f0a24ab6d9e4", - "logsBloom": "0x00000000000000400000000000200000000000000000000000000000000000000000200010000000000000000000000000000040000400000010000000000020000000000000000000000000000000000000000000000000000000900000000000800000000800000010000008000000000000000000000102000000000000100000080000000100000000000000000000000000000008000000000000008000800800000000000000000000400000000008200000000200200000000000000000000000000000200000000000000000000000000000000000000000000000000000000011000000000000800000000000000000000000000000000000000008", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4e", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x30c", - "extraData": "0x", - "baseFeePerGas": "0x26e6e24", - "blockHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c", - "transactions": [ - "0xf87c3f84026e6e2583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1ba7a3639ec15944466d72a2e972d5eda143fc54f07aa47ecd56769ba5fbf8a041018f9af7a55685cbfa25d35f353e4bccef32a5e0bcdb373191d34cfed9a8db" - ], - "withdrawals": [], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np79", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0x157062b78da942ff0b0e892142e8230ffdf9330f60c5f82c2d66291a6472fd7c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8bb2c279cf46bd7eb856cc00fdce9bb396b21f65da47fdf0f13b41e0c0e0aa7f", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x4f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x316", - "extraData": "0x", - "baseFeePerGas": "0x220c283", - "blockHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619", - "transactions": [ - "0xf86740840220c2848302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bcd36ef6498fd3ce093febc53b3e35004a9d9200816306515f5ffad98140426fa00656b7e75310845c1d2e47495ed7765d687f0a943a604644d9cf7b97b01f300f" - ], - "withdrawals": [], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np80", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0x39a05d1b50f4334060d2b37724df159784c5cbfe1a679f3b99d9f725aed4d619", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x62b57c9d164c28bc924ec89b1fe49adc736ee45e171f759f697899a766e3f7a4", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x50", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x320", - "extraData": "0x", - "baseFeePerGas": "0x1dce188", - "blockHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb", - "transactions": [ - "0xf869418401dce189825208945c62e091b8c0565f1bafad0dad5934276143ae2c01808718e5bb3abd10a0a0b82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d59fdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148" - ], - "withdrawals": [], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np81", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0xa7806a3f4d0f3d523bf65b89164372b524c897688d22d2ef2e218f7abb9cbddb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1820989c0844509c8b60af1baa9030bdcc357bc9462b8612493af9d17c76eb3d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x51", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x32a", - "extraData": "0x", - "baseFeePerGas": "0x1a14dd8", - "blockHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1", - "transactions": [], - "withdrawals": [ - { - "index": "0x0", - "validatorIndex": "0x5", - "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1", - "amount": "0x64" - } - ], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np82", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0x7ec45b0f5667acb560d6e0fee704bb74f7738deb2711e5f380e4a9b2528d29c1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8145365a52eb3a4b608966d28a8ed05598c13af426c7ab24f28f2bdc7a00b12b", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x52", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x334", - "extraData": "0x", - "baseFeePerGas": "0x16d241d", - "blockHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62", - "transactions": [ - "0xf8854284016d241e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a061c5ecaf5f73e89370f5b35c31bce60d04c7417cc70cc897beae6429cb6d3880a02271644378271ec296459da5181507d52bdbd4489600690c32998cdb4b032042" - ], - "withdrawals": [], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np83", - "method": "engine_newPayloadV2", - "params": [ - { - "parentHash": "0x8dbcafaa0e32cd9f71f1d5b0f22f549aee0fddce3bda577ac200e24c7dc8ba62", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x07cc0bca2e8f3b243635dc6f988372dd2427b6090f1035d06f2eff2e99315170", - "receiptsRoot": "0xace7ae7e3c226cecca4b33082b19cd1023960138a576ef77fddadcc223b4250a", - "logsBloom": "0x40000010010000000000000100000c00000001000000000000000000000000000000000200000000000042000000000000001000000000000000000000000000000000000000000000000820040000800000000000004000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000800000001000000000000000000000000000000000000000004000004000000000000000410000000000000000000000040000000000000000004000000000000000000000000000400001000000000000000000400000000000000000000200080000000000000000000000010000000040000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x53", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x33e", - "extraData": "0x", - "baseFeePerGas": "0x13f998a", - "blockHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721", - "transactions": [ - "0xf87c4384013f998b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a01001f6f02c9dac33915eb5d0fe81d88599a29341d84ee6f46b1ef05d270a0c1fa05ea1dbc664d9f4a83b4743bc40579e6b727ff8b5e78c4249bd59aa47c33d770f" - ], - "withdrawals": [], - "blobGasUsed": null, - "excessBlobGas": null - } - ] - }, - { - "jsonrpc": "2.0", - "id": "np84", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x686c223412a42d17a7fe0fe2a8b15d6181afa366cccd26a0b35a7581c0686721", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe1a71059650ccefaf7d0a407c43a87ccc9fe63a6369a46509074658f714c54ad", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x54", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x348", - "extraData": "0x", - "baseFeePerGas": "0x117b7e1", - "blockHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84", - "transactions": [ - "0xf86744840117b7e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b4a7e6c791f457a428f870b8df8ee0148acac74050aeea658c3dad552a7e8140a0793951ba22a6f628dd86ec8964b09c74e0f77306a28dd276dfe42f40ee76c73c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x83472eda6eb475906aeeb7f09e757ba9f6663b9f6a5bf8611d6306f677f67ebd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np85", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8a76d39e76bdf6ccf937b5253ae5c1db1bdc80ca64a71edccd41ba0c35b17b84", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x198575d6df4370febe3a96865e4a2280a5caa2f7bd55058b27ea5f3082db8d99", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x55", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x352", - "extraData": "0x", - "baseFeePerGas": "0xf4dd4f", - "blockHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059", - "transactions": [ - "0x02f86c870c72dd9d5e883e450183f4dd5082520894a25513c7e0f6eaa80a3337ee18081b9e2ed09e000180c080a0e8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8a07c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2c809fbc7e3991c8ab560d1431fa8b6f25be4ab50977f0294dfeca9677866b6e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np86", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc0d03736d9e3c2d4e14115f9702497daf53b39875122e51932f4b9b752ba7059", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x90c402a8569aae0c095540a9762aefac4f43df4e97fc7a24df1d4051c555bc2c", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x56", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x35c", - "extraData": "0x", - "baseFeePerGas": "0xd64603", - "blockHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd", - "transactions": [], - "withdrawals": [ - { - "index": "0x1", - "validatorIndex": "0x5", - "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x756e335a8778f6aadb2cc18c5bc68892da05a4d8b458eee5ce3335a024000c67" - ] - }, - { - "jsonrpc": "2.0", - "id": "np87", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa7323a02aa9acf63f26368292292d4bcb9dc7ef33296bbd98f423b24db3408bd", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7e1765cf5abdf835814ee20c9e401b0e99e2b31f2ad8ea14c62ef732c6e63d2d", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x57", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x366", - "extraData": "0x", - "baseFeePerGas": "0xbb7d43", - "blockHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04", - "transactions": [ - "0xf8844683bb7d44830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a052c928a2062b214d44b9a641faf87e439fbc5a07f571021f0f3c8fd2a2087a57a0650c77ab1cd522a7d3a435058f53636b6ae86d19fd4f691bf61c13fd8b7de69a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4b118bd31ed2c4eeb81dc9e3919e9989994333fe36f147c2930f12c53f0d3c78" - ] - }, - { - "jsonrpc": "2.0", - "id": "np88", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbbd89c9c2805888d9d1397d066495db1ce1c570e23b5b6f853dc0ff698575a04", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3ec8183c28814317cb7a7b86633041db40de94b45a47dab5614b21087c308648", - "receiptsRoot": "0xe2e7a47b1c0009f35c3a46c96e604a459822fe9f02929afa823f2c514f1fbd39", - "logsBloom": "0x00000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000200000000008000000000000000000000000000000800000000000000800000000000000000000002000000000100000000000000000000000000000000000000001000000000400000000000000000000000000000000001000000000000000000000000000000000000000000000020000000000000400000000000000100000000000100000000000000000000100200000000000000000000000000000010400000000000000050080004000000400000000010000000800030001000000000000000004000000000000000000a00", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x58", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x370", - "extraData": "0x", - "baseFeePerGas": "0xa41aed", - "blockHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849", - "transactions": [ - "0xf87b4783a41aee83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09799e22509fcf203235570e7ba0df80bad6124b89b812146b50bca27f03161a9a0118a4f264815d7cf1a069009bff736f04369e19e364bd1a409a4c4865ec7d81f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd0122166752d729620d41114ff5a94d36e5d3e01b449c23844900c023d1650a5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np89", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe67371f91330dd937081250eeda098394453c2ced0b6ffd31a67f8d95261d849", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x07118ca8999c49a924f92b54d21cecad7cbcc27401d16181bbcdee05b613399c", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x59", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x37a", - "extraData": "0x", - "baseFeePerGas": "0x8fa090", - "blockHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18", - "transactions": [ - "0xf86648838fa0918302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd5a86a96cbf94d2bba5c7fb6efd2bf501dd30c8b37e896ae360b40ab693272aa0331e570a5b3ce2cef67731c331bba3e6de2ede8145dd0719ce6dfcca587c64ba" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x60c606c4c44709ac87b367f42d2453744639fc5bee099a11f170de98408c8089" - ] - }, - { - "jsonrpc": "2.0", - "id": "np90", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x395eda9767326b57bbab88abee96eea91286c412a7297bedc3f1956f56db8b18", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0d9d080dde44cc511dc9dc457b9839409e1b3a186e6b9a5ae642b5354acc6cc4", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x384", - "extraData": "0x", - "baseFeePerGas": "0x7dbb15", - "blockHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9", - "transactions": [ - "0xf86949837dbb1682520894bbeebd879e1dff6918546dc0c179fdde505f2a2101808718e5bb3abd10a0a002f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849a0182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6ee04e1c27edad89a8e5a2253e4d9cca06e4f57d063ed4fe7cc1c478bb57eeca" - ] - }, - { - "jsonrpc": "2.0", - "id": "np91", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x919c92e04181d139a4860cce64252ab9c14a5be9fa6adfc76b4b27f804fce2b9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa5aea2e2c617a5a3a341e01c72fbf960e809dd589b4a988a04d50f6fb666b6c8", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x38e", - "extraData": "0x", - "baseFeePerGas": "0x6e05f1", - "blockHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3", - "transactions": [], - "withdrawals": [ - { - "index": "0x2", - "validatorIndex": "0x5", - "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x36616354a17658eb3c3e8e5adda6253660e3744cb8b213006f04302b723749a8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np92", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x17a574ee7489840acc4a8aecd1d7b540ba9b033b7236c13d0b0a5403ff07f7f3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd1e927e1a7106591aa46d3e327e9e7d493248786b4c6284bd138d329c6cb1fbb", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x398", - "extraData": "0x", - "baseFeePerGas": "0x604533", - "blockHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f", - "transactions": [ - "0xf8844a83604534830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0667955bfddc6500ad6a0a298d08a0fdeb453d483be41f7496f557039c99d5b8ea06ad5f6871f3d78ea543484d51590454f8a65b5b1b89f58992ff94a02a30c0c93" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc13802d4378dcb9c616f0c60ea0edd90e6c2dacf61f39ca06add0eaa67473b94" - ] - }, - { - "jsonrpc": "2.0", - "id": "np93", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x7848fe02daea45d47101fbe84b6d94576452c2d0cb9261bc346343b5b2df844f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8d4e68f0a1ad7578b1627d665263c04856efa4eb4938014a8c794547d597f89b", - "receiptsRoot": "0xa37a62134a71ef21b16f2eee431b806a4d13c0a80a11ddeb5cbb18e3707aecdf", - "logsBloom": "0x00000000000000000000000002000000000021000000000000000000240000000000000000000000000004000000010000000000000000000000000000000000000008000000000000000000000000000020000000000000000400000400000000000400000000000000000000000000000000000080000004000000000000000000000000000800000000000000000000000000000000000000000000002000000080000002010000420000000000000000000000000040402002000200000000000000000000000000008000000000000000000000000100000000000000000000000000000000000084000000000080000000000000000000040000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5d", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x3a2", - "extraData": "0x", - "baseFeePerGas": "0x544364", - "blockHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b", - "transactions": [ - "0xf87b4b8354436583011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09662003f67b0c146ecaa0c074b010d1f27d0803dc1809fd4f6ea80a5f09c34aea0100a5c0fbfdbee733f1baecb893a33ce2d42316303a5ddf1515645dfbb40d103" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8b345497936c51d077f414534be3f70472e4df101dee8820eaaff91a6624557b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np94", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6c5d29870c54d8c4e318523a7ea7fb9756b6633bbdf70dcb1e4659ff3564615b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbd07ab096fc1b3e50229bcff0fc5fca9e9f7d368e77fe43a71e468b7b0adb133", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x3ac", - "extraData": "0x", - "baseFeePerGas": "0x49bf97", - "blockHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80", - "transactions": [ - "0xf8664c8349bf988302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa03b3113a7b1919311fbc03ee25c4829b60f07341c72107de061da06eef7ec0856a01bc4eeb29301e1610984ee042f8236863ad78402d3d55c69a6922d67238dde75" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe958485d4b3e47b38014cc4eaeb75f13228072e7b362a56fc3ffe10155882629" - ] - }, - { - "jsonrpc": "2.0", - "id": "np95", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe7b8c1ca432a521b1e7f0cf3cb63be25da67e3364cc0b02b0a28e06ba8deed80", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4a154c665e5b68adadf9455bd905da607f0279b5d2b4bfb0c1a3db5b6a908d4d", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x5f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x3b6", - "extraData": "0x", - "baseFeePerGas": "0x408f22", - "blockHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387", - "transactions": [ - "0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3346706b38a2331556153113383581bc6f66f209fdef502f9fc9b6daf6ea555e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np96", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xaa62b2faefe50fe1562f3fb5bf96a765ca7c92164465e226fc9a8ba75cabc387", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3b2adb11488a7634a20bc6f81bcc0211993fe790f75eeb1f4889a98d1bdbcb37", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x60", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x3c0", - "extraData": "0x", - "baseFeePerGas": "0x387e65", - "blockHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d", - "transactions": [], - "withdrawals": [ - { - "index": "0x3", - "validatorIndex": "0x5", - "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x346910f7e777c596be32f0dcf46ccfda2efe8d6c5d3abbfe0f76dba7437f5dad" - ] - }, - { - "jsonrpc": "2.0", - "id": "np97", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6a6df67e09c4411bb89664cbc78f78237bb6a2fc299bc6a682cca406feb8dd4d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd67c810501ca4f4ee4262e86dcaf793ca75637249bf157dee4800274372f236f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x61", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x3ca", - "extraData": "0x", - "baseFeePerGas": "0x316e99", - "blockHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf", - "transactions": [ - "0xf8844e83316e9a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a036b2adb5bbd4d43198587067bf0b669e00862b0807adb947ee4c9869d79f9d8ca063e0b200645435853dceed29fd3b4c55d94b868a0aa6513ca6bd730705f2c9ef" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe62a7bd9263534b752176d1ff1d428fcc370a3b176c4a6312b6016c2d5f8d546" - ] - }, - { - "jsonrpc": "2.0", - "id": "np98", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfec8ebc1c3d312ec3537d860b406110aeac3980763165d0026ecab156a377bdf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xae82dda9df38bcc8d99e311b63ae055591953577b6b560840658eca24ecacee9", - "receiptsRoot": "0x675ab823f90b9bdd3d04afb108bc1a1dcd77654a0de4c8a539e355b6d24f29f4", - "logsBloom": "0x10000000000000000010000000000020000000000008000000000000000000000000000000000000000000020000000000000000000000000000040000010000000000000000000000000000000000000000000000008000000000000000000000000080000110000000000800000002000000800040800000000040000000000000004000000000001000000000000000000000000000000000008000000000000000000000000000000020010080001000000000000000000000000004008000004000008000000000000000040000000400000000000001000000000000000000000008000000000000000000000200000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x62", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x3d4", - "extraData": "0x", - "baseFeePerGas": "0x2b4449", - "blockHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517", - "transactions": [ - "0xf87b4f832b444a83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0824522ae97a912dd75a883798f4f296d960f6a7be8510e2a4a121d85f496da16a008cade93390e31f7b0e6615b4defe3bd4225b7a4d97a7835c02ad0b4d004fb5b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xffe267d11268388fd0426a627dedddeb075d68327df9172c0445cd2979ec7e4d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np99", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3124d842afa1334bb72f0a8f058d7d3ad489d6c6bd684f81d3ecdf71d287f517", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x588419f24b32499745bbae81eb1a303d563c31b2743c8621d39b820c2affb3cb", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x63", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x3de", - "extraData": "0x", - "baseFeePerGas": "0x25de20", - "blockHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962", - "transactions": [ - "0xf866508325de218302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0744b7f5fb26cc6dd16b1849d0c04236e3b4e993f37e5b91de6e55f5f899450baa0456225c91372bddd4e3a1dde449e59ad62d63f0c850f9b869870ea2621494fd7" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x23cc648c9cd82c08214882b7e28e026d6eb56920f90f64731bb09b6acf515427" - ] - }, - { - "jsonrpc": "2.0", - "id": "np100", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x53d785a42c58a40edbc18e6bee93d4072a4281c744f697f9b5cae1d0b3bf2962", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfee7a27147c7984caec35dc4cee4f3a38fee046e5d8f17ce7ec82b982decd9aa", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x64", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x3e8", - "extraData": "0x", - "baseFeePerGas": "0x212635", - "blockHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e", - "transactions": [ - "0xf86951832126368252089418ac3e7343f016890c510e93f935261169d9e3f501808718e5bb3abd10a0a099aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4a0582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x47c896f5986ec29f58ec60eec56ed176910779e9fc9cf45c3c090126aeb21acd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np101", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x96d2a59527aa149efe64eef6b2fbf4722c9c833aba48e0c7cb0cb4033fa1af5e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb1600603ea31446c716fece48a379fb946eab40182133a8032914e868bb4929e", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x65", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x3f2", - "extraData": "0x", - "baseFeePerGas": "0x1d0206", - "blockHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14", - "transactions": [], - "withdrawals": [ - { - "index": "0x4", - "validatorIndex": "0x5", - "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6d19894928a3ab44077bb85dcb47e0865ce1c4c187bba26bad059aa774c03cfe" - ] - }, - { - "jsonrpc": "2.0", - "id": "np102", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf2750d7772a6dcdcad79562ddf2dee24c1c2b7862905024a8468adfb62f8ef14", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd3908889240ecc36175f7ac23e9596230ea200b98ee9c9ca078154288b69c637", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x66", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x3fc", - "extraData": "0x", - "baseFeePerGas": "0x1961c6", - "blockHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4", - "transactions": [ - "0xf88452831961c7830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0c43b4e8ddaecaadfc1fd4b35659ced2bbaa2ab24b1cff975685cd35f486a723fa056a91d2ff05b4eae02ee1d87442ec57759e66ec13bfd3ea2655cf4f04b6e863d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xefc50f4fc1430b6d5d043065201692a4a02252fef0699394631f5213a5667547" - ] - }, - { - "jsonrpc": "2.0", - "id": "np103", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x57054aa8d635c98b3b71d24e11e22e9235bc384995b7b7b4acd5ca271d0898b4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd66957c43447a6edfb6b9bc9c4e985f28c24e6ce3253c68e5937c31c5d376f94", - "receiptsRoot": "0xd99d12e61c8e9be69f1eb49cea2f72664c7e569463415b064954bf5e0dbc6a01", - "logsBloom": "0x00000000000000000000100000000000200000000000000000200000000000000000000000040000000000200000000000000000000000000200000000000000000018000000000000000000010000000000000000000000000000000000100000000000000000000000000000000000000000000000000000800200000000021000000000002000000000002088400000000000000000000000000000000000000000000000000000000010000000000800000080000000000000000000000008000000000000000020000100001000000000080000002000400000000400000000000000002200000000000000000000000000000000000000000020000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x67", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x406", - "extraData": "0x", - "baseFeePerGas": "0x16375b", - "blockHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d", - "transactions": [ - "0xf87b538316375c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0e59d36f30ed2dfc5eb71433457547f63bf4ad98e0a2181c4373a5e7ddf04d17ea06dce4f88f48f6fd93c2c834537a8baef27bb2965b9e2ce68dc437adb3d657d28" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3cc9f65fc1f46927eb46fbf6d14bc94af078fe8ff982a984bdd117152cd1549f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np104", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf4f1f726bcb9a3db29481be3a2e00c6ab4bf594ae85927414540ec9ede649d4d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe06685d528d0c69051bcf8a6776d6c96c1f1c203da29851979c037be2faac486", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x68", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x410", - "extraData": "0x", - "baseFeePerGas": "0x1371a8", - "blockHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d", - "transactions": [ - "0xf86654831371a98302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a427e65413948a8a1cf63c15214525d05bffca4667149c6a4019513defe57e6ba02819aa7d6a404a7f0194ef3ba7ec45b876f4226b278ebbcfa4012a90a1af3905" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x63eb547e9325bc34fbbbdfda327a71dc929fd8ab6509795e56479e95dbd40a80" - ] - }, - { - "jsonrpc": "2.0", - "id": "np105", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc8fe6583a2370fa9bda247532a8fb7845fceea9b54c9e81cda787947bb0ad41d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x32d5d07d12d91b8b4392872b740f46492fea678e9f5dc334c21101767bd54833", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x69", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x41a", - "extraData": "0x", - "baseFeePerGas": "0x11056d", - "blockHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7", - "transactions": [ - "0x02f86c870c72dd9d5e883e55018311056e82520894de7d1b721a1e0632b7cf04edf5032c8ecffa9f9a0180c080a02a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97a027c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x67317288cf707b0325748c7947e2dda5e8b41e45e62330d00d80e9be403e5c4c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np106", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb30b266de816c61ef16e4abfc94fbed8b4032710f4275407df2bf716a1f0bbd7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf89d6d5f7a16d98062e1ef668ee9a1819b0634bd768ece2fc2b687f8968dc373", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x424", - "extraData": "0x", - "baseFeePerGas": "0xee50e", - "blockHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b", - "transactions": [], - "withdrawals": [ - { - "index": "0x5", - "validatorIndex": "0x5", - "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7fc37e0d22626f96f345b05516c8a3676b9e1de01d354e5eb9524f6776966885" - ] - }, - { - "jsonrpc": "2.0", - "id": "np107", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x35221530b572a05628d99d8ca9434287c581e30473f83d612cbbfb7f394c587b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xaf4107a57da519d24d0c0e3ae6a5c81f3958ddc49e3f1c2792154b47d58d79a1", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x42e", - "extraData": "0x", - "baseFeePerGas": "0xd086d", - "blockHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35", - "transactions": [ - "0xf88456830d086e830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04c088a3642c3cfad977a0927e6d694bd26be96246f127f03d37fe2b494b99da2a00ef5b6e7aca1ac95ef964978a7ec4bb66688fbb7abace43f90f0c344196379e5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc8c5ffb6f192e9bda046ecd4ebb995af53c9dd6040f4ba8d8db9292c1310e43f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np108", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe3981baf40fc5dac54055fab95177a854a37ff2627208247697d5627b8ae3c35", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9afc46d870489ac06cac1ea0b65c417d8e0086f0fb828dd92dca30da737c827b", - "receiptsRoot": "0x9b9c6d15a59d6b1c222cc63abe6aa28d734463877a3c34d4b3d9e80b768b77aa", - "logsBloom": "0x00000000000000000000000000000080000000000002000000000002000000000000004000000000000000000000010000000000000000000000000000000000000400000000000000100000000000000000200000000000000000000200000000000000000008000010000000000000000080000000000200000008000400000000000000000400000000000000000008000000001000000001000000000000000000000000008000000200000000000000000008400000000000000000000000001000000000000000000000001000010000000020000000040000000000000000000000000000000200080000000000000000000000040000000200000400", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6c", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x438", - "extraData": "0x", - "baseFeePerGas": "0xb684d", - "blockHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa", - "transactions": [ - "0xf87b57830b684e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06789a9252207970001fd703c22b2b7e5c0388bf018bc070a0469129f80cc5d63a048de0e437b02a8dd3a783892ad1691a1062cd73ddd35c481d9632f5158650317" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe40a9cfd9babe862d482ca0c07c0a4086641d16c066620cb048c6e673c5a4f91" - ] - }, - { - "jsonrpc": "2.0", - "id": "np109", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x54fcc3af800dbeae5c45ac8acba05313bd8d4c1bb06502702a14a225259367aa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x02324f55d0548cb8743857fe938f91e6f15bfbe94654aadde56c59f83083980a", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x442", - "extraData": "0x", - "baseFeePerGas": "0x9fbe4", - "blockHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3", - "transactions": [ - "0xf866588309fbe58302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07e3ef87807ccd797a0020fade1b7d65a7b190fbe40a6f8bdc35cd6a3a6fbed73a0283ad99e27eb389ca3b389bce3c29b3c711b74b6ecd05b290c7be33389830fab" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe82e7cff48aea45fb3f7b199b0b173497bf4c5ea66ff840e2ec618d7eb3d7470" - ] - }, - { - "jsonrpc": "2.0", - "id": "np110", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x62bb35defc0aac7bfbe789de02062f7ac622e9e354cfea5dceeccb792a61bae3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9932915761c4c894fc50819df189e875d3b025a7c045406fe415abe61d0e3086", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x44c", - "extraData": "0x", - "baseFeePerGas": "0x8bd6c", - "blockHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0", - "transactions": [ - "0xf869598308bd6d825208941b16b1df538ba12dc3f97edbb85caa7050d46c1401808718e5bb3abd109fa0abbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62ca03aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x84ceda57767ea709da7ab17897a70da1868c9670931da38f2438519a5249534d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np111", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2c4731fbb4f4adae94723c078548c510649e8973dfdb229fd6031b1b06eb75c0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2849b35fb3ec8146f637be768e3eaefda559928f8bb35753584d5b326a400ff5", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x6f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x456", - "extraData": "0x", - "baseFeePerGas": "0x7a5e7", - "blockHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7", - "transactions": [], - "withdrawals": [ - { - "index": "0x6", - "validatorIndex": "0x5", - "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe9dcf640383969359c944cff24b75f71740627f596110ee8568fa09f9a06db1c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np112", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x76b385d3f8a4b6e66ea8c246ed7c6275ad164d028ec5a986f9524bfe7437dcc7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2f24b6182543c677e7d1cab81bc020033c64e034571a20ecd632e252c8f202b3", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x70", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x460", - "extraData": "0x", - "baseFeePerGas": "0x6b12b", - "blockHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc", - "transactions": [ - "0xf8845a8306b12c830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf8a8863f63a16d43652b12e54dc61bd71c8ab86d88aebb756c6e420fca56a1aa01f62e0032c57f1629ee82b4fefb8d6c59a85c5c2889b1671ce0713581e773b6e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x430ef678bb92f1af44dcd77af9c5b59fb87d0fc4a09901a54398ad5b7e19a8f4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np113", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x33385ec44cfd01ba27c927a3ebe607a27e55fd8e89965af09b991a7cdc127dbc", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6d6c9c24ef7d93db6ba57324fb6f3604b09611301e12d250162c2b2b50871625", - "receiptsRoot": "0x257c29f688aaf63db2244378182225d104d84cfbd188c82b92323623d11574e9", - "logsBloom": "0x00000000000000000000080040000000000000000000000000008000000000000000000000000000000000000001000000000000000000000040000000040010000100000000000000400000000000000000020000000000000000800000000400000000000000000000000040000000000002000100400000000000000200000000000000000000000008000000010000000000000800000000000000000000000080000000000000000000000000000000080400000000000000000000400000000000010000000004000000000000000000000010020000000000000000000000000000000100000000040000000000000000000000200000001800000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x71", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x46a", - "extraData": "0x", - "baseFeePerGas": "0x5db80", - "blockHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f", - "transactions": [ - "0xf87b5b8305db8183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0f893fcd21c2a882bc3968ea3c41dd37a8dbfbf07a34a8694a49fdd8081996e25a0502578b516e04b1939fdad45fd0688e636d57f59826a8e252b63f496b919d91c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf7af0b8b729cd17b7826259bc183b196dbd318bd7229d5e8085bf4849c0b12bf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np114", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x66ad7aaacf3efede70dda0c82629af2046e67b96713cf3cf02a9a2613ca25b6f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x61c50266ae62e14edea48c9238f79f6369fd44e7f3d6519c7139aa1e87ee13ba", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x72", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x474", - "extraData": "0x", - "baseFeePerGas": "0x52063", - "blockHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d", - "transactions": [ - "0xf8665c830520648302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0961de3e3657fdc49c722cc23de35eaf41de51c3aab3ca9a09b3d358fc19195aca060ee48b2fad3f3798111a93038fcb5c9c9791daf3c6acbaf70134fd182b5c663" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe134e19217f1b4c7e11f193561056303a1f67b69dac96ff79a6d0aafa994f7cb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np115", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x00fd70a53be9c85c986d3dd87f46e079e4ce4a4a3dd95c1e497457c50bacbe2d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2bebf2f158ec1b8c7be21ef7c47c63fa5a3eb2292f409f365b40fa41bacb351e", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x73", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x47e", - "extraData": "0x", - "baseFeePerGas": "0x47cdc", - "blockHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c", - "transactions": [ - "0x02f86c870c72dd9d5e883e5d0183047cdd82520894043a718774c572bd8a25adbeb1bfcd5c0256ae110180c001a02ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196a077a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9cc58ab1a8cb0e983550e61f754aea1dd4f58ac6482a816dc50658de750de613" - ] - }, - { - "jsonrpc": "2.0", - "id": "np116", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbb9f244470573774df6fca785d3e11e6bd1b896213cacd43cdfcb131f806ca4c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3b359e20c5966cdcbb7b0298480621892d43f8efa58488b3548d84cf2ee514c1", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x74", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x488", - "extraData": "0x", - "baseFeePerGas": "0x3ed55", - "blockHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9", - "transactions": [], - "withdrawals": [ - { - "index": "0x7", - "validatorIndex": "0x5", - "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x79c2b067779a94fd3756070885fc8eab5e45033bde69ab17c0173d553df02978" - ] - }, - { - "jsonrpc": "2.0", - "id": "np117", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6d18b9bca4ee00bd7dc6ec4eb269cd4ba0aceb83a12520e5b825b827cb875fd9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9776b87f7c94469bd3f80d7d9b639dace4981230bbb7c14df9326aafe66f3da4", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x75", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x492", - "extraData": "0x", - "baseFeePerGas": "0x36fab", - "blockHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9", - "transactions": [ - "0xf8845e83036fac830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08315d9fb30662071b05a4e38240e4b85b8e240c0c3e190f27ada50678236c6e7a00ee07dc873780f17ac9d0c7b3d434f89be92231cfca042ca5f23d3f3d7346861" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd908ef75d05b895600d3f9938cb5259612c71223b68d30469ff657d61c6b1611" - ] - }, - { - "jsonrpc": "2.0", - "id": "np118", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcef84ea2c6fac4a2af80a594bbe5a40bf5f5285efe67fab7ceb858844c593ae9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcd5cc668a3b28217e9fd05ddaea82d453a6a7394770a888b7d88013a4c9bcb22", - "receiptsRoot": "0xe35b2accd70b81901c8d0c931a12687e493a489ed7b82d78ade199815c466d5f", - "logsBloom": "0x0000000000000000000000000000000000000a00000000000000000000000000000000000000000000018000000000000000000000000000008000000000000048000000000000004000000000000000000008000000000000000000000020000000000000000002201010000000000000000400000000200000000000000000000000000000000000000000200000000000a200000001000000000000000000000000200000000000000000000400040000000000000000000000800000000000000000001800000000000802000000000000000000000080000000000000000000000000000000000000000000000000400000010800000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x76", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x49c", - "extraData": "0x", - "baseFeePerGas": "0x301f5", - "blockHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305", - "transactions": [ - "0xf87b5f830301f683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a3952a3372b48d4ef804b20a0ff5bbd5440156de3b71d37024356a3c1c5205d8a02ff03cae2dc449ca7ed7d25c91f99b17f0bafcdaf0ecc6e20bdeb80895c83e82" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe0d31906b7c46ac7f38478c0872d3c634f7113d54ef0b57ebfaf7f993959f5a3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np119", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x7b65cb3becfab6b30f0d643095b11c6853a33ca064a272f1326adb74e876e305", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdd592cc191ae4ba2be51a47d5056c2f0ba8799c74445ea3f294e0fc95a973f16", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x77", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x4a6", - "extraData": "0x", - "baseFeePerGas": "0x2a1e1", - "blockHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0", - "transactions": [ - "0xf866608302a1e28302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0fd1714b8a15fa8a4e3ffe824632ec26f1daa6ce681e92845d1c1dfe60f032b4ea074bd5a60859bd735bbc70c9531a3ff48421f5c3b87e144406ee37ef78b8fda37" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2318f5c5e6865200ad890e0a8db21c780a226bec0b2e29af1cb3a0d9b40196ae" - ] - }, - { - "jsonrpc": "2.0", - "id": "np120", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5d089bec3bbf3a0c83c7796afaa1ae4d21df034a3e33a6acb80e700e19bcaab0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4b5122bd4713cd58711f405c4bd9a0e924347ffce532693cce1dd51f36094676", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x78", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x4b0", - "extraData": "0x", - "baseFeePerGas": "0x24dea", - "blockHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd", - "transactions": [ - "0xf8696183024deb825208942d711642b726b04401627ca9fbac32f5c8530fb101808718e5bb3abd109fa0b4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6a0676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x523997f8d8fed954658f547954fdeceab818b411862647f2b61a3619f6a4d4bc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np121", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x02c9511703f78db34f67541d80704165d8a698726ef2cbcfbdc257bcf51594dd", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x18484e0a8e7bcccf7fbf4f6c7e1eff4b4a8c5b5e0ba7c2f2b27da315a0a06f97", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x79", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x4ba", - "extraData": "0x", - "baseFeePerGas": "0x20438", - "blockHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403", - "transactions": [], - "withdrawals": [ - { - "index": "0x8", - "validatorIndex": "0x5", - "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbe3396540ea36c6928cccdcfe6c669666edbbbcd4be5e703f59de0e3c2720da7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np122", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1edbbce4143b5cb30e707564f7ada75afe632e72b13d7de14224e3ed0044a403", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6c921d64a95659dd6c62a919f2df9da2fda7cb8ec519aeb3b50ffb4e635dc561", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x4c4", - "extraData": "0x", - "baseFeePerGas": "0x1c3b1", - "blockHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca", - "transactions": [ - "0xf884628301c3b2830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f48d056f98b681d69f84fcde715c63b1669b11563164d7c17e03e5d3a4641a0fa010fce327ee99c5206995065cbb134d5458143a34cbc64b326476aeef47ae482a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2d3fcfd65d0a6881a2e8684d03c2aa27aee6176514d9f6d8ebb3b766f85e1039" - ] - }, - { - "jsonrpc": "2.0", - "id": "np123", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x38e1ce2b062e29a9dbe5f29a5fc2b3c47bf2eed39c98d2b2689a2e01650e97ca", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x09df4733053f80da4904bce8d847883472e20bc3b1378eb1579e2e3df44d3948", - "receiptsRoot": "0x03ecb1b96e21ef88b48a9f1a85a170bdb0406e26918c7b14b9602e6f9a7e6937", - "logsBloom": "0x00000004000000000000002000000000000000004000000000000000000000000000400000400000000000000000010000080000000024404000000000000000000000000000000800000000020000000001000100000080000000000000000000000000000800000000000000000000000014000000000000000000000000001000000000000002000000100000000000000000000000000000040000000000000000000000000000040000020000000000000000200000000000000000000000000000000000000000000480010000000000000000000000040000000000000000000000000008000000000000000020000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7b", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x4ce", - "extraData": "0x", - "baseFeePerGas": "0x18b5b", - "blockHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90", - "transactions": [ - "0xf87b6383018b5c83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b223787310f8ba4f9271d98c8bfc4f7e926ced7773cab6b5c856fb4c43b6dad5a07d0edf043f5b767ffd513479a43cbdc3dcbd18f254e3eb11043d4d7aa4dd7445" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7ce0d5c253a7f910cca7416e949ac04fdaec20a518ab6fcbe4a63d8b439a5cfc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np124", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xda82bddbddc44bf3ce23eb1f6f94ae987861720b6b180176080919015b1e4e90", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x15da947afcb1ba68f9fe2328e500881a302de649bd7d37f6e969bf7ec1aca37d", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x4d8", - "extraData": "0x", - "baseFeePerGas": "0x15a06", - "blockHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21", - "transactions": [ - "0xf8666483015a078302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa037c41575c8abba9465870babe53a436d036974edf6a9de15d40fff1b4cca7552a07e815124c036ad7c603e7faa56d1d9e517d60cee33c1e47122a303e42d59b6fa" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4da13d835ea44926ee13f34ce8fcd4b9d3dc65be0a351115cf404234c7fbd256" - ] - }, - { - "jsonrpc": "2.0", - "id": "np125", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8948407592d9c816f63c7194fa010c12115bee74e86c3b7d9e6ca30589830f21", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa085ae940536d1e745cf78acd4001cb88fbc1e939151193c4e792cb659fe1aa0", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x4e2", - "extraData": "0x", - "baseFeePerGas": "0x12ee9", - "blockHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5", - "transactions": [ - "0x02f86c870c72dd9d5e883e650183012eea82520894d10b36aa74a59bcf4a88185837f658afaf3646ef0180c080a0882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2aa041356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc5ee7483802009b45feabf4c5f701ec485f27bf7d2c4477b200ac53e210e9844" - ] - }, - { - "jsonrpc": "2.0", - "id": "np126", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5f66e4813f2b86dc401a90a05aafd8a2c38f6f1241e8a947bf54d679014a06a5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfb39354666f43e8f8b88f105333d6f595054b2e1b0019f89bf5dbddf7ec9a0ab", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x4ec", - "extraData": "0x", - "baseFeePerGas": "0x10912", - "blockHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8", - "transactions": [], - "withdrawals": [ - { - "index": "0x9", - "validatorIndex": "0x5", - "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0fc71295326a7ae8e0776c61be67f3ed8770311df88e186405b8d75bd0be552b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np127", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1b452f327c51d7a41d706af9b74ac14ff50b74dcef77fdb94333a8f5c86436a8", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb042b6a0d783d5e3757a9799dbc66d75515d0a511e5157650048a883a48d7c75", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x7f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x4f6", - "extraData": "0x", - "baseFeePerGas": "0xe7f0", - "blockHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161", - "transactions": [ - "0xf8836682e7f1830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e5232243797a918b702f03aa9ccf4e944ff52293e7f5b7b1cb6874047f064ed6a02ae2cefc3e4fdb15fb4172d6fe04c7d54a312d077dcd15f91bf5f7047c10d079" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7313b4315dd27586f940f8f2bf8af76825d8f24d2ae2c24d885dcb0cdd8d50f5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np128", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4831cdabfa81a5a7c4a8bb9fee309515e2d60dd5e754dfef4456794385771161", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0400502ad286f8ca3e6e362d38ec9f2119eddc480e9af1ec646bc48e5451a379", - "receiptsRoot": "0xdcfb036965921ecaf598a6a02e3fb77784da94be9ed9aeee279d085a20342e47", - "logsBloom": "0x00000002000041000000000200000200400000000000000008000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00080000000000000000000000000000000000000000000400000000000000008000000000000000000000014800000000000000000000000000000000000000000000000000000000000080000000000008000000000000000000000000000008000000000000000000000100000000000000000200000000000000000000000000000000000000030000800000000000000000000001000000002000000000000000020000400005002000004000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x80", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x500", - "extraData": "0x", - "baseFeePerGas": "0xcb03", - "blockHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2", - "transactions": [ - "0xf87a6782cb0483011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07e94803268c610035c580891ef0c6edd5c21babd8a2bb54d22373e982db9bf46a0375bc266e5e65f0a899b2299ddddbdc0e0d7d40c21e6d254d664abd7d0698076" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2739473baa23a9bca4e8d0f4f221cfa48440b4b73e2bae7386c14caccc6c2059" - ] - }, - { - "jsonrpc": "2.0", - "id": "np129", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfadcdb29ddbfaed75902beaecb3b9e859bf4faefe78591baf8ac9c99faec09d2", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1f1fc8702bf538caf0df25f854999a44a7583b4339011bc24dadcee848e3daf5", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x81", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x50a", - "extraData": "0x", - "baseFeePerGas": "0xb1ae", - "blockHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d", - "transactions": [ - "0xf8656882b1af8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a064097d6048ea289fa6b8a002f4a7d53d8381ee46bf0dadd3ac1befa477cef309a0300f780844db5eaa99ff65752886da8b671329d7c12db4e65dd7f525abe9b1d8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd4da00e33a11ee18f67b25ad5ff574cddcdccaa30e6743e01a531336b16cbf8f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np130", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5bc61ce8add484ead933542e385d4592d82aac6d47b46dcb2451390b884b8c3d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb04a7bb7f21e64f23bd415ee3ad1dc8a191975c86e0f0d43a92a4204a32ac090", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x82", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x514", - "extraData": "0x", - "baseFeePerGas": "0x9b8b", - "blockHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f", - "transactions": [ - "0xf86869829b8c82520894a5ab782c805e8bfbe34cb65742a0471cf5a53a9701808718e5bb3abd10a0a078e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245ea07563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe651765d4860f0c46f191212c8193e7c82708e5d8bef1ed6f19bdde577f980cf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np131", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x30fcf7ed7c580b55b92289383259c5c1d380d54c1f527bfdc8b062af1e898b8f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfd2a1032389a1b7c6221d287a69e56a32d8a618396b8ef829601a9bcb3e91cce", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x83", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x51e", - "extraData": "0x", - "baseFeePerGas": "0x881d", - "blockHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498", - "transactions": [], - "withdrawals": [ - { - "index": "0xa", - "validatorIndex": "0x5", - "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5b5b49487967b3b60bd859ba2fb13290c6eaf67e97e9f9f9dda935c08564b5f6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np132", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8b3a8443b32d2085952d89ca1b1ecb7574b37483cb38e71b150c00d001fea498", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x91120613028234db2b47071a122f6ff291d837abe46f1f79830276fd23934c56", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x84", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x528", - "extraData": "0x", - "baseFeePerGas": "0x771a", - "blockHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3", - "transactions": [ - "0xf8836a82771b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0a295fe01d21a6f8ffd36f8415e00da318f965a12155808a0d3b51c2c1914cf65a055022813f479686f077e227f3b00dc983081ad361dd8c8240b84d1cf86721ccf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x57b73780cc42a6a36676ce7008459d5ba206389dc9300f1aecbd77c4b90277fa" - ] - }, - { - "jsonrpc": "2.0", - "id": "np133", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc9a9cc06b8a5d6edad0116a50740cb23d1cb130f6c3052bae9f69a20abf639c3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1ec4000ab57cb0fec41b7221fff5ad7ec0dd4a042a739349045110b8116650c8", - "receiptsRoot": "0x870c88b91d896f4d6c0d6d8d9924dee345e36915e9244af9785f4ca1fea5fda3", - "logsBloom": "0x000000000008000000004000000000000000000000000000000000000000000400000000080000000000000000000000000000000000000000000000000c0000000000000000000002000000080000000000000000000004000000000000000000000000000000000000000000020000000400000000010000000040000000000000000000000000000004000000800008000100000202000000000000040000000000000000002000000000200000100000000000010000000000000001010000000000000000000000100000100000000401000000000000000000000000000000000000000000000000000000410000000800000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x85", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x532", - "extraData": "0x", - "baseFeePerGas": "0x6840", - "blockHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69", - "transactions": [ - "0xf87a6b82684183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa09ce0e0b4fb662dd87cf69350e376568655ce9436941c42e7815a0688db3d8281a037208359ff73e2b9389d9d6e32df5203a0239e5dbbf016e87b3714c122ff081f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x217e8514ea30f1431dc3cd006fe730df721f961cebb5d0b52069d1b4e1ae5d13" - ] - }, - { - "jsonrpc": "2.0", - "id": "np134", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4d61445a8ece151e7938bc9c2f4f819a10afddf32c0f2600d62281ecd6b1af69", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb078e743044057e03f894971bfc3dca4dc78990d5cba60c7c979182c419528cf", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x86", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x53c", - "extraData": "0x", - "baseFeePerGas": "0x5b3e", - "blockHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324", - "transactions": [ - "0xf8656c825b3f8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0fd01a89a43af89dfba5de6077a24873a459ee0c8de3beaa03e444bb712fdbebda04f920e07882701d12f9016e32bfe5859d3c1bf971e844c6fcd336953190a8aad" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x14b775119c252908bb10b13de9f8ae988302e1ea8b2e7a1b6d3c8ae24ba9396b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np135", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xadcc471cc18ae64a1ece9ef42013441477843c72962bcc0f1291df9dc8906324", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5ed1a679a1844883bb7c09f1349702b93a298fc8a77885f18810230f0322d292", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x87", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x546", - "extraData": "0x", - "baseFeePerGas": "0x4fe0", - "blockHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b", - "transactions": [ - "0x02f86b870c72dd9d5e883e6d01824fe1825208944bfa260a661d68110a7a0a45264d2d43af9727de0180c001a00bb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8a03b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe736f0b3c5672f76332a38a6c1e66e5f39e0d01f1ddede2c24671f48e78daf63" - ] - }, - { - "jsonrpc": "2.0", - "id": "np136", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd2e3126fb4b0cc3e1e98f8f2201e7a27192a721136d12c808f32a4ff0994601b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd4db74075dc9ae020d6016214314a7602a834c72ec99e34396e1d326aa112a27", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x88", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x550", - "extraData": "0x", - "baseFeePerGas": "0x45e6", - "blockHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa", - "transactions": [], - "withdrawals": [ - { - "index": "0xb", - "validatorIndex": "0x5", - "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7d112c85b58c64c576d34ea7a7c18287981885892fbf95110e62add156ca572e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np137", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa503a85bc5c12d4108445d5eab6518f1e4ccaeab30434202b53204a9378419fa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfd5f001adc20a6ab7bcb9cd5ce2ea1de26d9ecc573a7b595d2f6d682cf006610", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x89", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x55a", - "extraData": "0x", - "baseFeePerGas": "0x3d2a", - "blockHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c", - "transactions": [ - "0xf8836e823d2b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e853c07d5aba01cfcacc3a4191551d7b47d2e90aba323bd29b5b552147bc4055a03a7e1dee0d461376b43ac4c0dd1a85cc94e9fa64aa8effec98c026293e47240a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x28fbeedc649ed9d2a6feda6e5a2576949da6812235ebdfd030f8105d012f5074" - ] - }, - { - "jsonrpc": "2.0", - "id": "np138", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe0b036f2df5813e2e265d606ee533cd46924a8a7de2988e0e872c8b92c26399c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3bf11932c08c5317c7463697409eba5a6904575cc03593cb0eac6c82093d79b7", - "receiptsRoot": "0x3ef7cc7ec86f1ace231cdf7c7fadaf27ae84ad4afdd5f2261b60d5be03794001", - "logsBloom": "0x00000000000000000000080000000000000000000000000000000000000000000000000010000000004000008000000000000000000000000000000080001000000020000000000000000000000000000000000000000000000010000010200000040220000000000000000000010001000000800000000000400000002000000000000000000000400000000000000800000000000400000000000000080000500000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000004002000000000008000000000002000000400000000000000000000000000002000000000002000000000000002000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8a", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x564", - "extraData": "0x", - "baseFeePerGas": "0x358a", - "blockHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da", - "transactions": [ - "0xf87a6f82358b83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c28b8f557aaf82e47d9e1425824709427513131908ac636f142990468e40909ea05fe11510da000868cfe1a05bdf689a8c1954c87afeb9ef2defbed3075458a6ad" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6f7410cf59e390abe233de2a3e3fe022b63b78a92f6f4e3c54aced57b6c3daa6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np139", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfcca6f4e35f290be297bf6403b84c99d1a7b6d78299b5e2690d915bf834e85da", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe8258bde0dceac7f4b4734c8fa80fe5be662ae7238d9beb9669bc3ae4699efa8", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x56e", - "extraData": "0x", - "baseFeePerGas": "0x2edc", - "blockHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e", - "transactions": [ - "0xf86570822edd8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a02206472edd9c816508c6711c004500028a4a6a206caf23b20c6828dd60e1533fa0186dc116a92a8455d1cb92ed4b599c3f7cade6cf59da63b1aef46936c3a507e9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd5edc3d8781deea3b577e772f51949a8866f2aa933149f622f05cde2ebba9adb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np140", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x762df3955fc857f4c97acb59e4d7b69779986e20e3a8ea6bc5219dfd9e5a3d7e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9ff9a193050e74dfa00105084fa236099def4aa7993691c911db0a3f93422aeb", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x578", - "extraData": "0x", - "baseFeePerGas": "0x2906", - "blockHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84", - "transactions": [ - "0xf86871822907825208949defb0a9e163278be0e05aa01b312ec78cfa372601808718e5bb3abd109fa04adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93a0581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x20308d99bc1e1b1b0717f32b9a3a869f4318f5f0eb4ed81fddd10696c9746c6b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np141", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xffe6c202961ee6b5098db912c7203b49aa3b303b4482234371b49f7ef7a95f84", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf63dc083849dc5e722a7ca08620f43fc5cd558669664a485a3933b4dae3b84f4", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x582", - "extraData": "0x", - "baseFeePerGas": "0x23e6", - "blockHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe", - "transactions": [], - "withdrawals": [ - { - "index": "0xc", - "validatorIndex": "0x5", - "address": "0x075198bfe61765d35f990debe90959d438a943ce", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x91f7a302057a2e21d5e0ef4b8eea75dfb8b37f2c2db05c5a84517aaebc9d5131" - ] - }, - { - "jsonrpc": "2.0", - "id": "np142", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfa0dcd8b9d6e1c42eeea7bb90a311dd8b7215d858b6c4fb0f64ee01f2be00cfe", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6222bb96d397776358dd71f14580f5464202313769960ec680c50d9ccc2fa778", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x58c", - "extraData": "0x", - "baseFeePerGas": "0x1f6a", - "blockHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d", - "transactions": [ - "0xf88372821f6b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa067091ae37d21fdc5f9eed2877bddb24e52f69e80af27a89608b6fba1c5053f32a04817ab7dc0c3eaac266b08a1683c34fcd43098c6219ea5771d35fa3387b705a1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x743e5d0a5be47d489b121edb9f98dad7d0a85fc260909083656fabaf6d404774" - ] - }, - { - "jsonrpc": "2.0", - "id": "np143", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe501e9f498cd6b1a6d22c96a556c9218e3a7960eea3e9ab4ac2760cc09fdca0d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbe8a51adbc81161927f0b6f3e562cd046f1894145010a1b3d77394780478df3c", - "receiptsRoot": "0x8c32e3da3725025cad909cb977e252fd127d54c4f4da3852d18ef3976bfe4610", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000001000000000000004000000000000000000000000000800000000000000000000028000000020008000000008000000000000000000000000010000000000080000100000400100000000000000000000000100000000010000000000000000000000000000004000000000000000000008000000000080008000000000000000000000000000000000000000000080002800000000000120000000000004000000000000000000000004000000400000002000800000020000000080000000000000008000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x8f", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x596", - "extraData": "0x", - "baseFeePerGas": "0x1b7f", - "blockHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078", - "transactions": [ - "0xf87a73821b8083011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de521643ceaf711d0d3b6cda406ef8fba599658fccc750139851846435eba8afa057f5427948ca8d46609925641f81f72115860c16228821020b8020846a4c3158" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcdcf99c6e2e7d0951f762e787bdbe0e2b3b320815c9d2be91e9cd0848653e839" - ] - }, - { - "jsonrpc": "2.0", - "id": "np144", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdb3eb92355d58f317e762879ec891a76e0d9ba32a43f0a70f862af93780ef078", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb7933a921b5acf566cc2b8edb815d81a221222a0ac36dac609927aa75744daaf", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x90", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x5a0", - "extraData": "0x", - "baseFeePerGas": "0x1811", - "blockHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6", - "transactions": [ - "0xf865748218128302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0afbda9fa76936bc6be4d26905bc000b4b14cae781a8e3acb69675b6c5be20835a03858ad4e7e694bf0da56994a1e5f855ff845bae344de14109ae46607aa4172ca" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcc9476183d27810e9738f382c7f2124976735ed89bbafc7dc19c99db8cfa9ad1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np145", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6718dc62462698e0df2188c40596275679d2b8a49ab6fd6532a3d7c37efd30a6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa8a6a6386a956afbc3163f2ccdcaeffeb9b12c10d4bb40f2ef67bcb6df7cf64c", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x91", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x5aa", - "extraData": "0x", - "baseFeePerGas": "0x1512", - "blockHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb", - "transactions": [ - "0x02f86b870c72dd9d5e883e7501821513825208947da59d0dfbe21f43e842e8afb43e12a6445bbac00180c080a06ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81eca0568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf67e5fab2e7cacf5b89acd75ec53b0527d45435adddac6ee7523a345dcbcdceb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np146", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x891051fb49d284166b72a30c29b63bfe59994c9db2d89e54ca0791b4dfdb68fb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9ee7ad908d7c553d62d14ecd6a1e9eac6ed728f9a0d0dd8aa8db149e6e803262", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x92", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x5b4", - "extraData": "0x", - "baseFeePerGas": "0x1271", - "blockHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c", - "transactions": [], - "withdrawals": [ - { - "index": "0xd", - "validatorIndex": "0x5", - "address": "0x956062137518b270d730d4753000896de17c100a", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe20f8ab522b2f0d12c068043852139965161851ad910b840db53604c8774a579" - ] - }, - { - "jsonrpc": "2.0", - "id": "np147", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2ef94fa352357c07d9be6e271d8096b2cbf7dcae9bad922e95bc7c7c24375e7c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x14111c2a0f5c36f6b8ea455b9b897ab921a0f530aaee00447af56ffc35940e32", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x93", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x5be", - "extraData": "0x", - "baseFeePerGas": "0x1023", - "blockHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea", - "transactions": [ - "0xf88376821024830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa08e5e1207971ec2479337fa7c80f843dd80d51224eb9f9d8c37b1758d3d5acae4a04d2f89fb9005dc18fa4c72e8b1b4e611f90ca9c5e346b6201dfe4b83ec39c519" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf982160785861cb970559d980208dd00e6a2ec315f5857df175891b171438eeb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np148", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x406fbf5c2aa4db48fce6fe0041d09a3387c2c18c57a4fb77eca5d073586ca3ea", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc43ae2200cea3bdd1b211157150bd773118c818669e2650659ef3807ac7d2c29", - "receiptsRoot": "0x1f4bdefd1b3ded1be79051fe46e6e09f4543d4c983fdc21dee02b1e43fb34959", - "logsBloom": "0x00000000000000000000000000000110000000000002000000000000000000020008000000000000000800001000000000000000000000000020000010000400000000000000000000001000000000000000000000000000000020000000000000101000000000800000000000000000080000000000000000000000000000010000080000080000800000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000200000020000000000000000000000000002000001000000000040002000000024000000000280000000000000000000000000020000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x94", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x5c8", - "extraData": "0x", - "baseFeePerGas": "0xe20", - "blockHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2", - "transactions": [ - "0xf87a77820e2183011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b5b7b281fbe78ca0f9819a9015997a42ee896462db5ea7de089cd7e2cf84b346a02bc85175e51da947f89f947c30d7c1d77daa6e654a0007e56de98812039a76bd" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x230954c737211b72d5c7dcfe420bb07d5d72f2b4868c5976dd22c00d3df0c0b6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np149", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x34ca9a29c1cef7e8011dcce6240c1e36ee8e64643fc0ed98cb436d2f9a21baa2", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x21cafe51bfa7793c9a02f20282b59cbb5156dce1e252ab61f98fdd5cdecf8495", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x95", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x5d2", - "extraData": "0x", - "baseFeePerGas": "0xc5d", - "blockHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031", - "transactions": [ - "0xf86578820c5e8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0371194d9f0d8b28bc888d45cc571dd73c9dd620d54184b9776256d5e07049350a05f7bfb7cdccb54a2f0ea01374f1474e694daa1b128076bdc33efcee9bc0d56a7" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb7743e65d6bbe09d5531f1bc98964f75943d8c13e27527ca6afd40ca069265d4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np150", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xed939dcec9a20516bd7bb357af132b884efb9f6a6fc2bc04d4a1e5063f653031", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x503c44cab4d6c0010c3493e219249f1e30cfff1979b9da7268fd1121af73d872", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x96", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x5dc", - "extraData": "0x", - "baseFeePerGas": "0xad3", - "blockHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746", - "transactions": [ - "0xf86879820ad48252089484873854dba02cf6a765a6277a311301b2656a7f01808718e5bb3abd10a0a0ab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1fa05affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x31ac943dc649c639fa6221400183ca827c07b812a6fbfc1795eb835aa280adf3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np151", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x136665ab7316f05d4419e1f96315d3386b85ec0baeed10c0233f6e4148815746", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2e257bca2ea424f7c304c42fc35b14c8d3fd46c9066c7f895f775a2065a14bab", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x97", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x5e6", - "extraData": "0x", - "baseFeePerGas": "0x979", - "blockHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba", - "transactions": [], - "withdrawals": [ - { - "index": "0xe", - "validatorIndex": "0x5", - "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xded49c937c48d466987a4130f4b6d04ef658029673c3afc99f70f33b552e178d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np152", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xefc08cafa0b7c0e0bc67c0dbd563a855ba55f389d947bd9c524be5ef789505ba", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa124fe0abd3682da7263262172c9d2c57fb42d4f131cbc9f24ddea0ec1505e48", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x98", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x5f0", - "extraData": "0x", - "baseFeePerGas": "0x84a", - "blockHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7", - "transactions": [ - "0xf8837a82084b830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0be58da9e68f28cf1dd209a610214982ba767249f3b92cd8c0fb3850a9ee194d6a0613f59eec6c092b6d2fc55de85bc67b21c261dc48f1ddb74af3aac438b27ccd5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa0effc449cab515020d2012897155a792bce529cbd8d5a4cf94d0bbf141afeb6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np153", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb7a12ba1b0cd24019d0b9864ed28c0d460425eb1bd32837538d99da90f5c65b7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3c05bdceef0bdc9f676a3a0c00151f975e469e5bb08ab08f3eed090987119672", - "receiptsRoot": "0x73faa109b88bfbf7e2a71c36d556d9286c0a26988680cbe3058f045fd361b3b0", - "logsBloom": "0x00004000000800000000000000000000000000000000000000000000000000000004000000080000000000000800000000000000500000000000000000000200000000001000000800000000000002008000080000000000000000000000000000000000000000000008000200000000000000000000000000000001000000000000000000101000004000000000000000000000000000000000000000000000000000000080000000000000000000008200000000000080000000000000000000000000000000000800000000000000000000000400000080020002000000001040000000000000000000000000004000000000000000008000008000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x99", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x5fa", - "extraData": "0x", - "baseFeePerGas": "0x742", - "blockHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718", - "transactions": [ - "0xf87a7b82074383011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b9eb0510fdc334dde88b8ac75869aa2dd53988191ae1df94b7b926eae9b18050a00cbd9e12b7185723ed407175a7a70fa5cc0dbc4014b3040a9ade24a4eb97c8c1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1f36d9c66a0d437d8e49ffaeaa00f341e9630791b374e8bc0c16059c7445721f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np154", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0292db163d287eeb39bd22b82c483c9b83a9103a0c425a4f3954ef2330cc1718", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc2e93862e26d4df238b2b83a3ee0e008f25123aa211d83906fcd77bc9fd226ab", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x604", - "extraData": "0x", - "baseFeePerGas": "0x65b", - "blockHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea", - "transactions": [ - "0xf8657c82065c8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e5959821e9fe4b896ef2559fe6524aadead228d89f923061b6d2d340f6b9307fa02ed2929f37d24a57229f7a579aaab2d9551e71b0822895e91f04e7824da9a861" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x34f89e6134f26e7110b47ffc942a847d8c03deeed1b33b9c041218c4e1a1a4e6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np155", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xaeab3fe4b09329235bd8a0399db4d944fe1b247a91055c7de7f53703c94357ea", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0c94e7ea002f7b3bcc5100783e1e792160fb73ff4e836cd295e34423ff72f2a6", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x60e", - "extraData": "0x", - "baseFeePerGas": "0x591", - "blockHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6", - "transactions": [ - "0x02f86b870c72dd9d5e883e7d01820592825208948d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f20180c001a0f9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897a04cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x774404c430041ca4a58fdc281e99bf6fcb014973165370556d9e73fdec6d597b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np156", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcc221bd9ee16f8302994c688cd7cc18313e686cf21f29edea5da5ac08a28a9b6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x04ba5addea7916f0483658ea884c052ea6d759eeda62b9b47ee307bd46525bb0", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x618", - "extraData": "0x", - "baseFeePerGas": "0x4df", - "blockHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da", - "transactions": [], - "withdrawals": [ - { - "index": "0xf", - "validatorIndex": "0x5", - "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd616971210c381584bf4846ab5837b53e062cbbb89d112c758b4bd00ce577f09" - ] - }, - { - "jsonrpc": "2.0", - "id": "np157", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8c922bb4a1c7aad6fdc09082e5c90427d0643ffd281d0154cdd71a372108c5da", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3ae465791b7ce8492961c071fc50b34434552a1ab36c1854fbc308f55729e827", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x622", - "extraData": "0x", - "baseFeePerGas": "0x444", - "blockHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a", - "transactions": [ - "0xf8837e820445830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0140e450a0bc12c61bdf6acca1a56178466d88014d00a4a09c1088ce184128327a07daad374bb0d7fe879212bd7bdc8d454b4996bd7bebd6f6d0d4636ec7df28d0b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcdf6383634b0431468f6f5af19a2b7a087478b42489608c64555ea1ae0a7ee19" - ] - }, - { - "jsonrpc": "2.0", - "id": "np158", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1a883eed15a2f61dc157140d45f50e4bc6cc08ead08adf3ff0804ec9f1104c8a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe01f0f54fba649cdc0d6da6a9f519b6918149d82f134845e99847ff7b362b050", - "receiptsRoot": "0x36340e11a5f180862d423a676049d1c934b8d27940fdd50dc8704563ffd27b0f", - "logsBloom": "0x00000000000000008000000000800080000000000000000018040000000100100000000000010000000000000000000000000000000000000000000000010000000080080000800000000000010000000010000000000802000000000000000000000000001000000000004000000000000000000000004000000000000000004000000000000000000000000000000000000000000000401000000000010000000000000000000000000000000080000000000000000000000040000240000000000000000000000001000000000000000000000000100000000080000040000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9e", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x62c", - "extraData": "0x", - "baseFeePerGas": "0x3bc", - "blockHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0", - "transactions": [ - "0xf87a7f8203bd83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0331dd2ec5bf4bddde96cacb8a28ed1cc577d4a2289bae6da0e6ef3c9b1287fc3a04c2925895dfbed2b00ac9a2040371970da1a7fd333dc1e551e2e268c56717c79" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x00ec22e5df77320b4142c54fceaf2fe7ea30d1a72dc9c969a22acf66858d582b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np159", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5efcd9acd57f0652b1aa46406cf889b0da1f05e34fa9b642f7dec1bd924f3fd0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa6e1d00e54b539beb170e510a8594fdd73ad2bf8e695a0f052291454ee1f3ade", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x9f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x636", - "extraData": "0x", - "baseFeePerGas": "0x345", - "blockHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004", - "transactions": [ - "0xf86681808203468302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0f4a1b0681bb3c513fa757b560ef9cf0f004b8da91d920e157506ebb60d0d3954a0738da3b003ce68a9b4032770c0fe6481f54ea43baba54cad7153369486728790" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcb32d77facfda4decff9e08df5a5810fa42585fdf96f0db9b63b196116fbb6af" - ] - }, - { - "jsonrpc": "2.0", - "id": "np160", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x97570840bed5a39a4580302a64cbaf7ed55bcc82e9296502c4873d84f8384004", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9277b9454326e993436cef0b9a2e775cff46439f3d683da55a983e9850943a20", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x640", - "extraData": "0x", - "baseFeePerGas": "0x2dd", - "blockHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0", - "transactions": [ - "0xf86981818202de82520894c19a797fa1fd590cd2e5b42d1cf5f246e29b916801808718e5bb3abd109fa0857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291a07d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6d76316f272f0212123d0b4b21d16835fe6f7a2b4d1960386d8a161da2b7c6a2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np161", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4b01a4f9f924e7e386d2c94653c80bab2e3069d744ab107dd181d9b5f5d176d0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc9f74f81ace1e39dd67d9903221e22f1558da032968a4aaff354eaa92289f5c6", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x64a", - "extraData": "0x", - "baseFeePerGas": "0x282", - "blockHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286", - "transactions": [], - "withdrawals": [ - { - "index": "0x10", - "validatorIndex": "0x5", - "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2de2da72ae329e359b655fc6311a707b06dc930126a27261b0e8ec803bdb5cbf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np162", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9431a8d1844da9cc43e8b338de21722e23f78ed5b46391a6d924595759773286", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x853c0a8e4e964cc857f2dd40b10de2cefb2294a7da4d83d7b1da2f9581ee0961", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x654", - "extraData": "0x", - "baseFeePerGas": "0x232", - "blockHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d", - "transactions": [ - "0xf8848182820233830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01a7b8af754eba43e369957a413a3fef1255659f2bd05f902b29ee213c3989d46a00ca88ac892d58fdb0d9bd7640ca797280081275886cc2ac155a814eb498e7d7b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x08bed4b39d14dc1e72e80f605573cde6145b12693204f9af18bbc94a82389500" - ] - }, - { - "jsonrpc": "2.0", - "id": "np163", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x604f361dbc1085fb70812b618e53035d4747c3969a96620e4c179a93be5d124d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd89e02bde63bf214ad6a3bc94f3b092bc2a1fbc13f172049c854ecb070630fe6", - "receiptsRoot": "0x596413315e1e3fd6fc21e4ce81e618b76ad2bf7babfa040c822a5bcbffeb63be", - "logsBloom": "0x00080000001044010000000800000000000000000010000000040000000020000000800000000040000000000000000001008000000000800000000000000000000000001000000000020000080000000000000000000000000000000000000002000044000000000000000000000000000000000000000000000000000000000000002000000000000000800000000000000000000000000000000000104000800000000000000004000004000002000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000800020000000000000000000040000000000000000020", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa3", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x65e", - "extraData": "0x", - "baseFeePerGas": "0x1ec", - "blockHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa", - "transactions": [ - "0xf87b81838201ed83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06e6e8187c035f2788ba44e3f47b4102a1f263ae2f601b2fbfa9e2cdc3b0c22b1a06c229eebca1bdda1aba424cd8cf296f386cf2d50a6add950fd6cb34aac442c5a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe437f0465ac29b0e889ef4f577c939dd39363c08fcfc81ee61aa0b4f55805f69" - ] - }, - { - "jsonrpc": "2.0", - "id": "np164", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x00979cd18ef128aa75a51ad8606b381ce53f72c37d17bc6c6613d8de722abcfa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe2672f9ae97aeaeb22f42c389301a3b79ad6c47ad88c54e18e1d7a4ed5e9c903", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x668", - "extraData": "0x", - "baseFeePerGas": "0x1af", - "blockHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13", - "transactions": [ - "0xf86681848201b08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08ab61fe0265afe289954f7c2af8e070f3c40dda39e6cb6ff5c798fc7bc87b55ba00a8a440a7ba5a04a7bb73b093e94734dda228d33a43c640d719aef5ea5e81764" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x89ca120183cc7085b6d4674d779fc4fbc9de520779bfbc3ebf65f9663cb88080" - ] - }, - { - "jsonrpc": "2.0", - "id": "np165", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcabf8c1b47839908f6eb28261876b52404f3f8787c94d8aadc0aca721ff35d13", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4d9cd7b52c0daaec9a019730c237a2c3424f5d5a004c8bc9fa23997f3ec33768", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x672", - "extraData": "0x", - "baseFeePerGas": "0x17a", - "blockHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff", - "transactions": [ - "0x02f86c870c72dd9d5e883e81850182017b825208946922e93e3827642ce4b883c756b31abf800366490180c080a089e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299a03d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb15d5954c7b78ab09ede922684487c7a60368e82fdc7b5a0916842e58a44422b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np166", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6dcec039f7777c1fd96bbdd342e0ed787211132f753cf73a59847dc6cb30a6ff", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x03629dac3f669a8262e8246d46bac9acfb7cbca336d02e90c081561fa0b22aba", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x67c", - "extraData": "0x", - "baseFeePerGas": "0x14b", - "blockHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef", - "transactions": [], - "withdrawals": [ - { - "index": "0x11", - "validatorIndex": "0x5", - "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xad13055a49d2b6a4ffc8b781998ff79086adad2fd6470a0563a43b740128c5f2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np167", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x760da169c77450231e6a0d2dd4aad67de84633eb6918fc8607a3a709eea07bef", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4f5e79d4af5565b3b53649b1ddc3a03209cb583e7beb03db8b32924c641e6912", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x686", - "extraData": "0x", - "baseFeePerGas": "0x122", - "blockHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9", - "transactions": [ - "0xf8848186820123830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b2aafb3e2678dd48e6f31874bd478778480815c9d110ec8cc77a42f7d52999daa00705b1266fc1087167cc531caa9d2e0a0c8779e4ad5020d9d3a16500bf5b96a1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9e9909e4ed44f5539427ee3bc70ee8b630ccdaea4d0f1ed5337a067e8337119f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np168", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfcb210229cb48baf3d535e48a7577041268eadd6027942084a56dbec8f8423a9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8c6c100b7c75ced82b38315fd50c5439478a7ee256073ce17b845e0815912eab", - "receiptsRoot": "0xf8f8c85b17ada66c06f8e41b58b45213619bb309a197896adbaff4e9139967b1", - "logsBloom": "0x80000000000000000000000000000000800000000004008000200000000000000002820000000000000000000000000000000000000040020400000000000000000000000200000000000000000000000000000040000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000040080000000000000000000000000000000000200000000000000080000200000000000000000000000000000000000000000000000000000100000003000200000000000000000000000000000000000000200000000000000000000000004000000004000000040001010000000080400000000000000040000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa8", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x690", - "extraData": "0x", - "baseFeePerGas": "0xfe", - "blockHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1", - "transactions": [ - "0xf87a818781ff83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0b1e7ca73ef581fc880deb34aa6cf7958f6ce110efd121d48fb2292a747864815a02bf94b17dc034d8934b885faa269a9430a755ebfb4c6e87378376a094704f464" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbf1f3aba184e08d4c650f05fe3d948bdda6c2d6982f277f2cd6b1a60cd4f3dac" - ] - }, - { - "jsonrpc": "2.0", - "id": "np169", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x796a4e02d1da9c86b1a2e7b2ef1d82e1ebdac143ec7ff4a67dae2b241b22c3c1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9f527744fd44cf4c2ba60fe62d25d4f19e64c034cbf24785e0128d5fafa19e2a", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xa9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x69a", - "extraData": "0x", - "baseFeePerGas": "0xdf", - "blockHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d", - "transactions": [ - "0xf865818881e08302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c583bd1010c1e4158466575fb0c09ff710a5ff07c8f7a6e7960d90bffef8bd34a059ea0ba5c6fc64aad73252c780de287599d3100d80f7b1d3201b4865d82c0cad" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbb70fe131f94783dba356c8d4d9d319247ef61c768134303f0db85ee3ef0496f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np170", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x29a0d081e8aec6b2dcb307d73ca48d7d50e434617daf0e81fd28b35be9c7995d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x45c5f07a7d94c320222f43c12b04081fdbe870be18a2b76f7122bd7f4554118b", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xaa", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x6a4", - "extraData": "0x", - "baseFeePerGas": "0xc4", - "blockHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c", - "transactions": [ - "0xf868818981c582520894bceef655b5a034911f1c3718ce056531b45ef03b01808718e5bb3abd109fa0626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9fa07271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6a81ebd3bde6cc54a2521aa72de29ef191e3b56d94953439a72cafdaa2996da0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np171", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe878e98d05f60a8fd741a4aaab17a91c538f21552ac41922fe2b755e4f0e534c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf4a19b9765604687783462dbf36a0063ada2ba7babb4dd1c4857b2449565a41d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xab", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x6ae", - "extraData": "0x", - "baseFeePerGas": "0xac", - "blockHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315", - "transactions": [], - "withdrawals": [ - { - "index": "0x12", - "validatorIndex": "0x5", - "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4c83e809a52ac52a587d94590c35c71b72742bd15915fca466a9aaec4f2dbfed" - ] - }, - { - "jsonrpc": "2.0", - "id": "np172", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc3f33c71274b456303efd80efacba7d5fccb0ed278ee24e5594a38c45a294315", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4f9e280291036fb6cd64598fe0517d64d6da264d07d7fc3b8d664221d7af9021", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xac", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x6b8", - "extraData": "0x", - "baseFeePerGas": "0x97", - "blockHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5", - "transactions": [ - "0xf883818a8198830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a05f47b0ab77130dcc8f7143a2afaace6a2d1f82e25839cb9adee5aaebfe7dc681a05af90b75de35c90709b83861d8fdfd7805a89b1e76a4bdd5987e578ba72fc37e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x268fc70790f00ad0759497585267fbdc92afba63ba01e211faae932f0639854a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np173", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd785018f59628b9f13cc2d4a45e0b4b3af183acce4e5752346e79dbcdf7de4e5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe01cadedc509806ea9cd7475312a3768de034d1c849abadc46237b8cd4163179", - "receiptsRoot": "0x15dc68f6de1b068b96d32dbc11a048b915e7d62bd3662689ae5c095bb6ddab37", - "logsBloom": "0x00000100000000004000000004000000000000000000000000000000000000000000000004000000018004000000000000000000000000000002000000000000000020002000400000002000020000000100000000000000000080010000400000000000000200000000040000000000000000000000010000002000000000000000000000000004040000000000000000000000000000000000000000004000000000000000000000080000004000000000000000000000001000000000000100000800040000000000000000000000000000000000000000000000000000000000000000400000000000004001000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xad", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x6c2", - "extraData": "0x", - "baseFeePerGas": "0x85", - "blockHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb", - "transactions": [ - "0xf87a818b818683011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04a74ea0833e42d624ba0d9b589a16e05feae1c2dee89abfb29df95b650d3e756a037135f3e24572eb9d927a02c0c4eee7fd5d8a181e2384ef3b3b04c49c9dbbbe1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7e544f42df99d5666085b70bc57b3ca175be50b7a9643f26f464124df632d562" - ] - }, - { - "jsonrpc": "2.0", - "id": "np174", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbcff8f4e8c3d70d310900cd8246c3456e237ab8ea9fc036601995404b141e3bb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa862687747ffc388414ee5953589a70f2161a130886348157257a52347be9157", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xae", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x6cc", - "extraData": "0x", - "baseFeePerGas": "0x75", - "blockHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4", - "transactions": [ - "0xf864818c768302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a024414367540c94b1bd3ce29dd0b4ee6bdece373f9417e96f0ef8d632e82c4ecba031dae9539e84f7351a5b92f1246dfd909dd5a383011fbd44bb8e87fb6870189b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd59cf5f55903ba577be835706b27d78a50cacb25271f35a5f57fcb88a3b576f3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np175", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x943b23302ffed329664d45fee15ca334c92aa6195b22cb44c7fdd5bdbbe4e7d4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd70339e1158ecc97dc7db86b3177202ffa3dcba386fd52e54e6fe8b728003154", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xaf", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x6d6", - "extraData": "0x", - "baseFeePerGas": "0x67", - "blockHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351", - "transactions": [ - "0x02f86a870c72dd9d5e883e818d0168825208945a6e7a4754af8e7f47fc9493040d853e7b01e39d0180c001a08c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122a028e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x551cced461be11efdeaf8e47f3a91bb66d532af7294c4461c8009c5833bdbf57" - ] - }, - { - "jsonrpc": "2.0", - "id": "np176", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd2a0fc154d0bb77b346c7bb3532d24581bc1a5b5bf9ced18b419a6309ff84351", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1bc27508b52de3a750cc928dd89954462b4e4dbfb60707442e60b4b23aabb816", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x6e0", - "extraData": "0x", - "baseFeePerGas": "0x5b", - "blockHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970", - "transactions": [], - "withdrawals": [ - { - "index": "0x13", - "validatorIndex": "0x5", - "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc1e0e6907a57eefd12f1f95d28967146c836d72d281e7609de23d0a02351e978" - ] - }, - { - "jsonrpc": "2.0", - "id": "np177", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe3072603b13de812d2c58ece96eeb4f32ff7e3e93c8b9121dd18f0682a750970", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x78497ebf1fbf03732772a8c96b2fe6902af5ab844e49f2685763b4366ce8ddf6", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x6ea", - "extraData": "0x", - "baseFeePerGas": "0x50", - "blockHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238", - "transactions": [ - "0xf882818e51830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fd5ea8b7df5c3ecd87220b8ad7d15198722d94a64b0e8e099c8c7384c1d08a33a039707925aba6dad8d06c162fd292df0bf03033b7b6d1204ae4be0ce6f487fa71" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9d580c0ac3a7f00fdc3b135b758ae7c80ab135e907793fcf9621a3a3023ca205" - ] - }, - { - "jsonrpc": "2.0", - "id": "np178", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x996acbdde853cdc1e21426f4e53d07c09a13ed50798ee071582f24cc1014e238", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x197c4166e7f8f68ee6965c87c8ce720bee776a7b7119870371e6262bc913468d", - "receiptsRoot": "0x7c66f99e4434aa19cdf8845c495068fa5be336b71978d6fa90966129f300218a", - "logsBloom": "0x00000000000000000000000000400200000000000000800000000000000000008000008000000000000000000000000000000000000000000040000004000041004000000000000000000000000800000000000000000000000000000000080100000000000000000000000020000000004200000000001000000002000000100008080200000004000000000000200000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000800000000200000000000000000000100002000000000000000000002000000000000000000100000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb2", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x6f4", - "extraData": "0x", - "baseFeePerGas": "0x47", - "blockHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf", - "transactions": [ - "0xf879818f4883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03e0f9aa0ca6ec8b4f9e7fccd9b710c0de4414618726e298b36816cd6d689a89aa07d3950b5ebbaa58f5c4e0bc0571499d9d58d563ce2c039664cf210815e43d0e5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa7fd4dbac4bb62307ac7ad285ffa6a11ec679d950de2bd41839b8a846e239886" - ] - }, - { - "jsonrpc": "2.0", - "id": "np179", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf00d6a4f13579131abcd2c856040cf9295caed200698d7cf7a1574690b36b0bf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf56610f73e08c2ccaaa314c23bc79022214919c02d450cab12975da3546b68fd", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x6fe", - "extraData": "0x", - "baseFeePerGas": "0x3f", - "blockHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468", - "transactions": [ - "0xf8648190408302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f41a67e92f032c43cc601daa205026cc5a97affb0f92064991122a1aa92428dfa0237053c462847907c840ada5076caab16adc071da181e9277926a310adcb8e3d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6ba7b0ac30a04e11a3116b43700d91359e6b06a49058e543198d4b21e75fb165" - ] - }, - { - "jsonrpc": "2.0", - "id": "np180", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5711092388b2fd00bf4234aca7eede2bdc9329ea12e2777893d9001f4f2c8468", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfa57370da0cc72170d7838b8f8198b0ebd949e629ca3a09795b9c344dead4af5", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x708", - "extraData": "0x", - "baseFeePerGas": "0x38", - "blockHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517", - "transactions": [ - "0xf8678191398252089427952171c7fcdf0ddc765ab4f4e1c537cb29e5e501808718e5bb3abd109fa076a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7a01a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8835104ed35ffd4db64660b9049e1c0328e502fd4f3744749e69183677b8474b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np181", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb58807a37c03cf3b0f1c9104cfd96f6cb02b1e08e0eecdd369cac48d0003b517", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6d3f029e56f9ee3db9ed8f9156cd853fb1fcafe05475ec8c2a4dd337a5e3e20e", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x712", - "extraData": "0x", - "baseFeePerGas": "0x32", - "blockHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a", - "transactions": [], - "withdrawals": [ - { - "index": "0x14", - "validatorIndex": "0x5", - "address": "0x892f60b39450a0e770f00a836761c8e964fd7467", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x562f276b9f9ed46303e700c8863ad75fadff5fc8df27a90744ea04ad1fe8e801" - ] - }, - { - "jsonrpc": "2.0", - "id": "np182", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x56b5aa12ccfcbd86737fe279608cb7585fbc1e48ddfcdac859bb959f4d3aa92a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x58a6332c9e7b85155106515f20355c54bb03c6682024baa694cbaff31c3b84ff", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x71c", - "extraData": "0x", - "baseFeePerGas": "0x2c", - "blockHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c", - "transactions": [ - "0xf88281922d830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa01ae40537174a716b5f33d153e9251ae8c1d72852da25823f6d954b9dbc5740cca02ff07812990e0645cab5c9d89028f7255f50d0eee5bee334b3ba10d71485c421" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd19f68026d22ae0f60215cfe4a160986c60378f554c763651d872ed82ad69ebb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np183", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb0d7fbd46bd67d4c3fa51d0e1b1defaf69237d0f6e2049486c907b049b47e01c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x55d4e87d040358926c84414b854fc47a75b9963df75e359a2182464c51201088", - "receiptsRoot": "0x1fccfe93768ce1ed60d0f83cbc8bef650cb1d056c35a4b233ae41a1b8219f92d", - "logsBloom": "0x00000080000000000000000000000000000000000000004000000000000010000000000000000000000000000000014000800000000000000100102000000000000000000000020000000000200000000000000000100000000000200000002000000000000000000000002000000000000000000000000000000000000000001000002000400020040000000000000200000000000000000000000000000000000000002000000000000000000000100000000000022000000000000000000000000000000004000000080000000000000000000000000004004000000000040002000040000000000000000000000000000000000000000000000000100000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb7", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x726", - "extraData": "0x", - "baseFeePerGas": "0x27", - "blockHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4", - "transactions": [ - "0xf87981932883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa02d1dcc844efba97a51917ab3d79f837680f42e2e76ab51b4b630cbe9a6e4e10ea03d3f624c82de14b23b0c5553621cc9a4c649cd856a616f5a91bad8bf0c0d1709" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf087a515b4b62d707991988eb912d082b85ecdd52effc9e8a1ddf15a74388860" - ] - }, - { - "jsonrpc": "2.0", - "id": "np184", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x66011454670d5664e8e555d01d612c70cadabfb6a4a317f375495ef3daa9d1b4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd3ec16ab633987e17a4e8c573014b1fc9919f004b3cb80da11280d1caad1fe3e", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x730", - "extraData": "0x", - "baseFeePerGas": "0x23", - "blockHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94", - "transactions": [ - "0xf8648194248302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a01e5301a3386e11893c0275367ac5d31fea88f31731e66ee769bfddc3486cff1aa0203dbf8bbfa9df2d635e1889d51e06611e8c2a769609908aeb5e97decb03b141" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf7e28b7daff5fad40ec1ef6a2b7e9066558126f62309a2ab0d0d775d892a06d6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np185", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x36e1e3513460407c80dfcfab2d2826ea432dadb99aa7415f9cffcf56faf27f94", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x692ddd6938f00a07474233619f579b30c1eaaef353a2b0cc24b47d7898aa5c49", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xb9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x73a", - "extraData": "0x", - "baseFeePerGas": "0x1f", - "blockHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260", - "transactions": [ - "0x02f86a870c72dd9d5e883e819501208252089404d6c0c946716aac894fc1653383543a91faab600180c080a0039c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8aa05ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x77361844a8f4dd2451e6218d336378b837ba3fab921709708655e3f1ea91a435" - ] - }, - { - "jsonrpc": "2.0", - "id": "np186", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x44e05b6820cf1d7cf9cd2148d6f71a6a649c9a829b861539d2c950f701e27260", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9eac86abf4371646a564bb6df622644682e5de5bf01fed388ccaf10700e46e88", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xba", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x744", - "extraData": "0x", - "baseFeePerGas": "0x1c", - "blockHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0", - "transactions": [], - "withdrawals": [ - { - "index": "0x15", - "validatorIndex": "0x5", - "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe3cb33c7b05692a6f25470fbd63ab9c986970190729fab43191379da38bc0d8c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np187", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcc3b1096f3ce63881c77751baec2048561baa2dc84ea0ef9d3a5515061aa74e0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xff13e99ee95ffe82139758f33a816389654a5c73169b82983de9cf2f1f3dbd9f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xbb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x74e", - "extraData": "0x", - "baseFeePerGas": "0x19", - "blockHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a", - "transactions": [ - "0xf88281961a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0276782d84f5f6ab0805be5e57923747bae9fa2b06ed4b45bcc364bdb4f09eca1a0484f9fc2a31a4b5f24ba33da54649e6a3261c0bee52d91576246bb54698c1535" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc893f9de119ec83fe37b178b5671d63448e9b5cde4de9a88cace3f52c2591194" - ] - }, - { - "jsonrpc": "2.0", - "id": "np188", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x871cb66f77db23f8e70541a647329c5ca9b6d40afd3950d48df4915f300e664a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x522c1eb0c4d1332668a2e3676efd54899579d85fd4e7007fd228702d9c964baa", - "receiptsRoot": "0x90d4e326daf1e15e41687f281f8e638992c4cdfbe590eb4956fd943aa39f1bba", - "logsBloom": "0x48000040000000000000000000004000000000000000000000400000000000002000000000000000000000000000000018000000000000000000002000000000000000000000100000002000000800000000000000000000000000002000000000000000000000000000000000000000040000020000040000000000000000000000000101000000000000000000010000000000040000000000000000000000008000000000000000000000800000000000201008000000000000001000000000000010000000000000100000000000000000000000040100000000000000000008000000000000000000000000000000000000004000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xbc", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x758", - "extraData": "0x", - "baseFeePerGas": "0x16", - "blockHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d", - "transactions": [ - "0xf87981971783011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0870548904b9e901c294fd1c04a6cff92fbb40491e00a1ffcbc551c6c5eba2db3a0524ff53000a94b71aef3a2c516354bc5d7fdb3f236d4647020762a56d9bd2fbf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x39c96a6461782ac2efbcb5aaac2e133079b86fb29cb5ea69b0101bdad684ef0d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np189", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x174a8681a0d28b9a3d49afb279714acb2bfe4a3abfe490522bb3d899d3c71c8d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfb0eecb29a002997c00e0f67a77d21dd4fa07f2db85e3e362af4bbfcb69b6c12", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xbd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x762", - "extraData": "0x", - "baseFeePerGas": "0x14", - "blockHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1", - "transactions": [ - "0xf8648198158302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0111d3d32f82c89fc830943a4aa0b20e013886491e06acede59ea4252b3366c05a07b9f9199ecdb210151db8a50c74fa1488b198db4e5dda3ad1fa003b70d9bd03a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x72a2724cdf77138638a109f691465e55d32759d3c044a6cb41ab091c574e3bdb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np190", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1b56a73d407c9a5e222c2097149c2f2cbb480a70437ee41779974b8ab968a8e1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x36fce9409ec76cfda58bd4145be0289d761c81131ed0102347b96127fd0888e2", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xbe", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x76c", - "extraData": "0x", - "baseFeePerGas": "0x12", - "blockHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9", - "transactions": [ - "0xf86781991382520894478508483cbb05defd7dcdac355dadf06282a6f201808718e5bb3abd109fa0910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178a02ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x178ba15f24f0a8c33eed561d7927979c1215ddec20e1aef318db697ccfad0e03" - ] - }, - { - "jsonrpc": "2.0", - "id": "np191", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x07d1571c1d0fbaf6cd5c2fa18e868d6dfc2aa56f7ee3bd5aaf61fa816d775ee9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd5d1fc871c3a4694da0e9a9f453c0e6f4c8f38fbef45db36c67cd354e22eb303", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xbf", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x776", - "extraData": "0x", - "baseFeePerGas": "0x10", - "blockHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4", - "transactions": [], - "withdrawals": [ - { - "index": "0x16", - "validatorIndex": "0x5", - "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf7b2c01b7c625588c9596972fdebae61db89f0d0f2b21286d4c0fa76683ff946" - ] - }, - { - "jsonrpc": "2.0", - "id": "np192", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xda1708aede1e87f052ee6e9637f879462b613e4cbddacb18aa49907b55094ce4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4d19a2ce0d61642b6420c9f23ea32bb72ebe24384ed110394d7e5ca98589f055", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x780", - "extraData": "0x", - "baseFeePerGas": "0xe", - "blockHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45", - "transactions": [ - "0xf882819a0f830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02356373d8d8ca7c15e547e717f7327ab0d803867cfabedf8d75e4d1cb264862ca011a3879ae15ab356e9558926382b7fa68b5c5a5c5b127b6f5176523dfe0ae986" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x16e43284b041a4086ad1cbab9283d4ad3e8cc7c3a162f60b3df5538344ecdf54" - ] - }, - { - "jsonrpc": "2.0", - "id": "np193", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x082079039cffbdf78a5cc86fddb47d96c888e0e90b092f9e0591e0099086cc45", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd67263b379522c5059bb0a7164b9cd3fa70697e4012b3b5c519ecf888dbc5700", - "receiptsRoot": "0xc1c820ad9bde8ce9524a7fa712d4849dc2f9f9553e8c00f1fe6c41323e31fbf7", - "logsBloom": "0x00000000000000000000000000000000000000000080000000000200000040000000000000000000000000000000000000000000000000000000001000000000000000000000000000001002000004020000000000000000000011000000000000000080000082000082080000000404000000080010000000000000000000000000100000010000000000000400000000000000000000000000000000400402000000000000000000000000000000000000000000200000000000002000000004000000400000002000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000800000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc1", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x78a", - "extraData": "0x", - "baseFeePerGas": "0xd", - "blockHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3", - "transactions": [ - "0xf879819b0e83011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03423551e59962468cb263c416cb4025c462624b8c8c687177571976c345a8d20a0190d3ab5979e300998fc96429a75c50e1c195115cada83e01fb14a28f2e294de" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0a98ea7f737e17706432eba283d50dde10891b49c3424d46918ed2b6af8ecf90" - ] - }, - { - "jsonrpc": "2.0", - "id": "np194", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe1207296a903bee61a02dd94d685640d76ab57ea96dd5789819583e35f2d7eb3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2111d275b4901e864fcded894a9d9a046f9077d8f6c5af65a72c2243a32dbeaa", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x794", - "extraData": "0x", - "baseFeePerGas": "0xc", - "blockHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f", - "transactions": [ - "0xf864819c0d8302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b4dac384ec258b1a752856b3fcda42244c3e648577bf52d74f25313b3327bf1ca02f7b54b9475768335aab1778fd7ec882f3adbc9e78d4d04a0b78e93e4d41a76b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7637225dd61f90c3cb05fae157272985993b34d6c369bfe8372720339fe4ffd2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np195", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8fd42cbdbbe1b8de72a5bb13684131e04572585077e0d61a0dfbb38d72ef309f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2efd726637cb91156021ac4ae337a87f9a1f28efd620de55b77faef0d3b84b22", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x79e", - "extraData": "0x", - "baseFeePerGas": "0xb", - "blockHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1", - "transactions": [ - "0x02f86a870c72dd9d5e883e819d010c82520894ae3f4619b0413d70d3004b9131c3752153074e450180c001a07cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54a03bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6a7d064bc053c0f437707df7c36b820cca4a2e9653dd1761941af4070f5273b6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np196", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x326484b702b3c743f907227c8aad8733b1a6b7fda510512fe4fec0380bfbc0f1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xeba72457992e05a38b43a77a78ba648857cec13beb5412b632f6623521fe248d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x7a8", - "extraData": "0x", - "baseFeePerGas": "0xa", - "blockHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d", - "transactions": [], - "withdrawals": [ - { - "index": "0x17", - "validatorIndex": "0x5", - "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x91c1e6eec8f7944fd6aafdce5477f45d4f6e29298c9ef628a59e441a5e071fae" - ] - }, - { - "jsonrpc": "2.0", - "id": "np197", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6a40d1d491a8624685fa20d913a684f691f1281da37059d527241526c965874d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8713a1c42af83625ae9515312298d02425330b20a14b7040ec38f0655cb65317", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x7b2", - "extraData": "0x", - "baseFeePerGas": "0x9", - "blockHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14", - "transactions": [ - "0xf882819e0a830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02ed567eed3a763f56fe05c1e44575993df5b6cf67e093e0e9b5ec069ecaf76a2a04891e566e0d136b24d62ffe17f2bfaa0736a68f97b91e298b31897c790b2ed28" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa1c227db9bbd2e49934bef01cbb506dd1e1c0671a81aabb1f90a90025980a3c3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np198", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x25702b83ea77e2ad219178c026a506fa7a9c3f625b023963bc9c13c0d5cfeb14", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2250f011d079600d76d5905dca93324f2fceb110390e8a7e7177569bd8ec73fd", - "receiptsRoot": "0x8027ec2e573bf62c00695cb9a0f67e28e4cce8dc44dc641d7388e4864d8ff78a", - "logsBloom": "0x00080000100000000000100000000840000000000000000000000000000000000000000000000000000000000000000000000000080080000080000000000000000000004000000000000000000000000000000000000000000000000000000200000000000000100100000000008001000000000000000000800000000000020010000000000000000000000000001000800000200000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000012000000000000000000040800000040004000000040000800001000000000000000000000000000000010000100000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc6", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x7bc", - "extraData": "0x", - "baseFeePerGas": "0x8", - "blockHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22", - "transactions": [ - "0xf879819f0983011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0c362dc6d498fcbd0eab0518a012a348d87fe4f2e53f7843f350662c43258609ba026d83d49fd9654704da7435b3400713ed7909a7203d6c55b8d43dd1e9fe67226" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8fcfc1af10f3e8671505afadfd459287ae98be634083b5a35a400cc9186694cf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np199", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa752bd3886362e9e5e57dba077628fedbfbca6b2a657df205ad20d739b035c22", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa8faa1ccb44b8d8d3ad926bdcb75a9e9fd18fa77728ef12aa9c4ba7be1906d3f", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x7c6", - "extraData": "0x", - "baseFeePerGas": "0x8", - "blockHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad", - "transactions": [ - "0xf86481a0098302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a08683c22fc25a5413b758a32c5a6515b1b055541ad523ae4159c4d04c3f864260a06c8f2e1e929e9df95158a161e793ae162e1e4297f8042bf9358dcc119f5545e5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcc1ea9c015bd3a6470669f85c5c13e42c1161fc79704143df347c4a621dff44f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np200", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5d80c24a7a87ae0ab200b864029fbfe7bb750ba0a01c07191b7f52330d2c79ad", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe4f7f192080fd853f053608561854cdb68eb8de9eda499fd7ad840ca729487d3", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x7d0", - "extraData": "0x", - "baseFeePerGas": "0x8", - "blockHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae", - "transactions": [ - "0xf86781a109825208947c5bd2d144fdde498406edcb9fe60ce65b0dfa5f01808718e5bb3abd109fa015f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391a03b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb0a22c625dd0c6534e29bccc9ebf94a550736e2c68140b9afe3ddc7216f797de" - ] - }, - { - "jsonrpc": "2.0", - "id": "np201", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0fd7e67081119b73ebe7ae0483ce2154a2dfb8c503545d231e2af1f8942406ae", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5188152524460d35f0c837dab28ac48f6aac93a75ecbb0bcb4af6a9c95e18a67", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xc9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x7da", - "extraData": "0x", - "baseFeePerGas": "0x8", - "blockHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b", - "transactions": [], - "withdrawals": [ - { - "index": "0x18", - "validatorIndex": "0x5", - "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x92b8e6ca20622e5fd91a8f58d0d4faaf7be48a53ea262e963bcf26a1698f9df3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np202", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3043a03ed3369ba0dfdddac07cae4ca805dbbb0b411b3f5dd5e66198928a715b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x09f47830b792bc39aa6b0c12b7024fa34d561ff9e0d32c27eab5127239799bb0", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xca", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x7e4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8", - "transactions": [ - "0xf88281a208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03b50dfd68a93199762b4b47c08ca4c9f67d99e772f3fec9843a4e1c3ae4d6963a070a7b2cc31e53de9d1fa14f55f28b212979bd83bbd9e9097e65845e05a9ee40f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf6253b8e2f31df6ca7a97086c3b4d49d9cbbbdfc5be731b0c3040a4381161c53" - ] - }, - { - "jsonrpc": "2.0", - "id": "np203", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9178b45b38e39c3e3f4bc590a301254543eedb5b146bed0900465b194aaf94e8", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6a0d6e0a749247b4271d54ddfd2732ceb5b377c1db1ac40aa1d2339d3a143aaa", - "receiptsRoot": "0x189141497b4062bfbe61a7fb2f96cc8a95543e38c077c9150b740f8d01a313a8", - "logsBloom": "0x00000000000000000000040040000000000000000000080000000000004000000000000000004000000000008000000000000000000080000002008001000000000000000010000000000080000000000000000000200000002000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000020000000000000000000000800040000000000000000400000000000000000400001000000004000001000000000020000000000010000000000000000000000000000000000000000008000000000010000100000000000000001000000010000000000000800000000000000202000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xcb", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x7ee", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7", - "transactions": [ - "0xf87881a30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109f9f3c7a9aedd154caa41f602593b4bc78db1101336a81095174d4487dd8338878a0458e45144a4d1a634950ae79ac251065204776baa96a3f94c6d71a00323fe9b4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xea8d762903bd24b80037d7ffe80019a086398608ead66208c18f0a5778620e67" - ] - }, - { - "jsonrpc": "2.0", - "id": "np204", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9a575aa75a5f08a27533140141ffc7ed7d6e981da97316baf296dd1f8d1007d7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xda96365c5a33f358ed732463139254c4f186e899ad00b05d9a30ff39d4d1a27d", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xcc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x7f8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1", - "transactions": [ - "0xf86481a4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a82c39f1be580d16334c133165d5ceb8d9942b184ecccea09e73ff45120ac523a04432d6958bb18882f9f07e851abe454039a5b38d61fd975c7da486a834107204" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x543382975e955588ba19809cfe126ea15dc43c0bfe6a43d861d7ad40eac2c2f4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np205", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb35f9d9c454a03adc1eeeaa9fef20caeb8f9445663a4768d18bc0bc1790650b1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2258c0e37e5bedab21f7ea2f65190d1d51f781743653168d02181c8f16246c71", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xcd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x802", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952", - "transactions": [ - "0x02f86a870c72dd9d5e883e81a50108825208949a7b7b3a5d50781b4f4768cd7ce223168f6b449b0180c080a04f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25a0312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x095294f7fe3eb90cf23b3127d40842f61b85da2f48f71234fb94d957d865a8a2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np206", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x97f4a4e64ede52b5dfd694236e783d130206d111cf6a5eb83a3bb9a230dfd952", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xda2ecb481078839fd39c044b3fceae6468338266d9572da0f2281e58b9596914", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xce", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x80c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4", - "transactions": [], - "withdrawals": [ - { - "index": "0x19", - "validatorIndex": "0x5", - "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x144c2dd25fd12003ccd2678d69d30245b0222ce2d2bfead687931a7f6688482f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np207", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb3c2c9a5de90f0637203e60288b50ecb21d17a2437cccf553d2424321fa112d4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf0f20309e2cec2fb6af448c58c40e206b788241bb88e62a8e7479aadc6bfa94e", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xcf", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x816", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da", - "transactions": [ - "0xf88281a608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa079aa26a33abe2e9504cfc6552c6b39434478b081f5cbbb613269d64980edaf93a079ffe44aec63b05644681b948ea0e5a996e106f3e074a90991c963ff3e7a8aa6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7295f7d57a3547b191f55951f548479cbb9a60b47ba38beb8d85c4ccf0e4ae4c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np208", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9e63e1a7df1b726901e3139cfb429592ef8d2107aa566bcae5f3b8e21f99f0da", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x177fc88f477d3dd466f7cac43b50d4b2b77fd468ef479177ed562d2401acd6c0", - "receiptsRoot": "0xd1458a51a7ca8d2c87390d85d986956f392bdd634ffbe4d5a7e2b09a142ce514", - "logsBloom": "0x00200000000000000000000000000000000000000400000000400000000000000000100400000000000000000010108000000000000000000000200800000000000004000000000000000002000000000000000000000000000000020002000408000021000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000002000000000000000000000400000000000000000000020000000000000000000000800000000000080000000000000000000000800000810002000000000400000000000000000000000000000000000000000000020000000000000000000000010080000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd0", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x820", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a", - "transactions": [ - "0xf87981a70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0969f6d3d90ca6b62cbda31ed28b7522b297d847e9aa41e0eae0b9f70c9de1e01a0274e038abf0b9f2fba70485f52e4566901af94c9645b22a46b19aebb53b4c25d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9e8e241e13f76a4e6d777a2dc64072de4737ac39272bb4987bcecbf60739ccf4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np209", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4e8e6e31a8922b68a96992288e49ab9716dd37f1da1ae5b22391bc62d61ac75a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x55980d8ac0e8bfd779b40795a6d125a712db70daa937ace1f22a5fcd5fd2dfa6", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x82a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd", - "transactions": [ - "0xf86481a8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa04973c2a9d2fcff13428e8a3b3f0979185222cad34366777db8dfc6438cdac357a0128ad521391c000e18211ad8ffa45b41962fca43be83a50ce299d3bd4407f44b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfc753bcea3e720490efded4853ef1a1924665883de46c21039ec43e371e96bb9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np210", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xaf3e413fc388e1a5508f683df5806fe31d29f5df4552ccf2d6c6662816fae5fd", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x522d0f5f8de1ef5b02ad61a3bff28c2bd0ce74abca03116e21f8af6e564d7fd2", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x834", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c", - "transactions": [ - "0xf86781a9088252089485f97e04d754c81dac21f0ce857adc81170d08c601808718e5bb3abd109fa0547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0a028cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5f5204c264b5967682836ed773aee0ea209840fe628fd1c8d61702c416b427ca" - ] - }, - { - "jsonrpc": "2.0", - "id": "np211", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa5b31d7aaa42b7be0c35a0fa375718d25441f90296550c10325a3e0f4d63217c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xda7dd7f5babcf1b3c407e141b4ea76932922489f13265a468fb6ab88891ff588", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x83e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003", - "transactions": [], - "withdrawals": [ - { - "index": "0x1a", - "validatorIndex": "0x5", - "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5ba9a0326069e000b65b759236f46e54a0e052f379a876d242740c24f6c47aed" - ] - }, - { - "jsonrpc": "2.0", - "id": "np212", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa1ffa80abb4f7f92b3932aa0ca90de5bb4a2908866b3d6727b05d5d41139e003", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb6724f1d73bee909624707836e66ffbb21b568dd5bd697668ce18a4ae31818a4", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x848", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c", - "transactions": [ - "0xf88281aa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e582e9d64ed6f95da074eaeb70ca1e47e8627bb7cd4e34d5aab01ff49ee6dd90a022cc32cc7c3030b0b47f1f69911311acd2ae3e95f19f766b69ebb67804676262" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb40e9621d5634cd21f70274c345704af2e060c5befaeb2df109a78c7638167c2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np213", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9a77bcf7bf0d7e6cebeb8c60b4c36538b4fab0e633b9683ba589981c293a009c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6a1c08c9dfcc48c37e349407f37f9c10d9d4c4b1d6c28d30af2630679c74ea96", - "receiptsRoot": "0x730ab6f592da8dfc7815bcba110f6de8dd0343aa932f55b589ff99d83b9ec358", - "logsBloom": "0x00000000000000000000000000000000000000200000000400000000000000002008008000100100000800000000000020000000000000000000000000000000800001000000002000000000000000800000010000000000000000420008000004000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000004000000000000008000000000000000000000000000000000000000000000000000000400010000000000004000000000000008000000840000000000000000040000000000000000000000000000120000001000000100000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd5", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x852", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5", - "transactions": [ - "0xf87981ab0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08747d48d3358eb47195c17f67f22af5eca1177fba591b82b8b626058a347b2e5a0420e02657efee51f73f95017b354b1bca2850269a5de7b307a280c63830f3333" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x70e26b74456e6fea452e04f8144be099b0af0e279febdff17dd4cdf9281e12a7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np214", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xecb42acc218101eb9c6d883a333d07c7736d7ed0b233f3730f5b9c9a75314cf5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x67ca707e9bd81330c2fb9060e88ce0b0905c85c9be26ae4779874f3892ebab0c", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x85c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d", - "transactions": [ - "0xf86481ac088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a03752a40997c9b7b9c5dfd48f88990ddc727517540c403dadcb7476b8a4a9d4f6a0780178975646114017be4b06fae0689a979a45166f810604f76934239b0a2b9e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x43d7158f48fb1f124b2962dff613c5b4b8ea415967f2b528af6e7ae280d658e5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np215", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1191fbb4f2692461fc0ae4aa7141a1743a345c101dc9db157bc7ad3072fe1e9d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3b5ca86f1650f79fb42d74e523dc4e631989a3175023ced9a239e9bcc2c15a8e", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x866", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a", - "transactions": [ - "0x02f869870c72dd9d5e883e81ad010882520894414a21e525a759e3ffeb22556be6348a92d5a13e0180c001a0047b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab669fb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb50b2b14efba477dddca9682df1eafc66a9811c9c5bd1ae796abbef27ba14eb4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np216", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9b9e271d571b730c9e6acd133c99eba1ccd8b8174ffe080540fc3b1a5625943a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc1ab95016db7b79d93ee0303af69ce00bdb090d39e20a739d280beb3e301c9d5", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x870", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54", - "transactions": [], - "withdrawals": [ - { - "index": "0x1b", - "validatorIndex": "0x5", - "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc14936902147e9a121121f424ecd4d90313ce7fc603f3922cebb7d628ab2c8dd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np217", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4e27c497c83c3d06d4b209e7d5068920d7e22bb3c959daa4be5485d6ab0cce54", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf8c17319b995ce543f9ace79aab7f7c928b36facae4e6e0dd50991f95bed1542", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xd9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x87a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678", - "transactions": [ - "0xf88281ae08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05a8e9e2a3556016a65d5b99849bd44cd6ab17cfb15d7850356c9b491357f0611a01f7d3c43fe1759b4ec768275e918e12dae75db56a5d2140d1403ef3df41f56df" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x86609ed192561602f181a9833573213eb7077ee69d65107fa94f657f33b144d2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np218", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdf05b4a3aff6236d0d3c1ee058b874309c37005a2bbb41a37432b470ed49e678", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x05bd7288ee80780a92b234fec2f8bb5bb4d0425721ddbf89d866c62b288f6bff", - "receiptsRoot": "0xbebbd614564d81a64e904001523ad2e17a94b946d6dfc779928ec9048cf9a3f7", - "logsBloom": "0x40000000000020000000000040000000000000000000001000000000000000021000000000004008000000000002000001000100000000000000002000000000000400000000000008002000000000000000100000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000100000400000000000000000000000000000000000000000000000000000020000000000010040000002000000000000000000000000000000000000000000000000020000000000200000000000200000000000000011000000000201400000000000001000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xda", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x884", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46", - "transactions": [ - "0xf87981af0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0b3a49ddc2fc9f12cb1dc0a67623d5a1a6a1b5bf59a8f1736c9f0ab3b564250d3a05fc1ca6dab6b9337827afb55342af8a51fae064157e9c78b76dacd66bbea55d1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0a71a6dbc360e176a0f665787ed3e092541c655024d0b136a04ceedf572c57c5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np219", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf9a9d8409219172c2a602cfb9eadffdeb13a68c55a48e048a19c3b17d85e3b46", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8236fb6bc66022c43d12c08612fd031d8b42852bef9a2dec04c1bc4b83cba489", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xdb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x88e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6", - "transactions": [ - "0xf86481b0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08a2bbd86fd1bb42e548fa4b4c4710f6c6ed03b4700f9e3a213bc70d17f016a3ca076d8bf736d722af615228680c31acd9815b9380a8bc5895cddb2361170274a7f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa4bcbab632ddd52cb85f039e48c111a521e8944b9bdbaf79dd7c80b20221e4d6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np220", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf69983460a4d977eceea022607df6db15b3d8103f78e58d73eeac3593053dbc6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1d9d412ef451097aa53e4fc8f67393acfd520382a1c4cfa6c99e2fb180a661db", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xdc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x898", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6", - "transactions": [ - "0xf86781b10882520894fb95aa98d6e6c5827a57ec17b978d647fcc01d9801808718e5bb3abd10a0a0c71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0a03bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2bc468eab4fad397f9136f80179729b54caa2cb47c06b0695aab85cf9813620d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np221", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xecea5d6aa092dc29520fcd6cd44102c571c415fd5d641e978af4933c476020a6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x830dfc2fb9acb72d3c03a6181b026becbcdca1abf4ab584b2dd00c48fd2f6a62", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xdd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x8a2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311", - "transactions": [], - "withdrawals": [ - { - "index": "0x1c", - "validatorIndex": "0x5", - "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfc7f9a432e6fd69aaf025f64a326ab7221311147dd99d558633579a4d8a0667b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np222", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbc664826810922530f7e9876cd57ef0185f2f5f9bbafb8ee9f6db2d6e67be311", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7492f26a06f6b66d802f0ac93de1640ec7001652e4f9498afa5d279c1c405ccd", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xde", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x8ac", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794", - "transactions": [ - "0xf88281b208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa09765f880d3815c484a796d3fd4c1791ab32f501ba8167bfd55cde417b868e459a0310fdd4d8d953cf38b27fa32ad6e8922ef0d5bd7ba3e61539dd18942669187f1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x949613bd67fb0a68cf58a22e60e7b9b2ccbabb60d1d58c64c15e27a9dec2fb35" - ] - }, - { - "jsonrpc": "2.0", - "id": "np223", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb908ac3bd269a873b62219e78d5f36fdfd6fb7c9393ad50c624b4e8fd045b794", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1e515c524c17bcb3f8a1e8bd65c8403ae534c5c2c2fc0bddce2e69942c57028a", - "receiptsRoot": "0x336f567c728ef05cbd3f71c4a9e9195b8e9cd61f8f040fdd6583daf0580a0551", - "logsBloom": "0x00000000000000000000000000000000000000000000400000000000002000080000080000000000000000000000000000000000000000000000000000000000008000000040000030040000000000800000000006000000000008010001000000004000000000000020000000000000000000000000000000000000040000000400080000000000000000020000000000000040000020000000000000000000000020000001000000000000000000000000100000000000010000000000000001000000000000000000000002000000000000800000000000000200000000000000000000000000000000000020000000000000000000001000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xdf", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x8b6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e", - "transactions": [ - "0xf87981b30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdd0a69ca9a6c3977ae1734d40175aa0720a866ff9353ce4aadfd8a4cd762e53a0290a5ac57e2f318959aaadec811bf9f8017191594476415923ddafef9a25de7c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x289ddb1aee772ad60043ecf17a882c36a988101af91ac177954862e62012fc0e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np224", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2e8980e0390ae8503a42316b0e8ceb3bbe99245131ab69115f2b5555d4ac1f4e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa0a11d77a69e2c62b3cc952c07b650c8f13be0d6860ddf5ba26ef560cefd2000", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x8c0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db", - "transactions": [ - "0xf86481b4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0e55768f282e2db5f2e48da696a07d1bff5687ca7fa5941800d02a1c49a4781b4a00eb30d56234ac991413000037e0f7fb87c8c08b88ae75aa33cb316714b638e1b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbfa48b05faa1a2ee14b3eaed0b75f0d265686b6ce3f2b7fa051b8dc98bc23d6a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np225", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcd2f03e81d096f1c361b6b0a1d28ae2c0ec1d42a90909026754f3759717a65db", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd8287e5675676595007edfbfff082b9f6f86f21bb0371e336ca22e12c6218f68", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x8ca", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8", - "transactions": [ - "0x02f86a870c72dd9d5e883e81b5010882520894f031efa58744e97a34555ca98621d4e8a52ceb5f0180c001a099b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348a056e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7bf49590a866893dc77444d89717942e09acc299eea972e8a7908e9d694a1150" - ] - }, - { - "jsonrpc": "2.0", - "id": "np226", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2a2c4240cf6512959534cdaf586119243f718b4ff992ad851a61211a1ea744d8", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1e3c75d8db0bd225181cc77b2ec19c7033a35ba033f036a97ba8b683d57d0909", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x8d4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96", - "transactions": [], - "withdrawals": [ - { - "index": "0x1d", - "validatorIndex": "0x5", - "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x992f76aee242737eb21f14b65827f3ebc42524fb422b17f414f33c35a24092db" - ] - }, - { - "jsonrpc": "2.0", - "id": "np227", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1fb4e86909057635bfe8d130d4d606c1e9a32bd5e8da002df510861246633a96", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xacca3ad17c81310c870a9cf0df50479973bd92ade4a46b61a2012fa87c7b8a0f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x8de", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177", - "transactions": [ - "0xf88281b608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05147ab82c47d0c6f6298c21b54a83bc404088dcf119f5719034a1154f2c69acaa035070fffcba987b70efcfc6efbf5a43974de5e11331879bbfbfe7556915da7b2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xda6e4f935d966e90dffc6ac0f6d137d9e9c97d65396627e5486d0089b94076fa" - ] - }, - { - "jsonrpc": "2.0", - "id": "np228", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6f03c5c20de46ba707f29a6219e4902bc719b5f9e700c9182d76345fa8b86177", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0468ebde6657b86a2f1561ae8ef57c6cbe23b7dc08cc0ad823ea3831388e1691", - "receiptsRoot": "0x591e45121efd9a319ad048f68a35db27c69b829a65d0c7817224a1c5071ab327", - "logsBloom": "0x00000005000000000010000000080000000000000000000000000008200000004000002080000001000000000000000000010000000000080000000000000000000000000000800000000000000000000000000000000000000000000000000b00000200000000000000000000200000000000200001400000000000100000000000000000000400000000000000000000000000000000000000000000000000000002008000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000020000000010000080000000000000114000000000000000000000040000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe4", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x8e8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72", - "transactions": [ - "0xf87981b70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04ccccf5fa7c7ed5b48d30bee3e8b61c99f8ff9ddecff89747e5685b059d70fa7a042982d8d2a54f9a055fd75df65488462a0ceae67b8a80966427c5d7ea1cf563b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x65467514ed80f25b299dcf74fb74e21e9bb929832a349711cf327c2f8b60b57f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np229", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8c7ac6681ed2a5020837149f8953a2762227b7bb41f2f46bc0c33508190c3e72", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9f5936ddc444db8ba3787be50038f195ddb86663f39b62d556f7700334f441d1", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x8f2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663", - "transactions": [ - "0xf86481b8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07cc4f254afaef8c4953d8a30221c41a50b92629846448a90a62ebdc76de8b2eea073f46d5c867c718486a68dfdf1cd471d65caa8a2495faba0f0a19ca704201e1b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcc2ac03d7a26ff16c990c5f67fa03dabda95641a988deec72ed2fe38c0f289d6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np230", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x01bb09f016e5dfda9ef7170f45fe4b648dd3761b26c83c18bb0eea828bbc8663", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x57dc2fdfe5e59055a9effb9660cfc7af5e87d25a03c9f90ce99ee320996a1991", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x8fc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0", - "transactions": [ - "0xf86781b908825208940a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a01808718e5bb3abd109fa0d2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353a0542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x096dbe9a0190c6badf79de3747abfd4d5eda3ab95b439922cae7ec0cfcd79290" - ] - }, - { - "jsonrpc": "2.0", - "id": "np231", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x15d41d78de758ec47434a48dc695897705ad5990ac584d2a51d8b7a51419abe0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc6a8588f5fa71465604ccee5244d5c72a296994fb2bf1be478b664bc2aa77c39", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x906", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71", - "transactions": [], - "withdrawals": [ - { - "index": "0x1e", - "validatorIndex": "0x5", - "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0c659c769744094f60332ec247799d7ed5ae311d5738daa5dcead3f47ca7a8a2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np232", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa3b4d9f55cfc3ed49c694fa2a634b73f397d5847b73b340d123b2111ba5adc71", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x38cdb4e70eb9771bab194d9310b56dbfcba5d9912cd827406fff94bddf8549d3", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x910", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098", - "transactions": [ - "0xf88281ba08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a06f8db09016d87e96d45d0835a60822fb305336ab1d792944f6f0aa909b73c9d7a01da7c6ba739bf780143672031e860f222149e1e6314171737fee23537a1e7f0c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9cb8a0d41ede6b951c29182422db215e22aedfa1a3549cd27b960a768f6ed522" - ] - }, - { - "jsonrpc": "2.0", - "id": "np233", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4ff6fbd3afcc33972501397c65fe211d7f0bf85a3bde8b31e4b6836375d09098", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbf1db5dc400fd491fad1abd61287f081ebd7398c76f20ecc0a6c9afb30ba5508", - "receiptsRoot": "0xed257fe243a1ffa922e5a62e40ffb504d403afc1d870fdcacd7f0aaf714e9ca1", - "logsBloom": "0x200000000000000000000000000000000000000000000000000009000000800000000000104010000000000000000000000000000000000000000100000000080008000000000000000000800000000000000000000000000008000000000000400000000000004040000000000000000000002000000000080004010000000000000000100000000000000000000040000000000000000000000080010000000000000002000000020c0000000000000000000000000000000000000000000000000000000000000000000000000000080000000080000000000000000000000000400080000000400000000000080000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xe9", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x91a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9", - "transactions": [ - "0xf87981bb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ef0e59c1798c0a7645f75f893cf81eae4aff9f49159b7365b8d4e907367f91f6a0095a58cb4d8be1816acf8b4e11f9d9b2a03d3f392eee1f19bea70b50ed151584" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2510f8256a020f4735e2be224e3bc3e8c14e56f7588315f069630fe24ce2fa26" - ] - }, - { - "jsonrpc": "2.0", - "id": "np234", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf1364f41ffcf3f76e045b1634e4f62db38f5c053edfa7d0a13d87299896ddff9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5b75a7bfd5eb4c649cb36b69c5ccf86fecb002188d9e0f36c0fdbc8a160e4ac6", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xea", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x924", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180", - "transactions": [ - "0xf86481bc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a078dfab2121885d4181d63c7088757f7feb65131b155ad74541de35c055c31ec3a005cccd843ec8a535a567451c3b5034e05bac10f9328c63aa0b4893ee4f910ba2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2d3deb2385a2d230512707ece0bc6098ea788e3d5debb3911abe9a710dd332ea" - ] - }, - { - "jsonrpc": "2.0", - "id": "np235", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa2474d57b356b865a29ccfb79623d9a34ed84db9f056da5dd4e963f816baa180", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3f130c3409ad205204d14e6b5be4ccf2e65559d39cc98dfc265e1436990e5964", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xeb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x92e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d", - "transactions": [ - "0x02f86a870c72dd9d5e883e81bd010882520894f8d20e598df20877e4d826246fc31ffb4615cbc00180c001a0c982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350a07a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1cec4b230f3bccfff7ca197c4a35cb5b95ff7785d064be3628235971b7aff27c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np236", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9a195498e43997a5769957e54f0fa6f56d8442e54f8a26efafbf89130446fd4d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1ad56a036d6b544ee8f96f2d3e72dfdb360fa3c81edef33dd9e9fc1779d174a4", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xec", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x938", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205", - "transactions": [], - "withdrawals": [ - { - "index": "0x1f", - "validatorIndex": "0x5", - "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x18e4a4238d43929180c7a626ae6f8c87a88d723b661549f2f76ff51726833598" - ] - }, - { - "jsonrpc": "2.0", - "id": "np237", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xca48eaf8da077241a7938435cf1576b2628c65afea7b1aa2665c74573e352205", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf43c19d64439e20deb920de4efbb248d44d4f43d0dfecd11350501bc1a4bf240", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xed", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x942", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e", - "transactions": [ - "0xf88281be08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06ba7d56fdfaf77a1a66bfef9529419b73d68fc1aa9edef961ac3a8898f04e5caa054635ee7b91858d97e66944311c81fd4f57d328ee4fbdf8ce730633909a75f01" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x700e1755641a437c8dc888df24a5d80f80f9eaa0d17ddab17db4eb364432a1f5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np238", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd6a5ae0ebd55680da60432b756f7914f8fb8bbcead368348e3b7f07c8cfa501e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x05a62e01803a967ff89e7e9febf8d50b1b3092aab5580c7f85f465e7d70fef3f", - "receiptsRoot": "0x294eca38bb21bd8afeb2e5f59d0d4625058d237e2109428dfb41b97138478318", - "logsBloom": "0x00000040000000001000000000008000000000000000200000000000000000000000008000000000000000020000000040000000000000000000000004000000000000000000800000000000000000000000000000000080000000000000001000000000400000000400000000000000000000000000000000000000000000000880000000000400002000000040000000000000000000000000000810000100000080000080000000000000080000000000000001000000000000000000000000000000080000002000000000000010000000000000000010000000000000002000000000800000000400000000000000000000080000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xee", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x94c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1", - "transactions": [ - "0xf87981bf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0548377761079f73162f83bdc2cfb09dcde9e08c8db66d4d983f1856c5145fe6fa06b2bd1223fbb1b72016150f57bc7ae1f8cce5c0fd301bb9216bb804c89bf0a97" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcad29ceb73b2f3c90d864a2c27a464b36b980458e2d8c4c7f32f70afad707312" - ] - }, - { - "jsonrpc": "2.0", - "id": "np239", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x06466f86e40c982578b247579fa1fa5773d6169e77a79a625950c4aa16ce88b1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbca1fef6bcfcbb170b7b349f92a3b92fe03296dac1fd64ccda295c496a261a16", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xef", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x956", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681", - "transactions": [ - "0xf86481c0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08cfe044eb5748d538f72e560c45c7a01f94f4b7c6e9b1245bade89c0d97f9932a02b21fe651e5fb05d1f8de320dcf8cc037b2c0e989793f6b445f397c77f42a4f0" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa85e892063a7fd41d37142ae38037967eb047436c727fcf0bad813d316efe09f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np240", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x74b00e695ebf3210bda9ad8b3aa1523475d922fd556e551cfd606ebcf807d681", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x82a80ad266f2a1539a79b2dcf8827aabedcc1deeb6cfb4869a8ed2ea26923726", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x960", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3", - "transactions": [ - "0xf86781c10882520894fde502858306c235a3121e42326b53228b7ef46901808718e5bb3abd10a0a03d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34a04278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x040100f17208bcbd9456c62d98846859f7a5efa0e45a5b3a6f0b763b9c700fec" - ] - }, - { - "jsonrpc": "2.0", - "id": "np241", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd908ab400c351cee493619c9b0b56c6ae4d90bd6e995e59ac9302a7b20c13fc3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x59b60dbf89d7c0e705c1e05f6d861bfb38bec347663df6063be9eb020e49972a", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x96a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7", - "transactions": [], - "withdrawals": [ - { - "index": "0x20", - "validatorIndex": "0x5", - "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x49d54a5147de1f5208c509b194af6d64b509398e4f255c20315131e921f7bd04" - ] - }, - { - "jsonrpc": "2.0", - "id": "np242", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x13fdff4106d52399ab52ee5d1e6a03097f6db6de8066597f88be7a797a183cb7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1e5d7390e70d057c7dc29e173e338e7285e276a108eaecf3164dc734ce2fd9b5", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x974", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f", - "transactions": [ - "0xf88281c208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0057b9bf7b2b99c50cf16c0b995e2846ba833edc03f6efc1b97566022651cabeca0237b38f74a2a8c39a2c344ef2d7fe811c37cd20ed2f4d47bfc38d896f3c9db75" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x810ff6fcafb9373a4df3e91ab1ca64a2955c9e42ad8af964f829e38e0ea4ee20" - ] - }, - { - "jsonrpc": "2.0", - "id": "np243", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9cfff0339ca5c7928180f0d37f080f2c8cc4c00bfa2b6be3754b9d228219779f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8725e2687d45a52ad320e82b90e009b1aa5effe7ebfe994116afa25daa09468f", - "receiptsRoot": "0x2f9d61b38064fb9da0bb0f93ff73e1021c62ba761714e96a6674cd927bde4f9c", - "logsBloom": "0x00000000000800000000000000000000001000000000000000000000000000010000000000000000000000000000000000000000000000040000000000000000000000000010000000008000400000000000600000000000000000000800000140000000000080000000000000000000000200000000000000000000000000000000000000000180000000000000000000000000000000000000000000001000000000000000000100020000000000000001020000000000000080000000000000080000000000000000040000000000000000000000000000024080200000000000000000040000000208000000000000010000000000000000001000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf3", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x97e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0", - "transactions": [ - "0xf87981c30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017b61104ac6d28f1262b3750475b328dfd50f8496e0772bf19047d9d1ee9e56da01aed9f9280926e68fb66065edcf80320cab6f6d7c7af4bc8d9d007e1ea6a168d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9b72096b8b672ac6ff5362c56f5d06446d1693c5d2daa94a30755aa636320e78" - ] - }, - { - "jsonrpc": "2.0", - "id": "np244", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0c71dc4665ac65f63a44434a3d55ffc285af6ec8b90b4ddfd4b4001add0e93c0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc5f9b1665244a32dc0885794d5aaf3ce0b464eed1208412ca14abcfe4b908f64", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x988", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606", - "transactions": [ - "0xf86481c4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0a93d446ef64bccf6c88d5285e78e7625fd5c9ac9c8aa11ad45db01b95b6694a5a0761620f10b11ee3cc1932adf95133349f5107aed7b8c150192fa89665ecd7552" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf68bff777db51db5f29afc4afe38bd1bf5cdec29caa0dc52535b529e6d99b742" - ] - }, - { - "jsonrpc": "2.0", - "id": "np245", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1f7b85304f578a197b65ce6f6f9e0c90cf680cdb3f35a95d10ea0a32238df606", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5bacfe50ff7f0200bc1a4ea28e3fbe1a269ea7cbdbe7fb5d83bde19774c92e7e", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x992", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96", - "transactions": [ - "0x02f86a870c72dd9d5e883e81c501088252089427abdeddfe8503496adeb623466caa47da5f63ab0180c001a0deade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25a065f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9566690bde717eec59f828a2dba90988fa268a98ed224f8bc02b77bce10443c4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np246", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8f3a666d3d090603513d1e31ac73c5b47a7fe8279c7359a3bad523a8fd414a96", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1c407d215d7fa96b64c583107e028bcf1e789783c39c37482326b4d4dd522e05", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x99c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df", - "transactions": [], - "withdrawals": [ - { - "index": "0x21", - "validatorIndex": "0x5", - "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd0e821fbd57a4d382edd638b5c1e6deefb81352d41aa97da52db13f330e03097" - ] - }, - { - "jsonrpc": "2.0", - "id": "np247", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf1191b23680ae545b3ad4ffb3fd05209a7adefefc71e30970d1a4c72c383b5df", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x16a2c4f318277ea20b75f32c7c986673d92c14098e36dde553e451f131c21a66", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x9a6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288", - "transactions": [ - "0xf88281c608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02648ce9c5825b33559225aada97c08de484ab8282549d90cfc1e086052c22be8a02054d7eeb1e8bf4ab25b2581ccb0b0a3500625cf7a0315860202eb2eaf094f9c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x43f9aa6fa63739abec56c4604874523ac6dabfcc08bb283195072aeb29d38dfe" - ] - }, - { - "jsonrpc": "2.0", - "id": "np248", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2e34605bbfd5f548e1e9003c8d573e41a9286968bec837ba1f2b7780e3337288", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x291c5ca9a114bdb7bf296b4ff4182b930dc869905eaa1219cbb5188e8feaa9ab", - "receiptsRoot": "0x9f35106348d01548df28e681773a27cffe40648e4d923974e4b87903f578da11", - "logsBloom": "0x00000001000000000000000800000000000000000000000000000000100000000000000200080000000000080001000000000000000000000000000001000000000202000000000000000000000000000002000002000000000000040000000000000000000000000200800000000000800002000000000000000000008000000000000000000000000400008000000000008000000000000000000002000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000181000000800000000000000000000000002000200000000000000000000000000280000000000000000000000000040000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf8", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x9b0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a", - "transactions": [ - "0xf87981c70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09f49a6018e3736ea3599def5663a57cfe19cb3f27bfdd80657503262a5bcfc87a02a26782058025cfe1205be964cc9ac31cdf510a8a9f867bff2317275b13ed02c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x54ebfa924e887a63d643a8277c3394317de0e02e63651b58b6eb0e90df8a20cd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np249", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x22d7e31bcd496b70c0256f88d985be54cd46604897969a5edde95d8d75e2fc6a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x359fe6cc7b7596b4455fdc075bc490d3697d4366c39c40dd6fc935da0ceac7e7", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xf9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x9ba", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf", - "transactions": [ - "0xf86481c8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa043e1ad9aa519d9a1e8a15918ee6bbc0fd98061db6058597bd984098600495f96a01d5edd1b3fc3b45ff2a17a9c7eee3ad4c75e24fc090a4a0e48f39da49e7ad263" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9e414c994ee35162d3b718c47f8435edc2c93394a378cb41037b671366791fc8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np250", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1767170da9f173007588517f005241a12087642444518ce31bcf3ad27de4efcf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc73008737d0cfdbec09b3074d48f44e406f0598003eab9a1f4c733de38512855", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xfa", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x9c4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6", - "transactions": [ - "0xf86781c90882520894aa7225e7d5b0a2552bbb58880b3ec00c286995b801808718e5bb3abd109fa00968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694a060f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4356f072bb235238abefb3330465814821097327842b6e0dc4a0ef95680c4d34" - ] - }, - { - "jsonrpc": "2.0", - "id": "np251", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x163dc4f5b453d5fb626263184121f08cdb616a75e2f8ef978d38e91f5b995ee6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x693db83454936d0dacd29b34de3d2c49dc469bbe4337faec428b028e0d967642", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xfb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x9ce", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6", - "transactions": [], - "withdrawals": [ - { - "index": "0x22", - "validatorIndex": "0x5", - "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x215df775ab368f17ed3f42058861768a3fba25e8d832a00b88559ca5078b8fbc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np252", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8f9b318e4cd81ddd537dff3fcfe099d3609b357f3a4f2aed390edc103a5aa7a6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd358fe0baedc04a81fdaf6cdfc71c2c874291e47d16dd51cc032f0678078a009", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xfc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x9d8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb", - "transactions": [ - "0xf88281ca08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0941941ac43420c855cda955414a23d3bad4d0f2bfbeda999250f2f87d228878da0357223781ec5d666a8d5e8088721e9952f00a762d5fc078133bea6bc657c947e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd17835a18d61605a04d2e50c4f023966a47036e5c59356a0463db90a76f06e3e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np253", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x23a585160ac1b5428ad1dea7e732b641ace396c4135dbf899ab2559f869bb5fb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcb19946b2b5a905882151fff9a12cce6e4c3be46f7da6b67263b0cc781fbe80a", - "receiptsRoot": "0x9b15dea2f021c6c74dc60deea77fd6a1ce29c9efc2596cbaaf73ef60370a03e3", - "logsBloom": "0x0000000000000100800000000000000000800000000000010000000000000000000000000000000000000000000080000000000000000000000000400000000000002000000000000000000000000000000000000000000000000000100008000000000000000000000000000000000020000000000000a004200000000000800000000000000000000000000000100000000000000000000000000440000000000000001001000010000000010000004000000000000000000000200000000000000000000000000000000000000000000400000000000000000000000200000000000000000440000000000120000c00000001000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xfd", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x9e2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b", - "transactions": [ - "0xf87981cb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06fb97cf9fb9b8f7159a9dc549e412001ca969f0dafc3c9294b0e081741aa3d9aa003ed12873ddb354ccf7b0f8e511136ff335a8e4ff6bb7f93ce19e097970c9774" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x875032d74e62dbfd73d4617754d36cd88088d1e5a7c5354bf3e0906c749e6637" - ] - }, - { - "jsonrpc": "2.0", - "id": "np254", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x706168d939a58a0dd048595d1c88fe1735dbeee42111dfbb2adee0ea9ef1d77b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x907ae262cf7f9a93ecd0d1522c6a093ffe39594b65ec185c5059dfa7b3394371", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xfe", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x9ec", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55", - "transactions": [ - "0xf86481cc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a082f832d1212a980978d5716dca8820344200eb6967b24adb2bd112a896b4dda3a0393b965bcf272398cdd6de788c3aa929a67a42466883a472538fb1dad06c07ef" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6f22ae25f70f4b03a2a2b17f370ace1f2b15d17fc7c2457824348a8f2a1eff9f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np255", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xffd5337b506a04e2362e4a34847711bf688591ceb3ac4b7da257072ecef36a55", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc39a9999ffd22de07bcf6a6a16b5cf1da7675dcb135e3503111a1dd50913cf0c", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0xff", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x9f6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2", - "transactions": [ - "0x02f86a870c72dd9d5e883e81cd010882520894a8100ae6aa1940d0b663bb31cd466142ebbdbd510180c080a054eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32ba059af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf11fdf2cb985ce7472dc7c6b422c3a8bf2dfbbc6b86b15a1fa62cf9ebae8f6cf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np256", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcbf2f33d5616ea98f1b1cf12bdd145d35b4a928e4cb8b0fa41a6bd788ca3cbd2", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x979018c4d3a004db4c94102d34d495dd3a4dc9c3c4bcd27d1a001f8095384208", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x100", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xa00", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca", - "transactions": [], - "withdrawals": [ - { - "index": "0x23", - "validatorIndex": "0x5", - "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbbc97696e588f80fbe0316ad430fd4146a29c19b926248febe757cd9408deddc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np257", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x01b45ed6ccf0908b2e4b513eeea6aa86514677cb6d6d06d936e1871fc422daca", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x55e1fa04203cc0edebab3501d9552eaf0ac3bba421bf3480a50e1549cd479dc5", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x101", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xa0a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc", - "transactions": [ - "0xf88281ce08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08a7526f8f209ff44329b503a7d726f569b861894584401651a83668be3971cbfa040314bdfa618ead4fa21933ed3a8af7e814620e3befa914828b981b391096441" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x71dd15be02efd9f3d5d94d0ed9b5e60a205f439bb46abe6226879e857668881e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np258", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x48f84c09e8d4bd8effd3865e8b3ac4202cb0dc0fb72299f35c8bad4558b895dc", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8d05cad792af190bb84ad7a0bebd232c433cf16b90cffea9f4f824d562ec0eb5", - "receiptsRoot": "0x7b32e50058711e6aa1981f911bb5fb6bd05182c7e7850480874c3754788e5ee2", - "logsBloom": "0x000000000000000000000000000000000400000000000000000000000200000000000000000000000000000000002000000000000040000000000000000000800000000000000000000080080000000000040000000002002000002000008000000008000100000000000400000000000000000000000000000000000000200000000000002000000000002000000000004000000000000000000000000000020000000000000000010800000001000000000000000000000000000000000000000c0000010000000000000000000000000000000000000020000000000040000000000000000000000000300000000000000000000800008000000000400000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x102", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xa14", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1", - "transactions": [ - "0xf87981cf0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0fa1c9705b3794f376d02943123846aaae435a6590ddb802e16e91f87ae13c910a0609129061ec7d065ea3c154152c452f76a7894f2459c42c33675af6a20c9ad3c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb90e98bd91f1f7cc5c4456bb7a8868a2bb2cd3dda4b5dd6463b88728526dceea" - ] - }, - { - "jsonrpc": "2.0", - "id": "np259", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xed832bf95db43a650d06fac15b9b6474b7d82d03b27bd43835eee199c95b64f1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x06ffd1eba12cda277819f77a9a89a4f78265f7aed5158dc51332218976856e82", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x103", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xa1e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632", - "transactions": [ - "0xf86481d0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa07de64020fd82a08d2737ded6967d6a6095c02858161988f0626bad7dd2238057a00ad64af462ef2241d4e4c0da1dc108871126cf2aa2b82afd98d7069fc79d9085" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4e80fd3123fda9b404a737c9210ccb0bacc95ef93ac40e06ce9f7511012426c4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np260", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x65f5a3780beee8d82281e7fe3e82b81dae2a14ef861e9df584590dd429b8d632", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3d72e9a90b2dbfc909c697987538e4e9a8f2b127a783109fbb869bf3760bd7a0", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x104", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xa28", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f", - "transactions": [ - "0xf86781d10882520894a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e01808718e5bb3abd109fa004c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2adea05e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xafb50d96b2543048dc93045b62357cc18b64d0e103756ce3ad0e04689dd88282" - ] - }, - { - "jsonrpc": "2.0", - "id": "np261", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcab55b4abc18bcf8e1b24ae34df180dc00edeadc072fa2e52ed54f2b09c6367f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8c514217bbc30325a9d832e82e0f1816cff5d7fed0868f80269eb801957b22a0", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x105", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xa32", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c", - "transactions": [], - "withdrawals": [ - { - "index": "0x24", - "validatorIndex": "0x5", - "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd73341a1c9edd04a890f949ede6cc1e942ad62b63b6a60177f0f692f141a7e95" - ] - }, - { - "jsonrpc": "2.0", - "id": "np262", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x687b7f705112cf8d76b18d5ab3bc59fab146131c4b8efa05a38b42a14bcb251c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x32fc9182d259ea7090be7140ec35dee534b5e755af25c3a41b2fe23452cd75ae", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x106", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xa3c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f", - "transactions": [ - "0xf88281d208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0010b2ab5421f3fe86f38332dd1c862ddcfc711b2255d8f2a677985d3858b643aa025f4fec49790d44c9b50ed1bea3c5700de165dc239173328e0d0c045f0dd4558" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc26601e9613493118999d9268b401707e42496944ccdbfa91d5d7b791a6d18f1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np263", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x59763420efabb84b6d4ae2b2a34f6db6108950debfe1feba4f706ad5227eca5f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdbed2b577f83fcb221ae85377d9c4f41b8ca95de085a3a697098ceaa937d23f8", - "receiptsRoot": "0xf4e79fec628d38bdc719707be2f797b74efbc9468ba5a3ae9415877e11c21db4", - "logsBloom": "0x00000000000008004000000000000000000000000000000010800000000000000040000000000000020000000000800410800000008000040000000000000000000000000000000000040000040000000000000000000000000000001000000000020000000000000400200000000100002000000000000000000000000000000008000010000000000000000020004400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000008000000000000080010000000000000000000000000000000200000000000020000000000000000000000000000020000800000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x107", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xa46", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5", - "transactions": [ - "0xf87981d30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0aa1f3a14b2bee05c15deffd1fcbad6d16deb140557251b04ddb61574fa8c70d8a0614a539b7fe8c276d26cabc1ff36c88c3f6b9cf3bc8836309a1d3f46626b5153" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfb4619fb12e1b9c4b508797833eef7df65fcf255488660d502def2a7ddceef6d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np264", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf95bd5a6a4d1d51c8f00e6421bb1ecdb2a4b19222261aa412dcb4c371eea1af5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2eb443ed50d07a6b1dbb2c154cc221cfb0475593b39ca2d3569224ea7a08030e", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x108", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xa50", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc", - "transactions": [ - "0xf86481d4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0533560fb23c458df00902dbacef307e98096d91f179c49458d99e2eecaeaf3d3a0314508cba155f195ff77eff1a25ed4f454a07b404ac82d3ea73796bd9af3128d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd08b7458cd9d52905403f6f4e9dac15ad18bea1f834858bf48ecae36bf854f98" - ] - }, - { - "jsonrpc": "2.0", - "id": "np265", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x68bd9ab4e0b622e480296f040ad58d1b7f048c712ad5b46c7a596265d5f8e9fc", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6e68dd5ff68bf8a325446716e5bc1629a4e77167c3b5c9249ac2e440b35dea9b", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x109", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xa5a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9", - "transactions": [ - "0x02f86a870c72dd9d5e883e81d5010882520894ac9e61d54eb6967e212c06aab15408292f8558c40180c001a0898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100aa07e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xdf979da2784a3bb9e07c368094dc640aafc514502a62a58b464e50e5e50a34bd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np266", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfd61bbebf4026ea51b90fafefc671dc4540e83436c83eb9bc51e6b2b15db5dc9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4783eb369238bf2856e00bbc632735adf5ea404b766a0a70c27913314e170bac", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xa64", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c", - "transactions": [], - "withdrawals": [ - { - "index": "0x25", - "validatorIndex": "0x5", - "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x15855037d4712ce0019f0169dcd58b58493be8373d29decfa80b8df046e3d6ba" - ] - }, - { - "jsonrpc": "2.0", - "id": "np267", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xaa8b392a2333d1f8a498c60f1c9884705d0bff7dd5a524b5a119f547b0d6579c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd0b9db5bce164e65b476f578ff93039bad1be78c8d1f595ff8496c2f7a67fea4", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xa6e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea", - "transactions": [ - "0xf88281d608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa03329c0816ba8af740dd07a393681abfd26c3f0a121cdfa2390607d0d1832e741a051d0d0b427004563def4552ee51b81a2ca1f41bb48e8b9ae20615381c353d9b3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfd1462a68630956a33e4b65c8e171a08a131097bc7faf5d7f90b5503ab30b69c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np268", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa33f601ca31d93d804b269042c783f9a6f79857919289dbb935e81ba1fed86ea", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcb8d1404a32030e577a2628884f57433fe91b36b838f8576471bc36d87784132", - "receiptsRoot": "0x65c1a0ac45edc227576188f00c72612cd6c4d27cdac8d997bc6c9f499d21565c", - "logsBloom": "0x00000000020000000000000000000001000000000000000000000000402000000000000001000010000000000000000000000000000000000000000000000000000000000800040080000100000006000000000000000000000008000000000000000000000000000001000000000000001000040000000000000000000000000000000000000000080000100000000000000100200000000000000000000000000000000000080000000000000000000040000000000000000000000001000000000040000000000000000000000000000000000100000000000000000100002000000000200000000000000000008000000000000000008010000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10c", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xa78", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01", - "transactions": [ - "0xf87981d70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0310faf1dfcbc5597e207ab627226d2deeea1eedec7ffd8e68740fb76545586d1a01919f4683f202d4ccb3ab524d89d11119e7115645707333703d70f6fbe3c610d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xedad57fee633c4b696e519f84ad1765afbef5d2781b382acd9b8dfcf6cd6d572" - ] - }, - { - "jsonrpc": "2.0", - "id": "np269", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x295de1a3c0821f092b15b4e51f02dd17ab7f1753f22f97c88a2081f9a19ffa01", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0199e03e7400c428fb1bba7126f4eb3a12becd96c4458bff54952e5535b4a3d0", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xa82", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e", - "transactions": [ - "0xf86481d8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0ea5ad6553fb67639cec694e6697ac7b718bd7044fcdf5608fa64f6058e67db93a03953b5792d7d9ef7fc602fbe260e7a290760e8adc634f99ab1896e2c0d55afcb" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc2641ba296c2daa6edf09b63d0f1cfcefd51451fbbc283b6802cbd5392fb145c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np270", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x494693083463dc335450802ab50c97022e63c21e326ff7cebd7870802411db3e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xad6e3dc4bf8e680448a8a6292fc7b9f69129c16eb7d853992c13ce0c91e7d1ce", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xa8c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0", - "transactions": [ - "0xf86781d90882520894653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c01808718e5bb3abd109fa0f1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466ca02043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5615d64e1d3a10972cdea4e4b106b4b6e832bc261129f9ab1d10a670383ae446" - ] - }, - { - "jsonrpc": "2.0", - "id": "np271", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc54e865454d4ba4a092904e151d7afdc9b7b7ef9723dee0325ee075eb6a9a5c0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4347088d10fe319fb00e8eee17f1b872f2e044cbe1cb797657294404bf370e30", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x10f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xa96", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed", - "transactions": [], - "withdrawals": [ - { - "index": "0x26", - "validatorIndex": "0x5", - "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0757c6141fad938002092ff251a64190b060d0e31c31b08fb56b0f993cc4ef0d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np272", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc33055476392adfe03f3bd812f9bb09b7184dc8d58beefab62db84ee34860bed", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa9c73e0cd551b43953f3b13ee9c65436102e647a83bfefa9443ad27733d0371c", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x110", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xaa0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4", - "transactions": [ - "0xf88281da08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0972f048bcd4f8e2678a209e354570de7452fa342744fab1e44b7af67b2484d9ea0076f82074ff9697256d2661ad9f9a7321ff54fa3100ecc479166286a9a22ada5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x14ddc31bc9f9c877ae92ca1958e6f3affca7cc3064537d0bbe8ba4d2072c0961" - ] - }, - { - "jsonrpc": "2.0", - "id": "np273", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x39f74e3f7d2c3f4ab7e89f3b597535ffebd200abe4b1aa67f721ffaa13cbc2b4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf003762d896629dcd3a92a67ee13b96b080f4a3e71402a1dcbf9f444377329b5", - "receiptsRoot": "0x4d68fb9bfae6768b9578f5a63f455867ea5993ec2261fad2a25b45794d092f7c", - "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000000080000000000000100000008000000000000000800000000000000000000000000000000000000000000000400000000040000000240001100000000000000000000000000800000000000000000000000000000000060000000000000000000000000000040000000000002000000000000000080000000200000000000000000000000800000040000000040000000000000000000000000000100800000000000800100000000000000000000000000000002000800000000000000000000800000000014000040000000800000000000400000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x111", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xaaa", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0", - "transactions": [ - "0xf87981db0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a08883be3af4b0a273883412ad320e6dcace1f505d9b20194e8f9e2e092c8d5ce4a03da92647d3d92d2868d5b9c479d98faf263e78eb67f259101a65ff56ee1eccbf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x490b0f08777ad4364f523f94dccb3f56f4aacb2fb4db1bb042a786ecfd248c79" - ] - }, - { - "jsonrpc": "2.0", - "id": "np274", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x23408e1ac73e1dd9c3a735776a73b4c79249e5a9eb62ec9f9012f7f6c11ba7d0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x741d337861f144fc811cfac1db596e3bedb837b0fb090a3d013e5492bf02b233", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x112", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xab4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac", - "transactions": [ - "0xf86481dc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0bcd2b139343048e9174e86251017c9b7c4da9fc36e4a84cf98eaf3855561f8e3a01c25a7b3ff3ebd7d9cbed5aa65515f8ba06fb8860d0764a98591da24e7d1c842" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4a37c0e55f539f2ecafa0ce71ee3d80bc9fe33fb841583073c9f524cc5a2615a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np275", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc7578d8b738ac9f5ab97605ce1c8101160faa615feeb8fc43282d8bd6ae450ac", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe1ce5b13d3189869321889bb12feb5da33a621bf0dbc4612b370a4b6973201f7", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x113", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xabe", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a", - "transactions": [ - "0x02f86a870c72dd9d5e883e81dd010882520894d8c50d6282a1ba47f0a23430d177bbfbb72e2b840180c001a04330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85a07977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x133295fdf94e5e4570e27125807a77272f24622750bcf408be0360ba0dcc89f2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np276", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0bd8ca5ecbf0c960433cbe52bec31810c325088860cd911a1df20174fd30243a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x76aa5a1d0fc7c2f7e01a8c515f018e30afb794badc14b5d8e3651096458947a0", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x114", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xac8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47", - "transactions": [], - "withdrawals": [ - { - "index": "0x27", - "validatorIndex": "0x5", - "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa73eb87c45c96b121f9ab081c095bff9a49cfe5a374f316e9a6a66096f532972" - ] - }, - { - "jsonrpc": "2.0", - "id": "np277", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x604c3b8dbc400712146239b5b6e70426361e47c118c6fff4c1761554c3ad2e47", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xaad6081261920a2bddee7ad943a54ceebdb32edf169b206bd185bd957c029389", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x115", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xad2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309", - "transactions": [ - "0xf88281de08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a092ec956d91708337ef4625bb87caed7a2bab63e40c8e65e8c9ee79a89b525b53a02bfff0c6dadfbf70dbd9fb2d75a12414d808ee6cce90826132d63f8ef2ce96b5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9040bc28f6e830ca50f459fc3dac39a6cd261ccc8cd1cca5429d59230c10f34c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np278", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3dbceccc7aefcec187b98fc34ab00c1be2753676f6201a1e5e1356b5ce09c309", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xac5c584edba5f948690abb0f1c0f9bef685dec896c8f6c5c66ef8dd65810d53e", - "receiptsRoot": "0xdd1d7486ff21ad1c1e17b4d06cf0af6b4a32f650ac495deff2aae6cb73338de3", - "logsBloom": "0x00000000000000000000002000000200400000000082000000000000020100000000000000000000000000000000000000000000000000088000000000000010000000000000000000000800000800000000000000000000000000000000000000000000100000000004001004880000000000000000000000000000000000480000000000000000002000000000801000000000000000000000000000000080000010000000800000000000000000000000000000000000000000000000000040000000000000000000000000008010000100000000000100000000000000000000000000000000000000000000000000000000000000200000000010000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x116", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xadc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c", - "transactions": [ - "0xf87981df0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa099b6473bcd99e0f32d82c046bad2e1824a8468bae8347768d907768e2fe64a2ba051f3f8b7323eab23d5543c8e372e4e184bc3ee108eab5455b89d40d9cbc23008" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xec1d134c49cde6046ee295672a8f11663b6403fb71338181a89dc6bc92f7dea8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np279", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe69bddf40ecef2219c3ce0f27015125fb42d2339c75675f8e0dc587246cf617c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x909007de8369b2fd9597dd7b84ab31e36b949026383fa8957befdba94703689b", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x117", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xae6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87", - "transactions": [ - "0xf86481e0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d8414a9d94412185c316893b53c874ae28ad6c0d67910ec66b39051f7842408ea05329ebb7080c9a6ae9372e8004706b78f7465746c3492816b6255fcba4d84979" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3130a4c80497c65a7ee6ac20f6888a95bd5b05636d6b4bd13d616dcb01591e16" - ] - }, - { - "jsonrpc": "2.0", - "id": "np280", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3f0eb43bfa229f0449d1b975632be01a69ed6c63eda12fb61bf83a2f8cde3c87", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4dcb18dbea7ec4b9dc13b208172da29eb275e2095a6f8c6aeee59d62d5c9dd76", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x118", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xaf0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa", - "transactions": [ - "0xf86781e10882520894b519be874447e0f0a38ee8ec84ecd2198a9fac7701808718e5bb3abd109fa0cfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690a01e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xccdfd5b42f2cbd29ab125769380fc1b18a9d272ac5d3508a6bbe4c82360ebcca" - ] - }, - { - "jsonrpc": "2.0", - "id": "np281", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x12c3c44447da5af2e83d37224a825c26890db2483d5732e4bac08b87fe3ce5fa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcbbdc9e51f0cde277f8f0ba02544d4d2be87cb7a5853a501524d760b00ec5e57", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x119", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xafa", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0", - "transactions": [], - "withdrawals": [ - { - "index": "0x28", - "validatorIndex": "0x5", - "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x74342c7f25ee7dd1ae6eb9cf4e5ce5bcab56c798aea36b554ccb31a660e123af" - ] - }, - { - "jsonrpc": "2.0", - "id": "np282", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2ca033d3c29586c8a38da6008d4a446814d845565ed5955418b125fdbe4602e0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa5f40d100045883afd309122196cd37e687124adc5ec4c609e9d4ea9e8050be1", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xb04", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382", - "transactions": [ - "0xf88281e208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a02a4dd1a40886d389cecff4ca095a57e2f1e924b8d0e80e95c67961bec5af4b34a00adc6e41c4fe22eb93c7bc6ac529c405a8beb3b75d3f82a24029c560d293bee1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf6f75f51a452481c30509e5de96edae82892a61f8c02c88d710dc782b5f01fc7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np283", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x38ae7bdbc3e96e43871baeea0577a4a6e40dd3b4d2c6fea0b50d63e24dd24382", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7a69e46d9beb12acb2476f649cf7fa7d31624c8b521351b533e302290b7ce166", - "receiptsRoot": "0x8f6545857c380d6f9aefa3a76d16cc79ce6d3e8d951a9041f19d57cbde82f55f", - "logsBloom": "0x00000800000000000004000000000001000000000040000000000800025000000000000000000000000000020000000000000000000080000008000000000000000000000000000000000000000041000000000008000000000000800000000000000000000000000080000000000000000080000000000000000000000000000000000000000000000000000010000000000000000000000000040000000000000040000000200000000081000400000000800000000010000000000000000000800000000000001000000000000000000000200000000000000000000008000000000000000000000000000000000000000080000004010000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11b", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xb0e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b", - "transactions": [ - "0xf87981e30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0ac71118aff6dbdfd117ed52c41169a3c1eec7c7b137fed7ec058a48916198f2da05b684d53b4cc1cdafdba987f894eb9c42da47785983593ee1318f8a79f83eff7" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7ce6539cc82db9730b8c21b12d6773925ff7d1a46c9e8f6c986ada96351f36e9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np284", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbf711951f526479f4c5a6a945594daacff51aacb288122fc4eea157e7f26c46b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2d7b3e2f3ea5d7c34423a2461c1f17a4639b72a0a2f4715757ca44018b416be0", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xb18", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa", - "transactions": [ - "0xf86481e4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa088575e3574fdfafb5c288b553973607350d846bd81b304beddaa6ef3dd349eada03cacc2455d5296189c0fc6890380a3c405b96cecfc45dc04a7f7dafe76be64c9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1983684da5e48936b761c5e5882bbeb5e42c3a7efe92989281367fa5ab25e918" - ] - }, - { - "jsonrpc": "2.0", - "id": "np285", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf5882e396311b698818e2e02c699c77a0865ea6320dc69499197aaf8fd8e6daa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdc0d40e96eaa22025544b17cc122fab8f236a1a5d0bfa1a07a6ea680fc31661c", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xb22", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d", - "transactions": [ - "0x02f86a870c72dd9d5e883e81e5010882520894af2c6f1512d1cabedeaf129e0643863c574197320180c001a0c23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516a03f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc564aa993f2b446325ee674146307601dd87eb7409266a97e695e4bb09dd8bf5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np286", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0fabca07111b96e64ef425173cb375ed75f3e1b8ee34eed7593fe8930c9f487d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6d0b749b8735df89c9d0bd4fff2d180d87a7ff86301fc157573ff0e774a942fc", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xb2c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa", - "transactions": [], - "withdrawals": [ - { - "index": "0x29", - "validatorIndex": "0x5", - "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9ca2ff57d59decb7670d5f49bcca68fdaf494ba7dc06214d8e838bfcf7a2824e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np287", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x29d8373309b28aa3b206208c60bf6be454db83f0d5c4140604ec288251b4c5aa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x06f453054ff02cd966887e3e22bf509aacb23ee18ca302b612f10d2fb473cfa3", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x11f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xb36", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee", - "transactions": [ - "0xf88281e608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bac48741d1f314ffaab63f07d4e7a0bc34c68dde478b439f4bca7dcf0b0a1493a036448a9a4150cad5f24411e8a9bbe89096d555ad08818e90d524bbad8b380b7a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6d7b7476cecc036d470a691755f9988409059bd104579c0a2ded58f144236045" - ] - }, - { - "jsonrpc": "2.0", - "id": "np288", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x84b99bc78800f925e5ba4da02f58581a21a3ae711a6306147ff4379435e655ee", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb45e7c8ace763c55943f9c73da1319566234dad9d29651d6b08227eb88c9c4fe", - "receiptsRoot": "0x490106e6f82f2847cc9eb542a9836943df09d8a6b2e4a4fafba322228449195a", - "logsBloom": "0x40000000000000000000100000000000000000000002000000000000000000000008000000000100000000400000000000000000000040000000000000040000000000000000004000002000000000000200000000000000000204000000000000000000000100000000000000000008000000000000000002000000200000000000000000000000000000000000000000000000008000000000000000010800000000000000004200000000000040008000000100000000000000000000000000000000000010000000000000000000000000000000080000400000000000000000000000000000000000000000000000000000040000200000000004800000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x120", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xb40", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869", - "transactions": [ - "0xf87981e70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa017d70f5a57065bf0973a62206ec4a9b7f1f329904de722faf30fff8e2dca5719a006d0438164dd0ff38d669ebaa44dd53cec0b81d8cfe855a9aedee94b3b1f724d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x417504d79d00b85a29f58473a7ad643f88e9cdfe5da2ed25a5965411390fda4a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np289", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc7104befaf82feba7ad56db858cc6743e8ac2af4b6a1a0949c9c1ba51c0fe869", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4c863fc026d042a28f4ee149361f77c9dae309e18ea2497255ae91f8c41e0055", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x121", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xb4a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a", - "transactions": [ - "0xf86481e8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0428b809dd6147da7fc27a9520ae39b6a361b8f646b4eae45b3b32e3e406d766ea00c794c60066a8d4e435ba368662d9a6c0ffdd57ec6c49fdb0c2d4c07a69875cf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe910eb040bf32e56e9447d63497799419957ed7df2572e89768b9139c6fa6a23" - ] - }, - { - "jsonrpc": "2.0", - "id": "np290", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x38c868f4adbaf9c38505eee26eb316eb5065c194df8aeed5c605f8c309d4b68a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4849e0698f5f4b970db7b185d122842a6f842611058a838fe4c48bf3c63b89b6", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x122", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xb54", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e", - "transactions": [ - "0xf86781e90882520894b70654fead634e1ede4518ef34872c9d4f083a5301808718e5bb3abd10a0a0953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3da004e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8e462d3d5b17f0157bc100e785e1b8d2ad3262e6f27238fa7e9c62ba29e9c692" - ] - }, - { - "jsonrpc": "2.0", - "id": "np291", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x962c229b0020efff007766682c8af73f38bc87fa2a83cf4a520b1e6706ced05e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6334127515360bcab6eb39030e54b05d61d464576fb4f99fbece693ffa600610", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x123", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xb5e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1", - "transactions": [], - "withdrawals": [ - { - "index": "0x2a", - "validatorIndex": "0x5", - "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3e6f040dc96b2e05961c4e28df076fa654761f4b0e2e30f5e36b06f65d1893c1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np292", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd8f175dd35dd4a5d97e51309a5fdeb6e713aef85c25c9e2d661075535cf8d8c1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6a53dd10b53014df9fed6a4ae0fee8fc21111c58421916e9c770906b7676cbaf", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x124", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xb68", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d", - "transactions": [ - "0xf88281ea08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a04efd756d15757c98077f04c9f50a22f7e74b1f28f970614a6824b4a406c11d0ba01c4bc3461a415a9c4dbfd4406c3c684a5427ce1490c93d7a9f5e43891dedc709" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x07e71d03691704a4bd83c728529642884fc1b1a8cfeb1ddcbf659c9b71367637" - ] - }, - { - "jsonrpc": "2.0", - "id": "np293", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x56a449bf5c7dba876a8f68b55d9dbbb06c0dddd3c5f586ec4a95317a0f00c79d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x82f613ee711de05f2cc6a4a107500bdd5045f1ba99ce2738222f343f6081efe6", - "receiptsRoot": "0x2c3a6865afbff0ff9319c72cb9974b085dfe9a34eb9b34e0f4bc267272a883ca", - "logsBloom": "0x00000800000000000000004000010000000000000000000000000000000000000180000000000000800000400000000000001000000000000000100000000000000000000000000008000400008000000000000000000000001000000004000001000000000000000008000000000000000000000000000000000000000000000000000000000000090800000000000000004000000000000100000000002400000000000800000000000000000000000000000000000000000000000000000000000000000000000000200001000000000000000000000000000000000000002000000000000000000200000040000000000008008000000000000000022000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x125", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xb72", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736", - "transactions": [ - "0xf87981eb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03cbaa69de647fe3ea352a6e71bab2ee53555fb8ab88c5e68efe28f2e5d687b9ea063c88d4e12b282eb4075d28f2fc6f36c7017ed0d91e36dbfd9d63a358e96abac" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf4d05f5986e4b92a845467d2ae6209ca9b7c6c63ff9cdef3df180660158163ef" - ] - }, - { - "jsonrpc": "2.0", - "id": "np294", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x45a502a5a428913c585b13dbdd0857fbf4ffc3e928b942b5e96c98aced1a1736", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x291d2f7ab3a39d6c34a1b1c66e69262273221f6a8b2bac448e37e64da2330694", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x126", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xb7c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910", - "transactions": [ - "0xf86481ec088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aa81d6aa3b28238a33a52a3e3b5f00fa2300402a222f10c0e7451318b3f81e25a0223f13ffcec992f0ed7592df411b58352aad6d277dd16e7d0a55e5ab5702a18a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5ca251408392b25af49419f1ecd9338d1f4b5afa536dc579ab54e1e3ee6914d4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np295", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x00f4447478e16a0e4dbe26e2398381d77367268754921e89d20bb152c1648910", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe3e06a047edd89fc5a4f9ee475d8e10ace0a0bae37ad4df6613a6077870fcae4", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x127", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xb86", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4", - "transactions": [ - "0x02f86a870c72dd9d5e883e81ed010882520894be3eea9a483308cb3134ce068e77b56e7c25af190180c080a0190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60a02c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe98b64599520cf62e68ce0e2cdf03a21d3712c81fa74b5ade4885b7d8aec531b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np296", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1480b67138d2eb8359bf102ee31219dea9776af6c7fed33e8f4847ce943365c4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8d04702ac0333be2a1e6ae46e4aa31fe4fe23f5458c6899a7fd8800d24162bc5", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x128", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xb90", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7", - "transactions": [], - "withdrawals": [ - { - "index": "0x2b", - "validatorIndex": "0x5", - "address": "0x1c972398125398a3665f212930758ae9518a8c94", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd62ec5a2650450e26aac71a21d45ef795e57c231d28a18d077a01f761bc648fe" - ] - }, - { - "jsonrpc": "2.0", - "id": "np297", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5b6e5684623ac4835ad30948dca710bb10d4bf48695089a4eca9e472300f37d7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb59802d3b42a67087c2362fe27807e97ea95f8894d734e3711d61768b0779cc5", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x129", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xb9a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87", - "transactions": [ - "0xf88281ee08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a01a3bb1f736220feefc5706b013d9cd88f2e5d5c1ee3398b15ba14e84ed6a12c9a078068efcdcd82d92408e849bb10f551cc406e796ff1d2e7d20e06a273d27dfdf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4d3fb38cf24faf44f5b37f248553713af2aa9c3d99ddad4a534e49cd06bb8098" - ] - }, - { - "jsonrpc": "2.0", - "id": "np298", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5903dfb3ecee5d8bc0e0cc0208b17dfc9a0dc86de2eaaee48da23ea0877b6c87", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x18be7053419eb1d23d487c6a3df27d208a2f8973d17b6b3e78417df0d3ab1644", - "receiptsRoot": "0xa7318d908cd687d0e6d982ec99a33a54b0cb9d1bbe3782f31ae731231e79039f", - "logsBloom": "0x00000000000000000000000400000000000000000000000000000000000000000000000000000008000000000000000000000000040000000000800000000000000000000000000800000010000000110000000000000000000020000000000200000000000000000000000004000000001000000000000000000000000000040100000000000000000000000000200000000800040000080040000000004000000000000000200000000000000204000000000000000000000100000000400008008000080000000100000000000000000000000000000000000000000001000000000000000000000000000000001000000000000000000100000000800000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12a", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xba4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052", - "transactions": [ - "0xf87981ef0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dc80fe6320cc01dd2ab63a42dd099e2fa5e0a640e6ccdf8ed634ca0c7382bd9fa04b356107e6a61d8852e7dc24f02691a9bd203564fed22da46bc9d9cd560c3dd4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x36e90abacae8fbe712658e705ac28fa9d00118ef55fe56ea893633680147148a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np299", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x19f2a0716399f123d47e625de34fb2d6fbeadc26b2993e89504e73db85248052", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf704271ace032c151b512221e777247a677847e2588ffb6fdea3de9af775b059", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xbae", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458", - "transactions": [ - "0xf86481f0088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa06074cb58acfc1417684962272c546809696c6d2110b75735b19852066839a38ea03bd4f9b9b32c074215420391000ce0358e01e65745d7a6aa5513c4f857dd6579" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x164177f08412f7e294fae37457d238c4dd76775263e2c7c9f39e8a7ceca9028a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np300", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2d68907fbe46b2958a1e07b483359dd1e1ac8a6fa0b13e0a9c012cb5de4bf458", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0d6f0609afeda40249aad175bb482c3560b6f0e2fb612addd06c6f3953662531", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xbb8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6", - "transactions": [ - "0xf86781f1088252089408037e79bb41c0f1eda6751f0dabb5293ca2d5bf01808718e5bb3abd109fa0e3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5a051429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xaa5a5586bf2f68df5c206dbe45a9498de0a9b5a2ee92235b740971819838a010" - ] - }, - { - "jsonrpc": "2.0", - "id": "np301", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe7554d8e76e3ae2d92eceade591334e211020b97e176762c99573ba526c7fdc6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4ebd469b936b8d119664429fa99c55d75c007d4d12b7eb4db058248fa52b7f46", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xbc2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9", - "transactions": [], - "withdrawals": [ - { - "index": "0x2c", - "validatorIndex": "0x5", - "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x99d001850f513efdc613fb7c8ede12a943ff543c578a54bebbb16daecc56cec5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np302", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x20cae70a3b0dbe466c0cb52294f4a0fcc2fdae8e8e23a070cfa0ebe6a9fabab9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4e0e374db1e769d72af232e15f83b61024ab42a410b4088ad54ae31fb7ab24c2", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xbcc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b", - "transactions": [ - "0xf88281f208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03f816a6f00b46ffee7ae7dc0a8472c822003d7f175c03fc883435b5303662e29a053e91a9fcfb952b9d2ee2d3017e3d02c8988bb4abcb9c343b66d90094e9b9817" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x30a4501d58b23fc7eee5310f5262783b2dd36a94922d11e5e173ec763be8accb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np303", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8088940507cc523f7c12bcec9729eed01e631ccef6faa8a6413a89d77f109c0b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5cd39242444b2f075de43272eb00a7435191e5d07d4da17022f05f91167f8a71", - "receiptsRoot": "0x8c5ae4043b8c3ac3c3faf57678b01a0a80043b682d0a8ae2681dc5c892d7a562", - "logsBloom": "0x00000000000000008000808000000040000000000008000000010000000100000000000040000000000000000000001000000000000000000000000000000000100004000000000000800000000000000008008000000008000000000000000020000000000000000000000000000000000000040000000400000000000000000002000000000000000000000000000000000060000000000000000010000000000000000000001020000000080000400000000000000000000000000000000000000400100000000000000000000000200000400000000000000000800000000000000000000000000000000000000010000000004000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x12f", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xbd6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d", - "transactions": [ - "0xf87981f30883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0cdff6973fabfb503b56e50264fa9d542805c351a2cf282d14e9a7e3f90df3bcea03fc2b2ef3d6e5c8d141f20dab6ea64a6ad2f7c5ab3da95c98cff7a73429036a1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa804188a0434260c0825a988483de064ae01d3e50cb111642c4cfb65bfc2dfb7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np304", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3cfeeb3c000dbf1a34a7d601bacf17a26ab0618b14a821b61f847d10d41dd47d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb8480fa4b2321e09e390c660f11ec0d4466411bae4a7016975b2b4fd843260dd", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x130", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xbe0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f", - "transactions": [ - "0xf86481f4088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ceb79cfa45773ae766de6daf76c67f63fbf14c7cd3853b6cd9ba8cd7cd1608baa019c783f138465d2c59039c902cc9b90cbff0e71a09672939e2373390b1f8c4c5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc554c79292c950bce95e9ef57136684fffb847188607705454909aa5790edc64" - ] - }, - { - "jsonrpc": "2.0", - "id": "np305", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcb128d5be67707747d086abaf2a724879f3a54b7ca2bda6844678eb52a2d225f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x022e2901949be09d1a92be5055ced3cd0770b41c850daf830834dc7da22c9af3", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x131", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xbea", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0", - "transactions": [ - "0x02f86a870c72dd9d5e883e81f5010882520894f16ba6fa61da3398815be2a6c0f7cb1351982dbc0180c001a08dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482a02ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc89e3673025beff5031d48a885098da23d716b743449fd5533a04f25bd2cd203" - ] - }, - { - "jsonrpc": "2.0", - "id": "np306", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x36ddc7075c24073ea0b9b997ebf4a82596f13b41a831293600aaf876d5d1e0e0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xec2a36c595c95a6b095a795e22415b66f5875f243697e72c945361b4f440c3bc", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x132", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xbf4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6", - "transactions": [], - "withdrawals": [ - { - "index": "0x2d", - "validatorIndex": "0x5", - "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x44c310142a326a3822abeb9161413f91010858432d27c9185c800c9c2d92aea6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np307", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x90eae29a9b788583ec3624dac546f4372b97d2b1b58edbcca1b9f82e62b0d3c6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x427bbc009fe03135af46fb83f7cdcf27c022159be37615c8caceff14061d2f1f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x133", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xbfe", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250", - "transactions": [ - "0xf88281f608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa07b4f78cff0cb04bb8cb3d81e0aabef7b54c34db7438322bc8c1554448a37b027a00b760535ea891c9b4af5c70ac5726b3829418f5b21632aa8dda9ed2a91a7e30f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xae3f497ee4bd619d651097d3e04f50caac1f6af55b31b4cbde4faf1c5ddc21e8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np308", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdce2eeeafbf4e8ff4dbfa786434262fe7881254d7abcea2eabca03f5af5aa250", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4b11a079f7e911f563ce2c7a0bcda57feaea847b827bfceb4b0f0a1fde490e41", - "receiptsRoot": "0x2cea15106bcab9c8122ea9fc8d7b5ace9f0650a79134ad9732b933221eb0c440", - "logsBloom": "0x000000020000080000000000000000000000000000000000800000000000040000000001000000000000000000000001010000000010000000000000800000000000000000020008000080000000000000000000000000000000000080080000000000000000000000000200000100000000000000000000000002001000000000000000000800200000000000000000000000000000002000000000020020000008000000000000000000000000000000000000000000000000000000000100000000000004c0000000000000000000000010000000000000200000000000000000000000000010000000000004000200000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x134", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xc08", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f", - "transactions": [ - "0xf87981f70883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03d6fef2d466b342db8155272b9e676d55fdc0fedab7d1fce3b3be54459203a44a016b740412be1021d3f480fbf75fa6733d5a233489a0e1cf72bf56c8b37a0ef80" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3287d70a7b87db98964e828d5c45a4fa4cd7907be3538a5e990d7a3573ccb9c1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np309", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd619d2e9c151c94d9610527d55ab721a092f2566b79a92821e4c7c8a106cce4f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0d7fe7c7c5e17180dd3c5d11953d20c0df05569d83f29789680311e835d44c92", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x135", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xc12", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955", - "transactions": [ - "0xf86481f8088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0b82807e311788292f679bc187111f494eb67171b03e417afdfb54e17f53b9ecfa05d9e1261b6bd95693c5e7859fa6e9ac0f380083750f46dec3f5058026c00aa54" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb52bb578e25d833410fcca7aa6f35f79844537361a43192dce8dcbc72d15e09b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np310", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x722090df82f4d2bf93cc1d092239e427a1ed045284bc56b5aa142b02d2cb3955", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x97742ddf818bf71e18497c37e9532561f45ff6f209555d67e694ec0cec856e7e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x136", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xc1c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa", - "transactions": [ - "0xf86781f9088252089417333b15b4a5afd16cac55a104b554fc63cc873101808718e5bb3abd109fa0f2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aaa0657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xff8f6f17c0f6d208d27dd8b9147586037086b70baf4f70c3629e73f8f053d34f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np311", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x81f5ce1e85499179e132dbe7b9eb21403c7f3df276820c668ed86a018065dbfa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5feed3f1d6bc9de7faac7b8c1d3cfe80d29fbf205455bc25ac4c94ff5f514ca3", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x137", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xc26", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df", - "transactions": [], - "withdrawals": [ - { - "index": "0x2e", - "validatorIndex": "0x5", - "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x70bccc358ad584aacb115076c8aded45961f41920ffedf69ffa0483e0e91fa52" - ] - }, - { - "jsonrpc": "2.0", - "id": "np312", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x685678cda85d28dbe24cd7ef896866decc88be80af44933953112194baeb70df", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xde4840156998638689e0d07c0c706d3f79031636ae0d810638ecdd66c85516f4", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x138", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xc30", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3", - "transactions": [ - "0xf88281fa08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06193bab90c2a0e05f830df90babae78be711ea74e7fa7da80fb57bf1eac7b01ba007568dc41c59c9a3e9f4c46ad8bac850ecee5fdbe8add1a840db65266062453c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe3881eba45a97335a6d450cc37e7f82b81d297c111569e38b6ba0c5fb0ae5d71" - ] - }, - { - "jsonrpc": "2.0", - "id": "np313", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xabbd38fb9a670e62ceca6b3f5cb525834dc1208cd8bc51b3a855932951e34ee3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6fc93047d0ff562c8abee419aecf2b174b1c382f506dedcbb5ba04955cd985c7", - "receiptsRoot": "0xcd59afd93dd989872aa9f89197f533f1c6a90364b872e145f50ff782af2b758b", - "logsBloom": "0x00000000000000000000000001000000000000000000000010000000000000000000000800000000000000000000000004011000000000400000001000000000004000000000000000080000000080000000000000004000800000000400001000000000000000000008000000800004000000000000000000000000080008000000000040000000000000000000000000000020000001000000000000000000000400000000000000000300000000000000000000000000000000400000000000000000000000000000000000000000000400000000000000000000000000000010000000000000001000000000000000010000000000000000400000000040", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x139", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xc3a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c", - "transactions": [ - "0xf87981fb0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0465ab07ff3930a9a8f24c5108701be4a0475480d72147e12305f9d67017af925a07b3dd5fbeae129ce4ea30381c15b2afd9be701e4969422415e07ecea3df82db1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2217beb48c71769d8bf9caaac2858237552fd68cd4ddefb66d04551e7beaa176" - ] - }, - { - "jsonrpc": "2.0", - "id": "np314", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x323e57df6d8869c18eac5a0746e2e3fa96645813704b4af06659dfea08d2473c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcae6ffdf3092bcb2ebdc66df86177bce69bf2f5921e5c4d482d94f2fd5f6649b", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xc44", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c", - "transactions": [ - "0xf86481fc088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0d92908e16f6965c17390bafa5649b05b9150b6db7cb63fccfa3d8ccc1f18ec7fa04082aba5936ac8d14c3f78d12f12d9437b575cebd82337c4499f2176afb74cba" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x06b56638d2545a02757e7f268b25a0cd3bce792fcb1e88da21b0cc21883b9720" - ] - }, - { - "jsonrpc": "2.0", - "id": "np315", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x36c686b156ca6fb1280730a2f86acfd8bcee71bb9666a473d00f0c7813fe5a2c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x1220b41d89a79f31d67f2373ea8563b54fb61661818e9aab06059361fc1412ca", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xc4e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0", - "transactions": [ - "0x02f86a870c72dd9d5e883e81fd010882520894d20b702303d7d7c8afe50344d66a8a711bae14250180c001a067bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244a076661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xebdc8c9e2a85a1fb6582ca30616a685ec8ec25e9c020a65a85671e8b9dacc6eb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np316", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe5456434219d6d602162c56859d7a24895a28aac0958bd46bef986d7d8cab2e0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x65c692f846c2dc380a912a71c1387fec7221a2b0fffae2451370c30ed15350d1", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xc58", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1", - "transactions": [], - "withdrawals": [ - { - "index": "0x2f", - "validatorIndex": "0x5", - "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x738f3edb9d8d273aac79f95f3877fd885e1db732e86115fa3d0da18e6c89e9cf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np317", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa0f3387ab2dd15ebc6dc9522d5d0ee33f01548722c7fde856fb0f4f00fc6a7a1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3dc5f82b5983ab440abc575ac26ea2f4962c8c31f7e8721b537ea53d385827d5", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xc62", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa", - "transactions": [ - "0xf88281fe08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f5f035f73b86709cffa1134edc422e41e8ec49f3455943045c8571f4f12e8f6fa0659c80c0802ca16b9c71c90a8c1d7c32580b8dc2e33eb246d05e9c4920314a31" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xae5ccfc8201288b0c5981cdb60e16bc832ac92edc51149bfe40ff4a935a0c13a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np318", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf0da8bf67d04b148efa37b1c72f83bad458c873c35390e45853916d2a6011efa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb0a0edf94f736c11dfd920d0d386b5857441067979baff670d45380f5ce9c2b2", - "receiptsRoot": "0xbe0275e0c21d0b23665e6d0b34bbb1669b585dfb6ef89c0903dcf8586ec86d00", - "logsBloom": "0x00000020000000000000000000000000000100000000000000000000000040000000001000000000000040000000001000000000000000000000000000000000000000000000000000000000000001000000000000000400000000000002000000000000000000000000000000000000004800000000000000000000000000000000000020000000001004000000000004000000000000000100000800000401008000000000000000000800000000000100000000200000000000002000000000000000020002000000000000000000000000000000000000000200004002000004000000000000000000080200000000000000000000000000010000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13e", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xc6c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859", - "transactions": [ - "0xf87981ff0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a03b9f00d5731e51c973193cb6169cb8024b864d02e5347f287f8de4807e343922a04763ef63ac8ddc3fab7ccc70a4890b69fc944f330f5dd92f1b0266aaa6730eb6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x69a7a19c159c0534e50a98e460707c6c280e7e355fb97cf2b5e0fd56c45a0a97" - ] - }, - { - "jsonrpc": "2.0", - "id": "np319", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9b47d293dedc13b8b02e999ebaf1bf25c233229acf97e7ff9e9491ffbdbcf859", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe7a75428fc4aadb70c1e0ac2ae59a54df93458845525804742ae02a83d4f235e", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x13f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xc76", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702", - "transactions": [ - "0xf865820100088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa08c4b5e491ee67e169155453cdfc9f7ee6f122aeda5d73caf8337d6c29be1be3ca06b9a4038e45c6b5e858787dda6d1fe8d3c502a42996b4fe1abd2de1b834cf5fe" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4d2a1e9207a1466593e5903c5481a579e38e247afe5e80bd41d629ac3342e6a4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np320", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa2c25b920f18b7c73332a155d3ab99a4a88b6454f70c1bdfddfcbfe50311c702", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xda3147e8c80cfa63013d1700016a432d64c00213231ac510ab15f7011eea14e8", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x140", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xc80", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d", - "transactions": [ - "0xf8688201010882520894dd1e2826c0124a6d4f7397a5a71f633928926c0601808718e5bb3abd109fa01f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6a01960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd3e7d679c0d232629818cbb94251c24797ce36dd2a45dbe8c77a6a345231c3b3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np321", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xde65dcf316b36cd1d205e6df4a905df46ceedb163133ebffbab07fb6225d246d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x05dcc2c2d7e87e4e1d836888d7158131800d123c6b2de255ba83054dfa109b02", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x141", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xc8a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322", - "transactions": [], - "withdrawals": [ - { - "index": "0x30", - "validatorIndex": "0x5", - "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd1835b94166e1856dddb6eaa1cfdcc6979193f2ff4541ab274738bd48072899c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np322", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf2fb525ebc86939eeafb51c320f9793182f89f7bc58ad12900362db56d9d4322", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5efe08d743bbae45240fc20d02ab6e38e923dedc1027cf7bc3caff52a138dc06", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x142", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xc94", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2", - "transactions": [ - "0xf88382010208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0f8cf692109b242d13af60f7def7e34fc16e4589de28a3fc445e83fece028b046a07ab0d98800bffd516adf4a56b048f67b4d5ffcf438c8463d82a0fe41509f51e6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1f12c89436a94d427a69bca5a080edc328bd2424896f3f37223186b440deb45e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np323", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x815a67d4526461c4d40a205f5e8cbd11964bd0ed1079edc334250475a0efe1f2", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe6408a88797a6a4177fdb082766f6f35cd304745d96ceec7ba85908cf887ba77", - "receiptsRoot": "0xf0fa46b5337f820bd96b8bf1a50706c91cf6e2d8a9bb0fd9859f0f80d60009e3", - "logsBloom": "0x00400000000000080000000060000000000000020000000000100000100000040000040000000004000010000000000400000000000001020400000000000000000000000000000000000000000000000000000000000100000000000000400000000000020000800000100000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000014000000008000000000000000000000000800000000004000000000000000000000000000000020000000000010000800000000000000000000000000000000800000000000000000000000000000000000000000000400000000010000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x143", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xc9e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1", - "transactions": [ - "0xf87a8201030883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa04d42d5415cbd9d939ef53ef60dbdffb80d016dc6e0704059b94ea4c1d398a2c6a06276655ceed05dd6ed9d6adcb9bb38bf699ae5f7ad1d8e47871404cd3ca98a00" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xccb765890b7107fd98056a257381b6b1d10a83474bbf1bdf8e6b0b8eb9cef2a9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np324", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc80438a37c405d0d3748ca7c92fb89f010ba9b06bd2136b919b563978f1ae6c1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x38475f9f9a763356a2e995dd7ff0e2b3376078bd3048aa3d25bfec5257e1cf3f", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x144", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xca8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664", - "transactions": [ - "0xf865820104088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0654811f90e5259072ba79ea3e5a6ca7bfe8659e198ded895d149d1fc2bfe0167a052842cb4b3a0b0f2d722ec25a5c948bb2b78c3cd2d750303a5869a8812f17eed" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8bbf4e534dbf4580edc5a973194a725b7283f7b9fbb7d7d8deb386aaceebfa84" - ] - }, - { - "jsonrpc": "2.0", - "id": "np325", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1efad9b7aa7d15c849d6055ea15823066111fed8860177b6b0be3ed187a22664", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xda41e628e9aa8c362284b556f48a4e3f9e3e0daec75c7950cd5d4ea75b9f8223", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x145", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xcb2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054", - "transactions": [ - "0x02f86b870c72dd9d5e883e8201050108825208941219c38638722b91f3a909f930d3acc16e3098040180c001a063adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98a056f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x85a0516088f78d837352dcf12547ee3c598dda398e78a9f4d95acfbef19f5e19" - ] - }, - { - "jsonrpc": "2.0", - "id": "np326", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8cfb3cab3103d0431ed161ebec0a29ffce5b82e8fa5b00520169a8be360b9054", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbcdb535ac430393001427eab3b9ff8330ae1c997c2631196da62db6c3c5a5a08", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x146", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xcbc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f", - "transactions": [], - "withdrawals": [ - { - "index": "0x31", - "validatorIndex": "0x5", - "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0f669bc7780e2e5719f9c05872a112f6511e7f189a8649cda5d8dda88d6b8ac3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np327", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xacef7ee8af09f4b94fc20d862eb2426993ad2e2807e22be468143ea8cb585d0f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf54751e3cc778e70000823cc9800dbecaf86c60afe48ddd4f942c9c26f606d6f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x147", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xcc6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4", - "transactions": [ - "0xf88382010608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0af7d5214c1fa8aff20cfd3e89d0db2ff361cf5c23dae0823c6719d9bd3c3a996a0581c85fafb49fa0753c67f65e6ad04871fab4a72a9bf5d9ab3bd7aa33b230225" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa7816288f9712fcab6a2b6fbd0b941b8f48c2acb635580ed80c27bed7e840a57" - ] - }, - { - "jsonrpc": "2.0", - "id": "np328", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x61642769719bcfbed733fd6b7c2cd51038dc1404f0e77f50c330ac8c9629b8c4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xaf3502d0a6862e2cde40bbf084cba5e582a0ba3b3bc0beec6791a712c3d171e3", - "receiptsRoot": "0x52236ae99e7647366a3e31ba24153828332656ea5d242e422ffca1dbf576701d", - "logsBloom": "0x00000000000000004000000000000000000000001010000000000000000008000040000000000000000000000000000000020000200000000080000000000000000000200000000000000021000000000000400000000020000000000000000000000000000080000200000102000000000000000000000000000002000000000000000000000000000000000000000800000000000000000000000088000000800000000000000000000000000000000000020200004000000004000000000000000000002000000000000000000000020000002000080000000000000000000000402000000000000000000000000000000000000000000000000000000008", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x148", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xcd0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a", - "transactions": [ - "0xf87a8201070883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015a81314b3c04efc725ff998badcf9278fb668561e5f9cdd42336845be60ec6ea04c593cfd5526eaf42203a3e6b5020e612ddd4053fa3123f51ae02bf8dde98eb3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xda5168c8c83ac67dfc2772af49d689f11974e960dee4c4351bac637db1a39e82" - ] - }, - { - "jsonrpc": "2.0", - "id": "np329", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3acbeee2cb8786a166d6caf512afc82b72ed1ccbfbe39dd32dd53f842046866a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2a4691469da94625b4626e0a10273a2854e342a71b0711acebc46c8553eb8f0e", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x149", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xcda", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058", - "transactions": [ - "0xf865820108088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0f9f0dcc20f1b62b8c567ac92dc1fbf50908f8bcd504fff3a342de336052e66bea00d38043fb1b141dc3fa2b97eaf09bc490be62e1cf7c40b670503ce0fbd8f6dce" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3f720ecec02446f1af948de4eb0f54775562f2d615726375c377114515ac545b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np330", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1c012e1db133493333b09aff51ca8a110b148221aaf1f28c3d21b41382b0d058", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x44248f33cb76fe58bf53afa7a07e7b3d1d1efb1dcde8379ba1719d987a4cb83e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xce4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547", - "transactions": [ - "0xf86882010908825208941f5746736c7741ae3e8fa0c6e947cade81559a8601808718e5bb3abd109fa0edd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7da068cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x273830a0087f6cef0fdb42179aa1c6c8c19f7bc83c3dc7aa1a56e4e05ca473ea" - ] - }, - { - "jsonrpc": "2.0", - "id": "np331", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4e325a3f368a7235db02d7e604501ef2b416494a13136c23026e9dd3a3f38547", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x30f652c6dbb2b9b0f66b7031f6fd0a8c163866de7b7f33c3e8a0d1f9b37a6d20", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xcee", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf", - "transactions": [], - "withdrawals": [ - { - "index": "0x32", - "validatorIndex": "0x5", - "address": "0x984c16459ded76438d98ce9b608f175c28a910a0", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7044f700543fd542e87e7cdb94f0126b0f6ad9488d0874a8ac903a72bade34e9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np332", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb1a056033a59f165c7df49320a7a67b1fdf266039f12ca8cd2ca8b904425dadf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7ef2bb0e7090f0d465ded8b1064d0aafb5da43bc603b3ae8e39b678616f22f04", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xcf8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776", - "transactions": [ - "0xf88382010a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0b67083c09c180ffba5ddc095999eaacd6d2cec077395c58d882c7a0706954896a02aaa853bfdbcdac9eefd90ff627107b5ca67b0c3969f3a770a4545a3b9d01514" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf63a7ff76bb9713bea8d47831a1510d2c8971accd22a403d5bbfaaa3dc310616" - ] - }, - { - "jsonrpc": "2.0", - "id": "np333", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x961da5e8745e0e4ae8287d73382c5b0d651110a7c7f900abf5f04b3e114b4776", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xff5f5d4ea4c9cb2944bea27f92a309b59ac66d45d231125258186ad3fcd58b61", - "receiptsRoot": "0xd5a4c662356c2fb912cf7df7798aabe0c8598dd3918c2c7e05db6619b76d855e", - "logsBloom": "0x00000000044004000000000000000100000000000000001000000000800000000000000000000000000000001000000000000002000101000002000000000000080000100000000000000000000000000000000000000200000000000000000010000000000000000000000100000800800000000000000000004000000800000000020000001000000002000000000000000000000000000000000000000000000000000000000000000100200000000000000000000000000200200080000000000000000000000000000002000000200000000080000000000008000000000000000000400000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14d", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xd02", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c", - "transactions": [ - "0xf87a82010b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0e65e3fb877a256ecdcf4de6dc51df2bd755e14acad6b24c68e7168dbdfcf77b5a017ffeb5a31596ad459195610c5c5e3f348468dab79d930d49cddc0601cd5a965" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa68dbd9898dd1589501ca3220784c44d41852ad997a270e215539d461ec090f8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np334", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa966ce90648fa40427896d7206976e783f96979437cbb3aed9cc9b050675763c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc8b1d4c2863741606d2cb870ed951e27495def1661f5192eef61cea97b8cd79d", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xd0c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a", - "transactions": [ - "0xf86582010c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa041e92995e25443285655d748126496dbe98874a5cee8a1f0e58ea9f6a650f862a07feb73712a079a889322fcb61999780dab187d69eef21757af3eb0c9825f64c1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x59e501ae3ba9e0c3adafdf0f696d2e6a358e1bec43cbe9b0258c2335dd8d764f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np335", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x266c92734d3a74137a12e4f6af6fe2cc401992b473d8af9121edbf3a78e4cf8a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x53e02e88b716b3d80f9cac4ea6e30497d8a5e0f2dc4df131a20a9ffb78fe8cda", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x14f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xd16", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be", - "transactions": [ - "0x02f86b870c72dd9d5e883e82010d0108825208949ae62b6d840756c238b5ce936b910bb99d5650470180c080a0025cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30a0193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4f19cff0003bdc03c2fee20db950f0efb323be170f0b09c491a20abcf26ecf43" - ] - }, - { - "jsonrpc": "2.0", - "id": "np336", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xebbfb2910659e643ff415b200900100e8e116b6d84a3e8e17b87d3e93dcdf3be", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6be6c01d240a951a6adb298d9cb4e7c9e5e8960540de958b4b458fcfa489bf36", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x150", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xd20", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c", - "transactions": [], - "withdrawals": [ - { - "index": "0x33", - "validatorIndex": "0x5", - "address": "0x2847213288f0988543a76512fab09684131809d9", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x52b1b89795a8fabd3c8594bd571b44fd72279979aaa1d49ea7105c787f8f5fa6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np337", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1f86807324e8cce9f4294076c96c4b2007acb0d2aba5c9ad2695e68aad468f8c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd2cd6e558f19ab03db7ee9677a850741b4f1f763c3de94539a16d54c27f6cac0", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x151", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xd2a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b", - "transactions": [ - "0xf88382010e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a057a97e1fae6dc03c4a29ad01b4d2ebea7069f1bef844b28b92875346d4454c46a01f5821fcf724aa6b0a3b082a6462e5f191a3c5659ba1b66b82cd42cf3175ba59" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7c1416bd4838b93bc87990c9dcca108675bafab950dd0faf111d9eddc4e54327" - ] - }, - { - "jsonrpc": "2.0", - "id": "np338", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x7cec5c4064e153c1c3adeda621a8764ebd7a693aa70891ef0bc7b6f95e64ae7b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe1531cb938cfb7009f343d7ce9de03c63fe99878807b1ec8954b3a29a2d630f1", - "receiptsRoot": "0xa8c44170e431c7d7adf58109a7dbb58eeb38a19244c8a866311ef3a45fd13dfd", - "logsBloom": "0x00000000000000000000000000002000000000000000000000000000000080000000002000000000000000000000000000000000008000010000000000000000000000000000000000000000000000000800000040000420000400000000000000000000000000000000000000000000000000000000004000000000000000000200000018000000040000008400000000000000000000000000000001000000201000000010000001000400000000000000000000000000000002002000000000000400000000000000000000000000000000001000000000000000000000000000000000000080000000000004100000101000001000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x152", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xd34", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13", - "transactions": [ - "0xf87a82010f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0de79b818723588fa8952e0d007ef1e1db2240b355f4f0f69f2af9df6b3408407a00962c062cd7fc4b8bf627bab2c0a00349d7b1bfc6f7875ca3a18967ad30ff219" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xef87a35bb6e56e7d5a1f804c63c978bbd1c1516c4eb70edad2b8143169262c9f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np339", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x11bd9e6153d072615b7e129ce56e720c40c048dd37afb5fdbfff09f994ae4a13", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd35f874d00597dfb19f0363bbab78f3356e12ec8b4ee89f2883285139d7a3c29", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x153", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xd3e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea", - "transactions": [ - "0xf865820110088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa083a20e0b736688ba1f10440def989495ff253a281368f0ca21154d327c0468b8a0119312bdfeff761612ef529e4066bd28b4ed46895e5b67593fb0a3a897d3aa16" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe978f25d16f468c0a0b585994d1e912837f55e1cd8849e140f484a2702385ef2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np340", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf7122487788d84678b120512a25b1393417a66e19db5b507d471dd17628a84ea", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfa5b72ef0354b0b53f973b5285234c441e1bbf86d26374dd3856b36627d5caa3", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x154", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xd48", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8", - "transactions": [ - "0xf8688201110882520894b55a3d332d267493105927b892545d2cd4c83bd601808718e5bb3abd10a0a073cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1a0388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc3e85e9260b6fad139e3c42587cc2df7a9da07fadaacaf2381ca0d4a0c91c819" - ] - }, - { - "jsonrpc": "2.0", - "id": "np341", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb1d88e8bd186bb264de8def507f6a5876ec6f3af27be936763dfd39213ab07e8", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xac6b9759a537d44a1629532184219d1f658f68745491b27e81c87361e72ad602", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x155", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xd52", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d", - "transactions": [], - "withdrawals": [ - { - "index": "0x34", - "validatorIndex": "0x5", - "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbd2647c989abfd1d340fd05add92800064ad742cd82be8c2ec5cc7df20eb0351" - ] - }, - { - "jsonrpc": "2.0", - "id": "np342", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x70dad5a0db225381e8f841db9d8adf9a350051128cc22c0e5a00ad990c592b0d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe579eb979cbfd580c19ef8583f73a0fda902ee0895903a767d544ade95c50baa", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x156", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xd5c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99", - "transactions": [ - "0xf88382011208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0874d69f306b86e76465f6f0ad314cadee41f0f0d1844d35408201c3b2f690de0a0698f29877cb7dec8ee91a42a74f0f5270cbb391836fdaeda1e0876d3c16177b9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x99ac5ad7b62dd843abca85e485a6d4331e006ef9d391b0e89fb2eeccef1d29a2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np343", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb9b47ee8f7c38e7e1f69148756182d3da3a7d0c123948d2c56e5268357fced99", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf9106c3c4fcc77588a382ba0c2f605f6e07fcc418edac1cdd7de3b0e70f81b9f", - "receiptsRoot": "0x07a001dcc7eec5d1e8aa3508d61fcf5d511b4f9b766801b63319aa423ef08c3f", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000010000800000000000000000000840000004000000000080000010000000000000000000000000000000000000000000000020000000000000000008000010000000000000000000000000000000100000000108000000000000210000000000100000000000000000000002000000408000000000030000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200008800008000008000000000000000400000100000000000000008000000000000000000000080000000000000000000001010000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x157", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xd66", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214", - "transactions": [ - "0xf87a8201130883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa084f91b21758f4c28d386fa99e8b7e126d27a1f9e293e5df2683057e09a9c6a2fa051772044b702ac375f615dc0d6aaa8c1d38c3ac2a830539d2ab62935c5132921" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x02a4349c3ee7403fe2f23cad9cf2fb6933b1ae37e34c9d414dc4f64516ea9f97" - ] - }, - { - "jsonrpc": "2.0", - "id": "np344", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xde78022135caa19aa76718718d5de70d69e3f2488ff6769aee87c1d765237214", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x19268b0f7992afe0cf1f3c0ac73b371ed7d9e79dddf0435b72bc45e1682a9c74", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x158", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xd70", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a", - "transactions": [ - "0xf865820114088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0904e2a23972254826c8f3f5efa2d39122f980811cb9dd3e5d2869618d458856aa00fd104e760443aa8abcbdfbf2263d45a32a7aec32e59548b3e73575bc21f0243" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x627b41fdbdf4a95381da5e5186123bf808c119b849dfdd3f515fa8d54c19c771" - ] - }, - { - "jsonrpc": "2.0", - "id": "np345", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8123c0650f836341cace6e65f0826a678974333748bc91a93d569224d63f832a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3ef70ee0614b3ae112271af4be70033c61a89f337aa527b8657df19422d94913", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x159", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xd7a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530", - "transactions": [ - "0x02f86b870c72dd9d5e883e820115010882520894b68176634dde4d9402ecb148265db047d17cb4ab0180c080a09f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59ba06a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc087b16d7caa58e1361a7b158159469975f55582a4ef760465703a40123226d7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np346", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc74bc2976b5c5cbcfd64757534333c98d56bcac3109fc4504e3c324801f27530", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbbec06f293095304adb3f03ba055fd08a691c89d5de1ade4c1ed31b9c6672989", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xd84", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4", - "transactions": [], - "withdrawals": [ - { - "index": "0x35", - "validatorIndex": "0x5", - "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf7a477c0c27d4890e3fb56eb2dc0386e7409d1c59cab6c7f22b84de45b4c6867" - ] - }, - { - "jsonrpc": "2.0", - "id": "np347", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x60a82197fb6b3b7d9a4912ec6ac783460863e449f48c28d68a45b4d4bf0a99f4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x169c28a15311ed314bc0a4529aaddacc79d5fd6becdaaae69276079408d57eda", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xd8e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a", - "transactions": [ - "0xf88382011608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a065a20271c4b6acc45c7e172465adcdc218b164c0936999de9bdd37c4a4c63fd0a003792daae8ab2be81df0df962c26697830d30af560c8a85a0fba05e5cfc82d66" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1cb440b7d88e98ceb953bc46b003fde2150860be05e11b9a5abae2c814a71571" - ] - }, - { - "jsonrpc": "2.0", - "id": "np348", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xefbb190d45953f5e6292e14fc50b51539bca514890f94eda3e3ba2553417303a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x704fde0fccaf5957d60018e958bfb8cc7bb7e77eed37cee3bdcdcca280b3b1fb", - "receiptsRoot": "0x0016ae7d40181cb711af89f17dc40dfb53384c5ef535847ae4982b1d58bfadd1", - "logsBloom": "0x00000000000000000000000004800000000000000000000000000000000200000000000000000000000000008000000020000000000200000000000000000000000000000000000000000000000000000000000000004000000000000008000000000008010000000000100008000000000020000000000400000080000000080000000000040000000080000000000002000000000000000000000000001000000000200000000000800100000000000000000040000008000000000000000000000040200000000000000000000000000000000000000000000000020000000000200000020000001008000001000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15c", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xd98", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237", - "transactions": [ - "0xf87a8201170883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0a7fe70291d9f18d3daffb9c6845116569c9be21f8b04c47235999ad35c20a079a03ad45b41a4993ea744bb28012bae4998ad6e97da464162d4ce51810e442e3ccc" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x72613e3e30445e37af38976f6bb3e3bf7debbcf70156eb37c5ac4e41834f9dd2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np349", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xac7efb8f8fa8949755e520c30b52d9c292eb7e46eb8cac907f1267f72de81237", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x898ac18f3ec544e0908e3a1c5434515aa421b796a41501b0474375f49fba30c8", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xda2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba", - "transactions": [ - "0xf865820118088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0027208b707b49c8686502030a1029e738d91a7c0bf9dff86bb90ccda2e5fc158a04b1d06ac6269fc336d1e6d0bac45e82b7d47ca4c271c7fed3bd1c6599b4bd0c6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe69e7568b9e70ee7e71ebad9548fc8afad5ff4435df5d55624b39df9e8826c91" - ] - }, - { - "jsonrpc": "2.0", - "id": "np350", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x498a0d50858ecbfd2fe317843b04c02a00dfa8c2ee6a0e3641947439f0eb7dba", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3a29d14904f05f088f4aede9ab588a53f6a54db4f43cd77f0227445a0d7c8386", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xdac", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005", - "transactions": [ - "0xf8688201190882520894dfe052578c96df94fa617102199e66110181ed2c01808718e5bb3abd109fa0020ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1a00f72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc3f1682f65ee45ce7019ee7059d65f8f1b0c0a8f68f94383410f7e6f46f26577" - ] - }, - { - "jsonrpc": "2.0", - "id": "np351", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xac94cbd2aa423a9fc3dd35e9918a288b31a6b6127f829ef08b3d106212d5c005", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x693ec0330efa3e07b25a9a758d30a43389876e03846885dda5cdb009ff0e2674", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x15f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xdb6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c", - "transactions": [], - "withdrawals": [ - { - "index": "0x36", - "validatorIndex": "0x5", - "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x93ee1e4480ed7935097467737e54c595a2a6424cf8eaed5eacc2bf23ce368192" - ] - }, - { - "jsonrpc": "2.0", - "id": "np352", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5c72e42631163c4ff7bb5a0e0051317b4b432609769052e2efe6043155ead48c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc25a9e84540d654be4abb3e8581cd2cc7cf97e54895e7a62d08eb78431d3f244", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x160", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xdc0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7", - "transactions": [ - "0xf88382011a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00df7ffb1778e645f4fc3b0e2236b34c038c43aacbbc43abc8d710c3fc33901e5a00d7d3d9cbc790b2e206b30639a4b55c1d2f3c2ea18c058a5085f16d72b50455b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb07f8855348b496166d3906437b8b76fdf7918f2e87858d8a78b1deece6e2558" - ] - }, - { - "jsonrpc": "2.0", - "id": "np353", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf3760efebd2ee1fbbda6bfff5aded8bb4ac38928857a4b22edab12bda293a2d7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x911acb703f25c08267716b25fc43b19bf4ce43a053393e6f1dce78c1cba8c485", - "receiptsRoot": "0x758b6a000deb6b7275c48ea96b2cbf580372445f0bc5b285eb764ed1800e8747", - "logsBloom": "0x00000000000005001000000000000000000000000000908000000200420000000000020000000000000000004000800010000000000000000200000000000000004000000002000000000000000080000000000000000000040000000000000000000000100400000000400000000000000000000000010000000400000000000000010000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000200000000000000000000000020000820000800000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x161", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xdca", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d", - "transactions": [ - "0xf87a82011b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c6d3e03aa8b0625a3225e077addb3cf47c9d061148da25021b22a0746083cc11a06176a93c704e6c5088e9d18cbaca7eab1de348207c2ba50083934c4e215a079d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xec60e51de32061c531b80d2c515bfa8f81600b9b50fc02beaf4dc01dd6e0c9ca" - ] - }, - { - "jsonrpc": "2.0", - "id": "np354", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9584dd2f0e20e3b4c274103aa168c495888b69ef8de7fe40cf413b6964c8393d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xaca595525f5aa4f17314e44a3fdc0dae0f4037a1ee0a12bfb1bec7b9219f8d6c", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x162", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xdd4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0", - "transactions": [ - "0xf86582011c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ad6f8d4d86d80157b67311edc959413ac3f525a5ec6334cc826125dfb1908b05a02e91a1d46e2df7c7eb4dc92224252298c66dbbf321fbb6c827a6e2d348277298" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2fc9f34b3ed6b3cabd7b2b65b4a21381ad4419670eed745007f9efa8dd365ef1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np355", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x55a29172dc5a0a9d27b1778bec1c1591c0c8ec114d322fe60f5a39258e1783a0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa307681299c7c385c512cbf83195ee62d35d29487665eb57cf2698c1b3e82066", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x163", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xdde", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657", - "transactions": [ - "0x02f86b870c72dd9d5e883e82011d01088252089433fc6e8ad066231eb5527d1a39214c1eb390985d0180c001a0167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1ca0269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf4af3b701f9b088d23f93bb6d5868370ed1cdcb19532ddd164ed3f411f3e5a95" - ] - }, - { - "jsonrpc": "2.0", - "id": "np356", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb99cdd27bfb2535b0247fef5fe8097fc4e60f2a1c54a9adb3243192dafe1e657", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb36926502e2ee904451fa5970a453aebe89f5bc25cd8c1dcae196810968617c1", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x164", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xde8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3", - "transactions": [], - "withdrawals": [ - { - "index": "0x37", - "validatorIndex": "0x5", - "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8272e509366a028b8d6bbae2a411eb3818b5be7dac69104a4e72317e55a9e697" - ] - }, - { - "jsonrpc": "2.0", - "id": "np357", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbdd33f47e688a8c88c0bb8514d3eff12f6f1ca570d3ae31aab000689d8dd4af3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x67558b87a732daed74e1b9ed7aef6326aabe984df466494d2fc59d9ea951c6c6", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x165", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xdf2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0", - "transactions": [ - "0xf88382011e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0b20886ab8d36222d79bf9dad933333062a51e71dbd6de720f872874edb727276a05f68ff1bcbb8019f43e4e37a481075cc5565512eb56d34ccb707e8aec00a4204" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa194d76f417dafe27d02a6044a913c0b494fe893840b5b745386ae6078a44e9c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np358", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x60fbbf44b7687b97e348c42a24637f027125b00a39e5e63995405da84de95ce0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x15bdc9a6fcc0d4d133bc86adbda378e2110d51fc60304207240f24f60d4fc99d", - "receiptsRoot": "0xf9f06ad2e1bbf826b5cbeabfd01d508c4d7bc0781b946c5afc105a2e20d9155a", - "logsBloom": "0x0020000200000000000004000000000000000000010000001000000000000400000000000000008000000000000400000000a820000000000000000004000001001000000800000000000000000000000000000000000000100020000002000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000040000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000004000000000000000000000000000000000140000000000000800000000000010000000000000000000000004000000000010000000000004401000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x166", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xdfc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f", - "transactions": [ - "0xf87a82011f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0c35e2924126964cdf4a8847f4cb4a870f24a4654de527a3dc9fad248d338aab6a00d9292c8e92050bebef84a83b3deacddf95a33015a3d284b578cb0f1621c5a70" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa255e59e9a27c16430219b18984594fc1edaf88fe47dd427911020fbc0d92507" - ] - }, - { - "jsonrpc": "2.0", - "id": "np359", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb32a72eff6c1fed26a63381d9de7254e9a85e9c459fad22c037e8a11eb95d04f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x21d7cc2931eed33ddb03977b7d99c97ac378c41ed2ac25331478cd1fbd583e7a", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x167", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xe06", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36", - "transactions": [ - "0xf865820120088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0aab9710502eb45f06f5470674b88b22c30fdc865a22c86a7095f355629fb6d11a01d905abe10e39ed037ad29a46a81d0af6d52d9de2d7bef20e7b02db8c1cf13a0" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7996946b8891ebd0623c7887dd09f50a939f6f29dea4ca3c3630f50ec3c575cb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np360", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x31483924290768786929b9836507966e24a775f86f3724200851b2eaa262ac36", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x128ac2d4c23be8773c460ed383defee0e767a4fe0a55e9f600a60e0fe051735b", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x168", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xe10", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04", - "transactions": [ - "0xf8688201210882520894662fb906c0fb671022f9914d6bba12250ea6adfb01808718e5bb3abd10a0a0d3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7a0202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb04cbab069405f18839e6c6cf85cc19beeb9ee98c159510fcb67cb84652b7db9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np361", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdfabceebb90036f92ea3e859b9fcadd8642f00dcdf45278c09d93fb56d320b04", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa8f8fd676089911db9824cafe64222a854d4767d0cc5fded3fa1643f735afd80", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x169", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xe1a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380", - "transactions": [], - "withdrawals": [ - { - "index": "0x38", - "validatorIndex": "0x5", - "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6f241a5e530d1e261ef0f5800d7ff252c33ce148865926e6231d4718f0b9eded" - ] - }, - { - "jsonrpc": "2.0", - "id": "np362", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa7dab2cd20b59a5961ff34f49d421a579c939d6898b084ae4db8971604df1380", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb19cdea25a29e5ba5bf0a69180560c2bcf35823b81d82d8b97499ad1cc22873b", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xe24", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94", - "transactions": [ - "0xf88382012208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa034e8481ee12e75836d1e4cc88aef813a6bc8247b73aeb7a466a1ce95bca6e5fea07585402e69f5856a5724a9e83a9bf9cf77bc92cc619489f9903f09b8c3530f24" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfcfa9f1759f8db6a7e452af747a972cf3b1b493a216dbd32db21f7c2ce279cce" - ] - }, - { - "jsonrpc": "2.0", - "id": "np363", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0f9c87bb2b9d07ca411420399c22658ea7be36c5bd1fbbf1c759592959cc3a94", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x09f1a8d40ad941a3c47fd34c32682a0058f79387d467a7ebb5d957455aab9fb6", - "receiptsRoot": "0xde87ab5715c2af5f977bcf679cd4e771796d49365c3111487aba12fdb69483a2", - "logsBloom": "0x00800000000000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000008000000000000000000000000000002000000000000000000000000001020000000000000000000104000004000000000000000000000000000000000000000000800001000000040000000000000002000000000000000001000000000008400000000000000100000000000000000000001000000000000000040000000000000000010200000000000000000000000000080000000000000000000020002000000020000100400000000000000000000040000000000000100000010000000000000001000040000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16b", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xe2e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e", - "transactions": [ - "0xf87a8201230883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0317931eb522b3488621079d412251962cc5a02794939e3a3b0c94c92df0b4da5a001348209aa47bc1a55590243d5168b2beb06c929b46104d144ba526070b2e5ea" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xdf880227742710ac4f31c0466a6da7c56ec54caccfdb8f58e5d3f72e40e800f3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np364", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xcdbbd78682fb1c3e75c9821acce03f6fd048226147e7041d84952c6aa3c18b5e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x96f076c6c4d61d649b8f9c4290ff81fad55bfebe6e171f2d2bedb4b941977873", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xe38", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a", - "transactions": [ - "0xf865820124088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0886d94140ef16f0079167a92ea5577d300a4e87982588af41676d8d9a7a7f043a0388a734d4f7a8eb510a5e7aba3141505773bd329a70ff438be40d7b378fdafa6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xadfe28a0f8afc89c371dc7b724c78c2e3677904d03580c7141d32ba32f0ed46f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np365", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xab15226c228033c1118398e475d860a1ea7534e4d620ae9ceb2893fa3a73ff7a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x208cc1a739ecf1c8aed87a70e4f580b28d06f7dba19ef679a4b809870c0e66a4", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xe42", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde", - "transactions": [ - "0x02f86b870c72dd9d5e883e820125010882520894f1fc98c0060f0d12ae263986be65770e2ae42eae0180c080a06563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210a00a96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb264d19d2daf7d5fcf8d2214eba0aacf72cabbc7a2617219e535242258d43a31" - ] - }, - { - "jsonrpc": "2.0", - "id": "np366", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe3c3b2311857f76f1031d8384102288970bf25ab710e5e8ca3e7fee19ea3fcde", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf4a7f460684eacde84218991911d63333e89a5a8fe5293e43b2b283209bb7297", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xe4c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c", - "transactions": [], - "withdrawals": [ - { - "index": "0x39", - "validatorIndex": "0x5", - "address": "0x19041ad672875015bc4041c24b581eafc0869aab", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf2207420648dccc4f01992831e219c717076ff3c74fb88a96676bbcfe1e63f38" - ] - }, - { - "jsonrpc": "2.0", - "id": "np367", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf1f80c035c0860545aeb848923615c5bb8cbd15305ddc6a87b9d9a4d509a8d5c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x44f6e5c8fd3452b71ade752a742ca9f61626aeeaa20e89d47fe414d1df414745", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x16f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xe56", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a", - "transactions": [ - "0xf88382012608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a00d5ce478373461565e41764365499cc4a43519643829503796c5453e1bc7ff0ea03ef00a5fe608838a9156d394317734b358ac026af08b33c2aabfea8e9d485dfa" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x41e8fae73b31870db8546eea6e11b792e0c9daf74d2fbb6471f4f6c6aaead362" - ] - }, - { - "jsonrpc": "2.0", - "id": "np368", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xaa0d0fadd5774766ac1a78447bd5ef9f5a816c9068d28097c78d02737ce7f05a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7fd199408596db163d237e6d25f64b90ac2bc04158524e8baac5d55f881bb52b", - "receiptsRoot": "0x8d3f058248d263db5e6d6d78ddf91fd2ec0183f2bdf3e9e142af87a53388e526", - "logsBloom": "0x00000000000000000000000000000100000200008000000000000000000000000000400000000000000000000000000000000000010008000000000000000000000020000600000000000020000002000010000000000000000000000000000000000000080000000020200000000000000000000000000000000001000000000000000000800000002000000800000000000000010000000000000000000000000000000000000000000000004000000000008000000000000000000000000000000000040000000000000000000000200000000000000000000000401000000009800000000010000000000000000000000000000000000000808000000800", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x170", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xe60", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96", - "transactions": [ - "0xf87a8201270883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a008faafda0a060040eca56f846ecbd6a399914482c31359f1ec04c98cc476ce82a04d2b02adc2c947898fa00cbedb4532f471cb5eb92ee19a30697ddd0c713132e3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4e7a5876c1ee2f1833267b5bd85ac35744a258cc3d7171a8a8cd5c87811078a2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np369", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4b263e57c931fa090da8bc6890c9d6fc2ad2dd5a66bb3a5563cc477735893a96", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2a2360860a67f9187f50f56201c50d2309c961a2b408072e7c3d069c8c1216cd", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x171", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xe6a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226", - "transactions": [ - "0xf865820128088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0da49c9575be5d906d247a5f4f0574e76d1edb1368dbdda1b4a5b58fba3fca82da00fa1c561fc766acefeeabf085384962f2599b3ca6b02996962095eed297df611" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8d4a424d1a0ee910ccdfc38c7e7f421780c337232d061e3528e025d74b362315" - ] - }, - { - "jsonrpc": "2.0", - "id": "np370", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x0adc9e078ab6f0799b5cbc8e46e53a0d96d4fe4ba0b6ff75088445c304000226", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x971bbdee0e408ff826563636c5eccce30540c1cba590880849a72ac21f74a4e4", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x172", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xe74", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04", - "transactions": [ - "0xf8688201290882520894a92bb60b61e305ddd888015189d6591b0eab023301808718e5bb3abd109fa0626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dda0074494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfa65829d54aba84896370599f041413d50f1acdc8a178211b2960827c1f85cbf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np371", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1636ca42281a5e77303d2d1095d71b2c59f0b175c98a3adb9630cd6463d2be04", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2a239ffb7957e73c3eebeb33b01444599ddcd5861f1dfb4bbe31584061f11389", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x173", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xe7e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be", - "transactions": [], - "withdrawals": [ - { - "index": "0x3a", - "validatorIndex": "0x5", - "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xda5dfc12da14eafad2ac2a1456c241c4683c6e7e40a7c3569bc618cfc9d6dca3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np372", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbf62c63fdcd8b0648bfec616e9270243233b47c513a9519932cb82d70ed5c2be", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xadbba859a71886f49ccd216fbc6c51a42a7a6eff927970b298d4e0f6e2a9597d", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x174", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xe88", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a", - "transactions": [ - "0xf88382012a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa085c885407da43158c33afe4c9d10a846d4cf5bb820c70f019ff8b6ee9dfb027ba077c0e90a4a029bea55eadf3b0d39261b6204a5c1b8e5e80838ebeef5c9fd456c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x16243e7995312ffa3983c5858c6560b2abc637c481746003b6c2b58c62e9a547" - ] - }, - { - "jsonrpc": "2.0", - "id": "np373", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x349a0919fb81864d824dd7345c583a9fb5c99ef0bd9c549be68b10e72e7c8c2a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe5a5661f0d0f149de13c6a68eadbb59e31cb30cf6e18629346fe80789b1f3fbc", - "receiptsRoot": "0x97965a7b5cca18575c284022cd83e7efb8af6fcf19595c26001b159771ffb0ce", - "logsBloom": "0x80000000000000000000000100000000000000000000000000000010000008100180000000000000200040000000000002000000000000000000000040000000000000000000000000000000000100000000000000000000000000400000020020000000000000000000000000000000000008000000000000000000000000000000000000002000000000000000000000000000000000048200000000000000000000000000000000000000000000000000000000000000000000000100000800000000000000000000000000000000000000000000000000000000440000000000000000121400000000000000000000040001000020000000000040000200", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x175", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xe92", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992", - "transactions": [ - "0xf87a82012b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa03e8b18cd5d8c796e69f450a4c00e75d7e2d38cf9d25dd19e2033fbd56fbf4b84a0175ca19057500b32a52b668251a0aec6c8f3e1e92dec9c6741a13ffe3fb214cc" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb75f0189b31abbbd88cd32c47ed311c93ec429f1253ee715a1b00d1ca6a1e094" - ] - }, - { - "jsonrpc": "2.0", - "id": "np374", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x90c6119a5ecf366ff337473422f9872fddac4e2b193a2e0a065cf7de60644992", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0a82334be200ef303c1c3b95b92b6f397df138b7e6eb23d830fb306996f1c79b", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x176", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xe9c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d", - "transactions": [ - "0xf86582012c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0519fcc6ae02e4901d4ccfcd2b0560f06bf13478b459310ddaae39f44b7ed1394a03b529b53be6c0451a4b644f5031746cb1db62cfbe43b962da26aff507d4293ef" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd087eb94d6347da9322e3904add7ff7dd0fd72b924b917a8e10dae208251b49d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np375", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb023fb820fb7f3cc5b8c8ffec71401eae32858e7f5e69ffbdbdd71751bf1c23d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8e7778cdef2ec78802c7431cdd44768e4a4f6d9c6cc494ae02dc20c10bc6eead", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x177", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xea6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf", - "transactions": [ - "0x02f86b870c72dd9d5e883e82012d010882520894469542b3ece7ae501372a11c673d7627294a85ca0180c080a09add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fba021a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xbc17244b8519292d8fbb455f6253e57ecc16b5803bd58f62b0d94da7f8b2a1d6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np376", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xafe3e6ffafc8cd84d8aa5f81d7b622b3e18df979dbffb44601eb239bc22132bf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0b7ff239a80d7ca996fe534cf3d36898e55e3b4dbd6c130cc433dfb10d83c2dd", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x178", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xeb0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c", - "transactions": [], - "withdrawals": [ - { - "index": "0x3b", - "validatorIndex": "0x5", - "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3ff8b39a3c6de6646124497b27e8d4e657d103c72f2001bdd4c554208a0566e3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np377", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2b7573e48bca65c866e82401d2160b5bcaec5f8cd92fba6354d2fa8c50128e2c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5cac010e2605b327b97a4ef6f78d4c65554588283336081d8ef497a3860fdbde", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x179", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xeba", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3", - "transactions": [ - "0xf88382012e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a015118995d271e570428c3c349d49390af0fd81d3217f90159fc25b9d0791d6efa018c1a844d5d3523ce37308f0cd2e46e8d6ef99a9eb750e7325ca2c67d59aaf85" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4d0f765d2b6a01f0c787bbb13b1360c1624704883e2fd420ea36037fa7e3a563" - ] - }, - { - "jsonrpc": "2.0", - "id": "np378", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x77b6c58098c59ec84605e8f12c7fbe8a358d52adf77948577ce7396ae18aaac3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe908771dea594628e0f4d2b5d3354bbc6f9cfa04a97249657a74b792c3254b77", - "receiptsRoot": "0x8dc461a171023c5f8e3f5d78e0842291fbe7b0a502495a334a1bc98337a8a1b4", - "logsBloom": "0x00000004000000000000000000002000000000000000000000000100080000000000000020000000000020000000000000200100000000000000000010000000000000000000000008001000000000000000040200000000000000000000020000000000080000000000000000000000000000000000000100000000000000000000000000010000000000000000200000000400000000010000120000000010000008000000000000000000100000000000000000080000000200000000000000000800000000000400010000000000000000000000000000000000000000000004000000000000004000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17a", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xec4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4", - "transactions": [ - "0xf87a82012f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0d0666f18210bb986b7239269bfbd56336376ed77bb97b56e15df7647c1f06fe3a0718dc6abdefe863e76f0c3c356364d456d34d399b20ed93b61ed93a77bccbe80" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf6f1dc891258163196785ce9516a14056cbe823b17eb9b90eeee7a299c1ce0e0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np379", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x891853e3e9dd73b513556fa241d000aa63fecc5452cf39b3cc756619e9cea7b4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x197f321622808ee71925004345aaf99ac87a833c97ee852265b6d8be5c0656fe", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xece", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07", - "transactions": [ - "0xf865820130088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02f7e9b19c96e60b8bd18eaadf71b049e0f204d42e826667e5b741041663c1963a01ff9a63ae688fc0c05047b819d1b8326c55f60b62f84658814bf35c63b3e5c65" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1dbf19b70c0298507d20fb338cc167d9b07b8747351785047e1a736b42d999d1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np380", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8d3b2038418a6d5e44a3f5aef149d7d76a20f3ebd5aa3c9d4565ddaa94d00c07", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x19c0d6f1bcdcb2c419bb69ed7f176bd58c4833c057faede354566c4e6d6e9f20", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xed8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1", - "transactions": [ - "0xf86882013108825208947f2dce06acdeea2633ff324e5cb502ee2a42d97901808718e5bb3abd109fa0fd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24a0542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc3b71007b20abbe908fdb7ea11e3a3f0abff3b7c1ced865f82b07f100167de57" - ] - }, - { - "jsonrpc": "2.0", - "id": "np381", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa63604362866798edab2056c5ddadc63dc1490c6f13bf5dd54008e1e0f64ecd1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6c634927494436f7c4daaee4ea5c99813ec3066af379315b031f40fdf12c74d8", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xee2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44", - "transactions": [], - "withdrawals": [ - { - "index": "0x3c", - "validatorIndex": "0x5", - "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3f45edc424499d0d4bbc0fd5837d1790cb41c08f0269273fdf66d682429c25cc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np382", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x2187bb0b54e92e3bc6f0da1665631a818ac120ad68aa9674277d542f1e542f44", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x04f641173e82bbe7455a3acd37242315859a80d9b4a19a56997645e31a1d1097", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xeec", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f", - "transactions": [ - "0xf88382013208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a08bc9a47ee84ed9389b94c57e8c7014515fefd3e891eff0e1deac8cb1266cfb05a06612fac81c3e0a0b905873bb3f9137f9f8ae952344a174e4d425564b31851350" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xcb8f5db9446c485eaae7edbc03e3afed72892fa7f11ad8eb7fa9dffbe3c220eb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np383", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdd46cd98c3f0f31bf7b060263fa47e9b0aa1c4e4c7206af16ad3a01dac3bff5f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2cc62d5cb6ca1b74dd31ced44a51655d15f0c67d9e8b4560584124ea91649145", - "receiptsRoot": "0x7288150e98b9056465e864af6976d5ec6de80da74cee77596b9a67de235177ac", - "logsBloom": "0x000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000040000000000008200000000000000000000000000000000000000000000000041000000000000000000000010000000800c0000000000000000400001000000000000001610000000080000200080000000000008000000001000000800000000000200000000008000000000000000000000000040000000002000000000080000000000000000000000000000000000000000000000000000000000000000000000000008000000000200000000040000800080", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x17f", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xef6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe", - "transactions": [ - "0xf87a8201330883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0f1dbbd841499d2a51db61a05cf4a7a5650fd83eafe8516d0ad49e99db40c0d13a0542104414214add483f5e7397e9b98e95d336d60ff2b661eabfc8125548df848" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3d151527b5ba165352a450bee69f0afc78cf2ea9645bb5d8f36fb04435f0b67c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np384", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x808dd663054b022868554929395cf380b27661a0ae7333a92d69160769afbbbe", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf88d2d5d961b54872a1475e17a9107724ba2cd0ca28cb7320aad2f903dc74deb", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x180", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xf00", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a", - "transactions": [ - "0xf865820134088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0922834adc69ced79913745b4a53a63ff0b0d73552c658f63c35b74fe831f1990a072af738962b2108e1e3e534c88145aa55764f2908bdbce0a4433ef88e3fbfb0c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xdd96b35b4ffabce80d377420a0b00b7fbf0eff6a910210155d22d9bd981be5d3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np385", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x86bca890ff8f5be8c986745f38ef4a87ce167fcaacc0de928f4c8db469bba94a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x248cbc35df3f48575474369a9105962a22bff30f3e973711545bb9cae1e06dff", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x181", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xf0a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa", - "transactions": [ - "0x02f86b870c72dd9d5e883e8201350108825208943bcc2d6d48ffeade5ac5af3ee7acd7875082e50a0180c080a03931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6a0215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xace0c30b543d3f92f37eaac45d6f8730fb15fcaaaad4097ea42218abe57cb9f4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np386", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x83132e862eb410579a38d85bbec7fdd5b890647bc9ccc2ad881361a9389cd3fa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x899d1787e12b4ee7d5e497ac1b07d460146316edd86d589dd357e4e39e6e50a5", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x182", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xf14", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e", - "transactions": [], - "withdrawals": [ - { - "index": "0x3d", - "validatorIndex": "0x5", - "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf6342dd31867c9bef6ffa06b6cf192db23d0891ed8fe610eb8d1aaa79726da01" - ] - }, - { - "jsonrpc": "2.0", - "id": "np387", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb2b948b9139c380319a045813000f17a02153426ae3db02065a7bc6fb1b3d41e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6fd59459f6805b1c3f35cd672f058d3f4215b8ba06217056195a249529106097", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x183", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xf1e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3", - "transactions": [ - "0xf88382013608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f68ef0be353bceb12bd978567947ea2ade48f275f8488d4d9089a6a5df54ecaa01ea605cad7ded16c6744be5446342cef46c0f802938d30db72ee4e35eb0ee726" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa6589e823979c2c2ac55e034d547b0c63aa02109133575d9f159e8a7677f03cb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np388", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xec59612429465042cb5bfe00c2720e2b06608cc0befdf12185f61213dede36a3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x87aa8da72c4f54683d4ddfe7592b17518075332583bf40a0af34b072e1b8d5ca", - "receiptsRoot": "0x6b2a7f9df51def8b942a27f69021bd8954a4d01182bc78fe20171ec738d6a1cd", - "logsBloom": "0x00010000004000000000000000000000000000040000000020000000000000000000000100208000000000000004000000000000000000000000000000000000000000000000000020000000000002000000000000000000020000000000000048000000000000000000004810000000201000000000000000000000000000000000000000000008000000000000010000000000000000000000000080004000000000000000040000000000020000000000000010000000000000000000040000000080001000000400000000000000000000000000000000000000000000000000000000000000000000080000000000000020000200004000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x184", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xf28", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462", - "transactions": [ - "0xf87a8201370883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a036602b451fdd27281014a28c261ac59feabe8c6730619162c51ccd6452e0efcfa01dbbc3cb987dd50dbb59072a156ce01b7825d252e5855249afbda11fd763436e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9ce48bc641cc1d54ffdb409aab7da1304d5ee08042596b3542ca9737bb2b79a8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np389", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x18a50573c6144ce2d2c185b146827fbde1568f647d6bcc2c2556df64a00d3462", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4970ca728c597509e3afb689227e843d5da3be74aea9719a756d65db2694b152", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x185", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xf32", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5", - "transactions": [ - "0xf865820138088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09a9bf09cafb07d6a97b972a3b405a1dd30dcd6945d9adda6cf921c211bc046e1a03c97b3b08d67e3ccfcb8408e39d2e0971761c1905fbd7028fb52a1f163fb92f3" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa44be801bd978629775c00d70df6d70b76d0ba918595e81415a27d1e3d6fdee9" - ] - }, - { - "jsonrpc": "2.0", - "id": "np390", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3ad7ba10baedb1b98556cd20670c57f2f3a4aa0ddfbf76c9a2cbbcec188dada5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc5da7efe2ca6d0468002914ea2c334be08121fb5450b4a1b74baf08e65115192", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x186", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xf3c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506", - "transactions": [ - "0xf8688201390882520894f83af0ceb5f72a5725ffb7e5a6963647be7d884701808718e5bb3abd109fa0a38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751a067c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xce17f1e7af9f7ea8a99b2780d87b15d8b80a68fb29ea52f962b00fecfc6634e0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np391", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa2deafade520007dd7d127c439290f2bac7a2027b80ff616ccf8ce62eeba6506", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7f1f4d793182771fbacb9ef07a0736edbe4aa2417bf775c7b499b35ad791575a", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x187", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xf46", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92", - "transactions": [], - "withdrawals": [ - { - "index": "0x3e", - "validatorIndex": "0x5", - "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4bd91febab8df3770c957560e6185e8af59d2a42078756c525cd7769eb943894" - ] - }, - { - "jsonrpc": "2.0", - "id": "np392", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfce102ce6fa4701cfa7ca7c4aae937b79190e29b55a453e67f31adece99c4f92", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x58f87e8c7ffa26035df5258225c492a17f353b2d33420e0ac5b5413f0c29be1a", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x188", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xf50", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d", - "transactions": [ - "0xf88382013a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e60cd99574bb50b626cf0b20d73ece21858aba52609136e6e2dc420a9fdc00eea00aeff0a4419c24268d9784a1ae211927004d8dbbbda3c47c0d0e2d32178ce8f4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x414c2a52de31de93a3c69531247b016ac578435243073acc516d4ea673c8dd80" - ] - }, - { - "jsonrpc": "2.0", - "id": "np393", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5aff5c82ef6756d97e6caaf6bc6084f4091ed2503b88083a0c4b0484f6e9525d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x14a7327b3cff203afe17f16aca0470fbe12cfac971c79ef9bd5b3ef71bce5591", - "receiptsRoot": "0x3b0559fd9e27f69f8a378d27e3b5a82f18881f307f49ec63f89ad4bae18a1ee6", - "logsBloom": "0x00001000800000000000400040000000000010002000000000004000000000000000000000000000000000000000000000000000000000040000000020000000000000000000000000000000000001800000000200000000000000000000000021000000000000000000000000000000000000000000000000002000000000020000000008000002000000000000000000000000000000000000000000080100000000000000000000000000000020000000000040000000000000000000000000000000000000000020000000000000000001000000000000000200000000000000000000004000000000000000000004000080000000020000001000a00008", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x189", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xf5a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6", - "transactions": [ - "0xf87a82013b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa061705b5163977bf95976fb0d2f44c1c581d19de8f68084001ed516813a7f5785a07daeb176a18749f11e1cec56a72e988c8362c2e15b86a9c5ae3e2cb2ddde0ce2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x647fb60bdf2683bd46b63d6884745782364a5522282ed1dc67d9e17c4aaab17d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np394", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb22e30af8a7f23e2b73275e505b5c6f482357576c82e3d718b0c4c33914d97e6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x02eb8f611a78bed4123c7b1ec6ca3148dee547538828183756744882a58b6993", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xf64", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0", - "transactions": [ - "0xf86582013c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0463d74275ffee97deea0603bdab389823c88c03997f176d4c349514d78d4dbc4a06b9796eed221b40094ded3ec3fa9bdbf097561ac3f8a142fef5e2c894a8296de" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfa681ffd0b0dd6f6775e99a681241b86a3a24446bc8a69cdae915701243e3855" - ] - }, - { - "jsonrpc": "2.0", - "id": "np395", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9a348ddcb5d7c63d344358308acfd52c1be4432de1bdd02a4c1483521b95d7e0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe5d836ff1dc0a199a799bdb1aa945580acf9e06c96bd6b88cbc60903e5904b9c", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xf6e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca", - "transactions": [ - "0x02f86b870c72dd9d5e883e82013d010882520894469dacecdef1d68cb354c4a5c015df7cb6d655bf0180c001a06faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07ba0656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x106ca692777b30cb2aa23ca59f5591514b28196ee8e9b06aa2b4deaea30d9ef6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np396", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x584b00c97139674af12f17a4a4828e59951c7f7d0c4fae83d5711ce5e582fdca", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8fc7b0893f25c43c0dd53f57c7f98653e86d2570923f1831840c09c7c728efab", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xf78", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4", - "transactions": [], - "withdrawals": [ - { - "index": "0x3f", - "validatorIndex": "0x5", - "address": "0x6d09a879576c0d941bea7833fb2285051b10d511", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x494ac6d09377eb6a07ff759df61c2508e65e5671373d756c82e648bd9086d91a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np397", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8e2b4e77e4fd7ab14ffaca65bc3a0868f14ce792ffe5f26cc0cc4abf8ebc5cd4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb87cec8c84db91856e9ae32af116b449b8cb1d61cae190a182aebfb85d691e8f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18d", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xf82", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe", - "transactions": [ - "0xf88382013e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0065cd2e05815fd9bf6e9aced9947d0c43feed03d4bd010ce93828c5e45a9b483a019449b8fc18e639f9c1d7b0adbd3941622d1f2e8127b82993e0f8bb9cdc2999f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0ae4ccd2bffa603714cc453bfd92f769dce6c9731c03ac3e2083f35388e6c795" - ] - }, - { - "jsonrpc": "2.0", - "id": "np398", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x657f16f62e12433129b4b3f80e92eee4a65d1cb6e8b847ce632d32cb79ba5abe", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe154fbe6ca3c192310dea977b202b7e57523be45dfb36cf46816f7b1b86c910b", - "receiptsRoot": "0x09e88b070a05aab53918792ba761837b32e299692e1ee33a27d3b654a45ea25f", - "logsBloom": "0x00000001000000000400000000001000000008120000000220000000000400000000008000000000000000002000000000000000000000000000000000000000020000008000000000000000000004000000000000000000000000000000000080000000000000000000000000010000000000000200000000000000004004000000000010000000000001000008000000000000000000000000000000000008000000100000000000000000000000000010000000000000000000000000001000000000000000000000000000000010200000000004000010040000100000000000000000000000000000000000000000000000000000000000020000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18e", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xf8c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa", - "transactions": [ - "0xf87a82013f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a017bd3457b4b843b788bd719c6e49a5efad177ca349fa23ee93130c68a6c123a6a0595becbedbd04d964a7e8ca826f50061e1b1f16bea32c966670f7dbcc63dbbff" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd860c999490d9836cc00326207393c78445b7fb90b12aa1d3607e3662b3d32cd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np399", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x677cd475087726e83d09edba4d2e6cdcaa5f1b9f5e7c26260ff6ebf4dd86a6aa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x771db9f41d228f8d3e1a33889cc04468bb9691860cbdbf28203d90713eed1fb1", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x18f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xf96", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f", - "transactions": [ - "0xf865820140088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0db06597d4b08ca3fef9b08c69896cef6505785b448bfd0e051ebc7616a2f5a1aa07ca5051c69a0dcb5fae23ba89cb806d860072426d2e450eda056e9e9d8ee360c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9587384f876dfec24da857c0bcdb3ded17f3328f28a4d59aa35ca7c25c8102cf" - ] - }, - { - "jsonrpc": "2.0", - "id": "np400", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf60f85724891ffc25eb8c5c596e55846df4032b2edb35d0fc6ac64870db6b42f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd210aa806d0d5c95200a88fcc329357fb03782cc236bdc5f184c80246391162f", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x190", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xfa0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f", - "transactions": [ - "0xf8688201410882520894f14d90dc2815f1fc7536fc66ca8f73562feeedd101808718e5bb3abd109fa04a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836aa0598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4df8093d29bc0ec4e2a82be427771e77a206566194734a73c23477e1a9e451f8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np401", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe7a757335322c1008ee83083154c9a787ea3d93efce41c1b32882c8a6ea3a14f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf77d84bb9077b7805492805f09aaeac8fdd72dadaba54464256d1b9633d7313d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x191", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xfaa", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289", - "transactions": [], - "withdrawals": [ - { - "index": "0x40", - "validatorIndex": "0x5", - "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc56640f78acbd1da07701c365369766f09a19800ba70276f1f1d3cd1cf6e0686" - ] - }, - { - "jsonrpc": "2.0", - "id": "np402", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x32976c704b12fd1ec0e6a409b89c8d3d5d0802f676bfd1848ae07cbb612f0289", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8c45d111367d1e2766e18c8ef100cb4cbdd1db4171d269d0dee91b7789bf302e", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x192", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xfb4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658", - "transactions": [ - "0xf88382014208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0bab2abc49f4f65119331667d5bd95daefb8eec437cb7950b46f1b9a890efd4b7a065396085f5f690d669006b05bab15614816e44cf88bf49fcdf0a5857f364e6a1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7173d4210aa525eece6b4b19b16bab23686ff9ac71bb9d16008bb114365e79f2" - ] - }, - { - "jsonrpc": "2.0", - "id": "np403", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4cbab31c513775bdd5b7f91a153fff77cf1602430cedcebec80bedf0b6533658", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xade6dd841f231dcce74ab564f55972731c7eb4a0b5c3ec1a64bb979f754b786c", - "receiptsRoot": "0x424252c901f76c684b72e2637c97666a35b4020fe9fd8add1bd00fc83cf57512", - "logsBloom": "0x08000000000000000010000000000010002000000000000000000000040000200000000000000000001000000000020000000000000000000000000000000400010000000000000000000000000000000000000000000000000000000000000020400000000008100000040000000000000014000000028000000000000001000008000000000000000000000000000100000000001000000000000000000000000000020000000000000000000000000000000000000000000000000000800000000000080000000000000000000000000000000000000080000000000000001000000200800002000000000000000040000000000000000000000400000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x193", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xfbe", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514", - "transactions": [ - "0xf87a8201430883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0097f470d08b374cc1ea0e0ecfb841f22e6f105c4989a6a41f23619320011f4dba06c843174399416f4a98ee5b5170a4330fbc487cc1bdc4e67f8eb3ca279fa8415" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x89698b41d7ac70e767976a9f72ae6a46701456bc5ad8d146c248548409c90015" - ] - }, - { - "jsonrpc": "2.0", - "id": "np404", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x64bfcedbb6b431f370027c5e2414fa70536e4cadaedca69d960d815570b1a514", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x96e966680b69cd6f8f3c95b0bfcaa337959db055f2b4329813dd02f9e5350742", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x194", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xfc8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da", - "transactions": [ - "0xf865820144088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a09fd0702bca1c10269dcf83862a9f07981858a8a1579f3ed68642fdc8b77478cda027b1f49755229583c844b747c040251c2671dcfe83fa26df37d4bbfb54635864" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5b605ab5048d9e4a51ca181ac3fa7001ef5d415cb20335b095c54a40c621dbff" - ] - }, - { - "jsonrpc": "2.0", - "id": "np405", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4a13ab52191afd567f4587bee39174c54ca458576730a03854abfad2aca2e0da", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7fa007461e28a3bd63c35eb625b4c122197ed1d63a00b0a0959652cb745c034d", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x195", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0xfd2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173", - "transactions": [ - "0x02f86b870c72dd9d5e883e820145010882520894360671abc40afd33ae0091e87e589fc320bf9e3d0180c080a09b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87a02c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9129a84b729e7f69a5522a7020db57e27bf8cbb6042e030106c0cbd185bf0ab8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np406", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3c7adb6035b88d99e1113b076cd7ee852294e0f651e87e779f93b9625f50f173", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3d03d9ffcd17834d8b99988eb8c1c9f36b8e627f50e2d850a6538d7610ba8457", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x196", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0xfdc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561", - "transactions": [], - "withdrawals": [ - { - "index": "0x41", - "validatorIndex": "0x5", - "address": "0x6510225e743d73828aa4f73a3133818490bd8820", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x31a63d6d54153ab35fc57068db205a3e68908be238658ca82d8bee9873f82159" - ] - }, - { - "jsonrpc": "2.0", - "id": "np407", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xda2511fe0f2d0c7384fdfaa42ba9d93127690645ed7f3bb5b48ab3bf31550561", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xeb5feebaa9bd10619704d66efc97f95338c3e02dcebc2710be462faa47ddfc63", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x197", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0xfe6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996", - "transactions": [ - "0xf88382014608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e767d5dbf82d8857bccd947a04354b0023b0e283098f75e4d7d79348c24dca95a00a4d04094359f0817637570cf1ed12dcd2614da2e845751734d67175839a3903" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x828641bcea1bc6ee1329bc39dca0afddc11e6867f3da13d4bb5170c54158860d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np408", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x32704763870e0504f0386bb2e87511ccb2d033c83e9ef57a72327f5d23fd3996", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xaadc011ce89c8dd628f56494b7f19d8cf66c1555b3cb6b38fd6e31c908e83804", - "receiptsRoot": "0x0c78f3779ab455eed4ce5e60071fff80a3d289a33fd656e17017d53978fada5d", - "logsBloom": "0x00000000000000020000000040000000000080010000000000000000000000010000000000000000000000000000000000000000000000000000000004000000000000000000000000000001000000000000008001000000000000000000000000000000000000001000000000002000000000000000000000000000002000000000000000000000000000000810001000000004000000000000000000000000000000000040008000200000000000400000000000000000000800000000001000000000000000000000040100000000000000001000000000000000108000000000000000020000800000002000000100000000000000002000000000004000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x198", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0xff0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606", - "transactions": [ - "0xf87a8201470883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a00eab4059563c228f12cd79cdc77c5594af5bb5f9778dab439aead79a99c7da9aa010476536728e9bf977ad4c2cc25fb7d5587869148789e9fd6bf40d65b9e94bbb" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7e0752ddd86339f512ec1b647d3bf4b9b50c45e309ab9e70911da7716454b053" - ] - }, - { - "jsonrpc": "2.0", - "id": "np409", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x16f96f705d6378a460f67690c9df7ba0b0130dfb7bda8d79ac2ffe9fdee84606", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0ed00985c27ccb9453093f70f7cae8594259e64c8962ee22121019210fe01824", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x199", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0xffa", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259", - "transactions": [ - "0xf865820148088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0310416be8b0e49ec34116f9c8eb4dd4d4dc6e39e5c97ccb94ac96e8cd21a7333a029b7a950def860ab8bfd4e49e5f34bc731344ab60770ea27f656e64e6b2f90de" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x31d973051189456d5998e05b500da6552138644f8cdbe4ec63f96f21173cb6a1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np410", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x70c71163387d8226f299ed02fd7f266f79d708f11ea9133d28a6b13ee751e259", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7ff6b18a2c62836e16cad9956e08422a430c268cda51f219422b628491066c6e", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19a", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1004", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78", - "transactions": [ - "0xf8688201490882520894579ab019e6b461188300c7fb202448d34669e5ff01808718e5bb3abd10a0a0de600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dca047d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe33e65b3d29c3b55b2d7b584c5d0540eb5c00c9f157287863b0b619339c302f0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np411", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x67c274a189945d313dccd5b9cb4b7fd47614b59c716a4ed0944d8a1429781e78", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x95d1e2783fcf975ce0a79a05166ad33628065812d76f1f92f88d8f77f5a49e88", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19b", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x100e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c", - "transactions": [], - "withdrawals": [ - { - "index": "0x42", - "validatorIndex": "0x5", - "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x78d55514bcef24b40c7eb0fbe55f922d4468c194f313898f28ba85d8534df82c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np412", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x7ae0486d0457d3261e308c1074c7a206e11f3a41a8b3b49ff379d0998a62278c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa1e185a2970fcd9903cadff06453ace3bff731a5295334d332c3fafd1d50033a", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19c", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1018", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf", - "transactions": [ - "0xf88382014a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa06222a14090e09278dc92b9002ee33b54e5bbbecd9afe56fa18d00dfe761ce8a1a06e8ec220dc8219ae16f46f3a4696fc8b4046fd33fa41efb473222fc058d65ed4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2e0f4be4d8adf8690fd64deddbc543f35c5b4f3c3a27b10a77b1fdb8d590f1ee" - ] - }, - { - "jsonrpc": "2.0", - "id": "np413", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb075a9e715b341d481dfad3f02ff0a123aa8043d4ae24d5f0574a7249cc00bcf", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x19a70ab3d8102a74b87887d95a29fe82ce4d4ab36fe3f57f336ded8bd0a7b3d6", - "receiptsRoot": "0x2ac314ac40ad6f04e3ec1fc2b315d4ce6eb64537ae9bf3fad670a0a1df1e5e3a", - "logsBloom": "0x00000001008000000040000000000000000000000000000000000000000002000000000000000000000000200000000000001000000000002000000000000000001008000000002000000000000000000000000000000000000000000000000000000080000000000000008000080000002100000000000000000200000000000100000000000002040000000000000000000000000000000000200003000000000000004000000000000000000000020000000000000000000000000000000000040000000002000000002200000000000000000000000000000001000000004000000000000000000000000000000200000000100000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19d", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1022", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581", - "transactions": [ - "0xf87a82014b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a07af33005afb5f1b38c17ed2bb2b83a0c1d0d6ecd30ab4e32091582d5a3eceb28a008bfc076226d8ebf0a2c86c5ea5f65ea1f1d0cb7b7036b2049444c2fcfb55031" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe1b83ea8c4329f421296387826c89100d82bdc2263ffd8eb9368806a55d9b83b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np414", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x936ce32cab37d0a985a937a8d3c7191ec7f48a10d524d04289d59efa4ca4e581", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0e4a2aebaaa31e943227335fd579582b6ed68abaa2706294b038ccb00ceae64f", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19e", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x102c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd", - "transactions": [ - "0xf86582014c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa05e26cfc612b47c55ae5a521eca26d4adbeaefe893bf1b0226cd121cbd7cdb45aa00be4c1040e89e1db4b10b4f36b38ef682de4f3308fd65d4f39346ffcf016cfdb" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4ddad36d7262dd9201c5bdd58523f4724e3b740fddbed2185e32687fecacdf6b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np415", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd352dfead0be49f8a1f2f7954f90df4b3e4383f8adb54062abd8041b0a0878fd", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc149cc44783e5dc5c6be9d4facfc2e9d3d31dff27f8495ea3fc2acfc22310516", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x19f", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1036", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6", - "transactions": [ - "0x02f86b870c72dd9d5e883e82014d01088252089488654f0e7be1751967bba901ed70257a3cb799400180c001a0a79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0a0750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x156c0674e46cdec70505443c5269d42c7bb14ee6c00f86a23962f08906cbb846" - ] - }, - { - "jsonrpc": "2.0", - "id": "np416", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xddf15ae692657c7be84b2e663acd7d669dc84a83622c9bbca07aba3a8461d8a6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x39d41e6a842119b876ef50fcce4e677b2760950f191f0b17ac11bb61f5d271b0", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1040", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb", - "transactions": [], - "withdrawals": [ - { - "index": "0x43", - "validatorIndex": "0x5", - "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xdfc56ec6c218a08b471d757e0e7de8dddec9e82f401cb7d77df1f2a9ca54c607" - ] - }, - { - "jsonrpc": "2.0", - "id": "np417", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5647e4a4349ab2ed23ddc1f61244c94f194735701ad4041ea62bc578654fecdb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6f8f7979fade5692d7fd5e0f6253e0e3082614421af4bcfbd63c12f2df06876f", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x104a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631", - "transactions": [ - "0xf88382014e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0fea6631902fceb5662ca53076387bbbb0e0fd9bcac1df121172fd29bd6700434a0632755563256841b198d853ee1861224df35abe91c6d15ca60cb3f660ce05e2d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x395d660f77c4360705cdc0be895907ec183097f749fac18b6eaa0245c1009074" - ] - }, - { - "jsonrpc": "2.0", - "id": "np418", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb50098d59b2351e10448f5560aff3f933bb24fed7101cda025bcdd5308fb4631", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x26b3aa514e4bfed98a760b1cc6d5c7c855232ecac4f00826049369385376458b", - "receiptsRoot": "0xa3ea729352d4252acd6b48dcc940d3acfe0d657ca5d3091eda1ae882c7c14776", - "logsBloom": "0x00000080200000000000000000030000000000000000000008000000000000002000000400000400000000000080802000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000800000000000002000000080000000000000000000000000010000000800000000000000000000000000000200000000000000000080000000000000001000000000000000000000004000080000100100000000000000000200000000000040040000000000000000000040000000000100010080000000000000000000000000010000000000000000000000000000000000000000000000000040000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a2", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1054", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5", - "transactions": [ - "0xf87a82014f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa08ded8700920cf761c49ef0831076f10597be8fe624b891585941b1a1d145a18fa05640b1e1c59257bc6b6352be6bb6a7862a541b3fca52da28912b08b8072b57e5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x84c0060087da2c95dbd517d0f2dd4dfba70691a5952fe4048c310e88e9c06e4f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np419", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd87426372101b44c6fb40defa47f5e64ced815cf6bcbe830367d328e52fa3bd5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x730477c9b8be2e32598ff45ddf03837963e5d2fcd5c8c07d23b47b385c22d4b7", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x105e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211", - "transactions": [ - "0xf865820150088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0bb5b1c9e4a9e86b6381ce83f476e3efb45b847315ec3e27e1536539ba2290f42a07eee4b7b9b0d0dc1b873baf519a668f4605ccbb82ad619acb74598535a35bdd1" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf4df943c52b1d5fb9c1f73294ca743577d83914ec26d6e339b272cdeb62de586" - ] - }, - { - "jsonrpc": "2.0", - "id": "np420", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xac9d6592b309e9e3ec0d899eda9ccd7d508e846553ac4a87da8b420c99173211", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xef5088187720800d3dec63e4e25560c839cad852b7a795fd9e9876ee2a02b16a", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1068", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b", - "transactions": [ - "0xf868820151088252089447e642c9a2f80499964cfda089e0b1f52ed0f57d01808718e5bb3abd109fa0c37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618a0190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0bb47661741695863ef89d5c2b56666772f871be1cc1dccf695bd357e4bb26d6" - ] - }, - { - "jsonrpc": "2.0", - "id": "np421", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x834b28c2883caaa276a3a0f2603da1bb8171001967787b96071588f296b7671b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8fa327b5c3e6a5036585a3b751910d613c3d2b6b56b0a5c1da7727ce50d4cb57", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1072", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198", - "transactions": [], - "withdrawals": [ - { - "index": "0x44", - "validatorIndex": "0x5", - "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4a1f7691f29900287c6931545884881143ecae44cb26fdd644892844fde65dac" - ] - }, - { - "jsonrpc": "2.0", - "id": "np422", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1232a401598e285a5e94aaa0644787458ac9e410b4b50cbc103523f2d2d4c198", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa5eef4d5746f0409111e198bb292fd06bf9ac9a14dc734ca636005246e713e5c", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x107c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c", - "transactions": [ - "0xf88382015208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0435a46c3720f21ff83b01b3d6e88f602e45dee024e69f7df083e47ee400fa063a020b2e545bea301a0322157c61d6f8bdee62066305c627c1c10fb9eb1fbdf0fed" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9b133cc50cbc46d55ce2910eebaf8a09ab6d4e606062c94aac906da1646bc33f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np423", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x271fd072d8e81da656b1f06548d486ce23f9fd399e070d3a01a3bd28c2d4eb7c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5486d8d4c4159eb6389774b47a76d5e347e3b31ecf92c08eda9e261e3106f0cc", - "receiptsRoot": "0xc0c07d0984b850e6ccc2e081d26ec135c42d526e9bb51a6c1987784d659c07d5", - "logsBloom": "0x00000000000000000000000000000200000000000020000000400000000000000000000000000000000000100000000000000000000400000000000000200010000000000a00000008000000000200000000000000000200000000000000000000000000000000000000000000000001000000000000000000000000000000000000000806000000000000000048000000000000002000000040000500001000000002000000000000000000000000000000000000000000000000000000000000000000000000000000800000000800002008000000000000000000000000000000020000100010000000000000000000000000000000000000000010000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a7", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1086", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212", - "transactions": [ - "0xf87a8201530883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a015ae0fac40a467ff5ad10fe01c838c564f0d30707c8b02be656345842959fedda07a3d9842f721d8cb4494a2df6ff689c4c19e44c8c81f013d1f969624d49850b2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x473b076b542da72798f9de31c282cb1dcd76cba2a22adc7391670ffdbc910766" - ] - }, - { - "jsonrpc": "2.0", - "id": "np424", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x966f75efe4cd3d4171d4dd7dbe65453d3fae561f5af4d67142cc15ad53dae212", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa9339a9c149937412b8c9d01a85c7af270578af9eebb80ad2cf208764c40e608", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1090", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91", - "transactions": [ - "0xf865820154088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0c14791fa1c6907f6279226a31c5f287c93702ba72f19fb9999b93b8ad612b36fa0371a0819796295976ab02fcafbe818a711cf6485a21d038dcb72b5000f04d63d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x225dd472ef6b36a51de5c322a31a9f71c80f0f350432884526d9844bb2e676d3" - ] - }, - { - "jsonrpc": "2.0", - "id": "np425", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x92a740edd1bceefb2f497e906a5f53bc10928c909069ba76b34663dabfc01f91", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xac3cc175fd0ba02252342155b4d9dd7fb790eb49b667058912b43f5bd6e939d5", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1a9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x109a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5", - "transactions": [ - "0x02f86b870c72dd9d5e883e820155010882520894d854d6dd2b74dc45c9b883677584c3ac7854e01a0180c080a07a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09a075f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x31df97b2c9fc65b5520b89540a42050212e487f46fac67685868f1c3e652a9aa" - ] - }, - { - "jsonrpc": "2.0", - "id": "np426", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5a7a3b8f0d389c13d810588336964f1a94b29184e3d9bc751eb64ef4635ad0f5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe677d652ba3a8822155791a1d1491ee57497ebfa49e3e38c909752dd8067a9e8", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1aa", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x10a4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9", - "transactions": [], - "withdrawals": [ - { - "index": "0x45", - "validatorIndex": "0x5", - "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4416d885f34ad479409bb9e05e8846456a9be7e74655b9a4d7568a8d710aa06a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np427", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf963480776054d809830c23d97833cfbf2971fc0fa04a6fe4974ea25a761f8c9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x08414161950ff53f6f053f2886c473a22eb595a0052de01fd24c7af1bc27a5ac", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ab", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x10ae", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec", - "transactions": [ - "0xf88382015608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa02f6b9a47dcc55d9130085e0dfd615fee0acea46517280eea07dff8ee6afd40e3a01fc33c02a467db6d30ccf56ad8b5bb32fd49ad9a7866db580e7a581987518921" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xae627f8802a46c1357fa42a8290fd1366ea21b8ccec1cc624e42022647c53802" - ] - }, - { - "jsonrpc": "2.0", - "id": "np428", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe8c8baed11565acb9d54e46ed79327292e07686ada5cd14fb02558ac39c518ec", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5afe7e66edc543cc377a33069ba58d5788801f1ef0f370d69ff71db5f63b6b88", - "receiptsRoot": "0xb278e6670351b21cd1c267f24972d7868327ae82ef7a3b377af968b4c6659925", - "logsBloom": "0xc0000000000000000020000000000000000000001000000001000000000020000000000000000004000008000000000000000000000000000000000000000000000000001000000000000000800010000000000000000001000000000000000000000000008000000000000000000201000001800000000000000000000000000000000001000840080000000000040000100000000000000000000000000000000000000000000000000000000800000000000000000000000000020000000000002000000000000000000000000040000000000000001000000400000000010000000000000000008000000000000000000000000000100000020000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ac", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x10b8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34", - "transactions": [ - "0xf87a8201570883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cbb3f84663bf7369864941fe566b1beb8d5db0095cbd49ebfdee89c164031e6a0461b62f4b01d15206e95e6c7bfe9364456d8b7edd446d1b488a2688c47b83775" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8961e8b83d91487fc32b3d6af26b1d5e7b4010dd8d028fe165187cdfb04e151c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np429", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xedf9debf0ac1be313a1f9e6f0121d36c284e2c7962acac1fa5c8aae207c07b34", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf1c25b007a4c84577aa49389214e8b8b63f81cb20b61095db784cd8e781fbdcc", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ad", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x10c2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e", - "transactions": [ - "0xf865820158088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0a285aa615fe480c778997ca57059b8ddec5cee0e5a94ec05cd028a03d04aadaba07549f0c6ded9fe03eb40b413803b8f02d9dc51591e29977d12a204518648008e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc22e39f021605c6f3d967aef37f0bf40b09d776bac3edb4264d0dc07389b9845" - ] - }, - { - "jsonrpc": "2.0", - "id": "np430", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x94a14e5fafedb96bffc4624affb9a20762f447e5abb90865c4418a539743932e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x401f1feec84dc7c894bb9f03dd52b5af121262ab2f6bd29e6de4e96c1ed67870", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ae", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x10cc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d", - "transactions": [ - "0xf8688201590882520894c305dd6cfc073cfe5e194fc817536c419410a27d01808718e5bb3abd109fa0163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810a04ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x7cfa4c7066c690c12b9e8727551bef5fe05b750ac6637a5af632fce4ceb4e2ce" - ] - }, - { - "jsonrpc": "2.0", - "id": "np431", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x855b2ccb1c00d717f49ec7074cee1f781edfc072eeef44012e18613a9172fc9d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc97f5e63e102992e2a849afad97481ea818d213707de515acd9c2bc246cdf65f", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1af", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x10d6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e", - "transactions": [], - "withdrawals": [ - { - "index": "0x46", - "validatorIndex": "0x5", - "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x943d79e4329b86f8e53e8058961955f2b0a205fc3edeea2aae54ba0c22b40c31" - ] - }, - { - "jsonrpc": "2.0", - "id": "np432", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4155e12dee1bb9ed17527871568425b8eb672004a2e2c19cb1947004fc5f0b0e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9c177f669a297c904a6a6ad51765a5916a0e0a3d9858b289e70bf054b370d685", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x10e0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586", - "transactions": [ - "0xf88382015a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa078d6fdbc4224106e1f59483aff597485ed0eebf922317913522a0693727b5ee8a035876b3170b9a88dc391f83dcac8088aeb65233613c74d8f50f1d1d3b1ce842f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x66598070dab784e48a153bf9c6c3e57d8ca92bed6592f0b9e9abe308a17aedf0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np433", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd660a48f06384f7ee4402d24193c76d2f4a00b85ca53ae9883b4ee3c07260586", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x98d101f68f7aa5bb170cfdd60281d7a5c3ae335ab03c0f87bdb5e72cc022d55f", - "receiptsRoot": "0x1919995eb19582a49f7b79b55e7ec75fae399916006f29e4177543d99cc2a5e3", - "logsBloom": "0x00000000000040000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000080000040004000001000000008000000000000000000000000000000000000000000000000000000000800000000000000080000001000000000000080000000000400020000400000000000000000000000000000000000000000000001000000000000000000000000000000000000000000012000400000000000002000000000000000200000000100000000000000000000000000000000000000000000000000000000004004000000000000002000000000000002010000004000014000000000000080810000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b1", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x10ea", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a", - "transactions": [ - "0xf87a82015b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09fb0d3ddf1fce9562d227b3cd6c35ac2e89f39141823d94cda0e6efb4519c715a06925af0950104623efa7954872196fe6d539eb269263a17db3740652382d100f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xac8fe4eb91577288510a9bdae0d5a8c40b8225172379cd70988465d8b98cfa70" - ] - }, - { - "jsonrpc": "2.0", - "id": "np434", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x73404b62b42dbc6a6604152b87426e852cc3b34847f45f27c0fca1f3a619f84a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7d06044c1009a2320b83bdfe22ffe7b8ffa6fa1f65d5e42f7c1588417a8ff421", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x10f4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08", - "transactions": [ - "0xf86582015c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0aa24c6fb2c99f1ce21f7ffd84e87fb6f81ff76cebe06fb5c0871294a353210dfa0350602877ed48896e8b4124b35c0c47da66c17fc0d553d9248ca1de942114306" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2b0018a8548e5ce2a6b6b879f56e3236cc69d2efff80f48add54efd53681dfce" - ] - }, - { - "jsonrpc": "2.0", - "id": "np435", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x9832bc48443f86a5809f75ad91caa04101363a43b300cef39918deaae8594e08", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x03d23380eb6a02b52fcfeb82c0fefd180c014e72a7f48f2627237e7bda6d5610", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x10fe", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f", - "transactions": [ - "0x02f86b870c72dd9d5e883e82015d0108825208942143e52a9d8ad4c55c8fdda755f4889e3e3e77210180c001a0673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88a017f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x823445936237e14452e253a6692290c1be2e1be529ddbeecc35c9f54f7ea9887" - ] - }, - { - "jsonrpc": "2.0", - "id": "np436", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe5e23a0fd4a2515c0e1292823b094a1aeec3ed64db400675b591fc077bf34c3f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf8829f712e0ea692e266ae3c78400816c5f5bc1d75a3bff3816f7fef71b2044c", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1108", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1", - "transactions": [], - "withdrawals": [ - { - "index": "0x47", - "validatorIndex": "0x5", - "address": "0x5123198d8a827fe0c788c409e7d2068afde64339", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x3051a0d0701d233836b2c802060d6ee629816c856a25a62dc73bb2f2fc93b918" - ] - }, - { - "jsonrpc": "2.0", - "id": "np437", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6e26197c94723ba471d049f6082abd0a6e684225b2ee9d8fa675b18ef11492c1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc66ecc1bdb4fa4b85c0b383d4db20fdaa2cba32973260dc444abb43e8536e93a", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1112", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac", - "transactions": [ - "0xf88382015e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0179370023b242bccf25d4899c2f29936353b5f1c37a8f7c665e55b75f80bf297a018a66d1d2ef7072f7fc54af07d15edc14ecf5a71f510be740c090f0815178ff2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x44a50fda08d2f7ca96034186475a285a8a570f42891f72d256a52849cb188c85" - ] - }, - { - "jsonrpc": "2.0", - "id": "np438", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb5f0ca3b4503c50b8eab9c63a95b209426af616a5b0d8468e63246c3f590caac", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa9b50e298c6a4bbd23a659ab24a3a7426b1087497561c39de2f1bf27da019b83", - "receiptsRoot": "0x8f45041560ebf83ec428723c6d69db271346e4c5a1b234b56efe318d549187cb", - "logsBloom": "0x00000000000400400000000000041000000000000004000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000202000000000000000000000000000080000000000000000000000010000000040000000004000004800000000000000400000000020000400000000000000000008000020400000000000000000000000000000000000000000000000000000000000000000000000000000000000800002000000001000000000000800002000000100000000000000000000000000000000004000009000000000008000000080000000000000000000000000000000900", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b6", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x111c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86", - "transactions": [ - "0xf87a82015f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0354b9d4a470abdae9da30183321b96b5fd09bc96c1ebd3137b3c6350c21e8de2a026877262b14edc851e17cba052b022dd1038fd51ef65ecbaff09dd07186f035a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6e60069a12990ef960c0ac825fd0d9eb44aec9eb419d0df0c25d7a1d16c282e7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np439", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfe8e1ceca43818cb8f2e4fc94ead6cea53a8fd515af2bc67a39a15584ec3cd86", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xad6a72de336a98aec47ed431bf7d39d537741125313255629633cba91b0097bd", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1126", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3", - "transactions": [ - "0xf865820160088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa09c6b3542e181028aad33517584cd16e92836f975955abdcbf1205b6250c921d4a040816d88e011c2d3073502523867b94987fa0781793a7857ff2453ec2d121444" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x581ddf7753c91af00c894f8d5ab22b4733cfeb4e75c763725ebf46fb889fa76a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np440", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfd02d6b4d954d36af8829bf98464c0cc410de1e28216e45ac5e90fc1fc5780d3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x863de67ea016127a436ee6670f8642bd5ab997ce75361c3cce667abbe90b7283", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1130", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192", - "transactions": [ - "0xf86882016108825208940fe037febcc3adf9185b4e2ad4ea43c125f0504901808718e5bb3abd10a0a0654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892a070505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9a1dfba8b68440fcc9e89b86e2e290367c5e5fb0833b34612d1f4cfc53189526" - ] - }, - { - "jsonrpc": "2.0", - "id": "np441", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe0c31051877e8d3f6f625498659eff12247ded622d4155f6fd4a498852e46192", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x66989995258d8db8bd3b8eac83c7762c50323b8f21f1aaddf3ad0208afc6318d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1b9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x113a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac", - "transactions": [], - "withdrawals": [ - { - "index": "0x48", - "validatorIndex": "0x5", - "address": "0xd39b94587711196640659ec81855bcf397e419ff", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x54a623060b74d56f3c0d6793e40a9269c56f90bcd19898855113e5f9e42abc2d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np442", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe9da2b3df6fbc520bf3a80b36bd3437210880763ea7acbf422076049724a14ac", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf37b2d059d8764938039410fc2581f4793fb4f9c66abf4f8a32276dd60334f4d", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ba", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1144", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e", - "transactions": [ - "0xf88382016208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0bf7859d7e53ab582f4189f50f06832f2fa9763498350b739d7a677b34df97861a03ab21050f73bda7c737cef08e6a77edc9766aa0ef14dfdfc22fbcfdb6771825e" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1cfeb8cd5d56e1d202b4ec2851f22e99d6ad89af8a4e001eb014b724d2d64924" - ] - }, - { - "jsonrpc": "2.0", - "id": "np443", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xeafce24dfb100daa2a1ee55da0030d8e057fc943b96b6e7f321af98b47e8107e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x23eacf2b963df64726e41314251669bf12f3925de3933e0b713863d1a7a6fc6b", - "receiptsRoot": "0xc97de406788b669a824183dab763b8caa8988371aea1f18b96e6b1f9abdee729", - "logsBloom": "0x04000000200100000000002000000204000000000000000000000000000008000800000000000000000000000000000001000080000000400000000000000000000000000000000000000000000000000000400000100000000000004000040000000000000000001000000000000000080000000000000000200000000000000000000000000000000000008000000000000000000000000000040000000000000000040100000000000000000000000000000000010000080000000000000000001000002000000000000400000100000000000004000040020000000000000000000000000000000000000000000010000010000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1bb", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x114e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96", - "transactions": [ - "0xf87a8201630883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0332397d6a00a7d2a3453bf053c8d158774d82d6ea252c2d564bbd48f9e882418a01187aef824b2759cba8c1574666919b77889353a9905720170518b03b38cc71d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xad223cbf591f71ffd29e2f1c676428643313e3a8e8a7d0b0e623181b3047be92" - ] - }, - { - "jsonrpc": "2.0", - "id": "np444", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa53dc7dc3ac37fdd69bedd119e5113397594ab4171b7c010913864890dbd7f96", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x71e7debe9374beede2414966d6eb2c2eadf548c293ba65821869bc274709badb", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1bc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1158", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e", - "transactions": [ - "0xf865820164088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0b7296876d0713a392d440d71244cda1a3ecb09009a2f4d0ae5d26a398a8bee92a04dd844c3b7cbf88f10b080a3a0fd8a0e21e8d3041450c69786efe9ee7af18dcc" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe13f31f026d42cad54958ad2941f133d8bd85ee159f364a633a79472f7843b67" - ] - }, - { - "jsonrpc": "2.0", - "id": "np445", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x48640726ce7b39f951f82d46cfd4f8d71c93534109a0f93810c41289f6c97d2e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x58a574089cbd9986bf63c3ee8e0e8d400e9b97b8d1280166f7505de051f4c661", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1bd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1162", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6", - "transactions": [ - "0x02f86b870c72dd9d5e883e820165010882520894046dc70a4eba21473beb6d9460d880b8cfd666130180c080a09a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996ea0418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb45099ae3bbe17f4417d7d42951bd4425bce65f1db69a354a64fead61b56306d" - ] - }, - { - "jsonrpc": "2.0", - "id": "np446", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x40fa37188938bd349b17c8738f79a071533e0c0f6eaf4b1d6d6614fcae9925d6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbd0820c57ebb5be91343940d7197af10c1d95a23a1b99bc5fa1a77997849273c", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1be", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x116c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19", - "transactions": [], - "withdrawals": [ - { - "index": "0x49", - "validatorIndex": "0x5", - "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9d2b65379c5561a607df4dae8b36eca78818acec4455eb47cfa437a0b1941707" - ] - }, - { - "jsonrpc": "2.0", - "id": "np447", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xeebf24886684542e08624e438bfad2c52eded1a4924aef3fd58d60ed6eaa1d19", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbc2acbe23d81c5bec8c73c20cfbb12be681cc92fa399ed4a44e7a91fb433c577", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1bf", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1176", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f", - "transactions": [ - "0xf88382016608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0daffe9dd6ca6d33e1a44ce5725c7e795639c4bd4a36cfb18d520c9fc892b7ca5a01286dcff57cb583238854ca89346c969387d982ca7e14cbd82413855fdda282a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5855b3546d3becda6d5dd78c6440f879340a5734a18b06340576a3ce6a48d9a0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np448", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x837fc89a9611fa0b6a0d2f5a7dec3e06eda2ea3ee84bc6ce214c432b243c256f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x95fea999be7fc8cfa0e1c8a9a10dc33d073417bf87ff698edab332c6e18ecc60", - "receiptsRoot": "0xcf29f818a1be0922fc0576d2500603f4e9ab8a9e251986d891170f993f0c8f0a", - "logsBloom": "0x00000000000000000000000004010001000020000000000000040000000000000000000000000000000000000001000000000080001000000000000000000400000000000800000000000000000000000000400004000000000000008000000000000000000000000000000000000000000010000000000000000040000008000000000000000000000000000000000020000004020000000000000000000002000208200000000000080000000000000000000000000000000080000020000000000001200000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000010018000100000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c0", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1180", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa", - "transactions": [ - "0xf87a8201670883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0745918999757459ef7ab7145b734444d0437fa7b3939a6ca2a07652a727d1ef9a0074b0898accddb3ac54941b1fce130c31edd3d838dfefd506668cd989f4c5389" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xd6a61c76ae029bb5bca86d68422c55e8241d9fd9b616556b375c91fb7224b79e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np449", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x05505959a8095b30ab40f55294926448248b48b0430ce33332c7b748e956aafa", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa4269875f0bd6dc1360830e3e07eae0956700e8c3aa69cd61b423abf51bfce54", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x118a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30", - "transactions": [ - "0xf865820168088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa01f0e57c3b6f3908a7afb46717ef32caf9b73c4a4b2f48b09e0fcbea02ae716e1a017c79cab83300efab682d0c0438b23b49136a17e22560e75d32014c5951b4fd4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x96ac5006561083735919ae3cc8d0762a9cba2bdefd4a73b8e69f447f689fba31" - ] - }, - { - "jsonrpc": "2.0", - "id": "np450", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x57095cf08428bbd1fff32a14f1a811750ff2de206ee3ea1d6f6f18f7a2606d30", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd315f1048882fde9bc00a0bae351ab3229cec00efa7ef4b61fd5c1be40619f81", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1194", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08", - "transactions": [ - "0xf8688201690882520894104eb07eb9517a895828ab01a3595d3b94c766d501808718e5bb3abd10a0a0597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0aa01f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4ced18f55676b924d39aa7bcd7170bac6ff4fbf00f6a800d1489924c2a091412" - ] - }, - { - "jsonrpc": "2.0", - "id": "np451", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe6d3cb3da9e188604d0e8bc2f03a0df4fefa836f9bf4b679e54e97138f72dd08", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3222feed7d40d321811eb16ac78aaa0561580b176e0605bfecc30427a7702996", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x119e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b", - "transactions": [], - "withdrawals": [ - { - "index": "0x4a", - "validatorIndex": "0x5", - "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc95a6a7efdbefa710a525085bcb57ea2bf2d4ae9ebfcee4be3777cfcc3e534ea" - ] - }, - { - "jsonrpc": "2.0", - "id": "np452", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x465bd8f010df142744fc22da07b631a4e2d11ae75bca1608f7592548c420178b", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x96bcc6f26c5f94c33c57d1614edd2b385e36d9972250c79758eeaeb09927c0a8", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x11a8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9", - "transactions": [ - "0xf88382016a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a03fc929c6e9476221ddd5f2f5093981cc13f4b8206ee3454720f06c0bd5c95caba038f23a2c21ba59155127a15502ddd731f30d6f94c6aafde8e73fbe39237766a2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x2b2917b5b755eb6af226e16781382bd22a907c9c7411c34a248af2b5a0439079" - ] - }, - { - "jsonrpc": "2.0", - "id": "np453", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc7131bb27a6e1395d028d543cfd6f9e71ec4f2d2ecbc44cef53b5b626e01cad9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x168c847144cfea8b88e6ec4f673ebddbf18331bde8002e044b1d1df7408edf04", - "receiptsRoot": "0x4ff26b781abcaf6d8a14f4f5283feeee87038dbcb46b9987d6042a01b1b07f9a", - "logsBloom": "0x00000000000400000000000000800000000000002000008000200000020000000000000000000000000040000000000000000000000000000000000000800000000000000020000000000000000000000000000000000000400000000000000000000000000000000000000000800400000000000000000000000400020000000000000000800000000010000000000000004000000000000000800000000000000000001000000000000000800000000000000004010000000000000004000000000000000000000000008000000000000000000000000004000020010000000008000000000000000000000000000000100100000010000020000004000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c5", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x11b2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d", - "transactions": [ - "0xf87a82016b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa07061a8a3f917f765ec8aef5e4ad237d377c0131f63f31da7bdc6af9942a1bc4aa051bf3e7c6676f2fbde507834995f4e269113adf35b98bc71cd22d9c168692f5c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x18d5804f2e9ad3f891ecf05e0bfc2142c2a9f7b4de03aebd1cf18067a1ec6490" - ] - }, - { - "jsonrpc": "2.0", - "id": "np454", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x6d6eba2abd0851251651f038c9bcd8b21c56e6cefc95adb259a2b0c3ae4f158d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7e75fe29c17414bea5febf41c577c117b57c1a731aa7a18b6c5d2ba9e3bc27dd", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x11bc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c", - "transactions": [ - "0xf86582016c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ec3fe55b96a9d14e22fc0a8aa5991138ba954245754c0e0dda2b5b7dbb6711caa0296a6b87da18224fac7c922e2a7f0ec41330a6f510934a1e0e3c6a65dd72dfcb" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb47682f0ce3783700cbe5ffbb95d22c943cc74af12b9c79908c5a43f10677478" - ] - }, - { - "jsonrpc": "2.0", - "id": "np455", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5cfbc66c760f871b8cf6d87140887788db0622a0f54274737f9cd043b156f50c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdf26695268f674fc809ad21c323bcab53727af440302b923eec2d46ee3cd7aa3", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x11c6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb", - "transactions": [ - "0x02f86b870c72dd9d5e883e82016d01088252089446b61db0aac95a332cecadad86e52531e578cf1f0180c080a0774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008ba06f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe4b60e5cfb31d238ec412b0d0e3ad9e1eb00e029c2ded4fea89288f900f7db0e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np456", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x8f4a24fc6a150744744d03371d34758cf69d4216538804395397ed081692c7fb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x358b2d72362d209f8c7131a484e49caff1dda8f550fe6103be80ac369cfe49fc", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x11d0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a", - "transactions": [], - "withdrawals": [ - { - "index": "0x4b", - "validatorIndex": "0x5", - "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfc0ea3604298899c10287bba84c02b9ec5d6289c1493e9fc8d58920e4eaef659" - ] - }, - { - "jsonrpc": "2.0", - "id": "np457", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xafcf58746fc811dd74a0e4a66d91efbb00b2ab2c96680e132234a947798abf7a", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x2dd7146f049ba679aae26c42d1da7f6660ea964a7b227509e5296a9d0170e93e", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1c9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x11da", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4", - "transactions": [ - "0xf88382016e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa038214a2cc756a0ffe043200d5e12183223f81912c0156df732c3b1d85bc2a237a0744a52bf9fca64223bc279e589d21b9fda190325bf3b576f41a792ccbec5bc08" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4c3301a70611b34e423cf713bda7f6f75bd2070f909681d3e54e3a9a6d202e5a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np458", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5346eb38677572982317e96be00144f1600800e5a738c875522183ad74f408d4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x62b1bdf3b4a63f480b24af9f3b55dc6ad6e52bb81caa13b286960694b3b600b0", - "receiptsRoot": "0x25a0fc424c07569fb4229958de04f1d6497b3d8b6a78757f42963f95c354e2b1", - "logsBloom": "0x10001020000000000000000000000000000000000000000100000100000000000000000000000000000000800000000000000000000000000000000040000000000000000000000000000000020000080000000000000000400000000000000000001400000000010006000000000000000000800200800000000000000000000000000000002000000000000000000080000000000000000000000001000000000000000000000000800000000000000000000000000000000000000000000000080000000008004000000080000000000000000000000000000000000000000200000000020000000000000000400080000008004000000400000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ca", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x11e4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c", - "transactions": [ - "0xf87a82016f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa05e304ec406ec4c83644417e1e58b49757d3ac78da5c5280fbda19b1f149137daa035b73caa8da3b6ce0e5f1b014c127f93f7be595f104cd933b5ff07549fd1812b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x84a5b4e32a62bf3298d846e64b3896dffbbcc1fafb236df3a047b5223577d07b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np459", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x83f464b150683ab5ce359179f4f9d6e960049959d2ec46a4ae7a07af2de41a6c", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5614ae860626ff1e044740a53f3cb5126f72002928c034aecbdfe4291ce73b91", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1cb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x11ee", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5", - "transactions": [ - "0xf865820170088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05d0d172a5fb9787aa2ee5205e5986de935984adf6030d5668be0e31332f7b145a022c4c7a89391e8f4508095fc5c1ed16aa0c08da6790be108240dc64763d42dae" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xff70b97d34af8e2ae984ada7bc6f21ed294d9b392a903ad8bbb1be8b44083612" - ] - }, - { - "jsonrpc": "2.0", - "id": "np460", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3c1ccfa2b5f88830245f76a22fa29ce22fb5b284de5937ff66adc67a445bf5c5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x715b0d1e4306032fa54c79f84599828d98bc84ed9cdb52a407e58730b4c112db", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1cc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x11f8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6", - "transactions": [ - "0xf86882017108825208948a817bc42b2e2146dc4ca4dc686db0a4051d294401808718e5bb3abd10a0a0a755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1a067d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x73e186de72ef30e4be4aeebe3eaec84222f8a325d2d07cd0bd1a49f3939915ce" - ] - }, - { - "jsonrpc": "2.0", - "id": "np461", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xfc7412d30ba5b6f5b319b07e51296906a42fdae50a88c1f90016d487b1df41f6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8c6710fa12f6392a52eaa92d776fe1c24245dd52883ff2276547e65c34952eeb", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1cd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1202", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3", - "transactions": [], - "withdrawals": [ - { - "index": "0x4c", - "validatorIndex": "0x5", - "address": "0x48701721ec0115f04bc7404058f6c0f386946e09", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xed185ec518c0459392b274a3d10554e452577d33ecb72910f613941873e61215" - ] - }, - { - "jsonrpc": "2.0", - "id": "np462", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xdad167dfa9bb65a470a36a3996f0587d645b3fbfe9e3522a1436f1dd6a3a37f3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x8c73a23f75ee594dacc63d24a5d5655a1ccbeead972dba58ad86787c44442c6c", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ce", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x120c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61", - "transactions": [ - "0xf88382017208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0567311948632a5f4d53e0491aa8e7f939a3e0da38be1db4b6c757422de3f8bf6a01134e092948e423c7f8867c02822c95f3ce21b6d4e8d3666e2cf47ca88ad7499" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5cfbad3e509733bce64e0f6492b3886300758c47a38e9edec4b279074c7966d4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np463", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc50795e72a34041bdabf74a87f77d78f3a07f2005396dcf9925b08a8a686bd61", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb6a995ce6f848e4f2f2ad8ced5491859a5d0a3b6767108f3ce5cfcb33303349f", - "receiptsRoot": "0x5bb341cd099f8898164b032e64db73752f528a10e8d9c60c9b4fff08af32dcf5", - "logsBloom": "0x000002040000000000000000000000000000000000000000200000000000000000000000000000000000000000000300000000000000000000010020000000080000000000000000000000000000000000000000000200000000000000201000000000000000080000000000000000000000000000000040100000000010000080100000002000000000000000004000000008a0000000100000000000400000000000000000200000000000200400000000000000000000000000000000000000000000000000200000000000000002000000000000000000000000000000000000000000000000030000000000000200000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1cf", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1216", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d", - "transactions": [ - "0xf87a8201730883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a06092eab6a3d9e41841ad4b9c97154ac35269c852606da6dd04940a1a055fa979a052a6e3e769e27310acdef840cb1182f4a2b6b08583b01cb8325c98253feaf7aa" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x867a7ab4c504e836dd175bd6a00e8489f36edaeda95db9ce4acbf9fb8df28926" - ] - }, - { - "jsonrpc": "2.0", - "id": "np464", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x69a26219f28581c8898c2790cf785e3f2b0081a416d51722d85b5ac313d5f36d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf54cc52e78b0ea88b082230970d262fc78070bff347c000f60c53400d111a59c", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1220", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e", - "transactions": [ - "0xf865820174088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0342c58642563f78afdb5cf7b9fbc935268a8fd81a5bd7997c33f61cdff8fb9c2a07466870d997603b5dd7755f151b76f056d4948ae82372b05babc01b9addaad19" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x0d01993fd605f101c950c68b4cc2b8096ef7d0009395dec6129f86f195eb2217" - ] - }, - { - "jsonrpc": "2.0", - "id": "np465", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3ed11b20d6eced6314897749d304a677d345ce9343fe964143548980ea71615e", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5b583ecaeffb409a488709df2c592c932e93a9b954bb5b62c36739324ae7d89c", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x122a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca", - "transactions": [ - "0x02f86b870c72dd9d5e883e82017501088252089423e6931c964e77b02506b08ebf115bad0e1eca660180c080a06263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242a02b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x8e14fd675e72f78bca934e1ffad52b46fd26913063e7e937bce3fa11aed29075" - ] - }, - { - "jsonrpc": "2.0", - "id": "np466", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x20ca98d23c09a37aa1805c3989ca7a7bfff9ade344de4575f5063a10c60510ca", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xdaf72de0a7092d2a2a6d31336c138ab45852ca65398578fbc435b3c591fa7c3a", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1234", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb", - "transactions": [], - "withdrawals": [ - { - "index": "0x4d", - "validatorIndex": "0x5", - "address": "0x706be462488699e89b722822dcec9822ad7d05a7", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4ec1847e4361c22cdecc67633e244b9e6d04ec103f4019137f9ba1ecc90198f4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np467", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd1c6165f74a48fb1da29dde0ec4588f1b5708d1b810696ab128a6db9ce08a1eb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb9f6529424870d0fbfe7d70438762f3ccf9d2f212d3e42c837f6e9218d72451a", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x123e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810", - "transactions": [ - "0xf88382017608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e42b1ec38a455f867d421d170e634c86f8a84a2cb00ec5024f343667042f303ea067797c75de08e6eafd819d4c408324fba318e16b378b7dedbc0708056aebb696" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xec69e9bbb0184bf0889df50ec7579fa4029651658d639af456a1f6a7543930ef" - ] - }, - { - "jsonrpc": "2.0", - "id": "np468", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xee2b973ebc00c239bf4fd6c382cc78890065370286476ae02a9b1bd76788f810", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3017b68d781fb29ccbca4c6ff597a9e18d6cee4f02974dbb32f04b5a7f519271", - "receiptsRoot": "0x00fbb0bcdb236cd79dbbefe84d42f31ee3274cc5e9116ffb0d70301b983dbd52", - "logsBloom": "0x00000000010008200000000000000000200400000000000000000000022000000000000000000000000000000000000000000000000800000000000000000000000000200080000002000000000000000000000000008000000000000000000000000800080000000004004000000000000000001000000000000000000000000010000000000200000002000000000000010000000000000004000000000000000000000400000000000000000000000040000000000000000000000080000000000200000000000000000000000108000000000000000000000020010000000000000000000000000000000000000000000000000000000040000040000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d4", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1248", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9", - "transactions": [ - "0xf87a8201770883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa01975b5adb5e05e7dbaf63d31d34e5dfb802c4ca28127176811ada2b0a9411be6a02b9cd65ba817631163e95275ec2bd5319edeef4f74eb6efb32150a523282db16" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xefdd626048ad0aa6fcf806c7c2ad7b9ae138136f10a3c2001dc5b6c920db1554" - ] - }, - { - "jsonrpc": "2.0", - "id": "np469", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x66a71dd383d4ead0e00787a06fcfb3c75c36fa72b5d98f39dc37ca129315b8d9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7da79133a491b6c2566dc329ed006ee0010fe59b515fbce5589eda0f31dd091b", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1252", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832", - "transactions": [ - "0xf865820178088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa02a73665ddc16b8e231ef04b5f0ad8afa56248db6f43222848032c72e97a807b8a00a17dda1a1d0ba616354fda9e86c836bcb002c7e54153be4cc95776446c6b2a5" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x551de1e4cafd706535d77625558f8d3898173273b4353143e5e1c7e859848d6b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np470", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x7f166dd54e16fcd0e302579768e0bb090b06f4e35cba5b48b0b5c42e367c0832", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xcbeab9491879fdd48e387106f31e983546cff3f4795ff5190722d2ac1f3792b6", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x125c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0", - "transactions": [ - "0xf8688201790882520894878dedd9474cfa24d91bccc8b771e180cf01ac4001808718e5bb3abd109fa0515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367a023756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x137efe559a31d9c5468259102cd8634bba72b0d7a0c7d5bcfc449c5f4bdb997a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np471", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xeedbf487ab11603d1a8e08d672886d16cd318bc421a358d199df281a473ac7b0", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x60452d4fa157207a12986fb9c810855fe19a2492ad046335ec9b4fe41e48de19", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1266", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7", - "transactions": [], - "withdrawals": [ - { - "index": "0x4e", - "validatorIndex": "0x5", - "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xfb0a1b66acf5f6bc2393564580d74637945891687e61535aae345dca0b0f5e78" - ] - }, - { - "jsonrpc": "2.0", - "id": "np472", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe2cefda7c9752d4706e180cf9228524bd767f36f6380f0c6255498abedc66ce7", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x0b580cdca4b5a562a85801f2e45bd99e764124b9715915fd4bfc6f6eb483ef96", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d8", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1270", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df", - "transactions": [ - "0xf88382017a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa05c8cad8eec0edc7394b3bace08088ee19b7eacb754b0a5695fc52a0cd17c19f6a0033d27e9eeb87fa5ae4868a14d0b66d941f0ffa3a3781e60cbb751bab7b507da" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x96eea2615f9111ee8386319943898f15c50c0120b8f3263fab029123c5fff80c" - ] - }, - { - "jsonrpc": "2.0", - "id": "np473", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x35f103c6c3cfc385bf9f512f7b4d7903e314b60cb715df196cf574391b8506df", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd08b438590148463c602be8f8899fd6c2cb42972fe2df0e71cb42ebefea3f404", - "receiptsRoot": "0x307ca5ba4dfd34e9f362cea8e1f54ff58f9318a35cf7e1ae24823d41572d7742", - "logsBloom": "0x00000000000000000000000000000000800000000000000000008000000000000000000000040000000000000000100000000000000000000000000000000001000000000000000000000400000000000000000000000000300000000001000000002040000000000000008000000000000000000000000000000000000100000010000000000000000401000000000000000000000000000000000000000080000000000058400000000400000800000000000000000000000000000000000001000000000000000000000000004000000000000100100000000000000000000000000000000200400000000000100000000000002000040000000000100000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1d9", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x127a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1", - "transactions": [ - "0xf87a82017b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa06cfb2ecb740895c1bdd352c502898651d83d35cb17ec4a0b30b04fe190a05758a02606cabbaa5b1d57ff9da73837cff8cbd03f242b83880f8cf3ba6f0ee907d538" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x68725bebed18cd052386fd6af9b398438c01356223c5cc15f49093b92b673eff" - ] - }, - { - "jsonrpc": "2.0", - "id": "np474", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x1f50e2662ba03c36242e9717f767077fd0d1659ed1a5e2e5024bf1a9de6303f1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6d86e3351111e6c2d4eafc36553273c03636a22fae54a9e076be2e7cb0cdf9d7", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1da", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x1284", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3", - "transactions": [ - "0xf86582017c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a044380da66c7033fceaa15191e7549bd08fed4c16f96cf1282b2f39bccaad1ff0a00d036ed4649f8300b82a534b03a19b4547784997b61328ba41dd7fa5380de99b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe2f1e4557ed105cf3bd8bc51ebaa4446f554dcb38c005619bd9f203f4494f5dd" - ] - }, - { - "jsonrpc": "2.0", - "id": "np475", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa3baf412ffd440d9baceb4d19fc213652de91fee569633fb5f8f77b737dd23f3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4e2eff0a0a0cfaa9726ffd557089d4a85855fabe4b81334326bd400289f5ed12", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1db", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x128e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06", - "transactions": [ - "0x02f86b870c72dd9d5e883e82017d01088252089445dcb3e20af2d8ba583d774404ee8fedcd97672b0180c001a0d3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4a0368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x48ef06d84d5ad34fe56ce62e095a34ea4a903bf597a8640868706af7b4de7288" - ] - }, - { - "jsonrpc": "2.0", - "id": "np476", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa63c5dedb28356376c60a58b8b766be086203e9b8d9c016e0863fd4e8cf42a06", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x3de8e5ff6961615b029591cbe9ea51723c809d965421da4f3f8ae26ffe59d69d", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1dc", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1298", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc", - "transactions": [], - "withdrawals": [ - { - "index": "0x4f", - "validatorIndex": "0x5", - "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5c57714b2a85d0d9331ce1ee539a231b33406ec19adcf1d8f4c88ab8c1f4fbae" - ] - }, - { - "jsonrpc": "2.0", - "id": "np477", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xbcf5e09e90541f9a8e36eca4ce43a64e1e05e93f4aba193be8e2da860b5ba0bc", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x6eb0d2ff3e3dd2cdaad61b121b06afcf7863f34152ecbdf8b8773604630a56b3", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1dd", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x12a2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257", - "transactions": [ - "0xf88382017e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a0939d9f6f260f24b45073aeabe00660f617f1dbfcf522cd6c90ef189dfc9dbfa0a02dfd90c6f1a6822039b8fbd5bff435e939882da970ed1b58a4639eddcb79b23b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x204299e7aa8dfe5328a0b863b20b6b4cea53a469d6dc8d4b31c7873848a93f33" - ] - }, - { - "jsonrpc": "2.0", - "id": "np478", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd5c167589a4663ae0585e5fff8fe256f35baaa26843df17dedcf6040709d6257", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xfadd61dbce8d90cae8144c1b2297209079517cb13f3a4e60a6c8f2ea7b4d3770", - "receiptsRoot": "0x3ec27c047700a74288e3ee48062fed9fbba71b1704febedea9f4e9e3a92faabf", - "logsBloom": "0x00100000000000000000000040004000000000000800008080000000000000100000000000000001000000000000000000000000000004000008000008200000002000004000000400000000000000000000000008000000000000000000004000000000000000000000000040000000800004000000000000400000000000000000001000000000000000000410010000000000000000000400000000020000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010080000000000000000100000000000800000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1de", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x12ac", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00", - "transactions": [ - "0xf87a82017f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a0dffee1543462b1d024b5d54728f2e3284d90d8fd24b94fd96bd027b4ca51e768a02ed5ddd2050f1b7bcbc123e31fb0536fbf1661a8f7541c7a10729e8a505cc080" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb74eea6df3ce54ee9f069bebb188f4023673f8230081811ab78ce1c9719879e5" - ] - }, - { - "jsonrpc": "2.0", - "id": "np479", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xb061affdd716a0d4c5d081a1c3659d0201dce5c698ae942440565ca789e55b00", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x931dde8f1566d5b88162261e5f8c8fede3f14bfab1c11934aae8f2a38aca7b36", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1df", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x12b6", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece", - "transactions": [ - "0xf865820180088302088a808090435b8080556001015a6161a8106001578718e5bb3abd109fa0c2e07d6867be2220a74a18404d2b9b9adb2f6b1764907aaec954f46e0b9fd18aa01504fbbb49a910d6469e64741d99ea5031c14d4721e488998ef2f594022f34e2" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xaf5624a3927117b6f1055893330bdf07a64e96041241d3731b9315b5cd6d14d7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np480", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xd8fd694b37ff2f40373350baa6cbf326e675330a7d070dedf57065b72304aece", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x452e515470ad9f96543d5a469c85e77c4f675f70a56662537491b01528898b99", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x12c0", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9", - "transactions": [ - "0xf868820181088252089450996999ff63a9a1a07da880af8f8c745a7fe72c01808718e5bb3abd109fa0f06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6aa07fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc657b0e79c166b6fdb87c67c7fe2b085f52d12c6843b7d6090e8f230d8306cda" - ] - }, - { - "jsonrpc": "2.0", - "id": "np481", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xee3a60bb251ec04e27e020f297aa6f159dad08673e76b280e67114583478aec9", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa424a562451b0728dc1451b83451fb65f9cad240a6e12ae45314a3c0fc49c4bd", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x12ca", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5", - "transactions": [], - "withdrawals": [ - { - "index": "0x50", - "validatorIndex": "0x5", - "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa0e08ceff3f3c426ab2c30881eff2c2fc1edf04b28e1fb38e622648224ffbc6b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np482", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe261b4fbd07d32f5f19564c572258acbe4be1a6b2ea03a57ccbb94e254f37cd5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x5a1ad989a90bb48e30208fafcd5131d4dec171928eb27a8ab446df6086df0f94", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e2", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x12d4", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1", - "transactions": [ - "0xf88382018208830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd10a0a085873eb64b12c743e5652beb56056bd656368a87247a72b159667d4755d7a714a0134397c5062d25029e41def2275efe8c56e466e3a1547d3525533e29641d203f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc9792da588df98731dfcbf54a6264082e791540265acc2b3ccca5cbd5c0c16de" - ] - }, - { - "jsonrpc": "2.0", - "id": "np483", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe8f039d9e217e95c5622ac64609dcaaa54abbf24376fe6c65a29d2b50060cff1", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x54928b5673094b4ce9833ecf8c1490381f0317ac2e9d51f47673e386b82ae93d", - "receiptsRoot": "0xeda5fd4b20fab5a0732205bfe235b5b212cfa5eb525752ae8b9bb0ca224262ec", - "logsBloom": "0x04000000000420002000000000000000020000000000000000000000000000000000000000000000000000100000000040000102000000000000000080000000008000000000000000000000900000000000000000000000040000000000000000000000000000000000100000100000000000001000010000000000000000010000000000000001000040000000000000000000000000000100000000000000000000000020010000000008000000000002000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000080000000400000000000010000000000000000000000000000000002020000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e3", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x12de", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91", - "transactions": [ - "0xf87a8201830883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a05c87beb281558e43744b39a1d0b62e75dfb5ea245fd2d66c657ff053fa5c45e1a077a1c629133272d7fef83436c8f67f327fc77bedea95009b3d569a5f03485b50" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc74f4bb0f324f42c06e7aeacb9446cd5ea500c3b014d5888d467610eafb69297" - ] - }, - { - "jsonrpc": "2.0", - "id": "np484", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x4b31828b7c27c371fdbc62a7b0b6807d1050d15ad53736f73c4063b391aa8b91", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf92302c8ac6987ab39ddc9a7413f552337da61d611a086900a5e47b9b3c1422f", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x12e8", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958", - "transactions": [ - "0xf865820184088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a0ef66b5859d5e5be7e02ce0b7d103b957ceba18d69047aec94746e87945b7230ba071c5785cce709e44dd94db5684b4e552e343a44862fba233c49a3fa99b0d63f9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1acd960a8e1dc68da5b1db467e80301438300e720a450ab371483252529a409b" - ] - }, - { - "jsonrpc": "2.0", - "id": "np485", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x56c5997ee01e4a2bad320a6af0120843f01908c525450d04458eca33799e7958", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x89822c6bc267d77690ae905ebc8dbe9426f9a83764224d4bc9624104881db28e", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e5", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x12f2", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef", - "transactions": [ - "0x02f86b870c72dd9d5e883e820185010882520894913f841dfc8703ae76a4e1b8b84cd67aab15f17a0180c080a0d4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8a064c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x6cef279ba63cbac953676e889e4fe1b040994f044078196a6ec4e6d868b79aa1" - ] - }, - { - "jsonrpc": "2.0", - "id": "np486", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xa5d5571bc983cefbe29844e1914f948256b70833f1e99d8dcb0282e1f9dbbfef", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xe88ebfc2a7990356801a2e5a308418fa8fe4445548fafe8227f4382f64ad8597", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e6", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x12fc", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350", - "transactions": [], - "withdrawals": [ - { - "index": "0x51", - "validatorIndex": "0x5", - "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x60eb986cb497a0642b684852f009a1da143adb3128764b772daf51f6efaae90a" - ] - }, - { - "jsonrpc": "2.0", - "id": "np487", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x686566b93e0b0c5d08d2de9e0547a5639e6878d15c59baab066c48365ce7e350", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xb852ee14e385a383f894d49c4dabd2d0704216e924283102b9b281ae5306a291", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e7", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1306", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6", - "transactions": [ - "0xf88382018608830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0ddc578e5c190613c2dc0ce34585e98c512fc9b4ae877b0b3f9b85e01a36b90b5a044c7152f99374ce61bb3b9ebb9ec9e5c4f623faa9b8972cf80f891fd45be9bbf" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xc50024557485d98123c9d0e728db4fc392091f366e1639e752dd677901681acc" - ] - }, - { - "jsonrpc": "2.0", - "id": "np488", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xc005c46cb9de70c37edd02e3ae623bb8b6e4160674fafbbd34a802f85d2725b6", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa3f2cdabc9ec81196b1930e223115ab39e3aa82a3267c2eab58dfcd4ac28879d", - "receiptsRoot": "0xa98965822a3cbebe261b9e53038a23e30a7a9ea1878b91ee19c2b9ae55907433", - "logsBloom": "0x0000000000000000000000000000000c000000000000000000000000000000000000000000002000000000800000000008000000000000000000000000000000000000000000200200000000002004000000000000000000000000000000000000000000000000000000020000040000000000080000000000004000000000000000000000000000000000000000100000000200000000000000200000000800040000000000000000000000441000000000000000000000000000000000004020400000000000000000000800000000000000002000000000040000000000000000000000000000000000000000000100000000000000400100000200000010", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e8", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1310", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d", - "transactions": [ - "0xf87a8201870883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd10a0a09d84bd49c461dee138a01ba1116ba5a0866c4d398db99b3b6e8ec5119ddaf31da046d87610c10b340e616174c09a5addfb8ef7f1b64dcadf4edd14af37ec74a55c" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xb860632e22f3e4feb0fdf969b4241442eae0ccf08f345a1cc4bb62076a92d93f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np489", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xabe558d433bc22296ae2fc7412d05672f2ec66c7940ef6a76f9bb22aa09b219d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x39ebb75595ae4b664d792fdf4b702a8a4cec3fb1fa62debd297075d3543e05af", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1e9", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x131a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db", - "transactions": [ - "0xf865820188088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a06ffd1874ec840566ae82b8a15038ee44b5241705bdb421b459c17100d1300d1aa0121f314d9f41658c831f52b82d4a13b333413d68809cea260e790de9283a434b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x21085bf2d264529bd68f206abc87ac741a2b796919eeee6292ed043e36d23edb" - ] - }, - { - "jsonrpc": "2.0", - "id": "np490", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5591e9a74a56e9765790e3088a82c8e6e39ef0d75071afe13fa51c9b130413db", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xa3d5920be7fa102b7b35c191800c65c8b8806bd7c8c04cdc0342a3d28aeafa3c", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ea", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1324", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb", - "transactions": [ - "0xf8688201890882520894b47f70b774d780c3ec5ac411f2f9198293b9df7a01808718e5bb3abd10a0a0d33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5ca0667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x80052afb1f39f11c67be59aef7fe6551a74f6b7d155a73e3d91b3a18392120a7" - ] - }, - { - "jsonrpc": "2.0", - "id": "np491", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x38cee342db6a91998dd73c4d25bca6d8730977aaa19f0a092d47c00ff10c4edb", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xf1034fb8a7585c73d7df19cae6b0581d6836278bd57d05fa19f18c6501eace46", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1eb", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x132e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f", - "transactions": [], - "withdrawals": [ - { - "index": "0x52", - "validatorIndex": "0x5", - "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xa3b0793132ed37459f24d6376ecfa8827c4b1d42afcd0a8c60f9066f230d7675" - ] - }, - { - "jsonrpc": "2.0", - "id": "np492", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x669efe3cceb25caf14b93a424eaa152070686561e028d50b8adbf87d45f4d18f", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9b830dad01831671e183f743996cc400135e0b324f1270468af08b37e83b8b17", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ec", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x1338", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92", - "transactions": [ - "0xf88382018a08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0e94663b4e19d1c2f86adde879e4cb965b7eda513a542ba26136b7010aae11681a03e7d58f3bef3bba01e70b75c70bc0d070f95bba8994c9f12705f2a5281160f47" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xe69d353f4bc38681b4be8cd5bbce5eb4e819399688b0b6225b95384b08dcc8b0" - ] - }, - { - "jsonrpc": "2.0", - "id": "np493", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x92932a0312ff65482174399e2cd29656c7051fa3747e47a906b54207c4fd1a92", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xc616c572be45daa3d7eae2481876e5d8f753631f976d4da110a6ad29bdfad30f", - "receiptsRoot": "0x78902fbbd0a8ab65f6b731f1145a5f6f467f9fdae375707236cff65e050bbfeb", - "logsBloom": "0x00000000002000000000080000000000800000000000000000800000000100000000000000000000000000000000000000000000000004000000000010000000000040000000000010000000000400000000000000000000000000080000000000020000000000000000000000000000000000000000000010000000000000000000000000008000000000000000000000000000000000400000000001000040000000000000000000000000000000000000000040000000040000000880000000008020000000800000008000000000000040020180000000000000000000400800000000000000000000000080000200000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ed", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1342", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4", - "transactions": [ - "0xf87a82018b0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0fbd0141af6d135ce0949d33ba4beba57e9b7f388c37e9725b762cb61e8db17dea05ecd43ff335efc34b06551202c4223fc39e1c842d4edfad8e46f19bc7a93f57f" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x221e784d42a121cd1d13d111128fcae99330408511609ca8b987cc6eecafefc4" - ] - }, - { - "jsonrpc": "2.0", - "id": "np494", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x52b55abe0e252ea389cc21f01782fd70ca4e4ef6031883f6b79c097de33964d4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x7e626fcfe3b1ca7a31dc26a08fbc503c7a85876a64a22a270ec99ef534566c45", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ee", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x134c", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8", - "transactions": [ - "0xf86582018c088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a05a02d5d03439ebbdf2c3b2d98305dda7adbed1ce5549c474b4b9e4f7200d4beaa016d123a1de79c4a654c1d1ab2169ee672c66922fa036e951c60fec9fe4643ee9" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xdcd669ebef3fb5bebc952ce1c87ae4033b13f37d99cf887022428d024f3a3d2e" - ] - }, - { - "jsonrpc": "2.0", - "id": "np495", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x5370ce9fa467f03411f240030b4a0b9fcbb05c5b97b09356d071ade6548767e8", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x9d90c0fd0677204966d6fdbcafcfacc7fe93a465748d2ce8afbc76b6d9b9bbe1", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1ef", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1356", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4", - "transactions": [ - "0x02f86b870c72dd9d5e883e82018d0108825208946e3d512a9328fa42c7ca1e20064071f88958ed930180c080a0990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3da05d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4dd1eb9319d86a31fd56007317e059808f7a76eead67aecc1f80597344975f46" - ] - }, - { - "jsonrpc": "2.0", - "id": "np496", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x58488c77f4726356a586e999547ffa283a73f17058064f3f56eeb02a5f67b4b4", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x32f6d8bc2270e39de3a25c3d8d7b31595eef7d3eb5122eece96edf18a7b8290f", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1f0", - "gasLimit": "0x47e7c40", - "gasUsed": "0x0", - "timestamp": "0x1360", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3", - "transactions": [], - "withdrawals": [ - { - "index": "0x53", - "validatorIndex": "0x5", - "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7", - "amount": "0x64" - } - ], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x5e1834c653d853d146db4ab6d17509579497c5f4c2f9004598bcd83172f07a5f" - ] - }, - { - "jsonrpc": "2.0", - "id": "np497", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xe521dace14e46c9d8491f262d38c1741f6fa385466a68c7ceadd08c1515600d3", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0x4e1202b318372f0cacbc989e0aa420c4280dcb8ecd7c3bb05c645bf9fb27d54e", - "receiptsRoot": "0x18ff29662320d2c1d830d59b45b908cc2e4b65c1df400d3b8492ba583a1e3342", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1f1", - "gasLimit": "0x47e7c40", - "gasUsed": "0x146ec", - "timestamp": "0x136a", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5", - "transactions": [ - "0xf88382018e08830146ec8080ae43600052600060205260405b604060002060208051600101905281526020016102408110600b57506102006040f38718e5bb3abd109fa0d9866a4e71a4efbccc717617f5c712557608513ce8b49f6e24fc06e0d717b7b6a056d3c051f6dbe09a1c94e23499ba8014f74e123caa3252068ee67e8f25e1e323" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x9f78a30e124d21168645b9196d752a63166a1cf7bbbb9342d0b8fee3363ca8de" - ] - }, - { - "jsonrpc": "2.0", - "id": "np498", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x3464afae6c8c9839a124b8dba3d363e646b61c9160a61b1c231c67a6a72daff5", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xd04a20f359c38d0cb7a31e5e7b002251c15e0242b864964ddbe9642d1c8f7e30", - "receiptsRoot": "0xe40714733f96bc282c17b688a91dfb6d070114fc7bc3f095887afa3567af588c", - "logsBloom": "0x00400000000001400400000000000000020000000000000000000000400000000000000000400000000000000000000000040100000000800000000000000000000000000000010000000000000000080000000000000000008100000000000000000000000000000000000000200000300000008000000000000010002000000000000000008000000000000000000000000000000000000000100000000000000000000000000000000004000000000000100001000000480000000000000000000000000000000000000000000000000000440000000000000000000010000000000100000000000000000000000000000000000000000000000000800000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1f2", - "gasLimit": "0x47e7c40", - "gasUsed": "0xfc65", - "timestamp": "0x1374", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d", - "transactions": [ - "0xf87a82018f0883011f588080a54360005260006020525b604060002060208051600101905260206020a15a612710106009578718e5bb3abd109fa0dd12539d461aa41247581166cecdf2eb60a75ac780929c9e6b982d9625aadc1fa06b813ce4e36c5147759f90672f6e239fab2851a63ac3b998ead89c0ead85589b" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x1f7c1081e4c48cef7d3cb5fd64b05135775f533ae4dabb934ed198c7e97e7dd8" - ] - }, - { - "jsonrpc": "2.0", - "id": "np499", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0xf7ad3df877f1a7ac6d94087db3f3e01a80264b0909e681bf9c7d21879df0df5d", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xbd38c27a1fad5fb839aad98a9c6719652d1714351f24d786b23bf23076b31ba6", - "receiptsRoot": "0x8e47c51ae3cc2e7f29232aac553163472046f2668ba19aa17733e156999a8234", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1f3", - "gasLimit": "0x47e7c40", - "gasUsed": "0x1d36e", - "timestamp": "0x137e", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39", - "transactions": [ - "0xf865820190088302088a808090435b8080556001015a6161a8106001578718e5bb3abd10a0a012969b1c46cb1b69a3fdf15b8bbccc1574572b79b38bf81803c91b0384309545a06d1c09143ad2bfeccbb04d63441058c83b60a5cbfdad87db36421dfcf008cd16" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0x4d40a7ec354a68cf405cc57404d76de768ad71446e8951da553c91b06c7c2d51" - ] - }, - { - "jsonrpc": "2.0", - "id": "np500", - "method": "engine_newPayloadV3", - "params": [ - { - "parentHash": "0x96a73007443980c5e0985dfbb45279aa496dadea16918ad42c65c0bf8122ec39", - "feeRecipient": "0x0000000000000000000000000000000000000000", - "stateRoot": "0xea4c1f4d9fa8664c22574c5b2f948a78c4b1a753cebc1861e7fb5b1aa21c5a94", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000", - "blockNumber": "0x1f4", - "gasLimit": "0x47e7c40", - "gasUsed": "0x5208", - "timestamp": "0x1388", - "extraData": "0x", - "baseFeePerGas": "0x7", - "blockHash": "0x36a166f0dcd160fc5e5c61c9a7c2d7f236d9175bf27f43aaa2150e291f092ef7", - "transactions": [ - "0xf868820191088252089415af6900147a8730b5ce3e1db6333f33f64ebb2c01808718e5bb3abd109fa085b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7a052e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc" - ], - "withdrawals": [], - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" - }, - [], - "0xf653da50cdff4733f13f7a5e338290e883bdf04adf3f112709728063ea965d6c" - ] - } -] \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/testdata/txinfo.json b/builder/cmd/devp2p/internal/ethtest/testdata/txinfo.json deleted file mode 100644 index 8e1d917fb..000000000 --- a/builder/cmd/devp2p/internal/ethtest/testdata/txinfo.json +++ /dev/null @@ -1,3018 +0,0 @@ -{ - "deploy-callenv": { - "contract": "0x9344b07175800259691961298ca11c824e65032d", - "block": "0x1" - }, - "deploy-callme": { - "contract": "0x17e7eedce4ac02ef114a7ed9fe6e2f33feba1667", - "block": "0x2" - }, - "randomcode": null, - "randomlogs": null, - "randomstorage": null, - "uncles": { - "11": { - "hashes": [ - "0x900edfd7e6de8a4a4ae18d2e7df829de69427e06eb9a381c3fe1e3002a750d75" - ] - }, - "16": { - "hashes": [ - "0x750eda0129037fbbcfcbfd6362a60ffbbc53a3f14ba9259cf2ac7f02da2a827c" - ] - }, - "21": { - "hashes": [ - "0x763d1a545e23079b4796461f2146cd3b24cc45ceab6e932db010bd2736e45403" - ] - }, - "26": { - "hashes": [ - "0x98180f6103a7e303444de4e152e81539ad614d0cd755e0e655715ab676d11e32" - ] - }, - "31": { - "hashes": [ - "0x04a8c9b6d23b2ada25bff618036c08bf6428fb35b89bce694607fac697f470e3" - ] - }, - "36": { - "hashes": [ - "0x9225da0395e14243f1e626b330ea8fe6afde356e50e8448936a29e1c203d661d" - ] - }, - "41": { - "hashes": [ - "0x74a80b9b13a264aff16e9156de67474c916de966327e9e1666fc2027e1bf63ad" - ] - }, - "46": { - "hashes": [ - "0xcf2bddf3649c7af6e9c8592aa5fad693f39f46369749e1c7127848d4ae9ff1ec" - ] - }, - "51": { - "hashes": [ - "0xeb31c29a94de8cf2fc3d0b80023b716fb5d31cc24d695d606eef2389705ade45" - ] - }, - "56": { - "hashes": [ - "0xb3a6af7632306e2dbd56b3bbf0e77d7b5c199053f348c74ce938afae615cd4fe" - ] - }, - "6": { - "hashes": [ - "0x97186bc5df663e72934212ab5a7b4449f07f12f44b267e119817791fe0ed66c5" - ] - }, - "61": { - "hashes": [ - "0x3a2cf075f456fcf264293a32d41f72506ad8cf9697d6b6d8ab3d8258cdaa90bd" - ] - }, - "66": { - "hashes": [ - "0x94d338db2e75740d17df19b0d8a111d5d68b2dfa38819b88929190b4b08b5993" - ] - }, - "71": { - "hashes": [ - "0xe9938f6ac90bc4dfdea315ed630b03ad9392b264d362ee1e1b2703fb3db5047a" - ] - } - }, - "valuetransfer": [ - { - "block": "0x7", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "nonce": "0x5", - "to": "0xca358758f6d27e6cf45272937977a748fd88391d", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x1c", - "r": "0x7252efaed5a8dbefd451c8e39a3940dc5c6a1e81899e0252e892af3060fd90ed", - "s": "0x30b6bd9550c9685a1175cece7f680732ac7d3d5445160f8d9309ec1ddba414be", - "hash": "0xd04f2bb15db6c40aaf1dcb5babc47914b5f6033b2925cb9daa3c0e0dab493fcb" - } - }, - { - "block": "0xc", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x9", - "to": "0xef6cbd2161eaea7943ce8693b9824d23d1793ffb", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x1160803ff1253dead1d84d68a06cb92fcbb265ddb0edb9a5200b28b8c834ce6b", - "s": "0x4f1f42c91a7b177f696fc1890de6936097c205f9dcd1d17a4a83ac4d93d84d9c", - "hash": "0x778450f223b07f789e343c18207a3388c01070c2f6a89506f2db4c656bc1a37f" - } - }, - { - "block": "0x11", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xd", - "to": "0x4a64a107f0cb32536e5bce6c98c393db21cca7f4", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xea20f9d952a58697ffb40cefcab9627f552c9658b3181498fd706418f89a3360", - "s": "0x4988596c88fe69f7d032df8e6f515a618a2c2e30f330febb3b548eb4fc1e8ca2", - "hash": "0xc2cffc70d847fbe50a53d618de21a24629b97e8dd4c1bcbf73979b2a48ee16df" - } - }, - { - "block": "0x16", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x11", - "to": "0x7cb7c4547cf2653590d7a9ace60cc623d25148ad", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x5f315b1989161bf29054e9e030a05b05b3d7efb4c60e39531b96af1690913f91", - "s": "0x6f1d8de5adad6f76ed0d2b4c6885d3a5502c12dae1d124b310e8c8856bd22099", - "hash": "0xfa9cd1e12446cd8c23fc76b0ae9beba0ebdc021aa87726b6febcd5ba4a504f01" - } - }, - { - "block": "0x1b", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x15", - "to": "0x77adfc95029e73b173f60e556f915b0cd8850848", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x148500c79a2f0d59158458da4e3b2a5ace441bf314942243c9e05da3457d394e", - "s": "0x2a83c5f921ffddd3c0b2a05999f820d1d03bce9ac9810941bb286c4db4ce9939", - "hash": "0xbfeeb9406545ede112801fe48aeaf30c8e2384739e8e585f1c0e726689abc4b8" - } - }, - { - "block": "0x20", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x19", - "to": "0x36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a43", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x14346079d6d3690f923625efde8933b2ad99c2bfda9310983a21b60e3c261d3c", - "s": "0x501ae278f370f3c0283fb04f966b6c501cbee0ad4c784f4187e38fcc38a9ccbb", - "hash": "0x792614188c26e2f348ac3223813794c60de97b83a298e84f4bae51dda6de140c" - } - }, - { - "block": "0x25", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x1d", - "to": "0xbbf3f11cb5b43e700273a78d12de55e4a7eab741", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x86bc86521cc6091198253d75caf394a8e23fd4fb82b48236d29f81a95aeebec5", - "s": "0xae9de4ac4265e3f415514905d8f8c747c959771080fa031dc5fd9b7333ffc28", - "hash": "0xc44716fcd212d538b2d143ddec3003b209667bfc977e209e7da1e8bf3c5223b8" - } - }, - { - "block": "0x2a", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x21", - "to": "0x684888c0ebb17f374298b65ee2807526c066094c", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x88fa9d9bbc92e44b8edcda67ee23aca611deac4cec336b215fb72547a1d0e07e", - "s": "0x297c4d7054cb545bee5221a70454b6270e098f39f91bf25c0526aa8c0a0a441c", - "hash": "0xc97ceb5b227ade5363592a68c39dcf1788abbf67b2440934b1ae11cf4b19417c" - } - }, - { - "block": "0x2f", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x25", - "to": "0x8a5edab282632443219e051e4ade2d1d5bbc671c", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x649b4ad4dcf07bcfba3dd7afd2ce220d0ae463c1bcc891ab1fcae84eca6fcc69", - "s": "0x5c69b0ad46c90eee811e4b71ce0aed22f479c207bee813dac8cce07e5a65adae", - "hash": "0xaf340a1b347c756a11e331e771d37d9205eada520f4f0d8d27f725d7c196aed1" - } - }, - { - "block": "0x34", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x29", - "to": "0x4b227777d4dd1fc61c6f884f48641d02b4d121d3", - "gas": "0x5208", - "gasPrice": "0x1", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x7d015036540013eb6aa141a2475fa1dd88d3bee57a67beaf6ef5de8f40969601", - "s": "0x4dc750a08f793ff3105479e7919508d14abe56748698375046b995d86267b18c", - "hash": "0x07a2a98ac904bcf4c17a773426b34d2b3120af65b12f9bfd437d48c175f364eb" - } - }, - { - "block": "0x39", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x2d", - "to": "0x19581e27de7ced00ff1ce50b2047e7a567c76b1c", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x27f555e9", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xde8b08caa214d0087ffd11206d485cb5cde6a6b6a76b390f53d94a8c16691593", - "s": "0x14dfe16ec3e37b8c6d3257deaf987b70b0776b97e4213c1f912c367e7d558370", - "yParity": "0x1", - "hash": "0xa883c918fb6e392a2448ef21051482bfcbeb5d26b7ebfad2a010a40e188cb43b" - } - }, - { - "block": "0x3e", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x31", - "to": "0x62b67e1f685b7fef51102005dddd27774be3fee3", - "gas": "0x5208", - "gasPrice": "0x14847701", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x6797c616a0fe0fad65b6020fc658541fd25577a3f0e7de47a65690ab81c7a34b", - "s": "0x115e6d138f23c97d35422f53aa98d666877d513dbe5d4d8c4654500ead1f4f8f", - "hash": "0xb2203865a1a1eace5b82c5154f369d86de851d8c5cd6a19e187f437a1ae28e94" - } - }, - { - "block": "0x43", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x35", - "to": "0x6b23c0d5f35d1b11f9b683f0b0a617355deb1127", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0xa88fcba", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0xdc3f3d86de44ee4dd795ff8ab480f4f5273c8ca61edb4c7561a369c80fbbb983", - "s": "0x43a90e087a6f5ba014e17316ec63b97a5a9ada19ab78177c87cb39ded9b37b0d", - "yParity": "0x0", - "hash": "0x647d637e54f1de1216cdfd83477a067308365c837c6c317febc9d3593907c7cc" - } - }, - { - "block": "0x48", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x39", - "to": "0x44bd7ae60f478fae1061e11a7739f4b94d1daf91", - "gas": "0x5208", - "gasPrice": "0x568d2fa", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x50fc2310f542cf90b3376f54d296158f5be7ad852db200f9956e3210c0f8125c", - "s": "0x4f880fe872915a7843c37147a69758eff0a93cfaf8ce54f36502190e54b6e5c7", - "hash": "0x77050c3fb6b1212cf2f739f781b024b210177b3bcbd5b62e2b3c00f1d41764d1" - } - }, - { - "block": "0x4c", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x3d", - "to": "0x72dfcfb0c470ac255cde83fb8fe38de8a128188e", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x32ca5d0", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x116da1fc19daf120ddc2cc3fa0a834f9c176028e65d5f5d4c86834a0b4fe2a36", - "s": "0x17001c3ad456650dd1b28c12f41c94f50b4571da5b62e9f2a95dff4c8c3f61fd", - "yParity": "0x0", - "hash": "0x3e4639389b6a41ff157523860ffc77eb3e66a31aee867eb4148dcc5ee8b3c66f" - } - }, - { - "block": "0x50", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x41", - "to": "0x5c62e091b8c0565f1bafad0dad5934276143ae2c", - "gas": "0x5208", - "gasPrice": "0x1dce189", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xb82a5be85322581d1e611c5871123983563adb99e97980574d63257ab98807d5", - "s": "0xdd49901bf0b0077d71c9922c4bd8449a78e2918c6d183a6653be9aaa334148", - "hash": "0x9c9de14ea0ce069a4df1c658e70e48aa7baaf64fddd4ab31bf4cb6d5550a4691" - } - }, - { - "block": "0x55", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x45", - "to": "0xa25513c7e0f6eaa80a3337ee18081b9e2ed09e00", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0xf4dd50", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0xe8ac7cb5028b3e20e8fc1ec90520dab2be89c8f50f4a14e315f6aa2229d33ce8", - "s": "0x7c2504ac2e5b2fe4d430db81a923f6cc2d73b8fd71281d9f4e75ee9fc18759b9", - "yParity": "0x0", - "hash": "0xff5e3c25f68d57ee002b3b39229ffba0879390475a00fa67a679b707997df530" - } - }, - { - "block": "0x5a", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x49", - "to": "0xbbeebd879e1dff6918546dc0c179fdde505f2a21", - "gas": "0x5208", - "gasPrice": "0x7dbb16", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x2f0119acaae03520f87748a1a855d0ef7ac4d5d1961d8f72f42734b5316a849", - "s": "0x182ad3a9efddba6be75007e91afe800869a18a36a11feee4743dde2ab6cc54d9", - "hash": "0xd696adb31daca7c3121e65d11dc00e5d5fdb72c227c701a2925dc19a46fbd43e" - } - }, - { - "block": "0x5f", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x4d", - "to": "0xd2e2adf7177b7a8afddbc12d1634cf23ea1a7102", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x408f23", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x8556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6", - "s": "0x1cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4", - "yParity": "0x1", - "hash": "0x385b9f1ba5dbbe419dcbbbbf0840b76b941f3c216d383ec9deb9b1a323ee0cea" - } - }, - { - "block": "0x64", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x51", - "to": "0x18ac3e7343f016890c510e93f935261169d9e3f5", - "gas": "0x5208", - "gasPrice": "0x212636", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x99aba91f70df4d53679a578ed17e955f944dc96c7c449506b577ac1288dac6d4", - "s": "0x582c7577f2343dd5a7c7892e723e98122227fca8486debd9a43cd86f65d4448a", - "hash": "0xd622bf64af8b9bd305e0c86152721b0711b6d24abe3748e2a8cd3a3245f6f878" - } - }, - { - "block": "0x69", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x55", - "to": "0xde7d1b721a1e0632b7cf04edf5032c8ecffa9f9a", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x11056e", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x2a6c70afb68bff0d4e452f17042700e1ea43c10fc75e55d842344c1eb55e2e97", - "s": "0x27c64f6f48cfa60dc47bfb2063f9f742a0a4f284d6b65cb394871caca2928cde", - "yParity": "0x0", - "hash": "0x47efc21f94ef1ef4e9a7d76d9370713acdf8c2b822ad35409566b9251fb0bf5c" - } - }, - { - "block": "0x6e", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x59", - "to": "0x1b16b1df538ba12dc3f97edbb85caa7050d46c14", - "gas": "0x5208", - "gasPrice": "0x8bd6d", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xabbde17fddcc6495e854f86ae50052db04671ae3b6f502d45ba1363ae68ee62c", - "s": "0x3aa20e294b56797a930e48eda73a4b036b0d9389893806f65af26b05f303100f", - "hash": "0xcf4a0a2b8229fa2f772a90fdef00d073c821c8f56d93bce703007fc5eb528e71" - } - }, - { - "block": "0x73", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x5d", - "to": "0x043a718774c572bd8a25adbeb1bfcd5c0256ae11", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x47cdd", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x2ae4b3f6fa0e08145814f9e8da8305b9ca422e0da5508a7ae82e21f17d8c1196", - "s": "0x77a6ea7a39bbfe93f6b43a48be83fa6f9363775a5bdb956c8d36d567216ea648", - "yParity": "0x1", - "hash": "0xded7c87461fb84ffd49426b474741c2eace8982edf07af918bf8794415742384" - } - }, - { - "block": "0x78", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x61", - "to": "0x2d711642b726b04401627ca9fbac32f5c8530fb1", - "gas": "0x5208", - "gasPrice": "0x24deb", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xb4d70622cd8182ff705beb3dfa5ffa4b8c9e4b6ad5ad00a14613e28b076443f6", - "s": "0x676eb97410d3d70cfa78513f5ac156b9797abbecc7a8c69df814135947dc7d42", - "hash": "0x9e2b47fc494a2285f98c89949878e11f7c6d47d24ae95bdab2801333ea8d11a7" - } - }, - { - "block": "0x7d", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x65", - "to": "0xd10b36aa74a59bcf4a88185837f658afaf3646ef", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x12eea", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x882e961b849dc71672ce1014a55792da7aa8a43b07175d2b7452302c5b3cac2a", - "s": "0x41356d00a158aa670c1a280b28b3bc8bb9d194a159c05812fa0a545f5b4bc57b", - "yParity": "0x0", - "hash": "0x240efcc882536fad14fcd34be50b508cb4c39b39f1493b8d64682760505b6cf7" - } - }, - { - "block": "0x82", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x69", - "to": "0xa5ab782c805e8bfbe34cb65742a0471cf5a53a97", - "gas": "0x5208", - "gasPrice": "0x9b8c", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x78e180a6afd88ae67d063c032ffa7e1ee629ec053306ce2c0eb305b2fb98245e", - "s": "0x7563e1d27126c9294391a71da19044cb964fd6c093e8bc2a606b6cb5a0a604ac", - "hash": "0xa28d808cbc5ef9e82cd5023ea542fab4052895618b8627c000bb8cc8ccc2e693" - } - }, - { - "block": "0x87", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x6d", - "to": "0x4bfa260a661d68110a7a0a45264d2d43af9727de", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x4fe1", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xbb105cab879992d2769014717857e3c9f036abf31aa59aed2c2da524d938ff8", - "s": "0x3b5386a238de98973ff1a9cafa80c90cdcbdfdb4ca0e59ff2f48c925f0ea872e", - "yParity": "0x1", - "hash": "0x83adc66f82e98155384ae9ef0e5be253eba9be959a50bcb48a7a3e6df97d6996" - } - }, - { - "block": "0x8c", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x71", - "to": "0x9defb0a9e163278be0e05aa01b312ec78cfa3726", - "gas": "0x5208", - "gasPrice": "0x2907", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x4adf7509b10551a97f2cb6262c331096d354c6c8742aca384e63986006b8ac93", - "s": "0x581250d189e9e1557ccc88190cff66de404c99754b4eb3c94bb3c6ce89157281", - "hash": "0x8e285b12f0ec16977055c8bc17008411883af1b5b33883a8128e50ed3e585685" - } - }, - { - "block": "0x91", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x75", - "to": "0x7da59d0dfbe21f43e842e8afb43e12a6445bbac0", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x1513", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x6ca026ba6084e875f3ae5220bc6beb1cdb34e8415b4082a23dd2a0f7c13f81ec", - "s": "0x568da83b9f5855b786ac46fb241eee56b6165c3cc350d604e155aca72b0e0eb1", - "yParity": "0x0", - "hash": "0x41ca48c0312c6d3fc433f9fd363281dae924885f73ab7466f9e8c97d6ea3b993" - } - }, - { - "block": "0x96", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x79", - "to": "0x84873854dba02cf6a765a6277a311301b2656a7f", - "gas": "0x5208", - "gasPrice": "0xad4", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xab3202c9ba5532322b9d4eb7f4bdf19369f04c97f008cf407a2668f5353e8a1f", - "s": "0x5affa251c8d29f1741d26b42a8720c416f7832593cd3b64dff1311a337799e8f", - "hash": "0x7527f1a2c9cad727c70ca0d2117fc52dbfff87962411d0b821e7418a42abd273" - } - }, - { - "block": "0x9b", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x7d", - "to": "0x8d36bbb3d6fbf24f38ba020d9ceeef5d4562f5f2", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x592", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xf9075613b9069dab277505c54e8381b0bb91032f688a6fe036ef83f016771897", - "s": "0x4cb4fc2e695439af564635863f0855e1f40865997663d900bc2ab572e78a70a2", - "yParity": "0x1", - "hash": "0xab2e87692b96ba3083b497227a9a17671bc5eee7ff12d50b850f442a4cdcd8b5" - } - }, - { - "block": "0xa0", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x81", - "to": "0xc19a797fa1fd590cd2e5b42d1cf5f246e29b9168", - "gas": "0x5208", - "gasPrice": "0x2de", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x857754afc3330f54a3e6400f502ad4a850a968671b641e271dcb9f68aacea291", - "s": "0x7d8f3fb2f3062c39d4271535a7d02960be9cb5a0a8de0baef2211604576369bf", - "hash": "0x64f8f0ad9c6526cb33e626626a25b8660a546aefa002692e46cd4d0331cd26ed" - } - }, - { - "block": "0xa5", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x85", - "to": "0x6922e93e3827642ce4b883c756b31abf80036649", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x17b", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x89e6d36baf81743f164397205ded9e5b3c807e943610d5b9adb9cfeb71b90299", - "s": "0x3d56c57f842a92a5eb71c8f9f394fe106d993960421c711498013806957fdcaf", - "yParity": "0x0", - "hash": "0x33b886e4c1c43507a08f0da97d083aa507cf905a90c17ffe20a2a24296f2db31" - } - }, - { - "block": "0xaa", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x89", - "to": "0xbceef655b5a034911f1c3718ce056531b45ef03b", - "gas": "0x5208", - "gasPrice": "0xc5", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x626dfd18ca500eedb8b439667d9b8d965da2f2d8ffcd36a5c5b60b9a05a52d9f", - "s": "0x7271175e4b74032edeb9b678ffb5e460edb2986652e45ff9123aece5f6c66838", - "hash": "0xe92638806137815555a0ffe5cc4c2b63b29171fd6f2473736201d8c3c3dbb748" - } - }, - { - "block": "0xaf", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x8d", - "to": "0x5a6e7a4754af8e7f47fc9493040d853e7b01e39d", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x68", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x8c62285d8318f84e669d3a135f99bbfe054422c48e44c5b9ce95891f87a37122", - "s": "0x28e75a73707ee665c58ff54791b62bd43a79de1522918f4f13f00ed4bd82b71b", - "yParity": "0x1", - "hash": "0x3f9133ad0b7430b124cc4b1213bc3fa72be41a58584ca05e8d863ec728890873" - } - }, - { - "block": "0xb4", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x91", - "to": "0x27952171c7fcdf0ddc765ab4f4e1c537cb29e5e5", - "gas": "0x5208", - "gasPrice": "0x39", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x76a045602a7de6b1414bdc881a321db0ce5255e878a65513bad6ac3b7f473aa7", - "s": "0x1a33017b5bcf6e059de612293db8e62b4c4a3414a7ba057c08dd6172fb78a86c", - "hash": "0x201f5041569d4dd9e5cc533867f1864daf1a7ee1a424d703d7aa8a43b07b491d" - } - }, - { - "block": "0xb9", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x95", - "to": "0x04d6c0c946716aac894fc1653383543a91faab60", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x20", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x39c18634a9f085ba0cd63685a54ef8f5c5b648856382896c7b0812ee603cd8a", - "s": "0x5ecfde61ea3757f59f0d8f0c77df00c0e68392eea1d8b76e726cb94fb5052b8a", - "yParity": "0x0", - "hash": "0xf83394fd19018fd54a5004121bc780995f99cb47832ddb11f7c50bf507606202" - } - }, - { - "block": "0xbe", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x99", - "to": "0x478508483cbb05defd7dcdac355dadf06282a6f2", - "gas": "0x5208", - "gasPrice": "0x13", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x910304dbb7d545a9c528785d26bf9e4c06d4c84fdb1b8d38bc6ee28f3db06178", - "s": "0x2ffc39c46a66af7b3af96e1e016a62ca92fc5e7e6b9dbe631acbdc325b7230a1", - "hash": "0x586f6726554ffef84726c93123de9fb1f0194dfd55ed7ca3ceae67e27b1f4fef" - } - }, - { - "block": "0xc3", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x9d", - "to": "0xae3f4619b0413d70d3004b9131c3752153074e45", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0xc", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x7cb73f8bf18eacc2c753098683a80208ac92089492d43bc0349e3ca458765c54", - "s": "0x3bf3eb6da85497e7865d119fde3718cdac76e73109384a997000c0b153401677", - "yParity": "0x1", - "hash": "0xadfacbcb99b52f33c74cbd7c45d1f0d31efc4a3f025f9832cf28e666c79c8e4c" - } - }, - { - "block": "0xc8", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xa1", - "to": "0x7c5bd2d144fdde498406edcb9fe60ce65b0dfa5f", - "gas": "0x5208", - "gasPrice": "0x9", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x15f510b05236b83a9370eb084e66272f93b4b646e225bdef016b01b3ac406391", - "s": "0x3b4a2b683af1cb3ecae367c8a8e59c76c259ce2c5c5ffd1dc81de5066879e4b8", - "hash": "0xed00ce6bd533009ddfb39d7735f1e2c468a231cf4c5badb59d1e1234c5fe3794" - } - }, - { - "block": "0xcd", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xa5", - "to": "0x9a7b7b3a5d50781b4f4768cd7ce223168f6b449b", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x4f3e818870a240e585d8990561b00ad3538cf64a189d0f5703a9431bc8fd5f25", - "s": "0x312f64dd9ab223877e94c71d83cb3e7fe359b96250d6a3c7253238979dd2f32a", - "yParity": "0x0", - "hash": "0x883c915c1ef312df1e499ef78d09767a374706d8ec89af9c65c46acd675bf817" - } - }, - { - "block": "0xd2", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xa9", - "to": "0x85f97e04d754c81dac21f0ce857adc81170d08c6", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x547e9550b5c687a2eb89c66ea85e7cd06aa776edd3b6e3e696676e22a90382b0", - "s": "0x28cb3ab4ef2761a5b530f4e05ef50e5fc957cfbc0342f98b04aa2882eec906b2", - "hash": "0x27d83955c23134e42c9beaa88332f770d09e589354c1047870328b7a2f8612c9" - } - }, - { - "block": "0xd7", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xad", - "to": "0x414a21e525a759e3ffeb22556be6348a92d5a13e", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x47b3309af68dd86089494d30d3356a69a33aa30945e1f52a924298f3167ab66", - "s": "0xb8b7bd6670a8bbcb89555528ff5719165363988aad1905a90a26c02633f8b9", - "yParity": "0x1", - "hash": "0xb75adb0bd26a8060f67c947b699471d71a66c61f2b8c6903a776c3eca7ad731e" - } - }, - { - "block": "0xdc", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xb1", - "to": "0xfb95aa98d6e6c5827a57ec17b978d647fcc01d98", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xc71a69f756a2ef145f1fb1c9b009ff10af72ba0ee80ce59269708f917878bfb0", - "s": "0x3bfe6a6c41b3fe72e8e12c2927ee5df6d3d37bd94346a2398d4fcf80e1028dde", - "hash": "0x0301d78cc4bc0330c468026de4671377a07560c2356293c2af44334e6424361a" - } - }, - { - "block": "0xe1", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xb5", - "to": "0xf031efa58744e97a34555ca98621d4e8a52ceb5f", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x99b1b125ecb6df9a13deec5397266d4f19f7b87e067ef95a2bc8aba7b9822348", - "s": "0x56e2ee0d8be47d342fe36c22d4a9be2f26136dba3bd79fa6fe47900e93e40bf3", - "yParity": "0x1", - "hash": "0x6e07cf26de1881f062629d9efa026c55b9e8084082086e974ddeb66654cd9530" - } - }, - { - "block": "0xe6", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xb9", - "to": "0x0a3aaee7ccfb1a64f6d7bcd46657c27cb1f4569a", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xd2aa10777b7c398921921258eeecaff46668278fd6f814ea4edb06f2a1076353", - "s": "0x542ef4ed484a1403494238e418bb8d613012871710e72dde77bb1fa877f1fae3", - "hash": "0xd77aeb22fbd8f99b75c970995d226b6985f2dcac6f22d65aa5d492d66e90f53f" - } - }, - { - "block": "0xeb", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xbd", - "to": "0xf8d20e598df20877e4d826246fc31ffb4615cbc0", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xc982933a25dd67a6d0b714f50be154f841a72970b3ed52d0d12c143e6a273350", - "s": "0x7a9635960c75551def5d050beee4014e4fef2353c39d300e649c199eebc8fd5e", - "yParity": "0x1", - "hash": "0x597bc815e8b0c315e692257aabe4ecfce7055fa3659f02dd8444c7d58c9055f3" - } - }, - { - "block": "0xf0", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xc1", - "to": "0xfde502858306c235a3121e42326b53228b7ef469", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x3d79397e88a64f6c2ca58b5ec7ba305012e619331946e60d6ab7c40e84bf1a34", - "s": "0x4278773d2796a0944f6bedadea3794b7ad6a18ffd01496aabf597d4a7cf75e17", - "hash": "0xe9c1c01813ee52f2a9b8aa63e200714c7527315caf55d054890c10acc73c6cec" - } - }, - { - "block": "0xf5", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xc5", - "to": "0x27abdeddfe8503496adeb623466caa47da5f63ab", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xdeade75f98612138653ca1c81d8cc74eeda3e46ecf43c1f8fde86428a990ae25", - "s": "0x65f40f1aaf4d29268956348b7cc7fa054133ccb1522a045873cb43a9ffa25283", - "yParity": "0x1", - "hash": "0x2beff883cd58f8d155069d608dfc47f730a07f1ed361987b008c17a4b8b84a4b" - } - }, - { - "block": "0xfa", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xc9", - "to": "0xaa7225e7d5b0a2552bbb58880b3ec00c286995b8", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x968ae76ffc10f7b50ca349156119aaf1d81a8772683d1c3ed005147f4682694", - "s": "0x60f5f10a015e8685a3099140c2cc3ba0dc69026df97fb46748008c08978d162a", - "hash": "0x084d5438c574a2332976d95cfae552edb797001b5af69eacf4486538ab4bdbd2" - } - }, - { - "block": "0xff", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xcd", - "to": "0xa8100ae6aa1940d0b663bb31cd466142ebbdbd51", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x54eafef27c71a73357c888f788f1936378929e1cdb226a205644dc1e2d68f32b", - "s": "0x59af490b8ef4a4e98a282d9046655fc8818758e2af8ace2489927aaa3890fda3", - "yParity": "0x0", - "hash": "0xecce661913425dbe38e2d30e7ec20ead32185d76f516525148d2647ee94aac8e" - } - }, - { - "block": "0x104", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xd1", - "to": "0xa8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x4c1d18013fb8b0554b8aaa549ee64a5a33c98edd5e51257447b4dd3b37f2ade", - "s": "0x5e3a37e5ddec2893b3fd38c4983b356c26dab5abb8b8ba6f56ac1ab9e747268b", - "hash": "0x0d903532e3740a8fb644943befee0187e6180eb31a327afc73e042ec314c02cc" - } - }, - { - "block": "0x109", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xd5", - "to": "0xac9e61d54eb6967e212c06aab15408292f8558c4", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x898d514a1f15103335e066d0625c4ec34a69a03480d67dcb3d3fe0f4f932100a", - "s": "0x7e130fed862c1482467d112f64fb59e005068b52c291003c908b625b4993e20e", - "yParity": "0x1", - "hash": "0xdd62d8c48dd14b156b3ea74d123fe3ddd7bc7700d0f189df3761ec7a8d65d1e9" - } - }, - { - "block": "0x10e", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xd9", - "to": "0x653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xf1c5d5e335842170288da2c7c7af6856ea0b566d2b4ab4b00a19cb94144d466c", - "s": "0x2043677d1c397a96a2f8a355431a59a0d5c40fc053e9c45b6872464f3c77c5dc", - "hash": "0x284452da997f42dbe0e511078f5005514fdeda8d0905439fe2f3a5ecc3aec1ac" - } - }, - { - "block": "0x113", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xdd", - "to": "0xd8c50d6282a1ba47f0a23430d177bbfbb72e2b84", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x4330fe20e8b84e751616253b9bccc5ff2d896e00593bfbef92e81e72b4d98a85", - "s": "0x7977b87c7eca1f6a8e4a535cb26860e32487c6b4b826623a7390df521b21eac7", - "yParity": "0x1", - "hash": "0xd667f29e2cccf282a82791cb46f9181ad04c8179bc11af957c499b3627907a6f" - } - }, - { - "block": "0x118", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xe1", - "to": "0xb519be874447e0f0a38ee8ec84ecd2198a9fac77", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xcfbd9ff7eeb9aef477970dcba479f89c7573e6167d16d0882ead77b20aaee690", - "s": "0x1e34175b1b1758a581ca13f2ca021698933b1e8269c70fcb94c5e4aa39ee9b8e", - "hash": "0x935596bc447ea87dca90e3bac15f679129af2c813abe1657811f70dcafe660c2" - } - }, - { - "block": "0x11d", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xe5", - "to": "0xaf2c6f1512d1cabedeaf129e0643863c57419732", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xc23170a740ba640770aca9fb699a2799d072b2466c97f126a834d86bdb22f516", - "s": "0x3f242217b60ab672f352ae51249a8876a034ee51b6b4ad4a41b4d300c48e79f4", - "yParity": "0x1", - "hash": "0xc659a1be386492afe2ca97cbbe9d1645763b502030c17e3acf9d539e22b74093" - } - }, - { - "block": "0x122", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xe9", - "to": "0xb70654fead634e1ede4518ef34872c9d4f083a53", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x953d5aa69077225dba6a0333ea4d69a05f652e0d2abb8df492a7e6a9d0cdbe3d", - "s": "0x4e41cb847aa131b9bb1e19cb3dd5f7a6cc2ac8b7f459ab8c3061380d41721ff", - "hash": "0x6f7f93620049c80ba6429e3c2f7563f7048f725f245c22bcc6de438fd394bb7e" - } - }, - { - "block": "0x127", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xed", - "to": "0xbe3eea9a483308cb3134ce068e77b56e7c25af19", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x190737acd3a2a298d5a6f96a60ced561e536dd9d676c8494bc6d71e8b8a90b60", - "s": "0x2c407a67004643eba03f80965fea491c4a6c25d90d5a9fd53c6a61b62971e7c5", - "yParity": "0x0", - "hash": "0xe48311c620199dfc77bc280caa0a1bcbbd00457b079a7154a6f8bc229beb41f1" - } - }, - { - "block": "0x12c", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xf1", - "to": "0x08037e79bb41c0f1eda6751f0dabb5293ca2d5bf", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xe3edf14f32e7cacb36fd116b5381fac6b12325a5908dcec2b8e2c6b5517f5ec5", - "s": "0x51429c4c1e479fa018b7907e7e3b02a448e968368a5ce9e2ea807525d363f85e", - "hash": "0xa960e3583c41a164dc743eac939626f891f20f7dfdf71f204c2f84ca1087ae90" - } - }, - { - "block": "0x131", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xf5", - "to": "0xf16ba6fa61da3398815be2a6c0f7cb1351982dbc", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x8dac03d829e6f8eab08661cd070c8a58eed41467ad9e526bb3b9c939e3fd4482", - "s": "0x2ac7208f150195c44c455ddeea0bbe104b9121fef5cba865311940f4de428eec", - "yParity": "0x1", - "hash": "0xc7ccef252840e9fc1821f2c2eb0ca8c9508ff3f4c23f85322e09dd9313849694" - } - }, - { - "block": "0x136", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xf9", - "to": "0x17333b15b4a5afd16cac55a104b554fc63cc8731", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xf2179ec11444804bb595a6a2f569ea474b66e654ff8d6d162ec6ed565f83c1aa", - "s": "0x657ed11774d5d4bb0ed0eb1206d1d254735434a0c267912713099336c2dc147a", - "hash": "0x45ed5258df6ecd5ba8b99db384e39d22c193662830e79f972547d81e3857cc70" - } - }, - { - "block": "0x13b", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0xfd", - "to": "0xd20b702303d7d7c8afe50344d66a8a711bae1425", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x67bed94b25c4f3ab70b3aae5cd44c648c9807cdf086299e77cf2977b9bce8244", - "s": "0x76661b80df9b49579fce2e2201a51b08ecc4eb503d5f5517ecb20156fde7ec5a", - "yParity": "0x1", - "hash": "0xa3b085cc524be64d822be105f3bb92c05c773cb93bffc774ba9aac21f9603ce6" - } - }, - { - "block": "0x140", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x101", - "to": "0xdd1e2826c0124a6d4f7397a5a71f633928926c06", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x1f5208621cee9149c99848d808ee0fa8d57b358afbd39dc594f383b7f525f4c6", - "s": "0x1960c6254e869f06cfa3263972aa8e7cc79aec12caa728515c420d35b1336c0e", - "hash": "0x34671329e36adeee3261ea7313388804f481e6a0e2f77cce6961aed112498803" - } - }, - { - "block": "0x145", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x105", - "to": "0x1219c38638722b91f3a909f930d3acc16e309804", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x63adb9abb5014935b3dbf8c31059d6f1d9e12068a3f13bd3465db2b5a7f27f98", - "s": "0x56f0f5bed39985d0921989b132e9638472405a2b1ba757e22df3276ca9b527fa", - "yParity": "0x1", - "hash": "0x7bfa3e961b16291e9ee2f4dc0b6489bb0b12ff7a6ed6491c100dd1041472ff9e" - } - }, - { - "block": "0x14a", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x109", - "to": "0x1f5746736c7741ae3e8fa0c6e947cade81559a86", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xedd3402a6c7a96114e4c8520d7bf3f06c00d9f24ee08de4c8afdbf05b4487b7d", - "s": "0x68cd4cf2242a8df916b3594055ee05551b77021bbea9b9eb9740f9a8e6466d80", - "hash": "0x90ea391ff615d345ad4e35e53af26e283fc2fd9ecb3221a9610fb2a376c38caf" - } - }, - { - "block": "0x14f", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x10d", - "to": "0x9ae62b6d840756c238b5ce936b910bb99d565047", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x25cc19f12be3ff2a51342412dc152953e8e8b61c9c3858c9d476cc214be4e30", - "s": "0x193960b0d01b790ef99b9a39b7475d18e83499f1635fc0a3868fc67c4da5b2c3", - "yParity": "0x0", - "hash": "0xa1ea0831d6727a0e7316822d3cc3815f1e2ba71e124fcd8b886610d5d42fd5ff" - } - }, - { - "block": "0x154", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x111", - "to": "0xb55a3d332d267493105927b892545d2cd4c83bd6", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x73cc84153b8891468325ac12743faf7e373b78dbf8b9f856cb2622c7b4fd10e1", - "s": "0x388714fe9d2f85a88b962e213cbe1fa3c4a9823cea051cf91c607ecbd90093d8", - "hash": "0xd30ff6e59e0e1278dab8083cb01e1e66900adc72cc4263cbdffc98e08a728b89" - } - }, - { - "block": "0x159", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x115", - "to": "0xb68176634dde4d9402ecb148265db047d17cb4ab", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x9f3175e9aa2fe2332600b71de0b0977c7c60ccbeee66ea360226326817f2d59b", - "s": "0x6a870e0876002f789b3203f4a33d5e621ac67051704e1f2260b80d816260b3e6", - "yParity": "0x0", - "hash": "0x5565d4f07ad007f4bfe27837904f2ce365cff6c036aa5169df651f217944b1f4" - } - }, - { - "block": "0x15e", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x119", - "to": "0xdfe052578c96df94fa617102199e66110181ed2c", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x20ee6a1ada31c18eac485e0281a56fc6d8c4152213d0629e6d8dd325adb60b1", - "s": "0xf72e01c463b98817219db62e689416c510866450efc878a6035e9346a70795f", - "hash": "0x9055a34f1c764ce297f1bce6c94680a0e8d532debeb6af642c956122f4c7d079" - } - }, - { - "block": "0x163", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x11d", - "to": "0x33fc6e8ad066231eb5527d1a39214c1eb390985d", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x167190e2e0fed95ab5c7265a53f25a92d659e1d46eb9ecbac193e7151b82ec1c", - "s": "0x269353e9c5ef331135563e2983279669220687652e7f231725303ccf7d2a8ebd", - "yParity": "0x1", - "hash": "0x0aa77f1fa0e9ab541616fb3104788109f84010d4b410508e5779f052ee49c5b9" - } - }, - { - "block": "0x168", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x121", - "to": "0x662fb906c0fb671022f9914d6bba12250ea6adfb", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xd3a858be3712102b61ec73c8317d1e557043f308869f4a04e3a4578e2d9aa7e7", - "s": "0x202a5f044cc84da719ec69b7985345b2ef82cf6b0357976e99e46b38c77fe613", - "hash": "0x01bdc2fb7f53293c98e430dc42b1ef18773493f0f1bd03460eb45e438168048d" - } - }, - { - "block": "0x16d", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x125", - "to": "0xf1fc98c0060f0d12ae263986be65770e2ae42eae", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x6563737b6bfddfb8bc5ec084651a8e51e3b95fe6ed4361065c988acaf764f210", - "s": "0xa96a1747559028cd02304adb52867678419ebef0f66012733fea03ee4eae43b", - "yParity": "0x0", - "hash": "0x36cf0f21e046b484333889a22e4880ad05807f2922340e6e822591cfa5138815" - } - }, - { - "block": "0x172", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x129", - "to": "0xa92bb60b61e305ddd888015189d6591b0eab0233", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x626bd8978288bcf1d7719926fba91597d6aa8ead945c89044693d780523a05dd", - "s": "0x74494ccf5362aa73db798940296b77b80a7ec6037f5ed2c946094b9df8a2347", - "hash": "0x8cb5e311a3e79a31c06afaecbbf9c814759f039f55b06ead4e8a1c2933766c8c" - } - }, - { - "block": "0x177", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x12d", - "to": "0x469542b3ece7ae501372a11c673d7627294a85ca", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x9add65921c40226ee4a686b9fa70c7582eba8c033ccc9c27775c6bc33c9232fb", - "s": "0x21a6e73ccb2f16e540594b4acbba2c852a3e853742359fcbc772880879fe1197", - "yParity": "0x0", - "hash": "0x55c8ee8da8d54305ca22c9d7b4226539a60741ed599327d33013f8d0385c61bd" - } - }, - { - "block": "0x17c", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x131", - "to": "0x7f2dce06acdeea2633ff324e5cb502ee2a42d979", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xfd195ea41804b21ffffdbca38fd49a9874371e51e81642917d001d201a943e24", - "s": "0x542bca46a2dc92fddb9abffcf2b3e78dc491d6e95040692e6d1446a6b487a42a", - "hash": "0x3964c50008f0dce6974ef2c088a84207191eb56ab4ac86cbf5d149a661ecb479" - } - }, - { - "block": "0x181", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x135", - "to": "0x3bcc2d6d48ffeade5ac5af3ee7acd7875082e50a", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x3931e5e7d02ed045834da39a409083c260fbc96dc256c1d927f1704147eeaeb6", - "s": "0x215269010bb3e7dd8f03d71db3e617985b447c2e0dd6fc0939c125db43039d0f", - "yParity": "0x0", - "hash": "0x23583194a4443b0144115327770bf71f645283515ca26fc775dd23244a876e83" - } - }, - { - "block": "0x186", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x139", - "to": "0xf83af0ceb5f72a5725ffb7e5a6963647be7d8847", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xa38cf9766454bd02d4f06f5bd214f5fe9e53b7a299eda5c7523060704fcdb751", - "s": "0x67c33351f6f7bbd9de5b5435f6cadc10ba5e94f3cbcc40ee53496c782f99d71f", - "hash": "0x41019c72018f2f499368e96aed89293b24873f611018c3787eeb81a0a01b667b" - } - }, - { - "block": "0x18b", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x13d", - "to": "0x469dacecdef1d68cb354c4a5c015df7cb6d655bf", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x6faf4090490862eba3c27dfe0a030a442ccc89d4478eca3ed09039386554f07b", - "s": "0x656f741b64c54808ac5a6956540d3f7aaec811bf4efa7239a0ca0c7fb410b4d6", - "yParity": "0x1", - "hash": "0x054500013715ec41cb39492f2856925c7f22f80fd22365f19de8124b14e77e90" - } - }, - { - "block": "0x190", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x141", - "to": "0xf14d90dc2815f1fc7536fc66ca8f73562feeedd1", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x4a18131d30b0344910cae7c41ee5c1c23171c40292d34e9a82c9c7cef3d3836a", - "s": "0x598a3835ad1903c3d7ad158c57ff0db10e12d8acbef318ddd0514f671a08ce94", - "hash": "0x1b562d975247f54df92dc775c61ef8fb004714fd57d0c804dd64e44be2f10cb5" - } - }, - { - "block": "0x195", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x145", - "to": "0x360671abc40afd33ae0091e87e589fc320bf9e3d", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x9b0a44741dc7e6cb0f88199ca38f15034fab4164d9055788834e8123b7264c87", - "s": "0x2c38a3ecda52aebc3725c65ee1cd0461a8d706ddfc9ed27d156cf50b61ef5069", - "yParity": "0x0", - "hash": "0x3e3bec1253082bf314cb1155ef241912bc842b8ced86b70e5e3b24585a130d66" - } - }, - { - "block": "0x19a", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x149", - "to": "0x579ab019e6b461188300c7fb202448d34669e5ff", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xde600e017080351550412ac87f184ec2c3f672e08f1c362ab58b94631e8864dc", - "s": "0x47d41b8691a1f7f8818e59ad473451a0edfc88826a6b808f84f56baed90d5634", - "hash": "0x519fbf530d16289510ebb27b099ad16ad03e72227497db7a62e6c0e89d3a708a" - } - }, - { - "block": "0x19f", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x14d", - "to": "0x88654f0e7be1751967bba901ed70257a3cb79940", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xa79b0ff9846673061d1b90a17cd8bd9e7c7f62b99b39fbe4749777d3ed4544e0", - "s": "0x750ecfe9895402861ebea87e9b483b2c116bc2d4920329aa1c29efb9dcdf47e6", - "yParity": "0x1", - "hash": "0x6364bf260fee1aea143ec4a4c596d64e15252f8fa4c7ab7ae69d51ff4cbd343b" - } - }, - { - "block": "0x1a4", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x151", - "to": "0x47e642c9a2f80499964cfda089e0b1f52ed0f57d", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xc37c23a91d6abced211855a2d6d5e383f54aa6ff40c26abc5f27a22cdafa5618", - "s": "0x190f82ff101eabad8b9c7041006dcb3e3a9a85c814938bef8ec7d1aa63fa5892", - "hash": "0x2ee70986d957daba62588ac40c9bf75f6707a34dc5ef5897ae7cd3998f2e05bc" - } - }, - { - "block": "0x1a9", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x155", - "to": "0xd854d6dd2b74dc45c9b883677584c3ac7854e01a", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x7a17de801de3309b57dd86df30b61553d5c04071581d243f33f43c4d64930e09", - "s": "0x75f7e820212e8f96d7583c66548719db621537fe20f7568d5ee62176881b70e8", - "yParity": "0x0", - "hash": "0xbaf8e87ba94a0d70e37443c4475b2525806827b3ae964b30eb4dad7936b2eb6e" - } - }, - { - "block": "0x1ae", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x159", - "to": "0xc305dd6cfc073cfe5e194fc817536c419410a27d", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x163f29bc7be2e8fe3c6347fe4de06fa7330e3a3049c0e9dcded1795ff1c1e810", - "s": "0x4ea7492a5e457fd21252166f5a5d5d9d5e5c7a19da2c7fd4a822bf60156b91a9", - "hash": "0x4a84eeb0addd194ae92631aa43ed4f4fece16258bcbbc91de6324e20bde0f914" - } - }, - { - "block": "0x1b3", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x15d", - "to": "0x2143e52a9d8ad4c55c8fdda755f4889e3e3e7721", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0x673c5473955d0d26d49b25b82af905ee33ba365178f44dc4ac39221efec23c88", - "s": "0x17f46fc9b15ba0c1ea78d4d9f773582d94f61f6471f2918cb0598f33eb9bc89b", - "yParity": "0x1", - "hash": "0x01b1e85401ca88bc02c33956d0bfeea9ec0b6c916f1478d4eae39818e999cb74" - } - }, - { - "block": "0x1b8", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x161", - "to": "0x0fe037febcc3adf9185b4e2ad4ea43c125f05049", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x654dc39f93a879b9aec58ace2fdbd5c47e383cae2d14f1a49f6ec93d539be892", - "s": "0x70505a0ef2e83f057e9844dbd56eda0949197f0c4a2b6d0f2979db1710fca4ed", - "hash": "0xf8c7948d4418ad9948d7352c6c21dcb5b7f72664dfcfe553dfc444df7afc9c0b" - } - }, - { - "block": "0x1bd", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x165", - "to": "0x046dc70a4eba21473beb6d9460d880b8cfd66613", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x9a954eff1b0e590a3a78b724b687c6ab944181990998780d56cc3593c704996e", - "s": "0x418db96b5dc1057f6acb018244f82ed6ece03d88c07f6ae767eaebe3b7ac9387", - "yParity": "0x0", - "hash": "0xf09a7e0da3b14049923d019fb5d457531ddaa4456cf84124a17479b0bfd6261b" - } - }, - { - "block": "0x1c2", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x169", - "to": "0x104eb07eb9517a895828ab01a3595d3b94c766d5", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0x597dbb3f69603be721ae0f2a63eeee9f008829ff273b54243673f9ea192ddc0a", - "s": "0x1f7dd04defb45af840d46a950b8bede0b3ce8a718004c1ca2f3bbd4efcbd7563", - "hash": "0x00c458459a2d2f501907a6a4122fba7ae70fb3ef632676e492912231022f80c8" - } - }, - { - "block": "0x1c7", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x16d", - "to": "0x46b61db0aac95a332cecadad86e52531e578cf1f", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x774ced5c8674413b351ae8ac3b96705d1d3db10deae39134572be985f16c008b", - "s": "0x6f3e4b250f84fcf95ae85946da8a1c79f922a211dbe516fcfcff0180911429b8", - "yParity": "0x0", - "hash": "0x6603c100a34224ddb8aaeb9e234f0c611d40a5df807de68803b71e0ff0f3aea8" - } - }, - { - "block": "0x1cc", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x171", - "to": "0x8a817bc42b2e2146dc4ca4dc686db0a4051d2944", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xa755d1c641b8965ea140ad348135496fc412ffa43a72bbd2c7c0e26b814a75f1", - "s": "0x67d81cca370b6ea40ccd2ad3662d16fa36bd380845bee04c55c6531455d0687d", - "hash": "0x46e00cb4ede9be515c8910a31881df229ebb2804722ad9d6723e1101a87f1889" - } - }, - { - "block": "0x1d1", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x175", - "to": "0x23e6931c964e77b02506b08ebf115bad0e1eca66", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x6263b1d5b9028231af73bfa386be8fc770e11f60137428378137c34f12c2c242", - "s": "0x2b340f5b45217d9b914921a191ce5f7ba67af038e3b3c2c72aaca471412b02f7", - "yParity": "0x0", - "hash": "0xa5b751caaaff89a472fb427c17ac7637b4a9de7cda34beaaf891516278655479" - } - }, - { - "block": "0x1d6", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x179", - "to": "0x878dedd9474cfa24d91bccc8b771e180cf01ac40", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x515a62775619f55c366d080a7c397ea42dcfd2fdcce1862ef98dab875077f367", - "s": "0x23756d4f3bd644dde1c25f8cde45fbea557dacf0492bbecb409f6b2cdacbb9b8", - "hash": "0x2e232fb6d73423c9dcaff38257d36fcad74a2c627a70030b43a0bed36d136625" - } - }, - { - "block": "0x1db", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x17d", - "to": "0x45dcb3e20af2d8ba583d774404ee8fedcd97672b", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x1", - "r": "0xd3b69c226bf73db84babb6185a83b0dd491467adfc01d279df4c09d5d2d3fba4", - "s": "0x368ddb772caa32963df97961cf8ef0db33e0df5945000f0e39d9a288bd73ee30", - "yParity": "0x1", - "hash": "0xc80615944f9bfeb945b7416052667eec0a78b2f3beb7c2811ebb9e9210e45c4c" - } - }, - { - "block": "0x1e0", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x181", - "to": "0x50996999ff63a9a1a07da880af8f8c745a7fe72c", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0xf06ad492cdd04b44f321abe9cb98e5977f03909173e4b6361f50d44c080f9d6a", - "s": "0x7fdc23c04fab8e0a576e6896b13a661b2dcb256cf8ca42fa21f0f370097a53a4", - "hash": "0x8c1f1466ce25a97e88ab37bc9b5362eaf95fb523fb80d176429fa41c2fa2d629" - } - }, - { - "block": "0x1e5", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x185", - "to": "0x913f841dfc8703ae76a4e1b8b84cd67aab15f17a", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0xd4b8d15fc05f29b58f0459b336dc48b142e8d14572edad06e346aa7728491ce8", - "s": "0x64c8078691ba1c4bb110f6dff74e26d3c0df2505940558746a1c617091ddc61a", - "yParity": "0x0", - "hash": "0x969e178ea1a76626b96bf06e207edb6299c36c6a14e46462960832feb93f6d42" - } - }, - { - "block": "0x1ea", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x189", - "to": "0xb47f70b774d780c3ec5ac411f2f9198293b9df7a", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd10a0", - "r": "0xd33c0cd7f521603ea8deaa363ab591627f5af193759f0aeb8cd9fe4f22a4dd5c", - "s": "0x667bb0ee041403cba2e562882bb9afc43bd560af3c95136c7bf4f1e361355316", - "hash": "0xa35c19e4e8154c35656544b92e88fb62c4210e38f09608248e2a99841ac99964" - } - }, - { - "block": "0x1ef", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x2", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x18d", - "to": "0x6e3d512a9328fa42c7ca1e20064071f88958ed93", - "gas": "0x5208", - "gasPrice": null, - "maxPriorityFeePerGas": "0x1", - "maxFeePerGas": "0x8", - "value": "0x1", - "input": "0x", - "accessList": [], - "v": "0x0", - "r": "0x990aa3c805c666109799583317176d55a73d96137ff886be719a36537d577e3d", - "s": "0x5d1244d8c33e85b49e2061112549e616b166a1860b07f00ff963a0b37c29bcaa", - "yParity": "0x0", - "hash": "0xeb282a48d309db881eead661ee7c64696b2699fa7c431d39a573ecaa0bc31052" - } - }, - { - "block": "0x1f4", - "sender": "0x7435ed30a8b4aeb0877cef0c6e8cffe834eb865f", - "tx": { - "type": "0x0", - "chainId": "0xc72dd9d5e883e", - "nonce": "0x191", - "to": "0x15af6900147a8730b5ce3e1db6333f33f64ebb2c", - "gas": "0x5208", - "gasPrice": "0x8", - "maxPriorityFeePerGas": null, - "maxFeePerGas": null, - "value": "0x1", - "input": "0x", - "v": "0x18e5bb3abd109f", - "r": "0x85b3c275e830c2034a4666e3a57c8640a8e5e7b7c8d0687467e205c037b4c5d7", - "s": "0x52e2aa8b60be142eee26f197b1e0a983f8df844c770881d820dfc4d1bb3d9adc", - "hash": "0x22e616c85493bcd23147d1c9f5dd081b32daf5c7b3e824f61b5fc1bd34a47e67" - } - } - ], - "withdrawals": { - "101": { - "withdrawals": [ - { - "index": "0x4", - "validatorIndex": "0x5", - "address": "0x3f79bb7b435b05321651daefd374cdc681dc06fa", - "amount": "0x64" - } - ] - }, - "106": { - "withdrawals": [ - { - "index": "0x5", - "validatorIndex": "0x5", - "address": "0x189f40034be7a199f1fa9891668ee3ab6049f82d", - "amount": "0x64" - } - ] - }, - "111": { - "withdrawals": [ - { - "index": "0x6", - "validatorIndex": "0x5", - "address": "0x65c74c15a686187bb6bbf9958f494fc6b8006803", - "amount": "0x64" - } - ] - }, - "116": { - "withdrawals": [ - { - "index": "0x7", - "validatorIndex": "0x5", - "address": "0xe3b98a4da31a127d4bde6e43033f66ba274cab0e", - "amount": "0x64" - } - ] - }, - "121": { - "withdrawals": [ - { - "index": "0x8", - "validatorIndex": "0x5", - "address": "0xa1fce4363854ff888cff4b8e7875d600c2682390", - "amount": "0x64" - } - ] - }, - "126": { - "withdrawals": [ - { - "index": "0x9", - "validatorIndex": "0x5", - "address": "0x7ace431cb61584cb9b8dc7ec08cf38ac0a2d6496", - "amount": "0x64" - } - ] - }, - "131": { - "withdrawals": [ - { - "index": "0xa", - "validatorIndex": "0x5", - "address": "0x5ee0dd4d4840229fab4a86438efbcaf1b9571af9", - "amount": "0x64" - } - ] - }, - "136": { - "withdrawals": [ - { - "index": "0xb", - "validatorIndex": "0x5", - "address": "0x4f362f9093bb8e7012f466224ff1237c0746d8c8", - "amount": "0x64" - } - ] - }, - "141": { - "withdrawals": [ - { - "index": "0xc", - "validatorIndex": "0x5", - "address": "0x075198bfe61765d35f990debe90959d438a943ce", - "amount": "0x64" - } - ] - }, - "146": { - "withdrawals": [ - { - "index": "0xd", - "validatorIndex": "0x5", - "address": "0x956062137518b270d730d4753000896de17c100a", - "amount": "0x64" - } - ] - }, - "151": { - "withdrawals": [ - { - "index": "0xe", - "validatorIndex": "0x5", - "address": "0x2a0ab732b4e9d85ef7dc25303b64ab527c25a4d7", - "amount": "0x64" - } - ] - }, - "156": { - "withdrawals": [ - { - "index": "0xf", - "validatorIndex": "0x5", - "address": "0x6e3faf1e27d45fca70234ae8f6f0a734622cff8a", - "amount": "0x64" - } - ] - }, - "161": { - "withdrawals": [ - { - "index": "0x10", - "validatorIndex": "0x5", - "address": "0x8a8950f7623663222542c9469c73be3c4c81bbdf", - "amount": "0x64" - } - ] - }, - "166": { - "withdrawals": [ - { - "index": "0x11", - "validatorIndex": "0x5", - "address": "0xfe1dcd3abfcd6b1655a026e60a05d03a7f71e4b6", - "amount": "0x64" - } - ] - }, - "171": { - "withdrawals": [ - { - "index": "0x12", - "validatorIndex": "0x5", - "address": "0x087d80f7f182dd44f184aa86ca34488853ebcc04", - "amount": "0x64" - } - ] - }, - "176": { - "withdrawals": [ - { - "index": "0x13", - "validatorIndex": "0x5", - "address": "0xf4f97c88c409dcf3789b5b518da3f7d266c48806", - "amount": "0x64" - } - ] - }, - "181": { - "withdrawals": [ - { - "index": "0x14", - "validatorIndex": "0x5", - "address": "0x892f60b39450a0e770f00a836761c8e964fd7467", - "amount": "0x64" - } - ] - }, - "186": { - "withdrawals": [ - { - "index": "0x15", - "validatorIndex": "0x5", - "address": "0x281c93990bac2c69cf372c9a3b66c406c86cca82", - "amount": "0x64" - } - ] - }, - "191": { - "withdrawals": [ - { - "index": "0x16", - "validatorIndex": "0x5", - "address": "0xb12dc850a3b0a3b79fc2255e175241ce20489fe4", - "amount": "0x64" - } - ] - }, - "196": { - "withdrawals": [ - { - "index": "0x17", - "validatorIndex": "0x5", - "address": "0xd1211001882d2ce16a8553e449b6c8b7f71e6183", - "amount": "0x64" - } - ] - }, - "201": { - "withdrawals": [ - { - "index": "0x18", - "validatorIndex": "0x5", - "address": "0x4fb733bedb74fec8d65bedf056b935189a289e92", - "amount": "0x64" - } - ] - }, - "206": { - "withdrawals": [ - { - "index": "0x19", - "validatorIndex": "0x5", - "address": "0xc337ded6f56c07205fb7b391654d7d463c9e0c72", - "amount": "0x64" - } - ] - }, - "211": { - "withdrawals": [ - { - "index": "0x1a", - "validatorIndex": "0x5", - "address": "0x28969cdfa74a12c82f3bad960b0b000aca2ac329", - "amount": "0x64" - } - ] - }, - "216": { - "withdrawals": [ - { - "index": "0x1b", - "validatorIndex": "0x5", - "address": "0xaf193a8cdcd0e3fb39e71147e59efa5cad40763d", - "amount": "0x64" - } - ] - }, - "221": { - "withdrawals": [ - { - "index": "0x1c", - "validatorIndex": "0x5", - "address": "0x2795044ce0f83f718bc79c5f2add1e52521978df", - "amount": "0x64" - } - ] - }, - "226": { - "withdrawals": [ - { - "index": "0x1d", - "validatorIndex": "0x5", - "address": "0x30a5bfa58e128af9e5a4955725d8ad26d4d574a5", - "amount": "0x64" - } - ] - }, - "231": { - "withdrawals": [ - { - "index": "0x1e", - "validatorIndex": "0x5", - "address": "0xd0752b60adb148ca0b3b4d2591874e2dabd34637", - "amount": "0x64" - } - ] - }, - "236": { - "withdrawals": [ - { - "index": "0x1f", - "validatorIndex": "0x5", - "address": "0x45f83d17e10b34fca01eb8f4454dac34a777d940", - "amount": "0x64" - } - ] - }, - "241": { - "withdrawals": [ - { - "index": "0x20", - "validatorIndex": "0x5", - "address": "0xd4f09e5c5af99a24c7e304ca7997d26cb0090169", - "amount": "0x64" - } - ] - }, - "246": { - "withdrawals": [ - { - "index": "0x21", - "validatorIndex": "0x5", - "address": "0xb0b2988b6bbe724bacda5e9e524736de0bc7dae4", - "amount": "0x64" - } - ] - }, - "251": { - "withdrawals": [ - { - "index": "0x22", - "validatorIndex": "0x5", - "address": "0x04b8d34e20e604cadb04b9db8f6778c35f45a2d2", - "amount": "0x64" - } - ] - }, - "256": { - "withdrawals": [ - { - "index": "0x23", - "validatorIndex": "0x5", - "address": "0x47dc540c94ceb704a23875c11273e16bb0b8a87a", - "amount": "0x64" - } - ] - }, - "261": { - "withdrawals": [ - { - "index": "0x24", - "validatorIndex": "0x5", - "address": "0xbc5959f43bc6e47175374b6716e53c9a7d72c594", - "amount": "0x64" - } - ] - }, - "266": { - "withdrawals": [ - { - "index": "0x25", - "validatorIndex": "0x5", - "address": "0xc04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b", - "amount": "0x64" - } - ] - }, - "271": { - "withdrawals": [ - { - "index": "0x26", - "validatorIndex": "0x5", - "address": "0x24255ef5d941493b9978f3aabb0ed07d084ade19", - "amount": "0x64" - } - ] - }, - "276": { - "withdrawals": [ - { - "index": "0x27", - "validatorIndex": "0x5", - "address": "0xdbe726e81a7221a385e007ef9e834a975a4b528c", - "amount": "0x64" - } - ] - }, - "281": { - "withdrawals": [ - { - "index": "0x28", - "validatorIndex": "0x5", - "address": "0xae58b7e08e266680e93e46639a2a7e89fde78a6f", - "amount": "0x64" - } - ] - }, - "286": { - "withdrawals": [ - { - "index": "0x29", - "validatorIndex": "0x5", - "address": "0x5df7504bc193ee4c3deadede1459eccca172e87c", - "amount": "0x64" - } - ] - }, - "291": { - "withdrawals": [ - { - "index": "0x2a", - "validatorIndex": "0x5", - "address": "0xb71de80778f2783383f5d5a3028af84eab2f18a4", - "amount": "0x64" - } - ] - }, - "296": { - "withdrawals": [ - { - "index": "0x2b", - "validatorIndex": "0x5", - "address": "0x1c972398125398a3665f212930758ae9518a8c94", - "amount": "0x64" - } - ] - }, - "301": { - "withdrawals": [ - { - "index": "0x2c", - "validatorIndex": "0x5", - "address": "0x1c123d5c0d6c5a22ef480dce944631369fc6ce28", - "amount": "0x64" - } - ] - }, - "306": { - "withdrawals": [ - { - "index": "0x2d", - "validatorIndex": "0x5", - "address": "0x7f774bb46e7e342a2d9d0514b27cee622012f741", - "amount": "0x64" - } - ] - }, - "311": { - "withdrawals": [ - { - "index": "0x2e", - "validatorIndex": "0x5", - "address": "0x06f647b157b8557a12979ba04cf5ba222b9747cf", - "amount": "0x64" - } - ] - }, - "316": { - "withdrawals": [ - { - "index": "0x2f", - "validatorIndex": "0x5", - "address": "0xcccc369c5141675a9e9b1925164f30cdd60992dc", - "amount": "0x64" - } - ] - }, - "321": { - "withdrawals": [ - { - "index": "0x30", - "validatorIndex": "0x5", - "address": "0xacfa6b0e008d0208f16026b4d17a4c070e8f9f8d", - "amount": "0x64" - } - ] - }, - "326": { - "withdrawals": [ - { - "index": "0x31", - "validatorIndex": "0x5", - "address": "0x6a632187a3abf9bebb66d43368fccd612f631cbc", - "amount": "0x64" - } - ] - }, - "331": { - "withdrawals": [ - { - "index": "0x32", - "validatorIndex": "0x5", - "address": "0x984c16459ded76438d98ce9b608f175c28a910a0", - "amount": "0x64" - } - ] - }, - "336": { - "withdrawals": [ - { - "index": "0x33", - "validatorIndex": "0x5", - "address": "0x2847213288f0988543a76512fab09684131809d9", - "amount": "0x64" - } - ] - }, - "341": { - "withdrawals": [ - { - "index": "0x34", - "validatorIndex": "0x5", - "address": "0x1037044fabf0421617c47c74681d7cc9c59f136c", - "amount": "0x64" - } - ] - }, - "346": { - "withdrawals": [ - { - "index": "0x35", - "validatorIndex": "0x5", - "address": "0x8cf42eb93b1426f22a30bd22539503bdf838830c", - "amount": "0x64" - } - ] - }, - "351": { - "withdrawals": [ - { - "index": "0x36", - "validatorIndex": "0x5", - "address": "0x6b2884fef44bd4288621a2cda9f88ca07b480861", - "amount": "0x64" - } - ] - }, - "356": { - "withdrawals": [ - { - "index": "0x37", - "validatorIndex": "0x5", - "address": "0xf6152f2ad8a93dc0f8f825f2a8d162d6da46e81f", - "amount": "0x64" - } - ] - }, - "361": { - "withdrawals": [ - { - "index": "0x38", - "validatorIndex": "0x5", - "address": "0x8fa24283a8c1cc8a0f76ac69362139a173592567", - "amount": "0x64" - } - ] - }, - "366": { - "withdrawals": [ - { - "index": "0x39", - "validatorIndex": "0x5", - "address": "0x19041ad672875015bc4041c24b581eafc0869aab", - "amount": "0x64" - } - ] - }, - "371": { - "withdrawals": [ - { - "index": "0x3a", - "validatorIndex": "0x5", - "address": "0x2bb3295506aa5a21b58f1fd40f3b0f16d6d06bbc", - "amount": "0x64" - } - ] - }, - "376": { - "withdrawals": [ - { - "index": "0x3b", - "validatorIndex": "0x5", - "address": "0x23c86a8aded0ad81f8111bb07e6ec0ffb00ce5bf", - "amount": "0x64" - } - ] - }, - "381": { - "withdrawals": [ - { - "index": "0x3c", - "validatorIndex": "0x5", - "address": "0x96a1cabb97e1434a6e23e684dd4572e044c243ea", - "amount": "0x64" - } - ] - }, - "386": { - "withdrawals": [ - { - "index": "0x3d", - "validatorIndex": "0x5", - "address": "0xfd5e6e8c850fafa2ba2293c851479308c0f0c9e7", - "amount": "0x64" - } - ] - }, - "391": { - "withdrawals": [ - { - "index": "0x3e", - "validatorIndex": "0x5", - "address": "0xf997ed224012b1323eb2a6a0c0044a956c6b8070", - "amount": "0x64" - } - ] - }, - "396": { - "withdrawals": [ - { - "index": "0x3f", - "validatorIndex": "0x5", - "address": "0x6d09a879576c0d941bea7833fb2285051b10d511", - "amount": "0x64" - } - ] - }, - "401": { - "withdrawals": [ - { - "index": "0x40", - "validatorIndex": "0x5", - "address": "0x13dd437fc2ed1cd5d943ac1dd163524c815d305c", - "amount": "0x64" - } - ] - }, - "406": { - "withdrawals": [ - { - "index": "0x41", - "validatorIndex": "0x5", - "address": "0x6510225e743d73828aa4f73a3133818490bd8820", - "amount": "0x64" - } - ] - }, - "411": { - "withdrawals": [ - { - "index": "0x42", - "validatorIndex": "0x5", - "address": "0xd282cf9c585bb4f6ce71e16b6453b26aa8d34a53", - "amount": "0x64" - } - ] - }, - "416": { - "withdrawals": [ - { - "index": "0x43", - "validatorIndex": "0x5", - "address": "0xa179dbdd51c56d0988551f92535797bcf47ca0e7", - "amount": "0x64" - } - ] - }, - "421": { - "withdrawals": [ - { - "index": "0x44", - "validatorIndex": "0x5", - "address": "0x494d799e953876ac6022c3f7da5e0f3c04b549be", - "amount": "0x64" - } - ] - }, - "426": { - "withdrawals": [ - { - "index": "0x45", - "validatorIndex": "0x5", - "address": "0xb4bc136e1fb4ea0b3340d06b158277c4a8537a13", - "amount": "0x64" - } - ] - }, - "431": { - "withdrawals": [ - { - "index": "0x46", - "validatorIndex": "0x5", - "address": "0x368b766f1e4d7bf437d2a709577a5210a99002b6", - "amount": "0x64" - } - ] - }, - "436": { - "withdrawals": [ - { - "index": "0x47", - "validatorIndex": "0x5", - "address": "0x5123198d8a827fe0c788c409e7d2068afde64339", - "amount": "0x64" - } - ] - }, - "441": { - "withdrawals": [ - { - "index": "0x48", - "validatorIndex": "0x5", - "address": "0xd39b94587711196640659ec81855bcf397e419ff", - "amount": "0x64" - } - ] - }, - "446": { - "withdrawals": [ - { - "index": "0x49", - "validatorIndex": "0x5", - "address": "0x6ca60a92cbf88c7f527978dc183a22e774755551", - "amount": "0x64" - } - ] - }, - "451": { - "withdrawals": [ - { - "index": "0x4a", - "validatorIndex": "0x5", - "address": "0x102efa1f2e0ad16ada57759b815245b8f8d27ce4", - "amount": "0x64" - } - ] - }, - "456": { - "withdrawals": [ - { - "index": "0x4b", - "validatorIndex": "0x5", - "address": "0xfcc8d4cd5a42cca8ac9f9437a6d0ac09f1d08785", - "amount": "0x64" - } - ] - }, - "461": { - "withdrawals": [ - { - "index": "0x4c", - "validatorIndex": "0x5", - "address": "0x48701721ec0115f04bc7404058f6c0f386946e09", - "amount": "0x64" - } - ] - }, - "466": { - "withdrawals": [ - { - "index": "0x4d", - "validatorIndex": "0x5", - "address": "0x706be462488699e89b722822dcec9822ad7d05a7", - "amount": "0x64" - } - ] - }, - "471": { - "withdrawals": [ - { - "index": "0x4e", - "validatorIndex": "0x5", - "address": "0xe5ec19296e6d1518a6a38c1dbc7ad024b8a1a248", - "amount": "0x64" - } - ] - }, - "476": { - "withdrawals": [ - { - "index": "0x4f", - "validatorIndex": "0x5", - "address": "0x2e350f8e7f890a9301f33edbf55f38e67e02d72b", - "amount": "0x64" - } - ] - }, - "481": { - "withdrawals": [ - { - "index": "0x50", - "validatorIndex": "0x5", - "address": "0xc57aa6a4279377063b17c554d3e33a3490e67a9a", - "amount": "0x64" - } - ] - }, - "486": { - "withdrawals": [ - { - "index": "0x51", - "validatorIndex": "0x5", - "address": "0x311df588ca5f412f970891e4cc3ac23648968ca2", - "amount": "0x64" - } - ] - }, - "491": { - "withdrawals": [ - { - "index": "0x52", - "validatorIndex": "0x5", - "address": "0x3f31becc97226d3c17bf574dd86f39735fe0f0c1", - "amount": "0x64" - } - ] - }, - "496": { - "withdrawals": [ - { - "index": "0x53", - "validatorIndex": "0x5", - "address": "0x6cc0ab95752bf25ec58c91b1d603c5eb41b8fbd7", - "amount": "0x64" - } - ] - }, - "81": { - "withdrawals": [ - { - "index": "0x0", - "validatorIndex": "0x5", - "address": "0x4ae81572f06e1b88fd5ced7a1a000945432e83e1", - "amount": "0x64" - } - ] - }, - "86": { - "withdrawals": [ - { - "index": "0x1", - "validatorIndex": "0x5", - "address": "0xde5a6f78116eca62d7fc5ce159d23ae6b889b365", - "amount": "0x64" - } - ] - }, - "91": { - "withdrawals": [ - { - "index": "0x2", - "validatorIndex": "0x5", - "address": "0x245843abef9e72e7efac30138a994bf6301e7e1d", - "amount": "0x64" - } - ] - }, - "96": { - "withdrawals": [ - { - "index": "0x3", - "validatorIndex": "0x5", - "address": "0x8d33f520a3c4cef80d2453aef81b612bfe1cb44c", - "amount": "0x64" - } - ] - } - } -} \ No newline at end of file diff --git a/builder/cmd/devp2p/internal/ethtest/transaction.go b/builder/cmd/devp2p/internal/ethtest/transaction.go deleted file mode 100644 index 80b5d8074..000000000 --- a/builder/cmd/devp2p/internal/ethtest/transaction.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package ethtest - -import ( - "errors" - "fmt" - "os" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/internal/utesting" -) - -// sendTxs sends the given transactions to the node and -// expects the node to accept and propagate them. -func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error { - // Open sending conn. - sendConn, err := s.dial() - if err != nil { - return err - } - defer sendConn.Close() - if err = sendConn.peer(s.chain, nil); err != nil { - return fmt.Errorf("peering failed: %v", err) - } - - // Open receiving conn. - recvConn, err := s.dial() - if err != nil { - return err - } - defer recvConn.Close() - if err = recvConn.peer(s.chain, nil); err != nil { - return fmt.Errorf("peering failed: %v", err) - } - - if err = sendConn.Write(ethProto, eth.TransactionsMsg, eth.TransactionsPacket(txs)); err != nil { - return fmt.Errorf("failed to write message to connection: %v", err) - } - - var ( - got = make(map[common.Hash]bool) - end = time.Now().Add(timeout) - ) - - // Wait for the transaction announcements, make sure all txs ar propagated. - for time.Now().Before(end) { - msg, err := recvConn.ReadEth() - if err != nil { - return fmt.Errorf("failed to read from connection: %w", err) - } - switch msg := msg.(type) { - case *eth.TransactionsPacket: - for _, tx := range *msg { - got[tx.Hash()] = true - } - case *eth.NewPooledTransactionHashesPacket: - for _, hash := range msg.Hashes { - got[hash] = true - } - case *eth.GetBlockHeadersPacket: - headers, err := s.chain.GetHeaders(msg) - if err != nil { - t.Logf("invalid GetBlockHeaders request: %v", err) - } - recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{ - RequestId: msg.RequestId, - BlockHeadersRequest: headers, - }) - default: - return fmt.Errorf("unexpected eth wire msg: %s", pretty.Sdump(msg)) - } - - // Check if all txs received. - allReceived := func() bool { - for _, tx := range txs { - if !got[tx.Hash()] { - return false - } - } - return true - } - if allReceived() { - return nil - } - } - - return fmt.Errorf("timed out waiting for txs") -} - -func (s *Suite) sendInvalidTxs(t *utesting.T, txs []*types.Transaction) error { - // Open sending conn. - sendConn, err := s.dial() - if err != nil { - return err - } - defer sendConn.Close() - if err = sendConn.peer(s.chain, nil); err != nil { - return fmt.Errorf("peering failed: %v", err) - } - sendConn.SetDeadline(time.Now().Add(timeout)) - - // Open receiving conn. - recvConn, err := s.dial() - if err != nil { - return err - } - defer recvConn.Close() - if err = recvConn.peer(s.chain, nil); err != nil { - return fmt.Errorf("peering failed: %v", err) - } - recvConn.SetDeadline(time.Now().Add(timeout)) - - if err = sendConn.Write(ethProto, eth.TransactionsMsg, txs); err != nil { - return fmt.Errorf("failed to write message to connection: %w", err) - } - - // Make map of invalid txs. - invalids := make(map[common.Hash]struct{}) - for _, tx := range txs { - invalids[tx.Hash()] = struct{}{} - } - - // Get responses. - recvConn.SetReadDeadline(time.Now().Add(timeout)) - for { - msg, err := recvConn.ReadEth() - if errors.Is(err, os.ErrDeadlineExceeded) { - // Successful if no invalid txs are propagated before timeout. - return nil - } else if err != nil { - return fmt.Errorf("failed to read from connection: %w", err) - } - - switch msg := msg.(type) { - case *eth.TransactionsPacket: - for _, tx := range txs { - if _, ok := invalids[tx.Hash()]; ok { - return fmt.Errorf("received bad tx: %s", tx.Hash()) - } - } - case *eth.NewPooledTransactionHashesPacket: - for _, hash := range msg.Hashes { - if _, ok := invalids[hash]; ok { - return fmt.Errorf("received bad tx: %s", hash) - } - } - case *eth.GetBlockHeadersPacket: - headers, err := s.chain.GetHeaders(msg) - if err != nil { - t.Logf("invalid GetBlockHeaders request: %v", err) - } - recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{ - RequestId: msg.RequestId, - BlockHeadersRequest: headers, - }) - default: - return fmt.Errorf("unexpected eth message: %v", pretty.Sdump(msg)) - } - } -} diff --git a/builder/cmd/devp2p/internal/v4test/discv4tests.go b/builder/cmd/devp2p/internal/v4test/discv4tests.go deleted file mode 100644 index ca556851b..000000000 --- a/builder/cmd/devp2p/internal/v4test/discv4tests.go +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package v4test - -import ( - "bytes" - "crypto/rand" - "errors" - "fmt" - "net" - "time" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/p2p/discover/v4wire" -) - -const ( - expiration = 20 * time.Second - wrongPacket = 66 - macSize = 256 / 8 -) - -var ( - // Remote node under test - Remote string - // Listen1 is the IP where the first tester is listening, port will be assigned - Listen1 string = "127.0.0.1" - // Listen2 is the IP where the second tester is listening, port will be assigned - // Before running the test, you may have to `sudo ifconfig lo0 add 127.0.0.2` (on MacOS at least) - Listen2 string = "127.0.0.2" -) - -type pingWithJunk struct { - Version uint - From, To v4wire.Endpoint - Expiration uint64 - JunkData1 uint - JunkData2 []byte -} - -func (req *pingWithJunk) Name() string { return "PING/v4" } -func (req *pingWithJunk) Kind() byte { return v4wire.PingPacket } - -type pingWrongType struct { - Version uint - From, To v4wire.Endpoint - Expiration uint64 -} - -func (req *pingWrongType) Name() string { return "WRONG/v4" } -func (req *pingWrongType) Kind() byte { return wrongPacket } - -func futureExpiration() uint64 { - return uint64(time.Now().Add(expiration).Unix()) -} - -// BasicPing just sends a PING packet and expects a response. -func BasicPing(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - pingHash := te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - if err := te.checkPingPong(pingHash); err != nil { - t.Fatal(err) - } -} - -// checkPingPong verifies that the remote side sends both a PONG with the -// correct hash, and a PING. -// The two packets do not have to be in any particular order. -func (te *testenv) checkPingPong(pingHash []byte) error { - var ( - pings int - pongs int - ) - for i := 0; i < 2; i++ { - reply, _, err := te.read(te.l1) - if err != nil { - return err - } - switch reply.Kind() { - case v4wire.PongPacket: - if err := te.checkPong(reply, pingHash); err != nil { - return err - } - pongs++ - case v4wire.PingPacket: - pings++ - default: - return fmt.Errorf("expected PING or PONG, got %v %v", reply.Name(), reply) - } - } - if pongs == 1 && pings == 1 { - return nil - } - return fmt.Errorf("expected 1 PING (got %d) and 1 PONG (got %d)", pings, pongs) -} - -// checkPong verifies that reply is a valid PONG matching the given ping hash, -// and a PING. The two packets do not have to be in any particular order. -func (te *testenv) checkPong(reply v4wire.Packet, pingHash []byte) error { - if reply == nil { - return errors.New("expected PONG reply, got nil") - } - if reply.Kind() != v4wire.PongPacket { - return fmt.Errorf("expected PONG reply, got %v %v", reply.Name(), reply) - } - pong := reply.(*v4wire.Pong) - if !bytes.Equal(pong.ReplyTok, pingHash) { - return fmt.Errorf("PONG reply token mismatch: got %x, want %x", pong.ReplyTok, pingHash) - } - if want := te.localEndpoint(te.l1); !want.IP.Equal(pong.To.IP) || want.UDP != pong.To.UDP { - return fmt.Errorf("PONG 'to' endpoint mismatch: got %+v, want %+v", pong.To, want) - } - if v4wire.Expired(pong.Expiration) { - return fmt.Errorf("PONG is expired (%v)", pong.Expiration) - } - return nil -} - -// PingWrongTo sends a PING packet with wrong 'to' field and expects a PONG response. -func PingWrongTo(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - wrongEndpoint := v4wire.Endpoint{IP: net.ParseIP("192.0.2.0")} - pingHash := te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: te.localEndpoint(te.l1), - To: wrongEndpoint, - Expiration: futureExpiration(), - }) - if err := te.checkPingPong(pingHash); err != nil { - t.Fatal(err) - } -} - -// PingWrongFrom sends a PING packet with wrong 'from' field and expects a PONG response. -func PingWrongFrom(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - wrongEndpoint := v4wire.Endpoint{IP: net.ParseIP("192.0.2.0")} - pingHash := te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: wrongEndpoint, - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - - if err := te.checkPingPong(pingHash); err != nil { - t.Fatal(err) - } -} - -// PingExtraData This test sends a PING packet with additional data at the end and expects a PONG -// response. The remote node should respond because EIP-8 mandates ignoring additional -// trailing data. -func PingExtraData(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - pingHash := te.send(te.l1, &pingWithJunk{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - JunkData1: 42, - JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1}, - }) - - if err := te.checkPingPong(pingHash); err != nil { - t.Fatal(err) - } -} - -// This test sends a PING packet with additional data and wrong 'from' field -// and expects a PONG response. -func PingExtraDataWrongFrom(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - wrongEndpoint := v4wire.Endpoint{IP: net.ParseIP("192.0.2.0")} - req := pingWithJunk{ - Version: 4, - From: wrongEndpoint, - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - JunkData1: 42, - JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1}, - } - pingHash := te.send(te.l1, &req) - if err := te.checkPingPong(pingHash); err != nil { - t.Fatal(err) - } -} - -// This test sends a PING packet with an expiration in the past. -// The remote node should not respond. -func PingPastExpiration(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: -futureExpiration(), - }) - - reply, _, _ := te.read(te.l1) - if reply != nil { - t.Fatalf("Expected no reply, got %v %v", reply.Name(), reply) - } -} - -// This test sends an invalid packet. The remote node should not respond. -func WrongPacketType(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - te.send(te.l1, &pingWrongType{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - - reply, _, _ := te.read(te.l1) - if reply != nil { - t.Fatalf("Expected no reply, got %v %v", reply.Name(), reply) - } -} - -// This test verifies that the default behaviour of ignoring 'from' fields is unaffected by -// the bonding process. After bonding, it pings the target with a different from endpoint. -func BondThenPingWithWrongFrom(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - bond(t, te) - - wrongEndpoint := v4wire.Endpoint{IP: net.ParseIP("192.0.2.0")} - pingHash := te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: wrongEndpoint, - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - -waitForPong: - for { - reply, _, err := te.read(te.l1) - if err != nil { - t.Fatal(err) - } - switch reply.Kind() { - case v4wire.PongPacket: - if err := te.checkPong(reply, pingHash); err != nil { - t.Fatal(err) - } - break waitForPong - case v4wire.FindnodePacket: - // FINDNODE from the node is acceptable here since the endpoint - // verification was performed earlier. - default: - t.Fatalf("Expected PONG, got %v %v", reply.Name(), reply) - } - } -} - -// This test just sends FINDNODE. The remote node should not reply -// because the endpoint proof has not completed. -func FindnodeWithoutEndpointProof(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - req := v4wire.Findnode{Expiration: futureExpiration()} - rand.Read(req.Target[:]) - te.send(te.l1, &req) - - for { - reply, _, _ := te.read(te.l1) - if reply == nil { - // No response, all good - break - } - if reply.Kind() == v4wire.PingPacket { - continue // A ping is ok, just ignore it - } - t.Fatalf("Expected no reply, got %v %v", reply.Name(), reply) - } -} - -// BasicFindnode sends a FINDNODE request after performing the endpoint -// proof. The remote node should respond. -func BasicFindnode(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - bond(t, te) - - findnode := v4wire.Findnode{Expiration: futureExpiration()} - rand.Read(findnode.Target[:]) - te.send(te.l1, &findnode) - - reply, _, err := te.read(te.l1) - if err != nil { - t.Fatal("read find nodes", err) - } - if reply.Kind() != v4wire.NeighborsPacket { - t.Fatalf("Expected neighbors, got %v %v", reply.Name(), reply) - } -} - -// This test sends an unsolicited NEIGHBORS packet after the endpoint proof, then sends -// FINDNODE to read the remote table. The remote node should not return the node contained -// in the unsolicited NEIGHBORS packet. -func UnsolicitedNeighbors(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - bond(t, te) - - // Send unsolicited NEIGHBORS response. - fakeKey, _ := crypto.GenerateKey() - encFakeKey := v4wire.EncodePubkey(&fakeKey.PublicKey) - neighbors := v4wire.Neighbors{ - Expiration: futureExpiration(), - Nodes: []v4wire.Node{{ - ID: encFakeKey, - IP: net.IP{1, 2, 3, 4}, - UDP: 30303, - TCP: 30303, - }}, - } - te.send(te.l1, &neighbors) - - // Check if the remote node included the fake node. - te.send(te.l1, &v4wire.Findnode{ - Expiration: futureExpiration(), - Target: encFakeKey, - }) - - reply, _, err := te.read(te.l1) - if err != nil { - t.Fatal("read find nodes", err) - } - if reply.Kind() != v4wire.NeighborsPacket { - t.Fatalf("Expected neighbors, got %v %v", reply.Name(), reply) - } - nodes := reply.(*v4wire.Neighbors).Nodes - if contains(nodes, encFakeKey) { - t.Fatal("neighbors response contains node from earlier unsolicited neighbors response") - } -} - -// This test sends FINDNODE with an expiration timestamp in the past. -// The remote node should not respond. -func FindnodePastExpiration(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - bond(t, te) - - findnode := v4wire.Findnode{Expiration: -futureExpiration()} - rand.Read(findnode.Target[:]) - te.send(te.l1, &findnode) - - for { - reply, _, _ := te.read(te.l1) - if reply == nil { - return - } else if reply.Kind() == v4wire.NeighborsPacket { - t.Fatal("Unexpected NEIGHBORS response for expired FINDNODE request") - } - } -} - -// bond performs the endpoint proof with the remote node. -func bond(t *utesting.T, te *testenv) { - pingHash := te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - - var gotPing, gotPong bool - for !gotPing || !gotPong { - req, hash, err := te.read(te.l1) - if err != nil { - t.Fatal(err) - } - switch req.(type) { - case *v4wire.Ping: - te.send(te.l1, &v4wire.Pong{ - To: te.remoteEndpoint(), - ReplyTok: hash, - Expiration: futureExpiration(), - }) - gotPing = true - case *v4wire.Pong: - if err := te.checkPong(req, pingHash); err != nil { - t.Fatal(err) - } - gotPong = true - } - } -} - -// This test attempts to perform a traffic amplification attack against a -// 'victim' endpoint using FINDNODE. In this attack scenario, the attacker -// attempts to complete the endpoint proof non-interactively by sending a PONG -// with mismatching reply token from the 'victim' endpoint. The attack works if -// the remote node does not verify the PONG reply token field correctly. The -// attacker could then perform traffic amplification by sending many FINDNODE -// requests to the discovery node, which would reply to the 'victim' address. -func FindnodeAmplificationInvalidPongHash(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - // Send PING to start endpoint verification. - te.send(te.l1, &v4wire.Ping{ - Version: 4, - From: te.localEndpoint(te.l1), - To: te.remoteEndpoint(), - Expiration: futureExpiration(), - }) - - var gotPing, gotPong bool - for !gotPing || !gotPong { - req, _, err := te.read(te.l1) - if err != nil { - t.Fatal(err) - } - switch req.(type) { - case *v4wire.Ping: - // Send PONG from this node ID, but with invalid ReplyTok. - te.send(te.l1, &v4wire.Pong{ - To: te.remoteEndpoint(), - ReplyTok: make([]byte, macSize), - Expiration: futureExpiration(), - }) - gotPing = true - case *v4wire.Pong: - gotPong = true - } - } - - // Now send FINDNODE. The remote node should not respond because our - // PONG did not reference the PING hash. - findnode := v4wire.Findnode{Expiration: futureExpiration()} - rand.Read(findnode.Target[:]) - te.send(te.l1, &findnode) - - // If we receive a NEIGHBORS response, the attack worked and the test fails. - reply, _, _ := te.read(te.l1) - if reply != nil && reply.Kind() == v4wire.NeighborsPacket { - t.Error("Got neighbors") - } -} - -// This test attempts to perform a traffic amplification attack using FINDNODE. -// The attack works if the remote node does not verify the IP address of FINDNODE -// against the endpoint verification proof done by PING/PONG. -func FindnodeAmplificationWrongIP(t *utesting.T) { - te := newTestEnv(Remote, Listen1, Listen2) - defer te.close() - - // Do the endpoint proof from the l1 IP. - bond(t, te) - - // Now send FINDNODE from the same node ID, but different IP address. - // The remote node should not respond. - findnode := v4wire.Findnode{Expiration: futureExpiration()} - rand.Read(findnode.Target[:]) - te.send(te.l2, &findnode) - - // If we receive a NEIGHBORS response, the attack worked and the test fails. - reply, _, _ := te.read(te.l2) - if reply != nil { - t.Error("Got NEIGHBORS response for FINDNODE from wrong IP") - } -} - -var AllTests = []utesting.Test{ - {Name: "Ping/Basic", Fn: BasicPing}, - {Name: "Ping/WrongTo", Fn: PingWrongTo}, - {Name: "Ping/WrongFrom", Fn: PingWrongFrom}, - {Name: "Ping/ExtraData", Fn: PingExtraData}, - {Name: "Ping/ExtraDataWrongFrom", Fn: PingExtraDataWrongFrom}, - {Name: "Ping/PastExpiration", Fn: PingPastExpiration}, - {Name: "Ping/WrongPacketType", Fn: WrongPacketType}, - {Name: "Ping/BondThenPingWithWrongFrom", Fn: BondThenPingWithWrongFrom}, - {Name: "Findnode/WithoutEndpointProof", Fn: FindnodeWithoutEndpointProof}, - {Name: "Findnode/BasicFindnode", Fn: BasicFindnode}, - {Name: "Findnode/UnsolicitedNeighbors", Fn: UnsolicitedNeighbors}, - {Name: "Findnode/PastExpiration", Fn: FindnodePastExpiration}, - {Name: "Amplification/InvalidPongHash", Fn: FindnodeAmplificationInvalidPongHash}, - {Name: "Amplification/WrongIP", Fn: FindnodeAmplificationWrongIP}, -} diff --git a/builder/cmd/devp2p/internal/v4test/framework.go b/builder/cmd/devp2p/internal/v4test/framework.go deleted file mode 100644 index 928659418..000000000 --- a/builder/cmd/devp2p/internal/v4test/framework.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package v4test - -import ( - "crypto/ecdsa" - "fmt" - "net" - "time" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/p2p/discover/v4wire" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -const waitTime = 300 * time.Millisecond - -type testenv struct { - l1, l2 net.PacketConn - key *ecdsa.PrivateKey - remote *enode.Node - remoteAddr *net.UDPAddr -} - -func newTestEnv(remote string, listen1, listen2 string) *testenv { - l1, err := net.ListenPacket("udp", fmt.Sprintf("%v:0", listen1)) - if err != nil { - panic(err) - } - l2, err := net.ListenPacket("udp", fmt.Sprintf("%v:0", listen2)) - if err != nil { - panic(err) - } - key, err := crypto.GenerateKey() - if err != nil { - panic(err) - } - node, err := enode.Parse(enode.ValidSchemes, remote) - if err != nil { - panic(err) - } - if node.IP() == nil || node.UDP() == 0 { - var ip net.IP - var tcpPort, udpPort int - if ip = node.IP(); ip == nil { - ip = net.ParseIP("127.0.0.1") - } - if tcpPort = node.TCP(); tcpPort == 0 { - tcpPort = 30303 - } - if udpPort = node.TCP(); udpPort == 0 { - udpPort = 30303 - } - node = enode.NewV4(node.Pubkey(), ip, tcpPort, udpPort) - } - addr := &net.UDPAddr{IP: node.IP(), Port: node.UDP()} - return &testenv{l1, l2, key, node, addr} -} - -func (te *testenv) close() { - te.l1.Close() - te.l2.Close() -} - -func (te *testenv) send(c net.PacketConn, req v4wire.Packet) []byte { - packet, hash, err := v4wire.Encode(te.key, req) - if err != nil { - panic(fmt.Errorf("can't encode %v packet: %v", req.Name(), err)) - } - if _, err := c.WriteTo(packet, te.remoteAddr); err != nil { - panic(fmt.Errorf("can't send %v: %v", req.Name(), err)) - } - return hash -} - -func (te *testenv) read(c net.PacketConn) (v4wire.Packet, []byte, error) { - buf := make([]byte, 2048) - if err := c.SetReadDeadline(time.Now().Add(waitTime)); err != nil { - return nil, nil, err - } - n, _, err := c.ReadFrom(buf) - if err != nil { - return nil, nil, err - } - p, _, hash, err := v4wire.Decode(buf[:n]) - return p, hash, err -} - -func (te *testenv) localEndpoint(c net.PacketConn) v4wire.Endpoint { - addr := c.LocalAddr().(*net.UDPAddr) - return v4wire.Endpoint{ - IP: addr.IP.To4(), - UDP: uint16(addr.Port), - TCP: 0, - } -} - -func (te *testenv) remoteEndpoint() v4wire.Endpoint { - return v4wire.NewEndpoint(te.remoteAddr, 0) -} - -func contains(ns []v4wire.Node, key v4wire.Pubkey) bool { - for _, n := range ns { - if n.ID == key { - return true - } - } - return false -} diff --git a/builder/cmd/devp2p/internal/v5test/discv5tests.go b/builder/cmd/devp2p/internal/v5test/discv5tests.go deleted file mode 100644 index 56624a0ca..000000000 --- a/builder/cmd/devp2p/internal/v5test/discv5tests.go +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package v5test - -import ( - "bytes" - "net" - "sync" - "time" - - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/p2p/discover/v5wire" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/netutil" -) - -// Suite is the discv5 test suite. -type Suite struct { - Dest *enode.Node - Listen1, Listen2 string // listening addresses -} - -func (s *Suite) listen1(log logger) (*conn, net.PacketConn) { - c := newConn(s.Dest, log) - l := c.listen(s.Listen1) - return c, l -} - -func (s *Suite) listen2(log logger) (*conn, net.PacketConn, net.PacketConn) { - c := newConn(s.Dest, log) - l1, l2 := c.listen(s.Listen1), c.listen(s.Listen2) - return c, l1, l2 -} - -func (s *Suite) AllTests() []utesting.Test { - return []utesting.Test{ - {Name: "Ping", Fn: s.TestPing}, - {Name: "PingLargeRequestID", Fn: s.TestPingLargeRequestID}, - {Name: "PingMultiIP", Fn: s.TestPingMultiIP}, - {Name: "PingHandshakeInterrupted", Fn: s.TestPingHandshakeInterrupted}, - {Name: "TalkRequest", Fn: s.TestTalkRequest}, - {Name: "FindnodeZeroDistance", Fn: s.TestFindnodeZeroDistance}, - {Name: "FindnodeResults", Fn: s.TestFindnodeResults}, - } -} - -// TestPing sends PING and expects a PONG response. -func (s *Suite) TestPing(t *utesting.T) { - conn, l1 := s.listen1(t) - defer conn.close() - - ping := &v5wire.Ping{ReqID: conn.nextReqID()} - switch resp := conn.reqresp(l1, ping).(type) { - case *v5wire.Pong: - checkPong(t, resp, ping, l1) - default: - t.Fatal("expected PONG, got", resp.Name()) - } -} - -func checkPong(t *utesting.T, pong *v5wire.Pong, ping *v5wire.Ping, c net.PacketConn) { - if !bytes.Equal(pong.ReqID, ping.ReqID) { - t.Fatalf("wrong request ID %x in PONG, want %x", pong.ReqID, ping.ReqID) - } - if !pong.ToIP.Equal(laddr(c).IP) { - t.Fatalf("wrong destination IP %v in PONG, want %v", pong.ToIP, laddr(c).IP) - } - if int(pong.ToPort) != laddr(c).Port { - t.Fatalf("wrong destination port %v in PONG, want %v", pong.ToPort, laddr(c).Port) - } -} - -// TestPingLargeRequestID sends PING with a 9-byte request ID, which isn't allowed by the spec. -// The remote node should not respond. -func (s *Suite) TestPingLargeRequestID(t *utesting.T) { - conn, l1 := s.listen1(t) - defer conn.close() - - ping := &v5wire.Ping{ReqID: make([]byte, 9)} - switch resp := conn.reqresp(l1, ping).(type) { - case *v5wire.Pong: - t.Errorf("PONG response with unknown request ID %x", resp.ReqID) - case *readError: - if resp.err == v5wire.ErrInvalidReqID { - t.Error("response with oversized request ID") - } else if !netutil.IsTimeout(resp.err) { - t.Error(resp) - } - } -} - -// TestPingMultiIP establishes a session from one IP as usual. The session is then reused -// on another IP, which shouldn't work. The remote node should respond with WHOAREYOU for -// the attempt from a different IP. -func (s *Suite) TestPingMultiIP(t *utesting.T) { - conn, l1, l2 := s.listen2(t) - defer conn.close() - - // Create the session on l1. - ping := &v5wire.Ping{ReqID: conn.nextReqID()} - resp := conn.reqresp(l1, ping) - if resp.Kind() != v5wire.PongMsg { - t.Fatal("expected PONG, got", resp) - } - checkPong(t, resp.(*v5wire.Pong), ping, l1) - - // Send on l2. This reuses the session because there is only one codec. - ping2 := &v5wire.Ping{ReqID: conn.nextReqID()} - conn.write(l2, ping2, nil) - switch resp := conn.read(l2).(type) { - case *v5wire.Pong: - t.Fatalf("remote responded to PING from %v for session on IP %v", laddr(l2).IP, laddr(l1).IP) - case *v5wire.Whoareyou: - t.Logf("got WHOAREYOU for new session as expected") - resp.Node = s.Dest - conn.write(l2, ping2, resp) - default: - t.Fatal("expected WHOAREYOU, got", resp) - } - - // Catch the PONG on l2. - switch resp := conn.read(l2).(type) { - case *v5wire.Pong: - checkPong(t, resp, ping2, l2) - default: - t.Fatal("expected PONG, got", resp) - } - - // Try on l1 again. - ping3 := &v5wire.Ping{ReqID: conn.nextReqID()} - conn.write(l1, ping3, nil) - switch resp := conn.read(l1).(type) { - case *v5wire.Pong: - t.Fatalf("remote responded to PING from %v for session on IP %v", laddr(l1).IP, laddr(l2).IP) - case *v5wire.Whoareyou: - t.Logf("got WHOAREYOU for new session as expected") - default: - t.Fatal("expected WHOAREYOU, got", resp) - } -} - -// TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message -// packet instead of a handshake message packet. The remote node should respond with -// another WHOAREYOU challenge for the second packet. -func (s *Suite) TestPingHandshakeInterrupted(t *utesting.T) { - conn, l1 := s.listen1(t) - defer conn.close() - - // First PING triggers challenge. - ping := &v5wire.Ping{ReqID: conn.nextReqID()} - conn.write(l1, ping, nil) - switch resp := conn.read(l1).(type) { - case *v5wire.Whoareyou: - t.Logf("got WHOAREYOU for PING") - default: - t.Fatal("expected WHOAREYOU, got", resp) - } - - // Send second PING. - ping2 := &v5wire.Ping{ReqID: conn.nextReqID()} - switch resp := conn.reqresp(l1, ping2).(type) { - case *v5wire.Pong: - checkPong(t, resp, ping2, l1) - default: - t.Fatal("expected WHOAREYOU, got", resp) - } -} - -// TestTalkRequest sends TALKREQ and expects an empty TALKRESP response. -func (s *Suite) TestTalkRequest(t *utesting.T) { - conn, l1 := s.listen1(t) - defer conn.close() - - // Non-empty request ID. - id := conn.nextReqID() - resp := conn.reqresp(l1, &v5wire.TalkRequest{ReqID: id, Protocol: "test-protocol"}) - switch resp := resp.(type) { - case *v5wire.TalkResponse: - if !bytes.Equal(resp.ReqID, id) { - t.Fatalf("wrong request ID %x in TALKRESP, want %x", resp.ReqID, id) - } - if len(resp.Message) > 0 { - t.Fatalf("non-empty message %x in TALKRESP", resp.Message) - } - default: - t.Fatal("expected TALKRESP, got", resp.Name()) - } - - // Empty request ID. - resp = conn.reqresp(l1, &v5wire.TalkRequest{Protocol: "test-protocol"}) - switch resp := resp.(type) { - case *v5wire.TalkResponse: - if len(resp.ReqID) > 0 { - t.Fatalf("wrong request ID %x in TALKRESP, want empty byte array", resp.ReqID) - } - if len(resp.Message) > 0 { - t.Fatalf("non-empty message %x in TALKRESP", resp.Message) - } - default: - t.Fatal("expected TALKRESP, got", resp.Name()) - } -} - -// TestFindnodeZeroDistance checks that the remote node returns itself for FINDNODE with distance zero. -func (s *Suite) TestFindnodeZeroDistance(t *utesting.T) { - conn, l1 := s.listen1(t) - defer conn.close() - - nodes, err := conn.findnode(l1, []uint{0}) - if err != nil { - t.Fatal(err) - } - if len(nodes) != 1 { - t.Fatalf("remote returned more than one node for FINDNODE [0]") - } - if nodes[0].ID() != conn.remote.ID() { - t.Errorf("ID of response node is %v, want %v", nodes[0].ID(), conn.remote.ID()) - } -} - -// TestFindnodeResults pings the node under test from multiple nodes. After waiting for them to be -// accepted into the remote table, the test checks that they are returned by FINDNODE. -func (s *Suite) TestFindnodeResults(t *utesting.T) { - // Create bystanders. - nodes := make([]*bystander, 5) - added := make(chan enode.ID, len(nodes)) - for i := range nodes { - nodes[i] = newBystander(t, s, added) - defer nodes[i].close() - } - - // Get them added to the remote table. - timeout := 60 * time.Second - timeoutCh := time.After(timeout) - for count := 0; count < len(nodes); { - select { - case id := <-added: - t.Logf("bystander node %v added to remote table", id) - count++ - case <-timeoutCh: - t.Errorf("remote added %d bystander nodes in %v, need %d to continue", count, timeout, len(nodes)) - t.Logf("this can happen if the node has a non-empty table from previous runs") - return - } - } - t.Logf("all %d bystander nodes were added", len(nodes)) - - // Collect our nodes by distance. - var dists []uint - expect := make(map[enode.ID]*enode.Node) - for _, bn := range nodes { - n := bn.conn.localNode.Node() - expect[n.ID()] = n - d := uint(enode.LogDist(n.ID(), s.Dest.ID())) - if !containsUint(dists, d) { - dists = append(dists, d) - } - } - - // Send FINDNODE for all distances. - conn, l1 := s.listen1(t) - defer conn.close() - foundNodes, err := conn.findnode(l1, dists) - if err != nil { - t.Fatal(err) - } - t.Logf("remote returned %d nodes for distance list %v", len(foundNodes), dists) - for _, n := range foundNodes { - delete(expect, n.ID()) - } - if len(expect) > 0 { - t.Errorf("missing %d nodes in FINDNODE result", len(expect)) - t.Logf("this can happen if the test is run multiple times in quick succession") - t.Logf("and the remote node hasn't removed dead nodes from previous runs yet") - } else { - t.Logf("all %d expected nodes were returned", len(nodes)) - } -} - -// A bystander is a node whose only purpose is filling a spot in the remote table. -type bystander struct { - dest *enode.Node - conn *conn - l net.PacketConn - - addedCh chan enode.ID - done sync.WaitGroup -} - -func newBystander(t *utesting.T, s *Suite, added chan enode.ID) *bystander { - conn, l := s.listen1(t) - conn.setEndpoint(l) // bystander nodes need IP/port to get pinged - bn := &bystander{ - conn: conn, - l: l, - dest: s.Dest, - addedCh: added, - } - bn.done.Add(1) - go bn.loop() - return bn -} - -// id returns the node ID of the bystander. -func (bn *bystander) id() enode.ID { - return bn.conn.localNode.ID() -} - -// close shuts down loop. -func (bn *bystander) close() { - bn.conn.close() - bn.done.Wait() -} - -// loop answers packets from the remote node until quit. -func (bn *bystander) loop() { - defer bn.done.Done() - - var ( - lastPing time.Time - wasAdded bool - ) - for { - // Ping the remote node. - if !wasAdded && time.Since(lastPing) > 10*time.Second { - bn.conn.reqresp(bn.l, &v5wire.Ping{ - ReqID: bn.conn.nextReqID(), - ENRSeq: bn.dest.Seq(), - }) - lastPing = time.Now() - } - // Answer packets. - switch p := bn.conn.read(bn.l).(type) { - case *v5wire.Ping: - bn.conn.write(bn.l, &v5wire.Pong{ - ReqID: p.ReqID, - ENRSeq: bn.conn.localNode.Seq(), - ToIP: bn.dest.IP(), - ToPort: uint16(bn.dest.UDP()), - }, nil) - wasAdded = true - bn.notifyAdded() - case *v5wire.Findnode: - bn.conn.write(bn.l, &v5wire.Nodes{ReqID: p.ReqID, RespCount: 1}, nil) - wasAdded = true - bn.notifyAdded() - case *v5wire.TalkRequest: - bn.conn.write(bn.l, &v5wire.TalkResponse{ReqID: p.ReqID}, nil) - case *readError: - if !netutil.IsTemporaryError(p.err) { - bn.conn.logf("shutting down: %v", p.err) - return - } - } - } -} - -func (bn *bystander) notifyAdded() { - if bn.addedCh != nil { - bn.addedCh <- bn.id() - bn.addedCh = nil - } -} diff --git a/builder/cmd/devp2p/internal/v5test/framework.go b/builder/cmd/devp2p/internal/v5test/framework.go deleted file mode 100644 index 10856a50b..000000000 --- a/builder/cmd/devp2p/internal/v5test/framework.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package v5test - -import ( - "bytes" - "crypto/ecdsa" - "encoding/binary" - "fmt" - "net" - "time" - - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/p2p/discover/v5wire" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" -) - -// readError represents an error during packet reading. -// This exists to facilitate type-switching on the result of conn.read. -type readError struct { - err error -} - -func (p *readError) Kind() byte { return 99 } -func (p *readError) Name() string { return fmt.Sprintf("error: %v", p.err) } -func (p *readError) Error() string { return p.err.Error() } -func (p *readError) Unwrap() error { return p.err } -func (p *readError) RequestID() []byte { return nil } -func (p *readError) SetRequestID([]byte) {} - -func (p *readError) AppendLogInfo(ctx []interface{}) []interface{} { return ctx } - -// readErrorf creates a readError with the given text. -func readErrorf(format string, args ...interface{}) *readError { - return &readError{fmt.Errorf(format, args...)} -} - -// This is the response timeout used in tests. -const waitTime = 300 * time.Millisecond - -// conn is a connection to the node under test. -type conn struct { - localNode *enode.LocalNode - localKey *ecdsa.PrivateKey - remote *enode.Node - remoteAddr *net.UDPAddr - listeners []net.PacketConn - - log logger - codec *v5wire.Codec - idCounter uint32 -} - -type logger interface { - Logf(string, ...interface{}) -} - -// newConn sets up a connection to the given node. -func newConn(dest *enode.Node, log logger) *conn { - key, err := crypto.GenerateKey() - if err != nil { - panic(err) - } - db, err := enode.OpenDB("") - if err != nil { - panic(err) - } - ln := enode.NewLocalNode(db, key) - - return &conn{ - localKey: key, - localNode: ln, - remote: dest, - remoteAddr: &net.UDPAddr{IP: dest.IP(), Port: dest.UDP()}, - codec: v5wire.NewCodec(ln, key, mclock.System{}, nil), - log: log, - } -} - -func (tc *conn) setEndpoint(c net.PacketConn) { - tc.localNode.SetStaticIP(laddr(c).IP) - tc.localNode.SetFallbackUDP(laddr(c).Port) -} - -func (tc *conn) listen(ip string) net.PacketConn { - l, err := net.ListenPacket("udp", fmt.Sprintf("%v:0", ip)) - if err != nil { - panic(err) - } - tc.listeners = append(tc.listeners, l) - return l -} - -// close shuts down all listeners and the local node. -func (tc *conn) close() { - for _, l := range tc.listeners { - l.Close() - } - tc.localNode.Database().Close() -} - -// nextReqID creates a request id. -func (tc *conn) nextReqID() []byte { - id := make([]byte, 4) - tc.idCounter++ - binary.BigEndian.PutUint32(id, tc.idCounter) - return id -} - -// reqresp performs a request/response interaction on the given connection. -// The request is retried if a handshake is requested. -func (tc *conn) reqresp(c net.PacketConn, req v5wire.Packet) v5wire.Packet { - reqnonce := tc.write(c, req, nil) - switch resp := tc.read(c).(type) { - case *v5wire.Whoareyou: - if resp.Nonce != reqnonce { - return readErrorf("wrong nonce %x in WHOAREYOU (want %x)", resp.Nonce[:], reqnonce[:]) - } - resp.Node = tc.remote - tc.write(c, req, resp) - return tc.read(c) - default: - return resp - } -} - -// findnode sends a FINDNODE request and waits for its responses. -func (tc *conn) findnode(c net.PacketConn, dists []uint) ([]*enode.Node, error) { - var ( - findnode = &v5wire.Findnode{ReqID: tc.nextReqID(), Distances: dists} - reqnonce = tc.write(c, findnode, nil) - first = true - total uint8 - results []*enode.Node - ) - for n := 1; n > 0; { - switch resp := tc.read(c).(type) { - case *v5wire.Whoareyou: - // Handle handshake. - if resp.Nonce == reqnonce { - resp.Node = tc.remote - tc.write(c, findnode, resp) - } else { - return nil, fmt.Errorf("unexpected WHOAREYOU (nonce %x), waiting for NODES", resp.Nonce[:]) - } - case *v5wire.Ping: - // Handle ping from remote. - tc.write(c, &v5wire.Pong{ - ReqID: resp.ReqID, - ENRSeq: tc.localNode.Seq(), - }, nil) - case *v5wire.Nodes: - // Got NODES! Check request ID. - if !bytes.Equal(resp.ReqID, findnode.ReqID) { - return nil, fmt.Errorf("NODES response has wrong request id %x", resp.ReqID) - } - // Check total count. It should be greater than one - // and needs to be the same across all responses. - if first { - if resp.RespCount == 0 || resp.RespCount > 6 { - return nil, fmt.Errorf("invalid NODES response count %d (not in (0,7))", resp.RespCount) - } - total = resp.RespCount - n = int(total) - 1 - first = false - } else { - n-- - if resp.RespCount != total { - return nil, fmt.Errorf("invalid NODES response count %d (!= %d)", resp.RespCount, total) - } - } - // Check nodes. - nodes, err := checkRecords(resp.Nodes) - if err != nil { - return nil, fmt.Errorf("invalid node in NODES response: %v", err) - } - results = append(results, nodes...) - default: - return nil, fmt.Errorf("expected NODES, got %v", resp) - } - } - return results, nil -} - -// write sends a packet on the given connection. -func (tc *conn) write(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Whoareyou) v5wire.Nonce { - packet, nonce, err := tc.codec.Encode(tc.remote.ID(), tc.remoteAddr.String(), p, challenge) - if err != nil { - panic(fmt.Errorf("can't encode %v packet: %v", p.Name(), err)) - } - if _, err := c.WriteTo(packet, tc.remoteAddr); err != nil { - tc.logf("Can't send %s: %v", p.Name(), err) - } else { - tc.logf(">> %s", p.Name()) - } - return nonce -} - -// read waits for an incoming packet on the given connection. -func (tc *conn) read(c net.PacketConn) v5wire.Packet { - buf := make([]byte, 1280) - if err := c.SetReadDeadline(time.Now().Add(waitTime)); err != nil { - return &readError{err} - } - n, fromAddr, err := c.ReadFrom(buf) - if err != nil { - return &readError{err} - } - _, _, p, err := tc.codec.Decode(buf[:n], fromAddr.String()) - if err != nil { - return &readError{err} - } - tc.logf("<< %s", p.Name()) - return p -} - -// logf prints to the test log. -func (tc *conn) logf(format string, args ...interface{}) { - if tc.log != nil { - tc.log.Logf("(%s) %s", tc.localNode.ID().TerminalString(), fmt.Sprintf(format, args...)) - } -} - -func laddr(c net.PacketConn) *net.UDPAddr { - return c.LocalAddr().(*net.UDPAddr) -} - -func checkRecords(records []*enr.Record) ([]*enode.Node, error) { - nodes := make([]*enode.Node, len(records)) - for i := range records { - n, err := enode.New(enode.ValidSchemes, records[i]) - if err != nil { - return nil, err - } - nodes[i] = n - } - return nodes, nil -} - -func containsUint(ints []uint, x uint) bool { - for i := range ints { - if ints[i] == x { - return true - } - } - return false -} diff --git a/builder/cmd/devp2p/keycmd.go b/builder/cmd/devp2p/keycmd.go deleted file mode 100644 index 98d7bd76a..000000000 --- a/builder/cmd/devp2p/keycmd.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "net" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/urfave/cli/v2" -) - -var ( - keyCommand = &cli.Command{ - Name: "key", - Usage: "Operations on node keys", - Subcommands: []*cli.Command{ - keyGenerateCommand, - keyToIDCommand, - keyToNodeCommand, - keyToRecordCommand, - }, - } - keyGenerateCommand = &cli.Command{ - Name: "generate", - Usage: "Generates node key files", - ArgsUsage: "keyfile", - Action: genkey, - } - keyToIDCommand = &cli.Command{ - Name: "to-id", - Usage: "Creates a node ID from a node key file", - ArgsUsage: "keyfile", - Action: keyToID, - Flags: []cli.Flag{}, - } - keyToNodeCommand = &cli.Command{ - Name: "to-enode", - Usage: "Creates an enode URL from a node key file", - ArgsUsage: "keyfile", - Action: keyToURL, - Flags: []cli.Flag{hostFlag, tcpPortFlag, udpPortFlag}, - } - keyToRecordCommand = &cli.Command{ - Name: "to-enr", - Usage: "Creates an ENR from a node key file", - ArgsUsage: "keyfile", - Action: keyToRecord, - Flags: []cli.Flag{hostFlag, tcpPortFlag, udpPortFlag}, - } -) - -var ( - hostFlag = &cli.StringFlag{ - Name: "ip", - Usage: "IP address of the node", - Value: "127.0.0.1", - } - tcpPortFlag = &cli.IntFlag{ - Name: "tcp", - Usage: "TCP port of the node", - Value: 30303, - } - udpPortFlag = &cli.IntFlag{ - Name: "udp", - Usage: "UDP port of the node", - Value: 30303, - } -) - -func genkey(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return errors.New("need key file as argument") - } - file := ctx.Args().Get(0) - - key, err := crypto.GenerateKey() - if err != nil { - return fmt.Errorf("could not generate key: %v", err) - } - return crypto.SaveECDSA(file, key) -} - -func keyToID(ctx *cli.Context) error { - n, err := makeRecord(ctx) - if err != nil { - return err - } - fmt.Println(n.ID()) - return nil -} - -func keyToURL(ctx *cli.Context) error { - n, err := makeRecord(ctx) - if err != nil { - return err - } - fmt.Println(n.URLv4()) - return nil -} - -func keyToRecord(ctx *cli.Context) error { - n, err := makeRecord(ctx) - if err != nil { - return err - } - fmt.Println(n.String()) - return nil -} - -func makeRecord(ctx *cli.Context) (*enode.Node, error) { - if ctx.NArg() != 1 { - return nil, errors.New("need key file as argument") - } - - var ( - file = ctx.Args().Get(0) - host = ctx.String(hostFlag.Name) - tcp = ctx.Int(tcpPortFlag.Name) - udp = ctx.Int(udpPortFlag.Name) - ) - key, err := crypto.LoadECDSA(file) - if err != nil { - return nil, err - } - - var r enr.Record - if host != "" { - ip := net.ParseIP(host) - if ip == nil { - return nil, fmt.Errorf("invalid IP address %q", host) - } - r.Set(enr.IP(ip)) - } - if udp != 0 { - r.Set(enr.UDP(udp)) - } - if tcp != 0 { - r.Set(enr.TCP(tcp)) - } - - if err := enode.SignV4(&r, key); err != nil { - return nil, err - } - return enode.New(enode.ValidSchemes, &r) -} diff --git a/builder/cmd/devp2p/main.go b/builder/cmd/devp2p/main.go deleted file mode 100644 index 8461a8b9b..000000000 --- a/builder/cmd/devp2p/main.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - - "github.com/ethereum/go-ethereum/internal/debug" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/urfave/cli/v2" -) - -var app = flags.NewApp("go-ethereum devp2p tool") - -func init() { - app.Flags = append(app.Flags, debug.Flags...) - app.Before = func(ctx *cli.Context) error { - flags.MigrateGlobalFlags(ctx) - return debug.Setup(ctx) - } - app.After = func(ctx *cli.Context) error { - debug.Exit() - return nil - } - app.CommandNotFound = func(ctx *cli.Context, cmd string) { - fmt.Fprintf(os.Stderr, "No such command: %s\n", cmd) - os.Exit(1) - } - - // Add subcommands. - app.Commands = []*cli.Command{ - enrdumpCommand, - keyCommand, - discv4Command, - discv5Command, - dnsCommand, - nodesetCommand, - rlpxCommand, - } -} - -func main() { - exit(app.Run(os.Args)) -} - -// commandHasFlag returns true if the current command supports the given flag. -func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool { - names := flag.Names() - set := make(map[string]struct{}, len(names)) - for _, name := range names { - set[name] = struct{}{} - } - for _, fn := range ctx.FlagNames() { - if _, ok := set[fn]; ok { - return true - } - } - return false -} - -// getNodeArg handles the common case of a single node descriptor argument. -func getNodeArg(ctx *cli.Context) *enode.Node { - if ctx.NArg() < 1 { - exit("missing node as command-line argument") - } - n, err := parseNode(ctx.Args().First()) - if err != nil { - exit(err) - } - return n -} - -func exit(err interface{}) { - if err == nil { - os.Exit(0) - } - fmt.Fprintln(os.Stderr, err) - os.Exit(1) -} diff --git a/builder/cmd/devp2p/nodeset.go b/builder/cmd/devp2p/nodeset.go deleted file mode 100644 index 7360dc5bc..000000000 --- a/builder/cmd/devp2p/nodeset.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/p2p/enode" - "golang.org/x/exp/slices" -) - -const jsonIndent = " " - -// nodeSet is the nodes.json file format. It holds a set of node records -// as a JSON object. -type nodeSet map[enode.ID]nodeJSON - -type nodeJSON struct { - Seq uint64 `json:"seq"` - N *enode.Node `json:"record"` - - // The score tracks how many liveness checks were performed. It is incremented by one - // every time the node passes a check, and halved every time it doesn't. - Score int `json:"score,omitempty"` - // These two track the time of last successful contact. - FirstResponse time.Time `json:"firstResponse,omitempty"` - LastResponse time.Time `json:"lastResponse,omitempty"` - // This one tracks the time of our last attempt to contact the node. - LastCheck time.Time `json:"lastCheck,omitempty"` -} - -func loadNodesJSON(file string) nodeSet { - var nodes nodeSet - if err := common.LoadJSON(file, &nodes); err != nil { - exit(err) - } - return nodes -} - -func writeNodesJSON(file string, nodes nodeSet) { - nodesJSON, err := json.MarshalIndent(nodes, "", jsonIndent) - if err != nil { - exit(err) - } - if file == "-" { - os.Stdout.Write(nodesJSON) - return - } - if err := os.WriteFile(file, nodesJSON, 0644); err != nil { - exit(err) - } -} - -// nodes returns the node records contained in the set. -func (ns nodeSet) nodes() []*enode.Node { - result := make([]*enode.Node, 0, len(ns)) - for _, n := range ns { - result = append(result, n.N) - } - // Sort by ID. - slices.SortFunc(result, func(a, b *enode.Node) int { - return bytes.Compare(a.ID().Bytes(), b.ID().Bytes()) - }) - return result -} - -// add ensures the given nodes are present in the set. -func (ns nodeSet) add(nodes ...*enode.Node) { - for _, n := range nodes { - v := ns[n.ID()] - v.N = n - v.Seq = n.Seq() - ns[n.ID()] = v - } -} - -// topN returns the top n nodes by score as a new set. -func (ns nodeSet) topN(n int) nodeSet { - if n >= len(ns) { - return ns - } - - byscore := make([]nodeJSON, 0, len(ns)) - for _, v := range ns { - byscore = append(byscore, v) - } - slices.SortFunc(byscore, func(a, b nodeJSON) int { - if a.Score > b.Score { - return -1 - } - if a.Score < b.Score { - return 1 - } - return 0 - }) - result := make(nodeSet, n) - for _, v := range byscore[:n] { - result[v.N.ID()] = v - } - return result -} - -// verify performs integrity checks on the node set. -func (ns nodeSet) verify() error { - for id, n := range ns { - if n.N.ID() != id { - return fmt.Errorf("invalid node %v: ID does not match ID %v in record", id, n.N.ID()) - } - if n.N.Seq() != n.Seq { - return fmt.Errorf("invalid node %v: 'seq' does not match seq %d from record", id, n.N.Seq()) - } - } - return nil -} diff --git a/builder/cmd/devp2p/nodesetcmd.go b/builder/cmd/devp2p/nodesetcmd.go deleted file mode 100644 index 6fbc185ad..000000000 --- a/builder/cmd/devp2p/nodesetcmd.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "net" - "sort" - "strconv" - "strings" - "time" - - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/urfave/cli/v2" -) - -var ( - nodesetCommand = &cli.Command{ - Name: "nodeset", - Usage: "Node set tools", - Subcommands: []*cli.Command{ - nodesetInfoCommand, - nodesetFilterCommand, - }, - } - nodesetInfoCommand = &cli.Command{ - Name: "info", - Usage: "Shows statistics about a node set", - Action: nodesetInfo, - ArgsUsage: "", - } - nodesetFilterCommand = &cli.Command{ - Name: "filter", - Usage: "Filters a node set", - Action: nodesetFilter, - ArgsUsage: " filters..", - - SkipFlagParsing: true, - } -) - -func nodesetInfo(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need nodes file as argument") - } - - ns := loadNodesJSON(ctx.Args().First()) - fmt.Printf("Set contains %d nodes.\n", len(ns)) - showAttributeCounts(ns) - return nil -} - -// showAttributeCounts prints the distribution of ENR attributes in a node set. -func showAttributeCounts(ns nodeSet) { - attrcount := make(map[string]int) - var attrlist []interface{} - for _, n := range ns { - r := n.N.Record() - attrlist = r.AppendElements(attrlist[:0])[1:] - for i := 0; i < len(attrlist); i += 2 { - key := attrlist[i].(string) - attrcount[key]++ - } - } - - var keys []string - var maxlength int - for key := range attrcount { - keys = append(keys, key) - if len(key) > maxlength { - maxlength = len(key) - } - } - sort.Strings(keys) - fmt.Println("ENR attribute counts:") - for _, key := range keys { - fmt.Printf("%s%s: %d\n", strings.Repeat(" ", maxlength-len(key)+1), key, attrcount[key]) - } -} - -func nodesetFilter(ctx *cli.Context) error { - if ctx.NArg() < 1 { - return errors.New("need nodes file as argument") - } - // Parse -limit. - limit, err := parseFilterLimit(ctx.Args().Tail()) - if err != nil { - return err - } - // Parse the filters. - filter, err := andFilter(ctx.Args().Tail()) - if err != nil { - return err - } - - // Load nodes and apply filters. - ns := loadNodesJSON(ctx.Args().First()) - result := make(nodeSet) - for id, n := range ns { - if filter(n) { - result[id] = n - } - } - if limit >= 0 { - result = result.topN(limit) - } - writeNodesJSON("-", result) - return nil -} - -type nodeFilter func(nodeJSON) bool - -type nodeFilterC struct { - narg int - fn func([]string) (nodeFilter, error) -} - -var filterFlags = map[string]nodeFilterC{ - "-limit": {1, trueFilter}, // needed to skip over -limit - "-ip": {1, ipFilter}, - "-min-age": {1, minAgeFilter}, - "-eth-network": {1, ethFilter}, - "-les-server": {0, lesFilter}, - "-snap": {0, snapFilter}, -} - -// parseFilters parses nodeFilters from args. -func parseFilters(args []string) ([]nodeFilter, error) { - var filters []nodeFilter - for len(args) > 0 { - fc, ok := filterFlags[args[0]] - if !ok { - return nil, fmt.Errorf("invalid filter %q", args[0]) - } - if len(args)-1 < fc.narg { - return nil, fmt.Errorf("filter %q wants %d arguments, have %d", args[0], fc.narg, len(args)-1) - } - filter, err := fc.fn(args[1 : 1+fc.narg]) - if err != nil { - return nil, fmt.Errorf("%s: %v", args[0], err) - } - filters = append(filters, filter) - args = args[1+fc.narg:] - } - return filters, nil -} - -// parseFilterLimit parses the -limit option in args. It returns -1 if there is no limit. -func parseFilterLimit(args []string) (int, error) { - limit := -1 - for i, arg := range args { - if arg == "-limit" { - if i == len(args)-1 { - return -1, errors.New("-limit requires an argument") - } - n, err := strconv.Atoi(args[i+1]) - if err != nil { - return -1, fmt.Errorf("invalid -limit %q", args[i+1]) - } - limit = n - } - } - return limit, nil -} - -// andFilter parses node filters in args and returns a single filter that requires all -// of them to match. -func andFilter(args []string) (nodeFilter, error) { - checks, err := parseFilters(args) - if err != nil { - return nil, err - } - f := func(n nodeJSON) bool { - for _, filter := range checks { - if !filter(n) { - return false - } - } - return true - } - return f, nil -} - -func trueFilter(args []string) (nodeFilter, error) { - return func(n nodeJSON) bool { return true }, nil -} - -func ipFilter(args []string) (nodeFilter, error) { - _, cidr, err := net.ParseCIDR(args[0]) - if err != nil { - return nil, err - } - f := func(n nodeJSON) bool { return cidr.Contains(n.N.IP()) } - return f, nil -} - -func minAgeFilter(args []string) (nodeFilter, error) { - minage, err := time.ParseDuration(args[0]) - if err != nil { - return nil, err - } - f := func(n nodeJSON) bool { - age := n.LastResponse.Sub(n.FirstResponse) - return age >= minage - } - return f, nil -} - -func ethFilter(args []string) (nodeFilter, error) { - var filter forkid.Filter - switch args[0] { - case "mainnet": - filter = forkid.NewStaticFilter(params.MainnetChainConfig, core.DefaultGenesisBlock().ToBlock()) - case "goerli": - filter = forkid.NewStaticFilter(params.GoerliChainConfig, core.DefaultGoerliGenesisBlock().ToBlock()) - case "sepolia": - filter = forkid.NewStaticFilter(params.SepoliaChainConfig, core.DefaultSepoliaGenesisBlock().ToBlock()) - case "holesky": - filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock()) - default: - return nil, fmt.Errorf("unknown network %q", args[0]) - } - - f := func(n nodeJSON) bool { - var eth struct { - ForkID forkid.ID - Tail []rlp.RawValue `rlp:"tail"` - } - if n.N.Load(enr.WithEntry("eth", ð)) != nil { - return false - } - return filter(eth.ForkID) == nil - } - return f, nil -} - -func lesFilter(args []string) (nodeFilter, error) { - f := func(n nodeJSON) bool { - var les struct { - Tail []rlp.RawValue `rlp:"tail"` - } - return n.N.Load(enr.WithEntry("les", &les)) == nil - } - return f, nil -} - -func snapFilter(args []string) (nodeFilter, error) { - f := func(n nodeJSON) bool { - var snap struct { - Tail []rlp.RawValue `rlp:"tail"` - } - return n.N.Load(enr.WithEntry("snap", &snap)) == nil - } - return f, nil -} diff --git a/builder/cmd/devp2p/rlpxcmd.go b/builder/cmd/devp2p/rlpxcmd.go deleted file mode 100644 index aa7d06581..000000000 --- a/builder/cmd/devp2p/rlpxcmd.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "net" - - "github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/rlpx" - "github.com/ethereum/go-ethereum/rlp" - "github.com/urfave/cli/v2" -) - -var ( - rlpxCommand = &cli.Command{ - Name: "rlpx", - Usage: "RLPx Commands", - Subcommands: []*cli.Command{ - rlpxPingCommand, - rlpxEthTestCommand, - rlpxSnapTestCommand, - }, - } - rlpxPingCommand = &cli.Command{ - Name: "ping", - Usage: "ping ", - Action: rlpxPing, - } - rlpxEthTestCommand = &cli.Command{ - Name: "eth-test", - Usage: "Runs eth protocol tests against a node", - ArgsUsage: "", - Action: rlpxEthTest, - Flags: []cli.Flag{ - testPatternFlag, - testTAPFlag, - testChainDirFlag, - testNodeFlag, - testNodeJWTFlag, - testNodeEngineFlag, - }, - } - rlpxSnapTestCommand = &cli.Command{ - Name: "snap-test", - Usage: "Runs snap protocol tests against a node", - ArgsUsage: "", - Action: rlpxSnapTest, - Flags: []cli.Flag{ - testPatternFlag, - testTAPFlag, - testChainDirFlag, - testNodeFlag, - testNodeJWTFlag, - testNodeEngineFlag, - }, - } -) - -func rlpxPing(ctx *cli.Context) error { - n := getNodeArg(ctx) - fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", n.IP(), n.TCP())) - if err != nil { - return err - } - conn := rlpx.NewConn(fd, n.Pubkey()) - ourKey, _ := crypto.GenerateKey() - _, err = conn.Handshake(ourKey) - if err != nil { - return err - } - code, data, _, err := conn.Read() - if err != nil { - return err - } - switch code { - case 0: - var h ethtest.Hello - if err := rlp.DecodeBytes(data, &h); err != nil { - return fmt.Errorf("invalid handshake: %v", err) - } - fmt.Printf("%+v\n", h) - case 1: - var msg []p2p.DiscReason - if rlp.DecodeBytes(data, &msg); len(msg) == 0 { - return errors.New("invalid disconnect message") - } - return fmt.Errorf("received disconnect message: %v", msg[0]) - default: - return fmt.Errorf("invalid message code %d, expected handshake (code zero)", code) - } - return nil -} - -// rlpxEthTest runs the eth protocol test suite. -func rlpxEthTest(ctx *cli.Context) error { - p := cliTestParams(ctx) - suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt) - if err != nil { - exit(err) - } - return runTests(ctx, suite.EthTests()) -} - -// rlpxSnapTest runs the snap protocol test suite. -func rlpxSnapTest(ctx *cli.Context) error { - p := cliTestParams(ctx) - suite, err := ethtest.NewSuite(p.node, p.chainDir, p.engineAPI, p.jwt) - if err != nil { - exit(err) - } - return runTests(ctx, suite.SnapTests()) -} - -type testParams struct { - node *enode.Node - engineAPI string - jwt string - chainDir string -} - -func cliTestParams(ctx *cli.Context) *testParams { - nodeStr := ctx.String(testNodeFlag.Name) - if nodeStr == "" { - exit(fmt.Errorf("missing -%s", testNodeFlag.Name)) - } - node, err := parseNode(nodeStr) - if err != nil { - exit(err) - } - p := testParams{ - node: node, - engineAPI: ctx.String(testNodeEngineFlag.Name), - jwt: ctx.String(testNodeJWTFlag.Name), - chainDir: ctx.String(testChainDirFlag.Name), - } - if p.engineAPI == "" { - exit(fmt.Errorf("missing -%s", testNodeEngineFlag.Name)) - } - if p.jwt == "" { - exit(fmt.Errorf("missing -%s", testNodeJWTFlag.Name)) - } - if p.chainDir == "" { - exit(fmt.Errorf("missing -%s", testChainDirFlag.Name)) - } - return &p -} diff --git a/builder/cmd/devp2p/runtest.go b/builder/cmd/devp2p/runtest.go deleted file mode 100644 index 7e3723c64..000000000 --- a/builder/cmd/devp2p/runtest.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "os" - - "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/internal/utesting" - "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli/v2" -) - -var ( - testPatternFlag = &cli.StringFlag{ - Name: "run", - Usage: "Pattern of test suite(s) to run", - Category: flags.TestingCategory, - } - testTAPFlag = &cli.BoolFlag{ - Name: "tap", - Usage: "Output test results in TAP format", - Category: flags.TestingCategory, - } - - // for eth/snap tests - testChainDirFlag = &cli.StringFlag{ - Name: "chain", - Usage: "Test chain directory (required)", - Category: flags.TestingCategory, - } - testNodeFlag = &cli.StringFlag{ - Name: "node", - Usage: "Peer-to-Peer endpoint (ENR) of the test node (required)", - Category: flags.TestingCategory, - } - testNodeJWTFlag = &cli.StringFlag{ - Name: "jwtsecret", - Usage: "JWT secret for the engine API of the test node (required)", - Category: flags.TestingCategory, - Value: "0x7365637265747365637265747365637265747365637265747365637265747365", - } - testNodeEngineFlag = &cli.StringFlag{ - Name: "engineapi", - Usage: "Engine API endpoint of the test node (required)", - Category: flags.TestingCategory, - } - - // These two are specific to the discovery tests. - testListen1Flag = &cli.StringFlag{ - Name: "listen1", - Usage: "IP address of the first tester", - Value: v4test.Listen1, - Category: flags.TestingCategory, - } - testListen2Flag = &cli.StringFlag{ - Name: "listen2", - Usage: "IP address of the second tester", - Value: v4test.Listen2, - Category: flags.TestingCategory, - } -) - -func runTests(ctx *cli.Context, tests []utesting.Test) error { - // Filter test cases. - if ctx.IsSet(testPatternFlag.Name) { - tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name)) - } - // Disable logging unless explicitly enabled. - if !ctx.IsSet("verbosity") && !ctx.IsSet("vmodule") { - log.SetDefault(log.NewLogger(log.DiscardHandler())) - } - // Run the tests. - var run = utesting.RunTests - if ctx.Bool(testTAPFlag.Name) { - run = utesting.RunTAP - } - results := run(tests, os.Stdout) - if utesting.CountFailures(results) > 0 { - os.Exit(1) - } - return nil -} diff --git a/builder/cmd/era/main.go b/builder/cmd/era/main.go deleted file mode 100644 index e27d8ccec..000000000 --- a/builder/cmd/era/main.go +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "fmt" - "math/big" - "os" - "path" - "strconv" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/urfave/cli/v2" -) - -var app = flags.NewApp("go-ethereum era tool") - -var ( - dirFlag = &cli.StringFlag{ - Name: "dir", - Usage: "directory storing all relevant era1 files", - Value: "eras", - } - networkFlag = &cli.StringFlag{ - Name: "network", - Usage: "network name associated with era1 files", - Value: "mainnet", - } - eraSizeFlag = &cli.IntFlag{ - Name: "size", - Usage: "number of blocks per era", - Value: era.MaxEra1Size, - } - txsFlag = &cli.BoolFlag{ - Name: "txs", - Usage: "print full transaction values", - } -) - -var ( - blockCommand = &cli.Command{ - Name: "block", - Usage: "get block data", - ArgsUsage: "", - Action: block, - Flags: []cli.Flag{ - txsFlag, - }, - } - infoCommand = &cli.Command{ - Name: "info", - ArgsUsage: "", - Usage: "get epoch information", - Action: info, - } - verifyCommand = &cli.Command{ - Name: "verify", - ArgsUsage: "", - Usage: "verifies each era1 against expected accumulator root", - Action: verify, - } -) - -func init() { - app.Commands = []*cli.Command{ - blockCommand, - infoCommand, - verifyCommand, - } - app.Flags = []cli.Flag{ - dirFlag, - networkFlag, - eraSizeFlag, - } -} - -func main() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) - os.Exit(1) - } -} - -// block prints the specified block from an era1 store. -func block(ctx *cli.Context) error { - num, err := strconv.ParseUint(ctx.Args().First(), 10, 64) - if err != nil { - return fmt.Errorf("invalid block number: %w", err) - } - e, err := open(ctx, num/uint64(ctx.Int(eraSizeFlag.Name))) - if err != nil { - return fmt.Errorf("error opening era1: %w", err) - } - defer e.Close() - // Read block with number. - block, err := e.GetBlockByNumber(num) - if err != nil { - return fmt.Errorf("error reading block %d: %w", num, err) - } - // Convert block to JSON and print. - val := ethapi.RPCMarshalBlock(block, ctx.Bool(txsFlag.Name), ctx.Bool(txsFlag.Name), params.MainnetChainConfig) - b, err := json.MarshalIndent(val, "", " ") - if err != nil { - return fmt.Errorf("error marshaling json: %w", err) - } - fmt.Println(string(b)) - return nil -} - -// info prints some high-level information about the era1 file. -func info(ctx *cli.Context) error { - epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64) - if err != nil { - return fmt.Errorf("invalid epoch number: %w", err) - } - e, err := open(ctx, epoch) - if err != nil { - return err - } - defer e.Close() - acc, err := e.Accumulator() - if err != nil { - return fmt.Errorf("error reading accumulator: %w", err) - } - td, err := e.InitialTD() - if err != nil { - return fmt.Errorf("error reading total difficulty: %w", err) - } - info := struct { - Accumulator common.Hash `json:"accumulator"` - TotalDifficulty *big.Int `json:"totalDifficulty"` - StartBlock uint64 `json:"startBlock"` - Count uint64 `json:"count"` - }{ - acc, td, e.Start(), e.Count(), - } - b, _ := json.MarshalIndent(info, "", " ") - fmt.Println(string(b)) - return nil -} - -// open opens an era1 file at a certain epoch. -func open(ctx *cli.Context, epoch uint64) (*era.Era, error) { - var ( - dir = ctx.String(dirFlag.Name) - network = ctx.String(networkFlag.Name) - ) - entries, err := era.ReadDir(dir, network) - if err != nil { - return nil, fmt.Errorf("error reading era dir: %w", err) - } - if epoch >= uint64(len(entries)) { - return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch) - } - return era.Open(path.Join(dir, entries[epoch])) -} - -// verify checks each era1 file in a directory to ensure it is well-formed and -// that the accumulator matches the expected value. -func verify(ctx *cli.Context) error { - if ctx.Args().Len() != 1 { - return fmt.Errorf("missing accumulators file") - } - - roots, err := readHashes(ctx.Args().First()) - if err != nil { - return fmt.Errorf("unable to read expected roots file: %w", err) - } - - var ( - dir = ctx.String(dirFlag.Name) - network = ctx.String(networkFlag.Name) - start = time.Now() - reported = time.Now() - ) - - entries, err := era.ReadDir(dir, network) - if err != nil { - return fmt.Errorf("error reading %s: %w", dir, err) - } - - if len(entries) != len(roots) { - return fmt.Errorf("number of era1 files should match the number of accumulator hashes") - } - - // Verify each epoch matches the expected root. - for i, want := range roots { - // Wrap in function so defers don't stack. - err := func() error { - name := entries[i] - e, err := era.Open(path.Join(dir, name)) - if err != nil { - return fmt.Errorf("error opening era1 file %s: %w", name, err) - } - defer e.Close() - // Read accumulator and check against expected. - if got, err := e.Accumulator(); err != nil { - return fmt.Errorf("error retrieving accumulator for %s: %w", name, err) - } else if got != want { - return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want) - } - // Recompute accumulator. - if err := checkAccumulator(e); err != nil { - return fmt.Errorf("error verify era1 file %s: %w", name, err) - } - // Give the user some feedback that something is happening. - if time.Since(reported) >= 8*time.Second { - fmt.Printf("Verifying Era1 files \t\t verified=%d,\t elapsed=%s\n", i, common.PrettyDuration(time.Since(start))) - reported = time.Now() - } - return nil - }() - if err != nil { - return err - } - } - - return nil -} - -// checkAccumulator verifies the accumulator matches the data in the Era. -func checkAccumulator(e *era.Era) error { - var ( - err error - want common.Hash - td *big.Int - tds = make([]*big.Int, 0) - hashes = make([]common.Hash, 0) - ) - if want, err = e.Accumulator(); err != nil { - return fmt.Errorf("error reading accumulator: %w", err) - } - if td, err = e.InitialTD(); err != nil { - return fmt.Errorf("error reading total difficulty: %w", err) - } - it, err := era.NewIterator(e) - if err != nil { - return fmt.Errorf("error making era iterator: %w", err) - } - // To fully verify an era the following attributes must be checked: - // 1) the block index is constructed correctly - // 2) the tx root matches the value in the block - // 3) the receipts root matches the value in the block - // 4) the starting total difficulty value is correct - // 5) the accumulator is correct by recomputing it locally, which verifies - // the blocks are all correct (via hash) - // - // The attributes 1), 2), and 3) are checked for each block. 4) and 5) require - // accumulation across the entire set and are verified at the end. - for it.Next() { - // 1) next() walks the block index, so we're able to implicitly verify it. - if it.Error() != nil { - return fmt.Errorf("error reading block %d: %w", it.Number(), err) - } - block, receipts, err := it.BlockAndReceipts() - if it.Error() != nil { - return fmt.Errorf("error reading block %d: %w", it.Number(), err) - } - // 2) recompute tx root and verify against header. - tr := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)) - if tr != block.TxHash() { - return fmt.Errorf("tx root in block %d mismatch: want %s, got %s", block.NumberU64(), block.TxHash(), tr) - } - // 3) recompute receipt root and check value against block. - rr := types.DeriveSha(receipts, trie.NewStackTrie(nil)) - if rr != block.ReceiptHash() { - return fmt.Errorf("receipt root in block %d mismatch: want %s, got %s", block.NumberU64(), block.ReceiptHash(), rr) - } - hashes = append(hashes, block.Hash()) - td.Add(td, block.Difficulty()) - tds = append(tds, new(big.Int).Set(td)) - } - // 4+5) Verify accumulator and total difficulty. - got, err := era.ComputeAccumulator(hashes, tds) - if err != nil { - return fmt.Errorf("error computing accumulator: %w", err) - } - if got != want { - return fmt.Errorf("expected accumulator root does not match calculated: got %s, want %s", got, want) - } - return nil -} - -// readHashes reads a file of newline-delimited hashes. -func readHashes(f string) ([]common.Hash, error) { - b, err := os.ReadFile(f) - if err != nil { - return nil, fmt.Errorf("unable to open accumulators file") - } - s := strings.Split(string(b), "\n") - // Remove empty last element, if present. - if s[len(s)-1] == "" { - s = s[:len(s)-1] - } - // Convert to hashes. - r := make([]common.Hash, len(s)) - for i := range s { - r[i] = common.HexToHash(s[i]) - } - return r, nil -} diff --git a/builder/cmd/ethkey/README.md b/builder/cmd/ethkey/README.md deleted file mode 100644 index bfddd1467..000000000 --- a/builder/cmd/ethkey/README.md +++ /dev/null @@ -1,53 +0,0 @@ -ethkey -====== - -ethkey is a simple command-line tool for working with Ethereum keyfiles. - - -# Usage - -### `ethkey generate` - -Generate a new keyfile. -If you want to use an existing private key to use in the keyfile, it can be -specified by setting `--privatekey` with the location of the file containing the -private key. - - -### `ethkey inspect ` - -Print various information about the keyfile. -Private key information can be printed by using the `--private` flag; -make sure to use this feature with great caution! - - -### `ethkey signmessage ` - -Sign the message with a keyfile. -It is possible to refer to a file containing the message. -To sign a message contained in a file, use the `--msgfile` flag. - - -### `ethkey verifymessage
` - -Verify the signature of the message. -It is possible to refer to a file containing the message. -To sign a message contained in a file, use the --msgfile flag. - - -### `ethkey changepassword ` - -Change the password of a keyfile. -use the `--newpasswordfile` to point to the new password file. - - -## Passwords - -For every command that uses a keyfile, you will be prompted to provide the -password for decrypting the keyfile. To avoid this message, it is possible -to pass the password by using the `--passwordfile` flag pointing to a file that -contains the password. - -## JSON - -In case you need to output the result in a JSON format, you shall by using the `--json` flag. diff --git a/builder/cmd/ethkey/changepassword.go b/builder/cmd/ethkey/changepassword.go deleted file mode 100644 index 4298e2b83..000000000 --- a/builder/cmd/ethkey/changepassword.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "strings" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/urfave/cli/v2" -) - -var newPassphraseFlag = &cli.StringFlag{ - Name: "newpasswordfile", - Usage: "the file that contains the new password for the keyfile", -} - -var commandChangePassphrase = &cli.Command{ - Name: "changepassword", - Usage: "change the password on a keyfile", - ArgsUsage: "", - Description: ` -Change the password of a keyfile.`, - Flags: []cli.Flag{ - passphraseFlag, - newPassphraseFlag, - }, - Action: func(ctx *cli.Context) error { - keyfilepath := ctx.Args().First() - - // Read key from file. - keyjson, err := os.ReadFile(keyfilepath) - if err != nil { - utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) - } - - // Decrypt key with passphrase. - passphrase := getPassphrase(ctx, false) - key, err := keystore.DecryptKey(keyjson, passphrase) - if err != nil { - utils.Fatalf("Error decrypting key: %v", err) - } - - // Get a new passphrase. - fmt.Println("Please provide a new password") - var newPhrase string - if passFile := ctx.String(newPassphraseFlag.Name); passFile != "" { - content, err := os.ReadFile(passFile) - if err != nil { - utils.Fatalf("Failed to read new password file '%s': %v", passFile, err) - } - newPhrase = strings.TrimRight(string(content), "\r\n") - } else { - newPhrase = utils.GetPassPhrase("", true) - } - - // Encrypt the key with the new passphrase. - newJson, err := keystore.EncryptKey(key, newPhrase, keystore.StandardScryptN, keystore.StandardScryptP) - if err != nil { - utils.Fatalf("Error encrypting with new password: %v", err) - } - - // Then write the new keyfile in place of the old one. - if err := os.WriteFile(keyfilepath, newJson, 0600); err != nil { - utils.Fatalf("Error writing new keyfile to disk: %v", err) - } - - // Don't print anything. Just return successfully, - // producing a positive exit code. - return nil - }, -} diff --git a/builder/cmd/ethkey/generate.go b/builder/cmd/ethkey/generate.go deleted file mode 100644 index 60d8b3c77..000000000 --- a/builder/cmd/ethkey/generate.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "crypto/ecdsa" - "fmt" - "os" - "path/filepath" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/crypto" - "github.com/google/uuid" - "github.com/urfave/cli/v2" -) - -type outputGenerate struct { - Address string - AddressEIP55 string -} - -var ( - privateKeyFlag = &cli.StringFlag{ - Name: "privatekey", - Usage: "file containing a raw private key to encrypt", - } - lightKDFFlag = &cli.BoolFlag{ - Name: "lightkdf", - Usage: "use less secure scrypt parameters", - } -) - -var commandGenerate = &cli.Command{ - Name: "generate", - Usage: "generate new keyfile", - ArgsUsage: "[ ]", - Description: ` -Generate a new keyfile. - -If you want to encrypt an existing private key, it can be specified by setting ---privatekey with the location of the file containing the private key. -`, - Flags: []cli.Flag{ - passphraseFlag, - jsonFlag, - privateKeyFlag, - lightKDFFlag, - }, - Action: func(ctx *cli.Context) error { - // Check if keyfile path given and make sure it doesn't already exist. - keyfilepath := ctx.Args().First() - if keyfilepath == "" { - keyfilepath = defaultKeyfileName - } - if _, err := os.Stat(keyfilepath); err == nil { - utils.Fatalf("Keyfile already exists at %s.", keyfilepath) - } else if !os.IsNotExist(err) { - utils.Fatalf("Error checking if keyfile exists: %v", err) - } - - var privateKey *ecdsa.PrivateKey - var err error - if file := ctx.String(privateKeyFlag.Name); file != "" { - // Load private key from file. - privateKey, err = crypto.LoadECDSA(file) - if err != nil { - utils.Fatalf("Can't load private key: %v", err) - } - } else { - // If not loaded, generate random. - privateKey, err = crypto.GenerateKey() - if err != nil { - utils.Fatalf("Failed to generate random private key: %v", err) - } - } - - // Create the keyfile object with a random UUID. - UUID, err := uuid.NewRandom() - if err != nil { - utils.Fatalf("Failed to generate random uuid: %v", err) - } - key := &keystore.Key{ - Id: UUID, - Address: crypto.PubkeyToAddress(privateKey.PublicKey), - PrivateKey: privateKey, - } - - // Encrypt key with passphrase. - passphrase := getPassphrase(ctx, true) - scryptN, scryptP := keystore.StandardScryptN, keystore.StandardScryptP - if ctx.Bool(lightKDFFlag.Name) { - scryptN, scryptP = keystore.LightScryptN, keystore.LightScryptP - } - keyjson, err := keystore.EncryptKey(key, passphrase, scryptN, scryptP) - if err != nil { - utils.Fatalf("Error encrypting key: %v", err) - } - - // Store the file to disk. - if err := os.MkdirAll(filepath.Dir(keyfilepath), 0700); err != nil { - utils.Fatalf("Could not create directory %s", filepath.Dir(keyfilepath)) - } - if err := os.WriteFile(keyfilepath, keyjson, 0600); err != nil { - utils.Fatalf("Failed to write keyfile to %s: %v", keyfilepath, err) - } - - // Output some information. - out := outputGenerate{ - Address: key.Address.Hex(), - } - if ctx.Bool(jsonFlag.Name) { - mustPrintJSON(out) - } else { - fmt.Println("Address:", out.Address) - } - return nil - }, -} diff --git a/builder/cmd/ethkey/inspect.go b/builder/cmd/ethkey/inspect.go deleted file mode 100644 index 29b1c13e8..000000000 --- a/builder/cmd/ethkey/inspect.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/hex" - "fmt" - "os" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/crypto" - "github.com/urfave/cli/v2" -) - -type outputInspect struct { - Address string - PublicKey string - PrivateKey string -} - -var ( - privateFlag = &cli.BoolFlag{ - Name: "private", - Usage: "include the private key in the output", - } -) - -var commandInspect = &cli.Command{ - Name: "inspect", - Usage: "inspect a keyfile", - ArgsUsage: "", - Description: ` -Print various information about the keyfile. - -Private key information can be printed by using the --private flag; -make sure to use this feature with great caution!`, - Flags: []cli.Flag{ - passphraseFlag, - jsonFlag, - privateFlag, - }, - Action: func(ctx *cli.Context) error { - keyfilepath := ctx.Args().First() - - // Read key from file. - keyjson, err := os.ReadFile(keyfilepath) - if err != nil { - utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) - } - - // Decrypt key with passphrase. - passphrase := getPassphrase(ctx, false) - key, err := keystore.DecryptKey(keyjson, passphrase) - if err != nil { - utils.Fatalf("Error decrypting key: %v", err) - } - - // Output all relevant information we can retrieve. - showPrivate := ctx.Bool(privateFlag.Name) - out := outputInspect{ - Address: key.Address.Hex(), - PublicKey: hex.EncodeToString( - crypto.FromECDSAPub(&key.PrivateKey.PublicKey)), - } - if showPrivate { - out.PrivateKey = hex.EncodeToString(crypto.FromECDSA(key.PrivateKey)) - } - - if ctx.Bool(jsonFlag.Name) { - mustPrintJSON(out) - } else { - fmt.Println("Address: ", out.Address) - fmt.Println("Public key: ", out.PublicKey) - if showPrivate { - fmt.Println("Private key: ", out.PrivateKey) - } - } - return nil - }, -} diff --git a/builder/cmd/ethkey/main.go b/builder/cmd/ethkey/main.go deleted file mode 100644 index 25c0d104f..000000000 --- a/builder/cmd/ethkey/main.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/urfave/cli/v2" -) - -const ( - defaultKeyfileName = "keyfile.json" -) - -var app *cli.App - -func init() { - app = flags.NewApp("Ethereum key manager") - app.Commands = []*cli.Command{ - commandGenerate, - commandInspect, - commandChangePassphrase, - commandSignMessage, - commandVerifyMessage, - } -} - -// Commonly used command line flags. -var ( - passphraseFlag = &cli.StringFlag{ - Name: "passwordfile", - Usage: "the file that contains the password for the keyfile", - } - jsonFlag = &cli.BoolFlag{ - Name: "json", - Usage: "output JSON instead of human-readable format", - } -) - -func main() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/builder/cmd/ethkey/message.go b/builder/cmd/ethkey/message.go deleted file mode 100644 index 6b8dec03c..000000000 --- a/builder/cmd/ethkey/message.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/hex" - "fmt" - "os" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/urfave/cli/v2" -) - -type outputSign struct { - Signature string -} - -var msgfileFlag = &cli.StringFlag{ - Name: "msgfile", - Usage: "file containing the message to sign/verify", -} - -var commandSignMessage = &cli.Command{ - Name: "signmessage", - Usage: "sign a message", - ArgsUsage: " ", - Description: ` -Sign the message with a keyfile. - -To sign a message contained in a file, use the --msgfile flag. -`, - Flags: []cli.Flag{ - passphraseFlag, - jsonFlag, - msgfileFlag, - }, - Action: func(ctx *cli.Context) error { - message := getMessage(ctx, 1) - - // Load the keyfile. - keyfilepath := ctx.Args().First() - keyjson, err := os.ReadFile(keyfilepath) - if err != nil { - utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err) - } - - // Decrypt key with passphrase. - passphrase := getPassphrase(ctx, false) - key, err := keystore.DecryptKey(keyjson, passphrase) - if err != nil { - utils.Fatalf("Error decrypting key: %v", err) - } - - signature, err := crypto.Sign(accounts.TextHash(message), key.PrivateKey) - if err != nil { - utils.Fatalf("Failed to sign message: %v", err) - } - out := outputSign{Signature: hex.EncodeToString(signature)} - if ctx.Bool(jsonFlag.Name) { - mustPrintJSON(out) - } else { - fmt.Println("Signature:", out.Signature) - } - return nil - }, -} - -type outputVerify struct { - Success bool - RecoveredAddress string - RecoveredPublicKey string -} - -var commandVerifyMessage = &cli.Command{ - Name: "verifymessage", - Usage: "verify the signature of a signed message", - ArgsUsage: "
", - Description: ` -Verify the signature of the message. -It is possible to refer to a file containing the message.`, - Flags: []cli.Flag{ - jsonFlag, - msgfileFlag, - }, - Action: func(ctx *cli.Context) error { - addressStr := ctx.Args().First() - signatureHex := ctx.Args().Get(1) - message := getMessage(ctx, 2) - - if !common.IsHexAddress(addressStr) { - utils.Fatalf("Invalid address: %s", addressStr) - } - address := common.HexToAddress(addressStr) - signature, err := hex.DecodeString(signatureHex) - if err != nil { - utils.Fatalf("Signature encoding is not hexadecimal: %v", err) - } - - recoveredPubkey, err := crypto.SigToPub(accounts.TextHash(message), signature) - if err != nil || recoveredPubkey == nil { - utils.Fatalf("Signature verification failed: %v", err) - } - recoveredPubkeyBytes := crypto.FromECDSAPub(recoveredPubkey) - recoveredAddress := crypto.PubkeyToAddress(*recoveredPubkey) - success := address == recoveredAddress - - out := outputVerify{ - Success: success, - RecoveredPublicKey: hex.EncodeToString(recoveredPubkeyBytes), - RecoveredAddress: recoveredAddress.Hex(), - } - if ctx.Bool(jsonFlag.Name) { - mustPrintJSON(out) - } else { - if out.Success { - fmt.Println("Signature verification successful!") - } else { - fmt.Println("Signature verification failed!") - } - fmt.Println("Recovered public key:", out.RecoveredPublicKey) - fmt.Println("Recovered address:", out.RecoveredAddress) - } - return nil - }, -} - -func getMessage(ctx *cli.Context, msgarg int) []byte { - if file := ctx.String(msgfileFlag.Name); file != "" { - if ctx.NArg() > msgarg { - utils.Fatalf("Can't use --msgfile and message argument at the same time.") - } - msg, err := os.ReadFile(file) - if err != nil { - utils.Fatalf("Can't read message file: %v", err) - } - return msg - } else if ctx.NArg() == msgarg+1 { - return []byte(ctx.Args().Get(msgarg)) - } - utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg()) - return nil -} diff --git a/builder/cmd/ethkey/message_test.go b/builder/cmd/ethkey/message_test.go deleted file mode 100644 index 389bb8c8e..000000000 --- a/builder/cmd/ethkey/message_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "path/filepath" - "testing" -) - -func TestMessageSignVerify(t *testing.T) { - t.Parallel() - tmpdir := t.TempDir() - - keyfile := filepath.Join(tmpdir, "the-keyfile") - message := "test message" - - // Create the key. - generate := runEthkey(t, "generate", "--lightkdf", keyfile) - generate.Expect(` -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -Repeat password: {{.InputLine "foobar"}} -`) - _, matches := generate.ExpectRegexp(`Address: (0x[0-9a-fA-F]{40})\n`) - address := matches[1] - generate.ExpectExit() - - // Sign a message. - sign := runEthkey(t, "signmessage", keyfile, message) - sign.Expect(` -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -`) - _, matches = sign.ExpectRegexp(`Signature: ([0-9a-f]+)\n`) - signature := matches[1] - sign.ExpectExit() - - // Verify the message. - verify := runEthkey(t, "verifymessage", address, signature, message) - _, matches = verify.ExpectRegexp(` -Signature verification successful! -Recovered public key: [0-9a-f]+ -Recovered address: (0x[0-9a-fA-F]{40}) -`) - recovered := matches[1] - verify.ExpectExit() - - if recovered != address { - t.Error("recovered address doesn't match generated key") - } -} diff --git a/builder/cmd/ethkey/run_test.go b/builder/cmd/ethkey/run_test.go deleted file mode 100644 index 73506e5da..000000000 --- a/builder/cmd/ethkey/run_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "testing" - - "github.com/ethereum/go-ethereum/internal/cmdtest" - "github.com/ethereum/go-ethereum/internal/reexec" -) - -type testEthkey struct { - *cmdtest.TestCmd -} - -// spawns ethkey with the given command line args. -func runEthkey(t *testing.T, args ...string) *testEthkey { - tt := new(testEthkey) - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - tt.Run("ethkey-test", args...) - return tt -} - -func TestMain(m *testing.M) { - // Run the app if we've been exec'd as "ethkey-test" in runEthkey. - reexec.Register("ethkey-test", func() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - os.Exit(0) - }) - // check if we have been reexec'd - if reexec.Init() { - return - } - os.Exit(m.Run()) -} diff --git a/builder/cmd/ethkey/utils.go b/builder/cmd/ethkey/utils.go deleted file mode 100644 index 282114508..000000000 --- a/builder/cmd/ethkey/utils.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "fmt" - "os" - "strings" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/urfave/cli/v2" -) - -// getPassphrase obtains a passphrase given by the user. It first checks the -// --passfile command line flag and ultimately prompts the user for a -// passphrase. -func getPassphrase(ctx *cli.Context, confirmation bool) string { - // Look for the --passwordfile flag. - passphraseFile := ctx.String(passphraseFlag.Name) - if passphraseFile != "" { - content, err := os.ReadFile(passphraseFile) - if err != nil { - utils.Fatalf("Failed to read password file '%s': %v", - passphraseFile, err) - } - return strings.TrimRight(string(content), "\r\n") - } - - // Otherwise prompt the user for the passphrase. - return utils.GetPassPhrase("", confirmation) -} - -// mustPrintJSON prints the JSON encoding of the given object and -// exits the program with an error message when the marshaling fails. -func mustPrintJSON(jsonObject interface{}) { - str, err := json.MarshalIndent(jsonObject, "", " ") - if err != nil { - utils.Fatalf("Failed to marshal JSON object: %v", err) - } - fmt.Println(string(str)) -} diff --git a/builder/cmd/evm/README.md b/builder/cmd/evm/README.md deleted file mode 100644 index 25647c18a..000000000 --- a/builder/cmd/evm/README.md +++ /dev/null @@ -1,626 +0,0 @@ -# EVM tool - -The EVM tool provides a few useful subcommands to facilitate testing at the EVM -layer. - -* transition tool (`t8n`) : a stateless state transition utility -* transaction tool (`t9n`) : a transaction validation utility -* block builder tool (`b11r`): a block assembler utility - -## State transition tool (`t8n`) - - -The `evm t8n` tool is a stateless state transition utility. It is a utility -which can - -1. Take a prestate, including - - Accounts, - - Block context information, - - Previous blockshashes (*optional) -2. Apply a set of transactions, -3. Apply a mining-reward (*optional), -4. And generate a post-state, including - - State root, transaction root, receipt root, - - Information about rejected transactions, - - Optionally: a full or partial post-state dump - -### Specification - -The idea is to specify the behaviour of this binary very _strict_, so that other -node implementors can build replicas based on their own state-machines, and the -state generators can swap between a \`geth\`-based implementation and a \`parityvm\`-based -implementation. - -#### Command line params - -Command line params that need to be supported are - -``` - --input.alloc value (default: "alloc.json") - --input.env value (default: "env.json") - --input.txs value (default: "txs.json") - --output.alloc value (default: "alloc.json") - --output.basedir value - --output.body value - --output.result value (default: "result.json") - --state.chainid value (default: 1) - --state.fork value (default: "GrayGlacier") - --state.reward value (default: 0) - --trace.memory (default: false) - --trace.nomemory (default: true) - --trace.noreturndata (default: true) - --trace.nostack (default: false) - --trace.returndata (default: false) -``` -#### Objects - -The transition tool uses JSON objects to read and write data related to the transition operation. The -following object definitions are required. - -##### `alloc` - -The `alloc` object defines the prestate that transition will begin with. - -```go -// Map of address to account definition. -type Alloc map[common.Address]Account -// Genesis account. Each field is optional. -type Account struct { - Code []byte `json:"code"` - Storage map[common.Hash]common.Hash `json:"storage"` - Balance *big.Int `json:"balance"` - Nonce uint64 `json:"nonce"` - SecretKey []byte `json:"secretKey"` -} -``` - -##### `env` - -The `env` object defines the environmental context in which the transition will -take place. - -```go -type Env struct { - // required - CurrentCoinbase common.Address `json:"currentCoinbase"` - CurrentGasLimit uint64 `json:"currentGasLimit"` - CurrentNumber uint64 `json:"currentNumber"` - CurrentTimestamp uint64 `json:"currentTimestamp"` - Withdrawals []*Withdrawal `json:"withdrawals"` - // optional - CurrentDifficulty *big.Int `json:"currentDifficulty"` - CurrentRandom *big.Int `json:"currentRandom"` - CurrentBaseFee *big.Int `json:"currentBaseFee"` - ParentDifficulty *big.Int `json:"parentDifficulty"` - ParentGasUsed uint64 `json:"parentGasUsed"` - ParentGasLimit uint64 `json:"parentGasLimit"` - ParentTimestamp uint64 `json:"parentTimestamp"` - BlockHashes map[uint64]common.Hash `json:"blockHashes"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - Ommers []Ommer `json:"ommers"` -} -type Ommer struct { - Delta uint64 `json:"delta"` - Address common.Address `json:"address"` -} -type Withdrawal struct { - Index uint64 `json:"index"` - ValidatorIndex uint64 `json:"validatorIndex"` - Recipient common.Address `json:"recipient"` - Amount *big.Int `json:"amount"` -} -``` - -##### `txs` - -The `txs` object is an array of any of the transaction types: `LegacyTx`, -`AccessListTx`, or `DynamicFeeTx`. - -```go -type LegacyTx struct { - Nonce uint64 `json:"nonce"` - GasPrice *big.Int `json:"gasPrice"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -type AccessList []AccessTuple -type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` -} -type AccessListTx struct { - ChainID *big.Int `json:"chainId"` - Nonce uint64 `json:"nonce"` - GasPrice *big.Int `json:"gasPrice"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - AccessList AccessList `json:"accessList"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -type DynamicFeeTx struct { - ChainID *big.Int `json:"chainId"` - Nonce uint64 `json:"nonce"` - GasTipCap *big.Int `json:"maxPriorityFeePerGas"` - GasFeeCap *big.Int `json:"maxFeePerGas"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - AccessList AccessList `json:"accessList"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -``` - -##### `result` - -The `result` object is output after a transition is executed. It includes -information about the post-transition environment. - -```go -type ExecutionResult struct { - StateRoot common.Hash `json:"stateRoot"` - TxRoot common.Hash `json:"txRoot"` - ReceiptRoot common.Hash `json:"receiptsRoot"` - LogsHash common.Hash `json:"logsHash"` - Bloom types.Bloom `json:"logsBloom"` - Receipts types.Receipts `json:"receipts"` - Rejected []*rejectedTx `json:"rejected,omitempty"` - Difficulty *big.Int `json:"currentDifficulty"` - GasUsed uint64 `json:"gasUsed"` - BaseFee *big.Int `json:"currentBaseFee,omitempty"` -} -``` - -#### Error codes and output - -All logging should happen against the `stderr`. -There are a few (not many) errors that can occur, those are defined below. - -##### EVM-based errors (`2` to `9`) - -- Other EVM error. Exit code `2` -- Failed configuration: when a non-supported or invalid fork was specified. Exit code `3`. -- Block history is not supplied, but needed for a `BLOCKHASH` operation. If `BLOCKHASH` - is invoked targeting a block which history has not been provided for, the program will - exit with code `4`. - -##### IO errors (`10`-`20`) - -- Invalid input json: the supplied data could not be marshalled. - The program will exit with code `10` -- IO problems: failure to load or save files, the program will exit with code `11` - -``` -# This should exit with 3 -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Frontier+1346 2>/dev/null -exitcode:3 OK -``` -#### Forks -### Basic usage - -The chain configuration to be used for a transition is specified via the -`--state.fork` CLI flag. A list of possible values and configurations can be -found in [`tests/init.go`](../../tests/init.go). - -#### Examples -##### Basic usage - -Invoking it with the provided example files -``` -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin -``` -Two resulting files: - -`alloc.json`: -```json -{ - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "balance": "0xfeed1a9d", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "nonce": "0xac" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xa410" - } -} -``` -`result.json`: -```json -{ - "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13", - "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "rejected": [ - { - "index": 1, - "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x5208" -} -``` - -We can make them spit out the data to e.g. `stdout` like this: -``` -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.result=stdout --output.alloc=stdout --state.fork=Berlin -``` -Output: -```json -{ - "alloc": { - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "balance": "0xfeed1a9d", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "nonce": "0xac" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xa410" - } - }, - "result": { - "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13", - "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "rejected": [ - { - "index": 1, - "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x5208" - } -} -``` - -#### About Ommers - -Mining rewards and ommer rewards might need to be added. This is how those are applied: - -- `block_reward` is the block mining reward for the miner (`0xaa`), of a block at height `N`. -- For each ommer (mined by `0xbb`), with blocknumber `N-delta` - - (where `delta` is the difference between the current block and the ommer) - - The account `0xbb` (ommer miner) is awarded `(8-delta)/ 8 * block_reward` - - The account `0xaa` (block miner) is awarded `block_reward / 32` - -To make `t8n` apply these, the following inputs are required: - -- `--state.reward` - - For ethash, it is `5000000000000000000` `wei`, - - If this is not defined, mining rewards are not applied, - - A value of `0` is valid, and causes accounts to be 'touched'. -- For each ommer, the tool needs to be given an `address\` and a `delta`. This - is done via the `ommers` field in `env`. - -Note: the tool does not verify that e.g. the normal uncle rules apply, -and allows e.g two uncles at the same height, or the uncle-distance. This means that -the tool allows for negative uncle reward (distance > 8) - -Example: -`./testdata/5/env.json`: -```json -{ - "currentCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x750a163df65e8a", - "currentNumber": "1", - "currentTimestamp": "1000", - "ommers": [ - {"delta": 1, "address": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, - {"delta": 2, "address": "0xcccccccccccccccccccccccccccccccccccccccc" } - ] -} -``` -When applying this, using a reward of `0x08` -Output: -```json -{ - "alloc": { - "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": { - "balance": "0x88" - }, - "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": { - "balance": "0x70" - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "balance": "0x60" - } - } -} -``` -#### Future EIPS - -It is also possible to experiment with future eips that are not yet defined in a hard fork. -Example, putting EIP-1344 into Frontier: -``` -./evm t8n --state.fork=Frontier+1344 --input.pre=./testdata/1/pre.json --input.txs=./testdata/1/txs.json --input.env=/testdata/1/env.json -``` - -#### Block history - -The `BLOCKHASH` opcode requires blockhashes to be provided by the caller, inside the `env`. -If a required blockhash is not provided, the exit code should be `4`: -Example where blockhashes are provided: -``` -./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace --state.fork=Berlin - -``` - -``` -cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2 -``` -``` -{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"} -{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"BLOCKHASH"} -{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"depth":1,"refund":0,"opName":"STOP"} -{"output":"","gasUsed":"0x17"} -``` - -In this example, the caller has not provided the required blockhash: -``` -./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace --state.fork=Berlin -ERROR(4): getHash(3) invoked, blockhash for that block not provided -``` -Error code: 4 - -#### Chaining - -Another thing that can be done, is to chain invocations: -``` -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json --state.fork=Berlin - -``` -What happened here, is that we first applied two identical transactions, so the second one was rejected. -Then, taking the poststate alloc as the input for the next state, we tried again to include -the same two transactions: this time, both failed due to too low nonce. - -In order to meaningfully chain invocations, one would need to provide meaningful new `env`, otherwise the -actual blocknumber (exposed to the EVM) would not increase. - -#### Transactions in RLP form - -It is possible to provide already-signed transactions as input to, using an `input.txs` which ends with the `rlp` suffix. -The input format for RLP-form transactions is _identical_ to the _output_ format for block bodies. Therefore, it's fully possible -to use the evm to go from `json` input to `rlp` input. - -The following command takes **json** the transactions in `./testdata/13/txs.json` and signs them. After execution, they are output to `signed_txs.rlp`.: -``` -./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./testdata/13/txs.json --input.env=./testdata/13/env.json --output.result=alloc_jsontx.json --output.body=signed_txs.rlp -INFO [12-27|09:25:11.102] Trie dumping started root=e4b924..6aef61 -INFO [12-27|09:25:11.102] Trie dumping complete accounts=3 elapsed="275.66µs" -INFO [12-27|09:25:11.102] Wrote file file=alloc.json -INFO [12-27|09:25:11.103] Wrote file file=alloc_jsontx.json -INFO [12-27|09:25:11.103] Wrote file file=signed_txs.rlp -``` - -The `output.body` is the rlp-list of transactions, encoded in hex and placed in a string a'la `json` encoding rules: -``` -cat signed_txs.rlp -"0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" -``` - -We can use `rlpdump` to check what the contents are: -``` -rlpdump -hex $(cat signed_txs.rlp | jq -r ) -[ - 02f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904, - 02f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9, -] -``` -Now, we can now use those (or any other already signed transactions), as input, like so: -``` -./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./signed_txs.rlp --input.env=./testdata/13/env.json --output.result=alloc_rlptx.json -INFO [12-27|09:25:11.187] Trie dumping started root=e4b924..6aef61 -INFO [12-27|09:25:11.187] Trie dumping complete accounts=3 elapsed="123.676µs" -INFO [12-27|09:25:11.187] Wrote file file=alloc.json -INFO [12-27|09:25:11.187] Wrote file file=alloc_rlptx.json -``` -You might have noticed that the results from these two invocations were stored in two separate files. -And we can now finally check that they match. -``` -cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot -"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61" -"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61" -``` - -## Transaction tool - -The transaction tool is used to perform static validity checks on transactions such as: -* intrinsic gas calculation -* max values on integers -* fee semantics, such as `maxFeePerGas < maxPriorityFeePerGas` -* newer tx types on old forks - -### Examples - -``` -./evm t9n --state.fork Homestead --input.txs testdata/15/signed_txs.rlp -[ - { - "error": "transaction type not supported", - "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476" - }, - { - "error": "transaction type not supported", - "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a" - } -] -``` -``` -./evm t9n --state.fork London --input.txs testdata/15/signed_txs.rlp -[ - { - "address": "0xd02d72e067e77158444ef2020ff2d325f929b363", - "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476", - "intrinsicGas": "0x5208" - }, - { - "address": "0xd02d72e067e77158444ef2020ff2d325f929b363", - "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a", - "intrinsicGas": "0x5208" - } -] -``` -## Block builder tool (b11r) - -The `evm b11r` tool is used to assemble and seal full block rlps. - -### Specification - -#### Command line params - -Command line params that need to be supported are: - -``` - --input.header value `stdin` or file name of where to find the block header to use. (default: "header.json") - --input.ommers value `stdin` or file name of where to find the list of ommer header RLPs to use. - --input.txs value `stdin` or file name of where to find the transactions list in RLP form. (default: "txs.rlp") - --output.basedir value Specifies where output files are placed. Will be created if it does not exist. - --output.block value Determines where to put the alloc of the post-state. (default: "block.json") - - into the file - `stdout` - into the stdout output - `stderr` - into the stderr output - --seal.clique value Seal block with Clique. `stdin` or file name of where to find the Clique sealing data. - --seal.ethash Seal block with ethash. (default: false) - --seal.ethash.dir value Path to ethash DAG. If none exists, a new DAG will be generated. - --seal.ethash.mode value Defines the type and amount of PoW verification an ethash engine makes. (default: "normal") - --verbosity value Sets the verbosity level. (default: 3) -``` - -#### Objects - -##### `header` - -The `header` object is a consensus header. - -```go= -type Header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *big.Int `json:"difficulty"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *big.Int `json:"baseFeePerGas"` -} -``` -#### `ommers` - -The `ommers` object is a list of RLP-encoded ommer blocks in hex -representation. - -```go= -type Ommers []string -``` - -#### `txs` - -The `txs` object is a list of RLP-encoded transactions in hex representation. - -```go= -type Txs []string -``` - -#### `clique` - -The `clique` object provides the necessary information to complete a clique -seal of the block. - -```go= -var CliqueInfo struct { - Key *common.Hash `json:"secretKey"` - Voted *common.Address `json:"voted"` - Authorize *bool `json:"authorize"` - Vanity common.Hash `json:"vanity"` -} -``` - -#### `output` - -The `output` object contains two values, the block RLP and the block hash. - -```go= -type BlockInfo struct { - Rlp []byte `json:"rlp"` - Hash common.Hash `json:"hash"` -} -``` - -## A Note on Encoding - -The encoding of values for `evm` utility attempts to be relatively flexible. It -generally supports hex-encoded or decimal-encoded numeric values, and -hex-encoded byte values (like `common.Address`, `common.Hash`, etc). When in -doubt, the [`execution-apis`](https://github.com/ethereum/execution-apis) way -of encoding should always be accepted. - -## Testing - -There are many test cases in the [`cmd/evm/testdata`](./testdata) directory. -These fixtures are used to power the `t8n` tests in -[`t8n_test.go`](./t8n_test.go). The best way to verify correctness of new `evm` -implementations is to execute these and verify the output and error codes match -the expected values. - diff --git a/builder/cmd/evm/blockrunner.go b/builder/cmd/evm/blockrunner.go deleted file mode 100644 index c5d836e0e..000000000 --- a/builder/cmd/evm/blockrunner.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "errors" - "fmt" - "os" - "regexp" - "sort" - - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/tests" - "github.com/urfave/cli/v2" -) - -var RunFlag = &cli.StringFlag{ - Name: "run", - Value: ".*", - Usage: "Run only those tests matching the regular expression.", -} - -var blockTestCommand = &cli.Command{ - Action: blockTestCmd, - Name: "blocktest", - Usage: "Executes the given blockchain tests", - ArgsUsage: "", - Flags: []cli.Flag{RunFlag}, -} - -func blockTestCmd(ctx *cli.Context) error { - if len(ctx.Args().First()) == 0 { - return errors.New("path-to-test argument required") - } - - var tracer vm.EVMLogger - // Configure the EVM logger - if ctx.Bool(MachineFlag.Name) { - tracer = logger.NewJSONLogger(&logger.Config{ - EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), - DisableStack: ctx.Bool(DisableStackFlag.Name), - DisableStorage: ctx.Bool(DisableStorageFlag.Name), - EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), - }, os.Stderr) - } - // Load the test content from the input file - src, err := os.ReadFile(ctx.Args().First()) - if err != nil { - return err - } - var tests map[string]tests.BlockTest - if err = json.Unmarshal(src, &tests); err != nil { - return err - } - re, err := regexp.Compile(ctx.String(RunFlag.Name)) - if err != nil { - return fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err) - } - - // Run them in order - var keys []string - for key := range tests { - keys = append(keys, key) - } - sort.Strings(keys) - for _, name := range keys { - if !re.MatchString(name) { - continue - } - test := tests[name] - if err := test.Run(false, rawdb.HashScheme, tracer, func(res error, chain *core.BlockChain) { - if ctx.Bool(DumpFlag.Name) { - if state, _ := chain.State(); state != nil { - fmt.Println(string(state.Dump(nil))) - } - } - }); err != nil { - return fmt.Errorf("test %v: %w", name, err) - } - } - return nil -} diff --git a/builder/cmd/evm/compiler.go b/builder/cmd/evm/compiler.go deleted file mode 100644 index c071834b5..000000000 --- a/builder/cmd/evm/compiler.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "os" - - "github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" - - "github.com/urfave/cli/v2" -) - -var compileCommand = &cli.Command{ - Action: compileCmd, - Name: "compile", - Usage: "Compiles easm source to evm binary", - ArgsUsage: "", -} - -func compileCmd(ctx *cli.Context) error { - debug := ctx.Bool(DebugFlag.Name) - - if len(ctx.Args().First()) == 0 { - return errors.New("filename required") - } - - fn := ctx.Args().First() - src, err := os.ReadFile(fn) - if err != nil { - return err - } - - bin, err := compiler.Compile(fn, src, debug) - if err != nil { - return err - } - fmt.Println(bin) - return nil -} diff --git a/builder/cmd/evm/disasm.go b/builder/cmd/evm/disasm.go deleted file mode 100644 index b1f35cbaf..000000000 --- a/builder/cmd/evm/disasm.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "os" - "strings" - - "github.com/ethereum/go-ethereum/core/asm" - "github.com/urfave/cli/v2" -) - -var disasmCommand = &cli.Command{ - Action: disasmCmd, - Name: "disasm", - Usage: "Disassembles evm binary", - ArgsUsage: "", -} - -func disasmCmd(ctx *cli.Context) error { - var in string - switch { - case len(ctx.Args().First()) > 0: - fn := ctx.Args().First() - input, err := os.ReadFile(fn) - if err != nil { - return err - } - in = string(input) - case ctx.IsSet(InputFlag.Name): - in = ctx.String(InputFlag.Name) - default: - return errors.New("missing filename or --input value") - } - - code := strings.TrimSpace(in) - fmt.Printf("%v\n", code) - return asm.PrintDisassembled(code) -} diff --git a/builder/cmd/evm/internal/compiler/compiler.go b/builder/cmd/evm/internal/compiler/compiler.go deleted file mode 100644 index 54981b669..000000000 --- a/builder/cmd/evm/internal/compiler/compiler.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package compiler - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/core/asm" -) - -func Compile(fn string, src []byte, debug bool) (string, error) { - compiler := asm.NewCompiler(debug) - compiler.Feed(asm.Lex(src, debug)) - - bin, compileErrors := compiler.Compile() - if len(compileErrors) > 0 { - // report errors - for _, err := range compileErrors { - fmt.Printf("%s:%v\n", fn, err) - } - return "", errors.New("compiling failed") - } - return bin, nil -} diff --git a/builder/cmd/evm/internal/t8ntool/block.go b/builder/cmd/evm/internal/t8ntool/block.go deleted file mode 100644 index a2dc47343..000000000 --- a/builder/cmd/evm/internal/t8ntool/block.go +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/urfave/cli/v2" -) - -//go:generate go run github.com/fjl/gencodec -type header -field-override headerMarshaling -out gen_header.go -type header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *big.Int `json:"difficulty"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` -} - -type headerMarshaling struct { - Difficulty *math.HexOrDecimal256 - Number *math.HexOrDecimal256 - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Time math.HexOrDecimal64 - Extra hexutil.Bytes - BaseFee *math.HexOrDecimal256 - BlobGasUsed *math.HexOrDecimal64 - ExcessBlobGas *math.HexOrDecimal64 -} - -type bbInput struct { - Header *header `json:"header,omitempty"` - OmmersRlp []string `json:"ommers,omitempty"` - TxRlp string `json:"txs,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - Clique *cliqueInput `json:"clique,omitempty"` - - Ethash bool `json:"-"` - Txs []*types.Transaction `json:"-"` - Ommers []*types.Header `json:"-"` -} - -type cliqueInput struct { - Key *ecdsa.PrivateKey - Voted *common.Address - Authorize *bool - Vanity common.Hash -} - -// UnmarshalJSON implements json.Unmarshaler interface. -func (c *cliqueInput) UnmarshalJSON(input []byte) error { - var x struct { - Key *common.Hash `json:"secretKey"` - Voted *common.Address `json:"voted"` - Authorize *bool `json:"authorize"` - Vanity common.Hash `json:"vanity"` - } - if err := json.Unmarshal(input, &x); err != nil { - return err - } - if x.Key == nil { - return errors.New("missing required field 'secretKey' for cliqueInput") - } - if ecdsaKey, err := crypto.ToECDSA(x.Key[:]); err != nil { - return err - } else { - c.Key = ecdsaKey - } - c.Voted = x.Voted - c.Authorize = x.Authorize - c.Vanity = x.Vanity - return nil -} - -// ToBlock converts i into a *types.Block -func (i *bbInput) ToBlock() *types.Block { - header := &types.Header{ - ParentHash: i.Header.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: common.Address{}, - Root: i.Header.Root, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - Bloom: i.Header.Bloom, - Difficulty: common.Big0, - Number: i.Header.Number, - GasLimit: i.Header.GasLimit, - GasUsed: i.Header.GasUsed, - Time: i.Header.Time, - Extra: i.Header.Extra, - MixDigest: i.Header.MixDigest, - BaseFee: i.Header.BaseFee, - WithdrawalsHash: i.Header.WithdrawalsHash, - BlobGasUsed: i.Header.BlobGasUsed, - ExcessBlobGas: i.Header.ExcessBlobGas, - ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, - } - - // Fill optional values. - if i.Header.OmmerHash != nil { - header.UncleHash = *i.Header.OmmerHash - } else if len(i.Ommers) != 0 { - // Calculate the ommer hash if none is provided and there are ommers to hash - header.UncleHash = types.CalcUncleHash(i.Ommers) - } - if i.Header.Coinbase != nil { - header.Coinbase = *i.Header.Coinbase - } - if i.Header.TxHash != nil { - header.TxHash = *i.Header.TxHash - } - if i.Header.ReceiptHash != nil { - header.ReceiptHash = *i.Header.ReceiptHash - } - if i.Header.Nonce != nil { - header.Nonce = *i.Header.Nonce - } - if i.Header.Difficulty != nil { - header.Difficulty = i.Header.Difficulty - } - return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals) -} - -// SealBlock seals the given block using the configured engine. -func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) { - switch { - case i.Clique != nil: - return i.sealClique(block) - default: - return block, nil - } -} - -// sealClique seals the given block using clique. -func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) { - // If any clique value overwrites an explicit header value, fail - // to avoid silently building a block with unexpected values. - if i.Header.Extra != nil { - return nil, NewError(ErrorConfig, errors.New("sealing with clique will overwrite provided extra data")) - } - header := block.Header() - if i.Clique.Voted != nil { - if i.Header.Coinbase != nil { - return nil, NewError(ErrorConfig, errors.New("sealing with clique and voting will overwrite provided coinbase")) - } - header.Coinbase = *i.Clique.Voted - } - if i.Clique.Authorize != nil { - if i.Header.Nonce != nil { - return nil, NewError(ErrorConfig, errors.New("sealing with clique and voting will overwrite provided nonce")) - } - if *i.Clique.Authorize { - header.Nonce = [8]byte{} - } else { - header.Nonce = [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - } - } - // Extra is fixed 32 byte vanity and 65 byte signature - header.Extra = make([]byte, 32+65) - copy(header.Extra[0:32], i.Clique.Vanity.Bytes()[:]) - - // Sign the seal hash and fill in the rest of the extra data - h := clique.SealHash(header) - sighash, err := crypto.Sign(h[:], i.Clique.Key) - if err != nil { - return nil, err - } - copy(header.Extra[32:], sighash) - block = block.WithSeal(header) - return block, nil -} - -// BuildBlock constructs a block from the given inputs. -func BuildBlock(ctx *cli.Context) error { - baseDir, err := createBasedir(ctx) - if err != nil { - return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err)) - } - inputData, err := readInput(ctx) - if err != nil { - return err - } - block := inputData.ToBlock() - block, err = inputData.SealBlock(block) - if err != nil { - return err - } - return dispatchBlock(ctx, baseDir, block) -} - -func readInput(ctx *cli.Context) (*bbInput, error) { - var ( - headerStr = ctx.String(InputHeaderFlag.Name) - ommersStr = ctx.String(InputOmmersFlag.Name) - withdrawalsStr = ctx.String(InputWithdrawalsFlag.Name) - txsStr = ctx.String(InputTxsRlpFlag.Name) - cliqueStr = ctx.String(SealCliqueFlag.Name) - inputData = &bbInput{} - ) - if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector { - decoder := json.NewDecoder(os.Stdin) - if err := decoder.Decode(inputData); err != nil { - return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err)) - } - } - if cliqueStr != stdinSelector && cliqueStr != "" { - var clique cliqueInput - if err := readFile(cliqueStr, "clique", &clique); err != nil { - return nil, err - } - inputData.Clique = &clique - } - if headerStr != stdinSelector { - var env header - if err := readFile(headerStr, "header", &env); err != nil { - return nil, err - } - inputData.Header = &env - } - if ommersStr != stdinSelector && ommersStr != "" { - var ommers []string - if err := readFile(ommersStr, "ommers", &ommers); err != nil { - return nil, err - } - inputData.OmmersRlp = ommers - } - if withdrawalsStr != stdinSelector && withdrawalsStr != "" { - var withdrawals []*types.Withdrawal - if err := readFile(withdrawalsStr, "withdrawals", &withdrawals); err != nil { - return nil, err - } - inputData.Withdrawals = withdrawals - } - if txsStr != stdinSelector { - var txs string - if err := readFile(txsStr, "txs", &txs); err != nil { - return nil, err - } - inputData.TxRlp = txs - } - // Deserialize rlp txs and ommers - var ( - ommers = []*types.Header{} - txs = []*types.Transaction{} - ) - if inputData.TxRlp != "" { - if err := rlp.DecodeBytes(common.FromHex(inputData.TxRlp), &txs); err != nil { - return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode transaction from rlp data: %v", err)) - } - inputData.Txs = txs - } - for _, str := range inputData.OmmersRlp { - type extblock struct { - Header *types.Header - Txs []*types.Transaction - Ommers []*types.Header - } - var ommer *extblock - if err := rlp.DecodeBytes(common.FromHex(str), &ommer); err != nil { - return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode ommer from rlp data: %v", err)) - } - ommers = append(ommers, ommer.Header) - } - inputData.Ommers = ommers - - return inputData, nil -} - -// dispatchBlock writes the output data to either stderr or stdout, or to the specified -// files -func dispatchBlock(ctx *cli.Context, baseDir string, block *types.Block) error { - raw, _ := rlp.EncodeToBytes(block) - type blockInfo struct { - Rlp hexutil.Bytes `json:"rlp"` - Hash common.Hash `json:"hash"` - } - enc := blockInfo{ - Rlp: raw, - Hash: block.Hash(), - } - b, err := json.MarshalIndent(enc, "", " ") - if err != nil { - return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err)) - } - switch dest := ctx.String(OutputBlockFlag.Name); dest { - case "stdout": - os.Stdout.Write(b) - os.Stdout.WriteString("\n") - case "stderr": - os.Stderr.Write(b) - os.Stderr.WriteString("\n") - default: - if err := saveFile(baseDir, dest, enc); err != nil { - return err - } - } - return nil -} diff --git a/builder/cmd/evm/internal/t8ntool/execution.go b/builder/cmd/evm/internal/t8ntool/execution.go deleted file mode 100644 index cb975054c..000000000 --- a/builder/cmd/evm/internal/t8ntool/execution.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" -) - -type Prestate struct { - Env stEnv `json:"env"` - Pre types.GenesisAlloc `json:"pre"` -} - -// ExecutionResult contains the execution status after running a state test, any -// error that might have occurred and a dump of the final state if requested. -type ExecutionResult struct { - StateRoot common.Hash `json:"stateRoot"` - TxRoot common.Hash `json:"txRoot"` - ReceiptRoot common.Hash `json:"receiptsRoot"` - LogsHash common.Hash `json:"logsHash"` - Bloom types.Bloom `json:"logsBloom" gencodec:"required"` - Receipts types.Receipts `json:"receipts"` - Rejected []*rejectedTx `json:"rejected,omitempty"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"` - CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` - CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"` -} - -type ommer struct { - Delta uint64 `json:"delta"` - Address common.Address `json:"address"` -} - -//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go -type stEnv struct { - Coinbase common.Address `json:"currentCoinbase" gencodec:"required"` - Difficulty *big.Int `json:"currentDifficulty"` - Random *big.Int `json:"currentRandom"` - ParentDifficulty *big.Int `json:"parentDifficulty"` - ParentBaseFee *big.Int `json:"parentBaseFee,omitempty"` - ParentGasUsed uint64 `json:"parentGasUsed,omitempty"` - ParentGasLimit uint64 `json:"parentGasLimit,omitempty"` - GasLimit uint64 `json:"currentGasLimit" gencodec:"required"` - Number uint64 `json:"currentNumber" gencodec:"required"` - Timestamp uint64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp uint64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *big.Int `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - ExcessBlobGas *uint64 `json:"currentExcessBlobGas,omitempty"` - ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` -} - -type stEnvMarshaling struct { - Coinbase common.UnprefixedAddress - Difficulty *math.HexOrDecimal256 - Random *math.HexOrDecimal256 - ParentDifficulty *math.HexOrDecimal256 - ParentBaseFee *math.HexOrDecimal256 - ParentGasUsed math.HexOrDecimal64 - ParentGasLimit math.HexOrDecimal64 - GasLimit math.HexOrDecimal64 - Number math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - ParentTimestamp math.HexOrDecimal64 - BaseFee *math.HexOrDecimal256 - ExcessBlobGas *math.HexOrDecimal64 - ParentExcessBlobGas *math.HexOrDecimal64 - ParentBlobGasUsed *math.HexOrDecimal64 -} - -type rejectedTx struct { - Index int `json:"index"` - Err string `json:"error"` -} - -// Apply applies a set of transactions to a pre-state -func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, - txIt txIterator, miningReward int64, - getTracerFn func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)) (*state.StateDB, *ExecutionResult, []byte, error) { - // Capture errors for BLOCKHASH operation, if we haven't been supplied the - // required blockhashes - var hashError error - getHash := func(num uint64) common.Hash { - if pre.Env.BlockHashes == nil { - hashError = fmt.Errorf("getHash(%d) invoked, no blockhashes provided", num) - return common.Hash{} - } - h, ok := pre.Env.BlockHashes[math.HexOrDecimal64(num)] - if !ok { - hashError = fmt.Errorf("getHash(%d) invoked, blockhash for that block not provided", num) - } - return h - } - var ( - statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre) - signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) - gaspool = new(core.GasPool) - blockHash = common.Hash{0x13, 0x37} - rejectedTxs []*rejectedTx - includedTxs types.Transactions - gasUsed = uint64(0) - blobGasUsed = uint64(0) - receipts = make(types.Receipts, 0) - txIndex = 0 - ) - gaspool.AddGas(pre.Env.GasLimit) - vmContext := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: pre.Env.Coinbase, - BlockNumber: new(big.Int).SetUint64(pre.Env.Number), - Time: pre.Env.Timestamp, - Difficulty: pre.Env.Difficulty, - GasLimit: pre.Env.GasLimit, - GetHash: getHash, - } - // If currentBaseFee is defined, add it to the vmContext. - if pre.Env.BaseFee != nil { - vmContext.BaseFee = new(big.Int).Set(pre.Env.BaseFee) - } - // If random is defined, add it to the vmContext. - if pre.Env.Random != nil { - rnd := common.BigToHash(pre.Env.Random) - vmContext.Random = &rnd - } - // Calculate the BlobBaseFee - var excessBlobGas uint64 - if pre.Env.ExcessBlobGas != nil { - excessBlobGas := *pre.Env.ExcessBlobGas - vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) - } else { - // If it is not explicitly defined, but we have the parent values, we try - // to calculate it ourselves. - parentExcessBlobGas := pre.Env.ParentExcessBlobGas - parentBlobGasUsed := pre.Env.ParentBlobGasUsed - if parentExcessBlobGas != nil && parentBlobGasUsed != nil { - excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed) - vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) - } - } - // If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's - // done in StateProcessor.Process(block, ...), right before transactions are applied. - if chainConfig.DAOForkSupport && - chainConfig.DAOForkBlock != nil && - chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 { - misc.ApplyDAOHardFork(statedb) - } - if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil { - evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig) - core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb) - } - - for i := 0; txIt.Next(); i++ { - tx, err := txIt.Tx() - if err != nil { - log.Warn("rejected tx", "index", i, "error", err) - rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) - continue - } - if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil { - errMsg := "blob tx used but field env.ExcessBlobGas missing" - log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg) - rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg}) - continue - } - msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee) - if err != nil { - log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) - rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) - continue - } - txBlobGas := uint64(0) - if tx.Type() == types.BlobTxType { - txBlobGas = uint64(params.BlobTxBlobGasPerBlob * len(tx.BlobHashes())) - if used, max := blobGasUsed+txBlobGas, uint64(params.MaxBlobGasPerBlock); used > max { - err := fmt.Errorf("blob gas (%d) would exceed maximum allowance %d", used, max) - log.Warn("rejected tx", "index", i, "err", err) - rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) - continue - } - } - tracer, err := getTracerFn(txIndex, tx.Hash()) - if err != nil { - return nil, nil, nil, err - } - vmConfig.Tracer = tracer - statedb.SetTxContext(tx.Hash(), txIndex) - - var ( - txContext = core.NewEVMTxContext(msg) - snapshot = statedb.Snapshot() - prevGas = gaspool.Gas() - ) - evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) - - // (ret []byte, usedGas uint64, failed bool, err error) - msgResult, err := core.ApplyMessage(evm, msg, gaspool) - if err != nil { - statedb.RevertToSnapshot(snapshot) - log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err) - rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) - gaspool.SetGas(prevGas) - continue - } - includedTxs = append(includedTxs, tx) - if hashError != nil { - return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError) - } - blobGasUsed += txBlobGas - gasUsed += msgResult.UsedGas - - // Receipt: - { - var root []byte - if chainConfig.IsByzantium(vmContext.BlockNumber) { - statedb.Finalise(true) - } else { - root = statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)).Bytes() - } - - // Create a new receipt for the transaction, storing the intermediate root and - // gas used by the tx. - receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: gasUsed} - if msgResult.Failed() { - receipt.Status = types.ReceiptStatusFailed - } else { - receipt.Status = types.ReceiptStatusSuccessful - } - receipt.TxHash = tx.Hash() - receipt.GasUsed = msgResult.UsedGas - - // If the transaction created a contract, store the creation address in the receipt. - if msg.To == nil { - receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) - } - - // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - // These three are non-consensus fields: - //receipt.BlockHash - //receipt.BlockNumber - receipt.TransactionIndex = uint(txIndex) - receipts = append(receipts, receipt) - } - - txIndex++ - } - statedb.IntermediateRoot(chainConfig.IsEIP158(vmContext.BlockNumber)) - // Add mining reward? (-1 means rewards are disabled) - if miningReward >= 0 { - // Add mining reward. The mining reward may be `0`, which only makes a difference in the cases - // where - // - the coinbase self-destructed, or - // - there are only 'bad' transactions, which aren't executed. In those cases, - // the coinbase gets no txfee, so isn't created, and thus needs to be touched - var ( - blockReward = big.NewInt(miningReward) - minerReward = new(big.Int).Set(blockReward) - perOmmer = new(big.Int).Div(blockReward, big.NewInt(32)) - ) - for _, ommer := range pre.Env.Ommers { - // Add 1/32th for each ommer included - minerReward.Add(minerReward, perOmmer) - // Add (8-delta)/8 - reward := big.NewInt(8) - reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta)) - reward.Mul(reward, blockReward) - reward.Div(reward, big.NewInt(8)) - statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward)) - } - statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward)) - } - // Apply withdrawals - for _, w := range pre.Env.Withdrawals { - // Amount is in gwei, turn into wei - amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei)) - statedb.AddBalance(w.Address, uint256.MustFromBig(amount)) - } - // Commit block - root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber)) - if err != nil { - return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err)) - } - execRs := &ExecutionResult{ - StateRoot: root, - TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)), - ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)), - Bloom: types.CreateBloom(receipts), - LogsHash: rlpHash(statedb.Logs()), - Receipts: receipts, - Rejected: rejectedTxs, - Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty), - GasUsed: (math.HexOrDecimal64)(gasUsed), - BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee), - } - if pre.Env.Withdrawals != nil { - h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil)) - execRs.WithdrawalsRoot = &h - } - if vmContext.BlobBaseFee != nil { - execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas) - execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed) - } - // Re-create statedb instance with new root upon the updated database - // for accessing latest states. - statedb, err = state.New(root, statedb.Database(), nil) - if err != nil { - return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err)) - } - body, _ := rlp.EncodeToBytes(includedTxs) - return statedb, execRs, body, nil -} - -func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB { - sdb := state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true}) - statedb, _ := state.New(types.EmptyRootHash, sdb, nil) - for addr, a := range accounts { - statedb.SetCode(addr, a.Code) - statedb.SetNonce(addr, a.Nonce) - statedb.SetBalance(addr, uint256.MustFromBig(a.Balance)) - for k, v := range a.Storage { - statedb.SetState(addr, k, v) - } - } - // Commit and re-open to start with a clean state. - root, _ := statedb.Commit(0, false) - statedb, _ = state.New(root, sdb, nil) - return statedb -} - -func rlpHash(x interface{}) (h common.Hash) { - hw := sha3.NewLegacyKeccak256() - rlp.Encode(hw, x) - hw.Sum(h[:0]) - return h -} - -// calcDifficulty is based on ethash.CalcDifficulty. This method is used in case -// the caller does not provide an explicit difficulty, but instead provides only -// parent timestamp + difficulty. -// Note: this method only works for ethash engine. -func calcDifficulty(config *params.ChainConfig, number, currentTime, parentTime uint64, - parentDifficulty *big.Int, parentUncleHash common.Hash) *big.Int { - uncleHash := parentUncleHash - if uncleHash == (common.Hash{}) { - uncleHash = types.EmptyUncleHash - } - parent := &types.Header{ - ParentHash: common.Hash{}, - UncleHash: uncleHash, - Difficulty: parentDifficulty, - Number: new(big.Int).SetUint64(number - 1), - Time: parentTime, - } - return ethash.CalcDifficulty(config, currentTime, parent) -} diff --git a/builder/cmd/evm/internal/t8ntool/flags.go b/builder/cmd/evm/internal/t8ntool/flags.go deleted file mode 100644 index c2eca8cc2..000000000 --- a/builder/cmd/evm/internal/t8ntool/flags.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/tests" - "github.com/urfave/cli/v2" -) - -var ( - TraceFlag = &cli.BoolFlag{ - Name: "trace", - Usage: "Configures the use of the JSON opcode tracer. This tracer emits traces to files as trace--.jsonl", - } - TraceTracerFlag = &cli.StringFlag{ - Name: "trace.tracer", - Usage: "Configures the use of a custom tracer, e.g native or js tracers. Examples are callTracer and 4byteTracer. These tracers emit results into files as trace--.json", - } - TraceTracerConfigFlag = &cli.StringFlag{ - Name: "trace.jsonconfig", - Usage: "The configurations for the custom tracer specified by --trace.tracer. If provided, must be in JSON format", - } - TraceEnableMemoryFlag = &cli.BoolFlag{ - Name: "trace.memory", - Usage: "Enable full memory dump in traces", - } - TraceDisableStackFlag = &cli.BoolFlag{ - Name: "trace.nostack", - Usage: "Disable stack output in traces", - } - TraceEnableReturnDataFlag = &cli.BoolFlag{ - Name: "trace.returndata", - Usage: "Enable return data output in traces", - } - OutputBasedir = &cli.StringFlag{ - Name: "output.basedir", - Usage: "Specifies where output files are placed. Will be created if it does not exist.", - Value: "", - } - OutputBodyFlag = &cli.StringFlag{ - Name: "output.body", - Usage: "If set, the RLP of the transactions (block body) will be written to this file.", - Value: "", - } - OutputAllocFlag = &cli.StringFlag{ - Name: "output.alloc", - Usage: "Determines where to put the `alloc` of the post-state.\n" + - "\t`stdout` - into the stdout output\n" + - "\t`stderr` - into the stderr output\n" + - "\t - into the file ", - Value: "alloc.json", - } - OutputResultFlag = &cli.StringFlag{ - Name: "output.result", - Usage: "Determines where to put the `result` (stateroot, txroot etc) of the post-state.\n" + - "\t`stdout` - into the stdout output\n" + - "\t`stderr` - into the stderr output\n" + - "\t - into the file ", - Value: "result.json", - } - OutputBlockFlag = &cli.StringFlag{ - Name: "output.block", - Usage: "Determines where to put the `block` after building.\n" + - "\t`stdout` - into the stdout output\n" + - "\t`stderr` - into the stderr output\n" + - "\t - into the file ", - Value: "block.json", - } - InputAllocFlag = &cli.StringFlag{ - Name: "input.alloc", - Usage: "`stdin` or file name of where to find the prestate alloc to use.", - Value: "alloc.json", - } - InputEnvFlag = &cli.StringFlag{ - Name: "input.env", - Usage: "`stdin` or file name of where to find the prestate env to use.", - Value: "env.json", - } - InputTxsFlag = &cli.StringFlag{ - Name: "input.txs", - Usage: "`stdin` or file name of where to find the transactions to apply. " + - "If the file extension is '.rlp', then the data is interpreted as an RLP list of signed transactions." + - "The '.rlp' format is identical to the output.body format.", - Value: "txs.json", - } - InputHeaderFlag = &cli.StringFlag{ - Name: "input.header", - Usage: "`stdin` or file name of where to find the block header to use.", - Value: "header.json", - } - InputOmmersFlag = &cli.StringFlag{ - Name: "input.ommers", - Usage: "`stdin` or file name of where to find the list of ommer header RLPs to use.", - } - InputWithdrawalsFlag = &cli.StringFlag{ - Name: "input.withdrawals", - Usage: "`stdin` or file name of where to find the list of withdrawals to use.", - } - InputTxsRlpFlag = &cli.StringFlag{ - Name: "input.txs", - Usage: "`stdin` or file name of where to find the transactions list in RLP form.", - Value: "txs.rlp", - } - SealCliqueFlag = &cli.StringFlag{ - Name: "seal.clique", - Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.", - } - RewardFlag = &cli.Int64Flag{ - Name: "state.reward", - Usage: "Mining reward. Set to -1 to disable", - Value: 0, - } - ChainIDFlag = &cli.Int64Flag{ - Name: "state.chainid", - Usage: "ChainID to use", - Value: 1, - } - ForknameFlag = &cli.StringFlag{ - Name: "state.fork", - Usage: fmt.Sprintf("Name of ruleset to use."+ - "\n\tAvailable forknames:"+ - "\n\t %v"+ - "\n\tAvailable extra eips:"+ - "\n\t %v"+ - "\n\tSyntax (+ExtraEip)", - strings.Join(tests.AvailableForks(), "\n\t "), - strings.Join(vm.ActivateableEips(), ", ")), - Value: "GrayGlacier", - } - VerbosityFlag = &cli.IntFlag{ - Name: "verbosity", - Usage: "sets the verbosity level", - Value: 3, - } -) diff --git a/builder/cmd/evm/internal/t8ntool/gen_header.go b/builder/cmd/evm/internal/t8ntool/gen_header.go deleted file mode 100644 index a8c866897..000000000 --- a/builder/cmd/evm/internal/t8ntool/gen_header.go +++ /dev/null @@ -1,159 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package t8ntool - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" -) - -var _ = (*headerMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (h header) MarshalJSON() ([]byte, error) { - type header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - } - var enc header - enc.ParentHash = h.ParentHash - enc.OmmerHash = h.OmmerHash - enc.Coinbase = h.Coinbase - enc.Root = h.Root - enc.TxHash = h.TxHash - enc.ReceiptHash = h.ReceiptHash - enc.Bloom = h.Bloom - enc.Difficulty = (*math.HexOrDecimal256)(h.Difficulty) - enc.Number = (*math.HexOrDecimal256)(h.Number) - enc.GasLimit = math.HexOrDecimal64(h.GasLimit) - enc.GasUsed = math.HexOrDecimal64(h.GasUsed) - enc.Time = math.HexOrDecimal64(h.Time) - enc.Extra = h.Extra - enc.MixDigest = h.MixDigest - enc.Nonce = h.Nonce - enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee) - enc.WithdrawalsHash = h.WithdrawalsHash - enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed) - enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas) - enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (h *header) UnmarshalJSON(input []byte) error { - type header struct { - ParentHash *common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom *types.Bloom `json:"logsBloom"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - Number *math.HexOrDecimal256 `json:"number" gencodec:"required"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - } - var dec header - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.ParentHash != nil { - h.ParentHash = *dec.ParentHash - } - if dec.OmmerHash != nil { - h.OmmerHash = dec.OmmerHash - } - if dec.Coinbase != nil { - h.Coinbase = dec.Coinbase - } - if dec.Root == nil { - return errors.New("missing required field 'stateRoot' for header") - } - h.Root = *dec.Root - if dec.TxHash != nil { - h.TxHash = dec.TxHash - } - if dec.ReceiptHash != nil { - h.ReceiptHash = dec.ReceiptHash - } - if dec.Bloom != nil { - h.Bloom = *dec.Bloom - } - if dec.Difficulty != nil { - h.Difficulty = (*big.Int)(dec.Difficulty) - } - if dec.Number == nil { - return errors.New("missing required field 'number' for header") - } - h.Number = (*big.Int)(dec.Number) - if dec.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for header") - } - h.GasLimit = uint64(*dec.GasLimit) - if dec.GasUsed != nil { - h.GasUsed = uint64(*dec.GasUsed) - } - if dec.Time == nil { - return errors.New("missing required field 'timestamp' for header") - } - h.Time = uint64(*dec.Time) - if dec.Extra != nil { - h.Extra = *dec.Extra - } - if dec.MixDigest != nil { - h.MixDigest = *dec.MixDigest - } - if dec.Nonce != nil { - h.Nonce = dec.Nonce - } - if dec.BaseFee != nil { - h.BaseFee = (*big.Int)(dec.BaseFee) - } - if dec.WithdrawalsHash != nil { - h.WithdrawalsHash = dec.WithdrawalsHash - } - if dec.BlobGasUsed != nil { - h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) - } - if dec.ExcessBlobGas != nil { - h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - if dec.ParentBeaconBlockRoot != nil { - h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot - } - return nil -} diff --git a/builder/cmd/evm/internal/t8ntool/gen_stenv.go b/builder/cmd/evm/internal/t8ntool/gen_stenv.go deleted file mode 100644 index d47db4a87..000000000 --- a/builder/cmd/evm/internal/t8ntool/gen_stenv.go +++ /dev/null @@ -1,158 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package t8ntool - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" -) - -var _ = (*stEnvMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (s stEnv) MarshalJSON() ([]byte, error) { - type stEnv struct { - Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` - ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` - } - var enc stEnv - enc.Coinbase = common.UnprefixedAddress(s.Coinbase) - enc.Difficulty = (*math.HexOrDecimal256)(s.Difficulty) - enc.Random = (*math.HexOrDecimal256)(s.Random) - enc.ParentDifficulty = (*math.HexOrDecimal256)(s.ParentDifficulty) - enc.ParentBaseFee = (*math.HexOrDecimal256)(s.ParentBaseFee) - enc.ParentGasUsed = math.HexOrDecimal64(s.ParentGasUsed) - enc.ParentGasLimit = math.HexOrDecimal64(s.ParentGasLimit) - enc.GasLimit = math.HexOrDecimal64(s.GasLimit) - enc.Number = math.HexOrDecimal64(s.Number) - enc.Timestamp = math.HexOrDecimal64(s.Timestamp) - enc.ParentTimestamp = math.HexOrDecimal64(s.ParentTimestamp) - enc.BlockHashes = s.BlockHashes - enc.Ommers = s.Ommers - enc.Withdrawals = s.Withdrawals - enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee) - enc.ParentUncleHash = s.ParentUncleHash - enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas) - enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas) - enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed) - enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (s *stEnv) UnmarshalJSON(input []byte) error { - type stEnv struct { - Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"currentDifficulty"` - Random *math.HexOrDecimal256 `json:"currentRandom"` - ParentDifficulty *math.HexOrDecimal256 `json:"parentDifficulty"` - ParentBaseFee *math.HexOrDecimal256 `json:"parentBaseFee,omitempty"` - ParentGasUsed *math.HexOrDecimal64 `json:"parentGasUsed,omitempty"` - ParentGasLimit *math.HexOrDecimal64 `json:"parentGasLimit,omitempty"` - GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"` - Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"` - ParentTimestamp *math.HexOrDecimal64 `json:"parentTimestamp,omitempty"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - Ommers []ommer `json:"ommers,omitempty"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` - BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"` - ParentUncleHash *common.Hash `json:"parentUncleHash"` - ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"` - ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"` - ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` - } - var dec stEnv - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Coinbase == nil { - return errors.New("missing required field 'currentCoinbase' for stEnv") - } - s.Coinbase = common.Address(*dec.Coinbase) - if dec.Difficulty != nil { - s.Difficulty = (*big.Int)(dec.Difficulty) - } - if dec.Random != nil { - s.Random = (*big.Int)(dec.Random) - } - if dec.ParentDifficulty != nil { - s.ParentDifficulty = (*big.Int)(dec.ParentDifficulty) - } - if dec.ParentBaseFee != nil { - s.ParentBaseFee = (*big.Int)(dec.ParentBaseFee) - } - if dec.ParentGasUsed != nil { - s.ParentGasUsed = uint64(*dec.ParentGasUsed) - } - if dec.ParentGasLimit != nil { - s.ParentGasLimit = uint64(*dec.ParentGasLimit) - } - if dec.GasLimit == nil { - return errors.New("missing required field 'currentGasLimit' for stEnv") - } - s.GasLimit = uint64(*dec.GasLimit) - if dec.Number == nil { - return errors.New("missing required field 'currentNumber' for stEnv") - } - s.Number = uint64(*dec.Number) - if dec.Timestamp == nil { - return errors.New("missing required field 'currentTimestamp' for stEnv") - } - s.Timestamp = uint64(*dec.Timestamp) - if dec.ParentTimestamp != nil { - s.ParentTimestamp = uint64(*dec.ParentTimestamp) - } - if dec.BlockHashes != nil { - s.BlockHashes = dec.BlockHashes - } - if dec.Ommers != nil { - s.Ommers = dec.Ommers - } - if dec.Withdrawals != nil { - s.Withdrawals = dec.Withdrawals - } - if dec.BaseFee != nil { - s.BaseFee = (*big.Int)(dec.BaseFee) - } - if dec.ParentUncleHash != nil { - s.ParentUncleHash = *dec.ParentUncleHash - } - if dec.ExcessBlobGas != nil { - s.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - if dec.ParentExcessBlobGas != nil { - s.ParentExcessBlobGas = (*uint64)(dec.ParentExcessBlobGas) - } - if dec.ParentBlobGasUsed != nil { - s.ParentBlobGasUsed = (*uint64)(dec.ParentBlobGasUsed) - } - if dec.ParentBeaconBlockRoot != nil { - s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot - } - return nil -} diff --git a/builder/cmd/evm/internal/t8ntool/tracewriter.go b/builder/cmd/evm/internal/t8ntool/tracewriter.go deleted file mode 100644 index e4efad112..000000000 --- a/builder/cmd/evm/internal/t8ntool/tracewriter.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "encoding/json" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/log" -) - -// traceWriter is an vm.EVMLogger which also holds an inner logger/tracer. -// When the TxEnd event happens, the inner tracer result is written to the file, and -// the file is closed. -type traceWriter struct { - inner vm.EVMLogger - f io.WriteCloser -} - -// Compile-time interface check -var _ = vm.EVMLogger((*traceWriter)(nil)) - -func (t *traceWriter) CaptureTxEnd(restGas uint64) { - t.inner.CaptureTxEnd(restGas) - defer t.f.Close() - - if tracer, ok := t.inner.(tracers.Tracer); ok { - result, err := tracer.GetResult() - if err != nil { - log.Warn("Error in tracer", "err", err) - return - } - err = json.NewEncoder(t.f).Encode(result) - if err != nil { - log.Warn("Error writing tracer output", "err", err) - return - } - } -} - -func (t *traceWriter) CaptureTxStart(gasLimit uint64) { t.inner.CaptureTxStart(gasLimit) } -func (t *traceWriter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.inner.CaptureStart(env, from, to, create, input, gas, value) -} - -func (t *traceWriter) CaptureEnd(output []byte, gasUsed uint64, err error) { - t.inner.CaptureEnd(output, gasUsed, err) -} - -func (t *traceWriter) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { - t.inner.CaptureEnter(typ, from, to, input, gas, value) -} - -func (t *traceWriter) CaptureExit(output []byte, gasUsed uint64, err error) { - t.inner.CaptureExit(output, gasUsed, err) -} - -func (t *traceWriter) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - t.inner.CaptureState(pc, op, gas, cost, scope, rData, depth, err) -} -func (t *traceWriter) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { - t.inner.CaptureFault(pc, op, gas, cost, scope, depth, err) -} diff --git a/builder/cmd/evm/internal/t8ntool/transaction.go b/builder/cmd/evm/internal/t8ntool/transaction.go deleted file mode 100644 index 8533b7863..000000000 --- a/builder/cmd/evm/internal/t8ntool/transaction.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/tests" - "github.com/urfave/cli/v2" -) - -type result struct { - Error error - Address common.Address - Hash common.Hash - IntrinsicGas uint64 -} - -// MarshalJSON marshals as JSON with a hash. -func (r *result) MarshalJSON() ([]byte, error) { - type xx struct { - Error string `json:"error,omitempty"` - Address *common.Address `json:"address,omitempty"` - Hash *common.Hash `json:"hash,omitempty"` - IntrinsicGas hexutil.Uint64 `json:"intrinsicGas,omitempty"` - } - var out xx - if r.Error != nil { - out.Error = r.Error.Error() - } - if r.Address != (common.Address{}) { - out.Address = &r.Address - } - if r.Hash != (common.Hash{}) { - out.Hash = &r.Hash - } - out.IntrinsicGas = hexutil.Uint64(r.IntrinsicGas) - return json.Marshal(out) -} - -func Transaction(ctx *cli.Context) error { - var ( - err error - ) - // We need to load the transactions. May be either in stdin input or in files. - // Check if anything needs to be read from stdin - var ( - txStr = ctx.String(InputTxsFlag.Name) - inputData = &input{} - chainConfig *params.ChainConfig - ) - // Construct the chainconfig - if cConf, _, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil { - return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err)) - } else { - chainConfig = cConf - } - // Set the chain id - chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) - var body hexutil.Bytes - if txStr == stdinSelector { - decoder := json.NewDecoder(os.Stdin) - if err := decoder.Decode(inputData); err != nil { - return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err)) - } - // Decode the body of already signed transactions - body = common.FromHex(inputData.TxRlp) - } else { - // Read input from file - inFile, err := os.Open(txStr) - if err != nil { - return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err)) - } - defer inFile.Close() - decoder := json.NewDecoder(inFile) - if strings.HasSuffix(txStr, ".rlp") { - if err := decoder.Decode(&body); err != nil { - return err - } - } else { - return NewError(ErrorIO, errors.New("only rlp supported")) - } - } - signer := types.MakeSigner(chainConfig, new(big.Int), 0) - // We now have the transactions in 'body', which is supposed to be an - // rlp list of transactions - it, err := rlp.NewListIterator([]byte(body)) - if err != nil { - return err - } - var results []result - for it.Next() { - if err := it.Err(); err != nil { - return NewError(ErrorIO, err) - } - var tx types.Transaction - err := rlp.DecodeBytes(it.Value(), &tx) - if err != nil { - results = append(results, result{Error: err}) - continue - } - r := result{Hash: tx.Hash()} - if sender, err := types.Sender(signer, &tx); err != nil { - r.Error = err - results = append(results, r) - continue - } else { - r.Address = sender - } - // Check intrinsic gas - if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, - chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil { - r.Error = err - results = append(results, r) - continue - } else { - r.IntrinsicGas = gas - if tx.Gas() < gas { - r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas) - results = append(results, r) - continue - } - } - // Validate <256bit fields - switch { - case tx.Nonce()+1 < tx.Nonce(): - r.Error = errors.New("nonce exceeds 2^64-1") - case tx.Value().BitLen() > 256: - r.Error = errors.New("value exceeds 256 bits") - case tx.GasPrice().BitLen() > 256: - r.Error = errors.New("gasPrice exceeds 256 bits") - case tx.GasTipCap().BitLen() > 256: - r.Error = errors.New("maxPriorityFeePerGas exceeds 256 bits") - case tx.GasFeeCap().BitLen() > 256: - r.Error = errors.New("maxFeePerGas exceeds 256 bits") - case tx.GasFeeCap().Cmp(tx.GasTipCap()) < 0: - r.Error = errors.New("maxFeePerGas < maxPriorityFeePerGas") - case new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())).BitLen() > 256: - r.Error = errors.New("gas * gasPrice exceeds 256 bits") - case new(big.Int).Mul(tx.GasFeeCap(), new(big.Int).SetUint64(tx.Gas())).BitLen() > 256: - r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits") - } - // Check whether the init code size has been exceeded. - if chainConfig.IsShanghai(new(big.Int), 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - r.Error = errors.New("max initcode size exceeded") - } - results = append(results, r) - } - out, err := json.MarshalIndent(results, "", " ") - fmt.Println(string(out)) - return err -} diff --git a/builder/cmd/evm/internal/t8ntool/transition.go b/builder/cmd/evm/internal/t8ntool/transition.go deleted file mode 100644 index 7802d4965..000000000 --- a/builder/cmd/evm/internal/t8ntool/transition.go +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - "path" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/tests" - "github.com/urfave/cli/v2" -) - -const ( - ErrorEVM = 2 - ErrorConfig = 3 - ErrorMissingBlockhash = 4 - - ErrorJson = 10 - ErrorIO = 11 - ErrorRlp = 12 - - stdinSelector = "stdin" -) - -type NumberedError struct { - errorCode int - err error -} - -func NewError(errorCode int, err error) *NumberedError { - return &NumberedError{errorCode, err} -} - -func (n *NumberedError) Error() string { - return fmt.Sprintf("ERROR(%d): %v", n.errorCode, n.err.Error()) -} - -func (n *NumberedError) ExitCode() int { - return n.errorCode -} - -// compile-time conformance test -var ( - _ cli.ExitCoder = (*NumberedError)(nil) -) - -type input struct { - Alloc types.GenesisAlloc `json:"alloc,omitempty"` - Env *stEnv `json:"env,omitempty"` - Txs []*txWithKey `json:"txs,omitempty"` - TxRlp string `json:"txsRlp,omitempty"` -} - -func Transition(ctx *cli.Context) error { - var getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) { return nil, nil } - - baseDir, err := createBasedir(ctx) - if err != nil { - return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err)) - } - - if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing - // Configure the EVM logger - logConfig := &logger.Config{ - DisableStack: ctx.Bool(TraceDisableStackFlag.Name), - EnableMemory: ctx.Bool(TraceEnableMemoryFlag.Name), - EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name), - Debug: true, - } - getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) { - traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String()))) - if err != nil { - return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err)) - } - return &traceWriter{logger.NewJSONLogger(logConfig, traceFile), traceFile}, nil - } - } else if ctx.IsSet(TraceTracerFlag.Name) { - var config json.RawMessage - if ctx.IsSet(TraceTracerConfigFlag.Name) { - config = []byte(ctx.String(TraceTracerConfigFlag.Name)) - } - getTracer = func(txIndex int, txHash common.Hash) (vm.EVMLogger, error) { - traceFile, err := os.Create(path.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String()))) - if err != nil { - return nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err)) - } - tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config) - if err != nil { - return nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err)) - } - return &traceWriter{tracer, traceFile}, nil - } - } - // We need to load three things: alloc, env and transactions. May be either in - // stdin input or in files. - // Check if anything needs to be read from stdin - var ( - prestate Prestate - txIt txIterator // txs to apply - allocStr = ctx.String(InputAllocFlag.Name) - - envStr = ctx.String(InputEnvFlag.Name) - txStr = ctx.String(InputTxsFlag.Name) - inputData = &input{} - ) - // Figure out the prestate alloc - if allocStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector { - decoder := json.NewDecoder(os.Stdin) - if err := decoder.Decode(inputData); err != nil { - return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err)) - } - } - if allocStr != stdinSelector { - if err := readFile(allocStr, "alloc", &inputData.Alloc); err != nil { - return err - } - } - prestate.Pre = inputData.Alloc - - // Set the block environment - if envStr != stdinSelector { - var env stEnv - if err := readFile(envStr, "env", &env); err != nil { - return err - } - inputData.Env = &env - } - prestate.Env = *inputData.Env - - vmConfig := vm.Config{} - // Construct the chainconfig - var chainConfig *params.ChainConfig - if cConf, extraEips, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil { - return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err)) - } else { - chainConfig = cConf - vmConfig.ExtraEips = extraEips - } - // Set the chain id - chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name)) - - if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil { - return err - } - if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil { - return err - } - if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil { - return err - } - if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil { - return err - } - if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil { - return err - } - // Run the test and aggregate the result - s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer) - if err != nil { - return err - } - // Dump the execution result - collector := make(Alloc) - s.DumpToCollector(collector, nil) - return dispatchOutput(ctx, baseDir, result, collector, body) -} - -func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { - if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) { - return nil - } - // Sanity check, to not `panic` in state_transition - if env.BaseFee != nil { - // Already set, base fee has precedent over parent base fee. - return nil - } - if env.ParentBaseFee == nil || env.Number == 0 { - return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) - } - env.BaseFee = eip1559.CalcBaseFee(chainConfig, &types.Header{ - Number: new(big.Int).SetUint64(env.Number - 1), - BaseFee: env.ParentBaseFee, - GasUsed: env.ParentGasUsed, - GasLimit: env.ParentGasLimit, - }) - return nil -} - -func applyShanghaiChecks(env *stEnv, chainConfig *params.ChainConfig) error { - if !chainConfig.IsShanghai(big.NewInt(int64(env.Number)), env.Timestamp) { - return nil - } - if env.Withdrawals == nil { - return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) - } - return nil -} - -func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error { - isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0 - if !isMerged { - // pre-merge: If difficulty was not provided by caller, we need to calculate it. - if env.Difficulty != nil { - // already set - return nil - } - switch { - case env.ParentDifficulty == nil: - return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty")) - case env.Number == 0: - return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0")) - case env.Timestamp <= env.ParentTimestamp: - return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)", - env.Timestamp, env.ParentTimestamp)) - } - env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp, - env.ParentTimestamp, env.ParentDifficulty, env.ParentUncleHash) - return nil - } - // post-merge: - // - random must be supplied - // - difficulty must be zero - switch { - case env.Random == nil: - return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env")) - case env.Difficulty != nil && env.Difficulty.BitLen() != 0: - return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env")) - } - env.Difficulty = nil - return nil -} - -func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error { - if !chainConfig.IsCancun(big.NewInt(int64(env.Number)), env.Timestamp) { - env.ParentBeaconBlockRoot = nil // un-set it if it has been set too early - return nil - } - // Post-cancun - // We require EIP-4788 beacon root to be set in the env - if env.ParentBeaconBlockRoot == nil { - return NewError(ErrorConfig, errors.New("post-cancun env requires parentBeaconBlockRoot to be set")) - } - return nil -} - -type Alloc map[common.Address]types.Account - -func (g Alloc) OnRoot(common.Hash) {} - -func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) { - if addr == nil { - return - } - balance, _ := new(big.Int).SetString(dumpAccount.Balance, 0) - var storage map[common.Hash]common.Hash - if dumpAccount.Storage != nil { - storage = make(map[common.Hash]common.Hash) - for k, v := range dumpAccount.Storage { - storage[k] = common.HexToHash(v) - } - } - genesisAccount := types.Account{ - Code: dumpAccount.Code, - Storage: storage, - Balance: balance, - Nonce: dumpAccount.Nonce, - } - g[*addr] = genesisAccount -} - -// saveFile marshals the object to the given file -func saveFile(baseDir, filename string, data interface{}) error { - b, err := json.MarshalIndent(data, "", " ") - if err != nil { - return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err)) - } - location := path.Join(baseDir, filename) - if err = os.WriteFile(location, b, 0644); err != nil { - return NewError(ErrorIO, fmt.Errorf("failed writing output: %v", err)) - } - log.Info("Wrote file", "file", location) - return nil -} - -// dispatchOutput writes the output data to either stderr or stdout, or to the specified -// files -func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, body hexutil.Bytes) error { - stdOutObject := make(map[string]interface{}) - stdErrObject := make(map[string]interface{}) - dispatch := func(baseDir, fName, name string, obj interface{}) error { - switch fName { - case "stdout": - stdOutObject[name] = obj - case "stderr": - stdErrObject[name] = obj - case "": - // don't save - default: // save to file - if err := saveFile(baseDir, fName, obj); err != nil { - return err - } - } - return nil - } - if err := dispatch(baseDir, ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil { - return err - } - if err := dispatch(baseDir, ctx.String(OutputResultFlag.Name), "result", result); err != nil { - return err - } - if err := dispatch(baseDir, ctx.String(OutputBodyFlag.Name), "body", body); err != nil { - return err - } - if len(stdOutObject) > 0 { - b, err := json.MarshalIndent(stdOutObject, "", " ") - if err != nil { - return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err)) - } - os.Stdout.Write(b) - os.Stdout.WriteString("\n") - } - if len(stdErrObject) > 0 { - b, err := json.MarshalIndent(stdErrObject, "", " ") - if err != nil { - return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err)) - } - os.Stderr.Write(b) - os.Stderr.WriteString("\n") - } - return nil -} diff --git a/builder/cmd/evm/internal/t8ntool/tx_iterator.go b/builder/cmd/evm/internal/t8ntool/tx_iterator.go deleted file mode 100644 index 8f28dc702..000000000 --- a/builder/cmd/evm/internal/t8ntool/tx_iterator.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "bytes" - "crypto/ecdsa" - "encoding/json" - "fmt" - "io" - "os" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -// txWithKey is a helper-struct, to allow us to use the types.Transaction along with -// a `secretKey`-field, for input -type txWithKey struct { - key *ecdsa.PrivateKey - tx *types.Transaction - protected bool -} - -func (t *txWithKey) UnmarshalJSON(input []byte) error { - // Read the metadata, if present - type txMetadata struct { - Key *common.Hash `json:"secretKey"` - Protected *bool `json:"protected"` - } - var data txMetadata - if err := json.Unmarshal(input, &data); err != nil { - return err - } - if data.Key != nil { - k := data.Key.Hex()[2:] - if ecdsaKey, err := crypto.HexToECDSA(k); err != nil { - return err - } else { - t.key = ecdsaKey - } - } - if data.Protected != nil { - t.protected = *data.Protected - } else { - t.protected = true - } - // Now, read the transaction itself - var tx types.Transaction - if err := json.Unmarshal(input, &tx); err != nil { - return err - } - t.tx = &tx - return nil -} - -// signUnsignedTransactions converts the input txs to canonical transactions. -// -// The transactions can have two forms, either -// 1. unsigned or -// 2. signed -// -// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set. -// If so, we sign it here and now, with the given `secretKey` -// If the condition above is not met, then it's considered a signed transaction. -// -// To manage this, we read the transactions twice, first trying to read the secretKeys, -// and secondly to read them with the standard tx json format -func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) { - var signedTxs []*types.Transaction - for i, tx := range txs { - var ( - v, r, s = tx.tx.RawSignatureValues() - signed *types.Transaction - err error - ) - if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 { - // Already signed - signedTxs = append(signedTxs, tx.tx) - continue - } - // This transaction needs to be signed - if tx.protected { - signed, err = types.SignTx(tx.tx, signer, tx.key) - } else { - signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key) - } - if err != nil { - return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err)) - } - signedTxs = append(signedTxs, signed) - } - return signedTxs, nil -} - -func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) { - var txsWithKeys []*txWithKey - if txStr != stdinSelector { - data, err := os.ReadFile(txStr) - if err != nil { - return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err)) - } - if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list - var body hexutil.Bytes - if err := json.Unmarshal(data, &body); err != nil { - return nil, err - } - return newRlpTxIterator(body), nil - } - if err := json.Unmarshal(data, &txsWithKeys); err != nil { - return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err)) - } - } else { - if len(inputData.TxRlp) > 0 { - // Decode the body of already signed transactions - return newRlpTxIterator(common.FromHex(inputData.TxRlp)), nil - } - // JSON encoded transactions - txsWithKeys = inputData.Txs - } - // We may have to sign the transactions. - signer := types.LatestSignerForChainID(chainConfig.ChainID) - txs, err := signUnsignedTransactions(txsWithKeys, signer) - return newSliceTxIterator(txs), err -} - -type txIterator interface { - // Next returns true until EOF - Next() bool - // Tx returns the next transaction, OR an error. - Tx() (*types.Transaction, error) -} - -type sliceTxIterator struct { - idx int - txs []*types.Transaction -} - -func newSliceTxIterator(transactions types.Transactions) txIterator { - return &sliceTxIterator{0, transactions} -} - -func (ait *sliceTxIterator) Next() bool { - return ait.idx < len(ait.txs) -} - -func (ait *sliceTxIterator) Tx() (*types.Transaction, error) { - if ait.idx < len(ait.txs) { - ait.idx++ - return ait.txs[ait.idx-1], nil - } - return nil, io.EOF -} - -type rlpTxIterator struct { - in *rlp.Stream -} - -func newRlpTxIterator(rlpData []byte) txIterator { - in := rlp.NewStream(bytes.NewBuffer(rlpData), 1024*1024) - in.List() - return &rlpTxIterator{in} -} - -func (it *rlpTxIterator) Next() bool { - return it.in.MoreDataInList() -} - -func (it *rlpTxIterator) Tx() (*types.Transaction, error) { - var a types.Transaction - if err := it.in.Decode(&a); err != nil { - return nil, err - } - return &a, nil -} diff --git a/builder/cmd/evm/internal/t8ntool/utils.go b/builder/cmd/evm/internal/t8ntool/utils.go deleted file mode 100644 index 8ec38c761..000000000 --- a/builder/cmd/evm/internal/t8ntool/utils.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package t8ntool - -import ( - "encoding/json" - "fmt" - "os" - - "github.com/urfave/cli/v2" -) - -// readFile reads the json-data in the provided path and marshals into dest. -func readFile(path, desc string, dest interface{}) error { - inFile, err := os.Open(path) - if err != nil { - return NewError(ErrorIO, fmt.Errorf("failed reading %s file: %v", desc, err)) - } - defer inFile.Close() - decoder := json.NewDecoder(inFile) - if err := decoder.Decode(dest); err != nil { - return NewError(ErrorJson, fmt.Errorf("failed unmarshaling %s file: %v", desc, err)) - } - return nil -} - -// createBasedir makes sure the basedir exists, if user specified one. -func createBasedir(ctx *cli.Context) (string, error) { - baseDir := "" - if ctx.IsSet(OutputBasedir.Name) { - if base := ctx.String(OutputBasedir.Name); len(base) > 0 { - err := os.MkdirAll(base, 0755) // //rw-r--r-- - if err != nil { - return "", err - } - baseDir = base - } - } - return baseDir, nil -} diff --git a/builder/cmd/evm/main.go b/builder/cmd/evm/main.go deleted file mode 100644 index c3e6a4af9..000000000 --- a/builder/cmd/evm/main.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// evm executes EVM code snippets. -package main - -import ( - "fmt" - "math/big" - "os" - - "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" - "github.com/ethereum/go-ethereum/internal/debug" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/urfave/cli/v2" - - // Force-load the tracer engines to trigger registration - _ "github.com/ethereum/go-ethereum/eth/tracers/js" - _ "github.com/ethereum/go-ethereum/eth/tracers/native" -) - -var ( - DebugFlag = &cli.BoolFlag{ - Name: "debug", - Usage: "output full trace logs", - Category: flags.VMCategory, - } - StatDumpFlag = &cli.BoolFlag{ - Name: "statdump", - Usage: "displays stack and heap memory information", - Category: flags.VMCategory, - } - CodeFlag = &cli.StringFlag{ - Name: "code", - Usage: "EVM code", - Category: flags.VMCategory, - } - CodeFileFlag = &cli.StringFlag{ - Name: "codefile", - Usage: "File containing EVM code. If '-' is specified, code is read from stdin ", - Category: flags.VMCategory, - } - GasFlag = &cli.Uint64Flag{ - Name: "gas", - Usage: "gas limit for the evm", - Value: 10000000000, - Category: flags.VMCategory, - } - PriceFlag = &flags.BigFlag{ - Name: "price", - Usage: "price set for the evm", - Value: new(big.Int), - Category: flags.VMCategory, - } - ValueFlag = &flags.BigFlag{ - Name: "value", - Usage: "value set for the evm", - Value: new(big.Int), - Category: flags.VMCategory, - } - DumpFlag = &cli.BoolFlag{ - Name: "dump", - Usage: "dumps the state after the run", - Category: flags.VMCategory, - } - InputFlag = &cli.StringFlag{ - Name: "input", - Usage: "input for the EVM", - Category: flags.VMCategory, - } - InputFileFlag = &cli.StringFlag{ - Name: "inputfile", - Usage: "file containing input for the EVM", - Category: flags.VMCategory, - } - BenchFlag = &cli.BoolFlag{ - Name: "bench", - Usage: "benchmark the execution", - Category: flags.VMCategory, - } - CreateFlag = &cli.BoolFlag{ - Name: "create", - Usage: "indicates the action should be create rather than call", - Category: flags.VMCategory, - } - GenesisFlag = &cli.StringFlag{ - Name: "prestate", - Usage: "JSON file with prestate (genesis) config", - Category: flags.VMCategory, - } - MachineFlag = &cli.BoolFlag{ - Name: "json", - Usage: "output trace logs in machine readable format (json)", - Category: flags.VMCategory, - } - SenderFlag = &cli.StringFlag{ - Name: "sender", - Usage: "The transaction origin", - Category: flags.VMCategory, - } - ReceiverFlag = &cli.StringFlag{ - Name: "receiver", - Usage: "The transaction receiver (execution context)", - Category: flags.VMCategory, - } - DisableMemoryFlag = &cli.BoolFlag{ - Name: "nomemory", - Value: true, - Usage: "disable memory output", - Category: flags.VMCategory, - } - DisableStackFlag = &cli.BoolFlag{ - Name: "nostack", - Usage: "disable stack output", - Category: flags.VMCategory, - } - DisableStorageFlag = &cli.BoolFlag{ - Name: "nostorage", - Usage: "disable storage output", - Category: flags.VMCategory, - } - DisableReturnDataFlag = &cli.BoolFlag{ - Name: "noreturndata", - Value: true, - Usage: "enable return data output", - Category: flags.VMCategory, - } -) - -var stateTransitionCommand = &cli.Command{ - Name: "transition", - Aliases: []string{"t8n"}, - Usage: "Executes a full state transition", - Action: t8ntool.Transition, - Flags: []cli.Flag{ - t8ntool.TraceFlag, - t8ntool.TraceTracerFlag, - t8ntool.TraceTracerConfigFlag, - t8ntool.TraceEnableMemoryFlag, - t8ntool.TraceDisableStackFlag, - t8ntool.TraceEnableReturnDataFlag, - t8ntool.OutputBasedir, - t8ntool.OutputAllocFlag, - t8ntool.OutputResultFlag, - t8ntool.OutputBodyFlag, - t8ntool.InputAllocFlag, - t8ntool.InputEnvFlag, - t8ntool.InputTxsFlag, - t8ntool.ForknameFlag, - t8ntool.ChainIDFlag, - t8ntool.RewardFlag, - }, -} - -var transactionCommand = &cli.Command{ - Name: "transaction", - Aliases: []string{"t9n"}, - Usage: "Performs transaction validation", - Action: t8ntool.Transaction, - Flags: []cli.Flag{ - t8ntool.InputTxsFlag, - t8ntool.ChainIDFlag, - t8ntool.ForknameFlag, - }, -} - -var blockBuilderCommand = &cli.Command{ - Name: "block-builder", - Aliases: []string{"b11r"}, - Usage: "Builds a block", - Action: t8ntool.BuildBlock, - Flags: []cli.Flag{ - t8ntool.OutputBasedir, - t8ntool.OutputBlockFlag, - t8ntool.InputHeaderFlag, - t8ntool.InputOmmersFlag, - t8ntool.InputWithdrawalsFlag, - t8ntool.InputTxsRlpFlag, - t8ntool.SealCliqueFlag, - }, -} - -// vmFlags contains flags related to running the EVM. -var vmFlags = []cli.Flag{ - CodeFlag, - CodeFileFlag, - CreateFlag, - GasFlag, - PriceFlag, - ValueFlag, - InputFlag, - InputFileFlag, - GenesisFlag, - SenderFlag, - ReceiverFlag, -} - -// traceFlags contains flags that configure tracing output. -var traceFlags = []cli.Flag{ - BenchFlag, - DebugFlag, - DumpFlag, - MachineFlag, - StatDumpFlag, - DisableMemoryFlag, - DisableStackFlag, - DisableStorageFlag, - DisableReturnDataFlag, -} - -var app = flags.NewApp("the evm command line interface") - -func init() { - app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags) - app.Commands = []*cli.Command{ - compileCommand, - disasmCommand, - runCommand, - blockTestCommand, - stateTestCommand, - stateTransitionCommand, - transactionCommand, - blockBuilderCommand, - } - app.Before = func(ctx *cli.Context) error { - flags.MigrateGlobalFlags(ctx) - return debug.Setup(ctx) - } - app.After = func(ctx *cli.Context) error { - debug.Exit() - return nil - } -} - -func main() { - if err := app.Run(os.Args); err != nil { - code := 1 - if ec, ok := err.(*t8ntool.NumberedError); ok { - code = ec.ExitCode() - } - fmt.Fprintln(os.Stderr, err) - os.Exit(code) - } -} diff --git a/builder/cmd/evm/runner.go b/builder/cmd/evm/runner.go deleted file mode 100644 index b8e8b542b..000000000 --- a/builder/cmd/evm/runner.go +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "math/big" - "os" - goruntime "runtime" - "testing" - "time" - - "github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/core/vm/runtime" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/urfave/cli/v2" -) - -var runCommand = &cli.Command{ - Action: runCmd, - Name: "run", - Usage: "Run arbitrary evm binary", - ArgsUsage: "", - Description: `The run command runs arbitrary EVM code.`, - Flags: flags.Merge(vmFlags, traceFlags), -} - -// readGenesis will read the given JSON format genesis file and return -// the initialized Genesis structure -func readGenesis(genesisPath string) *core.Genesis { - // Make sure we have a valid genesis JSON - //genesisPath := ctx.Args().First() - if len(genesisPath) == 0 { - utils.Fatalf("Must supply path to genesis JSON file") - } - file, err := os.Open(genesisPath) - if err != nil { - utils.Fatalf("Failed to read genesis file: %v", err) - } - defer file.Close() - - genesis := new(core.Genesis) - if err := json.NewDecoder(file).Decode(genesis); err != nil { - utils.Fatalf("invalid genesis file: %v", err) - } - return genesis -} - -type execStats struct { - time time.Duration // The execution time. - allocs int64 // The number of heap allocations during execution. - bytesAllocated int64 // The cumulative number of bytes allocated during execution. -} - -func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) (output []byte, gasLeft uint64, stats execStats, err error) { - if bench { - result := testing.Benchmark(func(b *testing.B) { - for i := 0; i < b.N; i++ { - output, gasLeft, err = execFunc() - } - }) - - // Get the average execution time from the benchmarking result. - // There are other useful stats here that could be reported. - stats.time = time.Duration(result.NsPerOp()) - stats.allocs = result.AllocsPerOp() - stats.bytesAllocated = result.AllocedBytesPerOp() - } else { - var memStatsBefore, memStatsAfter goruntime.MemStats - goruntime.ReadMemStats(&memStatsBefore) - startTime := time.Now() - output, gasLeft, err = execFunc() - stats.time = time.Since(startTime) - goruntime.ReadMemStats(&memStatsAfter) - stats.allocs = int64(memStatsAfter.Mallocs - memStatsBefore.Mallocs) - stats.bytesAllocated = int64(memStatsAfter.TotalAlloc - memStatsBefore.TotalAlloc) - } - - return output, gasLeft, stats, err -} - -func runCmd(ctx *cli.Context) error { - logconfig := &logger.Config{ - EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), - DisableStack: ctx.Bool(DisableStackFlag.Name), - DisableStorage: ctx.Bool(DisableStorageFlag.Name), - EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), - Debug: ctx.Bool(DebugFlag.Name), - } - - var ( - tracer vm.EVMLogger - debugLogger *logger.StructLogger - statedb *state.StateDB - chainConfig *params.ChainConfig - sender = common.BytesToAddress([]byte("sender")) - receiver = common.BytesToAddress([]byte("receiver")) - preimages = ctx.Bool(DumpFlag.Name) - blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests - blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests - ) - if ctx.Bool(MachineFlag.Name) { - tracer = logger.NewJSONLogger(logconfig, os.Stdout) - } else if ctx.Bool(DebugFlag.Name) { - debugLogger = logger.NewStructLogger(logconfig) - tracer = debugLogger - } else { - debugLogger = logger.NewStructLogger(logconfig) - } - - initialGas := ctx.Uint64(GasFlag.Name) - genesisConfig := new(core.Genesis) - genesisConfig.GasLimit = initialGas - if ctx.String(GenesisFlag.Name) != "" { - genesisConfig = readGenesis(ctx.String(GenesisFlag.Name)) - if genesisConfig.GasLimit != 0 { - initialGas = genesisConfig.GasLimit - } - } else { - genesisConfig.Config = params.AllDevChainProtocolChanges - } - - db := rawdb.NewMemoryDatabase() - triedb := triedb.NewDatabase(db, &triedb.Config{ - Preimages: preimages, - HashDB: hashdb.Defaults, - }) - defer triedb.Close() - genesis := genesisConfig.MustCommit(db, triedb) - sdb := state.NewDatabaseWithNodeDB(db, triedb) - statedb, _ = state.New(genesis.Root(), sdb, nil) - chainConfig = genesisConfig.Config - - if ctx.String(SenderFlag.Name) != "" { - sender = common.HexToAddress(ctx.String(SenderFlag.Name)) - } - statedb.CreateAccount(sender) - - if ctx.String(ReceiverFlag.Name) != "" { - receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name)) - } - - var code []byte - codeFileFlag := ctx.String(CodeFileFlag.Name) - codeFlag := ctx.String(CodeFlag.Name) - - // The '--code' or '--codefile' flag overrides code in state - if codeFileFlag != "" || codeFlag != "" { - var hexcode []byte - if codeFileFlag != "" { - var err error - // If - is specified, it means that code comes from stdin - if codeFileFlag == "-" { - //Try reading from stdin - if hexcode, err = io.ReadAll(os.Stdin); err != nil { - fmt.Printf("Could not load code from stdin: %v\n", err) - os.Exit(1) - } - } else { - // Codefile with hex assembly - if hexcode, err = os.ReadFile(codeFileFlag); err != nil { - fmt.Printf("Could not load code from file: %v\n", err) - os.Exit(1) - } - } - } else { - hexcode = []byte(codeFlag) - } - hexcode = bytes.TrimSpace(hexcode) - if len(hexcode)%2 != 0 { - fmt.Printf("Invalid input length for hex data (%d)\n", len(hexcode)) - os.Exit(1) - } - code = common.FromHex(string(hexcode)) - } else if fn := ctx.Args().First(); len(fn) > 0 { - // EASM-file to compile - src, err := os.ReadFile(fn) - if err != nil { - return err - } - bin, err := compiler.Compile(fn, src, false) - if err != nil { - return err - } - code = common.Hex2Bytes(bin) - } - runtimeConfig := runtime.Config{ - Origin: sender, - State: statedb, - GasLimit: initialGas, - GasPrice: flags.GlobalBig(ctx, PriceFlag.Name), - Value: flags.GlobalBig(ctx, ValueFlag.Name), - Difficulty: genesisConfig.Difficulty, - Time: genesisConfig.Timestamp, - Coinbase: genesisConfig.Coinbase, - BlockNumber: new(big.Int).SetUint64(genesisConfig.Number), - BlobHashes: blobHashes, - BlobBaseFee: blobBaseFee, - EVMConfig: vm.Config{ - Tracer: tracer, - }, - } - - if chainConfig != nil { - runtimeConfig.ChainConfig = chainConfig - } else { - runtimeConfig.ChainConfig = params.AllEthashProtocolChanges - } - - var hexInput []byte - if inputFileFlag := ctx.String(InputFileFlag.Name); inputFileFlag != "" { - var err error - if hexInput, err = os.ReadFile(inputFileFlag); err != nil { - fmt.Printf("could not load input from file: %v\n", err) - os.Exit(1) - } - } else { - hexInput = []byte(ctx.String(InputFlag.Name)) - } - hexInput = bytes.TrimSpace(hexInput) - if len(hexInput)%2 != 0 { - fmt.Println("input length must be even") - os.Exit(1) - } - input := common.FromHex(string(hexInput)) - - var execFunc func() ([]byte, uint64, error) - if ctx.Bool(CreateFlag.Name) { - input = append(code, input...) - execFunc = func() ([]byte, uint64, error) { - output, _, gasLeft, err := runtime.Create(input, &runtimeConfig) - return output, gasLeft, err - } - } else { - if len(code) > 0 { - statedb.SetCode(receiver, code) - } - execFunc = func() ([]byte, uint64, error) { - return runtime.Call(receiver, input, &runtimeConfig) - } - } - - bench := ctx.Bool(BenchFlag.Name) - output, leftOverGas, stats, err := timedExec(bench, execFunc) - - if ctx.Bool(DumpFlag.Name) { - statedb.Commit(genesisConfig.Number, true) - fmt.Println(string(statedb.Dump(nil))) - } - - if ctx.Bool(DebugFlag.Name) { - if debugLogger != nil { - fmt.Fprintln(os.Stderr, "#### TRACE ####") - logger.WriteTrace(os.Stderr, debugLogger.StructLogs()) - } - fmt.Fprintln(os.Stderr, "#### LOGS ####") - logger.WriteLogs(os.Stderr, statedb.Logs()) - } - - if bench || ctx.Bool(StatDumpFlag.Name) { - fmt.Fprintf(os.Stderr, `EVM gas used: %d -execution time: %v -allocations: %d -allocated bytes: %d -`, initialGas-leftOverGas, stats.time, stats.allocs, stats.bytesAllocated) - } - if tracer == nil { - fmt.Printf("%#x\n", output) - if err != nil { - fmt.Printf(" error: %v\n", err) - } - } - - return nil -} diff --git a/builder/cmd/evm/staterunner.go b/builder/cmd/evm/staterunner.go deleted file mode 100644 index 458d809ad..000000000 --- a/builder/cmd/evm/staterunner.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bufio" - "encoding/json" - "fmt" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/tests" - "github.com/urfave/cli/v2" -) - -var stateTestCommand = &cli.Command{ - Action: stateTestCmd, - Name: "statetest", - Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).", - ArgsUsage: "", -} - -// StatetestResult contains the execution status after running a state test, any -// error that might have occurred and a dump of the final state if requested. -type StatetestResult struct { - Name string `json:"name"` - Pass bool `json:"pass"` - Root *common.Hash `json:"stateRoot,omitempty"` - Fork string `json:"fork"` - Error string `json:"error,omitempty"` - State *state.Dump `json:"state,omitempty"` -} - -func stateTestCmd(ctx *cli.Context) error { - // Configure the EVM logger - config := &logger.Config{ - EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), - DisableStack: ctx.Bool(DisableStackFlag.Name), - DisableStorage: ctx.Bool(DisableStorageFlag.Name), - EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), - } - var cfg vm.Config - switch { - case ctx.Bool(MachineFlag.Name): - cfg.Tracer = logger.NewJSONLogger(config, os.Stderr) - - case ctx.Bool(DebugFlag.Name): - cfg.Tracer = logger.NewStructLogger(config) - } - // Load the test content from the input file - if len(ctx.Args().First()) != 0 { - return runStateTest(ctx.Args().First(), cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name)) - } - // Read filenames from stdin and execute back-to-back - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - fname := scanner.Text() - if len(fname) == 0 { - return nil - } - if err := runStateTest(fname, cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name)); err != nil { - return err - } - } - return nil -} - -// runStateTest loads the state-test given by fname, and executes the test. -func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error { - src, err := os.ReadFile(fname) - if err != nil { - return err - } - var testsByName map[string]tests.StateTest - if err := json.Unmarshal(src, &testsByName); err != nil { - return err - } - - // Iterate over all the tests, run them and aggregate the results - results := make([]StatetestResult, 0, len(testsByName)) - for key, test := range testsByName { - for _, st := range test.Subtests() { - // Run the test and aggregate the result - result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} - test.Run(st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) { - var root common.Hash - if tstate.StateDB != nil { - root = tstate.StateDB.IntermediateRoot(false) - result.Root = &root - if jsonOut { - fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) - } - if dump { // Dump any state to aid debugging - cpy, _ := state.New(root, tstate.StateDB.Database(), nil) - dump := cpy.RawDump(nil) - result.State = &dump - } - } - if err != nil { - // Test failed, mark as so - result.Pass, result.Error = false, err.Error() - } - }) - results = append(results, *result) - } - } - out, _ := json.MarshalIndent(results, "", " ") - fmt.Println(string(out)) - return nil -} diff --git a/builder/cmd/evm/t8n_test.go b/builder/cmd/evm/t8n_test.go deleted file mode 100644 index ad36540de..000000000 --- a/builder/cmd/evm/t8n_test.go +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "fmt" - "os" - "reflect" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" - "github.com/ethereum/go-ethereum/internal/cmdtest" - "github.com/ethereum/go-ethereum/internal/reexec" -) - -func TestMain(m *testing.M) { - // Run the app if we've been exec'd as "ethkey-test" in runEthkey. - reexec.Register("evm-test", func() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - os.Exit(0) - }) - // check if we have been reexec'd - if reexec.Init() { - return - } - os.Exit(m.Run()) -} - -type testT8n struct { - *cmdtest.TestCmd -} - -type t8nInput struct { - inAlloc string - inTxs string - inEnv string - stFork string - stReward string -} - -func (args *t8nInput) get(base string) []string { - var out []string - if opt := args.inAlloc; opt != "" { - out = append(out, "--input.alloc") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inTxs; opt != "" { - out = append(out, "--input.txs") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inEnv; opt != "" { - out = append(out, "--input.env") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.stFork; opt != "" { - out = append(out, "--state.fork", opt) - } - if opt := args.stReward; opt != "" { - out = append(out, "--state.reward", opt) - } - return out -} - -type t8nOutput struct { - alloc bool - result bool - body bool -} - -func (args *t8nOutput) get() (out []string) { - if args.body { - out = append(out, "--output.body", "stdout") - } else { - out = append(out, "--output.body", "") // empty means ignore - } - if args.result { - out = append(out, "--output.result", "stdout") - } else { - out = append(out, "--output.result", "") - } - if args.alloc { - out = append(out, "--output.alloc", "stdout") - } else { - out = append(out, "--output.alloc", "") - } - return out -} - -func TestT8n(t *testing.T) { - t.Parallel() - tt := new(testT8n) - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - for i, tc := range []struct { - base string - input t8nInput - output t8nOutput - expExitCode int - expOut string - }{ - { // Test exit (3) on bad config - base: "./testdata/1", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Frontier+1346", "", - }, - output: t8nOutput{alloc: true, result: true}, - expExitCode: 3, - }, - { - base: "./testdata/1", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Byzantium", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // blockhash test - base: "./testdata/3", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Berlin", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // missing blockhash test - base: "./testdata/4", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Berlin", "", - }, - output: t8nOutput{alloc: true, result: true}, - expExitCode: 4, - }, - { // Uncle test - base: "./testdata/5", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Byzantium", "0x80", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // Sign json transactions - base: "./testdata/13", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "London", "", - }, - output: t8nOutput{body: true}, - expOut: "exp.json", - }, - { // Already signed transactions - base: "./testdata/13", - input: t8nInput{ - "alloc.json", "signed_txs.rlp", "env.json", "London", "", - }, - output: t8nOutput{result: true}, - expOut: "exp2.json", - }, - { // Difficulty calculation - no uncles - base: "./testdata/14", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "London", "", - }, - output: t8nOutput{result: true}, - expOut: "exp.json", - }, - { // Difficulty calculation - with uncles - base: "./testdata/14", - input: t8nInput{ - "alloc.json", "txs.json", "env.uncles.json", "London", "", - }, - output: t8nOutput{result: true}, - expOut: "exp2.json", - }, - { // Difficulty calculation - with ommers + Berlin - base: "./testdata/14", - input: t8nInput{ - "alloc.json", "txs.json", "env.uncles.json", "Berlin", "", - }, - output: t8nOutput{result: true}, - expOut: "exp_berlin.json", - }, - { // Difficulty calculation on arrow glacier - base: "./testdata/19", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "London", "", - }, - output: t8nOutput{result: true}, - expOut: "exp_london.json", - }, - { // Difficulty calculation on arrow glacier - base: "./testdata/19", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "ArrowGlacier", "", - }, - output: t8nOutput{result: true}, - expOut: "exp_arrowglacier.json", - }, - { // Difficulty calculation on gray glacier - base: "./testdata/19", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "GrayGlacier", "", - }, - output: t8nOutput{result: true}, - expOut: "exp_grayglacier.json", - }, - { // Sign unprotected (pre-EIP155) transaction - base: "./testdata/23", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Berlin", "", - }, - output: t8nOutput{result: true}, - expOut: "exp.json", - }, - { // Test post-merge transition - base: "./testdata/24", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Merge", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // Test post-merge transition where input is missing random - base: "./testdata/24", - input: t8nInput{ - "alloc.json", "txs.json", "env-missingrandom.json", "Merge", "", - }, - output: t8nOutput{alloc: false, result: false}, - expExitCode: 3, - }, - { // Test base fee calculation - base: "./testdata/25", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Merge", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // Test withdrawals transition - base: "./testdata/26", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Shanghai", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // Cancun tests - base: "./testdata/28", - input: t8nInput{ - "alloc.json", "txs.rlp", "env.json", "Cancun", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // More cancun tests - base: "./testdata/29", - input: t8nInput{ - "alloc.json", "txs.json", "env.json", "Cancun", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - { // More cancun test, plus example of rlp-transaction that cannot be decoded properly - base: "./testdata/30", - input: t8nInput{ - "alloc.json", "txs_more.rlp", "env.json", "Cancun", "", - }, - output: t8nOutput{alloc: true, result: true}, - expOut: "exp.json", - }, - } { - args := []string{"t8n"} - args = append(args, tc.output.get()...) - args = append(args, tc.input.get(tc.base)...) - var qArgs []string // quoted args for debugging purposes - for _, arg := range args { - if len(arg) == 0 { - qArgs = append(qArgs, `""`) - } else { - qArgs = append(qArgs, arg) - } - } - tt.Logf("args: %v\n", strings.Join(qArgs, " ")) - tt.Run("evm-test", args...) - // Compare the expected output, if provided - if tc.expOut != "" { - file := fmt.Sprintf("%v/%v", tc.base, tc.expOut) - want, err := os.ReadFile(file) - if err != nil { - t.Fatalf("test %d: could not read expected output: %v", i, err) - } - have := tt.Output() - ok, err := cmpJson(have, want) - switch { - case err != nil: - t.Fatalf("test %d, file %v: json parsing failed: %v", i, file, err) - case !ok: - t.Fatalf("test %d, file %v: output wrong, have \n%v\nwant\n%v\n", i, file, string(have), string(want)) - } - } - tt.WaitExit() - if have, want := tt.ExitStatus(), tc.expExitCode; have != want { - t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) - } - } -} - -type t9nInput struct { - inTxs string - stFork string -} - -func (args *t9nInput) get(base string) []string { - var out []string - if opt := args.inTxs; opt != "" { - out = append(out, "--input.txs") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.stFork; opt != "" { - out = append(out, "--state.fork", opt) - } - return out -} - -func TestT9n(t *testing.T) { - t.Parallel() - tt := new(testT8n) - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - for i, tc := range []struct { - base string - input t9nInput - expExitCode int - expOut string - }{ - { // London txs on homestead - base: "./testdata/15", - input: t9nInput{ - inTxs: "signed_txs.rlp", - stFork: "Homestead", - }, - expOut: "exp.json", - }, - { // London txs on London - base: "./testdata/15", - input: t9nInput{ - inTxs: "signed_txs.rlp", - stFork: "London", - }, - expOut: "exp2.json", - }, - { // An RLP list (a blockheader really) - base: "./testdata/15", - input: t9nInput{ - inTxs: "blockheader.rlp", - stFork: "London", - }, - expOut: "exp3.json", - }, - { // Transactions with too low gas - base: "./testdata/16", - input: t9nInput{ - inTxs: "signed_txs.rlp", - stFork: "London", - }, - expOut: "exp.json", - }, - { // Transactions with value exceeding 256 bits - base: "./testdata/17", - input: t9nInput{ - inTxs: "signed_txs.rlp", - stFork: "London", - }, - expOut: "exp.json", - }, - { // Invalid RLP - base: "./testdata/18", - input: t9nInput{ - inTxs: "invalid.rlp", - stFork: "London", - }, - expExitCode: t8ntool.ErrorIO, - }, - } { - args := []string{"t9n"} - args = append(args, tc.input.get(tc.base)...) - - tt.Run("evm-test", args...) - tt.Logf("args:\n go run . %v\n", strings.Join(args, " ")) - // Compare the expected output, if provided - if tc.expOut != "" { - want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) - if err != nil { - t.Fatalf("test %d: could not read expected output: %v", i, err) - } - have := tt.Output() - ok, err := cmpJson(have, want) - switch { - case err != nil: - t.Logf(string(have)) - t.Fatalf("test %d, json parsing failed: %v", i, err) - case !ok: - t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) - } - } - tt.WaitExit() - if have, want := tt.ExitStatus(), tc.expExitCode; have != want { - t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) - } - } -} - -type b11rInput struct { - inEnv string - inOmmersRlp string - inWithdrawals string - inTxsRlp string - inClique string - ethash bool - ethashMode string - ethashDir string -} - -func (args *b11rInput) get(base string) []string { - var out []string - if opt := args.inEnv; opt != "" { - out = append(out, "--input.header") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inOmmersRlp; opt != "" { - out = append(out, "--input.ommers") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inWithdrawals; opt != "" { - out = append(out, "--input.withdrawals") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inTxsRlp; opt != "" { - out = append(out, "--input.txs") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.inClique; opt != "" { - out = append(out, "--seal.clique") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if args.ethash { - out = append(out, "--seal.ethash") - } - if opt := args.ethashMode; opt != "" { - out = append(out, "--seal.ethash.mode") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - if opt := args.ethashDir; opt != "" { - out = append(out, "--seal.ethash.dir") - out = append(out, fmt.Sprintf("%v/%v", base, opt)) - } - out = append(out, "--output.block") - out = append(out, "stdout") - return out -} - -func TestB11r(t *testing.T) { - t.Parallel() - tt := new(testT8n) - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - for i, tc := range []struct { - base string - input b11rInput - expExitCode int - expOut string - }{ - { // unsealed block - base: "./testdata/20", - input: b11rInput{ - inEnv: "header.json", - inOmmersRlp: "ommers.json", - inTxsRlp: "txs.rlp", - }, - expOut: "exp.json", - }, - { // ethash test seal - base: "./testdata/21", - input: b11rInput{ - inEnv: "header.json", - inOmmersRlp: "ommers.json", - inTxsRlp: "txs.rlp", - }, - expOut: "exp.json", - }, - { // clique test seal - base: "./testdata/21", - input: b11rInput{ - inEnv: "header.json", - inOmmersRlp: "ommers.json", - inTxsRlp: "txs.rlp", - inClique: "clique.json", - }, - expOut: "exp-clique.json", - }, - { // block with ommers - base: "./testdata/22", - input: b11rInput{ - inEnv: "header.json", - inOmmersRlp: "ommers.json", - inTxsRlp: "txs.rlp", - }, - expOut: "exp.json", - }, - { // block with withdrawals - base: "./testdata/27", - input: b11rInput{ - inEnv: "header.json", - inOmmersRlp: "ommers.json", - inWithdrawals: "withdrawals.json", - inTxsRlp: "txs.rlp", - }, - expOut: "exp.json", - }, - } { - args := []string{"b11r"} - args = append(args, tc.input.get(tc.base)...) - - tt.Run("evm-test", args...) - tt.Logf("args:\n go run . %v\n", strings.Join(args, " ")) - // Compare the expected output, if provided - if tc.expOut != "" { - want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) - if err != nil { - t.Fatalf("test %d: could not read expected output: %v", i, err) - } - have := tt.Output() - ok, err := cmpJson(have, want) - switch { - case err != nil: - t.Logf(string(have)) - t.Fatalf("test %d, json parsing failed: %v", i, err) - case !ok: - t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) - } - } - tt.WaitExit() - if have, want := tt.ExitStatus(), tc.expExitCode; have != want { - t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) - } - } -} - -// cmpJson compares the JSON in two byte slices. -func cmpJson(a, b []byte) (bool, error) { - var j, j2 interface{} - if err := json.Unmarshal(a, &j); err != nil { - return false, err - } - if err := json.Unmarshal(b, &j2); err != nil { - return false, err - } - return reflect.DeepEqual(j2, j), nil -} diff --git a/builder/cmd/evm/testdata/1/alloc.json b/builder/cmd/evm/testdata/1/alloc.json deleted file mode 100644 index cef1a25ff..000000000 --- a/builder/cmd/evm/testdata/1/alloc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192":{ - "balance": "0xfeedbead", - "nonce" : "0x00" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/1/env.json b/builder/cmd/evm/testdata/1/env.json deleted file mode 100644 index dd60abd20..000000000 --- a/builder/cmd/evm/testdata/1/env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x750a163df65e8a", - "currentNumber": "1", - "currentTimestamp": "1000" -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/1/exp.json b/builder/cmd/evm/testdata/1/exp.json deleted file mode 100644 index d1351e5b7..000000000 --- a/builder/cmd/evm/testdata/1/exp.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "alloc": { - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "balance": "0xfeed1a9d", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "nonce": "0xac" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xa410" - } - }, - "result": { - "stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13", - "txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "rejected": [ - { - "index": 1, - "error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x5208" - } -} diff --git a/builder/cmd/evm/testdata/1/txs.json b/builder/cmd/evm/testdata/1/txs.json deleted file mode 100644 index 50b31ff31..000000000 --- a/builder/cmd/evm/testdata/1/txs.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "gas": "0x5208", - "gasPrice": "0x2", - "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "input": "0x", - "nonce": "0x0", - "r": "0x9500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdb", - "s": "0x7235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "v": "0x1b", - "value": "0x1" - }, - { - "gas": "0x5208", - "gasPrice": "0x2", - "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "input": "0x", - "nonce": "0x0", - "r": "0x9500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdb", - "s": "0x7235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "v": "0x1b", - "value": "0x1" - } -] diff --git a/builder/cmd/evm/testdata/10/alloc.json b/builder/cmd/evm/testdata/10/alloc.json deleted file mode 100644 index 6e98e7513..000000000 --- a/builder/cmd/evm/testdata/10/alloc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "0x1111111111111111111111111111111111111111" : { - "balance" : "0x010000000000", - "code" : "0xfe", - "nonce" : "0x01", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x010000000000", - "code" : "0x", - "nonce" : "0x01", - "storage" : { - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363" : { - "balance" : "0x01000000000000", - "code" : "0x", - "nonce" : "0x01", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/10/env.json b/builder/cmd/evm/testdata/10/env.json deleted file mode 100644 index 3a82d46a7..000000000 --- a/builder/cmd/evm/testdata/10/env.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentNumber" : "0x01", - "currentTimestamp" : "0x079e", - "previousHash" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f", - "currentGasLimit" : "0x40000000", - "currentBaseFee" : "0x036b", - "blockHashes" : { - "0" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/10/readme.md b/builder/cmd/evm/testdata/10/readme.md deleted file mode 100644 index afa378723..000000000 --- a/builder/cmd/evm/testdata/10/readme.md +++ /dev/null @@ -1,85 +0,0 @@ -## EIP-1559 testing - -This test contains testcases for EIP-1559, which were reported by Ori as misbehaving. - -``` -[user@work evm]$ dir=./testdata/10 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout 2>&1 -INFO [05-09|22:11:59.436] rejected tx index=3 hash=db07bf..ede1e8 from=0xd02d72E067e77158444ef2020Ff2d325f929B363 error="gas limit reached" -``` -Output: -```json -{ - "alloc": { - "0x1111111111111111111111111111111111111111": { - "code": "0xfe", - "balance": "0x10000000000", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x10000000000", - "nonce": "0x1" - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "balance": "0xff5beffffc95", - "nonce": "0x4" - } - }, - "result": { - "stateRoot": "0xf91a7ec08e4bfea88719aab34deabb000c86902360532b52afa9599d41f2bb8b", - "txRoot": "0xda925f2306a52fa24c15d5cd212d736ee016415fd8dd0c45fd368de7917d64bb", - "receiptsRoot": "0x439a25f7fc424c10fb1f89800e4aa1df74156b137239d9ac3eaa7c911c353cd5", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x10000001", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x88980f6efcc5358d9c359663e7b9414722d430497637340ea056b076bc206701", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000001", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x20000001", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0xd7bf3886f4e2aef74d525ae072c680f3846f550254401b67cbfda4a233757582", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000000", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x30000001", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x50308296760f01f1eeec7500e9e73cad67469249b1f59e9a9f55e6625a4923db", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x10000000", - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x2" - } - ], - "rejected": [ - { - "index": 3, - "error": "gas limit reached" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x30000001", - "currentBaseFee": "0x36b" - } -} -``` diff --git a/builder/cmd/evm/testdata/10/txs.json b/builder/cmd/evm/testdata/10/txs.json deleted file mode 100644 index f7c9baa26..000000000 --- a/builder/cmd/evm/testdata/10/txs.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x10000001", - "nonce" : "0x1", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x7a45f00bcde9036b026cdf1628b023cd8a31a95c62b5e4dbbee2fa7debe668fb", - "s" : "0x3cc9d6f2cd00a045b0263f2d6dad7d60938d5d13d061af4969f95928aa934d4a", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [ - ] - }, - { - "input" : "0x", - "gas" : "0x10000000", - "nonce" : "0x2", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x4c564b94b0281a8210eeec2dd1fe2e16ff1c1903a8c3a1078d735d7f8208b2af", - "s" : "0x56432b2593e6de95db1cb997b7385217aca03f1615327e231734446b39f266d", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [ - ] - }, - { - "input" : "0x", - "gas" : "0x10000000", - "nonce" : "0x3", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x2ed2ef52f924f59d4a21e1f2a50d3b1109303ce5e32334a7ece9b46f4fbc2a57", - "s" : "0x2980257129cbd3da987226f323d50ba3975a834d165e0681f991b75615605c44", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [ - ] - }, - { - "input" : "0x", - "gas" : "0x10000000", - "nonce" : "0x4", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x5df7d7f8f8e15b36fc9f189cacb625040fad10398d08fc90812595922a2c49b2", - "s" : "0x565fc1803f77a84d754ffe3c5363ab54a8d93a06ea1bb9d4c73c73a282b35917", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [ - ] - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/11/alloc.json b/builder/cmd/evm/testdata/11/alloc.json deleted file mode 100644 index 86938230f..000000000 --- a/builder/cmd/evm/testdata/11/alloc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x61ffff5060046000f3", - "nonce" : "0x01", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - "0x00" : "0x00" - } - }, - "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x00", - "code" : "0x6001600055", - "nonce" : "0x00", - "storage" : { - } - } -} - diff --git a/builder/cmd/evm/testdata/11/env.json b/builder/cmd/evm/testdata/11/env.json deleted file mode 100644 index 37dedf094..000000000 --- a/builder/cmd/evm/testdata/11/env.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentNumber" : "0x01", - "currentTimestamp" : "0x03e8", - "previousHash" : "0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2", - "currentGasLimit" : "0x0f4240", - "blockHashes" : { - "0" : "0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2" - } -} - diff --git a/builder/cmd/evm/testdata/11/readme.md b/builder/cmd/evm/testdata/11/readme.md deleted file mode 100644 index d499f8e99..000000000 --- a/builder/cmd/evm/testdata/11/readme.md +++ /dev/null @@ -1,13 +0,0 @@ -## Test missing basefee - -In this test, the `currentBaseFee` is missing from the env portion. -On a live blockchain, the basefee is present in the header, and verified as part of header validation. - -In `evm t8n`, we don't have blocks, so it needs to be added in the `env`instead. - -When it's missing, an error is expected. - -``` -dir=./testdata/11 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout 2>&1>/dev/null -ERROR(3): EIP-1559 config but missing 'currentBaseFee' in env section -``` \ No newline at end of file diff --git a/builder/cmd/evm/testdata/11/txs.json b/builder/cmd/evm/testdata/11/txs.json deleted file mode 100644 index c54b0a1f5..000000000 --- a/builder/cmd/evm/testdata/11/txs.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "input" : "0x38600060013960015160005560006000f3", - "gas" : "0x61a80", - "gasPrice" : "0x1", - "nonce" : "0x0", - "value" : "0x186a0", - "v" : "0x1c", - "r" : "0x2e1391fd903387f1cc2b51df083805fb4bbb0d4710a2cdf4a044d191ff7be63e", - "s" : "0x7f10a933c42ab74927db02b1db009e923d9d2ab24ac24d63c399f2fe5d9c9b22", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] - diff --git a/builder/cmd/evm/testdata/12/alloc.json b/builder/cmd/evm/testdata/12/alloc.json deleted file mode 100644 index 3ed96894f..000000000 --- a/builder/cmd/evm/testdata/12/alloc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "84000000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - "0x00" : "0x00" - } - } -} - diff --git a/builder/cmd/evm/testdata/12/env.json b/builder/cmd/evm/testdata/12/env.json deleted file mode 100644 index 8ae546536..000000000 --- a/builder/cmd/evm/testdata/12/env.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentNumber" : "0x01", - "currentTimestamp" : "0x03e8", - "previousHash" : "0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2", - "currentGasLimit" : "0x0f4240", - "currentBaseFee" : "0x20" -} - diff --git a/builder/cmd/evm/testdata/12/readme.md b/builder/cmd/evm/testdata/12/readme.md deleted file mode 100644 index e3195be48..000000000 --- a/builder/cmd/evm/testdata/12/readme.md +++ /dev/null @@ -1,43 +0,0 @@ -## Test 1559 balance + gasCap - -This test contains an EIP-1559 consensus issue which happened on Ropsten, where -`geth` did not properly account for the value transfer while doing the check on `max_fee_per_gas * gas_limit`. - -Before the issue was fixed, this invocation allowed the transaction to pass into a block: -``` -dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout -``` - -With the fix applied, the result is: -``` -dir=./testdata/12 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout --output.result=stdout -INFO [03-09|10:43:12.649] rejected tx index=0 hash=ccc996..d83435 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" -INFO [03-09|10:43:12.650] Trie dumping started root=e05f81..6597a5 -INFO [03-09|10:43:12.650] Trie dumping complete accounts=1 elapsed="46.393µs" -{ - "alloc": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x501bd00" - } - }, - "result": { - "stateRoot": "0xe05f81f8244a76503ceec6f88abfcd03047a612a1001217f37d30984536597a5", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "rejected": [ - { - "index": 0, - "error": "insufficient funds for gas * price + value: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B have 84000000 want 84000032" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x0", - "currentBaseFee": "0x20" - } -} -``` - -The transaction is rejected. \ No newline at end of file diff --git a/builder/cmd/evm/testdata/12/txs.json b/builder/cmd/evm/testdata/12/txs.json deleted file mode 100644 index cd683f271..000000000 --- a/builder/cmd/evm/testdata/12/txs.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5208", - "nonce" : "0x0", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x20", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x20", - "accessList" : [ - ] - } -] - diff --git a/builder/cmd/evm/testdata/13/alloc.json b/builder/cmd/evm/testdata/13/alloc.json deleted file mode 100644 index 6e98e7513..000000000 --- a/builder/cmd/evm/testdata/13/alloc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "0x1111111111111111111111111111111111111111" : { - "balance" : "0x010000000000", - "code" : "0xfe", - "nonce" : "0x01", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x010000000000", - "code" : "0x", - "nonce" : "0x01", - "storage" : { - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363" : { - "balance" : "0x01000000000000", - "code" : "0x", - "nonce" : "0x01", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/13/env.json b/builder/cmd/evm/testdata/13/env.json deleted file mode 100644 index 3a82d46a7..000000000 --- a/builder/cmd/evm/testdata/13/env.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentNumber" : "0x01", - "currentTimestamp" : "0x079e", - "previousHash" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f", - "currentGasLimit" : "0x40000000", - "currentBaseFee" : "0x036b", - "blockHashes" : { - "0" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/13/exp.json b/builder/cmd/evm/testdata/13/exp.json deleted file mode 100644 index 2b049dfb2..000000000 --- a/builder/cmd/evm/testdata/13/exp.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "body": "0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" -} diff --git a/builder/cmd/evm/testdata/13/exp2.json b/builder/cmd/evm/testdata/13/exp2.json deleted file mode 100644 index babce3592..000000000 --- a/builder/cmd/evm/testdata/13/exp2.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "result": { - "stateRoot": "0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61", - "txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d", - "receiptsRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x84d0", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x84d0", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x0", - "cumulativeGasUsed": "0x109a0", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x84d0", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x109a0", - "currentBaseFee": "0x36b" - } -} diff --git a/builder/cmd/evm/testdata/13/readme.md b/builder/cmd/evm/testdata/13/readme.md deleted file mode 100644 index 889975d47..000000000 --- a/builder/cmd/evm/testdata/13/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -## Input transactions in RLP form - -This testdata folder is used to exemplify how transaction input can be provided in rlp form. -Please see the README in `evm` folder for how this is performed. \ No newline at end of file diff --git a/builder/cmd/evm/testdata/13/signed_txs.rlp b/builder/cmd/evm/testdata/13/signed_txs.rlp deleted file mode 100644 index 9d1157ea4..000000000 --- a/builder/cmd/evm/testdata/13/signed_txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/13/txs.json b/builder/cmd/evm/testdata/13/txs.json deleted file mode 100644 index c45ef1e13..000000000 --- a/builder/cmd/evm/testdata/13/txs.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x84d0", - "nonce" : "0x1", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [] - }, - { - "input" : "0x", - "gas" : "0x84d0", - "nonce" : "0x2", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298", - "chainId" : "0x1", - "type" : "0x2", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [] - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/14/alloc.json b/builder/cmd/evm/testdata/14/alloc.json deleted file mode 100644 index cef1a25ff..000000000 --- a/builder/cmd/evm/testdata/14/alloc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192":{ - "balance": "0xfeedbead", - "nonce" : "0x00" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/14/env.json b/builder/cmd/evm/testdata/14/env.json deleted file mode 100644 index 0bf1c5cf4..000000000 --- a/builder/cmd/evm/testdata/14/env.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "12800000", - "currentTimestamp": "100015", - "parentTimestamp" : "99999", - "parentDifficulty" : "0x2000000000000" -} diff --git a/builder/cmd/evm/testdata/14/env.uncles.json b/builder/cmd/evm/testdata/14/env.uncles.json deleted file mode 100644 index 83811b95e..000000000 --- a/builder/cmd/evm/testdata/14/env.uncles.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "12800000", - "currentTimestamp": "100035", - "parentTimestamp" : "99999", - "parentDifficulty" : "0x2000000000000", - "parentUncleHash" : "0x000000000000000000000000000000000000000000000000000000000000beef" -} diff --git a/builder/cmd/evm/testdata/14/exp.json b/builder/cmd/evm/testdata/14/exp.json deleted file mode 100644 index 26d49173c..000000000 --- a/builder/cmd/evm/testdata/14/exp.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "currentDifficulty": "0x2000020000000", - "receipts": [], - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/14/exp2.json b/builder/cmd/evm/testdata/14/exp2.json deleted file mode 100644 index cd75b47d5..000000000 --- a/builder/cmd/evm/testdata/14/exp2.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x1ff8020000000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/14/exp_berlin.json b/builder/cmd/evm/testdata/14/exp_berlin.json deleted file mode 100644 index 5c00ef130..000000000 --- a/builder/cmd/evm/testdata/14/exp_berlin.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x1ff9000000000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/14/readme.md b/builder/cmd/evm/testdata/14/readme.md deleted file mode 100644 index 40dd75486..000000000 --- a/builder/cmd/evm/testdata/14/readme.md +++ /dev/null @@ -1,45 +0,0 @@ -## Difficulty calculation - -This test shows how the `evm t8n` can be used to calculate the (ethash) difficulty, if none is provided by the caller. - -Calculating it (with an empty set of txs) using `London` rules (and no provided unclehash for the parent block): -``` -[user@work evm]$ ./evm t8n --input.alloc=./testdata/14/alloc.json --input.txs=./testdata/14/txs.json --input.env=./testdata/14/env.json --output.result=stdout --state.fork=London -INFO [03-09|10:43:57.070] Trie dumping started root=6f0588..7f4bdc -INFO [03-09|10:43:57.070] Trie dumping complete accounts=2 elapsed="214.663µs" -INFO [03-09|10:43:57.071] Wrote file file=alloc.json -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x2000020000000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} -``` -Same thing, but this time providing a non-empty (and non-`emptyKeccak`) unclehash, which leads to a slightly different result: -``` -[user@work evm]$ ./evm t8n --input.alloc=./testdata/14/alloc.json --input.txs=./testdata/14/txs.json --input.env=./testdata/14/env.uncles.json --output.result=stdout --state.fork=London -INFO [03-09|10:44:20.511] Trie dumping started root=6f0588..7f4bdc -INFO [03-09|10:44:20.511] Trie dumping complete accounts=2 elapsed="184.319µs" -INFO [03-09|10:44:20.512] Wrote file file=alloc.json -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x1ff8020000000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} -``` - diff --git a/builder/cmd/evm/testdata/14/txs.json b/builder/cmd/evm/testdata/14/txs.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/14/txs.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/15/blockheader.rlp b/builder/cmd/evm/testdata/15/blockheader.rlp deleted file mode 100644 index 1124e8e2d..000000000 --- a/builder/cmd/evm/testdata/15/blockheader.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf901f0a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b0101020383010203a00000000000000000000000000000000000000000000000000000000000000000880000000000000000" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/15/exp.json b/builder/cmd/evm/testdata/15/exp.json deleted file mode 100644 index 1893fdfc0..000000000 --- a/builder/cmd/evm/testdata/15/exp.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "error": "transaction type not supported", - "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476" - }, - { - "error": "transaction type not supported", - "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/15/exp2.json b/builder/cmd/evm/testdata/15/exp2.json deleted file mode 100644 index dd5e8a358..000000000 --- a/builder/cmd/evm/testdata/15/exp2.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "address": "0xd02d72e067e77158444ef2020ff2d325f929b363", - "hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476", - "intrinsicGas": "0x5208" - }, - { - "address": "0xd02d72e067e77158444ef2020ff2d325f929b363", - "hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a", - "intrinsicGas": "0x5208" - } -] diff --git a/builder/cmd/evm/testdata/15/exp3.json b/builder/cmd/evm/testdata/15/exp3.json deleted file mode 100644 index d7606a207..000000000 --- a/builder/cmd/evm/testdata/15/exp3.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - }, - { - "error": "typed transaction too short" - }, - { - "error": "typed transaction too short" - }, - { - "error": "typed transaction too short" - }, - { - "error": "typed transaction too short" - }, - { - "error": "typed transaction too short" - }, - { - "error": "rlp: expected input list for types.AccessListTx" - }, - { - "error": "transaction type not supported" - }, - { - "error": "transaction type not supported" - } -] diff --git a/builder/cmd/evm/testdata/15/signed_txs.rlp b/builder/cmd/evm/testdata/15/signed_txs.rlp deleted file mode 100644 index 9d1157ea4..000000000 --- a/builder/cmd/evm/testdata/15/signed_txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/15/signed_txs.rlp.json b/builder/cmd/evm/testdata/15/signed_txs.rlp.json deleted file mode 100644 index 187f40f24..000000000 --- a/builder/cmd/evm/testdata/15/signed_txs.rlp.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "txsRlp" : "0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" -} - diff --git a/builder/cmd/evm/testdata/16/exp.json b/builder/cmd/evm/testdata/16/exp.json deleted file mode 100644 index 137ade651..000000000 --- a/builder/cmd/evm/testdata/16/exp.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6", - "intrinsicGas": "0x5208" - }, - { - "error": "intrinsic gas too low: have 82, want 21000", - "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b", - "intrinsicGas": "0x5208" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/16/signed_txs.rlp b/builder/cmd/evm/testdata/16/signed_txs.rlp deleted file mode 100644 index 952ced213..000000000 --- a/builder/cmd/evm/testdata/16/signed_txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf8cab86401f8610180018252089411111111111111111111111111111111111111112080c001a0937f65ef1deece46c473b99962678fb7c38425cf303d1e8fa9717eb4b9d012b5a01940c5a5647c4940217ffde1051a5fd92ec8551e275c1787f81f50a2ad84de43b86201f85f018001529411111111111111111111111111111111111111112080c001a0241c3aec732205542a87fef8c76346741e85480bce5a42d05a9a73dac892f84ca04f52e2dfce57f3a02ed10e085e1a154edf38a726da34127c85fc53b4921759c8" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/16/unsigned_txs.json b/builder/cmd/evm/testdata/16/unsigned_txs.json deleted file mode 100644 index f61958940..000000000 --- a/builder/cmd/evm/testdata/16/unsigned_txs.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5208", - "nonce" : "0x0", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x20", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "chainId" : "0x1", - "type" : "0x1", - "gasPrice": "0x1", - "accessList" : [ - ] - }, - { - "input" : "0x", - "gas" : "0x52", - "nonce" : "0x0", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x20", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "chainId" : "0x1", - "type" : "0x1", - "gasPrice": "0x1", - "accessList" : [ - ] - } -] diff --git a/builder/cmd/evm/testdata/17/exp.json b/builder/cmd/evm/testdata/17/exp.json deleted file mode 100644 index 485906041..000000000 --- a/builder/cmd/evm/testdata/17/exp.json +++ /dev/null @@ -1,22 +0,0 @@ - [ - { - "error": "value exceeds 256 bits", - "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "hash": "0xfbd91685dcbf8172f0e8c53e2ddbb4d26707840da6b51a74371f62a33868fd82", - "intrinsicGas": "0x5208" - }, - { - "error": "gasPrice exceeds 256 bits", - "address": "0x1b57ccef1fe5fb73f1e64530fb4ebd9cf1655964", - "hash": "0x45dc05035cada83748e4c1fe617220106b331eca054f44c2304d5654a9fb29d5", - "intrinsicGas": "0x5208" - }, - { - "error": "invalid transaction v, r, s values", - "hash": "0xf06691c2a803ab7f3c81d06a0c0a896f80f311105c599fc59a9fdbc669356d35" - }, - { - "error": "invalid transaction v, r, s values", - "hash": "0x84703b697ad5b0db25e4f1f98fb6b1adce85b9edb2232eeba9cedd8c6601694b" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/17/rlpdata.txt b/builder/cmd/evm/testdata/17/rlpdata.txt deleted file mode 100644 index 874461fd7..000000000 --- a/builder/cmd/evm/testdata/17/rlpdata.txt +++ /dev/null @@ -1,46 +0,0 @@ -[ - [ - "", - "d", - 5208, - d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0, - 010000000000000000000000000000000000000000000000000000000000000001, - "", - 1b, - c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d, - 6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28, - ], - [ - "", - 010000000000000000000000000000000000000000000000000000000000000001, - 5208, - d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0, - 11, - "", - 1b, - c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d, - 6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28, - ], - [ - "", - 11, - 5208, - d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0, - 11, - "", - 1b, - c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549daa, - 6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28, - ], - [ - "", - 11, - 5208, - d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0, - 11, - "", - 1b, - c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d, - 6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28bb, - ], -] diff --git a/builder/cmd/evm/testdata/17/signed_txs.rlp b/builder/cmd/evm/testdata/17/signed_txs.rlp deleted file mode 100644 index 0e351fb03..000000000 --- a/builder/cmd/evm/testdata/17/signed_txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf901c8f880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f88080a101000000000000000000000000000000000000000000000000000000000000000182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f860801182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba1c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549daaa06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f860801182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da16180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28bb" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/18/README.md b/builder/cmd/evm/testdata/18/README.md deleted file mode 100644 index 360a9bba0..000000000 --- a/builder/cmd/evm/testdata/18/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Invalid rlp - -This folder contains a sample of invalid RLP, and it's expected -that the t9n handles this properly: - -``` -$ go run . t9n --input.txs=./testdata/18/invalid.rlp --state.fork=London -ERROR(11): rlp: value size exceeds available input length -``` \ No newline at end of file diff --git a/builder/cmd/evm/testdata/18/invalid.rlp b/builder/cmd/evm/testdata/18/invalid.rlp deleted file mode 100644 index 7ff2824ca..000000000 --- a/builder/cmd/evm/testdata/18/invalid.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf852328001825208870b9331677e6ebf0a801ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa03887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/19/alloc.json b/builder/cmd/evm/testdata/19/alloc.json deleted file mode 100644 index cef1a25ff..000000000 --- a/builder/cmd/evm/testdata/19/alloc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192":{ - "balance": "0xfeedbead", - "nonce" : "0x00" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/19/env.json b/builder/cmd/evm/testdata/19/env.json deleted file mode 100644 index 0c64392af..000000000 --- a/builder/cmd/evm/testdata/19/env.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "13000000", - "currentTimestamp": "100015", - "parentTimestamp" : "99999", - "parentDifficulty" : "0x2000000000000" -} diff --git a/builder/cmd/evm/testdata/19/exp_arrowglacier.json b/builder/cmd/evm/testdata/19/exp_arrowglacier.json deleted file mode 100644 index dd49f7d02..000000000 --- a/builder/cmd/evm/testdata/19/exp_arrowglacier.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "currentDifficulty": "0x2000000200000", - "receipts": [], - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/19/exp_grayglacier.json b/builder/cmd/evm/testdata/19/exp_grayglacier.json deleted file mode 100644 index 86fd8e6c1..000000000 --- a/builder/cmd/evm/testdata/19/exp_grayglacier.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x2000000004000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/19/exp_london.json b/builder/cmd/evm/testdata/19/exp_london.json deleted file mode 100644 index 9e9a17da9..000000000 --- a/builder/cmd/evm/testdata/19/exp_london.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "currentDifficulty": "0x2000080000000", - "receipts": [], - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/19/readme.md b/builder/cmd/evm/testdata/19/readme.md deleted file mode 100644 index 9c7c4b365..000000000 --- a/builder/cmd/evm/testdata/19/readme.md +++ /dev/null @@ -1,25 +0,0 @@ -## Difficulty calculation - -This test shows how the `evm t8n` can be used to calculate the (ethash) difficulty, if none is provided by the caller, -this time on `GrayGlacier` (Eip 5133). - -Calculating it (with an empty set of txs) using `GrayGlacier` rules (and no provided unclehash for the parent block): -``` -[user@work evm]$ ./evm t8n --input.alloc=./testdata/19/alloc.json --input.txs=./testdata/19/txs.json --input.env=./testdata/19/env.json --output.result=stdout --state.fork=GrayGlacier -INFO [03-09|10:45:26.777] Trie dumping started root=6f0588..7f4bdc -INFO [03-09|10:45:26.777] Trie dumping complete accounts=2 elapsed="176.471µs" -INFO [03-09|10:45:26.777] Wrote file file=alloc.json -{ - "result": { - "stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x2000000004000", - "gasUsed": "0x0", - "currentBaseFee": "0x500" - } -} -``` \ No newline at end of file diff --git a/builder/cmd/evm/testdata/19/txs.json b/builder/cmd/evm/testdata/19/txs.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/19/txs.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/2/alloc.json b/builder/cmd/evm/testdata/2/alloc.json deleted file mode 100644 index a9720afc9..000000000 --- a/builder/cmd/evm/testdata/2/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x6001600053600160006001f0ff00", - "nonce" : "0x00", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/2/env.json b/builder/cmd/evm/testdata/2/env.json deleted file mode 100644 index ebadd3f06..000000000 --- a/builder/cmd/evm/testdata/2/env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "0x3b9aca00", - "currentNumber" : "0x01", - "currentTimestamp" : "0x03e8" -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/2/readme.md b/builder/cmd/evm/testdata/2/readme.md deleted file mode 100644 index 4bcf0f0fa..000000000 --- a/builder/cmd/evm/testdata/2/readme.md +++ /dev/null @@ -1 +0,0 @@ -These files exemplify a selfdestruct to the `0`-address. \ No newline at end of file diff --git a/builder/cmd/evm/testdata/2/txs.json b/builder/cmd/evm/testdata/2/txs.json deleted file mode 100644 index 304445858..000000000 --- a/builder/cmd/evm/testdata/2/txs.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5f5e100", - "gasPrice" : "0x1", - "nonce" : "0x0", - "to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "0x186a0", - "v" : "0x1b", - "r" : "0x88544c93a564b4c28d2ffac2074a0c55fdd4658fe0d215596ed2e32e3ef7f56b", - "s" : "0x7fb4075d54190f825d7c47bb820284757b34fd6293904a93cddb1d3aa961ac28", - "hash" : "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/20/exp.json b/builder/cmd/evm/testdata/20/exp.json deleted file mode 100644 index 7bec6cefd..000000000 --- a/builder/cmd/evm/testdata/20/exp.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf902d9f90211a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e997a23b159e2e2a5ce72333262972374b15425ca0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e99476574682f76312e302e312f6c696e75782f676f312e342e32a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf8897435673d874f7c8f8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600c0", - "hash": "0xaba9a3b6a4e96e9ecffcadaa5a2ae0589359455617535cd86589fe1dd26fe899" -} diff --git a/builder/cmd/evm/testdata/20/header.json b/builder/cmd/evm/testdata/20/header.json deleted file mode 100644 index fb9b7fc56..000000000 --- a/builder/cmd/evm/testdata/20/header.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e", - "miner": "0xe997a23b159e2e2a5ce72333262972374b15425c", - "stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x1000", - "number": "0xc3be", - "gasLimit": "0x50785", - "gasUsed": "0x0", - "timestamp": "0x55c5277e", - "extraData": "0x476574682f76312e302e312f6c696e75782f676f312e342e32", - "mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf", - "nonce": "0x97435673d874f7c8" -} diff --git a/builder/cmd/evm/testdata/20/ommers.json b/builder/cmd/evm/testdata/20/ommers.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/20/ommers.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/20/readme.md b/builder/cmd/evm/testdata/20/readme.md deleted file mode 100644 index 2c448a96e..000000000 --- a/builder/cmd/evm/testdata/20/readme.md +++ /dev/null @@ -1,11 +0,0 @@ -# Block building - -This test shows how `b11r` can be used to assemble an unsealed block. - -```console -$ go run . b11r --input.header=testdata/20/header.json --input.txs=testdata/20/txs.rlp --input.ommers=testdata/20/ommers.json --output.block=stdout -{ - "rlp": "0xf90216f90211a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e997a23b159e2e2a5ce72333262972374b15425ca0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e99476574682f76312e302e312f6c696e75782f676f312e342e32a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf8897435673d874f7c8c0c0", - "hash": "0xaba9a3b6a4e96e9ecffcadaa5a2ae0589359455617535cd86589fe1dd26fe899" -} -``` diff --git a/builder/cmd/evm/testdata/20/txs.rlp b/builder/cmd/evm/testdata/20/txs.rlp deleted file mode 100644 index 3599ff065..000000000 --- a/builder/cmd/evm/testdata/20/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/21/clique.json b/builder/cmd/evm/testdata/21/clique.json deleted file mode 100644 index 84fa259a0..000000000 --- a/builder/cmd/evm/testdata/21/clique.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "voted": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "authorize": false, - "vanity": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -} diff --git a/builder/cmd/evm/testdata/21/exp-clique.json b/builder/cmd/evm/testdata/21/exp-clique.json deleted file mode 100644 index c990ba8aa..000000000 --- a/builder/cmd/evm/testdata/21/exp-clique.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0", - "hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7" -} diff --git a/builder/cmd/evm/testdata/21/exp.json b/builder/cmd/evm/testdata/21/exp.json deleted file mode 100644 index b3e5e7a83..000000000 --- a/builder/cmd/evm/testdata/21/exp.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0", - "hash": "0x801411e9f6609a659825690d13e4f75a3cfe9143952fa2d9573f3b0a5eb9ebbb" -} diff --git a/builder/cmd/evm/testdata/21/header.json b/builder/cmd/evm/testdata/21/header.json deleted file mode 100644 index 62abe3cc2..000000000 --- a/builder/cmd/evm/testdata/21/header.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e", - "stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x1000", - "number": "0xc3be", - "gasLimit": "0x50785", - "gasUsed": "0x0", - "timestamp": "0x55c5277e", - "mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf" -} diff --git a/builder/cmd/evm/testdata/21/ommers.json b/builder/cmd/evm/testdata/21/ommers.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/21/ommers.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/21/readme.md b/builder/cmd/evm/testdata/21/readme.md deleted file mode 100644 index b70f106ff..000000000 --- a/builder/cmd/evm/testdata/21/readme.md +++ /dev/null @@ -1,23 +0,0 @@ -# Sealed block building - -This test shows how `b11r` can be used to assemble a sealed block. - -## Ethash - -```console -$ go run . b11r --input.header=testdata/21/header.json --input.txs=testdata/21/txs.rlp --input.ommers=testdata/21/ommers.json --seal.ethash --seal.ethash.mode=test --output.block=stdout -{ - "rlp": "0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0", - "hash": "0x801411e9f6609a659825690d13e4f75a3cfe9143952fa2d9573f3b0a5eb9ebbb" -} -``` - -## Clique - -```console -$ go run . b11r --input.header=testdata/21/header.json --input.txs=testdata/21/txs.rlp --input.ommers=testdata/21/ommers.json --seal.clique=testdata/21/clique.json --output.block=stdout -{ - "rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0", - "hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7" -} -``` diff --git a/builder/cmd/evm/testdata/21/txs.rlp b/builder/cmd/evm/testdata/21/txs.rlp deleted file mode 100644 index e815397b3..000000000 --- a/builder/cmd/evm/testdata/21/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"c0" diff --git a/builder/cmd/evm/testdata/22/exp-clique.json b/builder/cmd/evm/testdata/22/exp-clique.json deleted file mode 100644 index c990ba8aa..000000000 --- a/builder/cmd/evm/testdata/22/exp-clique.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0", - "hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7" -} diff --git a/builder/cmd/evm/testdata/22/exp.json b/builder/cmd/evm/testdata/22/exp.json deleted file mode 100644 index 14fd81997..000000000 --- a/builder/cmd/evm/testdata/22/exp.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf905f5f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea06eb9f0c3cd68c9e97134e6725d12b1f1d8f0644458da6870a37ff84c908fb1e7940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0f903f6f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000", - "hash": "0xd9a81c8fcd57a7f2a0d2c375eff6ad192c30c3729a271303f0a9a7e1b357e755" -} diff --git a/builder/cmd/evm/testdata/22/header.json b/builder/cmd/evm/testdata/22/header.json deleted file mode 100644 index 62abe3cc2..000000000 --- a/builder/cmd/evm/testdata/22/header.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e", - "stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x1000", - "number": "0xc3be", - "gasLimit": "0x50785", - "gasUsed": "0x0", - "timestamp": "0x55c5277e", - "mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf" -} diff --git a/builder/cmd/evm/testdata/22/ommers.json b/builder/cmd/evm/testdata/22/ommers.json deleted file mode 100644 index 997015b3c..000000000 --- a/builder/cmd/evm/testdata/22/ommers.json +++ /dev/null @@ -1 +0,0 @@ -["0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0","0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0"] diff --git a/builder/cmd/evm/testdata/22/readme.md b/builder/cmd/evm/testdata/22/readme.md deleted file mode 100644 index 2cac8a243..000000000 --- a/builder/cmd/evm/testdata/22/readme.md +++ /dev/null @@ -1,11 +0,0 @@ -# Building blocks with ommers - -This test shows how `b11r` can chain together ommer assembles into a canonical block. - -```console -$ echo "{ \"ommers\": [`go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --output.block=stdout | jq '.[\"rlp\"]'`,`go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --output.block=stdout | jq '.[\"rlp\"]'`]}" | go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --input.ommers=stdin --output.block=stdout -{ - "rlp": "0xf905f5f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea06eb9f0c3cd68c9e97134e6725d12b1f1d8f0644458da6870a37ff84c908fb1e7940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0f903f6f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000", - "hash": "0xd9a81c8fcd57a7f2a0d2c375eff6ad192c30c3729a271303f0a9a7e1b357e755" -} -``` diff --git a/builder/cmd/evm/testdata/22/txs.rlp b/builder/cmd/evm/testdata/22/txs.rlp deleted file mode 100644 index e815397b3..000000000 --- a/builder/cmd/evm/testdata/22/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"c0" diff --git a/builder/cmd/evm/testdata/23/alloc.json b/builder/cmd/evm/testdata/23/alloc.json deleted file mode 100644 index 239b3553f..000000000 --- a/builder/cmd/evm/testdata/23/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x6001", - "nonce" : "0x00", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } -} diff --git a/builder/cmd/evm/testdata/23/env.json b/builder/cmd/evm/testdata/23/env.json deleted file mode 100644 index 1b4632151..000000000 --- a/builder/cmd/evm/testdata/23/env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "0x3b9aca00", - "currentNumber" : "0x05", - "currentTimestamp" : "0x03e8" -} diff --git a/builder/cmd/evm/testdata/23/exp.json b/builder/cmd/evm/testdata/23/exp.json deleted file mode 100644 index 22dde0a27..000000000 --- a/builder/cmd/evm/testdata/23/exp.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "result": { - "stateRoot": "0x65334305e4accfa18352deb24f007b837b5036425b0712cf0e65a43bfa95154d", - "txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b", - "receiptsRoot": "0xf951f9396af203499cc7d379715a9110323de73967c5700e2f424725446a3c76", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x520b", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x520b", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x520b" - } -} diff --git a/builder/cmd/evm/testdata/23/readme.md b/builder/cmd/evm/testdata/23/readme.md deleted file mode 100644 index f31b64de2..000000000 --- a/builder/cmd/evm/testdata/23/readme.md +++ /dev/null @@ -1 +0,0 @@ -These files exemplify how to sign a transaction using the pre-EIP155 scheme. diff --git a/builder/cmd/evm/testdata/23/txs.json b/builder/cmd/evm/testdata/23/txs.json deleted file mode 100644 index 22f3840f8..000000000 --- a/builder/cmd/evm/testdata/23/txs.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5f5e100", - "gasPrice" : "0x1", - "nonce" : "0x0", - "to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "0x186a0", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "protected": false - } -] diff --git a/builder/cmd/evm/testdata/24/alloc.json b/builder/cmd/evm/testdata/24/alloc.json deleted file mode 100644 index 73a9a03c0..000000000 --- a/builder/cmd/evm/testdata/24/alloc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192":{ - "balance": "0xfeedbead", - "nonce" : "0x00", - "code" : "0x44600055", - "_comment": "The code is 'sstore(0, random)'" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/24/env-missingrandom.json b/builder/cmd/evm/testdata/24/env-missingrandom.json deleted file mode 100644 index db49fd3fc..000000000 --- a/builder/cmd/evm/testdata/24/env-missingrandom.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": null, - "currentRandom": null, - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "1", - "currentTimestamp": "1000" -} diff --git a/builder/cmd/evm/testdata/24/env.json b/builder/cmd/evm/testdata/24/env.json deleted file mode 100644 index 262cc2528..000000000 --- a/builder/cmd/evm/testdata/24/env.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": null, - "currentRandom": "0xdeadc0de", - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "1", - "currentTimestamp": "1000" -} diff --git a/builder/cmd/evm/testdata/24/exp.json b/builder/cmd/evm/testdata/24/exp.json deleted file mode 100644 index ac571d149..000000000 --- a/builder/cmd/evm/testdata/24/exp.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "alloc": { - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "code": "0x44600055", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000deadc0de" - }, - "balance": "0xfeedbeaf" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878b803f972", - "nonce": "0xae" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x1030600" - } - }, - "result": { - "stateRoot": "0x9e4224c6bba343d5b0fdbe9200cc66a7ef2068240d901ae516e634c45a043c15", - "txRoot": "0x16cd3a7daa6686ceebadf53b7af2bc6919eccb730907f0e74a95a4423c209593", - "receiptsRoot": "0x22b85cda738345a9880260b2a71e144aab1ca9485f5db4fd251008350fc124c8", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0xa861", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0xa861", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x10306", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x16b1d912f1d664f3f60f4e1b5f296f3c82a64a1a253117b4851d18bc03c4f1da", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5aa5", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - } - ], - "currentDifficulty": null, - "gasUsed": "0x10306", - "currentBaseFee": "0x500" - } -} diff --git a/builder/cmd/evm/testdata/24/txs.json b/builder/cmd/evm/testdata/24/txs.json deleted file mode 100644 index 99c2068f1..000000000 --- a/builder/cmd/evm/testdata/24/txs.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "gas": "0x186a0", - "gasPrice": "0x600", - "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "input": "0x", - "nonce": "0xac", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "value": "0x1", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - { - "gas": "0x186a0", - "gasPrice": "0x600", - "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "input": "0x", - "nonce": "0xad", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "value": "0x1", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] diff --git a/builder/cmd/evm/testdata/25/alloc.json b/builder/cmd/evm/testdata/25/alloc.json deleted file mode 100644 index d66366718..000000000 --- a/builder/cmd/evm/testdata/25/alloc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - } -} diff --git a/builder/cmd/evm/testdata/25/env.json b/builder/cmd/evm/testdata/25/env.json deleted file mode 100644 index bb2c9e0d7..000000000 --- a/builder/cmd/evm/testdata/25/env.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": null, - "currentRandom": "0xdeadc0de", - "currentGasLimit": "0x750a163df65e8a", - "parentBaseFee": "0x500", - "parentGasUsed": "0x0", - "parentGasLimit": "0x750a163df65e8a", - "currentNumber": "1", - "currentTimestamp": "1000" -} diff --git a/builder/cmd/evm/testdata/25/exp.json b/builder/cmd/evm/testdata/25/exp.json deleted file mode 100644 index 1cb521794..000000000 --- a/builder/cmd/evm/testdata/25/exp.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "alloc": { - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "balance": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878bc29ed73", - "nonce": "0xad" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x854d00" - } - }, - "result": { - "stateRoot": "0x5139609e39f4d158a7d1ad1800908eb0349cea9b500a8273a6cf0a7e4392639b", - "txRoot": "0x572690baf4898c2972446e56ecf0aa2a027c08a863927d2dce34472f0c5496fe", - "receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "currentDifficulty": null, - "gasUsed": "0x5208", - "currentBaseFee": "0x460" - } -} diff --git a/builder/cmd/evm/testdata/25/txs.json b/builder/cmd/evm/testdata/25/txs.json deleted file mode 100644 index acb4035fd..000000000 --- a/builder/cmd/evm/testdata/25/txs.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "gas": "0x186a0", - "gasPrice": "0x600", - "hash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673", - "input": "0x", - "nonce": "0xac", - "to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192", - "value": "0x1", - "v" : "0x0", - "r" : "0x0", - "s" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] diff --git a/builder/cmd/evm/testdata/26/alloc.json b/builder/cmd/evm/testdata/26/alloc.json deleted file mode 100644 index d67655a8a..000000000 --- a/builder/cmd/evm/testdata/26/alloc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x0", - "code": "0x", - "nonce": "0xac", - "storage": {} - } -} diff --git a/builder/cmd/evm/testdata/26/env.json b/builder/cmd/evm/testdata/26/env.json deleted file mode 100644 index 03d817b93..000000000 --- a/builder/cmd/evm/testdata/26/env.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": null, - "currentRandom": "0xdeadc0de", - "currentGasLimit": "0x750a163df65e8a", - "currentBaseFee": "0x500", - "currentNumber": "1", - "currentTimestamp": "1000", - "withdrawals": [ - { - "index": "0x42", - "validatorIndex": "0x42", - "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "amount": "0x2a" - } - ] -} diff --git a/builder/cmd/evm/testdata/26/exp.json b/builder/cmd/evm/testdata/26/exp.json deleted file mode 100644 index 4815e5cb6..000000000 --- a/builder/cmd/evm/testdata/26/exp.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "alloc": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x9c7652400", - "nonce": "0xac" - } - }, - "result": { - "stateRoot": "0x6e061c2f6513af27d267a0e3b07cb9a10f1ba3a0f65ab648d3a17c36e15021d2", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": null, - "gasUsed": "0x0", - "currentBaseFee": "0x500", - "withdrawalsRoot": "0x4921c0162c359755b2ae714a0978a1dad2eb8edce7ff9b38b9b6fc4cbc547eb5" - } -} diff --git a/builder/cmd/evm/testdata/26/txs.json b/builder/cmd/evm/testdata/26/txs.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/26/txs.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/27/exp.json b/builder/cmd/evm/testdata/27/exp.json deleted file mode 100644 index 5975a9c25..000000000 --- a/builder/cmd/evm/testdata/27/exp.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rlp": "0xf90239f9021aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88000000000000000080a04921c0162c359755b2ae714a0978a1dad2eb8edce7ff9b38b9b6fc4cbc547eb5c0c0d9d8424394a94f5374fce5edbc8e2a8697c15331677e6ebf0b2a", - "hash": "0xdc42abd3698499675819e0a85cc1266f16da90277509b867446a6b25fa2b9d87" -} diff --git a/builder/cmd/evm/testdata/27/header.json b/builder/cmd/evm/testdata/27/header.json deleted file mode 100644 index 4ed7eaca0..000000000 --- a/builder/cmd/evm/testdata/27/header.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e", - "stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x1000", - "number": "0xc3be", - "gasLimit": "0x50785", - "gasUsed": "0x0", - "timestamp": "0x55c5277e", - "mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf", - "withdrawalsRoot": "0x4921c0162c359755b2ae714a0978a1dad2eb8edce7ff9b38b9b6fc4cbc547eb5" -} diff --git a/builder/cmd/evm/testdata/27/ommers.json b/builder/cmd/evm/testdata/27/ommers.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/27/ommers.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/27/txs.rlp b/builder/cmd/evm/testdata/27/txs.rlp deleted file mode 100644 index e815397b3..000000000 --- a/builder/cmd/evm/testdata/27/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"c0" diff --git a/builder/cmd/evm/testdata/27/withdrawals.json b/builder/cmd/evm/testdata/27/withdrawals.json deleted file mode 100644 index 6634aff08..000000000 --- a/builder/cmd/evm/testdata/27/withdrawals.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "index": "0x42", - "validatorIndex": "0x43", - "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "amount": "0x2a" - } -] diff --git a/builder/cmd/evm/testdata/28/alloc.json b/builder/cmd/evm/testdata/28/alloc.json deleted file mode 100644 index 680a89f4e..000000000 --- a/builder/cmd/evm/testdata/28/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x016345785d8a0000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - }, - "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x016345785d8a0000", - "code" : "0x60004960015500", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/28/env.json b/builder/cmd/evm/testdata/28/env.json deleted file mode 100644 index 82f22ac62..000000000 --- a/builder/cmd/evm/testdata/28/env.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentNumber" : "0x01", - "currentTimestamp" : "0x079e", - "currentGasLimit" : "0x7fffffffffffffff", - "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6", - "currentBlobGasUsed" : "0x00", - "parentTimestamp" : "0x03b6", - "parentDifficulty" : "0x00", - "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "withdrawals" : [], - "parentBaseFee" : "0x0a", - "parentGasUsed" : "0x00", - "parentGasLimit" : "0x7fffffffffffffff", - "parentExcessBlobGas" : "0x00", - "parentBlobGasUsed" : "0x00", - "blockHashes" : { - "0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6" - }, - "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" -} diff --git a/builder/cmd/evm/testdata/28/exp.json b/builder/cmd/evm/testdata/28/exp.json deleted file mode 100644 index 75c715e97..000000000 --- a/builder/cmd/evm/testdata/28/exp.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "alloc": { - "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "balance": "0x150ca" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x16345785d80c3a9", - "nonce": "0x1" - }, - "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "code": "0x60004960015500", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x01a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - "balance": "0x16345785d8a0000" - } - }, - "result": { - "stateRoot": "0xa40cb3fab01848e922a48bd24191815df9f721ad4b60376edac75161517663e8", - "txRoot": "0x4409cc4b699384ba5f8248d92b784713610c5ff9c1de51e9239da0dac76de9ce", - "receiptsRoot": "0xbff643da765981266133094092d98c81d2ac8e9a83a7bbda46c3d736f1f874ac", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x3", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0xa865", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x7508d7139d002a4b3a26a4f12dec0d87cb46075c78bf77a38b569a133b509262", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0xa865", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "currentDifficulty": null, - "gasUsed": "0xa865", - "currentBaseFee": "0x9", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "currentExcessBlobGas": "0x0", - "blobGasUsed": "0x20000" - } -} diff --git a/builder/cmd/evm/testdata/28/txs.rlp b/builder/cmd/evm/testdata/28/txs.rlp deleted file mode 100644 index 8df20e3aa..000000000 --- a/builder/cmd/evm/testdata/28/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf88bb88903f8860180026483061a8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b8080c00ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d801a025e16bb498552165016751911c3608d79000ab89dc3100776e729e6ea13091c7a03acacff7fc0cff6eda8a927dec93ca17765e1ee6cbc06c5954ce102e097c01d2" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/29/alloc.json b/builder/cmd/evm/testdata/29/alloc.json deleted file mode 100644 index d2c879a45..000000000 --- a/builder/cmd/evm/testdata/29/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x016345785d8a0000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - }, - "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" : { - "balance" : "0x1", - "code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/29/env.json b/builder/cmd/evm/testdata/29/env.json deleted file mode 100644 index e752a909a..000000000 --- a/builder/cmd/evm/testdata/29/env.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentNumber" : "0x01", - "currentTimestamp" : "0x079e", - "currentGasLimit" : "0x7fffffffffffffff", - "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6", - "currentBlobGasUsed" : "0x00", - "parentTimestamp" : "0x03b6", - "parentDifficulty" : "0x00", - "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "withdrawals" : [ - ], - "parentBaseFee" : "0x0a", - "parentGasUsed" : "0x00", - "parentGasLimit" : "0x7fffffffffffffff", - "parentExcessBlobGas" : "0x00", - "parentBlobGasUsed" : "0x00", - "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/29/exp.json b/builder/cmd/evm/testdata/29/exp.json deleted file mode 100644 index c4c001ec1..000000000 --- a/builder/cmd/evm/testdata/29/exp.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "alloc": { - "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", - "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" - }, - "balance": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x16345785d871db8", - "nonce": "0x1" - } - }, - "result": { - "stateRoot": "0x19a4f821a7c0a6f4c934f9acb0fe9ce5417b68086e12513ecbc3e3f57e01573c", - "txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab", - "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "currentDifficulty": null, - "gasUsed": "0x5208", - "currentBaseFee": "0x9", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "currentExcessBlobGas": "0x0", - "blobGasUsed": "0x0" - } -} diff --git a/builder/cmd/evm/testdata/29/readme.md b/builder/cmd/evm/testdata/29/readme.md deleted file mode 100644 index ab02ce9cf..000000000 --- a/builder/cmd/evm/testdata/29/readme.md +++ /dev/null @@ -1,29 +0,0 @@ -## EIP 4788 - -This test contains testcases for EIP-4788. The 4788-contract is -located at address `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`, and this test executes a simple transaction. It also -implicitly invokes the system tx, which sets calls the contract and sets the -storage values - -``` -$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout -INFO [09-27|15:34:53.049] Trie dumping started root=19a4f8..01573c -INFO [09-27|15:34:53.049] Trie dumping complete accounts=2 elapsed="192.759µs" -INFO [09-27|15:34:53.050] Wrote file file=result.json -{ - "alloc": { - "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", - "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" - }, - "balance": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x16345785d871db8", - "nonce": "0x1" - } - } -} -``` diff --git a/builder/cmd/evm/testdata/29/txs.json b/builder/cmd/evm/testdata/29/txs.json deleted file mode 100644 index d6743cc4d..000000000 --- a/builder/cmd/evm/testdata/29/txs.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x10000000", - "nonce" : "0x0", - "to" : "0x1111111111111111111111111111111111111111", - "value" : "0x0", - "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "chainId" : "0x1", - "type" : "0x2", - "v": "0x0", - "r": "0x0", - "s": "0x0", - "maxFeePerGas" : "0xfa0", - "maxPriorityFeePerGas" : "0x0", - "accessList" : [ - ] - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/3/alloc.json b/builder/cmd/evm/testdata/3/alloc.json deleted file mode 100644 index dca318ee5..000000000 --- a/builder/cmd/evm/testdata/3/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x600140", - "nonce" : "0x00", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/3/env.json b/builder/cmd/evm/testdata/3/env.json deleted file mode 100644 index e283eff46..000000000 --- a/builder/cmd/evm/testdata/3/env.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "0x3b9aca00", - "currentNumber" : "0x05", - "currentTimestamp" : "0x03e8", - "blockHashes" : { "1" : "0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"} -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/3/exp.json b/builder/cmd/evm/testdata/3/exp.json deleted file mode 100644 index 7230dca2c..000000000 --- a/builder/cmd/evm/testdata/3/exp.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "alloc": { - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": { - "code": "0x600140", - "balance": "0xde0b6b3a76586a0" - }, - "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "balance": "0x521f" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xde0b6b3a7622741", - "nonce": "0x1" - } - }, - "result": { - "stateRoot": "0xb7341da3f9f762a6884eaa186c32942734c146b609efee11c4b0214c44857ea1", - "txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b", - "receiptsRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x521f", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x521f", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - } - ], - "currentDifficulty": "0x20000", - "gasUsed": "0x521f" - } -} diff --git a/builder/cmd/evm/testdata/3/readme.md b/builder/cmd/evm/testdata/3/readme.md deleted file mode 100644 index 246c58ef3..000000000 --- a/builder/cmd/evm/testdata/3/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -These files exemplify a transition where a transaction (executed on block 5) requests -the blockhash for block `1`. diff --git a/builder/cmd/evm/testdata/3/txs.json b/builder/cmd/evm/testdata/3/txs.json deleted file mode 100644 index 304445858..000000000 --- a/builder/cmd/evm/testdata/3/txs.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5f5e100", - "gasPrice" : "0x1", - "nonce" : "0x0", - "to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "0x186a0", - "v" : "0x1b", - "r" : "0x88544c93a564b4c28d2ffac2074a0c55fdd4658fe0d215596ed2e32e3ef7f56b", - "s" : "0x7fb4075d54190f825d7c47bb820284757b34fd6293904a93cddb1d3aa961ac28", - "hash" : "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/README.txt b/builder/cmd/evm/testdata/30/README.txt deleted file mode 100644 index 84c92de85..000000000 --- a/builder/cmd/evm/testdata/30/README.txt +++ /dev/null @@ -1,77 +0,0 @@ -This example comes from https://github.com/ethereum/go-ethereum/issues/27730. -The input transactions contain three transactions, number `0` and `2` are taken from -`testdata/13`, whereas number `1` is taken from #27730. - -The problematic second transaction cannot be RLP-decoded, and the expectation is -that that particular transaction should be rejected, but number `0` and `1` should -still be accepted. - -``` -$ go run . t8n --input.alloc=./testdata/30/alloc.json --input.txs=./testdata/30/txs_more.rlp --input.env=./testdata/30/env.json --output.result=stdout --output.alloc=stdout --state.fork=Cancun -WARN [10-22|15:38:03.283] rejected tx index=1 error="rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To" -INFO [10-22|15:38:03.284] Trie dumping started root=348312..915c93 -INFO [10-22|15:38:03.284] Trie dumping complete accounts=3 elapsed="160.831µs" -{ - "alloc": { - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": { - "code": "0x60004960005500", - "balance": "0xde0b6b3a7640000" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xde0b6b3a7640000" - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "balance": "0xfffffffb8390", - "nonce": "0x3" - } - }, - "result": { - "stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93", - "txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d", - "receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0xa410", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - } - ], - "rejected": [ - { - "index": 1, - "error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To" - } - ], - "currentDifficulty": null, - "gasUsed": "0xa410", - "currentBaseFee": "0x7", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - } -} - -``` \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/alloc.json b/builder/cmd/evm/testdata/30/alloc.json deleted file mode 100644 index 6bc93d255..000000000 --- a/builder/cmd/evm/testdata/30/alloc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x60004960005500", - "nonce" : "0x00", - "storage" : { - } - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363" : { - "balance": "0x01000000000000", - "code": "0x", - "nonce": "0x01", - "storage": { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/env.json b/builder/cmd/evm/testdata/30/env.json deleted file mode 100644 index 4acd9794b..000000000 --- a/builder/cmd/evm/testdata/30/env.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentNumber" : "0x01", - "currentTimestamp" : "0x03e8", - "currentGasLimit" : "0x1000000000", - "previousHash" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da", - "currentDataGasUsed" : "0x2000", - "parentTimestamp" : "0x00", - "parentDifficulty" : "0x00", - "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "parentBeaconBlockRoot" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000", - "withdrawals" : [ - ], - "parentBaseFee" : "0x08", - "parentGasUsed" : "0x00", - "parentGasLimit" : "0x1000000000", - "parentExcessBlobGas" : "0x1000", - "parentBlobGasUsed" : "0x2000", - "blockHashes" : { - "0" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/exp.json b/builder/cmd/evm/testdata/30/exp.json deleted file mode 100644 index f0b19c6b3..000000000 --- a/builder/cmd/evm/testdata/30/exp.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "alloc": { - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87": { - "code": "0x60004960005500", - "balance": "0xde0b6b3a7640000" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xde0b6b3a7640000" - }, - "0xd02d72e067e77158444ef2020ff2d325f929b363": { - "balance": "0xfffffffb8390", - "nonce": "0x3" - } - }, - "result": { - "stateRoot": "0x3483124b6710486c9fb3e07975669c66924697c88cccdcc166af5e1218915c93", - "txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d", - "receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [ - { - "type": "0x2", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0x5208", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x0" - }, - { - "type": "0x2", - "root": "0x", - "status": "0x1", - "cumulativeGasUsed": "0xa410", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logs": null, - "transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a", - "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x5208", - "effectiveGasPrice": null, - "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "transactionIndex": "0x1" - } - ], - "rejected": [ - { - "index": 1, - "error": "rlp: input string too short for common.Address, decoding into (types.Transaction)(types.BlobTx).To" - } - ], - "currentDifficulty": null, - "gasUsed": "0xa410", - "currentBaseFee": "0x7", - "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "currentExcessBlobGas": "0x0", - "blobGasUsed": "0x0" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/txs.rlp b/builder/cmd/evm/testdata/30/txs.rlp deleted file mode 100644 index 620c1a13a..000000000 --- a/builder/cmd/evm/testdata/30/txs.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf8dbb8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/30/txs_more.rlp b/builder/cmd/evm/testdata/30/txs_more.rlp deleted file mode 100644 index 35af8d1f2..000000000 --- a/builder/cmd/evm/testdata/30/txs_more.rlp +++ /dev/null @@ -1 +0,0 @@ -"0xf901adb86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9" \ No newline at end of file diff --git a/builder/cmd/evm/testdata/4/alloc.json b/builder/cmd/evm/testdata/4/alloc.json deleted file mode 100644 index fadf2bdc4..000000000 --- a/builder/cmd/evm/testdata/4/alloc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x600340", - "nonce" : "0x00", - "storage" : { - } - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/4/env.json b/builder/cmd/evm/testdata/4/env.json deleted file mode 100644 index e283eff46..000000000 --- a/builder/cmd/evm/testdata/4/env.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "0x3b9aca00", - "currentNumber" : "0x05", - "currentTimestamp" : "0x03e8", - "blockHashes" : { "1" : "0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"} -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/4/readme.md b/builder/cmd/evm/testdata/4/readme.md deleted file mode 100644 index eede41a9f..000000000 --- a/builder/cmd/evm/testdata/4/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -These files exemplify a transition where a transaction (executed on block 5) requests -the blockhash for block `4`, but where the hash for that block is missing. -It's expected that executing these should cause `exit` with errorcode `4`. diff --git a/builder/cmd/evm/testdata/4/txs.json b/builder/cmd/evm/testdata/4/txs.json deleted file mode 100644 index 304445858..000000000 --- a/builder/cmd/evm/testdata/4/txs.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "input" : "0x", - "gas" : "0x5f5e100", - "gasPrice" : "0x1", - "nonce" : "0x0", - "to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", - "value" : "0x186a0", - "v" : "0x1b", - "r" : "0x88544c93a564b4c28d2ffac2074a0c55fdd4658fe0d215596ed2e32e3ef7f56b", - "s" : "0x7fb4075d54190f825d7c47bb820284757b34fd6293904a93cddb1d3aa961ac28", - "hash" : "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81" - } -] \ No newline at end of file diff --git a/builder/cmd/evm/testdata/5/alloc.json b/builder/cmd/evm/testdata/5/alloc.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/builder/cmd/evm/testdata/5/alloc.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/5/env.json b/builder/cmd/evm/testdata/5/env.json deleted file mode 100644 index 1085f63e6..000000000 --- a/builder/cmd/evm/testdata/5/env.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "currentCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x750a163df65e8a", - "currentNumber": "1", - "currentTimestamp": "1000", - "ommers": [ - {"delta": 1, "address": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, - {"delta": 2, "address": "0xcccccccccccccccccccccccccccccccccccccccc" } - ] -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/5/exp.json b/builder/cmd/evm/testdata/5/exp.json deleted file mode 100644 index 7d715672c..000000000 --- a/builder/cmd/evm/testdata/5/exp.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "alloc": { - "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": { - "balance": "0x88" - }, - "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": { - "balance": "0x70" - }, - "0xcccccccccccccccccccccccccccccccccccccccc": { - "balance": "0x60" - } - }, - "result": { - "stateRoot": "0xa7312add33811645c6aa65d928a1a4f49d65d448801912c069a0aa8fe9c1f393", - "txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "receipts": [], - "currentDifficulty": "0x20000", - "gasUsed": "0x0" - } -} diff --git a/builder/cmd/evm/testdata/5/readme.md b/builder/cmd/evm/testdata/5/readme.md deleted file mode 100644 index 1a84afaab..000000000 --- a/builder/cmd/evm/testdata/5/readme.md +++ /dev/null @@ -1 +0,0 @@ -These files exemplify a transition where there are no transactions, two ommers, at block `N-1` (delta 1) and `N-2` (delta 2). \ No newline at end of file diff --git a/builder/cmd/evm/testdata/5/txs.json b/builder/cmd/evm/testdata/5/txs.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/5/txs.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/7/alloc.json b/builder/cmd/evm/testdata/7/alloc.json deleted file mode 100644 index cef1a25ff..000000000 --- a/builder/cmd/evm/testdata/7/alloc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "code": "0x", - "nonce": "0xac", - "storage": {} - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192":{ - "balance": "0xfeedbead", - "nonce" : "0x00" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/7/env.json b/builder/cmd/evm/testdata/7/env.json deleted file mode 100644 index 8fd9bc041..000000000 --- a/builder/cmd/evm/testdata/7/env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "currentCoinbase": "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff020000", - "currentGasLimit": "0x750a163df65e8a", - "currentNumber": "5", - "currentTimestamp": "1000" -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/7/readme.md b/builder/cmd/evm/testdata/7/readme.md deleted file mode 100644 index 59e0dbef9..000000000 --- a/builder/cmd/evm/testdata/7/readme.md +++ /dev/null @@ -1,375 +0,0 @@ -This is a test for HomesteadToDao, checking if the -DAO-transition works - -Example: -``` - ./evm t8n --input.alloc=./testdata/7/alloc.json --input.txs=./testdata/7/txs.json --input.env=./testdata/7/env.json --output.alloc=stdout --state.fork=HomesteadToDaoAt5 -INFO [03-09|10:47:37.255] Trie dumping started root=157847..2891b7 -INFO [03-09|10:47:37.256] Trie dumping complete accounts=120 elapsed="715.635µs" -INFO [03-09|10:47:37.256] Wrote file file=result.json -{ - "alloc": { - "0x005f5cee7a43331d5a3d3eec71305925a62f34b6": { - "balance": "0x0" - }, - "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9": { - "balance": "0x0" - }, - "0x057b56736d32b86616a10f619859c6cd6f59092a": { - "balance": "0x0" - }, - "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936": { - "balance": "0x0" - }, - "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53": { - "balance": "0x0" - }, - "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a": { - "balance": "0x0" - }, - "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d": { - "balance": "0x0" - }, - "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00": { - "balance": "0x0" - }, - "0x12e626b0eebfe86a56d633b9864e389b45dcb260": { - "balance": "0x0" - }, - "0x1591fc0f688c81fbeb17f5426a162a7024d430c2": { - "balance": "0x0" - }, - "0x17802f43a0137c506ba92291391a8a8f207f487d": { - "balance": "0x0" - }, - "0x1975bd06d486162d5dc297798dfc41edd5d160a7": { - "balance": "0x0" - }, - "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b": { - "balance": "0x0" - }, - "0x1cba23d343a983e9b5cfd19496b9a9701ada385f": { - "balance": "0x0" - }, - "0x200450f06520bdd6c527622a273333384d870efb": { - "balance": "0x0" - }, - "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241": { - "balance": "0x0" - }, - "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50": { - "balance": "0x0" - }, - "0x24c4d950dfd4dd1902bbed3508144a54542bba94": { - "balance": "0x0" - }, - "0x253488078a4edf4d6f42f113d1e62836a942cf1a": { - "balance": "0x0" - }, - "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f": { - "balance": "0x0" - }, - "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c": { - "balance": "0x0" - }, - "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2": { - "balance": "0x0" - }, - "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f": { - "balance": "0x0" - }, - "0x304a554a310c7e546dfe434669c62820b7d83490": { - "balance": "0x0" - }, - "0x319f70bab6845585f412ec7724b744fec6095c85": { - "balance": "0x0" - }, - "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b": { - "balance": "0x0" - }, - "0x3ba4d81db016dc2890c81f3acec2454bff5aada5": { - "balance": "0x0" - }, - "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5": { - "balance": "0x0" - }, - "0x40b803a9abce16f50f36a77ba41180eb90023925": { - "balance": "0x0" - }, - "0x440c59b325d2997a134c2c7c60a8c61611212bad": { - "balance": "0x0" - }, - "0x4486a3d68fac6967006d7a517b889fd3f98c102b": { - "balance": "0x0" - }, - "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a": { - "balance": "0x0" - }, - "0x47e7aa56d6bdf3f36be34619660de61275420af8": { - "balance": "0x0" - }, - "0x4863226780fe7c0356454236d3b1c8792785748d": { - "balance": "0x0" - }, - "0x492ea3bb0f3315521c31f273e565b868fc090f17": { - "balance": "0x0" - }, - "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c": { - "balance": "0x0" - }, - "0x4deb0033bb26bc534b197e61d19e0733e5679784": { - "balance": "0x0" - }, - "0x4fa802324e929786dbda3b8820dc7834e9134a2a": { - "balance": "0x0" - }, - "0x4fd6ace747f06ece9c49699c7cabc62d02211f75": { - "balance": "0x0" - }, - "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6": { - "balance": "0x0" - }, - "0x52c5317c848ba20c7504cb2c8052abd1fde29d03": { - "balance": "0x0" - }, - "0x542a9515200d14b68e934e9830d91645a980dd7a": { - "balance": "0x0" - }, - "0x5524c55fb03cf21f549444ccbecb664d0acad706": { - "balance": "0x0" - }, - "0x579a80d909f346fbfb1189493f521d7f48d52238": { - "balance": "0x0" - }, - "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb": { - "balance": "0x0" - }, - "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5": { - "balance": "0x0" - }, - "0x5c8536898fbb74fc7445814902fd08422eac56d0": { - "balance": "0x0" - }, - "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479": { - "balance": "0x0" - }, - "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f": { - "balance": "0x0" - }, - "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c": { - "balance": "0x0" - }, - "0x6131c42fa982e56929107413a9d526fd99405560": { - "balance": "0x0" - }, - "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b": { - "balance": "0x0" - }, - "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7": { - "balance": "0x0" - }, - "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf": { - "balance": "0x0" - }, - "0x6966ab0d485353095148a2155858910e0965b6f9": { - "balance": "0x0" - }, - "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb": { - "balance": "0x0" - }, - "0x6d87578288b6cb5549d5076a207456a1f6a63dc0": { - "balance": "0x0" - }, - "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d": { - "balance": "0x0" - }, - "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97": { - "balance": "0x0" - }, - "0x779543a0491a837ca36ce8c635d6154e3c4911a6": { - "balance": "0x0" - }, - "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6": { - "balance": "0x0" - }, - "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4": { - "balance": "0x0" - }, - "0x807640a13483f8ac783c557fcdf27be11ea4ac7a": { - "balance": "0x0" - }, - "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd": { - "balance": "0x0" - }, - "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106": { - "balance": "0x0" - }, - "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915": { - "balance": "0x0" - }, - "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { - "balance": "0xfeedbead" - }, - "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6": { - "balance": "0x0" - }, - "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79": { - "balance": "0x0" - }, - "0x97f43a37f595ab5dd318fb46e7a155eae057317a": { - "balance": "0x0" - }, - "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192": { - "balance": "0x0" - }, - "0x9c15b54878ba618f494b38f0ae7443db6af648ba": { - "balance": "0x0" - }, - "0x9c50426be05db97f5d64fc54bf89eff947f0a321": { - "balance": "0x0" - }, - "0x9da397b9e80755301a3b32173283a91c0ef6c87e": { - "balance": "0x0" - }, - "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416": { - "balance": "0x0" - }, - "0x9f27daea7aca0aa0446220b98d028715e3bc803d": { - "balance": "0x0" - }, - "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339": { - "balance": "0x0" - }, - "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7": { - "balance": "0x0" - }, - "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6": { - "balance": "0x0" - }, - "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90": { - "balance": "0x0" - }, - "0xa82f360a8d3455c5c41366975bde739c37bfeb8a": { - "balance": "0x0" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x5ffd4878be161d74", - "nonce": "0xac" - }, - "0xac1ecab32727358dba8962a0f3b261731aad9723": { - "balance": "0x0" - }, - "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6": { - "balance": "0x0" - }, - "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225": { - "balance": "0x0" - }, - "0xadf80daec7ba8dcf15392f1ac611fff65d94f880": { - "balance": "0x0" - }, - "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c": { - "balance": "0x0" - }, - "0xb136707642a4ea12fb4bae820f03d2562ebff487": { - "balance": "0x0" - }, - "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e": { - "balance": "0x0" - }, - "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425": { - "balance": "0x0" - }, - "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab": { - "balance": "0x0" - }, - "0xb9637156d330c0d605a791f1c31ba5890582fe1c": { - "balance": "0x0" - }, - "0xbb9bc244d798123fde783fcc1c72d3bb8c189413": { - "balance": "0x0" - }, - "0xbc07118b9ac290e4622f5e77a0853539789effbe": { - "balance": "0x0" - }, - "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76": { - "balance": "0x0" - }, - "0xbe8539bfe837b67d1282b2b1d61c3f723966f049": { - "balance": "0x0" - }, - "0xbf4ed7b27f1d666546e30d74d50d173d20bca754": { - "balance": "0x0" - }, - "0xc4bbd073882dd2add2424cf47d35213405b01324": { - "balance": "0x0" - }, - "0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x0" - }, - "0xca544e5c4687d109611d0f8f928b53a25af72448": { - "balance": "0x0" - }, - "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7": { - "balance": "0x0" - }, - "0xcc34673c6c40e791051898567a1222daf90be287": { - "balance": "0x0" - }, - "0xceaeb481747ca6c540a000c1f3641f8cef161fa7": { - "balance": "0x0" - }, - "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e": { - "balance": "0x0" - }, - "0xd164b088bd9108b60d0ca3751da4bceb207b0782": { - "balance": "0x0" - }, - "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091": { - "balance": "0x0" - }, - "0xd343b217de44030afaa275f54d31a9317c7f441e": { - "balance": "0x0" - }, - "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728": { - "balance": "0x0" - }, - "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b": { - "balance": "0x0" - }, - "0xda2fef9e4a3230988ff17df2165440f37e8b1708": { - "balance": "0x0" - }, - "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940": { - "balance": "0x0" - }, - "0xe308bd1ac5fda103967359b2712dd89deffb7973": { - "balance": "0x0" - }, - "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1": { - "balance": "0x0" - }, - "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5": { - "balance": "0x0" - }, - "0xecd135fa4f61a655311e86238c92adcd779555d2": { - "balance": "0x0" - }, - "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5": { - "balance": "0x0" - }, - "0xf1385fb24aad0cd7432824085e42aff90886fef5": { - "balance": "0x0" - }, - "0xf14c14075d6c4ed84b86798af0956deef67365b5": { - "balance": "0x0" - }, - "0xf4c64518ea10f995918a454158c6b61407ea345c": { - "balance": "0x0" - }, - "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f": { - "balance": "0x0" - } - } -} -``` \ No newline at end of file diff --git a/builder/cmd/evm/testdata/7/txs.json b/builder/cmd/evm/testdata/7/txs.json deleted file mode 100644 index fe51488c7..000000000 --- a/builder/cmd/evm/testdata/7/txs.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/builder/cmd/evm/testdata/8/alloc.json b/builder/cmd/evm/testdata/8/alloc.json deleted file mode 100644 index 1d1b5f86c..000000000 --- a/builder/cmd/evm/testdata/8/alloc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "0x000000000000000000000000000000000000aaaa": { - "balance": "0x03", - "code": "0x5854505854", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x100000", - "nonce": "0x00" - } -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/8/env.json b/builder/cmd/evm/testdata/8/env.json deleted file mode 100644 index 8b9193472..000000000 --- a/builder/cmd/evm/testdata/8/env.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x1000000000", - "currentNumber": "0x1000000", - "currentTimestamp": "0x04" -} \ No newline at end of file diff --git a/builder/cmd/evm/testdata/8/readme.md b/builder/cmd/evm/testdata/8/readme.md deleted file mode 100644 index 85aae1892..000000000 --- a/builder/cmd/evm/testdata/8/readme.md +++ /dev/null @@ -1,59 +0,0 @@ -## EIP-2930 testing - -This test contains testcases for EIP-2930, which uses transactions with access lists. - -### Prestate - -The alloc portion contains one contract (`0x000000000000000000000000000000000000aaaa`), containing the -following code: `0x5854505854`: `PC ;SLOAD; POP; PC; SLOAD`. - -Essentially, this contract does `SLOAD(0)` and `SLOAD(3)`. - -The alloc also contains some funds on `0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b`. - -## Transactions - -There are three transactions, each invokes the contract above. - -1. ACL-transaction, which contains some non-used slots -2. Regular transaction -3. ACL-transaction, which contains the slots `1` and `3` in `0x000000000000000000000000000000000000aaaa` - -## Execution - -Running it yields: -``` -dir=./testdata/8 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace 2>/dev/null && cat trace-* | grep SLOAD -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -``` - -Similarly, we can provide the input transactions via `stdin` instead of as file: - -``` -$ dir=./testdata/8 \ - && cat $dir/txs.json | jq "{txs: .}" \ - | ./evm t8n --state.fork=Berlin \ - --input.alloc=$dir/alloc.json \ - --input.txs=stdin \ - --input.env=$dir/env.json \ - --trace \ - 2>/dev/null \ - && cat trace-* | grep SLOAD -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -``` - -If we try to execute it on older rules: -``` -$ dir=./testdata/8 && ./evm t8n --state.fork=Istanbul --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json -ERROR(10): failed signing transactions: ERROR(10): tx 0: failed to sign tx: transaction type not supported -``` diff --git a/builder/cmd/evm/testdata/8/txs.json b/builder/cmd/evm/testdata/8/txs.json deleted file mode 100644 index 35142ba23..000000000 --- a/builder/cmd/evm/testdata/8/txs.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "gas": "0x4ef00", - "gasPrice": "0x1", - "chainId": "0x1", - "input": "0x", - "nonce": "0x0", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x1", - "type" : "0x1", - "accessList": [ - {"address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x0", - "s": "0x0", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - { - "gas": "0x4ef00", - "gasPrice": "0x1", - "input": "0x", - "nonce": "0x1", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x2", - "v": "0x0", - "r": "0x0", - "s": "0x0", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - { - "gas": "0x4ef00", - "gasPrice": "0x1", - "chainId": "0x1", - "input": "0x", - "nonce": "0x2", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x1", - "type" : "0x1", - "accessList": [ - {"address": "0x000000000000000000000000000000000000aaaa", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ] - } - ], - "v": "0x0", - "r": "0x0", - "s": "0x0", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] diff --git a/builder/cmd/evm/testdata/9/alloc.json b/builder/cmd/evm/testdata/9/alloc.json deleted file mode 100644 index c14e38e84..000000000 --- a/builder/cmd/evm/testdata/9/alloc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "0x000000000000000000000000000000000000aaaa": { - "balance": "0x03", - "code": "0x58585454", - "nonce": "0x1" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0x100000000000000", - "nonce": "0x00" - } -} diff --git a/builder/cmd/evm/testdata/9/env.json b/builder/cmd/evm/testdata/9/env.json deleted file mode 100644 index 082bff778..000000000 --- a/builder/cmd/evm/testdata/9/env.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x1000000000", - "currentBaseFee": "0x3B9ACA00", - "currentNumber": "0x1000000", - "currentTimestamp": "0x04" -} diff --git a/builder/cmd/evm/testdata/9/readme.md b/builder/cmd/evm/testdata/9/readme.md deleted file mode 100644 index 357e20068..000000000 --- a/builder/cmd/evm/testdata/9/readme.md +++ /dev/null @@ -1,79 +0,0 @@ -## EIP-1559 testing - -This test contains testcases for EIP-1559, which uses a new transaction type and has a new block parameter. - -### Prestate - -The alloc portion contains one contract (`0x000000000000000000000000000000000000aaaa`), containing the -following code: `0x58585454`: `PC; PC; SLOAD; SLOAD`. - -Essentially, this contract does `SLOAD(0)` and `SLOAD(1)`. - -The alloc also contains some funds on `0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b`. - -## Transactions - -There are two transactions, each invokes the contract above. - -1. EIP-1559 ACL-transaction, which contains the `0x0` slot for `0xaaaa` -2. Legacy transaction - -## Execution - -Running it yields: -``` -$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --trace 2>/dev/null && cat trace-* | grep SLOAD -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x47c86","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":2,"op":84,"gas":"0x48c28","gasCost":"0x834","memSize":0,"stack":["0x0","0x1"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":3,"op":84,"gas":"0x483f4","gasCost":"0x64","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x49cf6","gasCost":"0x834","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x494be","gasCost":"0x834","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":2,"op":84,"gas":"0x49cf4","gasCost":"0x834","memSize":0,"stack":["0x0","0x1"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":3,"op":84,"gas":"0x494c0","gasCost":"0x834","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":1,"op":84,"gas":"0x484be","gasCost":"0x64","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"SLOAD"} -{"pc":4,"op":84,"gas":"0x48456","gasCost":"0x64","memSize":0,"stack":["0x3"],"depth":1,"refund":0,"opName":"SLOAD"} -``` - -We can also get the post-alloc: -``` -$ dir=./testdata/9 && ./evm t8n --state.fork=London --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout 2>/dev/null -{ - "alloc": { - "0x000000000000000000000000000000000000aaaa": { - "code": "0x58585454", - "balance": "0x3", - "nonce": "0x1" - }, - "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "balance": "0x5bb10ddef6e0" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xff745ee8832120", - "nonce": "0x2" - } - } -} -``` - -If we try to execute it on older rules: -``` -dir=./testdata/9 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout -ERROR(10): Failed signing transactions: ERROR(10): Tx 0: failed to sign tx: transaction type not supported -``` - -It fails, due to the `evm t8n` cannot sign them in with the given signer. We can bypass that, however, -by feeding it presigned transactions, located in `txs_signed.json`. - -``` -dir=./testdata/9 && ./evm t8n --state.fork=Berlin --input.alloc=$dir/alloc.json --input.txs=$dir/txs_signed.json --input.env=$dir/env.json -WARN [03-09|11:06:22.065] rejected tx index=0 hash=334e09..f8dce5 error="transaction type not supported" -INFO [03-09|11:06:22.066] rejected tx index=1 hash=a9c6c6..fa4036 from=0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B error="nonce too high: address 0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B, tx: 1 state: 0" -INFO [03-09|11:06:22.066] Trie dumping started root=6eebe9..a0fda5 -INFO [03-09|11:06:22.066] Trie dumping complete accounts=2 elapsed="55.844µs" -INFO [03-09|11:06:22.066] Wrote file file=alloc.json -INFO [03-09|11:06:22.066] Wrote file file=result.json -``` - -Number `0` is not applicable, and therefore number `1` has wrong nonce, and both are rejected. - diff --git a/builder/cmd/evm/testdata/9/txs.json b/builder/cmd/evm/testdata/9/txs.json deleted file mode 100644 index 740abce07..000000000 --- a/builder/cmd/evm/testdata/9/txs.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "gas": "0x4ef00", - "maxPriorityFeePerGas": "0x2", - "maxFeePerGas": "0x12A05F200", - "chainId": "0x1", - "input": "0x", - "nonce": "0x0", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "type" : "0x2", - "accessList": [ - {"address": "0x000000000000000000000000000000000000aaaa", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x0", - "s": "0x0", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - { - "gas": "0x4ef00", - "gasPrice": "0x12A05F200", - "chainId": "0x1", - "input": "0x", - "nonce": "0x1", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "v": "0x0", - "r": "0x0", - "s": "0x0", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] diff --git a/builder/cmd/evm/testdata/9/txs_signed.json b/builder/cmd/evm/testdata/9/txs_signed.json deleted file mode 100644 index dcddf011b..000000000 --- a/builder/cmd/evm/testdata/9/txs_signed.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "gas": "0x4ef00", - "maxFeePerGas": "0x2", - "maxPriorityFeePerGas": "0x12A05F200", - "chainId": "0x1", - "input": "0x", - "nonce": "0x0", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "type" : "0x2", - "accessList": [ - {"address": "0x000000000000000000000000000000000000aaaa", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xd77c8ff989789b5d9d99254cbae2e2996dc7e6215cba4d55254c14e6d6b9f314", - "s": "0x5cc021481e7e6bb444bbb87ab32071e8fd0a8d1e125c7bb352d2879bd7ff5c0a", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - { - "gas": "0x4ef00", - "gasPrice": "0x12A05F200", - "chainId": "0x1", - "input": "0x", - "nonce": "0x1", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "v": "0x25", - "r": "0xbee5ec9f6650020266bf3455a852eece2b073a2fa918c4d1836a1af69c2aa50c", - "s": "0x556c897a58dbc007a6b09814e1fba7502adb76effd2146da4365816926f387ce", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - } -] diff --git a/builder/cmd/evm/transition-test.sh b/builder/cmd/evm/transition-test.sh deleted file mode 100644 index 2ddda2d47..000000000 --- a/builder/cmd/evm/transition-test.sh +++ /dev/null @@ -1,518 +0,0 @@ -#!/bin/bash -ticks="\`\`\`" - -function showjson(){ - echo "\`$1\`:" - echo "${ticks}json" - cat $1 - echo "" - echo "$ticks" -} -function demo(){ - echo "$ticks" - echo "$1" - $1 - echo "" - echo "$ticks" - echo "" -} -function tick(){ - echo "$ticks" -} - -function code(){ - echo "$ticks$1" -} - -cat << "EOF" -# EVM tool - -The EVM tool provides a few useful subcommands to facilitate testing at the EVM -layer. - -* transition tool (`t8n`) : a stateless state transition utility -* transaction tool (`t9n`) : a transaction validation utility -* block builder tool (`b11r`): a block assembler utility - -## State transition tool (`t8n`) - - -The `evm t8n` tool is a stateless state transition utility. It is a utility -which can - -1. Take a prestate, including - - Accounts, - - Block context information, - - Previous blockshashes (*optional) -2. Apply a set of transactions, -3. Apply a mining-reward (*optional), -4. And generate a post-state, including - - State root, transaction root, receipt root, - - Information about rejected transactions, - - Optionally: a full or partial post-state dump - -### Specification - -The idea is to specify the behaviour of this binary very _strict_, so that other -node implementors can build replicas based on their own state-machines, and the -state generators can swap between a \`geth\`-based implementation and a \`parityvm\`-based -implementation. - -#### Command line params - -Command line params that need to be supported are - -``` -EOF -./evm t8n -h | grep "\-\-trace\.\|\-\-output\.\|\-\-state\.\|\-\-input" -cat << "EOF" -``` -#### Objects - -The transition tool uses JSON objects to read and write data related to the transition operation. The -following object definitions are required. - -##### `alloc` - -The `alloc` object defines the prestate that transition will begin with. - -```go -// Map of address to account definition. -type Alloc map[common.Address]Account -// Genesis account. Each field is optional. -type Account struct { - Code []byte `json:"code"` - Storage map[common.Hash]common.Hash `json:"storage"` - Balance *big.Int `json:"balance"` - Nonce uint64 `json:"nonce"` - SecretKey []byte `json:"secretKey"` -} -``` - -##### `env` - -The `env` object defines the environmental context in which the transition will -take place. - -```go -type Env struct { - // required - CurrentCoinbase common.Address `json:"currentCoinbase"` - CurrentGasLimit uint64 `json:"currentGasLimit"` - CurrentNumber uint64 `json:"currentNumber"` - CurrentTimestamp uint64 `json:"currentTimestamp"` - Withdrawals []*Withdrawal `json:"withdrawals"` - // optional - CurrentDifficulty *big.Int `json:"currentDifficulty"` - CurrentRandom *big.Int `json:"currentRandom"` - CurrentBaseFee *big.Int `json:"currentBaseFee"` - ParentDifficulty *big.Int `json:"parentDifficulty"` - ParentGasUsed uint64 `json:"parentGasUsed"` - ParentGasLimit uint64 `json:"parentGasLimit"` - ParentTimestamp uint64 `json:"parentTimestamp"` - BlockHashes map[uint64]common.Hash `json:"blockHashes"` - ParentUncleHash common.Hash `json:"parentUncleHash"` - Ommers []Ommer `json:"ommers"` -} -type Ommer struct { - Delta uint64 `json:"delta"` - Address common.Address `json:"address"` -} -type Withdrawal struct { - Index uint64 `json:"index"` - ValidatorIndex uint64 `json:"validatorIndex"` - Recipient common.Address `json:"recipient"` - Amount *big.Int `json:"amount"` -} -``` - -##### `txs` - -The `txs` object is an array of any of the transaction types: `LegacyTx`, -`AccessListTx`, or `DynamicFeeTx`. - -```go -type LegacyTx struct { - Nonce uint64 `json:"nonce"` - GasPrice *big.Int `json:"gasPrice"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -type AccessList []AccessTuple -type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` -} -type AccessListTx struct { - ChainID *big.Int `json:"chainId"` - Nonce uint64 `json:"nonce"` - GasPrice *big.Int `json:"gasPrice"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - AccessList AccessList `json:"accessList"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -type DynamicFeeTx struct { - ChainID *big.Int `json:"chainId"` - Nonce uint64 `json:"nonce"` - GasTipCap *big.Int `json:"maxPriorityFeePerGas"` - GasFeeCap *big.Int `json:"maxFeePerGas"` - Gas uint64 `json:"gas"` - To *common.Address `json:"to"` - Value *big.Int `json:"value"` - Data []byte `json:"data"` - AccessList AccessList `json:"accessList"` - V *big.Int `json:"v"` - R *big.Int `json:"r"` - S *big.Int `json:"s"` - SecretKey *common.Hash `json:"secretKey"` -} -``` - -##### `result` - -The `result` object is output after a transition is executed. It includes -information about the post-transition environment. - -```go -type ExecutionResult struct { - StateRoot common.Hash `json:"stateRoot"` - TxRoot common.Hash `json:"txRoot"` - ReceiptRoot common.Hash `json:"receiptsRoot"` - LogsHash common.Hash `json:"logsHash"` - Bloom types.Bloom `json:"logsBloom"` - Receipts types.Receipts `json:"receipts"` - Rejected []*rejectedTx `json:"rejected,omitempty"` - Difficulty *big.Int `json:"currentDifficulty"` - GasUsed uint64 `json:"gasUsed"` - BaseFee *big.Int `json:"currentBaseFee,omitempty"` -} -``` - -#### Error codes and output - -All logging should happen against the `stderr`. -There are a few (not many) errors that can occur, those are defined below. - -##### EVM-based errors (`2` to `9`) - -- Other EVM error. Exit code `2` -- Failed configuration: when a non-supported or invalid fork was specified. Exit code `3`. -- Block history is not supplied, but needed for a `BLOCKHASH` operation. If `BLOCKHASH` - is invoked targeting a block which history has not been provided for, the program will - exit with code `4`. - -##### IO errors (`10`-`20`) - -- Invalid input json: the supplied data could not be marshalled. - The program will exit with code `10` -- IO problems: failure to load or save files, the program will exit with code `11` - -``` -# This should exit with 3 -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Frontier+1346 2>/dev/null -EOF -./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Frontier+1346 2>/dev/null -exitcode=$? -if [ $exitcode != 3 ]; then - echo "Failed, exitcode should be 3,was $exitcode" -else - echo "exitcode:$exitcode OK" -fi -cat << "EOF" -``` -#### Forks -### Basic usage - -The chain configuration to be used for a transition is specified via the -`--state.fork` CLI flag. A list of possible values and configurations can be -found in [`tests/init.go`](tests/init.go). - -#### Examples -##### Basic usage - -Invoking it with the provided example files -EOF -cmd="./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin" -tick;echo "$cmd"; tick -$cmd 2>/dev/null -echo "Two resulting files:" -echo "" -showjson alloc.json -showjson result.json -echo "" - -echo "We can make them spit out the data to e.g. \`stdout\` like this:" -cmd="./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.result=stdout --output.alloc=stdout --state.fork=Berlin" -tick;echo "$cmd"; tick -output=`$cmd 2>/dev/null` -echo "Output:" -echo "${ticks}json" -echo "$output" -echo "$ticks" - -cat << "EOF" - -#### About Ommers - -Mining rewards and ommer rewards might need to be added. This is how those are applied: - -- `block_reward` is the block mining reward for the miner (`0xaa`), of a block at height `N`. -- For each ommer (mined by `0xbb`), with blocknumber `N-delta` - - (where `delta` is the difference between the current block and the ommer) - - The account `0xbb` (ommer miner) is awarded `(8-delta)/ 8 * block_reward` - - The account `0xaa` (block miner) is awarded `block_reward / 32` - -To make `t8n` apply these, the following inputs are required: - -- `--state.reward` - - For ethash, it is `5000000000000000000` `wei`, - - If this is not defined, mining rewards are not applied, - - A value of `0` is valid, and causes accounts to be 'touched'. -- For each ommer, the tool needs to be given an `address\` and a `delta`. This - is done via the `ommers` field in `env`. - -Note: the tool does not verify that e.g. the normal uncle rules apply, -and allows e.g two uncles at the same height, or the uncle-distance. This means that -the tool allows for negative uncle reward (distance > 8) - -Example: -EOF - -showjson ./testdata/5/env.json - -echo "When applying this, using a reward of \`0x08\`" -cmd="./evm t8n --input.alloc=./testdata/5/alloc.json -input.txs=./testdata/5/txs.json --input.env=./testdata/5/env.json --output.alloc=stdout --state.reward=0x80 --state.fork=Berlin" -output=`$cmd 2>/dev/null` -echo "Output:" -echo "${ticks}json" -echo "$output" -echo "$ticks" - -echo "#### Future EIPS" -echo "" -echo "It is also possible to experiment with future eips that are not yet defined in a hard fork." -echo "Example, putting EIP-1344 into Frontier: " -cmd="./evm t8n --state.fork=Frontier+1344 --input.pre=./testdata/1/pre.json --input.txs=./testdata/1/txs.json --input.env=/testdata/1/env.json" -tick;echo "$cmd"; tick -echo "" - -echo "#### Block history" -echo "" -echo "The \`BLOCKHASH\` opcode requires blockhashes to be provided by the caller, inside the \`env\`." -echo "If a required blockhash is not provided, the exit code should be \`4\`:" -echo "Example where blockhashes are provided: " -demo "./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace --state.fork=Berlin" -cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2" -tick && echo $cmd && tick -echo "$ticks" -cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2 -echo "$ticks" -echo "" - -echo "In this example, the caller has not provided the required blockhash:" -cmd="./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace --state.fork=Berlin" -tick && echo $cmd && $cmd 2>&1 -errc=$? -tick -echo "Error code: $errc" -echo "" - -echo "#### Chaining" -echo "" -echo "Another thing that can be done, is to chain invocations:" -cmd1="./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --state.fork=Berlin --output.alloc=stdout" -cmd2="./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json --state.fork=Berlin" -echo "$ticks" -echo "$cmd1 | $cmd2" -output=$($cmd1 | $cmd2 ) -echo $output -echo "$ticks" -echo "What happened here, is that we first applied two identical transactions, so the second one was rejected. " -echo "Then, taking the poststate alloc as the input for the next state, we tried again to include" -echo "the same two transactions: this time, both failed due to too low nonce." -echo "" -echo "In order to meaningfully chain invocations, one would need to provide meaningful new \`env\`, otherwise the" -echo "actual blocknumber (exposed to the EVM) would not increase." -echo "" - -echo "#### Transactions in RLP form" -echo "" -echo "It is possible to provide already-signed transactions as input to, using an \`input.txs\` which ends with the \`rlp\` suffix." -echo "The input format for RLP-form transactions is _identical_ to the _output_ format for block bodies. Therefore, it's fully possible" -echo "to use the evm to go from \`json\` input to \`rlp\` input." -echo "" -echo "The following command takes **json** the transactions in \`./testdata/13/txs.json\` and signs them. After execution, they are output to \`signed_txs.rlp\`.:" -cmd="./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./testdata/13/txs.json --input.env=./testdata/13/env.json --output.result=alloc_jsontx.json --output.body=signed_txs.rlp" -echo "$ticks" -echo $cmd -$cmd 2>&1 -echo "$ticks" -echo "" -echo "The \`output.body\` is the rlp-list of transactions, encoded in hex and placed in a string a'la \`json\` encoding rules:" -demo "cat signed_txs.rlp" -echo "We can use \`rlpdump\` to check what the contents are: " -echo "$ticks" -echo "rlpdump -hex \$(cat signed_txs.rlp | jq -r )" -rlpdump -hex $(cat signed_txs.rlp | jq -r ) -echo "$ticks" -echo "Now, we can now use those (or any other already signed transactions), as input, like so: " -cmd="./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./signed_txs.rlp --input.env=./testdata/13/env.json --output.result=alloc_rlptx.json" -echo "$ticks" -echo $cmd -$cmd 2>&1 -echo "$ticks" -echo "You might have noticed that the results from these two invocations were stored in two separate files. " -echo "And we can now finally check that they match." -echo "$ticks" -echo "cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot" -cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot -echo "$ticks" - -cat << "EOF" - -## Transaction tool - -The transaction tool is used to perform static validity checks on transactions such as: -* intrinsic gas calculation -* max values on integers -* fee semantics, such as `maxFeePerGas < maxPriorityFeePerGas` -* newer tx types on old forks - -### Examples - -EOF - -cmd="./evm t9n --state.fork Homestead --input.txs testdata/15/signed_txs.rlp" -tick;echo "$cmd"; -$cmd 2>/dev/null -tick - -cmd="./evm t9n --state.fork London --input.txs testdata/15/signed_txs.rlp" -tick;echo "$cmd"; -$cmd 2>/dev/null -tick - -cat << "EOF" -## Block builder tool (b11r) - -The `evm b11r` tool is used to assemble and seal full block rlps. - -### Specification - -#### Command line params - -Command line params that need to be supported are: - -``` - --input.header value `stdin` or file name of where to find the block header to use. (default: "header.json") - --input.ommers value `stdin` or file name of where to find the list of ommer header RLPs to use. - --input.txs value `stdin` or file name of where to find the transactions list in RLP form. (default: "txs.rlp") - --output.basedir value Specifies where output files are placed. Will be created if it does not exist. - --output.block value Determines where to put the alloc of the post-state. (default: "block.json") - - into the file - `stdout` - into the stdout output - `stderr` - into the stderr output - --seal.clique value Seal block with Clique. `stdin` or file name of where to find the Clique sealing data. - --seal.ethash Seal block with ethash. (default: false) - --seal.ethash.dir value Path to ethash DAG. If none exists, a new DAG will be generated. - --seal.ethash.mode value Defines the type and amount of PoW verification an ethash engine makes. (default: "normal") - --verbosity value Sets the verbosity level. (default: 3) -``` - -#### Objects - -##### `header` - -The `header` object is a consensus header. - -```go= -type Header struct { - ParentHash common.Hash `json:"parentHash"` - OmmerHash *common.Hash `json:"sha3Uncles"` - Coinbase *common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot"` - ReceiptHash *common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *big.Int `json:"difficulty"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce *types.BlockNonce `json:"nonce"` - BaseFee *big.Int `json:"baseFeePerGas"` -} -``` -#### `ommers` - -The `ommers` object is a list of RLP-encoded ommer blocks in hex -representation. - -```go= -type Ommers []string -``` - -#### `txs` - -The `txs` object is a list of RLP-encoded transactions in hex representation. - -```go= -type Txs []string -``` - -#### `clique` - -The `clique` object provides the necessary information to complete a clique -seal of the block. - -```go= -var CliqueInfo struct { - Key *common.Hash `json:"secretKey"` - Voted *common.Address `json:"voted"` - Authorize *bool `json:"authorize"` - Vanity common.Hash `json:"vanity"` -} -``` - -#### `output` - -The `output` object contains two values, the block RLP and the block hash. - -```go= -type BlockInfo struct { - Rlp []byte `json:"rlp"` - Hash common.Hash `json:"hash"` -} -``` - -## A Note on Encoding - -The encoding of values for `evm` utility attempts to be relatively flexible. It -generally supports hex-encoded or decimal-encoded numeric values, and -hex-encoded byte values (like `common.Address`, `common.Hash`, etc). When in -doubt, the [`execution-apis`](https://github.com/ethereum/execution-apis) way -of encoding should always be accepted. - -## Testing - -There are many test cases in the [`cmd/evm/testdata`](./testdata) directory. -These fixtures are used to power the `t8n` tests in -[`t8n_test.go`](./t8n_test.go). The best way to verify correctness of new `evm` -implementations is to execute these and verify the output and error codes match -the expected values. - -EOF diff --git a/builder/cmd/geth/accountcmd.go b/builder/cmd/geth/accountcmd.go deleted file mode 100644 index cc22684e0..000000000 --- a/builder/cmd/geth/accountcmd.go +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli/v2" -) - -var ( - walletCommand = &cli.Command{ - Name: "wallet", - Usage: "Manage Ethereum presale wallets", - ArgsUsage: "", - Description: ` - geth wallet import /path/to/my/presale.wallet - -will prompt for your password and imports your ether presale account. -It can be used non-interactively with the --password option taking a -passwordfile as argument containing the wallet password in plaintext.`, - Subcommands: []*cli.Command{ - { - - Name: "import", - Usage: "Import Ethereum presale wallet", - ArgsUsage: "", - Action: importWallet, - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - utils.PasswordFileFlag, - utils.LightKDFFlag, - }, - Description: ` - geth wallet [options] /path/to/my/presale.wallet - -will prompt for your password and imports your ether presale account. -It can be used non-interactively with the --password option taking a -passwordfile as argument containing the wallet password in plaintext.`, - }, - }, - } - - accountCommand = &cli.Command{ - Name: "account", - Usage: "Manage accounts", - Description: ` - -Manage accounts, list all existing accounts, import a private key into a new -account, create a new account or update an existing account. - -It supports interactive mode, when you are prompted for password as well as -non-interactive mode where passwords are supplied via a given password file. -Non-interactive mode is only meant for scripted use on test networks or known -safe environments. - -Make sure you remember the password you gave when creating a new account (with -either new or import). Without it you are not able to unlock your account. - -Note that exporting your key in unencrypted format is NOT supported. - -Keys are stored under /keystore. -It is safe to transfer the entire directory or the individual keys therein -between ethereum nodes by simply copying. - -Make sure you backup your keys regularly.`, - Subcommands: []*cli.Command{ - { - Name: "list", - Usage: "Print summary of existing accounts", - Action: accountList, - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - }, - Description: ` -Print a short summary of all accounts`, - }, - { - Name: "new", - Usage: "Create a new account", - Action: accountCreate, - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - utils.PasswordFileFlag, - utils.LightKDFFlag, - }, - Description: ` - geth account new - -Creates a new account and prints the address. - -The account is saved in encrypted format, you are prompted for a password. - -You must remember this password to unlock your account in the future. - -For non-interactive use the password can be specified with the --password flag: - -Note, this is meant to be used for testing only, it is a bad idea to save your -password to file or expose in any other way. -`, - }, - { - Name: "update", - Usage: "Update an existing account", - Action: accountUpdate, - ArgsUsage: "
", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - utils.LightKDFFlag, - }, - Description: ` - geth account update
- -Update an existing account. - -The account is saved in the newest version in encrypted format, you are prompted -for a password to unlock the account and another to save the updated file. - -This same command can therefore be used to migrate an account of a deprecated -format to the newest format or change the password for an account. - -For non-interactive use the password can be specified with the --password flag: - - geth account update [options]
- -Since only one password can be given, only format update can be performed, -changing your password is only possible interactively. -`, - }, - { - Name: "import", - Usage: "Import a private key into a new account", - Action: accountImport, - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - utils.PasswordFileFlag, - utils.LightKDFFlag, - }, - ArgsUsage: "", - Description: ` - geth account import - -Imports an unencrypted private key from and creates a new account. -Prints the address. - -The keyfile is assumed to contain an unencrypted private key in hexadecimal format. - -The account is saved in encrypted format, you are prompted for a password. - -You must remember this password to unlock your account in the future. - -For non-interactive use the password can be specified with the -password flag: - - geth account import [options] - -Note: -As you can directly copy your encrypted accounts to another ethereum instance, -this import mechanism is not needed when you transfer an account between -nodes. -`, - }, - }, - } -) - -// makeAccountManager creates an account manager with backends -func makeAccountManager(ctx *cli.Context) *accounts.Manager { - cfg := loadBaseConfig(ctx) - am := accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: cfg.Node.InsecureUnlockAllowed}) - keydir, isEphemeral, err := cfg.Node.GetKeyStoreDir() - if err != nil { - utils.Fatalf("Failed to get the keystore directory: %v", err) - } - if isEphemeral { - utils.Fatalf("Can't use ephemeral directory as keystore path") - } - - if err := setAccountManagerBackends(&cfg.Node, am, keydir); err != nil { - utils.Fatalf("Failed to set account manager backends: %v", err) - } - return am -} - -func accountList(ctx *cli.Context) error { - am := makeAccountManager(ctx) - var index int - for _, wallet := range am.Wallets() { - for _, account := range wallet.Accounts() { - fmt.Printf("Account #%d: {%x} %s\n", index, account.Address, &account.URL) - index++ - } - } - - return nil -} - -// tries unlocking the specified account a few times. -func unlockAccount(ks *keystore.KeyStore, address string, i int, passwords []string) (accounts.Account, string) { - account, err := utils.MakeAddress(ks, address) - if err != nil { - utils.Fatalf("Could not list accounts: %v", err) - } - for trials := 0; trials < 3; trials++ { - prompt := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", address, trials+1, 3) - password := utils.GetPassPhraseWithList(prompt, false, i, passwords) - err = ks.Unlock(account, password) - if err == nil { - log.Info("Unlocked account", "address", account.Address.Hex()) - return account, password - } - if err, ok := err.(*keystore.AmbiguousAddrError); ok { - log.Info("Unlocked account", "address", account.Address.Hex()) - return ambiguousAddrRecovery(ks, err, password), password - } - if err != keystore.ErrDecrypt { - // No need to prompt again if the error is not decryption-related. - break - } - } - // All trials expended to unlock account, bail out - utils.Fatalf("Failed to unlock account %s (%v)", address, err) - - return accounts.Account{}, "" -} - -func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrError, auth string) accounts.Account { - fmt.Printf("Multiple key files exist for address %x:\n", err.Addr) - for _, a := range err.Matches { - fmt.Println(" ", a.URL) - } - fmt.Println("Testing your password against all of them...") - var match *accounts.Account - for i, a := range err.Matches { - if e := ks.Unlock(a, auth); e == nil { - match = &err.Matches[i] - break - } - } - if match == nil { - utils.Fatalf("None of the listed files could be unlocked.") - return accounts.Account{} - } - fmt.Printf("Your password unlocked %s\n", match.URL) - fmt.Println("In order to avoid this warning, you need to remove the following duplicate key files:") - for _, a := range err.Matches { - if a != *match { - fmt.Println(" ", a.URL) - } - } - return *match -} - -// accountCreate creates a new account into the keystore defined by the CLI flags. -func accountCreate(ctx *cli.Context) error { - cfg := loadBaseConfig(ctx) - keydir, isEphemeral, err := cfg.Node.GetKeyStoreDir() - if err != nil { - utils.Fatalf("Failed to get the keystore directory: %v", err) - } - if isEphemeral { - utils.Fatalf("Can't use ephemeral directory as keystore path") - } - scryptN := keystore.StandardScryptN - scryptP := keystore.StandardScryptP - if cfg.Node.UseLightweightKDF { - scryptN = keystore.LightScryptN - scryptP = keystore.LightScryptP - } - - password := utils.GetPassPhraseWithList("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) - - account, err := keystore.StoreKey(keydir, password, scryptN, scryptP) - - if err != nil { - utils.Fatalf("Failed to create account: %v", err) - } - fmt.Printf("\nYour new key was generated\n\n") - fmt.Printf("Public address of the key: %s\n", account.Address.Hex()) - fmt.Printf("Path of the secret key file: %s\n\n", account.URL.Path) - fmt.Printf("- You can share your public address with anyone. Others need it to interact with you.\n") - fmt.Printf("- You must NEVER share the secret key with anyone! The key controls access to your funds!\n") - fmt.Printf("- You must BACKUP your key file! Without the key, it's impossible to access account funds!\n") - fmt.Printf("- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!\n\n") - return nil -} - -// accountUpdate transitions an account from a previous format to the current -// one, also providing the possibility to change the pass-phrase. -func accountUpdate(ctx *cli.Context) error { - if ctx.Args().Len() == 0 { - utils.Fatalf("No accounts specified to update") - } - am := makeAccountManager(ctx) - backends := am.Backends(keystore.KeyStoreType) - if len(backends) == 0 { - utils.Fatalf("Keystore is not available") - } - ks := backends[0].(*keystore.KeyStore) - - for _, addr := range ctx.Args().Slice() { - account, oldPassword := unlockAccount(ks, addr, 0, nil) - newPassword := utils.GetPassPhraseWithList("Please give a new password. Do not forget this password.", true, 0, nil) - if err := ks.Update(account, oldPassword, newPassword); err != nil { - utils.Fatalf("Could not update the account: %v", err) - } - } - return nil -} - -func importWallet(ctx *cli.Context) error { - if ctx.Args().Len() != 1 { - utils.Fatalf("keyfile must be given as the only argument") - } - keyfile := ctx.Args().First() - keyJSON, err := os.ReadFile(keyfile) - if err != nil { - utils.Fatalf("Could not read wallet file: %v", err) - } - - am := makeAccountManager(ctx) - backends := am.Backends(keystore.KeyStoreType) - if len(backends) == 0 { - utils.Fatalf("Keystore is not available") - } - ks := backends[0].(*keystore.KeyStore) - passphrase := utils.GetPassPhraseWithList("", false, 0, utils.MakePasswordList(ctx)) - - acct, err := ks.ImportPreSaleKey(keyJSON, passphrase) - if err != nil { - utils.Fatalf("%v", err) - } - fmt.Printf("Address: {%x}\n", acct.Address) - return nil -} - -func accountImport(ctx *cli.Context) error { - if ctx.Args().Len() != 1 { - utils.Fatalf("keyfile must be given as the only argument") - } - keyfile := ctx.Args().First() - key, err := crypto.LoadECDSA(keyfile) - if err != nil { - utils.Fatalf("Failed to load the private key: %v", err) - } - am := makeAccountManager(ctx) - backends := am.Backends(keystore.KeyStoreType) - if len(backends) == 0 { - utils.Fatalf("Keystore is not available") - } - ks := backends[0].(*keystore.KeyStore) - passphrase := utils.GetPassPhraseWithList("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) - - acct, err := ks.ImportECDSA(key, passphrase) - if err != nil { - utils.Fatalf("Could not create the account: %v", err) - } - fmt.Printf("Address: {%x}\n", acct.Address) - return nil -} diff --git a/builder/cmd/geth/accountcmd_test.go b/builder/cmd/geth/accountcmd_test.go deleted file mode 100644 index ea3a7c3b6..000000000 --- a/builder/cmd/geth/accountcmd_test.go +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "os" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/cespare/cp" -) - -// These tests are 'smoke tests' for the account related -// subcommands and flags. -// -// For most tests, the test files from package accounts -// are copied into a temporary keystore directory. - -func tmpDatadirWithKeystore(t *testing.T) string { - datadir := t.TempDir() - keystore := filepath.Join(datadir, "keystore") - source := filepath.Join("..", "..", "accounts", "keystore", "testdata", "keystore") - if err := cp.CopyAll(keystore, source); err != nil { - t.Fatal(err) - } - return datadir -} - -func TestAccountListEmpty(t *testing.T) { - t.Parallel() - geth := runGeth(t, "account", "list") - geth.ExpectExit() -} - -func TestAccountList(t *testing.T) { - t.Parallel() - datadir := tmpDatadirWithKeystore(t) - var want = ` -Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 -Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa -Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz -` - if runtime.GOOS == "windows" { - want = ` -Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 -Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}\keystore\aaa -Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\keystore\zzz -` - } - { - geth := runGeth(t, "account", "list", "--datadir", datadir) - geth.Expect(want) - geth.ExpectExit() - } - { - geth := runGeth(t, "--datadir", datadir, "account", "list") - geth.Expect(want) - geth.ExpectExit() - } -} - -func TestAccountNew(t *testing.T) { - t.Parallel() - geth := runGeth(t, "account", "new", "--lightkdf") - defer geth.ExpectExit() - geth.Expect(` -Your new account is locked with a password. Please give a password. Do not forget this password. -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -Repeat password: {{.InputLine "foobar"}} - -Your new key was generated -`) - geth.ExpectRegexp(` -Public address of the key: 0x[0-9a-fA-F]{40} -Path of the secret key file: .*UTC--.+--[0-9a-f]{40} - -- You can share your public address with anyone. Others need it to interact with you. -- You must NEVER share the secret key with anyone! The key controls access to your funds! -- You must BACKUP your key file! Without the key, it's impossible to access account funds! -- You must REMEMBER your password! Without the password, it's impossible to decrypt the key! -`) -} - -func TestAccountImport(t *testing.T) { - t.Parallel() - tests := []struct{ name, key, output string }{ - { - name: "correct account", - key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", - output: "Address: {fcad0b19bb29d4674531d6f115237e16afce377c}\n", - }, - { - name: "invalid character", - key: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef1", - output: "Fatal: Failed to load the private key: invalid character '1' at end of key file\n", - }, - } - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - t.Parallel() - importAccountWithExpect(t, test.key, test.output) - }) - } -} - -func TestAccountHelp(t *testing.T) { - t.Parallel() - geth := runGeth(t, "account", "-h") - geth.WaitExit() - if have, want := geth.ExitStatus(), 0; have != want { - t.Errorf("exit error, have %d want %d", have, want) - } - - geth = runGeth(t, "account", "import", "-h") - geth.WaitExit() - if have, want := geth.ExitStatus(), 0; have != want { - t.Errorf("exit error, have %d want %d", have, want) - } -} - -func importAccountWithExpect(t *testing.T, key string, expected string) { - dir := t.TempDir() - keyfile := filepath.Join(dir, "key.prv") - if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil { - t.Error(err) - } - passwordFile := filepath.Join(dir, "password.txt") - if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil { - t.Error(err) - } - geth := runGeth(t, "--lightkdf", "account", "import", "-password", passwordFile, keyfile) - defer geth.ExpectExit() - geth.Expect(expected) -} - -func TestAccountNewBadRepeat(t *testing.T) { - t.Parallel() - geth := runGeth(t, "account", "new", "--lightkdf") - defer geth.ExpectExit() - geth.Expect(` -Your new account is locked with a password. Please give a password. Do not forget this password. -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "something"}} -Repeat password: {{.InputLine "something else"}} -Fatal: Passwords do not match -`) -} - -func TestAccountUpdate(t *testing.T) { - t.Parallel() - datadir := tmpDatadirWithKeystore(t) - geth := runGeth(t, "account", "update", - "--datadir", datadir, "--lightkdf", - "f466859ead1932d743d622cb74fc058882e8648a") - defer geth.ExpectExit() - geth.Expect(` -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -Please give a new password. Do not forget this password. -Password: {{.InputLine "foobar2"}} -Repeat password: {{.InputLine "foobar2"}} -`) -} - -func TestWalletImport(t *testing.T) { - t.Parallel() - geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json") - defer geth.ExpectExit() - geth.Expect(` -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foo"}} -Address: {d4584b5f6229b7be90727b0fc8c6b91bb427821f} -`) - - files, err := os.ReadDir(filepath.Join(geth.Datadir, "keystore")) - if len(files) != 1 { - t.Errorf("expected one key file in keystore directory, found %d files (error: %v)", len(files), err) - } -} - -func TestWalletImportBadPassword(t *testing.T) { - t.Parallel() - geth := runGeth(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json") - defer geth.ExpectExit() - geth.Expect(` -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "wrong"}} -Fatal: could not decrypt key with given password -`) -} - -func TestUnlockFlag(t *testing.T) { - t.Parallel() - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')") - geth.Expect(` -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -undefined -`) - geth.ExpectExit() - - wantMessages := []string{ - "Unlocked account", - "=0xf466859eAD1932D743d622CB74FC058882E8648A", - } - for _, m := range wantMessages { - if !strings.Contains(geth.StderrText(), m) { - t.Errorf("stderr text does not contain %q", m) - } - } -} - -func TestUnlockFlagWrongPassword(t *testing.T) { - t.Parallel() - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "console", "--exec", "loadScript('testdata/empty.js')") - - defer geth.ExpectExit() - geth.Expect(` -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "wrong1"}} -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 2/3 -Password: {{.InputLine "wrong2"}} -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 3/3 -Password: {{.InputLine "wrong3"}} -Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could not decrypt key with given password) -`) -} - -// https://github.com/ethereum/go-ethereum/issues/1785 -func TestUnlockFlagMultiIndex(t *testing.T) { - t.Parallel() - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')") - - geth.Expect(` -Unlocking account 0 | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -Unlocking account 2 | Attempt 1/3 -Password: {{.InputLine "foobar"}} -undefined -`) - geth.ExpectExit() - - wantMessages := []string{ - "Unlocked account", - "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8", - "=0x289d485D9771714CCe91D3393D764E1311907ACc", - } - for _, m := range wantMessages { - if !strings.Contains(geth.StderrText(), m) { - t.Errorf("stderr text does not contain %q", m) - } - } -} - -func TestUnlockFlagPasswordFile(t *testing.T) { - t.Parallel() - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password", "testdata/passwords.txt", "--unlock", "0,2", "console", "--exec", "loadScript('testdata/empty.js')") - - geth.Expect(` -undefined -`) - geth.ExpectExit() - - wantMessages := []string{ - "Unlocked account", - "=0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8", - "=0x289d485D9771714CCe91D3393D764E1311907ACc", - } - for _, m := range wantMessages { - if !strings.Contains(geth.StderrText(), m) { - t.Errorf("stderr text does not contain %q", m) - } - } -} - -func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) { - t.Parallel() - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--password", - "testdata/wrong-passwords.txt", "--unlock", "0,2") - defer geth.ExpectExit() - geth.Expect(` -Fatal: Failed to unlock account 0 (could not decrypt key with given password) -`) -} - -func TestUnlockFlagAmbiguous(t *testing.T) { - t.Parallel() - store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore", - store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", - "console", "--exec", "loadScript('testdata/empty.js')") - defer geth.ExpectExit() - - // Helper for the expect template, returns absolute keystore path. - geth.SetTemplateFunc("keypath", func(file string) string { - abs, _ := filepath.Abs(filepath.Join(store, file)) - return abs - }) - geth.Expect(` -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "foobar"}} -Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a: - keystore://{{keypath "1"}} - keystore://{{keypath "2"}} -Testing your password against all of them... -Your password unlocked keystore://{{keypath "1"}} -In order to avoid this warning, you need to remove the following duplicate key files: - keystore://{{keypath "2"}} -undefined -`) - geth.ExpectExit() - - wantMessages := []string{ - "Unlocked account", - "=0xf466859eAD1932D743d622CB74FC058882E8648A", - } - for _, m := range wantMessages { - if !strings.Contains(geth.StderrText(), m) { - t.Errorf("stderr text does not contain %q", m) - } - } -} - -func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) { - t.Parallel() - store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") - geth := runMinimalGeth(t, "--port", "0", "--ipcdisable", "--datadir", tmpDatadirWithKeystore(t), - "--unlock", "f466859ead1932d743d622cb74fc058882e8648a", "--keystore", - store, "--unlock", "f466859ead1932d743d622cb74fc058882e8648a") - - defer geth.ExpectExit() - - // Helper for the expect template, returns absolute keystore path. - geth.SetTemplateFunc("keypath", func(file string) string { - abs, _ := filepath.Abs(filepath.Join(store, file)) - return abs - }) - geth.Expect(` -Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3 -!! Unsupported terminal, password will be echoed. -Password: {{.InputLine "wrong"}} -Multiple key files exist for address f466859ead1932d743d622cb74fc058882e8648a: - keystore://{{keypath "1"}} - keystore://{{keypath "2"}} -Testing your password against all of them... -Fatal: None of the listed files could be unlocked. -`) - geth.ExpectExit() -} diff --git a/builder/cmd/geth/attach_test.go b/builder/cmd/geth/attach_test.go deleted file mode 100644 index 91007ccf6..000000000 --- a/builder/cmd/geth/attach_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// 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 main - -import ( - "fmt" - "net" - "net/http" - "sync/atomic" - "testing" -) - -type testHandler struct { - body func(http.ResponseWriter, *http.Request) -} - -func (t *testHandler) ServeHTTP(out http.ResponseWriter, in *http.Request) { - t.body(out, in) -} - -// TestAttachWithHeaders tests that 'geth attach' with custom headers works, i.e -// that custom headers are forwarded to the target. -func TestAttachWithHeaders(t *testing.T) { - t.Parallel() - ln, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } - port := ln.Addr().(*net.TCPAddr).Port - testReceiveHeaders(t, ln, "attach", "-H", "first: one", "-H", "second: two", fmt.Sprintf("http://localhost:%d", port)) - // This way to do it fails due to flag ordering: - // - // testReceiveHeaders(t, ln, "-H", "first: one", "-H", "second: two", "attach", fmt.Sprintf("http://localhost:%d", port)) - // This is fixed in a follow-up PR. -} - -// TestAttachWithHeaders tests that 'geth db --remotedb' with custom headers works, i.e -// that custom headers are forwarded to the target. -func TestRemoteDbWithHeaders(t *testing.T) { - t.Parallel() - ln, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } - port := ln.Addr().(*net.TCPAddr).Port - testReceiveHeaders(t, ln, "db", "metadata", "--remotedb", fmt.Sprintf("http://localhost:%d", port), "-H", "first: one", "-H", "second: two") -} - -func testReceiveHeaders(t *testing.T, ln net.Listener, gethArgs ...string) { - var ok atomic.Uint32 - server := &http.Server{ - Addr: "localhost:0", - Handler: &testHandler{func(w http.ResponseWriter, r *http.Request) { - // We expect two headers - if have, want := r.Header.Get("first"), "one"; have != want { - t.Fatalf("missing header, have %v want %v", have, want) - } - if have, want := r.Header.Get("second"), "two"; have != want { - t.Fatalf("missing header, have %v want %v", have, want) - } - ok.Store(1) - }}} - go server.Serve(ln) - defer server.Close() - runGeth(t, gethArgs...).WaitExit() - if ok.Load() != 1 { - t.Fatal("Test fail, expected invocation to succeed") - } -} diff --git a/builder/cmd/geth/chaincmd.go b/builder/cmd/geth/chaincmd.go deleted file mode 100644 index d333c1755..000000000 --- a/builder/cmd/geth/chaincmd.go +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "errors" - "fmt" - "os" - "runtime" - "strconv" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/urfave/cli/v2" -) - -var ( - initCommand = &cli.Command{ - Action: initGenesis, - Name: "init", - Usage: "Bootstrap and initialize a new genesis block", - ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ - utils.CachePreimagesFlag, - utils.OverrideCancun, - utils.OverrideVerkle, - }, utils.DatabaseFlags), - Description: ` -The init command initializes a new genesis block and definition for the network. -This is a destructive action and changes the network in which you will be -participating. - -It expects the genesis file as argument.`, - } - dumpGenesisCommand = &cli.Command{ - Action: dumpGenesis, - Name: "dumpgenesis", - Usage: "Dumps genesis block JSON configuration to stdout", - ArgsUsage: "", - Flags: append([]cli.Flag{utils.DataDirFlag}, utils.NetworkFlags...), - Description: ` -The dumpgenesis command prints the genesis configuration of the network preset -if one is set. Otherwise it prints the genesis from the datadir.`, - } - importCommand = &cli.Command{ - Action: importChain, - Name: "import", - Usage: "Import a blockchain file", - ArgsUsage: " ( ... ) ", - Flags: flags.Merge([]cli.Flag{ - utils.CacheFlag, - utils.SyncModeFlag, - utils.GCModeFlag, - utils.SnapshotFlag, - utils.CacheDatabaseFlag, - utils.CacheGCFlag, - utils.MetricsEnabledFlag, - utils.MetricsEnabledExpensiveFlag, - utils.MetricsHTTPFlag, - utils.MetricsPortFlag, - utils.MetricsEnableInfluxDBFlag, - utils.MetricsEnableInfluxDBV2Flag, - utils.MetricsInfluxDBEndpointFlag, - utils.MetricsInfluxDBDatabaseFlag, - utils.MetricsInfluxDBUsernameFlag, - utils.MetricsInfluxDBPasswordFlag, - utils.MetricsInfluxDBTagsFlag, - utils.MetricsInfluxDBTokenFlag, - utils.MetricsInfluxDBBucketFlag, - utils.MetricsInfluxDBOrganizationFlag, - utils.TxLookupLimitFlag, - utils.TransactionHistoryFlag, - utils.StateHistoryFlag, - }, utils.DatabaseFlags), - Description: ` -The import command imports blocks from an RLP-encoded form. The form can be one file -with several RLP-encoded blocks, or several files can be used. - -If only one file is used, import error will result in failure. If several files are used, -processing will proceed even if an individual RLP-file import failure occurs.`, - } - exportCommand = &cli.Command{ - Action: exportChain, - Name: "export", - Usage: "Export blockchain into file", - ArgsUsage: " [ ]", - Flags: flags.Merge([]cli.Flag{ - utils.CacheFlag, - utils.SyncModeFlag, - }, utils.DatabaseFlags), - Description: ` -Requires a first argument of the file to write to. -Optional second and third arguments control the first and -last block to write. In this mode, the file will be appended -if already existing. If the file ends with .gz, the output will -be gzipped.`, - } - importHistoryCommand = &cli.Command{ - Action: importHistory, - Name: "import-history", - Usage: "Import an Era archive", - ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ - utils.TxLookupLimitFlag, - }, - utils.DatabaseFlags, - utils.NetworkFlags, - ), - Description: ` -The import-history command will import blocks and their corresponding receipts -from Era archives. -`, - } - exportHistoryCommand = &cli.Command{ - Action: exportHistory, - Name: "export-history", - Usage: "Export blockchain history to Era archives", - ArgsUsage: " ", - Flags: flags.Merge(utils.DatabaseFlags), - Description: ` -The export-history command will export blocks and their corresponding receipts -into Era archives. Eras are typically packaged in steps of 8192 blocks. -`, - } - importPreimagesCommand = &cli.Command{ - Action: importPreimages, - Name: "import-preimages", - Usage: "Import the preimage database from an RLP stream", - ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ - utils.CacheFlag, - utils.SyncModeFlag, - }, utils.DatabaseFlags), - Description: ` -The import-preimages command imports hash preimages from an RLP encoded stream. -It's deprecated, please use "geth db import" instead. -`, - } - - dumpCommand = &cli.Command{ - Action: dump, - Name: "dump", - Usage: "Dump a specific block from storage", - ArgsUsage: "[? | ]", - Flags: flags.Merge([]cli.Flag{ - utils.CacheFlag, - utils.IterativeOutputFlag, - utils.ExcludeCodeFlag, - utils.ExcludeStorageFlag, - utils.IncludeIncompletesFlag, - utils.StartKeyFlag, - utils.DumpLimitFlag, - }, utils.DatabaseFlags), - Description: ` -This command dumps out the state for a given block (or latest, if none provided). -`, - } -) - -// initGenesis will initialise the given JSON format genesis file and writes it as -// the zero'd block (i.e. genesis) or will fail hard if it can't succeed. -func initGenesis(ctx *cli.Context) error { - if ctx.Args().Len() != 1 { - utils.Fatalf("need genesis.json file as the only argument") - } - genesisPath := ctx.Args().First() - if len(genesisPath) == 0 { - utils.Fatalf("invalid path to genesis file") - } - file, err := os.Open(genesisPath) - if err != nil { - utils.Fatalf("Failed to read genesis file: %v", err) - } - defer file.Close() - - genesis := new(core.Genesis) - if err := json.NewDecoder(file).Decode(genesis); err != nil { - utils.Fatalf("invalid genesis file: %v", err) - } - // Open and initialise both full and light databases - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - var overrides core.ChainOverrides - if ctx.IsSet(utils.OverrideCancun.Name) { - v := ctx.Uint64(utils.OverrideCancun.Name) - overrides.OverrideCancun = &v - } - if ctx.IsSet(utils.OverrideVerkle.Name) { - v := ctx.Uint64(utils.OverrideVerkle.Name) - overrides.OverrideVerkle = &v - } - for _, name := range []string{"chaindata", "lightchaindata"} { - chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false) - if err != nil { - utils.Fatalf("Failed to open database: %v", err) - } - defer chaindb.Close() - - triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle()) - defer triedb.Close() - - _, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides) - if err != nil { - utils.Fatalf("Failed to write genesis block: %v", err) - } - log.Info("Successfully wrote genesis state", "database", name, "hash", hash) - } - return nil -} - -func dumpGenesis(ctx *cli.Context) error { - // check if there is a testnet preset enabled - var genesis *core.Genesis - if utils.IsNetworkPreset(ctx) { - genesis = utils.MakeGenesis(ctx) - } else if ctx.IsSet(utils.DeveloperFlag.Name) && !ctx.IsSet(utils.DataDirFlag.Name) { - genesis = core.DeveloperGenesisBlock(11_500_000, nil) - } - - if genesis != nil { - if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil { - utils.Fatalf("could not encode genesis: %s", err) - } - return nil - } - - // dump whatever already exists in the datadir - stack, _ := makeConfigNode(ctx) - for _, name := range []string{"chaindata", "lightchaindata"} { - db, err := stack.OpenDatabase(name, 0, 0, "", true) - if err != nil { - if !os.IsNotExist(err) { - return err - } - continue - } - genesis, err := core.ReadGenesis(db) - if err != nil { - utils.Fatalf("failed to read genesis: %s", err) - } - db.Close() - - if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil { - utils.Fatalf("could not encode stored genesis: %s", err) - } - return nil - } - if ctx.IsSet(utils.DataDirFlag.Name) { - utils.Fatalf("no existing datadir at %s", stack.Config().DataDir) - } - utils.Fatalf("no network preset provided, and no genesis exists in the default datadir") - return nil -} - -func importChain(ctx *cli.Context) error { - if ctx.Args().Len() < 1 { - utils.Fatalf("This command requires an argument.") - } - // Start metrics export if enabled - utils.SetupMetrics(ctx) - // Start system runtime metrics collection - go metrics.CollectProcessMetrics(3 * time.Second) - - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chain, db := utils.MakeChain(ctx, stack, false) - defer db.Close() - - // Start periodically gathering memory profiles - var peakMemAlloc, peakMemSys atomic.Uint64 - go func() { - stats := new(runtime.MemStats) - for { - runtime.ReadMemStats(stats) - if peakMemAlloc.Load() < stats.Alloc { - peakMemAlloc.Store(stats.Alloc) - } - if peakMemSys.Load() < stats.Sys { - peakMemSys.Store(stats.Sys) - } - time.Sleep(5 * time.Second) - } - }() - // Import the chain - start := time.Now() - - var importErr error - - if ctx.Args().Len() == 1 { - if err := utils.ImportChain(chain, ctx.Args().First()); err != nil { - importErr = err - log.Error("Import error", "err", err) - } - } else { - for _, arg := range ctx.Args().Slice() { - if err := utils.ImportChain(chain, arg); err != nil { - importErr = err - log.Error("Import error", "file", arg, "err", err) - } - } - } - chain.Stop() - fmt.Printf("Import done in %v.\n\n", time.Since(start)) - - // Output pre-compaction stats mostly to see the import trashing - showLeveldbStats(db) - - // Print the memory statistics used by the importing - mem := new(runtime.MemStats) - runtime.ReadMemStats(mem) - - fmt.Printf("Object memory: %.3f MB current, %.3f MB peak\n", float64(mem.Alloc)/1024/1024, float64(peakMemAlloc.Load())/1024/1024) - fmt.Printf("System memory: %.3f MB current, %.3f MB peak\n", float64(mem.Sys)/1024/1024, float64(peakMemSys.Load())/1024/1024) - fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000) - fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs)) - - if ctx.Bool(utils.NoCompactionFlag.Name) { - return nil - } - - // Compact the entire database to more accurately measure disk io and print the stats - start = time.Now() - fmt.Println("Compacting entire database...") - if err := db.Compact(nil, nil); err != nil { - utils.Fatalf("Compaction failed: %v", err) - } - fmt.Printf("Compaction done in %v.\n\n", time.Since(start)) - - showLeveldbStats(db) - return importErr -} - -func exportChain(ctx *cli.Context) error { - if ctx.Args().Len() < 1 { - utils.Fatalf("This command requires an argument.") - } - - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chain, db := utils.MakeChain(ctx, stack, true) - defer db.Close() - start := time.Now() - - var err error - fp := ctx.Args().First() - if ctx.Args().Len() < 3 { - err = utils.ExportChain(chain, fp) - } else { - // This can be improved to allow for numbers larger than 9223372036854775807 - first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64) - last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64) - if ferr != nil || lerr != nil { - utils.Fatalf("Export error in parsing parameters: block number not an integer\n") - } - if first < 0 || last < 0 { - utils.Fatalf("Export error: block number must be greater than 0\n") - } - if head := chain.CurrentSnapBlock(); uint64(last) > head.Number.Uint64() { - utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.Number.Uint64()) - } - err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last)) - } - if err != nil { - utils.Fatalf("Export error: %v\n", err) - } - fmt.Printf("Export done in %v\n", time.Since(start)) - return nil -} - -func importHistory(ctx *cli.Context) error { - if ctx.Args().Len() != 1 { - utils.Fatalf("usage: %s", ctx.Command.ArgsUsage) - } - - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chain, db := utils.MakeChain(ctx, stack, false) - defer db.Close() - - var ( - start = time.Now() - dir = ctx.Args().Get(0) - network string - ) - - // Determine network. - if utils.IsNetworkPreset(ctx) { - switch { - case ctx.Bool(utils.MainnetFlag.Name): - network = "mainnet" - case ctx.Bool(utils.SepoliaFlag.Name): - network = "sepolia" - case ctx.Bool(utils.GoerliFlag.Name): - network = "goerli" - } - } else { - // No network flag set, try to determine network based on files - // present in directory. - var networks []string - for _, n := range params.NetworkNames { - entries, err := era.ReadDir(dir, n) - if err != nil { - return fmt.Errorf("error reading %s: %w", dir, err) - } - if len(entries) > 0 { - networks = append(networks, n) - } - } - if len(networks) == 0 { - return fmt.Errorf("no era1 files found in %s", dir) - } - if len(networks) > 1 { - return fmt.Errorf("multiple networks found, use a network flag to specify desired network") - } - network = networks[0] - } - - if err := utils.ImportHistory(chain, db, dir, network); err != nil { - return err - } - fmt.Printf("Import done in %v\n", time.Since(start)) - return nil -} - -// exportHistory exports chain history in Era archives at a specified -// directory. -func exportHistory(ctx *cli.Context) error { - if ctx.Args().Len() != 3 { - utils.Fatalf("usage: %s", ctx.Command.ArgsUsage) - } - - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chain, _ := utils.MakeChain(ctx, stack, true) - start := time.Now() - - var ( - dir = ctx.Args().Get(0) - first, ferr = strconv.ParseInt(ctx.Args().Get(1), 10, 64) - last, lerr = strconv.ParseInt(ctx.Args().Get(2), 10, 64) - ) - if ferr != nil || lerr != nil { - utils.Fatalf("Export error in parsing parameters: block number not an integer\n") - } - if first < 0 || last < 0 { - utils.Fatalf("Export error: block number must be greater than 0\n") - } - if head := chain.CurrentSnapBlock(); uint64(last) > head.Number.Uint64() { - utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.Number.Uint64()) - } - err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxEra1Size)) - if err != nil { - utils.Fatalf("Export error: %v\n", err) - } - fmt.Printf("Export done in %v\n", time.Since(start)) - return nil -} - -// importPreimages imports preimage data from the specified file. -// it is deprecated, and the export function has been removed, but -// the import function is kept around for the time being so that -// older file formats can still be imported. -func importPreimages(ctx *cli.Context) error { - if ctx.Args().Len() < 1 { - utils.Fatalf("This command requires an argument.") - } - - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, false) - defer db.Close() - start := time.Now() - - if err := utils.ImportPreimages(db, ctx.Args().First()); err != nil { - utils.Fatalf("Import error: %v\n", err) - } - fmt.Printf("Import done in %v\n", time.Since(start)) - return nil -} - -func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, ethdb.Database, common.Hash, error) { - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - var header *types.Header - if ctx.NArg() > 1 { - return nil, nil, common.Hash{}, fmt.Errorf("expected 1 argument (number or hash), got %d", ctx.NArg()) - } - if ctx.NArg() == 1 { - arg := ctx.Args().First() - if hashish(arg) { - hash := common.HexToHash(arg) - if number := rawdb.ReadHeaderNumber(db, hash); number != nil { - header = rawdb.ReadHeader(db, hash, *number) - } else { - return nil, nil, common.Hash{}, fmt.Errorf("block %x not found", hash) - } - } else { - number, err := strconv.ParseUint(arg, 10, 64) - if err != nil { - return nil, nil, common.Hash{}, err - } - if hash := rawdb.ReadCanonicalHash(db, number); hash != (common.Hash{}) { - header = rawdb.ReadHeader(db, hash, number) - } else { - return nil, nil, common.Hash{}, fmt.Errorf("header for block %d not found", number) - } - } - } else { - // Use latest - header = rawdb.ReadHeadHeader(db) - } - if header == nil { - return nil, nil, common.Hash{}, errors.New("no head block found") - } - startArg := common.FromHex(ctx.String(utils.StartKeyFlag.Name)) - var start common.Hash - switch len(startArg) { - case 0: // common.Hash - case 32: - start = common.BytesToHash(startArg) - case 20: - start = crypto.Keccak256Hash(startArg) - log.Info("Converting start-address to hash", "address", common.BytesToAddress(startArg), "hash", start.Hex()) - default: - return nil, nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg) - } - var conf = &state.DumpConfig{ - SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name), - SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name), - OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name), - Start: start.Bytes(), - Max: ctx.Uint64(utils.DumpLimitFlag.Name), - } - log.Info("State dump configured", "block", header.Number, "hash", header.Hash().Hex(), - "skipcode", conf.SkipCode, "skipstorage", conf.SkipStorage, - "start", hexutil.Encode(conf.Start), "limit", conf.Max) - return conf, db, header.Root, nil -} - -func dump(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - conf, db, root, err := parseDumpConfig(ctx, stack) - if err != nil { - return err - } - triedb := utils.MakeTrieDatabase(ctx, db, true, true, false) // always enable preimage lookup - defer triedb.Close() - - state, err := state.New(root, state.NewDatabaseWithNodeDB(db, triedb), nil) - if err != nil { - return err - } - if ctx.Bool(utils.IterativeOutputFlag.Name) { - state.IterativeDump(conf, json.NewEncoder(os.Stdout)) - } else { - fmt.Println(string(state.Dump(conf))) - } - return nil -} - -// hashish returns true for strings that look like hashes. -func hashish(x string) bool { - _, err := strconv.Atoi(x) - return err != nil -} diff --git a/builder/cmd/geth/config.go b/builder/cmd/geth/config.go deleted file mode 100644 index 9dd0f7cdf..000000000 --- a/builder/cmd/geth/config.go +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bufio" - "errors" - "fmt" - "os" - "reflect" - "runtime" - "strings" - "unicode" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/external" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/accounts/scwallet" - "github.com/ethereum/go-ethereum/accounts/usbwallet" - "github.com/ethereum/go-ethereum/builder" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - blockvalidationapi "github.com/ethereum/go-ethereum/eth/block-validation" - "github.com/ethereum/go-ethereum/eth/catalyst" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/internal/version" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/naoina/toml" - "github.com/urfave/cli/v2" -) - -var ( - dumpConfigCommand = &cli.Command{ - Action: dumpConfig, - Name: "dumpconfig", - Usage: "Export configuration values in a TOML format", - ArgsUsage: "", - Flags: flags.Merge(nodeFlags, rpcFlags), - Description: `Export configuration values in TOML format (to stdout by default).`, - } - - configFileFlag = &cli.StringFlag{ - Name: "config", - Usage: "TOML configuration file", - Category: flags.EthCategory, - } -) - -// These settings ensure that TOML keys use the same names as Go struct fields. -var tomlSettings = toml.Config{ - NormFieldName: func(rt reflect.Type, key string) string { - return key - }, - FieldToKey: func(rt reflect.Type, field string) string { - return field - }, - MissingField: func(rt reflect.Type, field string) error { - id := fmt.Sprintf("%s.%s", rt.String(), field) - if deprecated(id) { - log.Warn("Config field is deprecated and won't have an effect", "name", id) - return nil - } - var link string - if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" { - link = fmt.Sprintf(", see https://godoc.org/%s#%s for available fields", rt.PkgPath(), rt.Name()) - } - return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link) - }, -} - -type ethstatsConfig struct { - URL string `toml:",omitempty"` -} - -type gethConfig struct { - Eth ethconfig.Config - Node node.Config - Ethstats ethstatsConfig - Metrics metrics.Config - Builder builder.Config -} - -func loadConfig(file string, cfg *gethConfig) error { - f, err := os.Open(file) - if err != nil { - return err - } - defer f.Close() - - err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg) - // Add file name to errors that have a line number. - if _, ok := err.(*toml.LineError); ok { - err = errors.New(file + ", " + err.Error()) - } - return err -} - -func defaultNodeConfig() node.Config { - git, _ := version.VCS() - cfg := node.DefaultConfig - cfg.Name = clientIdentifier - cfg.Version = params.VersionWithCommit(git.Commit, git.Date) - cfg.HTTPModules = append(cfg.HTTPModules, "eth") - cfg.WSModules = append(cfg.WSModules, "eth") - cfg.IPCPath = "geth.ipc" - return cfg -} - -// loadBaseConfig loads the gethConfig based on the given command line -// parameters and config file. -func loadBaseConfig(ctx *cli.Context) gethConfig { - // Load defaults. - cfg := gethConfig{ - Eth: ethconfig.Defaults, - Node: defaultNodeConfig(), - Metrics: metrics.DefaultConfig, - Builder: builder.DefaultConfig, - } - - // Load config file. - if file := ctx.String(configFileFlag.Name); file != "" { - if err := loadConfig(file, &cfg); err != nil { - utils.Fatalf("%v", err) - } - } - - // Apply flags. - utils.SetNodeConfig(ctx, &cfg.Node) - return cfg -} - -// makeConfigNode loads geth configuration and creates a blank node instance. -func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { - cfg := loadBaseConfig(ctx) - stack, err := node.New(&cfg.Node) - if err != nil { - utils.Fatalf("Failed to create the protocol stack: %v", err) - } - // Node doesn't by default populate account manager backends - if err := setAccountManagerBackends(stack.Config(), stack.AccountManager(), stack.KeyStoreDir()); err != nil { - utils.Fatalf("Failed to set account manager backends: %v", err) - } - - utils.SetEthConfig(ctx, stack, &cfg.Eth) - if ctx.IsSet(utils.EthStatsURLFlag.Name) { - cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name) - } - applyMetricConfig(ctx, &cfg) - - // Apply builder flags - utils.SetBuilderConfig(ctx, &cfg.Builder) - - return stack, cfg -} - -// makeFullNode loads geth configuration and creates the Ethereum backend. -func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { - stack, cfg := makeConfigNode(ctx) - if ctx.IsSet(utils.OverrideCancun.Name) { - v := ctx.Uint64(utils.OverrideCancun.Name) - cfg.Eth.OverrideCancun = &v - } - if ctx.IsSet(utils.OverrideVerkle.Name) { - v := ctx.Uint64(utils.OverrideVerkle.Name) - cfg.Eth.OverrideVerkle = &v - } - backend, eth := utils.RegisterEthService(stack, &cfg.Eth, &cfg.Builder) - - // Create gauge with geth system and build information - if eth != nil { // The 'eth' backend may be nil in light mode - var protos []string - for _, p := range eth.Protocols() { - protos = append(protos, fmt.Sprintf("%v/%d", p.Name, p.Version)) - } - metrics.NewRegisteredGaugeInfo("geth/info", nil).Update(metrics.GaugeInfoValue{ - "arch": runtime.GOARCH, - "os": runtime.GOOS, - "version": cfg.Node.Version, - "protocols": strings.Join(protos, ","), - }) - } - - // Configure log filter RPC API. - filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth) - - bvConfig := blockvalidationapi.BlockValidationConfig{} - if ctx.IsSet(utils.BuilderBlockValidationBlacklistSourceFilePath.Name) { - bvConfig.BlacklistSourceFilePath = ctx.String(utils.BuilderBlockValidationBlacklistSourceFilePath.Name) - } - if ctx.IsSet(utils.BuilderBlockValidationUseBalanceDiff.Name) { - bvConfig.UseBalanceDiffProfit = ctx.Bool(utils.BuilderBlockValidationUseBalanceDiff.Name) - } - if ctx.IsSet(utils.BuilderBlockValidationExcludeWithdrawals.Name) { - bvConfig.ExcludeWithdrawals = ctx.Bool(utils.BuilderBlockValidationExcludeWithdrawals.Name) - } - - if err := blockvalidationapi.Register(stack, eth, bvConfig); err != nil { - utils.Fatalf("Failed to register the Block Validation API: %v", err) - } - - // Configure GraphQL if requested - if ctx.IsSet(utils.GraphQLEnabledFlag.Name) { - utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node) - } - // Add the Ethereum Stats daemon if requested. - if cfg.Ethstats.URL != "" { - utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL) - } - // Configure full-sync tester service if requested - if ctx.IsSet(utils.SyncTargetFlag.Name) { - hex := hexutil.MustDecode(ctx.String(utils.SyncTargetFlag.Name)) - if len(hex) != common.HashLength { - utils.Fatalf("invalid sync target length: have %d, want %d", len(hex), common.HashLength) - } - utils.RegisterFullSyncTester(stack, eth, common.BytesToHash(hex)) - } - // Start the dev mode if requested, or launch the engine API for - // interacting with external consensus client. - if ctx.IsSet(utils.DeveloperFlag.Name) { - simBeacon, err := catalyst.NewSimulatedBeacon(ctx.Uint64(utils.DeveloperPeriodFlag.Name), eth) - if err != nil { - utils.Fatalf("failed to register dev mode catalyst service: %v", err) - } - catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon) - stack.RegisterLifecycle(simBeacon) - } else { - err := catalyst.Register(stack, eth) - if err != nil { - utils.Fatalf("failed to register catalyst service: %v", err) - } - } - return stack, backend -} - -// dumpConfig is the dumpconfig command. -func dumpConfig(ctx *cli.Context) error { - _, cfg := makeConfigNode(ctx) - comment := "" - - if cfg.Eth.Genesis != nil { - cfg.Eth.Genesis = nil - comment += "# Note: this config doesn't contain the genesis block.\n\n" - } - - out, err := tomlSettings.Marshal(&cfg) - if err != nil { - return err - } - - dump := os.Stdout - if ctx.NArg() > 0 { - dump, err = os.OpenFile(ctx.Args().Get(0), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - defer dump.Close() - } - dump.WriteString(comment) - dump.Write(out) - - return nil -} - -func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) { - if ctx.IsSet(utils.MetricsEnabledFlag.Name) { - cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name) - } - if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) { - cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name) - } - if ctx.IsSet(utils.MetricsEnabledBuilderFlag.Name) { - cfg.Metrics.EnabledBuilder = ctx.Bool(utils.MetricsEnabledBuilderFlag.Name) - } - if ctx.IsSet(utils.MetricsHTTPFlag.Name) { - cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name) - } - if ctx.IsSet(utils.MetricsPortFlag.Name) { - cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name) - } - if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) { - cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) { - cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) { - cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) { - cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) { - cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) { - cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name) - } - if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) { - cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) { - cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) { - cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name) - } - if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) { - cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name) - } -} - -func deprecated(field string) bool { - switch field { - case "ethconfig.Config.EVMInterpreter": - return true - case "ethconfig.Config.EWASMInterpreter": - return true - case "ethconfig.Config.TrieCleanCacheJournal": - return true - case "ethconfig.Config.TrieCleanCacheRejournal": - return true - default: - return false - } -} - -func setAccountManagerBackends(conf *node.Config, am *accounts.Manager, keydir string) error { - scryptN := keystore.StandardScryptN - scryptP := keystore.StandardScryptP - if conf.UseLightweightKDF { - scryptN = keystore.LightScryptN - scryptP = keystore.LightScryptP - } - - // Assemble the supported backends - if len(conf.ExternalSigner) > 0 { - log.Info("Using external signer", "url", conf.ExternalSigner) - if extBackend, err := external.NewExternalBackend(conf.ExternalSigner); err == nil { - am.AddBackend(extBackend) - return nil - } else { - return fmt.Errorf("error connecting to external signer: %v", err) - } - } - - // For now, we're using EITHER external signer OR local signers. - // If/when we implement some form of lockfile for USB and keystore wallets, - // we can have both, but it's very confusing for the user to see the same - // accounts in both externally and locally, plus very racey. - am.AddBackend(keystore.NewKeyStore(keydir, scryptN, scryptP)) - if conf.USB { - // Start a USB hub for Ledger hardware wallets - if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil { - log.Warn(fmt.Sprintf("Failed to start Ledger hub, disabling: %v", err)) - } else { - am.AddBackend(ledgerhub) - } - // Start a USB hub for Trezor hardware wallets (HID version) - if trezorhub, err := usbwallet.NewTrezorHubWithHID(); err != nil { - log.Warn(fmt.Sprintf("Failed to start HID Trezor hub, disabling: %v", err)) - } else { - am.AddBackend(trezorhub) - } - // Start a USB hub for Trezor hardware wallets (WebUSB version) - if trezorhub, err := usbwallet.NewTrezorHubWithWebUSB(); err != nil { - log.Warn(fmt.Sprintf("Failed to start WebUSB Trezor hub, disabling: %v", err)) - } else { - am.AddBackend(trezorhub) - } - } - if len(conf.SmartCardDaemonPath) > 0 { - // Start a smart card hub - if schub, err := scwallet.NewHub(conf.SmartCardDaemonPath, scwallet.Scheme, keydir); err != nil { - log.Warn(fmt.Sprintf("Failed to start smart card hub, disabling: %v", err)) - } else { - am.AddBackend(schub) - } - } - - return nil -} diff --git a/builder/cmd/geth/consolecmd.go b/builder/cmd/geth/consolecmd.go deleted file mode 100644 index 526ede961..000000000 --- a/builder/cmd/geth/consolecmd.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/console" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/urfave/cli/v2" -) - -var ( - consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag} - - consoleCommand = &cli.Command{ - Action: localConsole, - Name: "console", - Usage: "Start an interactive JavaScript environment", - Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags), - Description: ` -The Geth console is an interactive shell for the JavaScript runtime environment -which exposes a node admin interface as well as the Ãapp JavaScript API. -See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`, - } - - attachCommand = &cli.Command{ - Action: remoteConsole, - Name: "attach", - Usage: "Start an interactive JavaScript environment (connect to node)", - ArgsUsage: "[endpoint]", - Flags: flags.Merge([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags), - Description: ` -The Geth console is an interactive shell for the JavaScript runtime environment -which exposes a node admin interface as well as the Ãapp JavaScript API. -See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console. -This command allows to open a console on a running geth node.`, - } - - javascriptCommand = &cli.Command{ - Action: ephemeralConsole, - Name: "js", - Usage: "(DEPRECATED) Execute the specified JavaScript files", - ArgsUsage: " [jsfile...]", - Flags: flags.Merge(nodeFlags, consoleFlags), - Description: ` -The JavaScript VM exposes a node admin interface as well as the Ãapp -JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`, - } -) - -// localConsole starts a new geth node, attaching a JavaScript console to it at the -// same time. -func localConsole(ctx *cli.Context) error { - // Create and start the node based on the CLI flags - prepare(ctx) - stack, backend := makeFullNode(ctx) - startNode(ctx, stack, backend, true) - defer stack.Close() - - // Attach to the newly started node and create the JavaScript console. - client := stack.Attach() - config := console.Config{ - DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.String(utils.JSpathFlag.Name), - Client: client, - Preload: utils.MakeConsolePreloads(ctx), - } - console, err := console.New(config) - if err != nil { - return fmt.Errorf("failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - // If only a short execution was requested, evaluate and return. - if script := ctx.String(utils.ExecFlag.Name); script != "" { - console.Evaluate(script) - return nil - } - - // Track node shutdown and stop the console when it goes down. - // This happens when SIGTERM is sent to the process. - go func() { - stack.Wait() - console.StopInteractive() - }() - - // Print the welcome screen and enter interactive mode. - console.Welcome() - console.Interactive() - return nil -} - -// remoteConsole will connect to a remote geth instance, attaching a JavaScript -// console to it. -func remoteConsole(ctx *cli.Context) error { - if ctx.Args().Len() > 1 { - utils.Fatalf("invalid command-line: too many arguments") - } - endpoint := ctx.Args().First() - if endpoint == "" { - cfg := defaultNodeConfig() - utils.SetDataDir(ctx, &cfg) - endpoint = cfg.IPCEndpoint() - } - client, err := utils.DialRPCWithHeaders(endpoint, ctx.StringSlice(utils.HttpHeaderFlag.Name)) - if err != nil { - utils.Fatalf("Unable to attach to remote geth: %v", err) - } - config := console.Config{ - DataDir: utils.MakeDataDir(ctx), - DocRoot: ctx.String(utils.JSpathFlag.Name), - Client: client, - Preload: utils.MakeConsolePreloads(ctx), - } - console, err := console.New(config) - if err != nil { - utils.Fatalf("Failed to start the JavaScript console: %v", err) - } - defer console.Stop(false) - - if script := ctx.String(utils.ExecFlag.Name); script != "" { - console.Evaluate(script) - return nil - } - - // Otherwise print the welcome screen and enter interactive mode - console.Welcome() - console.Interactive() - return nil -} - -// ephemeralConsole starts a new geth node, attaches an ephemeral JavaScript -// console to it, executes each of the files specified as arguments and tears -// everything down. -func ephemeralConsole(ctx *cli.Context) error { - var b strings.Builder - for _, file := range ctx.Args().Slice() { - b.Write([]byte(fmt.Sprintf("loadScript('%s');", file))) - } - utils.Fatalf(`The "js" command is deprecated. Please use the following instead: -geth --exec "%s" console`, b.String()) - return nil -} diff --git a/builder/cmd/geth/consolecmd_test.go b/builder/cmd/geth/consolecmd_test.go deleted file mode 100644 index 175879dd9..000000000 --- a/builder/cmd/geth/consolecmd_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "crypto/rand" - "math/big" - "path/filepath" - "runtime" - "strconv" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/params" -) - -const ( - ipcAPIs = "admin:1.0 clique:1.0 debug:1.0 engine:1.0 eth:1.0 flashbots:1.0 mev:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0" - httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0" -) - -// spawns geth with the given command line args, using a set of flags to minimise -// memory and disk IO. If the args don't set --datadir, the -// child g gets a temporary data directory. -func runMinimalGeth(t *testing.T, args ...string) *testgeth { - // --goerli to make the 'writing genesis to disk' faster (no accounts) - // --networkid=1337 to avoid cache bump - // --syncmode=full to avoid allocating fast sync bloom - allArgs := []string{"--goerli", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0", - "--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64", - "--datadir.minfreedisk", "0"} - return runGeth(t, append(allArgs, args...)...) -} - -// Tests that a node embedded within a console can be started up properly and -// then terminated by closing the input stream. -func TestConsoleWelcome(t *testing.T) { - t.Parallel() - coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" - - // Start a geth console, make sure it's cleaned up and terminate the console - geth := runMinimalGeth(t, "--miner.etherbase", coinbase, "console") - - // Gather all the infos the welcome message needs to contain - geth.SetTemplateFunc("goos", func() string { return runtime.GOOS }) - geth.SetTemplateFunc("goarch", func() string { return runtime.GOARCH }) - geth.SetTemplateFunc("gover", runtime.Version) - geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") }) - geth.SetTemplateFunc("niltime", func() string { - return time.Unix(1548854791, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)") - }) - geth.SetTemplateFunc("apis", func() string { return ipcAPIs }) - - // Verify the actual welcome message to the required template - geth.Expect(` -Welcome to the Geth JavaScript console! - -instance: Geth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}} -coinbase: {{.Etherbase}} -at block: 0 ({{niltime}}) - datadir: {{.Datadir}} - modules: {{apis}} - -To exit, press ctrl-d or type exit -> {{.InputLine "exit"}} -`) - geth.ExpectExit() -} - -// Tests that a console can be attached to a running node via various means. -func TestAttachWelcome(t *testing.T) { - var ( - ipc string - httpPort string - wsPort string - ) - // Configure the instance for IPC attachment - if runtime.GOOS == "windows" { - ipc = `\\.\pipe\geth` + strconv.Itoa(trulyRandInt(100000, 999999)) - } else { - ipc = filepath.Join(t.TempDir(), "geth.ipc") - } - // And HTTP + WS attachment - p := trulyRandInt(1024, 65533) // Yeah, sometimes this will fail, sorry :P - httpPort = strconv.Itoa(p) - wsPort = strconv.Itoa(p + 1) - geth := runMinimalGeth(t, "--miner.etherbase", "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182", - "--ipcpath", ipc, - "--http", "--http.port", httpPort, - "--ws", "--ws.port", wsPort) - t.Run("ipc", func(t *testing.T) { - waitForEndpoint(t, ipc, 3*time.Second) - testAttachWelcome(t, geth, "ipc:"+ipc, ipcAPIs) - }) - t.Run("http", func(t *testing.T) { - endpoint := "http://127.0.0.1:" + httpPort - waitForEndpoint(t, endpoint, 3*time.Second) - testAttachWelcome(t, geth, endpoint, httpAPIs) - }) - t.Run("ws", func(t *testing.T) { - endpoint := "ws://127.0.0.1:" + wsPort - waitForEndpoint(t, endpoint, 3*time.Second) - testAttachWelcome(t, geth, endpoint, httpAPIs) - }) - geth.Kill() -} - -func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) { - // Attach to a running geth node and terminate immediately - attach := runGeth(t, "attach", endpoint) - defer attach.ExpectExit() - attach.CloseStdin() - - // Gather all the infos the welcome message needs to contain - attach.SetTemplateFunc("goos", func() string { return runtime.GOOS }) - attach.SetTemplateFunc("goarch", func() string { return runtime.GOARCH }) - attach.SetTemplateFunc("gover", runtime.Version) - attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") }) - attach.SetTemplateFunc("etherbase", func() string { return geth.Etherbase }) - attach.SetTemplateFunc("niltime", func() string { - return time.Unix(1548854791, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)") - }) - attach.SetTemplateFunc("ipc", func() bool { return strings.HasPrefix(endpoint, "ipc") }) - attach.SetTemplateFunc("datadir", func() string { return geth.Datadir }) - attach.SetTemplateFunc("apis", func() string { return apis }) - - // Verify the actual welcome message to the required template - attach.Expect(` -Welcome to the Geth JavaScript console! - -instance: Geth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}} -coinbase: {{etherbase}} -at block: 0 ({{niltime}}){{if ipc}} - datadir: {{datadir}}{{end}} - modules: {{apis}} - -To exit, press ctrl-d or type exit -> {{.InputLine "exit" }} -`) - attach.ExpectExit() -} - -// trulyRandInt generates a crypto random integer used by the console tests to -// not clash network ports with other tests running concurrently. -func trulyRandInt(lo, hi int) int { - num, _ := rand.Int(rand.Reader, big.NewInt(int64(hi-lo))) - return int(num.Int64()) + lo -} diff --git a/builder/cmd/geth/dbcmd.go b/builder/cmd/geth/dbcmd.go deleted file mode 100644 index 1d885bd58..000000000 --- a/builder/cmd/geth/dbcmd.go +++ /dev/null @@ -1,761 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "fmt" - "os" - "os/signal" - "path/filepath" - "strconv" - "strings" - "syscall" - "time" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" - "github.com/olekukonko/tablewriter" - "github.com/urfave/cli/v2" -) - -var ( - removeStateDataFlag = &cli.BoolFlag{ - Name: "remove.state", - Usage: "If set, selects the state data for removal", - } - removeChainDataFlag = &cli.BoolFlag{ - Name: "remove.chain", - Usage: "If set, selects the state data for removal", - } - - removedbCommand = &cli.Command{ - Action: removeDB, - Name: "removedb", - Usage: "Remove blockchain and state databases", - ArgsUsage: "", - Flags: flags.Merge(utils.DatabaseFlags, - []cli.Flag{removeStateDataFlag, removeChainDataFlag}), - Description: ` -Remove blockchain and state databases`, - } - dbCommand = &cli.Command{ - Name: "db", - Usage: "Low level database operations", - ArgsUsage: "", - Subcommands: []*cli.Command{ - dbInspectCmd, - dbStatCmd, - dbCompactCmd, - dbGetCmd, - dbDeleteCmd, - dbPutCmd, - dbGetSlotsCmd, - dbDumpFreezerIndex, - dbImportCmd, - dbExportCmd, - dbMetadataCmd, - dbCheckStateContentCmd, - }, - } - dbInspectCmd = &cli.Command{ - Action: inspect, - Name: "inspect", - ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Usage: "Inspect the storage size for each type of data in the database", - Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`, - } - dbCheckStateContentCmd = &cli.Command{ - Action: checkStateContent, - Name: "check-state-content", - ArgsUsage: "", - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Usage: "Verify that state data is cryptographically correct", - Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes. -For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates -a data corruption.`, - } - dbStatCmd = &cli.Command{ - Action: dbStats, - Name: "stats", - Usage: "Print leveldb statistics", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - } - dbCompactCmd = &cli.Command{ - Action: dbCompact, - Name: "compact", - Usage: "Compact leveldb database. WARNING: May take a very long time", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - utils.CacheFlag, - utils.CacheDatabaseFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: `This command performs a database compaction. -WARNING: This operation may take a very long time to finish, and may cause database -corruption if it is aborted during execution'!`, - } - dbGetCmd = &cli.Command{ - Action: dbGet, - Name: "get", - Usage: "Show the value of a database key", - ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: "This command looks up the specified database key from the database.", - } - dbDeleteCmd = &cli.Command{ - Action: dbDelete, - Name: "delete", - Usage: "Delete a database key (WARNING: may corrupt your database)", - ArgsUsage: "", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: `This command deletes the specified database key from the database. -WARNING: This is a low-level operation which may cause database corruption!`, - } - dbPutCmd = &cli.Command{ - Action: dbPut, - Name: "put", - Usage: "Set the value of a database key (WARNING: may corrupt your database)", - ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: `This command sets a given database key to the given value. -WARNING: This is a low-level operation which may cause database corruption!`, - } - dbGetSlotsCmd = &cli.Command{ - Action: dbDumpTrie, - Name: "dumptrie", - Usage: "Show the storage key/values of a given storage trie", - ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: "This command looks up the specified database key from the database.", - } - dbDumpFreezerIndex = &cli.Command{ - Action: freezerInspect, - Name: "freezer-index", - Usage: "Dump out the index of a specific freezer table", - ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: "This command displays information about the freezer index.", - } - dbImportCmd = &cli.Command{ - Action: importLDBdata, - Name: "import", - Usage: "Imports leveldb-data from an exported RLP dump.", - ArgsUsage: " has .gz suffix, gzip compression will be used.", - ArgsUsage: " ", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", - } - dbMetadataCmd = &cli.Command{ - Action: showMetaData, - Name: "metadata", - Usage: "Shows metadata about the chain status.", - Flags: flags.Merge([]cli.Flag{ - utils.SyncModeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: "Shows metadata about the chain status.", - } -) - -func removeDB(ctx *cli.Context) error { - stack, config := makeConfigNode(ctx) - - // Resolve folder paths. - var ( - rootDir = stack.ResolvePath("chaindata") - ancientDir = config.Eth.DatabaseFreezer - ) - switch { - case ancientDir == "": - ancientDir = filepath.Join(stack.ResolvePath("chaindata"), "ancient") - case !filepath.IsAbs(ancientDir): - ancientDir = config.Node.ResolvePath(ancientDir) - } - // Delete state data - statePaths := []string{rootDir, filepath.Join(ancientDir, rawdb.StateFreezerName)} - confirmAndRemoveDB(statePaths, "state data", ctx, removeStateDataFlag.Name) - - // Delete ancient chain - chainPaths := []string{filepath.Join(ancientDir, rawdb.ChainFreezerName)} - confirmAndRemoveDB(chainPaths, "ancient chain", ctx, removeChainDataFlag.Name) - return nil -} - -// removeFolder deletes all files (not folders) inside the directory 'dir' (but -// not files in subfolders). -func removeFolder(dir string) { - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - // If we're at the top level folder, recurse into - if path == dir { - return nil - } - // Delete all the files, but not subfolders - if !info.IsDir() { - os.Remove(path) - return nil - } - return filepath.SkipDir - }) -} - -// confirmAndRemoveDB prompts the user for a last confirmation and removes the -// list of folders if accepted. -func confirmAndRemoveDB(paths []string, kind string, ctx *cli.Context, removeFlagName string) { - var ( - confirm bool - err error - ) - msg := fmt.Sprintf("Location(s) of '%s': \n", kind) - for _, path := range paths { - msg += fmt.Sprintf("\t- %s\n", path) - } - fmt.Println(msg) - if ctx.IsSet(removeFlagName) { - confirm = ctx.Bool(removeFlagName) - if confirm { - fmt.Printf("Remove '%s'? [y/n] y\n", kind) - } else { - fmt.Printf("Remove '%s'? [y/n] n\n", kind) - } - } else { - confirm, err = prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove '%s'?", kind)) - } - switch { - case err != nil: - utils.Fatalf("%v", err) - case !confirm: - log.Info("Database deletion skipped", "kind", kind, "paths", paths) - default: - var ( - deleted []string - start = time.Now() - ) - for _, path := range paths { - if common.FileExist(path) { - removeFolder(path) - deleted = append(deleted, path) - } else { - log.Info("Folder is not existent", "path", path) - } - } - log.Info("Database successfully deleted", "kind", kind, "paths", deleted, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -func inspect(ctx *cli.Context) error { - var ( - prefix []byte - start []byte - ) - if ctx.NArg() > 2 { - return fmt.Errorf("max 2 arguments: %v", ctx.Command.ArgsUsage) - } - if ctx.NArg() >= 1 { - if d, err := hexutil.Decode(ctx.Args().Get(0)); err != nil { - return fmt.Errorf("failed to hex-decode 'prefix': %v", err) - } else { - prefix = d - } - } - if ctx.NArg() >= 2 { - if d, err := hexutil.Decode(ctx.Args().Get(1)); err != nil { - return fmt.Errorf("failed to hex-decode 'start': %v", err) - } else { - start = d - } - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - return rawdb.InspectDatabase(db, prefix, start) -} - -func checkStateContent(ctx *cli.Context) error { - var ( - prefix []byte - start []byte - ) - if ctx.NArg() > 1 { - return fmt.Errorf("max 1 argument: %v", ctx.Command.ArgsUsage) - } - if ctx.NArg() > 0 { - if d, err := hexutil.Decode(ctx.Args().First()); err != nil { - return fmt.Errorf("failed to hex-decode 'start': %v", err) - } else { - start = d - } - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - var ( - it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) - hasher = crypto.NewKeccakState() - got = make([]byte, 32) - errs int - count int - startTime = time.Now() - lastLog = time.Now() - ) - for it.Next() { - count++ - k := it.Key() - v := it.Value() - hasher.Reset() - hasher.Write(v) - hasher.Read(got) - if !bytes.Equal(k, got) { - errs++ - fmt.Printf("Error at %#x\n", k) - fmt.Printf(" Hash: %#x\n", got) - fmt.Printf(" Data: %#x\n", v) - } - if time.Since(lastLog) > 8*time.Second { - log.Info("Iterating the database", "at", fmt.Sprintf("%#x", k), "elapsed", common.PrettyDuration(time.Since(startTime))) - lastLog = time.Now() - } - } - if err := it.Error(); err != nil { - return err - } - log.Info("Iterated the state content", "errors", errs, "items", count) - return nil -} - -func showLeveldbStats(db ethdb.KeyValueStater) { - if stats, err := db.Stat("leveldb.stats"); err != nil { - log.Warn("Failed to read database stats", "error", err) - } else { - fmt.Println(stats) - } - if ioStats, err := db.Stat("leveldb.iostats"); err != nil { - log.Warn("Failed to read database iostats", "error", err) - } else { - fmt.Println(ioStats) - } -} - -func dbStats(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - showLeveldbStats(db) - return nil -} - -func dbCompact(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, false) - defer db.Close() - - log.Info("Stats before compaction") - showLeveldbStats(db) - - log.Info("Triggering compaction") - if err := db.Compact(nil, nil); err != nil { - log.Info("Compact err", "error", err) - return err - } - log.Info("Stats after compaction") - showLeveldbStats(db) - return nil -} - -// dbGet shows the value of a given database key -func dbGet(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - key, err := common.ParseHexOrString(ctx.Args().Get(0)) - if err != nil { - log.Info("Could not decode the key", "error", err) - return err - } - - data, err := db.Get(key) - if err != nil { - log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err) - return err - } - fmt.Printf("key %#x: %#x\n", key, data) - return nil -} - -// dbDelete deletes a key from the database -func dbDelete(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, false) - defer db.Close() - - key, err := common.ParseHexOrString(ctx.Args().Get(0)) - if err != nil { - log.Info("Could not decode the key", "error", err) - return err - } - data, err := db.Get(key) - if err == nil { - fmt.Printf("Previous value: %#x\n", data) - } - if err = db.Delete(key); err != nil { - log.Info("Delete operation returned an error", "key", fmt.Sprintf("%#x", key), "error", err) - return err - } - return nil -} - -// dbPut overwrite a value in the database -func dbPut(ctx *cli.Context) error { - if ctx.NArg() != 2 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, false) - defer db.Close() - - var ( - key []byte - value []byte - data []byte - err error - ) - key, err = common.ParseHexOrString(ctx.Args().Get(0)) - if err != nil { - log.Info("Could not decode the key", "error", err) - return err - } - value, err = hexutil.Decode(ctx.Args().Get(1)) - if err != nil { - log.Info("Could not decode the value", "error", err) - return err - } - data, err = db.Get(key) - if err == nil { - fmt.Printf("Previous value: %#x\n", data) - } - return db.Put(key, value) -} - -// dbDumpTrie shows the key-value slots of a given storage trie -func dbDumpTrie(ctx *cli.Context) error { - if ctx.NArg() < 3 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) - defer triedb.Close() - - var ( - state []byte - storage []byte - account []byte - start []byte - max = int64(-1) - err error - ) - if state, err = hexutil.Decode(ctx.Args().Get(0)); err != nil { - log.Info("Could not decode the state root", "error", err) - return err - } - if account, err = hexutil.Decode(ctx.Args().Get(1)); err != nil { - log.Info("Could not decode the account hash", "error", err) - return err - } - if storage, err = hexutil.Decode(ctx.Args().Get(2)); err != nil { - log.Info("Could not decode the storage trie root", "error", err) - return err - } - if ctx.NArg() > 3 { - if start, err = hexutil.Decode(ctx.Args().Get(3)); err != nil { - log.Info("Could not decode the seek position", "error", err) - return err - } - } - if ctx.NArg() > 4 { - if max, err = strconv.ParseInt(ctx.Args().Get(4), 10, 64); err != nil { - log.Info("Could not decode the max count", "error", err) - return err - } - } - id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage)) - theTrie, err := trie.New(id, triedb) - if err != nil { - return err - } - trieIt, err := theTrie.NodeIterator(start) - if err != nil { - return err - } - var count int64 - it := trie.NewIterator(trieIt) - for it.Next() { - if max > 0 && count == max { - fmt.Printf("Exiting after %d values\n", count) - break - } - fmt.Printf(" %d. key %#x: %#x\n", count, it.Key, it.Value) - count++ - } - return it.Err -} - -func freezerInspect(ctx *cli.Context) error { - if ctx.NArg() < 4 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - var ( - freezer = ctx.Args().Get(0) - table = ctx.Args().Get(1) - ) - start, err := strconv.ParseInt(ctx.Args().Get(2), 10, 64) - if err != nil { - log.Info("Could not read start-param", "err", err) - return err - } - end, err := strconv.ParseInt(ctx.Args().Get(3), 10, 64) - if err != nil { - log.Info("Could not read count param", "err", err) - return err - } - stack, _ := makeConfigNode(ctx) - ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name)) - stack.Close() - return rawdb.InspectFreezerTable(ancient, freezer, table, start, end) -} - -func importLDBdata(ctx *cli.Context) error { - start := 0 - switch ctx.NArg() { - case 1: - break - case 2: - s, err := strconv.Atoi(ctx.Args().Get(1)) - if err != nil { - return fmt.Errorf("second arg must be an integer: %v", err) - } - start = s - default: - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - var ( - fName = ctx.Args().Get(0) - stack, _ = makeConfigNode(ctx) - interrupt = make(chan os.Signal, 1) - stop = make(chan struct{}) - ) - defer stack.Close() - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(interrupt) - defer close(interrupt) - go func() { - if _, ok := <-interrupt; ok { - log.Info("Interrupted during ldb import, stopping at next batch") - } - close(stop) - }() - db := utils.MakeChainDatabase(ctx, stack, false) - defer db.Close() - return utils.ImportLDBData(db, fName, int64(start), stop) -} - -type preimageIterator struct { - iter ethdb.Iterator -} - -func (iter *preimageIterator) Next() (byte, []byte, []byte, bool) { - for iter.iter.Next() { - key := iter.iter.Key() - if bytes.HasPrefix(key, rawdb.PreimagePrefix) && len(key) == (len(rawdb.PreimagePrefix)+common.HashLength) { - return utils.OpBatchAdd, key, iter.iter.Value(), true - } - } - return 0, nil, nil, false -} - -func (iter *preimageIterator) Release() { - iter.iter.Release() -} - -type snapshotIterator struct { - init bool - account ethdb.Iterator - storage ethdb.Iterator -} - -func (iter *snapshotIterator) Next() (byte, []byte, []byte, bool) { - if !iter.init { - iter.init = true - return utils.OpBatchDel, rawdb.SnapshotRootKey, nil, true - } - for iter.account.Next() { - key := iter.account.Key() - if bytes.HasPrefix(key, rawdb.SnapshotAccountPrefix) && len(key) == (len(rawdb.SnapshotAccountPrefix)+common.HashLength) { - return utils.OpBatchAdd, key, iter.account.Value(), true - } - } - for iter.storage.Next() { - key := iter.storage.Key() - if bytes.HasPrefix(key, rawdb.SnapshotStoragePrefix) && len(key) == (len(rawdb.SnapshotStoragePrefix)+2*common.HashLength) { - return utils.OpBatchAdd, key, iter.storage.Value(), true - } - } - return 0, nil, nil, false -} - -func (iter *snapshotIterator) Release() { - iter.account.Release() - iter.storage.Release() -} - -// chainExporters defines the export scheme for all exportable chain data. -var chainExporters = map[string]func(db ethdb.Database) utils.ChainDataIterator{ - "preimage": func(db ethdb.Database) utils.ChainDataIterator { - iter := db.NewIterator(rawdb.PreimagePrefix, nil) - return &preimageIterator{iter: iter} - }, - "snapshot": func(db ethdb.Database) utils.ChainDataIterator { - account := db.NewIterator(rawdb.SnapshotAccountPrefix, nil) - storage := db.NewIterator(rawdb.SnapshotStoragePrefix, nil) - return &snapshotIterator{account: account, storage: storage} - }, -} - -func exportChaindata(ctx *cli.Context) error { - if ctx.NArg() < 2 { - return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) - } - // Parse the required chain data type, make sure it's supported. - kind := ctx.Args().Get(0) - kind = strings.ToLower(strings.Trim(kind, " ")) - exporter, ok := chainExporters[kind] - if !ok { - var kinds []string - for kind := range chainExporters { - kinds = append(kinds, kind) - } - return fmt.Errorf("invalid data type %s, supported types: %s", kind, strings.Join(kinds, ", ")) - } - var ( - stack, _ = makeConfigNode(ctx) - interrupt = make(chan os.Signal, 1) - stop = make(chan struct{}) - ) - defer stack.Close() - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(interrupt) - defer close(interrupt) - go func() { - if _, ok := <-interrupt; ok { - log.Info("Interrupted during db export, stopping at next batch") - } - close(stop) - }() - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - return utils.ExportChaindata(ctx.Args().Get(1), kind, exporter(db), stop) -} - -func showMetaData(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - - ancients, err := db.Ancients() - if err != nil { - fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err) - } - data := rawdb.ReadChainMetadata(db) - data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)}) - data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))}) - if b := rawdb.ReadHeadBlock(db); b != nil { - data = append(data, []string{"headBlock.Hash", fmt.Sprintf("%v", b.Hash())}) - data = append(data, []string{"headBlock.Root", fmt.Sprintf("%v", b.Root())}) - data = append(data, []string{"headBlock.Number", fmt.Sprintf("%d (%#x)", b.Number(), b.Number())}) - } - if h := rawdb.ReadHeadHeader(db); h != nil { - data = append(data, []string{"headHeader.Hash", fmt.Sprintf("%v", h.Hash())}) - data = append(data, []string{"headHeader.Root", fmt.Sprintf("%v", h.Root)}) - data = append(data, []string{"headHeader.Number", fmt.Sprintf("%d (%#x)", h.Number, h.Number)}) - } - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Field", "Value"}) - table.AppendBulk(data) - table.Render() - return nil -} diff --git a/builder/cmd/geth/exportcmd_test.go b/builder/cmd/geth/exportcmd_test.go deleted file mode 100644 index 9570b1ffd..000000000 --- a/builder/cmd/geth/exportcmd_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "fmt" - "os" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -// TestExport does a basic test of "geth export", exporting the test-genesis. -func TestExport(t *testing.T) { - t.Parallel() - outfile := fmt.Sprintf("%v/testExport.out", os.TempDir()) - defer os.Remove(outfile) - geth := runGeth(t, "--datadir", initGeth(t), "export", outfile) - geth.WaitExit() - if have, want := geth.ExitStatus(), 0; have != want { - t.Errorf("exit error, have %d want %d", have, want) - } - have, err := os.ReadFile(outfile) - if err != nil { - t.Fatal(err) - } - want := common.FromHex("0xf9026bf90266a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08758259b018f7bce3d2be2ddb62f325eaeea0a0c188cf96623eab468a4413e03a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180837a12008080b875000000000000000000000000000000000000000000000000000000000000000002f0d131f1f97aef08aec6e3291b957d9efe71050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0") - if !bytes.Equal(have, want) { - t.Fatalf("wrong content exported") - } -} diff --git a/builder/cmd/geth/genesis_test.go b/builder/cmd/geth/genesis_test.go deleted file mode 100644 index ffe8176b0..000000000 --- a/builder/cmd/geth/genesis_test.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "path/filepath" - "strconv" - "testing" -) - -var customGenesisTests = []struct { - genesis string - query string - result string -}{ - // Genesis file with an empty chain configuration (ensure missing fields work) - { - genesis: `{ - "alloc" : {}, - "coinbase" : "0x0000000000000000000000000000000000000000", - "difficulty" : "0x20000", - "extraData" : "", - "gasLimit" : "0x2fefd8", - "nonce" : "0x0000000000001338", - "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp" : "0x00", - "config" : { - "terminalTotalDifficultyPassed": true - } - }`, - query: "eth.getBlock(0).nonce", - result: "0x0000000000001338", - }, - // Genesis file with specific chain configurations - { - genesis: `{ - "alloc" : {}, - "coinbase" : "0x0000000000000000000000000000000000000000", - "difficulty" : "0x20000", - "extraData" : "", - "gasLimit" : "0x2fefd8", - "nonce" : "0x0000000000001339", - "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp" : "0x00", - "config" : { - "homesteadBlock" : 42, - "daoForkBlock" : 141, - "daoForkSupport" : true, - "terminalTotalDifficultyPassed" : true - } - }`, - query: "eth.getBlock(0).nonce", - result: "0x0000000000001339", - }, -} - -// Tests that initializing Geth with a custom genesis block and chain definitions -// work properly. -func TestCustomGenesis(t *testing.T) { - t.Parallel() - for i, tt := range customGenesisTests { - // Create a temporary data directory to use and inspect later - datadir := t.TempDir() - - // Initialize the data directory with the custom genesis block - json := filepath.Join(datadir, "genesis.json") - if err := os.WriteFile(json, []byte(tt.genesis), 0600); err != nil { - t.Fatalf("test %d: failed to write genesis file: %v", i, err) - } - runGeth(t, "--datadir", datadir, "init", json).WaitExit() - - // Query the custom genesis block - geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16", - "--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0", - "--nodiscover", "--nat", "none", "--ipcdisable", - "--exec", tt.query, "console") - geth.ExpectRegexp(tt.result) - geth.ExpectExit() - } -} - -// TestCustomBackend that the backend selection and detection (leveldb vs pebble) works properly. -func TestCustomBackend(t *testing.T) { - t.Parallel() - // Test pebble, but only on 64-bit platforms - if strconv.IntSize != 64 { - t.Skip("Custom backends are only available on 64-bit platform") - } - genesis := `{ - "alloc" : {}, - "coinbase" : "0x0000000000000000000000000000000000000000", - "difficulty" : "0x20000", - "extraData" : "", - "gasLimit" : "0x2fefd8", - "nonce" : "0x0000000000001338", - "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp" : "0x00", - "config" : { - "terminalTotalDifficultyPassed": true - } - }` - type backendTest struct { - initArgs []string - initExpect string - execArgs []string - execExpect string - } - testfunc := func(t *testing.T, tt backendTest) error { - // Create a temporary data directory to use and inspect later - datadir := t.TempDir() - - // Initialize the data directory with the custom genesis block - json := filepath.Join(datadir, "genesis.json") - if err := os.WriteFile(json, []byte(genesis), 0600); err != nil { - return fmt.Errorf("failed to write genesis file: %v", err) - } - { // Init - args := append(tt.initArgs, "--datadir", datadir, "init", json) - geth := runGeth(t, args...) - geth.ExpectRegexp(tt.initExpect) - geth.ExpectExit() - } - { // Exec + query - args := append(tt.execArgs, "--networkid", "1337", "--syncmode=full", "--cache", "16", - "--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0", - "--nodiscover", "--nat", "none", "--ipcdisable", - "--exec", "eth.getBlock(0).nonce", "console") - geth := runGeth(t, args...) - geth.ExpectRegexp(tt.execExpect) - geth.ExpectExit() - } - return nil - } - for i, tt := range []backendTest{ - { // When not specified, it should default to pebble - execArgs: []string{"--db.engine", "pebble"}, - execExpect: "0x0000000000001338", - }, - { // Explicit leveldb - initArgs: []string{"--db.engine", "leveldb"}, - execArgs: []string{"--db.engine", "leveldb"}, - execExpect: "0x0000000000001338", - }, - { // Explicit leveldb first, then autodiscover - initArgs: []string{"--db.engine", "leveldb"}, - execExpect: "0x0000000000001338", - }, - { // Explicit pebble - initArgs: []string{"--db.engine", "pebble"}, - execArgs: []string{"--db.engine", "pebble"}, - execExpect: "0x0000000000001338", - }, - { // Explicit pebble, then auto-discover - initArgs: []string{"--db.engine", "pebble"}, - execExpect: "0x0000000000001338", - }, - { // Can't start pebble on top of leveldb - initArgs: []string{"--db.engine", "leveldb"}, - execArgs: []string{"--db.engine", "pebble"}, - execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was pebble but found pre-existing leveldb database in specified data directory`, - }, - { // Can't start leveldb on top of pebble - initArgs: []string{"--db.engine", "pebble"}, - execArgs: []string{"--db.engine", "leveldb"}, - execExpect: `Fatal: Failed to register the Ethereum service: db.engine choice was leveldb but found pre-existing pebble database in specified data directory`, - }, - { // Reject invalid backend choice - initArgs: []string{"--db.engine", "mssql"}, - initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`, - // Since the init fails, this will return the (default) mainnet genesis - // block nonce - execExpect: `0x0000000000000042`, - }, - } { - if err := testfunc(t, tt); err != nil { - t.Fatalf("test %d-leveldb: %v", i, err) - } - } -} diff --git a/builder/cmd/geth/logging_test.go b/builder/cmd/geth/logging_test.go deleted file mode 100644 index b5ce03f4b..000000000 --- a/builder/cmd/geth/logging_test.go +++ /dev/null @@ -1,237 +0,0 @@ -//go:build integrationtests - -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "io" - "math/rand" - "os" - "os/exec" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/internal/reexec" -) - -func runSelf(args ...string) ([]byte, error) { - cmd := &exec.Cmd{ - Path: reexec.Self(), - Args: append([]string{"geth-test"}, args...), - } - return cmd.CombinedOutput() -} - -func split(input io.Reader) []string { - var output []string - scanner := bufio.NewScanner(input) - scanner.Split(bufio.ScanLines) - for scanner.Scan() { - output = append(output, strings.TrimSpace(scanner.Text())) - } - return output -} - -func censor(input string, start, end int) string { - if len(input) < end { - return input - } - return input[:start] + strings.Repeat("X", end-start) + input[end:] -} - -func TestLogging(t *testing.T) { - t.Parallel() - testConsoleLogging(t, "terminal", 6, 24) - testConsoleLogging(t, "logfmt", 2, 26) -} - -func testConsoleLogging(t *testing.T, format string, tStart, tEnd int) { - haveB, err := runSelf("--log.format", format, "logtest") - if err != nil { - t.Fatal(err) - } - readFile, err := os.Open(fmt.Sprintf("testdata/logging/logtest-%v.txt", format)) - if err != nil { - t.Fatal(err) - } - wantLines := split(readFile) - haveLines := split(bytes.NewBuffer(haveB)) - for i, want := range wantLines { - if i > len(haveLines)-1 { - t.Fatalf("format %v, line %d missing, want:%v", format, i, want) - } - have := haveLines[i] - for strings.Contains(have, "Unknown config environment variable") { - // This can happen on CI runs. Drop it. - haveLines = append(haveLines[:i], haveLines[i+1:]...) - have = haveLines[i] - } - - // Black out the timestamp - have = censor(have, tStart, tEnd) - want = censor(want, tStart, tEnd) - if have != want { - t.Logf(nicediff([]byte(have), []byte(want))) - t.Fatalf("format %v, line %d\nhave %v\nwant %v", format, i, have, want) - } - } - if len(haveLines) != len(wantLines) { - t.Errorf("format %v, want %d lines, have %d", format, len(haveLines), len(wantLines)) - } -} - -func TestJsonLogging(t *testing.T) { - t.Parallel() - haveB, err := runSelf("--log.format", "json", "logtest") - if err != nil { - t.Fatal(err) - } - readFile, err := os.Open("testdata/logging/logtest-json.txt") - if err != nil { - t.Fatal(err) - } - wantLines := split(readFile) - haveLines := split(bytes.NewBuffer(haveB)) - for i, wantLine := range wantLines { - if i > len(haveLines)-1 { - t.Fatalf("format %v, line %d missing, want:%v", "json", i, wantLine) - } - haveLine := haveLines[i] - for strings.Contains(haveLine, "Unknown config environment variable") { - // This can happen on CI runs. Drop it. - haveLines = append(haveLines[:i], haveLines[i+1:]...) - haveLine = haveLines[i] - } - var have, want []byte - { - var h map[string]any - if err := json.Unmarshal([]byte(haveLine), &h); err != nil { - t.Fatal(err) - } - h["t"] = "xxx" - have, _ = json.Marshal(h) - } - { - var w map[string]any - if err := json.Unmarshal([]byte(wantLine), &w); err != nil { - t.Fatal(err) - } - w["t"] = "xxx" - want, _ = json.Marshal(w) - } - if !bytes.Equal(have, want) { - // show an intelligent diff - t.Logf(nicediff(have, want)) - t.Errorf("file content wrong") - } - } -} - -func TestVmodule(t *testing.T) { - t.Parallel() - checkOutput := func(level int, want, wantNot string) { - t.Helper() - output, err := runSelf("--log.format", "terminal", "--verbosity=0", "--log.vmodule", fmt.Sprintf("logtestcmd_active.go=%d", level), "logtest") - if err != nil { - t.Fatal(err) - } - if len(want) > 0 && !strings.Contains(string(output), want) { // trace should be present at 5 - t.Errorf("failed to find expected string ('%s') in output", want) - } - if len(wantNot) > 0 && strings.Contains(string(output), wantNot) { // trace should be present at 5 - t.Errorf("string ('%s') should not be present in output", wantNot) - } - } - checkOutput(5, "log at level trace", "") // trace should be present at 5 - checkOutput(4, "log at level debug", "log at level trace") // debug should be present at 4, but trace should be missing - checkOutput(3, "log at level info", "log at level debug") // info should be present at 3, but debug should be missing - checkOutput(2, "log at level warn", "log at level info") // warn should be present at 2, but info should be missing - checkOutput(1, "log at level error", "log at level warn") // error should be present at 1, but warn should be missing -} - -func nicediff(have, want []byte) string { - var i = 0 - for ; i < len(have) && i < len(want); i++ { - if want[i] != have[i] { - break - } - } - var end = i + 40 - var start = i - 50 - if start < 0 { - start = 0 - } - var h, w string - if end < len(have) { - h = string(have[start:end]) - } else { - h = string(have[start:]) - } - if end < len(want) { - w = string(want[start:end]) - } else { - w = string(want[start:]) - } - return fmt.Sprintf("have vs want:\n%q\n%q\n", h, w) -} - -func TestFileOut(t *testing.T) { - t.Parallel() - var ( - have, want []byte - err error - path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63()) - ) - t.Cleanup(func() { os.Remove(path) }) - if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil { - t.Fatal(err) - } - if have, err = os.ReadFile(path); err != nil { - t.Fatal(err) - } - if !bytes.Equal(have, want) { - // show an intelligent diff - t.Logf(nicediff(have, want)) - t.Errorf("file content wrong") - } -} - -func TestRotatingFileOut(t *testing.T) { - t.Parallel() - var ( - have, want []byte - err error - path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63()) - ) - t.Cleanup(func() { os.Remove(path) }) - if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil { - t.Fatal(err) - } - if have, err = os.ReadFile(path); err != nil { - t.Fatal(err) - } - if !bytes.Equal(have, want) { - // show an intelligent diff - t.Logf(nicediff(have, want)) - t.Errorf("file content wrong") - } -} diff --git a/builder/cmd/geth/logtestcmd_active.go b/builder/cmd/geth/logtestcmd_active.go deleted file mode 100644 index f2a2c5ded..000000000 --- a/builder/cmd/geth/logtestcmd_active.go +++ /dev/null @@ -1,171 +0,0 @@ -//go:build integrationtests - -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "errors" - "fmt" - "math" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/holiman/uint256" - "github.com/urfave/cli/v2" -) - -var logTestCommand = &cli.Command{ - Action: logTest, - Name: "logtest", - Usage: "Print some log messages", - ArgsUsage: " ", - Description: ` -This command is only meant for testing. -`} - -type customQuotedStringer struct { -} - -func (c customQuotedStringer) String() string { - return "output with 'quotes'" -} - -// logTest is an entry point which spits out some logs. This is used by testing -// to verify expected outputs -func logTest(ctx *cli.Context) error { - { // big.Int - ba, _ := new(big.Int).SetString("111222333444555678999", 10) // "111,222,333,444,555,678,999" - bb, _ := new(big.Int).SetString("-111222333444555678999", 10) // "-111,222,333,444,555,678,999" - bc, _ := new(big.Int).SetString("11122233344455567899900", 10) // "11,122,233,344,455,567,899,900" - bd, _ := new(big.Int).SetString("-11122233344455567899900", 10) // "-11,122,233,344,455,567,899,900" - log.Info("big.Int", "111,222,333,444,555,678,999", ba) - log.Info("-big.Int", "-111,222,333,444,555,678,999", bb) - log.Info("big.Int", "11,122,233,344,455,567,899,900", bc) - log.Info("-big.Int", "-11,122,233,344,455,567,899,900", bd) - } - { //uint256 - ua, _ := uint256.FromDecimal("111222333444555678999") - ub, _ := uint256.FromDecimal("11122233344455567899900") - log.Info("uint256", "111,222,333,444,555,678,999", ua) - log.Info("uint256", "11,122,233,344,455,567,899,900", ub) - } - { // int64 - log.Info("int64", "1,000,000", int64(1000000)) - log.Info("int64", "-1,000,000", int64(-1000000)) - log.Info("int64", "9,223,372,036,854,775,807", int64(math.MaxInt64)) - log.Info("int64", "-9,223,372,036,854,775,808", int64(math.MinInt64)) - } - { // uint64 - log.Info("uint64", "1,000,000", uint64(1000000)) - log.Info("uint64", "18,446,744,073,709,551,615", uint64(math.MaxUint64)) - } - { // Special characters - log.Info("Special chars in value", "key", "special \r\n\t chars") - log.Info("Special chars in key", "special \n\t chars", "value") - - log.Info("nospace", "nospace", "nospace") - log.Info("with space", "with nospace", "with nospace") - - log.Info("Bash escapes in value", "key", "\u001b[1G\u001b[K\u001b[1A") - log.Info("Bash escapes in key", "\u001b[1G\u001b[K\u001b[1A", "value") - - log.Info("Bash escapes in message \u001b[1G\u001b[K\u001b[1A end", "key", "value") - - colored := fmt.Sprintf("\u001B[%dmColored\u001B[0m[", 35) - log.Info(colored, colored, colored) - err := errors.New("this is an 'error'") - log.Info("an error message with quotes", "error", err) - } - { // Custom Stringer() - type - log.Info("Custom Stringer value", "2562047h47m16.854s", common.PrettyDuration(time.Duration(9223372036854775807))) - var c customQuotedStringer - log.Info("a custom stringer that emits quoted text", "output", c) - } - { // Multi-line message - log.Info("A message with wonky \U0001F4A9 characters") - log.Info("A multiline message \nINFO [10-18|14:11:31.106] with wonky characters \U0001F4A9") - log.Info("A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above") - } - { // Miscellaneous json-quirks - // This will check if the json output uses strings or json-booleans to represent bool values - log.Info("boolean", "true", true, "false", false) - // Handling of duplicate keys. - // This is actually ill-handled by the current handler: the format.go - // uses a global 'fieldPadding' map and mixes up the two keys. If 'alpha' - // is shorter than beta, it sometimes causes erroneous padding -- and what's more - // it causes _different_ padding in multi-handler context, e.g. both file- - // and console output, making the two mismatch. - log.Info("repeated-key 1", "foo", "alpha", "foo", "beta") - log.Info("repeated-key 2", "xx", "short", "xx", "longer") - } - { // loglevels - log.Debug("log at level debug") - log.Trace("log at level trace") - log.Info("log at level info") - log.Warn("log at level warn") - log.Error("log at level error") - } - { - // The current log formatter has a global map of paddings, storing the - // longest seen padding per key in a map. This results in a statefulness - // which has some odd side-effects. Demonstrated here: - log.Info("test", "bar", "short", "a", "aligned left") - log.Info("test", "bar", "a long message", "a", 1) - log.Info("test", "bar", "short", "a", "aligned right") - } - { - // This sequence of logs should be output with alignment, so each field becoems a column. - log.Info("The following logs should align so that the key-fields make 5 columns") - log.Info("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 1_123_123, "other", "first") - log.Info("Inserted new block", "number", 1, "hash", common.HexToHash("0x1235"), "txs", 2, "gas", 1_123, "other", "second") - log.Info("Inserted known block", "number", 99, "hash", common.HexToHash("0x12322"), "txs", 10, "gas", 1, "other", "third") - log.Warn("Inserted known block", "number", 1_012, "hash", common.HexToHash("0x1234"), "txs", 200, "gas", 99, "other", "fourth") - } - { // Various types of nil - type customStruct struct { - A string - B *uint64 - } - log.Info("(*big.Int)(nil)", "", (*big.Int)(nil)) - log.Info("(*uint256.Int)(nil)", "", (*uint256.Int)(nil)) - log.Info("(fmt.Stringer)(nil)", "res", (fmt.Stringer)(nil)) - log.Info("nil-concrete-stringer", "res", (*time.Time)(nil)) - - log.Info("error(nil) ", "res", error(nil)) - log.Info("nil-concrete-error", "res", (*customError)(nil)) - - log.Info("nil-custom-struct", "res", (*customStruct)(nil)) - log.Info("raw nil", "res", nil) - log.Info("(*uint64)(nil)", "res", (*uint64)(nil)) - } - { // Logging with 'reserved' keys - log.Info("Using keys 't', 'lvl', 'time', 'level' and 'msg'", "t", "t", "time", "time", "lvl", "lvl", "level", "level", "msg", "msg") - } - { // Logging with wrong attr-value pairs - log.Info("Odd pair (1 attr)", "key") - log.Info("Odd pair (3 attr)", "key", "value", "key2") - } - return nil -} - -// customError is a type which implements error -type customError struct{} - -func (c *customError) Error() string { return "" } diff --git a/builder/cmd/geth/logtestcmd_inactive.go b/builder/cmd/geth/logtestcmd_inactive.go deleted file mode 100644 index 691ab5bcd..000000000 --- a/builder/cmd/geth/logtestcmd_inactive.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build !integrationtests - -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import "github.com/urfave/cli/v2" - -var logTestCommand *cli.Command diff --git a/builder/cmd/geth/main.go b/builder/cmd/geth/main.go deleted file mode 100644 index 06715354a..000000000 --- a/builder/cmd/geth/main.go +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// geth is a command-line client for Ethereum. -package main - -import ( - "fmt" - "os" - "sort" - "strconv" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/internal/debug" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/node" - "go.uber.org/automaxprocs/maxprocs" - - // Force-load the tracer engines to trigger registration - _ "github.com/ethereum/go-ethereum/eth/tracers/js" - _ "github.com/ethereum/go-ethereum/eth/tracers/native" - - "github.com/urfave/cli/v2" -) - -const ( - clientIdentifier = "geth" // Client identifier to advertise over the network -) - -var ( - // flags that configure the node - nodeFlags = flags.Merge([]cli.Flag{ - utils.IdentityFlag, - utils.UnlockedAccountFlag, - utils.PasswordFileFlag, - utils.BootnodesFlag, - utils.MinFreeDiskSpaceFlag, - utils.KeyStoreDirFlag, - utils.ExternalSignerFlag, - utils.NoUSBFlag, // deprecated - utils.USBFlag, - utils.SmartCardDaemonPathFlag, - utils.OverrideCancun, - utils.OverrideVerkle, - utils.EnablePersonal, - utils.TxPoolLocalsFlag, - utils.TxPoolNoLocalsFlag, - utils.TxPoolJournalFlag, - utils.TxPoolRejournalFlag, - utils.TxPoolPriceLimitFlag, - utils.TxPoolPriceBumpFlag, - utils.TxPoolAccountSlotsFlag, - utils.TxPoolGlobalSlotsFlag, - utils.TxPoolAccountQueueFlag, - utils.TxPoolGlobalQueueFlag, - utils.TxPoolLifetimeFlag, - utils.TxPoolPrivateLifetimeFlag, - utils.BlobPoolDataDirFlag, - utils.BlobPoolDataCapFlag, - utils.BlobPoolPriceBumpFlag, - utils.SyncModeFlag, - utils.SyncTargetFlag, - utils.ExitWhenSyncedFlag, - utils.GCModeFlag, - utils.SnapshotFlag, - utils.TxLookupLimitFlag, // deprecated - utils.TransactionHistoryFlag, - utils.StateHistoryFlag, - utils.LightServeFlag, // deprecated - utils.LightIngressFlag, // deprecated - utils.LightEgressFlag, // deprecated - utils.LightMaxPeersFlag, // deprecated - utils.LightNoPruneFlag, // deprecated - utils.LightKDFFlag, - utils.LightNoSyncServeFlag, // deprecated - utils.EthRequiredBlocksFlag, - utils.LegacyWhitelistFlag, // deprecated - utils.BloomFilterSizeFlag, - utils.CacheFlag, - utils.CacheDatabaseFlag, - utils.CacheTrieFlag, - utils.CacheTrieJournalFlag, // deprecated - utils.CacheTrieRejournalFlag, // deprecated - utils.CacheGCFlag, - utils.CacheSnapshotFlag, - utils.CacheNoPrefetchFlag, - utils.CachePreimagesFlag, - utils.CacheLogSizeFlag, - utils.FDLimitFlag, - utils.CryptoKZGFlag, - utils.ListenPortFlag, - utils.DiscoveryPortFlag, - utils.MaxPeersFlag, - utils.MaxPendingPeersFlag, - utils.MiningEnabledFlag, - utils.MinerGasLimitFlag, - utils.MinerGasPriceFlag, - utils.MinerAlgoTypeFlag, - utils.MinerEtherbaseFlag, - utils.MinerExtraDataFlag, - utils.MinerRecommitIntervalFlag, - utils.MinerMaxMergedBundlesFlag, - utils.MinerBlocklistFileFlag, - utils.MinerNewPayloadTimeout, - utils.MinerPriceCutoffPercentFlag, - utils.NATFlag, - utils.NoDiscoverFlag, - utils.DiscoveryV4Flag, - utils.DiscoveryV5Flag, - utils.LegacyDiscoveryV5Flag, // deprecated - utils.NetrestrictFlag, - utils.NodeKeyFileFlag, - utils.NodeKeyHexFlag, - utils.DNSDiscoveryFlag, - utils.DeveloperFlag, - utils.DeveloperGasLimitFlag, - utils.DeveloperPeriodFlag, - utils.VMEnableDebugFlag, - utils.NetworkIdFlag, - utils.EthStatsURLFlag, - utils.NoCompactionFlag, - utils.GpoBlocksFlag, - utils.GpoPercentileFlag, - utils.GpoMaxGasPriceFlag, - utils.GpoIgnoreGasPriceFlag, - configFileFlag, - utils.LogDebugFlag, - utils.LogBacktraceAtFlag, - }, utils.NetworkFlags, utils.DatabaseFlags) - - builderApiFlags = []cli.Flag{ - utils.BuilderEnabled, - utils.BuilderAlgoTypeFlag, - utils.BuilderPriceCutoffPercentFlag, - utils.BuilderEnableValidatorChecks, - utils.BuilderBlockValidationBlacklistSourceFilePath, - utils.BuilderBlockValidationUseBalanceDiff, - utils.BuilderBlockValidationExcludeWithdrawals, - utils.BuilderEnableLocalRelay, - utils.BuilderSecondsInSlot, - utils.BuilderSlotsInEpoch, - utils.BuilderDisableBundleFetcher, - utils.BuilderDryRun, - utils.BuilderIgnoreLatePayloadAttributes, - utils.BuilderSecretKey, - utils.BuilderRelaySecretKey, - utils.BuilderListenAddr, - utils.BuilderGenesisForkVersion, - utils.BuilderBellatrixForkVersion, - utils.BuilderGenesisValidatorsRoot, - utils.BuilderBeaconEndpoints, - utils.BuilderRemoteRelayEndpoint, - utils.BuilderSecondaryRemoteRelayEndpoints, - utils.BuilderMevSidecarEndpoint, - utils.BuilderRateLimitDuration, - utils.BuilderRateLimitMaxBurst, - utils.BuilderBlockResubmitInterval, - utils.BuilderSubmissionOffset, - utils.BuilderDiscardRevertibleTxOnErr, - utils.BuilderEnableCancellations, - utils.BuilderBlockProcessorURL, - } - - rpcFlags = []cli.Flag{ - utils.HTTPEnabledFlag, - utils.HTTPListenAddrFlag, - utils.HTTPPortFlag, - utils.HTTPCORSDomainFlag, - utils.AuthListenFlag, - utils.AuthPortFlag, - utils.AuthVirtualHostsFlag, - utils.JWTSecretFlag, - utils.HTTPVirtualHostsFlag, - utils.GraphQLEnabledFlag, - utils.GraphQLCORSDomainFlag, - utils.GraphQLVirtualHostsFlag, - utils.HTTPApiFlag, - utils.HTTPPathPrefixFlag, - utils.WSEnabledFlag, - utils.WSListenAddrFlag, - utils.WSPortFlag, - utils.WSApiFlag, - utils.WSAllowedOriginsFlag, - utils.WSPathPrefixFlag, - utils.IPCDisabledFlag, - utils.IPCPathFlag, - utils.InsecureUnlockAllowedFlag, - utils.RPCGlobalGasCapFlag, - utils.RPCGlobalEVMTimeoutFlag, - utils.RPCGlobalTxFeeCapFlag, - utils.AllowUnprotectedTxs, - utils.BatchRequestLimit, - utils.BatchResponseMaxSize, - } - - metricsFlags = []cli.Flag{ - utils.MetricsEnabledFlag, - utils.MetricsEnabledExpensiveFlag, - utils.MetricsEnabledBuilderFlag, - utils.MetricsHTTPFlag, - utils.MetricsPortFlag, - utils.MetricsEnableInfluxDBFlag, - utils.MetricsInfluxDBEndpointFlag, - utils.MetricsInfluxDBDatabaseFlag, - utils.MetricsInfluxDBUsernameFlag, - utils.MetricsInfluxDBPasswordFlag, - utils.MetricsInfluxDBTagsFlag, - utils.MetricsEnableInfluxDBV2Flag, - utils.MetricsInfluxDBTokenFlag, - utils.MetricsInfluxDBBucketFlag, - utils.MetricsInfluxDBOrganizationFlag, - } -) - -var app = flags.NewApp("the go-ethereum command line interface") - -func init() { - // Initialize the CLI app and start Geth - app.Action = geth - app.Commands = []*cli.Command{ - // See chaincmd.go: - initCommand, - importCommand, - exportCommand, - importHistoryCommand, - exportHistoryCommand, - importPreimagesCommand, - removedbCommand, - dumpCommand, - dumpGenesisCommand, - // See accountcmd.go: - accountCommand, - walletCommand, - // See consolecmd.go: - consoleCommand, - attachCommand, - javascriptCommand, - // See misccmd.go: - versionCommand, - versionCheckCommand, - licenseCommand, - // See config.go - dumpConfigCommand, - // see dbcmd.go - dbCommand, - // See cmd/utils/flags_legacy.go - utils.ShowDeprecated, - // See snapshot.go - snapshotCommand, - // See verkle.go - verkleCommand, - } - if logTestCommand != nil { - app.Commands = append(app.Commands, logTestCommand) - } - sort.Sort(cli.CommandsByName(app.Commands)) - - app.Flags = flags.Merge( - nodeFlags, - rpcFlags, - builderApiFlags, - consoleFlags, - debug.Flags, - metricsFlags, - ) - flags.AutoEnvVars(app.Flags, "GETH") - - app.Before = func(ctx *cli.Context) error { - maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota. - flags.MigrateGlobalFlags(ctx) - if err := debug.Setup(ctx); err != nil { - return err - } - flags.CheckEnvVars(ctx, app.Flags, "GETH") - return nil - } - app.After = func(ctx *cli.Context) error { - debug.Exit() - prompt.Stdin.Close() // Resets terminal mode. - return nil - } -} - -func main() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -// prepare manipulates memory cache allowance and setups metric system. -// This function should be called before launching devp2p stack. -func prepare(ctx *cli.Context) { - // If we're running a known preset, log it for convenience. - switch { - case ctx.IsSet(utils.GoerliFlag.Name): - log.Info("Starting Geth on Görli testnet...") - - case ctx.IsSet(utils.SepoliaFlag.Name): - log.Info("Starting Geth on Sepolia testnet...") - - case ctx.IsSet(utils.HoleskyFlag.Name): - log.Info("Starting Geth on Holesky testnet...") - - case ctx.IsSet(utils.DeveloperFlag.Name): - log.Info("Starting Geth in ephemeral dev mode...") - log.Warn(`You are running Geth in --dev mode. Please note the following: - - 1. This mode is only intended for fast, iterative development without assumptions on - security or persistence. - 2. The database is created in memory unless specified otherwise. Therefore, shutting down - your computer or losing power will wipe your entire block data and chain state for - your dev environment. - 3. A random, pre-allocated developer account will be available and unlocked as - eth.coinbase, which can be used for testing. The random dev account is temporary, - stored on a ramdisk, and will be lost if your machine is restarted. - 4. Mining is enabled by default. However, the client will only seal blocks if transactions - are pending in the mempool. The miner's minimum accepted gas price is 1. - 5. Networking is disabled; there is no listen-address, the maximum number of peers is set - to 0, and discovery is disabled. -`) - - case !ctx.IsSet(utils.NetworkIdFlag.Name): - log.Info("Starting Geth on Ethereum mainnet...") - } - // If we're a full node on mainnet without --cache specified, bump default cache allowance - if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) { - // Make sure we're not on any supported preconfigured testnet either - if !ctx.IsSet(utils.HoleskyFlag.Name) && - !ctx.IsSet(utils.SepoliaFlag.Name) && - !ctx.IsSet(utils.GoerliFlag.Name) && - !ctx.IsSet(utils.DeveloperFlag.Name) { - // Nope, we're really on mainnet. Bump that cache up! - log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096) - ctx.Set(utils.CacheFlag.Name, strconv.Itoa(4096)) - } - } - - // Start metrics export if enabled - utils.SetupMetrics(ctx) - - // Start system runtime metrics collection - go metrics.CollectProcessMetrics(3 * time.Second) -} - -// geth is the main entry point into the system if no special subcommand is run. -// It creates a default node based on the command line arguments and runs it in -// blocking mode, waiting for it to be shut down. -func geth(ctx *cli.Context) error { - if args := ctx.Args().Slice(); len(args) > 0 { - return fmt.Errorf("invalid command: %q", args[0]) - } - - prepare(ctx) - stack, backend := makeFullNode(ctx) - defer stack.Close() - - startNode(ctx, stack, backend, false) - stack.Wait() - return nil -} - -// startNode boots up the system node and all registered protocols, after which -// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the -// miner. -func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isConsole bool) { - debug.Memsize.Add("node", stack) - - // Start up the node itself - utils.StartNode(ctx, stack, isConsole) - - // Unlock any account specifically requested - unlockAccounts(ctx, stack) - - // Register wallet event handlers to open and auto-derive wallets - events := make(chan accounts.WalletEvent, 16) - stack.AccountManager().Subscribe(events) - - // Create a client to interact with local geth node. - rpcClient := stack.Attach() - ethClient := ethclient.NewClient(rpcClient) - - go func() { - // Open any wallets already attached - for _, wallet := range stack.AccountManager().Wallets() { - if err := wallet.Open(""); err != nil { - log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) - } - } - // Listen for wallet event till termination - for event := range events { - switch event.Kind { - case accounts.WalletArrived: - if err := event.Wallet.Open(""); err != nil { - log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) - } - case accounts.WalletOpened: - status, _ := event.Wallet.Status() - log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) - - var derivationPaths []accounts.DerivationPath - if event.Wallet.URL().Scheme == "ledger" { - derivationPaths = append(derivationPaths, accounts.LegacyLedgerBaseDerivationPath) - } - derivationPaths = append(derivationPaths, accounts.DefaultBaseDerivationPath) - - event.Wallet.SelfDerive(derivationPaths, ethClient) - - case accounts.WalletDropped: - log.Info("Old wallet dropped", "url", event.Wallet.URL()) - event.Wallet.Close() - } - } - }() - - // Spawn a standalone goroutine for status synchronization monitoring, - // close the node when synchronization is complete if user required. - if ctx.Bool(utils.ExitWhenSyncedFlag.Name) { - go func() { - sub := stack.EventMux().Subscribe(downloader.DoneEvent{}) - defer sub.Unsubscribe() - for { - event := <-sub.Chan() - if event == nil { - continue - } - done, ok := event.Data.(downloader.DoneEvent) - if !ok { - continue - } - if timestamp := time.Unix(int64(done.Latest.Time), 0); time.Since(timestamp) < 10*time.Minute { - log.Info("Synchronisation completed", "latestnum", done.Latest.Number, "latesthash", done.Latest.Hash(), - "age", common.PrettyAge(timestamp)) - stack.Close() - } - } - }() - } - - // Start auxiliary services if enabled - if ctx.Bool(utils.MiningEnabledFlag.Name) { - // Mining only makes sense if a full Ethereum node is running - if ctx.String(utils.SyncModeFlag.Name) == "light" { - utils.Fatalf("Light clients do not support mining") - } - ethBackend, ok := backend.(*eth.EthAPIBackend) - if !ok { - utils.Fatalf("Ethereum service not running") - } - // Set the gas price to the limits from the CLI and start mining - gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) - ethBackend.TxPool().SetGasTip(gasprice) - if err := ethBackend.StartMining(); err != nil { - utils.Fatalf("Failed to start mining: %v", err) - } - } -} - -// unlockAccounts unlocks any account specifically requested. -func unlockAccounts(ctx *cli.Context, stack *node.Node) { - var unlocks []string - inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",") - for _, input := range inputs { - if trimmed := strings.TrimSpace(input); trimmed != "" { - unlocks = append(unlocks, trimmed) - } - } - // Short circuit if there is no account to unlock. - if len(unlocks) == 0 { - return - } - // If insecure account unlocking is not allowed if node's APIs are exposed to external. - // Print warning log to user and skip unlocking. - if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { - utils.Fatalf("Account unlock with HTTP access is forbidden!") - } - backends := stack.AccountManager().Backends(keystore.KeyStoreType) - if len(backends) == 0 { - log.Warn("Failed to unlock accounts, keystore is not available") - return - } - ks := backends[0].(*keystore.KeyStore) - passwords := utils.MakePasswordList(ctx) - for i, account := range unlocks { - unlockAccount(ks, account, i, passwords) - } -} diff --git a/builder/cmd/geth/misccmd.go b/builder/cmd/geth/misccmd.go deleted file mode 100644 index f3530c30f..000000000 --- a/builder/cmd/geth/misccmd.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "fmt" - "os" - "runtime" - "strings" - - "github.com/ethereum/go-ethereum/internal/version" - "github.com/ethereum/go-ethereum/params" - "github.com/urfave/cli/v2" -) - -var ( - VersionCheckUrlFlag = &cli.StringFlag{ - Name: "check.url", - Usage: "URL to use when checking vulnerabilities", - Value: "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json", - } - VersionCheckVersionFlag = &cli.StringFlag{ - Name: "check.version", - Usage: "Version to check", - Value: version.ClientName(clientIdentifier), - } - versionCommand = &cli.Command{ - Action: printVersion, - Name: "version", - Usage: "Print version numbers", - ArgsUsage: " ", - Description: ` -The output of this command is supposed to be machine-readable. -`, - } - versionCheckCommand = &cli.Command{ - Action: versionCheck, - Flags: []cli.Flag{ - VersionCheckUrlFlag, - VersionCheckVersionFlag, - }, - Name: "version-check", - Usage: "Checks (online) for known Geth security vulnerabilities", - ArgsUsage: "", - Description: ` -The version-check command fetches vulnerability-information from https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json, -and displays information about any security vulnerabilities that affect the currently executing version. -`, - } - licenseCommand = &cli.Command{ - Action: license, - Name: "license", - Usage: "Display license information", - ArgsUsage: " ", - } -) - -func printVersion(ctx *cli.Context) error { - git, _ := version.VCS() - - fmt.Println(strings.Title(clientIdentifier)) - fmt.Println("Version:", params.VersionWithMeta) - if git.Commit != "" { - fmt.Println("Git Commit:", git.Commit) - } - if git.Date != "" { - fmt.Println("Git Commit Date:", git.Date) - } - fmt.Println("Architecture:", runtime.GOARCH) - fmt.Println("Go Version:", runtime.Version()) - fmt.Println("Operating System:", runtime.GOOS) - fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) - fmt.Printf("GOROOT=%s\n", runtime.GOROOT()) - return nil -} - -func license(_ *cli.Context) error { - fmt.Println(`Geth 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. - -Geth 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 geth. If not, see .`) - return nil -} diff --git a/builder/cmd/geth/run_test.go b/builder/cmd/geth/run_test.go deleted file mode 100644 index 1d3288032..000000000 --- a/builder/cmd/geth/run_test.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "context" - "fmt" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/internal/cmdtest" - "github.com/ethereum/go-ethereum/internal/reexec" - "github.com/ethereum/go-ethereum/rpc" -) - -type testgeth struct { - *cmdtest.TestCmd - - // template variables for expect - Datadir string - Etherbase string -} - -func init() { - // Run the app if we've been exec'd as "geth-test" in runGeth. - reexec.Register("geth-test", func() { - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - os.Exit(0) - }) -} - -func TestMain(m *testing.M) { - // check if we have been reexec'd - if reexec.Init() { - return - } - os.Exit(m.Run()) -} - -func initGeth(t *testing.T) string { - args := []string{"--networkid=42", "init", "./testdata/clique.json"} - t.Logf("Initializing geth: %v ", args) - g := runGeth(t, args...) - datadir := g.Datadir - g.WaitExit() - return datadir -} - -// spawns geth with the given command line args. If the args don't set --datadir, the -// child g gets a temporary data directory. -func runGeth(t *testing.T, args ...string) *testgeth { - tt := &testgeth{} - tt.TestCmd = cmdtest.NewTestCmd(t, tt) - for i, arg := range args { - switch arg { - case "--datadir": - if i < len(args)-1 { - tt.Datadir = args[i+1] - } - case "--miner.etherbase": - if i < len(args)-1 { - tt.Etherbase = args[i+1] - } - } - } - if tt.Datadir == "" { - // The temporary datadir will be removed automatically if something fails below. - tt.Datadir = t.TempDir() - args = append([]string{"--datadir", tt.Datadir}, args...) - } - - // Boot "geth". This actually runs the test binary but the TestMain - // function will prevent any tests from running. - tt.Run("geth-test", args...) - - return tt -} - -// waitForEndpoint attempts to connect to an RPC endpoint until it succeeds. -func waitForEndpoint(t *testing.T, endpoint string, timeout time.Duration) { - probe := func() bool { - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - c, err := rpc.DialContext(ctx, endpoint) - if c != nil { - _, err = c.SupportedModules() - c.Close() - } - return err == nil - } - - start := time.Now() - for { - if probe() { - return - } - if time.Since(start) > timeout { - t.Fatal("endpoint", endpoint, "did not open within", timeout) - } - time.Sleep(200 * time.Millisecond) - } -} diff --git a/builder/cmd/geth/snapshot.go b/builder/cmd/geth/snapshot.go deleted file mode 100644 index 4284005a0..000000000 --- a/builder/cmd/geth/snapshot.go +++ /dev/null @@ -1,691 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "os" - "time" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/state/pruner" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - cli "github.com/urfave/cli/v2" -) - -var ( - snapshotCommand = &cli.Command{ - Name: "snapshot", - Usage: "A set of commands based on the snapshot", - Description: "", - Subcommands: []*cli.Command{ - { - Name: "prune-state", - Usage: "Prune stale ethereum state data based on the snapshot", - ArgsUsage: "", - Action: pruneState, - Flags: flags.Merge([]cli.Flag{ - utils.BloomFilterSizeFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot prune-state -will prune historical state data with the help of the state snapshot. -All trie nodes and contract codes that do not belong to the specified -version state will be deleted from the database. After pruning, only -two version states are available: genesis and the specific one. - -The default pruning target is the HEAD-127 state. - -WARNING: it's only supported in hash mode(--state.scheme=hash)". -`, - }, - { - Name: "verify-state", - Usage: "Recalculate state hash based on the snapshot for verification", - ArgsUsage: "", - Action: verifyState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot verify-state -will traverse the whole accounts and storages set based on the specified -snapshot and recalculate the root hash of state for verification. -In other words, this command does the snapshot to trie conversion. -`, - }, - { - Name: "check-dangling-storage", - Usage: "Check that there is no 'dangling' snap storage", - ArgsUsage: "", - Action: checkDanglingStorage, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot check-dangling-storage traverses the snap storage -data, and verifies that all snapshot storage data has a corresponding account. -`, - }, - { - Name: "inspect-account", - Usage: "Check all snapshot layers for the a specific account", - ArgsUsage: "
", - Action: checkAccount, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot inspect-account
checks all snapshot layers and prints out -information about the specified address. -`, - }, - { - Name: "traverse-state", - Usage: "Traverse the state with given root hash and perform quick verification", - ArgsUsage: "", - Action: traverseState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot traverse-state -will traverse the whole state from the given state root and will abort if any -referenced trie node or contract code is missing. This command can be used for -state integrity verification. The default checking target is the HEAD state. - -It's also usable without snapshot enabled. -`, - }, - { - Name: "traverse-rawstate", - Usage: "Traverse the state with given root hash and perform detailed verification", - ArgsUsage: "", - Action: traverseRawState, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth snapshot traverse-rawstate -will traverse the whole state from the given root and will abort if any referenced -trie node or contract code is missing. This command can be used for state integrity -verification. The default checking target is the HEAD state. It's basically identical -to traverse-state, but the check granularity is smaller. - -It's also usable without snapshot enabled. -`, - }, - { - Name: "dump", - Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)", - ArgsUsage: "[? | ]", - Action: dumpState, - Flags: flags.Merge([]cli.Flag{ - utils.ExcludeCodeFlag, - utils.ExcludeStorageFlag, - utils.StartKeyFlag, - utils.DumpLimitFlag, - }, utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -This command is semantically equivalent to 'geth dump', but uses the snapshots -as the backend data source, making this command a lot faster. - -The argument is interpreted as block number or hash. If none is provided, the latest -block is used. -`, - }, - { - Action: snapshotExportPreimages, - Name: "export-preimages", - Usage: "Export the preimage in snapshot enumeration order", - ArgsUsage: " []", - Flags: utils.DatabaseFlags, - Description: ` -The export-preimages command exports hash preimages to a flat file, in exactly -the expected order for the overlay tree migration. -`, - }, - }, - } -) - -// Deprecation: this command should be deprecated once the hash-based -// scheme is deprecated. -func pruneState(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, false) - defer chaindb.Close() - - if rawdb.ReadStateScheme(chaindb) != rawdb.HashScheme { - log.Crit("Offline pruning is not required for path scheme") - } - prunerconfig := pruner.Config{ - Datadir: stack.ResolvePath(""), - BloomSize: ctx.Uint64(utils.BloomFilterSizeFlag.Name), - } - pruner, err := pruner.NewPruner(chaindb, prunerconfig) - if err != nil { - log.Error("Failed to open snapshot tree", "err", err) - return err - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var targetRoot common.Hash - if ctx.NArg() == 1 { - targetRoot, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "err", err) - return err - } - } - if err = pruner.Prune(targetRoot); err != nil { - log.Error("Failed to prune state", "err", err) - return err - } - return nil -} - -func verifyState(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - - headBlock := rawdb.ReadHeadBlock(chaindb) - if headBlock == nil { - log.Error("Failed to load head block") - return errors.New("no head block") - } - triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) - defer triedb.Close() - - snapConfig := snapshot.Config{ - CacheSize: 256, - Recovery: false, - NoBuild: true, - AsyncBuild: false, - } - snaptree, err := snapshot.New(snapConfig, chaindb, triedb, headBlock.Root()) - if err != nil { - log.Error("Failed to open snapshot tree", "err", err) - return err - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var root = headBlock.Root() - if ctx.NArg() == 1 { - root, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "err", err) - return err - } - } - if err := snaptree.Verify(root); err != nil { - log.Error("Failed to verify state", "root", root, "err", err) - return err - } - log.Info("Verified the state", "root", root) - return snapshot.CheckDanglingStorage(chaindb) -} - -// checkDanglingStorage iterates the snap storage data, and verifies that all -// storage also has corresponding account data. -func checkDanglingStorage(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - db := utils.MakeChainDatabase(ctx, stack, true) - defer db.Close() - return snapshot.CheckDanglingStorage(db) -} - -// traverseState is a helper function used for pruning verification. -// Basically it just iterates the trie, ensure all nodes and associated -// contract codes are present. -func traverseState(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - - triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) - defer triedb.Close() - - headBlock := rawdb.ReadHeadBlock(chaindb) - if headBlock == nil { - log.Error("Failed to load head block") - return errors.New("no head block") - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var ( - root common.Hash - err error - ) - if ctx.NArg() == 1 { - root, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "err", err) - return err - } - log.Info("Start traversing the state", "root", root) - } else { - root = headBlock.Root() - log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) - } - t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) - if err != nil { - log.Error("Failed to open trie", "root", root, "err", err) - return err - } - var ( - accounts int - slots int - codes int - lastReport time.Time - start = time.Now() - ) - acctIt, err := t.NodeIterator(nil) - if err != nil { - log.Error("Failed to open iterator", "root", root, "err", err) - return err - } - accIter := trie.NewIterator(acctIt) - for accIter.Next() { - accounts += 1 - var acc types.StateAccount - if err := rlp.DecodeBytes(accIter.Value, &acc); err != nil { - log.Error("Invalid account encountered during traversal", "err", err) - return err - } - if acc.Root != types.EmptyRootHash { - id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root) - storageTrie, err := trie.NewStateTrie(id, triedb) - if err != nil { - log.Error("Failed to open storage trie", "root", acc.Root, "err", err) - return err - } - storageIt, err := storageTrie.NodeIterator(nil) - if err != nil { - log.Error("Failed to open storage iterator", "root", acc.Root, "err", err) - return err - } - storageIter := trie.NewIterator(storageIt) - for storageIter.Next() { - slots += 1 - - if time.Since(lastReport) > time.Second*8 { - log.Info("Traversing state", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - lastReport = time.Now() - } - } - if storageIter.Err != nil { - log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Err) - return storageIter.Err - } - } - if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { - if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { - log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash)) - return errors.New("missing code") - } - codes += 1 - } - if time.Since(lastReport) > time.Second*8 { - log.Info("Traversing state", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - lastReport = time.Now() - } - } - if accIter.Err != nil { - log.Error("Failed to traverse state trie", "root", root, "err", accIter.Err) - return accIter.Err - } - log.Info("State is complete", "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} - -// traverseRawState is a helper function used for pruning verification. -// Basically it just iterates the trie, ensure all nodes and associated -// contract codes are present. It's basically identical to traverseState -// but it will check each trie node. -func traverseRawState(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - - triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) - defer triedb.Close() - - headBlock := rawdb.ReadHeadBlock(chaindb) - if headBlock == nil { - log.Error("Failed to load head block") - return errors.New("no head block") - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var ( - root common.Hash - err error - ) - if ctx.NArg() == 1 { - root, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "err", err) - return err - } - log.Info("Start traversing the state", "root", root) - } else { - root = headBlock.Root() - log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) - } - t, err := trie.NewStateTrie(trie.StateTrieID(root), triedb) - if err != nil { - log.Error("Failed to open trie", "root", root, "err", err) - return err - } - var ( - nodes int - accounts int - slots int - codes int - lastReport time.Time - start = time.Now() - hasher = crypto.NewKeccakState() - got = make([]byte, 32) - ) - accIter, err := t.NodeIterator(nil) - if err != nil { - log.Error("Failed to open iterator", "root", root, "err", err) - return err - } - reader, err := triedb.Reader(root) - if err != nil { - log.Error("State is non-existent", "root", root) - return nil - } - for accIter.Next(true) { - nodes += 1 - node := accIter.Hash() - - // Check the present for non-empty hash node(embedded node doesn't - // have their own hash). - if node != (common.Hash{}) { - blob, _ := reader.Node(common.Hash{}, accIter.Path(), node) - if len(blob) == 0 { - log.Error("Missing trie node(account)", "hash", node) - return errors.New("missing account") - } - hasher.Reset() - hasher.Write(blob) - hasher.Read(got) - if !bytes.Equal(got, node.Bytes()) { - log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob) - return errors.New("invalid account node") - } - } - // If it's a leaf node, yes we are touching an account, - // dig into the storage trie further. - if accIter.Leaf() { - accounts += 1 - var acc types.StateAccount - if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil { - log.Error("Invalid account encountered during traversal", "err", err) - return errors.New("invalid account") - } - if acc.Root != types.EmptyRootHash { - id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root) - storageTrie, err := trie.NewStateTrie(id, triedb) - if err != nil { - log.Error("Failed to open storage trie", "root", acc.Root, "err", err) - return errors.New("missing storage trie") - } - storageIter, err := storageTrie.NodeIterator(nil) - if err != nil { - log.Error("Failed to open storage iterator", "root", acc.Root, "err", err) - return err - } - for storageIter.Next(true) { - nodes += 1 - node := storageIter.Hash() - - // Check the presence for non-empty hash node(embedded node doesn't - // have their own hash). - if node != (common.Hash{}) { - blob, _ := reader.Node(common.BytesToHash(accIter.LeafKey()), storageIter.Path(), node) - if len(blob) == 0 { - log.Error("Missing trie node(storage)", "hash", node) - return errors.New("missing storage") - } - hasher.Reset() - hasher.Write(blob) - hasher.Read(got) - if !bytes.Equal(got, node.Bytes()) { - log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob) - return errors.New("invalid storage node") - } - } - // Bump the counter if it's leaf node. - if storageIter.Leaf() { - slots += 1 - } - if time.Since(lastReport) > time.Second*8 { - log.Info("Traversing state", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - lastReport = time.Now() - } - } - if storageIter.Error() != nil { - log.Error("Failed to traverse storage trie", "root", acc.Root, "err", storageIter.Error()) - return storageIter.Error() - } - } - if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { - if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { - log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey())) - return errors.New("missing code") - } - codes += 1 - } - if time.Since(lastReport) > time.Second*8 { - log.Info("Traversing state", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - lastReport = time.Now() - } - } - } - if accIter.Error() != nil { - log.Error("Failed to traverse state trie", "root", root, "err", accIter.Error()) - return accIter.Error() - } - log.Info("State is complete", "nodes", nodes, "accounts", accounts, "slots", slots, "codes", codes, "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} - -func parseRoot(input string) (common.Hash, error) { - var h common.Hash - if err := h.UnmarshalText([]byte(input)); err != nil { - return h, err - } - return h, nil -} - -func dumpState(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - conf, db, root, err := parseDumpConfig(ctx, stack) - if err != nil { - return err - } - triedb := utils.MakeTrieDatabase(ctx, db, false, true, false) - defer triedb.Close() - - snapConfig := snapshot.Config{ - CacheSize: 256, - Recovery: false, - NoBuild: true, - AsyncBuild: false, - } - snaptree, err := snapshot.New(snapConfig, db, triedb, root) - if err != nil { - return err - } - accIt, err := snaptree.AccountIterator(root, common.BytesToHash(conf.Start)) - if err != nil { - return err - } - defer accIt.Release() - - log.Info("Snapshot dumping started", "root", root) - var ( - start = time.Now() - logged = time.Now() - accounts uint64 - ) - enc := json.NewEncoder(os.Stdout) - enc.Encode(struct { - Root common.Hash `json:"root"` - }{root}) - for accIt.Next() { - account, err := types.FullAccount(accIt.Account()) - if err != nil { - return err - } - da := &state.DumpAccount{ - Balance: account.Balance.String(), - Nonce: account.Nonce, - Root: account.Root.Bytes(), - CodeHash: account.CodeHash, - AddressHash: accIt.Hash().Bytes(), - } - if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { - da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash)) - } - if !conf.SkipStorage { - da.Storage = make(map[common.Hash]string) - - stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{}) - if err != nil { - return err - } - for stIt.Next() { - da.Storage[stIt.Hash()] = common.Bytes2Hex(stIt.Slot()) - } - } - enc.Encode(da) - accounts++ - if time.Since(logged) > 8*time.Second { - log.Info("Snapshot dumping in progress", "at", accIt.Hash(), "accounts", accounts, - "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - if conf.Max > 0 && accounts >= conf.Max { - break - } - } - log.Info("Snapshot dumping complete", "accounts", accounts, - "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} - -// snapshotExportPreimages dumps the preimage data to a flat file. -func snapshotExportPreimages(ctx *cli.Context) error { - if ctx.NArg() < 1 { - utils.Fatalf("This command requires an argument.") - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - - triedb := utils.MakeTrieDatabase(ctx, chaindb, false, true, false) - defer triedb.Close() - - var root common.Hash - if ctx.NArg() > 1 { - rootBytes := common.FromHex(ctx.Args().Get(1)) - if len(rootBytes) != common.HashLength { - return fmt.Errorf("invalid hash: %s", ctx.Args().Get(1)) - } - root = common.BytesToHash(rootBytes) - } else { - headBlock := rawdb.ReadHeadBlock(chaindb) - if headBlock == nil { - log.Error("Failed to load head block") - return errors.New("no head block") - } - root = headBlock.Root() - } - snapConfig := snapshot.Config{ - CacheSize: 256, - Recovery: false, - NoBuild: true, - AsyncBuild: false, - } - snaptree, err := snapshot.New(snapConfig, chaindb, triedb, root) - if err != nil { - return err - } - return utils.ExportSnapshotPreimages(chaindb, snaptree, ctx.Args().First(), root) -} - -// checkAccount iterates the snap data layers, and looks up the given account -// across all layers. -func checkAccount(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return errors.New("need arg") - } - var ( - hash common.Hash - addr common.Address - ) - switch arg := ctx.Args().First(); len(arg) { - case 40, 42: - addr = common.HexToAddress(arg) - hash = crypto.Keccak256Hash(addr.Bytes()) - case 64, 66: - hash = common.HexToHash(arg) - default: - return errors.New("malformed address or hash") - } - stack, _ := makeConfigNode(ctx) - defer stack.Close() - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - start := time.Now() - log.Info("Checking difflayer journal", "address", addr, "hash", hash) - if err := snapshot.CheckJournalAccount(chaindb, hash); err != nil { - return err - } - log.Info("Checked the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start))) - return nil -} diff --git a/builder/cmd/geth/testdata/blockchain.blocks b/builder/cmd/geth/testdata/blockchain.blocks deleted file mode 100644 index d29453d3e..000000000 Binary files a/builder/cmd/geth/testdata/blockchain.blocks and /dev/null differ diff --git a/builder/cmd/geth/testdata/clique.json b/builder/cmd/geth/testdata/clique.json deleted file mode 100644 index b54b4a7d3..000000000 --- a/builder/cmd/geth/testdata/clique.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "config": { - "chainId": 15, - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "clique": { - "period": 5, - "epoch": 30000 - } - }, - "difficulty": "1", - "gasLimit": "8000000", - "extradata": "0x000000000000000000000000000000000000000000000000000000000000000002f0d131f1f97aef08aec6e3291b957d9efe71050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "alloc": { - "02f0d131f1f97aef08aec6e3291b957d9efe7105": { - "balance": "300000" - } - } -} \ No newline at end of file diff --git a/builder/cmd/geth/testdata/empty.js b/builder/cmd/geth/testdata/empty.js deleted file mode 100644 index 8b1378917..000000000 --- a/builder/cmd/geth/testdata/empty.js +++ /dev/null @@ -1 +0,0 @@ - diff --git a/builder/cmd/geth/testdata/guswallet.json b/builder/cmd/geth/testdata/guswallet.json deleted file mode 100644 index e8ea4f332..000000000 --- a/builder/cmd/geth/testdata/guswallet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "encseed": "26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba", - "ethaddr": "d4584b5f6229b7be90727b0fc8c6b91bb427821f", - "email": "gustav.simonsson@gmail.com", - "btcaddr": "1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx" -} diff --git a/builder/cmd/geth/testdata/key.prv b/builder/cmd/geth/testdata/key.prv deleted file mode 100644 index 1d2687ea6..000000000 --- a/builder/cmd/geth/testdata/key.prv +++ /dev/null @@ -1 +0,0 @@ -48aa455c373ec5ce7fefb0e54f44a215decdc85b9047bc4d09801e038909bdbe \ No newline at end of file diff --git a/builder/cmd/geth/testdata/logging/logtest-json.txt b/builder/cmd/geth/testdata/logging/logtest-json.txt deleted file mode 100644 index d2bd0ad91..000000000 --- a/builder/cmd/geth/testdata/logging/logtest-json.txt +++ /dev/null @@ -1,52 +0,0 @@ -{"t":"2023-11-22T15:42:00.407963+08:00","lvl":"info","msg":"big.Int","111,222,333,444,555,678,999":"111222333444555678999"} -{"t":"2023-11-22T15:42:00.408084+08:00","lvl":"info","msg":"-big.Int","-111,222,333,444,555,678,999":"-111222333444555678999"} -{"t":"2023-11-22T15:42:00.408092+08:00","lvl":"info","msg":"big.Int","11,122,233,344,455,567,899,900":"11122233344455567899900"} -{"t":"2023-11-22T15:42:00.408097+08:00","lvl":"info","msg":"-big.Int","-11,122,233,344,455,567,899,900":"-11122233344455567899900"} -{"t":"2023-11-22T15:42:00.408127+08:00","lvl":"info","msg":"uint256","111,222,333,444,555,678,999":"111222333444555678999"} -{"t":"2023-11-22T15:42:00.408133+08:00","lvl":"info","msg":"uint256","11,122,233,344,455,567,899,900":"11122233344455567899900"} -{"t":"2023-11-22T15:42:00.408137+08:00","lvl":"info","msg":"int64","1,000,000":1000000} -{"t":"2023-11-22T15:42:00.408145+08:00","lvl":"info","msg":"int64","-1,000,000":-1000000} -{"t":"2023-11-22T15:42:00.408149+08:00","lvl":"info","msg":"int64","9,223,372,036,854,775,807":9223372036854775807} -{"t":"2023-11-22T15:42:00.408153+08:00","lvl":"info","msg":"int64","-9,223,372,036,854,775,808":-9223372036854775808} -{"t":"2023-11-22T15:42:00.408156+08:00","lvl":"info","msg":"uint64","1,000,000":1000000} -{"t":"2023-11-22T15:42:00.40816+08:00","lvl":"info","msg":"uint64","18,446,744,073,709,551,615":18446744073709551615} -{"t":"2023-11-22T15:42:00.408164+08:00","lvl":"info","msg":"Special chars in value","key":"special \r\n\t chars"} -{"t":"2023-11-22T15:42:00.408167+08:00","lvl":"info","msg":"Special chars in key","special \n\t chars":"value"} -{"t":"2023-11-22T15:42:00.408171+08:00","lvl":"info","msg":"nospace","nospace":"nospace"} -{"t":"2023-11-22T15:42:00.408174+08:00","lvl":"info","msg":"with space","with nospace":"with nospace"} -{"t":"2023-11-22T15:42:00.408178+08:00","lvl":"info","msg":"Bash escapes in value","key":"\u001b[1G\u001b[K\u001b[1A"} -{"t":"2023-11-22T15:42:00.408182+08:00","lvl":"info","msg":"Bash escapes in key","\u001b[1G\u001b[K\u001b[1A":"value"} -{"t":"2023-11-22T15:42:00.408186+08:00","lvl":"info","msg":"Bash escapes in message \u001b[1G\u001b[K\u001b[1A end","key":"value"} -{"t":"2023-11-22T15:42:00.408194+08:00","lvl":"info","msg":"\u001b[35mColored\u001b[0m[","\u001b[35mColored\u001b[0m[":"\u001b[35mColored\u001b[0m["} -{"t":"2023-11-22T15:42:00.408197+08:00","lvl":"info","msg":"an error message with quotes","error":"this is an 'error'"} -{"t":"2023-11-22T15:42:00.408202+08:00","lvl":"info","msg":"Custom Stringer value","2562047h47m16.854s":"2562047h47m16.854s"} -{"t":"2023-11-22T15:42:00.408208+08:00","lvl":"info","msg":"a custom stringer that emits quoted text","output":"output with 'quotes'"} -{"t":"2023-11-22T15:42:00.408219+08:00","lvl":"info","msg":"A message with wonky 💩 characters"} -{"t":"2023-11-22T15:42:00.408222+08:00","lvl":"info","msg":"A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩"} -{"t":"2023-11-22T15:42:00.408226+08:00","lvl":"info","msg":"A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above"} -{"t":"2023-11-22T15:42:00.408229+08:00","lvl":"info","msg":"boolean","true":true,"false":false} -{"t":"2023-11-22T15:42:00.408234+08:00","lvl":"info","msg":"repeated-key 1","foo":"alpha","foo":"beta"} -{"t":"2023-11-22T15:42:00.408237+08:00","lvl":"info","msg":"repeated-key 2","xx":"short","xx":"longer"} -{"t":"2023-11-22T15:42:00.408241+08:00","lvl":"info","msg":"log at level info"} -{"t":"2023-11-22T15:42:00.408244+08:00","lvl":"warn","msg":"log at level warn"} -{"t":"2023-11-22T15:42:00.408247+08:00","lvl":"error","msg":"log at level error"} -{"t":"2023-11-22T15:42:00.408251+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned left"} -{"t":"2023-11-22T15:42:00.408254+08:00","lvl":"info","msg":"test","bar":"a long message","a":1} -{"t":"2023-11-22T15:42:00.408258+08:00","lvl":"info","msg":"test","bar":"short","a":"aligned right"} -{"t":"2023-11-22T15:42:00.408261+08:00","lvl":"info","msg":"The following logs should align so that the key-fields make 5 columns"} -{"t":"2023-11-22T15:42:00.408275+08:00","lvl":"info","msg":"Inserted known block","number":1012,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","txs":200,"gas":1123123,"other":"first"} -{"t":"2023-11-22T15:42:00.408281+08:00","lvl":"info","msg":"Inserted new block","number":1,"hash":"0x0000000000000000000000000000000000000000000000000000000000001235","txs":2,"gas":1123,"other":"second"} -{"t":"2023-11-22T15:42:00.408287+08:00","lvl":"info","msg":"Inserted known block","number":99,"hash":"0x0000000000000000000000000000000000000000000000000000000000012322","txs":10,"gas":1,"other":"third"} -{"t":"2023-11-22T15:42:00.408296+08:00","lvl":"warn","msg":"Inserted known block","number":1012,"hash":"0x0000000000000000000000000000000000000000000000000000000000001234","txs":200,"gas":99,"other":"fourth"} -{"t":"2023-11-22T15:42:00.4083+08:00","lvl":"info","msg":"(*big.Int)(nil)","":""} -{"t":"2023-11-22T15:42:00.408303+08:00","lvl":"info","msg":"(*uint256.Int)(nil)","":""} -{"t":"2023-11-22T15:42:00.408311+08:00","lvl":"info","msg":"(fmt.Stringer)(nil)","res":null} -{"t":"2023-11-22T15:42:00.408318+08:00","lvl":"info","msg":"nil-concrete-stringer","res":""} -{"t":"2023-11-22T15:42:00.408322+08:00","lvl":"info","msg":"error(nil) ","res":null} -{"t":"2023-11-22T15:42:00.408326+08:00","lvl":"info","msg":"nil-concrete-error","res":""} -{"t":"2023-11-22T15:42:00.408334+08:00","lvl":"info","msg":"nil-custom-struct","res":null} -{"t":"2023-11-22T15:42:00.40835+08:00","lvl":"info","msg":"raw nil","res":null} -{"t":"2023-11-22T15:42:00.408354+08:00","lvl":"info","msg":"(*uint64)(nil)","res":null} -{"t":"2023-11-22T15:42:00.408361+08:00","lvl":"info","msg":"Using keys 't', 'lvl', 'time', 'level' and 'msg'","t":"t","time":"time","lvl":"lvl","level":"level","msg":"msg"} -{"t":"2023-11-29T15:13:00.195655931+01:00","lvl":"info","msg":"Odd pair (1 attr)","key":null,"LOG_ERROR":"Normalized odd number of arguments by adding nil"} -{"t":"2023-11-29T15:13:00.195681832+01:00","lvl":"info","msg":"Odd pair (3 attr)","key":"value","key2":null,"LOG_ERROR":"Normalized odd number of arguments by adding nil"} diff --git a/builder/cmd/geth/testdata/logging/logtest-logfmt.txt b/builder/cmd/geth/testdata/logging/logtest-logfmt.txt deleted file mode 100644 index 5c5316b7d..000000000 --- a/builder/cmd/geth/testdata/logging/logtest-logfmt.txt +++ /dev/null @@ -1,52 +0,0 @@ -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=big.Int 111,222,333,444,555,678,999=111222333444555678999 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=-big.Int -111,222,333,444,555,678,999=-111222333444555678999 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=big.Int 11,122,233,344,455,567,899,900=11122233344455567899900 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=-big.Int -11,122,233,344,455,567,899,900=-11122233344455567899900 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint256 111,222,333,444,555,678,999=111222333444555678999 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint256 11,122,233,344,455,567,899,900=11122233344455567899900 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 1,000,000=1000000 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 -1,000,000=-1000000 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 9,223,372,036,854,775,807=9223372036854775807 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=int64 -9,223,372,036,854,775,808=-9223372036854775808 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint64 1,000,000=1000000 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=uint64 18,446,744,073,709,551,615=18446744073709551615 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Special chars in value" key="special \r\n\t chars" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Special chars in key" "special \n\t chars"=value -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nospace nospace=nospace -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="with space" "with nospace"="with nospace" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in value" key="\x1b[1G\x1b[K\x1b[1A" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in key" "\x1b[1G\x1b[K\x1b[1A"=value -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m[" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="an error message with quotes" error="this is an 'error'" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Custom Stringer value" 2562047h47m16.854s=2562047h47m16.854s -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="a custom stringer that emits quoted text" output="output with 'quotes'" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A message with wonky 💩 characters" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="A multiline message \nLALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=boolean true=true false=false -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 1" foo=alpha foo=beta -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="repeated-key 2" xx=short xx=longer -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="log at level info" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=warn msg="log at level warn" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=error msg="log at level error" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned left" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar="a long message" a=1 -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=test bar=short a="aligned right" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="The following logs should align so that the key-fields make 5 columns" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=1123123 other=first -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted new block" number=1 hash=0x0000000000000000000000000000000000000000000000000000000000001235 txs=2 gas=1123 other=second -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Inserted known block" number=99 hash=0x0000000000000000000000000000000000000000000000000000000000012322 txs=10 gas=1 other=third -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=warn msg="Inserted known block" number=1012 hash=0x0000000000000000000000000000000000000000000000000000000000001234 txs=200 gas=99 other=fourth -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*big.Int)(nil) = -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*uint256.Int)(nil) = -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(fmt.Stringer)(nil) res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-concrete-stringer res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="error(nil) " res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-concrete-error res="" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=nil-custom-struct res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="raw nil" res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg=(*uint64)(nil) res= -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Using keys 't', 'lvl', 'time', 'level' and 'msg'" t=t time=time lvl=lvl level=level msg=msg -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Odd pair (1 attr)" key= LOG_ERROR="Normalized odd number of arguments by adding nil" -t=xxxx-xx-xxTxx:xx:xx+xxxx lvl=info msg="Odd pair (3 attr)" key=value key2= LOG_ERROR="Normalized odd number of arguments by adding nil" diff --git a/builder/cmd/geth/testdata/logging/logtest-terminal.txt b/builder/cmd/geth/testdata/logging/logtest-terminal.txt deleted file mode 100644 index e3b562117..000000000 --- a/builder/cmd/geth/testdata/logging/logtest-terminal.txt +++ /dev/null @@ -1,53 +0,0 @@ -INFO [xx-xx|xx:xx:xx.xxx] big.Int 111,222,333,444,555,678,999=111,222,333,444,555,678,999 -INFO [xx-xx|xx:xx:xx.xxx] -big.Int -111,222,333,444,555,678,999=-111,222,333,444,555,678,999 -INFO [xx-xx|xx:xx:xx.xxx] big.Int 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900 -INFO [xx-xx|xx:xx:xx.xxx] -big.Int -11,122,233,344,455,567,899,900=-11,122,233,344,455,567,899,900 -INFO [xx-xx|xx:xx:xx.xxx] uint256 111,222,333,444,555,678,999=111,222,333,444,555,678,999 -INFO [xx-xx|xx:xx:xx.xxx] uint256 11,122,233,344,455,567,899,900=11,122,233,344,455,567,899,900 -INFO [xx-xx|xx:xx:xx.xxx] int64 1,000,000=1,000,000 -INFO [xx-xx|xx:xx:xx.xxx] int64 -1,000,000=-1,000,000 -INFO [xx-xx|xx:xx:xx.xxx] int64 9,223,372,036,854,775,807=9,223,372,036,854,775,807 -INFO [xx-xx|xx:xx:xx.xxx] int64 -9,223,372,036,854,775,808=-9,223,372,036,854,775,808 -INFO [xx-xx|xx:xx:xx.xxx] uint64 1,000,000=1,000,000 -INFO [xx-xx|xx:xx:xx.xxx] uint64 18,446,744,073,709,551,615=18,446,744,073,709,551,615 -INFO [xx-xx|xx:xx:xx.xxx] Special chars in value key="special \r\n\t chars" -INFO [xx-xx|xx:xx:xx.xxx] Special chars in key "special \n\t chars"=value -INFO [xx-xx|xx:xx:xx.xxx] nospace nospace=nospace -INFO [xx-xx|xx:xx:xx.xxx] with space "with nospace"="with nospace" -INFO [xx-xx|xx:xx:xx.xxx] Bash escapes in value key="\x1b[1G\x1b[K\x1b[1A" -INFO [xx-xx|xx:xx:xx.xxx] Bash escapes in key "\x1b[1G\x1b[K\x1b[1A"=value -INFO [xx-xx|xx:xx:xx.xxx] "Bash escapes in message \x1b[1G\x1b[K\x1b[1A end" key=value -INFO [xx-xx|xx:xx:xx.xxx] "\x1b[35mColored\x1b[0m[" "\x1b[35mColored\x1b[0m["="\x1b[35mColored\x1b[0m[" -INFO [xx-xx|xx:xx:xx.xxx] an error message with quotes error="this is an 'error'" -INFO [xx-xx|xx:xx:xx.xxx] Custom Stringer value 2562047h47m16.854s=2562047h47m16.854s -INFO [xx-xx|xx:xx:xx.xxx] a custom stringer that emits quoted text output="output with 'quotes'" -INFO [xx-xx|xx:xx:xx.xxx] "A message with wonky 💩 characters" -INFO [xx-xx|xx:xx:xx.xxx] "A multiline message \nINFO [10-18|14:11:31.106] with wonky characters 💩" -INFO [xx-xx|xx:xx:xx.xxx] A multiline message -LALA [ZZZZZZZZZZZZZZZZZZ] Actually part of message above -INFO [xx-xx|xx:xx:xx.xxx] boolean true=true false=false -INFO [xx-xx|xx:xx:xx.xxx] repeated-key 1 foo=alpha foo=beta -INFO [xx-xx|xx:xx:xx.xxx] repeated-key 2 xx=short xx=longer -INFO [xx-xx|xx:xx:xx.xxx] log at level info -WARN [xx-xx|xx:xx:xx.xxx] log at level warn -ERROR[xx-xx|xx:xx:xx.xxx] log at level error -INFO [xx-xx|xx:xx:xx.xxx] test bar=short a="aligned left" -INFO [xx-xx|xx:xx:xx.xxx] test bar="a long message" a=1 -INFO [xx-xx|xx:xx:xx.xxx] test bar=short a="aligned right" -INFO [xx-xx|xx:xx:xx.xxx] The following logs should align so that the key-fields make 5 columns -INFO [xx-xx|xx:xx:xx.xxx] Inserted known block number=1012 hash=000000..001234 txs=200 gas=1,123,123 other=first -INFO [xx-xx|xx:xx:xx.xxx] Inserted new block number=1 hash=000000..001235 txs=2 gas=1123 other=second -INFO [xx-xx|xx:xx:xx.xxx] Inserted known block number=99 hash=000000..012322 txs=10 gas=1 other=third -WARN [xx-xx|xx:xx:xx.xxx] Inserted known block number=1012 hash=000000..001234 txs=200 gas=99 other=fourth -INFO [xx-xx|xx:xx:xx.xxx] (*big.Int)(nil) = -INFO [xx-xx|xx:xx:xx.xxx] (*uint256.Int)(nil) = -INFO [xx-xx|xx:xx:xx.xxx] (fmt.Stringer)(nil) res= -INFO [xx-xx|xx:xx:xx.xxx] nil-concrete-stringer res= -INFO [xx-xx|xx:xx:xx.xxx] error(nil) res= -INFO [xx-xx|xx:xx:xx.xxx] nil-concrete-error res= -INFO [xx-xx|xx:xx:xx.xxx] nil-custom-struct res= -INFO [xx-xx|xx:xx:xx.xxx] raw nil res= -INFO [xx-xx|xx:xx:xx.xxx] (*uint64)(nil) res= -INFO [xx-xx|xx:xx:xx.xxx] Using keys 't', 'lvl', 'time', 'level' and 'msg' t=t time=time lvl=lvl level=level msg=msg -INFO [xx-xx|xx:xx:xx.xxx] Odd pair (1 attr) key= LOG_ERROR="Normalized odd number of arguments by adding nil" -INFO [xx-xx|xx:xx:xx.xxx] Odd pair (3 attr) key=value key2= LOG_ERROR="Normalized odd number of arguments by adding nil" diff --git a/builder/cmd/geth/testdata/password.txt b/builder/cmd/geth/testdata/password.txt deleted file mode 100644 index f6ea04951..000000000 --- a/builder/cmd/geth/testdata/password.txt +++ /dev/null @@ -1 +0,0 @@ -foobar \ No newline at end of file diff --git a/builder/cmd/geth/testdata/passwords.txt b/builder/cmd/geth/testdata/passwords.txt deleted file mode 100644 index 96f98c7f4..000000000 --- a/builder/cmd/geth/testdata/passwords.txt +++ /dev/null @@ -1,3 +0,0 @@ -foobar -foobar -foobar diff --git a/builder/cmd/geth/testdata/vcheck/data.json b/builder/cmd/geth/testdata/vcheck/data.json deleted file mode 100644 index e7ee2bf7e..000000000 --- a/builder/cmd/geth/testdata/vcheck/data.json +++ /dev/null @@ -1,61 +0,0 @@ -[ - { - "name": "CorruptedDAG", - "uid": "GETH-2020-01", - "summary": "Mining nodes will generate erroneous PoW on epochs > `385`.", - "description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.", - "links": [ - "https://github.com/ethereum/go-ethereum/pull/21793", - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49" - ], - "introduced": "v1.6.0", - "fixed": "v1.9.24", - "published": "2020-11-12", - "severity": "Medium", - "check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.2(1|2|3)-.*" - }, - { - "name": "GoCrash", - "uid": "GETH-2020-02", - "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`", - "description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM", - "https://github.com/golang/go/issues/42552" - ], - "fixed": "v1.9.24", - "published": "2020-11-12", - "severity": "Critical", - "check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$" - }, - { - "name": "ShallowCopy", - "uid": "GETH-2020-03", - "summary": "A consensus flaw in Geth, related to `datacopy` precompile", - "description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/" - ], - "introduced": "v1.9.7", - "fixed": "v1.9.17", - "published": "2020-11-12", - "severity": "Critical", - "check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$" - }, - { - "name": "GethCrash", - "uid": "GETH-2020-04", - "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing", - "description": "Full details to be disclosed at a later date", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/" - ], - "introduced": "v1.9.16", - "fixed": "v1.9.18", - "published": "2020-11-12", - "severity": "Critical", - "check": "Geth\\/v1\\.9.(16|17).*$" - } -] diff --git a/builder/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig b/builder/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig deleted file mode 100644 index eaea9f905..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisig-sigs-new/data.json.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RUQkliYstQBOKLK05Sy5f3bVRMBqJT26ABo6Vbp3BNJAVjejoqYCu4GWE/+7qcDfHBqYIniDCbFIUvYEnOHxV6vZ93wO1xJWDQw= -trusted comment: timestamp:1693986492 file:data.json hashed -6Fdw2H+W1ZXK7QXSF77Z5AWC7+AEFAfDmTSxNGylU5HLT1AuSJQmxslj+VjtUBamYCvOuET7plbXza942AlWDw== diff --git a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 b/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 deleted file mode 100644 index f9066d4fe..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: timestamp:1605618622 file:vulnerabilities.json -osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ== diff --git a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 b/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 deleted file mode 100644 index a89a83d21..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: Here's a comment -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: Here's a trusted comment -3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 b/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 deleted file mode 100644 index 6fd33b19a..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: One more (untrusted) comment -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: Here's a trusted comment -3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/builder/cmd/geth/testdata/vcheck/minisign.pub b/builder/cmd/geth/testdata/vcheck/minisign.pub deleted file mode 100644 index 183dce5f6..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisign.pub +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign public key 284E00B52C269624 -RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp diff --git a/builder/cmd/geth/testdata/vcheck/minisign.sec b/builder/cmd/geth/testdata/vcheck/minisign.sec deleted file mode 100644 index 5c50715b2..000000000 --- a/builder/cmd/geth/testdata/vcheck/minisign.sec +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: minisign encrypted secret key -RWRTY0Iyz8kmPMKrqk6DCtlO9a33akKiaOQG1aLolqDxs52qvPoAAAACAAAAAAAAAEAAAAAArEiggdvyn6+WzTprirLtgiYQoU+ihz/HyGgjhuF+Pz2ddMduyCO+xjCHeq+vgVVW039fbsI8hW6LRGJZLBKV5/jdxCXAVVQE7qTQ6xpEdO0z8Z731/pV1hlspQXG2PNd16NMtwd9dWw= diff --git a/builder/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig b/builder/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig deleted file mode 100644 index 3d5fcacf9..000000000 --- a/builder/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: verify with ./signifykey.pub -RWSKLNhZb0KdAbhRUhW2LQZXdnwttu2SYhM9EuC4mMgOJB85h7/YIPupf8/ldTs4N8e9Y/fhgdY40q5LQpt5IFC62fq0v8U1/w8= diff --git a/builder/cmd/geth/testdata/vcheck/signifykey.pub b/builder/cmd/geth/testdata/vcheck/signifykey.pub deleted file mode 100644 index 328f973ab..000000000 --- a/builder/cmd/geth/testdata/vcheck/signifykey.pub +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: signify public key -RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/ diff --git a/builder/cmd/geth/testdata/vcheck/signifykey.sec b/builder/cmd/geth/testdata/vcheck/signifykey.sec deleted file mode 100644 index 3279a2e58..000000000 --- a/builder/cmd/geth/testdata/vcheck/signifykey.sec +++ /dev/null @@ -1,2 +0,0 @@ -untrusted comment: signify secret key -RWRCSwAAACpLQDLawSQCtI7eAVIvaiHzjTsTyJsfV5aKLNhZb0KdAWeICXJGa93/bHAcsY6jUh9I8RdEcDWEoGxmaXZC+IdVBPxDpkix9fBRGEUdKWHi3dOfqME0YRzErWI5AVg3cRw= diff --git a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 b/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 deleted file mode 100644 index f9066d4fe..000000000 --- a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: timestamp:1605618622 file:vulnerabilities.json -osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ== diff --git a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 b/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 deleted file mode 100644 index a89a83d21..000000000 --- a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: Here's a comment -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: Here's a trusted comment -3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 b/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 deleted file mode 100644 index 6fd33b19a..000000000 --- a/builder/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: One more (untrusted) comment -RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= -trusted comment: Here's a trusted comment -3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/builder/cmd/geth/testdata/vcheck/vulnerabilities.json b/builder/cmd/geth/testdata/vcheck/vulnerabilities.json deleted file mode 100644 index bee0e66dd..000000000 --- a/builder/cmd/geth/testdata/vcheck/vulnerabilities.json +++ /dev/null @@ -1,170 +0,0 @@ -[ - { - "name": "CorruptedDAG", - "uid": "GETH-2020-01", - "summary": "Mining nodes will generate erroneous PoW on epochs > `385`.", - "description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.", - "links": [ - "https://github.com/ethereum/go-ethereum/pull/21793", - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49", - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-v592-xf75-856p" - ], - "introduced": "v1.6.0", - "fixed": "v1.9.24", - "published": "2020-11-12", - "severity": "Medium", - "CVE": "CVE-2020-26240", - "check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.\\d-.*|Geth\\/v1\\.9\\.1.*|Geth\\/v1\\.9\\.2(0|1|2|3)-.*" - }, - { - "name": "Denial of service due to Go CVE-2020-28362", - "uid": "GETH-2020-02", - "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`", - "description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM", - "https://github.com/golang/go/issues/42552", - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-m6gx-rhvj-fh52" - ], - "introduced": "v0.0.0", - "fixed": "v1.9.24", - "published": "2020-11-12", - "severity": "Critical", - "CVE": "CVE-2020-28362", - "check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$" - }, - { - "name": "ShallowCopy", - "uid": "GETH-2020-03", - "summary": "A consensus flaw in Geth, related to `datacopy` precompile", - "description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-69v6-xc2j-r2jf" - ], - "introduced": "v1.9.7", - "fixed": "v1.9.17", - "published": "2020-11-12", - "severity": "Critical", - "CVE": "CVE-2020-26241", - "check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$" - }, - { - "name": "Geth DoS via MULMOD", - "uid": "GETH-2020-04", - "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing", - "description": "Affected versions suffer from a vulnerability which can be exploited through the `MULMOD` operation, by specifying a modulo of `0`: `mulmod(a,b,0)`, causing a `panic` in the underlying library. \nThe crash was in the `uint256` library, where a buffer [underflowed](https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L442).\n\n\tif `d == 0`, `dLen` remains `0`\n\nand https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L451 will try to access index `[-1]`.\n\nThe `uint256` library was first merged in this [commit](https://github.com/ethereum/go-ethereum/commit/cf6674539c589f80031f3371a71c6a80addbe454), on 2020-06-08. \nExploiting this vulnerabilty would cause all vulnerable nodes to drop off the network. \n\nThe issue was brought to our attention through a [bug report](https://github.com/ethereum/go-ethereum/issues/21367), showing a `panic` occurring on sync from genesis on the Ropsten network.\n \nIt was estimated that the least obvious way to fix this would be to merge the fix into `uint256`, make a new release of that library and then update the geth-dependency.\n", - "links": [ - "https://blog.ethereum.org/2020/11/12/geth_security_release/", - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m", - "https://github.com/holiman/uint256/releases/tag/v1.1.1", - "https://github.com/holiman/uint256/pull/80", - "https://github.com/ethereum/go-ethereum/pull/21368" - ], - "introduced": "v1.9.16", - "fixed": "v1.9.18", - "published": "2020-11-12", - "severity": "Critical", - "CVE": "CVE-2020-26242", - "check": "Geth\\/v1\\.9.(16|17).*$" - }, - { - "name": "LES Server DoS via GetProofsV2", - "uid": "GETH-2020-05", - "summary": "A DoS vulnerability can make a LES server crash.", - "description": "A DoS vulnerability can make a LES server crash via malicious GetProofsV2 request from a connected LES client.\n\nThe vulnerability was patched in #21896.\n\nThis vulnerability only concern users explicitly running geth as a light server", - "links": [ - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-r33q-22hv-j29q", - "https://github.com/ethereum/go-ethereum/pull/21896" - ], - "introduced": "v1.8.0", - "fixed": "v1.9.25", - "published": "2020-12-10", - "severity": "Medium", - "CVE": "CVE-2020-26264", - "check": "(Geth\\/v1\\.8\\.*)|(Geth\\/v1\\.9\\.\\d-.*)|(Geth\\/v1\\.9\\.1\\d-.*)|(Geth\\/v1\\.9\\.(20|21|22|23|24)-.*)$" - }, - { - "name": "SELFDESTRUCT-recreate consensus flaw", - "uid": "GETH-2020-06", - "introduced": "v1.9.4", - "fixed": "v1.9.20", - "summary": "A consensus-vulnerability in Geth could cause a chain split, where vulnerable versions refuse to accept the canonical chain.", - "description": "A flaw was repoted at 2020-08-11 by John Youngseok Yang (Software Platform Lab), where a particular sequence of transactions could cause a consensus failure.\n\n- Tx 1:\n - `sender` invokes `caller`.\n - `caller` invokes `0xaa`. `0xaa` has 3 wei, does a self-destruct-to-self\n - `caller` does a `1 wei` -call to `0xaa`, who thereby has 1 wei (the code in `0xaa` still executed, since the tx is still ongoing, but doesn't redo the selfdestruct, it takes a different path if callvalue is non-zero)\n\n-Tx 2:\n - `sender` does a 5-wei call to 0xaa. No exec (since no code). \n\nIn geth, the result would be that `0xaa` had `6 wei`, whereas OE reported (correctly) `5` wei. Furthermore, in geth, if the second tx was not executed, the `0xaa` would be destructed, resulting in `0 wei`. Thus obviously wrong. \n\nIt was determined that the root cause was this [commit](https://github.com/ethereum/go-ethereum/commit/223b950944f494a5b4e0957fd9f92c48b09037ad) from [this PR](https://github.com/ethereum/go-ethereum/pull/19953). The semantics of `createObject` was subtly changd, into returning a non-nil object (with `deleted=true`) where it previously did not if the account had been destructed. This return value caused the new object to inherit the old `balance`.\n", - "links": [ - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4" - ], - "published": "2020-12-10", - "severity": "High", - "CVE": "CVE-2020-26265", - "check": "(Geth\\/v1\\.9\\.(4|5|6|7|8|9)-.*)|(Geth\\/v1\\.9\\.1\\d-.*)$" - }, - { - "name": "Not ready for London upgrade", - "uid": "GETH-2021-01", - "summary": "The client is not ready for the 'London' technical upgrade, and will deviate from the canonical chain when the London upgrade occurs (at block '12965000' around August 4, 2021.", - "description": "At (or around) August 4, Ethereum will undergo a technical upgrade called 'London'. Clients not upgraded will fail to progress on the canonical chain.", - "links": [ - "https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md", - "https://notes.ethereum.org/@timbeiko/ropsten-postmortem" - ], - "introduced": "v1.10.1", - "fixed": "v1.10.6", - "published": "2021-07-22", - "severity": "High", - "check": "(Geth\\/v1\\.10\\.(1|2|3|4|5)-.*)$" - }, - { - "name": "RETURNDATA corruption via datacopy", - "uid": "GETH-2021-02", - "summary": "A consensus-flaw in the Geth EVM could cause a node to deviate from the canonical chain.", - "description": "A memory-corruption bug within the EVM can cause a consensus error, where vulnerable nodes obtain a different `stateRoot` when processing a maliciously crafted transaction. This, in turn, would lead to the chain being split: mainnet splitting in two forks.\n\nAll Geth versions supporting the London hard fork are vulnerable (the bug is older than London), so all users should update.\n\nThis bug was exploited on Mainnet at block 13107518.\n\nCredits for the discovery go to @guidovranken (working for Sentnl during an audit of the Telos EVM) and reported via bounty@ethereum.org.", - "links": [ - "https://github.com/ethereum/go-ethereum/blob/master/docs/postmortems/2021-08-22-split-postmortem.md", - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-9856-9gg9-qcmq", - "https://github.com/ethereum/go-ethereum/releases/tag/v1.10.8" - ], - "introduced": "v1.10.0", - "fixed": "v1.10.8", - "published": "2021-08-24", - "severity": "High", - "CVE": "CVE-2021-39137", - "check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7)-.*)$" - }, - { - "name": "DoS via malicious `snap/1` request", - "uid": "GETH-2021-03", - "summary": "A vulnerable node is susceptible to crash when processing a maliciously crafted message from a peer, via the snap/1 protocol. The crash can be triggered by sending a malicious snap/1 GetTrieNodes package.", - "description": "The `snap/1` protocol handler contains two vulnerabilities related to the `GetTrieNodes` packet, which can be exploited to crash the node. Full details are available at the Github security [advisory](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-59hh-656j-3p7v)", - "links": [ - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-59hh-656j-3p7v", - "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities", - "https://github.com/ethereum/go-ethereum/pull/23657" - ], - "introduced": "v1.10.0", - "fixed": "v1.10.9", - "published": "2021-10-24", - "severity": "Medium", - "CVE": "CVE-2021-41173", - "check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7|8)-.*)$" - }, - { - "name": "DoS via malicious p2p message", - "uid": "GETH-2022-01", - "summary": "A vulnerable node can crash via p2p messages sent from an attacker node, if running with non-default log options.", - "description": "A vulnerable node, if configured to use high verbosity logging, can be made to crash when handling specially crafted p2p messages sent from an attacker node. Full details are available at the Github security [advisory](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-wjxw-gh3m-7pm5)", - "links": [ - "https://github.com/ethereum/go-ethereum/security/advisories/GHSA-wjxw-gh3m-7pm5", - "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities", - "https://github.com/ethereum/go-ethereum/pull/24507" - ], - "introduced": "v1.10.0", - "fixed": "v1.10.17", - "published": "2022-05-11", - "severity": "Low", - "CVE": "CVE-2022-29177", - "check": "(Geth\\/v1\\.10\\.(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16)-.*)$" - } -] diff --git a/builder/cmd/geth/testdata/wrong-passwords.txt b/builder/cmd/geth/testdata/wrong-passwords.txt deleted file mode 100644 index 7d1e338bb..000000000 --- a/builder/cmd/geth/testdata/wrong-passwords.txt +++ /dev/null @@ -1,3 +0,0 @@ -wrong -wrong -wrong diff --git a/builder/cmd/geth/verkle.go b/builder/cmd/geth/verkle.go deleted file mode 100644 index 420b063d8..000000000 --- a/builder/cmd/geth/verkle.go +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2022 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "os" - - "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/gballet/go-verkle" - cli "github.com/urfave/cli/v2" -) - -var ( - zero [32]byte - - verkleCommand = &cli.Command{ - Name: "verkle", - Usage: "A set of experimental verkle tree management commands", - Description: "", - Subcommands: []*cli.Command{ - { - Name: "verify", - Usage: "verify the conversion of a MPT into a verkle tree", - ArgsUsage: "", - Action: verifyVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth verkle verify -This command takes a root commitment and attempts to rebuild the tree. - `, - }, - { - Name: "dump", - Usage: "Dump a verkle tree to a DOT file", - ArgsUsage: " [ ...]", - Action: expandVerkle, - Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags), - Description: ` -geth verkle dump [ ...] -This command will produce a dot file representing the tree, rooted at . -in which key1, key2, ... are expanded. - `, - }, - }, - } -) - -// recurse into each child to ensure they can be loaded from the db. The tree isn't rebuilt -// (only its nodes are loaded) so there is no need to flush them, the garbage collector should -// take care of that for us. -func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error { - switch node := root.(type) { - case *verkle.InternalNode: - for i, child := range node.Children() { - childC := child.Commit().Bytes() - - childS, err := resolver(childC[:]) - if bytes.Equal(childC[:], zero[:]) { - continue - } - if err != nil { - return fmt.Errorf("could not find child %x in db: %w", childC, err) - } - // depth is set to 0, the tree isn't rebuilt so it's not a problem - childN, err := verkle.ParseNode(childS, 0) - if err != nil { - return fmt.Errorf("decode error child %x in db: %w", child.Commitment().Bytes(), err) - } - if err := checkChildren(childN, resolver); err != nil { - return fmt.Errorf("%x%w", i, err) // write the path to the erroring node - } - } - case *verkle.LeafNode: - // sanity check: ensure at least one value is non-zero - - for i := 0; i < verkle.NodeWidth; i++ { - if len(node.Value(i)) != 0 { - return nil - } - } - return errors.New("both balance and nonce are 0") - case verkle.Empty: - // nothing to do - default: - return fmt.Errorf("unsupported type encountered %v", root) - } - - return nil -} - -func verifyVerkle(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - headBlock := rawdb.ReadHeadBlock(chaindb) - if headBlock == nil { - log.Error("Failed to load head block") - return errors.New("no head block") - } - if ctx.NArg() > 1 { - log.Error("Too many arguments given") - return errors.New("too many arguments") - } - var ( - rootC common.Hash - err error - ) - if ctx.NArg() == 1 { - rootC, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "error", err) - return err - } - log.Info("Rebuilding the tree", "root", rootC) - } else { - rootC = headBlock.Root() - log.Info("Rebuilding the tree", "root", rootC, "number", headBlock.NumberU64()) - } - - serializedRoot, err := chaindb.Get(rootC[:]) - if err != nil { - return err - } - root, err := verkle.ParseNode(serializedRoot, 0) - if err != nil { - return err - } - - if err := checkChildren(root, chaindb.Get); err != nil { - log.Error("Could not rebuild the tree from the database", "err", err) - return err - } - - log.Info("Tree was rebuilt from the database") - return nil -} - -func expandVerkle(ctx *cli.Context) error { - stack, _ := makeConfigNode(ctx) - defer stack.Close() - - chaindb := utils.MakeChainDatabase(ctx, stack, true) - defer chaindb.Close() - var ( - rootC common.Hash - keylist [][]byte - err error - ) - if ctx.NArg() >= 2 { - rootC, err = parseRoot(ctx.Args().First()) - if err != nil { - log.Error("Failed to resolve state root", "error", err) - return err - } - keylist = make([][]byte, 0, ctx.Args().Len()-1) - args := ctx.Args().Slice() - for i := range args[1:] { - key, err := hex.DecodeString(args[i+1]) - log.Info("decoded key", "arg", args[i+1], "key", key) - if err != nil { - return fmt.Errorf("error decoding key #%d: %w", i+1, err) - } - keylist = append(keylist, key) - } - log.Info("Rebuilding the tree", "root", rootC) - } else { - return fmt.Errorf("usage: %s root key1 [key 2...]", ctx.App.Name) - } - - serializedRoot, err := chaindb.Get(rootC[:]) - if err != nil { - return err - } - root, err := verkle.ParseNode(serializedRoot, 0) - if err != nil { - return err - } - - for i, key := range keylist { - log.Info("Reading key", "index", i, "key", keylist[0]) - root.Get(key, chaindb.Get) - } - - if err := os.WriteFile("dump.dot", []byte(verkle.ToDot(root)), 0600); err != nil { - log.Error("Failed to dump file", "err", err) - } else { - log.Info("Tree was dumped to file", "file", "dump.dot") - } - return nil -} diff --git a/builder/cmd/geth/version_check.go b/builder/cmd/geth/version_check.go deleted file mode 100644 index 237556788..000000000 --- a/builder/cmd/geth/version_check.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "os" - "regexp" - "strings" - - "github.com/ethereum/go-ethereum/log" - "github.com/jedisct1/go-minisign" - "github.com/urfave/cli/v2" -) - -var gethPubKeys []string = []string{ - //@holiman, minisign public key FB1D084D39BAEC24 - "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", - //minisign public key 138B1CA303E51687 - "RWSHFuUDoxyLEzjszuWZI1xStS66QTyXFFZG18uDfO26CuCsbckX1e9J", - //minisign public key FD9813B2D2098484 - "RWSEhAnSshOY/b+GmaiDkObbCWefsAoavjoLcPjBo1xn71yuOH5I+Lts", -} - -type vulnJson struct { - Name string - Uid string - Summary string - Description string - Links []string - Introduced string - Fixed string - Published string - Severity string - Check string - CVE string -} - -func versionCheck(ctx *cli.Context) error { - url := ctx.String(VersionCheckUrlFlag.Name) - version := ctx.String(VersionCheckVersionFlag.Name) - log.Info("Checking vulnerabilities", "version", version, "url", url) - return checkCurrent(url, version) -} - -func checkCurrent(url, current string) error { - var ( - data []byte - sig []byte - err error - ) - if data, err = fetch(url); err != nil { - return fmt.Errorf("could not retrieve data: %w", err) - } - if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil { - return fmt.Errorf("could not retrieve signature: %w", err) - } - if err = verifySignature(gethPubKeys, data, sig); err != nil { - return err - } - var vulns []vulnJson - if err = json.Unmarshal(data, &vulns); err != nil { - return err - } - allOk := true - for _, vuln := range vulns { - r, err := regexp.Compile(vuln.Check) - if err != nil { - return err - } - if r.MatchString(current) { - allOk = false - fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name) - fmt.Printf("Severity: %v\n", vuln.Severity) - fmt.Printf("Summary : %v\n", vuln.Summary) - fmt.Printf("Fixed in: %v\n", vuln.Fixed) - if len(vuln.CVE) > 0 { - fmt.Printf("CVE: %v\n", vuln.CVE) - } - if len(vuln.Links) > 0 { - fmt.Printf("References:\n") - for _, ref := range vuln.Links { - fmt.Printf("\t- %v\n", ref) - } - } - fmt.Println() - } - } - if allOk { - fmt.Println("No vulnerabilities found") - } - return nil -} - -// fetch makes an HTTP request to the given url and returns the response body -func fetch(url string) ([]byte, error) { - if filep := strings.TrimPrefix(url, "file://"); filep != url { - return os.ReadFile(filep) - } - res, err := http.Get(url) - if err != nil { - return nil, err - } - defer res.Body.Close() - body, err := io.ReadAll(res.Body) - if err != nil { - return nil, err - } - return body, nil -} - -// verifySignature checks that the sigData is a valid signature of the given -// data, for pubkey GethPubkey -func verifySignature(pubkeys []string, data, sigdata []byte) error { - sig, err := minisign.DecodeSignature(string(sigdata)) - if err != nil { - return err - } - // find the used key - var key *minisign.PublicKey - for _, pubkey := range pubkeys { - pub, err := minisign.NewPublicKey(pubkey) - if err != nil { - // our pubkeys should be parseable - return err - } - if pub.KeyId != sig.KeyId { - continue - } - key = &pub - break - } - if key == nil { - log.Info("Signing key not trusted", "keyid", keyID(sig.KeyId), "error", err) - return errors.New("signature could not be verified") - } - if ok, err := key.Verify(data, sig); !ok || err != nil { - log.Info("Verification failed error", "keyid", keyID(key.KeyId), "error", err) - return errors.New("signature could not be verified") - } - return nil -} - -// keyID turns a binary minisign key ID into a hex string. -// Note: key IDs are printed in reverse byte order. -func keyID(id [8]byte) string { - var rev [8]byte - for i := range id { - rev[len(rev)-1-i] = id[i] - } - return fmt.Sprintf("%X", rev) -} diff --git a/builder/cmd/geth/version_check_test.go b/builder/cmd/geth/version_check_test.go deleted file mode 100644 index 3676d25d0..000000000 --- a/builder/cmd/geth/version_check_test.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "regexp" - "strconv" - "strings" - "testing" - - "github.com/jedisct1/go-minisign" -) - -func TestVerification(t *testing.T) { - t.Parallel() - // Signatures generated with `minisign`. Legacy format, not pre-hashed file. - t.Run("minisig-legacy", func(t *testing.T) { - t.Parallel() - // For this test, the pubkey is in testdata/vcheck/minisign.pub - // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' ) - pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" - testVerification(t, pub, "./testdata/vcheck/minisig-sigs/") - }) - t.Run("minisig-new", func(t *testing.T) { - t.Parallel() - // For this test, the pubkey is in testdata/vcheck/minisign.pub - // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' ) - // `minisign -S -s ./minisign.sec -m data.json -x ./minisig-sigs-new/data.json.minisig` - pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" - testVerification(t, pub, "./testdata/vcheck/minisig-sigs-new/") - }) - // Signatures generated with `signify-openbsd` - t.Run("signify-openbsd", func(t *testing.T) { - t.Parallel() - t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2") - // For this test, the pubkey is in testdata/vcheck/signifykey.pub - // (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' ) - pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/" - testVerification(t, pub, "./testdata/vcheck/signify-sigs/") - }) -} - -func testVerification(t *testing.T, pubkey, sigdir string) { - // Data to verify - data, err := os.ReadFile("./testdata/vcheck/data.json") - if err != nil { - t.Fatal(err) - } - // Signatures, with and without comments, both trusted and untrusted - files, err := os.ReadDir(sigdir) - if err != nil { - t.Fatal(err) - } - if len(files) == 0 { - t.Fatal("Missing tests") - } - for _, f := range files { - sig, err := os.ReadFile(filepath.Join(sigdir, f.Name())) - if err != nil { - t.Fatal(err) - } - err = verifySignature([]string{pubkey}, data, sig) - if err != nil { - t.Fatal(err) - } - } -} - -func versionUint(v string) int { - mustInt := func(s string) int { - a, err := strconv.Atoi(s) - if err != nil { - panic(v) - } - return a - } - components := strings.Split(strings.TrimPrefix(v, "v"), ".") - a := mustInt(components[0]) - b := mustInt(components[1]) - c := mustInt(components[2]) - return a*100*100 + b*100 + c -} - -// TestMatching can be used to check that the regexps are correct -func TestMatching(t *testing.T) { - t.Parallel() - data, _ := os.ReadFile("./testdata/vcheck/vulnerabilities.json") - var vulns []vulnJson - if err := json.Unmarshal(data, &vulns); err != nil { - t.Fatal(err) - } - check := func(version string) { - vFull := fmt.Sprintf("Geth/%v-unstable-15339cf1-20201204/linux-amd64/go1.15.4", version) - for _, vuln := range vulns { - r, err := regexp.Compile(vuln.Check) - vulnIntro := versionUint(vuln.Introduced) - vulnFixed := versionUint(vuln.Fixed) - current := versionUint(version) - if err != nil { - t.Fatal(err) - } - if vuln.Name == "Denial of service due to Go CVE-2020-28362" { - // this one is not tied to geth-versions - continue - } - if vulnIntro <= current && vulnFixed > current { - // Should be vulnerable - if !r.MatchString(vFull) { - t.Errorf("Should be vulnerable, version %v, intro: %v, fixed: %v %v %v", - version, vuln.Introduced, vuln.Fixed, vuln.Name, vuln.Check) - } - } else { - if r.MatchString(vFull) { - t.Errorf("Should not be flagged vulnerable, version %v, intro: %v, fixed: %v %v %d %d %d", - version, vuln.Introduced, vuln.Fixed, vuln.Name, vulnIntro, current, vulnFixed) - } - } - } - } - for major := 1; major < 2; major++ { - for minor := 0; minor < 30; minor++ { - for patch := 0; patch < 30; patch++ { - vShort := fmt.Sprintf("v%d.%d.%d", major, minor, patch) - check(vShort) - } - } - } -} - -func TestGethPubKeysParseable(t *testing.T) { - t.Parallel() - for _, pubkey := range gethPubKeys { - _, err := minisign.NewPublicKey(pubkey) - if err != nil { - t.Errorf("Should be parseable") - } - } -} - -func TestKeyID(t *testing.T) { - t.Parallel() - type args struct { - id [8]byte - } - tests := []struct { - name string - args args - want string - }{ - {"@holiman key", args{id: extractKeyId(gethPubKeys[0])}, "FB1D084D39BAEC24"}, - {"second key", args{id: extractKeyId(gethPubKeys[1])}, "138B1CA303E51687"}, - {"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := keyID(tt.args.id); got != tt.want { - t.Errorf("keyID() = %v, want %v", got, tt.want) - } - }) - } -} - -func extractKeyId(pubkey string) [8]byte { - p, _ := minisign.NewPublicKey(pubkey) - return p.KeyId -} diff --git a/builder/cmd/p2psim/main.go b/builder/cmd/p2psim/main.go deleted file mode 100644 index a0f5f0d28..000000000 --- a/builder/cmd/p2psim/main.go +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright 2017 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// p2psim provides a command-line client for a simulation HTTP API. -// -// Here is an example of creating a 2 node network with the first node -// connected to the second: -// -// $ p2psim node create -// Created node01 -// -// $ p2psim node start node01 -// Started node01 -// -// $ p2psim node create -// Created node02 -// -// $ p2psim node start node02 -// Started node02 -// -// $ p2psim node connect node01 node02 -// Connected node01 to node02 -package main - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "strings" - "text/tabwriter" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/simulations" - "github.com/ethereum/go-ethereum/p2p/simulations/adapters" - "github.com/ethereum/go-ethereum/rpc" - "github.com/urfave/cli/v2" -) - -var client *simulations.Client - -var ( - // global command flags - apiFlag = &cli.StringFlag{ - Name: "api", - Value: "http://localhost:8888", - Usage: "simulation API URL", - EnvVars: []string{"P2PSIM_API_URL"}, - } - - // events subcommand flags - currentFlag = &cli.BoolFlag{ - Name: "current", - Usage: "get existing nodes and conns first", - } - filterFlag = &cli.StringFlag{ - Name: "filter", - Value: "", - Usage: "message filter", - } - - // node create subcommand flags - nameFlag = &cli.StringFlag{ - Name: "name", - Value: "", - Usage: "node name", - } - servicesFlag = &cli.StringFlag{ - Name: "services", - Value: "", - Usage: "node services (comma separated)", - } - keyFlag = &cli.StringFlag{ - Name: "key", - Value: "", - Usage: "node private key (hex encoded)", - } - - // node rpc subcommand flags - subscribeFlag = &cli.BoolFlag{ - Name: "subscribe", - Usage: "method is a subscription", - } -) - -func main() { - app := flags.NewApp("devp2p simulation command-line client") - app.Flags = []cli.Flag{ - apiFlag, - } - app.Before = func(ctx *cli.Context) error { - client = simulations.NewClient(ctx.String(apiFlag.Name)) - return nil - } - app.Commands = []*cli.Command{ - { - Name: "show", - Usage: "show network information", - Action: showNetwork, - }, - { - Name: "events", - Usage: "stream network events", - Action: streamNetwork, - Flags: []cli.Flag{ - currentFlag, - filterFlag, - }, - }, - { - Name: "snapshot", - Usage: "create a network snapshot to stdout", - Action: createSnapshot, - }, - { - Name: "load", - Usage: "load a network snapshot from stdin", - Action: loadSnapshot, - }, - { - Name: "node", - Usage: "manage simulation nodes", - Action: listNodes, - Subcommands: []*cli.Command{ - { - Name: "list", - Usage: "list nodes", - Action: listNodes, - }, - { - Name: "create", - Usage: "create a node", - Action: createNode, - Flags: []cli.Flag{ - nameFlag, - servicesFlag, - keyFlag, - }, - }, - { - Name: "show", - ArgsUsage: "", - Usage: "show node information", - Action: showNode, - }, - { - Name: "start", - ArgsUsage: "", - Usage: "start a node", - Action: startNode, - }, - { - Name: "stop", - ArgsUsage: "", - Usage: "stop a node", - Action: stopNode, - }, - { - Name: "connect", - ArgsUsage: " ", - Usage: "connect a node to a peer node", - Action: connectNode, - }, - { - Name: "disconnect", - ArgsUsage: " ", - Usage: "disconnect a node from a peer node", - Action: disconnectNode, - }, - { - Name: "rpc", - ArgsUsage: " []", - Usage: "call a node RPC method", - Action: rpcNode, - Flags: []cli.Flag{ - subscribeFlag, - }, - }, - }, - }, - } - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func showNetwork(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - network, err := client.GetNetwork() - if err != nil { - return err - } - w := tabwriter.NewWriter(ctx.App.Writer, 1, 2, 2, ' ', 0) - defer w.Flush() - fmt.Fprintf(w, "NODES\t%d\n", len(network.Nodes)) - fmt.Fprintf(w, "CONNS\t%d\n", len(network.Conns)) - return nil -} - -func streamNetwork(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - events := make(chan *simulations.Event) - sub, err := client.SubscribeNetwork(events, simulations.SubscribeOpts{ - Current: ctx.Bool(currentFlag.Name), - Filter: ctx.String(filterFlag.Name), - }) - if err != nil { - return err - } - defer sub.Unsubscribe() - enc := json.NewEncoder(ctx.App.Writer) - for { - select { - case event := <-events: - if err := enc.Encode(event); err != nil { - return err - } - case err := <-sub.Err(): - return err - } - } -} - -func createSnapshot(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - snap, err := client.CreateSnapshot() - if err != nil { - return err - } - return json.NewEncoder(os.Stdout).Encode(snap) -} - -func loadSnapshot(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - snap := &simulations.Snapshot{} - if err := json.NewDecoder(os.Stdin).Decode(snap); err != nil { - return err - } - return client.LoadSnapshot(snap) -} - -func listNodes(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodes, err := client.GetNodes() - if err != nil { - return err - } - w := tabwriter.NewWriter(ctx.App.Writer, 1, 2, 2, ' ', 0) - defer w.Flush() - fmt.Fprintf(w, "NAME\tPROTOCOLS\tID\n") - for _, node := range nodes { - fmt.Fprintf(w, "%s\t%s\t%s\n", node.Name, strings.Join(protocolList(node), ","), node.ID) - } - return nil -} - -func protocolList(node *p2p.NodeInfo) []string { - protos := make([]string, 0, len(node.Protocols)) - for name := range node.Protocols { - protos = append(protos, name) - } - return protos -} - -func createNode(ctx *cli.Context) error { - if ctx.NArg() != 0 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - config := adapters.RandomNodeConfig() - config.Name = ctx.String(nameFlag.Name) - if key := ctx.String(keyFlag.Name); key != "" { - privKey, err := crypto.HexToECDSA(key) - if err != nil { - return err - } - config.ID = enode.PubkeyToIDV4(&privKey.PublicKey) - config.PrivateKey = privKey - } - if services := ctx.String(servicesFlag.Name); services != "" { - config.Lifecycles = strings.Split(services, ",") - } - node, err := client.CreateNode(config) - if err != nil { - return err - } - fmt.Fprintln(ctx.App.Writer, "Created", node.Name) - return nil -} - -func showNode(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodeName := ctx.Args().First() - node, err := client.GetNode(nodeName) - if err != nil { - return err - } - w := tabwriter.NewWriter(ctx.App.Writer, 1, 2, 2, ' ', 0) - defer w.Flush() - fmt.Fprintf(w, "NAME\t%s\n", node.Name) - fmt.Fprintf(w, "PROTOCOLS\t%s\n", strings.Join(protocolList(node), ",")) - fmt.Fprintf(w, "ID\t%s\n", node.ID) - fmt.Fprintf(w, "ENODE\t%s\n", node.Enode) - for name, proto := range node.Protocols { - fmt.Fprintln(w) - fmt.Fprintf(w, "--- PROTOCOL INFO: %s\n", name) - fmt.Fprintf(w, "%v\n", proto) - fmt.Fprintf(w, "---\n") - } - return nil -} - -func startNode(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodeName := ctx.Args().First() - if err := client.StartNode(nodeName); err != nil { - return err - } - fmt.Fprintln(ctx.App.Writer, "Started", nodeName) - return nil -} - -func stopNode(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodeName := ctx.Args().First() - if err := client.StopNode(nodeName); err != nil { - return err - } - fmt.Fprintln(ctx.App.Writer, "Stopped", nodeName) - return nil -} - -func connectNode(ctx *cli.Context) error { - if ctx.NArg() != 2 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - args := ctx.Args() - nodeName := args.Get(0) - peerName := args.Get(1) - if err := client.ConnectNode(nodeName, peerName); err != nil { - return err - } - fmt.Fprintln(ctx.App.Writer, "Connected", nodeName, "to", peerName) - return nil -} - -func disconnectNode(ctx *cli.Context) error { - args := ctx.Args() - if args.Len() != 2 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodeName := args.Get(0) - peerName := args.Get(1) - if err := client.DisconnectNode(nodeName, peerName); err != nil { - return err - } - fmt.Fprintln(ctx.App.Writer, "Disconnected", nodeName, "from", peerName) - return nil -} - -func rpcNode(ctx *cli.Context) error { - args := ctx.Args() - if args.Len() < 2 { - return cli.ShowCommandHelp(ctx, ctx.Command.Name) - } - nodeName := args.Get(0) - method := args.Get(1) - rpcClient, err := client.RPCClient(context.Background(), nodeName) - if err != nil { - return err - } - if ctx.Bool(subscribeFlag.Name) { - return rpcSubscribe(rpcClient, ctx.App.Writer, method, args.Slice()[3:]...) - } - var result interface{} - params := make([]interface{}, len(args.Slice()[3:])) - for i, v := range args.Slice()[3:] { - params[i] = v - } - if err := rpcClient.Call(&result, method, params...); err != nil { - return err - } - return json.NewEncoder(ctx.App.Writer).Encode(result) -} - -func rpcSubscribe(client *rpc.Client, out io.Writer, method string, args ...string) error { - namespace, method, _ := strings.Cut(method, "_") - ch := make(chan interface{}) - subArgs := make([]interface{}, len(args)+1) - subArgs[0] = method - for i, v := range args { - subArgs[i+1] = v - } - sub, err := client.Subscribe(context.Background(), namespace, ch, subArgs...) - if err != nil { - return err - } - defer sub.Unsubscribe() - enc := json.NewEncoder(out) - for { - select { - case v := <-ch: - if err := enc.Encode(v); err != nil { - return err - } - case err := <-sub.Err(): - return err - } - } -} diff --git a/builder/cmd/rlpdump/main.go b/builder/cmd/rlpdump/main.go deleted file mode 100644 index 7e1d314d4..000000000 --- a/builder/cmd/rlpdump/main.go +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// rlpdump is a pretty-printer for RLP data. -package main - -import ( - "bufio" - "bytes" - "container/list" - "encoding/hex" - "flag" - "fmt" - "io" - "math" - "os" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rlp" -) - -var ( - hexMode = flag.String("hex", "", "dump given hex data") - reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp") - noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably") - single = flag.Bool("single", false, "print only the first element, discard the rest") - showpos = flag.Bool("pos", false, "display element byte posititions") -) - -func init() { - flag.Usage = func() { - fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex ][-reverse] [filename]") - flag.PrintDefaults() - fmt.Fprintln(os.Stderr, ` -Dumps RLP data from the given file in readable form. -If the filename is omitted, data is read from stdin.`) - } -} - -func main() { - flag.Parse() - - var r *inStream - switch { - case *hexMode != "": - data, err := hex.DecodeString(strings.TrimPrefix(*hexMode, "0x")) - if err != nil { - die(err) - } - r = newInStream(bytes.NewReader(data), int64(len(data))) - - case flag.NArg() == 0: - r = newInStream(bufio.NewReader(os.Stdin), 0) - - case flag.NArg() == 1: - fd, err := os.Open(flag.Arg(0)) - if err != nil { - die(err) - } - defer fd.Close() - var size int64 - finfo, err := fd.Stat() - if err == nil { - size = finfo.Size() - } - r = newInStream(bufio.NewReader(fd), size) - - default: - fmt.Fprintln(os.Stderr, "Error: too many arguments") - flag.Usage() - os.Exit(2) - } - - out := os.Stdout - if *reverseMode { - data, err := textToRlp(r) - if err != nil { - die(err) - } - fmt.Printf("%#x\n", data) - return - } else { - err := rlpToText(r, out) - if err != nil { - die(err) - } - } -} - -func rlpToText(in *inStream, out io.Writer) error { - stream := rlp.NewStream(in, 0) - for { - if err := dump(in, stream, 0, out); err != nil { - if err != io.EOF { - return err - } - break - } - fmt.Fprintln(out) - if *single { - break - } - } - return nil -} - -func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error { - if *showpos { - fmt.Fprintf(out, "%s: ", in.posLabel()) - } - kind, size, err := s.Kind() - if err != nil { - return err - } - switch kind { - case rlp.Byte, rlp.String: - str, err := s.Bytes() - if err != nil { - return err - } - if len(str) == 0 || !*noASCII && isASCII(str) { - fmt.Fprintf(out, "%s%q", ws(depth), str) - } else { - fmt.Fprintf(out, "%s%x", ws(depth), str) - } - case rlp.List: - s.List() - defer s.ListEnd() - if size == 0 { - fmt.Fprintf(out, ws(depth)+"[]") - } else { - fmt.Fprintln(out, ws(depth)+"[") - for i := 0; ; i++ { - if i > 0 { - fmt.Fprint(out, ",\n") - } - if err := dump(in, s, depth+1, out); err == rlp.EOL { - break - } else if err != nil { - return err - } - } - fmt.Fprint(out, ws(depth)+"]") - } - } - return nil -} - -func isASCII(b []byte) bool { - for _, c := range b { - if c < 32 || c > 126 { - return false - } - } - return true -} - -func ws(n int) string { - return strings.Repeat(" ", n) -} - -func die(args ...interface{}) { - fmt.Fprintln(os.Stderr, args...) - os.Exit(1) -} - -// textToRlp converts text into RLP (best effort). -func textToRlp(r io.Reader) ([]byte, error) { - // We're expecting the input to be well-formed, meaning that - // - each element is on a separate line - // - each line is either an (element OR a list start/end) + comma - // - an element is either hex-encoded bytes OR a quoted string - var ( - scanner = bufio.NewScanner(r) - obj []interface{} - stack = list.New() - ) - for scanner.Scan() { - t := strings.TrimSpace(scanner.Text()) - if len(t) == 0 { - continue - } - switch t { - case "[": // list start - stack.PushFront(obj) - obj = make([]interface{}, 0) - case "]", "],": // list end - parent := stack.Remove(stack.Front()).([]interface{}) - obj = append(parent, obj) - case "[],": // empty list - obj = append(obj, make([]interface{}, 0)) - default: // element - data := []byte(t)[:len(t)-1] // cut off comma - if data[0] == '"' { // ascii string - data = []byte(t)[1 : len(data)-1] - } else { // hex data - data = common.FromHex(string(data)) - } - obj = append(obj, data) - } - } - if err := scanner.Err(); err != nil { - return nil, err - } - data, err := rlp.EncodeToBytes(obj[0]) - return data, err -} - -type inStream struct { - br rlp.ByteReader - pos int - columns int -} - -func newInStream(br rlp.ByteReader, totalSize int64) *inStream { - col := int(math.Ceil(math.Log10(float64(totalSize)))) - return &inStream{br: br, columns: col} -} - -func (rc *inStream) Read(b []byte) (n int, err error) { - n, err = rc.br.Read(b) - rc.pos += n - return n, err -} - -func (rc *inStream) ReadByte() (byte, error) { - b, err := rc.br.ReadByte() - if err == nil { - rc.pos++ - } - return b, err -} - -func (rc *inStream) posLabel() string { - l := strconv.FormatInt(int64(rc.pos), 10) - if len(l) < rc.columns { - l = strings.Repeat(" ", rc.columns-len(l)) + l - } - return l -} diff --git a/builder/cmd/rlpdump/rlpdump_test.go b/builder/cmd/rlpdump/rlpdump_test.go deleted file mode 100644 index 4b0ae680a..000000000 --- a/builder/cmd/rlpdump/rlpdump_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package main - -import ( - "bytes" - "fmt" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -func TestRoundtrip(t *testing.T) { - t.Parallel() - for i, want := range []string{ - "0xf880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28", - "0xd5c0d3cb84746573742a2a808213378667617a6f6e6b", - "0xc780c0c1c0825208", - } { - var out strings.Builder - in := newInStream(bytes.NewReader(common.FromHex(want)), 0) - err := rlpToText(in, &out) - if err != nil { - t.Fatal(err) - } - text := out.String() - rlpBytes, err := textToRlp(strings.NewReader(text)) - if err != nil { - t.Errorf("test %d: error %v", i, err) - continue - } - have := fmt.Sprintf("%#x", rlpBytes) - if have != want { - t.Errorf("test %d: have\n%v\nwant:\n%v\n", i, have, want) - } - } -} - -func TestTextToRlp(t *testing.T) { - t.Parallel() - type tc struct { - text string - want string - } - cases := []tc{ - { - text: `[ - "", - [], -[ - [], - ], - 5208, -]`, - want: "0xc780c0c1c0825208", - }, - } - for i, tc := range cases { - have, err := textToRlp(strings.NewReader(tc.text)) - if err != nil { - t.Errorf("test %d: error %v", i, err) - continue - } - if hexutil.Encode(have) != tc.want { - t.Errorf("test %d:\nhave %v\nwant %v", i, hexutil.Encode(have), tc.want) - } - } -} diff --git a/builder/cmd/utils/cmd.go b/builder/cmd/utils/cmd.go deleted file mode 100644 index 4b5716466..000000000 --- a/builder/cmd/utils/cmd.go +++ /dev/null @@ -1,866 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// Package utils contains internal helper functions for go-ethereum commands. -package utils - -import ( - "bufio" - "bytes" - "compress/gzip" - "crypto/sha256" - "errors" - "fmt" - "io" - "os" - "os/signal" - "path" - "runtime" - "strings" - "syscall" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/debug" - "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/urfave/cli/v2" -) - -const ( - importBatchSize = 2500 -) - -// Fatalf formats a message to standard error and exits the program. -// The message is also printed to standard output if standard error -// is redirected to a different file. -func Fatalf(format string, args ...interface{}) { - w := io.MultiWriter(os.Stdout, os.Stderr) - if runtime.GOOS == "windows" { - // The SameFile check below doesn't work on Windows. - // stdout is unlikely to get redirected though, so just print there. - w = os.Stdout - } else { - outf, _ := os.Stdout.Stat() - errf, _ := os.Stderr.Stat() - if outf != nil && errf != nil && os.SameFile(outf, errf) { - w = os.Stderr - } - } - fmt.Fprintf(w, "Fatal: "+format+"\n", args...) - os.Exit(1) -} - -func StartNode(ctx *cli.Context, stack *node.Node, isConsole bool) { - if err := stack.Start(); err != nil { - Fatalf("Error starting protocol stack: %v", err) - } - go func() { - sigc := make(chan os.Signal, 1) - signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(sigc) - - minFreeDiskSpace := 2 * ethconfig.Defaults.TrieDirtyCache // Default 2 * 256Mb - if ctx.IsSet(MinFreeDiskSpaceFlag.Name) { - minFreeDiskSpace = ctx.Int(MinFreeDiskSpaceFlag.Name) - } else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { - minFreeDiskSpace = 2 * ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 - } - if minFreeDiskSpace > 0 { - go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024) - } - - shutdown := func() { - log.Info("Got interrupt, shutting down...") - go stack.Close() - for i := 10; i > 0; i-- { - <-sigc - if i > 1 { - log.Warn("Already shutting down, interrupt more to panic.", "times", i-1) - } - } - debug.Exit() // ensure trace and CPU profile data is flushed. - debug.LoudPanic("boom") - } - - if isConsole { - // In JS console mode, SIGINT is ignored because it's handled by the console. - // However, SIGTERM still shuts down the node. - for { - sig := <-sigc - if sig == syscall.SIGTERM { - shutdown() - return - } - } - } else { - <-sigc - shutdown() - } - }() -} - -func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritical uint64) { - if path == "" { - return - } - for { - freeSpace, err := getFreeDiskSpace(path) - if err != nil { - log.Warn("Failed to get free disk space", "path", path, "err", err) - break - } - if freeSpace < freeDiskSpaceCritical { - log.Error("Low disk space. Gracefully shutting down Geth to prevent database corruption.", "available", common.StorageSize(freeSpace), "path", path) - sigc <- syscall.SIGTERM - break - } else if freeSpace < 2*freeDiskSpaceCritical { - log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical), "path", path) - } - time.Sleep(30 * time.Second) - } -} - -func ImportChain(chain *core.BlockChain, fn string) error { - // Watch for Ctrl-C while the import is running. - // If a signal is received, the import will stop at the next batch. - interrupt := make(chan os.Signal, 1) - stop := make(chan struct{}) - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) - defer signal.Stop(interrupt) - defer close(interrupt) - go func() { - if _, ok := <-interrupt; ok { - log.Info("Interrupted during import, stopping at next batch") - } - close(stop) - }() - checkInterrupt := func() bool { - select { - case <-stop: - return true - default: - return false - } - } - - log.Info("Importing blockchain", "file", fn) - - // Open the file handle and potentially unwrap the gzip stream - fh, err := os.Open(fn) - if err != nil { - return err - } - defer fh.Close() - - var reader io.Reader = fh - if strings.HasSuffix(fn, ".gz") { - if reader, err = gzip.NewReader(reader); err != nil { - return err - } - } - stream := rlp.NewStream(reader, 0) - - // Run actual the import. - blocks := make(types.Blocks, importBatchSize) - n := 0 - for batch := 0; ; batch++ { - // Load a batch of RLP blocks. - if checkInterrupt() { - return errors.New("interrupted") - } - i := 0 - for ; i < importBatchSize; i++ { - var b types.Block - if err := stream.Decode(&b); err == io.EOF { - break - } else if err != nil { - return fmt.Errorf("at block %d: %v", n, err) - } - // don't import first block - if b.NumberU64() == 0 { - i-- - continue - } - blocks[i] = &b - n++ - } - if i == 0 { - break - } - // Import the batch. - if checkInterrupt() { - return errors.New("interrupted") - } - missing := missingBlocks(chain, blocks[:i]) - if len(missing) == 0 { - log.Info("Skipping batch as all blocks present", "batch", batch, "first", blocks[0].Hash(), "last", blocks[i-1].Hash()) - continue - } - if failindex, err := chain.InsertChain(missing); err != nil { - var failnumber uint64 - if failindex > 0 && failindex < len(missing) { - failnumber = missing[failindex].NumberU64() - } else { - failnumber = missing[0].NumberU64() - } - return fmt.Errorf("invalid block %d: %v", failnumber, err) - } - } - return nil -} - -func readList(filename string) ([]string, error) { - b, err := os.ReadFile(filename) - if err != nil { - return nil, err - } - return strings.Split(string(b), "\n"), nil -} - -// ImportHistory imports Era1 files containing historical block information, -// starting from genesis. -func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, network string) error { - if chain.CurrentSnapBlock().Number.BitLen() != 0 { - return fmt.Errorf("history import only supported when starting from genesis") - } - entries, err := era.ReadDir(dir, network) - if err != nil { - return fmt.Errorf("error reading %s: %w", dir, err) - } - checksums, err := readList(path.Join(dir, "checksums.txt")) - if err != nil { - return fmt.Errorf("unable to read checksums.txt: %w", err) - } - if len(checksums) != len(entries) { - return fmt.Errorf("expected equal number of checksums and entries, have: %d checksums, %d entries", len(checksums), len(entries)) - } - var ( - start = time.Now() - reported = time.Now() - imported = 0 - forker = core.NewForkChoice(chain, nil) - h = sha256.New() - buf = bytes.NewBuffer(nil) - ) - for i, filename := range entries { - err := func() error { - f, err := os.Open(path.Join(dir, filename)) - if err != nil { - return fmt.Errorf("unable to open era: %w", err) - } - defer f.Close() - - // Validate checksum. - if _, err := io.Copy(h, f); err != nil { - return fmt.Errorf("unable to recalculate checksum: %w", err) - } - if have, want := common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex(), checksums[i]; have != want { - return fmt.Errorf("checksum mismatch: have %s, want %s", have, want) - } - h.Reset() - buf.Reset() - - // Import all block data from Era1. - e, err := era.From(f) - if err != nil { - return fmt.Errorf("error opening era: %w", err) - } - it, err := era.NewIterator(e) - if err != nil { - return fmt.Errorf("error making era reader: %w", err) - } - for it.Next() { - block, err := it.Block() - if err != nil { - return fmt.Errorf("error reading block %d: %w", it.Number(), err) - } - if block.Number().BitLen() == 0 { - continue // skip genesis - } - receipts, err := it.Receipts() - if err != nil { - return fmt.Errorf("error reading receipts %d: %w", it.Number(), err) - } - if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start, forker); err != nil { - return fmt.Errorf("error inserting header %d: %w", it.Number(), err) - } else if status != core.CanonStatTy { - return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status) - } - if _, err := chain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{receipts}, 2^64-1); err != nil { - return fmt.Errorf("error inserting body %d: %w", it.Number(), err) - } - imported += 1 - - // Give the user some feedback that something is happening. - if time.Since(reported) >= 8*time.Second { - log.Info("Importing Era files", "head", it.Number(), "imported", imported, "elapsed", common.PrettyDuration(time.Since(start))) - imported = 0 - reported = time.Now() - } - } - return nil - }() - if err != nil { - return err - } - } - - return nil -} - -func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block { - head := chain.CurrentBlock() - for i, block := range blocks { - // If we're behind the chain head, only check block, state is available at head - if head.Number.Uint64() > block.NumberU64() { - if !chain.HasBlock(block.Hash(), block.NumberU64()) { - return blocks[i:] - } - continue - } - // If we're above the chain head, state availability is a must - if !chain.HasBlockAndState(block.Hash(), block.NumberU64()) { - return blocks[i:] - } - } - return nil -} - -// ExportChain exports a blockchain into the specified file, truncating any data -// already present in the file. -func ExportChain(blockchain *core.BlockChain, fn string) error { - log.Info("Exporting blockchain", "file", fn) - - // Open the file handle and potentially wrap with a gzip stream - fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return err - } - defer fh.Close() - - var writer io.Writer = fh - if strings.HasSuffix(fn, ".gz") { - writer = gzip.NewWriter(writer) - defer writer.(*gzip.Writer).Close() - } - // Iterate over the blocks and export them - if err := blockchain.Export(writer); err != nil { - return err - } - log.Info("Exported blockchain", "file", fn) - - return nil -} - -// ExportAppendChain exports a blockchain into the specified file, appending to -// the file if data already exists in it. -func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error { - log.Info("Exporting blockchain", "file", fn) - - // Open the file handle and potentially wrap with a gzip stream - fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm) - if err != nil { - return err - } - defer fh.Close() - - var writer io.Writer = fh - if strings.HasSuffix(fn, ".gz") { - writer = gzip.NewWriter(writer) - defer writer.(*gzip.Writer).Close() - } - // Iterate over the blocks and export them - if err := blockchain.ExportN(writer, first, last); err != nil { - return err - } - log.Info("Exported blockchain to", "file", fn) - return nil -} - -// ExportHistory exports blockchain history into the specified directory, -// following the Era format. -func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) error { - log.Info("Exporting blockchain history", "dir", dir) - if head := bc.CurrentBlock().Number.Uint64(); head < last { - log.Warn("Last block beyond head, setting last = head", "head", head, "last", last) - last = head - } - network := "unknown" - if name, ok := params.NetworkNames[bc.Config().ChainID.String()]; ok { - network = name - } - if err := os.MkdirAll(dir, os.ModePerm); err != nil { - return fmt.Errorf("error creating output directory: %w", err) - } - var ( - start = time.Now() - reported = time.Now() - h = sha256.New() - buf = bytes.NewBuffer(nil) - checksums []string - ) - for i := first; i <= last; i += step { - err := func() error { - filename := path.Join(dir, era.Filename(network, int(i/step), common.Hash{})) - f, err := os.Create(filename) - if err != nil { - return fmt.Errorf("could not create era file: %w", err) - } - defer f.Close() - - w := era.NewBuilder(f) - for j := uint64(0); j < step && j <= last-i; j++ { - var ( - n = i + j - block = bc.GetBlockByNumber(n) - ) - if block == nil { - return fmt.Errorf("export failed on #%d: not found", n) - } - receipts := bc.GetReceiptsByHash(block.Hash()) - if receipts == nil { - return fmt.Errorf("export failed on #%d: receipts not found", n) - } - td := bc.GetTd(block.Hash(), block.NumberU64()) - if td == nil { - return fmt.Errorf("export failed on #%d: total difficulty not found", n) - } - if err := w.Add(block, receipts, td); err != nil { - return err - } - } - root, err := w.Finalize() - if err != nil { - return fmt.Errorf("export failed to finalize %d: %w", step/i, err) - } - // Set correct filename with root. - os.Rename(filename, path.Join(dir, era.Filename(network, int(i/step), root))) - - // Compute checksum of entire Era1. - if _, err := f.Seek(0, io.SeekStart); err != nil { - return err - } - if _, err := io.Copy(h, f); err != nil { - return fmt.Errorf("unable to calculate checksum: %w", err) - } - checksums = append(checksums, common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex()) - h.Reset() - buf.Reset() - return nil - }() - if err != nil { - return err - } - if time.Since(reported) >= 8*time.Second { - log.Info("Exporting blocks", "exported", i, "elapsed", common.PrettyDuration(time.Since(start))) - reported = time.Now() - } - } - - os.WriteFile(path.Join(dir, "checksums.txt"), []byte(strings.Join(checksums, "\n")), os.ModePerm) - - log.Info("Exported blockchain to", "dir", dir) - - return nil -} - -// ImportPreimages imports a batch of exported hash preimages into the database. -// It's a part of the deprecated functionality, should be removed in the future. -func ImportPreimages(db ethdb.Database, fn string) error { - log.Info("Importing preimages", "file", fn) - - // Open the file handle and potentially unwrap the gzip stream - fh, err := os.Open(fn) - if err != nil { - return err - } - defer fh.Close() - - var reader io.Reader = bufio.NewReader(fh) - if strings.HasSuffix(fn, ".gz") { - if reader, err = gzip.NewReader(reader); err != nil { - return err - } - } - stream := rlp.NewStream(reader, 0) - - // Import the preimages in batches to prevent disk thrashing - preimages := make(map[common.Hash][]byte) - - for { - // Read the next entry and ensure it's not junk - var blob []byte - - if err := stream.Decode(&blob); err != nil { - if err == io.EOF { - break - } - return err - } - // Accumulate the preimages and flush when enough ws gathered - preimages[crypto.Keccak256Hash(blob)] = common.CopyBytes(blob) - if len(preimages) > 1024 { - rawdb.WritePreimages(db, preimages) - preimages = make(map[common.Hash][]byte) - } - } - // Flush the last batch preimage data - if len(preimages) > 0 { - rawdb.WritePreimages(db, preimages) - } - return nil -} - -// ExportPreimages exports all known hash preimages into the specified file, -// truncating any data already present in the file. -// It's a part of the deprecated functionality, should be removed in the future. -func ExportPreimages(db ethdb.Database, fn string) error { - log.Info("Exporting preimages", "file", fn) - - // Open the file handle and potentially wrap with a gzip stream - fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return err - } - defer fh.Close() - - var writer io.Writer = fh - if strings.HasSuffix(fn, ".gz") { - writer = gzip.NewWriter(writer) - defer writer.(*gzip.Writer).Close() - } - // Iterate over the preimages and export them - it := db.NewIterator([]byte("secure-key-"), nil) - defer it.Release() - - for it.Next() { - if err := rlp.Encode(writer, it.Value()); err != nil { - return err - } - } - log.Info("Exported preimages", "file", fn) - return nil -} - -// ExportSnapshotPreimages exports the preimages corresponding to the enumeration of -// the snapshot for a given root. -func ExportSnapshotPreimages(chaindb ethdb.Database, snaptree *snapshot.Tree, fn string, root common.Hash) error { - log.Info("Exporting preimages", "file", fn) - - fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return err - } - defer fh.Close() - - // Enable gzip compressing if file name has gz suffix. - var writer io.Writer = fh - if strings.HasSuffix(fn, ".gz") { - gz := gzip.NewWriter(writer) - defer gz.Close() - writer = gz - } - buf := bufio.NewWriter(writer) - defer buf.Flush() - writer = buf - - type hashAndPreimageSize struct { - Hash common.Hash - Size int - } - hashCh := make(chan hashAndPreimageSize) - - var ( - start = time.Now() - logged = time.Now() - preimages int - ) - go func() { - defer close(hashCh) - accIt, err := snaptree.AccountIterator(root, common.Hash{}) - if err != nil { - log.Error("Failed to create account iterator", "error", err) - return - } - defer accIt.Release() - - for accIt.Next() { - acc, err := types.FullAccount(accIt.Account()) - if err != nil { - log.Error("Failed to get full account", "error", err) - return - } - preimages += 1 - hashCh <- hashAndPreimageSize{Hash: accIt.Hash(), Size: common.AddressLength} - - if acc.Root != (common.Hash{}) && acc.Root != types.EmptyRootHash { - stIt, err := snaptree.StorageIterator(root, accIt.Hash(), common.Hash{}) - if err != nil { - log.Error("Failed to create storage iterator", "error", err) - return - } - for stIt.Next() { - preimages += 1 - hashCh <- hashAndPreimageSize{Hash: stIt.Hash(), Size: common.HashLength} - - if time.Since(logged) > time.Second*8 { - logged = time.Now() - log.Info("Exporting preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start))) - } - } - stIt.Release() - } - if time.Since(logged) > time.Second*8 { - logged = time.Now() - log.Info("Exporting preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start))) - } - } - }() - - for item := range hashCh { - preimage := rawdb.ReadPreimage(chaindb, item.Hash) - if len(preimage) == 0 { - return fmt.Errorf("missing preimage for %v", item.Hash) - } - if len(preimage) != item.Size { - return fmt.Errorf("invalid preimage size, have %d", len(preimage)) - } - rlpenc, err := rlp.EncodeToBytes(preimage) - if err != nil { - return fmt.Errorf("error encoding preimage: %w", err) - } - if _, err := writer.Write(rlpenc); err != nil { - return fmt.Errorf("failed to write preimage: %w", err) - } - } - log.Info("Exported preimages", "count", preimages, "elapsed", common.PrettyDuration(time.Since(start)), "file", fn) - return nil -} - -// exportHeader is used in the export/import flow. When we do an export, -// the first element we output is the exportHeader. -// Whenever a backwards-incompatible change is made, the Version header -// should be bumped. -// If the importer sees a higher version, it should reject the import. -type exportHeader struct { - Magic string // Always set to 'gethdbdump' for disambiguation - Version uint64 - Kind string - UnixTime uint64 -} - -const exportMagic = "gethdbdump" -const ( - OpBatchAdd = 0 - OpBatchDel = 1 -) - -// ImportLDBData imports a batch of snapshot data into the database -func ImportLDBData(db ethdb.Database, f string, startIndex int64, interrupt chan struct{}) error { - log.Info("Importing leveldb data", "file", f) - - // Open the file handle and potentially unwrap the gzip stream - fh, err := os.Open(f) - if err != nil { - return err - } - defer fh.Close() - - var reader io.Reader = bufio.NewReader(fh) - if strings.HasSuffix(f, ".gz") { - if reader, err = gzip.NewReader(reader); err != nil { - return err - } - } - stream := rlp.NewStream(reader, 0) - - // Read the header - var header exportHeader - if err := stream.Decode(&header); err != nil { - return fmt.Errorf("could not decode header: %v", err) - } - if header.Magic != exportMagic { - return errors.New("incompatible data, wrong magic") - } - if header.Version != 0 { - return fmt.Errorf("incompatible version %d, (support only 0)", header.Version) - } - log.Info("Importing data", "file", f, "type", header.Kind, "data age", - common.PrettyDuration(time.Since(time.Unix(int64(header.UnixTime), 0)))) - - // Import the snapshot in batches to prevent disk thrashing - var ( - count int64 - start = time.Now() - logged = time.Now() - batch = db.NewBatch() - ) - for { - // Read the next entry - var ( - op byte - key, val []byte - ) - if err := stream.Decode(&op); err != nil { - if err == io.EOF { - break - } - return err - } - if err := stream.Decode(&key); err != nil { - return err - } - if err := stream.Decode(&val); err != nil { - return err - } - if count < startIndex { - count++ - continue - } - switch op { - case OpBatchDel: - batch.Delete(key) - case OpBatchAdd: - batch.Put(key, val) - default: - return fmt.Errorf("unknown op %d", op) - } - if batch.ValueSize() > ethdb.IdealBatchSize { - if err := batch.Write(); err != nil { - return err - } - batch.Reset() - } - // Check interruption emitted by ctrl+c - if count%1000 == 0 { - select { - case <-interrupt: - if err := batch.Write(); err != nil { - return err - } - log.Info("External data import interrupted", "file", f, "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - return nil - default: - } - } - if count%1000 == 0 && time.Since(logged) > 8*time.Second { - log.Info("Importing external data", "file", f, "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - count += 1 - } - // Flush the last batch snapshot data - if batch.ValueSize() > 0 { - if err := batch.Write(); err != nil { - return err - } - } - log.Info("Imported chain data", "file", f, "count", count, - "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} - -// ChainDataIterator is an interface wraps all necessary functions to iterate -// the exporting chain data. -type ChainDataIterator interface { - // Next returns the key-value pair for next exporting entry in the iterator. - // When the end is reached, it will return (0, nil, nil, false). - Next() (byte, []byte, []byte, bool) - - // Release releases associated resources. Release should always succeed and can - // be called multiple times without causing error. - Release() -} - -// ExportChaindata exports the given data type (truncating any data already present) -// in the file. If the suffix is 'gz', gzip compression is used. -func ExportChaindata(fn string, kind string, iter ChainDataIterator, interrupt chan struct{}) error { - log.Info("Exporting chain data", "file", fn, "kind", kind) - defer iter.Release() - - // Open the file handle and potentially wrap with a gzip stream - fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return err - } - defer fh.Close() - - var writer io.Writer = fh - if strings.HasSuffix(fn, ".gz") { - writer = gzip.NewWriter(writer) - defer writer.(*gzip.Writer).Close() - } - // Write the header - if err := rlp.Encode(writer, &exportHeader{ - Magic: exportMagic, - Version: 0, - Kind: kind, - UnixTime: uint64(time.Now().Unix()), - }); err != nil { - return err - } - // Extract data from source iterator and dump them out to file - var ( - count int64 - start = time.Now() - logged = time.Now() - ) - for { - op, key, val, ok := iter.Next() - if !ok { - break - } - if err := rlp.Encode(writer, op); err != nil { - return err - } - if err := rlp.Encode(writer, key); err != nil { - return err - } - if err := rlp.Encode(writer, val); err != nil { - return err - } - if count%1000 == 0 { - // Check interruption emitted by ctrl+c - select { - case <-interrupt: - log.Info("Chain data exporting interrupted", "file", fn, - "kind", kind, "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - return nil - default: - } - if time.Since(logged) > 8*time.Second { - log.Info("Exporting chain data", "file", fn, "kind", kind, - "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - count++ - } - log.Info("Exported chain data", "file", fn, "kind", kind, "count", count, - "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} diff --git a/builder/cmd/utils/diskusage.go b/builder/cmd/utils/diskusage.go deleted file mode 100644 index 0e88f9194..000000000 --- a/builder/cmd/utils/diskusage.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -//go:build !windows && !openbsd -// +build !windows,!openbsd - -package utils - -import ( - "fmt" - - "golang.org/x/sys/unix" -) - -func getFreeDiskSpace(path string) (uint64, error) { - var stat unix.Statfs_t - if err := unix.Statfs(path, &stat); err != nil { - return 0, fmt.Errorf("failed to call Statfs: %v", err) - } - - // Available blocks * size per block = available space in bytes - var bavail = stat.Bavail - // nolint:staticcheck - if stat.Bavail < 0 { - // FreeBSD can have a negative number of blocks available - // because of the grace limit. - bavail = 0 - } - //nolint:unconvert - return uint64(bavail) * uint64(stat.Bsize), nil -} diff --git a/builder/cmd/utils/diskusage_openbsd.go b/builder/cmd/utils/diskusage_openbsd.go deleted file mode 100644 index 0d71d84a6..000000000 --- a/builder/cmd/utils/diskusage_openbsd.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -//go:build openbsd -// +build openbsd - -package utils - -import ( - "fmt" - - "golang.org/x/sys/unix" -) - -func getFreeDiskSpace(path string) (uint64, error) { - var stat unix.Statfs_t - if err := unix.Statfs(path, &stat); err != nil { - return 0, fmt.Errorf("failed to call Statfs: %v", err) - } - - // Available blocks * size per block = available space in bytes - var bavail = stat.F_bavail - // Not sure if the following check is necessary for OpenBSD - if stat.F_bavail < 0 { - // FreeBSD can have a negative number of blocks available - // because of the grace limit. - bavail = 0 - } - //nolint:unconvert - return uint64(bavail) * uint64(stat.F_bsize), nil -} diff --git a/builder/cmd/utils/diskusage_windows.go b/builder/cmd/utils/diskusage_windows.go deleted file mode 100644 index db3144932..000000000 --- a/builder/cmd/utils/diskusage_windows.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package utils - -import ( - "fmt" - - "golang.org/x/sys/windows" -) - -func getFreeDiskSpace(path string) (uint64, error) { - - cwd, err := windows.UTF16PtrFromString(path) - if err != nil { - return 0, fmt.Errorf("failed to call UTF16PtrFromString: %v", err) - } - - var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64 - if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil { - return 0, fmt.Errorf("failed to call GetDiskFreeSpaceEx: %v", err) - } - - return freeBytesAvailableToCaller, nil -} diff --git a/builder/cmd/utils/export_test.go b/builder/cmd/utils/export_test.go deleted file mode 100644 index 84ba8d0c3..000000000 --- a/builder/cmd/utils/export_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package utils - -import ( - "fmt" - "os" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/rlp" -) - -// TestExport does basic sanity checks on the export/import functionality -func TestExport(t *testing.T) { - f := fmt.Sprintf("%v/tempdump", os.TempDir()) - defer func() { - os.Remove(f) - }() - testExport(t, f) -} - -func TestExportGzip(t *testing.T) { - f := fmt.Sprintf("%v/tempdump.gz", os.TempDir()) - defer func() { - os.Remove(f) - }() - testExport(t, f) -} - -type testIterator struct { - index int -} - -func newTestIterator() *testIterator { - return &testIterator{index: -1} -} - -func (iter *testIterator) Next() (byte, []byte, []byte, bool) { - if iter.index >= 999 { - return 0, nil, nil, false - } - iter.index += 1 - if iter.index == 42 { - iter.index += 1 - } - return OpBatchAdd, []byte(fmt.Sprintf("key-%04d", iter.index)), - []byte(fmt.Sprintf("value %d", iter.index)), true -} - -func (iter *testIterator) Release() {} - -func testExport(t *testing.T, f string) { - err := ExportChaindata(f, "testdata", newTestIterator(), make(chan struct{})) - if err != nil { - t.Fatal(err) - } - db := rawdb.NewMemoryDatabase() - err = ImportLDBData(db, f, 5, make(chan struct{})) - if err != nil { - t.Fatal(err) - } - // verify - for i := 0; i < 1000; i++ { - v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i))) - if (i < 5 || i == 42) && err == nil { - t.Fatalf("expected no element at idx %d, got '%v'", i, string(v)) - } - if !(i < 5 || i == 42) { - if err != nil { - t.Fatalf("expected element idx %d: %v", i, err) - } - if have, want := string(v), fmt.Sprintf("value %d", i); have != want { - t.Fatalf("have %v, want %v", have, want) - } - } - } - v, err := db.Get([]byte(fmt.Sprintf("key-%04d", 1000))) - if err == nil { - t.Fatalf("expected no element at idx %d, got '%v'", 1000, string(v)) - } -} - -// testDeletion tests if the deletion markers can be exported/imported correctly -func TestDeletionExport(t *testing.T) { - f := fmt.Sprintf("%v/tempdump", os.TempDir()) - defer func() { - os.Remove(f) - }() - testDeletion(t, f) -} - -// TestDeletionExportGzip tests if the deletion markers can be exported/imported -// correctly with gz compression. -func TestDeletionExportGzip(t *testing.T) { - f := fmt.Sprintf("%v/tempdump.gz", os.TempDir()) - defer func() { - os.Remove(f) - }() - testDeletion(t, f) -} - -type deletionIterator struct { - index int -} - -func newDeletionIterator() *deletionIterator { - return &deletionIterator{index: -1} -} - -func (iter *deletionIterator) Next() (byte, []byte, []byte, bool) { - if iter.index >= 999 { - return 0, nil, nil, false - } - iter.index += 1 - if iter.index == 42 { - iter.index += 1 - } - return OpBatchDel, []byte(fmt.Sprintf("key-%04d", iter.index)), nil, true -} - -func (iter *deletionIterator) Release() {} - -func testDeletion(t *testing.T, f string) { - err := ExportChaindata(f, "testdata", newDeletionIterator(), make(chan struct{})) - if err != nil { - t.Fatal(err) - } - db := rawdb.NewMemoryDatabase() - for i := 0; i < 1000; i++ { - db.Put([]byte(fmt.Sprintf("key-%04d", i)), []byte(fmt.Sprintf("value %d", i))) - } - err = ImportLDBData(db, f, 5, make(chan struct{})) - if err != nil { - t.Fatal(err) - } - for i := 0; i < 1000; i++ { - v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i))) - if i < 5 || i == 42 { - if err != nil { - t.Fatalf("expected element at idx %d, got '%v'", i, err) - } - if have, want := string(v), fmt.Sprintf("value %d", i); have != want { - t.Fatalf("have %v, want %v", have, want) - } - } - if !(i < 5 || i == 42) { - if err == nil { - t.Fatalf("expected no element idx %d: %v", i, string(v)) - } - } - } -} - -// TestImportFutureFormat tests that we reject unsupported future versions. -func TestImportFutureFormat(t *testing.T) { - t.Parallel() - f := fmt.Sprintf("%v/tempdump-future", os.TempDir()) - defer func() { - os.Remove(f) - }() - fh, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - t.Fatal(err) - } - defer fh.Close() - if err := rlp.Encode(fh, &exportHeader{ - Magic: exportMagic, - Version: 500, - Kind: "testdata", - UnixTime: uint64(time.Now().Unix()), - }); err != nil { - t.Fatal(err) - } - db2 := rawdb.NewMemoryDatabase() - err = ImportLDBData(db2, f, 0, make(chan struct{})) - if err == nil { - t.Fatal("Expected error, got none") - } - if !strings.HasPrefix(err.Error(), "incompatible version") { - t.Fatalf("wrong error: %v", err) - } -} diff --git a/builder/cmd/utils/flags.go b/builder/cmd/utils/flags.go deleted file mode 100644 index e45100ae2..000000000 --- a/builder/cmd/utils/flags.go +++ /dev/null @@ -1,2531 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// Package utils contains internal helper functions for go-ethereum commands. -package utils - -import ( - "context" - "crypto/ecdsa" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "math" - "math/big" - "net" - "net/http" - "os" - "path/filepath" - godebug "runtime/debug" - "strconv" - "strings" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/builder" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/fdlimit" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/catalyst" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/remotedb" - "github.com/ethereum/go-ethereum/ethstats" - "github.com/ethereum/go-ethereum/graphql" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/metrics/exp" - "github.com/ethereum/go-ethereum/metrics/influxdb" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/nat" - "github.com/ethereum/go-ethereum/p2p/netutil" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - pcsclite "github.com/gballet/go-libpcsclite" - gopsutil "github.com/shirou/gopsutil/mem" - "github.com/urfave/cli/v2" -) - -// These are all the command line flags we support. -// If you add to this list, please remember to include the -// flag in the appropriate command definition. -// -// The flags are defined here so their names and help texts -// are the same for all commands. - -var ( - // General settings - DataDirFlag = &flags.DirectoryFlag{ - Name: "datadir", - Usage: "Data directory for the databases and keystore", - Value: flags.DirectoryString(node.DefaultDataDir()), - Category: flags.EthCategory, - } - RemoteDBFlag = &cli.StringFlag{ - Name: "remotedb", - Usage: "URL for remote database", - Category: flags.LoggingCategory, - } - DBEngineFlag = &cli.StringFlag{ - Name: "db.engine", - Usage: "Backing database implementation to use ('pebble' or 'leveldb')", - Value: node.DefaultConfig.DBEngine, - Category: flags.EthCategory, - } - AncientFlag = &flags.DirectoryFlag{ - Name: "datadir.ancient", - Usage: "Root directory for ancient data (default = inside chaindata)", - Category: flags.EthCategory, - } - MinFreeDiskSpaceFlag = &flags.DirectoryFlag{ - Name: "datadir.minfreedisk", - Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)", - Category: flags.EthCategory, - } - KeyStoreDirFlag = &flags.DirectoryFlag{ - Name: "keystore", - Usage: "Directory for the keystore (default = inside the datadir)", - Category: flags.AccountCategory, - } - USBFlag = &cli.BoolFlag{ - Name: "usb", - Usage: "Enable monitoring and management of USB hardware wallets", - Category: flags.AccountCategory, - } - SmartCardDaemonPathFlag = &cli.StringFlag{ - Name: "pcscdpath", - Usage: "Path to the smartcard daemon (pcscd) socket file", - Value: pcsclite.PCSCDSockName, - Category: flags.AccountCategory, - } - NetworkIdFlag = &cli.Uint64Flag{ - Name: "networkid", - Usage: "Explicitly set network id (integer)(For testnets: use --goerli, --sepolia, --holesky instead)", - Value: ethconfig.Defaults.NetworkId, - Category: flags.EthCategory, - } - MainnetFlag = &cli.BoolFlag{ - Name: "mainnet", - Usage: "Ethereum mainnet", - Category: flags.EthCategory, - } - GoerliFlag = &cli.BoolFlag{ - Name: "goerli", - Usage: "Görli network: pre-configured proof-of-authority test network", - Category: flags.EthCategory, - } - SepoliaFlag = &cli.BoolFlag{ - Name: "sepolia", - Usage: "Sepolia network: pre-configured proof-of-work test network", - Category: flags.EthCategory, - } - HoleskyFlag = &cli.BoolFlag{ - Name: "holesky", - Usage: "Holesky network: pre-configured proof-of-stake test network", - Category: flags.EthCategory, - } - // Dev mode - DeveloperFlag = &cli.BoolFlag{ - Name: "dev", - Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", - Category: flags.DevCategory, - } - DeveloperPeriodFlag = &cli.Uint64Flag{ - Name: "dev.period", - Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", - Category: flags.DevCategory, - } - DeveloperGasLimitFlag = &cli.Uint64Flag{ - Name: "dev.gaslimit", - Usage: "Initial block gas limit", - Value: 11500000, - Category: flags.DevCategory, - } - - IdentityFlag = &cli.StringFlag{ - Name: "identity", - Usage: "Custom node name", - Category: flags.NetworkingCategory, - } - DocRootFlag = &flags.DirectoryFlag{ - Name: "docroot", - Usage: "Document Root for HTTPClient file scheme", - Value: flags.DirectoryString(flags.HomeDir()), - Category: flags.APICategory, - } - ExitWhenSyncedFlag = &cli.BoolFlag{ - Name: "exitwhensynced", - Usage: "Exits after block synchronisation completes", - Category: flags.EthCategory, - } - - // Dump command options. - IterativeOutputFlag = &cli.BoolFlag{ - Name: "iterative", - Usage: "Print streaming JSON iteratively, delimited by newlines", - Value: true, - } - ExcludeStorageFlag = &cli.BoolFlag{ - Name: "nostorage", - Usage: "Exclude storage entries (save db lookups)", - } - IncludeIncompletesFlag = &cli.BoolFlag{ - Name: "incompletes", - Usage: "Include accounts for which we don't have the address (missing preimage)", - } - ExcludeCodeFlag = &cli.BoolFlag{ - Name: "nocode", - Usage: "Exclude contract code (save db lookups)", - } - StartKeyFlag = &cli.StringFlag{ - Name: "start", - Usage: "Start position. Either a hash or address", - Value: "0x0000000000000000000000000000000000000000000000000000000000000000", - } - DumpLimitFlag = &cli.Uint64Flag{ - Name: "limit", - Usage: "Max number of elements (0 = no limit)", - Value: 0, - } - - defaultSyncMode = ethconfig.Defaults.SyncMode - SnapshotFlag = &cli.BoolFlag{ - Name: "snapshot", - Usage: `Enables snapshot-database mode (default = enable)`, - Value: true, - Category: flags.EthCategory, - } - LightKDFFlag = &cli.BoolFlag{ - Name: "lightkdf", - Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", - Category: flags.AccountCategory, - } - EthRequiredBlocksFlag = &cli.StringFlag{ - Name: "eth.requiredblocks", - Usage: "Comma separated block number-to-hash mappings to require for peering (=)", - Category: flags.EthCategory, - } - BloomFilterSizeFlag = &cli.Uint64Flag{ - Name: "bloomfilter.size", - Usage: "Megabytes of memory allocated to bloom-filter for pruning", - Value: 2048, - Category: flags.EthCategory, - } - OverrideCancun = &cli.Uint64Flag{ - Name: "override.cancun", - Usage: "Manually specify the Cancun fork timestamp, overriding the bundled setting", - Category: flags.EthCategory, - } - OverrideVerkle = &cli.Uint64Flag{ - Name: "override.verkle", - Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", - Category: flags.EthCategory, - } - SyncModeFlag = &flags.TextMarshalerFlag{ - Name: "syncmode", - Usage: `Blockchain sync mode ("snap" or "full")`, - Value: &defaultSyncMode, - Category: flags.StateCategory, - } - GCModeFlag = &cli.StringFlag{ - Name: "gcmode", - Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`, - Value: "full", - Category: flags.StateCategory, - } - StateSchemeFlag = &cli.StringFlag{ - Name: "state.scheme", - Usage: "Scheme to use for storing ethereum state ('hash' or 'path')", - Category: flags.StateCategory, - } - StateHistoryFlag = &cli.Uint64Flag{ - Name: "history.state", - Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)", - Value: ethconfig.Defaults.StateHistory, - Category: flags.StateCategory, - } - TransactionHistoryFlag = &cli.Uint64Flag{ - Name: "history.transactions", - Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", - Value: ethconfig.Defaults.TransactionHistory, - Category: flags.StateCategory, - } - // Transaction pool settings - TxPoolLocalsFlag = &cli.StringFlag{ - Name: "txpool.locals", - Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", - Category: flags.TxPoolCategory, - } - TxPoolNoLocalsFlag = &cli.BoolFlag{ - Name: "txpool.nolocals", - Usage: "Disables price exemptions for locally submitted transactions", - Category: flags.TxPoolCategory, - } - TxPoolJournalFlag = &cli.StringFlag{ - Name: "txpool.journal", - Usage: "Disk journal for local transaction to survive node restarts", - Value: ethconfig.Defaults.TxPool.Journal, - Category: flags.TxPoolCategory, - } - TxPoolRejournalFlag = &cli.DurationFlag{ - Name: "txpool.rejournal", - Usage: "Time interval to regenerate the local transaction journal", - Value: ethconfig.Defaults.TxPool.Rejournal, - Category: flags.TxPoolCategory, - } - TxPoolPriceLimitFlag = &cli.Uint64Flag{ - Name: "txpool.pricelimit", - Usage: "Minimum gas price tip to enforce for acceptance into the pool", - Value: ethconfig.Defaults.TxPool.PriceLimit, - Category: flags.TxPoolCategory, - } - TxPoolPriceBumpFlag = &cli.Uint64Flag{ - Name: "txpool.pricebump", - Usage: "Price bump percentage to replace an already existing transaction", - Value: ethconfig.Defaults.TxPool.PriceBump, - Category: flags.TxPoolCategory, - } - TxPoolAccountSlotsFlag = &cli.Uint64Flag{ - Name: "txpool.accountslots", - Usage: "Minimum number of executable transaction slots guaranteed per account", - Value: ethconfig.Defaults.TxPool.AccountSlots, - Category: flags.TxPoolCategory, - } - TxPoolGlobalSlotsFlag = &cli.Uint64Flag{ - Name: "txpool.globalslots", - Usage: "Maximum number of executable transaction slots for all accounts", - Value: ethconfig.Defaults.TxPool.GlobalSlots, - Category: flags.TxPoolCategory, - } - TxPoolAccountQueueFlag = &cli.Uint64Flag{ - Name: "txpool.accountqueue", - Usage: "Maximum number of non-executable transaction slots permitted per account", - Value: ethconfig.Defaults.TxPool.AccountQueue, - Category: flags.TxPoolCategory, - } - TxPoolGlobalQueueFlag = &cli.Uint64Flag{ - Name: "txpool.globalqueue", - Usage: "Maximum number of non-executable transaction slots for all accounts", - Value: ethconfig.Defaults.TxPool.GlobalQueue, - Category: flags.TxPoolCategory, - } - TxPoolLifetimeFlag = &cli.DurationFlag{ - Name: "txpool.lifetime", - Usage: "Maximum amount of time non-executable transaction are queued", - Value: ethconfig.Defaults.TxPool.Lifetime, - Category: flags.TxPoolCategory, - } - TxPoolPrivateLifetimeFlag = &cli.DurationFlag{ - Name: "txpool.privatelifetime", - Usage: "Maximum amount of time private transactions are withheld from public broadcasting", - Value: ethconfig.Defaults.TxPool.PrivateTxLifetime, - Category: flags.TxPoolCategory, - } - // Blob transaction pool settings - BlobPoolDataDirFlag = &cli.StringFlag{ - Name: "blobpool.datadir", - Usage: "Data directory to store blob transactions in", - Value: ethconfig.Defaults.BlobPool.Datadir, - Category: flags.BlobPoolCategory, - } - BlobPoolDataCapFlag = &cli.Uint64Flag{ - Name: "blobpool.datacap", - Usage: "Disk space to allocate for pending blob transactions (soft limit)", - Value: ethconfig.Defaults.BlobPool.Datacap, - Category: flags.BlobPoolCategory, - } - BlobPoolPriceBumpFlag = &cli.Uint64Flag{ - Name: "blobpool.pricebump", - Usage: "Price bump percentage to replace an already existing blob transaction", - Value: ethconfig.Defaults.BlobPool.PriceBump, - Category: flags.BlobPoolCategory, - } - // Performance tuning settings - CacheFlag = &cli.IntFlag{ - Name: "cache", - Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)", - Value: 1024, - Category: flags.PerfCategory, - } - CacheDatabaseFlag = &cli.IntFlag{ - Name: "cache.database", - Usage: "Percentage of cache memory allowance to use for database io", - Value: 50, - Category: flags.PerfCategory, - } - CacheTrieFlag = &cli.IntFlag{ - Name: "cache.trie", - Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", - Value: 15, - Category: flags.PerfCategory, - } - CacheGCFlag = &cli.IntFlag{ - Name: "cache.gc", - Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", - Value: 25, - Category: flags.PerfCategory, - } - CacheSnapshotFlag = &cli.IntFlag{ - Name: "cache.snapshot", - Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", - Value: 10, - Category: flags.PerfCategory, - } - CacheNoPrefetchFlag = &cli.BoolFlag{ - Name: "cache.noprefetch", - Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", - Category: flags.PerfCategory, - } - CachePreimagesFlag = &cli.BoolFlag{ - Name: "cache.preimages", - Usage: "Enable recording the SHA3/keccak preimages of trie keys", - Category: flags.PerfCategory, - } - CacheLogSizeFlag = &cli.IntFlag{ - Name: "cache.blocklogs", - Usage: "Size (in number of blocks) of the log cache for filtering", - Category: flags.PerfCategory, - Value: ethconfig.Defaults.FilterLogCacheSize, - } - FDLimitFlag = &cli.IntFlag{ - Name: "fdlimit", - Usage: "Raise the open file descriptor resource limit (default = system fd limit)", - Category: flags.PerfCategory, - } - CryptoKZGFlag = &cli.StringFlag{ - Name: "crypto.kzg", - Usage: "KZG library implementation to use; gokzg (recommended) or ckzg", - Value: "gokzg", - Category: flags.PerfCategory, - } - - // Miner settings - MiningEnabledFlag = &cli.BoolFlag{ - Name: "mine", - Usage: "Enable mining", - Category: flags.MinerCategory, - } - MinerGasLimitFlag = &cli.Uint64Flag{ - Name: "miner.gaslimit", - Usage: "Target gas ceiling for mined blocks", - Value: ethconfig.Defaults.Miner.GasCeil, - Category: flags.MinerCategory, - } - MinerGasPriceFlag = &flags.BigFlag{ - Name: "miner.gasprice", - Usage: "Minimum gas price for mining a transaction", - Value: ethconfig.Defaults.Miner.GasPrice, - Category: flags.MinerCategory, - } - MinerAlgoTypeFlag = &cli.StringFlag{ - Name: "miner.algotype", - Usage: "[NOTE: Deprecated, please use builder.algotype instead] Block building algorithm to use [=mev-geth] (mev-geth, greedy, greedy-buckets)", - Value: "mev-geth", - Category: flags.MinerCategory, - } - MinerEtherbaseFlag = &cli.StringFlag{ - Name: "miner.etherbase", - Usage: "0x prefixed public address for block mining rewards", - Category: flags.MinerCategory, - } - MinerExtraDataFlag = &cli.StringFlag{ - Name: "miner.extradata", - Usage: "Block extra data set by the miner (default = client version)", - Category: flags.MinerCategory, - } - MinerRecommitIntervalFlag = &cli.DurationFlag{ - Name: "miner.recommit", - Usage: "Time interval to recreate the block being mined", - Value: ethconfig.Defaults.Miner.Recommit, - Category: flags.MinerCategory, - } - MinerMaxMergedBundlesFlag = &cli.IntFlag{ - Name: "miner.maxmergedbundles", - Usage: "flashbots - The maximum amount of bundles to merge. The miner will run this many workers in parallel to calculate if the full block is more profitable with these additional bundles.", - Value: 3, - Category: flags.MinerCategory, - } - MinerBlocklistFileFlag = &cli.StringFlag{ - Name: "miner.blocklist", - Usage: "[NOTE: Deprecated, please use builder.blacklist] flashbots - Path to JSON file with list of blocked addresses. Miner will ignore txs that touch mentioned addresses.", - Category: flags.MinerCategory, - } - MinerNewPayloadTimeout = &cli.DurationFlag{ - Name: "miner.newpayload-timeout", - Usage: "Specify the maximum time allowance for creating a new payload", - Value: ethconfig.Defaults.Miner.NewPayloadTimeout, - Category: flags.MinerCategory, - } - MinerPriceCutoffPercentFlag = &cli.IntFlag{ - Name: "miner.price_cutoff_percent", - Usage: "flashbots - The minimum effective gas price threshold used for bucketing transactions by price. " + - "For example if the top transaction in a list has an effective gas price of 1000 wei and price_cutoff_percent " + - "is 10 (i.e. 10%), then the minimum effective gas price included in the same bucket as the top transaction " + - "is (1000 * 10%) = 100 wei.\n" + - "NOTE: This flag is only used when miner.algotype=greedy-buckets", - Value: ethconfig.Defaults.Miner.PriceCutoffPercent, - Category: flags.MinerCategory, - EnvVars: []string{"FLASHBOTS_MINER_PRICE_CUTOFF_PERCENT"}, - } - - // Account settings - UnlockedAccountFlag = &cli.StringFlag{ - Name: "unlock", - Usage: "Comma separated list of accounts to unlock", - Value: "", - Category: flags.AccountCategory, - } - PasswordFileFlag = &cli.PathFlag{ - Name: "password", - Usage: "Password file to use for non-interactive password input", - TakesFile: true, - Category: flags.AccountCategory, - } - ExternalSignerFlag = &cli.StringFlag{ - Name: "signer", - Usage: "External signer (url or path to ipc file)", - Value: "", - Category: flags.AccountCategory, - } - InsecureUnlockAllowedFlag = &cli.BoolFlag{ - Name: "allow-insecure-unlock", - Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", - Category: flags.AccountCategory, - } - - // EVM settings - VMEnableDebugFlag = &cli.BoolFlag{ - Name: "vmdebug", - Usage: "Record information useful for VM and contract debugging", - Category: flags.VMCategory, - } - - // API options. - RPCGlobalGasCapFlag = &cli.Uint64Flag{ - Name: "rpc.gascap", - Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", - Value: ethconfig.Defaults.RPCGasCap, - Category: flags.APICategory, - } - RPCGlobalEVMTimeoutFlag = &cli.DurationFlag{ - Name: "rpc.evmtimeout", - Usage: "Sets a timeout used for eth_call (0=infinite)", - Value: ethconfig.Defaults.RPCEVMTimeout, - Category: flags.APICategory, - } - RPCGlobalTxFeeCapFlag = &cli.Float64Flag{ - Name: "rpc.txfeecap", - Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", - Value: ethconfig.Defaults.RPCTxFeeCap, - Category: flags.APICategory, - } - // Authenticated RPC HTTP settings - AuthListenFlag = &cli.StringFlag{ - Name: "authrpc.addr", - Usage: "Listening address for authenticated APIs", - Value: node.DefaultConfig.AuthAddr, - Category: flags.APICategory, - } - AuthPortFlag = &cli.IntFlag{ - Name: "authrpc.port", - Usage: "Listening port for authenticated APIs", - Value: node.DefaultConfig.AuthPort, - Category: flags.APICategory, - } - AuthVirtualHostsFlag = &cli.StringFlag{ - Name: "authrpc.vhosts", - Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", - Value: strings.Join(node.DefaultConfig.AuthVirtualHosts, ","), - Category: flags.APICategory, - } - JWTSecretFlag = &flags.DirectoryFlag{ - Name: "authrpc.jwtsecret", - Usage: "Path to a JWT secret to use for authenticated RPC endpoints", - Category: flags.APICategory, - } - - // Logging and debug settings - EthStatsURLFlag = &cli.StringFlag{ - Name: "ethstats", - Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", - Category: flags.MetricsCategory, - } - NoCompactionFlag = &cli.BoolFlag{ - Name: "nocompaction", - Usage: "Disables db compaction after import", - Category: flags.LoggingCategory, - } - - // MISC settings - SyncTargetFlag = &cli.StringFlag{ - Name: "synctarget", - Usage: `Hash of the block to full sync to (dev testing feature)`, - TakesFile: true, - Category: flags.MiscCategory, - } - // Builder API settings - BuilderEnabled = &cli.BoolFlag{ - Name: "builder", - Usage: "Enable the builder", - Category: flags.BuilderCategory, - } - - // BuilderAlgoTypeFlag replaces MinerAlgoTypeFlag to move away from deprecated miner package - // Note: builder.algotype was previously miner.algotype - this flag is still propagated to the miner configuration, - // see setMiner in cmd/utils/flags.go - BuilderAlgoTypeFlag = &cli.StringFlag{ - Name: "builder.algotype", - Usage: "Block building algorithm to use [=mev-geth] (mev-geth, greedy, greedy-buckets)", - Category: flags.BuilderCategory, - } - - // BuilderPriceCutoffPercentFlag replaces MinerPriceCutoffPercentFlag to move away from deprecated miner package - // Note: builder.price_cutoff_percent was previously miner.price_cutoff_percent - - // this flag is still propagated to the miner configuration, see setMiner in cmd/utils/flags.go - BuilderPriceCutoffPercentFlag = &cli.IntFlag{ - Name: "builder.price_cutoff_percent", - Usage: "flashbots - The minimum effective gas price threshold used for bucketing transactions by price. " + - "For example if the top transaction in a list has an effective gas price of 1000 wei and price_cutoff_percent " + - "is 10 (i.e. 10%), then the minimum effective gas price included in the same bucket as the top transaction " + - "is (1000 * 10%) = 100 wei.\n" + - "NOTE: This flag is only used when builder.algotype=greedy-buckets", - Value: ethconfig.Defaults.Miner.PriceCutoffPercent, - Category: flags.BuilderCategory, - EnvVars: []string{"FLASHBOTS_BUILDER_PRICE_CUTOFF_PERCENT"}, - } - - BuilderEnableValidatorChecks = &cli.BoolFlag{ - Name: "builder.validator_checks", - Usage: "Enable the validator checks", - Category: flags.BuilderCategory, - } - BuilderBlockValidationBlacklistSourceFilePath = &cli.StringFlag{ - Name: "builder.blacklist", - Usage: "Path to file containing blacklisted addresses, json-encoded list of strings. " + - "Builder will ignore transactions that touch mentioned addresses. This flag is also used for block validation API.\n" + - "NOTE: builder.validation_blacklist is deprecated and will be removed in the future in favor of builder.blacklist", - Aliases: []string{"builder.validation_blacklist"}, - Category: flags.BuilderCategory, - } - BuilderBlockValidationUseBalanceDiff = &cli.BoolFlag{ - Name: "builder.validation_use_balance_diff", - Usage: "Block validation API will use fee recipient balance difference for profit calculation.", - Value: false, - Category: flags.BuilderCategory, - } - BuilderBlockValidationExcludeWithdrawals = &cli.BoolFlag{ - Name: "builder.validation_exclude_withdrawals", - Usage: "Block validation API will exclude CL withdrawals to the fee recipient from the balance delta.", - Value: false, - Category: flags.BuilderCategory, - } - BuilderEnableLocalRelay = &cli.BoolFlag{ - Name: "builder.local_relay", - Usage: "Enable the local relay", - Category: flags.BuilderCategory, - } - BuilderSlotsInEpoch = &cli.Uint64Flag{ - Name: "builder.slots_in_epoch", - Usage: "Set the number of slots in an epoch in the local relay", - Value: 32, - Category: flags.BuilderCategory, - } - BuilderSecondsInSlot = &cli.Uint64Flag{ - Name: "builder.seconds_in_slot", - Usage: "Set the number of seconds in a slot in the local relay", - Value: 12, - Category: flags.BuilderCategory, - } - BuilderDisableBundleFetcher = &cli.BoolFlag{ - Name: "builder.no_bundle_fetcher", - Usage: "Disable the bundle fetcher", - Category: flags.BuilderCategory, - } - BuilderDryRun = &cli.BoolFlag{ - Name: "builder.dry-run", - Usage: "Builder only validates blocks without submission to the relay", - Category: flags.BuilderCategory, - } - BuilderIgnoreLatePayloadAttributes = &cli.BoolFlag{ - Name: "builder.ignore_late_payload_attributes", - Usage: "Builder will ignore all but the first payload attributes. Use if your CL sends non-canonical head updates.", - Category: flags.BuilderCategory, - } - BuilderSecretKey = &cli.StringFlag{ - Name: "builder.secret_key", - Usage: "Builder key used for signing blocks", - EnvVars: []string{"BUILDER_SECRET_KEY"}, - Value: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11", - Category: flags.BuilderCategory, - } - BuilderRelaySecretKey = &cli.StringFlag{ - Name: "builder.relay_secret_key", - Usage: "Builder local relay API key used for signing headers", - EnvVars: []string{"BUILDER_RELAY_SECRET_KEY"}, - Value: "0x2fc12ae741f29701f8e30f5de6350766c020cb80768a0ff01e6838ffd2431e11", - Category: flags.BuilderCategory, - } - BuilderListenAddr = &cli.StringFlag{ - Name: "builder.listen_addr", - Usage: "Listening address for builder endpoint", - EnvVars: []string{"BUILDER_LISTEN_ADDR"}, - Value: ":28545", - Category: flags.BuilderCategory, - } - BuilderGenesisForkVersion = &cli.StringFlag{ - Name: "builder.genesis_fork_version", - Usage: "Gensis fork version.", - EnvVars: []string{"BUILDER_GENESIS_FORK_VERSION"}, - Value: "0x00000000", - Category: flags.BuilderCategory, - } - BuilderBellatrixForkVersion = &cli.StringFlag{ - Name: "builder.bellatrix_fork_version", - Usage: "Bellatrix fork version.", - EnvVars: []string{"BUILDER_BELLATRIX_FORK_VERSION"}, - Value: "0x02000000", - Category: flags.BuilderCategory, - } - BuilderGenesisValidatorsRoot = &cli.StringFlag{ - Name: "builder.genesis_validators_root", - Usage: "Genesis validators root of the network.", - EnvVars: []string{"BUILDER_GENESIS_VALIDATORS_ROOT"}, - Value: "0x0000000000000000000000000000000000000000000000000000000000000000", - Category: flags.BuilderCategory, - } - BuilderBeaconEndpoints = &cli.StringFlag{ - Name: "builder.beacon_endpoints", - Usage: "Comma separated list of beacon endpoints to connect to for beacon chain data", - EnvVars: []string{"BUILDER_BEACON_ENDPOINTS"}, - Value: "http://127.0.0.1:5052", - Category: flags.BuilderCategory, - } - BuilderRemoteRelayEndpoint = &cli.StringFlag{ - Name: "builder.remote_relay_endpoint", - Usage: "Relay endpoint to connect to for validator registration data, if not provided will expose validator registration locally", - EnvVars: []string{"BUILDER_REMOTE_RELAY_ENDPOINT"}, - Value: "", - Category: flags.BuilderCategory, - } - BuilderSecondaryRemoteRelayEndpoints = &cli.StringFlag{ - Name: "builder.secondary_remote_relay_endpoints", - Usage: "Comma separated relay endpoints to connect to for validator registration data missing from the primary remote relay, and to push blocks for registrations missing from or matching the primary", - EnvVars: []string{"BUILDER_SECONDARY_REMOTE_RELAY_ENDPOINTS"}, - Value: "", - Category: flags.BuilderCategory, - } - BuilderMevSidecarEndpoint = &cli.StringFlag{ - Name: "builder.mev_sidecar_endpoint", - Usage: "MEV sidecar endpoint to connect to for Bolt CC", - EnvVars: []string{"BUILDER_MEV_SIDECAR_ENDPOINT"}, - Value: "", - Category: flags.BuilderCategory, - } - - // Builder rate limit settings - - BuilderRateLimitDuration = &cli.StringFlag{ - Name: "builder.rate_limit_duration", - Usage: "Determines rate limit of events processed by builder. For example, a value of \"500ms\" denotes that the builder processes events every 500ms. " + - "A duration string is a possibly signed sequence " + - "of decimal numbers, each with optional fraction and a unit suffix, such as \"300ms\", \"-1.5h\" or \"2h45m\"", - EnvVars: []string{"FLASHBOTS_BUILDER_RATE_LIMIT_DURATION"}, - Value: builder.RateLimitIntervalDefault.String(), - Category: flags.BuilderCategory, - } - - // BuilderRateLimitMaxBurst burst value can be thought of as a bucket of size b, initially full and refilled at rate r per second. - // b is defined by BuilderRateLimitMaxBurst and r is defined by BuilderRateLimitDuration. - // Additional details can be found on rate.Limiter documentation: https://pkg.go.dev/golang.org/x/time/rate#Limiter - BuilderRateLimitMaxBurst = &cli.IntFlag{ - Name: "builder.rate_limit_max_burst", - Usage: "Determines the maximum number of burst events the builder can accommodate at any given point in time.", - EnvVars: []string{"FLASHBOTS_BUILDER_RATE_LIMIT_MAX_BURST"}, - Value: builder.RateLimitBurstDefault, - Category: flags.BuilderCategory, - } - - BuilderBlockResubmitInterval = &cli.StringFlag{ - Name: "builder.block_resubmit_interval", - Usage: "Determines the interval at which builder will resubmit block submissions", - EnvVars: []string{"FLASHBOTS_BUILDER_RATE_LIMIT_RESUBMIT_INTERVAL"}, - Value: builder.BlockResubmitIntervalDefault.String(), - Category: flags.BuilderCategory, - } - - BuilderSubmissionOffset = &cli.DurationFlag{ - Name: "builder.submission_offset", - Usage: "Determines the offset from the end of slot time that the builder will submit blocks. " + - "For example, if a slot is 12 seconds long, and the offset is 2 seconds, the builder will submit blocks at 10 seconds into the slot.", - EnvVars: []string{"FLASHBOTS_BUILDER_SUBMISSION_OFFSET"}, - Value: builder.SubmissionOffsetFromEndOfSlotSecondsDefault, - Category: flags.BuilderCategory, - } - - BuilderDiscardRevertibleTxOnErr = &cli.BoolFlag{ - Name: "builder.discard_revertible_tx_on_error", - Usage: "When enabled, if a transaction submitted as part of a bundle in a send bundle request has error on commit, " + - "and its hash is specified as one that can revert in the request body, the builder will discard the hash of the failed transaction from the submitted bundle." + - "For additional details on the structure of the request body, see https://docs.flashbots.net/flashbots-mev-share/searchers/understanding-bundles#bundle-definition", - EnvVars: []string{"FLASHBOTS_BUILDER_DISCARD_REVERTIBLE_TX_ON_ERROR"}, - Value: builder.DefaultConfig.DiscardRevertibleTxOnErr, - Category: flags.BuilderCategory, - } - - BuilderEnableCancellations = &cli.BoolFlag{ - Name: "builder.cancellations", - Usage: "Enable cancellations for the builder", - Category: flags.BuilderCategory, - } - - BuilderBlockProcessorURL = &cli.StringFlag{ - Name: "builder.block_processor_url", - Usage: "RPC URL for the block processor", - Category: flags.BuilderCategory, - } - - // RPC settings - IPCDisabledFlag = &cli.BoolFlag{ - Name: "ipcdisable", - Usage: "Disable the IPC-RPC server", - Category: flags.APICategory, - } - IPCPathFlag = &flags.DirectoryFlag{ - Name: "ipcpath", - Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", - Category: flags.APICategory, - } - HTTPEnabledFlag = &cli.BoolFlag{ - Name: "http", - Usage: "Enable the HTTP-RPC server", - Category: flags.APICategory, - } - HTTPListenAddrFlag = &cli.StringFlag{ - Name: "http.addr", - Usage: "HTTP-RPC server listening interface", - Value: node.DefaultHTTPHost, - Category: flags.APICategory, - } - HTTPPortFlag = &cli.IntFlag{ - Name: "http.port", - Usage: "HTTP-RPC server listening port", - Value: node.DefaultHTTPPort, - Category: flags.APICategory, - } - HTTPCORSDomainFlag = &cli.StringFlag{ - Name: "http.corsdomain", - Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", - Value: "", - Category: flags.APICategory, - } - HTTPVirtualHostsFlag = &cli.StringFlag{ - Name: "http.vhosts", - Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", - Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), - Category: flags.APICategory, - } - HTTPApiFlag = &cli.StringFlag{ - Name: "http.api", - Usage: "API's offered over the HTTP-RPC interface", - Value: "", - Category: flags.APICategory, - } - HTTPPathPrefixFlag = &cli.StringFlag{ - Name: "http.rpcprefix", - Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: "", - Category: flags.APICategory, - } - GraphQLEnabledFlag = &cli.BoolFlag{ - Name: "graphql", - Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.", - Category: flags.APICategory, - } - GraphQLCORSDomainFlag = &cli.StringFlag{ - Name: "graphql.corsdomain", - Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", - Value: "", - Category: flags.APICategory, - } - GraphQLVirtualHostsFlag = &cli.StringFlag{ - Name: "graphql.vhosts", - Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", - Value: strings.Join(node.DefaultConfig.GraphQLVirtualHosts, ","), - Category: flags.APICategory, - } - WSEnabledFlag = &cli.BoolFlag{ - Name: "ws", - Usage: "Enable the WS-RPC server", - Category: flags.APICategory, - } - WSListenAddrFlag = &cli.StringFlag{ - Name: "ws.addr", - Usage: "WS-RPC server listening interface", - Value: node.DefaultWSHost, - Category: flags.APICategory, - } - WSPortFlag = &cli.IntFlag{ - Name: "ws.port", - Usage: "WS-RPC server listening port", - Value: node.DefaultWSPort, - Category: flags.APICategory, - } - WSApiFlag = &cli.StringFlag{ - Name: "ws.api", - Usage: "API's offered over the WS-RPC interface", - Value: "", - Category: flags.APICategory, - } - WSAllowedOriginsFlag = &cli.StringFlag{ - Name: "ws.origins", - Usage: "Origins from which to accept websockets requests", - Value: "", - Category: flags.APICategory, - } - WSPathPrefixFlag = &cli.StringFlag{ - Name: "ws.rpcprefix", - Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", - Value: "", - Category: flags.APICategory, - } - ExecFlag = &cli.StringFlag{ - Name: "exec", - Usage: "Execute JavaScript statement", - Category: flags.APICategory, - } - PreloadJSFlag = &cli.StringFlag{ - Name: "preload", - Usage: "Comma separated list of JavaScript files to preload into the console", - Category: flags.APICategory, - } - AllowUnprotectedTxs = &cli.BoolFlag{ - Name: "rpc.allow-unprotected-txs", - Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC", - Category: flags.APICategory, - } - BatchRequestLimit = &cli.IntFlag{ - Name: "rpc.batch-request-limit", - Usage: "Maximum number of requests in a batch", - Value: node.DefaultConfig.BatchRequestLimit, - Category: flags.APICategory, - } - BatchResponseMaxSize = &cli.IntFlag{ - Name: "rpc.batch-response-max-size", - Usage: "Maximum number of bytes returned from a batched call", - Value: node.DefaultConfig.BatchResponseMaxSize, - Category: flags.APICategory, - } - EnablePersonal = &cli.BoolFlag{ - Name: "rpc.enabledeprecatedpersonal", - Usage: "Enables the (deprecated) personal namespace", - Category: flags.APICategory, - } - - // Network Settings - MaxPeersFlag = &cli.IntFlag{ - Name: "maxpeers", - Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: node.DefaultConfig.P2P.MaxPeers, - Category: flags.NetworkingCategory, - } - MaxPendingPeersFlag = &cli.IntFlag{ - Name: "maxpendpeers", - Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", - Value: node.DefaultConfig.P2P.MaxPendingPeers, - Category: flags.NetworkingCategory, - } - ListenPortFlag = &cli.IntFlag{ - Name: "port", - Usage: "Network listening port", - Value: 30303, - Category: flags.NetworkingCategory, - } - BootnodesFlag = &cli.StringFlag{ - Name: "bootnodes", - Usage: "Comma separated enode URLs for P2P discovery bootstrap", - Value: "", - Category: flags.NetworkingCategory, - } - NodeKeyFileFlag = &cli.StringFlag{ - Name: "nodekey", - Usage: "P2P node key file", - Category: flags.NetworkingCategory, - } - NodeKeyHexFlag = &cli.StringFlag{ - Name: "nodekeyhex", - Usage: "P2P node key as hex (for testing)", - Category: flags.NetworkingCategory, - } - NATFlag = &cli.StringFlag{ - Name: "nat", - Usage: "NAT port mapping mechanism (any|none|upnp|pmp|pmp:|extip:)", - Value: "any", - Category: flags.NetworkingCategory, - } - NoDiscoverFlag = &cli.BoolFlag{ - Name: "nodiscover", - Usage: "Disables the peer discovery mechanism (manual peer addition)", - Category: flags.NetworkingCategory, - } - DiscoveryV4Flag = &cli.BoolFlag{ - Name: "discovery.v4", - Aliases: []string{"discv4"}, - Usage: "Enables the V4 discovery mechanism", - Category: flags.NetworkingCategory, - Value: true, - } - DiscoveryV5Flag = &cli.BoolFlag{ - Name: "discovery.v5", - Aliases: []string{"discv5"}, - Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", - Category: flags.NetworkingCategory, - } - NetrestrictFlag = &cli.StringFlag{ - Name: "netrestrict", - Usage: "Restricts network communication to the given IP networks (CIDR masks)", - Category: flags.NetworkingCategory, - } - DNSDiscoveryFlag = &cli.StringFlag{ - Name: "discovery.dns", - Usage: "Sets DNS discovery entry points (use \"\" to disable DNS)", - Category: flags.NetworkingCategory, - } - DiscoveryPortFlag = &cli.IntFlag{ - Name: "discovery.port", - Usage: "Use a custom UDP port for P2P discovery", - Value: 30303, - Category: flags.NetworkingCategory, - } - - // Console - JSpathFlag = &flags.DirectoryFlag{ - Name: "jspath", - Usage: "JavaScript root path for `loadScript`", - Value: flags.DirectoryString("."), - Category: flags.APICategory, - } - HttpHeaderFlag = &cli.StringSliceFlag{ - Name: "header", - Aliases: []string{"H"}, - Usage: "Pass custom headers to the RPC server when using --" + RemoteDBFlag.Name + " or the geth attach console. This flag can be given multiple times.", - Category: flags.APICategory, - } - - // Gas price oracle settings - GpoBlocksFlag = &cli.IntFlag{ - Name: "gpo.blocks", - Usage: "Number of recent blocks to check for gas prices", - Value: ethconfig.Defaults.GPO.Blocks, - Category: flags.GasPriceCategory, - } - GpoPercentileFlag = &cli.IntFlag{ - Name: "gpo.percentile", - Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", - Value: ethconfig.Defaults.GPO.Percentile, - Category: flags.GasPriceCategory, - } - GpoMaxGasPriceFlag = &cli.Int64Flag{ - Name: "gpo.maxprice", - Usage: "Maximum transaction priority fee (or gasprice before London fork) to be recommended by gpo", - Value: ethconfig.Defaults.GPO.MaxPrice.Int64(), - Category: flags.GasPriceCategory, - } - GpoIgnoreGasPriceFlag = &cli.Int64Flag{ - Name: "gpo.ignoreprice", - Usage: "Gas price below which gpo will ignore transactions", - Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(), - Category: flags.GasPriceCategory, - } - - // Metrics flags - MetricsEnabledFlag = &cli.BoolFlag{ - Name: "metrics", - Usage: "Enable metrics collection and reporting", - Category: flags.MetricsCategory, - } - MetricsEnabledExpensiveFlag = &cli.BoolFlag{ - Name: "metrics.expensive", - Usage: "Enable expensive metrics collection and reporting", - Category: flags.MetricsCategory, - } - // Builder metrics flag - MetricsEnabledBuilderFlag = &cli.BoolFlag{ - Name: "metrics.builder", - Usage: "Enable builder metrics collection and reporting", - Category: flags.MetricsCategory, - } - - // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. - // Since the pprof service enables sensitive/vulnerable behavior, this allows a user - // to enable a public-OK metrics endpoint without having to worry about ALSO exposing - // other profiling behavior or information. - MetricsHTTPFlag = &cli.StringFlag{ - Name: "metrics.addr", - Usage: `Enable stand-alone metrics HTTP server listening interface.`, - Category: flags.MetricsCategory, - } - MetricsPortFlag = &cli.IntFlag{ - Name: "metrics.port", - Usage: `Metrics HTTP server listening port. -Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.`, - Value: metrics.DefaultConfig.Port, - Category: flags.MetricsCategory, - } - MetricsEnableInfluxDBFlag = &cli.BoolFlag{ - Name: "metrics.influxdb", - Usage: "Enable metrics export/push to an external InfluxDB database", - Category: flags.MetricsCategory, - } - MetricsInfluxDBEndpointFlag = &cli.StringFlag{ - Name: "metrics.influxdb.endpoint", - Usage: "InfluxDB API endpoint to report metrics to", - Value: metrics.DefaultConfig.InfluxDBEndpoint, - Category: flags.MetricsCategory, - } - MetricsInfluxDBDatabaseFlag = &cli.StringFlag{ - Name: "metrics.influxdb.database", - Usage: "InfluxDB database name to push reported metrics to", - Value: metrics.DefaultConfig.InfluxDBDatabase, - Category: flags.MetricsCategory, - } - MetricsInfluxDBUsernameFlag = &cli.StringFlag{ - Name: "metrics.influxdb.username", - Usage: "Username to authorize access to the database", - Value: metrics.DefaultConfig.InfluxDBUsername, - Category: flags.MetricsCategory, - } - MetricsInfluxDBPasswordFlag = &cli.StringFlag{ - Name: "metrics.influxdb.password", - Usage: "Password to authorize access to the database", - Value: metrics.DefaultConfig.InfluxDBPassword, - Category: flags.MetricsCategory, - } - // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. - // For example `host` tag could be used so that we can group all nodes and average a measurement - // across all of them, but also so that we can select a specific node and inspect its measurements. - // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key - MetricsInfluxDBTagsFlag = &cli.StringFlag{ - Name: "metrics.influxdb.tags", - Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", - Value: metrics.DefaultConfig.InfluxDBTags, - Category: flags.MetricsCategory, - } - - MetricsEnableInfluxDBV2Flag = &cli.BoolFlag{ - Name: "metrics.influxdbv2", - Usage: "Enable metrics export/push to an external InfluxDB v2 database", - Category: flags.MetricsCategory, - } - - MetricsInfluxDBTokenFlag = &cli.StringFlag{ - Name: "metrics.influxdb.token", - Usage: "Token to authorize access to the database (v2 only)", - Value: metrics.DefaultConfig.InfluxDBToken, - Category: flags.MetricsCategory, - } - - MetricsInfluxDBBucketFlag = &cli.StringFlag{ - Name: "metrics.influxdb.bucket", - Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", - Value: metrics.DefaultConfig.InfluxDBBucket, - Category: flags.MetricsCategory, - } - - MetricsInfluxDBOrganizationFlag = &cli.StringFlag{ - Name: "metrics.influxdb.organization", - Usage: "InfluxDB organization name (v2 only)", - Value: metrics.DefaultConfig.InfluxDBOrganization, - Category: flags.MetricsCategory, - } -) - -var ( - // TestnetFlags is the flag group of all built-in supported testnets. - TestnetFlags = []cli.Flag{ - GoerliFlag, - SepoliaFlag, - HoleskyFlag, - } - // NetworkFlags is the flag group of all built-in supported networks. - NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...) - - // DatabaseFlags is the flag group of all database flags. - DatabaseFlags = []cli.Flag{ - DataDirFlag, - AncientFlag, - RemoteDBFlag, - DBEngineFlag, - StateSchemeFlag, - HttpHeaderFlag, - } -) - -// MakeDataDir retrieves the currently requested data directory, terminating -// if none (or the empty string) is specified. If the node is starting a testnet, -// then a subdirectory of the specified datadir will be used. -func MakeDataDir(ctx *cli.Context) string { - if path := ctx.String(DataDirFlag.Name); path != "" { - if ctx.Bool(GoerliFlag.Name) { - return filepath.Join(path, "goerli") - } - if ctx.Bool(SepoliaFlag.Name) { - return filepath.Join(path, "sepolia") - } - if ctx.Bool(HoleskyFlag.Name) { - return filepath.Join(path, "holesky") - } - return path - } - Fatalf("Cannot determine default data directory, please set manually (--datadir)") - return "" -} - -// setNodeKey creates a node key from set command line flags, either loading it -// from a file or as a specified hex value. If neither flags were provided, this -// method returns nil and an ephemeral key is to be generated. -func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { - var ( - hex = ctx.String(NodeKeyHexFlag.Name) - file = ctx.String(NodeKeyFileFlag.Name) - key *ecdsa.PrivateKey - err error - ) - switch { - case file != "" && hex != "": - Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) - case file != "": - if key, err = crypto.LoadECDSA(file); err != nil { - Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) - } - cfg.PrivateKey = key - case hex != "": - if key, err = crypto.HexToECDSA(hex); err != nil { - Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) - } - cfg.PrivateKey = key - } -} - -// setNodeUserIdent creates the user identifier from CLI flags. -func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { - if identity := ctx.String(IdentityFlag.Name); len(identity) > 0 { - cfg.UserIdent = identity - } -} - -// setBootstrapNodes creates a list of bootstrap nodes from the command line -// flags, reverting to pre-configured ones if none have been specified. -// Priority order for bootnodes configuration: -// -// 1. --bootnodes flag -// 2. Config file -// 3. Network preset flags (e.g. --goerli) -// 4. default to mainnet nodes -func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { - urls := params.MainnetBootnodes - if ctx.IsSet(BootnodesFlag.Name) { - urls = SplitAndTrim(ctx.String(BootnodesFlag.Name)) - } else { - if cfg.BootstrapNodes != nil { - return // Already set by config file, don't apply defaults. - } - switch { - case ctx.Bool(HoleskyFlag.Name): - urls = params.HoleskyBootnodes - case ctx.Bool(SepoliaFlag.Name): - urls = params.SepoliaBootnodes - case ctx.Bool(GoerliFlag.Name): - urls = params.GoerliBootnodes - } - } - cfg.BootstrapNodes = mustParseBootnodes(urls) -} - -func mustParseBootnodes(urls []string) []*enode.Node { - nodes := make([]*enode.Node, 0, len(urls)) - for _, url := range urls { - if url != "" { - node, err := enode.Parse(enode.ValidSchemes, url) - if err != nil { - log.Crit("Bootstrap URL invalid", "enode", url, "err", err) - return nil - } - nodes = append(nodes, node) - } - } - return nodes -} - -// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line -// flags, reverting to pre-configured ones if none have been specified. -func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { - urls := params.V5Bootnodes - switch { - case ctx.IsSet(BootnodesFlag.Name): - urls = SplitAndTrim(ctx.String(BootnodesFlag.Name)) - case cfg.BootstrapNodesV5 != nil: - return // already set, don't apply defaults. - } - - cfg.BootstrapNodesV5 = make([]*enode.Node, 0, len(urls)) - for _, url := range urls { - if url != "" { - node, err := enode.Parse(enode.ValidSchemes, url) - if err != nil { - log.Error("Bootstrap URL invalid", "enode", url, "err", err) - continue - } - cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) - } - } -} - -// setListenAddress creates TCP/UDP listening address strings from set command -// line flags -func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { - if ctx.IsSet(ListenPortFlag.Name) { - cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name)) - } - if ctx.IsSet(DiscoveryPortFlag.Name) { - cfg.DiscAddr = fmt.Sprintf(":%d", ctx.Int(DiscoveryPortFlag.Name)) - } -} - -// setNAT creates a port mapper from command line flags. -func setNAT(ctx *cli.Context, cfg *p2p.Config) { - if ctx.IsSet(NATFlag.Name) { - natif, err := nat.Parse(ctx.String(NATFlag.Name)) - if err != nil { - Fatalf("Option %s: %v", NATFlag.Name, err) - } - cfg.NAT = natif - } -} - -// SplitAndTrim splits input separated by a comma -// and trims excessive white space from the substrings. -func SplitAndTrim(input string) (ret []string) { - l := strings.Split(input, ",") - for _, r := range l { - if r = strings.TrimSpace(r); r != "" { - ret = append(ret, r) - } - } - return ret -} - -// setHTTP creates the HTTP RPC listener interface string from the set -// command line flags, returning empty if the HTTP endpoint is disabled. -func setHTTP(ctx *cli.Context, cfg *node.Config) { - if ctx.Bool(HTTPEnabledFlag.Name) { - if cfg.HTTPHost == "" { - cfg.HTTPHost = "127.0.0.1" - } - if ctx.IsSet(HTTPListenAddrFlag.Name) { - cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name) - } - } - - if ctx.IsSet(HTTPPortFlag.Name) { - cfg.HTTPPort = ctx.Int(HTTPPortFlag.Name) - } - - if ctx.IsSet(AuthListenFlag.Name) { - cfg.AuthAddr = ctx.String(AuthListenFlag.Name) - } - - if ctx.IsSet(AuthPortFlag.Name) { - cfg.AuthPort = ctx.Int(AuthPortFlag.Name) - } - - if ctx.IsSet(AuthVirtualHostsFlag.Name) { - cfg.AuthVirtualHosts = SplitAndTrim(ctx.String(AuthVirtualHostsFlag.Name)) - } - - if ctx.IsSet(HTTPCORSDomainFlag.Name) { - cfg.HTTPCors = SplitAndTrim(ctx.String(HTTPCORSDomainFlag.Name)) - } - - if ctx.IsSet(HTTPApiFlag.Name) { - cfg.HTTPModules = SplitAndTrim(ctx.String(HTTPApiFlag.Name)) - } - - if ctx.IsSet(HTTPVirtualHostsFlag.Name) { - cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(HTTPVirtualHostsFlag.Name)) - } - - if ctx.IsSet(HTTPPathPrefixFlag.Name) { - cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name) - } - if ctx.IsSet(AllowUnprotectedTxs.Name) { - cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name) - } - - if ctx.IsSet(BatchRequestLimit.Name) { - cfg.BatchRequestLimit = ctx.Int(BatchRequestLimit.Name) - } - - if ctx.IsSet(BatchResponseMaxSize.Name) { - cfg.BatchResponseMaxSize = ctx.Int(BatchResponseMaxSize.Name) - } -} - -// setGraphQL creates the GraphQL listener interface string from the set -// command line flags, returning empty if the GraphQL endpoint is disabled. -func setGraphQL(ctx *cli.Context, cfg *node.Config) { - if ctx.IsSet(GraphQLCORSDomainFlag.Name) { - cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name)) - } - if ctx.IsSet(GraphQLVirtualHostsFlag.Name) { - cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.String(GraphQLVirtualHostsFlag.Name)) - } -} - -// setWS creates the WebSocket RPC listener interface string from the set -// command line flags, returning empty if the HTTP endpoint is disabled. -func setWS(ctx *cli.Context, cfg *node.Config) { - if ctx.Bool(WSEnabledFlag.Name) { - if cfg.WSHost == "" { - cfg.WSHost = "127.0.0.1" - } - if ctx.IsSet(WSListenAddrFlag.Name) { - cfg.WSHost = ctx.String(WSListenAddrFlag.Name) - } - } - if ctx.IsSet(WSPortFlag.Name) { - cfg.WSPort = ctx.Int(WSPortFlag.Name) - } - - if ctx.IsSet(WSAllowedOriginsFlag.Name) { - cfg.WSOrigins = SplitAndTrim(ctx.String(WSAllowedOriginsFlag.Name)) - } - - if ctx.IsSet(WSApiFlag.Name) { - cfg.WSModules = SplitAndTrim(ctx.String(WSApiFlag.Name)) - } - - if ctx.IsSet(WSPathPrefixFlag.Name) { - cfg.WSPathPrefix = ctx.String(WSPathPrefixFlag.Name) - } -} - -// setIPC creates an IPC path configuration from the set command line flags, -// returning an empty string if IPC was explicitly disabled, or the set path. -func setIPC(ctx *cli.Context, cfg *node.Config) { - CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) - switch { - case ctx.Bool(IPCDisabledFlag.Name): - cfg.IPCPath = "" - case ctx.IsSet(IPCPathFlag.Name): - cfg.IPCPath = ctx.String(IPCPathFlag.Name) - } -} - -// setLes shows the deprecation warnings for LES flags. -func setLes(ctx *cli.Context, cfg *ethconfig.Config) { - if ctx.IsSet(LightServeFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightServeFlag.Name) - } - if ctx.IsSet(LightIngressFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightIngressFlag.Name) - } - if ctx.IsSet(LightEgressFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightEgressFlag.Name) - } - if ctx.IsSet(LightMaxPeersFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightMaxPeersFlag.Name) - } - if ctx.IsSet(LightNoPruneFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoPruneFlag.Name) - } - if ctx.IsSet(LightNoSyncServeFlag.Name) { - log.Warn("The light server has been deprecated, please remove this flag", "flag", LightNoSyncServeFlag.Name) - } -} - -// MakeDatabaseHandles raises out the number of allowed file handles per process -// for Geth and returns half of the allowance to assign to the database. -func MakeDatabaseHandles(max int) int { - limit, err := fdlimit.Maximum() - if err != nil { - Fatalf("Failed to retrieve file descriptor allowance: %v", err) - } - switch { - case max == 0: - // User didn't specify a meaningful value, use system limits - case max < 128: - // User specified something unhealthy, just use system defaults - log.Error("File descriptor limit invalid (<128)", "had", max, "updated", limit) - case max > limit: - // User requested more than the OS allows, notify that we can't allocate it - log.Warn("Requested file descriptors denied by OS", "req", max, "limit", limit) - default: - // User limit is meaningful and within allowed range, use that - limit = max - } - raised, err := fdlimit.Raise(uint64(limit)) - if err != nil { - Fatalf("Failed to raise file descriptor allowance: %v", err) - } - return int(raised / 2) // Leave half for networking and other stuff -} - -// MakeAddress converts an account specified directly as a hex encoded string or -// a key index in the key store to an internal account representation. -func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { - // If the specified account is a valid address, return it - if common.IsHexAddress(account) { - return accounts.Account{Address: common.HexToAddress(account)}, nil - } - // Otherwise try to interpret the account as a keystore index - index, err := strconv.Atoi(account) - if err != nil || index < 0 { - return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) - } - log.Warn("-------------------------------------------------------------------") - log.Warn("Referring to accounts by order in the keystore folder is dangerous!") - log.Warn("This functionality is deprecated and will be removed in the future!") - log.Warn("Please use explicit addresses! (can search via `geth account list`)") - log.Warn("-------------------------------------------------------------------") - - accs := ks.Accounts() - if len(accs) <= index { - return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) - } - return accs[index], nil -} - -// setEtherbase retrieves the etherbase from the directly specified command line flags. -func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) { - if !ctx.IsSet(MinerEtherbaseFlag.Name) { - return - } - addr := ctx.String(MinerEtherbaseFlag.Name) - if strings.HasPrefix(addr, "0x") || strings.HasPrefix(addr, "0X") { - addr = addr[2:] - } - b, err := hex.DecodeString(addr) - if err != nil || len(b) != common.AddressLength { - Fatalf("-%s: invalid etherbase address %q", MinerEtherbaseFlag.Name, addr) - return - } - cfg.Miner.Etherbase = common.BytesToAddress(b) -} - -// MakePasswordList reads password lines from the file specified by the global --password flag. -func MakePasswordList(ctx *cli.Context) []string { - path := ctx.Path(PasswordFileFlag.Name) - if path == "" { - return nil - } - text, err := os.ReadFile(path) - if err != nil { - Fatalf("Failed to read password file: %v", err) - } - lines := strings.Split(string(text), "\n") - // Sanitise DOS line endings. - for i := range lines { - lines[i] = strings.TrimRight(lines[i], "\r") - } - return lines -} - -func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { - setNodeKey(ctx, cfg) - setNAT(ctx, cfg) - setListenAddress(ctx, cfg) - setBootstrapNodes(ctx, cfg) - setBootstrapNodesV5(ctx, cfg) - - if ctx.IsSet(MaxPeersFlag.Name) { - cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name) - } - ethPeers := cfg.MaxPeers - log.Info("Maximum peer count", "ETH", ethPeers, "total", cfg.MaxPeers) - - if ctx.IsSet(MaxPendingPeersFlag.Name) { - cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) - } - if ctx.IsSet(NoDiscoverFlag.Name) { - cfg.NoDiscovery = true - } - - CheckExclusive(ctx, DiscoveryV4Flag, NoDiscoverFlag) - CheckExclusive(ctx, DiscoveryV5Flag, NoDiscoverFlag) - cfg.DiscoveryV4 = ctx.Bool(DiscoveryV4Flag.Name) - cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name) - - if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" { - list, err := netutil.ParseNetlist(netrestrict) - if err != nil { - Fatalf("Option %q: %v", NetrestrictFlag.Name, err) - } - cfg.NetRestrict = list - } - - if ctx.Bool(DeveloperFlag.Name) { - // --dev mode can't use p2p networking. - cfg.MaxPeers = 0 - cfg.ListenAddr = "" - cfg.NoDial = true - cfg.NoDiscovery = true - cfg.DiscoveryV5 = false - } -} - -// SetBuilderConfig applies node-related command line flags to the builder config. -func SetBuilderConfig(ctx *cli.Context, cfg *builder.Config) { - if ctx.IsSet(BuilderEnabled.Name) { - cfg.Enabled = ctx.Bool(BuilderEnabled.Name) - } - cfg.EnableValidatorChecks = ctx.IsSet(BuilderEnableValidatorChecks.Name) - cfg.EnableLocalRelay = ctx.IsSet(BuilderEnableLocalRelay.Name) - cfg.SlotsInEpoch = ctx.Uint64(BuilderSlotsInEpoch.Name) - cfg.SecondsInSlot = ctx.Uint64(BuilderSecondsInSlot.Name) - cfg.DisableBundleFetcher = ctx.IsSet(BuilderDisableBundleFetcher.Name) - cfg.DryRun = ctx.IsSet(BuilderDryRun.Name) - cfg.IgnoreLatePayloadAttributes = ctx.IsSet(BuilderIgnoreLatePayloadAttributes.Name) - cfg.BuilderSecretKey = ctx.String(BuilderSecretKey.Name) - cfg.RelaySecretKey = ctx.String(BuilderRelaySecretKey.Name) - cfg.ListenAddr = ctx.String(BuilderListenAddr.Name) - cfg.GenesisForkVersion = ctx.String(BuilderGenesisForkVersion.Name) - cfg.BellatrixForkVersion = ctx.String(BuilderBellatrixForkVersion.Name) - cfg.GenesisValidatorsRoot = ctx.String(BuilderGenesisValidatorsRoot.Name) - cfg.BeaconEndpoints = strings.Split(ctx.String(BuilderBeaconEndpoints.Name), ",") - cfg.RemoteRelayEndpoint = ctx.String(BuilderRemoteRelayEndpoint.Name) - cfg.SecondaryRemoteRelayEndpoints = strings.Split(ctx.String(BuilderSecondaryRemoteRelayEndpoints.Name), ",") - cfg.BuilderMevSidecarEndpoint = ctx.String(BuilderMevSidecarEndpoint.Name) - // NOTE: This flag is deprecated and will be removed in the future in favor of BuilderBlockValidationBlacklistSourceFilePath - if ctx.IsSet(MinerBlocklistFileFlag.Name) { - cfg.ValidationBlocklist = ctx.String(MinerBlocklistFileFlag.Name) - } - - // NOTE: This flag takes precedence and will overwrite value set by MinerBlocklistFileFlag - if ctx.IsSet(BuilderBlockValidationBlacklistSourceFilePath.Name) { - cfg.ValidationBlocklist = ctx.String(BuilderBlockValidationBlacklistSourceFilePath.Name) - } - cfg.ValidationUseCoinbaseDiff = ctx.Bool(BuilderBlockValidationUseBalanceDiff.Name) - cfg.ValidationExcludeWithdrawals = ctx.Bool(BuilderBlockValidationExcludeWithdrawals.Name) - cfg.BuilderRateLimitDuration = ctx.String(BuilderRateLimitDuration.Name) - cfg.BuilderRateLimitMaxBurst = ctx.Int(BuilderRateLimitMaxBurst.Name) - cfg.BuilderSubmissionOffset = ctx.Duration(BuilderSubmissionOffset.Name) - cfg.DiscardRevertibleTxOnErr = ctx.Bool(BuilderDiscardRevertibleTxOnErr.Name) - cfg.EnableCancellations = ctx.IsSet(BuilderEnableCancellations.Name) - cfg.BuilderRateLimitResubmitInterval = ctx.String(BuilderBlockResubmitInterval.Name) - - cfg.BlockProcessorURL = ctx.String(BuilderBlockProcessorURL.Name) -} - -// SetNodeConfig applies node-related command line flags to the config. -func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { - SetP2PConfig(ctx, &cfg.P2P) - setIPC(ctx, cfg) - setHTTP(ctx, cfg) - setGraphQL(ctx, cfg) - setWS(ctx, cfg) - setNodeUserIdent(ctx, cfg) - SetDataDir(ctx, cfg) - setSmartCard(ctx, cfg) - - if ctx.IsSet(JWTSecretFlag.Name) { - cfg.JWTSecret = ctx.String(JWTSecretFlag.Name) - } - - if ctx.IsSet(EnablePersonal.Name) { - cfg.EnablePersonal = true - } - - if ctx.IsSet(ExternalSignerFlag.Name) { - cfg.ExternalSigner = ctx.String(ExternalSignerFlag.Name) - } - - if ctx.IsSet(KeyStoreDirFlag.Name) { - cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name) - } - if ctx.IsSet(DeveloperFlag.Name) { - cfg.UseLightweightKDF = true - } - if ctx.IsSet(LightKDFFlag.Name) { - cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) - } - if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB { - log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") - } - if ctx.IsSet(USBFlag.Name) { - cfg.USB = ctx.Bool(USBFlag.Name) - } - if ctx.IsSet(InsecureUnlockAllowedFlag.Name) { - cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name) - } - if ctx.IsSet(DBEngineFlag.Name) { - dbEngine := ctx.String(DBEngineFlag.Name) - if dbEngine != "leveldb" && dbEngine != "pebble" { - Fatalf("Invalid choice for db.engine '%s', allowed 'leveldb' or 'pebble'", dbEngine) - } - log.Info(fmt.Sprintf("Using %s as db engine", dbEngine)) - cfg.DBEngine = dbEngine - } - // deprecation notice for log debug flags (TODO: find a more appropriate place to put these?) - if ctx.IsSet(LogBacktraceAtFlag.Name) { - log.Warn("log.backtrace flag is deprecated") - } - if ctx.IsSet(LogDebugFlag.Name) { - log.Warn("log.debug flag is deprecated") - } -} - -func setSmartCard(ctx *cli.Context, cfg *node.Config) { - // Skip enabling smartcards if no path is set - path := ctx.String(SmartCardDaemonPathFlag.Name) - if path == "" { - return - } - // Sanity check that the smartcard path is valid - fi, err := os.Stat(path) - if err != nil { - log.Info("Smartcard socket not found, disabling", "err", err) - return - } - if fi.Mode()&os.ModeType != os.ModeSocket { - log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String()) - return - } - // Smartcard daemon path exists and is a socket, enable it - cfg.SmartCardDaemonPath = path -} - -func SetDataDir(ctx *cli.Context, cfg *node.Config) { - switch { - case ctx.IsSet(DataDirFlag.Name): - cfg.DataDir = ctx.String(DataDirFlag.Name) - case ctx.Bool(DeveloperFlag.Name): - cfg.DataDir = "" // unless explicitly requested, use memory databases - case ctx.Bool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir(): - cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") - case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir(): - cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia") - case ctx.Bool(HoleskyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): - cfg.DataDir = filepath.Join(node.DefaultDataDir(), "holesky") - } -} - -func setGPO(ctx *cli.Context, cfg *gasprice.Config) { - if ctx.IsSet(GpoBlocksFlag.Name) { - cfg.Blocks = ctx.Int(GpoBlocksFlag.Name) - } - if ctx.IsSet(GpoPercentileFlag.Name) { - cfg.Percentile = ctx.Int(GpoPercentileFlag.Name) - } - if ctx.IsSet(GpoMaxGasPriceFlag.Name) { - cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name)) - } - if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) { - cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name)) - } -} - -func setTxPool(ctx *cli.Context, cfg *legacypool.Config) { - if ctx.IsSet(TxPoolLocalsFlag.Name) { - locals := strings.Split(ctx.String(TxPoolLocalsFlag.Name), ",") - for _, account := range locals { - if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { - Fatalf("Invalid account in --txpool.locals: %s", trimmed) - } else { - cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) - } - } - } - if ctx.IsSet(TxPoolNoLocalsFlag.Name) { - cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name) - } - if ctx.IsSet(TxPoolJournalFlag.Name) { - cfg.Journal = ctx.String(TxPoolJournalFlag.Name) - } - if ctx.IsSet(TxPoolRejournalFlag.Name) { - cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name) - } - if ctx.IsSet(TxPoolPriceLimitFlag.Name) { - cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name) - } - if ctx.IsSet(TxPoolPriceBumpFlag.Name) { - cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name) - } - if ctx.IsSet(TxPoolAccountSlotsFlag.Name) { - cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name) - } - if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) { - cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name) - } - if ctx.IsSet(TxPoolAccountQueueFlag.Name) { - cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name) - } - if ctx.IsSet(TxPoolGlobalQueueFlag.Name) { - cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name) - } - if ctx.IsSet(TxPoolLifetimeFlag.Name) { - cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) - } - if ctx.IsSet(TxPoolPrivateLifetimeFlag.Name) { - cfg.PrivateTxLifetime = ctx.Duration(TxPoolPrivateLifetimeFlag.Name) - } -} - -func setMiner(ctx *cli.Context, cfg *miner.Config) { - if ctx.IsSet(MinerExtraDataFlag.Name) { - cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name)) - } - if ctx.IsSet(MinerGasLimitFlag.Name) { - cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name) - } - if ctx.IsSet(MinerGasPriceFlag.Name) { - cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name) - } - // NOTE: This flag is deprecated and will be removed in the future. - if ctx.IsSet(MinerAlgoTypeFlag.Name) { - algoType, err := miner.AlgoTypeFlagToEnum(ctx.String(BuilderAlgoTypeFlag.Name)) - if err != nil { - Fatalf("Invalid algo in --miner.algotype: %s", ctx.String(BuilderAlgoTypeFlag.Name)) - } - cfg.AlgoType = algoType - } - // NOTE: BuilderAlgoTypeFlag takes precedence and will overwrite value set by MinerAlgoTypeFlag. - if ctx.IsSet(BuilderAlgoTypeFlag.Name) { - algoType, err := miner.AlgoTypeFlagToEnum(ctx.String(BuilderAlgoTypeFlag.Name)) - if err != nil { - Fatalf("Invalid algo in --builder.algotype: %s", ctx.String(BuilderAlgoTypeFlag.Name)) - } - cfg.AlgoType = algoType - } - if ctx.IsSet(MinerRecommitIntervalFlag.Name) { - cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) - } - if ctx.IsSet(MinerNewPayloadTimeout.Name) { - cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name) - } - - cfg.MaxMergedBundles = ctx.Int(MinerMaxMergedBundlesFlag.Name) - - // NOTE: This flag is deprecated and will be removed in the future in favor of BuilderBlockValidationBlacklistSourceFilePath - if ctx.IsSet(MinerBlocklistFileFlag.Name) { - bytes, err := os.ReadFile(ctx.String(MinerBlocklistFileFlag.Name)) - if err != nil { - Fatalf("Failed to read blocklist file: %s", err) - } - - if err := json.Unmarshal(bytes, &cfg.Blocklist); err != nil { - Fatalf("Failed to parse blocklist: %s", err) - } - } - - // NOTE: This flag takes precedence and will overwrite value set by MinerBlocklistFileFlag - if ctx.IsSet(BuilderBlockValidationBlacklistSourceFilePath.Name) { - bytes, err := os.ReadFile(ctx.String(BuilderBlockValidationBlacklistSourceFilePath.Name)) - if err != nil { - Fatalf("Failed to read blocklist file: %s", err) - } - - if err := json.Unmarshal(bytes, &cfg.Blocklist); err != nil { - Fatalf("Failed to parse blocklist: %s", err) - } - } - - cfg.DiscardRevertibleTxOnErr = ctx.Bool(BuilderDiscardRevertibleTxOnErr.Name) - cfg.PriceCutoffPercent = ctx.Int(BuilderPriceCutoffPercentFlag.Name) -} - -func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) { - requiredBlocks := ctx.String(EthRequiredBlocksFlag.Name) - if requiredBlocks == "" { - if ctx.IsSet(LegacyWhitelistFlag.Name) { - log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks") - requiredBlocks = ctx.String(LegacyWhitelistFlag.Name) - } else { - return - } - } - cfg.RequiredBlocks = make(map[uint64]common.Hash) - for _, entry := range strings.Split(requiredBlocks, ",") { - parts := strings.Split(entry, "=") - if len(parts) != 2 { - Fatalf("Invalid required block entry: %s", entry) - } - number, err := strconv.ParseUint(parts[0], 0, 64) - if err != nil { - Fatalf("Invalid required block number %s: %v", parts[0], err) - } - var hash common.Hash - if err = hash.UnmarshalText([]byte(parts[1])); err != nil { - Fatalf("Invalid required block hash %s: %v", parts[1], err) - } - cfg.RequiredBlocks[number] = hash - } -} - -// CheckExclusive verifies that only a single instance of the provided flags was -// set by the user. Each flag might optionally be followed by a string type to -// specialize it further. -func CheckExclusive(ctx *cli.Context, args ...interface{}) { - set := make([]string, 0, 1) - for i := 0; i < len(args); i++ { - // Make sure the next argument is a flag and skip if not set - flag, ok := args[i].(cli.Flag) - if !ok { - panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) - } - // Check if next arg extends current and expand its name if so - name := flag.Names()[0] - - if i+1 < len(args) { - switch option := args[i+1].(type) { - case string: - // Extended flag check, make sure value set doesn't conflict with passed in option - if ctx.String(flag.Names()[0]) == option { - name += "=" + option - set = append(set, "--"+name) - } - // shift arguments and continue - i++ - continue - - case cli.Flag: - default: - panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) - } - } - // Mark the flag if it's set - if ctx.IsSet(flag.Names()[0]) { - set = append(set, "--"+name) - } - } - if len(set) > 1 { - Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) - } -} - -// SetEthConfig applies eth-related command line flags to the config. -func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { - // Avoid conflicting network flags - CheckExclusive(ctx, MainnetFlag, DeveloperFlag, GoerliFlag, SepoliaFlag, HoleskyFlag) - CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer - - // Set configurations from CLI flags - setEtherbase(ctx, cfg) - setGPO(ctx, &cfg.GPO) - setTxPool(ctx, &cfg.TxPool) - setMiner(ctx, &cfg.Miner) - setRequiredBlocks(ctx, cfg) - setLes(ctx, cfg) - - // Cap the cache allowance and tune the garbage collector - mem, err := gopsutil.VirtualMemory() - if err == nil { - if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 { - log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024) - mem.Total = 2 * 1024 * 1024 * 1024 - } - allowance := int(mem.Total / 1024 / 1024 / 3) - if cache := ctx.Int(CacheFlag.Name); cache > allowance { - log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) - ctx.Set(CacheFlag.Name, strconv.Itoa(allowance)) - } - } - // Ensure Go's GC ignores the database cache for trigger percentage - cache := ctx.Int(CacheFlag.Name) - gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) - - log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) - godebug.SetGCPercent(int(gogc)) - - if ctx.IsSet(SyncTargetFlag.Name) { - cfg.SyncMode = downloader.FullSync // dev sync target forces full sync - } else if ctx.IsSet(SyncModeFlag.Name) { - cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) - } - if ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) - } - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) { - cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 - } - cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) - if ctx.IsSet(AncientFlag.Name) { - cfg.DatabaseFreezer = ctx.String(AncientFlag.Name) - } - - if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { - Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) - } - if ctx.IsSet(GCModeFlag.Name) { - cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" - } - if ctx.IsSet(CacheNoPrefetchFlag.Name) { - cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) - } - // Read the value from the flag no matter if it's set or not. - cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name) - if cfg.NoPruning && !cfg.Preimages { - cfg.Preimages = true - log.Info("Enabling recording of key preimages since archive mode is used") - } - if ctx.IsSet(StateHistoryFlag.Name) { - cfg.StateHistory = ctx.Uint64(StateHistoryFlag.Name) - } - if ctx.IsSet(StateSchemeFlag.Name) { - cfg.StateScheme = ctx.String(StateSchemeFlag.Name) - } - // Parse transaction history flag, if user is still using legacy config - // file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'. - if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit { - log.Warn("The config option 'TxLookupLimit' is deprecated and will be removed, please use 'TransactionHistory'") - cfg.TransactionHistory = cfg.TxLookupLimit - } - if ctx.IsSet(TransactionHistoryFlag.Name) { - cfg.TransactionHistory = ctx.Uint64(TransactionHistoryFlag.Name) - } else if ctx.IsSet(TxLookupLimitFlag.Name) { - log.Warn("The flag --txlookuplimit is deprecated and will be removed, please use --history.transactions") - cfg.TransactionHistory = ctx.Uint64(TxLookupLimitFlag.Name) - } - if ctx.String(GCModeFlag.Name) == "archive" && cfg.TransactionHistory != 0 { - cfg.TransactionHistory = 0 - log.Warn("Disabled transaction unindexing for archive node") - } - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { - cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 - } - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { - cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 - } - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { - cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 - } - if ctx.IsSet(CacheLogSizeFlag.Name) { - cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name) - } - if !ctx.Bool(SnapshotFlag.Name) || cfg.SnapshotCache == 0 { - // If snap-sync is requested, this flag is also required - if cfg.SyncMode == downloader.SnapSync { - if !ctx.Bool(SnapshotFlag.Name) { - log.Warn("Snap sync requested, enabling --snapshot") - } - if cfg.SnapshotCache == 0 { - log.Warn("Snap sync requested, resetting --cache.snapshot") - cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * CacheSnapshotFlag.Value / 100 - } - } else { - cfg.TrieCleanCache += cfg.SnapshotCache - cfg.SnapshotCache = 0 // Disabled - } - } - if ctx.IsSet(DocRootFlag.Name) { - cfg.DocRoot = ctx.String(DocRootFlag.Name) - } - if ctx.IsSet(VMEnableDebugFlag.Name) { - // TODO(fjl): force-enable this in --dev mode - cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) - } - - if ctx.IsSet(RPCGlobalGasCapFlag.Name) { - cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name) - } - if cfg.RPCGasCap != 0 { - log.Info("Set global gas cap", "cap", cfg.RPCGasCap) - } else { - log.Info("Global gas cap disabled") - } - if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) { - cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) - } - if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) { - cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name) - } - if ctx.IsSet(NoDiscoverFlag.Name) { - cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{} - } else if ctx.IsSet(DNSDiscoveryFlag.Name) { - urls := ctx.String(DNSDiscoveryFlag.Name) - if urls == "" { - cfg.EthDiscoveryURLs = []string{} - } else { - cfg.EthDiscoveryURLs = SplitAndTrim(urls) - } - } - // Override any default configs for hard coded networks. - switch { - case ctx.Bool(MainnetFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1 - } - cfg.Genesis = core.DefaultGenesisBlock() - SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) - case ctx.Bool(HoleskyFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 17000 - } - cfg.Genesis = core.DefaultHoleskyGenesisBlock() - SetDNSDiscoveryDefaults(cfg, params.HoleskyGenesisHash) - case ctx.Bool(SepoliaFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 11155111 - } - cfg.Genesis = core.DefaultSepoliaGenesisBlock() - SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash) - case ctx.Bool(GoerliFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 5 - } - cfg.Genesis = core.DefaultGoerliGenesisBlock() - SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash) - case ctx.Bool(DeveloperFlag.Name): - if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1337 - } - cfg.SyncMode = downloader.FullSync - // Create new developer account or reuse existing one - var ( - developer accounts.Account - passphrase string - err error - ) - if list := MakePasswordList(ctx); len(list) > 0 { - // Just take the first value. Although the function returns a possible multiple values and - // some usages iterate through them as attempts, that doesn't make sense in this setting, - // when we're definitely concerned with only one account. - passphrase = list[0] - } - - // Unlock the developer account by local keystore. - var ks *keystore.KeyStore - if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { - ks = keystores[0].(*keystore.KeyStore) - } - if ks == nil { - Fatalf("Keystore is not available") - } - - // Figure out the dev account address. - // setEtherbase has been called above, configuring the miner address from command line flags. - if cfg.Miner.Etherbase != (common.Address{}) { - developer = accounts.Account{Address: cfg.Miner.Etherbase} - } else if accs := ks.Accounts(); len(accs) > 0 { - developer = ks.Accounts()[0] - } else { - developer, err = ks.NewAccount(passphrase) - if err != nil { - Fatalf("Failed to create developer account: %v", err) - } - } - // Make sure the address is configured as fee recipient, otherwise - // the miner will fail to start. - cfg.Miner.Etherbase = developer.Address - - if err := ks.Unlock(developer, passphrase); err != nil { - Fatalf("Failed to unlock developer account: %v", err) - } - log.Info("Using developer account", "address", developer.Address) - - // Create a new developer genesis block or reuse existing one - cfg.Genesis = core.DeveloperGenesisBlock(ctx.Uint64(DeveloperGasLimitFlag.Name), &developer.Address) - if ctx.IsSet(DataDirFlag.Name) { - chaindb := tryMakeReadOnlyDatabase(ctx, stack) - if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { - cfg.Genesis = nil // fallback to db content - - //validate genesis has PoS enabled in block 0 - genesis, err := core.ReadGenesis(chaindb) - if err != nil { - Fatalf("Could not read genesis from database: %v", err) - } - if !genesis.Config.TerminalTotalDifficultyPassed { - Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true in developer mode") - } - if genesis.Config.TerminalTotalDifficulty == nil { - Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified.") - } - if genesis.Difficulty.Cmp(genesis.Config.TerminalTotalDifficulty) != 1 { - Fatalf("Bad developer-mode genesis configuration: genesis block difficulty must be > terminalTotalDifficulty") - } - } - chaindb.Close() - } - if !ctx.IsSet(MinerGasPriceFlag.Name) { - cfg.Miner.GasPrice = big.NewInt(1) - } - default: - if cfg.NetworkId == 1 { - SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) - } - } - // Set any dangling config values - if ctx.String(CryptoKZGFlag.Name) != "gokzg" && ctx.String(CryptoKZGFlag.Name) != "ckzg" { - Fatalf("--%s flag must be 'gokzg' or 'ckzg'", CryptoKZGFlag.Name) - } - log.Info("Initializing the KZG library", "backend", ctx.String(CryptoKZGFlag.Name)) - if err := kzg4844.UseCKZG(ctx.String(CryptoKZGFlag.Name) == "ckzg"); err != nil { - Fatalf("Failed to set KZG library implementation to %s: %v", ctx.String(CryptoKZGFlag.Name), err) - } -} - -// SetDNSDiscoveryDefaults configures DNS discovery with the given URL if -// no URLs are set. -func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { - if cfg.EthDiscoveryURLs != nil { - return // already set through flags/config - } - protocol := "all" - if url := params.KnownDNSNetwork(genesis, protocol); url != "" { - cfg.EthDiscoveryURLs = []string{url} - cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs - } -} - -// RegisterEthService adds an Ethereum client to the stack. -// The second return value is the full node instance. -func RegisterEthService(stack *node.Node, cfg *ethconfig.Config, bpCfg *builder.Config) (ethapi.Backend, *eth.Ethereum) { - backend, err := eth.New(stack, cfg) - if err != nil { - Fatalf("Failed to register the Ethereum service: %v", err) - } - - if bpCfg.Enabled { - if err := builder.Register(stack, backend, bpCfg); err != nil { - Fatalf("Failed to register the builder service: %v", err) - } - } - - stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) - return backend.APIBackend, backend -} - -// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node. -func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) { - if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil { - Fatalf("Failed to register the Ethereum Stats service: %v", err) - } -} - -// RegisterGraphQLService adds the GraphQL API to the node. -func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cfg *node.Config) { - err := graphql.New(stack, backend, filterSystem, cfg.GraphQLCors, cfg.GraphQLVirtualHosts) - if err != nil { - Fatalf("Failed to register the GraphQL service: %v", err) - } -} - -// RegisterFilterAPI adds the eth log filtering RPC API to the node. -func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem { - filterSystem := filters.NewFilterSystem(backend, filters.Config{ - LogCacheSize: ethcfg.FilterLogCacheSize, - }) - stack.RegisterAPIs([]rpc.API{{ - Namespace: "eth", - Service: filters.NewFilterAPI(filterSystem, false), - }}) - return filterSystem -} - -// RegisterFullSyncTester adds the full-sync tester service into node. -func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.Hash) { - catalyst.RegisterFullSyncTester(stack, eth, target) - log.Info("Registered full-sync tester", "hash", target) -} - -func SetupMetrics(ctx *cli.Context) { - if metrics.Enabled { - log.Info("Enabling metrics collection") - - var ( - enableExport = ctx.Bool(MetricsEnableInfluxDBFlag.Name) - enableExportV2 = ctx.Bool(MetricsEnableInfluxDBV2Flag.Name) - ) - - if enableExport || enableExportV2 { - CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag) - - v1FlagIsSet := ctx.IsSet(MetricsInfluxDBUsernameFlag.Name) || - ctx.IsSet(MetricsInfluxDBPasswordFlag.Name) - - v2FlagIsSet := ctx.IsSet(MetricsInfluxDBTokenFlag.Name) || - ctx.IsSet(MetricsInfluxDBOrganizationFlag.Name) || - ctx.IsSet(MetricsInfluxDBBucketFlag.Name) - - if enableExport && v2FlagIsSet { - Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2") - } else if enableExportV2 && v1FlagIsSet { - Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1") - } - } - - var ( - endpoint = ctx.String(MetricsInfluxDBEndpointFlag.Name) - database = ctx.String(MetricsInfluxDBDatabaseFlag.Name) - username = ctx.String(MetricsInfluxDBUsernameFlag.Name) - password = ctx.String(MetricsInfluxDBPasswordFlag.Name) - - token = ctx.String(MetricsInfluxDBTokenFlag.Name) - bucket = ctx.String(MetricsInfluxDBBucketFlag.Name) - organization = ctx.String(MetricsInfluxDBOrganizationFlag.Name) - ) - - if enableExport { - tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name)) - - log.Info("Enabling metrics export to InfluxDB") - - go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) - } else if enableExportV2 { - tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name)) - - log.Info("Enabling metrics export to InfluxDB (v2)") - - go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) - } - - if ctx.IsSet(MetricsHTTPFlag.Name) { - address := net.JoinHostPort(ctx.String(MetricsHTTPFlag.Name), fmt.Sprintf("%d", ctx.Int(MetricsPortFlag.Name))) - log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) - exp.Setup(address) - } else if ctx.IsSet(MetricsPortFlag.Name) { - log.Warn(fmt.Sprintf("--%s specified without --%s, metrics server will not start.", MetricsPortFlag.Name, MetricsHTTPFlag.Name)) - } - } -} - -func SplitTagsFlag(tagsFlag string) map[string]string { - tags := strings.Split(tagsFlag, ",") - tagsMap := map[string]string{} - - for _, t := range tags { - if t != "" { - kv := strings.Split(t, "=") - - if len(kv) == 2 { - tagsMap[kv[0]] = kv[1] - } - } - } - - return tagsMap -} - -// MakeChainDatabase opens a database using the flags passed to the client and will hard crash if it fails. -func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database { - var ( - cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 - handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) - err error - chainDb ethdb.Database - ) - switch { - case ctx.IsSet(RemoteDBFlag.Name): - log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name), "headers", len(ctx.StringSlice(HttpHeaderFlag.Name))) - client, err := DialRPCWithHeaders(ctx.String(RemoteDBFlag.Name), ctx.StringSlice(HttpHeaderFlag.Name)) - if err != nil { - break - } - chainDb = remotedb.New(client) - case ctx.String(SyncModeFlag.Name) == "light": - chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) - default: - chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly) - } - if err != nil { - Fatalf("Could not open database: %v", err) - } - return chainDb -} - -// tryMakeReadOnlyDatabase try to open the chain database in read-only mode, -// or fallback to write mode if the database is not initialized. -func tryMakeReadOnlyDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { - // If the database doesn't exist we need to open it in write-mode to allow - // the engine to create files. - readonly := true - if rawdb.PreexistingDatabase(stack.ResolvePath("chaindata")) == "" { - readonly = false - } - return MakeChainDatabase(ctx, stack, readonly) -} - -func IsNetworkPreset(ctx *cli.Context) bool { - for _, flag := range NetworkFlags { - bFlag, _ := flag.(*cli.BoolFlag) - if ctx.IsSet(bFlag.Name) { - return true - } - } - return false -} - -func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error) { - if endpoint == "" { - return nil, errors.New("endpoint must be specified") - } - if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { - // Backwards compatibility with geth < 1.5 which required - // these prefixes. - endpoint = endpoint[4:] - } - var opts []rpc.ClientOption - if len(headers) > 0 { - customHeaders := make(http.Header) - for _, h := range headers { - kv := strings.Split(h, ":") - if len(kv) != 2 { - return nil, fmt.Errorf("invalid http header directive: %q", h) - } - customHeaders.Add(kv[0], kv[1]) - } - opts = append(opts, rpc.WithHeaders(customHeaders)) - } - return rpc.DialOptions(context.Background(), endpoint, opts...) -} - -func MakeGenesis(ctx *cli.Context) *core.Genesis { - var genesis *core.Genesis - switch { - case ctx.Bool(MainnetFlag.Name): - genesis = core.DefaultGenesisBlock() - case ctx.Bool(HoleskyFlag.Name): - genesis = core.DefaultHoleskyGenesisBlock() - case ctx.Bool(SepoliaFlag.Name): - genesis = core.DefaultSepoliaGenesisBlock() - case ctx.Bool(GoerliFlag.Name): - genesis = core.DefaultGoerliGenesisBlock() - case ctx.Bool(DeveloperFlag.Name): - Fatalf("Developer chains are ephemeral") - } - return genesis -} - -// MakeChain creates a chain manager from set command line flags. -func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockChain, ethdb.Database) { - var ( - gspec = MakeGenesis(ctx) - chainDb = MakeChainDatabase(ctx, stack, readonly) - ) - config, err := core.LoadChainConfig(chainDb, gspec) - if err != nil { - Fatalf("%v", err) - } - engine, err := ethconfig.CreateConsensusEngine(config, chainDb) - if err != nil { - Fatalf("%v", err) - } - if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { - Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) - } - scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), chainDb) - if err != nil { - Fatalf("%v", err) - } - cache := &core.CacheConfig{ - TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, - TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), - TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, - TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", - TrieTimeLimit: ethconfig.Defaults.TrieTimeout, - SnapshotLimit: ethconfig.Defaults.SnapshotCache, - Preimages: ctx.Bool(CachePreimagesFlag.Name), - StateScheme: scheme, - StateHistory: ctx.Uint64(StateHistoryFlag.Name), - } - if cache.TrieDirtyDisabled && !cache.Preimages { - cache.Preimages = true - log.Info("Enabling recording of key preimages since archive mode is used") - } - if !ctx.Bool(SnapshotFlag.Name) { - cache.SnapshotLimit = 0 // Disabled - } - // If we're in readonly, do not bother generating snapshot data. - if readonly { - cache.SnapshotNoBuild = true - } - - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { - cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 - } - if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { - cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 - } - vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)} - - // Disable transaction indexing/unindexing by default. - chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil) - if err != nil { - Fatalf("Can't create BlockChain: %v", err) - } - return chain, chainDb -} - -// MakeConsolePreloads retrieves the absolute paths for the console JavaScript -// scripts to preload before starting. -func MakeConsolePreloads(ctx *cli.Context) []string { - // Skip preloading if there's nothing to preload - if ctx.String(PreloadJSFlag.Name) == "" { - return nil - } - // Otherwise resolve absolute paths and return them - var preloads []string - - for _, file := range strings.Split(ctx.String(PreloadJSFlag.Name), ",") { - preloads = append(preloads, strings.TrimSpace(file)) - } - return preloads -} - -// MakeTrieDatabase constructs a trie database based on the configured scheme. -func MakeTrieDatabase(ctx *cli.Context, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool) *triedb.Database { - config := &triedb.Config{ - Preimages: preimage, - IsVerkle: isVerkle, - } - scheme, err := rawdb.ParseStateScheme(ctx.String(StateSchemeFlag.Name), disk) - if err != nil { - Fatalf("%v", err) - } - if scheme == rawdb.HashScheme { - // Read-only mode is not implemented in hash mode, - // ignore the parameter silently. TODO(rjl493456442) - // please config it if read mode is implemented. - config.HashDB = hashdb.Defaults - return triedb.NewDatabase(disk, config) - } - if readOnly { - config.PathDB = pathdb.ReadOnly - } else { - config.PathDB = pathdb.Defaults - } - return triedb.NewDatabase(disk, config) -} diff --git a/builder/cmd/utils/flags_legacy.go b/builder/cmd/utils/flags_legacy.go deleted file mode 100644 index 243abd831..000000000 --- a/builder/cmd/utils/flags_legacy.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package utils - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/flags" - "github.com/urfave/cli/v2" -) - -var ShowDeprecated = &cli.Command{ - Action: showDeprecated, - Name: "show-deprecated-flags", - Usage: "Show flags that have been deprecated", - ArgsUsage: " ", - Description: "Show flags that have been deprecated and will soon be removed", -} - -var DeprecatedFlags = []cli.Flag{ - NoUSBFlag, - LegacyWhitelistFlag, - CacheTrieJournalFlag, - CacheTrieRejournalFlag, - LegacyDiscoveryV5Flag, - TxLookupLimitFlag, - LightServeFlag, - LightIngressFlag, - LightEgressFlag, - LightMaxPeersFlag, - LightNoPruneFlag, - LightNoSyncServeFlag, - LogBacktraceAtFlag, - LogDebugFlag, -} - -var ( - // Deprecated May 2020, shown in aliased flags section - NoUSBFlag = &cli.BoolFlag{ - Name: "nousb", - Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)", - Category: flags.DeprecatedCategory, - } - // Deprecated March 2022 - LegacyWhitelistFlag = &cli.StringFlag{ - Name: "whitelist", - Usage: "Comma separated block number-to-hash mappings to enforce (=) (deprecated in favor of --eth.requiredblocks)", - Category: flags.DeprecatedCategory, - } - // Deprecated July 2023 - CacheTrieJournalFlag = &cli.StringFlag{ - Name: "cache.trie.journal", - Usage: "Disk journal directory for trie cache to survive node restarts", - Category: flags.DeprecatedCategory, - } - CacheTrieRejournalFlag = &cli.DurationFlag{ - Name: "cache.trie.rejournal", - Usage: "Time interval to regenerate the trie cache journal", - Category: flags.DeprecatedCategory, - } - LegacyDiscoveryV5Flag = &cli.BoolFlag{ - Name: "v5disc", - Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism (deprecated, use --discv5 instead)", - Category: flags.DeprecatedCategory, - } - // Deprecated August 2023 - TxLookupLimitFlag = &cli.Uint64Flag{ - Name: "txlookuplimit", - Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain) (deprecated, use history.transactions instead)", - Value: ethconfig.Defaults.TransactionHistory, - Category: flags.DeprecatedCategory, - } - // Light server and client settings, Deprecated November 2023 - LightServeFlag = &cli.IntFlag{ - Name: "light.serve", - Usage: "Maximum percentage of time allowed for serving LES requests (deprecated)", - Value: ethconfig.Defaults.LightServ, - Category: flags.LightCategory, - } - LightIngressFlag = &cli.IntFlag{ - Name: "light.ingress", - Usage: "Incoming bandwidth limit for serving light clients (deprecated)", - Value: ethconfig.Defaults.LightIngress, - Category: flags.LightCategory, - } - LightEgressFlag = &cli.IntFlag{ - Name: "light.egress", - Usage: "Outgoing bandwidth limit for serving light clients (deprecated)", - Value: ethconfig.Defaults.LightEgress, - Category: flags.LightCategory, - } - LightMaxPeersFlag = &cli.IntFlag{ - Name: "light.maxpeers", - Usage: "Maximum number of light clients to serve, or light servers to attach to (deprecated)", - Value: ethconfig.Defaults.LightPeers, - Category: flags.LightCategory, - } - LightNoPruneFlag = &cli.BoolFlag{ - Name: "light.nopruning", - Usage: "Disable ancient light chain data pruning (deprecated)", - Category: flags.LightCategory, - } - LightNoSyncServeFlag = &cli.BoolFlag{ - Name: "light.nosyncserve", - Usage: "Enables serving light clients before syncing (deprecated)", - Category: flags.LightCategory, - } - // Deprecated November 2023 - LogBacktraceAtFlag = &cli.StringFlag{ - Name: "log.backtrace", - Usage: "Request a stack trace at a specific logging statement (deprecated)", - Value: "", - Category: flags.DeprecatedCategory, - } - LogDebugFlag = &cli.BoolFlag{ - Name: "log.debug", - Usage: "Prepends log messages with call-site location (deprecated)", - Category: flags.DeprecatedCategory, - } -) - -// showDeprecated displays deprecated flags that will be soon removed from the codebase. -func showDeprecated(*cli.Context) error { - fmt.Println("--------------------------------------------------------------------") - fmt.Println("The following flags are deprecated and will be removed in the future!") - fmt.Println("--------------------------------------------------------------------") - fmt.Println() - for _, flag := range DeprecatedFlags { - fmt.Println(flag.String()) - } - fmt.Println() - return nil -} diff --git a/builder/cmd/utils/flags_test.go b/builder/cmd/utils/flags_test.go deleted file mode 100644 index 00c73a526..000000000 --- a/builder/cmd/utils/flags_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// Package utils contains internal helper functions for go-ethereum commands. -package utils - -import ( - "reflect" - "testing" -) - -func Test_SplitTagsFlag(t *testing.T) { - t.Parallel() - tests := []struct { - name string - args string - want map[string]string - }{ - { - "2 tags case", - "host=localhost,bzzkey=123", - map[string]string{ - "host": "localhost", - "bzzkey": "123", - }, - }, - { - "1 tag case", - "host=localhost123", - map[string]string{ - "host": "localhost123", - }, - }, - { - "empty case", - "", - map[string]string{}, - }, - { - "garbage", - "smth=smthelse=123", - map[string]string{}, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) { - t.Errorf("splitTagsFlag() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/builder/cmd/utils/history_test.go b/builder/cmd/utils/history_test.go deleted file mode 100644 index 9b7f1797d..000000000 --- a/builder/cmd/utils/history_test.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2023 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -package utils - -import ( - "bytes" - "crypto/sha256" - "io" - "math/big" - "os" - "path" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/era" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" -) - -var ( - count uint64 = 128 - step uint64 = 16 -) - -func TestHistoryImportAndExport(t *testing.T) { - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{address: {Balance: big.NewInt(1000000000000000000)}}, - } - signer = types.LatestSigner(genesis.Config) - ) - - // Generate chain. - db, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), int(count), func(i int, g *core.BlockGen) { - if i == 0 { - return - } - tx, err := types.SignNewTx(key, signer, &types.DynamicFeeTx{ - ChainID: genesis.Config.ChainID, - Nonce: uint64(i - 1), - GasTipCap: common.Big0, - GasFeeCap: g.PrevBlock(0).BaseFee(), - Gas: 50000, - To: &common.Address{0xaa}, - Value: big.NewInt(int64(i)), - Data: nil, - AccessList: nil, - }) - if err != nil { - t.Fatalf("error creating tx: %v", err) - } - g.AddTx(tx) - }) - - // Initialize BlockChain. - chain, err := core.NewBlockChain(db, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("unable to initialize chain: %v", err) - } - if _, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("error insterting chain: %v", err) - } - - // Make temp directory for era files. - dir, err := os.MkdirTemp("", "history-export-test") - if err != nil { - t.Fatalf("error creating temp test directory: %v", err) - } - defer os.RemoveAll(dir) - - // Export history to temp directory. - if err := ExportHistory(chain, dir, 0, count, step); err != nil { - t.Fatalf("error exporting history: %v", err) - } - - // Read checksums. - b, err := os.ReadFile(path.Join(dir, "checksums.txt")) - if err != nil { - t.Fatalf("failed to read checksums: %v", err) - } - checksums := strings.Split(string(b), "\n") - - // Verify each Era. - entries, _ := era.ReadDir(dir, "mainnet") - for i, filename := range entries { - func() { - f, err := os.Open(path.Join(dir, filename)) - if err != nil { - t.Fatalf("error opening era file: %v", err) - } - var ( - h = sha256.New() - buf = bytes.NewBuffer(nil) - ) - if _, err := io.Copy(h, f); err != nil { - t.Fatalf("unable to recalculate checksum: %v", err) - } - if got, want := common.BytesToHash(h.Sum(buf.Bytes()[:])).Hex(), checksums[i]; got != want { - t.Fatalf("checksum %d does not match: got %s, want %s", i, got, want) - } - e, err := era.From(f) - if err != nil { - t.Fatalf("error opening era: %v", err) - } - defer e.Close() - it, err := era.NewIterator(e) - if err != nil { - t.Fatalf("error making era reader: %v", err) - } - for j := 0; it.Next(); j++ { - n := i*int(step) + j - if it.Error() != nil { - t.Fatalf("error reading block entry %d: %v", n, it.Error()) - } - block, receipts, err := it.BlockAndReceipts() - if err != nil { - t.Fatalf("error reading block entry %d: %v", n, err) - } - want := chain.GetBlockByNumber(uint64(n)) - if want, got := uint64(n), block.NumberU64(); want != got { - t.Fatalf("blocks out of order: want %d, got %d", want, got) - } - if want.Hash() != block.Hash() { - t.Fatalf("block hash mismatch %d: want %s, got %s", n, want.Hash().Hex(), block.Hash().Hex()) - } - if got := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); got != want.TxHash() { - t.Fatalf("tx hash %d mismatch: want %s, got %s", n, want.TxHash(), got) - } - if got := types.CalcUncleHash(block.Uncles()); got != want.UncleHash() { - t.Fatalf("uncle hash %d mismatch: want %s, got %s", n, want.UncleHash(), got) - } - if got := types.DeriveSha(receipts, trie.NewStackTrie(nil)); got != want.ReceiptHash() { - t.Fatalf("receipt root %d mismatch: want %s, got %s", n, want.ReceiptHash(), got) - } - } - }() - } - - // Now import Era. - freezer := t.TempDir() - db2, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false) - if err != nil { - panic(err) - } - t.Cleanup(func() { - db2.Close() - }) - - genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults)) - imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("unable to initialize chain: %v", err) - } - if err := ImportHistory(imported, db2, dir, "mainnet"); err != nil { - t.Fatalf("failed to import chain: %v", err) - } - if have, want := imported.CurrentHeader(), chain.CurrentHeader(); have.Hash() != want.Hash() { - t.Fatalf("imported chain does not match expected, have (%d, %s) want (%d, %s)", have.Number, have.Hash(), want.Number, want.Hash()) - } -} diff --git a/builder/cmd/utils/prompt.go b/builder/cmd/utils/prompt.go deleted file mode 100644 index f513e3818..000000000 --- a/builder/cmd/utils/prompt.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// Package utils contains internal helper functions for go-ethereum commands. -package utils - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/console/prompt" -) - -// GetPassPhrase displays the given text(prompt) to the user and requests some textual -// data to be entered, but one which must not be echoed out into the terminal. -// The method returns the input provided by the user. -func GetPassPhrase(text string, confirmation bool) string { - if text != "" { - fmt.Println(text) - } - password, err := prompt.Stdin.PromptPassword("Password: ") - if err != nil { - Fatalf("Failed to read password: %v", err) - } - if confirmation { - confirm, err := prompt.Stdin.PromptPassword("Repeat password: ") - if err != nil { - Fatalf("Failed to read password confirmation: %v", err) - } - if password != confirm { - Fatalf("Passwords do not match") - } - } - return password -} - -// GetPassPhraseWithList retrieves the password associated with an account, either fetched -// from a list of preloaded passphrases, or requested interactively from the user. -func GetPassPhraseWithList(text string, confirmation bool, index int, passwords []string) string { - // If a list of passwords was supplied, retrieve from them - if len(passwords) > 0 { - if index < len(passwords) { - return passwords[index] - } - return passwords[len(passwords)-1] - } - // Otherwise prompt the user for the password - password := GetPassPhrase(text, confirmation) - return password -} diff --git a/builder/cmd/utils/prompt_test.go b/builder/cmd/utils/prompt_test.go deleted file mode 100644 index 889bf71de..000000000 --- a/builder/cmd/utils/prompt_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum 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. -// -// go-ethereum 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 go-ethereum. If not, see . - -// Package utils contains internal helper functions for go-ethereum commands. -package utils - -import ( - "testing" -) - -func TestGetPassPhraseWithList(t *testing.T) { - t.Parallel() - type args struct { - text string - confirmation bool - index int - passwords []string - } - tests := []struct { - name string - args args - want string - }{ - { - "test1", - args{ - "text1", - false, - 0, - []string{"zero", "one", "two"}, - }, - "zero", - }, - { - "test2", - args{ - "text2", - false, - 5, - []string{"zero", "one", "two"}, - }, - "two", - }, - { - "test3", - args{ - "text3", - true, - 1, - []string{"zero", "one", "two"}, - }, - "one", - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := GetPassPhraseWithList(tt.args.text, tt.args.confirmation, tt.args.index, tt.args.passwords); got != tt.want { - t.Errorf("GetPassPhraseWithList() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/builder/common/big.go b/builder/common/big.go deleted file mode 100644 index 9986bacee..000000000 --- a/builder/common/big.go +++ /dev/null @@ -1,42 +0,0 @@ -// 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 common - -import ( - "math/big" - - "github.com/holiman/uint256" -) - -// Common big integers often used -var ( - Big1 = big.NewInt(1) - Big2 = big.NewInt(2) - Big3 = big.NewInt(3) - Big0 = big.NewInt(0) - Big32 = big.NewInt(32) - Big256 = big.NewInt(256) - Big257 = big.NewInt(257) - - U2560 = uint256.NewInt(0) - U256100 = uint256.NewInt(100) -) - -func PercentOf(val *uint256.Int, percent int) *uint256.Int { - res := new(uint256.Int).Mul(val, uint256.NewInt(uint64(percent))) - return new(uint256.Int).Div(res, U256100) -} diff --git a/builder/common/bitutil/bitutil.go b/builder/common/bitutil/bitutil.go deleted file mode 100644 index cd3e72169..000000000 --- a/builder/common/bitutil/bitutil.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Adapted from: https://golang.org/src/crypto/cipher/xor.go - -// Package bitutil implements fast bitwise operations. -package bitutil - -import ( - "runtime" - "unsafe" -) - -const wordSize = int(unsafe.Sizeof(uintptr(0))) -const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" - -// XORBytes xors the bytes in a and b. The destination is assumed to have enough -// space. Returns the number of bytes xor'd. -func XORBytes(dst, a, b []byte) int { - if supportsUnaligned { - return fastXORBytes(dst, a, b) - } - return safeXORBytes(dst, a, b) -} - -// fastXORBytes xors in bulk. It only works on architectures that support -// unaligned read/writes. -func fastXORBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - w := n / wordSize - if w > 0 { - dw := *(*[]uintptr)(unsafe.Pointer(&dst)) - aw := *(*[]uintptr)(unsafe.Pointer(&a)) - bw := *(*[]uintptr)(unsafe.Pointer(&b)) - for i := 0; i < w; i++ { - dw[i] = aw[i] ^ bw[i] - } - } - for i := n - n%wordSize; i < n; i++ { - dst[i] = a[i] ^ b[i] - } - return n -} - -// safeXORBytes xors one by one. It works on all architectures, independent if -// it supports unaligned read/writes or not. -func safeXORBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - for i := 0; i < n; i++ { - dst[i] = a[i] ^ b[i] - } - return n -} - -// ANDBytes ands the bytes in a and b. The destination is assumed to have enough -// space. Returns the number of bytes and'd. -func ANDBytes(dst, a, b []byte) int { - if supportsUnaligned { - return fastANDBytes(dst, a, b) - } - return safeANDBytes(dst, a, b) -} - -// fastANDBytes ands in bulk. It only works on architectures that support -// unaligned read/writes. -func fastANDBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - w := n / wordSize - if w > 0 { - dw := *(*[]uintptr)(unsafe.Pointer(&dst)) - aw := *(*[]uintptr)(unsafe.Pointer(&a)) - bw := *(*[]uintptr)(unsafe.Pointer(&b)) - for i := 0; i < w; i++ { - dw[i] = aw[i] & bw[i] - } - } - for i := n - n%wordSize; i < n; i++ { - dst[i] = a[i] & b[i] - } - return n -} - -// safeANDBytes ands one by one. It works on all architectures, independent if -// it supports unaligned read/writes or not. -func safeANDBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - for i := 0; i < n; i++ { - dst[i] = a[i] & b[i] - } - return n -} - -// ORBytes ors the bytes in a and b. The destination is assumed to have enough -// space. Returns the number of bytes or'd. -func ORBytes(dst, a, b []byte) int { - if supportsUnaligned { - return fastORBytes(dst, a, b) - } - return safeORBytes(dst, a, b) -} - -// fastORBytes ors in bulk. It only works on architectures that support -// unaligned read/writes. -func fastORBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - w := n / wordSize - if w > 0 { - dw := *(*[]uintptr)(unsafe.Pointer(&dst)) - aw := *(*[]uintptr)(unsafe.Pointer(&a)) - bw := *(*[]uintptr)(unsafe.Pointer(&b)) - for i := 0; i < w; i++ { - dw[i] = aw[i] | bw[i] - } - } - for i := n - n%wordSize; i < n; i++ { - dst[i] = a[i] | b[i] - } - return n -} - -// safeORBytes ors one by one. It works on all architectures, independent if -// it supports unaligned read/writes or not. -func safeORBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - for i := 0; i < n; i++ { - dst[i] = a[i] | b[i] - } - return n -} - -// TestBytes tests whether any bit is set in the input byte slice. -func TestBytes(p []byte) bool { - if supportsUnaligned { - return fastTestBytes(p) - } - return safeTestBytes(p) -} - -// fastTestBytes tests for set bits in bulk. It only works on architectures that -// support unaligned read/writes. -func fastTestBytes(p []byte) bool { - n := len(p) - w := n / wordSize - if w > 0 { - pw := *(*[]uintptr)(unsafe.Pointer(&p)) - for i := 0; i < w; i++ { - if pw[i] != 0 { - return true - } - } - } - for i := n - n%wordSize; i < n; i++ { - if p[i] != 0 { - return true - } - } - return false -} - -// safeTestBytes tests for set bits one byte at a time. It works on all -// architectures, independent if it supports unaligned read/writes or not. -func safeTestBytes(p []byte) bool { - for i := 0; i < len(p); i++ { - if p[i] != 0 { - return true - } - } - return false -} diff --git a/builder/common/bitutil/bitutil_test.go b/builder/common/bitutil/bitutil_test.go deleted file mode 100644 index 307bf731f..000000000 --- a/builder/common/bitutil/bitutil_test.go +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Adapted from: https://golang.org/src/crypto/cipher/xor_test.go - -package bitutil - -import ( - "bytes" - "testing" -) - -// Tests that bitwise XOR works for various alignments. -func TestXOR(t *testing.T) { - for alignP := 0; alignP < 2; alignP++ { - for alignQ := 0; alignQ < 2; alignQ++ { - for alignD := 0; alignD < 2; alignD++ { - p := make([]byte, 1023)[alignP:] - q := make([]byte, 1023)[alignQ:] - - for i := 0; i < len(p); i++ { - p[i] = byte(i) - } - for i := 0; i < len(q); i++ { - q[i] = byte(len(q) - i) - } - d1 := make([]byte, 1023+alignD)[alignD:] - d2 := make([]byte, 1023+alignD)[alignD:] - - XORBytes(d1, p, q) - safeXORBytes(d2, p, q) - if !bytes.Equal(d1, d2) { - t.Error("not equal", d1, d2) - } - } - } - } -} - -// Tests that bitwise AND works for various alignments. -func TestAND(t *testing.T) { - for alignP := 0; alignP < 2; alignP++ { - for alignQ := 0; alignQ < 2; alignQ++ { - for alignD := 0; alignD < 2; alignD++ { - p := make([]byte, 1023)[alignP:] - q := make([]byte, 1023)[alignQ:] - - for i := 0; i < len(p); i++ { - p[i] = byte(i) - } - for i := 0; i < len(q); i++ { - q[i] = byte(len(q) - i) - } - d1 := make([]byte, 1023+alignD)[alignD:] - d2 := make([]byte, 1023+alignD)[alignD:] - - ANDBytes(d1, p, q) - safeANDBytes(d2, p, q) - if !bytes.Equal(d1, d2) { - t.Error("not equal") - } - } - } - } -} - -// Tests that bitwise OR works for various alignments. -func TestOR(t *testing.T) { - for alignP := 0; alignP < 2; alignP++ { - for alignQ := 0; alignQ < 2; alignQ++ { - for alignD := 0; alignD < 2; alignD++ { - p := make([]byte, 1023)[alignP:] - q := make([]byte, 1023)[alignQ:] - - for i := 0; i < len(p); i++ { - p[i] = byte(i) - } - for i := 0; i < len(q); i++ { - q[i] = byte(len(q) - i) - } - d1 := make([]byte, 1023+alignD)[alignD:] - d2 := make([]byte, 1023+alignD)[alignD:] - - ORBytes(d1, p, q) - safeORBytes(d2, p, q) - if !bytes.Equal(d1, d2) { - t.Error("not equal") - } - } - } - } -} - -// Tests that bit testing works for various alignments. -func TestTest(t *testing.T) { - for align := 0; align < 2; align++ { - // Test for bits set in the bulk part - p := make([]byte, 1023)[align:] - p[100] = 1 - - if TestBytes(p) != safeTestBytes(p) { - t.Error("not equal") - } - // Test for bits set in the tail part - q := make([]byte, 1023)[align:] - q[len(q)-1] = 1 - - if TestBytes(q) != safeTestBytes(q) { - t.Error("not equal") - } - } -} - -// Benchmarks the potentially optimized XOR performance. -func BenchmarkFastXOR1KB(b *testing.B) { benchmarkFastXOR(b, 1024) } -func BenchmarkFastXOR2KB(b *testing.B) { benchmarkFastXOR(b, 2048) } -func BenchmarkFastXOR4KB(b *testing.B) { benchmarkFastXOR(b, 4096) } - -func benchmarkFastXOR(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - XORBytes(p, p, q) - } -} - -// Benchmarks the baseline XOR performance. -func BenchmarkBaseXOR1KB(b *testing.B) { benchmarkBaseXOR(b, 1024) } -func BenchmarkBaseXOR2KB(b *testing.B) { benchmarkBaseXOR(b, 2048) } -func BenchmarkBaseXOR4KB(b *testing.B) { benchmarkBaseXOR(b, 4096) } - -func benchmarkBaseXOR(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - safeXORBytes(p, p, q) - } -} - -// Benchmarks the potentially optimized AND performance. -func BenchmarkFastAND1KB(b *testing.B) { benchmarkFastAND(b, 1024) } -func BenchmarkFastAND2KB(b *testing.B) { benchmarkFastAND(b, 2048) } -func BenchmarkFastAND4KB(b *testing.B) { benchmarkFastAND(b, 4096) } - -func benchmarkFastAND(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - ANDBytes(p, p, q) - } -} - -// Benchmarks the baseline AND performance. -func BenchmarkBaseAND1KB(b *testing.B) { benchmarkBaseAND(b, 1024) } -func BenchmarkBaseAND2KB(b *testing.B) { benchmarkBaseAND(b, 2048) } -func BenchmarkBaseAND4KB(b *testing.B) { benchmarkBaseAND(b, 4096) } - -func benchmarkBaseAND(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - safeANDBytes(p, p, q) - } -} - -// Benchmarks the potentially optimized OR performance. -func BenchmarkFastOR1KB(b *testing.B) { benchmarkFastOR(b, 1024) } -func BenchmarkFastOR2KB(b *testing.B) { benchmarkFastOR(b, 2048) } -func BenchmarkFastOR4KB(b *testing.B) { benchmarkFastOR(b, 4096) } - -func benchmarkFastOR(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - ORBytes(p, p, q) - } -} - -// Benchmarks the baseline OR performance. -func BenchmarkBaseOR1KB(b *testing.B) { benchmarkBaseOR(b, 1024) } -func BenchmarkBaseOR2KB(b *testing.B) { benchmarkBaseOR(b, 2048) } -func BenchmarkBaseOR4KB(b *testing.B) { benchmarkBaseOR(b, 4096) } - -func benchmarkBaseOR(b *testing.B, size int) { - p, q := make([]byte, size), make([]byte, size) - - for i := 0; i < b.N; i++ { - safeORBytes(p, p, q) - } -} - -var GloBool bool // Exported global will not be dead-code eliminated, at least not yet. - -// Benchmarks the potentially optimized bit testing performance. -func BenchmarkFastTest1KB(b *testing.B) { benchmarkFastTest(b, 1024) } -func BenchmarkFastTest2KB(b *testing.B) { benchmarkFastTest(b, 2048) } -func BenchmarkFastTest4KB(b *testing.B) { benchmarkFastTest(b, 4096) } - -func benchmarkFastTest(b *testing.B, size int) { - p := make([]byte, size) - a := false - for i := 0; i < b.N; i++ { - a = a != TestBytes(p) - } - GloBool = a // Use of benchmark "result" to prevent total dead code elimination. -} - -// Benchmarks the baseline bit testing performance. -func BenchmarkBaseTest1KB(b *testing.B) { benchmarkBaseTest(b, 1024) } -func BenchmarkBaseTest2KB(b *testing.B) { benchmarkBaseTest(b, 2048) } -func BenchmarkBaseTest4KB(b *testing.B) { benchmarkBaseTest(b, 4096) } - -func benchmarkBaseTest(b *testing.B, size int) { - p := make([]byte, size) - a := false - for i := 0; i < b.N; i++ { - a = a != safeTestBytes(p) - } - GloBool = a // Use of benchmark "result" to prevent total dead code elimination. -} diff --git a/builder/common/bitutil/compress.go b/builder/common/bitutil/compress.go deleted file mode 100644 index c057cee4a..000000000 --- a/builder/common/bitutil/compress.go +++ /dev/null @@ -1,170 +0,0 @@ -// 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 bitutil - -import "errors" - -var ( - // errMissingData is returned from decompression if the byte referenced by - // the bitset header overflows the input data. - errMissingData = errors.New("missing bytes on input") - - // errUnreferencedData is returned from decompression if not all bytes were used - // up from the input data after decompressing it. - errUnreferencedData = errors.New("extra bytes on input") - - // errExceededTarget is returned from decompression if the bitset header has - // more bits defined than the number of target buffer space available. - errExceededTarget = errors.New("target data size exceeded") - - // errZeroContent is returned from decompression if a data byte referenced in - // the bitset header is actually a zero byte. - errZeroContent = errors.New("zero byte in input content") -) - -// The compression algorithm implemented by CompressBytes and DecompressBytes is -// optimized for sparse input data which contains a lot of zero bytes. Decompression -// requires knowledge of the decompressed data length. -// -// Compression works as follows: -// -// if data only contains zeroes, -// CompressBytes(data) == nil -// otherwise if len(data) <= 1, -// CompressBytes(data) == data -// otherwise: -// CompressBytes(data) == append(CompressBytes(nonZeroBitset(data)), nonZeroBytes(data)...) -// where -// nonZeroBitset(data) is a bit vector with len(data) bits (MSB first): -// nonZeroBitset(data)[i/8] && (1 << (7-i%8)) != 0 if data[i] != 0 -// len(nonZeroBitset(data)) == (len(data)+7)/8 -// nonZeroBytes(data) contains the non-zero bytes of data in the same order - -// CompressBytes compresses the input byte slice according to the sparse bitset -// representation algorithm. If the result is bigger than the original input, no -// compression is done. -func CompressBytes(data []byte) []byte { - if out := bitsetEncodeBytes(data); len(out) < len(data) { - return out - } - cpy := make([]byte, len(data)) - copy(cpy, data) - return cpy -} - -// bitsetEncodeBytes compresses the input byte slice according to the sparse -// bitset representation algorithm. -func bitsetEncodeBytes(data []byte) []byte { - // Empty slices get compressed to nil - if len(data) == 0 { - return nil - } - // One byte slices compress to nil or retain the single byte - if len(data) == 1 { - if data[0] == 0 { - return nil - } - return data - } - // Calculate the bitset of set bytes, and gather the non-zero bytes - nonZeroBitset := make([]byte, (len(data)+7)/8) - nonZeroBytes := make([]byte, 0, len(data)) - - for i, b := range data { - if b != 0 { - nonZeroBytes = append(nonZeroBytes, b) - nonZeroBitset[i/8] |= 1 << byte(7-i%8) - } - } - if len(nonZeroBytes) == 0 { - return nil - } - return append(bitsetEncodeBytes(nonZeroBitset), nonZeroBytes...) -} - -// DecompressBytes decompresses data with a known target size. If the input data -// matches the size of the target, it means no compression was done in the first -// place. -func DecompressBytes(data []byte, target int) ([]byte, error) { - if len(data) > target { - return nil, errExceededTarget - } - if len(data) == target { - cpy := make([]byte, len(data)) - copy(cpy, data) - return cpy, nil - } - return bitsetDecodeBytes(data, target) -} - -// bitsetDecodeBytes decompresses data with a known target size. -func bitsetDecodeBytes(data []byte, target int) ([]byte, error) { - out, size, err := bitsetDecodePartialBytes(data, target) - if err != nil { - return nil, err - } - if size != len(data) { - return nil, errUnreferencedData - } - return out, nil -} - -// bitsetDecodePartialBytes decompresses data with a known target size, but does -// not enforce consuming all the input bytes. In addition to the decompressed -// output, the function returns the length of compressed input data corresponding -// to the output as the input slice may be longer. -func bitsetDecodePartialBytes(data []byte, target int) ([]byte, int, error) { - // Sanity check 0 targets to avoid infinite recursion - if target == 0 { - return nil, 0, nil - } - // Handle the zero and single byte corner cases - decomp := make([]byte, target) - if len(data) == 0 { - return decomp, 0, nil - } - if target == 1 { - decomp[0] = data[0] // copy to avoid referencing the input slice - if data[0] != 0 { - return decomp, 1, nil - } - return decomp, 0, nil - } - // Decompress the bitset of set bytes and distribute the non zero bytes - nonZeroBitset, ptr, err := bitsetDecodePartialBytes(data, (target+7)/8) - if err != nil { - return nil, ptr, err - } - for i := 0; i < 8*len(nonZeroBitset); i++ { - if nonZeroBitset[i/8]&(1<= len(data) { - return nil, 0, errMissingData - } - if i >= len(decomp) { - return nil, 0, errExceededTarget - } - // Make sure the data is valid and push into the slot - if data[ptr] == 0 { - return nil, 0, errZeroContent - } - decomp[i] = data[ptr] - ptr++ - } - } - return decomp, ptr, nil -} diff --git a/builder/common/bitutil/compress_test.go b/builder/common/bitutil/compress_test.go deleted file mode 100644 index c6f6fe8bc..000000000 --- a/builder/common/bitutil/compress_test.go +++ /dev/null @@ -1,223 +0,0 @@ -// 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 bitutil - -import ( - "bytes" - "fmt" - "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// Tests that data bitset encoding and decoding works and is bijective. -func TestEncodingCycle(t *testing.T) { - tests := []string{ - // Tests generated by go-fuzz to maximize code coverage - "0x000000000000000000", - "0xef0400", - "0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb", - "0x7b64000000", - "0x000034000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0000000000000000000", - "0x4912385c0e7b64000000", - "0x000034000000000000000000000000000000", - "0x00", - "0x000003e834ff7f0000", - "0x0000", - "0x0000000000000000000000000000000000000000000000000000000000ff00", - "0x895f0c6a020f850c6a020f85f88df88d", - "0xdf7070533534333636313639343638373432313536346c1bc3315aac2f65fefb", - "0x0000000000", - "0xdf70706336346c65fefb", - "0x00006d643634000000", - "0xdf7070533534333636313639343638373532313536346c1bc333393438373130707063363430353639343638373532313536346c1bc333393438336336346c65fe", - } - for i, tt := range tests { - if err := testEncodingCycle(hexutil.MustDecode(tt)); err != nil { - t.Errorf("test %d: %v", i, err) - } - } -} - -func testEncodingCycle(data []byte) error { - proc, err := bitsetDecodeBytes(bitsetEncodeBytes(data), len(data)) - if err != nil { - return fmt.Errorf("failed to decompress compressed data: %v", err) - } - if !bytes.Equal(data, proc) { - return fmt.Errorf("compress/decompress mismatch: have %x, want %x", proc, data) - } - return nil -} - -// Tests that data bitset decoding and rencoding works and is bijective. -func TestDecodingCycle(t *testing.T) { - tests := []struct { - size int - input string - fail error - }{ - {size: 0, input: "0x"}, - - // Crashers generated by go-fuzz - {size: 0, input: "0x0020", fail: errUnreferencedData}, - {size: 0, input: "0x30", fail: errUnreferencedData}, - {size: 1, input: "0x00", fail: errUnreferencedData}, - {size: 2, input: "0x07", fail: errMissingData}, - {size: 1024, input: "0x8000", fail: errZeroContent}, - - // Tests generated by go-fuzz to maximize code coverage - {size: 29490, input: "0x343137343733323134333839373334323073333930783e3078333930783e70706336346c65303e", fail: errMissingData}, - {size: 59395, input: "0x00", fail: errUnreferencedData}, - {size: 52574, input: "0x70706336346c65c0de", fail: errExceededTarget}, - {size: 42264, input: "0x07", fail: errMissingData}, - {size: 52, input: "0xa5045bad48f4", fail: errExceededTarget}, - {size: 52574, input: "0xc0de", fail: errMissingData}, - {size: 52574, input: "0x"}, - {size: 29490, input: "0x34313734373332313433383937333432307333393078073034333839373334323073333930783e3078333937333432307333393078073061333930783e70706336346c65303e", fail: errMissingData}, - {size: 29491, input: "0x3973333930783e30783e", fail: errMissingData}, - - {size: 1024, input: "0x808080608080"}, - {size: 1024, input: "0x808470705e3632383337363033313434303137393130306c6580ef46806380635a80"}, - {size: 1024, input: "0x8080808070"}, - {size: 1024, input: "0x808070705e36346c6580ef46806380635a80"}, - {size: 1024, input: "0x80808046802680"}, - {size: 1024, input: "0x4040404035"}, - {size: 1024, input: "0x4040bf3ba2b3f684402d353234373438373934409fe5b1e7ada94ebfd7d0505e27be4035"}, - {size: 1024, input: "0x404040bf3ba2b3f6844035"}, - {size: 1024, input: "0x40402d35323437343837393440bfd7d0505e27be4035"}, - } - for i, tt := range tests { - data := hexutil.MustDecode(tt.input) - - orig, err := bitsetDecodeBytes(data, tt.size) - if err != tt.fail { - t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.fail) - } - if err != nil { - continue - } - if comp := bitsetEncodeBytes(orig); !bytes.Equal(comp, data) { - t.Errorf("test %d: decompress/compress mismatch: have %x, want %x", i, comp, data) - } - } -} - -// TestCompression tests that compression works by returning either the bitset -// encoded input, or the actual input if the bitset version is longer. -func TestCompression(t *testing.T) { - // Check the compression returns the bitset encoding is shorter - in := hexutil.MustDecode("0x4912385c0e7b64000000") - out := hexutil.MustDecode("0x80fe4912385c0e7b64") - - if data := CompressBytes(in); !bytes.Equal(data, out) { - t.Errorf("encoding mismatch for sparse data: have %x, want %x", data, out) - } - if data, err := DecompressBytes(out, len(in)); err != nil || !bytes.Equal(data, in) { - t.Errorf("decoding mismatch for sparse data: have %x, want %x, error %v", data, in, err) - } - // Check the compression returns the input if the bitset encoding is longer - in = hexutil.MustDecode("0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb") - out = hexutil.MustDecode("0xdf7070533534333636313639343638373532313536346c1bc33339343837313070706336343035336336346c65fefb3930393233383838ac2f65fefb") - - if data := CompressBytes(in); !bytes.Equal(data, out) { - t.Errorf("encoding mismatch for dense data: have %x, want %x", data, out) - } - if data, err := DecompressBytes(out, len(in)); err != nil || !bytes.Equal(data, in) { - t.Errorf("decoding mismatch for dense data: have %x, want %x, error %v", data, in, err) - } - // Check that decompressing a longer input than the target fails - if _, err := DecompressBytes([]byte{0xc0, 0x01, 0x01}, 2); err != errExceededTarget { - t.Errorf("decoding error mismatch for long data: have %v, want %v", err, errExceededTarget) - } -} - -// Crude benchmark for compressing random slices of bytes. -func BenchmarkEncoding1KBVerySparse(b *testing.B) { benchmarkEncoding(b, 1024, 0.0001) } -func BenchmarkEncoding2KBVerySparse(b *testing.B) { benchmarkEncoding(b, 2048, 0.0001) } -func BenchmarkEncoding4KBVerySparse(b *testing.B) { benchmarkEncoding(b, 4096, 0.0001) } - -func BenchmarkEncoding1KBSparse(b *testing.B) { benchmarkEncoding(b, 1024, 0.001) } -func BenchmarkEncoding2KBSparse(b *testing.B) { benchmarkEncoding(b, 2048, 0.001) } -func BenchmarkEncoding4KBSparse(b *testing.B) { benchmarkEncoding(b, 4096, 0.001) } - -func BenchmarkEncoding1KBDense(b *testing.B) { benchmarkEncoding(b, 1024, 0.1) } -func BenchmarkEncoding2KBDense(b *testing.B) { benchmarkEncoding(b, 2048, 0.1) } -func BenchmarkEncoding4KBDense(b *testing.B) { benchmarkEncoding(b, 4096, 0.1) } - -func BenchmarkEncoding1KBSaturated(b *testing.B) { benchmarkEncoding(b, 1024, 0.5) } -func BenchmarkEncoding2KBSaturated(b *testing.B) { benchmarkEncoding(b, 2048, 0.5) } -func BenchmarkEncoding4KBSaturated(b *testing.B) { benchmarkEncoding(b, 4096, 0.5) } - -func benchmarkEncoding(b *testing.B, bytes int, fill float64) { - // Generate a random slice of bytes to compress - random := rand.NewSource(0) // reproducible and comparable - - data := make([]byte, bytes) - bits := int(float64(bytes) * 8 * fill) - - for i := 0; i < bits; i++ { - idx := random.Int63() % int64(len(data)) - bit := uint(random.Int63() % 8) - data[idx] |= 1 << bit - } - // Reset the benchmark and measure encoding/decoding - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - bitsetDecodeBytes(bitsetEncodeBytes(data), len(data)) - } -} - -func FuzzEncoder(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - if err := testEncodingCycle(data); err != nil { - t.Fatal(err) - } - }) -} -func FuzzDecoder(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - fuzzDecode(data) - }) -} - -// fuzzDecode implements a go-fuzz fuzzer method to test the bit decoding and -// reencoding algorithm. -func fuzzDecode(data []byte) { - blob, err := DecompressBytes(data, 1024) - if err != nil { - return - } - // re-compress it (it's OK if the re-compressed differs from the - // original - the first input may not have been compressed at all) - comp := CompressBytes(blob) - if len(comp) > len(blob) { - // After compression, it must be smaller or equal - panic("bad compression") - } - // But decompressing it once again should work - decomp, err := DecompressBytes(data, 1024) - if err != nil { - panic(err) - } - if !bytes.Equal(decomp, blob) { - panic("content mismatch") - } -} diff --git a/builder/common/bytes.go b/builder/common/bytes.go deleted file mode 100644 index d1f5c6c99..000000000 --- a/builder/common/bytes.go +++ /dev/null @@ -1,151 +0,0 @@ -// 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 common contains various helper functions. -package common - -import ( - "encoding/hex" - "errors" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// FromHex returns the bytes represented by the hexadecimal string s. -// s may be prefixed with "0x". -func FromHex(s string) []byte { - if has0xPrefix(s) { - s = s[2:] - } - if len(s)%2 == 1 { - s = "0" + s - } - return Hex2Bytes(s) -} - -// CopyBytes returns an exact copy of the provided bytes. -func CopyBytes(b []byte) (copiedBytes []byte) { - if b == nil { - return nil - } - copiedBytes = make([]byte, len(b)) - copy(copiedBytes, b) - - return -} - -// has0xPrefix validates str begins with '0x' or '0X'. -func has0xPrefix(str string) bool { - return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') -} - -// isHexCharacter returns bool of c being a valid hexadecimal. -func isHexCharacter(c byte) bool { - return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') -} - -// isHex validates whether each byte is valid hexadecimal string. -func isHex(str string) bool { - if len(str)%2 != 0 { - return false - } - for _, c := range []byte(str) { - if !isHexCharacter(c) { - return false - } - } - return true -} - -// Bytes2Hex returns the hexadecimal encoding of d. -func Bytes2Hex(d []byte) string { - return hex.EncodeToString(d) -} - -// Hex2Bytes returns the bytes represented by the hexadecimal string str. -func Hex2Bytes(str string) []byte { - h, _ := hex.DecodeString(str) - return h -} - -// Hex2BytesFixed returns bytes of a specified fixed length flen. -func Hex2BytesFixed(str string, flen int) []byte { - h, _ := hex.DecodeString(str) - if len(h) == flen { - return h - } - if len(h) > flen { - return h[len(h)-flen:] - } - hh := make([]byte, flen) - copy(hh[flen-len(h):flen], h) - return hh -} - -// ParseHexOrString tries to hexdecode b, but if the prefix is missing, it instead just returns the raw bytes -func ParseHexOrString(str string) ([]byte, error) { - b, err := hexutil.Decode(str) - if errors.Is(err, hexutil.ErrMissingPrefix) { - return []byte(str), nil - } - return b, err -} - -// RightPadBytes zero-pads slice to the right up to length l. -func RightPadBytes(slice []byte, l int) []byte { - if l <= len(slice) { - return slice - } - - padded := make([]byte, l) - copy(padded, slice) - - return padded -} - -// LeftPadBytes zero-pads slice to the left up to length l. -func LeftPadBytes(slice []byte, l int) []byte { - if l <= len(slice) { - return slice - } - - padded := make([]byte, l) - copy(padded[l-len(slice):], slice) - - return padded -} - -// TrimLeftZeroes returns a subslice of s without leading zeroes -func TrimLeftZeroes(s []byte) []byte { - idx := 0 - for ; idx < len(s); idx++ { - if s[idx] != 0 { - break - } - } - return s[idx:] -} - -// TrimRightZeroes returns a subslice of s without trailing zeroes -func TrimRightZeroes(s []byte) []byte { - idx := len(s) - for ; idx > 0; idx-- { - if s[idx-1] != 0 { - break - } - } - return s[:idx] -} diff --git a/builder/common/bytes_test.go b/builder/common/bytes_test.go deleted file mode 100644 index 0e3ec974e..000000000 --- a/builder/common/bytes_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// 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 common - -import ( - "bytes" - "testing" -) - -func TestCopyBytes(t *testing.T) { - input := []byte{1, 2, 3, 4} - - v := CopyBytes(input) - if !bytes.Equal(v, []byte{1, 2, 3, 4}) { - t.Fatal("not equal after copy") - } - v[0] = 99 - if bytes.Equal(v, input) { - t.Fatal("result is not a copy") - } -} - -func TestLeftPadBytes(t *testing.T) { - val := []byte{1, 2, 3, 4} - padded := []byte{0, 0, 0, 0, 1, 2, 3, 4} - - if r := LeftPadBytes(val, 8); !bytes.Equal(r, padded) { - t.Fatalf("LeftPadBytes(%v, 8) == %v", val, r) - } - if r := LeftPadBytes(val, 2); !bytes.Equal(r, val) { - t.Fatalf("LeftPadBytes(%v, 2) == %v", val, r) - } -} - -func TestRightPadBytes(t *testing.T) { - val := []byte{1, 2, 3, 4} - padded := []byte{1, 2, 3, 4, 0, 0, 0, 0} - - if r := RightPadBytes(val, 8); !bytes.Equal(r, padded) { - t.Fatalf("RightPadBytes(%v, 8) == %v", val, r) - } - if r := RightPadBytes(val, 2); !bytes.Equal(r, val) { - t.Fatalf("RightPadBytes(%v, 2) == %v", val, r) - } -} - -func TestFromHex(t *testing.T) { - input := "0x01" - expected := []byte{1} - result := FromHex(input) - if !bytes.Equal(expected, result) { - t.Errorf("Expected %x got %x", expected, result) - } -} - -func TestIsHex(t *testing.T) { - tests := []struct { - input string - ok bool - }{ - {"", true}, - {"0", false}, - {"00", true}, - {"a9e67e", true}, - {"A9E67E", true}, - {"0xa9e67e", false}, - {"a9e67e001", false}, - {"0xHELLO_MY_NAME_IS_STEVEN_@#$^&*", false}, - } - for _, test := range tests { - if ok := isHex(test.input); ok != test.ok { - t.Errorf("isHex(%q) = %v, want %v", test.input, ok, test.ok) - } - } -} - -func TestFromHexOddLength(t *testing.T) { - input := "0x1" - expected := []byte{1} - result := FromHex(input) - if !bytes.Equal(expected, result) { - t.Errorf("Expected %x got %x", expected, result) - } -} - -func TestNoPrefixShortHexOddLength(t *testing.T) { - input := "1" - expected := []byte{1} - result := FromHex(input) - if !bytes.Equal(expected, result) { - t.Errorf("Expected %x got %x", expected, result) - } -} - -func TestTrimRightZeroes(t *testing.T) { - tests := []struct { - arr []byte - exp []byte - }{ - {FromHex("0x00ffff00ff0000"), FromHex("0x00ffff00ff")}, - {FromHex("0x00000000000000"), []byte{}}, - {FromHex("0xff"), FromHex("0xff")}, - {[]byte{}, []byte{}}, - {FromHex("0x00ffffffffffff"), FromHex("0x00ffffffffffff")}, - } - for i, test := range tests { - got := TrimRightZeroes(test.arr) - if !bytes.Equal(got, test.exp) { - t.Errorf("test %d, got %x exp %x", i, got, test.exp) - } - } -} diff --git a/builder/common/compiler/helpers.go b/builder/common/compiler/helpers.go deleted file mode 100644 index 063fc1081..000000000 --- a/builder/common/compiler/helpers.go +++ /dev/null @@ -1,45 +0,0 @@ -// 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 compiler wraps the Solidity and Vyper compiler executables (solc; vyper). -package compiler - -// Contract contains information about a compiled contract, alongside its code and runtime code. -type Contract struct { - Code string `json:"code"` - RuntimeCode string `json:"runtime-code"` - Info ContractInfo `json:"info"` - Hashes map[string]string `json:"hashes"` -} - -// ContractInfo contains information about a compiled contract, including access -// to the ABI definition, source mapping, user and developer docs, and metadata. -// -// Depending on the source, language version, compiler version, and compiler -// options will provide information about how the contract was compiled. -type ContractInfo struct { - Source string `json:"source"` - Language string `json:"language"` - LanguageVersion string `json:"languageVersion"` - CompilerVersion string `json:"compilerVersion"` - CompilerOptions string `json:"compilerOptions"` - SrcMap interface{} `json:"srcMap"` - SrcMapRuntime string `json:"srcMapRuntime"` - AbiDefinition interface{} `json:"abiDefinition"` - UserDoc interface{} `json:"userDoc"` - DeveloperDoc interface{} `json:"developerDoc"` - Metadata string `json:"metadata"` -} diff --git a/builder/common/compiler/solidity.go b/builder/common/compiler/solidity.go deleted file mode 100644 index 9de94017c..000000000 --- a/builder/common/compiler/solidity.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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 compiler wraps the ABI compilation outputs. -package compiler - -import ( - "encoding/json" - "fmt" -) - -// --combined-output format -type solcOutput struct { - Contracts map[string]struct { - BinRuntime string `json:"bin-runtime"` - SrcMapRuntime string `json:"srcmap-runtime"` - Bin, SrcMap, Abi, Devdoc, Userdoc, Metadata string - Hashes map[string]string - } - Version string -} - -// solidity v.0.8 changes the way ABI, Devdoc and Userdoc are serialized -type solcOutputV8 struct { - Contracts map[string]struct { - BinRuntime string `json:"bin-runtime"` - SrcMapRuntime string `json:"srcmap-runtime"` - Bin, SrcMap, Metadata string - Abi interface{} - Devdoc interface{} - Userdoc interface{} - Hashes map[string]string - } - Version string -} - -// ParseCombinedJSON takes the direct output of a solc --combined-output run and -// parses it into a map of string contract name to Contract structs. The -// provided source, language and compiler version, and compiler options are all -// passed through into the Contract structs. -// -// The solc output is expected to contain ABI, source mapping, user docs, and dev docs. -// -// Returns an error if the JSON is malformed or missing data, or if the JSON -// embedded within the JSON is malformed. -func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { - var output solcOutput - if err := json.Unmarshal(combinedJSON, &output); err != nil { - // Try to parse the output with the new solidity v.0.8.0 rules - return parseCombinedJSONV8(combinedJSON, source, languageVersion, compilerVersion, compilerOptions) - } - // Compilation succeeded, assemble and return the contracts. - contracts := make(map[string]*Contract) - for name, info := range output.Contracts { - // Parse the individual compilation results. - var abi, userdoc, devdoc interface{} - if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { - return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) - } - if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil { - return nil, fmt.Errorf("solc: error reading userdoc definition (%v)", err) - } - if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil { - return nil, fmt.Errorf("solc: error reading devdoc definition (%v)", err) - } - - contracts[name] = &Contract{ - Code: "0x" + info.Bin, - RuntimeCode: "0x" + info.BinRuntime, - Hashes: info.Hashes, - Info: ContractInfo{ - Source: source, - Language: "Solidity", - LanguageVersion: languageVersion, - CompilerVersion: compilerVersion, - CompilerOptions: compilerOptions, - SrcMap: info.SrcMap, - SrcMapRuntime: info.SrcMapRuntime, - AbiDefinition: abi, - UserDoc: userdoc, - DeveloperDoc: devdoc, - Metadata: info.Metadata, - }, - } - } - return contracts, nil -} - -// parseCombinedJSONV8 parses the direct output of solc --combined-output -// and parses it using the rules from solidity v.0.8.0 and later. -func parseCombinedJSONV8(combinedJSON []byte, source string, languageVersion string, compilerVersion string, compilerOptions string) (map[string]*Contract, error) { - var output solcOutputV8 - if err := json.Unmarshal(combinedJSON, &output); err != nil { - return nil, err - } - // Compilation succeeded, assemble and return the contracts. - contracts := make(map[string]*Contract) - for name, info := range output.Contracts { - contracts[name] = &Contract{ - Code: "0x" + info.Bin, - RuntimeCode: "0x" + info.BinRuntime, - Hashes: info.Hashes, - Info: ContractInfo{ - Source: source, - Language: "Solidity", - LanguageVersion: languageVersion, - CompilerVersion: compilerVersion, - CompilerOptions: compilerOptions, - SrcMap: info.SrcMap, - SrcMapRuntime: info.SrcMapRuntime, - AbiDefinition: info.Abi, - UserDoc: info.Userdoc, - DeveloperDoc: info.Devdoc, - Metadata: info.Metadata, - }, - } - } - return contracts, nil -} diff --git a/builder/common/debug.go b/builder/common/debug.go deleted file mode 100644 index 28c52b4a9..000000000 --- a/builder/common/debug.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 common - -import ( - "fmt" - "os" - "runtime" - "runtime/debug" - "strings" -) - -// Report gives off a warning requesting the user to submit an issue to the github tracker. -func Report(extra ...interface{}) { - fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues") - fmt.Fprintln(os.Stderr, extra...) - - _, file, line, _ := runtime.Caller(1) - fmt.Fprintf(os.Stderr, "%v:%v\n", file, line) - - debug.PrintStack() - - fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####") -} - -// PrintDeprecationWarning prints the given string in a box using fmt.Println. -func PrintDeprecationWarning(str string) { - line := strings.Repeat("#", len(str)+4) - emptyLine := strings.Repeat(" ", len(str)) - fmt.Printf(` -%s -# %s # -# %s # -# %s # -%s - -`, line, emptyLine, str, emptyLine, line) -} diff --git a/builder/common/fdlimit/fdlimit_bsd.go b/builder/common/fdlimit/fdlimit_bsd.go deleted file mode 100644 index a3a6902c0..000000000 --- a/builder/common/fdlimit/fdlimit_bsd.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2016 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 . - -//go:build freebsd || dragonfly -// +build freebsd dragonfly - -package fdlimit - -import "syscall" - -// This file is largely identical to fdlimit_unix.go, -// but Rlimit fields have type int64 on *BSD so it needs -// an extra conversion. - -// Raise tries to maximize the file descriptor allowance of this process -// to the maximum hard-limit allowed by the OS. -func Raise(max uint64) (uint64, error) { - // Get the current limit - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // Try to update the limit to the max allowance - limit.Cur = limit.Max - if limit.Cur > int64(max) { - limit.Cur = int64(max) - } - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return uint64(limit.Cur), nil -} - -// Current retrieves the number of file descriptors allowed to be opened by this -// process. -func Current() (int, error) { - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return int(limit.Cur), nil -} - -// Maximum retrieves the maximum number of file descriptors this process is -// allowed to request for itself. -func Maximum() (int, error) { - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return int(limit.Max), nil -} diff --git a/builder/common/fdlimit/fdlimit_darwin.go b/builder/common/fdlimit/fdlimit_darwin.go deleted file mode 100644 index 6b26fa00f..000000000 --- a/builder/common/fdlimit/fdlimit_darwin.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2016 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 fdlimit - -import "syscall" - -// hardlimit is the number of file descriptors allowed at max by the kernel. -const hardlimit = 10240 - -// Raise tries to maximize the file descriptor allowance of this process -// to the maximum hard-limit allowed by the OS. -// Returns the size it was set to (may differ from the desired 'max') -func Raise(max uint64) (uint64, error) { - // Get the current limit - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // Try to update the limit to the max allowance - limit.Cur = limit.Max - if limit.Cur > max { - limit.Cur = max - } - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // MacOS can silently apply further caps, so retrieve the actually set limit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return limit.Cur, nil -} - -// Current retrieves the number of file descriptors allowed to be opened by this -// process. -func Current() (int, error) { - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return int(limit.Cur), nil -} - -// Maximum retrieves the maximum number of file descriptors this process is -// allowed to request for itself. -func Maximum() (int, error) { - // Retrieve the maximum allowed by dynamic OS limits - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // Cap it to OPEN_MAX (10240) because macos is a special snowflake - if limit.Max > hardlimit { - limit.Max = hardlimit - } - return int(limit.Max), nil -} diff --git a/builder/common/fdlimit/fdlimit_test.go b/builder/common/fdlimit/fdlimit_test.go deleted file mode 100644 index 9fd5e9fc3..000000000 --- a/builder/common/fdlimit/fdlimit_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 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 fdlimit - -import ( - "testing" -) - -// TestFileDescriptorLimits simply tests whether the file descriptor allowance -// per this process can be retrieved. -func TestFileDescriptorLimits(t *testing.T) { - target := 4096 - hardlimit, err := Maximum() - if err != nil { - t.Fatal(err) - } - if hardlimit < target { - t.Skipf("system limit is less than desired test target: %d < %d", hardlimit, target) - } - - if limit, err := Current(); err != nil || limit <= 0 { - t.Fatalf("failed to retrieve file descriptor limit (%d): %v", limit, err) - } - if _, err := Raise(uint64(target)); err != nil { - t.Fatalf("failed to raise file allowance") - } - if limit, err := Current(); err != nil || limit < target { - t.Fatalf("failed to retrieve raised descriptor limit (have %v, want %v): %v", limit, target, err) - } -} diff --git a/builder/common/fdlimit/fdlimit_unix.go b/builder/common/fdlimit/fdlimit_unix.go deleted file mode 100644 index a1f388ebb..000000000 --- a/builder/common/fdlimit/fdlimit_unix.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2016 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 . - -//go:build linux || netbsd || openbsd || solaris -// +build linux netbsd openbsd solaris - -package fdlimit - -import "syscall" - -// Raise tries to maximize the file descriptor allowance of this process -// to the maximum hard-limit allowed by the OS. -// Returns the size it was set to (may differ from the desired 'max') -func Raise(max uint64) (uint64, error) { - // Get the current limit - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // Try to update the limit to the max allowance - limit.Cur = limit.Max - if limit.Cur > max { - limit.Cur = max - } - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - // MacOS can silently apply further caps, so retrieve the actually set limit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return limit.Cur, nil -} - -// Current retrieves the number of file descriptors allowed to be opened by this -// process. -func Current() (int, error) { - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return int(limit.Cur), nil -} - -// Maximum retrieves the maximum number of file descriptors this process is -// allowed to request for itself. -func Maximum() (int, error) { - var limit syscall.Rlimit - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil { - return 0, err - } - return int(limit.Max), nil -} diff --git a/builder/common/fdlimit/fdlimit_windows.go b/builder/common/fdlimit/fdlimit_windows.go deleted file mode 100644 index f47215366..000000000 --- a/builder/common/fdlimit/fdlimit_windows.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2018 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 fdlimit - -import "fmt" - -// hardlimit is the number of file descriptors allowed at max by the kernel. -const hardlimit = 16384 - -// Raise tries to maximize the file descriptor allowance of this process -// to the maximum hard-limit allowed by the OS. -func Raise(max uint64) (uint64, error) { - // This method is NOP by design: - // * Linux/Darwin counterparts need to manually increase per process limits - // * On Windows Go uses the CreateFile API, which is limited to 16K files, non - // changeable from within a running process - // This way we can always "request" raising the limits, which will either have - // or not have effect based on the platform we're running on. - if max > hardlimit { - return hardlimit, fmt.Errorf("file descriptor limit (%d) reached", hardlimit) - } - return max, nil -} - -// Current retrieves the number of file descriptors allowed to be opened by this -// process. -func Current() (int, error) { - // Please see Raise for the reason why we use hard coded 16K as the limit - return hardlimit, nil -} - -// Maximum retrieves the maximum number of file descriptors this process is -// allowed to request for itself. -func Maximum() (int, error) { - return Current() -} diff --git a/builder/common/format.go b/builder/common/format.go deleted file mode 100644 index 7af41f52d..000000000 --- a/builder/common/format.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 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 common - -import ( - "fmt" - "regexp" - "strings" - "time" -) - -// PrettyDuration is a pretty printed version of a time.Duration value that cuts -// the unnecessary precision off from the formatted textual representation. -type PrettyDuration time.Duration - -var prettyDurationRe = regexp.MustCompile(`\.[0-9]{4,}`) - -// String implements the Stringer interface, allowing pretty printing of duration -// values rounded to three decimals. -func (d PrettyDuration) String() string { - label := time.Duration(d).String() - if match := prettyDurationRe.FindString(label); len(match) > 4 { - label = strings.Replace(label, match, match[:4], 1) - } - return label -} - -// PrettyAge is a pretty printed version of a time.Duration value that rounds -// the values up to a single most significant unit, days/weeks/years included. -type PrettyAge time.Time - -// ageUnits is a list of units the age pretty printing uses. -var ageUnits = []struct { - Size time.Duration - Symbol string -}{ - {12 * 30 * 24 * time.Hour, "y"}, - {30 * 24 * time.Hour, "mo"}, - {7 * 24 * time.Hour, "w"}, - {24 * time.Hour, "d"}, - {time.Hour, "h"}, - {time.Minute, "m"}, - {time.Second, "s"}, -} - -// String implements the Stringer interface, allowing pretty printing of duration -// values rounded to the most significant time unit. -func (t PrettyAge) String() string { - // Calculate the time difference and handle the 0 cornercase - diff := time.Since(time.Time(t)) - if diff < time.Second { - return "0" - } - // Accumulate a precision of 3 components before returning - result, prec := "", 0 - - for _, unit := range ageUnits { - if diff > unit.Size { - result = fmt.Sprintf("%s%d%s", result, diff/unit.Size, unit.Symbol) - diff %= unit.Size - - if prec += 1; prec >= 3 { - break - } - } - } - return result -} diff --git a/builder/common/hexutil/hexutil.go b/builder/common/hexutil/hexutil.go deleted file mode 100644 index d3201850a..000000000 --- a/builder/common/hexutil/hexutil.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2016 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 hexutil implements hex encoding with 0x prefix. -This encoding is used by the Ethereum RPC API to transport binary data in JSON payloads. - -# Encoding Rules - -All hex data must have prefix "0x". - -For byte slices, the hex data must be of even length. An empty byte slice -encodes as "0x". - -Integers are encoded using the least amount of digits (no leading zero digits). Their -encoding may be of uneven length. The number zero encodes as "0x0". -*/ -package hexutil - -import ( - "encoding/hex" - "fmt" - "math/big" - "strconv" -) - -const uintBits = 32 << (uint64(^uint(0)) >> 63) - -// Errors -var ( - ErrEmptyString = &decError{"empty hex string"} - ErrSyntax = &decError{"invalid hex string"} - ErrMissingPrefix = &decError{"hex string without 0x prefix"} - ErrOddLength = &decError{"hex string of odd length"} - ErrEmptyNumber = &decError{"hex string \"0x\""} - ErrLeadingZero = &decError{"hex number with leading zero digits"} - ErrUint64Range = &decError{"hex number > 64 bits"} - ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} - ErrBig256Range = &decError{"hex number > 256 bits"} -) - -type decError struct{ msg string } - -func (err decError) Error() string { return err.msg } - -// Decode decodes a hex string with 0x prefix. -func Decode(input string) ([]byte, error) { - if len(input) == 0 { - return nil, ErrEmptyString - } - if !has0xPrefix(input) { - return nil, ErrMissingPrefix - } - b, err := hex.DecodeString(input[2:]) - if err != nil { - err = mapError(err) - } - return b, err -} - -// MustDecode decodes a hex string with 0x prefix. It panics for invalid input. -func MustDecode(input string) []byte { - dec, err := Decode(input) - if err != nil { - panic(err) - } - return dec -} - -// Encode encodes b as a hex string with 0x prefix. -func Encode(b []byte) string { - enc := make([]byte, len(b)*2+2) - copy(enc, "0x") - hex.Encode(enc[2:], b) - return string(enc) -} - -// DecodeUint64 decodes a hex string with 0x prefix as a quantity. -func DecodeUint64(input string) (uint64, error) { - raw, err := checkNumber(input) - if err != nil { - return 0, err - } - dec, err := strconv.ParseUint(raw, 16, 64) - if err != nil { - err = mapError(err) - } - return dec, err -} - -// MustDecodeUint64 decodes a hex string with 0x prefix as a quantity. -// It panics for invalid input. -func MustDecodeUint64(input string) uint64 { - dec, err := DecodeUint64(input) - if err != nil { - panic(err) - } - return dec -} - -// EncodeUint64 encodes i as a hex string with 0x prefix. -func EncodeUint64(i uint64) string { - enc := make([]byte, 2, 10) - copy(enc, "0x") - return string(strconv.AppendUint(enc, i, 16)) -} - -var bigWordNibbles int - -func init() { - // This is a weird way to compute the number of nibbles required for big.Word. - // The usual way would be to use constant arithmetic but go vet can't handle that. - b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) - switch len(b.Bits()) { - case 1: - bigWordNibbles = 16 - case 2: - bigWordNibbles = 8 - default: - panic("weird big.Word size") - } -} - -// DecodeBig decodes a hex string with 0x prefix as a quantity. -// Numbers larger than 256 bits are not accepted. -func DecodeBig(input string) (*big.Int, error) { - raw, err := checkNumber(input) - if err != nil { - return nil, err - } - if len(raw) > 64 { - return nil, ErrBig256Range - } - words := make([]big.Word, len(raw)/bigWordNibbles+1) - end := len(raw) - for i := range words { - start := end - bigWordNibbles - if start < 0 { - start = 0 - } - for ri := start; ri < end; ri++ { - nib := decodeNibble(raw[ri]) - if nib == badNibble { - return nil, ErrSyntax - } - words[i] *= 16 - words[i] += big.Word(nib) - } - end = start - } - dec := new(big.Int).SetBits(words) - return dec, nil -} - -// MustDecodeBig decodes a hex string with 0x prefix as a quantity. -// It panics for invalid input. -func MustDecodeBig(input string) *big.Int { - dec, err := DecodeBig(input) - if err != nil { - panic(err) - } - return dec -} - -// EncodeBig encodes bigint as a hex string with 0x prefix. -func EncodeBig(bigint *big.Int) string { - if sign := bigint.Sign(); sign == 0 { - return "0x0" - } else if sign > 0 { - return "0x" + bigint.Text(16) - } else { - return "-0x" + bigint.Text(16)[1:] - } -} - -func has0xPrefix(input string) bool { - return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') -} - -func checkNumber(input string) (raw string, err error) { - if len(input) == 0 { - return "", ErrEmptyString - } - if !has0xPrefix(input) { - return "", ErrMissingPrefix - } - input = input[2:] - if len(input) == 0 { - return "", ErrEmptyNumber - } - if len(input) > 1 && input[0] == '0' { - return "", ErrLeadingZero - } - return input, nil -} - -const badNibble = ^uint64(0) - -func decodeNibble(in byte) uint64 { - switch { - case in >= '0' && in <= '9': - return uint64(in - '0') - case in >= 'A' && in <= 'F': - return uint64(in - 'A' + 10) - case in >= 'a' && in <= 'f': - return uint64(in - 'a' + 10) - default: - return badNibble - } -} - -func mapError(err error) error { - if err, ok := err.(*strconv.NumError); ok { - switch err.Err { - case strconv.ErrRange: - return ErrUint64Range - case strconv.ErrSyntax: - return ErrSyntax - } - } - if _, ok := err.(hex.InvalidByteError); ok { - return ErrSyntax - } - if err == hex.ErrLength { - return ErrOddLength - } - return err -} diff --git a/builder/common/hexutil/hexutil_test.go b/builder/common/hexutil/hexutil_test.go deleted file mode 100644 index f2b800d82..000000000 --- a/builder/common/hexutil/hexutil_test.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2016 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 hexutil - -import ( - "bytes" - "math/big" - "testing" -) - -type marshalTest struct { - input interface{} - want string -} - -type unmarshalTest struct { - input string - want interface{} - wantErr error // if set, decoding must fail on any platform - wantErr32bit error // if set, decoding must fail on 32bit platforms (used for Uint tests) -} - -var ( - encodeBytesTests = []marshalTest{ - {[]byte{}, "0x"}, - {[]byte{0}, "0x00"}, - {[]byte{0, 0, 1, 2}, "0x00000102"}, - } - - encodeBigTests = []marshalTest{ - {referenceBig("0"), "0x0"}, - {referenceBig("1"), "0x1"}, - {referenceBig("ff"), "0xff"}, - {referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"}, - {referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"}, - {referenceBig("-80a7f2c1bcc396c00"), "-0x80a7f2c1bcc396c00"}, - } - - encodeUint64Tests = []marshalTest{ - {uint64(0), "0x0"}, - {uint64(1), "0x1"}, - {uint64(0xff), "0xff"}, - {uint64(0x1122334455667788), "0x1122334455667788"}, - } - - encodeUintTests = []marshalTest{ - {uint(0), "0x0"}, - {uint(1), "0x1"}, - {uint(0xff), "0xff"}, - {uint(0x11223344), "0x11223344"}, - } - - decodeBytesTests = []unmarshalTest{ - // invalid - {input: ``, wantErr: ErrEmptyString}, - {input: `0`, wantErr: ErrMissingPrefix}, - {input: `0x0`, wantErr: ErrOddLength}, - {input: `0x023`, wantErr: ErrOddLength}, - {input: `0xxx`, wantErr: ErrSyntax}, - {input: `0x01zz01`, wantErr: ErrSyntax}, - // valid - {input: `0x`, want: []byte{}}, - {input: `0X`, want: []byte{}}, - {input: `0x02`, want: []byte{0x02}}, - {input: `0X02`, want: []byte{0x02}}, - {input: `0xffffffffff`, want: []byte{0xff, 0xff, 0xff, 0xff, 0xff}}, - { - input: `0xffffffffffffffffffffffffffffffffffff`, - want: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - }, - } - - decodeBigTests = []unmarshalTest{ - // invalid - {input: `0`, wantErr: ErrMissingPrefix}, - {input: `0x`, wantErr: ErrEmptyNumber}, - {input: `0x01`, wantErr: ErrLeadingZero}, - {input: `0xx`, wantErr: ErrSyntax}, - {input: `0x1zz01`, wantErr: ErrSyntax}, - { - input: `0x10000000000000000000000000000000000000000000000000000000000000000`, - wantErr: ErrBig256Range, - }, - // valid - {input: `0x0`, want: big.NewInt(0)}, - {input: `0x2`, want: big.NewInt(0x2)}, - {input: `0x2F2`, want: big.NewInt(0x2f2)}, - {input: `0X2F2`, want: big.NewInt(0x2f2)}, - {input: `0x1122aaff`, want: big.NewInt(0x1122aaff)}, - {input: `0xbBb`, want: big.NewInt(0xbbb)}, - {input: `0xfffffffff`, want: big.NewInt(0xfffffffff)}, - { - input: `0x112233445566778899aabbccddeeff`, - want: referenceBig("112233445566778899aabbccddeeff"), - }, - { - input: `0xffffffffffffffffffffffffffffffffffff`, - want: referenceBig("ffffffffffffffffffffffffffffffffffff"), - }, - { - input: `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`, - want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - }, - } - - decodeUint64Tests = []unmarshalTest{ - // invalid - {input: `0`, wantErr: ErrMissingPrefix}, - {input: `0x`, wantErr: ErrEmptyNumber}, - {input: `0x01`, wantErr: ErrLeadingZero}, - {input: `0xfffffffffffffffff`, wantErr: ErrUint64Range}, - {input: `0xx`, wantErr: ErrSyntax}, - {input: `0x1zz01`, wantErr: ErrSyntax}, - // valid - {input: `0x0`, want: uint64(0)}, - {input: `0x2`, want: uint64(0x2)}, - {input: `0x2F2`, want: uint64(0x2f2)}, - {input: `0X2F2`, want: uint64(0x2f2)}, - {input: `0x1122aaff`, want: uint64(0x1122aaff)}, - {input: `0xbbb`, want: uint64(0xbbb)}, - {input: `0xffffffffffffffff`, want: uint64(0xffffffffffffffff)}, - } -) - -func TestEncode(t *testing.T) { - for _, test := range encodeBytesTests { - enc := Encode(test.input.([]byte)) - if enc != test.want { - t.Errorf("input %x: wrong encoding %s", test.input, enc) - } - } -} - -func TestDecode(t *testing.T) { - for _, test := range decodeBytesTests { - dec, err := Decode(test.input) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if !bytes.Equal(test.want.([]byte), dec) { - t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) - continue - } - } -} - -func TestEncodeBig(t *testing.T) { - for _, test := range encodeBigTests { - enc := EncodeBig(test.input.(*big.Int)) - if enc != test.want { - t.Errorf("input %x: wrong encoding %s", test.input, enc) - } - } -} - -func TestDecodeBig(t *testing.T) { - for _, test := range decodeBigTests { - dec, err := DecodeBig(test.input) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if dec.Cmp(test.want.(*big.Int)) != 0 { - t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) - continue - } - } -} - -func TestEncodeUint64(t *testing.T) { - for _, test := range encodeUint64Tests { - enc := EncodeUint64(test.input.(uint64)) - if enc != test.want { - t.Errorf("input %x: wrong encoding %s", test.input, enc) - } - } -} - -func TestDecodeUint64(t *testing.T) { - for _, test := range decodeUint64Tests { - dec, err := DecodeUint64(test.input) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if dec != test.want.(uint64) { - t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) - continue - } - } -} - -func BenchmarkEncodeBig(b *testing.B) { - for _, bench := range encodeBigTests { - b.Run(bench.want, func(b *testing.B) { - b.ReportAllocs() - bigint := bench.input.(*big.Int) - for i := 0; i < b.N; i++ { - EncodeBig(bigint) - } - }) - } -} diff --git a/builder/common/hexutil/json.go b/builder/common/hexutil/json.go deleted file mode 100644 index e0ac98f52..000000000 --- a/builder/common/hexutil/json.go +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright 2016 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 hexutil - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - "reflect" - "strconv" - - "github.com/holiman/uint256" -) - -var ( - bytesT = reflect.TypeOf(Bytes(nil)) - bigT = reflect.TypeOf((*Big)(nil)) - uintT = reflect.TypeOf(Uint(0)) - uint64T = reflect.TypeOf(Uint64(0)) - u256T = reflect.TypeOf((*uint256.Int)(nil)) -) - -// Bytes marshals/unmarshals as a JSON string with 0x prefix. -// The empty slice marshals as "0x". -type Bytes []byte - -// MarshalText implements encoding.TextMarshaler -func (b Bytes) MarshalText() ([]byte, error) { - result := make([]byte, len(b)*2+2) - copy(result, `0x`) - hex.Encode(result[2:], b) - return result, nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (b *Bytes) UnmarshalJSON(input []byte) error { - if !isString(input) { - return errNonString(bytesT) - } - return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (b *Bytes) UnmarshalText(input []byte) error { - raw, err := checkText(input, true) - if err != nil { - return err - } - dec := make([]byte, len(raw)/2) - if _, err = hex.Decode(dec, raw); err != nil { - err = mapError(err) - } else { - *b = dec - } - return err -} - -// String returns the hex encoding of b. -func (b Bytes) String() string { - return Encode(b) -} - -// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type. -func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (b *Bytes) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - data, err := Decode(input) - if err != nil { - return err - } - *b = data - default: - err = fmt.Errorf("unexpected type %T for Bytes", input) - } - return err -} - -// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out -// determines the required input length. This function is commonly used to implement the -// UnmarshalJSON method for fixed-size types. -func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { - if !isString(input) { - return errNonString(typ) - } - return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) -} - -// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out -// determines the required input length. This function is commonly used to implement the -// UnmarshalText method for fixed-size types. -func UnmarshalFixedText(typname string, input, out []byte) error { - raw, err := checkText(input, true) - if err != nil { - return err - } - if len(raw)/2 != len(out) { - return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) - } - // Pre-verify syntax before modifying out. - for _, b := range raw { - if decodeNibble(b) == badNibble { - return ErrSyntax - } - } - hex.Decode(out, raw) - return nil -} - -// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The -// length of out determines the required input length. This function is commonly used to -// implement the UnmarshalText method for fixed-size types. -func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { - raw, err := checkText(input, false) - if err != nil { - return err - } - if len(raw)/2 != len(out) { - return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) - } - // Pre-verify syntax before modifying out. - for _, b := range raw { - if decodeNibble(b) == badNibble { - return ErrSyntax - } - } - hex.Decode(out, raw) - return nil -} - -// Big marshals/unmarshals as a JSON string with 0x prefix. -// The zero value marshals as "0x0". -// -// Negative integers are not supported at this time. Attempting to marshal them will -// return an error. Values larger than 256bits are rejected by Unmarshal but will be -// marshaled without error. -type Big big.Int - -// MarshalText implements encoding.TextMarshaler -func (b Big) MarshalText() ([]byte, error) { - return []byte(EncodeBig((*big.Int)(&b))), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (b *Big) UnmarshalJSON(input []byte) error { - if !isString(input) { - return errNonString(bigT) - } - return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT) -} - -// UnmarshalText implements encoding.TextUnmarshaler -func (b *Big) UnmarshalText(input []byte) error { - raw, err := checkNumberText(input) - if err != nil { - return err - } - if len(raw) > 64 { - return ErrBig256Range - } - words := make([]big.Word, len(raw)/bigWordNibbles+1) - end := len(raw) - for i := range words { - start := end - bigWordNibbles - if start < 0 { - start = 0 - } - for ri := start; ri < end; ri++ { - nib := decodeNibble(raw[ri]) - if nib == badNibble { - return ErrSyntax - } - words[i] *= 16 - words[i] += big.Word(nib) - } - end = start - } - var dec big.Int - dec.SetBits(words) - *b = (Big)(dec) - return nil -} - -// ToInt converts b to a big.Int. -func (b *Big) ToInt() *big.Int { - return (*big.Int)(b) -} - -// String returns the hex encoding of b. -func (b *Big) String() string { - return EncodeBig(b.ToInt()) -} - -// ImplementsGraphQLType returns true if Big implements the provided GraphQL type. -func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (b *Big) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - return b.UnmarshalText([]byte(input)) - case int32: - var num big.Int - num.SetInt64(int64(input)) - *b = Big(num) - default: - err = fmt.Errorf("unexpected type %T for BigInt", input) - } - return err -} - -// U256 marshals/unmarshals as a JSON string with 0x prefix. -// The zero value marshals as "0x0". -type U256 uint256.Int - -// MarshalText implements encoding.TextMarshaler -func (b U256) MarshalText() ([]byte, error) { - u256 := (*uint256.Int)(&b) - return []byte(u256.Hex()), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (b *U256) UnmarshalJSON(input []byte) error { - // The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be - // more strict, hence we check string and invoke SetFromHex directly. - if !isString(input) { - return errNonString(u256T) - } - // The hex decoder needs to accept empty string ("") as '0', which uint256.Int - // would reject. - if len(input) == 2 { - (*uint256.Int)(b).Clear() - return nil - } - err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1])) - if err != nil { - return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T} - } - return nil -} - -// UnmarshalText implements encoding.TextUnmarshaler -func (b *U256) UnmarshalText(input []byte) error { - // The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be - // more strict, hence we check string and invoke SetFromHex directly. - return (*uint256.Int)(b).SetFromHex(string(input)) -} - -// String returns the hex encoding of b. -func (b *U256) String() string { - return (*uint256.Int)(b).Hex() -} - -// Uint64 marshals/unmarshals as a JSON string with 0x prefix. -// The zero value marshals as "0x0". -type Uint64 uint64 - -// MarshalText implements encoding.TextMarshaler. -func (b Uint64) MarshalText() ([]byte, error) { - buf := make([]byte, 2, 10) - copy(buf, `0x`) - buf = strconv.AppendUint(buf, uint64(b), 16) - return buf, nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (b *Uint64) UnmarshalJSON(input []byte) error { - if !isString(input) { - return errNonString(uint64T) - } - return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T) -} - -// UnmarshalText implements encoding.TextUnmarshaler -func (b *Uint64) UnmarshalText(input []byte) error { - raw, err := checkNumberText(input) - if err != nil { - return err - } - if len(raw) > 16 { - return ErrUint64Range - } - var dec uint64 - for _, byte := range raw { - nib := decodeNibble(byte) - if nib == badNibble { - return ErrSyntax - } - dec *= 16 - dec += nib - } - *b = Uint64(dec) - return nil -} - -// String returns the hex encoding of b. -func (b Uint64) String() string { - return EncodeUint64(uint64(b)) -} - -// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type. -func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (b *Uint64) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - return b.UnmarshalText([]byte(input)) - case int32: - *b = Uint64(input) - default: - err = fmt.Errorf("unexpected type %T for Long", input) - } - return err -} - -// Uint marshals/unmarshals as a JSON string with 0x prefix. -// The zero value marshals as "0x0". -type Uint uint - -// MarshalText implements encoding.TextMarshaler. -func (b Uint) MarshalText() ([]byte, error) { - return Uint64(b).MarshalText() -} - -// UnmarshalJSON implements json.Unmarshaler. -func (b *Uint) UnmarshalJSON(input []byte) error { - if !isString(input) { - return errNonString(uintT) - } - return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT) -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (b *Uint) UnmarshalText(input []byte) error { - var u64 Uint64 - err := u64.UnmarshalText(input) - if u64 > Uint64(^uint(0)) || err == ErrUint64Range { - return ErrUintRange - } else if err != nil { - return err - } - *b = Uint(u64) - return nil -} - -// String returns the hex encoding of b. -func (b Uint) String() string { - return EncodeUint64(uint64(b)) -} - -func isString(input []byte) bool { - return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' -} - -func bytesHave0xPrefix(input []byte) bool { - return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') -} - -func checkText(input []byte, wantPrefix bool) ([]byte, error) { - if len(input) == 0 { - return nil, nil // empty strings are allowed - } - if bytesHave0xPrefix(input) { - input = input[2:] - } else if wantPrefix { - return nil, ErrMissingPrefix - } - if len(input)%2 != 0 { - return nil, ErrOddLength - } - return input, nil -} - -func checkNumberText(input []byte) (raw []byte, err error) { - if len(input) == 0 { - return nil, nil // empty strings are allowed - } - if !bytesHave0xPrefix(input) { - return nil, ErrMissingPrefix - } - input = input[2:] - if len(input) == 0 { - return nil, ErrEmptyNumber - } - if len(input) > 1 && input[0] == '0' { - return nil, ErrLeadingZero - } - return input, nil -} - -func wrapTypeError(err error, typ reflect.Type) error { - if _, ok := err.(*decError); ok { - return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} - } - return err -} - -func errNonString(typ reflect.Type) error { - return &json.UnmarshalTypeError{Value: "non-string", Type: typ} -} diff --git a/builder/common/hexutil/json_example_test.go b/builder/common/hexutil/json_example_test.go deleted file mode 100644 index 80180d918..000000000 --- a/builder/common/hexutil/json_example_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// 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 hexutil_test - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -type MyType [5]byte - -func (v *MyType) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("MyType", input, v[:]) -} - -func (v MyType) String() string { - return hexutil.Bytes(v[:]).String() -} - -func ExampleUnmarshalFixedText() { - var v1, v2 MyType - fmt.Println("v1 error:", json.Unmarshal([]byte(`"0x01"`), &v1)) - fmt.Println("v2 error:", json.Unmarshal([]byte(`"0x0101010101"`), &v2)) - fmt.Println("v2:", v2) - // Output: - // v1 error: hex string has length 2, want 10 for MyType - // v2 error: - // v2: 0x0101010101 -} diff --git a/builder/common/hexutil/json_test.go b/builder/common/hexutil/json_test.go deleted file mode 100644 index 7cca30095..000000000 --- a/builder/common/hexutil/json_test.go +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2016 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 hexutil - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "errors" - "math/big" - "testing" - - "github.com/holiman/uint256" -) - -func checkError(t *testing.T, input string, got, want error) bool { - if got == nil { - if want != nil { - t.Errorf("input %s: got no error, want %q", input, want) - return false - } - return true - } - if want == nil { - t.Errorf("input %s: unexpected error %q", input, got) - } else if got.Error() != want.Error() { - t.Errorf("input %s: got error %q, want %q", input, got, want) - } - return false -} - -func referenceBig(s string) *big.Int { - b, ok := new(big.Int).SetString(s, 16) - if !ok { - panic("invalid") - } - return b -} - -func referenceBytes(s string) []byte { - b, err := hex.DecodeString(s) - if err != nil { - panic(err) - } - return b -} - -var errJSONEOF = errors.New("unexpected end of JSON input") - -var unmarshalBytesTests = []unmarshalTest{ - // invalid encoding - {input: "", wantErr: errJSONEOF}, - {input: "null", wantErr: errNonString(bytesT)}, - {input: "10", wantErr: errNonString(bytesT)}, - {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bytesT)}, - {input: `"0x0"`, wantErr: wrapTypeError(ErrOddLength, bytesT)}, - {input: `"0xxx"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, - {input: `"0x01zz01"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, - - // valid encoding - {input: `""`, want: referenceBytes("")}, - {input: `"0x"`, want: referenceBytes("")}, - {input: `"0x02"`, want: referenceBytes("02")}, - {input: `"0X02"`, want: referenceBytes("02")}, - {input: `"0xffffffffff"`, want: referenceBytes("ffffffffff")}, - { - input: `"0xffffffffffffffffffffffffffffffffffff"`, - want: referenceBytes("ffffffffffffffffffffffffffffffffffff"), - }, -} - -func TestUnmarshalBytes(t *testing.T) { - for _, test := range unmarshalBytesTests { - var v Bytes - err := json.Unmarshal([]byte(test.input), &v) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if !bytes.Equal(test.want.([]byte), v) { - t.Errorf("input %s: value mismatch: got %x, want %x", test.input, &v, test.want) - continue - } - } -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - input := []byte(`"0x123456789abcdef123456789abcdef"`) - for i := 0; i < b.N; i++ { - var v Bytes - if err := v.UnmarshalJSON(input); err != nil { - b.Fatal(err) - } - } -} - -func TestMarshalBytes(t *testing.T) { - for _, test := range encodeBytesTests { - in := test.input.([]byte) - out, err := json.Marshal(Bytes(in)) - if err != nil { - t.Errorf("%x: %v", in, err) - continue - } - if want := `"` + test.want + `"`; string(out) != want { - t.Errorf("%x: MarshalJSON output mismatch: got %q, want %q", in, out, want) - continue - } - if out := Bytes(in).String(); out != test.want { - t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) - continue - } - } -} - -var unmarshalBigTests = []unmarshalTest{ - // invalid encoding - {input: "", wantErr: errJSONEOF}, - {input: "null", wantErr: errNonString(bigT)}, - {input: "10", wantErr: errNonString(bigT)}, - {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bigT)}, - {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, bigT)}, - {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, bigT)}, - {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, - {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, - { - input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`, - wantErr: wrapTypeError(ErrBig256Range, bigT), - }, - - // valid encoding - {input: `""`, want: big.NewInt(0)}, - {input: `"0x0"`, want: big.NewInt(0)}, - {input: `"0x2"`, want: big.NewInt(0x2)}, - {input: `"0x2F2"`, want: big.NewInt(0x2f2)}, - {input: `"0X2F2"`, want: big.NewInt(0x2f2)}, - {input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)}, - {input: `"0xbBb"`, want: big.NewInt(0xbbb)}, - {input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)}, - { - input: `"0x112233445566778899aabbccddeeff"`, - want: referenceBig("112233445566778899aabbccddeeff"), - }, - { - input: `"0xffffffffffffffffffffffffffffffffffff"`, - want: referenceBig("ffffffffffffffffffffffffffffffffffff"), - }, - { - input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`, - want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - }, -} - -func TestUnmarshalBig(t *testing.T) { - for _, test := range unmarshalBigTests { - var v Big - err := json.Unmarshal([]byte(test.input), &v) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if test.want != nil && test.want.(*big.Int).Cmp((*big.Int)(&v)) != 0 { - t.Errorf("input %s: value mismatch: got %x, want %x", test.input, (*big.Int)(&v), test.want) - continue - } - } -} - -var unmarshalU256Tests = []unmarshalTest{ - // invalid encoding - {input: "", wantErr: errJSONEOF}, - {input: "null", wantErr: errNonString(u256T)}, - {input: "10", wantErr: errNonString(u256T)}, - {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, u256T)}, - {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, u256T)}, - {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, u256T)}, - {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, u256T)}, - {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, u256T)}, - { - input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`, - wantErr: wrapTypeError(ErrBig256Range, u256T), - }, - - // valid encoding - {input: `""`, want: big.NewInt(0)}, - {input: `"0x0"`, want: big.NewInt(0)}, - {input: `"0x2"`, want: big.NewInt(0x2)}, - {input: `"0x2F2"`, want: big.NewInt(0x2f2)}, - {input: `"0X2F2"`, want: big.NewInt(0x2f2)}, - {input: `"0x1122aaff"`, want: big.NewInt(0x1122aaff)}, - {input: `"0xbBb"`, want: big.NewInt(0xbbb)}, - {input: `"0xfffffffff"`, want: big.NewInt(0xfffffffff)}, - { - input: `"0x112233445566778899aabbccddeeff"`, - want: referenceBig("112233445566778899aabbccddeeff"), - }, - { - input: `"0xffffffffffffffffffffffffffffffffffff"`, - want: referenceBig("ffffffffffffffffffffffffffffffffffff"), - }, - { - input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`, - want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - }, -} - -func TestUnmarshalU256(t *testing.T) { - for _, test := range unmarshalU256Tests { - var v U256 - err := json.Unmarshal([]byte(test.input), &v) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if test.want == nil { - continue - } - want := new(uint256.Int) - want.SetFromBig(test.want.(*big.Int)) - have := (*uint256.Int)(&v) - if want.Cmp(have) != 0 { - t.Errorf("input %s: value mismatch: have %x, want %x", test.input, have, want) - continue - } - } -} - -func BenchmarkUnmarshalBig(b *testing.B) { - input := []byte(`"0x123456789abcdef123456789abcdef"`) - for i := 0; i < b.N; i++ { - var v Big - if err := v.UnmarshalJSON(input); err != nil { - b.Fatal(err) - } - } -} - -func TestMarshalBig(t *testing.T) { - for _, test := range encodeBigTests { - in := test.input.(*big.Int) - out, err := json.Marshal((*Big)(in)) - if err != nil { - t.Errorf("%d: %v", in, err) - continue - } - if want := `"` + test.want + `"`; string(out) != want { - t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) - continue - } - if out := (*Big)(in).String(); out != test.want { - t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) - continue - } - } -} - -var unmarshalUint64Tests = []unmarshalTest{ - // invalid encoding - {input: "", wantErr: errJSONEOF}, - {input: "null", wantErr: errNonString(uint64T)}, - {input: "10", wantErr: errNonString(uint64T)}, - {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uint64T)}, - {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uint64T)}, - {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uint64T)}, - {input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUint64Range, uint64T)}, - {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, - {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, - - // valid encoding - {input: `""`, want: uint64(0)}, - {input: `"0x0"`, want: uint64(0)}, - {input: `"0x2"`, want: uint64(0x2)}, - {input: `"0x2F2"`, want: uint64(0x2f2)}, - {input: `"0X2F2"`, want: uint64(0x2f2)}, - {input: `"0x1122aaff"`, want: uint64(0x1122aaff)}, - {input: `"0xbbb"`, want: uint64(0xbbb)}, - {input: `"0xffffffffffffffff"`, want: uint64(0xffffffffffffffff)}, -} - -func TestUnmarshalUint64(t *testing.T) { - for _, test := range unmarshalUint64Tests { - var v Uint64 - err := json.Unmarshal([]byte(test.input), &v) - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if uint64(v) != test.want.(uint64) { - t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) - continue - } - } -} - -func BenchmarkUnmarshalUint64(b *testing.B) { - input := []byte(`"0x123456789abcdf"`) - for i := 0; i < b.N; i++ { - var v Uint64 - v.UnmarshalJSON(input) - } -} - -func TestMarshalUint64(t *testing.T) { - for _, test := range encodeUint64Tests { - in := test.input.(uint64) - out, err := json.Marshal(Uint64(in)) - if err != nil { - t.Errorf("%d: %v", in, err) - continue - } - if want := `"` + test.want + `"`; string(out) != want { - t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) - continue - } - if out := (Uint64)(in).String(); out != test.want { - t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) - continue - } - } -} - -func TestMarshalUint(t *testing.T) { - for _, test := range encodeUintTests { - in := test.input.(uint) - out, err := json.Marshal(Uint(in)) - if err != nil { - t.Errorf("%d: %v", in, err) - continue - } - if want := `"` + test.want + `"`; string(out) != want { - t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) - continue - } - if out := (Uint)(in).String(); out != test.want { - t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) - continue - } - } -} - -var ( - // These are variables (not constants) to avoid constant overflow - // checks in the compiler on 32bit platforms. - maxUint33bits = uint64(^uint32(0)) + 1 - maxUint64bits = ^uint64(0) -) - -var unmarshalUintTests = []unmarshalTest{ - // invalid encoding - {input: "", wantErr: errJSONEOF}, - {input: "null", wantErr: errNonString(uintT)}, - {input: "10", wantErr: errNonString(uintT)}, - {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, uintT)}, - {input: `"0x"`, wantErr: wrapTypeError(ErrEmptyNumber, uintT)}, - {input: `"0x01"`, wantErr: wrapTypeError(ErrLeadingZero, uintT)}, - {input: `"0x100000000"`, want: uint(maxUint33bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, - {input: `"0xfffffffffffffffff"`, wantErr: wrapTypeError(ErrUintRange, uintT)}, - {input: `"0xx"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, - {input: `"0x1zz01"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, - - // valid encoding - {input: `""`, want: uint(0)}, - {input: `"0x0"`, want: uint(0)}, - {input: `"0x2"`, want: uint(0x2)}, - {input: `"0x2F2"`, want: uint(0x2f2)}, - {input: `"0X2F2"`, want: uint(0x2f2)}, - {input: `"0x1122aaff"`, want: uint(0x1122aaff)}, - {input: `"0xbbb"`, want: uint(0xbbb)}, - {input: `"0xffffffff"`, want: uint(0xffffffff)}, - {input: `"0xffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, -} - -func TestUnmarshalUint(t *testing.T) { - for _, test := range unmarshalUintTests { - var v Uint - err := json.Unmarshal([]byte(test.input), &v) - if uintBits == 32 && test.wantErr32bit != nil { - checkError(t, test.input, err, test.wantErr32bit) - continue - } - if !checkError(t, test.input, err, test.wantErr) { - continue - } - if uint(v) != test.want.(uint) { - t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) - continue - } - } -} - -func TestUnmarshalFixedUnprefixedText(t *testing.T) { - tests := []struct { - input string - want []byte - wantErr error - }{ - {input: "0x2", wantErr: ErrOddLength}, - {input: "2", wantErr: ErrOddLength}, - {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, - {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, - // check that output is not modified for partially correct input - {input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, - {input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, - // valid inputs - {input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, - {input: "0x44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, - } - - for _, test := range tests { - out := make([]byte, 4) - err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out) - switch { - case err == nil && test.wantErr != nil: - t.Errorf("%q: got no error, expected %q", test.input, test.wantErr) - case err != nil && test.wantErr == nil: - t.Errorf("%q: unexpected error %q", test.input, err) - case err != nil && err.Error() != test.wantErr.Error(): - t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr) - } - if test.want != nil && !bytes.Equal(out, test.want) { - t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want) - } - } -} diff --git a/builder/common/lru/basiclru.go b/builder/common/lru/basiclru.go deleted file mode 100644 index a429157fe..000000000 --- a/builder/common/lru/basiclru.go +++ /dev/null @@ -1,223 +0,0 @@ -// 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 lru implements generically-typed LRU caches. -package lru - -// BasicLRU is a simple LRU cache. -// -// This type is not safe for concurrent use. -// The zero value is not valid, instances must be created using NewCache. -type BasicLRU[K comparable, V any] struct { - list *list[K] - items map[K]cacheItem[K, V] - cap int -} - -type cacheItem[K any, V any] struct { - elem *listElem[K] - value V -} - -// NewBasicLRU creates a new LRU cache. -func NewBasicLRU[K comparable, V any](capacity int) BasicLRU[K, V] { - if capacity <= 0 { - capacity = 1 - } - c := BasicLRU[K, V]{ - items: make(map[K]cacheItem[K, V]), - list: newList[K](), - cap: capacity, - } - return c -} - -// Add adds a value to the cache. Returns true if an item was evicted to store the new item. -func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) { - item, ok := c.items[key] - if ok { - // Already exists in cache. - item.value = value - c.items[key] = item - c.list.moveToFront(item.elem) - return false - } - - var elem *listElem[K] - if c.Len() >= c.cap { - elem = c.list.removeLast() - delete(c.items, elem.v) - evicted = true - } else { - elem = new(listElem[K]) - } - - // Store the new item. - // Note that, if another item was evicted, we re-use its list element here. - elem.v = key - c.items[key] = cacheItem[K, V]{elem, value} - c.list.pushElem(elem) - return evicted -} - -// Contains reports whether the given key exists in the cache. -func (c *BasicLRU[K, V]) Contains(key K) bool { - _, ok := c.items[key] - return ok -} - -// Get retrieves a value from the cache. This marks the key as recently used. -func (c *BasicLRU[K, V]) Get(key K) (value V, ok bool) { - item, ok := c.items[key] - if !ok { - return value, false - } - c.list.moveToFront(item.elem) - return item.value, true -} - -// GetOldest retrieves the least-recently-used item. -// Note that this does not update the item's recency. -func (c *BasicLRU[K, V]) GetOldest() (key K, value V, ok bool) { - lastElem := c.list.last() - if lastElem == nil { - return key, value, false - } - key = lastElem.v - item := c.items[key] - return key, item.value, true -} - -// Len returns the current number of items in the cache. -func (c *BasicLRU[K, V]) Len() int { - return len(c.items) -} - -// Peek retrieves a value from the cache, but does not mark the key as recently used. -func (c *BasicLRU[K, V]) Peek(key K) (value V, ok bool) { - item, ok := c.items[key] - return item.value, ok -} - -// Purge empties the cache. -func (c *BasicLRU[K, V]) Purge() { - c.list.init() - for k := range c.items { - delete(c.items, k) - } -} - -// Remove drops an item from the cache. Returns true if the key was present in cache. -func (c *BasicLRU[K, V]) Remove(key K) bool { - item, ok := c.items[key] - if ok { - delete(c.items, key) - c.list.remove(item.elem) - } - return ok -} - -// RemoveOldest drops the least recently used item. -func (c *BasicLRU[K, V]) RemoveOldest() (key K, value V, ok bool) { - lastElem := c.list.last() - if lastElem == nil { - return key, value, false - } - - key = lastElem.v - item := c.items[key] - delete(c.items, key) - c.list.remove(lastElem) - return key, item.value, true -} - -// Keys returns all keys in the cache. -func (c *BasicLRU[K, V]) Keys() []K { - keys := make([]K, 0, len(c.items)) - return c.list.appendTo(keys) -} - -// list is a doubly-linked list holding items of type he. -// The zero value is not valid, use newList to create lists. -type list[T any] struct { - root listElem[T] -} - -type listElem[T any] struct { - next *listElem[T] - prev *listElem[T] - v T -} - -func newList[T any]() *list[T] { - l := new(list[T]) - l.init() - return l -} - -// init reinitializes the list, making it empty. -func (l *list[T]) init() { - l.root.next = &l.root - l.root.prev = &l.root -} - -// push adds an element to the front of the list. -func (l *list[T]) pushElem(e *listElem[T]) { - e.prev = &l.root - e.next = l.root.next - l.root.next = e - e.next.prev = e -} - -// moveToFront makes 'node' the head of the list. -func (l *list[T]) moveToFront(e *listElem[T]) { - e.prev.next = e.next - e.next.prev = e.prev - l.pushElem(e) -} - -// remove removes an element from the list. -func (l *list[T]) remove(e *listElem[T]) { - e.prev.next = e.next - e.next.prev = e.prev - e.next, e.prev = nil, nil -} - -// removeLast removes the last element of the list. -func (l *list[T]) removeLast() *listElem[T] { - last := l.last() - if last != nil { - l.remove(last) - } - return last -} - -// last returns the last element of the list, or nil if the list is empty. -func (l *list[T]) last() *listElem[T] { - e := l.root.prev - if e == &l.root { - return nil - } - return e -} - -// appendTo appends all list elements to a slice. -func (l *list[T]) appendTo(slice []T) []T { - for e := l.root.prev; e != &l.root; e = e.prev { - slice = append(slice, e.v) - } - return slice -} diff --git a/builder/common/lru/basiclru_test.go b/builder/common/lru/basiclru_test.go deleted file mode 100644 index 29812bda1..000000000 --- a/builder/common/lru/basiclru_test.go +++ /dev/null @@ -1,255 +0,0 @@ -// 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 lru - -import ( - crand "crypto/rand" - "fmt" - "io" - "math/rand" - "testing" -) - -// Some of these test cases were adapted -// from https://github.com/hashicorp/golang-lru/blob/master/simplelru/lru_test.go - -func TestBasicLRU(t *testing.T) { - cache := NewBasicLRU[int, int](128) - - for i := 0; i < 256; i++ { - cache.Add(i, i) - } - if cache.Len() != 128 { - t.Fatalf("bad len: %v", cache.Len()) - } - - // Check that Keys returns least-recent key first. - keys := cache.Keys() - if len(keys) != 128 { - t.Fatal("wrong Keys() length", len(keys)) - } - for i, k := range keys { - v, ok := cache.Peek(k) - if !ok { - t.Fatalf("expected key %d be present", i) - } - if v != k { - t.Fatalf("expected %d == %d", k, v) - } - if v != i+128 { - t.Fatalf("wrong value at key %d: %d, want %d", i, v, i+128) - } - } - - for i := 0; i < 128; i++ { - _, ok := cache.Get(i) - if ok { - t.Fatalf("%d should be evicted", i) - } - } - for i := 128; i < 256; i++ { - _, ok := cache.Get(i) - if !ok { - t.Fatalf("%d should not be evicted", i) - } - } - - for i := 128; i < 192; i++ { - ok := cache.Remove(i) - if !ok { - t.Fatalf("%d should be in cache", i) - } - ok = cache.Remove(i) - if ok { - t.Fatalf("%d should not be in cache", i) - } - _, ok = cache.Get(i) - if ok { - t.Fatalf("%d should be deleted", i) - } - } - - // Request item 192. - cache.Get(192) - // It should be the last item returned by Keys(). - for i, k := range cache.Keys() { - if (i < 63 && k != i+193) || (i == 63 && k != 192) { - t.Fatalf("out of order key: %v", k) - } - } - - cache.Purge() - if cache.Len() != 0 { - t.Fatalf("bad len: %v", cache.Len()) - } - if _, ok := cache.Get(200); ok { - t.Fatalf("should contain nothing") - } -} - -func TestBasicLRUAddExistingKey(t *testing.T) { - cache := NewBasicLRU[int, int](1) - - cache.Add(1, 1) - cache.Add(1, 2) - - v, _ := cache.Get(1) - if v != 2 { - t.Fatal("wrong value:", v) - } -} - -// This test checks GetOldest and RemoveOldest. -func TestBasicLRUGetOldest(t *testing.T) { - cache := NewBasicLRU[int, int](128) - for i := 0; i < 256; i++ { - cache.Add(i, i) - } - - k, _, ok := cache.GetOldest() - if !ok { - t.Fatalf("missing") - } - if k != 128 { - t.Fatalf("bad: %v", k) - } - - k, _, ok = cache.RemoveOldest() - if !ok { - t.Fatalf("missing") - } - if k != 128 { - t.Fatalf("bad: %v", k) - } - - k, _, ok = cache.RemoveOldest() - if !ok { - t.Fatalf("missing oldest item") - } - if k != 129 { - t.Fatalf("wrong oldest item: %v", k) - } -} - -// Test that Add returns true/false if an eviction occurred -func TestBasicLRUAddReturnValue(t *testing.T) { - cache := NewBasicLRU[int, int](1) - if cache.Add(1, 1) { - t.Errorf("first add shouldn't have evicted") - } - if !cache.Add(2, 2) { - t.Errorf("second add should have evicted") - } -} - -// This test verifies that Contains doesn't change item recency. -func TestBasicLRUContains(t *testing.T) { - cache := NewBasicLRU[int, int](2) - cache.Add(1, 1) - cache.Add(2, 2) - if !cache.Contains(1) { - t.Errorf("1 should be in the cache") - } - cache.Add(3, 3) - if cache.Contains(1) { - t.Errorf("Contains should not have updated recency of 1") - } -} - -// Test that Peek doesn't update recent-ness -func TestBasicLRUPeek(t *testing.T) { - cache := NewBasicLRU[int, int](2) - cache.Add(1, 1) - cache.Add(2, 2) - if v, ok := cache.Peek(1); !ok || v != 1 { - t.Errorf("1 should be set to 1") - } - cache.Add(3, 3) - if cache.Contains(1) { - t.Errorf("should not have updated recent-ness of 1") - } -} - -func BenchmarkLRU(b *testing.B) { - var ( - capacity = 1000 - indexes = make([]int, capacity*20) - keys = make([]string, capacity) - values = make([][]byte, capacity) - ) - for i := range indexes { - indexes[i] = rand.Intn(capacity) - } - for i := range keys { - b := make([]byte, 32) - crand.Read(b) - keys[i] = string(b) - crand.Read(b) - values[i] = b - } - - var sink []byte - - b.Run("Add/BasicLRU", func(b *testing.B) { - cache := NewBasicLRU[int, int](capacity) - for i := 0; i < b.N; i++ { - cache.Add(i, i) - } - }) - b.Run("Get/BasicLRU", func(b *testing.B) { - cache := NewBasicLRU[string, []byte](capacity) - for i := 0; i < capacity; i++ { - index := indexes[i] - cache.Add(keys[index], values[index]) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - k := keys[indexes[i%len(indexes)]] - v, ok := cache.Get(k) - if ok { - sink = v - } - } - }) - - // // vs. github.com/hashicorp/golang-lru/simplelru - // b.Run("Add/simplelru.LRU", func(b *testing.B) { - // cache, _ := simplelru.NewLRU(capacity, nil) - // for i := 0; i < b.N; i++ { - // cache.Add(i, i) - // } - // }) - // b.Run("Get/simplelru.LRU", func(b *testing.B) { - // cache, _ := simplelru.NewLRU(capacity, nil) - // for i := 0; i < capacity; i++ { - // index := indexes[i] - // cache.Add(keys[index], values[index]) - // } - // - // b.ResetTimer() - // for i := 0; i < b.N; i++ { - // k := keys[indexes[i%len(indexes)]] - // v, ok := cache.Get(k) - // if ok { - // sink = v.([]byte) - // } - // } - // }) - - fmt.Fprintln(io.Discard, sink) -} diff --git a/builder/common/lru/blob_lru.go b/builder/common/lru/blob_lru.go deleted file mode 100644 index c9b339850..000000000 --- a/builder/common/lru/blob_lru.go +++ /dev/null @@ -1,84 +0,0 @@ -// 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 lru - -import ( - "math" - "sync" -) - -// blobType is the type constraint for values stored in SizeConstrainedCache. -type blobType interface { - ~[]byte | ~string -} - -// SizeConstrainedCache is a cache where capacity is in bytes (instead of item count). When the cache -// is at capacity, and a new item is added, older items are evicted until the size -// constraint is met. -// -// OBS: This cache assumes that items are content-addressed: keys are unique per content. -// In other words: two Add(..) with the same key K, will always have the same value V. -type SizeConstrainedCache[K comparable, V blobType] struct { - size uint64 - maxSize uint64 - lru BasicLRU[K, V] - lock sync.Mutex -} - -// NewSizeConstrainedCache creates a new size-constrained LRU cache. -func NewSizeConstrainedCache[K comparable, V blobType](maxSize uint64) *SizeConstrainedCache[K, V] { - return &SizeConstrainedCache[K, V]{ - size: 0, - maxSize: maxSize, - lru: NewBasicLRU[K, V](math.MaxInt), - } -} - -// Add adds a value to the cache. Returns true if an eviction occurred. -// OBS: This cache assumes that items are content-addressed: keys are unique per content. -// In other words: two Add(..) with the same key K, will always have the same value V. -// OBS: The value is _not_ copied on Add, so the caller must not modify it afterwards. -func (c *SizeConstrainedCache[K, V]) Add(key K, value V) (evicted bool) { - c.lock.Lock() - defer c.lock.Unlock() - - // Unless it is already present, might need to evict something. - // OBS: If it is present, we still call Add internally to bump the recentness. - if !c.lru.Contains(key) { - targetSize := c.size + uint64(len(value)) - for targetSize > c.maxSize { - evicted = true - _, v, ok := c.lru.RemoveOldest() - if !ok { - // list is now empty. Break - break - } - targetSize -= uint64(len(v)) - } - c.size = targetSize - } - c.lru.Add(key, value) - return evicted -} - -// Get looks up a key's value from the cache. -func (c *SizeConstrainedCache[K, V]) Get(key K) (V, bool) { - c.lock.Lock() - defer c.lock.Unlock() - - return c.lru.Get(key) -} diff --git a/builder/common/lru/blob_lru_test.go b/builder/common/lru/blob_lru_test.go deleted file mode 100644 index ca1b0ddd7..000000000 --- a/builder/common/lru/blob_lru_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// 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 lru - -import ( - "encoding/binary" - "fmt" - "testing" -) - -type testKey [8]byte - -func mkKey(i int) (key testKey) { - binary.LittleEndian.PutUint64(key[:], uint64(i)) - return key -} - -func TestSizeConstrainedCache(t *testing.T) { - lru := NewSizeConstrainedCache[testKey, []byte](100) - var want uint64 - // Add 11 items of 10 byte each. First item should be swapped out - for i := 0; i < 11; i++ { - k := mkKey(i) - v := fmt.Sprintf("value-%04d", i) - lru.Add(k, []byte(v)) - want += uint64(len(v)) - if want > 100 { - want = 100 - } - if have := lru.size; have != want { - t.Fatalf("size wrong, have %d want %d", have, want) - } - } - // Zero:th should be evicted - { - k := mkKey(0) - if _, ok := lru.Get(k); ok { - t.Fatalf("should be evicted: %v", k) - } - } - // Elems 1-11 should be present - for i := 1; i < 11; i++ { - k := mkKey(i) - want := fmt.Sprintf("value-%04d", i) - have, ok := lru.Get(k) - if !ok { - t.Fatalf("missing key %v", k) - } - if string(have) != want { - t.Fatalf("wrong value, have %v want %v", have, want) - } - } -} - -// This test adds inserting an element exceeding the max size. -func TestSizeConstrainedCacheOverflow(t *testing.T) { - lru := NewSizeConstrainedCache[testKey, []byte](100) - - // Add 10 items of 10 byte each, filling the cache - for i := 0; i < 10; i++ { - k := mkKey(i) - v := fmt.Sprintf("value-%04d", i) - lru.Add(k, []byte(v)) - } - // Add one single large elem. We expect it to swap out all entries. - { - k := mkKey(1337) - v := make([]byte, 200) - lru.Add(k, v) - } - // Elems 0-9 should be missing - for i := 1; i < 10; i++ { - k := mkKey(i) - if _, ok := lru.Get(k); ok { - t.Fatalf("should be evicted: %v", k) - } - } - // The size should be accurate - if have, want := lru.size, uint64(200); have != want { - t.Fatalf("size wrong, have %d want %d", have, want) - } - // Adding one small item should swap out the large one - { - i := 0 - k := mkKey(i) - v := fmt.Sprintf("value-%04d", i) - lru.Add(k, []byte(v)) - if have, want := lru.size, uint64(10); have != want { - t.Fatalf("size wrong, have %d want %d", have, want) - } - } -} - -// This checks what happens when inserting the same k/v multiple times. -func TestSizeConstrainedCacheSameItem(t *testing.T) { - lru := NewSizeConstrainedCache[testKey, []byte](100) - - // Add one 10 byte-item 10 times. - k := mkKey(0) - v := fmt.Sprintf("value-%04d", 0) - for i := 0; i < 10; i++ { - lru.Add(k, []byte(v)) - } - - // The size should be accurate. - if have, want := lru.size, uint64(10); have != want { - t.Fatalf("size wrong, have %d want %d", have, want) - } -} - -// This tests that empty/nil values are handled correctly. -func TestSizeConstrainedCacheEmpties(t *testing.T) { - lru := NewSizeConstrainedCache[testKey, []byte](100) - - // This test abuses the lru a bit, using different keys for identical value(s). - for i := 0; i < 10; i++ { - lru.Add(testKey{byte(i)}, []byte{}) - lru.Add(testKey{byte(255 - i)}, nil) - } - - // The size should not count, only the values count. So this could be a DoS - // since it basically has no cap, and it is intentionally overloaded with - // different-keyed 0-length values. - if have, want := lru.size, uint64(0); have != want { - t.Fatalf("size wrong, have %d want %d", have, want) - } - - for i := 0; i < 10; i++ { - if v, ok := lru.Get(testKey{byte(i)}); !ok { - t.Fatalf("test %d: expected presence", i) - } else if v == nil { - t.Fatalf("test %d, v is nil", i) - } - - if v, ok := lru.Get(testKey{byte(255 - i)}); !ok { - t.Fatalf("test %d: expected presence", i) - } else if v != nil { - t.Fatalf("test %d, v is not nil", i) - } - } -} diff --git a/builder/common/lru/lru.go b/builder/common/lru/lru.go deleted file mode 100644 index 45965adb0..000000000 --- a/builder/common/lru/lru.go +++ /dev/null @@ -1,95 +0,0 @@ -// 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 lru - -import "sync" - -// Cache is a LRU cache. -// This type is safe for concurrent use. -type Cache[K comparable, V any] struct { - cache BasicLRU[K, V] - mu sync.Mutex -} - -// NewCache creates an LRU cache. -func NewCache[K comparable, V any](capacity int) *Cache[K, V] { - return &Cache[K, V]{cache: NewBasicLRU[K, V](capacity)} -} - -// Add adds a value to the cache. Returns true if an item was evicted to store the new item. -func (c *Cache[K, V]) Add(key K, value V) (evicted bool) { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Add(key, value) -} - -// Contains reports whether the given key exists in the cache. -func (c *Cache[K, V]) Contains(key K) bool { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Contains(key) -} - -// Get retrieves a value from the cache. This marks the key as recently used. -func (c *Cache[K, V]) Get(key K) (value V, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Get(key) -} - -// Len returns the current number of items in the cache. -func (c *Cache[K, V]) Len() int { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Len() -} - -// Peek retrieves a value from the cache, but does not mark the key as recently used. -func (c *Cache[K, V]) Peek(key K) (value V, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Peek(key) -} - -// Purge empties the cache. -func (c *Cache[K, V]) Purge() { - c.mu.Lock() - defer c.mu.Unlock() - - c.cache.Purge() -} - -// Remove drops an item from the cache. Returns true if the key was present in cache. -func (c *Cache[K, V]) Remove(key K) bool { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Remove(key) -} - -// Keys returns all keys of items currently in the LRU. -func (c *Cache[K, V]) Keys() []K { - c.mu.Lock() - defer c.mu.Unlock() - - return c.cache.Keys() -} diff --git a/builder/common/math/big.go b/builder/common/math/big.go deleted file mode 100644 index 013c0ba4b..000000000 --- a/builder/common/math/big.go +++ /dev/null @@ -1,270 +0,0 @@ -// 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 math provides integer math utilities. -package math - -import ( - "fmt" - "math/big" -) - -// Various big integer limit values. -var ( - tt255 = BigPow(2, 255) - tt256 = BigPow(2, 256) - tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) - tt63 = BigPow(2, 63) - MaxBig256 = new(big.Int).Set(tt256m1) - MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1)) -) - -const ( - // number of bits in a big.Word - wordBits = 32 << (uint64(^big.Word(0)) >> 63) - // number of bytes in a big.Word - wordBytes = wordBits / 8 -) - -// HexOrDecimal256 marshals big.Int as hex or decimal. -type HexOrDecimal256 big.Int - -// NewHexOrDecimal256 creates a new HexOrDecimal256 -func NewHexOrDecimal256(x int64) *HexOrDecimal256 { - b := big.NewInt(x) - h := HexOrDecimal256(*b) - return &h -} - -// UnmarshalJSON implements json.Unmarshaler. -// -// It is similar to UnmarshalText, but allows parsing real decimals too, not just -// quoted decimal strings. -func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error { - if len(input) > 0 && input[0] == '"' { - input = input[1 : len(input)-1] - } - return i.UnmarshalText(input) -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (i *HexOrDecimal256) UnmarshalText(input []byte) error { - bigint, ok := ParseBig256(string(input)) - if !ok { - return fmt.Errorf("invalid hex or decimal integer %q", input) - } - *i = HexOrDecimal256(*bigint) - return nil -} - -// MarshalText implements encoding.TextMarshaler. -func (i *HexOrDecimal256) MarshalText() ([]byte, error) { - if i == nil { - return []byte("0x0"), nil - } - return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil -} - -// Decimal256 unmarshals big.Int as a decimal string. When unmarshalling, -// it however accepts either "0x"-prefixed (hex encoded) or non-prefixed (decimal) -type Decimal256 big.Int - -// NewDecimal256 creates a new Decimal256 -func NewDecimal256(x int64) *Decimal256 { - b := big.NewInt(x) - d := Decimal256(*b) - return &d -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (i *Decimal256) UnmarshalText(input []byte) error { - bigint, ok := ParseBig256(string(input)) - if !ok { - return fmt.Errorf("invalid hex or decimal integer %q", input) - } - *i = Decimal256(*bigint) - return nil -} - -// MarshalText implements encoding.TextMarshaler. -func (i *Decimal256) MarshalText() ([]byte, error) { - return []byte(i.String()), nil -} - -// String implements Stringer. -func (i *Decimal256) String() string { - if i == nil { - return "0" - } - return fmt.Sprintf("%#d", (*big.Int)(i)) -} - -// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax. -// Leading zeros are accepted. The empty string parses as zero. -func ParseBig256(s string) (*big.Int, bool) { - if s == "" { - return new(big.Int), true - } - var bigint *big.Int - var ok bool - if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { - bigint, ok = new(big.Int).SetString(s[2:], 16) - } else { - bigint, ok = new(big.Int).SetString(s, 10) - } - if ok && bigint.BitLen() > 256 { - bigint, ok = nil, false - } - return bigint, ok -} - -// MustParseBig256 parses s as a 256 bit big integer and panics if the string is invalid. -func MustParseBig256(s string) *big.Int { - v, ok := ParseBig256(s) - if !ok { - panic("invalid 256 bit integer: " + s) - } - return v -} - -// BigPow returns a ** b as a big integer. -func BigPow(a, b int64) *big.Int { - r := big.NewInt(a) - return r.Exp(r, big.NewInt(b), nil) -} - -// BigMax returns the larger of x or y. -func BigMax(x, y *big.Int) *big.Int { - if x.Cmp(y) < 0 { - return y - } - return x -} - -// BigMin returns the smaller of x or y. -func BigMin(x, y *big.Int) *big.Int { - if x.Cmp(y) > 0 { - return y - } - return x -} - -// FirstBitSet returns the index of the first 1 bit in v, counting from LSB. -func FirstBitSet(v *big.Int) int { - for i := 0; i < v.BitLen(); i++ { - if v.Bit(i) > 0 { - return i - } - } - return v.BitLen() -} - -// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length -// of the slice is at least n bytes. -func PaddedBigBytes(bigint *big.Int, n int) []byte { - if bigint.BitLen()/8 >= n { - return bigint.Bytes() - } - ret := make([]byte, n) - ReadBits(bigint, ret) - return ret -} - -// bigEndianByteAt returns the byte at position n, -// in Big-Endian encoding -// So n==0 returns the least significant byte -func bigEndianByteAt(bigint *big.Int, n int) byte { - words := bigint.Bits() - // Check word-bucket the byte will reside in - i := n / wordBytes - if i >= len(words) { - return byte(0) - } - word := words[i] - // Offset of the byte - shift := 8 * uint(n%wordBytes) - - return byte(word >> shift) -} - -// Byte returns the byte at position n, -// with the supplied padlength in Little-Endian encoding. -// n==0 returns the MSB -// Example: bigint '5', padlength 32, n=31 => 5 -func Byte(bigint *big.Int, padlength, n int) byte { - if n >= padlength { - return byte(0) - } - return bigEndianByteAt(bigint, padlength-1-n) -} - -// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure -// that buf has enough space. If buf is too short the result will be incomplete. -func ReadBits(bigint *big.Int, buf []byte) { - i := len(buf) - for _, d := range bigint.Bits() { - for j := 0; j < wordBytes && i > 0; j++ { - i-- - buf[i] = byte(d) - d >>= 8 - } - } -} - -// U256 encodes as a 256 bit two's complement number. This operation is destructive. -func U256(x *big.Int) *big.Int { - return x.And(x, tt256m1) -} - -// U256Bytes converts a big Int into a 256bit EVM number. -// This operation is destructive. -func U256Bytes(n *big.Int) []byte { - return PaddedBigBytes(U256(n), 32) -} - -// S256 interprets x as a two's complement number. -// x must not exceed 256 bits (the result is undefined if it does) and is not modified. -// -// S256(0) = 0 -// S256(1) = 1 -// S256(2**255) = -2**255 -// S256(2**256-1) = -1 -func S256(x *big.Int) *big.Int { - if x.Cmp(tt255) < 0 { - return x - } - return new(big.Int).Sub(x, tt256) -} - -// Exp implements exponentiation by squaring. -// Exp returns a newly-allocated big integer and does not change -// base or exponent. The result is truncated to 256 bits. -// -// Courtesy @karalabe and @chfast -func Exp(base, exponent *big.Int) *big.Int { - result := big.NewInt(1) - - for _, word := range exponent.Bits() { - for i := 0; i < wordBits; i++ { - if word&1 == 1 { - U256(result.Mul(result, base)) - } - U256(base.Mul(base, base)) - word >>= 1 - } - } - return result -} diff --git a/builder/common/math/big_test.go b/builder/common/math/big_test.go deleted file mode 100644 index 803b5e1cc..000000000 --- a/builder/common/math/big_test.go +++ /dev/null @@ -1,324 +0,0 @@ -// 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 math - -import ( - "bytes" - "encoding/hex" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func TestHexOrDecimal256(t *testing.T) { - tests := []struct { - input string - num *big.Int - ok bool - }{ - {"", big.NewInt(0), true}, - {"0", big.NewInt(0), true}, - {"0x0", big.NewInt(0), true}, - {"12345678", big.NewInt(12345678), true}, - {"0x12345678", big.NewInt(0x12345678), true}, - {"0X12345678", big.NewInt(0x12345678), true}, - // Tests for leading zero behaviour: - {"0123456789", big.NewInt(123456789), true}, // note: not octal - {"00", big.NewInt(0), true}, - {"0x00", big.NewInt(0), true}, - {"0x012345678abc", big.NewInt(0x12345678abc), true}, - // Invalid syntax: - {"abcdef", nil, false}, - {"0xgg", nil, false}, - // Larger than 256 bits: - {"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false}, - } - for _, test := range tests { - var num HexOrDecimal256 - err := num.UnmarshalText([]byte(test.input)) - if (err == nil) != test.ok { - t.Errorf("ParseBig(%q) -> (err == nil) == %t, want %t", test.input, err == nil, test.ok) - continue - } - if test.num != nil && (*big.Int)(&num).Cmp(test.num) != 0 { - t.Errorf("ParseBig(%q) -> %d, want %d", test.input, (*big.Int)(&num), test.num) - } - } -} - -func TestMustParseBig256(t *testing.T) { - defer func() { - if recover() == nil { - t.Error("MustParseBig should've panicked") - } - }() - MustParseBig256("ggg") -} - -func TestBigMax(t *testing.T) { - a := big.NewInt(10) - b := big.NewInt(5) - - max1 := BigMax(a, b) - if max1 != a { - t.Errorf("Expected %d got %d", a, max1) - } - - max2 := BigMax(b, a) - if max2 != a { - t.Errorf("Expected %d got %d", a, max2) - } -} - -func TestBigMin(t *testing.T) { - a := big.NewInt(10) - b := big.NewInt(5) - - min1 := BigMin(a, b) - if min1 != b { - t.Errorf("Expected %d got %d", b, min1) - } - - min2 := BigMin(b, a) - if min2 != b { - t.Errorf("Expected %d got %d", b, min2) - } -} - -func TestFirstBigSet(t *testing.T) { - tests := []struct { - num *big.Int - ix int - }{ - {big.NewInt(0), 0}, - {big.NewInt(1), 0}, - {big.NewInt(2), 1}, - {big.NewInt(0x100), 8}, - } - for _, test := range tests { - if ix := FirstBitSet(test.num); ix != test.ix { - t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix) - } - } -} - -func TestPaddedBigBytes(t *testing.T) { - tests := []struct { - num *big.Int - n int - result []byte - }{ - {num: big.NewInt(0), n: 4, result: []byte{0, 0, 0, 0}}, - {num: big.NewInt(1), n: 4, result: []byte{0, 0, 0, 1}}, - {num: big.NewInt(512), n: 4, result: []byte{0, 0, 2, 0}}, - {num: BigPow(2, 32), n: 4, result: []byte{1, 0, 0, 0, 0}}, - } - for _, test := range tests { - if result := PaddedBigBytes(test.num, test.n); !bytes.Equal(result, test.result) { - t.Errorf("PaddedBigBytes(%d, %d) = %v, want %v", test.num, test.n, result, test.result) - } - } -} - -func BenchmarkPaddedBigBytesLargePadding(b *testing.B) { - bigint := MustParseBig256("123456789123456789123456789123456789") - for i := 0; i < b.N; i++ { - PaddedBigBytes(bigint, 200) - } -} - -func BenchmarkPaddedBigBytesSmallPadding(b *testing.B) { - bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") - for i := 0; i < b.N; i++ { - PaddedBigBytes(bigint, 5) - } -} - -func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) { - bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") - for i := 0; i < b.N; i++ { - PaddedBigBytes(bigint, 32) - } -} - -func BenchmarkByteAtBrandNew(b *testing.B) { - bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") - for i := 0; i < b.N; i++ { - bigEndianByteAt(bigint, 15) - } -} - -func BenchmarkByteAt(b *testing.B) { - bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") - for i := 0; i < b.N; i++ { - bigEndianByteAt(bigint, 15) - } -} - -func BenchmarkByteAtOld(b *testing.B) { - bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") - for i := 0; i < b.N; i++ { - PaddedBigBytes(bigint, 32) - } -} - -func TestReadBits(t *testing.T) { - check := func(input string) { - want, _ := hex.DecodeString(input) - int, _ := new(big.Int).SetString(input, 16) - buf := make([]byte, len(want)) - ReadBits(int, buf) - if !bytes.Equal(buf, want) { - t.Errorf("have: %x\nwant: %x", buf, want) - } - } - check("000000000000000000000000000000000000000000000000000000FEFCF3F8F0") - check("0000000000012345000000000000000000000000000000000000FEFCF3F8F0") - check("18F8F8F1000111000110011100222004330052300000000000000000FEFCF3F8F0") -} - -func TestU256(t *testing.T) { - tests := []struct{ x, y *big.Int }{ - {x: big.NewInt(0), y: big.NewInt(0)}, - {x: big.NewInt(1), y: big.NewInt(1)}, - {x: BigPow(2, 255), y: BigPow(2, 255)}, - {x: BigPow(2, 256), y: big.NewInt(0)}, - {x: new(big.Int).Add(BigPow(2, 256), big.NewInt(1)), y: big.NewInt(1)}, - // negative values - {x: big.NewInt(-1), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1))}, - {x: big.NewInt(-2), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2))}, - {x: BigPow(2, -255), y: big.NewInt(1)}, - } - for _, test := range tests { - if y := U256(new(big.Int).Set(test.x)); y.Cmp(test.y) != 0 { - t.Errorf("U256(%x) = %x, want %x", test.x, y, test.y) - } - } -} - -func TestU256Bytes(t *testing.T) { - ubytes := make([]byte, 32) - ubytes[31] = 1 - - unsigned := U256Bytes(big.NewInt(1)) - if !bytes.Equal(unsigned, ubytes) { - t.Errorf("expected %x got %x", ubytes, unsigned) - } -} - -func TestBigEndianByteAt(t *testing.T) { - tests := []struct { - x string - y int - exp byte - }{ - {"00", 0, 0x00}, - {"01", 1, 0x00}, - {"00", 1, 0x00}, - {"01", 0, 0x01}, - {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30}, - {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00}, - } - for _, test := range tests { - v := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) - actual := bigEndianByteAt(v, test.y) - if actual != test.exp { - t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) - } - } -} -func TestLittleEndianByteAt(t *testing.T) { - tests := []struct { - x string - y int - exp byte - }{ - {"00", 0, 0x00}, - {"01", 1, 0x00}, - {"00", 1, 0x00}, - {"01", 0, 0x00}, - {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00}, - {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD}, - {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00}, - {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD}, - {"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30}, - {"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0}, - } - for _, test := range tests { - v := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) - actual := Byte(v, 32, test.y) - if actual != test.exp { - t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) - } - } -} - -func TestS256(t *testing.T) { - tests := []struct{ x, y *big.Int }{ - {x: big.NewInt(0), y: big.NewInt(0)}, - {x: big.NewInt(1), y: big.NewInt(1)}, - {x: big.NewInt(2), y: big.NewInt(2)}, - { - x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), - y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), - }, - { - x: BigPow(2, 255), - y: new(big.Int).Neg(BigPow(2, 255)), - }, - { - x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)), - y: big.NewInt(-1), - }, - { - x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)), - y: big.NewInt(-2), - }, - } - for _, test := range tests { - if y := S256(test.x); y.Cmp(test.y) != 0 { - t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y) - } - } -} - -func TestExp(t *testing.T) { - tests := []struct{ base, exponent, result *big.Int }{ - {base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)}, - {base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)}, - {base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)}, - {base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)}, - {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")}, - {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, - } - for _, test := range tests { - if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { - t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result) - } - } -} diff --git a/builder/common/math/integer.go b/builder/common/math/integer.go deleted file mode 100644 index da01c0a08..000000000 --- a/builder/common/math/integer.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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 math - -import ( - "fmt" - "math/bits" - "strconv" -) - -// Integer limit values. -const ( - MaxInt8 = 1<<7 - 1 - MinInt8 = -1 << 7 - MaxInt16 = 1<<15 - 1 - MinInt16 = -1 << 15 - MaxInt32 = 1<<31 - 1 - MinInt32 = -1 << 31 - MaxInt64 = 1<<63 - 1 - MinInt64 = -1 << 63 - MaxUint8 = 1<<8 - 1 - MaxUint16 = 1<<16 - 1 - MaxUint32 = 1<<32 - 1 - MaxUint64 = 1<<64 - 1 -) - -// HexOrDecimal64 marshals uint64 as hex or decimal. -type HexOrDecimal64 uint64 - -// UnmarshalJSON implements json.Unmarshaler. -// -// It is similar to UnmarshalText, but allows parsing real decimals too, not just -// quoted decimal strings. -func (i *HexOrDecimal64) UnmarshalJSON(input []byte) error { - if len(input) > 0 && input[0] == '"' { - input = input[1 : len(input)-1] - } - return i.UnmarshalText(input) -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (i *HexOrDecimal64) UnmarshalText(input []byte) error { - int, ok := ParseUint64(string(input)) - if !ok { - return fmt.Errorf("invalid hex or decimal integer %q", input) - } - *i = HexOrDecimal64(int) - return nil -} - -// MarshalText implements encoding.TextMarshaler. -func (i HexOrDecimal64) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("%#x", uint64(i))), nil -} - -// ParseUint64 parses s as an integer in decimal or hexadecimal syntax. -// Leading zeros are accepted. The empty string parses as zero. -func ParseUint64(s string) (uint64, bool) { - if s == "" { - return 0, true - } - if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { - v, err := strconv.ParseUint(s[2:], 16, 64) - return v, err == nil - } - v, err := strconv.ParseUint(s, 10, 64) - return v, err == nil -} - -// MustParseUint64 parses s as an integer and panics if the string is invalid. -func MustParseUint64(s string) uint64 { - v, ok := ParseUint64(s) - if !ok { - panic("invalid unsigned 64 bit integer: " + s) - } - return v -} - -// SafeSub returns x-y and checks for overflow. -func SafeSub(x, y uint64) (uint64, bool) { - diff, borrowOut := bits.Sub64(x, y, 0) - return diff, borrowOut != 0 -} - -// SafeAdd returns x+y and checks for overflow. -func SafeAdd(x, y uint64) (uint64, bool) { - sum, carryOut := bits.Add64(x, y, 0) - return sum, carryOut != 0 -} - -// SafeMul returns x*y and checks for overflow. -func SafeMul(x, y uint64) (uint64, bool) { - hi, lo := bits.Mul64(x, y) - return lo, hi != 0 -} diff --git a/builder/common/math/integer_test.go b/builder/common/math/integer_test.go deleted file mode 100644 index b31c7c26c..000000000 --- a/builder/common/math/integer_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// 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 math - -import ( - "testing" -) - -type operation byte - -const ( - sub operation = iota - add - mul -) - -func TestOverflow(t *testing.T) { - for i, test := range []struct { - x uint64 - y uint64 - overflow bool - op operation - }{ - // add operations - {MaxUint64, 1, true, add}, - {MaxUint64 - 1, 1, false, add}, - - // sub operations - {0, 1, true, sub}, - {0, 0, false, sub}, - - // mul operations - {0, 0, false, mul}, - {10, 10, false, mul}, - {MaxUint64, 2, true, mul}, - {MaxUint64, 1, false, mul}, - } { - var overflows bool - switch test.op { - case sub: - _, overflows = SafeSub(test.x, test.y) - case add: - _, overflows = SafeAdd(test.x, test.y) - case mul: - _, overflows = SafeMul(test.x, test.y) - } - - if test.overflow != overflows { - t.Errorf("%d failed. Expected test to be %v, got %v", i, test.overflow, overflows) - } - } -} - -func TestHexOrDecimal64(t *testing.T) { - tests := []struct { - input string - num uint64 - ok bool - }{ - {"", 0, true}, - {"0", 0, true}, - {"0x0", 0, true}, - {"12345678", 12345678, true}, - {"0x12345678", 0x12345678, true}, - {"0X12345678", 0x12345678, true}, - // Tests for leading zero behaviour: - {"0123456789", 123456789, true}, // note: not octal - {"0x00", 0, true}, - {"0x012345678abc", 0x12345678abc, true}, - // Invalid syntax: - {"abcdef", 0, false}, - {"0xgg", 0, false}, - // Doesn't fit into 64 bits: - {"18446744073709551617", 0, false}, - } - for _, test := range tests { - var num HexOrDecimal64 - err := num.UnmarshalText([]byte(test.input)) - if (err == nil) != test.ok { - t.Errorf("ParseUint64(%q) -> (err == nil) = %t, want %t", test.input, err == nil, test.ok) - continue - } - if err == nil && uint64(num) != test.num { - t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num) - } - } -} - -func TestMustParseUint64(t *testing.T) { - if v := MustParseUint64("12345"); v != 12345 { - t.Errorf(`MustParseUint64("12345") = %d, want 12345`, v) - } -} - -func TestMustParseUint64Panic(t *testing.T) { - defer func() { - if recover() == nil { - t.Error("MustParseBig should've panicked") - } - }() - MustParseUint64("ggg") -} diff --git a/builder/common/mclock/alarm.go b/builder/common/mclock/alarm.go deleted file mode 100644 index e83810a6a..000000000 --- a/builder/common/mclock/alarm.go +++ /dev/null @@ -1,106 +0,0 @@ -// 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 mclock - -import ( - "time" -) - -// Alarm sends timed notifications on a channel. This is very similar to a regular timer, -// but is easier to use in code that needs to re-schedule the same timer over and over. -// -// When scheduling an Alarm, the channel returned by C() will receive a value no later -// than the scheduled time. An Alarm can be reused after it has fired and can also be -// canceled by calling Stop. -type Alarm struct { - ch chan struct{} - clock Clock - timer Timer - deadline AbsTime -} - -// NewAlarm creates an Alarm. -func NewAlarm(clock Clock) *Alarm { - if clock == nil { - panic("nil clock") - } - return &Alarm{ - ch: make(chan struct{}, 1), - clock: clock, - } -} - -// C returns the alarm notification channel. This channel remains identical for -// the entire lifetime of the alarm, and is never closed. -func (e *Alarm) C() <-chan struct{} { - return e.ch -} - -// Stop cancels the alarm and drains the channel. -// This method is not safe for concurrent use. -func (e *Alarm) Stop() { - // Clear timer. - if e.timer != nil { - e.timer.Stop() - } - e.deadline = 0 - - // Drain the channel. - select { - case <-e.ch: - default: - } -} - -// Schedule sets the alarm to fire no later than the given time. If the alarm was already -// scheduled but has not fired yet, it may fire earlier than the newly-scheduled time. -func (e *Alarm) Schedule(time AbsTime) { - now := e.clock.Now() - e.schedule(now, time) -} - -func (e *Alarm) schedule(now, newDeadline AbsTime) { - if e.timer != nil { - if e.deadline > now && e.deadline <= newDeadline { - // Here, the current timer can be reused because it is already scheduled to - // occur earlier than the new deadline. - // - // The e.deadline > now part of the condition is important. If the old - // deadline lies in the past, we assume the timer has already fired and needs - // to be rescheduled. - return - } - e.timer.Stop() - } - - // Set the timer. - d := time.Duration(0) - if newDeadline < now { - newDeadline = now - } else { - d = newDeadline.Sub(now) - } - e.timer = e.clock.AfterFunc(d, e.send) - e.deadline = newDeadline -} - -func (e *Alarm) send() { - select { - case e.ch <- struct{}{}: - default: - } -} diff --git a/builder/common/mclock/alarm_test.go b/builder/common/mclock/alarm_test.go deleted file mode 100644 index d2ad9913f..000000000 --- a/builder/common/mclock/alarm_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// 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 mclock - -import "testing" - -// This test checks basic functionality of Alarm. -func TestAlarm(t *testing.T) { - clk := new(Simulated) - clk.Run(20) - a := NewAlarm(clk) - - a.Schedule(clk.Now() + 10) - if recv(a.C()) { - t.Fatal("Alarm fired before scheduled deadline") - } - if ntimers := clk.ActiveTimers(); ntimers != 1 { - t.Fatal("clock has", ntimers, "active timers, want", 1) - } - clk.Run(5) - if recv(a.C()) { - t.Fatal("Alarm fired too early") - } - - clk.Run(5) - if !recv(a.C()) { - t.Fatal("Alarm did not fire") - } - if recv(a.C()) { - t.Fatal("Alarm fired twice") - } - if ntimers := clk.ActiveTimers(); ntimers != 0 { - t.Fatal("clock has", ntimers, "active timers, want", 0) - } - - a.Schedule(clk.Now() + 5) - if recv(a.C()) { - t.Fatal("Alarm fired before scheduled deadline when scheduling the second event") - } - - clk.Run(5) - if !recv(a.C()) { - t.Fatal("Alarm did not fire when scheduling the second event") - } - if recv(a.C()) { - t.Fatal("Alarm fired twice when scheduling the second event") - } -} - -// This test checks that scheduling an Alarm to an earlier time than the -// one already scheduled works properly. -func TestAlarmScheduleEarlier(t *testing.T) { - clk := new(Simulated) - clk.Run(20) - a := NewAlarm(clk) - - a.Schedule(clk.Now() + 50) - clk.Run(5) - a.Schedule(clk.Now() + 1) - clk.Run(3) - if !recv(a.C()) { - t.Fatal("Alarm did not fire") - } -} - -// This test checks that scheduling an Alarm to a later time than the -// one already scheduled works properly. -func TestAlarmScheduleLater(t *testing.T) { - clk := new(Simulated) - clk.Run(20) - a := NewAlarm(clk) - - a.Schedule(clk.Now() + 50) - clk.Run(5) - a.Schedule(clk.Now() + 100) - clk.Run(50) - if !recv(a.C()) { - t.Fatal("Alarm did not fire") - } -} - -// This test checks that scheduling an Alarm in the past makes it fire immediately. -func TestAlarmNegative(t *testing.T) { - clk := new(Simulated) - clk.Run(50) - a := NewAlarm(clk) - - a.Schedule(-1) - clk.Run(1) // needed to process timers - if !recv(a.C()) { - t.Fatal("Alarm did not fire for negative time") - } -} - -func recv(ch <-chan struct{}) bool { - select { - case <-ch: - return true - default: - return false - } -} diff --git a/builder/common/mclock/mclock.go b/builder/common/mclock/mclock.go deleted file mode 100644 index c05738cf2..000000000 --- a/builder/common/mclock/mclock.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2016 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 mclock is a wrapper for a monotonic clock source -package mclock - -import ( - "time" - - _ "unsafe" // for go:linkname -) - -//go:noescape -//go:linkname nanotime runtime.nanotime -func nanotime() int64 - -// AbsTime represents absolute monotonic time. -type AbsTime int64 - -// Now returns the current absolute monotonic time. -func Now() AbsTime { - return AbsTime(nanotime()) -} - -// Add returns t + d as absolute time. -func (t AbsTime) Add(d time.Duration) AbsTime { - return t + AbsTime(d) -} - -// Sub returns t - t2 as a duration. -func (t AbsTime) Sub(t2 AbsTime) time.Duration { - return time.Duration(t - t2) -} - -// The Clock interface makes it possible to replace the monotonic system clock with -// a simulated clock. -type Clock interface { - Now() AbsTime - Sleep(time.Duration) - NewTimer(time.Duration) ChanTimer - After(time.Duration) <-chan AbsTime - AfterFunc(d time.Duration, f func()) Timer -} - -// Timer is a cancellable event created by AfterFunc. -type Timer interface { - // Stop cancels the timer. It returns false if the timer has already - // expired or been stopped. - Stop() bool -} - -// ChanTimer is a cancellable event created by NewTimer. -type ChanTimer interface { - Timer - - // The channel returned by C receives a value when the timer expires. - C() <-chan AbsTime - // Reset reschedules the timer with a new timeout. - // It should be invoked only on stopped or expired timers with drained channels. - Reset(time.Duration) -} - -// System implements Clock using the system clock. -type System struct{} - -// Now returns the current monotonic time. -func (c System) Now() AbsTime { - return Now() -} - -// Sleep blocks for the given duration. -func (c System) Sleep(d time.Duration) { - time.Sleep(d) -} - -// NewTimer creates a timer which can be rescheduled. -func (c System) NewTimer(d time.Duration) ChanTimer { - ch := make(chan AbsTime, 1) - t := time.AfterFunc(d, func() { - // This send is non-blocking because that's how time.Timer - // behaves. It doesn't matter in the happy case, but does - // when Reset is misused. - select { - case ch <- c.Now(): - default: - } - }) - return &systemTimer{t, ch} -} - -// After returns a channel which receives the current time after d has elapsed. -func (c System) After(d time.Duration) <-chan AbsTime { - ch := make(chan AbsTime, 1) - time.AfterFunc(d, func() { ch <- c.Now() }) - return ch -} - -// AfterFunc runs f on a new goroutine after the duration has elapsed. -func (c System) AfterFunc(d time.Duration, f func()) Timer { - return time.AfterFunc(d, f) -} - -type systemTimer struct { - *time.Timer - ch <-chan AbsTime -} - -func (st *systemTimer) Reset(d time.Duration) { - st.Timer.Reset(d) -} - -func (st *systemTimer) C() <-chan AbsTime { - return st.ch -} diff --git a/builder/common/mclock/mclock.s b/builder/common/mclock/mclock.s deleted file mode 100644 index 99a7a878f..000000000 --- a/builder/common/mclock/mclock.s +++ /dev/null @@ -1 +0,0 @@ -// This file exists in order to be able to use go:linkname. diff --git a/builder/common/mclock/simclock.go b/builder/common/mclock/simclock.go deleted file mode 100644 index f5ad3f8bc..000000000 --- a/builder/common/mclock/simclock.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2018 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 mclock - -import ( - "container/heap" - "sync" - "time" -) - -// Simulated implements a virtual Clock for reproducible time-sensitive tests. It -// simulates a scheduler on a virtual timescale where actual processing takes zero time. -// -// The virtual clock doesn't advance on its own, call Run to advance it and execute timers. -// Since there is no way to influence the Go scheduler, testing timeout behaviour involving -// goroutines needs special care. A good way to test such timeouts is as follows: First -// perform the action that is supposed to time out. Ensure that the timer you want to test -// is created. Then run the clock until after the timeout. Finally observe the effect of -// the timeout using a channel or semaphore. -type Simulated struct { - now AbsTime - scheduled simTimerHeap - mu sync.RWMutex - cond *sync.Cond -} - -// simTimer implements ChanTimer on the virtual clock. -type simTimer struct { - at AbsTime - index int // position in s.scheduled - s *Simulated - do func() - ch <-chan AbsTime -} - -func (s *Simulated) init() { - if s.cond == nil { - s.cond = sync.NewCond(&s.mu) - } -} - -// Run moves the clock by the given duration, executing all timers before that duration. -func (s *Simulated) Run(d time.Duration) { - s.mu.Lock() - s.init() - - end := s.now.Add(d) - var do []func() - for len(s.scheduled) > 0 && s.scheduled[0].at <= end { - ev := heap.Pop(&s.scheduled).(*simTimer) - do = append(do, ev.do) - } - s.now = end - s.mu.Unlock() - - for _, fn := range do { - fn() - } -} - -// ActiveTimers returns the number of timers that haven't fired. -func (s *Simulated) ActiveTimers() int { - s.mu.RLock() - defer s.mu.RUnlock() - - return len(s.scheduled) -} - -// WaitForTimers waits until the clock has at least n scheduled timers. -func (s *Simulated) WaitForTimers(n int) { - s.mu.Lock() - defer s.mu.Unlock() - s.init() - - for len(s.scheduled) < n { - s.cond.Wait() - } -} - -// Now returns the current virtual time. -func (s *Simulated) Now() AbsTime { - s.mu.RLock() - defer s.mu.RUnlock() - - return s.now -} - -// Sleep blocks until the clock has advanced by d. -func (s *Simulated) Sleep(d time.Duration) { - <-s.After(d) -} - -// NewTimer creates a timer which fires when the clock has advanced by d. -func (s *Simulated) NewTimer(d time.Duration) ChanTimer { - s.mu.Lock() - defer s.mu.Unlock() - - ch := make(chan AbsTime, 1) - var timer *simTimer - timer = s.schedule(d, func() { ch <- timer.at }) - timer.ch = ch - return timer -} - -// After returns a channel which receives the current time after the clock -// has advanced by d. -func (s *Simulated) After(d time.Duration) <-chan AbsTime { - return s.NewTimer(d).C() -} - -// AfterFunc runs fn after the clock has advanced by d. Unlike with the system -// clock, fn runs on the goroutine that calls Run. -func (s *Simulated) AfterFunc(d time.Duration, fn func()) Timer { - s.mu.Lock() - defer s.mu.Unlock() - - return s.schedule(d, fn) -} - -func (s *Simulated) schedule(d time.Duration, fn func()) *simTimer { - s.init() - - at := s.now.Add(d) - ev := &simTimer{do: fn, at: at, s: s} - heap.Push(&s.scheduled, ev) - s.cond.Broadcast() - return ev -} - -func (ev *simTimer) Stop() bool { - ev.s.mu.Lock() - defer ev.s.mu.Unlock() - - if ev.index < 0 { - return false - } - heap.Remove(&ev.s.scheduled, ev.index) - ev.s.cond.Broadcast() - ev.index = -1 - return true -} - -func (ev *simTimer) Reset(d time.Duration) { - if ev.ch == nil { - panic("mclock: Reset() on timer created by AfterFunc") - } - - ev.s.mu.Lock() - defer ev.s.mu.Unlock() - ev.at = ev.s.now.Add(d) - if ev.index < 0 { - heap.Push(&ev.s.scheduled, ev) // already expired - } else { - heap.Fix(&ev.s.scheduled, ev.index) // hasn't fired yet, reschedule - } - ev.s.cond.Broadcast() -} - -func (ev *simTimer) C() <-chan AbsTime { - if ev.ch == nil { - panic("mclock: C() on timer created by AfterFunc") - } - return ev.ch -} - -type simTimerHeap []*simTimer - -func (h *simTimerHeap) Len() int { - return len(*h) -} - -func (h *simTimerHeap) Less(i, j int) bool { - return (*h)[i].at < (*h)[j].at -} - -func (h *simTimerHeap) Swap(i, j int) { - (*h)[i], (*h)[j] = (*h)[j], (*h)[i] - (*h)[i].index = i - (*h)[j].index = j -} - -func (h *simTimerHeap) Push(x interface{}) { - t := x.(*simTimer) - t.index = len(*h) - *h = append(*h, t) -} - -func (h *simTimerHeap) Pop() interface{} { - end := len(*h) - 1 - t := (*h)[end] - t.index = -1 - (*h)[end] = nil - *h = (*h)[:end] - return t -} diff --git a/builder/common/mclock/simclock_test.go b/builder/common/mclock/simclock_test.go deleted file mode 100644 index 582bc31dc..000000000 --- a/builder/common/mclock/simclock_test.go +++ /dev/null @@ -1,162 +0,0 @@ -// 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 mclock - -import ( - "testing" - "time" -) - -var _ Clock = System{} -var _ Clock = new(Simulated) - -func TestSimulatedAfter(t *testing.T) { - var ( - timeout = 30 * time.Minute - offset = 99 * time.Hour - adv = 11 * time.Minute - c Simulated - ) - c.Run(offset) - - end := c.Now().Add(timeout) - ch := c.After(timeout) - for c.Now() < end.Add(-adv) { - c.Run(adv) - select { - case <-ch: - t.Fatal("Timer fired early") - default: - } - } - - c.Run(adv) - select { - case stamp := <-ch: - want := AbsTime(0).Add(offset).Add(timeout) - if stamp != want { - t.Errorf("Wrong time sent on timer channel: got %v, want %v", stamp, want) - } - default: - t.Fatal("Timer didn't fire") - } -} - -func TestSimulatedAfterFunc(t *testing.T) { - var c Simulated - - called1 := false - timer1 := c.AfterFunc(100*time.Millisecond, func() { called1 = true }) - if c.ActiveTimers() != 1 { - t.Fatalf("%d active timers, want one", c.ActiveTimers()) - } - if fired := timer1.Stop(); !fired { - t.Fatal("Stop returned false even though timer didn't fire") - } - if c.ActiveTimers() != 0 { - t.Fatalf("%d active timers, want zero", c.ActiveTimers()) - } - if called1 { - t.Fatal("timer 1 called") - } - if fired := timer1.Stop(); fired { - t.Fatal("Stop returned true after timer was already stopped") - } - - called2 := false - timer2 := c.AfterFunc(100*time.Millisecond, func() { called2 = true }) - c.Run(50 * time.Millisecond) - if called2 { - t.Fatal("timer 2 called") - } - c.Run(51 * time.Millisecond) - if !called2 { - t.Fatal("timer 2 not called") - } - if fired := timer2.Stop(); fired { - t.Fatal("Stop returned true after timer has fired") - } -} - -func TestSimulatedSleep(t *testing.T) { - var ( - c Simulated - timeout = 1 * time.Hour - done = make(chan AbsTime, 1) - ) - go func() { - c.Sleep(timeout) - done <- c.Now() - }() - - c.WaitForTimers(1) - c.Run(2 * timeout) - select { - case stamp := <-done: - want := AbsTime(2 * timeout) - if stamp != want { - t.Errorf("Wrong time after sleep: got %v, want %v", stamp, want) - } - case <-time.After(5 * time.Second): - t.Fatal("Sleep didn't return in time") - } -} - -func TestSimulatedTimerReset(t *testing.T) { - var ( - c Simulated - timeout = 1 * time.Hour - ) - timer := c.NewTimer(timeout) - c.Run(2 * timeout) - select { - case ftime := <-timer.C(): - if ftime != AbsTime(timeout) { - t.Fatalf("wrong time %v sent on timer channel, want %v", ftime, AbsTime(timeout)) - } - default: - t.Fatal("timer didn't fire") - } - - timer.Reset(timeout) - c.Run(2 * timeout) - select { - case ftime := <-timer.C(): - if ftime != AbsTime(3*timeout) { - t.Fatalf("wrong time %v sent on timer channel, want %v", ftime, AbsTime(3*timeout)) - } - default: - t.Fatal("timer didn't fire again") - } -} - -func TestSimulatedTimerStop(t *testing.T) { - var ( - c Simulated - timeout = 1 * time.Hour - ) - timer := c.NewTimer(timeout) - c.Run(2 * timeout) - if timer.Stop() { - t.Errorf("Stop returned true for fired timer") - } - select { - case <-timer.C(): - default: - t.Fatal("timer didn't fire") - } -} diff --git a/builder/common/path.go b/builder/common/path.go deleted file mode 100644 index c1e382fd2..000000000 --- a/builder/common/path.go +++ /dev/null @@ -1,40 +0,0 @@ -// 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 common - -import ( - "os" - "path/filepath" -) - -// FileExist checks if a file exists at filePath. -func FileExist(filePath string) bool { - _, err := os.Stat(filePath) - if err != nil && os.IsNotExist(err) { - return false - } - - return true -} - -// AbsolutePath returns datadir + filename, or filename if it is absolute. -func AbsolutePath(datadir string, filename string) string { - if filepath.IsAbs(filename) { - return filename - } - return filepath.Join(datadir, filename) -} diff --git a/builder/common/prque/lazyqueue.go b/builder/common/prque/lazyqueue.go deleted file mode 100644 index 59bda72fa..000000000 --- a/builder/common/prque/lazyqueue.go +++ /dev/null @@ -1,195 +0,0 @@ -// 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 prque - -import ( - "container/heap" - "time" - - "github.com/ethereum/go-ethereum/common/mclock" - "golang.org/x/exp/constraints" -) - -// LazyQueue is a priority queue data structure where priorities can change over -// time and are only evaluated on demand. -// Two callbacks are required: -// - priority evaluates the actual priority of an item -// - maxPriority gives an upper estimate for the priority in any moment between -// now and the given absolute time -// -// If the upper estimate is exceeded then Update should be called for that item. -// A global Refresh function should also be called periodically. -type LazyQueue[P constraints.Ordered, V any] struct { - clock mclock.Clock - // Items are stored in one of two internal queues ordered by estimated max - // priority until the next and the next-after-next refresh. Update and Refresh - // always places items in queue[1]. - queue [2]*sstack[P, V] - popQueue *sstack[P, V] - period time.Duration - maxUntil mclock.AbsTime - indexOffset int - setIndex SetIndexCallback[V] - priority PriorityCallback[P, V] - maxPriority MaxPriorityCallback[P, V] - lastRefresh1, lastRefresh2 mclock.AbsTime -} - -type ( - PriorityCallback[P constraints.Ordered, V any] func(data V) P // actual priority callback - MaxPriorityCallback[P constraints.Ordered, V any] func(data V, until mclock.AbsTime) P // estimated maximum priority callback -) - -// NewLazyQueue creates a new lazy queue -func NewLazyQueue[P constraints.Ordered, V any](setIndex SetIndexCallback[V], priority PriorityCallback[P, V], maxPriority MaxPriorityCallback[P, V], clock mclock.Clock, refreshPeriod time.Duration) *LazyQueue[P, V] { - q := &LazyQueue[P, V]{ - popQueue: newSstack[P, V](nil), - setIndex: setIndex, - priority: priority, - maxPriority: maxPriority, - clock: clock, - period: refreshPeriod, - lastRefresh1: clock.Now(), - lastRefresh2: clock.Now(), - } - q.Reset() - q.refresh(clock.Now()) - return q -} - -// Reset clears the contents of the queue -func (q *LazyQueue[P, V]) Reset() { - q.queue[0] = newSstack[P, V](q.setIndex0) - q.queue[1] = newSstack[P, V](q.setIndex1) -} - -// Refresh performs queue re-evaluation if necessary -func (q *LazyQueue[P, V]) Refresh() { - now := q.clock.Now() - for time.Duration(now-q.lastRefresh2) >= q.period*2 { - q.refresh(now) - q.lastRefresh2 = q.lastRefresh1 - q.lastRefresh1 = now - } -} - -// refresh re-evaluates items in the older queue and swaps the two queues -func (q *LazyQueue[P, V]) refresh(now mclock.AbsTime) { - q.maxUntil = now.Add(q.period) - for q.queue[0].Len() != 0 { - q.Push(heap.Pop(q.queue[0]).(*item[P, V]).value) - } - q.queue[0], q.queue[1] = q.queue[1], q.queue[0] - q.indexOffset = 1 - q.indexOffset - q.maxUntil = q.maxUntil.Add(q.period) -} - -// Push adds an item to the queue -func (q *LazyQueue[P, V]) Push(data V) { - heap.Push(q.queue[1], &item[P, V]{data, q.maxPriority(data, q.maxUntil)}) -} - -// Update updates the upper priority estimate for the item with the given queue index -func (q *LazyQueue[P, V]) Update(index int) { - q.Push(q.Remove(index)) -} - -// Pop removes and returns the item with the greatest actual priority -func (q *LazyQueue[P, V]) Pop() (V, P) { - var ( - resData V - resPri P - ) - q.MultiPop(func(data V, priority P) bool { - resData = data - resPri = priority - return false - }) - return resData, resPri -} - -// peekIndex returns the index of the internal queue where the item with the -// highest estimated priority is or -1 if both are empty -func (q *LazyQueue[P, V]) peekIndex() int { - if q.queue[0].Len() != 0 { - if q.queue[1].Len() != 0 && q.queue[1].blocks[0][0].priority > q.queue[0].blocks[0][0].priority { - return 1 - } - return 0 - } - if q.queue[1].Len() != 0 { - return 1 - } - return -1 -} - -// MultiPop pops multiple items from the queue and is more efficient than calling -// Pop multiple times. Popped items are passed to the callback. MultiPop returns -// when the callback returns false or there are no more items to pop. -func (q *LazyQueue[P, V]) MultiPop(callback func(data V, priority P) bool) { - nextIndex := q.peekIndex() - for nextIndex != -1 { - data := heap.Pop(q.queue[nextIndex]).(*item[P, V]).value - heap.Push(q.popQueue, &item[P, V]{data, q.priority(data)}) - nextIndex = q.peekIndex() - for q.popQueue.Len() != 0 && (nextIndex == -1 || q.queue[nextIndex].blocks[0][0].priority < q.popQueue.blocks[0][0].priority) { - i := heap.Pop(q.popQueue).(*item[P, V]) - if !callback(i.value, i.priority) { - for q.popQueue.Len() != 0 { - q.Push(heap.Pop(q.popQueue).(*item[P, V]).value) - } - return - } - nextIndex = q.peekIndex() // re-check because callback is allowed to push items back - } - } -} - -// PopItem pops the item from the queue only, dropping the associated priority value. -func (q *LazyQueue[P, V]) PopItem() V { - i, _ := q.Pop() - return i -} - -// Remove removes the item with the given index. -func (q *LazyQueue[P, V]) Remove(index int) V { - return heap.Remove(q.queue[index&1^q.indexOffset], index>>1).(*item[P, V]).value -} - -// Empty checks whether the priority queue is empty. -func (q *LazyQueue[P, V]) Empty() bool { - return q.queue[0].Len() == 0 && q.queue[1].Len() == 0 -} - -// Size returns the number of items in the priority queue. -func (q *LazyQueue[P, V]) Size() int { - return q.queue[0].Len() + q.queue[1].Len() -} - -// setIndex0 translates internal queue item index to the virtual index space of LazyQueue -func (q *LazyQueue[P, V]) setIndex0(data V, index int) { - if index == -1 { - q.setIndex(data, -1) - } else { - q.setIndex(data, index+index) - } -} - -// setIndex1 translates internal queue item index to the virtual index space of LazyQueue -func (q *LazyQueue[P, V]) setIndex1(data V, index int) { - q.setIndex(data, index+index+1) -} diff --git a/builder/common/prque/lazyqueue_test.go b/builder/common/prque/lazyqueue_test.go deleted file mode 100644 index ffb7e5e9e..000000000 --- a/builder/common/prque/lazyqueue_test.go +++ /dev/null @@ -1,123 +0,0 @@ -// 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 prque - -import ( - "math/rand" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common/mclock" -) - -const ( - testItems = 1000 - testPriorityStep = 100 - testSteps = 1000000 - testStepPeriod = time.Millisecond - testQueueRefresh = time.Second - testAvgRate = float64(testPriorityStep) / float64(testItems) / float64(testStepPeriod) -) - -type lazyItem struct { - p, maxp int64 - last mclock.AbsTime - index int -} - -func testPriority(a interface{}) int64 { - return a.(*lazyItem).p -} - -func testMaxPriority(a interface{}, until mclock.AbsTime) int64 { - i := a.(*lazyItem) - dt := until - i.last - i.maxp = i.p + int64(float64(dt)*testAvgRate) - return i.maxp -} - -func testSetIndex(a interface{}, i int) { - a.(*lazyItem).index = i -} - -func TestLazyQueue(t *testing.T) { - clock := &mclock.Simulated{} - q := NewLazyQueue(testSetIndex, testPriority, testMaxPriority, clock, testQueueRefresh) - - var ( - items [testItems]lazyItem - maxPri int64 - ) - - for i := range items[:] { - items[i].p = rand.Int63n(testPriorityStep * 10) - if items[i].p > maxPri { - maxPri = items[i].p - } - items[i].index = -1 - q.Push(&items[i]) - } - - var ( - lock sync.Mutex - wg sync.WaitGroup - stopCh = make(chan chan struct{}) - ) - defer wg.Wait() - wg.Add(1) - go func() { - defer wg.Done() - for { - select { - case <-clock.After(testQueueRefresh): - lock.Lock() - q.Refresh() - lock.Unlock() - case <-stopCh: - return - } - } - }() - - for c := 0; c < testSteps; c++ { - i := rand.Intn(testItems) - lock.Lock() - items[i].p += rand.Int63n(testPriorityStep*2-1) + 1 - if items[i].p > maxPri { - maxPri = items[i].p - } - items[i].last = clock.Now() - if items[i].p > items[i].maxp { - q.Update(items[i].index) - } - if rand.Intn(100) == 0 { - p := q.PopItem().(*lazyItem) - if p.p != maxPri { - lock.Unlock() - close(stopCh) - t.Fatalf("incorrect item (best known priority %d, popped %d)", maxPri, p.p) - } - q.Push(p) - } - lock.Unlock() - clock.Run(testStepPeriod) - clock.WaitForTimers(1) - } - - close(stopCh) -} diff --git a/builder/common/prque/prque.go b/builder/common/prque/prque.go deleted file mode 100755 index 0e8c9f897..000000000 --- a/builder/common/prque/prque.go +++ /dev/null @@ -1,77 +0,0 @@ -// CookieJar - A contestant's algorithm toolbox -// Copyright (c) 2013 Peter Szilagyi. All rights reserved. -// -// CookieJar is dual licensed: use of this source code is governed by a BSD -// license that can be found in the LICENSE file. Alternatively, the CookieJar -// toolbox may be used in accordance with the terms and conditions contained -// in a signed written agreement between you and the author(s). - -// This is a duplicated and slightly modified version of "gopkg.in/karalabe/cookiejar.v2/collections/prque". - -// Package prque implements a priority queue data structure supporting arbitrary -// value types and int64 priorities. -// -// If you would like to use a min-priority queue, simply negate the priorities. -// -// Internally the queue is based on the standard heap package working on a -// sortable version of the block based stack. -package prque - -import ( - "container/heap" - - "golang.org/x/exp/constraints" -) - -// Priority queue data structure. -type Prque[P constraints.Ordered, V any] struct { - cont *sstack[P, V] -} - -// New creates a new priority queue. -func New[P constraints.Ordered, V any](setIndex SetIndexCallback[V]) *Prque[P, V] { - return &Prque[P, V]{newSstack[P, V](setIndex)} -} - -// Pushes a value with a given priority into the queue, expanding if necessary. -func (p *Prque[P, V]) Push(data V, priority P) { - heap.Push(p.cont, &item[P, V]{data, priority}) -} - -// Peek returns the value with the greatest priority but does not pop it off. -func (p *Prque[P, V]) Peek() (V, P) { - item := p.cont.blocks[0][0] - return item.value, item.priority -} - -// Pops the value with the greatest priority off the stack and returns it. -// Currently no shrinking is done. -func (p *Prque[P, V]) Pop() (V, P) { - item := heap.Pop(p.cont).(*item[P, V]) - return item.value, item.priority -} - -// Pops only the item from the queue, dropping the associated priority value. -func (p *Prque[P, V]) PopItem() V { - return heap.Pop(p.cont).(*item[P, V]).value -} - -// Remove removes the element with the given index. -func (p *Prque[P, V]) Remove(i int) V { - return heap.Remove(p.cont, i).(*item[P, V]).value -} - -// Checks whether the priority queue is empty. -func (p *Prque[P, V]) Empty() bool { - return p.cont.Len() == 0 -} - -// Returns the number of element in the priority queue. -func (p *Prque[P, V]) Size() int { - return p.cont.Len() -} - -// Clears the contents of the priority queue. -func (p *Prque[P, V]) Reset() { - *p = *New[P, V](p.cont.setIndex) -} diff --git a/builder/common/prque/prque_test.go b/builder/common/prque/prque_test.go deleted file mode 100644 index c4910f205..000000000 --- a/builder/common/prque/prque_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// CookieJar - A contestant's algorithm toolbox -// Copyright (c) 2013 Peter Szilagyi. All rights reserved. -// -// CookieJar is dual licensed: use of this source code is governed by a BSD -// license that can be found in the LICENSE file. Alternatively, the CookieJar -// toolbox may be used in accordance with the terms and conditions contained -// in a signed written agreement between you and the author(s). - -package prque - -import ( - "math/rand" - "testing" -) - -func TestPrque(t *testing.T) { - // Generate a batch of random data and a specific priority order - size := 16 * blockSize - prio := rand.Perm(size) - data := make([]int, size) - for i := 0; i < size; i++ { - data[i] = rand.Int() - } - queue := New[int, int](nil) - - for rep := 0; rep < 2; rep++ { - // Fill a priority queue with the above data - for i := 0; i < size; i++ { - queue.Push(data[i], prio[i]) - if queue.Size() != i+1 { - t.Errorf("queue size mismatch: have %v, want %v.", queue.Size(), i+1) - } - } - // Create a map the values to the priorities for easier verification - dict := make(map[int]int) - for i := 0; i < size; i++ { - dict[prio[i]] = data[i] - } - - // Pop out the elements in priority order and verify them - prevPrio := size + 1 - for !queue.Empty() { - val, prio := queue.Pop() - if prio > prevPrio { - t.Errorf("invalid priority order: %v after %v.", prio, prevPrio) - } - prevPrio = prio - if val != dict[prio] { - t.Errorf("push/pop mismatch: have %v, want %v.", val, dict[prio]) - } - delete(dict, prio) - } - } -} - -func TestReset(t *testing.T) { - // Generate a batch of random data and a specific priority order - size := 16 * blockSize - prio := rand.Perm(size) - data := make([]int, size) - for i := 0; i < size; i++ { - data[i] = rand.Int() - } - queue := New[int, int](nil) - - for rep := 0; rep < 2; rep++ { - // Fill a priority queue with the above data - for i := 0; i < size; i++ { - queue.Push(data[i], prio[i]) - if queue.Size() != i+1 { - t.Errorf("queue size mismatch: have %v, want %v.", queue.Size(), i+1) - } - } - // Create a map the values to the priorities for easier verification - dict := make(map[int]int) - for i := 0; i < size; i++ { - dict[prio[i]] = data[i] - } - // Pop out half the elements in priority order and verify them - prevPrio := size + 1 - for i := 0; i < size/2; i++ { - val, prio := queue.Pop() - if prio > prevPrio { - t.Errorf("invalid priority order: %v after %v.", prio, prevPrio) - } - prevPrio = prio - if val != dict[prio] { - t.Errorf("push/pop mismatch: have %v, want %v.", val, dict[prio]) - } - delete(dict, prio) - } - // Reset and ensure it's empty - queue.Reset() - if !queue.Empty() { - t.Errorf("priority queue not empty after reset: %v", queue) - } - } -} - -func BenchmarkPush(b *testing.B) { - // Create some initial data - data := make([]int, b.N) - prio := make([]int64, b.N) - for i := 0; i < len(data); i++ { - data[i] = rand.Int() - prio[i] = rand.Int63() - } - // Execute the benchmark - b.ResetTimer() - queue := New[int64, int](nil) - for i := 0; i < len(data); i++ { - queue.Push(data[i], prio[i]) - } -} - -func BenchmarkPop(b *testing.B) { - // Create some initial data - data := make([]int, b.N) - prio := make([]int64, b.N) - for i := 0; i < len(data); i++ { - data[i] = rand.Int() - prio[i] = rand.Int63() - } - queue := New[int64, int](nil) - for i := 0; i < len(data); i++ { - queue.Push(data[i], prio[i]) - } - // Execute the benchmark - b.ResetTimer() - for !queue.Empty() { - queue.Pop() - } -} diff --git a/builder/common/prque/sstack.go b/builder/common/prque/sstack.go deleted file mode 100755 index 5dcd1d9dd..000000000 --- a/builder/common/prque/sstack.go +++ /dev/null @@ -1,113 +0,0 @@ -// CookieJar - A contestant's algorithm toolbox -// Copyright (c) 2013 Peter Szilagyi. All rights reserved. -// -// CookieJar is dual licensed: use of this source code is governed by a BSD -// license that can be found in the LICENSE file. Alternatively, the CookieJar -// toolbox may be used in accordance with the terms and conditions contained -// in a signed written agreement between you and the author(s). - -// This is a duplicated and slightly modified version of "gopkg.in/karalabe/cookiejar.v2/collections/prque". - -package prque - -import "golang.org/x/exp/constraints" - -// The size of a block of data -const blockSize = 4096 - -// A prioritized item in the sorted stack. -type item[P constraints.Ordered, V any] struct { - value V - priority P -} - -// SetIndexCallback is called when the element is moved to a new index. -// Providing SetIndexCallback is optional, it is needed only if the application needs -// to delete elements other than the top one. -type SetIndexCallback[V any] func(data V, index int) - -// Internal sortable stack data structure. Implements the Push and Pop ops for -// the stack (heap) functionality and the Len, Less and Swap methods for the -// sortability requirements of the heaps. -type sstack[P constraints.Ordered, V any] struct { - setIndex SetIndexCallback[V] - size int - capacity int - offset int - - blocks [][]*item[P, V] - active []*item[P, V] -} - -// Creates a new, empty stack. -func newSstack[P constraints.Ordered, V any](setIndex SetIndexCallback[V]) *sstack[P, V] { - result := new(sstack[P, V]) - result.setIndex = setIndex - result.active = make([]*item[P, V], blockSize) - result.blocks = [][]*item[P, V]{result.active} - result.capacity = blockSize - return result -} - -// Pushes a value onto the stack, expanding it if necessary. Required by -// heap.Interface. -func (s *sstack[P, V]) Push(data any) { - if s.size == s.capacity { - s.active = make([]*item[P, V], blockSize) - s.blocks = append(s.blocks, s.active) - s.capacity += blockSize - s.offset = 0 - } else if s.offset == blockSize { - s.active = s.blocks[s.size/blockSize] - s.offset = 0 - } - if s.setIndex != nil { - s.setIndex(data.(*item[P, V]).value, s.size) - } - s.active[s.offset] = data.(*item[P, V]) - s.offset++ - s.size++ -} - -// Pops a value off the stack and returns it. Currently no shrinking is done. -// Required by heap.Interface. -func (s *sstack[P, V]) Pop() (res any) { - s.size-- - s.offset-- - if s.offset < 0 { - s.offset = blockSize - 1 - s.active = s.blocks[s.size/blockSize] - } - res, s.active[s.offset] = s.active[s.offset], nil - if s.setIndex != nil { - s.setIndex(res.(*item[P, V]).value, -1) - } - return -} - -// Returns the length of the stack. Required by sort.Interface. -func (s *sstack[P, V]) Len() int { - return s.size -} - -// Compares the priority of two elements of the stack (higher is first). -// Required by sort.Interface. -func (s *sstack[P, V]) Less(i, j int) bool { - return s.blocks[i/blockSize][i%blockSize].priority > s.blocks[j/blockSize][j%blockSize].priority -} - -// Swaps two elements in the stack. Required by sort.Interface. -func (s *sstack[P, V]) Swap(i, j int) { - ib, io, jb, jo := i/blockSize, i%blockSize, j/blockSize, j%blockSize - a, b := s.blocks[jb][jo], s.blocks[ib][io] - if s.setIndex != nil { - s.setIndex(a.value, i) - s.setIndex(b.value, j) - } - s.blocks[ib][io], s.blocks[jb][jo] = a, b -} - -// Resets the stack, effectively clearing its contents. -func (s *sstack[P, V]) Reset() { - *s = *newSstack[P, V](s.setIndex) -} diff --git a/builder/common/prque/sstack_test.go b/builder/common/prque/sstack_test.go deleted file mode 100644 index edc99955e..000000000 --- a/builder/common/prque/sstack_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// CookieJar - A contestant's algorithm toolbox -// Copyright (c) 2013 Peter Szilagyi. All rights reserved. -// -// CookieJar is dual licensed: use of this source code is governed by a BSD -// license that can be found in the LICENSE file. Alternatively, the CookieJar -// toolbox may be used in accordance with the terms and conditions contained -// in a signed written agreement between you and the author(s). - -package prque - -import ( - "math/rand" - "sort" - "testing" -) - -func TestSstack(t *testing.T) { - // Create some initial data - size := 16 * blockSize - data := make([]*item[int64, int], size) - for i := 0; i < size; i++ { - data[i] = &item[int64, int]{rand.Int(), rand.Int63()} - } - stack := newSstack[int64, int](nil) - for rep := 0; rep < 2; rep++ { - // Push all the data into the stack, pop out every second - secs := []*item[int64, int]{} - for i := 0; i < size; i++ { - stack.Push(data[i]) - if i%2 == 0 { - secs = append(secs, stack.Pop().(*item[int64, int])) - } - } - rest := []*item[int64, int]{} - for stack.Len() > 0 { - rest = append(rest, stack.Pop().(*item[int64, int])) - } - // Make sure the contents of the resulting slices are ok - for i := 0; i < size; i++ { - if i%2 == 0 && data[i] != secs[i/2] { - t.Errorf("push/pop mismatch: have %v, want %v.", secs[i/2], data[i]) - } - if i%2 == 1 && data[i] != rest[len(rest)-i/2-1] { - t.Errorf("push/pop mismatch: have %v, want %v.", rest[len(rest)-i/2-1], data[i]) - } - } - } -} - -func TestSstackSort(t *testing.T) { - // Create some initial data - size := 16 * blockSize - data := make([]*item[int64, int], size) - for i := 0; i < size; i++ { - data[i] = &item[int64, int]{rand.Int(), int64(i)} - } - // Push all the data into the stack - stack := newSstack[int64, int](nil) - for _, val := range data { - stack.Push(val) - } - // Sort and pop the stack contents (should reverse the order) - sort.Sort(stack) - for _, val := range data { - out := stack.Pop() - if out != val { - t.Errorf("push/pop mismatch after sort: have %v, want %v.", out, val) - } - } -} - -func TestSstackReset(t *testing.T) { - // Create some initial data - size := 16 * blockSize - data := make([]*item[int64, int], size) - for i := 0; i < size; i++ { - data[i] = &item[int64, int]{rand.Int(), rand.Int63()} - } - stack := newSstack[int64, int](nil) - for rep := 0; rep < 2; rep++ { - // Push all the data into the stack, pop out every second - secs := []*item[int64, int]{} - for i := 0; i < size; i++ { - stack.Push(data[i]) - if i%2 == 0 { - secs = append(secs, stack.Pop().(*item[int64, int])) - } - } - // Reset and verify both pulled and stack contents - stack.Reset() - if stack.Len() != 0 { - t.Errorf("stack not empty after reset: %v", stack) - } - for i := 0; i < size; i++ { - if i%2 == 0 && data[i] != secs[i/2] { - t.Errorf("push/pop mismatch: have %v, want %v.", secs[i/2], data[i]) - } - } - } -} diff --git a/builder/common/size.go b/builder/common/size.go deleted file mode 100644 index 097b6304a..000000000 --- a/builder/common/size.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 common - -import ( - "fmt" -) - -// StorageSize is a wrapper around a float value that supports user friendly -// formatting. -type StorageSize float64 - -// String implements the stringer interface. -func (s StorageSize) String() string { - if s > 1099511627776 { - return fmt.Sprintf("%.2f TiB", s/1099511627776) - } else if s > 1073741824 { - return fmt.Sprintf("%.2f GiB", s/1073741824) - } else if s > 1048576 { - return fmt.Sprintf("%.2f MiB", s/1048576) - } else if s > 1024 { - return fmt.Sprintf("%.2f KiB", s/1024) - } else { - return fmt.Sprintf("%.2f B", s) - } -} - -// TerminalString implements log.TerminalStringer, formatting a string for console -// output during logging. -func (s StorageSize) TerminalString() string { - if s > 1099511627776 { - return fmt.Sprintf("%.2fTiB", s/1099511627776) - } else if s > 1073741824 { - return fmt.Sprintf("%.2fGiB", s/1073741824) - } else if s > 1048576 { - return fmt.Sprintf("%.2fMiB", s/1048576) - } else if s > 1024 { - return fmt.Sprintf("%.2fKiB", s/1024) - } else { - return fmt.Sprintf("%.2fB", s) - } -} diff --git a/builder/common/size_test.go b/builder/common/size_test.go deleted file mode 100644 index 28f053d39..000000000 --- a/builder/common/size_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 common - -import ( - "testing" -) - -func TestStorageSizeString(t *testing.T) { - tests := []struct { - size StorageSize - str string - }{ - {2839274474874, "2.58 TiB"}, - {2458492810, "2.29 GiB"}, - {2381273, "2.27 MiB"}, - {2192, "2.14 KiB"}, - {12, "12.00 B"}, - } - - for _, test := range tests { - if test.size.String() != test.str { - t.Errorf("%f: got %q, want %q", float64(test.size), test.size.String(), test.str) - } - } -} - -func TestStorageSizeTerminalString(t *testing.T) { - tests := []struct { - size StorageSize - str string - }{ - {2839274474874, "2.58TiB"}, - {2458492810, "2.29GiB"}, - {2381273, "2.27MiB"}, - {2192, "2.14KiB"}, - {12, "12.00B"}, - } - - for _, test := range tests { - if test.size.TerminalString() != test.str { - t.Errorf("%f: got %q, want %q", float64(test.size), test.size.TerminalString(), test.str) - } - } -} diff --git a/builder/common/test_utils.go b/builder/common/test_utils.go deleted file mode 100644 index 7a175412f..000000000 --- a/builder/common/test_utils.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 common - -import ( - "encoding/json" - "fmt" - "os" -) - -// LoadJSON reads the given file and unmarshals its content. -func LoadJSON(file string, val interface{}) error { - content, err := os.ReadFile(file) - if err != nil { - return err - } - if err := json.Unmarshal(content, val); err != nil { - if syntaxerr, ok := err.(*json.SyntaxError); ok { - line := findLine(content, syntaxerr.Offset) - return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) - } - return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) - } - return nil -} - -// findLine returns the line number for the given offset into data. -func findLine(data []byte, offset int64) (line int) { - line = 1 - for i, r := range string(data) { - if int64(i) >= offset { - return - } - if r == '\n' { - line++ - } - } - return -} diff --git a/builder/common/types.go b/builder/common/types.go deleted file mode 100644 index 21dff9777..000000000 --- a/builder/common/types.go +++ /dev/null @@ -1,636 +0,0 @@ -// 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 common - -import ( - "bytes" - "database/sql/driver" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "math/big" - "math/rand" - "reflect" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common/hexutil" - "golang.org/x/crypto/sha3" - - "github.com/attestantio/go-builder-client/api/bellatrix" - "github.com/attestantio/go-builder-client/api/capella" - "github.com/attestantio/go-builder-client/api/deneb" - builderSpec "github.com/attestantio/go-builder-client/spec" - consensusSpec "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/phase0" - fastSsz "github.com/ferranbt/fastssz" -) - -// Lengths of hashes and addresses in bytes. -const ( - // HashLength is the expected length of the hash - HashLength = 32 - // AddressLength is the expected length of the address - AddressLength = 20 -) - -var ( - hashT = reflect.TypeOf(Hash{}) - addressT = reflect.TypeOf(Address{}) - - // MaxAddress represents the maximum possible address value. - MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff") - - // MaxHash represents the maximum possible hash value. - MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") -) - -// Hash represents the 32 byte Keccak256 hash of arbitrary data. -type Hash [HashLength]byte - -// BytesToHash sets b to hash. -// If b is larger than len(h), b will be cropped from the left. -func BytesToHash(b []byte) Hash { - var h Hash - h.SetBytes(b) - return h -} - -// BigToHash sets byte representation of b to hash. -// If b is larger than len(h), b will be cropped from the left. -func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } - -// HexToHash sets byte representation of s to hash. -// If b is larger than len(h), b will be cropped from the left. -func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } - -// Cmp compares two hashes. -func (h Hash) Cmp(other Hash) int { - return bytes.Compare(h[:], other[:]) -} - -// Bytes gets the byte representation of the underlying hash. -func (h Hash) Bytes() []byte { return h[:] } - -// Big converts a hash to a big integer. -func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } - -// Hex converts a hash to a hex string. -func (h Hash) Hex() string { return hexutil.Encode(h[:]) } - -// TerminalString implements log.TerminalStringer, formatting a string for console -// output during logging. -func (h Hash) TerminalString() string { - return fmt.Sprintf("%x..%x", h[:3], h[29:]) -} - -// String implements the stringer interface and is used also by the logger when -// doing full logging into a file. -func (h Hash) String() string { - return h.Hex() -} - -// Format implements fmt.Formatter. -// Hash supports the %v, %s, %q, %x, %X and %d format verbs. -func (h Hash) Format(s fmt.State, c rune) { - hexb := make([]byte, 2+len(h)*2) - copy(hexb, "0x") - hex.Encode(hexb[2:], h[:]) - - switch c { - case 'x', 'X': - if !s.Flag('#') { - hexb = hexb[2:] - } - if c == 'X' { - hexb = bytes.ToUpper(hexb) - } - fallthrough - case 'v', 's': - s.Write(hexb) - case 'q': - q := []byte{'"'} - s.Write(q) - s.Write(hexb) - s.Write(q) - case 'd': - fmt.Fprint(s, ([len(h)]byte)(h)) - default: - fmt.Fprintf(s, "%%!%c(hash=%x)", c, h) - } -} - -// UnmarshalText parses a hash in hex syntax. -func (h *Hash) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("Hash", input, h[:]) -} - -// UnmarshalJSON parses a hash in hex syntax. -func (h *Hash) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) -} - -// MarshalText returns the hex representation of h. -func (h Hash) MarshalText() ([]byte, error) { - return hexutil.Bytes(h[:]).MarshalText() -} - -// SetBytes sets the hash to the value of b. -// If b is larger than len(h), b will be cropped from the left. -func (h *Hash) SetBytes(b []byte) { - if len(b) > len(h) { - b = b[len(b)-HashLength:] - } - - copy(h[HashLength-len(b):], b) -} - -// Generate implements testing/quick.Generator. -func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { - m := rand.Intn(len(h)) - for i := len(h) - 1; i > m; i-- { - h[i] = byte(rand.Uint32()) - } - return reflect.ValueOf(h) -} - -// Scan implements Scanner for database/sql. -func (h *Hash) Scan(src interface{}) error { - srcB, ok := src.([]byte) - if !ok { - return fmt.Errorf("can't scan %T into Hash", src) - } - if len(srcB) != HashLength { - return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength) - } - copy(h[:], srcB) - return nil -} - -// Value implements valuer for database/sql. -func (h Hash) Value() (driver.Value, error) { - return h[:], nil -} - -// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. -func (Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (h *Hash) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - err = h.UnmarshalText([]byte(input)) - default: - err = fmt.Errorf("unexpected type %T for Hash", input) - } - return err -} - -// UnprefixedHash allows marshaling a Hash without 0x prefix. -type UnprefixedHash Hash - -// UnmarshalText decodes the hash from hex. The 0x prefix is optional. -func (h *UnprefixedHash) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) -} - -// MarshalText encodes the hash as hex. -func (h UnprefixedHash) MarshalText() ([]byte, error) { - return []byte(hex.EncodeToString(h[:])), nil -} - -/////////// Address - -// Address represents the 20 byte address of an Ethereum account. -type Address [AddressLength]byte - -// BytesToAddress returns Address with value b. -// If b is larger than len(h), b will be cropped from the left. -func BytesToAddress(b []byte) Address { - var a Address - a.SetBytes(b) - return a -} - -// BigToAddress returns Address with byte values of b. -// If b is larger than len(h), b will be cropped from the left. -func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } - -// HexToAddress returns Address with byte values of s. -// If s is larger than len(h), s will be cropped from the left. -func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } - -// IsHexAddress verifies whether a string can represent a valid hex-encoded -// Ethereum address or not. -func IsHexAddress(s string) bool { - if has0xPrefix(s) { - s = s[2:] - } - return len(s) == 2*AddressLength && isHex(s) -} - -// Cmp compares two addresses. -func (a Address) Cmp(other Address) int { - return bytes.Compare(a[:], other[:]) -} - -// Bytes gets the string representation of the underlying address. -func (a Address) Bytes() []byte { return a[:] } - -// Big converts an address to a big integer. -func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } - -// Hex returns an EIP55-compliant hex string representation of the address. -func (a Address) Hex() string { - return string(a.checksumHex()) -} - -// String implements fmt.Stringer. -func (a Address) String() string { - return a.Hex() -} - -func (a *Address) checksumHex() []byte { - buf := a.hex() - - // compute checksum - sha := sha3.NewLegacyKeccak256() - sha.Write(buf[2:]) - hash := sha.Sum(nil) - for i := 2; i < len(buf); i++ { - hashByte := hash[(i-2)/2] - if i%2 == 0 { - hashByte = hashByte >> 4 - } else { - hashByte &= 0xf - } - if buf[i] > '9' && hashByte > 7 { - buf[i] -= 32 - } - } - return buf[:] -} - -func (a Address) hex() []byte { - var buf [len(a)*2 + 2]byte - copy(buf[:2], "0x") - hex.Encode(buf[2:], a[:]) - return buf[:] -} - -// Format implements fmt.Formatter. -// Address supports the %v, %s, %q, %x, %X and %d format verbs. -func (a Address) Format(s fmt.State, c rune) { - switch c { - case 'v', 's': - s.Write(a.checksumHex()) - case 'q': - q := []byte{'"'} - s.Write(q) - s.Write(a.checksumHex()) - s.Write(q) - case 'x', 'X': - // %x disables the checksum. - hex := a.hex() - if !s.Flag('#') { - hex = hex[2:] - } - if c == 'X' { - hex = bytes.ToUpper(hex) - } - s.Write(hex) - case 'd': - fmt.Fprint(s, ([len(a)]byte)(a)) - default: - fmt.Fprintf(s, "%%!%c(address=%x)", c, a) - } -} - -// SetBytes sets the address to the value of b. -// If b is larger than len(a), b will be cropped from the left. -func (a *Address) SetBytes(b []byte) { - if len(b) > len(a) { - b = b[len(b)-AddressLength:] - } - copy(a[AddressLength-len(b):], b) -} - -// MarshalText returns the hex representation of a. -func (a Address) MarshalText() ([]byte, error) { - return hexutil.Bytes(a[:]).MarshalText() -} - -// UnmarshalText parses a hash in hex syntax. -func (a *Address) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("Address", input, a[:]) -} - -// UnmarshalJSON parses a hash in hex syntax. -func (a *Address) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(addressT, input, a[:]) -} - -// Scan implements Scanner for database/sql. -func (a *Address) Scan(src interface{}) error { - srcB, ok := src.([]byte) - if !ok { - return fmt.Errorf("can't scan %T into Address", src) - } - if len(srcB) != AddressLength { - return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength) - } - copy(a[:], srcB) - return nil -} - -// Value implements valuer for database/sql. -func (a Address) Value() (driver.Value, error) { - return a[:], nil -} - -// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. -func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (a *Address) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - err = a.UnmarshalText([]byte(input)) - default: - err = fmt.Errorf("unexpected type %T for Address", input) - } - return err -} - -// UnprefixedAddress allows marshaling an Address without 0x prefix. -type UnprefixedAddress Address - -// UnmarshalText decodes the address from hex. The 0x prefix is optional. -func (a *UnprefixedAddress) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) -} - -// MarshalText encodes the address as hex. -func (a UnprefixedAddress) MarshalText() ([]byte, error) { - return []byte(hex.EncodeToString(a[:])), nil -} - -// MixedcaseAddress retains the original string, which may or may not be -// correctly checksummed -type MixedcaseAddress struct { - addr Address - original string -} - -// NewMixedcaseAddress constructor (mainly for testing) -func NewMixedcaseAddress(addr Address) MixedcaseAddress { - return MixedcaseAddress{addr: addr, original: addr.Hex()} -} - -// NewMixedcaseAddressFromString is mainly meant for unit-testing -func NewMixedcaseAddressFromString(hexaddr string) (*MixedcaseAddress, error) { - if !IsHexAddress(hexaddr) { - return nil, errors.New("invalid address") - } - a := FromHex(hexaddr) - return &MixedcaseAddress{addr: BytesToAddress(a), original: hexaddr}, nil -} - -// UnmarshalJSON parses MixedcaseAddress -func (ma *MixedcaseAddress) UnmarshalJSON(input []byte) error { - if err := hexutil.UnmarshalFixedJSON(addressT, input, ma.addr[:]); err != nil { - return err - } - return json.Unmarshal(input, &ma.original) -} - -// MarshalJSON marshals the original value -func (ma MixedcaseAddress) MarshalJSON() ([]byte, error) { - if strings.HasPrefix(ma.original, "0x") || strings.HasPrefix(ma.original, "0X") { - return json.Marshal(fmt.Sprintf("0x%s", ma.original[2:])) - } - return json.Marshal(fmt.Sprintf("0x%s", ma.original)) -} - -// Address returns the address -func (ma *MixedcaseAddress) Address() Address { - return ma.addr -} - -// String implements fmt.Stringer -func (ma *MixedcaseAddress) String() string { - if ma.ValidChecksum() { - return fmt.Sprintf("%s [chksum ok]", ma.original) - } - return fmt.Sprintf("%s [chksum INVALID]", ma.original) -} - -// ValidChecksum returns true if the address has valid checksum -func (ma *MixedcaseAddress) ValidChecksum() bool { - return ma.original == ma.addr.Hex() -} - -// Original returns the mixed-case input string -func (ma *MixedcaseAddress) Original() string { - return ma.original -} - -// AddressEIP55 is an alias of Address with a customized json marshaller -type AddressEIP55 Address - -// String returns the hex representation of the address in the manner of EIP55. -func (addr AddressEIP55) String() string { - return Address(addr).Hex() -} - -// MarshalJSON marshals the address in the manner of EIP55. -func (addr AddressEIP55) MarshalJSON() ([]byte, error) { - return json.Marshal(addr.String()) -} - -type Decimal uint64 - -func isString(input []byte) bool { - return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' -} - -// UnmarshalJSON parses a hash in hex syntax. -func (d *Decimal) UnmarshalJSON(input []byte) error { - if !isString(input) { - return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))} - } - if i, err := strconv.ParseInt(string(input[1:len(input)-1]), 10, 64); err == nil { - *d = Decimal(i) - return nil - } else { - return err - } -} - -type HexBytes []byte - -// MarshalJSON implements json.Marshaler. -func (h HexBytes) MarshalJSON() ([]byte, error) { - return []byte(fmt.Sprintf(`"%#x"`, []byte(h))), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *HexBytes) UnmarshalJSON(input []byte) error { - if len(input) == 0 { - return errors.New("input missing") - } - - if !bytes.HasPrefix(input, []byte{'"', '0', 'x'}) { - return errors.New("invalid prefix") - } - if !bytes.HasSuffix(input, []byte{'"'}) { - return errors.New("invalid suffix") - } - - src := input[3 : len(input)-1] - *s = make([]byte, hex.DecodedLen(len(src))) - - _, err := hex.Decode(*s, input[3:len(input)-1]) - if err != nil { - return err - } - - return nil -} - -// InclusionProof is a Merkle Multiproof of inclusion of a set of TransactionHashes -type InclusionProof struct { - TransactionHashes []Hash `json:"transaction_hashes"` - GeneralizedIndexes []uint64 `json:"generalized_indexes"` - MerkleHashes []*HexBytes `json:"merkle_hashes"` -} - -// InclusionProofFromMultiProof converts a fastssz.Multiproof into an InclusionProof, without -// filling the TransactionHashes -func InclusionProofFromMultiProof(mp *fastSsz.Multiproof) *InclusionProof { - merkleHashes := make([]*HexBytes, len(mp.Hashes)) - for i, h := range mp.Hashes { - merkleHashes[i] = new(HexBytes) - *(merkleHashes[i]) = h - } - - leaves := make([]*HexBytes, len(mp.Leaves)) - for i, h := range mp.Leaves { - leaves[i] = new(HexBytes) - *(leaves[i]) = h - } - generalIndexes := make([]uint64, len(mp.Indices)) - for i, idx := range mp.Indices { - generalIndexes[i] = uint64(idx) - } - return &InclusionProof{ - MerkleHashes: merkleHashes, - GeneralizedIndexes: generalIndexes, - } -} - -func (p *InclusionProof) String() string { - return JSONStringify(p) -} - -// A wrapper struct over `builderSpec.VersionedSubmitBlockRequest` -// to include preconfirmation proofs -type VersionedSubmitBlockRequestWithProofs struct { - Inner *builderSpec.VersionedSubmitBlockRequest `json:"inner"` - Proofs *InclusionProof `json:"proofs"` -} - -// this is necessary, because the mev-boost-relay deserialization doesn't expect a "Version" and "Data" wrapper object -// for deserialization. Instead, it tries to decode the object into the "Deneb" version first and if that fails, it tries -// the "Capella" version. This is a workaround to make the deserialization work. -func (v *VersionedSubmitBlockRequestWithProofs) MarshalJSON() ([]byte, error) { - switch v.Inner.Version { - case consensusSpec.DataVersionBellatrix: - return json.Marshal(struct { - Inner *bellatrix.SubmitBlockRequest `json:"inner"` - Proofs *InclusionProof `json:"proofs"` - }{ - Inner: v.Inner.Bellatrix, - Proofs: v.Proofs, - }) - case consensusSpec.DataVersionCapella: - return json.Marshal(struct { - Inner *capella.SubmitBlockRequest `json:"inner"` - Proofs *InclusionProof `json:"proofs"` - }{ - Inner: v.Inner.Capella, - Proofs: v.Proofs, - }) - case consensusSpec.DataVersionDeneb: - return json.Marshal(struct { - Inner *deneb.SubmitBlockRequest `json:"inner"` - Proofs *InclusionProof `json:"proofs"` - }{ - Inner: v.Inner.Deneb, - Proofs: v.Proofs, - }) - } - - return nil, fmt.Errorf("unknown data version %d", v.Inner.Version) -} - -func (v *VersionedSubmitBlockRequestWithProofs) String() string { - return JSONStringify(v) -} - -// SignedConstraintsList are a list of proposer constraints that a builder must satisfy -// in order to produce a valid bid. This is not defined on the -// [spec](https://chainbound.github.io/bolt-docs/api/builder-api) -// but it's useful as an helper type -type SignedConstraintsList = []*SignedConstraints - -// Reference: https://chainbound.github.io/bolt-docs/api/builder-api -type SignedConstraints struct { - Message ConstraintMessage `json:"message"` - Signature phase0.BLSSignature `json:"signature"` -} - -// Reference: https://chainbound.github.io/bolt-docs/api/builder-api -type ConstraintMessage struct { - Constraints []*Constraint `json:"constraints"` - ValidatorIndex uint64 `json:"validator_index"` - Slot uint64 `json:"slot"` -} - -// Reference: https://chainbound.github.io/bolt-docs/api/builder-api -type Constraint struct { - Index *uint64 `json:"index"` - Tx HexBytes `json:"tx"` -} - -// ConstraintSubscriptionAuth is the struct the builder signs over to authenticate -// when subscribing to SSE constraint events from the relay -type ConstraintSubscriptionAuth struct { - PublicKey phase0.BLSPubKey `json:"publicKey"` - Slot uint64 `json:"slot"` -} - -func (c *ConstraintSubscriptionAuth) String() string { - buf, err := json.Marshal(c) - if err != nil { - return fmt.Sprintf("failed to marshal ConstraintSubscriptionAuth: %v", err) - } - return string(buf) -} diff --git a/builder/common/types_test.go b/builder/common/types_test.go deleted file mode 100644 index cec689ea3..000000000 --- a/builder/common/types_test.go +++ /dev/null @@ -1,597 +0,0 @@ -// 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 common - -import ( - "bytes" - "database/sql/driver" - "encoding/json" - "fmt" - "math/big" - "reflect" - "strings" - "testing" - "time" -) - -func TestBytesConversion(t *testing.T) { - bytes := []byte{5} - hash := BytesToHash(bytes) - - var exp Hash - exp[31] = 5 - - if hash != exp { - t.Errorf("expected %x got %x", exp, hash) - } -} - -func TestIsHexAddress(t *testing.T) { - tests := []struct { - str string - exp bool - }{ - {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, - {"5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, - {"0X5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, - {"0XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", true}, - {"0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", true}, - {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed1", false}, - {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beae", false}, - {"5aaeb6053f3e94c9b9a09f33669435e7ef1beaed11", false}, - {"0xxaaeb6053f3e94c9b9a09f33669435e7ef1beaed", false}, - } - - for _, test := range tests { - if result := IsHexAddress(test.str); result != test.exp { - t.Errorf("IsHexAddress(%s) == %v; expected %v", - test.str, result, test.exp) - } - } -} - -func TestHashJsonValidation(t *testing.T) { - var tests = []struct { - Prefix string - Size int - Error string - }{ - {"", 62, "json: cannot unmarshal hex string without 0x prefix into Go value of type common.Hash"}, - {"0x", 66, "hex string has length 66, want 64 for common.Hash"}, - {"0x", 63, "json: cannot unmarshal hex string of odd length into Go value of type common.Hash"}, - {"0x", 0, "hex string has length 0, want 64 for common.Hash"}, - {"0x", 64, ""}, - {"0X", 64, ""}, - } - for _, test := range tests { - input := `"` + test.Prefix + strings.Repeat("0", test.Size) + `"` - var v Hash - err := json.Unmarshal([]byte(input), &v) - if err == nil { - if test.Error != "" { - t.Errorf("%s: error mismatch: have nil, want %q", input, test.Error) - } - } else { - if err.Error() != test.Error { - t.Errorf("%s: error mismatch: have %q, want %q", input, err, test.Error) - } - } - } -} - -func TestAddressUnmarshalJSON(t *testing.T) { - var tests = []struct { - Input string - ShouldErr bool - Output *big.Int - }{ - {"", true, nil}, - {`""`, true, nil}, - {`"0x"`, true, nil}, - {`"0x00"`, true, nil}, - {`"0xG000000000000000000000000000000000000000"`, true, nil}, - {`"0x0000000000000000000000000000000000000000"`, false, big.NewInt(0)}, - {`"0x0000000000000000000000000000000000000010"`, false, big.NewInt(16)}, - } - for i, test := range tests { - var v Address - err := json.Unmarshal([]byte(test.Input), &v) - if err != nil && !test.ShouldErr { - t.Errorf("test #%d: unexpected error: %v", i, err) - } - if err == nil { - if test.ShouldErr { - t.Errorf("test #%d: expected error, got none", i) - } - if got := new(big.Int).SetBytes(v.Bytes()); got.Cmp(test.Output) != 0 { - t.Errorf("test #%d: address mismatch: have %v, want %v", i, got, test.Output) - } - } - } -} - -func TestAddressHexChecksum(t *testing.T) { - var tests = []struct { - Input string - Output string - }{ - // Test cases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md#specification - {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"}, - {"0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359", "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"}, - {"0xdbf03b407c01e7cd3cbea99509d93f8dddc8c6fb", "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"}, - {"0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb", "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"}, - // Ensure that non-standard length input values are handled correctly - {"0xa", "0x000000000000000000000000000000000000000A"}, - {"0x0a", "0x000000000000000000000000000000000000000A"}, - {"0x00a", "0x000000000000000000000000000000000000000A"}, - {"0x000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000A"}, - } - for i, test := range tests { - output := HexToAddress(test.Input).Hex() - if output != test.Output { - t.Errorf("test #%d: failed to match when it should (%s != %s)", i, output, test.Output) - } - } -} - -func BenchmarkAddressHex(b *testing.B) { - testAddr := HexToAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") - for n := 0; n < b.N; n++ { - testAddr.Hex() - } -} - -// Test checks if the customized json marshaller of MixedcaseAddress object -// is invoked correctly. In golang the struct pointer will inherit the -// non-pointer receiver methods, the reverse is not true. In the case of -// MixedcaseAddress, it must define the MarshalJSON method in the object -// but not the pointer level, so that this customized marshalled can be used -// for both MixedcaseAddress object and pointer. -func TestMixedcaseAddressMarshal(t *testing.T) { - var ( - output string - input = "0xae967917c465db8578ca9024c205720b1a3651A9" - ) - addr, err := NewMixedcaseAddressFromString(input) - if err != nil { - t.Fatal(err) - } - blob, err := json.Marshal(*addr) - if err != nil { - t.Fatal(err) - } - json.Unmarshal(blob, &output) - if output != input { - t.Fatal("Failed to marshal/unmarshal MixedcaseAddress object") - } -} - -func TestMixedcaseAccount_Address(t *testing.T) { - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md - // Note: 0X{checksum_addr} is not valid according to spec above - - var res []struct { - A MixedcaseAddress - Valid bool - } - if err := json.Unmarshal([]byte(`[ - {"A" : "0xae967917c465db8578ca9024c205720b1a3651A9", "Valid": false}, - {"A" : "0xAe967917c465db8578ca9024c205720b1a3651A9", "Valid": true}, - {"A" : "0XAe967917c465db8578ca9024c205720b1a3651A9", "Valid": false}, - {"A" : "0x1111111111111111111112222222222223333323", "Valid": true} - ]`), &res); err != nil { - t.Fatal(err) - } - - for _, r := range res { - if got := r.A.ValidChecksum(); got != r.Valid { - t.Errorf("Expected checksum %v, got checksum %v, input %v", r.Valid, got, r.A.String()) - } - } - - // These should throw exceptions: - var r2 []MixedcaseAddress - for _, r := range []string{ - `["0x11111111111111111111122222222222233333"]`, // Too short - `["0x111111111111111111111222222222222333332"]`, // Too short - `["0x11111111111111111111122222222222233333234"]`, // Too long - `["0x111111111111111111111222222222222333332344"]`, // Too long - `["1111111111111111111112222222222223333323"]`, // Missing 0x - `["x1111111111111111111112222222222223333323"]`, // Missing 0 - `["0xG111111111111111111112222222222223333323"]`, //Non-hex - } { - if err := json.Unmarshal([]byte(r), &r2); err == nil { - t.Errorf("Expected failure, input %v", r) - } - } -} - -func TestHash_Scan(t *testing.T) { - type args struct { - src interface{} - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "working scan", - args: args{src: []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0x10, 0x00, - }}, - wantErr: false, - }, - { - name: "non working scan", - args: args{src: int64(1234567890)}, - wantErr: true, - }, - { - name: "invalid length scan", - args: args{src: []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - }}, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - h := &Hash{} - if err := h.Scan(tt.args.src); (err != nil) != tt.wantErr { - t.Errorf("Hash.Scan() error = %v, wantErr %v", err, tt.wantErr) - } - - if !tt.wantErr { - for i := range h { - if h[i] != tt.args.src.([]byte)[i] { - t.Errorf( - "Hash.Scan() didn't scan the %d src correctly (have %X, want %X)", - i, h[i], tt.args.src.([]byte)[i], - ) - } - } - } - }) - } -} - -func TestHash_Value(t *testing.T) { - b := []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0x10, 0x00, - } - var usedH Hash - usedH.SetBytes(b) - tests := []struct { - name string - h Hash - want driver.Value - wantErr bool - }{ - { - name: "Working value", - h: usedH, - want: b, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := tt.h.Value() - if (err != nil) != tt.wantErr { - t.Errorf("Hash.Value() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Hash.Value() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestAddress_Scan(t *testing.T) { - type args struct { - src interface{} - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "working scan", - args: args{src: []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - }}, - wantErr: false, - }, - { - name: "non working scan", - args: args{src: int64(1234567890)}, - wantErr: true, - }, - { - name: "invalid length scan", - args: args{src: []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, - }}, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - a := &Address{} - if err := a.Scan(tt.args.src); (err != nil) != tt.wantErr { - t.Errorf("Address.Scan() error = %v, wantErr %v", err, tt.wantErr) - } - - if !tt.wantErr { - for i := range a { - if a[i] != tt.args.src.([]byte)[i] { - t.Errorf( - "Address.Scan() didn't scan the %d src correctly (have %X, want %X)", - i, a[i], tt.args.src.([]byte)[i], - ) - } - } - } - }) - } -} - -func TestAddress_Value(t *testing.T) { - b := []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - } - var usedA Address - usedA.SetBytes(b) - tests := []struct { - name string - a Address - want driver.Value - wantErr bool - }{ - { - name: "Working value", - a: usedA, - want: b, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := tt.a.Value() - if (err != nil) != tt.wantErr { - t.Errorf("Address.Value() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Address.Value() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestAddress_Format(t *testing.T) { - b := []byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - } - var addr Address - addr.SetBytes(b) - - tests := []struct { - name string - out string - want string - }{ - { - name: "println", - out: fmt.Sprintln(addr), - want: "0xB26f2b342AAb24BCF63ea218c6A9274D30Ab9A15\n", - }, - { - name: "print", - out: fmt.Sprint(addr), - want: "0xB26f2b342AAb24BCF63ea218c6A9274D30Ab9A15", - }, - { - name: "printf-s", - out: func() string { - buf := new(bytes.Buffer) - fmt.Fprintf(buf, "%s", addr) - return buf.String() - }(), - want: "0xB26f2b342AAb24BCF63ea218c6A9274D30Ab9A15", - }, - { - name: "printf-q", - out: fmt.Sprintf("%q", addr), - want: `"0xB26f2b342AAb24BCF63ea218c6A9274D30Ab9A15"`, - }, - { - name: "printf-x", - out: fmt.Sprintf("%x", addr), - want: "b26f2b342aab24bcf63ea218c6a9274d30ab9a15", - }, - { - name: "printf-X", - out: fmt.Sprintf("%X", addr), - want: "B26F2B342AAB24BCF63EA218C6A9274D30AB9A15", - }, - { - name: "printf-#x", - out: fmt.Sprintf("%#x", addr), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15", - }, - { - name: "printf-v", - out: fmt.Sprintf("%v", addr), - want: "0xB26f2b342AAb24BCF63ea218c6A9274D30Ab9A15", - }, - // The original default formatter for byte slice - { - name: "printf-d", - out: fmt.Sprintf("%d", addr), - want: "[178 111 43 52 42 171 36 188 246 62 162 24 198 169 39 77 48 171 154 21]", - }, - // Invalid format char. - { - name: "printf-t", - out: fmt.Sprintf("%t", addr), - want: "%!t(address=b26f2b342aab24bcf63ea218c6a9274d30ab9a15)", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.out != tt.want { - t.Errorf("%s does not render as expected:\n got %s\nwant %s", tt.name, tt.out, tt.want) - } - }) - } -} - -func TestHash_Format(t *testing.T) { - var hash Hash - hash.SetBytes([]byte{ - 0xb2, 0x6f, 0x2b, 0x34, 0x2a, 0xab, 0x24, 0xbc, 0xf6, 0x3e, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0xa2, 0x18, 0xc6, 0xa9, 0x27, 0x4d, 0x30, 0xab, 0x9a, 0x15, - 0x10, 0x00, - }) - - tests := []struct { - name string - out string - want string - }{ - { - name: "println", - out: fmt.Sprintln(hash), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000\n", - }, - { - name: "print", - out: fmt.Sprint(hash), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000", - }, - { - name: "printf-s", - out: func() string { - buf := new(bytes.Buffer) - fmt.Fprintf(buf, "%s", hash) - return buf.String() - }(), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000", - }, - { - name: "printf-q", - out: fmt.Sprintf("%q", hash), - want: `"0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000"`, - }, - { - name: "printf-x", - out: fmt.Sprintf("%x", hash), - want: "b26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000", - }, - { - name: "printf-X", - out: fmt.Sprintf("%X", hash), - want: "B26F2B342AAB24BCF63EA218C6A9274D30AB9A15A218C6A9274D30AB9A151000", - }, - { - name: "printf-#x", - out: fmt.Sprintf("%#x", hash), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000", - }, - { - name: "printf-#X", - out: fmt.Sprintf("%#X", hash), - want: "0XB26F2B342AAB24BCF63EA218C6A9274D30AB9A15A218C6A9274D30AB9A151000", - }, - { - name: "printf-v", - out: fmt.Sprintf("%v", hash), - want: "0xb26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000", - }, - // The original default formatter for byte slice - { - name: "printf-d", - out: fmt.Sprintf("%d", hash), - want: "[178 111 43 52 42 171 36 188 246 62 162 24 198 169 39 77 48 171 154 21 162 24 198 169 39 77 48 171 154 21 16 0]", - }, - // Invalid format char. - { - name: "printf-t", - out: fmt.Sprintf("%t", hash), - want: "%!t(hash=b26f2b342aab24bcf63ea218c6a9274d30ab9a15a218c6a9274d30ab9a151000)", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.out != tt.want { - t.Errorf("%s does not render as expected:\n got %s\nwant %s", tt.name, tt.out, tt.want) - } - }) - } -} - -func TestAddressEIP55(t *testing.T) { - addr := HexToAddress("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") - addrEIP55 := AddressEIP55(addr) - - if addr.Hex() != addrEIP55.String() { - t.Fatal("AddressEIP55 should match original address hex") - } - - blob, err := addrEIP55.MarshalJSON() - if err != nil { - t.Fatal("Failed to marshal AddressEIP55", err) - } - if strings.Trim(string(blob), "\"") != addr.Hex() { - t.Fatal("Address with checksum is expected") - } - var dec Address - if err := json.Unmarshal(blob, &dec); err != nil { - t.Fatal("Failed to unmarshal AddressEIP55", err) - } - if addr != dec { - t.Fatal("Unexpected address after unmarshal") - } -} - -func BenchmarkPrettyDuration(b *testing.B) { - var x = PrettyDuration(time.Duration(int64(1203123912312))) - b.Logf("Pre %s", time.Duration(x).String()) - var a string - b.ResetTimer() - for i := 0; i < b.N; i++ { - a = x.String() - } - b.Logf("Post %s", a) -} diff --git a/builder/common/utils.go b/builder/common/utils.go deleted file mode 100644 index 50ee385ea..000000000 --- a/builder/common/utils.go +++ /dev/null @@ -1,66 +0,0 @@ -package common - -import "encoding/json" - -func Find[T any](slice []*T, predicate func(el *T) bool) *T { - for _, el := range slice { - if predicate(el) { - return el - } - } - return nil -} - -// Filter filters a slice in place, removing elements for which the predicate returns false. -func Filter[T any](slice *[]*T, predicate func(el *T) bool) { - if slice == nil { - return - } - - for i := 0; i < len(*slice); i++ { - el := (*slice)[i] - if !predicate(el) { - // Remove the element by slicing - if i == len(*slice)-1 { - *slice = (*slice)[:i] - } else { - *slice = append((*slice)[:i], (*slice)[i+1:]...) - } - i-- // Decrement index to adjust for the removed element - } - } -} - -func Pop[T any](slice *[]*T) *T { - if slice == nil || len(*slice) == 0 { - return nil - } - el := (*slice)[len(*slice)-1] - *slice = (*slice)[:len(*slice)-1] - return el -} - -func Shift[T any](slice *[]*T) *T { - if slice == nil || len(*slice) == 0 { - return nil - } - el := (*slice)[0] - *slice = (*slice)[1:] - return el -} - -func Map[T any, U any](slice []*T, mapper func(el *T) *U) []*U { - result := make([]*U, len(slice)) - for i, el := range slice { - result[i] = mapper(el) - } - return result -} - -func JSONStringify(obj any) string { - b, err := json.Marshal(obj) - if err != nil { - return "" - } - return string(b) -} diff --git a/builder/common/utils_test.go b/builder/common/utils_test.go deleted file mode 100644 index bbccefe2e..000000000 --- a/builder/common/utils_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package common - -import "testing" - -func TestGenericFilter(t *testing.T) { - slice := []*int{new(int), new(int), new(int), new(int)} - for i := 0; i < len(slice); i++ { - *slice[i] = i - } - - Filter(&slice, func(el *int) bool { - return el != nil - }) - if len(slice) != 4 { - t.Errorf("Filter failed") - } - Filter(&slice, func(el *int) bool { - return *el%2 == 0 - }) - if len(slice) != 2 { - t.Errorf("Filter failed") - } - Filter(&slice, func(el *int) bool { - return el == nil - }) - if len(slice) != 0 { - t.Errorf("Filter failed") - } -} diff --git a/builder/consensus/beacon/consensus.go b/builder/consensus/beacon/consensus.go deleted file mode 100644 index a350e383a..000000000 --- a/builder/consensus/beacon/consensus.go +++ /dev/null @@ -1,473 +0,0 @@ -// 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 beacon - -import ( - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" -) - -// Proof-of-stake protocol constants. -var ( - beaconDifficulty = common.Big0 // The default block difficulty in the beacon consensus - beaconNonce = types.EncodeNonce(0) // The default block nonce in the beacon consensus -) - -// Various error messages to mark blocks invalid. These should be private to -// prevent engine specific errors from being referenced in the remainder of the -// codebase, inherently breaking if the engine is swapped out. Please put common -// error types into the consensus package. -var ( - errTooManyUncles = errors.New("too many uncles") - errInvalidNonce = errors.New("invalid nonce") - errInvalidUncleHash = errors.New("invalid uncle hash") - errInvalidTimestamp = errors.New("invalid timestamp") -) - -// Beacon is a consensus engine that combines the eth1 consensus and proof-of-stake -// algorithm. There is a special flag inside to decide whether to use legacy consensus -// rules or new rules. The transition rule is described in the eth1/2 merge spec. -// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3675.md -// -// The beacon here is a half-functional consensus engine with partial functions which -// is only used for necessary consensus checks. The legacy consensus engine can be any -// engine implements the consensus interface (except the beacon itself). -type Beacon struct { - ethone consensus.Engine // Original consensus engine used in eth1, e.g. ethash or clique -} - -// New creates a consensus engine with the given embedded eth1 engine. -func New(ethone consensus.Engine) *Beacon { - if _, ok := ethone.(*Beacon); ok { - panic("nested consensus engine") - } - return &Beacon{ethone: ethone} -} - -// Author implements consensus.Engine, returning the verified author of the block. -func (beacon *Beacon) Author(header *types.Header) (common.Address, error) { - if !beacon.IsPoSHeader(header) { - return beacon.ethone.Author(header) - } - return header.Coinbase, nil -} - -// VerifyHeader checks whether a header conforms to the consensus rules of the -// stock Ethereum consensus engine. -func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { - reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) - if err != nil { - return err - } - if !reached { - return beacon.ethone.VerifyHeader(chain, header) - } - // Short circuit if the parent is not known - parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } - // Sanity checks passed, do a proper verification - return beacon.verifyHeader(chain, header, parent) -} - -// errOut constructs an error channel with prefilled errors inside. -func errOut(n int, err error) chan error { - errs := make(chan error, n) - for i := 0; i < n; i++ { - errs <- err - } - return errs -} - -// splitHeaders splits the provided header batch into two parts according to -// the configured ttd. It requires the parent of header batch along with its -// td are stored correctly in chain. If ttd is not configured yet, all headers -// will be treated legacy PoW headers. -// Note, this function will not verify the header validity but just split them. -func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) { - // TTD is not defined yet, all headers should be in legacy format. - ttd := chain.Config().TerminalTotalDifficulty - if ttd == nil { - return headers, nil, nil - } - ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1) - if ptd == nil { - return nil, nil, consensus.ErrUnknownAncestor - } - // The entire header batch already crosses the transition. - if ptd.Cmp(ttd) >= 0 { - return nil, headers, nil - } - var ( - preHeaders = headers - postHeaders []*types.Header - td = new(big.Int).Set(ptd) - tdPassed bool - ) - for i, header := range headers { - if tdPassed { - preHeaders = headers[:i] - postHeaders = headers[i:] - break - } - td = td.Add(td, header.Difficulty) - if td.Cmp(ttd) >= 0 { - // This is the last PoW header, it still belongs to - // the preHeaders, so we cannot split+break yet. - tdPassed = true - } - } - return preHeaders, postHeaders, nil -} - -// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers -// concurrently. The method returns a quit channel to abort the operations and -// a results channel to retrieve the async verifications. -// VerifyHeaders expect the headers to be ordered and continuous. -func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { - preHeaders, postHeaders, err := beacon.splitHeaders(chain, headers) - if err != nil { - return make(chan struct{}), errOut(len(headers), err) - } - if len(postHeaders) == 0 { - return beacon.ethone.VerifyHeaders(chain, headers) - } - if len(preHeaders) == 0 { - return beacon.verifyHeaders(chain, headers, nil) - } - // The transition point exists in the middle, separate the headers - // into two batches and apply different verification rules for them. - var ( - abort = make(chan struct{}) - results = make(chan error, len(headers)) - ) - go func() { - var ( - old, new, out = 0, len(preHeaders), 0 - errors = make([]error, len(headers)) - done = make([]bool, len(headers)) - oldDone, oldResult = beacon.ethone.VerifyHeaders(chain, preHeaders) - newDone, newResult = beacon.verifyHeaders(chain, postHeaders, preHeaders[len(preHeaders)-1]) - ) - // Collect the results - for { - for ; done[out]; out++ { - results <- errors[out] - if out == len(headers)-1 { - return - } - } - select { - case err := <-oldResult: - if !done[old] { // skip TTD-verified failures - errors[old], done[old] = err, true - } - old++ - case err := <-newResult: - errors[new], done[new] = err, true - new++ - case <-abort: - close(oldDone) - close(newDone) - return - } - } - }() - return abort, results -} - -// VerifyUncles verifies that the given block's uncles conform to the consensus -// rules of the Ethereum consensus engine. -func (beacon *Beacon) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - if !beacon.IsPoSHeader(block.Header()) { - return beacon.ethone.VerifyUncles(chain, block) - } - // Verify that there is no uncle block. It's explicitly disabled in the beacon - if len(block.Uncles()) > 0 { - return errTooManyUncles - } - return nil -} - -// verifyHeader checks whether a header conforms to the consensus rules of the -// stock Ethereum consensus engine. The difference between the beacon and classic is -// (a) The following fields are expected to be constants: -// - difficulty is expected to be 0 -// - nonce is expected to be 0 -// - unclehash is expected to be Hash(emptyHeader) -// to be the desired constants -// -// (b) we don't verify if a block is in the future anymore -// (c) the extradata is limited to 32 bytes -func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header) error { - // Ensure that the header's extra-data section is of a reasonable size - if len(header.Extra) > 32 { - return fmt.Errorf("extra-data longer than 32 bytes (%d)", len(header.Extra)) - } - // Verify the seal parts. Ensure the nonce and uncle hash are the expected value. - if header.Nonce != beaconNonce { - return errInvalidNonce - } - if header.UncleHash != types.EmptyUncleHash { - return errInvalidUncleHash - } - // Verify the timestamp - if header.Time <= parent.Time { - return errInvalidTimestamp - } - // Verify the block's difficulty to ensure it's the default constant - if beaconDifficulty.Cmp(header.Difficulty) != 0 { - return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, beaconDifficulty) - } - // Verify that the gas limit is <= 2^63-1 - if header.GasLimit > params.MaxGasLimit { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) - } - // Verify that the gasUsed is <= gasLimit - if header.GasUsed > header.GasLimit { - return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) - } - // Verify that the block number is parent's +1 - if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(common.Big1) != 0 { - return consensus.ErrInvalidNumber - } - // Verify the header's EIP-1559 attributes. - if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { - return err - } - // Verify existence / non-existence of withdrawalsHash. - shanghai := chain.Config().IsShanghai(header.Number, header.Time) - if shanghai && header.WithdrawalsHash == nil { - return errors.New("missing withdrawalsHash") - } - if !shanghai && header.WithdrawalsHash != nil { - return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) - } - // Verify the existence / non-existence of cancun-specific header fields - cancun := chain.Config().IsCancun(header.Number, header.Time) - if !cancun { - switch { - case header.ExcessBlobGas != nil: - return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) - case header.BlobGasUsed != nil: - return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - case header.ParentBeaconRoot != nil: - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) - } - } else { - if header.ParentBeaconRoot == nil { - return errors.New("header is missing beaconRoot") - } - if err := eip4844.VerifyEIP4844Header(parent, header); err != nil { - return err - } - } - return nil -} - -// verifyHeaders is similar to verifyHeader, but verifies a batch of headers -// concurrently. The method returns a quit channel to abort the operations and -// a results channel to retrieve the async verifications. An additional parent -// header will be passed if the relevant header is not in the database yet. -func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, ancestor *types.Header) (chan<- struct{}, <-chan error) { - var ( - abort = make(chan struct{}) - results = make(chan error, len(headers)) - ) - go func() { - for i, header := range headers { - var parent *types.Header - if i == 0 { - if ancestor != nil { - parent = ancestor - } else { - parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) - } - } else if headers[i-1].Hash() == headers[i].ParentHash { - parent = headers[i-1] - } - if parent == nil { - select { - case <-abort: - return - case results <- consensus.ErrUnknownAncestor: - } - continue - } - err := beacon.verifyHeader(chain, header, parent) - select { - case <-abort: - return - case results <- err: - } - } - }() - return abort, results -} - -// Prepare implements consensus.Engine, initializing the difficulty field of a -// header to conform to the beacon protocol. The changes are done inline. -func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - // Transition isn't triggered yet, use the legacy rules for preparation. - reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) - if err != nil { - return err - } - if !reached { - return beacon.ethone.Prepare(chain, header) - } - header.Difficulty = beaconDifficulty - return nil -} - -// Finalize implements consensus.Engine and processes withdrawals on top. -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { - if !beacon.IsPoSHeader(header) { - beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) - return - } - // Withdrawals processing. - for _, w := range withdrawals { - // Convert amount from gwei to wei. - amount := new(uint256.Int).SetUint64(w.Amount) - amount = amount.Mul(amount, uint256.NewInt(params.GWei)) - state.AddBalance(w.Address, amount) - } - // No block reward which is issued by consensus layer instead. -} - -// FinalizeAndAssemble implements consensus.Engine, setting the final state and -// assembling the block. -func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { - if !beacon.IsPoSHeader(header) { - return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) - } - shanghai := chain.Config().IsShanghai(header.Number, header.Time) - if shanghai { - // All blocks after Shanghai must include a withdrawals root. - if withdrawals == nil { - withdrawals = make([]*types.Withdrawal, 0) - } - } else { - if len(withdrawals) > 0 { - return nil, errors.New("withdrawals set before Shanghai activation") - } - } - // Finalize and assemble the block. - beacon.Finalize(chain, header, state, txs, uncles, withdrawals) - - // Assign the final state root to header. - header.Root = state.IntermediateRoot(true) - - // Assemble and return the final block. - return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil -} - -// Seal generates a new sealing request for the given input block and pushes -// the result into the given channel. -// -// Note, the method returns immediately and will send the result async. More -// than one result may also be returned depending on the consensus algorithm. -func (beacon *Beacon) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - if !beacon.IsPoSHeader(block.Header()) { - return beacon.ethone.Seal(chain, block, results, stop) - } - // The seal verification is done by the external consensus engine, - // return directly without pushing any block back. In another word - // beacon won't return any result by `results` channel which may - // blocks the receiver logic forever. - return nil -} - -// SealHash returns the hash of a block prior to it being sealed. -func (beacon *Beacon) SealHash(header *types.Header) common.Hash { - return beacon.ethone.SealHash(header) -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns -// the difficulty that a new block should have when created at time -// given the parent block's time and difficulty. -func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - // Transition isn't triggered yet, use the legacy rules for calculation - if reached, _ := IsTTDReached(chain, parent.Hash(), parent.Number.Uint64()); !reached { - return beacon.ethone.CalcDifficulty(chain, time, parent) - } - return beaconDifficulty -} - -// APIs implements consensus.Engine, returning the user facing RPC APIs. -func (beacon *Beacon) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return beacon.ethone.APIs(chain) -} - -// Close shutdowns the consensus engine -func (beacon *Beacon) Close() error { - return beacon.ethone.Close() -} - -// IsPoSHeader reports the header belongs to the PoS-stage with some special fields. -// This function is not suitable for a part of APIs like Prepare or CalcDifficulty -// because the header difficulty is not set yet. -func (beacon *Beacon) IsPoSHeader(header *types.Header) bool { - if header.Difficulty == nil { - panic("IsPoSHeader called with invalid difficulty") - } - return header.Difficulty.Cmp(beaconDifficulty) == 0 -} - -// InnerEngine returns the embedded eth1 consensus engine. -func (beacon *Beacon) InnerEngine() consensus.Engine { - return beacon.ethone -} - -// SetThreads updates the mining threads. Delegate the call -// to the eth1 engine if it's threaded. -func (beacon *Beacon) SetThreads(threads int) { - type threaded interface { - SetThreads(threads int) - } - if th, ok := beacon.ethone.(threaded); ok { - th.SetThreads(threads) - } -} - -// IsTTDReached checks if the TotalTerminalDifficulty has been surpassed on the `parentHash` block. -// It depends on the parentHash already being stored in the database. -// If the parentHash is not stored in the database a UnknownAncestor error is returned. -func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) { - if chain.Config().TerminalTotalDifficulty == nil { - return false, nil - } - td := chain.GetTd(parentHash, parentNumber) - if td == nil { - return false, consensus.ErrUnknownAncestor - } - return td.Cmp(chain.Config().TerminalTotalDifficulty) >= 0, nil -} diff --git a/builder/consensus/beacon/faker.go b/builder/consensus/beacon/faker.go deleted file mode 100644 index 981e345e3..000000000 --- a/builder/consensus/beacon/faker.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2023 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 beacon - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/types" -) - -// NewFaker creates a fake consensus engine for testing. -// The fake engine simulates a merged network. -// It can not be used to test the merge transition. -// This type is needed since the fakeChainReader can not be used with -// a normal beacon consensus engine. -func NewFaker() consensus.Engine { - return new(faker) -} - -type faker struct { - Beacon -} - -func (f *faker) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - return beaconDifficulty -} diff --git a/builder/consensus/clique/api.go b/builder/consensus/clique/api.go deleted file mode 100644 index 374b50692..000000000 --- a/builder/consensus/clique/api.go +++ /dev/null @@ -1,235 +0,0 @@ -// 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 clique - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -// API is a user facing RPC API to allow controlling the signer and voting -// mechanisms of the proof-of-authority scheme. -type API struct { - chain consensus.ChainHeaderReader - clique *Clique -} - -// GetSnapshot retrieves the state snapshot at a given block. -func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return its snapshot - if header == nil { - return nil, errUnknownBlock - } - return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) -} - -// GetSnapshotAtHash retrieves the state snapshot at a given block. -func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) -} - -// GetSigners retrieves the list of authorized signers at the specified block. -func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { - // Retrieve the requested block number (or current if none requested) - var header *types.Header - if number == nil || *number == rpc.LatestBlockNumber { - header = api.chain.CurrentHeader() - } else { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - // Ensure we have an actually valid block and return the signers from its snapshot - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - return snap.signers(), nil -} - -// GetSignersAtHash retrieves the list of authorized signers at the specified block. -func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) { - header := api.chain.GetHeaderByHash(hash) - if header == nil { - return nil, errUnknownBlock - } - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - return snap.signers(), nil -} - -// Proposals returns the current proposals the node tries to uphold and vote on. -func (api *API) Proposals() map[common.Address]bool { - api.clique.lock.RLock() - defer api.clique.lock.RUnlock() - - proposals := make(map[common.Address]bool) - for address, auth := range api.clique.proposals { - proposals[address] = auth - } - return proposals -} - -// Propose injects a new authorization proposal that the signer will attempt to -// push through. -func (api *API) Propose(address common.Address, auth bool) { - api.clique.lock.Lock() - defer api.clique.lock.Unlock() - - api.clique.proposals[address] = auth -} - -// Discard drops a currently running proposal, stopping the signer from casting -// further votes (either for or against). -func (api *API) Discard(address common.Address) { - api.clique.lock.Lock() - defer api.clique.lock.Unlock() - - delete(api.clique.proposals, address) -} - -type status struct { - InturnPercent float64 `json:"inturnPercent"` - SigningStatus map[common.Address]int `json:"sealerActivity"` - NumBlocks uint64 `json:"numBlocks"` -} - -// Status returns the status of the last N blocks, -// - the number of active signers, -// - the number of signers, -// - the percentage of in-turn blocks -func (api *API) Status() (*status, error) { - var ( - numBlocks = uint64(64) - header = api.chain.CurrentHeader() - diff = uint64(0) - optimals = 0 - ) - snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) - if err != nil { - return nil, err - } - var ( - signers = snap.signers() - end = header.Number.Uint64() - start = end - numBlocks - ) - if numBlocks > end { - start = 1 - numBlocks = end - start - } - signStatus := make(map[common.Address]int) - for _, s := range signers { - signStatus[s] = 0 - } - for n := start; n < end; n++ { - h := api.chain.GetHeaderByNumber(n) - if h == nil { - return nil, fmt.Errorf("missing block %d", n) - } - if h.Difficulty.Cmp(diffInTurn) == 0 { - optimals++ - } - diff += h.Difficulty.Uint64() - sealer, err := api.clique.Author(h) - if err != nil { - return nil, err - } - signStatus[sealer]++ - } - return &status{ - InturnPercent: float64(100*optimals) / float64(numBlocks), - SigningStatus: signStatus, - NumBlocks: numBlocks, - }, nil -} - -type blockNumberOrHashOrRLP struct { - *rpc.BlockNumberOrHash - RLP hexutil.Bytes `json:"rlp,omitempty"` -} - -func (sb *blockNumberOrHashOrRLP) UnmarshalJSON(data []byte) error { - bnOrHash := new(rpc.BlockNumberOrHash) - // Try to unmarshal bNrOrHash - if err := bnOrHash.UnmarshalJSON(data); err == nil { - sb.BlockNumberOrHash = bnOrHash - return nil - } - // Try to unmarshal RLP - var input string - if err := json.Unmarshal(data, &input); err != nil { - return err - } - blob, err := hexutil.Decode(input) - if err != nil { - return err - } - sb.RLP = blob - return nil -} - -// GetSigner returns the signer for a specific clique block. -// Can be called with a block number, a block hash or a rlp encoded blob. -// The RLP encoded blob can either be a block or a header. -func (api *API) GetSigner(rlpOrBlockNr *blockNumberOrHashOrRLP) (common.Address, error) { - if len(rlpOrBlockNr.RLP) == 0 { - blockNrOrHash := rlpOrBlockNr.BlockNumberOrHash - var header *types.Header - if blockNrOrHash == nil { - header = api.chain.CurrentHeader() - } else if hash, ok := blockNrOrHash.Hash(); ok { - header = api.chain.GetHeaderByHash(hash) - } else if number, ok := blockNrOrHash.Number(); ok { - header = api.chain.GetHeaderByNumber(uint64(number.Int64())) - } - if header == nil { - return common.Address{}, fmt.Errorf("missing block %v", blockNrOrHash.String()) - } - return api.clique.Author(header) - } - block := new(types.Block) - if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, block); err == nil { - return api.clique.Author(block.Header()) - } - header := new(types.Header) - if err := rlp.DecodeBytes(rlpOrBlockNr.RLP, header); err != nil { - return common.Address{}, err - } - return api.clique.Author(header) -} diff --git a/builder/consensus/clique/clique.go b/builder/consensus/clique/clique.go deleted file mode 100644 index c693189ea..000000000 --- a/builder/consensus/clique/clique.go +++ /dev/null @@ -1,781 +0,0 @@ -// 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 clique implements the proof-of-authority consensus engine. -package clique - -import ( - "bytes" - "errors" - "fmt" - "io" - "math/big" - "math/rand" - "sync" - "time" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - lru "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/trie" - "golang.org/x/crypto/sha3" -) - -const ( - checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database - inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory - inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - - wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers -) - -// Clique proof-of-authority protocol constants. -var ( - epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes - - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = crypto.SignatureLength // Fixed number of extra-data suffix bytes reserved for signer seal - - nonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer - nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. - - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. - - diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures - diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures -) - -// Various error messages to mark blocks invalid. These should be private to -// prevent engine specific errors from being referenced in the remainder of the -// codebase, inherently breaking if the engine is swapped out. Please put common -// error types into the consensus package. -var ( - // errUnknownBlock is returned when the list of signers is requested for a block - // that is not part of the local blockchain. - errUnknownBlock = errors.New("unknown block") - - // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition - // block has a beneficiary set to non-zeroes. - errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") - - // errInvalidVote is returned if a nonce value is something else that the two - // allowed constants of 0x00..0 or 0xff..f. - errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") - - // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block - // has a vote nonce set to non-zeroes. - errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") - - // errMissingVanity is returned if a block's extra-data section is shorter than - // 32 bytes, which is required to store the signer vanity. - errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") - - // errMissingSignature is returned if a block's extra-data section doesn't seem - // to contain a 65 byte secp256k1 signature. - errMissingSignature = errors.New("extra-data 65 byte signature suffix missing") - - // errExtraSigners is returned if non-checkpoint block contain signer data in - // their extra-data fields. - errExtraSigners = errors.New("non-checkpoint block contains extra signer list") - - // errInvalidCheckpointSigners is returned if a checkpoint block contains an - // invalid list of signers (i.e. non divisible by 20 bytes). - errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") - - // errMismatchingCheckpointSigners is returned if a checkpoint block contains a - // list of signers different than the one the local node calculated. - errMismatchingCheckpointSigners = errors.New("mismatching signer list on checkpoint block") - - // errInvalidMixDigest is returned if a block's mix digest is non-zero. - errInvalidMixDigest = errors.New("non-zero mix digest") - - // errInvalidUncleHash is returned if a block contains an non-empty uncle list. - errInvalidUncleHash = errors.New("non empty uncle hash") - - // errInvalidDifficulty is returned if the difficulty of a block neither 1 or 2. - errInvalidDifficulty = errors.New("invalid difficulty") - - // errWrongDifficulty is returned if the difficulty of a block doesn't match the - // turn of the signer. - errWrongDifficulty = errors.New("wrong difficulty") - - // errInvalidTimestamp is returned if the timestamp of a block is lower than - // the previous block's timestamp + the minimum block period. - errInvalidTimestamp = errors.New("invalid timestamp") - - // errInvalidVotingChain is returned if an authorization list is attempted to - // be modified via out-of-range or non-contiguous headers. - errInvalidVotingChain = errors.New("invalid voting chain") - - // errUnauthorizedSigner is returned if a header is signed by a non-authorized entity. - errUnauthorizedSigner = errors.New("unauthorized signer") - - // errRecentlySigned is returned if a header is signed by an authorized entity - // that already signed a header recently, thus is temporarily not allowed to. - errRecentlySigned = errors.New("recently signed") -) - -// SignerFn hashes and signs the data to be signed by a backing account. -type SignerFn func(signer accounts.Account, mimeType string, message []byte) ([]byte, error) - -// ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) { - // If the signature's already cached, return that - hash := header.Hash() - if address, known := sigcache.Get(hash); known { - return address, nil - } - // Retrieve the signature from the header extra-data - if len(header.Extra) < extraSeal { - return common.Address{}, errMissingSignature - } - signature := header.Extra[len(header.Extra)-extraSeal:] - - // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) - if err != nil { - return common.Address{}, err - } - var signer common.Address - copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) - - sigcache.Add(hash, signer) - return signer, nil -} - -// Clique is the proof-of-authority consensus engine proposed to support the -// Ethereum testnet following the Ropsten attacks. -type Clique struct { - config *params.CliqueConfig // Consensus engine configuration parameters - db ethdb.Database // Database to store and retrieve snapshot checkpoints - - recents *lru.Cache[common.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs - signatures *sigLRU // Signatures of recent blocks to speed up mining - - proposals map[common.Address]bool // Current list of proposals we are pushing - - signer common.Address // Ethereum address of the signing key - signFn SignerFn // Signer function to authorize hashes with - lock sync.RWMutex // Protects the signer and proposals fields - - // The fields below are for testing only - fakeDiff bool // Skip difficulty verifications -} - -// New creates a Clique proof-of-authority consensus engine with the initial -// signers set to the ones provided by the user. -func New(config *params.CliqueConfig, db ethdb.Database) *Clique { - // Set any missing consensus parameters to their defaults - conf := *config - if conf.Epoch == 0 { - conf.Epoch = epochLength - } - // Allocate the snapshot caches and create the engine - recents := lru.NewCache[common.Hash, *Snapshot](inmemorySnapshots) - signatures := lru.NewCache[common.Hash, common.Address](inmemorySignatures) - - return &Clique{ - config: &conf, - db: db, - recents: recents, - signatures: signatures, - proposals: make(map[common.Address]bool), - } -} - -// Author implements consensus.Engine, returning the Ethereum address recovered -// from the signature in the header's extra-data section. -func (c *Clique) Author(header *types.Header) (common.Address, error) { - return ecrecover(header, c.signatures) -} - -// VerifyHeader checks whether a header conforms to the consensus rules. -func (c *Clique) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { - return c.verifyHeader(chain, header, nil) -} - -// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The -// method returns a quit channel to abort the operations and a results channel to -// retrieve the async verifications (the order is that of the input slice). -func (c *Clique) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { - abort := make(chan struct{}) - results := make(chan error, len(headers)) - - go func() { - for i, header := range headers { - err := c.verifyHeader(chain, header, headers[:i]) - - select { - case <-abort: - return - case results <- err: - } - } - }() - return abort, results -} - -// verifyHeader checks whether a header conforms to the consensus rules.The -// caller may optionally pass in a batch of parents (ascending order) to avoid -// looking those up from the database. This is useful for concurrently verifying -// a batch of new headers. -func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - if header.Number == nil { - return errUnknownBlock - } - number := header.Number.Uint64() - - // Don't waste time checking blocks from the future - if header.Time > uint64(time.Now().Unix()) { - return consensus.ErrFutureBlock - } - // Checkpoint blocks need to enforce zero beneficiary - checkpoint := (number % c.config.Epoch) == 0 - if checkpoint && header.Coinbase != (common.Address{}) { - return errInvalidCheckpointBeneficiary - } - // Nonces must be 0x00..0 or 0xff..f, zeroes enforced on checkpoints - if !bytes.Equal(header.Nonce[:], nonceAuthVote) && !bytes.Equal(header.Nonce[:], nonceDropVote) { - return errInvalidVote - } - if checkpoint && !bytes.Equal(header.Nonce[:], nonceDropVote) { - return errInvalidCheckpointVote - } - // Check that the extra-data contains both the vanity and signature - if len(header.Extra) < extraVanity { - return errMissingVanity - } - if len(header.Extra) < extraVanity+extraSeal { - return errMissingSignature - } - // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise - signersBytes := len(header.Extra) - extraVanity - extraSeal - if !checkpoint && signersBytes != 0 { - return errExtraSigners - } - if checkpoint && signersBytes%common.AddressLength != 0 { - return errInvalidCheckpointSigners - } - // Ensure that the mix digest is zero as we don't have fork protection currently - if header.MixDigest != (common.Hash{}) { - return errInvalidMixDigest - } - // Ensure that the block doesn't contain any uncles which are meaningless in PoA - if header.UncleHash != uncleHash { - return errInvalidUncleHash - } - // Ensure that the block's difficulty is meaningful (may not be correct at this point) - if number > 0 { - if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { - return errInvalidDifficulty - } - } - // Verify that the gas limit is <= 2^63-1 - if header.GasLimit > params.MaxGasLimit { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) - } - if chain.Config().IsShanghai(header.Number, header.Time) { - return errors.New("clique does not support shanghai fork") - } - // Verify the non-existence of withdrawalsHash. - if header.WithdrawalsHash != nil { - return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) - } - if chain.Config().IsCancun(header.Number, header.Time) { - return errors.New("clique does not support cancun fork") - } - // Verify the non-existence of cancun-specific header fields - switch { - case header.ExcessBlobGas != nil: - return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) - case header.BlobGasUsed != nil: - return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - case header.ParentBeaconRoot != nil: - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) - } - // All basic checks passed, verify cascading fields - return c.verifyCascadingFields(chain, header, parents) -} - -// verifyCascadingFields verifies all the header fields that are not standalone, -// rather depend on a batch of previous headers. The caller may optionally pass -// in a batch of parents (ascending order) to avoid looking those up from the -// database. This is useful for concurrently verifying a batch of new headers. -func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - // The genesis block is the always valid dead-end - number := header.Number.Uint64() - if number == 0 { - return nil - } - // Ensure that the block's timestamp isn't too close to its parent - var parent *types.Header - if len(parents) > 0 { - parent = parents[len(parents)-1] - } else { - parent = chain.GetHeader(header.ParentHash, number-1) - } - if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { - return consensus.ErrUnknownAncestor - } - if parent.Time+c.config.Period > header.Time { - return errInvalidTimestamp - } - // Verify that the gasUsed is <= gasLimit - if header.GasUsed > header.GasLimit { - return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) - } - if !chain.Config().IsLondon(header.Number) { - // Verify BaseFee not present before EIP-1559 fork. - if header.BaseFee != nil { - return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee) - } - if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { - return err - } - } else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { - // Verify the header's EIP-1559 attributes. - return err - } - // Retrieve the snapshot needed to verify this header and cache it - snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) - if err != nil { - return err - } - // If the block is a checkpoint block, verify the signer list - if number%c.config.Epoch == 0 { - signers := make([]byte, len(snap.Signers)*common.AddressLength) - for i, signer := range snap.signers() { - copy(signers[i*common.AddressLength:], signer[:]) - } - extraSuffix := len(header.Extra) - extraSeal - if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) { - return errMismatchingCheckpointSigners - } - } - // All basic checks passed, verify the seal and return - return c.verifySeal(snap, header, parents) -} - -// snapshot retrieves the authorization snapshot at a given point in time. -func (c *Clique) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { - // Search for a snapshot in memory or on disk for checkpoints - var ( - headers []*types.Header - snap *Snapshot - ) - for snap == nil { - // If an in-memory snapshot was found, use that - if s, ok := c.recents.Get(hash); ok { - snap = s - break - } - // If an on-disk checkpoint snapshot can be found, use that - if number%checkpointInterval == 0 { - if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil { - log.Trace("Loaded voting snapshot from disk", "number", number, "hash", hash) - snap = s - break - } - } - // If we're at the genesis, snapshot the initial state. Alternatively if we're - // at a checkpoint block without a parent (light client CHT), or we have piled - // up more headers than allowed to be reorged (chain reinit from a freezer), - // consider the checkpoint trusted and snapshot it. - if number == 0 || (number%c.config.Epoch == 0 && (len(headers) > params.FullImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) { - checkpoint := chain.GetHeaderByNumber(number) - if checkpoint != nil { - hash := checkpoint.Hash() - - signers := make([]common.Address, (len(checkpoint.Extra)-extraVanity-extraSeal)/common.AddressLength) - for i := 0; i < len(signers); i++ { - copy(signers[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:]) - } - snap = newSnapshot(c.config, c.signatures, number, hash, signers) - if err := snap.store(c.db); err != nil { - return nil, err - } - log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) - break - } - } - // No snapshot for this header, gather the header and move backward - var header *types.Header - if len(parents) > 0 { - // If we have explicit parents, pick from there (enforced) - header = parents[len(parents)-1] - if header.Hash() != hash || header.Number.Uint64() != number { - return nil, consensus.ErrUnknownAncestor - } - parents = parents[:len(parents)-1] - } else { - // No explicit parents (or no more left), reach out to the database - header = chain.GetHeader(hash, number) - if header == nil { - return nil, consensus.ErrUnknownAncestor - } - } - headers = append(headers, header) - number, hash = number-1, header.ParentHash - } - // Previous snapshot found, apply any pending headers on top of it - for i := 0; i < len(headers)/2; i++ { - headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] - } - snap, err := snap.apply(headers) - if err != nil { - return nil, err - } - c.recents.Add(snap.Hash, snap) - - // If we've generated a new checkpoint snapshot, save to disk - if snap.Number%checkpointInterval == 0 && len(headers) > 0 { - if err = snap.store(c.db); err != nil { - return nil, err - } - log.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash) - } - return snap, err -} - -// VerifyUncles implements consensus.Engine, always returning an error for any -// uncles as this consensus mechanism doesn't permit uncles. -func (c *Clique) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - if len(block.Uncles()) > 0 { - return errors.New("uncles not allowed") - } - return nil -} - -// verifySeal checks whether the signature contained in the header satisfies the -// consensus protocol requirements. The method accepts an optional list of parent -// headers that aren't yet part of the local blockchain to generate the snapshots -// from. -func (c *Clique) verifySeal(snap *Snapshot, header *types.Header, parents []*types.Header) error { - // Verifying the genesis block is not supported - number := header.Number.Uint64() - if number == 0 { - return errUnknownBlock - } - // Resolve the authorization key and check against signers - signer, err := ecrecover(header, c.signatures) - if err != nil { - return err - } - if _, ok := snap.Signers[signer]; !ok { - return errUnauthorizedSigner - } - for seen, recent := range snap.Recents { - if recent == signer { - // Signer is among recents, only fail if the current block doesn't shift it out - if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit { - return errRecentlySigned - } - } - } - // Ensure that the difficulty corresponds to the turn-ness of the signer - if !c.fakeDiff { - inturn := snap.inturn(header.Number.Uint64(), signer) - if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { - return errWrongDifficulty - } - if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { - return errWrongDifficulty - } - } - return nil -} - -// Prepare implements consensus.Engine, preparing all the consensus fields of the -// header for running the transactions on top. -func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - // If the block isn't a checkpoint, cast a random vote (good enough for now) - header.Coinbase = common.Address{} - header.Nonce = types.BlockNonce{} - - number := header.Number.Uint64() - // Assemble the voting snapshot to check which votes make sense - snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) - if err != nil { - return err - } - c.lock.RLock() - if number%c.config.Epoch != 0 { - // Gather all the proposals that make sense voting on - addresses := make([]common.Address, 0, len(c.proposals)) - for address, authorize := range c.proposals { - if snap.validVote(address, authorize) { - addresses = append(addresses, address) - } - } - // If there's pending proposals, cast a vote on them - if len(addresses) > 0 { - header.Coinbase = addresses[rand.Intn(len(addresses))] - if c.proposals[header.Coinbase] { - copy(header.Nonce[:], nonceAuthVote) - } else { - copy(header.Nonce[:], nonceDropVote) - } - } - } - - // Copy signer protected by mutex to avoid race condition - signer := c.signer - c.lock.RUnlock() - - // Set the correct difficulty - header.Difficulty = calcDifficulty(snap, signer) - - // Ensure the extra data has all its components - if len(header.Extra) < extraVanity { - header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) - } - header.Extra = header.Extra[:extraVanity] - - if number%c.config.Epoch == 0 { - for _, signer := range snap.signers() { - header.Extra = append(header.Extra, signer[:]...) - } - } - header.Extra = append(header.Extra, make([]byte, extraSeal)...) - - // Mix digest is reserved for now, set to empty - header.MixDigest = common.Hash{} - - // Ensure the timestamp has the correct delay - parent := chain.GetHeader(header.ParentHash, number-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } - header.Time = parent.Time + c.config.Period - if header.Time < uint64(time.Now().Unix()) { - header.Time = uint64(time.Now().Unix()) - } - return nil -} - -// Finalize implements consensus.Engine. There is no post-transaction -// consensus rules in clique, do nothing here. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { - // No block rewards in PoA, so the state remains as is -} - -// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, -// nor block rewards given, and returns the final block. -func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { - if len(withdrawals) > 0 { - return nil, errors.New("clique does not support withdrawals") - } - // Finalize block - c.Finalize(chain, header, state, txs, uncles, nil) - - // Assign the final state root to header. - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - - // Assemble and return the final block for sealing. - return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil -} - -// Authorize injects a private key into the consensus engine to mint new blocks -// with. -func (c *Clique) Authorize(signer common.Address, signFn SignerFn) { - c.lock.Lock() - defer c.lock.Unlock() - - c.signer = signer - c.signFn = signFn -} - -// Seal implements consensus.Engine, attempting to create a sealed block using -// the local signing credentials. -func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - header := block.Header() - - // Sealing the genesis block is not supported - number := header.Number.Uint64() - if number == 0 { - return errUnknownBlock - } - // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) - if c.config.Period == 0 && len(block.Transactions()) == 0 { - return errors.New("sealing paused while waiting for transactions") - } - // Don't hold the signer fields for the entire sealing procedure - c.lock.RLock() - signer, signFn := c.signer, c.signFn - c.lock.RUnlock() - - // Bail out if we're unauthorized to sign a block - snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) - if err != nil { - return err - } - if _, authorized := snap.Signers[signer]; !authorized { - return errUnauthorizedSigner - } - // If we're amongst the recent signers, wait for the next block - for seen, recent := range snap.Recents { - if recent == signer { - // Signer is among recents, only wait if the current block doesn't shift it out - if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit { - return errors.New("signed recently, must wait for others") - } - } - } - // Sweet, the protocol permits us to sign the block, wait for our time - delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple - if header.Difficulty.Cmp(diffNoTurn) == 0 { - // It's not our turn explicitly to sign, delay it a bit - wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime - delay += time.Duration(rand.Int63n(int64(wiggle))) - - log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) - } - // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeClique, CliqueRLP(header)) - if err != nil { - return err - } - copy(header.Extra[len(header.Extra)-extraSeal:], sighash) - // Wait until sealing is terminated or delay timeout. - log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) - go func() { - select { - case <-stop: - return - case <-time.After(delay): - } - - select { - case results <- block.WithSeal(header): - default: - log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) - } - }() - - return nil -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty -// that a new block should have: -// * DIFF_NOTURN(2) if BLOCK_NUMBER % SIGNER_COUNT != SIGNER_INDEX -// * DIFF_INTURN(1) if BLOCK_NUMBER % SIGNER_COUNT == SIGNER_INDEX -func (c *Clique) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) - if err != nil { - return nil - } - c.lock.RLock() - signer := c.signer - c.lock.RUnlock() - return calcDifficulty(snap, signer) -} - -func calcDifficulty(snap *Snapshot, signer common.Address) *big.Int { - if snap.inturn(snap.Number+1, signer) { - return new(big.Int).Set(diffInTurn) - } - return new(big.Int).Set(diffNoTurn) -} - -// SealHash returns the hash of a block prior to it being sealed. -func (c *Clique) SealHash(header *types.Header) common.Hash { - return SealHash(header) -} - -// Close implements consensus.Engine. It's a noop for clique as there are no background threads. -func (c *Clique) Close() error { - return nil -} - -// APIs implements consensus.Engine, returning the user facing RPC API to allow -// controlling the signer voting. -func (c *Clique) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{{ - Namespace: "clique", - Service: &API{chain: chain, clique: c}, - }} -} - -// SealHash returns the hash of a block prior to it being sealed. -func SealHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - encodeSigHeader(hasher, header) - hasher.(crypto.KeccakState).Read(hash[:]) - return hash -} - -// CliqueRLP returns the rlp bytes which needs to be signed for the proof-of-authority -// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func CliqueRLP(header *types.Header) []byte { - b := new(bytes.Buffer) - encodeSigHeader(b, header) - return b.Bytes() -} - -func encodeSigHeader(w io.Writer, header *types.Header) { - enc := []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-crypto.SignatureLength], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - } - if header.BaseFee != nil { - enc = append(enc, header.BaseFee) - } - if header.WithdrawalsHash != nil { - panic("unexpected withdrawal hash value in clique") - } - if header.ExcessBlobGas != nil { - panic("unexpected excess blob gas value in clique") - } - if header.BlobGasUsed != nil { - panic("unexpected blob gas used value in clique") - } - if header.ParentBeaconRoot != nil { - panic("unexpected parent beacon root value in clique") - } - if err := rlp.Encode(w, enc); err != nil { - panic("can't encode: " + err.Error()) - } -} diff --git a/builder/consensus/clique/clique_test.go b/builder/consensus/clique/clique_test.go deleted file mode 100644 index 8ef8dbffa..000000000 --- a/builder/consensus/clique/clique_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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 clique - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -// This test case is a repro of an annoying bug that took us forever to catch. -// In Clique PoA networks (Görli, etc), consecutive blocks might have -// the same state root (no block subsidy, empty block). If a node crashes, the -// chain ends up losing the recent state and needs to regenerate it from blocks -// already in the database. The bug was that processing the block *prior* to an -// empty one **also completes** the empty one, ending up in a known-block error. -func TestReimportMirroredState(t *testing.T) { - // Initialize a Clique chain with a single signer - var ( - db = rawdb.NewMemoryDatabase() - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key.PublicKey) - engine = New(params.AllCliqueProtocolChanges.Clique, db) - signer = new(types.HomesteadSigner) - ) - genspec := &core.Genesis{ - Config: params.AllCliqueProtocolChanges, - ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal), - Alloc: map[common.Address]types.Account{ - addr: {Balance: big.NewInt(10000000000000000)}, - }, - BaseFee: big.NewInt(params.InitialBaseFee), - } - copy(genspec.ExtraData[extraVanity:], addr[:]) - - // Generate a batch of blocks, each properly signed - chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genspec, nil, engine, vm.Config{}, nil, nil) - defer chain.Stop() - - _, blocks, _ := core.GenerateChainWithGenesis(genspec, engine, 3, func(i int, block *core.BlockGen) { - // The chain maker doesn't have access to a chain, so the difficulty will be - // lets unset (nil). Set it here to the correct value. - block.SetDifficulty(diffInTurn) - - // We want to simulate an empty middle block, having the same state as the - // first one. The last is needs a state change again to force a reorg. - if i != 1 { - tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr), common.Address{0x00}, new(big.Int), params.TxGas, block.BaseFee(), nil), signer, key) - if err != nil { - panic(err) - } - block.AddTxWithChain(chain, tx) - } - }) - for i, block := range blocks { - header := block.Header() - if i > 0 { - header.ParentHash = blocks[i-1].Hash() - } - header.Extra = make([]byte, extraVanity+extraSeal) - header.Difficulty = diffInTurn - - sig, _ := crypto.Sign(SealHash(header).Bytes(), key) - copy(header.Extra[len(header.Extra)-extraSeal:], sig) - blocks[i] = block.WithSeal(header) - } - // Insert the first two blocks and make sure the chain is valid - db = rawdb.NewMemoryDatabase() - chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil) - defer chain.Stop() - - if _, err := chain.InsertChain(blocks[:2]); err != nil { - t.Fatalf("failed to insert initial blocks: %v", err) - } - if head := chain.CurrentBlock().Number.Uint64(); head != 2 { - t.Fatalf("chain head mismatch: have %d, want %d", head, 2) - } - - // Simulate a crash by creating a new chain on top of the database, without - // flushing the dirty states out. Insert the last block, triggering a sidechain - // reimport. - chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil) - defer chain.Stop() - - if _, err := chain.InsertChain(blocks[2:]); err != nil { - t.Fatalf("failed to insert final block: %v", err) - } - if head := chain.CurrentBlock().Number.Uint64(); head != 3 { - t.Fatalf("chain head mismatch: have %d, want %d", head, 3) - } -} - -func TestSealHash(t *testing.T) { - have := SealHash(&types.Header{ - Difficulty: new(big.Int), - Number: new(big.Int), - Extra: make([]byte, 32+65), - BaseFee: new(big.Int), - }) - want := common.HexToHash("0xbd3d1fa43fbc4c5bfcc91b179ec92e2861df3654de60468beb908ff805359e8f") - if have != want { - t.Errorf("have %x, want %x", have, want) - } -} diff --git a/builder/consensus/clique/snapshot.go b/builder/consensus/clique/snapshot.go deleted file mode 100644 index a97115121..000000000 --- a/builder/consensus/clique/snapshot.go +++ /dev/null @@ -1,322 +0,0 @@ -// 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 clique - -import ( - "bytes" - "encoding/json" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "golang.org/x/exp/slices" -) - -// Vote represents a single vote that an authorized signer made to modify the -// list of authorizations. -type Vote struct { - Signer common.Address `json:"signer"` // Authorized signer that cast this vote - Block uint64 `json:"block"` // Block number the vote was cast in (expire old votes) - Address common.Address `json:"address"` // Account being voted on to change its authorization - Authorize bool `json:"authorize"` // Whether to authorize or deauthorize the voted account -} - -// Tally is a simple vote tally to keep the current score of votes. Votes that -// go against the proposal aren't counted since it's equivalent to not voting. -type Tally struct { - Authorize bool `json:"authorize"` // Whether the vote is about authorizing or kicking someone - Votes int `json:"votes"` // Number of votes until now wanting to pass the proposal -} - -type sigLRU = lru.Cache[common.Hash, common.Address] - -// Snapshot is the state of the authorization voting at a given point in time. -type Snapshot struct { - config *params.CliqueConfig // Consensus engine parameters to fine tune behavior - sigcache *sigLRU // Cache of recent block signatures to speed up ecrecover - - Number uint64 `json:"number"` // Block number where the snapshot was created - Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - Signers map[common.Address]struct{} `json:"signers"` // Set of authorized signers at this moment - Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections - Votes []*Vote `json:"votes"` // List of votes cast in chronological order - Tally map[common.Address]Tally `json:"tally"` // Current vote tally to avoid recalculating -} - -// newSnapshot creates a new snapshot with the specified startup parameters. This -// method does not initialize the set of recent signers, so only ever use if for -// the genesis block. -func newSnapshot(config *params.CliqueConfig, sigcache *sigLRU, number uint64, hash common.Hash, signers []common.Address) *Snapshot { - snap := &Snapshot{ - config: config, - sigcache: sigcache, - Number: number, - Hash: hash, - Signers: make(map[common.Address]struct{}), - Recents: make(map[uint64]common.Address), - Tally: make(map[common.Address]Tally), - } - for _, signer := range signers { - snap.Signers[signer] = struct{}{} - } - return snap -} - -// loadSnapshot loads an existing snapshot from the database. -func loadSnapshot(config *params.CliqueConfig, sigcache *sigLRU, db ethdb.Database, hash common.Hash) (*Snapshot, error) { - blob, err := db.Get(append(rawdb.CliqueSnapshotPrefix, hash[:]...)) - if err != nil { - return nil, err - } - snap := new(Snapshot) - if err := json.Unmarshal(blob, snap); err != nil { - return nil, err - } - snap.config = config - snap.sigcache = sigcache - - return snap, nil -} - -// store inserts the snapshot into the database. -func (s *Snapshot) store(db ethdb.Database) error { - blob, err := json.Marshal(s) - if err != nil { - return err - } - return db.Put(append(rawdb.CliqueSnapshotPrefix, s.Hash[:]...), blob) -} - -// copy creates a deep copy of the snapshot, though not the individual votes. -func (s *Snapshot) copy() *Snapshot { - cpy := &Snapshot{ - config: s.config, - sigcache: s.sigcache, - Number: s.Number, - Hash: s.Hash, - Signers: make(map[common.Address]struct{}), - Recents: make(map[uint64]common.Address), - Votes: make([]*Vote, len(s.Votes)), - Tally: make(map[common.Address]Tally), - } - for signer := range s.Signers { - cpy.Signers[signer] = struct{}{} - } - for block, signer := range s.Recents { - cpy.Recents[block] = signer - } - for address, tally := range s.Tally { - cpy.Tally[address] = tally - } - copy(cpy.Votes, s.Votes) - - return cpy -} - -// validVote returns whether it makes sense to cast the specified vote in the -// given snapshot context (e.g. don't try to add an already authorized signer). -func (s *Snapshot) validVote(address common.Address, authorize bool) bool { - _, signer := s.Signers[address] - return (signer && !authorize) || (!signer && authorize) -} - -// cast adds a new vote into the tally. -func (s *Snapshot) cast(address common.Address, authorize bool) bool { - // Ensure the vote is meaningful - if !s.validVote(address, authorize) { - return false - } - // Cast the vote into an existing or new tally - if old, ok := s.Tally[address]; ok { - old.Votes++ - s.Tally[address] = old - } else { - s.Tally[address] = Tally{Authorize: authorize, Votes: 1} - } - return true -} - -// uncast removes a previously cast vote from the tally. -func (s *Snapshot) uncast(address common.Address, authorize bool) bool { - // If there's no tally, it's a dangling vote, just drop - tally, ok := s.Tally[address] - if !ok { - return false - } - // Ensure we only revert counted votes - if tally.Authorize != authorize { - return false - } - // Otherwise revert the vote - if tally.Votes > 1 { - tally.Votes-- - s.Tally[address] = tally - } else { - delete(s.Tally, address) - } - return true -} - -// apply creates a new authorization snapshot by applying the given headers to -// the original one. -func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { - // Allow passing in no headers for cleaner code - if len(headers) == 0 { - return s, nil - } - // Sanity check that the headers can be applied - for i := 0; i < len(headers)-1; i++ { - if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { - return nil, errInvalidVotingChain - } - } - if headers[0].Number.Uint64() != s.Number+1 { - return nil, errInvalidVotingChain - } - // Iterate through the headers and create a new snapshot - snap := s.copy() - - var ( - start = time.Now() - logged = time.Now() - ) - for i, header := range headers { - // Remove any votes on checkpoint blocks - number := header.Number.Uint64() - if number%s.config.Epoch == 0 { - snap.Votes = nil - snap.Tally = make(map[common.Address]Tally) - } - // Delete the oldest signer from the recent list to allow it signing again - if limit := uint64(len(snap.Signers)/2 + 1); number >= limit { - delete(snap.Recents, number-limit) - } - // Resolve the authorization key and check against signers - signer, err := ecrecover(header, s.sigcache) - if err != nil { - return nil, err - } - if _, ok := snap.Signers[signer]; !ok { - return nil, errUnauthorizedSigner - } - for _, recent := range snap.Recents { - if recent == signer { - return nil, errRecentlySigned - } - } - snap.Recents[number] = signer - - // Header authorized, discard any previous votes from the signer - for i, vote := range snap.Votes { - if vote.Signer == signer && vote.Address == header.Coinbase { - // Uncast the vote from the cached tally - snap.uncast(vote.Address, vote.Authorize) - - // Uncast the vote from the chronological list - snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - break // only one vote allowed - } - } - // Tally up the new vote from the signer - var authorize bool - switch { - case bytes.Equal(header.Nonce[:], nonceAuthVote): - authorize = true - case bytes.Equal(header.Nonce[:], nonceDropVote): - authorize = false - default: - return nil, errInvalidVote - } - if snap.cast(header.Coinbase, authorize) { - snap.Votes = append(snap.Votes, &Vote{ - Signer: signer, - Block: number, - Address: header.Coinbase, - Authorize: authorize, - }) - } - // If the vote passed, update the list of signers - if tally := snap.Tally[header.Coinbase]; tally.Votes > len(snap.Signers)/2 { - if tally.Authorize { - snap.Signers[header.Coinbase] = struct{}{} - } else { - delete(snap.Signers, header.Coinbase) - - // Signer list shrunk, delete any leftover recent caches - if limit := uint64(len(snap.Signers)/2 + 1); number >= limit { - delete(snap.Recents, number-limit) - } - // Discard any previous votes the deauthorized signer cast - for i := 0; i < len(snap.Votes); i++ { - if snap.Votes[i].Signer == header.Coinbase { - // Uncast the vote from the cached tally - snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize) - - // Uncast the vote from the chronological list - snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - - i-- - } - } - } - // Discard any previous votes around the just changed account - for i := 0; i < len(snap.Votes); i++ { - if snap.Votes[i].Address == header.Coinbase { - snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) - i-- - } - } - delete(snap.Tally, header.Coinbase) - } - // If we're taking too much time (ecrecover), notify the user once a while - if time.Since(logged) > 8*time.Second { - log.Info("Reconstructing voting history", "processed", i, "total", len(headers), "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - if time.Since(start) > 8*time.Second { - log.Info("Reconstructed voting history", "processed", len(headers), "elapsed", common.PrettyDuration(time.Since(start))) - } - snap.Number += uint64(len(headers)) - snap.Hash = headers[len(headers)-1].Hash() - - return snap, nil -} - -// signers retrieves the list of authorized signers in ascending order. -func (s *Snapshot) signers() []common.Address { - sigs := make([]common.Address, 0, len(s.Signers)) - for sig := range s.Signers { - sigs = append(sigs, sig) - } - slices.SortFunc(sigs, common.Address.Cmp) - return sigs -} - -// inturn returns if a signer at a given block height is in-turn or not. -func (s *Snapshot) inturn(number uint64, signer common.Address) bool { - signers, offset := s.signers(), 0 - for offset < len(signers) && signers[offset] != signer { - offset++ - } - return (number % uint64(len(signers))) == uint64(offset) -} diff --git a/builder/consensus/clique/snapshot_test.go b/builder/consensus/clique/snapshot_test.go deleted file mode 100644 index 26cebe008..000000000 --- a/builder/consensus/clique/snapshot_test.go +++ /dev/null @@ -1,508 +0,0 @@ -// 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 clique - -import ( - "bytes" - "crypto/ecdsa" - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "golang.org/x/exp/slices" -) - -// testerAccountPool is a pool to maintain currently active tester accounts, -// mapped from textual names used in the tests below to actual Ethereum private -// keys capable of signing transactions. -type testerAccountPool struct { - accounts map[string]*ecdsa.PrivateKey -} - -func newTesterAccountPool() *testerAccountPool { - return &testerAccountPool{ - accounts: make(map[string]*ecdsa.PrivateKey), - } -} - -// checkpoint creates a Clique checkpoint signer section from the provided list -// of authorized signers and embeds it into the provided header. -func (ap *testerAccountPool) checkpoint(header *types.Header, signers []string) { - auths := make([]common.Address, len(signers)) - for i, signer := range signers { - auths[i] = ap.address(signer) - } - slices.SortFunc(auths, common.Address.Cmp) - for i, auth := range auths { - copy(header.Extra[extraVanity+i*common.AddressLength:], auth.Bytes()) - } -} - -// address retrieves the Ethereum address of a tester account by label, creating -// a new account if no previous one exists yet. -func (ap *testerAccountPool) address(account string) common.Address { - // Return the zero account for non-addresses - if account == "" { - return common.Address{} - } - // Ensure we have a persistent key for the account - if ap.accounts[account] == nil { - ap.accounts[account], _ = crypto.GenerateKey() - } - // Resolve and return the Ethereum address - return crypto.PubkeyToAddress(ap.accounts[account].PublicKey) -} - -// sign calculates a Clique digital signature for the given block and embeds it -// back into the header. -func (ap *testerAccountPool) sign(header *types.Header, signer string) { - // Ensure we have a persistent key for the signer - if ap.accounts[signer] == nil { - ap.accounts[signer], _ = crypto.GenerateKey() - } - // Sign the header and embed the signature in extra data - sig, _ := crypto.Sign(SealHash(header).Bytes(), ap.accounts[signer]) - copy(header.Extra[len(header.Extra)-extraSeal:], sig) -} - -// testerVote represents a single block signed by a particular account, where -// the account may or may not have cast a Clique vote. -type testerVote struct { - signer string - voted string - auth bool - checkpoint []string - newbatch bool -} - -type cliqueTest struct { - epoch uint64 - signers []string - votes []testerVote - results []string - failure error -} - -// Tests that Clique signer voting is evaluated correctly for various simple and -// complex scenarios, as well as that a few special corner cases fail correctly. -func TestClique(t *testing.T) { - // Define the various voting scenarios to test - tests := []cliqueTest{ - { - // Single signer, no votes cast - signers: []string{"A"}, - votes: []testerVote{{signer: "A"}}, - results: []string{"A"}, - }, { - // Single signer, voting to add two others (only accept first, second needs 2 votes) - signers: []string{"A"}, - votes: []testerVote{ - {signer: "A", voted: "B", auth: true}, - {signer: "B"}, - {signer: "A", voted: "C", auth: true}, - }, - results: []string{"A", "B"}, - }, { - // Two signers, voting to add three others (only accept first two, third needs 3 votes already) - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: true}, - {signer: "B", voted: "C", auth: true}, - {signer: "A", voted: "D", auth: true}, - {signer: "B", voted: "D", auth: true}, - {signer: "C"}, - {signer: "A", voted: "E", auth: true}, - {signer: "B", voted: "E", auth: true}, - }, - results: []string{"A", "B", "C", "D"}, - }, { - // Single signer, dropping itself (weird, but one less cornercase by explicitly allowing this) - signers: []string{"A"}, - votes: []testerVote{ - {signer: "A", voted: "A", auth: false}, - }, - results: []string{}, - }, { - // Two signers, actually needing mutual consent to drop either of them (not fulfilled) - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "B", auth: false}, - }, - results: []string{"A", "B"}, - }, { - // Two signers, actually needing mutual consent to drop either of them (fulfilled) - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "B", auth: false}, - {signer: "B", voted: "B", auth: false}, - }, - results: []string{"A"}, - }, { - // Three signers, two of them deciding to drop the third - signers: []string{"A", "B", "C"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B", voted: "C", auth: false}, - }, - results: []string{"A", "B"}, - }, { - // Four signers, consensus of two not being enough to drop anyone - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B", voted: "C", auth: false}, - }, - results: []string{"A", "B", "C", "D"}, - }, { - // Four signers, consensus of three already being enough to drop someone - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "D", auth: false}, - {signer: "B", voted: "D", auth: false}, - {signer: "C", voted: "D", auth: false}, - }, - results: []string{"A", "B", "C"}, - }, { - // Authorizations are counted once per signer per target - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: true}, - {signer: "B"}, - {signer: "A", voted: "C", auth: true}, - {signer: "B"}, - {signer: "A", voted: "C", auth: true}, - }, - results: []string{"A", "B"}, - }, { - // Authorizing multiple accounts concurrently is permitted - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: true}, - {signer: "B"}, - {signer: "A", voted: "D", auth: true}, - {signer: "B"}, - {signer: "A"}, - {signer: "B", voted: "D", auth: true}, - {signer: "A"}, - {signer: "B", voted: "C", auth: true}, - }, - results: []string{"A", "B", "C", "D"}, - }, { - // Deauthorizations are counted once per signer per target - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "B", auth: false}, - {signer: "B"}, - {signer: "A", voted: "B", auth: false}, - {signer: "B"}, - {signer: "A", voted: "B", auth: false}, - }, - results: []string{"A", "B"}, - }, { - // Deauthorizing multiple accounts concurrently is permitted - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B"}, - {signer: "C"}, - {signer: "A", voted: "D", auth: false}, - {signer: "B"}, - {signer: "C"}, - {signer: "A"}, - {signer: "B", voted: "D", auth: false}, - {signer: "C", voted: "D", auth: false}, - {signer: "A"}, - {signer: "B", voted: "C", auth: false}, - }, - results: []string{"A", "B"}, - }, { - // Votes from deauthorized signers are discarded immediately (deauth votes) - signers: []string{"A", "B", "C"}, - votes: []testerVote{ - {signer: "C", voted: "B", auth: false}, - {signer: "A", voted: "C", auth: false}, - {signer: "B", voted: "C", auth: false}, - {signer: "A", voted: "B", auth: false}, - }, - results: []string{"A", "B"}, - }, { - // Votes from deauthorized signers are discarded immediately (auth votes) - signers: []string{"A", "B", "C"}, - votes: []testerVote{ - {signer: "C", voted: "D", auth: true}, - {signer: "A", voted: "C", auth: false}, - {signer: "B", voted: "C", auth: false}, - {signer: "A", voted: "D", auth: true}, - }, - results: []string{"A", "B"}, - }, { - // Cascading changes are not allowed, only the account being voted on may change - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B"}, - {signer: "C"}, - {signer: "A", voted: "D", auth: false}, - {signer: "B", voted: "C", auth: false}, - {signer: "C"}, - {signer: "A"}, - {signer: "B", voted: "D", auth: false}, - {signer: "C", voted: "D", auth: false}, - }, - results: []string{"A", "B", "C"}, - }, { - // Changes reaching consensus out of bounds (via a deauth) execute on touch - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B"}, - {signer: "C"}, - {signer: "A", voted: "D", auth: false}, - {signer: "B", voted: "C", auth: false}, - {signer: "C"}, - {signer: "A"}, - {signer: "B", voted: "D", auth: false}, - {signer: "C", voted: "D", auth: false}, - {signer: "A"}, - {signer: "C", voted: "C", auth: true}, - }, - results: []string{"A", "B"}, - }, { - // Changes reaching consensus out of bounds (via a deauth) may go out of consensus on first touch - signers: []string{"A", "B", "C", "D"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: false}, - {signer: "B"}, - {signer: "C"}, - {signer: "A", voted: "D", auth: false}, - {signer: "B", voted: "C", auth: false}, - {signer: "C"}, - {signer: "A"}, - {signer: "B", voted: "D", auth: false}, - {signer: "C", voted: "D", auth: false}, - {signer: "A"}, - {signer: "B", voted: "C", auth: true}, - }, - results: []string{"A", "B", "C"}, - }, { - // Ensure that pending votes don't survive authorization status changes. This - // corner case can only appear if a signer is quickly added, removed and then - // re-added (or the inverse), while one of the original voters dropped. If a - // past vote is left cached in the system somewhere, this will interfere with - // the final signer outcome. - signers: []string{"A", "B", "C", "D", "E"}, - votes: []testerVote{ - {signer: "A", voted: "F", auth: true}, // Authorize F, 3 votes needed - {signer: "B", voted: "F", auth: true}, - {signer: "C", voted: "F", auth: true}, - {signer: "D", voted: "F", auth: false}, // Deauthorize F, 4 votes needed (leave A's previous vote "unchanged") - {signer: "E", voted: "F", auth: false}, - {signer: "B", voted: "F", auth: false}, - {signer: "C", voted: "F", auth: false}, - {signer: "D", voted: "F", auth: true}, // Almost authorize F, 2/3 votes needed - {signer: "E", voted: "F", auth: true}, - {signer: "B", voted: "A", auth: false}, // Deauthorize A, 3 votes needed - {signer: "C", voted: "A", auth: false}, - {signer: "D", voted: "A", auth: false}, - {signer: "B", voted: "F", auth: true}, // Finish authorizing F, 3/3 votes needed - }, - results: []string{"B", "C", "D", "E", "F"}, - }, { - // Epoch transitions reset all votes to allow chain checkpointing - epoch: 3, - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A", voted: "C", auth: true}, - {signer: "B"}, - {signer: "A", checkpoint: []string{"A", "B"}}, - {signer: "B", voted: "C", auth: true}, - }, - results: []string{"A", "B"}, - }, { - // An unauthorized signer should not be able to sign blocks - signers: []string{"A"}, - votes: []testerVote{ - {signer: "B"}, - }, - failure: errUnauthorizedSigner, - }, { - // An authorized signer that signed recently should not be able to sign again - signers: []string{"A", "B"}, - votes: []testerVote{ - {signer: "A"}, - {signer: "A"}, - }, - failure: errRecentlySigned, - }, { - // Recent signatures should not reset on checkpoint blocks imported in a batch - epoch: 3, - signers: []string{"A", "B", "C"}, - votes: []testerVote{ - {signer: "A"}, - {signer: "B"}, - {signer: "A", checkpoint: []string{"A", "B", "C"}}, - {signer: "A"}, - }, - failure: errRecentlySigned, - }, { - // Recent signatures should not reset on checkpoint blocks imported in a new - // batch (https://github.com/ethereum/go-ethereum/issues/17593). Whilst this - // seems overly specific and weird, it was a Rinkeby consensus split. - epoch: 3, - signers: []string{"A", "B", "C"}, - votes: []testerVote{ - {signer: "A"}, - {signer: "B"}, - {signer: "A", checkpoint: []string{"A", "B", "C"}}, - {signer: "A", newbatch: true}, - }, - failure: errRecentlySigned, - }, - } - - // Run through the scenarios and test them - for i, tt := range tests { - t.Run(fmt.Sprint(i), tt.run) - } -} - -func (tt *cliqueTest) run(t *testing.T) { - // Create the account pool and generate the initial set of signers - accounts := newTesterAccountPool() - - signers := make([]common.Address, len(tt.signers)) - for j, signer := range tt.signers { - signers[j] = accounts.address(signer) - } - for j := 0; j < len(signers); j++ { - for k := j + 1; k < len(signers); k++ { - if bytes.Compare(signers[j][:], signers[k][:]) > 0 { - signers[j], signers[k] = signers[k], signers[j] - } - } - } - // Create the genesis block with the initial set of signers - genesis := &core.Genesis{ - ExtraData: make([]byte, extraVanity+common.AddressLength*len(signers)+extraSeal), - BaseFee: big.NewInt(params.InitialBaseFee), - } - for j, signer := range signers { - copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:]) - } - - // Assemble a chain of headers from the cast votes - config := *params.TestChainConfig - config.Clique = ¶ms.CliqueConfig{ - Period: 1, - Epoch: tt.epoch, - } - genesis.Config = &config - - engine := New(config.Clique, rawdb.NewMemoryDatabase()) - engine.fakeDiff = true - - _, blocks, _ := core.GenerateChainWithGenesis(genesis, engine, len(tt.votes), func(j int, gen *core.BlockGen) { - // Cast the vote contained in this block - gen.SetCoinbase(accounts.address(tt.votes[j].voted)) - if tt.votes[j].auth { - var nonce types.BlockNonce - copy(nonce[:], nonceAuthVote) - gen.SetNonce(nonce) - } - }) - // Iterate through the blocks and seal them individually - for j, block := range blocks { - // Get the header and prepare it for signing - header := block.Header() - if j > 0 { - header.ParentHash = blocks[j-1].Hash() - } - header.Extra = make([]byte, extraVanity+extraSeal) - if auths := tt.votes[j].checkpoint; auths != nil { - header.Extra = make([]byte, extraVanity+len(auths)*common.AddressLength+extraSeal) - accounts.checkpoint(header, auths) - } - header.Difficulty = diffInTurn // Ignored, we just need a valid number - - // Generate the signature, embed it into the header and the block - accounts.sign(header, tt.votes[j].signer) - blocks[j] = block.WithSeal(header) - } - // Split the blocks up into individual import batches (cornercase testing) - batches := [][]*types.Block{nil} - for j, block := range blocks { - if tt.votes[j].newbatch { - batches = append(batches, nil) - } - batches[len(batches)-1] = append(batches[len(batches)-1], block) - } - // Pass all the headers through clique and ensure tallying succeeds - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create test chain: %v", err) - } - defer chain.Stop() - - for j := 0; j < len(batches)-1; j++ { - if k, err := chain.InsertChain(batches[j]); err != nil { - t.Fatalf("failed to import batch %d, block %d: %v", j, k, err) - break - } - } - if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure { - t.Errorf("failure mismatch: have %v, want %v", err, tt.failure) - } - if tt.failure != nil { - return - } - - // No failure was produced or requested, generate the final voting snapshot - head := blocks[len(blocks)-1] - - snap, err := engine.snapshot(chain, head.NumberU64(), head.Hash(), nil) - if err != nil { - t.Fatalf("failed to retrieve voting snapshot: %v", err) - } - // Verify the final list of signers against the expected ones - signers = make([]common.Address, len(tt.results)) - for j, signer := range tt.results { - signers[j] = accounts.address(signer) - } - for j := 0; j < len(signers); j++ { - for k := j + 1; k < len(signers); k++ { - if bytes.Compare(signers[j][:], signers[k][:]) > 0 { - signers[j], signers[k] = signers[k], signers[j] - } - } - } - result := snap.signers() - if len(result) != len(signers) { - t.Fatalf("signers mismatch: have %x, want %x", result, signers) - } - for j := 0; j < len(result); j++ { - if !bytes.Equal(result[j][:], signers[j][:]) { - t.Fatalf("signer %d: signer mismatch: have %x, want %x", j, result[j], signers[j]) - } - } -} diff --git a/builder/consensus/consensus.go b/builder/consensus/consensus.go deleted file mode 100644 index 3a2c2d222..000000000 --- a/builder/consensus/consensus.go +++ /dev/null @@ -1,129 +0,0 @@ -// 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 consensus implements different Ethereum consensus engines. -package consensus - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -// ChainHeaderReader defines a small collection of methods needed to access the local -// blockchain during header verification. -type ChainHeaderReader interface { - // Config retrieves the blockchain's chain configuration. - Config() *params.ChainConfig - - // CurrentHeader retrieves the current header from the local chain. - CurrentHeader() *types.Header - - // GetHeader retrieves a block header from the database by hash and number. - GetHeader(hash common.Hash, number uint64) *types.Header - - // GetHeaderByNumber retrieves a block header from the database by number. - GetHeaderByNumber(number uint64) *types.Header - - // GetHeaderByHash retrieves a block header from the database by its hash. - GetHeaderByHash(hash common.Hash) *types.Header - - // GetTd retrieves the total difficulty from the database by hash and number. - GetTd(hash common.Hash, number uint64) *big.Int -} - -// ChainReader defines a small collection of methods needed to access the local -// blockchain during header and/or uncle verification. -type ChainReader interface { - ChainHeaderReader - - // GetBlock retrieves a block from the database by hash and number. - GetBlock(hash common.Hash, number uint64) *types.Block -} - -// Engine is an algorithm agnostic consensus engine. -type Engine interface { - // Author retrieves the Ethereum address of the account that minted the given - // block, which may be different from the header's coinbase if a consensus - // engine is based on signatures. - Author(header *types.Header) (common.Address, error) - - // VerifyHeader checks whether a header conforms to the consensus rules of a - // given engine. - VerifyHeader(chain ChainHeaderReader, header *types.Header) error - - // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers - // concurrently. The method returns a quit channel to abort the operations and - // a results channel to retrieve the async verifications (the order is that of - // the input slice). - VerifyHeaders(chain ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) - - // VerifyUncles verifies that the given block's uncles conform to the consensus - // rules of a given engine. - VerifyUncles(chain ChainReader, block *types.Block) error - - // Prepare initializes the consensus fields of a block header according to the - // rules of a particular engine. The changes are executed inline. - Prepare(chain ChainHeaderReader, header *types.Header) error - - // Finalize runs any post-transaction state modifications (e.g. block rewards - // or process withdrawals) but does not assemble the block. - // - // Note: The state database might be updated to reflect any consensus rules - // that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, withdrawals []*types.Withdrawal) - - // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block - // rewards or process withdrawals) and assembles the final block. - // - // Note: The block header and state database might be updated to reflect any - // consensus rules that happen at finalization (e.g. block rewards). - FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) - - // Seal generates a new sealing request for the given input block and pushes - // the result into the given channel. - // - // Note, the method returns immediately and will send the result async. More - // than one result may also be returned depending on the consensus algorithm. - Seal(chain ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error - - // SealHash returns the hash of a block prior to it being sealed. - SealHash(header *types.Header) common.Hash - - // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty - // that a new block should have. - CalcDifficulty(chain ChainHeaderReader, time uint64, parent *types.Header) *big.Int - - // APIs returns the RPC APIs this consensus engine provides. - APIs(chain ChainHeaderReader) []rpc.API - - // Close terminates any background threads maintained by the consensus engine. - Close() error -} - -// PoW is a consensus engine based on proof-of-work. -type PoW interface { - Engine - - // Hashrate returns the current mining hashrate of a PoW consensus engine. - Hashrate() float64 -} diff --git a/builder/consensus/errors.go b/builder/consensus/errors.go deleted file mode 100644 index d508b6580..000000000 --- a/builder/consensus/errors.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 consensus - -import "errors" - -var ( - // ErrUnknownAncestor is returned when validating a block requires an ancestor - // that is unknown. - ErrUnknownAncestor = errors.New("unknown ancestor") - - // ErrPrunedAncestor is returned when validating a block requires an ancestor - // that is known, but the state of which is not available. - ErrPrunedAncestor = errors.New("pruned ancestor") - - // ErrFutureBlock is returned when a block's timestamp is in the future according - // to the current node. - ErrFutureBlock = errors.New("block in the future") - - // ErrInvalidNumber is returned if a block's number doesn't equal its parent's - // plus one. - ErrInvalidNumber = errors.New("invalid block number") - - // ErrInvalidTerminalBlock is returned if a block is invalid wrt. the terminal - // total difficulty. - ErrInvalidTerminalBlock = errors.New("invalid terminal block") -) diff --git a/builder/consensus/ethash/consensus.go b/builder/consensus/ethash/consensus.go deleted file mode 100644 index c2936fd4b..000000000 --- a/builder/consensus/ethash/consensus.go +++ /dev/null @@ -1,598 +0,0 @@ -// 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 ethash - -import ( - "errors" - "fmt" - "math/big" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" -) - -// Ethash proof-of-work protocol constants. -var ( - FrontierBlockReward = uint256.NewInt(5e+18) // Block reward in wei for successfully mining a block - ByzantiumBlockReward = uint256.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium - ConstantinopleBlockReward = uint256.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople - maxUncles = 2 // Maximum number of uncles allowed in a single block - allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks - - // calcDifficultyEip5133 is the difficulty adjustment algorithm as specified by EIP 5133. - // It offsets the bomb a total of 11.4M blocks. - // Specification EIP-5133: https://eips.ethereum.org/EIPS/eip-5133 - calcDifficultyEip5133 = makeDifficultyCalculator(big.NewInt(11_400_000)) - - // calcDifficultyEip4345 is the difficulty adjustment algorithm as specified by EIP 4345. - // It offsets the bomb a total of 10.7M blocks. - // Specification EIP-4345: https://eips.ethereum.org/EIPS/eip-4345 - calcDifficultyEip4345 = makeDifficultyCalculator(big.NewInt(10_700_000)) - - // calcDifficultyEip3554 is the difficulty adjustment algorithm as specified by EIP 3554. - // It offsets the bomb a total of 9.7M blocks. - // Specification EIP-3554: https://eips.ethereum.org/EIPS/eip-3554 - calcDifficultyEip3554 = makeDifficultyCalculator(big.NewInt(9700000)) - - // calcDifficultyEip2384 is the difficulty adjustment algorithm as specified by EIP 2384. - // It offsets the bomb 4M blocks from Constantinople, so in total 9M blocks. - // Specification EIP-2384: https://eips.ethereum.org/EIPS/eip-2384 - calcDifficultyEip2384 = makeDifficultyCalculator(big.NewInt(9000000)) - - // calcDifficultyConstantinople is the difficulty adjustment algorithm for Constantinople. - // It returns the difficulty that a new block should have when created at time given the - // parent block's time and difficulty. The calculation uses the Byzantium rules, but with - // bomb offset 5M. - // Specification EIP-1234: https://eips.ethereum.org/EIPS/eip-1234 - calcDifficultyConstantinople = makeDifficultyCalculator(big.NewInt(5000000)) - - // calcDifficultyByzantium is the difficulty adjustment algorithm. It returns - // the difficulty that a new block should have when created at time given the - // parent block's time and difficulty. The calculation uses the Byzantium rules. - // Specification EIP-649: https://eips.ethereum.org/EIPS/eip-649 - calcDifficultyByzantium = makeDifficultyCalculator(big.NewInt(3000000)) -) - -// Various error messages to mark blocks invalid. These should be private to -// prevent engine specific errors from being referenced in the remainder of the -// codebase, inherently breaking if the engine is swapped out. Please put common -// error types into the consensus package. -var ( - errOlderBlockTime = errors.New("timestamp older than parent") - errTooManyUncles = errors.New("too many uncles") - errDuplicateUncle = errors.New("duplicate uncle") - errUncleIsAncestor = errors.New("uncle is ancestor") - errDanglingUncle = errors.New("uncle's parent is not ancestor") -) - -// Author implements consensus.Engine, returning the header's coinbase as the -// proof-of-work verified author of the block. -func (ethash *Ethash) Author(header *types.Header) (common.Address, error) { - return header.Coinbase, nil -} - -// VerifyHeader checks whether a header conforms to the consensus rules of the -// stock Ethereum ethash engine. -func (ethash *Ethash) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error { - // Short circuit if the header is known, or its parent not - number := header.Number.Uint64() - if chain.GetHeader(header.Hash(), number) != nil { - return nil - } - parent := chain.GetHeader(header.ParentHash, number-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } - // Sanity checks passed, do a proper verification - return ethash.verifyHeader(chain, header, parent, false, time.Now().Unix()) -} - -// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers -// concurrently. The method returns a quit channel to abort the operations and -// a results channel to retrieve the async verifications. -func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) { - // If we're running a full engine faking, accept any input as valid - if ethash.fakeFull || len(headers) == 0 { - abort, results := make(chan struct{}), make(chan error, len(headers)) - for i := 0; i < len(headers); i++ { - results <- nil - } - return abort, results - } - abort := make(chan struct{}) - results := make(chan error, len(headers)) - unixNow := time.Now().Unix() - - go func() { - for i, header := range headers { - var parent *types.Header - if i == 0 { - parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) - } else if headers[i-1].Hash() == headers[i].ParentHash { - parent = headers[i-1] - } - var err error - if parent == nil { - err = consensus.ErrUnknownAncestor - } else { - err = ethash.verifyHeader(chain, header, parent, false, unixNow) - } - select { - case <-abort: - return - case results <- err: - } - } - }() - return abort, results -} - -// VerifyUncles verifies that the given block's uncles conform to the consensus -// rules of the stock Ethereum ethash engine. -func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { - // If we're running a full engine faking, accept any input as valid - if ethash.fakeFull { - return nil - } - // Verify that there are at most 2 uncles included in this block - if len(block.Uncles()) > maxUncles { - return errTooManyUncles - } - if len(block.Uncles()) == 0 { - return nil - } - // Gather the set of past uncles and ancestors - uncles, ancestors := mapset.NewSet[common.Hash](), make(map[common.Hash]*types.Header) - - number, parent := block.NumberU64()-1, block.ParentHash() - for i := 0; i < 7; i++ { - ancestorHeader := chain.GetHeader(parent, number) - if ancestorHeader == nil { - break - } - ancestors[parent] = ancestorHeader - // If the ancestor doesn't have any uncles, we don't have to iterate them - if ancestorHeader.UncleHash != types.EmptyUncleHash { - // Need to add those uncles to the banned list too - ancestor := chain.GetBlock(parent, number) - if ancestor == nil { - break - } - for _, uncle := range ancestor.Uncles() { - uncles.Add(uncle.Hash()) - } - } - parent, number = ancestorHeader.ParentHash, number-1 - } - ancestors[block.Hash()] = block.Header() - uncles.Add(block.Hash()) - - // Verify each of the uncles that it's recent, but not an ancestor - for _, uncle := range block.Uncles() { - // Make sure every uncle is rewarded only once - hash := uncle.Hash() - if uncles.Contains(hash) { - return errDuplicateUncle - } - uncles.Add(hash) - - // Make sure the uncle has a valid ancestry - if ancestors[hash] != nil { - return errUncleIsAncestor - } - if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { - return errDanglingUncle - } - if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, time.Now().Unix()); err != nil { - return err - } - } - return nil -} - -// verifyHeader checks whether a header conforms to the consensus rules of the -// stock Ethereum ethash engine. -// See YP section 4.3.4. "Block Header Validity" -func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, unixNow int64) error { - // Ensure that the header's extra-data section is of a reasonable size - if uint64(len(header.Extra)) > params.MaximumExtraDataSize { - return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) - } - // Verify the header's timestamp - if !uncle { - if header.Time > uint64(unixNow+allowedFutureBlockTimeSeconds) { - return consensus.ErrFutureBlock - } - } - if header.Time <= parent.Time { - return errOlderBlockTime - } - // Verify the block's difficulty based on its timestamp and parent's difficulty - expected := ethash.CalcDifficulty(chain, header.Time, parent) - - if expected.Cmp(header.Difficulty) != 0 { - return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) - } - // Verify that the gas limit is <= 2^63-1 - if header.GasLimit > params.MaxGasLimit { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) - } - // Verify that the gasUsed is <= gasLimit - if header.GasUsed > header.GasLimit { - return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) - } - // Verify the block's gas usage and (if applicable) verify the base fee. - if !chain.Config().IsLondon(header.Number) { - // Verify BaseFee not present before EIP-1559 fork. - if header.BaseFee != nil { - return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) - } - if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { - return err - } - } else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { - // Verify the header's EIP-1559 attributes. - return err - } - // Verify that the block number is parent's +1 - if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { - return consensus.ErrInvalidNumber - } - if chain.Config().IsShanghai(header.Number, header.Time) { - return errors.New("ethash does not support shanghai fork") - } - // Verify the non-existence of withdrawalsHash. - if header.WithdrawalsHash != nil { - return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) - } - if chain.Config().IsCancun(header.Number, header.Time) { - return errors.New("ethash does not support cancun fork") - } - // Verify the non-existence of cancun-specific header fields - switch { - case header.ExcessBlobGas != nil: - return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) - case header.BlobGasUsed != nil: - return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - case header.ParentBeaconRoot != nil: - return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) - } - // Add some fake checks for tests - if ethash.fakeDelay != nil { - time.Sleep(*ethash.fakeDelay) - } - if ethash.fakeFail != nil && *ethash.fakeFail == header.Number.Uint64() { - return errors.New("invalid tester pow") - } - // If all checks passed, validate any special fields for hard forks - if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { - return err - } - return nil -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns -// the difficulty that a new block should have when created at time -// given the parent block's time and difficulty. -func (ethash *Ethash) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { - return CalcDifficulty(chain.Config(), time, parent) -} - -// CalcDifficulty is the difficulty adjustment algorithm. It returns -// the difficulty that a new block should have when created at time -// given the parent block's time and difficulty. -func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { - next := new(big.Int).Add(parent.Number, big1) - switch { - case config.IsGrayGlacier(next): - return calcDifficultyEip5133(time, parent) - case config.IsArrowGlacier(next): - return calcDifficultyEip4345(time, parent) - case config.IsLondon(next): - return calcDifficultyEip3554(time, parent) - case config.IsMuirGlacier(next): - return calcDifficultyEip2384(time, parent) - case config.IsConstantinople(next): - return calcDifficultyConstantinople(time, parent) - case config.IsByzantium(next): - return calcDifficultyByzantium(time, parent) - case config.IsHomestead(next): - return calcDifficultyHomestead(time, parent) - default: - return calcDifficultyFrontier(time, parent) - } -} - -// Some weird constants to avoid constant memory allocs for them. -var ( - expDiffPeriod = big.NewInt(100000) - big1 = big.NewInt(1) - big2 = big.NewInt(2) - big9 = big.NewInt(9) - big10 = big.NewInt(10) - bigMinus99 = big.NewInt(-99) -) - -// makeDifficultyCalculator creates a difficultyCalculator with the given bomb-delay. -// the difficulty is calculated with Byzantium rules, which differs from Homestead in -// how uncles affect the calculation -func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { - // Note, the calculations below looks at the parent number, which is 1 below - // the block number. Thus we remove one from the delay given - bombDelayFromParent := new(big.Int).Sub(bombDelay, big1) - return func(time uint64, parent *types.Header) *big.Int { - // https://github.com/ethereum/EIPs/issues/100. - // algorithm: - // diff = (parent_diff + - // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - // ) + 2^(periodCount - 2) - - bigTime := new(big.Int).SetUint64(time) - bigParentTime := new(big.Int).SetUint64(parent.Time) - - // holds intermediate values to make the algo easier to read & audit - x := new(big.Int) - y := new(big.Int) - - // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9 - x.Sub(bigTime, bigParentTime) - x.Div(x, big9) - if parent.UncleHash == types.EmptyUncleHash { - x.Sub(big1, x) - } else { - x.Sub(big2, x) - } - // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) - if x.Cmp(bigMinus99) < 0 { - x.Set(bigMinus99) - } - // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - y.Div(parent.Difficulty, params.DifficultyBoundDivisor) - x.Mul(y, x) - x.Add(parent.Difficulty, x) - - // minimum difficulty can ever be (before exponential factor) - if x.Cmp(params.MinimumDifficulty) < 0 { - x.Set(params.MinimumDifficulty) - } - // calculate a fake block number for the ice-age delay - // Specification: https://eips.ethereum.org/EIPS/eip-1234 - fakeBlockNumber := new(big.Int) - if parent.Number.Cmp(bombDelayFromParent) >= 0 { - fakeBlockNumber = fakeBlockNumber.Sub(parent.Number, bombDelayFromParent) - } - // for the exponential factor - periodCount := fakeBlockNumber - periodCount.Div(periodCount, expDiffPeriod) - - // the exponential factor, commonly referred to as "the bomb" - // diff = diff + 2^(periodCount - 2) - if periodCount.Cmp(big1) > 0 { - y.Sub(periodCount, big2) - y.Exp(big2, y, nil) - x.Add(x, y) - } - return x - } -} - -// calcDifficultyHomestead is the difficulty adjustment algorithm. It returns -// the difficulty that a new block should have when created at time given the -// parent block's time and difficulty. The calculation uses the Homestead rules. -func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md - // algorithm: - // diff = (parent_diff + - // (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) - // ) + 2^(periodCount - 2) - - bigTime := new(big.Int).SetUint64(time) - bigParentTime := new(big.Int).SetUint64(parent.Time) - - // holds intermediate values to make the algo easier to read & audit - x := new(big.Int) - y := new(big.Int) - - // 1 - (block_timestamp - parent_timestamp) // 10 - x.Sub(bigTime, bigParentTime) - x.Div(x, big10) - x.Sub(big1, x) - - // max(1 - (block_timestamp - parent_timestamp) // 10, -99) - if x.Cmp(bigMinus99) < 0 { - x.Set(bigMinus99) - } - // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) - y.Div(parent.Difficulty, params.DifficultyBoundDivisor) - x.Mul(y, x) - x.Add(parent.Difficulty, x) - - // minimum difficulty can ever be (before exponential factor) - if x.Cmp(params.MinimumDifficulty) < 0 { - x.Set(params.MinimumDifficulty) - } - // for the exponential factor - periodCount := new(big.Int).Add(parent.Number, big1) - periodCount.Div(periodCount, expDiffPeriod) - - // the exponential factor, commonly referred to as "the bomb" - // diff = diff + 2^(periodCount - 2) - if periodCount.Cmp(big1) > 0 { - y.Sub(periodCount, big2) - y.Exp(big2, y, nil) - x.Add(x, y) - } - return x -} - -// calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the -// difficulty that a new block should have when created at time given the parent -// block's time and difficulty. The calculation uses the Frontier rules. -func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { - diff := new(big.Int) - adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor) - bigTime := new(big.Int) - bigParentTime := new(big.Int) - - bigTime.SetUint64(time) - bigParentTime.SetUint64(parent.Time) - - if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 { - diff.Add(parent.Difficulty, adjust) - } else { - diff.Sub(parent.Difficulty, adjust) - } - if diff.Cmp(params.MinimumDifficulty) < 0 { - diff.Set(params.MinimumDifficulty) - } - - periodCount := new(big.Int).Add(parent.Number, big1) - periodCount.Div(periodCount, expDiffPeriod) - if periodCount.Cmp(big1) > 0 { - // diff = diff + 2^(periodCount - 2) - expDiff := periodCount.Sub(periodCount, big2) - expDiff.Exp(big2, expDiff, nil) - diff.Add(diff, expDiff) - diff = math.BigMax(diff, params.MinimumDifficulty) - } - return diff -} - -// Exported for fuzzing -var FrontierDifficultyCalculator = calcDifficultyFrontier -var HomesteadDifficultyCalculator = calcDifficultyHomestead -var DynamicDifficultyCalculator = makeDifficultyCalculator - -// Prepare implements consensus.Engine, initializing the difficulty field of a -// header to conform to the ethash protocol. The changes are done inline. -func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { - parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) - if parent == nil { - return consensus.ErrUnknownAncestor - } - header.Difficulty = ethash.CalcDifficulty(chain, header.Time, parent) - return nil -} - -// Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { - // Accumulate any block and uncle rewards - accumulateRewards(chain.Config(), state, header, uncles) -} - -// FinalizeAndAssemble implements consensus.Engine, accumulating the block and -// uncle rewards, setting the final state and assembling the block. -func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { - if len(withdrawals) > 0 { - return nil, errors.New("ethash does not support withdrawals") - } - // Finalize block - ethash.Finalize(chain, header, state, txs, uncles, nil) - - // Assign the final state root to header. - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - - // Header seems complete, assemble into a block and return - return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil -} - -// SealHash returns the hash of a block prior to it being sealed. -func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - - enc := []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra, - } - if header.BaseFee != nil { - enc = append(enc, header.BaseFee) - } - if header.WithdrawalsHash != nil { - panic("withdrawal hash set on ethash") - } - if header.ExcessBlobGas != nil { - panic("excess blob gas set on ethash") - } - if header.BlobGasUsed != nil { - panic("blob gas used set on ethash") - } - if header.ParentBeaconRoot != nil { - panic("parent beacon root set on ethash") - } - rlp.Encode(hasher, enc) - hasher.Sum(hash[:0]) - return hash -} - -// Some weird constants to avoid constant memory allocs for them. -var ( - u256_8 = uint256.NewInt(8) - u256_32 = uint256.NewInt(32) -) - -// AccumulateRewards credits the coinbase of the given block with the mining -// reward. The total reward consists of the static block reward and rewards for -// included uncles. The coinbase of each uncle block is also rewarded. -func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { - // Select the correct block reward based on chain progression - blockReward := FrontierBlockReward - if config.IsByzantium(header.Number) { - blockReward = ByzantiumBlockReward - } - if config.IsConstantinople(header.Number) { - blockReward = ConstantinopleBlockReward - } - // Accumulate the rewards for the miner and any included uncles - reward := new(uint256.Int).Set(blockReward) - r := new(uint256.Int) - hNum, _ := uint256.FromBig(header.Number) - for _, uncle := range uncles { - uNum, _ := uint256.FromBig(uncle.Number) - r.AddUint64(uNum, 8) - r.Sub(r, hNum) - r.Mul(r, blockReward) - r.Div(r, u256_8) - state.AddBalance(uncle.Coinbase, r) - - r.Div(blockReward, u256_32) - reward.Add(reward, r) - } - state.AddBalance(header.Coinbase, reward) -} diff --git a/builder/consensus/ethash/consensus_test.go b/builder/consensus/ethash/consensus_test.go deleted file mode 100644 index e3793cd1b..000000000 --- a/builder/consensus/ethash/consensus_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// 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 ethash - -import ( - crand "crypto/rand" - "encoding/binary" - "encoding/json" - "math/big" - "math/rand" - "os" - "path/filepath" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -type diffTest struct { - ParentTimestamp uint64 - ParentDifficulty *big.Int - CurrentTimestamp uint64 - CurrentBlocknumber *big.Int - CurrentDifficulty *big.Int -} - -func (d *diffTest) UnmarshalJSON(b []byte) (err error) { - var ext struct { - ParentTimestamp string - ParentDifficulty string - CurrentTimestamp string - CurrentBlocknumber string - CurrentDifficulty string - } - if err := json.Unmarshal(b, &ext); err != nil { - return err - } - - d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp) - d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty) - d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp) - d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber) - d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty) - - return nil -} - -func TestCalcDifficulty(t *testing.T) { - file, err := os.Open(filepath.Join("..", "..", "tests", "testdata", "BasicTests", "difficulty.json")) - if err != nil { - t.Skip(err) - } - defer file.Close() - - tests := make(map[string]diffTest) - err = json.NewDecoder(file).Decode(&tests) - if err != nil { - t.Fatal(err) - } - - config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1150000)} - - for name, test := range tests { - number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1)) - diff := CalcDifficulty(config, test.CurrentTimestamp, &types.Header{ - Number: number, - Time: test.ParentTimestamp, - Difficulty: test.ParentDifficulty, - }) - if diff.Cmp(test.CurrentDifficulty) != 0 { - t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff) - } - } -} - -func randSlice(min, max uint32) []byte { - var b = make([]byte, 4) - crand.Read(b) - a := binary.LittleEndian.Uint32(b) - size := min + a%(max-min) - out := make([]byte, size) - crand.Read(out) - return out -} - -func TestDifficultyCalculators(t *testing.T) { - for i := 0; i < 5000; i++ { - // 1 to 300 seconds diff - var timeDelta = uint64(1 + rand.Uint32()%3000) - diffBig := new(big.Int).SetBytes(randSlice(2, 10)) - if diffBig.Cmp(params.MinimumDifficulty) < 0 { - diffBig.Set(params.MinimumDifficulty) - } - //rand.Read(difficulty) - header := &types.Header{ - Difficulty: diffBig, - Number: new(big.Int).SetUint64(rand.Uint64() % 50_000_000), - Time: rand.Uint64() - timeDelta, - } - if rand.Uint32()&1 == 0 { - header.UncleHash = types.EmptyUncleHash - } - bombDelay := new(big.Int).SetUint64(rand.Uint64() % 50_000_000) - for i, pair := range []struct { - bigFn func(time uint64, parent *types.Header) *big.Int - u256Fn func(time uint64, parent *types.Header) *big.Int - }{ - {FrontierDifficultyCalculator, CalcDifficultyFrontierU256}, - {HomesteadDifficultyCalculator, CalcDifficultyHomesteadU256}, - {DynamicDifficultyCalculator(bombDelay), MakeDifficultyCalculatorU256(bombDelay)}, - } { - time := header.Time + timeDelta - want := pair.bigFn(time, header) - have := pair.u256Fn(time, header) - if want.BitLen() > 256 { - continue - } - if want.Cmp(have) != 0 { - t.Fatalf("pair %d: want %x have %x\nparent.Number: %x\np.Time: %x\nc.Time: %x\nBombdelay: %v\n", i, want, have, - header.Number, header.Time, time, bombDelay) - } - } - } -} - -func BenchmarkDifficultyCalculator(b *testing.B) { - x1 := makeDifficultyCalculator(big.NewInt(1000000)) - x2 := MakeDifficultyCalculatorU256(big.NewInt(1000000)) - h := &types.Header{ - ParentHash: common.Hash{}, - UncleHash: types.EmptyUncleHash, - Difficulty: big.NewInt(0xffffff), - Number: big.NewInt(500000), - Time: 1000000, - } - b.Run("big-frontier", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - calcDifficultyFrontier(1000014, h) - } - }) - b.Run("u256-frontier", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - CalcDifficultyFrontierU256(1000014, h) - } - }) - b.Run("big-homestead", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - calcDifficultyHomestead(1000014, h) - } - }) - b.Run("u256-homestead", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - CalcDifficultyHomesteadU256(1000014, h) - } - }) - b.Run("big-generic", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - x1(1000014, h) - } - }) - b.Run("u256-generic", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - x2(1000014, h) - } - }) -} diff --git a/builder/consensus/ethash/difficulty.go b/builder/consensus/ethash/difficulty.go deleted file mode 100644 index 66a18059c..000000000 --- a/builder/consensus/ethash/difficulty.go +++ /dev/null @@ -1,191 +0,0 @@ -// 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 ethash - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/holiman/uint256" -) - -const ( - // frontierDurationLimit is for Frontier: - // The decision boundary on the blocktime duration used to determine - // whether difficulty should go up or down. - frontierDurationLimit = 13 - // minimumDifficulty The minimum that the difficulty may ever be. - minimumDifficulty = 131072 - // expDiffPeriod is the exponential difficulty period - expDiffPeriodUint = 100000 - // difficultyBoundDivisorBitShift is the bound divisor of the difficulty (2048), - // This constant is the right-shifts to use for the division. - difficultyBoundDivisor = 11 -) - -// CalcDifficultyFrontierU256 is the difficulty adjustment algorithm. It returns the -// difficulty that a new block should have when created at time given the parent -// block's time and difficulty. The calculation uses the Frontier rules. -func CalcDifficultyFrontierU256(time uint64, parent *types.Header) *big.Int { - /* - Algorithm - block_diff = pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) + int(2^((num // 100000) - 2)) - - Where: - - pdiff = parent.difficulty - - ptime = parent.time - - time = block.timestamp - - num = block.number - */ - - pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff - adjust := pDiff.Clone() - adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 - - if time-parent.Time < frontierDurationLimit { - pDiff.Add(pDiff, adjust) - } else { - pDiff.Sub(pDiff, adjust) - } - if pDiff.LtUint64(minimumDifficulty) { - pDiff.SetUint64(minimumDifficulty) - } - // 'pdiff' now contains: - // pdiff + pdiff / 2048 * (1 if time - ptime < 13 else -1) - - if periodCount := (parent.Number.Uint64() + 1) / expDiffPeriodUint; periodCount > 1 { - // diff = diff + 2^(periodCount - 2) - expDiff := adjust.SetOne() - expDiff.Lsh(expDiff, uint(periodCount-2)) // expdiff: 2 ^ (periodCount -2) - pDiff.Add(pDiff, expDiff) - } - return pDiff.ToBig() -} - -// CalcDifficultyHomesteadU256 is the difficulty adjustment algorithm. It returns -// the difficulty that a new block should have when created at time given the -// parent block's time and difficulty. The calculation uses the Homestead rules. -func CalcDifficultyHomesteadU256(time uint64, parent *types.Header) *big.Int { - /* - https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md - Algorithm: - block_diff = pdiff + pdiff / 2048 * max(1 - (time - ptime) / 10, -99) + 2 ^ int((num / 100000) - 2)) - - Our modification, to use unsigned ints: - block_diff = pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) + 2 ^ int((num / 100000) - 2)) - - Where: - - pdiff = parent.difficulty - - ptime = parent.time - - time = block.timestamp - - num = block.number - */ - - pDiff, _ := uint256.FromBig(parent.Difficulty) // pDiff: pdiff - adjust := pDiff.Clone() - adjust.Rsh(adjust, difficultyBoundDivisor) // adjust: pDiff / 2048 - - x := (time - parent.Time) / 10 // (time - ptime) / 10) - var neg = true - if x == 0 { - x = 1 - neg = false - } else if x >= 100 { - x = 99 - } else { - x = x - 1 - } - z := new(uint256.Int).SetUint64(x) - adjust.Mul(adjust, z) // adjust: (pdiff / 2048) * max((time - ptime) / 10 - 1, 99) - if neg { - pDiff.Sub(pDiff, adjust) // pdiff - pdiff / 2048 * max((time - ptime) / 10 - 1, 99) - } else { - pDiff.Add(pDiff, adjust) // pdiff + pdiff / 2048 * max((time - ptime) / 10 - 1, 99) - } - if pDiff.LtUint64(minimumDifficulty) { - pDiff.SetUint64(minimumDifficulty) - } - // for the exponential factor, a.k.a "the bomb" - // diff = diff + 2^(periodCount - 2) - if periodCount := (1 + parent.Number.Uint64()) / expDiffPeriodUint; periodCount > 1 { - expFactor := adjust.Lsh(adjust.SetOne(), uint(periodCount-2)) - pDiff.Add(pDiff, expFactor) - } - return pDiff.ToBig() -} - -// MakeDifficultyCalculatorU256 creates a difficultyCalculator with the given bomb-delay. -// the difficulty is calculated with Byzantium rules, which differs from Homestead in -// how uncles affect the calculation -func MakeDifficultyCalculatorU256(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { - // Note, the calculations below looks at the parent number, which is 1 below - // the block number. Thus we remove one from the delay given - bombDelayFromParent := bombDelay.Uint64() - 1 - return func(time uint64, parent *types.Header) *big.Int { - /* - https://github.com/ethereum/EIPs/issues/100 - pDiff = parent.difficulty - BLOCK_DIFF_FACTOR = 9 - a = pDiff + (pDiff // BLOCK_DIFF_FACTOR) * adj_factor - b = min(parent.difficulty, MIN_DIFF) - child_diff = max(a,b ) - */ - x := (time - parent.Time) / 9 // (block_timestamp - parent_timestamp) // 9 - c := uint64(1) // if parent.unclehash == emptyUncleHashHash - if parent.UncleHash != types.EmptyUncleHash { - c = 2 - } - xNeg := x >= c - if xNeg { - // x is now _negative_ adjustment factor - x = x - c // - ( (t-p)/p -( 2 or 1) ) - } else { - x = c - x // (2 or 1) - (t-p)/9 - } - if x > 99 { - x = 99 // max(x, 99) - } - // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - y := new(uint256.Int) - y.SetFromBig(parent.Difficulty) // y: p_diff - pDiff := y.Clone() // pdiff: p_diff - z := new(uint256.Int).SetUint64(x) //z : +-adj_factor (either pos or negative) - y.Rsh(y, difficultyBoundDivisor) // y: p__diff / 2048 - z.Mul(y, z) // z: (p_diff / 2048 ) * (+- adj_factor) - - if xNeg { - y.Sub(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor - } else { - y.Add(pDiff, z) // y: parent_diff + parent_diff/2048 * adjustment_factor - } - // minimum difficulty can ever be (before exponential factor) - if y.LtUint64(minimumDifficulty) { - y.SetUint64(minimumDifficulty) - } - // calculate a fake block number for the ice-age delay - // Specification: https://eips.ethereum.org/EIPS/eip-1234 - var pNum = parent.Number.Uint64() - if pNum >= bombDelayFromParent { - if fakeBlockNumber := pNum - bombDelayFromParent; fakeBlockNumber >= 2*expDiffPeriodUint { - z.SetOne() - z.Lsh(z, uint(fakeBlockNumber/expDiffPeriodUint-2)) - y.Add(z, y) - } - } - return y.ToBig() - } -} diff --git a/builder/consensus/ethash/ethash.go b/builder/consensus/ethash/ethash.go deleted file mode 100644 index f37ec2605..000000000 --- a/builder/consensus/ethash/ethash.go +++ /dev/null @@ -1,85 +0,0 @@ -// 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 ethash implements the ethash proof-of-work consensus engine. -package ethash - -import ( - "time" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" -) - -// Ethash is a consensus engine based on proof-of-work implementing the ethash -// algorithm. -type Ethash struct { - fakeFail *uint64 // Block number which fails PoW check even in fake mode - fakeDelay *time.Duration // Time delay to sleep for before returning from verify - fakeFull bool // Accepts everything as valid -} - -// NewFaker creates an ethash consensus engine with a fake PoW scheme that accepts -// all blocks' seal as valid, though they still have to conform to the Ethereum -// consensus rules. -func NewFaker() *Ethash { - return new(Ethash) -} - -// NewFakeFailer creates a ethash consensus engine with a fake PoW scheme that -// accepts all blocks as valid apart from the single one specified, though they -// still have to conform to the Ethereum consensus rules. -func NewFakeFailer(fail uint64) *Ethash { - return &Ethash{ - fakeFail: &fail, - } -} - -// NewFakeDelayer creates a ethash consensus engine with a fake PoW scheme that -// accepts all blocks as valid, but delays verifications by some time, though -// they still have to conform to the Ethereum consensus rules. -func NewFakeDelayer(delay time.Duration) *Ethash { - return &Ethash{ - fakeDelay: &delay, - } -} - -// NewFullFaker creates an ethash consensus engine with a full fake scheme that -// accepts all blocks as valid, without checking any consensus rules whatsoever. -func NewFullFaker() *Ethash { - return &Ethash{ - fakeFull: true, - } -} - -// Close closes the exit channel to notify all backend threads exiting. -func (ethash *Ethash) Close() error { - return nil -} - -// APIs implements consensus.Engine, returning no APIs as ethash is an empty -// shell in the post-merge world. -func (ethash *Ethash) APIs(chain consensus.ChainHeaderReader) []rpc.API { - return []rpc.API{} -} - -// Seal generates a new sealing request for the given input block and pushes -// the result into the given channel. For the ethash engine, this method will -// just panic as sealing is not supported anymore. -func (ethash *Ethash) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - panic("ethash (pow) sealing not supported any more") -} diff --git a/builder/consensus/merger.go b/builder/consensus/merger.go deleted file mode 100644 index ffbcbf2b8..000000000 --- a/builder/consensus/merger.go +++ /dev/null @@ -1,110 +0,0 @@ -// 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 consensus - -import ( - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// transitionStatus describes the status of eth1/2 transition. This switch -// between modes is a one-way action which is triggered by corresponding -// consensus-layer message. -type transitionStatus struct { - LeftPoW bool // The flag is set when the first NewHead message received - EnteredPoS bool // The flag is set when the first FinalisedBlock message received -} - -// Merger is an internal help structure used to track the eth1/2 transition status. -// It's a common structure can be used in both full node and light client. -type Merger struct { - db ethdb.KeyValueStore - status transitionStatus - mu sync.RWMutex -} - -// NewMerger creates a new Merger which stores its transition status in the provided db. -func NewMerger(db ethdb.KeyValueStore) *Merger { - var status transitionStatus - blob := rawdb.ReadTransitionStatus(db) - if len(blob) != 0 { - if err := rlp.DecodeBytes(blob, &status); err != nil { - log.Crit("Failed to decode the transition status", "err", err) - } - } - return &Merger{ - db: db, - status: status, - } -} - -// ReachTTD is called whenever the first NewHead message received -// from the consensus-layer. -func (m *Merger) ReachTTD() { - m.mu.Lock() - defer m.mu.Unlock() - - if m.status.LeftPoW { - return - } - m.status = transitionStatus{LeftPoW: true} - blob, err := rlp.EncodeToBytes(m.status) - if err != nil { - panic(fmt.Sprintf("Failed to encode the transition status: %v", err)) - } - rawdb.WriteTransitionStatus(m.db, blob) - log.Info("Left PoW stage") -} - -// FinalizePoS is called whenever the first FinalisedBlock message received -// from the consensus-layer. -func (m *Merger) FinalizePoS() { - m.mu.Lock() - defer m.mu.Unlock() - - if m.status.EnteredPoS { - return - } - m.status = transitionStatus{LeftPoW: true, EnteredPoS: true} - blob, err := rlp.EncodeToBytes(m.status) - if err != nil { - panic(fmt.Sprintf("Failed to encode the transition status: %v", err)) - } - rawdb.WriteTransitionStatus(m.db, blob) - log.Info("Entered PoS stage") -} - -// TDDReached reports whether the chain has left the PoW stage. -func (m *Merger) TDDReached() bool { - m.mu.RLock() - defer m.mu.RUnlock() - - return m.status.LeftPoW -} - -// PoSFinalized reports whether the chain has entered the PoS stage. -func (m *Merger) PoSFinalized() bool { - m.mu.RLock() - defer m.mu.RUnlock() - - return m.status.EnteredPoS -} diff --git a/builder/consensus/misc/dao.go b/builder/consensus/misc/dao.go deleted file mode 100644 index e21a44f63..000000000 --- a/builder/consensus/misc/dao.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2016 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 misc - -import ( - "bytes" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -var ( - // ErrBadProDAOExtra is returned if a header doesn't support the DAO fork on a - // pro-fork client. - ErrBadProDAOExtra = errors.New("bad DAO pro-fork extra-data") - - // ErrBadNoDAOExtra is returned if a header does support the DAO fork on a no- - // fork client. - ErrBadNoDAOExtra = errors.New("bad DAO no-fork extra-data") -) - -// VerifyDAOHeaderExtraData validates the extra-data field of a block header to -// ensure it conforms to DAO hard-fork rules. -// -// DAO hard-fork extension to the header validity: -// -// - if the node is no-fork, do not accept blocks in the [fork, fork+10) range -// with the fork specific extra-data set. -// - if the node is pro-fork, require blocks in the specific range to have the -// unique extra-data set. -func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) error { - // Short circuit validation if the node doesn't care about the DAO fork - if config.DAOForkBlock == nil { - return nil - } - // Make sure the block is within the fork's modified extra-data range - limit := new(big.Int).Add(config.DAOForkBlock, params.DAOForkExtraRange) - if header.Number.Cmp(config.DAOForkBlock) < 0 || header.Number.Cmp(limit) >= 0 { - return nil - } - // Depending on whether we support or oppose the fork, validate the extra-data contents - if config.DAOForkSupport { - if !bytes.Equal(header.Extra, params.DAOForkBlockExtra) { - return ErrBadProDAOExtra - } - } else { - if bytes.Equal(header.Extra, params.DAOForkBlockExtra) { - return ErrBadNoDAOExtra - } - } - // All ok, header has the same extra-data we expect - return nil -} - -// ApplyDAOHardFork modifies the state database according to the DAO hard-fork -// rules, transferring all balances of a set of DAO accounts to a single refund -// contract. -func ApplyDAOHardFork(statedb *state.StateDB) { - // Retrieve the contract to refund balances into - if !statedb.Exist(params.DAORefundContract) { - statedb.CreateAccount(params.DAORefundContract) - } - - // Move every DAO account and extra-balance account funds into the refund contract - for _, addr := range params.DAODrainList() { - statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr)) - statedb.SetBalance(addr, new(uint256.Int)) - } -} diff --git a/builder/consensus/misc/eip1559/eip1559.go b/builder/consensus/misc/eip1559/eip1559.go deleted file mode 100644 index 84b82c4c4..000000000 --- a/builder/consensus/misc/eip1559/eip1559.go +++ /dev/null @@ -1,95 +0,0 @@ -// 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 eip1559 - -import ( - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -// VerifyEIP1559Header verifies some header attributes which were changed in EIP-1559, -// - gas limit check -// - basefee check -func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error { - // Verify that the gas limit remains within allowed bounds - parentGasLimit := parent.GasLimit - if !config.IsLondon(parent.Number) { - parentGasLimit = parent.GasLimit * config.ElasticityMultiplier() - } - if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil { - return err - } - // Verify the header is not malformed - if header.BaseFee == nil { - return errors.New("header is missing baseFee") - } - // Verify the baseFee is correct based on the parent header. - expectedBaseFee := CalcBaseFee(config, parent) - if header.BaseFee.Cmp(expectedBaseFee) != 0 { - return fmt.Errorf("invalid baseFee: have %s, want %s, parentBaseFee %s, parentGasUsed %d", - header.BaseFee, expectedBaseFee, parent.BaseFee, parent.GasUsed) - } - return nil -} - -// CalcBaseFee calculates the basefee of the header. -func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int { - // If the current block is the first EIP-1559 block, return the InitialBaseFee. - if !config.IsLondon(parent.Number) { - return new(big.Int).SetUint64(params.InitialBaseFee) - } - - parentGasTarget := parent.GasLimit / config.ElasticityMultiplier() - // If the parent gasUsed is the same as the target, the baseFee remains unchanged. - if parent.GasUsed == parentGasTarget { - return new(big.Int).Set(parent.BaseFee) - } - - var ( - num = new(big.Int) - denom = new(big.Int) - ) - - if parent.GasUsed > parentGasTarget { - // If the parent block used more gas than its target, the baseFee should increase. - // max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) - num.SetUint64(parent.GasUsed - parentGasTarget) - num.Mul(num, parent.BaseFee) - num.Div(num, denom.SetUint64(parentGasTarget)) - num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) - baseFeeDelta := math.BigMax(num, common.Big1) - - return num.Add(parent.BaseFee, baseFeeDelta) - } else { - // Otherwise if the parent block used less gas than its target, the baseFee should decrease. - // max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator) - num.SetUint64(parentGasTarget - parent.GasUsed) - num.Mul(num, parent.BaseFee) - num.Div(num, denom.SetUint64(parentGasTarget)) - num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator())) - baseFee := num.Sub(parent.BaseFee, num) - - return math.BigMax(baseFee, common.Big0) - } -} diff --git a/builder/consensus/misc/eip1559/eip1559_test.go b/builder/consensus/misc/eip1559/eip1559_test.go deleted file mode 100644 index b5afdf0fe..000000000 --- a/builder/consensus/misc/eip1559/eip1559_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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 eip1559 - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -// copyConfig does a _shallow_ copy of a given config. Safe to set new values, but -// do not use e.g. SetInt() on the numbers. For testing only -func copyConfig(original *params.ChainConfig) *params.ChainConfig { - return ¶ms.ChainConfig{ - ChainID: original.ChainID, - HomesteadBlock: original.HomesteadBlock, - DAOForkBlock: original.DAOForkBlock, - DAOForkSupport: original.DAOForkSupport, - EIP150Block: original.EIP150Block, - EIP155Block: original.EIP155Block, - EIP158Block: original.EIP158Block, - ByzantiumBlock: original.ByzantiumBlock, - ConstantinopleBlock: original.ConstantinopleBlock, - PetersburgBlock: original.PetersburgBlock, - IstanbulBlock: original.IstanbulBlock, - MuirGlacierBlock: original.MuirGlacierBlock, - BerlinBlock: original.BerlinBlock, - LondonBlock: original.LondonBlock, - TerminalTotalDifficulty: original.TerminalTotalDifficulty, - Ethash: original.Ethash, - Clique: original.Clique, - } -} - -func config() *params.ChainConfig { - config := copyConfig(params.TestChainConfig) - config.LondonBlock = big.NewInt(5) - return config -} - -// TestBlockGasLimits tests the gasLimit checks for blocks both across -// the EIP-1559 boundary and post-1559 blocks -func TestBlockGasLimits(t *testing.T) { - initial := new(big.Int).SetUint64(params.InitialBaseFee) - - for i, tc := range []struct { - pGasLimit uint64 - pNum int64 - gasLimit uint64 - ok bool - }{ - // Transitions from non-london to london - {10000000, 4, 20000000, true}, // No change - {10000000, 4, 20019530, true}, // Upper limit - {10000000, 4, 20019531, false}, // Upper +1 - {10000000, 4, 19980470, true}, // Lower limit - {10000000, 4, 19980469, false}, // Lower limit -1 - // London to London - {20000000, 5, 20000000, true}, - {20000000, 5, 20019530, true}, // Upper limit - {20000000, 5, 20019531, false}, // Upper limit +1 - {20000000, 5, 19980470, true}, // Lower limit - {20000000, 5, 19980469, false}, // Lower limit -1 - {40000000, 5, 40039061, true}, // Upper limit - {40000000, 5, 40039062, false}, // Upper limit +1 - {40000000, 5, 39960939, true}, // lower limit - {40000000, 5, 39960938, false}, // Lower limit -1 - } { - parent := &types.Header{ - GasUsed: tc.pGasLimit / 2, - GasLimit: tc.pGasLimit, - BaseFee: initial, - Number: big.NewInt(tc.pNum), - } - header := &types.Header{ - GasUsed: tc.gasLimit / 2, - GasLimit: tc.gasLimit, - BaseFee: initial, - Number: big.NewInt(tc.pNum + 1), - } - err := VerifyEIP1559Header(config(), parent, header) - if tc.ok && err != nil { - t.Errorf("test %d: Expected valid header: %s", i, err) - } - if !tc.ok && err == nil { - t.Errorf("test %d: Expected invalid header", i) - } - } -} - -// TestCalcBaseFee assumes all blocks are 1559-blocks -func TestCalcBaseFee(t *testing.T) { - tests := []struct { - parentBaseFee int64 - parentGasLimit uint64 - parentGasUsed uint64 - expectedBaseFee int64 - }{ - {params.InitialBaseFee, 20000000, 10000000, params.InitialBaseFee}, // usage == target - {params.InitialBaseFee, 20000000, 9000000, 987500000}, // usage below target - {params.InitialBaseFee, 20000000, 11000000, 1012500000}, // usage above target - } - for i, test := range tests { - parent := &types.Header{ - Number: common.Big32, - GasLimit: test.parentGasLimit, - GasUsed: test.parentGasUsed, - BaseFee: big.NewInt(test.parentBaseFee), - } - if have, want := CalcBaseFee(config(), parent), big.NewInt(test.expectedBaseFee); have.Cmp(want) != 0 { - t.Errorf("test %d: have %d want %d, ", i, have, want) - } - } -} diff --git a/builder/consensus/misc/eip4844/eip4844.go b/builder/consensus/misc/eip4844/eip4844.go deleted file mode 100644 index 2dad9a0cd..000000000 --- a/builder/consensus/misc/eip4844/eip4844.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2023 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 eip4844 - -import ( - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -var ( - minBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice) - blobGaspriceUpdateFraction = big.NewInt(params.BlobTxBlobGaspriceUpdateFraction) -) - -// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that -// if the current block contains no transactions, the excessBlobGas is updated -// accordingly. -func VerifyEIP4844Header(parent, header *types.Header) error { - // Verify the header is not malformed - if header.ExcessBlobGas == nil { - return errors.New("header is missing excessBlobGas") - } - if header.BlobGasUsed == nil { - return errors.New("header is missing blobGasUsed") - } - // Verify that the blob gas used remains within reasonable limits. - if *header.BlobGasUsed > params.MaxBlobGasPerBlock { - return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, params.MaxBlobGasPerBlock) - } - if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 { - return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob) - } - // Verify the excessBlobGas is correct based on the parent header - var ( - parentExcessBlobGas uint64 - parentBlobGasUsed uint64 - ) - if parent.ExcessBlobGas != nil { - parentExcessBlobGas = *parent.ExcessBlobGas - parentBlobGasUsed = *parent.BlobGasUsed - } - expectedExcessBlobGas := CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed) - if *header.ExcessBlobGas != expectedExcessBlobGas { - return fmt.Errorf("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d", - *header.ExcessBlobGas, expectedExcessBlobGas, parentExcessBlobGas, parentBlobGasUsed) - } - return nil -} - -// CalcExcessBlobGas calculates the excess blob gas after applying the set of -// blobs on top of the excess blob gas. -func CalcExcessBlobGas(parentExcessBlobGas uint64, parentBlobGasUsed uint64) uint64 { - excessBlobGas := parentExcessBlobGas + parentBlobGasUsed - if excessBlobGas < params.BlobTxTargetBlobGasPerBlock { - return 0 - } - return excessBlobGas - params.BlobTxTargetBlobGasPerBlock -} - -// CalcBlobFee calculates the blobfee from the header's excess blob gas field. -func CalcBlobFee(excessBlobGas uint64) *big.Int { - return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(excessBlobGas), blobGaspriceUpdateFraction) -} - -// fakeExponential approximates factor * e ** (numerator / denominator) using -// Taylor expansion. -func fakeExponential(factor, numerator, denominator *big.Int) *big.Int { - var ( - output = new(big.Int) - accum = new(big.Int).Mul(factor, denominator) - ) - for i := 1; accum.Sign() > 0; i++ { - output.Add(output, accum) - - accum.Mul(accum, numerator) - accum.Div(accum, denominator) - accum.Div(accum, big.NewInt(int64(i))) - } - return output.Div(output, denominator) -} diff --git a/builder/consensus/misc/eip4844/eip4844_test.go b/builder/consensus/misc/eip4844/eip4844_test.go deleted file mode 100644 index ec417380f..000000000 --- a/builder/consensus/misc/eip4844/eip4844_test.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2023 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 eip4844 - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/params" -) - -func TestCalcExcessBlobGas(t *testing.T) { - var tests = []struct { - excess uint64 - blobs uint64 - want uint64 - }{ - // The excess blob gas should not increase from zero if the used blob - // slots are below - or equal - to the target. - {0, 0, 0}, - {0, 1, 0}, - {0, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, 0}, - - // If the target blob gas is exceeded, the excessBlobGas should increase - // by however much it was overshot - {0, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob}, - {1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 1, params.BlobTxBlobGasPerBlob + 1}, - {1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) + 2, 2*params.BlobTxBlobGasPerBlob + 1}, - - // The excess blob gas should decrease by however much the target was - // under-shot, capped at zero. - {params.BlobTxTargetBlobGasPerBlock, params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob, params.BlobTxTargetBlobGasPerBlock}, - {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, params.BlobTxTargetBlobGasPerBlock - params.BlobTxBlobGasPerBlob}, - {params.BlobTxTargetBlobGasPerBlock, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 2, params.BlobTxTargetBlobGasPerBlock - (2 * params.BlobTxBlobGasPerBlob)}, - {params.BlobTxBlobGasPerBlob - 1, (params.BlobTxTargetBlobGasPerBlock / params.BlobTxBlobGasPerBlob) - 1, 0}, - } - for i, tt := range tests { - result := CalcExcessBlobGas(tt.excess, tt.blobs*params.BlobTxBlobGasPerBlob) - if result != tt.want { - t.Errorf("test %d: excess blob gas mismatch: have %v, want %v", i, result, tt.want) - } - } -} - -func TestCalcBlobFee(t *testing.T) { - tests := []struct { - excessBlobGas uint64 - blobfee int64 - }{ - {0, 1}, - {2314057, 1}, - {2314058, 2}, - {10 * 1024 * 1024, 23}, - } - for i, tt := range tests { - have := CalcBlobFee(tt.excessBlobGas) - if have.Int64() != tt.blobfee { - t.Errorf("test %d: blobfee mismatch: have %v want %v", i, have, tt.blobfee) - } - } -} - -func TestFakeExponential(t *testing.T) { - tests := []struct { - factor int64 - numerator int64 - denominator int64 - want int64 - }{ - // When numerator == 0 the return value should always equal the value of factor - {1, 0, 1, 1}, - {38493, 0, 1000, 38493}, - {0, 1234, 2345, 0}, // should be 0 - {1, 2, 1, 6}, // approximate 7.389 - {1, 4, 2, 6}, - {1, 3, 1, 16}, // approximate 20.09 - {1, 6, 2, 18}, - {1, 4, 1, 49}, // approximate 54.60 - {1, 8, 2, 50}, - {10, 8, 2, 542}, // approximate 540.598 - {11, 8, 2, 596}, // approximate 600.58 - {1, 5, 1, 136}, // approximate 148.4 - {1, 5, 2, 11}, // approximate 12.18 - {2, 5, 2, 23}, // approximate 24.36 - {1, 50000000, 2225652, 5709098764}, - } - for i, tt := range tests { - f, n, d := big.NewInt(tt.factor), big.NewInt(tt.numerator), big.NewInt(tt.denominator) - original := fmt.Sprintf("%d %d %d", f, n, d) - have := fakeExponential(f, n, d) - if have.Int64() != tt.want { - t.Errorf("test %d: fake exponential mismatch: have %v want %v", i, have, tt.want) - } - later := fmt.Sprintf("%d %d %d", f, n, d) - if original != later { - t.Errorf("test %d: fake exponential modified arguments: have\n%v\nwant\n%v", i, later, original) - } - } -} diff --git a/builder/consensus/misc/gaslimit.go b/builder/consensus/misc/gaslimit.go deleted file mode 100644 index dfcabd9a8..000000000 --- a/builder/consensus/misc/gaslimit.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 misc - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/params" -) - -// VerifyGaslimit verifies the header gas limit according increase/decrease -// in relation to the parent gas limit. -func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error { - // Verify that the gas limit remains within allowed bounds - diff := int64(parentGasLimit) - int64(headerGasLimit) - if diff < 0 { - diff *= -1 - } - limit := parentGasLimit / params.GasLimitBoundDivisor - if uint64(diff) >= limit { - return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1) - } - if headerGasLimit < params.MinGasLimit { - return fmt.Errorf("invalid gas limit below %d", params.MinGasLimit) - } - return nil -} diff --git a/builder/console/bridge.go b/builder/console/bridge.go deleted file mode 100644 index 37578041c..000000000 --- a/builder/console/bridge.go +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright 2016 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 console - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "reflect" - "strings" - "time" - - "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/accounts/scwallet" - "github.com/ethereum/go-ethereum/accounts/usbwallet" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/internal/jsre" - "github.com/ethereum/go-ethereum/rpc" -) - -// bridge is a collection of JavaScript utility methods to bride the .js runtime -// environment and the Go RPC connection backing the remote method calls. -type bridge struct { - client *rpc.Client // RPC client to execute Ethereum requests through - prompter prompt.UserPrompter // Input prompter to allow interactive user feedback - printer io.Writer // Output writer to serialize any display strings to -} - -// newBridge creates a new JavaScript wrapper around an RPC client. -func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writer) *bridge { - return &bridge{ - client: client, - prompter: prompter, - printer: printer, - } -} - -func getJeth(vm *goja.Runtime) *goja.Object { - jeth := vm.Get("jeth") - if jeth == nil { - panic(vm.ToValue("jeth object does not exist")) - } - return jeth.ToObject(vm) -} - -// NewAccount is a wrapper around the personal.newAccount RPC method that uses a -// non-echoing password prompt to acquire the passphrase and executes the original -// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call. -func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) { - var ( - password string - confirm string - err error - ) - switch { - // No password was specified, prompt the user for it - case len(call.Arguments) == 0: - if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil { - return nil, err - } - if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil { - return nil, err - } - if password != confirm { - return nil, errors.New("passwords don't match") - } - // A single string password was specified, use that - case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil: - password = call.Argument(0).ToString().String() - default: - return nil, errors.New("expected 0 or 1 string argument") - } - // Password acquired, execute the call and return - newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount")) - if !callable { - return nil, errors.New("jeth.newAccount is not callable") - } - ret, err := newAccount(goja.Null(), call.VM.ToValue(password)) - if err != nil { - return nil, err - } - return ret, nil -} - -// OpenWallet is a wrapper around personal.openWallet which can interpret and -// react to certain error messages, such as the Trezor PIN matrix request. -func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) { - // Make sure we have a wallet specified to open - if call.Argument(0).ToObject(call.VM).ClassName() != "String" { - return nil, errors.New("first argument must be the wallet URL to open") - } - wallet := call.Argument(0) - - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - passwd = call.VM.ToValue("") - } else { - passwd = call.Argument(1) - } - // Open the wallet and return if successful in itself - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - val, err := openWallet(goja.Null(), wallet, passwd) - if err == nil { - return val, nil - } - - // Wallet open failed, report error unless it's a PIN or PUK entry - switch { - case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()): - val, err = b.readPinAndReopenWallet(call) - if err == nil { - return val, nil - } - val, err = b.readPassphraseAndReopenWallet(call) - if err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()): - // PUK input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter the pairing password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - if val, err = openWallet(goja.Null(), wallet, passwd); err != nil { - if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) { - return nil, err - } - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()): - // PIN unblock requested, fetch PUK and new PIN from the user - var pukpin string - input, err := b.prompter.PromptPassword("Please enter current PUK: ") - if err != nil { - return nil, err - } - pukpin = input - input, err = b.prompter.PromptPassword("Please enter new PIN: ") - if err != nil { - return nil, err - } - pukpin += input - - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil { - return nil, err - } - - case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()): - // PIN input requested, fetch from the user and call open again - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil { - return nil, err - } - - default: - // Unknown error occurred, drop to the user - return nil, err - } - return val, nil -} - -func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - input, err := b.prompter.PromptPassword("Please enter your passphrase: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) { - wallet := call.Argument(0) - // Trezor PIN matrix input requested, display the matrix to the user and fetch the data - fmt.Fprintf(b.printer, "Look at the device for number positions\n\n") - fmt.Fprintf(b.printer, "7 | 8 | 9\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "4 | 5 | 6\n") - fmt.Fprintf(b.printer, "--+---+--\n") - fmt.Fprintf(b.printer, "1 | 2 | 3\n\n") - - input, err := b.prompter.PromptPassword("Please enter current PIN: ") - if err != nil { - return nil, err - } - openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet")) - if !callable { - return nil, errors.New("jeth.openWallet is not callable") - } - return openWallet(goja.Null(), wallet, call.VM.ToValue(input)) -} - -// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that -// uses a non-echoing password prompt to acquire the passphrase and executes the -// original RPC method (saved in jeth.unlockAccount) with it to actually execute -// the RPC call. -func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) { - if len(call.Arguments) < 1 { - return nil, errors.New("usage: unlockAccount(account, [ password, duration ])") - } - - account := call.Argument(0) - // Make sure we have an account specified to unlock. - if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the account to unlock") - } - - // If password is not given or is the null value, prompt the user for it. - var passwd goja.Value - if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) { - fmt.Fprintf(b.printer, "Unlock account %s\n", account) - input, err := b.prompter.PromptPassword("Passphrase: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else { - if call.Argument(1).ExportType().Kind() != reflect.String { - return nil, errors.New("password must be a string") - } - passwd = call.Argument(1) - } - - // Third argument is the duration how long the account should be unlocked. - duration := goja.Null() - if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) { - if !isNumber(call.Argument(2)) { - return nil, errors.New("unlock duration must be a number") - } - duration = call.Argument(2) - } - - // Send the request to the backend and return. - unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount")) - if !callable { - return nil, errors.New("jeth.unlockAccount is not callable") - } - return unlockAccount(goja.Null(), account, passwd, duration) -} - -// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password -// prompt to acquire the passphrase and executes the original RPC method (saved in -// jeth.sign) with it to actually execute the RPC call. -func (b *bridge) Sign(call jsre.Call) (goja.Value, error) { - if nArgs := len(call.Arguments); nArgs < 2 { - return nil, errors.New("usage: sign(message, account, [ password ])") - } - var ( - message = call.Argument(0) - account = call.Argument(1) - passwd = call.Argument(2) - ) - - if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String { - return nil, errors.New("first argument must be the message to sign") - } - if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String { - return nil, errors.New("second argument must be the account to sign with") - } - - // if the password is not given or null ask the user and ensure password is a string - if goja.IsUndefined(passwd) || goja.IsNull(passwd) { - fmt.Fprintf(b.printer, "Give password for account %s\n", account) - input, err := b.prompter.PromptPassword("Password: ") - if err != nil { - return nil, err - } - passwd = call.VM.ToValue(input) - } else if passwd.ExportType().Kind() != reflect.String { - return nil, errors.New("third argument must be the password to unlock the account") - } - - // Send the request to the backend and return - sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign")) - if !callable { - return nil, errors.New("jeth.sign is not callable") - } - return sign(goja.Null(), message, account, passwd) -} - -// Sleep will block the console for the specified number of seconds. -func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) { - if nArgs := len(call.Arguments); nArgs < 1 { - return nil, errors.New("usage: sleep()") - } - sleepObj := call.Argument(0) - if goja.IsUndefined(sleepObj) || goja.IsNull(sleepObj) || !isNumber(sleepObj) { - return nil, errors.New("usage: sleep()") - } - sleep := sleepObj.ToFloat() - time.Sleep(time.Duration(sleep * float64(time.Second))) - return call.VM.ToValue(true), nil -} - -// SleepBlocks will block the console for a specified number of new blocks optionally -// until the given timeout is reached. -func (b *bridge) SleepBlocks(call jsre.Call) (goja.Value, error) { - // Parse the input parameters for the sleep. - var ( - blocks = int64(0) - sleep = int64(9999999999999999) // indefinitely - ) - nArgs := len(call.Arguments) - if nArgs == 0 { - return nil, errors.New("usage: sleepBlocks([, max sleep in seconds])") - } - if nArgs >= 1 { - if goja.IsNull(call.Argument(0)) || goja.IsUndefined(call.Argument(0)) || !isNumber(call.Argument(0)) { - return nil, errors.New("expected number as first argument") - } - blocks = call.Argument(0).ToInteger() - } - if nArgs >= 2 { - if goja.IsNull(call.Argument(1)) || goja.IsUndefined(call.Argument(1)) || !isNumber(call.Argument(1)) { - return nil, errors.New("expected number as second argument") - } - sleep = call.Argument(1).ToInteger() - } - - // Poll the current block number until either it or a timeout is reached. - deadline := time.Now().Add(time.Duration(sleep) * time.Second) - var lastNumber hexutil.Uint64 - if err := b.client.Call(&lastNumber, "eth_blockNumber"); err != nil { - return nil, err - } - for time.Now().Before(deadline) { - var number hexutil.Uint64 - if err := b.client.Call(&number, "eth_blockNumber"); err != nil { - return nil, err - } - if number != lastNumber { - lastNumber = number - blocks-- - } - if blocks <= 0 { - break - } - time.Sleep(time.Second) - } - return call.VM.ToValue(true), nil -} - -type jsonrpcCall struct { - ID int64 - Method string - Params []interface{} -} - -// Send implements the web3 provider "send" method. -func (b *bridge) Send(call jsre.Call) (goja.Value, error) { - // Remarshal the request into a Go value. - reqVal, err := call.Argument(0).ToObject(call.VM).MarshalJSON() - if err != nil { - return nil, err - } - - var ( - rawReq = string(reqVal) - dec = json.NewDecoder(strings.NewReader(rawReq)) - reqs []jsonrpcCall - batch bool - ) - dec.UseNumber() // avoid float64s - if rawReq[0] == '[' { - batch = true - dec.Decode(&reqs) - } else { - batch = false - reqs = make([]jsonrpcCall, 1) - dec.Decode(&reqs[0]) - } - - // Execute the requests. - var resps []*goja.Object - for _, req := range reqs { - resp := call.VM.NewObject() - resp.Set("jsonrpc", "2.0") - resp.Set("id", req.ID) - - var result json.RawMessage - if err = b.client.Call(&result, req.Method, req.Params...); err == nil { - if result == nil { - // Special case null because it is decoded as an empty - // raw message for some reason. - resp.Set("result", goja.Null()) - } else { - JSON := call.VM.Get("JSON").ToObject(call.VM) - parse, callable := goja.AssertFunction(JSON.Get("parse")) - if !callable { - return nil, errors.New("JSON.parse is not a function") - } - resultVal, err := parse(goja.Null(), call.VM.ToValue(string(result))) - if err != nil { - setError(resp, -32603, err.Error(), nil) - } else { - resp.Set("result", resultVal) - } - } - } else { - code := -32603 - var data interface{} - if err, ok := err.(rpc.Error); ok { - code = err.ErrorCode() - } - if err, ok := err.(rpc.DataError); ok { - data = err.ErrorData() - } - setError(resp, code, err.Error(), data) - } - resps = append(resps, resp) - } - // Return the responses either to the callback (if supplied) - // or directly as the return value. - var result goja.Value - if batch { - result = call.VM.ToValue(resps) - } else { - result = resps[0] - } - if fn, isFunc := goja.AssertFunction(call.Argument(1)); isFunc { - fn(goja.Null(), goja.Null(), result) - return goja.Undefined(), nil - } - return result, nil -} - -func setError(resp *goja.Object, code int, msg string, data interface{}) { - err := make(map[string]interface{}) - err["code"] = code - err["message"] = msg - if data != nil { - err["data"] = data - } - resp.Set("error", err) -} - -// isNumber returns true if input value is a JS number. -func isNumber(v goja.Value) bool { - k := v.ExportType().Kind() - return k >= reflect.Int && k <= reflect.Float64 -} - -func getObject(vm *goja.Runtime, name string) *goja.Object { - v := vm.Get(name) - if v == nil { - return nil - } - return v.ToObject(vm) -} diff --git a/builder/console/bridge_test.go b/builder/console/bridge_test.go deleted file mode 100644 index e57e294fc..000000000 --- a/builder/console/bridge_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// 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 console - -import ( - "testing" - - "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/internal/jsre" -) - -// TestUndefinedAsParam ensures that personal functions can receive -// `undefined` as a parameter. -func TestUndefinedAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Undefined()} - - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) -} - -// TestNullAsParam ensures that personal functions can receive -// `null` as a parameter. -func TestNullAsParam(t *testing.T) { - b := bridge{} - call := jsre.Call{} - call.Arguments = []goja.Value{goja.Null()} - - b.UnlockAccount(call) - b.Sign(call) - b.Sleep(call) -} diff --git a/builder/console/console.go b/builder/console/console.go deleted file mode 100644 index cdee53684..000000000 --- a/builder/console/console.go +++ /dev/null @@ -1,567 +0,0 @@ -// Copyright 2016 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 console - -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - "path/filepath" - "regexp" - "sort" - "strings" - "sync" - "syscall" - - "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/internal/jsre" - "github.com/ethereum/go-ethereum/internal/jsre/deps" - "github.com/ethereum/go-ethereum/internal/web3ext" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" - "github.com/mattn/go-colorable" - "github.com/peterh/liner" -) - -var ( - // u: unlock, s: signXX, sendXX, n: newAccount, i: importXX - passwordRegexp = regexp.MustCompile(`personal.[nusi]`) - onlyWhitespace = regexp.MustCompile(`^\s*$`) - exit = regexp.MustCompile(`^\s*exit\s*;*\s*$`) -) - -// HistoryFile is the file within the data directory to store input scrollback. -const HistoryFile = "history" - -// DefaultPrompt is the default prompt line prefix to use for user input querying. -const DefaultPrompt = "> " - -// Config is the collection of configurations to fine tune the behavior of the -// JavaScript console. -type Config struct { - DataDir string // Data directory to store the console history at - DocRoot string // Filesystem path from where to load JavaScript files from - Client *rpc.Client // RPC client to execute Ethereum requests through - Prompt string // Input prompt prefix string (defaults to DefaultPrompt) - Prompter prompt.UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter) - Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout) - Preload []string // Absolute paths to JavaScript files to preload -} - -// Console is a JavaScript interpreted runtime environment. It is a fully fledged -// JavaScript console attached to a running node via an external or in-process RPC -// client. -type Console struct { - client *rpc.Client // RPC client to execute Ethereum requests through - jsre *jsre.JSRE // JavaScript runtime environment running the interpreter - prompt string // Input prompt prefix string - prompter prompt.UserPrompter // Input prompter to allow interactive user feedback - histPath string // Absolute path to the console scrollback history - history []string // Scroll history maintained by the console - printer io.Writer // Output writer to serialize any display strings to - - interactiveStopped chan struct{} - stopInteractiveCh chan struct{} - signalReceived chan struct{} - stopped chan struct{} - wg sync.WaitGroup - stopOnce sync.Once -} - -// New initializes a JavaScript interpreted runtime environment and sets defaults -// with the config struct. -func New(config Config) (*Console, error) { - // Handle unset config values gracefully - if config.Prompter == nil { - config.Prompter = prompt.Stdin - } - if config.Prompt == "" { - config.Prompt = DefaultPrompt - } - if config.Printer == nil { - config.Printer = colorable.NewColorableStdout() - } - - // Initialize the console and return - console := &Console{ - client: config.Client, - jsre: jsre.New(config.DocRoot, config.Printer), - prompt: config.Prompt, - prompter: config.Prompter, - printer: config.Printer, - histPath: filepath.Join(config.DataDir, HistoryFile), - interactiveStopped: make(chan struct{}), - stopInteractiveCh: make(chan struct{}), - signalReceived: make(chan struct{}, 1), - stopped: make(chan struct{}), - } - if err := os.MkdirAll(config.DataDir, 0700); err != nil { - return nil, err - } - if err := console.init(config.Preload); err != nil { - return nil, err - } - - console.wg.Add(1) - go console.interruptHandler() - - return console, nil -} - -// init retrieves the available APIs from the remote RPC provider and initializes -// the console's JavaScript namespaces based on the exposed modules. -func (c *Console) init(preload []string) error { - c.initConsoleObject() - - // Initialize the JavaScript <-> Go RPC bridge. - bridge := newBridge(c.client, c.prompter, c.printer) - if err := c.initWeb3(bridge); err != nil { - return err - } - if err := c.initExtensions(); err != nil { - return err - } - - // Add bridge overrides for web3.js functionality. - c.jsre.Do(func(vm *goja.Runtime) { - c.initAdmin(vm, bridge) - c.initPersonal(vm, bridge) - }) - - // Preload JavaScript files. - for _, path := range preload { - if err := c.jsre.Exec(path); err != nil { - failure := err.Error() - if gojaErr, ok := err.(*goja.Exception); ok { - failure = gojaErr.String() - } - return fmt.Errorf("%s: %v", path, failure) - } - } - - // Configure the input prompter for history and tab completion. - if c.prompter != nil { - if content, err := os.ReadFile(c.histPath); err != nil { - c.prompter.SetHistory(nil) - } else { - c.history = strings.Split(string(content), "\n") - c.prompter.SetHistory(c.history) - } - c.prompter.SetWordCompleter(c.AutoCompleteInput) - } - return nil -} - -func (c *Console) initConsoleObject() { - c.jsre.Do(func(vm *goja.Runtime) { - console := vm.NewObject() - console.Set("log", c.consoleOutput) - console.Set("error", c.consoleOutput) - vm.Set("console", console) - }) -} - -func (c *Console) initWeb3(bridge *bridge) error { - if err := c.jsre.Compile("bignumber.js", deps.BigNumberJS); err != nil { - return fmt.Errorf("bignumber.js: %v", err) - } - if err := c.jsre.Compile("web3.js", deps.Web3JS); err != nil { - return fmt.Errorf("web3.js: %v", err) - } - if _, err := c.jsre.Run("var Web3 = require('web3');"); err != nil { - return fmt.Errorf("web3 require: %v", err) - } - var err error - c.jsre.Do(func(vm *goja.Runtime) { - transport := vm.NewObject() - transport.Set("send", jsre.MakeCallback(vm, bridge.Send)) - transport.Set("sendAsync", jsre.MakeCallback(vm, bridge.Send)) - vm.Set("_consoleWeb3Transport", transport) - _, err = vm.RunString("var web3 = new Web3(_consoleWeb3Transport)") - }) - return err -} - -var defaultAPIs = map[string]string{"eth": "1.0", "net": "1.0", "debug": "1.0"} - -// initExtensions loads and registers web3.js extensions. -func (c *Console) initExtensions() error { - const methodNotFound = -32601 - apis, err := c.client.SupportedModules() - if err != nil { - if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == methodNotFound { - log.Warn("Server does not support method rpc_modules, using default API list.") - apis = defaultAPIs - } else { - return err - } - } - - // Compute aliases from server-provided modules. - aliases := map[string]struct{}{"eth": {}} - for api := range apis { - if api == "web3" { - continue - } - aliases[api] = struct{}{} - if file, ok := web3ext.Modules[api]; ok { - if err = c.jsre.Compile(api+".js", file); err != nil { - return fmt.Errorf("%s.js: %v", api, err) - } - } - } - - // Apply aliases. - c.jsre.Do(func(vm *goja.Runtime) { - web3 := getObject(vm, "web3") - for name := range aliases { - if v := web3.Get(name); v != nil { - vm.Set(name, v) - } - } - }) - return nil -} - -// initAdmin creates additional admin APIs implemented by the bridge. -func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) { - if admin := getObject(vm, "admin"); admin != nil { - admin.Set("sleepBlocks", jsre.MakeCallback(vm, bridge.SleepBlocks)) - admin.Set("sleep", jsre.MakeCallback(vm, bridge.Sleep)) - admin.Set("clearHistory", c.clearHistory) - } -} - -// initPersonal redirects account-related API methods through the bridge. -// -// If the console is in interactive mode and the 'personal' API is available, override -// the openWallet, unlockAccount, newAccount and sign methods since these require user -// interaction. The original web3 callbacks are stored in 'jeth'. These will be called -// by the bridge after the prompt and send the original web3 request to the backend. -func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) { - personal := getObject(vm, "personal") - if personal == nil || c.prompter == nil { - return - } - log.Warn("Enabling deprecated personal namespace") - jeth := vm.NewObject() - vm.Set("jeth", jeth) - jeth.Set("openWallet", personal.Get("openWallet")) - jeth.Set("unlockAccount", personal.Get("unlockAccount")) - jeth.Set("newAccount", personal.Get("newAccount")) - jeth.Set("sign", personal.Get("sign")) - personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet)) - personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount)) - personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount)) - personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign)) -} - -func (c *Console) clearHistory() { - c.history = nil - c.prompter.ClearHistory() - if err := os.Remove(c.histPath); err != nil { - fmt.Fprintln(c.printer, "can't delete history file:", err) - } else { - fmt.Fprintln(c.printer, "history file deleted") - } -} - -// consoleOutput is an override for the console.log and console.error methods to -// stream the output into the configured output stream instead of stdout. -func (c *Console) consoleOutput(call goja.FunctionCall) goja.Value { - var output []string - for _, argument := range call.Arguments { - output = append(output, fmt.Sprintf("%v", argument)) - } - fmt.Fprintln(c.printer, strings.Join(output, " ")) - return goja.Null() -} - -// AutoCompleteInput is a pre-assembled word completer to be used by the user -// input prompter to provide hints to the user about the methods available. -func (c *Console) AutoCompleteInput(line string, pos int) (string, []string, string) { - // No completions can be provided for empty inputs - if len(line) == 0 || pos == 0 { - return "", nil, "" - } - // Chunk data to relevant part for autocompletion - // E.g. in case of nested lines eth.getBalance(eth.coinb - start := pos - 1 - for ; start > 0; start-- { - // Skip all methods and namespaces (i.e. including the dot) - c := line[start] - if c == '.' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '1' && c <= '9') { - continue - } - // We've hit an unexpected character, autocomplete form here - start++ - break - } - return line[:start], c.jsre.CompleteKeywords(line[start:pos]), line[pos:] -} - -// Welcome show summary of current Geth instance and some metadata about the -// console's available modules. -func (c *Console) Welcome() { - message := "Welcome to the Geth JavaScript console!\n\n" - - // Print some generic Geth metadata - if res, err := c.jsre.Run(` - var message = "instance: " + web3.version.node + "\n"; - try { - message += "coinbase: " + eth.coinbase + "\n"; - } catch (err) {} - message += "at block: " + eth.blockNumber + " (" + new Date(1000 * eth.getBlock(eth.blockNumber).timestamp) + ")\n"; - try { - message += " datadir: " + admin.datadir + "\n"; - } catch (err) {} - message - `); err == nil { - message += res.String() - } - // List all the supported modules for the user to call - if apis, err := c.client.SupportedModules(); err == nil { - modules := make([]string, 0, len(apis)) - for api, version := range apis { - modules = append(modules, fmt.Sprintf("%s:%s", api, version)) - } - sort.Strings(modules) - message += " modules: " + strings.Join(modules, " ") + "\n" - } - message += "\nTo exit, press ctrl-d or type exit" - fmt.Fprintln(c.printer, message) -} - -// Evaluate executes code and pretty prints the result to the specified output -// stream. -func (c *Console) Evaluate(statement string) { - defer func() { - if r := recover(); r != nil { - fmt.Fprintf(c.printer, "[native] error: %v\n", r) - } - }() - c.jsre.Evaluate(statement, c.printer) - - // Avoid exiting Interactive when jsre was interrupted by SIGINT. - c.clearSignalReceived() -} - -// interruptHandler runs in its own goroutine and waits for signals. -// When a signal is received, it interrupts the JS interpreter. -func (c *Console) interruptHandler() { - defer c.wg.Done() - - // During Interactive, liner inhibits the signal while it is prompting for - // input. However, the signal will be received while evaluating JS. - // - // On unsupported terminals, SIGINT can also happen while prompting. - // Unfortunately, it is not possible to abort the prompt in this case and - // the c.readLines goroutine leaks. - sig := make(chan os.Signal, 1) - signal.Notify(sig, syscall.SIGINT) - defer signal.Stop(sig) - - for { - select { - case <-sig: - c.setSignalReceived() - c.jsre.Interrupt(errors.New("interrupted")) - case <-c.stopInteractiveCh: - close(c.interactiveStopped) - c.jsre.Interrupt(errors.New("interrupted")) - case <-c.stopped: - return - } - } -} - -func (c *Console) setSignalReceived() { - select { - case c.signalReceived <- struct{}{}: - default: - } -} - -func (c *Console) clearSignalReceived() { - select { - case <-c.signalReceived: - default: - } -} - -// StopInteractive causes Interactive to return as soon as possible. -func (c *Console) StopInteractive() { - select { - case c.stopInteractiveCh <- struct{}{}: - case <-c.stopped: - } -} - -// Interactive starts an interactive user session, where input is prompted from -// the configured user prompter. -func (c *Console) Interactive() { - var ( - prompt = c.prompt // the current prompt line (used for multi-line inputs) - indents = 0 // the current number of input indents (used for multi-line inputs) - input = "" // the current user input - inputLine = make(chan string, 1) // receives user input - inputErr = make(chan error, 1) // receives liner errors - requestLine = make(chan string) // requests a line of input - ) - - defer func() { - c.writeHistory() - }() - - // The line reader runs in a separate goroutine. - go c.readLines(inputLine, inputErr, requestLine) - defer close(requestLine) - - for { - // Send the next prompt, triggering an input read. - requestLine <- prompt - - select { - case <-c.interactiveStopped: - fmt.Fprintln(c.printer, "node is down, exiting console") - return - - case <-c.signalReceived: - // SIGINT received while prompting for input -> unsupported terminal. - // I'm not sure if the best choice would be to leave the console running here. - // Bash keeps running in this case. node.js does not. - fmt.Fprintln(c.printer, "caught interrupt, exiting") - return - - case err := <-inputErr: - if err == liner.ErrPromptAborted { - // When prompting for multi-line input, the first Ctrl-C resets - // the multi-line state. - prompt, indents, input = c.prompt, 0, "" - continue - } - return - - case line := <-inputLine: - // User input was returned by the prompter, handle special cases. - if indents <= 0 && exit.MatchString(line) { - return - } - if onlyWhitespace.MatchString(line) { - continue - } - // Append the line to the input and check for multi-line interpretation. - input += line + "\n" - indents = countIndents(input) - if indents <= 0 { - prompt = c.prompt - } else { - prompt = strings.Repeat(".", indents*3) + " " - } - // If all the needed lines are present, save the command and run it. - if indents <= 0 { - if len(input) > 0 && input[0] != ' ' && !passwordRegexp.MatchString(input) { - if command := strings.TrimSpace(input); len(c.history) == 0 || command != c.history[len(c.history)-1] { - c.history = append(c.history, command) - if c.prompter != nil { - c.prompter.AppendHistory(command) - } - } - } - c.Evaluate(input) - input = "" - } - } - } -} - -// readLines runs in its own goroutine, prompting for input. -func (c *Console) readLines(input chan<- string, errc chan<- error, prompt <-chan string) { - for p := range prompt { - line, err := c.prompter.PromptInput(p) - if err != nil { - errc <- err - } else { - input <- line - } - } -} - -// countIndents returns the number of indentations for the given input. -// In case of invalid input such as var a = } the result can be negative. -func countIndents(input string) int { - var ( - indents = 0 - inString = false - strOpenChar = ' ' // keep track of the string open char to allow var str = "I'm ...."; - charEscaped = false // keep track if the previous char was the '\' char, allow var str = "abc\"def"; - ) - - for _, c := range input { - switch c { - case '\\': - // indicate next char as escaped when in string and previous char isn't escaping this backslash - if !charEscaped && inString { - charEscaped = true - } - case '\'', '"': - if inString && !charEscaped && strOpenChar == c { // end string - inString = false - } else if !inString && !charEscaped { // begin string - inString = true - strOpenChar = c - } - charEscaped = false - case '{', '(': - if !inString { // ignore brackets when in string, allow var str = "a{"; without indenting - indents++ - } - charEscaped = false - case '}', ')': - if !inString { - indents-- - } - charEscaped = false - default: - charEscaped = false - } - } - - return indents -} - -// Stop cleans up the console and terminates the runtime environment. -func (c *Console) Stop(graceful bool) error { - c.stopOnce.Do(func() { - // Stop the interrupt handler. - close(c.stopped) - c.wg.Wait() - }) - - c.jsre.Stop(graceful) - return nil -} - -func (c *Console) writeHistory() error { - if err := os.WriteFile(c.histPath, []byte(strings.Join(c.history, "\n")), 0600); err != nil { - return err - } - return os.Chmod(c.histPath, 0600) // Force 0600, even if it was different previously -} diff --git a/builder/console/console_test.go b/builder/console/console_test.go deleted file mode 100644 index a13be6a99..000000000 --- a/builder/console/console_test.go +++ /dev/null @@ -1,322 +0,0 @@ -// 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 console - -import ( - "bytes" - "errors" - "fmt" - "os" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/jsre" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" -) - -const ( - testInstance = "console-tester" - testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182" -) - -// hookedPrompter implements UserPrompter to simulate use input via channels. -type hookedPrompter struct { - scheduler chan string -} - -func (p *hookedPrompter) PromptInput(prompt string) (string, error) { - // Send the prompt to the tester - select { - case p.scheduler <- prompt: - case <-time.After(time.Second): - return "", errors.New("prompt timeout") - } - // Retrieve the response and feed to the console - select { - case input := <-p.scheduler: - return input, nil - case <-time.After(time.Second): - return "", errors.New("input timeout") - } -} - -func (p *hookedPrompter) PromptPassword(prompt string) (string, error) { - return "", errors.New("not implemented") -} -func (p *hookedPrompter) PromptConfirm(prompt string) (bool, error) { - return false, errors.New("not implemented") -} -func (p *hookedPrompter) SetHistory(history []string) {} -func (p *hookedPrompter) AppendHistory(command string) {} -func (p *hookedPrompter) ClearHistory() {} -func (p *hookedPrompter) SetWordCompleter(completer prompt.WordCompleter) {} - -// tester is a console test environment for the console tests to operate on. -type tester struct { - workspace string - stack *node.Node - ethereum *eth.Ethereum - console *Console - input *hookedPrompter - output *bytes.Buffer -} - -// newTester creates a test environment based on which the console can operate. -// Please ensure you call Close() on the returned tester to avoid leaks. -func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester { - // Create a temporary storage for the node keys and initialize it - workspace := t.TempDir() - - // Create a networkless protocol stack and start an Ethereum service within - stack, err := node.New(&node.Config{DataDir: workspace, UseLightweightKDF: true, Name: testInstance}) - if err != nil { - t.Fatalf("failed to create node: %v", err) - } - ethConf := ðconfig.Config{ - Genesis: core.DeveloperGenesisBlock(11_500_000, nil), - Miner: miner.Config{ - Etherbase: common.HexToAddress(testAddress), - }, - } - if confOverride != nil { - confOverride(ethConf) - } - ethBackend, err := eth.New(stack, ethConf) - if err != nil { - t.Fatalf("failed to register Ethereum protocol: %v", err) - } - // Start the node and assemble the JavaScript console around it - if err = stack.Start(); err != nil { - t.Fatalf("failed to start test stack: %v", err) - } - client := stack.Attach() - t.Cleanup(func() { - client.Close() - }) - - prompter := &hookedPrompter{scheduler: make(chan string)} - printer := new(bytes.Buffer) - - console, err := New(Config{ - DataDir: stack.DataDir(), - DocRoot: "testdata", - Client: client, - Prompter: prompter, - Printer: printer, - Preload: []string{"preload.js"}, - }) - if err != nil { - t.Fatalf("failed to create JavaScript console: %v", err) - } - // Create the final tester and return - return &tester{ - workspace: workspace, - stack: stack, - ethereum: ethBackend, - console: console, - input: prompter, - output: printer, - } -} - -// Close cleans up any temporary data folders and held resources. -func (env *tester) Close(t *testing.T) { - if err := env.console.Stop(false); err != nil { - t.Errorf("failed to stop embedded console: %v", err) - } - if err := env.stack.Close(); err != nil { - t.Errorf("failed to tear down embedded node: %v", err) - } - os.RemoveAll(env.workspace) -} - -// Tests that the node lists the correct welcome message, notably that it contains -// the instance name, coinbase account, block number, data directory and supported -// console modules. -func TestWelcome(t *testing.T) { - tester := newTester(t, nil) - defer tester.Close(t) - - tester.console.Welcome() - - output := tester.output.String() - if want := "Welcome"; !strings.Contains(output, want) { - t.Fatalf("console output missing welcome message: have\n%s\nwant also %s", output, want) - } - if want := fmt.Sprintf("instance: %s", testInstance); !strings.Contains(output, want) { - t.Fatalf("console output missing instance: have\n%s\nwant also %s", output, want) - } - if want := fmt.Sprintf("coinbase: %s", testAddress); !strings.Contains(output, want) { - t.Fatalf("console output missing coinbase: have\n%s\nwant also %s", output, want) - } - if want := "at block: 0"; !strings.Contains(output, want) { - t.Fatalf("console output missing sync status: have\n%s\nwant also %s", output, want) - } - if want := fmt.Sprintf("datadir: %s", tester.workspace); !strings.Contains(output, want) { - t.Fatalf("console output missing coinbase: have\n%s\nwant also %s", output, want) - } -} - -// Tests that JavaScript statement evaluation works as intended. -func TestEvaluate(t *testing.T) { - tester := newTester(t, nil) - defer tester.Close(t) - - tester.console.Evaluate("2 + 2") - if output := tester.output.String(); !strings.Contains(output, "4") { - t.Fatalf("statement evaluation failed: have %s, want %s", output, "4") - } -} - -// Tests that the console can be used in interactive mode. -func TestInteractive(t *testing.T) { - // Create a tester and run an interactive console in the background - tester := newTester(t, nil) - defer tester.Close(t) - - go tester.console.Interactive() - - // Wait for a prompt and send a statement back - select { - case <-tester.input.scheduler: - case <-time.After(time.Second): - t.Fatalf("initial prompt timeout") - } - select { - case tester.input.scheduler <- "2+2": - case <-time.After(time.Second): - t.Fatalf("input feedback timeout") - } - // Wait for the second prompt and ensure first statement was evaluated - select { - case <-tester.input.scheduler: - case <-time.After(time.Second): - t.Fatalf("secondary prompt timeout") - } - if output := tester.output.String(); !strings.Contains(output, "4") { - t.Fatalf("statement evaluation failed: have %s, want %s", output, "4") - } -} - -// Tests that preloaded JavaScript files have been executed before user is given -// input. -func TestPreload(t *testing.T) { - tester := newTester(t, nil) - defer tester.Close(t) - - tester.console.Evaluate("preloaded") - if output := tester.output.String(); !strings.Contains(output, "some-preloaded-string") { - t.Fatalf("preloaded variable missing: have %s, want %s", output, "some-preloaded-string") - } -} - -// Tests that the JavaScript objects returned by statement executions are properly -// pretty printed instead of just displaying "[object]". -func TestPrettyPrint(t *testing.T) { - tester := newTester(t, nil) - defer tester.Close(t) - - tester.console.Evaluate("obj = {int: 1, string: 'two', list: [3, 3, 3], obj: {null: null, func: function(){}}}") - - // Define some specially formatted fields - var ( - one = jsre.NumberColor("1") - two = jsre.StringColor("\"two\"") - three = jsre.NumberColor("3") - null = jsre.SpecialColor("null") - fun = jsre.FunctionColor("function()") - ) - // Assemble the actual output we're after and verify - want := `{ - int: ` + one + `, - list: [` + three + `, ` + three + `, ` + three + `], - obj: { - null: ` + null + `, - func: ` + fun + ` - }, - string: ` + two + ` -} -` - if output := tester.output.String(); output != want { - t.Fatalf("pretty print mismatch: have %s, want %s", output, want) - } -} - -// Tests that the JavaScript exceptions are properly formatted and colored. -func TestPrettyError(t *testing.T) { - tester := newTester(t, nil) - defer tester.Close(t) - tester.console.Evaluate("throw 'hello'") - - want := jsre.ErrorColor("hello") + "\n\tat :1:1(1)\n\n" - if output := tester.output.String(); output != want { - t.Fatalf("pretty error mismatch: have %s, want %s", output, want) - } -} - -// Tests that tests if the number of indents for JS input is calculated correct. -func TestIndenting(t *testing.T) { - testCases := []struct { - input string - expectedIndentCount int - }{ - {`var a = 1;`, 0}, - {`"some string"`, 0}, - {`"some string with (parenthesis`, 0}, - {`"some string with newline - ("`, 0}, - {`function v(a,b) {}`, 0}, - {`function f(a,b) { var str = "asd("; };`, 0}, - {`function f(a) {`, 1}, - {`function f(a, function(b) {`, 2}, - {`function f(a, function(b) { - var str = "a)}"; - });`, 0}, - {`function f(a,b) { - var str = "a{b(" + a, ", " + b; - }`, 0}, - {`var str = "\"{"`, 0}, - {`var str = "'("`, 0}, - {`var str = "\\{"`, 0}, - {`var str = "\\\\{"`, 0}, - {`var str = 'a"{`, 0}, - {`var obj = {`, 1}, - {`var obj = { {a:1`, 2}, - {`var obj = { {a:1}`, 1}, - {`var obj = { {a:1}, b:2}`, 0}, - {`var obj = {}`, 0}, - {`var obj = { - a: 1, b: 2 - }`, 0}, - {`var test = }`, -1}, - {`var str = "a\""; var obj = {`, 1}, - } - - for i, tt := range testCases { - counted := countIndents(tt.input) - if counted != tt.expectedIndentCount { - t.Errorf("test %d: invalid indenting: have %d, want %d", i, counted, tt.expectedIndentCount) - } - } -} diff --git a/builder/console/prompt/prompter.go b/builder/console/prompt/prompter.go deleted file mode 100644 index 2a20b6906..000000000 --- a/builder/console/prompt/prompter.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2016 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 prompt - -import ( - "fmt" - "strings" - - "github.com/peterh/liner" -) - -// Stdin holds the stdin line reader (also using stdout for printing prompts). -// Only this reader may be used for input because it keeps an internal buffer. -var Stdin = newTerminalPrompter() - -// UserPrompter defines the methods needed by the console to prompt the user for -// various types of inputs. -type UserPrompter interface { - // PromptInput displays the given prompt to the user and requests some textual - // data to be entered, returning the input of the user. - PromptInput(prompt string) (string, error) - - // PromptPassword displays the given prompt to the user and requests some textual - // data to be entered, but one which must not be echoed out into the terminal. - // The method returns the input provided by the user. - PromptPassword(prompt string) (string, error) - - // PromptConfirm displays the given prompt to the user and requests a boolean - // choice to be made, returning that choice. - PromptConfirm(prompt string) (bool, error) - - // SetHistory sets the input scrollback history that the prompter will allow - // the user to scroll back to. - SetHistory(history []string) - - // AppendHistory appends an entry to the scrollback history. It should be called - // if and only if the prompt to append was a valid command. - AppendHistory(command string) - - // ClearHistory clears the entire history - ClearHistory() - - // SetWordCompleter sets the completion function that the prompter will call to - // fetch completion candidates when the user presses tab. - SetWordCompleter(completer WordCompleter) -} - -// WordCompleter takes the currently edited line with the cursor position and -// returns the completion candidates for the partial word to be completed. If -// the line is "Hello, wo!!!" and the cursor is before the first '!', ("Hello, -// wo!!!", 9) is passed to the completer which may returns ("Hello, ", {"world", -// "Word"}, "!!!") to have "Hello, world!!!". -type WordCompleter func(line string, pos int) (string, []string, string) - -// terminalPrompter is a UserPrompter backed by the liner package. It supports -// prompting the user for various input, among others for non-echoing password -// input. -type terminalPrompter struct { - *liner.State - warned bool - supported bool - normalMode liner.ModeApplier - rawMode liner.ModeApplier -} - -// newTerminalPrompter creates a liner based user input prompter working off the -// standard input and output streams. -func newTerminalPrompter() *terminalPrompter { - p := new(terminalPrompter) - // Get the original mode before calling NewLiner. - // This is usually regular "cooked" mode where characters echo. - normalMode, _ := liner.TerminalMode() - // Turn on liner. It switches to raw mode. - p.State = liner.NewLiner() - rawMode, err := liner.TerminalMode() - if err != nil || !liner.TerminalSupported() { - p.supported = false - } else { - p.supported = true - p.normalMode = normalMode - p.rawMode = rawMode - // Switch back to normal mode while we're not prompting. - normalMode.ApplyMode() - } - p.SetCtrlCAborts(true) - p.SetTabCompletionStyle(liner.TabPrints) - p.SetMultiLineMode(true) - return p -} - -// PromptInput displays the given prompt to the user and requests some textual -// data to be entered, returning the input of the user. -func (p *terminalPrompter) PromptInput(prompt string) (string, error) { - if p.supported { - p.rawMode.ApplyMode() - defer p.normalMode.ApplyMode() - } else { - // liner tries to be smart about printing the prompt - // and doesn't print anything if input is redirected. - // Un-smart it by printing the prompt always. - fmt.Print(prompt) - prompt = "" - defer fmt.Println() - } - return p.State.Prompt(prompt) -} - -// PromptPassword displays the given prompt to the user and requests some textual -// data to be entered, but one which must not be echoed out into the terminal. -// The method returns the input provided by the user. -func (p *terminalPrompter) PromptPassword(prompt string) (passwd string, err error) { - if p.supported { - p.rawMode.ApplyMode() - defer p.normalMode.ApplyMode() - return p.State.PasswordPrompt(prompt) - } - if !p.warned { - fmt.Println("!! Unsupported terminal, password will be echoed.") - p.warned = true - } - // Just as in Prompt, handle printing the prompt here instead of relying on liner. - fmt.Print(prompt) - passwd, err = p.State.Prompt("") - fmt.Println() - return passwd, err -} - -// PromptConfirm displays the given prompt to the user and requests a boolean -// choice to be made, returning that choice. -func (p *terminalPrompter) PromptConfirm(prompt string) (bool, error) { - input, err := p.Prompt(prompt + " [y/n] ") - if len(input) > 0 && strings.EqualFold(input[:1], "y") { - return true, nil - } - return false, err -} - -// SetHistory sets the input scrollback history that the prompter will allow -// the user to scroll back to. -func (p *terminalPrompter) SetHistory(history []string) { - p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n"))) -} - -// AppendHistory appends an entry to the scrollback history. -func (p *terminalPrompter) AppendHistory(command string) { - p.State.AppendHistory(command) -} - -// ClearHistory clears the entire history -func (p *terminalPrompter) ClearHistory() { - p.State.ClearHistory() -} - -// SetWordCompleter sets the completion function that the prompter will call to -// fetch completion candidates when the user presses tab. -func (p *terminalPrompter) SetWordCompleter(completer WordCompleter) { - p.State.SetWordCompleter(liner.WordCompleter(completer)) -} diff --git a/builder/console/testdata/preload.js b/builder/console/testdata/preload.js deleted file mode 100644 index 556793970..000000000 --- a/builder/console/testdata/preload.js +++ /dev/null @@ -1 +0,0 @@ -var preloaded = "some-preloaded-string"; diff --git a/builder/core/.gitignore b/builder/core/.gitignore deleted file mode 100644 index f725d58d1..000000000 --- a/builder/core/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. -# -# If you find yourself ignoring temporary files generated by your text editor -# or operating system, you probably want to add a global ignore instead: -# git config --global core.excludesfile ~/.gitignore_global - -/tmp -*/**/*un~ -*un~ -.DS_Store -*/**/.DS_Store - diff --git a/builder/core/asm/asm.go b/builder/core/asm/asm.go deleted file mode 100644 index 294eb6ffa..000000000 --- a/builder/core/asm/asm.go +++ /dev/null @@ -1,136 +0,0 @@ -// 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 asm provides support for dealing with EVM assembly instructions (e.g., disassembling them). -package asm - -import ( - "encoding/hex" - "fmt" - - "github.com/ethereum/go-ethereum/core/vm" -) - -// Iterator for disassembled EVM instructions -type instructionIterator struct { - code []byte - pc uint64 - arg []byte - op vm.OpCode - error error - started bool -} - -// NewInstructionIterator creates a new instruction iterator. -func NewInstructionIterator(code []byte) *instructionIterator { - it := new(instructionIterator) - it.code = code - return it -} - -// Next returns true if there is a next instruction and moves on. -func (it *instructionIterator) Next() bool { - if it.error != nil || uint64(len(it.code)) <= it.pc { - // We previously reached an error or the end. - return false - } - - if it.started { - // Since the iteration has been already started we move to the next instruction. - if it.arg != nil { - it.pc += uint64(len(it.arg)) - } - it.pc++ - } else { - // We start the iteration from the first instruction. - it.started = true - } - - if uint64(len(it.code)) <= it.pc { - // We reached the end. - return false - } - - it.op = vm.OpCode(it.code[it.pc]) - if it.op.IsPush() { - a := uint64(it.op) - uint64(vm.PUSH1) + 1 - u := it.pc + 1 + a - if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u { - it.error = fmt.Errorf("incomplete push instruction at %v", it.pc) - return false - } - it.arg = it.code[it.pc+1 : u] - } else { - it.arg = nil - } - return true -} - -// Error returns any error that may have been encountered. -func (it *instructionIterator) Error() error { - return it.error -} - -// PC returns the PC of the current instruction. -func (it *instructionIterator) PC() uint64 { - return it.pc -} - -// Op returns the opcode of the current instruction. -func (it *instructionIterator) Op() vm.OpCode { - return it.op -} - -// Arg returns the argument of the current instruction. -func (it *instructionIterator) Arg() []byte { - return it.arg -} - -// PrintDisassembled pretty-print all disassembled EVM instructions to stdout. -func PrintDisassembled(code string) error { - script, err := hex.DecodeString(code) - if err != nil { - return err - } - - it := NewInstructionIterator(script) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - fmt.Printf("%05x: %v %#x\n", it.PC(), it.Op(), it.Arg()) - } else { - fmt.Printf("%05x: %v\n", it.PC(), it.Op()) - } - } - return it.Error() -} - -// Disassemble returns all disassembled EVM instructions in human-readable format. -func Disassemble(script []byte) ([]string, error) { - instrs := make([]string, 0) - - it := NewInstructionIterator(script) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - instrs = append(instrs, fmt.Sprintf("%05x: %v %#x\n", it.PC(), it.Op(), it.Arg())) - } else { - instrs = append(instrs, fmt.Sprintf("%05x: %v\n", it.PC(), it.Op())) - } - } - if err := it.Error(); err != nil { - return nil, err - } - return instrs, nil -} diff --git a/builder/core/asm/asm_test.go b/builder/core/asm/asm_test.go deleted file mode 100644 index cd7520ec6..000000000 --- a/builder/core/asm/asm_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// 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 asm - -import ( - "testing" - - "encoding/hex" -) - -// Tests disassembling instructions -func TestInstructionIterator(t *testing.T) { - for i, tc := range []struct { - want int - code string - wantErr string - }{ - {2, "61000000", ""}, // valid code - {0, "6100", "incomplete push instruction at 0"}, // invalid code - {2, "5900", ""}, // push0 - {0, "", ""}, // empty - - } { - var ( - have int - code, _ = hex.DecodeString(tc.code) - it = NewInstructionIterator(code) - ) - for it.Next() { - have++ - } - var haveErr = "" - if it.Error() != nil { - haveErr = it.Error().Error() - } - if haveErr != tc.wantErr { - t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr) - continue - } - if have != tc.want { - t.Errorf("wrong instruction count, have %d want %d", have, tc.want) - } - } -} diff --git a/builder/core/asm/compiler.go b/builder/core/asm/compiler.go deleted file mode 100644 index 02c589b2c..000000000 --- a/builder/core/asm/compiler.go +++ /dev/null @@ -1,292 +0,0 @@ -// 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 asm - -import ( - "encoding/hex" - "errors" - "fmt" - "math/big" - "os" - "strings" - - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/vm" -) - -// Compiler contains information about the parsed source -// and holds the tokens for the program. -type Compiler struct { - tokens []token - out []byte - - labels map[string]int - - pc, pos int - - debug bool -} - -// NewCompiler returns a new allocated compiler. -func NewCompiler(debug bool) *Compiler { - return &Compiler{ - labels: make(map[string]int), - debug: debug, - } -} - -// Feed feeds tokens into ch and are interpreted by -// the compiler. -// -// feed is the first pass in the compile stage as it collects the used labels in the -// program and keeps a program counter which is used to determine the locations of the -// jump dests. The labels can than be used in the second stage to push labels and -// determine the right position. -func (c *Compiler) Feed(ch <-chan token) { - var prev token - for i := range ch { - switch i.typ { - case number: - num := math.MustParseBig256(i.text).Bytes() - if len(num) == 0 { - num = []byte{0} - } - c.pc += len(num) - case stringValue: - c.pc += len(i.text) - 2 - case element: - c.pc++ - case labelDef: - c.labels[i.text] = c.pc - c.pc++ - case label: - c.pc += 4 - if prev.typ == element && isJump(prev.text) { - c.pc++ - } - } - c.tokens = append(c.tokens, i) - prev = i - } - if c.debug { - fmt.Fprintln(os.Stderr, "found", len(c.labels), "labels") - } -} - -// Compile compiles the current tokens and returns a binary string that can be interpreted -// by the EVM and an error if it failed. -// -// compile is the second stage in the compile phase which compiles the tokens to EVM -// instructions. -func (c *Compiler) Compile() (string, []error) { - var errors []error - // continue looping over the tokens until - // the stack has been exhausted. - for c.pos < len(c.tokens) { - if err := c.compileLine(); err != nil { - errors = append(errors, err) - } - } - - // turn the binary to hex - h := hex.EncodeToString(c.out) - return h, errors -} - -// next returns the next token and increments the -// position. -func (c *Compiler) next() token { - token := c.tokens[c.pos] - c.pos++ - return token -} - -// compileLine compiles a single line instruction e.g. -// "push 1", "jump @label". -func (c *Compiler) compileLine() error { - n := c.next() - if n.typ != lineStart { - return compileErr(n, n.typ.String(), lineStart.String()) - } - - lvalue := c.next() - switch lvalue.typ { - case eof: - return nil - case element: - if err := c.compileElement(lvalue); err != nil { - return err - } - case labelDef: - c.compileLabel() - case lineEnd: - return nil - default: - return compileErr(lvalue, lvalue.text, fmt.Sprintf("%v or %v", labelDef, element)) - } - - if n := c.next(); n.typ != lineEnd { - return compileErr(n, n.text, lineEnd.String()) - } - - return nil -} - -// parseNumber compiles the number to bytes -func parseNumber(tok token) ([]byte, error) { - if tok.typ != number { - panic("parseNumber of non-number token") - } - num, ok := math.ParseBig256(tok.text) - if !ok { - return nil, errors.New("invalid number") - } - bytes := num.Bytes() - if len(bytes) == 0 { - bytes = []byte{0} - } - return bytes, nil -} - -// compileElement compiles the element (push & label or both) -// to a binary representation and may error if incorrect statements -// where fed. -func (c *Compiler) compileElement(element token) error { - switch { - case isJump(element.text): - return c.compileJump(element.text) - case isPush(element.text): - return c.compilePush() - default: - c.outputOpcode(toBinary(element.text)) - return nil - } -} - -func (c *Compiler) compileJump(jumpType string) error { - rvalue := c.next() - switch rvalue.typ { - case number: - numBytes, err := parseNumber(rvalue) - if err != nil { - return err - } - c.outputBytes(numBytes) - - case stringValue: - // strings are quoted, remove them. - str := rvalue.text[1 : len(rvalue.text)-2] - c.outputBytes([]byte(str)) - - case label: - c.outputOpcode(vm.PUSH4) - pos := big.NewInt(int64(c.labels[rvalue.text])).Bytes() - pos = append(make([]byte, 4-len(pos)), pos...) - c.outputBytes(pos) - - case lineEnd: - // push without argument is supported, it just takes the destination from the stack. - c.pos-- - - default: - return compileErr(rvalue, rvalue.text, "number, string or label") - } - // push the operation - c.outputOpcode(toBinary(jumpType)) - return nil -} - -func (c *Compiler) compilePush() error { - // handle pushes. pushes are read from left to right. - var value []byte - rvalue := c.next() - switch rvalue.typ { - case number: - value = math.MustParseBig256(rvalue.text).Bytes() - if len(value) == 0 { - value = []byte{0} - } - case stringValue: - value = []byte(rvalue.text[1 : len(rvalue.text)-1]) - case label: - value = big.NewInt(int64(c.labels[rvalue.text])).Bytes() - value = append(make([]byte, 4-len(value)), value...) - default: - return compileErr(rvalue, rvalue.text, "number, string or label") - } - if len(value) > 32 { - return fmt.Errorf("%d: string or number size > 32 bytes", rvalue.lineno+1) - } - c.outputOpcode(vm.OpCode(int(vm.PUSH1) - 1 + len(value))) - c.outputBytes(value) - return nil -} - -// compileLabel pushes a jumpdest to the binary slice. -func (c *Compiler) compileLabel() { - c.outputOpcode(vm.JUMPDEST) -} - -func (c *Compiler) outputOpcode(op vm.OpCode) { - if c.debug { - fmt.Printf("%d: %v\n", len(c.out), op) - } - c.out = append(c.out, byte(op)) -} - -// output pushes the value v to the binary stack. -func (c *Compiler) outputBytes(b []byte) { - if c.debug { - fmt.Printf("%d: %x\n", len(c.out), b) - } - c.out = append(c.out, b...) -} - -// isPush returns whether the string op is either any of -// push(N). -func isPush(op string) bool { - return strings.EqualFold(op, "PUSH") -} - -// isJump returns whether the string op is jump(i) -func isJump(op string) bool { - return strings.EqualFold(op, "JUMPI") || strings.EqualFold(op, "JUMP") -} - -// toBinary converts text to a vm.OpCode -func toBinary(text string) vm.OpCode { - return vm.StringToOp(strings.ToUpper(text)) -} - -type compileError struct { - got string - want string - - lineno int -} - -func (err compileError) Error() string { - return fmt.Sprintf("%d: syntax error: unexpected %v, expected %v", err.lineno, err.got, err.want) -} - -func compileErr(c token, got, want string) error { - return compileError{ - got: got, - want: want, - lineno: c.lineno + 1, - } -} diff --git a/builder/core/asm/compiler_test.go b/builder/core/asm/compiler_test.go deleted file mode 100644 index 3d64c96bc..000000000 --- a/builder/core/asm/compiler_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// 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 asm - -import ( - "testing" -) - -func TestCompiler(t *testing.T) { - tests := []struct { - input, output string - }{ - { - input: ` - GAS - label: - PUSH @label -`, - output: "5a5b6300000001", - }, - { - input: ` - PUSH @label - label: -`, - output: "63000000055b", - }, - { - input: ` - PUSH @label - JUMP - label: -`, - output: "6300000006565b", - }, - { - input: ` - JUMP @label - label: -`, - output: "6300000006565b", - }, - { - input: ` - JUMP @label -label: ;; comment - ADD ;; comment -`, - output: "6300000006565b01", - }, - } - for _, test := range tests { - ch := Lex([]byte(test.input), false) - c := NewCompiler(false) - c.Feed(ch) - output, err := c.Compile() - if len(err) != 0 { - t.Errorf("compile error: %v\ninput: %s", err, test.input) - continue - } - if output != test.output { - t.Errorf("incorrect output\ninput: %sgot: %s\nwant: %s\n", test.input, output, test.output) - } - } -} diff --git a/builder/core/asm/lex_test.go b/builder/core/asm/lex_test.go deleted file mode 100644 index 1e62d776d..000000000 --- a/builder/core/asm/lex_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// 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 asm - -import ( - "reflect" - "testing" -) - -func lexAll(src string) []token { - ch := Lex([]byte(src), false) - - var tokens []token - for i := range ch { - tokens = append(tokens, i) - } - return tokens -} - -func TestLexer(t *testing.T) { - tests := []struct { - input string - tokens []token - }{ - { - input: ";; this is a comment", - tokens: []token{{typ: lineStart}, {typ: eof}}, - }, - { - input: "0x12345678", - tokens: []token{{typ: lineStart}, {typ: number, text: "0x12345678"}, {typ: eof}}, - }, - { - input: "0x123ggg", - tokens: []token{{typ: lineStart}, {typ: number, text: "0x123"}, {typ: element, text: "ggg"}, {typ: eof}}, - }, - { - input: "12345678", - tokens: []token{{typ: lineStart}, {typ: number, text: "12345678"}, {typ: eof}}, - }, - { - input: "123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "0123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "0123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "00123abc", - tokens: []token{{typ: lineStart}, {typ: number, text: "00123"}, {typ: element, text: "abc"}, {typ: eof}}, - }, - { - input: "@foo", - tokens: []token{{typ: lineStart}, {typ: label, text: "foo"}, {typ: eof}}, - }, - { - input: "@label123", - tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, - }, - // Comment after label - { - input: "@label123 ;; comment", - tokens: []token{{typ: lineStart}, {typ: label, text: "label123"}, {typ: eof}}, - }, - // Comment after instruction - { - input: "push 3 ;; comment\nadd", - tokens: []token{{typ: lineStart}, {typ: element, text: "push"}, {typ: number, text: "3"}, {typ: lineEnd, text: "\n"}, {typ: lineStart, lineno: 1}, {typ: element, lineno: 1, text: "add"}, {typ: eof, lineno: 1}}, - }, - } - - for _, test := range tests { - tokens := lexAll(test.input) - if !reflect.DeepEqual(tokens, test.tokens) { - t.Errorf("input %q\ngot: %+v\nwant: %+v", test.input, tokens, test.tokens) - } - } -} diff --git a/builder/core/asm/lexer.go b/builder/core/asm/lexer.go deleted file mode 100644 index e025c6f36..000000000 --- a/builder/core/asm/lexer.go +++ /dev/null @@ -1,275 +0,0 @@ -// 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 asm - -import ( - "fmt" - "os" - "strings" - "unicode" - "unicode/utf8" -) - -// stateFn is used through the lifetime of the -// lexer to parse the different values at the -// current state. -type stateFn func(*lexer) stateFn - -// token is emitted when the lexer has discovered -// a new parsable token. These are delivered over -// the tokens channels of the lexer -type token struct { - typ tokenType - lineno int - text string -} - -// tokenType are the different types the lexer -// is able to parse and return. -type tokenType int - -//go:generate go run golang.org/x/tools/cmd/stringer -type tokenType - -const ( - eof tokenType = iota // end of file - lineStart // emitted when a line starts - lineEnd // emitted when a line ends - invalidStatement // any invalid statement - element // any element during element parsing - label // label is emitted when a label is found - labelDef // label definition is emitted when a new label is found - number // number is emitted when a number is found - stringValue // stringValue is emitted when a string has been found -) - -const ( - decimalNumbers = "1234567890" // characters representing any decimal number - hexNumbers = decimalNumbers + "aAbBcCdDeEfF" // characters representing any hexadecimal - alpha = "abcdefghijklmnopqrstuwvxyzABCDEFGHIJKLMNOPQRSTUWVXYZ" // characters representing alphanumeric -) - -// lexer is the basic construct for parsing -// source code and turning them in to tokens. -// Tokens are interpreted by the compiler. -type lexer struct { - input string // input contains the source code of the program - - tokens chan token // tokens is used to deliver tokens to the listener - state stateFn // the current state function - - lineno int // current line number in the source file - start, pos, width int // positions for lexing and returning value - - debug bool // flag for triggering debug output -} - -// Lex lexes the program by name with the given source. It returns a -// channel on which the tokens are delivered. -func Lex(source []byte, debug bool) <-chan token { - ch := make(chan token) - l := &lexer{ - input: string(source), - tokens: ch, - state: lexLine, - debug: debug, - } - go func() { - l.emit(lineStart) - for l.state != nil { - l.state = l.state(l) - } - l.emit(eof) - close(l.tokens) - }() - - return ch -} - -// next returns the next rune in the program's source. -func (l *lexer) next() (rune rune) { - if l.pos >= len(l.input) { - l.width = 0 - return 0 - } - rune, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) - l.pos += l.width - return rune -} - -// backup backsup the last parsed element (multi-character) -func (l *lexer) backup() { - l.pos -= l.width -} - -// peek returns the next rune but does not advance the seeker -func (l *lexer) peek() rune { - r := l.next() - l.backup() - return r -} - -// ignore advances the seeker and ignores the value -func (l *lexer) ignore() { - l.start = l.pos -} - -// Accepts checks whether the given input matches the next rune -func (l *lexer) accept(valid string) bool { - if strings.ContainsRune(valid, l.next()) { - return true - } - - l.backup() - - return false -} - -// acceptRun will continue to advance the seeker until valid -// can no longer be met. -func (l *lexer) acceptRun(valid string) { - for strings.ContainsRune(valid, l.next()) { - } - l.backup() -} - -// acceptRunUntil is the inverse of acceptRun and will continue -// to advance the seeker until the rune has been found. -func (l *lexer) acceptRunUntil(until rune) bool { - // Continues running until a rune is found - for i := l.next(); !strings.ContainsRune(string(until), i); i = l.next() { - if i == 0 { - return false - } - } - - return true -} - -// blob returns the current value -func (l *lexer) blob() string { - return l.input[l.start:l.pos] -} - -// Emits a new token on to token channel for processing -func (l *lexer) emit(t tokenType) { - token := token{t, l.lineno, l.blob()} - - if l.debug { - fmt.Fprintf(os.Stderr, "%04d: (%-20v) %s\n", token.lineno, token.typ, token.text) - } - - l.tokens <- token - l.start = l.pos -} - -// lexLine is state function for lexing lines -func lexLine(l *lexer) stateFn { - for { - switch r := l.next(); { - case r == '\n': - l.emit(lineEnd) - l.ignore() - l.lineno++ - l.emit(lineStart) - case r == ';' && l.peek() == ';': - return lexComment - case isSpace(r): - l.ignore() - case isLetter(r) || r == '_': - return lexElement - case isNumber(r): - return lexNumber - case r == '@': - l.ignore() - return lexLabel - case r == '"': - return lexInsideString - default: - return nil - } - } -} - -// lexComment parses the current position until the end -// of the line and discards the text. -func lexComment(l *lexer) stateFn { - l.acceptRunUntil('\n') - l.backup() - l.ignore() - - return lexLine -} - -// lexLabel parses the current label, emits and returns -// the lex text state function to advance the parsing -// process. -func lexLabel(l *lexer) stateFn { - l.acceptRun(alpha + "_" + decimalNumbers) - - l.emit(label) - - return lexLine -} - -// lexInsideString lexes the inside of a string until -// the state function finds the closing quote. -// It returns the lex text state function. -func lexInsideString(l *lexer) stateFn { - if l.acceptRunUntil('"') { - l.emit(stringValue) - } - - return lexLine -} - -func lexNumber(l *lexer) stateFn { - acceptance := decimalNumbers - if l.accept("xX") { - acceptance = hexNumbers - } - l.acceptRun(acceptance) - - l.emit(number) - - return lexLine -} - -func lexElement(l *lexer) stateFn { - l.acceptRun(alpha + "_" + decimalNumbers) - - if l.peek() == ':' { - l.emit(labelDef) - - l.accept(":") - l.ignore() - } else { - l.emit(element) - } - return lexLine -} - -func isLetter(t rune) bool { - return unicode.IsLetter(t) -} - -func isSpace(t rune) bool { - return unicode.IsSpace(t) -} - -func isNumber(t rune) bool { - return unicode.IsNumber(t) -} diff --git a/builder/core/asm/tokentype_string.go b/builder/core/asm/tokentype_string.go deleted file mode 100644 index ade76aa36..000000000 --- a/builder/core/asm/tokentype_string.go +++ /dev/null @@ -1,31 +0,0 @@ -// Code generated by "stringer -type tokenType"; DO NOT EDIT. - -package asm - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[eof-0] - _ = x[lineStart-1] - _ = x[lineEnd-2] - _ = x[invalidStatement-3] - _ = x[element-4] - _ = x[label-5] - _ = x[labelDef-6] - _ = x[number-7] - _ = x[stringValue-8] -} - -const _tokenType_name = "eoflineStartlineEndinvalidStatementelementlabellabelDefnumberstringValue" - -var _tokenType_index = [...]uint8{0, 3, 12, 19, 35, 42, 47, 55, 61, 72} - -func (i tokenType) String() string { - if i < 0 || i >= tokenType(len(_tokenType_index)-1) { - return "tokenType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _tokenType_name[_tokenType_index[i]:_tokenType_index[i+1]] -} diff --git a/builder/core/bench_test.go b/builder/core/bench_test.go deleted file mode 100644 index 97713868a..000000000 --- a/builder/core/bench_test.go +++ /dev/null @@ -1,331 +0,0 @@ -// 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 core - -import ( - "crypto/ecdsa" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" -) - -func BenchmarkInsertChain_empty_memdb(b *testing.B) { - benchInsertChain(b, false, nil) -} -func BenchmarkInsertChain_empty_diskdb(b *testing.B) { - benchInsertChain(b, true, nil) -} -func BenchmarkInsertChain_valueTx_memdb(b *testing.B) { - benchInsertChain(b, false, genValueTx(0)) -} -func BenchmarkInsertChain_valueTx_diskdb(b *testing.B) { - benchInsertChain(b, true, genValueTx(0)) -} -func BenchmarkInsertChain_valueTx_100kB_memdb(b *testing.B) { - benchInsertChain(b, false, genValueTx(100*1024)) -} -func BenchmarkInsertChain_valueTx_100kB_diskdb(b *testing.B) { - benchInsertChain(b, true, genValueTx(100*1024)) -} -func BenchmarkInsertChain_uncles_memdb(b *testing.B) { - benchInsertChain(b, false, genUncles) -} -func BenchmarkInsertChain_uncles_diskdb(b *testing.B) { - benchInsertChain(b, true, genUncles) -} -func BenchmarkInsertChain_ring200_memdb(b *testing.B) { - benchInsertChain(b, false, genTxRing(200)) -} -func BenchmarkInsertChain_ring200_diskdb(b *testing.B) { - benchInsertChain(b, true, genTxRing(200)) -} -func BenchmarkInsertChain_ring1000_memdb(b *testing.B) { - benchInsertChain(b, false, genTxRing(1000)) -} -func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) { - benchInsertChain(b, true, genTxRing(1000)) -} - -var ( - // This is the content of the genesis block used by the benchmarks. - benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey) - benchRootFunds = math.BigPow(2, 200) -) - -// genValueTx returns a block generator that includes a single -// value-transfer transaction with n bytes of extra data in each -// block. -func genValueTx(nbytes int) func(int, *BlockGen) { - return func(i int, gen *BlockGen) { - toaddr := common.Address{} - data := make([]byte, nbytes) - gas, _ := IntrinsicGas(data, nil, false, false, false, false) - signer := gen.Signer() - gasPrice := big.NewInt(0) - if gen.header.BaseFee != nil { - gasPrice = gen.header.BaseFee - } - tx, _ := types.SignNewTx(benchRootKey, signer, &types.LegacyTx{ - Nonce: gen.TxNonce(benchRootAddr), - To: &toaddr, - Value: big.NewInt(1), - Gas: gas, - Data: data, - GasPrice: gasPrice, - }) - gen.AddTx(tx) - } -} - -var ( - ringKeys = make([]*ecdsa.PrivateKey, 1000) - ringAddrs = make([]common.Address, len(ringKeys)) -) - -func init() { - ringKeys[0] = benchRootKey - ringAddrs[0] = benchRootAddr - for i := 1; i < len(ringKeys); i++ { - ringKeys[i], _ = crypto.GenerateKey() - ringAddrs[i] = crypto.PubkeyToAddress(ringKeys[i].PublicKey) - } -} - -// genTxRing returns a block generator that sends ether in a ring -// among n accounts. This is creates n entries in the state database -// and fills the blocks with many small transactions. -func genTxRing(naccounts int) func(int, *BlockGen) { - from := 0 - availableFunds := new(big.Int).Set(benchRootFunds) - return func(i int, gen *BlockGen) { - block := gen.PrevBlock(i - 1) - gas := block.GasLimit() - gasPrice := big.NewInt(0) - if gen.header.BaseFee != nil { - gasPrice = gen.header.BaseFee - } - signer := gen.Signer() - for { - gas -= params.TxGas - if gas < params.TxGas { - break - } - to := (from + 1) % naccounts - burn := new(big.Int).SetUint64(params.TxGas) - burn.Mul(burn, gen.header.BaseFee) - availableFunds.Sub(availableFunds, burn) - if availableFunds.Cmp(big.NewInt(1)) < 0 { - panic("not enough funds") - } - tx, err := types.SignNewTx(ringKeys[from], signer, - &types.LegacyTx{ - Nonce: gen.TxNonce(ringAddrs[from]), - To: &ringAddrs[to], - Value: availableFunds, - Gas: params.TxGas, - GasPrice: gasPrice, - }) - if err != nil { - panic(err) - } - gen.AddTx(tx) - from = to - } - } -} - -// genUncles generates blocks with two uncle headers. -func genUncles(i int, gen *BlockGen) { - if i >= 7 { - b2 := gen.PrevBlock(i - 6).Header() - b2.Extra = []byte("foo") - gen.AddUncle(b2) - b3 := gen.PrevBlock(i - 6).Header() - b3.Extra = []byte("bar") - gen.AddUncle(b3) - } -} - -func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { - // Create the database in memory or in a temporary directory. - var db ethdb.Database - var err error - if !disk { - db = rawdb.NewMemoryDatabase() - } else { - dir := b.TempDir() - db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "", false) - if err != nil { - b.Fatalf("cannot create temporary database: %v", err) - } - defer db.Close() - } - - // Generate a chain of b.N blocks using the supplied block - // generator function. - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}}, - } - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), b.N, gen) - - // Time the insertion of the new chain. - // State and blocks are stored in the same DB. - chainman, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer chainman.Stop() - b.ReportAllocs() - b.ResetTimer() - if i, err := chainman.InsertChain(chain); err != nil { - b.Fatalf("insert error (block %d): %v\n", i, err) - } -} - -func BenchmarkChainRead_header_10k(b *testing.B) { - benchReadChain(b, false, 10000) -} -func BenchmarkChainRead_full_10k(b *testing.B) { - benchReadChain(b, true, 10000) -} -func BenchmarkChainRead_header_100k(b *testing.B) { - benchReadChain(b, false, 100000) -} -func BenchmarkChainRead_full_100k(b *testing.B) { - benchReadChain(b, true, 100000) -} -func BenchmarkChainRead_header_500k(b *testing.B) { - benchReadChain(b, false, 500000) -} -func BenchmarkChainRead_full_500k(b *testing.B) { - benchReadChain(b, true, 500000) -} -func BenchmarkChainWrite_header_10k(b *testing.B) { - benchWriteChain(b, false, 10000) -} -func BenchmarkChainWrite_full_10k(b *testing.B) { - benchWriteChain(b, true, 10000) -} -func BenchmarkChainWrite_header_100k(b *testing.B) { - benchWriteChain(b, false, 100000) -} -func BenchmarkChainWrite_full_100k(b *testing.B) { - benchWriteChain(b, true, 100000) -} -func BenchmarkChainWrite_header_500k(b *testing.B) { - benchWriteChain(b, false, 500000) -} -func BenchmarkChainWrite_full_500k(b *testing.B) { - benchWriteChain(b, true, 500000) -} - -// makeChainForBench writes a given number of headers or empty blocks/receipts -// into a database. -func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uint64) { - var hash common.Hash - for n := uint64(0); n < count; n++ { - header := &types.Header{ - Coinbase: common.Address{}, - Number: big.NewInt(int64(n)), - ParentHash: hash, - Difficulty: big.NewInt(1), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - } - if n == 0 { - header = genesis.ToBlock().Header() - } - hash = header.Hash() - - rawdb.WriteHeader(db, header) - rawdb.WriteCanonicalHash(db, hash, n) - rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1))) - - if n == 0 { - rawdb.WriteChainConfig(db, hash, genesis.Config) - } - rawdb.WriteHeadHeaderHash(db, hash) - - if full || n == 0 { - block := types.NewBlockWithHeader(header) - rawdb.WriteBody(db, hash, n, block.Body()) - rawdb.WriteReceipts(db, hash, n, nil) - rawdb.WriteHeadBlockHash(db, hash) - } - } -} - -func benchWriteChain(b *testing.B, full bool, count uint64) { - genesis := &Genesis{Config: params.AllEthashProtocolChanges} - for i := 0; i < b.N; i++ { - dir := b.TempDir() - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) - } - makeChainForBench(db, genesis, full, count) - db.Close() - } -} - -func benchReadChain(b *testing.B, full bool, count uint64) { - dir := b.TempDir() - - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) - } - genesis := &Genesis{Config: params.AllEthashProtocolChanges} - makeChainForBench(db, genesis, full, count) - db.Close() - cacheConfig := *defaultCacheConfig - cacheConfig.TrieDirtyDisabled = true - - b.ReportAllocs() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", dir, err) - } - chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - b.Fatalf("error creating chain: %v", err) - } - - for n := uint64(0); n < count; n++ { - header := chain.GetHeaderByNumber(n) - if full { - hash := header.Hash() - rawdb.ReadBody(db, hash, n) - rawdb.ReadReceipts(db, hash, n, header.Time, chain.Config()) - } - } - chain.Stop() - db.Close() - } -} diff --git a/builder/core/block_validator.go b/builder/core/block_validator.go deleted file mode 100644 index f3d65cea2..000000000 --- a/builder/core/block_validator.go +++ /dev/null @@ -1,172 +0,0 @@ -// 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 core - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" -) - -// BlockValidator is responsible for validating block headers, uncles and -// processed state. -// -// BlockValidator implements Validator. -type BlockValidator struct { - config *params.ChainConfig // Chain configuration options - bc *BlockChain // Canonical block chain - engine consensus.Engine // Consensus engine used for validating -} - -// NewBlockValidator returns a new block validator which is safe for re-use -func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator { - validator := &BlockValidator{ - config: config, - engine: engine, - bc: blockchain, - } - return validator -} - -// ValidateBody validates the given block's uncles and verifies the block -// header's transaction and uncle roots. The headers are assumed to be already -// validated at this point. -func (v *BlockValidator) ValidateBody(block *types.Block) error { - // Check whether the block is already imported. - if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) { - return ErrKnownBlock - } - - // Header validity is known at this point. Here we verify that uncles, transactions - // and withdrawals given in the block body match the header. - header := block.Header() - if err := v.engine.VerifyUncles(v.bc, block); err != nil { - return err - } - if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash { - return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash) - } - if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash { - return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash) - } - - // Withdrawals are present after the Shanghai fork. - if header.WithdrawalsHash != nil { - // Withdrawals list must be present in body after Shanghai. - if block.Withdrawals() == nil { - return errors.New("missing withdrawals in block body") - } - if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash { - return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash) - } - } else if block.Withdrawals() != nil { - // Withdrawals are not allowed prior to Shanghai fork - return errors.New("withdrawals present in block body") - } - - // Blob transactions may be present after the Cancun fork. - var blobs int - for i, tx := range block.Transactions() { - // Count the number of blobs to validate against the header's blobGasUsed - blobs += len(tx.BlobHashes()) - - // If the tx is a blob tx, it must NOT have a sidecar attached to be valid in a block. - if tx.BlobTxSidecar() != nil { - return fmt.Errorf("unexpected blob sidecar in transaction at index %d", i) - } - - // The individual checks for blob validity (version-check + not empty) - // happens in StateTransition. - } - - // Check blob gas usage. - if header.BlobGasUsed != nil { - if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated - return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob) - } - } else { - if blobs > 0 { - return errors.New("data blobs present in block body") - } - } - - // Ancestor block must be known. - if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { - if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { - return consensus.ErrUnknownAncestor - } - return consensus.ErrPrunedAncestor - } - return nil -} - -// ValidateState validates the various changes that happen after a state transition, -// such as amount of used gas, the receipt roots and the state root itself. -func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { - header := block.Header() - if block.GasUsed() != usedGas { - return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) - } - // Validate the received block's bloom with the one derived from the generated receipts. - // For valid blocks this should always validate to true. - rbloom := types.CreateBloom(receipts) - if rbloom != header.Bloom { - return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) - } - // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]])) - receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil)) - if receiptSha != header.ReceiptHash { - return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) - } - // Validate the state root against the received state root and throw - // an error if they don't match. - if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { - return fmt.Errorf("invalid merkle root (remote: %x local: %x) dberr: %w", header.Root, root, statedb.Error()) - } - return nil -} - -// CalcGasLimit computes the gas limit of the next block after parent. It aims -// to keep the baseline gas close to the provided target, and increase it towards -// the target if the baseline gas is lower. -func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 { - delta := parentGasLimit/params.GasLimitBoundDivisor - 1 - limit := parentGasLimit - if desiredLimit < params.MinGasLimit { - desiredLimit = params.MinGasLimit - } - // If we're outside our allowed gas range, we try to hone towards them - if limit < desiredLimit { - limit = parentGasLimit + delta - if limit > desiredLimit { - limit = desiredLimit - } - return limit - } - if limit > desiredLimit { - limit = parentGasLimit - delta - if limit < desiredLimit { - limit = desiredLimit - } - } - return limit -} diff --git a/builder/core/block_validator_test.go b/builder/core/block_validator_test.go deleted file mode 100644 index 385c0afd9..000000000 --- a/builder/core/block_validator_test.go +++ /dev/null @@ -1,272 +0,0 @@ -// 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 core - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -// Tests that simple header verification works, for both good and bad blocks. -func TestHeaderVerification(t *testing.T) { - testHeaderVerification(t, rawdb.HashScheme) - testHeaderVerification(t, rawdb.PathScheme) -} - -func testHeaderVerification(t *testing.T, scheme string) { - // Create a simple chain to verify - var ( - gspec = &Genesis{Config: params.TestChainConfig} - _, blocks, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 8, nil) - ) - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer chain.Stop() - - for i := 0; i < len(blocks); i++ { - for j, valid := range []bool{true, false} { - var results <-chan error - - if valid { - engine := ethash.NewFaker() - _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}) - } else { - engine := ethash.NewFakeFailer(headers[i].Number.Uint64()) - _, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}) - } - // Wait for the verification result - select { - case result := <-results: - if (result == nil) != valid { - t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, result, valid) - } - case <-time.After(time.Second): - t.Fatalf("test %d.%d: verification timeout", i, j) - } - // Make sure no more data is returned - select { - case result := <-results: - t.Fatalf("test %d.%d: unexpected result returned: %v", i, j, result) - case <-time.After(25 * time.Millisecond): - } - } - chain.InsertChain(blocks[i : i+1]) - } -} - -func TestHeaderVerificationForMergingClique(t *testing.T) { testHeaderVerificationForMerging(t, true) } -func TestHeaderVerificationForMergingEthash(t *testing.T) { testHeaderVerificationForMerging(t, false) } - -// Tests the verification for eth1/2 merging, including pre-merge and post-merge -func testHeaderVerificationForMerging(t *testing.T, isClique bool) { - var ( - gspec *Genesis - preBlocks []*types.Block - postBlocks []*types.Block - engine consensus.Engine - merger = consensus.NewMerger(rawdb.NewMemoryDatabase()) - ) - if isClique { - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key.PublicKey) - config = *params.AllCliqueProtocolChanges - ) - engine = beacon.New(clique.New(params.AllCliqueProtocolChanges.Clique, rawdb.NewMemoryDatabase())) - gspec = &Genesis{ - Config: &config, - ExtraData: make([]byte, 32+common.AddressLength+crypto.SignatureLength), - Alloc: map[common.Address]types.Account{ - addr: {Balance: big.NewInt(1)}, - }, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: new(big.Int), - } - copy(gspec.ExtraData[32:], addr[:]) - - td := 0 - genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) - for i, block := range blocks { - header := block.Header() - if i > 0 { - header.ParentHash = blocks[i-1].Hash() - } - header.Extra = make([]byte, 32+crypto.SignatureLength) - header.Difficulty = big.NewInt(2) - - sig, _ := crypto.Sign(engine.SealHash(header).Bytes(), key) - copy(header.Extra[len(header.Extra)-crypto.SignatureLength:], sig) - blocks[i] = block.WithSeal(header) - - // calculate td - td += int(block.Difficulty().Uint64()) - } - preBlocks = blocks - gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) - postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, nil) - } else { - config := *params.TestChainConfig - gspec = &Genesis{Config: &config} - engine = beacon.New(ethash.NewFaker()) - td := int(params.GenesisDifficulty.Uint64()) - genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) - for _, block := range blocks { - // calculate td - td += int(block.Difficulty().Uint64()) - } - preBlocks = blocks - gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) - t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty) - postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) { - gen.SetPoS() - }) - } - // Assemble header batch - preHeaders := make([]*types.Header, len(preBlocks)) - for i, block := range preBlocks { - preHeaders[i] = block.Header() - t.Logf("Pre-merge header: %d", block.NumberU64()) - } - postHeaders := make([]*types.Header, len(postBlocks)) - for i, block := range postBlocks { - postHeaders[i] = block.Header() - t.Logf("Post-merge header: %d", block.NumberU64()) - } - // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) - defer chain.Stop() - - // Verify the blocks before the merging - for i := 0; i < len(preBlocks); i++ { - _, results := engine.VerifyHeaders(chain, []*types.Header{preHeaders[i]}) - // Wait for the verification result - select { - case result := <-results: - if result != nil { - t.Errorf("pre-block %d: verification failed %v", i, result) - } - case <-time.After(time.Second): - t.Fatalf("pre-block %d: verification timeout", i) - } - // Make sure no more data is returned - select { - case result := <-results: - t.Fatalf("pre-block %d: unexpected result returned: %v", i, result) - case <-time.After(25 * time.Millisecond): - } - chain.InsertChain(preBlocks[i : i+1]) - } - - // Make the transition - merger.ReachTTD() - merger.FinalizePoS() - - // Verify the blocks after the merging - for i := 0; i < len(postBlocks); i++ { - _, results := engine.VerifyHeaders(chain, []*types.Header{postHeaders[i]}) - // Wait for the verification result - select { - case result := <-results: - if result != nil { - t.Errorf("post-block %d: verification failed %v", i, result) - } - case <-time.After(time.Second): - t.Fatalf("test %d: verification timeout", i) - } - // Make sure no more data is returned - select { - case result := <-results: - t.Fatalf("post-block %d: unexpected result returned: %v", i, result) - case <-time.After(25 * time.Millisecond): - } - chain.InsertBlockWithoutSetHead(postBlocks[i]) - } - - // Verify the blocks with pre-merge blocks and post-merge blocks - var headers []*types.Header - for _, block := range preBlocks { - headers = append(headers, block.Header()) - } - for _, block := range postBlocks { - headers = append(headers, block.Header()) - } - _, results := engine.VerifyHeaders(chain, headers) - for i := 0; i < len(headers); i++ { - select { - case result := <-results: - if result != nil { - t.Errorf("test %d: verification failed %v", i, result) - } - case <-time.After(time.Second): - t.Fatalf("test %d: verification timeout", i) - } - } - // Make sure no more data is returned - select { - case result := <-results: - t.Fatalf("unexpected result returned: %v", result) - case <-time.After(25 * time.Millisecond): - } -} - -func TestCalcGasLimit(t *testing.T) { - for i, tc := range []struct { - pGasLimit uint64 - max uint64 - min uint64 - }{ - {20000000, 20019530, 19980470}, - {40000000, 40039061, 39960939}, - } { - // Increase - if have, want := CalcGasLimit(tc.pGasLimit, 2*tc.pGasLimit), tc.max; have != want { - t.Errorf("test %d: have %d want <%d", i, have, want) - } - // Decrease - if have, want := CalcGasLimit(tc.pGasLimit, 0), tc.min; have != want { - t.Errorf("test %d: have %d want >%d", i, have, want) - } - // Small decrease - if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit-1), tc.pGasLimit-1; have != want { - t.Errorf("test %d: have %d want %d", i, have, want) - } - // Small increase - if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit+1), tc.pGasLimit+1; have != want { - t.Errorf("test %d: have %d want %d", i, have, want) - } - // No change - if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit), tc.pGasLimit; have != want { - t.Errorf("test %d: have %d want %d", i, have, want) - } - } -} diff --git a/builder/core/blockchain.go b/builder/core/blockchain.go deleted file mode 100644 index 88308a795..000000000 --- a/builder/core/blockchain.go +++ /dev/null @@ -1,2601 +0,0 @@ -// 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 core implements the Ethereum consensus protocol. -package core - -import ( - "errors" - "fmt" - "io" - "math/big" - "runtime" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/syncx" - "github.com/ethereum/go-ethereum/internal/version" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" - "golang.org/x/exp/slices" -) - -var ( - headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil) - headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) - headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) - headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil) - headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil) - - chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil) - - accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) - accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) - accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil) - accountCommitTimer = metrics.NewRegisteredTimer("chain/account/commits", nil) - - storageReadTimer = metrics.NewRegisteredTimer("chain/storage/reads", nil) - storageHashTimer = metrics.NewRegisteredTimer("chain/storage/hashes", nil) - storageUpdateTimer = metrics.NewRegisteredTimer("chain/storage/updates", nil) - storageCommitTimer = metrics.NewRegisteredTimer("chain/storage/commits", nil) - - snapshotAccountReadTimer = metrics.NewRegisteredTimer("chain/snapshot/account/reads", nil) - snapshotStorageReadTimer = metrics.NewRegisteredTimer("chain/snapshot/storage/reads", nil) - snapshotCommitTimer = metrics.NewRegisteredTimer("chain/snapshot/commits", nil) - - triedbCommitTimer = metrics.NewRegisteredTimer("chain/triedb/commits", nil) - - blockInsertTimer = metrics.NewRegisteredTimer("chain/inserts", nil) - blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil) - blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil) - blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil) - - blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil) - blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) - blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) - - blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) - blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) - - errInsertionInterrupted = errors.New("insertion is interrupted") - errChainStopped = errors.New("blockchain is stopped") - errInvalidOldChain = errors.New("invalid old chain") - errInvalidNewChain = errors.New("invalid new chain") -) - -const ( - bodyCacheLimit = 256 - blockCacheLimit = 256 - receiptsCacheLimit = 32 - txLookupCacheLimit = 1024 - maxFutureBlocks = 256 - maxTimeFutureBlocks = 30 - TriesInMemory = 128 - - // BlockChainVersion ensures that an incompatible database forces a resync from scratch. - // - // Changelog: - // - // - Version 4 - // The following incompatible database changes were added: - // * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted - // * the `Bloom` field of receipt is deleted - // * the `BlockIndex` and `TxIndex` fields of txlookup are deleted - // - Version 5 - // The following incompatible database changes were added: - // * the `TxHash`, `GasCost`, and `ContractAddress` fields are no longer stored for a receipt - // * the `TxHash`, `GasCost`, and `ContractAddress` fields are computed by looking up the - // receipts' corresponding block - // - Version 6 - // The following incompatible database changes were added: - // * Transaction lookup information stores the corresponding block number instead of block hash - // - Version 7 - // The following incompatible database changes were added: - // * Use freezer as the ancient database to maintain all ancient data - // - Version 8 - // The following incompatible database changes were added: - // * New scheme for contract code in order to separate the codes and trie nodes - BlockChainVersion uint64 = 8 -) - -// CacheConfig contains the configuration values for the trie database -// and state snapshot these are resident in a blockchain. -type CacheConfig struct { - TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory - TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks - TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk - TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node) - TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk - SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory - Preimages bool // Whether to store preimage of trie key to the disk - StateHistory uint64 // Number of blocks from head whose state histories are reserved. - StateScheme string // Scheme used to store ethereum states and merkle tree nodes on top - - SnapshotNoBuild bool // Whether the background generation is allowed - SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it -} - -// triedbConfig derives the configures for trie database. -func (c *CacheConfig) triedbConfig() *triedb.Config { - config := &triedb.Config{Preimages: c.Preimages} - if c.StateScheme == rawdb.HashScheme { - config.HashDB = &hashdb.Config{ - CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, - } - } - if c.StateScheme == rawdb.PathScheme { - config.PathDB = &pathdb.Config{ - StateHistory: c.StateHistory, - CleanCacheSize: c.TrieCleanLimit * 1024 * 1024, - DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024, - } - } - return config -} - -// defaultCacheConfig are the default caching values if none are specified by the -// user (also used during testing). -var defaultCacheConfig = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: true, - StateScheme: rawdb.HashScheme, -} - -// DefaultCacheConfigWithScheme returns a deep copied default cache config with -// a provided trie node scheme. -func DefaultCacheConfigWithScheme(scheme string) *CacheConfig { - config := *defaultCacheConfig - config.StateScheme = scheme - return &config -} - -// txLookup is wrapper over transaction lookup along with the corresponding -// transaction object. -type txLookup struct { - lookup *rawdb.LegacyTxLookupEntry - transaction *types.Transaction -} - -// BlockChain represents the canonical chain given a database with a genesis -// block. The Blockchain manages chain imports, reverts, chain reorganisations. -// -// Importing blocks in to the block chain happens according to the set of rules -// defined by the two stage Validator. Processing of blocks is done using the -// Processor which processes the included transaction. The validation of the state -// is done in the second part of the Validator. Failing results in aborting of -// the import. -// -// The BlockChain also helps in returning blocks from **any** chain included -// in the database as well as blocks that represents the canonical chain. It's -// important to note that GetBlock can return any block and does not need to be -// included in the canonical one where as GetBlockByNumber always represents the -// canonical chain. -type BlockChain struct { - chainConfig *params.ChainConfig // Chain & network configuration - cacheConfig *CacheConfig // Cache configuration for pruning - - db ethdb.Database // Low level persistent database to store final content in - snaps *snapshot.Tree // Snapshot tree for fast trie leaf access - triegc *prque.Prque[int64, common.Hash] // Priority queue mapping block numbers to tries to gc - gcproc time.Duration // Accumulates canonical block processing for trie dumping - lastWrite uint64 // Last block when the state was flushed - flushInterval atomic.Int64 // Time interval (processing time) after which to flush a state - triedb *triedb.Database // The database handler for maintaining trie nodes. - stateCache state.Database // State database to reuse between imports (contains state cache) - txIndexer *txIndexer // Transaction indexer, might be nil if not enabled - - hc *HeaderChain - rmLogsFeed event.Feed - chainFeed event.Feed - chainSideFeed event.Feed - chainHeadFeed event.Feed - logsFeed event.Feed - blockProcFeed event.Feed - scope event.SubscriptionScope - genesisBlock *types.Block - - // This mutex synchronizes chain write operations. - // Readers don't need to take it, they can just read the database. - chainmu *syncx.ClosableMutex - - currentBlock atomic.Pointer[types.Header] // Current head of the chain - currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync - currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block - currentSafeBlock atomic.Pointer[types.Header] // Latest (consensus) safe block - - bodyCache *lru.Cache[common.Hash, *types.Body] - bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] - receiptsCache *lru.Cache[common.Hash, []*types.Receipt] - blockCache *lru.Cache[common.Hash, *types.Block] - txLookupCache *lru.Cache[common.Hash, txLookup] - - // future blocks are blocks added for later processing - futureBlocks *lru.Cache[common.Hash, *types.Block] - - wg sync.WaitGroup - quit chan struct{} // shutdown signal, closed in Stop. - stopping atomic.Bool // false if chain is running, true when stopped - procInterrupt atomic.Bool // interrupt signaler for block processing - - engine consensus.Engine - validator Validator // Block and state validator interface - prefetcher Prefetcher - processor Processor // Block transaction processor interface - forker *ForkChoice - vmConfig vm.Config -} - -// NewBlockChain returns a fully initialised block chain using information -// available in the database. It initialises the default Ethereum Validator -// and Processor. -func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) { - if cacheConfig == nil { - cacheConfig = defaultCacheConfig - } - // Open trie database with provided config - triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig()) - - // Setup the genesis block, commit the provided genesis specification - // to database if the genesis block is not present yet, or load the - // stored one from database. - chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) - if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { - return nil, genesisErr - } - log.Info("") - log.Info(strings.Repeat("-", 153)) - for _, line := range strings.Split(chainConfig.Description(), "\n") { - log.Info(line) - } - log.Info(strings.Repeat("-", 153)) - log.Info("") - - bc := &BlockChain{ - chainConfig: chainConfig, - cacheConfig: cacheConfig, - db: db, - triedb: triedb, - triegc: prque.New[int64, common.Hash](nil), - quit: make(chan struct{}), - chainmu: syncx.NewClosableMutex(), - bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), - bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), - receiptsCache: lru.NewCache[common.Hash, []*types.Receipt](receiptsCacheLimit), - blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), - txLookupCache: lru.NewCache[common.Hash, txLookup](txLookupCacheLimit), - futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks), - engine: engine, - vmConfig: vmConfig, - } - bc.flushInterval.Store(int64(cacheConfig.TrieTimeLimit)) - bc.forker = NewForkChoice(bc, shouldPreserve) - bc.stateCache = state.NewDatabaseWithNodeDB(bc.db, bc.triedb) - bc.validator = NewBlockValidator(chainConfig, bc, engine) - bc.prefetcher = newStatePrefetcher(chainConfig, bc, engine) - bc.processor = NewStateProcessor(chainConfig, bc, engine) - - var err error - bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped) - if err != nil { - return nil, err - } - bc.genesisBlock = bc.GetBlockByNumber(0) - if bc.genesisBlock == nil { - return nil, ErrNoGenesis - } - - bc.currentBlock.Store(nil) - bc.currentSnapBlock.Store(nil) - bc.currentFinalBlock.Store(nil) - bc.currentSafeBlock.Store(nil) - - // Update chain info data metrics - chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()}) - - // If Geth is initialized with an external ancient store, re-initialize the - // missing chain indexes and chain flags. This procedure can survive crash - // and can be resumed in next restart since chain flags are updated in last step. - if bc.empty() { - rawdb.InitDatabaseFromFreezer(bc.db) - } - // Load blockchain states from disk - if err := bc.loadLastState(); err != nil { - return nil, err - } - // Make sure the state associated with the block is available, or log out - // if there is no available state, waiting for state sync. - head := bc.CurrentBlock() - if !bc.HasState(head.Root) { - if head.Number.Uint64() == 0 { - // The genesis state is missing, which is only possible in the path-based - // scheme. This situation occurs when the initial state sync is not finished - // yet, or the chain head is rewound below the pivot point. In both scenarios, - // there is no possible recovery approach except for rerunning a snap sync. - // Do nothing here until the state syncer picks it up. - log.Info("Genesis state is missing, wait state sync") - } else { - // Head state is missing, before the state recovery, find out the - // disk layer point of snapshot(if it's enabled). Make sure the - // rewound point is lower than disk layer. - var diskRoot common.Hash - if bc.cacheConfig.SnapshotLimit > 0 { - diskRoot = rawdb.ReadSnapshotRoot(bc.db) - } - if diskRoot != (common.Hash{}) { - log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash(), "snaproot", diskRoot) - - snapDisk, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, diskRoot, true) - if err != nil { - return nil, err - } - // Chain rewound, persist old snapshot number to indicate recovery procedure - if snapDisk != 0 { - rawdb.WriteSnapshotRecoveryNumber(bc.db, snapDisk) - } - } else { - log.Warn("Head state missing, repairing", "number", head.Number, "hash", head.Hash()) - if _, err := bc.setHeadBeyondRoot(head.Number.Uint64(), 0, common.Hash{}, true); err != nil { - return nil, err - } - } - } - } - // Ensure that a previous crash in SetHead doesn't leave extra ancients - if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 { - var ( - needRewind bool - low uint64 - ) - // The head full block may be rolled back to a very low height due to - // blockchain repair. If the head full block is even lower than the ancient - // chain, truncate the ancient store. - fullBlock := bc.CurrentBlock() - if fullBlock != nil && fullBlock.Hash() != bc.genesisBlock.Hash() && fullBlock.Number.Uint64() < frozen-1 { - needRewind = true - low = fullBlock.Number.Uint64() - } - // In snap sync, it may happen that ancient data has been written to the - // ancient store, but the LastFastBlock has not been updated, truncate the - // extra data here. - snapBlock := bc.CurrentSnapBlock() - if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 { - needRewind = true - if snapBlock.Number.Uint64() < low || low == 0 { - low = snapBlock.Number.Uint64() - } - } - if needRewind { - log.Error("Truncating ancient chain", "from", bc.CurrentHeader().Number.Uint64(), "to", low) - if err := bc.SetHead(low); err != nil { - return nil, err - } - } - } - // The first thing the node will do is reconstruct the verification data for - // the head block (ethash cache or clique voting snapshot). Might as well do - // it in advance. - bc.engine.VerifyHeader(bc, bc.CurrentHeader()) - - // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain - for hash := range BadHashes { - if header := bc.GetHeaderByHash(hash); header != nil { - // get the canonical block corresponding to the offending header's number - headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64()) - // make sure the headerByNumber (if present) is in our current canonical chain - if headerByNumber != nil && headerByNumber.Hash() == header.Hash() { - log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash) - if err := bc.SetHead(header.Number.Uint64() - 1); err != nil { - return nil, err - } - log.Error("Chain rewind was successful, resuming normal operation") - } - } - } - - // Load any existing snapshot, regenerating it if loading failed - if bc.cacheConfig.SnapshotLimit > 0 { - // If the chain was rewound past the snapshot persistent layer (causing - // a recovery block number to be persisted to disk), check if we're still - // in recovery mode and in that case, don't invalidate the snapshot on a - // head mismatch. - var recover bool - - head := bc.CurrentBlock() - if layer := rawdb.ReadSnapshotRecoveryNumber(bc.db); layer != nil && *layer >= head.Number.Uint64() { - log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer) - recover = true - } - snapconfig := snapshot.Config{ - CacheSize: bc.cacheConfig.SnapshotLimit, - Recovery: recover, - NoBuild: bc.cacheConfig.SnapshotNoBuild, - AsyncBuild: !bc.cacheConfig.SnapshotWait, - } - bc.snaps, _ = snapshot.New(snapconfig, bc.db, bc.triedb, head.Root) - } - - // Start future block processor. - bc.wg.Add(1) - go bc.updateFutureBlocks() - - // Rewind the chain in case of an incompatible config upgrade. - if compat, ok := genesisErr.(*params.ConfigCompatError); ok { - log.Warn("Rewinding chain to upgrade configuration", "err", compat) - if compat.RewindToTime > 0 { - bc.SetHeadWithTimestamp(compat.RewindToTime) - } else { - bc.SetHead(compat.RewindToBlock) - } - rawdb.WriteChainConfig(db, genesisHash, chainConfig) - } - // Start tx indexer if it's enabled. - if txLookupLimit != nil { - bc.txIndexer = newTxIndexer(*txLookupLimit, bc) - } - return bc, nil -} - -// empty returns an indicator whether the blockchain is empty. -// Note, it's a special case that we connect a non-empty ancient -// database with an empty node, so that we can plugin the ancient -// into node seamlessly. -func (bc *BlockChain) empty() bool { - genesis := bc.genesisBlock.Hash() - for _, hash := range []common.Hash{rawdb.ReadHeadBlockHash(bc.db), rawdb.ReadHeadHeaderHash(bc.db), rawdb.ReadHeadFastBlockHash(bc.db)} { - if hash != genesis { - return false - } - } - return true -} - -// loadLastState loads the last known chain state from the database. This method -// assumes that the chain manager mutex is held. -func (bc *BlockChain) loadLastState() error { - // Restore the last known head block - head := rawdb.ReadHeadBlockHash(bc.db) - if head == (common.Hash{}) { - // Corrupt or empty database, init from scratch - log.Warn("Empty database, resetting chain") - return bc.Reset() - } - // Make sure the entire head block is available - headBlock := bc.GetBlockByHash(head) - if headBlock == nil { - // Corrupt or empty database, init from scratch - log.Warn("Head block missing, resetting chain", "hash", head) - return bc.Reset() - } - // Everything seems to be fine, set as the head block - bc.currentBlock.Store(headBlock.Header()) - headBlockGauge.Update(int64(headBlock.NumberU64())) - - // Restore the last known head header - headHeader := headBlock.Header() - if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) { - if header := bc.GetHeaderByHash(head); header != nil { - headHeader = header - } - } - bc.hc.SetCurrentHeader(headHeader) - - // Restore the last known head snap block - bc.currentSnapBlock.Store(headBlock.Header()) - headFastBlockGauge.Update(int64(headBlock.NumberU64())) - - if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { - if block := bc.GetBlockByHash(head); block != nil { - bc.currentSnapBlock.Store(block.Header()) - headFastBlockGauge.Update(int64(block.NumberU64())) - } - } - - // Restore the last known finalized block and safe block - // Note: the safe block is not stored on disk and it is set to the last - // known finalized block on startup - if head := rawdb.ReadFinalizedBlockHash(bc.db); head != (common.Hash{}) { - if block := bc.GetBlockByHash(head); block != nil { - bc.currentFinalBlock.Store(block.Header()) - headFinalizedBlockGauge.Update(int64(block.NumberU64())) - bc.currentSafeBlock.Store(block.Header()) - headSafeBlockGauge.Update(int64(block.NumberU64())) - } - } - // Issue a status log for the user - var ( - currentSnapBlock = bc.CurrentSnapBlock() - currentFinalBlock = bc.CurrentFinalBlock() - - headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64()) - blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64()) - ) - if headHeader.Hash() != headBlock.Hash() { - log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0))) - } - log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0))) - if headBlock.Hash() != currentSnapBlock.Hash() { - snapTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64()) - log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", snapTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0))) - } - if currentFinalBlock != nil { - finalTd := bc.GetTd(currentFinalBlock.Hash(), currentFinalBlock.Number.Uint64()) - log.Info("Loaded most recent local finalized block", "number", currentFinalBlock.Number, "hash", currentFinalBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalBlock.Time), 0))) - } - if pivot := rawdb.ReadLastPivotNumber(bc.db); pivot != nil { - log.Info("Loaded last snap-sync pivot marker", "number", *pivot) - } - return nil -} - -// SetHead rewinds the local chain to a new head. Depending on whether the node -// was snap synced or full synced and in which state, the method will try to -// delete minimal data from disk whilst retaining chain consistency. -func (bc *BlockChain) SetHead(head uint64) error { - if _, err := bc.setHeadBeyondRoot(head, 0, common.Hash{}, false); err != nil { - return err - } - // Send chain head event to update the transaction pool - header := bc.CurrentBlock() - block := bc.GetBlock(header.Hash(), header.Number.Uint64()) - if block == nil { - // This should never happen. In practice, previously currentBlock - // contained the entire block whereas now only a "marker", so there - // is an ever so slight chance for a race we should handle. - log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) - return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) - } - bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) - return nil -} - -// SetHeadWithTimestamp rewinds the local chain to a new head that has at max -// the given timestamp. Depending on whether the node was snap synced or full -// synced and in which state, the method will try to delete minimal data from -// disk whilst retaining chain consistency. -func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error { - if _, err := bc.setHeadBeyondRoot(0, timestamp, common.Hash{}, false); err != nil { - return err - } - // Send chain head event to update the transaction pool - header := bc.CurrentBlock() - block := bc.GetBlock(header.Hash(), header.Number.Uint64()) - if block == nil { - // This should never happen. In practice, previously currentBlock - // contained the entire block whereas now only a "marker", so there - // is an ever so slight chance for a race we should handle. - log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) - return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) - } - bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) - return nil -} - -// SetFinalized sets the finalized block. -func (bc *BlockChain) SetFinalized(header *types.Header) { - bc.currentFinalBlock.Store(header) - if header != nil { - rawdb.WriteFinalizedBlockHash(bc.db, header.Hash()) - headFinalizedBlockGauge.Update(int64(header.Number.Uint64())) - } else { - rawdb.WriteFinalizedBlockHash(bc.db, common.Hash{}) - headFinalizedBlockGauge.Update(0) - } -} - -// SetSafe sets the safe block. -func (bc *BlockChain) SetSafe(header *types.Header) { - bc.currentSafeBlock.Store(header) - if header != nil { - headSafeBlockGauge.Update(int64(header.Number.Uint64())) - } else { - headSafeBlockGauge.Update(0) - } -} - -// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition -// that the rewind must pass the specified state root. This method is meant to be -// used when rewinding with snapshots enabled to ensure that we go back further than -// persistent disk layer. Depending on whether the node was snap synced or full, and -// in which state, the method will try to delete minimal data from disk whilst -// retaining chain consistency. -// -// The method also works in timestamp mode if `head == 0` but `time != 0`. In that -// case blocks are rolled back until the new head becomes older or equal to the -// requested time. If both `head` and `time` is 0, the chain is rewound to genesis. -// -// The method returns the block number where the requested root cap was found. -func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Hash, repair bool) (uint64, error) { - if !bc.chainmu.TryLock() { - return 0, errChainStopped - } - defer bc.chainmu.Unlock() - - // Track the block number of the requested root hash - var rootNumber uint64 // (no root == always 0) - - // Retrieve the last pivot block to short circuit rollbacks beyond it and the - // current freezer limit to start nuking id underflown - pivot := rawdb.ReadLastPivotNumber(bc.db) - frozen, _ := bc.db.Ancients() - - updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (*types.Header, bool) { - // Rewind the blockchain, ensuring we don't end up with a stateless head - // block. Note, depth equality is permitted to allow using SetHead as a - // chain reparation mechanism without deleting any data! - if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.Number.Uint64() { - newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) - if newHeadBlock == nil { - log.Error("Gap in the chain, rewinding to genesis", "number", header.Number, "hash", header.Hash()) - newHeadBlock = bc.genesisBlock - } else { - // Block exists. Keep rewinding until either we find one with state - // or until we exceed the optional threshold root hash - beyondRoot := (root == common.Hash{}) // Flag whether we're beyond the requested root (no root, always true) - - for { - // If a root threshold was requested but not yet crossed, check - if root != (common.Hash{}) && !beyondRoot && newHeadBlock.Root() == root { - beyondRoot, rootNumber = true, newHeadBlock.NumberU64() - } - if !bc.HasState(newHeadBlock.Root()) && !bc.stateRecoverable(newHeadBlock.Root()) { - log.Trace("Block state missing, rewinding further", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) - if pivot == nil || newHeadBlock.NumberU64() > *pivot { - parent := bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) - if parent != nil { - newHeadBlock = parent - continue - } - log.Error("Missing block in the middle, aiming genesis", "number", newHeadBlock.NumberU64()-1, "hash", newHeadBlock.ParentHash()) - newHeadBlock = bc.genesisBlock - } else { - log.Trace("Rewind passed pivot, aiming genesis", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "pivot", *pivot) - newHeadBlock = bc.genesisBlock - } - } - if beyondRoot || newHeadBlock.NumberU64() == 0 { - if !bc.HasState(newHeadBlock.Root()) && bc.stateRecoverable(newHeadBlock.Root()) { - // Rewind to a block with recoverable state. If the state is - // missing, run the state recovery here. - if err := bc.triedb.Recover(newHeadBlock.Root()); err != nil { - log.Crit("Failed to rollback state", "err", err) // Shouldn't happen - } - log.Debug("Rewound to block with state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash()) - } - break - } - log.Debug("Skipping block with threshold state", "number", newHeadBlock.NumberU64(), "hash", newHeadBlock.Hash(), "root", newHeadBlock.Root()) - newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) // Keep rewinding - } - } - rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash()) - - // Degrade the chain markers if they are explicitly reverted. - // In theory we should update all in-memory markers in the - // last step, however the direction of SetHead is from high - // to low, so it's safe to update in-memory markers directly. - bc.currentBlock.Store(newHeadBlock.Header()) - headBlockGauge.Update(int64(newHeadBlock.NumberU64())) - - // The head state is missing, which is only possible in the path-based - // scheme. This situation occurs when the chain head is rewound below - // the pivot point. In this scenario, there is no possible recovery - // approach except for rerunning a snap sync. Do nothing here until the - // state syncer picks it up. - if !bc.HasState(newHeadBlock.Root()) { - log.Info("Chain is stateless, wait state sync", "number", newHeadBlock.Number(), "hash", newHeadBlock.Hash()) - } - } - // Rewind the snap block in a simpleton way to the target head - if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() { - newHeadSnapBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) - // If either blocks reached nil, reset to the genesis state - if newHeadSnapBlock == nil { - newHeadSnapBlock = bc.genesisBlock - } - rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash()) - - // Degrade the chain markers if they are explicitly reverted. - // In theory we should update all in-memory markers in the - // last step, however the direction of SetHead is from high - // to low, so it's safe the update in-memory markers directly. - bc.currentSnapBlock.Store(newHeadSnapBlock.Header()) - headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64())) - } - var ( - headHeader = bc.CurrentBlock() - headNumber = headHeader.Number.Uint64() - ) - // If setHead underflown the freezer threshold and the block processing - // intent afterwards is full block importing, delete the chain segment - // between the stateful-block and the sethead target. - var wipe bool - if headNumber+1 < frozen { - wipe = pivot == nil || headNumber >= *pivot - } - return headHeader, wipe // Only force wipe if full synced - } - // Rewind the header chain, deleting all block bodies until then - delFn := func(db ethdb.KeyValueWriter, hash common.Hash, num uint64) { - // Ignore the error here since light client won't hit this path - frozen, _ := bc.db.Ancients() - if num+1 <= frozen { - // Truncate all relative data(header, total difficulty, body, receipt - // and canonical hash) from ancient store. - if _, err := bc.db.TruncateHead(num); err != nil { - log.Crit("Failed to truncate ancient data", "number", num, "err", err) - } - // Remove the hash <-> number mapping from the active store. - rawdb.DeleteHeaderNumber(db, hash) - } else { - // Remove relative body and receipts from the active store. - // The header, total difficulty and canonical hash will be - // removed in the hc.SetHead function. - rawdb.DeleteBody(db, hash, num) - rawdb.DeleteReceipts(db, hash, num) - } - // Todo(rjl493456442) txlookup, bloombits, etc - } - // If SetHead was only called as a chain reparation method, try to skip - // touching the header chain altogether, unless the freezer is broken - if repair { - if target, force := updateFn(bc.db, bc.CurrentBlock()); force { - bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn) - } - } else { - // Rewind the chain to the requested head and keep going backwards until a - // block with a state is found or snap sync pivot is passed - if time > 0 { - log.Warn("Rewinding blockchain to timestamp", "target", time) - bc.hc.SetHeadWithTimestamp(time, updateFn, delFn) - } else { - log.Warn("Rewinding blockchain to block", "target", head) - bc.hc.SetHead(head, updateFn, delFn) - } - } - // Clear out any stale content from the caches - bc.bodyCache.Purge() - bc.bodyRLPCache.Purge() - bc.receiptsCache.Purge() - bc.blockCache.Purge() - bc.txLookupCache.Purge() - bc.futureBlocks.Purge() - - // Clear safe block, finalized block if needed - if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() { - log.Warn("SetHead invalidated safe block") - bc.SetSafe(nil) - } - if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() { - log.Error("SetHead invalidated finalized block") - bc.SetFinalized(nil) - } - return rootNumber, bc.loadLastState() -} - -// SnapSyncCommitHead sets the current head block to the one defined by the hash -// irrelevant what the chain contents were prior. -func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error { - // Make sure that both the block as well at its state trie exists - block := bc.GetBlockByHash(hash) - if block == nil { - return fmt.Errorf("non existent block [%x..]", hash[:4]) - } - // Reset the trie database with the fresh snap synced state. - root := block.Root() - if bc.triedb.Scheme() == rawdb.PathScheme { - if err := bc.triedb.Enable(root); err != nil { - return err - } - } - if !bc.HasState(root) { - return fmt.Errorf("non existent state [%x..]", root[:4]) - } - // If all checks out, manually set the head block. - if !bc.chainmu.TryLock() { - return errChainStopped - } - bc.currentBlock.Store(block.Header()) - headBlockGauge.Update(int64(block.NumberU64())) - bc.chainmu.Unlock() - - // Destroy any existing state snapshot and regenerate it in the background, - // also resuming the normal maintenance of any previously paused snapshot. - if bc.snaps != nil { - bc.snaps.Rebuild(root) - } - log.Info("Committed new head block", "number", block.Number(), "hash", hash) - return nil -} - -// Reset purges the entire blockchain, restoring it to its genesis state. -func (bc *BlockChain) Reset() error { - return bc.ResetWithGenesisBlock(bc.genesisBlock) -} - -// ResetWithGenesisBlock purges the entire blockchain, restoring it to the -// specified genesis state. -func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error { - // Dump the entire block chain and purge the caches - if err := bc.SetHead(0); err != nil { - return err - } - if !bc.chainmu.TryLock() { - return errChainStopped - } - defer bc.chainmu.Unlock() - - // Prepare the genesis block and reinitialise the chain - batch := bc.db.NewBatch() - rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) - rawdb.WriteBlock(batch, genesis) - if err := batch.Write(); err != nil { - log.Crit("Failed to write genesis block", "err", err) - } - bc.writeHeadBlock(genesis) - - // Last update all in-memory chain markers - bc.genesisBlock = genesis - bc.currentBlock.Store(bc.genesisBlock.Header()) - headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) - bc.hc.SetGenesis(bc.genesisBlock.Header()) - bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) - bc.currentSnapBlock.Store(bc.genesisBlock.Header()) - headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) - return nil -} - -// Export writes the active chain to the given writer. -func (bc *BlockChain) Export(w io.Writer) error { - return bc.ExportN(w, uint64(0), bc.CurrentBlock().Number.Uint64()) -} - -// ExportN writes a subset of the active chain to the given writer. -func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error { - if first > last { - return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last) - } - log.Info("Exporting batch of blocks", "count", last-first+1) - - var ( - parentHash common.Hash - start = time.Now() - reported = time.Now() - ) - for nr := first; nr <= last; nr++ { - block := bc.GetBlockByNumber(nr) - if block == nil { - return fmt.Errorf("export failed on #%d: not found", nr) - } - if nr > first && block.ParentHash() != parentHash { - return errors.New("export failed: chain reorg during export") - } - parentHash = block.Hash() - if err := block.EncodeRLP(w); err != nil { - return err - } - if time.Since(reported) >= statsReportLimit { - log.Info("Exporting blocks", "exported", block.NumberU64()-first, "elapsed", common.PrettyDuration(time.Since(start))) - reported = time.Now() - } - } - return nil -} - -// writeHeadBlock injects a new head block into the current block chain. This method -// assumes that the block is indeed a true head. It will also reset the head -// header and the head snap sync block to this very same block if they are older -// or if they are on a different side chain. -// -// Note, this function assumes that the `mu` mutex is held! -func (bc *BlockChain) writeHeadBlock(block *types.Block) { - // Add the block to the canonical chain number scheme and mark as the head - batch := bc.db.NewBatch() - rawdb.WriteHeadHeaderHash(batch, block.Hash()) - rawdb.WriteHeadFastBlockHash(batch, block.Hash()) - rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) - rawdb.WriteTxLookupEntriesByBlock(batch, block) - rawdb.WriteHeadBlockHash(batch, block.Hash()) - - // Flush the whole batch into the disk, exit the node if failed - if err := batch.Write(); err != nil { - log.Crit("Failed to update chain indexes and markers", "err", err) - } - // Update all in-memory chain markers in the last step - bc.hc.SetCurrentHeader(block.Header()) - - bc.currentSnapBlock.Store(block.Header()) - headFastBlockGauge.Update(int64(block.NumberU64())) - - bc.currentBlock.Store(block.Header()) - headBlockGauge.Update(int64(block.NumberU64())) -} - -// stopWithoutSaving stops the blockchain service. If any imports are currently in progress -// it will abort them using the procInterrupt. This method stops all running -// goroutines, but does not do all the post-stop work of persisting data. -// OBS! It is generally recommended to use the Stop method! -// This method has been exposed to allow tests to stop the blockchain while simulating -// a crash. -func (bc *BlockChain) stopWithoutSaving() { - if !bc.stopping.CompareAndSwap(false, true) { - return - } - // Signal shutdown tx indexer. - if bc.txIndexer != nil { - bc.txIndexer.close() - } - // Unsubscribe all subscriptions registered from blockchain. - bc.scope.Close() - - // Signal shutdown to all goroutines. - close(bc.quit) - bc.StopInsert() - - // Now wait for all chain modifications to end and persistent goroutines to exit. - // - // Note: Close waits for the mutex to become available, i.e. any running chain - // modification will have exited when Close returns. Since we also called StopInsert, - // the mutex should become available quickly. It cannot be taken again after Close has - // returned. - bc.chainmu.Close() - bc.wg.Wait() -} - -// Stop stops the blockchain service. If any imports are currently in progress -// it will abort them using the procInterrupt. -func (bc *BlockChain) Stop() { - bc.stopWithoutSaving() - - // Ensure that the entirety of the state snapshot is journaled to disk. - var snapBase common.Hash - if bc.snaps != nil { - var err error - if snapBase, err = bc.snaps.Journal(bc.CurrentBlock().Root); err != nil { - log.Error("Failed to journal state snapshot", "err", err) - } - bc.snaps.Release() - } - if bc.triedb.Scheme() == rawdb.PathScheme { - // Ensure that the in-memory trie nodes are journaled to disk properly. - if err := bc.triedb.Journal(bc.CurrentBlock().Root); err != nil { - log.Info("Failed to journal in-memory trie nodes", "err", err) - } - } else { - // Ensure the state of a recent block is also stored to disk before exiting. - // We're writing three different states to catch different restart scenarios: - // - HEAD: So we don't need to reprocess any blocks in the general case - // - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle - // - HEAD-127: So we have a hard limit on the number of blocks reexecuted - if !bc.cacheConfig.TrieDirtyDisabled { - triedb := bc.triedb - - for _, offset := range []uint64{0, 1, TriesInMemory - 1} { - if number := bc.CurrentBlock().Number.Uint64(); number > offset { - recent := bc.GetBlockByNumber(number - offset) - - log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) - if err := triedb.Commit(recent.Root(), true); err != nil { - log.Error("Failed to commit recent state trie", "err", err) - } - } - } - if snapBase != (common.Hash{}) { - log.Info("Writing snapshot state to disk", "root", snapBase) - if err := triedb.Commit(snapBase, true); err != nil { - log.Error("Failed to commit recent state trie", "err", err) - } - } - for !bc.triegc.Empty() { - triedb.Dereference(bc.triegc.PopItem()) - } - if _, nodes, _ := triedb.Size(); nodes != 0 { // all memory is contained within the nodes return for hashdb - log.Error("Dangling trie nodes after full cleanup") - } - } - } - // Close the trie database, release all the held resources as the last step. - if err := bc.triedb.Close(); err != nil { - log.Error("Failed to close trie database", "err", err) - } - log.Info("Blockchain stopped") -} - -// StopInsert interrupts all insertion methods, causing them to return -// errInsertionInterrupted as soon as possible. Insertion is permanently disabled after -// calling this method. -func (bc *BlockChain) StopInsert() { - bc.procInterrupt.Store(true) -} - -// insertStopped returns true after StopInsert has been called. -func (bc *BlockChain) insertStopped() bool { - return bc.procInterrupt.Load() -} - -func (bc *BlockChain) procFutureBlocks() { - blocks := make([]*types.Block, 0, bc.futureBlocks.Len()) - for _, hash := range bc.futureBlocks.Keys() { - if block, exist := bc.futureBlocks.Peek(hash); exist { - blocks = append(blocks, block) - } - } - if len(blocks) > 0 { - slices.SortFunc(blocks, func(a, b *types.Block) int { - return a.Number().Cmp(b.Number()) - }) - // Insert one by one as chain insertion needs contiguous ancestry between blocks - for i := range blocks { - bc.InsertChain(blocks[i : i+1]) - } - } -} - -// WriteStatus status of write -type WriteStatus byte - -const ( - NonStatTy WriteStatus = iota - CanonStatTy - SideStatTy -) - -// InsertReceiptChain attempts to complete an already existing header chain with -// transaction and receipt data. -func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) { - // We don't require the chainMu here since we want to maximize the - // concurrency of header insertion and receipt insertion. - bc.wg.Add(1) - defer bc.wg.Done() - - var ( - ancientBlocks, liveBlocks types.Blocks - ancientReceipts, liveReceipts []types.Receipts - ) - // Do a sanity check that the provided chain is actually ordered and linked - for i, block := range blockChain { - if i != 0 { - prev := blockChain[i-1] - if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() { - log.Error("Non contiguous receipt insert", - "number", block.Number(), "hash", block.Hash(), "parent", block.ParentHash(), - "prevnumber", prev.Number(), "prevhash", prev.Hash()) - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", - i-1, prev.NumberU64(), prev.Hash().Bytes()[:4], - i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4]) - } - } - if block.NumberU64() <= ancientLimit { - ancientBlocks, ancientReceipts = append(ancientBlocks, block), append(ancientReceipts, receiptChain[i]) - } else { - liveBlocks, liveReceipts = append(liveBlocks, block), append(liveReceipts, receiptChain[i]) - } - - // Here we also validate that blob transactions in the block do not contain a sidecar. - // While the sidecar does not affect the block hash / tx hash, sending blobs within a block is not allowed. - for txIndex, tx := range block.Transactions() { - if tx.Type() == types.BlobTxType && tx.BlobTxSidecar() != nil { - return 0, fmt.Errorf("block #%d contains unexpected blob sidecar in tx at index %d", block.NumberU64(), txIndex) - } - } - } - - var ( - stats = struct{ processed, ignored int32 }{} - start = time.Now() - size = int64(0) - ) - - // updateHead updates the head snap sync block if the inserted blocks are better - // and returns an indicator whether the inserted blocks are canonical. - updateHead := func(head *types.Block) bool { - if !bc.chainmu.TryLock() { - return false - } - defer bc.chainmu.Unlock() - - // Rewind may have occurred, skip in that case. - if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 { - reorg, err := bc.forker.ReorgNeeded(bc.CurrentSnapBlock(), head.Header()) - if err != nil { - log.Warn("Reorg failed", "err", err) - return false - } else if !reorg { - return false - } - rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) - bc.currentSnapBlock.Store(head.Header()) - headFastBlockGauge.Update(int64(head.NumberU64())) - return true - } - return false - } - // writeAncient writes blockchain and corresponding receipt chain into ancient store. - // - // this function only accepts canonical chain data. All side chain will be reverted - // eventually. - writeAncient := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { - first := blockChain[0] - last := blockChain[len(blockChain)-1] - - // Ensure genesis is in ancients. - if first.NumberU64() == 1 { - if frozen, _ := bc.db.Ancients(); frozen == 0 { - td := bc.genesisBlock.Difficulty() - writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td) - if err != nil { - log.Error("Error writing genesis to ancients", "err", err) - return 0, err - } - size += writeSize - log.Info("Wrote genesis to ancients") - } - } - // Before writing the blocks to the ancients, we need to ensure that - // they correspond to the what the headerchain 'expects'. - // We only check the last block/header, since it's a contiguous chain. - if !bc.HasHeader(last.Hash(), last.NumberU64()) { - return 0, fmt.Errorf("containing header #%d [%x..] unknown", last.Number(), last.Hash().Bytes()[:4]) - } - - // Write all chain data to ancients. - td := bc.GetTd(first.Hash(), first.NumberU64()) - writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, td) - if err != nil { - log.Error("Error importing chain data to ancients", "err", err) - return 0, err - } - size += writeSize - - // Sync the ancient store explicitly to ensure all data has been flushed to disk. - if err := bc.db.Sync(); err != nil { - return 0, err - } - // Update the current snap block because all block data is now present in DB. - previousSnapBlock := bc.CurrentSnapBlock().Number.Uint64() - if !updateHead(blockChain[len(blockChain)-1]) { - // We end up here if the header chain has reorg'ed, and the blocks/receipts - // don't match the canonical chain. - if _, err := bc.db.TruncateHead(previousSnapBlock + 1); err != nil { - log.Error("Can't truncate ancient store after failed insert", "err", err) - } - return 0, errSideChainReceipts - } - - // Delete block data from the main database. - var ( - batch = bc.db.NewBatch() - canonHashes = make(map[common.Hash]struct{}) - ) - for _, block := range blockChain { - canonHashes[block.Hash()] = struct{}{} - if block.NumberU64() == 0 { - continue - } - rawdb.DeleteCanonicalHash(batch, block.NumberU64()) - rawdb.DeleteBlockWithoutNumber(batch, block.Hash(), block.NumberU64()) - } - // Delete side chain hash-to-number mappings. - for _, nh := range rawdb.ReadAllHashesInRange(bc.db, first.NumberU64(), last.NumberU64()) { - if _, canon := canonHashes[nh.Hash]; !canon { - rawdb.DeleteHeader(batch, nh.Hash, nh.Number) - } - } - if err := batch.Write(); err != nil { - return 0, err - } - stats.processed += int32(len(blockChain)) - return 0, nil - } - - // writeLive writes blockchain and corresponding receipt chain into active store. - writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { - var ( - skipPresenceCheck = false - batch = bc.db.NewBatch() - ) - for i, block := range blockChain { - // Short circuit insertion if shutting down or processing failed - if bc.insertStopped() { - return 0, errInsertionInterrupted - } - // Short circuit if the owner header is unknown - if !bc.HasHeader(block.Hash(), block.NumberU64()) { - return i, fmt.Errorf("containing header #%d [%x..] unknown", block.Number(), block.Hash().Bytes()[:4]) - } - if !skipPresenceCheck { - // Ignore if the entire data is already known - if bc.HasBlock(block.Hash(), block.NumberU64()) { - stats.ignored++ - continue - } else { - // If block N is not present, neither are the later blocks. - // This should be true, but if we are mistaken, the shortcut - // here will only cause overwriting of some existing data - skipPresenceCheck = true - } - } - // Write all the data out into the database - rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()) - rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i]) - - // Write everything belongs to the blocks into the database. So that - // we can ensure all components of body is completed(body, receipts) - // except transaction indexes(will be created once sync is finished). - if batch.ValueSize() >= ethdb.IdealBatchSize { - if err := batch.Write(); err != nil { - return 0, err - } - size += int64(batch.ValueSize()) - batch.Reset() - } - stats.processed++ - } - // Write everything belongs to the blocks into the database. So that - // we can ensure all components of body is completed(body, receipts, - // tx indexes) - if batch.ValueSize() > 0 { - size += int64(batch.ValueSize()) - if err := batch.Write(); err != nil { - return 0, err - } - } - updateHead(blockChain[len(blockChain)-1]) - return 0, nil - } - - // Write downloaded chain data and corresponding receipt chain data - if len(ancientBlocks) > 0 { - if n, err := writeAncient(ancientBlocks, ancientReceipts); err != nil { - if err == errInsertionInterrupted { - return 0, nil - } - return n, err - } - } - if len(liveBlocks) > 0 { - if n, err := writeLive(liveBlocks, liveReceipts); err != nil { - if err == errInsertionInterrupted { - return 0, nil - } - return n, err - } - } - var ( - head = blockChain[len(blockChain)-1] - context = []interface{}{ - "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)), - "number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)), - "size", common.StorageSize(size), - } - ) - if stats.ignored > 0 { - context = append(context, []interface{}{"ignored", stats.ignored}...) - } - log.Debug("Imported new block receipts", context...) - - return 0, nil -} - -// writeBlockWithoutState writes only the block and its metadata to the database, -// but does not write any state. This is used to construct competing side forks -// up to the point where they exceed the canonical total difficulty. -func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (err error) { - if bc.insertStopped() { - return errInsertionInterrupted - } - batch := bc.db.NewBatch() - rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td) - rawdb.WriteBlock(batch, block) - if err := batch.Write(); err != nil { - log.Crit("Failed to write block into disk", "err", err) - } - return nil -} - -// writeKnownBlock updates the head block flag with a known block -// and introduces chain reorg if necessary. -func (bc *BlockChain) writeKnownBlock(block *types.Block) error { - current := bc.CurrentBlock() - if block.ParentHash() != current.Hash() { - if err := bc.reorg(current, block); err != nil { - return err - } - } - bc.writeHeadBlock(block) - return nil -} - -// writeBlockWithState writes block, metadata and corresponding state data to the -// database. -func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error { - // Calculate the total difficulty of the block - ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) - if ptd == nil { - return consensus.ErrUnknownAncestor - } - // Make sure no inconsistent state is leaked during insertion - externTd := new(big.Int).Add(block.Difficulty(), ptd) - - // Irrelevant of the canonical status, write the block itself to the database. - // - // Note all the components of block(td, hash->number map, header, body, receipts) - // should be written atomically. BlockBatch is used for containing all components. - blockBatch := bc.db.NewBatch() - rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd) - rawdb.WriteBlock(blockBatch, block) - rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts) - rawdb.WritePreimages(blockBatch, state.Preimages()) - if err := blockBatch.Write(); err != nil { - log.Crit("Failed to write block into disk", "err", err) - } - // Commit all cached state changes into underlying memory database. - root, err := state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number())) - if err != nil { - return err - } - // If node is running in path mode, skip explicit gc operation - // which is unnecessary in this mode. - if bc.triedb.Scheme() == rawdb.PathScheme { - return nil - } - // If we're running an archive node, always flush - if bc.cacheConfig.TrieDirtyDisabled { - return bc.triedb.Commit(root, false) - } - // Full but not archive node, do proper garbage collection - bc.triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive - bc.triegc.Push(root, -int64(block.NumberU64())) - - // Flush limits are not considered for the first TriesInMemory blocks. - current := block.NumberU64() - if current <= TriesInMemory { - return nil - } - // If we exceeded our memory allowance, flush matured singleton nodes to disk - var ( - _, nodes, imgs = bc.triedb.Size() // all memory is contained within the nodes return for hashdb - limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 - ) - if nodes > limit || imgs > 4*1024*1024 { - bc.triedb.Cap(limit - ethdb.IdealBatchSize) - } - // Find the next state trie we need to commit - chosen := current - TriesInMemory - flushInterval := time.Duration(bc.flushInterval.Load()) - // If we exceeded time allowance, flush an entire trie to disk - if bc.gcproc > flushInterval { - // If the header is missing (canonical chain behind), we're reorging a low - // diff sidechain. Suspend committing until this operation is completed. - header := bc.GetHeaderByNumber(chosen) - if header == nil { - log.Warn("Reorg in progress, trie commit postponed", "number", chosen) - } else { - // If we're exceeding limits but haven't reached a large enough memory gap, - // warn the user that the system is becoming unstable. - if chosen < bc.lastWrite+TriesInMemory && bc.gcproc >= 2*flushInterval { - log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", flushInterval, "optimum", float64(chosen-bc.lastWrite)/TriesInMemory) - } - // Flush an entire trie and restart the counters - bc.triedb.Commit(header.Root, true) - bc.lastWrite = chosen - bc.gcproc = 0 - } - } - // Garbage collect anything below our required write retention - for !bc.triegc.Empty() { - root, number := bc.triegc.Pop() - if uint64(-number) > chosen { - bc.triegc.Push(root, number) - break - } - bc.triedb.Dereference(root) - } - return nil -} - -// WriteBlockAndSetHead writes the given block and all associated state to the database, -// and applies the block as the new chain head. -func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { - if !bc.chainmu.TryLock() { - return NonStatTy, errChainStopped - } - defer bc.chainmu.Unlock() - - return bc.writeBlockAndSetHead(block, receipts, logs, state, emitHeadEvent) -} - -// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. -// This function expects the chain mutex to be held. -func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { - if err := bc.writeBlockWithState(block, receipts, state); err != nil { - return NonStatTy, err - } - currentBlock := bc.CurrentBlock() - reorg, err := bc.forker.ReorgNeeded(currentBlock, block.Header()) - if err != nil { - return NonStatTy, err - } - if reorg { - // Reorganise the chain if the parent is not the head block - if block.ParentHash() != currentBlock.Hash() { - if err := bc.reorg(currentBlock, block); err != nil { - return NonStatTy, err - } - } - status = CanonStatTy - } else { - status = SideStatTy - } - // Set new head. - if status == CanonStatTy { - bc.writeHeadBlock(block) - } - bc.futureBlocks.Remove(block.Hash()) - - if status == CanonStatTy { - bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs}) - if len(logs) > 0 { - bc.logsFeed.Send(logs) - } - // In theory, we should fire a ChainHeadEvent when we inject - // a canonical block, but sometimes we can insert a batch of - // canonical blocks. Avoid firing too many ChainHeadEvents, - // we will fire an accumulated ChainHeadEvent and disable fire - // event here. - if emitHeadEvent { - bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) - } - } else { - bc.chainSideFeed.Send(ChainSideEvent{Block: block}) - } - return status, nil -} - -// addFutureBlock checks if the block is within the max allowed window to get -// accepted for future processing, and returns an error if the block is too far -// ahead and was not added. -// -// TODO after the transition, the future block shouldn't be kept. Because -// it's not checked in the Geth side anymore. -func (bc *BlockChain) addFutureBlock(block *types.Block) error { - max := uint64(time.Now().Unix() + maxTimeFutureBlocks) - if block.Time() > max { - return fmt.Errorf("future block timestamp %v > allowed %v", block.Time(), max) - } - if block.Difficulty().Cmp(common.Big0) == 0 { - // Never add PoS blocks into the future queue - return nil - } - bc.futureBlocks.Add(block.Hash(), block) - return nil -} - -// InsertChain attempts to insert the given batch of blocks in to the canonical -// chain or, otherwise, create a fork. If an error is returned it will return -// the index number of the failing block as well an error describing what went -// wrong. After insertion is done, all accumulated events will be fired. -func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) { - // Sanity check that we have something meaningful to import - if len(chain) == 0 { - return 0, nil - } - bc.blockProcFeed.Send(true) - defer bc.blockProcFeed.Send(false) - - // Do a sanity check that the provided chain is actually ordered and linked. - for i := 1; i < len(chain); i++ { - block, prev := chain[i], chain[i-1] - if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() { - log.Error("Non contiguous block insert", - "number", block.Number(), - "hash", block.Hash(), - "parent", block.ParentHash(), - "prevnumber", prev.Number(), - "prevhash", prev.Hash(), - ) - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, prev.NumberU64(), - prev.Hash().Bytes()[:4], i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4]) - } - } - // Pre-checks passed, start the full block imports - if !bc.chainmu.TryLock() { - return 0, errChainStopped - } - defer bc.chainmu.Unlock() - return bc.insertChain(chain, true) -} - -// insertChain is the internal implementation of InsertChain, which assumes that -// 1) chains are contiguous, and 2) The chain mutex is held. -// -// This method is split out so that import batches that require re-injecting -// historical blocks can do so without releasing the lock, which could lead to -// racey behaviour. If a sidechain import is in progress, and the historic state -// is imported, but then new canon-head is added before the actual sidechain -// completes, then the historic state could be pruned again -func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) { - // If the chain is terminating, don't even bother starting up. - if bc.insertStopped() { - return 0, nil - } - - // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) - SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain) - - var ( - stats = insertStats{startTime: mclock.Now()} - lastCanon *types.Block - ) - // Fire a single chain head event if we've progressed the chain - defer func() { - if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() { - bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon}) - } - }() - // Start the parallel header verifier - headers := make([]*types.Header, len(chain)) - for i, block := range chain { - headers[i] = block.Header() - } - abort, results := bc.engine.VerifyHeaders(bc, headers) - defer close(abort) - - // Peek the error for the first block to decide the directing import logic - it := newInsertIterator(chain, results, bc.validator) - block, err := it.next() - - // Left-trim all the known blocks that don't need to build snapshot - if bc.skipBlock(err, it) { - // First block (and state) is known - // 1. We did a roll-back, and should now do a re-import - // 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot - // from the canonical chain, which has not been verified. - // Skip all known blocks that are behind us. - var ( - reorg bool - current = bc.CurrentBlock() - ) - for block != nil && bc.skipBlock(err, it) { - reorg, err = bc.forker.ReorgNeeded(current, block.Header()) - if err != nil { - return it.index, err - } - if reorg { - // Switch to import mode if the forker says the reorg is necessary - // and also the block is not on the canonical chain. - // In eth2 the forker always returns true for reorg decision (blindly trusting - // the external consensus engine), but in order to prevent the unnecessary - // reorgs when importing known blocks, the special case is handled here. - if block.NumberU64() > current.Number.Uint64() || bc.GetCanonicalHash(block.NumberU64()) != block.Hash() { - break - } - } - log.Debug("Ignoring already known block", "number", block.Number(), "hash", block.Hash()) - stats.ignored++ - - block, err = it.next() - } - // The remaining blocks are still known blocks, the only scenario here is: - // During the snap sync, the pivot point is already submitted but rollback - // happens. Then node resets the head full block to a lower height via `rollback` - // and leaves a few known blocks in the database. - // - // When node runs a snap sync again, it can re-import a batch of known blocks via - // `insertChain` while a part of them have higher total difficulty than current - // head full block(new pivot point). - for block != nil && bc.skipBlock(err, it) { - log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash()) - if err := bc.writeKnownBlock(block); err != nil { - return it.index, err - } - lastCanon = block - - block, err = it.next() - } - // Falls through to the block import - } - switch { - // First block is pruned - case errors.Is(err, consensus.ErrPrunedAncestor): - if setHead { - // First block is pruned, insert as sidechain and reorg only if TD grows enough - log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash()) - return bc.insertSideChain(block, it) - } else { - // We're post-merge and the parent is pruned, try to recover the parent state - log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash()) - _, err := bc.recoverAncestors(block) - return it.index, err - } - // First block is future, shove it (and all children) to the future queue (unknown ancestor) - case errors.Is(err, consensus.ErrFutureBlock) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())): - for block != nil && (it.index == 0 || errors.Is(err, consensus.ErrUnknownAncestor)) { - log.Debug("Future block, postponing import", "number", block.Number(), "hash", block.Hash()) - if err := bc.addFutureBlock(block); err != nil { - return it.index, err - } - block, err = it.next() - } - stats.queued += it.processed() - stats.ignored += it.remaining() - - // If there are any still remaining, mark as ignored - return it.index, err - - // Some other error(except ErrKnownBlock) occurred, abort. - // ErrKnownBlock is allowed here since some known blocks - // still need re-execution to generate snapshots that are missing - case err != nil && !errors.Is(err, ErrKnownBlock): - bc.futureBlocks.Remove(block.Hash()) - stats.ignored += len(it.chain) - bc.reportBlock(block, nil, err) - return it.index, err - } - // No validation errors for the first block (or chain prefix skipped) - var activeState *state.StateDB - defer func() { - // The chain importer is starting and stopping trie prefetchers. If a bad - // block or other error is hit however, an early return may not properly - // terminate the background threads. This defer ensures that we clean up - // and dangling prefetcher, without deferring each and holding on live refs. - if activeState != nil { - activeState.StopPrefetcher() - } - }() - - for ; block != nil && err == nil || errors.Is(err, ErrKnownBlock); block, err = it.next() { - // If the chain is terminating, stop processing blocks - if bc.insertStopped() { - log.Debug("Abort during block processing") - break - } - // If the header is a banned one, straight out abort - if BadHashes[block.Hash()] { - bc.reportBlock(block, nil, ErrBannedHash) - return it.index, ErrBannedHash - } - // If the block is known (in the middle of the chain), it's a special case for - // Clique blocks where they can share state among each other, so importing an - // older block might complete the state of the subsequent one. In this case, - // just skip the block (we already validated it once fully (and crashed), since - // its header and body was already in the database). But if the corresponding - // snapshot layer is missing, forcibly rerun the execution to build it. - if bc.skipBlock(err, it) { - logger := log.Debug - if bc.chainConfig.Clique == nil { - logger = log.Warn - } - logger("Inserted known block", "number", block.Number(), "hash", block.Hash(), - "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(), - "root", block.Root()) - - // Special case. Commit the empty receipt slice if we meet the known - // block in the middle. It can only happen in the clique chain. Whenever - // we insert blocks via `insertSideChain`, we only commit `td`, `header` - // and `body` if it's non-existent. Since we don't have receipts without - // reexecution, so nothing to commit. But if the sidechain will be adopted - // as the canonical chain eventually, it needs to be reexecuted for missing - // state, but if it's this special case here(skip reexecution) we will lose - // the empty receipt entry. - if len(block.Transactions()) == 0 { - rawdb.WriteReceipts(bc.db, block.Hash(), block.NumberU64(), nil) - } else { - log.Error("Please file an issue, skip known block execution without receipt", - "hash", block.Hash(), "number", block.NumberU64()) - } - if err := bc.writeKnownBlock(block); err != nil { - return it.index, err - } - stats.processed++ - - // We can assume that logs are empty here, since the only way for consecutive - // Clique blocks to have the same state is if there are no transactions. - lastCanon = block - continue - } - - // Retrieve the parent block and it's state to execute on top - start := time.Now() - parent := it.previous() - if parent == nil { - parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) - } - statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps) - if err != nil { - return it.index, err - } - - // Enable prefetching to pull in trie node paths while processing transactions - statedb.StartPrefetcher("chain") - activeState = statedb - - // If we have a followup block, run that against the current state to pre-cache - // transactions and probabilistically some of the account/storage trie nodes. - var followupInterrupt atomic.Bool - if !bc.cacheConfig.TrieCleanNoPrefetch { - if followup, err := it.peek(); followup != nil && err == nil { - throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps) - - go func(start time.Time, followup *types.Block, throwaway *state.StateDB) { - bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) - - blockPrefetchExecuteTimer.Update(time.Since(start)) - if followupInterrupt.Load() { - blockPrefetchInterruptMeter.Mark(1) - } - }(time.Now(), followup, throwaway) - } - } - - // Process block using the parent state as reference point - pstart := time.Now() - receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig) - if err != nil { - bc.reportBlock(block, receipts, err) - followupInterrupt.Store(true) - return it.index, err - } - ptime := time.Since(pstart) - - vstart := time.Now() - if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { - bc.reportBlock(block, receipts, err) - followupInterrupt.Store(true) - return it.index, err - } - vtime := time.Since(vstart) - proctime := time.Since(start) // processing + validation - - // Update the metrics touched during block processing and validation - accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing) - storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing) - snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing) - snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing) - accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation) - storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation) - accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation) - storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete(in validation) - triehash := statedb.AccountHashes + statedb.StorageHashes // The time spent on tries hashing - trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update - trieRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read - trieRead += statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read - blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing - blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation - - // Write the block to the chain and get the status. - var ( - wstart = time.Now() - status WriteStatus - ) - if !setHead { - // Don't set the head, only insert the block - err = bc.writeBlockWithState(block, receipts, statedb) - } else { - status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false) - } - followupInterrupt.Store(true) - if err != nil { - return it.index, err - } - // Update the metrics touched during block commit - accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them - storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them - snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them - triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them - - blockWriteTimer.Update(time.Since(wstart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits) - blockInsertTimer.UpdateSince(start) - - // Report the import stats before returning the various results - stats.processed++ - stats.usedGas += usedGas - - var snapDiffItems, snapBufItems common.StorageSize - if bc.snaps != nil { - snapDiffItems, snapBufItems = bc.snaps.Size() - } - trieDiffNodes, trieBufNodes, _ := bc.triedb.Size() - stats.report(chain, it.index, snapDiffItems, snapBufItems, trieDiffNodes, trieBufNodes, setHead) - - if !setHead { - // After merge we expect few side chains. Simply count - // all blocks the CL gives us for GC processing time - bc.gcproc += proctime - - return it.index, nil // Direct block insertion of a single block - } - switch status { - case CanonStatTy: - log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(), - "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(), - "elapsed", common.PrettyDuration(time.Since(start)), - "root", block.Root()) - - lastCanon = block - - // Only count canonical blocks for GC processing time - bc.gcproc += proctime - - case SideStatTy: - log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(), - "diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)), - "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()), - "root", block.Root()) - - default: - // This in theory is impossible, but lets be nice to our future selves and leave - // a log, instead of trying to track down blocks imports that don't emit logs. - log.Warn("Inserted block with unknown status", "number", block.Number(), "hash", block.Hash(), - "diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)), - "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()), - "root", block.Root()) - } - } - - // Any blocks remaining here? The only ones we care about are the future ones - if block != nil && errors.Is(err, consensus.ErrFutureBlock) { - if err := bc.addFutureBlock(block); err != nil { - return it.index, err - } - block, err = it.next() - - for ; block != nil && errors.Is(err, consensus.ErrUnknownAncestor); block, err = it.next() { - if err := bc.addFutureBlock(block); err != nil { - return it.index, err - } - stats.queued++ - } - } - stats.ignored += it.remaining() - - return it.index, err -} - -// insertSideChain is called when an import batch hits upon a pruned ancestor -// error, which happens when a sidechain with a sufficiently old fork-block is -// found. -// -// The method writes all (header-and-body-valid) blocks to disk, then tries to -// switch over to the new chain if the TD exceeded the current chain. -// insertSideChain is only used pre-merge. -func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) { - var ( - externTd *big.Int - lastBlock = block - current = bc.CurrentBlock() - ) - // The first sidechain block error is already verified to be ErrPrunedAncestor. - // Since we don't import them here, we expect ErrUnknownAncestor for the remaining - // ones. Any other errors means that the block is invalid, and should not be written - // to disk. - err := consensus.ErrPrunedAncestor - for ; block != nil && errors.Is(err, consensus.ErrPrunedAncestor); block, err = it.next() { - // Check the canonical state root for that number - if number := block.NumberU64(); current.Number.Uint64() >= number { - canonical := bc.GetBlockByNumber(number) - if canonical != nil && canonical.Hash() == block.Hash() { - // Not a sidechain block, this is a re-import of a canon block which has it's state pruned - - // Collect the TD of the block. Since we know it's a canon one, - // we can get it directly, and not (like further below) use - // the parent and then add the block on top - externTd = bc.GetTd(block.Hash(), block.NumberU64()) - continue - } - if canonical != nil && canonical.Root() == block.Root() { - // This is most likely a shadow-state attack. When a fork is imported into the - // database, and it eventually reaches a block height which is not pruned, we - // just found that the state already exist! This means that the sidechain block - // refers to a state which already exists in our canon chain. - // - // If left unchecked, we would now proceed importing the blocks, without actually - // having verified the state of the previous blocks. - log.Warn("Sidechain ghost-state attack detected", "number", block.NumberU64(), "sideroot", block.Root(), "canonroot", canonical.Root()) - - // If someone legitimately side-mines blocks, they would still be imported as usual. However, - // we cannot risk writing unverified blocks to disk when they obviously target the pruning - // mechanism. - return it.index, errors.New("sidechain ghost-state attack") - } - } - if externTd == nil { - externTd = bc.GetTd(block.ParentHash(), block.NumberU64()-1) - } - externTd = new(big.Int).Add(externTd, block.Difficulty()) - - if !bc.HasBlock(block.Hash(), block.NumberU64()) { - start := time.Now() - if err := bc.writeBlockWithoutState(block, externTd); err != nil { - return it.index, err - } - log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(), - "diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)), - "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()), - "root", block.Root()) - } - lastBlock = block - } - // At this point, we've written all sidechain blocks to database. Loop ended - // either on some other error or all were processed. If there was some other - // error, we can ignore the rest of those blocks. - // - // If the externTd was larger than our local TD, we now need to reimport the previous - // blocks to regenerate the required state - reorg, err := bc.forker.ReorgNeeded(current, lastBlock.Header()) - if err != nil { - return it.index, err - } - if !reorg { - localTd := bc.GetTd(current.Hash(), current.Number.Uint64()) - log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd) - return it.index, err - } - // Gather all the sidechain hashes (full blocks may be memory heavy) - var ( - hashes []common.Hash - numbers []uint64 - ) - parent := it.previous() - for parent != nil && !bc.HasState(parent.Root) { - if bc.stateRecoverable(parent.Root) { - if err := bc.triedb.Recover(parent.Root); err != nil { - return 0, err - } - break - } - hashes = append(hashes, parent.Hash()) - numbers = append(numbers, parent.Number.Uint64()) - - parent = bc.GetHeader(parent.ParentHash, parent.Number.Uint64()-1) - } - if parent == nil { - return it.index, errors.New("missing parent") - } - // Import all the pruned blocks to make the state available - var ( - blocks []*types.Block - memory uint64 - ) - for i := len(hashes) - 1; i >= 0; i-- { - // Append the next block to our batch - block := bc.GetBlock(hashes[i], numbers[i]) - - blocks = append(blocks, block) - memory += block.Size() - - // If memory use grew too large, import and continue. Sadly we need to discard - // all raised events and logs from notifications since we're too heavy on the - // memory here. - if len(blocks) >= 2048 || memory > 64*1024*1024 { - log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64()) - if _, err := bc.insertChain(blocks, true); err != nil { - return 0, err - } - blocks, memory = blocks[:0], 0 - - // If the chain is terminating, stop processing blocks - if bc.insertStopped() { - log.Debug("Abort during blocks processing") - return 0, nil - } - } - } - if len(blocks) > 0 { - log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64()) - return bc.insertChain(blocks, true) - } - return 0, nil -} - -// recoverAncestors finds the closest ancestor with available state and re-execute -// all the ancestor blocks since that. -// recoverAncestors is only used post-merge. -// We return the hash of the latest block that we could correctly validate. -func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) { - // Gather all the sidechain hashes (full blocks may be memory heavy) - var ( - hashes []common.Hash - numbers []uint64 - parent = block - ) - for parent != nil && !bc.HasState(parent.Root()) { - if bc.stateRecoverable(parent.Root()) { - if err := bc.triedb.Recover(parent.Root()); err != nil { - return common.Hash{}, err - } - break - } - hashes = append(hashes, parent.Hash()) - numbers = append(numbers, parent.NumberU64()) - parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1) - - // If the chain is terminating, stop iteration - if bc.insertStopped() { - log.Debug("Abort during blocks iteration") - return common.Hash{}, errInsertionInterrupted - } - } - if parent == nil { - return common.Hash{}, errors.New("missing parent") - } - // Import all the pruned blocks to make the state available - for i := len(hashes) - 1; i >= 0; i-- { - // If the chain is terminating, stop processing blocks - if bc.insertStopped() { - log.Debug("Abort during blocks processing") - return common.Hash{}, errInsertionInterrupted - } - var b *types.Block - if i == 0 { - b = block - } else { - b = bc.GetBlock(hashes[i], numbers[i]) - } - if _, err := bc.insertChain(types.Blocks{b}, false); err != nil { - return b.ParentHash(), err - } - } - return block.Hash(), nil -} - -// collectLogs collects the logs that were generated or removed during -// the processing of a block. These logs are later announced as deleted or reborn. -func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { - var blobGasPrice *big.Int - excessBlobGas := b.ExcessBlobGas() - if excessBlobGas != nil { - blobGasPrice = eip4844.CalcBlobFee(*excessBlobGas) - } - receipts := rawdb.ReadRawReceipts(bc.db, b.Hash(), b.NumberU64()) - if err := receipts.DeriveFields(bc.chainConfig, b.Hash(), b.NumberU64(), b.Time(), b.BaseFee(), blobGasPrice, b.Transactions()); err != nil { - log.Error("Failed to derive block receipts fields", "hash", b.Hash(), "number", b.NumberU64(), "err", err) - } - var logs []*types.Log - for _, receipt := range receipts { - for _, log := range receipt.Logs { - if removed { - log.Removed = true - } - logs = append(logs, log) - } - } - return logs -} - -// reorg takes two blocks, an old chain and a new chain and will reconstruct the -// blocks and inserts them to be part of the new canonical chain and accumulates -// potential missing transactions and post an event about them. -// Note the new head block won't be processed here, callers need to handle it -// externally. -func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error { - var ( - newChain types.Blocks - oldChain types.Blocks - commonBlock *types.Block - - deletedTxs []common.Hash - addedTxs []common.Hash - ) - oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) - if oldBlock == nil { - return errors.New("current head block missing") - } - newBlock := newHead - - // Reduce the longer chain to the same number as the shorter one - if oldBlock.NumberU64() > newBlock.NumberU64() { - // Old chain is longer, gather all transactions and logs as deleted ones - for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) { - oldChain = append(oldChain, oldBlock) - for _, tx := range oldBlock.Transactions() { - deletedTxs = append(deletedTxs, tx.Hash()) - } - } - } else { - // New chain is longer, stash all blocks away for subsequent insertion - for ; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) { - newChain = append(newChain, newBlock) - } - } - if oldBlock == nil { - return errInvalidOldChain - } - if newBlock == nil { - return errInvalidNewChain - } - // Both sides of the reorg are at the same number, reduce both until the common - // ancestor is found - for { - // If the common ancestor was found, bail out - if oldBlock.Hash() == newBlock.Hash() { - commonBlock = oldBlock - break - } - // Remove an old block as well as stash away a new block - oldChain = append(oldChain, oldBlock) - for _, tx := range oldBlock.Transactions() { - deletedTxs = append(deletedTxs, tx.Hash()) - } - newChain = append(newChain, newBlock) - - // Step back with both chains - oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) - if oldBlock == nil { - return errInvalidOldChain - } - newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) - if newBlock == nil { - return errInvalidNewChain - } - } - - // Ensure the user sees large reorgs - if len(oldChain) > 0 && len(newChain) > 0 { - logFn := log.Info - msg := "Chain reorg detected" - if len(oldChain) > 63 { - msg = "Large chain reorg detected" - logFn = log.Warn - } - logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(), - "drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash()) - blockReorgAddMeter.Mark(int64(len(newChain))) - blockReorgDropMeter.Mark(int64(len(oldChain))) - blockReorgMeter.Mark(1) - } else if len(newChain) > 0 { - // Special case happens in the post merge stage that current head is - // the ancestor of new head while these two blocks are not consecutive - log.Info("Extend chain", "add", len(newChain), "number", newChain[0].Number(), "hash", newChain[0].Hash()) - blockReorgAddMeter.Mark(int64(len(newChain))) - } else { - // len(newChain) == 0 && len(oldChain) > 0 - // rewind the canonical chain to a lower point. - log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain)) - } - // Reset the tx lookup cache in case to clear stale txlookups. - // This is done before writing any new chain data to avoid the - // weird scenario that canonical chain is changed while the - // stale lookups are still cached. - bc.txLookupCache.Purge() - - // Insert the new chain(except the head block(reverse order)), - // taking care of the proper incremental order. - for i := len(newChain) - 1; i >= 1; i-- { - // Insert the block in the canonical way, re-writing history - bc.writeHeadBlock(newChain[i]) - - // Collect the new added transactions. - for _, tx := range newChain[i].Transactions() { - addedTxs = append(addedTxs, tx.Hash()) - } - } - - // Delete useless indexes right now which includes the non-canonical - // transaction indexes, canonical chain indexes which above the head. - var ( - indexesBatch = bc.db.NewBatch() - diffs = types.HashDifference(deletedTxs, addedTxs) - ) - for _, tx := range diffs { - rawdb.DeleteTxLookupEntry(indexesBatch, tx) - } - // Delete all hash markers that are not part of the new canonical chain. - // Because the reorg function does not handle new chain head, all hash - // markers greater than or equal to new chain head should be deleted. - number := commonBlock.NumberU64() - if len(newChain) > 1 { - number = newChain[1].NumberU64() - } - for i := number + 1; ; i++ { - hash := rawdb.ReadCanonicalHash(bc.db, i) - if hash == (common.Hash{}) { - break - } - rawdb.DeleteCanonicalHash(indexesBatch, i) - } - if err := indexesBatch.Write(); err != nil { - log.Crit("Failed to delete useless indexes", "err", err) - } - - // Send out events for logs from the old canon chain, and 'reborn' - // logs from the new canon chain. The number of logs can be very - // high, so the events are sent in batches of size around 512. - - // Deleted logs + blocks: - var deletedLogs []*types.Log - for i := len(oldChain) - 1; i >= 0; i-- { - // Also send event for blocks removed from the canon chain. - bc.chainSideFeed.Send(ChainSideEvent{Block: oldChain[i]}) - - // Collect deleted logs for notification - if logs := bc.collectLogs(oldChain[i], true); len(logs) > 0 { - deletedLogs = append(deletedLogs, logs...) - } - if len(deletedLogs) > 512 { - bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs}) - deletedLogs = nil - } - } - if len(deletedLogs) > 0 { - bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs}) - } - - // New logs: - var rebirthLogs []*types.Log - for i := len(newChain) - 1; i >= 1; i-- { - if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 { - rebirthLogs = append(rebirthLogs, logs...) - } - if len(rebirthLogs) > 512 { - bc.logsFeed.Send(rebirthLogs) - rebirthLogs = nil - } - } - if len(rebirthLogs) > 0 { - bc.logsFeed.Send(rebirthLogs) - } - return nil -} - -// InsertBlockWithoutSetHead executes the block, runs the necessary verification -// upon it and then persist the block and the associate state into the database. -// The key difference between the InsertChain is it won't do the canonical chain -// updating. It relies on the additional SetCanonical call to finalize the entire -// procedure. -func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error { - if !bc.chainmu.TryLock() { - return errChainStopped - } - defer bc.chainmu.Unlock() - - _, err := bc.insertChain(types.Blocks{block}, false) - return err -} - -// SetCanonical rewinds the chain to set the new head block as the specified -// block. It's possible that the state of the new head is missing, and it will -// be recovered in this function as well. -func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) { - if !bc.chainmu.TryLock() { - return common.Hash{}, errChainStopped - } - defer bc.chainmu.Unlock() - - // Re-execute the reorged chain in case the head state is missing. - if !bc.HasState(head.Root()) { - if latestValidHash, err := bc.recoverAncestors(head); err != nil { - return latestValidHash, err - } - log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash()) - } - // Run the reorg if necessary and set the given block as new head. - start := time.Now() - if head.ParentHash() != bc.CurrentBlock().Hash() { - if err := bc.reorg(bc.CurrentBlock(), head); err != nil { - return common.Hash{}, err - } - } - bc.writeHeadBlock(head) - - // Emit events - logs := bc.collectLogs(head, false) - bc.chainFeed.Send(ChainEvent{Block: head, Hash: head.Hash(), Logs: logs}) - if len(logs) > 0 { - bc.logsFeed.Send(logs) - } - bc.chainHeadFeed.Send(ChainHeadEvent{Block: head}) - - context := []interface{}{ - "number", head.Number(), - "hash", head.Hash(), - "root", head.Root(), - "elapsed", time.Since(start), - } - if timestamp := time.Unix(int64(head.Time()), 0); time.Since(timestamp) > time.Minute { - context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) - } - log.Info("Chain head was updated", context...) - return head.Hash(), nil -} - -func (bc *BlockChain) updateFutureBlocks() { - futureTimer := time.NewTicker(5 * time.Second) - defer futureTimer.Stop() - defer bc.wg.Done() - for { - select { - case <-futureTimer.C: - bc.procFutureBlocks() - case <-bc.quit: - return - } - } -} - -// skipBlock returns 'true', if the block being imported can be skipped over, meaning -// that the block does not need to be processed but can be considered already fully 'done'. -func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool { - // We can only ever bypass processing if the only error returned by the validator - // is ErrKnownBlock, which means all checks passed, but we already have the block - // and state. - if !errors.Is(err, ErrKnownBlock) { - return false - } - // If we're not using snapshots, we can skip this, since we have both block - // and (trie-) state - if bc.snaps == nil { - return true - } - var ( - header = it.current() // header can't be nil - parentRoot common.Hash - ) - // If we also have the snapshot-state, we can skip the processing. - if bc.snaps.Snapshot(header.Root) != nil { - return true - } - // In this case, we have the trie-state but not snapshot-state. If the parent - // snapshot-state exists, we need to process this in order to not get a gap - // in the snapshot layers. - // Resolve parent block - if parent := it.previous(); parent != nil { - parentRoot = parent.Root - } else if parent = bc.GetHeaderByHash(header.ParentHash); parent != nil { - parentRoot = parent.Root - } - if parentRoot == (common.Hash{}) { - return false // Theoretically impossible case - } - // Parent is also missing snapshot: we can skip this. Otherwise process. - if bc.snaps.Snapshot(parentRoot) == nil { - return true - } - return false -} - -// reportBlock logs a bad block error. -func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) { - rawdb.WriteBadBlock(bc.db, block) - log.Error(summarizeBadBlock(block, receipts, bc.Config(), err)) -} - -// summarizeBadBlock returns a string summarizing the bad block and other -// relevant information. -func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *params.ChainConfig, err error) string { - var receiptString string - for i, receipt := range receipts { - receiptString += fmt.Sprintf("\n %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x", - i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(), - receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState) - } - version, vcs := version.Info() - platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS) - if vcs != "" { - vcs = fmt.Sprintf("\nVCS: %s", vcs) - } - return fmt.Sprintf(` -########## BAD BLOCK ######### -Block: %v (%#x) -Error: %v -Platform: %v%v -Chain config: %#v -Receipts: %v -############################## -`, block.Number(), block.Hash(), err, platform, vcs, config, receiptString) -} - -// InsertHeaderChain attempts to insert the given header chain in to the local -// chain, possibly creating a reorg. If an error is returned, it will return the -// index number of the failing header as well an error describing what went wrong. -func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) { - if len(chain) == 0 { - return 0, nil - } - start := time.Now() - if i, err := bc.hc.ValidateHeaderChain(chain); err != nil { - return i, err - } - - if !bc.chainmu.TryLock() { - return 0, errChainStopped - } - defer bc.chainmu.Unlock() - _, err := bc.hc.InsertHeaderChain(chain, start, bc.forker) - return 0, err -} - -// SetBlockValidatorAndProcessorForTesting sets the current validator and processor. -// This method can be used to force an invalid blockchain to be verified for tests. -// This method is unsafe and should only be used before block import starts. -func (bc *BlockChain) SetBlockValidatorAndProcessorForTesting(v Validator, p Processor) { - bc.validator = v - bc.processor = p -} - -// ValidatePayload validates the payload of the block. -// It returns nil if the payload is valid, otherwise it returns an error. -// - `useBalanceDiffProfit` if set to false, proposer payment is assumed to be in the last transaction of the block -// otherwise we use proposer balance changes after the block to calculate proposer payment (see details in the code) -// - `excludeWithdrawals` if set to true, withdrawals to the fee recipient are excluded from the balance change -func (bc *BlockChain) ValidatePayload(block *types.Block, feeRecipient common.Address, expectedProfit *big.Int, registeredGasLimit uint64, vmConfig vm.Config, useBalanceDiffProfit, excludeWithdrawals bool) error { - header := block.Header() - if err := bc.engine.VerifyHeader(bc, header); err != nil { - return err - } - - current := bc.CurrentBlock() - reorg, err := bc.forker.ReorgNeeded(current, header) - if err == nil && reorg { - return errors.New("block requires a reorg") - } - - parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) - if parent == nil { - return errors.New("parent not found") - } - - calculatedGasLimit := CalcGasLimit(parent.GasLimit, registeredGasLimit) - if calculatedGasLimit != header.GasLimit { - return errors.New("incorrect gas limit set") - } - - statedb, err := bc.StateAt(parent.Root) - if err != nil { - return err - } - - // The chain importer is starting and stopping trie prefetchers. If a bad - // block or other error is hit however, an early return may not properly - // terminate the background threads. This defer ensures that we clean up - // and dangling prefetcher, without defering each and holding on live refs. - defer statedb.StopPrefetcher() - - feeRecipientBalanceBefore := new(uint256.Int).Set(statedb.GetBalance(feeRecipient)) - - receipts, _, usedGas, err := bc.processor.Process(block, statedb, vmConfig) - if err != nil { - return err - } - - feeRecipientBalanceDelta := new(uint256.Int).Set(statedb.GetBalance(feeRecipient)) - feeRecipientBalanceDelta.Sub(feeRecipientBalanceDelta, feeRecipientBalanceBefore) - if excludeWithdrawals { - for _, w := range block.Withdrawals() { - if w.Address == feeRecipient { - amount := new(uint256.Int).Mul(new(uint256.Int).SetUint64(w.Amount), uint256.NewInt(params.GWei)) - feeRecipientBalanceDelta.Sub(feeRecipientBalanceDelta, amount) - } - } - } - - if bc.Config().IsShanghai(header.Number, header.Time) { - if header.WithdrawalsHash == nil { - return fmt.Errorf("withdrawals hash is missing") - } - // withdrawals hash and withdrawals validated later in ValidateBody - } else { - if header.WithdrawalsHash != nil { - return fmt.Errorf("withdrawals hash present before shanghai") - } - if block.Withdrawals() != nil { - return fmt.Errorf("withdrawals list present in block body before shanghai") - } - } - - if err := bc.validator.ValidateBody(block); err != nil { - return err - } - - if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { - return err - } - - // Validate proposer payment - - if useBalanceDiffProfit { - uint256ExpectedProfit, ok := uint256.FromBig(expectedProfit) - if !ok { - if feeRecipientBalanceDelta.Cmp(uint256ExpectedProfit) >= 0 { - if feeRecipientBalanceDelta.Cmp(uint256ExpectedProfit) > 0 { - log.Warn("builder claimed profit is lower than calculated profit", "expected", expectedProfit, "actual", feeRecipientBalanceDelta) - } - return nil - } - log.Warn("proposer payment not enough, trying last tx payment validation", "expected", expectedProfit, "actual", feeRecipientBalanceDelta) - } - - if len(receipts) == 0 { - return errors.New("no proposer payment receipt") - } - - lastReceipt := receipts[len(receipts)-1] - if lastReceipt.Status != types.ReceiptStatusSuccessful { - return errors.New("proposer payment not successful") - } - txIndex := lastReceipt.TransactionIndex - if txIndex+1 != uint(len(block.Transactions())) { - return fmt.Errorf("proposer payment index not last transaction in the block (%d of %d)", txIndex, len(block.Transactions())-1) - } - - paymentTx := block.Transaction(lastReceipt.TxHash) - if paymentTx == nil { - return errors.New("payment tx not in the block") - } - - paymentTo := paymentTx.To() - if paymentTo == nil || *paymentTo != feeRecipient { - return fmt.Errorf("payment tx not to the proposers fee recipient (%v)", paymentTo) - } - - if paymentTx.Value().Cmp(expectedProfit) != 0 { - return fmt.Errorf("inaccurate payment %s, expected %s", paymentTx.Value().String(), expectedProfit.String()) - } - - if len(paymentTx.Data()) != 0 { - return fmt.Errorf("malformed proposer payment, contains calldata") - } - - if paymentTx.GasPrice().Cmp(block.BaseFee()) != 0 { - return fmt.Errorf("malformed proposer payment, gas price not equal to base fee") - } - - if paymentTx.GasTipCap().Cmp(block.BaseFee()) != 0 && paymentTx.GasTipCap().Sign() != 0 { - return fmt.Errorf("malformed proposer payment, unexpected gas tip cap") - } - - if paymentTx.GasFeeCap().Cmp(block.BaseFee()) != 0 { - return fmt.Errorf("malformed proposer payment, unexpected gas fee cap") - } - } - - return nil -} - -// SetTrieFlushInterval configures how often in-memory tries are persisted to disk. -// The interval is in terms of block processing time, not wall clock. -// It is thread-safe and can be called repeatedly without side effects. -func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) { - bc.flushInterval.Store(int64(interval)) -} - -// GetTrieFlushInterval gets the in-memory tries flushAlloc interval -func (bc *BlockChain) GetTrieFlushInterval() time.Duration { - return time.Duration(bc.flushInterval.Load()) -} diff --git a/builder/core/blockchain_insert.go b/builder/core/blockchain_insert.go deleted file mode 100644 index 9bf662b6b..000000000 --- a/builder/core/blockchain_insert.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2018 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 core - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -// insertStats tracks and reports on block insertion. -type insertStats struct { - queued, processed, ignored int - usedGas uint64 - lastIndex int - startTime mclock.AbsTime -} - -// statsReportLimit is the time limit during import and export after which we -// always print out progress. This avoids the user wondering what's going on. -const statsReportLimit = 8 * time.Second - -// report prints statistics if some number of blocks have been processed -// or more than a few seconds have passed since the last message. -func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, snapBufItems, trieDiffNodes, triebufNodes common.StorageSize, setHead bool) { - // Fetch the timings for the batch - var ( - now = mclock.Now() - elapsed = now.Sub(st.startTime) - ) - // If we're at the last block of the batch or report period reached, log - if index == len(chain)-1 || elapsed >= statsReportLimit { - // Count the number of transactions in this segment - var txs int - for _, block := range chain[st.lastIndex : index+1] { - txs += len(block.Transactions()) - } - end := chain[index] - - // Assemble the log context and send it to the logger - context := []interface{}{ - "number", end.Number(), "hash", end.Hash(), - "blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000, - "elapsed", common.PrettyDuration(elapsed), "mgasps", float64(st.usedGas) * 1000 / float64(elapsed), - } - if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { - context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) - } - if snapDiffItems != 0 || snapBufItems != 0 { // snapshots enabled - context = append(context, []interface{}{"snapdiffs", snapDiffItems}...) - if snapBufItems != 0 { // future snapshot refactor - context = append(context, []interface{}{"snapdirty", snapBufItems}...) - } - } - if trieDiffNodes != 0 { // pathdb - context = append(context, []interface{}{"triediffs", trieDiffNodes}...) - } - context = append(context, []interface{}{"triedirty", triebufNodes}...) - - if st.queued > 0 { - context = append(context, []interface{}{"queued", st.queued}...) - } - if st.ignored > 0 { - context = append(context, []interface{}{"ignored", st.ignored}...) - } - if setHead { - log.Info("Imported new chain segment", context...) - } else { - log.Info("Imported new potential chain segment", context...) - } - // Bump the stats reported to the next section - *st = insertStats{startTime: now, lastIndex: index + 1} - } -} - -// insertIterator is a helper to assist during chain import. -type insertIterator struct { - chain types.Blocks // Chain of blocks being iterated over - - results <-chan error // Verification result sink from the consensus engine - errors []error // Header verification errors for the blocks - - index int // Current offset of the iterator - validator Validator // Validator to run if verification succeeds -} - -// newInsertIterator creates a new iterator based on the given blocks, which are -// assumed to be a contiguous chain. -func newInsertIterator(chain types.Blocks, results <-chan error, validator Validator) *insertIterator { - return &insertIterator{ - chain: chain, - results: results, - errors: make([]error, 0, len(chain)), - index: -1, - validator: validator, - } -} - -// next returns the next block in the iterator, along with any potential validation -// error for that block. When the end is reached, it will return (nil, nil). -func (it *insertIterator) next() (*types.Block, error) { - // If we reached the end of the chain, abort - if it.index+1 >= len(it.chain) { - it.index = len(it.chain) - return nil, nil - } - // Advance the iterator and wait for verification result if not yet done - it.index++ - if len(it.errors) <= it.index { - it.errors = append(it.errors, <-it.results) - } - if it.errors[it.index] != nil { - return it.chain[it.index], it.errors[it.index] - } - // Block header valid, run body validation and return - return it.chain[it.index], it.validator.ValidateBody(it.chain[it.index]) -} - -// peek returns the next block in the iterator, along with any potential validation -// error for that block, but does **not** advance the iterator. -// -// Both header and body validation errors (nil too) is cached into the iterator -// to avoid duplicating work on the following next() call. -func (it *insertIterator) peek() (*types.Block, error) { - // If we reached the end of the chain, abort - if it.index+1 >= len(it.chain) { - return nil, nil - } - // Wait for verification result if not yet done - if len(it.errors) <= it.index+1 { - it.errors = append(it.errors, <-it.results) - } - if it.errors[it.index+1] != nil { - return it.chain[it.index+1], it.errors[it.index+1] - } - // Block header valid, ignore body validation since we don't have a parent anyway - return it.chain[it.index+1], nil -} - -// previous returns the previous header that was being processed, or nil. -func (it *insertIterator) previous() *types.Header { - if it.index < 1 { - return nil - } - return it.chain[it.index-1].Header() -} - -// current returns the current header that is being processed, or nil. -func (it *insertIterator) current() *types.Header { - if it.index == -1 || it.index >= len(it.chain) { - return nil - } - return it.chain[it.index].Header() -} - -// first returns the first block in the it. -func (it *insertIterator) first() *types.Block { - return it.chain[0] -} - -// remaining returns the number of remaining blocks. -func (it *insertIterator) remaining() int { - return len(it.chain) - it.index -} - -// processed returns the number of processed blocks. -func (it *insertIterator) processed() int { - return it.index + 1 -} diff --git a/builder/core/blockchain_reader.go b/builder/core/blockchain_reader.go deleted file mode 100644 index 9e8e3bd41..000000000 --- a/builder/core/blockchain_reader.go +++ /dev/null @@ -1,447 +0,0 @@ -// 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 core - -import ( - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/triedb" -) - -// CurrentHeader retrieves the current head header of the canonical chain. The -// header is retrieved from the HeaderChain's internal cache. -func (bc *BlockChain) CurrentHeader() *types.Header { - return bc.hc.CurrentHeader() -} - -// CurrentBlock retrieves the current head block of the canonical chain. The -// block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentBlock() *types.Header { - return bc.currentBlock.Load() -} - -// CurrentSnapBlock retrieves the current snap-sync head block of the canonical -// chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentSnapBlock() *types.Header { - return bc.currentSnapBlock.Load() -} - -// CurrentFinalBlock retrieves the current finalized block of the canonical -// chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentFinalBlock() *types.Header { - return bc.currentFinalBlock.Load() -} - -// CurrentSafeBlock retrieves the current safe block of the canonical -// chain. The block is retrieved from the blockchain's internal cache. -func (bc *BlockChain) CurrentSafeBlock() *types.Header { - return bc.currentSafeBlock.Load() -} - -// HasHeader checks if a block header is present in the database or not, caching -// it if present. -func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { - return bc.hc.HasHeader(hash, number) -} - -// GetHeader retrieves a block header from the database by hash and number, -// caching it if found. -func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header { - return bc.hc.GetHeader(hash, number) -} - -// GetHeaderByHash retrieves a block header from the database by hash, caching it if -// found. -func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header { - return bc.hc.GetHeaderByHash(hash) -} - -// GetHeaderByNumber retrieves a block header from the database by number, -// caching it (associated with its hash) if found. -func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { - return bc.hc.GetHeaderByNumber(number) -} - -// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going -// backwards from the given number. -func (bc *BlockChain) GetHeadersFrom(number, count uint64) []rlp.RawValue { - return bc.hc.GetHeadersFrom(number, count) -} - -// GetBody retrieves a block body (transactions and uncles) from the database by -// hash, caching it if found. -func (bc *BlockChain) GetBody(hash common.Hash) *types.Body { - // Short circuit if the body's already in the cache, retrieve otherwise - if cached, ok := bc.bodyCache.Get(hash); ok { - return cached - } - number := bc.hc.GetBlockNumber(hash) - if number == nil { - return nil - } - body := rawdb.ReadBody(bc.db, hash, *number) - if body == nil { - return nil - } - // Cache the found body for next time and return - bc.bodyCache.Add(hash, body) - return body -} - -// GetBodyRLP retrieves a block body in RLP encoding from the database by hash, -// caching it if found. -func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue { - // Short circuit if the body's already in the cache, retrieve otherwise - if cached, ok := bc.bodyRLPCache.Get(hash); ok { - return cached - } - number := bc.hc.GetBlockNumber(hash) - if number == nil { - return nil - } - body := rawdb.ReadBodyRLP(bc.db, hash, *number) - if len(body) == 0 { - return nil - } - // Cache the found body for next time and return - bc.bodyRLPCache.Add(hash, body) - return body -} - -// HasBlock checks if a block is fully present in the database or not. -func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool { - if bc.blockCache.Contains(hash) { - return true - } - if !bc.HasHeader(hash, number) { - return false - } - return rawdb.HasBody(bc.db, hash, number) -} - -// HasFastBlock checks if a fast block is fully present in the database or not. -func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool { - if !bc.HasBlock(hash, number) { - return false - } - if bc.receiptsCache.Contains(hash) { - return true - } - return rawdb.HasReceipts(bc.db, hash, number) -} - -// GetBlock retrieves a block from the database by hash and number, -// caching it if found. -func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - // Short circuit if the block's already in the cache, retrieve otherwise - if block, ok := bc.blockCache.Get(hash); ok { - return block - } - block := rawdb.ReadBlock(bc.db, hash, number) - if block == nil { - return nil - } - // Cache the found block for next time and return - bc.blockCache.Add(block.Hash(), block) - return block -} - -// GetBlockByHash retrieves a block from the database by hash, caching it if found. -func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block { - number := bc.hc.GetBlockNumber(hash) - if number == nil { - return nil - } - return bc.GetBlock(hash, *number) -} - -// GetBlockByNumber retrieves a block from the database by number, caching it -// (associated with its hash) if found. -func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block { - hash := rawdb.ReadCanonicalHash(bc.db, number) - if hash == (common.Hash{}) { - return nil - } - return bc.GetBlock(hash, number) -} - -// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. -// [deprecated by eth/62] -func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { - number := bc.hc.GetBlockNumber(hash) - if number == nil { - return nil - } - for i := 0; i < n; i++ { - block := bc.GetBlock(hash, *number) - if block == nil { - break - } - blocks = append(blocks, block) - hash = block.ParentHash() - *number-- - } - return -} - -// GetReceiptsByHash retrieves the receipts for all transactions in a given block. -func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts { - if receipts, ok := bc.receiptsCache.Get(hash); ok { - return receipts - } - number := rawdb.ReadHeaderNumber(bc.db, hash) - if number == nil { - return nil - } - header := bc.GetHeader(hash, *number) - if header == nil { - return nil - } - receipts := rawdb.ReadReceipts(bc.db, hash, *number, header.Time, bc.chainConfig) - if receipts == nil { - return nil - } - bc.receiptsCache.Add(hash, receipts) - return receipts -} - -// GetUnclesInChain retrieves all the uncles from a given block backwards until -// a specific distance is reached. -func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.Header { - uncles := []*types.Header{} - for i := 0; block != nil && i < length; i++ { - uncles = append(uncles, block.Uncles()...) - block = bc.GetBlock(block.ParentHash(), block.NumberU64()-1) - } - return uncles -} - -// GetCanonicalHash returns the canonical hash for a given block number -func (bc *BlockChain) GetCanonicalHash(number uint64) common.Hash { - return bc.hc.GetCanonicalHash(number) -} - -// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or -// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the -// number of blocks to be individually checked before we reach the canonical chain. -// -// Note: ancestor == 0 returns the same block, 1 returns its parent and so on. -func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) -} - -// GetTransactionLookup retrieves the lookup along with the transaction -// itself associate with the given transaction hash. -// -// An error will be returned if the transaction is not found, and background -// indexing for transactions is still in progress. The transaction might be -// reachable shortly once it's indexed. -// -// A null will be returned in the transaction is not found and background -// transaction indexing is already finished. The transaction is not existent -// from the node's perspective. -func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLookupEntry, *types.Transaction, error) { - // Short circuit if the txlookup already in the cache, retrieve otherwise - if item, exist := bc.txLookupCache.Get(hash); exist { - return item.lookup, item.transaction, nil - } - tx, blockHash, blockNumber, txIndex := rawdb.ReadTransaction(bc.db, hash) - if tx == nil { - progress, err := bc.TxIndexProgress() - if err != nil { - return nil, nil, nil - } - // The transaction indexing is not finished yet, returning an - // error to explicitly indicate it. - if !progress.Done() { - return nil, nil, errors.New("transaction indexing still in progress") - } - // The transaction is already indexed, the transaction is either - // not existent or not in the range of index, returning null. - return nil, nil, nil - } - lookup := &rawdb.LegacyTxLookupEntry{ - BlockHash: blockHash, - BlockIndex: blockNumber, - Index: txIndex, - } - bc.txLookupCache.Add(hash, txLookup{ - lookup: lookup, - transaction: tx, - }) - return lookup, tx, nil -} - -// GetTd retrieves a block's total difficulty in the canonical chain from the -// database by hash and number, caching it if found. -func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int { - return bc.hc.GetTd(hash, number) -} - -// HasState checks if state trie is fully present in the database or not. -func (bc *BlockChain) HasState(hash common.Hash) bool { - _, err := bc.stateCache.OpenTrie(hash) - return err == nil -} - -// HasBlockAndState checks if a block and associated state trie is fully present -// in the database or not, caching it if present. -func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool { - // Check first that the block itself is known - block := bc.GetBlock(hash, number) - if block == nil { - return false - } - return bc.HasState(block.Root()) -} - -// stateRecoverable checks if the specified state is recoverable. -// Note, this function assumes the state is not present, because -// state is not treated as recoverable if it's available, thus -// false will be returned in this case. -func (bc *BlockChain) stateRecoverable(root common.Hash) bool { - if bc.triedb.Scheme() == rawdb.HashScheme { - return false - } - result, _ := bc.triedb.Recoverable(root) - return result -} - -// ContractCodeWithPrefix retrieves a blob of data associated with a contract -// hash either from ephemeral in-memory cache, or from persistent storage. -// -// If the code doesn't exist in the in-memory cache, check the storage with -// new code scheme. -func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) { - type codeReader interface { - ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) - } - // TODO(rjl493456442) The associated account address is also required - // in Verkle scheme. Fix it once snap-sync is supported for Verkle. - return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash) -} - -// State returns a new mutable state based on the current HEAD block. -func (bc *BlockChain) State() (*state.StateDB, error) { - return bc.StateAt(bc.CurrentBlock().Root) -} - -// StateAt returns a new mutable state based on a particular point in time. -func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { - return state.New(root, bc.stateCache, bc.snaps) -} - -// Config retrieves the chain's fork configuration. -func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } - -// Engine retrieves the blockchain's consensus engine. -func (bc *BlockChain) Engine() consensus.Engine { return bc.engine } - -// Snapshots returns the blockchain snapshot tree. -func (bc *BlockChain) Snapshots() *snapshot.Tree { - return bc.snaps -} - -// Validator returns the current validator. -func (bc *BlockChain) Validator() Validator { - return bc.validator -} - -// Processor returns the current processor. -func (bc *BlockChain) Processor() Processor { - return bc.processor -} - -// StateCache returns the caching database underpinning the blockchain instance. -func (bc *BlockChain) StateCache() state.Database { - return bc.stateCache -} - -// GasLimit returns the gas limit of the current HEAD block. -func (bc *BlockChain) GasLimit() uint64 { - return bc.CurrentBlock().GasLimit -} - -// Genesis retrieves the chain's genesis block. -func (bc *BlockChain) Genesis() *types.Block { - return bc.genesisBlock -} - -// GetVMConfig returns the block chain VM config. -func (bc *BlockChain) GetVMConfig() *vm.Config { - return &bc.vmConfig -} - -// TxIndexProgress returns the transaction indexing progress. -func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) { - if bc.txIndexer == nil { - return TxIndexProgress{}, errors.New("tx indexer is not enabled") - } - return bc.txIndexer.txIndexProgress() -} - -// TrieDB retrieves the low level trie database used for data storage. -func (bc *BlockChain) TrieDB() *triedb.Database { - return bc.triedb -} - -// HeaderChain returns the underlying header chain. -func (bc *BlockChain) HeaderChain() *HeaderChain { - return bc.hc -} - -// SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent. -func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription { - return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch)) -} - -// SubscribeChainEvent registers a subscription of ChainEvent. -func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription { - return bc.scope.Track(bc.chainFeed.Subscribe(ch)) -} - -// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent. -func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { - return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch)) -} - -// SubscribeChainSideEvent registers a subscription of ChainSideEvent. -func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription { - return bc.scope.Track(bc.chainSideFeed.Subscribe(ch)) -} - -// SubscribeLogsEvent registers a subscription of []*types.Log. -func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return bc.scope.Track(bc.logsFeed.Subscribe(ch)) -} - -// SubscribeBlockProcessingEvent registers a subscription of bool where true means -// block processing has started while false means it has stopped. -func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { - return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) -} diff --git a/builder/core/blockchain_repair_test.go b/builder/core/blockchain_repair_test.go deleted file mode 100644 index b2df39d17..000000000 --- a/builder/core/blockchain_repair_test.go +++ /dev/null @@ -1,2016 +0,0 @@ -// 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 . - -// Tests that abnormal program termination (i.e.crash) and restart doesn't leave -// the database in some strange state with gaps in the chain, nor with block data -// dangling in the future. - -package core - -import ( - "math/big" - "path" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" -) - -// Tests a recovery for a short canonical chain where a recent block was already -// committed to disk and then the process crashed. In this case we expect the full -// chain to be rolled back to the committed block, but the chain data itself left -// in the database for replaying. -func TestShortRepair(t *testing.T) { testShortRepair(t, false) } -func TestShortRepairWithSnapshots(t *testing.T) { testShortRepair(t, true) } - -func testShortRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain where the fast sync pivot point was -// already committed, after which the process crashed. In this case we expect the full -// chain to be rolled back to the committed block, but the chain data itself left in -// the database for replaying. -func TestShortSnapSyncedRepair(t *testing.T) { testShortSnapSyncedRepair(t, false) } -func TestShortSnapSyncedRepairWithSnapshots(t *testing.T) { testShortSnapSyncedRepair(t, true) } - -func testShortSnapSyncedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain where the fast sync pivot point was -// not yet committed, but the process crashed. In this case we expect the chain to -// detect that it was fast syncing and not delete anything, since we can just pick -// up directly where we left off. -func TestShortSnapSyncingRepair(t *testing.T) { testShortSnapSyncingRepair(t, false) } -func TestShortSnapSyncingRepairWithSnapshots(t *testing.T) { testShortSnapSyncingRepair(t, true) } - -func testShortSnapSyncingRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where a -// recent block was already committed to disk and then the process crashed. In this -// test scenario the side chain is below the committed block. In this case we expect -// the canonical chain to be rolled back to the committed block, but the chain data -// itself left in the database for replaying. -func TestShortOldForkedRepair(t *testing.T) { testShortOldForkedRepair(t, false) } -func TestShortOldForkedRepairWithSnapshots(t *testing.T) { testShortOldForkedRepair(t, true) } - -func testShortOldForkedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was already committed to disk and then the process -// crashed. In this test scenario the side chain is below the committed block. In -// this case we expect the canonical chain to be rolled back to the committed block, -// but the chain data itself left in the database for replaying. -func TestShortOldForkedSnapSyncedRepair(t *testing.T) { - testShortOldForkedSnapSyncedRepair(t, false) -} -func TestShortOldForkedSnapSyncedRepairWithSnapshots(t *testing.T) { - testShortOldForkedSnapSyncedRepair(t, true) -} - -func testShortOldForkedSnapSyncedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was not yet committed, but the process crashed. In this -// test scenario the side chain is below the committed block. In this case we expect -// the chain to detect that it was fast syncing and not delete anything, since we -// can just pick up directly where we left off. -func TestShortOldForkedSnapSyncingRepair(t *testing.T) { - testShortOldForkedSnapSyncingRepair(t, false) -} -func TestShortOldForkedSnapSyncingRepairWithSnapshots(t *testing.T) { - testShortOldForkedSnapSyncingRepair(t, true) -} - -func testShortOldForkedSnapSyncingRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where a -// recent block was already committed to disk and then the process crashed. In this -// test scenario the side chain reaches above the committed block. In this case we -// expect the canonical chain to be rolled back to the committed block, but the -// chain data itself left in the database for replaying. -func TestShortNewlyForkedRepair(t *testing.T) { testShortNewlyForkedRepair(t, false) } -func TestShortNewlyForkedRepairWithSnapshots(t *testing.T) { testShortNewlyForkedRepair(t, true) } - -func testShortNewlyForkedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 6, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 6, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was already committed to disk and then the process -// crashed. In this test scenario the side chain reaches above the committed block. -// In this case we expect the canonical chain to be rolled back to the committed -// block, but the chain data itself left in the database for replaying. -func TestShortNewlyForkedSnapSyncedRepair(t *testing.T) { - testShortNewlyForkedSnapSyncedRepair(t, false) -} -func TestShortNewlyForkedSnapSyncedRepairWithSnapshots(t *testing.T) { - testShortNewlyForkedSnapSyncedRepair(t, true) -} - -func testShortNewlyForkedSnapSyncedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 6, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 6, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was not yet committed, but the process crashed. In -// this test scenario the side chain reaches above the committed block. In this -// case we expect the chain to detect that it was fast syncing and not delete -// anything, since we can just pick up directly where we left off. -func TestShortNewlyForkedSnapSyncingRepair(t *testing.T) { - testShortNewlyForkedSnapSyncingRepair(t, false) -} -func TestShortNewlyForkedSnapSyncingRepairWithSnapshots(t *testing.T) { - testShortNewlyForkedSnapSyncingRepair(t, true) -} - -func testShortNewlyForkedSnapSyncingRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 6, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 6, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then the process crashed. In this -// case we expect the canonical chain to be rolled back to the committed block, but -// the chain data itself left in the database for replaying. -func TestShortReorgedRepair(t *testing.T) { testShortReorgedRepair(t, false) } -func TestShortReorgedRepairWithSnapshots(t *testing.T) { testShortReorgedRepair(t, true) } - -func testShortReorgedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then the process -// crashed. In this case we expect the canonical chain to be rolled back to the -// committed block, but the chain data itself left in the database for replaying. -func TestShortReorgedSnapSyncedRepair(t *testing.T) { - testShortReorgedSnapSyncedRepair(t, false) -} -func TestShortReorgedSnapSyncedRepairWithSnapshots(t *testing.T) { - testShortReorgedSnapSyncedRepair(t, true) -} - -func testShortReorgedSnapSyncedRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but the process crashed. In -// this case we expect the chain to detect that it was fast syncing and not delete -// anything, since we can just pick up directly where we left off. -func TestShortReorgedSnapSyncingRepair(t *testing.T) { - testShortReorgedSnapSyncingRepair(t, false) -} -func TestShortReorgedSnapSyncingRepairWithSnapshots(t *testing.T) { - testShortReorgedSnapSyncingRepair(t, true) -} - -func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 8, - expSidechainBlocks: 10, - expFrozen: 0, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where a recent -// block - newer than the ancient limit - was already committed to disk and then -// the process crashed. In this case we expect the chain to be rolled back to the -// committed block, with everything afterwards kept as fast sync data. -func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) } -func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) } - -func testLongShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where a recent -// block - older than the ancient limit - was already committed to disk and then -// the process crashed. In this case we expect the chain to be rolled back to the -// committed block, with everything afterwards deleted. -func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) } -func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) } - -func testLongDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where the fast -// sync pivot point - newer than the ancient limit - was already committed, after -// which the process crashed. In this case we expect the chain to be rolled back -// to the committed block, with everything afterwards kept as fast sync data. -func TestLongSnapSyncedShallowRepair(t *testing.T) { - testLongSnapSyncedShallowRepair(t, false) -} -func TestLongSnapSyncedShallowRepairWithSnapshots(t *testing.T) { - testLongSnapSyncedShallowRepair(t, true) -} - -func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where the fast -// sync pivot point - older than the ancient limit - was already committed, after -// which the process crashed. In this case we expect the chain to be rolled back -// to the committed block, with everything afterwards deleted. -func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) } -func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) } - -func testLongSnapSyncedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where the fast -// sync pivot point - older than the ancient limit - was not yet committed, but the -// process crashed. In this case we expect the chain to detect that it was fast -// syncing and not delete anything, since we can just pick up directly where we -// left off. -func TestLongSnapSyncingShallowRepair(t *testing.T) { - testLongSnapSyncingShallowRepair(t, false) -} -func TestLongSnapSyncingShallowRepairWithSnapshots(t *testing.T) { - testLongSnapSyncingShallowRepair(t, true) -} - -func testLongSnapSyncingShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks where the fast -// sync pivot point - newer than the ancient limit - was not yet committed, but the -// process crashed. In this case we expect the chain to detect that it was fast -// syncing and not delete anything, since we can just pick up directly where we -// left off. -func TestLongSnapSyncingDeepRepair(t *testing.T) { testLongSnapSyncingDeepRepair(t, false) } -func TestLongSnapSyncingDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncingDeepRepair(t, true) } - -func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected in leveldb: - // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 - // - // Expected head header : C24 - // Expected head fast block: C24 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 24, - expSidechainBlocks: 0, - expFrozen: 9, - expHeadHeader: 24, - expHeadFastBlock: 24, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - newer than the ancient limit - was already -// committed to disk and then the process crashed. In this test scenario the side -// chain is below the committed block. In this case we expect the chain to be -// rolled back to the committed block, with everything afterwards kept as fast -// sync data; the side chain completely nuked by the freezer. -func TestLongOldForkedShallowRepair(t *testing.T) { - testLongOldForkedShallowRepair(t, false) -} -func TestLongOldForkedShallowRepairWithSnapshots(t *testing.T) { - testLongOldForkedShallowRepair(t, true) -} - -func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - older than the ancient limit - was already -// committed to disk and then the process crashed. In this test scenario the side -// chain is below the committed block. In this case we expect the canonical chain -// to be rolled back to the committed block, with everything afterwards deleted; -// the side chain completely nuked by the freezer. -func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) } -func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) } - -func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then the process crashed. In this test scenario -// the side chain is below the committed block. In this case we expect the chain -// to be rolled back to the committed block, with everything afterwards kept as -// fast sync data; the side chain completely nuked by the freezer. -func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) { - testLongOldForkedSnapSyncedShallowRepair(t, false) -} -func TestLongOldForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncedShallowRepair(t, true) -} - -func testLongOldForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then the process crashed. In this test scenario -// the side chain is below the committed block. In this case we expect the canonical -// chain to be rolled back to the committed block, with everything afterwards deleted; -// the side chain completely nuked by the freezer. -func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) { - testLongOldForkedSnapSyncedDeepRepair(t, false) -} -func TestLongOldForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncedDeepRepair(t, true) -} - -func testLongOldForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this test scenario the side -// chain is below the committed block. In this case we expect the chain to detect -// that it was fast syncing and not delete anything. The side chain is completely -// nuked by the freezer. -func TestLongOldForkedSnapSyncingShallowRepair(t *testing.T) { - testLongOldForkedSnapSyncingShallowRepair(t, false) -} -func TestLongOldForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncingShallowRepair(t, true) -} - -func testLongOldForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this test scenario the side -// chain is below the committed block. In this case we expect the chain to detect -// that it was fast syncing and not delete anything. The side chain is completely -// nuked by the freezer. -func TestLongOldForkedSnapSyncingDeepRepair(t *testing.T) { - testLongOldForkedSnapSyncingDeepRepair(t, false) -} -func TestLongOldForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncingDeepRepair(t, true) -} - -func testLongOldForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected in leveldb: - // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 - // - // Expected head header : C24 - // Expected head fast block: C24 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 24, - expSidechainBlocks: 0, - expFrozen: 9, - expHeadHeader: 24, - expHeadFastBlock: 24, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - newer than the ancient limit - was already -// committed to disk and then the process crashed. In this test scenario the side -// chain is above the committed block. In this case we expect the chain to be -// rolled back to the committed block, with everything afterwards kept as fast -// sync data; the side chain completely nuked by the freezer. -func TestLongNewerForkedShallowRepair(t *testing.T) { - testLongNewerForkedShallowRepair(t, false) -} -func TestLongNewerForkedShallowRepairWithSnapshots(t *testing.T) { - testLongNewerForkedShallowRepair(t, true) -} - -func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - older than the ancient limit - was already -// committed to disk and then the process crashed. In this test scenario the side -// chain is above the committed block. In this case we expect the canonical chain -// to be rolled back to the committed block, with everything afterwards deleted; -// the side chain completely nuked by the freezer. -func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) } -func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) } - -func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then the process crashed. In this test scenario -// the side chain is above the committed block. In this case we expect the chain -// to be rolled back to the committed block, with everything afterwards kept as fast -// sync data; the side chain completely nuked by the freezer. -func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) { - testLongNewerForkedSnapSyncedShallowRepair(t, false) -} -func TestLongNewerForkedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncedShallowRepair(t, true) -} - -func testLongNewerForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then the process crashed. In this test scenario -// the side chain is above the committed block. In this case we expect the canonical -// chain to be rolled back to the committed block, with everything afterwards deleted; -// the side chain completely nuked by the freezer. -func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) { - testLongNewerForkedSnapSyncedDeepRepair(t, false) -} -func TestLongNewerForkedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncedDeepRepair(t, true) -} - -func testLongNewerForkedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this test scenario the side -// chain is above the committed block. In this case we expect the chain to detect -// that it was fast syncing and not delete anything. The side chain is completely -// nuked by the freezer. -func TestLongNewerForkedSnapSyncingShallowRepair(t *testing.T) { - testLongNewerForkedSnapSyncingShallowRepair(t, false) -} -func TestLongNewerForkedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncingShallowRepair(t, true) -} - -func testLongNewerForkedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this test scenario the side -// chain is above the committed block. In this case we expect the chain to detect -// that it was fast syncing and not delete anything. The side chain is completely -// nuked by the freezer. -func TestLongNewerForkedSnapSyncingDeepRepair(t *testing.T) { - testLongNewerForkedSnapSyncingDeepRepair(t, false) -} -func TestLongNewerForkedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncingDeepRepair(t, true) -} - -func testLongNewerForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected in leveldb: - // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 - // - // Expected head header : C24 - // Expected head fast block: C24 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 24, - expSidechainBlocks: 0, - expFrozen: 9, - expHeadHeader: 24, - expHeadFastBlock: 24, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - newer than the ancient limit - was already committed -// to disk and then the process crashed. In this case we expect the chain to be -// rolled back to the committed block, with everything afterwards kept as fast sync -// data. The side chain completely nuked by the freezer. -func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) } -func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) } - -func testLongReorgedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - older than the ancient limit - was already committed -// to disk and then the process crashed. In this case we expect the canonical chains -// to be rolled back to the committed block, with everything afterwards deleted. The -// side chain completely nuked by the freezer. -func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) } -func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) } - -func testLongReorgedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then the process crashed. In this case we -// expect the chain to be rolled back to the committed block, with everything -// afterwards kept as fast sync data. The side chain completely nuked by the -// freezer. -func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) { - testLongReorgedSnapSyncedShallowRepair(t, false) -} -func TestLongReorgedSnapSyncedShallowRepairWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncedShallowRepair(t, true) -} - -func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then the process crashed. In this case we -// expect the canonical chains to be rolled back to the committed block, with -// everything afterwards deleted. The side chain completely nuked by the freezer. -func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) { - testLongReorgedSnapSyncedDeepRepair(t, false) -} -func TestLongReorgedSnapSyncedDeepRepairWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncedDeepRepair(t, true) -} - -func testLongReorgedSnapSyncedDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but the process crashed. In this case we expect the -// chain to detect that it was fast syncing and not delete anything, since we -// can just pick up directly where we left off. -func TestLongReorgedSnapSyncingShallowRepair(t *testing.T) { - testLongReorgedSnapSyncingShallowRepair(t, false) -} -func TestLongReorgedSnapSyncingShallowRepairWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncingShallowRepair(t, true) -} - -func testLongReorgedSnapSyncingShallowRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 - // - // Expected head header : C18 - // Expected head fast block: C18 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 18, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 18, - expHeadFastBlock: 18, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a recovery for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but the process crashed. In this case we expect the -// chain to detect that it was fast syncing and not delete anything, since we -// can just pick up directly where we left off. -func TestLongReorgedSnapSyncingDeepRepair(t *testing.T) { - testLongReorgedSnapSyncingDeepRepair(t, false) -} -func TestLongReorgedSnapSyncingDeepRepairWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncingDeepRepair(t, true) -} - -func testLongReorgedSnapSyncingDeepRepair(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected in leveldb: - // C8)->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 - // - // Expected head header : C24 - // Expected head fast block: C24 - // Expected head block : G - testRepair(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - expCanonicalBlocks: 24, - expSidechainBlocks: 0, - expFrozen: 9, - expHeadHeader: 24, - expHeadFastBlock: 24, - expHeadBlock: 0, - }, snapshots) -} - -func testRepair(t *testing.T, tt *rewindTest, snapshots bool) { - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - testRepairWithScheme(t, tt, snapshots, scheme) - } -} - -func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { - // It's hard to follow the test case, visualize the input - //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump(true)) - - // Create a temporary persistent database - datadir := t.TempDir() - ancient := path.Join(datadir, "ancient") - - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) - } - defer db.Close() // Might double close, should be fine - - // Initialize a fresh chain - var ( - gspec = &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.AllEthashProtocolChanges, - } - engine = ethash.NewFullFaker() - config = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, // Disable snapshot by default - StateScheme: scheme, - } - ) - defer engine.Close() - if snapshots { - config.SnapshotLimit = 256 - config.SnapshotWait = true - } - chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to create chain: %v", err) - } - // If sidechain blocks are needed, make a light chain and import it - var sideblocks types.Blocks - if tt.sidechainBlocks > 0 { - sideblocks, _ = GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x01}) - }) - if _, err := chain.InsertChain(sideblocks); err != nil { - t.Fatalf("Failed to import side chain: %v", err) - } - } - canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x02}) - b.SetDifficulty(big.NewInt(1000000)) - }) - if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - if tt.commitBlock > 0 { - if err := chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false); err != nil { - t.Fatalf("Failed to flush trie state: %v", err) - } - if snapshots { - if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { - t.Fatalf("Failed to flatten snapshots: %v", err) - } - } - } - if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) - } - // Force run a freeze cycle - type freezer interface { - Freeze(threshold uint64) error - Ancients() (uint64, error) - } - db.(freezer).Freeze(tt.freezeThreshold) - - // Set the simulated pivot block - if tt.pivotBlock != nil { - rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) - } - // Pull the plug on the database, simulating a hard crash - chain.triedb.Close() - db.Close() - chain.stopWithoutSaving() - - // Start a new blockchain back up and see where the repair leads us - db, err = rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) - } - defer db.Close() - - newChain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer newChain.Stop() - - // Iterate over all the remaining blocks and ensure there are no gaps - verifyNoGaps(t, newChain, true, canonblocks) - verifyNoGaps(t, newChain, false, sideblocks) - verifyCutoff(t, newChain, true, canonblocks, tt.expCanonicalBlocks) - verifyCutoff(t, newChain, false, sideblocks, tt.expSidechainBlocks) - - if head := newChain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { - t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) - } - if head := newChain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) - } - if head := newChain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) - } - if frozen, err := db.(freezer).Ancients(); err != nil { - t.Errorf("Failed to retrieve ancient count: %v\n", err) - } else if int(frozen) != tt.expFrozen { - t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) - } -} - -// TestIssue23496 tests scenario described in https://github.com/ethereum/go-ethereum/pull/23496#issuecomment-926393893 -// Credits to @zzyalbert for finding the issue. -// -// Local chain owns these blocks: -// G B1 B2 B3 B4 -// B1: state committed -// B2: snapshot disk layer -// B3: state committed -// B4: head block -// -// Crash happens without fully persisting snapshot and in-memory states, -// chain rewinds itself to the B1 (skip B3 in order to recover snapshot) -// In this case the snapshot layer of B3 is not created because of existent -// state. -func TestIssue23496(t *testing.T) { - testIssue23496(t, rawdb.HashScheme) - testIssue23496(t, rawdb.PathScheme) -} - -func testIssue23496(t *testing.T, scheme string) { - // It's hard to follow the test case, visualize the input - //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - - // Create a temporary persistent database - datadir := t.TempDir() - ancient := path.Join(datadir, "ancient") - - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - }) - if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) - } - defer db.Close() // Might double close, should be fine - - // Initialize a fresh chain - var ( - gspec = &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - engine = ethash.NewFullFaker() - ) - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to create chain: %v", err) - } - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x02}) - b.SetDifficulty(big.NewInt(1000000)) - }) - - // Insert block B1 and commit the state into disk - if _, err := chain.InsertChain(blocks[:1]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - chain.triedb.Commit(blocks[0].Root(), false) - - // Insert block B2 and commit the snapshot into disk - if _, err := chain.InsertChain(blocks[1:2]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - if err := chain.snaps.Cap(blocks[1].Root(), 0); err != nil { - t.Fatalf("Failed to flatten snapshots: %v", err) - } - - // Insert block B3 and commit the state into disk - if _, err := chain.InsertChain(blocks[2:3]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - chain.triedb.Commit(blocks[2].Root(), false) - - // Insert the remaining blocks - if _, err := chain.InsertChain(blocks[3:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) - } - - // Pull the plug on the database, simulating a hard crash - chain.triedb.Close() - db.Close() - chain.stopWithoutSaving() - - // Start a new blockchain back up and see where the repair leads us - db, err = rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) - } - defer db.Close() - - chain, err = NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer chain.Stop() - - if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { - t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) - } - if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { - t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) - } - expHead := uint64(1) - if scheme == rawdb.PathScheme { - expHead = uint64(2) - } - if head := chain.CurrentBlock(); head.Number.Uint64() != expHead { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, expHead) - } - - // Reinsert B2-B4 - if _, err := chain.InsertChain(blocks[1:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) - } - if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { - t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) - } - if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { - t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) - } - if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) - } - if layer := chain.Snapshots().Snapshot(blocks[2].Root()); layer == nil { - t.Error("Failed to regenerate the snapshot of known state") - } -} diff --git a/builder/core/blockchain_sethead_test.go b/builder/core/blockchain_sethead_test.go deleted file mode 100644 index 1504c74e0..000000000 --- a/builder/core/blockchain_sethead_test.go +++ /dev/null @@ -1,2190 +0,0 @@ -// 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 . - -// Tests that setting the chain head backwards doesn't leave the database in some -// strange state with gaps in the chain, nor with block data dangling in the future. - -package core - -import ( - "fmt" - "math/big" - "path" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" -) - -// rewindTest is a test case for chain rollback upon user request. -type rewindTest struct { - canonicalBlocks int // Number of blocks to generate for the canonical chain (heavier) - sidechainBlocks int // Number of blocks to generate for the side chain (lighter) - freezeThreshold uint64 // Block number until which to move things into the freezer - commitBlock uint64 // Block number for which to commit the state to disk - pivotBlock *uint64 // Pivot block number in case of fast sync - - setheadBlock uint64 // Block number to set head back to - expCanonicalBlocks int // Number of canonical blocks expected to remain in the database (excl. genesis) - expSidechainBlocks int // Number of sidechain blocks expected to remain in the database (excl. genesis) - expFrozen int // Number of canonical blocks expected to be in the freezer (incl. genesis) - expHeadHeader uint64 // Block number of the expected head header - expHeadFastBlock uint64 // Block number of the expected head fast sync block - expHeadBlock uint64 // Block number of the expected head full block -} - -//nolint:unused -func (tt *rewindTest) dump(crash bool) string { - buffer := new(strings.Builder) - - fmt.Fprint(buffer, "Chain:\n G") - for i := 0; i < tt.canonicalBlocks; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprint(buffer, " (HEAD)\n") - if tt.sidechainBlocks > 0 { - fmt.Fprintf(buffer, " â””") - for i := 0; i < tt.sidechainBlocks; i++ { - fmt.Fprintf(buffer, "->S%d", i+1) - } - fmt.Fprintf(buffer, "\n") - } - fmt.Fprintf(buffer, "\n") - - if tt.canonicalBlocks > int(tt.freezeThreshold) { - fmt.Fprint(buffer, "Frozen:\n G") - for i := 0; i < tt.canonicalBlocks-int(tt.freezeThreshold); i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprintf(buffer, "\n\n") - } else { - fmt.Fprintf(buffer, "Frozen: none\n") - } - fmt.Fprintf(buffer, "Commit: G") - if tt.commitBlock > 0 { - fmt.Fprintf(buffer, ", C%d", tt.commitBlock) - } - fmt.Fprint(buffer, "\n") - - if tt.pivotBlock == nil { - fmt.Fprintf(buffer, "Pivot : none\n") - } else { - fmt.Fprintf(buffer, "Pivot : C%d\n", *tt.pivotBlock) - } - if crash { - fmt.Fprintf(buffer, "\nCRASH\n\n") - } else { - fmt.Fprintf(buffer, "\nSetHead(%d)\n\n", tt.setheadBlock) - } - fmt.Fprintf(buffer, "------------------------------\n\n") - - if tt.expFrozen > 0 { - fmt.Fprint(buffer, "Expected in freezer:\n G") - for i := 0; i < tt.expFrozen-1; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprintf(buffer, "\n\n") - } - if tt.expFrozen > 0 { - if tt.expFrozen >= tt.expCanonicalBlocks { - fmt.Fprintf(buffer, "Expected in leveldb: none\n") - } else { - fmt.Fprintf(buffer, "Expected in leveldb:\n C%d)", tt.expFrozen-1) - for i := tt.expFrozen - 1; i < tt.expCanonicalBlocks; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprint(buffer, "\n") - if tt.expSidechainBlocks > tt.expFrozen { - fmt.Fprintf(buffer, " â””") - for i := tt.expFrozen - 1; i < tt.expSidechainBlocks; i++ { - fmt.Fprintf(buffer, "->S%d", i+1) - } - fmt.Fprintf(buffer, "\n") - } - } - } else { - fmt.Fprint(buffer, "Expected in leveldb:\n G") - for i := tt.expFrozen; i < tt.expCanonicalBlocks; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprint(buffer, "\n") - if tt.expSidechainBlocks > tt.expFrozen { - fmt.Fprintf(buffer, " â””") - for i := tt.expFrozen; i < tt.expSidechainBlocks; i++ { - fmt.Fprintf(buffer, "->S%d", i+1) - } - fmt.Fprintf(buffer, "\n") - } - } - fmt.Fprintf(buffer, "\n") - fmt.Fprintf(buffer, "Expected head header : C%d\n", tt.expHeadHeader) - fmt.Fprintf(buffer, "Expected head fast block: C%d\n", tt.expHeadFastBlock) - if tt.expHeadBlock == 0 { - fmt.Fprintf(buffer, "Expected head block : G\n") - } else { - fmt.Fprintf(buffer, "Expected head block : C%d\n", tt.expHeadBlock) - } - return buffer.String() -} - -// Tests a sethead for a short canonical chain where a recent block was already -// committed to disk and then the sethead called. In this case we expect the full -// chain to be rolled back to the committed block. Everything above the sethead -// point should be deleted. In between the committed block and the requested head -// the data can remain as "fast sync" data to avoid redownloading it. -func TestShortSetHead(t *testing.T) { testShortSetHead(t, false) } -func TestShortSetHeadWithSnapshots(t *testing.T) { testShortSetHead(t, true) } - -func testShortSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain where the fast sync pivot point was -// already committed, after which sethead was called. In this case we expect the -// chain to behave like in full sync mode, rolling back to the committed block -// Everything above the sethead point should be deleted. In between the committed -// block and the requested head the data can remain as "fast sync" data to avoid -// redownloading it. -func TestShortSnapSyncedSetHead(t *testing.T) { testShortSnapSyncedSetHead(t, false) } -func TestShortSnapSyncedSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncedSetHead(t, true) } - -func testShortSnapSyncedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain where the fast sync pivot point was -// not yet committed, but sethead was called. In this case we expect the chain to -// detect that it was fast syncing and delete everything from the new head, since -// we can just pick up fast syncing from there. The head full block should be set -// to the genesis. -func TestShortSnapSyncingSetHead(t *testing.T) { testShortSnapSyncingSetHead(t, false) } -func TestShortSnapSyncingSetHeadWithSnapshots(t *testing.T) { testShortSnapSyncingSetHead(t, true) } - -func testShortSnapSyncingSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 0, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where a -// recent block was already committed to disk and then sethead was called. In this -// test scenario the side chain is below the committed block. In this case we expect -// the canonical full chain to be rolled back to the committed block. Everything -// above the sethead point should be deleted. In between the committed block and -// the requested head the data can remain as "fast sync" data to avoid redownloading -// it. The side chain should be left alone as it was shorter. -func TestShortOldForkedSetHead(t *testing.T) { testShortOldForkedSetHead(t, false) } -func TestShortOldForkedSetHeadWithSnapshots(t *testing.T) { testShortOldForkedSetHead(t, true) } - -func testShortOldForkedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was already committed to disk and then sethead was -// called. In this test scenario the side chain is below the committed block. In -// this case we expect the canonical full chain to be rolled back to the committed -// block. Everything above the sethead point should be deleted. In between the -// committed block and the requested head the data can remain as "fast sync" data -// to avoid redownloading it. The side chain should be left alone as it was shorter. -func TestShortOldForkedSnapSyncedSetHead(t *testing.T) { - testShortOldForkedSnapSyncedSetHead(t, false) -} -func TestShortOldForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) { - testShortOldForkedSnapSyncedSetHead(t, true) -} - -func testShortOldForkedSnapSyncedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was not yet committed, but sethead was called. In this -// test scenario the side chain is below the committed block. In this case we expect -// the chain to detect that it was fast syncing and delete everything from the new -// head, since we can just pick up fast syncing from there. The head full block -// should be set to the genesis. -func TestShortOldForkedSnapSyncingSetHead(t *testing.T) { - testShortOldForkedSnapSyncingSetHead(t, false) -} -func TestShortOldForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) { - testShortOldForkedSnapSyncingSetHead(t, true) -} - -func testShortOldForkedSnapSyncingSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 3, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where a -// recent block was already committed to disk and then sethead was called. In this -// test scenario the side chain reaches above the committed block. In this case we -// expect the canonical full chain to be rolled back to the committed block. All -// data above the sethead point should be deleted. In between the committed block -// and the requested head the data can remain as "fast sync" data to avoid having -// to redownload it. The side chain should be truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortNewlyForkedSetHead(t *testing.T) { testShortNewlyForkedSetHead(t, false) } -func TestShortNewlyForkedSetHeadWithSnapshots(t *testing.T) { testShortNewlyForkedSetHead(t, true) } - -func testShortNewlyForkedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 10, - sidechainBlocks: 8, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was already committed to disk and then sethead was -// called. In this case we expect the canonical full chain to be rolled back to -// between the committed block and the requested head the data can remain as -// "fast sync" data to avoid having to redownload it. The side chain should be -// truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortNewlyForkedSnapSyncedSetHead(t *testing.T) { - testShortNewlyForkedSnapSyncedSetHead(t, false) -} -func TestShortNewlyForkedSnapSyncedSetHeadWithSnapshots(t *testing.T) { - testShortNewlyForkedSnapSyncedSetHead(t, true) -} - -func testShortNewlyForkedSnapSyncedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 10, - sidechainBlocks: 8, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a shorter side chain, where -// the fast sync pivot point was not yet committed, but sethead was called. In -// this test scenario the side chain reaches above the committed block. In this -// case we expect the chain to detect that it was fast syncing and delete -// everything from the new head, since we can just pick up fast syncing from -// there. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortNewlyForkedSnapSyncingSetHead(t *testing.T) { - testShortNewlyForkedSnapSyncingSetHead(t, false) -} -func TestShortNewlyForkedSnapSyncingSetHeadWithSnapshots(t *testing.T) { - testShortNewlyForkedSnapSyncingSetHead(t, true) -} - -func testShortNewlyForkedSnapSyncingSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 10, - sidechainBlocks: 8, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where a -// recent block was already committed to disk and then sethead was called. In this -// case we expect the canonical full chain to be rolled back to the committed block. -// All data above the sethead point should be deleted. In between the committed -// block and the requested head the data can remain as "fast sync" data to avoid -// having to redownload it. The side chain should be truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSetHead(t *testing.T) { testShortReorgedSetHead(t, false) } -func TestShortReorgedSetHeadWithSnapshots(t *testing.T) { testShortReorgedSetHead(t, true) } - -func testShortReorgedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : none - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was already committed to disk and then sethead was -// called. In this case we expect the canonical full chain to be rolled back to -// the committed block. All data above the sethead point should be deleted. In -// between the committed block and the requested head the data can remain as -// "fast sync" data to avoid having to redownload it. The side chain should be -// truncated to the head set. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSnapSyncedSetHead(t *testing.T) { - testShortReorgedSnapSyncedSetHead(t, false) -} -func TestShortReorgedSnapSyncedSetHeadWithSnapshots(t *testing.T) { - testShortReorgedSnapSyncedSetHead(t, true) -} - -func testShortReorgedSnapSyncedSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a short canonical chain and a longer side chain, where -// the fast sync pivot point was not yet committed, but sethead was called. In -// this case we expect the chain to detect that it was fast syncing and delete -// everything from the new head, since we can just pick up fast syncing from -// there. -// -// The side chain could be left to be if the fork point was before the new head -// we are deleting to, but it would be exceedingly hard to detect that case and -// properly handle it, so we'll trade extra work in exchange for simpler code. -func TestShortReorgedSnapSyncingSetHead(t *testing.T) { - testShortReorgedSnapSyncingSetHead(t, false) -} -func TestShortReorgedSnapSyncingSetHeadWithSnapshots(t *testing.T) { - testShortReorgedSnapSyncingSetHead(t, true) -} - -func testShortReorgedSnapSyncingSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10 - // - // Frozen: none - // Commit: G - // Pivot : C4 - // - // SetHead(7) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7 - // â””->S1->S2->S3->S4->S5->S6->S7 - // - // Expected head header : C7 - // Expected head fast block: C7 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 8, - sidechainBlocks: 10, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 7, - expCanonicalBlocks: 7, - expSidechainBlocks: 7, - expFrozen: 0, - expHeadHeader: 7, - expHeadFastBlock: 7, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where a recent -// block - newer than the ancient limit - was already committed to disk and then -// sethead was called. In this case we expect the full chain to be rolled back -// to the committed block. Everything above the sethead point should be deleted. -// In between the committed block and the requested head the data can remain as -// "fast sync" data to avoid redownloading it. -func TestLongShallowSetHead(t *testing.T) { testLongShallowSetHead(t, false) } -func TestLongShallowSetHeadWithSnapshots(t *testing.T) { testLongShallowSetHead(t, true) } - -func testLongShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where a recent -// block - older than the ancient limit - was already committed to disk and then -// sethead was called. In this case we expect the full chain to be rolled back -// to the committed block. Since the ancient limit was underflown, everything -// needs to be deleted onwards to avoid creating a gap. -func TestLongDeepSetHead(t *testing.T) { testLongDeepSetHead(t, false) } -func TestLongDeepSetHeadWithSnapshots(t *testing.T) { testLongDeepSetHead(t, true) } - -func testLongDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where the fast -// sync pivot point - newer than the ancient limit - was already committed, after -// which sethead was called. In this case we expect the full chain to be rolled -// back to the committed block. Everything above the sethead point should be -// deleted. In between the committed block and the requested head the data can -// remain as "fast sync" data to avoid redownloading it. -func TestLongSnapSyncedShallowSetHead(t *testing.T) { - testLongSnapSyncedShallowSetHead(t, false) -} -func TestLongSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { - testLongSnapSyncedShallowSetHead(t, true) -} - -func testLongSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where the fast -// sync pivot point - older than the ancient limit - was already committed, after -// which sethead was called. In this case we expect the full chain to be rolled -// back to the committed block. Since the ancient limit was underflown, everything -// needs to be deleted onwards to avoid creating a gap. -func TestLongSnapSyncedDeepSetHead(t *testing.T) { testLongSnapSyncedDeepSetHead(t, false) } -func TestLongSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { testLongSnapSyncedDeepSetHead(t, true) } - -func testLongSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where the fast -// sync pivot point - newer than the ancient limit - was not yet committed, but -// sethead was called. In this case we expect the chain to detect that it was fast -// syncing and delete everything from the new head, since we can just pick up fast -// syncing from there. -func TestLongSnapSyncingShallowSetHead(t *testing.T) { - testLongSnapSyncingShallowSetHead(t, false) -} -func TestLongSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { - testLongSnapSyncingShallowSetHead(t, true) -} - -func testLongSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks where the fast -// sync pivot point - older than the ancient limit - was not yet committed, but -// sethead was called. In this case we expect the chain to detect that it was fast -// syncing and delete everything from the new head, since we can just pick up fast -// syncing from there. -func TestLongSnapSyncingDeepSetHead(t *testing.T) { - testLongSnapSyncingDeepSetHead(t, false) -} -func TestLongSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { - testLongSnapSyncingDeepSetHead(t, true) -} - -func testLongSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 0, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 7, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter side -// chain, where a recent block - newer than the ancient limit - was already committed -// to disk and then sethead was called. In this case we expect the canonical full -// chain to be rolled back to the committed block. Everything above the sethead point -// should be deleted. In between the committed block and the requested head the data -// can remain as "fast sync" data to avoid redownloading it. The side chain is nuked -// by the freezer. -func TestLongOldForkedShallowSetHead(t *testing.T) { - testLongOldForkedShallowSetHead(t, false) -} -func TestLongOldForkedShallowSetHeadWithSnapshots(t *testing.T) { - testLongOldForkedShallowSetHead(t, true) -} - -func testLongOldForkedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter side -// chain, where a recent block - older than the ancient limit - was already committed -// to disk and then sethead was called. In this case we expect the canonical full -// chain to be rolled back to the committed block. Since the ancient limit was -// underflown, everything needs to be deleted onwards to avoid creating a gap. The -// side chain is nuked by the freezer. -func TestLongOldForkedDeepSetHead(t *testing.T) { testLongOldForkedDeepSetHead(t, false) } -func TestLongOldForkedDeepSetHeadWithSnapshots(t *testing.T) { testLongOldForkedDeepSetHead(t, true) } - -func testLongOldForkedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then sethead was called. In this test scenario -// the side chain is below the committed block. In this case we expect the canonical -// full chain to be rolled back to the committed block. Everything above the -// sethead point should be deleted. In between the committed block and the -// requested head the data can remain as "fast sync" data to avoid redownloading -// it. The side chain is nuked by the freezer. -func TestLongOldForkedSnapSyncedShallowSetHead(t *testing.T) { - testLongOldForkedSnapSyncedShallowSetHead(t, false) -} -func TestLongOldForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncedShallowSetHead(t, true) -} - -func testLongOldForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then sethead was called. In this test scenario -// the side chain is below the committed block. In this case we expect the canonical -// full chain to be rolled back to the committed block. Since the ancient limit was -// underflown, everything needs to be deleted onwards to avoid creating a gap. The -// side chain is nuked by the freezer. -func TestLongOldForkedSnapSyncedDeepSetHead(t *testing.T) { - testLongOldForkedSnapSyncedDeepSetHead(t, false) -} -func TestLongOldForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncedDeepSetHead(t, true) -} - -func testLongOldForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but sethead was called. In this test scenario the side -// chain is below the committed block. In this case we expect the chain to detect -// that it was fast syncing and delete everything from the new head, since we can -// just pick up fast syncing from there. The side chain is completely nuked by the -// freezer. -func TestLongOldForkedSnapSyncingShallowSetHead(t *testing.T) { - testLongOldForkedSnapSyncingShallowSetHead(t, false) -} -func TestLongOldForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncingShallowSetHead(t, true) -} - -func testLongOldForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but sethead was called. In this test scenario the side -// chain is below the committed block. In this case we expect the chain to detect -// that it was fast syncing and delete everything from the new head, since we can -// just pick up fast syncing from there. The side chain is completely nuked by the -// freezer. -func TestLongOldForkedSnapSyncingDeepSetHead(t *testing.T) { - testLongOldForkedSnapSyncingDeepSetHead(t, false) -} -func TestLongOldForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { - testLongOldForkedSnapSyncingDeepSetHead(t, true) -} - -func testLongOldForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 3, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 7, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - newer than the ancient limit - was already -// committed to disk and then sethead was called. In this test scenario the side -// chain is above the committed block. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongShallowSetHead. -func TestLongNewerForkedShallowSetHead(t *testing.T) { - testLongNewerForkedShallowSetHead(t, false) -} -func TestLongNewerForkedShallowSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedShallowSetHead(t, true) -} - -func testLongNewerForkedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where a recent block - older than the ancient limit - was already -// committed to disk and then sethead was called. In this test scenario the side -// chain is above the committed block. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongDeepSetHead. -func TestLongNewerForkedDeepSetHead(t *testing.T) { - testLongNewerForkedDeepSetHead(t, false) -} -func TestLongNewerForkedDeepSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedDeepSetHead(t, true) -} - -func testLongNewerForkedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then sethead was called. In this test scenario -// the side chain is above the committed block. In this case the freezer will delete -// the sidechain since it's dangling, reverting to TestLongSnapSyncedShallowSetHead. -func TestLongNewerForkedSnapSyncedShallowSetHead(t *testing.T) { - testLongNewerForkedSnapSyncedShallowSetHead(t, false) -} -func TestLongNewerForkedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncedShallowSetHead(t, true) -} - -func testLongNewerForkedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then sethead was called. In this test scenario -// the side chain is above the committed block. In this case the freezer will delete -// the sidechain since it's dangling, reverting to TestLongSnapSyncedDeepSetHead. -func TestLongNewerForkedSnapSyncedDeepSetHead(t *testing.T) { - testLongNewerForkedSnapSyncedDeepSetHead(t, false) -} -func TestLongNewerForkedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncedDeepSetHead(t, true) -} - -func testLongNewerForkedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but sethead was called. In this test scenario the side -// chain is above the committed block. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongSnapSyncinghallowSetHead. -func TestLongNewerForkedSnapSyncingShallowSetHead(t *testing.T) { - testLongNewerForkedSnapSyncingShallowSetHead(t, false) -} -func TestLongNewerForkedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncingShallowSetHead(t, true) -} - -func testLongNewerForkedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a shorter -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but sethead was called. In this test scenario the side -// chain is above the committed block. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongSnapSyncingDeepSetHead. -func TestLongNewerForkedSnapSyncingDeepSetHead(t *testing.T) { - testLongNewerForkedSnapSyncingDeepSetHead(t, false) -} -func TestLongNewerForkedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { - testLongNewerForkedSnapSyncingDeepSetHead(t, true) -} - -func testLongNewerForkedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 12, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 7, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - newer than the ancient limit - was already committed -// to disk and then sethead was called. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongShallowSetHead. -func TestLongReorgedShallowSetHead(t *testing.T) { testLongReorgedShallowSetHead(t, false) } -func TestLongReorgedShallowSetHeadWithSnapshots(t *testing.T) { testLongReorgedShallowSetHead(t, true) } - -func testLongReorgedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer side -// chain, where a recent block - older than the ancient limit - was already committed -// to disk and then sethead was called. In this case the freezer will delete the -// sidechain since it's dangling, reverting to TestLongDeepSetHead. -func TestLongReorgedDeepSetHead(t *testing.T) { testLongReorgedDeepSetHead(t, false) } -func TestLongReorgedDeepSetHeadWithSnapshots(t *testing.T) { testLongReorgedDeepSetHead(t, true) } - -func testLongReorgedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : none - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: nil, - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was already committed to disk and then sethead was called. In this case the -// freezer will delete the sidechain since it's dangling, reverting to -// TestLongSnapSyncedShallowSetHead. -func TestLongReorgedSnapSyncedShallowSetHead(t *testing.T) { - testLongReorgedSnapSyncedShallowSetHead(t, false) -} -func TestLongReorgedSnapSyncedShallowSetHeadWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncedShallowSetHead(t, true) -} - -func testLongReorgedSnapSyncedShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was already committed to disk and then sethead was called. In this case the -// freezer will delete the sidechain since it's dangling, reverting to -// TestLongSnapSyncedDeepSetHead. -func TestLongReorgedSnapSyncedDeepSetHead(t *testing.T) { - testLongReorgedSnapSyncedDeepSetHead(t, false) -} -func TestLongReorgedSnapSyncedDeepSetHeadWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncedDeepSetHead(t, true) -} - -func testLongReorgedSnapSyncedDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G, C4 - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4 - // - // Expected in leveldb: none - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 4, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 4, - expSidechainBlocks: 0, - expFrozen: 5, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - newer than the ancient limit - -// was not yet committed, but sethead was called. In this case we expect the -// chain to detect that it was fast syncing and delete everything from the new -// head, since we can just pick up fast syncing from there. The side chain is -// completely nuked by the freezer. -func TestLongReorgedSnapSyncingShallowSetHead(t *testing.T) { - testLongReorgedSnapSyncingShallowSetHead(t, false) -} -func TestLongReorgedSnapSyncingShallowSetHeadWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncingShallowSetHead(t, true) -} - -func testLongReorgedSnapSyncingShallowSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2 - // - // Expected in leveldb: - // C2)->C3->C4->C5->C6 - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 18, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 3, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -// Tests a sethead for a long canonical chain with frozen blocks and a longer -// side chain, where the fast sync pivot point - older than the ancient limit - -// was not yet committed, but sethead was called. In this case we expect the -// chain to detect that it was fast syncing and delete everything from the new -// head, since we can just pick up fast syncing from there. The side chain is -// completely nuked by the freezer. -func TestLongReorgedSnapSyncingDeepSetHead(t *testing.T) { - testLongReorgedSnapSyncingDeepSetHead(t, false) -} -func TestLongReorgedSnapSyncingDeepSetHeadWithSnapshots(t *testing.T) { - testLongReorgedSnapSyncingDeepSetHead(t, true) -} - -func testLongReorgedSnapSyncingDeepSetHead(t *testing.T, snapshots bool) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10->C11->C12->C13->C14->C15->C16->C17->C18->C19->C20->C21->C22->C23->C24 (HEAD) - // â””->S1->S2->S3->S4->S5->S6->S7->S8->S9->S10->S11->S12->S13->S14->S15->S16->S17->S18->S19->S20->S21->S22->S23->S24->S25->S26 - // - // Frozen: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Commit: G - // Pivot : C4 - // - // SetHead(6) - // - // ------------------------------ - // - // Expected in freezer: - // G->C1->C2->C3->C4->C5->C6 - // - // Expected in leveldb: none - // - // Expected head header : C6 - // Expected head fast block: C6 - // Expected head block : G - testSetHead(t, &rewindTest{ - canonicalBlocks: 24, - sidechainBlocks: 26, - freezeThreshold: 16, - commitBlock: 0, - pivotBlock: uint64ptr(4), - setheadBlock: 6, - expCanonicalBlocks: 6, - expSidechainBlocks: 0, - expFrozen: 7, - expHeadHeader: 6, - expHeadFastBlock: 6, - expHeadBlock: 0, - }, snapshots) -} - -func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) { - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - testSetHeadWithScheme(t, tt, snapshots, scheme) - } -} - -func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump(false)) - - // Create a temporary persistent database - datadir := t.TempDir() - ancient := path.Join(datadir, "ancient") - - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) - } - defer db.Close() - - // Initialize a fresh chain - var ( - gspec = &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.AllEthashProtocolChanges, - } - engine = ethash.NewFullFaker() - config = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, // Disable snapshot - StateScheme: scheme, - } - ) - if snapshots { - config.SnapshotLimit = 256 - config.SnapshotWait = true - } - chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to create chain: %v", err) - } - defer chain.Stop() - - // If sidechain blocks are needed, make a light chain and import it - var sideblocks types.Blocks - if tt.sidechainBlocks > 0 { - sideblocks, _ = GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.sidechainBlocks, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x01}) - }) - if _, err := chain.InsertChain(sideblocks); err != nil { - t.Fatalf("Failed to import side chain: %v", err) - } - } - canonblocks, _ := GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0x02}) - b.SetDifficulty(big.NewInt(1000000)) - }) - if _, err := chain.InsertChain(canonblocks[:tt.commitBlock]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - if tt.commitBlock > 0 { - chain.triedb.Commit(canonblocks[tt.commitBlock-1].Root(), false) - if snapshots { - if err := chain.snaps.Cap(canonblocks[tt.commitBlock-1].Root(), 0); err != nil { - t.Fatalf("Failed to flatten snapshots: %v", err) - } - } - } - if _, err := chain.InsertChain(canonblocks[tt.commitBlock:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) - } - // Reopen the trie database without persisting in-memory dirty nodes. - chain.triedb.Close() - dbconfig := &triedb.Config{} - if scheme == rawdb.PathScheme { - dbconfig.PathDB = pathdb.Defaults - } else { - dbconfig.HashDB = hashdb.Defaults - } - chain.triedb = triedb.NewDatabase(chain.db, dbconfig) - chain.stateCache = state.NewDatabaseWithNodeDB(chain.db, chain.triedb) - - // Force run a freeze cycle - type freezer interface { - Freeze(threshold uint64) error - Ancients() (uint64, error) - } - db.(freezer).Freeze(tt.freezeThreshold) - - // Set the simulated pivot block - if tt.pivotBlock != nil { - rawdb.WriteLastPivotNumber(db, *tt.pivotBlock) - } - // Set the head of the chain back to the requested number - chain.SetHead(tt.setheadBlock) - - // Iterate over all the remaining blocks and ensure there are no gaps - verifyNoGaps(t, chain, true, canonblocks) - verifyNoGaps(t, chain, false, sideblocks) - verifyCutoff(t, chain, true, canonblocks, tt.expCanonicalBlocks) - verifyCutoff(t, chain, false, sideblocks, tt.expSidechainBlocks) - - if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { - t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) - } - if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) - } - if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) - } - if frozen, err := db.(freezer).Ancients(); err != nil { - t.Errorf("Failed to retrieve ancient count: %v\n", err) - } else if int(frozen) != tt.expFrozen { - t.Errorf("Frozen block count mismatch: have %d, want %d", frozen, tt.expFrozen) - } -} - -// verifyNoGaps checks that there are no gaps after the initial set of blocks in -// the database and errors if found. -func verifyNoGaps(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks) { - t.Helper() - - var end uint64 - for i := uint64(0); i <= uint64(len(inserted)); i++ { - header := chain.GetHeaderByNumber(i) - if header == nil && end == 0 { - end = i - } - if header != nil && end > 0 { - if canonical { - t.Errorf("Canonical header gap between #%d-#%d", end, i-1) - } else { - t.Errorf("Sidechain header gap between #%d-#%d", end, i-1) - } - end = 0 // Reset for further gap detection - } - } - end = 0 - for i := uint64(0); i <= uint64(len(inserted)); i++ { - block := chain.GetBlockByNumber(i) - if block == nil && end == 0 { - end = i - } - if block != nil && end > 0 { - if canonical { - t.Errorf("Canonical block gap between #%d-#%d", end, i-1) - } else { - t.Errorf("Sidechain block gap between #%d-#%d", end, i-1) - } - end = 0 // Reset for further gap detection - } - } - end = 0 - for i := uint64(1); i <= uint64(len(inserted)); i++ { - receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()) - if receipts == nil && end == 0 { - end = i - } - if receipts != nil && end > 0 { - if canonical { - t.Errorf("Canonical receipt gap between #%d-#%d", end, i-1) - } else { - t.Errorf("Sidechain receipt gap between #%d-#%d", end, i-1) - } - end = 0 // Reset for further gap detection - } - } -} - -// verifyCutoff checks that there are no chain data available in the chain after -// the specified limit, but that it is available before. -func verifyCutoff(t *testing.T, chain *BlockChain, canonical bool, inserted types.Blocks, head int) { - t.Helper() - - for i := 1; i <= len(inserted); i++ { - if i <= head { - if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header == nil { - if canonical { - t.Errorf("Canonical header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain header #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block == nil { - if canonical { - t.Errorf("Canonical block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain block #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts == nil { - if canonical { - t.Errorf("Canonical receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain receipts #%2d [%x...] missing before cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - } else { - if header := chain.GetHeader(inserted[i-1].Hash(), uint64(i)); header != nil { - if canonical { - t.Errorf("Canonical header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain header #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - if block := chain.GetBlock(inserted[i-1].Hash(), uint64(i)); block != nil { - if canonical { - t.Errorf("Canonical block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain block #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - if receipts := chain.GetReceiptsByHash(inserted[i-1].Hash()); receipts != nil { - if canonical { - t.Errorf("Canonical receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } else { - t.Errorf("Sidechain receipts #%2d [%x...] present after cap %d", inserted[i-1].Number(), inserted[i-1].Hash().Bytes()[:3], head) - } - } - } - } -} - -// uint64ptr is a weird helper to allow 1-line constant pointer creation. -func uint64ptr(n uint64) *uint64 { - return &n -} diff --git a/builder/core/blockchain_snapshot_test.go b/builder/core/blockchain_snapshot_test.go deleted file mode 100644 index dd012c430..000000000 --- a/builder/core/blockchain_snapshot_test.go +++ /dev/null @@ -1,713 +0,0 @@ -// 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 . - -// Tests that abnormal program termination (i.e.crash) and restart can recovery -// the snapshot properly if the snapshot is enabled. - -package core - -import ( - "bytes" - "fmt" - "math/big" - "os" - "path" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" -) - -// snapshotTestBasic wraps the common testing fields in the snapshot tests. -type snapshotTestBasic struct { - scheme string // Disk scheme used for storing trie nodes - chainBlocks int // Number of blocks to generate for the canonical chain - snapshotBlock uint64 // Block number of the relevant snapshot disk layer - commitBlock uint64 // Block number for which to commit the state to disk - - expCanonicalBlocks int // Number of canonical blocks expected to remain in the database (excl. genesis) - expHeadHeader uint64 // Block number of the expected head header - expHeadFastBlock uint64 // Block number of the expected head fast sync block - expHeadBlock uint64 // Block number of the expected head full block - expSnapshotBottom uint64 // The block height corresponding to the snapshot disk layer - - // share fields, set in runtime - datadir string - ancient string - db ethdb.Database - genDb ethdb.Database - engine consensus.Engine - gspec *Genesis -} - -func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) { - // Create a temporary persistent database - datadir := t.TempDir() - ancient := path.Join(datadir, "ancient") - - db, err := rawdb.Open(rawdb.OpenOptions{ - Directory: datadir, - AncientsDirectory: ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to create persistent database: %v", err) - } - // Initialize a fresh chain - var ( - gspec = &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.AllEthashProtocolChanges, - } - engine = ethash.NewFullFaker() - ) - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(basic.scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to create chain: %v", err) - } - genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, basic.chainBlocks, func(i int, b *BlockGen) {}) - - // Insert the blocks with configured settings. - var breakpoints []uint64 - if basic.commitBlock > basic.snapshotBlock { - breakpoints = append(breakpoints, basic.snapshotBlock, basic.commitBlock) - } else { - breakpoints = append(breakpoints, basic.commitBlock, basic.snapshotBlock) - } - var startPoint uint64 - for _, point := range breakpoints { - if _, err := chain.InsertChain(blocks[startPoint:point]); err != nil { - t.Fatalf("Failed to import canonical chain start: %v", err) - } - startPoint = point - - if basic.commitBlock > 0 && basic.commitBlock == point { - chain.TrieDB().Commit(blocks[point-1].Root(), false) - } - if basic.snapshotBlock > 0 && basic.snapshotBlock == point { - // Flushing the entire snap tree into the disk, the - // relevant (a) snapshot root and (b) snapshot generator - // will be persisted atomically. - chain.snaps.Cap(blocks[point-1].Root(), 0) - diskRoot, blockRoot := chain.snaps.DiskRoot(), blocks[point-1].Root() - if !bytes.Equal(diskRoot.Bytes(), blockRoot.Bytes()) { - t.Fatalf("Failed to flush disk layer change, want %x, got %x", blockRoot, diskRoot) - } - } - } - if _, err := chain.InsertChain(blocks[startPoint:]); err != nil { - t.Fatalf("Failed to import canonical chain tail: %v", err) - } - - // Set runtime fields - basic.datadir = datadir - basic.ancient = ancient - basic.db = db - basic.genDb = genDb - basic.engine = engine - basic.gspec = gspec - return chain, blocks -} - -func (basic *snapshotTestBasic) verify(t *testing.T, chain *BlockChain, blocks []*types.Block) { - // Iterate over all the remaining blocks and ensure there are no gaps - verifyNoGaps(t, chain, true, blocks) - verifyCutoff(t, chain, true, blocks, basic.expCanonicalBlocks) - - if head := chain.CurrentHeader(); head.Number.Uint64() != basic.expHeadHeader { - t.Errorf("Head header mismatch: have %d, want %d", head.Number, basic.expHeadHeader) - } - if head := chain.CurrentSnapBlock(); head.Number.Uint64() != basic.expHeadFastBlock { - t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, basic.expHeadFastBlock) - } - if head := chain.CurrentBlock(); head.Number.Uint64() != basic.expHeadBlock { - t.Errorf("Head block mismatch: have %d, want %d", head.Number, basic.expHeadBlock) - } - - // Check the disk layer, ensure they are matched - block := chain.GetBlockByNumber(basic.expSnapshotBottom) - if block == nil { - t.Errorf("The corresponding block[%d] of snapshot disk layer is missing", basic.expSnapshotBottom) - } else if !bytes.Equal(chain.snaps.DiskRoot().Bytes(), block.Root().Bytes()) { - t.Errorf("The snapshot disk layer root is incorrect, want %x, get %x", block.Root(), chain.snaps.DiskRoot()) - } - - // Check the snapshot, ensure it's integrated - if err := chain.snaps.Verify(block.Root()); err != nil { - t.Errorf("The disk layer is not integrated %v", err) - } -} - -//nolint:unused -func (basic *snapshotTestBasic) dump() string { - buffer := new(strings.Builder) - - fmt.Fprint(buffer, "Chain:\n G") - for i := 0; i < basic.chainBlocks; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprint(buffer, " (HEAD)\n\n") - - fmt.Fprintf(buffer, "Commit: G") - if basic.commitBlock > 0 { - fmt.Fprintf(buffer, ", C%d", basic.commitBlock) - } - fmt.Fprint(buffer, "\n") - - fmt.Fprintf(buffer, "Snapshot: G") - if basic.snapshotBlock > 0 { - fmt.Fprintf(buffer, ", C%d", basic.snapshotBlock) - } - fmt.Fprint(buffer, "\n") - - //if crash { - // fmt.Fprintf(buffer, "\nCRASH\n\n") - //} else { - // fmt.Fprintf(buffer, "\nSetHead(%d)\n\n", basic.setHead) - //} - fmt.Fprintf(buffer, "------------------------------\n\n") - - fmt.Fprint(buffer, "Expected in leveldb:\n G") - for i := 0; i < basic.expCanonicalBlocks; i++ { - fmt.Fprintf(buffer, "->C%d", i+1) - } - fmt.Fprintf(buffer, "\n\n") - fmt.Fprintf(buffer, "Expected head header : C%d\n", basic.expHeadHeader) - fmt.Fprintf(buffer, "Expected head fast block: C%d\n", basic.expHeadFastBlock) - if basic.expHeadBlock == 0 { - fmt.Fprintf(buffer, "Expected head block : G\n") - } else { - fmt.Fprintf(buffer, "Expected head block : C%d\n", basic.expHeadBlock) - } - if basic.expSnapshotBottom == 0 { - fmt.Fprintf(buffer, "Expected snapshot disk : G\n") - } else { - fmt.Fprintf(buffer, "Expected snapshot disk : C%d\n", basic.expSnapshotBottom) - } - return buffer.String() -} - -func (basic *snapshotTestBasic) teardown() { - basic.db.Close() - basic.genDb.Close() - os.RemoveAll(basic.datadir) - os.RemoveAll(basic.ancient) -} - -// snapshotTest is a test case type for normal snapshot recovery. -// It can be used for testing that restart Geth normally. -type snapshotTest struct { - snapshotTestBasic -} - -func (snaptest *snapshotTest) test(t *testing.T) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump()) - chain, blocks := snaptest.prepare(t) - - // Restart the chain normally - chain.Stop() - newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer newchain.Stop() - - snaptest.verify(t, newchain, blocks) -} - -// crashSnapshotTest is a test case type for irregular snapshot recovery. -// It can be used for testing that restart Geth after the crash. -type crashSnapshotTest struct { - snapshotTestBasic -} - -func (snaptest *crashSnapshotTest) test(t *testing.T) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump()) - chain, blocks := snaptest.prepare(t) - - // Pull the plug on the database, simulating a hard crash - db := chain.db - db.Close() - chain.stopWithoutSaving() - chain.triedb.Close() - - // Start a new blockchain back up and see where the repair leads us - newdb, err := rawdb.Open(rawdb.OpenOptions{ - Directory: snaptest.datadir, - AncientsDirectory: snaptest.ancient, - Ephemeral: true, - }) - if err != nil { - t.Fatalf("Failed to reopen persistent database: %v", err) - } - defer newdb.Close() - - // The interesting thing is: instead of starting the blockchain after - // the crash, we do restart twice here: one after the crash and one - // after the normal stop. It's used to ensure the broken snapshot - // can be detected all the time. - newchain, err := NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - newchain.Stop() - - newchain, err = NewBlockChain(newdb, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer newchain.Stop() - - snaptest.verify(t, newchain, blocks) -} - -// gappedSnapshotTest is a test type used to test this scenario: -// - have a complete snapshot -// - restart without enabling the snapshot -// - insert a few blocks -// - restart with enabling the snapshot again -type gappedSnapshotTest struct { - snapshotTestBasic - gapped int // Number of blocks to insert without enabling snapshot -} - -func (snaptest *gappedSnapshotTest) test(t *testing.T) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump()) - chain, blocks := snaptest.prepare(t) - - // Insert blocks without enabling snapshot if gapping is required. - chain.Stop() - gappedBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.gapped, func(i int, b *BlockGen) {}) - - // Insert a few more blocks without enabling snapshot - var cacheConfig = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - StateScheme: snaptest.scheme, - } - newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - newchain.InsertChain(gappedBlocks) - newchain.Stop() - - // Restart the chain with enabling the snapshot - newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer newchain.Stop() - - snaptest.verify(t, newchain, blocks) -} - -// setHeadSnapshotTest is the test type used to test this scenario: -// - have a complete snapshot -// - set the head to a lower point -// - restart -type setHeadSnapshotTest struct { - snapshotTestBasic - setHead uint64 // Block number to set head back to -} - -func (snaptest *setHeadSnapshotTest) test(t *testing.T) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump()) - chain, blocks := snaptest.prepare(t) - - // Rewind the chain if setHead operation is required. - chain.SetHead(snaptest.setHead) - chain.Stop() - - newchain, err := NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - defer newchain.Stop() - - snaptest.verify(t, newchain, blocks) -} - -// wipeCrashSnapshotTest is the test type used to test this scenario: -// - have a complete snapshot -// - restart, insert more blocks without enabling the snapshot -// - restart again with enabling the snapshot -// - crash -type wipeCrashSnapshotTest struct { - snapshotTestBasic - newBlocks int -} - -func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) { - // It's hard to follow the test case, visualize the input - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - // fmt.Println(tt.dump()) - chain, blocks := snaptest.prepare(t) - - // Firstly, stop the chain properly, with all snapshot journal - // and state committed. - chain.Stop() - - config := &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - StateScheme: snaptest.scheme, - } - newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - newBlocks, _ := GenerateChain(snaptest.gspec.Config, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *BlockGen) {}) - newchain.InsertChain(newBlocks) - newchain.Stop() - - // Restart the chain, the wiper should start working - config = &CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 256, - SnapshotWait: false, // Don't wait rebuild - StateScheme: snaptest.scheme, - } - tmp, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - - // Simulate the blockchain crash. - tmp.triedb.Close() - tmp.stopWithoutSaving() - - newchain, err = NewBlockChain(snaptest.db, DefaultCacheConfigWithScheme(snaptest.scheme), snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to recreate chain: %v", err) - } - snaptest.verify(t, newchain, blocks) - newchain.Stop() -} - -// Tests a Geth restart with valid snapshot. Before the shutdown, all snapshot -// journal will be persisted correctly. In this case no snapshot recovery is -// required. -func TestRestartWithNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G - // Snapshot: G - // - // SetHead(0) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C8 - // Expected snapshot disk : G - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &snapshotTest{ - snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 8, - expSnapshotBottom: 0, // Initial disk layer built from genesis - }, - } - test.test(t) - test.teardown() - } -} - -// Tests a Geth was crashed and restarts with a broken snapshot. In this case the -// chain head should be rewound to the point with available state. And also the -// new head should must be lower than disk layer. But there is no committed point -// so the chain should be rewound to genesis and the disk layer should be left -// for recovery. -func TestNoCommitCrashWithNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G - // Snapshot: G, C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - // Expected snapshot disk : C4 - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &crashSnapshotTest{ - snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 0, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 0, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, - } - test.test(t) - test.teardown() - } -} - -// Tests a Geth was crashed and restarts with a broken snapshot. In this case the -// chain head should be rewound to the point with available state. And also the -// new head should must be lower than disk layer. But there is only a low committed -// point so the chain should be rewound to committed point and the disk layer -// should be left for recovery. -func TestLowCommitCrashWithNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G, C2 - // Snapshot: G, C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : C2 - // Expected snapshot disk : C4 - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &crashSnapshotTest{ - snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 2, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: 2, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, - } - test.test(t) - test.teardown() - } -} - -// Tests a Geth was crashed and restarts with a broken snapshot. In this case -// the chain head should be rewound to the point with available state. And also -// the new head should must be lower than disk layer. But there is only a high -// committed point so the chain should be rewound to genesis and the disk layer -// should be left for recovery. -func TestHighCommitCrashWithNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G, C6 - // Snapshot: G, C4 - // - // CRASH - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8 - // - // Expected head header : C8 - // Expected head fast block: C8 - // Expected head block : G - // Expected snapshot disk : C4 - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - expHead := uint64(0) - if scheme == rawdb.PathScheme { - expHead = uint64(4) - } - test := &crashSnapshotTest{ - snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 6, - expCanonicalBlocks: 8, - expHeadHeader: 8, - expHeadFastBlock: 8, - expHeadBlock: expHead, - expSnapshotBottom: 4, // Last committed disk layer, wait recovery - }, - } - test.test(t) - test.teardown() - } -} - -// Tests a Geth was running with snapshot enabled. Then restarts without -// enabling snapshot and after that re-enable the snapshot again. In this -// case the snapshot should be rebuilt with latest chain head. -func TestGappedNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G - // Snapshot: G - // - // SetHead(0) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 - // - // Expected head header : C10 - // Expected head fast block: C10 - // Expected head block : C10 - // Expected snapshot disk : C10 - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &gappedSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 10, - expHeadHeader: 10, - expHeadFastBlock: 10, - expHeadBlock: 10, - expSnapshotBottom: 10, // Rebuilt snapshot from the latest HEAD - }, - gapped: 2, - } - test.test(t) - test.teardown() - } -} - -// Tests the Geth was running with snapshot enabled and resetHead is applied. -// In this case the head is rewound to the target(with state available). After -// that the chain is restarted and the original disk layer is kept. -func TestSetHeadWithNewSnapshot(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G - // Snapshot: G - // - // SetHead(4) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4 - // - // Expected head header : C4 - // Expected head fast block: C4 - // Expected head block : C4 - // Expected snapshot disk : G - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &setHeadSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 0, - commitBlock: 0, - expCanonicalBlocks: 4, - expHeadHeader: 4, - expHeadFastBlock: 4, - expHeadBlock: 4, - expSnapshotBottom: 0, // The initial disk layer is built from the genesis - }, - setHead: 4, - } - test.test(t) - test.teardown() - } -} - -// Tests the Geth was running with a complete snapshot and then imports a few -// more new blocks on top without enabling the snapshot. After the restart, -// crash happens. Check everything is ok after the restart. -func TestRecoverSnapshotFromWipingCrash(t *testing.T) { - // Chain: - // G->C1->C2->C3->C4->C5->C6->C7->C8 (HEAD) - // - // Commit: G - // Snapshot: G - // - // SetHead(0) - // - // ------------------------------ - // - // Expected in leveldb: - // G->C1->C2->C3->C4->C5->C6->C7->C8->C9->C10 - // - // Expected head header : C10 - // Expected head fast block: C10 - // Expected head block : C8 - // Expected snapshot disk : C10 - for _, scheme := range []string{rawdb.HashScheme, rawdb.PathScheme} { - test := &wipeCrashSnapshotTest{ - snapshotTestBasic: snapshotTestBasic{ - scheme: scheme, - chainBlocks: 8, - snapshotBlock: 4, - commitBlock: 0, - expCanonicalBlocks: 10, - expHeadHeader: 10, - expHeadFastBlock: 10, - expHeadBlock: 10, - expSnapshotBottom: 10, - }, - newBlocks: 2, - } - test.test(t) - test.teardown() - } -} diff --git a/builder/core/blockchain_test.go b/builder/core/blockchain_test.go deleted file mode 100644 index 876d662f7..000000000 --- a/builder/core/blockchain_test.go +++ /dev/null @@ -1,4328 +0,0 @@ -// 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 core - -import ( - "errors" - "fmt" - "math/big" - "math/rand" - "os" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" -) - -// So we can deterministically seed different blockchains -var ( - canonicalSeed = 1 - forkSeed = 2 -) - -// newCanonical creates a chain database, and injects a deterministic canonical -// chain. Depending on the full flag, it creates either a full block chain or a -// header only chain. The database and genesis specification for block generation -// are also returned in case more test blocks are needed later. -func newCanonical(engine consensus.Engine, n int, full bool, scheme string) (ethdb.Database, *Genesis, *BlockChain, error) { - var ( - genesis = &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.AllEthashProtocolChanges, - } - ) - // Initialize a fresh chain with only a genesis block - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - - // Create and inject the requested chain - if n == 0 { - return rawdb.NewMemoryDatabase(), genesis, blockchain, nil - } - if full { - // Full block-chain requested - genDb, blocks := makeBlockChainWithGenesis(genesis, n, engine, canonicalSeed) - _, err := blockchain.InsertChain(blocks) - return genDb, genesis, blockchain, err - } - // Header-only chain requested - genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed) - _, err := blockchain.InsertHeaderChain(headers) - return genDb, genesis, blockchain, err -} - -func newGwei(n int64) *big.Int { - return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei)) -} - -// Test fork of length N starting from block i -func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int), scheme string) { - // Copy old chain up to #i into a new db - genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme) - if err != nil { - t.Fatal("could not make new canonical in testFork", err) - } - defer blockchain2.Stop() - - // Assert the chains have the same header/block at #i - var hash1, hash2 common.Hash - if full { - hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() - hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() - } else { - hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() - hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() - } - if hash1 != hash2 { - t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) - } - // Extend the newly created chain - var ( - blockChainB []*types.Block - headerChainB []*types.Header - ) - if full { - blockChainB = makeBlockChain(blockchain2.chainConfig, blockchain2.GetBlockByHash(blockchain2.CurrentBlock().Hash()), n, ethash.NewFaker(), genDb, forkSeed) - if _, err := blockchain2.InsertChain(blockChainB); err != nil { - t.Fatalf("failed to insert forking chain: %v", err) - } - } else { - headerChainB = makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed) - if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil { - t.Fatalf("failed to insert forking chain: %v", err) - } - } - // Sanity check that the forked chain can be imported into the original - var tdPre, tdPost *big.Int - - if full { - cur := blockchain.CurrentBlock() - tdPre = blockchain.GetTd(cur.Hash(), cur.Number.Uint64()) - if err := testBlockChainImport(blockChainB, blockchain); err != nil { - t.Fatalf("failed to import forked block chain: %v", err) - } - last := blockChainB[len(blockChainB)-1] - tdPost = blockchain.GetTd(last.Hash(), last.NumberU64()) - } else { - cur := blockchain.CurrentHeader() - tdPre = blockchain.GetTd(cur.Hash(), cur.Number.Uint64()) - if err := testHeaderChainImport(headerChainB, blockchain); err != nil { - t.Fatalf("failed to import forked header chain: %v", err) - } - last := headerChainB[len(headerChainB)-1] - tdPost = blockchain.GetTd(last.Hash(), last.Number.Uint64()) - } - // Compare the total difficulties of the chains - comparator(tdPre, tdPost) -} - -// testBlockChainImport tries to process a chain of blocks, writing them into -// the database if successful. -func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { - for _, block := range chain { - // Try and process the block - err := blockchain.engine.VerifyHeader(blockchain, block.Header()) - if err == nil { - err = blockchain.validator.ValidateBody(block) - } - if err != nil { - if err == ErrKnownBlock { - continue - } - return err - } - statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) - if err != nil { - return err - } - receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{}) - if err != nil { - blockchain.reportBlock(block, receipts, err) - return err - } - err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas) - if err != nil { - blockchain.reportBlock(block, receipts, err) - return err - } - - blockchain.chainmu.MustLock() - rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTd(block.ParentHash(), block.NumberU64()-1))) - rawdb.WriteBlock(blockchain.db, block) - statedb.Commit(block.NumberU64(), false) - blockchain.chainmu.Unlock() - } - return nil -} - -// testHeaderChainImport tries to process a chain of header, writing them into -// the database if successful. -func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { - for _, header := range chain { - // Try and validate the header - if err := blockchain.engine.VerifyHeader(blockchain, header); err != nil { - return err - } - // Manually insert the header into the database, but don't reorganise (allows subsequent testing) - blockchain.chainmu.MustLock() - rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTd(header.ParentHash, header.Number.Uint64()-1))) - rawdb.WriteHeader(blockchain.db, header) - blockchain.chainmu.Unlock() - } - return nil -} -func TestLastBlock(t *testing.T) { - testLastBlock(t, rawdb.HashScheme) - testLastBlock(t, rawdb.PathScheme) -} - -func testLastBlock(t *testing.T, scheme string) { - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - defer blockchain.Stop() - - blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 1, ethash.NewFullFaker(), genDb, 0) - if _, err := blockchain.InsertChain(blocks); err != nil { - t.Fatalf("Failed to insert block: %v", err) - } - if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { - t.Fatalf("Write/Get HeadBlockHash failed") - } -} - -// Test inserts the blocks/headers after the fork choice rule is changed. -// The chain is reorged to whatever specified. -func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full bool, scheme string) { - // Copy old chain up to #i into a new db - genDb, _, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, scheme) - if err != nil { - t.Fatal("could not make new canonical in testFork", err) - } - defer blockchain2.Stop() - - // Assert the chains have the same header/block at #i - var hash1, hash2 common.Hash - if full { - hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() - hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() - } else { - hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() - hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() - } - if hash1 != hash2 { - t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) - } - - // Extend the newly created chain - if full { - blockChainB := makeBlockChain(blockchain2.chainConfig, blockchain2.GetBlockByHash(blockchain2.CurrentBlock().Hash()), n, ethash.NewFaker(), genDb, forkSeed) - if _, err := blockchain2.InsertChain(blockChainB); err != nil { - t.Fatalf("failed to insert forking chain: %v", err) - } - if blockchain2.CurrentBlock().Number.Uint64() != blockChainB[len(blockChainB)-1].NumberU64() { - t.Fatalf("failed to reorg to the given chain") - } - if blockchain2.CurrentBlock().Hash() != blockChainB[len(blockChainB)-1].Hash() { - t.Fatalf("failed to reorg to the given chain") - } - } else { - headerChainB := makeHeaderChain(blockchain2.chainConfig, blockchain2.CurrentHeader(), n, ethash.NewFaker(), genDb, forkSeed) - if _, err := blockchain2.InsertHeaderChain(headerChainB); err != nil { - t.Fatalf("failed to insert forking chain: %v", err) - } - if blockchain2.CurrentHeader().Number.Uint64() != headerChainB[len(headerChainB)-1].Number.Uint64() { - t.Fatalf("failed to reorg to the given chain") - } - if blockchain2.CurrentHeader().Hash() != headerChainB[len(headerChainB)-1].Hash() { - t.Fatalf("failed to reorg to the given chain") - } - } -} - -// Tests that given a starting canonical chain of a given size, it can be extended -// with various length chains. -func TestExtendCanonicalHeaders(t *testing.T) { - testExtendCanonical(t, false, rawdb.HashScheme) - testExtendCanonical(t, false, rawdb.PathScheme) -} -func TestExtendCanonicalBlocks(t *testing.T) { - testExtendCanonical(t, true, rawdb.HashScheme) - testExtendCanonical(t, true, rawdb.PathScheme) -} - -func testExtendCanonical(t *testing.T, full bool, scheme string) { - length := 5 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - // Define the difficulty comparator - better := func(td1, td2 *big.Int) { - if td2.Cmp(td1) <= 0 { - t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) - } - } - // Start fork from current height - testFork(t, processor, length, 1, full, better, scheme) - testFork(t, processor, length, 2, full, better, scheme) - testFork(t, processor, length, 5, full, better, scheme) - testFork(t, processor, length, 10, full, better, scheme) -} - -// Tests that given a starting canonical chain of a given size, it can be extended -// with various length chains. -func TestExtendCanonicalHeadersAfterMerge(t *testing.T) { - testExtendCanonicalAfterMerge(t, false, rawdb.HashScheme) - testExtendCanonicalAfterMerge(t, false, rawdb.PathScheme) -} -func TestExtendCanonicalBlocksAfterMerge(t *testing.T) { - testExtendCanonicalAfterMerge(t, true, rawdb.HashScheme) - testExtendCanonicalAfterMerge(t, true, rawdb.PathScheme) -} - -func testExtendCanonicalAfterMerge(t *testing.T, full bool, scheme string) { - length := 5 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - testInsertAfterMerge(t, processor, length, 1, full, scheme) - testInsertAfterMerge(t, processor, length, 10, full, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating shorter -// forks do not take canonical ownership. -func TestShorterForkHeaders(t *testing.T) { - testShorterFork(t, false, rawdb.HashScheme) - testShorterFork(t, false, rawdb.PathScheme) -} -func TestShorterForkBlocks(t *testing.T) { - testShorterFork(t, true, rawdb.HashScheme) - testShorterFork(t, true, rawdb.PathScheme) -} - -func testShorterFork(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - // Define the difficulty comparator - worse := func(td1, td2 *big.Int) { - if td2.Cmp(td1) >= 0 { - t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) - } - } - // Sum of numbers must be less than `length` for this to be a shorter fork - testFork(t, processor, 0, 3, full, worse, scheme) - testFork(t, processor, 0, 7, full, worse, scheme) - testFork(t, processor, 1, 1, full, worse, scheme) - testFork(t, processor, 1, 7, full, worse, scheme) - testFork(t, processor, 5, 3, full, worse, scheme) - testFork(t, processor, 5, 4, full, worse, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating shorter -// forks do not take canonical ownership. -func TestShorterForkHeadersAfterMerge(t *testing.T) { - testShorterForkAfterMerge(t, false, rawdb.HashScheme) - testShorterForkAfterMerge(t, false, rawdb.PathScheme) -} -func TestShorterForkBlocksAfterMerge(t *testing.T) { - testShorterForkAfterMerge(t, true, rawdb.HashScheme) - testShorterForkAfterMerge(t, true, rawdb.PathScheme) -} - -func testShorterForkAfterMerge(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - testInsertAfterMerge(t, processor, 0, 3, full, scheme) - testInsertAfterMerge(t, processor, 0, 7, full, scheme) - testInsertAfterMerge(t, processor, 1, 1, full, scheme) - testInsertAfterMerge(t, processor, 1, 7, full, scheme) - testInsertAfterMerge(t, processor, 5, 3, full, scheme) - testInsertAfterMerge(t, processor, 5, 4, full, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating longer -// forks do take canonical ownership. -func TestLongerForkHeaders(t *testing.T) { - testLongerFork(t, false, rawdb.HashScheme) - testLongerFork(t, false, rawdb.PathScheme) -} -func TestLongerForkBlocks(t *testing.T) { - testLongerFork(t, true, rawdb.HashScheme) - testLongerFork(t, true, rawdb.PathScheme) -} - -func testLongerFork(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - testInsertAfterMerge(t, processor, 0, 11, full, scheme) - testInsertAfterMerge(t, processor, 0, 15, full, scheme) - testInsertAfterMerge(t, processor, 1, 10, full, scheme) - testInsertAfterMerge(t, processor, 1, 12, full, scheme) - testInsertAfterMerge(t, processor, 5, 6, full, scheme) - testInsertAfterMerge(t, processor, 5, 8, full, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating longer -// forks do take canonical ownership. -func TestLongerForkHeadersAfterMerge(t *testing.T) { - testLongerForkAfterMerge(t, false, rawdb.HashScheme) - testLongerForkAfterMerge(t, false, rawdb.PathScheme) -} -func TestLongerForkBlocksAfterMerge(t *testing.T) { - testLongerForkAfterMerge(t, true, rawdb.HashScheme) - testLongerForkAfterMerge(t, true, rawdb.PathScheme) -} - -func testLongerForkAfterMerge(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - testInsertAfterMerge(t, processor, 0, 11, full, scheme) - testInsertAfterMerge(t, processor, 0, 15, full, scheme) - testInsertAfterMerge(t, processor, 1, 10, full, scheme) - testInsertAfterMerge(t, processor, 1, 12, full, scheme) - testInsertAfterMerge(t, processor, 5, 6, full, scheme) - testInsertAfterMerge(t, processor, 5, 8, full, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating equal -// forks do take canonical ownership. -func TestEqualForkHeaders(t *testing.T) { - testEqualFork(t, false, rawdb.HashScheme) - testEqualFork(t, false, rawdb.PathScheme) -} -func TestEqualForkBlocks(t *testing.T) { - testEqualFork(t, true, rawdb.HashScheme) - testEqualFork(t, true, rawdb.PathScheme) -} - -func testEqualFork(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - // Define the difficulty comparator - equal := func(td1, td2 *big.Int) { - if td2.Cmp(td1) != 0 { - t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) - } - } - // Sum of numbers must be equal to `length` for this to be an equal fork - testFork(t, processor, 0, 10, full, equal, scheme) - testFork(t, processor, 1, 9, full, equal, scheme) - testFork(t, processor, 2, 8, full, equal, scheme) - testFork(t, processor, 5, 5, full, equal, scheme) - testFork(t, processor, 6, 4, full, equal, scheme) - testFork(t, processor, 9, 1, full, equal, scheme) -} - -// Tests that given a starting canonical chain of a given size, creating equal -// forks do take canonical ownership. -func TestEqualForkHeadersAfterMerge(t *testing.T) { - testEqualForkAfterMerge(t, false, rawdb.HashScheme) - testEqualForkAfterMerge(t, false, rawdb.PathScheme) -} -func TestEqualForkBlocksAfterMerge(t *testing.T) { - testEqualForkAfterMerge(t, true, rawdb.HashScheme) - testEqualForkAfterMerge(t, true, rawdb.PathScheme) -} - -func testEqualForkAfterMerge(t *testing.T, full bool, scheme string) { - length := 10 - - // Make first chain starting from genesis - _, _, processor, err := newCanonical(ethash.NewFaker(), length, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer processor.Stop() - - testInsertAfterMerge(t, processor, 0, 10, full, scheme) - testInsertAfterMerge(t, processor, 1, 9, full, scheme) - testInsertAfterMerge(t, processor, 2, 8, full, scheme) - testInsertAfterMerge(t, processor, 5, 5, full, scheme) - testInsertAfterMerge(t, processor, 6, 4, full, scheme) - testInsertAfterMerge(t, processor, 9, 1, full, scheme) -} - -// Tests that chains missing links do not get accepted by the processor. -func TestBrokenHeaderChain(t *testing.T) { - testBrokenChain(t, false, rawdb.HashScheme) - testBrokenChain(t, false, rawdb.PathScheme) -} -func TestBrokenBlockChain(t *testing.T) { - testBrokenChain(t, true, rawdb.HashScheme) - testBrokenChain(t, true, rawdb.PathScheme) -} - -func testBrokenChain(t *testing.T, full bool, scheme string) { - // Make chain starting from genesis - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, scheme) - if err != nil { - t.Fatalf("failed to make new canonical chain: %v", err) - } - defer blockchain.Stop() - - // Create a forked chain, and try to insert with a missing link - if full { - chain := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 5, ethash.NewFaker(), genDb, forkSeed)[1:] - if err := testBlockChainImport(chain, blockchain); err == nil { - t.Errorf("broken block chain not reported") - } - } else { - chain := makeHeaderChain(blockchain.chainConfig, blockchain.CurrentHeader(), 5, ethash.NewFaker(), genDb, forkSeed)[1:] - if err := testHeaderChainImport(chain, blockchain); err == nil { - t.Errorf("broken header chain not reported") - } - } -} - -// Tests that reorganising a long difficult chain after a short easy one -// overwrites the canonical numbers and links in the database. -func TestReorgLongHeaders(t *testing.T) { - testReorgLong(t, false, rawdb.HashScheme) - testReorgLong(t, false, rawdb.PathScheme) -} -func TestReorgLongBlocks(t *testing.T) { - testReorgLong(t, true, rawdb.HashScheme) - testReorgLong(t, true, rawdb.PathScheme) -} - -func testReorgLong(t *testing.T, full bool, scheme string) { - testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280+params.GenesisDifficulty.Int64(), full, scheme) -} - -// Tests that reorganising a short difficult chain after a long easy one -// overwrites the canonical numbers and links in the database. -func TestReorgShortHeaders(t *testing.T) { - testReorgShort(t, false, rawdb.HashScheme) - testReorgShort(t, false, rawdb.PathScheme) -} -func TestReorgShortBlocks(t *testing.T) { - testReorgShort(t, true, rawdb.HashScheme) - testReorgShort(t, true, rawdb.PathScheme) -} - -func testReorgShort(t *testing.T, full bool, scheme string) { - // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment - // we need a fairly long chain of blocks with different difficulties for a short - // one to become heavier than a long one. The 96 is an empirical value. - easy := make([]int64, 96) - for i := 0; i < len(easy); i++ { - easy[i] = 60 - } - diff := make([]int64, len(easy)-1) - for i := 0; i < len(diff); i++ { - diff[i] = -9 - } - testReorg(t, easy, diff, 12615120+params.GenesisDifficulty.Int64(), full, scheme) -} - -func testReorg(t *testing.T, first, second []int64, td int64, full bool, scheme string) { - // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - defer blockchain.Stop() - - // Insert an easy and a difficult chain afterwards - easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), genDb, len(first), func(i int, b *BlockGen) { - b.OffsetTime(first[i]) - }) - diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), genDb, len(second), func(i int, b *BlockGen) { - b.OffsetTime(second[i]) - }) - if full { - if _, err := blockchain.InsertChain(easyBlocks); err != nil { - t.Fatalf("failed to insert easy chain: %v", err) - } - if _, err := blockchain.InsertChain(diffBlocks); err != nil { - t.Fatalf("failed to insert difficult chain: %v", err) - } - } else { - easyHeaders := make([]*types.Header, len(easyBlocks)) - for i, block := range easyBlocks { - easyHeaders[i] = block.Header() - } - diffHeaders := make([]*types.Header, len(diffBlocks)) - for i, block := range diffBlocks { - diffHeaders[i] = block.Header() - } - if _, err := blockchain.InsertHeaderChain(easyHeaders); err != nil { - t.Fatalf("failed to insert easy chain: %v", err) - } - if _, err := blockchain.InsertHeaderChain(diffHeaders); err != nil { - t.Fatalf("failed to insert difficult chain: %v", err) - } - } - // Check that the chain is valid number and link wise - if full { - prev := blockchain.CurrentBlock() - for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().Number.Uint64() - 1); block.NumberU64() != 0; prev, block = block.Header(), blockchain.GetBlockByNumber(block.NumberU64()-1) { - if prev.ParentHash != block.Hash() { - t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash, block.Hash()) - } - } - } else { - prev := blockchain.CurrentHeader() - for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { - if prev.ParentHash != header.Hash() { - t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) - } - } - } - // Make sure the chain total difficulty is the correct one - want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) - if full { - cur := blockchain.CurrentBlock() - if have := blockchain.GetTd(cur.Hash(), cur.Number.Uint64()); have.Cmp(want) != 0 { - t.Errorf("total difficulty mismatch: have %v, want %v", have, want) - } - } else { - cur := blockchain.CurrentHeader() - if have := blockchain.GetTd(cur.Hash(), cur.Number.Uint64()); have.Cmp(want) != 0 { - t.Errorf("total difficulty mismatch: have %v, want %v", have, want) - } - } -} - -// Tests that the insertion functions detect banned hashes. -func TestBadHeaderHashes(t *testing.T) { - testBadHashes(t, false, rawdb.HashScheme) - testBadHashes(t, false, rawdb.PathScheme) -} -func TestBadBlockHashes(t *testing.T) { - testBadHashes(t, true, rawdb.HashScheme) - testBadHashes(t, true, rawdb.PathScheme) -} - -func testBadHashes(t *testing.T, full bool, scheme string) { - // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - defer blockchain.Stop() - - // Create a chain, ban a hash and try to import - if full { - blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 3, ethash.NewFaker(), genDb, 10) - - BadHashes[blocks[2].Header().Hash()] = true - defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() - - _, err = blockchain.InsertChain(blocks) - } else { - headers := makeHeaderChain(blockchain.chainConfig, blockchain.CurrentHeader(), 3, ethash.NewFaker(), genDb, 10) - - BadHashes[headers[2].Hash()] = true - defer func() { delete(BadHashes, headers[2].Hash()) }() - - _, err = blockchain.InsertHeaderChain(headers) - } - if !errors.Is(err, ErrBannedHash) { - t.Errorf("error mismatch: have: %v, want: %v", err, ErrBannedHash) - } -} - -// Tests that bad hashes are detected on boot, and the chain rolled back to a -// good state prior to the bad hash. -func TestReorgBadHeaderHashes(t *testing.T) { - testReorgBadHashes(t, false, rawdb.HashScheme) - testReorgBadHashes(t, false, rawdb.PathScheme) -} -func TestReorgBadBlockHashes(t *testing.T) { - testReorgBadHashes(t, true, rawdb.HashScheme) - testReorgBadHashes(t, true, rawdb.PathScheme) -} - -func testReorgBadHashes(t *testing.T, full bool, scheme string) { - // Create a pristine chain and database - genDb, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - // Create a chain, import and ban afterwards - headers := makeHeaderChain(blockchain.chainConfig, blockchain.CurrentHeader(), 4, ethash.NewFaker(), genDb, 10) - blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 4, ethash.NewFaker(), genDb, 10) - - if full { - if _, err = blockchain.InsertChain(blocks); err != nil { - t.Errorf("failed to import blocks: %v", err) - } - if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { - t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) - } - BadHashes[blocks[3].Header().Hash()] = true - defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() - } else { - if _, err = blockchain.InsertHeaderChain(headers); err != nil { - t.Errorf("failed to import headers: %v", err) - } - if blockchain.CurrentHeader().Hash() != headers[3].Hash() { - t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) - } - BadHashes[headers[3].Hash()] = true - defer func() { delete(BadHashes, headers[3].Hash()) }() - } - blockchain.Stop() - - // Create a new BlockChain and check that it rolled back the state. - ncm, err := NewBlockChain(blockchain.db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create new chain manager: %v", err) - } - if full { - if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { - t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) - } - if blocks[2].Header().GasLimit != ncm.GasLimit() { - t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) - } - } else { - if ncm.CurrentHeader().Hash() != headers[2].Hash() { - t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) - } - } - ncm.Stop() -} - -// Tests chain insertions in the face of one entity containing an invalid nonce. -func TestHeadersInsertNonceError(t *testing.T) { - testInsertNonceError(t, false, rawdb.HashScheme) - testInsertNonceError(t, false, rawdb.PathScheme) -} -func TestBlocksInsertNonceError(t *testing.T) { - testInsertNonceError(t, true, rawdb.HashScheme) - testInsertNonceError(t, true, rawdb.PathScheme) -} - -func testInsertNonceError(t *testing.T, full bool, scheme string) { - doTest := func(i int) { - // Create a pristine chain and database - genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - defer blockchain.Stop() - - // Create and insert a chain with a failing nonce - var ( - failAt int - failRes int - failNum uint64 - ) - if full { - blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), i, ethash.NewFaker(), genDb, 0) - - failAt = rand.Int() % len(blocks) - failNum = blocks[failAt].NumberU64() - - blockchain.engine = ethash.NewFakeFailer(failNum) - failRes, err = blockchain.InsertChain(blocks) - } else { - headers := makeHeaderChain(blockchain.chainConfig, blockchain.CurrentHeader(), i, ethash.NewFaker(), genDb, 0) - - failAt = rand.Int() % len(headers) - failNum = headers[failAt].Number.Uint64() - - blockchain.engine = ethash.NewFakeFailer(failNum) - blockchain.hc.engine = blockchain.engine - failRes, err = blockchain.InsertHeaderChain(headers) - } - // Check that the returned error indicates the failure - if failRes != failAt { - t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) - } - // Check that all blocks after the failing block have been inserted - for j := 0; j < i-failAt; j++ { - if full { - if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { - t.Errorf("test %d: invalid block in chain: %v", i, block) - } - } else { - if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { - t.Errorf("test %d: invalid header in chain: %v", i, header) - } - } - } - } - for i := 1; i < 25 && !t.Failed(); i++ { - doTest(i) - } -} - -// Tests that fast importing a block chain produces the same chain data as the -// classical full block processing. -func TestFastVsFullChains(t *testing.T) { - testFastVsFullChains(t, rawdb.HashScheme) - testFastVsFullChains(t, rawdb.PathScheme) -} - -func testFastVsFullChains(t *testing.T, scheme string) { - // Configure and generate a sample block chain - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{address: {Balance: funds}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - signer = types.LatestSigner(gspec.Config) - ) - _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, func(i int, block *BlockGen) { - block.SetCoinbase(common.Address{0x00}) - - // If the block number is multiple of 3, send a few bonus transactions to the miner - if i%3 == 2 { - for j := 0; j < i%4+1; j++ { - tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key) - if err != nil { - panic(err) - } - block.AddTx(tx) - } - } - // If the block number is a multiple of 5, add an uncle to the block - if i%5 == 4 { - block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 2).Hash(), Number: big.NewInt(int64(i))}) - } - }) - // Import the chain as an archive node for the comparison baseline - archiveDb := rawdb.NewMemoryDatabase() - archive, _ := NewBlockChain(archiveDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer archive.Stop() - - if n, err := archive.InsertChain(blocks); err != nil { - t.Fatalf("failed to process block %d: %v", n, err) - } - // Fast import the chain as a non-archive node to test - fastDb := rawdb.NewMemoryDatabase() - fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer fast.Stop() - - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - if n, err := fast.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { - t.Fatalf("failed to insert receipt %d: %v", n, err) - } - // Freezer style fast import the chain. - ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - defer ancientDb.Close() - - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer ancient.Stop() - - if n, err := ancient.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { - t.Fatalf("failed to insert receipt %d: %v", n, err) - } - - // Iterate over all chain data components, and cross reference - for i := 0; i < len(blocks); i++ { - num, hash, time := blocks[i].NumberU64(), blocks[i].Hash(), blocks[i].Time() - - if ftd, atd := fast.GetTd(hash, num), archive.GetTd(hash, num); ftd.Cmp(atd) != 0 { - t.Errorf("block #%d [%x]: td mismatch: fastdb %v, archivedb %v", num, hash, ftd, atd) - } - if antd, artd := ancient.GetTd(hash, num), archive.GetTd(hash, num); antd.Cmp(artd) != 0 { - t.Errorf("block #%d [%x]: td mismatch: ancientdb %v, archivedb %v", num, hash, antd, artd) - } - if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { - t.Errorf("block #%d [%x]: header mismatch: fastdb %v, archivedb %v", num, hash, fheader, aheader) - } - if anheader, arheader := ancient.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); anheader.Hash() != arheader.Hash() { - t.Errorf("block #%d [%x]: header mismatch: ancientdb %v, archivedb %v", num, hash, anheader, arheader) - } - if fblock, arblock, anblock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash), ancient.GetBlockByHash(hash); fblock.Hash() != arblock.Hash() || anblock.Hash() != arblock.Hash() { - t.Errorf("block #%d [%x]: block mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock, anblock, arblock) - } else if types.DeriveSha(fblock.Transactions(), trie.NewStackTrie(nil)) != types.DeriveSha(arblock.Transactions(), trie.NewStackTrie(nil)) || types.DeriveSha(anblock.Transactions(), trie.NewStackTrie(nil)) != types.DeriveSha(arblock.Transactions(), trie.NewStackTrie(nil)) { - t.Errorf("block #%d [%x]: transactions mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Transactions(), anblock.Transactions(), arblock.Transactions()) - } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) || types.CalcUncleHash(anblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) { - t.Errorf("block #%d [%x]: uncles mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Uncles(), anblock, arblock.Uncles()) - } - - // Check receipts. - freceipts := rawdb.ReadReceipts(fastDb, hash, num, time, fast.Config()) - anreceipts := rawdb.ReadReceipts(ancientDb, hash, num, time, fast.Config()) - areceipts := rawdb.ReadReceipts(archiveDb, hash, num, time, fast.Config()) - if types.DeriveSha(freceipts, trie.NewStackTrie(nil)) != types.DeriveSha(areceipts, trie.NewStackTrie(nil)) { - t.Errorf("block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, freceipts, anreceipts, areceipts) - } - - // Check that hash-to-number mappings are present in all databases. - if m := rawdb.ReadHeaderNumber(fastDb, hash); m == nil || *m != num { - t.Errorf("block #%d [%x]: wrong hash-to-number mapping in fastdb: %v", num, hash, m) - } - if m := rawdb.ReadHeaderNumber(ancientDb, hash); m == nil || *m != num { - t.Errorf("block #%d [%x]: wrong hash-to-number mapping in ancientdb: %v", num, hash, m) - } - if m := rawdb.ReadHeaderNumber(archiveDb, hash); m == nil || *m != num { - t.Errorf("block #%d [%x]: wrong hash-to-number mapping in archivedb: %v", num, hash, m) - } - } - - // Check that the canonical chains are the same between the databases - for i := 0; i < len(blocks)+1; i++ { - if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { - t.Errorf("block #%d: canonical hash mismatch: fastdb %v, archivedb %v", i, fhash, ahash) - } - if anhash, arhash := rawdb.ReadCanonicalHash(ancientDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); anhash != arhash { - t.Errorf("block #%d: canonical hash mismatch: ancientdb %v, archivedb %v", i, anhash, arhash) - } - } -} - -// Tests that various import methods move the chain head pointers to the correct -// positions. -func TestLightVsFastVsFullChainHeads(t *testing.T) { - testLightVsFastVsFullChainHeads(t, rawdb.HashScheme) - testLightVsFastVsFullChainHeads(t, rawdb.PathScheme) -} - -func testLightVsFastVsFullChainHeads(t *testing.T, scheme string) { - // Configure and generate a sample block chain - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{address: {Balance: funds}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - ) - height := uint64(1024) - _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil) - - // makeDb creates a db instance for testing. - makeDb := func() ethdb.Database { - db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - return db - } - // Configure a subchain to roll back - remove := blocks[height/2].NumberU64() - - // Create a small assertion method to check the three heads - assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { - t.Helper() - - if num := chain.CurrentBlock().Number.Uint64(); num != block { - t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) - } - if num := chain.CurrentSnapBlock().Number.Uint64(); num != fast { - t.Errorf("%s head snap-block mismatch: have #%v, want #%v", kind, num, fast) - } - if num := chain.CurrentHeader().Number.Uint64(); num != header { - t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) - } - } - // Import the chain as an archive node and ensure all pointers are updated - archiveDb := makeDb() - defer archiveDb.Close() - - archiveCaching := *defaultCacheConfig - archiveCaching.TrieDirtyDisabled = true - archiveCaching.StateScheme = scheme - - archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if n, err := archive.InsertChain(blocks); err != nil { - t.Fatalf("failed to process block %d: %v", n, err) - } - defer archive.Stop() - - assert(t, "archive", archive, height, height, height) - archive.SetHead(remove - 1) - assert(t, "archive", archive, height/2, height/2, height/2) - - // Import the chain as a non-archive node and ensure all pointers are updated - fastDb := makeDb() - defer fastDb.Close() - fast, _ := NewBlockChain(fastDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer fast.Stop() - - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - if n, err := fast.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { - t.Fatalf("failed to insert receipt %d: %v", n, err) - } - assert(t, "fast", fast, height, height, 0) - fast.SetHead(remove - 1) - assert(t, "fast", fast, height/2, height/2, 0) - - // Import the chain as a ancient-first node and ensure all pointers are updated - ancientDb := makeDb() - defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer ancient.Stop() - - if n, err := ancient.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { - t.Fatalf("failed to insert receipt %d: %v", n, err) - } - assert(t, "ancient", ancient, height, height, 0) - ancient.SetHead(remove - 1) - assert(t, "ancient", ancient, 0, 0, 0) - - if frozen, err := ancientDb.Ancients(); err != nil || frozen != 1 { - t.Fatalf("failed to truncate ancient store, want %v, have %v", 1, frozen) - } - // Import the chain as a light node and ensure all pointers are updated - lightDb := makeDb() - defer lightDb.Close() - light, _ := NewBlockChain(lightDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if n, err := light.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - defer light.Stop() - - assert(t, "light", light, height, 0, 0) - light.SetHead(remove - 1) - assert(t, "light", light, height/2, 0, 0) -} - -// Tests that chain reorganisations handle transaction removals and reinsertions. -func TestChainTxReorgs(t *testing.T) { - testChainTxReorgs(t, rawdb.HashScheme) - testChainTxReorgs(t, rawdb.PathScheme) -} - -func testChainTxReorgs(t *testing.T, scheme string) { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - addr3 = crypto.PubkeyToAddress(key3.PublicKey) - gspec = &Genesis{ - Config: params.TestChainConfig, - GasLimit: 3141592, - Alloc: types.GenesisAlloc{ - addr1: {Balance: big.NewInt(1000000000000000)}, - addr2: {Balance: big.NewInt(1000000000000000)}, - addr3: {Balance: big.NewInt(1000000000000000)}, - }, - } - signer = types.LatestSigner(gspec.Config) - ) - - // Create two transactions shared between the chains: - // - postponed: transaction included at a later block in the forked chain - // - swapped: transaction included at the same block number in the forked chain - postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, key1) - swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, key1) - - // Create two transactions that will be dropped by the forked chain: - // - pastDrop: transaction dropped retroactively from a past block - // - freshDrop: transaction dropped exactly at the block where the reorg is detected - var pastDrop, freshDrop *types.Transaction - - // Create three transactions that will be added in the forked chain: - // - pastAdd: transaction added before the reorganization is detected - // - freshAdd: transaction added at the exact block the reorg is detected - // - futureAdd: transaction added after the reorg has already finished - var pastAdd, freshAdd, futureAdd *types.Transaction - - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) { - switch i { - case 0: - pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key2) - - gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point - gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork - - case 2: - freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key2) - - gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point - gen.AddTx(swapped) // This transaction will be swapped out at the exact height - - gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain - } - }) - // Import the chain. This runs all block validation rules. - db := rawdb.NewMemoryDatabase() - blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if i, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert original chain[%d]: %v", i, err) - } - defer blockchain.Stop() - - // overwrite the old chain - _, chain, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 5, func(i int, gen *BlockGen) { - switch i { - case 0: - pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key3) - gen.AddTx(pastAdd) // This transaction needs to be injected during reorg - - case 2: - gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain - gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain - - freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key3) - gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time - - case 3: - futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key3) - gen.AddTx(futureAdd) // This transaction will be added after a full reorg - } - }) - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - - // removed tx - for i, tx := range (types.Transactions{pastDrop, freshDrop}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { - t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) - } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { - t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) - } - } - // added tx - for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { - t.Errorf("add %d: expected tx to be found", i) - } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { - t.Errorf("add %d: expected receipt to be found", i) - } - } - // shared tx - for i, tx := range (types.Transactions{postponed, swapped}) { - if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { - t.Errorf("share %d: expected tx to be found", i) - } - if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { - t.Errorf("share %d: expected receipt to be found", i) - } - } -} - -func TestLogReorgs(t *testing.T) { - testLogReorgs(t, rawdb.HashScheme) - testLogReorgs(t, rawdb.PathScheme) -} - -func testLogReorgs(t *testing.T, scheme string) { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - - // this code generates a log - code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} - signer = types.LatestSigner(gspec.Config) - ) - - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - rmLogsCh := make(chan RemovedLogsEvent) - blockchain.SubscribeRemovedLogsEvent(rmLogsCh) - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) { - if i == 1 { - tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, code), signer, key1) - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - } - }) - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert chain: %v", err) - } - - _, chain, _ = GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {}) - done := make(chan struct{}) - go func() { - ev := <-rmLogsCh - if len(ev.Logs) == 0 { - t.Error("expected logs") - } - close(done) - }() - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - timeout := time.NewTimer(1 * time.Second) - defer timeout.Stop() - select { - case <-done: - case <-timeout.C: - t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") - } -} - -// This EVM code generates a log when the contract is created. -var logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - -// This test checks that log events and RemovedLogsEvent are sent -// when the chain reorganizes. -func TestLogRebirth(t *testing.T) { - testLogRebirth(t, rawdb.HashScheme) - testLogRebirth(t, rawdb.PathScheme) -} - -func testLogRebirth(t *testing.T, scheme string) { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} - signer = types.LatestSigner(gspec.Config) - engine = ethash.NewFaker() - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - ) - defer blockchain.Stop() - - // The event channels. - newLogCh := make(chan []*types.Log, 10) - rmLogsCh := make(chan RemovedLogsEvent, 10) - blockchain.SubscribeLogsEvent(newLogCh) - blockchain.SubscribeRemovedLogsEvent(rmLogsCh) - - // This chain contains 10 logs. - genDb, chain, _ := GenerateChainWithGenesis(gspec, engine, 3, func(i int, gen *BlockGen) { - if i < 2 { - for ii := 0; ii < 5; ii++ { - tx, err := types.SignNewTx(key1, signer, &types.LegacyTx{ - Nonce: gen.TxNonce(addr1), - GasPrice: gen.header.BaseFee, - Gas: uint64(1000001), - Data: logCode, - }) - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - } - } - }) - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 10, 0) - - // Generate long reorg chain containing more logs. Inserting the - // chain removes one log and adds four. - _, forkChain, _ := GenerateChainWithGenesis(gspec, engine, 3, func(i int, gen *BlockGen) { - if i == 2 { - // The last (head) block is not part of the reorg-chain, we can ignore it - return - } - for ii := 0; ii < 5; ii++ { - tx, err := types.SignNewTx(key1, signer, &types.LegacyTx{ - Nonce: gen.TxNonce(addr1), - GasPrice: gen.header.BaseFee, - Gas: uint64(1000000), - Data: logCode, - }) - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - } - gen.OffsetTime(-9) // higher block difficulty - }) - if _, err := blockchain.InsertChain(forkChain); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 10, 10) - - // This chain segment is rooted in the original chain, but doesn't contain any logs. - // When inserting it, the canonical chain switches away from forkChain and re-emits - // the log event for the old chain, as well as a RemovedLogsEvent for forkChain. - newBlocks, _ := GenerateChain(gspec.Config, chain[len(chain)-1], engine, genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := blockchain.InsertChain(newBlocks); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 10, 10) -} - -// This test is a variation of TestLogRebirth. It verifies that log events are emitted -// when a side chain containing log events overtakes the canonical chain. -func TestSideLogRebirth(t *testing.T) { - testSideLogRebirth(t, rawdb.HashScheme) - testSideLogRebirth(t, rawdb.PathScheme) -} - -func testSideLogRebirth(t *testing.T, scheme string) { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} - signer = types.LatestSigner(gspec.Config) - blockchain, _ = NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - ) - defer blockchain.Stop() - - newLogCh := make(chan []*types.Log, 10) - rmLogsCh := make(chan RemovedLogsEvent, 10) - blockchain.SubscribeLogsEvent(newLogCh) - blockchain.SubscribeRemovedLogsEvent(rmLogsCh) - - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) { - if i == 1 { - gen.OffsetTime(-9) // higher block difficulty - } - }) - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) - - // Generate side chain with lower difficulty - genDb, sideChain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) { - if i == 1 { - tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, logCode), signer, key1) - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - } - }) - if _, err := blockchain.InsertChain(sideChain); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) - - // Generate a new block based on side chain. - newBlocks, _ := GenerateChain(gspec.Config, sideChain[len(sideChain)-1], ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := blockchain.InsertChain(newBlocks); err != nil { - t.Fatalf("failed to insert forked chain: %v", err) - } - checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) -} - -func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) { - t.Helper() - var ( - countNew int - countRm int - prev int - ) - // Drain events. - for len(logsCh) > 0 { - x := <-logsCh - countNew += len(x) - for _, log := range x { - // We expect added logs to be in ascending order: 0:0, 0:1, 1:0 ... - have := 100*int(log.BlockNumber) + int(log.TxIndex) - if have < prev { - t.Fatalf("Expected new logs to arrive in ascending order (%d < %d)", have, prev) - } - prev = have - } - } - prev = 0 - for len(rmLogsCh) > 0 { - x := <-rmLogsCh - countRm += len(x.Logs) - for _, log := range x.Logs { - // We expect removed logs to be in ascending order: 0:0, 0:1, 1:0 ... - have := 100*int(log.BlockNumber) + int(log.TxIndex) - if have < prev { - t.Fatalf("Expected removed logs to arrive in ascending order (%d < %d)", have, prev) - } - prev = have - } - } - - if countNew != wantNew { - t.Fatalf("wrong number of log events: got %d, want %d", countNew, wantNew) - } - if countRm != wantRemoved { - t.Fatalf("wrong number of removed log events: got %d, want %d", countRm, wantRemoved) - } -} - -func TestReorgSideEvent(t *testing.T) { - testReorgSideEvent(t, rawdb.HashScheme) - testReorgSideEvent(t, rawdb.PathScheme) -} - -func testReorgSideEvent(t *testing.T, scheme string) { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}, - } - signer = types.LatestSigner(gspec.Config) - ) - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {}) - if _, err := blockchain.InsertChain(chain); err != nil { - t.Fatalf("failed to insert chain: %v", err) - } - - _, replacementBlocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, gen *BlockGen) { - tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, nil), signer, key1) - if i == 2 { - gen.OffsetTime(-9) - } - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - }) - chainSideCh := make(chan ChainSideEvent, 64) - blockchain.SubscribeChainSideEvent(chainSideCh) - if _, err := blockchain.InsertChain(replacementBlocks); err != nil { - t.Fatalf("failed to insert chain: %v", err) - } - - // first two block of the secondary chain are for a brief moment considered - // side chains because up to that point the first one is considered the - // heavier chain. - expectedSideHashes := map[common.Hash]bool{ - replacementBlocks[0].Hash(): true, - replacementBlocks[1].Hash(): true, - chain[0].Hash(): true, - chain[1].Hash(): true, - chain[2].Hash(): true, - } - - i := 0 - - const timeoutDura = 10 * time.Second - timeout := time.NewTimer(timeoutDura) -done: - for { - select { - case ev := <-chainSideCh: - block := ev.Block - if _, ok := expectedSideHashes[block.Hash()]; !ok { - t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) - } - i++ - - if i == len(expectedSideHashes) { - timeout.Stop() - - break done - } - timeout.Reset(timeoutDura) - - case <-timeout.C: - t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") - } - } - - // make sure no more events are fired - select { - case e := <-chainSideCh: - t.Errorf("unexpected event fired: %v", e) - case <-time.After(250 * time.Millisecond): - } -} - -// Tests if the canonical block can be fetched from the database during chain insertion. -func TestCanonicalBlockRetrieval(t *testing.T) { - testCanonicalBlockRetrieval(t, rawdb.HashScheme) - testCanonicalBlockRetrieval(t, rawdb.PathScheme) -} - -func testCanonicalBlockRetrieval(t *testing.T, scheme string) { - _, gspec, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, scheme) - if err != nil { - t.Fatalf("failed to create pristine chain: %v", err) - } - defer blockchain.Stop() - - _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 10, func(i int, gen *BlockGen) {}) - - var pend sync.WaitGroup - pend.Add(len(chain)) - - for i := range chain { - go func(block *types.Block) { - defer pend.Done() - - // try to retrieve a block by its canonical hash and see if the block data can be retrieved. - for { - ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) - if ch == (common.Hash{}) { - continue // busy wait for canonical hash to be written - } - if ch != block.Hash() { - t.Errorf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) - return - } - fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) - if fb == nil { - t.Errorf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) - return - } - if fb.Hash() != block.Hash() { - t.Errorf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) - return - } - return - } - }(chain[i]) - - if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { - t.Fatalf("failed to insert block %d: %v", i, err) - } - } - pend.Wait() -} -func TestEIP155Transition(t *testing.T) { - testEIP155Transition(t, rawdb.HashScheme) - testEIP155Transition(t, rawdb.PathScheme) -} - -func testEIP155Transition(t *testing.T, scheme string) { - // Configure and generate a sample block chain - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000) - deleteAddr = common.Address{1} - gspec = &Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(2), - HomesteadBlock: new(big.Int), - }, - Alloc: types.GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, - } - ) - genDb, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, block *BlockGen) { - var ( - tx *types.Transaction - err error - basicTx = func(signer types.Signer) (*types.Transaction, error) { - return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) - } - ) - switch i { - case 0: - tx, err = basicTx(types.HomesteadSigner{}) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - case 2: - tx, err = basicTx(types.HomesteadSigner{}) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - - tx, err = basicTx(types.LatestSigner(gspec.Config)) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - case 3: - tx, err = basicTx(types.HomesteadSigner{}) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - - tx, err = basicTx(types.LatestSigner(gspec.Config)) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - } - }) - - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - if _, err := blockchain.InsertChain(blocks); err != nil { - t.Fatal(err) - } - block := blockchain.GetBlockByNumber(1) - if block.Transactions()[0].Protected() { - t.Error("Expected block[0].txs[0] to not be replay protected") - } - - block = blockchain.GetBlockByNumber(3) - if block.Transactions()[0].Protected() { - t.Error("Expected block[3].txs[0] to not be replay protected") - } - if !block.Transactions()[1].Protected() { - t.Error("Expected block[3].txs[1] to be replay protected") - } - if _, err := blockchain.InsertChain(blocks[4:]); err != nil { - t.Fatal(err) - } - - // generate an invalid chain id transaction - config := ¶ms.ChainConfig{ - ChainID: big.NewInt(2), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(2), - HomesteadBlock: new(big.Int), - } - blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), genDb, 4, func(i int, block *BlockGen) { - var ( - tx *types.Transaction - err error - basicTx = func(signer types.Signer) (*types.Transaction, error) { - return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) - } - ) - if i == 0 { - tx, err = basicTx(types.LatestSigner(config)) - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - } - }) - _, err := blockchain.InsertChain(blocks) - if have, want := err, types.ErrInvalidChainId; !errors.Is(have, want) { - t.Errorf("have %v, want %v", have, want) - } -} -func TestEIP161AccountRemoval(t *testing.T) { - testEIP161AccountRemoval(t, rawdb.HashScheme) - testEIP161AccountRemoval(t, rawdb.PathScheme) -} - -func testEIP161AccountRemoval(t *testing.T, scheme string) { - // Configure and generate a sample block chain - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000) - theAddr = common.Address{1} - gspec = &Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: new(big.Int), - EIP155Block: new(big.Int), - EIP150Block: new(big.Int), - EIP158Block: big.NewInt(2), - }, - Alloc: types.GenesisAlloc{address: {Balance: funds}}, - } - ) - _, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, block *BlockGen) { - var ( - tx *types.Transaction - err error - signer = types.LatestSigner(gspec.Config) - ) - switch i { - case 0: - tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) - case 1: - tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) - case 2: - tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) - } - if err != nil { - t.Fatal(err) - } - block.AddTx(tx) - }) - // account must exist pre eip 161 - blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { - t.Fatal(err) - } - if st, _ := blockchain.State(); !st.Exist(theAddr) { - t.Error("expected account to exist") - } - - // account needs to be deleted post eip 161 - if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { - t.Fatal(err) - } - if st, _ := blockchain.State(); st.Exist(theAddr) { - t.Error("account should not exist") - } - - // account mustn't be created post eip 161 - if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { - t.Fatal(err) - } - if st, _ := blockchain.State(); st.Exist(theAddr) { - t.Error("account should not exist") - } -} - -// This is a regression test (i.e. as weird as it is, don't delete it ever), which -// tests that under weird reorg conditions the blockchain and its internal header- -// chain return the same latest block/header. -// -// https://github.com/ethereum/go-ethereum/pull/15941 -func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { - testBlockchainHeaderchainReorgConsistency(t, rawdb.HashScheme) - testBlockchainHeaderchainReorgConsistency(t, rawdb.PathScheme) -} - -func testBlockchainHeaderchainReorgConsistency(t *testing.T, scheme string) { - // Generate a canonical chain to act as the main dataset - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - genDb, blocks, _ := GenerateChainWithGenesis(genesis, engine, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - - // Generate a bunch of fork blocks, each side forking from the canonical chain - forks := make([]*types.Block, len(blocks)) - for i := 0; i < len(forks); i++ { - parent := genesis.ToBlock() - if i > 0 { - parent = blocks[i-1] - } - fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) - forks[i] = fork[0] - } - // Import the canonical and fork chain side by side, verifying the current block - // and current header consistency - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - for i := 0; i < len(blocks); i++ { - if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", i, err) - } - if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { - t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) - } - if _, err := chain.InsertChain(forks[i : i+1]); err != nil { - t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) - } - if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { - t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) - } - } -} - -// Tests that importing small side forks doesn't leave junk in the trie database -// cache (which would eventually cause memory issues). -func TestTrieForkGC(t *testing.T) { - // Generate a canonical chain to act as the main dataset - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - genDb, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - - // Generate a bunch of fork blocks, each side forking from the canonical chain - forks := make([]*types.Block, len(blocks)) - for i := 0; i < len(forks); i++ { - parent := genesis.ToBlock() - if i > 0 { - parent = blocks[i-1] - } - fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) - forks[i] = fork[0] - } - // Import the canonical and fork chain side by side, forcing the trie cache to cache both - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - for i := 0; i < len(blocks); i++ { - if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", i, err) - } - if _, err := chain.InsertChain(forks[i : i+1]); err != nil { - t.Fatalf("fork %d: failed to insert into chain: %v", i, err) - } - } - // Dereference all the recent tries and ensure no past trie is left in - for i := 0; i < TriesInMemory; i++ { - chain.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) - chain.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) - } - if _, nodes, _ := chain.TrieDB().Size(); nodes > 0 { // all memory is returned in the nodes return for hashdb - t.Fatalf("stale tries still alive after garbase collection") - } -} - -// Tests that doing large reorgs works even if the state associated with the -// forking point is not available any more. -func TestLargeReorgTrieGC(t *testing.T) { - testLargeReorgTrieGC(t, rawdb.HashScheme) - testLargeReorgTrieGC(t, rawdb.PathScheme) -} - -func testLargeReorgTrieGC(t *testing.T, scheme string) { - // Generate the original common chain segment and the two competing forks - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - genDb, shared, _ := GenerateChainWithGenesis(genesis, engine, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - original, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) - competitor, _ := GenerateChain(genesis.Config, shared[len(shared)-1], engine, genDb, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) - - // Import the shared chain and the original canonical one - db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - defer db.Close() - - chain, err := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if _, err := chain.InsertChain(shared); err != nil { - t.Fatalf("failed to insert shared chain: %v", err) - } - if _, err := chain.InsertChain(original); err != nil { - t.Fatalf("failed to insert original chain: %v", err) - } - // Ensure that the state associated with the forking point is pruned away - if chain.HasState(shared[len(shared)-1].Root()) { - t.Fatalf("common-but-old ancestor still cache") - } - // Import the competitor chain without exceeding the canonical's TD and ensure - // we have not processed any of the blocks (protection against malicious blocks) - if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { - t.Fatalf("failed to insert competitor chain: %v", err) - } - for i, block := range competitor[:len(competitor)-2] { - if chain.HasState(block.Root()) { - t.Fatalf("competitor %d: low TD chain became processed", i) - } - } - // Import the head of the competitor chain, triggering the reorg and ensure we - // successfully reprocess all the stashed away blocks. - if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { - t.Fatalf("failed to finalize competitor chain: %v", err) - } - // In path-based trie database implementation, it will keep 128 diff + 1 disk - // layers, totally 129 latest states available. In hash-based it's 128. - states := TriesInMemory - if scheme == rawdb.PathScheme { - states = states + 1 - } - for i, block := range competitor[:len(competitor)-states] { - if chain.HasState(block.Root()) { - t.Fatalf("competitor %d: unexpected competing chain state", i) - } - } - for i, block := range competitor[len(competitor)-states:] { - if !chain.HasState(block.Root()) { - t.Fatalf("competitor %d: competing chain state missing", i) - } - } -} - -func TestBlockchainRecovery(t *testing.T) { - testBlockchainRecovery(t, rawdb.HashScheme) - testBlockchainRecovery(t, rawdb.PathScheme) -} - -func testBlockchainRecovery(t *testing.T, scheme string) { - // Configure and generate a sample block chain - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000) - gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{address: {Balance: funds}}} - ) - height := uint64(1024) - _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(height), nil) - - // Import the chain as a ancient-first node and ensure all pointers are updated - ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - defer ancientDb.Close() - ancient, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - if n, err := ancient.InsertHeaderChain(headers); err != nil { - t.Fatalf("failed to insert header %d: %v", n, err) - } - if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { - t.Fatalf("failed to insert receipt %d: %v", n, err) - } - rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior - ancient.Stop() - - // Destroy head fast block manually - midBlock := blocks[len(blocks)/2] - rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) - - // Reopen broken blockchain again - ancient, _ = NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer ancient.Stop() - if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { - t.Errorf("head block mismatch: have #%v, want #%v", num, 0) - } - if num := ancient.CurrentSnapBlock().Number.Uint64(); num != midBlock.NumberU64() { - t.Errorf("head snap-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) - } - if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { - t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) - } -} - -// This test checks that InsertReceiptChain will roll back correctly when attempting to insert a side chain. -func TestInsertReceiptChainRollback(t *testing.T) { - testInsertReceiptChainRollback(t, rawdb.HashScheme) - testInsertReceiptChainRollback(t, rawdb.PathScheme) -} - -func testInsertReceiptChainRollback(t *testing.T, scheme string) { - // Generate forked chain. The returned BlockChain object is used to process the side chain blocks. - tmpChain, sideblocks, canonblocks, gspec, err := getLongAndShortChains(scheme) - if err != nil { - t.Fatal(err) - } - defer tmpChain.Stop() - // Get the side chain receipts. - if _, err := tmpChain.InsertChain(sideblocks); err != nil { - t.Fatal("processing side chain failed:", err) - } - t.Log("sidechain head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) - sidechainReceipts := make([]types.Receipts, len(sideblocks)) - for i, block := range sideblocks { - sidechainReceipts[i] = tmpChain.GetReceiptsByHash(block.Hash()) - } - // Get the canon chain receipts. - if _, err := tmpChain.InsertChain(canonblocks); err != nil { - t.Fatal("processing canon chain failed:", err) - } - t.Log("canon head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) - canonReceipts := make([]types.Receipts, len(canonblocks)) - for i, block := range canonblocks { - canonReceipts[i] = tmpChain.GetReceiptsByHash(block.Hash()) - } - - // Set up a BlockChain that uses the ancient store. - ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - defer ancientDb.Close() - - ancientChain, _ := NewBlockChain(ancientDb, DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer ancientChain.Stop() - - // Import the canonical header chain. - canonHeaders := make([]*types.Header, len(canonblocks)) - for i, block := range canonblocks { - canonHeaders[i] = block.Header() - } - if _, err = ancientChain.InsertHeaderChain(canonHeaders); err != nil { - t.Fatal("can't import canon headers:", err) - } - - // Try to insert blocks/receipts of the side chain. - _, err = ancientChain.InsertReceiptChain(sideblocks, sidechainReceipts, uint64(len(sideblocks))) - if err == nil { - t.Fatal("expected error from InsertReceiptChain.") - } - if ancientChain.CurrentSnapBlock().Number.Uint64() != 0 { - t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentSnapBlock().Number) - } - if frozen, err := ancientChain.db.Ancients(); err != nil || frozen != 1 { - t.Fatalf("failed to truncate ancient data, frozen index is %d", frozen) - } - - // Insert blocks/receipts of the canonical chain. - _, err = ancientChain.InsertReceiptChain(canonblocks, canonReceipts, uint64(len(canonblocks))) - if err != nil { - t.Fatalf("can't import canon chain receipts: %v", err) - } - if ancientChain.CurrentSnapBlock().Number.Uint64() != canonblocks[len(canonblocks)-1].NumberU64() { - t.Fatalf("failed to insert ancient recept chain after rollback") - } - if frozen, _ := ancientChain.db.Ancients(); frozen != uint64(len(canonblocks))+1 { - t.Fatalf("wrong ancients count %d", frozen) - } -} - -// Tests that importing a very large side fork, which is larger than the canon chain, -// but where the difficulty per block is kept low: this means that it will not -// overtake the 'canon' chain until after it's passed canon by about 200 blocks. -// -// Details at: -// - https://github.com/ethereum/go-ethereum/issues/18977 -// - https://github.com/ethereum/go-ethereum/pull/18988 -func TestLowDiffLongChain(t *testing.T) { - testLowDiffLongChain(t, rawdb.HashScheme) - testLowDiffLongChain(t, rawdb.PathScheme) -} - -func testLowDiffLongChain(t *testing.T, scheme string) { - // Generate a canonical chain to act as the main dataset - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - // We must use a pretty long chain to ensure that the fork doesn't overtake us - // until after at least 128 blocks post tip - genDb, blocks, _ := GenerateChainWithGenesis(genesis, engine, 6*TriesInMemory, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - b.OffsetTime(-9) - }) - - // Import the canonical chain - diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - defer diskdb.Close() - - chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - // Generate fork chain, starting from an early block - parent := blocks[10] - fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 8*TriesInMemory, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{2}) - }) - - // And now import the fork - if i, err := chain.InsertChain(fork); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", i, err) - } - head := chain.CurrentBlock() - if got := fork[len(fork)-1].Hash(); got != head.Hash() { - t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) - } - // Sanity check that all the canonical numbers are present - header := chain.CurrentHeader() - for number := head.Number.Uint64(); number > 0; number-- { - if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { - t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) - } - header = chain.GetHeader(header.ParentHash, number-1) - } -} - -// Tests that importing a sidechain (S), where -// - S is sidechain, containing blocks [Sn...Sm] -// - C is canon chain, containing blocks [G..Cn..Cm] -// - A common ancestor is placed at prune-point + blocksBetweenCommonAncestorAndPruneblock -// - The sidechain S is prepended with numCanonBlocksInSidechain blocks from the canon chain -// -// The mergePoint can be these values: -// -1: the transition won't happen -// 0: the transition happens since genesis -// 1: the transition happens after some chain segments -func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommonAncestorAndPruneblock int, mergePoint int) { - // Generate a canonical chain to act as the main dataset - chainConfig := *params.TestChainConfig - var ( - merger = consensus.NewMerger(rawdb.NewMemoryDatabase()) - engine = beacon.New(ethash.NewFaker()) - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key.PublicKey) - nonce = uint64(0) - - gspec = &Genesis{ - Config: &chainConfig, - Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - signer = types.LatestSigner(gspec.Config) - mergeBlock = math.MaxInt32 - ) - // Generate and import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - // Activate the transition since genesis if required - if mergePoint == 0 { - mergeBlock = 0 - merger.ReachTTD() - merger.FinalizePoS() - - // Set the terminal total difficulty in the config - gspec.Config.TerminalTotalDifficulty = big.NewInt(0) - } - genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2*TriesInMemory, func(i int, gen *BlockGen) { - tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key) - if err != nil { - t.Fatalf("failed to create tx: %v", err) - } - gen.AddTx(tx) - if int(gen.header.Number.Uint64()) >= mergeBlock { - gen.SetPoS() - } - nonce++ - }) - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - lastPrunedIndex := len(blocks) - TriesInMemory - 1 - lastPrunedBlock := blocks[lastPrunedIndex] - firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] - - // Verify pruning of lastPrunedBlock - if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { - t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) - } - // Verify firstNonPrunedBlock is not pruned - if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { - t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) - } - - // Activate the transition in the middle of the chain - if mergePoint == 1 { - merger.ReachTTD() - merger.FinalizePoS() - // Set the terminal total difficulty in the config - ttd := big.NewInt(int64(len(blocks))) - ttd.Mul(ttd, params.GenesisDifficulty) - gspec.Config.TerminalTotalDifficulty = ttd - mergeBlock = len(blocks) - } - - // Generate the sidechain - // First block should be a known block, block after should be a pruned block. So - // canon(pruned), side, side... - - // Generate fork chain, make it longer than canon - parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock - parent := blocks[parentIndex] - fork, _ := GenerateChain(gspec.Config, parent, engine, genDb, 2*TriesInMemory, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{2}) - if int(b.header.Number.Uint64()) >= mergeBlock { - b.SetPoS() - } - }) - // Prepend the parent(s) - var sidechain []*types.Block - for i := numCanonBlocksInSidechain; i > 0; i-- { - sidechain = append(sidechain, blocks[parentIndex+1-i]) - } - sidechain = append(sidechain, fork...) - n, err := chain.InsertChain(sidechain) - if err != nil { - t.Errorf("Got error, %v number %d - %d", err, sidechain[n].NumberU64(), n) - } - head := chain.CurrentBlock() - if got := fork[len(fork)-1].Hash(); got != head.Hash() { - t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) - } -} - -// Tests that importing a sidechain (S), where -// - S is sidechain, containing blocks [Sn...Sm] -// - C is canon chain, containing blocks [G..Cn..Cm] -// - The common ancestor Cc is pruned -// - The first block in S: Sn, is == Cn -// -// That is: the sidechain for import contains some blocks already present in canon chain. -// So the blocks are: -// -// [ Cn, Cn+1, Cc, Sn+3 ... Sm] -// ^ ^ ^ pruned -func TestPrunedImportSide(t *testing.T) { - //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) - //glogger.Verbosity(3) - //log.Root().SetHandler(log.Handler(glogger)) - testSideImport(t, 3, 3, -1) - testSideImport(t, 3, -3, -1) - testSideImport(t, 10, 0, -1) - testSideImport(t, 1, 10, -1) - testSideImport(t, 1, -10, -1) -} - -func TestPrunedImportSideWithMerging(t *testing.T) { - //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) - //glogger.Verbosity(3) - //log.Root().SetHandler(log.Handler(glogger)) - testSideImport(t, 3, 3, 0) - testSideImport(t, 3, -3, 0) - testSideImport(t, 10, 0, 0) - testSideImport(t, 1, 10, 0) - testSideImport(t, 1, -10, 0) - - testSideImport(t, 3, 3, 1) - testSideImport(t, 3, -3, 1) - testSideImport(t, 10, 0, 1) - testSideImport(t, 1, 10, 1) - testSideImport(t, 1, -10, 1) -} - -func TestInsertKnownHeaders(t *testing.T) { - testInsertKnownChainData(t, "headers", rawdb.HashScheme) - testInsertKnownChainData(t, "headers", rawdb.PathScheme) -} -func TestInsertKnownReceiptChain(t *testing.T) { - testInsertKnownChainData(t, "receipts", rawdb.HashScheme) - testInsertKnownChainData(t, "receipts", rawdb.PathScheme) -} -func TestInsertKnownBlocks(t *testing.T) { - testInsertKnownChainData(t, "blocks", rawdb.HashScheme) - testInsertKnownChainData(t, "blocks", rawdb.PathScheme) -} - -func testInsertKnownChainData(t *testing.T, typ string, scheme string) { - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - genDb, blocks, receipts := GenerateChainWithGenesis(genesis, engine, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - - // A longer chain but total difficulty is lower. - blocks2, receipts2 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - - // A shorter chain but total difficulty is higher. - blocks3, receipts3 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 64, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - b.OffsetTime(-9) // A higher difficulty - }) - // Import the shared chain and the original canonical one - chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - defer chaindb.Close() - - chain, err := NewBlockChain(chaindb, DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - var ( - inserter func(blocks []*types.Block, receipts []types.Receipts) error - asserter func(t *testing.T, block *types.Block) - ) - if typ == "headers" { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - headers := make([]*types.Header, 0, len(blocks)) - for _, block := range blocks { - headers = append(headers, block.Header()) - } - _, err := chain.InsertHeaderChain(headers) - return err - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentHeader().Hash() != block.Hash() { - t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) - } - } - } else if typ == "receipts" { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - headers := make([]*types.Header, 0, len(blocks)) - for _, block := range blocks { - headers = append(headers, block.Header()) - } - _, err := chain.InsertHeaderChain(headers) - if err != nil { - return err - } - _, err = chain.InsertReceiptChain(blocks, receipts, 0) - return err - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentSnapBlock().Hash() != block.Hash() { - t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentSnapBlock().Hash().Hex(), block.Hash().Hex()) - } - } - } else { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - _, err := chain.InsertChain(blocks) - return err - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentBlock().Hash() != block.Hash() { - t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) - } - } - } - - if err := inserter(blocks, receipts); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - - // Reimport the chain data again. All the imported - // chain data are regarded "known" data. - if err := inserter(blocks, receipts); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks[len(blocks)-1]) - - // Import a long canonical chain with some known data as prefix. - rollback := blocks[len(blocks)/2].NumberU64() - - chain.SetHead(rollback - 1) - if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks2[len(blocks2)-1]) - - // Import a heavier shorter but higher total difficulty chain with some known data as prefix. - if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks3[len(blocks3)-1]) - - // Import a longer but lower total difficulty chain with some known data as prefix. - if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - // The head shouldn't change. - asserter(t, blocks3[len(blocks3)-1]) - - // Rollback the heavier chain and re-insert the longer chain again - chain.SetHead(rollback - 1) - if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks2[len(blocks2)-1]) -} - -func TestInsertKnownHeadersWithMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "headers", 0) -} -func TestInsertKnownReceiptChainWithMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "receipts", 0) -} -func TestInsertKnownBlocksWithMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "blocks", 0) -} -func TestInsertKnownHeadersAfterMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "headers", 1) -} -func TestInsertKnownReceiptChainAfterMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "receipts", 1) -} -func TestInsertKnownBlocksAfterMerging(t *testing.T) { - testInsertKnownChainDataWithMerging(t, "blocks", 1) -} - -// mergeHeight can be assigned in these values: -// 0: means the merging is applied since genesis -// 1: means the merging is applied after the first segment -func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight int) { - // Copy the TestChainConfig so we can modify it during tests - chainConfig := *params.TestChainConfig - var ( - genesis = &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: &chainConfig, - } - engine = beacon.New(ethash.NewFaker()) - mergeBlock = uint64(math.MaxUint64) - ) - // Apply merging since genesis - if mergeHeight == 0 { - genesis.Config.TerminalTotalDifficulty = big.NewInt(0) - mergeBlock = uint64(0) - } - - genDb, blocks, receipts := GenerateChainWithGenesis(genesis, engine, 32, - func(i int, b *BlockGen) { - if b.header.Number.Uint64() >= mergeBlock { - b.SetPoS() - } - b.SetCoinbase(common.Address{1}) - }) - - // Apply merging after the first segment - if mergeHeight == 1 { - // TTD is genesis diff + blocks - ttd := big.NewInt(1 + int64(len(blocks))) - ttd.Mul(ttd, params.GenesisDifficulty) - genesis.Config.TerminalTotalDifficulty = ttd - mergeBlock = uint64(len(blocks)) - } - // Longer chain and shorter chain - blocks2, receipts2 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 65, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - if b.header.Number.Uint64() >= mergeBlock { - b.SetPoS() - } - }) - blocks3, receipts3 := GenerateChain(genesis.Config, blocks[len(blocks)-1], engine, genDb, 64, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - b.OffsetTime(-9) // Time shifted, difficulty shouldn't be changed - if b.header.Number.Uint64() >= mergeBlock { - b.SetPoS() - } - }) - // Import the shared chain and the original canonical one - chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - if err != nil { - t.Fatalf("failed to create temp freezer db: %v", err) - } - defer chaindb.Close() - - chain, err := NewBlockChain(chaindb, nil, genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - var ( - inserter func(blocks []*types.Block, receipts []types.Receipts) error - asserter func(t *testing.T, block *types.Block) - ) - if typ == "headers" { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - headers := make([]*types.Header, 0, len(blocks)) - for _, block := range blocks { - headers = append(headers, block.Header()) - } - i, err := chain.InsertHeaderChain(headers) - if err != nil { - return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err) - } - return err - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentHeader().Hash() != block.Hash() { - t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) - } - } - } else if typ == "receipts" { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - headers := make([]*types.Header, 0, len(blocks)) - for _, block := range blocks { - headers = append(headers, block.Header()) - } - i, err := chain.InsertHeaderChain(headers) - if err != nil { - return fmt.Errorf("index %d: %w", i, err) - } - _, err = chain.InsertReceiptChain(blocks, receipts, 0) - return err - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentSnapBlock().Hash() != block.Hash() { - t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentSnapBlock().Hash().Hex(), block.Hash().Hex()) - } - } - } else { - inserter = func(blocks []*types.Block, receipts []types.Receipts) error { - i, err := chain.InsertChain(blocks) - if err != nil { - return fmt.Errorf("index %d: %w", i, err) - } - return nil - } - asserter = func(t *testing.T, block *types.Block) { - if chain.CurrentBlock().Hash() != block.Hash() { - t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) - } - } - } - if err := inserter(blocks, receipts); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - - // Reimport the chain data again. All the imported - // chain data are regarded "known" data. - if err := inserter(blocks, receipts); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks[len(blocks)-1]) - - // Import a long canonical chain with some known data as prefix. - rollback := blocks[len(blocks)/2].NumberU64() - chain.SetHead(rollback - 1) - if err := inserter(blocks, receipts); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks[len(blocks)-1]) - - // Import a longer chain with some known data as prefix. - if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks2[len(blocks2)-1]) - - // Import a shorter chain with some known data as prefix. - // The reorg is expected since the fork choice rule is - // already changed. - if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - // The head shouldn't change. - asserter(t, blocks3[len(blocks3)-1]) - - // Reimport the longer chain again, the reorg is still expected - chain.SetHead(rollback - 1) - if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { - t.Fatalf("failed to insert chain data: %v", err) - } - asserter(t, blocks2[len(blocks2)-1]) -} - -// getLongAndShortChains returns two chains: A is longer, B is heavier. -func getLongAndShortChains(scheme string) (*BlockChain, []*types.Block, []*types.Block, *Genesis, error) { - // Generate a canonical chain to act as the main dataset - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - // Generate and import the canonical chain, - // Offset the time, to keep the difficulty low - genDb, longChain, _ := GenerateChainWithGenesis(genesis, engine, 80, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - return nil, nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) - } - // Generate fork chain, make it shorter than canon, with common ancestor pretty early - parentIndex := 3 - parent := longChain[parentIndex] - heavyChainExt, _ := GenerateChain(genesis.Config, parent, engine, genDb, 75, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{2}) - b.OffsetTime(-9) - }) - var heavyChain []*types.Block - heavyChain = append(heavyChain, longChain[:parentIndex+1]...) - heavyChain = append(heavyChain, heavyChainExt...) - - // Verify that the test is sane - var ( - longerTd = new(big.Int) - shorterTd = new(big.Int) - ) - for index, b := range longChain { - longerTd.Add(longerTd, b.Difficulty()) - if index <= parentIndex { - shorterTd.Add(shorterTd, b.Difficulty()) - } - } - for _, b := range heavyChain { - shorterTd.Add(shorterTd, b.Difficulty()) - } - if shorterTd.Cmp(longerTd) <= 0 { - return nil, nil, nil, nil, fmt.Errorf("test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) - } - longerNum := longChain[len(longChain)-1].NumberU64() - shorterNum := heavyChain[len(heavyChain)-1].NumberU64() - if shorterNum >= longerNum { - return nil, nil, nil, nil, fmt.Errorf("test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) - } - return chain, longChain, heavyChain, genesis, nil -} - -// TestReorgToShorterRemovesCanonMapping tests that if we -// 1. Have a chain [0 ... N .. X] -// 2. Reorg to shorter but heavier chain [0 ... N ... Y] -// 3. Then there should be no canon mapping for the block at height X -// 4. The forked block should still be retrievable by hash -func TestReorgToShorterRemovesCanonMapping(t *testing.T) { - testReorgToShorterRemovesCanonMapping(t, rawdb.HashScheme) - testReorgToShorterRemovesCanonMapping(t, rawdb.PathScheme) -} - -func testReorgToShorterRemovesCanonMapping(t *testing.T, scheme string) { - chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme) - if err != nil { - t.Fatal(err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(canonblocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - canonNum := chain.CurrentBlock().Number.Uint64() - canonHash := chain.CurrentBlock().Hash() - _, err = chain.InsertChain(sideblocks) - if err != nil { - t.Errorf("Got error, %v", err) - } - head := chain.CurrentBlock() - if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { - t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) - } - // We have now inserted a sidechain. - if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { - t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) - } - if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { - t.Errorf("expected header to be gone: %v", headerByNum.Number) - } - if blockByHash := chain.GetBlockByHash(canonHash); blockByHash == nil { - t.Errorf("expected block to be present: %x", blockByHash.Hash()) - } - if headerByHash := chain.GetHeaderByHash(canonHash); headerByHash == nil { - t.Errorf("expected header to be present: %x", headerByHash.Hash()) - } -} - -// TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario -// as TestReorgToShorterRemovesCanonMapping, but applied on headerchain -// imports -- that is, for fast sync -func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { - testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.HashScheme) - testReorgToShorterRemovesCanonMappingHeaderChain(t, rawdb.PathScheme) -} - -func testReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T, scheme string) { - chain, canonblocks, sideblocks, _, err := getLongAndShortChains(scheme) - if err != nil { - t.Fatal(err) - } - defer chain.Stop() - - // Convert into headers - canonHeaders := make([]*types.Header, len(canonblocks)) - for i, block := range canonblocks { - canonHeaders[i] = block.Header() - } - if n, err := chain.InsertHeaderChain(canonHeaders); err != nil { - t.Fatalf("header %d: failed to insert into chain: %v", n, err) - } - canonNum := chain.CurrentHeader().Number.Uint64() - canonHash := chain.CurrentBlock().Hash() - sideHeaders := make([]*types.Header, len(sideblocks)) - for i, block := range sideblocks { - sideHeaders[i] = block.Header() - } - if n, err := chain.InsertHeaderChain(sideHeaders); err != nil { - t.Fatalf("header %d: failed to insert into chain: %v", n, err) - } - head := chain.CurrentHeader() - if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { - t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) - } - // We have now inserted a sidechain. - if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { - t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) - } - if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { - t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) - } - if blockByHash := chain.GetBlockByHash(canonHash); blockByHash == nil { - t.Errorf("expected block to be present: %x", blockByHash.Hash()) - } - if headerByHash := chain.GetHeaderByHash(canonHash); headerByHash == nil { - t.Errorf("expected header to be present: %x", headerByHash.Hash()) - } -} - -// Benchmarks large blocks with value transfers to non-existing accounts -func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { - var ( - signer = types.HomesteadSigner{} - testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) - bankFunds = big.NewInt(100000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - testBankAddress: {Balance: bankFunds}, - common.HexToAddress("0xc0de"): { - Code: []byte{0x60, 0x01, 0x50}, - Balance: big.NewInt(0), - }, // push 1, pop - }, - GasLimit: 100e6, // 100 M - } - ) - // Generate the original common chain segment and the two competing forks - engine := ethash.NewFaker() - - blockGenerator := func(i int, block *BlockGen) { - block.SetCoinbase(common.Address{1}) - for txi := 0; txi < numTxs; txi++ { - uniq := uint64(i*numTxs + txi) - recipient := recipientFn(uniq) - tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, block.header.BaseFee, nil), signer, testBankKey) - if err != nil { - b.Error(err) - } - block.AddTx(tx) - } - } - - _, shared, _ := GenerateChainWithGenesis(gspec, engine, numBlocks, blockGenerator) - b.StopTimer() - b.ResetTimer() - for i := 0; i < b.N; i++ { - // Import the shared chain and the original canonical one - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - b.Fatalf("failed to create tester chain: %v", err) - } - b.StartTimer() - if _, err := chain.InsertChain(shared); err != nil { - b.Fatalf("failed to insert shared chain: %v", err) - } - b.StopTimer() - block := chain.GetBlockByHash(chain.CurrentBlock().Hash()) - if got := block.Transactions().Len(); got != numTxs*numBlocks { - b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) - } - } -} - -func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { - var ( - numTxs = 1000 - numBlocks = 1 - ) - recipientFn := func(nonce uint64) common.Address { - return common.BigToAddress(new(big.Int).SetUint64(1337 + nonce)) - } - dataFn := func(nonce uint64) []byte { - return nil - } - benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) -} - -func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { - var ( - numTxs = 1000 - numBlocks = 1 - ) - b.StopTimer() - b.ResetTimer() - - recipientFn := func(nonce uint64) common.Address { - return common.BigToAddress(new(big.Int).SetUint64(1337)) - } - dataFn := func(nonce uint64) []byte { - return nil - } - benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) -} - -func BenchmarkBlockChain_1x1000Executions(b *testing.B) { - var ( - numTxs = 1000 - numBlocks = 1 - ) - b.StopTimer() - b.ResetTimer() - - recipientFn := func(nonce uint64) common.Address { - return common.BigToAddress(new(big.Int).SetUint64(0xc0de)) - } - dataFn := func(nonce uint64) []byte { - return nil - } - benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) -} - -// Tests that importing a some old blocks, where all blocks are before the -// pruning point. -// This internally leads to a sidechain import, since the blocks trigger an -// ErrPrunedAncestor error. -// This may e.g. happen if -// 1. Downloader rollbacks a batch of inserted blocks and exits -// 2. Downloader starts to sync again -// 3. The blocks fetched are all known and canonical blocks -func TestSideImportPrunedBlocks(t *testing.T) { - testSideImportPrunedBlocks(t, rawdb.HashScheme) - testSideImportPrunedBlocks(t, rawdb.PathScheme) -} - -func testSideImportPrunedBlocks(t *testing.T, scheme string) { - // Generate a canonical chain to act as the main dataset - engine := ethash.NewFaker() - genesis := &Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - // Generate and import the canonical chain - _, blocks, _ := GenerateChainWithGenesis(genesis, engine, 2*TriesInMemory, nil) - - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), genesis, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - // In path-based trie database implementation, it will keep 128 diff + 1 disk - // layers, totally 129 latest states available. In hash-based it's 128. - states := TriesInMemory - if scheme == rawdb.PathScheme { - states = TriesInMemory + 1 - } - lastPrunedIndex := len(blocks) - states - 1 - lastPrunedBlock := blocks[lastPrunedIndex] - - // Verify pruning of lastPrunedBlock - if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { - t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) - } - firstNonPrunedBlock := blocks[len(blocks)-states] - // Verify firstNonPrunedBlock is not pruned - if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { - t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) - } - // Now re-import some old blocks - blockToReimport := blocks[5:8] - _, err = chain.InsertChain(blockToReimport) - if err != nil { - t.Errorf("Got error, %v", err) - } -} - -// TestDeleteCreateRevert tests a weird state transition corner case that we hit -// while changing the internals of statedb. The workflow is that a contract is -// self destructed, then in a followup transaction (but same block) it's created -// again and the transaction reverted. -// -// The original statedb implementation flushed dirty objects to the tries after -// each transaction, so this works ok. The rework accumulated writes in memory -// first, but the journal wiped the entire state object on create-revert. -func TestDeleteCreateRevert(t *testing.T) { - testDeleteCreateRevert(t, rawdb.HashScheme) - testDeleteCreateRevert(t, rawdb.PathScheme) -} - -func testDeleteCreateRevert(t *testing.T, scheme string) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(100000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xAAAAA selfdestructs if called - aa: { - // Code needs to just selfdestruct - Code: []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)}, - Nonce: 1, - Balance: big.NewInt(0), - }, - // The address 0xBBBB send 1 wei to 0xAAAA, then reverts - bb: { - Code: []byte{ - byte(vm.PC), // [0] - byte(vm.DUP1), // [0,0] - byte(vm.DUP1), // [0,0,0] - byte(vm.DUP1), // [0,0,0,0] - byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) - byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] - byte(vm.GAS), - byte(vm.CALL), - byte(vm.REVERT), - }, - Balance: big.NewInt(1), - }, - }, - } - ) - - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - // One transaction to AAAA - tx, _ := types.SignTx(types.NewTransaction(0, aa, - big.NewInt(0), 50000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - // One transaction to BBBB - tx, _ = types.SignTx(types.NewTransaction(1, bb, - big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } -} - -// TestDeleteRecreateSlots tests a state-transition that contains both deletion -// and recreation of contract state. -// Contract A exists, has slots 1 and 2 set -// Tx 1: Selfdestruct A -// Tx 2: Re-create A, set slots 3 and 4 -// Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, -// and then the new slots exist -func TestDeleteRecreateSlots(t *testing.T) { - testDeleteRecreateSlots(t, rawdb.HashScheme) - testDeleteRecreateSlots(t, rawdb.PathScheme) -} - -func testDeleteRecreateSlots(t *testing.T, scheme string) { - var ( - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") - aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA - aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) - ) - // Populate two slots - aaStorage[common.HexToHash("01")] = common.HexToHash("01") - aaStorage[common.HexToHash("02")] = common.HexToHash("02") - - // The bb-code needs to CREATE2 the aa contract. It consists of - // both initcode and deployment code - // initcode: - // 1. Set slots 3=3, 4=4, - // 2. Return aaCode - - initCode := []byte{ - byte(vm.PUSH1), 0x3, // value - byte(vm.PUSH1), 0x3, // location - byte(vm.SSTORE), // Set slot[3] = 3 - byte(vm.PUSH1), 0x4, // value - byte(vm.PUSH1), 0x4, // location - byte(vm.SSTORE), // Set slot[4] = 4 - // Slots are set, now return the code - byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack - byte(vm.PUSH1), 0x0, // memory start on stack - byte(vm.MSTORE), - // Code is now in memory. - byte(vm.PUSH1), 0x2, // size - byte(vm.PUSH1), byte(32 - 2), // offset - byte(vm.RETURN), - } - if l := len(initCode); l > 32 { - t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") - } - bbCode := []byte{ - // Push initcode onto stack - byte(vm.PUSH1) + byte(len(initCode)-1)} - bbCode = append(bbCode, initCode...) - bbCode = append(bbCode, []byte{ - byte(vm.PUSH1), 0x0, // memory start on stack - byte(vm.MSTORE), - byte(vm.PUSH1), 0x00, // salt - byte(vm.PUSH1), byte(len(initCode)), // size - byte(vm.PUSH1), byte(32 - len(initCode)), // offset - byte(vm.PUSH1), 0x00, // endowment - byte(vm.CREATE2), - }...) - - initHash := crypto.Keccak256Hash(initCode) - aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) - t.Logf("Destination address: %x\n", aa) - - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xAAAAA selfdestructs if called - aa: { - // Code needs to just selfdestruct - Code: aaCode, - Nonce: 1, - Balance: big.NewInt(0), - Storage: aaStorage, - }, - // The contract BB recreates AA - bb: { - Code: bbCode, - Balance: big.NewInt(1), - }, - }, - } - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - // One transaction to AA, to kill it - tx, _ := types.SignTx(types.NewTransaction(0, aa, - big.NewInt(0), 50000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - // One transaction to BB, to recreate AA - tx, _ = types.SignTx(types.NewTransaction(1, bb, - big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ - Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - statedb, _ := chain.State() - - // If all is correct, then slot 1 and 2 are zero - if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { - t.Errorf("got %x exp %x", got, exp) - } - if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { - t.Errorf("got %x exp %x", got, exp) - } - // Also, 3 and 4 should be set - if got, exp := statedb.GetState(aa, common.HexToHash("03")), common.HexToHash("03"); got != exp { - t.Fatalf("got %x exp %x", got, exp) - } - if got, exp := statedb.GetState(aa, common.HexToHash("04")), common.HexToHash("04"); got != exp { - t.Fatalf("got %x exp %x", got, exp) - } -} - -// TestDeleteRecreateAccount tests a state-transition that contains deletion of a -// contract with storage, and a recreate of the same contract via a -// regular value-transfer -// Expected outcome is that _all_ slots are cleared from A -func TestDeleteRecreateAccount(t *testing.T) { - testDeleteRecreateAccount(t, rawdb.HashScheme) - testDeleteRecreateAccount(t, rawdb.PathScheme) -} - -func testDeleteRecreateAccount(t *testing.T, scheme string) { - var ( - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - - aa = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f43") - aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA - aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) - ) - // Populate two slots - aaStorage[common.HexToHash("01")] = common.HexToHash("01") - aaStorage[common.HexToHash("02")] = common.HexToHash("02") - - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xAAAAA selfdestructs if called - aa: { - // Code needs to just selfdestruct - Code: aaCode, - Nonce: 1, - Balance: big.NewInt(0), - Storage: aaStorage, - }, - }, - } - - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - // One transaction to AA, to kill it - tx, _ := types.SignTx(types.NewTransaction(0, aa, - big.NewInt(0), 50000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - // One transaction to AA, to recreate it (but without storage - tx, _ = types.SignTx(types.NewTransaction(1, aa, - big.NewInt(1), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ - Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - statedb, _ := chain.State() - - // If all is correct, then both slots are zero - if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { - t.Errorf("got %x exp %x", got, exp) - } - if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { - t.Errorf("got %x exp %x", got, exp) - } -} - -// TestDeleteRecreateSlotsAcrossManyBlocks tests multiple state-transition that contains both deletion -// and recreation of contract state. -// Contract A exists, has slots 1 and 2 set -// Tx 1: Selfdestruct A -// Tx 2: Re-create A, set slots 3 and 4 -// Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, -// and then the new slots exist -func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { - testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.HashScheme) - testDeleteRecreateSlotsAcrossManyBlocks(t, rawdb.PathScheme) -} - -func testDeleteRecreateSlotsAcrossManyBlocks(t *testing.T, scheme string) { - var ( - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") - aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA - aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) - ) - // Populate two slots - aaStorage[common.HexToHash("01")] = common.HexToHash("01") - aaStorage[common.HexToHash("02")] = common.HexToHash("02") - - // The bb-code needs to CREATE2 the aa contract. It consists of - // both initcode and deployment code - // initcode: - // 1. Set slots 3=blocknum+1, 4=4, - // 2. Return aaCode - - initCode := []byte{ - byte(vm.PUSH1), 0x1, // - byte(vm.NUMBER), // value = number + 1 - byte(vm.ADD), // - byte(vm.PUSH1), 0x3, // location - byte(vm.SSTORE), // Set slot[3] = number + 1 - byte(vm.PUSH1), 0x4, // value - byte(vm.PUSH1), 0x4, // location - byte(vm.SSTORE), // Set slot[4] = 4 - // Slots are set, now return the code - byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack - byte(vm.PUSH1), 0x0, // memory start on stack - byte(vm.MSTORE), - // Code is now in memory. - byte(vm.PUSH1), 0x2, // size - byte(vm.PUSH1), byte(32 - 2), // offset - byte(vm.RETURN), - } - if l := len(initCode); l > 32 { - t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") - } - bbCode := []byte{ - // Push initcode onto stack - byte(vm.PUSH1) + byte(len(initCode)-1)} - bbCode = append(bbCode, initCode...) - bbCode = append(bbCode, []byte{ - byte(vm.PUSH1), 0x0, // memory start on stack - byte(vm.MSTORE), - byte(vm.PUSH1), 0x00, // salt - byte(vm.PUSH1), byte(len(initCode)), // size - byte(vm.PUSH1), byte(32 - len(initCode)), // offset - byte(vm.PUSH1), 0x00, // endowment - byte(vm.CREATE2), - }...) - - initHash := crypto.Keccak256Hash(initCode) - aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) - t.Logf("Destination address: %x\n", aa) - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xAAAAA selfdestructs if called - aa: { - // Code needs to just selfdestruct - Code: aaCode, - Nonce: 1, - Balance: big.NewInt(0), - Storage: aaStorage, - }, - // The contract BB recreates AA - bb: { - Code: bbCode, - Balance: big.NewInt(1), - }, - }, - } - var nonce uint64 - - type expectation struct { - exist bool - blocknum int - values map[int]int - } - var current = &expectation{ - exist: true, // exists in genesis - blocknum: 0, - values: map[int]int{1: 1, 2: 2}, - } - var expectations []*expectation - var newDestruct = func(e *expectation, b *BlockGen) *types.Transaction { - tx, _ := types.SignTx(types.NewTransaction(nonce, aa, - big.NewInt(0), 50000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - nonce++ - if e.exist { - e.exist = false - e.values = nil - } - //t.Logf("block %d; adding destruct\n", e.blocknum) - return tx - } - var newResurrect = func(e *expectation, b *BlockGen) *types.Transaction { - tx, _ := types.SignTx(types.NewTransaction(nonce, bb, - big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - nonce++ - if !e.exist { - e.exist = true - e.values = map[int]int{3: e.blocknum + 1, 4: 4} - } - //t.Logf("block %d; adding resurrect\n", e.blocknum) - return tx - } - - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 150, func(i int, b *BlockGen) { - var exp = new(expectation) - exp.blocknum = i + 1 - exp.values = make(map[int]int) - for k, v := range current.values { - exp.values[k] = v - } - exp.exist = current.exist - - b.SetCoinbase(common.Address{1}) - if i%2 == 0 { - b.AddTx(newDestruct(exp, b)) - } - if i%3 == 0 { - b.AddTx(newResurrect(exp, b)) - } - if i%5 == 0 { - b.AddTx(newDestruct(exp, b)) - } - if i%7 == 0 { - b.AddTx(newResurrect(exp, b)) - } - expectations = append(expectations, exp) - current = exp - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ - //Debug: true, - //Tracer: vm.NewJSONLogger(nil, os.Stdout), - }, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - var asHash = func(num int) common.Hash { - return common.BytesToHash([]byte{byte(num)}) - } - for i, block := range blocks { - blockNum := i + 1 - if n, err := chain.InsertChain([]*types.Block{block}); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - statedb, _ := chain.State() - // If all is correct, then slot 1 and 2 are zero - if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { - t.Errorf("block %d, got %x exp %x", blockNum, got, exp) - } - if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { - t.Errorf("block %d, got %x exp %x", blockNum, got, exp) - } - exp := expectations[i] - if exp.exist { - if !statedb.Exist(aa) { - t.Fatalf("block %d, expected %v to exist, it did not", blockNum, aa) - } - for slot, val := range exp.values { - if gotValue, expValue := statedb.GetState(aa, asHash(slot)), asHash(val); gotValue != expValue { - t.Fatalf("block %d, slot %d, got %x exp %x", blockNum, slot, gotValue, expValue) - } - } - } else { - if statedb.Exist(aa) { - t.Fatalf("block %d, expected %v to not exist, it did", blockNum, aa) - } - } - } -} - -// TestInitThenFailCreateContract tests a pretty notorious case that happened -// on mainnet over blocks 7338108, 7338110 and 7338115. -// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated -// with 0.001 ether (thus created but no code) -// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on -// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the -// deployment fails due to OOG during initcode execution -// - Block 7338115: another tx checks the balance of -// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as -// zero. -// -// The problem being that the snapshotter maintains a destructset, and adds items -// to the destructset in case something is created "onto" an existing item. -// We need to either roll back the snapDestructs, or not place it into snapDestructs -// in the first place. -// - -func TestInitThenFailCreateContract(t *testing.T) { - testInitThenFailCreateContract(t, rawdb.HashScheme) - testInitThenFailCreateContract(t, rawdb.PathScheme) -} - -func testInitThenFailCreateContract(t *testing.T, scheme string) { - var ( - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") - ) - - // The bb-code needs to CREATE2 the aa contract. It consists of - // both initcode and deployment code - // initcode: - // 1. If blocknum < 1, error out (e.g invalid opcode) - // 2. else, return a snippet of code - initCode := []byte{ - byte(vm.PUSH1), 0x1, // y (2) - byte(vm.NUMBER), // x (number) - byte(vm.GT), // x > y? - byte(vm.PUSH1), byte(0x8), - byte(vm.JUMPI), // jump to label if number > 2 - byte(0xFE), // illegal opcode - byte(vm.JUMPDEST), - byte(vm.PUSH1), 0x2, // size - byte(vm.PUSH1), 0x0, // offset - byte(vm.RETURN), // return 2 bytes of zero-code - } - if l := len(initCode); l > 32 { - t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") - } - bbCode := []byte{ - // Push initcode onto stack - byte(vm.PUSH1) + byte(len(initCode)-1)} - bbCode = append(bbCode, initCode...) - bbCode = append(bbCode, []byte{ - byte(vm.PUSH1), 0x0, // memory start on stack - byte(vm.MSTORE), - byte(vm.PUSH1), 0x00, // salt - byte(vm.PUSH1), byte(len(initCode)), // size - byte(vm.PUSH1), byte(32 - len(initCode)), // offset - byte(vm.PUSH1), 0x00, // endowment - byte(vm.CREATE2), - }...) - - initHash := crypto.Keccak256Hash(initCode) - aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) - t.Logf("Destination address: %x\n", aa) - - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address aa has some funds - aa: {Balance: big.NewInt(100000)}, - // The contract BB tries to create code onto AA - bb: { - Code: bbCode, - Balance: big.NewInt(1), - }, - }, - } - nonce := uint64(0) - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - // One transaction to BB - tx, _ := types.SignTx(types.NewTransaction(nonce, bb, - big.NewInt(0), 100000, b.header.BaseFee, nil), types.HomesteadSigner{}, key) - b.AddTx(tx) - nonce++ - }) - - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{ - //Debug: true, - //Tracer: vm.NewJSONLogger(nil, os.Stdout), - }, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - statedb, _ := chain.State() - if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 { - t.Fatalf("Genesis err, got %v exp %v", got, exp) - } - // First block tries to create, but fails - { - block := blocks[0] - if _, err := chain.InsertChain([]*types.Block{blocks[0]}); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) - } - statedb, _ = chain.State() - if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 { - t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) - } - } - // Import the rest of the blocks - for _, block := range blocks[1:] { - if _, err := chain.InsertChain([]*types.Block{block}); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) - } - } -} - -// TestEIP2718Transition tests that an EIP-2718 transaction will be accepted -// after the fork block has passed. This is verified by sending an EIP-2930 -// access list transaction, which specifies a single slot access, and then -// checking that the gas usage of a hot SLOAD and a cold SLOAD are calculated -// correctly. -func TestEIP2718Transition(t *testing.T) { - testEIP2718Transition(t, rawdb.HashScheme) - testEIP2718Transition(t, rawdb.PathScheme) -} - -func testEIP2718Transition(t *testing.T, scheme string) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xAAAA sloads 0x00 and 0x01 - aa: { - Code: []byte{ - byte(vm.PC), - byte(vm.PC), - byte(vm.SLOAD), - byte(vm.SLOAD), - }, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - ) - // Generate blocks - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - - // One transaction to 0xAAAA - signer := types.LatestSigner(gspec.Config) - tx, _ := types.SignNewTx(key, signer, &types.AccessListTx{ - ChainID: gspec.Config.ChainID, - Nonce: 0, - To: &aa, - Gas: 30000, - GasPrice: b.header.BaseFee, - AccessList: types.AccessList{{ - Address: aa, - StorageKeys: []common.Hash{{0}}, - }}, - }) - b.AddTx(tx) - }) - - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block := chain.GetBlockByNumber(1) - - // Expected gas is intrinsic + 2 * pc + hot load + cold load, since only one load is in the access list - expected := params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas + - vm.GasQuickStep*2 + params.WarmStorageReadCostEIP2929 + params.ColdSloadCostEIP2929 - if block.GasUsed() != expected { - t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expected, block.GasUsed()) - } -} - -// TestEIP1559Transition tests the following: -// -// 1. A transaction whose gasFeeCap is greater than the baseFee is valid. -// 2. Gas accounting for access lists on EIP-1559 transactions is correct. -// 3. Only the transaction's tip will be received by the coinbase. -// 4. The transaction sender pays for both the tip and baseFee. -// 5. The coinbase receives only the partially realized tip when -// gasFeeCap - gasTipCap < baseFee. -// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap). -func TestEIP1559Transition(t *testing.T) { - testEIP1559Transition(t, rawdb.HashScheme) - testEIP1559Transition(t, rawdb.PathScheme) -} - -func testEIP1559Transition(t *testing.T, scheme string) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) - config = *params.AllEthashProtocolChanges - gspec = &Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{ - addr1: {Balance: funds}, - addr2: {Balance: funds}, - // The address 0xAAAA sloads 0x00 and 0x01 - aa: { - Code: []byte{ - byte(vm.PC), - byte(vm.PC), - byte(vm.SLOAD), - byte(vm.SLOAD), - }, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - ) - - gspec.Config.BerlinBlock = common.Big0 - gspec.Config.LondonBlock = common.Big0 - signer := types.LatestSigner(gspec.Config) - - genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{1}) - - // One transaction to 0xAAAA - accesses := types.AccessList{types.AccessTuple{ - Address: aa, - StorageKeys: []common.Hash{{0}}, - }} - - txdata := &types.DynamicFeeTx{ - ChainID: gspec.Config.ChainID, - Nonce: 0, - To: &aa, - Gas: 30000, - GasFeeCap: newGwei(5), - GasTipCap: big.NewInt(2), - AccessList: accesses, - Data: []byte{}, - } - tx := types.NewTx(txdata) - tx, _ = types.SignTx(tx, signer, key1) - - b.AddTx(tx) - }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block := chain.GetBlockByNumber(1) - - // 1+2: Ensure EIP-1559 access lists are accounted for via gas usage. - expectedGas := params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas + - vm.GasQuickStep*2 + params.WarmStorageReadCostEIP2929 + params.ColdSloadCostEIP2929 - if block.GasUsed() != expectedGas { - t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed()) - } - - state, _ := chain.State() - - // 3: Ensure that miner received only the tx's tip. - actual := state.GetBalance(block.Coinbase()).ToBig() - expected := new(big.Int).Add( - new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()), - ethash.ConstantinopleBlockReward.ToBig(), - ) - if actual.Cmp(expected) != 0 { - t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) - } - - // 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee). - actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig()) - expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64())) - if actual.Cmp(expected) != 0 { - t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) - } - - blocks, _ = GenerateChain(gspec.Config, block, engine, genDb, 1, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{2}) - - txdata := &types.LegacyTx{ - Nonce: 0, - To: &aa, - Gas: 30000, - GasPrice: newGwei(5), - } - tx := types.NewTx(txdata) - tx, _ = types.SignTx(tx, signer, key2) - - b.AddTx(tx) - }) - - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block = chain.GetBlockByNumber(2) - state, _ = chain.State() - effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64() - - // 6+5: Ensure that miner received only the tx's effective tip. - actual = state.GetBalance(block.Coinbase()).ToBig() - expected = new(big.Int).Add( - new(big.Int).SetUint64(block.GasUsed()*effectiveTip), - ethash.ConstantinopleBlockReward.ToBig(), - ) - if actual.Cmp(expected) != 0 { - t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) - } - - // 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee). - actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig()) - expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64())) - if actual.Cmp(expected) != 0 { - t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) - } -} - -// Tests the scenario the chain is requested to another point with the missing state. -// It expects the state is recovered and all relevant chain markers are set correctly. -func TestSetCanonical(t *testing.T) { - testSetCanonical(t, rawdb.HashScheme) - testSetCanonical(t, rawdb.PathScheme) -} - -func testSetCanonical(t *testing.T, scheme string) { - //log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(100000000000000000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{address: {Balance: funds}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - signer = types.LatestSigner(gspec.Config) - engine = ethash.NewFaker() - ) - // Generate and import the canonical chain - _, canon, _ := GenerateChainWithGenesis(gspec, engine, 2*TriesInMemory, func(i int, gen *BlockGen) { - tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key) - if err != nil { - panic(err) - } - gen.AddTx(tx) - }) - diskdb, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false) - defer diskdb.Close() - - chain, err := NewBlockChain(diskdb, DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - - if n, err := chain.InsertChain(canon); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - // Generate the side chain and import them - _, side, _ := GenerateChainWithGenesis(gspec, engine, 2*TriesInMemory, func(i int, gen *BlockGen) { - tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1), params.TxGas, gen.header.BaseFee, nil), signer, key) - if err != nil { - panic(err) - } - gen.AddTx(tx) - }) - for _, block := range side { - err := chain.InsertBlockWithoutSetHead(block) - if err != nil { - t.Fatalf("Failed to insert into chain: %v", err) - } - } - for _, block := range side { - got := chain.GetBlockByHash(block.Hash()) - if got == nil { - t.Fatalf("Lost the inserted block") - } - } - - // Set the chain head to the side chain, ensure all the relevant markers are updated. - verify := func(head *types.Block) { - if chain.CurrentBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) - } - if chain.CurrentSnapBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) - } - if chain.CurrentHeader().Hash() != head.Hash() { - t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) - } - if !chain.HasState(head.Root()) { - t.Fatalf("Lost block state %v %x", head.Number(), head.Hash()) - } - } - chain.SetCanonical(side[len(side)-1]) - verify(side[len(side)-1]) - - // Reset the chain head to original chain - chain.SetCanonical(canon[TriesInMemory-1]) - verify(canon[TriesInMemory-1]) -} - -// TestCanonicalHashMarker tests all the canonical hash markers are updated/deleted -// correctly in case reorg is called. -func TestCanonicalHashMarker(t *testing.T) { - testCanonicalHashMarker(t, rawdb.HashScheme) - testCanonicalHashMarker(t, rawdb.PathScheme) -} - -func testCanonicalHashMarker(t *testing.T, scheme string) { - var cases = []struct { - forkA int - forkB int - }{ - // ForkA: 10 blocks - // ForkB: 1 blocks - // - // reorged: - // markers [2, 10] should be deleted - // markers [1] should be updated - {10, 1}, - - // ForkA: 10 blocks - // ForkB: 2 blocks - // - // reorged: - // markers [3, 10] should be deleted - // markers [1, 2] should be updated - {10, 2}, - - // ForkA: 10 blocks - // ForkB: 10 blocks - // - // reorged: - // markers [1, 10] should be updated - {10, 10}, - - // ForkA: 10 blocks - // ForkB: 11 blocks - // - // reorged: - // markers [1, 11] should be updated - {10, 11}, - } - for _, c := range cases { - var ( - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - engine = ethash.NewFaker() - ) - _, forkA, _ := GenerateChainWithGenesis(gspec, engine, c.forkA, func(i int, gen *BlockGen) {}) - _, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {}) - - // Initialize test chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - // Insert forkA and forkB, the canonical should on forkA still - if n, err := chain.InsertChain(forkA); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - if n, err := chain.InsertChain(forkB); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - verify := func(head *types.Block) { - if chain.CurrentBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) - } - if chain.CurrentSnapBlock().Hash() != head.Hash() { - t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) - } - if chain.CurrentHeader().Hash() != head.Hash() { - t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) - } - if !chain.HasState(head.Root()) { - t.Fatalf("Lost block state %v %x", head.Number(), head.Hash()) - } - } - - // Switch canonical chain to forkB if necessary - if len(forkA) < len(forkB) { - verify(forkB[len(forkB)-1]) - } else { - verify(forkA[len(forkA)-1]) - chain.SetCanonical(forkB[len(forkB)-1]) - verify(forkB[len(forkB)-1]) - } - - // Ensure all hash markers are updated correctly - for i := 0; i < len(forkB); i++ { - block := forkB[i] - hash := chain.GetCanonicalHash(block.NumberU64()) - if hash != block.Hash() { - t.Fatalf("Unexpected canonical hash %d", block.NumberU64()) - } - } - if c.forkA > c.forkB { - for i := uint64(c.forkB) + 1; i <= uint64(c.forkA); i++ { - hash := chain.GetCanonicalHash(i) - if hash != (common.Hash{}) { - t.Fatalf("Unexpected canonical hash %d", i) - } - } - } - chain.Stop() - } -} - -func TestCreateThenDeletePreByzantium(t *testing.T) { - // We use Ropsten chain config instead of Testchain config, this is - // deliberate: we want to use pre-byz rules where we have intermediate state roots - // between transactions. - testCreateThenDelete(t, ¶ms.ChainConfig{ - ChainID: big.NewInt(3), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(10), - EIP158Block: big.NewInt(10), - ByzantiumBlock: big.NewInt(1_700_000), - }) -} -func TestCreateThenDeletePostByzantium(t *testing.T) { - testCreateThenDelete(t, params.TestChainConfig) -} - -// testCreateThenDelete tests a creation and subsequent deletion of a contract, happening -// within the same block. -func testCreateThenDelete(t *testing.T, config *params.ChainConfig) { - var ( - engine = ethash.NewFaker() - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - destAddress = crypto.CreateAddress(address, 0) - funds = big.NewInt(1000000000000000) - ) - - // runtime code is 0x60ffff : PUSH1 0xFF SELFDESTRUCT, a.k.a SELFDESTRUCT(0xFF) - code := append([]byte{0x60, 0xff, 0xff}, make([]byte, 32-3)...) - initCode := []byte{ - // SSTORE 1:1 - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x1, - byte(vm.SSTORE), - // Get the runtime-code on the stack - byte(vm.PUSH32)} - initCode = append(initCode, code...) - initCode = append(initCode, []byte{ - byte(vm.PUSH1), 0x0, // offset - byte(vm.MSTORE), - byte(vm.PUSH1), 0x3, // size - byte(vm.PUSH1), 0x0, // offset - byte(vm.RETURN), // return 3 bytes of zero-code - }...) - gspec := &Genesis{ - Config: config, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - }, - } - nonce := uint64(0) - signer := types.HomesteadSigner{} - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2, func(i int, b *BlockGen) { - fee := big.NewInt(1) - if b.header.BaseFee != nil { - fee = b.header.BaseFee - } - b.SetCoinbase(common.Address{1}) - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 100000, - Data: initCode, - }) - nonce++ - b.AddTx(tx) - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 100000, - To: &destAddress, - }) - b.AddTx(tx) - nonce++ - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{ - //Debug: true, - //Tracer: logger.NewJSONLogger(nil, os.Stdout), - }, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - // Import the blocks - for _, block := range blocks { - if _, err := chain.InsertChain([]*types.Block{block}); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) - } - } -} - -func TestDeleteThenCreate(t *testing.T) { - var ( - engine = ethash.NewFaker() - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - factoryAddr = crypto.CreateAddress(address, 0) - funds = big.NewInt(1000000000000000) - ) - /* - contract Factory { - function deploy(bytes memory code) public { - address addr; - assembly { - addr := create2(0, add(code, 0x20), mload(code), 0) - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - } - } - */ - factoryBIN := common.Hex2Bytes("608060405234801561001057600080fd5b50610241806100206000396000f3fe608060405234801561001057600080fd5b506004361061002a5760003560e01c80627743601461002f575b600080fd5b610049600480360381019061004491906100d8565b61004b565b005b6000808251602084016000f59050803b61006457600080fd5b5050565b600061007b61007684610146565b610121565b905082815260208101848484011115610097576100966101eb565b5b6100a2848285610177565b509392505050565b600082601f8301126100bf576100be6101e6565b5b81356100cf848260208601610068565b91505092915050565b6000602082840312156100ee576100ed6101f5565b5b600082013567ffffffffffffffff81111561010c5761010b6101f0565b5b610118848285016100aa565b91505092915050565b600061012b61013c565b90506101378282610186565b919050565b6000604051905090565b600067ffffffffffffffff821115610161576101606101b7565b5b61016a826101fa565b9050602081019050919050565b82818337600083830152505050565b61018f826101fa565b810181811067ffffffffffffffff821117156101ae576101ad6101b7565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f830116905091905056fea2646970667358221220ea8b35ed310d03b6b3deef166941140b4d9e90ea2c92f6b41eb441daf49a59c364736f6c63430008070033") - - /* - contract C { - uint256 value; - constructor() { - value = 100; - } - function destruct() public payable { - selfdestruct(payable(msg.sender)); - } - receive() payable external {} - } - */ - contractABI := common.Hex2Bytes("6080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c63430008070033") - contractAddr := crypto.CreateAddress2(factoryAddr, [32]byte{}, crypto.Keccak256(contractABI)) - - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - }, - } - nonce := uint64(0) - signer := types.HomesteadSigner{} - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2, func(i int, b *BlockGen) { - fee := big.NewInt(1) - if b.header.BaseFee != nil { - fee = b.header.BaseFee - } - b.SetCoinbase(common.Address{1}) - - // Block 1 - if i == 0 { - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 500000, - Data: factoryBIN, - }) - nonce++ - b.AddTx(tx) - - data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000") - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 500000, - To: &factoryAddr, - Data: data, - }) - b.AddTx(tx) - nonce++ - } else { - // Block 2 - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 500000, - To: &contractAddr, - Data: common.Hex2Bytes("2b68b9c6"), // destruct - }) - nonce++ - b.AddTx(tx) - - data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000") - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 500000, - To: &factoryAddr, // re-creation - Data: data, - }) - b.AddTx(tx) - nonce++ - } - }) - // Import the canonical chain - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - for _, block := range blocks { - if _, err := chain.InsertChain([]*types.Block{block}); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) - } - } -} - -// TestTransientStorageReset ensures the transient storage is wiped correctly -// between transactions. -func TestTransientStorageReset(t *testing.T) { - var ( - engine = ethash.NewFaker() - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - destAddress = crypto.CreateAddress(address, 0) - funds = big.NewInt(1000000000000000) - vmConfig = vm.Config{ - ExtraEips: []int{1153}, // Enable transient storage EIP - } - ) - code := append([]byte{ - // TLoad value with location 1 - byte(vm.PUSH1), 0x1, - byte(vm.TLOAD), - - // PUSH location - byte(vm.PUSH1), 0x1, - - // SStore location:value - byte(vm.SSTORE), - }, make([]byte, 32-6)...) - initCode := []byte{ - // TSTORE 1:1 - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x1, - byte(vm.TSTORE), - - // Get the runtime-code on the stack - byte(vm.PUSH32)} - initCode = append(initCode, code...) - initCode = append(initCode, []byte{ - byte(vm.PUSH1), 0x0, // offset - byte(vm.MSTORE), - byte(vm.PUSH1), 0x6, // size - byte(vm.PUSH1), 0x0, // offset - byte(vm.RETURN), // return 6 bytes of zero-code - }...) - gspec := &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - }, - } - nonce := uint64(0) - signer := types.HomesteadSigner{} - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - fee := big.NewInt(1) - if b.header.BaseFee != nil { - fee = b.header.BaseFee - } - b.SetCoinbase(common.Address{1}) - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 100000, - Data: initCode, - }) - nonce++ - b.AddTxWithVMConfig(tx, vmConfig) - - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: nonce, - GasPrice: new(big.Int).Set(fee), - Gas: 100000, - To: &destAddress, - }) - b.AddTxWithVMConfig(tx, vmConfig) - nonce++ - }) - - // Initialize the blockchain with 1153 enabled. - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vmConfig, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - // Import the blocks - if _, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("failed to insert into chain: %v", err) - } - // Check the storage - state, err := chain.StateAt(chain.CurrentHeader().Root) - if err != nil { - t.Fatalf("Failed to load state %v", err) - } - loc := common.BytesToHash([]byte{1}) - slot := state.GetState(destAddress, loc) - if slot != (common.Hash{}) { - t.Fatalf("Unexpected dirty storage slot") - } -} - -func TestEIP3651(t *testing.T) { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") - engine = beacon.NewFaker() - - // A sender who makes transactions, has some funds - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether)) - config = *params.AllEthashProtocolChanges - gspec = &Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{ - addr1: {Balance: funds}, - addr2: {Balance: funds}, - // The address 0xAAAA sloads 0x00 and 0x01 - aa: { - Code: []byte{ - byte(vm.PC), - byte(vm.PC), - byte(vm.SLOAD), - byte(vm.SLOAD), - }, - Nonce: 0, - Balance: big.NewInt(0), - }, - // The address 0xBBBB calls 0xAAAA - bb: { - Code: []byte{ - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.PUSH2), // address - byte(0xaa), - byte(0xaa), - byte(vm.GAS), // gas - byte(vm.DELEGATECALL), - }, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - ) - - gspec.Config.BerlinBlock = common.Big0 - gspec.Config.LondonBlock = common.Big0 - gspec.Config.TerminalTotalDifficulty = common.Big0 - gspec.Config.TerminalTotalDifficultyPassed = true - gspec.Config.ShanghaiTime = u64(0) - signer := types.LatestSigner(gspec.Config) - - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { - b.SetCoinbase(aa) - // One transaction to Coinbase - txdata := &types.DynamicFeeTx{ - ChainID: gspec.Config.ChainID, - Nonce: 0, - To: &bb, - Gas: 500000, - GasFeeCap: newGwei(5), - GasTipCap: big.NewInt(2), - AccessList: nil, - Data: []byte{}, - } - tx := types.NewTx(txdata) - tx, _ = types.SignTx(tx, signer, key1) - - b.AddTx(tx) - }) - chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - defer chain.Stop() - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - - block := chain.GetBlockByNumber(1) - - // 1+2: Ensure EIP-1559 access lists are accounted for via gas usage. - innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2 - expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list - if block.GasUsed() != expectedGas { - t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed()) - } - - state, _ := chain.State() - - // 3: Ensure that miner received only the tx's tip. - actual := state.GetBalance(block.Coinbase()).ToBig() - expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64()) - if actual.Cmp(expected) != 0 { - t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) - } - - // 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee). - actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig()) - expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64())) - if actual.Cmp(expected) != 0 { - t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) - } -} diff --git a/builder/core/blocks.go b/builder/core/blocks.go deleted file mode 100644 index f20ba4aaf..000000000 --- a/builder/core/blocks.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 core - -import "github.com/ethereum/go-ethereum/common" - -// BadHashes represent a set of manually tracked bad hashes (usually hard forks) -var BadHashes = map[common.Hash]bool{ - common.HexToHash("05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689"): true, - common.HexToHash("7d05d08cbc596a2e5e4f13b80a743e53e09221b5323c3a61946b20873e58583f"): true, -} diff --git a/builder/core/bloom_indexer.go b/builder/core/bloom_indexer.go deleted file mode 100644 index 68a35d811..000000000 --- a/builder/core/bloom_indexer.go +++ /dev/null @@ -1,92 +0,0 @@ -// 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 core - -import ( - "context" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/bitutil" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" -) - -const ( - // bloomThrottling is the time to wait between processing two consecutive index - // sections. It's useful during chain upgrades to prevent disk overload. - bloomThrottling = 100 * time.Millisecond -) - -// BloomIndexer implements a core.ChainIndexer, building up a rotated bloom bits index -// for the Ethereum header bloom filters, permitting blazing fast filtering. -type BloomIndexer struct { - size uint64 // section size to generate bloombits for - db ethdb.Database // database instance to write index data and metadata into - gen *bloombits.Generator // generator to rotate the bloom bits crating the bloom index - section uint64 // Section is the section number being processed currently - head common.Hash // Head is the hash of the last header processed -} - -// NewBloomIndexer returns a chain indexer that generates bloom bits data for the -// canonical chain for fast logs filtering. -func NewBloomIndexer(db ethdb.Database, size, confirms uint64) *ChainIndexer { - backend := &BloomIndexer{ - db: db, - size: size, - } - table := rawdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) - - return NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits") -} - -// Reset implements core.ChainIndexerBackend, starting a new bloombits index -// section. -func (b *BloomIndexer) Reset(ctx context.Context, section uint64, lastSectionHead common.Hash) error { - gen, err := bloombits.NewGenerator(uint(b.size)) - b.gen, b.section, b.head = gen, section, common.Hash{} - return err -} - -// Process implements core.ChainIndexerBackend, adding a new header's bloom into -// the index. -func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error { - b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), header.Bloom) - b.head = header.Hash() - return nil -} - -// Commit implements core.ChainIndexerBackend, finalizing the bloom section and -// writing it out into the database. -func (b *BloomIndexer) Commit() error { - batch := b.db.NewBatchWithSize((int(b.size) / 8) * types.BloomBitLength) - for i := 0; i < types.BloomBitLength; i++ { - bits, err := b.gen.Bitset(uint(i)) - if err != nil { - return err - } - rawdb.WriteBloomBits(batch, uint(i), b.section, b.head, bitutil.CompressBytes(bits)) - } - return batch.Write() -} - -// Prune returns an empty error since we don't support pruning here. -func (b *BloomIndexer) Prune(threshold uint64) error { - return nil -} diff --git a/builder/core/bloombits/doc.go b/builder/core/bloombits/doc.go deleted file mode 100644 index 3d159e74f..000000000 --- a/builder/core/bloombits/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -// 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 bloombits implements bloom filtering on batches of data. -package bloombits diff --git a/builder/core/bloombits/generator.go b/builder/core/bloombits/generator.go deleted file mode 100644 index 646151db0..000000000 --- a/builder/core/bloombits/generator.go +++ /dev/null @@ -1,98 +0,0 @@ -// 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 bloombits - -import ( - "errors" - - "github.com/ethereum/go-ethereum/core/types" -) - -var ( - // errSectionOutOfBounds is returned if the user tried to add more bloom filters - // to the batch than available space, or if tries to retrieve above the capacity. - errSectionOutOfBounds = errors.New("section out of bounds") - - // errBloomBitOutOfBounds is returned if the user tried to retrieve specified - // bit bloom above the capacity. - errBloomBitOutOfBounds = errors.New("bloom bit out of bounds") -) - -// Generator takes a number of bloom filters and generates the rotated bloom bits -// to be used for batched filtering. -type Generator struct { - blooms [types.BloomBitLength][]byte // Rotated blooms for per-bit matching - sections uint // Number of sections to batch together - nextSec uint // Next section to set when adding a bloom -} - -// NewGenerator creates a rotated bloom generator that can iteratively fill a -// batched bloom filter's bits. -func NewGenerator(sections uint) (*Generator, error) { - if sections%8 != 0 { - return nil, errors.New("section count not multiple of 8") - } - b := &Generator{sections: sections} - for i := 0; i < types.BloomBitLength; i++ { - b.blooms[i] = make([]byte, sections/8) - } - return b, nil -} - -// AddBloom takes a single bloom filter and sets the corresponding bit column -// in memory accordingly. -func (b *Generator) AddBloom(index uint, bloom types.Bloom) error { - // Make sure we're not adding more bloom filters than our capacity - if b.nextSec >= b.sections { - return errSectionOutOfBounds - } - if b.nextSec != index { - return errors.New("bloom filter with unexpected index") - } - // Rotate the bloom and insert into our collection - byteIndex := b.nextSec / 8 - bitIndex := byte(7 - b.nextSec%8) - for byt := 0; byt < types.BloomByteLength; byt++ { - bloomByte := bloom[types.BloomByteLength-1-byt] - if bloomByte == 0 { - continue - } - base := 8 * byt - b.blooms[base+7][byteIndex] |= ((bloomByte >> 7) & 1) << bitIndex - b.blooms[base+6][byteIndex] |= ((bloomByte >> 6) & 1) << bitIndex - b.blooms[base+5][byteIndex] |= ((bloomByte >> 5) & 1) << bitIndex - b.blooms[base+4][byteIndex] |= ((bloomByte >> 4) & 1) << bitIndex - b.blooms[base+3][byteIndex] |= ((bloomByte >> 3) & 1) << bitIndex - b.blooms[base+2][byteIndex] |= ((bloomByte >> 2) & 1) << bitIndex - b.blooms[base+1][byteIndex] |= ((bloomByte >> 1) & 1) << bitIndex - b.blooms[base][byteIndex] |= (bloomByte & 1) << bitIndex - } - b.nextSec++ - return nil -} - -// Bitset returns the bit vector belonging to the given bit index after all -// blooms have been added. -func (b *Generator) Bitset(idx uint) ([]byte, error) { - if b.nextSec != b.sections { - return nil, errors.New("bloom not fully generated yet") - } - if idx >= types.BloomBitLength { - return nil, errBloomBitOutOfBounds - } - return b.blooms[idx], nil -} diff --git a/builder/core/bloombits/generator_test.go b/builder/core/bloombits/generator_test.go deleted file mode 100644 index ac1aee0b2..000000000 --- a/builder/core/bloombits/generator_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// 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 bloombits - -import ( - "bytes" - crand "crypto/rand" - "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/core/types" -) - -// Tests that batched bloom bits are correctly rotated from the input bloom -// filters. -func TestGenerator(t *testing.T) { - // Generate the input and the rotated output - var input, output [types.BloomBitLength][types.BloomByteLength]byte - - for i := 0; i < types.BloomBitLength; i++ { - for j := 0; j < types.BloomBitLength; j++ { - bit := byte(rand.Int() % 2) - - input[i][j/8] |= bit << byte(7-j%8) - output[types.BloomBitLength-1-j][i/8] |= bit << byte(7-i%8) - } - } - // Crunch the input through the generator and verify the result - gen, err := NewGenerator(types.BloomBitLength) - if err != nil { - t.Fatalf("failed to create bloombit generator: %v", err) - } - for i, bloom := range input { - if err := gen.AddBloom(uint(i), bloom); err != nil { - t.Fatalf("bloom %d: failed to add: %v", i, err) - } - } - for i, want := range output { - have, err := gen.Bitset(uint(i)) - if err != nil { - t.Fatalf("output %d: failed to retrieve bits: %v", i, err) - } - if !bytes.Equal(have, want[:]) { - t.Errorf("output %d: bit vector mismatch have %x, want %x", i, have, want) - } - } -} - -func BenchmarkGenerator(b *testing.B) { - var input [types.BloomBitLength][types.BloomByteLength]byte - b.Run("empty", func(b *testing.B) { - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - // Crunch the input through the generator and verify the result - gen, err := NewGenerator(types.BloomBitLength) - if err != nil { - b.Fatalf("failed to create bloombit generator: %v", err) - } - for j, bloom := range &input { - if err := gen.AddBloom(uint(j), bloom); err != nil { - b.Fatalf("bloom %d: failed to add: %v", i, err) - } - } - } - }) - for i := 0; i < types.BloomBitLength; i++ { - crand.Read(input[i][:]) - } - b.Run("random", func(b *testing.B) { - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - // Crunch the input through the generator and verify the result - gen, err := NewGenerator(types.BloomBitLength) - if err != nil { - b.Fatalf("failed to create bloombit generator: %v", err) - } - for j, bloom := range &input { - if err := gen.AddBloom(uint(j), bloom); err != nil { - b.Fatalf("bloom %d: failed to add: %v", i, err) - } - } - } - }) -} diff --git a/builder/core/bloombits/matcher.go b/builder/core/bloombits/matcher.go deleted file mode 100644 index 6a4cfb23d..000000000 --- a/builder/core/bloombits/matcher.go +++ /dev/null @@ -1,645 +0,0 @@ -// 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 bloombits - -import ( - "bytes" - "context" - "errors" - "math" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common/bitutil" - "github.com/ethereum/go-ethereum/crypto" -) - -// bloomIndexes represents the bit indexes inside the bloom filter that belong -// to some key. -type bloomIndexes [3]uint - -// calcBloomIndexes returns the bloom filter bit indexes belonging to the given key. -func calcBloomIndexes(b []byte) bloomIndexes { - b = crypto.Keccak256(b) - - var idxs bloomIndexes - for i := 0; i < len(idxs); i++ { - idxs[i] = (uint(b[2*i])<<8)&2047 + uint(b[2*i+1]) - } - return idxs -} - -// partialMatches with a non-nil vector represents a section in which some sub- -// matchers have already found potential matches. Subsequent sub-matchers will -// binary AND their matches with this vector. If vector is nil, it represents a -// section to be processed by the first sub-matcher. -type partialMatches struct { - section uint64 - bitset []byte -} - -// Retrieval represents a request for retrieval task assignments for a given -// bit with the given number of fetch elements, or a response for such a request. -// It can also have the actual results set to be used as a delivery data struct. -// -// The context and error fields are used by the light client to terminate matching -// early if an error is encountered on some path of the pipeline. -type Retrieval struct { - Bit uint - Sections []uint64 - Bitsets [][]byte - - Context context.Context - Error error -} - -// Matcher is a pipelined system of schedulers and logic matchers which perform -// binary AND/OR operations on the bit-streams, creating a stream of potential -// blocks to inspect for data content. -type Matcher struct { - sectionSize uint64 // Size of the data batches to filter on - - filters [][]bloomIndexes // Filter the system is matching for - schedulers map[uint]*scheduler // Retrieval schedulers for loading bloom bits - - retrievers chan chan uint // Retriever processes waiting for bit allocations - counters chan chan uint // Retriever processes waiting for task count reports - retrievals chan chan *Retrieval // Retriever processes waiting for task allocations - deliveries chan *Retrieval // Retriever processes waiting for task response deliveries - - running atomic.Bool // Atomic flag whether a session is live or not -} - -// NewMatcher creates a new pipeline for retrieving bloom bit streams and doing -// address and topic filtering on them. Setting a filter component to `nil` is -// allowed and will result in that filter rule being skipped (OR 0x11...1). -func NewMatcher(sectionSize uint64, filters [][][]byte) *Matcher { - // Create the matcher instance - m := &Matcher{ - sectionSize: sectionSize, - schedulers: make(map[uint]*scheduler), - retrievers: make(chan chan uint), - counters: make(chan chan uint), - retrievals: make(chan chan *Retrieval), - deliveries: make(chan *Retrieval), - } - // Calculate the bloom bit indexes for the groups we're interested in - m.filters = nil - - for _, filter := range filters { - // Gather the bit indexes of the filter rule, special casing the nil filter - if len(filter) == 0 { - continue - } - bloomBits := make([]bloomIndexes, len(filter)) - for i, clause := range filter { - if clause == nil { - bloomBits = nil - break - } - bloomBits[i] = calcBloomIndexes(clause) - } - // Accumulate the filter rules if no nil rule was within - if bloomBits != nil { - m.filters = append(m.filters, bloomBits) - } - } - // For every bit, create a scheduler to load/download the bit vectors - for _, bloomIndexLists := range m.filters { - for _, bloomIndexList := range bloomIndexLists { - for _, bloomIndex := range bloomIndexList { - m.addScheduler(bloomIndex) - } - } - } - return m -} - -// addScheduler adds a bit stream retrieval scheduler for the given bit index if -// it has not existed before. If the bit is already selected for filtering, the -// existing scheduler can be used. -func (m *Matcher) addScheduler(idx uint) { - if _, ok := m.schedulers[idx]; ok { - return - } - m.schedulers[idx] = newScheduler(idx) -} - -// Start starts the matching process and returns a stream of bloom matches in -// a given range of blocks. If there are no more matches in the range, the result -// channel is closed. -func (m *Matcher) Start(ctx context.Context, begin, end uint64, results chan uint64) (*MatcherSession, error) { - // Make sure we're not creating concurrent sessions - if m.running.Swap(true) { - return nil, errors.New("matcher already running") - } - defer m.running.Store(false) - - // Initiate a new matching round - session := &MatcherSession{ - matcher: m, - quit: make(chan struct{}), - ctx: ctx, - } - for _, scheduler := range m.schedulers { - scheduler.reset() - } - sink := m.run(begin, end, cap(results), session) - - // Read the output from the result sink and deliver to the user - session.pend.Add(1) - go func() { - defer session.pend.Done() - defer close(results) - - for { - select { - case <-session.quit: - return - - case res, ok := <-sink: - // New match result found - if !ok { - return - } - // Calculate the first and last blocks of the section - sectionStart := res.section * m.sectionSize - - first := sectionStart - if begin > first { - first = begin - } - last := sectionStart + m.sectionSize - 1 - if end < last { - last = end - } - // Iterate over all the blocks in the section and return the matching ones - for i := first; i <= last; i++ { - // Skip the entire byte if no matches are found inside (and we're processing an entire byte!) - next := res.bitset[(i-sectionStart)/8] - if next == 0 { - if i%8 == 0 { - i += 7 - } - continue - } - // Some bit it set, do the actual submatching - if bit := 7 - i%8; next&(1<= req.section }) - requests[req.bit] = append(queue[:index], append([]uint64{req.section}, queue[index:]...)...) - - // If it's a new bit and we have waiting fetchers, allocate to them - if len(queue) == 0 { - assign(req.bit) - } - - case fetcher := <-retrievers: - // New retriever arrived, find the lowest section-ed bit to assign - bit, best := uint(0), uint64(math.MaxUint64) - for idx := range unallocs { - if requests[idx][0] < best { - bit, best = idx, requests[idx][0] - } - } - // Stop tracking this bit (and alloc notifications if no more work is available) - delete(unallocs, bit) - if len(unallocs) == 0 { - retrievers = nil - } - allocs++ - fetcher <- bit - - case fetcher := <-m.counters: - // New task count request arrives, return number of items - fetcher <- uint(len(requests[<-fetcher])) - - case fetcher := <-m.retrievals: - // New fetcher waiting for tasks to retrieve, assign - task := <-fetcher - if want := len(task.Sections); want >= len(requests[task.Bit]) { - task.Sections = requests[task.Bit] - delete(requests, task.Bit) - } else { - task.Sections = append(task.Sections[:0], requests[task.Bit][:want]...) - requests[task.Bit] = append(requests[task.Bit][:0], requests[task.Bit][want:]...) - } - fetcher <- task - - // If anything was left unallocated, try to assign to someone else - if len(requests[task.Bit]) > 0 { - assign(task.Bit) - } - - case result := <-m.deliveries: - // New retrieval task response from fetcher, split out missing sections and - // deliver complete ones - var ( - sections = make([]uint64, 0, len(result.Sections)) - bitsets = make([][]byte, 0, len(result.Bitsets)) - missing = make([]uint64, 0, len(result.Sections)) - ) - for i, bitset := range result.Bitsets { - if len(bitset) == 0 { - missing = append(missing, result.Sections[i]) - continue - } - sections = append(sections, result.Sections[i]) - bitsets = append(bitsets, bitset) - } - m.schedulers[result.Bit].deliver(sections, bitsets) - allocs-- - - // Reschedule missing sections and allocate bit if newly available - if len(missing) > 0 { - queue := requests[result.Bit] - for _, section := range missing { - index := sort.Search(len(queue), func(i int) bool { return queue[i] >= section }) - queue = append(queue[:index], append([]uint64{section}, queue[index:]...)...) - } - requests[result.Bit] = queue - - if len(queue) == len(missing) { - assign(result.Bit) - } - } - - // End the session when all pending deliveries have arrived. - if shutdown == nil && allocs == 0 { - return - } - } - } -} - -// MatcherSession is returned by a started matcher to be used as a terminator -// for the actively running matching operation. -type MatcherSession struct { - matcher *Matcher - - closer sync.Once // Sync object to ensure we only ever close once - quit chan struct{} // Quit channel to request pipeline termination - - ctx context.Context // Context used by the light client to abort filtering - err error // Global error to track retrieval failures deep in the chain - errLock sync.Mutex - - pend sync.WaitGroup -} - -// Close stops the matching process and waits for all subprocesses to terminate -// before returning. The timeout may be used for graceful shutdown, allowing the -// currently running retrievals to complete before this time. -func (s *MatcherSession) Close() { - s.closer.Do(func() { - // Signal termination and wait for all goroutines to tear down - close(s.quit) - s.pend.Wait() - }) -} - -// Error returns any failure encountered during the matching session. -func (s *MatcherSession) Error() error { - s.errLock.Lock() - defer s.errLock.Unlock() - - return s.err -} - -// allocateRetrieval assigns a bloom bit index to a client process that can either -// immediately request and fetch the section contents assigned to this bit or wait -// a little while for more sections to be requested. -func (s *MatcherSession) allocateRetrieval() (uint, bool) { - fetcher := make(chan uint) - - select { - case <-s.quit: - return 0, false - case s.matcher.retrievers <- fetcher: - bit, ok := <-fetcher - return bit, ok - } -} - -// pendingSections returns the number of pending section retrievals belonging to -// the given bloom bit index. -func (s *MatcherSession) pendingSections(bit uint) int { - fetcher := make(chan uint) - - select { - case <-s.quit: - return 0 - case s.matcher.counters <- fetcher: - fetcher <- bit - return int(<-fetcher) - } -} - -// allocateSections assigns all or part of an already allocated bit-task queue -// to the requesting process. -func (s *MatcherSession) allocateSections(bit uint, count int) []uint64 { - fetcher := make(chan *Retrieval) - - select { - case <-s.quit: - return nil - case s.matcher.retrievals <- fetcher: - task := &Retrieval{ - Bit: bit, - Sections: make([]uint64, count), - } - fetcher <- task - return (<-fetcher).Sections - } -} - -// deliverSections delivers a batch of section bit-vectors for a specific bloom -// bit index to be injected into the processing pipeline. -func (s *MatcherSession) deliverSections(bit uint, sections []uint64, bitsets [][]byte) { - s.matcher.deliveries <- &Retrieval{Bit: bit, Sections: sections, Bitsets: bitsets} -} - -// Multiplex polls the matcher session for retrieval tasks and multiplexes it into -// the requested retrieval queue to be serviced together with other sessions. -// -// This method will block for the lifetime of the session. Even after termination -// of the session, any request in-flight need to be responded to! Empty responses -// are fine though in that case. -func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) { - for { - // Allocate a new bloom bit index to retrieve data for, stopping when done - bit, ok := s.allocateRetrieval() - if !ok { - return - } - // Bit allocated, throttle a bit if we're below our batch limit - if s.pendingSections(bit) < batch { - select { - case <-s.quit: - // Session terminating, we can't meaningfully service, abort - s.allocateSections(bit, 0) - s.deliverSections(bit, []uint64{}, [][]byte{}) - return - - case <-time.After(wait): - // Throttling up, fetch whatever is available - } - } - // Allocate as much as we can handle and request servicing - sections := s.allocateSections(bit, batch) - request := make(chan *Retrieval) - - select { - case <-s.quit: - // Session terminating, we can't meaningfully service, abort - s.deliverSections(bit, sections, make([][]byte, len(sections))) - return - - case mux <- request: - // Retrieval accepted, something must arrive before we're aborting - request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx} - - result := <-request - - // Deliver a result before s.Close() to avoid a deadlock - s.deliverSections(result.Bit, result.Sections, result.Bitsets) - - if result.Error != nil { - s.errLock.Lock() - s.err = result.Error - s.errLock.Unlock() - s.Close() - } - } - } -} diff --git a/builder/core/bloombits/matcher_test.go b/builder/core/bloombits/matcher_test.go deleted file mode 100644 index 7f3d5f279..000000000 --- a/builder/core/bloombits/matcher_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// 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 bloombits - -import ( - "context" - "math/rand" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" -) - -const testSectionSize = 4096 - -// Tests that wildcard filter rules (nil) can be specified and are handled well. -func TestMatcherWildcards(t *testing.T) { - t.Parallel() - matcher := NewMatcher(testSectionSize, [][][]byte{ - {common.Address{}.Bytes(), common.Address{0x01}.Bytes()}, // Default address is not a wildcard - {common.Hash{}.Bytes(), common.Hash{0x01}.Bytes()}, // Default hash is not a wildcard - {common.Hash{0x01}.Bytes()}, // Plain rule, sanity check - {common.Hash{0x01}.Bytes(), nil}, // Wildcard suffix, drop rule - {nil, common.Hash{0x01}.Bytes()}, // Wildcard prefix, drop rule - {nil, nil}, // Wildcard combo, drop rule - {}, // Inited wildcard rule, drop rule - nil, // Proper wildcard rule, drop rule - }) - if len(matcher.filters) != 3 { - t.Fatalf("filter system size mismatch: have %d, want %d", len(matcher.filters), 3) - } - if len(matcher.filters[0]) != 2 { - t.Fatalf("address clause size mismatch: have %d, want %d", len(matcher.filters[0]), 2) - } - if len(matcher.filters[1]) != 2 { - t.Fatalf("combo topic clause size mismatch: have %d, want %d", len(matcher.filters[1]), 2) - } - if len(matcher.filters[2]) != 1 { - t.Fatalf("singletone topic clause size mismatch: have %d, want %d", len(matcher.filters[2]), 1) - } -} - -// Tests the matcher pipeline on a single continuous workflow without interrupts. -func TestMatcherContinuous(t *testing.T) { - t.Parallel() - testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, false, 75) - testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, false, 81) - testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, false, 36) -} - -// Tests the matcher pipeline on a constantly interrupted and resumed work pattern -// with the aim of ensuring data items are requested only once. -func TestMatcherIntermittent(t *testing.T) { - t.Parallel() - testMatcherDiffBatches(t, [][]bloomIndexes{{{10, 20, 30}}}, 0, 100000, true, 75) - testMatcherDiffBatches(t, [][]bloomIndexes{{{32, 3125, 100}}, {{40, 50, 10}}}, 0, 100000, true, 81) - testMatcherDiffBatches(t, [][]bloomIndexes{{{4, 8, 11}, {7, 8, 17}}, {{9, 9, 12}, {15, 20, 13}}, {{18, 15, 15}, {12, 10, 4}}}, 0, 10000, true, 36) -} - -// Tests the matcher pipeline on random input to hopefully catch anomalies. -func TestMatcherRandom(t *testing.T) { - t.Parallel() - for i := 0; i < 10; i++ { - testMatcherBothModes(t, makeRandomIndexes([]int{1}, 50), 0, 10000, 0) - testMatcherBothModes(t, makeRandomIndexes([]int{3}, 50), 0, 10000, 0) - testMatcherBothModes(t, makeRandomIndexes([]int{2, 2, 2}, 20), 0, 10000, 0) - testMatcherBothModes(t, makeRandomIndexes([]int{5, 5, 5}, 50), 0, 10000, 0) - testMatcherBothModes(t, makeRandomIndexes([]int{4, 4, 4}, 20), 0, 10000, 0) - } -} - -// Tests that the matcher can properly find matches if the starting block is -// shifted from a multiple of 8. This is needed to cover an optimisation with -// bitset matching https://github.com/ethereum/go-ethereum/issues/15309. -func TestMatcherShifted(t *testing.T) { - t.Parallel() - // Block 0 always matches in the tests, skip ahead of first 8 blocks with the - // start to get a potential zero byte in the matcher bitset. - - // To keep the second bitset byte zero, the filter must only match for the first - // time in block 16, so doing an all-16 bit filter should suffice. - - // To keep the starting block non divisible by 8, block number 9 is the first - // that would introduce a shift and not match block 0. - testMatcherBothModes(t, [][]bloomIndexes{{{16, 16, 16}}}, 9, 64, 0) -} - -// Tests that matching on everything doesn't crash (special case internally). -func TestWildcardMatcher(t *testing.T) { - t.Parallel() - testMatcherBothModes(t, nil, 0, 10000, 0) -} - -// makeRandomIndexes generates a random filter system, composed of multiple filter -// criteria, each having one bloom list component for the address and arbitrarily -// many topic bloom list components. -func makeRandomIndexes(lengths []int, max int) [][]bloomIndexes { - res := make([][]bloomIndexes, len(lengths)) - for i, topics := range lengths { - res[i] = make([]bloomIndexes, topics) - for j := 0; j < topics; j++ { - for k := 0; k < len(res[i][j]); k++ { - res[i][j][k] = uint(rand.Intn(max-1) + 2) - } - } - } - return res -} - -// testMatcherDiffBatches runs the given matches test in single-delivery and also -// in batches delivery mode, verifying that all kinds of deliveries are handled -// correctly within. -func testMatcherDiffBatches(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32) { - singleton := testMatcher(t, filter, start, blocks, intermittent, retrievals, 1) - batched := testMatcher(t, filter, start, blocks, intermittent, retrievals, 16) - - if singleton != batched { - t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, %v in singleton vs. %v in batched mode", filter, blocks, intermittent, singleton, batched) - } -} - -// testMatcherBothModes runs the given matcher test in both continuous as well as -// in intermittent mode, verifying that the request counts match each other. -func testMatcherBothModes(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, retrievals uint32) { - continuous := testMatcher(t, filter, start, blocks, false, retrievals, 16) - intermittent := testMatcher(t, filter, start, blocks, true, retrievals, 16) - - if continuous != intermittent { - t.Errorf("filter = %v blocks = %v: request count mismatch, %v in continuous vs. %v in intermittent mode", filter, blocks, continuous, intermittent) - } -} - -// testMatcher is a generic tester to run the given matcher test and return the -// number of requests made for cross validation between different modes. -func testMatcher(t *testing.T, filter [][]bloomIndexes, start, blocks uint64, intermittent bool, retrievals uint32, maxReqCount int) uint32 { - // Create a new matcher an simulate our explicit random bitsets - matcher := NewMatcher(testSectionSize, nil) - matcher.filters = filter - - for _, rule := range filter { - for _, topic := range rule { - for _, bit := range topic { - matcher.addScheduler(bit) - } - } - } - // Track the number of retrieval requests made - var requested atomic.Uint32 - - // Start the matching session for the filter and the retriever goroutines - quit := make(chan struct{}) - matches := make(chan uint64, 16) - - session, err := matcher.Start(context.Background(), start, blocks-1, matches) - if err != nil { - t.Fatalf("failed to stat matcher session: %v", err) - } - startRetrievers(session, quit, &requested, maxReqCount) - - // Iterate over all the blocks and verify that the pipeline produces the correct matches - for i := start; i < blocks; i++ { - if expMatch3(filter, i) { - match, ok := <-matches - if !ok { - t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, results channel closed", filter, blocks, intermittent, i) - return 0 - } - if match != i { - t.Errorf("filter = %v blocks = %v intermittent = %v: expected #%v, got #%v", filter, blocks, intermittent, i, match) - } - // If we're testing intermittent mode, abort and restart the pipeline - if intermittent { - session.Close() - close(quit) - - quit = make(chan struct{}) - matches = make(chan uint64, 16) - - session, err = matcher.Start(context.Background(), i+1, blocks-1, matches) - if err != nil { - t.Fatalf("failed to stat matcher session: %v", err) - } - startRetrievers(session, quit, &requested, maxReqCount) - } - } - } - // Ensure the result channel is torn down after the last block - match, ok := <-matches - if ok { - t.Errorf("filter = %v blocks = %v intermittent = %v: expected closed channel, got #%v", filter, blocks, intermittent, match) - } - // Clean up the session and ensure we match the expected retrieval count - session.Close() - close(quit) - - if retrievals != 0 && requested.Load() != retrievals { - t.Errorf("filter = %v blocks = %v intermittent = %v: request count mismatch, have #%v, want #%v", filter, blocks, intermittent, requested.Load(), retrievals) - } - return requested.Load() -} - -// startRetrievers starts a batch of goroutines listening for section requests -// and serving them. -func startRetrievers(session *MatcherSession, quit chan struct{}, retrievals *atomic.Uint32, batch int) { - requests := make(chan chan *Retrieval) - - for i := 0; i < 10; i++ { - // Start a multiplexer to test multiple threaded execution - go session.Multiplex(batch, 100*time.Microsecond, requests) - - // Start a services to match the above multiplexer - go func() { - for { - // Wait for a service request or a shutdown - select { - case <-quit: - return - - case request := <-requests: - task := <-request - - task.Bitsets = make([][]byte, len(task.Sections)) - for i, section := range task.Sections { - if rand.Int()%4 != 0 { // Handle occasional missing deliveries - task.Bitsets[i] = generateBitset(task.Bit, section) - retrievals.Add(1) - } - } - request <- task - } - } - }() - } -} - -// generateBitset generates the rotated bitset for the given bloom bit and section -// numbers. -func generateBitset(bit uint, section uint64) []byte { - bitset := make([]byte, testSectionSize/8) - for i := 0; i < len(bitset); i++ { - for b := 0; b < 8; b++ { - blockIdx := section*testSectionSize + uint64(i*8+b) - bitset[i] += bitset[i] - if (blockIdx % uint64(bit)) == 0 { - bitset[i]++ - } - } - } - return bitset -} - -func expMatch1(filter bloomIndexes, i uint64) bool { - for _, ii := range filter { - if (i % uint64(ii)) != 0 { - return false - } - } - return true -} - -func expMatch2(filter []bloomIndexes, i uint64) bool { - for _, ii := range filter { - if expMatch1(ii, i) { - return true - } - } - return false -} - -func expMatch3(filter [][]bloomIndexes, i uint64) bool { - for _, ii := range filter { - if !expMatch2(ii, i) { - return false - } - } - return true -} diff --git a/builder/core/bloombits/scheduler.go b/builder/core/bloombits/scheduler.go deleted file mode 100644 index 6449c7465..000000000 --- a/builder/core/bloombits/scheduler.go +++ /dev/null @@ -1,181 +0,0 @@ -// 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 bloombits - -import ( - "sync" -) - -// request represents a bloom retrieval task to prioritize and pull from the local -// database or remotely from the network. -type request struct { - section uint64 // Section index to retrieve the a bit-vector from - bit uint // Bit index within the section to retrieve the vector of -} - -// response represents the state of a requested bit-vector through a scheduler. -type response struct { - cached []byte // Cached bits to dedup multiple requests - done chan struct{} // Channel to allow waiting for completion -} - -// scheduler handles the scheduling of bloom-filter retrieval operations for -// entire section-batches belonging to a single bloom bit. Beside scheduling the -// retrieval operations, this struct also deduplicates the requests and caches -// the results to minimize network/database overhead even in complex filtering -// scenarios. -type scheduler struct { - bit uint // Index of the bit in the bloom filter this scheduler is responsible for - responses map[uint64]*response // Currently pending retrieval requests or already cached responses - lock sync.Mutex // Lock protecting the responses from concurrent access -} - -// newScheduler creates a new bloom-filter retrieval scheduler for a specific -// bit index. -func newScheduler(idx uint) *scheduler { - return &scheduler{ - bit: idx, - responses: make(map[uint64]*response), - } -} - -// run creates a retrieval pipeline, receiving section indexes from sections and -// returning the results in the same order through the done channel. Concurrent -// runs of the same scheduler are allowed, leading to retrieval task deduplication. -func (s *scheduler) run(sections chan uint64, dist chan *request, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) { - // Create a forwarder channel between requests and responses of the same size as - // the distribution channel (since that will block the pipeline anyway). - pend := make(chan uint64, cap(dist)) - - // Start the pipeline schedulers to forward between user -> distributor -> user - wg.Add(2) - go s.scheduleRequests(sections, dist, pend, quit, wg) - go s.scheduleDeliveries(pend, done, quit, wg) -} - -// reset cleans up any leftovers from previous runs. This is required before a -// restart to ensure the no previously requested but never delivered state will -// cause a lockup. -func (s *scheduler) reset() { - s.lock.Lock() - defer s.lock.Unlock() - - for section, res := range s.responses { - if res.cached == nil { - delete(s.responses, section) - } - } -} - -// scheduleRequests reads section retrieval requests from the input channel, -// deduplicates the stream and pushes unique retrieval tasks into the distribution -// channel for a database or network layer to honour. -func (s *scheduler) scheduleRequests(reqs chan uint64, dist chan *request, pend chan uint64, quit chan struct{}, wg *sync.WaitGroup) { - // Clean up the goroutine and pipeline when done - defer wg.Done() - defer close(pend) - - // Keep reading and scheduling section requests - for { - select { - case <-quit: - return - - case section, ok := <-reqs: - // New section retrieval requested - if !ok { - return - } - // Deduplicate retrieval requests - unique := false - - s.lock.Lock() - if s.responses[section] == nil { - s.responses[section] = &response{ - done: make(chan struct{}), - } - unique = true - } - s.lock.Unlock() - - // Schedule the section for retrieval and notify the deliverer to expect this section - if unique { - select { - case <-quit: - return - case dist <- &request{bit: s.bit, section: section}: - } - } - select { - case <-quit: - return - case pend <- section: - } - } - } -} - -// scheduleDeliveries reads section acceptance notifications and waits for them -// to be delivered, pushing them into the output data buffer. -func (s *scheduler) scheduleDeliveries(pend chan uint64, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) { - // Clean up the goroutine and pipeline when done - defer wg.Done() - defer close(done) - - // Keep reading notifications and scheduling deliveries - for { - select { - case <-quit: - return - - case idx, ok := <-pend: - // New section retrieval pending - if !ok { - return - } - // Wait until the request is honoured - s.lock.Lock() - res := s.responses[idx] - s.lock.Unlock() - - select { - case <-quit: - return - case <-res.done: - } - // Deliver the result - select { - case <-quit: - return - case done <- res.cached: - } - } - } -} - -// deliver is called by the request distributor when a reply to a request arrives. -func (s *scheduler) deliver(sections []uint64, data [][]byte) { - s.lock.Lock() - defer s.lock.Unlock() - - for i, section := range sections { - if res := s.responses[section]; res != nil && res.cached == nil { // Avoid non-requests and double deliveries - res.cached = data[i] - close(res.done) - } - } -} diff --git a/builder/core/bloombits/scheduler_test.go b/builder/core/bloombits/scheduler_test.go deleted file mode 100644 index dcaaa9152..000000000 --- a/builder/core/bloombits/scheduler_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// 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 bloombits - -import ( - "bytes" - "math/big" - "sync" - "sync/atomic" - "testing" -) - -// Tests that the scheduler can deduplicate and forward retrieval requests to -// underlying fetchers and serve responses back, irrelevant of the concurrency -// of the requesting clients or serving data fetchers. -func TestSchedulerSingleClientSingleFetcher(t *testing.T) { testScheduler(t, 1, 1, 5000) } -func TestSchedulerSingleClientMultiFetcher(t *testing.T) { testScheduler(t, 1, 10, 5000) } -func TestSchedulerMultiClientSingleFetcher(t *testing.T) { testScheduler(t, 10, 1, 5000) } -func TestSchedulerMultiClientMultiFetcher(t *testing.T) { testScheduler(t, 10, 10, 5000) } - -func testScheduler(t *testing.T, clients int, fetchers int, requests int) { - t.Parallel() - f := newScheduler(0) - - // Create a batch of handler goroutines that respond to bloom bit requests and - // deliver them to the scheduler. - var fetchPend sync.WaitGroup - fetchPend.Add(fetchers) - defer fetchPend.Wait() - - fetch := make(chan *request, 16) - defer close(fetch) - - var delivered atomic.Uint32 - for i := 0; i < fetchers; i++ { - go func() { - defer fetchPend.Done() - - for req := range fetch { - delivered.Add(1) - - f.deliver([]uint64{ - req.section + uint64(requests), // Non-requested data (ensure it doesn't go out of bounds) - req.section, // Requested data - req.section, // Duplicated data (ensure it doesn't double close anything) - }, [][]byte{ - {}, - new(big.Int).SetUint64(req.section).Bytes(), - new(big.Int).SetUint64(req.section).Bytes(), - }) - } - }() - } - // Start a batch of goroutines to concurrently run scheduling tasks - quit := make(chan struct{}) - - var pend sync.WaitGroup - pend.Add(clients) - - for i := 0; i < clients; i++ { - go func() { - defer pend.Done() - - in := make(chan uint64, 16) - out := make(chan []byte, 16) - - f.run(in, fetch, out, quit, &pend) - - go func() { - for j := 0; j < requests; j++ { - in <- uint64(j) - } - close(in) - }() - b := new(big.Int) - for j := 0; j < requests; j++ { - bits := <-out - if want := b.SetUint64(uint64(j)).Bytes(); !bytes.Equal(bits, want) { - t.Errorf("vector %d: delivered content mismatch: have %x, want %x", j, bits, want) - } - } - }() - } - pend.Wait() - - if have := delivered.Load(); int(have) != requests { - t.Errorf("request count mismatch: have %v, want %v", have, requests) - } -} diff --git a/builder/core/chain_indexer.go b/builder/core/chain_indexer.go deleted file mode 100644 index f5fce7258..000000000 --- a/builder/core/chain_indexer.go +++ /dev/null @@ -1,523 +0,0 @@ -// 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 core - -import ( - "context" - "encoding/binary" - "errors" - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" -) - -// ChainIndexerBackend defines the methods needed to process chain segments in -// the background and write the segment results into the database. These can be -// used to create filter blooms or CHTs. -type ChainIndexerBackend interface { - // Reset initiates the processing of a new chain segment, potentially terminating - // any partially completed operations (in case of a reorg). - Reset(ctx context.Context, section uint64, prevHead common.Hash) error - - // Process crunches through the next header in the chain segment. The caller - // will ensure a sequential order of headers. - Process(ctx context.Context, header *types.Header) error - - // Commit finalizes the section metadata and stores it into the database. - Commit() error - - // Prune deletes the chain index older than the given threshold. - Prune(threshold uint64) error -} - -// ChainIndexerChain interface is used for connecting the indexer to a blockchain -type ChainIndexerChain interface { - // CurrentHeader retrieves the latest locally known header. - CurrentHeader() *types.Header - - // SubscribeChainHeadEvent subscribes to new head header notifications. - SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription -} - -// ChainIndexer does a post-processing job for equally sized sections of the -// canonical chain (like BlooomBits and CHT structures). A ChainIndexer is -// connected to the blockchain through the event system by starting a -// ChainHeadEventLoop in a goroutine. -// -// Further child ChainIndexers can be added which use the output of the parent -// section indexer. These child indexers receive new head notifications only -// after an entire section has been finished or in case of rollbacks that might -// affect already finished sections. -type ChainIndexer struct { - chainDb ethdb.Database // Chain database to index the data from - indexDb ethdb.Database // Prefixed table-view of the db to write index metadata into - backend ChainIndexerBackend // Background processor generating the index data content - children []*ChainIndexer // Child indexers to cascade chain updates to - - active atomic.Bool // Flag whether the event loop was started - update chan struct{} // Notification channel that headers should be processed - quit chan chan error // Quit channel to tear down running goroutines - ctx context.Context - ctxCancel func() - - sectionSize uint64 // Number of blocks in a single chain segment to process - confirmsReq uint64 // Number of confirmations before processing a completed segment - - storedSections uint64 // Number of sections successfully indexed into the database - knownSections uint64 // Number of sections known to be complete (block wise) - cascadedHead uint64 // Block number of the last completed section cascaded to subindexers - - checkpointSections uint64 // Number of sections covered by the checkpoint - checkpointHead common.Hash // Section head belonging to the checkpoint - - throttling time.Duration // Disk throttling to prevent a heavy upgrade from hogging resources - - log log.Logger - lock sync.Mutex -} - -// NewChainIndexer creates a new chain indexer to do background processing on -// chain segments of a given size after certain number of confirmations passed. -// The throttling parameter might be used to prevent database thrashing. -func NewChainIndexer(chainDb ethdb.Database, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer { - c := &ChainIndexer{ - chainDb: chainDb, - indexDb: indexDb, - backend: backend, - update: make(chan struct{}, 1), - quit: make(chan chan error), - sectionSize: section, - confirmsReq: confirm, - throttling: throttling, - log: log.New("type", kind), - } - // Initialize database dependent fields and start the updater - c.loadValidSections() - c.ctx, c.ctxCancel = context.WithCancel(context.Background()) - - go c.updateLoop() - - return c -} - -// AddCheckpoint adds a checkpoint. Sections are never processed and the chain -// is not expected to be available before this point. The indexer assumes that -// the backend has sufficient information available to process subsequent sections. -// -// Note: knownSections == 0 and storedSections == checkpointSections until -// syncing reaches the checkpoint -func (c *ChainIndexer) AddCheckpoint(section uint64, shead common.Hash) { - c.lock.Lock() - defer c.lock.Unlock() - - // Short circuit if the given checkpoint is below than local's. - if c.checkpointSections >= section+1 || section < c.storedSections { - return - } - c.checkpointSections = section + 1 - c.checkpointHead = shead - - c.setSectionHead(section, shead) - c.setValidSections(section + 1) -} - -// Start creates a goroutine to feed chain head events into the indexer for -// cascading background processing. Children do not need to be started, they -// are notified about new events by their parents. -func (c *ChainIndexer) Start(chain ChainIndexerChain) { - events := make(chan ChainHeadEvent, 10) - sub := chain.SubscribeChainHeadEvent(events) - - go c.eventLoop(chain.CurrentHeader(), events, sub) -} - -// Close tears down all goroutines belonging to the indexer and returns any error -// that might have occurred internally. -func (c *ChainIndexer) Close() error { - var errs []error - - c.ctxCancel() - - // Tear down the primary update loop - errc := make(chan error) - c.quit <- errc - if err := <-errc; err != nil { - errs = append(errs, err) - } - // If needed, tear down the secondary event loop - if c.active.Load() { - c.quit <- errc - if err := <-errc; err != nil { - errs = append(errs, err) - } - } - // Close all children - for _, child := range c.children { - if err := child.Close(); err != nil { - errs = append(errs, err) - } - } - // Return any failures - switch { - case len(errs) == 0: - return nil - - case len(errs) == 1: - return errs[0] - - default: - return fmt.Errorf("%v", errs) - } -} - -// eventLoop is a secondary - optional - event loop of the indexer which is only -// started for the outermost indexer to push chain head events into a processing -// queue. -func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainHeadEvent, sub event.Subscription) { - // Mark the chain indexer as active, requiring an additional teardown - c.active.Store(true) - - defer sub.Unsubscribe() - - // Fire the initial new head event to start any outstanding processing - c.newHead(currentHeader.Number.Uint64(), false) - - var ( - prevHeader = currentHeader - prevHash = currentHeader.Hash() - ) - for { - select { - case errc := <-c.quit: - // Chain indexer terminating, report no failure and abort - errc <- nil - return - - case ev, ok := <-events: - // Received a new event, ensure it's not nil (closing) and update - if !ok { - errc := <-c.quit - errc <- nil - return - } - header := ev.Block.Header() - if header.ParentHash != prevHash { - // Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then) - // TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly? - - if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash { - if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, header); h != nil { - c.newHead(h.Number.Uint64(), true) - } - } - } - c.newHead(header.Number.Uint64(), false) - - prevHeader, prevHash = header, header.Hash() - } - } -} - -// newHead notifies the indexer about new chain heads and/or reorgs. -func (c *ChainIndexer) newHead(head uint64, reorg bool) { - c.lock.Lock() - defer c.lock.Unlock() - - // If a reorg happened, invalidate all sections until that point - if reorg { - // Revert the known section number to the reorg point - known := (head + 1) / c.sectionSize - stored := known - if known < c.checkpointSections { - known = 0 - } - if stored < c.checkpointSections { - stored = c.checkpointSections - } - if known < c.knownSections { - c.knownSections = known - } - // Revert the stored sections from the database to the reorg point - if stored < c.storedSections { - c.setValidSections(stored) - } - // Update the new head number to the finalized section end and notify children - head = known * c.sectionSize - - if head < c.cascadedHead { - c.cascadedHead = head - for _, child := range c.children { - child.newHead(c.cascadedHead, true) - } - } - return - } - // No reorg, calculate the number of newly known sections and update if high enough - var sections uint64 - if head >= c.confirmsReq { - sections = (head + 1 - c.confirmsReq) / c.sectionSize - if sections < c.checkpointSections { - sections = 0 - } - if sections > c.knownSections { - if c.knownSections < c.checkpointSections { - // syncing reached the checkpoint, verify section head - syncedHead := rawdb.ReadCanonicalHash(c.chainDb, c.checkpointSections*c.sectionSize-1) - if syncedHead != c.checkpointHead { - c.log.Error("Synced chain does not match checkpoint", "number", c.checkpointSections*c.sectionSize-1, "expected", c.checkpointHead, "synced", syncedHead) - return - } - } - c.knownSections = sections - - select { - case c.update <- struct{}{}: - default: - } - } - } -} - -// updateLoop is the main event loop of the indexer which pushes chain segments -// down into the processing backend. -func (c *ChainIndexer) updateLoop() { - var ( - updating bool - updated time.Time - ) - - for { - select { - case errc := <-c.quit: - // Chain indexer terminating, report no failure and abort - errc <- nil - return - - case <-c.update: - // Section headers completed (or rolled back), update the index - c.lock.Lock() - if c.knownSections > c.storedSections { - // Periodically print an upgrade log message to the user - if time.Since(updated) > 8*time.Second { - if c.knownSections > c.storedSections+1 { - updating = true - c.log.Info("Upgrading chain index", "percentage", c.storedSections*100/c.knownSections) - } - updated = time.Now() - } - // Cache the current section count and head to allow unlocking the mutex - c.verifyLastHead() - section := c.storedSections - var oldHead common.Hash - if section > 0 { - oldHead = c.SectionHead(section - 1) - } - // Process the newly defined section in the background - c.lock.Unlock() - newHead, err := c.processSection(section, oldHead) - if err != nil { - select { - case <-c.ctx.Done(): - <-c.quit <- nil - return - default: - } - c.log.Error("Section processing failed", "error", err) - } - c.lock.Lock() - - // If processing succeeded and no reorgs occurred, mark the section completed - if err == nil && (section == 0 || oldHead == c.SectionHead(section-1)) { - c.setSectionHead(section, newHead) - c.setValidSections(section + 1) - if c.storedSections == c.knownSections && updating { - updating = false - c.log.Info("Finished upgrading chain index") - } - c.cascadedHead = c.storedSections*c.sectionSize - 1 - for _, child := range c.children { - c.log.Trace("Cascading chain index update", "head", c.cascadedHead) - child.newHead(c.cascadedHead, false) - } - } else { - // If processing failed, don't retry until further notification - c.log.Debug("Chain index processing failed", "section", section, "err", err) - c.verifyLastHead() - c.knownSections = c.storedSections - } - } - // If there are still further sections to process, reschedule - if c.knownSections > c.storedSections { - time.AfterFunc(c.throttling, func() { - select { - case c.update <- struct{}{}: - default: - } - }) - } - c.lock.Unlock() - } - } -} - -// processSection processes an entire section by calling backend functions while -// ensuring the continuity of the passed headers. Since the chain mutex is not -// held while processing, the continuity can be broken by a long reorg, in which -// case the function returns with an error. -func (c *ChainIndexer) processSection(section uint64, lastHead common.Hash) (common.Hash, error) { - c.log.Trace("Processing new chain section", "section", section) - - // Reset and partial processing - if err := c.backend.Reset(c.ctx, section, lastHead); err != nil { - c.setValidSections(0) - return common.Hash{}, err - } - - for number := section * c.sectionSize; number < (section+1)*c.sectionSize; number++ { - hash := rawdb.ReadCanonicalHash(c.chainDb, number) - if hash == (common.Hash{}) { - return common.Hash{}, fmt.Errorf("canonical block #%d unknown", number) - } - header := rawdb.ReadHeader(c.chainDb, hash, number) - if header == nil { - return common.Hash{}, fmt.Errorf("block #%d [%x..] not found", number, hash[:4]) - } else if header.ParentHash != lastHead { - return common.Hash{}, errors.New("chain reorged during section processing") - } - if err := c.backend.Process(c.ctx, header); err != nil { - return common.Hash{}, err - } - lastHead = header.Hash() - } - if err := c.backend.Commit(); err != nil { - return common.Hash{}, err - } - return lastHead, nil -} - -// verifyLastHead compares last stored section head with the corresponding block hash in the -// actual canonical chain and rolls back reorged sections if necessary to ensure that stored -// sections are all valid -func (c *ChainIndexer) verifyLastHead() { - for c.storedSections > 0 && c.storedSections > c.checkpointSections { - if c.SectionHead(c.storedSections-1) == rawdb.ReadCanonicalHash(c.chainDb, c.storedSections*c.sectionSize-1) { - return - } - c.setValidSections(c.storedSections - 1) - } -} - -// Sections returns the number of processed sections maintained by the indexer -// and also the information about the last header indexed for potential canonical -// verifications. -func (c *ChainIndexer) Sections() (uint64, uint64, common.Hash) { - c.lock.Lock() - defer c.lock.Unlock() - - c.verifyLastHead() - return c.storedSections, c.storedSections*c.sectionSize - 1, c.SectionHead(c.storedSections - 1) -} - -// AddChildIndexer adds a child ChainIndexer that can use the output of this one -func (c *ChainIndexer) AddChildIndexer(indexer *ChainIndexer) { - if indexer == c { - panic("can't add indexer as a child of itself") - } - c.lock.Lock() - defer c.lock.Unlock() - - c.children = append(c.children, indexer) - - // Cascade any pending updates to new children too - sections := c.storedSections - if c.knownSections < sections { - // if a section is "stored" but not "known" then it is a checkpoint without - // available chain data so we should not cascade it yet - sections = c.knownSections - } - if sections > 0 { - indexer.newHead(sections*c.sectionSize-1, false) - } -} - -// Prune deletes all chain data older than given threshold. -func (c *ChainIndexer) Prune(threshold uint64) error { - return c.backend.Prune(threshold) -} - -// loadValidSections reads the number of valid sections from the index database -// and caches is into the local state. -func (c *ChainIndexer) loadValidSections() { - data, _ := c.indexDb.Get([]byte("count")) - if len(data) == 8 { - c.storedSections = binary.BigEndian.Uint64(data) - } -} - -// setValidSections writes the number of valid sections to the index database -func (c *ChainIndexer) setValidSections(sections uint64) { - // Set the current number of valid sections in the database - var data [8]byte - binary.BigEndian.PutUint64(data[:], sections) - c.indexDb.Put([]byte("count"), data[:]) - - // Remove any reorged sections, caching the valids in the mean time - for c.storedSections > sections { - c.storedSections-- - c.removeSectionHead(c.storedSections) - } - c.storedSections = sections // needed if new > old -} - -// SectionHead retrieves the last block hash of a processed section from the -// index database. -func (c *ChainIndexer) SectionHead(section uint64) common.Hash { - var data [8]byte - binary.BigEndian.PutUint64(data[:], section) - - hash, _ := c.indexDb.Get(append([]byte("shead"), data[:]...)) - if len(hash) == len(common.Hash{}) { - return common.BytesToHash(hash) - } - return common.Hash{} -} - -// setSectionHead writes the last block hash of a processed section to the index -// database. -func (c *ChainIndexer) setSectionHead(section uint64, hash common.Hash) { - var data [8]byte - binary.BigEndian.PutUint64(data[:], section) - - c.indexDb.Put(append([]byte("shead"), data[:]...), hash.Bytes()) -} - -// removeSectionHead removes the reference to a processed section from the index -// database. -func (c *ChainIndexer) removeSectionHead(section uint64) { - var data [8]byte - binary.BigEndian.PutUint64(data[:], section) - - c.indexDb.Delete(append([]byte("shead"), data[:]...)) -} diff --git a/builder/core/chain_indexer_test.go b/builder/core/chain_indexer_test.go deleted file mode 100644 index f09960901..000000000 --- a/builder/core/chain_indexer_test.go +++ /dev/null @@ -1,246 +0,0 @@ -// 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 core - -import ( - "context" - "errors" - "fmt" - "math/big" - "math/rand" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" -) - -// Runs multiple tests with randomized parameters. -func TestChainIndexerSingle(t *testing.T) { - for i := 0; i < 10; i++ { - testChainIndexer(t, 1) - } -} - -// Runs multiple tests with randomized parameters and different number of -// chain backends. -func TestChainIndexerWithChildren(t *testing.T) { - for i := 2; i < 8; i++ { - testChainIndexer(t, i) - } -} - -// testChainIndexer runs a test with either a single chain indexer or a chain of -// multiple backends. The section size and required confirmation count parameters -// are randomized. -func testChainIndexer(t *testing.T, count int) { - db := rawdb.NewMemoryDatabase() - defer db.Close() - - // Create a chain of indexers and ensure they all report empty - backends := make([]*testChainIndexBackend, count) - for i := 0; i < count; i++ { - var ( - sectionSize = uint64(rand.Intn(100) + 1) - confirmsReq = uint64(rand.Intn(10)) - ) - backends[i] = &testChainIndexBackend{t: t, processCh: make(chan uint64)} - backends[i].indexer = NewChainIndexer(db, rawdb.NewTable(db, string([]byte{byte(i)})), backends[i], sectionSize, confirmsReq, 0, fmt.Sprintf("indexer-%d", i)) - - if sections, _, _ := backends[i].indexer.Sections(); sections != 0 { - t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, 0) - } - if i > 0 { - backends[i-1].indexer.AddChildIndexer(backends[i].indexer) - } - } - defer backends[0].indexer.Close() // parent indexer shuts down children - // notify pings the root indexer about a new head or reorg, then expect - // processed blocks if a section is processable - notify := func(headNum, failNum uint64, reorg bool) { - backends[0].indexer.newHead(headNum, reorg) - if reorg { - for _, backend := range backends { - headNum = backend.reorg(headNum) - backend.assertSections() - } - return - } - var cascade bool - for _, backend := range backends { - headNum, cascade = backend.assertBlocks(headNum, failNum) - if !cascade { - break - } - backend.assertSections() - } - } - // inject inserts a new random canonical header into the database directly - inject := func(number uint64) { - header := &types.Header{Number: big.NewInt(int64(number)), Extra: big.NewInt(rand.Int63()).Bytes()} - if number > 0 { - header.ParentHash = rawdb.ReadCanonicalHash(db, number-1) - } - rawdb.WriteHeader(db, header) - rawdb.WriteCanonicalHash(db, header.Hash(), number) - } - // Start indexer with an already existing chain - for i := uint64(0); i <= 100; i++ { - inject(i) - } - notify(100, 100, false) - - // Add new blocks one by one - for i := uint64(101); i <= 1000; i++ { - inject(i) - notify(i, i, false) - } - // Do a reorg - notify(500, 500, true) - - // Create new fork - for i := uint64(501); i <= 1000; i++ { - inject(i) - notify(i, i, false) - } - for i := uint64(1001); i <= 1500; i++ { - inject(i) - } - // Failed processing scenario where less blocks are available than notified - notify(2000, 1500, false) - - // Notify about a reorg (which could have caused the missing blocks if happened during processing) - notify(1500, 1500, true) - - // Create new fork - for i := uint64(1501); i <= 2000; i++ { - inject(i) - notify(i, i, false) - } -} - -// testChainIndexBackend implements ChainIndexerBackend -type testChainIndexBackend struct { - t *testing.T - indexer *ChainIndexer - section, headerCnt, stored uint64 - processCh chan uint64 -} - -// assertSections verifies if a chain indexer has the correct number of section. -func (b *testChainIndexBackend) assertSections() { - // Keep trying for 3 seconds if it does not match - var sections uint64 - for i := 0; i < 300; i++ { - sections, _, _ = b.indexer.Sections() - if sections == b.stored { - return - } - time.Sleep(10 * time.Millisecond) - } - b.t.Fatalf("Canonical section count mismatch: have %v, want %v", sections, b.stored) -} - -// assertBlocks expects processing calls after new blocks have arrived. If the -// failNum < headNum then we are simulating a scenario where a reorg has happened -// after the processing has started and the processing of a section fails. -func (b *testChainIndexBackend) assertBlocks(headNum, failNum uint64) (uint64, bool) { - var sections uint64 - if headNum >= b.indexer.confirmsReq { - sections = (headNum + 1 - b.indexer.confirmsReq) / b.indexer.sectionSize - if sections > b.stored { - // expect processed blocks - for expectd := b.stored * b.indexer.sectionSize; expectd < sections*b.indexer.sectionSize; expectd++ { - if expectd > failNum { - // rolled back after processing started, no more process calls expected - // wait until updating is done to make sure that processing actually fails - var updating bool - for i := 0; i < 300; i++ { - b.indexer.lock.Lock() - updating = b.indexer.knownSections > b.indexer.storedSections - b.indexer.lock.Unlock() - if !updating { - break - } - time.Sleep(10 * time.Millisecond) - } - if updating { - b.t.Fatalf("update did not finish") - } - sections = expectd / b.indexer.sectionSize - break - } - select { - case <-time.After(10 * time.Second): - b.t.Fatalf("Expected processed block #%d, got nothing", expectd) - case processed := <-b.processCh: - if processed != expectd { - b.t.Errorf("Expected processed block #%d, got #%d", expectd, processed) - } - } - } - b.stored = sections - } - } - if b.stored == 0 { - return 0, false - } - return b.stored*b.indexer.sectionSize - 1, true -} - -func (b *testChainIndexBackend) reorg(headNum uint64) uint64 { - firstChanged := (headNum + 1) / b.indexer.sectionSize - if firstChanged < b.stored { - b.stored = firstChanged - } - return b.stored * b.indexer.sectionSize -} - -func (b *testChainIndexBackend) Reset(ctx context.Context, section uint64, prevHead common.Hash) error { - b.section = section - b.headerCnt = 0 - return nil -} - -func (b *testChainIndexBackend) Process(ctx context.Context, header *types.Header) error { - b.headerCnt++ - if b.headerCnt > b.indexer.sectionSize { - b.t.Error("Processing too many headers") - } - //t.processCh <- header.Number.Uint64() - select { - case <-time.After(10 * time.Second): - b.t.Error("Unexpected call to Process") - // Can't use Fatal since this is not the test's goroutine. - // Returning error stops the chainIndexer's updateLoop - return errors.New("Unexpected call to Process") - case b.processCh <- header.Number.Uint64(): - } - return nil -} - -func (b *testChainIndexBackend) Commit() error { - if b.headerCnt != b.indexer.sectionSize { - b.t.Error("Not enough headers processed") - } - return nil -} - -func (b *testChainIndexBackend) Prune(threshold uint64) error { - return nil -} diff --git a/builder/core/chain_makers.go b/builder/core/chain_makers.go deleted file mode 100644 index 06bbfd6cf..000000000 --- a/builder/core/chain_makers.go +++ /dev/null @@ -1,574 +0,0 @@ -// 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 core - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" - "github.com/holiman/uint256" -) - -// BlockGen creates blocks for testing. -// See GenerateChain for a detailed explanation. -type BlockGen struct { - i int - cm *chainMaker - parent *types.Block - header *types.Header - statedb *state.StateDB - - gasPool *GasPool - txs []*types.Transaction - receipts []*types.Receipt - uncles []*types.Header - withdrawals []*types.Withdrawal - - engine consensus.Engine -} - -// SetCoinbase sets the coinbase of the generated block. -// It can be called at most once. -func (b *BlockGen) SetCoinbase(addr common.Address) { - if b.gasPool != nil { - if len(b.txs) > 0 { - panic("coinbase must be set before adding transactions") - } - panic("coinbase can only be set once") - } - b.header.Coinbase = addr - b.gasPool = new(GasPool).AddGas(b.header.GasLimit) -} - -// SetExtra sets the extra data field of the generated block. -func (b *BlockGen) SetExtra(data []byte) { - b.header.Extra = data -} - -// SetNonce sets the nonce field of the generated block. -func (b *BlockGen) SetNonce(nonce types.BlockNonce) { - b.header.Nonce = nonce -} - -// SetDifficulty sets the difficulty field of the generated block. This method is -// useful for Clique tests where the difficulty does not depend on time. For the -// ethash tests, please use OffsetTime, which implicitly recalculates the diff. -func (b *BlockGen) SetDifficulty(diff *big.Int) { - b.header.Difficulty = diff -} - -// SetPoS makes the header a PoS-header (0 difficulty) -func (b *BlockGen) SetPoS() { - b.header.Difficulty = new(big.Int) -} - -// Difficulty returns the currently calculated difficulty of the block. -func (b *BlockGen) Difficulty() *big.Int { - return new(big.Int).Set(b.header.Difficulty) -} - -// SetParentBeaconRoot sets the parent beacon root field of the generated -// block. -func (b *BlockGen) SetParentBeaconRoot(root common.Hash) { - b.header.ParentBeaconRoot = &root - var ( - blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) - vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{}) - ) - ProcessBeaconBlockRoot(root, vmenv, b.statedb) -} - -// addTx adds a transaction to the generated block. If no coinbase has -// been set, the block's coinbase is set to the zero address. -// -// There are a few options can be passed as well in order to run some -// customized rules. -// - bc: enables the ability to query historical block hashes for BLOCKHASH -// - vmConfig: extends the flexibility for customizing evm rules, e.g. enable extra EIPs -func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transaction) { - if b.gasPool == nil { - b.SetCoinbase(common.Address{}) - } - b.statedb.SetTxContext(tx.Hash(), len(b.txs)) - receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, nil) - if err != nil { - panic(err) - } - b.txs = append(b.txs, tx) - b.receipts = append(b.receipts, receipt) - if b.header.BlobGasUsed != nil { - *b.header.BlobGasUsed += receipt.BlobGasUsed - } -} - -// AddTx adds a transaction to the generated block. If no coinbase has -// been set, the block's coinbase is set to the zero address. -// -// AddTx panics if the transaction cannot be executed. In addition to the protocol-imposed -// limitations (gas limit, etc.), there are some further limitations on the content of -// transactions that can be added. Notably, contract code relying on the BLOCKHASH -// instruction will panic during execution if it attempts to access a block number outside -// of the range created by GenerateChain. -func (b *BlockGen) AddTx(tx *types.Transaction) { - b.addTx(nil, vm.Config{}, tx) -} - -// AddTxWithChain adds a transaction to the generated block. If no coinbase has -// been set, the block's coinbase is set to the zero address. -// -// AddTxWithChain panics if the transaction cannot be executed. In addition to the -// protocol-imposed limitations (gas limit, etc.), there are some further limitations on -// the content of transactions that can be added. If contract code relies on the BLOCKHASH -// instruction, the block in chain will be returned. -func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { - b.addTx(bc, vm.Config{}, tx) -} - -// AddTxWithVMConfig adds a transaction to the generated block. If no coinbase has -// been set, the block's coinbase is set to the zero address. -// The evm interpreter can be customized with the provided vm config. -func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) { - b.addTx(nil, config, tx) -} - -// GetBalance returns the balance of the given address at the generated block. -func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int { - return b.statedb.GetBalance(addr) -} - -// AddUncheckedTx forcefully adds a transaction to the block without any validation. -// -// AddUncheckedTx will cause consensus failures when used during real -// chain processing. This is best used in conjunction with raw block insertion. -func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) { - b.txs = append(b.txs, tx) -} - -// Number returns the block number of the block being generated. -func (b *BlockGen) Number() *big.Int { - return new(big.Int).Set(b.header.Number) -} - -// Timestamp returns the timestamp of the block being generated. -func (b *BlockGen) Timestamp() uint64 { - return b.header.Time -} - -// BaseFee returns the EIP-1559 base fee of the block being generated. -func (b *BlockGen) BaseFee() *big.Int { - return new(big.Int).Set(b.header.BaseFee) -} - -// Gas returns the amount of gas left in the current block. -func (b *BlockGen) Gas() uint64 { - return b.header.GasLimit - b.header.GasUsed -} - -// Signer returns a valid signer instance for the current block. -func (b *BlockGen) Signer() types.Signer { - return types.MakeSigner(b.cm.config, b.header.Number, b.header.Time) -} - -// AddUncheckedReceipt forcefully adds a receipts to the block without a -// backing transaction. -// -// AddUncheckedReceipt will cause consensus failures when used during real -// chain processing. This is best used in conjunction with raw block insertion. -func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) { - b.receipts = append(b.receipts, receipt) -} - -// TxNonce returns the next valid transaction nonce for the -// account at addr. It panics if the account does not exist. -func (b *BlockGen) TxNonce(addr common.Address) uint64 { - if !b.statedb.Exist(addr) { - panic("account does not exist") - } - return b.statedb.GetNonce(addr) -} - -// AddUncle adds an uncle header to the generated block. -func (b *BlockGen) AddUncle(h *types.Header) { - // The uncle will have the same timestamp and auto-generated difficulty - h.Time = b.header.Time - - var parent *types.Header - for i := b.i - 1; i >= 0; i-- { - if b.cm.chain[i].Hash() == h.ParentHash { - parent = b.cm.chain[i].Header() - break - } - } - h.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, parent) - - // The gas limit and price should be derived from the parent - h.GasLimit = parent.GasLimit - if b.cm.config.IsLondon(h.Number) { - h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent) - if !b.cm.config.IsLondon(parent.Number) { - parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier() - h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) - } - } - b.uncles = append(b.uncles, h) -} - -// AddWithdrawal adds a withdrawal to the generated block. -// It returns the withdrawal index. -func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 { - cpy := *w - cpy.Index = b.nextWithdrawalIndex() - b.withdrawals = append(b.withdrawals, &cpy) - return cpy.Index -} - -// nextWithdrawalIndex computes the index of the next withdrawal. -func (b *BlockGen) nextWithdrawalIndex() uint64 { - if len(b.withdrawals) != 0 { - return b.withdrawals[len(b.withdrawals)-1].Index + 1 - } - for i := b.i - 1; i >= 0; i-- { - if wd := b.cm.chain[i].Withdrawals(); len(wd) != 0 { - return wd[len(wd)-1].Index + 1 - } - if i == 0 { - // Correctly set the index if no parent had withdrawals. - if wd := b.cm.bottom.Withdrawals(); len(wd) != 0 { - return wd[len(wd)-1].Index + 1 - } - } - } - return 0 -} - -// PrevBlock returns a previously generated block by number. It panics if -// num is greater or equal to the number of the block being generated. -// For index -1, PrevBlock returns the parent block given to GenerateChain. -func (b *BlockGen) PrevBlock(index int) *types.Block { - if index >= b.i { - panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i)) - } - if index == -1 { - return b.cm.bottom - } - return b.cm.chain[index] -} - -// OffsetTime modifies the time instance of a block, implicitly changing its -// associated difficulty. It's useful to test scenarios where forking is not -// tied to chain length directly. -func (b *BlockGen) OffsetTime(seconds int64) { - b.header.Time += uint64(seconds) - if b.header.Time <= b.cm.bottom.Header().Time { - panic("block time out of range") - } - b.header.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, b.parent.Header()) -} - -// GenerateChain creates a chain of n blocks. The first block's -// parent will be the provided parent. db is used to store -// intermediate states and should contain the parent's state trie. -// -// The generator function is called with a new block generator for -// every block. Any transactions and uncles added to the generator -// become part of the block. If gen is nil, the blocks will be empty -// and their coinbase will be the zero address. -// -// Blocks created by GenerateChain do not contain valid proof of work -// values. Inserting them into BlockChain requires use of FakePow or -// a similar non-validating proof of work implementation. -func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { - if config == nil { - config = params.TestChainConfig - } - if engine == nil { - panic("nil consensus engine") - } - cm := newChainMaker(parent, config, engine) - - genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) { - b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine} - b.header = cm.makeHeader(parent, statedb, b.engine) - - // Set the difficulty for clique block. The chain maker doesn't have access - // to a chain, so the difficulty will be left unset (nil). Set it here to the - // correct value. - if b.header.Difficulty == nil { - if config.TerminalTotalDifficulty == nil { - // Clique chain - b.header.Difficulty = big.NewInt(2) - } else { - // Post-merge chain - b.header.Difficulty = big.NewInt(0) - } - } - // Mutate the state and block according to any hard-fork specs - if daoBlock := config.DAOForkBlock; daoBlock != nil { - limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) - if b.header.Number.Cmp(daoBlock) >= 0 && b.header.Number.Cmp(limit) < 0 { - if config.DAOForkSupport { - b.header.Extra = common.CopyBytes(params.DAOForkBlockExtra) - } - } - } - if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 { - misc.ApplyDAOHardFork(statedb) - } - // Execute any user modifications to the block - if gen != nil { - gen(i, b) - } - - block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals) - if err != nil { - panic(err) - } - - // Write state changes to db - root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number)) - if err != nil { - panic(fmt.Sprintf("state write error: %v", err)) - } - if err = triedb.Commit(root, false); err != nil { - panic(fmt.Sprintf("trie write error: %v", err)) - } - return block, b.receipts - } - - // Forcibly use hash-based state scheme for retaining all nodes in disk. - triedb := triedb.NewDatabase(db, triedb.HashDefaults) - defer triedb.Close() - - for i := 0; i < n; i++ { - statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil) - if err != nil { - panic(err) - } - block, receipts := genblock(i, parent, triedb, statedb) - - // Post-process the receipts. - // Here we assign the final block hash and other info into the receipt. - // In order for DeriveFields to work, the transaction and receipt lists need to be - // of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be - // extra ones, so we just trim the lists here. - receiptsCount := len(receipts) - txs := block.Transactions() - if len(receipts) > len(txs) { - receipts = receipts[:len(txs)] - } else if len(receipts) < len(txs) { - txs = txs[:len(receipts)] - } - var blobGasPrice *big.Int - if block.ExcessBlobGas() != nil { - blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas()) - } - if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil { - panic(err) - } - - // Re-expand to ensure all receipts are returned. - receipts = receipts[:receiptsCount] - - // Advance the chain. - cm.add(block, receipts) - parent = block - } - return cm.chain, cm.receipts -} - -// GenerateChainWithGenesis is a wrapper of GenerateChain which will initialize -// genesis block to database first according to the provided genesis specification -// then generate chain on top. -func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) { - db := rawdb.NewMemoryDatabase() - triedb := triedb.NewDatabase(db, triedb.HashDefaults) - defer triedb.Close() - _, err := genesis.Commit(db, triedb) - if err != nil { - panic(err) - } - blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen) - return db, blocks, receipts -} - -func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header { - time := parent.Time() + 10 // block time is fixed at 10 seconds - header := &types.Header{ - Root: state.IntermediateRoot(cm.config.IsEIP158(parent.Number())), - ParentHash: parent.Hash(), - Coinbase: parent.Coinbase(), - Difficulty: engine.CalcDifficulty(cm, time, parent.Header()), - GasLimit: parent.GasLimit(), - Number: new(big.Int).Add(parent.Number(), common.Big1), - Time: time, - } - - if cm.config.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(cm.config, parent.Header()) - if !cm.config.IsLondon(parent.Number()) { - parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier() - header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) - } - } - if cm.config.IsCancun(header.Number, header.Time) { - var ( - parentExcessBlobGas uint64 - parentBlobGasUsed uint64 - ) - if parent.ExcessBlobGas() != nil { - parentExcessBlobGas = *parent.ExcessBlobGas() - parentBlobGasUsed = *parent.BlobGasUsed() - } - excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed) - header.ExcessBlobGas = &excessBlobGas - header.BlobGasUsed = new(uint64) - header.ParentBeaconRoot = new(common.Hash) - } - return header -} - -// makeHeaderChain creates a deterministic chain of headers rooted at parent. -func makeHeaderChain(chainConfig *params.ChainConfig, parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header { - blocks := makeBlockChain(chainConfig, types.NewBlockWithHeader(parent), n, engine, db, seed) - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - return headers -} - -// makeHeaderChainWithGenesis creates a deterministic chain of headers from genesis. -func makeHeaderChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Header) { - db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed) - headers := make([]*types.Header, len(blocks)) - for i, block := range blocks { - headers[i] = block.Header() - } - return db, headers -} - -// makeBlockChain creates a deterministic chain of blocks rooted at parent. -func makeBlockChain(chainConfig *params.ChainConfig, parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block { - blocks, _ := GenerateChain(chainConfig, parent, engine, db, n, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) - }) - return blocks -} - -// makeBlockChain creates a deterministic chain of blocks from genesis -func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Block) { - db, blocks, _ := GenerateChainWithGenesis(genesis, engine, n, func(i int, b *BlockGen) { - b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) - }) - return db, blocks -} - -// chainMaker contains the state of chain generation. -type chainMaker struct { - bottom *types.Block - engine consensus.Engine - config *params.ChainConfig - chain []*types.Block - chainByHash map[common.Hash]*types.Block - receipts []types.Receipts -} - -func newChainMaker(bottom *types.Block, config *params.ChainConfig, engine consensus.Engine) *chainMaker { - return &chainMaker{ - bottom: bottom, - config: config, - engine: engine, - chainByHash: make(map[common.Hash]*types.Block), - } -} - -func (cm *chainMaker) add(b *types.Block, r []*types.Receipt) { - cm.chain = append(cm.chain, b) - cm.chainByHash[b.Hash()] = b - cm.receipts = append(cm.receipts, r) -} - -func (cm *chainMaker) blockByNumber(number uint64) *types.Block { - if number == cm.bottom.NumberU64() { - return cm.bottom - } - cur := cm.CurrentHeader().Number.Uint64() - lowest := cm.bottom.NumberU64() + 1 - if number < lowest || number > cur { - return nil - } - return cm.chain[number-lowest] -} - -// ChainReader/ChainContext implementation - -// Config returns the chain configuration (for consensus.ChainReader). -func (cm *chainMaker) Config() *params.ChainConfig { - return cm.config -} - -// Engine returns the consensus engine (for ChainContext). -func (cm *chainMaker) Engine() consensus.Engine { - return cm.engine -} - -func (cm *chainMaker) CurrentHeader() *types.Header { - if len(cm.chain) == 0 { - return cm.bottom.Header() - } - return cm.chain[len(cm.chain)-1].Header() -} - -func (cm *chainMaker) GetHeaderByNumber(number uint64) *types.Header { - b := cm.blockByNumber(number) - if b == nil { - return nil - } - return b.Header() -} - -func (cm *chainMaker) GetHeaderByHash(hash common.Hash) *types.Header { - b := cm.chainByHash[hash] - if b == nil { - return nil - } - return b.Header() -} - -func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header { - return cm.GetHeaderByNumber(number) -} - -func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block { - return cm.blockByNumber(number) -} - -func (cm *chainMaker) GetTd(hash common.Hash, number uint64) *big.Int { - return nil // not supported -} diff --git a/builder/core/chain_makers_test.go b/builder/core/chain_makers_test.go deleted file mode 100644 index b46b898af..000000000 --- a/builder/core/chain_makers_test.go +++ /dev/null @@ -1,260 +0,0 @@ -// 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 core - -import ( - "fmt" - "math/big" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" -) - -func TestGeneratePOSChain(t *testing.T) { - var ( - keyHex = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c" - key, _ = crypto.HexToECDSA(keyHex) - address = crypto.PubkeyToAddress(key.PublicKey) // 658bdf435d810c91414ec09147daa6db62406379 - aa = common.Address{0xaa} - bb = common.Address{0xbb} - funds = big.NewInt(0).Mul(big.NewInt(1337), big.NewInt(params.Ether)) - config = *params.AllEthashProtocolChanges - asm4788 = common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500") - gspec = &Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: asm4788}, - }, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: common.Big1, - GasLimit: 5_000_000, - } - gendb = rawdb.NewMemoryDatabase() - db = rawdb.NewMemoryDatabase() - ) - - config.TerminalTotalDifficultyPassed = true - config.TerminalTotalDifficulty = common.Big0 - config.ShanghaiTime = u64(0) - config.CancunTime = u64(0) - - // init 0xaa with some storage elements - storage := make(map[common.Hash]common.Hash) - storage[common.Hash{0x00}] = common.Hash{0x00} - storage[common.Hash{0x01}] = common.Hash{0x01} - storage[common.Hash{0x02}] = common.Hash{0x02} - storage[common.Hash{0x03}] = common.HexToHash("0303") - gspec.Alloc[aa] = types.Account{ - Balance: common.Big1, - Nonce: 1, - Storage: storage, - Code: common.Hex2Bytes("6042"), - } - gspec.Alloc[bb] = types.Account{ - Balance: common.Big2, - Nonce: 1, - Storage: storage, - Code: common.Hex2Bytes("600154600354"), - } - genesis := gspec.MustCommit(gendb, triedb.NewDatabase(gendb, triedb.HashDefaults)) - - genchain, genreceipts := GenerateChain(gspec.Config, genesis, beacon.NewFaker(), gendb, 4, func(i int, gen *BlockGen) { - gen.SetParentBeaconRoot(common.Hash{byte(i + 1)}) - - // Add value transfer tx. - tx := types.MustSignNewTx(key, gen.Signer(), &types.LegacyTx{ - Nonce: gen.TxNonce(address), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Add(gen.BaseFee(), common.Big1), - }) - gen.AddTx(tx) - - // Add withdrawals. - if i == 1 { - gen.AddWithdrawal(&types.Withdrawal{ - Validator: 42, - Address: common.Address{0xee}, - Amount: 1337, - }) - gen.AddWithdrawal(&types.Withdrawal{ - Validator: 13, - Address: common.Address{0xee}, - Amount: 1, - }) - } - if i == 3 { - gen.AddWithdrawal(&types.Withdrawal{ - Validator: 42, - Address: common.Address{0xee}, - Amount: 1337, - }) - gen.AddWithdrawal(&types.Withdrawal{ - Validator: 13, - Address: common.Address{0xee}, - Amount: 1, - }) - } - }) - - // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec, nil, beacon.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - if i, err := blockchain.InsertChain(genchain); err != nil { - t.Fatalf("insert error (block %d): %v\n", genchain[i].NumberU64(), err) - } - - // enforce that withdrawal indexes are monotonically increasing from 0 - var ( - withdrawalIndex uint64 - ) - for i := range genchain { - blocknum := genchain[i].NumberU64() - block := blockchain.GetBlockByNumber(blocknum) - if block == nil { - t.Fatalf("block %d not found", blocknum) - } - - // Verify receipts. - genBlockReceipts := genreceipts[i] - for _, r := range genBlockReceipts { - if r.BlockNumber.Cmp(block.Number()) != 0 { - t.Errorf("receipt has wrong block number %d, want %d", r.BlockNumber, block.Number()) - } - if r.BlockHash != block.Hash() { - t.Errorf("receipt has wrong block hash %v, want %v", r.BlockHash, block.Hash()) - } - - // patch up empty logs list to make DeepEqual below work - if r.Logs == nil { - r.Logs = []*types.Log{} - } - } - blockchainReceipts := blockchain.GetReceiptsByHash(block.Hash()) - if !reflect.DeepEqual(genBlockReceipts, blockchainReceipts) { - t.Fatalf("receipts mismatch\ngenerated: %s\nblockchain: %s", spew.Sdump(genBlockReceipts), spew.Sdump(blockchainReceipts)) - } - - // Verify withdrawals. - if len(block.Withdrawals()) == 0 { - continue - } - for j := 0; j < len(block.Withdrawals()); j++ { - if block.Withdrawals()[j].Index != withdrawalIndex { - t.Fatalf("withdrawal index %d does not equal expected index %d", block.Withdrawals()[j].Index, withdrawalIndex) - } - withdrawalIndex += 1 - } - - // Verify parent beacon root. - want := common.Hash{byte(blocknum)} - if got := block.BeaconRoot(); *got != want { - t.Fatalf("block %d, wrong parent beacon root: got %s, want %s", i, got, want) - } - state, _ := blockchain.State() - idx := block.Time()%8191 + 8191 - got := state.GetState(params.BeaconRootsStorageAddress, common.BigToHash(new(big.Int).SetUint64(idx))) - if got != want { - t.Fatalf("block %d, wrong parent beacon root in state: got %s, want %s", i, got, want) - } - } -} - -func ExampleGenerateChain() { - var ( - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - addr3 = crypto.PubkeyToAddress(key3.PublicKey) - db = rawdb.NewMemoryDatabase() - genDb = rawdb.NewMemoryDatabase() - ) - - // Ensure that key1 has some funds in the genesis block. - gspec := &Genesis{ - Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, - Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, - } - genesis := gspec.MustCommit(genDb, triedb.NewDatabase(genDb, triedb.HashDefaults)) - - // This call generates a chain of 5 blocks. The function runs for - // each block and adds different features to gen based on the - // block index. - signer := types.HomesteadSigner{} - chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), genDb, 5, func(i int, gen *BlockGen) { - switch i { - case 0: - // In block 1, addr1 sends addr2 some ether. - tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) - gen.AddTx(tx) - case 1: - // In block 2, addr1 sends some more ether to addr2. - // addr2 passes it on to addr3. - tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) - tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) - gen.AddTx(tx1) - gen.AddTx(tx2) - case 2: - // Block 3 is empty but was mined by addr3. - gen.SetCoinbase(addr3) - gen.SetExtra([]byte("yeehaw")) - case 3: - // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). - b2 := gen.PrevBlock(1).Header() - b2.Extra = []byte("foo") - gen.AddUncle(b2) - b3 := gen.PrevBlock(2).Header() - b3.Extra = []byte("foo") - gen.AddUncle(b3) - } - }) - - // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.HashScheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer blockchain.Stop() - - if i, err := blockchain.InsertChain(chain); err != nil { - fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err) - return - } - - state, _ := blockchain.State() - fmt.Printf("last block: #%d\n", blockchain.CurrentBlock().Number) - fmt.Println("balance of addr1:", state.GetBalance(addr1)) - fmt.Println("balance of addr2:", state.GetBalance(addr2)) - fmt.Println("balance of addr3:", state.GetBalance(addr3)) - // Output: - // last block: #5 - // balance of addr1: 989000 - // balance of addr2: 10000 - // balance of addr3: 19687500000000001000 -} diff --git a/builder/core/dao_test.go b/builder/core/dao_test.go deleted file mode 100644 index b9a899ef2..000000000 --- a/builder/core/dao_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2016 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 core - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" -) - -// Tests that DAO-fork enabled clients can properly filter out fork-commencing -// blocks based on their extradata fields. -func TestDAOForkRangeExtradata(t *testing.T) { - forkBlock := big.NewInt(32) - chainConfig := *params.NonActivatedConfig - chainConfig.HomesteadBlock = big.NewInt(0) - - // Generate a common prefix for both pro-forkers and non-forkers - gspec := &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: &chainConfig, - } - genDb, prefix, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) - - // Create the concurrent, conflicting two nodes - proDb := rawdb.NewMemoryDatabase() - proConf := *params.NonActivatedConfig - proConf.HomesteadBlock = big.NewInt(0) - proConf.DAOForkBlock = forkBlock - proConf.DAOForkSupport = true - progspec := &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: &proConf, - } - proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer proBc.Stop() - - conDb := rawdb.NewMemoryDatabase() - conConf := *params.NonActivatedConfig - conConf.HomesteadBlock = big.NewInt(0) - conConf.DAOForkBlock = forkBlock - conConf.DAOForkSupport = false - congspec := &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: &conConf, - } - conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer conBc.Stop() - - if _, err := proBc.InsertChain(prefix); err != nil { - t.Fatalf("pro-fork: failed to import chain prefix: %v", err) - } - if _, err := conBc.InsertChain(prefix); err != nil { - t.Fatalf("con-fork: failed to import chain prefix: %v", err) - } - // Try to expand both pro-fork and non-fork chains iteratively with other camp's blocks - for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ { - // Create a pro-fork block, and try to feed into the no-fork chain - bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - - blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) - for j := 0; j < len(blocks)/2; j++ { - blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] - } - if _, err := bc.InsertChain(blocks); err != nil { - t.Fatalf("failed to import contra-fork chain for expansion: %v", err) - } - if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { - t.Fatalf("failed to commit contra-fork head for expansion: %v", err) - } - bc.Stop() - blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := conBc.InsertChain(blocks); err == nil { - t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) - } - // Create a proper no-fork block for the contra-forker - blocks, _ = GenerateChain(&conConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := conBc.InsertChain(blocks); err != nil { - t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) - } - // Create a no-fork block, and try to feed into the pro-fork chain - bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - - blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) - for j := 0; j < len(blocks)/2; j++ { - blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] - } - if _, err := bc.InsertChain(blocks); err != nil { - t.Fatalf("failed to import pro-fork chain for expansion: %v", err) - } - if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { - t.Fatalf("failed to commit pro-fork head for expansion: %v", err) - } - bc.Stop() - blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := proBc.InsertChain(blocks); err == nil { - t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) - } - // Create a proper pro-fork block for the pro-forker - blocks, _ = GenerateChain(&proConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := proBc.InsertChain(blocks); err != nil { - t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err) - } - } - // Verify that contra-forkers accept pro-fork extra-datas after forking finishes - bc, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer bc.Stop() - - blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64())) - for j := 0; j < len(blocks)/2; j++ { - blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] - } - if _, err := bc.InsertChain(blocks); err != nil { - t.Fatalf("failed to import contra-fork chain for expansion: %v", err) - } - if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { - t.Fatalf("failed to commit contra-fork head for expansion: %v", err) - } - blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := conBc.InsertChain(blocks); err != nil { - t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) - } - // Verify that pro-forkers accept contra-fork extra-datas after forking finishes - bc, _ = NewBlockChain(rawdb.NewMemoryDatabase(), nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - defer bc.Stop() - - blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) - for j := 0; j < len(blocks)/2; j++ { - blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] - } - if _, err := bc.InsertChain(blocks); err != nil { - t.Fatalf("failed to import pro-fork chain for expansion: %v", err) - } - if err := bc.triedb.Commit(bc.CurrentHeader().Root, false); err != nil { - t.Fatalf("failed to commit pro-fork head for expansion: %v", err) - } - blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) - if _, err := proBc.InsertChain(blocks); err != nil { - t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) - } -} diff --git a/builder/core/error.go b/builder/core/error.go deleted file mode 100644 index 72cacf8c7..000000000 --- a/builder/core/error.go +++ /dev/null @@ -1,113 +0,0 @@ -// 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 core - -import ( - "errors" - - "github.com/ethereum/go-ethereum/core/types" -) - -var ( - // ErrKnownBlock is returned when a block to import is already known locally. - ErrKnownBlock = errors.New("block already known") - - // ErrBannedHash is returned if a block to import is on the banned list. - ErrBannedHash = errors.New("banned hash") - - // ErrNoGenesis is returned when there is no Genesis Block. - ErrNoGenesis = errors.New("genesis not found in chain") - - errSideChainReceipts = errors.New("side blocks can't be accepted as ancient chain data") -) - -// List of evm-call-message pre-checking errors. All state transition messages will -// be pre-checked before execution. If any invalidation detected, the corresponding -// error should be returned which is defined here. -// -// - If the pre-checking happens in the miner, then the transaction won't be packed. -// - If the pre-checking happens in the block processing procedure, then a "BAD BLOCk" -// error should be emitted. -var ( - // 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") - - // ErrNonceTooHigh is returned if the nonce of a transaction is higher than the - // next one expected based on the local chain. - ErrNonceTooHigh = errors.New("nonce too high") - - // ErrNonceMax is returned if the nonce of a transaction sender account has - // maximum allowed value and would become invalid if incremented. - ErrNonceMax = errors.New("nonce has max value") - - // ErrGasLimitReached is returned by the gas pool if the amount of gas required - // by a transaction is higher than what's left in the block. - ErrGasLimitReached = errors.New("gas limit reached") - - // ErrInsufficientFundsForTransfer is returned if the transaction sender doesn't - // have enough funds for transfer(topmost call only). - ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer") - - // ErrMaxInitCodeSizeExceeded is returned if creation transaction provides the init code bigger - // than init code size limit. - ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded") - - // 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") - - // ErrGasUintOverflow is returned when calculating gas usage. - ErrGasUintOverflow = errors.New("gas uint64 overflow") - - // 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") - - // ErrTxTypeNotSupported is returned if a transaction is not supported in the - // current network configuration. - ErrTxTypeNotSupported = types.ErrTxTypeNotSupported - - // ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a - // transaction with a tip higher than the total fee cap. - ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas") - - // ErrTipVeryHigh is a sanity error to avoid extremely big numbers specified - // in the tip field. - ErrTipVeryHigh = errors.New("max priority fee per gas higher than 2^256-1") - - // ErrFeeCapVeryHigh is a sanity error to avoid extremely big numbers specified - // in the fee cap field. - ErrFeeCapVeryHigh = errors.New("max fee per gas higher than 2^256-1") - - // ErrFeeCapTooLow is returned if the transaction fee cap is less than the - // base fee of the block. - ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee") - - // ErrSenderNoEOA is returned if the sender of a transaction is a contract. - ErrSenderNoEOA = errors.New("sender not an eoa") - - // ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the - // blob gas fee of the block. - ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee") - - // ErrMissingBlobHashes is returned if a blob transaction has no blob hashes. - ErrMissingBlobHashes = errors.New("blob transaction missing blob hashes") - - // ErrBlobTxCreate is returned if a blob transaction has no explicit to field. - ErrBlobTxCreate = errors.New("blob transaction of type create") -) diff --git a/builder/core/events.go b/builder/core/events.go deleted file mode 100644 index ac935a137..000000000 --- a/builder/core/events.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 core - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// NewTxsEvent is posted when a batch of transactions enter the transaction pool. -type NewTxsEvent struct{ Txs []*types.Transaction } - -// NewMinedBlockEvent is posted when a block has been imported. -type NewMinedBlockEvent struct{ Block *types.Block } - -// RemovedLogsEvent is posted when a reorg happens -type RemovedLogsEvent struct{ Logs []*types.Log } - -type ChainEvent struct { - Block *types.Block - Hash common.Hash - Logs []*types.Log -} - -type ChainSideEvent struct { - Block *types.Block -} - -type ChainHeadEvent struct{ Block *types.Block } diff --git a/builder/core/evm.go b/builder/core/evm.go deleted file mode 100644 index 73f6d7bc2..000000000 --- a/builder/core/evm.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2016 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 core - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/holiman/uint256" -) - -// ChainContext supports retrieving headers and consensus parameters from the -// current blockchain to be used during transaction processing. -type ChainContext interface { - // Engine retrieves the chain's consensus engine. - Engine() consensus.Engine - - // GetHeader returns the header corresponding to the hash/number argument pair. - GetHeader(common.Hash, uint64) *types.Header -} - -// NewEVMBlockContext creates a new context for use in the EVM. -func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common.Address) vm.BlockContext { - var ( - beneficiary common.Address - baseFee *big.Int - blobBaseFee *big.Int - random *common.Hash - ) - - // If we don't have an explicit author (i.e. not mining), extract from the header - if author == nil { - beneficiary, _ = chain.Engine().Author(header) // Ignore error, we're past header validation - } else { - beneficiary = *author - } - if header.BaseFee != nil { - baseFee = new(big.Int).Set(header.BaseFee) - } - if header.ExcessBlobGas != nil { - blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas) - } - if header.Difficulty.Cmp(common.Big0) == 0 { - random = &header.MixDigest - } - return vm.BlockContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: header.Time, - Difficulty: new(big.Int).Set(header.Difficulty), - BaseFee: baseFee, - BlobBaseFee: blobBaseFee, - GasLimit: header.GasLimit, - Random: random, - } -} - -// NewEVMTxContext creates a new transaction context for a single transaction. -func NewEVMTxContext(msg *Message) vm.TxContext { - ctx := vm.TxContext{ - Origin: msg.From, - GasPrice: new(big.Int).Set(msg.GasPrice), - BlobHashes: msg.BlobHashes, - } - if msg.BlobGasFeeCap != nil { - ctx.BlobFeeCap = new(big.Int).Set(msg.BlobGasFeeCap) - } - return ctx -} - -// GetHashFn returns a GetHashFunc which retrieves header hashes by number -func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash { - // Cache will initially contain [refHash.parent], - // Then fill up with [refHash.p, refHash.pp, refHash.ppp, ...] - var cache []common.Hash - - return func(n uint64) common.Hash { - if ref.Number.Uint64() <= n { - // This situation can happen if we're doing tracing and using - // block overrides. - return common.Hash{} - } - // If there's no hash cache yet, make one - if len(cache) == 0 { - cache = append(cache, ref.ParentHash) - } - if idx := ref.Number.Uint64() - n - 1; idx < uint64(len(cache)) { - return cache[idx] - } - // No luck in the cache, but we can start iterating from the last element we already know - lastKnownHash := cache[len(cache)-1] - lastKnownNumber := ref.Number.Uint64() - uint64(len(cache)) - - for { - header := chain.GetHeader(lastKnownHash, lastKnownNumber) - if header == nil { - break - } - cache = append(cache, header.ParentHash) - lastKnownHash = header.ParentHash - lastKnownNumber = header.Number.Uint64() - 1 - if n == lastKnownNumber { - return lastKnownHash - } - } - return common.Hash{} - } -} - -// CanTransfer checks whether there are enough funds in the address' account to make a transfer. -// This does not take the necessary gas in to account to make the transfer valid. -func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool { - return db.GetBalance(addr).Cmp(amount) >= 0 -} - -// Transfer subtracts amount from sender and adds amount to recipient using the given Db -func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) { - db.SubBalance(sender, amount) - db.AddBalance(recipient, amount) -} diff --git a/builder/core/forkchoice.go b/builder/core/forkchoice.go deleted file mode 100644 index b293c851b..000000000 --- a/builder/core/forkchoice.go +++ /dev/null @@ -1,113 +0,0 @@ -// 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 core - -import ( - crand "crypto/rand" - "errors" - "math/big" - mrand "math/rand" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" -) - -// ChainReader defines a small collection of methods needed to access the local -// blockchain during header verification. It's implemented by both blockchain -// and lightchain. -type ChainReader interface { - // Config retrieves the header chain's chain configuration. - Config() *params.ChainConfig - - // GetTd returns the total difficulty of a local block. - GetTd(common.Hash, uint64) *big.Int -} - -// ForkChoice is the fork chooser based on the highest total difficulty of the -// chain(the fork choice used in the eth1) and the external fork choice (the fork -// choice used in the eth2). This main goal of this ForkChoice is not only for -// offering fork choice during the eth1/2 merge phase, but also keep the compatibility -// for all other proof-of-work networks. -type ForkChoice struct { - chain ChainReader - rand *mrand.Rand - - // preserve is a helper function used in td fork choice. - // Miners will prefer to choose the local mined block if the - // local td is equal to the extern one. It can be nil for light - // client - preserve func(header *types.Header) bool -} - -func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header) bool) *ForkChoice { - // Seed a fast but crypto originating random generator - seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) - if err != nil { - log.Crit("Failed to initialize random seed", "err", err) - } - return &ForkChoice{ - chain: chainReader, - rand: mrand.New(mrand.NewSource(seed.Int64())), - preserve: preserve, - } -} - -// ReorgNeeded returns whether the reorg should be applied -// based on the given external header and local canonical chain. -// In the td mode, the new head is chosen if the corresponding -// total difficulty is higher. In the extern mode, the trusted -// header is always selected as the head. -func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (bool, error) { - var ( - localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64()) - externTd = f.chain.GetTd(extern.Hash(), extern.Number.Uint64()) - ) - if localTD == nil || externTd == nil { - return false, errors.New("missing td") - } - // Accept the new header as the chain head if the transition - // is already triggered. We assume all the headers after the - // transition come from the trusted consensus layer. - if ttd := f.chain.Config().TerminalTotalDifficulty; ttd != nil && ttd.Cmp(externTd) <= 0 { - return true, nil - } - - // If the total difficulty is higher than our known, add it to the canonical chain - if diff := externTd.Cmp(localTD); diff > 0 { - return true, nil - } else if diff < 0 { - return false, nil - } - // Local and external difficulty is identical. - // Second clause in the if statement reduces the vulnerability to selfish mining. - // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf - reorg := false - externNum, localNum := extern.Number.Uint64(), current.Number.Uint64() - if externNum < localNum { - reorg = true - } else if externNum == localNum { - var currentPreserve, externPreserve bool - if f.preserve != nil { - currentPreserve, externPreserve = f.preserve(current), f.preserve(extern) - } - reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5) - } - return reorg, nil -} diff --git a/builder/core/forkid/forkid.go b/builder/core/forkid/forkid.go deleted file mode 100644 index 76825d3be..000000000 --- a/builder/core/forkid/forkid.go +++ /dev/null @@ -1,297 +0,0 @@ -// 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 forkid implements EIP-2124 (https://eips.ethereum.org/EIPS/eip-2124). -package forkid - -import ( - "encoding/binary" - "errors" - "hash/crc32" - "math" - "math/big" - "reflect" - "strings" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "golang.org/x/exp/slices" -) - -var ( - // ErrRemoteStale is returned by the validator if a remote fork checksum is a - // subset of our already applied forks, but the announced next fork block is - // not on our already passed chain. - ErrRemoteStale = errors.New("remote needs update") - - // ErrLocalIncompatibleOrStale is returned by the validator if a remote fork - // checksum does not match any local checksum variation, signalling that the - // two chains have diverged in the past at some point (possibly at genesis). - ErrLocalIncompatibleOrStale = errors.New("local incompatible or needs update") -) - -// timestampThreshold is the Ethereum mainnet genesis timestamp. It is used to -// differentiate if a forkid.next field is a block number or a timestamp. Whilst -// very hacky, something's needed to split the validation during the transition -// period (block forks -> time forks). -const timestampThreshold = 1438269973 - -// Blockchain defines all necessary method to build a forkID. -type Blockchain interface { - // Config retrieves the chain's fork configuration. - Config() *params.ChainConfig - - // Genesis retrieves the chain's genesis block. - Genesis() *types.Block - - // CurrentHeader retrieves the current head header of the canonical chain. - CurrentHeader() *types.Header -} - -// ID is a fork identifier as defined by EIP-2124. -type ID struct { - Hash [4]byte // CRC32 checksum of the genesis block and passed fork block numbers - Next uint64 // Block number of the next upcoming fork, or 0 if no forks are known -} - -// Filter is a fork id filter to validate a remotely advertised ID. -type Filter func(id ID) error - -// NewID calculates the Ethereum fork ID from the chain config, genesis hash, head and time. -func NewID(config *params.ChainConfig, genesis *types.Block, head, time uint64) ID { - // Calculate the starting checksum from the genesis hash - hash := crc32.ChecksumIEEE(genesis.Hash().Bytes()) - - // Calculate the current fork checksum and the next fork block - forksByBlock, forksByTime := gatherForks(config, genesis.Time()) - for _, fork := range forksByBlock { - if fork <= head { - // Fork already passed, checksum the previous hash and the fork number - hash = checksumUpdate(hash, fork) - continue - } - return ID{Hash: checksumToBytes(hash), Next: fork} - } - for _, fork := range forksByTime { - if fork <= time { - // Fork already passed, checksum the previous hash and fork timestamp - hash = checksumUpdate(hash, fork) - continue - } - return ID{Hash: checksumToBytes(hash), Next: fork} - } - return ID{Hash: checksumToBytes(hash), Next: 0} -} - -// NewIDWithChain calculates the Ethereum fork ID from an existing chain instance. -func NewIDWithChain(chain Blockchain) ID { - head := chain.CurrentHeader() - - return NewID( - chain.Config(), - chain.Genesis(), - head.Number.Uint64(), - head.Time, - ) -} - -// NewFilter creates a filter that returns if a fork ID should be rejected or not -// based on the local chain's status. -func NewFilter(chain Blockchain) Filter { - return newFilter( - chain.Config(), - chain.Genesis(), - func() (uint64, uint64) { - head := chain.CurrentHeader() - return head.Number.Uint64(), head.Time - }, - ) -} - -// NewStaticFilter creates a filter at block zero. -func NewStaticFilter(config *params.ChainConfig, genesis *types.Block) Filter { - head := func() (uint64, uint64) { return 0, 0 } - return newFilter(config, genesis, head) -} - -// newFilter is the internal version of NewFilter, taking closures as its arguments -// instead of a chain. The reason is to allow testing it without having to simulate -// an entire blockchain. -func newFilter(config *params.ChainConfig, genesis *types.Block, headfn func() (uint64, uint64)) Filter { - // Calculate the all the valid fork hash and fork next combos - var ( - forksByBlock, forksByTime = gatherForks(config, genesis.Time()) - forks = append(append([]uint64{}, forksByBlock...), forksByTime...) - sums = make([][4]byte, len(forks)+1) // 0th is the genesis - ) - hash := crc32.ChecksumIEEE(genesis.Hash().Bytes()) - sums[0] = checksumToBytes(hash) - for i, fork := range forks { - hash = checksumUpdate(hash, fork) - sums[i+1] = checksumToBytes(hash) - } - // Add two sentries to simplify the fork checks and don't require special - // casing the last one. - forks = append(forks, math.MaxUint64) // Last fork will never be passed - if len(forksByTime) == 0 { - // In purely block based forks, avoid the sentry spilling into timestapt territory - forksByBlock = append(forksByBlock, math.MaxUint64) // Last fork will never be passed - } - // Create a validator that will filter out incompatible chains - return func(id ID) error { - // Run the fork checksum validation ruleset: - // 1. If local and remote FORK_CSUM matches, compare local head to FORK_NEXT. - // The two nodes are in the same fork state currently. They might know - // of differing future forks, but that's not relevant until the fork - // triggers (might be postponed, nodes might be updated to match). - // 1a. A remotely announced but remotely not passed block is already passed - // locally, disconnect, since the chains are incompatible. - // 1b. No remotely announced fork; or not yet passed locally, connect. - // 2. If the remote FORK_CSUM is a subset of the local past forks and the - // remote FORK_NEXT matches with the locally following fork block number, - // connect. - // Remote node is currently syncing. It might eventually diverge from - // us, but at this current point in time we don't have enough information. - // 3. If the remote FORK_CSUM is a superset of the local past forks and can - // be completed with locally known future forks, connect. - // Local node is currently syncing. It might eventually diverge from - // the remote, but at this current point in time we don't have enough - // information. - // 4. Reject in all other cases. - block, time := headfn() - for i, fork := range forks { - // Pick the head comparison based on fork progression - head := block - if i >= len(forksByBlock) { - head = time - } - // If our head is beyond this fork, continue to the next (we have a dummy - // fork of maxuint64 as the last item to always fail this check eventually). - if head >= fork { - continue - } - // Found the first unpassed fork block, check if our current state matches - // the remote checksum (rule #1). - if sums[i] == id.Hash { - // Fork checksum matched, check if a remote future fork block already passed - // locally without the local node being aware of it (rule #1a). - if id.Next > 0 && (head >= id.Next || (id.Next > timestampThreshold && time >= id.Next)) { - return ErrLocalIncompatibleOrStale - } - // Haven't passed locally a remote-only fork, accept the connection (rule #1b). - return nil - } - // The local and remote nodes are in different forks currently, check if the - // remote checksum is a subset of our local forks (rule #2). - for j := 0; j < i; j++ { - if sums[j] == id.Hash { - // Remote checksum is a subset, validate based on the announced next fork - if forks[j] != id.Next { - return ErrRemoteStale - } - return nil - } - } - // Remote chain is not a subset of our local one, check if it's a superset by - // any chance, signalling that we're simply out of sync (rule #3). - for j := i + 1; j < len(sums); j++ { - if sums[j] == id.Hash { - // Yay, remote checksum is a superset, ignore upcoming forks - return nil - } - } - // No exact, subset or superset match. We are on differing chains, reject. - return ErrLocalIncompatibleOrStale - } - log.Error("Impossible fork ID validation", "id", id) - return nil // Something's very wrong, accept rather than reject - } -} - -// checksumUpdate calculates the next IEEE CRC32 checksum based on the previous -// one and a fork block number (equivalent to CRC32(original-blob || fork)). -func checksumUpdate(hash uint32, fork uint64) uint32 { - var blob [8]byte - binary.BigEndian.PutUint64(blob[:], fork) - return crc32.Update(hash, crc32.IEEETable, blob[:]) -} - -// checksumToBytes converts a uint32 checksum into a [4]byte array. -func checksumToBytes(hash uint32) [4]byte { - var blob [4]byte - binary.BigEndian.PutUint32(blob[:], hash) - return blob -} - -// gatherForks gathers all the known forks and creates two sorted lists out of -// them, one for the block number based forks and the second for the timestamps. -func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64) { - // Gather all the fork block numbers via reflection - kind := reflect.TypeOf(params.ChainConfig{}) - conf := reflect.ValueOf(config).Elem() - x := uint64(0) - var ( - forksByBlock []uint64 - forksByTime []uint64 - ) - for i := 0; i < kind.NumField(); i++ { - // Fetch the next field and skip non-fork rules - field := kind.Field(i) - - time := strings.HasSuffix(field.Name, "Time") - if !time && !strings.HasSuffix(field.Name, "Block") { - continue - } - - // Extract the fork rule block number or timestamp and aggregate it - if field.Type == reflect.TypeOf(&x) { - if rule := conf.Field(i).Interface().(*uint64); rule != nil { - forksByTime = append(forksByTime, *rule) - } - } - if field.Type == reflect.TypeOf(new(big.Int)) { - if rule := conf.Field(i).Interface().(*big.Int); rule != nil { - forksByBlock = append(forksByBlock, rule.Uint64()) - } - } - } - slices.Sort(forksByBlock) - slices.Sort(forksByTime) - - // Deduplicate fork identifiers applying multiple forks - for i := 1; i < len(forksByBlock); i++ { - if forksByBlock[i] == forksByBlock[i-1] { - forksByBlock = append(forksByBlock[:i], forksByBlock[i+1:]...) - i-- - } - } - for i := 1; i < len(forksByTime); i++ { - if forksByTime[i] == forksByTime[i-1] { - forksByTime = append(forksByTime[:i], forksByTime[i+1:]...) - i-- - } - } - // Skip any forks in block 0, that's the genesis ruleset - if len(forksByBlock) > 0 && forksByBlock[0] == 0 { - forksByBlock = forksByBlock[1:] - } - // Skip any forks before genesis. - for len(forksByTime) > 0 && forksByTime[0] <= genesis { - forksByTime = forksByTime[1:] - } - return forksByBlock, forksByTime -} diff --git a/builder/core/forkid/forkid_test.go b/builder/core/forkid/forkid_test.go deleted file mode 100644 index b9d346bd9..000000000 --- a/builder/core/forkid/forkid_test.go +++ /dev/null @@ -1,441 +0,0 @@ -// 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 forkid - -import ( - "bytes" - "hash/crc32" - "math" - "math/big" - "testing" - - "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/rlp" -) - -// TestCreation tests that different genesis and fork rule combinations result in -// the correct fork ID. -func TestCreation(t *testing.T) { - type testcase struct { - head uint64 - time uint64 - want ID - } - tests := []struct { - config *params.ChainConfig - genesis *types.Block - cases []testcase - }{ - // Mainnet test cases - { - params.MainnetChainConfig, - core.DefaultGenesisBlock().ToBlock(), - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Unsynced - {1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}}, // Last Frontier block - {1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // First Homestead block - {1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}}, // Last Homestead block - {1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // First DAO block - {2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}}, // Last DAO block - {2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // First Tangerine block - {2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}}, // Last Tangerine block - {2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // First Spurious block - {4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}}, // Last Spurious block - {4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // First Byzantium block - {7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}}, // Last Byzantium block - {7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // First and last Constantinople, first Petersburg block - {9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}}, // Last Petersburg block - {9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // First Istanbul and first Muir Glacier block - {9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}}, // Last Istanbul and first Muir Glacier block - {9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // First Muir Glacier block - {12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block - {12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block - {12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block - {12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // First London block - {13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}}, // Last London block - {13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // First Arrow Glacier block - {15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}}, // Last Arrow Glacier block - {15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // First Gray Glacier block - {20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block - {20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // First Shanghai block - {30000000, 1710338134, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // Last Shanghai block - {40000000, 1710338135, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // First Cancun block - {50000000, 2000000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}}, // Future Cancun block - }, - }, - // Goerli test cases - { - params.GoerliChainConfig, - core.DefaultGoerliGenesisBlock().ToBlock(), - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block - {1561650, 0, ID{Hash: checksumToBytes(0xa3f5ab08), Next: 1561651}}, // Last Petersburg block - {1561651, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // First Istanbul block - {4460643, 0, ID{Hash: checksumToBytes(0xc25efa5c), Next: 4460644}}, // Last Istanbul block - {4460644, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // First Berlin block - {5000000, 0, ID{Hash: checksumToBytes(0x757a1c47), Next: 5062605}}, // Last Berlin block - {5062605, 0, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block - {6000000, 1678832735, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last London block - {6000001, 1678832736, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // First Shanghai block - {6500002, 1705473119, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // Last Shanghai block - {6500003, 1705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // First Cancun block - {6500003, 2705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // Future Cancun block - }, - }, - // Sepolia test cases - { - params.SepoliaChainConfig, - core.DefaultSepoliaGenesisBlock().ToBlock(), - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block - {1735370, 0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block - {1735371, 0, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block - {1735372, 1677557087, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last MergeNetsplit block - {1735372, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // First Shanghai block - {1735372, 1706655071, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // Last Shanghai block - {1735372, 1706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // First Cancun block - {1735372, 2706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // Future Cancun block - }, - }, - // Holesky test cases - { - params.HoleskyChainConfig, - core.DefaultHoleskyGenesisBlock().ToBlock(), - []testcase{ - {0, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris block - {123, 0, ID{Hash: checksumToBytes(0xc61a6098), Next: 1696000704}}, // First MergeNetsplit block - {123, 1696000704, ID{Hash: checksumToBytes(0xfd4f016b), Next: 1707305664}}, // First Shanghai block - {123, 1707305663, ID{Hash: checksumToBytes(0xfd4f016b), Next: 1707305664}}, // Last Shanghai block - {123, 1707305664, ID{Hash: checksumToBytes(0x9b192ad0), Next: 0}}, // First Cancun block - {123, 2707305664, ID{Hash: checksumToBytes(0x9b192ad0), Next: 0}}, // Future Cancun block - }, - }, - } - for i, tt := range tests { - for j, ttt := range tt.cases { - if have := NewID(tt.config, tt.genesis, ttt.head, ttt.time); have != ttt.want { - t.Errorf("test %d, case %d: fork ID mismatch: have %x, want %x", i, j, have, ttt.want) - } - } - } -} - -// TestValidation tests that a local peer correctly validates and accepts a remote -// fork ID. -func TestValidation(t *testing.T) { - // Config that has not timestamp enabled - legacyConfig := *params.MainnetChainConfig - legacyConfig.ShanghaiTime = nil - legacyConfig.CancunTime = nil - - tests := []struct { - config *params.ChainConfig - head uint64 - time uint64 - id ID - err error - }{ - //------------------ - // Block based tests - //------------------ - - // Local is mainnet Gray Glacier, remote announces the same. No future fork is announced. - {&legacyConfig, 15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 0}, nil}, - - // Local is mainnet Gray Glacier, remote announces the same. Remote also announces a next fork - // at block 0xffffffff, but that is uncertain. - {&legacyConfig, 15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: math.MaxUint64}, nil}, - - // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces - // also Byzantium, but it's not yet aware of Petersburg (e.g. non updated node before the fork). - // In this case we don't know if Petersburg passed yet or not. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, nil}, - - // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces - // also Byzantium, and it's also aware of Petersburg (e.g. updated node before the fork). We - // don't know if Petersburg passed yet (will pass) or not. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil}, - - // Local is mainnet currently in Byzantium only (so it's aware of Petersburg), remote announces - // also Byzantium, and it's also aware of some random fork (e.g. misconfigured Petersburg). As - // neither forks passed at neither nodes, they may mismatch, but we still connect for now. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: math.MaxUint64}, nil}, - - // Local is mainnet exactly on Petersburg, remote announces Byzantium + knowledge about Petersburg. Remote - // is simply out of sync, accept. - {&legacyConfig, 7280000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil}, - - // Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. Remote - // is simply out of sync, accept. - {&legacyConfig, 7987396, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil}, - - // Local is mainnet Petersburg, remote announces Spurious + knowledge about Byzantium. Remote - // is definitely out of sync. It may or may not need the Petersburg update, we don't know yet. - {&legacyConfig, 7987396, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil}, - - // Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 0}, nil}, - - // Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. Local - // out of sync. Local also knows about a future fork, but that is uncertain yet. - {&legacyConfig, 4369999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, nil}, - - // Local is mainnet Petersburg. remote announces Byzantium but is not aware of further forks. - // Remote needs software update. - {&legacyConfig, 7987396, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, ErrRemoteStale}, - - // Local is mainnet Petersburg, and isn't aware of more forks. Remote announces Petersburg + - // 0xffffffff. Local needs software update, reject. - {&legacyConfig, 7987396, 0, ID{Hash: checksumToBytes(0x5cddc0e1), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg + - // 0xffffffff. Local needs software update, reject. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0x5cddc0e1), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Petersburg, remote is Rinkeby Petersburg. - {&legacyConfig, 7987396, 0, ID{Hash: checksumToBytes(0xafec6b27), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Gray Glacier, far in the future. Remote announces Gopherium (non existing fork) - // at some future block 88888888, for itself, but past block for local. Local is incompatible. - // - // This case detects non-upgraded nodes with majority hash power (typical Ropsten mess). - {&legacyConfig, 88888888, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 88888888}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing - // fork) at block 7279999, before Petersburg. Local is incompatible. - {&legacyConfig, 7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7279999}, ErrLocalIncompatibleOrStale}, - - //------------------------------------ - // Block to timestamp transition tests - //------------------------------------ - - // Local is mainnet currently in Gray Glacier only (so it's aware of Shanghai), remote announces - // also Gray Glacier, but it's not yet aware of Shanghai (e.g. non updated node before the fork). - // In this case we don't know if Shanghai passed yet or not. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 0}, nil}, - - // Local is mainnet currently in Gray Glacier only (so it's aware of Shanghai), remote announces - // also Gray Glacier, and it's also aware of Shanghai (e.g. updated node before the fork). We - // don't know if Shanghai passed yet (will pass) or not. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}, nil}, - - // Local is mainnet currently in Gray Glacier only (so it's aware of Shanghai), remote announces - // also Gray Glacier, and it's also aware of some random fork (e.g. misconfigured Shanghai). As - // neither forks passed at neither nodes, they may mismatch, but we still connect for now. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: math.MaxUint64}, nil}, - - // Local is mainnet exactly on Shanghai, remote announces Gray Glacier + knowledge about Shanghai. Remote - // is simply out of sync, accept. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}, nil}, - - // Local is mainnet Shanghai, remote announces Gray Glacier + knowledge about Shanghai. Remote - // is simply out of sync, accept. - {params.MainnetChainConfig, 20123456, 1681338456, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}, nil}, - - // Local is mainnet Shanghai, remote announces Arrow Glacier + knowledge about Gray Glacier. Remote - // is definitely out of sync. It may or may not need the Shanghai update, we don't know yet. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}, nil}, - - // Local is mainnet Gray Glacier, remote announces Shanghai. Local is out of sync, accept. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, nil}, - - // Local is mainnet Arrow Glacier, remote announces Gray Glacier, but is not aware of Shanghai. Local - // out of sync. Local also knows about a future fork, but that is uncertain yet. - {params.MainnetChainConfig, 13773000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 0}, nil}, - - // Local is mainnet Shanghai. remote announces Gray Glacier but is not aware of further forks. - // Remote needs software update. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 0}, ErrRemoteStale}, - - // Local is mainnet Gray Glacier, and isn't aware of more forks. Remote announces Gray Glacier + - // 0xffffffff. Local needs software update, reject. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(checksumUpdate(0xf0afd0e3, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Gray Glacier, and is aware of Shanghai. Remote announces Shanghai + - // 0xffffffff. Local needs software update, reject. - {params.MainnetChainConfig, 15050000, 0, ID{Hash: checksumToBytes(checksumUpdate(0xdce96c2d, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Gray Glacier, far in the future. Remote announces Gopherium (non existing fork) - // at some future timestamp 8888888888, for itself, but past block for local. Local is incompatible. - // - // This case detects non-upgraded nodes with majority hash power (typical Ropsten mess). - {params.MainnetChainConfig, 888888888, 1660000000, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1660000000}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Gray Glacier. Remote is also in Gray Glacier, but announces Gopherium (non existing - // fork) at block 7279999, before Shanghai. Local is incompatible. - {params.MainnetChainConfig, 19999999, 1667999999, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1667999999}, ErrLocalIncompatibleOrStale}, - - //---------------------- - // Timestamp based tests - //---------------------- - - // Local is mainnet Shanghai, remote announces the same. No future fork is announced. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, nil}, - - // Local is mainnet Shanghai, remote announces the same. Remote also announces a next fork - // at time 0xffffffff, but that is uncertain. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: math.MaxUint64}, nil}, - - // Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces - // also Shanghai, but it's not yet aware of Cancun (e.g. non updated node before the fork). - // In this case we don't know if Cancun passed yet or not. - {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, nil}, - - // Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces - // also Shanghai, and it's also aware of Cancun (e.g. updated node before the fork). We - // don't know if Cancun passed yet (will pass) or not. - {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil}, - - // Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces - // also Shanghai, and it's also aware of some random fork (e.g. misconfigured Cancun). As - // neither forks passed at neither nodes, they may mismatch, but we still connect for now. - {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: math.MaxUint64}, nil}, - - // Local is mainnet exactly on Cancun, remote announces Shanghai + knowledge about Cancun. Remote - // is simply out of sync, accept. - {params.MainnetChainConfig, 21000000, 1710338135, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil}, - - // Local is mainnet Cancun, remote announces Shanghai + knowledge about Cancun. Remote - // is simply out of sync, accept. - {params.MainnetChainConfig, 21123456, 1710338136, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}, nil}, - - // Local is mainnet Prague, remote announces Shanghai + knowledge about Cancun. Remote - // is definitely out of sync. It may or may not need the Prague update, we don't know yet. - // - // TODO(karalabe): Enable this when Cancun **and** Prague is specced, update all the numbers - //{params.MainnetChainConfig, 0, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil}, - - // Local is mainnet Shanghai, remote announces Cancun. Local is out of sync, accept. - {params.MainnetChainConfig, 21000000, 1700000000, ID{Hash: checksumToBytes(0x9f3d2254), Next: 0}, nil}, - - // Local is mainnet Shanghai, remote announces Cancun, but is not aware of Prague. Local - // out of sync. Local also knows about a future fork, but that is uncertain yet. - // - // TODO(karalabe): Enable this when Cancun **and** Prague is specced, update remote checksum - //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil}, - - // Local is mainnet Cancun. remote announces Shanghai but is not aware of further forks. - // Remote needs software update. - {params.MainnetChainConfig, 21000000, 1710338135, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}, ErrRemoteStale}, - - // Local is mainnet Shanghai, and isn't aware of more forks. Remote announces Shanghai + - // 0xffffffff. Local needs software update, reject. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(checksumUpdate(0xdce96c2d, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Shanghai, and is aware of Cancun. Remote announces Cancun + - // 0xffffffff. Local needs software update, reject. - {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(checksumUpdate(0x9f3d2254, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Shanghai, remote is random Shanghai. - {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x12345678), Next: 0}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Cancun, far in the future. Remote announces Gopherium (non existing fork) - // at some future timestamp 8888888888, for itself, but past block for local. Local is incompatible. - // - // This case detects non-upgraded nodes with majority hash power (typical Ropsten mess). - {params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0x9f3d2254), Next: 8888888888}, ErrLocalIncompatibleOrStale}, - - // Local is mainnet Shanghai. Remote is also in Shanghai, but announces Gopherium (non existing - // fork) at timestamp 1668000000, before Cancun. Local is incompatible. - {params.MainnetChainConfig, 20999999, 1699999999, ID{Hash: checksumToBytes(0x71147644), Next: 1700000000}, ErrLocalIncompatibleOrStale}, - } - genesis := core.DefaultGenesisBlock().ToBlock() - for i, tt := range tests { - filter := newFilter(tt.config, genesis, func() (uint64, uint64) { return tt.head, tt.time }) - if err := filter(tt.id); err != tt.err { - t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err) - } - } -} - -// Tests that IDs are properly RLP encoded (specifically important because we -// use uint32 to store the hash, but we need to encode it as [4]byte). -func TestEncoding(t *testing.T) { - tests := []struct { - id ID - want []byte - }{ - {ID{Hash: checksumToBytes(0), Next: 0}, common.Hex2Bytes("c6840000000080")}, - {ID{Hash: checksumToBytes(0xdeadbeef), Next: 0xBADDCAFE}, common.Hex2Bytes("ca84deadbeef84baddcafe,")}, - {ID{Hash: checksumToBytes(math.MaxUint32), Next: math.MaxUint64}, common.Hex2Bytes("ce84ffffffff88ffffffffffffffff")}, - } - for i, tt := range tests { - have, err := rlp.EncodeToBytes(tt.id) - if err != nil { - t.Errorf("test %d: failed to encode forkid: %v", i, err) - continue - } - if !bytes.Equal(have, tt.want) { - t.Errorf("test %d: RLP mismatch: have %x, want %x", i, have, tt.want) - } - } -} - -// Tests that time-based forks which are active at genesis are not included in -// forkid hash. -func TestTimeBasedForkInGenesis(t *testing.T) { - var ( - time = uint64(1690475657) - genesis = types.NewBlockWithHeader(&types.Header{Time: time}) - forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes())) - config = func(shanghai, cancun uint64) *params.ChainConfig { - return ¶ms.ChainConfig{ - ChainID: big.NewInt(1337), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: &shanghai, - CancunTime: &cancun, - Ethash: new(params.EthashConfig), - } - } - ) - tests := []struct { - config *params.ChainConfig - want ID - }{ - // Shanghai active before genesis, skip - {config(time-1, time+1), ID{Hash: forkidHash, Next: time + 1}}, - - // Shanghai active at genesis, skip - {config(time, time+1), ID{Hash: forkidHash, Next: time + 1}}, - - // Shanghai not active, skip - {config(time+1, time+2), ID{Hash: forkidHash, Next: time + 1}}, - } - for _, tt := range tests { - if have := NewID(tt.config, genesis, 0, time); have != tt.want { - t.Fatalf("incorrect forkid hash: have %x, want %x", have, tt.want) - } - } -} diff --git a/builder/core/gaspool.go b/builder/core/gaspool.go deleted file mode 100644 index 767222674..000000000 --- a/builder/core/gaspool.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 core - -import ( - "fmt" - "math" -) - -// GasPool tracks the amount of gas available during execution of the transactions -// in a block. The zero value is a pool with zero gas available. -type GasPool uint64 - -// AddGas makes gas available for execution. -func (gp *GasPool) AddGas(amount uint64) *GasPool { - if uint64(*gp) > math.MaxUint64-amount { - panic("gas pool pushed above uint64") - } - *(*uint64)(gp) += amount - return gp -} - -// SubGas deducts the given amount from the pool if enough gas is -// available and returns an error otherwise. -func (gp *GasPool) SubGas(amount uint64) error { - if uint64(*gp) < amount { - return ErrGasLimitReached - } - *(*uint64)(gp) -= amount - return nil -} - -// Gas returns the amount of gas remaining in the pool. -func (gp *GasPool) Gas() uint64 { - return uint64(*gp) -} - -// SetGas sets the amount of gas with the provided number. -func (gp *GasPool) SetGas(gas uint64) { - *(*uint64)(gp) = gas -} - -func (gp *GasPool) String() string { - return fmt.Sprintf("%d", *gp) -} diff --git a/builder/core/gen_genesis.go b/builder/core/gen_genesis.go deleted file mode 100644 index 2028f98ed..000000000 --- a/builder/core/gen_genesis.go +++ /dev/null @@ -1,137 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package core - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -var _ = (*genesisSpecMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (g Genesis) MarshalJSON() ([]byte, error) { - type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce math.HexOrDecimal64 `json:"nonce"` - Timestamp math.HexOrDecimal64 `json:"timestamp"` - ExtraData hexutil.Bytes `json:"extraData"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"` - Number math.HexOrDecimal64 `json:"number"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - } - var enc Genesis - enc.Config = g.Config - enc.Nonce = math.HexOrDecimal64(g.Nonce) - enc.Timestamp = math.HexOrDecimal64(g.Timestamp) - enc.ExtraData = g.ExtraData - enc.GasLimit = math.HexOrDecimal64(g.GasLimit) - enc.Difficulty = (*math.HexOrDecimal256)(g.Difficulty) - enc.Mixhash = g.Mixhash - enc.Coinbase = g.Coinbase - if g.Alloc != nil { - enc.Alloc = make(map[common.UnprefixedAddress]types.Account, len(g.Alloc)) - for k, v := range g.Alloc { - enc.Alloc[common.UnprefixedAddress(k)] = v - } - } - enc.Number = math.HexOrDecimal64(g.Number) - enc.GasUsed = math.HexOrDecimal64(g.GasUsed) - enc.ParentHash = g.ParentHash - enc.BaseFee = (*math.HexOrDecimal256)(g.BaseFee) - enc.ExcessBlobGas = (*math.HexOrDecimal64)(g.ExcessBlobGas) - enc.BlobGasUsed = (*math.HexOrDecimal64)(g.BlobGasUsed) - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (g *Genesis) UnmarshalJSON(input []byte) error { - type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce *math.HexOrDecimal64 `json:"nonce"` - Timestamp *math.HexOrDecimal64 `json:"timestamp"` - ExtraData *hexutil.Bytes `json:"extraData"` - GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - Mixhash *common.Hash `json:"mixHash"` - Coinbase *common.Address `json:"coinbase"` - Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"` - Number *math.HexOrDecimal64 `json:"number"` - GasUsed *math.HexOrDecimal64 `json:"gasUsed"` - ParentHash *common.Hash `json:"parentHash"` - BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"` - ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"` - BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"` - } - var dec Genesis - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Config != nil { - g.Config = dec.Config - } - if dec.Nonce != nil { - g.Nonce = uint64(*dec.Nonce) - } - if dec.Timestamp != nil { - g.Timestamp = uint64(*dec.Timestamp) - } - if dec.ExtraData != nil { - g.ExtraData = *dec.ExtraData - } - if dec.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for Genesis") - } - g.GasLimit = uint64(*dec.GasLimit) - if dec.Difficulty == nil { - return errors.New("missing required field 'difficulty' for Genesis") - } - g.Difficulty = (*big.Int)(dec.Difficulty) - if dec.Mixhash != nil { - g.Mixhash = *dec.Mixhash - } - if dec.Coinbase != nil { - g.Coinbase = *dec.Coinbase - } - if dec.Alloc == nil { - return errors.New("missing required field 'alloc' for Genesis") - } - g.Alloc = make(types.GenesisAlloc, len(dec.Alloc)) - for k, v := range dec.Alloc { - g.Alloc[common.Address(k)] = v - } - if dec.Number != nil { - g.Number = uint64(*dec.Number) - } - if dec.GasUsed != nil { - g.GasUsed = uint64(*dec.GasUsed) - } - if dec.ParentHash != nil { - g.ParentHash = *dec.ParentHash - } - if dec.BaseFee != nil { - g.BaseFee = (*big.Int)(dec.BaseFee) - } - if dec.ExcessBlobGas != nil { - g.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - if dec.BlobGasUsed != nil { - g.BlobGasUsed = (*uint64)(dec.BlobGasUsed) - } - return nil -} diff --git a/builder/core/genesis.go b/builder/core/genesis.go deleted file mode 100644 index 54570ac61..000000000 --- a/builder/core/genesis.go +++ /dev/null @@ -1,598 +0,0 @@ -// 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 core - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" -) - -//go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go - -var errGenesisNoConfig = errors.New("genesis has no chain configuration") - -// Deprecated: use types.GenesisAccount instead. -type GenesisAccount = types.Account - -// Deprecated: use types.GenesisAlloc instead. -type GenesisAlloc = types.GenesisAlloc - -// Genesis specifies the header fields, state of a genesis block. It also defines hard -// fork switch-over blocks through the chain configuration. -type Genesis struct { - Config *params.ChainConfig `json:"config"` - Nonce uint64 `json:"nonce"` - Timestamp uint64 `json:"timestamp"` - ExtraData []byte `json:"extraData"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - Difficulty *big.Int `json:"difficulty" gencodec:"required"` - Mixhash common.Hash `json:"mixHash"` - Coinbase common.Address `json:"coinbase"` - Alloc types.GenesisAlloc `json:"alloc" gencodec:"required"` - - // These fields are used for consensus tests. Please don't use them - // in actual genesis blocks. - Number uint64 `json:"number"` - GasUsed uint64 `json:"gasUsed"` - ParentHash common.Hash `json:"parentHash"` - BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559 - ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844 - BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844 -} - -func ReadGenesis(db ethdb.Database) (*Genesis, error) { - var genesis Genesis - stored := rawdb.ReadCanonicalHash(db, 0) - if (stored == common.Hash{}) { - return nil, fmt.Errorf("invalid genesis hash in database: %x", stored) - } - blob := rawdb.ReadGenesisStateSpec(db, stored) - if blob == nil { - return nil, errors.New("genesis state missing from db") - } - if len(blob) != 0 { - if err := genesis.Alloc.UnmarshalJSON(blob); err != nil { - return nil, fmt.Errorf("could not unmarshal genesis state json: %s", err) - } - } - genesis.Config = rawdb.ReadChainConfig(db, stored) - if genesis.Config == nil { - return nil, errors.New("genesis config missing from db") - } - genesisBlock := rawdb.ReadBlock(db, stored, 0) - if genesisBlock == nil { - return nil, errors.New("genesis block missing from db") - } - genesisHeader := genesisBlock.Header() - genesis.Nonce = genesisHeader.Nonce.Uint64() - genesis.Timestamp = genesisHeader.Time - genesis.ExtraData = genesisHeader.Extra - genesis.GasLimit = genesisHeader.GasLimit - genesis.Difficulty = genesisHeader.Difficulty - genesis.Mixhash = genesisHeader.MixDigest - genesis.Coinbase = genesisHeader.Coinbase - genesis.BaseFee = genesisHeader.BaseFee - genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas - genesis.BlobGasUsed = genesisHeader.BlobGasUsed - - return &genesis, nil -} - -// hashAlloc computes the state root according to the genesis specification. -func hashAlloc(ga *types.GenesisAlloc, isVerkle bool) (common.Hash, error) { - // If a genesis-time verkle trie is requested, create a trie config - // with the verkle trie enabled so that the tree can be initialized - // as such. - var config *triedb.Config - if isVerkle { - config = &triedb.Config{ - PathDB: pathdb.Defaults, - IsVerkle: true, - } - } - // Create an ephemeral in-memory database for computing hash, - // all the derived states will be discarded to not pollute disk. - db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), config) - statedb, err := state.New(types.EmptyRootHash, db, nil) - if err != nil { - return common.Hash{}, err - } - for addr, account := range *ga { - if account.Balance != nil { - statedb.AddBalance(addr, uint256.MustFromBig(account.Balance)) - } - statedb.SetCode(addr, account.Code) - statedb.SetNonce(addr, account.Nonce) - for key, value := range account.Storage { - statedb.SetState(addr, key, value) - } - } - return statedb.Commit(0, false) -} - -// flushAlloc is very similar with hash, but the main difference is all the generated -// states will be persisted into the given database. Also, the genesis state -// specification will be flushed as well. -func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, triedb *triedb.Database, blockhash common.Hash) error { - statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseWithNodeDB(db, triedb), nil) - if err != nil { - return err - } - for addr, account := range *ga { - if account.Balance != nil { - statedb.AddBalance(addr, uint256.MustFromBig(account.Balance)) - } - statedb.SetCode(addr, account.Code) - statedb.SetNonce(addr, account.Nonce) - for key, value := range account.Storage { - statedb.SetState(addr, key, value) - } - } - root, err := statedb.Commit(0, false) - if err != nil { - return err - } - // Commit newly generated states into disk if it's not empty. - if root != types.EmptyRootHash { - if err := triedb.Commit(root, true); err != nil { - return err - } - } - // Marshal the genesis state specification and persist. - blob, err := json.Marshal(ga) - if err != nil { - return err - } - rawdb.WriteGenesisStateSpec(db, blockhash, blob) - return nil -} - -// field type overrides for gencodec -type genesisSpecMarshaling struct { - Nonce math.HexOrDecimal64 - Timestamp math.HexOrDecimal64 - ExtraData hexutil.Bytes - GasLimit math.HexOrDecimal64 - GasUsed math.HexOrDecimal64 - Number math.HexOrDecimal64 - Difficulty *math.HexOrDecimal256 - Alloc map[common.UnprefixedAddress]types.Account - BaseFee *math.HexOrDecimal256 - ExcessBlobGas *math.HexOrDecimal64 - BlobGasUsed *math.HexOrDecimal64 -} - -// GenesisMismatchError is raised when trying to overwrite an existing -// genesis block with an incompatible one. -type GenesisMismatchError struct { - Stored, New common.Hash -} - -func (e *GenesisMismatchError) Error() string { - return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) -} - -// ChainOverrides contains the changes to chain config. -type ChainOverrides struct { - OverrideCancun *uint64 - OverrideVerkle *uint64 -} - -// SetupGenesisBlock writes or updates the genesis block in db. -// The block that will be used is: -// -// genesis == nil genesis != nil -// +------------------------------------------ -// db has no genesis | main-net default | genesis -// db has genesis | from DB | genesis (if compatible) -// -// The stored chain configuration will be updated if it is compatible (i.e. does not -// specify a fork block below the local head block). In case of a conflict, the -// error is a *params.ConfigCompatError and the new, unwritten config is returned. -// -// The returned chain configuration is never nil. -func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlockWithOverride(db, triedb, genesis, nil) -} - -func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) { - if genesis != nil && genesis.Config == nil { - return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig - } - applyOverrides := func(config *params.ChainConfig) { - if config != nil { - if overrides != nil && overrides.OverrideCancun != nil { - config.CancunTime = overrides.OverrideCancun - } - if overrides != nil && overrides.OverrideVerkle != nil { - config.VerkleTime = overrides.OverrideVerkle - } - } - } - // Just commit the new block if there is no stored genesis block. - stored := rawdb.ReadCanonicalHash(db, 0) - if (stored == common.Hash{}) { - if genesis == nil { - log.Info("Writing default main-net genesis block") - genesis = DefaultGenesisBlock() - } else { - log.Info("Writing custom genesis block") - } - applyOverrides(genesis.Config) - block, err := genesis.Commit(db, triedb) - if err != nil { - return genesis.Config, common.Hash{}, err - } - return genesis.Config, block.Hash(), nil - } - // The genesis block is present(perhaps in ancient database) while the - // state database is not initialized yet. It can happen that the node - // is initialized with an external ancient store. Commit genesis state - // in this case. - header := rawdb.ReadHeader(db, stored, 0) - if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) { - if genesis == nil { - genesis = DefaultGenesisBlock() - } - applyOverrides(genesis.Config) - // Ensure the stored genesis matches with the given one. - hash := genesis.ToBlock().Hash() - if hash != stored { - return genesis.Config, hash, &GenesisMismatchError{stored, hash} - } - block, err := genesis.Commit(db, triedb) - if err != nil { - return genesis.Config, hash, err - } - return genesis.Config, block.Hash(), nil - } - // Check whether the genesis block is already written. - if genesis != nil { - applyOverrides(genesis.Config) - hash := genesis.ToBlock().Hash() - if hash != stored { - return genesis.Config, hash, &GenesisMismatchError{stored, hash} - } - } - // Get the existing chain configuration. - newcfg := genesis.configOrDefault(stored) - applyOverrides(newcfg) - if err := newcfg.CheckConfigForkOrder(); err != nil { - return newcfg, common.Hash{}, err - } - storedcfg := rawdb.ReadChainConfig(db, stored) - if storedcfg == nil { - log.Warn("Found genesis block without chain config") - rawdb.WriteChainConfig(db, stored, newcfg) - return newcfg, stored, nil - } - storedData, _ := json.Marshal(storedcfg) - // Special case: if a private network is being used (no genesis and also no - // mainnet hash in the database), we must not apply the `configOrDefault` - // chain config as that would be AllProtocolChanges (applying any new fork - // on top of an existing private network genesis block). In that case, only - // apply the overrides. - if genesis == nil && stored != params.MainnetGenesisHash { - newcfg = storedcfg - applyOverrides(newcfg) - } - // Check config compatibility and write the config. Compatibility errors - // are returned to the caller unless we're already at block zero. - head := rawdb.ReadHeadHeader(db) - if head == nil { - return newcfg, stored, errors.New("missing head header") - } - compatErr := storedcfg.CheckCompatible(newcfg, head.Number.Uint64(), head.Time) - if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) { - return newcfg, stored, compatErr - } - // Don't overwrite if the old is identical to the new - if newData, _ := json.Marshal(newcfg); !bytes.Equal(storedData, newData) { - rawdb.WriteChainConfig(db, stored, newcfg) - } - return newcfg, stored, nil -} - -// LoadChainConfig loads the stored chain config if it is already present in -// database, otherwise, return the config in the provided genesis specification. -func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, error) { - // Load the stored chain config from the database. It can be nil - // in case the database is empty. Notably, we only care about the - // chain config corresponds to the canonical chain. - stored := rawdb.ReadCanonicalHash(db, 0) - if stored != (common.Hash{}) { - storedcfg := rawdb.ReadChainConfig(db, stored) - if storedcfg != nil { - return storedcfg, nil - } - } - // Load the config from the provided genesis specification - if genesis != nil { - // Reject invalid genesis spec without valid chain config - if genesis.Config == nil { - return nil, errGenesisNoConfig - } - // If the canonical genesis header is present, but the chain - // config is missing(initialize the empty leveldb with an - // external ancient chain segment), ensure the provided genesis - // is matched. - if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored { - return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()} - } - return genesis.Config, nil - } - // There is no stored chain config and no new config provided, - // In this case the default chain config(mainnet) will be used - return params.MainnetChainConfig, nil -} - -func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { - switch { - case g != nil: - return g.Config - case ghash == params.MainnetGenesisHash: - return params.MainnetChainConfig - case ghash == params.HoleskyGenesisHash: - return params.HoleskyChainConfig - case ghash == params.SepoliaGenesisHash: - return params.SepoliaChainConfig - case ghash == params.GoerliGenesisHash: - return params.GoerliChainConfig - default: - return params.AllEthashProtocolChanges - } -} - -// IsVerkle indicates whether the state is already stored in a verkle -// tree at genesis time. -func (g *Genesis) IsVerkle() bool { - return g.Config.IsVerkle(new(big.Int).SetUint64(g.Number), g.Timestamp) -} - -// ToBlock returns the genesis block according to genesis specification. -func (g *Genesis) ToBlock() *types.Block { - root, err := hashAlloc(&g.Alloc, g.IsVerkle()) - if err != nil { - panic(err) - } - head := &types.Header{ - Number: new(big.Int).SetUint64(g.Number), - Nonce: types.EncodeNonce(g.Nonce), - Time: g.Timestamp, - ParentHash: g.ParentHash, - Extra: g.ExtraData, - GasLimit: g.GasLimit, - GasUsed: g.GasUsed, - BaseFee: g.BaseFee, - Difficulty: g.Difficulty, - MixDigest: g.Mixhash, - Coinbase: g.Coinbase, - Root: root, - } - if g.GasLimit == 0 { - head.GasLimit = params.GenesisGasLimit - } - if g.Difficulty == nil && g.Mixhash == (common.Hash{}) { - head.Difficulty = params.GenesisDifficulty - } - if g.Config != nil && g.Config.IsLondon(common.Big0) { - if g.BaseFee != nil { - head.BaseFee = g.BaseFee - } else { - head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) - } - } - var withdrawals []*types.Withdrawal - if conf := g.Config; conf != nil { - num := big.NewInt(int64(g.Number)) - if conf.IsShanghai(num, g.Timestamp) { - head.WithdrawalsHash = &types.EmptyWithdrawalsHash - withdrawals = make([]*types.Withdrawal, 0) - } - if conf.IsCancun(num, g.Timestamp) { - // EIP-4788: The parentBeaconBlockRoot of the genesis block is always - // the zero hash. This is because the genesis block does not have a parent - // by definition. - head.ParentBeaconRoot = new(common.Hash) - // EIP-4844 fields - head.ExcessBlobGas = g.ExcessBlobGas - head.BlobGasUsed = g.BlobGasUsed - if head.ExcessBlobGas == nil { - head.ExcessBlobGas = new(uint64) - } - if head.BlobGasUsed == nil { - head.BlobGasUsed = new(uint64) - } - } - } - return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) -} - -// Commit writes the block and state of a genesis specification to the database. -// The block is committed as the canonical head block. -func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) { - block := g.ToBlock() - if block.Number().Sign() != 0 { - return nil, errors.New("can't commit genesis block with number > 0") - } - config := g.Config - if config == nil { - config = params.AllEthashProtocolChanges - } - if err := config.CheckConfigForkOrder(); err != nil { - return nil, err - } - if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength { - return nil, errors.New("can't start clique chain without signers") - } - // All the checks has passed, flushAlloc the states derived from the genesis - // specification as well as the specification itself into the provided - // database. - if err := flushAlloc(&g.Alloc, db, triedb, block.Hash()); err != nil { - return nil, err - } - rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) - rawdb.WriteBlock(db, block) - rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil) - rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) - rawdb.WriteHeadBlockHash(db, block.Hash()) - rawdb.WriteHeadFastBlockHash(db, block.Hash()) - rawdb.WriteHeadHeaderHash(db, block.Hash()) - rawdb.WriteChainConfig(db, block.Hash(), config) - return block, nil -} - -// MustCommit writes the genesis block and state to db, panicking on error. -// The block is committed as the canonical head block. -func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.Block { - block, err := g.Commit(db, triedb) - if err != nil { - panic(err) - } - return block -} - -// DefaultGenesisBlock returns the Ethereum main net genesis block. -func DefaultGenesisBlock() *Genesis { - return &Genesis{ - Config: params.MainnetChainConfig, - Nonce: 66, - ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"), - GasLimit: 5000, - Difficulty: big.NewInt(17179869184), - Alloc: decodePrealloc(mainnetAllocData), - } -} - -// DefaultGoerliGenesisBlock returns the Görli network genesis block. -func DefaultGoerliGenesisBlock() *Genesis { - return &Genesis{ - Config: params.GoerliChainConfig, - Timestamp: 1548854791, - ExtraData: hexutil.MustDecode("0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - GasLimit: 10485760, - Difficulty: big.NewInt(1), - Alloc: decodePrealloc(goerliAllocData), - } -} - -// DefaultSepoliaGenesisBlock returns the Sepolia network genesis block. -func DefaultSepoliaGenesisBlock() *Genesis { - return &Genesis{ - Config: params.SepoliaChainConfig, - Nonce: 0, - ExtraData: []byte("Sepolia, Athens, Attica, Greece!"), - GasLimit: 0x1c9c380, - Difficulty: big.NewInt(0x20000), - Timestamp: 1633267481, - Alloc: decodePrealloc(sepoliaAllocData), - } -} - -// DefaultHoleskyGenesisBlock returns the Holesky network genesis block. -func DefaultHoleskyGenesisBlock() *Genesis { - return &Genesis{ - Config: params.HoleskyChainConfig, - Nonce: 0x1234, - GasLimit: 0x17d7840, - Difficulty: big.NewInt(0x01), - Timestamp: 1695902100, - Alloc: decodePrealloc(holeskyAllocData), - } -} - -// DeveloperGenesisBlock returns the 'geth --dev' genesis block. -func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis { - // Override the default period to the user requested one - config := *params.AllDevChainProtocolChanges - - // Assemble and return the genesis with the precompiles and faucet pre-funded - genesis := &Genesis{ - Config: &config, - GasLimit: gasLimit, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: big.NewInt(1), - Alloc: map[common.Address]types.Account{ - common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover - common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256 - common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD - common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity - common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp - common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd - common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul - common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing - common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b - }, - } - if faucet != nil { - genesis.Alloc[*faucet] = types.Account{Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))} - } - return genesis -} - -func decodePrealloc(data string) types.GenesisAlloc { - var p []struct { - Addr *big.Int - Balance *big.Int - Misc *struct { - Nonce uint64 - Code []byte - Slots []struct { - Key common.Hash - Val common.Hash - } - } `rlp:"optional"` - } - if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil { - panic(err) - } - ga := make(types.GenesisAlloc, len(p)) - for _, account := range p { - acc := types.Account{Balance: account.Balance} - if account.Misc != nil { - acc.Nonce = account.Misc.Nonce - acc.Code = account.Misc.Code - - acc.Storage = make(map[common.Hash]common.Hash) - for _, slot := range account.Misc.Slots { - acc.Storage[slot.Key] = slot.Val - } - } - ga[common.BigToAddress(account.Addr)] = acc - } - return ga -} diff --git a/builder/core/genesis_alloc.go b/builder/core/genesis_alloc.go deleted file mode 100644 index 94c4ec535..000000000 --- a/builder/core/genesis_alloc.go +++ /dev/null @@ -1,27 +0,0 @@ -// 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 core - -// Constants containing the genesis allocation of built-in genesis blocks. -// Their content is an RLP-encoded list of (address, balance) tuples. -// Use mkalloc.go to create/update them. - -// nolint: misspell -const mainnetAllocData = "\xfa\x04]X\u0793\r\x83b\x011\x8e\u0189\x9agT\x06\x908'\x80t2\x80\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0793\x17bC\x0e\xa9\u00e2nWI\xaf\xdbp\xda_x\u077b\x8c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0793\x1d\x14\x80K9\x9cn\xf8\x0edWoev`\x80O\xec\v\x89\u3bb5sr@\xa0\x00\x00\u07932@5\x87\x94{\x9f\x15b*h\xd1\x04\xd5M3\xdb\xd1\u0349\x043\x87Oc,\xc6\x00\x00\u0793I~\x92\xcd\xc0\xe0\xb9c\xd7R\xb2)j\u02c7\u0682\x8b$\x89\n\x8fd\x9f\xe7\xc6\x18\x00\x00\u0793K\xfb\xe1Tk\xc6\xc6[\\~\xaaU0K8\xbb\xfe\xc6\u04c9lk\x93[\x8b\xbd@\x00\x00\u0793Z\x9c\x03\xf6\x9d\x17\xd6l\xbb\x8a\xd7!\x00\x8a\x9e\xbb\xb86\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u0793]\x0e\xe8\x15^\xc0\xa6\xffh\bU,\xa5\xf1k\xb5\xbe2:\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u0793v\"\xd8J#K\xb8\xb0x#\x0f\u03c4\xb6z\u9a2c\xae\x89%\xe1\xccQ\x99R\xf8\x00\x00\u0793{\x9f\xc3\x19\x05\xb4\x99K\x04\xc9\xe2\xcf\xdc^'pP?B\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u0793\u007fJ#\xca\x00\xcd\x04=%\u0088\x8c\x1a\xa5h\x8f\x81\xa3D\x89)\xf0\xa9[\xfb\xf7)\x00\x00\u0793\x869\u06bb\u3bac\x88{]\xc0\xe4>\x13\xbc\u0487\xd7l\x89\x10\xd0\xe3\xc8}n,\x00\x00\u0793\x89P\x86y\xab\xf8\xc7\x1b\xf6x\x16\x87\x12\x0e>j\x84XM\x89a\x94\x04\x9f0\xf7 \x00\x00\u0793\x8f\xc7\u02ed\xff\xbd\r\u007f\xe4O\x8d\xfd`\xa7\x9dr\x1a\x1c\x9c\x8965\u026d\xc5\u07a0\x00\x00\u0793\x95`\xa3\xdebxh\xf9\x1f\xa8\xbf\xe1\xc1\xb7\xaf\xaf\b\x18k\x89\x1cg\xf5\xf7\xba\xa0\xb0\x00\x00\u0793\x96\x97G\xf7\xa5\xb3\x06E\xfe\x00\xe4I\x01CZ\xce$\xcc7\x89\\(=A\x03\x94\x10\x00\x00\u0793\x9am}\xb3&g\x9bw\xc9\x03\x91\xa7Gm#\x8f;\xa3>\x89\n\xdaUGK\x814\x00\x00\u0793\x9e\xef\n\b\x86\x05n?i!\x18S\xb9\xb7E\u007f7\x82\u4262\xa8x\x06\x9b(\xe0\x00\x00\u0793\x9f\xdb\xf4N\x1fJcb\xb7i\u00daG_\x95\xa9l+\u01c9\x1e\x93\x12\x83\xcc\xc8P\x00\x00\u07d3\xa5y\u007fR\xc9\u054f\x18\x9f6\xb1\xd4]\x1b\xf6\x04\x1f/k\x8a\x01'\u0473F\x1a\xcd\x1a\x00\x00\u0793\xaaS\x81\xb2\x13\x8e\xbe\xff\xc1\x91\xd5\xd8\u00d1u;p\x98\u04895\xab\xb0\x9f\xfe\u07b6\x80\x00\u0793\xaa\xda%\xea\"\x86p\x9a\xbbB-A\x92?\u04c0\xcd\x04\u01c9#=\xf3)\x9far\x00\x00\u0793\xac\xbf\xb2\xf2ZT\x85\xc79\xefp\xa4N\xee\xeb|e\xa6o\x89\x05k\xc7^-c\x10\x00\x00\u07d3\xac\xc6\xf0\x82\xa4B\x82\x87d\xd1\x1fX\u0589J\xe4\b\xf0s\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u0793\xb2w\xb0\x99\xa8\xe8f\xca\x0e\xc6[\u02c7(O\xd1B\xa5\x82\x89j\xcb=\xf2~\x1f\x88\x00\x00\u0753\xbd\xd4\x01:\xa3\x1c\x04al+\xc9x_'\x88\xf9\x15g\x9b\x88\xb9\xf6]\x00\xf6<\x00\x00\u0793\xc2}c\xfd\xe2K\x92\xee\x8a\x1e~\xd5\xd2m\x8d\xc5\xc8;\x03\x89lk\x93[\x8b\xbd@\x00\x00\u0553\xc4\x0f\xe2\tT#P\x9b\x9f\u0677T21X\xaf#\x10\xf3\x80\u0793\xd7^\xd6\fwO\x8b:ZQs\xfb\x183\xadq\x05\xa2\u0649l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d3\u05cd\x89\xb3_G'\x16\xec\xea\xfe\xbf`\x05'\u04e1\xf9i\x8a\x05\xe0T\x9c\x962\xe1\xd8\x00\x00\u0793\xda\xe2{5\v\xae \xc5e!$\xaf]\x8b\\\xba\x00\x1e\xc1\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u0793\xdc\x01\xcb\xf4Ix\xa4.\x8d\xe8\xe46\xed\xf9B\x05\u03f6\xec\x89O\x0f\xeb\xbc\u068c\xb4\x00\x00\u07d3\u607c-\x10\xdbb\u0785\x84\x83$I\"P4\x8e\x90\xbf\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d3\xf4c\xe17\xdc\xf6%\xfb\U000fc8de\u0298\u04b9h\xcf\u007f\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\x01\x00\a9K\x8bue\xa1e\x8a\xf8\x8c\xe4cI\x915\u05b7\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x01\r\xf1\xdfK\xed#v\r-\x1c\x03x\x15\x86\xdd\xf7\x91\x8eT\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\x01\x0fJ\x98\u07e1\xd9y\x9b\xf5\u01d6\xfbU\x0e\xfb\xe7\xec\xd8w\x8a\x01\xb2\xf2\x92#b\x92\xc7\x00\x00\u07d4\x01\x15PW\x00/k\r\x18\xac\xb98\x8d;\xc8\x12\x9f\x8fz \x89H\xa4\xa9\x0f\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01k`\xbbmg\x92\x8c)\xfd\x03\x13\xc6f\u068f\x16\x98\xd9\u0149lk\x93[\x8b\xbd@\x00\x00\u07d4\x01l\x85\xe1a;\x90\x0f\xa3W\xb8(;\x12\x0ee\xae\xfc\xdd\b\x89+]\x97\x84\xa9|\xd5\x00\x00\u07d4\x01\x84\x92H\x8b\xa1\xa2\x924\"G\xb3\x18U\xa5Y\x05\xfe\xf2i\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x01\x8f \xa2{'\xecD\x1a\xf7#\xfd\x90\x99\xf2\u02f7\x9dbc\x89uy*\x8a\xbd\xef|\x00\x00\u07d4\x01\x91\xebT~{\xf6\x97k\x9b\x1bWuFv\x1d\xe6V\"\xe2\x89lkLM\xa6\u077e\x00\x00\u07d4\x01\x9dp\x95y\xffK\xc0\x9f\xdc\xdd\xe41\xdc\x14G\xd2\xc2`\xbc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x01\xa2Z_Z\xf0\x16\x9b0\x86L;\xe4\xd7V<\xcdD\xf0\x9e\x89M\x85<\x8f\x89\b\x98\x00\x00\xe0\x94\x01\xa7\xd9\xfa}\x0e\xb1\x18\\g\xe5M\xa8<.u\xdbi\u37ca\x01\x9dJ\xdd\xd0\u063c\x96\x00\x00\u07d4\x01\xa8\x18\x13ZAB\x10\xc3|b\xb6%\xac\xa1\xa5F\x11\xac6\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\x01\xb1\xca\xe9\x1a;\x95Y\xaf\xb3<\xdcmh\x94B\xfd\xbf\xe07\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01\xb5\xb5\xbcZ\x11\u007f\xa0\x8b4\xed\x1d\xb9D\x06\bYz\xc5H\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x01\xbb\xc1Og\xaf\x069\xaa\xb1D\x1ej\b\xd4\xceqb\t\x0f\x89F\xfc\xf6\x8f\xf8\xbe\x06\x00\x00\xe0\x94\x01\xd08\x15\xc6\x1fAkq\xa2a\n-\xab\xa5\x9f\xf6\xa6\xde[\x8a\x02\x05\xdf\xe5\v\x81\xc8.\x00\x00\u07d4\x01\u0559\xee\r_\x8c8\xab-9.,e\xb7L<\xe3\x18 \x89\x1b\xa5\xab\xf9\xe7y8\x00\x00\u07d4\x01\xe4\x05!\x12%0\u066c\x91\x11<\x06\xa0\x19\vmc\x85\v\x89Hz\x9a0E9D\x00\x00\u07d4\x01\xe6A]X{\x06T\x90\xf1\xed\u007f!\xd6\xe0\xf3\x86\xeegG\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x01\xe8d\xd3Tt\x1bB>oB\x85\x17$F\x8ct\xf5\xaa\x9c\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x01\xed_\xba\x8d.\xabg:\xec\x04-0\xe4\xe8\xa6\x11\xd8\xc5Z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x01\xfb\x8e\xc1$%\xa0O\x81>F\xc5L\x05t\x8c\xa6\xb2\x9a\xa9\x89\x0e\x15s\x03\x85F|\x00\x00\u07d4\x01\xff\x1e\xb1\u07adP\xa7\xf2\xf9c\x8f\xde\xe6\xec\xcf:{*\u0209 \x86\xac5\x10R`\x00\x00\u07d4\x02\x03b\u00ed\xe8x\u0290\u05b2\u0609\xa4\xccU\x10\xee\xd5\xf3\x898\x88\xe8\xb3\x11\xad\xb3\x80\x00\u07d4\x02\x03\xae\x01\xd4\xc4\x1c\xae\x18e\xe0K\x1f[S\xcd\xfa\xec\xae1\x896\x89\xcd\u03b2\x8c\xd7\x00\x00\u07d4\x02\b\x93a\xa3\xfetQ\xfb\x1f\x87\xf0\x1a-\x86fS\xdc\v\a\x89\x02*\xc7H2\xb5\x04\x00\x00\u07d4\x02\x1fi\x04=\xe8\x8cI\x17\xca\x10\xf1\x84(\x97\xee\xc0X\x9c|\x89kD\u03f8\x14\x87\xf4\x00\x00\u07d4\x02)\x0f\xb5\xf9\xa5\x17\xf8(E\xac\xde\xca\x0f\xc8F\x03\x9b\xe23\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x029\xb4\xf2\x1f\x8e\x05\xcd\x01Q++\xe7\xa0\xe1\x8am\x97F\a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x02Gr\x12\xff\xddu\xe5\x15VQ\xb7e\x06\xb1dfq\xa1\xeb\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x02J\t\x8a\xe7\x02\xbe\xf5@l\x9c\"\xb7\x8b\xd4\xeb,\u01e2\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x02K\xdd,{\xfdP\x0e\xe7@O\u007f\xb3\xe9\xfb1\xdd \xfb\u0449\t\xc2\x00vQ\xb2P\x00\x00\u07d4\x02Sg\x96\x03\x04\xbe\xee4Y\x11\x18\xe9\xac-\x13X\xd8\x02\x1a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x02V\x14\x9f[Pc\xbe\xa1N\x15f\x1f\xfbX\xf9\xb4Y\xa9W\x89&)\xf6n\fS\x00\x00\x00\u07d4\x02`=z;\xb2\x97\xc6|\x87~]4\xfb\u0579\x13\xd4\xc6:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x02a\xad:\x17*\xbf\x13\x15\xf0\xff\xec2p\x98j\x84\t\xcb%\x89\v\b!;\u03cf\xfe\x00\x00\u07d4\x02d2\xaf7\xdcQ\x13\xf1\xf4mH\nM\u0c80R#~\x89\x13I\xb7\x86\xe4\v\xfc\x00\x00\u07d4\x02f\xab\x1ck\x02\x16#\v\x93\x95D=_\xa7^hEh\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x02u\x1d\u018c\xb5\xbdsp'\xab\xf7\u0777s\x90\xcdw\xc1k\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x02w\x8e9\x0f\xa1u\x10\xa3B\x8a\xf2\x87\fBsT}8l\x8a\x03lw\x80\x18\x8b\xf0\xef\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x037|\x0eUkd\x01\x03(\x9aa\x89\u1baecI4g\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03IcM\u00a9\xe8\f?w!\xee+PF\xae\xaa\xed\xfb\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x03U\xbc\xac\xbd!D\x1e\x95\xad\xee\xdc0\xc1r\x18\u0224\b\u0389\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x03n\xef\xf5\xba\x90\xa6\x87\x9a\x14\xdf\xf4\xc5\x04;\x18\xca\x04`\u0249\x05k\xc7^-c\x10\x00\x00\xe0\x94\x03qKA\u04a6\xf7Q\x00\x8e\xf8\xddM+)\xae\u02b8\xf3n\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x03r\xe8RX.\t44J\x0f\xed!x0M\xf2]F(\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03r\xeeU\b\xbf\x81c\xed(N^\xef\x94\xceMsg\xe5\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x03}\xd0V\xe7\xfd\xbdd\x1d\xb5\xb6\xbe\xa2\xa8x\n\x83\xfa\u1009\a\x96\xe3\xea?\x8a\xb0\x00\x00\xe0\x94\x03\x83#\xb1\x84\xcf\xf7\xa8*\xe2\u1f67y?\xe41\x9c\xa0\xbf\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x03\x87y\xca-\xbef>c\xdb?\xe7V\x83\xea\x0e\xc6.#\x83\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\x03\x8eE\xea\xdd=\x88\xb8\u007f\xe4\u06b0fh\x05\"\xf0\xdf\xc8\xf9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x03\x92T\x9ar\u007f\x81eT)\u02d2\x8bR\x9f%\xdfM\x13\x85\x89\x01lC\xa0\xee\xa0t\x00\x00\u07d4\x03\x94\xb9\x0f\xad\xb8`O\x86\xf4?\xc1\xe3]1$\xb3*Y\x89\x89)j\xa1@'\x8ep\x00\x00\u0794\x03\x9ezN\xbc(N,\xcdB\xb1\xbd\xd6\v\xd6Q\x1c\x0fw\x06\x88\xf0\x15\xf2W6B\x00\x00\u07d4\x03\x9e\xf1\xceR\xfeyc\xf1f\u0562u\u0131\x06\x9f\xe3\xa82\x89\x15\xaf9\u4ab2t\x00\x00\u07d4\x03\xa2l\xfcL\x181op\u055e\x9e\x1ay\xee>\x8b\x96/L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x03\xaab(\x81#m\xd0\xf4\x94\f$\xc3$\xff\x8b{~!\x86\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4\x03\xafz\xd9\xd5\"<\xf7\xc8\xc1? \xdfg\xeb\xe5\xff\u017bA\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x03\xb0\xf1|\xd4F\x9d\xdc\u03f7\xdai~\x82\xa9\x1a_\x9ewt\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x03\xb4\x1bQ\xf4\x1d\xf2\r\xd2y\xba\xe1\x8c\x12w_w\xadw\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x03\xbe[F)\xae\xfb\xbc\xab\x9d\xe2m9Wl\xb7\xf6\x91\xd7d\x89\n\xdf0\xbap\u0217\x00\x00\u07d4\x03\xc6G\xa9\xf9)\xb0x\x1f\xe9\xae\x01\u02a3\xe1\x83\xe8vw~\x89\x18*\xb7\xc2\f\xe5$\x00\x00\u07d4\x03\xc9\x1d\x92\x946\x03\xe7R >\x054\x0eV`\x13\xb9\x00E\x89+|\xc2\xe9\xc3\"\\\x00\x00\u07d4\x03\xcbLOE\x16\xc4\xffy\xa1\xb6$O\xbfW.\x1c\u007f\xeay\x89\x94\x89#z\u06daP\x00\x00\u07d4\x03\u02d8\u05ec\xd8\x17\u079d\x88m\"\xfa\xb3\xf1\xb5}\x92\xa6\b\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x03\u031d-!\xf8k\x84\xac\x8c\xea\xf9q\u06e7\x8a\x90\xe6%p\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\x03\xd1rO\xd0\x0eT\xaa\xbc\xd2\xde*\x91\xe8F+\x10I\xdd:\x89\x8f\x1d\\\x1c\xae7@\x00\x00\u07d4\x03\xde\xdf\xcd\v<.\x17\xc7\x05\xda$\x87\x90\uf626\xbdWQ\x89Hz\x9a0E9D\x00\x00\u07d4\x03\u8c04SuW\xe7\t\xea\xe2\xe1\u1966\xbc\xe1\xef\x83\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x03\xeam&\u0400\xe5z\xee9&\xb1\x8e\x8e\xd7:N[(&\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x03\xeb<\xb8`\xf6\x02\x8d\xa5T\xd3D\xa2\xbbZP\n\xe8\xb8o\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x03\xeb\xc6?\xdaf`\xa4e\x04^#_\xben\\\xf1\x95s_\x89\a\xb0l\xe8\u007f\xddh\x00\x00\xe0\x94\x03\xefj\xd2\x0f\xf7\xbdO\x00+\xacX\xd4uD\u03c7\x9a\xe7(\x8a\x01u\xc7X\u0439n\\\x00\x00\u07d4\x03\xf7\xb9 \b\x81:\xe0\xa6v\xeb!(\x14\xaf\xab5\"\x10i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\x11p\xf5\x81\u0780\xe5\x8b*\x04\\\x8f|\x14\x93\xb0\x01\xb7\u02c90\xc8\xeca2\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\x04i\xe8\xc4@E\v\x0eQ&&\xfe\x81~gT\xa8\x15(0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04m'K\x1a\xf6\x15\xfbPZvJ\xd8\u0767p\xb1\xdb/=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x04}Z&\u05ed\x8f\x8ep`\x0fp\xa3\x98\u076a\x1c-\xb2o\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x04~\x87\xc8\xf7\xd1\xfc\xe3\xb0\x13S\xa8Xb\xa9H\xac\x04\x9f>\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x04\u007f\x9b\xf1R\x9d\xaf\x87\xd4\a\x17^o\x17\x1b^Y\xe9\xff>\x89#<\x8f\xe4'\x03\xe8\x00\x00\xe0\x94\x04\x85'2\xb4\xc6R\xf6\xc2\u53b3e\x87\xe6\nb\xda\x14\u06ca\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x04\x8a\x89p\xeaAE\xc6MU\x17\xb8\xde[F\xd0YZ\xad\x06\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x04\x9c]K\xc6\xf2]NEli{R\xa0x\x11\xcc\u045f\xb1\x89\x10D\x00\xa2G\x0eh\x00\x00\u07d4\x04\xa1\xca\xda\x1c\xc7Q\b/\xf8\u0692\x8e<\xfa\x00\b \xa9\xe9\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x04\xa8\n\xfa\xd5>\xf1\xf8Ae\xcf\xd8R\xb0\xfd\xf1\xb1\xc2K\xa8\x89\x03$\xe9d\xb3\xec\xa8\x00\x00\u07d4\x04\xaa\xfc\x8a\xe5\xceoI\x03\u021d\u007f\xac\x9c\xb1\x95\x12\"Gw\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x04\xbaK\xb8q@\x02,!Jo\xacB\xdbZ\x16\u0755@E\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x04\xba\x8a?\x03\xf0\x8b\x89P\x95\x99M\xdaa\x9e\u06ac\xee>z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\xc2\xc6K\xb5L>\xcc\xd0U\x85\xe1\x0e\xc6\xf9\x9a\f\xdb\x01\xa3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x04\xceE\xf6\x00\xdb\x18\xa9\u0405\x1b)\xd99>\xbd\xaa\xfe=\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x04\u05b8\xd4\u0686t\a\xbb\x99wI\u07bb\xcd\xc0\xb3XS\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x04\xd78\x96\xcfe\x93\xa6\x91\x97*\x13\xa6\xe4\x87\x1f\xf2\xc4+\x13\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x04\xd8*\xf9\xe0\x1a\x93m\x97\xf8\xf8Y@\xb9p\xf9\xd4\u06d96\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x04\xe5\xf5\xbc|\x92?\xd1\xe3\x175\xe7.\xf9h\xfdg\x11\fn\x89WU\x1d\xbc\x8ebL\x00\x00\u07d4\x04\xec\xa5\x01c\n\xbc\xe3R\x18\xb1t\x95k\x89\x1b\xa2^\xfb#\x8966\x9e\xd7t}&\x00\x00\u07d4\x05\x05\xa0\x8e\"\xa1\t\x01Z\"\xf6\x850STf*U1\u0549\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\x05\x14\x95L\xe8\x81\xc807\x03d\x00\x89lO\xd1\xee$nx\x00\x00\u07d4\x05\x1dBBv\xb2\x129fQ\x86\x13=e;\xb8\xb1\x86/\x89\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x05!\xbc:\x9f\x87\x11\xfe\xcb\x10\xf5\a\x97\xd7\x10\x83\xe3A\ub749\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x05#mL\x90\xd0e\xf9\u34c3X\xaa\xff\xd7w\xb8j\xecI\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x05*X\xe05\xf1\xfe\x9c\xdd\x16\x9b\xcf \x97\x03E\xd1+\x9cQ\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x05.\xab\x1fa\xb6\xd4U\x17(?A\xd1D\x18$\x87\x87I\u0409\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x053n\x9ar'(\xd9c\xe7\xa1\xcf'Y\xfd\x02tS\x0f\u02891\xa2D?\x88\x8ay\x80\x00\u07d4\x054q\u035aA\x92[9\x04\xa5\xa8\xff\xca6Y\xe04\xbe#\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4\x056\x1d\x8e\xb6\x94\x1dN\x90\xfb~\x14\x18\xa9Z2\xd5%w2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x05B:T\xc8\xd0\xf9p~pAs\xd9#\xb9F\xed\xc8\xe7\x00\x89\x06\xea\x03\u00bf\x8b\xa5\x80\x00\u07d4\x05D\f[\a;R\x9bH) \x9d\xff\x88\t\x0e\a\xc4\xf6\xf5\x89E\u04977\xe2/ \x00\x00\u07d4\x05Z\xb6X\xc6\xf0\xedO\x87^\xd6t.K\xc7)-\x1a\xbb\xf0\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\u07d4\x05[\xd0,\xaf\x19\xd6 +\xbc\u0703m\x18{\xd1\xc0\x1c\xf2a\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x05^\xacO\x1a\xd3\xf5\x8f\v\xd0$\u058e\xa6\r\xbe\x01\u01af\xb3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x05fQU\xccI\xcb\xf6\xaa\xbd\u056e\x92\xcb\xfa\xad\x82\xb8\xc0\xc1\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x05f\x86\a\x8f\xb6\xbc\xf9\xba\n\x8a\x8d\xc6:\x90o_\xea\xc0\xea\x89\x1b\x18\x1eK\xf24<\x00\x00\u07d4\x05iks\x91k\xd3\x03>\x05R\x1e2\x11\xdf\xec\x02n\x98\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x05k\x15F\x89O\x9a\x85\xe2\x03\xfb3m\xb5i\xb1l%\xe0O\x89\t.\xdb\t\xff\b\u0600\x00\u07d4\x05yI\xe1\xca\x05pF\x9eL\xe3\u0190\xaea:k\x01\xc5Y\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x05}\u049f-\x19\xaa=\xa4#'\xeaP\xbc\xe8o\xf5\xc9\x11\u0649\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x05\u007f\u007f\x81\xcdz@o\xc4Y\x94@\x8bPI\x91,Vdc\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x05\x91]N\"Zf\x81b\xae\xe7\xd6\xc2_\xcf\xc6\xed\x18\xdb\x03\x89\x03\x98\xc3ry%\x9e\x00\x00\u07d4\x05\x96\xa2}\xc3\xee\x11_\xce/\x94\xb4\x81\xbc z\x9e&\x15%\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x05\xa80rC\x02\xbc\x0fn\xbd\xaa\x1e\xbe\xee\xb4nl\xe0\v9\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\x05\xae\u007f\u053b\u0300\xca\x11\xa9\n\x1e\u01e3\x01\xf7\xcc\u0303\u06c91T\xc9r\x9d\x05x\x00\x00\u07d4\x05\xbbd\xa9\x16\xbef\xf4`\xf5\xe3\xb6C2\x11\r \x9e\x19\xae\x89\u3bb5sr@\xa0\x00\x00\xe0\x94\x05\xbfO\xcf\xe7r\xe4[\x82dC\x85.l5\x13P\xcer\xa2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\x05\xc6@\x04\xa9\xa8&\xe9N^N\xe2g\xfa*v2\xddNo\x8a\x03m\xc4.\xbf\xf9\v\u007f\x80\x00\xe0\x94\x05\xc76\xd3e\xaa7\xb5\xc0\xbe\x9c\x12\u022d\\\xd9\x03\xc3,\xf9\x8a\x01E^{\x80\n\x86\x88\x00\x00\xe0\x94\x05\xcbl;\x00r\xd3\x11ga\xb52\xb2\x18D;S\xe8\xf6\u014a\x1e\x02\xc3\xd7\xfc\xa9\xb6(\x00\x00\u07d4\x05\xd0\xf4\xd7(\xeb\xe8.\x84\xbfYu\x15\xadA\xb6\v\xf2\x8b9\x89\u3bb5sr@\xa0\x00\x00\u07d4\x05\u058d\xada\u04fb\u07f3\xf7y&\\IGJ\xff?\xcd0\x89\x02\"\xc5]\xc1Q\x9d\x80\x00\u07d4\x05\xe6q\xdeU\xaf\xec\x96K\aM\xe5t\xd5\x15\x8d]!\xb0\xa3\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x05\xe9{\tI,\u058fc\xb1+\x89.\xd1\xd1\x1d\x15,\x0e\u02897\b\xba\xed=h\x90\x00\x00\u07d4\x05\xf3c\x1fVd\xbd\xad]\x012\xc88\x8d6\xd7\u0612\t\x18\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x06\t\xd8:l\xe1\xff\u0276\x90\xf3\xe9\xa8\x1e\x98>\x8b\xdcM\x9d\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\u07d4\x06\x1e\xa4\x87|\u0409D\xebd\u0096n\x9d\xb8\xde\xdc\xfe\xc0k\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x06%\xd0`V\x96\x8b\x00\"\x06\xff\x91\x98\x01@$+\xfa\xa4\x99\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x06(\xbf\xbeU5x/\xb5\x88@k\xc9f`\xa4\x9b\x01\x1a\xf5\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\x061\u044b\xbb\xbd0\xd9\xe1s+\xf3n\xda\xe2\u0389\x01\xab\x80\x89\xa3\xf9\x88U\xec9\x90\x00\x00\u07d4\x061\xdc@\xd7NP\x95\xe3r\x9e\xdd\xf4\x95D\xec\xd49og\x89\b\xacr0H\x9e\x80\x00\x00\xe0\x94\x067Y\xdd\x1cN6.\xb1\x93\x98\x95\x1f\xf9\xf8\xfa\xd1\xd3\x10h\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x06_\xf5u\xfd\x9c\x16\xd3\xcbo\u058f\xfc\x8fH?\xc3.\xc85\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x06a\x8e\x9dWb\xdfb\x02\x86\x01\xa8\x1dD\x87\u05a0\xec\xb8\x0e\x89Hz\x9a0E9D\x00\x00\xe0\x94\x06fG\xcf\xc8]#\xd3v\x05W= \x8c\xa1T\xb2D\xd7l\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x06xeJ\xc6v\x1d\xb9\x04\xa2\xf7\xe8Y^\xc1\xea\xacsC\b\x89/\x98\xb2\x9c(\x18\xf8\x00\x00\u07d4\x06\x86\n\x93RYU\xffbI@\xfa\xdc\xff\xb8\xe1I\xfdY\x9c\x89lh\xcc\u041b\x02,\x00\x00\xe0\x94\x06\x8c\xe8\xbdn\x90*E\u02c3\xb5\x15A\xb4\x0f9\xc4F\x97\x12\x8a\x01\x1c\x0f\x9b\xadJF\xe0\x00\x00\u07d4\x06\x8e)\xb3\xf1\x91\xc8\x12\xa699\x18\xf7\x1a\xb93\xaehG\xf2\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x06\x8eeWf\xb9D\xfb&6\x19e\x87@\xb8P\xc9J\xfa1\x89\x01\xe8\u007f\x85\x80\x9d\xc0\x00\x00\u0794\x06\x96N-\x17\xe9\x18\x9f\x88\xa8 96\xb4\n\xc9nS<\x06\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x06\x99L\xd8:\xa2d\n\x97\xb2`\vA3\x9d\x1e\r>\xdel\x89\r\x8drkqw\xa8\x00\x00\u07d4\x06\x9e\u042bz\xa7}\xe5q\xf1a\x06\x05\x1d\x92\xaf\xe1\x95\xf2\u0409\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x06\xac&\xad\x92\u02c5\x9b\u0550]\xdc\xe4&j\xa0\xecP\xa9\u0149*\x03I\x19\u07ff\xbc\x00\x00\u07d4\x06\xb0\xc1\xe3\u007fZ^\u013b\xf5\b@T\x8f\x9d:\xc0(\x88\x97\x89\xd8\u0602\u148e}\x00\x00\u07d4\x06\xb0\xff\x83@s\xcc\xe1\xcb\xc9\xeaU~\xa8{`Yc\u8d09\x10CV\x1a\x88)0\x00\x00\xe0\x94\x06\xb1\x06d\x9a\xa8\xc4!\xdd\xcd\x1b\x8c2\xcd\x04\x18\xcf0\xda\x1f\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x06\xb5\xed\xe6\xfd\xf1\xd6\xe9\xa3G!7\x9a\xea\xa1|q=\xd8*\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x06\xcb\xfa\b\xcd\xd4\xfb\xa77\xba\xc4\a\xbe\x82$\xf4\xee\xf3X(\x89 +\xe5\xe88.\x8b\x80\x00\u07d4\x06\xd6\xcb0\x84\x81\xc36\xa6\xe1\xa2%\xa9\x12\xf6\xe65Y@\xa1\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x06\xdc\u007f\x18\xce\xe7\xed\xab[yS7\xb1\xdfj\x9e\x8b\u062eY\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x06\xf6\x8d\xe3\xd79\xdbA\x12\x1e\xac\xf7y\xaa\xda=\xe8v!\a\x89\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\x06\xf7\u070d\x1b\x94b\xce\xf6\xfe\xb13h\xa7\xe3\x97K\t\u007f\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\a\x01\xf9\xf1G\xecHhV\xf5\xe1\xb7\x1d\xe9\xf1\x17\xe9\x9e!\x05\x89\te\xdaq\u007f\u0578\x00\x00\u07d4\a\r]6L\xb7\xbb\xf8\"\xfc,\xa9\x1a5\xbd\xd4A\xb2\x15\u0549lk\x93[\x8b\xbd@\x00\x00\xe0\x94\a\x1d\xd9\r\x14\xd4\x1fO\xf7\xc4\x13\xc2B8\xd35\x9c\xd6\x1a\a\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\u07d4\a&\xc4.\x00\xf4T\x04\x83n\xb1\xe2\x80\xd0s\xe7\x05\x96\x87\xf5\x89X\x00>?\xb9G\xa3\x80\x00\xe0\x94\a'\xbe\n*\x00! H\xb5R\x0f\xbe\xfb\x95>\xbc\x9dT\xa0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\a)\xa8\xa4\xa5\xba#\xf5y\xd0\x02[\x1a\xd0\xf8\xa0\xd3\\\xdf\u048a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4\a)\xb4\xb4|\t\xeb\x16\x15\x84d\u022a\u007f\xd9i\vC\x889\x89lh\xcc\u041b\x02,\x00\x00\u0794\a4\xa0\xa8\x1c\x95b\xf4\xd9\xe9\xe1\n\x85\x03\xda\x15\xdbF\xd7n\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\a\xa7\xef[G\x00\x00\xe0\x94\ap\xc6\x1b\xe7\x87r#\f\xb5\xa3\xbb$)\xa7&\x14\xa0\xb36\x8a\x01n\u0899\xb7\x13A\x80\x00\u07d4\ar><0\xe8\xb71\xeeEj)\x1e\xe0\u7630 Jw\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\as\xee\xac\xc0P\xf7G \xb4\xa1\xbdW\x89[\x1c\xce\xebI]\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\a\x80\r/\x80h\xe4H\u01daOi\xb1\xf1^\xf6\x82\xaa\xe5\xf6\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\a\xa8\xda\xde\xc1BW\x1a}S\xa4)pQxm\a,\xbaU\x89\x01;m\xa1\x13\x9b\u0680\x00\u07d4\a\xaf\x93\x8c\x127\xa2|\x900\tM\xcf$\aP$n=,\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\a\xb1\xa3\x06\xcbC\x12\xdffH,,\xaer\xd1\xe0a@\x0f\u034a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\a\xb7\xa5p3\xf8\xf1\x130\xe4f^\x18]#N\x83\xec\x14\v\x89\xea~\xe9*\f\x9a\v\x80\x00\u07d4\a\xbc,\xc8\xee\xdc\x01\x97\a\x00\xef\xc9\xc4\xfb6s^\x98\xcdq\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\a\xd4\x12\x17\xba\u0725\xe0\xe6\x03'\xd8E\xa3FO\x0f'\xf8J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\a\xd43N\u00c5\xe8\xaaT\xee\xda\xea\xdb0\x02/\f\u07e4\xab\x89\x8e\x91\xd5 \xf2\xeby\x00\x00\u07d4\a\xda\xe6\"c\r\x1168\x193\u04adk\"\xb89\xd8!\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\a\xdc+\xf8;\u01af\x19\xa8B\xff\xeaf\x1a\xf5\xb4\x1bg\xfd\xa1\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\a\u070c\x8b\x92z\xdb\xed\xfa\x8f]c\x9bCR5\x1f/6\u0489\x11\n\xed;U0\xdb\x00\x00\u07d4\a\xdd\xd0B,\x86\xefe\xbf\f\u007f\xc3E(b\xb1\"\x8b\b\xb8\x89o\xf5\u04aa\x8f\x9f\xcf\x00\x00\u07d4\a\xe1\x16,\xea\xe3\xcf!\xa3\xf6-\x10Y\x900.0\u007fN;\x89R\xf1\x03\xed\xb6k\xa8\x00\x00\u07d4\a\xe2\xb4\xcd\xee\xd9\u0407\xb1.Um\x9ew\f\x13\xc0\x99a_\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\a\xfe\xefT\xc16\x85\b)\xba\xdcKI\xc3\xf2\xa7<\x89\xfb\x9e\x89\x06hZ\xc1\xbf\xe3,\x00\x00\u07d4\b\x05FP\x8a=&\x82\u0239\x88O\x13c{\x88G\xb4M\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\t\bv\xba\xad\xfe\xe6\\=6;\xa5S\x12t\x8c\xfa\x87=\x89\\*\x997\x1c\xff\xe1\x00\x00\u07d4\b\x16o\x021?\xea\u12f0D\xe7\x87|\x80\x8bU\xb5\xbfX\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\b)\xd0\xf7\xbb|Dl\xfb\xb0\u07ad\xb29M\x9d\xb7$\x9a\x87\x89\x02,\xa3X|\xf4\xeb\x00\x00\u07d4\b0m\xe5\x19\x81\u7b21\x85hY\xb7\xc7xijki\xf9\x89\xadx\xeb\u016cb\x00\x00\x00\xe0\x94\b7S\x9b_jR*H,\xdc\u04e9\xbbpC\xaf9\xbd\u048a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\b8\xa7v\x8d\x9c*\u028b\xa2y\xad\xfe\xe4\xb1\xf4\x91\xe3&\xf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\bA\x16R\xc8qq6\t\xaf\x00b\xa8\xa1(\x1b\xf1\xbb\xcf\u0649K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\bM\x102Tu\x9b4<\xb2\xb9\xc2\xd8\xff\x9e\x1a\xc5\xf1E\x96\x8a\x01\x9b\xff/\xf5yh\xc0\x00\x00\u07d4\bPO\x05d?\xabY\x19\xf5\xee\xa5Y%\u05e3\xed}\x80z\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\b[J\xb7]\x83b\xd9\x14C\\\xed\xee\x1d\xaa+\x1e\xe1\xa2;\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\b[\xa6_\xeb\xe2>\xef\xc2\xc8\x02fj\xb1&#\x82\xcf\u0114\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\bt\x98\xc0FFh\xf3\x11P\xf4\xd3\u013c\u0765\"\x1b\xa1\x02\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\bw\uebabx\xd5\xc0\x0e\x83\xc3+-\x98\xfay\xadQH/\x89\x17\xd2-q\xdab&\x00\x00\u0794\b\x93j7\u07c5\xb3\xa1X\xca\xfd\x9d\xe0!\xf5\x817h\x13G\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\b\xa9\xa4N\x1fA\xde=\xbb\xa7\xa3c\xa3\xabA,\x12L\xd1^\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\b\xb7\xbd\u03d4MUp\x83\x8b\xe7\x04`$:\x86\x94HXX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xb8E6\xb7L\x8c\x01T=\xa8\x8b\x84\u05cb\xb9WG\xd8\"\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\b\xc2\xf26\xacJ\xdc\xd3\xfd\xa9\xfb\xc6\xe4S\"S\xf9\xda;\xec\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\b\xc8\x02\xf8wX4\x9f\xa0>k\xc2\xe2\xfd\a\x91\x19~\ua689lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xc9\U0007fd89\xfd\xf8\x04\xd7i\xf8!#6\x02\x15\xaf\xf9;\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\b\xca\u0215&A\xd8\xfcRn\xc1\xabO-\xf8&\xa5\xe7q\x0f\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\b\xcc\xdaP\xe4\xb2j\x0f\xfc\x0e\xf9.\x92\x051\a\x06\xbe\xc2\u01ca\x01Iul8W\xc6\x00\x00\x00\u07d4\b\u0406M\xc3/\x9a\xcb6\xbfN\xa4G\xe8\xddg&\x90j\x15\x89lnY\xe6|xT\x00\x00\u07d4\b\xd4&\u007f\xeb\x15\u0697\x00\xf7\xcc\xc3\xc8J\x89\x18\xbf\x17\xcf\u0789a\t=|,m8\x00\x00\xe0\x94\b\xd41\x1c\x9c\x1b\xba\xf8\u007f\xab\xe1\xa1\xd0\x14c\x82\x8d]\x98\u038a\x13\x0e\xe8\xe7\x17\x90D@\x00\x00\u07d4\b\xd5N\x83\xadHj\x93L\xfa\xea\u20e3>\xfd\"|\x0e\x99\x898S\x05\x83$^\xdc\x00\x00\u07d4\b\xd9~\xad\xfc\xb7\xb0d\xe1\xcc\xd9\u0217\x9f\xbe\xe5\xe7z\x97\x19\x89\x0el]\xa8\xd6z\xc1\x80\x00\u07d4\b\xda:z\x0fE!a\u03fc\xec1\x1b\xb6\x8e\xbf\xde\xe1~\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\b\xe3\x8e\xe0\xceH\xc9\xcad\\\x10\x19\xf7;SUX\x1cV\xe6\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\b\xef?\xa4\xc4<\xcd\xc5{\"\xa4\xb9\xb23\x1a\x82\xe58\x18\xf2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\t\td\x8c\x18\xa3\xce[\xaez\x04~\xc2\xf8h\xd2L\u0768\x1d\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\t\f\xd6{`\xe8\x1dT\xe7\xb5\xf6\a\x8f>\x02\x1b\xa6[\x9a\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\f\xeb\xef),>\xb0\x81\xa0_\u062a\xf7\u04db\xf0{\x89\u0509\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\t\x0f\xa96{\xdaW\xd0\xd3%:\n\x8f\xf7l\xe0\xb8\xe1\x9as\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\x14n\xa3\x88Qv\xf0w\x82\xe1\xfe0\xdc\xe3\xce$\u011e\x1f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\t!`_\x99\x16N;\xcc(\xf3\x1c\xae\xcex\x971\x82V\x1d\x89+\ai*\x90e\xa8\x00\x00\xe0\x94\t&\x1f\x9a\xcbE\x1c7\x88\x84O\f\x14Q\xa3[\xadP\x98\xe3\x8a\x01\u056d'P) `\x00\x00\xe0\x94\t'\"\x04\x92\x19K.\u069f\u013b\xe3\x8f%\u0581\xdf\xd3l\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\t*\xcbbK\b\xc0U\x10\x18\x9b\xbb\xe2\x1ee$\xd6D\u032d\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\t.\x81UX@-g\xf9\rk\xfem\xa0\xb2\xff\xfa\x91EZ\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\tP0\xe4\xb8&\x92\xdc\xf8\xb8\u0411$\x94\xb9\xb3x\xec\x93(\x89H\xa4zu\x80\x00\u07d4\t\x89\xc2\x00D\v\x87\x89\x91\xb6\x9d`\x95\xdf\xe6\x9e3\xa2.p\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\t\x90\xe8\x1c\u05c5Y\x9e\xa26\xbd\x19f\xcfRc\x02\xc3[\x9c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\t\x98\xd8'1\x15\xb5j\xf4%\xff\xc8>!\x8c\x1e\n\xfe\x89(\u01c8\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\t\xaeI\xe3\u007f\x12\x1d\xf5\xdc\x15\x8c\xfd\xe8\x06\xf1s\xa0k\f\u007f\x89\xd80\x9e&\xab\xa1\xd0\x00\x00\u07d4\t\xaf\xa7;\xc0G\xefF\xb9w\xfd\x97c\xf8r\x86\xa6\xbeh\u0189\x1b/\xb5\xe8\xf0jf\x00\x00\u07d4\t\xb4f\x86\x96\xf8j\b\x0f\x8b\xeb\xb9\x1d\xb8\xe6\xf8p\x15\x91Z\x89#\x8f\xf7\xb3O`\x01\x00\x00\xe0\x94\t\xb5\x9b\x86\x98\xa7\xfb\xd3\xd2\xf8\xc7:\x00\x89\x88\xde>@k+\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94\t\xb7\xa9\x88\xd1?\xf8\x91\x86so\x03\xfd\xf4au\xb5=\x16\xe0\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\t\xc1w\xf1\xaeD$\x11\u076c\xf1\x87\xd4m\xb9V\x14\x83`\xe7\x8a\x01\xe5.3l\xde\"\x18\x00\x00\xe0\x94\t\u020f\x91~Mj\xd4s\xfa\x12\u93a3\xc4G*^\xd6\u068a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\t\u0438\xcd\a|i\xd9\xf3-\x9c\xcaC\xb3\xc2\b\xa2\x1e\u050b\x89\b!\xd2!\xb5)\x1f\x80\x00\xe0\x94\t\xd6\xce\xfdu\xb0\u0133\xf8\xf1\u0587\xa5\"\xc9a#\xf1\xf59\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\t\xe47\xd4H\x86\x12(\xa22\xb6.\xe8\xd3ye\xa9\x04\ud70a\x04\x98\xcf@\x1d\xf8\x84.\x80\x00\u07d4\t\xee\x12\xb1\xb4+\x05\xaf\x9c\xf2\a\xd5\xfc\xac%[.\xc4\x11\xf2\x89\x031\xcd\xddG\xe0\xfe\x80\x00\u07d4\t\xf3\xf6\x01\xf6\x05D\x11@Xl\xe0eo\xa2J\xa5\xb1\u066e\x89Sswo\xe8\xc4T\x00\x00\u07d4\t\xf9W[\xe5}\x00G\x93\u01e4\ub137\x15\x87\xf9|\xbbj\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n\x06P\x86\x1fx^\xd8\xe4\xbf\x10\x05\xc4P\xbb\xd0n\xb4\x8f\xb6\x89\xa6A;y\x14N~\x00\x00\u07d4\n\x06\xfa\xd7\xdc\u05e4\x92\xcb\xc0S\xee\xab\xdei4\xb3\x9d\x867\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\n\a}\xb1?\xfe\xb0\x94\x84\xc2\x17p\x9dX\x86\xb8\xbf\x9cZ\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\n\x0e\u0366cow\x16\xef\x19saF\x87\xfd\x89\xa8 \xa7\x06\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\n)\xa8\xa4\xd5\xfd\x95\x00u\xff\xb3Mw\xaf\xeb-\x82;\u0589\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n*\u0795\xb2\xe8\xc6m\x8a\xe6\xf0\xbad\xcaW\u05c3\xbemD\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\n+O\xc5\xd8\x1a\xceg\xdcK\xba\x03\xf7\xb4UA=F\xfe=\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\n-\xcbzg\x17\x01\u06f8\xf4\x95r\x80\x88&Xs5l\x8e\x89\b?\x16\xce\b\xa0l\x00\x00\u07d4\n=\xe1U\xd5\xec\xd8\xe8\x1c\x1f\xf9\xbb\xf07\x83\x01\xf8\xd4\xc6#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\nG\xad\x90Y\xa2I\xfc\x93k&b5=\xa6\x90_u\u00b9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\nH)ov1p\x8c\x95\u04b7Iu\xbcJ\xb8\x8a\xc19*\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\nJ\x01\x19\x95\u0181\xbc\x99\x9f\xddyuN\x9a2J\xe3\xb3y\x8a\b\xc1\x9a\xb0n\xb8\x9a\xf6\x00\x00\u07d4\nX\xfd\xddq\x89\x8d\xe7s\xa7O\xda\xe4^{\xd8N\xf46F\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\n[y\xd8\xf2;d\x83\xdb\u2f6ab\xb1\x06L\xc7cf\xae\x89j\u0202\x10\tR\u01c0\x00\u07d4\ne.*\x8bw\xbd\x97\xa7\x90\xd0\xe9\x13a\u0248\x90\u06f0N\x8965\u026d\xc5\u07a0\x00\x00\u07d4\nn\xber;n\xd1\xf9\xa8ji\xdd\xdah\xdcGF\\+\x1b\x89@=-\xb5\x99\xd5\xe4\x00\x00\u07d4\nw\xe7\xf7+C{WO\x00\x12\x8b!\xf2\xac&Q3R\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\n\x91\u007f;\\\xb0\xb8\x83\x04\u007f\u0676Y=\xbc\xd5W\xf4S\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\n\x93\x1bD\x9e\xa8\xf1,\xdb\xd5\xe2\xc8\xccv\xba\xd2\xc2|\x069\x89\x01?\x9e\x8cy\xfe\x05\x80\x00\u0794\n\x98\x04\x13x\x03\xbahh\xd9:U\xf9\x98_\xcdT\x04Q\u4239\x8b\xc8)\xa6\xf9\x00\x00\u07d4\n\x9a\xb2c\x8b\x1c\xfdeM%\u06b0\x18\xa0\xae\xbd\u07c5\xfdU\x89\x01.\x8c\xb5\xfeLJ\x80\x00\u07d4\n\xb3f\xe6\xe7\u056b\xbc\xe6\xb4JC\x8di\xa1\u02bb\x90\xd13\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\n\xb4(\x1e\xbb1\x85\x90\xab\xb8\x9a\x81\xdf\a\xfa:\xf9\x04%\x8a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\n\xb5\x9d9\a\x02\xc9\xc0Y\xdb\x14\x8e\xb4\xf3\xfc\xfa}\x04\xc7\xe7\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\n\xbf\xb3\x9b\x11HmyW(f\x19[\xa2lc\vg\x84\u06ca\x19\xba\x877\xf9i(\xf0\x00\x00\u07d4\n\u029aV&\x91;\b\xcf\u0266m@P\x8d\xceR\xb6\x0f\x87\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\n\xd3\xe4M<\x00\x1f\xa2\x90\xb3\x93ap0TA\b\xacn\xb9\x89j\xbd\xa0\xbc0\xb2\u07c0\x00\u07d4\n\xec.Bn\xd6\xcc\f\xf3\xc2I\xc1\x89~\xacG\xa7\xfa\xa9\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\n\xf6_\x14xNU\xa6\xf9Vg\xfds%*\x1c\x94\a-*\x89\nv;\x8e\x02\xd4O\x80\x00\u07d4\n\xf6\xc8\xd59\xc9mP%\x9e\x1b\xa6q\x9e\x9c\x80`\xf3\x88\u008965\u026d\xc5\u07a0\x00\x00\u07d4\v\x069\x0f$7\xb2\x0e\u0123\xd3C\x1b2y\xc6X>^\u05c9\n\x84Jt$\xd9\xc8\x00\x00\u07d4\v\v8b\x11*\xee\u00e04\x92\xb1\xb0_D\x0e\xcaT%n\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\v\x0e\x05[(\xcb\xd0=\xc5\xffD\xaad\xf3\xdc\xe0O^c\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\x11\x9d\xf9\x9ck\x8d\xe5\x8a\x1e,?)zgD\xbfU\"w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\x14\x89\x19\x99\xa6\\\x9e\xf73\b\xef\xe3\x10\f\xa1\xb2\x0e\x81\x92\x89+^:\xf1k\x18\x80\x00\x00\u07d4\v!\x13PE4d*\x1d\xaf\x10.\xee\x10\xb9\xeb\xdev\xe2a\x89\x94,\xdd|\x95\xf2\xbd\x80\x00\xe0\x94\v(\x8aZ\x8bu\xf3\xdcA\x91\xeb\x04W\xe1\xc8=\xbd M%\x8a\x01\a\x14\xe7{\xb4:\xb4\x00\x00\u07d4\v6\x9e\x00.\x1bLy\x13\xfc\xf0\x0f-^\x19\u0141eG\x8f\x89\x03\u007fe\x16(\x8c4\x00\x00\u07d4\vC\xbd#\x91\x02U\x81\u0615l\xe4*\a%y\u02ff\xcb\x14\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u07d4\vP|\xf5SV\x8d\xaa\xf6U\x04\xaeN\xaa\x17\xa8\xea<\xdb\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v]f\xb1<\x87\xb3\x92\xe9M\x91\xd5\xf7l\rE\nU(C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v^ \x11\xeb\xc2Z\x00\u007f!6)`I\x8a\xfb\x8a\xf2\x80\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vd\x9d\xa3\xb9j\x10,\xdcm\xb6R\xa0\xc0}e\xb1\xe4C\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vi \xa6K6;\x8d]\x90\x80$\x94\xcfVKT|C\r\x89A\rXj \xa4\xc0\x00\x00\u07d4\vp\x11\x01\xa4\x10\x9f\x9c\xb3`\xdcW\xb7tBg=^Y\x83\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\vq\xf5T\x12$i\uf5ce/\x1f\xef\xd7\u02f4\x10\x98'r\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\xe0\x94\v{\xb3B\xf0\x1b\u0248\x8ej\x9a\xf4\xa8\x87\xcb\xf4\xc2\xdd,\xaf\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\v}3\x93q\xe5\xbeg'\xe6\xe31\xb5\x82\x1f\xa2K\u06ddZ\x89.\u007f\x81\x86\x82b\x01\x00\x00\u07d4\v\u007f\xc9\xdd\xf7\x05v\xf63\x06i\xea\xaaq\xb6\xa81\xe9\x95(\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\v\x80\xfcp(,\xbd\xd5\xfd\xe3[\xf7\x89\x84\xdb;\xdb\x12\x01\x88\x8968\x02\x1c\xec\u06b0\x00\x00\u07d4\v\x92M\xf0\a\xe9\xc0\x87\x84\x17\xcf\xe6;\x97n\xa1\xa3\x82\xa8\x97\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\v\x93\xfc\xa4\xa4\xf0\x9c\xac \xdb`\xe0e\xed\xcc\xcc\x11\u0976\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\v\x9d\xf8\x0f\xbe# \t\xda\xcf\n\xa8\xca\u0153v\xe2Gb\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xa6\xe4j\xf2Z\x13\xf5qi%Z4\xa4\xda\xc7\xce\x12\xbe\x04\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\v\xa8p[\xf5\\\xf2\x19\xc0\x95k^?\xc0\x1cDt\xa6\xcd\xc1\x89\x05%\xe0Y]Mk\x80\x00\u07d4\v\xafn\u0379\x1a\xcb6\x06\xa85|\v\xc4\xf4\\\xfd-~o\x8965\u026d\xc5\u07a0\x00\x00\u07d4\v\xb0_r$\xbbX\x04\x85eV\xc0~\xea\xdb\ud1fa\x8f|\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\v\xb0\xc1&\x82\xa2\xf1\\\x9bWA\xb28\\\xbeA\xf04\x06\x8e\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\v\xb2\\\xa7\u0448\xe7\x1eMi={\x17\a\x17\xd6\xf8\xf0\xa7\n\x89\x12C\x02\xa8/\xad\xd7\x00\x00\u07d4\v\xb2e\x0e\xa0\x1a\xcau[\xc0\xc0\x17\xb6K\x1a\xb5\xa6m\x82\xe3\x89Hz\x9a0E9D\x00\x00\u07d4\v\xb5Lr\xfdf\x10\xbf\xa463\x97\xe0 8K\x02+\fI\x89Hz\x9a0E9D\x00\x00\u07d4\v\xb7\x16\n\xba)7b\xf8sO>\x03&\xff\u0264\xca\xc1\x90\x8965\u026d\xc5\u07a0\x00\x00\u07d4\v\xc9\\\xb3-\xbbWL\x83/\xa8\x17J\x815m8\xbc\x92\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xd6}\xbd\xe0z\x85n\xbd\x89;^\xdcO:[\xe4 &\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xdb\xc5L\u023d\xbb\xb4\x02\xa0\x89\x11\xe2#*T`\u0386k\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\v\xddX\xb9n|\x91m\xd2\xfb05o*\xeb\xfa\xaf\x1d\x860\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\v\u1f39\x03C\xfa\xe501s\xf4a\xbd\x91JH9\x05l\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\v\xe1\xfd\xf6&\xeea\x89\x10-p\xd1;1\x01,\x95\xcd\x1c\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\v\xe2\xb9J\xd9P\xa2\xa6&@\xc3[\xfc\xcdlg\xda\xe4P\xf6\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\v\u681eC\a\xfeH\xd4\x12\xb8\u0461\xa8(M\xceHba\x8a\x04\x0f\xbf\xf8\\\x0180\x00\x00\u07d4\v\xef\xb5G\a\xf6\x1b,\x9f\xb0G\x15\xab\x02n\x1b\xb7 B\xbd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\v\xf0dB\x8f\x83bg\"\xa7\xb5\xb2j\x9a\xb2\x04!\xa7r>\x89\a?u\u0460\x85\xba\x00\x00\u07d4\v\xfb\xb6\x92]\xc7^R\xcf&\x84\"K\xbe\x05P\xfe\xa6\x85\u04c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\f\b\x80\x06\xc6K0\xc4\u076f\xbc6\xcb_\x05F\x9e\xb6(4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f s\xbaD\xd3\u077d\xb69\xc0N\x19\x109\xa7\x17\x16#\u007f\x89M\x85<\x8f\x89\b\x98\x00\x00\xe0\x94\f\",|A\u0270H\xef\xcc\xe0\xa22CCb\xe1-g;\x8a\x02\x1e\x83Yivw8\x00\x00\xe0\x94\f(\b\xb9Q\ud787-{2y\x0f\xccY\x94\xaeA\xff\u070a\x15\x99n[<\u05b3\xc0\x00\x00\u07d4\f(\x84~O\t\xdf\xce_\x9b%\xaf|NS\x0fY\u0200\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f-\\\x92\x058\xe9S\u02af$\xf0s\u007fUL\u0192wB\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f0\xca\xcc?r&\x9f\x8bO\x04\xcf\a=+\x05\xa8=\x9a\u0449lyt\x12?d\xa4\x00\x00\u07d4\f29\xe2\xe8A$-\xb9\x89\xa6\x15\x18\xc2\"G\xe8\xc5R\b\x89\x0eJ\xf6G\x174d\x00\x00\xe0\x94\fH\r\xe9\xf7F\x10\x02\x90\x8bI\xf6\x0f\xc6\x1e+b\xd3\x14\v\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\fH\xaeb\xd1S\x97\x88\xeb\xa0\x13\xd7^\xa6\vd\xee\xbaN\x80\x89w\xfb\xdcC\xe00\x99\x80\x00\u07d4\fU\x89\xa7\xa8\x9b\x9a\xd1[\x02u\x190AYH\xa8u\xfb\xef\x89\x06\u0519\xeclc8\x00\x00\u07d4\fg\x03=\xd8\xee\u007f\f\x8a\xe54\xd4*Q\xf7\xd9\xd4\xf7\x97\x8f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\fhE\xbfA\xd5\xee'<>\u6d70\u059fo\xd5\xea\xbb\xf7\x89\xa2\xa1\xb9h.X\t\x00\x00\xe0\x94\f\u007f\x86\x9f\x8e\x90\xd5?\xdc\x03\u8c81\x9b\x01k\x9d\x18\xeb&\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\f\x86\x92\xee\xff*S\xd6\xd1h\x8e\xd5j\x9d\u06fdh\u06bb\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f\x8ff\xc6\x01{\xce[ 4r\x04\xb6\x02\xb7C\xba\u05cd`\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\f\x8f\xd7w^T\xa6\xd9\u0263\xbf\x89\x0ev\x1fewi?\xf0\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\f\x92Z\xd5\xeb5,\x8e\xf7m\f\"-\x11[\a\x91\xb9b\xa1\x89\xacc]\u007f\xa3N0\x00\x00\u07d4\f\x96~0a\xb8zu>\x84P~\xb6\t\x86x,\x8f0\x13\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\f\xa1*\xb0\xb9fl\xf0\xce\xc6g\x1a\x15)/&SGj\xb2\x8a,x'\xc4-\"\xd0|\x00\x00\u07d4\f\xa6p\xeb,\x8b\x96\u02e3y!\u007fY)\u00b8\x92\xf3\x9e\xf6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\f\xae\x10\x8em\xb9\x9b\x9ecxv\xb0d\xc60>\u068ae\u0209\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\f\xbd\x92\x1d\xbe\x12\x15c\xb9\x8ahq\xfe\xcb\x14\xf1\xcc~\x88\u05c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\f\xbf\x87p\xf0\xd1\b.\\ \u016e\xad4\xe5\xfc\xa9\xaez\xe2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\f\xc6\u007f\x82s\xe1\xba\xe0\x86\u007f\xd4.\x8b\x81\x93\xd7&y\xdb\xf8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\f\u05a1A\x91\x8d\x12k\x10m\x9f.\xbfi\xe1\x02\xdeM2w\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\f\xda\x12\xbfr\xd4a\xbb\xc4y\xeb\x92\xe6I\x1d\x05~kZ\u044a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\f\u0716\v\x99\x8c\x14\x19\x98\x16\r\xc1y\xb3l\x15\u0484p\xed\x89\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\f\xfb\x17#5\xb1l\x87\xd5\x19\xcd\x14uS\r W\u007f^\x0e\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\r\x1f*Wq>\xbcn\x94\xde)\x84n\x88D\xd3vfWc\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\r2e\xd3\u7f79=^\x8e\x8b\x1c\xa4\u007f!\ny>\u030e\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\r5@\x8f\"ef\x11o\xb8\xac\u06a9\xe2\xc9\u055bvh?\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\rU\x1e\xc1\xa2\x13<\x98\x1d_\u01a8\xc8\x17?\x9e|OG\xaf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r]\x98V\\d|\xa5\xf1w\xa2\xad\xb9\xd3\x02/\xac(\u007f!\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\re\x80\x14\xa1\x99\x06\x1c\xf6\xb3\x943\x14\x03\x03\xc2\x0f\xfdNZ\x8a\x01\xbc\x85\xdc*\x89\xbb \x00\x00\u07d4\rg\x87\x06\xd07\x18\u007f>\"\xe6\xf6\x9b\x99\xa5\x92\xd1\x1e\xbcY\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\ri\x10\f9\\\xe6\xc5\xea\xad\xf9]\x05\xd8r\x83~\xde\xdd!\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\rt~\u559b\xf7\x9dW8\x1do\xe3\xa2@l\xd0\xd8\xce'\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\r\x80#\x92\x9d\x91r4\xae@Q+\x1a\xab\xb5\xe8\xa4Q'q\x89\b\x05\xe9\x9f\xdc\xc5\xd0\x00\x00\xe0\x94\r\x8a\xab\x8ft\xea\x86,\xdfvh\x05\x00\x9d?>B\xd8\xd0\v\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\r\x8c@\xa7\x9e\x18\x99O\xf9\x9e\xc2Q\xee\x10\u0408\u00d1.\x80\x89\x066d\xfc\u04bb\xc4\x00\x00\u07d4\r\x8e\xd7\xd0\xd1V83\x0e\xd7\xe4\xea\u032b\x8aE\x8dus~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r\x92X/\u06e0^\xab\xc3\xe5\x158\xc5m\xb8\x817\x85\xb3(\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\r\x94C\xa7\x94h\xa5\xbb\xf7\xc1\xe5\xb9\x15\xb3d\x87\xf9\x16\x1f\x19\x84m\x10\x1431\x8a\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\r\xbdA|7+\x8b\r\x01\xbc\xd9Dpk\xd3.`\xae(\u0449\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\r\xc1\x00\xb1\a\x01\x1c\u007f\xc0\xa13\x96\x12\xa1l\xce\xc3(R\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\r\u03dd\x8c\x98\x04E\x9fd|\x14\x13\x8e\xd5\x0f\xadV;AT\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4\r\xcf\xe87\xea\x1c\xf2\x8ce\xfc\xce\u00fe\xf1\xf8NY\xd1P\xc0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\r\xd4\xe6t\xbb\xad\xb1\xb0\u0702D\x98q=\xce;QV\xda)\x89\t79SM(h\x00\x00\u07d4\r\xfb\u0501pP\xd9\x1d\x9db\\\x02\x05<\xf6\x1a>\xe2\x85r\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\x0e\x02N\u007f\x02\x9cj\xaf:\x8b\x91\x0f^\b\bs\xb8W\x95\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0e\tdl\x99\xafC\x8e\x99\xfa'L\xb2\xf9\xc8V\xcbe\xf76\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x0e\f\x9d\x00^\xa0\x16\u0095\xcdy\\\xc9!>\x87\xfe\xbc3\xeb\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\x0e\rf3\xdb\x1e\f\u007f#Jm\xf1c\xa1\x0e\n\xb3\x9c \x0f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x0e\x11\xd7z\x89w\xfa\xc3\r&\x84E\xe51\x14\x9b1T\x1a$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\x12=}\xa6\xd1\xe6\xfa\xc2\u072d\xd2p)$\v\xb3\x90R\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0e\x18\x01\xe7\vbb\x86\x1b\x114\u033c9\x1fV\x8a\xfc\x92\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x0e \x94\xac\x16T\xa4k\xa1\xc4\u04e4\v\xb8\xc1}\xa7\U000d6209\x13h?\u007f<\x15\xd8\x00\x00\u07d4\x0e!\xaf\x1b\x8d\xbf'\xfc\xf6?7\xe0G\xb8z\x82\\\xbe|'\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x0e.PJ-\x11\"\xb5\xa9\xfe\xee\\\xb1E\x1b\xf4\u00ac\xe8{\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x0e/\x8e(\xa6\x81\xf7|X;\xd0\xec\xde\x16cK\xdd~\x00\u0349\x05'8\xf6Y\xbc\xa2\x00\x00\u07d4\x0e2\x02\x19\x83\x8e\x85\x9b/\x9f\x18\xb7.=@s\xcaP\xb3}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e3\xfc\xbb\xc0\x03Q\v\xe3W\x85\xb5*\x9c]!k\xc0\x05\xf4\x89e\xea=\xb7UF`\x00\x00\u07d4\x0e6\x96\xcf\x1fB\x17\xb1c\u047c\x12\xa5\xeas\x0f\x1c2\xa1J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x0e9\x0fD\x05=\xdf\xce\xf0\xd6\b\xb3^M\x9c,\xbe\x98q\xbb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x0e:(\xc1\u07ef\xb0P[\xdc\xe1\x9f\xe0%\xf5\x06\xa6\xd0\x1c\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e=\xd7\xd4\xe4)\xfe90\xa6A@5\xf5+\xdcY\x9dxM\x89\x02,\xa3X|\xf4\xeb\x00\x00\u07d4\x0eGey\x03Rek\xc6Vh,$\xfc^\xf3\xe7j#\u01c9\x02\x86\xd7\xfc\f\xb4\xf5\x00\x00\u07d4\x0eI\x88\x00Dqw\xb8\u022f\xc3\xfd\xfa\u007fi\xf4\x05\x1b\xb6)\x89t\x05\xb6\x9b\x8d\xe5a\x00\x00\u07d4\x0ek\xaa\xa3\u07b9\x89\xf2\x89b\x00vf\x86\x18\xe9\xac3(e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x0el\xd6d\xad\x9c\x1e\xd6K\xf9\x87I\xf4\x06D\xb6&\xe3y,\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\xe0\x94\x0em\xfdU;.\x87=*\xec\x15\xbd_\xbb?\x84r\xd8\u04d4\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\x0en\xc3\x137bq\xdf\xf5T#\xabT\"\xcc:\x8b\x06\xb2+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x0en\u0399\x11\x1c\xad\x19a\xc7H\xed=\xf5\x1e\xddi\u04a3\xb1\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x0e\x83\xb8PH\x1a\xb4MI\xe0\xa2)\xa2\xe4d\x90,iS\x9b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0e\x89\xed\xdd?\xa0\xd7\x1d\x8a\xb0\xff\x8d\xa5X\x06\x86\xe3\xd4\xf7O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\x90\x96\xd3C\xc0`\xdbX\x1a\x12\x01\x12\xb2x`~\xc6\xe5+\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x0e\x9cQ\x18d\xa1w\xf4\x9b\xe7\x82\x02w?`H\x9f\xe0NR\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x0e\xa2\xa2\x101+>\x86~\xe0\xd1\xcch,\xe1\xd6f\xf1\x8e\u054a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x0e\xb1\x89\xef,-Wb\xa9c\u05b7\xbd\xf9i\x8e\xa8\u7d0a\x89Hz\x9a0E9D\x00\x00\xe0\x94\x0e\xb5\xb6b\xa1\xc7\x18`\x8f\xd5/\f%\xf97\x880\x17\x85\x19\x8a\x01J7(\x1aa.t\x00\x00\xe0\x94\x0e\xc4f\x96\xff\xac\x1fX\x00_\xa8C\x98$\xf0\x8e\xed\x1d\xf8\x9b\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x0e\xc5\n\xa8#\xf4e\xb9FK\v\xc0\u0125w$\xa5U\xf5\u058a\f\x83\xd1Bj\u01f1\xf0\x00\x00\u07d4\x0e\xc50\x8b1(.!\x8f\xc9\xe7Y\xd4\xfe\xc5\xdb7\b\xce\u01096C\xaady\x86\x04\x00\x00\u07d4\x0e\xcc\xf6\x17\x84O\xd6\x1f\xbab\xcb\x0eD[z\u018b\xcc\x1f\xbe\x89\x14\xfeO\xe65e\xc6\x00\x00\u07d4\x0e\u04fb:N\xb5T\xcf\u0297\x94}WU\a\xcd\xfdm!\u0609\x1d\xb3 _\xcc#\u0540\x00\u07d4\x0e\xd7l,;]P\xff\x8f\xb5\v>\xea\xcdh\x15\x90\xbe\x1c-\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0e\u0680\xf4\xed\aJ\xeaiz\xed\xdf(;c\xdb\xca=\xc4\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4\x0e\xddKX\x0f\xf1\x0f\xe0lJ\x03\x11b9\xef\x96b+\xae5\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x0e\xe3\x91\xf0^\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x0f\x92\x9c\xf8\x95\xdb\x01z\xf7\x9f>\xad\"\x16\xb1\xbdi\xc3}\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f\xa0\x10\xce\fs\x1d;b\x8e6\xb9\x1fW\x13\x00\u477e\xab\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\x0f\xa5\xd8\u0173\xf2\x94\xef\u0515\xabi\xd7h\xf8\x18rP\x85H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x0f\xa6\u01f0\x97=\v\xae)@T\x0e$}6'\xe3|\xa3G\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x0f\xad\x05P|\u070f$\xb2\xbeL\xb7\xfa]\x92}\u06d1\x1b\x88\x89\xa2\xdf\x13\xf4A\xf0\t\x80\x00\u07d4\x0f\xb5\xd2\xc6s\xbf\xb1\xdd\xca\x14\x1b\x98\x94\xfdm?\x05\xdag \x89\x05k\xc7^-c\x10\x00\x00\u07d4\x0f\u0260\xe3AE\xfb\xfd\xd2\xc9\u04a4\x99\xb6\x17\u05e0)i\xb9\x89\t\xc2\x00vQ\xb2P\x00\x00\xe0\x94\x0f\xcf\xc4\x06P\b\xcf\xd3#0_b\x86\xb5zM\xd7\xee\xe2;\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x0f\xdde@#\x95\u07db\u045f\xeeE\a\xefSE\xf7E\x10L\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x0f\xecN\xe0\xd7\xca\x18\x02\x90\xb6\xbd \xf9\x99#B\xf6\x0f\xf6\x8d\x89\x12 \u007f\x0e\xdc\xe9q\x80\x00\u07d4\x0f\ue06c3\x1e\xfd\x8f\x81\x16\x1cW8+\xb4P{\xb9\xeb\xec\x89\x15\xaf\x88\r\x8c\u06c3\x00\x00\u07d4\x0f\xfe\xa0mq\x13\xfbj\xec(i\xf4\xa9\u07f0\x90\a\xfa\xce\xf4\x89\f8F\x81\xb1\xe1t\x00\x00\u07d4\x10\tq\x98\xb4\xe7\xee\x91\xff\x82\xcc/;\xd9_\xeds\xc5@\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x10\vM\tw\xfc\xba\xd4\u07bd^d\xa0Iz\xea\xe5\x16\x8f\xab\x89\x11\f\x90s\xb5$Z\x00\x00\xe0\x94\x10\x1a\nd\xf9\xaf\xccD\x8a\x8a\x13\rM\xfc\xbe\xe8\x957\xd8T\x8a\x037\xfe_\xea\xf2\u0440\x00\x00\u07d4\x10,G}i\xaa\u06e9\xa0\xb0\xf6+tY\xe1\u007f\xbb\x1c\x15a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x101\xe0\xec\xb5I\x85\xae!\xaf\x17\x93\x95\r\xc8\x11\x88\x8f\xde|\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x104d\x14\xbe\xc6\xd3\xdc\xc4NP\xe5MT\u00b8\xc3sN>\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x108\x98X\xb8\x00\xe8\xc0\xec2\xf5\x1e\xd6\x1a5YF\xcc@\x9b\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x10Y\xcb\xc6>6\xc4>\x88\xf3\x00\b\xac\xa7\xce\x05\x8e\ua816\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\x10n\xd5\xc7\x19\xb5&\x14w\x89\x04%\xaeuQ\xdcY\xbd%\\\x8a\x02\x89jX\xc9[\xe5\x88\x00\x00\u07d4\x10q\x1c=\xda21x\x85\xf0\xa2\xfd\x8a\xe9.\x82\x06\x9b\r\v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x10sy\xd4\xc4gFO#[\xc1\x8eU\x93\x8a\xad>h\x8a\u05c9\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x10v!-Ou\x8c\x8e\xc7\x12\x1c\x1c}t%I&E\x92\x84\x8a\ai[Y\xb5\xc1{L\x00\x00\u07d4\x10x\xd7\xf6\x1b\x0eV\xc7N\xe6c[.\x18\x19\xef\x1e=\x87\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x10z\x03\xcf\bB\xdb\u07b0a\x8f\xb5\x87\xcai\x18\x9e\xc9/\xf5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x10\x80\xc1\xd85\x8a\x15\xbc\x84\xda\xc8%\x89\u0392\xb9\x81\x89t\xc1\xfa\xb8\xad\xb4T\x00\x00\u07d4\x10\xe1\xe37x\x85\xc4-}\xf2\x18R.\xe7vh\x87\xc0^j\x89\x10C\xc4<\xde\x1d9\x80\x00\u07d4\x10\u342d+\xa3=\x82\xb3s\x88\u041cED\u01b0\"]\xe5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x10\xf4\xbf\xf0\u02a5\x02|\nj-\xcf\xc9R\x82M\xe2\x94\t\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11\x00\x1b\x89\xed\x87>:\xae\xc1\x15V4\xb4h\x16C\x98c#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x11\x027\u03d1\x17\xe7g\x92/\u0121\xb7\x8dyd\u0682\xdf \x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x11\x11\xe5\xdb\xf4^o\x90mb\x86o\x17\b\x10\x17\x88\xdd\xd5q\x89F{\xe6S>\xc2\xe4\x00\x00\xe0\x94\x11\x17+'\x8d\xddD\xee\xa2\xfd\xf4\xcb\x1d\x16\x96#\x91\xc4S\u064a\xc6/=\x9b\xfdH\x95\xf0\x00\x00\u07d4\x11&4\xb4\xec0\xffxn\x02AY\xf7\x96\xa5y9\xea\x14N\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x110l}WX\x867x\x0f\xc9\xfd\xe8\xe9\x8e\xcb\x00\x8f\x01d\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x116\x12\xbc;\xa0\xeeH\x98\xb4\x9d\xd2\x023\x90_/E\x8fb\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x11A_\xaba\xe0\xdf\u0539\x06v\x14\x1aUz\x86\x9b\xa0\xbd\xe9\x89o\x05\xb5\x9d; \x00\x00\x00\u07d4\x11L\xbb\xbfo\xb5*\xc4\x14\xbe~\xc6\x1f{\xb7\x14\x95\xce\x1d\xfa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x11L\xfe\xfeP\x17\r\xd9z\xe0\x8f\nDTIx\u0159T\x8d\x89.\u0207\xe7\xa1J\x1c\x00\x00\u07d4\x11a\b\xc1 \x84a.\xed\xa7\xa9=\xdc\xf8\xd2`.'\x9e\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11d\u02aa\x8c\u0157z\xfe\x1f\xad\x8a}`(\xce-W)\x9b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x11gZ%UF\a\xa3\xb6\xc9*\x9e\xe8\xf3ou\xed\xd3\xe36\x89\b\xa9\xab\xa5W\xe3l\x00\x00\u07d4\x11j\t\xdff\xcb\x15\x0e\x97W\x8e)\u007f\xb0n\x13\x04\f\x89<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11o\xef^`\x16B\xc9\x18\u02c9\x16\x0f\xc2);\xa7\x1d\xa96\x89+|\xc2\xe9\xc3\"\\\x00\x00\u07d4\x11xP\x1f\xf9J\xdd\x1cX\x81\xfe\x88a6\xf6\xdf\xdb\xe6\x1a\x94\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x11y\xc6\r\xbd\x06\x8b\x15\v\aM\xa4\xbe#\x03; \u0185X\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\x11}\x9a\xa3\xc4\xd1;\xee\x12\xc7P\x0f\t\xf5\xdd\x1cf\xc4e\x04\x89\v*\xd3\x04\x90\xb2x\x00\x00\xe0\x94\x11}\xb867\u007f\xe1TU\xe0,.\xbd\xa4\v\x1c\xebU\x1b\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x11\x8c\x18\xb2\xdc\xe1p\xe8\xf4Eu;\xa5\xd7Q<\xb7cm-\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\x11\x8f\xbdu;\x97\x929Z\xefzMx\xd2c\xcd\u02ab\xd4\xf7\x8963\x03\"\xd5#\x8c\x00\x00\xe0\x94\x11\x92\x83x\xd2}U\xc5 \xce\xed\xf2L\xeb\x1e\x82-\x89\r\xf0\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x11\x9a\xa6M[}\x18\x1d\xae\x9d<\xb4I\x95\\\x89\xc1\xf9c\xfa\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\x11\xc05\x8a\xa6G\x9d\xe2\x18f\xfe!\a\x19$\xb6^p\xf8\xb9\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\xe0\x94\x11\xd2$z\"\x1ep\xc2\xd6m\x17\xee\x13\x8d8\xc5_\xfb\x86@\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x11\u05c4JG\x1e\xf8\x9a\x8d\x87uUX<\xee\xbd\x149\xea&\x8a\x02#i\u6e80\u0188\x00\x00\u07d4\x11\xdda\x85\u0668\xd7=\xdf\u06a7\x1e\x9bwtC\x1cM\xfe\u008965\u026d\xc5\u07a0\x00\x00\u07d4\x11\xe7\x99~\u0750E\x03\xd7}\xa6\x03\x8a\xb0\xa4\xc84\xbb\xd5c\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\x11\xec\x00\xf8I\xb61\x9c\xf5\x1a\xa8\u074ff\xb3U)\xc0\xbew\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x11\ufe22\x04Q\x16\x1bdJ\x8c\u03bb\xc1\xd3C\xa3\xbb\xcbR\x89\xadx\xeb\u016cb\x00\x00\x00\xe0\x94\x11\xfe\xfb]\xc1\xa4Y\x8a\xa7\x12d\fQwu\u07e1\xd9\x1f\x8c\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x12\x0f\x9d\xe6\xe0\xaf~\xc0*\a\xc6\t\u0284G\xf1W\xe64L\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x12\x10\xf8\v\u06c2l\x17Tb\xab\a\x16\xe6\x9eF\xc2J\xd0v\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x12\x13N\u007fk\x01{\xf4\x8e\x85Z9\x9c\xa5\x8e.\x89/\xa5\u020965\u026d\xc5\u07a0\x00\x00\u07d4\x12\x170t\x98\x01S\xae\xaaK\r\xcb\xc7\x13.\xad\xce\xc2\x1bd\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4\x12\x1f\x85[p\x14\x9a\xc84s\xb9po\xb4MG\x82\x8b\x98;\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x12'\xe1\nM\xbf\x9c\xac\xa3\x1b\x17\x80#\x9fUv\x15\xfc5\xc1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x12-\xcf\xd8\x1a\u0779}\x1a\x0eI%\u0135I\x80n\x9f;\xeb\x89R 5\xccn\x01!\x00\x00\u07d4\x12/V\x12%I\xd1h\xa5\xc5\xe2g\xf5&b\xe5\xc5\xcc\xe5\u0209\n\ad\a\xd3\xf7D\x00\x00\xe0\x94\x121o\xc7\xf1x\xea\xc2.\xb2\xb2Z\xed\xea\xdf=u\xd0\x01w\x8a\x04<3\xbe\x05\xf6\xbf\xb9\x80\x00\xe0\x94\x127Y\xf33\xe1>0i\xe2\x03KO\x059\x89\x18\x11\x9d6\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x12\\\xc5\xe4\xd5k+\xcc.\xe1\xc7\t\xfb\x9eh\xfb\x17t@\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x12c#\x88\xb2v^\xe4E+P\x16\x1d\x1f\xff\xd9\x1a\xb8\x1fJ\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\u07d4\x12h\x97\xa3\x11\xa1J\xd4;x\xe0\x92\x01\x00\xc4Bk\xfdk\u07494\xc7&\x89?-\x94\x80\x00\u07d4\x12m\x91\xf7\xad\x86\u07bb\x05W\xc6\x12\xca'n\xb7\xf9m\x00\xa1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x12}?\xc5\x00;\xf6<\r\x83\xe99W\x83e\x15\xfd'\x90E\x89\x06\x10\xc9\".nu\x00\x00\xe0\x94\x12}\xb1\xca\xdf\x1bw\x1c\xbdtu\xe1\xb2ri\x0fU\x8c\x85e\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x12\x84\xf0\xce\xe9\xd2\xff)\x89\xb6Ut\xd0o\xfd\x9a\xb0\xf7\xb8\x05\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x12\x8b\x90\x8f\xe7C\xa44 =\xe2\x94\xc4A\xc7\xe2\n\x86\xeag\x89&\xab\x14\xe0\xc0\xe1<\x00\x00\xe0\x94\x12\x93\u01cc}jD;\x9dt\xb0\xba^\xe7\xbbG\xfdA\x85\x88\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\x12\x96\xac\xde\xd1\xe0c\xaf9\xfe\x8b\xa0\xb4\xb6=\xf7\x89\xf7\x05\x17\x89\x05k\xf9\x1b\x1ae\xeb\x00\x00\u07d4\x12\xaa}\x86\xdd\xfb\xad0\x16\x92\xfe\xac\x8a\b\xf8A\xcb!\\7\x89\amA\xc6$\x94\x84\x00\x00\xe0\x94\x12\xaf\xbc\xba\x14'\xa6\xa3\x9e{\xa4\x84\x9fz\xb1\xc45\x8a\xc3\x1b\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x12\xb5\xe2\x89E\xbb)i\xf9\xc6Lc\xcc\x05\xb6\xf1\xf8\xd6\xf4\u054a\x01\xa2\x9e\x86\x91;t\x05\x00\x00\u0794\x12\u03cb\x0eFR\x13!\x1a[S\u07f0\xdd'\x1a(,\x12\u0248\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x12\xd2\a\x90\xb7\xd3\xdb\u060c\x81\xa2y\xb8\x12\x03\x9e\x8a`;\u0409V\xf9\x85\u04c6D\xb8\x00\x00\xe0\x94\x12\xd6\re\xb7\xd9\xfcH\x84\v\xe5\xf8\x91\xc7E\xcev\xeeP\x1e\x8a\x04\x85\xe58\x8d\fv\x84\x00\x00\u0794\x12\xd9\x1a\x92\xd7O\xc8a\xa7)dm\xb1\x92\xa1%\xb7\x9fSt\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\x12\u992d*\xd5t\x84\xddp\x05e\xbd\xdbFB;\u067d1\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x12\xf3,\n\x1f-\xaa\xb6v\xfei\xab\xd9\xe0\x185-L\xcdE\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x12\xf4`\xaedl\xd2x\x0f\xd3\\P\xa6\xafK\x9a\xcc\xfa\x85\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x12\xff\xc1\x12\x86\x05\xcb\f\x13p\x9ar\x90Po&\x90\x97q\x93\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x13\x03$F\xe7\xd6\x10\xaa\x00\xec\x8cV\u0275t\xd3l\xa1\xc0\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\x1cy,\x19}\x18\xbd\x04]p$\x93|\x1f\x84\xb6\x0fD8\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13\x1d\xf8\xd30\xeb|\xc7\x14}\nUWo\x05\u078d&\xa8\xb7\x89\n1\x06+\xee\xedp\x00\x00\u07d4\x13\x1f\xae\xd1%a\xbbz\xee\x04\xe5\x18Z\xf8\x02\xb1\xc3C\x8d\x9b\x89\v\xdf\x0e\u0733\x90\xc9\xc8V\b\xb7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13!\xcc\xf2\x979\xb9t\xe5\xa5\x16\xf1\x8f:\x846q\xe3\x96B\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13'\xd7Y\xd5n\n\xb8z\xf3~\xcfc\xfe\x01\xf3\x10\xbe\x10\n\x89#\xbc<\xdbh\xa1\x80\x00\x00\u07d4\x13)\xdd\x19\xcdK\xaa\x9f\xc6C\x10\xef\xec\xea\xb2!\x17%\x1f\x12\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x137\x1f\x92\xa5n\xa88\x1eC\x05\x9a\x95\x12\x8b\xdcMC\u0166\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x13O\x15\xe1\xe3\x9cSCY0\xaa\xed\xf3\xe0\xfeV\xfd\xe8C\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x13Ac\xbe\x9f\xbb\xe1\xc5in\xe2U\xe9\v\x13%C\x95\xc3\x18\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x13\\\xec\xd9U\xe5y\x83pv\x920\x15\x93\x03\u0671\x83\x9ff\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x13]\x17\x19\xbf\x03\xe3\xf8f1$y\xfe3\x81\x18\xcd8~p\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x13^\xb8\xc0\xe9\xe1\x01\xde\xed\xec\x11\xf2\xec\xdbf\xae\x1a\xae\x88g\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x13`\xe8}\xf2Li\xeemQ\xc7nsv\u007f\xfe\x19\xa2\x13\x1c\x89\x04\xfc\xc1\xa8\x90'\xf0\x00\x00\u07d4\x13l\x83K\xf1\x112m s\x95)[.X>\xa7\xf35r\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x13mKf+\xbd\x10\x80\xcf\xe4D[\x0f\xa2\x13\x86D5\xb7\xf1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13oI\a\u02b4\x1e'\bK\x98E\x06\x9f\xf2\xfd\f\x9a\xdey\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13t\xfa\xcd{?\x8dhd\x9d`\xd4U\x0e\xe6\x9f\xf0HA3\x89\x0e\x9e\xd6\xe1\x11r\xda\x00\x00\u07d4\x13|\xf3A\xe8Ql\x81X\x14\xeb\xcds\xe6V\x9a\xf1L\xf7\xbc\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x13\x84\x8bF\xeau\xbe\xb7\xea\xa8_Y\xd8f\xd7\u007f\xd2L\xf2\x1a\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x13\x9d51\u0252*\xd5bi\xf60\x9a\xa7\x89\xfb$\x85\xf9\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x13\x9eG\x97d\xb4\x99\xd6f \x8cJ\x8a\x04z\x97\x041c\u0749 w!*\xffm\xf0\x00\x00\u07d4\x13\xa5\xee\xcb80]\xf9Iq\xef-\x9e\x17\x9a\xe6\u03ba\xb37\x89\x11\u3ac3\x95\xc6\xe8\x00\x00\u07d4\x13\xac\xad\xa8\x98\n\xff\xc7PI!\xbe\x84\xebID\xc8\xfb\xb2\xbd\x89V\u04aa:\\\t\xa0\x00\x00\u07d4\x13\xb9\xb1\a\x15qL\t\xcf\xd6\x10\u03dc\x98F\x05\x1c\xb1\xd5\x13\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x13\xce3-\xffe\xa6\xab\x938\x97X\x8a\xa2>\x00\t\x80\xfa\x82\x89\x0e\x02\x056\xf0(\xf0\x00\x00\u07d4\x13\xd6z~%\xf2\xb1,\u06c5XP\t\xf8\xac\u011b\x96s\x01\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x13\xde\xe0>7\x99\x95-\a8\x84=K\xe8\xfc\n\x80?\xb2\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\xe0/\xb4H\xd6\xc8J\xe1}\xb3\x10\xad(m\x05a`\u0695\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x13\xe3!r\x8c\x9cWb\x80X\xe9?\xc8f\xa02\xdd\v\u0690\x89&\xbc\xca#\xfe.\xa2\x00\x00\u07d4\x13\xec\x81\"\x84\x02n@\x9b\xc0f\xdf\xeb\xf9\u0564\xa2\xbf\x80\x1e\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\x14\x01)\xea\xa7f\xb5\xa2\x9f[:\xf2WND\t\xf8\xf6\xd3\xf1\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u07d4\x14\x05\x18\xa3\x19K\xad\x13P\xb8\x94\x9ee\x05e\u07bem\xb3\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14\x06\x85M\x14\x9e\b\x1a\xc0\x9c\xb4\xcaV\r\xa4c\xf3\x120Y\x89Hz\x9a0E9D\x00\x00\u07d4\x14\f\xa2\x8f\xf3;\x9ff\xd7\xf1\xfc\x00x\xf8\xc1\xee\xf6\x9a\x1b\xc0\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x14\x0f\xbaX\xdb\xc0H\x03\xd8L!0\xf0\x19x\xf9\xe0\xc71)\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\x14\x1a^9\xee/h\n`\x0f\xbfo\xa2\x97\u0790\xf3\"\\\u074a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x14%N\xa1&\xb5-\x01B\xda\n~\x18\x8c\xe2U\xd8\xc4qx\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\x14+\x87\xc5\x04?\xfbZ\x91\xdf\x18\xc2\xe1\t\xce\xd6\xfeJq\u06c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x14\x87\xf5\xa5$\u0288Q^\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4\x14\xa75 f6D\x04\xdbP\xf0\xd0\u05cduJ\"\x19\x8e\xf4\x89e\xea=\xb7UF`\x00\x00\u07d4\x14\xab\x16K;RL\x82\u05ab\xfb\xc0\u0783\x11&\xae\x8d\x13u\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x14\xb1`>\xc6+ \x02 3\xee\xc4\xd6\xd6eZ\xc2J\x01Z\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x14\xc6;\xa2\u0731\xddM\xf3=\u06b1\x1cO\x00\a\xfa\x96\xa6-\x8a\x03HA\xb6\x05z\xfa\xb0\x00\x00\xe0\x94\x14\xcd\u077c\x8b\t\xe6gZ\x9e\x9e\x05\t\x1c\xb9\"8\u00de\x1e\x8a\x01\x14x\xb7\xc3\n\xbc0\x00\x00\u07d4\x14\xd0\n\xad9\xa0\xa7\u045c\xa0SP\xf7\xb07'\xf0\x8d\xd8.\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x14\xee\xc0\x9b\xf0>5+\xd6\xff\x1b\x1e\x87k\xe6d\xce\xff\xd0\u03c9\x01\x16\xdc:\x89\x94\xb3\x00\x00\u07d4\x14\xf2!\x15\x95\x18x;\u0127\x06go\xc4\xf3\xc5\xee@X)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x14\xfc\xd19\x1e}s/Avl\xda\u0344\xfa\x1d\xeb\x9f\xfd\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x0e=\xbc\xbc\xfc\x84\xcc\xf8\x9bsBwc\xa5e\xc2>`\u0409\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\x15\x18b{\x885\x1f\xed\xe7\x96\xd3\xf3\b3d\xfb\u0508{\f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u0794\x15\"J\xd1\xc0\xfa\xceF\xf9\xf5V\xe4wJ0%\xad\x06\xbdR\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x15/+\xd2)\xdd\xf3\xcb\x0f\xda\xf4U\xc1\x83 \x9c\x0e\x1e9\xa2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x15/N\x86\x0e\xf3\xee\x80jP'w\xa1\xb8\xdb\xc9\x1a\x90vh\x89 \x86\xac5\x10R`\x00\x00\u07d4\x15<\b\xaa\x8b\x96\xa6\x11\xefc\xc0%>*C4\x82\x9eW\x9d\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\x15<\xf2\x84,\xb9\u0787l'o\xa6Gg\u0468\xec\xf5s\xbb\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15>\xf5\x8a\x1e.z>\xb6\xb4Y\xa8\n\xb2\xa5G\xc9A\x82\xa2\x8a\x14T+\xa1*3|\x00\x00\x00\u07d4\x15DY\xfa/!1\x8e44D\x97\x89\xd8&\xcd\xc1W\f\xe5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15G\xb9\xbfz\xd6bt\xf3A8'#\x1b\xa4\x05\ue308\xc1\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\x15H\xb7p\xa5\x11\x8e\u0787\u06e2\xf6\x903\u007fam\u60eb\x89\x1c\x99V\x85\u0fc7\x00\x00\u07d4\x15R\x83P\xe0\xd9g\n.\xa2\u007f{J3\xb9\xc0\xf9b\x1d!\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x15[7y\xbbmV4./\u0681{[-\x81\xc7\xf4\x13'\x89\x02\xb8\xaa:\al\x9c\x00\x00\u07d4\x15e\xaf\x83~\xf3\xb0\xbdN+#V\x8dP#\xcd4\xb1d\x98\x89\x15Q\xe9rJ\u013a\x00\x00\u07d4\x15f\x91\x80\xde\u2558\x86\x9b\b\xa7!\xc7\xd2LL\x0e\xe6?\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x15r\xcd\xfa\xb7*\x01\u0396\x8ex\xf5\xb5D\x8d\xa2\x98S\xfb\u074a\x01\x12blI\x06\x0f\xa6\x00\x00\xe0\x94\x15uY\xad\xc5Wd\xccm\xf7\x93#\t%4\xe3\xd6dZf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x15x\xbd\xbc7\x1bM$8E3\x05V\xff\xf2\xd5\xefM\xffg\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x15~\xb3\xd3\x11;\u04f5\x97qM:\x95N\xdd\x01\x89\x82\xa5\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x84\xa2\xc0f\xb7\xa4U\xdb\u05ae(\a\xa73N\x83\xc3_\xa5\x89\a\f\x1c\xc7;\x00\xc8\x00\x00\u07d4\x15\x87F\x86\xb6s=\x10\xd7\x03\xc9\xf9\xbe\xc6\xc5.\xb8b\x8dg\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x15\x8a\ra\x92S\xbfD2\xb5\xcd\x02\u01f8b\xf7\u00b7V6\x89\a[\xac|[\x12\x18\x80\x00\u07d4\x15\x98\x12y\x82\xf2\xf8\xad;k\x8f\xc3\xcf'\xbfax\x01\xba+\x89\t`\xdbwh\x1e\x94\x00\x00\xe0\x94\x15\x9a\xdc\xe2z\xa1\vG#d)\xa3JZ\xc4,\xad[d\x16\x8a\x06\xbf\x90\xa9n\xdb\xfaq\x80\x00\u07d4\x15\xa0\xae\xc3\u007f\xf9\xff=T\t\xf2\xa4\xf0\xc1!*\xac\xcb\x02\x96\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x15\xaaS\r\xc3iX\xb4\xed\xb3\x8e\xeem\xd9\xe3\xc7}L\x91E\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15\xac\xb6\x15h\xecJ\xf7\xea(\x198a\x81\xb1\x16\xa6\xc5\xeep\x8a\x06\x90\x83l\n\xf5\xf5`\x00\x00\u07d4\x15\xb9o0\xc2;\x86d\xe7I\x06Q\x06k\x00\xc49\x1f\xbf\x84\x89\x16B\xe9\xdfHv)\x00\x00\u07d4\x15\xc7\xed\xb8\x11\x8e\xe2{4\"\x85\xebY&\xb4z\x85[\u01e5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x15\u0654hPz\xa0A?\xb6\r\xca*\xdc\u007fV\x9c\xb3kT\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x15\u06f4\x8c\x980\x97d\xf9\x9c\xed6\x92\xdc\xca5\xee0k\xac\x8a\x1f\u00c4+\xd1\xf0q\xc0\x00\x00\xe0\x94\x15\u072f\xcc+\xac\xe7\xb5[T\xc0\x1a\x1cQF&\xbfa\xeb\u060a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x15\u3d44\x05kb\xc9s\xcf^\xb0\x96\xf1s>T\xc1\\\x91\x892\xc7Z\x02#\xdd\xf3\x00\x00\u07d4\x15\xeb\xd1\xc7\xca\u04af\xf1\x92u\xc6W\xc4\xd8\b\xd0\x10\xef\xa0\xf5\x89\n\xdf0\xbap\u0217\x00\x00\u07d4\x15\xee\x0f\xc6>\xbf\x1b\x1f\u011d{\xb3\x8f\x88c\x82:.\x17\u0489g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x15\xf1\xb3R\x11\rh\x90\x1d\x8fg\xaa\xc4jl\xfa\xfe\x03\x14w\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x15\xf2\xb7\xb1d2\xeeP\xa5\xf5[A#/c4\xedX\xbd\xc0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x16\x01\x9aM\xaf\xabC\xf4\u067fAc\xfa\xe0\x84}\x84\x8a\xfc\xa2\x89\x01[\xc7\x019\xf7J\x00\x00\u07d4\x16\x02&\xef\xe7\xb5:\x8a\xf4b\xd1\x17\xa0\x10\x80\x89\xbd\xec\xc2\u0449\n\xdf0\xbap\u0217\x00\x00\u07d4\x16\f\xebo\x98\x0e\x041_S\xc4\xfc\x98\x8b+\xf6\x9e(M}\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\xe0\x94\x16\x1c\xafZ\x97*\u0383y\xa6\u0420J\xe6\xe1c\xfe!\xdf+\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x16\x1d&\xefgY\xba[\x9f \xfd\xcdf\xf1a2\xc3RA^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16!\x10\xf2\x9e\xac_}\x02\xb5C\xd8\xdc\u057bY\xa5\xe3;s\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x16+\xa5\x03'b\x14\xb5\t\xf9u\x86\xbd\x84!\x10\xd1\x03\xd5\x17\x8a\x01\xe7\xff\u0609\\\"h\x00\x00\u07d4\x16-v\xc2\xe6QJ:\xfbo\xe3\xd3\u02d3\xa3\\Z\xe7\x83\xf1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16;\xadJ\x12+E}d\xe8\x15\nA>\xaeM\a\x02>k\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u07d4\x16<\u023e\"vF\xcb\tq\x91Y\xf2\x8e\u041c]\xc0\xdc\xe0\x89Hz\x9a0E9D\x00\x00\u07d4\x16=\xcas\xd7\xd6\xea?>`b2*\x874\x18\f\vx\uf25ft \x03\xcb}\xfc\x00\x00\u07d4\x16Mz\xac>\xec\xba\uc86dQ\x91\xb7S\xf1s\xfe\x12\xec3\x89(VR\xb8\xa4hi\x00\x00\u07d4\x16Rl\x9e\u07d4>\xfaOm\x0f\v\xae\x81\xe1\x8b1\xc5@y\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x16S\x05\xb7\x872.%\xdcj\xd0\xce\xfelo3Fx\xd5i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16e\xab\x179\xd7\x11\x19\xeea2\xab\xbd\x92j'\x9f\xe6yH\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x16k\xf6\u06b2-\x84\x1bHl8\xe7\xbaj\xb3:\x14\x87\ud30a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x16v\x99\xf4\x8ax\xc6\x15Q%\x15s\x99X\x993\x12WO\a\x89\x02\x1d;\xd5^\x80<\x00\x00\u07d4\x16x\xc5\xf2\xa5\"92%\x19ca\x89OS\xccu/\xe2\xf3\x89h\xf3e\xae\xa1\xe4@\x00\x00\u07d4\x16|\xe7\xdee\xe8G\bYZRT\x97\xa3\xeb^ZfPs\x89\x1f1Gsfo\xc4\x00\x00\u07d4\x16~>:\xe2\x003HE\x93\x92\xf7\xdf\xceD\xaf|!\xadY\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x16\x80\xce\xc5\x02\x1e\xe90P\xf8\xae\x12rQ\x83\x9et\xc1\xf1\xfd\x8a\x02\xc6\x14a\xe5\xd7C\u0580\x00\u07d4\x16\x81j\xac\x0e\xde\r-<\xd4B\xday\xe0c\x88\x0f\x0f\x1dg\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x16\x8bP\x19\xb8\x18i\x16D\x83_\xe6\x9b\xf2)\xe1q\x12\xd5,\x8a\x05\xed\xe2\x0f\x01\xa4Y\x80\x00\x00\u07d4\x16\x8b\xde\xc8\x18\xea\xfcm)\x92\xe5\xefT\xaa\x0e\x16\x01\xe3\xc5a\x8967Pz0\xab\xeb\x00\x00\u07d4\x16\x8d0\xe5?\xa6\x81\t+R\xe9\xba\xe1Z\r\xcbA\xa8\u027b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x16\x9b\xbe\xfcA\xcf\xd7\xd7\u02f8\xdf\xc60 \xe9\xfb\x06\u0515F\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xa5\x8e\x98]\xcc\xd7\a\xa5\x94\u0453\xe7\u0327\x8b]\x02xI\x89I\xb9\u029aiC@\x00\x00\u07d4\x16\xa9\xe9\xb7:\u92c6M\x17(y\x8b\x87f\xdb\xc6\xea\x8d\x12\x893\xe7\xb4K\r\xb5\x04\x00\x00\u07d4\x16\xaaR\xcb\vUG#\xe7\x06\x0f!\xf3'\xb0\xa6\x83\x15\xfe\xa3\x89\r\x8drkqw\xa8\x00\x00\u07d4\x16\xab\xb8\xb0!\xa7\x10\xbd\u01ce\xa54\x94\xb2\x06\x14\xffN\xaf\xe8\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x16\xaf\xa7\x87\xfc\x9f\x94\xbd\xffiv\xb1\xa4/C\n\x8b\xf6\xfb\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xba\xe5\xd2N\xff\x91w\x8c\u064bM:\x1c\xc3\x16/D\xaaw\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\x16\xbc@!Z\xbb\u066e](\v\x95\xb8\x01\vE\x14\xff\x12\x92\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x16\xbeu\u9299Z9R\"\xd0\v\u05df\xf4\xb6\xe68\u144a\a\x9f\x90\\o\xd3N\x80\x00\x00\u07d4\x16\xc1\xbf[}\xc9\xc8<\x17\x9e\xfa\xcb\xcf.\xb1t\xe3V\x1c\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x16\u01f3\x1e\x8c7b\x82\xac\"qr\x8c1\xc9^5\xd9R\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xf3\x13\u03ca\xd0\x00\x91J\n\x17m\u01a44+y\xec%8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x16\xff\xac\x84\x03)@\xf0\x12\x1a\tf\x8b\x85\x8a~y\xff\xa3\xbb\x89\xd2J\xdan\x10\x87\x11\x00\x00\xe0\x94\x17\x03\xb4\xb2\x92\xb8\xa9\xde\xdd\xed\xe8\x1b\xb2]\x89\x17\x9fdF\xb6\x8a\x04+e\xa4U\xe8\xb1h\x00\x00\u07d4\x17\x04\x93\x11\x10\x1d\x81~\xfb\x1de\x91\x0ff6b\xa6\x99\u024c\x89lh\xcc\u041b\x02,\x00\x00\u07d4\x17\x04\xce\xfc\xfb\x131\xeczx8\x8b)9>\x85\xc1\xafy\x16\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17\n\x88\xa8\x99\u007f\x92\xd287\x0f\x1a\xff\xde\xe64pP\xb0\x13\x89\xa2\xacw5\x14\x880\x00\x00\u07d4\x17\x10\x8d\xab,P\xf9\x9d\xe1\x10\u1cf3\xb4\u0342\xf5\xdf(\xe7\x895 ;g\xbc\xca\xd0\x00\x00\xe0\x94\x17\x12[Y\xacQ\xce\xe0)\xe4\xbdx\xd7\xf5\x94}\x1e\xa4\x9b\xb2\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4\x17\x1a\u0660K\xed\u0238a\xe8\xedK\xdd\xf5qx\x13\xb1\xbbH\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17\x1c\xa0*\x8bmb\xbfL\xa4~\x90i\x14\a\x98a\x97,\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x17\"\xc4\xcb\xe7\n\x94\xb6U\x9dBP\x84\xca\xee\xd4\xd6\xe6n!\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x17X\vvotSR\\\xa4\u01a8\x8b\x01\xb5\x05p\xea\b\x8c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x17X\x9al\x00jT\xca\xd7\x01\x03\x12:\xae\n\x82\x13_\u07b4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x17Z\x18::#_\xfb\xb0;\xa85gRg\"\x94\x17\xa0\x91\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x17_\xee\xea*\xa4\xe0\xef\xda\x12\xe1X\x8d/H2\x90\xed\xe8\x1a\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x17e6\x1c.\xc2\xf86\x16\u0383c\xaa\xe2\x10%\xf2Vo@\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x17gR\\_Z\"\xed\x80\xe9\xd4\xd7q\x0f\x03b\u049e\xfa3\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x17v%`\xe8*\x93\xb3\xf5\"\xe0\xe5$\xad\xb8a,:tp\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x17}\xaex\xbc\x01\x13\xd8\u04dcD\x02\xf2\xa6A\xae*\x10Z\xb8\x89b\x92BV \xb4H\x00\x00\xe0\x94\x17\x84\x94\x8b\xf9\x98H\u021eDV8PM\u0598'\x1bY$\x8a\x01GLA\r\x87\xba\xee\x00\x00\u07d4\x17\x88\u069bW\xfd\x05\xed\xc4\xff\x99\xe7\xfe\xf3\x01Q\x9c\x8a\n\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\x8e\xafk\x85T\xc4]\xfd\xe1kx\xce\f\x15\u007f.\xe3\x13Q\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\x17\x96\x1dc;\xcf \xa7\xb0)\xa7\xd9K}\xf4\xda.\xc5B\u007f\x89\fo\xf0p\U000532c0\x00\u07d4\x17\x96\xbc\xc9{\x8a\xbcq\u007fKJ|k\x106\xea!\x82c\x9f\x89\x13A\xf9\x1c\xd8\xe3Q\x00\x00\u07d4\x17\x99=1*\xa1\x10iW\x86\x8fjU\xa5\xe8\xf1/w\xc8C\x89\x18e\xe8\x14\xf4\x14.\x80\x00\u07d4\x17\x9a\x82^\x0f\x1fn\x98S\tf\x84e\xcf\xfe\xd46\xf6\xae\xa9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x17\xb2\xd6\xcfe\xc6\xf4\xa3G\xdd\xc6W&U5M\x8aA+)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xb8\a\xaf\xa3\xdd\xd6G\xe7#T.{R\xfe\xe3\x95'\xf3\x06\x89\x15\xaf@\xff\xa7\xfc\x01\x00\x00\u07d4\x17\xc0G\x86W\xe1\xd3\xd1z\xaa3\x1d\xd4)\xce\u03d1\xf8\xae]\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\x17\xc0\xfe\xf6\x98l\xfb.@A\xf9\x97\x9d\x99@\xb6\x9d\xff=\xe2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x17\u0511\x8d\xfa\xc1]w\xc4\u007f\x9e\xd4\x00\xa8P\x19\rd\xf1Q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xd5!\xa8\xd9w\x90#\xf7\x16M#<;d \xff\xd2#\xed\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x17\xd91\xd4\xc5b\x94\u073ew\xc8e[\xe4i_\x00mJ<\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xdfIQ\x8ds\xb1)\xf0\xda6\xb1\u0274\f\xb6d \xfd\u01ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x17\xe4\xa0\xe5+\xac>\xe4N\xfe\tT\xe7S\u0538]dN\x05\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xe5\x84\xe8\x10\xe5gp,a\xd5]CK4\u0375\xee0\xf6\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x17\xe8.px\xdcO\xd9\xe8y\xfb\x8aPf\u007fS\xa5\xc5E\x91\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x17\xe8o;[0\xc0\xbaY\xf2\xb2\xe8XB[\xa8\x9f\n\x10\xb0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x17\xee\x9fT\xd4\xdd\xc8Mg\x0e\xff\x11\xe5Je\x9f\xd7/DU\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94\x17\xefJ\xcc\x1b\xf1G\xe3&t\x9d\x10\xe6w\xdc\xff\xd7o\x9e\x06\x8a\bwQ\xf4\xe0\xe1\xb50\x00\x00\u07d4\x17\xf1F2\xa7\xe2\x82\v\xe6\xe8\xf6\u07c25X(=\xad\xab-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x17\xf5#\xf1\x17\xbc\x9f\xe9x\xaaH\x1e\xb4\xf5V\x17\x117\x1b\u0209li\xf7>)\x13N\x00\x00\u07d4\x17\xfd\x9bU\x1a\x98\xcba\xc2\xe0\u007f\xbfA\xd3\xe8\u02650\u02e5\x89\x01v\x8c0\x81\x93\x04\x80\x00\u07d4\x18\x04x\xa6U\u05cd\x0f;\fO +aH[\xc4\x00/\u0549lk\x93[\x8b\xbd@\x00\x00\u07d4\x18\x13l\x9d\xf1g\xaa\x17\xb6\xf1\x8e\"\xa7\x02\u020fK\u0082E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x18\x15'\x9d\xff\x99R\xda;\xe8\xf7rI\xdb\xe2\"C7{\xe7\x8a\x01\x01|\xb7n{&d\x00\x00\u07d4\x18\x1f\xbb\xa8R\xa7\xf5\x01x\xb1\xc7\xf0>\xd9\xe5\x8dT\x16))\x89$\x1a\x9bOaz(\x00\x00\xe0\x94\x18'\x03\x9f\tW\x02\x94\b\x8f\xdd\xf0G\x16\\3\u65a4\x92\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\x18-\xb8R\x93\xf6\x06\u8248\xc3pL\xb3\xf0\xc0\xbb\xbf\xcaZ\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x18H\x00<%\xbf\u052a\x90\xe7\xfc\xb5\u05f1k\xcd\f\xff\xc0\u060965\u026d\xc5\u07a0\x00\x00\xe0\x94\x18JO\v\xebq\xff\xd5X\xa6\xb6\xe8\xf2(\xb7\x87\x96\xc4\xcf>\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94\x18M\x86\xf3Fj\xe6h;\x19r\x99\x82\xe7\xa7\u1903G\xb2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x18Q\xa0c\xcc\xdb0T\x90w\xf1\xd19\xe7-\xe7\x97\x11\x97\u0549lk\x93[\x8b\xbd@\x00\x00\u07d4\x18UF\xe8v\x8dPhs\x81\x8a\xc9u\x1c\x1f\x12\x11j;\xef\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x18X\xcf\x11\xae\xa7\x9fS\x98\xad+\xb2\"g\xb5\xa3\xc9R\xeat\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\xe0\x94\x18Z\u007f\u012c\xe3h\xd23\xe6 \xb2\xa4Y5f\x12\x92\xbd\xf2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x18d\xa3\u01f4\x81UD\x8cT\u020cp\x8f\x16g\tsm1\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x18j\xfd\xc0\x85\xf2\xa3\xdc\xe4a^\xdf\xfb\xad\xf7\x1a\x11x\x0fP\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x18k\x95\xf8\xe5\xef\xfd\xdc\xc9O\x1a1[\xf0)];\x1e\xa5\x88\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x18}\x9f\f\a\xf8\xebt\xfa\xaa\xd1^\xbc{\x80Dt\x17\xf7\x82\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x18\x95\xa0\xebJCrr/\xcb\u016f\xe6\x93o(\x9c\x88\xa4\x19\x891T\xc9r\x9d\x05x\x00\x00\u07d4\x18\x99\xf6\x9fe;\x05\xa5\xa6\xe8\x1fH\a\x11\u041b\xbf\x97X\x8c\x89i\xfb\x13=\xf7P\xac\x00\x00\u07d4\x18\xa6\xd2\xfcR\xbes\b@#\xc9\x18\x02\xf0[\xc2JK\xe0\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x18\xb0@|\xda\xd4\xceR`\x06#\xbd^\x1fj\x81\xaba\xf0&\x89\x11Q\xcc\xf0\xc6T\u0180\x00\u07d4\x18\xb8\xbc\xf9\x83!\xdaa\xfbN>\xac\xc1\xecT\x17'-\xc2~\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\x18\xc6r:gS)\x9c\xb9\x14G}\x04\xa3\xbd!\x8d\xf8\xc7u\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x18\xe1\x13\xd8\x17|i\x1aa\xbexXR\xfa[\xb4z\uef6f\x89Hz\x9a0E9D\x00\x00\xe0\x94\x18\xe4\xceGH;S\x04\n\u06eb5\x17,\x01\xefdPn\f\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\xe0\x94\x18\xe52C\x98\x1a\xab\xc8v}\xa1\fsD\x9f\x13\x91V\x0e\xaa\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x18\xfa\x86%\xc9\u0704>\x00\x15\x9e\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94\x193\xe34\xc4\x0f:\u02ed\f\v\x85\x11X i$\xbe\xca:\x8a\x01\x99^\xaf\x01\xb8\x96\x18\x80\x00\xe0\x94\x197\xc5\xc5\x15\x05uS\u033dF\u0546dU\xcef)\x02\x84\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u07d4\x19:\xc6Q\x83e\x18\x00\xe25\x80\xf8\xf0\xea\u04fbY~\xb8\xa4\x89\x02\xb6*\xbc\xfb\x91\n\x00\x00\u07d4\x19=7\xed4}\x1c/N55\r\x9aDK\xc5|\xa4\xdbC\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\x19@\u0713d\xa8R\x16_GAN'\xf5\x00$E\xa4\xf1C\x8a\x02L-\xffj<|H\x00\x00\u07d4\x19E\xfe7\u007f\xe6\u0537\x1e>y\x1fo\x17\xdb$<\x9b\x8b\x0f\x89vy\u7fb9\x886\x00\x00\u07d4\x19Jk\xb3\x02\xb8\xab\xa7\xa5\xb5y\u07d3\xe0\xdf\x15t\x96v%\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x19L\ubd12\x98\x82\xbf;K\xf9\x86L+\x1b\x0fb\u0083\xf9\x89\x1e\xf8aS\x1ft\xaa\x00\x00\u07d4\x19O\xf4J\xef\xc1{\xd2\x0e\xfdz LG\xd1b\f\x86\xdb]\x89\xa2\x99\th\u007fj\xa4\x00\x00\xe0\x94\x19O\xfex\xbb\xf5\xd2\r\u044a\x1f\x01\xdaU.\x00\xb7\xb1\x1d\xb1\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x19S1>*\xd7F#\x9c\xb2'\x0fH\xaf4\u063b\x9cDe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19W\x1a+\x8f\x81\u01bc\xf6j\xb3\xa1\x00\x83)V\x17\x15\x00\x03\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\xe0\x94\x19h}\xaa9\xc3h\x13\x9bn{\xe6\r\xc1u:\x9f\f\xbe\xa3\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x19l\x02!\nE\n\xb0\xb3cpe_qz\xa8{\xd1\xc0\x04\x89\x0e\x10\xac\xe1W\xdb\xc0\x00\x00\u07d4\x19n\x85\xdf~s+J\x8f\x0e\xd06#\xf4\u06dd\xb0\xb8\xfa1\x89\x01%\xb9/\\\xef$\x80\x00\u07d4\x19s+\xf9s\x05]\xbd\x91\xa4S:\u06a2\x14\x9a\x91\u04c3\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19vr\xfd9\xd6\xf2F\xcef\xa7\x90\xd1:\xa9\"\xd7\x0e\xa1\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x19y\x8c\xbd\xa7\x15\ua69b\x9dj\xab\x94,U\x12\x1e\x98\xbf\x91\x89A\rXj \xa4\xc0\x00\x00\u07d4\x19\x8b\xfc\xf1\xb0z\xe3\b\xfa,\x02\x06\x9a\xc9\xda\xfeq5\xfbG\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x19\x8e\xf1\xec2Z\x96\xcc5Lrf\xa08\xbe\x8b\\U\x8fg\x8a\x80\xd1\xe47>\u007f!\xda\x00\x00\xe0\x94\x19\x91\x8a\xa0\x9e}IN\x98\xff\xa5\xdbP5\b\x92\xf7\x15j\u018a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x19\xb3k\f\x87\xeafN\xd8\x03\x18\xdcw\xb6\x88\xdd\xe8}\x95\xa5\x89i\x9fI\x98\x020=\x00\x00\u07d4\x19\u07d4E\xa8\x1c\x1b=\x80J\xea\xebon NB6f?\x89\x02\x06\xd9NjI\x87\x80\x00\u07d4\x19\xe5\u07a37\n,tj\xae4\xa3|S\x1fA\xda&N\x83\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x19\xe7\xf3\xeb{\xf6\u007f5\x99 \x9e\xbe\b\xb6*\xd32\u007f\x8c\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\x19\xe9Nb\x00P\xaa\xd7f\xb9\xe1\xba\xd91#\x83\x12\u053fI\x89\x81\xe3-\xf9r\xab\xf0\x00\x00\u07d4\x19\xec\xf2\xab\xf4\f\x9e\x85{%/\xe1\xdb\xfd=L]\x8f\x81n\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x19\xf5\xca\xf4\xc4\x0ei\b\x81<\aE\xb0\xae\xa9Xm\x9d\xd91\x89#\xfe\xd9\xe1\xfa+`\x00\x00\u07d4\x19\xf6C\xe1\xa8\xfa\x04\xae\x16\x00`(\x13\x833\xa5\x9a\x96\u0787\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x19\xf9\x9f,\vF\u0389\x06\x87]\xc9\xf9\n\xe1\x04\xda\xe3U\x94\x89\xf4WZ]M\x16*\x00\x00\u07d4\x19\xff$O\xcf\xe3\xd4\xfa/O\u065f\x87\xe5[\xb3\x15\xb8\x1e\xb6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1a\x04\xce\xc4 \xadC\"\x15$mw\xfe\x17\x8d3\x9e\u0435\x95\x89\x11!a\x85\u009fp\x00\x00\xe0\x94\x1a\x04\xd58\x9e\xb0\x06\xf9\u0388\f0\xd1SS\xf8\xd1\x1cK1\x8a\x03\x9d\x84\xb2\x18m\xc9\x10\x00\x00\u07d4\x1a\bA\xb9*\u007fpuV\x9d\xc4b~kv\u02b0Z\u0791\x89Rf<\u02b1\xe1\xc0\x00\x00\xe0\x94\x1a\b]C\xec\x92AN\xa2{\x91O\xe7g\xb6\xd4k\x1e\xefD\x8a\x06A\xe8\xa15c\xd8\xf8\x00\x00\u07d4\x1a\t\xfd\xc2\u01e2\x0e#WK\x97\u019e\x93\u07bag\xd3r \x89lO\xd1\xee$nx\x00\x00\u07d4\x1a\n\x1d\u07f01\xe5\xc8\xcc\x1dF\xcf\x05\x84-P\xfd\xdcq0\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1a\x1c\x9a&\xe0\xe0$\x18\xa5\xcfh}\xa7Z'\\b,\x94@\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x1a \x1bC'\u03a7\xf3\x99\x04bF\xa3\xc8~n\x03\xa3\u0368\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a$4\xccwD\"\u050dS\u055c]V,\u0384\a\xc9K\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\x1a%\xe1\u017c~_P\xec\x16\xf8\x88_!\x0e\xa1\xb98\x80\x0e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x1a&\x94\xec\a\xcf^Mh\xba@\xf3\xe7\xa1LS\xf3\x03\x8cn\x8966\xcd\x06\xe2\xdb:\x80\x00\u07d4\x1a5 E5\x82\xc7\x18\xa2\x1cB7[\xc5\as%RS\xe1\x89*\xd3s\xcef\x8e\x98\x00\x00\xe0\x94\x1a7n\x1b-/Y\ai\xbb\x85\x8dEu2\rN\x14\x99p\x8a\x01\x06q%v9\x1d\x18\x00\x00\u07d4\x1a:3\x0eO\xcbi\xdb\xef^i\x01x;\xf5\x0f\xd1\xc1SB\x89\u3bb5sr@\xa0\x00\x00\u07d4\x1aN\u01a0\xae\u007fZ\x94'\xd2=\xb9rL\r\f\xff\xb2\xab/\x89\t\xb4\x1f\xbf\x9e\n\xec\x00\x00\u07d4\x1aP^b\xa7N\x87\xe5wG>O:\xfa\x16\xbe\xdd<\xfaR\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x1a^\xe53\xac\xbf\xb3\xa2\xd7m[hRw\xb7\x96\xc5j\x05+\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1adJP\xcb\u00ae\xe8#\xbd+\xf2C\xe8%\xbeMG\xdf\x02\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\x1apD\xe28?\x87\b0[I[\xd1\x17k\x92\xe7\xef\x04:\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1ay\xc7\xf4\x03\x9cg\xa3\x9du\x13\x88L\xdc\x0e,4\"$\x90\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1a\x89\x89\x9c\xbe\xbd\xbbd\xbb&\xa1\x95\xa6<\bI\x1f\u035e\xee\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1a\x8a\\\xe4\x14\u079c\xd1r\x93~7\xf2\u055c\xffq\xceW\xa0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1a\x95\xa8\xa8\b.FR\xe4\x17\r\xf9'\x1c\xb4\xbbC\x05\xf0\xb2\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x1a\x95\u0277Tk]\x17\x86\u00c5\x8f\xb1#dF\xbc\f\xa4\u0389j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1a\x98~?\x83\xdeu\xa4/\x1b\xde|\x99|\x19!{J_$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1a\x9ep/8]\xcd\x10^\x8b\x9f\xa4(\xee\xa2\x1cW\xffR\x8a\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1a\xa1\x02\x1fU\n\xf1X\xc7Gf\x8d\xd1;F1`\xf9Z@\x89O\xb0Y\x1b\x9b08\x00\x00\u07d4\x1a\xa2v\x99\xca\u068d\u00e7oy3\xaaf\xc7\x19\x19\x04\x0e\x88\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x1a\xa4\x02p\xd2\x1e\\\u0786\xb61m\x1a\xc3\xc53IKy\xed\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1a\xb5:\x11\xbc\xc6=\u07ea@\xa0+\x9e\x18d\x96\u037b\x8a\xff\x89l?*\xac\x80\f\x00\x00\x00\u07d4\x1a\xbcN%;\b\n\xebCy\x84\xab\x05\xbc\xa0\x97\x9a\xa4>\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a\xc0\x89\u00fcM\x82\xf0j \x05\x1a\x9ds-\xc0\xe74\xcba\x89%\xf6\x9dc\xa6\xce\x0e\x00\x00\xe0\x94\x1a\xd4V>\xa5xk\xe1\x15\x995\xab\xb0\xf1\u0547\x9c>sr\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1a\xd7- \xa7n\u007f\xcckv@X\xf4\x8dA}Io\xa6\u0349lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1a\xda\xf4\xab\xfa\x86}\xb1\u007f\x99\xafj\xbe\xbfpz<\xf5]\xf6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1a\xf6\x03C6\x0e\v-u%R\x107W \xdf!\xdb\\}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1a\xfc\u0145\x89l\xd0\xed\xe1)\xee-\xe5\xc1\x9e\xa8\x11T\vd\x89\xaf*\xba\f\x8e[\xef\x80\x00\u07d4\x1b\x05\xeajj\u022f|\xb6\xa8\xb9\x11\xa8\xcc\xe8\xfe\x1a*\xcf\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\v1\xaf\xffKm\xf3e:\x94\xd7\xc8yx\xae5\xf3J\xae\x89\x139\x10E?\xa9\x84\x00\x00\u07d4\x1b\r\ah\x17\xe8\u058e\xe2\xdfN\x1d\xa1\xc1\x14-\x19\x8cD5\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\x1b\x13\ro\xa5\x1d\\H\xec\x8d\x1dR\u070a\"{\xe8s\\\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b#\u02c6cUHq\xfb\xbe\r\x9e`9~\xfbo\xae\xdc>\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1b&9X\x8bU\xc3D\xb0#\xe8\xde_\xd4\b{\x1f\x04\x03a\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x1b9 \xd0\x01\xc4>r\xb2N|\xa4o\x0f\xd6\xe0\xc2\n_\xf2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1b<\xb8\x1eQ\x01\x1bT\x9dx\xbfr\v\r\x92J\xc7c\xa7\u008av\x95\xa9, \xd6\xfe\x00\x00\x00\u07d4\x1bC#,\xcdH\x80\xd6\xf4o\xa7Q\xa9l\xd8$s1XA\x89\x04V9\x18$O@\x00\x00\u07d4\x1bK\xbc\xb1\x81e!\x1b&[(\a\x16\xcb?\x1f!!v\xe8\x89\x19\x9a\xd3}\x03\xd0`\x80\x00\u07d4\x1bM\a\xac\u04c1\x83\xa6\x1b\xb2x=+{\x17\x8d\xd5\x02\xac\x8d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1bckzIo\x04MsYYn5:\x10F\x16Cok\x89\x13\x88\xea\x95\xc3?\x1d\x00\x00\u07d4\x1bd\x95\x89\x12@\xe6NYD\x93\xc2f!q\xdb^0\xce\x13\x89\tX\x87\u0595\xedX\x00\x00\u07d4\x1bf\x10\xfbh\xba\xd6\xed\x1c\xfa\xa0\xbb\xe3:$\xeb.\x96\xfa\xfb\x89\b=lz\xabc`\x00\x00\u07d4\x1by\x903\xefm\xc7\x12x\"\xf7EB\xbb\"\xdb\xfc\t\xa3\b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x1b~\xd9t\xb6\xe24\u0381$t\x98B\x9a[\u0520\xa2\xd19\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\x82o\xb3\xc0\x12\xb0\xd1Y\u253a[\x8aI\x9f\xf3\xc0\xe0<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\x8a\xa0\x16\f\u05df\x00_\x88Q\nqI\x13\xd7\n\u04fe3\x89\n\xef\xfb\x83\a\x9a\xd0\x00\x00\xe0\x94\x1b\x8b\xd6\xd2\xec\xa2\x01\x85\xa7\x8e}\x98\xe8\xe1\x85g\x8d\xacH0\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\x1b\x9b-\u0096\x0eL\xb9@\x8ft\x05\x82|\x9bY\a\x16\x12\xfd\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1b\xa9\"\x8d8\x87'\xf3\x89\x15\x0e\xa0;s\xc8-\xe8\xeb.\t\x8a\x01\x89t\xfb\xe1w\xc9(\x00\x00\u07d4\x1b\xa9\xf7\x99~S\x87\xb6\xb2\xaa\x015\xac$R\xfe6\xb4\xc2\r\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\x1b\xba\x03\xffkJ\u057f\x18\x18J\xcb!\xb1\x88\xa3\x99\xe9\xebJ\x89a\t=|,m8\x00\x00\u07d4\x1b\xbc\x19\x9eXg\x90\xbe\x87\xaf\xed\xc8I\xc0G&t\\]{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x1b\xbc`\xbc\xc8\x0e\\\xdc5\xc5Aj\x1f\n@\xa8=\xae\x86{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xc4L\x87a#\x1b\xa1\xf1\x1f_\xaa@\xfaf\x9a\x01>\x12\u0389\v\tR\xc4Z\xea\xad\x00\x00\u07d4\x1b\xcf4A\xa8f\xbd\xbe\x960\t\xce3\xc8\x1c\xbb\x02a\xb0,\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\x1b\u048c\xd5\u01ca\xeeQ5|\x95\xc1\xef\x925\xe7\xc1\x8b\xc8T\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xd8\xeb\xaavt\xbb\x18\u1458\xdb$OW\x03\x13\a_C\x89\b!\xab\rD\x14\x98\x00\x00\u07d4\x1b\xd9\t\xac\rJ\x11\x02\xec\x98\xdc\xf2\u0329j\n\xdc\u05e9Q\x89\x01\x16Q\xac>zu\x80\x00\u07d4\x1b\xe3T,6\x13hte\xf1Zp\xae\xeb\x81f+e\u0328\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1b\xeaM\xf5\x12/\xaf\u07b3`~\xdd\xda\x1e\xa4\xff\u06da\xbf*\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d4\x1b\xecM\x02\u0385\xfcH\xfe\xb6$\x89\x84\x1d\x85\xb1pXj\x9b\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\x1b\xf9t\u0650OE\u0381\xa8E\xe1\x1e\xf4\xcb\xcf'\xafq\x9e\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x1c\x04VI\xcdS\xdc#T\x1f\x8e\xd4\xd3A\x81(\b\xd5\u075c\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x1c\x12\x8b\xd6\u0365\xfc\xa2uu\xe4\xb4;2S\xc8\xc4\x17*\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\x13\u04c67\xb9\xa4|\xe7\x9d7\xa8oP\xfb@\x9c\x06\a(\x89Hz\x9a0E9D\x00\x00\u07d4\x1c \x10\xbdf-\xf4\x17\xf2\xa2q\x87\x9a\xfb\x13\xefL\x88\xa3\xae\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x1c%z\u0525Q\x05\xea;X\xed7K\x19\x8d\xa2f\xc8_c\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x1c.6\a\xe1'\xca\xca\x0f\xbd\\YH\xad\xad}\xd80\xb2\x85\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x1c5l\xfd\xb9_\xeb\xb7\x14c;(\xd5\xc12\u0744\xa9\xb46\x89\x01Z\xf1\u05cbX\xc4\x00\x00\u07d4\x1c5\xaa\xb6\x88\xa0\u034e\xf8.vT\x1b\xa7\xac9R\u007ft;\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x1c>\xf0]\xae\x9d\xcb\u0509\xf3\x02D\bf\x9d\xe2D\xc5*\x02\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x1cJ\xf0\xe8c\xd2el\x865\xbco\xfe\xc8\u0759(\x90\x8c\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c`\x19\x93x\x92\a\xf9e\xbb\x86\\\xbbL\xd6W\xcc\xe7o\xc0\x89\x05T\x1ap7P?\x00\x00\u07d4\x1cc\xfa\x9e,\xbb\xf21a\xda3\xa1\xda}\xf7\r\x1b\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1c\xb6\xb2\xd7\xcf\xc5Y\xb7\xf4\x1eoV\xab\x95\xc7\xc9X\xcd\x0eL\x89Hz\x9a0E9D\x00\x00\u07d4\x1c\xc1\xd3\xc1O\x0f\xb8d\x0e6rM\xc42)\xd2\xeaz\x1eH\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x1c\xc9\bv\x00A\t\xcdy\xa3\u07a8f\u02c4\n\xc3d\xba\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xd1\xf0\xa3\x14\u02f2\x00\xde\n\f\xb1\xef\x97\xe9 p\x9d\x97\u0089lk\x93[\x8b\xbd@\x00\x00\u0794\x1c\xdaA\x1b\xd5\x16;\xae\xca\x1eU\x85c`\x1c\xe7 \xe2N\xe1\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1c\xe8\x1d1\xa7\x920\"\xe1%\xbfH\xa3\xe06\x93\xb9\x8d\xc9\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xeb\xf0\x98]\u007fh\n\xaa\x91\\D\xccb\xed\xb4\x9e\xab&\x9e\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1c\xedg\x15\xf8b\xb1\xff\x86\x05\x82\x01\xfc\xceP\x82\xb3nb\xb2\x8a\x01j^`\xbe\xe2s\xb1\x00\x00\u07d4\x1c\xf0L\xb1C\x80\x05\x9e\xfd?#\x8be\u057e\xb8j\xfa\x14\u0609\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1c\xf1\x05\xab#\x02;ULX>\x86\u05d2\x11y\xee\x83\x16\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1c\xf2\xebz\x8c\xca\u00ad\xea\xef\x0e\xe8sG\xd55\u04f9@X\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1c\xfc\xf7Q\u007f\f\bE\x97 \x94+dz\u0452\xaa\x9c\x88(\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\x1d\t\xad$\x12i\x1c\u0141\xc1\xab6\xb6\xf9CL\xd4\xf0\x8bT\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\x1d\x15|Xv\xc5\xca\xd5S\xc9\x12\xca\xf6\xce-Rw\xe0\\s\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x1d&\x15\xf8\xb6\xcaP\x12\xb6c\xbd\u0414\xb0\xc5\x13|w\x8d\u07ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1d)\u01ea\xb4+ H\u04b2R%\u0518\u06e6z\x03\xfb\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0794\x1d4\x1f\xa5\xa3\xa1\xbd\x05\x1f}\xb8\a\xb6\xdb/\u01faO\x9bE\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1d4N\x96%g\xcb'\xe4M\xb9\xf2\xfa\u01f6\x8d\xf1\xc1\xe6\xf7\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x1d6h0c\xb7\xe9\xeb\x99F-\xab\xd5i\xbd\xdc\xe7\x16\x86\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1d7aky?\x94\x91\x188\xac\x8e\x19\xee\x94I\u07d2\x1e\u0109QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94\x1d9[0\xad\xda\x1c\xf2\x1f\t\x1aOJ{u3q\x18\x94A\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x1dEXn\xb8\x03\xca!\x90e\v\xf7H\xa2\xb1t1+\xb5\a\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1dW.\xdd-\x87\xca'\x1ag\x14\xc1Z;7v\x1d\u0320\x05\x89\x06\xeb\xd5*\x8d\xdd9\x00\x00\u07d4\x1dc0\x97\xa8R%\xa1\xffC!\xb1)\x88\xfd\xd5\\+8D\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x1di\xc8=(\xff\x04t\xce\xeb\xea\xcb:\xd2'\xa1D\xec\u78ca\x01(\xcc\x03\x92\nb\u0480\x00\u07d4\x1d\x96\xbc\u0544W\xbb\xf1\xd3\u00a4o\xfa\xf1m\xbf}\x83hY\x89\tIr\t\xd8F~\x80\x00\u07d4\x1d\x9ej\xaf\x80\x19\xa0_#\x0e]\xef\x05\xaf]\x88\x9b\xd4\xd0\xf2\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x1d\xab\x17.\xff\xa6\xfb\xeeSL\x94\xb1~yN\xda\xc5OU\xf8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x1d\xb9\xac\x9a\x9e\xae\xec\nR7W\x05\fq\xf4rx\xc7-P\x89Hz\x9a0E9D\x00\x00\u07d4\x1d\xbe\x8e\x1c+\x8a\x00\x9f\x85\xf1\xad<\xe8\r.\x055\x0e\u3709\aW\rn\x9e\xbb\xe4\x00\x00\u07d4\x1d\xc7\xf7\xda\xd8]\xf5?\x12q\x15$\x03\xf4\xe1\xe4\xfd\xb3\xaf\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1d\u03bc\xb7em\xf5\u072a3h\xa0U\xd2/\x9e\xd6\xcd\xd9@\x89\x1b\x18\x1eK\xf24<\x00\x00\xe0\x94\x1d\xd7tA\x84J\xfe\x9c\xc1\x8f\x15\xd8\xc7{\xcc\xfbe^\xe04\x8a\x01\x06\xebEW\x99D\x88\x00\x00\u07d4\x1d\xde\xfe\xfd5\xab\x8fe\x8b$q\xe5G\x90\xbc\x17\xaf\x98\u07a4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1d\xee\xc0\x1a\xbe\\\r\x95-\xe9\x10l=\xc3\x069\xd8P\x05\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\x1d\xf6\x91\x16rg\x9b\xb0\xef5\t\x03\x8c\f'\xe3\x94\xfd\xfe0\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\x1d\xfa\xee\ar\x12\xf1\xbe\xaf\x0eo/\x18@Sz\xe1T\xad\x86\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x1e\x06\r\xc6\xc5\xf1\u02cc\xc7\xe1E.\x02\xee\x16u\b\xb5eB\x8a\x02\xb1O\x02\xc8d\xc7~\x00\x00\xe0\x94\x1e\x13\xecQ\x14,\ubde2`\x83A,<\xe3QD\xbaV\xa1\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x1e\x1aH(\x11\x9b\xe3\t\xbd\x88#nMH+PM\xc5W\x11\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\x1e\x1a\ud178leb\u02cf\xa1\xebo\x8f;\xc9\u072eny\x89\xf4\xd2\u0744%\x9b$\x00\x00\u07d4\x1e\x1ccQwj\xc3\x10\x919~\xcf\x16\x00-\x97\x9a\x1b-Q\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x1e\x1dz_$h\xb9N\xa8&\x98-\xbf!%yR*\xb7\xdf\n\u02ac\x9e\xee\xd3Y09\xe5\xacuy\x8a+\x14F\xddj\xef\xe4\x1c\x00\x00\u07d4\x1e{^M\x1fW+\xec\xf2\xc0\x0f\xc9\f\xb4v{Jn3\u0509\x06\x1f\xc6\x10u\x93\xe1\x00\x00\u07d4\x1e\x8eh\x9b\x02\x91|\xdc)$]\f\x9ch\xb0\x94\xb4\x1a\x9e\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xa34\xb5u\b\a\xeat\xaa\u016b\x86\x94\xec_(\xaaw\u03c9\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\x1e\xa4qU\x04\u01af\x10{\x01\x94\xf4\xf7\xb1\xcbo\xcc\xcdoK\x89 \x041\x97\xe0\xb0'\x00\x00\u07d4\x1e\xa4\x92\xbc\xe1\xad\x10~3\u007fK\u0527\xac\x9a{\xab\xcc\u036b\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x1e\xa6\xbf/\x15\xae\x9c\x1d\xbcd\u06a7\xf8\xeaM\r\x81\xaa\xd3\xeb\x89\u3bb5sr@\xa0\x00\x00\u07d4\x1e\xb4\xbfs\x15j\x82\xa0\xa6\x82 \x80\xc6\xed\xf4\x9cF\x9a\xf8\xb9\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\x1e\xba\xcbxD\xfd\xc3\"\xf8\x05\x90O\xbf\x19b\x80-\xb1S|\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x1e\xc4\xecKw\xbf\x19\u0411\xa8h\xe6\xf4\x91T\x18\x05A\xf9\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xd0n\xe5\x16b\xa8lcE\x88\xfbb\xdcC\xc8\xf2~|\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1e\u063b?\x06w\x8b\x03\x9e\x99a\xd8\x1c\xb7\x1as\xe6x|\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x1e\xda\bNye\x00\xba\x14\xc5\x12\x1c\r\x90\x84of\xe4\xbeb\x89\x1c\xfd\xd7F\x82\x16\xe8\x00\x00\u07d4\x1e\xeel\xbe\xe4\xfe\x96\xadaZ\x9c\xf5\x85zdy@\u07ccx\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4\x1e\xf2\u073f\xe0\xa5\x00A\x1d\x95n\xb8\u0213\x9c=l\xfef\x9d\x89*\x11)\u0413g \x00\x00\xe0\x94\x1e\xf5\xc9\xc76P\u03fb\xde\\\x88U1\xd4'\xc7\xc3\xfeUD\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x1f\x04\x12\xbf\xed\u0356N\x83}\t,q\xa5\xfc\xba\xf3\x01&\xe2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\x17O@\xa0Dr4\xe6fS\x91Mu\xbc\x00>V\x90\u0709\b\xacr0H\x9e\x80\x00\x00\u07d4\x1f!\x86\xde\xd2>\f\xf9R\x16\x94\xe4\xe1dY>i\n\x96\x85\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x1f*\xfc\n\xed\x11\xbf\xc7\x1ew\xa9\ae{6\xeav\xe3\xfb\x99\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\x1f9Y\xfc)\x11\x10\xe8\x822\xc3kvg\xfcx\xa3ya?\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x1f=\xa6\x8f\xe8~\xafC\xa8)\xabm~\u0166\xe0\t\xb2\x04\xfb\x89\x1e\x16\x01u\x8c,~\x00\x00\u07d4\x1fI\xb8m\r9EY\x06\x98\xa6\xaa\xf1g<7u\\\xa8\r\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\x1f_;4\xbd\x13K'\x81\xaf\xe5\xa0BJ\u0144l\xde\xfd\x11\x89\x05]\xe6\xa7y\xbb\xac\x00\x00\u07d4\x1fo\x0004\x97R\x06\x1c\x96\a+\xc3\xd6\xeb5I \x8dk\x89\x01K\x8d\xe1\xeb\x88\u06c0\x00\u07d4\x1f}\x8e\x86\xd6\xee\xb0%E\xaa\xd9\x0e\x912{\xd3i\xd7\xd2\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\x81\x16\xbd\n\xf5W\x0e\xaf\fV\u011cz\xb5\xe3zX\x04X\x89lk\x93[\x8b\xbd@\x00\x00\u0794\x1f\x88\xf8\xa13\x8f\xc7\xc1\tv\xab\xcd?\xb8\u04c5T\xb5\uc708\xb9\xf6]\x00\xf6<\x00\x00\u07d4\x1f\x9c2hE\x8d\xa3\x01\xa2\xbeZ\xb0\x82W\xf7{\xb5\xa9\x8a\xa4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x1f\xa21\x9f\xed\x8c-F*\xdf.\x17\xfe\xecjo0Qn\x95\x89\x06\xca\xe3\x06!\xd4r\x00\x00\u07d4\x1f\xb4c\xa08\x99\x83\xdf}Y?{\xddmxI\u007f\xed\x88y\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x1f\xb7\xbd1\r\x95\xf2\xa6\u067a\xaf\x8a\x8aC\n\x9a\x04E:\x8b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x1f\xcc|\xe6\xa8HX\x95\xa3\x19\x9e\x16H\x1fr\xe1\xf7b\xde\xfe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x1f\xcf\xd1\xd5\u007f\x87\"\x90V\f\xb6-`\x0e\x1d\xef\xbe\xfc\xcc\x1c\x89P\xc5\xe7a\xa4D\b\x00\x00\u0794\x1f\u0496\xbe\x03\xads|\x92\xf9\u0186\x9e\x8d\x80\xa7\x1cW\x14\xaa\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x1f\xdd\xd8_\u024b\xe9\xc4\x04Ya\xf4\x0f\x93\x80^\xccEI\xe5\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4 \x01\xbe\xf7{f\xf5\x1e\x15\x99\xb0/\xb1\x10\x19J\x00\x99\xb7\x8d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4 \x02d\xa0\x9f\x8ch\xe3\xe6b\x97\x95(\x0fV%O\x86@\u0409\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \x03qy\a\xa7%`\xf40\u007f\x1b\xee\xccT6\xf4=!\xe7\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4 \r\xfc\vq\xe3Y\xb2\xb4eD\n6\xa6\xcd\xc3Rw0\a\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4 \x13L\xbf\xf8\x8b\xfa\xdcFkR\xec\ua9d8W\x89\x1d\x83\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4 \x14&\x1f\x01\b\x9fSyV0\xba\x9d\xd2O\x9a4\xc2\xd9B\x89Hz\x9a0E9D\x00\x00\u07d4 \x16\x89]\xf3,\x8e\xd5G\x82iF\x84#\xae\xa7\xb7\xfb\xceP\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \x18\x1cKA\xf6\xf9r\xb6iX!_\x19\xf5p\xc1]\xdf\xf1\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4 \x18d\xa8\xf7\x84\xc2'{\v|\x9e\xe74\xf7\xb3w\xea\xb6H\x89\xf2(\x14\x00\xd1\xd5\xec\x00\x00\u07d4 \xb8\x1a\xe59&\xac\xe9\xf7\xd7AZ\x05\f\x03\x1dX_ \x89\x12\u007f\x19\xe8>\xb3H\x00\x00\xe0\x94 \x1d\x9e\xc1\xbc\v\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4 \xa1RV\xd5\f\xe0X\xbf\x0e\xacC\xaaS:\xa1n\u0273\x80\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4 \xa2\x9cPy\xe2k?\x181\x8b\xb2\xe5\x0e\x8e\x8b4n[\xe8\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4 \xa8\x16\x80\xe4e\xf8\x87\x90\xf0\aO`\xb4\xf3_]\x1ej\xa5\x89Ea\x80'\x8f\fw\x80\x00\u07d4 \xb9\xa9\u6f48\x80\u0659J\xe0\r\u0439(*\v\xea\xb8\x16\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4 \u0084\xba\x10\xa2\b0\xfc=i\x9e\xc9}-\xfa'\xe1\xb9^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4 \xd1A\u007f\x99\xc5i\u3fb0\x95\x85e0\xfe\x12\xd0\xfc\uaa89@\x15\xf9K\x11\x83i\x80\x00\u07d4 \u074f\u02f4n\xa4o\u3066\x8b\x8c\xa0\xea[\xe2\x1f\u9949lk\x93[\x8b\xbd@\x00\x00\xe0\x94 \xff>\u078c\xad\xb5\xc3{H\xcb\x14X\x0f\xb6^#\t\n{\x8a\b\xe4\xd3\x16\x82v\x86@\x00\x00\xe0\x94!\x008\x1d`\xa5\xb5J\xdc\t\u0456\x83\xa8\xf6\u057bK\xfb\u02ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94!\x18\xc1\x16\xab\f\xdfo\xd1\x1dT\xa40\x93\a\xb4w\xc3\xfc\x0f\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94!\x1b)\xce\xfcy\xae\x97gD\xfd\xeb\u03bd<\xbb2\xc5\x13\x03\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4! l\xe2.\xa4\x80\xe8Y@\xd3\x13\x14\xe0\xd6ONM:\x04\x8965\u026d\xc5\u07a0\x00\x00\u07d4!2\xc0Qj.\x17\x17J\xc5G\xc4;{\x00 \xd1\xebLY\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94!@\x8bMz,\x0en\xcaAC\xf2\xca\u037b\u033a\x12\x1b\u060a\x04<3\xc1\x93ud\x80\x00\x00\u07d4!Kt9U\xa5\x12\xden\r\x88j\x8c\xbd\x02\x82\xbe\xe6\u04a2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!L\x89\u017d\x8e}\"\xbcWK\xb3^H\x95\x02\x11\xc6\xf7v\x89\x01\x06T\xf2X\xfd5\x80\x00\xe0\x94!Ti\x14\xdf\u04ef*\xddA\xb0\xff>\x83\xff\xdat\x14\xe1\xe0\x8a\x01C\x95\xe78ZP.\x00\x00\u07d4!X.\x99\xe5\x02\xcb\xf3\xd3\xc2;\xdf\xfbv\xe9\x01\xacmV\xb2\x89\x05k\xc7^-c\x10\x00\x00\u07d4!Y$\b\x13\xa70\x95\xa7\xeb\xf7\u00f3t>\x80(\xae_\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!`\xb4\xc0,\xac\n\x81\u0791\b\xdeCE\x90\xa8\xbf\xe6\x875\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94!nA\x86N\xf9\x8f\x06\r\xa0\x8e\xca\xe1\x9a\xd1\x16j\x17\xd06\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4!\x84o/\xdfZA\xed\x8d\xf3n^\xd8TM\xf7Y\x88\xec\xe3\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94!\xa6\xdbe'F{\xc6\xda\xd5K\xc1n\x9f\xe2\x95;g\x94\xed\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4!\xa6\xfe\xb6\xab\x11\xc7f\xfd\xd9w\xf8\xdfA!\x15_G\xa1\xc0\x89\x03\x19\xcf8\xf1\x00X\x00\x00\u07d4!\xb1\x82\xf2\xda+8D\x93\xcf_5\xf8=\x9d\x1e\xe1O*!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!\xbf\xe1\xb4\\\xac\xdebt\xfd\x86\b\u0661x\xbf>\xebn\u0709l\xee\x06\u077e\x15\xec\x00\x00\u07d4!\xc0s\x80HOl\xbc\x87$\xad2\xbc\x86L;Z\xd5\x00\xb7\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94!\u00e8\xbb\xa2g\xc8\u0322{\x1a\x9a\xfa\xba\xd8o`z\xf7\b\x8a\x01\xe4\xa3lI\u06580\x00\x00\u07d4!\xcem[\x90\x18\xce\xc0J\u0596yD\xbe\xa3\x9e\x800\xb6\xb8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4!\xd0'\x05\xf3\xf6I\x05\xd8\x0e\xd9\x14y\x13\xea\x8cs\a\u0595\x89I\xed\xb1\xc0\x98\x876\x00\x00\u07d4!\xd1?\f@$\xe9g\xd9G\a\x91\xb5\x0f\"\xde:\xfe\xcf\x1b\x89\xf1Z\xd3^.1\xe5\x00\x00\xe0\x94!\xdb\u06c1z\r\x84\x04\u01bd\xd6\x15\x047N\x9cC\xc9!\x0e\x8a\x02\x1e\x18\xb9\xe9\xabE\xe4\x80\x00\xe0\x94!\xdf\x1e\xc2KNK\xfey\xb0\xc0\x95\u03ba\xe1\x98\xf2\x91\xfb\u044a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94!\xdf-\u036ft\xb2\xbf\x804\x04\xddM\xe6\xa3^\xab\xec\x1b\xbd\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4!\xe2\x19\u021c\xa8\xac\x14\xaeL\xbaa0\xee\xb7}\x9em9b\x89*\u035f\xaa\xa08\xee\x00\x00\u07d4!\xe5\u04ba\xe9\x95\xcc\xfd\b\xa5\xc1k\xb5$\xe1\xf60D\x8f\x82\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4!\xe5\xd7s 0L \x1c\x1eS\xb2a\xa1#\u0421\x06>\x81\x89\x04\xb6\xfa\x9d3\xddF\x00\x00\xe0\x94!\xea\xe6\xfe\xff\xa9\xfb\xf4\u0347OG9\xac\xe50\u033eY7\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4!\xec\xb2\u07e6Wy\xc7Y-\x04\x1c\xd2\x10Z\x81\xf4\xfdNF\x8965\u026d\xc5\u07a0\x00\x00\u07d4!\uff20\x9b5\x80\xb9\x8es\xf5\xb2\xf7\xf4\xdc\v\xf0,R\x9c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4!\xfd\v\xad\xe5\xf4\xeftt\xd0X\xb7\xf3\xd8T\xcb\x13\x00RN\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94!\xfdG\xc5%`\x12\x19\x8f\xa5\xab\xf11\xc0mj\xa1\x96_u\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4!\xfdl]\x97\xf9\xc6\x00\xb7h!\xdd\xd4\xe7v5\x0f\xce+\xe0\x89lj\u04c2\xd4\xfba\x00\x00\u07d4\"\r\u018d\xf0\x19\xb6\xb0\u033f\xfbxKZZ\xb4\xb1]@`\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\"\x0e+\x92\xc0\xf6\xc9\x02\xb5\x13\xd9\xf1\xe6\xfa\xb6\xa8\xb0\xde\xf3\u05c9+^:\xf1k\x18\x80\x00\x00\u07d4\"V\x1cY1\x14560\x9c\x17\xe82X{b\\9\v\x9a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\"W\xfc\xa1jn\\*d|<)\xf3l\xe2)\xab\x93\xb1~\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\"]5\xfa\xed\xb3\x91\u01fc-\xb7\xfa\x90q\x16\x04\x05\x99m\x00\x89\t\x18T\xfc\x18bc\x00\x00\u07d4\"_\x9e\xb3\xfbo\xf3\xe9\xe3\xc8D~\x14\xa6n\x8dO7y\xf6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\"r\x18n\xf2}\xcb\xe2\xf5\xfc70P\xfd\xae\u007f*\xce#\x16\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4\"s\xba\u05fcNHv\"\xd1u\xefzf\x98\x8bj\x93\xc4\xee\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\"v&K\xec\x85&\xc0\xc0\xf2pgz\xba\xf4\xf0\xe4A\xe1g\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\"\x82B\xf83n\xec\xd8$.\x1f\x00\x0fA\x93~q\xdf\xfb\xbf\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\"\x84*\xb80\xdaP\x99\x13\xf8\x1d\xd1\xf0O\x10\xaf\x9e\xdd\x1cU\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\"\x94O\xbc\xa9\xb5yc\bN\xb8M\xf7\xc8_\xb9\xbc\u07f8V\x89\xfc\x11\x8f\uf43a8\x80\x00\u07d4\"\x9c\xc4q\x1bbu^\xa2\x96DZ\u00f7\u007f\xc63\x82\x1c\xf2\x89\x02#\xe8\xb0R\x192\x80\x00\u0794\"\x9eC\r\xe2\xb7OD&Q\xdd\u0377\x01v\xbc\x05L\xadT\x88\xbb\xf9\x81\xbcJ\xaa\x80\x00\u07d4\"\x9fO\x1a*OT\atP[G\a\xa8\x1d\xe4D\x10%[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\"\x9f\xf8\v\xf5p\x80\t\xa9\xf79\xe0\xf8\xb5`\x91@\x16\u0566\x89\x12\x11\xec\xb5m\x13H\x80\x00\u07d4\"\xa2X\x12\xabV\xdc\xc4#\x17^\xd1\u062d\xac\xce3\xcd\x18\x10\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94\"\xb9j\xb2\xca\xd5]\xb1\x00\xb50\x01\xf9\xe4\xdb7\x81\x04\xc8\a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\"\xbd\xff\xc2@\xa8\x8f\xf7C\x1a\xf3\xbf\xf5\x0e\x14\xda7\xd5\x18>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\"\xce4\x91Y\xee\xb1D\xef\x06\xff&6X\x8a\xefy\xf6(2\x89\n1\x06+\xee\xedp\x00\x00\u07d4\"\xdbU\x9f,<\x14u\xa2\xe6\xff\xe8:YyY\x91\x96\xa7\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\"\xe1QX\xb5\xee>\x86\xeb\x032\xe3\u6a6cl\u0675^\u0349\b\xacr0H\x9e\x80\x00\x00\u07d4\"\xe2H\x8e-\xa2jI\xae\x84\xc0\x1b\xd5K!\xf2\x94x\x91\u0189]\u0212\xaa\x111\xc8\x00\x00\u07d4\"\xe5\x12\x14\x9a\x18\xd3i\xb7\x86\xc9\xed\xab\xaf\x1d\x89N\xe0.g\x14a\\\x00\x00\u07d4\"\xeb}\xb0\xbaV\xb0\xf8\xb8\x16\u0332\x06\xe6\x15\xd9)\x18[\r\x89\x04])s~\"\xf2\x00\x00\u07d4\"\xee\xd3'\xf8\xeb\x1d\x138\xa3\xcb{\x0f\x8aK\xaaY\a\u0355\x89\x01E]_Hw\b\x80\x00\xe0\x94\"\xf0\x04\u07cd\xe9\xe6\xeb\xf5#\u032c\xe4W\xac\xcb&\xf9r\x81\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794\"\xf2\xdc\xffZ\u05cc>\xb6\x85\v\\\xb9Q\x12{e\x95\"\u623e -j\x0e\xda\x00\x00\u07d4\"\xf3\xc7y\xddy\x02>\xa9*x\xb6\\\x1a\x17\x80\xf6-\\J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\"\xfe\x88M\x907)\x1bMR\xe6(Z\xe6\x8d\xea\v\xe9\xff\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\x06\u07d3\x1a\x94\rX\xc0\x16e\xfaM\b\x00\x80,\x02\xed\xfe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94#\t\xd3@\x91D[22Y\v\xd7\x0fO\x10\x02[,\x95\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4#\x12\x00F\xf6\x83!\x02\xa7R\xa7fVi\x1c\x86>\x17\u5709\x11\xe0\xe4\xf8\xa5\v\xd4\x00\x00\u07d4#\x1a\x15\xac\xc1\x99\u021f\xa9\xcb\"D\x1c\xc7\x030\xbd\xcc\xe6\x17\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4#\x1d\x94\x15]\xbc\xfe*\x93\xa3\x19\xb6\x17\x1fc\xb2\v\u04b6\xfa\x89\xcf\x14{\xb9\x06\xe2\xf8\x00\x00\u07d4#(2\xcdYw\xe0\nL0\xd0\x16?.$\xf0\x88\xa6\xcb\t\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4#,m\x03\xb5\xb6\xe6q\x1e\xff\xf1\x90\xe4\x9c(\xee\xf3l\x82\xb0\x89Hz\x9a0E9D\x00\x00\xe0\x94#,\xb1\xcdI\x99<\x14J?\x88\xb3a\x1e#5i\xa8k\u058a\x03L`lB\u042c`\x00\x00\u07d4#,\xe7\x82Pb%\xfd\x98`\xa2\xed\xc1Jz0Gsm\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4#/R]U\x85\x9b}N`\x8d H\u007f\xaa\xdb\x00)15\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94#4\u0150\u01e4\x87i\x100E\u0176SL\x8a4i\xf4J\x8a\x03\xb1\x99\a=\xf7-\xc0\x00\x00\u07d4#7n\u02bftl\xe53!\xcfB\xc8fI\xb9+g\xb2\xff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#7\x8fB\x92m\x01\x84\xb7\x93\xb0\xc8'\xa6\xdd>=3O\u0349\x03\t'\xf7L\x9d\xe0\x00\x00\u07d4#8B\xb1\xd0i/\xd1\x11@\xcfZ\u0364\xbf\x960\xba\xe5\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#9\xe9I(p\xaf\xea%7\xf3\x89\xac/\x83\x83\x02\xa3<\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#;\xdd\xdd]\xa9HR\xf4\xad\xe8\xd2\x12\x88V\x82\xd9\ak\u0189\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#OF\xba\xb7?\xe4]1\xbf\x87\xf0\xa1\xe0Fa\x99\xf2\ubb09\x1aJ\xba\"\\ t\x00\x00\u07d4#U\x1fV\x97_\xe9+1\xfaF\x9cI\xeaf\xeefb\xf4\x1e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4#V\x95B\xc9}V`\x18\xc9\a\xac\xfc\xf3\x91\xd1@g\xe8~\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94#_\xa6l\x02^\xf5T\x00p\xeb\xcf\r7-\x81w\xc4g\xab\x8a\a\x12\x9e\x1c\xdf7>\xe0\x00\x00\xe0\x94#r\xc4\xc1\u0253\x9fz\xafl\xfa\xc0@\x90\xf0\x04t\x84\n\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4#s\f5z\x91\x02nD\xb1\xd0\xe2\xfc*Q\xd0q\xd8\xd7{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#v\xad\xa9\x033\xb1\u0441\bL\x97\xe6E\xe8\x10\xaa[v\xf1\x89(\xa8WBTf\xf8\x00\x00\u07d4#x\xfdC\x82Q\x1e\x96\x8e\u0452\x10g7\xd3$\xf4T\xb55\x8965\u026d\xc5\u07a0\x00\x00\u07d4#\x82\xa9\u050e\xc8>\xa3e(\x90\xfd\x0e\u7710{[-\xc1\x89\a?u\u0460\x85\xba\x00\x00\u07d4#\x83\xc2\"\xe6~\x96\x91\x90\xd3!\x9e\xf1M\xa3xP\xe2lU\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\x8akv5%/RDHl\n\xf0\xa7: s\x85\xe09\x89JD\x91\xbdm\xcd(\x00\x00\u07d4#\x9as>k\x85Z\u0152\xd6c\x15a\x86\xa8\xa1t\xd2D\x9e\x89X\xbe7X\xb2A\xf6\x00\x00\xe0\x94#\xab\t\xe7?\x87\xaa\x0f;\xe0\x13\x9d\xf0\xc8\xebk\xe5cO\x95\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94#\xab\xd9\xe9>yW\xe5\xb66\xbeey\x05\x1c\x15\xe5\xce\v\x0e\x8a\x03\xa3\xc8\xf7\xcb\xf4,8\x00\x00\u07d4#\xb1\u0111\u007f\xbd\x93\xee=H8\x93\x06\x95s\x84\xa5Il\xbf\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94#\xba8d\xdaX=\xabV\xf4 \x87<7g\x96\x90\xe0/\x00\x8a\x02\x13BR\r_\xec \x00\x00\u07d4#\xc5Z\xebW9\x87o\n\xc8\xd7\xeb\xea\x13\xber\x96\x85\xf0\x00\x89Hz\x9a0E9D\x00\x00\u07d4#\u025b\xa0\x87D\x8e\x19\xc9p\x1d\xf6n\f\xabR6\x831\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xcc\xc3\u01ac\xd8\\.F\fO\xfd\xd8+\xc7]\xc8I\xea\x14\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4#\xcd%\x98\xa2\x0e\x14\x9e\xad*\u0593yWn\xce\xdb`\u3389lk\x93[\x8b\xbd@\x00\x00\u07d4#\u07cfH\xee\x00\x92V\xeay~\x1f\xa3i\xbe\xeb\xcfk\xc6c\x89|\xd3\xfa\xc2m\x19\x81\x80\x00\u07d4#\xe2\u01a8\xbe\x8e\n\u03e5\xc4\xdf^6\x05\x8b\xb7\u02ecZ\x81\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xeaf\x9e5d\x81\x9a\x83\xb0\xc2l\x00\xa1m\x9e\x82olF\x89M\x8dl\xa9h\xca\x13\x00\x00\u07d4#\xebo\xd8Vq\xa9\x06:\xb7g\x8e\xbe&Z \xf6\x1a\x02\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4#\xf9\xec\xf3\xe5\xdd\u0723\x88\x15\xd3\xe5\x9e\xd3K[\x90\xb4\xa3S\x89\v\x17\x81\xa3\xf0\xbb \x00\x00\u07d4#\xfa~\xb5\x1aH\"\x95\x98\xf9~v+\xe0\x86\x96R\xdf\xfcf\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94$\x03\x05rs\x13\xd0\x1esT,w_\xf5\x9d\x11\xcd5\xf8\x19\x8a\x01A\x88Vf\x80\u007f\\\x80\x00\u07d4$\x04k\x91\u069ba\xb6)\u02cb\x8e\xc0\xc3Q\xa0~\a\x03\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4$\x0eU\x9e'J\xae\xf0\xc2X\x99\x8c\x97\x9fg\x1d\x11s\xb8\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94$\x13aU\x9f\xee\xf8\x0e\xf170!S\xbd\x9e\xd2\xf2]\xb3\xef\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94$;;\xcaj)\x93Y\xe8\x86\xce3\xa3\x03A\xfa\xfeMW=\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4$<\x84\xd1$ W\f\xc4\xef;\xab\xa1\xc9Y\u0083$\x95 \x89\u007f\x1fi\x93\xa8S\x04\x00\x00\xe0\x94$CJ>2\xe5N\xcf'/\xe3G\v_oQ/gU \x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4$HYo\x91\xc0\x9b\xaa0\xbc\x96\x10j-7\xb5p^](\x89lk\x93[\x8b\xbd@\x00\x00\u0794$Xn\xc5E\x175\xee\xaa\xebG\r\xc8sj\xaeu/\x82\xe5\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4$X\xd6U_\xf9\x8a\x12\x9c\xce@7\x95=\x00 n\xffB\x87\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4$b\x91\x16[Y3-\xf5\xf1\x8c\xe5\u0248V\xfa\xe9X\x97\u0589\\(=A\x03\x94\x10\x00\x00\u07d4$g\u01a5\u0196\xed\xe9\xa1\xe5B\xbf\x1a\xd0k\xccK\x06\xac\xa0\x89\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4$v\xb2\xbbu\x1c\xe7H\xe1\xa4\xc4\xff{#\v\xe0\xc1]\"E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4$z\n\x11\xc5\u007f\x03\x83\xb9I\xdeT\vf\xde\xe6\x86\x04\xb0\xa1\x899\xfb\xae\x8d\x04-\xd0\x00\x00\u07d4$\x87\xc3\u013e\x86\xa2r=\x91|\x06\xb4XU\x01p\xc3\xed\xba\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\x89\xac\x12i4\xd4\u05a9M\xf0\x87C\xda{v\x91\xe9y\x8e\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\x9d\xb2\x9d\xbc\x19\xd1#]\xa7)\x8a\x04\b\x1c1WB\u9b09a\xac\xff\x81\xa7\x8a\xd4\x00\x00\u07d4$\xa4\xeb6\xa7\xe4\x98\xc3o\x99\x97\\\x1a\x8dr\x9f\u05b3\x05\u05c9\r\xfcx!\x0e\xb2\xc8\x00\x00\u07d4$\xa7P\xea\xe5\x87G\x11\x11m\xd7\xd4{q\x86\u0399\r1\x03\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4$\xaa\x11Q\xbbv_\xa3\xa8\x9c\xa5\x0e\xb6\xe1\xb1\xc7\x06A\u007f\u0509\xa8\r$g~\xfe\xf0\x00\x00\u0794$\xac\xa0\x8d[\xe8^\xbb\x9f12\xdf\xc1\xb6 \x82N\xdf\xed\xf9\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4$\xb2\xbe\x11\x8b\x16\u0632\x17Gi\xd1{L\xf8O\a\u0294m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4$\xb8\xb4F\u07bd\x19G\x95]\u0404\xf2\xc5D\x933F\u04ed\x89\xeaim\x90@9\xbd\x80\x00\u07d4$\xb9^\xbe\xf7\x95\x00\xba\xa0\xed\xa7.w\xf8wA]\xf7\\3\x891T\xc9r\x9d\x05x\x00\x00\u07d4$\xb9\xe6dOk\xa4\xcd\xe1&'\r\x81\xf6\xab`\xf2\x86\xdf\xf4\x89\a?u\u0460\x85\xba\x00\x00\u07d4$\xbdY\x04\x05\x90\x91\xd2\xf9\xe1-j&\xa0\x10\xca\"\xab\x14\xe8\x89e\xea=\xb7UF`\x00\x00\u07d4$\xc0\u020bT\xa3TG\t\x82\x8a\xb4\xab\x06\x84\x05Y\xf6\xc5\u2250\xf54`\x8ar\x88\x00\x00\u07d4$\xc1\x17\xd1\u04b3\xa9z\xb1\x1aFy\u025awJ\x9e\xad\xe8\u044965\u026d\xc5\u07a0\x00\x00\u07d4$\xcf\xf0\xe93j\x9f\x80\xf9\xb1\u02d6\x8c\xafk\x1d\x1cI2\xa4\x89\n\xdaUGK\x814\x00\x00\u07d4$\u06aa\xdd\xf7\xb0k\xbc\ua6c0Y\x00\x85\xa8\x85gh+N\x89\x11K \x15\u04bb\xd0\x00\x00\u07d4$\xdc\xc2K\xd9\xc7!\f\xea\u03f3\r\xa9\x8a\xe0JM{\x8a\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4$\xf7E\r\xdb\xf1\x8b\x02\x0f\xeb\x1a 2\xd9\xd5Kc>\xdf7\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4$\xfcs\xd2\a\x93\t\x8e\t\u076bW\x98Pb$\xfa\x1e\x18P\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4$\xfd\x9al\x87L/\xab?\xf3n\x9a\xfb\xf8\xce\r2\xc7\u0792\x89Hz\x9a0E9D\x00\x00\u07d4%\n@\xce\xf3 #\x97\xf2@F\x95H\xbe\xb5bj\xf4\xf2<\x89\x05\x03\xb2\x03\xe9\xfb\xa2\x00\x00\u07d4%\niC\av\xf64w\x03\xf9R\x97\x83\x95Za\x97\xb6\x82\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4%\x0e\xb7\xc6o\x86\x9d\xdfI\u0685\xf39>\x98\f\x02\x9a\xa44\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%\x10j\xb6u]\xf8mkc\xa1\x87p;\f\xfe\xa0\u5520\x89\x01|@Z\xd4\x1d\xb4\x00\x00\xe0\x94%\x18_2Z\xcf-dP\x06\x98\xf6\\v\x9d\xdfh0\x16\x02\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4%\x1c\x12r,hy\"y\x92\xa3\x04\xeb5v\xcd\x18CN\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\x1eh8\xf7\xce\u0173\x83\xc1\xd9\x01F4\x12t\xda\xf8\xe5\x02\x89\a\xff\x1c\xcbua\xdf\x00\x00\u07d4%%\x9d\x97Z!\xd8:\xe3\x0e3\xf8\x00\xf5?7\u07e0\x198\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4%({\x81_\\\x828\ns\xb0\xb1?\xba\xf9\x82\xbe$\xc4\u04c9\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94%+eU\xaf\u0700\xf2\xd9m\x97-\x17\u06c4\xeaZ\xd5!\xac\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4%8S)6\x81<\x91\xe6S(O\x01|\x80\u00f8\xf8\xa3o\x89l\x87T\xc8\xf3\f\b\x00\x00\xe0\x94%>2\xb7N\xa4I\n\xb9&\x06\xfd\xa0\xaa%{\xf2=\u02cb\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94%?\x1et*,\uc1b0\u05f3\x06\xe5\xea\xcbl\xcb/\x85T\x8a\x04>^\xde\x1f\x87\x8c \x00\x00\u07d4%A1J\v@\x8e\x95\xa6\x94DIwq*Pq5\x91\xab\x89X\x9e\x1a]\xf4\u05f5\x00\x00\u07d4%L\x1e\xccc\f(w\u0780\x95\xf0\xa8\u06e1\xe8\xbf\x1fU\f\x89\\(=A\x03\x94\x10\x00\x00\u07d4%Z\xbc\x8d\b\xa0\x96\xa8\x8f=j\xb5_\xbcsR\xbd\u0739\u0389\x04t6\x821>\u0780\x00\u07d4%[\xdddt\u0302b\xf2j\"\u00cfE\x94\x0e\x1c\ue99b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%`\xb0\x9b\x89\xa4\xaehI\xedZ<\x99XBf1qDf\x89\\(=A\x03\x94\x10\x00\x00\u07d4%a\xa18\xdc\xf8;\xd8\x13\xe0\xe7\xf1\bd+\xe3\xde=o\x05\x8964\xf4\x84\x17@\x1a\x00\x00\u0794%a\xec\x0f7\x92\x18\xfe^\xd4\xe0(\xa3\xf7D\xaaAuLr\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u0794%b\x92\xa1\x91\xbd\xda4\xc4\xdakk\u0591G\xbfu\u2a6b\x88\xc2\xff.\r\xfb\x03\x80\x00\u07d4%i~\xf2\f\u032ap\xd3-7o\x82r\xd9\xc1\a\f=x\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4%o\xa1P\u0307\xb5\x05j\a\xd0\x04\xef\xc8E$s\x9eb\xb5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4%r\x1c\x87\xb0\xdc!7|r\x00\xe5$\xb1J\"\xf0\xafi\xfb\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4%\x899\xbb\xf0\f\x9d\xe9\xafS8\xf5\xd7\x14\xab\xf6\xd0\xc1\xc6q\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94%\x90\x12hp\xe0\xbd\xe8\xa6c\xab\x04\nr\xa5W=\x8dA\u008a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4%\x9e\xc4\xd2e\xf3\xabSk|p\xfa\x97\xac\xa1Bi,\x13\xfc\x89\x01\x1b\x1b[\xea\x89\xf8\x00\x00\xe0\x94%\xa5\x00\xee\xeczf*\x84\x15R\xb5\x16\x8bp{\r\xe2\x1e\x9e\x8a\x02\x1f/o\x0f\xc3\xc6\x10\x00\x00\xe0\x94%\xa5\xa4M8\xa2\xf4Lj\x9d\xb9\u037ck\x1e.\x97\xab\xb5\t\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4%\xa7L*\xc7]\u023a\xa8\xb3\x1a\x9c|\xb4\xb7\x82\x9b$V\u0689lk\x93[\x8b\xbd@\x00\x00\xe0\x94%\xad\xb8\xf9o9I,\x9b\xb4|^\u0708bNF\aV\x97\x8a\x05\xa9\x94\v\xc5hyP\x00\x00\u07d4%\xae\xe6\x8d\t\xaf\xb7\x1d\x88\x17\xf3\xf1\x84\xecV/x\x97\xb74\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\xb0S;\x81\xd0*a{\x92)\xc7\xec]o/g.[Z\x8965\u026d\xc5\u07a0\x00\x00\u07d4%\xb7\x8c\x9f\xad\x85\xb43C\xf0\xbf\xcd\x0f\xac\x11\u0254\x9c\xa5\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4%\xbcI\xef(\x8c\xd1e\xe5%\xc6a\xa8\x12\u03c4\xfb\xec\x8f3\x89\x12Y!\xae\xbd\xa9\xd0\x00\x00\u07d4%\xbd\xfa>\xe2o8Ia{#\x00bX\x8a\x97\xe3\xca\xe7\x01\x8965\xe6\x19\xbb\x04\xd4\x00\x00\u07d4%\xc1\xa3~\xe5\xf0\x82e\xa1\xe1\r=\x90\xd5G)U\xf9x\x06\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4%\xc6\xe7O\xf1\xd9(\u07d8\x13z\xf4\u07c40\xdf$\xf0|\u05c9\x15$VU\xb1\x02X\x00\x00\xe0\x94%\xcf\xc4\xe2\\5\xc1;i\xf7\xe7}\xbf\xb0\x8b\xafXuk\x8d\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94%\xda\u0515\xa1\x1a\x86\xb9\xee\xec\xe1\xee\xec\x80^W\xf1W\xfa\xff\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94%\xe07\xf0\n\x18'\v\xa5\xec4 \"\x9d\xdb\n,\u33e2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4%\xe6a\xc99\x86:\xcc\x04No\x17\xb5i\x8c\xce7\x9e\xc3\u0309JD\x91\xbdm\xcd(\x00\x00\u07d4&\x04\x8f\xe8M\x9b\x01\nb\xe71b~I\xbc.\xb7?@\x8f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4&\x06\u00f3\xb4\xca\x1b\t\x14\x98`,\xb1\x97\x8b\xf3\xb9R!\xc0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4&\n#\x0eDe\a~\v\x14\xeeDB\xa4\x82\u0570\xc9\x14\xbf\x89Z\xf6\x06\xa0k[\x11\x80\x00\u07d4&\r\xf8\x94:\x8c\x9a]\xbayE2\u007f\xd7\xe0\x83|\x11\xad\a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4&\x14\xf4-]\xa8D7ux\xe6\xb4H\xdc$0[\xef+\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\x15\x10\x0e\xa7\xe2[\xba\x9b\xcat`X\xaf\xbb\xb4\xff\xbeBD\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4&\x15u\xe9\xcfY\xc8\"o\xa7\xaa\xf9\x1d\xe8o\xb7\x0fZ\u00ee\x89\x10C\xa4CjR?\x00\x00\xe0\x94&\x1e\x0f\xa6LQ\x13te\xee\xcf[\x90\xf1\x97\xf7\x93\u007f\xdb\x05\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4&*\x8b\xfd}\x9d\xc5\xdd:\u05c1a\xb6\xbbV\b$76U\x89?j\x83\x84\a+v\x00\x00\xe0\x94&*\xedK\xc0\xf4\xa4\xb2\xc6\xfb5y>\x83ZI\x18\x9c\xdf\xec\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94&-\xc16L\xcfm\xf8\\C&\x8e\xe1\x82UM\xaei.)\x8a\x01\v /\xect\xce\xd8\x00\x00\u07d4&8\x140\x9d\xe4\xe65\xcfX^\r6Tw\xfc@\xe6l\xf7\x89\a\xea(2uw\b\x00\x00\u07d4&9\xee\xe9\x87<\xee\xc2o\u0314T\xb5H\xb9\xe7\xc5J\xa6\\\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94&>W\xda\xcb\xe0\x14\x9f\x82\xfee\xa2fH\x98\x86o\xf5\xb4c\x8a\b\v\xfb\xef\xcb_\v\xc0\x00\x00\u07d4>\x19\xc0m_\x14z\xa5\x97$\x8e\xb4l\xf7\xbe\xfad\xa5\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4&L\xc8\bj\x87\x10\xf9\x1b!r\t\x05\x91,\u05d6J\xe8h\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94&S\x83\u058bR\xd04\x16\x1b\xfa\xb0\x1a\xe1\xb0G\x94/\xbc2\x8a\x04rq\xde\xe2\rt\\\x00\x00\u07d4&Y\xfa\xcb\x1e\x83CeS\xb5\xb4)\x89\xad\xb8\a_\x99S\xed\x89\x01\x97evw\x1a^\x00\x00\xe0\x94&o-\xa7\xf0\b^\xf3\xf3\xfa\t\xba\xee#+\x93\xc7D\xdb.\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4&qH\xfdr\xc5Ob\nY/\xb9'\x991\x9c\xc4S+\\\x89\x169\u46fa\x16(\x00\x00\xe0\x94&xJ\u0791\u0228:\x8e9e\x8c\x8d\x82wA<\u0319T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4&z~n\x82\xe1\xb9\x1dQ\xde\u0776D\xf0\xe9m\xbb\x1f\u007f~\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4&\x80q=@\x80\x8e*P\xed\x011P\xa2\xa6\x94\xb9j\u007f\x1d\x89a\t=|,m8\x00\x00\u07d4&\x97\xb39\x81;\f-\x96K$q\xeb\x1c`oN\u02d6\x16\x89>\x8e\xf7\x95\u0610\xc8\x00\x00\u07d4&\xa6\x8e\xab\x90Z\x8b=\xce\x00\xe3\x170\x82%\u06b1\xb9\xf6\xb8\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4&\xb1\x1d\x06e\x88\xcet\xa5r\xa8Zc(s\x92\x12\xaa\x8b@\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xba\xbfB\xb2g\xfd\xcf8a\xfd\xd4#j^GHH\xb3X\x8965\u026d\xc5\u07a0\x00\x00\u07d4&\xc0\x05Kp\r:|-\xcb\xe2uh\x9dOL\xad\x16\xa35\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xc2\xff\xc3\x0e\xfd\xc5'>v\x18:\x16\xc2i\x8dnS\x12\x86\x89*\x11)\u0413g \x00\x00\u07d4&\u025f\x88I\u0240+\x83\xc8a!\u007f\xd0z\x9e\x84\u0377\x9d\x89\x10CV\x1a\x88)0\x00\x00\u07d4&\xcf\xff\xd0R\x15+\xb3\xf9W\xb4x\xd5\xf9\x8b#:|+\x92\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4&\u0521h\x91\xf5)\"x\x92\x17\xfc\u0606\xf7\xfc\xe2\x96\xd4\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4&\xd4\xec\x17\xd5\u03b2\u0214\xbd\u015d\nji]\xad+C\u0309\x9f\x1fxv\x1d4\x1a\x00\x00\u07d4&\xe8\x01\xb6,\x82q\x91\xddh\xd3\x1a\x01\x19\x90\x94\u007f\xd0\xeb\xe0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4&\xe9\xe2\xadr\x97\x02bd\x17\xef%\xde\r\xc8\x00\xf7\xa7y\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4&\xf9\xf7\xce\xfd~9K\x9d9$A+\xf2\u0083\x1f\xaf\x1f\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94&\xfe\x17L\xbfRfP\xe0\xcd\x00\x9b\xd6\x12e\x02\u038ehM\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\xe0\x94&\xff\nQ\xe7\xce\u0384\x00'ix\xdb\xd6#n\xf1b\xc0\xe6\x8a\x15.\x18V'T\nP\x00\x00\u07d4'\x10\x1a\x0fV\u04da\x88\u0168O\x9b2L\xdd\xe3>\\\xb6\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'\x14L\xa9\xa7w\x1a\x83j\xd5\x0f\x80?d\xd8i\xb2\xae+ \x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4'\x14i\x13V:\xa7E\xe2X\x840\xd94\x8e\x86\xea|5\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4'\x1d=H\x1c\xb8\x8evq\xad!iI\xb66^\x060=\xe0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4' \xf9\xcaBn\xf2\xf2\xcb\xd2\xfe\xcd9\x92\fO\x1a\x89\xe1m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'*\x13\x1aZejz:\xca5\u023d \"\"\xa7Y\"X\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4'D\xffgFA!\xe3Z\xfc)\"\x17qd\xfa/\xcb\x02g\x89\x05k\xc7^-c\x10\x00\x00\u07d4'J=w\x1a=p\x97\x96\xfb\xc4\xd5\xf4\x8f\xce/\xe3\x8cy\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4'Mi\x17\x0f\xe7\x14\x14\x01\x88+\x88j\xc4a\x8cj\xe4\x0e\u06c93\xc5I\x901r\f\x00\x00\u07d4'R\x1d\xeb;n\xf1An\xa4\u01c1\xa2\xe5\u05f3n\xe8\x1ca\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'Xu\xffO\xbb\f\xf3\xa40!1'H\u007fv\b\xd0L\xba\x89\x1b\x1c\x01\x0evmX\x00\x00\u07d4'j\x00n0(\xec\xd4L\xdbb\xba\nw\u0394\xeb\xd9\xf1\x0f\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4'k\x05!\xb0\xe6\x8b'}\xf0\xbb2\xf3\xfdH2cP\xbf\xb2\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4'o\xd7\xd2O\x8f\x88?Zz()[\xf1qQ\u01e8K\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'p\xf1N\xfb\x16]\u07bay\xc1\v\xb0\xaf1\xc3\x1eY3L\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4'vw\xab\xa1\xe5,;S\xbf\xa2\a\x1dN\x85\x9a\n\xf7\xe8\xe1\x8965\u026d\xc5\u07a0\x00\x00\u07d4'\x82Ff\xd2x\xd7\x04#\xf0=\xfe\x1d\u01e3\xf0/C\u2d4966\xc2^f\xec\xe7\x00\x00\u07d4'\x83\f_`#\xaf\xaa\xf7\x97Egl J\x0f\xac\u0360\xba\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94'\x84\x90?\x1d|\x1b\\\xd9\x01\xf8\x87]\x14\xa7\x9b<\xbe*V\x8a\x04\xbd\xa7\xe9\xd7J\xd5P\x00\x00\u07d4'\x8c\v\xdec\x0e\u00d3\xb1\xe7&\u007f\xc9\xd7\xd9p\x19\xe4\x14[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4'\x98q\x10\"\x1a\x88\b&\xad\xb2\xe7\xab^\xcax\xc6\xe3\x1a\xec\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94'\xac\a;\xe7\x9c\xe6W\xa9:\xa6\x93\xeeC\xbf\x0f\xa4\x1f\xef\x04\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4'\xb1iN\xaf\xa1e\xeb\xd7\xcc{\u025et\x81J\x95\x14\x19\u0709+^:\xf1k\x18\x80\x00\x00\u07d4'\xb6(\x16\xe1\xe3\xb8\u045by\xd1Q=]\xfa\x85[\f:*\x89\x05j\xf5\xc1\xfdiP\x80\x00\u07d4'\xbf\x94<\x163\xfe2\xf8\xbc\xcc\xdbc\x02\xb4\a\xa5rND\x892\xf8Lm\xf4\b\xc0\x80\x00\u07d4'\xbf\x9fD\xba}\x05\xc35@\u00e5;\xb0,\xbb\xff\xe7\xc3\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4'\xc2\xd7\xcaPM\xaa=\x90f\xdc\t\x13}\xc4/:\xaa\xb4R\x89 \x86\xac5\x10R`\x00\x00\u07d4'\xd1X\xac=>\x11\t\xabnW\x0e\x90\xe8]8\x92\xcdv\x80\x89\x05k\xc7^-c\x10\x00\x00\u07d4'\xe69\x89\xca\x1e\x90;\xc6 \xcf\x1b\x9c?g\xb9\xe2\xaee\x81\x89Hz\x9a0E9D\x00\x00\xe0\x94'\xf0<\xf1\xab\xc5\xe1\xb5\x1d\xbcDK(\x9eT,\x9d\u07f0\xe6\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4'\xfc\x85\xa4\x9c\xff\x90\xdb\xcf\xda\u071d\xdd@\u05b9\xa2!\nl\x89\x05k\xc7^-c\x10\x00\x00\u07d4(\x05A^\x1d\u007f\xde\xc6\xde\u07f8\x9eR\x1d\x10Y-t<\x10\x89\x05k\xc7^-c\x10\x00\x00\u07d4(\a>\xfc\x17\xd0\\\xab1\x95\xc2\xdb3+a\x98Gw\xa6\x12\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x12P\xa2\x91!'\nN\xe5\u05cd$\xfe\xaf\xe8,p\xba:\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x13\xd2c\xfc_\xf2G\x9e\x97\x05\x95\u05b6\xb5`\xf8\xd6\xd6\u0449lk\x93[\x8b\xbd@\x00\x00\u07d4(.\x80\xa5T\x87ZVy\x9f\xa0\xa9\u007fU\x10\u7557LN\x8965\u026d\xc5\u07a0\x00\x00\u07d4(3\x96\xce<\xac9\x8b\xcb\xe7\"\u007f2>x\xff\x96\u0407g\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4(4\x9f~\xf9t\xeaU\xfe6\xa1X;4\xce\xc3\xc4Pe\xf0\x89\f\xb63\u051eeY\x00\x00\u07d4(6\x120F\xb2\x84\xe5\xef\x10+\xfd\"\xb1v^P\x81\x16\xad\x89\x16S\xfb\xb5\xc4'\xe4\x00\x00\u07d4(<#\x14(<\x92\u0530d\xf0\xae\xf9\xbbRF\xa7\x00\u007f9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4(>\x11 7I\xb1\xfaO2\xfe\xbbq\xe4\x9d\x13Y\x198*\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94(>bR\xb4\xef\xcfFT9\x1a\xcbu\xf9\x03\u015bx\xc5\xfb\x8a\x02\x8a\x85t%Fo\x80\x00\x00\xe0\x94(Q\x0en\xff\x1f\xc8)\xb6WoC(\xbc98\xecze\x80\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4(X\xac\xac\xaf!\xea\x81\u02b7Y\x8f\xdb\xd8kE.\x9e\x8e\x15\x89$\x1a\x9bOaz(\x00\x00\u07d4(Z\xe5\x1b\x95\x00\u014dT\x13e\xd9ui\xf1K\xb2\xa3p\x9b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(f\xb8\x1d\xec\xb0.\xe7\n\xe2P\xce\xe5\xcd\xc7{Y\u05f6y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(i\x06\xb6\xbdIr\xe3\xc7\x16U\xe0K\xaf6&\f|\xb1S\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4(k\x18ma\xea\x1f\u05cd\x990\xfe\x12\xb0e7\xb0\\=Q\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94(t\xf3\xe2\x98]_{@f'\xe1{\xaaw+\x01\xab\u031e\x8a\x01F\x05\x04\x10v_8\x00\x00\xe0\x94(|\xf9\u0410.\xf8\x19\xa7\xa5\xf1ID[\xf1w^\xe8\xc4|\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4(\x81\x8e\x18\xb6\x10\x00\x13!\xb3\x1d\xf6\xfe}(\x15\u036d\xc9\xf5\x8965\u026d\xc5\u07a0\x00\x00\u07d4(\x86\x83$3~\x11\xba\x10l\xb4\x81\u0696/:\x84S\x80\x8d\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94(\x90K\xb7\xc40)C\xb7\t\xb1Myp\xe4+\x83$\u184a\x02\x1f\x97\x84j\a-~\x00\x00\u07d4(\x95\xe8\t\x99\xd4\x06\xadY.+&'7\xd3_}\xb4\xb6\x99\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4(\x96r\x80!N!\x8a\x12\f]\xda7\x04\x1b\x11\x1e\xa3mt\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4(\xa3\xda\t\xa8\x19H\x19\xae\x19\x9f.m\x9d\x13\x04\x81~(\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4(\xab\x16_\xfbi\xed\xa0\xc5I\xae8\xe9\x82o_\u007f\x92\xf8S\x89FM\xf6\xd7\xc8DY\x00\x00\u07d4(\xb7u\x85\xcb=U\xa1\x99\xab)\x1d:\x18\u018f\u8684\x8a\x89j@v\xcfy\x95\xa0\x00\x00\xe0\x94(\xd4\xeb\xf4\x1e=\x95\xf9\xbb\x9a\x89u#\\\x1d\x009>\x80\x00\u07d4)\nV\xd4\x1fn\x9e\xfb\xdc\xea\x03B\u0dd2\x9a\x8c\xdf\xcb\x05\x89\x12\xa5\xf5\x81h\xee`\x00\x00\u07d4)\x15bK\xcbg\x917\xb8\xda\xe9\xabW\xd1\x1bI\x05\xea\xeeK\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4)\x1e\xfe\x00\x81\xdc\xe8\xc1G\x99\xf7\xb2\xa46\x19\xc0\u00f3\xfc\x1f\x89A\rXj \xa4\xc0\x00\x00\u07d4)\x1f\x92\x9c\xa5\x9bT\xf8D>=Mu\xd9]\xee$<\xefx\x89\x1b\x1a\b\x927\a=\x00\x00\xe0\x94))\x8c\xcb\xdf\xf6\x89\xf8\u007f\xe4\x1a\xa6\xe9\x8f\u07f5=\xea\xf3z\x8a\x041\\2\xd7\x1a\x9e`\x00\x00\u07d4)/\"\x8b\n\x94t\x8c\x8e\xeca-$o\x98\x93c\xe0\x8f\b\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4)3\x84\xc4+o\x8f)\x05\xceR\xb7 \\\"t7la+\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4)4\xc0\xdf{\xbc\x17+l\x18k\vrTz\u038b\xf7TT\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4)<#\x06\xdf6\x04\xaeO\xda\r z\xbasog\xde\a\x92\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94)I\xfd\x1d\xef\\v\xa2\x86\xb3\x87$$\x80\x9a\a\xdb9f\xf3\x8a\x01\x1b\xd9\x06\u06a0\xc9C\x80\x00\u07d4)OIK?.\x14\xa3\xf8\xab\x00\x00\x00\u07d4)U\xc3W\xfd\x8fu\xd5\x15\x9a=\xfai\u0178z5\x9d\ua309lk\x93[\x8b\xbd@\x00\x00\u07d4)a\xfb9\x1ca\x95|\xb5\xc9\xe4\a\u0762\x938\u04f9,\x80\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4)h\x1d\x99\x12\xdd\xd0~\xaa\xbb\x88\xd0]\x90\xf7f\xe8bA}\x8965\u026d\xc5\u07a0\x00\x00\u07d4)kq\xc0\x01X\x19\xc2B\xa7\x86\x1eo\xf7\xed\xed\x8a_q\xe3\x89lh\xcc\u041b\x02,\x00\x00\u07d4)mf\xb5!W\x1aNA\x03\xa7\xf5b\xc5\x11\xe6\xaas-\x81\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4)o\x00\xde\x1d\u00fb\x01\xd4z\x8c\xcd\x1e]\x1d\u0661\xebw\x91\x8965\u026d\xc5\u07a0\x00\x00\u07d4)s\x85\xe8\x864FV\x85\xc21\xa3\x14\xa0\xd5\xdc\xd1F\xaf\x01\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4)v=\xd6\u069a|\x16\x11s\x88\x83!\ub9b6<\x8f\xb8E\x89\x11\xc7\xea\x16.x \x00\x00\u07d4)yt\x11t\xa8\xc1\xea\v\u007f\x9e\xdfe\x81w\x85\x94\x17\xf5\x12\x89\x19\x01\x96l\x84\x96\x83\x80\x00\u07d4)z\x88\x92\x1b_\xca\x10\u5edd\xed`\x02T7\xae\"\x16\x94\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94)}]\xbe\"//\xb5%1\xac\xbd\v\x01=\xc4F\xacsh\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4)\x82N\x94\xccCH\xbc\x962y\xdc\xdfG9\x17\x152L\u04c9i*\xe8\x89p\x81\xd0\x00\x00\u07d4)\x82\xd7j\x15\xf8G\xddA\xf1\x92*\xf3h\xfeg\x8d\x0eh\x1e\x89\x05k\xc7^-c\x10\x00\x00\u07d4)\x88\x87\xba\xb5|[\xa4\xf0aR)\xd7R_\xa1\x13\xb7\ua249\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94)\x8e\xc7kD\r\x88\a\xb3\xf7\x8b_\x90\x97\x9b\xeeB\xedC\u06ca\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4)\x93h`\x90B\xa8X\xd1\xec\xdf\x1f\xc0\xad\xa5\xea\xce\xca)\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4)\x9e\v\xcaU\xe0i\u0785\x04\xe8\x9a\xcan\xca!\u04ca\x9a]\x89\x03\x027\x9b\xf2\xca.\x00\x00\u07d4)\xac+E\x84T\xa3l~\x96\xc7:\x86g\"*\x12$,q\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94)\xad\u03c3\xb6\xb2\n\u01a44\xab\xb1\x99<\xbd\x05\xc6\x0e\xa2\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94)\xae\xf4\x8d\xe8\xc9\xfb\xadK\x9eL\xa9pyzU3\xebr-\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4)\xb3\xf5a\xeezn%\x94\x1e\x98\xa52[x\xad\u01d7\x85\xf3\x89\x05k\xc7^-c\x10\x00\x00\u07d4)\xbd\xc4\xf2\x8d\xe0\x18\x0fC<&\x94\xebt\xf5PL\xe9C7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4)\u0300M\x92+\xe9\x1fY\t\xf3H\xb0\xaa\xa5\xd2\x1b`x0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94)\xda>5\xb2;\xb1\xf7/\x8e\"X\xcf\u007fU3Y\xd2K\xac\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94)\xe6y\x90\xe1\xb6\xd5.\x10U\xff\xe0I\xc51\x95\xa8\x15B\u03ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4)\uab82v\x17b\xf4\xd2\xdbS\xa9\u018b\x0fk\vmNf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4)\xeb~\xef\xda\xe9\xfe\xb4I\xc6?\xf5\xf2y\xd6u\x10\xeb\x14\"\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4)\xf0\xed\xc6\x038\xe7\x11 \x85\xa1\xd1\x14\u068cB\u038fU\u0589\xa0Z\u007f\x0f\xd8%x\x00\x00\u07d4)\xf8\xfb\xa4\xc3\ar\xb0W\xed\xbb\xe6*\xe7B\f9\x05r\xe1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94)\xf9(l\x0es\x8d\x17!\xa6\x91\u01b9Z\xb3\u0667\x97\xed\xe8\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4*\b^%\xb6Hb\xf5\xe6\x8dv\x8e+\x0fz\x85)\x85\x8e\xee\x89k\x88:\xcdWf\xcd\x00\x00\u07d4**\xb6\xb7Lz\xf1\xd9Gk\xb5\xbc\xb4RG\x97\xbe\xdc5R\x8965\u026d\xc5\u07a0\x00\x00\u07d4*9\x19\nO\u0783\u07f3\xdd\xcbL_\xbb\x83\xaclIu\\\x8965\u026d\xc5\u07a0\x00\x00\u07d4*@\r\xff\x85\x94\xder(\xb4\xfd\x15\xc3#\"\xb7[\xb8}\xa8\x89\x051\xa1\u007f`z-\x00\x00\xe0\x94*D\xa7!\x8f\xe4Me\xa1\xb4\xb7\xa7\u0671\xc2\xc5,\x8c>4\x8a\r-\x06\xc3\x05\xa1\xebW\x80\x00\u07d4*F\xd3Swqv\xff\x8e\x83\xff\xa8\x00\x1fOp\xf9s:\xa5\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4*Y_\x16\xee\xe4\xcb\f\x17\u0662\xd99\xb3\xc1\x0flgrC\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4*Y\xe4~\xa5\xd8\xf0\xe7\xc0(\xa3\xe8\xe0\x93\xa4\x9c\x1bP\xb9\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4*[\xa9\xe3L\u054d\xa5L\x9a'\x12f:;\xe2t\xc8\xe4{\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94*^:@\xd2\xcd\x03%vm\xe7:=g\x18\x96\xb3b\xc7;\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94*cY\x0e\xfe\x99\x86\xc3\xfe\xe0\x9b\n\n3\x8b\x15\xbe\xd9\x1f!\x8a\x01^\x1cN\x05\xee&\xd0\x00\x00\u07d4*gf\n\x13h\xef\xcdbn\xf3k+\x1b`\x19\x80\x94\x1c\x05\x89\a?u\u0460\x85\xba\x00\x00\u07d4*t+\x89\x10\x94\x1e\t2\x83\n\x1d\x96\x92\xcf\u0484\x94\xcf@\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4*tl\xd4@'\xaf>\xbd7\xc3x\xc8^\xf7\xf7T\xab_(\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4*\x81\xd2|\xb6\xd4w\x0f\xf4\xf3\u0123\xba\x18\xe5\xe5\u007f\aQ|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4*\x91\xa9\xfe\xd4\x1b}\x0e\\\xd2\xd81X\xd3\xe8\xa4\x1a\x9a-q\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94*\x9cW\xfe{k\x13\x8a\x92\rgo{\x1a%\x10\x80\xff\xb9\x8a4\xf0\x86\xf3\xb3;h@\x00\x00\u07d4+p\x1d\x16\xc0\xd3\xcc\x1eL\xd8TE\xe6\xad\x02\ue92c\x01-\x89 \x86\xac5\x10R`\x00\x00\xe0\x94+q|\xd42\xa3#\xa4e\x909\x84\x8d;\x87\xde&\xfc\x95F\x8ai\xe1\r\xe7fv\u0400\x00\x00\u07d4+t\xc3s\xd0K\xfb\x0f\xd6\n\x18\xa0\x1a\x88\xfb\xe8Gp\u5309\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4+w\xa4\u060c\rV\xa3\xdb\xe3\xba\xe0J\x05\xf4\xfc\u0477W\xe1\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94+\x84\x88\xbd-<\x19z=&\x15\x18\x15\xb5\xa7\x98\xd2qh\u070a\x01j\x1f\x9f_\xd7\xd9`\x00\x00\u07d4+\x8a\r\xee\\\xb0\xe1\xe9~\x15\xcf\xcan\x19\xad!\xf9\x95\ufb49\x1bUC\x8d\x9a$\x9b\x00\x00\xe0\x94+\x8f\xe4\x16n#\xd1\x19c\xc0\x93+\x8a\u078e\x01E\xea\ap\x8a\t(\x96R\x9b\xad\u0708\x00\x00\xe0\x94+\x99\xb4.OBa\x9e\xe3k\xaa~J\xf2\xd6^\xac\xfc\xba5\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4+\xab\x0f\xbe(\u0544 \xb5 6w\n\x12\xf9\x95*\xeai\x11\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4+\xad\xe9\x1d\x15E\x17b\x0f\u05349\xac\x97\x15zA\x02\xa9\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4+\xaf\x8dn\"\x11t\x12H \xeeI+\x94Y\xecO\xad\xaf\xbb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4+\xaf\xbf\x9e\x9e\xd2\xc2\x19\xf7\xf2y\x13t\xe7\xd0\\\xb0gw\xe7\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\xe0\x94+\xb3f\xb9\xed\xcb\r\xa6\x80\xf0\xe1\v;n(t\x81\x90\xd6\u00ca\x01:b\u05f5v@d\x00\x00\xe0\x94+\xb6\xf5x\xad\xfb\u7ca1\x16\xb3UO\xac\xf9\x96\x98\x13\xc3\x19\x8a\x01\x91'\xa19\x1e\xa2\xa0\x00\x00\u07d4+\xbeb\xea\xc8\f\xa7\xf4\xd6\xfd\xee~}\x8e(\xb6:\xcfw\x0e\x89\x81\xe3-\xf9r\xab\xf0\x00\x00\u07d4+\xbeg*\x18WP\x8fc\x0f*^\xdbV=\x9e\x9d\xe9(\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4+\xc4)\xd6\x18\xa6jL\xf8-\xbb-\x82N\x93V\xef\xfa\x12j\x89lj\xccg\u05f1\xd4\x00\x00\u07d4+\xd2R\xe0\xd72\xff\x1d|x\xf0\xa0.l\xb2T#\xcf\x1b\x1a\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4+\xdd\x03\xbe\xbb\xee';l\xa1\x05\x9b4\x99\x9a[\xbda\xbby\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,\x04\x11\\>R\x96\x1b\r\xc0\xb0\xbf1\xfb\xa4ToYf\xfd\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94,\x06\u0752+aQJ\xaf\xed\xd8D\x88\xc0\u008em\xcf\x0e\x99\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94,\f\xc3\xf9QH,\u0222\x92X\x15hN\xb9\xf9N\x06\x02\x00\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4,\x0e\xe14\u0633aE\xb4{\xee\u7bcd'8\xdb\xda\b\xe8\x89\n\xe5os\x0em\x84\x00\x00\u07d4,\x0f[\x9d\xf46%y\x8e~\x03\xc1\xa5\xfdjm\t\x1a\xf8+\x89\x01\xb0\xfc\xaa\xb2\x000\x00\x00\u07d4,\x12\x8c\x95\xd9W!Q\x01\xf0C\u074f\u0142EmA\x01m\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4,\x18\x00\xf3_\xa0->\xb6\xff[%(_^J\xdd\x13\xb3\x8d\x891\"\u04ed\xaf\xde\x10\x00\x00\u07d4,\x1c\x19\x11N=m\xe2xQHK\x8d'\x15\xe5\x0f\x8a\x10e\x89\x05k\xc7^-c\x10\x00\x00\u07d4,\x1c\xc6\xe1\x8c\x15$\x88\xba\x11\xc2\xcc\x1b\xce\xfa-\xf3\x06\xab\u0449Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94,\x1d\xf8\xa7oH\xf6\xb5K\u03dc\xafV\xf0\xee\x1c\xf5z\xb3=\x8a\x02$\u007fu\x00\x89\xdaX\x00\x00\u07d4,!G\x94z\xe3?\xb0\x98\xb4\x89\xa5\xc1k\xff\xf9\xab\xcdN*\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4,#OP\\\xa8\xdc\xc7}\x9b~\x01\xd2W\xc3\x18\xcc\x199m\x89\x05k\xc7^-c\x10\x00\x00\u07d4,$(\xe4\xa6it\xed\xc8\"\xd5\xdb\xfb$\x1b'(\aQX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,-\x15\xff9V\x1c\x1br\xed\xa1\xcc\x02\u007f\xfe\xf27C\xa1D\x89\u0500\xed\x9e\xf3+@\x00\x00\u07d4,-\xb2\x8c3\t7^\xea1\x82\x1b\x84\xd4\b\x93\x0e\xfa\x1a\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4,Z-\n\xbd\xa0;\xbe!W\x81\xb4\xff)l\x8ca\xbd\xba\xf6\x89\x01\xa8\xe5oH\xc0\"\x80\x00\u07d4,[}{\x19Z7\x1b\xf9\xab\u0774/\xe0O/\x1d\x9a\x99\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4,]\xf8ffj\x19K&\u03bb@~J\x1f\xd7> \x8d^\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94,`?\xf0\xfe\x93alCW>\xf2y\xbf\xea@\x88\x8dj\xe7\x8a\x01\x00\xf4\xb6\xd6gW\x90\x00\x00\xe0\x94,hF\xa1\xaa\x99\x9a\"F\xa2\x87\x05`\x00\xbaM\u02e8\xe6=\x8a\x02\x1f/o\x0f\xc3\xc6\x10\x00\x00\u0794,j\xfc\xd4\x03|\x1e\xd1O\xa7O\xf6u\x8e\tE\xa1\x85\xa8\xe8\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4,ki\x9d\x9e\xad4\x9f\x06\u007fEq\x1a\aJd\x1d\xb6\xa8\x97\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,o\\\x12L\u01c9\xf8\xbb9\x8e?\x88\x97Q\xbcK`-\x9e\x89\x01Y\xf2\v\xed\x00\xf0\x00\x00\u07d4,\x83\xae\xb0/\xcf\x06}e\xa4p\x82\xfd\x97x3\xab\x1c\uc449\b'8#%\x8a\xc0\x00\x00\xe0\x94,\x89\xf5\xfd\xca=\x15T\t\xb68\xb9\x8at.U\xebFR\xb7\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4,\x96HI\xb1\xf6\x9c\xc7\u03a4D%8\xed\x87\xfd\xf1l\xfc\x8f\x89lk\x93[\x8b\xbd@\x00\x00\u0794,\x9f\xa7,\x95\xf3}\b\xe9\xa3`\t\u7930\u007f)\xba\xd4\x1a\x88\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4,\xafk\xf4\xec}Z\x19\xc5\xe0\x89z^\xeb\x01\x1d\xce\xceB\x10\x89\a\x93H5\xa01\x16\x00\x00\u07d4,\xb4\xc3\xc1k\xb1\xc5^|kz\x19\xb1'\xa1\xac\x93\x90\xcc\t\x89\xb8'\x94\xa9$O\f\x80\x00\xe0\x94,\xb5IZPS6\xc2FT\x10\xd1\xca\xe0\x95\xb8\xe1\xba\\\u074a\x04<3\xc1\x93ud\x80\x00\x00\u07d4,\xb6\x15\a:@\xdc\u06d9\xfa\xa8HW.\x98{;\x05n\xfb\x89+X\xad\u06c9\xa2X\x00\x00\u07d4,\xbam]\r\xc2\x04\xea\x8a%\xad\xa2\xe2oVu\xbd_/\u0709H#\xef}\u06da\xf3\x80\x00\u07d4,\xbb\fs\u07d1\xb9\x17@\xb6i;wJ}\x05\x17~\x8eX\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4,\xcbfIM\n\xf6\x89\xab\xf9H=6]x$D\xe7\u07ad\x8965\u026d\xc5\u07a0\x00\x00\u07d4,\xcc\x1f\x1c\xb5\xf4\xa8\x00.\x18k \x88]\x9d\xbc\x03\f\b\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,\u03c0\xe2\x18\x98\x12^\xb4\xe8\a\u0342\xe0\x9b\x9d(Y/n\x89lk\x93[\x8b\xbd@\x00\x00\u07d4,\u0456\x94\u0452j\x0f\xa9\x18\x9e\u07ba\xfcg\x1c\xf1\xb2\u02a5\x8965\u026d\xc5\u07a0\x00\x00\u07d4,\u04d34\xac~\xacyrW\xab\xe3sa\x95\xf5\xb4\xb5\xce\x0f\x89\x05kGx^7&\x00\x00\u07d4,\u05de\xb5 '\xb1,\x18\x82\x8e>\xaa\xb2\x96\x9b\xfc\u0487\xe9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4,\xd8xfV\x8d\xd8\x1a\xd4}\x9d:\u0404nZePss\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4,\xdb9De\x06\x16\xe4|\xb1\x82\xe0`2/\xa1Hyx\u0389b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4,\xe1\x1a\x92\xfa\xd0$\xff+>\x87\xe3\xb5B\xe6\xc6\r\xcb\u0656\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4-\x03&\xb2?\x04\t\xc0\xc0\xe9#hc\xa13\aZ\x94\xba\x18\x89\vg\x9b\xe7[\xe6\xae\x00\x00\u07d4-\r\xecQ\xa6\xe8s0\xa6\xa8\xfa*\x0fe\u060dJ\xbc\xdfs\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4-#vkok\x05s}\xad\x80\xa4\x19\xc4\x0e\xdaMw\x10>\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4-+\x03#Y\xb3c\x96O\xc1\x1aQ\x82c\xbf\xd0T1\xe8g\x89\b\x1c\x1d\xf7b\x9ep\x00\x00\u07d4-4\x80\xbf\be\aJr\xc7u\x9e\xe5\x13{Mp\xc5\x1c\xe9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4-5\xa9\xdfbu\u007f\u007f\xfa\xd1\x04\x9a\xfb\x06\xcaJ\xfcFLQ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4-@U\x8b\x06\xf9\n9#\x14U\x92\x12;gt\xe4n1\xf4\x8965\u026d\xc5\u07a0\x00\x00\u07d4-Bi\x12\xd0Y\xfa\xd9t\v.9\n.\xea\xc0To\xf0\x1b\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4-S-\xf4\xc69\x11\xd1\u0391\xf6\xd1\xfc\xbf\xf7\x96\x0fx\xa8\x85\x89Z\x85\x96\x8aXx\u0680\x00\u07d4-S\x91\xe98\xb3HX\u03d6[\x84\x051\xd5\xef\xdaA\v\t\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94-[B\xfcY\xeb\xda\r\xfdf\xae\x91K\u008c\x1b\nn\xf8:\x8a+\u0235\x9f\xdc\xd86c\x80\x00\u07d4-]s5\xac\xb06+G\u07e3\xa8\xa4\xd3\xf5\x94\x95D\u04c0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-a\xbf\xc5hs\x92<+\x00\t]\xc3\xea\xa0\xf5\x90\u062e\x0f\x8a\x04ef\xdf\xf8\xceU`\x00\x00\u07d4-e\x11\xfdz8\x00\xb2hT\xc7\xec9\xc0\u0735\xf4\xc4\xe8\xe8\x89\x15\xad\u077a/\x9ew\x00\x00\u07d4-}\\@\u076f\xc4P\xb0Jt\xa4\u06bc+\xb5\xd6e\x00.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4-\x89\xa8\x00jO\x13z \xdc+\xecF\xfe.\xb3\x12\xea\x96T\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4-\x8cR2\x9f8\u04a2\xfa\x9c\xba\xf5\u0143\xda\xf1I\v\xb1\x1c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4-\x8e\x06\x18\x92\xa5\xdc\xce!\x96j\xe1\xbb\a\x88\xfd>\x8b\xa0Y\x89\r\x8e\\\xe6\x17\xf2\xd5\x00\x00\u07d4-\x8e[\xb8\xd3R\x16\x95\xc7~|\x83N\x02\x91\xbf\xac\xeet\b\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4-\x90\xb4\x15\xa3\x8e.\x19\xcd\xd0/\U000ed069z\xf7\xcb\xf6r\x89\x05\xf3\xc7\xf6A1\xe4\x00\x00\u07d4-\x9b\xado\x1e\xe0*p\xf1\xf1=\xef\\\u0332z\x9a'@1\x89a\t=|,m8\x00\x00\u07d4-\x9c_\xec\u04b4O\xbbj\x1e\xc72\xea\x05\x9fO\x1f\x9d+\\\x896\xca2f\x1d\x1a\xa7\x00\x00\xe0\x94-\xa6\x17iP\t\xccW\xd2j\u0510\xb3*]\xfb\xeb\x93N^\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4-\xa7k|9\xb4 \u323a,\x10 \xb0\x85k\x02pd\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4-\u01ddn\u007fU\xbc\xe2\xe2\xd0\xc0*\xd0|\uca3bR\x93T\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\xe0\x94-\xca\x0eD\x9a\xb6F\xdb\xdf\u04d3\xa9fb\x96\v\u02b5\xae\x1e\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4-\xd3%\xfd\xff\xb9{\x19\x99R\x84\xaf\xa5\xab\xdbWJ\x1d\xf1j\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4-\xd5x\xf7@}\xfb\xd5H\xd0^\x95\xcc\u00dcHT)bj\x89\u3bb5sr@\xa0\x00\x00\u07d4-\xd8\xee\xef\x87\x19J\xbc,\xe7X]\xa1\xe3[|\xeax\f\xb7\x8965\xc6 G9\u0640\x00\u07d4-\xdf@\x90Wi\xbc\xc4&\xcb,)8\xff\xe0w\xe1\u8758\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4-\xe0\x96D\x00\u0082\xbd\u05ca\x91\x9ck\xf7|k_yay\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-\xe3\x1a\xfd\x18\x9a\x13\xa7o\xf6\xfes\xea\xd9\xf7K\xb5\u0126)\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4-\xec\x982\x9d\x1f\x96\u00e5\x9c\xaay\x81uTR\xd4\xdaI\u0549\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94-\ue422\x8f\x19-gj\x87s#+V\xf1\x8f#\x9e/\xad\x8a\x03\xef\xa7\xe7G\xb6\u046d\x00\x00\xe0\x94.\b\x80\xa3E\x96#\a \xf0Z\xc8\xf0e\xaf\x86\x81\u0736\u008a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4.\fW\xb4qP\xf9Z\xa6\xa7\xe1j\xb9\xb1\xcb\xf5C(\x97\x9a\x89\x05k\xc7^-c\x10\x00\x00\u07d4.\x10\x91\v\xa6\xe0\xbc\x17\xe0UUf\x14\u02c7\t\x0fM~[\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94.$\xb5\x97\x87;\xb1A\xbd\xb27\xea\x8aZ\xb7Gy\x9a\xf0-\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4.(\x10\xde\xe4J\xe4\xdf\xf3\xd8cB\xab\x12fW\xd6S\xc36\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4.,\xbdz\xd8%G\xb4\xf5\xff\x8b:\xb5o\x94*dE\xa3\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4.-~\xa6k\x9fG\xd8\xccR\xc0\x1cR\xb6\u147c}G\x86\x89\xd8\xd4`,&\xbfl\x00\x00\u07d4.C\x93H\u07caBw\xb2*v\x84W\xd1\x15\x8e\x97\xc4\t\x04\x89*\x1e\x9f\xf2o\xbfA\x00\x00\xe0\x94.F\xfc\xeej;\xb1E\xb5\x94\xa2C\xa3\x91?\xce]\xado\xba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794.G\xf2\x87\xf4\x98#7\x13\x85\r1&\x82<\xc6}\xce\xe2U\x88\u029d\x9e\xa5X\xb4\x00\x00\u07d4.N\u1b99j\xa0\xa1\xd9$(\xd0fR\xa6\xbe\xa6\xd2\xd1]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.R\x91+\xc1\x0e\xa3\x9dT\xe2\x93\xf7\xae\u05b9\x9a\x0fLs\xbe\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4.a\x9fW\xab\xc1\u91ea\x93j\xe3\xa2&Ib\xe7\xeb-\x9a\x89(\xfb\x9b\x8a\x8aSP\x00\x00\u07d4.d\xa8\xd7\x11\x11\xa2/L]\xe1\xe09\xb36\xf6\x8d9\x8a|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.i3T=O,\xc0\vSP\xbd\x80h\xba\x92C\u05be\xb0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94.~\x05\xe2\x9e\u0767\xe4\xae%\xc5\x175C\xef\xd7\x1fm=\x80\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4.\u007fFU \xec5\xcc#\u058eue\x1b\xb6h\x95D\xa1\x96\x898\xec[r\x1a\x1a&\x80\x00\u07d4.\x8e\xb3\nqn_\xe1\\t#>\x03\x9b\xfb\x11\x06\xe8\x1d\x12\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94.\x98$\xb5\xc12\x11\x1b\xca$\xdd\xfb\xa7\xe5u\xa5\xcdr\x96\xc1\x8a\x03\xa4\x84Qnm\u007f\xfe\x00\x00\u07d4.\xa5\xfe\xe6?3z7nK\x91\x8e\xa8!H\xf9MH\xa6&\x89e\x0f\x8e\r\u0493\xc5\x00\x00\u07d4.\xafN*F\xb7\x89\xcc\u0088\xc8\xd1\xd9)N?\xb0\x858\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4.\xaf\xf9\xf8\xf8\x110d\u04d5z\xc6\xd6\xe1\x1e\xeeB\xc8\x19]\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4.\xba\fn\xe5\xa1\x14\\\x1cW9\x84\x96:`]\x88\nz \x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4.\xc9X\"\xeb\x88{\xc1\x13\xb4q*M\xfd\u007f\x13\xb0\x97\xb5\xe7\x8965\u026d\xc5\u07a0\x00\x00\u07d4.\xcaj<]\x9fD\x9d\tV\xbdC\xfa{M{\xe8CYX\x89lk\xdaip\x9c\xc2\x00\x00\xe0\x94.\xca\xc5\x04\xb23\x86n\xb5\xa4\xa9\x9e{\u0490\x13Y\xe4;=\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4.\xeb\xf5\x942\xb5(\x92\xf98\v\xd1@\xaa\x99\xdc\xf8\xad\f\x0f\x89\b=lz\xabc`\x00\x00\u07d4.\xee\xd5\x04q\xa1\xa2\xbfS\xee0\xb1#.n\x9d\x80\xef\x86m\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4.\xefk\x14\x17\u05f1\x0e\xcf\xc1\x9b\x12:\x8a\x89\xe7>RlX\x89 \x86\xac5\x10R`\x00\x00\u07d4.\xf8i\xf05\vW\xd54x\xd7\x01\xe3\xfe\xe5)\xbc\x91\x1cu\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4.\xf9\xe4eqj\xca\u03f8\xc8%/\xa8\xe7\xbcyi\xeb\xf6\u4255\x9e\xb1\xc0\xe4\xae \x00\x00\xe0\x94.\xfcLd}\xacj\xca\xc3Uw\xad\"\x17X\xfe\xf6ao\xaa\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4/\x13eu&\xb1w\xca\xd5G\u00d0\x8c\x84\x0e\xffd{E\u0649?v\x84\x9c\xf1\xee,\x80\x00\u07d4/\x18}ZpMZ3\x8c[(v\xa0\x90\xdc\xe9d(N)\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94/%#\u0303O\x00\x86\x05$\x02bb\x96gQ\x86\xa8\u508a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4/(*\xbb\xb6\u0523\xc3\xcd;\\\xa8\x12\xf7d>\x800_\x06\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4/+\xba\x1b\x17\x96\x82\x1avo\xced\xb8O(\xech\xf1Z\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4/1]\x90\x16\xe8\xee_Sf\x81 /\x90\x84\xb02TMM\x898<\xd1+\x9e\x86<\x00\x00\u07d4/M\xa7SC\x0f\xc0\x9es\xac\xbc\xcd\xcd\xe9\xdad\u007f+]7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4/P\x80\xb8?~-\xc0\xa1\xdd\x11\xb0\x92\xad\x04+\xffx\x8fL\x89\xb4\xf8\xfby#\x1d+\x80\x00\u07d4/a\uf941\x9dp_+\x1eN\xe7T\xae\xb8\xa8\x19Pju\x89O%\x91\xf8\x96\xa6P\x00\x00\xe0\x94/f\xbf\xbf\"b\xef\u030d+\xd0DO\u0170ib\x98\xff\x1e\x8a\x02\x1a\xd95\xf7\x9fv\xd0\x00\x00\u07d4/m\xce\x130\u015e\xf9!`!TW-MK\xac\xbd\x04\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4/}2\x90\x85\x1b\xe5\u01b4\xb4?}Et2\x9fa\xa7\x92\u00c9\x05k\xc7^-c\x10\x00\x00\u07d4/\x858\x17\xaf\u04f8\xf3\xb8n\x9f`\xeew\xb5\xd9ws\xc0\xe3\x89N\xae\xeaD\xe3h\xb9\x00\x00\u07d4/\xa4\x91\xfbY \xa6WN\xbd(\x9f9\xc1\xb2C\r-\x9aj\x89lk\x93[\x8b\xbd@\x00\x00\u07d4/\xb5f\xc9K\xbb\xa4\xe3\xcbg\xcd\xda}_\xadq1S\x91\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4/\xbbPJ]\xc5'\xd3\xe3\xeb\x00\x85\xe2\xfc<}\xd58\xcbz\x89C\u00b1\x8a\xec<\n\x80\x00\u07d4/\xbc\x85y\x8aX5\x98\xb5\"\x16mn\x9d\xda\x12\x1db}\xbc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4/\xbc\xef3\x84\xd4 \xe4\xbfa\xa0f\x99\x90\xbcpT\U00065bc9lk\x93[\x8b\xbd@\x00\x00\xe0\x94/\xc8.\xf0v\x93#A&Oaz\f\x80\xddW\x1ej\xe99\x8a\x01\x84$\xf5\xf0\xb1\xb4\xe0\x00\x00\u07d4/\u075by\u07cd\xf50\xadc\xc2\x0eb\xafC\x1a\xe9\x92\x16\xb8\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4/\xe0\x02?W\"e\x0f:\x8a\xc0\x10\t\x12^t\xe3\xf8.\x9b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4/\xe0\xccBKS\xa3\x1f\t\x16\xbe\b\xec\x81\xc5\v\xf8\xea\xb0\xc1\x89 \x86\xac5\x10R`\x00\x00\u07d4/\xe1:\x8d\a\x85\u0787X\xa5\xe4\x18v\xc3n\x91l\xf7Pt\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4/\xea\x1b/\x83O\x02\xfcT3?\x8a\x80\x9f\x048\xe5\x87\n\xa9\x89\x01\x18T\xd0\xf9\xce\xe4\x00\x00\u07d4/\xee6\xa4\x9e\xe5\x0e\xcfqo\x10G\x91VFw\x9f\x8b\xa0?\x899B\"\xc4\u0686\xd7\x00\x00\u07d4/\xef\x81G\x8aK.\x80\x98\xdb_\xf3\x87\xba!S\xf4\xe2+y\x896'\xe8\xf7\x127<\x00\x00\u07d4/\xf1`\xc4Or\xa2\x99\xb5\xec-q\xe2\x8c\xe5Dm/\u02ef\x89\x13\x84\x00\xec\xa3d\xa0\x00\x00\u07d4/\xf1\xcaU\xfd\x9c\xec\x1b\x1f\xe9\U00029af7LQ<\x1e*\xaa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94/\xf5\u02b1,\r\x95\u007f\xd33\xf3\x82\xee\xb7Q\a\xa6L\xb8\xe8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94/\xf80\xcfU\xfb\x00\u0560\xe05\x14\xfe\xcdD1K\xd6\xd9\xf1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4/\xfe\x93\xec\x1aV6\xe9\xee4\xafp\xdf\xf5&\x82\xe6\xffpy\x89lk\x93[\x8b\xbd@\x00\x00\u07d40\x03y\x88p&q\xac\xbe\x89,\x03\xfeW\x88\xaa\x98\xaf(z\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d40$\x8dX\xe4\x14\xb2\x0f\xed:lH+Y\xd9\xd8\xf5\xa4\xb7\xe2\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4019\xbcYd\x03\xd5\u04d3\x1fwLf\u013aFtT\u06c9\\%\xe1J\xea(?\x00\x00\u079408\x00\x87xie\x14\x9e\x81B;\x15\xe3\x13\xba2\xc5\u01c3\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d40:0\xacB\x86\xae\x17\xcfH=\xad{\x87\fk\xd6M{J\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d40?\xba\xeb\xbeF\xb3[n[t\x94j_\x99\xbc\x15\x85\xca\xe7\x89/\x9a\xc0i_[\xba\x00\x00\u07d40ADZ3\xba\x15\x87A\x16\r\x9c4N\xb8\x8e\\0o\x94\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d40H\x01d\xbc\xd8It\xeb\xc0\xd9\f\x9b\x9a\xfa\xb6&\xcd\x1cs\x89+^:\xf1k\x18\x80\x00\x00\u07d40N\u019atTW!\xd71j\xefM\u03f4\x1a\u015e\xe2\xf0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x940Q\x182\x91\x8d\x804\xa7\xbe\xe7.\xf2\xbf\xeeD\x0e\u02fc\xf6\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d40Q?\u029f6\xfdx\x8c\xfe\xa7\xa3@\xe8m\xf9\x82\x94\xa2D\x89\x18;_\x03\xb1G\x9c\x00\x00\u07d40U\xef\xd2`)\xe0\xd1\x1b\x93\r\xf4\xf5;\x16,\x8c?\xd2\u0389\x1b\x1a\b\x927\a=\x00\x00\u07d40]&\xc1\v\xdc\x10?k\x9c!'.\xb7\xcb-\x91\b\xc4~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d40_x\xd6\x18\xb9\x90\xb4)[\xac\x8a-\xfa&(\x84\xf8\x04\xea\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x940d\x89\x9a\x96\x1a>\x1d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d40\x98\xb6]\xb9>\xca\xca\xf75\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d40\uc4d2$J!\b\u0247\xbc\\\xdd\xe0\ud7c3z\x81{\x89T\x99%\xf6\xc9\xc5%\x00\x00\xe0\x940\xed\x11\xb7{\xc1~^f\x94\u023c[nG\x98\xf6\x8d\x9c\xa7\x8a\x1eo\xb3B\x1f\xe0)\x9e\x00\x00\u07d40\xf7\xd0%\xd1o{\xee\x10U\x80Ho\x9fV\x1c{\xae?\xef\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x940\xfb\xe5\x88_\x9f\xcc\xe9\xea^\u06c2\xedJ\x11\x96\xdd%\x9a\xed\x8a\x01\x19\xe4\u007f!8\x1f@\x00\x00\u07d41\x04}p?c\xb94$\xfb\xbdn/\x1f\x9et\xde\x13\xe7\t\x89\x9a\x81f\xf7\u6ca7\x80\x00\u07d411?\xfdc[\xf2\xf32HA\xa8\x8c\a\xed\x14aD\xce\xeb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d41Y\xe9\fH\xa9\x15\x90J\xdf\u24b2/\xa5\xfd^ryk\x896\xaf\xe9\x8f&\x06\x10\x00\x00\u07d41]\xb7C\x9f\xa1\u0574#\xaf\xa7\xddq\x98\xc1\xcft\xc9\x18\xbc\x89 \x86\xac5\x10R`\x00\x00\u07d41^\xf2\xdab\x0f\xd30\xd1.\xe5]\xe5\xf3)\xa6\x96\xe0\xa9h\x89\b!\xab\rD\x14\x98\x00\x00\u07d41n\x92\xa9\x1b\xbd\xa6\x8b\x9e/\x98\xb3\xc0H\x93N<\xc0\xb4\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d41n\xb4\xe4}\xf7\x1bB\xe1mo\xe4h%\xb72{\xaf1$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d41q\x87~\x9d\x82\f\xc6\x18\xfc\t\x19\xb2\x9e\xfd3?\xdaI4\x8965\u026d\xc5\u07a0\x00\x00\u07d41|\xf4\xa2<\xb1\x91\xcd\xc5c\x12\u009d\x15\xe2\x10\xb3\xb9\xb7\x84\x89\a\xcef\xc5\x0e(@\x00\x00\u07d41\x8b.\xa5\xf0\xaa\xa8y\xc4\xd5\xe5H\xac\x9d\x92\xa0\xc6t\x87\xb7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d41\x8cv\xec\xfd\x8a\xf6\x8dpUSR\xe1\xf6\x01\xe3Y\x88\x04-\x89\x1b1\x19.h\xc7\xf0\x00\x00\u07d41\x8f\x1f\x8b\xd2 \xb0U\x8b\x95\xfb3\x10\x0f\xfd\xbbd\r|\xa6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d41\xaa;\x1e\xbe\x8cM\xbc\xb6\xa7\b\xb1\xd7H1\xe6\x0eIv`\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d41\xab\b\x89f\xec\xc7\"\x92X\xf6\t\x8f\xceh\xcf9\xb3\x84\x85\x8965\u026d\xc5\u07a0\x00\x00\xe0\x941\xadM\x99F\xef\t\xd8\xe9\x88\xd9F\xb1\"\u007f\x91A\x90\x176\x8a\x04\xd8S\xc8\xf8\x90\x89\x80\x00\x00\xe0\x941\xb4;\x01]\x00\x81d~h\x00\x00\u07d424\x86\xcad\xb3uGO\xb2\xb7Y\xa9\xe7\xa15\x85\x9b\xd9\xf6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d427I\xa3\xb9q\x95\x9eF\u0234\x82-\xca\xfa\xf7\xaa\xf9\xbdn\x89\x01\x16q\xa5\xb2Ep\x00\x00\u07d42:\xadA\xdfKo\xc8\xfe\u038c\x93\x95\x8a\xa9\x01\xfah\bC\x894\x95tD\xb8@\xe8\x00\x00\xe0\x942;<\xfe>\xe6+\xbd\xe2\xa2a\xe5<\xb3\xec\xc0X\x10\xf2\u018a\x02\ub3b1\xa1r\u0738\x00\x00\u07d42?\xca^\xd7\u007fi\x9f\x9d\x990\xf5\xce\xef\xf8\xe5oY\xf0<\x89Hz\x9a0E9D\x00\x00\u07d42H\\\x81\x87(\xc1\x97\xfe\xa4\x87\xfb\xb6\xe8)\x15\x9e\xba\x83p\x899!\xb4\x13\xbcN\xc0\x80\x00\xe0\x942P\xe3\xe8X\xc2j\xde\u032d\xf3jVc\xc2*\xa8LAp\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x942Y\xbd/\xdd\xfb\xbco\xba\u04f6\xe8t\xf0\xbb\xc0,\xda\x18\xb5\x8a\x02\x84`VI[\r\x18\x80\x00\u07d42uIo\xd4\u07491\xfdi\xfb\n\v\x04\xc4\xd1\xff\x87\x9e\xf5\x89\x18-~L\xfd\xa08\x00\x00\u07d42{\xb4\x9euOo\xb4\xf73\xc6\xe0o9\x89\xb4\xf6]K\xee\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d42\x82y\x1do\xd7\x13\xf1\xe9OK\xfdV^\xaax\xb3\xa0Y\x9d\x89Hz\x9a0E9D\x00\x00\u07d42\x83\xeb\u007f\x917\xdd9\xbe\xd5_\xfek\x8d\xc8E\xf3\xe1\xa0y\x89\x03\x97\n\xe9!Ux\x00\x00\u07d42\x86\t\x97\xd70\xb2\xd8;s$\x1a%\xd3f}Q\xc9\b\xef\x89\x1b\x1a\b\x927\a=\x00\x00\xe0\x942\x86\u047cez1,\x88G\xd9<\xb3\xcbyP\xf2\xb0\xc6\xe3\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x942\xa2\r\x02\x8e,b\x18\xb9\xd9[D\\w\x15$cj\"\xef\x8a\x02\x02\xfe\xfb\xf2\xd7\xc2\xf0\x00\x00\u07d42\xa7\x06\x91%\\\x9f\xc9y\x1aOu\u0238\x1f8\x8e\n%\x03\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d42\xb7\xfe\xeb\xc5\u015b\xf6^\x86\x1cL\v\xe4*v\x11\xa5T\x1a\x89w\u9aa8R\\\x10\x00\x00\xe0\x942\xba\x9a}\x04#\xe0:R_\xe2\xeb\xebf\x1d \x85w\x8b\u060a\x04<3\xc1\x93ud\x80\x00\x00\u07d42\xbb.\x96\x93\xe4\xe0\x854M/\r\xbdF\xa2\x83\u3807\xfd\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x942\xc2\xfd\u2daa\xbb\x80\u5ba2\xb9I\xa2\x17\xf3\xcb\t\"\x83\x8a\x010a`\xaf\xdf 7\x80\x00\u07d42\xd9P\xd5\xe9>\xa1\u0574\x8d\xb4qO\x86{\x03 \xb3\x1c\x0f\x897\b\xba\xed=h\x90\x00\x00\u07d42\u06f6qlT\xe81e\x82\x9aJ\xbb6uxI\xb6\xe4}\x8965\u026d\xc5\u07a0\x00\x00\u07d42\xebd\xbe\x1b]\xed\xe4\b\u01bd\xef\xben@\\\x16\xb7\xed\x02\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d42\xef\\\xdcg\x1d\xf5V*\x90\x1a\xee]\xb7\x16\xb9\xbev\xdc\xf6\x89lk\x93[\x8b\xbd@\x00\x00\u07d42\xf2\x9e\x87'\xa7LkC\x01\xe3\xff\xff\x06\x87\xc1\xb8p\xda\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d42\xfa\x0e\x86\xcd\b}\u058di1\x90\xf3-\x931\t\t\xedS\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d42\xfb\xee\xd6\xf6&\xfc\xdf\xd5\x1a\xca\xfbs\v\x9e\xef\xf6\x12\xf5d\x89lk\x93[\x8b\xbd@\x00\x00\u07943\x00\xfb\x14\x9a\xde\xd6[\u02e6\xc0N\x9c\u05b7\xa0;\x89;\xb1\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x943\x01\xd9\xca/;\xfe\x02by\xcdh\x19\xf7\x9a)=\x98\x15n\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\xe0\x943\b\xb04f\xc2z\x17\xdf\xe1\xaa\xfc\xeb\x81\xe1m)4Vo\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07943\x1a\x1c&\xcci\x94\xcd\xd3\xc1K\xec\xe2v\xff\xffK\x9d\xf7|\x88\xfaz\xed\xdfO\x06\x80\x00\xe0\x943&\xb8\x8d\xe8\x06\x18DT\xc4\v'\xf3\t\xd9\xddm\u03f9x\x8a\x03\xca\\f\u067cD0\x00\x00\xe0\x943)\xeb;\xafCE\xd6\x00\xce\xd4\x0en\x99ueo\x117B\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d432\r\xd9\x0f+\xaa\x11\r\xd34\x87*\x99\x8f\x14\x84&E<\x8965f3\xeb\xd8\xea\x00\x00\u07d436\xc3\xefn\x8bP\xee\x90\xe07\xb1d\xb7\xa8\xea_\xaa\xc6]\x89\x0e\u0223\xa7\x1c\"T\x00\x00\xe0\x9438\fo\xffZ\xcd&Q0\x96)\u06daq\xbf? \u017a\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d43:\xd1Yd\x01\xe0Z\xea-6\xcaG1\x8e\xf4\xcd,\xb3\u07c9\x9d\xc0\\\xce(\u00b8\x00\x00\u07d43C@\xeeK\x9c\u0701\xf8P\xa7Q\x16\xd5\x0e\u9d98%\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d43H\x1e\x85n\xbe\u050e\xa7\b\xa2t&\xef(\xe8g\xf5|\u0449\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x943V[\xa9\xda,\x03\xe7x\xce\x12)O\b\x1d\xfe\x81\x06M$\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07943X\x1c\xee#0\x88\xc0\x86\r\x94N\f\xf1\u03ab\xb8&\x1c.\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d43XX\xf7I\xf1i\u02bc\xfeR\xb7\x96\xe3\xc1\x1e\xc4~\xa3\u0089\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x943^\"\x02[zw\u00e0t\u01cb\x8e=\xfe\a\x13A\x94n\x8a\x02'\xcas\n\xb3\xf6\xac\x00\x00\u07d43b\x9b\xd5/\x0e\x10{\xc0q\x17ld\xdf\x10\x8fdw}I\x89\x01\xcf\xddth!n\x80\x00\u07d43{;\u07c6\xd7\x13\xdb\xd0{]\xbf\xcc\x02+z{\x19F\xae\x89\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d43|\xfe\x11W\xa5\u0191 \x10\xddV\x153y\x17i\u00b6\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d43\xb36\xf5\xba^\xdb{\x1c\xcc~\xb1\xa0\u0644\xc1#\x1d\x0e\u0709lk\x93[\x8b\xbd@\x00\x00\u07d43\xc4\a\x13;\x84\xb3\xcaL=\xed\x1fFX\x90\f8\x10\x16$\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\xe0\x943\xd1r\xab\a\\Q\xdb\x1c\xd4\n\x8c\xa8\xdb\xff\r\x93\xb8C\xbb\x8a\x016x\x05\x10\xd1-\xe3\x80\x00\u07d43\xe9\xb7\x18#\x95.\x1ff\x95\x8c'\x8f\u008b\x11\x96\xa6\u0164\x89\x05k\xc7^-c\x10\x00\x00\u07d43\xeakxU\xe0[\a\xab\x80\u06b1\xe1M\xe9\xb6I\xe9\x9bl\x89\x1c\xd6\xfb\xadW\xdb\xd0\x00\x00\u07d43\xf1R#1\rD\u078bf6h_:L=\x9cVU\xa5\x89\r\x94b\xc6\xcbKZ\x00\x00\u07d43\xf4\xa6G\x1e\xb1\xbc\xa6\xa9\xf8[;Hr\xe1\aU\xc8+\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d43\xfbWzM!O\xe0\x10\xd3,\xca|>\xed\xa6?\x87\xce\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d43\xfdq\x8f\v\x91\xb5\xce\u020a]\xc1^\xec\xf0\xec\xef\xa4\xef=\x89\x17r$\xaa\x84Lr\x00\x00\u07d44\x14\x80\u030c\xb4v\xf8\xd0\x1f\xf3\b\x12\xe7\xc7\x0e\x05\xaf\xaf]\x89lk\x93[\x8b\xbd@\x00\x00\u07d44'-^ut1]\xca\u9afd1{\xac\x90(\x9dGe\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x9440\xa1c\x81\xf8i\xf6\xeaT#\x91XU\xe8\x00\x885%\xa9\x8a\x03\xca\\f\u067cD0\x00\x00\u07d441\x86%\x81\x8e\xc1?\x11\x83Z\xe9sS\xce7}oY\n\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d449<]\x91\xb9\xdeYr\x03\xe7[\xacC\t\xb5\xfa=(\u00c9\n\x84Jt$\xd9\xc8\x00\x00\u07d449\x99\x8b$|\xb4\xbf\x8b\xc8\nm+5'\xf1\xdf\xe9\xa6\u0489\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d44C}\x14ed\v\x13l\xb5\x84\x1c?\x93O\x9b\xa0\xb7\t}\x89\t`\xdbwh\x1e\x94\x00\x00\u07d44J\x8d\xb0\x86\xfa\xedN\xfc7\x13\x1b:\"\xb0x-\xadp\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x944fM\"\x0f\xa7\xf3yX\x02J32\u0584\xbc\xc6\xd4\u023d\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d44f\xf6~9cl\x01\xf4;:!\xa0\xe8R\x93%\xc0\x86$\x89-\xb1\x16vP\xac\xd8\x00\x00\u07d44\x856\x1e\xe6\xbf\x06\xefe\b\xcc\xd2=\x94d\x1f\x81M>/\x89lk\x93[\x8b\xbd@\x00\x00\u07d44\x85\xf6!%d3\xb9\x8aB\x00\xda\xd8W\xef\xe5Y7\uc609lk\x93[\x8b\xbd@\x00\x00\u07d44\x95\x8aF\xd3\x0e0\xb2s\xec\xc6\xe5\xd3X\xa2\x12\xe50~\x8c\x89lk\x93[\x8b\xbd@\x00\x00\u07d44\x97\xddf\xfd\x11\x80q\xa7\x8c,\xb3n@\xb6e\x1c\xc8%\x98\x89\x05\xf1\x01kPv\xd0\x00\x00\xe0\x944\x9a\x81k\x17\xab='\xbb\xc0\xae\x00Q\xf6\xa0p\xbe\x1f\xf2\x9d\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d44\x9d,\x91\x8f\u041e(\a1\x8ef\xceC)\t\x17k\xd5\v\x89<\xb7\x1fQ\xfcU\x80\x00\x00\u07d44\xa0C\x1f\xff^\xad\x92\u007f\xb6`\f\x1e\xa8\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d44\xff&\xeb`\xa8\u0469ZH\x9f\xae\x13n\xe9\x1dNX\bL\x89 \x86\xac5\x10R`\x00\x00\u07d44\xffX)R\xff$E\x8f{\x13\xd5\x1f\vO\x98p\"\xc1\xfe\x89\x98\x06\xde=\xa6\xe9x\x00\x00\u07d45\x10k\xa9N\x85c\u0533\xcb<\\i,\x10\xe6\x04\xb7\xce\u0609lk\x93[\x8b\xbd@\x00\x00\xe0\x945\x14_b\x03\x97\u019c\xb8\xe0\tb\x96\x1f\x0fH\x86d9\x89\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d45\x14t0\xc3\x10e\x00\u77e2\xf5\x02F.\x94p<#\xb1\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x945\x17\x87\x845\x05\xf8\xe4\xef\xf4ef\xcc\u695fM\x1c_\xe7\x8a\x01\xf5q\x89\x87fKH\x00\x00\xe0\x945\x1f\x16\xe5\xe0sZ\xf5gQ\xb0\xe2%\xb2B\x11q9@\x90\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\xe0\x945$\xa0\x00#N\xba\xaf\a\x89\xa14\xa2\xa4\x178<\xe5(*\x8a\x011yU\x94}\x8e,\x00\x00\u07d45&\xee\xce\x1ak\xdc>\xe7\xb4\x00\xfe\x93[HF?1\xbe\u05c9\x04w\x87\x9bm\x140\x00\x00\u07d45*x_J\x92\x162PL\xe5\xd0\x15\xf8\xd7FO\xa3\xdb\x14\xe7r\x92\x13\u03aa7\x8c\t^\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d45\xaf\x04\n\f\xc23zv\xaf(\x81T\xc7V\x1e\x1a#3I\x8965\u026d\xc5\u07a0\x00\x00\u07d45\xb0>\xa4$W6\xf5{\x85\xd2\xebyb\x8f\x03m\xdc\xd7\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d45\xbd$he\xfa\xb4\x90\xac\bz\xc1\xf1\xd4\xf2\xc1\r\f\xda\x03\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x945\xbff\x88R/5Fz\u007fu0#\x14\xc0+\xa1v\x80\x0e\x8a\x03\xafA\x82\x02\xd9T\xe0\x00\x00\u07d45\u022d\xc1\x11%C+;w\xac\xd6F%\xfeX\xeb\xee\x9df\x89lk\x93[\x8b\xbd@\x00\x00\u07d45\u0497\x0fI\xdc\xc8\x1e\xa9\xeep~\x9c\x8a\n\xb2\xa8\xbbtc\x89N\x10\x03\xb2\x8d\x92\x80\x00\x00\u07d45\xe0\x96\x12\r\xea\xa5\xc1\xec\xb1d^,\u02cbN\xdb\xd9)\x9a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d45\xea!c\xa3\x8c\u07da\x12?\x82\xa5\xec\x00%\x8d\xae\v\xc7g\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d45\xf1\xda\x12{\x837o\x1b\x88\xc8*3Y\xf6z^g\xddP\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d45\xf2\x94\x9c\xf7\x8b\xc2\x19\xbbO\x01\x90|\xf3\xb4\xb3\u04c6T\x82\x89\x0f\xb5\xc8l\x92\xe44\x00\x00\u07d45\xf5\x86\x01I\xe4\xbb\xc0K\x8a\u0172r\xbeU\xad\x1a\xcaX\xe0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d46\x02E\x8d\xa8omj\x9d\x9e\xb0=\xaf\x97\xfeV\x19\xd4B\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x057-\x93\xa9\x01\t\x88\x01\x8f\x9f1]\x03.\u0448\x0f\xa1\x89\x1b\x1b\xcfQ\x89j}\x00\x00\u07d46\x16\xd4H\x98_]2\xae\xfa\x8b\x93\xa9\x93\xe0\x94\xbd\x85I\x86\x89\v\"\u007fc\xbe\x81<\x00\x00\u07d46\x16\xfbF\xc8\x15x\xc9\xc8\xebM;\xf8\x80E\x1a\x887\x9d}\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d46\x1cu\x93\x16\x96\xbc=B}\x93\xe7lw\xfd\x13\xb2A\xf6\xf4\x89\x1d\xc5\xd8\xfc&m\xd6\x00\x00\u07d46\x1d\x9e\xd8\v[\xd2|\xf9\xf1\"o&u2X\xee_\x9b?\x89\xbfi\x14\xba}r\xc2\x00\x00\u07d46\x1f;\xa9\xed\x95kw\x0f%}6r\xfe\x1f\xf9\xf7\xb0$\f\x89 \x86\xac5\x10R`\x00\x00\u07d46\"|\u07e0\xfd;\x9d~jtF\x85\xf5\xbe\x9a\xa3f\xa7\xf0\x89\n\xc2s\x0e\xe9\xc6\xc1\x80\x00\u07d46/\xbc\xb1\x06b7\n\x06\x8f\xc2e&\x02\xa2Wy7\xcc\xe6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d460\xc5\xe5e\u03aa\x8a\x0f\x0f\xfe2\x87^\xae*l\xe6<\x19\x89\t7r+7t\xd0\x00\x00\u07d463\x9f\x84\xa5\u00b4L\xe5=\xfd\xb6\xd4\xf9}\xf7\x82\x12\xa7\u07c9\x11o\x18\xb8\x17\x15\xa0\x00\x00\u07d464:\xec\xa0{n\u054a\x0eb\xfaN\xcbI\x8a\x12O\xc9q\x89\x10CV\x1a\x88)0\x00\x00\u07d46au@4\x81\xe0\xab\x15\xbbQF\x15\u02f9\x89\xeb\u018f\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d46ro;\x88Z$\xf9)\x96\u0681b^\u022d\x16\xd8\xcb\xe6\x89S\xafu\u0441HW\x80\x00\xe0\x946s\x95C\x99\xf6\u07feg\x18\x18%\x9b\xb2x\xe2\xe9.\xe3\x15\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d46u\x8e\x04\x9c\u064b\u03a1\"w\xa6v\xf9)sb\x89\x00#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d46\u007fY\u0302yS)8NA\xe1(1\x15\xe7\x91\xf2j\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x81\x0f\xf9\xd2\x13\xa2q\xed\xa2\xb8\xaay\x8b\xe6T\xfaK\xbe\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d46\x8cT\x14\xb5k\x84U\x17\x1f\xbf\ab \xc1\u02e4\xb5\xca1\x89\x1e>\xf9\x11\xe8=r\x00\x00\xe0\x946\x90$k\xa3\xc8\x06y\xe2.\xacD\x12\xa1\xae\xfc\xe6\xd7\u0342\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d46\x92\x8bU\xbc\x86\x15\t\xd5\x1c\x8c\xf1\xd5F\xbf\xecn>\x90\xaf\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d46\x98\"\xf5W\x8b@\xdd\x1fDqpk\"\u0357\x13R\xdak\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d46\x9e\xf7a\x19_:7>$\xec\xe6\xcd\"R\x0f\xe0\xb9\xe8n\x89\x1c\xff\xaf\xc9M\xb2\b\x80\x00\u07d46\xa0\x8f\xd6\xfd\x1a\xc1|\xe1^\xd5~\xef\xb1*+\u2048\xbf\x89Hz\x9a0E9D\x00\x00\u07d46\xa0\xe6\x1e\x1b\xe4\u007f\xa8~0\xd3(\x88\xee\x030\x90\x1c\xa9\x91\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x946\xb2\xc8^:\xee\xeb\xb7\rc\u0124s\f\xe2\xe8\xe8\x8a6$\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x946\xbfC\xff5\u07d0\x90\x88$3l\x9b1\xce3\x06~/P\x8aIr\x15\x10\xc1\xc1\xe9H\x00\x00\u07d46\xbf\xe1\xfa;{p\xc1r\xeb\x04/h\x19\xa8\x97%\x95A>\x8965\u026d\xc5\u07a0\x00\x00\xe0\x946\xc5\x10\xbf\x8dnV\x9b\xf2\xf3}G&]\xbc\xb5\x02\xff+\u038a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x946\xd8]\xc3h1V\xe6;\xf8\x80\xa9\xfa\xb7x\x8c\xf8\x14:'\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d46\u07cf\x88<\x12s\xec\x8a\x17\x1fz3\xcf\xd6I\xb1\xfe`u\x89\fRHJ\xc4\x16\x89\x00\x00\xe0\x946\xe1Va\f\xd8\xffd\xe7\x80\u061d\x00T8\\\xa7gU\xaa\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d46\xfe\xc6,,B^!\x9b\x18D\x8a\xd7W\x00\x9d\x8cT\x02o\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d47\x00\xe3\x02t$\xd99\xdb\xde]B\xfbx\xf6\xc4\xdb\xec\x1a\x8f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d47\x02\xe7\x04\xcc!at9\xadN\xa2zW\x14\xf2\xfd\xa1\xe92\x8965\u026d\xc5\u07a0\x00\x00\u07d47\x035\fMo\xe374,\xdd\xc6[\xf1\xe28k\xf3\xf9\xb2\x89m\x81!\xa1\x94\xd1\x10\x00\x00\xe0\x947\b\xe5\x9d\xe6\xb4\x05P\x88x)\x02\xe0W\x9cr\x01\xa8\xbfP\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d47\x126~^U\xa9mZ\x19\x16\x8fn\xb2\xbc~\x99q\xf8i\x8965\u026d\xc5\u07a0\x00\x00\u07d47\x19Zc]\xccb\xf5jq\x80I\xd4~\x8f\x9f\x96\x83(\x91\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d47'4\x1f&\xc1 \x01\xe3x@^\xe3\x8b-\x84d\xecq@\x89lk\x93[\x8b\xbd@\x00\x00\u07d47.E:kb\x9f'g\x8c\u022e\xb5\xe5|\xe8^\xc0\xae\xf9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d474\xcb\x18t\x91\xed\xe7\x13\xae[;-\x12(J\xf4k\x81\x01\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d477!n\xe9\x1f\x17w2\xfbX\xfa@\x97&r\a\xe2\xcfU\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d47M;\xbb\x057Q\xf9\xf6\x8d\xdb\a\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d48r\xf4\x8d\xc5\xe3\xf8\x17\xbck*\xd2\xd00\xfc^\x04q\x19=\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d48~\xea\xfdk@\t\u07af\x8b\u0578Zr\x98:\x8d\xcc4\x87\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d48\x81\xde\xfa\xe1\xc0{<\xe0Lx\xab\xe2k\f\u070ds\xf0\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d48\x83\xbe\xcc\b\xb9\xbeh\xad;\b6\xaa\u00f6 \xdc\x00\x17\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d48\x85\xfe\xe6q\a\xdc:\xa9\x8a\x1d\x99:t\xdf\\\xd7T\xb9\x8dR\x9a\x89a\t=|,m8\x00\x00\u07d48\xe4m\xe4E<8\xe9A\xe7\x93\x0fC0O\x94\xbb{+\xe8\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d48\xe7\u06e8\xfdO\x1f\x85\r\xbc&I\xd8\xe8O\tR\xe3\xeb<\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d48\xe8\xa3\x1a\xf2\xd2e\xe3\x1a\x9f\xff-\x8fF(m\x12E\xa4g\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d48\xeao[Z{\x88AuQ\xb4\x12=\xc1'\xdf\xe94-\xa6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d48\xee\xc6\xe2\x17\xf4\xd4\x1a\xa9 \xe4$\xb9RQ\x97\x04\x1c\xd4\u0189\xf0\r%\xeb\x92.g\x00\x00\xe0\x948\xf3\x87\xe1\xa4\xedJs\x10n\xf2\xb4b\xe4t\xe2\xe3\x14:\u040a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d49\x11a\xb0\xe4<0 f\u898d,\xe7\xe1\x99\xec\xdb\x1dW\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x949\x15\uad6b.Yw\xd0u\xde\xc4}\x96\xb6\x8bK\\\xf5\x15\x8a\r\a\x01\x81\x85\x12\x0f@\x00\x00\u07d49\x1aw@\\\t\xa7+^\x846#z\xaa\xf9]h\xda\x17\t\x89\x02\xa9&J\xf3\u0479\x00\x00\u07d49\x1f \x17m\x126\rrMQG\n\x90p6uYJM\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d49$3\xd2\u0383\xd3\xfbJv\x02\u0323\xfa\xcaN\xc1@\xa4\xb0\x89\x02\xc3\xc4e\xcaX\xec\x00\x00\xe0\x949?x;\\\u06c6\"\x1b\xf0)O\xb7\x14\x95\x9c{E\x89\x9c\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d49?\xf4%^\\e\x8f.\u007f\x10\xec\xbd)%rg\x1b\xc2\u0489lk\x93[\x8b\xbd@\x00\x00\u07d49A2`\x0fAU\xe0\u007fME\xbc>\xb8\xd9\xfbr\xdc\u05c4\x89\x9fn\x92\xed\xea\a\xd4\x00\x00\u07d49Q\xe4\x8e<\x86\x9ekr\xa1C\xb6\xa4Ph\u0379\xd4f\u0409\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x949T\xbd\xfe\v\xf5\x87\u0195\xa3\x05\xd9$L=[\xdd\xda\u027b\x8a\x04\x10'\x83'\xf9\x85`\x80\x00\u07d49]m%U \xa8\xdb)\xab\xc4}\x83\xa5\u06ca\x1a}\xf0\x87\x89\x05k\xc7^-c\x10\x00\x00\u07d49ck%\x81\x1b\x17j\xbf\xcf\xee\xcad\xbc\x87E/\x1f\xdf\xf4\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d49i\xb4\xf7\x1b\xb8u\x1e\xdeC\xc0\x166:zaOv\x11\x8e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x949x/\xfe\x06\xacx\x82*<:\x8a\xfe0^P\xa5a\x88\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d49zn\xf8v:\x18\xf0\x0f\xac!~\x05\\\r0\x94\x10\x10\x11\x89lk\x93[\x8b\xbd@\x00\x00\u07d49|\u06cc\x80\xc6yP\xb1\x8deB)a\x0e\x93\xbf\xa6\xee\x1a\x89?\x95\xc8\xe0\x82\x15!\x00\x00\u07d49\x82O\x8b\xce\xd1v\xfd>\xa2.\u01a4\x93\xd0\xcc\xc3?\xc1G\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d49\x93l'\x19E\v\x94 \xcc%\"\u03d1\xdb\x01\xf2'\xc1\xc1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d49\x95\xe0\x96\xb0\x8aZrh\x00\xfc\xd1}\x9cd\xc6N\b\x8d+\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d49\x9a\xa6\xf5\xd0x\xcb\tp\x88+\u0259 \x06\xf8\xfb\xdf4q\x8965\u026d\xc5\u07a0\x00\x00\u07d49\xaa\x05\xe5m}28T!\u03d36\xe9\r=\x15\xa9\xf8Y\x89\x01h\u048e?\x00(\x00\x00\u07d49\xaa\xf0\x85M\xb6\xeb9\xbc{.C\x84jv\x17\x1c\x04E\u0789dI\xe8NG\xa8\xa8\x00\x00\u07d49\xb1\xc4q\xae\x94\xe1!dE.\x81\x1f\xbb\xe2\xb3\xcdru\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d49\xb2\x992t\x90\xd7/\x9a\x9e\xdf\xf1\x1b\x83\xaf\xd0\xe9\xd3\xc4P\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d49\xba\u018d\x94xY\xf5\x9e\x92&\b\x9c\x96\xd6.\x9f\xbe<\u0789\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x949\xbf\xd9xh\x9b\xec\x04\x8f\xc7v\xaa\x15$\u007f^\x1d|9\xa2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d49\xc7s6|\x88%\xd3YlhoB\xbf\r\x141\x9e?\x84\x89\a?u\u0460\x85\xba\x00\x00\u07d49\u05291@,\fy\xc4W\x18o$\u07c7)\u03d5p1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d49\xd6\xca\xca\"\xbc\xcdjr\xf8~\xe7\u05b5\x9e\v\xde!\xd7\x19\x89l\x87T\xc8\xf3\f\b\x00\x00\u07d49\xe0\xdbM`V\x8c\x80\v\x8cU\x00\x02l%\x94\xf5v\x89`\x8965\u026d\xc5\u07a0\x00\x00\xe0\x949\xeeO\xe0\x0f\xbc\xeddph\xd4\xf5|\x01\xcb\"\xa8\v\xcc\u044a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d49\xf1\x983\x1eK!\xc1\xb7`\xa3\x15_J\xb2\xfe\x00\xa7F\x19\x89lk\x93[\x8b\xbd@\x00\x00\u07d49\xf4Fc\xd9%a\t\x1b\x82\xa7\r\xcfY=u@\x05\x97:\x89\n\u05cb.\xdc!Y\x80\x00\u07d4:\x03U\x94\xc7GGmB\xd1\xee\x96l6\"L\xdd\"I\x93\x89\x13J\xf7Ei\xf9\xc5\x00\x00\u07d4:\x04W(G\xd3\x1e\x81\xf7v\\\xa5\xbf\xc9\xd5W\x15\x9f6\x83\x89\a6-\r\xab\xea\xfd\x80\x00\xe0\x94:\x06\xe3\xbb\x1e\xdc\xfd\fD\xc3\aM\xe0\xbb`k\x04\x98\x94\xa2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794:\x10\x88\x8b~\x14\x9c\xae',\x010,2}\n\xf0\x1a\v$\x88\xeb\xec!\xee\x1d\xa4\x00\x00\u07d4:1\b\xc1\u6023;3l!\x13\x134@\x9d\x97\xe5\xad\xec\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4:6\x8e\xfeJ\u05c6\xe2c\x95\xec\x9f\u01adi\x8c\xae)\xfe\x01\x89\"E\x89\x96u\xf9\xf4\x00\x00\u07d4:=\xd1\x04\xcd~\xb0O!\x93/\xd43\xeaz\xff\u04d3i\xf5\x89\x13aO#\xe2B&\x00\x00\u07d4:B\x97\xda\xc4.\x1eO\xb8\xcb1\xec\xddC\xaew<\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94:\x99`&m\xf6I cS\x8a\x99\xf4\x87\xc9P\xa3\xa5\uc78a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4:\x9b\x11\x10)\xce\x1f \xc9\x10\x9czt\xee\xee\xf3OO.\xb2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4:\x9eTA\xd4K$;\xe5[u\x02z\x1c\ub7ac\xf5\r\xf2\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94:\xa0z4\xa1\xaf\u0216}=\x13\x83\xb9kb\u03d6\xd5\xfa\x90\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94:\xa4,!\xb9\xb3\x1c>'\xcc\xd1~\t\x9a\xf6y\xcd\xf5i\a\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4:\xa9H\xea\x029wU\xef\xfb/\x9d\xc99-\xf1\x05\x8f~3\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4:\xad\xf9\x8ba\xe5\u0216\xe7\xd1\x00\xa39\x1d2P\"]a\u07c9\f\xafg\x007\x01h\x00\x00\u07d4:\xaeHr\xfd\x90\x93\xcb\xca\xd1@o\x1e\x80x\xba\xb5\x03Y\xe2\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4:\xbb\x8a\xdf\xc6\x04\xf4\x8dY\x84\x81\x1d\u007f\x1dR\xfe\xf6u\x82p\x89\xf2\x97\x19\xb6o\x11\f\x00\x00\u07d4:\xc2\xf0\xff\x16\x12\xe4\xa1\xc3F\xd53\x82\xab\xf6\u0622[\xaaS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4:\xc9\xdczCj\xe9\x8f\xd0\x1cz\x96!\xaa\x8e\x9d\v\x8bS\x1d\x89a\t=|,m8\x00\x00\xe0\x94:\xd0aI\xb2\x1cU\xff\x86|\xc3\xfb\x97@\u04bc\xc7\x10\x121\x8a)\xb7d2\xb9DQ \x00\x00\u07d4:\xd7\x02C\u060b\xf0@\x0fW\xc8\xc1\xfdW\x81\x18H\xaf\x16*\x89.\x9e\xe5\u00c6S\xf0\x00\x00\u07d4:\xd9\x15\xd5P\xb7#AV \xf5\xa9\xb5\xb8\x8a\x85\xf3\x82\xf05\x8965\u026d\xc5\u07a0\x00\x00\u07d4:\xe1`\xe3\xcd`\xae1\xb9\xd6t-h\xe1Nv\xbd\x96\xc5\x17\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4:\xe6+\xd2q\xa7`c\u007f\xady\xc3\x1c\x94\xffb\xb4\xcd\x12\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4:\xeaN\x82\xd2@\x02H\xf9\x98q\xa4\x1c\xa2W\x06\r:\"\x1b\x8965\u026d\xc5\u07a0\x00\x00\u07d4:\xf6[>(\x89ZJ\x00\x11S9\x1d\x1ei\xc3\x1f\xb9\xdb9\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4;\a\xdbZ5\u007fZ\xf2HL\xbc\x9dw\xd7;\x1f\xd0Q\x9f\u01c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4;\n\u032fK`|\xfea\xd1s4\xc2\x14\xb7\\\xde\xfd\xbd\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\x13c\x1a\x1b\x89\xcbVeH\x89\x9a\x1d`\x91\\\xdc\xc4 [\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\x15\x90\x99\aR\a\u0180vc\xb1\xf0\xf7\xed\xa5J\xc8\xcc\xe3\x89j\xc4\xe6[i\xf9-\x80\x00\u07d4;\x197\xd5\u74f8\x9bc\xfb\x8e\xb5\xf1\xb1\xc9\xcak\xa0\xfa\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\"\xda*\x02q\xc8\xef\xe1\x02S'scji\xb1\xc1~\t\x89\x1b6\xa6DJ>\x18\x00\x00\u07d4;\"\u07a3\xc2_\x1bY\u01fd'\xbb\x91\u04e3\xea\xec\xef9\x84\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94;#g\xf8IK_\xe1\x8dh<\x05]\x89\x99\x9c\x9f=\x1b4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4;,E\x99\x0e!GDQ\xcfOY\xf0\x19U\xb31\xc7\xd7\u0249lk\x93[\x8b\xbd@\x00\x00\xe0\x94;A\x00\xe3\ns\xb0\xc74\xb1\x8f\xfa\x84&\u045b\x191/\x1a\x8a\v\xb5\u046ap\n\xfd\x90\x00\x00\u07d4;B\xa6m\x97\x9fX(4tz\x8b`B\x8e\x9bN\xec\xcd#\x89!\xa1\u01d0\xfa\xdcX\x00\x00\u07d4;Gh\xfdq\xe2\xdb,\xbe\u007f\xa0PH<'\xb4\xeb\x93\x1d\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;Vj\x8a\xfa\u0456\x82\xdc,\xe8g\x9a<\xe4D\xa5\xb0\xfdO\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94;\\%\x1d\u007f\u05c9;\xa2\t\xfeT\x1c\xec\xd0\xce%:\x99\r\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4;^\x8b\x17w\xca\x18A\x896\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94;\x93\xb1a6\xf1\x1e\xaf\x10\x99l\x95\x99\r;'9\xcc\xea_\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4;\xabK\x01\xa7\xc8K\xa1?\uea70\xbb\x19\x1bw\xa3\xaa\u0723\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4;\xb55\x98\xcc \xe2\x05]\xc5S\xb0I@J\u0277\xdd\x1e\x83\x89!W\x1d\xf7|\x00\xbe\x00\x00\u07d4;\xbc\x13\xd0J\xcc\xc0pz\xeb\u072e\xf0\x87\u0438~\v^\u327e\xd1\xd0&=\x9f\x00\x00\x00\u07d4;\xc6\xe3\xeezV\u038f\x14\xa3u2Y\x0fcqk\x99f\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\xc8]ls[\x9c\xdaK\xba_H\xb2K\x13\xe7\x0600{\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4;\xd6$\xb5H\xcbe\x976\x90~\u062a<\fp^$\xb5u\x89lk\x93[\x8b\xbd@\x00\x00\u07d4;\u0660m\x1b\xd3lN\xdd'\xfc\r\x1f[\b\x8d\xda\xe3\xc7*\x89\x1b\x1azB\v\xa0\r\x00\x00\u0794;\u077c\x814\xf7}UY\u007f\xc9|&\xd2f\x98\t\x06\x04\ub23e -j\x0e\xda\x00\x00\xe0\x94;\xf8n\u0623\x15>\xc93xj\x02\xac\t\x03\x01\x85^Wk\x8a_J\x8c\x83u\xd1U@\x00\x00\u07d4;\xfb\u04c4|\x17\xa6\x1c\xf3\xf1{R\xf8\ub879`\xb3\U000df262\xa1]\tQ\x9b\xe0\x00\x00\u07d4<\x03\xbb\xc0#\xe1\xe9?\xa3\xa3\xa6\xe4(\xcf\f\xd8\xf9^\x1e\u0189Rf<\u02b1\xe1\xc0\x00\x00\u07d4<\f=\ufb1c\xeaz\xcc1\x9a\x96\xc3\v\x8e\x1f\xed\xabEt\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4<\x15\xb3Q\x1d\xf6\xf04.sH\u0309\xaf9\xa1h\xb7s\x0f\x8965\u026d\xc5\u07a0\x00\x00\u07d4<\x1f\x91\xf3\x01\xf4\xb5e\xbc\xa2GQ\xaa\x1fv\x13\"p\x9d\u0749a\t=|,m8\x00\x00\xe0\x94<(l\xfb0\x14n_\u05d0\xc2\xc8T\x15RW\x8d\xe34\u060a\x02)\x1b\x11\xaa0n\x8c\x00\x00\u07d4<2.a\x1f\u06c2\rG\xc6\xf8\xfcd\xb6\xfa\xd7L\xa9_^\x89\r%\x8e\xce\x1b\x13\x15\x00\x00\u07d4\xa5\xe5\xbfb\xbb\u0309\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4<\x86\x9c\tie#\xce\xd8$\xa0pAF\x05\xbbv#\x1f\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4<\x92V\x19\u02731DF?\x057\u06165\x87\x06\xc5 \xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\x98YK\xf6\x8bW5\x1e\x88\x14\xae\x9em\xfd-%J\xa0o\x89\x10CV\x1a\x88)0\x00\x00\u07d4<\xad\xeb=>\xed?b1\x1dRU>p\xdfJ\xfc\xe5o#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94<\xae\xdbS\x19\xfe\x80eC\xc5nP!\xd3r\xf7\x1b\xe9\x06.\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4<\xaf\xaf^bPV\x15\x06\x8a\xf8\xeb\"\xa1:\u0629\xe5Pp\x89lf\x06E\xaaG\x18\x00\x00\u07d4<\xb1y\xcbH\x01\xa9\x9b\x95\u00f0\xc3$\xa2\xbd\xc1\x01\xa6S`\x89\x01h\u048e?\x00(\x00\x00\u07d4<\xb5a\u0386BK5\x98\x91\xe3d\xec\x92_\xfe\xff'}\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xcbq\xaah\x80\xcb\v\x84\x01-\x90\xe6\a@\xec\x06\xac\u05cf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\xce\xf8\x86yW9G\xe9I\x97y\x8a\x1e2~\b`:e\x89+\xc9\x16\u059f;\x02\x00\x00\xe0\x94<\xd1\xd9s\x1b\xd5H\xc1\xddo\u03a6\x1b\xebu\xd9\x17T\xf7\u04ca\x01\x16\x1d\x01\xb2\x15\xca\xe4\x80\x00\u07d4<\u04e6\xe95y\xc5mIAq\xfcS>z\x90\xe6\xf5\x94d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4<\u05b7Y<\xbe\xe7x0\xa8\xb1\x9d\b\x01\x95\x8f\xcdK\xc5z\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4<\xd7\xf7\xc7\xc257\x80\xcd\xe0\x81\xee\xecE\x82+%\xf2\x86\f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xe1\u0717\xfc\u05f7\xc4\u04e1\x8aI\xd6\xf2\xa5\xc1\xb1\xa9\x06\u05c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4<\xea0*G*\x94\x03y\xdd9\x8a$\xea\xfd\xba\u07c8\xady\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94<\xec\xa9k\xb1\xcd\xc2\x14\x02\x9c\xbc^\x18\x1d9\x8a\xb9M=A\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4<\xf4\x84RO\xbd\xfa\xda\xe2m\xc1\x85\xe3++c\x0f\xd2\xe7&\x89\x18TR\xcb*\x91\xc3\x00\x00\u07d4<\xf9\xa1\xd4e\xe7\x8bp9\xe3iDx\xe2b{6\xfc\xd1A\x89J`S*\xd5\x1b\xf0\x00\x00\u07d4<\xfb\xf0fVYpc\x9e\x13\r\xf2\xa7\xd1k\x0e\x14\xd6\t\x1c\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94=\th\x8d\x93\xad\a\xf3\xab\xe6\x8cr'#\xcdh\t\x90C^\x8a\x06ZL\xe9\x9fv\x9en\x00\x00\u07d4=1X{_\u0546\x98Ex\x87%\xa6c)\nI\xd3g\x8c\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4=?\xadI\xc9\xe5\xd2u\x9c\x8e\x8eZzM`\xa0\xdd\x13V\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4=WO\xcf\x00\xfa\xe1\u064c\u023f\x9d\u07e1\xb3\x95;\x97A\xbc\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4=Z\x8b+\x80\xbe\x8b5\xd8\xec\xf7\x89\xb5\xedz\au\xc5\al\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4=f\xcdK\xd6M\\\x8c\x1b^\xea(\x1e\x10m\x1cZ\xad#s\x89i\xc4\xf3\xa8\xa1\x10\xa6\x00\x00\u0794=j\xe0S\xfc\xbc1\x8do\xd0\xfb\xc3S\xb8\xbfT.h\r'\x88\xc6s\xce<@\x16\x00\x00\u07d4=o\xf8,\x93w\x05\x9f\xb3\r\x92\x15r?`\xc7u\u0211\xfe\x89\r\x8e\\\xe6\x17\xf2\xd5\x00\x00\u07d4=y\xa8S\xd7\x1b\xe0b\x1bD\xe2\x97Yel\xa0u\xfd\xf4\t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4=~\xa5\xbf\x03R\x81\x00\xed\x8a\xf8\xae\xd2e>\x92\x1bng%\x8965\u026d\xc5\u07a0\x00\x00\u07d4=\x81?\xf2\xb6\xedW\xb97\u06bf+8\x1d\x14\x8aA\x1f\xa0\x85\x89\x05k\xc7^-c\x10\x00\x00\u07d4=\x88\x143\xf0J}\r'\xf8ID\xe0\x8aQ-\xa3UR\x87\x89A\rXj \xa4\xc0\x00\x00\u07d4=\x89\xe5\x05\xcbF\xe2\x11\xa5?2\xf1g\xa8w\xbe\xc8\u007fK\n\x89\x01[5W\xf1\x93\u007f\x80\x00\xe0\x94=\x8d\a#r\x1es\xa6\xc0\xd8`\xaa\x05W\xab\xd1L\x1e\xe3b\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4=\x8f9\x88\x1b\x9e\xdf\xe9\x12'\xc3?\xa4\xcd\xd9\x1eg\x85D\xb0\x89\x04\xab\a\xbaC\xad\xa9\x80\x00\u07d4=\x9dk\xe5\u007f\xf8>\x06Y\x85fO\x12VD\x83\xf2\xe6\x00\xb2\x89n\xac\xe4?#\xbd\x80\x00\x00\u07d4=\xa3\x9c\xe3\xefJz9f\xb3.\xe7\xeaN\xbc#5\xa8\xf1\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4=\xaa\x01\u03b7\x0e\xaf\x95\x91\xfaR\x1b\xa4\xa2~\xa9\xfb\x8e\xdeJ\x89Zc\xd2\u027cvT\x00\x00\u07d4=\xb5\xfejh\xbd6\x12\xac\x15\xa9\x9aa\xe5U\x92\x8e\xec\xea\xf3\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4=\xb9\xed\u007f\x02L~&7/\xea\xcf+\x05\b\x03D^8\x10\x89E\xb1H\xb4\x99j0\x00\x00\u07d4=\xbf\r\xbf\xd7x\x90\x80\x053\xf0\x9d\xea\x83\x01\xb9\xf0%\u04a6\x8965\u026d\xc5\u07a0\x00\x00\u07d4=\xce\U0005c18b\x15\xd3N\xdaBn\xc7\xe0K\x18\xb6\x01p\x02\x89lh\xcc\u041b\x02,\x00\x00\xe0\x94=\xd1.Uj`76\xfe\xbaJo\xa8\xbdJ\xc4]f*\x04\x8a#u{\x91\x83\xe0x(\x00\x00\u07d4=\u078b\x15\xb3\u033a\xa5x\x01\x12\xc3\xd6t\xf3\x13\xbb\xa6\x80&\x89`\x1dQZ>O\x94\x00\x00\xe0\x94=\xde\xdb\xe4\x89#\xfb\xf9\xe56\xbf\x9f\xfb\aG\xc9\xcd\u04de\xef\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4=\xea\xe43'\x91?b\x80\x8f\xaa\x1bbv\xa2\xbdch\xea\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4=\xf7b\x04\x9e\u068a\u0192}\x90Lz\xf4/\x94\xe5Q\x96\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>\x04\r@\u02c0\xba\x01%\xf3\xb1_\xde\xfc\xc8?0\x05\xda\x1b\x898E$\xccp\xb7x\x00\x00\u07d4>\v\x8e\xd8n\xd6i\xe1'#\xafur\xfb\xac\xfe\x82\x9b\x1e\x16\x89QM\xe7\xf9\xb8\x12\xdc\x00\x00\xe0\x94>\f\xbejm\xcba\xf1\x10\xc4[\xa2\xaa6\x1d\u007f\xca\xd3\xdas\x8a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4>\x19KN\xce\xf8\xbbq\x1e\xa2\xff$\xfe\xc4\xe8{\xd02\xf7\u0449\x8b\x9d\xc1\xbc\x1a\x03j\x80\x00\xe0\x94>\x1b\"0\xaf\xbb\xd3\x10\xb4\x92jLwmZ\u705cf\x1d\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4>\x1cS0\x0eL\x16\x89\x12\x16<~\x99\xb9]\xa2h\xad(\n\x896b2\\\u044f\xe0\x00\x00\u07d4>\x1c\x96 c\xe0\xd5)YA\xf2\x10\u0723\xabS\x1e\xec\x88\t\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4>,\xa0\xd24\xba\xf6\a\xadFj\x1b\x85\xf4\xa6H\x8e\xf0\n\xe7\x89\x04\xda!\xa3H=V\x80\x00\u07d4>/&#^\x13zs$\xe4\xdc\x15K]\xf5\xafF\xea\x1aI\x89\x017\xaa\xd8\x03-\xb9\x00\x00\xe0\x94>1a\xf1\xea/\xbf\x12ny\xda\x18\x01\u0695\x12\xb3y\x88\u024a\nm\xd9\f\xaeQ\x14H\x00\x00\xe0\x94>6\xc1rS\xc1\x1c\xf3\x89t\xed\r\xb1\xb7Y\x16\r\xa67\x83\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4><\u04fe\xc0e\x91\xd64o%Kb\x1e\xb4\x1c\x89\x00\x8d1\x895\u07fe\u069f74\x00\x00\u07d4>E\xbdU\u06d0`\xec\xed\x92;\xb9\xcbs<\xb3W?\xb51\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4>M\x13\xc5Z\x84\xe4n\xd7\xe9\u02d0\xfd5^\x8a\u0651\u33c965\u026d\xc5\u07a0\x00\x00\u07d4>N\x92e\"<\x9782L\xf2\v\xd0`\x06\xd0\a>\u06cc\x89\a?u\u0460\x85\xba\x00\x00\xe0\x94>O\xbdf\x10\x15\xf6F\x1e\xd6s\\\xef\xef\x01\xf3\x14E\xde:\x8a\x03n4)\x98\xb8\xb0 \x00\x00\xe0\x94>S\xff!\a\xa8\u07be3(I:\x92\xa5\x86\xa7\xe1\xf4\x97X\x8a\x04\xe6\x9c*q\xa4\x05\xab\x00\x00\u07d4>Z9\xfd\xdap\xdf\x11&\xab\r\u011asx1\x1aSz\x1f\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\xe0\x94>Z\xbd\t\xceZ\xf7\xba\x84\x87\xc3Y\xe0\xf2\xa9:\x98k\v\x18\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4>\\\xb8\x92\x8cAx%\xc0:;\xfc\xc5!\x83\xe5\xc9\x1eB\u05c9\xe71\xd9\xc5,\x96/\x00\x00\u07d4>^\x93\xfbL\x9c\x9d\x12F\xf8\xf2G5\x8e\"\xc3\xc5\xd1{j\x89\b!\xab\rD\x14\x98\x00\x00\u07d4>a\x83P\xfa\x01ez\xb0\xef>\xba\xc8\xe3p\x12\xf8\xfc+o\x89\x98\x06\xde=\xa6\xe9x\x00\x00\u07d4>c\xce;$\xca(e\xb4\u0166\x87\xb7\xae\xa3Y~\xf6\xe5H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>f\xb8GiVj\xb6yE\xd5\xfa\x8175V\xbc\u00e1\xfa\x89\b=lz\xabc`\x00\x00\xe0\x94>v\xa6-\xb1\x87\xaat\xf68\x17S;0l\xea\xd0\xe8\u03be\x8a\x06\x9bZ\xfa\xc7P\xbb\x80\x00\x00\u07d4>z\x96k]\xc3W\xff\xb0~\x9f\xe0g\xc4W\x91\xfd\x8e0I\x89\x034-`\xdf\xf1\x96\x00\x00\xe0\x94>\x81w!u#~\xb4\xcb\xe0\xfe-\xca\xfd\xad\xff\xebj\x19\x99\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4>\x83I\xb6\u007fWED\x9fe\x93g\u066dG\x12\xdb[\x89Z\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4>\x83TO\x00\x82U%r\u01c2\xbe\xe5\xd2\x18\xf1\xef\x06J\x9d\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4>\x84\xb3\\[\"ePpa\xd3\vo\x12\xda\x03?\xe6\xf8\xb9\x89a\t=|,m8\x00\x00\u07d4>\x86A\xd4\x87E\xba2/_\xd6\xcbP\x12N\xc4f\x88\u01e6\x9a\u007f\xae\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4>\x91N0\x18\xac\x00D\x93A\u011d\xa7\x1d\x04\xdf\xee\xedb!\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4>\x94\x10\u04f9\xa8~\xd5\xe4Q\xa6\xb9\x1b\xb8\x92?\xe9\x0f\xb2\xb5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4>\x94\xdfS\x13\xfaR\x05p\xef#+\xc31\x1d_b/\xf1\x83\x89lk\x93[\x8b\xbd@\x00\x00\u0794>\x9b4\xa5\u007f3u\xaeY\xc0\xa7^\x19\u0136A\"\x8d\x97\x00\x88\xf8i\x93)g~\x00\x00\u07d4>\xad\xa8\xc9/V\x06~\x1b\xb7<\xe3x\xdaV\xdc,\xdf\xd3e\x89w\xcd\xe9:\xeb\rH\x00\x00\xe0\x94>\xaf\by\xb5\xb6\xdb\x15\x9bX\x9f\x84W\x8bjt\xf6\xc1\x03W\x8a\x01\x898\xb6q\xfae\xa2\x80\x00\u07d4>\xaf1k\x87a]\x88\xf7\xad\xc7|X\xe7\x12\xedMw\x96k\x89\x05m\xbcL\xee$d\x80\x00\u07d4>\xb8\xb3;!\xd2<\u0686\xd8(\x88\x84\xabG\x0e\x16F\x91\xb5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4>\xb9\xef\x06\xd0\xc2Y\x04\x03\x19\x94~\x8czh\x12\xaa\x02S\u0609\t\r\x97/22<\x00\x00\u07d4>\u030e\x16h\xdd\xe9\x95\xdcW\x0f\xe4\x14\xf4B\x11\xc54\xa6\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4>\u03752\xe3\x97W\x96b\xb2\xa4aA\u73c25\x93j_\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4>\xeeo\x1e\x966\vv\x89\xb3\x06\x9a\xda\xf9\xaf\x8e\xb6\f\u404965\u026d\xc5\u07a0\x00\x00\xe0\x94?\b\u066d\x89O\x81>\x8e!H\xc1`\xd2K5:\x8et\xb0\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4?\f\x83\xaa\xc5qybsN\\\xea\xea\xec\u04db(\xad\x06\xbe\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94?\x10\x80\x02\x82\u0477\xdd\u01cf\xa9-\x820\aN\x1b\xf6\xae\xae\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4?\x123qO M\xe9\xdeN\xe9m\a;6\x8d\x81\x97\x98\x9f\x89\x02\x17\xc4\x10t\xe6\xbb\x00\x00\u07d4?\x17:\xa6\xed\xf4i\u0445\xe5\x9b\xd2j\xe4#k\x92\xb4\xd8\xe1\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4?\x1b\xc4 \xc5<\x00,\x9e\x90\x03|D\xfej\x8e\xf4\xdd\xc9b\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4?#a\b\xee\xc7\"\x89\xba\u00e6\\\u0483\xf9^\x04\x1d\x14L\x8964\xbf9\xab\x98x\x80\x00\u07d4?-\xa0\x93\xbb\x16\xeb\x06O\x8b\xfa\x9e0\xb9)\xd1_\x8e\x1cL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?-\xd5]\xb7\xea\xb0\xeb\xeee\xb3>\xd8 ,\x1e\x99.\x95\x8b\x89,s\xc97t,P\x00\x00\u07d4?/8\x14\x91y|\xc5\xc0\u0502\x96\xc1O\xd0\xcd\x00\xcd\xfa-\x89+\x95\xbd\xcc9\xb6\x10\x00\x00\u07d4?0\u04fc\x9f`\"2\xbcrB\x88\xcaF\xcd\v\a\x88\xf7\x15\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4?<\x8ea\xe5`L\xef\x06\x05\xd46\xdd\"\xac\u0346\"\x17\xfc\x89Hz\x9a0E9D\x00\x00\u07d4??F\xb7\\\xab\xe3{\xfa\u0307`(\x1fCA\xca\u007fF=\x89 \xacD\x825\xfa\xe8\x80\x00\u07d4?G)c\x19x\x83\xbb\xdaZ\x9b}\xfc\xb2-\xb1\x14@\xad1\x89\x1a\x19d<\xb1\xef\xf0\x80\x00\u07d4?L\xd19\x9f\x8a4\xed\u06da\x17\xa4q\xfc\x92+Xp\xaa\xfc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4?U\x1b\xa9<\xd5F\x93\xc1\x83\xfb\x9a\xd6\re\xe1`\x96s\u0249lk\x93[\x8b\xbd@\x00\x00\xe0\x94?bzv\x9ej\x95\x0e\xb8p\x17\xa7\u035c\xa2\bq\x13h1\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4?m\xd3e\x0e\xe4(\u0737u\x95S\xb0\x17\xa9j\x94(j\u0249Hz\x9a0E9D\x00\x00\u07d4?tr7\x80o\xed?\x82\x8ahR\xeb\bg\xf7\x90'\xaf\x89\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4?u\xaea\xcc\x1d\x80Be;[\xae\xc4D>\x05\x1c^z\xbd\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4?\xb7\u0457\xb3\xbaO\xe0E\xef\xc2=P\xa1E\x85\xf5X\u0672\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94?\xbc\x1eE\x18\xd74\x00\xc6\xd0F5\x949\xfbh\xea\x1aI\xf4\x8a\x03y\v\xb8U\x13v@\x00\x00\u07d4?\xbe\xd6\xe7\xe0\u029c\x84\xfb\xe9\xeb\u03ddN\xf9\xbbIB\x81e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?\u043bGy\x8c\xf4L\u07feM3=\xe67\xdfJ\x00\xe4\\\x89\x05lUy\xf7\"\x14\x00\x00\xe0\x94?\xe4\x0f\xbd\x91\x9a\xad(\x18\xdf\x01\xeeM\xf4lF\x84*\xc59\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4?\xe8\x01\xe6\x135\xc5\x14\r\xc7\xed\xa2\xefR\x04F\nP\x120\x89lk\x93[\x8b\xbd@\x00\x00\u07d4?\xf86\xb6\xf5{\x90\x1bD\f0\xe4\xdb\xd0e\xcf7\xd3\u050c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4?\xfc\xb8p\xd4\x02=%]Qg\u0625\a\xce\xfc6kh\xba\x89#4^\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4@s\xfaI\xb8q\x17\u02d0\x8c\xf1\xabQ-\xa7T\xa92\xd4w\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4@\x8ai\xa4\a\x15\xe1\xb3\x13\xe15N`\b\x00\xa1\xe6\xdc\x02\xa5\x89\x01\u7e11\u0312T\x00\x00\u07d4@\x9b\xd7P\x85\x82\x1c\x1d\xe7\f\xdc;\x11\xff\xc3\xd9#\xc7@\x10\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4@\x9dZ\x96.\xde\uefa1x\x01\x8c\x0f8\xb9\u0372\x13\xf2\x89\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4@\xa31\x19[\x97s%\u00aa(\xfa/B\xcb%\xec<%<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4@\xa7\xf7(g\xa7\u0706w\v\x16+uW\xa44\xedP\xcc\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d4@\xab\n>\x83\xd0\u022c\x93f\x91\x05 \xea\xb1w+\xac;\x1a\x894\xf1\f-\xc0^|\x00\x00\u07d4@\xabf\xfe!>\xa5l:\xfb\x12\xc7[\xe3?\x8e2\xfd\b]\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94@\xadt\xbc\v\xce*E\xe5/6\xc3\u07bb\x1b:\xda\x1bv\x19\x8a\x01p\x16-\xe1\t\xc6X\x00\x00\u07d4@\u03c9\x05\x91\xea\u484f\x81*)T\xcb)_c3'\xe6\x89\x02\x9b\xf76\xfcY\x1a\x00\x00\u07d4@\u03d0\xef[v\x8c]\xa5\x85\x00,\xcb\xe6avP\xd8\xe87\x8963\x03\"\xd5#\x8c\x00\x00\xe0\x94@\xd4]\x9dv%\xd1QV\xc92\xb7q\xca{\x05'\x13\tX\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4@\xdb\x1b\xa5\x85\xce4S\x1e\xde\xc5IHI9\x13\x81\xe6\xcc\u04c9a\t=|,m8\x00\x00\xe0\x94@\xdfI^\xcf?\x8bL\xef*l\x18\x99W$\x8f\u813c+\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4@\xe0\xdb\xf3\xef\uf404\xea\x1c\xd7\xe5\x03\xf4\v;J\x84C\xf6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4@\xe2D\n\xe1B\u02006j\x12\xc6\xd4\x10/K\x844\xb6*\x8965\u026d\xc5\u07a0\x00\x00\u07d4@\xe3\u0083\xf7\xe2M\xe0A\f\x12\x1b\xee`\xa5`\u007f>)\xa6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94@\xeaPD\xb2\x04\xb20v\xb1\xa5\x80;\xf1\xd3\f\x0f\x88\x87\x1a\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94@\xed\xdbD\x8di\x0e\xd7.\x05\xc2%\xd3O\xc85\x0f\xa1\xe4\u014a\x01{x\x83\xc0i\x16`\x00\x00\xe0\x94@\xf4\xf4\xc0ls,\xd3[\x11\x9b\x89;\x12~}\x9d\aq\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4A\x01\x0f\u023a\xf8C}\x17\xa0Ci\x80\x9a\x16\x8a\x17\xcaV\xfb\x89\x05k\xc7^-c\x10\x00\x00\u07d4A\x03)\x96q\xd4gc\x97\x8f\xa4\xaa\x19\xee4\xb1\xfc\x95'\x84\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4A\x03<\x1bm\x05\xe1\u0289\xb0\x94\x8f\xc6DS\xfb\xe8z\xb2^\x89Hz\x9a0E9D\x00\x00\u07d4A\t\x8a\x81E#\x17\xc1\x9e>\xef\v\xd1#\xbb\xe1x\xe9\xe9\u0289\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4A\x16\x10\xb1x\xd5a}\xfa\xb94\u0493\xf5\x12\xa9>\\\x10\xe1\x89\t79SM(h\x00\x00\u07d4A\x1c\x83\x1c\xc6\xf4O\x19e\xecWW\xabN[<\xa4\xcf\xfd\x1f\x89\x17\n\x0fP@\xe5\x04\x00\x00\xe0\x94A*h\xf6\xc6EU\x9c\xc9w\xfcId\x04z \x1d\x1b\xb0\xe2\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4A?K\x02f\x9c\xcf\xf6\x80k\xc8&\xfc\xb7\xde\xca;\x0e\xa9\xbc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4AE\x99\t.\x87\x9a\xe2Sr\xa8MsZ\xf5\xc4\xe5\x10\xcdm\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4AHV\x12\xd04F\xecL\x05\xe5$NV?\x1c\xba\xe0\xf1\x97\x894\x95tD\xb8@\xe8\x00\x00\u07d4A]\tj\xb0b\x93\x18?<\x03=%\xf6\xcfqx\xac;\u01c9\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4Af\xfc\b\u0285\xf7f\xfd\xe81F\x0e\x9d\xc9<\x0e!\xaal\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Ag\x84\xaf`\x960\xb0p\u051a\x8b\xcd\x12#\\d(\xa4\b\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Ag\xcdH\xe73A\x8e\x8f\x99\xff\xd14\x12\x1cJJ\xb2x\u0109\xc5S%\xcat\x15\xe0\x00\x00\u07d4Al\x86\xb7 \x83\xd1\xf8\x90}\x84\xef\xd2\xd2\u05c3\xdf\xfa>\xfb\x89lj\xccg\u05f1\xd4\x00\x00\u07d4AsA\x9d\\\x9fc)U\x1d\xc4\xd3\xd0\u03ac\x1bp\x1b\x86\x9e\x89\x04\xc5>\xcd\xc1\x8a`\x00\x00\u07d4At\xfa\x1b\xc1*;q\x83\u02eb\xb7z\vYU{\xa5\xf1\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4Axj\x10\xd4G\xf4\x84\xd32D\u0337\xfa\u034bB{[\x8c\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Az<\u0454\x96S\nmB\x04\u00f5\xa1|\xe0\xf2\a\xb1\xa5\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4A~N&\x88\xb1\xfdf\xd8!R\x9eF\xedOB\xf8\xb3\xdb=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94A\x9aq\xa3l\x11\xd1\x05\xe0\xf2\xae\xf5\xa3\xe5\x98\a\x8e\x85\xc8\v\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94A\x9b\xdes\x16\xcc\x1e\u0495\u0205\xac\xe3B\u01db\xf7\xee3\xea\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4A\xa2\xf2\xe6\xec\xb8c\x94\xec\x0e3\x8c\x0f\xc9~\x9cU\x83\xde\u0489l\xee\x06\u077e\x15\xec\x00\x00\u07d4A\xa8\u0083\x00\x81\xb1\x02\xdfn\x011e|\a\xabc[T\u0389lj\xccg\u05f1\xd4\x00\x00\u07d4A\xa8\xe26\xa3\x0emc\xc1\xffdM\x13*\xa2\\\x89S~\x01\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4A\xa9\xa4\x04\xfc\x9f[\xfe\xe4\x8e\xc2e\xb1%#3\x8e)\xa8\xbf\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4A\xad6\x9fu\x8f\xef8\xa1\x9a\xa3\x14\x93y\x83,\x81\x8e\xf2\xa0\x8966\x9e\xd7t}&\x00\x00\u07d4A\xb2\xd3O\xde\v\x10)&+Ar\xc8\x1c\x15\x90@[\x03\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4A\xb2\xdb\u05dd\u069b\x86Ojp0'T\x19\u00dd>\xfd;\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4A\xc3\xc26u4\xd1;\xa2\xb3?\x18\\\xdb\xe6\xacC\xc2\xfa1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4A\u02d8\x96D_p\xa1\n\x14!R\x96\xda\xf6\x14\xe3,\xf4\u0549g\x8a\x93 b\xe4\x18\x00\x00\u07d4A\xcey\x95\t5\xcf\xf5[\xf7\x8eL\xce\xc2\xfec\x17\x85\u06d5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4A\u04f71\xa3&\xe7hX\xba\xa5\xf4\xbd\x89\xb5{6\x93#C\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\xe0\x94A\xe4\xa2\x02u\xe3\x9b\xdc\xef\xebe\\\x03\"tKvQ@\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4A\xed-\x8ep\x81H,\x91\x9f\xc2=\x8f\x00\x91\xb3\xc8,F\x85\x89F:\x1ev[\u05ca\x00\x00\xe0\x94A\xf2~tK\u049d\xe2\xb0Y\x8f\x02\xa0\xbb\x9f\x98\xe6\x81\ua90a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\u07d4A\xf4\x89\xa1\xect{\u009c>_\x9d\x8d\xb9xw\xd4\u0474\xe9\x89\a?u\u0460\x85\xba\x00\x00\u07d4B\x0f\xb8n}+Q@\x1f\xc5\xe8\xc7 \x15\xde\xcbN\xf8\xfc.\x8965\u026d\xc5\u07a0\x00\x00\u07d4B\x16\x84\xba\xa9\xc0\xb4\xb5\xf5S8\xe6\xf6\xe7\xc8\xe1F\xd4\x1c\xb7\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4B9\x96Y\xac\xa6\xa5\xa8c\xea\"E\xc93\xfe\x9a5\xb7\x88\x0e\x89n\xce2\xc2l\x82p\x00\x00\xe0\x94B;\xcaG\xab\xc0\fpW\xe3\xad4\xfc\xa6>7_\xbd\x8bJ\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4B<1\a\xf4\xba\xceANI\x9cd9\nQ\xf7F\x15\xca^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B<\xc4YL\xf4\xab\xb66\x8d\xe5\x9f\u04b1#\a4a!C\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94BD\xf13\x11X\xb9\xce&\xbb\xe0\xb9#k\x92\x03\xca5\x144\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794BQw\xebt\xad\n\x9d\x9aWR\"\x81G\xeemcV\xa6\u6239\x8b\xc8)\xa6\xf9\x00\x00\u07d4BW%\xc0\xf0\x8f\b\x11\xf5\xf0\x06\xee\xc9\x1c\\\\\x12k\x12\xae\x89\b!\xab\rD\x14\x98\x00\x00\xe0\x94BX\xfdf/\xc4\xce2\x95\xf0\xd4\xed\x8f{\xb1D\x96\x00\xa0\xa9\x8a\x01lE.\xd6\b\x8a\xd8\x00\x00\xe0\x94B\\\x18\x16\x86\x8fww\xcc+\xa6\xc6\u048c\x9e\x1eylR\xb3\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4B\\3\x8a\x13%\xe3\xa1W\x8e\xfa)\x9eW\u0646\xebGO\x81\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94BbY\xb0\xa7Vp\x1a\x8bf5(R!V\xc0(\x8f\x0f$\x8a\x02\x18\xae\x19k\x8dO0\x00\x00\u07d4Bm\x15\xf4\a\xa0\x115\xb1:kr\xf8\xf2R\v51\xe3\x02\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Box\xf7\r\xb2Y\xac\x854\x14[)4\xf4\xef\x10\x98\xb5\u0609\x13\x84\x00\xec\xa3d\xa0\x00\x00\u07d4Bs-\x8e\xf4\x9f\xfd\xa0K\x19x\x0f\xd3\xc1\x84i\xfb7A\x06\x89\x17\v\x00\xe5\u4a7e\x00\x00\u07d4Bt\x17\xbd\x16\xb1\xb3\xd2-\xbb\x90-\x8f\x96W\x01o$\xa6\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Btj\xee\xa1O'\xbe\xff\f\r\xa6BS\xf1\xe7\x97\x18\x90\xa0\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4B{F*\xb8NP\x91\xf4\x8aF\xeb\f\u0712\xdd\xcb&\xe0x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B~GQ\u00fa\xbex\xcf\xf8\x83\b\x86\xfe\xbc\x10\xf9\x90\x8dt\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94B~\xc6h\xac\x94\x04\xe8\x95\u0306\x15\x11\xd1b\nI\x12\xbe\x98\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4B\x80\xa5\x8f\x8b\xb1\v\x94@\u0794\xf4+OY! \x82\x01\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4B\x8a\x1e\xe0\xed3\x1dyR\u033e\x1cyt\xb2\x85+\u0453\x8a\x89w\xb7JN\x8d\xe5e\x00\x00\u0794B\x9c\x06\xb4\x87\xe8Tj\xbd\xfc\x95\x8a%\xa3\xf0\xfb\xa5?o\x00\x88\xbbdJ\xf5B\x19\x80\x00\xe0\x94B\xa9\x8b\xf1`'\xceX\x9cN\xd2\xc9X1\xe2rB\x05\x06N\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4B\xc6\xed\xc5\x15\xd3UW\x80\x8d\x13\xcdD\xdc\xc4@\v%\x04\xe4\x89\n\xba\x14\u015b\xa72\x00\x00\u07d4B\xce\xcf\u0492\x10y\xc2\xd7\xdf?\b\xb0z\xa3\xbe\xee^!\x9a\x8965\u026d\xc5\u07a0\x00\x00\u07d4B\u04669\x9b0\x16\xa8Y\u007f\x8bd\t'\xb8\xaf\xbc\xe4\xb2\x15\x89\xa1\x8b\xce\xc3H\x88\x10\x00\x00\u07d4B\xd3I@\xed\xd2\xe7\x00]F\xe2\x18\x8eL\xfe\u0383\x11\xd7M\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4B\u04e5\xa9\x01\xf2\xf6\xbd\x93V\xf1\x12\xa7\x01\x80\xe5\xa1U\v`\x892$\xf4'#\xd4T\x00\x00\u07d4B\u05b2c\xd9\xe9\xf4\x11lA\x14$\xfc\x99Ux;\xa1\xc5\x1b\x81\x0f\xc4g\u057aM\xeaB\xf7\xa9\x88^i\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94C>\xb9J3\x90\x86\xed\x12\u067d\xe9\xcd\x1dE\x86\x03\xc9}\u058a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4CI\"Zb\xf7\n\xeaH\n\x02\x99\x15\xa0\x1eSy\xe6O\xa5\x89\x8c\xd6~#4\xc0\xd8\x00\x00\u07d4CT\"\x1eb\xdc\t\xe6@d6\x16:\x18^\xf0m\x11J\x81\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94CTC\xb8\x1d\xfd\xb9\xbd\x8cg\x87\xbc%\x18\xe2\xd4~W\xc1_\x8a\x01C\x8d\x93\x97\x88\x1e\xf2\x00\x00\u07d4Ca\u0504o\xaf\xb3w\xb6\xc0\xeeI\xa5\x96\xa7\x8d\xdf5\x16\xa3\x89\xc2\x12z\xf8X\xdap\x00\x00\xe0\x94Cd0\x9a\x9f\xa0p\x95`\x0fy\xed\xc6Q \xcd\xcd#\xdcd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Cg\xaeK\f\xe9d\xf4\xa5J\xfdK\\6\x84\x96\xdb\x16\x9e\x9a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Ct\x89(\xe8\xc3\xecD6\xa1\u0412\xfb\xe4:\xc7I\xbe\x12Q\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4Cv{\xf7\xfd*\xf9[r\xe91-\xa9D<\xb1h\x8eCC\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94Cy\x838\x8a\xb5\x9aO\xfc!_\x8e\x82iF\x10)\xc3\xf1\xc1\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4C\x89\x8cI\xa3MP\x9b\xfe\xd4\xf7`A\xee\x91\xca\xf3\xaaj\xa5\x89\x10CV\x1a\x88)0\x00\x00\u07d4C\x8c/T\xff\x8eb\x9b\xab6\xb1D+v\v\x12\xa8\x8f\x02\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\x98b\x8e\xa6c-9>\x92\x9c\xbd\x92\x84d\xc5h\xaaJ\f\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4C\x9d//Q\x10\xa4\u054b\x17W\x93P\x15@\x87@\xfe\xc7\xf8\x89\u03e5\xc5\x15\x0fL\x88\x80\x00\u07d4C\x9d\xee?vy\xff\x100s?\x93@\xc0\x96hkI9\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xb0y\xba\xf0ry\x99\xe6k\xf7C\u057c\xbfwl;\t\"\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xbc-M\xdc\xd6X;\xe2\u01fc\tK(\xfbr\xe6+\xa8;\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xc7\xeb\u0173\xe7\xaf\x16\xf4}\xc5az\xb1\x0e\x0f9\xb4\xaf\xbb\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4C\u02d6R\x81\x8coMg\x96\xb0\xe8\x94\t0ly\xdbcI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4C\xcc\b\xd0s*\xa5\x8a\xde\xf7a\x9b\xedFU\x8a\xd7wAs\x89\xf0\xe7\u0730\x12*\x8f\x00\x00\xe0\x94C\u0567\x1c\xe8\xb8\xf8\xae\x02\xb2\xea\xf8\xea\xf2\xca(@\xb9?\xb6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794C\xdb\u007f\xf9Z\bm(\ubff8/\xb8\xfb_#\n^\xbc\u0348\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4C\xe7\xec\x84cX\xd7\xd0\xf97\xad\x1c5\v\xa0i\u05ffr\xbf\x89\x06p\xaeb\x92\x14h\x00\x00\u07d4C\xf1o\x1eu\xc3\xc0j\x94x\xe8\u0157\xa4\n<\xb0\xbf\x04\u0309\x9d\xf7\u07e8\xf7`H\x00\x00\u07d4C\xf4p\xede\x9e)\x91\xc3u\x95~]\xde\u017d\x1d8\"1\x89\x05k\xc7^-c\x10\x00\x00\u07d4C\xf7\xe8n8\x1e\xc5\x1e\u0110m\x14v\u02e9z=\xb5\x84\xe4\x8965\u026d\xc5\u07a0\x00\x00\u07d4C\xff8t>\xd0\xcdC0\x8c\x06e\t\u030e~r\xc8b\xaa\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94C\xff\x88S\xe9\x8e\xd8@k\x95\x00\n\u0684\x83b\u05a09*\x8a\x04\xae\v\x1cM.\x84\xd0\x00\x00\u07d4D\t\x88f\xa6\x9bh\xc0\xb6\xbc\x16\x82)\xb9`5\x87\x05\x89g\x89\n1\x06+\xee\xedp\x00\x00\u07d4D\x19\xaca\x8d]\xea|\xdc`w o\xb0}\xbd\xd7\x1c\x17\x02\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4D\x1aR\x00\x16a\xfa\xc7\x18\xb2\u05f3Q\xb7\xc6\xfbR\x1az\xfd\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94D\x1a\u0282c\x13$\xac\xbf\xa2F\x8b\xda2[\xbdxG{\xbf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4D\x1f7\xe8\xa0)\xfd\x02H/(\x9cI\xb5\xd0m\x00\xe4\b\xa4\x89\x12\x11\xec\xb5m\x13H\x80\x00\u07d4D \xaa5F[\xe6\x17\xad$\x98\xf3p\xde\n<\xc4\xd20\xaf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4D#/\xf6m\xda\xd1\xfd\x84\x12f8\x006\xaf\xd7\xcf}\u007fB\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4D%\rGn\x06$\x84\xe9\b\n9g\xbf:Js*\xd7?\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4D)\xa2\x9f\xee\x19\x84Pg,\f\x1d\a1b%\v\xecdt\x896*\xaf\x82\x02\xf2P\x00\x00\u07d4D5RS\xb2wH\xe3\xf3O\xe9\xca\xe1\xfbq\x8c\x8f$\x95)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4D8\xe8\x80\xcb'f\xb0\xc1\u03ae\xc9\xd2A\x8f\u03b9R\xa0D\x89\a?\xa0s\x90?\b\x00\x00\u07d4DL\xafy\xb7\x138\ue6a7\xc73\xb0*\u02a7\xdc\x02YH\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4D\\\xb8\xde^=\xf5 \xb4\x99\xef\u0240\xf5+\xff@\xf5\\v\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Dj\x809\xce\u03dd\xceHy\xcb\xca\xf3I;\xf5E\xa8\x86\x10\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4Dt)\x9d\x0e\xe0\x90\u0710x\x9a\x14\x86H\x9c=\rd^m\x8965\u026d\xc5\u07a0\x00\x00\u07d4D\x8b\xf4\x10\xad\x9b\xbc/\xec\xc4P\x8d\x87\xa7\xfc.K\x85a\xad\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4D\x90\x1e\r\x0e\b\xac=^\x95\xb8\xec\x9d^\x0f\xf5\xf1.\x03\x93\x89\x16\xa1\xf9\xf5\xfd}\x96\x00\x00\xe0\x94D\x93\x12<\x02\x1e\xce;3\xb1\xa4R\xc9&\x8d\xe1@\a\xf9\u04ca\x01je\x02\xf1Z\x1eT\x00\x00\xe0\x94D\x9a\xc4\xfb\xe3\x83\xe3g8\x85^6JW\xf4q\xb2\xbf\xa11\x8a)\xb7d2\xb9DQ \x00\x00\u07d4D\xa0\x1f\xb0J\xc0\xdb,\xce]\xbe(\x1e\x1cF\xe2\x8b9\xd8x\x89lj\xccg\u05f1\xd4\x00\x00\u07d4D\xa6=\x18BE\x87\xb9\xb3\a\xbf\xc3\xc3d\xae\x10\xcd\x04\xc7\x13\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94D\xa8\x98\x9e20\x81!\xf7$f\x97\x8d\xb3\x95\xd1\xf7l:K\x8a\x01\x88P)\x9fB\xb0j\x00\x00\u07d4D\xc1\x11\v\x18\x87\x0e\xc8\x11x\xd9=!X8\xc5Q\u050ed\x89\n\xd6\xf9\x85\x93\xbd\x8f\x00\x00\u07d4D\xc1Ge\x12|\xde\x11\xfa\xb4l],\xf4\u0532\x89\x00#\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94D\xc5N\xaa\x8a\xc9@\xf9\xe8\x0f\x1et\xe8/\xc1O\x16v\x85j\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4D\xcdwSZ\x89?\xa7\xc4\xd5\xeb:$\x0ey\u0419\xa7--\x89,s\xc97t,P\x00\x00\u07d4D\u07faP\xb8)\xbe\xcc_O\x14\u0470J\xab3 \xa2\x95\xe5\x8965\u026d\xc5\u07a0\x00\x00\u07d4D\xe2\xfd\xc6y\xe6\xbe\xe0\x1e\x93\xefJ:\xb1\xbc\xce\x01*\xbc|\x89\x16=\x19I\x00\xc5E\x80\x00\xe0\x94D\xf6/*\xaa\xbc)\xad:k\x04\xe1\xffo\x9c\xe4R\xd1\xc1@\x8a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4D\xff\xf3{\xe0\x1a8\x88\u04f8\xb8\u1200\xa7\xdd\xef\xee\xea\u04c9\x0e\f[\xfc}\xae\x9a\x80\x00\u07d4E\x06\xfe\x19\xfaK\x00k\xaa9\x84R\x9d\x85\x16\xdb++P\xab\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\x1b6\x99G[\xed]y\x05\xf8\x90Z\xa3Eo\x1e\u05c8\xfc\x89\x8a\xc7#\x04\x89\xe8\x00\x00\x00\u0794E\x1bpp%\x9b\u06e2q\x00\xe3n#B\x8aS\xdf\xe3\x04\u9239\x8b\xc8)\xa6\xf9\x00\x00\u07d4E'+\x8fb\xe9\xf9\xfa\x8c\xe0D \u1ba3\xeb\xa9hn\xac\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94E+d\u06ce\xf7\xd6\u07c7\u01c8c\x9c\"\x90\xbe\x84\x82\xd5u\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4E>5\x9a3\x97\x94LZ'Z\xb1\xa2\xf7\n^Z?i\x89\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4EI\xb1Yy%_~e\xe9\x9b\rV\x04\u06d8\xdf\xca\u023f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4EKa\xb3D\xc0\xef\x96Qy#\x81U\xf2w\u00c2\x9d\v8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94EO\x01A\xd7!\xd3<\xbd\xc4\x10\x18\xbd\x01\x11\x9a\xa4xH\x18\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4ES3\x90\xe3@\xfe\r\xe3\xb3\xcf_\xb9\xfc\x8e\xa5R\xe2\x9eb\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4ES\x96\xa4\xbb\u067a\u8bdf\xb7\xc4\xd6MG\x1d\xb9\xc2E\x05\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4E[\x92\x96\x92\x1at\xd1\xfcAa\u007fC\xb80>o>\xd7l\x89\u3bb5sr@\xa0\x00\x00\u07d4E\\\xb8\xee9\xff\xbcu#1\xe5\xae\xfcX\x8e\xf0\xeeY4T\x8965F:x\r\xef\x80\x00\u07d4Ej\u0b24\x8e\xbc\xfa\xe1f\x06\x02PR_c\x96^v\x0f\x89\x10CV\x1a\x88)0\x00\x00\u07d4Eo\x8dtf\x82\xb2$g\x93I\x06M\x1b6\x8c|\x05\xb1v\x89\u0213\u041c\x8fQP\x00\x00\u07d4Ep)\xc4i\xc4T\x8d\x16\x8c\xec>e\x87.D(\xd4+g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Eq\xdeg+\x99\x04\xba\xd8t6\x92\xc2\x1cO\xdc\xeaL.\x01\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Ex\x1b\xbew\x14\xa1\xc8\xf7;\x1cty!\xdfO\x84'\x8bp\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E{\xce\xf3}\xd3\xd6\v-\xd0\x19\xe3\xfea\xd4k?\x1erR\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94E\x8e<\u025e\x94xD\xa1\x8ejB\x91\x8f\xef~\u007f_^\xb3\x8a\a\xb5?y\xe8\x88\xda\xc0\x00\x00\u07d4E\x93\x93\xd6:\x06>\xf3r\x1e\x16\xbd\x9f\xdeE\ue77dw\xfb\x89j\xba\u05a3\xc1S\x05\x00\x00\u07d4E\xa5p\xdc\xc2\t\f\x86\xa6\xb3\xea)\xa6\bc\xdd\xe4\x1f\x13\xb5\x89\f\x9a\x95\xee)\x86R\x00\x00\u07d4E\xa8 \xa0g/\x17\xdct\xa0\x81\x12\xbcd?\xd1\x16w6\u00c9\n\xd6\xc4;(\x15\xed\x80\x00\u07d4E\xb4q\x05\xfeB\xc4q-\xcen*!\xc0[\xff\xd5\xeaG\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\xbb\x82\x96R\u063f\xb5\x8b\x85'\xf0\xec\xb6!\u009e!.\u00c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\xc0\u045f\v\x8e\x05O\x9e\x8986\xd5\xec\xaey\x01\xaf(\x12\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4E\xc4\xec\xb4\xee\x89\x1e\xa9\x84\xa7\xc5\xce\xfd\x8d\xfb\x001\v(P\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4E\u028d\x95f\b\xf9\xe0\n/\x99t\x02\x86@\x88\x84ef\x8f\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\u0298b\x00;N@\xa3\x17\x1f\xb5\xca\xfa\x90(\xca\xc8\xde\x19\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4E\xd1\xc9\xee\xdf|\xabA\xa7y\x05{y9_T(\xd8\x05(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4E\u0535M7\xa8\xcfY\x98!#_\x06/\xa9\xd1p\xed\u8909\x11\x90g;_\u0690\x00\x00\xe0\x94E\xdb\x03\xbc\xcf\u05a5\xf4\xd0&k\x82\xa2*6\x87\x92\xc7}\x83\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4E\xe3\xa9>r\x14J\u0686\f\xbcV\xff\x85\x14Z\xda8\xc6\u0689WG=\x05\u06ba\xe8\x00\x00\u07d4E\u6378\u06fa\xba_\xc2\xcb3|b\xbc\xd0\xd6\x1b\x05\x91\x89\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94E\u6379L}\n\xb7\xacA\x85zq\xd6qG\x87\x0fNq\x8aT\xb4\v\x1f\x85+\xda\x00\x00\x00\u07d4E\xf4\xfc`\xf0\x8e\xac\xa1\x05\x98\xf03c)\x80\x1e<\x92\xcbF\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4F\rSU\xb2\xce\xebnb\x10}\x81\xe5\x12p\xb2k\xf4V \x89l\xb7\xe7Hg\xd5\xe6\x00\x00\xe0\x94F\"O2\xf4\xec\xe5\u0206p\x90\xd4@\x9dU\xe5\v\x18C-\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4F'\xc6\x06\x84&q\xab\u0782\x95\xee]\xd9L\u007fT\x954\xf4\x89\x0f\x89_\xbd\x872\xf4\x00\x00\u07d4F+g\x8bQ\xb5\x84\xf3\xedz\xda\a\v\\\u065c\v\xf7\xb8\u007f\x89\x05k\xc7^-c\x10\x00\x00\u07d4FM\x9c\x89\xcc\xe4\x84\xdf\x00\x02w\x19\x8e\xd8\a_\xa65r\u0449\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4FPNj!Z\xc8;\xcc\xf9V\xbe\xfc\x82\xabZg\x93q\u0209\x1c!(\x05\u00b4\xa5\x00\x00\xe0\x94FQ\xdcB\x0e\b\xc3);'\xd2Ix\x90\xebP\":\xe2\xf4\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4FS\x1e\x8b\x1b\xde\t\u007f\u07c4\x9dm\x11\x98\x85`\x8a\x00\x8d\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4Fb\x92\xf0\xe8\rC\xa7\x87t'u\x90\xa9\xebE\x96\x12\x14\xf4\x894\x95tD\xb8@\xe8\x00\x00\xe0\x94Fb\xa1v^\xe9!\x84-\u0708\x89\x8d\x1d\xc8bu\x97\xbd~\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Fe\xe4s\x96\xc7\u06d7\xeb*\x03\xd9\bc\xd5\u053a1\x9a\x94\x89 \x86\xac5\x10R`\x00\x00\u07d4Fo\xdak\x9bX\xc5S'P0j\x10\xa2\xa8\xc7h\x10;\a\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4Fq$\xae\u007fE/&\xb3\xd5t\xf6\b\x88\x94\xfa]\x1c\xfb;\x89\x92^\x06\xee\xc9r\xb0\x00\x00\u0794Fr*6\xa0\x1e\x84\x1d\x03\xf7\x80\x93^\x91}\x85\u0566z\xbd\x88\xce\xc7o\x0eqR\x00\x00\u07d4Fw\x9aVV\xff\x00\xd7>\xac:\xd0\u00cbl\x850\x94\xfb@\x89\f\x82S\xc9lj\xf0\x00\x00\u07d4Fw\xb0N\x03C\xa3!1\xfdj\xbb9\xb1\xb6\x15k\xba=[\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4F}Y\x88$\x9ahaG\x16e\x98@\xed\n\xe6\xf6\xf4W\xbc\x89\x15\x01\xa4\x8c\xef\xdf\xde\x00\x00\u07d4F~\x0e\xd5O;v\xae\x066\x17n\aB\b\x15\xa0!sn\x89lk\x93[\x8b\xbd@\x00\x00\u07d4F~\xa1\x04E\x82~\xf1\xe5\x02\xda\xf7k\x92\x8a \x9e\r@2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94F\u007f\xbfAD\x16\x00u\u007f\xe1X0\xc8\xcd_O\xfb\xbb\xd5`\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94F\x93Xp\x932\xc8+\x88~ \xbc\xdd\xd0\"\x0f\x8e\u06e7\u040a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4F\x97\xba\xaf\x9c\xcb`?\xd3\x040h\x9dCTE\xe9\u024b\xf5\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4F\xa3\v\x8a\x80\x891!tE\xc3\xf5\xa9>\x88,\x03E\xb4&\x89\r\x8d\xb5\xeb\u05f2c\x80\x00\u07d4F\xa40\xa2\u0528\x94\xa0\u062a?\xea\xc6\x156\x14\x15\xc3\xf8\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4F\xaaP\x18pg~\u007f\nPHv\xb4\xe8\x80\x1a\n\xd0\x1cF\x89+^:\xf1k\x18\x80\x00\x00\u07d4F\xbf\u0172\a\xeb \x13\xe2\xe6\x0fw_\xec\xd7\x18\x10\u0159\f\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4F\xc1\xaa\"D\xb9\u0229W\u028f\xacC\x1b\x05\x95\xa3\xb8h$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4F\xd8\x061(B\x03\xf6(\x8e\xcdNWX\xbb\x9dA\xd0]\xbe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\n\xc5\xd1\xf3\xef\xe2\x8f8\x02\xaf\x92[W\x1ec\x86\x8b9}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\x10\x10\xdaI/@\x18\x83;\b\x8d\x98r\x90\x1e\x06\x12\x91t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4G\x12T\x02e\xcb\xee\u00c4p\"\u015f\x1b1\x8dC@\n\x9e\x89\xbd\xbcA\xe04\x8b0\x00\x00\xe0\x94G\x14\u03e4\xf4k\u05bdps}u\x87\x81\x97\xe0\x8f\x88\xe61\x8a\x02\u007f>\u07f3Nn@\x00\x00\u07d4G H\xcc`\x9a\xeb$!e\uaa87\x05\x85\f\xf3\x12]\xe0\x8965\u026d\xc5\u07a0\x00\x00\u07d4G!\x92)\xe8\xcdVe\x9ae\u00a9C\xe2\u075a\x8fK\xfd\x89\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4G7\xd0B\xdcj\xe7>\xc7:\xe2Qz\u03a2\xfd\xd9d\x87\u014965\u026d\xc5\u07a0\x00\x00\u07d4GAX\xa1\xa9\xdci<\x13?e\xe4{\\:\xe2\xf7s\xa8o\x89\n\xdaUGK\x814\x00\x00\u07d4GE\xab\x18\x1a6\xaa\x8c\xbf\"\x89\xd0\xc4Qe\xbc~\xbe#\x81\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4GPf\xf9\xad&eQ\x96\xd5SS'\xbb\xeb\x9by)\xcb\x04\x89\xa4\xccy\x95c\u00c0\x00\x00\xe0\x94GR!\x8eT\xdeB?\x86\xc0P\x193\x91z\xea\b\xc8\xfe\u054a\x04<3\xc1\x93ud\x80\x00\x00\u07d4GZa\x93W-JNY\u05fe\t\u02d6\r\u074cS\x0e/\x89$,\xf7\x8c\xdf\a\xff\x80\x00\u07d4Gd\x8b\xed\x01\xf3\xcd2I\bNc]\x14\u06a9\xe7\xec<\x8a\x89\n\x84Jt$\xd9\xc8\x00\x00\u07d4Gh\x84\x10\xff%\xd6T\xd7.\xb2\xbc\x06\xe4\xad$\xf83\xb0\x94\x89\b\xb2\x8da\xf3\u04ec\x00\x00\u07d4GkU\x99\b\x9a?\xb6\xf2\x9clr\xe4\x9b.G@\ua00d\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4Gs\x0f_\x8e\xbf\x89\xacr\xef\x80\xe4l\x12\x19P8\xec\xdcI\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94G{$\xee\u80deO\u045d\x12P\xbd\vfEyJa\u028a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4G\x81\xa1\nM\xf5\uef02\xf4\xcf\xe1\a\xba\x1d\x8av@\xbdf\x89a\t=|,m8\x00\x00\u07d4G\x88Z\xba\xbe\xdfM\x92\x8e\x1c\x88\x83\xa6a\x9cl(\x11\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94G\xe2]\xf8\x82%8\xa8Yk(\xc67\x89kM\x14<5\x1d\x8a\x11\v\xe9\xeb$\xb8\x81P\x00\x00\u07d4G\xf4ik\xd4b\xb2\r\xa0\x9f\xb8>\xd2\x03\x98\x18\xd7v%\xb3\x89\b\x13\xcaV\x90m4\x00\x00\u07d4G\xfe\xf5\x85\x84FRH\xa0\x81\r`F>\xe9>Zn\xe8\u04c9\x0fX\xcd>\x12i\x16\x00\x00\u07d4G\xffo\xebC! `\xbb\x15\x03\u05e3\x97\xfc\b\xf4\xe7\x03R\x89lk\x93[\x8b\xbd@\x00\x00\u07d4G\xff\xf4,g\x85Q\xd1A\xebu\xa6\xee9\x81\x17\xdf>J\x8d\x89\x05k\xea\xe5\x1f\xd2\xd1\x00\x00\u07d4H\x01\x0e\xf3\xb8\xe9^?0\x8f0\xa8\xcb\u007fN\xb4\xbf`\xd9e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4H\n\xf5 v\x00\x9c\xa77\x81\xb7\x0eC\xb9Y\x16\xa6\"\x03\xab\x892\x19r\xf4\b=\x87\x80\x00\u07d4H\x0f1\xb9\x891\x1eA$\u01a7F_ZD\tM6\xf9\u04097\x90\xbb\x85Q7d\x00\x00\xe0\x94H\x11\x15)j\xb7\xdbRI/\xf7\xb6G\xd63)\xfb\\\xbck\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4H\x1e:\x91\xbf\xdc/\x1c\x84(\xa0\x11\x9d\x03\xa4\x16\x01A~\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4H(\xe4\xcb\xe3N\x15\x10\xaf\xb7,+\ueb0aE\x13\xea\xeb\u0649\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94H)\x82\xac\x1f\x1cm\x17!\xfe\xec\u0679\xc9l\xd9I\x80PU\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4H0,1\x1e\xf8\xe5\xdcfAX\xddX<\x81\x19Mn\rX\x89\xb6gl\xe0\xbc\xcb\\\x00\x00\u07d4H;\xa9\x904\xe9\x00\xe3\xae\xdfaI\x9d;+\xce9\xbe\xb7\xaa\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4HT\x8bK\xa6+\xcb/\r4\xa8\x8d\u019ah\x0eS\x9c\xf0F\x89\x05l\xf1\u02fbt2\x00\x00\u07d4Hc\x84\x979&Zc\xb0\xa2\xbf#jY\x13\xe6\xf9Y\xce\x15\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4He\x9d\x8f\x8c\x9a/\xd4Oh\u06a5]#\xa6\b\xfb\xe5\x00\u0709lk\x93[\x8b\xbd@\x00\x00\xe0\x94Hf\x9e\xb5\xa8\x01\u0637_\xb6\xaaX\xc3E\x1bpX\xc2C\xbf\x8a\x06\x8dB\xc18\u06b9\xf0\x00\x00\u07d4Hjl\x85\x83\xa8D\x84\xe3\xdfC\xa1#\x83\u007f\x8c~#\x17\u0409\x11\x87\xc5q\xab\x80E\x00\x00\u07d4Hz\xdf}p\xa6t\x0f\x8dQ\xcb\xddh\xbb?\x91\u0125\xceh\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4H~\x10\x85\x02\xb0\xb1\x89\uf70cm\xa4\xd0\xdbba\xee\xc6\xc0\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94H\x88\xfb%\xcdP\u06f9\xe0H\xf4\x1c\xa4}x\xb7\x8a'\xc7\u064a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u0794H\x934\u00b6\x95\xc8\xee\a\x94\xbd\x86B\x17\xfb\x9f\xd8\xf8\xb15\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4H\xa3\r\xe1\xc9\x19\xd3\xfd1\x80\xe9}_+*\x9d\xbd\x96M-\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4H\xbf\x14\u05f1\xfc\x84\xeb\xf3\xc9k\xe1/{\xce\x01\xaai\xb0>\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4H\xc2\ue465\aV\xd8\u039a\xbe\xebu\x89\xd2,o\xee]\xfb\x89\xae\x8ez\v\xb5u\xd0\x00\x00\u07d4H\xc5\u0197\v\x91a\xbb\x1c{z\xdf\xed\x9c\xde\u078a\x1b\xa8d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94H\xd2CKz}\xbb\xff\b\";c\x87\xb0]\xa2\xe5\t1&\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4H\xd4\xf2F\x8f\x96?\u05da\x00a\x98\xbbg\x89]-Z\xa4\u04c9K\xe4\xe7&{j\xe0\x00\x00\u07d4H\xe0\xcb\xd6\u007f\x18\xac\xdbzb\x91\xe1%M\xb3.\trs\u007f\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4H\xf6\n5HO\xe7y+\u030a{c\x93\xd0\u0761\xf6\xb7\x17\x89\xc3(\t>a\xee@\x00\x00\u07d4H\xf8\x83\xe5g\xb46\xa2{\xb5\xa3\x12M\xbc\x84\xde\xc7u\xa8\x00\x89)\xd7n\x86\x9d\u0340\x00\x00\xe0\x94I\x01E\xaf\xa8\xb5E\"\xbb!\xf3R\xf0m\xa5\xa7\x88\xfa\x8f\x1d\x8a\x01\xf4lb\x90\x1a\x03\xfb\x00\x00\u07d4I\t\xb3\x19\x98\xea\xd4\x14\xb8\xfb\x0e\x84k\xd5\xcb\xde995\xbe\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4I\x12\xd9\x02\x93\x16v\xff9\xfc4\xfe<<\xc8\xfb!\x82\xfaz\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4I\x13o\xe6\xe2\x8btS\xfc\xb1kk\xbb\u9aac\xba\x837\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94I\x15a\u06cbo\xaf\xb9\x00~b\xd0P\u0082\xe9,Kk\u020a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4I\x18]\xd7\xc262\xf4lu\x94s\ubb96`\b\xcd5\x98\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4I,\xb5\xf8a\xb1\x87\xf9\xdf!\xcdD\x85\xbe\xd9\vP\xff\xe2-\x89\x1b\x19\xe5\vD\x97|\x00\x00\u07d4I-\xe4j\xaf\x8f\x1dp\x8dY\u05da\xf1\xd0:\xd2\xcb`\x90/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I.p\xf0M\x18@\x8c\xb4\x1e%`70Pk5\xa2\x87k\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4I:g\xfe#\xde\xccc\xb1\r\xdau\xf3(v\x95\xa8\x1b\u056b\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4I=H\xbd\xa0\x15\xa9\xbf\xcf\x16\x03\x93n\xabh\x02L\xe5Q\xe0\x89\x018\xa3\x88\xa4<\x00\x00\x00\xe0\x94IBV\xe9\x9b\x0f\x9c\xd6\xe5\xeb\xca8\x99\x862R\x90\x01e\u020a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4IM\xecM^\xe8\x8a'q\xa8\x15\xf1\xeerd\x94/\xb5\x8b(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I[d\x1b\x1c\u07a3b\u00f4\u02fd\x0f\\\xc5\v\x1e\x17k\x9c\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94Ih\xa2\xce\xdbEuU\xa19)Z\xea(wnT\x00<\x87\x8a\x02#\x1a\xef\u0266b\x8f\x00\x00\u07d4Im6U4S\n_\xc1W|\nRA\u02c8\xc4\xdapr\x89a\t=|,m8\x00\x00\xe0\x94In1\x95\x92\xb3A\xea\xcc\xd7x\u0767\xc8\x19mT\xca\xc7u\x8a\x01\xf5q\x89\x87fKH\x00\x00\u07d4IoXC\xf6\xd2L\u064d%^L#\xd1\xe1\xf0#\"uE\x89_\x17\x9f\u0526\xee\t\x80\x00\xe0\x94Ip\u04ec\xf7+[\x1f2\xa7\x00<\xf1\x02\xc6N\xe0TyA\x8a\x1d\xa5jK\b5\xbf\x80\x00\x00\u07d4Iw\xa7\x93\x9d\t9h\x94U\xce&9\xd0\xeeZL\xd9\x10\xed\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4Iy\x19N\xc9\xe9}\xb9\xbe\xe84;|w\xd9\xd7\xf3\xf1\u071f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Iy4c\xe1h\x10\x83\u05ab\xd6\xe7%\u057b\xa7E\xdc\xcd\xe8\x89\x1d\x98\xe9LNG\x1f\x00\x00\u07d4I\x81\xc5\xfff\xccN\x96\x80%\x1f\xc4\xcd/\xf9\a\xcb2xe\x89(\xa8WBTf\xf8\x00\x00\u07d4I\x89\u007f\xe92\xbb\xb3\x15L\x95\u04fc\xe6\xd9;ms)\x04\u0749\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4I\x89\xe1\xab^|\xd0\aF\xb3\x93\x8e\xf0\xf0\xd0d\xa2\x02[\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4I\x8a\xbd\xeb\x14\xc2k{r4\xd7\x0f\u03ae\xf3a\xa7m\xffr\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4I\xa6E\xe0f}\xfd{2\xd0u\xcc$g\u074ch\t\a\u0109\a\x06\x01\x95\x8f\u02dc\x00\x00\xe0\x94I\xb7N\x16\x92e\xf0\x1a\x89\xecL\x90r\u0164\xcdr\xe4\xe85\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4I\xbd\xbc{\xa5\xab\xeb\xb68\x9e\x91\xa3(R \xd3E\x1b\xd2S\x8965\u026d\xc5\u07a0\x00\x00\u07d4I\xc9A\xe0\xe5\x01\x87&\xb7)\x0f\xc4s\xb4q\xd4\x1d\xae\x80\u0449\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94I\xc9w\x1f\xca\x19\u0579\xd2E\u0211\xf8\x15\x8f\xe4\x9fG\xa0b\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4I\xcf\x1eT\xbe61\x06\xb9 r\x9d-\v\xa4o\bg\x98\x9a\x89\x0e\x87?D\x13<\xb0\x00\x00\u07d4I\xd2\u008e\xe9\xbcT^\xaa\xf7\xfd\x14\xc2|@s\xb4\xbb_\x1a\x89O\xe9\xb8\x06\xb4\r\xaf\x00\x00\u07d4I\xdd\xee\x90.\x1d\f\x99\u0471\x1a\xf3\u030a\x96\xf7\x8eM\xcf\x1a\x89\n\u03a5\xe4\xc1\x8cS\x00\x00\u07d4I\xf0(9[Z\x86\xc9\xe0\u007fwxc\x0eL.=7:w\x89\x06\xa7JP8\u06d1\x80\x00\xe0\x94J\x19 5\xe2a\x9b$\xb0p\x9dVY\x0e\x91\x83\xcc\xf2\xc1\u064a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4J@S\xb3\x1d\x0e\xe5\u06ef\xb1\xd0k\u05ec\u007f\xf3\",G\u0589K\xe4\xe7&{j\xe0\x00\x00\u07d4JC\x01p\x15-\xe5\x17&3\u0742b\xd1\a\xa0\xaf\xd9j\x0f\x89\xabM\xcf9\x9a:`\x00\x00\u07d4JG\xfc>\x17\u007fVz\x1e8\x93\xe0\x00\xe3k\xba#R\n\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4JR\xba\xd2\x03W\"\x8f\xaa\x1e\x99k\xedy\f\x93gK\xa7\u0409Hz\x9a0E9D\x00\x00\u07d4JS\xdc\xdbV\xceL\xdc\xe9\xf8.\xc0\xeb\x13\xd6sR\xe7\u020b\x89\u3bb5sr@\xa0\x00\x00\u07d4J_\xae;\x03r\xc20\xc1%\xd6\xd4p\x14\x037\xab\x91VV\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4Jq\x90a\xf5(T\x95\xb3{\x9d~\xf8\xa5\x1b\a\xd6\u6b2c\x89\n\xd4\xc81j\v\f\x00\x00\u07d4Js8\x92\x98\x03\x1b\x88\x16\u0329FB\x1c\x19\x9e\x18\xb3C\u0589\"8h\xb8y\x14o\x00\x00\u07d4Js]\"G\x927m3\x13g\xc0\x93\xd3\x1c\x87\x944\x15\x82\x89f\xff\xcb\xfd^Z0\x00\x00\u07d4Jt\x94\xcc\xe4HU\u0300X(B\xbe\x95\x8a\r\x1c\x00r\ue242\x1a\xb0\xd4AI\x80\x00\x00\u07d4Ju\xc3\xd4\xfao\u033d]\u0567\x03\xc1Sy\xa1\xe7\x83\u9dc9b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94J\x81\xab\xe4\x98L|k\xefc\u0598 \xe5WC\xc6\x1f \x1c\x8a\x03d\x01\x00N\x9a\xa3G\x00\x00\u07d4J\x82iO\xa2\x9d\x9e!2\x02\xa1\xa2\t(]\xf6\xe7E\xc2\t\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4J\x83\\%\x82LG\xec\xbf\u01d49\xbf?\\4\x81\xaau\u0349K\xe4\xe7&{j\xe0\x00\x00\u07d4J\x91\x802C\x91Y\xbb1[g%\xb6\x83\r\xc86\x97s\x9f\x89\x12\xa3.\xf6x3L\x00\x00\u07d4J\x97\xe8\xfc\xf4c^\xa7\xfc^\x96\xeeQu.\u00c8qk`\x89\x1d\x99E\xab+\x03H\x00\x00\u07d4J\x9a&\xfd\n\x8b\xa1\x0f\x97}\xa4\xf7|1\x90\x8d\xabJ\x80\x16\x89a\t=|,m8\x00\x00\u07d4J\xa1H\xc2\xc34\x01\xe6j+Xnew\u0132\x92\xd3\xf2@\x89\v\xb8`\xb2\x85\xf7t\x00\x00\u07d4J\xa6\x93\xb1\"\xf3\x14H*G\xb1\x1c\xc7|h\xa4\x97\x87ab\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4J\xb2\xd3O\x04\x83O\xbftyd\x9c\xab\x92=,G%\xc5S\x89\xbe\xd1\xd0&=\x9f\x00\x00\x00\u07d4J\xc0vs\xe4/d\xc1\xa2^\xc2\xfa-\x86\xe5\xaa+4\xe09\x89lk\x93[\x8b\xbd@\x00\x00\u07d4J\u016c\xad\x00\v\x88w!L\xb1\xae\x00\xea\u0263}Y\xa0\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4J\u0250ZL\xb6\xab\x1c\xfdbTn\xe5\x91s\x00\xb8|O\u07897\b\xba\xed=h\x90\x00\x00\u07d4J\u03e9\xd9N\xdaf%\xc9\u07e5\xf9\xf4\xf5\xd1\a\xc4\x03\x1f\u07c9\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4J\xd0G\xfa\xe6~\xf1b\xfeh\xfe\xdb\xc2};e\xca\xf1\f6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4J\xd9]\x18\x8dddp\x9a\xdd%U\xfbM\x97\xfe\x1e\xbf1\x1f\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\u07d4J\xdb\xf4\xaa\xe0\xe3\xefD\xf7\xddM\x89\x85\u03ef\tn\u010e\x98\x89\b!\xab\rD\x14\x98\x00\x00\u07d4J\xe2\xa0M9\t\xefENTL\xcf\xd6\x14\xbf\xef\xa7\x10\x89\xae\x89\x18\x01\x15\x9d\xf1\xee\xf8\x00\x00\xe0\x94J\xe90\x82\xe4Q\x87\xc2a`\xe6g\x92\xf5\u007f\xad5Q\xc7:\x8a\x04\x96\x15 \xda\xff\x82(\x00\x00\u07d4J\xf0\xdb\a{\xb9\xba^D>!\xe1H\xe5\x9f7\x91\x05\u0152\x89 \x86\xac5\x10R`\x00\x00\u07d4K\x06\x19\xd9\u062a1:\x951\xac}\xbe\x04\xca\rjZ\u0476\x89lk\x93[\x8b\xbd@\x00\x00\u07d4K\v\u062c\xfc\xbcS\xa6\x01\v@\xd4\u040d\xdd-\x9dib-\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4K\x19\xeb\f5K\xc199`\xeb\x06\x06;\x83\x92o\rg\xb2\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4K)C|\x97\xb4\xa8D\xbeq\u0323\xb6H\xd4\xca\x0f\u075b\xa4\x89\b$q\x984\u03ec\x00\x00\u07d4K1\xbfA\xab\xc7\\\x9a\xe2\u034f\u007f5\x16;n+tPT\x89\x14\xb5P\xa0\x13\xc78\x00\x00\u07d4K:|\u00e7\u05f0\x0e\xd5(\"!\xa6\x02Y\xf2[\xf6S\x8a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94K:\xab3^\xbb\xfa\xa8p\xccM`^}.t\xc6h6\x9f\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4K\xcd\xc1\x8a`\x00\x00\u07d4K`\xa3\xe2S\xbf8\xc8\xd5f \x10\xbb\x93\xa4s\xc9e\xc3\xe5\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4Kt\xf5\xe5\x8e.\xdfv\xda\xf7\x01Q\x96J\v\x8f\x1d\xe0f<\x89\x11\x90\xaeID\xba\x12\x00\x00\u07d4Kv!f\xdd\x11\x18\xe8Ci\xf8\x04\xc7_\x9c\xd6W\xbfs\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Ky.)h>\xb5\x86\u353b3Rl`\x01\xb3\x97\x99\x9e\x89 \x86\xac5\x10R`\x00\x00\u07d4K\x90N\x93K\xd0\u030b p_\x87\x9e\x90[\x93\xea\f\xcc0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94K\x92\x06\xbakT\x9a\x1a\u007f\x96\x9e\x1d]\xba\x86u9\xd1\xfag\x8a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4K\x98N\xf2lWn\x81Z.\xae\xd2\xf5\x17\u007f\a\u06f1\xc4v\x89T\x91YV\xc4\t`\x00\x00\u07d4K\x9e\x06\x8f\xc4h\tv\xe6\x15\x04\x91)\x85\xfd\\\xe9K\xab\r\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4K\xa0\xd9\xe8\x96\x01w+IhG\xa2\xbbC@\x18g\x87\xd2e\x8965\u026d\xc5\u07a0\x00\x00\u07d4K\xa5:\xb5I\xe2\x01m\xfa\"<\x9e\u0563\x8f\xad\x91(\x8d\a\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94K\xa8\xe0\x11\u007f\xc0\xb6\xa3\xe5k$\xa3\xa5\x8f\xe6\xce\xf4B\xff\x98\x8a\x011\xbe\xb9%\xff\xd3 \x00\x00\u07d4K\xac\x84j\xf4\x16\x9f\x1d\x95C\x1b4\x1d\x88\x00\xb2!\x80\xaf\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4K\xb6\xd8k\x83\x14\xc2-\x8d7\xeaQm\x00\x19\xf1V\xaa\xe1-\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94K\xb9e\\\xfb*6\xea|cz{\x85\x9bJ1T\xe2n\xbe\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\xe0\x94K\xbc\xbf8\xb3\xc9\x01c\xa8K\x1c\u04a9;X\xb2\xa34\x8d\x87\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94K\xd6\xdd\f\xff#@\x0e\x170\xba{\x89E\x04W}\x14\xe7J\x8a+\xa0\xcc\xdd\xd0\xdfs\xb0\x00\x00\u07d4K\xe8b\x8a\x81T\x87N\x04\x8d\x80\xc1B\x18\x10\"\xb1\x80\xbc\xc1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4K\xe9\rA!)\u0564\xd0BCa\xd6d\x9dNG\xa6#\x16\x897\b\xba\xed=h\x90\x00\x00\xe0\x94K\xea(\x8e\xeaB\u0115^\xb9\xfa\xad*\x9f\xafG\x83\xcb\u076c\x8a\x06\x18\xbe\x16c\u012fI\x00\x00\u07d4K\xf4G\x97\x99\xef\x82\xee\xa2\tC7OV\xa1\xbfT\x00\x1e^\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4K\xf8\xbf\x1d5\xa211Wd\xfc\x80\x01\x80\x9a\x94\x92\x94\xfcI\x89\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\u07d4K\xf8\xe2oL'\x90\xdae3\xa2\xac\x9a\xba\xc3\u019a\x19\x943\x89\n\u05ce\xbcZ\xc6 \x00\x00\u0794L\n\xcaP\x8b<\xaf^\xe0(\xbcp}\xd1\xe8\x00\xb88\xf4S\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94L\v\x15\x15\xdf\xce\u05e1>\x13\xee\x12\xc0\xf5#\xaePO\x03+\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4L\x13\x98\f2\xdc\xf3\x92\vx\xa4\xa7\x903\x12\x90|\x1b\x12?\x89\x03A\x00\x15\xfa\xae\f\x00\x00\u07d4L\x15y\xaf3\x12\xe4\xf8\x8a\xe9\x95\xcc9W\xd2R\xce\v\xf0\xc8}[O\"4g.p\x89\x87\x86x2n\xac\x90\x00\x00\u07d4LB1y\x82i\x1d\x10\x89\x05k\xc7^-c\x10\x00\x00\u07d4LZ\xfe@\xf1\x8f\xfcH\u04e1\xae\xc4\x1f\u009d\xe1y\xf4\u0497\x89lk\x93[\x8b\xbd@\x00\x00\u07d4L[=\xc0\xe2\xb96\x0f\x91(\x9b\x1f\xe1<\xe1,\x0f\xbd\xa3\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Lfk\x86\xf1\xc5\ue324\x12\x85\xf5\xbd\xe4\xf7\x90R\b\x14\x06\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Lik\xe9\x9f:i\x04@\xc3CjY\xa7\xd7\xe97\u05ba\r\x89\xbb\x91%T\"c\x90\x00\x00\u07d4Lj$\x8f\xc9}p]\xefI\\\xa2\aY\x16\x9e\xf0\xd3dq\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4Lj\x9d\xc2\u02b1\n\xbb.|\x13p\x06\xf0\x8f\ucd77y\xe1\x89\x1b\r\x04 /G\xec\x00\x00\u07d4Lk\x93\xa3\xbe\xc1cIT\f\xbf\xca\xe9l\x96!\xd6dP\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Lu\x98\x13\xad\x13\x86\xbe\xd2\u007f\xfa\xe9\xe4\x81^60\u0323\x12\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Lv\f\xd9\xe1\x95\xeeO-k\xce%\x00\xff\x96\xda|C\ue44a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4Lv{e\xfd\x91\x16\x1fO\xbd\xccji\xe2\xf6\xadq\x1b\xb9\x18\x89'\b\x01\xd9F\xc9@\x00\x00\u07d4L~.+w\xad\f\xd6\xf4J\xcb(a\xf0\xfb\x8b(u\x0e\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4L\x85\xed6/$\xf6\xb9\xf0L\xdf\xcc\xd0\"\xaeSQG\u02f9\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4L\x93[\xb2Pw\x8b0\x9b==\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4L\xee\x90\x1bJ\u0231V\xc5\xe2\xf8\xa6\xf1\xbe\xf5r\xa7\xdc\xeb~\x8965\u026d\xc5\u07a0\x00\x00\u07d4L\xef\xbe#\x98\xe4}R\u73743L\x8bivu\U00053b89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4L\xf5S{\x85\x84/\x89\xcf\xee5\x9e\xaeP\x0f\xc4I\xd2\x11\x8f\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94M\bG\x1dh\x00z\xff*\xe2y\xbc^?\xe4\x15o\xbb\xe3\u078a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4M \x01\x10\x12@\b\xd5ov\x98\x12VB\f\x94jo\xf4\\\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4M$\xb7\xacG\xd2\xf2}\xe9\tt\xba=\xe5\xea\xd2\x03TK\u0349\x05k\xc7^-c\x10\x00\x00\u0794M)\xfcR:,\x16)S!!\u0699\x98\u9d6b\x9d\x1bE\x88\xdbD\xe0I\xbb,\x00\x00\u07d4M8\xd9\x0f\x83\xf4Q\\\x03\xccx2j\x15M5\x8b\u0602\xb7\x89\n\ad\a\xd3\xf7D\x00\x00\u07d4ML\xf5\x80t)a^0\xcd\xfa\xce\x1eZ\xaeM\xad0U\xe6\x89 \x86\xac5\x10R`\x00\x00\u07d4MW\xe7\x16\x87l\f\x95\xef^\xae\xbd5\xc8\xf4\x1b\x06\x9bk\xfe\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Mg\U000ab159\xfe\xf5\xfcA9\x99\xaa\x01\xfd\u007f\xcep\xb4=\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Mn\x8f\xe1\t\xcc\xd2\x15\x8eM\xb1\x14\x13/\xe7_\xec\u023e[\x89\x01[5W\xf1\x93\u007f\x80\x00\xe0\x94Mq\xa6\xeb=\u007f2~\x184'\x8e(\v\x03\x9e\xdd\xd3\x1c/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4M|\xfa\xa8L\xb31\x06\x80\n\x8c\x80/\xb8\xaaF8\x96\u0159\x89a\t=|,m8\x00\x00\u07d4M\x80\x10\x93\xc1\x9c\xa9\xb8\xf3B\xe3<\xc9\xc7{\xbdL\x83\x12\u03c9\x12\xb3\xe7\xfb\x95\u0364\x80\x00\u07d4M\x82\x88\x94u/o%\x17]\xaf!w\tD\x87\x95Ko\x9f\x89O!+\xc2\u011c\x83\x80\x00\xe0\x94M\x82\xd7p\f\x12;\xb9\x19A\x9b\xba\xf0Fy\x9ck\x0e,f\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4M\x83m\x9d;\x0e,\xbdM\xe0PYo\xaaI\f\xff\xb6\r]\x89\x10CV\x1a\x88)0\x00\x00\u07d4M\x86\x97\xaf\x0f\xbf,\xa3n\x87h\xf4\xaf\"\x135phZ`\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4M\x92y\x96 )\xa8\xbdEc\x977\xe9\x8bQ\x1e\xff\aL!\x89Hz\x9a0E9D\x00\x00\u07d4M\x93io\xa2HY\xf5\u0493\x9a\xeb\xfaT\xb4\xb5\x1a\xe1\xdc\u0309\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4M\x9cw\xd0u\f^o\xbc$\u007f/\u05d2thl\xb3S\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4M\xa5\xed\u0188\xb0\xcbb\xe1@=\x17\x00\xd9\u0739\x9f\xfe?\u04c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94M\xa8\x03\ai\x84K\xc3A\x86\xb8\\\xd4\xc74\x88I\xffI\xe9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4M\xb1\xc4:\x0f\x83M}\x04x\xb8\x96\ag\xec\x1a\xc4L\x9a\xeb\x89/Q\x810V'7\x00\x00\u07d4M\xb2\x12\x84\xbc\xd4\xf7\x87\xa7Ue\x00\xd6\xd7\xd8\xf3f#\xcf5\x89i(7Ow\xa3c\x00\x00\u07d4M\xc3\xda\x13\xb2\xb4\xaf\xd4O]\r1\x89\xf4D\xd4\xdd\xf9\x1b\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4M\u013f^u\x89\xc4{(7\x8du\x03\u03d6H\x80a\u06fd\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4M\xc9\u057bK\x19\xce\u0354\xf1\x9e\xc2] \x0e\xa7/%\xd7\xed\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94M\xcd\x11\x81X\x18\xae)\xb8]\x016sI\xa8\xa7\xfb\x12\xd0k\x8a\x01\xacB\x86\x10\x01\x91\xf0\x00\x00\u07d4M\xcfb\xa3\xde?\x06\x1d\xb9\x14\x98\xfda\x06\x0f\x1fc\x98\xffs\x89lj\xccg\u05f1\xd4\x00\x00\u07d4M\xd11\xc7J\x06\x8a7\xc9\n\xde\xd4\xf3\t\xc2@\x9fdx\u04c9\x15\xaf9\u4ab2t\x00\x00\xe0\x94M\u0767Xk\"7\xb0S\xa7\xf3(\x9c\xf4`\xdcW\xd3z\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4M\xe3\xfe4\xa6\xfb\xf64\xc0Q\x99\u007fG\xcc\u007fHy\x1fX$\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4M\xf1@\xbaye\x85\xddT\x891[\xcaK\xbah\n\u06f8\x18\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4N\x02\ay\xb5\xdd\xd3\xdf\"\x8a\x00\xcbH\xc2\xfc\x97\x9d\xa6\xae8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4N\v\xd3$s\xc4\xc5\x1b\xf2VT\xde\xf6\x9fy|k)\xa22\x89V\xc9]\xe8\xe8\xca\x1d\x00\x00\u07d4N\"%\xa1\xbbY\xbc\x88\xa21ft\xd33\xb9\xb0\xaf\xcafU\x89\bg\x0e\x9e\xc6Y\x8c\x00\x00\u07d4N#\x10\x19\x1e\xad\x8d;\xc6H\x98s\xa5\xf0\xc2\xeck\x87\u1f8965\u026d\xc5\u07a0\x00\x00\u07d4N#-S\xb3\u6f8f\x89Sa\xd3\x1c4\xd4v+\x12\xc8.\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4N+\xfaJFo\x82g\x1b\x80\x0e\xeeBj\xd0\f\a\x1b\xa1p\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4N>\xda\u0506M\xabd\xca\xe4\xc5Azvw@S\xdcd2\x89 \b\xfbG\x8c\xbf\xa9\x80\x00\u07d4NC\x18\xf5\xe1>\x82JT\xed\xfe0\xa7\xedO&\xcd=\xa5\x04\x89lk\x93[\x8b\xbd@\x00\x00\u07d4N[w\xf9\x06aY\xe6\x15\x93?-\xdatw\xfaNG\xd6H\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94Nf\x00\x80b\x89EJ\u03630\xa2\xa3U`\x10\u07ec\xad\xe6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Ns\xcf#y\xf1$\x86\x0fs\xd6\xd9\x1b\xf5\x9a\xcc\\\xfc\x84[\x89\x02,\xa3X|\xf4\xeb\x00\x00\xe0\x94Nz\xa6~\x12\x18>\xf9\xd7F\x8e\xa2\x8a\xd29\xc2\xee\xf7\x1bv\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\xe0\x94N{TGM\x01\xfe\xfd8\x8d\xfc\xd5;\x9ff&$A\x8a\x05\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94N\x89.\x80\x81\xbf6\xe4\x88\xfd\xdb;&0\xf3\xf1\xe8\xda0\u048a\x02\x8a\xba0u$Q\xfc\x00\x00\xe0\x94N\x8amcH\x9c\xcc\x10\xa5\u007f\x88_\x96\xeb\x04\xec\xbbT`$\x8a\x03\xea\xe3\x13\x0e\u0316\x90\x00\x00\u07d4N\x8eG\xae;\x1e\xf5\f\x9dT\xa3\x8e\x14 \x8c\x1a\xbd6\x03\u0089y(\xdb\x12vf\f\x00\x00\u0794N\x90\u03312X\xac\xaa\x9fO\xeb\xc0\xa3B\x92\xf9Y\x91\xe20\x88\xdbD\xe0I\xbb,\x00\x00\u07d4N\xa5n\x11\x12d\x1c\x03\x8d\x05e\xa9\u0096\xc4c\xaf\xef\xc1~\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\xe0\x94N\xa7\x0f\x041?\xaee\xc3\xff\"J\x05\\=-\xab(\xdd\u07ca\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4N\xb1EKW8\x05\u022c\xa3~\xde\xc7\x14\x9aA\xf6\x12\x02\xf4\x89\x10CV\x1a\x88)0\x00\x00\u07d4N\xb8{\xa8x\x8e\xba\r\xf8~[\x9b\xd5\n\x8eE6\x80\x91\xc1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4N\xbcV)\xf9\xa6\xa6k,\xf36:\u0109\\\x03H\u8fc7\x8967\tlK\xcci\x00\x00\u07d4N\xc7h)^\xea\xba\xfcB\x95\x84\x15\xe2+\xe2\x16\xcd\xe7v\x18\x89\x03;\x1d\xbc9\xc5H\x00\x00\u07d4N\xcc\x19\x94\x8d\xd9\u0347\xb4\xc7 \x1a\xb4\x8eu\x8f(\xe7\xccv\x89\x1b\x1d\xaba\u04ead\x00\x00\u07d4N\xd1M\x81\xb6\v#\xfb%\x05M\x89%\u07e5s\u072eah\x89\x12nr\xa6\x9aP\xd0\x00\x00\xe0\x94N\xe1<\rA \vF\u045d\xee\\K\xce\xc7\x1d\x82\xbb\x8e8\x8a\x01\xab\xee\x13\u033e\ufbc0\x00\u07d4N\xea\xd4\n\xad\x8cs\xef\b\xfc\x84\xbc\n\x92\xc9\t/j6\xbf\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4N\xeb\xe8\f\xb6\xf3\xaeY\x04\xf6\xf4\xb2\x8d\x90\u007f\x90q\x89\xfc\xab\x89lj\xccg\u05f1\xd4\x00\x00\u07d4N\xeb\xf1 ]\f\xc2\f\xeel\u007f\x8f\xf3\x11_V\u050f\xba&\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4N\xf1\xc2\x14c:\xd9\xc0p;N#t\xa2\xe3>>B\x92\x91\x89Hz\x9a0E9D\x00\x00\u07d4N\xfc\xd9\u01df\xb43L\xa6${\n3\xbd\x9c\xc32\b\xe2r\x89Hz\x9a0E9D\x00\x00\xe0\x94O\x06$k\x8dK\u0496a\xf4>\x93v\"\x01\u0486\x93Z\xb1\x8a\x01\x059O\xfcF6\x11\x00\x00\u07d4O\x15+/\xb8e\x9dCwn\xbb\x1e\x81g:\xa8Ai\xbe\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4O\x17\u007f\x9dV\x95=\xedq\xa5a\x1f93\"\xc3\x02y\x89\\\x89\rU\uf422\xda\x18\x00\x00\u07d4O\x1a-\xa5JLm\xa1\x9d\x14$\x12\xe5n\x81WA\xdb#%\x89\x05k\xc7^-c\x10\x00\x00\u07d4O#\xb6\xb8\x17\xff\xa5\xc6d\xac\xda\u05db\xb7\xb7&\xd3\n\xf0\xf9\x89_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94O&i\f\x99+z1*\xb1.\x13\x85\xd9J\xcdX(\x8e{\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4O+G\xe2wZ\x1f\xa7\x17\x8d\xad\x92\x98Z[\xbeI;\xa6\u0589\n\u05ce\xbcZ\xc6 \x00\x00\u07d4O:HT\x91\x11E\xea\x01\xc6D\x04K\xdb.Z\x96\n\x98/\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4O?,g0i\xac\x97\xc2\x026\a\x15)\x81\xf5\xcd`c\xa0\x89 \x86\xac5\x10R`\x00\x00\xe0\x94OJ\x9b\xe1\f\xd5\xd3\xfb]\xe4\x8c\x17\xbe)o\x89V\x90d[\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4OR\xadap\xd2[*.\x85\x0e\xad\xbbRA?\xf20>\u007f\x89\xa4\xccy\x95c\u00c0\x00\x00\u07d4OX\x01\xb1\xeb0\xb7\x12\u0620WZ\x9aq\xff\x96]O4\xeb\x89\x10CV\x1a\x88)0\x00\x00\u07d4O]\xf5\xb9CW\u0794\x86\x04\xc5\x1bx\x93\xcd\xdf`v\xba\xad\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\u07d4Od\xa8^\x8e\x9a@I\x8c\fu\xfc\xeb\x037\xfbI\b>^\x8965\u026d\xc5\u07a0\x00\x00\u07d4Og9m%S\xf9\x98x_pN\a\xa69\x19}\u0454\x8d\x89\x10DrR\x1b\xa78\x00\x00\u07d4OmG7\u05e9@8$\x87&H\x86i|\xf7c\u007f\x80\x15\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4Os0\toy\xed&N\xe0\x12\u007f]0\xd2\xf7?!\xcb\u007f\x04\x89\x04\x82\xfe&\f\xbc\xa9\x00\x00\u07d4O\xeeP\xc5\xf9\x88 k\t\xa5sF\x9f\xb1\u0434.\xbbm\u0389l\xee\x06\u077e\x15\xec\x00\x00\u07d4O\xf6v\xe2\u007fh\x1a\x98-\x8f\xd9\xd2\x0ed\x8b=\xce\x05\xe9E\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4O\xf6\u007f\xb8\u007fn\xfb\xa9'\x990\u03fd\x1bz4L\u057a\x8bN\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94PFf\u03891\x17^\x11\xa5\xed\x11\xc1\u072a\x06\xe5\u007fNf\x8a\x02\u007f>\u07f3Nn@\x00\x00\u0794PXM\x92\x06\xa4l\xe1\\0\x11\x17\xee(\xf1\\0\xe6\x0eu\x88\xb9\xf6]\x00\xf6<\x00\x00\xe0\x94PZ3\xa1\x864\xddH\x00i)\x13N\x00\x00\u07d4P\u0286\xb5\xeb\x1d\x01\x87M\xf8\xe5\xf3IE\u051cl\x1a\xb8H\x8965\u026d\xc5\u07a0\x00\x00\u07d4P\u0357\xe97\x8b\\\xf1\x8f\x179c#l\x99Q\xeft8\xa5\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4P\u073c'\xbc\xad\x98@\x93\xa2\x12\xa9\xb4\x17\x8e\xab\xe9\x01ua\x89\a\xe3by\v\\\xa4\x00\x00\u07d4P\xe10#\xbd\x9c\xa9j\xd4\xc5?\xdf\xd4\x10\xcbk\x1fB\v\u07c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94P\xe1\xc8\xec\x98A[\xefD&\x18p\x87\x99C{\x86\xe6\xc2\x05\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4P\xf8\xfaK\xb9\xe2g|\x99\nN\xe8\xcep\xdd\x15#%\x1eO\x89\x01i=#\x16Ok\x00\x00\u07d4P\xfb6\xc2q\a\xee,\xa9\xa3#n'F\u0321\x9a\xcekI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4P\xfe\xf2\x96\x95U\x88\u02aet\xc6.\xc3*#\xa4T\xe0\x9a\xb8\x89A\x1d\xff\xab\xc5\a8\x00\x00\u07d4Q\x02\xa4\xa4 w\xe1\x1cX\xdfGs\u3b14F#\xa6m\x9f\x89lp\x15\xfdR\xed@\x80\x00\u07d4Q\x03\x93w\xee\xd0\xc5s\xf9\x86\xc5\xe8\xa9_\xb9\x9aY\xe93\x0f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Q\x03\xbc\t\x93>\x99!\xfdS\xdcSo\x11\xf0]\rG\x10}\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94Q\x04\xec\xc0\xe30\xdd\x1f\x81\xb5\x8a\xc9\u06f1\xa9\xfb\xf8\x8a<\x85\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4Q\r\x81Y\u0314Wh\xc7E\a\x90\xba\a>\xc0\xd9\xf8\x9e0\x89\x8a\xc7#\x04\x89\xe8\x00\x00\x00\u07d4Q\x0e\xdaV\x01I\x9a\r^\x1a\x00k\xff\xfd\x836r\xf2\xe2g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x12dF\xab=\x802U~\x8e\xbaeY}u\xfa\u0701\\\x89\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\xe0\x94Q\x18U}`\r\x05\xc2\xfc\xbf8\x06\xff\xbd\x93\xd0 %\xd70\x8a\x02g\u04ebd#\xf5\x80\x00\x00\u07d4Q\x1e\x0e\xfb\x04\xacN?\xf2\xe6U\x0eI\x82\x95\xbf\xcdV\xff\u0549$=M\x18\"\x9c\xa2\x00\x00\u07d4Q!\x16\x81{\xa9\xaa\xf8C\xd1P|e\xa5\xead\n{\x9e\xec\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4Q&F\ri,q\u026fo\x05WM\x93\x99\x83h\xa27\x99\x89\x02\u0465\x1c~\x00P\x00\x00\u07d4Q'\u007f\xe7\xc8\x1e\xeb\xd2R\xa0=\xf6\x9ak\x9f2n'\"\a\x89\x03@.y\u02b4L\x80\x00\u07d4Q)oPD'\r\x17pvF\x12\x9c\x86\xaa\xd1d^\xad\xc1\x89H|r\xb3\x10\xd4d\x80\x00\xe0\x94Q+\x91\xbb\xfa\xa9\xe5\x81\xefh?\xc9\r\x9d\xb2*\x8fI\xf4\x8b\x8aA\xa5\"8m\x9b\x95\xc0\x00\x00\u07d4Q5\xfb\x87W`\f\xf4tTbR\xf7M\xc0tm\x06&,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4QF2\xef\xbdd,\x04\xdel\xa3B1]@\u0750\xa2\u06e6\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4QKu\x12\u026e^\xa6<\xbf\x11q[c\xf2\x1e\x18\u0496\xc1\x89lj\xccg\u05f1\xd4\x00\x00\u07d4QS\xa0\xc3\u0211(\x81\xbf\x1c5\x01\xbfd\xb4VI\xe4\x82\"\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94QVQ\xd6\xdbO\xaf\x9e\xcd\x10:\x92\x1b\xbb\xbej\xe9p\xfd\u050a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94Q_0\xbc\x90\xcd\xf4W~\xe4}e\u05c5\xfb\xe2\xe87\u01bc\x8a\x02'\x1b^\x01\x8b\xa0X\x00\x00\u07d4Q`\xeda.\x1bH\xe7??\xc1[\xc42\x1b\x8f#\xb8\xa2K\x89\x1e\x82kB(e\xd8\x00\x00\u07d4Qa\xfdI\xe8G\xf6tU\xf1\u023bz\xbb6\xe9\x85&\r\x03\x89A\rXj \xa4\xc0\x00\x00\u07d4QiT\x02_\xca&\b\xf4}\xa8\x1c!^\xed\xfd\x84J\t\xff\x89\x14\xb5P\xa0\x13\xc78\x00\x00\u07d4Qi\xc6\n\xeeL\xee\u0444\x9a\xb3mfL\xff\x97\x06\x1e\x8e\xa8\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4Q|uC\r\xe4\x01\xc3A\x03&\x86\x11'\x90\xf4mM6\x9e\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4Q|\xd7`\x8e]\r\x83\xa2kq\u007f6\x03\xda\xc2'}\u00e4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x86]\xb1H\x88\x19Q\xf5\x12Qq\x0e\x82\xb9\xbe\r~\xad\xb2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\x89\x1b,\xcd\xd2\xf5\xa4K*\x8b\u011a]\x9b\xcadw%\x1c\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4Q\x8c\xef'\xb1\x05\x82\xb6\xd1OiH=\u06a0\xdd<\x87\xbb\\\x89 \x86\xac5\x10R`\x00\x00\u07d4Q\xa6\xd6'\xf6j\x89#\u060d`\x94\xc4qS\x80\xd3\x05|\xb6\x89>s\xd2z5\x94\x1e\x00\x00\u07d4Q\xa8\xc2\x166\x02\xa3.\xe2L\xf4\xaa\x97\xfd\x9e\xa4\x14QiA\x89\x03h\xf7\xe6\xb8g,\x00\x00\u07d4Q\xb4u\x8e\x9e\x14P\xe7\xafBh\xc3\u01f1\xe7\xbdo\\uP\x8965\u026d\xc5\u07a0\x00\x00\u07d4Q\u028b\xd4\xdcdO\xacG\xafgUc\u0540J\r\xa2\x1e\xeb\x89*\xb7\xb2`\xff?\xd0\x00\x00\u07d4Q\xd2K\xc3so\x88\xddc\xb7\" &\x88f0\xb6\ub1cd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Q\u05cb\x17\x8dp~9n\x87\x10\x96\\OA\xb1\xa1\xd9\x17\x9d\x89\x05\xfe\xe2\"\x04\x1e4\x00\x00\u07d4Q\xe3/\x14\xf4\xca^(|\xda\xc0W\xa7y^\xa9\xe0C\x99S\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Q\xe4?\xe0\xd2\\x(`\xaf\x81\xea\x89\xddy<\x13\xf0\u02f1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4Q\xe7\xb5\\/\x98 \xee\xd78\x846\x1bPf\xa5\x9boE\u0189lk\x93[\x8b\xbd@\x00\x00\xe0\x94Q\xea\x1c\t4\xe3\xd0@\"\ud715\xa0\x87\xa1P\xefp^\x81\x8a\x01Tp\x81\xe7\"M \x00\x00\u07d4Q\xee\f\xca;\xcb\x10\xcd>\x987\"\xce\xd8I=\x92l\bf\x8965f3\xeb\xd8\xea\x00\x00\xe0\x94Q\xf4f:\xb4O\xf7\x93E\xf4'\xa0\xf6\xf8\xa6\u0225?\xf24\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Q\xf5^\xf4~dV\xa4\x18\xab2\xb9\"\x1e\xd2}\xbaf\b\xee\x89\u3bb5sr@\xa0\x00\x00\xe0\x94Q\xf9\xc42\xa4\xe5\x9a\xc8b\x82\u05ad\xabL.\xb8\x91\x91`\xeb\x8ap;[\x89\u00e6\xe7@\x00\x00\u07d4R\x0ff\xa0\xe2e\u007f\xf0\xacA\x95\xf2\xf0d\xcf/\xa4\xb2BP\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4R\x10#T\xa6\xac\xa9]\x8a.\x86\xd5\u07bd\xa6\xdei4`v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\x13\xf4Y\xe0x\xad:\xb9Z\t #\x9f\xcf\x163\xdc\x04\u0289\x8c\xf2\x18|*\xfb\x18\x80\x00\u07d4R\x15\x18;\x8f\x80\xa9\xbc\x03\xd2l\xe9\x12\a\x83*\r9\xe6 \x8965\u026d\xc5\u07a0\x00\x00\xe0\x94R!Cx\xb5@\x04\x05j|\xc0\x8c\x89\x13'y\x8a\u01b2H\x8a\x037\xfe_\xea\xf2\u0440\x00\x00\xe0\x94R##\xaa\xd7\x1d\xbc\x96\xd8Z\xf9\x0f\bK\x99\xc3\xf0\x9d\ucdca\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4R>\x14\r\xc8\x11\xb1\x86\xde\xe5\xd6\u020b\xf6\x8e\x90\xb8\xe0\x96\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R?mdi\x0f\xda\u0354(SY\x1b\xb0\xff \xd3em\x95\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4RO\xb2\x10R,^#\xbbg\u07ff\x8c&\xaaam\xa4\x99U\x8965b\xa6m4#\x80\x00\u07d4RU\xdci\x15ZE\xb9p\xc6\x04\xd3\x00G\xe2\xf50i\x0e\u007f\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4R`\xdcQ\xee\a\xbd\u06ab\xab\xb9\xeetK9<\u007fG\x93\xa6\x89\x01\xd8f_\xa5\xfaL\x00\x00\u07d4Rg\xf4\xd4\x12\x92\xf3p\x86<\x90\u05d3)i\x03\x846%\u01c9K\xe4\xe7&{j\xe0\x00\x00\u07d4Rk\xb53\xb7n \xc8\xee\x1e\xbf\x12?\x1e\x9f\xf4\x14\x8e@\xbe\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4Rl\xb0\x9c\u3b63g.\xec\x1d\xebF [\xe8\x9aKV>\x89\x85\xcaa[\xf9\xc0\x10\x00\x00\u07d4Rs\x8c\x90\xd8`\xe0L\xb1/I\x8d\x96\xfd\xb5\xbf6\xfc4\x0e\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4Rz\x8c\xa1&\x863\xa6\xc99\xc5\xde\x1b\x92\x9a\ue4ae\xac\x8d\x890\xca\x02O\x98{\x90\x00\x00\u07d4R\x81\x01\xceF\xb7 \xa2!M\u036ef\x18\xa51w\xff\xa3w\x89\x1b\x96\x12\xb9\xdc\x01\xae\x00\x00\xe0\x94R\x81s4s\xe0\r\x87\xf1\x1e\x99U\u5275\x9fJ\u008ez\x8a\x8b\xd6/\xf4\xee\xc5Y \x00\x00\u07d4R\x98\xab\x18*\x195\x9f\xfc\xec\xaf\xd7\u0475\xfa!-\xed\xe6\u0749\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4R\x9a\xa0\x02\u0196*:\x85E\x02\u007f\u0630_\"\xb5\xbf\x95d\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4R\x9e\x82O\xa0rX+@2h:\xc7\xee\xcc\x1c\x04\xb4\xca\xc1\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94R\xa5\xe4\xdeC\x93\xee\xcc\xf0X\x1a\xc1\x1bR\u0183\xc7n\xa1]\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4R\xb4%|\xf4\x1bn(\x87\x8dP\xd5{\x99\x91O\xfa\x89\x87:\x89\xd5\r\u026a,Aw\x00\x00\u07d4R\xb8\xa9Y&4\xf70\v|\\Y\xa34[\x83_\x01\xb9\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\xbd\u066fYx\x85\v\xc2A\x10q\x8b7#u\x9bC~Y\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4R\xcd @;\xa7\xed\xa6\xbc0z=c\xb5\x91\x1b\x81|\x12c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794R\u04c0Q\x1d\xf1\x9d^\u0080{\xbc\xb6vX\x1bg\xfd7\xa3\x88\xb9\xf6]\x00\xf6<\x00\x00\xe0\x94R\xe1s\x13P\xf9\x83\xcc,A\x89\x84/\xde\x06\x13\xfa\xd5\f\xe1\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\u07d4R\xe4g\x832\x9av\x93\x01\xb1u\x00\x9d4gh\xf4\xc8~\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4R\xf0X\xd4aG\xe9\x00m)\xbf,\t0J\xd1\xcd\xddn\x15\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4R\xf1T#2<$\xf1\x9a\xe2\xabg7\x17\"\x9d?t}\x9b\x897\xa04\xcb\xe8\xe3\xf3\x80\x00\u07d4R\xf8\xb5\t\xfe\xe1\xa8t\xabo\x9d\x876\u007f\xbe\xaf\x15\xac\x13\u007f\x8965\u026d\xc5\u07a0\x00\x00\u07d4R\xfbF\xac]\x00\xc3Q\x8b,:\x1c\x17}D/\x81eU_\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4S\x00w\xc9\xf7\xb9\a\xff\x9c\xec\fw\xa4\x1ap\xe9\x02\x9a\xddJ\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\x03\x19\xdb\n\x8f\x93\xe5\xbb}M\xbfH\x161O\xbe\xd86\x1b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\x04}\u022c\x90\x83\xd9\x06r\xe8\xb3G<\x10\f\xcd'\x83#\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4S\va\xe4/9Bm$\b\xd4\bR\xb9\xe3J\xb5\xeb\xeb\u0149\x0e~\xeb\xa3A\vt\x00\x00\u07d4S\x0f\xfa\u00fc4\x12\xe2\xec\x0e\xa4{y\x81\xc7p\xf5\xbb/5\x89\a?u\u0460\x85\xba\x00\x00\u07d4S\x17\xec\xb0#\x05,\xa7\xf5e+\xe2\xfa\x85L\xfeEc\xdfM\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4S\x19M\x8a\xfa>\x885\x02v~\xdb\xc3\x05\x86\xaf3\xb1\x14\u04c9lk\x93[\x8b\xbd@\x00\x00\u07d4S*}\xa0\xa5\xadt\aF\x8d;\xe8\xe0~i\xc7\xddd\xe8a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4S-2\xb0\x0f0[\xcc$\xdc\xefV\x81}b/4\xfb,$\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4S4DX@\x82\xeb\xa6T\xe1\xad0\xe1Is\\o{\xa9\"\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4S8\xefp\xea\xc9\u075a\xf5\xa0P;^\xfa\xd1\x03\x9eg\xe7%\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94S9oJ&\u00b4`D\x960lTB\xe7\xfc\xba'.6\x8a\x04?/\b\xd4\x0eZ\xfc\x00\x00\xe0\x94S:s\xa4\xa2\"\x8e\xee\x05\xc4\xff\xd7\x18\xbb\xf3\xf9\xc1\xb1)\xa7\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4S<\x06\x92\x8f\x19\u0429V\xcc(\x86k\xf6\xc8\xd8\xf4\x19\x1a\x94\x89\x0f\xd8\xc1C8\xe60\x00\x00\u07d4S@e6\x1c\xb8T\xfa\xc4+\xfb\\\x9f\xcd\xe0`J\xc9\x19\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4SC\u007f\xec\xf3J\xb9\xd45\xf4\u07b8\xca\x18\x15\x19\xe2Y 5\x89\n1\x06+\xee\xedp\x00\x00\u07d4SR\x01\xa0\xa1\xd74\"\x80\x1fU\xde\xd4\u07ee\xe4\xfb\xaan;\x89\x02&!\x1fy\x15B\x80\x00\xe0\x94S`\x81\x05\xceK\x9e\x11\xf8k\xf4\x97\xff\xca;x\x96{_\x96\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4SnM\x80)\xb7?Uy\u0723>p\xb2N\xba\x89\xe1\x1d~\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Sp\rS%MC\x0f\"x\x1aJv\xa4c\x93;]k\b\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94S\u007f\x9dM1\xefp\x83\x9d\x84\xb0\xd9\u0377+\x9a\xfe\xdb\xdf5\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\xe0\x94S\x81D\x85\x03\xc0\xc7\x02T+\x1d\xe7\xcc_\xb5\xf6\xab\x1c\xf6\xa5\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94S\x94.yI\xd6x\x8b\xb7\x80\xa7\xe8\xa0y'\x81\xb1aK\x84\x8a\x03]\xebFhO\x10\xc8\x00\x00\u07d4S\x95\xa4E]\x95\xd1x\xb4S*\xa4r[\x19?\xfeQ)a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94S\x98\x9e\xd30V?\xd5}\xfe\u027d4<7`\xb0y\x93\x90\x8a\x01P\x89N\x84\x9b9\x00\x00\x00\u07d4S\xa2Dg(\x95H\x0fJ+\x1c\xdf}\xa5\xe5\xa2B\xecM\xbc\x8965\u026d\xc5\u07a0\x00\x00\u07d4S\xa7\x14\xf9\x9f\xa0\x0f\xefu\x8e#\xa2\xe7F2m\xad$|\xa7\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4S\xaf2\xc2/\uf640?\x17\x8c\xf9\v\x80/\xb5q\xc6\x1c\xb9\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4S\xc0\xbb\u007f\u020e\xa4\"\xd2\xef~T\x0e-\x8f(\xb1\xbb\x81\x83\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94S\xc5\xfe\x01\x19\xe1\xe8Hd\f\xee0\xad\ua594\x0f*]\x8b\x8a\x04\x9a\xda_\xa8\xc1\f\x88\x00\x00\u07d4S\xc9\xec\xa4\ts\xf6;\xb5\x92{\xe0\xbcj\x8a\x8b\xe1\x95\x1ft\x89lk\x93[\x8b\xbd@\x00\x00\u07d4S\u0388\xe6lZ\xf2\U0009bf4fY*V\xa3\xd1_ l2\x89\a\xa2\x8c1\xcc6\x04\x00\x00\u07d4S\xce\xc6\u0200\x92\xf7V\xef\xe5o}\xb1\x12(\xa2\xdbE\xb1\"\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4S\xe3[\x12#\x1f\x19\xc3\xfdwL\x88\xfe\xc8\xcb\xee\xdf\x14\b\xb2\x89\x1b\xc1mgN\xc8\x00\x00\x00\u07d4S\xe4\xd9im\xcb?M{?p\u072aN\xec\xb7\x17\x82\xff\\\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4S\xfa\xf1e\xbe\x03\x1e\xc1\x830\xd9\xfc\xe5\xbd\x12\x81\xa1\xaf\b\u06c9\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4T\n\x18\x19\xbd|5\x86\x1ey\x18\x04\xe5\xfb\xb3\xbc\x97\u026b\xb1\x89N\xd7\xda\xc6B0 \x00\x00\xe0\x94T\f\a(\x02\x01N\xf0\xd5a4Z\xecH\x1e\x8e\x11\xcb5p\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94T\f\xf2=\xd9\\MU\x8a'\x9dw\x8d+75\xb3\x16A\x91\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4T\x10`\xfcX\xc7P\xc4\x05\x12\xf83i\xc0\xa63@\xc1\"\xb6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4T\x13\xc9\u007f\xfaJn*{\xba\x89a\u071f\u03850\xa7\x87\u05c965\u026d\xc5\u07a0\x00\x00\u07d4T\x1d\xb2\n\x80\xcf;\x17\xf1b\x1f\x1b?\xf7\x9b\x88/P\xde\xf3\x8965\u026d\xc5\u07a0\x00\x00\u07d4T.\x80\x96\xba\xfb\x88\x16&\x06\x00.\x8c\x8a>\u0458\x14\xae\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T1\v:\xa8\x87\x03\xa7%\u07e5}\xe6\xe6F\x93Qd\x80,\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4T1\xb1\u0447Q\xb9\x8f\xc9\u220a\xc7u\x9f\x155\xa2\xdbG\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T1\xcaB~ae\xa6D\xba\xe3&\xbd\tu\n\x17\x8ce\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T5\xc6\xc1y3\x17\xd3,\xe1;\xbaLO\xfe\xb9s\xb7\x8a\u0709\r\x8ek\x1c\x12\x85\xef\x00\x00\xe0\x94T6)\xc9\\\xde\xf4(\xad7\xd4S\u02958\xa9\xf9\t\x00\xac\x8a\t(\x96R\x9b\xad\u0708\x00\x00\u07d4T9\x1bM\x17mGl\xea\x16N_\xb55\u0197\x00\xcb%5\x89\x05l\xd5_\xc6M\xfe\x00\x00\xe0\x94T:\x8c\x0e\xfb\x8b\xcd\x15\xc5C\u29a4\xf8\aYv1\xad\xef\x8a\x01?\x80\xe7\xe1O-D\x00\x00\u07d4T?\x8cgN$b\xd8\xd5\u06a0\xe8\x01\x95\xa8p\x8e\x11\xa2\x9e\x89\x03wX\x83;:z\x00\x00\xe0\x94TK[5\x1d\x1b\xc8.\x92\x97C\x99H\xcfHa\xda\u026e\x11\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4TM\xdaB\x1d\xc1\xebs\xbb$\xe3\xe5j$\x80\x13\xb8|\x0fD\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4TW\\1\x14u\x1e\x14o\xfe\u00c7nE\xf2\x0e\xe8AJ\u07ba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4T\xb4B\x9b\x18/\x03w\xbe~bi9\xc5\xdbd@\xf7]z\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4T\xbc\xb8\xe7\xf7<\xda=s\xf4\u04cb-\bG\xe6\x00\xba\r\xf8\x89:pAX\x82\xdf\x18\x00\x00\u07d4T\xc9>\x03\xa9\xb2\xe8\xe4\xc3g(5\xa9\xeev\xf9a[\xc1N\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4T\u0388'YV\xde\xf5\xf9E\x8e;\x95\xde\xca\xcdH@!\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4T\xdb^\x06\xb4\x81]1\xcbV\xa8q\x9b\xa3:\xf2\xd7>rR\x89$R\x1e*0\x17\xb8\x00\x00\xe0\x94T\xe0\x12\x83\u030b8E8\xdddgp\xb3W\xc9`\xd6\xca\u034a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4T\xecs\x00\xb8\x1a\xc8C3\xed\x1b\x03<\xd5\u05e39r\xe24\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4T\xfe\xbc\xce \xfez\x90\x98\xa7U\xbd\x90\x98\x86\x02\xa4\x8c\b\x9e\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4U\n\xad\xae\x12!\xb0z\xfe\xa3\x9f\xba.\xd6.\x05\u5df5\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4U\f0o\x81\xef]\x95\x80\xc0l\xb1\xab \x1b\x95\xc7H\xa6\x91\x89$\x17\xd4\xc4p\xbf\x14\x00\x00\xe0\x94U\x19\x99\xdd\xd2\x05V3'\xb9\xb50xZ\xcf\xf9\xbcs\xa4\xba\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4U\x1ew\x84w\x8e\xf8\xe0H\xe4\x95\xdfI\xf2aO\x84\xa4\xf1\u0709 \x86\xac5\x10R`\x00\x00\xe0\x94U)\x83\na\xc1\xf1<\x19~U\v\xed\xdf\u05bd\x19\\\x9d\x02\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4U)\x87\xf0e\x1b\x91[.\x1eS(\xc1!\x96\rK\xddj\xf4\x89a\t=|,m8\x00\x00\u07d4U;k\x1cW\x05\x0e\x88\xcf\f1\x06{\x8dL\xd1\xff\x80\xcb\t\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4U?7\xd9$fU\x0e\x9f\xd7u\xaet6-\xf00\x17\x912\x89lk\x93[\x8b\xbd@\x00\x00\u07d4UC6\xeeN\xa1U\xf9\xf2O\x87\xbc\xa9\xcar\xe2S\xe1,\u0489\x05k\xc7^-c\x10\x00\x00\u0794UC\xddm\x16\x9e\xec\x8a!;\xbfz\x8a\xf9\xff\xd1]O\xf7Y\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4UG\xfd\xb4\xae\x11\x95>\x01)+x\a\xfa\x92#\xd0\xe4`j\x89\x05]\x11}\xcb\x1d&\x00\x00\u07d4UR\xf4\xb3\xed>\x1d\xa7\x9a/x\xbb\x13\xe8\xaeZh\xa9\xdf;\x8965\u026d\xc5\u07a0\x00\x00\u07d4U\\\xa9\xf0\\\xc14\xabT\xae\x9b\xea\x1c?\xf8z\xa8Q\x98\u0289\x05k\xc7^-c\x10\x00\x00\xe0\x94U]\x8d<\xe1y\x8a\u0290'T\xf1d\xb8\xbe*\x022\x9cl\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4U]\xf1\x93\x90\xc1m\x01)\x87r\xba\xe8\xbc:\x11R\x19\x9c\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4U^\xbe\x84\u06a4+\xa2V\xeax\x91\x05\xce\u0136\x93\xf1/\x18\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94U\u007f^e\xe0\xda3\x99\x82\x19\xadN\x99W\x05E\xb2\xa9\xd5\x11\x8a\x02U\x9c\xbb\x98XB@\x00\x00\u07d4U\x83` h\x83\xdd\x1bmJYc\x9eV)\xd0\xf0\xc6u\u0409lk\x93[\x8b\xbd@\x00\x00\u07d4U\x84B0P\xe3\xc2\x05\x1f\v\xbd\x8fD\xbdm\xbc'\xec\xb6,\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4U\x85)CI)p\xf8\xd6)\xa1Sf\xcd\xda\x06\xa9OE\x13\x89lk\x93[\x8b\xbd@\x00\x00\u0794U\x86d\x86\xec\x16\x8fy\xdb\xe0\u1af1\x88d\u0649\x91\xae,\x88\xdfn\xb0\xb2\xd3\xca\x00\x00\u07d4U\x8cTd\x9a\x8an\x94r+\xd6\xd2\x1d\x14qOqx\x054\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\x91\x940O\x14\xb1\xb9:\xfeDO\x06$\xe0S\xc2:\x00\t\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4U\x93\xc9\u0536ds\x0f\xd9<\xa6\x01Q\xc2\\.\xae\xd9<;\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4U\x97\x06\xc32\xd2\ay\xc4_\x8am\x04ji\x91Y\xb7I!\x89\x14\x9bD.\x85\xa3\u03c0\x00\u07d4U\x98\xb3\xa7\x9aH\xf3+\x1f_\xc9\x15\xb8{d]\x80]\x1a\xfe\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4U\xa3\xdfW\xb7\xaa\xec\x16\xa1b\xfdS\x16\xf3[\xec\b(!\u03c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4U\xa4\xca\xc0\u02cbX-\x9f\xef8\xc5\xc9\xff\xf9\xbdS\t=\x1f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4U\xa6\x1b\x10\x94\x80\xb5\xb2\xc4\xfc\xfd\xef\x92\xd9\x05\x84\x16\f\r5\x89\x02lVM+S\xf6\x00\x00\u07d4U\xaa]1>\xbb\bM\xa0\xe7\x80\x10\x91\u2792\xc5\xde\u00ea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\xab\x99\xb0\xe0\xe5]{\xb8t\xb7\xcf\xe84\xdec\x1c\x97\xec#\x897\xe9\x8c\xe3h\x99\xe4\x00\x00\u07d4U\xaf\t/\x94\xbajy\x91\x8b\f\xf99\xea\xb3\xf0\x1b?Q\u01c9\b \xd5\xe3\x95v\x12\x00\x00\u07d4U\xc5dfAf\xa1\xed\xf3\x91>\x01i\xf1\xcdE\x1f\xdb]\f\x89\x82\x17\xeaIP\x8el\x00\x00\xe0\x94U\xcaj\xbey\xea$\x97\xf4o\u06f804`\x10\xfeF\x9c\xbe\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4U\xca\xffK\xba\x04\xd2 \u0265\xd2\x01\x86r\xec\x85\xe3\x1e\xf8>\x89lk\x93[\x8b\xbd@\x00\x00\u07d4U\xd0W\xbc\xc0K\xd0\xf4\xaf\x96BQ:\xa5\t\v\xb3\xff\x93\xfe\x89;\xfeE,\x8e\xddL\x00\x00\u07d4U\xd4.\xb4\x95\xbfF\xa64\x99{_.\xa3b\x81I\x18\u2c09\x05\xc0\xd2e\xb5\xb2\xa8\x00\x00\u07d4U\u069d\xcd\xcaa\xcb\xfe\x1f\x13<{\xce\xfc\x86{\x9c\x81\"\xf9\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4U\xe2 \x87bb\xc2\x18\xafOVxG\x98\xc7\xe5]\xa0\x9e\x91\x89\a=\x99\xc1VE\xd3\x00\x00\u07d4U\xfd\b\u0440d\xbd ,\x0e\xc3\xd2\xcc\xe0\xce\v\x9d\x16\x9cM\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4V\x00s\nU\xf6\xb2\x0e\xbd$\x81\x1f\xaa=\xe9m\x16b\xab\xab\x89e\xea=\xb7UF`\x00\x00\u07d4V\x03$\x1e\xb8\xf0\x8fr\x1e4\x8c\x9d\x9a\xd9/H\u342a$\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4V\x056yJ\x9e+\x00I\xd1\x023\xc4\x1a\xdc_A\x8a&J\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\aY\x00Y\xa9\xfe\xc1\x88\x11I\xa4K6\x94\x9a\xef\x85\xd5`\x89lk\x93[\x8b\xbd@\x00\x00\u07d4V\v\xec\xdfR\xb7\x1f=\x88'\xd9'a\x0f\x1a\x98\x0f3qo\x89\x17GMp_V\u0400\x00\xe0\x94V\r\xa3~\x95m\x86/\x81\xa7_\u0540\xa7\x13\\\x1b$cR\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94V\x0f\xc0\x8d\a\x9f\x04~\xd8\xd7\xdfuU\x1a\xa55\x01\xf5p\x13\x8a\x01\x9b\xff/\xf5yh\xc0\x00\x00\u07d4V\x1b\xe9)\x9b>k>c\xb7\x9b\t\x16\x9d\x1a\x94\x8a\xe6\xdb\x01\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94V \xe3\xedy-/\x185\xfe_UA}Q\x11F\fj\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4V \xf4m\x14Q\xc25=bC\xa5\u0534'\x13\v\xe2\xd4\a\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94V!\x05\xe8+\t\x975\xdeI\xf6&\x92\u0307\xcd8\xa8\xed\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94V*\x8d\u02fe\xee\xf7\xb3`h]'0;\u059e\tJ\xcc\xf6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4V+\xce\u04ca\xb2\xabl\b\x0f;\x05A\xb8Enp\x82K?\x89\"\xca5\x87\xcfN\xb0\x00\x00\xe0\x94V+\xe9Z\xba\x17\xc57\x1f\u2e82\x87\x99\xb1\xf5]!w\u058a\b\x16\xd3~\x87\xb9\xd1\xe0\x00\x00\u07d4V/\x16\u05da\xbf\xce\u00d4>4\xb2\x0f\x05\xf9{\xdf\u0366\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4V7=\xaa\xb4c\x16\xfd~\x15v\xc6\x1ej\xff\xcbeY\xdd\u05c9\v\xacq]\x14l\x9e\x00\x00\u07d4V9v8\xbb<\xeb\xf1\xf6 byK^\xb9B\xf9\x16\x17\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4V:\x03\xab\x9cV\xb6\x00\xf6\xd2[f\f!\xe1c5Qzu\x8965\u026d\xc5\u07a0\x00\x00\u07d4V<\xb8\x80<\x1d2\xa2['\xb6A\x14\x85+\xd0M\x9c \u0349\v\x14\x9e\xad\n\xd9\xd8\x00\x00\u07d4VXc\x91\x04\fW\xee\xc6\xf5\xaf\xfd\x8c\u052b\xde\x10\xb5\n\u0309\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Vl\x10\xd68\u8e0bG\xd6\xe6\xa4\x14Iz\xfd\xd0\x06\x00\u0509\x05k9Bc\xa4\f\x00\x00\u07d4Vl(\xe3L8\b\xd9vo\xe8B\x1e\xbfO+\x1cO}w\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4V\x8d\xf3\x18Vi\x9b\xb5\xac\xfc\x1f\xe1\u0580\u07d9`\xcaCY\x89J\xcfUR\xf3\xb2I\x80\x00\u07d4V\x91\xdd/gE\xf2\x0e\"\xd2\xe1\u0479U\xaa)\x03\xd6VV\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4V\xa1\xd6\r@\xf5\u007f0\x8e\xeb\xf0\x87\xde\xe3\xb3\u007f\x1e|,\xba\x89>\u072e\xc8-\x06\xf8\x00\x00\u07d4V\xac \xd6;\xd8\x03Y\\\xec\x03m\xa7\xed\x1d\xc6n\n\x9e\a\x89\x03w*S\xcc\xdce\x80\x00\u07d4V\xb6\xc2=\xd2\uc434r\x8f;\xb2\xe7d\xc3\xc5\f\x85\xf1D\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\xdf\x05\xba\xd4l?\x00\xaeGn\xcf\x01{\xb8\xc8w8?\xf1\x89\n\xb1]\xaa\xefp@\x00\x00\u07d4V\xee\x19\u007fK\xbf\x9f\x1b\x06b\xe4\x1c+\xbd\x9a\xa1\xf7\x99\xe8F\x8965\u026d\xc5\u07a0\x00\x00\u07d4V\xf4\x93\xa3\xd1\b\xaa\xa2\u044d\x98\x92/\x8e\xfe\x16b\u03f7=\x89m\x81!\xa1\x94\xd1\x10\x00\x00\u07d4V\xfc\x1a{\xad@G#|\xe1\x16\x14b\x96#\x8e\a\x8f\x93\xad\x89\t\xa6?\b\xeac\x88\x00\x00\u07d4V\xfe\xbf\x9e\x10\x03\xaf\x15\xb1\xbdI\a\xec\b\x9aJ\x1b\x91\xd2h\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4W\x17\u0313\x01Q\x1dJ\x81\xb9\xf5\x83\x14\x8b\xee\xd3\xd3\u0303\t\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4W\x17\xf2\xd8\xf1\x8f\xfc\xc0\xe5\xfe$}:B\x19\x03|:d\x9c\x89\u063beI\xb0+\xb8\x00\x00\u07d4W\x19P\xea,\x90\xc1B}\x93\x9da\xb4\xf2\xdeL\xf1\u03ff\xb0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4W\x19\xf4\x9br\r\xa6\x88V\xf4\xb9\xe7\b\xf2VE\xbd\xbcKA\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4W*\xc1\xab\xa0\xde#\xaeA\xa7\xca\xe1\xdc\bB\u062b\xfc\x10;\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94W-\xd8\xcd?\xe3\x99\xd1\xd0\xec(\x121\xb7\xce\xfc \xb9\u4eca\x023\xc8\xfeBp>\x80\x00\x00\xe0\x94WI!\x83\x8c\xc7}l\x98\xb1}\x90::\xe0\xee\r\xa9[\u040a\vS(\x17\x8a\xd0\xf2\xa0\x00\x00\u07d4WJ\xd95S\x90\u421e\xf4*\xcd\x13\x8b*'\xe7\x8c\x00\xae\x89Tg\xb72\xa9\x134\x00\x00\u07d4WM\xe1\xb3\xf3\x8d\x91XF\xae7\x18VJZ\xda \xc2\xf3\xed\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94W\\\x00\u0081\x82\x10\u0085U\xa0\xff)\x01\x02\x89\xd3\xf8#\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94Ws\xb6\x02g!\xa1\xdd\x04\xb7\x82\x8c\xd6+Y\x1b\xfb4SL\x8a\x05\xb7\xacES\xdez\xe0\x00\x00\xe0\x94WwD\x1c\x83\xe0?\v\xe8\xdd4\v\xdechP\x84|b\v\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4Wx\xff\u071b\x94\u0165\x9e\"N\xb9e\xb6\u0790\xf2\"\xd1p\x89\x12-\u007f\xf3f\x03\xfc\x00\x00\u07d4Wz\xee\xe8\u053c\b\xfc\x97\xab\x15n\xd5\u007f\xb9p\x92Sf\xbe\x89\x12\r\xf1\x14rX\xbf\x00\x00\u07d4W{-\a\xe9\xcfRJ\x18\u04c9\x15Vak\x96\x06g\x00\x00\u07d4W\xd5\xfd\x0e=0I3\x0f\xfc\xdc\xd0 Ei\x17e{\xa2\u0689k\xf2\x01\x95\xf5T\xd4\x00\x00\u07d4W\u0754q\xcb\xfa&'\t\xf5\U00106f37t\xc5\xf5'\xb8\xf8\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4W\xdf#\xbe\xbd\xc6^\xb7_\ub732\xfa\xd1\xc0si++\xaf\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4X\x00\u03410\x83\x9e\x94I]-\x84\x15\xa8\xea,\x90\xe0\xc5\u02c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94X\x03\xe6\x8b4\xda\x12\x1a\xef\b\xb6\x02\xba\u06ef\xb4\xd1$\x81\u028a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\xe0\x94X\x16\xc2hww\xb6\xd7\u04a2C-Y\xa4\x1f\xa0Y\xe3\xa4\x06\x8a\x1cO\xe4:\xdb\n^\x90\x00\x00\u07d4X\x1a:\xf2\x97\xef\xa4Cj)\xaf\x00r\x92\x9a\xbf\x98&\xf5\x8b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\x1b\x9f\xd6\xea\xe3r\xf3P\x1fB\xeb\x96\x19\xee\xc8 \xb7\x8a\x84\x8a\x04+\xe2\xc0\f\xa5;\x8d\x80\x00\u07d4X\x1b\xdf\x1b\xb2v\xdb\u0746\xae\xdc\xdb9z\x01\xef\xc0\xe0\f[\x8965\u026d\xc5\u07a0\x00\x00\u07d4X\x1f4\xb5#\xe5\xb4\x1c\t\xc8|)\x8e)\x9c\xbc\x0e)\xd0f\x89=X3\xaa\xfd9u\x80\x00\xe0\x94X$\xa7\xe2(8'q40\x8c_KP\u06b6^C\xbb1\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4X+pf\x9c\x97\xaa\xb7\u0581H\xd8\xd4\xe9\x04\x11\xe2\x81\rV\x8965f3\xeb\xd8\xea\x00\x00\u07d4X.|\xc4o\x1d{Nn\x9d\x95\x86\x8b\xfd7\x05s\x17\x8fL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4X>\x83\xbaU\xe6~\x13\xe0\xe7o\x83\x92\xd8s\xcd!\xfb\xf7\x98\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Xi\xfb\x86}q\xf18\u007f\x86;i\x8d\t\xfd\xfb\x87\u011b\\\x89\u01bb\xf8X\xb3\x16\b\x00\x00\u07d4X}hI\xb1h\xf6\xc33+z\xba\xe7\xeblB\xc3\u007fH\xbf\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4X\x87\xdcj3\xdf\xedZ\xc1\xed\xef\xe3^\xf9\x1a!b1\xac\x96\x89\r\x8drkqw\xa8\x00\x00\xe0\x94X\x8e\u0650\xa2\xaf\xf4J\x94\x10]X\xc3\x05%w5\xc8h\xac\x8a\x03h\xc8b:\x8bM\x10\x00\x00\u07d4X\xae-\xdc_L\x8a\u0697\xe0l\x00\x86\x17\x17g\xc4#\xf5\u05c9WG=\x05\u06ba\xe8\x00\x00\u07d4X\xae\xd6gJ\xff\xd9\xf6B3'*W\x8d\xd98k\x99\xc2c\x89\xb8Pz\x82\a( \x00\x00\xe0\x94X\xb8\b\xa6[Q\xe63\x89i\xaf\xb9^\xc7\a5\xe4Q\xd5&\x8a\bxK\xc1\xb9\x83z8\x00\x00\u07d4X\xb8\xae\x8fc\xef5\xed\ab\xf0\xb6#=J\xc1Nd\xb6M\x89lk\x93[\x8b\xbd@\x00\x00\u07d4X\xba\x15ie\x0e[\xbb\xb2\x1d5\xd3\xe1u\xc0\u05b0\xc6Q\xa9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4X\xc5U\xbc)<\xdb\x16\xc66.\xd9z\xe9U\v\x92\xea\x18\x0e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4X\xc6P\xce\xd4\v\xb6VA\xb8\xe8\xa9$\xa09\xde\xf4hT\u07c9\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4X\xc9\aT\xd2\xf2\n\x1c\xb1\xdd3\x06%\xe0KE\xfaa\x9d\\\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\xe2\xf1\x12#\xfc\x827\xf6\x9d\x99\xc6(\x9c\x14\x8c\x06\x04\xf7B\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4X\xe5T\xaf=\x87b\x96 \xdaa\xd58\xc7\xf5\xb4\xb5LJ\xfe\x89FP\x9diE4r\x80\x00\u07d4X\xe5\xc9\xe3D\xc8\x06e\r\xac\xfc\x90M3\xed\xbaQ\a\xb0\u0789\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4X\xe6a\u043as\xd6\xcf$\t\x9aUb\xb8\b\xf7\xb3g;h\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94X\xf0[&%`P<\xa7a\xc6\x18\x90\xa4\x03_Lsr\x80\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4X\xfb\x94sd\xe7iWe6\x1e\xbb\x1e\x80\x1f\xfb\x8b\x95\xe6\u0409\n\u05ce\xbcZ\xc6 \x00\x00\u07d4Y\x01\x81\xd4E\x00{\u0407Z\xaf\x06\x1c\x8dQ\x159\x00\x83j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y\x02\xe4J\xf7i\xa8rF\xa2\x1e\a\x9c\b\xbf6\xb0n\xfe\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4Y\n\xcb\xda7)\f\r>\xc8O\xc2\x00\rv\x97\xf9\xa4\xb1]\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94Y\f\xcbY\x11\xcfx\xf6\xf6\"\xf55\xc4t7_J\x12\xcf\u03ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y\x10\x10m\xeb\u0491\xa1\u0340\xb0\xfb\xbb\x8d\x8d\x9e\x93\xa7\xcc\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Y\x16\x17I\xfe\xdc\xf1\xc7!\xf2 -\x13\xad\xe2\xab\xcfF\v=\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94Y\x1b\xef1q\xd1\u0155w\x17\xa4\xe9\x8d\x17\xeb\x14,!NV\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y <\xc3u\x99\xb6H1*|\xc9\xe0m\xac\xb5\x89\xa9\xaej\x89\b\x0fyq\xb6@\x0e\x80\x00\u07d4Y&\x81q\xb83\xe0\xaa\x13\xc5KR\xcc\xc0B.O\xa0:\ub262\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94Y'w&\x1e;\xd8R\u010e\u0295\xb3\xa4L[\u007f-B,\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4Y0Dg\x0f\xae\xff\x00\xa5[Z\xe0Q\xeb{\xe8p\xb1\x16\x94\x89\a?u\u0460\x85\xba\x00\x00\xe0\x94Y;E\xa1\x86J\xc5\xc7\xe8\xf0\u02ae\xba\r\x87<\xd5\xd1\x13\xb2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Y_^\xdajV\xf1N%\xe0\xc6\xf3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4Z\x1a3ib\xd6\xe0\xc601\u0303\u01a5\u01a6\xf4G\x8e\u02c965\u026d\xc5\u07a0\x00\x00\u07d4Z\x1d--\x1dR\x03\x04\xb6 \x88IW\x047\xeb0\x91\xbb\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4Z&s1\xfa\xcb&-\xaa\xec\xd9\xddc\xa9p\f_RY\u07c9\x05k\xc7^-c\x10\x00\x00\xe0\x94Z(WU9\x1e\x91NX\x02_\xaaH\xcch_O\xd4\xf5\xb8\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4Z)\x16\xb8\xd2\xe8\xcc\x12\xe2\a\xabFMC>#p\xd8#\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4Z+\x1c\x85:\xeb(\xc4U9\xafv\xa0\n\xc2\u0628$(\x96\x89\x01Z\xf1\u05cbX\xc4\x00\x00\u07d4Z-\xaa\xb2\\1\xa6\x1a\x92\xa4\xc8,\x99%\xa1\xd2\xefXX^\x89\f8\r\xa9\u01d5\f\x00\x00\u07d4Z0\xfe\xac7\xac\x9fr\u05f4\xaf\x0f+\xc79R\xc7O\xd5\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4ZTh\xfa\\\xa2&\xc7S.\xcf\x06\xe1\xbc\x1cE\"]~\u0249g\x8a\x93 b\xe4\x18\x00\x00\u07d4ZVR\x857JI\xee\xddPL\x95}Q\bt\xd0\x04U\xbc\x89\x05k\xc7^-c\x10\x00\x00\u07d4Z^\xe8\xe9\xbb\x0e\x8a\xb2\xfe\xcbK3\u0494x\xbeP\xbb\xd4K\x89*\x11)\u0413g \x00\x00\xe0\x94Z_\x85\b\xda\x0e\xbe\xbb\x90\xbe\x903\xbdM\x9e'A\x05\xae\x00\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4Z`q\xbc\xeb\xfc\xbaJ\xb5\u007fM\xb9o\u01e6\x8b\xec\xe2\xba[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z`\xc9$\x16(s\xfc~\xa4\xda\u007f\x97.5\x01g7`1\x89\x04\x87\xf2w\xa8\x85y\x80\x00\u07d4Zf\x86\xb0\xf1~\a\xed\xfcY\xb7Y\xc7}[\xef\x16M8y\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4Zp\x10o \xd6?\x87Re\xe4\x8e\r5\xf0\x0e\x17\xd0+\u0249\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794Zt\xbab\xe7\xc8\x1a4t\xe2}\x89O\xed3\xdd$\xad\x95\xfe\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94Zw5\x00}p\xb0hD\u0699\x01\xcd\xfa\xdb\x11\xa2X,/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4Z\x82\xf9l\u0537\xe2\xd9=\x10\xf3\x18]\xc8\xf4=Ku\xaai\x89lc?\xba\xb9\x8c\x04\x00\x00\u07d4Z\x87\xf04\xe6\xf6\x8fNt\xff\xe6\fd\x81\x946\x03l\xf7\u05c9\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94Z\x89\x11U\xf5\x0eB\aCt\xc79\xba\xad\xf7\xdf&Q\x15:\x8a\x01\x02\xdao\xd0\xf7:<\x00\x00\u07d4Z\x9c\x8bi\xfcaMiVI\x99\xb0\r\xcbB\xdbg\xf9~\x90\x89\xb9\xe6\x15\xab\xad:w\x80\x00\xe0\x94Z\xaf\x1c1%Jn\x00_\xba\u007fZ\xb0\xecy\xd7\xfc+c\x0e\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4Z\xb1\xa5aSH\x00\x1c|w]\xc7WHf\x9b\x8b\xe4\xde\x14\x89%jr\xfb)\xe6\x9c\x00\x00\xe1\x94Z\xbf\xec%\xf7L\u06047c\x1aw1\x90i2wcV\xf9\x8b\t\xd8<\xc0\u07e1\x11w\xff\x80\x00\u07d4Z\u0090\x8b\x0f9\x8c\r\xf5\xba\xc2\xcb\x13\xcas\x14\xfb\xa8\xfa=\x89\n\xd4\xc81j\v\f\x00\x00\xe0\x94Z\u025a\u05c1j\xe9\x02\x0f\xf8\xad\xf7\x9f\xa9\x86\x9b|\xeaf\x01\x8a\x04ri\x8bA;C \x00\x00\u07d4Z\xd1,^\xd4\xfa\x82~!P\u03e0\u058c\n\xa3{\x17i\xb8\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94Z\xd5\xe4 uV\x13\x88o5\xaaV\xac@>\xeb\xdf\xe4\xb0\u040a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4Z\xdew\xfd\x81\xc2\\\n\xf7\x13\xb1\a\x02v\x8c\x1e\xb2\xf9u\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4Z\xe6N\x85;\xa0\xa5\x12\x82\u02cd\xb5.Aa^|\x9fs?\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z\xed\x0el\xfe\x95\xf9\u0580\xc7dr\xa8\x1a+h\n\u007f\x93\xe2\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4Z\xef\x16\xa2&\xddh\a\x1f$\x83\xe1\xdaBY\x83\x19\xf6\x9b,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4Z\xf4j%\xac\t\xcbsakS\xb1O\xb4/\xf0\xa5\x1c\u0772\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4Z\xf7\xc0r\xb2\u016c\xd7\x1cv\xad\xdc\xceS\\\xf7\xf8\xf95\x85\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94Z\xfd\xa9@\\\x8e\x976QEt\u0692\x8d\xe6tV\x01\t\x18\x8a\x01E\xb8\xb0#\x9aF\x92\x00\x00\u07d4[\x06\xd1\xe6\x93\f\x10Ti+y\xe3\xdb\xe6\xec\xceS\x96d \x89\v\"\u007fc\xbe\x81<\x00\x00\u07d4[%\xca\xe8m\xca\xfa*`\xe7r61\xfc_\xa4\x9c\x1a\xd8}\x89\x87\fXQ\x0e\x85 \x00\x00\u07d4[(|~sB\x99\xe7'bo\x93\xfb\x11\x87\xa6\rPW\xfe\x89\x05|\xd94\xa9\x14\xcb\x00\x00\u07d4[)\f\x01\x96|\x81.M\xc4\xc9\v\x17L\x1b@\x15\xba\xe7\x1e\x89\b \xeb4\x8dR\xb9\x00\x00\u07d4[+d\xe9\xc0X\u30a8\xb2\x99\"N\xec\xaa\x16\xe0\x9c\x8d\x92\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\xe0\x94[./\x16\x18U.\xab\r\xb9\x8a\xddUc|)Q\xf1\xfb\x19\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4[0`\x8cg\x8e\x1a\xc4d\xa8\x99L;3\xe5\xcd\xf3Iq\x12\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4[36\x96\xe0L\xca\x16\x92\xe7\x19\x86W\x9c\x92\rk)\x16\xf9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94[C\rw\x96\x96\xa3e?\xc6\x0et\xfb\u02ec\xf6\xb9\u00ba\xf1\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4[Cse\xae:\x9a/\xf9|h\xe6\xf9\nv \x18\x8c}\x19\x89l\x87T\xc8\xf3\f\b\x00\x00\u07d4[I\xaf\xcduDx8\xf6\xe7\xce\u068d!w}O\xc1\xc3\xc0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4[L\f`\xf1\x0e\u0489K\xdbB\xd9\xdd\x1d!\x05\x87\x81\n\r\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4[N\xa1m\xb6\x80\x9b\x03R\u0536\xe8\x1c9\x13\xf7jQ\xbb2\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4[[\xe0\xd8\xc6rv\xba\xab\xd8\xed\xb3\rH\xeaud\v\x8b)\x89,\xb1\xf5_\xb7\xbe\x10\x00\x00\u07d4[]Qp)2\x15b\x11\x1bC\bm\v\x045\x91\x10\x9ap\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\xe0\x94[]\x8c\x8e\xedl\x85\xac!Va\xde\x02fv\x82?\xaa\n\f\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4[mU\xf6q)g@\\e\x91)\xf4\xb1\xde\t\xac\xf2\xcb{\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4[p\u011c\u024b=\xf3\xfb\xe2\xb1Y\u007f\\\x1bcG\xa3\x88\xb7\x894\x95tD\xb8@\xe8\x00\x00\u07d4[sn\xb1\x83Sb\x9b\u0796v\xda\xdd\x16P4\xce^\xcch\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4[u\x9f\xa1\x10\xa3\x1c\x88F\x9fT\xd4K\xa3\x03\xd5}\xd3\xe1\x0f\x89[F\xdd/\x0e\xa3\xb8\x00\x00\u07d4[w\x84\xca\xea\x01y\x9c\xa3\x02'\x82vg\xce |\\\xbcv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4[x\xec\xa2\u007f\xbd\xeao&\xbe\xfb\xa8\x97+)^x\x146K\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94[\x80\v\xfd\x1b>\u0525}\x87Z\xed&\xd4/\x1aw\b\xd7*\x8a\x01Z\x82\xd1\u057b\x88\xe0\x00\x00\u07d4[\x85\xe6\x0e*\xf0TO/\x01\xc6N 2\x90\x0e\xbd8\xa3\u01c9lk\x93[\x8b\xbd@\x00\x00\u07d4[\xa2\xc6\xc3]\xfa\xec)h&Y\x19\x04\xd5DFJ\xea\xbd^\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94[\xafmt\x96 \x80>\x83H\xaf7\x10\xe5\xc4\xfb\xf2\x0f\u0214\x8a\x01\x0f@\x02a]\xfe\x90\x00\x00\u07d4[\xc1\xf9U\a\xb1\x01\x86B\xe4\\\xd9\xc0\xe2'3\xb9\xb1\xa3&\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94[\xd25GG\u007fm\t\u05f2\xa0\x05\xc5\xeee\fQ\fV\u05ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4[\xd2J\xac6\x12\xb2\f`\x9e\xb4gy\xbf\x95i\x84\a\xc5|\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4[\u0586-Q}M\xe4U\x9dN\xec\n\x06\xca\xd0^/\x94n\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4[\xe0EQ*\x02n?\x1c\xeb\xfdZ~\xc0\xcf\xc3o-\xc1k\x89\x06\x81U\xa46v\xe0\x00\x00\xe0\x94[\xf9\xf2\"nZ\xea\xcf\x1d\x80\xae\nY\xc6\xe3\x808\xbc\x8d\xb5\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4[\xfa\xfe\x97\xb1\xdd\x1dq+\xe8mA\xdfy\x89SE\x87Z\x87\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\\\x0f.Q7\x8fk\r{\xabas1X\vn9\xad<\xa5\x8a\x02\bj\xc3Q\x05&\x00\x00\x00\u07d4\\)\xf9\xe9\xa5#\xc1\xf8f\x94H\xb5\\H\xcb\xd4|%\xe6\x10\x894F\xa0\xda\xd0L\xb0\x00\x00\xe0\x94\\0\x8b\xacHW\xd3;\xae\xa0t\xf3\x95m6!\xd9\xfa(\xe1\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\\1*V\u01c4\xb1\"\t\x9bvM\x05\x9c!\xec\xe9^\x84\u0289\x05&c\u032b\x1e\x1c\x00\x00\u07d4\\1\x99m\xca\xc0\x15\xf9\xbe\x98[a\x1fF\x870\xef$M\x90\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\\24W\xe1\x87v\x1a\x82v\xe3Y\xb7\xb7\xaf?;n=\xf6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\\<\x1cd[\x91uC\x11;>l\x1c\x05M\xa1\xfet+\x9a\x89+^:\xf1k\x18\x80\x00\x00\u0794\\=\x19D\x1d\x19l\xb4Cf \xfc\xad\u007f\xbby\xb2\x9ex\x88\xc6s\xce<@\x16\x00\x00\u07d4\\?V\u007f\xaf\xf7\xba\u0475\x12\x00\"\xe8\xcb\u02a8+I\x17\xb3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\\Ch\x91\x8a\xced\t\u01de\u0280\u036a\xe49\x1d+bN\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\\FA\x97y\x1c\x8a=\xa3\xc9%Co'z\xb1;\xf2\xfa\xa2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\\H\x81\x16\\\xb4+\xb8.\x979l\x8e\xf4J\xdb\xf1s\xfb\x99\x89\x05\xfe\xe2\"\x04\x1e4\x00\x00\xe0\x94\\H\x92\x90z\a \xdfo\xd3A>c\xffv}k9\x80#\x8a\x02\xcb\x00\x9f\u04f5y\x0f\x80\x00\u07d4\\O$\xe9\x94\ud3c5\x0e\xa7\x81\x8fG\x1c\x8f\xac;\xcf\x04R\x89]\x80h\x8d\x9e1\xc0\x00\x00\u07d4\\T\x19V\\:\xadNqN\a92\x8e5!\u024f\x05\u0309\x1c\x9fx\u0489>@\x00\x00\u07d4\\a6\xe2\x18\xde\na\xa17\xb2\xb3\x96-*a\x12\xb8\t\u05c9\x0f\xf3\u06f6_\xf4\x86\x80\x00\xe0\x94\\a\xaby\xb4\b\xdd2)\xf6bY7\x05\xd7/\x1e\x14{\xb8\x8a\x04\xd0$=4\x98\u0344\x00\x00\u07d4\\m\x04\x1d\xa7\xafD\x87\xb9\xdcH\xe8\xe1\xf6\af\u0425m\xbc\x89O\a\n\x00>\x9ct\x00\x00\u07d4\\o6\xaf\x90\xab\x1aeln\xc8\xc7\xd5!Q'b\xbb\xa3\xe1\x89lh\xcc\u041b\x02,\x00\x00\u07d4\\{\x9e\u01e2C\x8d\x1eD*\x86\x0f\x8a\x02\x1e\x18\x99\xf07z\xea\x00\x00\u07d4\\\xcc\xf1P\x8b\xfd5\xc2\x050\xaad%\x00\xc1\r\xeee\xea\xed\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\\\xcer\xd0h\xc7\xc3\xf5[\x1d(\x19T^w1|\xae\x82@\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\\\xd0\xe4u\xb5D!\xbd\xfc\f\x12\xea\x8e\b+\u05e5\xaf\nj\x89\x032\xca\x1bg\x94\f\x00\x00\u07d4\\\u0548\xa1N\xc6H\xcc\xf6G)\xf9\x16z\xa7\xbf\x8b\xe6\xeb=\x8965\u026d\xc5\u07a0\x00\x00\u07d4\\\u062f`\xdee\xf2M\xc3\xceW0\xba\x92e0\"\xdcYc\x89a\t=|,m8\x00\x00\u07d4\\\xdcG\b\xf1O@\xdc\xc1Zy_}\xc8\xcb\v\u007f\xaa\x9en\x89\x1d\x1c_>\xda \xc4\x00\x00\u07d4\\\u0d86,\u0391b\xe8~\bI\xe3\x87\xcb]\xf4\xf9\x11\x8c\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\\\xe2\xe7\u03aa\xa1\x8a\xf0\xf8\xaa\xfa\u007f\xba\xd7L\u021e<\xd46\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\\\xe4@h\xb8\xf4\xa3\xfey\x9ej\x83\x11\xdb\xfd\xed\xa2\x9d\xee\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u0794\\\xeb\xe3\v*\x95\xf4\xae\xfd\xa6ee\x1d\xc0\xcf~\xf5u\x81\x99\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\\\xf1\x8f\xa7\u0227\xc0\xa2\xb3\xd5\xef\u0459\x0fd\xdd\xc5i$,\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\\\xf4N\x10T\reqd#\xb1\xbc\xb5B\xd2\x1f\xf8:\x94\u034a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\\\xf8\xc0>\xb3\xe8r\xe5\x0f|\xfd\f/\x8d;?,\xb5\x18:\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\\\xfa\x8dV\x85ue\x8c\xa4\xc1\xa5\x93\xacL]\x0eD\xc6\aE\x89\x0f\xc6o\xae7F\xac\x00\x00\u07d4\\\xfa\x98w\xf7\x19\u01dd\x9eIJ\b\xd1\xe4\x1c\xf1\x03\xfc\x87\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4]\x1d\xc38{G\xb8E\x1eU\x10l\f\xc6}m\xc7+\u007f\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4]#\x1ap\xc1\xdf\xeb6\n\xbd\x97\xf6\x16\xe2\xd1\r9\xf3\u02b5\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4]$\xbd\xbc\x1cG\xf0\xeb\x83\xd1(\xca\xe4\x8a\xc3\xf4\xb5\x02bt\a\xda'/g\x81Jk\xec\u0509\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4]\x83\xb2\x1b\xd2q#`Ckg\xa5\x97\xee3x\xdb>z\xe4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94]\x87+\x12.\x99N\xf2|q\xd7\u07b4W\xbfeB\x9e\xcal\x8a\x01\xb1\xad\xed\x81\u04d4\x10\x80\x00\xe0\x94]\x8d1\xfa\xa8d\xe2!Y\xcdoQu\xcc\xec\xc5?\xa5Mr\x8a\x05\xb6\x96\xb7\r\xd5g\x10\x00\x00\xe0\x94]\x95\x8a\x9b\u0449\u0098_\x86\u014a\x8ci\xa7\xa7\x88\x06\xe8\u068a\x02(\xf1o\x86\x15x`\x00\x00\u07d4]\xa2\xa9\xa4\xc2\xc0\xa4\xa9$\xcb\xe0\xa5:\xb9\xd0\xc6'\xa1\u03e0\x89'\xbf8\xc6TM\xf5\x00\x00\u07d4]\xa4\u0288\x93\\'\xf5\\1\x10H\x84\x0eX\x9e\x04\xa8\xa0I\x89\x04V9\x18$O@\x00\x00\u07d4]\xa5G\x85\u027d0W\\\x89\u07b5\x9d A\xd2\n9\xe1{\x89j\xa2\t\xf0\xb9\x1de\x80\x00\xe0\x94]\xb6\x9f\xe9>o\xb6\xfb\xd4P\x96k\x97#\x8b\x11\n\xd8'\x9a\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4]\xb7\xbb\xa1\xf9W?$\x11]\x8c\x8cb\xe9\u0388\x95\x06\x8e\x9f\x89\x02\xb5\xaa\xd7,e \x00\x00\xe0\x94]\xb8D\x00W\x00i\xa9W<\xab\x04\xb4\u6d955\xe2\x02\xb8\x8a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4]\xc3m\xe55\x94P\xa1\xec\t\xcb\fD\xcf+\xb4+:\xe45\x89<\x94m\x89;3\x06\x00\x00\u07d4]\xc6\xf4_\xef&\xb0n3\x021?\x88M\xafH\xe2to\xb9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94]\u0376\xb8zP\xa9\xde\x02C\x80\x00\x00\u07d4^Q\xb8\xa3\xbb\t\xd3\x03\xea|\x86\x05\x15\x82\xfd`\x0f\xb3\xdc\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794^X\xe2U\xfc\x19\x87\n\x040_\xf2\xa0F1\xf2\xff)K\xb1\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4^ZD\x19t\xa8=t\u0187\xeb\xdcc?\xb1\xa4\x9e{\x1a\u05c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^eE\x8b\xe9d\xaeD\x9fqw7\x04\x97\x97f\xf8\x89\x87a\x89\x1c\xa7\xccs[o|\x00\x00\u07d4^g\u07c9i\x10\x1a\u06bd\x91\xac\xcdk\xb1\x99\x12t\xaf\x8d\xf2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4^n\x97G\xe1b\xf8\xb4\\en\x0fl\xaez\x84\xba\xc8\x0eN\x89lk\x93[\x8b\xbd@\x00\x00\u07d4^s\x1bU\xce\xd4R\xbb??\xe8q\xdd\xc3\xed~\xe6Q\n\x8f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^t\xed\x80\xe9eW\x88\xe1\xbb&\x97R1\x96g\xfeuNZ\x89\x03\t'\xf7L\x9d\xe0\x00\x00\u07d4^w.'\xf2\x88\x00\xc5\r\u0697;\xb3>\x10v.n\xea \x89a\t=|,m8\x00\x00\u07d4^{\x8cT\xdcW\xb0@ bq\x9d\xee~\xf5\xe3~\xa3]b\x89\x9b\xf9\x81\x0f\xd0\\\x84\x00\x00\u07d4^\u007fp7\x87uX\x9f\xc6j\x81\xd3\xf6S\xe9T\xf5U`\ub243\xf2\x89\x18\x1d\x84\xc8\x00\x00\xe0\x94^\x80n\x84W0\xf8\a>l\xc9\x01\x8e\xe9\x0f\\\x05\xf9\t\xa3\x8a\x02\x01\xe9m\xac\u03af \x00\x00\u07d4^\x8eM\xf1\x8c\xf0\xafw\tx\xa8\u07cd\xac\x90\x93\x15\x10\xa6y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4^\x90\xc8Xw\x19\x87V\xb06l\x0e\x17\xb2\x8eR\xb4FPZ\x89\x14JJ\x18\xef\xebh\x00\x00\u07d4^\x95\xfe_\xfc\xf9\x98\xf9\xf9\xac\x0e\x9a\x81\u06b8>\xadw\x00=\x89\x1dB\xc2\r2y\u007f\x00\x00\u07d4^\xad)\x03z\x12\x89dx\xb1)j\xb7\x14\xe9\u02d5B\x8c\x81\x89\x03\xe0C\a-@n\x00\x00\u07d4^\xb3q\xc4\a@lB{;}\xe2q\xad<\x1e\x04&\x95y\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4^\u037a\xea\xb9\x10o\xfe]{Q\x96\x96`\x9a\x05\xba\ub16d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4^\xd0\xd63\x85Y\xefD\xdcza\xed\xeb\x89?\xa5\xd8?\xa1\xb5\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\xe0\x94^\u04fb\xc0R@\xe0\u04d9\xebm\xdf\xe6\x0fb\xdeM\x95\t\xaf\x8a)\x14\xc0$u\xf9\xd6\xd3\x00\x00\u0594^\xd3\xf1\xeb\xe2\xaegV\xb5\xd8\xdc\x19\xca\xd0,A\x9a\xa5w\x8b\x80\u07d4^\xd5a\x15\xbde\x05\xa8\x82s\xdf\\V\x83\x94p\xd2J-\xb7\x89\x03\x8ee\x91\xeeVf\x80\x00\xe0\x94^\xf8\xc9a\x86\xb3y\x84\xcb\xfe\x04\u0158@n;\n\xc3\x17\x1f\x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4^\xfb\xdf\xe58\x99\x99c<&`Z[\xfc,\x1b\xb5\x95\x93\x93\x89\x03\xc0W\xc9\\\xd9\b\x00\x00\xe0\x94_\x13\x15F1Fm\xcb\x13S\u0210\x93*|\x97\xe0\x87\x8e\x90\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4_\x16z\xa2B\xbcL\x18\x9a\xde\xcb:\u0127\xc4R\xcf\x19/\u03c9lkLM\xa6\u077e\x00\x00\xe0\x94_\x1c\x8a\x04\xc9\rs[\x8a\x15)\t\xae\xaeco\xb0\xce\x16e\x8a\x01{x'a\x8cZ7\x00\x00\u07d4_#\xba\x1f7\xa9lE\xbcI\x02YS\x8aT\u008b\xa3\xb0\u0549A\rXj \xa4\xc0\x00\x00\u07d4_&\xcf4Y\x9b\xc3n\xa6{\x9ez\x9f\x9bC0\xc9\xd5B\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4_)\xc9\xdev]\xde%\x85*\xf0}3\xf2\xceF\x8f\xd2\t\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_/\a\xd2\u0597\xe8\xc5g\xfc\xfd\xfe\x02\x0fI\xf3`\xbe!9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_2\x1b=\xaa\xa2\x96\xca\xdf)C\x9f\x9d\xab\x06*K\xff\xed\u0589\x04p%\x90>\xa7\xae\x00\x00\u07d4_3:;#\x10vZ\r\x182\xb9\xbeL\n\x03pL\x1c\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4_4K\x01\xc7\x19\x1a2\xd0v*\xc1\x88\xf0\xec-\xd4`\x91\x1d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94_6>\n\xb7G\xe0-\x1b;f\xab\xb6\x9e\xa5<{\xafR:\x8a\x02w\x01s8\xa3\n\xe0\x00\x00\u07d4_7[\x86`\f@\u0328\xb2gkz\x1a\x1d\x16D\xc5\xf5,\x89\x04F\x18\xd7Lb?\x00\x00\u07d4_>\x1eg9\xb0\xc6\"\x00\xe0\n\x006\x91\xd9\xef\xb28\u061f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4_H?\xfb\x8fh\n\xed\xf2\xa3\x8fx3\xaf\xdc\xdeY\xb6\x1eK\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94_J\xceL\x1c\xc13\x91\xe0\x1f\x00\xb1\x98\xe1\xf2\v_\x91\xcb\xf5\x8a\x01\x0f\x0f\xa8\xb9\u04c1\x1a\x00\x00\xe0\x94_R\x12\x82\xe9\xb2x\u070c\x03Lr\xafS\xee)\xe5D=x\x8a\x01as-/\x8f:\xe0\x00\x00\u07d4_h\xa2L~\xb4\x11vgs{39?\xb3\xc2\x14\x8aS\xb6\x89\x02\xce\u0791\x8dE<\x00\x00\u07d4_p\x8e\xaf9\xd8#\x94lQ\xb3\xa3\u9df3\xc0\x03\xe2cA\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4_t.H~:\xb8\x1a\xf2\xf9J\xfd\xbe\x1b\x9b\x8f\\\u0301\xbc\x89u\xc4E\xd4\x11c\xe6\x00\x00\u07d4_t\xed\x0e$\xff\x80\u0672\u0124K\xaa\x99uB\x8c\u05b95\x89\xa1\x8b\xce\xc3H\x88\x10\x00\x00\u07d4_v\xf0\xa3\x06&\x9cx0k=e\r\xc3\xe9\xc3p\x84\xdba\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4_w\xa1\a\xab\x12&\xb3\xf9_\x10\ue0ee\xfcl]\xff>\u0709\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4_{;\xba\xc1m\xab\x83\x1aJ\x0f\xc5;\fT\x9d\xc3l1\u0289i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94_\x93\xff\x83't\xdbQ\x14\xc5[\xb4\xbfD\xcc\U000f53d0?\x8a(\xa9\xc9\x1a&4X)\x00\x00\u07d4_\x96\x16\xc4{Jg\xf4\x06\xb9Z\x14\xfeo\xc2h9o\x17!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4_\x98\x109\xfc\xf5\x02%\xe2\xad\xf7bu!\x12\xd1\xcc&\xb6\xe3\x89\x1b\x1aAj!S\xa5\x00\x00\u07d4_\x99\u070eI\xe6\x1dW\xda\xef`j\xcd\xd9\x1bMp\a2j\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4_\xa6\x1f\x15-\xe6\x125\x16\xc7Q$)y(_yj\u01d1\x89\v\x0f\x11\x97)c\xb0\x00\x00\u07d4_\xa7\xbf\xe0C\x88a'\xd4\x01\x1d\x83V\xa4~\x94yc\xac\xa8\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94_\xa8\xa5Nh\x17lO\xe2\xc0\x1c\xf6q\xc5\x15\xbf\xbd\xd5(\xa8\x8aE\xe1U\xfa\x01\x10\xfa@\x00\x00\u07d4_\xad\x96\x0fk,\x84V\x9c\x9fMG\xbf\x19\x85\xfc\xb2\xc6]\xa6\x8965f3\xeb\xd8\xea\x00\x00\u07d4_\xc6\xc1\x14&\xb4\xa1\xea\xe7\xe5\x1d\xd5\x12\xad\x10\x90\xc6\xf1\xa8[\x89\x93\xfe\\W\xd7\x10h\x00\x00\u07d4_\u0344Th\x96\xdd\b\x1d\xb1\xa3 \xbdM\x8c\x1d\xd1R\x8cL\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4_\u0368G\xaa\xf8\xd7\xfa\x8b\xca\b\x02\x9c\xa2\x84\x91f\xaa\x15\xa3\x89!\u02b8\x12Y\xa3\xbf\x00\x00\u07d4_\xd1\xc3\xe3\x17x'l\xb4.\xa7@\xf5\xea\xe9\xc6A\xdb\xc7\x01\x89\n\x84Jt$\xd9\xc8\x00\x00\u07d4_\xd3\xd6w~\xc2b\n\xe8:\x05R\x8e\xd4%\a-<\xa8\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4_\xd9s\xaf6j\xa5\x15|Te\x9b\u03f2|\xbf\xa5\xac\x15\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4_\xe7w\x03\x80\x8f\x82>l9\x93R\x10\x8b\xdb,R|\xb8|\x89j@v\xcfy\x95\xa0\x00\x00\xe0\x94_\xecI\xc6e\xe6N\xe8\x9d\xd4A\xeet\x05n\x1f\x01\xe9(p\x8a\x01V\x9b\x9es4t\xc0\x00\x00\u07d4_\xf3&\xcd`\xfd\x13k$^)\xe9\bzj\u04e6R\u007f\r\x89e\xea=\xb7UF`\x00\x00\u07d4_\xf9=\xe6\xee\x05L\xadE\x9b-^\xb0\xf6\x87\x03\x89\xdf\xcbt\x89\v\xed\x1d\x02c\xd9\xf0\x00\x00\u07d4`\x06\xe3m\x92\x9b\xf4]\x8f\x16#\x1b\x12j\x01\x1a\xe2\x83\xd9%\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4`!\xe8Z\x88\x14\xfc\xe1\xe8*A\xab\xd1\u04f2\xda\xd2\xfa\xef\xe0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4`8t\n\xe2\x8df\xba\x93\xb0\xbe\bH+2\x05\xa0\xf7\xa0{\x89\x11!a\x85\u009fp\x00\x00\u07d4`?/\xabz\xfbn\x01{\x94v`i\xa4\xb4;8\x96I#\x89Y\xd2\xdb$\x14\u0699\x00\x00\u07d4`B'm\xf2\x98?\xe2\xbcGY\xdc\x19C\xe1\x8f\xdb\xc3Ow\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4`B\xc6D\xba\xe2\xb9o%\xf9M1\xf6x\xc9\r\xc9f\x90\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4`L\xdf\x18b\x8d\xbf\xa82\x91\x94\xd4x\xddR\x01\xee\xccK\xe7\x89\x01?0j$\t\xfc\x00\x00\u07d4`N\x94w\xeb\xf4r|t[\u02bb\xed\xcbl\xcf)\x99@\"\x8966\x9e\xd7t}&\x00\x00\u07d4`gm\x1f\xa2\x1f\xca\x05\"\x97\xe2K\xf9c\x89\u0171*p\u05c9\r\x17|Zzh\xd6\x00\x00\u07d4`gn\x92\u044b\x00\x05\t\xc6\x1d\xe5@\xe6\xc5\u0776v\xd5\t\x89A\rXj \xa4\xc0\x00\x00\u07d4`o\x17q!\xf7\x85\\!\xa5\x06#0\xc8v\"d\xa9{1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4`\x86B6\x93\r\x04\xd8@+]\xcb\xeb\x80\u007f<\xafa\x1e\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4`\xabq\xcd&\xeamnY\xa7\xa0\xf6'\xee\a\x9c\x88^\xbb\xf6\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4`\xaf\x0e\xe1\x18D<\x9b7\xd2\xfe\xadw\xf5\xe5!\u07be\x15s\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4`\xb3X\xcb=\xbe\xfa7\xf4}\xf2\xd76X@\u068e;\u024c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4`\xb8\u05b7;ySO\xb0\x8b\xb8\xcb\xce\xfa\xc7\xf3\x93\xc5{\xfe\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4`\xbeo\x95?*M%\xb6%o\xfd$#\xac\x148%.N\x89\b!\xab\rD\x14\x98\x00\x00\u0794`\xc3qO\xdd\xdbcFY\u48b1\xeaB\xc4r\x8c\u01f8\xba\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4`\xcc=D^\xbd\xf7j}z\xe5q\u0197\x1d\xffh\u0305\x85\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94`\xd5fq@\xd1&\x14\xb2\x1c\x8e^\x8a3\b.2\xdf\xcf#\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4`\xde\"\xa1Pt2\xa4{\x01\xcch\xc5*\v\xf8\xa2\xe0\u0418\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4`\xe0\xbd\u0422Y\xbb\x9c\xb0\x9d?7\xe5\u034b\x9d\xac\uafca\x89JD\x91\xbdm\xcd(\x00\x00\u07d4`\xe3\xccC\xbc\xdb\x02j\xadu\x9cpf\xf5U\xbb\xf2\xacf\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\x04+\x80\xfd`\x95\u0478{\xe2\xf0\x0f\x10\x9f\xab\xaf\xd1W\xa6\x89\x05k\xc7^-c\x10\x00\x00\u07d4a\a\xd7\x1d\xd6\xd0\xee\xfb\x11\xd4\xc9\x16@L\xb9\x8cu>\x11}\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\x0f\xd6\xeeN\xeb\xab\x10\xa8\xc5]\vK\xd2\xe7\xd6\xef\x81qV\x89\x01\x15\x95a\x06]]\x00\x00\u07d4a\x14\xb0\xea\xe5Wi\x03\xf8\v\xfb\x98\x84-$\xed\x92#\u007f\x1e\x89\x05k\xc7^-c\x10\x00\x00\u07d4a!\xaf9\x8a[-\xa6\x9fe\xc68\x1a\xec\x88\u039c\xc6D\x1f\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\u07d4a&g\xf1r\x13[\x95\v,\xd1\xde\x10\xaf\xde\xcehW\xb8s\x8965\u026d\xc5\u07a0\x00\x00\u07d4a,\xed\x8d\xc0\u071e\x89\x9e\xe4oyb33\x15\xf3\xf5^D\x89\x12^5\xf9\xcd=\x9b\x00\x00\u07d4a4\xd9B\xf07\xf2\xcc=BJ#\f`=g\xab\xd3\xed\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a:\xc5;\xe5e\xd4e6\xb8 q[\x9b\x8d:\xe6\x8aK\x95\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\u07d4a?\xabD\xb1k\xbeUMD\xaf\xd1x\xab\x1d\x02\xf3z\ua949lk\x93[\x8b\xbd@\x00\x00\u07d4aN\x8b\xef=\xd2\u015bY\xa4\x14Vt@\x10\x185\x18\x84\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4aQ\x84d\xfd\u0637<\x1b\xb6\xacm\xb6\x00eI8\xdb\xf1z\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4aT}7nSi\xbc\xf9x\xfc\x16,1\xc9\b\"3\xb8%\xd0%\xbe?{\x10V\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4a\x91\xdd\u0276J\x8e\b\x90\xb427\t\u05e0|H\xb9*d\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4a\x96\xc3\xd3\xc0\x90\x8d%Cf\xb7\xbc\xa5WE\"-\x9dM\xb1\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4a\x9f\x17\x14E\xd4+\x02\xe2\xe0p\x04\xad\x8a\xfeiO\xa5=j\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4a\xad\xf5\x92\x9a^)\x81hN\xa2C\xba\xa0\x1f}\x1f^\x14\x8a\x89\x05\xfa\xbfl\x98O#\x00\x00\u07d4a\xb1\xb8\xc0\x12\xcdLx\xf6\x98\xe4p\xf9\x02V\xe6\xa3\x0fH\u0749\n\u05ce\xbcZ\xc6 \x00\x00\u07d4a\xb3\xdf.\x9e\x9f\xd9h\x13\x1f\x1e\x88\xf0\xa0\xeb[\xd7eFM\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4a\xb9\x02\u0166s\x88X&\x82\r\x1f\xe1EI\xe4\x86_\xbd\u0089\x12$\xef\xed*\u1440\x00\u07d4a\xb9\x05\xdef?\xc1s\x86R;:(\xe2\xf7\xd07\xa6U\u0349\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4a\xba\x87\xc7~\x9bYm\xe7\xba\x0e2o\xdd\xfe\xec!c\xeff\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4a\xbf\x84\u056b\x02oX\xc8s\xf8o\xf0\xdf\u0282\xb5W3\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\xc4\xee|\x86LMk^7\xea\x131\xc2\x03s\x9e\x82k/\x89\x01\xa15;8*\x91\x80\x00\u07d4a\xc80\xf1eG\x18\xf0u\u032b\xa3\x16\xfa\xac\xb8[}\x12\v\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4a\xc8\xf1\xfaC\xbf\x84i\x99\xec\xf4{+2M\xfbkc\xfe:\x89+^:\xf1k\x18\x80\x00\x00\u07d4a\xc9\xdc\u8c98\x1c\xb4\x0e\x98\xb0@+\xc3\xeb(4\x8f\x03\xac\x89\n\xac\xac\u0679\xe2+\x00\x00\u07d4a\u03a7\x1f\xa4d\xd6*\a\x06?\x92\v\f\xc9\x17S\x973\u0609Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4a\xd1\x01\xa03\xee\x0e.\xbb1\x00\xed\xe7f\xdf\x1a\xd0$IT\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4a\xedU\x96\u0197 \u007f=U\xb2\xa5\x1a\xa7\xd5\x0f\a\xfa\t\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4a\xff\x8eg\xb3M\x9e\xe6\xf7\x8e\xb3o\xfe\xa1\xb9\xf7\xc1W\x87\xaf\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4b\x05\xc2\xd5dtp\x84\x8a8@\xf3\x88~\x9b\x01]4u\\\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4b(\xad\xe9^\x8b\xb1}\x1a\xe2;\xfb\x05\x18AMI~\x0e\xb8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94b)\xdc\xc2\x03\xb1\xed\xcc\xfd\xf0n\x87\x91\fE*\x1fMzr\x8a\x06\xe1\xd4\x1a\x8f\x9e\xc3P\x00\x00\u0794b+\xe4\xb4T\x95\xfc\xd91C\xef\xc4\x12\u0599\xd6\xcd\xc2=\u0148\xf0\x15\xf2W6B\x00\x00\u07d4b3\x1d\xf2\xa3\xcb\xee5 \xe9\x11\u07a9\xf7>\x90_\x89%\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4bVD\xc9Z\x87>\xf8\xc0l\u06de\x9fm\x8dv\x80\x04=b\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4be\xb2\xe7s\x0f6\xb7v\xb5-\f\x9d\x02\xad\xa5]\x8e<\xb6\x8965\u026d\xc5\u07a0\x00\x00\u07d4bh\n\x15\xf8\u0338\xbd\xc0/s`\xc2Z\xd8\u03f5{\x8c\u034965\u026d\xc5\u07a0\x00\x00\u07d4b\x94\xea\xe6\xe4 \xa3\xd5`\n9\xc4\x14\x1f\x83\x8f\xf8\xe7\xccH\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4b\x97\x1b\xf2cL\xee\v\xe3\u0249\x0fQ\xa5`\x99\u06f9Q\x9b\x89#\x8f\xd4,\\\xf0@\x00\x00\u07d4b\x9b\xe7\xab\x12jS\x98\xed\xd6\u069f\x18D~x\u0192\xa4\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4b\xb4\xa9\"nah\a\x1el\xbea\x11\xfe\xf0\xbcc\x8a\x03\xba\x19\x10\xbf4\x1b\x00\x00\x00\xe0\x94c\n\x91:\x901\xc9I*\xbdLA\u06f1PT\xcf\xecD\x16\x8a\x014X\xdbg\xaf5\xe0\x00\x00\xe0\x94c\fRs\x12mQ|\xe6q\x01\x81\x1c\xab\x16\xb8SL\xf9\xa8\x8a\x01\xfe\xcc\xc6%s\xbb\u04c0\x00\u07d4c\x100\xa5\xb2{\a(\x8aEio\x18\x9e\x11\x14\xf1*\x81\xc0\x89\x1b\x1azB\v\xa0\r\x00\x00\u07d4c\x10\xb0 \xfd\x98\x04IW\x99P\x92\t\x0f\x17\xf0NR\xcd\xfd\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4c+\x91I\xd7\x01x\xa7364'^\x82\u0555?'\x96{\x89%\xf2s\x93=\xb5p\x00\x00\u07d4c,\xec\xb1\f\xfc\xf3\x8e\u0246\xb4;\x87p\xad\xec\xe9 \x02!\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4c1\x02\x8c\xbbZ!H[\xc5\x1bVQB\x99;\xdb%\x82\xa9\x89\x1c\xfd\xd7F\x82\x16\xe8\x00\x00\u07d4c3O\xcf\x17E\x84\x0eK\tJ;\xb4\v\xb7o\x96\x04\xc0L\x89\u05e5\xd7\x03\xa7\x17\xe8\x00\x00\u07d4c4\nWqk\xfac\xebl\xd13r\x12\x02W[\xf7\x96\xf0\x89\va\xe0\xa2\f\x12q\x80\x00\u07d4cN\xfc$7\x11\a\xb4\xcb\xf0?y\xa9=\xfd\x93\xe41\xd5\xfd\x89B5\x82\xe0\x8e\xdc\\\x80\x00\xe0\x94c\\\x00\xfd\xf05\xbc\xa1_\xa3a\r\xf38N\x0f\xb7\x90h\xb1\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4ca.xb\xc2{X|\xfbm\xaf\x99\x12\xcb\x05\x1f\x03\n\x9f\x89\x02[\x19\u053f\xe8\xed\x00\x00\u07d4cfgU\xbdA\xb5\x98i\x97x<\x13\x040\b$+<\xb5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4c{\xe7\x1b:\xa8\x15\xffE=VB\xf70tE\vd\xc8*\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94c}g\xd8\u007fXo\nZG\x9e \xee\x13\xea1\n\x10\xb6G\x8a\n:Y&\xaf\xa1\xe70\x00\x00\u07d4c\u007fXi\xd6\xe4i_\x0e\xb9\xe2s\x11\u0107\x8a\xff33\x80\x89j\xc0Nh\xaa\xec\x86\x00\x00\u07d4c\x97|\xad}\r\xcd\xc5+\x9a\xc9\xf2\xff\xa16\xe8d(\x82\xb8\x89\x04\x10\u0546\xa2\nL\x00\x00\u07d4c\xa6\x1d\xc3\n\x8e;0\xa7c\xc4!<\x80\x1c\xbf\x98s\x81x\x8965\u026d\xc5\u07a0\x00\x00\u07d4c\xacT\\\x99\x12C\xfa\x18\xae\xc4\x1dOoY\x8eUP\x15\u0709 \x86\xac5\x10R`\x00\x00\u07d4c\xb9uMu\xd1-8@9\xeci\x06<\v\xe2\x10\xd5\xe0\u3252\v\x86\f\xc8\xec\xfd\x80\x00\u07d4c\xbbfO\x91\x17\x03v(YM\xa7\xe3\xc5\b\x9f\xd6\x18\xb5\xb5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4c\u00a3\xd25\xe5\xee\xab\xd0\u0526\xaf\u06c9\xd9F'9d\x95\x89CN\xf0[\x9d\x84\x82\x00\x00\u07d4c\xc8\xdf\xde\v\x8e\x01\xda\xdc.t\x8c\x82L\xc06\x9d\U00010cc9\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4c\xd5Z\u065b\x917\xfd\x1b \xcc+O\x03\xd4,\xba\xdd\xf34\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4c\xd8\x00H\x87u\x96\xe0\u0084\x89\xe6P\xcdJ\xc1\x80\tjI\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94c\xe4\x14`>\x80\xd4\xe5\xa0\xf5\xc1\x87t FB%\x82\b\xe4\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94c\xe8\x8e.S\x9f\xfbE\x03\x86\xb4\xe4g\x89\xb2#\xf5GlE\x8a\x01U\x17\nw\x8e%\xd0\x00\x00\u07d4c\xef/\xbc=\xaf^\xda\xf4\xa2\x95b\x9c\xcf1\xbc\xdf@8\xe5\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4c\xf0\xe5\xa7R\xf7\x9fg\x12N\xedc:\xd3\xfd'\x05\xa3\x97\u0509\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94c\xf5\xb5=y\xbf.A\x14\x89Re0\"8E\xfa\xc6\xf6\x01\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4c\xfc\x93\x00\x13\x05\xad\xfb\u0278])\xd9)\x1a\x05\xf8\xf1A\v\x8965\u026d\xc5\u07a0\x00\x00\u0794c\xfek\xccK\x8a\x98P\xab\xbeu\x8070\xc92%\x1f\x14[\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4d\x03\xd0bT\x96\x90\xc8\xe8\xb6>\xaeA\xd6\xc1\tGn%\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4d\x04+\xa6\x8b\x12\xd4\xc1Qe\x1c\xa2\x81;sR\xbdV\xf0\x8e\x89 \x86\xac5\x10R`\x00\x00\u0794d\x05\xdd\x13\xe9:\xbc\xff7~p\x0e<\x1a\x00\x86\xec\xa2})\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94d\n\xbam\xe9\x84\xd9E\x177x\x03p^\xae\xa7\t_J\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4d\v\xf8t\x15\xe0\xcf@s\x01\xe5Y\x9ah6m\xa0\x9b\xba\u0209\x1a\xbc\x9fA`\x98\x15\x80\x00\u07d4d \xf8\xbc\xc8\x16JaR\xa9\x9dk\x99i0\x05\xcc\xf7\xe0S\x8965f3\xeb\xd8\xea\x00\x00\u07d4d$\x1axD)\x0e\n\xb8U\xf1\u052au\xb5SE\x03\"$\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4d&J\xed\xd5-\xca\xe9\x18\xa0\x12\xfb\xcd\f\x03\x0e\xe6\xf7\x18!\x8965\u026d\xc5\u07a0\x00\x00\u07d4d7\x0e\x87 &E\x12Z5\xb2\a\xaf\x121\xfb`r\xf9\xa7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4d=\x9a\xee\u0531\x80\x94~\u04b9 |\xceL=\xdcU\xe1\xf7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4dC\xb8\xaec\x9d\xe9\x1c\xf7\xf0p\xa5G\x03\xb7\x18NH'l\\\x00w\xefK4\x89\x11X\xe4`\x91=\x00\x00\x00\xe0\x94d\xe2\xde! \v\x18\x99\u00e0\xc0e;P@\x13m\r\xc8B\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4d\xec\x8a[t?4y\xe7\a\xda\xe9\xee \u076aO@\xf1\u0649\n\u05ce\xbcZ\xc6 \x00\x00\u07d4e\x03\x86\v\x19\x10\b\xc1U\x83\xbf\u0201X\t\x93\x01v((\x8965\u026d\xc5\u07a0\x00\x00\u07d4e\x051\x911\x9e\x06z%\xe66\x1dG\xf3\u007fc\x18\xf84\x19\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4e\t;#\x9b\xbf\xba#\xc7w\\\xa7\xdaZ\x86H\xa9\xf5L\xf7\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4e\t\xee\xb14~\x84/\xfbA>7\x15^,\xbcs\x82s\xfd\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94e\vBUU\xe4\xe4\xc5\x17\x18\x14h6\xa2\xc1\xeew\xa5\xb4!\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4e\f\xf6}\xb0`\xcc\xe1uh\xd5\xf2\xa4#h|Idv\t\x89\x05k\xc7^-c\x10\x00\x00\u07d4e\x10\xdfB\xa5\x99\xbc\xb0\xa5\x19\u0329a\xb4\x88u\x9aogw\x89lk\x93[\x8b\xbd@\x00\x00\u07d4e6u\xb8B\xd7\u0634a\xf7\"\xb4\x11|\xb8\x1d\xac\x8ec\x9d\x89\x01\xae6\x1f\xc1E\x1c\x00\x00\u07d4eK~\x80\x87\x99\xa8=r\x87\xc6w\x06\xf2\xab\xf4\x9aId\x04\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94eORHG\xb3\xa6\xac\xc0\xd3\xd5\xf1\xf3b\xb6\x03\xed\xf6_\x96\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4eY4\u068etN\xaa=\xe3M\xbb\xc0\x89LN\xda\va\xf2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4e]\\\xd7H\x96)\xe2ANIb?\xabb\xa1~M6\x11\x89\x05\fL\xb2\xa1\f`\x00\x00\u07d4e\xaf\x8d\x8b[\x1d\x1e\xed\xfaw\xbc\xbc\x96\xc1\xb13\xf83\x06\u07c9\x05P\x05\xf0\xc6\x14H\x00\x00\u07d4e\xaf\x90\x87\xe0QgqT\x97\u0265\xa7I\x18\x94\x89\x00M\xef\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u0794e\xb4/\xae\xcc\x1e\u07f1B\x83\u0297\x9a\xf5E\xf6;0\xe6\f\x88\xfc\x93c\x92\x80\x1c\x00\x00\u0794e\xd3>\xb3\x9c\xdadS\xb1\x9ea\xc1\xfeM\xb91p\xef\x9d4\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4e\xd8\xddN%\x1c\xbc\x02\x1f\x05\xb0\x10\xf2\xd5\xdcR\f8r\xe0\x89-CW\x9a6\xa9\x0e\x00\x00\u07d4e\xea&\xea\xbb\xe2\xf6L\xcc\xcf\xe0h)\xc2]F7R\x02%\x89%\xf2s\x93=\xb5p\x00\x00\u07d4e\xeag\xad?\xb5j\xd5\xfb\x948}\u04ce\xb3\x83\x00\x1d|h\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94e\xeb\xae\xd2~\u06dd\xcc\x19W\xae\xe5\xf4R\xac!\x05\xa6\\\x0e\x8a\t7\u07ed\xae%\u26c0\x00\u07d4e\xee \xb0m\x9a\u0549\xa7\xe7\xce\x04\xb9\xf5\xf7\x95\xf4\x02\xae\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4e\xf544m/\xfbx\u007f\xa9\xcf\x18]t[\xa4)\x86\xbdn\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94e\xf5\x87\x0f&\xbc\xe0\x89g}\xfc#\xb5\x00\x1e\xe4\x92H4(\x8a\x01\x12\xb1\xf1U\xaa2\xa3\x00\x00\u07d4e\xfd\x02\xd7\x04\xa1*M\xac\xe9G\x1b\x06E\xf9b\xa8\x96q\u0209\x01\x8d\x1c\xe6\xe4'\u0340\x00\u07d4e\xff\x87O\xaf\xceM\xa3\x18\xd6\xc9=W\xe2\u00ca\rs\xe8 \x8968\x02\x1c\xec\u06b0\x00\x00\xe0\x94f\x05W\xbbC\xf4\xbe:\x1b\x8b\x85\xe7\xdf{<[\xcdT\x80W\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4f\b,u\xa8\xde1\xa59\x13\xbb\xd4M\xe3\xa07O\u007f\xaaA\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4f\x11\xceY\xa9\x8b\a*\xe9Y\xdcI\xadQ\x1d\xaa\xaa\xa1\x9dk\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4f \x1b\xd2'\xaem\u01bd\xfe\xd5\xfb\u0781\x1f\xec\xfe^\x9d\u0649 >\x9e\x84\x92x\x8c\x00\x00\u07d4f#4\x81G$\x93[y1\xdd\xcaa\x00\xe0\rFw'\u0349\"\x88&\x9d\a\x83\xd4\x00\x00\u07d4f'O\xea\x82\xcd0\xb6\u009b#5\x0eOO=1\nX\x99\x89p7\x05P\xab\x82\x98\x00\x00\u07d4f,\xfa\x03\x8f\xab7\xa0\x17E\xa3d\u1e41'\xc5\x03tm\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4f5\xb4oq\x1d-\xa6\xf0\xe1cp\u034e\xe4>\xfb,-R\x89lk\x93[\x8b\xbd@\x00\x00\u07d4f6\x04\xb0P0F\xe6$\xcd&\xa8\xb6\xfbGB\xdc\xe0*o\x89\x03\x8b\x9by~\xf6\x8c\x00\x00\u07d4f6\u05ecczH\xf6\x1d8\xb1L\xfdHe\xd3m\x14(\x05\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4f@\xcc\xf0SU\\\x13\n\xe2\xb6Vd~\xa6\xe3\x167\xb9\xab\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4fBK\xd8x[\x8c\xb4a\x10*\x90\x02\x83\xc3]\xfa\a\xefj\x89\x02.-\xb2ff\xfc\x80\x00\u07d4fL\xd6}\xcc\u026c\x82(\xb4\\U\u06cdvU\ve\x9c\u0709\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4fNC\x11\x98p\xaf\x10zD\x8d\xb1'\x8b\x04H8\xff\u036f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4fQso\xb5\x9b\x91\xfe\xe9\xc9:\xa0\xbdn\xa2\xf7\xb2Pa\x80\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4f[\x00\x0f\vw'P\xcc\x89k\x91\x8a\xacIK\x16\x80\x00\xe0\x94g]\\\xaa`\x9b\xf7\n\x18\xac\xa5\x80F]\x8f\xb71\r\x1b\xbb\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4gc F\u0732ZT\x93i(\xa9oB?3 \xcb\ud489lk\x93[\x8b\xbd@\x00\x00\u07d4ge\xdf%(\x0e\x8eO8\u0531\xcfDo\xc5\xd7\xebe\x9e4\x89\x05k\xc7^-c\x10\x00\x00\u07d4gv\xe13\xd9\xdc5L\x12\xa9Q\b{c\x96P\xf59\xa43\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4g\x85Q<\xf72\xe4~\x87g\ap\xb5A\x9b\xe1\f\xd1\xfct\x89lk\x93[\x8b\xbd@\x00\x00\u07d4g\x947\xea\xcfCxx\xdc)=H\xa3\x9c\x87\xb7B\x1a!l\x89\x03\u007f\x81\x82\x1d\xb2h\x00\x00\u07d4g\x9b\x9a\x10\x990Q~\x89\x99\t\x9c\xcf*\x91LL\x8d\xd94\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4g\xa8\x0e\x01\x90r\x1f\x949\rh\x02r\x9d\xd1,1\xa8\x95\xad\x89lk\x13u\xbc\x91V\x00\x00\u07d4g\xb8\xa6\xe9\x0f\xdf\n\x1c\xacD\x17\x930\x1e\x87P\xa9\xfayW\x890\x84\x9e\xbe\x166\x9c\x00\x00\u07d4g\xbc\x85\xe8}\xc3LN\x80\xaa\xfa\x06k\xa8\u049d\xbb\x8eC\x8e\x89\x15\xd1\xcfAv\xae\xba\x00\x00\u07d4g\xc9&\t>\x9b\x89'\x938\x10\u0642\"\xd6.+\x82\x06\xbb\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4g\xcf\xdanp\xbfvW\u04d0Y\xb5\x97\x90\xe5\x14Z\xfd\xbea\x89#\x05\r\tXfX\x00\x00\u07d4g\u0582\xa2\x82\xefs\xfb\x8dn\x90q\xe2aOG\xab\x1d\x0f^\x8965\u026d\xc5\u07a0\x00\x00\u07d4g\u05a8\xaa\x1b\xf8\xd6\xea\xf78N\x99=\xfd\xf1\x0f\n\xf6\x8aa\x89\n\xbc\xbbW\x18\x97K\x80\x00\u07d4g\u0692.\xff\xa4r\xa6\xb1$\xe8N\xa8\xf8k$\xe0\xf5\x15\xaa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4g\xdf$-$\r\u0538\a\x1dr\xf8\xfc\xf3[\xb3\x80\x9dq\xe8\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4g\xee@n\xa4\xa7\xaej:8\x1e\xb4\xed\xd2\xf0\x9f\x17KI(\x898)c_\th\xb0\x00\x00\u07d4g\xf2\xbbx\xb8\xd3\xe1\x1f|E\x8a\x10\xb5\xc8\xe0\xa1\xd3tF}\x89a\t=|,m8\x00\x00\u07d4g\xfcR}\xce\x17\x85\xf0\xfb\x8b\xc7\xe5\x18\xb1\xc6i\xf7\xec\u07f5\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4h\x02}\x19U\x8e\xd73\x9a\b\xae\xe8\xde5Y\xbe\x06>\xc2\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4h\x06@\x83\x8b\xd0zD{\x16\x8dm\x92;\x90\xcflC\xcd\u0289]\u0212\xaa\x111\xc8\x00\x00\u07d4h\a\xdd\u020d\xb4\x89\xb03\xe6\xb2\xf9\xa8\x15SW\x1a\xb3\xc8\x05\x89\x01\x9f\x8euY\x92L\x00\x00\xe0\x94h\rY\x11\xed\x8d\xd9\xee\xc4\\\x06\f\"?\x89\xa7\xf6 \xbb\u054a\x04<3\xc1\x93ud\x80\x00\x00\u07d4h\x11\xb5L\u0456c\xb1\x1b\x94\xda\x1d\xe2D\x82\x85\u035fh\u0649;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4h\x19\f\xa8\x85\xdaB1\x87L\x1c\xfbB\xb1X\n!s\u007f8\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94h(\x97\xbcO\x8e\x89\x02\x91 \xfc\xff\xb7\x87\xc0\x1a\x93\xe6A\x84\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4h)^\x8e\xa5\xaf\xd9\t?\xc0\xa4e\xd1W\x92+]*\xe24\x89\x01\x15NS!}\xdb\x00\x00\u07d4h.\x96'oQ\x8d1\xd7\xe5n0\u07f0\t\xc1!\x82\x01\xbd\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4h5\xc8\xe8\xb7J,\xa2\xae?J\x8d\x0fk\x95J>*\x83\x92\x89\x03B\x9c3]W\xfe\x00\x00\u07d4h63\x01\n\x88hk\xeaZ\x98\xeaS\xe8y\x97\xcb\xf7>i\x89\x05k9Bc\xa4\f\x00\x00\u07d4h=\xba6\xf7\xe9O@\xeaj\xea\ry\xb8\xf5!\xdeU\an\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4hA\x9cm\xd2\xd3\xceo\u02f3\xc7>/\xa0y\xf0`Q\xbd\xe6\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4hG;z}\x96Y\x04\xbe\u06e5V\u07fc\x17\x13l\xd5\xd44\x89\x05k\xc7^-c\x10\x00\x00\u07d4hG\x82[\xde\xe8$\x0e(\x04,\x83\xca\xd6B\U000868fd\u0709QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94hJD\xc0i3\x9d\b\xe1\x9auf\x8b\u06e3\x03\xbe\x85S2\x8a\x0e\u04b5%\x84\x1a\xdf\xc0\x00\x00\u07d4hS\x1fM\u0680\x8fS vz\x03\x114(\xca\f\xe2\xf3\x89\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4hy'\xe3\x04\x8b\xb5\x16*\xe7\xc1\\\xf7k\xd1$\xf9I{\x9e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94h\x80\x9a\xf5\xd52\xa1\x1c\x1aMn2\xaa\xc7\\LR\xb0\x8e\xad\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4h\x86\xad\xa7\xbb\xb0a{\u0684!\x91\u018c\x92.\xa3\xa8\xac\x82\x89>\xe2;\xde\x0e} \x00\x00\xe0\x94h\x88>\x15.V`\xfe\xe5\x96&\xe7\xe3\xb4\xf0Q\x10\xe6\"/\x8a\v\x94c;\xe9u\xa6*\x00\x00\u07d4h\x8aV\x9e\x96U$\xeb\x1d\n\xc3\xd3s>\xab\x90\x9f\xb3\xd6\x1e\x89G\x8e\xae\x0eW\x1b\xa0\x00\x00\xe0\x94h\x8e\xb3\x85;\xbc\xc5\x0e\xcf\xee\x0f\xa8\u007f\n\xb6\x93\u02bd\xef\x02\x8a\x06\xb1\n\x18@\x06G\xc0\x00\x00\u07d4h\xa7B_\xe0\x9e\xb2\x8c\xf8n\xb1y>A\xb2\x11\xe5{\u058d\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4h\xa8l@#\x88\xfd\xdcY\x02\x8f\xecp!\u933f\x83\x0e\xac\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\xe0\x94h\xac\u06a9\xfb\x17\xd3\xc3\t\x91\x1aw\xb0_S\x91\xfa\x03N\xe9\x8a\x01\xe5.3l\xde\"\x18\x00\x00\u07d4h\xad\xdf\x01\x9dk\x9c\xabp\xac\xb1?\v1\x17\x99\x9f\x06.\x12\x89\x02\xb5\x12\x12\xe6\xb7\u0200\x00\u07d4h\xb3\x186\xa3\n\x01j\xda\x15{c\x8a\xc1]\xa7?\x18\xcf\u0789\x01h\u048e?\x00(\x00\x00\xe0\x94h\xb6\x85G\x88\xa7\xc6Il\xdb\xf5\xf8K\x9e\xc5\xef9+x\xbb\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4h\xc0\x84\x90\u021b\xf0\u05b6\xf3 \xb1\xac\xa9\\\x83\x12\xc0\x06\b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4h\xc7\xd1q\x1b\x01\x1a3\xf1o\x1fU\xb5\xc9\x02\xcc\xe9p\xbd\u05c9\b=lz\xabc`\x00\x00\u07d4h\xc8y\x1d\xc3B\xc3sv\x9e\xa6\x1f\xb7\xb5\x10\xf2Q\xd3 \x88\x8965\u026d\xc5\u07a0\x00\x00\u07d4h\u07d4|I[\ubbb8\u8273\xf9S\xd53\x87K\xf1\x06\x89\x1d\x99E\xab+\x03H\x00\x00\u07d4h\xe8\x02'@\xf4\xaf)\xebH\xdb2\xbc\xec\xdd\xfd\x14\x8d=\xe3\x8965\u026d\xc5\u07a0\x00\x00\u07d4h\xecy\u057eqUql@\x94\x1cy\u05cd\x17\u079e\xf8\x03\x89\x1b#8w\xb5 \x8c\x00\x00\u07d4h\xee\xc1\u222c1\xb6\xea\xba~\x1f\xbdO\x04\xadW\x9ak]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4h\xf5%\x92\x1d\xc1\x1c2\x9buO\xbf>R\x9f\xc7#\xc84\u0349WG=\x05\u06ba\xe8\x00\x00\u07d4h\xf7\x19\xae4+\xd7\xfe\xf1\x8a\x05\u02f0/pZ\u04ce\u0572\x898\xeb\xad\\\u0710(\x00\x00\xe0\x94h\xf7W<\xd4W\xe1L\x03\xfe\xa4>0-04|\x10p\\\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4h\xf8\xf4QU\xe9\x8cP)\xa4\xeb\u0175'\xa9.\x9f\xa81 \x89\xf0{D\xb4\a\x93 \x80\x00\u07d4h\xfe\x13W!\x8d\tXI\xcdW\x98B\u012a\x02\xff\x88\x8d\x93\x89lk\x93[\x8b\xbd@\x00\x00\u07d4i\x02(\xe4\xbb\x12\xa8\u0535\u09d7\xb0\xc5\xcf*u\t\x13\x1e\x89e\xea=\xb7UF`\x00\x00\u07d4i\x05\x94\xd3\x06a<\xd3\xe2\xfd$\xbc\xa9\x99J\u064a=s\xf8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94i\a2ir\x9ed\x14\xb2n\xc8\xdc\x0f\xd95\xc7;W\x9f\x1e\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x94i\x19\xdd^]\xfb\x1a\xfa@G\x03\xb9\xfa\xea\x8c\xee5\xd0\rp\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4i4\x92\xa5\xc5\x13\x96\xa4\x82\x88\x16i\xcc\xf6\xd8\xd7y\xf0\tQ\x89\x12\xbfPP:\xe3\x03\x80\x00\u07d4i=\x83\xbe\tE\x9e\xf89\v.0\xd7\xf7\u008d\xe4\xb4(N\x89lk\x93[\x8b\xbd@\x00\x00\u07d4iQp\x83\xe3\x03\xd4\xfb\xb6\xc2\x11E\x14!]i\xbcF\xa2\x99\x89\x05k\xc7^-c\x10\x00\x00\u07d4iUPel\xbf\x90\xb7]\x92\xad\x91\"\xd9\r#\xcah\xcaM\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94iX\xf8;\xb2\xfd\xfb'\xce\x04\t\xcd\x03\xf9\xc5\xed\xbfL\xbe\u074a\x04<3\xc1\x93ud\x80\x00\x00\u0794i[\x0fRBu7\x01\xb2d\xa6pq\xa2\u0708\b6\xb8\u06c8\u3601\x1b\xech\x00\x00\xe0\x94i[L\xce\bXV\xd9\xe1\xf9\xff>y\x94 #5\x9e_\xbc\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94if\x06:\xa5\xde\x1d\xb5\xc6q\xf3\xddi\x9dZ\xbe!>\xe9\x02\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4it\u0224\x14\u03ae\xfd<.M\xfd\xbe\xf40V\x8d\x9a\x96\v\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\xe0\x94iximQP\xa9\xa2cQ?\x8ft\u0196\xf8\xb19|\xab\x8a\x01g\xf4\x82\xd3\u0171\xc0\x00\x00\xe0\x94iy{\xfb\x12\u027e\u0582\xb9\x1f\xbcY5\x91\xd5\xe4\x027(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94i\u007fUSk\xf8Z\xdaQ\x84\x1f\x02\x87b:\x9f\x0e\u041a\x17\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4i\x82\xfe\x8a\x86~\x93\xebJ\v\xd0QX\x93\x99\xf2\xec\x9aR\x92\x89lk\x93[\x8b\xbd@\x00\x00\u07d4i\x8a\x8ao\x01\xf9\xabh/c|yi\xbe\x88_lS\x02\xbf\x89\x01\r:\xa56\xe2\x94\x00\x00\u07d4i\x8a\xb9\xa2\xf33\x81\xe0|\fGC=\r!\xd6\xf36\xb1'\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4i\x94\xfb21\xd7\xe4\x1dI\x1a\x9dh\xd1\xfaL\xae,\xc1Y`\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\x9c\x9e\xe4q\x95Q\x1f5\xf8b\xcaL\"\xfd5\xae\x8f\xfb\xf4\x89\x04V9\x18$O@\x00\x00\u07d4i\x9f\xc6\u058aGuW<\x1d\u036e\xc80\xfe\xfdP9|N\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4i\xaf(\xb0tl\xac\r\xa1p\x84\xb99\x8c^6\xbb:\r\xf2\x896w\x03n\xdf\n\xf6\x00\x00\u07d4i\xb8\x0e\xd9\x0f\x84\x83J\xfa?\xf8.\xb9dp;V\tw\u0589\x01s\x17\x90SM\xf2\x00\x00\xe0\x94i\xb8\x1dY\x81\x14\x1e\u01e7\x14\x10`\xdf\u03cf5\x99\xff\xc6>\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4i\xbc\xfc\x1dC\xb4\xba\x19\xde{'K\xdf\xfb5\x13\x94\x12\xd3\u05c95e\x9e\xf9?\x0f\xc4\x00\x00\u07d4i\xbd%\xad\xe1\xa34lY\xc4\xe90\xdb*\x9dq^\xf0\xa2z\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\xc0\x8dtGT\xdep\x9c\xe9n\x15\xae\r\x1d9[:\"c\x8965\u026d\xc5\u07a0\x00\x00\u07d4i\xc2\xd85\xf1>\xe9\x05\x80@\x8ej2\x83\xc8\u0326\xa44\xa2\x89#\x8f\xd4,\\\xf0@\x00\x00\u07d4i\xc9N\a\u0129\xbe3\x84\xd9]\xfa<\xb9)\x00Q\x87;{\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4i\xcb>!S\x99\x8d\x86\xe5\xee \xc1\xfc\u0466\xba\uec86?\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4i\u04ddQ\b\x89\xe5R\xa3\x96\x13[\xfc\xdb\x06\xe3~8v3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94i\u064f8\xa3\xba=\xbc\x01\xfa\\,\x14'\xd8b\x83//p\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94i\xe2\xe2\xe7\x040|\xcc[\\\xa3\xf1d\xfe\xce.\xa7\xb2\xe5\x12\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4i\xffB\x90t\u02dblc\xbc\x91B\x84\xbc\xe5\xf0\xc8\xfb\xf7\u0409\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4i\xff\x89\x01\xb5Av?\x81|_)\x98\xf0-\xcf\xc1\xdf)\x97\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4j\x02:\xf5}XM\x84^i\x876\xf10\u06dd\xb4\r\xfa\x9a\x89\x05[ \x1c\x89\x00\x98\x00\x00\u07d4j\x04\xf5\xd5?\xc0\xf5\x15\xbe\x94+\x8f\x12\xa9\xcbz\xb0\xf3\x97x\x89\xa9\xaa\xb3E\x9b\xe1\x94\x00\x00\u07d4j\x05\xb2\x1cO\x17\xf9\xd7?_\xb2\xb0\u02c9\xffSV\xa6\xcc~\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\xe0\x94j\x0f\x05`f\xc2\xd5f(\x85\x02s\xd7\xec\xb7\xf8\xe6\xe9\x12\x9e\x8a\x01\x0f\r)<\u01e5\x88\x00\x00\u07d4j\x13\xd5\xe3,\x1f\xd2m~\x91\xffn\x051`\xa8\x9b,\x8a\xad\x89\x02\xe6/ \xa6\x9b\xe4\x00\x00\u07d4j.\x86F\x9a[\xf3|\xee\x82\xe8\x8bL8c\x89](\xfc\xaf\x89\x1c\"\x92f8[\xbc\x00\x00\u07d4j6\x94BL|\u01b8\xbc\u067c\u02baT\f\xc1\xf5\xdf\x18\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94jB\u0297\x1cex\u056d\xe2\x95\xc3\xe7\xf4\xad3\x1d\xd3BN\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4jD\xaf\x96\xb3\xf02\xaed\x1b\xebg\xf4\xb6\xc83B\xd3|]\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4jL\x89\a\xb6\x00$\x80W\xb1\xe4cT\xb1\x9b\u0705\x9c\x99\x1a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4jQNbB\xf6\xb6\x8c\x13~\x97\xfe\xa1\u73b5U\xa7\xe5\xf7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4jS\xd4\x1a\xe4\xa7R\xb2\x1a\xbe\xd57FI\x95:Q=\xe5\xe5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4jaY\aJ\xb5s\xe0\xeeX\x1f\x0f=\xf2\u05a5\x94b\x9bt\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4jc7\x83?\x8fjk\xf1\f\xa7\xec!\xaa\x81\x0e\xd4D\xf4\u02c97\xbd$4\\\xe8\xa4\x00\x00\u07d4jcS\xb9qX\x9f\x18\xf2\x95\\\xba(\xab\xe8\xac\xcejWa\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4jc\xfc\x89\xab\xc7\xf3n(-\x80x{{\x04\xaf\xd6U>q\x89\b\xacr0H\x9e\x80\x00\x00\u07d4jg\x9e7\x8f\xdc\xe6\xbf\xd9\u007f\xe6/\x04)Z$\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4j\x8c\xea-\xe8J\x8d\xf9\x97\xfd?\x84\xe3\b=\x93\xdeW\u0369\x89\x05k\xe0<\xa3\xe4}\x80\x00\xe0\x94j\x97Xt;`>\xea:\xa0RKB\x88\x97#\xc4\x159H\x8a\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4j\xa5s/;\x86\xfb\x8c\x81\xef\xbek[G\xb5cs\v\x06\u020965\u026d\xc5\u07a0\x00\x00\u07d4j\xb3#\xaePV\xed\nE0r\u016b\xe2\xe4/\xcf]q9\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4j\xb5\xb4\xc4\x1c\u0778)i\f/\xda\u007f \xc8^b\x9d\xd5\u0549d\u052fqL2\x90\x00\x00\u07d4j\xc4\x0fS-\xfe\xe5\x11\x81\x17\u04ad5-\xa7}Om\xa2\u0209\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4j\xc4\u053e-\xb0\u065d\xa3\xfa\xaa\xf7RZ\xf2\x82\x05\x1dj\x90\x89\x04X\xcaX\xa9b\xb2\x80\x00\u07d4j\xcd\u0723\xcd+I\x90\xe2\\\xd6\\$\x14\x9d\t\x12\t\x9ey\x89\xa2\xa1\xe0|\x9fl\x90\x80\x00\u07d4j\xd9\v\xe2R\xd9\xcdFM\x99\x81%\xfa\xb6\x93\x06\v\xa8\xe4)\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4j\u0753!\x93\xcd8IJ\xa3\xf0:\xec\xccKz\xb7\xfa\xbc\xa2\x89\x04\xdbs%Gc\x00\x00\x00\xe0\x94j\xe5\u007f'\x91|V*\x13*M\x1b\xf7\xec\n\u01c5\x83)&\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4j\xeb\x9ftt.\xa4\x91\x81=\xbb\xf0\xd6\xfc\xde\x1a\x13\x1dM\xb3\x89\x17\xe5T0\x8a\xa00\x00\x00\u07d4j\xf25\u04bb\xe0P\xe6)\x16\x15\xb7\x1c\xa5\x82\x96X\x81\x01B\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4j\xf6\xc7\xee\x99\xdf'\x1b\xa1[\xf3\x84\xc0\xb7d\xad\xcbM\xa1\x82\x8965f3\xeb\xd8\xea\x00\x00\u07d4j\xf8\xe5Yih,q_H\xadO\xc0\xfb\xb6~\xb5\x97\x95\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4j\xf9@\xf6>\u0278\xd8v'*\u0296\xfe\xf6\\\xda\xce\xcd\ua262\xa1]\tQ\x9b\xe0\x00\x00\u07d4j\xf9\xf0\xdf\uebbb_d\xbf\x91\xabw\x16i\xbf\x05)US\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4j\xff\x14f\xc2b6u\xe3\xcb\x0eu\xe4#\xd3z%\xe4B\xeb\x89]\u0212\xaa\x111\xc8\x00\x00\xe0\x94k\r\xa2Z\xf2g\u05c3l\"k\xca\xe8\xd8r\xd2\xceR\xc9A\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4k\x10\xf8\xf8\xb3\xe3\xb6\r\xe9\n\xa1-\x15_\x9f\xf5\xff\xb2,P\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\x17Y\x8a\x8e\xf5Oyz\xe5\x15\u0336Q}\x18Y\xbf\x80\x11\x89\x05k\xc7^-c\x10\x00\x00\u07d4k \xc0\x80`jy\xc7;\xd8\xe7[\x11qzN\x8d\xb3\xf1\u00c9\x10?sX\x03\xf0\x14\x00\x00\u07d4k\"\x84D\x02!\xce\x16\xa88-\xe5\xff\x02)G\"i\xde\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4k0\xf1\x829\x10\xb8m:\xcbZj\xfc\x9d\xef\xb6\xf3\xa3\v\xf8\x89\u3bb5sr@\xa0\x00\x00\u07d4k8\u0784\x1f\xad\u007fS\xfe\x02\xda\x11[\xd8j\xaff$f\xbd\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4kK\x99\xcb?\xa9\xf7\xb7L\u3903\x17\xb1\xcd\x13\t\n\x1az\x89\x03\x1b2~i]\xe2\x00\x00\u07d4kZ\xe7\xbfx\xecu\xe9\f\xb5\x03\xc7x\xcc\u04f2KO\x1a\xaf\x89+^:\xf1k\x18\x80\x00\x00\u07d4kc\xa2\u07f2\xbc\xd0\xca\xec\x00\"\xb8\x8b\xe3\f\x14Q\xeaV\xaa\x89+\xdbk\xf9\x1f\u007fL\x80\x00\u07d4kew\xf3\x90\x9aMm\xe0\xf4\x11R-Ep8d\x004\\\x89e\xea=\xb7UF`\x00\x00\u07d4kr\xa8\xf0a\xcf\xe6\x99j\xd4G\xd3\xc7,(\xc0\xc0\x8a\xb3\xa7\x89\xe7\x8cj\u01d9\x12b\x00\x00\u07d4kv\rHw\xe6\xa6'\xc1\xc9g\xbe\xe4Q\xa8P}\xdd\u06eb\x891T\xc9r\x9d\x05x\x00\x00\u07d4k\x83\xba\xe7\xb5e$EXU[\xcfK\xa8\xda \x11\x89\x1c\x17\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\x92]\xd5\xd8\xeda2\xabm\b`\xb8,D\xe1\xa5\x1f\x1f\xee\x89P; >\x9f\xba \x00\x00\xe0\x94k\x94a]\xb7Pej\u00cc~\x1c\xf2\x9a\x9d\x13g\u007fN\x15\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4k\x95\x1aC'N\xea\xfc\x8a\t\x03\xb0\xaf.\xc9+\xf1\xef\xc89\x89\x05k\xc7^-c\x10\x00\x00\u07d4k\x99%!\xec\x85#p\x84\x8a\u0597\xcc-\xf6Nc\xcc\x06\xff\x8965\u026d\xc5\u07a0\x00\x00\u07d4k\xa8\xf7\xe2_\xc2\xd8qa\x8e$\xe4\x01\x84\x19\x917\xf9\xf6\xaa\x89\x15\xafd\x86\x9ak\xc2\x00\x00\u07d4k\xa9\xb2\x1b5\x10k\xe1Y\xd1\xc1\xc2ez\xc5l\u049f\xfdD\x89\xf2\xdc}G\xf1V\x00\x00\x00\u07d4k\xafz*\x02\xaex\x80\x1e\x89\x04\xadz\xc0Q\b\xfcV\xcf\xf6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94k\xb2\xac\xa2?\xa1bm\x18\xef\xd6w\u007f\xb9}\xb0-\x8e\n\xe4\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4k\xb4\xa6a\xa3:q\xd4$\u051b\xb5\xdf(b.\xd4\xdf\xfc\xf4\x89\",\x8e\xb3\xfff@\x00\x00\u07d4k\xb5\b\x13\x14j\x9a\xddB\xee\"\x03\x8c\x9f\x1fti\xd4\u007fG\x89\n\xdaUGK\x814\x00\x00\u07d4k\xbc?5\x8af\x8d\u0461\x1f\x03\x80\xf3\xf71\bBj\xbdJ\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4k\xbd\x1eq\x93\x90\xe6\xb9\x10C\xf8\xb6\xb9\u07c9\x8e\xa8\x00\x1b4\x89llO\xa6\xc3\xdaX\x80\x00\u07d4k\xc8Z\xcdY(r.\xf5\tS1\xee\x88\xf4\x84\xb8\u03c3W\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4k\xd3\xe5\x9f#\x9f\xaf\xe4wk\xb9\xbd\xddk\ue0fa]\x9d\x9f\x8965\u026d\xc5\u07a0\x00\x00\u07d4k\xd4W\xad\xe0Qy]\xf3\xf2F\\89\xae\xd3\xc5\xde\xe9x\x8964\xbf9\xab\x98x\x80\x00\u07d4k\xe1c\x13d>\xbc\x91\xff\x9b\xb1\xa2\xe1\x16\xb8T\xea\x93:E\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4k\xe7Y^\xa0\xf0hH\x9a'\x01\xecFI\x15\x8d\xdcC\xe1x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4k\xe9\x03\x0e\xe6\xe2\xfb\u0111\xac\xa3\xde@\"\xd3\x01w+{}\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94k\xec1\x1a\xd0P\b\xb4\xaf5<\x95\x8c@\xbd\x06s\x9a?\xf3\x8a\x03w\xf6*\x0f\nbp\x00\x00\u07d4k\xf7\xb3\xc0e\xf2\xc1\xe7\xc6\xeb\t+\xa0\xd1Pf\xf3\x93\u0478\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4k\xf8o\x1e/+\x802\xa9\\Mw8\xa1\t\xd3\xd0\xed\x81\x04\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4l\x05\xe3N^\xf2\xf4.\u041d\xef\xf1\x02l\xd6k\xcbi`\xbb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4l\b\xa6\xdc\x01s\xc74)U\xd1\xd3\xf2\xc0e\xd6/\x83\xae\u01c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4l\n\xe9\xf0C\xc84\xd4Bq\xf14\x06Y=\xfe\tO8\x9f\x89RD*\xe13\xb6*\x80\x00\u07d4l\f\xc9\x17\xcb\xee}|\t\x97c\xf1Nd\xdf}4\xe2\xbf\t\x89\r\x8drkqw\xa8\x00\x00\xe0\x94l\x0eq/@\\Yr_\xe8)\xe9wK\xf4\xdf\u007fM\xd9e\x8a\f(h\x88\x9c\xa6\x8aD\x00\x00\xe0\x94l\x10\x12\x05\xb3#\xd7uD\xd6\xdcR\xaf7\xac\xa3\xce\xc6\xf7\xf1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4l\x15\xec5 \xbf\x8e\xbb\xc8 \xbd\x0f\xf1\x97x7T\x94\u03dd\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\xe0\x94l\x1d\xdd3\xc8\x19f\u0706!w`q\xa4\x12\x94\x82\xf2\xc6_\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4l%2\u007f\x8d\u02f2\xf4^V\x1e\x86\xe3]\x88P\xe5:\xb0Y\x89;\xcd\xf9\xba\xfe\xf2\xf0\x00\x00\u07d4l.\x9b\xe6\u052bE\x0f\xd1%1\xf3?\x02\x8caFt\xf1\x97\x89\xc2\x12z\xf8X\xdap\x00\x00\u07d4l5\x9eX\xa1=Ex\xa93\x8e3\\g\xe7c\x9f_\xb4\u05c9\v\xd1[\x94\xfc\x8b(\x00\x00\u07d4l=\x18pA&\xaa\x99\xee3B\xce`\xf5\xd4\xc8_\x18g\u0349\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4lGK\xc6jTx\x00f\xaaOQ.\xef\xa7s\xab\xf9\x19\u01c9\x05\x18\x83\x15\xf7v\xb8\x00\x00\u07d4lNBn\x8d\xc0\x05\u07e3Ql\xb8\xa6\x80\xb0.\ua56e\x8e\x89Hz\x9a0E9D\x00\x00\u07d4lR\xcf\b\x95\xbb5\xe6V\x16\x1eM\xc4j\xe0\xe9m\xd3\xe6,\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4lT\"\xfbK\x14\xe6\u064b`\x91\xfd\xecq\xf1\xf0\x86@A\x9d\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4l\\:T\u0367\xc2\xf1\x18\xed\xbaCN\xd8\x1en\xbb\x11\xddz\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4lc\xf8EV\u0490\xbf\u0359\xe44\ue657\xbf\xd7yWz\x89lk\x93[\x8b\xbd@\x00\x00\u07d4lc\xfc\x85\x02\x9a&T\u05db+\xeaM\xe3I\xe4REw\u0149#\xc7W\a+\x8d\xd0\x00\x00\u07d4led\xe5\xc9\xc2N\xaa\xa7D\xc9\xc7\xc9h\xc9\xe2\xc9\xf1\xfb\xae\x89I\x9bB\xa2\x119d\x00\x00\xe0\x94lg\xd6\xdb\x1d\x03Ql\x12\x8b\x8f\xf24\xbf=I\xb2m)A\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4lg\xe0\u05f6.*\bPiE\xa5\xdf\xe3\x82c3\x9f\x1f\"\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4lj\xa0\xd3\vdr\x19\x90\xb9PJ\x86?\xa0\xbf\xb5\xe5}\xa7\x89\x92^\x06\xee\xc9r\xb0\x00\x00\u07d4lqJX\xff\xf6\xe9}\x14\xb8\xa5\xe3\x05\xeb$@eh\x8b\xbd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4l\x80\rKI\xba\a%\x04`\xf9\x93\xb8\xcb\xe0\v&j%S\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4l\x80\x8c\xab\xb8\xff_\xbbc\x12\xd9\xc8\xe8J\xf8\xcf\x12\xef\bu\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94l\x82 )!\x8a\xc8\xe9\x8a&\f\x1e\x06@)4\x889\x87[\x8a\x01\x0f\x97\xb7\x87\xe1\xe3\b\x00\x00\u07d4l\x84\u02e7|m\xb4\xf7\xf9\x0e\xf1=^\xe2\x1e\x8c\xfc\u007f\x83\x14\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94l\x86\x87\xe3Aw\x10\xbb\x8a\x93U\x90!\xa1F\x9ej\x86\xbcw\x8a\x02[-\xa2x\xd9k{\x80\x00\xe0\x94l\x88,'s,\xef\\|\x13\xa6\x86\xf0\xa2\xeawUZ\u0089\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4l\xa5\xde\x00\x81}\xe0\xce\xdc\xe5\xfd\x00\x01(\xde\xde\x12d\x8b<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4l\xa6\xa12\xce\x1c\u0488\xbe\xe3\x0e\xc7\xcf\xef\xfb\x85\xc1\xf5\nT\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94l\xb1\x1e\xcb2\xd3\u0382\x96\x011\x066\xf5\xa1\f\xf7\u03db_\x8a\x04?\u851c8\x01\xf5\x00\x00\u07d4l\xc1\xc8x\xfal\u078a\x9a\v\x83\x11$~t\x1eFB\xfem\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94l\xcb\x03\xac\xf7\xf5<\xe8z\xad\xcc!\xa9\x93-\xe9\x15\xf8\x98\x04\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4l\xd2\x12\xae\xe0N\x01?=*\xba\u04a0#`k\xfb\\j\u01c9lj\xccg\u05f1\xd4\x00\x00\u07d4l\xd2(\xdcq!i0\u007f\xe2|\xebtw\xb4\x8c\xfc\x82r\xe5\x89\x044\xea\x94\u06caP\x00\x00\u07d4l\xe1\xb0\xf6\xad\xc4pQ\xe8\xab8\xb3\x9e\xdbA\x86\xb0;\xab\u0309Ay\x97\x94\xcd$\xcc\x00\x00\u07d4l\xea\xe3s=\x8f\xa4=l\xd8\f\x1a\x96\xe8\xeb\x93\x10\x9c\x83\xb7\x89\x10'\x94\xad \xdah\x00\x00\u07d4m\x05i\xe5U\x8f\xc7\xdf'f\xf2\xba\x15\u070a\xef\xfc[\xebu\x89\xd8\xe6\x00\x1el0+\x00\x00\u07d4m\x12\x0f\f\xaa\xe4O\xd9K\xca\xfeU\xe2\xe2y\uf5ba\\z\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4m\x14V\xff\xf0\x10N\xe8D\xa31G7\x8438\xd2L\xd6l\x89\a\xb0l\xe8\u007f\xddh\x00\x00\u07d4m \xef\x97\x04g\nP\v\xb2i\xb5\x83.\x85\x98\x02\x04\x9f\x01\x89\a\f\x1c\xc7;\x00\xc8\x00\x00\xe0\x94m/\x97g4\xb9\xd0\a\r\x18\x83\xcfz\u02b8\xb3\xe4\x92\x0f\xc1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4m9\xa9\u93c1\xf7i\xd7:\xad,\xea\xd2v\xac\x13\x87\xba\xbe\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4m;x6\xa2\xb9\u0619r\x1aM#{R#\x85\xdc\xe8\xdf\u034966\xc2^f\xec\xe7\x00\x00\u07d4m?+\xa8V\u033b\x027\xfava\x15k\x14\xb0\x13\xf2\x12@\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94m@\b\xb4\xa8\x88\xa8&\xf2H\xeej\v\r\xfd\xe9\xf92\x10\xb9\x8a\x01'\xfc\xb8\xaf\xae \xd0\x00\x00\u07d4m@\xca'\x82m\x97s\x1b>\x86\xef\xfc\u05f9*Aa\xfe\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4mD\x97J1\u0447\xed\xa1m\xddG\xb9\xc7\xecP\x02\xd6\x1f\xbe\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94mK\\\x05\xd0j \x95~\x17H\xabm\xf2\x06\xf3C\xf9/\x01\x8a\x02\x1f6\x06\x99\xbf\x82_\x80\x00\xe0\x94mL\xbf=\x82\x84\x83:\xe9\x93D0>\b\xb4\xd6\x14\xbf\xda;\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4mY\xb2\x1c\xd0\xe2t\x88\x04\u066b\xe0d\xea\u00be\xf0\xc9_'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4mc\u04ce\xe8\xb9\x0e\x0en\xd8\xf1\x92\xed\xa0Q\xb2\u05a5\x8b\xfd\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4mf4\xb5\xb8\xa4\x01\x95\xd9I\x02z\xf4\x82\x88\x02\t,\ued89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94m}\x1c\x94\x95\x11\xf8\x83\x03\x80\x8c`\xc5\xea\x06@\xfc\xc0&\x83\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4m\x84m\xc1&W\xe9\x1a\xf2P\bQ\x9c>\x85\u007fQp}\u0589\xf8\xd3\v\xc9#B\xf8\x00\x00\u07d4m\x91\x93\x99k\x19F\x17!\x11\x06\xd1c^\xb2l\u0136ll\x89\x15\xaa\x1e~\x9d\xd5\x1c\x00\x00\u07d4m\x99\x97P\x98\x82\x02~\xa9G#\x14$\xbe\xde\xde)e\u043a\x89l\x81\u01f3\x11\x95\xe0\x00\x00\u07d4m\xa0\xed\x8f\x1di3\x9f\x05\x9f*\x0e\x02G\x1c\xb4O\xb8\u00fb\x892\xbc8\xbbc\xa8\x16\x00\x00\u07d4m\xb7+\xfdC\xfe\xf4e\xcaV2\xb4Z\xabra@N\x13\xbf\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94m\xbe\x8a\xbf\xa1t(\x06&9\x817\x1b\xf3\xd3U\x90\x80kn\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4m\xc3\xf9+\xaa\x1d!\u06b78+\x892a\xa05o\xa7\xc1\x87\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4m\xc7\x05:q\x86\x16\xcf\u01cb\xeec\x82\xeeQ\xad\xd0\xc7\x030\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94m\xcc~d\xfc\xaf\xcb\xc2\xdcl\x0e^f,\xb3G\xbf\xfc\xd7\x02\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4m\xda_x\x8alh\x8d\u07d2\x1f\xa3\x85.\xb6\xd6\xc6\xc6)f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4m\xdb`\x92w\x9dXB\xea\xd3x\xe2\x1e\x81 \xfdLk\xc12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4m\xdf\xefc\x91U\u06ab\n\\\xb4\x95:\xa8\u016f\xaa\x88\x04S\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4m\xe0/-\xd6~\xfd\xb794\x02\xfa\x9e\xaa\xcb\xcfX\x9d.V\x89@\x13\x8b\x91~\u07f8\x00\x00\u07d4m\u4d418\\\xf7\xfc\x9f\xe8\xc7}\x13\x1f\xe2\xeew$\xc7j\x89})\x97s=\xcc\xe4\x00\x00\u07d4m\xe4\xd1R\x19\x18/\xaf:\xa2\xc5\xd4\xd2Y_\xf20\x91\xa7'\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4m\xed\xf6.t?M,*K\x87\xa7\x87\xf5BJz\xeb9<\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4m\xf2Of\x85\xa6/y\x1b\xa37\xbf?\xf6~\x91\xf3\u053c:\x89ukI\xd4\nH\x18\x00\x00\u07d4m\xf5\xc8O{\x90\x9a\xab>a\xfe\x0e\xcb\x1b;\xf2`\"*\u0489\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4m\xff\x90\xe6\xdc5\x9d%\x90\x88+\x14\x83\xed\xbc\xf8\x87\xc0\xe4#\x8965\u026d\xc5\u07a0\x00\x00\u07d4n\x01\xe4\xadV\x9c\x95\xd0\a\xad\xa3\r^-\xb1(\x88I\"\x94\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\a;f\u0478\xc6gD\u0600\x96\xa8\u0759\xec~\x02(\u0689\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\x0e\xe7\x06\x12\xc9v(}I\x9d\u07e6\xc0\xdc\xc1,\x06\xde\xea\x89\a\v\u0579V!F\x00\x00\xe0\x94n\x12\xb5\x1e\"[JCr\xe5\x9a\u05e2\xa1\xa1>\xa3\u04e17\x8a\x03\x00F\xc8\xccw_\x04\x00\x00\u07d4n\x1a\x04l\xaf[JW\xf4\xfdK\xc1sb!&\xb4\xe2\xfd\x86\x89a\t=|,m8\x00\x00\u07d4n\x1e\xa4\xb1\x83\xe2R\u027bwg\xa0\x06\u05346\x96\u02ca\xe9\x89\x0f\xf3x<\x85\xee\u0400\x00\u07d4n%[p\n\xe7\x13\x8aK\xac\xf2(\x88\xa9\xe2\xc0\n(^\xec\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n'\n\xd5)\xf1\xf0\xb8\xd9\xcbm$'\xec\x1b~-\xc6Jt\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4n.\xab\x85\u0709\xfe)\xdc\n\xa1\x852G\u06b4:R=V\x89\x04V9\x18$O@\x00\x00\u07d4n:Q\xdbt=3M/\xe8\x82$\xb5\xfe|\x00\x8e\x80\xe6$\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4nL*\xb7\xdb\x02i9\xdb\u04fch8J\xf6`\xa6\x18\x16\xb2\x89\t\r\x97/22<\x00\x00\u07d4nM.9\u0203f)\u5d07\xb1\x91\x8af\x9a\xeb\u07556\x8965\u026d\xc5\u07a0\x00\x00\u07d4n\\-\x9b\x1cTj\x86\xee\xfd]\nQ \xc9\xe4\xe70\x19\x0e\x89\n\xd2\x01\xa6yO\xf8\x00\x00\u07d4n`\xae\u19cf\x8e\u068bBLs\xe3S5J\xe6|0B\x89\xbd5\xa4\x8d\x99\x19\xe6\x00\x00\u07d4nd\xe6\x12\x9f\"N7\x8c\x0ensj~z\x06\xc2\x11\xe9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4nm[\xbb\xb9\x05;\x89\xd7D\xa2s\x16\u00a7\xb8\xc0\x9bT}\x891Rq\n\x02>m\x80\x00\u07d4nr\xb2\xa1\x18j\x8e)\x16T;\x1c\xb3jh\x87\x0e\xa5\u0457\x89\n\x15D\xbe\x87\x9e\xa8\x00\x00\u07d4nv\x1e\xaa\x0f4_w{TA\xb7:\x0f\xa5\xb5k\x85\xf2-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4ny\xed\u0504[\anL\u060d\x18\x8bnC-\xd9?5\xaa\x893\xc5I\x901r\f\x00\x00\u07d4n\x82\x12\xb7\"\xaf\xd4\b\xa7\xa7>\xd3\xe29^\xe6EJ\x030\x89\b\x9e\x91y\x94\xf7\x1c\x00\x00\u07d4n\x84\x87m\xbb\x95\xc4\vfV\xe4+\xa9\xae\xa0\x8a\x99;T\u0709;\xbc`\xe3\xb6\u02fe\x00\x00\u07d4n\x84\xc2\xfd\x18\xd8\tW\x14\xa9h\x17\x18\x9c\xa2\x1c\xcab\xba\xb1\x89\x12{lp&!\u0340\x00\u07d4n\x86m\x03-@Z\xbd\xd6\\\xf6QA\x1d\x807\x96\xc2#\x11\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94n\x89\x9eY\xa9\xb4\x1a\xb7\xeaA\xdfu\x17\x86\x0f*\xcbY\xf4\xfd\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4n\x89\xc5\x1e\xa6\xde\x13\xe0l\xdct\x8bg\xc4A\x0f\u9f2b\x03\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\x8a&h\x9fz/\xde\xfd\x00\x9c\xba\xaaS\x10%4P\u06ba\x89o!7\x17\xba\xd8\xd3\x00\x00\u07d4n\x96\xfa\xed\xa3\x05C\x02\xc4_X\xf1a2L\x99\xa3\xee\xbbb\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4n\xb0\xa5\xa9\xae\x96\xd2,\xf0\x1d\x8f\xd6H;\x9f8\xf0\x8c,\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xb3\x81\x96\x17@@X&\x8f\f<\xff5\x96\xbf\xe9\x14\x8c\x1c\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94n\xb5W\x8ak\xb7\xc3!S\x19[\r\x80 \xa6\x91HR\xc0Y\x8a\x8b\u00ab\xf4\x02!\xf4\x80\x00\x00\u07d4n\xbb^iW\xaa\x82\x1e\xf6Y\xb6\x01\x8a9:PL\xaeDP\x89lk\x93[\x8b\xbd@\x00\x00\u07d4n\xbc\xf9\x95\u007f_\xc5\u916d\xd4u\";\x04\xb8\xc1Jz\xed\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4n\xc3e\x95q\xb1\x1f\x88\x9d\xd49\xbc\xd4\xd6u\x10\xa2[\xe5~\x89\x06\xaa\xf7\xc8Qm\f\x00\x00\u07d4n\u021b9\xf9\xf5'jU>\x8d\xa3\x0en\xc1z\xa4~\xef\u01c9\x18BO_\v\x1bN\x00\x00\u07d4n\xc9m\x13\xbd\xb2M\u01e5W)?\x02\x9e\x02\xddt\xb9zU\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xca\xef\xa6\xfc>\xe54bm\xb0,o\x85\xa0\u00d5W\x1ew\x89 \x86\xac5\x10R`\x00\x00\u07d4n\u04a1+\x02\xf8\u0188\u01f5\u04e6\xea\x14\xd66\x87\u06b3\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4n\u0604E\x9f\x80\x9d\xfa\x10\x16\xe7p\xed\xaf>\x9f\xefF\xfa0\x89\xb8R\xd6x \x93\xf1\x00\x00\xe0\x94n\xdf\u007fR\x83r\\\x95>\xe6C\x17\xf6a\x88\xaf\x11\x84\xb03\x8a\x01\xb4d1\x1dE\xa6\x88\x00\x00\u07d4n\xe8\xaa\xd7\xe0\xa0e\u0605-|;\x9an_\xdcK\xf5\f\x00\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4n\xef\u0705\x0e\x87\xb7\x15\xc7'\x91w<\x03\x16\xc3U\x9bX\xa4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4n\xf9\xe8\u0276!}Vv\x9a\xf9}\xbb\x1c\x8e\x1b\x8b\xe7\x99\u0489\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4n\xfb\xa8\xfb*\u0176s\a)\xa9r\xec\"D&\xa2\x87\u00ed\x89\x0fY\x85\xfb\xcb\xe1h\x00\x00\xe0\x94n\xfd\x90\xb55\xe0\v\xbd\x88\x9f\xda~\x9c1\x84\xf8y\xa1Q\u06ca\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4o\x05\x16f\xcbO{\u04b1\x90r!\xb8)\xb5U\u05e3\xdbt\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4o\x0e\xdd#\xbc\xd8_`\x15\xf9(\x9c(\x84\x1f\xe0L\x83\xef\xeb\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4o\x13zq\xa6\xf1\x97\xdf,\xbb\xf0\x10\u073d\x89a\t=|,m8\x00\x00\u07d4p\x10\xbe-\xf5{\u042b\x9a\xe8\x19l\xd5\n\xb0\xc5!\xab\xa9\xf9\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4p#\xc7\tV\xe0J\x92\xd7\x00%\xaa\u0497\xb59\xaf5Xi\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p%\x96]+\x88\xda\x19}DY\xbe=\xc98cD\xcc\x1f1\x89l\xb7\xe7Hg\xd5\xe6\x00\x00\u07d4p(\x02\xf3m\x00%\x0f\xabS\xad\xbc\u0596\xf0\x17oc\x8aI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4pH\x19\xd2\xe4Mn\xd1\xda%\xbf\u0384\u011f\u0322V\x13\xe5\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4pJn\xb4\x1b\xa3O\x13\xad\xdd\xe7\xd2\xdb}\xf0I\x15\u01e2!\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4pJ\xb1\x15\r^\x10\xf5\xe3I\x95\b\xf0\xbfpe\x0f\x02\x8dK\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4pJ\xe2\x1dv-n\x1d\xde(\xc25\xd11\x04Yr6\xdb\x1a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4pM$<)x\xe4l,\x86\xad\xbe\xcd$n;)_\xf63\x89m\x12\x1b\xeb\xf7\x95\xf0\x00\x00\u07d4pM]\xe4\x84m9\xb5<\xd2\x1d\x1cI\xf0\x96\xdb\\\x19\xba)\x89\b=lz\xabc`\x00\x00\u07d4p]\xdd85T\x82\xb8\xc7\u04f5\x15\xbd\xa1P\r\xd7\u05e8\x17\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94pan(\x92\xfa&\x97\x05\xb2\x04k\x8f\xe3\xe7/\xa5X\x16\u04ca\x04<3\xc1\x93ud\x80\x00\x00\u07d4pg\x0f\xbb\x05\xd30\x14DK\x8d\x1e\x8ew\x00%\x8b\x8c\xaam\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\x81\xfak\xaa\xd6\u03f7\xf5\x1b,\xca\x16\xfb\x89p\x99\x1ad\xba\x89\f\xae\xc0\x05\xf6\xc0\xf6\x80\x00\xe0\x94p\x85\xae~~M\x93!\x97\xb5\u01c5\x8c\x00\xa3gF&\xb7\xa5\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4p\x86\xb4\xbd\xe3\xe3]J\xeb$\xb8%\xf1\xa2\x15\xf9\x9d\x85\xf7E\x89lh\xcc\u041b\x02,\x00\x00\u07d4p\x8a*\xf4%\u03b0\x1e\x87\xff\xc1\xbeT\xc0\xf52\xb2\x0e\xac\u0589\aE\u0503\xb1\xf5\xa1\x80\x00\u07d4p\x8e\xa7\a\xba\xe45\u007f\x1e\xbe\xa9Y\u00e2P\xac\u05aa!\xb3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794p\x8f\xa1\x1f\xe3=\x85\xad\x1b\xef\u02ee8\x18\xac\xb7\x1fj}~\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4p\x9101\x16\xd5\xf28\x9b##\x8bMej\x85\x96\u0644\u04c9;N~\x80\xaaX3\x00\x00\u07d4p\x99\xd1/n\xc6V\x89\x9b\x04\x9avW\x06]b\x99h\x92\u0209\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4p\x9f\xe9\xd2\xc1\xf1\xceB |\x95\x85\x04J`\x89\x9f5\x94/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\xa05I\xaaah\xe9~\x88\xa5\b3\nZ\v\xeatq\x1a\x89Hz\x9a0E9D\x00\x00\u07d4p\xa4\x06}D\x8c\xc2]\xc8\xe7\x0ee\x1c\xea|\xf8N\x92\x10\x9e\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4p\xab4\xbc\x17\xb6o\x9c;c\xf1Q'O*r|S\x92c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4p\xc2\x13H\x8a\x02\f<\xfb9\x01N\xf5\xbad\x04rK\u02a3\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4p\xd2^\xd2\u022d\xa5\x9c\b\x8c\xf7\r\xd2+\xf2\u06d3\xac\xc1\x8a\x899GEE\u4b7c\x00\x00\u07d4p\xe5\xe9\xdas_\xf0w$\x9d\u02da\xaf=\xb2\xa4\x8d\x94\x98\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4p\xfe\xe0\x8b\x00\xc6\xc2\xc0Jp\xc0\xce=\x92\u03ca\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u0794q\v\xe8\xfd^)\x18F\x8b\u2abe\xa8\r\x82\x845\u05d6\x12\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4q\x13]\x8f\x05\x96<\x90ZJ\a\x92)\t#Z\x89jR\ua262\xa1]\tQ\x9b\xe0\x00\x00\u07d4q\x1e\xcfw\xd7\x1b=\x0e\xa9\\\xe4u\x8a\xfe\u0379\xc11\a\x9d\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4q!?\xca14\x04 N\u02e8q\x97t\x1a\xa9\xdf\xe9c8\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94q+vQ\x02\x14\xdcb\x0fl:\x1d\u049a\xa2+\xf6\xd2\x14\xfb\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4q/\xf77\n\x13\xed6\ts\xfe\u071f\xf5\xd2\xc9:P^\x9e\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4q3\x84:x\xd99\u019dD\x86\xe1\x0e\xbc{`*4\x9f\xf7\x89\x11\xd5\xca\xcc\xe2\x1f\x84\x00\x00\u07d4qH\xae\xf32a\xd8\x03\x1f\xac?q\x82\xff5\x92\x8d\xafT\u0649\xdeB\xee\x15D\u0750\x00\x00\u07d4qcu\x8c\xbblLR^\x04\x14\xa4\n\x04\x9d\xcc\xcc\xe9\x19\xbb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4qh\xb3\xbb\x8c\x16s!\u067d\xb0#\xa6\xe9\xfd\x11\xaf\u026f\u0649a\t=|,m8\x00\x00\u07d4qirN\xe7\"q\xc54\xca\xd6B\x0f\xb0N\xe6D\u02c6\xfe\x89\x16<+@\u06e5R\x00\x00\u07d4qj\xd3\xc3:\x9b\x9a\n\x18\x96sW\x96\x9b\x94\xee}*\xbc\x10\x89\x1a!\x17\xfeA*H\x00\x00\xe0\x94qk\xa0\x1e\xad*\x91'\x065\xf9_%\xbf\xaf-\xd6\x10\xca#\x8a\ty\xe7\x01 V\xaax\x00\x00\u07d4qmP\u0320\x1e\x93\x85\x00\xe6B\x1c\xc0p\xc3P|g\u04c7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4qv,cg\x8c\x18\xd1\xc67\x8c\xe0h\xe6f8\x13\x15\x14~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4qxL\x10Q\x17\xc1\xf6\x895y\u007f\xe1Y\xab\xc7NC\xd1j\x89l\x81\u01f3\x11\x95\xe0\x00\x00\xe0\x94qyro\\q\xae\x1bm\x16\xa6\x84(\x17Nk4\xb26F\x8a\x01\x8e\xa2P\t|\xba\xf6\x00\x00\xe0\x94q|\xf9\xbe\xab680\x8d\xed~\x19^\f\x86\x13-\x16?\xed\x8a\x032n\xe6\xf8e\xf4\"\x00\x00\u07d4q\x80\xb8>\xe5WC\x17\xf2\x1c\x80r\xb1\x91\u0615\xd4aS\u00c9\x18\xef\xc8J\xd0\u01f0\x00\x00\u07d4q\x94kq\x17\xfc\x91^\xd1\a8_B\u065d\xda\xc62I\u0089lk\x93[\x8b\xbd@\x00\x00\xe0\x94q\x9e\x89\x1f\xbc\xc0\xa3>\x19\xc1-\xc0\xf0 9\xca\x05\xb8\x01\u07ca\x01OU8F:\x1bT\x00\x00\u07d4q\xc7#\n\x1d5\xbd\u0581\x9e\u0539\xa8\x8e\x94\xa0\xeb\a\x86\u0749\uc80b5=$\x14\x00\x00\u07d4q\xd2\xccm\x02W\x8ce\xf7\r\xf1\x1bH\xbe\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4r\x83\xcdFu\xdaX\u0116UaQ\xda\xfd\x80\xc7\xf9\x95\xd3\x18\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4r\x86\xe8\x9c\xd9\u078fz\x8a\x00\xc8o\xfd\xb59\x92\u0752Q\u0449i*\xe8\x89p\x81\xd0\x00\x00\u07d4r\x8f\x9a\xb0\x80\x15}\xb3\a1V\xdb\xca\x1a\x16\x9e\xf3\x17\x94\a\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4r\x94\xc9\x18\xb1\xae\xfbM%\x92~\xf9\u05d9\xe7\x1f\x93\xa2\x8e\x85\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94r\x94\uc763\x10\xbckK\xbd\xf5C\xb0\xefE\xab\xfc>\x1bM\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4r\x9a\xadF'tNS\xf5\xd6c\t\xaatD\x8b:\xcd\xf4o\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xa2\xfc\x86u\xfe\xb9r\xfaA\xb5\r\xff\u06fa\xe7\xfa*\u07f7\x89\x9a\xb4\xfcg\xb5(\xc8\x00\x00\u07d4r\xa8&\b&)G&\xa7[\xf3\x9c\u066a\x9e\a\xa3\xea\x14\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4r\xb0Yb\xfb*\u0549\xd6Z\xd1j\"U\x9e\xba\x14X\xf3\x87\x89\a?u\u0460\x85\xba\x00\x00\u07d4r\xb5c?\xe4w\xfeT.t/\xac\xfdi\f\x13xT\xf2\x16\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4r\xb7\xa0=\xda\x14\u029cf\x1a\x1dF\x9f\xd376\xf6s\xc8\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xb9\x04D\x0e\x90\xe7 \u05ac\x1c*\u05dc2\x1d\xcc\x1c\x1a\x86\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94r\xb9\nM\xc0\x97#\x94\x92\u0179w}\xcd\x1eR\xba+\xe2\u008a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4r\xbb'\u02d9\xf3\xe2\xc2\u03d0\xa9\x8fp}0\xe4\xa2\x01\xa0q\x89X\xe7\x92n\xe8X\xa0\x00\x00\xe0\x94r\xc0\x83\xbe\xad\xbd\xc2'\xc5\xfbC\x88\x15\x97\xe3.\x83\xc2`V\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4r\xcd\x04\x8a\x11\x05tH)\x83I-\xfb\x1b\xd2yB\xa6\x96\xba\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xd0=M\xfa\xb3P\f\xf8\x9b\x86\x86o\x15\xd4R\x8e\x14\xa1\x95\x89\xf3K\x82\xfd\x8e\x91 \x00\x00\u07d4r\u06bb[n\ud799\xbe\x91X\x88\xf6V\x80V8\x16\b\xf8\x89\vL\x96\xc5,\xb4\xfe\x80\x00\u07d4r\xfbI\u009d#\xa1\x89P\u0132\xdc\r\xdfA\x0fS-oS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4r\xfe\xaf\x12EyR9Td[\u007f\xaf\xff\x03x\xd1\xc8$.\x8965\u026d\xc5\u07a0\x00\x00\u07d4s\x01\xdcL\xf2mq\x86\xf2\xa1\x1b\xf8\xb0\x8b\xf2)F?d\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s\x04G\xf9|\xe9\xb2_\"\xba\x1a\xfb6\xdf'\xf9Xk\ub6c9,s\xc97t,P\x00\x00\u07d4s\x06\xde\x0e(\x8bV\xcf\u07d8~\xf0\xd3\xcc)f\a\x93\xf6\u0749\x1b\x8a\xbf\xb6.\xc8\xf6\x00\x00\xe0\x94s\r\x87c\u01a4\xfd\x82J\xb8\xb8Y\x16\x1e\xf7\xe3\xa9j\x12\x00\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4s\x12\x81sH\x95(\x01.v\xb4\x1a^(\u018b\xa4\xe3\xa9\u050965\u026d\xc5\u07a0\x00\x00\u07d4s\x13F\x12\bETUFTE\xa4Y\xb0l7s\xb0\xeb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s/\xea\xd6\x0f{\xfd\u05a9\xde\u0101%\xe3s]\xb1\xb6eO\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4sB#\xd2\u007f\xf2>Y\x06\xca\xed\"YW\x01\xbb4\x83\f\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4sG>r\x11Q\x10\xd0\xc3\xf1\x17\b\xf8nw\xbe+\xb0\x98<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4sRXm\x02\x1a\xd0\xcfw\xe0\xe9(@JY\xf3t\xffE\x82\x89\xb8Pz\x82\a( \x00\x00\u07d4sU\v\xebs+\xa9\u076f\xdaz\xe4\x06\xe1\x8f\u007f\xeb\x0f\x8b\xb2\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4s[\x97\xf2\xfc\x1b\xd2K\x12\an\xfa\xf3\xd1(\x80s\xd2\f\x8c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4s^2\x86f\xedV7\x14+3\x06\xb7|\xccT`\xe7,=\x89j\xb8\xf3xy\u0251\x00\x00\u07d4sc\u0350\xfb\xab[\xb8\u011a\xc2\x0f\xc6,9\x8f\xe6\xfbtL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4skDP=\xd2\xf6\xddTi\xffL[-\xb8\xeaO\xece\u0409\x11\x04\xeeu\x9f!\xe3\x00\x00\xe0\x94sk\xf1@,\x83\x80\x0f\x89>X1\x92X*\x13N\xb52\xe9\x8a\x02\x1e\x19\u0493\xc0\x1f&\x00\x00\xe0\x94s\x8c\xa9M\xb7\u038b\xe1\xc3\x05l\u0598\x8e\xb3v5\x9f3S\x8a\x05f[\x96\xcf5\xac\xf0\x00\x00\u07d4s\x91K\"\xfc/\x13\x15\x84$}\x82\xbeO\ucfd7\x8a\u053a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4s\x93'\t\xa9\u007f\x02\u024eQ\xb0\x911(e\x12#\x85\xae\x8e\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4s\x93\xcb\xe7\xf9\xba!e\xe5\xa7U5\x00\xb6\xe7]\xa3\xc3:\xbf\x89\x05k\xc7^-c\x10\x00\x00\u07d4s\xb4\u0519\xde?8\xbf5\xaa\xf7i\xa6\xe3\x18\xbcm\x126\x92\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94s\xbe\xddo\xda{\xa3'!\x85\b{cQ\xfc\x13=HN7\x8a\x01\x12&\xbf\x9d\xceYx\x00\x00\u07d4s\xbf\xe7q\x0f1\u02b9I\xb7\xa2`O\xbfR9\xce\xe7\x90\x15\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94s\u03c0\xae\x96\x88\xe1X\x0eh\xe7\x82\xcd\b\x11\xf7\xaaIM,\x8a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\xe0\x94s\xd7&\x9f\xf0l\x9f\xfd3uL\xe5\x88\xf7J\x96j\xbb\xbb\xba\x8a\x01e\xc9fG\xb3\x8a \x00\x00\u07d4s\xd8\xfe\xe3\u02c6M\xce\"\xbb&\u029c/\bm^\x95\xe6;\x8965\u026d\xc5\u07a0\x00\x00\u07d4s\xdf<>yU\xf4\xf2\xd8Y\x83\x1b\xe3\x80\x00\xb1\ak8\x84\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4s\u48b6\f\U0010e2ef+w~\x17Z[\x1eM\f-\x8f\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94t\n\xf1\xee\xfd3e\u05cb\xa7\xb1,\xb1\xa6s\xe0j\arF\x8a\x04+\xf0kx\xed;P\x00\x00\xe0\x94t\v\xfdR\xe0\x16g\xa3A\x9b\x02\x9a\x1b\x8eEWj\x86\xa2\u06ca\x03\x8e\xba\xd5\xcd\xc9\x02\x80\x00\x00\u07d4t\x0fd\x16\x14w\x9d\u03e8\x8e\xd1\xd4%\xd6\r\xb4*\x06\f\xa6\x896\"\xc6v\b\x10W\x00\x00\u07d4t\x12\u027c0\xb4\xdfC\x9f\x021\x00\xe69$\x06j\xfdS\xaf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4t\x16\x93\xc3\x03vP\x85\x13\b \xcc+c\xe9\xfa\x92\x13\x1b\x89A\rXj \xa4\xc0\x00\x00\u07d4t!\xce[\xe3\x81s\x8d\u0703\xf0&!\x97O\xf0hly\xb8\x89Xx\x8c\xb9K\x1d\x80\x00\x00\u07d4t1j\xdf%7\x8c\x10\xf5v\u0574\x1aoG\xfa\x98\xfc\xe3=\x89\x128\x13\x1e\\z\xd5\x00\x00\u07d4t6Q\xb5^\xf8B\x9d\xf5\f\xf8\x198\xc2P\x8d\xe5\u0207\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t=\xe5\x00&\xcag\xc9M\xf5O\x06b`\xe1\xd1J\xcc\x11\xac\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tE /\ft)z\x00N\xb3rj\xa6\xa8-\xd7\xc0/\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tK\x03\xbb\xa8X*\xe5I\x8e-\xc2-\x19\x94\x94g\xabS\xfc\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4tL\fw\xba\u007f#i \xd1\xe44\xde]\xa3>H\xeb\xf0,\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4tP\xff\u007f\x99\xea\xa9\x11bu\u07ach\xe4(\xdf[\xbc\u0639\x89lk\x93[\x8b\xbd@\x00\x00\u07d4tV\u0172\xc5Cn>W\x10\b\x93?\x18\x05\xcc\xfe4\xe9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4tZ\u04eb\xc6\xee\xeb$qh\x9bS\x9ex\x9c\xe2\xb8&\x83\x06\x89=A\x94\xbe\xa0\x11\x92\x80\x00\xe0\x94tZ\xec\xba\xf9\xbb9\xb7Jg\xea\x1c\xe6#\xde6\x84\x81\xba\xa6\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4t\\\xcf-\x81\x9e\u06fd\u07a8\x11{\\I\xed<*\x06n\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4tb\u021c\xaa\x9d\x8dx\x91\xb2T]\xef!otd\u057b!\x89\x05\xea\xedT\xa2\x8b1\x00\x00\u07d4td\x8c\xaa\xc7H\xdd\x13\\\xd9\x1e\xa1L(\xe1\xbdM\u007f\xf6\xae\x89\xa8\r$g~\xfe\xf0\x00\x00\xe0\x94tq\xf7.\xeb0\x06$\xeb(.\xabM\x03r\x00\x00\x00\xe0\x94t\x84\xd2k\xec\xc1\xee\xa8\xc61^\xc3\xee\nE\x01\x17\u0706\xa0\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4t\x86:\xce\xc7]\x03\xd5>\x86\x0ed\x00/,\x16^S\x83w\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\x89\u030a\xbeu\u0364\xef\r\x01\xce\xf2`^G\xed\xa6z\xb1\x89\a?u\u0460\x85\xba\x00\x00\u07d4t\x8c(^\xf1#?\xe4\xd3\x1c\x8f\xb17\x833r\x1c\x12\xe2z\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t\x90\x87\xac\x0fZ\x97\xc6\xfa\xd0!S\x8b\xf1\xd6\u0361\x8e\r\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\x95\xaex\xc0\xd9\x02a\xe2\x14\x0e\xf2\x061\x04s\x1a`\xd1\xed\x89\x01\xdbPq\x89%!\x00\x00\u07d4t\x9aJv\x8b_#rH\x93\x8a\x12\xc6#\x84{\xd4\xe6\x88\u0709\x03\xe73b\x87\x14 \x00\x00\u07d4t\x9a\xd6\xf2\xb5pk\xbe/h\x9aD\u0136@\xb5\x8e\x96\xb9\x92\x89\x05k\xc7^-c\x10\x00\x00\u07d4t\xa1\u007f\x06K4N\x84\xdbce\u0695\x91\xff\x16(%vC\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4t\xae\xec\x91]\xe0\x1c\u019b,\xb5\xa65o\xee\xa1FX\xc6\u0149\f\x9a\x95\xee)\x86R\x00\x00\u07d4t\xaf\xe5I\x02\xd6\x15x%v\xf8\xba\xac\x13\xac\x97\f\x05\x0fn\x89\t\xa1\xaa\xa3\xa9\xfb\xa7\x00\x00\u07d4t\xb7\xe0\"\x8b\xae\xd6YW\xae\xbbM\x91m3:\xae\x16O\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4t\xbcJ^ E\xf4\xff\x8d\xb1\x84\xcf:\x9b\f\x06Z\xd8\a\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4t\xbc\xe9\xec86-l\x94\u032c&\xd5\xc0\xe1:\x8b;\x1d@\x8965&A\x04B\xf5\x00\x00\u07d4t\xbfzZ\xb5\x92\x93\x14\x9b\\`\xcf6Bc\xe5\xeb\xf1\xaa\r\x89\x06G\f>w\x1e<\x00\x00\xe0\x94t\xc7<\x90R\x8a\x15s6\xf1\xe7\xea b\n\xe5?\xd2G(\x8a\x01\xe6:.S\x8f\x16\xe3\x00\x00\u07d4t\u0464\xd0\xc7RN\x01\x8dN\x06\xed;d\x80\x92\xb5\xb6\xaf,\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94t\xd3f\xb0{/VG}|pw\xaco\xe4\x97\xe0\xebeY\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4t\xd3zQt{\xf8\xb7q\xbf\xbfC\x9493\xd1\x00\xd2\x14\x83\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\xd6q\u065c\xbe\xa1\xabW\x90cu\xb6?\xf4+PE\x1d\x17\x8965\u026d\xc5\u07a0\x00\x00\u07d4t\xeb\xf4BVF\xe6\u03c1\xb1\t\xce{\xf4\xa2\xa6=\x84\x81_\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4t\xed3\xac\xf4?5\xb9\x8c\x920\xb9\xe6d.\xcbS0\x83\x9e\x89$\xf6\xdf\xfbI\x8d(\x00\x00\u07d4t\xef(i\xcb\xe6\b\x85`E\xd8\xc2\x04\x11\x18W\x9f\"6\xea\x89\x03<\xd6E\x91\x95n\x00\x00\u07d4t\xfcZ\x99\xc0\xc5F\x05\x03\xa1;\x05\tE\x9d\xa1\x9c\xe7\u0350\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4u\v\xbb\x8c\x06\xbb\xbf$\bC\xccux.\xe0/\b\xa9tS\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4u\x14\xad\xbd\xc6?H?0M\x8e\x94\xb6\u007f\xf30\x9f\x18\v\x82\x89!\u0120n-\x13Y\x80\x00\u0794u\x17\xf1l(\xd12\xbb@\xe3\xba6\u01ae\xf11\xc4b\xda\x17\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4u\x1a,\xa3Nq\x87\xc1c\u048e6\x18\xdb(\xb1<\x19m&\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94u\x1a\xbc\xb6\xcc\x030Y\x91\x18\x15\xc9o\u04516\n\xb0D-\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4u&\xe4\x82R\x9f\n\x14\xee\u0248q\xdd\xdd\x0er\x1b\f\u0662\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4u)\xf3y{\xb6\xa2\x0f~\xa6I$\x19\xc8L\x86vA\xd8\x1c\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94u*^\xe22a,\xd3\x00_\xb2n[Y}\xe1\x9fwk\xe6\x8a\x01'\xfc\xb8\xaf\xae \xd0\x00\x00\u07d4u,\x9f\xeb\xf4/f\xc4x{\xfa~\xb1|\xf53;\xbaPp\x89j\x99\xf2\xb5O\xddX\x00\x00\u07d4u930F\u07b1\xef\x8e\u07b9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94u\xc1\xad#\xd2?$\xb3\x84\xd0\xc3\x14\x91w\xe8f\x97a\r!\x8a\x01\\[\xcdl(\x8b\xbd\x00\x00\u07d4u\xc2\xff\xa1\xbe\xf5I\x19\xd2\t\u007fz\x14-.\x14\xf9\xb0JX\x89\x90\xf3XP@2\xa1\x00\x00\u07d4u\xd6|\xe1N\x8d)\xe8\xc2\xff\u3051{\x93\v\x1a\xff\x1a\x87\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4u\xde~\x93R\xe9\v\x13\xa5\x9aXx\xff\xec\u01c3\x1c\xacM\x82\x89\x94\x89#z\u06daP\x00\x00\u07d4u\xf7S\x9d0\x9e\x909\x98\x9e\xfe.\x8b-\xbd\x86Z\r\xf0\x88\x89\x85[[\xa6\\\x84\xf0\x00\x00\u07d4v\b\xf47\xb3\x1f\x18\xbc\vd\u04c1\xae\x86\xfd\x97\x8e\u05f3\x1f\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94v\x0f\xf35N\x0f\u0793\x8d\x0f\xb5\xb8,\xef[\xa1\\=)\x16\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4v\x1an6,\x97\xfb\xbd|Yw\xac\xba-\xa7F\x876_I\x89\t\xf7J\xe1\xf9S\xd0\x00\x00\u07d4v\x1el\xae\xc1\x89\xc20\xa1b\xec\x00e0\x19>g\u03dd\x19\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94v\x1f\x8a:*\U00028f7e\x1d\xa0\t2\x1f\xb2\x97d\xebb\xa1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4v)\x98\xe1\xd7R'\xfc\xedzp\xbe\x10\x9aL\vN\xd8d\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4v-o0\u06b9\x915\xe4\xec\xa5\x1dRC\xd6\xc8b\x11\x02\u0549\x0fI\x89A\xe6d(\x00\x00\u07d4v3\x1e0yl\xe6d\xb2p\x0e\rASp\x0e\u0706\x97w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v8\x86\xe33\xc5o\xef\xf8[\xe3\x95\x1a\xb0\xb8\x89\xce&.\x95\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v:|\xba\xb7\rzd\u0427\xe5)\x80\xf6\x81G%\x93I\f\x89 \x86\xac5\x10R`\x00\x00\u07d4v>\xec\u0c0a\u021e2\xbf\xa4\xbe\xcev\x95\x14\xd8\xcb[\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4v@\xa3\u007f\x80R\x98\x15\x15\xbc\xe0x\u0693\xaf\xa4x\x9bW4\x89lk\x93[\x8b\xbd@\x00\x00\u0794vA\xf7\xd2j\x86\xcd\xdb+\xe10\x81\x81\x0e\x01\xc9\xc8E\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94vO\xc4mB\x8bm\xbc\"\x8a\x0f_U\xc9P\x8cw.\xab\x9f\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4vPn\xb4\xa7\x80\xc9Q\xc7J\x06\xb0=;\x83b\xf0\x99\x9dq\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94v[\xe2\xe1/b\x9ecI\xb9}!\xb6*\x17\xb7\xc80\xed\xab\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94vb\x81P\xe2\x99[['\x9f\xc8>\r\xd5\xf1\x02\xa6q\xdd\x1c\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4vk7Y\xe8yN\x92m\xacG=\x91:\x8f\xb6\x1a\xd0\xc2\u0249\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4vp\xb0/,<\xf8\xfdOG0\xf38\x1aq\xeaC\x1c3\u01c9\x0e~\xeb\xa3A\vt\x00\x00\u07d4vz\x03eZ\xf3`\x84\x1e\x81\r\x83\xf5\xe6\x1f\xb4\x0fL\xd1\x13\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4vz\u0190y\x1c.#E\x10\x89\xfelp\x83\xfeU\u07b6+\x89,s\xc97t,P\x00\x00\u07d4v\u007f\xd7y}Qi\xa0_sd2\x1c\x19\x84:\x8c4\x8e\x1e\x89\x01\x04\xe7\x04d\xb1X\x00\x00\u0794v\x84o\r\xe0;Zv\x97\x1e\xad)\x8c\xdd\b\x84:K\xc6\u0188\xd7\x1b\x0f\u088e\x00\x00\xe0\x94v\x84\x98\x93N7\xe9\x05\xf1\xd0\xe7{D\xb5t\xbc\xf3\xecJ\xe8\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4v\x8c\xe0\u06a0)\xb7\xde\xd0\"\xe5\xfcWM\x11\xcd\xe3\xec\xb5\x17\x89\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\xe0\x94v\x93\xbd\xebo\xc8+[\xcar\x13U\"1u\xd4z\bKM\x8a\x04\xa8\x9fT\xef\x01!\xc0\x00\x00\u07d4v\xaa\xf8\xc1\xac\x01/\x87R\xd4\xc0\x9b\xb4f\a\xb6e\x1d\\\xa8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4v\xab\x87\xddZ\x05\xad\x83\x9aN/\xc8\xc8Z\xa6\xba\x05d\x170\x89lk\x93[\x8b\xbd@\x00\x00\u07d4v\xaf\xc2%\xf4\xfa0}\xe4\x84U+\xbe\x1d\x9d?\x15\aLJ\x89\xa2\x90\xb5\u01ed9h\x00\x00\xe0\x94v\xbe\xca\xe4\xa3\x1d6\xf3\xcbW\u007f*CYO\xb1\xab\xc1\xbb\x96\x8a\x05C\xa9\xce\x0e\x132\xf0\x00\x00\u07d4v\xc2u5\xbc\xb5\x9c\xe1\xfa-\x8c\x91\x9c\xab\xebJk\xba\x01\u0449lk\x93[\x8b\xbd@\x00\x00\u07d4v\xca\"\xbc\xb8y\x9eS'\u012a*}\tI\xa1\xfc\xce_)\x89R\xa0?\"\x8cZ\xe2\x00\x00\u07d4v\xca\u0108\x11\x1aO\u0555\xf5h\xae:\x85\x87p\xfc\x91]_\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94v\u02dc\x8bi\xf48vu\u0102S\xe24\xcb~\rt\xa4&\x8a\x01\x90\xf4H.\xb9\x1d\xae\x00\x00\u07d4v\xf8:\xc3\xda0\xf7\t&(\xc73\x9f \x8b\xfc\x14,\xb1\ue25a\x18\xff\xe7B}d\x00\x00\xe0\x94v\xf9\xad=\x9b\xbd\x04\xae\x05\\\x14w\xc0\xc3^u\x92\xcb* \x8a\b\x83?\x11\xe3E\x8f \x00\x00\u07d4v\xff\xc1W\xadk\xf8\xd5m\x9a\x1a\u007f\u077c\x0f\xea\x01\n\xab\xf4\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\x02\x8e@\x9c\xc4:;\xd3=!\xa9\xfcS\xec`n\x94\x91\x0e\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4w\f/\xb2\u0128\x17S\xac\x01\x82\xeaF\x0e\xc0\x9c\x90\xa5\x16\xf8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4w\r\x98\xd3\x1bCS\xfc\xee\xe8V\fL\u03c0>\x88\xc0\xc4\xe0\x89 \x86\xac5\x10R`\x00\x00\xe0\x94w\x13\xab\x807A\x1c\t\xbah\u007fo\x93d\xf0\xd3#\x9f\xac(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4w\x15\a\xae\xeej%]\xc2\u035d\xf5QT\x06-\b\x97\xb2\x97\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4w\x19\x88\x87\x95\xadtY$\xc7W`\u0771\x82}\xff\xd8\u0368\x89lkLM\xa6\u077e\x00\x00\u07d4w'\xaf\x10\x1f\n\xab\xa4\xd2:\x1c\xaf\xe1|n\xb5\u06b1\xc6\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4w,)\u007f\n\u0454H.\xe8\xc3\xf06\xbd\xeb\x01\xc2\x01\xd5\u0309\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94w0o\xfe.J\x8f<\xa8&\xc1\xa2I\xf7!-\xa4:\xef\xfd\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4w1A\x12}\x8c\xf3\x18\xae\xbf\x886Z\xdd=U'\xd8[j\x8966\u05ef^\u024e\x00\x00\u07d4wF\xb6\xc6i\x9c\x8f4\xca'h\xa8 \xf1\xff\xa4\xc2\a\xfe\x05\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4wQ\xf3c\xa0\xa7\xfd\x053\x19\b\t\u076f\x93@\xd8\xd1\x12\x91\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4wW\xa4\xb9\xcc=\x02G\u032a\xeb\x99\t\xa0\xe5n\x1d\xd6\xdc\u0089\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4w\\\x10\xc9>\r\xb7 [&CE\x823\xc6O\xc3?\xd7[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4wa~\xbcK\xeb\xc5\xf5\xdd\xeb\x1bzp\xcd\xebj\xe2\xff\xa0$\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4wiC\xff\xb2\xef\\\xdd5\xb8<(\xbc\x04k\xd4\xf4gp\x98\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94wp\x1e,I=\xa4|\x1bX\xf4!\xb5I]\xeeE\xbe\xa3\x9b\x8a\x01H\xf6I\xcfaB\xa5\x80\x00\u07d4wy\x8f \x12W\xb9\xc3R\x04\x95pW\xb5Ft\xae\xfaQ\u07c9\b\x13\xcaV\x90m4\x00\x00\u07d4w\x8cC\xd1\x1a\xfe;Xo\xf3t\x19-\x96\xa7\xf2=+\x9b\u007f\x89\x8b\xb4\xfc\xfa;}k\x80\x00\u07d4w\x8cy\xf4\xde\x19S\xeb\u0398\xfe\x80\x06\xd5:\x81\xfbQ@\x12\x8963\x03\"\xd5#\x8c\x00\x00\u07d4w\x92t\xbf\x18\x03\xa36\xe4\u04f0\r\u0753\xf2\xd4\xf5\xf4\xa6.\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\xa1q\"\xfa1\xb9\x8f\x17\x11\xd3*\x99\xf0>\xc3&\xf3=\b\x89\\(=A\x03\x94\x10\x00\x00\u07d4w\xa3I\a\xf3\x05\xa5L\x85\xdb\t\xc3c\xfd\xe3\xc4~j\xe2\x1f\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4w\xa7i\xfa\xfd\xec\xf4\xa68v-[\xa3\x96\x9d\xf61 \xa4\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4w\xbekd\xd7\xc73\xa46\xad\xec^\x14\xbf\x9a\xd7@+\x1bF\x8965\u026d\xc5\u07a0\x00\x00\u07d4w\xbf\xe9<\u0367P\x84~A\xa1\xaf\xfe\xe6\xb2\u0696\xe7!N\x89\x10CV\x1a\x88)0\x00\x00\u07d4w\u0126\x97\xe6\x03\xd4+\x12\x05l\xbb\xa7a\xe7\xf5\x1d\x04C\xf5\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4w\xcc\x02\xf6#\xa9\u03d8S\t\x97\xeag\xd9\\;I\x18Y\xae\x89Is\x03\xc3n\xa0\xc2\x00\x00\u07d4w\xd4?\xa7\xb4\x81\xdb\xf3\xdbS\f\xfb\xf5\xfd\xce\xd0\xe6W\x181\x89lk\x93[\x8b\xbd@\x00\x00\u07d4w\xda^lr\xfb6\xbc\xe1\xd9y\x8f{\xcd\xf1\u044fE\x9c.\x89\x016\x95\xbbl\xf9>\x00\x00\u07d4w\xf4\xe3\xbd\xf0V\x88<\xc8r\x80\xdb\xe6@\xa1\x8a\r\x02\xa2\a\x89\n\x81\x99:+\xfb[\x00\x00\u0794w\xf6\t\u0287 \xa0#&,U\xc4o-&\xfb90\xaci\x88\xf0\x15\xf2W6B\x00\x00\u07d4w\xf8\x1b\x1b&\xfc\x84\xd6\u0797\uf2df\xbdr\xa310\xccJ\x8965\u026d\xc5\u07a0\x00\x00\u07d4x\x19\xb0E\x8e1N+S\xbf\xe0\f8I_\u0539\xfd\xf8\u0589\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4x\x1b\x15\x01dz.\x06\xc0\xedC\xff\x19\u007f\xcc\xec5\xe1p\v\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4x/R\xf0\xa6v\xc7w\x16\xd5t\xc8\x1e\xc4hO\x9a\x02\n\x97\x89.\x14\xe2\x06\xb70\xad\x80\x00\u07d4x5]\xf0\xa20\xf8=\x03,p1TAM\xe3\xee\u06b5W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4x6\xf7\xefk\u01fd\x0f\xf3\xac\xafD\x9c\x84\xddk\x1e,\x93\x9f\x89\xe0\x8d\xe7\xa9,\xd9|\x00\x00\u07d4x7\xfc\xb8v\xda\x00\xd1\xeb;\x88\xfe\xb3\xdf?\xa4\x04/\xac\x82\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4x>\uc2a5\xda\xc7{.f#\xedQ\x98\xa41\xab\xba\xee\a\x89\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4x\\\x8e\xa7t\xd70D\xa74\xfay\n\x1b\x1et>w\xed|\x89\f\xf1Rd\f\\\x83\x00\x00\u07d4x`\xa3\xde8\xdf8*\xe4\xa4\xdc\xe1\x8c\f\a\xb9\x8b\xce=\xfa\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94xcCq\xe1s\x04\xcb\xf39\xb1E*L\xe48\xdcvL\u038a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4xd\u0719\x9f\xe4\xf8\xe0\x03\xc0\xf4=\xec\u00da\xae\x15\"\xdc\x0f\x89\x05\x1e\x10+\xd8\xec\xe0\x00\x00\u07d4xtj\x95\x8d\xce\xd4\xc7d\xf8vP\x8cAJh4,\uce49\x02\xbe7O\xe8\xe2\xc4\x00\x00\xe0\x94x}1?\xd3k\x05>\xee\xae\xdb\xcet\xb9\xfb\x06x32\x89\x8a\x05\xc0X\xb7\x84'\x19`\x00\x00\u07d4x\x85\x9c[T\x8bp\r\x92\x84\xce\xe4\xb6c=GJ\x8a\x04{\x92\xc4\x15B$-\n\b\xc7\x0f\x99\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4x\u03c36\xb3(\xdb=\x87\x81:G+\x9e\x89\xb7^\f\xf3\xbc\x8965\u026d\xc5\u07a0\x00\x00\u07d4x\xd4\xf8\xc7\x1c\x1eh\xa6\x9a\x98\xf5/\xcbE\u068a\xf5n\xa1\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4x\xdf&\x81\xd6\xd6\x02\xe2!B\xd5A\x16\u07a1]EIW\xaa\x89\x10'\x94\xad \xdah\x00\x00\u07d4x\xe0\x8b\xc53A<&\u2473\x14?\xfa|\u026f\xb9{x\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4x\xe8?\x80\xb3g\x8cz\nN>\x8c\x84\xdc\xcd\xe0dBbw\x89a\t=|,m8\x00\x00\u07d4x\xf5\xc7G\x85\xc5f\x8a\x83\x80r\x04\x8b\xf8\xb4SYM\u06ab\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4y\x0f\x91\xbd]\x1c\\\xc4s\x9a\xe9\x13\x00\u06c9\xe1\xc10<\x93\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\x17\u5f42\xa9y\x0f\xd6P\xd0C\xcd\xd90\xf7y\x963\u06c9\xd8\xd4`,&\xbfl\x00\x00\u07d4y\x19\xe7b\u007f\x9b}T\xea;\x14\xbbM\xd4d\x9fO9\xde\xe0\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4y\x1f`@\xb4\xe3\xe5\r\xcf5S\xf1\x82\u0357\xa9\x060\xb7]\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4y0\xc2\xd9\xcb\xfa\x87\xf5\x10\xf8\xf9\x87w\xff\x8a\x84H\xcaV)\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4yE)\u041d\x01rq5\x970\x02pu\xb8z\xd8=\xaen\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4yKQ\u00deS\xd9\xe7b\xb0a;\x82\x9aD\xb4r\xf4\xff\xf3\x89$5\xe0dxA\u0300\x00\xe0\x94yU\x1c\xed\xe3v\xf7G\xe3ql\x8dy@\rvm.\x01\x95\x8a\t\xcb7\xaf\xa4\xffxh\x00\x00\u07d4y^\xbc&&\xfc9\xb0\xc8b\x94\xe0\xe87\xdc\xf5#U0\x90\x8965\u026d\xc5\u07a0\x00\x00\u07d4yn\xbb\xf4\x9b>6\xd6v\x94\xady\xf8\xff6vz\xc6\xfa\xb0\x89\x03K\xc4\xfd\xde'\xc0\x00\x00\u07d4yo\x87\xbaaz)0\xb1g\v\xe9.\xd1(\x1f\xb0\xb3F\xe1\x89\x06\xf5\xe8o\xb5((\x00\x00\u07d4yt'\xe3\xdb\xf0\xfe\xaez%\x06\xf1-\xf1\xdc@2n\x85\x05\x8965\u026d\xc5\u07a0\x00\x00\u07d4yu\x10\xe3\x86\xf5c\x93\xce\xd8\xf4w7\x8aDLHO}\xad\x8965\u026d\xc5\u07a0\x00\x00\u07d4y{\xb7\xf1W\xd9\xfe\xaa\x17\xf7m\xa4\xf7\x04\xb7M\xc1\x03\x83A\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4y\x88\x90\x131\xe3\x87\xf7\x13\xfa\u03b9\x00\\\xb9\xb6Q6\xeb\x14\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4y\x89\u041f8&\xc3\u5bccu*\x81\x15r:\x84\xd8\tp\x89\x16\x86\xf8aL\xf0\xad\x00\x00\xe0\x94y\x95\xbd\x8c\xe2\xe0\xc6{\xf1\u01e51\xd4w\xbc\xa1\xb2\xb9ua\x8a\x01BH\xd6\x17\x82\x9e\xce\x00\x00\u07d4y\xae\xb3Ef\xb9t\xc3ZX\x81\xde\xc0 \x92}\xa7\xdf]%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\xb1 \xeb\x88\x06s#!(\x8fgZ'\xa9\"_\x1c\xd2\ub245\xa0\xbf7\xde\xc9\xe4\x00\x00\u07d4y\xb4\x8d-a7\u00c5Ma\x1c\x01\xeaBBz\x0fY{\xb7\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4y\xb8\xaa\xd8y\xdd0V~\x87x\xd2\xd21\xc8\xf3z\xb8sN\x89lk\x93[\x8b\xbd@\x00\x00\u07d4y\xbf/{n2\x8a\xaf&\xe0\xbb\t?\xa2-\xa2\x9e\xf2\xf4q\x89a\t=|,m8\x00\x00\u07d4y\xc10\xc7b\xb8v[\x19\u04ab\u0260\x83\xab\x8f:\xady@\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4y\xc1\xbe\x19q\x1fs\xbe\xe4\xe61j\xe7T\x94Y\xaa\u03a2\xe0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4y\xc6\x00/\x84R\xca\x15\u007f\x13\x17\xe8\n/\xaf$GUY\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4y\xca\xc6IO\x11\xef'\x98t\x8c\xb52\x85\xbd\x8e\"\xf9|\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4y\u03e9x\n\xe6\xd8{,1\x88?\t'i\x86\u021ag5\x8965\u026d\xc5\u07a0\x00\x00\u07d4y\u06e2VG-\xb4\xe0X\xf2\xe4\xcd\xc3\xeaN\x8aBw83\x89O%\x91\xf8\x96\xa6P\x00\x00\u07d4y\xed\x10\xcf\x1fm\xb4\x82\x06\xb5\t\x19\xb9\xb6\x97\b\x1f\xbd\xaa\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u0794y\xf0\x8e\x01\xce\t\x88\xe6<\u007f\x8f)\b\xfa\xdeC\xc7\xf9\xf5\u0248\xfc\x93c\x92\x80\x1c\x00\x00\u07d4y\xfdmH1Pf\xc2\x04\xf9e\x18i\xc1\tl\x14\xfc\x97\x81\x89lk\x93[\x8b\xbd@\x00\x00\u0794y\xff\xb4\xac\x13\x81*\vx\u0123{\x82u\">\x17k\xfd\xa5\x88\xf0\x15\xf2W6B\x00\x00\u07d4z\x05\x89\xb1C\xa8\xe5\xe1\a\u026cf\xa9\xf9\xf8Yz\xb3\u7ac9Q\xe92\xd7n\x8f{\x00\x00\u07d4z\nx\xa9\xcc9?\x91\xc3\xd9\xe3\x9ak\x8c\x06\x9f\a^k\xf5\x89Hz\x9a0E9D\x00\x00\u07d4z\x13p\xa7B\xec&\x87\xe7a\xa1\x9a\u0167\x942\x9e\xe6t\x04\x89\xa2\xa12ga\xe2\x92\x00\x00\xe0\x94z-\xfcw\x0e$6\x811\xb7\x84w\x95\xf2\x03\xf3\xd5\r[V\x8a\x02i\xfe\xc7\xf06\x1d \x00\x00\u07d4z3\x83N\x85\x83s>-R\xae\xadX\x9b\u046f\xfb\x1d\xd2V\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94z6\xab\xa5\xc3\x1e\xa0\xca~'{\xaa2\xecF\u0393\xcfu\x06\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94z8\x11\"\xba\xday\x1az\xb1\xf6\x03}\xac\x80C'S\xba\xad\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94zH\xd8w\xb6:\x8f\x8f\x93\x83\xe9\xd0\x1eS\xe8\fR\x8e\x95_\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4zO\x9b\x85\x06\x90\xc7\xc9F\x00\xdb\xee\f\xa4\xb0\xa4\x11\xe9\xc2!\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4zc\x86\x9f\xc7g\xa4\u01b1\xcd\x0e\x06I\xf3cL\xb1!\xd2K\x89\x043\x87Oc,\xc6\x00\x00\u07d4zg\xdd\x04:PO\xc2\xf2\xfcq\x94\xe9\xbe\xcfHL\xec\xb1\xfb\x89\r\x8drkqw\xa8\x00\x00\xe0\x94zk&\xf48\u0663RD\x91U\xb8\x87l\xbd\x17\xc9\u065bd\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4zmx\x1cw\u013a\x1f\xca\xdfhsA\xc1\xe3\x17\x99\xe9='\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4zph\xe1\xc37\\\x0eY\x9d\xb1\xfb\xe6\xb2\xea#\xb8\xf4\a\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4zt\xce\xe4\xfa\x0fcp\xa7\x89O\x11l\xd0\f\x11G\xb8>Y\x89+^:\xf1k\x18\x80\x00\x00\u07d4zy\xe3\x0f\xf0W\xf7\n=\x01\x91\xf7\xf5?v\x157\xaf}\xff\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94zzO\x80sW\xa4\xbb\xe6\x8e\x1a\xa8\x0692\x10\xc4\x11\u0333\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4z\x85c\x86y\x01 o?+\xf0\xfa>\x1c\x81\t\u02bc\u0345\x89\amA\xc6$\x94\x84\x00\x00\xe0\x94z\x87\x97i\n\xb7{Tp\xbf|\f\x1b\xbaa%\b\xe1\xac}\x8a\x01\xe0\x92\x96\xc37\x8d\xe4\x00\x00\u07d4z\x8c\x89\xc0\x14P\x9dV\u05f6\x810f\x8f\xf6\xa3\xec\xecsp\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94z\x94\xb1\x99\x92\u03b8\xcec\xbc\x92\xeeKZ\xde\xd1\fM\x97%\x8a\x03\x8d\x1a\x80d\xbbd\xc8\x00\x00\u07d4z\xa7\x9a\xc0C\x16\u030d\b\xf2\x00e\xba\xa6\xd4\x14(\x97\xd5N\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4z\xadM\xbc\u04ec\xf9\x97\u07d3XiV\xf7+d\u062d\x94\xee\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94z\xb2V\xb2\x04\x80\n\xf2\x017\xfa\xbc\xc9\x16\xa22Xu%\x01\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4z\xbaV\xf6:H\xbc\b\x17\u05b9p9\x03\x9az\xd6/\xae.\x89 \x86\xac5\x10R`\x00\x00\xe0\x94z\xbb\x10\xf5\xbd\x9b\xc3;\x8e\xc1\xa8-d\xb5[k\x18wuA\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4z\u010d@\xc6d\u031am\x89\xf1\xc5\xf5\xc8\n\x1cp\xe7D\u6263\x10b\xbe\xee\xd7\x00\x00\x00\u07d4z\u014fo\xfcO\x81\a\xaen07\x8eN\x9f\x99\xc5\u007f\xbb$\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4z\xd3\xf3\aao\x19\u0731C\xe6DM\xab\x9c<3a\x1fR\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4z\xd8,\xae\xa1\xa8\xb4\xed\x051\x9b\x9c\x98p\x17<\x81N\x06\xee\x89!d\xb7\xa0J\u0220\x00\x00\u07d4z\xde]f\xb9D\xbb\x86\f\x0e\xfd\xc8bv\u054fFS\xf7\x11\x89lk\x93[\x8b\xbd@\x00\x00\u07d4z\xdf\xed\xb0m\x91\xf3\xccs\x90E\v\x85U\x02p\x88<{\xb7\x89\x11x\xfa@Q]\xb4\x00\x00\u07d4z\xe1\xc1\x9eS\xc7\x1c\xeeLs\xfa\xe2\xd7\xfcs\xbf\x9a\xb5\u348965\u026d\xc5\u07a0\x00\x00\u07d4z\xe6Y\xeb;\xc4hR\xfa\x86\xfa\xc4\xe2\x1cv\x8dP8\x89E\x89\x0f\x81\f\x1c\xb5\x01\xb8\x00\x00\u07d4z\xea%\xd4+&\x12(n\x99\xc56\x97\u01bcA\x00\xe2\u06ff\x89lk\x93[\x8b\xbd@\x00\x00\u07d4z\xef{U\x1f\v\x9cF\xe7U\xc0\xf3\x8e[:s\xfe\x11\x99\xf5\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4{\v1\xffn$t^\xad\x8e\u067b\x85\xfc\v\xf2\xfe\x1dU\u0509+^:\xf1k\x18\x80\x00\x00\xe0\x94{\x0f\xea\x11v\xd5!Y3:\x14<)IC\xda6\xbb\u0774\x8a\x01\xfc}\xa6N\xa1L\x10\x00\x00\u07d4{\x11g<\xc0\x19bk)\f\xbd\xce&\x04o~m\x14\x1e!\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4{\x12!b\xc9\x13\xe7\x14l\xad\v~\xd3z\xff\xc9*\v\xf2\u007f\x89Q\xaf\tk#\x01\u0440\x00\u07d4{\x1b\xf5:\x9c\xbe\x83\xa7\u07a44W\x9f\xe7*\xac\x8d*\f\u0409\n\xd4\xc81j\v\f\x00\x00\u07d4{\x1d\xaf\x14\x89\x1b\x8a\x1e\x1b\xd4)\u0633k\x9aJ\xa1\u066f\xbf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4{\x1f\xe1\xabM\xfd\x00\x88\xcd\xd7\xf6\x01c\xefY\xec*\xee\x06\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4{%\xbb\x9c\xa8\xe7\x02!~\x933\"RP\xe5<6\x80MH\x89e\xea=\xb7UF`\x00\x00\u07d4{'\xd0\xd1\xf3\xdd<\x14\x02\x94\xd0H\x8bx>\xbf@\x15'}\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94{@\a\xc4^ZW?\u06f6\xf8\xbdtk\xf9J\xd0J<&\x8a\x038!\xf5\x13]%\x9a\x00\x00\u07d4{C\xc7\xee\xa8\xd6#U\xb0\xa8\xa8\x1d\xa0\x81\xc6Dk3\xe9\xe0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4{M*8&\x90i\xc1\x85Ww\rY\x1d$\xc5\x12\x1f^\x83\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94{au\xec\x9b\xef\xc78$\x955\xdd\xde4h\x8c\xd3n\xdf%\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94{f\x12hy\x84M\xfa4\xfee\xc9\xf2\x88\x11\u007f\xef\xb4I\xad\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4{j\x84q\x8d\xd8nc3\x84)\xac\x81\x1d|\x8a\x86\x0f!\xf1\x89a\t=|,m8\x00\x00\xe0\x94{q,z\xf1\x16v\x00jf\xd2\xfc\\\x1a\xb4\xc4y\xce`7\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4{s$-u\u029a\xd5X\xd6P)\r\xf1v\x92\xd5L\u0638\x89lnY\xe6|xT\x00\x00\u07d4{v\x1f\xeb\u007f\u03e7\xde\xd1\xf0\xeb\x05\x8fJ`\v\xf3\xa7\b\u02c9\xf9]\xd2\xec'\xcc\xe0\x00\x00\xe0\x94{\x82|\xae\u007f\xf4t\t\x18\xf2\xe00\xab&\u02d8\xc4\xf4l\xf5\x8a\x01\x94hL\v9\xde\x10\x00\x00\xe0\x94{\x892\x86B~r\xdb!\x9a!\xfcM\xcd_\xbfY(<1\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4{\x92&\xd4o\xe7Q\x94\v\xc4\x16\xa7\x98\xb6\x9c\xcf\r\xfa\xb6g\x89\u3bb5sr@\xa0\x00\x00\u07d4{\x98\xe2<\xb9k\xee\xe8\n\x16\x80i\ube8f \xed\xd5\\\u03c9\v\xa0\xc9\x15\x87\xc1J\x00\x00\u07d4{\xb0\xfd\xf5\xa6c\xb5\xfb\xa2\x8d\x9c\x90*\xf0\xc8\x11\xe2R\xf2\x98\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4{\xb9W\x1f9K\v\x1a\x8e\xbaVd\xe9\u0635\xe8@g{\xea\x89\x01\x11du\x9f\xfb2\x00\x00\xe0\x94{\xb9\x84\xc6\u06f9\xe2y\x96j\xfa\xfd\xa5\x9c\x01\xd0&'\xc8\x04\x8a\x01\xb4d1\x1dE\xa6\x88\x00\x00\u07d4{\xbb\xec^p\xbd\xea\u063b2\xb4(\x05\x98\x8e\x96H\xc0\xaa\x97\x8966\u05ef^\u024e\x00\x00\u07d4{\xca\x1d\xa6\xc8\nf\xba\xa5\xdbZ\u0245A\u013e'kD}\x89$\xcf\x04\x96\x80\xfa<\x00\x00\u07d4{\u0772\xee\x98\xde\x19\xeeL\x91\xf6a\xee\x8eg\xa9\x1d\x05K\x97\x8965\u026d\xc5\u07a0\x00\x00\u0794{\xe2\xf7h\f\x80-\xa6\x15L\x92\xc0\x19J\xe72Qzqi\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4{\xe7\xf2Eiq\x88;\x9a\x8d\xbeL\x91\xde\xc0\x8a\xc3N\x88b\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4{\xe8\u0334\xf1\x1bf\xcan\x1dW\xc0\xb59b!\xa3\x1b\xa5:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94{\xeb\x81\xfb/^\x91Rk*\xc9y^v\u019b\xcf\xf0K\xc0\x8a\x0e\xb2.yO\n\x8d`\x00\x00\u07d4|\b\x83\x05L-\x02\xbcz\x85+\x1f\x86\xc4'w\xd0\xd5\xc8V\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4|\x0f^\a C\xc9\xeet\x02B\x19~x\xccK\x98\xcd\xf9`\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|\x1d\xf2JO\u007f\xb2\u01f4r\xe0\xbb\x00l\xb2}\xcd\x16AV\x8965\u026d\xc5\u07a0\x00\x00\u07d4|)\xd4}W\xa73\xf5k\x9b!pc\xb5\x13\xdc;1Y#\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4|+\x96\x03\x88JO.FN\u03b9}\x17\x93\x8d\x82\x8b\xc0,\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4|8,\x02\x96a.N\x97\xe4@\xe0-8q';U\xf5;\x89\n\xb6@9\x12\x010\x00\x00\u07d4|>\xb7\x13\xc4\xc9\xe08\x1c\xd8\x15L|\x9a}\xb8d\\\xde\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|D\x01\xae\x98\xf1.\xf6\xde9\xae$\u03df\xc5\x1f\x80\xeb\xa1k\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|E\xf0\xf8D*V\xdb\u04dd\xbf\x15\x99\x95A\\R\xedG\x9b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94|S-\xb9\xe0\xc0l&\xfd@\xac\xc5j\xc5\\\x1e\xe9-<:\x8a?\x87\bW\xa3\xe0\xe3\x80\x00\x00\u07d4|`\xa0_zJ_\x8c\xf2xC\x916.uZ\x83A\xefY\x89f\x94\xf0\x18*7\xae\x00\x00\u07d4|`\xe5\x1f\v\xe2(\xe4\xd5o\xdd)\x92\xc8\x14\xdaw@\u01bc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4|i$\xd0|>\xf5\x89\x19f\xfe\nxV\xc8{\xef\x9d 4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94|\x8b\xb6Zo\xbbI\xbdA3\x96\xa9\xd7\xe3\x10S\xbb\xb3z\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94|\x9a\x11\f\xb1\x1f%\x98\xb2\xb2\x0e,\xa4\x002^A\xe9\xdb3\x8a\x05\x81v{\xa6\x18\x9c@\x00\x00\u07d4|\xbc\xa8\x8f\xcaj\x00`\xb9`\x98\\\x9a\xa1\xb0%4\xdc\"\b\x89\x19\x12z\x13\x91\xea*\x00\x00\u07d4|\xbe\xb9\x992\xe9~n\x02\x05\x8c\xfcb\u0432k\xc7\u0325+\x89lk\x93[\x8b\xbd@\x00\x00\u07d4|\xc2Jj\x95\x8c \xc7\xd1$\x96`\xf7Xb&\x95\v\r\x9a\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4|\xd2\x0e\u0335\x18\xb6\f\xab\t[r\x0fW\x15p\u02aaD~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4|\xd5\xd8\x1e\xab7\xe1\x1ebv\xa3\xa1\t\x12Q`~\r~8\x89\x03hM^\xf9\x81\xf4\x00\x00\u07d4|\xdft!9E\x95=\xb3\x9a\xd0\xe8\xa9x\x1a\xddy.M\x1d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4|\xe4hdF\U000547be\xd6r\x15\xeb\rZ\x1d\xd7,\x11\xb8\x89x9\xd3!\xb8\x1a\xb8\x00\x00\u07d4|\xefMC\xaaA\u007f\x9e\xf8\xb7\x87\xf8\xb9\x9dS\xf1\xfe\xa1\ue209g\x8a\x93 b\xe4\x18\x00\x00\u07d4}\x03P\xe4\v3\x8d\xdasfa\x87+\xe3?\x1f\x97R\xd7U\x89\x02\xb4\xf5\xa6\U00051500\x00\xe0\x94}\x04\xd2\xed\xc0X\xa1\xaf\xc7a\xd9\u025a\xe4\xfc\\\x85\xd4\u0226\x8aB\xa9\xc4g\\\x94g\xd0\x00\x00\u07d4}\v%^\xfbW\xe1\x0fp\b\xaa\"\xd4\x0e\x97R\xdf\xcf\x03x\x89\x01\x9f\x8euY\x92L\x00\x00\xe0\x94}\x13\xd6pX\x84\xab!W\u074d\xccpF\xca\xf5\x8e\xe9K\xe4\x8a\x1d\r\xa0|\xbb>\xe9\xc0\x00\x00\u07d4}'>c~\xf1\xea\u0101\x11\x94\x13\xb9\x1c\x98\x9d\xc5\xea\xc1\"\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4}*R\xa7\xcf\f\x846\xa8\xe0\a\x97kl&\xb7\"\x9d\x1e\x15\x89\x17\xbf\x06\xb3*$\x1c\x00\x00\u07d4}4\x805i\xe0\v\u05b5\x9f\xff\b\x1d\xfa\\\n\xb4\x19zb\x89\\\xd8|\xb7\xb9\xfb\x86\x00\x00\u07d4}4\xffY\xae\x84\nt\x13\u01baL[\xb2\xba,u\xea\xb0\x18\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4}9(R\xf3\xab\xd9/\xf4\xbb[\xb2l\xb6\bt\xf2\xbeg\x95\x8966\xc2^f\xec\xe7\x00\x00\u07d4}DRg\u015a\xb8\u04a2\xd9\xe7\t\x99\x0e\th%\x80\u011f\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94}U\x13\x97\xf7\x9a)\x88\xb0d\xaf\xd0\xef\xeb\xee\x80,w!\xbc\x8a\bW\xe0\xd6\xf1\xdav\xa0\x00\x00\u07d4}Z\xa3?\xc1KQ\x84\x1a\x06\x90n\xdb+\xb4\x9c*\x11ri\x89\x10D\x00\xa2G\x0eh\x00\x00\xe0\x94}]/s\x94\x9d\xad\xda\bV\xb2\x06\x98\x9d\xf0\a\x8dQ\xa1\xe5\x8a\x02\xc4:H\x1d\xf0M\x01wb\xed\xcb\\\xaab\x9bZ\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4~\x8f\x96\xcc)\xf5{\tu\x12\f\xb5\x93\xb7\u0743=`kS\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4~\x97*\x8a|*D\xc9;!Cl8\xd2\x1b\x92R\xc3E\xfe\x89a\t=|,m8\x00\x00\u07d4~\x99\u07fe\x98\x9d;\xa5)\u0457Q\xb7\xf41\u007f\x89S\xa3\xe2\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4~\xa0\xf9n\xe0\xa5s\xa30\xb5h\x97v\x1f=L\x010\xa8\xe3\x89Hz\x9a0E9D\x00\x00\u0794~\xa7\x91\xeb\xab\x04E\xa0\x0e\xfd\xfcNJ\x8e\x9a~ue\x13m\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4~\xab\xa05\xe2\xaf7\x93\xfdtgK\x10%@\xcf\x19\n\u0779\x89E\x02l\x83[`D\x00\x00\xe0\x94~\xb4\xb0\x18\\\x92\xb6C\x9a\b\xe72!h\xcb5<\x8awJ\x8a\x02'\x19l\xa0I\x83\xca\x00\x00\xe0\x94~\xbd\x95\xe9\xc4p\xf7(5\x83\xdcn\x9d,M\xce\v\ua3c4\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4~\u0425\xa8G\xbe\xf9\xa9\xda|\xba\x1dd\x11\xf5\xc3\x161&\x19\x89\x02(\xeb7\xe8u\x1d\x00\x00\u07d4~\xda\xfb\xa8\x98K\xafc\x1a\x82\vk\x92\xbb\xc2\xc56U\xf6\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4~\xdb\x02\xc6\x1a\"r\x87a\x1a\xd9Pici\xccNdzh\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4~\xe5\u0280]\xce#\xaf\x89\xc2\xd4D\xe7\xe4\af\xc5Lt\x04\x89\r\v\xd4\x12\xed\xbd\x82\x00\x00\xe0\x94~\xe6\x04\u01e9\xdc)\t\xce2\x1d\u6e72OWgWuU\x8a\x01+\xf9\u01d8\\\xf6-\x80\x00\u07d4~\xf1o\xd8\xd1[7\x8a\x0f\xba0k\x8d\x03\u0758\xfc\x92a\x9f\x89%\xf2s\x93=\xb5p\x00\x00\u07d4~\xf9\x8bR\xbe\xe9S\xbe\xf9\x92\xf3\x05\xfd\xa0'\xf8\x91\x1cXQ\x89\x1b\xe7\" i\x96\xbc\x80\x00\u07d4~\xfc\x90vj\x00\xbcR7,\xac\x97\xfa\xbd\x8a<\x83\x1f\x8e\u0349\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4~\xfe\xc0\xc6%<\xaf9\u007fq(|\x1c\a\xf6\xc9X+[\x86\x89\x1a,\xbc\xb8O0\u0540\x00\u07d4\u007f\x01\xdc|7G\xca`\x8f\x98=\xfc\x8c\x9b9\xe7U\xa3\xb9\x14\x89\v8l\xad_zZ\x00\x00\u07d4\u007f\x06b\xb4\x10)\x8c\x99\xf3\x11\u04e1EJ\x1e\xed\xba/\xeav\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\u007f\x06\u021dY\x80\u007f\xa6\v\xc6\x016\xfc\xf8\x14\u02ef%C\xbd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u007f\v\x90\xa1\xfd\u050f'\xb2h\xfe\xb3\x83\x82\xe5]\xdbP\xef\x0f\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\u007f\x0e\xc3\u06c0F\x92\xd4\xd1\xea2E6Z\xab\x05\x90\a[\u0109\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u007f\x0f\x04\xfc\xf3zS\xa4\xe2N\xden\x93\x10Nx\xbe\x1d<\x9e\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u007f\x13\xd7`I\x8dq\x93\xcahY\xbc\x95\xc9\x018d#\xd7l\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\u007f\x15\n\xfb\x1aw\u00b4Y(\xc2h\xc1\u9f74d\x1dG\u0609lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\x16\x19\x98\x8f7\x15\xe9O\xf1\xd2S&-\xc5X\x1d\xb3\xde\x1c\x890\xca\x02O\x98{\x90\x00\x00\u07d4\u007f\x1c\x81\xee\x16\x97\xfc\x14K|\v\xe5I;V\x15\xae\u007f\xdd\u0289\x1b\x1d\xaba\u04ead\x00\x00\u07d4\u007f#\x82\xff\xd8\xf89VFy7\xf9\xbar7F#\xf1\x1b8\x89 \x86\xac5\x10R`\x00\x00\u07d4\u007f7\t9\x1f?\xbe\xba5\x92\xd1u\xc7@\xe8z\tT\x1d\x02\x89\x1a\x05V\x90\xd9\u06c0\x00\x00\u07d4\u007f8\x9c\x12\xf3\xc6\x16OdFVlwf\x95\x03\xc2y%'\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\xe0\x94\u007f:\x1eE\xf6~\x92\u0200\xe5s\xb43y\xd7\x1e\xe0\x89\xdbT\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\u007f=r\x03\u0224G\xf7\xbf6\u060a\xe9\xb6\x06*^\xeex\xae\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\u007fF\xbb%F\r\xd7\xda\xe4!\x1c\xa7\xf1Z\xd3\x12\xfc}\xc7\\\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\u007fI\xe7\xa4&\x98\x82\xbd\x87\"\u0526\xf5f4v)b@y\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u007fI\xf2\a&G\x1a\xc1\u01e8>\xf1\x06\xe9w\\\xebf%f\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\u007fK^'\x85x\xc0F\xcc\xea\xf6W0\xa0\xe0h2\x9e\u0576\x89e\xea=\xb7UF`\x00\x00\u07d4\u007fOY;a\x8c3\v\xa2\xc3\xd5\xf4\x1e\xce\xeb\x92\xe2~Bl\x89\x96n\xdcuk|\xfc\x00\x00\u07d4\u007fT\x14\x91\u04ac\x00\xd2a/\x94\xaa\u007f\v\xcb\x01FQ\xfb\u0509\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\u007fZ\xe0Z\xe0\xf8\xcb\xe5\xdf\xe7!\xf0D\u05e7\xbe\xf4\xc2y\x97\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\u007f`:\xec\x17Y\xea_\a\xc7\xf8\xd4\x1a\x14(\xfb\xba\xf9\xe7b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u007falo\x00\x8a\u07e0\x82\xf3M\xa7\xd0e\x04`6\x80u\xfb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u007fa\xfal\xf5\xf8\x98\xb4@\xda\u016b\xd8`\rmi\x1f\xde\xf9\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94\u007fe\\g\x89\xed\xdfE\\\xb4\xb8\x80\x99r\x0698\x9e\ubb0a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u007fk(\u0204!\xe4\x85~E\x92\x81\u05c4ai$\x89\xd3\xfb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007fn\xfboC\x18\x87m.\xe6$\xe2u\x95\xf4DF\xf6\x8e\x93\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u007fq\x92\xc0\xdf\x1c}\xb6\xd9\xede\xd7\x11\x84\xd8\xe4\x15Z\x17\xba\x89\x04Sr\x8d3\x94,\x00\x00\u07d4\u007fz:!\xb3\xf5\xa6]\x81\xe0\xfc\xb7\xd5-\xd0\n\x1a\xa3m\xba\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u007f\x8d\xbc\xe1\x80\xed\x9cV65\xaa\xd2\xd9{L\xbcB\x89\x06\u0649\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\u007f\x99=\xdb~\x02\u0082\xb8\x98\xf6\x15_h\x0e\xf5\xb9\xaf\xf9\a\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\u007f\x9f\x9bV\xe4(\x9d\xfbX\xe7\x0f\xd5\xf1*\x97\xb5m5\u01a5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u007f\xa3~\xd6x\x87u\x1aG\x1f\x0e\xb3\x06\xbeD\xe0\xdb\xcd`\x89\x899vt\u007f\xe1\x1a\x10\x00\x00\u07d4\u007f\xaa0\xc3\x15\x19\xb5\x84\xe9rP\xed*<\xf38^\xd5\xfdP\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xcf[\xa6fo\x96lTH\xc1{\xf1\xcb\v\xbc\xd8\x01\x9b\x06\x89\x05k\xc3\u042e\xbeI\x80\x00\xe0\x94\u007f\xd6y\xe5\xfb\r\xa2\xa5\xd1\x16\x19M\xcbP\x83\x18\xed\u0140\xf3\x8a\x01c\x9eI\xbb\xa1b\x80\x00\x00\u07d4\u007f\u06e01\u01cf\x9c\tmb\xd0Z6\x9e\uac3c\xccU\u5257\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\u007f\xdb\u00e8D\xe4\r\x96\xb2\xf3\xa652.`e\xf4\xca\x0e\x84\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xdf\u020dx\xbf\x1b(Z\xc6O\x1a\xdb5\xdc\x11\xfc\xb09Q\x89|\x06\xfd\xa0/\xb06\x00\x00\u07d4\u007f\xea\x19b\xe3]b\x05\x97h\xc7I\xbe\u0756\u02b90\xd3x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u007f\xef\x8c8w\x9f\xb3\a\xeco\x04K\xeb\xe4\u007f<\xfa\xe7\x96\xf1\x89\t#@\xf8l\xf0\x9e\x80\x00\u07d4\u007f\xf0\xc6?p$\x1b\xec\xe1\x9bs~SA\xb1+\x10\x901\u0609\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\u007f\xfa\xbf\xbc9\f\xbeC\u0389\x18\x8f\bh\xb2}\xcb\x0f\f\xad\x8a\x01YQ\x82\"K&H\x00\x00\xe0\x94\u007f\xfd\x02\xed7\fp`\xb2\xaeS\xc0x\xc8\x01!\x90\u07fbu\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u0794\x80\x02*\x12\a\xe9\x10\x91\x1f\xc9(I\xb0i\xab\f\xda\xd0C\u04c8\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\x80\t\xa7\xcb\u0452\xb3\xae\u052d\xb9\x83\xd5(ER\xc1ltQ\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80\x0e}c\x1cnW:\x903/\x17\xf7\x1f_\u045bR\x8c\xb9\x89\b=lz\xabc`\x00\x00\u07d4\x80\x15m\x10\ufa320\u0254\x10c\r7\xe2i\xd4\t<\xea\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\x172\xa4\x81\u00c0\xe5~\xd6-l)\u0799\x8a\xf3\xfa;\x13\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x1de\xc5\x18\xb1\x1d\x0e?OG\x02!Ap\x13\xc8\xe5>\u0149\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80&CZ\xacr\x8dI{\x19\xb3\xe7\xe5|(\xc5c\x95O+\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x80-\xc3\xc4\xff-}\x92^\u215fJ\x06\u05fa`\xf10\x8c\x89\x05P\x94\f\x8f\xd3L\x00\x00\u07d4\x800\xb1\x11\u0198?\x04\x85\u076c\xa7b$\xc6\x18\x064x\x9f\x89\x04V9\x18$O@\x00\x00\u07d4\x805\xbc\xff\xae\xfd\xee\xea5\x83\fI}\x14(\x9d6 #\u0789\x10CV\x1a\x88)0\x00\x00\u07d4\x805\xfeNkj\xf2z\u44a5xQ^\x9d9\xfao\xa6[\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80C\xed\"\xf9\x97\u58a4\xc1n6D\x86\xaed\x97V\x92\u0109=I\x04\xff\xc9\x11.\x80\x00\u07d4\x80C\xfd\u043cL\x97=\x16c\xd5_\xc15P\x8e\xc5\xd4\xf4\xfa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x80L\xa9IrcOc:Q\xf3V\v\x1d\x06\xc0\xb2\x93\xb3\xb1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x80R-\u07d4N\xc5.'\xd7$\xedL\x93\xe1\xf7\xbe`\x83\u0589\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x80Y\x1aB\x17\x9f4\xe6M\x9d\xf7]\xcdF;(hoUt\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x80\\\xe5\x12\x97\xa0y;\x81 g\xf0\x17\xb3\xe7\xb2\u07db\xb1\xf9\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x80]\x84o\xb0\xbc\x02\xa73r&\u0585\xbe\x9e\xe7s\xb9\x19\x8a\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x80c7\x9a{\xf2\u02d2:\x84\xc5\t>h\xda\xc7\xf7T\x81\u0149\x11v\x10.n2\xdf\x00\x00\u07d4\x80hTX\x8e\xcc\xe5AI_\x81\u008a)\x03s\xdf\x02t\xb2\x89\x1f\x8c\xdf\\n\x8dX\x00\x00\u07d4\x80oD\xbd\xebh\x807\x01^\x84\xff!\x80I\xe3\x823*3\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\x80tF\x18\xde9jT1\x97\xeeH\x94\xab\xd0c\x98\xdd|'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80w\xc3\xe4\xc4EXn\tL\xe1\x02\x93\u007f\xa0[s{V\x8c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x90\u007fY1H\xb5|F\xc1w\xe2=%\xab\u012a\xe1\x83a\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\x97s\x16\x94NYB\xe7\x9b\x0e:\xba\u04cd\xa7F\be\x19\x89\x02\x1auJm\xc5(\x00\x00\xe0\x94\x80\xa0\xf6\xcc\x18l\xf6 \x14\x00sn\x06Z9\x1fR\xa9\xdfJ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x80\xab\xecZ\xa3n\\\x9d\t\x8f\x1b\x94(\x81\xbdZ\xca\u0196=\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xb2=8\v\x82\\F\xe098\x99\xa8UVF-\xa0\u1309lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xb4-\xe1p\xdb\xd7#\xf4T\xe8\x8fw\x16E-\x92\x98P\x92\x89\x10F#\xc0v-\xd1\x00\x00\u07d4\x80\xb7\x9f3\x83\x90\u047a\x1b77\xa2\x9a\x02W\xe5\xd9\x1e\a1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x80\xbf\x99^\u063a\x92p\x1d\x10\xfe\u011f\x9e}\x01M\xbe\xe0&\x89\x1f\x047\xca\x1a~\x12\x80\x00\u07d4\x80\xc0N\xfd1\x0fD\x04\x83\xc7?tK[\x9edY\x9c\xe3\xec\x89A\rXj \xa4\xc0\x00\x00\u07d4\x80\u00e9\xf6\x95\xb1m\xb1Yr\x86\u0473\xa8\xb7il9\xfa'\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x80\xc5>\xe7\xe35\u007f\x94\xce\rxh\x00\x9c \x8bJ\x13\x01%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x80\xcc!\xbd\x99\xf3\x90\x05\u014f\xe4\xa4H\x90\x92 !\x8ff\u02c966\xc9yd6t\x00\x00\u07d4\x80\xd5\xc4\fY\xc7\xf5N\xa3\xa5_\xcf\xd1uG\x1e\xa3P\x99\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x80\xda/\u0762\x9a\x9e'\xf9\xe1\x15\x97^i\xae\x9c\xfb\xf3\xf2~\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x80\xe7\xb3 R0\xa5f\xa1\xf0a\xd9\"\x81\x9b\xb4\xd4\u04a0\xe1\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x80\xea\x1a\xcc\x13n\xcaKh\xc8B\xa9Z\xdfk\u007f\xee~\xb8\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x80\xf0z\xc0\x9e{,<\n=\x1e\x94\x13\xa5D\xc7:A\xbe\u02c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x81\r\xb2Vu\xf4^\xa4\xc7\xf3\x17\u007f7\xce)\xe2-g\x99\x9c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81\x13\x9b\xfd\u0326V\xc40 ?r\x95\x8cT;e\x80\xd4\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x81\x14a\xa2\xb0\u0290\xba\xda\xc0j\x9e\xa1nx{3\xb1\x96\u0309\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\x81\x16M\xeb\x10\x81J\xe0\x83\x91\xf3,\bf{bH\xc2}z\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\x81\x18i1\x18A7\xd1\x19*\u020c\xd3\xe1\xe5\xd0\xfd\xb8jt\x89\x9d5\x95\xab$8\xd0\x00\x00\u0794\x81*U\xc4<\xae\xdcYr\x187\x90\x00\xceQ\rT\x886\xfd\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x81.\xa7\xa3\xb2\xc8n\xed2\xffO,sQL\xc6;\xac\xfb\u038965\u026d\xc5\u07a0\x00\x00\u07d4\x814\xdd\x1c\x9d\xf0\xd6\u0225\x81$&\xbbU\xc7a\u0283\x1f\b\x89\x06\xa2\x16\v\xb5|\xcc\x00\x00\u07d4\x81A5\u068f\x98\x11\aW\x83\xbf\x1a\xb6pb\xaf\x8d>\x9f@\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x81I\x8c\xa0{\x0f/\x17\xe8\xbb\xc7\xe6\x1a\u007fJ\xe7\xbef\xb7\x8b\x89\x05\x81\xfb\xb5\xb3;\xb0\x00\x00\u07d4\x81Um\xb2sI\xab\x8b'\x00ID\xedP\xa4n\x94\x1a\x0f_\x89\u063beI\xb0+\xb8\x00\x00\u07d4\x81U\xfalQ\xeb1\xd8\bA-t\x8a\xa0\x86\x10P\x18\x12/\x89e\xea=\xb7UF`\x00\x00\xe0\x94\x81V6\v\xbd7\ta\xce\xcakf\x91\xd7P\x06\xad L\xf2\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x81a\xd9@\xc3v\x01\x00\xb9\b\x05)\xf8\xa6\x03%\x03\x0fn\u0709\x10CV\x1a\x88)0\x00\x00\xe0\x94\x81d\xe7\x83\x14\xae\x16\xb2\x89&\xccU=,\xcb\x16\xf3V'\r\x8a\x01\xca\x13N\x95\xfb2\xc8\x00\x00\u07d4\x81e\u02b0\xea\xfbZ2\x8f\xc4\x1a\xc6M\xaeq[.\xef,e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81h\xed\xce\u007f)a\xcf)[\x9f\xcdZE\xc0l\xde\xdan\xf5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81m\x97r\xcf\x119\x91\x16\xcc\x1er\xc2lgt\xc9\xed\xd79\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x81s\xc85djg.\x01R\xbe\x10\xff\xe8Ab\xdd%nL\x89\x1a\xab\xdf!E\xb40\x00\x00\u07d4\x81t\x93\u035b\xc6#p*$\xa5o\x9f\x82\xe3\xfdH\xf3\xcd1\x89\x9eK#\xf1-L\xa0\x00\x00\u07d4\x81y\xc8\tp\x18,\u0177\xd8*M\xf0n\xa9M\xb6:%\xf3\x89'o%\x9d\xe6k\xf4\x00\x00\u07d4\x81z\xc3;\xd8\xf8GVsr\x95\x1fJ\x10\u05e9\x1c\xe3\xf40\x89\n\xd7\xc4\x06\xc6m\xc1\x80\x00\xe0\x94\x81\x8f\xfe'\x1f\u00d75e\xc3\x03\xf2\x13\xf6\xd2\u0689\x89~\xbd\x8a\x016\xe0SB\xfe\u1e40\x00\u07d4\x81\x97\x94\x81!s.c\xd9\xc1H\x19N\xca\xd4n0\xb7I\u0209\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x81\x9a\xf9\xa1\xc2s2\xb1\xc3i\xbb\xda\x1b=\xe1\xc6\xe93\xd6@\x89\x11\t\xe6T\xb9\x8fz\x00\x00\xe0\x94\x81\x9c\u06a506x\xef|\xecY\u050c\x82\x16:\xcc`\xb9R\x8a\x03\x13QT_y\x81l\x00\x00\u07d4\x81\x9e\xb4\x99\vZ\xbaUG\t=\xa1+k<\x10\x93\xdfmF\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81\xa8\x81\x96\xfa\xc5\xf2<>\x12\xa6\x9d\xecK\x88\x0e\xb7\xd9s\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x81\xbc\xcb\xff\x8fD4~\xb7\xfc\xa9['\xce|\x95$\x92\xaa\xad\x89\b@\xc1!e\xddx\x00\x00\u07d4\x81\xbdu\xab\xd8e\xe0\xc3\xf0J\vO\xdb\xcbt\xd3@\x82\xfb\xb7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x81\xc1\x8c*#\x8d\xdcL\xba#\n\a-\xd7\xdc\x10\x1eb\x02s\x89Hz\x9a0E9D\x00\x00\u07d4\x81\xc9\xe1\xae\xe2\xd36]S\xbc\xfd\u0356\xc7\xc58\xb0\xfd~\xec\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\x81\u03edv\t\x13\xd3\xc3\"\xfc\xc7{I\u00ae9\a\xe7On\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x81\xd6\x19\xffW&\xf2@_\x12\x90Lr\xeb\x1e$\xa0\xaa\xeeO\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x81\xef\u25aev\xc8`\xd1\xc5\xfb\xd3=G\xe8\u0399\x96\xd1W\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x81\xf8\xde,(=_\u052f\xbd\xa8]\xed\xf9v\x0e\xab\xbb\xb5r\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x82\f\x19)\x11\x96P[e\x05\x9d\x99\x14\xb7\t\v\xe1\u06c7\u0789\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x82\x1c\xb5\xcd\x05\xc7\uf41f\xe1\xbe`s=\x89c\xd7`\xdcA\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x82\x1dy\x8a\xf1\x99\x89\u00ee[\x84\xa7\xa7(<\xd7\xfd\xa1\xfa\xbe\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x82\x1e\xb9\t\x94\xa2\xfb\xf9K\xdc23\x91\x02\x96\xf7o\x9b\xf6\xe7\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x82$\x9f\xe7\x0fa\u01b1o\x19\xa3$\x84\x0f\xdc\x02\x021\xbb\x02\x8a\x02\x036\xb0\x8a\x93c[\x00\x00\u07d4\x82(\xeb\xc0\x87H\x0f\xd6EG\xca(\x1f^\xac\xe3\x04\x14S\xb9\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\x82)\u03b9\xf0\xd7\b9I\x8dD\xe6\xab\xed\x93\xc5\xca\x05\x9f]\x8a\x1a\x1c\x1b<\x98\x9a \x10\x00\x00\u07d4\x82.\xdf\xf66V:a\x06\xe5.\x9a%\x98\xf7\xe6\xd0\xef'\x82\x89\x01\xf4\xf9i=B\u04c0\x00\u07d4\x822\x19\xa2Yv\xbb*\xa4\xaf\x8b\xadA\xac5&\xb4\x936\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x822\xd1\xf9t.\u07cd\xd9'\xda5;*\xe7\xb4\xcb\xceu\x92\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\x824\xf4c\u0444\x85P\x1f\x8f\x85\xac\xe4\x97,\x9bc-\xbc\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\x827htg7\xcem\xa3\x12\xd5>TSN\x10o\x96|\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82;\xa7dr8\xd1\x13\xbc\xe9\x96JC\u0420\x98\x11\x8b\xfeM\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x82@t1(\x06\xdaGHCBf\xee\x00!@\u305a\u0089Q\xb1\u04c3\x92a\xac\x00\x00\u07d4\x82C\x8f\u04b3*\x9b\xddgKI\xd8\xcc_\xa2\xef\xf9x\x18G\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82HW(\xd0\xe2\x81V7X\xc7Z\xb2~\xd9\u80a0\x00-\x89\a\xf8\b\xe9)\x1el\x00\x00\u07d4\x82K<\x19)]~\xf6\xfa\xa7\xf3t\xa4y\x84\x86\xa8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82Q5\x8c\xa4\xe0`\u0775Y\xcaX\xbc\v\u077e\xb4\a\x02\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82Q5\xb1\xa7\xfc\x16\x05aL\x8a\xa4\u042cm\xba\u040fH\x0e\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\x82S\t\xa7\xd4]\x18\x12\xf5\x1en\x8d\xf5\xa7\xb9ol\x90\x88\x87\x89\x804\xf7\u0671f\xd4\x00\x00\u07d4\x82Z\u007fN\x10\x94\x9c\xb6\xf8\x96Bh\xf1\xfa_W\xe7\x12\xb4\u0109\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x82a\xfa#\f\x90\x1dC\xffW\x9fG\x80\u04d9\xf3\x1e`v\xbc\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82b\x16\x9baXp\x13N\xb4\xacl_G\x1ck\xf2\xf7\x89\xfc\x89\x19\x12z\x13\x91\xea*\x00\x00\u07d4\x82c\xec\xe5\xd7\t\xe0\u05eeq\u0328h\xed7\xcd/\xef\x80{\x895\xab\x02\x8a\xc1T\xb8\x00\x00\xe0\x94\x82l\xe5y\x052\xe0T\x8ca\x02\xa3\r>\xac\x83k\xd68\x8f\x8a\x03\xcf\xc8.7\xe9\xa7@\x00\x00\u07d4\x82n\xb7\xcds\x19\xb8-\xd0z\x1f;@\x90q\xd9n9g\u007f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x82u1\xa6\u0141z\xe3_\x82\xb0\v\x97T\xfc\xf7LU\xe22\x89\xc3(\t>a\xee@\x00\x00\u0794\x82u\xcdhL6y\u0548}\x03fN3\x83E\xdc<\xdd\xe1\x88\xdbD\xe0I\xbb,\x00\x00\u07d4\x82\x84\x92;b\u62ff|+\x9f4\x14\xd1>\xf6\xc8\x12\xa9\x04\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\x82\x8b\xa6Q\u02d3\x0e\xd9xqV)\x9a=\xe4L\u040br\x12\x89Hz\x9a0E9D\x00\x00\u07d4\x82\xa1\\\xef\x1dl\x82`\xea\xf1Y\xea?\x01\x80\xd8g}\xce\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82\xa8\xb9kl\x9e\x13\xeb\xec\x1e\x9f\x18\xac\x02\xa6\x0e\xa8\x8aH\xff\x89lk\x8c@\x8es\xb3\x00\x00\u07d4\x82\xa8\u02ff\xdf\xf0+.8\xaeK\xbf\xca\x15\xf1\xf0\xe8;\x1a\xea\x89\x04\x9b\x99\x1c'\xefm\x80\x00\u07d4\x82\xe4F\x1e\xb9\xd8I\xf0\x04\x1c\x14\x04!\x9eBr\u0110\n\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x82\xe5w\xb5\x15\xcb+\b`\xaa\xfe\x1c\xe0\x9aY\xe0\x9f\xe7\xd0@\x89 \x86\xac5\x10R`\x00\x00\u07d4\x82\xea\x01\xe3\xbf.\x83\x83nqpN\"\xa2q\x93w\xef\xd9\u00c9\xa4\xccy\x95c\u00c0\x00\x00\u07d4\x82\xf2\xe9\x91\xfd2L_]\x17v\x8e\x9fa3]\xb61\x9dl\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x82\xf3\x9b'X\xaeB'{\x86\u059fu\xe6(\xd9X\xeb\u02b0\x8a\bxg\x83&\xea\xc9\x00\x00\x00\xe0\x94\x82\xf8T\xc9\xc2\xf0\x87\xdf\xfa\x98Z\xc8 \x1ebl\xa5Fv\x86\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\x82\xffqo\xdf\x03>\xc7\xe9B\xc9\t\u0643\x18g\xb8\xb6\xe2\xef\x89a\t=|,m8\x00\x00\u07d4\x83\b\xed\n\xf7\xf8\xa3\xc1u\x1f\xaf\xc8w\xb5\xa4*\xf7\xd3X\x82\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x83\x1cD\xb3\b@G\x18K*\xd2\x18h\x06@\x907P\xc4]\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x83!\x05\x83\xc1jN\x1e\x1d\xac\x84\xeb\xd3~=\x0f|W\ub909lk\x93[\x8b\xbd@\x00\x00\u07d4\x83,T\x17k\xdfC\xd2\u027c\u05f8\b\xb8\x95V\xb8\x9c\xbf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x833\x16\x98]Gt+\xfe\xd4\x10`J\x91\x95<\x05\xfb\x12\xb0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x834vK{9zNW\x8fP6M`\xceD\x89\x9b\xff\x94\x89\x05\x03\xb2\x03\xe9\xfb\xa2\x00\x00\xe0\x94\x83;j\x8e\xc8\xda@\x81\x86\xac\x8a}*m\xd6\x15#\xe7\u0384\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x83=?\xaeT*\xd5\xf8\xb5\f\xe1\x9b\xde+\xecW\x91\x80\u020c\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\x83=\xb4,\x14\x16<{\xe4\u02b8j\u0153\xe0bf\u0599\u054a$\xe4\r+iC\xef\x90\x00\x00\xe0\x94\x83V;\xc3d\ud060\xc6\xda;V\xffI\xbb\xf2g\x82z\x9c\x8a\x03\xab\x91\xd1{ \xdeP\x00\x00\u07d4\x83zd]\xc9\\IT\x9f\x89\x9cN\x8b\u03c7S$\xb2\xf5|\x89 \x8c9J\xf1\u0208\x00\x00\u07d4\x83\x8b\xd5e\xf9\x9f\xdeH\x05?y\x17\xfe3<\xf8J\xd5H\xab\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x83\x90\x8a\xa7G\x8am\x1c\x9b\x9b\x02\x81\x14\x8f\x8f\x9f$+\x9f\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\x83\x92\xe57vq5x\x01[\xffI@\xcfC\x84\x9d}\u02e1\x89\bM\xf05]V\x17\x00\x00\xe0\x94\x83\x97\xa1\xbcG\xac\xd6GA\x81Y\xb9\x9c\xeaW\xe1\xe6S-n\x8a\x01\xf1\x0f\xa8'\xb5P\xb4\x00\x00\u07d4\x83\x98\xe0~\xbc\xb4\xf7_\xf2\x11m\xe7|\x1c*\x99\xf3\x03\xa4\u03c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xa3\x14\x883\xd9dI\x84\xf7\xc4u\xa7\x85\a\x16\ufd00\xff\x89\xb8Pz\x82\a( \x00\x00\u07d4\x83\xa4\x02C\x8e\x05\x19w=TH2k\xfba\xf8\xb2\f\xf5-\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\x83\xa9;[\xa4\x1b\xf8\x87 \xe4\x15y\f\xdc\vg\xb4\xaf4\u0109\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x83\xc2=\x8aP!$\xee\x15\x0f\b\xd7\x1d\xc6rt\x10\xa0\xf9\x01\x8a\a3\x1f;\xfef\x1b\x18\x00\x00\u07d4\x83\u0217\xa8Ki^\xeb\xe4fy\xf7\xda\x19\xd7vb\x1c&\x94\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xd52\u04cdm\xee?`\xad\u018b\x93a3\u01e2\xa1\xb0\u0749\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x83\xdb\xf8\xa1(S\xb4\n\xc6\x19\x96\xf8\xbf\x1d\xc8\xfd\xba\xdd\xd3)\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x83\xdb\xfd\x8e\xda\x01\xd0\u078e\x15\x8b\x16\u0413_\xc28\n]\u01c9 \x86\xac5\x10R`\x00\x00\u07d4\x83\xe4\x80U2|(\xb5\x93o\xd9\xf4D~s\xbd\xb2\xdd3v\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\x83\xfeZ\x1b2\x8b\xaeD\a\x11\xbe\xafj\xad`&\xed\xa6\xd2 \x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x84\x00\x8ar\xf8\x03o?\xeb\xa5B\xe3Px\xc0W\xf3*\x88%\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x84\x0e\xc8>\xa96!\xf04\xe7\xbb7b\xbb\x8e)\xde\xd4\xc4y\x89\x87\x86x2n\xac\x90\x00\x00\xe0\x94\x84\x11E\xb4H@\xc9F\xe2\x1d\xbc\x19\x02d\xb8\xe0\xd5\x02\x93i\x8a?\x87\bW\xa3\xe0\xe3\x80\x00\x00\u07d4\x84#!\a\x93+\x12\xe01\x86X5%\xce\x02:p>\xf8\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4\x84$O\xc9ZiW\xed|\x15\x04\xe4\x9f0\xb8\xc3^\xcaKy\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x841'}{\xdd\x10E}\xc0\x17@\x8c\x8d\xbb\xbdAJ\x8d\xf3\x89\x02\"\xc8\xeb?\xf6d\x00\x00\u07d4\x847Z\xfb\xf5\x9b:\x1da\xa1\xbe2\xd0u\xe0\xe1ZO\xbc\xa5\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x84;\xd3P/E\xf8\xbcM\xa3p\xb3#\xbd\xac?\xcf_\x19\xa6\x89P\x03\x9dc\xd1\x1c\x90\x00\x00\u07d4\x84P34c\rw\xf7AG\xf6\x8b.\bf\x13\xc8\xf1\xad\xe9\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x84R\x03u\x0fqH\xa9\xaa&)!\xe8mC\xbfd\x19t\xfd\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x84a\xec\u0126\xa4^\xb1\xa5\xb9G\xfb\x86\xb8\x80i\xb9\x1f\xcdo\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84g^\x91wrmE\xea\xa4k9\x92\xa3@\xba\u007fq\f\x95\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x84hl{\xadv,T\xb6g\u055f\x90\x94<\xd1M\x11z&\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\x89\xf6\xad\x1d\x9a\x94\xa2\x97x\x91V\x89\x9d\xb6AT\xf1\u06f5\x89\x13t\a\xc0<\x8c&\x80\x00\u07d4\x84\x8c\x99Jy\x00?\xe7\xb7\xc2l\xc62\x12\xe1\xfc/\x9c\x19\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\x8f\xbd)\xd6|\xf4\xa0\x13\xcb\x02\xa4\xb1v\xef$N\x9e\u6349\x01\x17*ck\xbd\xc2\x00\x00\u07d4\x84\x94\x9d\xbaU\x9ac\xbf\xc8E\xde\xd0n\x9f-\x9b\u007f\x11\xef$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\x9a\xb8\a\x90\xb2\x8f\xf1\xff\u05ba9N\xfctc\x10\\6\xf7\x89\x01\xe0+\xe4\xael\x84\x00\x00\u07d4\x84\x9b\x11oYc\x01\xc5\u063bb\xe0\xe9z\x82H\x12n9\xf3\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x84\xa7L\xee\xcf\xf6\\\xb9;/\x94\x9dw>\xf1\xad\u007f\xb4\xa2E\x89\x05\n\x9bDF\x85\xc7\x00\x00\u07d4\x84\xaa\xc7\xfa\x19\u007f\xf8\\0\xe0;zS\x82\xb9W\xf4\x1f:\xfb\x89\b\x8b#\xac\xff\u0650\x00\x00\u07d4\x84\xaf\x1b\x15sB\xd5Ch&\r\x17\x87b0\xa54\xb5K\x0e\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x84\xb0\xeek\xb87\u04e4\xc4\xc5\x01\x1c:\"\x8c\x0e\u06b4cJ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\xb4\xb7Nf#\xba\x9d\x15\x83\xe0\u03feId?\x168AI\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x84\xb6\xb6\xad\xbe/[>-h,f\xaf\x1b\u0110S@\xc3\xed\x89!\x92\xf8\xd2\"\x15\x00\x80\x00\xe0\x94\x84\xb9\x1e.)\x02\xd0^+Y\x1bA\b;\u05fe\xb2\xd5,t\x8a\x02\x15\xe5\x12\x8bE\x04d\x80\x00\u07d4\x84\xbc\xbf\"\xc0\x96\a\xac\x844\x1d.\xdb\xc0;\xfb\x179\xd7D\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x84\xbf\xce\xf0I\x1a\n\xe0iK7\u03ac\x02E\x84\xf2\xaa\x04g\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x84\xcb}\xa0P-\xf4\\\xf5a\x81{\xbd#b\xf4Q\xbe\x02\u0689Hz\x9a0E9D\x00\x00\u07d4\x84\xccxx\xda`_\xdb\x01\x9f\xab\x9bL\xcf\xc1Wp\x9c\u0765\x89Hy\x85\x13\xaf\x04\xc9\x00\x00\u07d4\x84\xdb\x14Y\xbb\x00\x81.\xa6~\xcb=\xc1\x89\xb7!\x87\xd9\xc5\x01\x89\b\x11\xb8\xfb\u0685\xab\x80\x00\u07d4\x84\u9516\x80\xbe\xcehA\xb9\xa7\xe5%\r\b\xac\xd8}\x16\u0349\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x84\xe9\u03c1f\xc3j\xbf\xa4\x90S\xb7\xa1\xad@6 &\x81\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x84\xec\x06\xf2G\x00\xfeBAL\xb9\x89|\x15L\x88\xde/a2\x89Hz\x9a0E9D\x00\x00\xe0\x94\x84\xf5\"\xf0R\x0e\xbaR\xdd\x18\xad!\xfaK\x82\x9f+\x89\u02d7\x8a\x01\fQ\x06\xd5\x13O\x13\x00\x00\u07d4\x85\v\x9d\xb1\x8f\xf8K\xf0\xc7\xdaI\xea7\x81\xd9 \x90\xad~d\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\x85\x10\xee\x93O\f\xbc\x90\x0e\x10\a\xeb8\xa2\x1e*Q\x01\xb8\xb2\x89\x05\xbf\v\xa6cOh\x00\x00\u07d4\x85\x16\xfc\xafw\u0213\x97\x0f\xcd\x1a\x95\x8b\xa9\xa0\x0eI\x04@\x19\x89\n\xa3\xeb\x16\x91\xbc\xe5\x80\x00\u07d4\x85\x1a\xa9\x1c\x82\xf4/\xad]\xd8\xe8\xbb^\xa6\x9c\x8f:Yw\u0449\b\x0eV\x1f%xy\x80\x00\u07d4\x85\x1c\rb\xbeF5\xd4w~\x805\xe3~K\xa8Q|a2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x85\x1d\u00ca\xdbE\x93r\x9av\xf3:\x86\x16\u06b6\xf5\xf5\x9aw\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x852I\b\x97\xbb\xb4\u038b\u007fk\x83~L\xba\x84\x8f\xbe\x99v\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x85>j\xba\xf4Di\xc7/\x15\x1dN\"8\x19\xac\xedN7(\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x85F\x91\xceqO2\\\xedU\xceY(\u039b\xa1/\xac\u0478\x89\xedp\xb5\xe9\xc3\xf2\xf0\x00\x00\u07d4\x85L\fF\x9c$k\x83\xb5\u0473\xec\xa4C\xb3\x9a\xf5\xee\x12\x8a\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x85]\x9a\xef,9\xc6#\r\t\u025e\xf6II\x89\xab\u61c5\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\x85c\u0113a\xb6%\xe7hw\x1c\x96\x15\x1d\xbf\xbd\x1c\x90iv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x85fa\t\x01\xaa\xce8\xb82D\xf3\xa9\xc810jg\xb9\u0709\xb0\x82\x13\xbc\xf8\xff\xe0\x00\x00\xe0\x94\x85j\xa2<\x82\xd7![\xec\x8dW\xf6\n\xd7^\xf1O\xa3_D\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x85nZ\xb3\xf6L\x9a\xb5k\x00\x93\x93\xb0\x16d\xfc\x03$\x05\x0e\x89a\t=|,m8\x00\x00\u07d4\x85n\xb2\x04$\x1a\x87\x83\x0f\xb2)\x03\x13C\xdc0\x85OX\x1a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x85s,\x06\\\xbdd\x11\x99A\xae\xd40\xacYg\vlQ\u0109'\xa5sb\xab\n\x0e\x80\x00\xe0\x94\x85x\xe1\x02\x12\xca\x14\xff\a2\xa8$\x1e7F}\xb8V2\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x85y\xda\xdf\x1a9Z4q\xe2\vov=\x9a\x0f\xf1\x9a?o\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x85\u007f\x10\v\x1aY0\"^\xfc~\x90 \u05c3'\xb4\x1c\x02\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x85\x94mV\xa4\xd3q\xa93hS\x96\x90\xb6\x0e\xc8%\x10tT\x89]\u0212\xaa\x111\xc8\x00\x00\xe0\x94\x85\x99\xcb\u0566\xa9\xdc\u0539f\xbe8}iw]\xa5\xe3C'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86$_Yf\x91\t>\xce?=<\xa2&>\xac\xe8\x19A\u0649\n1\x06+\xee\xedp\x00\x00\u07d4\x86%i!\x1e\x8cc'\xb5A^:g\xe5s\x8b\x15\xba\xafn\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x86)}s\x0f\xe0\xf7\xa9\xee$\xe0\x8f\xb1\b{1\xad\xb3\x06\xa7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86D\xcc(\x1b\xe32\xcc\xce\xd3m\xa4\x83\xfb*\aF\u067a.\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x86I\x9a\x12(\xff-~\xe3\au\x93dPo\x8e\x8c\x83\a\xa5\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x86K\xecPi\xf8U\xa4\xfdX\x92\xa6\xc4I\x1d\xb0|\x88\xff|\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86W\n\xb2Y\u0271\xc3,\x97) /w\xf5\x90\xc0}\xd6\x12\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86c\xa2A\xa0\xa8\x9ep\xe1\x82\xc8E\xe2\x10\\\x8a\xd7&K\u03ca\x03#\xb1=\x83\x98\xf3#\x80\x00\u07d4\x86g\xfa\x11U\xfe\xd72\u03f8\u0725\xa0\xd7e\xce\r\a\x05\xed\x89\x04n\xc9e\u00d3\xb1\x00\x00\u07d4\x86h\xaf\x86\x8a\x1e\x98\x88_\x93\u007f&\x15\xde\xd6u\x18\x04\xeb-\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x86t\nFd\x8e\x84Z]\x96F\x1b\x18\t\x1f\xf5{\xe8\xa1o\x8a\x14\xc0\x974\x85\xbf9@\x00\x00\xe0\x94\x86~\xbaVt\x8aY\x045\r,\xa2\xa5\u039c\xa0\vg\n\x9b\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x86\x80dt\xc3X\x04}\x94\x06\xe6\xa0\u007f@\x94[\xc82\x8eg\x8a\x01u.\xb0\xf7\x01=\x10\x00\x00\u07d4\x86\x88=T\xcd9\x15\xe5I\tU0\xf9\xab\x18\x05\xe8\xc5C-\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x86\x8c#\xbe\x874f\xd4\xc7L\"\n\x19\xb2E\xd1x~\x80\u007f\x89J\x13\xbb\xbd\x92\u020e\x80\x00\xe0\x94\x86\x92O\xb2\x11\xaa\xd2<\xf5\xce`\x0e\n\xae\x80c\x96D@\x87\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x86\x93\u9e3e\x94B^\xefyi\xbci\xf9\xd4/|\xadg\x1e\x8967\tlK\xcci\x00\x00\xe0\x94\x86\x9f\x1a\xa3\x0eDU\xbe\xb1\x82 \x91\xde\\\xad\xecy\xa8\xf9F\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x86\xa1\xea\xde\xeb0F\x13E\xd9\xefk\xd0R\x16\xfa$|\r\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86\xa5\xf8%\x9e\u0570\x9e\x18\x8c\xe3F\xee\x92\xd3J\xa5\u0753\xfa\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xb7\xbdV<\uad86\xf9bD\xf9\xdd\xc0*\u05f0\xb1K\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x86\u008bVx\xaf7\xd7'\xec\x05\xe4Dw\x90\xf1_q\xf2\xea\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xc4\xce\x06\u066c\x18[\xb1H\xd9o{z\xbes\xf4A\x00m\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x86\xc8\xd0\u0642\xb59\xf4\x8f\x980\xf9\x89\x1f\x9d`z\x94&Y\x8a\x02\xce\xd3wa\x82O\xb0\x00\x00\u07d4\x86\xc94\xe3\x8eS\xbe;3\xf2t\xd0S\x9c\xfc\xa1Y\xa4\xd0\u04494\x95tD\xb8@\xe8\x00\x00\xe0\x94\x86\xca\x01E\x95~k\r\xfe6\x87_\xbez\r\xecU\xe1z(\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x86\u02af\xac\xf3*\xa01|\x03*\xc3k\xab\xed\x97G\x91\xdc\x03\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x86\u0377\xe5\x1a\xc4Gr\xbe6\x90\xf6\x1d\x0eYvn\x8b\xfc\x18\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x86\xdfs\xbd7\u007f,\t\xdec\xc4]g\xf2\x83\xea\xef\xa0\xf4\xab\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x86\xe3\xfe\x86\xe9=\xa4\x86\xb1Bf\xea\xdf\x05l\xbf\xa4\xd9\x14C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x86\xe8g\x0e'Y\x8e\xa0\x9c8\x99\xabw\x11\u04f9\xfe\x90\x1c\x17\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x86\xefd&!\x19I\xcc7\xf4\xc7^xP6\x9d\f\xf5\xf4y\x8a\x02\xd6_2\xea\x04Z\xf6\x00\x00\u07d4\x86\xf0]\x19\x06>\x93i\xc6\x00N\xb3\xf1#\x94:|\xffN\xab\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x86\xf2>\x9c\n\xaf\u01cb\x9c@M\xcd`3\x9a\x92[\xff\xa2f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x86\xf4\xf4\n\u0644\xfb\xb8\t3\xaebn\x0eB\xf93?\xddA\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x86\xf9\\[\x11\xa2\x93\x94\x0e5\xc0\xb8\x98\u0637_\b\xaa\xb0m\x8a\x06D\xe3\xe8u\xfc\xcft\x00\x00\u07d4\x86\xff\xf2 \xe5\x93\x05\xc0\x9fH8`\xd6\xf9N\x96\xfb\xe3/W\x89\x02S[j\xb4\xc0B\x00\x00\u07d4\x87\a\x96\xab\xc0\u06c4\xaf\x82\xdaR\xa0\xedhsM\xe7\xe66\xf5\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x87\x0f\x15\xe5\u07cb\x0e\xab\xd0%iSz\x8e\xf9;Vx\\B\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\x87\x181`\xd1r\xd2\xe0\x84\xd3'\xb8k\xcb|\x1d\x8eg\x84\xef\x89\xd8\xd8X?\xa2\xd5/\x00\x00\xe0\x94\x87\x1b\x8a\x8bQ\u07a1\x98\x9aY!\xf1>\xc1\xa9U\xa5\x15\xadG\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x87%\xe8\xc7S\xb3\xac\xbf\u0725_I\x13\\3\x91\x99\x10`)\n\xa7\xf6\u0338\xf8Zx\u06c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x87Pa\xee\x12\xe8 \x04\x1a\x01\x94,\xb0\xe6[\xb4'\xb0\x00`\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\x87XJ?a;\xd4\xfa\xc7L\x1ex\v\x86\xd6\xca\xeb\x89\f\xb2\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x87d\xd0'\"\x00\t\x96\xec\xd4u\xb43)\x8e\x9fT\v\x05\xbf\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x87l?!\x8bGv\xdf<\xa9\xdb\xfb'\r\xe1R\xd9N\xd2R\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x87u\xa6\x10\xc5\x02\xb9\xf1\xe6\xadL\xda\u06cc\xe2\x9b\xffu\xf6\xe4\x89 \x86\xac5\x10R`\x00\x00\u07d4\x87vN6w\xee\xf6\x04\xcb\u015a\xed$\xab\xdcVk\t\xfc%\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\x87\x87\xd1&w\xa5\xec)\x1eW\xe3\x1f\xfb\xfa\xd1\x05\xc32K\x87\x8a\x02\xa2N\xb52\b\xf3\x12\x80\x00\u07d4\x87\x94\xbfG\xd5E@\xec\xe5\xc7\"7\xa1\xff\xb5\x11\u0777Gb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x87\xa5>\xa3\x9fY\xa3[\xad\xa85%!dU\x94\xa1\xa7\x14\u02c9g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x87\xa7\xc5\b\xefqX-\u0665Cr\xf8\x9c\xb0\x1f%/\xb1\x80\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x87\xaf%\xd3\xf6\xf8\xee\xa1S\x13\xd5\xfeEW\xe8\x10\xc5$\xc0\x83\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x87\xb1\x0f\x9c(\x00\x98\x17\x9a+v\xe9\u0390\xbea\xfc\x84M\r\x89Hz\x9a0E9D\x00\x00\u07d4\x87\xbf|\xd5\u0629)\xe1\u01c5\xf9\xe5D\x91\x06\xac#$c\u0249\x047\xb1\x1f\xccEd\x00\x00\u07d4\x87\u0118\x17\t4\xb8#=\x1a\xd1\xe7i1}\\G_/@\x897\b\xba\xed=h\x90\x00\x00\u07d4\x87\xcf6\xad\x03\xc9\xea\xe9\x05:\xbbRB\u0791\x17\xbb\x0f*\v\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x87\u05ec\x06S\xcc\xc6z\xa9\xc3F\x9e\xefCR\x19?}\xbb\x86\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94\x87\xe3\x06+#!\xe9\u07f0\x87\\\u311c\x9b.5\"\xd5\n\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x87\xe6\x03N\xcf#\xf8\xb5c\x9d_\x0e\xa7\n\"S\x8a\x92\x04#\x89\x11\xc7\xea\x16.x \x00\x00\u07d4\x87\xefm\x8bj|\xbf\x9b\\\x8c\x97\xf6~\xe2\xad\u00a7;?w\x89\n\xdd\x1b\xd2<\x00L\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x88F\x92\x8dh2\x89\xa2\xd1\x1d\xf8\xdbz\x94t\x98\x8e\xf0\x13H\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x88I\x80\xebEe\xc1\x04\x83\x17\xa8\xf4\u007f\u06f4a\x96[\u4049\xd8\xd6\x11\x9a\x81F\x05\x00\x00\xe0\x94\x88Jz9\u0411n\x05\xf1\xc2B\xdfU`\u007f7\u07cc_\u068a\x04\xf4\x84<\x15|\x8c\xa0\x00\x00\u07d4\x88T\x93\xbd\xa3j\x042\x97eF\xc1\xdd\xceq\xc3\xf4W\x00!\x89\v\xbfQ\r\xdf\xcb&\x00\x00\xe0\x94\x88`\x9e\nF[n\x99\xfc\xe9\a\x16mW\xe9\xda\b\x14\xf5\u020a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x88m\n\x9e\x17\xc9\xc0\x95\xaf.\xa25\x8b\x89\xecpR\x12\ue509\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\x88y~Xg^\xd5\xccL\x19\x98\a\x83\xdb\xd0\xc9V\bQS\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x88|\xacA\xcdpo3E\xf2\xd3J\xc3N\x01u*nY\t\x89 F\\\ue7617\x00\x00\u07d4\x88\x88\x8aW\xbd\x96\x87\xcb\xf9P\xae\xea\u03d7@\xdc\xc4\xd1\xefY\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u0794\x88\x89D\x83\x16\xcc\xf1N\xd8m\xf8\xe2\xf4x\xdcc\xc43\x83@\x88\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x88\x8c\x16\x14I3\x19|\xac&PM\xd7n\x06\xfdf\x00\u01c9\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x88\x8e\x94\x91p\x83\xd1R +S\x1699\x86\x9d'\x11u\xb4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x88\x90\x87\xf6o\xf2\x84\xf8\xb5\xef\xbd)I;pg3\xab\x14G\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\x88\x95\xebrb&\xed\xc3\xf7\x8c\u01a5\x15\a{2\x96\xfd\xb9^\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x88\x97Z_\x1e\xf2R\x8c0\v\x83\xc0\xc6\a\xb8\xe8}\u0593\x15\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\u07d4\x88\x9d\xa4\x0f\xb1\xb6\x0f\x9e\xa9\xbdzE>XL\xf7\xb1\xb4\xd9\xf7\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x88\x9d\xa6b\xebJ\n*\x06\x9d+\xc2K\x05\xb4\xee.\x92\xc4\x1b\x89Z,\x8cTV\xc9\xf2\x80\x00\u07d4\x88\xa1\"\xa28,R91\xfbQ\xa0\u032d;\xeb[rY\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x88\xa2\x15D0\xc0\xe4\x11G\xd3\xc1\xfe\u3cf0\x06\xf8Q\xed\xbd\x8965f3\xeb\xd8\xea\x00\x00\u07d4\x88\xb2\x17\u0337\x86\xa2T\xcfM\xc5\u007f]\x9a\xc3\xc4U\xa3\x04\x83\x892$\xf4'#\xd4T\x00\x00\xe0\x94\x88\xbcC\x01.\xdb\x0e\xa9\xf0b\xacCxC%\n9\xb7\x8f\xbb\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x88\xc2Qj|\xdb\t\xa6'mr\x97\xd3\x0fZM\xb1\xe8K\x86\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x88\xc3ad\rki7;\b\x1c\xe0\xc43\xbdY\x02\x87\xd5\xec\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x88\xd5A\xc8@\xceC\xce\xfb\xafm\x19\xafk\x98Y\xb5s\xc1E\x89\t79SM(h\x00\x00\u07d4\x88\xde\x13\xb0\x991\x87|\x91\rY1e\xc3d\u0221d\x1b\u04c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x88\xde\u017d?N\xba-\x18\xb8\xaa\xce\xfa{r\x15H\xc3\x19\xba\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\x88\xe6\xf9\xb2G\xf9\x88\xf6\xc0\xfc\x14\xc5o\x1d\xe5>\u019dC\u0309\x05k\xc7^-c\x10\x00\x00\u07d4\x88\xee\u007f\x0e\xfc\x8fw\x8ckh~\xc3+\xe9\xe7\xd6\xf0 \xb6t\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x88\xf1\x04_\x19\xf2\xd3\x19\x18\x16\xb1\xdf\x18\xbbn\x145\xad\x1b8\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x89\x00\x9e\a\xe3\xfahc\xa7x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x89Wr~r\xcfb\x90 \xf4\xe0^\xdfy\x9a\xa7E\x80b\u0409wC\"\x17\xe6\x83`\x00\x00\u07d4\x89]iN\x88\v\x13\xcc\u0404\x8a\x86\xc5\xceA\x1f\x88Gk\xbf\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x89^\xc5TVD\u0dc30\xff\xfa\xb8\xdd\xea\xc9\xe83\x15l\x89 \x86\xac5\x10R`\x00\x00\u07d4\x89`\tRj,{\f\t\xa6\xf6:\x80\xbd\U0009d707\u079c\x89\xbb\xb8k\x82#\xed\xeb\x00\x00\u07d4\x89g\u05f9\xbd\xb7\xb4\xae\xd2.e\xa1]\xc8\x03\xcbz!?\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x89n3\\\xa4z\xf5yb\xfa\x0fM\xbf>E\xe6\x88\u02e5\x84\x89J/\xc0\xab`R\x12\x00\x00\u07d4\x89s\xae\xfd^\xfa\xee\x96\t]\x9e(\x8fj\x04l\x977KC\x89\a\xa4\u0120\xf32\x14\x00\x00\u07d4\x89\x8cr\xddseX\xef\x9eK\xe9\xfd\xc3O\xefT\xd7\xfc~\b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x89\x9b<$\x9f\fK\x81\xdfu\xd2\x12\x00M=m\x95/\xd2#\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x89\xab\x13\xee&mw\x9c5\xe8\xbb\x04\u034a\x90\xcc!\x03\xa9[\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\x89\xc43\xd6\x01\xfa\xd7\x14\xdaci0\x8f\xd2l\x1d\u0254+\xbf\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x89\xd7[\x8e\b1\xe4o\x80\xbc\x17A\x88\x18N\x00o\xde\x0e\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x89\u3d5a\x15\x86G7\u0513\xc1\xd2<\xc5=\xbf\x8d\xcb\x13b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x89\xfc\x8eM8k\r\v\xb4\xa7\a\xed\xf3\xbdV\r\xf1\xad\x8fN\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\x89\xfe\xe3\r\x17(\xd9l\xec\xc1\u06b3\xda.w\x1a\xfb\u03eaA\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x8a\x1c\u016c\x11\x1cI\xbf\xcf\xd8H\xf3}\xd7h\xaae\u0208\x02\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x8a \xe5\xb5\xce\xe7\xcd\x1fU\x15\xba\xce;\xf4\xf7\u007f\xfd\xe5\xcc\a\x89\x04V9\x18$O@\x00\x00\xe0\x94\x8a!}\xb3\x8b\xc3_!_\xd9)\x06\xbeBCo\xe7\xe6\xed\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x8a$:\n\x9f\xeaI\xb89TwE\xff-\x11\xaf?K\x05\"\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x8a$}\x18e\x10\x80\x9fq\xcf\xfcEYG\x1c9\x10\x85\x81!\x89a\t=|,m8\x00\x00\u07d4\x8a4p(-^**\xef\u05e7P\x94\xc8\"\xc4\xf5\xae\uf289\r(\xbc`dx\xa5\x80\x00\u07d4\x8a6\x86\x9a\xd4x\x99|\xbfm\x89$\xd2\n<\x80\x18\xe9\x85[\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8aC\x14\xfba\u0353\x8f\xc3>\x15\xe8\x16\xb1\x13\U000ac267\xfb\x89\x17vNz\xede\x10\x00\x00\u07d4\x8aOJ\u007fR\xa3U\xba\x10_\xca r\xd3\x06_\xc8\xf7\x94K\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8aX1(,\xe1Jezs\r\xc1\x88&\xf7\xf9\xb9\x9d\xb9h\x89\uaf8a[A\xc16\x00\x00\u07d4\x8a_\xb7W\x93\xd0C\xf1\xbc\xd48\x85\xe07\xbd0\xa5(\xc9'\x89\x13Snm.\x9a\xc2\x00\x00\u07d4\x8af\xab\xbc-0\xce!\xa83\xb0\u06ceV\x1dQ\x05\xe0\xa7,\x89%\xf1\xde\\v\xac\xdf\x00\x00\u07d4\x8atl]g\x06G\x11\xbf\xcah[\x95\xa4\xfe)\x1a'\x02\x8e\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8ax\n\xb8z\x91E\xfe\x10\xed`\xfaGjt\n\xf4\u02b1\u0489\x12\x1b.^ddx\x00\x00\u07d4\x8az\x06\xbe\x19\x9a:X\x01\x9d\x84j\xc9\xcb\xd4\xd9]\xd7W\u0789\xa2\xa4#\x94BV\xf4\x00\x00\u07d4\x8a\x81\x01\x14\xb2\x02]\xb9\xfb\xb5\x00\x99\xa6\xe0\u02de.\xfak\u0709g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x8a\x86\xe4\xa5\x1c\x01;\x1f\xb4\xc7k\xcf0f|x\xd5.\xed\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\x9e\u029cZ\xba\x8e\x13\x9f\x80\x03\xed\xf1\x16:\xfbp\xaa:\xa9\x89#\xc7W\a+\x8d\xd0\x00\x00\u07d4\x8a\xb89\xae\xaf*\xd3|\xb7\x8b\xac\xbb\xb63\xbc\xc5\xc0\x99\xdcF\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\u021b\u06780\x1ek\x06w\xfa%\xfc\xf0\xf5\x8f\f\u01f6\x11\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x8a\xdcS\xef\x8c\x18\xed0Qx]\x88\xe9\x96\xf3\xe4\xb2\x0e\xcdQ\x8a\b\xe4\xd3\x16\x82v\x86@\x00\x00\u07d4\x8a\xe6\xf8\vp\xe1\xf2<\x91\xfb\u0569f\xb0\xe4\x99\xd9]\xf82\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x8a\xe9\uf30a\x8a\u07e6\xaby\x8a\xb2\xcd\xc4\x05\b*\x1b\xbbp\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8a\xf6&\xa5\xf3'\xd7Pe\x89\xee\xb7\x01\x0f\xf9\xc9D` \u0489K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\x8b\x01\xda4\xd4p\xc1\xd1\x15\xac\xf4\xd8\x11\xe1\x01\xdb\x1e\x14\xec\xc7\xd3\"\xc7+\x8c\x04s\x89\x18\xb2j1>\x8a\xe9\x00\x00\xe0\x94\x8bH\xe1\x9d9\xdd5\xb6nn\x1b\xb6\xb9\xc6W\xcb,\xf5\x9d\x04\x8a\x03\xc7U\xac\x9c\x02J\x01\x80\x00\xe0\x94\x8bP^(q\xf7\u07b7\xa68\x95 \x8e\x82'\u072a\x1b\xff\x05\x8a\f\xf6\x8e\xfc0\x8dy\xbc\x00\x00\u07d4\x8bW\xb2\xbc\x83\u030dM\xe31 N\x89?/;\x1d\xb1\a\x9a\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8b\\\x91K\x12\x8b\xf1i\\\b\x89#\xfaF~y\x11\xf3Q\xfa\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\xe0\x94\x8b_)\xcc/\xaa&,\xde\xf3\x0e\xf5T\xf5\x0e\xb4\x88\x14n\xac\x8a\x01;hp\\\x97 \x81\x00\x00\u07d4\x8bpV\xf6\xab\xf3\xb1\x18\xd0&\xe9D\xd5\xc0sC<\xa4Q\u05c965\xc6 G9\u0640\x00\u07d4\x8bqE\"\xfa(9b\x04p\xed\xcf\fD\x01\xb7\x13f=\xf1\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x8bt\xa7\xcb\x1b\xb8\u014f\xce&tf\xa3\x03X\xad\xafR\u007fa\x8a\x02\xe2WxN%\xb4P\x00\x00\u07d4\x8b~\x9fo\x05\xf7\xe3dv\xa1n>q\x00\xc9\x03\x1c\xf4\x04\xaf\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8b\x81\x15ni\x869\x94<\x01\xa7Rr\xad=5\x85\x1a\xb2\x82\x89\x12\xb3\x16_e\xd3\xe5\x00\x00\u07d4\x8b\x95w\x92\x00S\xb1\xa0\x01\x890M\x88\x80\x10\xd9\xef,\xb4\xbf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8b\x98A\x86.w\xfb\xbe\x91\x94p\x93U\x83\xa9<\xf0'\xe4P\x89llS4B\u007f\x1f\x00\x00\u07d4\x8b\x99}\xbc\a\x8a\xd0)a5]\xa0\xa1Y\xf2\x92~\xd4=d\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x8b\x9f\xda}\x98\x1f\xe9\xd6B\x87\xf8\\\x94\xd8?\x90t\x84\x9f\u030a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x8b\xb0!/2\x95\xe0)\u02b1\xd9a\xb0A3\xa1\x80\x9e{\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8b\xbe\xac\xfc)\xcf\xe94\x02\xdb\xd6j\x1a\xcbvv\x85c7\xb9;\xf0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8b\xf3s\xd0v\x81L\xbcW\xe1\xc6\xd1j\x82\u017e\x13\xc7=7\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x8c\x10#\xfd\xe1WM\xb8\xbbT\xf1s\x96p\x15|\xa4}\xa6R\x8a\x01y\u03da\u00e1\xb1w\x00\x00\u07d4\x8c\x1f\xbe_\n\xea5\x9cZ\xa1\xfa\b\u0209T\x12\u028e\x05\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\"B`U\xb7o\x11\xf0\xa2\xde\x1a\u007f\x81\x9aa\x96\x85\xfe`\x89kV\x05\x15\x82\xa9p\x00\x00\u07d4\x8c+}\x8b`\x8d(\xb7\u007f\\\xaa\x9c\xd6E$*\x82>L\u0649b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\x8c/\xbe\ue3ac\xc5\xc5\xd7|\x16\xab\xd4b\ue701E\xf3K\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x8c:\x9e\xe7\x1fr\x9f#l\xba8g\xb4\u05dd\x8c\xee\xe2]\xbc\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8cP\xaa*\x92\x12\xbc\xdeVA\x8a\xe2a\xf0\xb3^z\x9d\xbb\x82\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8cT\xc7\xf8\xb9\x89nu\xd7\xd5\xf5\xc7`%\x86\x99\x95qB\xad\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x8c]\x16\xede\xe3\xed~\x8b\x96\u0297+\xc8as\xe3P\v\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8cj\xa8\x82\xee2,\xa8HW\x8c\x06\xcb\x0f\xa9\x11\xd3`\x83\x05\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\x8cj\xe7\xa0Z\x1d\xe5u\x82\xae'h Bv\xc0\xffG\xed\x03\x8a,\v\xb3\xdd0\xc4\xe2\x00\x00\x00\u07d4\x8co\x9fN[z\xe2v\xbfXI{\u05ff*}%$_d\x89\x93\xfe\\W\xd7\x10h\x00\x00\u07d4\x8cu\x95n\x8f\xedP\xf5\xa7\xdd|\xfd'\xda \x0fgF\xae\xa6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c|\xb4\xe4\x8b%\x03\x1a\xa1\xc4\xf9)%\xd61\xa8\xc3\xed\xc7a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\u007f\xa5\xca\xe8/\xed\xb6\x9a\xb1\x89\xd3\xff'\xae \x92\x93\xfb\x93\x89\x15\xaf\x88\r\x8c\u06c3\x00\x00\xe0\x94\x8c\x81A\x0e\xa85L\xc5\xc6\\A\xbe\x8b\xd5\xdes<\v\x11\x1d\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\x8c\x83\xd4$\xa3\xcf$\xd5\x1f\x01\x92=\xd5J\x18\u05b6\xfe\xde{\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8c\x90\n\x826\xb0\x8c+e@]9\xd7_ \x06*ua\xfd\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\x8c\x93\xc3\xc6\u06dd7q}\xe1e\u00e1\xb4\xfeQ\x95,\b\u0789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8c\x99\x95\x91\xfdr\xefq\x11\xef\xcaz\x9e\x97\xa25k;\x00\n\x89\xddd\xe2\xaa\ngP\x00\x00\u07d4\x8c\xa6\x98\x97F\xb0n2\xe2Hta\xb1\u0399j':\xcf\u05c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8c\xb3\xaa?\xcd!(T\xd7W\x8f\xcc0\xfd\xed\xe6t*1*\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x8c\xc0\xd7\xc0\x16\xfaz\xa9P\x11J\xa1\xdb\tH\x82\xed\xa2t\xea\x89\b\xa9\xab\xa5W\xe3l\x00\x00\u07d4\x8c\xc6R\xdd\x13\xe7\xfe\x14\u06bb\xb3m]2\r\xb9\xff\xee\x8aT\x89a\t=|,m8\x00\x00\u07d4\x8c\u02bf%\a\u007f:\xa4\x15E4MS\xbe\x1b+\x9c3\x90\x00\x89[\xe8f\xc5b\xc5D\x00\x00\u07d4\x8c\xcf:\xa2\x1a\xb7BWj\xd8\xc4\"\xf7\x1b\xb1\x88Y\x1d\ua28965\u026d\xc5\u07a0\x00\x00\u07d4\x8c\xd0\xcd\"\xe6 \xed\xa7\x9c\x04a\xe8\x96\xc9\xd1b)\x12K_z\xfb\xec\x89\a?u\u0460\x85\xba\x00\x00\u07d4\x8c\xe2/\x9f\xa3rD\x9aB\x06\x10\xb4z\xe0\xc8\xd5eH\x122\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x8c\u451d\x8a\x16T-B<\x17\x98Ng9\xfar\u03b1w\x8a\x05K@Y&\xf4\xa6=\x80\x00\u07d4\x8c\xe5\xe3\xb5\xf5\x91\xd5\uc8ca\xbf\"\x8f.<5\x13K\xda\xc0\x89}\xc3[\x84\x89|8\x00\x00\xe0\x94\x8c\xee8\xd6YW\x88\xa5n?\xb9F4\xb3\xff\xe1\xfb\xdb&\u058a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x8c\xee\xa1^\xec;\xda\xd8\x02?\x98\xec\xf2[+\x8f\xef'\xdb)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8c\xf3To\xd1\u0363=X\x84_\xc8\xfc\xfe\u02bc\xa7\xc5d*\x89\x1f\x1e9\x93,\xb3'\x80\x00\u07d4\x8c\xf6\xda\x02\x04\xdb\u0106\vF\xad\x97?\xc1\x11\x00\x8d\x9e\fF\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x8c\xfe\xde\xf1\x98\xdb\n\x91C\xf0\x91)\xb3\xfdd\u073b\x9bIV\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\x04\xa5\xeb\xfb]\xb4\t\xdb\x06\x17\xc9\xfaV1\xc1\x92\x86\x1fJ\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x8d\x06\xe4d$\\\xadaI9\xe0\xaf\bE\xe6\xd70\xe2\x03t\x89\n\u070a(\xf3\xd8}\x80\x00\u07d4\x8d\a\xd4-\x83\x1c-|\x83\x8a\xa1\x87+:\xd5\xd2w\x17h#\x89\x12\xee\x1f\x9d\xdb\xeeh\x00\x00\u07d4\x8d\v\x9e\xa5?\xd2cA^\xac\x119\x1f|\xe9\x12V\xb9\xfb\x06`\xf6\xf0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8dy\\_JV\x89\xadb\u0696\x16q\xf0(\x06R\x86\xd5T\x89o\x05\xb5\x9d; \x00\x00\x00\u07d4\x8d\u007f>a)\x9c-\xb9\xb9\xc0H|\xf6'Q\x9e\xd0\n\x91#\x89^t\xa8P^\x80\xa0\x00\x00\xe0\x94\x8d\x89\x17\v\x92\xb2\xbe,\b\xd5|H\xa7\xb1\x90\xa2\xf1Fr\x0f\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\x8d\x93\xda\u01c5\xf8\x8f\x1a\x84\xbf\x92}Se+E\xa1T\xcc\u0749\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x8d\x99R\u043bN\xbf\xa0\xef\xd0\x1a:\xa9\xe8\xe8\u007f\x05%t.\x89\xbb\x91%T\"c\x90\x00\x00\u07d4\x8d\x9a\fp\xd2& B\xdf\x10\x17\xd6\xc3\x03\x13 $w'\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\x9e\xd7\xf4U0X\xc2ox6\xa3\x80-0d\xeb\x1b6=\x89\x04\xe1\x00;(\xd9(\x00\x00\u07d4\x8d\xa1\x17\x8fU\xd9wr\xbb\x1d$\x11\x1a@JO\x87\x15\xb9]\x89/\x9a\xc3\xf6\xde\x00\x80\x80\x00\u07d4\x8d\xa1\xd3Y\xbal\xb4\xbc\xc5}zCw \xd5]\xb2\xf0\x1cr\x89\x04V9\x18$O@\x00\x00\u07d4\x8d\xab\x94\x8a\xe8\x1d\xa3\x01\xd9r\xe3\xf6\x17\xa9\x12\xe5\xa7Sq.\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x8d\xad\xdfR\xef\xbdt\u0695\xb9i\xa5GoO\xbb\xb5c\xbf\u0489-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4\x8d\xb1\x85\xfe\x1bp\xa9Jj\b\x0e~#\xa8\xbe\xdcJ\xcb\xf3K\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x8d\xb5\x8e@n -\xf9\xbcpl\xb43\xe1\x94\xf4\x0f\x82\xb4\x0f\xaa\xdb\x1f\x8b\x85a\x16\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x8d\xc1\xd5\x11\x1d\t\xaf%\xfd\xfc\xacE\\|\xec(>mgu\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8d\u0504\xff\x8a0sd\xebf\xc5%\xa5q\xaa\xc7\x01\xc5\xc3\x18\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\u05a9\xba\xe5\u007fQ\x85I\xad\xa6wFo\ua2b0O\u0674\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\xde<\xb8\x11\x85h\xefE\x03\xfe\x99\x8c\xcd\xf56\xbf\x19\xa0\x98\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8d\xde`\xeb\b\xa0\x99\xd7\u06a3V\u06aa\xb2G\r{\x02Zk\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\x8d\xf39!Kj\u0472Fc\xceq`4t\x9dn\xf88\u064a\x02TO\xaaw\x80\x90\xe0\x00\x00\xe0\x94\x8d\xf5=\x96\x19\x14q\xe0Y\xdeQ\xc7\x18\xb9\x83\xe4\xa5\x1d*\xfd\x8a\x06\u01b95\xb8\xbb\xd4\x00\x00\x00\u07d4\x8d\xfb\xaf\xbc\x0e[\\\x86\xcd\x1a\u0597\xfe\xea\x04\xf41\x88\u0796\x89\x15%+\u007f_\xa0\xde\x00\x00\u07d4\x8e\a;\xad%\xe4\"\x18a_J\x0ek.\xa8\xf8\xde\"0\xc0\x89\x82=b\x9d\x02k\xfa\x00\x00\u07d4\x8e\x0f\xee8hZ\x94\xaa\xbc\xd7\u0385{k\x14\t\x82Ou\xb8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e#\xfa\xcd\x12\xc7e\xc3j\xb8\x1am\xd3M\x8a\xa9\xe6\x89\x18\xae\x89\t\x11\u418d\xba\x9b\x00\x00\xe0\x94\x8e/\x904\xc9%G\x19\u00ceP\u026ad0^\u0596\xdf\x1e\x8a\x01\x00N.E\xfb~\xe0\x00\x00\u07d4\x8e2@\xb0\x81\x0e\x1c\xf4\a\xa5\x00\x80G@\u03cdad2\xa4\x89\x02/fU\xef\v8\x80\x00\u07d4\x8eHj\x04B\xd1q\xc8`[\xe3H\xfe\xe5~\xb5\b^\xff\r\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8eaV3k\xe2\u037e2\x14\r\xf0\x8a+\xa5_\u0425\x84c\x89\x04\t\x9e\x1dcW\x18\x00\x00\u07d4\x8eg\b\x15\xfbg\xae\xae\xa5{\x86SN\xdc\x00\xcd\xf5d\xfe\u5272\xe4\xb3#\xd9\xc5\x10\x00\x00\u07d4\x8emt\x85\xcb\u942c\xc1\xad\x0e\xe9\xe8\xcc\xf3\x9c\f\x93D\x0e\x893\xc5I\x901r\f\x00\x00\xe0\x94\x8et\xe0\u0477~\xbc\x82:\xca\x03\xf1\x19\x85L\xb1 '\xf6\u05ca\x16\xb3R\xda^\x0e\xd3\x00\x00\x00\u07d4\x8ex\xf3QE}\x01oJ\xd2u^\xc7BN\\!\xbamQ\x89\a\xea(2uw\b\x00\x00\u07d4\x8ey6\u0552\x00\x8f\xdcz\xa0N\xde\xebuZ\xb5\x13\u06f8\x9d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8e\u007f\xd28H\xf4\xdb\a\x90j}\x10\xc0K!\x80;\xb0\x82'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8e\x92\xab\xa3\x8er\xa0\x98\x17\v\x92\x95\x92FSz.UV\xc0\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x8e\x98ve$\xb0\xcf'G\xc5\r\xd4;\x95gYM\x971\u0789lD\xb7\xc2a\x82(\x00\x00\u07d4\x8e\x9b5\xadJ\n\x86\xf7XDo\xff\xde4&\x9d\x94\f\xea\u0349\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8e\x9c\b\xf78f\x1f\x96v#n\xff\x82\xbaba\xdd?H\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8e\x9cB\x92f\xdf\x05~\xfax\xdd\x1d_w\xfc@t*\xd4f\x89\x10D.\u0475l|\x80\x00\u07d4\x8e\xa6V\xe7\x1e\xc6Q\xbf\xa1|ZWY\xd8`1\xcc5\x99w\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x8e\xae)CU\x98\xba\x8f\x1c\x93B\x8c\xdb>+M1\a\x8e\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\xb1\xfb\xe4\xe5\xd3\x01\x9c\xd7\xd3\r\xae\x9c\r[Lv\xfbc1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\xb5\x17t\xaf k\x96k\x89\t\xc4Z\xa6r'H\x80,\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e\xb8\xc7\x19\x82\xa0\x0f\xb8Bu)2S\xf8\x04ED\xb6kI\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\x8e\xcb\u03ec\xbf\xaf\xe9\xf0\f9\"\xa2N,\xf0\x02gV\xca \x8a\x011\xbe\xb9%\xff\xd3 \x00\x00\u07d4\x8e\u03b2\xe1$Sl[_\xfcd\x0e\xd1O\xf1^\u0668\xcbq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8e\u042f\x11\xff(p\xda\x06\x81\x00J\xfe\x18\xb0\x13\xf7\xbd8\x82\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\x8e\xd1Cp\x1f/r(\x0f\xd0J{Ad(\x19y\xea\x87\u0248\xc2I\xfd\xd3'x\x00\x00\u07d4\x8e\xd1R\x8bD~\xd4)y\x02\xf69\xc5\x14\u0414J\x88\xf8\u0209\n\xc6\xe7z\xb6c\xa8\x00\x00\u07d4\x8e\xd4(L\x0fGD\x9c\x15\xb8\u0673$]\u8fb6\u0380\xbf\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\x8e\xde~=\xc5\aI\xc6\xc5\x0e.(\x16\x84x\xc3M\xb8\x19F\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\x8e\xe5\x843}\xdb\xc8\x0f\x9e4\x98\xdfU\xf0\xa2\x1e\xac\xb5\u007f\xb1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x8e\xeb\xec\x1ab\xc0\x8b\x05\xa7\xd1\u0551\x80\xaf\x9f\xf0\u044e?6\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x8e\xf4\u0622\xc2o\xf7\x14\xb6u\x89\x19\x80\x1c\x83\xb6\xc7\xc0\x00\x00\u07d4\x8fM\x1dAi>F,\xf9\x82\xfd\x81\u042ap\x1d:St\u0249\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8fM\x1e~Ea(J4\xfe\xf9g<\r4\xe1*\xf4\xaa\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8fO\xb1\xae\xa7\xcd\x0fW\x0e\xa5\xe6\x1b@\xa4\xf4Q\vbd\xe4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x8fV\x1bA\xb2\t\xf2H\u0229\x9f\x85\x87\x887bP`\x9c\xf3\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94\x8fX\xd84\x8f\xc1\xdcN\r\xd84;eC\xc8W\x04^\xe9@\x8a\x02\xe3\x03\x8d\xf4s\x03(\x00\x00\u07d4\x8f`\x89_\xbe\xbb\xb5\x01\u007f\xcb\xff<\u0763\x97)+\xf2[\xa6\x89\x17D\x06\xff\x9fo\u0480\x00\u07d4\x8fd\xb9\xc1$m\x85x1d1\a\xd3U\xb5\xc7_\xef]O\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\x8ff\x0f\x8b.L|\u00b4\xac\x9cG\xed(P\x8d_\x8f\x86P\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x8fi\xea\xfd\x023\xca\xdb@Y\xabw\x9cF\xed\xf2\xa0PnH\x89`\xf0f \xa8IE\x00\x00\xe0\x94\x8fq~\xc1U/LD\x00\x84\xfb\xa1\x15J\x81\xdc\x00>\xbd\xc0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\x8f\x8a\xcb\x10v\a8\x84y\xf6K\xaa\xab\xea\x8f\xf0\a\xad\xa9}\x8a\x05\xc6\xf3\b\n\xd4#\xf4\x00\x00\u07d4\x8f\x8c\xd2n\x82\xe7\xc6\xde\xfd\x02\u07ed\a\x97\x90!\xcb\xf7\x15\f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x8f\x8f7\u042d\x8f3]*q\x01\xb4\x11V\xb6\x88\xa8\x1a\x9c\xbe\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\x8f\x92\x84O(*\x92\x99\x9e\u5d28\xd7s\xd0kiM\xbd\x9f\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x8f\xact\x8fxJ\x0f\xedh\u06e43\x19\xb4*u\xb4d\x9cn\x891T\xc9r\x9d\x05x\x00\x00\u07d4\x8f\u0665\xc3:}\x9e\xdc\xe0\x99{\xdfw\xab0d$\xa1\x1e\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x8f\xef\xfa\xdb8z\x15G\xfb(M\xa9\xb8\x14\u007f>|m\xc6\u0689-b{\xe4S\x05\b\x00\x00\u07d4\x8f\xf4`Ehw#\xdc3\xe4\u0419\xa0i\x04\xf1\ubd44\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\x8f\xfa\x06!\"\xac0t\x18\x82\x1a\u06d3\x11\aZ7\x03\xbf\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x8f\xfe2)\x97\xb8\xe4\x04B-\x19\xc5J\xad\xb1\x8f[\xc8\u9dc9\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x90\x01\x94\u0131\aC\x05\u045d\xe4\x05\xb0\xacx(\x0e\xca\xf9g\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x90\x03\xd2p\x89\x1b\xa2\xdfd=\xa84\x15\x83\x195E\xe3\xe0\x00\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x90\x05z\xf9\xaaf0~\xc9\xf03\xb2\x97$\u04f2\xf4\x1e\xb6\xf9\x8a\x19\xd1\u05aa\xdb,R\xe8\x00\x00\u07d4\x90\x0f\v\x8e5\xb6h\xf8\x1e\xf2R\xb18U\xaaP\a\xd0\x12\xe7\x89\x17\n\x0fP@\xe5\x04\x00\x00\u07d4\x90\x18\xcc\x1fH\xd20\x8e%*\xb6\b\x9f\xb9\x9a|\x1dV\x94\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x90\x1d\x99\xb6\x99\xe5\u0191\x15\x19\xcb v\xb4\xc7c0\xc5M\"\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x90-t\xa1W\xf7\u04b9\xa37\x8b\x1fVp70\xe0:\x17\x19\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x904\x13\x87\x8a\xea;\xc1\bc\t\xa3\xfev\x8beU\x9e\x8c\xab\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x90If\xcc\"\x13\xb5\xb8\xcb[\xd6\b\x9e\xf9\xcd\xdb\xef~\xdf\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\x90L\xaaB\x9ca\x9d\x94\x0f\x8egA\x82j\r\xb6\x92\xb1\x97(\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x90R\xf2\xe4\xa3\xe3\xc1-\xd1\xc7\x1b\xf7\x8aN\xc3\x04=\u020b~\x89\x0e~\xeb\xa3A\vt\x00\x00\u0794\x90U&V\x8a\xc1#\xaf\xc0\xe8J\xa7\x15\x12O\xeb\xe8=\xc8|\x88\xf8i\x93)g~\x00\x00\u07d4\x90\x92\x91\x87\a\xc6!\xfd\xbd\x1d\x90\xfb\x80\xebx\u007f\xd2osP\x89\x85[[\xa6\\\x84\xf0\x00\x00\u07d4\x90\x9b^v:9\xdc\u01d5\"=s\xa1\u06f7\xd9L\xa7Z\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\x90\xac\xce\xd7\xe4\x8c\b\u01b94dm\xfa\n\xdf)\u0714\aO\x89\x03\vK\x15{\xbdI\x00\x00\u07d4\x90\xb1\xf3p\xf9\xc1\xeb\v\xe0\xfb\x8e+\x8a\xd9jAcq\u074a\x890\xca\x02O\x98{\x90\x00\x00\u07d4\x90\xb6/\x13\x1a_)\xb4UqQ>\xe7\xa7J\x8f\v#\"\x02\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x90\xbdb\xa0P\x84Ra\xfaJ\x9f|\xf2A\xeac\v\x05\ufe09\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x90\xc4\x1e\xba\x00\x8e \xcb\xe9'\xf3F`?\u0206\x98\x12Yi\x89\x02F\xdd\xf9yvh\x00\x00\u07d4\x90\u0480\x9a\xe1\xd1\xff\xd8\xf6>\xda\x01\xdeI\xddU-\xf3\u047c\x89\u063beI\xb0+\xb8\x00\x00\u07d4\x90\xdc\t\xf7\x17\xfc*[i\xfd`\xba\b\xeb\xf4\v\xf4\xe8$l\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x90\xe3\x00\xacqE\x1e@\x1f\x88\u007fnw(\x85\x16G\xa8\x0e\a\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x90\xe3Z\xab\xb2\xde\xef@\x8b\xb9\xb5\xac\xefqDW\xdf\xdebr\x89\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\x90\xe7\a\x0fM\x03?\xe6\x91\f\x9e\xfeZ'\x8e\x1f\xc6#M\xef\x89\x05q8\b\x19\xb3\x04\x00\x00\u07d4\x90\xe9>M\xc1q!HyR36\x14\x00+\xe4#VI\x8e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x90\u9a68.\u06a8\x14\u0084\xd22\xb6\u9e90p\x1dIR\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\x90\xf7t\xc9\x14}\u0790\x85=\xdcC\xf0\x8f\x16\xd4U\x17\x8b\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x90\xfcS{!\x06Xf\n\x83\xba\xa9\xacJ\x84\x02\xf6WF\xa8\x89e\xea=\xb7UF`\x00\x00\u07d4\x91\x05\n\\\xff\xad\xed\xb4\xbbn\xaa\xfb\xc9\xe5\x014(\xe9l\x80\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x91\x05\x17d\xafk\x80\x8eB\x12\xc7~0\xa5W.\xaa1pp\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x91\v}Wz~9\xaa#\xac\xf6*\xd7\xf1\xef4)4\xb9h\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x91\x0e\x99eC4Lh\x15\xfb\x97\u0367\xafK\x86\x98vZ[\x89\x05\x9a\xf6\x98)\xcfd\x00\x00\u07d4\x91\x1f\xee\xa6\x1f\xe0\xedP\u0179\xe5\xa0\xd6`q9\x9d(\xbd\u0189\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x91\x1f\xf23\xe1\xa2\x11\xc0\x17,\x92\xb4l\xf9\x97\x03\x05\x82\xc8:\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x91 \xe7\x11s\xe1\xba\x19\xba\x8f\x9fO\xdb\u072a4\xe1\u05bbx\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91!\x17\x12q\x9f+\bM;8u\xa8Pi\xf4f61A\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x91#\x04\x11\x8b\x80G=\x9e\x9f\xe3\xeeE\x8f\xbea\x0f\xfd\xa2\xbb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x91Tky\xec\xf6\x9f\x93kZV\x15\b\xb0\xd7\xe5\f\u0159/\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x91V\u0440)5\x0eG\x04\b\xf1_\x1a\xa3\xbe\x9f\x04\ng\u018965\u026d\xc5\u07a0\x00\x00\u07d4\x91b\x0f>\xb3\x04\xe8\x13\u048b\x02\x97Ume\xdcN]\u5a89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\x91k\xf7\xe3\xc5E\x92\x1d2\x06\xd9\x00\xc2O\x14\x12|\xbd^p\x8a\x03\xd0\u077c}\xf2\xbb\x10\x00\x00\u0794\x91l\xf1}qA(\x05\xf4\xaf\xc3DJ\v\x8d\xd1\xd93\x9d\x16\x88\xc6s\xce<@\x16\x00\x00\u07d4\x91{\x8f\x9f:\x8d\t\xe9 ,R\u009erA\x96\xb8\x97\xd3^\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\x91\x89g\x91\x8c\u0617\xdd\x00\x05\xe3m\xc6\u0203\xefC\x8f\xc8\u01c9\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\x91\x89\x8e\xab\x8c\x05\xc0\"(\x83\xcdM\xb2;w\x95\xe1\xa2J\u05c9lk\x93[\x8b\xbd@\x00\x00\u0794\x91\x91\xf9F\x98!\x05\x16\xcfc!\xa1B\a\x0e Yvt\xed\x88\xee\x9d[\xe6\xfc\x11\x00\x00\u07d4\x91\xa4\x14\x9a,{\x1b:g\xea(\xaf\xf3G%\u0fcdu$\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x91\xa7\x87\xbcQ\x96\xf3HW\xfe\f7/M\xf3v\xaa\xa7f\x13\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91\xa8\xba\xae\xd0\x12\xea.c\x80;Y=\r\f*\xabL[\n\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x91\xac\\\xfeg\xc5J\xa7\xeb\xfb\xa4HflF\x1a;\x1f\xe2\xe1\x89\x15\xc94\x92\xbf\x9d\xfc\x00\x00\u07d4\x91\xbb?y\x02+\xf3\xc4S\xf4\xff%n&\x9b\x15\xcf,\x9c\xbd\x89RX\\\x13\xfe:\\\x00\x00\u07d4\x91\xc7^<\xb4\xaa\x89\xf3F\x19\xa1d\xe2\xa4x\x98\xf5gM\x9c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x91\xc8\f\xaa\b\x1b85\x1d*\x0e\x0e\x00\xf8\n4\xe5dt\xc1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x91\xccF\xaa7\x9f\x85jf@\xdc\xcdZd\x8ay\x02\xf8I\u0649\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x91\u04a9\xee\x1am\xb2\x0fS\x17\u0327\xfb\xe218\x95\u06ce\xf8\x8a\x01\xcc\u00e5/0n(\x00\x00\u07d4\x91\xd6n\xa6(\x8f\xaaK=`l*\xa4\\{k\x8a%'9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x91\u06f6\xaa\xad\x14\x95\x85\xbeG7\\]m\xe5\xff\t\x19\x15\x18\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x91\xe8\x81\x06R\xe8\xe6\x16\x15%\xd6;\xb7u\x1d\xc2\x0fg`v\x89'Mej\xc9\x0e4\x00\x00\u07d4\x91\xf5\x16\x14l\xda (\x17\x19\x97\x80`\u01beAI\x06|\x88\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x91\xf6$\xb2J\x1f\xa5\xa0V\xfeW\x12)\xe77\x9d\xb1K\x9a\x1e\x8a\x02\x8a\x85\x17\xc6i\xb3W\x00\x00\xe0\x94\x91\xfe\x8aLad\u07cf\xa6\x06\x99]k\xa7\xad\xca\xf1\u0213\u038a\x03\x99\x92d\x8a#\u0220\x00\x00\u07d4\x92\x1fRa\xf4\xf6\x12v\a\x06\x89&%\xc7^{\u0396\xb7\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92!\xc9\xce\x01#&et\x10\x96\xac\a#Y\x03\xad\x1f\xe2\xfc\x89\x06\xdbc3U\"b\x80\x00\u07d4\x92%\x988`\xa1\xcbF#\xc7$\x80\xac\x16'+\f\x95\xe5\xf5\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x92%\xd4jZ\x80\x949$\xa3\x9e[\x84\xb9m\xa0\xacE\x05\x81\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x92* \u01da\x1d:&\xdd8)g{\xf1\xd4\\\x8fg+\xb6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x92C\x8eR\x03\xb64o\xf8\x86\xd7\xc3b\x88\xaa\xcc\xccx\xce\u028965\u026d\xc5\u07a0\x00\x00\u07d4\x92C\xd7v-w({\x12c\x86\x88\xb9\x85N\x88\xa7i\xb2q\x8965\u026d\xc5\u07a0\x00\x00\u0794\x92K\xcez\x85<\x97\v\xb5\xec{\xb7Y\xba\xeb\x9ct\x10\x85{\x88\xbe -j\x0e\xda\x00\x00\u07d4\x92N\xfam\xb5\x95\xb7\x93\x13'~\x881\x96%\akX\n\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92U\x82&\xb3\x84bl\xadH\xe0\x9d\x96k\xf19^\xe7\xea]\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4\x92`\x82\xcb~\xedK\x19\x93\xad$ZGrg\xe1\xc3<\xd5h\x89\x14Jt\xba\u07e4\xb6\x00\x00\u07d4\x92b\t\xb7\xfd\xa5N\x8d\u06dd\x9eM=\x19\xeb\u070e\x88\u009f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92h\xd6&FV6\x11\xdc;\x83*0\xaa#\x94\xc6F\x13\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92i\x8e4Sx\xc6-\x8e\xda\x18M\x946j\x14K\f\x10[\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\x92y:\u0173rhwJq0\xde+\xbd3\x04\x05f\x17s\x89\x02,\xa3X|\xf4\xeb\x00\x00\xe0\x94\x92y\xb2\"\x8c\xec\x8f{M\xda?2\x0e\x9a\x04f\xc2\xf5\x85\u028a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x92|\xb7\xdc\x18p6\xb5B{\xc7\xe2\x00\xc5\xecE\f\x1d'\u0509\v\xb5\x9a'\x95<`\x00\x00\u07d4\x92|\u00bf\xda\x0e\b\x8d\x02\xef\xf7\v8\xb0\x8a\xa5<\xc3\tA\x89do`\xa1\xf9\x866\x00\x00\xe0\x94\x92\x84\xf9m\xdbG\xb5\x18n\xe5X\xaa12M\xf56\x1c\x0fs\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\x92\x9d6\x8e\xb4j-\x1f\xbd\xc8\xff\xa0`~\xdeK\xa8\x8fY\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xa7\u0166Cb\xe9\xf8B\xa2=\xec\xa2\x105\x85\u007f\x88\x98\x00\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\x92\xa8\x98\xd4o\x19q\x9c8\x12j\x8a<'\x86z\xe2\xce\u5589lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xa9q\xa79y\x9f\x8c\xb4\x8e\xa8G]r\xb2\xd2GAr\xe6\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x92\xaa\xe5\x97h\xed\xdf\xf8<\xfe`\xbbQ.s\n\x05\xa1a\u05c9\\\x97xA\fv\u0440\x00\u07d4\x92\xad\x1b=u\xfb\xa6}Tf=\xa9\xfc\x84\x8a\x8a\xde\x10\xfag\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xae[|~\xb4\x92\xff\x1f\xfa\x16\xddB\xad\x9c\xad@\xb7\xf8\u0709.\xe4IU\b\x98\xe4\x00\x00\u07d4\x92\xc0\xf5s\xec\xcfb\xc5H\x10\xeek\xa8\xd1\xf1\x13T+0\x1b\x89\xb7ro\x16\u0331\xe0\x00\x00\u07d4\x92\xc1?\xe0\xd6\u0387\xfdP\xe0=\uf7e6@\x05\t\xbdps\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x92\xc9L( \xdf\xcfqV\xe6\xf10\x88\xec\u754b6v\xfd\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4\x92\xcf\xd6\x01\x88\xef\u07f2\xf8\xc2\xe7\xb1i\x8a\xbb\x95&\xc1Q\x1f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\u062d\x9aMah;\x80\u0526g.\x84\xc2\rbB\x1e\x80\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x92\u0725\xe1\x02\xb3\xb8\x1b`\xf1\xa5\x04cIG\xc3t\xa8\x8c\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x92\xe454\x0e\x9d%<\x00%c\x89\xf5+\x06}U\x97Nv\x89\x0e\x87?D\x13<\xb0\x00\x00\xe0\x94\x92\xe49(\x16\xe5\xf2\xef_\xb6X7\xce\xc2\xc22\\\xc6I\"\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x92\xe6X\x1e\x1d\xa1\xf9\xb8F\xe0\x93G3=\xc8\x18\xe2\u04acf\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\x93\x1d\xf3M\x12%\xbc\xd4\"Nch\r\\L\t\xbc\xe75\xa6\x89\x03\xaf\xb0\x87\xb8v\x90\x00\x00\u07d4\x93\x1f\xe7\x12\xf6B\a\xa2\xfdP\"r\x88CT\x8b\xfb\x8c\xbb\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x93#_4\r(c\xe1\x8d/LR\x99e\x16\x13\x8d\"\x02g\x89\x04\x00.D\xfd\xa7\xd4\x00\x00\u07d4\x93%\x82U\xb3|\u007fX\xf4\xb1\x06s\xa92\xdd:\xfd\x90\xf4\xf2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x93(\xd5\\\xcb?\xceS\x1f\x19\x93\x823\x9f\x0eWn\xe8@\xa3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x93)\xff\xdc&\x8b\xab\u0788t\xb3f@l\x81D[\x9b-5\x89\x16\xe6/\x8cs\f\xa1\x80\x00\u07d4\x93+\x9c\x04\xd4\r*\xc80\x83\xd9B\x98\x16\x9d\xae\x81\xab.\u0409lk\x93[\x8b\xbd@\x00\x00\u07d4\x9346\xc8G&U\xf6L:\xfa\xaf|Lb\x1c\x83\xa6+8\x8965\u026d\xc5\u07a0\x00\x00\u0794\x93;\xf3?\x82\x99p+:\x90&B\xc3>\v\xfa\xea\\\x1c\xa3\x88\xd2\xf1?w\x89\xf0\x00\x00\u07d4\x93@4\\\xa6\xa3\uaf77sc\xf2X`C\xf2\x948\xce\v\x89\x1c\xc8\x05\xda\r\xff\xf1\x00\x00\xe0\x94\x93@\xb5\xf6x\xe4^\xe0^\xb7\b\xbbz\xbbn\xc8\xf0\x8f\x1bk\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x93J\xf2\x1b~\xbf\xa4g\xe2\xce\xd6Z\xa3N\xdd:\x0e\xc7\x132\x8a\a\x80\x1f>\x80\xcc\x0f\xf0\x00\x00\xe0\x94\x93PiDJj\x98M\xe2\bNFi*\xb9\x9fg\x1f\xc7'\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\xe0\x94\x93P~\x9e\x81\x19\xcb\xce\u068a\xb0\x87\xe7\xec\xb0q8=i\x81\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\x93g\x8a\x00\x00\xe0\x94\x93m\xcf\x00\x01\x94\xe3\xbf\xf5\n\u0174$:;\xa0\x14\xd6a\u060a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x93o8\x13\xf5\xf6\xa1;\x8eO\xfe\xc8?\xe7\xf8&\x18jq\u0349\x1c0s\x1c\xec\x03 \x00\x00\u07d4\x93t\x86\x9dJ\x99\x11\xee\x1e\xafU\x8b\xc4\u00b6>\xc6:\xcf\u074965\u026d\xc5\u07a0\x00\x00\u07d4\x93uc\u0628\x0f\u05657\xb0\xe6m \xa0%%\xd5\u0606`\x89\x87\x86x2n\xac\x90\x00\x00\u07d4\x93v\xdc\xe2\xaf.\xc8\xdc\xdat\x1b~sEfF\x81\xd96h\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x93\x86\x8d\xdb*yM\x02\xeb\xda/\xa4\x80|v\xe3`\x98X\u0709m\xee\x15\xfc|$\xa7\x80\x00\xe0\x94\x93\x9cC\x13\xd2(\x0e\xdf^\a\x1b\xce\xd8F\x06?\n\x97]T\x8a\x19i6\x89t\xc0[\x00\x00\x00\xe0\x94\x93\xa6\xb3\xabB0\x10\xf9\x81\xa7H\x9dJ\xad%\xe2b\\WA\x8a\x04F\x80\xfej\x1e\xdeN\x80\x00\u07d4\x93\xaa\x8f\x92\xeb\xff\xf9\x91\xfc\x05^\x90ne\x1a\xc7h\xd3+\u02092\xf5\x1e\u06ea\xa30\x00\x00\u07d4\x93\xb4\xbf?\xdf\xf6\xde?NV\xbamw\x99\xdcK\x93\xa6T\x8f\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4\x93\xbc}\x9aJ\xbdD\u023b\xb8\xfe\x8b\xa8\x04\xc6\x1a\xd8\xd6Wl\x89\xd8\xd6\x11\x9a\x81F\x05\x00\x00\u07d4\x93\xc2\xe6N]\xe5X\x9e\xd2P\x06\xe8C\x19n\xe9\xb1\xcf\v>\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\x93\u020e-\x88b\x1e0\xf5\x8a\x95\x86\xbe\xd4\t\x89\x99\xebg\u074a\x06\x9bZ\xfa\xc7P\xbb\x80\x00\x00\u07d4\x93\xe0\xf3~\xcd\xfb\x00\x86\xe3\xe8b\xa9p4D{\x1eM\xec\x1a\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\xe0\x94\x93\xe3\x03A\x1a\xfa\xf6\xc1\a\xa4A\x01\u026c[6\xe9\xd6S\x8b\x8a\r\xf9\xdd\xfe\xcd\x03e@\x00\x00\u07d4\x93\xf1\x8c\xd2R`@v\x14\x88\xc5\x13\x17M\x1eycv\x8b,\x89\x82\xff\xac\x9a\u0553r\x00\x00\u07d4\x94\x0fqQ@P\x9f\xfa\xbf\x97EF\xfa\xb3\x90\"\xa4\x19R\u0489K\xe4\xe7&{j\xe0\x00\x00\u07d4\x94,k\x8c\x95[\xc0\u0608\x12g\x8a#g%\xb3'9\xd9G\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\x94=7\x86JJS}5\xc8\u0657#\xcdd\x06\xce%b\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94C\x9c\xa9\xcc\x16\x9ay\u0520\x9c\xae^gvJo\x87\x1a!\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x94D\x9c\x01\xb3*\u007f\xa5Z\xf8\x10OB\xcd\xd8D\xaa\x8c\xbc@\x8a\x03\x81\x11\xa1\xf4\xf0<\x10\x00\x00\xe0\x94\x94E\xba\\0\xe9\x89a\xb8`$a\xd08]@\xfb\xd8\x03\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x94O\a\xb9o\x90\xc5\xf0\xd7\xc0\u0140S1I\xf3\xf5\x85\xa0x\x89\x04\x02\xf4\xcf\xeeb\xe8\x00\x00\u07d4\x94T\xb3\xa8\xbf\xf9p\x9f\xd0\u1407~l\xb6\u0219t\xdb\u0589\x90\xf54`\x8ar\x88\x00\x00\u07d4\x94]\x96\xeaW>\x8d\xf7&+\xbf\xa5r\"\x9bK\x16\x01k\x0f\x89\vX\x9e\xf9\x14\xc1B\x00\x00\u07d4\x94^\x18v\x9d~\xe7'\xc7\x01?\x92\xde$\xd1\x17\x96\u007f\xf3\x17\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94a'\x81\x03;W\xb1F\xeet\xe7S\xc6r\x01\u007fS\x85\xe4\x89\xc3(\t>a\xee@\x00\x00\xe0\x94\x94dJ\xd1\x16\xa4\x1c\xe2\xca\u007f\xbe\xc6\t\xbd\xefs\x8a*\xc7\u01ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x94p\xcc6YE\x86\x82\x18!\xc5\u0256\xb6\xed\xc8;mZ2\x89\x01M\x11 \u05f1`\x00\x00\xe0\x94\x94u\xc5\x10\xec\x9a&\x97\x92GtL=\x8c;\x0e\v_D\u04ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x94~\x11\xe5\xea)\ro\u00f3\x80H\x97\x9e\f\xd4N\xc7\xc1\u007f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94\x83\u064f\x14\xa3?\xdc\x11\x8d@9U\u00995\xed\xfc_p\x89\x18\xea;4\xefQ\x88\x00\x00\u07d4\x94\x911\xf2\x89C\x92\\\xfc\x97\xd4\x1e\f\xea\v&)s\xa70\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\x94\x9f\x84\xf0\xb1\xd7\u0127\xcfI\xee\u007f\x8b,J\x13M\xe3(x\x89%\"H\u07b6\xe6\x94\x00\x00\u07d4\x94\x9f\x8c\x10{\xc7\xf0\xac\xea\xa0\xf1pR\xaa\xdb\xd2\xf9s+.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x94\xa7\u0368\xf4\x81\xf9\u061dB\xc3\x03\xae\x162\xb3\xb7\t\xdb\x1d\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x94\xa9\xa7\x16\x911| d'\x1bQ\xc95?\xbd\xed5\x01\xa8\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x94\xadK\xad\x82K\xd0\ub7a4\x9cX\u03bc\xc0\xff^\b4k\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\x94\xbb\xc6}\x13\xf8\x9e\xbc\xa5\x94\xbe\x94\xbcQp\x92\f0\xd9\xf3\x89\x04X\xff\xa3\x15\nT\x00\x00\u07d4\x94\xbe:\xe5Ob\xd6c\xb0\xd4\u031e\x1e\xa8\xfe\x95V\ua7bf\x89\x01C\x13,\xa8C\x18\x00\x00\xe0\x94\x94\xc0U\xe8X5z\xaa0\xcf A\xfa\x90Y\xce\x16J\x1f\x91\x8a\x04<%\xe0\xdc\xc1\xbd\x1c\x00\x00\xe0\x94\x94\xc7B\xfdz\x8by\x06\xb3\xbf\xe4\xf8\x90O\xc0\xbe\\v\x803\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x94\xcaV\xdew\u007f\xd4S\x17\u007f^\x06\x94\xc4x\xe6j\xff\x8a\x84\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x94\xd8\x10t\xdbZ\xe1\x97\u04bb\x13s\xab\x80\xa8}\x12\x1cK\u04ca\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x94\u06c0xs\x86\n\xac=Z\xea\x1e\x88^R\xbf\xf2\x86\x99T\x89\xae\x8ez\v\xb5u\xd0\x00\x00\u07d4\x94\xe1\xf5\u02db\x8a\xba\xce\x03\xa1\xa6B\x82VU;i\f#U\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x94\xef\x8b\xe4Pw\xc7\xd4\xc5e'@\u0794jbbOq?\x89\x05l\xf5Y:\x18\xf8\x80\x00\u07d4\x94\xf1?\x9f\b6\xa3\xee$7\xa8I\"\u0498M\xc0\xf7\xd5;\x89\xa2\xa02\x9b\u00ca\xbe\x00\x00\u07d4\x94\xf8\xf0W\xdb~`\xe6u\xad\x94\x0f\x15X\x85\u0464w4\x8e\x89\x15\xbeat\xe1\x91.\x00\x00\xe0\x94\x94\xfc\u03ad\xfe\\\x10\x9c^\xae\xafF-C\x871B\u020e\"\x8a\x01\x045a\xa8\x82\x93\x00\x00\x00\u07d4\x95\x03N\x16!\x86Q7\xcdG9\xb3F\xdc\x17\xda:'\xc3N\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\x95\fh\xa4\t\x88\x15M#\x93\xff\xf8\xda|\u0369\x96\x14\xf7,\x89\xf9AF\xfd\x8d\xcd\xe5\x80\x00\xe0\x94\x95\x0f\xe9\xc6\xca\xd5\f\x18\xf1\x1a\x9e\xd9\xc4W@\xa6\x18\x06\x12\u040a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x95!\x83\xcf\u04ce5.W\x9d6\xde\xce\u0171\x84P\xf7\xfb\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95'\x8b\b\xde\xe7\xc0\xf2\xc8\xc0\xf7\"\xf9\xfc\xbb\xb9\xa5$\x1f\u0689\x82\x93\t\xf6O\r\xb0\x00\x00\u07d4\x95,W\xd2\xfb\x19Q\a\xd4\xcd\\\xa3\x00wA\x19\u07ed/x\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x955r\xf0\xeam\xf9\xb1\x97\xca\xe4\x0eK\x8e\xcc\x05lCq\u014965\u026d\xc5\u07a0\x00\x00\u07d4\x95>\xf6R\xe7\xb7i\xf5=nxjX\x95/\xa9>\xe6\xab\u725b\ny\x1f\x12\x110\x00\x00\u07d4\x95DpF1;/:^\x19\xb9H\xfd;\x8b\xed\xc8,q|\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x95]\xb3\xb7C`\xb9\xa2hg~s\u03a8!f\x8a\xf6\xfa\u038a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\x95`\xe8\xacg\x18\xa6\xa1\xcd\xcf\xf1\x89\xd6\x03\xc9\x06>A=\xa6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x95g\xa0\u0781\x1d\xe6\xff\t[~\xe6N\u007f\x1b\x83\xc2a[\x80\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\x95h\x1c\xda\xe6\x9b I\xce\x10\x1e2\\u\x98\x92\xca\xc3\xf8\x11\x89\x9a\xe9*\x9b\xc9L@\x00\x00\xe0\x94\x95h\xb7\xdeuV(\xaf5\x9a\x84T=\xe25\x04\xe1^A\xe6\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x95i\xc6:\x92\x84\xa8\x05bm\xb3\xa3.\x9d#c\x93GaQ\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x95\x80\x9e\x8d\xa3\xfb\xe4\xb7\xf2\x81\xf0\xb8\xb1q_B\x0f}}c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95\x9fW\xfd\xedj\xe3y\x13\xd9\x00\xb8\x1e_H\xa7\x93\"\xc6'\x89\r\xdb&\x10GI\x11\x80\x00\u07d4\x95\x9f\xf1\u007f\x1dQ\xb4s\xb4@\x10\x05'U\xa7\xfa\x8cu\xbdT\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x95\xa5w\xdc.\xb3\xael\xb9\xdf\xc7z\xf6\x97\xd7\xef\xdf\xe8\x9a\x01\x89\a_a\x0fp\xed \x00\x00\u07d4\x95\xcbm\x8acy\xf9J\xba\x8b\x88ViV,MD\x8eV\xa7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x95\xd5PB{ZQLu\x1ds\xa0\xf6\u049f\xb6]\"\xed\x10\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x95\u064d\f\x10i\x90\x8f\x06zR\xac\xac+\x8bSM\xa3z\xfd\x89oY\xb60\xa9)p\x80\x00\xe0\x94\x95\xdfN4E\xd7f&$\u010e\xbat\u03de\nS\xe9\xf72\x8a\v\xdb\xc4\x1e\x03H\xb3\x00\x00\x00\u07d4\x95\xe6\xa5K-_g\xa2JHu\xafu\x10|\xa7\xea\x9f\xd2\xfa\x89Hz\x9a0E9D\x00\x00\xe0\x94\x95\xe6\xf9=\xac\"\x8b\xc7XZ%sZ\xc2\xd0v\xcc:@\x17\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x95\xe7ad$\xcd\ta\xa7\x17'$t7\xf0\x06\x92r(\x0e\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x95\xe8\n\x82\xc2\f\xbe= `$,\xb9-sX\x10\xd04\xa2\x89\x01\xc3.F?\u0539\x80\x00\u07d4\x95\xf6-\x02C\xed\xe6\x1d\xad\x9a1e\xf59\x05'\rT\xe2B\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\x95\xfbZ\xfb\x14\xc1\uf6b7\xd1y\xc5\xc3\x00P?\xd6j^\xe2\x89\x01\xda\xf7\xa0+\r\xbe\x80\x00\u07d4\x96\x10Y\"\x02\u0082\xab\x9b\u0628\x84Q\x8b>\v\xd4u\x817\x89\x0e\x87?D\x13<\xb0\x00\x00\xe0\x94\x96\x1cY\xad\xc7E\x05\u0446M\x1e\xcf\u02ca\xfa\x04\x12Y<\x93\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\x96,\r\xec\x8a=FK\xf3\x9b\x12\x15\xea\xfd&H\n\xe4\x90\u0349l\x82\xe3\xea\xa5\x13\xe8\x00\x00\u07d4\x96,\xd2*\x8e\xdf\x1eONU\xb4\xb1]\xdb\xfb]\x9dT\x19q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x963K\xfe\x04\xff\xfaY\x02\x13\xea\xb3e\x14\xf38\xb8d\xb76\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x967\xdc\x12r=\x9cxX\x85B\uac02fO?\x03\x8d\x9d\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x96N\xabK'kL\u0618>\x15\xcar\xb1\x06\x90\x0f\xe4\x1f\u0389\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x96b\xee\x02\x19&h+1\xc5\xf2\x00\xceEz\xbe\xa7ll\xe9\x89$Y\x0e\x85\x89\xebj\x00\x00\xe0\x94\x96l\x04x\x1c\xb5\xe6}\xde25\xd7\xf8b\x0e\x1a\xb6c\xa9\xa5\x8a\x10\r P\xdacQ`\x00\x00\u07d4\x96pv\xa8w\xb1\x8e\xc1ZA[\xb1\x16\xf0n\xf3&E\u06e3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96{\xfa\xf7bC\u0379@\t\xae<\x8d5\x05\xe9\xc0\x80EK\xe0\xe8\x19\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x96\x92A\x91\xb7\xdfe[3\x19\xdcma7\xf4\x81\xa7:\x0f\xf3\x89\xd9\xec\xb4\xfd \x8eP\x00\x00\u07d4\x96\x96\x05!83\x8cr/\x11@\x81\\\xf7t\x9d\r;:t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x96\xa5_\x00\xdf\xf4\x05\xdcM\xe5\xe5\x8cW\xf6\xf6\xf0\xca\xc5]/\x89jf\x167\x9c\x87\xb5\x80\x00\u07d4\x96\xaaW?\xed/#4\x10\u06eeQ\x80\x14[#\xc3\x1a\x02\xf0\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x96\xadW\x9b\xbf\xa8\u06ce\xbe\xc9\u0486\xa7.Fa\xee\xd8\xe3V\x89:\v\xa4+\xeca\x83\x00\x00\u07d4\x96\xb44\xfe\x06W\xe4*\u0302\x12\xb6\x86Q9\xde\xde\x15\x97\x9c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x96\xb9\x06\xear\x9fFU\xaf\xe3\xe5}5'|\x96}\xfa\x15w\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x96\xd6-\xfdF\b\u007fb@\x9d\x93\xdd`a\x88\xe7\x0e8\x12W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96\xd9\u0328\xf5^\xea\x00@\xecn\xb3H\xa1wK\x95\xd9>\xf4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x96\xe7\xc0\xc9\u057f\x10\x82\x1b\xf1@\xc5X\xa1E\xb7\xca\xc2\x13\x97\x899>\xf1\xa5\x12|\x80\x00\x00\u07d4\x96\xeaj\u021a+\xac\x954{Q\u06e6=\x8b\xd5\xeb\xde\xdc\xe1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x96\xea\xfb\xf2\xfboM\xb9\xa46\xa7LE\xb5eDR\xe28\x19\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x96\xebR>\x83/P\n\x01}\xe1>\xc2\u007f]6lV\x0e\xff\x89\x10\xac\u03baC\xee(\x00\x00\u07d4\x96\xf0F*\xe6\xf8\xb9`\x88\xf7\xe9\u018ct\xb9\u062d4\xb3G\x89a\t=|,m8\x00\x00\u07d4\x96\xf8 P\vp\xf4\xa3\xe3#\x9da\x9c\xff\x8f\" u\xb15\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x96\xfeY\xc3\u06f3\xaa|\xc8\xcbbH\fe\xe5nb\x04\xa7\xe2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x96\xffoP\x99h\xf3l\xb4,\xbaH\xdb2\xf2\x1fVv\xab\xf8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x97\t8R*\xfb^\x8f\x99Hs\xc9\xfb\xdc&\xe3\xb3~1L\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x97\n\xbdS\xa5O\xcaJd) |\x18-MW\xbb9\u0520\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97\r\x8b\x8a\x00\x16\xd1C\x05O\x14\x9f\xb3\xb8\xe5P\xdc\a\x97\u01c965\u026d\xc5\u07a0\x00\x00\u07d4\x97,/\x96\xaa\x00\u03ca/ Z\xbc\xf8\x93|\fu\xf5\xd8\u0649\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97?N6\x1f\xe5\xde\u0358\x9dL\x8f}|\xc9y\x908]\xaf\x89\x15\x0f\x85C\xa3\x87B\x00\x00\u07d4\x97M\x05A\xabJG\xec\u007fu6\x9c\x00i\xb6J\x1b\x81w\x10\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u0794\x97M/\x17\x89_)\x02\x04\x9d\xea\xae\xcf\t\xc3\x04e\a@-\x88\xcc\x19\u00947\xab\x80\x00\u07d4\x97R\xd1O^\x10\x93\xf0qq\x1c\x1a\xdb\xc4\xe3\xeb\x1e\\W\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97V\xe1v\xc9\xefi>\xe1\xee\u01b9\xf8\xb1Q\xd3\x13\xbe\xb0\x99\x89A\rXj \xa4\xc0\x00\x00\u07d4\x97_7d\xe9{\xbc\xcfv|\xbd;y[\xa8m\x8b\xa9\x84\x0e\x89\x12\xc1\xb6\xee\xd0=(\x00\x00\xe0\x94\x97j\x18Sj\xf4\x18tBc\b\x87\x1b\xcd\x15\x12\xa7u\xc9\xf8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x97n<\xea\xf3\xf1\xafQ\xf8\u009a\xff]\u007f\xa2\x1f\x03\x86\xd8\xee\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x97w\xcca\xcfuk\xe3\xb3\xc2\f\xd4I\x1ci\xd2u\xe7\xa1 \x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x97\x81\v\xaf\xc3~\x840c2\xaa\xcb5\xe9*\xd9\x11\xd2=$\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x97\x8cC\f\xe45\x9b\x06\xbc,\xdf\\)\x85\xfc\x95\x0eP\xd5\u0209\x1a\x05V\x90\xd9\u06c0\x00\x00\u07d4\x97\x95\xf6C\x19\xfc\x17\xdd\x0f\x82a\xf9\xd2\x06\xfbf\xb6L\xd0\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97\x99\xca!\xdb\xcfi\xbf\xa1\xb3\xf7+\xacQ\xb9\xe3\xcaX|\xf9\x89\\(=A\x03\x94\x10\x00\x00\u07d4\x97\x9c\xbf!\xdf\xec\x8a\xce?\x1c\x19m\x82\u07d6%4\xdf9O\x89\x99\x91\xd4x\xddM\x16\x00\x00\u07d4\x97\x9dh\x1ca}\xa1o!\xbc\xac\xa1\x01\xed\x16\xed\x01Z\xb6\x96\x89e\xea=\xb7UF`\x00\x00\u07d4\x97\x9f0\x15\x8bWK\x99\x9a\xab4\x81\a\xb9\xee\xd8[\x1f\xf8\xc1\x894\x95tD\xb8@\xe8\x00\x00\u07d4\x97\xa8o\x01\xce?|\xfdDA3\x0e\x1c\x9b\x19\xe1\xb1\x06\x06\xef\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x97\xb9\x1e\xfesP\xc2\xd5~~@k\xab\x18\xf3a{\xcd\xe1J\x8a\x02\x1e\x19\x99\xbb\xd5\u04be\x00\x00\u07d4\x97\xd0\xd9r^;p\xe6u\x841s\x93\x8e\xd3q\xb6,\u007f\xac\x89\t79SM(h\x00\x00\u07d4\x97\xd9\xe4jv\x04\u05f5\xa4\xeaN\xe6\x1aB\xb3\xd25\x0f\xc3\xed\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x97\xdc&\xecg\n1\xe0\"\x1d*u\xbc]\xc9\xf9\f\x1fo\u0509\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\x97\xde!\xe4!\xc3\u007f\xe4\xb8\x02_\x9aQ\xb7\xb3\x90\xb5\xdfx\x04\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\x97\xe2\x89s\xb8`\xc5g@(\x00\xfb\xb6<\xe3\x9a\x04\x8a=y\x89\x05B%:\x12l\xe4\x00\x00\u07d4\x97\xe5\xcca'\xc4\xf8\x85\xbe\x02\xf4KB\xd1\u0230\xac\x91\u44c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x97\xf1\xfeL\x80\x83\xe5\x96!*\x18w(\xdd\\\xf8\n1\xbe\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\x97\xf7v\x06W\xc1\xe2\x02u\x90\x86\x96>\xb4!\x1c_\x819\xb9\x8a\n\x8a\t\u007f\xcb=\x17h\x00\x00\xe0\x94\x97\xf9\x9bk\xa3\x13F\u0358\xa9\xfeL0\x8f\x87\u0165\x8cQQ\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x98\n\x84\xb6\x86\xfc1\xbd\xc8<\"\x10XTjq\xb1\x1f\x83\x8a\x89*AUH\xaf\x86\x81\x80\x00\u07d4\x98\x10\xe3J\x94\xdbn\xd1V\xd08\x9a\x0e+\x80\xf4\xfdk\n\x8a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\x1d\xdf\x04\x04\xe4\xd2-\xdaUj\a&\xf0\v-\x98\xab\x95i\x8965f3\xeb\xd8\xea\x00\x00\xe0\x94\x98\x1fq'u\xc0\xda\xd9u\x18\xff\xed\xcbG\xb9\xad\x1dl'b\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\x984h!\x80\xb9\x82\xd1f\xba\u06dd\x9d\x1d\x9b\xbf\x01m\x87\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x986\xb4\xd3\x04sd\x1a\xb5j\xee\xe1\x92Bv\x1drrQx\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x989sB\xec_=L\xb8w\xe5N\xf5\xd6\xf1\xd3fs\x1b\u050a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\x98Fd\x886\xa3\a\xa0W\x18O\xd5\x1fb\x8a_\x8c\x12B|\x8a\x04\vi\xbfC\xdc\xe8\xf0\x00\x00\xe0\x94\x98Jy\x85\xe3\xcc~\xb5\xc96\x91\xf6\xf8\xcc{\x8f$]\x01\xb2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x98]p\xd2\a\x89+\xed9\x85\x90\x02N$!\xb1\xcc\x11\x93Y\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x98m\xf4~v\xe4\u05e7\x89\xcd\xee\x91<\u0243\x16P\x93l\x9d\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\x98t\x80?\xe1\xf3\xa06^y\"\xb1Bp\xea\xeb\x03,\xc1\xb5\x89<\xf5\x92\x88$\xc6\xc2\x00\x00\u07d4\x98ub4\x95\xa4l\xdb\xf2YS\x0f\xf88\xa1y\x9e\u00c9\x91\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98v\x18\xc8VV |{\xac\x15\a\xc0\xff\xef\xa2\xfbd\xb0\x92\x89\x03}\xfeC1\x89\xe3\x80\x00\u07d4\x98|\x9b\xcdn?9\x90\xa5+\xe3\xed\xa4q\f'Q\x8fOr\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x98\x82\x96|\xeeh\u04a89\xfa\u062bJ|=\xdd\xf6\xc0\xad\u0209Hx\xbe\x1f\xfa\xf9]\x00\x00\u07d4\x98\x85\\}\xfb\xee3SD\x90J\x12\xc4\fs\x17\x95\xb1:T\x899\xfb\xae\x8d\x04-\xd0\x00\x00\u07d4\x98\x9c\f\xcf\xf6T\xda\x03\xae\xb1\x1a\xf7\x01\x05Ea\xd6)~\x1d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x98\xa0\xe5Lm\x9d\u023e\x96'l\xeb\xf4\xfe\xc4`\xf6#]\x85\x89j\u0202\x10\tR\u01c0\x00\u07d4\x98\xb7i\xcc0\\\xec\xfbb\x9a\x00\xc9\a\x06\x9d~\xf9\xbc:\x12\x89\x01h\u048e?\x00(\x00\x00\xe0\x94\x98\xbaN\x9c\xa7/\xdd\xc2\fi\xb49ov\xf8\x18?z*N\x8a\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\x00\u07d4\x98\xbeimQ\xe3\x90\xff\x1cP\x1b\x8a\x0fc1\xb6(\xdd\u016d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\xbe\u04e7.\xcc\xfb\xaf\xb9#H\x92\x93\xe4)\xe7\x03\xc7\xe2[\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x98\xbfJ\xf3\x81\v\x84#\x87\xdbp\xc1MF\t\x96&\x00=\x10\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x98\xc1\x0e\xbf,O\x97\u02e5\xa1\xab?*\xaf\xe1\xca\xc4#\xf8\u02c9\x10CV\x1a\x88)0\x00\x00\u07d4\x98\xc1\x9d\xba\x81\v\xa6\x11\xe6\x8f/\x83\xee\x16\xf6\xe7tO\f\x1f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x98\xc5IJ\x03\xac\x91\xa7h\xdf\xfc\x0e\xa1\xdd\u0b3f\x88\x90\x19\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\x98\xd2\x04\xf9\b_\x8c\x8e}\xe2>X\x9bd\xc6\xef\xf6\x92\xccc\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x98\xd3s\x19\x92\xd1\xd4\x0e\x12\x11\xc7\xf75\xf2\x18\x9a\xfa\a\x02\xe0\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x98\xe2\xb6\xd6\x06\xfd-i\x91\xc9\xd6\xd4\a\u007f\xdf?\xddE\x85\u06890\xdf\x1ao\x8a\xd6(\x00\x00\u07d4\x98\xe3\xe9\v(\xfc\xca\ue087y\xb8\xd4\nUh\xc4\x11n!\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\x98\xe6\xf5G\u06c8\xe7_\x1f\x9c\x8a\xc2\xc5\xcf\x16'\xbaX\v>\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x98\xf4\xaf:\xf0\xae\xde_\xaf\xdcB\xa0\x81\xec\xc1\xf8\x9e<\xcf \x8a\x01\xfd\x934\x94\xaa_\xe0\x00\x00\u07d4\x98\xf6\xb8\xe6!=\xbc\x9aU\x81\xf4\xcc\xe6e_\x95%+\xdb\a\x89\x11Xr\xb0\xbc\xa40\x00\x00\u07d4\x99\te\r\u05719{\x8b\x8b\x0e\xb6\x94\x99\xb2\x91\xb0\xad\x12\x13\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x99\x11s`\x19G\xc2\bJb\xd69R~\x96\x15\x12W\x9a\xf9\x89 \x86\xac5\x10R`\x00\x00\u07d4\x99\x12\x9d[<\f\xdeG\xea\r\xefM\xfc\a\r\x1fJY\x95'\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x99\x17\u058dJ\xf3A\xd6Q\xe7\xf0\a\\m\xe6\xd7\x14Nt\t\x8a\x012\xd4Gl\b\xe6\xf0\x00\x00\u07d4\x99\x1a\xc7\xcap\x97\x11_& ^\xee\x0e\xf7\xd4\x1e\xb4\xe3\x11\xae\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\x99#e\xd7d\xc5\xce5@9\xdd\xfc\x91.\x02:u\xb8\xe1h\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x99&F\xac\x1a\u02ab\xf5\u076b\xa8\xf9B\x9a\xa6\xa9Nt\x96\xa7\x8967Pz0\xab\xeb\x00\x00\u07d4\x99&\x83'\xc3s3.\x06\xc3\xf6\x16B\x87\xd4U\xb9\xd5\xfaK\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99(\xffqZ\xfc:+`\xf8\xebL\u013aN\xe8\u06b6\u5749\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4\x992\xef\x1c\x85\xb7Z\x9b*\x80\x05}P\x874\xc5\x10\x85\xbe\u0309\x02\xb8?\xa50\x1dY\x00\x00\xe0\x94\x99?\x14ax`^f\xd5\x17\xbex.\xf0\xb3\xc6\x1aN\x19%\x8a\x01|\x1f\x055\u05e5\x83\x00\x00\xe0\x94\x99A7\x04\xb1\xa3.p\xf3\xbc\ri\u0748\x1c8VkT\u02ca\x05\xcckiF1\xf7\x12\x00\x00\u07d4\x99AR\xfc\x95\xd5\xc1\u028b\x88\x11:\xbb\xadMq\x0e@\xde\xf6\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x99D\xfe\xe9\xd3JJ\x88\x00#\u01c92\xc0\vY\xd5\xc8*\x82\x89(\xa8\xa5k6\x90\a\x00\x00\u07d4\x99L\u00b5\"~\xc3\xcf\x04\x85\x12F|A\xb7\xb7\xb7H\x90\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99q\xdf`\xf0\xaef\xdc\xe9\xe8\xc8N\x17\x14\x9f\t\xf9\xc5/d\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x99v\x94~\xff_j\xe5\xda\b\xddT\x11\x92\xf3x\xb4(\xff\x94\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x99}e\x92\xa3\x15\x89\xac\xc3\x1b\x99\x01\xfb\xeb<\xc3\xd6[2\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\x82\xa5\x89\x0f\xfbT\x06\u04ec\xa8\u04bf\xc1\xddp\xaa\xa8\n\xe0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\x87\x8f\x9dn\n~\u066e\u01c2\x97\xb78y\xa8\x01\x95\xaf\xe0\x89\xd7\xc1\x98q\x0ef\xb0\x00\x00\u07d4\x99\x8c\x1f\x93\xbc\xdbo\xf2<\x10\xd0\u0712G(\xb7;\xe2\xff\x9f\x896[\xf3\xa43\xea\xf3\x00\x00\u07d4\x99\x91aL[\xaaG\xddl\x96\x87FE\xf9z\xdd,=\x83\x80\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x99\x92J\x98\x16\xbb}\xdf?\xec\x18D\x82\x8e\x9a\xd7\xd0k\xf4\xe6\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\x99\x99vh\xf7\xc1\xa4\xff\x9e1\xf9\x97z\xe3\"K\u02c8z\x85\x89\x0f\xc969(\x01\xc0\x00\x00\u07d4\x99\x9cI\xc1t\xca\x13\xbc\x83l\x1e\n\x92\xbf\xf4\x8b'\x15C\u0289\xb1\xcf$\xdd\u0431@\x00\x00\u07d4\x99\xa4\xde\x19\xde\u05d0\b\xcf\xdc\xd4]\x01M.XK\x89\x14\xa8\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\x99\xa9k\xf2$.\xa1\xb3\x9e\xceo\xcc\r\x18\xae\xd0\f\x01y\xf3\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x99\xb0\x18\x93+\xca\xd3U\xb6y+%]\xb6p-\xec\x8c\xe5\u0749\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\x99\xb7C\xd1\xd9\xef\xf9\r\x9a\x194\xb4\xdb!\xd5\x19\u061bJ8\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x99\xb8\xc8$\x86\x9d\xe9\xed$\xf3\xbf\xf6\x85L\xb6\xddE\xcc?\x9f\x89e\xea=\xb7UF`\x00\x00\u07d4\x99\xc0\x17L\xf8N\a\x83\xc2 \xb4\xebj\xe1\x8f\xe7\x03\x85J\u04c9py\xa2W=\fx\x00\x00\u07d4\x99\xc1\xd9\xf4\fj\xb7\xf8\xa9/\xce/\xdc\xe4zT\xa5\x86\xc5?\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x99\xc26\x14\x1d\xae\xc87\xec\xe0O\xda\xee\x1d\x90\u03cb\xbd\xc1\x04\x89ve\x16\xac\xac\r \x00\x00\u07d4\x99\xc3\x1f\xe7HX7\x87\xcd\xd3\xe5%\xb2\x81\xb2\x18\x96\x179\xe3\x897\b\xba\xed=h\x90\x00\x00\u07d4\x99\xc4u\xbf\x02\xe8\xb9!J\xda_\xad\x02\xfd\xfd\x15\xba6\\\f\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\x99\u0203%\x85F\xcc~N\x97\x1fR.8\x99\x18\xda^\xa6:\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x99\xc9\xf9>E\xfe<\x14\x18\xc3S\xe4\u016c8\x94\xee\xf8\x12\x1e\x89\x05\x85\xba\xf1E\x05\v\x00\x00\xe0\x94\x99\xd1W\x9c\xd4&\x82\xb7dN\x1dOq(D\x1e\xef\xfe3\x9d\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\x99\u0475\x85\x96_@jB\xa4\x9a\x1c\xa7\x0fv\x9evZ?\x98\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\x99\xdf\xd0PL\x06\xc7C\xe4e4\xfd{U\xf1\xf9\xc7\xec3)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\xf4\x14|\xcck\u02c0\u0304.i\xf6\xd0\x0e0\xfaA3\u0649\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\x99\xf7\u007f\x99\x8b \xe0\xbc\xdc\xd9\xfc\x83\x86ARl\xf2Y\x18\xef\x89a\t=|,m8\x00\x00\u07d4\x99\xfa\xd5\x008\xd0\xd9\xd4\xc3\xfb\xb4\xbc\xe0V\x06\xec\xad\xcdQ!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x99\xfe\r \x12(\xa7S\x14VU\xd4(\xeb\x9f\xd9I\x85\xd3m\x89i \xbf\xf3QZ:\x00\x00\u07d4\x9a\a\x9c\x92\xa6)\xca\x15\xc8\xca\xfa.\xb2\x8d[\xc1z\xf8(\x11\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9a\r<\xee=\x98\x92\xea;7\x00\xa2\u007f\xf8A@\xd9\x02T\x93\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x9a$\u038dH\\\xc4\xc8nI\u07b3\x90\"\xf9,t0\xe6~\x89Fy\x1f\xc8N\a\xd0\x00\x00\u07d4\x9a,\xe4;]\x89\u0593k\x8e\x8c5G\x91\xb8\xaf\xff\x96$%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9a9\x01bS^9\x88w\xe4\x16x}b9\xe0uN\x93|\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9a=\xa6P#\xa10 \xd2!E\xcf\xc1\x8b\xab\x10\xbd\x19\xceN\x89\x18\xbfn\xa3FJ:\x00\x00\xe0\x94\x9a>+\x1b\xf3F\xdd\a\v\x02sW\xfe\xacD\xa4\xb2\xc9}\xb8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9aL\xa8\xb8!\x17\x89NC\xdbr\xb9\xfax\xf0\xb9\xb9:\xce\t\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x9aR.R\xc1\x95\xbf\xb7\xcf_\xfa\xae\u06d1\xa3\xbath\x16\x1d\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9aZ\xf3\x1c~\x063\x9a\u0234b\x8d|M\xb0\xce\x0fE\u0224\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\x9ac?\xcd\x11,\xce\xebv_\xe0A\x81ps*\x97\x05\u7708\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x9ac\u0445\xa7\x91)\xfd\xab\x19\xb5\x8b\xb61\xea6\xa4 TN\x89\x02F\xdd\xf9yvh\x00\x00\u07d4\x9ag\b\u0778\x90<(\x9f\x83\xfe\x88\x9c\x1e\xdc\xd6\x1f\x85D#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9ao\xf5\xf6\xa7\xaf{z\xe0\xed\x9c \xec\xecP#\u0481\xb7\x86\x89\x8a\x12\xb9\xbdjg\xec\x00\x00\xe0\x94\x9a\x82\x82m<)H\x1d\xcc+\u0495\x00G\xe8\xb6\x04\x86\xc38\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9a\x8e\xcaA\x89\xffJ\xa8\xff~\u0536\xb7\x03\x9f\t\x02!\x9b\x15\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9a\x95;[\xccp\x93y\xfc\xb5Y\u05f9\x16\xaf\u06a5\f\xad\u0309\x05k\xc7^-c\x10\x00\x00\u07d4\x9a\x99\v\x8a\xebX\x8d~\xe7\xec.\xd8\xc2\xe6Os\x82\xa9\xfe\xe2\x89\x01\xd1'\xdbi\xfd\x8b\x00\x00\u07d4\x9a\x9d\x1d\xc0\xba\xa7}n \xc3\xd8I\u01c8b\xdd\x1c\x05L\x87\x89/\xb4t\t\x8fg\xc0\x00\x00\xe0\x94\x9a\xa4\x8cf\xe4\xfbJ\u0419\x93N2\x02.\x82t'\xf2w\xba\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9a\xa80\x8fB\x91\x0eZ\xde\t\xc1\xa5\xe2\x82\xd6\xd9\x17\x10\xbd\xbf\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9a\xaa\xfa\x00gd~\u0659\x06kzL\xa5\xb4\xb3\xf3\xfe\xaao\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9a\xb9\x88\xb5\x05\xcf\xee\x1d\xbe\x9c\u044e\x9bTs\xb9\xa2\xd4\xf56\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\x9a\xb9\x8dm\xbb\x1e\xaa\xe1mE\xa0EhT\x1a\xd3\xd8\xfe\x06\u0309\x0e\xc5\x04d\xfe#\xf3\x80\x00\xe0\x94\x9a\xba+^'\xffx\xba\xaa\xb5\xcd\u0248\xb7\xbe\x85\\\xeb\xbd\u038a\x02\x1e\f\x00\x13\a\n\xdc\x00\x00\u07d4\x9a\xc4\xdaQ\xd2x\"\xd1\xe2\b\xc9n\xa6J\x1e[U)\x97#\x89\x05lUy\xf7\"\x14\x00\x00\u0794\x9a\xc8S\x97y*i\u05cf(k\x86C*\a\xae\u03b6\x0ed\x88\xc6s\xce<@\x16\x00\x00\xe0\x94\x9a\xc9\a\xee\x85\xe6\xf3\xe2#E\x99\x92\xe2V\xa4?\xa0\x8f\xa8\xb2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9a\xd4\u007f\xdc\xf9\u0354-(\xef\xfd[\x84\x11[1\xa6X\xa1>\x89\xb2Y\xec\x00\xd5;(\x00\x00\u07d4\x9a\xdb\u04fc{\n\xfc\x05\xd1\xd2\xed\xa4\x9f\xf8c\x93\x9cH\xdbF\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x9a\xdfE\x8b\xff5\x99\xee\xe1\xa2c\x98\x85\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\x9a\xf9\xdb\xe4t\"\xd1w\xf9E\xbd\xea\xd7\xe6\xd8)05b0\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x9a\xfaSkLf\xbc8\xd8u\u0133\x00\x99\xd9&\x1f\xdb8\xeb\x89\v*\x8f\x84*w\xbc\x80\x00\u07d4\x9b\x06\xad\x84\x1d\xff\xbeL\xcfF\xf1\x03\x9f\u00c6\xf3\xc3!Dn\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\x11h\u078a\xb6KGU/3\x89\x80\n\x9c\xc0\x8bFf\u03c9]\u0212\xaa\x111\xc8\x00\x00\u07d4\x9b\x18\x11\xc3\x05\x1fF\xe6d\xaeK\xc9\xc8$\u0445\x92\xc4WJ\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\x9b\x18G\x86U\xa4\x85\x1c\xc9\x06\xe6`\xfe\xaca\xf7\xf4\u023f\xfc\x89\xe2G\x8d8\x90}\x84\x00\x00\u07d4\x9b\"\xa8\r\\{3t\xa0[D`\x81\xf9}\n4\a\x9e\u007f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x9b+\xe7\xf5gT\xf5\x05\xe3D\x1a\x10\xf7\xf0\xe2\x0f\xd3\xdd\xf8I\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\x9b2\xcfOQ\x15\xf4\xb3J\x00\xa6La}\xe0c\x875C#\x89\x05\xb8\x1e\u0608 |\x80\x00\u07d4\x9bC\u0739_\xde1\x80u\xa5g\xf1\xe6\xb5v\x17\x05^\xf9\xe8\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\x9bDO\xd37\xe5\xd7R\x93\xad\xcf\xffp\xe1\xea\x01\xdb\x022\"\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9bH$\xff\x9f\xb2\xab\xdaUM\xeeO\xb8\xcfT\x91eW\x061\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9bL'\x15x\f\xa4\xe9\x9e`\xeb\xf2\x19\xf1Y\f\x8c\xadP\n\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\x9bY\xeb!;\x1eue\xe4PG\xe0N\xa07O\x10v-\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\\9\xf7\xe0\xac\x16\x8c\x8e\xd0\xed4\x04w\x11}\x1bh.\xe9\x89\x05P\x05\xf0\xc6\x14H\x00\x00\u07d4\x9b^\xc1\x8e\x83\x13\x88}\xf4a\u0490.\x81\xe6z\x8f\x11;\xb1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9bd\xd3\u034d+s\xf6hA\xb5\xc4k\xb6\x95\xb8\x8a\x9a\xb7]\x89\x01 :Ov\f\x16\x80\x00\u07d4\x9be\x8f\xb3a\xe0F\xd4\xfc\xaa\x8a\xefm\x02\xa9\x91\x11\"6%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9bfA\xb1>\x17/\xc0r\xcaK\x83'\xa3\xbc(\xa1[f\xa9\x89\x06\x81U\xa46v\xe0\x00\x00\xe0\x94\x9bh\xf6t\x16\xa6;\xf4E\x1a1\x16L\x92\xf6r\xa6\x87Y\xe9\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\x9bw6i\xe8}v\x01\x8c\t\x0f\x82U\xe5D\t\xb9\u0728\xb2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9bw\xeb\xce\xd7\xe2\x15\xf0\x92\x0e\x8c+\x87\x00$\xf6\xec\xb2\xff1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9b|\x88\x10\xcc|\u021e\x80Nm>8\x12\x18PG(w\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9b\xa5=\xc8\xc9^\x9aG/\xeb\xa2\xc4\xe3,\x1d\xc4\xdd{\xabF\x89Hz\x9a0E9D\x00\x00\xe0\x94\x9b\xac\xd3\xd4\x0f;\x82\xac\x91\xa2d\xd9\u060d\x90\x8e\xac\x86d\xb9\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9b\xb7`\xd5\u0089\xa3\xe1\xdb\x18\xdb\tSE\xcaA;\x9aC\u0089\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\x9b\xb7b\x04\x18j\xf2\xf6;\xe7\x91h`\x16\x87\xfc\x9b\xadf\x1f\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9b\xb9\xb0*&\xbf\xe1\xcc\xc3\xf0\xc6!\x9e&\x1c9\u007f\xc5\xcax\x89Hz\x9a0E9D\x00\x00\u07d4\x9b\xc5s\xbc\xda#\xb8\xb2o\x90s\xd9\f#\x0e\x8eq\xe0'\v\x896/u\xa40]\f\x00\x00\u07d4\x9b\xd7\u00caB\x100JMe>\xde\xff\x1b<\xe4_\xcexC\x89\x0fI\x89A\xe6d(\x00\x00\xe0\x94\x9b\u0600h\xe10u\xf3\xa8\xca\xc4d\xa5\xf9I\xd6\xd8\x18\xc0\xf6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9b\xd9\x05\xf1q\x9f\u01ec\xd0\x15\x9dM\xc1\xf8\xdb/!G#8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9b\xdb\u071b\x9741\xd1<\x89\xa3\xf9u~\x9b;bu\xbf\u01c9\x1b\x1a}\u03caD\u04c0\x00\u07d4\x9b\xe3\xc3)\xb6*(\xb8\xb0\x88l\xbd\x8b\x99\xf8\xbc\x93\f\xe3\xe6\x89\x04\t\xe5+H6\x9a\x00\x00\xe0\x94\x9b\xf5\x8e\xfb\xea\a\x84\xeb\x06\x8a\xde\u03e0\xbb!P\x84\xc7:5\x8a\x01:k+VHq\xa0\x00\x00\u07d4\x9b\xf6r\xd9y\xb3fR\xfcR\x82Tzjk\xc2\x12\xaeCh\x89#\x8f\xd4,\\\xf0@\x00\x00\xe0\x94\x9b\xf7\x03\xb4\x1c6$\xe1_@T\x96#\x90\xbc\xba0R\xf0\xfd\x8a\x01H>\x01S<.<\x00\x00\u07d4\x9b\xf7\x1f\u007f\xb57\xacT\xf4\xe5\x14\x94\u007f\xa7\xffg(\xf1m/\x89\x01\u03c4\xa3\n\n\f\x00\x00\u07d4\x9b\xf9\xb3\xb2\xf2<\xf4a\xebY\x1f(4\v\xc7\x19\x93\x1c\x83d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x9b\xfce\x9c\x9c`\x1e\xa4*k!\xb8\xf1p\x84\xec\x87\xd7\x02\x12\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9b\xff\xf5\r\xb3jxUU\xf0vR\xa1S\xb0\xc4+\x1b\x8bv\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\x05\xe9\xd0\xf0u\x8eyS\x03q~1\xda!<\xa1W\u618965\u026d\xc5\u07a0\x00\x00\u07d4\x9c\x1bw\x1f\t\xaf\x88*\xf0d0\x83\xde*\xa7\x9d\xc0\x97\xc4\x0e\x89\x86p\xe9\xece\x98\xc0\x00\x00\u07d4\x9c(\xa2\xc4\b`\x91\xcb]\xa2&\xa6W\xce2H\xe8\xea{o\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\x9c/\xd5@\x89\xaff]\xf5\x97\x1ds\xb8\x04a`9dsu\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c4@\x98\xbaaZ9\x8f\x11\xd0\t\x90[\x17|D\xa7\xb6\x02\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c=\x06\x92\xce\xee\xf8\n\xa4\x96\\\xee\xd2b\xff\xc7\xf0i\xf2\u0709\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9c@\\\xf6\x97\x95a8\x06^\x11\xc5\xf7U\x9eg$[\u0465\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9cE *%\xf6\xad\x00\x11\xf1\x15\xa5\xa7\"\x04\xf2\xf2\x19\x88f\x8a\x01\x0f\xcf:b\xb0\x80\x98\x00\x00\xe0\x94\x9cI\xde\xffG\b_\xc0\x97\x04\u02a2\u0728\u0087\xa9\xa17\u068a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\x9cK\xbc\xd5\xf1dJo\aX$\xdd\xfe\x85\xc5q\u05ab\xf6\x9c\x89a\x94\x04\x9f0\xf7 \x00\x00\u07d4\x9cRj\x14\x06\x83\xed\xf1C\x1c\xfa\xa1(\xa95\xe2\xb6\x14\u060b\x89\x06\x04o7\xe5\x94\\\x00\x00\xe0\x94\x9cT\xe4\xedG\x9a\x85h)\u01bbB\u069f\vi*u\xf7(\x8a\x01\x97\xa8\xf6\xddU\x19\x80\x00\x00\xe0\x94\x9cX\x1a`\xb6\x10(\xd94\x16y)\xb2-p\xb3\x13\xc3O\u040a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\x9c\\\xc1\x11\t,\x12!\x16\xf1\xa8_N\xe3\x14\bt\x1a}/\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\x9ck\u0264k\x03\xaeT\x04\xf0C\xdf\xcf!\x88>A\x10\xcc3\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9cx\x96?\xbc&<\t\xbdr\xe4\xf8\xde\xf7J\x94u\xf7\x05\\\x8a\x02\ub3b1\xa1r\u0738\x00\x00\u07d4\x9cx\xfb\xb4\xdfv\x9c\xe2\xc1V\x92\f\xfe\xdf\xda\x03:\x0e%J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x9c{m\xc5\x19\x0f\xe2\x91)c\xfc\xd5yh>\xc79Q\x16\xb0\x89*\x11)\u0413g \x00\x00\u07d4\x9c\x80\xbc\x18\xe9\xf8\u0516\x8b\x18]\xa8\u01df\xa6\xe1\x1f\xfc>#\x89\r\x02\xabHl\xed\xc0\x00\x00\xe0\x94\x9c\x98\xfd\xf1\xfd\u034b\xa8\xf4\u0170L:\xe8X~\xfd\xf0\xf6\xe6\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\x9c\x99\xa1\u0691\u0552\v\xc1N\f\xb9\x14\xfd\xf6+\x94\u02c3X\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\x9c\x99\xb6&\x06(\x1b\\\xef\xab\xf3aV\xc8\xfeb\x83\x9e\xf5\xf3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x9c\x9a\a\xa8\xe5|1r\xa9\x19\xefdx\x94tI\x0f\r\x9fQ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9c\x9d\xe4G$\xa4\x05M\xa0\xea\xa6\x05\xab\u0300&hw\x8b\xea\x89\n\xd7\xd5\xca?\xa5\xa2\x00\x00\u07d4\x9c\x9f;\x8a\x81\x1b!\xf3\xff?\xe2\x0f\xe9p\x05\x1c\xe6j\x82O\x89>\xc2\u07bc\a\u053e\x00\x00\xe0\x94\x9c\x9f\x89\xa3\x91\x0fj*\xe8\xa9\x10G\xa1z\xb7\x88\xbd\xde\xc1p\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9c\xa0B\x9f\x87O\x8d\xce\xe2\xe9\xc0b\xa9\x02\n\x84*Xz\xb9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\xa4.\u7838\x98\xf6\xa5\xcc`\xb5\xa5\u05f1\xbf\xa3\xc321\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9c\xb2\x8a\xc1\xa2\n\x10o\u007f76\x92\xc5\xceLs\xf172\xa1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9c\xcd\u0732\xcf\u00b2[\br\x9a\n\x98\xd9\xe6\xf0 .\xa2\xc1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9c\xe2\u007f$^\x02\xd1\xc3\x12\xc1\xd5\x00x\x8c\x9d\xefv\x90E;\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9c\xe56;\x13\xe8#\x8a\xa4\xdd\x15\xac\u0432\xe8\xaf\xe0\x872G\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\x9c\xf2\x92\x8b\xee\xf0\x9a@\xf9\xbf\xc9S\xbe\x06\xa2Q\x11a\x82\xfb\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9d\x06\x91\x97\xd1\xdeP\x04Z\x18o^\xc7D\xac@\u8bd1\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\x9d\x0e}\x92\xfb0XS\u05d8&;\xf1^\x97\xc7+\xf9\xd7\xe0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9d\x0f4~\x82k}\u03aa\xd2y\x06\n5\xc0\x06\x1e\xcf3K\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d u\x17B,\xc0\xd6\r\xe7\xc27\tzMO\xce \x94\f\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\x9d%\n\xe4\xf1\x10\xd7\x1c\xaf\u01f0\xad\xb5.\x8d\x9a\xcbfy\xb8\x8a\x02\x15mn\x99r\x13\xc0\x00\x00\xe0\x94\x9d+\xfc6\x10o\x03\x82P\xc0\x18\x01hW\x85\xb1l\x86\xc6\r\x8aPw\xd7]\xf1\xb6u\x80\x00\x00\xe0\x94\x9d0\xcb#{\xc0\x96\xf1p6\xfc\x80\xdd!\xcah\x99,\xa2\u064a\x06n\xe71\x8f\u070f0\x00\x00\u07d4\x9d2\x96.\xa9\x97\x00\xd92(\xe9\xdb\xda\xd2\xcc7\xbb\x99\xf0~\x89\xb4c+\xed\xd4\xde\xd4\x00\x00\u07d4\x9d4\xda\xc2[\xd1X(\xfa\xef\xaa\xf2\x8fq\aS\xb3\x9e\x89\u0709;\x1cV\xfe\xd0-\xf0\x00\x00\u07d4\x9d6\x91e\xfbp\xb8\x1a:v_\x18\x8f\xd6\f\xbe^{\th\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9d@\xe0\x12\xf6\x04%\xa3@\xd8-\x03\xa1\xc7W\xbf\xab\xc7\x06\xfb\x89\t4o:\xdd\u020d\x80\x00\u07d4\x9dAt\xaaj\xf2\x84v\xe2)\xda\xdbF\x18\b\b\xc6u\x05\xc1\x89B\x1a\xfd\xa4.\u0597\x00\x00\u07d4\x9dB\x133\x9a\x01U\x18avL\x87\xa9<\xe8\xf8_\x87\x95\x9a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9dF\f\x1b7\x9d\xdb\x19\xa8\xc8[LgG\x05\r\xdf\x17\xa8u\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\x9dG\xba[L\x85\x05\xad\x8d\xa4)4(\va\xa0\xe1\xe8\xb9q\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9dM2\x11w%n\xbd\x9a\xfb\xda0A5\xd5\x17\xc3\xdcV\x93\x89!d\xb7\xa0J\u0220\x00\x00\u07d4\x9dO\xf9\x89\xb7\xbe\u066b\x10\x9d\x10\xc8\xc7\xe5_\x02\xd7g4\xad\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\x9dQ\x15C\xb3\xd9\xdc`\xd4\u007f\t\u051d\x01\xb6\u0118\xd8 x\x8a\x02a\x97\xb9Qo\u00d4\x00\x00\u07d4\x9dn\u03e0:\xf2\xc6\xe1D\xb7\xc4i*\x86\x95\x1e\x90.\x9e\x1f\x89\xa2\xa5\xaa`\xad$?\x00\x00\u07d4\x9dvU\xe9\xf3\xe5\xba]n\x87\xe4\x12\xae\xbe\x9e\xe0\u0512G\ue24e\t1\x1c\x1d\x80\xfa\x00\x00\u07d4\x9dx1\xe84\xc2\v\x1b\xaaiz\xf1\xd8\xe0\xc6!\u016f\xff\x9a\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4\x9dx\xa9u\xb7\xdb^M\x8e(\x84\\\xfb\xe7\xe3\x14\x01\xbe\r\u0649H\xa40k\xa2\u5e5c\x8ahX\u02f5,\f\xf75\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\x9d\u007f\xdapp\xbf>\xe9\xbb\u0664\x1fU\xca\u0505J\xe6\xc2,\x8a\x02U\u02e3\xc4o\xcf\x12\x00\x00\u07d4\x9d\x81\xae\xa6\x9a\xedj\xd0p\x89\xd6\x14E4\x8c\x17\xf3K\xfc[\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9d\x91\x1f6\x82\xf3/\xe0y.\x9f\xb6\xff<\xfcG\xf5\x89\xfc\xa5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\x91;]3\x9c\x95\xd8wEV%c\xfe\xa9\x8b#\xc6\f\u0109\tA0,\u007fM#\x00\x00\u07d4\x9d\x93\xfa\xb6\xe2(E\xf8\xf4Z\aIo\x11\xdeqS\r\xeb\u01c9lO\xd1\xee$nx\x00\x00\u07d4\x9d\x99\xb1\x89\xbb\u0664\x8f\xc2\xe1n\x8f\u0363;\xb9\x9a1{\xbb\x89=\x16\xe1\vm\x8b\xb2\x00\x00\u07d4\x9d\x9cN\xfe\x9fC9\x89\xe2;\xe9@I!S)\xfaU\xb4\u02c9\r\u3c89\x03\u01b5\x80\x00\u07d4\x9d\x9eW\xfd\xe3\x0ePh\xc0>I\x84\x8e\xdc\xe3C\xb7\x02\x83X\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\x9d\xa30\"@\xaf\x05\x11\xc6\xfd\x18W\xe6\u07779Ow\xabk\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\x9d\xa4\xec@pw\xf4\xb9p{-\x9d.\xde^\xa5(+\xf1\u07c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\xa6\t\xfa:~l\xf2\xcc\x0ep\u036b\xe7\x8d\xc4\xe3\x82\xe1\x1e\x89A\rXj \xa4\xc0\x00\x00\xe0\x94\x9d\xa6\x1c\xcdb\xbf\x86\x06V\xe02]qW\xe2\xf1`\xd9;\xb5\x8a\x01\x0f\f\xa9V\xf8y\x9e\x00\x00\xe0\x94\x9d\xa6\xe0u\x98\x9ct\x19\tL\xc9\xf6\xd2\u44d3\xbb\x19\x96\x88\x8a\x02Y\xbbq\u056d\xf3\xf0\x00\x00\u07d4\x9d\xa8\xe2,\xa1\x0eg\xfe\xa4NR^GQ\xee\xac6\xa3\x11\x94\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\x9d\xb2\xe1\\\xa6\x81\xf4\xc6`H\xf6\xf9\xb7\x94\x1e\u040b\x1f\xf5\x06\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9d\xc1\x0f\xa3\x8f\x9f\xb0h\x10\xe1\x1f`\x17>\xc3\xd2\xfdju\x1e\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\x9d\xd2\x19f$\xa1\xdd\xf1J\x9d7^_\a\x15+\xaf\"\xaf\xa2\x89A\xb0^$c\xa5C\x80\x00\u07d4\x9d\xd4k\x1cm?\x05\u279co\x03~\xed\x9aYZ\xf4\xa9\xaa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9d\xdd5^cN\xe9\x92~K\u007fl\x97\xe7\xbf:/\x1ehz\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\x9d\xe2\n\xe7j\xa0\x82c\xb2\x05\xd5\x14$a\x96\x1e$\b\xd2f\x89\r\xa93\xd8\xd8\xc6p\x00\x00\u07d4\x9d\xe2\v\xc3~\u007fH\xa8\x0f\xfdz\xd8O\xfb\xf1\xa1\xab\xe1s\x8c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9d\xe78m\xde@\x1c\xe4\xc6{q\xb6U?\x8a\xa3N\xa5\xa1}\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\x9d\xeb9\x02z\xf8w\x99+\x89\xf2\xecJ\x1f\x82.\xcd\xf1&\x93\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9d\xef\xe5j\x0f\xf1\xa1\x94}\xba\t#\xf7\xdd%\x8d\x8f\x12\xfaE\x8a\x05\xb1*\ufbe8\x04\x00\x00\x00\u07d4\x9d\xf0W\xcd\x03\xa4\xe2~\x8e\x03/\x85y\x85\xfd\u007f\x01\xad\xc8\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9d\xf3*P\x1c\vx\x1c\x02\x81\x02/B\xa1)?\xfd{\x89*\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4\x9e\x01vZ\xff\b\xbc\"\x05P\xac\xa5\xea.\x1c\xe8\u5c19#\x8965\u026d\xc5\u07a0\x00\x00\u07d4\x9e \xe5\xfd6\x1e\xab\xcfc\x89\x1f[\x87\xb0\x92h\xb8\xeb7\x93\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9e#,\b\xc1M\xc1\xa6\xed\v\x8a;(h\x97{\xa5\xc1}\x10\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e#\xc5\u4dc2\xb0\n_\xad\U0006eb47\xda\xcf[\x03g\xa1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e59\x90q\xa4\xa1\x01\xe9\x19M\xaa?\t\xf0J\v_\x98p\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9e>\xb5\t'\x8f\xe0\xdc\xd8\xe0\xbb\xe7\x8a\x19N\x06\xb6\x809C\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\x9eBrrQk>g\xd4\xfc\xbf\x82\xf5\x93\x90\xd0L\x8e(\xe5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\x9eL\xec5:\xc3\u3043^<\t\x91\xf8\xfa\xa5\xb7\u0428\xe6\x8a\x02\x1e\x18\xb9\xe9\xabE\xe4\x80\x00\u07d4\x9eX\x11\xb4\v\xe1\xe2\xa1\xe1\u048c;\at\xac\xde\n\t`=\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\x9eZ1\x1d\x9fi\x89\x8a|j\x9dc`h\x048\xe6z{/\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\x9e| P\xa2'\xbb\xfd`\x93~&\x8c\xea>h\xfe\xa8\xd1\xfe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\x9e\u007fe\xa9\x0e\x85\b\x86{\xcc\xc9\x14%j\x1e\xa5t\xcf\a\xe3\x89C8t\xf62\xcc`\x00\x00\xe0\x94\x9e\x81D\xe0\x8e\x89dx\x11\xfekr\xd4E\u05a5\xf8\n\xd2D\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9e\x8fd\xdd\xcd\u9e34Q\xba\xfa\xa25\xa9\xbfQ\x1a%\xac\x91\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\x9e\x95\x1fm\xc5\xe3R\xaf\xb8\xd0B\x99\xd2G\x8aE\x12Y\xbfV\x89\x03\xe7A\x98\x81\xa7:\x00\x00\u07d4\x9e\x96\r\xcd\x03\u057a\x99\xcb\x11]\x17\xffL\t$\x8a\xd4\u043e\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9e\xafj2\x8a@v\x02N\xfakg\xb4\x8b!\xee\xdc\xc0\xf0\xb8\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\x9e\xb1\xffqy\x8f(\xd6\xe9\x89\xfa\x1e\xa0X\x8e'\xba\x86\xcb}\x89\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\x9e\xb2\x81\xc3'\x19\xc4\x0f\xdb>!m\xb0\xf3\u007f\xbcs\xa0&\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\x9e\xb3\xa7\xcb^g&Bz:6\x1c\xfa\x8dad\xdb\u043a\x16\x89+\x95\xbd\xcc9\xb6\x10\x00\x00\u07d4\x9e\xb7\x83N\x17\x1dA\xe0i\xa7yG\xfc\xa8v\"\xf0\xbaNH\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\x9e\xc0>\x02\u51f7v\x9d\xefS\x84\x13\xe9\u007f~U\xbeq\u060a\x04+\xf0kx\xed;P\x00\x00\u07d4\x9e\u02eb\xb0\xb2'\x82\xb3uD)\xe1uz\xab\xa0K\x81\x18\x9f\x89,\xa7\xbb\x06\x1f^\x99\x80\x00\u07d4\x9e\xce\x14\x00\x80\t6\xc7\xc6H_\xcd\xd3b`\x17\u041a\xfb\xf6\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4\x9e\xd4\xe6?ReB\xd4O\xdd\xd3MY\xcd%8\x8f\xfdk\u0689\u049b4\xa4cH\x94\x00\x00\u07d4\x9e\xd8\x0e\xda\u007fU\x05M\xb9\xfbR\x82E\x16\x88\xf2k\xb3t\xc1\x89\x10CV\x1a\x88)0\x00\x00\u07d4\x9e\u0710\xf4\xbe!\be!J\xb5\xb3^Z\x8d\xd7t\x15'\x9d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9e\u07acL\x02k\x93\x05M\u0171\xd6a\fo9`\xf2\xads\x89A\rXj \xa4\xc0\x00\x00\u07d4\x9e\xe9?3\x9eg&\xece\xee\xa4O\x8aK\xfe\x10\xda=2\x82\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\x9e\xe9v\f\xc2s\xd4pj\xa0\x83u\xc3\xe4o\xa20\xaf\xf3\u054a\x01\xe5.3l\xde\"\x18\x00\x00\u07d4\x9e\xeb\a\xbd+x\x90\x19^}F\xbd\xf2\a\x1bf\x17QM\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\x9e\xefD-)\x1aD}t\xc5\xd2S\u011e\xf3$\xea\xc1\xd8\xf0\x89\xb9f\b\xc8\x10;\xf0\x00\x00\u07d4\x9e\xf1\x89k\x00|2\xa1Q\x14\xfb\x89\xd7=\xbdG\xf9\x12+i\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9f\x01w\x06\xb80\xfb\x9c0\ufc20\x9fPk\x91WEu4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x10\xf2\xa0F;e\xae0\xb0p\xb3\xdf\x18\xcfF\xf5\x1e\x89\xbd\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\x9f\x19\xfa\u0223$7\xd8\n\u0183z\v\xb7\x84\x17)\xf4\x97.\x89#=\xf3)\x9far\x00\x00\u07d4\x9f\x1a\xa8\xfc\xfc\x89\xa1\xa52\x8c\xbdcD\xb7\x1f'\x8a,\xa4\xa0\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\x9f!0,\xa5\tk\xeat\x02\xb9\x1b\x0f\xd5\x06%O\x99\x9a=\x89C\x97E\x1a\x00=\xd8\x00\x00\u07d4\x9f'\x1d(U\x00\xd78F\xb1\x8fs>%\u074bO]J\x8b\x89'#\xc3F\xae\x18\b\x00\x00\u07d4\x9f4\x97\xf5\xef_\xe60\x95\x83l\x00N\xb9\xce\x02\xe9\x01;K\x89\"V\x86\x1b\xf9\xcf\b\x00\x00\xe0\x94\x9f:t\xfd^~\xdc\xc1\x16)\x93\x17\x13\x81\u02f62\xb7\xcf\xf0\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\x9fF\xe7\xc1\xe9\a\x8c\xae\x860Z\xc7\x06\v\x01F}f\x85\xee\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\x9fIl\xb2\x06\x95c\x14M\b\x11g{\xa0\xe4q:\nAC\x89<\xd2\xe0\xbfc\xa4H\x00\x00\u07d4\x9fJq\x95\xac|\x15\x1c\xa2X\xca\xfd\xa0\u02b0\x83\xe0I\xc6\x02\x89SS\x8c2\x18\\\xee\x00\x00\u07d4\x9fJ\xc9\xc9\xe7\xe2L\xb2DJ\x04T\xfa[\x9a\xd9\xd9-8S\x89-C\xf3\xeb\xfa\xfb,\x00\x00\u07d4\x9f_D\x02kWjJ\xdbA\xe9YaV\x1dA\x03\x9c\xa3\x91\x89\r\x8drkqw\xa8\x00\x00\u07d4\x9f`{?\x12F\x9fDa!\u03bf4u5kq\xb42\x8c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\x9fa\xbe\xb4o^\x85=\n\x85!\xc7Dnh\xe3L}\ts\x89\x1e[\x8f\xa8\xfe*\xc0\x00\x00\u07d4\x9fd\xa8\xe8\xda\xcfJ\xde0\xd1\x0fMY\xb0\xa3\u056b\xfd\xbft\x8966\x9e\xd7t}&\x00\x00\u07d4\x9ff.\x95'A!\xf1wVncm#\x96L\xf1\xfdho\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9fj2*mF\x99\x81Bj\xe8D\x86]~\xe0\xbb\x15\u01f3\x89\x02\xb5\xeeW\x92\x9f\u06c0\x00\u07d4\x9fy\x86\x92J\xeb\x02h|\xd6A\x89\x18\x9f\xb1g\xde\xd2\xdd\\\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\x9fz\x03\x92\xf8Ws.0\x04\xa3u\xe6\xb1\x06\x8dI\xd801\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x82E\u00eb}\x171d\x86\x1c\u04d9\x1b\x94\xf1\xba@\xa9:\x89\x9b\ny\x1f\x12\x110\x00\x00\u07d4\x9f\x83\xa2\x93\xc3$\xd4\x10l\x18\xfa\xa8\x88\x8fd\u0499\x05L\xa0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\x9f\x86\xa0f\xed\xb6\x1f\xcbXV\u0793\xb7\\\x8cy\x18d\xb9{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\x9f\x98\xeb4\xd4iy\xb0\xa6\u078b\x05\xaaS:\x89\xb8%\xdc\xf1\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\xe0\x94\x9f\x9f\xe0\xc9_\x10\xfe\xe8z\xf1\xaf r6\xc8\xf3aN\xf0/\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\x9f\xae\xa1\xc5\xe8\x1ez\xcb?\x17\xf1\xc3Q\xee.\u0649\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa0\b\x01\x98c\xc1\xa7|\x14\x99\xeb9\xbb\u05ff-\u05e3\x1c\xb9\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xa0\t\xbf\ao\x1b\xa3\xfaW\u04a7!r\x18\xbe\xd5VZzz\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa0\x1e\x94v\u07c4C\x18%\xc86\xe8\x80:\x97\xe2/\xa5\xa0\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\xa0\x1f\x12\xd7\x0fD\xaa{\x11;(\\\"\xdc\xdbE\x874T\xa7\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xa0\x1f\u0450j\x90\x85\x06\xde\xda\xe1\xe2\b\x12\x88r\xb5n\u7489\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa0\"\x82@\xf9\x9e\x1d\xe9\xcb2\xd8,\x0f/\xa9\xa3\xd4K\v\xf3\x89V\xbcu\xe2\xd61\x00\x00\x00\xe0\x94\xa0+\xdedahn\x19\xace\f\x97\r\x06r\xe7m\xcbO\u008a\x01\xe0\x92\x96\xc37\x8d\xe4\x00\x00\u07d4\xa0,\x1e4\x06O\x04u\xf7\xfa\x83\x1c\xcb%\x01L:\xa3\x1c\xa2\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xa0-\u01aa2\x8b\x88\r\u97acTh#\xfc\xcfw@G\xfb\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa0.?\x8fYY\xa7\xaa\xb7A\x86\x12\x12\x9bp\x1c\xa1\xb8\x00\x10\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa04\u007f\n\x98wc\x90\x16\\\x16m2\x96;\xf7M\xcd\n/\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa05\xa3e$x\xf8-\xbdm\x11_\xaa\x8c\xa9F\xec\x9eh\x1d\x89\x05\xf4\xe4-\u052f\xec\x00\x00\u07d4\xa0:=\xc7\xc53\xd1tB\x95\xbe\x95]a\xaf?R\xb5\x1a\xf5\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa0E\x9e\xf3i:\xac\xd1d|\xd5\u0612\x989 L\xefS\xbe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa0O*\xe0*\xdd\x14\xc1/\xafe\xcb%\x90\"\u0403\n\x8e&\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xa0l\xd1\xf3\x969l\ndFFQ\xd7\xc2\x05\xef\xaf8|\xa3\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xa0ri\x1c\x8d\xd7\xcdB7\xffr\xa7\\\x1a\x95\x06\xd0\xce[\x9e\x89\x14\x0e\xc8\x0f\xa7\xee\x88\x00\x00\u07d4\xa0r\u03beb\xa9\xe9\xf6\x1c\xc3\xfb\xf8\x8a\x9e\xfb\xfe>\x9a\x8dp\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa0v\x82\x00\v\x1b\xcf0\x02\xf8\\\x80\xc0\xfa)I\xbd\x1e\x82\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa0z\xa1mt\xae\u8a63(\x8dR\xdb\x15Q\u0553\x882\x97\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa0\x8d![[j\xacHa\xa2\x81\xac~@\vx\xfe\xf0L\xbf\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa0\x95\x19p\xdf\u0403/\xb8;\xda\x12\xc25E\xe7\x90Aul\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa0\x9fM^\xaae\xa2\xf4\xcbu\nI\x924\x01\xda\u5410\xaf\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\xe0\x94\xa0\xa0\xe6R\x04T\x1f\u029b/\xb2\x82\u0355\x13\x8f\xae\x16\xf8\t\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa0\xaa_\x02\x01\xf0M;\xbe\xb8\x98\x13/|\x11g\x94f\xd9\x01\x89\x01\xfb\xedR\x15\xbbL\x00\x00\u07d4\xa0\xaa\xdb\xd9P\x97\"p_m#X\xa5\u01df7\x97\x0f\x00\xf6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa0\xb7q\x95\x1c\xe1\xde\xee6:\xe2\xb7q\xb7>\a\u0135\xe8\x00\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa0\xde\\`\x1eif5\u0198\xb7\xae\x9c\xa4S\x9f\u01f9A\xec\x89\x12\xc3\xcb\xd7\x04\xc9w\x00\x00\u07d4\xa0\xe8\xbaf\x1bH\x15L\xf8C\xd4\u00a5\xc0\xf7\x92\xd5(\xee)\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa0\xfc~S\xc5\xeb\xd2z*\xbd\xacE&\x1f\x84\xab;Q\xae\xfb\x89\xa3\x13\xda\xec\x9b\xc0\xd9\x00\x00\xe0\x94\xa0\xff[L\xf0\x16\x02~\x83#I}D(\xd3\xe5\xa8;\x87\x95\x8a\x01e\x98\xd3\xc8>\xc0B\x00\x00\u07d4\xa1\x06F[\xbd\x19\u1dbc\xe5\r\x1b\x11W\xdcY\tZ60\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa1\x06\xe6\x92>\xddS\u028e\xd6P\x96\x8a\x91\b\xd6\xcc\xfd\x96p\x8a\x02\x02\xfe\x15\x05\xaf\uc240\x00\u07d4\xa1\t\u12f0\xa3\x9c\x9e\xf8/\xa1\x95\x97\xfc^\xd8\xe9\xebmX\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\xa1\x1a\x03\u013b&\xd2\x1e\xffg}]U\\\x80\xb2TS\xeez\x89\x03\xcb'Y\xbcA\x0f\x80\x00\u07d4\xa1\x1e\xff\xabl\xf0\xf5\x97,\xff\xe4\xd5e\x96\xe9\x89h\x14J\x8f\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xa1 M\xad_V\a(\xa3\\\r\x8f\u01d4\x81\x05{\xf7s\x86\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa1&#\xe6)\u07d3\tg\x04\xb1`\x84\xbe,\u061dV-\xa4\x8a\x01\xcc\xc92E\x11\xe4P\x00\x00\xe0\x94\xa1*l-\x98]\xaf\x0eO_ z\xe8Q\xaa\xf7)\xb32\u034a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xa13m\xfb\x96\xb6\xbc\xbeK>\xdf2\x05\xbeW#\xc9\x0f\xadR\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa1;\x9d\x82\xa9\x9b<\x9b\xbaZ\xe7.\xf2\x19\x9e\xdc};\xb3l\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xa1<\xfe\x82mm\x18A\u072eD;\xe8\u00c7Q\x816\xb5\xe8\x8a\x1d\xa5jK\b5\xbf\x80\x00\x00\xe0\x94\xa1C.\xd2\u01b7wz\x88\xe8\xd4m8\x8epG\u007f \x8c\xa5\x8a\x01\xb1\xa7\xe4\x13\xa1\x96\xc5\x00\x00\u07d4\xa1D\xf6\xb6\x0fr\xd6J!\xe30\xda\xdbb\u0619\n\xde+\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa1P%\xf5\x95\xac\xdb\xf3\x11\x0fw\u017f$G~eH\xf9\xe8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1X\x14\x8a.\x0f>\x92\xdc,\xe3\x8f\xeb\xc2\x01\a\xe3%<\x96\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1a`\x85\x1d+\x9c4\x9b\x92\xe4o\x82\x9a\xbf\xb2\x10\x945\x95\x89a\t=|,m8\x00\x00\u07d4\xa1f\xf9\x11\xc6D\xac2\x13\u049e\x0e\x1a\xe0\x10\xf7\x94\u056d&\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1m\x9e=c\x98aY\xa8\x00\xb4h7\xf4^\x8b\xb9\x80\xee\v\x89n\x11u\xdaz\xd1 \x00\x00\u07d4\xa1pp\xc2\xe9\u0169@\xa4\xec\x0eIT\xc4\xd7\xd6C\xbe\x8fI\x89lk\x17\x03;6\x1c\x80\x00\u07d4\xa1|\x9eC#\x06\x95\x18\x18\x9dR\a\xa0r\x8d\u02d20j?\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa1\x83`\xe9\x85\xf2\x06.\x8f\x8e\xfe\x02\xad,\xbc\x91\xad\x9aZ\xad\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa1\x91\x14\x05\xcfn\x99\x9e\xd0\x11\xf0\xdd\xcd*O\xf7\u008f%&\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa1\x92i\x80\a\xcc\x11\xaa`=\"\x1d_\xee\xa0v\xbc\xf7\xc3\r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\x92\xf0j\xb0R\xd5\xfd\u007f\x94\xee\xa81\x8e\x82x\x15\xfegz\x89\a\x1f\x8a\x93\xd0\x1eT\x00\x00\u07d4\xa1\x99\x81D\x96\x8a\\p\xa6AUT\xce\xfe\u0082F\x90\u0125\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa1\xa1\xf0\xfam \xb5\nyO\x02\xefR\b\\\x9d\x03j\xa6\u028965\u026d\xc5\u07a0\x00\x00\u07d4\xa1\xae\x8dE@\xd4\xdbo\xdd\xe7\x14oA[C\x1e\xb5\\y\x83\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xa1\xb4|M\x0e\xd6\x01\x88B\xe6\xcf\xc8c\n\u00e3\x14.^k\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xa1\xc4\xf4Z\x82\xe1\xc4x\xd8E\b.\xb1\x88u\xc4\xeae9\xab\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xa1\xdc\xd0\xe5\xb0Z\x97|\x96#\xe5\xae/Y\xb9\xad\xa2\xf3>1\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa1\xe48\n;\x1ft\x96s\xe2p\"\x99\x93\xeeU\xf3Vc\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\xf1\x93\xa0Y/\x1f\xeb\x9f\xdf\xc9\n\xa8\x13xN\xb8\x04q\u0249K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa1\xf2\x85@P\xf8re\x8e\xd8.R\xb0\xad{\xbc\x1c\xb9!\xf6\x89m\x03\x17\xe2\xb3&\xf7\x00\x00\u07d4\xa1\xf5\xb8@\x14\rZ\x9a\xce\xf4\x02\xac<\u00c8jh\xca\xd2H\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa1\xf7e\xc4O\xe4_y\x06w\x94HD\xbeO-B\x16_\xbd\x89\xc7\xe9\xcf\xdev\x8e\xc7\x00\x00\u07d4\xa1\xf7\xdd\xe1\xd78\xd8\xcdg\x9e\xa1\xee\x96[\xee\"K\xe7\xd0M\x89=\x18DP\xe5\xe9<\x00\x00\u07d4\xa1\xf8\u063c\xf9\x0ew\u007f\x19\xb3\xa6Iu\x9a\xd9P'\xab\xdf\u00c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\x02TrB\x80onp\xe7@X\xd6\xe5)-\xef\xc8\xc8\u0509l\x87T\xc8\xf3\f\b\x00\x00\u07d4\xa2\r\a\x1b\x1b\x000cI}y\x90\xe1$\x9d\xab\xf3l5\xf7\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa2\r\x8f\xf6\f\xaa\xe3\x1d\x02\xe0\xb6e\xfaC]v\xf7|\x94B\x89\x1a\x8a\x90\x9d\xfc\xef@\x00\x00\u07d4\xa2\x11\xda\x03\xcc\x0e1\xec\xceS\t\x99\x87\x18QU(\xa0\x90\u07c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\x14B\xab\x054\n\xdeh\xc9\x15\xf3\xc39\x9b\x99U\xf3\xf7\xeb\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xa2\"\"Y\u075c>=\xed\x12p\x84\xf8\b\xe9*\x18\x870,\x89\b\xc83\x9d\xaf\xedH\x00\x00\u07d4\xa2*\xde\r\xdb\\n\xf8\xd0\u034d\xe9M\x82\xb1\x10\x82\xcb.\x91\x897KW\xf3\xce\xf2p\x00\x00\u07d4\xa2L:\xb6!\x81\xe9\xa1[x\xc4b\x1eL|X\x81'\xbe&\x89\b\xcd\xe4:\x83\xd31\x00\x00\u07d4\xa2W\xadYK\u0603(\xa7\xd9\x0f\xc0\xa9\a\u07d5\xee\xca\xe3\x16\x89\x1c7\x86\xff8F\x93\x00\x00\u07d4\xa2[\bd7\xfd!\x92\u0420\xf6On\xd0D\xf3\x8e\xf3\xda2\x89\x12)\x0f\x15\x18\v\xdc\x00\x00\u07d4\xa2v\xb0X\u02d8\u060b\xee\xdbg\xe5CPl\x9a\r\x94p\u0609\x90\xaa\xfcv\xe0/\xbe\x00\x00\u07d4\xa2\x82\xe9i\xca\xc9\xf7\xa0\xe1\xc0\u0350\xf5\xd0\xc48\xacW\r\xa3\x89\"\a\xeb\x89\xfc'8\x00\x00\xe0\x94\xa2\x91\xe9\u01d9\rU-\u046e\x16\u03bc?\xca4,\xba\xf1\u044a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa2\x93\x19\xe8\x10i\xe5\xd6\r\xf0\x0f=\xe5\xad\xee5\x05\xec\xd5\xfb\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa2\x96\x8f\xc1\xc6K\xac\vz\xe0\u058b\xa9I\x87Mm\xb2S\xf4\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xa2\x9d[\xdat\xe0\x03GHr\xbdX\x94\xb8\x853\xffd\u00b5\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa2\x9df\x1acv\xf6m\vt\xe2\xfe\x9d\x8f&\xc0$~\xc8L\x89\xdf3\x04\a\x9c\x13\xd2\x00\x00\u07d4\xa2\xa45\xdeD\xa0\x1b\xd0\ucc9eD\xe4vD\xe4j\f\xdf\xfb\x89\x1b\x1dDZz\xff\xe7\x80\x00\u07d4\xa2\xac\xe4\u0253\xbb\x1eS\x83\xf8\xact\xe1y\x06n\x81O\x05\x91\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa2\xb7\x01\xf9\xf5\xcd\u041eK\xa6+\xae\xba\u3a02W\x10X\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa2\u0145O\xf1Y\x9f\x98\x89,W%\xd2b\xbe\x1d\xa9\x8a\xad\xac\x89\x11\t\xff30\x10\xe7\x80\x00\u07d4\xa2\xc7\xea\xff\xdc,\x9d\x93sE l\x90\x9aR\u07f1LG\x8f\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\xa2\u04aabk\t\xd6\xd4\xe4\xb1?\u007f\xfcZ\x88\xbdz\xd3gB\x89\xfb\x80xPuS\x83\x00\x00\u07d4\xa2\u04cd\xe1\xc79\x06\xf6\xa7\xcan\xfe\xb9|\xf6\xf6\x9c\xc4!\xbe\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa2\xdce\xee%kY\xa5\xbdy)wO\x90K5\x8d\U000ed84a\x04\x83\xbc\xe2\x8b\xeb\t\xf8\x00\x00\u07d4\xa2\xe0h:\x80]\xe6\xa0^\xdb/\xfb\xb5\xe9o\x05p\xb67\u00c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa2\u1e2a\x90\x0e\x9c\x13\x9b?\xa1\"5OaV\xd9*\x18\xb1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa2\u2d54\x1e\f\x01\x94K\xfe\x1d_\xb4\xe8\xa3K\x92,\u03f1\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\xe4`\xa9\x89\xcb\x15V_\x9e\u0327\xd1!\xa1\x8eN\xb4\x05\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa2\xec\xce,I\xf7*\t\x95\xa0\xbd\xa5z\xac\xf1\xe9\xf0\x01\xe2*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xa2\xf4r\xfeO\"\xb7}\xb4\x89!\x9e\xa4\x02=\x11X*\x93)\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xa2\xf7\x98\xe0w\xb0}\x86\x12N\x14\a\xdf2\x89\r\xbbKcy\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa2\xf8k\xc0a\x88N\x9e\xef\x05d\x0e\xddQ\xa2\xf7\xc0Yli\x89llD\xfeG\xec\x05\x00\x00\u07d4\xa2\xfa\x17\xc0\xfbPl\xe4\x94\x00\x8b\x95W\x84\x1c?d\x1b\x8c\xae\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa3\x04X\x8f\r\x85\f\xd8\u04cfv\xe9\xe8<\x1b\xf6>3>\u0789\x02(V\x01!l\x8c\x00\x00\u07d4\xa3\x05\x8cQszN\x96\xc5_.\xf6\xbd{\xb3X\x16~\u00a7\x89 \xdb:\xe4H\x1a\u0500\x00\u07d4\xa3\t\xdfT\u02bc\xe7\f\x95\xec03\x14\x9c\xd6g\x8ao\xd4\u03c9\f\x1f\x12\xc7Q\x01X\x00\x00\u07d4\xa3\nER\x0eR\x06\xd9\x00@p\xe6\xaf>{\xb2\xe8\xddS\x13\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa3\x0e\n\xcbSL\x9b0\x84\xe8P\x1d\xa0\x90\xb4\xeb\x16\xa2\xc0\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3 0\x95\xed\xb7\x02\x8ehq\xce\n\x84\xf5HE\x9f\x830\n\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa3!\t\x1d0\x18\x06By\xdb9\x9d+*\x88\xa6\xf4@\xae$\x89\xadx\xeb\u016cb\x00\x00\x00\u07d4\xa3#-\x06\x8dP\x06I\x03\xc9\xeb\xc5c\xb5\x15\xac\u0237\xb0\x97\x89l\x87T\xc8\xf3\f\b\x00\x00\xe0\x94\xa3$\x1d\x89\n\x92\xba\xf5)\b\xdcJ\xa0Irk\xe4&\xeb\u04ca\x04<-\xa6a\xca/T\x00\x00\u07d4\xa3)F&\xec)\x84\xc4;C\xdaM]\x8eFi\xb1\x1dKY\x896\xa4\xcfcc\x19\xc0\x00\x00\u07d4\xa3,\xf7\xdd\xe2\f=\xd5g\x9f\xf5\xe3%\x84\\p\u0156&b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa39\xa3\xd8\xca(\x0e'\xd2A[&\xd1\xfcy2(\xb6`C\x896\U00086577\x8f\xf0\x00\x00\u07d4\xa3<\xb4P\xf9[\xb4n%\xaf\xb5\x0f\xe0_\xee\xe6\xfb\x8c\xc8\xea\x89*\x11)\u0413g \x00\x00\u07d4\xa3?p\xdaru\xef\x05q\x04\u07e7\xdbd\xf4r\xe9\xf5\xd5S\x89\x04YF\xb0\xf9\xe9\xd6\x00\x00\u07d4\xa3@v\xf8K\xd9\x17\xf2\x0f\x83B\u024b\xa7\x9eo\xb0\x8e\xcd1\x89\u3bb5sr@\xa0\x00\x00\u07d4\xa3C\x0e\x1fd\u007f2\x1e\xd3G9V##\xc7\xd6#A\vV\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xa3O\x9dV\x8b\xf7\xaf\xd9L*[\x8a_\xf5\\f\xc4\by\x99\x89\x84}P;\"\x0e\xb0\x00\x00\u07d4\xa3V\x06\xd5\x12 \xee\u007f!F\xd4\x11X.\xe4\xeeJEYn\x89\u062a\xbe\b\v\xc9@\x00\x00\u07d4\xa3VU\x1b\xb7}OE\xa6\xd7\xe0\x9f\n\b\x9ey\u0322I\u02c9\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xa3\\\x19\x13,\xac\x195Wj\xbf\xedl\x04\x95\xfb\a\x88\x1b\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3e\x91\x8b\xfe?&'\xb9\xf3\xa8gu\xd8un\x0f\u0629K\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa3n\r\x94\xb9Sd\xa8&q\xb6\b\xcb-72Ea)\t\x89\b!\xd2!\xb5)\x1f\x80\x00\u07d4\xa3u\xb4\xbc$\xa2N\x1fyu\x93\xcc0+/3\x10c\xfa\\\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa3v\"\xac\x9b\xbd\xc4\xd8+u\x01]t[\x9f\x8d\xe6Z(\uc25d\xc0\\\xce(\u00b8\x00\x00\xe0\x94\xa3y\xa5\a\fP=/\xac\x89\xb8\xb3\xaf\xa0\x80\xfdE\xedK\xec\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xa3\x80-\x8ae\x9e\x89\xa2\xc4~\x90T0\xb2\xa8'\x97\x89P\xa7\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa3\x83\x06\xcbp\xba\xa8\u4446\xbdh\xaap\xa8=$/)\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\x84vi\x1d4\x94.\xeak/v\x88\x92#\x04}\xb4az\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\x87\xceN\x96\x1axG\xf5`\a\\d\xe1YkVA\xd2\x1c\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xa3\x87\xec\xde\x0e\xe4\xc8\a\x94\x99\xfd\x8e\x03G;\u060a\xd7R*\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa3\x88:$\xf7\xf1f _\x1aj\x99I\al&\xa7nqx\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xa3\x8b[\xd8\x1a\x9d\xb9\u04b2\x1d^\xc7\xc6\x05R\xcd\x02\xedV\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa3\x90\xca\x12+\x85\x01\xee>^\a\xa8\xcaKA\x9f~M\xae\x15\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xa3\x93*1\xd6\xffu\xfb;\x12q\xac\xe7\u02a7\xd5\xe1\xff\x10Q\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xa3\x94\xadO\xd9\xe6S\x0eo\\S\xfa\xec\xbe\u0781\xcb\x17-\xa1\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xa3\x97\x9a\x92v\n\x13Z\xdfi\xd7/u\xe1gu_\x1c\xb8\u00c9\x05k\xc7^-c\x10\x00\x00\xe0\x94\xa3\x9b\xfe\xe4\xae\u027du\xbd\"\u01b6r\x89\x8c\xa9\xa1\xe9]2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa3\xa2b\xaf\u0493h\x19#\b\x92\xfd\xe8O-ZYJ\xb2\x83\x89e\xea=\xb7UF`\x00\x00\u07d4\xa3\xa2\xe3\x19\xe7\u04e1D\x8bZ\xa2F\x89S\x16\f-\xbc\xbaq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\xa5{\a\x16\x13(\x04\xd6\n\xac(\x11\x97\xff+=#{\x01\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xa3\xa9>\xf9\xdb\xea&6&=\x06\xd8I/jA\u0790|\"\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\xa3\xae\x18y\x00}\x80\x1c\xb5\xf3RqjM\u063a'!\xde=\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xa3\xba\r:6\x17\xb1\xe3\x1bNB,\xe2i\xe8s\x82\x8d]i\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\xa3\xbc\x97\x9bp\x80\t/\xa1\xf9/n\x0f\xb3G\u2359PE\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xa3\xbf\xf1\u07e9\x97\x16h6\f\r\x82\x82\x842\xe2{\xf5Ng\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa3\xc1J\xce(\xb1\x92\u02f0b\x14_\u02fdXi\xc6rq\xf6\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa3\xc3:\xfc\x8c\xb4pN#\x15=\xe2\x04\x9d5\xaeq3$r\x89+X\xad\u06c9\xa2X\x00\x00\u07d4\xa3\u0430<\xff\xbb&\x9fyj\u009d\x80\xbf\xb0}\xc7\u01ad\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa3\u0543\xa7\xb6[#\xf6\vy\x05\xf3\xe4\xaab\xaa\xc8\u007fB'\x898\xbe\xfa\x12mZ\x9f\x80\x00\u07d4\xa3\xdb6J3-\x88K\xa9;&\x17\xaeM\x85\xa1H\x9b\xeaG\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xa3\xe0Q\xfbtJ\xa3A\f;\x88\xf8\x99\xf5\xd5\u007f\x16\x8d\xf1-\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\xa3\xe3\xa6\xeaP\x95s\xe2\x1b\xd0#\x9e\xce\x05#\xa7\xb7\u061b/\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xa3\xf4\xad\x14\xe0\xbbD\xe2\xce,\x145\x9cu\xb8\xe72\xd3pT\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa3\xfa\xccP\x19\\\vI3\xc8X\x97\xfe\xcc[\xbd\x99\\4\xb8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\x03Z\xb1\xe5\x18\b!\xf0\xf3\x80\xf1\x13\x1bs\x87\xc8\u0641\u0349\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\n\xa2\xbb\xce\fr\xb4\xd0\xdf\xff\xccBq[+T\xb0\x1b\xfa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4\x19\xa9\x84\x14#c&uuV`\x894\x0e\xea\x0e\xa2\b\x19\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xa4!\u06f8\x9b:\aA\x90\x84\xad\x10\xc3\xc1]\xfe\x9b2\xd0\u008a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa4\"\xe4\xbf\v\xf7AG\u0309[\xed\x8f\x16\xd3\xce\xf3BaT\x89\x12\xef?b\xee\x116\x80\x00\u07d4\xa4%\x9f\x83E\xf7\u3a37+\x0f\xec,\xf7^2\x1f\xdaM\u0089g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xa4)\b\xe7\xfeS\x98\n\x9a\xbf@D\xe9W\xa5Kp\u973e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4)\xfa\x88s\x1f\xdd5\x0e\x8e\xcdn\xa5B\x96\xb6HO\u6549j\xc5\xc6-\x94\x86\a\x00\x00\xe0\x94\xa40\x99]\xdb\x18[\x98e\xdb\xe6%9\xad\x90\xd2.Ks\u008a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa46\xc7TS\xcc\xcaJ\x1f\x1bb\xe5\u0123\r\x86\xdd\xe4\xbeh\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa47\xfen\xc1\x03\u028d\x15\x8fc\xb34\"N\u032c[>\xa3\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4;m\xa6\xcbz\xacW\x1d\xff'\xf0\x9d9\xf8F\xf57i\xb1\x89\x14\x99\x8f2\xacxp\x00\x00\u07d4\xa4;\x81\xf9\x93V\xc0\xaf\x14\x1a\x03\x01\rw\xbd\x04,q\xc1\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4>\x19G\xa9$+5Ua\xc3\n\x82\x9d\xfe\uc881Z\xf8\x89\xd2=\x99\x96\x9f\u0591\x80\x00\u07d4\xa4H\x9aP\xea\xd5\xd5DZ{\xeeM-U6\u00a7lA\xf8\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa4O\xe8\x00\xd9o\xca\xd7;qp\xd0\xf6\x10\u02cc\x06\x82\xd6\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa4T2\xa6\xf2\xac\x9dVW{\x93\x8a7\xfa\xba\xc8\xcc|F\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4f\xd7p\u0618\xd8\xc9\xd4\x05\xe4\xa0\xe5Q\xef\xaf\xcd\xe5<\xf9\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\xe0\x94\xa4g\a1\x17X\x93\xbb\xcf\xf4\xfa\x85\u0397\xd9O\xc5\x1cK\xa8\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4kC\x87\xfbM\xcc\xe0\x11\xe7nMsT}D\x81\xe0\x9b\xe5\x89Hz\x9a0E9D\x00\x00\u07d4\xa4l\xd27\xb6>\xeaC\x8c\x8e;e\x85\xf6y\xe4\x86\b2\xac\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4wy\u063c\x1c{\xce\x0f\x01\x1c\xcb9\xefh\xb8T\xf8\u078f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa4\x82kl8\x82\xfa\xd0\xed\\\x8f\xbb%\xcc@\xccO3u\x9f\x89p\x1bC\xe3D3\xd0\x00\x00\u07d4\xa4\x87Y(E\x8e\xc2\x00]\xbbW\x8c\\\xd35\x80\xf0\xcf\x14R\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa4\x9fR:\xa5\x13d\xcb\xc7\u0655\x16=4\xebY\r\xed/\b\x89\x90'B\x1b*\x9f\xbc\x00\x00\u07d4\xa4\xa4\x9f\v\xc8h\x8c\xc9\xe6\xdc\x04\xe1\xe0\x8dR\x10&\xe6Ut\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa4\xa7\xd3\x06\xf5\x10\xcdX5\x94(\xc0\xd2\xf7\xc3`\x9dVt\u05c9\xb5\x8c\xb6\x1c<\xcf4\x00\x00\u07d4\xa4\xa8:\a8y\x9b\x97\x1b\xf2\xdep\x8c.\xbf\x91\x1c\xa7\x9e\xb2\x89 \x86\xac5\x10R`\x00\x00\u07d4\xa4\xb0\x9d\xe6\xe7\x13\xdciTnv\xef\n\xcf@\xb9O\x02A\xe6\x89\x11}\xc0b~\xc8p\x00\x00\xe0\x94\xa4\u04b4)\xf1\xadSI\xe3\x17\x04\x96\x9e\xdc_%\xee\x8a\xca\x10\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xa4\xd6\xc8.\u076eYG\xfb\xe9\xcd\xfb\xd5H\xae3\xd9\x1aq\x91\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa4\xda4E\r\"\xec\x0f\xfc\xed\xe0\x00K\x02\xf7\x87.\xe0\xb7:\x89\x05\x0fafs\xf0\x83\x00\x00\xe0\x94\xa4\xddY\xab^Q}9\x8eI\xfaS\u007f\x89\x9f\xedL\x15\xe9]\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa4\xe6#E\x1e~\x94\xe7\u86e5\xed\x95\u0228:b\xff\xc4\xea\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa4\xed\x11\xb0r\u061f\xb16u\x9f\u019bB\x8cH\xaa]L\xed\x89\x0e?\x15'\xa0<\xa8\x00\x00\u07d4\xa4\xfb\x14@\x9ag\xb4V\x88\xa8Y>\\\xc2\xcfYl\xedo\x11\x89a\t=|,m8\x00\x00\xe0\x94\xa5\x14\xd0\x0e\xddq\b\xa6\xbe\x83\x9ac\x8d\xb2AT\x18\x17A\x96\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\xe0\x94\xa5\"\xde~\xb6\xae\x12PR*Q13\xa9;\xd4(IG\\\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa5$\xa8\xcc\xccIQ\x8d\x17\n2\x82p\xa2\xf8\x813\xfb\xaf]\x89\x0f\xf7\x02-\xac\x10\x8a\x00\x00\u07d4\xa59\xb4\xa4\x01\xb5\x84\xdf\xe0\xf3D\xb1\xb4\"\xc6UC\x16~.\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa5>\xadT\xf7\x85\n\xf2\x148\xcb\xe0z\xf6\x86'\x9a1[\x86\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa5C\xa0f\xfb2\xa8f\x8a\xa0sj\f\x9c\xd4\rx\t\x87'\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa5gw\vj\xe3 \xbd\xdeP\xf9\x04\xd6c\xe7F\xa6\x1d\xac\xe6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5h\xdbMW\xe4\xd6tb\xd73\u019a\x9e\x0f\xe2n!\x83'\x89;k\xff\x92f\xc0\xae\x00\x00\u07d4\xa5i\x8059\x1eg\xa4\x90\x13\xc0\x00 yY1\x14\xfe\xb3S\x89\r\x02\xabHl\xed\xc0\x00\x00\u07d4\xa5p\":\xe3\u02a8QA\x8a\x98C\xa1\xacU\xdbH$\xf4\xfd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa5s`\xf0\x02\xe0\xd6M-tE}\x8c\xa4\x85~\xe0\v\xcd\u07c9\x123\xe22\xf6\x18\xaa\x00\x00\u07d4\xa5u\xf2\x89\x1d\xcf\u0368<\\\xf0\x14t\xaf\x11\xee\x01\xb7-\u0089\x05l\xd5_\xc6M\xfe\x00\x00\u07d4\xa5x;\xf342\xff\x82\xacI\x89\x85\xd7\xd4`\xaeg\xec6s\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xa5\x87MuF5\xa7b\xb3\x81\xa5\xc4\u01d2H:\xf8\xf2=\x1d\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\xa5\xa4\"\u007fl\xf9\x88%\xc0\u057a\xffS\x15u,\xcc\x1a\x13\x91\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa5\xabK\xd3X\x8fF\xcb'.V\xe9=\xee\u04c6\xba\x8bu=\x89HB\xf0A\x05\x87,\x80\x00\xe0\x94\xa5\xba\xd8e\t\xfb\xe0\xe0\xe3\xc0\xe9?m8\x1f\x1a\xf6\xe9\u0501\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa5\xc36\b;\x04\xf9G\x1b\x8cn\xd76y\xb7Mf\xc3c\uc263e\nL\x9d \xe2\x00\x00\u07d4\xa5\xcd\x129\x92\x19K4\xc4x\x13\x140;\x03\xc5IH\xf4\xb9\x89l\xfc\xc3\xd9\x1d\xa5c\x00\x00\u07d4\xa5\u0578\xb6-\x00-\xef\x92A7\x10\xd1;o\xf8\xd4\xfc}\u04c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xa5\xd9ni}F5\x8d\x11\x9a\xf7\x81\x9d\xc7\b\u007fj\xe4\u007f\xef\x8a\x03\x17\xbe\xe8\xaf3\x15\xa7\x80\x00\u07d4\xa5\xde^CO\xdc\xddh\x8f\x1c1\xb6\xfbQ,\xb1\x96rG\x01\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xa5\xe0\xfc<:\xff\xed=\xb6q\tG\xd1\xd6\xfb\x01\u007f>'m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5\xe9;I\xea|P\x9d\xe7\xc4Ml\xfe\xdd\xefY\x10\u07aa\xf2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa5\xe9\xcdKt%]\"\xb7\u0672z\xe8\xddC\xedn\xd0%+\x89)\x8d\xb2\xf5D\x11\u0640\x00\xe0\x94\xa5\xf0\a{5\x1flP\\\xd5\x15\u07e6\xd2\xfa\u007f\\L\u0487\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xa5\xf0u\xfd@\x135W{f\x83\u0081\xe6\xd1\x01C-\xc6\xe0\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xa5\xfe,\xe9\u007f\x0e\x8c8V\xbe\r\xe5\xf4\u0732\xce]8\x9a\x16\x89\x01=\xb0\xb8\xb6\x86>\x00\x00\u07d4\xa5\xffb\"-\x80\xc0\x13\xce\xc1\xa0\xe8\x85\x0e\xd4\xd3T\xda\xc1m\x89\vA\a\\\x16\x8b\x18\x00\x00\u07d4\xa6\t\xc2m\xd3P\xc25\xe4K+\x9c\x1d\xdd\xcc\u0429\xd9\xf87\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa6\f\x12\tuO]\x87\xb1\x81\xdaO\b\x17\xa8\x18Y\xef\x9f\u0609\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\xe0\x94\xa6\x10\x1c\x96\x1e\x8e\x1c\x15y\x8f\xfc\xd0\xe3 \x1dw\x86\xec7:\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xa6\x13Ei\x96@\x8a\xf1\xc2\xe9>\x17w\x88\xabU\x89^+2\x8a\x01Y\x19\xffG|\x88\xb8\x00\x00\u07d4\xa6\x18\x87\x81\x8f\x91J \xe3\x10w)\v\x83qZk-n\xf9\x89e\xea=\xb7UF`\x00\x00\u07d4\xa6\x1aT\xdfxJD\xd7\x1bw\x1b\x871u\t!\x13\x81\xf2\x00\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa6\x1c\u06ed\xf0K\x1eT\u0203\xde`\x05\xfc\xdf\x16\xbe\xb8\xeb/\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa69\xac\xd9k1\xbaS\xb0\u0407c\"\x9e\x1f\x06\xfd\x10^\x9d\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa6BP\x10\x04\xc9\x0e\xa9\xc9\xed\x19\x98\xba\x14\nL\xd6,o_\x89\r\x94\xfb\x8b\x10\xf8\xb1\x80\x00\u07d4\xa6D\xed\x92,\xc27\xa3\xe5\u0117\x9a\x99Tw\xf3nP\xbcb\x89\x1f\xa7=\x84]~\x96\x00\x00\u07d4\xa6F\xa9\\moY\xf1\x04\xc6T\x1dw`uz\xb3\x92\xb0\x8c\x89\u3bb5sr@\xa0\x00\x00\xe0\x94\xa6HL\u0184\xc4\xc9\x1d\xb5>\xb6\x8aM\xa4Zjk\xda0g\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa6N_\xfbpL,\x919\xd7~\xf6\x1d\x8c\u07e3\x1dz\x88\xe9\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\xe0\x94\xa6T&\xcf\xf3x\xed#%5\x13\xb1\x9fIm\xe4_\xa7\u13ca\x01\x86P\x12|\xc3\u0700\x00\x00\u07d4\xa6jIc\xb2\u007f\x1e\xe1\x93+\x17+\xe5\x96N\r:\xe5KQ\x89\t`\xdbwh\x1e\x94\x00\x00\u07d4\xa6\u007f8\x81\x95eB:\xa8_>:\xb6\x1b\xc7c\u02eb\x89\u0749sw\xb0\"\u01be\b\x00\x00\u07d4\xa6\x8c14E\xc2-\x91\x9e\xe4l\xc2\xd0\xcd\xff\x04:uX%\x89\x04\x13t\xfd!\xb0\u0600\x00\u07d4\xa6\x8e\f0\u02e3\xbcZ\x88>T\x03 \xf9\x99\xc7\xcdU\x8e\\\x89a\x9237b\xa5\x8c\x80\x00\u07d4\xa6\x90\xf1\xa4\xb2\n\xb7\xba4b\x86 \u079c\xa0@\xc4<\x19c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa6\x9d|\xd1}HB\xfe\x03\xf6*\x90\xb2\xfb\xf8\xf6\xaf{\xb3\x80\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa6\xa0\x82R\xc8YQw\xcc.`\xfc'Y>#y\xc8\x1f\xb1\x89\x01\x16Q\xac>zu\x80\x00\u07d4\xa6\xa0\xdeB\x1a\xe5Om\x17(\x13\b\xf5dm/9\xf7w]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa6\xb2\xd5s)s`\x10,\a\xa1\x8f\xc2\x1d\xf2\xe7I\x9f\xf4\xeb\x89\xd9o\u0390\u03eb\xcc\x00\x00\xe0\x94\xa6\xc9\x10\xceMIJ\x91\x9c\u036a\xa1\xfc;\x82\xaat\xba\x06\u03ca\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xa6\u3ea3\x8e\x10J\x1e'\xa4\xd8(i\xaf\xb1\xc0\xaen\xff\x8d\x89\x01\x11@\ueb4bq\x00\x00\u07d4\xa6\xee\xbb\xe4d\u04d1\x87\xbf\x80\u029c\x13\xd7 '\xec[\xa8\xbe\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa6\xf6+\x8a=\u007f\x11\"\a\x01\xab\x9f\xff\xfc\xb3'\x95\x9a'\x85\x89\x1bn)\x1f\x18\u06e8\x00\x00\u07d4\xa6\xf93\a\xf8\xbc\xe01\x95\xfe\u0387 C\xe8\xa0?{\xd1\x1a\x89\x9csK\xadQ\x11X\x00\x00\u07d4\xa7\x01\xdfy\xf5\x94\x90\x1a\xfe\x14DH^k \u00fd\xa2\xb9\xb3\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa7\x02L\xfdt,\x1e\xc1<\x01\xfe\xa1\x8d0B\xe6_\x1d]\xee\x8a\x02c\x11\x9a(\xab\u0430\x80\x00\u07d4\xa7\x18\xaa\xadY\xbf9\\\xba+#\xe0\x9b\x02\xfe\f\x89\x81bG\x8960<\x97\xe4hx\x00\x00\u07d4\xa7$|S\xd0Y\xeb|\x93\x10\xf6(\xd7\xfclj\nw?\b\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xa7%7c\xcfJu\u07d2\xca\x1evm\xc4\xee\x8a'E\x14{\x8a\x02F7p\xe9\n\x8fP\x00\x00\u07d4\xa7.\xe6f\u0133^\x82\xa5\x06\x80\x8bD<\xeb\xd5\xc62\xc7\u0749+^:\xf1k\x18\x80\x00\x00\u07d4\xa7DD\xf9\x0f\xbbT\xe5o:\u0276\xcf\u032aH\x19\xe4aJ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa7GC\x9a\xd0\u04d3\xb5\xa08a\xd7r\x962m\u8edd\xb9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xa7`{BW;\xb6\xf6\xb4\xd4\xf2<~*&\xb3\xa0\xf6\xb6\xf0\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\xa7i)\x89\n{G\xfb\x85\x91\x96\x01lo\u0742\x89\u03b7U\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u0794\xa7kt?\x98\x1bi0r\xa11\xb2+\xa5\x10\x96\\/\xef\u05c8\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xa7m?\x15bQ\xb7,\f\xcfKG\xa39<\xbdoI\xa9\u0149Hz\x9a0E9D\x00\x00\u07d4\xa7t(\xbc\xb2\xa0\xdbv\xfc\x8e\xf1\xe2\x0eF\x1a\n2\u016c\x15\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xa7u\x8c\xec\xb6\x0e\x8faL\u0396\x13~\xf7+O\xbd\awJ\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa7w^J\xf6\xa2:\xfa \x1f\xb7\x8b\x91^Q\xa5\x15\xb7\xa7(\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\xa7\u007f>\u1793\x88\xbb\xbb\"\x15\xc6#\x97\xb9e`\x13#`\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa7\x85\x9f\xc0\u007fun\xa7\xdc\xeb\xbc\xcdB\xf0X\x17X-\x97?\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa7\x96lH\x9fLt\x8az\u902a'\xa5t%\x17g\xca\xf9\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xa7\xa3\xbba9\xb0\xad\xa0\f\x1f\u007f\x1f\x9fV\u0654\xbaM\x1f\xa8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa7\xa3\xf1S\xcd\u00c8!\xc2\f]\x8c\x82A\xb2\x94\xa3\xf8+$\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa7\xa5\x17\u05ed5\x82\v\t\u0517\xfa~U@\xcd\xe9IXS\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xa7\xc9\u04c8\xeb\xd8s\xe6k\x17\x13D\x83\x97\xd0\xf3\u007f\x8b\u04e8\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa7\u073b\xa9\xb9\xbfgb\xc1EAlPjq\u3d17 \x9c\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xa7\xe7O\v\xdb'\x8f\xf0\xa8\x05\xa6Ha\x8e\xc5+\x16o\xf1\xbe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa7\xe87r\xbc \x0f\x90\x06\xaa*&\r\xba\xa8H=\xc5+0\x89\vB\xd56f7\xe5\x00\x00\xe0\x94\xa7\xef5\u0387\xed\xa6\u008d\xf2HxX\x15\x05>\xc9zPE\x8a\x01\x0f\f\xe9I\xe0\x0f\x93\x00\x00\u07d4\xa7\xf9\"\f\x80G\x82k\xd5\xd5\x18?Ngjmw\xbf\xed6\x89\bPh\x97k\xe8\x1c\x00\x00\u07d4\xa8\a\x10O'\x03\xd6y\xf8\u07af\xc4B\xbe\xfe\x84\x9eB\x95\v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\f\xb1s\x8b\xac\b\xd4\xf9\xc0\x8bM\xef\xf5\x15T_\xa8XO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa8\x19\xd2\xec\xe1\"\xe0(\xc8\xe8\xa0J\x06M\x02\xb9\x02\x9b\b\xb9\x8965\u026d\xc5\u07a0\x00\x00\u0794\xa8%\xfdZ\xbby&\xa6|\xf3k\xa2F\xa2K\xd2{\xe6\xf6\xed\x88\xf4?\xc2\xc0N\xe0\x00\x00\u07d4\xa8(U9\x86\x9d\x88\xf8\xa9aS7Uq}~\xb6Uv\xae\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xa83\x82\xb6\xe1Rg\x97J\x85P\xb9\x8fqv\xc1\xa3S\xf9\xbe\x89\xbf\xfd\xaf/\xc1\xb1\xa4\x00\x00\xe0\x94\xa8DlG\x81\xa77\xacC(\xb1\xe1[\x8a\v?\xbb\x0f\xd6h\x8a\x04\x87\x94\xd1\xf2F\x19*\x00\x00\u07d4\xa8E[A\x17e\u0590\x1e1\x1erd\x03\t\x1eB\xc5f\x83\x89\xb7:\xec;\xfe\x14P\x00\x00\xe0\x94\xa8f\x13\xe6\u0124\xc9\xc5_\\\x10\xbc\xda2\x17]\u02f4\xaf`\x8a\x02C\xd6\xc2\xe3k\xe6\xae\x00\x00\u07d4\xa8m\xb0}\x9f\x81/G\x96b-@\xe0=\x13Xt\xa8\x8at\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa8\u007fz\xbdo\xa3\x11\x94(\x96x\xef\xb6<\xf5\x84\xee^*a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xa8\x80\u2a3f\x88\xa1\xa8&H\xb4\x01W\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa8\x9d\xf3HY\xed\xd7\xc8 \u06c8w@\xd8\xff\x9e\x15\x15|{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\xa4<\x00\x91\x00al\xb4\xaeN\x03?\x1f\xc5\xd7\xe0\xb6\xf1R\x89\u0548\xd0x\xb4?M\x80\x00\u07d4\xa8\xa7\b\xe8O\x82\u06c6\xa3U\x02\x19;Ln\xe9\xa7n\xbe\x8f\x897\b\xba\xed=h\x90\x00\x00\xe0\x94\xa8\xa7\xb6\x8a\u06b4\xe3\xea\xdf\xf1\x9f\xfaX\xe3J?\xce\xc0\xd9j\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xa8\xa8\xdb\xdd\x1a\x85\u047e\xee%i\xe9\x1c\xccM\t\xae\u007fn\xa1\x8a\x01:k+VHq\xa0\x00\x00\u07d4\xa8\xac\xa7H\xf9\xd3\x12\xect\u007f\x8bex\x14&\x94\xc7\xe9\xf3\x99\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa8\xb6[\xa3\x17\x1a?w\xa65\v\x9d\xaf\x1f\x8dU\xb4\xd2\x01\xeb\x89(b\xf3\xb0\xd2\"\x04\x00\x00\u07d4\xa8\xbe\xb9\x1c+\x99\u0216J\xa9[kJ\x18K\x12i\xfc4\x83\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u0794\xa8\xc0\xb0/\xaf\x02\xcbU\x19\u0768\x84\xde{\xbc\x8c\x88\xa2\u0681\x88\xe7\xc2Q\x85\x05\x06\x00\x00\u07d4\xa8\xc1\u05aaA\xfe=e\xf6{\xd0\x1d\xe2\xa8f\xed\x1e\u066eR\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\xa8\xca\xfa\xc3\"\x80\xd0!\x02\v\xf6\xf2\xa9x(\x83\u05ea\xbe\x12\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xa8\xdb\v\x9b \x14S3A<;\fb\xf5\xf5.\u0544\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa8\xf3\u007f\n\xb3\xa1\xd4H\xa9\xe3\xce@\x96_\x97\xa6F\b:4\x89\x11\xe0\xe4\xf8\xa5\v\xd4\x00\x00\u07d4\xa8\xf8\x9d\xd5\xccnd\u05f1\xee\xac\xe0\a\x02\x02,\xd7\xd2\xf0=\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\xa9\x04v\xe2\xef\xdf\xeeO8{\x0f2\xa5\x06x\xb0\xef\xb5s\xb5\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa9\x14PF\xfa6(\xcf_\xd4\xc6\x13\x92{\xe51\xe6\xdb\x1f\u0749\x06\x12O\xee\x99;\xc0\x00\x00\u07d4\xa9\x14\u0375q\xbf\xd9=d\xdaf\xa4\xe1\b\xea\x13NP\xd0\x00\x89M\x878\x99G\x13y\x80\x00\xe0\x94\xa9\x1aZ{4\x1f\x99\xc55\x14N \xbe\x9ck;\xb4\u008eM\x8a\x01&u:\xa2$\xa7\v\x00\x00\u07d4\xa9%%Q\xa6$\xaeQ7\x19\u06beR\a\xfb\xef\xb2\xfdwI\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xa9'\u050b\xb6\u02c1K\xc6\t\xcb\u02a9\x15\x1f]E\x9a'\xe1\x89\x0e\xb95\t\x00d\x18\x00\x00\u07d4\xa9)\u023dq\xdb\f0\x8d\xac\x06\b\n\x17G\xf2\x1b\x14e\xaa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xa9K\xbb\x82\x14\u03cd\xa0\xc2\xf6h\xa2\xacs\xe8bHR\x8dK\x894\n\xad!\xb3\xb7\x00\x00\x00\u07d4\xa9Q\xb2D\xffP\u03eeY\x1d^\x1a\x14\x8d\xf6\xa98\xef*\x1a\x89^\x00\x15\x84\xdf\xcfX\x00\x00\u07d4\xa9`\xb1\xca\xdd;\\\x1a\x8el\xb3\xab\xca\xf5.\xe7\xc3\xd9\xfa\x88\x89R\x8b\xc3T^Rh\x00\x00\u07d4\xa9a\x17\x1fSB\xb1s\xddp\xe7\xbf\xe5\xb5\xca#\x8b\x13\xbc\u0749\xb8'\x94\xa9$O\f\x80\x00\u07d4\xa9u\xb0w\xfc\xb4\u030e\xfc\xbf\x83\x84Y\xb6\xfa$:AY\u0589\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xa9{\xeb:H\xc4_\x15((L\xb6\xa9_}\xe4S5\x8e\u018a\x06\x90\x83l\n\xf5\xf5`\x00\x00\u07d4\xa9~\a!DI\x9f\xe5\xeb\xbd5J\xcc~~\xfbX\x98]\b\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xa9\x86v/zO)O.\v\x172y\xad,\x81\xa2\"4X\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xa9\x8f\x10\x985\xf5\xea\xcd\x05Cd|4\xa6\xb2i\xe3\x80/\xac\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xa9\x97\xdf\u01d8j'\x05\bH\xfa\x1cd\u05e7\xd6\xe0z\u0322\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\u07d4\xa9\x99\x91\u03bd\x98\xd9\xc88\xc2_zt\x16\xd9\xe2D\xca%\r\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xa9\xa1\xcd\xc3;\xfd7o\x1c\rv\xfbl\x84\xb6\xb4\xac'Mh\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xa9\xa8\xec\xa1\x1a#\xd6F\x89\xa2\xaa>A}\xbb=3k\xb5\x9a\x89\x0e4S\xcd;g\xba\x80\x00\u07d4\xa9\xac\xf6\x00\b\x1b\xb5[\xb6\xbf\xba\xb1\x81_\xfcN\x17\xe8Z\x95\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xa9\xad\x19&\xbcf\xbd\xb31X\x8e\xa8\x197\x88SM\x98,\x98\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xa9\xaf!\xac\xbeH/\x811\x89j\"\x806\xbaQ\xb1\x94S\u00c9\x02\xb5\xe0!\x98\f\xc1\x80\x00\xe0\x94\xa9\xb2\xd2\xe0IN\xab\x18\xe0}7\xbb\xb8V\xd8\x0e\x80\xf8L\u04ca\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xa9\xbaoA;\x82\xfc\xdd\xf3\xaf\xfb\xbd\u0412\x87\xdc\xf5\x04\x15\u0289\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xa9\xbe\x88\xad\x1eQ\x8b\v\xbb\x02J\xb1\xd8\xf0\xe7?y\x0e\fv\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xa9\xbf\xc4\x10\xdd\xdb q\x1eE\xc0s\x87\xea\xb3\n\x05N\x19\xac\x89>\x99`\x1e\xdfNS\x00\x00\u07d4\xa9\u0522\xbc\xbe[\x9e\bi\xd7\x0f\x0f\xe2\xe1\u05aa\xcdE\xed\u0149\n\xc6\xe7z\xb6c\xa8\x00\x00\xe0\x94\xa9\xd6KO;\xb7\x85\a\"\xb5\x8bG\x8b\xa6\x917^\"NB\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xa9\xd6\xf8q\xcax\x1au\x9a \xac:\u06d7,\xf1()\xa2\b\x892$\xf4'#\xd4T\x00\x00\xe0\x94\xa9\xdc\x04$\u0196\x9dy\x83X\xb3\x93\xb1\x93:\x1fQ\xbe\xe0\n\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xa9\xe1\x94f\x1a\xacpN\xe9\u07a0C\x97N\x96\x92\xde\xd8J]\x89\x1a&\xa5\x14\"\xa0p\x00\x00\u07d4\xa9\xe2\x837\xe65q\x93\xd9\xe2\xcb#k\x01\xbeD\xb8\x14'\u07c9wC\"\x17\xe6\x83`\x00\x00\u07d4\xa9\xe6\xe2^ekv%Xa\x9f\x14z!\x98[\x88t\xed\xfe\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xa9\xe9\xdb\xcez,\xb06\x94y\x98\x97\xbe\xd7\xc5M\x15_\u06a8\x89\n\xb5\xae\x8f\u025de\x80\x00\u07d4\xa9\xed7{}n\xc2Yq\xc1\xa5\x97\xa3\xb0\xf3\xbe\xadW\u024f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xaa\x02\x00\xf1\xd1~\x9cT\xda\x06G\xbb\x969]W\xa7\x858\u06099>\xf1\xa5\x12|\x80\x00\x00\u07d4\xaa\f\xa3ss7\x17\x8a\f\xaa\xc3\t\x9cXK\x05lV0\x1c\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xaa\x13kG\x96+\xb8\xb4\xfbT\r\xb4\xcc\xf5\xfd\xd0B\xff\xb8\u03c9\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\xaa\x14B-o\n\xe5\xa7X\x19N\xd1W\x80\xc88\xd6\u007f\x1e\xe1\x8a\x06\t2\x05lD\x9d\xe8\x00\x00\u07d4\xaa\x16&\x9a\xac\x9c\r\x800h\xd8/\u01d1Q\xda\xdd3Kf\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xaa\x16p&\u04da\xb7\xa8V5\x94N\xd9\xed\xb2\xbf\xeb\xa1\x18P\x8a\x01\xc1\xd5\xe2\x1bO\xcfh\x00\x00\u07d4\xaa\x1b7h\xc1m\x82\x1fX\x0ev\xc8\xe4\xc8\xe8m}\u01c8S\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xaa\x1d\xf9.Q\xdf\xf7\v\x19s\xe0\xe9$\xc6b\x87\xb4\x94\xa1x\x89\x1c\xf8J0\xa0\xa0\xc0\x00\x00\u07d4\xaa,g\x00\x96\xd3\xf990S%B~\xb9U\xa8\xa6\r\xb3\u0149l\x95Y\x06\x99#-\x00\x00\u07d4\xaa15\xcbT\xf1\x02\xcb\xef\xe0\x9e\x96\x10:\x1ayg\x18\xffT\x89\x03\"\"\xd9\xc31\x94\x00\x00\u07d4\xaa2\x1f\xdb\xd4I\x18\r\xb8\xdd\xd3O\x0f\xe9\x06\xec\x18\xee\t\x14\x89%\"H\u07b6\xe6\x94\x00\x00\xe0\x94\xaa9%\xdc\"\v\xb4\xae!w\xb2\x880x\xb6\xdc4l\xa1\xb2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xaa?)`\x1a\x131t^\x05\xc4(0\xa1^q\x93\x8ab7\x89\\(=A\x03\x94\x10\x00\x00\xe0\x94\xaaG\xa4\xff\xc9y622\u025b\x99\xfa\xda\x0f'4\xb0\xae\xee\x8a\x01\xb8H\x9d\xf4\xdb\xff\x94\x00\x00\u07d4\xaaI=?O\xb8fI\x1c\xf8\xf8\x00\xef\xb7\xe22N\xd7\xcf\xe5\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xaaV\xa6]\u012b\xb7/\x11\xba\xe3+o\xbb\aDG\x91\xd5\u0249(\x94\xe9u\xbfIl\x00\x00\xe0\x94\xaaZ\xfc\xfd\x83\t\xc2\u07dd\x15\xbe^jPN}pf$\u014a\x01<\xf4\"\xe3\x05\xa17\x80\x00\u07d4\xaa\x8e\xb0\x82;\a\xb0\xe6\xd2\n\xad\xda\x0e\x95\xcf85\xbe\x19.\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xaa\x91#~t\r%\xa9/\u007f\xa1F\xfa\xa1\x8c\xe5m\xc6\xe1\xf3\x892$\xf4'#\xd4T\x00\x00\u07d4\xaa\x96\x0e\x10\xc5#\x91\xc5N\x158|\xc6z\xf8'\xb51m\u0309lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\x9b\xd4X\x955\xdb'\xfa+\xc9\x03\xca\x17\xd6y\xddeH\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\xa8\xde\xfe\x11\xe3a?\x11\x06\u007f\xb9\x83bZ\b\x99Z\x8d\xfc\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaa\xaa\xe6\x8b2\x14\x02\xc8\xeb\xc14h\xf3A\xc6<\f\xf0?\u0389Rf<\u02b1\xe1\xc0\x00\x00\u07d4\xaa\xad\x1b\xaa\xdeZ\xf0N+\x17C\x9e\x93Y\x87\xbf\x8c+\xb4\xb9\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xaa\xb0\n\xbfX(\xd7\xeb\xf2kG\u03ac\u0378\xba\x032Qf\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xaa\xbd\xb3\\\x15\x14\x98J\x03\x92\x13y?3E\xa1h\xe8\x1f\xf1\x89\x10\xca\u0216\xd29\x00\x00\x00\u07d4\xaa\xca`\xd9\xd7\x00\u7156\xbb\xbb\xb1\xf1\xe2\xf7\x0fF'\xf9\u060965\xbbw\xcbK\x86\x00\x00\u07d4\xaa\xce\u0629V;\x1b\xc3\x11\xdb\xdf\xfc\x1a\xe7\xf5u\x19\xc4D\f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\u04b7\xf8\x10f\x95\a\x8el\x13\x8e\xc8\x1at\x86\xaa\xca\x1e\xb2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaa\xe6\x1eC\xcb\r\f\x96\xb3\x06\x99\xf7~\x00\xd7\x11\u0423\x97\x9b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaa\xe72\xed\xa6Y\x88\u00e0\f\u007fG/5\x1cF;\x1c\x96\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaa\xf0#\xfe\U0009091b\xb7\x8b\xb7\xab\xc9]f\x9cP\xd5(\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xaa\xf5\xb2\a\xb8\x8b\r\xe4\xac@\xd7G\xce\xe0n\x17-\xf6\xe7E\x8a\x06\xa7\xb7\x1d\u007fQ\u0410\x00\x00\u07d4\xaa\xf9\xeeK\x88lm\x1e\x95Io\xd2t#[\xf4\xec\xfc\xb0}\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xaa\xfb{\x01:\xa1\xf8T\x1c~2{\xf6P\xad\xbd\x19L \x8f\x89I\x9e\t-\x01\xf4x\x00\x00\xe0\x94\xab\t\x863\xee\xee\f\xce\xfd\xf62\xf9WTV\xf6\u0740\xfc\x86\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xab\f\xedv.\x16a\xfa\xe1\xa9*\xfb\x14\b\x88\x94\x13yH%\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xab\x14\xd2!\xe3=TF)\x19\x8c\u0416\xedc\u07e2\x8d\x9fG\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xab \x9f\u0729y\u0426G\x01\n\xf9\xa8\xb5/\xc7\xd2\r\x8c\u044a\x01\xee\xe2S,|-\x04\x00\x00\u07d4\xab'\xbax\xc8\xe5\xe3\xda\xef1\xad\x05\xae\xf0\xff\x03%r\x1e\b\x89\x19^\xce\x00n\x02\xd0\x00\x00\u07d4\xab(q\xe5\a\u01fe9eI\x8e\x8f\xb4b\x02Z\x1a\x1cBd\x89*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xab8a\"o\xfe\xc1(\x91\x87\xfb\x84\xa0\x8e\xc3\xed\x042d\xe8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab=\x86\xbc\x82\x92~\f\xd4!\xd1F\xe0\u007f\x91\x93'\xcd\xf6\xf9\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xab>b\xe7z\x8b\"^A\x15\x92\xb1\xaf0\aR\xfeA$c\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xab>x)K\xa8\x86\xa0\xcf\xd5\xd3H\u007f\xb3\xa3\a\x8d3\x8dn\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xab@\x04\xc0@?~\xab\xb0\xeaXo!!V\xc4 =g\xf1\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xabAo\xe3\rX\xaf\xe5\xd9EL\u007f\xce\u007f\x83\v\xccu\x03V\x89\x0657\x01\xc6\x05\u06c0\x00\u07d4\xabEr\xfb\xb1\xd7+W]i\xecj\xd1s3\x87>\x85R\xfc\x89lj\xc5L\xdahG\x00\x00\u07d4\xabZy\x01av2\ts\xe8\xcd8\xf67U0\x02%1\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab]\xfc\x1e\xa2\x1a\xdcB\u03cc?n6\x1e$?\xd0\xdaa\xe5\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xabke\xea\xb8\xdf\xc9\x17\xec\x02Q\xb9\xdb\x0e\u03e0\xfa\x03(I\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xabp\x91\x93.K\u00dd\xbbU#\x80\u0293O\xd7\x16m\x1en\x89\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\xabt\x16\xff2%IQ\u02fcbN\xc7\xfbE\xfc~\u02a8r\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xab|B\xc5\xe5-d\x1a\a\xadu\t\x9cb\x92\x8b\u007f\x86b/\x89\x126\x1a\xa2\x1d\x14\xba\x00\x00\u07d4\xab}T\xc7\xc6W\x0e\xfc\xa5\xb4\xb8\xcep\xf5*Ws\xe5\xd5;\x89\x0f(:\xbe\x9d\x9f8\x00\x00\u07d4\xab~\v\x83\xed\x9aBLm\x1ejo\x87\xa4\xdb\xf0d\t\xc7\u0589\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xab\x84\xa0\xf1G\xad&T\x00\x00+\x85\x02\x9aA\xfc\x9c\xe5\u007f\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xab\x93\xb2n\xce\n\n\xa2\x13e\xaf\xed\x1f\xa9\xae\xa3\x1c\xd5Dh\x89W+{\x98sl \x00\x00\u07d4\xab\x94\x8aJ\xe3y\\\xbc\xa11&\xe1\x92S\xbd\xc2\x1d:\x85\x14\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xab\x9a\xd3n\\t\xce.\x969\x9fW\x83\x941\xd0\u77d6\xab\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\xab\xb2\xe6\xa7*@\xban\xd9\b\u037c\xec\x91\xac\xfdwx0\xd1dcG\x8a\xe0\xfcw \x89\a?u\u0460\x85\xba\x00\x00\xe0\x94\xab\u071f\x1b\xcfM\x19\xee\x96Y\x100\xe7r\xc340/}\x83\x8a\b~^\x11\xa8\x1c\xb5\xf8\x00\x00\u07d4\xab\xde\x14{*\xf7\x89\ua946T~f\xc4\xfa&d\xd3(\xa4\x89\rk`\x81\xf3L\x12\x80\x00\xe0\x94\xab\xe0|\xedj\xc5\xdd\xf9\x91\xef\xf6\xc3\xda\"jt\x1b\xd2C\xfe\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xab\xf1/\xa1\x9e\x82\xf7lq\x8f\x01\xbd\xca\x00\x03gE#\xef0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xab\xf7(\u03d3\x12\xf2!(\x02NpF\xc2Q\xf5\xdcY\x01\xed\x8a\x06A\xe8\xa15c\xd8\xf8\x00\x00\u07d4\xab\xf8\xff\xe0p\x8a\x99\xb5(\xcc\x1e\xd4\xe9\xceK\r\x060\xbe\x8c\x89z\xb5\u00ae\xee\xe68\x00\x00\u07d4\xab\xfc\xf5\xf2P\x91\xceW\x87_\xc6t\xdc\xf1\x04\xe2\xa7=\xd2\xf2\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xab\xfe\x93d%\xdc\u01f7K\x95P\x82\xbb\xaa\xf2\xa1\x1dx\xbc\x05\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xac\x02OYO\x95X\xf0ICa\x8e\xb0\xe6\xb2\xeeP\x1d\xc2r\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\x12*\x03\xcd\x05\x8c\x12._\xe1{\x87/Hw\xf9\u07d5r\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xac\x14.\xda\x11W\xb9\xa9\xa6C\x90\xdf~j\xe6\x94\xfa\u0249\x05\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\x1d\xfc\x98Kq\xa1\x99)\xa8\x1d\x81\xf0J|\xbb\x14\a7\x03\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xac!\xc1\xe5\xa3\xd7\xe0\xb5\x06\x81g\x9d\xd6\u01d2\xdb\u0287\xde\u02ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xac(\x89\xb5\x96o\f\u007f\x9e\xdbB\x89\\\xb6\x9d\x1c\x04\xf9#\xa2\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xac(\xb5\xed\xea\x05\xb7o\x8c_\x97\bEA'|\x96ijL\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xac,\x8e\t\xd0d\x93\xa68XC{\xd2\v\xe0\x19bE\x03e\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xac.vm\xac?d\x8fcz\xc6q?\u0770h\xe4\xa4\xf0M\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\xac9\x00)\x8d\xd1M|\xc9mJ\xbbB\x8d\xa1\xba\xe2\x13\xff\xed\x8a\x05<\xa1)t\x85\x1c\x01\x00\x00\u07d4\xac=\xa5&\xcf\u0388)s\x02\xf3LI\xcaR\r\xc2q\xf9\xb2\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xacD`\xa7nm\xb2\xb9\xfc\xd1R\xd9\xc7q\x8d\x9a\xc6\xed\x8co\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xacJ\xcf\xc3n\xd6\tJ'\xe1\x18\xec\xc9\x11\xcdG>\x8f\xb9\x1f\x89a\x91>\x14@<\f\x00\x00\u07d4\xacL\xc2V\xaet\xd6$\xac\xe8\r\xb0x\xb2 \u007fW\x19\x8fk\x89lyt\x12?d\xa4\x00\x00\u07d4\xacN\xe9\xd5\x02\xe7\xd2\xd2\xe9\x9eY\xd8\xca}_\x00\xc9KM\u058965\u026d\xc5\u07a0\x00\x00\u07d4\xacR\xb7~\x15fH\x14\xf3\x9eO'\x1b\xe6A0\x8d\x91\xd6\u0309\v\xed\x1d\x02c\xd9\xf0\x00\x00\u07d4\xacY\x99\xa8\x9d-\u0486\u0568\fm\xee~\x86\xaa\xd4\x0f\x9e\x12\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xac_br1H\r\r\x950.m\x89\xfc2\xcb\x1dO\xe7\xe3\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xac`\x8e+\xac\x9d\xd2\a(\u0494~\xff\xbb\xbf\x90\n\x9c\xe9K\x8a\x01EK\r\xb3uh\xfc\x00\x00\u07d4\xacm\x02\xe9\xa4k7\x9f\xacJ\u0271\u05f5\xd4{\xc8P\xce\x16\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xacoh\xe87\xcf\x19a\xcb\x14\xabGDm\xa1h\xa1m\u0789\x89Hz\x9a0E9D\x00\x00\u07d4\xacw\xbd\xf0\x0f\u0558[]\xb1+\xbe\xf8\x008\n\xbc*\x06w\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xac~\x03p'#\xcb\x16\xee'\xe2-\u0438\x15\xdc-\\\xae\x9f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xac\x8bP\x9a\xef\xea\x1d\xbf\xaf+\xb35\x00\xd6W\vo\xd9mQ\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xac\x8e\x87\xdd\xda^x\xfc\xbc\xb9\xfa\u007f\xc3\xce\x03\x8f\x9f}.4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xac\x9f\xffh\xc6\x1b\x01\x1e\xfb\xec\xf08\xedr\u06d7\xbb\x9er\x81\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xac\xa1\xe6\xbcd\xcc1\x80\xf6 \xe9M\u0171\xbc\xfd\x81X\xe4]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\xa2\xa883\v\x170-\xa71\xd3\r\xb4\x8a\x04\xf0\xf2\a\xc1\x89Hz\x9a0E9D\x00\x00\u07d4\xac\xaa\xdd\xcb\xf2\x86\xcb\x0e!]\xdaUY\x8f\u007f\xf0\xf4\xad\xa5\u018965\u026d\xc5\u07a0\x00\x00\u07d4\xac\xb9C8UK\u0108\u0308\xae-\x9d\x94\b\rk\u07c4\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xac\xbc-\x19\xe0l;\xab\xbb[o\x05+k\xf7\xfc7\xe0r)\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\xbd\x18U\x89\xf7\xa6\x8ag\xaaK\x1b\xd6Pw\xf8\xc6NN!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xac\xc0bp,Ya]4D\xefb\x14\xb8\x86+\x00\x9a\x02\xed\x89QO\xcb$\xff\x9cP\x00\x00\u07d4\xac\xc0\x90\x9f\xda.\xa6\xb7\xb7\xa8\x8d\xb7\xa0\xaa\xc8h\t\x1d\xdb\xf6\x89\x013v_\x1e&\u01c0\x00\u07d4\xac\xc1\u01c7\x86\xabM+;'q5\xb5\xba\x12>\x04\x00Hk\x89\x04E\x91\xd6\u007f\xec\xc8\x00\x00\u07d4\xac\xc4j*U\\t\xde\u0522\xbd\tN\x82\x1b\x97\x84;@\xc0\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xac\u015f;0\xce\xff\xc5da\xcc[\x8d\xf4\x89\x02$\x0e\x0e{\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\xce\x01\xe0\xa7\x06\x10\xdcp\xbb\x91\xe9\x92o\xa9\x95\u007f7/\xba\x89\x1d\x1c_>\xda \xc4\x00\x00\u07d4\xac\xd8\u0751\xf7\x14vLEg|c\xd8R\xe5n\xb9\xee\xce.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xac\u2af6;\x06\x04@\x9f\xbd\xe3\xe7\x16\u0487mD\xe8\xe5\u0749\b=lz\xabc`\x00\x00\xe0\x94\xac\xec\x91\xefiA\xcfc\v\xa9\xa3\u71e0\x12\xf4\xa2\xd9\x1d\u050a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xad\nJ\xe4x\xe9cn\x88\xc6\x04\xf2B\xcfT9\xc6\xd4V9\x89\xbe\xd1\xd0&=\x9f\x00\x00\x00\u07d4\xad\x17\x99\xaa\xd7`+E@\u0343/\x9d\xb5\xf1\x11P\xf1hz\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xad\x1dh\xa08\xfd%\x86\x06~\xf6\xd15\xd9b\x8ey\xc2\xc9$\x89\xfe\t\xa5'\x9e*\xbc\x00\x00\u07d4\xad*\\\x00\xf9#\xaa\xf2\x1a\xb9\xf3\xfb\x06n\xfa\n\x03\xde/\xb2\x8965\xbbw\xcbK\x86\x00\x00\u07d4\xad5e\xd5+h\x8a\xdd\xed\b\x16\x8b-8r\xd1}\n&\xae\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xad7|\xd2^\xb5>\x83\xae\t\x1a\n\x1d+E\x16\xf4\x84\xaf\u0789i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xadAM)\xcb~\xe9s\xfe\xc5N\"\xa3\x88I\x17\x86\xcfT\x02\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xadD5~\x01~$OGi1\u01f8\x18\x9e\xfe\xe8\n]\n\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xadW\xaa\x9d\x00\xd1\fC\x9b5\xef\xcc\v\xec\xac.9U\xc3\x13\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xadY\xa7\x8e\xb9\xa7J\u007f\xbd\xae\xfa\xfa\x82\xea\u0684u\xf0\u007f\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xadZ\x8dV\x01L\xfc\xb3`\xf4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xadr\x81!\x87?\x04V\xd0Q\x8b\x80\xabe\x80\xa2\x03pe\x95\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xads,\x97e\x93\xee\xc4x;N.\xcdy9yx\v\xfe\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xad}\xd0S\x85\x9e\xdf\xf1\xcbo\x9d*\xcb\xedm\xd5\xe32Bo\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xad\x80\xd8e\xb8\\4\xd2\xe6IK.z\xef\xeak\x9a\xf1\x84\u06c9\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xad\x8b\xfe\xf8\u018aH\x16\xb3\x91o5\xcb{\xfc\xd7\xd3\x04\tv\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xad\x8eH\xa3wi]\xe0\x146:R:(\xb1\xa4\fx\xf2\b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xad\x91\n#\u0585\x06\x13eJ\xf7\x863z\u04a7\bh\xacm\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xad\x92~\x03\xd1Y\x9ax\xca+\xf0\xca\u04a1\x83\xdc\xebq\xea\xc0\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xad\x92\xca\x06n\xdb|q\x1d\xfc[\x16a\x92\xd1\xed\xf8\xe7q\x85\x8a\a\x9f\x90\\o\xd3N\x80\x00\x00\u07d4\xad\x94#_\u00f3\xf4z$\x13\xaf1\u8111I\b\xef\fE\x89\x1b\x1b\x01B\xd8\x15\x84\x00\x00\u07d4\xad\x9e\x97\xa0H/5:\x05\xc0\xf7\x92\xb9w\xb6\xc7\xe8\x11\xfa_\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xad\x9fL\x89\n;Q\x1c\xeeQ\xdf\xe6\xcf\xd7\xf1\t;vA,\x89\x1bv|\xbf\xeb\f\xe4\x00\x00\u07d4\xad\xaa\x0eT\x8c\x03Z\xff\xedd\xcag\x8a\x96?\xab\xe9\xa2k\xfd\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\xad\xb9H\xb1\xb6\xfe\xfe }\xe6^\x9b\xbc-\xe9\x8e`]\vW\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xad\xc1\x9e\xc85\xaf\xe3\u5347\u0713\xa8\xa9!<\x90E\x13&\x89j\xdb\xe54\"\x82\x00\x00\x00\u07d4\xad\xc8\"\x8e\xf9(\xe1\x8b*\x80}\x00\xfb1\xfcgX\x15\xaa\x00\x00\u07d4\xad\xff\r\x1d\v\x97G\x1ev\u05c9\xd2\u470at\xf9\xbdT\xff\x89e\xea=\xb7UF`\x00\x00\u07d4\xae\x06,D\x86\x18d0u\xdez\x0004-\xce\xd6=\xba\u05c9,\xc6\u034c\u0082\xb3\x00\x00\xe0\x94\xae\x10\xe2z\x01O\r0k\xaf&mH\x97\u021a\xee\xe2\xe9t\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xae\x12k8,\xf2W\xfa\xd7\xf0\xbc}\x16)~T\xccrg\u0689\x10CV\x1a\x88)0\x00\x00\u07d4\xae\x13\xa0\x85\x11\x11\x0f2\xe5;\xe4\x12xE\xc8C\xa1\xa5|{\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xae\x17\x9aF\r\xb6c&t=$\xe6u#\xa5{$m\xaf\u007f\x8a\x01\x00\a\xae|\xe5\xbb\xe4\x00\x00\u07d4\xae\"(ey\x90y\xaa\xf4\xf0gJ\f\u06ab\x02\xa6\xd5p\xff\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xae#\x9a\xcf\xfdN\xbe.\x1b\xa5\xb4\x17\x05r\xdcy\xcce3\xec\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xae/\x9c\x19\xacv\x13e\x94C#\x93\xb0G\x1d\b\x90!d\u04c9%\xdf\x05\u01a8\x97\xe4\x00\x00\u07d4\xae4\x86\x1d4\"S\x19O\xfcfR\xdf\xdeQ\xabD\xca\xd3\xfe\x89\x19F\bhc\x16\xbd\x80\x00\u07d4\xae6\xf7E!!\x91>\x80\x0e\x0f\xcd\x1ae\xa5G\x1c#\x84o\x89\b\xe3\xf5\v\x17<\x10\x00\x00\u07d4\xae?\x98\xa4C\xef\xe0\x0f>q\x1dR]\x98\x94\u071aa\x15{\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\xe0\x94\xaeG\xe2`\x9c\xfa\xfe6\x9df\xd4\x15\xd99\xde\x05\b\x1a\x98r\x8a\x05\xba\xec\xf0%\xf9\xb6P\x00\x00\u07d4\xaeO\x12.5\xc0\xb1\xd1\xe4\x06\x92\x91E|\x83\xc0\u007f\x96_\xa3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaePU\x81L\xb8\xbe\f\x11{\xb8\xb1\xc8\u04b6;F\x98\xb7(\x89\x01\xbc\x93.\xc5s\xa3\x80\x00\u07d4\xaeS\x8cs\u0173\x8d\x8dXM~\xbd\xad\xef\xb1\\\xab\xe4\x83W\x896'\xe8\xf7\x127<\x00\x00\u07d4\xaeW\xcc\x12\x9a\x96\xa8\x99\x81\xda\xc6\r/\xfb\x87}]\xc5\xe42\x89<:#\x94\xb3\x96U\x00\x00\u07d4\xaeZ\xa1\xe6\u00b6\x0fo\xd3\xef\xe7!\xbbJq\x9c\xbe=o]\x89+$\u01b5Z^b\x00\x00\u07d4\xae\\\x9b\xda\xd3\xc5\u0221\"\x04D\xae\xa5\xc2)\xc1\x83\x9f\x1dd\x89\x19\xe2\xa4\xc8\x18\xb9\x06\x00\x00\u07d4\xae\\\xe35Z{\xa9\xb32v\f\tP\u00bcE\xa8_\xa9\xa0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xae]\"\x1a\xfc\xd3\u0493U\xf5\b\xea\xdf\xca@\x8c\xe3<\xa9\x03\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xaec[\xf781\x11\x9d-)\xc0\xd0O\xf8\xf8\xd8\u0425zF\x89Hz\x9a0E9D\x00\x00\xe0\x94\xaed\x81U\xa6X7\x0f\x92\x9b\xe3\x84\xf7\xe0\x01\x04~I\xddF\x8a\x02\xdf$\xae2\xbe D\x00\x00\xe0\x94\xaeo\fs\xfd\xd7|H\x97'Q!t\u0675\x02\x96a\x1cL\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xaep\xe6\x9d,J\n\xf8\x18\x80{\x1a'\x05\xf7\x9f\u0435\xdb\u01095e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xaew9\x12N\xd1S\x05%\x03\xfc\x10\x14\x10\xd1\xff\xd8\xcd\x13\xb7\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xaex\xbb\x84\x919\xa6\xba8\xae\x92\xa0\x9ai`\x1c\xc4\xcbb\u0449\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xae\x84\"\x10\xf4M\x14\u0124\u06d1\xfc\x9d;;P\x01O{\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xae\x84.\x81\x85\x8e\xcf\xed\xf6Plhm\xc2\x04\xac\x15\xbf\x8b$\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xae\x89T\xf8\xd6\x16m\xe5\a\xcfa)}\x0f\xc7\xcak\x9eq(\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xae\x9e\xcdk\u0755.\xf4\x97\xc0\x05\n\u0aca\x82\xa9\x18\x98\u0389\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\xae\x9f\\?\xbb\xe0\u027c\xbf\x1a\xf8\xfft\xea(\v:]\x8b\b\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xae\xad\x88\u0589Ak\x1c\x91\xf26D!7[}\x82\xd0RR\n\xfb\\Wm\x9f~\xb9>\u048a\r\xd0A \xba\t\xcf\xe6\x00\x00\u07d4\xae\xc2\u007f\xf5\xd7\xf9\xdd\u0691\x18?F\xf9\xd5%C\xb6\xcd+/\x89\x18e\x01'\xcc=\xc8\x00\x00\u07d4\xae\xe4\x9dh\xad\xed\xb0\x81\xfdCpZ_x\xc7x\xfb\x90\xdeH\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xae\xf5\xb1\"X\xa1\x8d\xec\a\xd5\xec.1et\x91\x9dy\xd6\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\xae\xfc\xfe\x88\xc8&\xcc\xf11\xd5N\xb4\ua7b8\x0ea\xe1\xee%\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xaf\x06\xf5\xfam\x12\x14\xecC\x96}\x1b\xd4\xdd\xe7J\xb8\x14\xa98\x89\x04\xc5>\xcd\xc1\x8a`\x00\x00\u07d4\xaf\x11H\xefl\x8e\x10=u0\xef\xc9\x16y\u026c'\x00\t\x93\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xaf >\"\x9d~mA\x9d\xf47\x8e\xa9\x87\x15Q_c\x14\x85\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xaf X\xc7(,\xf6|\x8c<\xf90\x13<\x89a|\xe7])\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4\xaf&\xf7\u01bfE> x\xf0\x89S\u4c80\x04\xa2\xc1\xe2\t\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xaf0\x87\xe6.\x04\xbf\x90\rZT\xdc>\x94bt\u0692B;\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf6\x14\u0736\x8a6\xe4ZN\x91\x1ebybG\"-Y[\x89z\x81\x06_\x11\x03\xbc\x00\x00\u07d4\xaf6\x15\u01c9\u0431\x15*\xd4\xdb%\xfe]\xcf\"(\x04\xcfb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xaf<\xb5\x96Y3\xe7\xda\u0603i;\x9c>\x15\xbe\xb6\x8aHs\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xafD\x93\xe8R\x1c\xa8\x9d\x95\xf5&|\x1a\xb6?\x9fEA\x1e\x1b\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xafL\xf4\x17\x85\x16\x1fW\x1d\f\xa6\x9c\x94\xf8\x02\x1fA)N\u028a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xafR\x9b\xdbE\x9c\xc1\x85\xbe\xe5\xa1\u014b\xf7\xe8\xcc\xe2\\\x15\r\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xafg\xfd>\x12\u007f\xd9\xdc6\xeb?\xcdj\x80\u01feOu2\xb2\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xafw\x1094Z40\x01\xbc\x0f\x8aY#\xb1&\xb6\rP\x9c\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94\xaf\u007fy\xcbAZ\x1f\xb8\u06fd\tF\a\xee\x8dA\xfb|Z;\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xaf\x87\xd27\x1e\xf3x\x95\u007f\xbd\x05\xba/\x1df\x93\x1b\x01\u2e09%\xf2s\x93=\xb5p\x00\x00\u07d4\xaf\x88\x0f\xc7V}U\x95\xca\xcc\xe1\\?\xc1L\x87B\xc2l\x9e\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xaf\x8e\x1d\xcb1L\x95\r6\x87CM0\x98X\xe1\xa8s\x9c\u0509\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xaf\x99-\xd6i\xc0\x88>U\x15\xd3\xf3\x11*\x13\xf6\x17\xa4\xc3g\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaf\xa1\u056d8\xfe\xd4GY\xc0[\x89\x93\xc1\xaa\r\xac\xe1\x9f@\x89\x04V9\x18$O@\x00\x00\xe0\x94\xaf\xa59XnG\x19\x17J;F\xb9\xb3\xe6c\xa7\u0475\xb9\x87\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xaf\xa6\x94n\xff\xd5\xffS\x15O\x82\x01\x02S\xdfG\xae(\f\u0309j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xaf\xc8\xeb\u860b\xd4\x10Z\xccL\x01\x8eTj\x1e\x8f\x9cx\x88\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xaf\xcc}\xbb\x83V\xd8B\xd4:\xe7\xe2<\x84\"\xb0\"\xa3\b\x03\x8a\x06o\xfc\xbf\xd5\xe5\xa3\x00\x00\x00\u07d4\xaf\xd0\x19\xff6\xa0\x91U4ki\x97H\x15\xa1\xc9\x12\xc9\n\xa4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xaf\xda\xc5\xc1\xcbV\xe2E\xbfp3\x00f\xa8\x17\uabecL\u0449\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf\xdd\x1bxab\xb81~ \xf0\xe9y\xf4\xb2\xceHmv]\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xaf\xf1\x04Z\xdf'\xa1\xaa2\x94a\xb2M\xe1\xba\u950ai\x8b\x89\x01\u03c4\xa3\n\n\f\x00\x00\u07d4\xaf\xf1\a\x96\v~\xc3N\u0590\xb6e\x02M`\x83\x8c\x19\x0fp\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xaf\xf1\x1c\xcfi\x93\x04\xd5\xf5\x86*\xf8`\x83E\x1c&\xe7\x9a\xe5\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xaf\xf1at\nm\x90\x9f\xe9\x9cY\xa9\xb7yE\xc9\x1c\xc9\x14H\x89\x03@\xaa\xd2\x1b;p\x00\x00\xe0\x94\xaf\xfc\x99\xd5\ubd28O\xe7x\x8d\x97\xdc\xe2t\xb08$\x048\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xaf\xfe\xa0G7\"\xcb\u007f\x0e\x0e\x86\xb9\xe1\x18\x83\xbfB\x8d\x8dT\x89i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xb0\t\x96\xb0Vn\xcb>rC\xb8\"y\x88\u0733R\xc2\x18\x99\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xb0\x1e8\x9b(\xa3\x1d\x8eI\x95\xbd\xd7\xd7\xc8\x1b\xee\xab\x1eA\x19\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb0-\x06(s3EE\u03a2\x92\x18\xe4\x05w`Y\x0ft#\x89\xac\xb6\xa1\xc7\xd9:\x88\x00\x00\u07d4\xb0/\xa2\x93\x87\xec\x12\xe3\u007fi\"\xacL\xe9\x8c[\t\xe0\xb0\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb06\x91k\xda\u03d4\xb6\x9eZ\x8ae`)u\xeb\x02a\x04\u0749\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb0A1\x0f\xe9\xee\u0586L\xed\u053e\xe5\x8d\xf8\x8e\xb4\xed<\xac\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb0U\xafL\xad\xfc\xfd\xb4%\xcfe\xbad1\a\x8f\a\xec\u056b\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xb0W\x11S\xdb\x1cN\u05ec\xae\xfe\x13\xec\xdf\xdbr\xe7\xe4\xf0j\x8a\x11\f\xffyj\xc1\x95 \x00\x00\u07d4\xb0n\xab\t\xa6\x10\u01a5=V\xa9F\xb2\xc44\x87\xac\x1d[-\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb0rI\xe0U\x04J\x91U5\x9a@)7\xbb\xd9T\xfeH\xb6\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xb0v\x182\x8a\x90\x13\a\xa1\xb7\xa0\xd0X\xfc\xd5xn\x9er\xfe\x8a\x06gI]JC0\xce\x00\x00\u07d4\xb0y\xbbM\x98f\x14:m\xa7*\xe7\xac\x00\"\x06)\x811\\\x89)3\x1eeX\xf0\xe0\x00\x00\u07d4\xb0{\xcc\bZ\xb3\xf7)\xf2D\x00Ah7\xb6\x996\xba\x88s\x89lm\x84\xbc\xcd\xd9\xce\x00\x00\u07d4\xb0{\xcf\x1c\xc5\xd4F.Q$\xc9e\xec\xf0\xd7\r\xc2z\xcau\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\xb0|\xb9\xc1$\x05\xb7\x11\x80uC\u0113De\xf8\u007f\x98\xbd-\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb0\u007f\u07af\xf9\x1dD`\xfel\xd0\u8870\xbd\x8d\"\xa6.\x87\x8a\x01\x1d%)\xf3SZ\xb0\x00\x00\xe0\x94\xb0\x9f\xe6\xd44\x9b\x99\xbc7\x93\x80T\x02-T\xfc\xa3f\xf7\xaf\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\xe0\x94\xb0\xaa\x00\x95\f\x0e\x81\xfa2\x10\x17>r\x9a\xaf\x16:'\xcdq\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xb0\xacN\xfff\x80\xee\x14\x16\x9c\xda\xdb\xff\xdb0\x80Om%\xf5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb0\xb3j\xf9\xae\xee\u07d7\xb6\xb0\"\x80\xf1\x14\xf19\x84\xea2`\x895e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xb0\xb7y\xb9K\xfa<.\x1fX{\u031c~!x\x92\"7\x8f\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xb0\xba\xeb0\xe3\x13wlLm$t\x02\xbaAg\xaf\u0361\u0309j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb0\xbb)\xa8a\xea\x1dBME\xac\u053f\u0112\xfb\x8e\xd8\t\xb7\x89\x04V9\x18$O@\x00\x00\xe0\x94\xb0\xc1\xb1w\xa2 \xe4\x1f|t\xd0|\u0785i\xc2\x1cu\xc2\xf9\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xb0\xc7\xceL\r\xc3\u00bb\xb9\x9c\xc1\x85{\x8aE_a\x17\x11\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb0\xce\xf8\xe8\xfb\x89\x84\xa6\x01\x9f\x01\xc6y\xf2r\xbb\xe6\x8f\\w\x89\b=lz\xabc`\x00\x00\xe0\x94\xb0\xd3+\xd7\xe4\u6577\xb0\x1a\xa3\xd0Ao\x80U}\xba\x99\x03\x8a\x03s\x9f\xf0\xf6\xe6\x130\x00\x00\xe0\x94\xb0\xd3\u0247+\x85\x05n\xa0\xc0\xe6\xd1\xec\xf7\xa7~<\u6ac5\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\xb0\xe4i\u0206Y8\x15\xb3IV8Y]\xae\xf0f_\xaeb\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xb0\xe7`\xbb\a\xc0\x81wsE\xe0W\x8e\x8b\u0218\"mN;\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1\x040\x04\xec\x19A\xa8\xcfO+\x00\xb1W\x00\u076co\xf1~\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb1\x05\xdd=\x98|\xff\xd8\x13\xe9\xc8P\n\x80\xa1\xad%}V\u0189lj\xccg\u05f1\xd4\x00\x00\u07d4\xb1\x0f\u04a6G\x10/\x88\x1ft\xc9\xfb\xc3}\xa62\x94\x9f#u\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xb1\x15\xee:\xb7d\x1e\x1a\xa6\xd0\x00\xe4\x1b\xfc\x1e\xc7!\f/2\x8a\x02\xc0\xbb=\xd3\fN \x00\x00\u07d4\xb1\x17\x8a\xd4s\x83\xc3\x1c\x814\xa1\x94\x1c\xbc\xd4t\xd0bD\xe2\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xb1\x17\x95\x89\u1779\xd4\x15W\xbb\xec\x1c\xb2L\xcc-\xec\x1c\u007f\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xb1\x19\u76a9\xb9\x16Re\x81\xcb\xf5!\xefGJ\xe8M\xcf\xf4\x89O\xba\x10\x01\xe5\xbe\xfe\x00\x00\u07d4\xb1\x1f\xa7\xfb'\n\xbc\xdfZ.\xab\x95\xaa0\u013566\uffc9+^:\xf1k\x18\x80\x00\x00\u07d4\xb1$\xbc\xb6\xff\xa40\xfc\xae.\x86\xb4_'\xe3\xf2\x1e\x81\xee\b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1)\xa5\xcbq\x05\xfe\x81\v\u0615\xdcr\x06\xa9\x91\xa4TT\x88\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\xe0\x94\xb1.\xd0{\x8a8\xadU\x066?\xc0z\vmy\x996\xbd\xaf\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb14\xc0\x049\x1a\xb4\x99(x3zQ\xec$/B(WB\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1?\x93\xaf0\xe8\xd7fs\x81\xb2\xb9[\xc1\xa6\x99\xd5\xe3\xe1)\x89\x16\u012b\xbe\xbe\xa0\x10\x00\x00\u07d4\xb1E\x92\x85\x86>\xa2\xdb7Y\xe5F\u03b3\xfb7a\xf5\x90\x9c\x89<\xd7*\x89@\x87\xe0\x80\x00\u07d4\xb1F\xa0\xb9%U<\xf0o\xca\xf5J\x1bM\xfe\xa6!)\aW\x89lnY\xe6|xT\x00\x00\xe0\x94\xb1Jz\xaa\x8fI\xf2\xfb\x9a\x81\x02\u05bb\xe4\u010a\xe7\xc0o\xb2\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb1K\xbe\xffpr\tu\xdca\x91\xb2\xa4O\xf4\x9f&r\x87<\x89\a\xc0\x86\x0eZ\x80\xdc\x00\x00\xe0\x94\xb1L\xc8\xde3\xd63\x826S\x9aH\x90 \xceFU\xa3+\u018a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb1M\xdb\x03\x86\xfb`c\x98\xb8\xccGVZ\xfa\xe0\x0f\xf1\xd6j\x89\xa1*\xff\b>f\xf0\x00\x00\u07d4\xb1S\xf8(\xdd\amJ|\x1c%t\xbb-\xee\x1aD\xa3\x18\xa8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb1T\x0e\x94\xcf\xf3F\\\xc3\u0447\xe7\xc8\u3f6f\x98FY\u2262\x15\xe4C\x90\xe33\x00\x00\u07d4\xb1X\xdbC\xfab\xd3\x0ee\xf3\u041b\xf7\x81\u01f6sr\uba89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xb1ar_\xdc\xed\xd1yR\xd5{#\xef([~K\x11i\xe8\x89\x02\xb6\xdf\xed6d\x95\x80\x00\u07d4\xb1dy\xba\x8e}\xf8\xf6>\x1b\x95\xd1I\u0345)\xd75\xc2\u0689-\xe3:j\xac2T\x80\x00\u07d4\xb1f\xe3}.P\x1a\xe7<\x84\x14+_\xfbZ\xa6U\xddZ\x99\x89l]\xb2\xa4\xd8\x15\xdc\x00\x00\u07d4\xb1\x83\xeb\xeeO\xcbB\xc2 \xe4wt\xf5\x9dlT\xd5\xe3*\xb1\x89V\xf7\xa9\xc3<\x04\xd1\x00\x00\u07d4\xb1\x88\a\x84D\x02~8g\x98\xa8\xaehi\x89\x19\xd5\xcc#\r\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xb1\x89j7\xe5\u0602Z-\x01vZ\xe5\xdeb\x99w\u0783R\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb1\x8eg\xa5\x05\n\x1d\xc9\xfb\x19\t\x19\xa3=\xa88\xefDP\x14\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb1\xa2\xb4:t3\xdd\x15\v\xb8\"'\xedQ\x9c\u05b1B\u04c2\x89\x94mb\rtK\x88\x00\x00\u07d4\xb1\xc0\u040b6\xe1\x84\xf9\x95*@7\xe3\xe5:f}\a\nN\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb1\xc3(\xfb\x98\xf2\xf1\x9a\xb6do\n|\x8cVo\xdaZ\x85@\x89\x87\x86x2n\xac\x90\x00\x00\xe0\x94\xb1\xc7Qxi9\xbb\xa0\xd6q\xa6w\xa1X\u01ab\xe7&^F\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xb1\xcdK\xdf\xd1\x04H\x9a\x02n\u025dYs\a\xa0By\xf1s\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb1\u03d4\xf8\t\x15\x05\x05_\x01\n\xb4\xba\u0196\xe0\xca\x0fg\xa1\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xb1\u05b0\x1b\x94\xd8T\xfe\x8b7J\xa6^\x89\\\xf2*\xa2V\x0e\x892\xf5\x1e\u06ea\xa30\x00\x00\xe0\x94\xb1\u06e5%\v\xa9bWU$n\x06yg\xf2\xad/\a\x91\u078a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xb1\xe2\u0755\xe3\x9a\xe9w\\U\xae\xb1?\x12\xc2\xfa#0S\xba\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb1\xe6\xe8\x10\xc2J\xb0H\x8d\xe9\xe0\x1eWH7\x82\x9f|w\u0409\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb1\xe9\xc5\xf1\xd2\x1eauzk.\xe7Y\x13\xfcZ\x1aA\x01\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\x03\u049elV\xb9&\x99\u0139-\x1fo\x84d\x8d\xc4\u03fc\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\x16\xdcY\xe2|=ry\xf5\xcd[\xb2\xbe\u03f2`n\x14\u0649\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\x1byy\xbf|\\\xa0\x1f\xa8-\xd6@\xb4\x1c9\xe6\u01bcu\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xb2#\xbf\x1f\xbf\x80H\\\xa2\xb5V}\x98\xdb{\xc3SM\xd6i\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb2-PU\xd9b15\x96\x1ej\xbd'<\x90\xde\xea\x16\xa3\xe7\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xb2-\xad\xd7\xe1\xe0R2\xa927\xba\xed\x98\xe0\u07d2\xb1\x86\x9e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb24\x03_uDF<\xe1\xe2+\xc5S\x06F\x84\xc5\x13\xcdQ\x89\r\x89\xfa=\u010d\xcf\x00\x00\u07d4\xb2G\u03dcr\xecH*\xf3\xea\xa7Ye\x8fy=g\nW\f\x891p\x8a\xe0\x04T@\x00\x00\u07d4\xb2ghA\xee\x9f-1\xc1r\xe8#\x03\xb0\xfe\x9b\xbf\x9f\x1e\t\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb2y\xc7\xd3U\u0088\x03\x92\xaa\u046a!\xee\x86|;5\a\u07c9D[\xe3\xf2\uf1d4\x00\x00\u07d4\xb2|\x1a$ L\x1e\x11\x8du\x14\x9d\xd1\t1\x1e\a\xc0s\xab\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb2\x81\x81\xa4X\xa4@\xf1\u01bb\x1d\xe8@\x02\x81\xa3\x14\x8fL5\x89\x14b\fW\xdd\xda\xe0\x00\x00\xe0\x94\xb2\x82E\x03|\xb1\x92\xf7W\x85\u02c6\xcb\xfe|\x93\r\xa2X\xb0\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xb2\x87\xf7\xf8\xd8\u00c7,\x1bXk\xcd}\n\xed\xbf~s'2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb2\x8b\xb3\x9f4fQ|\xd4o\x97\x9c\xf5\x96S\xee}\x8f\x15.\x89\x18e\x01'\xcc=\xc8\x00\x00\u07d4\xb2\x8d\xbf\xc6I\x98\x94\xf7:q\xfa\xa0\n\xbe\x0fK\xc9\u045f*\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xb2\x96\x8f}5\xf2\b\x87\x161\xc6h{?=\xae\xab\xc6al\x89\bu\xc4\u007f(\x9fv\x00\x00\u07d4\xb2\x9f[|\x190\xd9\xf9z\x11^\x06pf\xf0\xb5M\xb4K;\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb2\xa1D\xb1\xeag\xb9Q\x0f\"g\xf9\xda9\xd3\xf9=\xe2fB\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xa2\xc2\x11\x16\x12\xfb\x8b\xbb\x8e}\xd97\x8dg\xf1\xa3\x84\xf0P\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb2\xa4\x98\xf0;\xd7\x17\x8b\u0627\x89\xa0\x0fR7\xafy\xa3\xe3\xf8\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\u07d4\xb2\xaa/\x1f\x8e\x93\xe7\x97\x13\xd9,\xea\x9f\xfc\xe9\xa4\n\xf9\xc8-\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xb5\x16\xfd\u045e\u007f8d\xb6\xd2\xcf\x1b%*AV\xf1\xb0;\x89\x02\xe9\x83\xc7a\x15\xfc\x00\x00\u07d4\xb2\xb7\u0374\xffKa\u0577\xce\v\"p\xbb\xb5&\x97C\xec\x04\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb2\xbd\xbe\u07d5\x90\x84v\xd7\x14\x8a7\f\u0193t6(\x05\u007f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb2\xbf\xaaX\xb5\x19l\\\xb7\xf8\x9d\xe1_G\x9d\x188\xdeq=\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4\xb2\xc5>\xfa3\xfeJ:\x1a\x80 \\s\xec;\x1d\xbc\xad\x06\x02\x89h\x01\u06b3Y\x18\x93\x80\x00\xe0\x94\xb2\xd06\x05\x15\xf1}\xab\xa9\x0f\u02ec\x82\x05\xd5i\xb9\x15\u05ac\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xb2\xd1\xe9\x9a\xf9\x121\x85\x8epe\xdd\x19\x183\r\xc4\xc7G\u054a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\xb2\u066b\x96d\xbc\xf6\xdf <4o\u0192\xfd\x9c\xba\xb9 ^\x89\x17\xbex\x97`e\x18\x00\x00\u07d4\xb2\u0777\x86\xd3yN'\x01\x87\xd0E\x1a\xd6\u0237\x9e\x0e\x87E\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb2\xe0\x85\xfd\xdd\x14h\xba\aA['NsN\x11#\u007f\xb2\xa9\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xb2\xe9\xd7k\xf5\x0f\xc3k\xf7\u04d4Kc\xe9\u0288\x9bi\x99h\x89\x902\xeab\xb7K\x10\x00\x00\xe0\x94\xb2\xf9\xc9r\xc1\xe9swU\xb3\xff\x1b0\x88s\x83\x969[&\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xb2\xfc\x84\xa3\xe5\nP\xaf\x02\xf9M\xa08>\u055fq\xff\x01\u05ca\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xb3\x05\v\xef\xf9\xde3\xc8\x0e\x1f\xa1R%\xe2\x8f,A:\xe3\x13\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\xb3\x11\x96qJH\xdf\xf7&\xea\x943\xcd)\x12\xf1\xa4\x14\xb3\xb3\x89\x91Hx\xa8\xc0^\xe0\x00\x00\xe0\x94\xb3\x14[tPm\x1a\x8d\x04|\xdc\xdcU9*{SPy\x9a\x8a\x1bb)t\x1c\r=]\x80\x00\u07d4\xb3 \x83H6\xd1\xdb\xfd\xa9\xe7\xa3\x18M\x1a\xd1\xfdC \xcc\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3#\u073f.\xdd\xc58.\u4efb \x1c\xa3\x93\x1b\xe8\xb48\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb3$\x00\xfd\x13\xc5P\t\x17\xcb\x03{)\xfe\"\xe7\xd5\"\x8f-\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xb3%gL\x01\xe3\xf7)\rR&3\x9f\xbe\xacg\xd2!'\x9f\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xb3(%\xd5\xf3\xdb$\x9e\xf4\xe8\\\xc4\xf31S\x95\x89v\u8f09\x1b-\xf9\xd2\x19\xf5y\x80\x00\u07d4\xb3*\xf3\xd3\xe8\xd0u4I&To.2\x88{\xf9;\x16\xbd\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb3/\x1c&\x89\xa5\xcey\xf1\xbc\x97\v1XO\x1b\xcf\"\x83\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb3<\x03#\xfb\xf9\xc2l\x1d\x8a\xc4N\xf7C\x91\u0400F\x96\u0689\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb3O\x04\xb8\xdbe\xbb\xa9\xc2n\xfcL\xe6\xef\xc5\x04\x81\xf3\xd6]\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb3U}9\xb5A\x1b\x84D__T\xf3\x8fb\xd2qM\x00\x87\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xb3X\xe9|p\xb6\x05\xb1\xd7\xd7)\u07f6@\xb4<^\xaf\xd1\xe7\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xb3^\x8a\x1c\r\xac~\x0ef\u06ecsjY*\xbdD\x01%a\x88\xcf\xceU\xaa\x12\xb3\x00\x00\xe0\x94\xb3fx\x94\xb7\x86<\x06\x8a\xd3D\x87?\xcf\xf4\xb5g\x1e\x06\x89\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb3qw1\xda\xd6Q2\xday-\x87`0\xe4j\xc2'\xbb\x8a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3s\x1b\x04l\x8a\u0195\xa1'\xfdy\u0425\xd5\xfaj\xe6\xd1.\x89lO\xd1\xee$nx\x00\x00\u07d4\xb3|+\x9fPc{\xec\xe0\u0295\x92\b\xae\xfe\xe6F;\xa7 \x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb3\x88\xb5\xdf\xec\xd2\xc5\u4d56W|d%V\xdb\xfe'xU\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb3\x8cNS{]\xf90\xd6Zt\xd0C\x83\x1dkH[\xbd\xe4\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xb3\x919Wa\x94\xa0\x86a\x95\x15\x1f3\xf2\x14\n\xd1\u0306\u03ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xb3\x9fL\x00\xb2c\f\xab}\xb7)^\xf4=G\xd5\x01\xe1\u007f\u05c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb3\xa6K\x11vrOT\t\xe1AJ5#f\x1b\xae\xe7KJ\x89\x01ch\xffO\xf9\xc1\x00\x00\u07d4\xb3\xa6\xbdA\xf9\xd9\xc3 \x1e\x05\v\x87\x19\x8f\xbd\xa3\x994\"\x10\x89\xc4a\xe1\xdd\x10)\xb5\x80\x00\u07d4\xb3\xa8\xc2\xcb}5\x8eW9\x94\x1d\x94[\xa9\x04Z\x02:\x8b\xbb\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3\xaeT\xfb\xa0\x9d>\xe1\u05bd\xd1\xe9W\x929\x19\x02L5\xfa\x89\x03\x8d,\xeee\xb2*\x80\x00\u07d4\xb3\xb7\xf4\x93\xb4J,\x8d\x80\xecx\xb1\xcd\xc7Ze+s\xb0l\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb3\xc2(s\x1d\x18m-\xed[_\xbe\x00Lfl\x8eF\x9b\x86\x89\x01\x92t\xb2Y\xf6T\x00\x00\u07d4\xb3\xc2``\x9b\x9d\xf4\t^l]\xff9\x8e\xeb^-\xf4\x99\x85\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xb3\xc6[\x84Z\xbal\xd8\x16\xfb\xaa\xe9\x83\xe0\xe4l\x82\xaa\x86\"\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb3\xc9H\x11\xe7\x17[\x14\x8b(\x1c\x1a\x84[\xfc\x9b\xb6\xfb\xc1\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb3\xe2\x0e\xb4\xde\x18\xbd\x06\x02!h\x98\x94\xbe\u5bb2SQ\xee\x89\x03\xfc\x80\xcc\xe5\x16Y\x80\x00\u07d4\xb3\xe3\xc49\x06\x98\x80\x15f\x00\u0089.D\x8dA6\xc9-\x9b\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\xe0\x94\xb3\xf8*\x87\xe5\x9a9\xd0\u0480\x8f\aQ\xebr\xc22\x9c\xdc\u014a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb3\xfc\x1dh\x81\xab\xfc\xb8\xbe\xcc\v\xb0!\xb8\xb7;r3\u0751\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xb4\x05\x94\xc4\xf3fN\xf8I\u0326\"{\x8a%\xaai\t%\xee\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb4\x1e\xaf]Q\xa5\xba\x1b\xa3\x9b\xb4\x18\u06f5O\xabu\x0e\xfb\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4$\u058d\x9d\r\x00\xce\xc1\x93\x8c\x85N\x15\xff\xb8\x80\xba\x01p\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb4%bs\x96+\xf61\xd0\x14U\\\xc1\xda\r\xcc1akI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb40g\xfep\u0675Ys\xbaX\xdcd\xdd\u007f1\x1eUBY\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb46W\xa5\x0e\xec\xbc0w\xe0\x05\xd8\xf8\xd9O7xv\xba\u0509\x01\xec\x1b:\x1f\xf7Z\x00\x00\u07d4\xb4<'\xf7\xa0\xa1\"\bK\x98\xf4\x83\x92%A\u0203l\xee,\x89&\u009eG\u0104L\x00\x00\xe0\x94\xb4A5v\x86\x9c\b\xf9Q*\xd3\x11\xfe\x92Y\x88\xa5-4\x14\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xb4F\x05U$q\xa6\xee\xe4\u06abq\xff;\xb4\x13&\xd4s\xe0\x89-~=Q\xbaS\xd0\x00\x00\u07d4\xb4GW\x1d\xac\xbb>\u02f6\xd1\xcf\v\f\x8f88\xe5#$\xe2\x89\x01\xa3\x18f\u007f\xb4\x05\x80\x00\u07d4\xb4G\x83\xc8\xe5{H\a\x93\xcb\u059aE\xd9\f{O\fH\xac\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb4H\x15\xa0\xf2\x8eV\x9d\x0e\x92\x1aJ\u078f\xb2d%&Iz\x89\x03\x027\x9b\xf2\xca.\x00\x00\u07d4\xb4Im\xdb'y\x9a\"$W\xd79y\x11g(\u8844[\x89\x8d\x81\x9e\xa6_\xa6/\x80\x00\xe0\x94\xb4RL\x95\xa7\x86\x0e!\x84\x02\x96\xa6\x16$@\x19B\x1cJ\xba\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb4\\\xca\r6\x82fbh<\xf7\u0432\xfd\xach\u007f\x02\xd0\u010965\u026d\xc5\u07a0\x00\x00\u0794\xb4d@\u01d7\xa5V\xe0L}\x91\x04f\x04\x91\xf9k\xb0v\xbf\x88\xce\xc7o\x0eqR\x00\x00\u07d4\xb4j\u0386^,P\xeaF\x98\xd2\x16\xabE]\xffZ\x11\xcdr\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4m\x11\x82\xe5\xaa\xca\xff\r&\xb2\xfc\xf7/<\x9f\xfb\xcd\xd9}\x89\xaa*`<\xdd\u007f,\x00\x00\u07d4\xb4\x89!\xc9h}U\x10tE\x84\x93n\x88\x86\xbd\xbf-\xf6\x9b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\x98\xbb\x0fR\x00\x05\xb6!jD%\xb7Z\xa9\xad\xc5-b+\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xb4\xb1\x1d\x10\x9f`\x8f\xa8\xed\xd3\xfe\xa9\xf8\xc3\x15d\x9a\xeb=\x11\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb4\xb1K\xf4TU\u042b\b\x035\x8bu$\xa7+\xe1\xa2\x04[\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb4\xb1\x85\xd9C\xee+Xc\x1e3\xdf\xf5\xafhT\xc1y\x93\xac\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\xbf$\u02c3hk\xc4i\x86\x9f\xef\xb0D\xb9\tqi\x93\xe2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb4\xc2\x00@\xcc\u0661\xa3(=\xa4\u0522\xf3e\x82\bC\xd7\xe2\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb4\xc8\x17\x0f{*\xb56\xd1\u0662[\xdd :\xe1(\x8d\xc3\u0549\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb4\xd8/.i\x94?}\xe0\xf5\xf7t8y@o\xac.\x9c\xec\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xb4\xddF\f\xd0\x16rZd\xb2.\xa4\xf8\xe0n\x06gN\x03>\x8a\x01#\x1b\xb8t\x85G\xa8\x00\x00\u07d4\xb4\xddT\x99\xda\xeb%\a\xfb-\xe1\"\x97s\x1dLr\xb1k\xb0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb5\x04l\xb3\xdc\x1d\xed\xbd6E\x14\xa2\x84\x8eD\xc1\xdeN\xd1G\x8a\x03{}\x9b\xb8 @^\x00\x00\xe0\x94\xb5\b\xf9\x87\xb2\xde4\xaeL\xf1\x93\u0785\xbf\xf6\x13\x89b\x1f\x88\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xb5\tU\xaan4\x15q\x98f\b\xbd\u0211\xc2\x13\x9fT\f\u07c9j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb5\f\x14\x9a\x19\x06\xfa\xd2xo\xfb\x13Z\xabP\x177\xe9\xe5o\x89\x15\b\x94\xe8I\xb3\x90\x00\x00\u07d4\xb5\f\x9fW\x89\xaeD\xe2\xdc\xe0\x17\xc7\x14\xca\xf0\f\x83\x00\x84\u0089\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xb5\x14\x88,\x97\x9b\xb6B\xa8\r\u04c7T\u0578\xc8)m\x9a\a\x893\xc5I\x901r\f\x00\x00\u07d4\xb5\x1d\u0734\xddN\x8a\xe6\xbe3m\xd9eIq\xd9\xfe\xc8kA\x89\x16\xd4d\xf8=\u2500\x00\u07d4\xb5\x1eU\x8e\xb5Q/\xbc\xfa\x81\xf8\u043d\x93\x8cy\xeb\xb5$+\x89&\u009eG\u0104L\x00\x00\u07d4\xb5#\xff\xf9t\x98q\xb3S\x88C\x887\xf7\xe6\xe0\u07a9\xcbk\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xb5-\xfbE\xde]t\xe3\xdf \x832\xbcW\x1c\x80\x9b\x8d\xcf2\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xb55\xf8\u06c7\x9f\xc6\u007f\xecX\x82J\\\xbenT\x98\xab\xa6\x92\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xb57\xd3jp\xee\xb8\xd3\xe5\xc8\r\xe8\x15\"\\\x11X\u02d2\u0109QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xb5;\xcb\x17L%\x184\x8b\x81\x8a\xec\xe0 6E\x96Fk\xa3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5I>\xf1srDE\xcf4\\\x03]'\x9b\xa7Y\xf2\x8dQ\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb5S\xd2]kT!\xe8\x1c*\xd0^\v\x8b\xa7Q\xf8\xf0\x10\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5Tt\xbaX\xf0\xf2\xf4\x0el\xba\xbe\xd4\xea\x17n\x01\x1f\xca\u0589j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb5U\xd0\x0f\x91\x90\xcc6w\xae\xf3\x14\xac\xd7?\xdc99\x92Y\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5W\xab\x949\xefP\xd27\xb5S\xf0%\b6JFj\\\x03\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5jx\x00(\x03\x9c\x81\xca\xf3{gu\xc6 \u7195Gd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5j\u04ae\xc6\xc8\xc3\xf1\x9e\x15\x15\xbb\xb7\u0751(RV\xb69\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5t\x13\x06\n\xf3\xf1N\xb4y\x06_\x1e\x9d\x19\xb3uz\xe8\u0309\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xb5uI\xbf\xbc\x9b\xdd\x18\xf76\xb2&P\xe4\x8as`\x1f\xa6\\\x89\x18-~L\xfd\xa08\x00\x00\xe0\x94\xb5w\xb6\xbe\xfa\x05N\x9c\x04\x04a\x85P\x94\xb0\x02\xd7\xf5{\u05ca\x18#\xf3\xcfb\x1d#@\x00\x00\u07d4\xb5{\x04\xfa#\xd1 ?\xae\x06\x1e\xacEB\xcb`\xf3\xa5v7\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\xb5\x87\f\xe3B\xd43C36s\x03\x8bGd\xa4n\x92_>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5\x87\xb4J,\xa7\x9eK\xc1\u074b\xfd\xd4: qP\xf2\xe7\xe0\x89\",\x8e\xb3\xfff@\x00\x00\u07d4\xb5\x89gm\x15\xa0DH4B0\xd4\xff'\xc9^\xdf\x12,I\x8965\u026d\xc5\u07a0\x00\x00\u0794\xb5\x8bR\x86^\xa5]\x806\xf2\xfa\xb2`\x98\xb3R\u0283~\x18\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xb5\x90k\n\u9881X\xe8\xacU\x0e9\xda\bn\xe3\x15v#\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5\xa4g\x96\x85\xfa\x14\x19l.\x920\xc8\xc4\xe3;\xff\xbc\x10\xe2\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xb5\xa5\x89\u075f@q\u06f6\xfb\xa8\x9b?]]\xae}\x96\xc1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5\xa6\x06\xf4\xdd\u02f9G\x1e\xc6\u007fe\x8c\xaf+\x00\xees\x02^\x89\xeaun\xa9*\xfct\x00\x00\u07d4\xb5\xadQW\u0769!\xe6\xba\xfa\u0350\x86\xaes\xae\x1fa\x1d?\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb5\xad\xd1\u701f}\x03\x06\x9b\xfe\x88;\n\x93\"\x10\xbe\x87\x12\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb5\xba)\x91|x\xa1\xd9\xe5\xc5\xc7\x13fl\x1eA\x1d\u007fi:\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb5\xc8\x16\xa8(<\xa4\xdfh\xa1\xa7=c\xbd\x80&\x04\x88\xdf\b\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb5\xca\xc5\xed\x03G}9\v\xb2g\xd4\xeb\xd4a\x01\xfb\xc2\xc3\u0689\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xb5\u037cA\x15@oR\u5a85\xd0\xfe\xa1p\u0497\x9c\u01fa\x89Hz\x9a0E9D\x00\x00\u0794\xb5\u0653M{)+\xcf`;(\x80t\x1e\xb7`(\x83\x83\xa0\x88\xe7\xc2Q\x85\x05\x06\x00\x00\u07d4\xb5\xddP\xa1]\xa3Ih\x89\nS\xb4\xf1?\xe1\xaf\b\x1b\xaa\xaa\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb5\xfa\x81\x84\xe4>\xd3\u0e2b\x91!da\xb3R\x8d\x84\xfd\t\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xb5\xfb~\xa2\xdd\xc1Y\x8bfz\x9dW\xdd9\xe8Z8\xf3]V\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb6\x00B\x97R\xf3\x99\xc8\r\a4tK\xae\n\x02.\xcag\u0189\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb6\x00\xfe\xabJ\xa9lSu\x04\xd9`W\"1Ai,\x19:\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xb6\x04|\u07d3-\xb3\xe4\x04_Iv\x12#AS~\u0556\x1e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb6\x15\xe9@\x14>\xb5\u007f\x87X\x93\xbc\x98\xa6\x1b=a\x8c\x1e\x8c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xb6\x1c4\xfc\xac\xdap\x1aZ\xa8p$Y\u07b0\u4b83\x8d\xf8\x8a\aiZ\x92\xc2\ro\xe0\x00\x00\xe0\x94\xb60d\xbd3U\xe6\xe0~-7p$\x12Z3wlJ\xfa\x8a\b7Z*\xbc\xca$@\x00\x00\u07d4\xb65\xa4\xbcq\xfb(\xfd\xd5\xd2\xc3\"\x98:V\u0084Bni\x89\t79SM(h\x00\x00\u07d4\xb6F\u07d8\xb4\x94BtkaR\\\x81\xa3\xb0K\xa3\x10bP\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xb6YA\xd4LP\xd2Ffg\r6Gf\xe9\x91\xc0.\x11\u0089 \x86\xac5\x10R`\x00\x00\xe0\x94\xb6[\u05c0\xc7CA\x15\x16 'VR#\xf4NT\x98\xff\x8c\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\xb6d\x11\xe3\xa0-\xed\xb7&\xfay\x10}\xc9\v\xc1\xca\xe6MH\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb6fu\x14.1\x11\xa1\xc2\xea\x1e\xb2A\x9c\xfaB\xaa\xf7\xa24\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xb6o\x92\x12K^c\x03XY\xe3\x90b\x88i\xdb\u07a9H^\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xb6rsJ\xfc\xc2$\xe2\xe6\t\xfcQ\xd4\xf0Ys'D\xc9H\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\xe0\x94\xb6w\x1b\v\xf3B\u007f\x9a\xe7\xa9>|.a\xeec\x94\x1f\xdb\b\x8a\x03\xfb&i)T\xbf\xc0\x00\x00\u07d4\xb6z\x80\xf1p\x19}\x96\xcd\xccJ\xb6\u02e6'\xb4\xaf\xa6\xe1,\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xb6\x88\x99\xe7a\rL\x93\xa255\xbc\xc4H\x94[\xa1fo\x1c\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb6\xa8)3\xc9\xea\u06bd\x98\x1e]m`\xa6\x81\x8f\xf8\x06\xe3k\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xb6\xaa\u02cc\xb3\v\xab*\xe4\xa2BF&\xe6\xe1+\x02\xd0F\x05\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xb6\xb3J&?\x10\xc3\xd2\xec\xeb\n\xccU\x9a{*\xb8\\\xe5e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb6\xbf\xe1\xc3\xef\x94\xe1\x84o\xb9\xe3\xac\xfe\x9bP\xc3\xe9\x06\x923\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xb6\xcdt2\xd5\x16\x1b\xe7\x97h\xadE\xde>Dz\a\x98 c\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb6\xceM\xc5`\xfcs\xdci\xfbzb\xe3\x88\xdb~r\xeavO\x894]\xf1i\xe9\xa3X\x00\x00\u07d4\xb6\xde\u03c2\x96\x98\x19\xba\x02\xde)\xb9\xb5\x93\xf2\x1bd\xee\xda\x0f\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\xe0\x94\xb6\xe6\xc3\"+ko\x9b\xe2\x87]*\x89\xf1'\xfbd\x10\x0f\xe2\x8a\x01\xb2\x1dS#\xcc0 \x00\x00\u07d4\xb6\xe8\xaf\xd9=\xfa\x9a\xf2\u007f9\xb4\xdf\x06\ag\x10\xbe\xe3\u07eb\x89\x01Z\xf1\u05cbX\xc4\x00\x00\xe0\x94\xb6\xf7\x8d\xa4\xf4\xd0A\xb3\xbc\x14\xbc[\xa5\x19\xa5\xba\f2\xf1(\x8a$}\xd3,?\xe1\x95\x04\x80\x00\xe0\x94\xb6\xfb9xbP\b\x14&\xa3B\xc7\rG\xeeR\x1e[\xc5c\x8a\x03-&\xd1.\x98\v`\x00\x00\u07d4\xb7\r\xba\x93\x91h+J6Nw\xfe\x99%c\x01\xa6\xc0\xbf\x1f\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\x16#\xf3Q\a\xcft1\xa8?\xb3\xd2\x04\xb2\x9e\u0c67\xf4\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xb7\x1a\x13\xba\x8e\x95\x16{\x803\x1bR\u059e7\x05O\xe7\xa8&\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\x1bb\xf4\xb4H\xc0+\x12\x01\xcb^9J\xe6'\xb0\xa5`\xee\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xb7\" \xad\xe3d\xd06\x9f--\xa7\x83\xcaGM{\x9b4\u0389\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\xe0\x94\xb7#\r\x1d\x1f\xf2\xac\xa3f\x969\x14\xa7\x9d\xf9\xf7\xc5\xea,\x98\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\xb7$\n\U000af433<\b\xae\x97d\x10>5\xdc\xe3c\x84(\x8a\x01\xca\xdd/\xe9hnc\x80\x00\u07d4\xb7'\xa9\xfc\x82\xe1\xcf\xfc\\\x17_\xa1HZ\x9b\xef\xa2\u037d\u04496'\xe8\xf7\x127<\x00\x00\u07d4\xb7,*\x01\x1c\r\xf5\x0f\xbbn(\xb2\n\xe1\xaa\xd2\x17\x88g\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb78-7\xdb\x03\x98\xacrA\f\xf9\x81=\xe9\xf8\xe1\uc36d\x8966\xc2^f\xec\xe7\x00\x00\u07d4\xb7;O\xf9\x9e\xb8\x8f\u061b\vmW\xa9\xbc3\x8e\x88o\xa0j\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xb7=jwU\x9c\x86\xcfet$)\x039K\xac\xf9n5p\x89\x04\xf1\xa7|\xcd;\xa0\x00\x00\u07d4\xb7Cr\xdb\xfa\x18\x1d\xc9$/9\xbf\x1d71\xdf\xfe+\xda\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7G\x9d\xabP\"\xc4\xd5\u06ea\xf8\xde\x17\x1bN\x95\x1d\u0464W\x89\x04V9\x18$O@\x00\x00\u07d4\xb7I\xb5N\x04\u0571\x9b\xdc\xed\xfb\x84\xdaw\x01\xabG\x8c'\xae\x89\x91Hx\xa8\xc0^\xe0\x00\x00\u07d4\xb7N\xd2f`\x01\xc1c3\xcfz\xf5\x9eJ=H`6;\x9c\x89\n~\xbd^Cc\xa0\x00\x00\u07d4\xb7QI\xe1\x85\xf6\xe3\x92pWs\x90s\xa1\x82*\xe1\xcf\r\xf2\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xb7S\xa7_\x9e\xd1\v!d:\n=\xc0Qz\xc9k\x1a@h\x89\x15\xc8\x18[,\x1f\xf4\x00\x00\xe0\x94\xb7V\xadR\xf3\xbft\xa7\xd2LgG\x1e\b\x87Ci6PL\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xb7Wn\x9d1M\xf4\x1e\xc5Pd\x94):\xfb\x1b\xd5\xd3\xf6]\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb7X\x89o\x1b\xaa\x86O\x17\xeb\xed\x16\xd9S\x88o\xeeh\xaa\xe6\x8965\u026d\xc5\u07a0\x00\x00\u0794\xb7h\xb5#N\xba:\x99h\xb3Mm\xdbH\x1c\x84\x19\xb3e]\x88\xcf\xceU\xaa\x12\xb3\x00\x00\u07d4\xb7\x82\xbf\xd1\xe2\xdep\xf4gdo\x9b\xc0\x9e\xa5\xb1\xfc\xf4P\xaf\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xb7\xa2\xc1\x03r\x8bs\x05\xb5\xaen\x96\x1c\x94\xee\x99\xc9\xfe\x8e+\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xb7\xa3\x1a|8\xf3\xdb\t2.\xae\x11\xd2'!A\xea\"\x99\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7\xa6y\x1c\x16\xebN!b\xf1Ke7\xa0+=c\xbf\xc6\x02\x89*Rc\x91\xac\x93v\x00\x00\u07d4\xb7\xa7\xf7|4\x8f\x92\xa9\xf1\x10\fk\xd8)\xa8\xacm\u007f\u03d1\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xb7\xc0w\x94ft\xba\x93A\xfbLtz]P\xf5\xd2\xdad\x15\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xb7\xc0\xd0\xcc\vM4-@b\xba\xc6$\xcc\xc3\xc7\f\xc6\xda?\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xb7\xc9\xf1+\x03\x8esCm\x17\xe1\xc1/\xfe\x1a\xec\u0373\xf5\x8c\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\xb7\xcck\x1a\xcc2\u0632\x95\xdfh\xed\x9d^`\xb8\xf6L\xb6{\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xb7\xcehK\t\xab\xdaS8\x9a\x87Si\xf7\x19X\xae\xac;\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\xb7\xd1.\x84\xa2\xe4\u01264Z\xf1\xdd\x1d\xa9\xf2PJ*\x99n\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xb7\xd2R\xee\x94\x02\xb0\xee\xf1D)_\x0ei\xf0\xdbXl\bq\x89#\xc7W\a+\x8d\xd0\x00\x00\xe0\x94\xb7\u0541\xfe\n\xf1\xec8?;\xce\x00\xaf\x91\x99\xf3\xcf_\xe0\xcc\xe2\x8c\xd1J\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\xb8R\x18\xf3B\xf8\x01.\u069f'Nc\xce!R\xb2\xdc\xfd\xab\x89\xa8\r$g~\xfe\xf0\x00\x00\u07d4\xb8UP\x10wn<\\\xb3\x11\xa5\xad\xee\xfe\x9e\x92\xbb\x9ad\xb9\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xb8_&\xdd\x0er\xd9\u009e\xba\xf6\x97\xa8\xafwG,+X\xb5\x8a\x02\x85\x19\xac\xc7\x19\fp\x00\x00\u07d4\xb8_\xf0>{_\xc4\"\x98\x1f\xae^\x99A\xda\xcb\u06bau\x84\x89Hz\x9a0E9D\x00\x00\xe0\x94\xb8f\a\x02\x1bb\xd3@\xcf&R\xf3\xf9_\xd2\xdcgi\x8b\u07ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xb8}\xe1\xbc\u0492i\xd5!\xb8v\x1c\u00dc\xfbC\x19\xd2\xea\u054965\u026d\xc5\u07a0\x00\x00\u07d4\xb8\u007fSv\xc2\xde\vl\xc3\xc1y\xc0`\x87\xaaG=kFt\x89Hz\x9a0E9D\x00\x00\u07d4\xb8\x84\xad\u060d\x83\xdcVJ\xb8\xe0\xe0,\xbd\xb69\x19\xae\xa8D\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\x8a7\xc2\u007fx\xa6\x17\xd5\xc0\x91\xb7\u0577:7a\xe6_*\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\x94x\"\u056c\u79ad\x83&\xe9T\x96\"\x1e\v\xe6\xb7=\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb8\x9c\x03n\xd7\u0112\x87\x99!\xbeA\xe1\f\xa1i\x81\x98\xa7L\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xb8\x9fF2\xdfY\t\xe5\x8b*\x99d\xf7O\xeb\x9a;\x01\xe0\u014a\x04\x88u\xbc\xc6\xe7\xcb\xeb\x80\x00\u07d4\xb8\xa7\x9c\x84\x94^G\xa9\xc3C\x86\x83\u05b5\x84,\xffv\x84\xb1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xb8\xa9y5'Y\xba\t\xe3Z\xa5\x93]\xf1u\xbf\xf6x\xa1\b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xb8\xab9\x80[\xd8!\x18Ol\xbd=$s4{\x12\xbf\x17\\\x89\x06hZ\xc1\xbf\xe3,\x00\x00\xe0\x94\xb8\xac\x11}\x9f\r\xba\x80\x90\x14E\x82:\x92\x11\x03\xa51o\x85Zew\x9d\x1b\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4\xb9\xe9\f\x11\x92\xb3\xd5\xd3\xe3\xab\a\x00\xf1\xbfe_]\xd44z\x89\x1b\x19\xe5\vD\x97|\x00\x00\u07d4\xb9\xfd83\xe8\x8e|\xf1\xfa\x98y\xbd\xf5Z\xf4\xb9\x9c\xd5\xce?\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xba\x02I\xe0\x1d\x94[\xef\x93\xee^\xc6\x19%\xe0<\\\xa5\t\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xba\x0f9\x02;\xdb)\xeb\x18b\xa9\xf9\x05\x9c\xab]0nf/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\x10\xf2vB\x90\xf8uCCr\xf7\x9d\xbfq8\x01\u02ac\x01\x893\xc5I\x901r\f\x00\x00\u07d4\xba\x151\xfb\x9ey\x18\x96\xbc\xf3\xa8\x05X\xa3Y\xf6\xe7\xc1D\xbd\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xba\x17m\xbe2I\xe3E\xcdO\xa9g\xc0\xed\x13\xb2LG\u5189\x15\xae\xf9\xf1\xc3\x1c\u007f\x00\x00\xe0\x94\xba\x1f\x0e\x03\u02da\xa0!\xf4\xdc\xeb\xfa\x94\xe5\u0209\xc9\u01fc\x9e\x8a\x06\u0450\xc4u\x16\x9a \x00\x00\u07d4\xba\x1f\xca\xf2#\x93~\xf8\x9e\x85gU\x03\xbd\xb7\xcaj\x92\x8bx\x89\"\xb1\xc8\xc1\"z\x00\x00\x00\xe0\x94\xba$\xfcCgS\xa79\xdb,\x8d@\xe6\xd4\xd0LR\x8e\x86\xfa\x8a\x02\xc0\xbb=\xd3\fN \x00\x00\u07d4\xbaB\xf9\xaa\xceL\x18E\x04\xab\xf5BWb\xac\xa2oq\xfb\u0709\x02\a\a}\u0627\x9c\x00\x00\u07d4\xbaF\x9a\xa5\u00c6\xb1\x92\x95\u0521\xb5G;T\x03S9\f\x85\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbad@\xae\xb3s{\x8e\xf0\xf1\xaf\x9b\f\x15\xf4\xc2\x14\xff\xc7\u03c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbam1\xb9\xa2a\xd6@\xb5\u07a5\x1e\xf2\x16,1\t\xf1\uba0a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xbap\xe8\xb4u\x9c\f<\x82\xcc\x00\xacN\x9a\x94\xdd[\xaf\xb2\xb8\x890C\xfa3\xc4\x12\xd7\x00\x00\u07d4\xba\x8ac\xf3\xf4\r\u4a03\x88\xbcP!/\xea\x8e\x06O\xbb\x86\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\x8eF\u059d.#C\xd8l`\xd8,\xf4, A\xa0\xc1\u0089\x05k\xc7^-c\x10\x00\x00\u07d4\xba\xa4\xb6L+\x15\xb7\x9f_ BF\xfdp\xbc\xbd\x86\xe4\xa9*\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xba\u0212,J\xcc},\xb6\xfdY\xa1N\xb4\\\xf3\xe7\x02!K\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xba\xd25\xd5\b]\u01f0h\xa6|A&w\xb0>\x186\x88L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xba\xd4B^\x17\x1c>r\x97^\xb4j\xc0\xa0\x15\xdb1Z]\x8f\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xba\xdc*\xef\x9fYQ\xa8\u05cak5\xc3\u0433\xa4\xe6\xe2\xe79\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xba\xdeCY\x9e\x02\xf8OL0\x14W\x1c\x97k\x13\xa3le\xab\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xba\xe9\xb8/r\x99c\x14\be\x9d\xd7N\x89\x1c\xb8\xf3\x86\x0f\xe5\x89j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xbb\x03f\xa7\u03fd4E\xa7\r\xb7\xfeZ\xe3H\x85uO\xd4h\x8a\x01M\xef,B\xeb\xd6@\x00\x00\u07d4\xbb\aj\xac\x92 \x80i\xea1\x8a1\xff\x8e\xeb\x14\xb7\xe9\x96\xe3\x89\b\x13\xcaV\x90m4\x00\x00\u07d4\xbb\bW\xf1\xc9\x11\xb2K\x86\u0227\x06\x81G?\u6aa1\xcc\xe2\x89\x05k\xc7^-c\x10\x00\x00\u0794\xbb\x19\xbf\x91\u02edt\xcc\xeb_\x81\x1d\xb2~A\x1b\xc2\xea\x06V\x88\xf4?\xc2\xc0N\xe0\x00\x00\xe0\x94\xbb'\u01a7\xf9\x10uGZ\xb2)a\x90@\xf8\x04\xc8\xeczj\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xbb7\x1cr\xc9\xf01l\xea+\xd9\xc6\xfb\xb4\a\x9ewT)\xef\x89_h\xe8\x13\x1e\u03c0\x00\x00\xe0\x94\xbb;\x01\v\x18\xe6\xe2\xbe\x115\x87\x10&\xb7\xba\x15\xea\x0f\xde$\x8a\x02 |\x800\x9bwp\x00\x00\xe0\x94\xbb;\x90\x05\xf4o\xd2\xca;0\x16%\x99\x92\x8cw\xd9\xf6\xb6\x01\x8a\x01\xb1\xae\u007f+\x1b\xf7\xdb\x00\x00\u07d4\xbb?\xc0\xa2\x9c\x03Mq\b\x12\xdc\xc7u\xc8\u02b9\u048diu\x899\xd4\xe8D\xd1\xcf_\x00\x00\u07d4\xbbH\xea\xf5\x16\xce-\xec>A\xfe\xb4\xc6y\xe4\x95vA\x16O\x89\xcf\x15&@\xc5\xc80\x00\x00\u07d4\xbbKJKT\x80p\xffAC,\x9e\b\xa0\xcao\xa7\xbc\x9fv\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\u07d4\xbbV\xa4\x04r<\xff \xd0hT\x88\xb0Z\x02\xcd\xc3Z\xac\xaa\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbba\x8e%\"\x1a\u0667@\xb2\x99\xed\x14\x06\xbc94\xb0\xb1m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbba\xa0K\xff\xd5|\x10G\rE\u00d1\x03\xf6FP4v\x16\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbbh#\xa1\xbd\x81\x9f\x13QU8&J-\xe0R\xb4D\"\b\x89\x01ch\xffO\xf9\xc1\x00\x00\u07d4\xbbl(J\xac\x8ai\xb7\\\u0770\x0f(\xe1EX;V\xbe\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xbbu\xcbPQ\xa0\xb0\x94KFs\xcau*\x97\x03\u007f|\x8c\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbb\x99;\x96\xee\x92Z\xda}\x99\u05c6W=?\x89\x18\f\u3a89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xa3\u0180\x04$\x8eH\x95s\xab\xb2t6w\x06k$\u0227\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbb\xa4\xfa\xc3\xc4 9\xd8(\xe7B\xcd\xe0\xef\xff\xe7t\x94\x1b9\x89lj\u04c2\xd4\xfba\x00\x00\u07d4\xbb\xa8\xab\"\xd2\xfe\xdb\xcf\xc6?hL\b\xaf\xdf\x1c\x17P\x90\xb5\x89\x05_)\xf3~N;\x80\x00\u07d4\xbb\xa9v\xf1\xa1!_u\x12\x87\x18\x92\xd4_pH\xac\xd3V\u0209lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbb\xab\x00\v\x04\b\xed\x01Z7\xc0GG\xbcF\x1a\xb1N\x15\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xbb\xab\xf6d;\xebK\xd0\x1c\x12\v\xd0Y\x8a\t\x87\xd8)g\u0449\xb52\x81x\xad\x0f*\x00\x00\u07d4\xbb\xb4\xee\x1d\x82\xf2\xe1VD,\xc938\xa2\xfc(o\xa2\x88d\x89JD\x91\xbdm\xcd(\x00\x00\u07d4\xbb\xb5\xa0\xf4\x80,\x86H\x00\x9e\x8ai\x98\xaf5,\u0787TO\x89\x05-T(\x04\xf1\xce\x00\x00\u07d4\xbb\xb6C\xd2\x18{6J\xfc\x10\xa6\xfd6\x8d}U\xf5\r\x1a<\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbb\xb8\xff\xe4?\x98\u078e\xae\x18F#\xaeRd\xe4$\u0438\u05c9\x05\xd5?\xfd\xe9(\b\x00\x00\u07d4\xbb\xbdn\u02f5u(\x91\xb4\u03b3\xcc\xe7:\x8fGpY7o\x89\x01\xf3\x99\xb1C\x8a\x10\x00\x00\u07d4\xbb\xbf9\xb1\xb6y\x95\xa4\"APO\x97\x03\u04a1JQV\x96\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xbb\xc8\xea\xffc~\x94\xfc\u014d\x91\xdb\\\x89\x12\x1d\x06\xe1/\xff\x98\x80\x00\u07d4\xbc\u065e\xdc!`\xf2\x10\xa0^:\x1f\xa0\xb0CL\xed\x00C\x9b\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbc\u07ec\xb9\xd9\x02<4\x17\x18.\x91\x00\xe8\xea\x1d73\x93\xa3\x89\x034-`\xdf\xf1\x96\x00\x00\u07d4\xbc\xe1>\"2*\u03f3U\xcd!\xfd\r\xf6\f\xf9:\xdd&\u0189\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xbc\xe4\x04u\xd3E\xb0q-\xeep=\x87\xcdvW\xfc\u007f;b\x8a\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\xbc\xed\xc4&|\u02c9\xb3\x1b\xb7d\xd7!\x11q\x00\x8d\x94\xd4M\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbc\xfc\x98\xe5\xc8+j\xdb\x18\n?\xcb\x12\v\x9av\x90\xc8j?\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbd\x04;g\xc6>`\xf8A\xcc\xca\x15\xb1)\xcd\xfee\x90\xc8\xe3\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbd\x04\u007f\xf1\xe6\x9c\u01b2\x9a\xd2d\x97\xa9\xa6\xf2z\x90?\xc4\u0749.\xe4IU\b\x98\xe4\x00\x00\u07d4\xbd\b\xe0\xcd\xde\xc0\x97\xdby\x01\ua05a=\x1f\xd9\u0789Q\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbd\t\x12l\x89\x1cJ\x83\x06\x80Y\xfe\x0e\x15ylFa\xa9\xf4\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xbd\f\\\u05d9\xeb\u0106B\xef\x97\xd7N\x8eB\x90d\xfe\u4489\x11\xac(\xa8\xc7)X\x00\x00\u07d4\xbd\x17\xee\xd8+\x9a%\x92\x01\x9a\x1b\x1b<\x0f\xba\xd4\\@\x8d\"\x89\r\x8drkqw\xa8\x00\x00\u07d4\xbd\x18\x037\v\u0771)\xd29\xfd\x16\xea\x85&\xa6\x18\x8a\u5389\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xbd+p\xfe\xcc7d\x0fiQO\xc7\xf3@IF\xaa\xd8k\x11\x89A\rXj \xa4\xc0\x00\x00\u07d4\xbd0\x97\xa7\x9b<\r.\xbf\xf0\xe6\xe8j\xb0\xed\xad\xbe\xd4p\x96\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xbd2]@)\xe0\xd8r\x9fm9\x9cG\x82$\xae\x9ez\xe4\x1e\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xbdC*9\x16$\x9bG$):\xf9\x14nI\xb8(\n\u007f*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbdG\xf5\xf7n;\x93\x0f\xd9HR\t\xef\xa0\xd4v=\xa0uh\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbdK`\xfa\xect\n!\xe3\a\x13\x91\xf9j\xa54\xf7\xc1\xf4N\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xbdK\u0571\"\xd8\xef{|\x8f\x06gE\x03 \xdb!\x16\x14.\x89 \x86\xac5\x10R`\x00\x00\u07d4\xbdQ\xee.\xa1C\u05f1\u05b7~~D\xbd\xd7\xda\x12\U00105b09G~\x06\u0332\xb9(\x00\x00\u07d4\xbdY\tN\aO\x8dy\x14*\xb1H\x9f\x14\x8e2\x15\x1f \x89\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbdZ\x8c\x94\xbd\x8b\xe6G\x06D\xf7\f\x8f\x8a3\xa8\xa5\\cA\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbd^G:\xbc\xe8\xf9zi2\xf7|/\xac\xaf\x9c\xc0\xa0\x05\x14\x89<\x92X\xa1\x06\xa6\xb7\x00\x00\u07d4\xbd_F\u02ab,=K(\x93\x96\xbb\xb0\u007f *\x06\x11>\xd4\xc3\xfb\xa1\xa8\x91;\x19@~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\x9eV\xe9\x02\xf4\xbe\x1f\xc8v\x8d\x808\xba\xc6>*\u02ff\x8e\x8965f3\xeb\xd8\xea\x00\x00\u07d4\xbd\xa4\xbe1~~K\xed\x84\xc0I^\xee2\xd6\a\xec8\xcaR\x89}2'yx\xefN\x80\x00\u07d4\xbd\xb6\v\x82:\x11s\xd4Z\a\x92$_\xb4\x96\xf1\xfd3\x01\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xba\xf6CM@\xd65[\x1e\x80\xe4\f\u012b\x9ch\xd9a\x16\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xbd\xc0,\xd43\f\x93\xd6\xfb\xdaOm\xb2\xa8]\xf2/C\xc23\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xc4aF+c\"\xb4b\xbd\xb3?\"y\x9e\x81\b\xe2A}\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xbd\xc79\xa6\x99p\v.\x8e,JL{\x05\x8a\x0eQ=\u07be\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbd\xc7Hs\xaf\x92+\x9d\xf4t\x85;\x0f\xa7\xff\v\xf8\xc8&\x95\x89\xd8\xc9F\x00c\xd3\x1c\x00\x00\u07d4\xbd\xca*\x0f\xf3E\x88\xafb_\xa8\xe2\x8f\xc3\x01Z\xb5\xa3\xaa\x00\x89~\xd7?w5R\xfc\x00\x00\u07d4\xbd\xd3%N\x1b:m\xc6\xcc,i}Eq\x1a\xca!\xd5\x16\xb2\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbd\u07e3M\x0e\xbf\x1b\x04\xafS\xb9\x9b\x82IJ\x9e=\x8a\xa1\x00\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xbd\xe4\xc7?\x96\x9b\x89\xe9\u03aef\xa2\xb5\x18DH\x0e\x03\x8e\x9a\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbd\xe9xj\x84\xe7[H\xf1\x8erm\u05cdp\xe4\xaf>\xd8\x02\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4\xbd\xed\x11a/\xb5\xc6\u0699\xd1\xe3\x0e2\v\xc0\x99Tf\x14\x1e\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xbd\xed~\a\xd0q\x1ehM\xe6Z\u0232\xabW\xc5\\\x1a\x86E\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\xbd\xf6\x93\xf83\xc3\xfeG\x17S\x18G\x88\xebK\xfeJ\xdc?\x96\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbd\xf6\xe6\x8c\f\xd7X@\x80\xe8G\xd7,\xbb#\xaa\xd4j\xeb\x1d\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbe\n/8_\t\xdb\xfc\xe9g2\xe1+\xb4\n\xc3I\x87\x1b\xa8\x89WL\x11^\x02\xb8\xbe\x00\x00\u07d4\xbe\f*\x80\xb9\xde\bK\x17(\x94\xa7l\xf4szOR\x9e\x1a\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xbe\x1c\xd7\xf4\xc4r\a\th\xf3\xbd\xe2h6k!\xee\xea\x83!\x89\xe9\x1a|\u045f\xa3\xb0\x00\x00\u07d4\xbe#F\xa2\u007f\xf9\xb7\x02\x04OP\r\xef\xf2\xe7\xff\xe6\x82EA\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xbe$q\xa6\u007f`G\x91\x87r\xd0\xe3h9%^\xd9\u0591\xae\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xbe+\"\x80R7h\xea\x8a\xc3\\\xd9\xe8\x88\xd6\nq\x93\x00\u0509lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbe+2nx\xed\x10\xe5P\xfe\xe8\xef\xa8\xf8\a\x03\x96R/Z\x8a\bW\xe0\xd6\xf1\xdav\xa0\x00\x00\xe0\x94\xbe0Zyn3\xbb\xf7\xf9\xae\xaee\x12\x95\x90f\xef\xda\x10\x10\x8a\x02M\xceT\xd3J\x1a\x00\x00\x00\u07d4\xbeG\x8e\x8e=\xdek\xd4\x03\xbb-\x1ce|C\x10\xee\x19'#\x89\x1a\xb2\xcf|\x9f\x87\xe2\x00\x00\u07d4\xbeN}\x98?.*ck\x11\x02\xecp9\xef\xeb\xc8B\u9349\x03\x93\xef\x1aQ'\xc8\x00\x00\u07d4\xbeO\xd0sap\"\xb6\u007f\\\x13I\x9b\x82\u007fv69\xe4\xe3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbeRZ3\xea\x91aw\xf1r\x83\xfc\xa2\x9e\x8b5\v\u007fS\v\x89\x8f\x01\x9a\xafF\xe8x\x00\x00\u07d4\xbeS2/C\xfb\xb5\x84\x94\xd7\xcc\xe1\x9d\xda'+$P\xe8'\x89\n\xd7\u03afB\\\x15\x00\x00\u07d4\xbeS\x82F\xddNo\f \xbfZ\xd17<;F:\x13\x1e\x86\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbeZ`h\x99\x98c\x9a\xd7[\xc1\x05\xa3qt>\xef\x0fy@\x89\x1b2|s\xe1%z\x00\x00\u07d4\xbe\\\xba\x8d7By\x86\xe8\xca&\x00\xe8X\xbb\x03\xc3YR\x0f\x89\xa00\xdc\xeb\xbd/L\x00\x00\u07d4\xbe`\x03~\x90qJK\x91~a\xf1\x93\xd84\x90g\x03\xb1:\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xbec:77\xf6\x849\xba\xc7\xc9\nR\x14 X\ue38ao\x894\n\xad!\xb3\xb7\x00\x00\x00\xe0\x94\xbee\x9d\x85\xe7\xc3O\x883\xea\u007fH\x8d\xe1\xfb\xb5\xd4\x14\x9b\xef\x8a\x01\xeb\xd2:\xd9\u057br\x00\x00\u07d4\xbes'M\x8cZ\xa4J<\xbe\xfc\x82c\xc3{\xa1!\xb2\n\u04c9\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xbe\x86\u0430C\x84\x19\u03b1\xa081\x927\xbaR\x06\xd7.F\x8964\xfb\x9f\x14\x89\xa7\x00\x00\u07d4\xbe\x8d\u007f\x18\xad\xfe]l\xc7u9I\x89\xe1\x93\f\x97\x9d\x00}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbe\x91\x86\xc3JRQJ\xbb\x91\a\x86\x0fgO\x97\xb8!\xbd[\x89\x1b\xa0\x1e\xe4\x06\x03\x10\x00\x00\u07d4\xbe\x93W\x93\xf4[p\xd8\x04]&T\xd8\xdd:\xd2K[a7\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xbe\x98\xa7\u007f\xd4\x10\x97\xb3OY\xd7X\x9b\xaa\xd0!e\x9f\xf7\x12\x890\xca\x02O\x98{\x90\x00\x00\u07d4\xbe\x9b\x8c4\xb7\x8e\xe9G\xff\x81G.\xdaz\xf9\xd2\x04\xbc\x84f\x89\b!\xab\rD\x14\x98\x00\x00\u07d4\xbe\xa0\r\xf1pg\xa4:\x82\xbc\x1d\xae\xca\xfbl\x140\x0e\x89\xe6\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xbe\xa0\xaf\xc9:\xae!\b\xa3\xfa\xc0Yb;\xf8o\xa5\x82\xa7^\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xbe\xb35\x8cP\u03dfu\xff\xc7mD<,\u007fU\aZ\x05\x89\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xbe\xb4\xfd1UYC`E\u0739\x9dI\xdc\xec\x03\xf4\fB\u0709lk\x93[\x8b\xbd@\x00\x00\u07d4\xbe\xc2\xe6\xde9\xc0|+\xaeUj\u03fe\xe2\xc4r\x8b\x99\x82\xe3\x89\x1f\x0f\xf8\xf0\x1d\xaa\xd4\x00\x00\u07d4\xbe\xc6d\x0fI\t\xb5\x8c\xbf\x1e\x80cB\x96\x1d`u\x95\tl\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xbe\xc8\xca\xf7\xeeIF\x8f\xeeU.\xff:\xc5#N\xb9\xb1}B\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbe\xce\xf6\x1c\x1cD+\xef|\xe0Ks\xad\xb2I\xa8\xba\x04~\x00\x896;V\u00e7T\xc8\x00\x00\u0794\xbe\xd4d\x9d\xf6F\u2052)\x03-\x88hUo\xe1\xe0S\u04c8\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\xbe\xd4\xc8\xf0\x06\xa2|\x1e_|\xe2\x05\xdeu\xf5\x16\xbf\xb9\xf7d\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xbe\xe8\u0430\bB\x19T\xf9-\x00\r9\x0f\xb8\xf8\xe6X\xea\xee\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbe\xec\u05af\x90\f\x8b\x06J\xfc\xc6\a?-\x85\u055a\xf1\x19V\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xbe\xef\x94!8y\xe0&\"\x14+\xeaa)\tx\x93\x9a`\u05ca\x016\x85{2\xad\x86\x04\x80\x00\xe0\x94\xbe\xf0}\x97\xc3H\x1f\x9dj\xee\x1c\x98\xf9\xd9\x1a\x18\n2D+\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xbe\xfbD\x8c\f_h?\xb6~\xe5p\xba\xf0\xdbV\x86Y\x97Q\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xbf\x05\a\f,4!\x93\x11\xc4T\x8b&\x14\xa48\x81\r\xedm\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbf\x05\xff^\xcf\r\xf2\u07c8wY\xfb\x82t\xd928\xac&}\x89+^:\xf1k\x18\x80\x00\x00\xe0\x94\xbf\t\xd7pH\xe2p\xb6b3\x0e\x94\x86\xb3\x8bC\xcdx\x14\x95\x8a\\S\x9b{\xf4\xff(\x80\x00\x00\u07d4\xbf\x17\xf3\x97\xf8\xf4o\x1b\xaeE\u0447\x14\x8c\x06\xee\xb9Y\xfaM\x896I\u0156$\xbb0\x00\x00\u07d4\xbf\x186A\xed\xb8\x86\xce`\xb8\x19\x02a\xe1OB\xd9<\xce\x01\x89\x01[5W\xf1\x93\u007f\x80\x00\u07d4\xbf*\xeaZ\x1d\xcfn\u04f5\xe829D\xe9\x83\xfe\xdf\u046c\xfb\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xbf@\x96\xbcT}\xbf\xc4\xe7H\t\xa3\x1c\x03\x9e{8\x9d^\x17\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xbfI\xc1H\x981eg\u0637\t\xc2\xe5\x05\x94\xb3f\xc6\u04cc\x89'\xbf8\xc6TM\xf5\x00\x00\u07d4\xbfLs\xa7\xed\xe7\xb1d\xfe\a!\x14\x846T\xe4\xd8x\x1d\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xbfP\xce.&K\x9f\xe2\xb0h0az\xed\xf5\x02\xb25\x1bE\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbfY\xae\xe2\x81\xfaC\xfe\x97\x19CQ\xa9\x85~\x01\xa3\xb8\x97\xb2\x89 \x86\xac5\x10R`\x00\x00\u07d4\xbfh\u048a\xaf\x1e\xee\xfe\xf6F\xb6^\x8c\xc8\u0450\xf6\xc6\u069c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xbfi%\xc0\aQ\x00\x84@\xa6s\x9a\x02\xbf+l\u06ab^:\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xbfw\x01\xfcb%\u0561x\x15C\x8a\x89A\xd2\x1e\xbc]\x05\x9d\x89e\xea=\xb7UF`\x00\x00\u07d4\xbf\x8b\x80\x05\xd66\xa4\x96d\xf7Bu\xefBC\x8a\xcde\xac\x91\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbf\x92A\x8a\fl1$M\"\x02`\xcb>\x86}\u05f4\xefI\x89\x05i\x00\xd3<\xa7\xfc\x00\x00\u07d4\xbf\x9a\xcdDE\xd9\xc9UF\x89\u02bb\xba\xb1\x88\x00\xff\x17A\u008965\u026d\xc5\u07a0\x00\x00\u07d4\xbf\x9f'\x1fz~\x12\xe3m\xd2\xfe\x9f\xac\xeb\xf3\x85\xfeaB\xbd\x89\x03f\xf8O{\xb7\x84\x00\x00\u07d4\xbf\xa8\xc8X\xdf\x10,\xb1$!\x00\x8b\n1\xc4\xc7\x19\n\xd5`\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xbf\xae\xb9\x10ga}\u03cbD\x17+\x02\xafaVt\x83]\xba\x89\b\xb5\x9e\x88H\x13\b\x80\x00\xe0\x94\xbf\xb0\xea\x02\xfe\xb6\x1d\xec\x9e\"\xa5\a\tY3\x02\x99\xc40r\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xbf\xbc\xa4\x18\xd3R\x9c\xb3\x93\b\x10b\x03*n\x11\x83\u01b2\u070a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xbf\xbe\x05\u831c\xbb\xcc\x0e\x92\xa4\x05\xfa\xc1\xd8]\xe2H\xee$\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xbf\xbf\xbc\xb6V\u0099+\xe8\xfc\u0782\x19\xfb\xc5J\xad\u055f)\x8a\x02\x1e\x18\xd2\xc8!\xc7R\x00\x00\u07d4\xbf\xc5z\xa6f\xfa\u239f\x10zI\xcbP\x89\xa4\xe2!Q\u074965\u026d\xc5\u07a0\x00\x00\u07d4\xbf\u02d70$c\x04p\r\xa9\vAS\xe7\x11Ab.\x1cA\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xbf\xd9<\x90\u009c\a\xbc_\xb5\xfcI\xae\xeaU\xa4\x0e\x13O5\x8a\x05\xed\xe2\x0f\x01\xa4Y\x80\x00\x00\xe0\x94\xbf\xe3\xa1\xfcn$\xc8\xf7\xb3%\x05`\x99\x1f\x93\u02e2\u03c0G\x8a\x10\xf0\xcf\x06M\u0552\x00\x00\x00\u07d4\xbf\u6f30\xf0\xc0xRd3$\xaa]\xf5\xfdb%\xab\xc3\u0289\x04\t\xe5+H6\x9a\x00\x00\u07d4\xbf\xf5\xdfv\x994\xb8\x94<\xa9\x13}\x0e\xfe\xf2\xfen\xbb\xb3N\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xbf\xfbi)$\x1fx\x86\x93'>p\"\xe6\x0e>\xab\x1f\xe8O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\x06O\x1d\x94t\xab\x91]V\x90l\x9f\xb3 \xa2\xc7\t\x8c\x9b\x89\x13h?\u007f<\x15\xd8\x00\x00\u07d4\xc0\a\xf0\xbd\xb6\xe7\x00\x92\x02\xb7\xaf>\xa9\t\x02i|r\x14\x13\x89\xa2\xa0\xe4>\u007f\xb9\x83\x00\x00\u07d4\xc0\n\xb0\x80\xb6C\xe1\u00ba\xe3c\xe0\u0455\xde.\xff\xfc\x1cD\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u0794\xc0 wD\x9a\x13Jz\xd1\xef~M\x92z\xff\xec\ueb75\xae\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xc0$q\xe3\xfc.\xa0S&\x15\xa7W\x1dI2\x89\xc1<6\xef\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0-n\xad\xea\xcf\x1bx\xb3\u0285\x03\\c{\xb1\xce\x01\xf4\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc03\xb12Z\n\xf4Tr\xc2U'\x85;\x1f\x1c!\xfa5\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xc03\xbe\x10\xcbHa;\xd5\xeb\xcb3\xedI\x02\xf3\x8bX0\x03\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc04[3\xf4\x9c\xe2\u007f\xe8,\xf7\xc8M\x14\x1ch\xf5\x90\xcev\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc0=\xe4*\x10\x9bezd\xe9\"$\xc0\x8d\xc1'^\x80\u0672\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0@i\u07f1\x8b\tlxg\xf8\xbe\xe7zm\xc7Gz\xd0b\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xc0A?Z|-\x9aK\x81\b(\x9e\xf6\xec\xd2qx\x15$\xf4\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xc0C\xf2E-\u02d6\x02\xefb\xbd6\x0e\x03=\xd29q\xfe\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc0OK\xd4\x04\x9f\x04F\x85\xb8\x83\xb6)Y\xaec\x1df~5\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\xc0V\u053dk\xf3\u02ec\xace\xf8\xf5\xa0\xe3\x98\v\x85'@\xae\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xc0[t\x06 \xf1s\xf1nRG\x1d\u00cb\x9cQJ\v\x15&\x89\a\x96\xe3\xea?\x8a\xb0\x00\x00\u07d4\xc0i\xef\x0e\xb3B\x99\xab\xd2\xe3-\xab\xc4yD\xb2r3H$\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\xc0l\xeb\xbb\xf7\xf5\x14\x9af\xf7\xeb\x97k>G\xd5e\x16\xda/\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc0r^\u00bd\xc3:\x1d\x82`q\u07a2\x9db\xd48Z\x8c%\x8a\b\xa0\x85\x13F:\xa6\x10\x00\x00\u07d4\xc0~8g\xad\xa0\x96\x80z\x05\x1al\x9c4\xcc;?J\xd3J\x89`\xf0f \xa8IE\x00\x00\u07d4\xc0\x89^\xfd\x05m\x9a:\x81\xc3\xdaW\x8a\xda1\x1b\xfb\x93V\u03c9\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc0\x90\xfe#\xdc\xd8k5\x8c2\xe4\x8d*\xf9\x10$%\x9fef\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc0\x9af\x17*\xea7\r\x9ac\xda\x04\xffq\xff\xbb\xfc\xff\u007f\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\x9e<\xfc\x19\xf6\x05\xff>\xc9\xc9\xc7\x0e%@\xd7\xee\x97Cf\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc0\xa0*\xb9N\xbeV\xd0E\xb4\x1bb\x9b\x98F.:\x02J\x93\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xc0\xa3\x93\b\xa8\x0e\x9e\x84\xaa\xaf\x16\xac\x01\xe3\xb0\x1dt\xbdk-\x89\afM\xddL\x1c\v\x80\x00\u07d4\xc0\xa6\u02edwi*=\x88\xd1A\xefv\x9a\x99\xbb\x9e<\x99Q\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xc0\xa7\xe8C]\xff\x14\xc2Uws\x9d\xb5\\$\u057fW\xa3\u064a\nm\xd9\f\xaeQ\x14H\x00\x00\u07d4\xc0\xae\x14\xd7$\x83./\xce'x\xde\u007f{\x8d\xaf{\x12\xa9>\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc0\xaf\xb7\u0637\x93p\xcf\xd6c\u018c\u01b9p*7\u035e\xff\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc0\xb0\xb7\xa8\xa6\xe1\xac\xdd\x05\xe4\u007f\x94\xc0\x96\x88\xaa\x16\u01ed\x8d\x89\x03{m\x02\xacvq\x00\x00\xe0\x94\xc0\xb3\xf2D\xbc\xa7\xb7\xde[H\xa5>\u06dc\xbe\xab\vm\x88\xc0\x8a\x01;\x80\xb9\x9cQ\x85p\x00\x00\u07d4\xc0\xc0M\x01\x06\x81\x0e>\xc0\xe5J\x19\U000ab157\xe6\x9aW=\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xc0\xca2w\x94.tE\x87K\xe3\x1c\xeb\x90)rqO\x18#\x89\r\x8drkqw\xa8\x00\x00\u07d4\xc0\u02ed<\xcd\xf6T\xda\"\xcb\xcf\\xe\x97\xca\x19U\xc1\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc0\xcb\xf6\x03/\xa3\x9e|F\xffw\x8a\x94\xf7\xd4E\xfe\"\xcf0\x89\x10\xce\x1d=\x8c\xb3\x18\x00\x00\u07d4\xc0\xe0\xb9\x03\b\x8e\fc\xf5=\xd0iWTR\xaf\xf5$\x10\u00c9\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc0\xe4W\xbdV\xec6\xa1$k\xfa20\xff\xf3\x8eY&\xef\"\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xc0\xed\rJ\xd1\r\xe045\xb1S\xa0\xfc%\xde;\x93\xf4R\x04\x89\xabM\xcf9\x9a:`\x00\x00\u07d4\xc0\xf2\x9e\xd0\af\x11\xb5\xe5^\x13\x05G\xe6\x8aH\xe2m\xf5\u4262\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xc1\x13(x#\\]\u06e5\xd9\xf3\"\x8bR6\xe4p \xdco\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc1\x17\r\xba\xad\xb3\xde\xe6\x19\x8e\xa5D\xba\xec\x93%\x18`\xfd\xa5\x89A\rXj \xa4\xc0\x00\x00\xe0\x94\xc1&W=\x87\xb0\x17ZR\x95\xf1\xdd\a\xc5u\u03cc\xfa\x15\xf2\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc1'\xaa\xb5\x90e\xa2\x86D\xa5k\xa3\xf1^.\xac\x13\xda)\x95\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xc1+\u007f@\u07da/{\xf9\x83f\x14\"\xab\x84\xc9\xc1\xf5\bX\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xc1,\xfb{=\xf7\x0f\xce\xca\x0e\xde&5\x00\xe2xs\xf8\xed\x16\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc1/\x88\x1f\xa1\x12\xb8\x19\x9e\xcb\xc7>\xc4\x18W\x90\xe6\x14\xa2\x0f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc18Lnq~\xbeK#\x01NQ\xf3\x1c\x9d\xf7\xe4\xe2[1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc1C\x8c\x99\xddQ\xef\x1c\xa88j\xf0\xa3\x17\xe9\xb0AEx\x88\x89\f\x1d\xaf\x81\u0623\xce\x00\x00\u07d4\xc1c\x12(\xef\xbf*.:@\x92\xee\x89\x00\xc69\xed4\xfb\u02093\xc5I\x901r\f\x00\x00\u07d4\xc1u\xbe1\x94\xe6iB-\x15\xfe\xe8\x1e\xb9\xf2\xc5lg\xd9\u0249\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc1\x82v\x86\xc0\x16\x94\x85\xec\x15\xb3\xa7\xc8\xc0\x15\x17\xa2\x87M\xe1\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xc1\x8a\xb4g\xfe\xb5\xa0\xaa\xdf\xff\x91#\x0f\xf0VFMx\xd8\x00\x89lk\x93[\x8b\xbd@\x00\x00\u0794\xc1\x95\x05CUM\x8aq0\x03\xf6b\xbba,\x10\xadL\xdf!\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xc1\xa4\x1aZ'\x19\x92&\xe4\xc7\xeb\x19\x8b\x03\x1bY\x19o\x98B\x89\nZ\xa8P\t\xe3\x9c\x00\x00\u07d4\xc1\xb2\xa0\xfb\x9c\xadE\xcdi\x91\x92\xcd'T\v\x88\xd38By\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc1\xb2\xaa\x8c\xb2\xbfb\xcd\xc1:G\xec\xc4e\u007f\xac\xaa\x99_\x98\x8967\x93\xfa\x96\u6980\x00\u07d4\xc1\xb5\x00\x01\x1c\xfb\xa9]|\xd66\xe9^l\xbfagFK%\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc1\xb9\xa5pM5\x1c\xfe\x98?y\xab\xee\xc3\u06fb\xae;\xb6)\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc1\xcb\xd2\xe23*RL\xf2\x19\xb1\r\x87\x1c\xcc \xaf\x1f\xb0\xfa\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xc1\xcd\xc6\x01\xf8\x9c\x04(\xb3\x13\x02\u0447\xe0\xdc\b\xad}\x1cW\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xc1\u052f8\xe9\xbay\x90@\x89HI\xb8\xa8!\x93u\xf1\xacx\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc1\xe1@\x9c\xa5,%CQ4\xd0\x06\u00a6\xa8T-\xfbrs\x89\x01\xdd\x1eK\xd8\xd1\xee\x00\x00\u07d4\xc1\xeb\xa5hJ\xa1\xb2L\xbac\x15\x02c\xb7\xa9\x13\x1a\xee\u008d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc1\xec\x81\xdd\x12=K|-\u0674\xd48\xa7\a,\x11\u0707L\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc1\xf3\x9b\xd3]\xd9\xce\xc37\xb9oG\xc6w\x81\x81`\xdf7\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\xc1\xff\xad\a\u06d6\x13\x8cK*S\x0e\xc1\xc7\xde)\xb8\xa0Y,\x88\xf4?\xc2\xc0N\xe0\x00\x00\xe0\x94\xc2\x1f\xa6d:\x1f\x14\xc0)\x96\xadqD\xb7Y&\xe8~\xcbK\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc24\nL\xa9L\x96x\xb7IL<\x85%(\xed\xe5\xeeR\x9f\x89\x02\xa3k\x05\xa3\xfd|\x80\x00\u07d4\xc29\xab\u07ee>\x9a\xf5E\u007fR\xed+\x91\xfd\n\xb4\xd9\xc7\x00\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2;/\x92\x1c\xe4\xa3z%\x9e\u4b4b!X\xd1]fOY\x89\x01`\x89\x95\xe8\xbd?\x80\x00\u07d4\xc2C\x99\xb4\xbf\x86\xf73\x8f\xbfd^;\"\xb0\u0dd79\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2L\u03bc#D\xcc\xe5d\x17\xfbhL\xf8\x16\x13\xf0\xf4\xb9\xbd\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xc2Rf\xc7gf2\xf1>\xf2\x9b\xe4U\ud50a\xddVw\x92\x89Hz\x9a0E9D\x00\x00\u07d4\xc2\\\xf8&U\f\x8e\xaf\x10\xaf\"4\xfe\xf9\x04\u0779R\x13\xbe\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc2f?\x81E\xdb\xfe\xc6\xc6F\xfc\\I\x96\x13E\xde\x1c\x9f\x11\x89%g\xacp9+\x88\x00\x00\u07d4\xc2pEh\x854+d\vL\xfc\x1bR\x0e\x1aTN\xe0\xd5q\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xc2sv\xf4]!\xe1^\xde;&\xf2e_\xce\xe0,\xcc\x0f*\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xc2w\x97q\xf0Smy\xa8p\x8fi1\xab\xc4K05\u964a\x047\u04ca\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xc2\xc1>r\xd2h\xe7\x15\r\u01d9\xe7\xc6\xcf\x03\u0209T\xce\u05c9%\xf2s\x93=\xb5p\x00\x00\u07d4\xc2\xcb\x1a\xda]\xa9\xa0B8s\x81G\x93\xf1aD\xef6\xb2\xf3\x89HU~;p\x17\xdf\x00\x00\u07d4\xc2\xd1w\x8e\xf6\xee_\xe4\x88\xc1E\xf3Xkn\xbb\xe3\xfb\xb4E\x89>\x1f\xf1\xe0;U\xa8\x00\x00\xe0\x94\xc2\xd9\xee\xdb\xc9\x01\x92c\xd9\xd1l\u016e\a-\x1d=\xd9\xdb\x03\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc2\xe0XJq4\x8c\xc3\x14\xb7; )\xb6#\v\x92\u06f1\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc2\xe2\u0518\xf7\r\xcd\bY\xe5\v\x02:q\nmK!3\xbd\x8989\x11\xf0\f\xbc\xe1\x00\x00\u07d4\xc2\xed_\xfd\u046d\xd8U\xa2i/\xe0b\xb5\xd6\x18t#`\u0509A\rXj \xa4\xc0\x00\x00\u07d4\xc2\xee\x91\xd3\xefX\xc9\u0465\x89\x84N\xa1\xae1%\xd6\u017ai\x894\x95tD\xb8@\xe8\x00\x00\u07d4\xc2\xfa\xfd\xd3\n\xcbmg\x06\xe9)<\xb0&A\xf9\xed\xbe\a\xb5\x89Q\x00\x86\vC\x0fH\x00\x00\u07d4\xc2\xfd\v\xf7\xc7%\xef>\x04~Z\xe1\u009f\xe1\x8f\x12\xa7)\x9c\x89Hz\x9a0E9D\x00\x00\u07d4\xc2\xfe}us\x1fcm\xcd\t\xdb\xda\x06q9;\xa0\xc8*}\x89wC\"\x17\xe6\x83`\x00\x00\u07d4\xc3\x10z\x9a\xf32-R8\xdf\x012A\x911b\x959W}\x89\x1a\xb4\xe4d\xd4\x141\x00\x00\xe0\x94\xc3\x11\v\xe0\x1d\xc9sL\xfcn\x1c\xe0\u007f\x87\xd7}\x13E\xb7\xe1\x8a\x01\x0f\f\xe9I\xe0\x0f\x93\x00\x00\u07d4\xc3 8\xcaR\xae\xe1\x97E\xbe\\1\xfc\xdcT\x14\x8b\xb2\xc4\u0409\x02\xb5\xaa\xd7,e \x00\x00\u07d4\xc3%\xc3R\x80\x1b\xa8\x83\xb3\"l_\xeb\r\xf9\xea\xe2\xd6\xe6S\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xc3.\xc7\xe4*\xd1l\xe3\xe2UZ\xd4\xc5C\x06\xed\xa0\xb2gX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc32\xdfP\xb1<\x014\x90\xa5\xd7\xc7]\xbf\xa3f\u0687\xb6\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc3:\u0373\xba\x1a\xab'P{\x86\xb1]g\xfa\xf9\x1e\xcfb\x93\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3>\u0393Z\x8fN\xf98\xea~\x1b\xac\x87\u02d2]\x84\x90\u028a\a\x03\x8c\x16x\x1fxH\x00\x00\u07d4\xc3@\xf9\xb9\x1c&r\x8c1\xd1!\xd5\xd6\xfc;\xb5m=\x86$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3F\xcb\x1f\xbc\xe2\xab(]\x8eT\x01\xf4-\xd7#M7\xe8m\x89\x04\x86\u02d7\x99\x19\x1e\x00\x00\xe0\x94\xc3H=n\x88\xac\x1fJ\xe7<\xc4@\x8dl\x03\xab\xe0\xe4\x9d\u028a\x03\x99\x92d\x8a#\u0220\x00\x00\xe0\x94\xc3H\xfcZF\x13#\xb5{\xe3\x03\u02c96\x1b\x99\x19\x13\xdf(\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xc3N;\xa12.\xd0W\x11\x83\xa2O\x94 N\xe4\x9c\x18fA\x89\x03'\xaf\uf927\xbc\x00\x00\xe0\x94\xc3[\x95\xa2\xa3s|\xb8\xf0\xf5\x96\xb3E$\x87+\xd3\r\xa24\x8a\x01\x98\xbe\x85#^-P\x00\x00\xe0\x94\xc3c\x1cv\x98\xb6\xc5\x11\x19\x89\xbfE''\xb3\xf99Zm\xea\x8a\x02C'X\x96d\x1d\xbe\x00\x00\u07d4\xc3l\vc\xbf\xd7\\/\x8e\xfb\x06\b\x83\xd8h\xcc\xcdl\xbd\xb4\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xc3uk\xcd\xcc~\xect\xed\x89j\xdf\xc35'Y0&n\b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u00c4\xacn\xe2|9\xe2\xf2x\xc2 \xbd\xfa[\xae\xd6&\xd9\u04c9 \x86\xac5\x10R`\x00\x00\u07d4\u00e0F\xe3\u04b2\xbfh\x14\x88\x82n2\xd9\xc0aQ\x8c\xfe\x8c\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\u07d4\u00e9\"j\xe2u\xdf,\xab1+\x91\x10@cJ\x9c\x9c\x9e\xf6\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u00f9(\xa7o\xadex\xf0O\x05U\xe69R\xcd!\xd1R\n\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3\xc2)s)\xa6\xfd\x99\x11~T\xfcj\xf3y\xb4\xd5VT~\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc3\xc3\xc2Q\rg\x80 HZcs]\x13\a\xecL\xa60+\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc3\xcbk6\xafD?,n%\x8bJ9U:\x81\x87G\x81\x1f\x89WG=\x05\u06ba\xe8\x00\x00\xe0\x94\xc3\xdbVW\xbbr\xf1\rX\xf21\xfd\xdf\x11\x98\n\xffg\x86\x93\x8a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\xc3\u06df\xb6\xf4lH\n\xf3De\u05d7S\xb4\xe2\xb7Jg\u038a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc3\xddX\x908\x860;\x92\x86%%z\xe1\xa0\x13\xd7\x1a\xe2\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\xe0G\x1cd\xff5\xfaR2\xcc1!\xd1\u04cd\x1a\x0f\xb7\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\xe2\f\x96\u07cdN8\xf5\v&Z\x98\xa9\x06\xd6\x1b\xc5\x1aq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc3\u31f0<\xe9\\\xcf\xd7\xfaQ\u0744\x01\x83\xbcCS(\t\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc3\xf8\xf6r\x95\xa5\xcd\x04\x93d\xd0]#P&#\xa3\xe5.\x84\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc4\x01\xc4'\xcc\xcf\xf1\r\xec\xb8d /6\xf5\x80\x83\"\xa0\xa8\x89\xb4{Q\xa6\x9c\xd4\x02\x00\x00\u07d4\xc4\b\x8c\x02_>\x85\x01?T9\xfb4@\xa1s\x01\xe5D\xfe\x89~\t\xdbM\x9f?4\x00\x00\u07d4\xc4\x14a\xa3\u03fd2\u0246UU\xa4\x8117\xc0v1#`\x8965\xc6 G9\u0640\x00\u07d4\xc4 8\x8f\xbe\xe8J\xd6V\xddh\xcd\xc1\xfb\xaa\x93\x92x\v4\x89\n-\xcac\xaa\xf4\u0140\x00\u07d4\xc4\"P\xb0\xfeB\xe6\xb7\xdc\xd5\u0210\xa6\xf0\u020f__\xb5t\x89\b\x1e\xe4\x82SY\x84\x00\x00\u07d4\xc4-j\xebq\x0e:P\xbf\xb4Ml1\t)i\xa1\x1a\xa7\xf3\x89\b\"c\xca\xfd\x8c\xea\x00\x00\xe0\x94\xc4@\xc7\xca/\x96Kir\xeffJ\"a\xdd\xe8\x92a\x9d\x9c\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xc4K\xde\xc8\xc3l\\h\xba\xa2\xdd\xf1\xd41i2)rlC\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xc4OJ\xb5\xbc`9|s~\xb0h3\x91\xb63\xf8\xa2G\x1b\x12\x1c\xa4\x89 .h\xf2\u00ae\xe4\x00\x00\u07d4\xc4h\x1es\xbb\x0e2\xf6\xb7& H1\xffi\xba\xa4\x87~2\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xc4k\xbd\xefv\xd4\xca`\xd3\x16\xc0\u007f]\x1ax\x0e;\x16_~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc4}a\v9\x92P\xf7\x0e\xcf\x13\x89\xba\xb6),\x91&O#\x89\x0f\xa7\xe7\xb5\xdf<\xd0\x00\x00\u07d4\u0100;\xb4\a\xc7b\xf9\vu\x96\xe6\xfd\u1513\x1ev\x95\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0106Q\xc1\xd9\xc1k\xffL\x95T\x88l??&C\x1foh\x89#\xab\x95\x99\xc4?\b\x00\x00\u07d4\u0109\xc8?\xfb\xb0%*\xc0\xdb\xe3R\x12\x17c\x0e\x0fI\x1f\x14\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u010bi<\xac\xef\xdb\xd6\xcb]x\x95\xa4.1\x962~&\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0113H\x9eV\u00fd\xd8)\x00}\xc2\xf9VA)\x06\xf7k\xfa\x89\x02\xa7\x91H\x8eqT\x00\x00\u07d4\u0116\u02f0E\x9aj\x01`\x0f\u0149\xa5Z2\xb4T!\u007f\x9d\x89\x0e\u0683\x8cI)\b\x00\x00\u07d4\u011c\xfa\xa9g\xf3\xaf\xbfU\x03\x10a\xfcL\xef\x88\xf8]\xa5\x84\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u0136\xe5\xf0\x9c\xc1\xb9\r\xf0x\x03\xce=M\x13vj\x9cF\xf4\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\u013e\xc9c\b\xa2\x0f\x90\u02b1\x83\x99\u0113\xfd=\x06Z\xbfE\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xc4\xc0\x1a\xfc>\x0f\x04R!\xda\x12\x84\u05c7\x85tD/\xb9\xac\x8a\x01\x92\xb5\u0249\x02J\x19\xc1\xbdo\x12\x80\x00\xe0\x94\xc5\x00\xb7 sN\xd2)8\u05cc^H\xb2\xba\x93g\xa5u\xba\x8a\a\x12\x9e\x1c\xdf7>\xe0\x00\x00\u07d4\xc5\x0f\xe4\x15\xa6A\xb0\x85lNu\xbf\x96\x05\x15D\x1a\xfa5\x8d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5\x13L\xfb\xb1\xdfz \xb0\xedpWb.\xee\u0480\x94}\xad\x89\xcd\xff\x97\xfa\xbc\xb4`\x00\x00\xe0\x94\xc5\x17\xd01\\\x87\x88\x13\xc7\x17\u132f\xa1\xea\xb2eN\x01\u068a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc5\x18y\x9aY%Wb\x13\xe2\x18\x96\xe0S\x9a\xbb\x85\xb0Z\xe3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc5\"\xe2\x0f\xbf\x04\xed\u007fk\x05\xa3{G\x18\xd6\xfc\xe0\x14.\x1a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc5$\bmF\xc8\x11+\x12\x8b/\xafo|}\x81`\xa88l\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc5-\x1a\fs\u00a1\xbe\x84\x91Q\x85\xf8\xb3O\xaa\n\xdf\x1d\xe3\x89K\xe4\xea\xb3\xfa\x0f\xa6\x80\x00\xe0\x94\xc55\x94\xc7\u03f2\xa0\x8f(L\xc9\u05e6;\xbd\xfc\v1\x972\x8a\nk#(\xff:b\xc0\x00\x00\u07d4\xc57I(\xcd\xf1\x93pTC\xb1L\xc2\r\xa4#G<\xd9\u03c9\a}\x10P\x9b\xb3\xaf\x80\x00\u07d4\xc58\xa0\xff(*\xaa_Ku\u03f6,p\x03~\xe6}O\xb5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5;P\xfd;+r\xbclC\v\xaf\x19JQU\x85\u04d8m\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xc5=y\xf7\u02dbp\x95/\xd3\x0f\xceX\xd5K\x9f\vY\xf6G\x8a\x01\x13\xe2\xd6tCE\xf8\x00\x00\u07d4\xc5I\u07c3\xc6\xf6^\xec\x0f\x1d\u0260\x93J\\_:P\xfd\x88\x89\x9d\xc0\\\xce(\u00b8\x00\x00\u07d4\xc5P\x05\xa6\xc3~\x8c\xa7\xe5C\xce%\x99s\xa3\xca\u0396\x1aJ\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5U\xb91V\xf0\x91\x01#\x80\x00\xe0\x94\u0166)\xa3\x96%R\u02ce\xde\u0609cj\xaf\xbd\f\x18\xcee\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u016e\x86\xb0\xc6\xc7\xe3\x90\x0f\x13h\x10\\VS\u007f\xaf\x8dt>\x89\n1\x06+\xee\xedp\x00\x00\u07d4\u0170\t\xba\xea\xf7\x88\xa2v\xbd5\x81:\xd6[@\v\x84\x9f;\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0175l\xd24&|(\xe8\x9cok\"f\xb0\x86\xa1/\x97\f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xc5\u01a4\x99\x8a3\xfe\xb7dCz\x8b\xe9)\xa7;\xa3J\ad\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\xe0\x94\xc5\xc7=a\xcc\xe7\xc8\xfeL\x8f\xce)\xf3\x90\x92\xcd\x19>\x0f\xff\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xc5\xc7Y\vV!\xec\xf85\x85\x88\u079bh\x90\xf2baC\U000498a1]\tQ\x9b\xe0\x00\x00\u07d4\xc5\xcd\xce\xe0\xe8]\x11}\xab\xbfSj?@i\xbfD?T\xe7\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xc5\u050c\xa2\xdb/\x85\xd8\xc5U\xcb\x0e\x9c\xfe\x82i6x?\x9e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc5\xde\x12\x03\xd3\xcc,\xea1\xc8.\xe2\xdeY\x16\x88\a\x99\xea\xfd\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xc5\xe4\x88\xcf+Vw\x939q\xf6L\xb8 -\xd0WR\xa2\xc0\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc5\xe8\x12\xf7o\x15\xf2\xe1\xf2\xf9\xbcH#H<\x88\x04cog\x89\x03\xf5\x14\x19:\xbb\x84\x00\x00\u07d4\xc5\u94d34\xf1%.\u04ba&\x81D\x87\xdf\u0498+1(\x89\x03\xcbq\xf5\x1f\xc5X\x00\x00\u07d4\xc5\xebB)^\x9c\xad\xea\xf2\xaf\x12\xde\u078a\x8dS\xc5y\xc4i\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\xc5\xed\xbb\xd2\xca\x03WeJ\xd0\xeaG\x93\xf8\xc5\xce\xcd0\xe2T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc5\xf6K\xab\xb7\x031B\xf2\x0eF\u05eab\x01\xed\x86\xf6q\x03\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc5\xf6\x87qrF\u068a \r \xe5\u9f2c`\xb6\u007f8a\x89\x01\x8d\x99?4\xae\xf1\x00\x00\u07d4\xc6\x04[<5\vL\xe9\xca\fkuO\xb4\x1ai\xb9~\x99\x00\x892$\xf4'#\xd4T\x00\x00\u07d4\xc6\v\x04eN\x00;F\x83\x04\x1f\x1c\xbdk\u00cf\xda|\xdb\u0589lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\x14F\xb7T\xc2N;\x16B\xd9\xe5\x17e\xb4\xd3\xe4k4\xb6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\x18R\x13!\xab\xaf[&Q:J\x95(\bo\"\n\xdco\x89\x01v\xb3D\xf2\xa7\x8c\x00\x00\u07d4\xc6#FW\xa8\a8A&\xf8\x96\x8c\xa1p\x8b\xb0{\xaaI<\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc6%\xf8\u024d'\xa0\x9a\x1b\u02bdQ(\xb1\u00a9HV\xaf0\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc65^\xc4v\x8cp\xa4\x9a\xf6\x95\x13\u0343\xa5\xbc\xa7\xe3\xb9\u034a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc6:\xc4\x17\x99.\x9f\x9b`8n\xd9S\xe6\xd7\xdf\xf2\xb0\x90\xe8\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xc6<\u05c8!\x18\xb8\xa9\x1e\aML\x8fK\xa9\x18Q0;\x9a\x89\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xc6R\x87\x1d\x19$\"\u01bc#_\xa0c\xb4J~\x1dC\u3149\bg\x0e\x9e\xc6Y\x8c\x00\x00\xe0\x94\xc6gD\x1e\u007f)y\x9a\xbaadQ\xd5;?H\x9f\x9e\x0fH\x8a\x02\xf2\x9a\xceh\xad\u0740\x00\x00\u07d4\xc6j\xe4\xce\xe8\u007f\xb352\x19\xf7\u007f\x1dd\x86\u0140(\x032\x89\x01\x9a\x16\xb0o\xf8\xcb\x00\x00\u07d4\xc6t\xf2\x8c\x8a\xfd\a?\x8by\x96\x91\xb2\xf0XM\xf9B\xe8D\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u0197\xb7\x04w\u02b4.+\x8b&f\x81\xf4\xaesu\xbb%A\x8a\x01.W2\xba\xba\\\x98\x00\x00\u07d4\u019b\x85U9\xce\x1b\x04qG(\xee\xc2Z7\xf3g\x95\x1d\xe7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u019b\xe4@\x13Mb\x80\x98\x01D\xa9\xf6M\x84t\x8a7\xf3I\x89&\u009eG\u0104L\x00\x00\u07d4\u019df<\x8d`\x90\x83\x91\xc8\xd26\x19\x153\xfd\xf7wV\x13\x89\x1aJ\xba\"\\ t\x00\x00\u0794\u01a2\x86\xe0e\xc8_:\xf7H\x12\xed\x8b\u04e8\xce]%\xe2\x1d\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\u01a3\x0e\xf5\xbb3 \xf4\r\xc5\xe9\x81#\rR\xae:\xc1\x93\"\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\u01ae(}\xdb\xe1\x14\x9b\xa1m\xdc\xcaO\xe0j\xa2\uaa48\xa9\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc6\xc7\xc1\x917\x98\x97\u075c\x9d\x9a3\x83\x9cJ_b\xc0\x89\r\x89\xd8\xd8T\xb2$0h\x80\x00\xe0\x94\xc6\xcdh\xec56,Z\xd8L\x82\xadN\xdc#!%\x91-\x99\x8a\x05\xe0T\x9c\x962\xe1\xd8\x00\x00\u07d4\xc6\u0615N\x8f?\xc53\xd2\xd20\xff\x02\\\xb4\xdc\xe1O4&\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xc6\xdb\u06de\xfd^\xc1\xb3xn\x06q\xeb\"y\xb2S\xf2\x15\xed\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc6\xdf u\xeb\xd2@\xd4Hi\u00bek\u07c2\xe6=N\xf1\xf5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc6\xe2\xf5\xaf\x97\x9a\x03\xfdr:\x1bn\xfar\x83\x18\u03dc\x18\x00\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xc6\xe3$\xbe\xeb[6v^\xcdFB`\xf7\xf2`\x06\xc5\xc6.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc6\xe4\xcc\fr\x83\xfc\x1c\x85\xbcH\x13\xef\xfa\xafr\xb4\x98#\xc0\x89\x0f\x03\x1e\xc9\xc8}\xd3\x00\x00\xe0\x94\xc6\xee5\x93B)i5)\xdcA\u067bq\xa2IfX\xb8\x8e\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xc6\xfb\x1e\xe3t\x17\u0400\xa0\xd0H\x92;\u06ba\xb0\x95\xd0w\u0189\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc7\x05'\xd4D\u0110\xe9\xfc?\\\xc4Nf\xebO0k8\x0f\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7\r\x85mb\x1e\xc1E0<\nd\x00\xcd\x17\xbb\xd6\xf5\xea\xf7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xc7\x0f\xa4Uv\xbf\x9c\x86_\x988\x93\x00,AI&\xf6\x10)\x89\x15\xb4\xaa\x8e\x97\x02h\x00\x00\u07d4\xc7\x11E\xe5)\u01e7\x14\xe6y\x03\xeeb\x06\xe4\xc3\x04+g'\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xc7\x1b*=q5\u04a8_\xb5\xa5q\u073ei^\x13\xfcC\u034965\u026d\xc5\u07a0\x00\x00\u07d4\xc7\x1f\x1du\x87?3\u0732\xddK9\x87\xa1-\a\x91\xa5\xce'\x897\b\xba\xed=h\x90\x00\x00\u07d4\xc7\x1f\x92\xa3\xa5J{\x8c/^\xa4C\x05\xfc\u02c4\xee\xe21H\x89\x02\xb5\x9c\xa11\xd2\x06\x00\x00\u07d4\xc7!\xb2\xa7\xaaD\xc2\x12\x98\xe8P9\xd0\x0e.F\x0eg\v\x9c\x89\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\xc7,\xb3\x01%\x8e\x91\xbc\b\x99\x8a\x80]\u0452\xf2\\/\x9a5\x89 \t\xc5\u023fo\xdc\x00\x00\xe0\x94\xc76\x8b\x97\t\xa5\xc1\xb5\x1c\n\xdf\x18ze\xdf\x14\xe1+}\xba\x8a\x02\x02o\xc7\u007f\x03\u5b80\x00\u07d4\xc79%\x9e\u007f\x85\xf2e\x9b\xef_`\x9e\xd8k=Yl \x1e\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc7>!\x12(\"\x15\xdc\ab\xf3+~\x80}\xcd\x1az\xae>\x8a\x01v\f\xbcb;\xb3P\x00\x00\xe0\x94\xc7If\x80B\xe7\x11#\xa6H\x97^\b\xedc\x82\xf8>\x05\xe2\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xc7J9\x95\xf8\a\xde\x1d\xb0\x1a.\xb9\xc6.\x97\xd0T\x8fio\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc7Pl\x10\x19\x12\x1f\xf0\x8a,\x8c\x15\x91\xa6^\xb4\xbd\xfbJ?\x89 \x86\xac5\x10R`\x00\x00\u07d4\xc7\\7\xce-\xa0k\xbc@\b\x11Y\u01ba\x0f\x97n9\x93\xb1\x89:y#\x15\x1e\xcfX\x00\x00\u07d4\xc7]\"Y0j\xec}\xf0\"v\x8ci\x89\x9ae!\x85\xdb\u0109\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7`\x97\x1b\xbc\x18\x1cj|\xf7tA\xf2BG\u045c\xe9\xb4\u03c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xc7a0\xc7<\xb9!\x028\x02\\\x9d\xf9]\v\xe5J\xc6\u007f\xbe\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xc7e\xe0\x04v\x81\tG\x81j\xf1B\xd4m.\u7f28\xccO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc7g^VG\xb9\xd8\xda\xf4\xd3\xdf\xf1\xe5R\xf6\xb0qT\xac8\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xc7{\x01\xa6\xe9\x11\xfa\x98\x8d\x01\xa3\xab3dk\xee\xf9\xc18\xf3\x89'\x1bo\xa5\xdb\xe6\xcc\x00\x00\u07d4\u01c3z\u0420\xbf\x14\x18i7\xac\xe0lUF\xa3j\xa5OF\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u01d8\x06\x03+\xc7\xd8(\xf1\x9a\u01a6@\u018e=\x82\x0f\xa4B\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u01d9\xe3N\x88\xff\x88\xbe}\xe2\x8e\x15\xe4\xf2\xa6=\v3\xc4\u02c9\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\u01ddPb\u01d6\xddwa\xf1\xf1>U\x8ds\xa5\x9f\x82\xf3\x8b\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\u01e0\x18\xf0\x96\x8aQ\xd1\xf6`<\\I\xdcT[\xcb\x0f\xf2\x93\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u01ef\xf9\x19)yt\x89UZ/\xf1\xd1M\\iZ\x10\x83U\x8965\u026d\xc5\u07a0\x00\x00\u0794\u01f1\xc8>c ?\x95G&>\xf6(.}\xa3;n\xd6Y\x88\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\u01f3\x9b\x06\x04Q\x00\f\xa1\x04\x9b\xa1T\xbc\xfa\x00\xff\x8a\xf2b\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\u01ff\x17\xc4\xc1\x1f\x98\x94\x1fP~w\bO\xff\xbd-\xbd=\xb5\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\u01ff.\xd1\xed1)@\xeej\xde\xd1Qn&\x8eJ`HV\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xc7\xd4O\xe3,\u007f\x8c\xd5\xf1\xa9t'\xb6\xcd:\xfc\x9eE\x02>\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xc7\xd5\xc7\x05@\x81\xe9\x18\xech{Z\xb3n\x97=\x18\x13)5\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xc7\xde^\x8e\xaf\xb5\xf6+\x1a\n\xf2\x19\\\xf7\x93\u01c9L\x92h\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xc7\xe30\xcd\f\x89\n\u025f\xe7q\xfc\xc7\xe7\xb0\t\xb7A=\x8a\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc7\xea\xc3\x1a\xbc\xe6\xd5\xf1\u07a4\"\x02\xb6\xa6t\x15=\xb4z)\x89 \t\xc5\u023fo\xdc\x00\x00\xe0\x94\xc7\xecb\xb8\x04\xb1\xf6\x9b\x1e0p\xb5\xd3b\xc6/\xb3\t\xb0p\x8a\x02\xc4k\xf5A`f\x11\x00\x00\u07d4\xc7\xf7+\xb7X\x01k7G\x14\u0509\x9b\xce\"\xb4\xae\xc7\n1\x89:&\xc9G\x8f^-\x00\x00\u0794\xc8\v6\u047e\xaf\xba_\xccdM`\xacnF\xed)'\xe7\u0708\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xc8\x11\xc2\xe9\xaa\x1a\xc3F.\xba^\x88\xfc\xb5\x12\x0e\x9fn,\xa2\x89K\xe6\u0607\xbd\x87n\x00\x00\u07d4\xc8\x17\xdf\x1b\x91\xfa\xf3\x0f\xe3%\x15qr|\x97\x11\xb4]\x8f\x06\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xc8\x1f\xb7\xd2\x0f\u0480\x01\x92\xf0\xaa\xc1\x98\xd6\u05a3}?\xcb}\x89\x0e\x11I3\x1c-\xde\x00\x00\u07d4\xc8 \xc7\x11\xf0w\x05'8\a\xaa\xaam\xe4M\x0eKH\xbe.\x89\bg\x0e\x9e\xc6Y\x8c\x00\x00\u07d4\xc8#\x1b\xa5\xa4\x11\xa1>\"+)\xbf\xc1\b?v1X\xf2&\x8967\tlK\xcci\x00\x00\u07d4\xc86\xe2Jo\xcf)\x94;6\b\xe6b)\n!_e)\xea\x89\x0f\xd4Pd\xea\xee\x10\x00\x00\xe0\x94\xc8;\xa6\u0755I\xbe\x1d2\x87\xa5\xa6T\xd1\x06\xc3Lk]\xa2\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xc8>\x9djX%;\uefb7\x93\xe6\xf2\x8b\x05JXI\x1bt\x89\x0fF\u00b6\xf5\xa9\x14\x00\x00\u07d4\xc8A\x88O\xa4x_\xb7s\xb2\x8e\x97\x15\xfa\xe9\x9aQ40]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc8M\x9b\xea\n{\x9f\x14\x02 \xfd\x8b\x90\x97\u03ff\xd5\xed\xf5d\x89\x06\xab\x9e\u0091\xad}\x80\x00\u07d4\xc8RB\x8d+Xd\x97\xac\xd3\fV\xaa\x13\xfbU\x82\xf8D\x02\x893B\xd6\r\xff\x19`\x00\x00\u07d4\xc8S![\x9b\x9f-,\xd0t\x1eX^\x98{_\xb8\f!.\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xc8S%\uaca5\x9b>\xd8c\xc8j_)\x06\xa0B)\xff\xa9\x89\x19=\u007f}%=\xe0\x00\x00\u07d4\xc8^\xf2}\x82\x04\x03\x80_\xc9\xed%\x9f\xffd\xac\xb8\xd64j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc8akN\xc0\x91(\xcd\xff9\xd6\u4e6c\x86\xee\xc4q\xd5\xf2\x89\x01\r:\xa56\xe2\x94\x00\x00\xe0\x94\xc8a\x90\x90K\x8d\a\x9e\xc0\x10\xe4b\xcb\xff\xc9\b4\xff\xaa\\\x8a\x02#\x85\xa8'\xe8\x15P\x00\x00\u07d4\xc8q\r~\x8bZ;\u059aB\xfe\x0f\xa8\xb8|5\u007f\xdd\xcd\u0209\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc8sR\u06e5\x82\xee f\xb9\xc0\x02\xa9b\xe0\x03\x13Ox\xb1\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xc8|w\xe3\xc2J\xde\xcd\xcd\x108\xa3\x8bV\xe1\x8d\xea\u04f7\x02\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\xc8}:\xe3\u0607\x04\u066b\x00\t\xdc\xc1\xa0\x06q1\xf8\xba<\x89j\xc5\xc6-\x94\x86\a\x00\x00\xe0\x94\u0201N4R>8\xe1\xf9'\xa7\xdc\xe8FjDz\t6\x03\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u0202U\xed\xdc\xf5!\xc6\xf8\x1d\x97\xf5\xa4!\x81\xc9\a=N\xf1\x89\x0f\u00d0D\xd0\n*\x80\x00\u07d4\u0205\xa1\x8a\xab\xf4T\x1b{{~\xcd0\xf6\xfa\u619d\x95i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u020c\xa1\xe6\xe5\xf4\xd5X\xd17\x80\xf4\x88\xf1\rJ\xd3\x13\r4\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u020e\xecT\xd3\x05\xc9(\xcc(H\xc2\xfe\xe251\xac\xb9mI\x89lj\u04c2\xd4\xfba\x00\x00\xe0\x94\u021c\xf5\x04\xb9\xf3\xf85\x18\x1f\xd8BO\\\xcb\xc8\xe1\xbd\xdf}\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u0222\xc4\xe5\x9e\x1c\u007f\xc5H\x05X\x048\xae\xd3\xe4J\xfd\xf0\x0e\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4\u022aI\u301f\b\x99\xf2\x8a\xb5~gCp\x9dXA\x903\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\u022b\x1a<\xf4l\xb8\xb0d\xdf.\"-9`s\x94 2w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0231\x85\x05%\xd9F\xf2\xae\x84\xf3\x17\xb1Q\x88\xc56\xa5\u0706\x89\x91\x8d\xdc:B\xa3\xd4\x00\x00\u07d4\xc8\xd4\xe1Y\x9d\x03\xb7\x98\t\xe0\x13\n\x8d\u00c4\b\xf0^\x8c\u04c9\x9f\xad\x06$\x12y\x16\x00\x00\u07d4\xc8\xdd'\xf1k\xf2$P\xf5w\x1b\x9f\xe4\xedO\xfc\xb3\t6\xf4\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xc8\xdezVL\u007f@\x12\xa6\xf6\xd1\x0f\u040fG\x89\x0f\xbf\a\u0509\x10CV\x1a\x88)0\x00\x00\u07d4\xc8\xe2\xad\xebT^I\x9d\x98,\f\x11sc\u03b4\x89\u0171\x1f\x895e\x9e\xf9?\x0f\xc4\x00\x00\xe0\x94\xc8\xe5X\xa3\xc5i~o\xb2:%\x94\u0200\xb7\xa1\xb6\x8f\x98`\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xc8\xf2\xb3 \xe6\xdf\xd7\t\x06\u0157\xba\xd2\xf9P\x13\x12\u01c2Y\x89Q\x93K\x8b:W\xd0\x00\x00\u07d4\xc9\x03\x00\xcb\x1d@w\xe6\xa6\xd7\xe1i\xa4`F\x8c\xf4\xa4\x92\u05c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9\f7e\x15k\u028eH\x97\xab\x80$\x19\x15<\xbeR%\xa9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xc9\x10\xa9pUl\x97\x16\xeaS\xaff\xdd\xef\x93\x141$\x91=\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\xe0\x94\xc9\x12{\u007ff)\xee\x13\xfc?`\xbc/Dg\xa2\aE\xa7b\x8a\x03|\x9a\xa4\xe7\xceB\x1d\x80\x00\u07d4\xc9\x1b\xb5b\xe4+\xd4a0\xe2\u04eeFR\xb6\xa4\ub1bc\x0f\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\xe0\x94\xc90\x88y\x05m\xfe\x13\x8e\xf8 \x8fy\xa9\x15\u01bc~p\xa8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xc94\xbe\xca\xf7\x1f\"_\x8bJK\xf7\xb1\x97\xf4\xac\x9604\\\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc9?\xbd\xe8\xd4m+\xcc\x0f\xa9\xb3;\u063a\u007f\x80B\x12Ue\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xc9@\x89U:\xe4\xc2,\xa0\x9f\xbc\x98\xf5pu\xcf.\u0155\x04\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xc9A\x10\xe7\x1a\xfeW\x8a\xa2\x18\xe4\xfc(d\x03\xb03\n\u038d\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xc9F\u056c\xc14n\xba\nry\xa0\xac\x1dF\\\x99m\x82~\x8a\x03x=T_\xdf\n\xa4\x00\x00\u07d4\xc9J(\xfb20\xa9\xdd\xfa\x96Nw\x0f,\xe3\xc2S\xa7\xbeO\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xc9JXR\x03\xda{\xba\xfd\x93\xe1X\x84\xe6`\u0531\xea\xd8T\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xc9O|5\xc0'\xd4}\xf8\xefO\x9d\xf8Z\x92H\xa1}\xd2;\x89\x01\x9f\x8euY\x92L\x00\x00\u07d4\xc9Q\x90\f4\x1a\xbb\xb3\xba\xfb\xf7\xee )7pq\xdb\xc3j\x89\x11\xc2]\x00M\x01\xf8\x00\x00\u07d4\xc9S\xf94\xc0\xeb-\x0f\x14K\u06b0\x04\x83\xfd\x81\x94\x86\\\xe7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9f&r\x8a\xaaLO\xb3\xd3\x1c&\xdf:\xf3\x10\b\x17\x10\u0449\xb5\x0f\u03ef\xeb\xec\xb0\x00\x00\u07d4\xc9gQel\n\x8e\xf45{sD2!4\xb9\x83PJ\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\u0240Hh\u007f+\xfc\u027d\x90\xed\x18slW\xed\xd3R\xb6]\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0241\xd3\x12\u0487\xd5X\x87\x1e\u0757:\xbbv\xb9y\xe5\xc3^\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0242Xmc\xb0\xd7L \x1b\x1a\xf8A\x83r\xe3\fv\x16\xbe\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u0249CO\x82Z\xaf\x9cU/h^\xba|\x11\xdbJ_\xc7:\x89\x1b(\u014d\x96\x96\xb4\x00\x00\u07d4\u0249\xee\xc3\a\u80db\x9dr7\xcf\xda\b\x82)b\xab\u41c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u0252\xbeY\xc6r\x1c\xafN\x02\x8f\x9e\x8f\x05\xc2\\UQ[\u0509\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0255{\xa9L\x1b)\xe5'~\xc3f\"pI\x04\xc6=\xc0#\x89h>\xfcg\x82d,\x00\x00\xe0\x94\u025a\x9c\xd6\xc9\xc1\xbe54\xee\u0352\xec\xc2/\\8\xe9Q[\x8a\x01\x05Y;:\x16\x9dw\x00\x00\xe0\x94\u026c\x01\xc3\xfb\t)\x03?\f\xcc~\x1a\xcf\uaae7\x94]G\x8a\x02\xa3j\x9e\x9c\xa4\xd2\x03\x80\x00\u07d4\u0276\x98\xe8\x98\xd2\rMO@\x8eNM\x06\x19\"\xaa\x85c\a\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u0276\xb6\x86\x11\x16\x91\xeej\xa1\x97\xc7#\x1a\x88\xdc`\xbd)]\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc9\u01ec\v\u0753B\xb5\xea\xd46\t#\xf6\x8cr\xa6\xbac:\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xc9\xc8\r\xc1.{\xab\x86\xe9I\xd0\x1eL>\xd3_+\x9b\xba_\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xc9\xd7dF\u056a\xdf\xf8\vh\xb9\x1b\b\u035b\xc8\xf5U\x1a\xc1\x89&\xb4\xbd\x91\x10\xdc\xe8\x00\x00\xe0\x94\xc9\u073b\x05oM\xb7\xd9\xda9\x93b\x02\u017d\x820\xb3\xb4w\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xc9\xe0&\b\x06h(\x84\x8a\xeb(\xc76r\xa1)%\x18\x1fM\x89\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xca\x042\xcb\x15{Qy\xf0.\xbb\xa5\xc9\u0475O\xecM\x88\u028965\u026d\xc5\u07a0\x00\x00\u07d4\xca\x12,\xf0\U00094216\xb7HC\xf4\x9a\xfe\u043a\x16\x18\xee\u05c9\x1e[\x8f\xa8\xfe*\xc0\x00\x00\xe0\x94\xca\"\u0363`m\xa5\xca\xd0\x13\xb8\aG\x06\xd7\xe9\xe7!\xa5\f\x8a\x01q\x81\xc6\xfa9\x81\x94\x00\x00\u07d4\xca#\xf6-\xff\rd`\x03lb\xe8@\xae\xc5W~\v\xef\u0489\a\xa1\xfe\x16\x02w\x00\x00\x00\u07d4\xca%\xff4\x93L\x19B\xe2*N{\xd5o\x14\x02\x1a\x1a\xf0\x88\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xca7?\xe3\xc9\x06\xb8\xc6U\x9e\xe4\x9c\xcd\a\xf3|\xd4\xfbRf\x89a\t=|,m8\x00\x00\u07d4\xcaA\u032c0\x17 R\xd5\"\xcd//\x95}$\x81S@\x9f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xcaB\x88\x01N\xdd\xc5c/_\xac\xb5\xe3\x85\x17\xa8\xf8\xbc]\x98\x89\x12nr\xa6\x9aP\xd0\x00\x00\u07d4\xcaB\x88c\xa5\xca06\x98\x92\xd6\x12\x18>\xf9\xfb\x1a\x04\xbc\xea\x89Rf<\u02b1\xe1\xc0\x00\x00\u07d4\xcaI\xa5\xf5\x8a\xdb\xef\xae#\xeeY\xee\xa2A\xcf\x04\x82b.\xaa\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xcaL\xa9\xe4w\x9dS\x0e\u02ec\xd4~j\x80X\xcf\xdee\u064f\x89+^:\xf1k\x18\x80\x00\x00\u07d4\xcae~\xc0o\xe5\xbc\t\xcf#\xe5*\xf7\xf8\f\xc3h\x9en\u07890\xca\x02O\x98{\x90\x00\x00\u07d4\xcaf\xb2(\x0f\xa2\x82\u0176v1\xceU+b\xeeU\xad\x84t\x89j\xc4\"\xf54\x92\x88\x00\x00\xe0\x94\xcal\x81\x8b\xef\xd2Q6\x1e\x02t@h\xbe\x99\u062a`\xb8J\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcap\xf4\u077f\x06\x9d!C\xbdk\xbc\u007fikRx\x9b2\u7262\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xcatuvDjL\x8f0\xb0\x83@\xfe\xe1\x98\xdec\xec\x92\u03ca\x01|\x8e\x12\x06r*0\x00\x00\u07d4\xca{\xa3\xffSl~_\x0e\x158\x00\xbd8=\xb81)\x98\xe0\x89\t1\xac=k\xb2@\x00\x00\xe0\x94\u0282v\xc4w\xb4\xa0{\x80\x10{\x845\x94\x18\x96\a\xb5;\xec\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\u0284\t\b>\x01\xb3\x97\xcf\x12\x92\x8a\x05\xb6\x84U\xceb\x01\u07c9V\xbcu\xe2\xd61\x00\x00\x00\u07d4\u0298\u01d8\x8e\xfa\b\xe9%\uf719ER\x03&\xe9\xf4;\x99\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u029a\x04*j\x80o\xfc\x92\x17\x95\x00\xd2D)\xe8\xabR\x81\x17\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\u029d\xec\x02\x84\x1a\xdf\\\xc9 WjQ\x87\xed\u04bdCJ\x18\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u029f\xaa\x17T/\xaf\xbb8\x8e\xab!\xbcL\x94\u89f3G\x88\x89lk\x8f\xce\r\x18y\x80\x00\xe0\x94\u02aah\xeel\xdf\r4EJv\x9b\r\xa1H\xa1\xfa\xaa\x18e\x8a\x01\x87.\x1d\xe7\xfeR\xc0\x00\x00\u07d4\u02ad\x9d\xc2\rX\x9c\xe4(\xd8\xfd\xa3\xa9\xd5:`{y\x88\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u02b0\xd3,\xf3v\u007f\xa6\xb3S|\x842\x8b\xaa\x9fPE\x816\x8a\x01\xe5\xb8\xfa\x8f\xe2\xac\x00\x00\x00\u07d4\u02b9\xa3\x01\xe6\xbdF\xe9@5P(\xec\xcd@\xceMZ\x1a\u00c9\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u02b9\xa9z\xda\x06\\\x87\x81nh`\xa8\xf1Bo\xe6\xb3\xd7u\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\u02ba\xb6'N\xd1P\x89s~({\xe8x\xb7W\x93Hd\xe2\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\u02bd\xaf5OG \xa4f\xa7d\xa5(\xd6\x0e:H*9<\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xca\xcbg^\t\x96#T\x04\ufbfb.\u02c1R'\x1bU\xe0\x89%\xf2s\x93=\xb5p\x00\x00\u07d4\xca\xd1O\x9e\xbb\xa7f\x80\xeb\x83k\a\x9c\u007f{\xaa\xf4\x81\xedm\x89\f\xef={\xd7\xd04\x00\x00\xe0\x94\xca\xe3\xa2S\xbc\xb2\xcfN\x13\xba\x80\u0098\xab\x04\x02\xda|*\xa0\x8a\x01$\xbc\r\u0752\xe5`\x00\x00\u07d4\xca\xef\x02{\x1a\xb5\x04\xc7?A\xf2\xa1\ty\xb4t\xf9~0\x9f\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xca\xf4H\x1d\x9d\xb7\x8d\xc4\xf2_{J\u023d;\x1c\xa0\x10k1\x8a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\xca\xfd\xe8U\x86L%\x98\xda<\xaf\xc0Z\u064d\U00089380H\x8a\x03\x00\xa8\xed\x96\xffJ\x94\x00\x00\xe0\x94\xcb\r\xd7\xcfN]\x86a\xf6\x02\x89C\xa4\xb9\xb7\\\x91D6\xa7\x8a\x19i6\x89t\xc0[\x00\x00\x00\u07d4\xcb\x1b\xb6\xf1\xda^\xb1\rH\x99\xf7\xe6\x1d\x06\xc1\xb0\x0f\u07f5-\x898E$\xccp\xb7x\x00\x00\u07d4\xcb=vl\x98?\x19+\xce\xca\xc7\x0fN\xe0=\xd9\xffqMQ\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xcbB\xb4N\xb5\xfd`\xb5\x83~O\x9e\xb4rgR=\x1a\"\x9c\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xcbG\xbd0\u03e8\xecTh\xaa\xa6\xa9FB\xce\xd9\xc8\x19\xc8\u0509\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xcbH\xfe\x82e\u066fU\xebp\x06\xbc3VE\xb0\xa3\xa1\x83\xbe\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xcbJ\x91M+\xb0)\xf3._\xef\\#LO\xec--\xd5w\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xcbJ\xbf\u0082\xae\xd7n]W\xaf\xfd\xa5B\xc1\xf3\x82\xfc\xac\xf4\x8a\x01\xb9\x0f\x11\xc3\x18?\xaa\x00\x00\u07d4\xcbJ\xd0\xc7#\xdaF\xabV\xd5&\xda\f\x1d%\xc7=\xaf\xf1\n\x89\x1b\xa5\xab\xf9\xe7y8\x00\x00\u07d4\xcbK\xb1\xc6#\xba(\xdcB\xbd\xaa\xa6\xe7N\x1d*\xa1%l*\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xcbPXt\x12\x82#\x04\xeb\u02e0}\xab:\x0f\t\xff\xfe\u4189JD\x91\xbdm\xcd(\x00\x00\u07d4\xcbX\x99\v\u0350\u03ffm\x8f\t\x86\xf6\xfa`\x02v\xb9N-\x8964\xbf9\xab\x98x\x80\x00\u07d4\xcbh\xaeZ\xbe\x02\xdc\xf8\xcb\u016aq\x9c%\x81FQ\xaf\x8b\x85\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xcbty\x10\x9bC\xb2fW\xf4F_M\x18\xc6\xf9t\xbe_B\x89b\xa9\x92\xe5:\n\xf0\x00\x00\xe0\x94\xcb}+\x80\x89\xe91,\u026e\xaa's\xf3S\b\xecl*{\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u02c6\xed\xbc\x8b\xbb\x1f\x911\x02+\xe6IV^\xbd\xb0\x9e2\xa1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u02d3\x19\x9b\x9c\x90\xbcI\x15\xbd\x85\x9e=B\x86m\xc8\xc1\x87I\x89\f\x90\xdf\a\xde\xf7\x8c\x00\x00\u07d4\u02d4\xe7o\xeb\xe2\b\x11g3\xe7n\x80]H\xd1\x12\xec\x9f\u028965\u026d\xc5\u07a0\x00\x00\u07d4\u02dbQ\x03\xe4\u0389\xafOd\x91aP\xbf\xf9\xee\u02df\xaa\\\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u02e2\\zP<\xc8\xe0\xd0Iq\xca\x05\xc7b\xf9\xb7b\xb4\x8b\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u02e2\x88\xcd<\x1e\xb4\u055d\xdb\x06\xa6B\x1c\x14\xc3E\xa4{$\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u02f3\x18\x9eK\xd7\xf4_\x17\x8b\x1c0\xc7n&1MJK\n\x89\x0f\xfe\vg|e\xa9\x80\x00\xe0\x94\u02f7\xbe\x17\x95?,\u0313\u1f19\x80[\xf4U\x11CNL\x8a\n\xae[\x9d\xf5m/ \x00\x00\xe0\x94\xcb\xc0KM\x8b\x82\xca\xf6p\x99o\x16\f6)@\xd6o\xcf\x1a\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcb\u07974\xb8\xe6\xaaS\x8c)\x1dm\u007f\xac\xed\xb0\xf38\xf8W\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xcb\xe1\xb9H\x86M\x84t\xe7e\x14XX\xfc\xa4U\x0fxK\x92\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xe5/\xc53\xd7\xdd`\x8c\x92\xa2`\xb3|?E\u07b4\xeb3\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcb\xe8\x10\xfe\x0f\xec\xc9dGJ\x1d\xb9w(\xbc\x87\xe9s\xfc\xbd\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xf1j\x0f\xe2tRX\xcdR\xdb+\xf2\x19T\xc9u\xfcj\x15\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\xcb\xf3\u007f\xf8T\xa2\xf1\xceS\x93D\x94wx\x92\xd3\xeceW\x82\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcb\xfaj\xf6\u0083\xb0F\xe2w,`c\xb0\xb2\x15S\xc4\x01\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcb\xfav\xdb\x04\xce8\xfb ]7\xb8\xd3w\xcf\x13\x80\xda\x03\x17\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xcc\x03I\x85\xd3\xf2\x8c-9\xb1\xa3K\xce\xd4\u04f2\xb6\xca#N\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xcc\x04\x8d\u01f9]\xca%\xdf&\xee\xfac\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcc+_D\x8f5(\xd3\xfeA\xcc}\x1f\xa9\xc0\xdcv\xf1\xb7v\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xcc-\x04\xf0\xa4\x01q\x89\xb3@\xcaw\x19\x86A\xdc\xf6Ek\x91\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94\xccA\x9f\u0651+\x85\x13VY\xe7z\x93\xbc=\xf1\x82\xd4Q\x15\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xccE\xfb:U[\xad\x80{8\x8a\x03W\xc8U _|u\xe8\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xccHAM*\xc4\xd4*Yb\xf2\x9e\xeeD\x97\t/C\x13R\x89\b\xbaR\xe6\xfcE\xe4\x00\x00\u07d4\xccJ/,\xf8l\xf3\xe43u\xf3`\xa4sF\x91\x19_\x14\x90\x89I\x15\x05;\xd1)\t\x80\x00\u07d4\xccO\x0f\xf2\xae\xb6}T\xce;\xc8\xc6Q\v\x9a\xe8>\x9d2\x8b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xccO\xaa\xc0\v\xe6b\x8f\x92\xefk\x8c\xb1\xb1\xe7j\xac\x81\xfa\x18\x89\v\"\xa2\xea\xb0\xf0\xfd\x00\x00\xe0\x94\xccO\xebr\u07d8\xff5\xa18\xe0\x17a\xd1 ?\x9b~\xdf\n\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xcc`oQ\x13\x97\xa3\x8f\u01c7+\u04f0\xbd\x03\xc7\x1b\xbdv\x8b\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xcc`\xf86\xac\xde\xf3T\x8a\x1f\xef\u0321>\u01a97\xdbD\xa0\x89\x04\xb0m\xbb\xb4\x0fJ\x00\x00\u07d4\xccl\x03\xbd`>\t\xdeT\xe9\xc4\u056cmA\xcb\xceqW$\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\xccl-\xf0\x0e\x86\xec\xa4\x0f!\xff\xda\x1ag\xa1i\x0fG|e\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94\xccm{\x12\x06\x1b\xc9m\x10M`me\xff\xa3+\x006\xeb\a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xccs\xdd5kIy\xb5y\xb4\x01\xd4\xccz1\xa2h\xdd\xceZ\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xccu\x8d\a\x1d%\xa62\n\xf6\x8c]\xc9\xc4\xf6\x95[\xa9E \x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcc{\x04\x81\xcc2\xe6\xfa\xef#\x86\xa0p\"\xbc\xb6\xd2\u00f4\xfc\x89\xabM\xcf9\x9a:`\x00\x00\xe0\x94\u0314;\xe1\",\xd1@\n#\x99\xdd\x1bE\x94E\xcfmT\xa9\x8a\x02\xa7@\xaee6\xfc\x88\x00\x00\u07d4\u0315\x19\xd1\xf3\x98_k%^\xad\xed\x12\xd5bJ\x97'!\xe1\x8965\u026d\xc5\u07a0\x00\x00\u0794\u031a\xc7\x15\xcdo&\x10\xc5+XgdV\x88B\x97\x01\x8b)\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\u0320{\xb7\x94W\x1dJ\xcf\x04\x1d\xad\x87\xf0\xd1\xef1\x85\xb3\x19\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u032b\xc6\x04\x8aSFD$\xfc\xf7n\xeb\x9en\x18\x01\xfa#\u0509\x02\xab{&\x0f\xf3\xfd\x00\x00\u07d4\u032e\r=\x85*}\xa3\x86\x0f\x066\x15L\nl\xa3\x16(\u0509\x05\xc6\xd1+k\xc1\xa0\x00\x00\u07d4\xcc\xca$\xd8\xc5mn,\a\xdb\bn\xc0~X[\xe2g\xac\x8d\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xcc\xd5!\x13-\x98l\xb9hi\x84&\"\xa7\u0762l>\xd0W\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcc\xf49u\xb7k\xfes_\xec<\xb7\xd4\xdd$\xf8\x05\xba\tb\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xcc\xf6*f?\x13S\xba.\xf8\xe6R\x1d\xc1\xec\xb6s\xec\x8e\xf7\x89\b=lz\xabc`\x00\x00\u07d4\xcc\xf7\x11\r\x1b\u0667K\xfd\x1d}}-\x9dU`~{\x83}\x890\xca\x02O\x98{\x90\x00\x00\u07d4\xcc\xfdrW`\xa6\x88#\xff\x1e\x06/L\xc9~\x13`\xe8\u0657\x89\x15\xacV\xed\xc4\xd1,\x00\x00\u07d4\xcd\x02\x0f\x8e\xdf\xcfRG\x98\xa9\xb7:d\x034\xbb\xf7/\x80\xa5\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xcd\x06\xf8\xc1\xb5\u037d(\xe2\xd9kcF\xc3\xe8Z\x04\x83\xba$\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcd\a.n\x183\x13y\x95\x19m{\xb1r_\xef\x87a\xf6U\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xcd\n\x16\x1b\xc3g\xae\t'\xa9*\xac\x9c\xf6\xe5\bg\x14\xef\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\xcd\n\xf3GN\"\xf0i\xec4\a\x87\r\xd7pD=[\x12\xb0\x89\x8e^\xb4\xeew\xb2\xef\x00\x00\u07d4\xcd\v\x02W\u70e3\xd2\xc2\u3e9dny\xb7^\xf9\x80$\u0509\x9f\xad\x06$\x12y\x16\x00\x00\u07d4\xcd\x10,\xd6\xdb=\xf1J\u05af\x0f\x87\xc7$y\x86\x1b\xfc=$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcd\x1ef\xedS\x9d\xd9/\xc4\v\xba\xa1\xfa\x16\u078c\x02\xc1ME\x89\fw\xe4%hc\xd8\x00\x00\u07d4\xcd\x1e\xd2c\xfb\xf6\xf6\xf7\xb4\x8a\xef\x8fs=2\x9dC\x82\xc7\u01c9\x01\x00\xbd3\xfb\x98\xba\x00\x00\u07d4\xcd*6\xd7S\xe9\xe0\xed\x01*XMqh\aX{A\xd5j\x89\x0e+\xa7[\v\x1f\x1c\x00\x00\u07d4\xcd2\xa4\xa8\xa2\u007f\x1c\xc69T\xaacOxW\x05s4\u01e3\x89:\xd1fWlr\xd4\x00\x00\u07d4\xcd5\xff\x01\x0e\xc5\x01\xa7!\xa1\xb2\xf0z\x9c\xa5\x87}\xfc\xf9Z\x89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4\xcdC\x06\xd7\xf6\x94z\xc1tMN\x13\xb8\xef2\xcbe~\x1c\x00\x89\x1b\x1a\xb3\x19\xf5\xecu\x00\x00\u07d4\xcdC%\x8bs\x92\xa90\x83\x9aQ\xb2\xef\x8a\xd24\x12\xf7Z\x9f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcdI\xbf\x18^p\xd0E\a\x99\x9f\x92\xa4\xdeDU1('\u040965\u026d\xc5\u07a0\x00\x00\u07d4\xcdU\x10\xa2B\u07f0\x18=\xe9%\xfb\xa8f\xe3\x12\xfa\xbc\x16W\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xcdVj\u05f8\x83\xf0\x1f\u04d9\x8a\x9aX\xa9\xde\xe4rM\u0725\x89\x030\xae\x185\xbe0\x00\x00\xe0\x94\xcdY\xf3\xdd\xe7~\t\x94\v\xef\xb6\xeeX\x03\x19e\xca\xe7\xa36\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xcdr]p\xbe\x97\xe6w\xe3\xc8\xe8\\\v&\xef1\xe9\x95PE\x89Hz\x9a0E9D\x00\x00\xe0\x94\xcd~G\x90\x94d\xd8q\xb9\xa6\xdcv\xa8\xe9\x19]\xb3H^z\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xcd~\xce\bkKa\x9b;6\x93R\xee8\xb7\x1d\xdb\x06C\x9a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xcd\u007f\t\xd7\xedf\xd0\u00cb\u016dN2\xb7\xf2\xb0\x8d\xc1\xb3\r\x89>;\xb3M\xa2\xa4p\x00\x00\u07d4\u0355)I+\\)\xe4u\xac\xb9A@+=;\xa5\x06\x86\xb0\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0355\xfaB=o\xc1 'J\xac\xde\x19\xf4\xee\xb7f\xf1\x04 \x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u035bL\xefs9\f\x83\xa8\xfdq\u05f5@\xa7\xf9\u03cb\x8c\x92\x89\x04\xe1\x00;(\xd9(\x00\x00\u07d4\u0361t\x11\t\xc0&[?\xb2\xbf\x8d^\xc9\u00b8\xa34kc\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0361\xb8\x86\u39d5\u027aw\x91N\n/\xe5go\x0f\\\u03c9\x05\xbf`\xeaB\xc2\x04\x00\x00\u07d4\u0364S\x0fK\x9b\xc5\t\x05\xb7\x9d\x17\u008f\xc4o\x954\x9b\u07c93\x10\xe0I\x11\xf1\xf8\x00\x00\u07d4\u036bF\xa5\x90 \x80do\xbf\x95B\x04 J\xe8\x84\x04\x82+\x89\x1d\x8a\x96\xe5\xc6\x06\xeb\x00\x00\u07d4\u0375\x97)\x900\x18?n-#\x853\xf4d*\xa5\x87T\xb6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xcd\xd5\u0601\xa76,\x90p\a;\u07fcu\xe7$S\xacQ\x0e\x89-\xa5\x18\xea\xe4\x8e\xe8\x00\x00\u07d4\xcd\xd6\rs\xef\xaa\xd8s\u027b\xfb\x17\x8c\xa1\xb7\x10Z\x81\xa6\x81\x89\x01\xbc\x16\xd6t\xec\x80\x00\x00\u07d4\xcd\xd9\xef\xacMm`\xbdq\xd9U\x85\xdc\xe5\u0557\x05\xc15d\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xcd\xe3m\x81\xd1(\u015d\xa1Ee!\x93\xee\u00bf\xd9e\x86\xef\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xcd\xea8o\x9d\x0f\xd8\x04\xd0(\x18\xf27\xb7\xd9\xfavF\xd3^\x89\xa3I\xd3m\x80\xecW\x80\x00\u07d4\xcd\xec\xf5gT3\u0370\xc2\xe5Zh\xdb]\x8b\xbexA\x9d\u0489\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xcd\xfd\x82\x173\x97%\xd7\xeb\xac\x11\xa66U\xf2e\xef\xf1\xcc=\x8a\x01\x0f\fid\x10\xe3\xa9\x00\x00\u07d4\xce\a\x9fQ\x88wt\xd8\x02\x1c\xb3\xb5u\xf5\x8f\x18\xe9\xac\xf9\x84\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xce\x18\x84\u077b\xb8\xe1\x0eM\xbanD\xfe\xee\u00a7\xe5\xf9/\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xce\x1b\f\xb4j\xae\xcf\u05db\x88\f\xad\x0f-\u068a\x8d\xed\u0431\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xce&\xf9\xa50_\x83\x81\tCT\xdb\xfc\x92fN\x84\xf9\x02\xb5\x89\fz\xaa\xb0Y\x1e\xec\x00\x00\u07d4\xce-\xea\xb5\x1c\n\x9a\xe0\x9c\xd2\x12\xc4\xfaL\xc5+S\xcc\r\xec\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xce.\r\xa8\x93F\x99\xbb\x1aU>U\xa0\xb8\\\x16\x945\xbe\xa3\x8a\x01\x0f\fid\x10\xe3\xa9\x00\x00\u07d4\xce:a\xf0F\x1b\x00\x93^\x85\xfa\x1e\xad\x82\xc4^Zd\u0508\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xceK\x06]\xbc\xb20G 2b\xfbH\xc1\x18\x83d\x97tp\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xceS\xc8\xcd\xd7B\x96\xac\xa9\x87\xb2\xbc\x19\u00b8u\xa4\x87I\u0409\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xce^\x04\xf0\x18Ci\xbc\xfa\x06\xac\xa6o\xfa\x91\xbfY\xfa\x0f\xb9\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xce^\xb6:{\xf4\xfb\xc2\xf6\u4ea0\u018a\xb1\xcbL\xf9\x8f\xb4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xceb\x12Z\xde\xc37\n\xc5!\x10\x95:Nv\v\xe9E\x1e;\x89\b=lz\xabc`\x00\x00\xe0\x94\xceq\bmL`%T\xb8-\xcb\xfc\xe8\x8d cMS\xccM\x8a\t(\x96R\x9b\xad\u0708\x00\x00\u07d4\u038akmP3\xb1I\x8b\x1f\xfe\xb4\x1aAU\x04\x05\xfa\x03\xa2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0397\x86\xd3q/\xa2\x00\xe9\xf6\x857\xee\xaa\x1a\x06\xa6\xf4ZK\x89a\t=|,m8\x00\x00\u07d4\u039d!\u0192\xcd<\x01\xf2\x01\x1fP_\x87\x006\xfa\x8fl\u0489\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\u03a2\x89f#\xf4\x91\x02\x87\xa2\xbd\u017e\x83\xae\xa3\xf2\xe6\xde\b\x8a\x01\xfbZ7Q\xe4\x90\xdc\x00\x00\u07d4\u03a3JM\xd9=\u066e\xfd9\x90\x02\xa9}\x99z\x1bK\x89\u0349QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\u03a4?pu\x81k`\xbb\xfc\u62d9:\xf0\x88\x12p\xf6\u0109lk\x93[\x8b\xbd@\x00\x00\u07d4\u03a8t3AS<\xb2\xf0\xb9\xc6\xef\xb8\xfd\xa8\rw\x16(%\x89\x05k\xc7^-c\x10\x00\x00\u07d4\u03b0\x89\xec\x8ax3~\x8e\xf8\x8d\xe1\x1bI\xe3\u0751\x0ft\x8f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u03b3=x\xe7Tz\x9d\xa2\xe8}Q\xae\xc5\xf3D\x1c\x87\x92:\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u03b3\x898\x1dH\xa8\xaeO\xfcH:\u043b^ L\xfd\xb1\xec\x89('\xe6\xe4\xddb\xba\x80\x00\u07d4\xce\xc6\xfce\x85?\x9c\xce_\x8e\x84Fv6.\x15y\x01_\x02\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xce\xd3\u01fe\x8d\xe7XQ@\x95*\xebP\x1d\xc1\xf8v\ucbf0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xce\xd8\x1e\xc3S?\xf1\xbf\xeb\xf3\xe3\x84>\xe7@\xad\x11u\x8d>\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xce\u0733\xa1\u0584?\xb6\xbe\xf6Ca}\xea\U000cf398\xdd_\x89\x19\xe2\xa4\xc8\x18\xb9\x06\x00\x00\u07d4\xce\xe6\x99\xc0pzx6%+)/\x04|\xe8\xad(\x9b/U\x89\x11\x9a\x1e!\xaaiV\x00\x00\u07d4\xce\xedG\xca[\x89\x9f\xd1b?!\xe9\xbdM\xb6Z\x10\u5c1d\x89\a8w@L\x1e\xee\x00\x00\u07d4\xce\xf7tQ\u07e2\xc6C\xe0\v\x15mlo\xf8N#s\xebf\x89\n1\x06+\xee\xedp\x00\x00\u07d4\xcf\x11i\x04\x1c\x17E\xe4[\x17$5\xa2\xfc\x99\xb4\x9a\xce+\x00\x89\x01\xbb\x88\xba\xab-|\x00\x00\xe0\x94\xcf\x15v\x12vN\x0f\u0596\xc8\xcb_\xba\x85\xdfL\r\xdc<\xb0\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u0794\xcf\x1b\xdby\x9b.\xa6<\xe14f\x8b\xdc\x19\x8bT\x84\x0f\x18\v\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xcf\"\x88\xefN\xbf\x88\xe8m\xb1=\x8a\x0e\v\xf5*\x05e\x82\u00c9\x89Po\xbf\x97@t\x00\x00\u07d4\xcf&Ni%\x13\t\x06\xc4\xd7\xc1\x85\x91\xaaA\xb2\xa6\u007foX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf&\xb4{\xd04\xbcP\x8elK\xcf\xd6\xc7\xd3\x004\x92Wa\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xcf.*\xd65\xe9\x86\x1a\xe9\\\xb9\xba\xfc\xca\x03kR\x81\xf5\u038a\at2!~h6\x00\x00\x00\u07d4\xcf.s@B\xa3U\xd0_\xfb.9\x15\xb1h\x11\xf4Zi^\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf4\x8f/\xe4{~A<\az{\xaf:u\xfb\xf8B\x86\x92\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xcf?\x91(\xb0r\x03\xa3\xe1\r}WU\xc0\u012b\xc6\xe2\xca\u008a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xcf?\xbf\xa1\xfd2\u05e6\xe0\xe6\xf8\xefN\xabW\xbe4\x02\\L\x899\xa1\xc0\xf7YMH\x00\x00\u07d4\xcfAftn\x1d;\xc1\xf8\xd0qK\x01\xf1~\x8ab\xdf\x14d\x896w\x03n\xdf\n\xf6\x00\x00\u07d4\xcfO\x118\xf1\xbdk\xf5\xb6\u0505\xcc\xe4\xc1\x01\u007f\u02c5\xf0}\x89/\u043cw\xc3+\xff\x00\x00\u07d4\xcfZo\x9d\xf7Uy\xc6D\xf7\x94q\x12\x15\xb3\rw\xa0\xce@\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcf^\x0e\xac\u0473\x9d\x06U\xf2\xf7u5\xeff\b\xeb\x95\v\xa0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xcfhM\xfb\x83\x04r\x93U\xb5\x83\x15\xe8\x01\x9b\x1a\xa2\xad\x1b\xac\x89\x17r$\xaa\x84Lr\x00\x00\u07d4\xcfi@\x81\xc7m\x18\xc6L\xa7\x13\x82\xbe\\\xd6;<\xb4v\xf8\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xcfnR\xe6\xb7t\x80\xb1\x86~\xfe\xc6Dm\x9f\xc3\xcc5w\xe8\x89\f\t\x01\xf6\xbd\x98y\x00\x00\u07d4\u03c8: 2\x96g\xea\"j\x1e\x9a\x92*\x12\xf2\x1f\xaa\x03\x81V\x91\x8cO\u02dc\x89\x04E\x91\xd6\u007f\xec\xc8\x00\x00\u07d4\xcf\xf7\xf8\x9aMB\x19\xa3\x82\x95%\x131V\x82\x10\xff\xc1\xc14\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xcf\xf8\xd0k\x00\xe3\xf5\f\x19\x10\x99\xadV\xbaj\xe2eq\u0348\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xcf\xfcI\xc1x~\ubcb5l\xab\xe9$\x04\xb66\x14}EX\x8a\x013\xe00\x8f@\xa3\u0680\x00\u07d4\xd0\bQ;'`J\x89\xba\x17c\xb6\xf8L\u6233F\x94[\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\x0f\x06r\x86\xc0\xfb\u0402\xf9\xf4\xa6\x10\x83\xecv\u07b3\xce\xe6\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\x15\xf6\xfc\xb8M\xf7\xbbA\x0e\x8c\x8f\x04\x89J\x88\x1d\xca\xc27\x898E$\xccp\xb7x\x00\x00\u07d4\xd0\x1a\xf9\x13O\xafRW\x17N\x8by\x18oB\xee5Nd-\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0!\b\u04ae<\xab\x10\xcb\xcf\x16W\xaf\">\x02|\x82\x10\xf6\x89lm\x84\xbc\xcd\xd9\xce\x00\x00\u07d4\xd0*\xfe\u03ce.\u00b6*\u022d Aa\xfd\x1f\xaew\x1d\x0e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd01\x919\xfb\xab.\x8e*\xcc\xc1\xd9$\u0531\x1d\xf6ilZ\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd07\xd2\x15\xd1\x1d\x1d\xf3\xd5O\xbd2\x1c\u0495\xc5F^';\x89K\xe4\xe7&{j\xe0\x00\x00\u07d4\xd0:-\xa4\x1e\x86\x8e\xd3\xfe\xf5t[\x96\xf5\xec\xa4b\xffo\u0689\xa2\xa1]\tQ\x9b\xe0\x00\x00\xe0\x94\xd0?\xc1eWj\xae\xd5%\xe5P,\x8e\x14\x0f\x8b.\x86\x969\x8a\x01sV\u0633%\x01\xc8\x00\x00\u07d4\xd0C\xa0\x11\xecBp\xee~\u0239hsu\x15\xe5\x03\xf80(\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd0K\x86\x1b=\x9a\xccV:\x90\x16\x89\x94\x1a\xb1\xe1\x86\x11a\xa2\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd0ZD|\x91\x1d\xbb'[\xfb.Z7\xe5\xa7\x03\xa5o\x99\x97\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd0_\xfb+t\xf8g O\xe51e;\x02H\xe2\x1c\x13TN\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0bX\x81q\u03d9\xbb\xebX\xf1&\xb8p\xf9\xa3r\x8da\xec\x89\xf3\xf2\v\x8d\xfai\xd0\x00\x00\u07d4\xd0c\x8e\xa5q\x89\xa6\xa6\x99\x02J\u05ccq\xd99\xc1\xc2\xff\x8c\x89\x8e\xaeVg\x10\xfc \x00\x00\xe0\x94\xd0d\x8aX\x1b5\b\xe15\xa2\x93]\x12\xc9epE\xd8q\u028a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4\xd0q\x19)f\xebi\xc3R\x0f\xca:\xa4\xdd\x04)~\xa0KN\x89\x05\xf6\x8e\x811\xec\xf8\x00\x00\u07d4\xd0q\x85 \xea\xe0\xa4\xd6-p\xde\x1b\xe0\xcaC\x1c^\xea$\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd0w]\xba*\xf4\xc3\n:x6Y9\xcdq\xc2\xf9\u0795\u0489i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xd0{\xe0\xf9\t\x97\xca\xf9\x03\u022c\x1dS\xcd\xe9\x04\xfb\x19\aA\x8968\x908\xb6\x99\xb4\x00\x00\u07d4\xd0~Q\x18d\xb1\u03d9i\xe3V\x06\x02\x82\x9e2\xfcNq\xf5\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\u0400\x94\x98\xc5H\x04z\x1e**\xa6\xa2\x9c\xd6\x1a\x0e\xe2h\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0402'_tZ,\xac\x02v\xfb\xdb\x02\u0532\xa3\xab\x17\x11\xfe\x89\x01\xa0Ui\r\x9d\xb8\x00\x00\u07d4\u040f\xc0\x9a\x000\xfd\t(\xcd2\x11\x98X\x01\x82\xa7j\xae\x9f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0413\xe8)\x81\x9f\xd2\xe2[\x978\x00\xbb=XA\xdd\x15-\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0414J\xa1\x85\xa13pa\xae \u071d\xd9l\x83\xb2\xbaF\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u0416V[|t\a\xd0e6X\x03U\xfd\xd6\xd29\x14J\xa1\x89\r\x8drkqw\xa8\x00\x00\u07d4\u041c\xb2\xe6\b-i:\x13\xe8\xd2\xf6\x8d\xd1\u0744a\xf5X@\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u0426\xc6\xf9\xe9\u0133\x83\xd7\x16\xb3\x1d\xe7\x8dVAM\xe8\xfa\x91\x89\x10CV\x1a\x88)0\x00\x00\u07d4\u0427 \x9b\x80\xcf`\xdbb\xf5}\n]}R\x1ai`fU\x89\b\xacr0H\x9e\x80\x00\x00\xe0\x94\u0428\xab\xd8\n\x19\x9bT\xb0\x8be\xf0\x1d \x9c'\xfe\xf0\x11[\x8a\x01a\xc6&\xdca\xa2\xef\x80\x00\xe0\x94\u042b\xccp\xc0B\x0e\x0e\x17/\x97\xd4;\x87\xd5\xe8\f3n\xa9\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u042es]\x91^\x94hf\xe1\xfe\xa7~^\xa4f\xb5\xca\xdd\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0431\x1do+\u0394^\fjP \u00f5'S\xf8\x03\xf9\u0449\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xd0\xc1\x01\xfd\x1f\x01\xc6?k\x1d\x19\xbc\x92\r\x9f\x93#\x14\xb16\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd0\xc5Z\xbf\x97o\xdc=\xb2\xaf\u9f99\u0519HMWl\x02\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd0\u0422\xadE\xf5\x9a\x9d\xcc\u0195\xd8_%\xcaF\xed1\xa5\xa3\x89-\x89W}}@ \x00\x00\u07d4\xd0\xd6,G\xea`\xfb\x90\xa3c\x92\t\xbb\xfd\xd4\xd93\x99\x1c\u0189\n\x84Jt$\xd9\xc8\x00\x00\u07d4\xd0\xdbEax o\\D0\xfe\x00Pc\x90<=zI\xa7\x89&I\x1eE\xa7S\xc0\x80\x00\u07d4\xd0\xe1\x94\xf3K\x1d\xb6\t(\x85\t\xcc\xd2\xe7;a1\xa2S\x8b\x8965f3\xeb\xd8\xea\x00\x00\u07d4\xd0\xe3^\x04vF\xe7Y\xf4Qp\x93\xd6@\x86BQ\u007f\bM\x89\u054f\xa4h\x18\xec\u02c0\x00\u07d4\xd0\xeeM\x02\xcf$8,0\x90\xd3\xe9\x95`\xde6xs\\\u07c9\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\xd0\xf0OR\x10\x9a\xeb\xec\x9a{\x1e\x932v\x1e\x9f\xe2\xb9{\xb5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd0\xf9Yx\x11\xb0\xb9\x92\xbb}7W\xaa%\xb4\xc2V\x1d2\xe2\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\x03\x02\xfa\xa1\x92\x9a2i\x04\xd3v\xbf\v\x8d\xc9:\xd0LL\x89a\t=|,m8\x00\x00\xe0\x94\xd1\x10\r\xd0\x0f\xe2\xdd\xf1\x81c\xad\x96M\vi\xf1\xf2\xe9e\x8a\x8a\x01C\x12\tU\xb2Pk\x00\x00\u07d4\xd1\x16\xf3\xdc\xd5\xdbtK\xd0\b\x88v\x87\xaa\x0e\xc9\xfdr\x92\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd1\x19A|Fs,\xf3M\x1a\x1a\xfby\xc3\xe7\xe2\u034e\xec\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1-w\xae\x01\xa9-5\x11{\xacpZ\xac\u0642\xd0.t\xc1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd15yK\x14\x9a\x18\xe1G\xd1nb\x1ai1\xf0\xa4\n\x96\x9a\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xd1C%8\xe3[vd\x95j\u4563*\xbd\xf0A\xa7\xa2\x1c\x8a\x04+\xf0kx\xed;P\x00\x00\u07d4\xd1C\x82g#\x17\x04\xfcr\x80\xd5c\xad\xf4v8D\xa8\a\"\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd1S\x8e\x9a\x87\u5729\xec\x8eX&\xa5\xb7\x93\xf9\x9f\x96\xc4\u00c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd1d\x85\x03\xb1\xcc\u0178\xbe\x03\xfa\x1e\xc4\xf3\xee&~j\xdf{\x8a\x01;\xef\xbfQ\xee\xc0\x90\x00\x00\xe0\x94\xd1h,!Y\x01\x8d\xc3\xd0\u007f\b$\n\x8c`m\xafe\xf8\xe1\x8a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xd1q\xc3\xf2%\x8a\xef5\xe5\x99\xc7\xda\x1a\xa0s\x00#M\xa9\xa6\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1w\x8c\x13\xfb\xd9h\xbc\b<\xb7\xd1\x02O\xfe\x1fI\xd0,\xaa\x89\xd9\xec\xb4\xfd \x8eP\x00\x00\u07d4\xd1\u007f\xbe\"\xd9\x04b\xed7(\x06p\xa2\xea\v0\x86\xa0\xd6\u0589\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\u0441\x1cU\x97i\x80\xf0\x83\x90\x1d\x8a\r\xb2i\"-\xfb\\\xfe\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\u044e\xb9\xe1\u0485\u06be\x93\xe5\u053a\xe7k\xee\xfeC\xb5!\xe8\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\u0453\xe5\x83\xd6\a\x05c\xe7\xb8b\xb9aJG\u9509\xf3\xe5\x8965f3\xeb\xd8\xea\x00\x00\u07d4\u0457\x8f.4@\u007f\xab\x1d\xc2\x18=\x95\xcf\xdab`\xb3Y\x82\x89*\xb7\xb2`\xff?\xd0\x00\x00\u07d4\u045c\xaf9\xbb7\u007f\xdf,\xf1\x9b\xd4\xfbRY\x1c&1\xa6<\x8965\u026d\xc5\u07a0\x00\x00\u0794\u0463\x96\xdc\u06b2\xc7IA0\xb3\xfd0x 4\r\xfd\x8c\x1f\x88\xf9\"P\xe2\xdf\xd0\x00\x00\xe0\x94\u0467\x1b-\bX\xe82p\b]\x95\xa3\xb1T\x96P\x03^#\x8a\x03'\xbb\t\xd0j\xa8P\x00\x00\u07d4\u046c\xb5\xad\xc1\x189s%\x8dk\x85$\xff\xa2\x8f\xfe\xb2=\xe3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u0473\u007f\x03\xcb\x10t$\xe9\xc4\xddW\\\xcdOL\xeeW\xe6\u0349lk\x93[\x8b\xbd@\x00\x00\u07d4\u0475\xa4T\xac4\x05\xbbAy \x8cl\x84\xde\x00k\u02db\xe9\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\xc4YT\xa6+\x91\x1a\xd7\x01\xff.\x90\x13\x1e\x8c\xeb\x89\xc9\\\x89K\x91\xa2\xdeE~\x88\x00\x00\u07d4\xd1\xc9np\xf0Z\xe0\xe6\xcd`!\xb2\b7P\xa7q|\xdeV\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\u0571\u007f\xfe-{\xbby\xcc}y0\xbc\xb2\xe5\x18\xfb\x1b\xbf\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd1\xda\f\x8f\xb7\xc2\x10\xe0\xf2\xeca\x8f\x85\xbd\xae}>sK\x1c\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd1\xddy\xfb\x15\x81`\xe5\xb4\xe8\xe2?1.j\x90\u007f\xbcMN\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd1\xdeZ\xad:_\xd8\x03\U00071bb6\x10<\xb8\xe1O\xe7#\xb7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd1\xe1\xf2\xb9\xc1l0\x98t\xde\xe7\xfa\xc3&u\xaf\xf1)\u00d8\x89\x03\xf2M\x8eJ\x00p\x00\x00\xe0\x94\xd1\xe5\xe24\xa9\xf4Bf\xa4\xa6$\x1a\x84\u05e1\xa5Z\u0567\xfe\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd1\xeaMr\xa6{[>\x0f1UY\xf5+\xd0aMq0i\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd1\xee\x90YW\xfe|\xc7\x0e\xc8\xf2\x86\x8bC\xfeG\xb1?\xeb\xff\x89\x02b\x9ff\xe0\xc50\x00\x00\u07d4\xd1\xf1iM\"g\x1bZ\xadj\x94\x99\\6\x9f\xbea3go\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd1\xf4\xdc\x1d\u06ca\xbb\x88H\xa8\xb1N%\xf3\xb5Z\x85\x91\xc2f\x89\r\x8drkqw\xa8\x00\x00\u07d4\xd1\xfe\u042e\xe6\xf5\xdf\xd7\xe2Wi%L<\xfa\xd1Z\xde\u032a\x89'\x92\xc8\xfcKS(\x00\x00\u07d4\xd2\x05\x1c\xb3\xcbg\x04\xf0T\x8c\u0210\xab\n\x19\xdb4\x15\xb4*\x89\x12\x1b.^ddx\x00\x00\u07d4\xd2\x06\xaa\u07736\xd4^yr\xe9<\xb0uG\x1d\x15\x89{]\x89 \x86\xac5\x10R`\x00\x00\u07d4\xd2\tH+\xb5I\xab\xc4w{\xeam\u007fe\x00b\xc9\xc5z\x1c\x89\x11e\x1a\xc3\xe7\xa7X\x00\x00\u07d4\xd2\r\xcb\vxh+\x94\xbc0\x00(\x14H\xd5W\xa2\v\xfc\x83\x890\x84\x9e\xbe\x166\x9c\x00\x00\u07d4\xd2\x10{57&\u00e2\xb4ef\xea\xa7\xd9\xf8\v]!\xdb\xe3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd2\x11\xb2\x1f\x1b\x12\xb5\ta\x81Y\r\xe0~\xf8\x1a\x89S~\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd2\x18\xef\xb4\u06d8\x1c\xddjy\u007fK\u050c|&)<\xeb@\x89\xa1Fk1\xc6C\x1c\x00\x00\xe0\x94\xd2\x1asA\xeb\x84\xfd\x15\x10T\xe5\u31fb%\xd3nI\x9c\t\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xd2$\xf8\x80\xf9G\x9a\x89\xd3/\t\xe5+\u9432\x88\x13\\\xef\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xd2/\f\xa4\xcdG\x9ef\x17u\x05;\xccI\xe3\x90\xf6p\u074a\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd21\x92\x975\x13!\x02G\x1b\xa5\x90\a\xb6dL\xc0\xc1\xde>\x8967\tlK\xcci\x00\x00\u07d4\xd25\xd1\\\xb5\xec\xee\xbba)\x9e\x0e\x82\u007f\xa8'H\x91\x1d\x89\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd2:$\xd7\xf9F\x83C\xc1C\xa4\x1ds\xb8\x8f|\xbec\xbe^\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd2=z\xff\xac\xdc>\x9f=\xaez\xfc\xb4\x00oX\xf8\xa4F\x00\x89\xc3(\t>a\xee@\x00\x00\u07d4\xd2C\x18L\x80\x1e]y\xd2\x06?5x\u06ee\x81\u7ce9\u02c9k\u0722h\x1e\x1a\xba\x00\x00\u07d4\xd2KfD\xf49\xc8\x05\x1d\xfcd\u04c1\xb8\xc8lu\xc1u8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd2K\xf1--\xdfE}\xec\xb1xt\xef\xde R\xb6\\\xbbI\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\xe0\x94\xd2Q\xf9\x03\xae\x18rrY\xee\xe8A\xa1\x89\xa1\xf5i\xa5\xfdv\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd2R\x96\v\v\xf6\xb2\x84\x8f\u07ad\x80\x13m\xb5\xf5\a\xf8\xbe\x02\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd2X\x1aU\xce#\xab\x10\u062d\x8cD7\x8fY\a\x9b\xd6\xf6X\x8a\x01\xdd\f\x88_\x9a\r\x80\x00\x00\u07d4\xd2Z\xec\xd7\xeb\x8b\xd64[\x06;]\xbd'\x1cw\xd3QD\x94\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xd2|#O\xf7\xac\xca\xce=\x99g\b\xf8\xf9\xb0Ip\xf9}6\x89Hz\x9a0E9D\x00\x00\u07d4\u0482\x98RM\xf5\xecK$\xb0\xff\xb9\u07c5\x17\n\x14Z\x9e\xb5\x89\x0f\x98\xa3\xb9\xb37\xe2\x00\x00\xe0\x94\u0483\xb8\xed\xb1\n%R\x8aD\x04\xde\x1ce\xe7A\r\xbc\xaag\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\u0484\xa5\x03\x82\xf8:am9\xb8\xa9\xc0\xf3\x96\xe0\ubfe9]\x8966\xc2^f\xec\xe7\x00\x00\u07d4\u0488\xe7\xcb{\xa9\xf6 \xab\x0ftR\xe5\bc=\x1cZ\xa2v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u049d\xc0\x8e\xfb\xb3\xd7.&?x\xabv\x10\xd0\"m\xe7k\x00\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\u04a00\xac\x89R2_\x9e\x1d\xb3x\xa7\x14\x85\xa2N\x1b\a\xb2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u04a4y@CG\xc5T:\xab)*\xe1\xbbJo\x15\x83W\xfa\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\u04a5\xa0$#\nW\xcc\xc6fv\v\x89\xb0\xe2l\xaf\u0449\u01ca\n\x96YZ\\n\x8a?\x80\x00\u07d4\u04a8\x03'\xcb\xe5\\L{\xd5\x1f\xf9\xdd\xe4\xcad\x8f\x9e\xb3\xf8\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\u04a8Oug\\b\xd8\f\x88ulB\x8e\xee+\xcb\x18T!\x89A\rXj \xa4\xc0\x00\x00\u07d4\u04ab\xd8J\x18\x10\x93\xe5\xe2)\x13oB\xd85\xe8#]\xe1\t\x89\x05k\xe0<\xa3\xe4}\x80\x00\u07d4\u04ac\r:X`^\x1d\x0f\x0e\xb3\xde%\xb2\xca\xd1)\xed`X\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u04bfg\xa7\xf3\xc6\xceV\xb7\xbeAg]\xbb\xad\xfe~\xa9:3\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd2\xdb\xeb\xe8\x9b\x03W\xae\xa9\x8b\xbe\x8eIc8\u07bb(\xe8\x05\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd2\xe2\x1e\xd5hh\xfa\xb2\x8e\tG\x92z\xda\xf2\x9f#\xeb\xadl\x89l\x18O\x13U\xd0\xe8\x00\x00\u07d4\xd2\xe8\x17s\x8a\xbf\x1f\xb4\x86X?\x80\xc3P1\x8b\xed\x86\f\x80\x89\r\x02\xce\xcf_]\x81\x00\x00\u07d4\xd2\xed\xd1\xdd\xd6\xd8m\xc0\x05\xba\xebT\x1d\"\xb6@\xd5\xc7\xca\xe5\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd2\xf1\x99\x8e\x1c\xb1X\f\xecOl\x04}\xcd=\xce\xc5L\xf7<\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd2\xf2A%]\xd7\xc3\xf7<\a\x040q\xec\b\xdd\xd9\xc5\xcd\xe5\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd2\xffg \x16\xf6;/\x859\x8fJo\xed\xbb`\xa5\r<\u0389\x12\x91$o[sJ\x00\x00\u07d4\xd3\rLC\xad\xcfU\xb2\xcbS\u0583#&A4I\x8d\x89\u038965\u026d\xc5\u07a0\x00\x00\u07d4\xd3\x0e\xe9\xa1+Mh\xab\xac\xe6\xba\u029a\u05ff\\\xd1\xfa\xf9\x1c\x89QO\xcb$\xff\x9cP\x00\x00\u07d4\xd3\x11\x8e\xa3\xc85\x05\xa9\u0613\xbbg\xe2\xde\x14-Sz>\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd3\x11\xbc\u05eaN\x9bO8?\xf3\xd0\u05b6\xe0~!\xe3p]\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd3\x15\xde\xea\x1d\x8c\x12q\xf9\xd11\x12c\xabG\xc0\a\xaf\xb6\xf5\x89\x03\xc8\x1dNeK@\x00\x00\u07d4\xd3+,y\xc3dx\xc5C\x19\x01\xf6\xd7\x00\xb0M\xbe\x9b\x88\x10\x89\x15w\x9a\x9d\xe6\xee\xb0\x00\x00\u07d4\xd3+EVF\x14Ql\x91\xb0\u007f\xa9\xf7-\xcfx|\xceN\x1c\x89\x0f\xc6o\xae7F\xac\x00\x00\u07d4\xd30r\x811\xfe\x8e:\x15Hz4W<\x93E~*\xfe\x95\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd31\xc8#\x82Z\x9eRc\xd0R\u0611]M\xcd\xe0z\\7\x89\x1e\x93\x12\x83\xcc\xc8P\x00\x00\u07d4\xd33btE\xf2\u05c7\x90\x1e\xf3;\xb2\xa8\xa3g^'\xff\xec\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd3<\xf8+\xf1LY&@\xa0\x86\b\x91L#py\u057e4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd3Mp\x8ds\x98\x02E3\xa5\xa2\xb20\x9b\x19\xd3\xc5Qq\xbb\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd3N\x03\xd3j+\xd4\u045a_\xa1b\x18\xd1\xd6\x1e?\xfa\v\x15\x89\x11X\xe4`\x91=\x00\x00\x00\u07d4\xd3Pu\xcaa\xfeY\xd1#\x96\x9c6\xa8-\x1a\xb2\xd9\x18\xaa8\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xd3g\x00\x9a\xb6X&;b\xc23:\x1c\x9eA@I\x8e\x13\x89\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd3g\x9aG\xdf-\x99\xa4\x9b\x01\u024d\x1c>\f\x98|\xe1\xe1X\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\xe0\x94\u04cf\xa2\xc4\xcc\x14z\xd0j\u0562\xf7Uy(\x1f\"\xa7\xcc\x1f\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\u04da]\xa4`9+\x94\v\u01ee8\xf1e\u007f\x8a\x01f\xc5H\b\x89\xdbw\x00\x00\xe0\x94\xd3\xd6\xe9\xfb\x82T/\u049e\xd9\xea6\t\x89\x1e\x15\x13\x96\xb6\xf7\x8a\voX\x8a\xa7\xbc\xf5\xc0\x00\x00\xe0\x94\xd3\xda\u0476\u040dE\x81\u032ee\xa8s-\xb6\xaci\xf0\u019e\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xd3\xdf;S\xcb;GU\xdeT\xe1\x80E\x1c\xc4L\x9e\x8a\u0a89#\u0114\t\xb9w\x82\x80\x00\u07d4\xd3\xf8s\xbd\x99V\x13W\x89\xab\x00\xeb\xc1\x95\xb9\"\xe9K%\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4\x02\xb4\xf6\xa0\x99\xeb\xe7\x16\xcb\x14\xdfOy\xc0\xcd\x01\xc6\a\x1b\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd4\r\x00U\xfd\x9a8H\x8a\xff\x92?\xd0=5\xecF\xd7\x11\xb3\x8a\x01\x0f\b\xed\xa8\xe5U\t\x80\x00\u07d4\xd4\x0e\xd6j\xb3\xce\xff$\xca\x05\xec\xd4q\ufd12\xc1__\xfa\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd4\x18\x87\v\xc2\xe4\xfa{\x8aa!\xae\br\xd5RG\xb6%\x01\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xd4\x1d\u007f\xb4\x9f\xe7\x01\xba\xac%qpBl\u0273\x8c\xa3\xa9\xb2\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4\xd4 U\x92\x84@U\xb3\u01e1\xf8\f\xef\xe3\xb8\xebP\x9b\xcd\xe7\x89\t\xb3\xbf\xd3B\xa9\xfc\x80\x00\u07d4\xd4+ \xbd\x03\x11`\x8bf\xf8\xa6\xd1[*\x95\xe6\xde'\u017f\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd44O}\\\xade\xd1~\\-\x0es#\x94=ob\xfe\x92\x89\x0e~\xeb\xa3A\vt\x00\x00\u07d4\xd4>\xe48\xd8=\xe9\xa3ub\xbbN(l\xb1\xbd\x19\xf4\x96M\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd4C4\xb4\xe2:\x16\x9a\f\x16\xbd!\xe8f\xbb\xa5-\x97\x05\x87\x89\x8c\xf2?\x90\x9c\x0f\xa0\x00\x00\xe0\x94\xd4M\x81\xe1\x8fF\xe2\u03f5\xc1\xfc\xf5\x04\x1b\xc8V\x97g\xd1\x00\x8a\a\xb4B\xe6\x84\xf6Z\xa4\x00\x00\u07d4\xd4OJ\xc5\xfa\xd7k\xdc\x157\xa3\xb3\xafdr1\x9bA\r\x9d\x89V\xbcu\xe2\xd61\x00\x00\x00\u07d4\xd4O^\xdf+\xcf$3\xf2\x11\xda\xdd\f\xc4P\xdb\x1b\x00\x8e\x14\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xd4Oj\u00d2;_\xd71\xa4\xc4YD\xecO~\xc5*j\xe4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd4[3A\xe8\xf1\\\x802\x93 \u00d7~;\x90\xe7\x82j~\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xd4]]\xaa\x13\x8d\xd1\xd3t\xc7\x1b\x90\x19\x91h\x11\xf4\xb2\nN\x89\x1f9\x9b\x148\xa1\x00\x00\x00\u07d4\xd4`\xa4\xb9\b\xdd+\x05gY\xb4\x88\x85\vf\xa88\xfcw\xa8\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd4g\xcf\x06L\bq\x98\x9b\x90\u0632\xeb\x14\xcc\xc6;6\b#\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd4k\xaea\xb0'\xe5\xbbB.\x83\xa3\xf9\xc9?<\x8f\xc7}'\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4o\x82#E)\x82\xa1\xee\xa0\x19\xa8\x81n\xfc-o\xc0\ah\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xd4uG\u007f\xa5c\x90\xd30\x17Q\x8dg\x11\x02\u007f\x05\U0008dfc9k\x11\x133\xd4\xfdL\x00\x00\u07d4\xd4|$.\xdf\xfe\xa0\x91\xbcT\xd5}\xf5\xd1\xfd\xb91\x01Gl\x89\x9d\xf7\u07e8\xf7`H\x00\x00\u07d4\xd4}\x86\x85\xfa\xee\x14|R\x0f\u0646p\x91u\xbf/\x88k\xef\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd4\u007fP\u07c9\xa1\xcf\xf9e\x13\xbe\xf1\xb2\xae:)q\xac\xcf,\x89-\x89W}}@ \x00\x00\u07d4\u0502\xe7\xf6\x8eA\xf28\xfeQx)\xde\x15G\u007f\xe0\xf6\xdd\x1d\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u0507\x9f\xd1+\x1f:'\xf7\xe1\tv\x1b#\xca4\xfa#\x06K\x1c\xaf\x00Qn(pJ\x82\xa4\xf8\x89Hz\x9a0E9D\x00\x00\u07d4\xd5\x00\xe4\xd1\u0242K\xa9\xf5\xb65\u03e3\xa8\xc2\u00cb\xbdL\xed\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd5\b\u04dcp\x91oj\xbcL\xc7\xf9\x99\xf0\x11\xf0w\x10X\x02\x89\x05rM$\xaf\xe7\u007f\x00\x00\u07d4\xd5\x0f\u007f\xa0>8\x98v\u04d0\x8b`\xa57\xa6pc\x04\xfbV\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xd5\x13\xa4P\x80\xff/\xeb\xe6,\u0545J\xbe)\xeeDg\xf9\x96\x89\bN\x13\xbcO\xc5\xd8\x00\x00\u07d4\xd5'o\f\xd5\xff\xd5\xff\xb6?\x98\xb5p=U\x94\xed\xe0\x83\x8b\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xd5)KfbB0;m\xf0\xb1\u020d7B\x9b\xc8\xc9e\xaa\x89\x10M\r\x00\u04b7\xf6\x00\x00\u07d4\xd5*\xec\xc6I98\xa2\x8c\xa1\xc3g\xb7\x01\xc2\x15\x98\xb6\xa0.\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\xd5\x99x\xee \xa3\x8c?I\x8dc\xd5\u007f1\xa3\x9fj\x06\x8a\x022\xb3o\xfcg*\xb0\x00\x00\u07d4\u05568\xd3\xc5\xfa\xa7q\x1b\xf0\x85t_\x9d[\xdc#\u0518\u0609lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u055d\x92\xd2\xc8p\x19\x80\xcc\a<7]r\n\xf0dt<\f\x8a\x04\x05\xfd\xf7\u5bc5\xe0\x00\x00\u07d4\u0567\xbe\xc32\xad\xde\x18\xb3\x10KW\x92Tj\xa5\x9b\x87\x9bR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0571\x17\xec\x11n\xb8FA\x89a\xeb~\xdbb\x9c\xd0\xddi\u007f\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\u0572\x84\x04\x010\xab\xf7\xc1\xd1cq#q\xcc~(\xadf\u0689j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u0579\xd2w\u062a\xd2\x06\x97\xa5\x1fv\xe2\tx\x99k\xff\xe0U\x89\a\xc3\xfe<\aj\xb5\x00\x00\u07d4\u057d^\x84U\xc10\x16\x93W\xc4q\xe3\u6077\x99jrv\x89-\x9e(\x8f\x8a\xbb6\x00\x00\u07d4\xd5\u02e5\xb2k\xea]s\xfa\xbb\x1a\xba\xfa\xcd\xef\x85\xde\xf3h\u0309\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd5\xceU\u0476/YC\xc0?\x89\b\xe3\x1f\xe1h\x9d\x8a\x00\x00\u07d4\xd6\x06Q\xe3\x93x4#\xe5\xcc\x1b\xc5\xf8\x89\xe4N\xf7\xea$>\x89\x15\x9ev7\x11)\xc8\x00\x00\u07d4\xd6\t\xbfO\x14n\xeak\r\xc8\xe0m\xdc\xf4D\x8a\x1f\xcc\xc9\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\t\xec\v\xe7\r\n\xd2ong\xc9\xd4v+R\xeeQ\x12,\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd6\nRX\a(R\r\xf7Tk\xc1\xe2\x83)\x17\x88\u06ee\f\x8964\x89\xef?\xf0\xd7\x00\x00\u07d4\xd6\v$s!\xa3*Z\xff\xb9k\x1e'\x99'\xccXM\xe9C\x89z\xd0 \xd6\xdd\xd7v\x00\x00\u07d4\xd6\x11\x02v\xcf\xe3\x1eB\x82ZW\u007fkC]\xbc\xc1\f\xf7d\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd6\x12Y{\xc3\x17C\u01c63\xf63\xf29\xb1\xe9Bk\xd9%\x8a\x10\x17\xf7\u07d6\xbe\x17\x80\x00\x00\u07d4\xd6#J\xafE\xc6\xf2.f\xa2%\xff\xb9:\xddb\x9bN\xf8\x0f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd6.\u06d6\xfc\u259a\xaflT^\x96|\xf1\xc0\xbc\x80R\x05\x89\x04\xa5eSjZ\u0680\x00\u07d4\xd60\v2\x15\xb1\x1d\xe7b\xec\xdeKp\xb7\x92}\x01)\x15\x82\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd69]\xb5\xa4\xbbf\xe6\x0fL\xfb\xcd\xf0\x05{\xb4\xd9xb\xe2\x891T\xc9r\x9d\x05x\x00\x00\xe0\x94\xd6J-P\xf8\x85\x857\x18\x8a$\xe0\xf5\r\xf1h\x1a\xb0~\u05ca\b7Z*\xbc\xca$@\x00\x00\u07d4\xd6X\n\xb5\xedL}\xfaPo\xa6\xfed\xad\\\xe1)pw2\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd6Y\x8b\x13\x86\xe9<\\\u02d6\x02\xffK\xbb\xec\xdb\xd3p\x1d\u0109\f%\xf4\xec\xb0A\xf0\x00\x00\u07d4\xd6dM@\xe9\v\xc9\u007f\xe7\xdf\xe7\u02bd2i\xfdW\x9b\xa4\xb3\x89\b\x9e\x91y\x94\xf7\x1c\x00\x00\xe0\x94\xd6g\f\x03m\xf7T\xbeC\xda\u074fP\xfe\xea(\x9d\x06\x1f\u058a\x01D\xa2\x904H\xce\xf7\x80\x00\u07d4\xd6hR:\x90\xf0)=e\xc58\xd2\xddlWg7\x10\x19n\x89\x02$,0\xb8S\xee\x00\x00\u07d4\xd6j\xb7\x92\x94\aL\x8bb}\x84-\xabA\xe1}\xd7\f]\xe5\x8965\u026d\xc5\u07a0\x00\x00\u0794\xd6j\xcc\r\x11\xb6\x89\u03a6\xd9\xea_\xf4\x01L\"J]\xc7\u0108\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xd6m\xdf\x11Y\xcf\"\xfd\x8czK\xc8\u0540wV\xd43\xc4>\x89wC\"\x17\xe6\x83`\x00\x00\u07d4\u0587\xce\xc0\x05\x90\x87\xfd\xc7\x13\xd4\xd2\xd6^w\xda\xef\xed\xc1_\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\u0588\xe7\x85\u024f\x00\xf8K:\xa1S3U\u01e2X\xe8yH\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u05a2.Y\x8d\xab\u04ce\xa6\xe9X\xbdy\u050d\u0756\x04\xf4\u07c965\u026d\xc5\u07a0\x00\x00\u07d4\u05a7\xacM\xe7\xb5\x10\xf0\xe8\xdeQ\x9d\x97?\xa4\xc0\x1b\xa84\x00\x89e\xea=\xb7UF`\x00\x00\u07d4\u05ac\xc2 \xba.Q\xdf\xcf!\xd4C6\x1e\xeav\\\xbd5\u0609\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u05ac\xff\u043f\u065c8.{\xd5o\xf0\xe6\x14J\x9eR\xb0\x8e\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xd6\xc0\u043c\x93\xa6.%qtp\x0e\x10\xf0$\u0232?\x1f\x87\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd6\xcf\\\x1b\u03dd\xa6b\xbc\xea\"U\x90P\x99\xf9\xd6\xe8M\u030a\x01\u011eB\x01W\xd9\xc2\x00\x00\u07d4\xd6\xd05r\xa4RE\xdb\xd46\x8cO\x82\xc9W\x14\xbd!g\xe2\x89?\x00\xc3\xd6f\x86\xfc\x00\x00\u07d4\xd6\xd6wiX\xee#\x14:\x81\xad\xad\xeb\b8 \t\xe9\x96\u0089\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd6\xd9\xe3\x0f\bB\x01*qv\xa9\x17\xd9\xd2\x04\x8c\xa0s\x87Y\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd6\xe0\x9e\x98\xfe\x13\x003!\x04\xc1\xca4\xfb\xfa\xc5T6N\u0649lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\xe8\xe9z\u90db\x9e\xe5\a\xee\xdb(\xed\xfbtw\x03\x149\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd6\uea18\u052e+q\x80'\xa1\x9c\xe9\xa5\xebs\x00\xab\xe3\u0289\x01}J\xce\xeec\u06c0\x00\xe0\x94\xd6\xf1\xe5[\x16\x94\b\x9e\xbc\xb4\xfe}x\x82\xaaf\u0217av\x8a\x04<#\xbd\xbe\x92\x9d\xb3\x00\x00\u07d4\xd6\xf4\xa7\xd0N\x8f\xaf \xe8\xc6\ub15c\xf7\xf7\x8d\xd2=z\x15\x89\a$\xde\xd1\xc7H\x14\x00\x00\u07d4\xd6\xfc\x04F\u01a8\xd4\n\xe3U\x1d\xb7\xe7\x01\xd1\xfa\x87nJI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\x03\u01a4\xf1\x1d`\x19Ey\u054c'f\xa7\xef\x16\xc3\n)\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\x05%\x19uj\xf4%\x90\xf1S\x91\xb7#\xa0?\xa5d\xa9Q\x89\xfa61H\r\x01\xfd\x80\x00\u07d4\xd7\na+\xd6\u0769\xea\xb0\xdd\xdc\xffJ\xafA\"\u04cf\xea\xe4\x89\x1dF\x01b\xf5\x16\xf0\x00\x00\u07d4\xd7\n\xd2\xc4\xe9\uefe67\xefV\xbdHj\u04a1\xe5\xbc\xe0\x93\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\x14\f\x8eZC\a\xfa\xb0\xcc'\xba\u0752\x95\x01\x8b\xf8yp\x89\x05\xf1\x01kPv\xd0\x00\x00\u07d4\xd7\x16J\xa2a\xc0\x9a\u0672\xb5\x06\x8dE>\xd8\xebj\xa10\x83\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd7\x1eC\xa4Qw\xadQ\xcb\xe0\xf7!\x84\xa5\xcbP9\x17(Z\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\x1f\xb10\xf0\x15\fVRi\xe0\x0e\xfbC\x90+R\xa4U\xa6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\"W8\xdc\xf3W\x848\xf8\xe7\u0233\x83~B\xe0J&/\x89\x18+\x8c\ubec3\xaa\x00\x00\u07d4\xd7'MP\x80M\x9cw\u0693\xfaH\x01V\xef\xe5{\xa5\x01\u0789i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xd71\xbbk_<79^\t\u03ac\xcd\x14\xa9\x18\xa6\x06\a\x89\x89\u0556{\xe4\xfc?\x10\x00\x00\xe0\x94\xd7>\xd2\u0645\xb5\xf2\x1bU\xb2td;\xc6\xda\x03\x1d\x8e\u074d\x8a\nm\xd9\f\xaeQ\x14H\x00\x00\u07d4\xd7D\xac~S\x10\xbeijc\xb0\x03\xc4\v\xd097\x05a\u0189Z\x87\xe7\xd7\xf5\xf6X\x00\x00\xe0\x94\xd7Jn\x8dj\xab4\u0385\x97h\x14\xc12{\xd6\xea\a\x84\u048a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xd7ZP*[gr\x87G\x0fe\u016aQ\xb8|\x10\x15\x05r\x8910\xb4dc\x85t\x00\x00\u07d4\xd7m\xba\xeb\xc3\rN\xf6{\x03\xe6\xe6\xec\xc6\xd8N\x00MP-\x89mv\xb9\x18\x8e\x13\x85\x00\x00\u07d4\xd7q\xd9\xe0\u028a\b\xa1\x13wW1CN\xb3'\x05\x99\xc4\r\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xd7x\x8e\xf2\x86X\xaa\x06\xccS\xe1\xf3\xf0\xdeX\xe5\xc3q\xbex\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xd7x\x92\xe2';#]v\x89\xe40\xe7\xae\ud73c\xe8\xa1\xf3\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u05c1\xf7\xfc\t\x18F\x11V\x85p\xb4\x98n,r\x87+~\u0409\x01\x15\x95a\x06]]\x00\x00\u07d4\u05c5\xa8\xf1\x8c8\xb9\xbcO\xfb\x9b\x8f\xa8\xc7r{\xd6B\xee\x1c\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u05ce\xcd%\xad\xc8k\xc2\x05\x1d\x96\xf6Sd\x86kB\xa4&\xb7\x89\xd20X\xbf/&\x12\x00\x00\xe0\x94\u05cf\x84\xe3\x89D\xa0\xe0%_\xae\xceH\xbaIP\u053d9\u048a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\u05d4\x83\xf6\xa8DO%I\xd6\x11\xaf\xe0,C-\x15\xe1\x10Q\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u05d85\xe4\x04\xfb\x86\xbf\x84_\xba\t\rk\xa2^\f\x88f\xa6\x89\x82\x1a\xb0\xd4AI\x80\x00\x00\u07d4\u05da\xff\x13\xba-\xa7]F$\f\xac\n$g\xc6V\x94\x98#\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\u05dd\xb5\xabCb\x1az=\xa7\x95\xe5\x89)\xf3\xdd%\xafg\u0649lj\xccg\u05f1\xd4\x00\x00\u07d4\u05e1C\x1e\xe4S\xd1\xe4\x9a\x05P\xd1%hy\xb4\xf5\xd1\x02\x01\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\u05ed\t\xc6\xd3&WhSU\xb5\xc6\uc39fW\xb4\ube42\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u05f7@\xdf\xf8\xc4Wf\x8f\xdft\xf6\xa2f\xbf\xc1\u0737#\xf9\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xd7\u0080>\u05f0\xe0\x83sQA\x1a\x8ef7\xd1h\xbc[\x05\x8a\x06A\xda\xf5\xc9\x1b\xd95\x80\x00\u07d4\xd7\xc6&]\xea\x11\x87l\x90;q\x8eL\u062b$\xfe&[\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xca\u007f\xdc\xfe\xbeE\x88\xef\xf5B\x1d\x15\"\xb6\x13(\xdf{\xf3\x89\xd8\xe6\x00\x1el0+\x00\x00\u07d4\xd7\u037dA\xff\xf2\r\xf7'\xc7\vbU\xc1\xbav\x06\x05Th\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\xd1W\xe4\xc0\xa9d7\xa6\u0485t\x1d\xd2>\xc46\x1f\xa3k\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xd2\xc6\xfc\xa8\xad\x1fu9R\x10\xb5}\xe5\xdf\xd6s\x939\t\x89\x12nr\xa6\x9aP\xd0\x00\x00\xe0\x94\xd7\xd3\xc7Y Y\x048\xb8,>\x95\x15\xbe.\xb6\xedz\x8b\x1a\x8a\f\xb4\x9bD\xba`-\x80\x00\x00\u07d4\xd7\xd7\xf2\u02a4b\xa4\x1b;0\xa3J\xeb;\xa6\x10\x10\xe2bo\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd7\xe7J\xfd\xba\xd5^\x96\u03bcZ7O,\x8bv\x86\x80\xf2\xb0\x89\x05]\xe6\xa7y\xbb\xac\x00\x00\xe0\x94\xd7\xeb\x901b'\x1c\x1a\xfa5\xfei\xe3s\"\u0224\u049b\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xd7\xeb\u0779\xf99\x87w\x9bh\x01U7T8\xdbe\xaf\xcbj\x89\x05t\x1a\xfe\xff\x94L\x00\x00\u07d4\xd7\xef4\x0ef\xb0\u05ef\xcc\xe2\n\x19\xcb{\xfc\x81\xda3\xd9N\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xd7\xf3p\u053e\xd9\xd5|oI\u0259\xder\x9e\xe5i\xd3\xf4\xe4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd7\xfa_\xfb`H\xf9o\xb1\xab\xa0\x9e\xf8{\x1c\x11\xddp\x05\xe4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd8\x06\x9f\x84\xb5!I?G\x15\x03\u007f2&\xb2_3\xb6\x05\x86\x89g\x8a\x93 b\xe4\x18\x00\x00\u0794\xd8\x15\xe1\xd9\xf4\xe2\xb5\xe5~4\x82k|\xfd\x88\x81\xb8Th\x90\x88\xf0\x15\xf2W6B\x00\x00\u07d4\xd8\x1b\xd5K\xa2\xc4Jok\xeb\x15a\u058b\x80\xb5DNm\u0189?\x17\r~\xe4\"\xf8\x9c\x80-1({\x96q\xe8\x1c\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xd8K\x92/xA\xfcWt\xf0\x0e\x14`J\xe0\xdfB\xc8U\x1e\x89\xd9o\u0390\u03eb\xcc\x00\x00\u07d4\xd8U\xb0<\xcb\x02\x9awG\xb1\xf0s\x03\xe0\xa6dy59\u0209lk\x93[\x8b\xbd@\x00\x00\u07d4\xd8_\u07af*a\xf9]\xb9\x02\xf9\xb5\xa5<\x9b\x8f\x92f\u00ec\x89l\xf6Z~\x90G(\x00\x00\u07d4\xd8q^\xf9\x17o\x85\v.0\xeb\x8e8'\a\xf7w\xa6\xfb\xe9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd8t\xb9\u07eeEj\x92\x9b\xa3\xb1\xa2~W,\x9b,\xec\u07f3\x89\t79SM(h\x00\x00\u07d4\u0613\n9\xc7sW\xc3\n\u04e0`\xf0\v\x06\x04c1\xfdb\x89,s\xc97t,P\x00\x00\u07d4\u061b\xc2q\xb2{\xa3\xabib\xc9JU\x90\x06\xae8\xd5\xf5j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0637}\xb9\xb8\x1b\xbe\x90B{b\xf7\x02\xb2\x01\xff\u009f\xf6\x18\x892m\x1eC\x96\xd4\\\x00\x00\u07d4\xd8\xcdd\xe0(N\xecS\xaaF9\xaf\xc4u\b\x10\xb9\u007f\xabV\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd8\xd6C\x84$\x9bwg\x94\x06;V\x98x\xd5\xe3\xb50\xa4\xb2\x89\t\xa0C\u0432\xf9V\x80\x00\u07d4\xd8\xd6T \xc1\x8c#'\xccZ\xf9t%\xf8W\xe4\xa9\xfdQ\xb3\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xd8\xe5\xc9g^\xf4\xde\xed&k\x86\x95o\xc4Y\x0e\xa7\u0522}\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xd8\xe8GB\x92\xe7\xa0Q`L\xa1d\xc0pw\x83\xbb(\x85\xe8\x8a\x02\xd4\xca\x05\xe2\xb4<\xa8\x00\x00\u07d4\xd8\xebxP>\xc3\x1aT\xa9\x016x\x1a\xe1\t\x00Lt2W\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd8\xee\xf4\xcfK\xeb\x01\xee \xd1\x11t\x8ba\xcbM?d\x1a\x01\x89\x94\x89#z\u06daP\x00\x00\u07d4\xd8\xf4\xba\xe6\xf8M\x91\rm}Z\xc9\x14\xb1\xe6\x83r\xf9A5\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xd8\xf6 6\xf0;v5\xb8X\xf1\x10?\x8a\x1d\x90\x19\xa8\x92\xb6\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xd8\xf6e\xfd\x8c\xd5\u00bc\xc6\xdd\xc0\xa8\xaeR\x1eM\u01aa``\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xd8\xf9$\fU\xcf\xf05RB\x80\xc0\x9e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xd8\xfe\b\x8f\xff\u0394\x8fQ7\xee#\xb0\x1d\x95\x9e\x84\xacB#\x89\f[T\xa9O\xc0\x17\x00\x00\u07d4\xd9\x0f0\t\xdbC~N\x11\u01c0\xbe\u0209os\x8de\xef\r\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd9\x10;\xb6\xb6zU\xa7\xfe\xce-\x1a\xf6-E|!x\x94m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd9\x13\xf0w\x19Iu\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xd9D\u0226\x9f\xf2\xca\x12Ii\f\x12)\xc7\x19/6%\x10b\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xd9JW\x88*Rs\x9b\xbe*\x06G\xc8\f$\xf5\x8a+O\x1c\x89H\xb5N*\xdb\xe1+\x00\x00\xe0\x94\xd9SB\x95<\x8a!\xe8\xb65\xee\xfa\u01c1\x9b\xea0\xf1pG\x8a\x13\xf0l\u007f\xfe\xf0]@\x00\x00\u07d4\xd9\\\x90\xff\xbeT\x84\x86G\x80\xb8gIJ\x83\u0212V\xd6\xe4\x89X\xe7\x92n\xe8X\xa0\x00\x00\u07d4\xd9g\x11T\x0e.\x99\x83C\xd4\xf5\x90\xb6\xfc\x8f\xac;\xb8\xb3\x1d\x89_Z@h\xb7\x1c\xb0\x00\x00\u07d4\xd9j\xc2Pt\t\u01e3\x83\xab.\xee\x18\"\xa5\xd78\xb3kV\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xd9m\xb3;{Z\x95\f>\xfa-\xc3\x1b\x10\xba\x10\xa52\uf1c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xd9wYe\xb7\x16Gfu\xa8\xd5\x13\xeb\x14\xbb\xf7\xb0|\xd1J\x8a\x01\x13.m-#\xc5\xe4\x00\x00\u07d4\xd9{\xc8J\xbdG\xc0[\xbfE{.\xf6Y\xd6\x1c\xa5\xe5\u43c9\x06\x9d\x17\x11\x9d\u0168\x00\x00\u07d4\xd9\u007fE&\u07a9\xb1c\xf8\xe8\xe3:k\u03d2\xfb\x90}\xe6\xec\x89\x0feJ\xafM\xb2\xf0\x00\x00\u07d4\xd9\u007f\xe6\xf5?*X\xf6\xd7mu*\xdft\xa8\xa2\xc1\x8e\x90t\x89\x10\xcd\xf9\xb6\x9aCW\x00\x00\u07d4\u0659\x99\xa2I\r\x94\x94\xa50\xca\xe4\xda\xf3\x85T\xf4\xddc>\x89\x06\x81U\xa46v\xe0\x00\x00\u07d4\u065d\xf7B\x1b\x93\x82\xe4,\x89\xb0\x06\xc7\xf0\x87p*\aW\xc0\x89\x1a\x05V\x90\xd9\u06c0\x00\x00\xe0\x94\u0677\x83\xd3\x1d2\xad\xc5\x0f\xa3\xea\u02a1]\x92\xb5h\xea\xebG\x8a\a3\xaf\x907L\x1b(\x00\x00\u07d4\xd9\xd3p\xfe\xc65v\xab\x15\xb3\x18\xbf\x9eX6M\u00a3U*\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xd9\xd4/\xd1>\xbdK\xf6\x9c\xac^\x9c~\x82H:\xb4m\xd7\xe9\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xd9\xe2~\xb0}\xfcq\xa7\x06\x06\f\u007f\a\x928\u0293\xe8\x859\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xd9\xe3\x85~\xfd\x1e *D\x17p\xa7w\xa4\x9d\xccE\xe2\xe0\u04c9\f\x1d\xaf\x81\u0623\xce\x00\x00\u07d4\xd9\xec.\xfe\x99\xff\\\xf0\r\x03\xa81{\x92\xa2J\xefD\x1f~\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xd9\xec\x8f\xe6\x9bw\x16\xc0\x86Z\xf8\x88\xa1\x1b+\x12\xf7 \xed3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xd9\xf1\xb2d\b\xf0\xecg\xad\x1d\ro\xe2.\x85\x15\xe1t\x06$\x89\x01M\x11 \u05f1`\x00\x00\u07d4\xd9\xf5G\xf2\xc1\xde\x0e\u064aS\xd1a\xdfWc]\xd2\x1a\x00\xbd\x89\x05V\xf6L\x1f\xe7\xfa\x00\x00\u07d4\xd9\xff\x11]\x01&l\x9fs\xb0c\xc1\xc28\xef5e\xe6;6\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\xda\x06\x04N)#&\xffil\x0091h\xceF\xff\xac9\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda*\x14\xf9r@\x15\u05d0\x14\xed\x8eY\th\x1dYaH\xf1\x89\x02\xa1\x0f\x0f\x8a\x91\xab\x80\x00\u07d4\xda*\u054ew\xde\xdd\xed\xe2\x18vF\xc4e\x94Z\x8d\xc3\xf6A\x89#\xc7W\a+\x8d\xd0\x00\x00\u07d4\xda0\x17\xc1P\xdd\r\xce\u007f\u03c8\x1b\nH\xd0\xd1\xc7V\xc4\u01c9\x05k\xf9\x1b\x1ae\xeb\x00\x00\u07d4\xda4\xb2\xea\xe3\v\xaf\xe8\xda\xec\xcd\xe8\x19\xa7\x94\u0349\xe0\x95I\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdaJ_U\u007f;\xab9\n\x92\xf4\x9b\x9b\x90\n\xf3\fF\xae\x80\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdaPU7S\u007f\xfb3\xc4\x15\xfe\xc6Ni\xba\xe0\x90\xc5\xf6\x0f\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xdai\x8dd\xc6\\\u007f+,rS\x05\x9c\xd3\u0441\u0619\xb6\xb7\x89\x10\x04\xe2\xe4_\xb7\xee\x00\x00\u07d4\xdaw2\xf0/.'.\xaf(\u07d7.\xcc\r\xde\xed\x9c\xf4\x98\x89\v \xbf\xbfig\x89\x00\x00\u07d4\xdaz\xd0%\xeb\xde%\xd2\"C\u02c3\x0e\xa1\xd3\xf6JVc#\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\u0685]SG\u007fP^\xc4\xc8\xd5\u8ed1\x80\u04c6\x81\x11\x9c\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\u0687^N/<\xab\xe4\xf3~\x0e\xae\xd7\xd1\xf6\xdc\xc6\xff\xefC\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u068b\xbe\xe1\x82\xe4U\xd2\t\x8a\xcb3\x8amE\xb4\xb1~\u0636\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0698.\x96C\xff\xec\xe7#\aZ@\xfewnZ\xce\x04\xb2\x9b\x89\b\xb8\xb6\u0259\x9b\xf2\x00\x00\u07d4\u069fUF\tF\u05ff\xb5p\xdd\xecu|\xa5w;XB\x9a\x89\x1b\x84]v\x9e\xb4H\x00\x00\u07d4\u06a1\xbdz\x91H\xfb\x86\\\xd6\x12\xdd5\xf1b\x86\x1d\x0f;\u0709\xa68\xabr\xd9,\x13\x80\x00\xe0\x94\u06a6<\xbd\xa4]\u0507\xa3\xf1\xcdJtj\x01\xbb^\x06\v\x90\x8a\x01\x04\x16\u0670*\x89$\x00\x00\u07d4\u06a7v\xa6uDi\u05f9&z\x89\xb8g%\xe7@\xda\x0f\xa0\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\u06ac\x91\xc1\xe8Y\xd5\xe5~\xd3\bKP \x0f\x97f\xe2\xc5+\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u06ac\xda\xf4\"&\xd1\\\xb1\u03d8\xfa\x15\x04\x8c\u007fL\xee\xfei\x89\x10CV\x1a\x88)0\x00\x00\xe0\x94\u06b6\xbc\u06c3\xcf$\xa0\xae\x1c\xb2\x1b;[\x83\xc2\xf3\x82I'\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\u06bb\b\x89\xfc\x04)&\xb0^\xf5{% \x91\n\xbcKAI\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06bc\"PB\xa6Y,\xfa\x13\xeb\xe5N\xfaA\x04\bx\xa5\xa2\x89\x0e\x11\xfa\xd5\xd8\\\xa3\x00\x00\u07d4\xda\xc0\xc1w\xf1\x1c\\>>x\xf2\xef\xd6c\xd12!H\x85t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda\xd16\xb8\x81x\xb4\x83zlx\x0f\xeb\xa2&\xb9\x85i\xa9L\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xda\xdb\xfa\xfd\x8bb\xb9*$\xef\xd7RV\u0743\xab\xdb\u05fb\u06c9\x01\x11du\x9f\xfb2\x00\x00\u07d4\xda\xdc\x00\xaby'`\xaa4\x15i\xfa\x9f\xf5\x98&\x84\x85JJ2\x8an\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xda\xe7 \x1e\xab\x8c\x063\x02\x93\ri9)\xd0\u007f\x95\xe7\x19b\x89\x91\xae\xc0(\xb4\x19\x81\x00\x00\u07d4\xda\xed\u052d\x10{'\x1e\x89Hl\xbf\x80\xeb\xd6!\u0757Ex\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x04\xfa\xd9\u011f\x9e\x88\v\xeb\x8f\xcf\x1d:8\x90\u4cc4o\x89CZ\xe6\xcc\fX\xe5\x00\x00\u07d4\xdb\f\u01cft\u0642{\u070ads'n\xb8O\u0717b\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x12\x93\xa5\x06\xe9\f\xad*Y\xe1\xb8V\x1f^f\x96\x1ag\x88\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb\x19\xa3\x98\"06\x8f\x01w!\x9c\xb1\f\xb2Y\u0372%|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb#\xa6\xfe\xf1\xaf{X\x1ew,\xf9\x18\x82\u07b2Qo\xc0\xa7\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb$O\x97\xd9\xc4K\x15\x8a@\xed\x96\x06\xd9\xf7\xbd8\x9131\x89\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xdb(\x8f\x80\xff\xe22\u00baG\u0314\xc7c\xcfo\u0278+\r\x89\x04\x9b\x9c\xa9\xa6\x944\x00\x00\u07d4\xdb*\f\x9a\xb6M\xf5\x8d\u07f1\u06ec\xf8\xba\r\x89\xc8[1\xb4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdb4t^\u0785v\xb4\x99\xdb\x01\xbe\xb7\xc1\xec\u0685\xcfJ\xbe\x89\x04V9\x18$O@\x00\x00\u07d4\xdb?%\x8a\xb2\xa3\xc2\xcf3\x9cD\x99\xf7ZK\xd1\xd3G.\x9e\x89QP\xae\x84\xa8\xcd\xf0\x00\x00\u07d4\xdbK\xc8;\x0ek\xaa\xdb\x11V\xc5\xcf\x06\xe0\xf7!\x80\x8cR\u01c9/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xdbc\x12-\xe7\x03}\xa4\x97\x151\xfa\u9bc5\x86x\x86\u0192\x89\x0f\x04%\xb0d\x1f4\x00\x00\u07d4\xdbl*s\xda\xc7BJ\xb0\xd01\xb6ga\x12%f\xc0\x10C\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xdbnV\f\x9b\xc6 \u053e\xa3\xa9MG\xf7\x88\v\xf4\u007f-_\x89\x04\xda\x0f\xdf\xcf\x05v\x00\x00\u07d4\xdbo\xf7\x1b=\xb0\x92\x8f\x83\x9e\x05\xa72;\xfbW\u049c\x87\xaa\x891T\xc9r\x9d\x05x\x00\x00\u07d4\xdbsF\vY\xd8\xe8PE\xd5\xe7R\xe6%Y\x87^BP.\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\xdbw\xb8\x8d\xcbq/\xd1~\xe9\x1a[\x94t\x8dr\f\x90\xa9\x94\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdb}@7\b\x1fle\xf9Gk\x06\x87\xd9\u007f\x1e\x04M\n\x1d\x89#\xc7W\a+\x8d\xd0\x00\x00\xe0\x94\u06c8.\xac\xed\xd0\xef\xf2cQ\x1b1*\u06fcY\u01b8\xb2[\x8a\x01\xedO\xdez\"6\xb0\x00\x00\u07d4\u06d3q\xb3\fL\x84NY\xe0>\x92K\xe6\x06\xa98\xd1\xd3\x10\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06e4ym\f\xebM:\x83k\x84\xc9o\x91\n\xfc\x10?[\xa0\x89\t\b\xf4\x93\xf77A\x00\x00\u07d4\u06ed\xc6\x1e\xd5\xf0F\n\u007f\x18\xe5\x1b/\xb2aM\x92d\xa0\xe0\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u06f6\xacH@'\x04\x16B\xbb\xfd\x8d\x80\xf9\xd0\xc1\xcf3\xc1\xeb\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u06fc\xbby\xbfG\x9aB\xadq\xdb\u02b7{Z\u07ea\x87,X\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xdb\xc1\xce\x0eI\xb1\xa7\x05\xd2. 7\xae\xc8x\xee\ru\xc7\x03\x89\r\x8drkqw\xa8\x00\x00\u07d4\xdb\xc1\xd0\xee+\xabS\x11@\xde\x13w\"\xcd6\xbd\xb4\xe4q\x94\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb\u015e\u0609s\u07ad1\b\x84\":\xf4\x97c\xc0P0\xf1\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u0794\xdb\xc6ie\xe4&\xff\x1a\xc8z\xd6\xebx\xc1\xd9Rq\x15\x8f\x9f\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xdb\xcb\xcdzW\ua7724\x9b\x87\x8a\xf3K\x1a\xd6B\xa7\xf1\u0449\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdb\xd5\x1c\xdf,;\xfa\xcd\xff\x10b!\xde.\x19\xadmB\x04\x14\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xdb\xd7\x1e\xfaK\x93\u0209\xe7e\x93\xde`\x9c;\x04\u02ef\xbe\b\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xdb\xf5\xf0a\xa0\xf4\x8e^ia\x879\xa7}.\xc1\x97h\xd2\x01\x89\b=lz\xabc`\x00\x00\u07d4\xdb\xf8\xb19g\xf5Q%'-\xe0V%6\xc4P\xbaVU\xa0\x89n\xf5x\xf0n\f\xcb\x00\x00\u07d4\xdb\xfb\x1b\xb4d\xb8\xa5\x8eP\r.\xd8\u0797,E\xf5\xf1\xc0\xfb\x89V\xbcu\xe2\xd61\x00\x00\x00\xe0\x94\xdc\x06~\xd3\xe1-q\x1e\xd4u\xf5\x15n\xf7\xe7\x1a\x80\xd94\xb9\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xdc\b\u007f\x93\x90\xfb\x9e\x97j\xc2:\xb6\x89TJ\tB\xec !\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xdc\x1e\xb9\xb6\xe6CQ\xf5d$P\x96E\xf8>y\xee\xe7l\xf4\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdc\x1f\x19ya_\b!@\xb8\xbbx\xc6{'\xa1\x94'\x13\xb1\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xdc#\xb2`\xfc\xc2n}\x10\xf4\xbd\x04J\xf7\x94W\x94`\xd9\u0689\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xdc)\x11\x97E\xd23s \xdaQ\xe1\x91\x00\xc9H\u0640\xb9\x15\x89\b\xacr0H\x9e\x80\x00\x00\u07d4\xdc-\x15\xa6\x9fk\xb3;$j\xef@E\aQ\xc2\xf6uj\u0489l4\x10\x80\xbd\x1f\xb0\x00\x00\u07d4\xdc=\xaeY\xed\x0f\xe1\x8bXQ\x1eo\xe2\xfbi\xb2\x19h\x94#\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xdc?\x0evr\xf7\x1f\xe7R[\xa3\v\x97U\x18: \xb9\x16j\x8a\x02\b\x9c\xf5{[>\x96\x80\x00\xe0\x94\xdcCE\u0581.\x87\n\xe9\fV\x8cg\xd2\xc5g\u03f4\xf0<\x8a\x01k5-\xa5\xe0\xed0\x00\x00\u07d4\xdcD'[\x17\x15\xba\xea\x1b\x03EsZ)\xacB\xc9\xf5\x1bO\x89?\x19\xbe\xb8\xdd\x1a\xb0\x00\x00\u07d4\xdcF\xc13%\u034e\xdf\x020\xd0h\x89d\x86\xf0\a\xbfN\xf1\x89Hz\x9a0E9D\x00\x00\u07d4\xdcQ\xb2\u071d$z\x1d\x0e[\xc3l\xa3\x15oz\xf2\x1f\xf9\xf6\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xdcS\x05\xb4\x02\n\x06\xb4\x9de||\xa3L5\xc9\x1c_,V\x8a\x01}\xf6\xc1\r\xbe\xba\x97\x00\x00\u07d4\xdcW4[8\xe0\xf0g\u0263\x1d\x9d\xea\xc5'Z\x10\x94\x93!\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdcWG}\xaf\xa4/p\\\u007f\xe4\x0e\xae\x9c\x81un\x02%\xf1\x89\x1b\x1b\x81(\xa7An\x00\x00\u07d4\xdc_Z\xd6c\xa6\xf2c2}d\xca\xc9\xcb\x13=,\x96\x05\x97\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdcp:_7\x94\xc8Ml\xb3TI\x18\xca\xe1J5\u00fdO\x89dI\xe8NG\xa8\xa8\x00\x00\xe0\x94\xdcs\x8f\xb2\x17\u03ad/iYL\b\x17\r\xe1\xaf\x10\xc4\x19\xe3\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xdcv\xe8[\xa5\v\x9b1\xec\x1e& \xbc\xe6\xe7\xc8\x05\x8c\x0e\xaf\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\u0703\xb6\xfd\rQ!1 G\a\xea\xf7.\xa0\xc8\u027e\xf9v\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u070c)\x12\xf0\x84\xa6\u0444\xaasc\x85\x13\u033c2n\x01\x02\x89F3\xbc6\xcb\xc2\xdc\x00\x00\u07d4\u0711\x1c\xf7\xdc]\u04016Vg\x05(\xe93\x8eg\x03G\x86\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0730;\xfal\x111#NV\xb7\xea|Or\x14\x87Tkz\x89Hz\x9a0E9D\x00\x00\xe0\x94\u0736M\xf47X\xc7\u03d7O\xa6`HO\xbbq\x8f\x8cg\xc1\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xdc\xc5-\x8f\x8d\x9f\xc7B\xa8\xb8'g\xf0US\x87\xc5c\xef\xff\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xdc\xcb7\x0e\u058a\xa9\"(0C\xef|\xad\x1b\x9d@?\xc3J\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdc\u0324 E\xec>\x16P\x8b`?\xd96\xe7\xfd}\xe5\xf3j\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xdc\xd1\fU\xbb\x85OuD4\xf1!\x9c,\x9a\x98\xac\xe7\x9f\x03\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xdc\u057c\xa2\x00S\x95\xb6u\xfd\xe5\x03VY\xb2k\xfe\xfcI\xee\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xdc\u06fdN&\x04\xe4\x0e\x17\x10\xccg0(\x9d\xcc\xfa\u04c9-\x89\xf9]\xd2\xec'\xcc\xe0\x00\x00\u07d4\xdc\xe3\f1\xf3\xcafr\x1e\xcb!<\x80\x9a\xabV\x1d\x9bR\xe4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdc\xf39eS\x13\x80\x161h\xfc\x11\xf6~\x89\xc6\xf1\xbc\x17\x8a\x89\x12'v\x854\x06\xb0\x80\x00\u07d4\xdc\xf6\xb6W&n\x91\xa4\xda\xe6\x03=\xda\xc1S2\u074d+4\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xdc\xf9q\x9b\xe8|oFum\xb4\x89\x1d\xb9\xb6\x11\xd2F\x9cP\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xdc\xff\xf3\xe8\xd2<*4\xb5k\u0473\xbdE\u01d3tC\"9\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xdd\x04\xee\xe7N\v\xf3\f?\x8dl,\u007fR\xe0Q\x92\x10\u07d3\x89\x04V9\x18$O@\x00\x00\xe0\x94\xdd&\xb4)\xfdC\xd8N\xc1y\x82S$\xba\u057f\xb9\x16\xb3`\x8a\x01\x16\xbf\x95\xbc\x842\x98\x00\x00\u07d4\xdd*#:\xde\xdef\xfe\x11&\xd6\xc1h#\xb6*\x02\x1f\xed\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xdd+\u07e9\x17\xc1\xf3\x10\xe6\xfa5\xaa\x8a\xf1i9\xc23\xcd}\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xdd5\xcf\xdb\u02d93\x95Sz\xec\xc9\xf5\x90\x85\xa8\xd5\u0776\xf5\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xddG\x18\x9a>d9qg\xf0b\x0eHEe\xb7b\xbf\xbb\xf4\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4\xddM\xd6\xd3`3\xb0co\u030d\t8`\x9fM\xd6OJ\x86\x89\x03@\xaa\xd2\x1b;p\x00\x00\u07d4\xddO_\xa2\x11\x1d\xb6\x8fk\xde5\x89\xb60)9[i\xa9-\x89\b\x96=\xd8\xc2\xc5\xe0\x00\x00\xe0\x94\xddc\x04/%\xed2\x88J\xd2n:\xd9Y\xeb\x94\xea6\xbfg\x8a\x04\x84\xd7\xfd\xe7\u0553\xf0\x00\x00\u07d4\xdde\xf6\xe1qc\xb5\xd2\x03d\x1fQ\xcc{$\xb0\x0f\x02\xc8\xfb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xddl\x06!\x93\xea\xc2=/\xdb\xf9\x97\xd5\x06:4k\xb3\xb4p\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdd{\u0366Y$\xaa\xa4\x9b\x80\x98J\xe1su\x02X\xb9(G\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdd\u007f\xf4A\xbao\xfe6q\xf3\xc0\u06bb\xff\x18#\xa5\x043p\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u0742T\x12\x1an\x94/\xc9\b(\xf2C\x1fQ\x1d\xad\u007f2\u6263\x9b)\xe1\xf3`\xe8\x00\x00\xe0\x94\u074a\xf9\xe7vR#\xf4DoD\xd3\xd5\t\x81\x9a==\xb4\x11\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\u0755\xdb\xe3\x0f\x1f\x18w\xc5\xddv\x84\xae\xef0*\xb6\x88Q\x92\x8a\x01\xc5\xd8\xd6\xeb>2P\x00\x00\xe0\x94\u0756|L_\x8a\xe4~&o\xb4\x16\xaa\u0456N\xe3\xe7\xe8\u00ca\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\u075bHZ;\x1c\xd3:j\x9cb\xf1\xe5\xbe\xe9'\x01\x85m%\x89\f3\x83\xed\x03\x1b~\x80\x00\xe0\x94\u0763q\xe6\x00\xd3\x06\x88\xd4q\x0e\b\x8e\x02\xfd\xf2\xb9RM_\x8a\x01w\"J\xa8D\xc7 \x00\x00\u07d4\u0764\xed*X\xa8\xdd \xa72u4{X\rq\xb9[\xf9\x9a\x89\x15\xa1<\xc2\x01\xe4\xdc\x00\x00\xe0\x94\u0764\xff}\xe4\x91\u0187\xdfEt\xdd\x1b\x17\xff\x8f$k\xa3\u044a\x04&\x84\xa4\x1a\xbf\xd8@\x00\x00\u07d4\u076bkQ\xa9\x03\v@\xfb\x95\xcf\vt\x8a\x05\x9c$\x17\xbe\u01c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\u076bu\xfb/\xf9\xfe\u02c8\xf8\x94vh\x8e+\x00\xe3g\xeb\xf9\x8a\x04\x1b\xad\x15^e\x12 \x00\x00\xe0\x94\u076b\xf1<<\x8e\xa4\xe3\xd7=x\xecqz\xfa\xfaC\x0eTy\x8a\b\xcf#\xf9\t\xc0\xfa\x00\x00\x00\u07d4\u076c1*\x96UBj\x9c\f\x9e\xfa?\xd8%Y\xefE\x05\xbf\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\u076ck\xf4\xbb\xdd}Y}\x9chm\x06\x95Y;\xed\xcc\xc7\xfa\x89.\xe4IU\b\x98\xe4\x00\x00\xe0\x94\u077d+\x93,v;\xa5\xb1\xb7\xae;6.\xac>\x8d@\x12\x1a\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\u077d\xdd\x1b\xbd8\xff\xad\xe00]0\xf0 (\xd9.\x9f:\xa8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\u077e\xe6\xf0\x94\xea\xe64 \xb0\x03\xfbGW\x14*\xeal\xd0\xfd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdd\u059c[\x9b\xf5\xebZ9\xce\xe7\xc34\x1a\x12\r\x97?\xdb4\x89k\xc1K\x8f\x8e\x1b5\x00\x00\xe0\x94\xdd\xdd{\x9en\xab@\x9b\x92&:\xc2r\u0680\x1bfO\x8aW\x8ai\xe1\r\xe7fv\u0400\x00\x00\u07d4\xdd\xe6p\xd0\x169fuv\xa2-\xd0]2F\xd6\x1f\x06\xe0\x83\x89\x01s\x17\x90SM\xf2\x00\x00\xe0\x94\xdd\xe7zG@\xba\b\xe7\xf7?\xbe:\x16t\x91)1t.\xeb\x8a\x044\xfeMC\x82\xf1\u0500\x00\u07d4\xdd\xe8\xf0\xc3\x1bt\x15Q\x1d\xce\xd1\xcd}F2>K\xd1\"2\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\xdd\xe9i\xae\xf3N\xa8z\u0099\xb7Y~)+J\x01U\u030a\x89\x102\xf2YJ\x01s\x80\x00\u07d4\xdd\xf0\xcc\xe1\xfe\x99m\x91v5\xf0\a\x12\xf4\x05 \x91\xdf\xf9\xea\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdd\xf3\xadv58\x10\xbej\x89\xd71\xb7\x87\xf6\xf1q\x88a+\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xdd\xf5\x81\n\x0e\xb2\xfb.22;\xb2\u0255\t\xab2\x0f$\xac\x8a\x03\xca\\f\u067cD0\x00\x00\xe0\x94\xdd\xf9\\\x1e\x99\xce/\x9fV\x98\x05|\x19\xd5\xc9@'\xeeJn\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u0794\xdd\xfa\xfd\xbc|\x90\xf12\x0eT\xb9\x8f7F\x17\xfb\xd0\x1d\x10\x9f\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xdd\xfc\xca\x13\xf94\xf0\u03fe#\x1d\xa109\xd7\x04u\xe6\xa1\u040968\"\x16`\xa5\xaa\x80\x00\u07d4\xde\x02~\xfb\xb3\x85\x03\"n\xd8q\t\x9c\xb3\v\xdb\x02\xaf\x135\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xde\x06\xd5\xeawzN\xb1G^`]\xbc\xbfCDN\x807\xea\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xde\a\xfb[zFN;\xa7\xfb\xe0\x9e\x9a\xcb'\x1a\xf53\x8cX\x89\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xde\x11!\x82\x9c\x9a\b(@\x87\xa4?\xbd/\xc1\x14*23\xb4\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xde\x17kR\x84\xbc\xee:\x83\x8b\xa2Og\xfc|\xbfg\u05ce\xf6\x89\x02\t\xce\b\xc9b\xb0\x00\x00\u07d4\xde!\"\x93\xf8\xf1\xd21\xfa\x10\xe6\tG\rQ,\xb8\xff\xc5\x12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde0\xe4\x9eZ\xb3\x13!M/\x01\u072b\u0389@\xb8\x1b\x1cv\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xde3\xd7\b\xa3\xb8\x9e\x90\x9e\xafe;0\xfd\u00e5\xd5\u0334\xb3\x89\t\x9c\x88\"\x9f\xd4\xc2\x00\x00\u07d4\xde7B\x99\xc1\xd0}ySs\x85\x19\x0fD.\xf9\xca$\x06\x1f\x89\a?u\u0460\x85\xba\x00\x00\u07d4\xdeB\xfc\xd2L\xe4#\x93\x830CgY_\x06\x8f\fa\a@\x89\x02r*p\xf1\xa9\xa0\x00\x00\u07d4\xdeP\x86\x8e\xb7\xe3\xc7\x197\xecs\xfa\x89\u074b\x9e\xe1\rE\xaa\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xdeU\xde\x04X\xf8P\xb3~Mx\xa6A\xdd.\xb2\u074f8\u0389\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xde[\x00_\xe8\u06ae\x8d\x1f\x05\xde>\xda\x04 f\xc6\xc4i\x1c\x89;\xa1\x91\v\xf3A\xb0\x00\x00\u07d4\xdea-\a$\xe8N\xa4\xa7\xfe\xaa=!B\xbd^\xe8-2\x01\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdem61\x06\xccb8\xd2\xf0\x92\xf0\xf07!6\xd1\xcdP\u018a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xde}\xee\"\x0f\x04W\xa7\x18}V\xc1\xc4\x1f.\xb0\n\xc5`!\x89\"%\xf3\x9c\x85\x05*\x00\x00\u07d4\u0782\u030dJ\x1b\xb1\xd9CC\x92\x96[>\x80\xba\xd3\xc0=O\x89P\x18nu\u0797\xa6\x00\x00\u07d4\u0797\xf43\a\x00\xb4\x8cImC|\x91\xca\x1d\xe9\u0130\x1b\xa4\x89\x9d\xcc\x05\x15\xb5n\f\x00\x00\u07d4\u079e\xffLy\x88\x11\xd9h\xdc\xcbF\r\x9b\x06\x9c\xf3\x02x\xe0\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\u07b1\xbc4\xd8mJM\xde%\x80\u063e\xaf\aN\xb0\xe1\xa2D\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\u07b2I]j\xca{*j-\x13\x8bn\x1aB\xe2\xdc1\x1f\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\u07b9rTGL\r/Zyp\xdc\xdb/R\xfb\x10\x98\xb8\x96\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u07b9\xa4\x9aC\x870 \xf0u\x91\x85\xe2\v\xbbL\U000c1ecf\x89\vx\xed\xb0\xbf.^\x00\x00\u07d4\u07bb\u0743\x1e\x0f \xaen7\x82R\xde\xcd\xf9/|\xf0\xc6X\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde\xc3\xee\xc2d\nu,Fn+~~\u616f\xe9\xacA\xf4\x89G\u0257SYk(\x80\x00\u07d4\xde\xc8#s\xad\xe8\xeb\xcf*\xcbo\x8b\xc2AM\u05eb\xb7\rw\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xde\u0221\xa8\x98\xf1\xb8\x95\xd80\x1f\xe6J\xb3\xad]\xe9A\xf6\x89\x89*\xb4\xf6~\x8as\x0f\x80\x00\u07d4\xde\u025e\x97/\xcaqwP\x8c\x8e\x1aG\xac\"\xd7h\xac\xab|\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xde\xd8w7\x84\a\xb9Nx\x1cN\xf4\xaf|\xfc[\xc2 \xb5\x16\x89\x141y\xd8i\x11\x02\x00\x00\u07d4\xde\xe9B\xd5\xca\xf5\xfa\xc1\x14!\xd8k\x01\vE\x8e\\9)\x90\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xde\xee&\x89\xfa\x90\x06\xb5\x9c\xf2\x85#}\xe5;:\u007f\xd0\x148\x89\x18ey\xf2\x9e %\x00\x00\u07d4\xde\xfd\xdf\u055b\x8d,\x15N\xec\xf5\xc7\xc1g\xbf\v\xa2\x90]>\x89\x05\x12\xcb^&GB\x00\x00\u07d4\xde\xfe\x91A\xf4pE\x99\x15\x9d{\"=\xe4+\xff\xd8\x04\x96\xb3\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xdf\t\x8f^N=\xff\xa5\x1a\xf27\xbd\xa8e,Os\ud726\x89\x1b6\xa6DJ>\x18\x00\x00\xe0\x94\xdf\r\ba{\xd2R\xa9\x11\u07cb\xd4\x1a9\xb8=\u07c0\x96s\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xdf\x0f\xf1\xf3\xd2z\x8e\xc9\xfb\x8fk\f\xb2T\xa6;\xba\x82$\xa5\x89\xec\xc5 )E\xd0\x02\x00\x00\u07d4\xdf\x1f\xa2\xe2\x0e1\x98^\xbe,\x0f\f\x93\xb5L\x0f\xb6z&K\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xdf!\x1c\xd2\x12\x88\xd6\xc5o\xaef\xc3\xffTb]\u0531T'\x89\x87\x86\xcdvN\x1f,\x00\x00\u07d4\xdf#k\xf6\xab\xf4\xf3)7\x95\xbf\f(q\x8f\x93\u3c73k\x89Hz\x9a0E9D\x00\x00\u07d4\xdf1\x02_VI\xd2\xc6\xee\xa4\x1e\u04fd\xd3G\x1ay\x0fu\x9a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xdf7\xc2.`:\xed\xb6\nbrS\xc4}\x8b\xa8f\xf6\xd9r\x8a\x05\x15\n\xe8J\x8c\xdf\x00\x00\x00\u07d4\xdf;r\u017dq\u0501N\x88\xa6#!\xa9=@\x11\xe3W\x8b\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdf?W\xb8\xeed4\xd0G\"=\xeft\xb2\x0fc\xf9\xe4\xf9U\x89\r\x94b\xc6\xcbKZ\x00\x00\u07d4\xdfD\xc4\u007f\xc3\x03\xacv\xe7O\x97\x19L\xcag\xb5\xbb<\x02?\x89 \t\xc5\u023fo\xdc\x00\x00\u07d4\xdfG\xa6\x1brSQ\x93\xc5a\xcc\xccu\xc3\xf3\xce\b\x04\xa2\x0e\x89\x15\x93\\\vN=x\x00\x00\u07d4\xdfG\xa8\xef\x95\xf2\xf4\x9f\x8eoX\x18AT\x14]\x11\xf7'\x97\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xdfS\x003F\xd6\\^zdk\xc04\xf2\xb7\xd3/\xcb\xe5j\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xdfW5:\xaf\xf2\xaa\xdb\n\x04\xf9\x01N\x8d\xa7\x88N\x86X\x9c\x89\bH\x86\xa6nO\xb0\x00\x00\u07d4\xdf`\xf1\x8c\x81*\x11\xedN'v\xe7\xa8\x0e\xcf^S\x05\xb3\u05890\xca\x02O\x98{\x90\x00\x00\u07d4\xdfd\x85\xc4)z\xc1R\xb2\x89\xb1\x9d\xde2\xc7~\xc4\x17\xf4}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xdff\n\x91\u06b9\xf70\xf6\x19\rP\xc89\x05aP\aV\u0289lk\x93[\x8b\xbd@\x00\x00\u07d4\xdfn\xd6\x00jj\xbe\x88n\xd3=\x95\xa4\xde(\xfc\x12\x189'\x891T\xc9r\x9d\x05x\x00\x00\u07d4\u07c5\x10y>\xee\x81\x1c-\xab\x1c\x93\xc6\xf4G?0\xfb\xef[\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u07cdH\xb1\xeb\a\xb3\xc2\x17y\x0el-\xf0M\xc3\x19\xe7\xe8H\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\u07e6\xb8\xb8\xad1\x84\xe3W\xda()Q\u05d1a\u03f0\x89\xbc\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\u07ef1\xe6\"\xc0=\x9e\x18\xa0\u0778\xbe`\xfb\xe3\xe6a\xbe\n\x8a\x02\x1e\x17\x1a>\xc9\xf7,\x00\x00\u07d4\u07f1bn\xf4\x8a\x1d}uR\xa5\xe0)\x8f\x1f\xc2:;H-\x89\\\xe8\x95\u0754\x9e\xfa\x00\x00\xe0\x94\u07f4\u052d\xe5/\u0301\x8a\xccz,k\xb2\xb0\x02$e\x8fx\x8a\x01\xa4 \xdb\x02\xbd}X\x00\x00\u07d4\u07fdB2\xc1|@z\x98\r\xb8\u007f\xfb\u036060\xe5\xc4Y\x89\x1d\xfc\u007f\x92I#S\x00\x00\u07d4\xdf\xcb\xdf\tEN\x1a^J@\xd3\xee\xf7\xc5\xcf\x1c\xd3\u0794\x86\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xdf\xdb\xce\xc1\x01K\x96\xda!X\xcaQ>\x9c\x8d;\x9a\xf1\xc3\u0409lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xdf\xde\xd2WK'\xd1a:}\x98\xb7\x15\x15\x9b\r\x00\xba\xab(\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xdf\xdfC9P\x8b\x0fnZ\xb1\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe0\x06\x04b\xc4\u007f\xf9g\x9b\xae\xf0qY\xca\xe0\x8c)\xf2t\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\r\x15;\x106\x91C\xf9\u007fT\xb8\xd4\xca\"\x9e\xb3\xe8\xf3$\x89\b=lz\xabc`\x00\x00\u07d4\xe0\x12\xdbE8'\xa5\x8e\x16\xc16V\b\xd3n\xd6Xr\x05\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x15G\xbaB\xfc\xaf\xaf\x93\x93\x8b\xec\xf7i\x9ft)\n\xf7O\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x16\xdc\x13\x8e%\x81[\x90\xbe?\xe9\xee\xe8\xff\xb2\xe1\x05bO\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0\x18Y\xf2B\xf1\xa0\xec`/\xa8\xa3\xb0\xb5v@\xec\x89\a^\x89\x1e\x16,\x17{\xe5\xcc\x00\x00\xe0\x94\xe0 \xe8cb\xb4\x87u(6\xa6\xde\v\xc0,\xd8\u061a\x8bj\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xe0#\xf0\x9b(\x87a,|\x9c\xf1\x98\x8e::`+3\x94\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0'\"\x13\xe8\xd2\xfd>\x96\xbdb\x17\xb2KK\xa0\x1bapy\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe0+t\xa4v(\xbe1[\x1fv\xb3\x15\x05J\xd4J\xe9qo\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xe02 \u0197\xbc\u048f&\xef\vt@J\x8b\xeb\x06\xb2\xba{\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xe05/\u07c1\x9b\xa2e\xf1L\x06\xa61\\J\xc1\xfe\x13\x1b.\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe08\x8a\xed\xdd?\xe2\xadV\xf8WH\xe8\x0eq\n4\xb7\xc9.\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0<\x00\xd0\x03\x88\xec\xbfO&=\n\xc7x\xbbA\xa5z@\u064966\xc9yd6t\x00\x00\u07d4\xe0I \xdcn\xcc\x1dn\xcc\bO\x88\xaa\n\xf5\u06d7\xbf\x89:\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xe0Ir\xa8<\xa4\x11+\xc8q\xc7-J\xe1al/\a(\u06c9\x0e\x81\xc7\u007f)\xa3/\x00\x00\u07d4\xe0O\xf5\xe5\xa7\u2bd9]\x88W\xce\x02\x90\xb5:+\x0e\xda]\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xe0P)\xac\xeb\axg[\xef\x17A\xab,\u0493\x1e\xf7\xc8K\x8a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4\xe0V\xbf?\xf4\x1c&%o\xefQqf\x12\xb9\u04da\u0799\x9c\x89\x05k\xe7W\xa1.\n\x80\x00\u07d4\xe0a\xa4\xf2\xfcw\xb2\x96\u045a\xda#\x8eI\xa5\u02ce\xcb\xfap\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe0f>\x8c\xd6g\x92\xa6A\xf5nP\x03f\x01G\x88\x0f\x01\x8e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0f\x8f\xa8,\x14\xd6\xe8\xd9:S\x11>\xf2\x86/\xa8\x15\x81\xbc\x89//9\xfclT\x00\x00\x00\u07d4\xe0i\xc0\x173R\xb1\v\xf6\x83G\x19\xdb[\xed\x01\xad\xf9{\xbc\x89\x01\x064\xf8\xe52;\x00\x00\u07d4\xe0l)\xa8\x15\x17\xe0\u0507\xb6\u007f\xb0\xb6\xaa\xbcOW6\x83\x88\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xe0l\xb6)G\x04\xee\xa7C|/\xc3\xd3\as\xb7\xbf8\x88\x9a\x89\x01\x16\xdc:\x89\x94\xb3\x00\x00\u07d4\xe0q7\xae\r\x11m\x0353\xc4\uad16\xf8\xa9\xfb\tV\x9c\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\xe0v\xdb0\xabHoy\x19N\xbb\xc4]\x8f\xab\x9a\x92B\xf6T\x8a\x01\x06`~4\x94\xba\xa0\x00\x00\u07d4\xe0~\xbb\xc7\xf4\xdaAnB\xc8\xd4\xf8B\xab\xa1b3\xc1%\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x81\xca\x1fH\x82\xdb`C\u0569\x19\a\x03\xfd\xe0\xab;\xf5m\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\x83\xd3Hc\xe0\xe1\u007f\x92ky(\xed\xff1~\x99\x8e\x9cK\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\x8b\x9a\xbak\xd9\u048b\xc2\x05gy\xd2\xfb\xf0\xf2\x85Z=\x9d\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\x8b\u009c+H\xb1i\xff+\xdc\x16qLXnl\xb8\\\u03c9\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe0\x8c`11\x06\xe3\xf93O\xe6\xf7\xe7bM!\x110\xc0w\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xe0\x9ch\xe6\x19\x98\xd9\xc8\x1b\x14\xe4\xee\x80+\xa7\xad\xf6\xd7L\u06c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe0\x9f\xeauZ\xee\x1aD\xc0\xa8\x9f\x03\xb5\u07b7b\xba3\x00o\x89;\xa2\x89\xbc\x94O\xf7\x00\x00\xe0\x94\xe0\xa2T\xac\t\xb9r[\xeb\xc8\xe4`C\x1d\xd0s.\xbc\xab\xbf\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xe0\xaai6UU\xb7?(#3\xd1\xe3\f\x1b\xbd\a(T\xe8\x8a\x01{x\x83\xc0i\x16`\x00\x00\u07d4\xe0\xba\u064e\ue598\xdb\xf6\xd7`\x85\xb7\x92=\xe5uN\x90m\x89\t\r\x97/22<\x00\x00\u07d4\xe0\u012b\x90r\xb4\xe6\xe3eJI\xf8\xa8\xdb\x02jK3\x86\xa9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\u0380\xa4a\xb6H\xa5\x01\xfd\v\x82F\x90\u0206\x8b\x0eM\xe8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe0\xcfi\x8a\x053'\xeb\xd1k}w\x00\t/\xe2\xe8T$F\x89\x05*4\u02f6\x1fW\x80\x00\xe0\x94\xe0\xd21\xe1D\xec\x91\a8l|\x9b\x02\xf1p,\xea\xa4\xf7\x00\x8a\x01\x0f\r\xba\xe6\x10\tR\x80\x00\u07d4\xe0\xd7kqf\xb1\xf3\xa1+@\x91\xee+)\u078c\xaa}\a\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xe0\xe0\xb2\xe2\x9d\xdes\xafu\x98~\xe4Dl\x82\x9a\x18\x9c\x95\xbc\x89\b\x13\xcaV\x90m4\x00\x00\xe0\x94\xe0\xe9xu=\x98/\u007f\x9d\x1d#\x8a\x18\xbdH\x89\xae\xfeE\x1b\x8a\x02\r\u058a\xaf2\x89\x10\x00\x00\u07d4\xe0\xf3r4|\x96\xb5_}C\x06\x03K\xeb\x83&o\xd9\tf\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe0\xf9\x03\xc1\xe4\x8a\xc4!\xabHR\x8f=J&H\b\x0f\xe0C\x897\b\xba\xed=h\x90\x00\x00\u07d4\xe0\xff\v\xd9\x15D9\u0125\xb7#>)\x1d}\x86\x8a\xf5?3\x89\x15y!jQ\xbb\xfb\x00\x00\xe0\x94\xe1\n\xc1\x9cTo\xc2T|a\xc19\xf5\xd1\xf4Zff\u0570\x8a\x01\x02\xdao\xd0\xf7:<\x00\x00\xe0\x94\xe1\fT\x00\x88\x11?\xa6\xec\x00\xb4\xb2\u0202O\x87\x96\xe9n\u010a2\x0fE\t\xab\x1e\xc7\xc0\x00\x00\xe0\x94\xe1\x17:$})\xd8#\x8d\xf0\x92/M\xf2Z\x05\xf2\xafw\u00ca\bx\xc9]V\x0f0G\x80\x00\xe0\x94\xe1 >\xb3\xa7#\xe9\x9c\" \x11|\xa6\xaf\xebf\xfaBOa\x8a\x02\x00\uf49e2V\xfe\x00\x00\xe0\x94\xe11\xf8~\xfc^\xf0~C\xf0\xf2\xf4\xa7G\xb5Q\xd7P\xd9\xe6\x8a\x04<%\xe0\xdc\xc1\xbd\x1c\x00\x00\u07d4\xe13N\x99\x83y\xdf\xe9\x83\x17pby\x1b\x90\xf8\x0e\xe2-\x8d\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe15@\xec\xee\x11\xb2\x12\xe8\xb7u\u070eq\xf3t\xaa\xe9\xb3\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe1;=+\xbf\u073c\x87r\xa23\x15rL\x14%\x16|V\x88\x897\xf3y\x14\x1e\xd0K\x80\x00\u07d4\xe1D=\xbd\x95\xccA#\u007fa:HEi\x88\xa0Oh2\x82\x89\xd8\xd8X?\xa2\xd5/\x00\x00\u07d4\xe1F\x17\xf6\x02%\x01\xe9~{>-\x886\xaaa\xf0\xff-\xba\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe1I\xb5rl\xafm^\xb5\xbf*\xccA\xd4\xe2\xdc2\x8d\u1089i*\xe8\x89p\x81\xd0\x00\x00\xe0\x94\xe1T\xda\xea\xdbTX8\xcb\u01aa\fUu\x19\x02\xf5(h*\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\u07d4\xe1l\xe3Ya\xcdt\xbdY\r\x04\u012dJ\x19\x89\xe0V\x91\u0189\a\xea(2uw\b\x00\x00\u07d4\xe1r\xdf\xc8\xf8\f\xd1\xf8\u03459\xdc&\b \x14\xf5\xa8\xe3\u8262\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xe1w\xe0\xc2\x01\xd35\xba9V\x92\x9cW\x15\x88\xb5\x1cR#\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe1x\x12\xf6l^e\x94\x1e\x18lF\x92+n{/\x0e\xebF\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xe1\x80\u079e\x86\xf5{\xaf\xac\u05d0O\x98&\xb6\xb4\xb2c7\xa3\x89-\x04\x1dpZ,`\x00\x00\xe0\x94\xe1\x92H\x9b\x85\xa9\x82\xc1\x882F\xd9\x15\xb2)\xcb\x13 \u007f8\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xe1\x95\xbb\xc6,{tD\x04\x0e\xb9\x96#\x96Ovg\xb3v\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe2\x06\xfbs$\xe9\u07b7\x9e\x19\x904\x96\u0596\x1b\x9b\xe5f\x03\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe2\aW\x8e\x1fM\u06cf\xf6\u0546{9X-q\xb9\x81*\u0149\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xe2\b\x81*h@\x98\xf3\xdaN\xfej\xba%bV\xad\xfe?\xe6\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe2\tT\xd0\xf4\x10\x8c\x82\xd4\u0732\x14\x8d&\xbb\xd9$\xf6\xdd$\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe2\v\xb9\xf3\x96d\x19\xe1K\xbb\xaa\xaag\x89\xe9$\x96\u03e4y\x89\xbb\xd8%\x03\aRv\x00\x00\u07d4\xe2\r\x1b\xcbq(m\xc7\x12\x8a\x9f\xc7\xc6\xed\u007fs8\x92\xee\xf5\x896d\xf8\xe7\xc2J\xf4\x00\x00\u0794\xe2\x19\x12\x15\x98?3\xfd3\xe2,\u0522I\x00T\xdaS\xfd\u0708\xdbD\xe0I\xbb,\x00\x00\u07d4\xe2\x19\x8c\x8c\xa1\xb3\x99\xf7R\x15a\xfdS\x84\xa7\x13/\xbaHk\x897\b\xba\xed=h\x90\x00\x00\xe0\x94\xe2\x1cw\x8e\xf2\xa0\xd7\xf7Q\xea\x8c\aM\x1f\x81\"C\x86>N\x8a\x01\x1f\xc7\x0e,\x8c\x8a\xe1\x80\x00\xe0\x94\xe2)\xe7F\xa8?,\xe2S\xb0\xb0>\xb1G$\x11\xb5~W\x00\x8a\x016\x9f\xb9a(\xacH\x00\x00\u07d4\xe2+ \xc7x\x94F;\xafwL\xc2V\u057d\u06ff}\xdd\t\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe20\xfe\x1b\xff\x03\x18m\x02\x19\xf1]LH\x1b}Y\xbe(j\x89\x01\xfdt\x1e\x80\x88\x97\x00\x00\u07d4\xe27\xba\xa4\xdb\u0252n2\xa3\xd8]\x12d@-T\xdb\x01/\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2A\t\xbe/Q=\x87I\x8e\x92j(d\x99uO\x9e\u051e\x890\x0e\xa8\xad\x1f'\xca\x00\x00\u07d4\xe2Fh<\u025d\xb7\u0125+\u02ec\xaa\xb0\xb3/k\xfc\x93\u05c9lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe2Z\x16{\x03\x1e\x84am\x0f\x01?1\xbd\xa9]\xcccP\xb9\x8a\x02\x8c*\xaa\u0243\xd0]\u0187st\xa8\xf4F\xee\xe9\x89\n\xb6@9\x12\x010\x00\x00\u07d4\xe2\x8b\x06\"Y\xe9n\xeb<\x8dA\x04\x94?\x9e\xb3%\x89<\xf5\x89Hz\x9a0E9D\x00\x00\xe0\x94\u237c\x8e\xfd^Ajv.\xc0\xe0\x18\x86K\xb9\xaa\x83({\x8a\x051\xf2\x00\xab>\x03\n\x80\x00\u07d4\xe2\x90K\x1a\xef\xa0V9\x8bb4\xcb5\x81\x12\x88\xd76\xdbg\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\u274a\xe4R\xdc\xf3\xb6\xacd^c\x04\t8UQ\xfa\xae\n\x89\x04Z\r\xa4\xad\xf5B\x00\x00\u07d4\xe2\xbb\xf8FA\xe3T\x1fl3\xe6\xedh:cZp\xbd\xe2\xec\x89\x1bA<\xfc\xbfY\xb7\x80\x00\u07d4\xe2\xcf6\n\xa22\x9e\xb7\x9d+\xf7\xca\x04\xa2z\x17\xc52\xe4\u0609\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xe2\xdf#\xf6\xea\x04\xbe\xcfJ\xb7\x01t\x8d\xc0\x961\x84U\\\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xe2\xe1\\`\xdd8\x1e:K\xe2Pq\xab$\x9aL\\Rd\u0689\u007fk\u011b\x81\xb57\x00\x00\u07d4\xe2\xe2nN\x1d\xcf0\xd0H\xccn\u03ddQ\xec\x12\x05\xa4\xe9&\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xe2\xeei\x1f#~\xe6R\x9beW\xf2\xfc\xdd=\xcf\fY\xecc\x8a\x01'r\x9c\x14h| \x00\x00\u07d4\xe2\xef\xa5\xfc\xa7\x958\xce`h\xbf1\xd2\xc5\x16\xd4\xd5<\b\xe5\x89\a\x1c\xc4\b\xdfc@\x00\x00\xe0\x94\xe2\xef\u0429\xbc@~\xce\x03\xd6~\x8e\xc8\xe9\u0483\xf4\x8d*I\x8a\x02\x99\xb3;\xf9\u0144\xe0\x00\x00\u07d4\xe2\xf4\r5\x8f^?\xe7F>\xc7\x04\x80\xbd.\u04d8\xa7\x06;\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe2\xf98=X\x10\xea{C\x18+\x87\x04\xb6+'\xf5\x92]9\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe2\xff\x9e\xe4\xb6\xec\xc1AA\xcct\xcaR\xa9\xe7\xa2\xee\x14\xd9\b\x89K\xe4\xe7&{j\xe0\x00\x00\xe0\x94\xe3\x02\x12\xb2\x01\x1b\xb5k\xdb\xf1\xbc5i\x0f:N\x0f\xd9\x05\xea\x8a\x01\xb2\u07dd!\x9fW\x98\x00\x00\u07d4\xe3\x03\x16\u007f=I`\xfe\x88\x1b2\x80\n+J\xef\xf1\xb0\x88\u0509lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3\x04\xa3/\x05\xa87btJ\x95B\x97o\xf9\xb7#\xfa1\xea\x89Ur\xf2@\xa3F \x00\x00\u07d4\xe3\bCR\x04y7d\xf5\xfc\xbee\xebQ\x0fZtJeZ\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3\t\x97L\xe3\x9d`\xaa\xdf.ig2Q\xbf\x0e\x04v\n\x10\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xe3\x1bN\xef\x18L$\xab\t\x8e6\xc8\x02qK\xd4t=\xd0\u0509\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3!\xbbJ\x94j\xda\xfd\xad\xe4W\x1f\xb1\\\x00C\u04de\xe3_\x89Udu8+L\x9e\x00\x00\u07d4\xe3&<\xe8\xafm\xb3\xe4gXE\x02\xedq\t\x12^\xae\"\xa5\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3+\x1cG%\xa1\x87TI\u93d7\x0e\xb3\xe5@b\xd1X\x00\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe3/\x95vmW\xb5\xcdK\x172\x89\u0587o\x9edU\x81\x94\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xe38@\u063c\xa7\u0698\xa6\xf3\u0416\xd8=\xe7\x8bp\xb7\x1e\xf8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe38\xe8Y\xfe.\x8c\x15UHH\xb7\\\xae\u0368w\xa0\xe82\x89a\xac\xff\x81\xa7\x8a\xd4\x00\x00\u07d4\xe3=\x98\x02 \xfa\xb2Y\xafj\x1fK8\xcf\x0e\xf3\xc6\xe2\xea\x1a\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe3=\xf4\u0380\u0336*v\xb1+\xcd\xfc\xec\xc4b\x89\x97:\xa9\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xe3?\xf9\x87T\x1d\xde\\\xde\u0a29m\xcc?3\xc3\xf2L\u008a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xe3A\v\xb7U|\xf9\x1dy\xfai\xd0\xdf\xea\n\xa0u@&Q\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe3Ad-@\u04af\xce.\x91\a\xc6py\xacz&`\bl\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe3TS\xee\xf2\xcc2\x89\x10CR\x8d\t\x84i\x80\x00\xe0\x94\xe5\x10\xd6y\u007f\xba=f\x93\x83Z\x84N\xa2\xadT\x06\x91\x97\x1b\x8a\x03\xae9\xd4s\x83\xe8t\x00\x00\u07d4\xe5\x14!\xf8\xee\"\x10\xc7\x1e\xd8p\xfea\x82v\u0215J\xfb\xe9\x89Hz\x9a0E9D\x00\x00\u07d4\xe5\x1e\xb8~\u007f\xb71\x1fR(\xc4y\xb4\x8e\u0247\x881\xacL\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5!V1\xb1BH\xd4Z%R\x96\xbe\xd1\xfb\xfa\x030\xff5\x89G\x03\xe6\xebR\x91\xb8\x00\x00\xe0\x94\xe5(\xa0\xe5\xa2g\xd6g\xe99:e\x84\xe1\x9b4\u071b\xe9s\x8a\x01/\x93\x9c\x99\xed\xab\x80\x00\x00\u07d4\xe54%\xd8\xdf\x1f\x11\xc3A\xffX\xae_\x148\xab\xf1\xcaS\u03c9\x11t\xa5\xcd\xf8\x8b\xc8\x00\x00\u07d4\xe5No\x9c\xffV\xe1\x9cF\x1e\xb4T\xf9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5A\x02SM\xe8\xf2>\xff\xb0\x93\xb3\x12B\xad;#?\xac\xfd\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xe5E\xee\x84\xeaH\xe5d\x16\x1e\x94\x82\u055b\xcf@j`,\xa2\x89dI\xe8NG\xa8\xa8\x00\x00\u07d4\xe5H\x1a\u007f\xedB\xb9\x01\xbb\xed x\x9b\u052d\xe5\r_\x83\xb9\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5Y\xb5\xfd3{\x9cUr\xa9\xbf\x9e\x0f%!\xf7\xd4F\xdb\xe4\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe5\\\x80R\n\x1b\x0fu[\x9a,\xd3\xce!Ov%e>\x8a\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe5mC\x13$\xc9)\x11\xa1t\x9d\xf2\x92p\x9c\x14\xb7ze\u034a\x01\xbc\x85\xdc*\x89\xbb \x00\x00\u07d4\xe5})\x95\xb0\xeb\xdf?<\xa6\xc0\x15\xeb\x04&\r\xbb\x98\xb7\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\u51f1j\xbc\x8at\b\x1e6\x13\xe1CB\xc03u\xbf\bG\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\x89\xfav\x98M\xb5\xec@\x04\xb4n\u8954\x92\xc3\aD\u0389\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xe5\x8d\xd228\xeen\xa7\xc2\x13\x8d8]\xf5\x00\xc3%\xf3v\xbe\x89b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xe5\x95?\xeaIq\x04\xef\x9a\xd2\xd4\xe5\x84\x1c'\x1f\a5\x19\u0089&)\xf6n\fS\x00\x00\x00\xe0\x94\u5587\x97F\x8e\xf7g\x10\x1bv\x1dC\x1f\xce\x14\xab\xff\u06f4\x8a\x01\xb3\xd9i\xfaA\x1c\xa0\x00\x00\u07d4\xe5\x97\xf0\x83\xa4i\xc4Y\x1c=+\x1d,w'\x87\xbe\xfe'\xb2\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xe5\x9b;\xd3\x00\x89?\x97#>\xf9G\xc4or\x17\xe3\x92\xf7\xe9\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5\xa3e4<\xc4\xeb\x1ew\x03h\xe1\xf1\x14Jw\xb82\xd7\xe0\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe5\xa3\xd7\xeb\x13\xb1\\\x10\x01w#m\x1b\xeb0\xd1~\xe1T \x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xaa\v\x83;\xb9\x16\xdc\x19\xa8\xddh?\x0e\xde$\x1d\x98\x8e\xba\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\u5def\x14i\x86\xc0\xff\x8f\x85\xd2.l\xc34\a}\x84\xe8$\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xb8&\x19l\x0e\x1b\xc1\x11\x9b\x02\x1c\xf6\xd2Y\xa6\x10\u0256p\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe5\xb9o\u026c\x03\xd4H\xc1a:\xc9\x1d\x15\x97\x81E\xdb\xdf\u0449\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\u5e40\u048e\xec\xe2\xc0o\xcal\x94s\x06\x8b7\u0526\xd6\xe9\x89%\xaf\u058c\xac+\x90\x00\x00\u07d4\u5eb4\xf0\xaf\u0629\u0463\x81\xb4Wa\xaa\x18\xf3\xd3\xcc\xe1\x05\x89Q\xbf\xd7\xc18x\xd1\x00\x00\u07d4\xe5\xbc\u020c;%on\xd5\xfeU\x0eJ\x18\x19\x8b\x943V\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xbd\xf3OL\xccH>L\xa50\xcc|\xf2\xbb\x18\xfe\xbe\x92\xb3\x89\x06\xd85\xa1\v\xbc\xd2\x00\x00\u07d4\xe5\u0713I\xcbR\xe1a\x19a\"\u03c7\xa3\x896\xe2\xc5\u007f4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xe38\x00\xa1\xb2\xe9k\xde\x101c\n\x95\x9a\xa0\a\xf2nQ\x89Hz\x9a0E9D\x00\x00\u07d4\xe5\xe3~\x19@\x8f,\xfb\xec\x834\x9d\u0501S\xa4\xa7\x95\xa0\x8f\x89\u3bb5sr@\xa0\x00\x00\u07d4\xe5\xed\xc7>bo]4A\xa4U9\xb5\xf7\xa3\x98\u0153\xed\xf6\x89.\xe4IU\b\x98\xe4\x00\x00\u07d4\xe5\xed\xf8\x12?$\x03\xce\x1a\x02\x99\xbe\xcfz\xactM\a_#\x89\n\xdaUGK\x814\x00\x00\u07d4\xe5\xf8\xefm\x97\x066\xb0\u072aO \x0f\xfd\xc9\xe7Z\xf1t\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe5\xfb1\xa5\xca\xeej\x96\xde9;\xdb\xf8\x9f\xbee\xfe\x12[\xb3\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe5\xfb\xe3I\x84\xb67\x19o3\x1cg\x9d\f\fG\xd84\x10\xe1\x89llD\xfeG\xec\x05\x00\x00\u07d4\xe6\tU\xdc\v\xc1V\xf6\xc4\x18I\xf6\xbdwk\xa4K\x0e\xf0\xa1\x89\x10C\x16'\xa0\x93;\x00\x00\u07d4\xe6\nU\xf2\u07d9m\u00ee\xdbil\b\xdd\xe09\xb2d\x1d\xe8\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe6\x11[\x13\xf9y_~\x95e\x02\xd5\aEg\u06b9E\xcek\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xe6\x1f(\t\x15\xc7t\xa3\x1d\"<\xf8\f\x06\x92f\xe5\xad\xf1\x9b\x89/\xb4t\t\x8fg\xc0\x00\x00\u07d4\xe6/\x98e\a\x12\xeb\x15\x87S\xd8)r\xb8\u9723\xf6\x18w\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe6/\x9d|d\xe8\xe2cZ\xeb\x88=\xd7;\xa6\x84\xee|\x10y\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xe6>xt\x14\xb9\x04\x84x\xa5\a35\x9e\xcd\xd7\xe3dz\xa6\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xe6FfXr\xe4\v\rz\xa2\xff\x82r\x9c\xaa\xba[\xc3\u8789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe6N\xf0\x12e\x8dT\xf8\xe8`\x9cN\x90#\xc0\x9f\xe8e\xc8;\x89\x01\x84\x93\xfb\xa6N\xf0\x00\x00\u07d4\xe6On\x1dd\x01\xb5l\akd\xa1\xb0\x86}\v/1\rN\x89\x02\u02edq\xc5:\xe5\x00\x00\u07d4\xe6g\xf6R\xf9W\u008c\x0ef\u04364\x17\xc8\f\x8c\x9d\xb8x\x89 \x9d\x92/RY\xc5\x00\x00\xe0\x94\xe6w\xc3\x1f\xd9\xcbr\x00u\u0724\x9f\x1a\xbc\xcdY\xec3\xf74\x8a\x01\xa6\u05be\xb1\xd4.\xe0\x00\x00\u07d4\xe6|,\x16e\u02038h\x81\x87b\x9fI\xe9\x9b`\xb2\u04fa\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xe6\x9al\xdb:\x8a}\xb8\xe1\xf3\f\x8b\x84\xcds\xba\xe0+\xc0\xf8\x8a\x03\x94\xfd\xc2\xe4R\xf6q\x80\x00\u07d4\xe6\x9d\x1c7\x8bw\x1e\x0f\xef\xf0Q\xdbi\xd9f\xacgy\xf4\xed\x89\x1d\xfaj\xaa\x14\x97\x04\x00\x00\u07d4\xe6\x9f\xcc&\xed\"_{.7\x984\xc5$\xd7\f\x175\u5f09lk\x93[\x8b\xbd@\x00\x00\u07d4\xe6\xa3\x01\x0f\x02\x01\xbc\x94\xffg\xa2\xf6\x99\xdf\xc2\x06\xf9\xe7gB\x89/\xa7\xcb\xf6dd\x98\x00\x00\u07d4\xe6\xa6\xf6\xddop\xa4V\xf4\xec\x15\xefz\xd5\xe5\u06f6\x8b\xd7\u0709\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe6\xb2\x0f\x98\n\xd8S\xad\x04\xcb\xfc\x88|\xe6`\x1ck\xe0\xb2L\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\u6cec?]M\xa5\xa8\x85}\v?0\xfcK+i+w\u05c9O%\x91\xf8\x96\xa6P\x00\x00\u07d4\xe6\xb9T_~\u0406\xe5R\x92F9\xf9\xa9\xed\xbb\xd5T\v>\x89\xcb\xd4{n\xaa\x8c\xc0\x00\x00\xe0\x94\xe6\xbc\xd3\n\x8f\xa18\xc5\xd9\xe5\xf6\xc7\xd2\u0680i\x92\x81-\u034a7\x0e\xa0\xd4|\xf6\x1a\x80\x00\x00\u07d4\xe6\xc8\x1f\xfc\xec\xb4~\xcd\xc5\\\vq\xe4\x85_>^\x97\xfc\x1e\x89\x12\x1e\xa6\x8c\x11NQ\x00\x00\u07d4\xe6\xcb&\vqmL\n\xb7&\xee\xeb\a\xc8pr\x04\xe2v\xae\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe6\xcb?1$\xc9\xc9\xcc84\xb1'K\xc33dV\xa3\x8b\xac\x89\x17+\x1d\xe0\xa2\x13\xff\x00\x00\xe0\x94\xe6\xd2\"\t\xff\u0438u\t\xad\xe3\xa8\xe2\xefB\x98y\u02c9\xb5\x8a\x03\xa7\xaa\x9e\x18\x99\xca0\x00\x00\u07d4\xe6\u051f\x86\xc2(\xf4sg\xa3^\x88l\xaa\xcb'\x1eS\x94)\x89\x16^\xc0\x9d\xa7\xa1\x98\x00\x00\u07d4\xe6\xe6!\xea\xab\x01\xf2\x0e\xf0\x83k|\xadGFL\xb5\xfd<\x96\x89\x11!\x93B\xaf\xa2K\x00\x00\u07d4\xe6\xe8\x861{jf\xa5\xb4\xf8\x1b\xf1d\xc58\xc2d5\x17e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe6\u98ddu\x0f\xe9\x949N\xb6\x82\x86\xe5\xeab\xa6\x99x\x82\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xe6\xec\\\xf0\u011b\x9c1~\x1epc\x15\uf7b7\xc0\xbf\x11\xa7\x8a\x03\xa4i\xf3F~\x8e\xc0\x00\x00\u07d4\xe6\xf5\xebd\x9a\xfb\x99Y\x9cAK'\xa9\xc9\xc8U5\u007f\xa8x\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xe6\xfe\n\xfb\x9d\xce\xdd7\xb2\xe2,E\x1b\xa6\xfe\xabg4\x803\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xe7\x10\xdc\u041b\x81\x01\xf9C{\xd9}\xb9\ns\xef\x99=\v\xf4\x89\x14\xee6\xc0Z\xc2R\x00\x00\u07d4\xe7'\xe6~\xf9\x11\xb8\x1fl\xf9\xc7?\xcb\xfe\xbc+\x02\xb5\xbf\u0189lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7.\x1d3\\\u009a\x96\xb9\xb1\xc0/\x00:\x16\xd9q\xe9\v\x9d\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xe71\x1c\x953\xf0\t,rH\xc9s\x9b[,\x86J4\xb1\u0389\x97\xf9}l\xc2m\xfe\x00\x00\u07d4\xe7;\xfe\xad\xa6\xf0\xfd\x01o\xbc\x84>\xbc\xf6\xe3p\xa6[\xe7\f\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xe7<\xcfCg%\xc1Q\xe2U\xcc\xf5!\f\xfc\xe5\xa4?\x13\xe3\x89\x01\x15NS!}\xdb\x00\x00\u07d4\xe7B\xb1\xe6\x06\x9a\x8f\xfc'\f\xc6\x1f\xa1d\xac\x15SE\\\x10]\x04\x88~\x14\x89\x06\x96\xd8Y\x00 \xbb\x00\x00\u07d4\xe7\\\x1f\xb1w\b\x9f>X\xb1\x06y5\xa6Yn\xf1s\u007f\xb5\x89\x05j\x87\x9f\xa7uG\x00\x00\u07d4\xe7\\;8\xa5\x8a?3\xd5V\x90\xa5\xa5\x97f\xbe\x18^\x02\x84\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe7a\xd2\u007f\xa3P,\xc7k\xb1\xa6\bt\x0e\x14\x03\u03dd\xfci\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xe7f\xf3O\xf1o<\xfc\xc9s!r\x1fC\xdd\xf5\xa3\x8b\f\xf4\x89T\x06\x923\xbf\u007fx\x00\x00\u07d4\xe7m\x94Z\xa8\x9d\xf1\xe4W\xaa4+1\x02\x8a^\x910\xb2\u03897\b\xba\xed=h\x90\x00\x00\u07d4\xe7s^\xc7e\x18\xfcj\xa9-\xa8qZ\x9e\xe3\xf6%x\x8f\x13\x89lM\x16\v\xaf\xa1\xb7\x80\x00\xe0\x94\xe7z\x89\xbdE\xdc\x04\xee\xb4\xe4\x1d{Ykp~nQ\xe7L\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xe7}}\uac96\u0234\xfa\a\xca;\xe1\x84\x16=Zm`l\x89\x05\x049\x04\xb6q\x19\x00\x00\u07d4\xe7\u007f\xeb\xab\xdf\b\x0f\x0f]\xca\x1d?Wf\xf2\xa7\x9c\x0f\xfa|\x89K\"\x9d(\xa8Ch\x00\x00\xe0\x94\u7025c\x06\xba\x1ek\xb31\x95,\"S\x9b\x85\x8a\xf9\xf7}\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\xe7\x81\xecs-@\x12\x02\xbb\x9b\xd18`\x91\r\xd6\u009a\xc0\xb6\x89C8t\xf62\xcc`\x00\x00\u07d4\xe7\x84\xdc\xc8s\xaa\x8c\x15\x13\xec&\xff6\xbc\x92\xea\xc6\xd4\xc9h\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe7\x91-L\xf4V,W=\xdc[q\xe3s\x10\xe3x\xef\x86\u0249\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xe7\x91\u0545\xb8\x996\xb2])\x8f\x9d5\xf9\xf9\xed\xc2Z)2\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7\x924\x9c\xe9\xf6\xf1O\x81\xd0g@\x96\xbe\xfa\x1f\x92!\xcd\xea\x89[]#J\r\xb48\x80\x00\u07d4\xe7\x96\xfdN\x83\x9bL\x95\xd7Q\x0f\xb7\xc5\xc7+\x83\xc6\xc3\xe3\u01c9\x1b\xc43\xf2?\x83\x14\x00\x00\xe0\x94\xe7\xa4/Y\xfe\xe0t\xe4\xfb\x13\xea\x9eW\xec\xf1\xccH(\"I\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xe7\xa4V\f\x84\xb2\x0e\x0f\xb5LIg\f)\x03\xb0\xa9lB\xa4\x89 j\xea\u01e9\x03\x98\x00\x00\u07d4\xe7\xa8\xe4q\xea\xfby\x8fET\xccnRg0\xfdV\xe6,}\x8965\u026d\xc5\u07a0\x00\x00\u07d4\u7f82\xc6Y<\x1e\xed\xdd*\xe0\xb1P\x01\xff \x1a\xb5{/\x89\x01\t\x10\xd4\xcd\xc9\xf6\x00\x00\u07d4\xe7\u01b5\xfc\x05\xfct\x8e[C\x81rdI\xa1\xc0\xad\x0f\xb0\xf1\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe7\xd1u$\xd0\v\xad\x82I|\x0f'\x15jd\u007f\xf5\x1d'\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xe7\xd2\x13\x94\u007f\u02d0J\xd78H\v\x1e\xed/\\2\x9f'\xe8\x89\x01\x03\u00f1\xd3\xe9\xc3\x00\x00\u07d4\xe7\xd6$\x06 \xf4,^\u06f2\xed\xe6\xae\xc4=\xa4\xed\x9bWW\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe7\xda`\x9d@\xcd\xe8\x0f\x00\xce[O\xfbj\xa9\u04304\x94\xfc\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe7\xf0oi\x9b\xe3\x1cD\vC\xb4\xdb\x05\x01\xec\x0e%&\x16D\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe7\xf4\xd7\xfeoV\x1f\u007f\xa1\xda0\x05\xfd6TQ\xad\x89\u07c9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe7\xfd\x8f\xd9Y\xae\xd2v~\xa7\xfa\x96\f\xe1\xdbS\xaf\x80%s\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe8\x0e\u007f\xef\x18\xa5\xdb\x15\xb0\x14s\xf3\xadkx\xb2\xa2\xf8\xac\u0649\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xe8\x13\u007f\xc1\xb2\xec|\xc7\x10:\xf9!\x89\x9bJ9\xe1\xd9Y\xa1\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\xe8\x1c-4l\n\xdfL\xc5g\b\xf69K\xa6\xc8\u0226J\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8,X\xc5yC\x1bg5F\xb5:\x86E\x9a\xca\xf1\u079b\x93\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xe84\xc6C\x18 \\\xa7\xddJ!\xab\xcb\b&l\xb2\x1f\xf0,\x8965\xc6 G9\u0640\x00\u07d4\xe86\x04\xe4\xffk\xe7\xf9o`\x18\xd3\xec0r\xecR]\xffk\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\xe0\x94\xe8E\xe3\x87\xc4\xcb\u07d8\"\x80\xf6\xaa\x01\xc4\x0eK\xe9X\u0772\x8a\x05K@\xb1\xf8R\xbd\xa0\x00\x00\u07d4\xe8H\xca~\xbf\xf5\xc2O\x9b\x9c1g\x97\xa4;\xf7\xc3V)-\x89\x06.\x11\\\x00\x8a\x88\x00\x00\u07d4\xe8KU\xb5%\xf1\x03\x9etK\x91\x8c\xb33$\x92\xe4^\xcaz\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe8O\x80v\xa0\xf2\x96\x9e\xcd3>\xef\x8d\xe4\x10B\x98b\x91\xf2\x89\x17k4O*x\xc0\x00\x00\u07d4\xe8d\xfe\xc0~\xd1!Je1\x1e\x11\xe3)\xde\x04\r\x04\xf0\xfd\x89Y\u0283\xf5\xc4\x04\x96\x80\x00\u07d4\xe8}\xba\xc66\xa3w!\xdfT\xb0\x8a2\xefIY\xb5\xe4\xff\x82\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xe8~\x9b\xbf\xbb\xb7\x1c\x1at\ft\xc7#Bm\xf5]\x06=\u064a\x01\xb1\x92\x8c\x00\u01e68\x00\x00\u07d4\xe8~\xacm`+A\t\xc9g\x1b\xf5{\x95\f,\xfd\xb9\x9dU\x89\x02\xb4\xf2\x19r\xec\xce\x00\x00\xe0\x94\u807b\xbeir-\x81\xef\xec\xaaH\u0455*\x10\xa2\xbf\xac\x8f\x8a\x03c\\\x9a\xdc]\xea\x00\x00\x00\u07d4\xe8\x92Is\x8b~\xce\xd7\xcbfjf\xe4s\xbcv\x82/U\t\x8d\x89\xb9\x1c\u0149lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8\xc3\u04f0\xe1\u007f\x97\xd1\xe7V\xe6\x84\xf9N\x14p\xf9\x9c\x95\xa1\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xe8\xc3\xf0E\xbb}8\xc9\xd2\U000d5c3a\x84\x92\xb2S#\t\x01\x8a\x01\xe7\xe4\x17\x1b\xf4\u04e0\x00\x00\u07d4\xe8\xccC\xbcO\x8a\xcf9\xbf\xf0N\xbf\xbfB\xaa\xc0j2\x84p\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xe8\xd9B\xd8/\x17^\xcb\x1c\x16\xa4\x05\xb1\x01C\xb3\xf4k\x96:\x89\x1e\xd2\xe8\xffm\x97\x1c\x00\x00\u07d4\xe8\u077e\xd72\xeb\xfeu@\x96\xfd\xe9\bk\x8e\xa4\xa4\xcd\xc6\x16\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe8\xder^\xca]\xef\x80_\xf7\x94\x1d1\xac\x1c.4-\xfe\x95\x89\x85~\ro\x1d\xa7j\x00\x00\u07d4\xe8\xe9\x85\x05\x86\xe9OR\x99\xabIK\xb8!\xa5\xf4\f\x00\xbd\x04\x89\xcf\x15&@\xc5\xc80\x00\x00\xe0\x94\xe8\xea\u047b\x90\xcc\u00ee\xa2\xb0\xdc\u0175\x80VUFU\xd1\u054a\x01\xa4\xab\xa2%\xc2\a@\x00\x00\u07d4\xe8\xea\xf1)D\t-\xc3Y\x9b9S\xfa|\xb1\xc9v\x1c\xc2F\x89a\x94\x04\x9f0\xf7 \x00\x00\xe0\x94\xe8\xedQ\xbb\xb3\xac\xe6\x9e\x06\x02K3\xf8hD\xc4sH\u06de\x8a\"\xf9\xea\x89\xf4\xa7\xd6\xc4\x00\x00\u07d4\xe8\xef\x10\r|\xe0\x89X2\xf2g\x8d\xf7-J\u03cc(\xb8\xe3\x89\x1b\x1bk\u05efd\xc7\x00\x00\u07d4\xe8\xf2\x99i\xe7\\e\xe0\x1c\xe3\xd8aT }\n\x9e|v\xf2\x89\xa2/\xa9\xa7:'\x19\x80\x00\u07d4\xe8\xfc6\xb0\x13\x1e\xc1 \xac\x9e\x85\xaf\xc1\f\xe7\vV\u0636\xba\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe9\n5L\xec\x04\u059e]\x96\xdd\xc0\xc5\x13\x8d=3\x15\n\xa0\x89\x1b\x1a}\u03caD\u04c0\x00\xe0\x94\xe9\x13>}1\x84]_+f\xa2a\x87\x92\xe8i1\x1a\xcff\x8a\x05\x17\xc0\xcb\xf9\xa3\x90\x88\x00\x00\u07d4\xe9\x1d\xac\x01\x95\xb1\x9e7\xb5\x9bS\xf7\xc0\x17\xc0\xb29[\xa4L\x89e\xea=\xb7UF`\x00\x00\u07d4\xe9\x1f\xa0\xba\xda\u0779\xa9~\x88\xd3\xf4\xdb|U\u05bbt0\xfe\x89\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\xe9#\xc0aw\xb3B~\xa4H\xc0\xa6\xff\x01\x9bT\xccT\x8d\x95\x89\x01\xf7\x80\x01Fg\xf2\x80\x00\xe0\x94\xe9=G\xa8\u0288]T\fNRo%\xd5\xc6\xf2\xc1\b\u0138\x8a\x17\xda:\x04\u01f3\xe0\x00\x00\x00\u07d4\xe9E\x8fh\xbb',\xb5g:\x04\xf7\x81\xb4\x03Uo\u04e3\x87\x89\x03N\x8b\x88\xce\xe2\xd4\x00\x00\u07d4\xe9IA\xb6\x03`\x19\xb4\x01j0\xc1\x03}Zi\x03\xba\xba\xad\x89*H\xac\xabb\x04\xb0\x00\x00\u07d4\xe9I[\xa5\x84'(\xc0\ud5fe7\xd0\xe4\"\xb9\x8di ,\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xe9M\xed\x99\u0735r\xb9\xbb\x1d\u02e3/m\xee\x91\xe0W\x98N\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\xe0\x94\xe9QyR}\uc951l\xa9\xa3\x8f!\\\x1e\x9c\xe77\xb4\u024a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xe9U\x91\x85\xf1f\xfc\x95\x13\xccq\x11aD\xce-\xeb\x0f\x1dK\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xe9^\x92\xbb\xc6\xde\a\xbf:f\x0e\xbf_\xeb\x1c\x8a5'\xe1\u0148\xfc\x93c\x92\x80\x1c\x00\x00\xe0\x94\xe9e\u06a3@9\xf7\xf0\xdfb7Z7\u5acar\xb3\x01\xe7\x8a\x01\x03\xfd\xde\u0373\xf5p\x00\x00\u07d4\xe9i\xea\x15\x95\xed\xc5\u0127\a\xcf\xde8\t)c2Q\xa2\xb0\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xe9k\x18N\x1f\x0fT\x92J\xc8t\xf6\v\xbfDptF\xb7+\x89\x9d\xcc\x05\x15\xb5n\f\x00\x00\xe0\x94\xe9m}L\xdd\x15U:NM1mmd\x80\xca<\xea\x1e8\x8a\x02\x95]\x02\xe1\xa15\xa0\x00\x00\u07d4\xe9n-8\x13\xef\xd1\x16_\x12\xf6\x02\xf9\u007fJb\x90\x9d\x1b;\xc0\xe9\xaa\"\u007f\x90\x89'\xcaK\xd7\x19\xf0\xb8\x00\x00\u07d4\xea,\x19}&\xe9\x8b\r\xa8>\x1br\u01c7a\x8c\x97\x9d=\xb0\x89\x01\x11du\x9f\xfb2\x00\x00\xe0\x94\xea7y\xd1J\x13\xf6\u01c5f\xbc\xde@5\x91A:b9\u06ca)\xb7d2\xb9DQ \x00\x00\u07d4\xeaN\x80\x9e&j\xe5\xf1<\xdb\u33dd\x04V\xe68m\x12t\x89\xf3\xf2\v\x8d\xfai\xd0\x00\x00\xe0\x94\xeaS\xc9T\xf4\xed\x97\xfdH\x10\x11\x1b\u06b6\x9e\xf9\x81\xef%\xb9\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xeaS\xd2ed\x85\x9d\x9e\x90\xbb\x0eS\xb7\xab\xf5`\xe0\x16,8\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xea`Ci\x12\xdek\xf1\x87\u04e4r\xff\x8fS3\xa0\xf7\xed\x06\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xea`T\x9e\xc7U?Q\x1d!I\xf2\xd4fl\xbd\x92C\xd9<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xeaf\xe7\xb8M\u037f6\xee\xa3\xe7[\x858*u\xf1\xa1]\x96\x89]\xbc\x91\x91&o\x11\x80\x00\u07d4\xeahlPW\t<\x17\x1cf\u06d9\xe0\x1b\x0e\xce\xcb0\x86\x83\x89\x14\u0768],\xe1G\x80\x00\u07d4\xeaj\xfe,\xc9(\xac\x83\x91\xeb\x1e\x16_\xc4\x00@\xe3t!\u7262\u007f\xa0c\xb2\xe2\xe6\x80\x00\u07d4\xeay\x05}\xab\xef^d\xe7\xb4O\u007f\x18d\x8e~S7\x18\u0489\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xea|Mm\xc7)\xcdk\x15|\x03\xad#|\xa1\x9a \x93F\u00c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\x81h\xfb\xf2%\xe7\x86E\x9c\xa6\xbb\x18\xd9c\xd2kPS\t\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xea\x81\u02868T\f\xd9\xd4\xd7=\x06\x0f,\xeb\xf2$\x1f\xfc>\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xea\x83\x17\x19yYB@A\xd9\xd7\xc6z>\xce\x1d\xbbx\xbbU\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xea\x85'\xfe\xbf\xa1\xad\xe2\x9e&A\x93)\u04d3\xb9@\xbb\xb7\u0709lj\xccg\u05f1\xd4\x00\x00\u07d4\xea\x8f0\xb6\xe4\xc5\xe6R\x90\xfb\x98d%\x9b\u0159\x0f\xa8\ue289\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xea\x94\xf3(\b\xa2\uf29b\xf0\x86\x1d\x1d$\x04\xf7\xb7\xbe%\x8a\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xea\xa4\\\xea\x02\xd8},\xc8\xfd\xa9CN-\x98[\xd4\x03\x15\x84\x89h\x1f\xc2\xccn+\x8b\x00\x00\xe0\x94\uac3d\x14\x83\t\x18l\xf8\xcb\xd1;r2\xd8\tZ\u02c3:\x8a\x02C\x9a\x88\x1cjq|\x00\x00\u07d4\uaed0\xd3y\x89\xaa\xb3\x1f\xea\xe5G\xe0\xe6\xf3\x99\x9c\xe6\xa3]\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xc0\x82~\xff\fn?\xf2\x8a}JT\xf6\\\xb7h\x9d{\x99\x89\x9a\xd9\u67ddGR\x00\x00\u07d4\xea\xc1H(&\xac\xb6\x11\x1e\x19\xd3@\xa4_\xb8QWk\xed`\x89\x01\xbe\x8b\xab\x04\u067e\x80\x00\xe0\x94\xea\xc1{\x81\xedQ\x91\xfb\b\x02\xaaT3s\x13\x83A\a\xaa\xa4\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xea\u00efW\x84\x92\u007f\u9958\xfcN\xec8\xb8\x10/7\xbcX\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xea\u01b9\x88BT.\xa1\v\xb7O&\xd7\xc7H\x8fi\x8bdR\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xea\xc7h\xbf\x14\xb8\xf9C.i\xea\xa8*\x99\xfb\xeb\x94\xcd\f\x9c\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4\xea\xd2\x1c\x1d\xec\u03ff\x1c\\\xd9f\x88\xa2Gki\xba\a\xceJ\x89\x03\xf2M\x8eJ\x00p\x00\x00\u07d4\xea\xd4\xd2\xee\xfbv\xab\xaeU3\x96\x1e\xdd\x11@\x04\x06\xb2\x98\xfc\x89\xd2U\xd1\x12\xe1\x03\xa0\x00\x00\u07d4\xea\xd6Rb\xed]\x12-\xf2\xb2u\x14\x10\xf9\x8c2\xd1#\x8fQ\x89\x05\x83\x17\xedF\xb9\xb8\x00\x00\u07d4\xea\xd7P\x16\u3801Pr\xb6\xb1\b\xbc\xc1\xb7\x99\xac\xf08>\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xea#\xaa\x05r\x00\xe7\xc9\xc1^\x8f\xf1\x90\xd0\xe6l\f\x0e\x83\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xea\xed\x16\xea\xf5\u06ab[\xf0)^^\a\u007fY\xfb\x82U\x90\v\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xea\xed\xcck\x8bib\xd5\xd9(\x8c\x15lW\x9dG\xc0\xa9\xfc\xff\x89\x04\x9b\x9c\xa9\xa6\x944\x00\x00\u07d4\xea\xf5#\x88Tn\xc3Z\xcaolc\x93\xd8\xd6\t\xde:K\xf3\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xeb\x10E\x8d\xac\xa7\x9eJk$\xb2\x9a\x8a\x8a\xdaq\x1b\u007f.\xb6\x89\u063beI\xb0+\xb8\x00\x00\u07d4\xeb\x1c\xea{E\u047dM\x0e*\x00{\u04ff\xb3Tu\x9e,\x16\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\xeb%H\x1f\u035c\"\x1f\x1a\xc7\xe5\xfd\x1e\u0353\a\xa1b\x15\xb8\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\xe0\x94\xeb.\xf3\u04cf\xe6R@<\xd4\xc9\xd8^\xd7\xf0h,\xd7\xc2\u078a\t\x0fSF\b\xa7(\x80\x00\x00\xe0\x94\xeb;\xddY\xdc\u0765\xa9\xbb*\xc1d\x1f\xd0!\x80\xf5\xf3e`\x8a\x01e\xc9fG\xb3\x8a \x00\x00\u07d4\xeb<\xe7\xfc8\x1cQ\xdb}_\xbdi/\x8f\x9e\x05\x8aLp=\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xebE?Z:\xdd\u074a\xb5gP\xfa\xdb\x0f\xe7\xf9M\x9c\x89\xe7\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xebO\x00\xe2\x836\xea\t\x94%\x88\ueb12\x18\x11\xc5\"\x14<\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xebR\xab\x10U4\x922\x9c\x1cT\x83:\xe6\x10\xf3\x98\xa6[\x9d\x89\b=lz\xabc`\x00\x00\u07d4\xebW\r\xba\x97R'\xb1\xc4-n\x8d\xea,V\u026d\x96\x06p\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xebc\x94\xa7\xbf\xa4\u0489\x11\u0565\xb2>\x93\xf3^4\f\"\x94\x89\x04:w\xaa\xbd\x00x\x00\x00\u07d4\xebh\x10i\x1d\x1a\xe0\u045eG\xbd\"\u03be\u0cfa'\xf8\x8a\x89\x87\x85c\x15\xd8x\x15\x00\x00\u07d4\xebvBL\x0f\u0557\xd3\xe3A\xa9d*\xd1\xee\x11\x8b+W\x9d\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xeb| +F+|\u0145]t\x84u_n&\xefC\xa1\x15\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xeb\x83\\\x1a\x91\x18\x17\x87\x8a3\xd1gV\x9e\xa3\xcd\u04c7\xf3(\x8965\u026d\xc5\u07a0\x00\x00\u07d4\ub268\x82g\t\t\xcf7~\x9ex(n\xe9{\xa7\x8dF\u0089+|\xc2\xe9\xc3\"\\\x00\x00\xe0\x94\xeb\x90\u01d3\xb3S\x97a\xe1\xc8\x14\xa2\x96q\x14\x86\x92\x19>\xb4\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xeb\x9c\xc9\xfe\bi\xd2\u06b5,\u01ea\xe8\xfdW\xad\xb3_\x9f\xeb\x89j\x93\xbb\x17\xaf\x81\xf8\x00\x00\xe0\x94\ub8c8\xb0\xda'\xc8{\x1c\xc0\xea\xc6\xc5{,Z\vE\x9c\x1a\x8a\x01p\xa0\xf5\x04\x0eP@\x00\x00\u07d4\xeb\xaa!m\xe9\xccZC\x03\x17\a\xd3o\xe6\u057e\xdc\x05\xbd\xf0\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xeb\xac+D\b\xefT1\xa1;\x85\b\xe8bP\x98!\x14\xe1E\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xeb\xb6,\xf8\xe2,\x88K\x1b(\xc6\xfa\x88\xfb\xbc\x17\x93\x8a\xa7\x87\x89+By\x84\x03\u0278\x00\x00\u07d4\xeb\xb7\xd2\xe1\x1b\u01b5\x8f\n\x8dE\xc2\xf6\xde0\x10W\n\u0211\x89\x01s\x17\x90SM\xf2\x00\x00\u07d4\xeb\xbbO,=\xa8\xbe>\xb6-\x1f\xfb\x1f\x95\x02a\u03d8\xec\u0689lk\x93[\x8b\xbd@\x00\x00\u07d4\xeb\xbdM\xb9\x01\x99R\u058b\x1b\x0fm\x8c\xf0h<\x008{\xb5\x89\x12\x04\x01V=}\x91\x00\x00\u07d4\xeb\xbe\xeb%\x91\x84\xa6\xe0\x1c\xcc\xfc\"\a\xbb\u0603xZ\xc9\n\x89!\x9b\xc1\xb0G\x83\xd3\x00\x00\u07d4\xeb\xd3V\x15j81#4=H\x84;\xff\xeda\x03\xe8f\xb3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xeb\xd3{%ec\xe3\fo\x92\x89\xa8\xe2p/\bR\x88\b3\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xeb\xe4l\xc3\xc3L2\xf5\xad\xd6\xc3\x19[\xb4\x86\xc4q>\xb9\x18\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xeb\xff\x84\xbb\xefB0q\xe6\x04\xc3a\xbb\xa6w\xf5Y=\xefN\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xec\t'\xba\xc7\xdc6f\x9c(5J\xb1\xbe\x83\xd7\xee\xc3\t4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\x0e\x18\xa0\x1d\xc4\xdc]\xaa\xe5g\xc3\xfaL\u007f\x8f\x9bY\x02\x05\x89\x11\x1f\xfe@JA\xe6\x00\x00\xe0\x94\xec\x116,\xec\x81\t\x85\xd0\xeb\xbd{sE\x14D\x98[6\x9f\x8a\x06ZNIWpW1\x80\x00\u07d4\xec,\xb8\xb97\x8d\xff1\xae\xc3\xc2.\x0em\xad\xff1J\xb5\u0749lk\x93[\x8b\xbd@\x00\x00\u07d4\xec0\xad\u0749[\x82\xee1\x9eT\xfb\x04\xcb+\xb09q\xf3k\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec;\x8bX\xa1'\x03\xe5\x81\xce_\xfd~!\xc5}\x1e\\f?\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xecHg\xd2\x17Z\xb5\xb9F\x93aYUFUF\x84\u0364`\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xecM\b\xaa.GIm\u0287\"]\xe3?+@\xa8\xa5\xb3o\x89\b\x90\xb0\xc2\xe1O\xb8\x00\x00\u07d4\xecX\xbc\r\f \xd8\xf4\x94efAS\xc5\xc1\x96\xfeY\u6f89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xec[\x19\x8a\x00\u03f5Z\x97\xb5\xd56D\xcf\xfa\x8a\x04\u04abE\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec]\xf2'\xbf\xa8]z\xd7kBn\x1c\xee\x96;\xc7\xf5\x19\u074965\u026d\xc5\u07a0\x00\x00\xe0\x94\xec_\xea\xfe!\f\x12\xbf\u0265\xd0Y%\xa1#\xf1\xe7?\xbe\xf8\x8a`\x8f\xcf=\x88t\x8d\x00\x00\x00\u07d4\xeci\x04\xba\xe1\xf6\x97\x90Y\x17\t\xb0`\x97\x83s?%s\xe3\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\xe0\x94\xecs\x11L^@o\u06fe\t\xb4\xfab\x1b\xd7\x0e\xd5N\xa1\xef\x8a\x050%\xcd!o\xceP\x00\x00\u07d4\xecs\x83=\xe4\xb8\x10\xbb\x02x\x10\xfc\x8fi\xf5D\xe8<\x12\u044965\u026d\xc5\u07a0\x00\x00\u07d4\xecu\xb4\xa4u\x13\x12\v\xa5\xf8`9\x81O\x19\x98\xe3\x81z\u00c9\t\xb0\xbc\xe2\xe8\xfd\xba\x00\x00\u07d4\xecv\xf1.W\xa6U\x04\x03?,\v\xceo\xc0;\xd7\xfa\n\u0109\xc2\x12z\xf8X\xdap\x00\x00\u0794\xec\x80\x14\xef\xc7\xcb\xe5\xb0\xceP\xf3V,\xf4\xe6\u007f\x85\x93\xcd2\x88\xf0\x15\xf2W6B\x00\x00\u07d4\xec\x82\xf5\r\x06G_hM\xf1\xb3\x92\xe0\r\xa3A\xaa\x14TD\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xec\x83\xe7\x98\u00d6\xb7\xa5^*\"$\xab\u0343K'\xeaE\x9c\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xec\x89\xf2\xb6x\xa1\xa1[\x914\xec^\xb7\fjb\a\x1f\xba\xf9\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xec\x8c\x1d{j\xac\xcdB\x9d\xb3\xa9\x1e\xe4\xc9\xeb\x1c\xa4\xf6\xf7<\x89\xe6d\x99\"\x88\xf2(\x00\x00\xe0\x94\xec\x98Q\xbd\x91rpa\x02g\xd6\x05\x18\xb5M<\xa2\xb3[\x17\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xec\x99\xe9]\xec\xe4o\xff\xfb\x17^\xb6@\x0f\xbe\xbb\b\ue6d5\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xec\xa5\xf5\x87\x92\xb8\xc6-*\xf5Vq~\xe3\xee0(\xbeM\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\xabZ\xba[\x82\x8d\xe1pS\x81\xf3\x8b\xc7D\xb3+\xa1\xb47\x892\xf5\x1e\u06ea\xa30\x00\x00\u07d4\xec\xaf3P\xb7\xce\x14M\x06\x8b\x18`\x10\x85,\x84\xdd\f\xe0\xf0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xec\xb9LV\x8b\xfeY\xad\xe6Pd_O&0lsl\xac\xe4\x89\x0e~\xeb\xa3A\vt\x00\x00\xe0\x94\xec\xbeB^g\r9\tN \xfbVC\xa9\xd8\x18\xee\xd26\u078a\x01\x0f\f\xf0d\xddY \x00\x00\xe0\x94\xec\xbe^\x1c\x9a\u04b1\xdc\xcf\n0_\xc9R/Fi\xdd:\xe7\x8a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xec\xcfz\x04W\xb5f\xb3F\xcag:\x18\x0fDA0!j\u00c9\x05k\xc7^-c\x10\x00\x00\u07d4\xec\u0466(\x025\x1aAV\x8d#\x030\x04\xac\xc6\xc0\x05\xa5\u04c9\x02\xb5\xe3\xaf\x16\xb1\x88\x00\x00\u07d4\xec\xd2v\xafd\u01dd\x1b\u0669+\x86\xb5\u835a\x95\xeb\x88\xf8\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xec\u0506\xfc\x19g\x91\xb9,\xf6\x12\xd3HaO\x91VH\x8b~\x8a\x02\x8a\x85t%Fo\x80\x00\x00\u07d4\xec\xda\xf92)\xb4^\xe6r\xf6]\xb5\x06\xfb^\xca\x00\xf7\xfc\xe6\x89W\x01\xf9m\xcc@\xee\x80\x00\u07d4\xec\xe1\x11g\vV<\u037e\xbc\xa5#\x84)\x0e\xcdh\xfe\\\x92\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xec\xe1\x15&\x82\xb7Y\x8f\xe2\xd1\xe2\x1e\xc1U3\x88T5\xac\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xec\xe1)\bw\xb5\x83\xe3a\xa2\xd4\x1b\x00\x93F\xe6'N%8\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xec\xf0]\a\xea\x02n~\xbfIA\x00#5\xba\xf2\xfe\xd0\xf0\x02\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xec\xf2L\xdd|\"\x92\x8cD\x1eiM\xe4\xaa1\xb0\xfa\xb5\x97x\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xec\xfd\x00M\x02\xf3l\xd4\u0634\xa8\xc1\xa9S;j\xf8\\\xd7\x16\x8a\x01\x0fA\xac\xb4\xbb;\x9c\x00\x00\xe0\x94\xed\x02\x06\xcb#1Q(\xf8\xca\xff&\xf6\xa3\v\x98Tg\xd0\"\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xed\x10e\xdb\u03dds\xc0O\xfcy\b\x87\r\x88\x14h\xc1\xe12\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xed\x12vQ;o\u0186(\xa7A\x85\xc2\xe2\f\xbb\xcax\x17\xbf\x89\nZ\xa8P\t\xe3\x9c\x00\x00\xe0\x94\xed\x12\xa1\xba\x1f\xb8\xad\xfc\xb2\r\xfa\x19X.RZ\xa3\xb7E$\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xed\x16\xce9\xfe\xef;\xd7\xf5\xd1b\x04^\x0fg\xc0\xf0\x00F\xbb\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xed\x1a\\C\xc5t\xd4\xe94)\x9b$\xf1G,\u071f\xd6\xf0\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xed\x1b$\xb6\x91-Q\xb34\xac\r\xe6\xe7q\xc7\xc0EF\x95\xea\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xed\x1f\x1e\x11Z\r`\xce\x02\xfb%\xdf\x01M(\x9e:\f\xbe}\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xed10\\1\x9f\x92s\u04d3m\x8f[/q\u9c72)c\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xed2z\x14\xd5\u03ed\u0641\x03\xfc\t\x99q\x8d~\xd7\x05(\xea\x89N\x10\x03\xb2\x8d\x92\x80\x00\x00\u07d4\xed<\xbc7\x82\u03bdg\x98\x9b0\\A3\xb2\xcd\xe3\"\x11\xeb\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xed@\x14S\x8c\xeefJ/\xbc\xb6\xdcf\x9fz\xb1m\v\xa5|\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xedA\u188f\\\xaa\x848\x80\xefN\x8b\b\xbdl3\x14\x1e\u07c9*\xd5\xdd\xfaz\x8d\x83\x00\x00\xe0\x94\xedK\xe0J\x05-z\u0333\xdc\u03901\x9d\xba@ \xab,h\x8a\a\xf3zp\xea\xf3b\x17\x80\x00\xe0\x94\xedR\xa2\xcc\bi\u071e\x9f\x84+\u0415|G\xa8\xe9\xb0\xc9\xff\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xed[LA\xe7b\xd9B@Cs\xca\xf2\x1e\xd4a]%\xe6\xc1\x89m-O=\x95%\xb4\x00\x00\u07d4\xed`\u012bnT\x02\x061~5\x94zc\xa9\xcak\x03\xe2\u02c9\x03\x1a\u066d\vF\u007f\x80\x00\u07d4\xedd\x1e\x066\x8f\xb0\xef\xaa\x17\x03\xe0\x1f\xe4\x8fJhS\t\xeb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xedfC\xc0\xe8\x88K-2\x11\x857\x85\xa0\x8b\xf8\xf3>\u049f\x89Hz\x9a0E9D\x00\x00\xe0\x94\xedp\xa3|\xdd\x1c\xbd\xa9tm\x93\x96X\xae*a\x81(\x85x\x8a\x02\bj\xc3Q\x05&\x00\x00\x00\u07d4\xedsFvn\x1agm\r\x06\xec\x82\x18g\xa2v\xa0\x83\xbf1\x89\u064a\t1\xcc-I\x00\x00\u07d4\xed\x86&\x16\xfc\xbf\xb3\xbe\xcbt\x06\xf7<\\\xbf\xf0\f\x94\aU\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xed\x9e\x03\f\xa7\\\xb1\u049e\xa0\x1d\rL\xdf\xdc\xcd8D\xb6\xe4\x89\x01\xac\xc1\x16\u03ef\xb1\x80\x00\xe0\x94\ud7bc\u02e4/\x98\x15\xe7\x823&m\xd6\xe85\xb6\xaf\xc3\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\ud7f1\xf5\xaf/\xbf\u007f\xfcP)\xce\xe4+p\xff\\'[\xf5\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xed\xa4\xb2\xfaY\u0584\xb2z\x81\r\xf8\x97\x8as\xdf0\x8ac\u0089\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xed\xb4s59y\xa2\x06\x87\x9d\xe1D\xc1\n:\xcf\x12\xa7'OV9a\xf57R\x9d\x89\xc7\u0789lk\x93[\x8b\xbd@\x00\x00\u07d4\xeer\x88\xd9\x10\x86\xd9\xe2\xeb\x91\x00\x14\u066b\x90\xa0-x\u00a0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xee|=\xed|(\xf4Y\xc9/\xe1;M\x95\xba\xfb\xab\x026}\x89%\xf2s\x93=\xb5p\x00\x00\xe0\x94\xee\x86} \x91k\xd2\xe9\xc9\xec\xe0\x8a\xa0C\x85\xdbf|\x91.\x8a\n\x96\x81c\xf0\xa5{@\x00\x00\u07d4\ue25b\x02\xcb\xcb99\xcda\xde\x13B\xd5\x04\x82\xab\xb6\x852\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xee\x90m}_\x17H%\x81t\xbeL\xbc8\x93\x03\x02\xab{B\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\ue5ea\x8a\u019e\xdfz\x98}mp\x97\x9f\x8e\xc1\xfb\xcaz\x94\x89\x14b\fW\xdd\xda\xe0\x00\x00\u07d4\xee\xa1\xe9y\x88\xdeu\xd8!\xcd(\xadh\"\xb2,\u0398\x8b1\x89\x1c0s\x1c\xec\x03 \x00\x00\xe0\x94\xee\u048c?\x06\x8e\tJ0K\x85<\x95\nh\t\xeb\xcb\x03\xe0\x8a\x03\xa9\u057a\xa4\xab\xf1\xd0\x00\x00\u07d4\xee\u04c4\xef-A\xd9\xd2\x03\x97NW\xc1#(\xeav\x0e\b\xea\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xee\xdflB\x80\xe6\xeb\x05\xb94\xac\xe4(\xe1\x1dB1\xb5\x90[\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xee\xe7a\x84~3\xfda\u0653\x87\xee\x14b\x86\x94\u047f\xd5%\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xee\xe9\xd0Rn\xda\x01\xe41\x16\xa3\x952-\u0689pW\x8f9\x8a\x02\x1e\x19\x99\xbb\xd5\u04be\x00\x00\u07d4\xee\xf1\xbb\xb1\xe5\xa8?\u0782H\xf8\x8e\xe3\x01\x8a\xfa-\x132\xeb\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xee\xfb\xa1-\xfc\x99gB\xdby\x04d\xca}';\xe6\xe8\x1b>\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xee\xfd\x05\xb0\xe3\xc4\x17\xd5[3C\x06\x04\x86\xcd\xd5\xe9*\xa7\xa6\x89M\x85<\x8f\x89\b\x98\x00\x00\u07d4\xef\r\xc7\xddzS\xd6\x12r\x8b\xcb\u04b2|\x19\xddM}fo\x89&A\x1c[5\xf0Z\x00\x00\u07d4\xef\x11RR\xb1\xb8E\u0345\u007f\x00-c\x0f\x1bo\xa3zNP\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xef\x1c\x04w\xf1\x18M`\xac\u02b3t\xd3tUz\n>\x10\xf3\x89\b=lz\xabc`\x00\x00\u07d4\xef,4\xbbH}7b\xc3\u0327\x82\xcc\xddz\x8f\xbb\n\x991\x89\t\xc2\x00vQ\xb2P\x00\x00\u07d4\xef5\xf6\u0531\a^j\xa19\x15\x1c\x97K/FX\xf7\x058\x89<;\xc3?\x94\xe5\r\x80\x00\u07d4\xef9\u0291s\xdf\x15S\x1ds\xe6\xb7*hKQ\xba\x0f+\xb4\x89V\xa0\xb4un\xe28\x00\x00\u07d4\xefF<&y\xfb'\x91d\xe2\f=&\x915\x87s\xa0\xad\x95\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xefG\xcf\a>6\xf2q\xd5\"\xd7\xfaNq \xadP\a\xa0\xbc\x89\x87\x86x2n\xac\x90\x00\x00\u07d4\xefa\x15[\xa0\t\xdc\u07be\xf1\v(\xd9\xda=\x1b\xc6\xc9\xce\u0509\x034-`\xdf\xf1\x96\x00\x00\u0794\xefix\x1f2\xff\xce34o,\x9a\xe3\xf0\x84\x93\xf3\xe8/\x89\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xefv\xa4\u034f\xeb\xcb\u0278\x18\xf1x(\xf8\xd94s\xf3\xf3\u02c9\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\uf4c1\x8fhM\xb0\xc3g^\xc8\x132\xb3\x18>\xcc(\xa4\x95\x89T\x06\x923\xbf\u007fx\x00\x00\xe0\x94\xef\x9fY\xae\xdaA\x8c\x14\x94h-\x94\x1a\xabI$\xb5\xf4\x92\x9a\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\uf9b1\xf0\xdb`57\x82h\x91\xb8\xb4\xbc\x169\x84\xbb@\u03495e\x9e\xf9?\x0f\xc4\x00\x00\u07d4\xef\xbdR\xf9}\xa5\xfd:g:F\xcb\xf30D{~\x8a\xad\\\x89\x05l<\x9b\x80\xa0\xa6\x80\x00\xe0\x94\xef\xc8\xcf\x19c\u0269Rg\xb2(\xc0\x86#\x98\x89\xf4\xdf\xd4g\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xef\u02ae\x9f\xf6M,\xd9[RI\xdc\xff\xe7\xfa\xa0\xa0\xc0\xe4M\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xef\xcc\xe0k\xd6\b\x9d\x0eE\x8e\xf5a\xf5\xa6\x89H\n\xfep\x00\x89 \x86\xac5\x10R`\x00\x00\u07d4\xef\xe0g]\xa9\x8a]\xdap\u0356\x19k\x87\xf4\xe7&\xb43H\x89?\x19\xbe\xb8\xdd\x1a\xb0\x00\x00\u07d4\xef\xe8\xff\x87\xfc&\x0e\agc\x8d\xd5\xd0/\xc4g.\x0e\xc0m\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xef\xeb\x19\x97\xaa\xd2w\xcc3C\x0ea\x11\xed\tCY@H\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xef\xee\xa0\x10uo\x81\xdaK\xa2[r\x17\x87\xf0X\x17\v\uff49\x01\u009c\x9c\xf7p\xef\x00\x00\u07d4\xef\xf5\x1dr\xad\xfa\xe1C\xed\xf3\xa4+\x1a\xecU\xa2\xcc\xdd\v\x90\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xef\xf8kQ#\xbc\xdc\x17\xedL\xe8\xe0[~\x12\xe5\x13\x93\xa1\xf7\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xef\xfc\x15\u41f1\xbe\xda\n\x8d\x13%\xbd\xb4\x17\"@\xdcT\n\x89\x03\x8599\xee\xe1\xde\x00\x00\xe0\x94\xf0\x11\x95\xd6W\xef<\x94.l\xb89I\xe5\xa2\v\\\xfa\x8b\x1e\x8a\x05ts\xd0]\xab\xae\x80\x00\x00\u07d4\xf0'\x96)Q\x01gB\x88\xc1\xd94g\x05=\x04\"\x19\xb7\x94\x89(\x1d\x90\x1fO\xdd\x10\x00\x00\u07d4\xf09h={=\"[\xc7\xd8\u07ed\xefc\x164A\xbeA\xe2\x89\x01\xdd\x1eK\xd8\xd1\xee\x00\x00\u07d4\xf0Jj7\x97\b\xb9B\x8dr*\xa2\xb0kw\xe8\x895\u03c9\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xf0M,\x91\xef\xb6\xe9\xc4_\xfb\xe7KCL\x8c_+\x02\x8f\x1f\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf0W\xaaf\xcav~\xde\x12J\x1c[\x9c\xc5\xfc\x94\xef\v\x017\x89p\xa2K\u02b6\xf4]\x00\x00\u07d4\xf0[\xa8\u05f6\x859\xd930\v\xc9(\x9c=\x94t\xd0A\x9e\x89\x06\xda'\x02M\xd9`\x00\x00\u07d4\xf0\\\xee\xabeA\x05dp\x99Qw<\x84E\xad\x9fN\u01d7\x89\x10C\x16'\xa0\x93;\x00\x00\xe0\x94\xf0_\xcdL\rs\xaa\x16~US\xc8\xc0\xd6\xd4\xf2\xfa\xa3\x97W\x8a\x02\xd2\xd6l1p\xb2\x98\x00\x00\u07d4\xf0g\xe1\xf1\u0583UjL\xc4\xfd\f\x03\x13#\x9f2\xc4\xcf\u060965\u026d\xc5\u07a0\x00\x00\u07d4\xf0g\xfb\x10\u07f2\x93\u962b\xe5d\xc0U\xe34\x8f\x9f\xbf\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0h\xdf\xe9]\x15\xcd:\u007f\x98\xff\xa6\x88\xb44hB\xbe&\x90\x89D\n\xd8\x19\xe0\x97L\x00\x00\xe0\x94\xf0j\x85J<]\xc3m\x1cI\xf4\xc8}m\xb33\xb5~J\u074a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf0y\xe1\xb1&_P\xe8\u0229\x8e\xc0\u01c1^\xb3\xae\xac\x9e\xb4\x89\x01\x16\xdc:\x89\x94\xb3\x00\x00\xe0\x94\xf0{\xd0\xe5\xc2\xcei\xc7\u0127$\xbd&\xbb\xfa\x9d*\x17\xca\x03\x8a\x01@a\xb9\xd7z^\x98\x00\x00\xe0\x94\xf0\x83*k\xb2U\x03\xee\xcaC[\xe3\x1b\v\xf9\x05\xca\x1f\xcfW\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xf0\x9b>\x87\xf9\x13\xdd\xfdW\xae\x80I\xc71\u06e9\xb66\xdf\u00c9 \xf5\xb1\uab4d\x80\x00\x00\u07d4\xf0\xb14\v\x99oo\v\xf0\xd9V\x1c\x84\x9c\xaf\u007fD0\xbe\xfa\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf0\xb1\xf9\xe2x2\xc6\xdei\x14\xd7\n\xfc#\x8ct\x99\x95\xac\xe4\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xf0\xb4i\xea\xe8\x9d@\f\xe7\xd5\xd6j\x96\x95\x03p6\xb8\x89\x03\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xf0\xb9\u0583\u03a1+\xa6\x00\xba\xac\xe2\x19\xb0\xb3\xc9~\x8c\x00\xe4\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf0\xbe\x0f\xafMy#\xfcDF\"\u0458\f\xf2\u0650\xaa\xb3\a\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0\xc0\x81\xdaR\xa9\xae6d*\xdf^\b _\x05\xc5Ah\xa6\x89\x06\x04o7\xe5\x94\\\x00\x00\u07d4\xf0\xc7\r\rm\xabvc\xaa\x9e\xd9\xce\xeaV~\xe2\u01b0'e\x89qC\x8a\u0167\x91\xa0\x80\x00\u07d4\xf0\xcb\xef\x84\xe1ic\x00\x98\xd4\xe3\x01\xb2\x02\b\xef\x05\x84j\u0249\x0e\v\x83EPkN\x00\x00\u07d4\xf0\xd2\x16c\u0630\x17n\x05\xfd\xe1\xb9\x0e\xf3\x1f\x850\xfd\xa9_\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xf0\xd5\xc3\x1c\xcbl\xbe0\xc7\xc9\xea\x19\xf2h\xd1Y\x85\x1f\x8c\x9c\x8a\x03\x89O\x0eo\x9b\x9fp\x00\x00\u07d4\xf0\xd6L\xf9\xdf\tt\x113\xd1pH_\xd2K\x00P\x11\xd5 \x89\x1b\b\x93A\xe1O\xcc\x00\x00\u07d4\xf0\xd8X\x10^\x1bd\x81\x01\xac?\x85\xa0\xf8\"+\xf4\xf8\x1dj\x89 \x86\xac5\x10R`\x00\x00\u07d4\xf0\xdcC\xf2\x05a\x91'P{+\x1c\x1c\xfd\xf3-(1\t \x89\x10^\xb7\x9b\x94\x17\b\x80\x00\u07d4\xf0\xe1\u07e4*\u07ac/\x17\xf6\xfd\xf5\x84\xc9Hb\xfdV3\x93\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf0\xe2d\x9c~j?,]\xfe3\xbb\xfb\xd9'\xca<5\nX\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf0\xe7\xfb\x9eB\nS@\xd56\xf4\x04\b4O\xea\xef\xc0j\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf1\x04b\xe5\x8f\xcc\a\U000d5121\x87c\x94Q\x16~\x85\x92\x01\x89\t4\xdd]3\xbc\x97\x00\x00\xe0\x94\xf1\x06a\xff\x94\x14\x0f >zH%rCy8\xbe\xc9\xc3\xf7\x8a\x04<3\xc1\x93ud\x80\x00\x00\u0794\xf1\x14\xff\r\x0f$\xef\xf8\x96\xed\xdeTq\u07a4\x84\x82J\x99\xb3\x88\xbe -j\x0e\xda\x00\x00\u07d4\xf1\x16\xb0\xb4h\x0fS\xabr\xc9h\xba\x80.\x10\xaa\x1b\xe1\x1d\u0209\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xf1\x1c\xf5\xd3cto\xeehd\xd3\xca3m\xd8\x06y\xbb\x87\xae\x8a\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xf1\x1e\x01\u01e9\xd1$\x99\x00_M\xaew\x16\tZ4\x17bw\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf1;\b0\x93\xbaVN-\xc61V\x8c\xf7T\r\x9a\x0e\xc7\x19\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xf1O\x0e\xb8m\xb0\xebhu?\x16\x91\x8e]K\x80t7\xbd>\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf1Qx\xff\xc4:\xa8\a\x0e\xce2~\x93\x0f\x80\x9a\xb1\xa5O\x9d\x89\n\xb6@9\x12\x010\x00\x00\u07d4\xf1V\xdc\v*\x98\x1e[U\xd3\xf2\xf0;\x814\xe31\u06ed\xb7\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf1]\x9dZ!\xb1\x92\x9ey\x03q\xa1\u007f\x16\xd9_\fie\\\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1^\x18,O\xbb\xady\xbd\x934\"B\xd4\xdc\xcf+\xe5\x89%\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf1bM\x98\ve3o\xea\u0166\xd5A%\x00\\\xfc\xf2\xaa\u02c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1g\xf5\x86\x8d\xcfB3\xa7\x83\x06\th,\xaf-\xf4\xb1\xb8\a\x89\x81\xe5B\xe1\xa78?\x00\x00\u07d4\xf1m\xe1\x89\x1d\x81\x96F\x13\x95\xf9\xb16&[;\x95F\xf6\xef\x89\x01\xb2\x8e\x1f\x98\xbb\u0380\x00\u07d4\xf1z\x92\xe06\x1d\xba\xce\xcd\xc5\xde\r\x18\x94\x95Z\xf6\xa9\xb6\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1z\xdbt\x0fE\u02fd\xe3\tN~\x13qo\x81\x03\xf5c\xbd\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1\x8b\x14\xcb\xf6iC6\xd0\xfe\x12\xac\x1f%\xdf-\xa0\xc0]\xbb\x89\xd8\xd4`,&\xbfl\x00\x00\u07d4\xf1\x9b98\x9dG\xb1\x1b\x8a,?\x1d\xa9\x12M\xec\xff\xbe\xfa\xf7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf1\x9f\x195\b9>M*\x12{ \xb2\x03\x1f9\xc8%\x81\u0189\xbd\xbdz\x83\xbd/l\x00\x00\u07d4\xf1\xa1\xf3 @yd\xfd<\x8f.,\u0224X\r\xa9O\x01\xea\x89ll!wU|D\x00\x00\u07d4\xf1\xb4\xec\xc65%\xf7C,=\x83O\xfe+\x97\x0f\xbe\xb8r\x12\x89\xa2\xa2@h\xfa\u0340\x00\x00\u07d4\U000753ef\xfa\x87\x94\xf5\n\xf8\xe8\x83\t\u01e6&TU\xd5\x1a\x8963\x03\"\xd5#\x8c\x00\x00\u07d4\xf1\xc8\u0129A\xb4b\x8c\rl0\xfd\xa5dR\u065c~\x1bd\x89N\x8c\xea\x1e\xdeu\x04\x00\x00\u07d4\xf1\xda@so\x99\xd5\xdf;\x06\x8a]t_\xaf\xc6F?\u0271\x89\x06\x96\xca#\x05\x8d\xa1\x00\x00\u07d4\xf1\u070a\xc8\x10B\xc6z\x9c\\c2!\xa8\xf76>e\x87\f\x9f(t$\u04a9`\x89J\xcfX\xe0rW\x10\x00\x00\u07d4\xf2B\u0684]B\u053fw\x9a\x00\xf2\x95\xb4\aP\xfeI\xea\x13\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf2RY\xa5\xc99\xcd%\x96l\x9bc\x03\xd3s\x1cS\u077cL\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf2^Lp\xbcFV2\u021eV%\xa82\xa7r/k\xff\xab\x89\xf3K\x82\xfd\x8e\x91 \x00\x00\u07d4\xf2k\xce\xdc\xe3\xfe\xad\u03a3\xbc>\x96\xeb\x10@\xdf\xd8\xff\u1809*\x03I\x19\u07ff\xbc\x00\x00\u07d4\xf2py%v\xf0]QD\x93\xff\xd1\xf5\xe8K\xecK-\xf8\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf2s,\xf2\xc1;\x8b\xb8\xe7I*\x98\x8f_\x89\xe3\x82s\xdd\u0209 \x86\xac5\x10R`\x00\x00\xe0\x94\xf2t.hY\xc5i\xd5\xf2\x10\x83Q\xe0\xbfM\xca5*H\xa8\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf2\x81:d\xc5&]\x02\x025\u02dc1\x9bl\x96\xf9\x06\xc4\x1e\x89\x12\xf99\u025e\u06b8\x00\x00\u07d4\xf2\x87\xffR\xf4a\x11z\xdb>\x1d\xaaq\x93-\x14\x93\xc6_.\x89\xc5S%\xcat\x15\xe0\x00\x00\u07d4\xf2\xab\x11au\x02D\xd0\xec\xd0H\xee\r>Q\xab\xb1C\xa2\xfd\x89B\xfe+\x90ss\xbc\x00\x00\u07d4\xf2\xb4\xab,\x94'\xa9\x01^\xf6\xee\xff\xf5\xed\xb6\x019\xb7\x19\u0449&\u06d9*;\x18\x00\x00\x00\u07d4\xf2\xc0>*8\x99\x8c!d\x87`\xf1\xe5\xae~\xa3\a}\x85\"\x89\x8f?q\x93\xab\a\x9c\x00\x00\u0794\xf2\u0090N\x9f\xa6d\xa1\x1e\xe2VV\xd8\xfd,\xc0\u0665\"\xa0\x88\xb9\x8b\xc8)\xa6\xf9\x00\x00\u07d4\xf2\xc3b\xb0\xef\x99\x1b\xc8/\xb3nf\xffu\x93*\xe8\u0742%\x89\x04\x02\xf4\xcf\xeeb\xe8\x00\x00\u07d4\xf2\xd0\xe9\x86\xd8\x14\xea\x13\xc8\xf4f\xa0S\x8cS\u0712&Q\xf0\x89J\xcfX\xe0rW\x10\x00\x00\xe0\x94\xf2\u04775w$\xecL\x03\x18[\x87\x9bc\xf5~&X\x91S\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xf2\xd5v<\xe0s\x12~,\xed\xdeo\xab\xa7\x86\xc7<\xa9AA\x8a\x01\xacB\x86\x10\x01\x91\xf0\x00\x00\xe0\x94\xf2\u055c\x89#u\x90s\xd6\xf4\x15\xaa\xf8\xeb\x06_\xf2\U000f614a\x01\xab,\xf7\xc9\xf8~ \x00\x00\u07d4\xf2\xe9\x9f\\\xbb\x83kz\xd3bGW\x1a0,\xbeKH\x1ci\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf2\xed>w%J\u02c3#\x1d\xc0\x86\x0e\x1a\x11$+\xa6'\u06c9kV\x05\x15\x82\xa9p\x00\x00\xe0\x94\xf2\xed\xde7\xf9\xa8\u00dd\u07a2My\xf4\x01WW\xd0k\xf7\x86\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xf2\xef\xe9e`\xc9\xd9{r\xbd6DxC\x88\\\x1d\x90\xc21\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf2\xfb\xb6\u0607\xf8\xb8\xcc:\x86\x9a\xba\x84\u007f=\x1fd\xfcc\x97\xaae\xfbS\xa8\xf0z\x0f\x89:\xae0\xe8\xbc\xee\x89|\xf28\x1fa\x9f\x15\x00\x00\u07d4\xf3@\x83\xec\xea8P\x17\xaa@\xbd\xd3^\xf7\xef\xfbL\xe7v-\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf3F\xd7\u0792t\x1c\b\xfcX\xa6M\xb5[\x06-\xde\x01-\x14\x89\x0f\xffk\x1fv\x1em\x00\x00\xe0\x94\xf3U\xd3\xec\f\xfb\x90}\x8d\xbb\x1b\xf3FNE\x81(\x19\v\xac\x8a\x01\v\x04n\u007f\r\x80\x10\x00\x00\u07d4\xf3m\xf0/\xbd\x89`sG\xaf\xce)i\xb9\xc4#jX\xa5\x06\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3s\xe9\u06ac\f\x86u\xf5;yz\x16\x0fo\xc04\xaek#\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf3{BeG\xa1d-\x8032H\x14\xf0\xed\xe3\x11O\xc2\x12\x89\x15\xbeat\xe1\x91.\x00\x00\u07d4\xf3{\xf7\x8cXu\x15G\x11\xcbd\r7\xeam(\xcf\xcb\x12Y\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xf3\x82\xdfX1U\xd8T\x8f?\x93D\f\xd5\xf6\x8c\xb7\x9d`&\x8a8u}\x02\u007f\xc1\xfd\\\x00\x00\xe0\x94\xf3\x82\xe4\xc2\x04\x10\xb9Q\b\x9e\x19\xba\x96\xa2\xfe\xe3\xd9\x1c\xce~\x8a\x01\x11\xfaV\xee\u00a88\x00\x00\xe0\x94\xf3\x8al\xa8\x01hS~\x97M\x14\xe1\xc3\xd19\x90\xa4L,\x1b\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\u07d4\xf3\x9a\x9dz\xa3X\x1d\xf0~\xe4'\x9a\xe6\xc3\x12\xef!\x036X\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf3\xb6h\xb3\xf1M\x92\x0e\xbc7\x90\x92\u06d8\x03\x1bg\xb2\x19\xb3\x89\n\xd6\xee\xdd\x17\xcf;\x80\x00\u07d4\U000fe679\x10<\xe7U\n\xa7O\xf1\xdb\x18\xe0\x9d\xfe2\xe0\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xc1\xab\u049d\xc5{A\xdc\x19-\x0e8M\x02\x1d\xf0\xb4\xf6\u0509\x97\xae\f\u07cf\x86\xf8\x00\x00\u07d4\xf3\xc4qm\x1e\xe5'\x9a\x86\xd0\x16:\x14a\x81\x81\xe1a6\u01c965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf3\u030b\xcbU\x94e\xf8\x1b\xfeX;\u05eb\n#\x06E;\x9e\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xf3\u0588\xf0k\xbd\xbfP\xf9\x93,AE\xcb\xe4\x8e\xcd\xf6\x89\x04\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf3\xdb\xcf\x13Z\u02dd\xee\x1aH\x9cY<\x02O\x03\u00bb\xae\u0389lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xde_&\xefj\xde\xd6\xf0m;\x91\x13F\xeep@\x1d\xa4\xa0\x89\x13:\xb3}\x9f\x9d\x03\x00\x00\u07d4\xf3\xdfc\xa9q\x99\x93308;>\xd7W\v\x96\u0101#4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf3\xe7OG\f}:?\x003x\x0fv\xa8\x9f>\xf6\x91\xe6\u02c9\xa3\xcf\xe61\xd1Cd\x00\x00\u07d4\xf3\xeb\x19H\xb9Q\xe2-\xf1ax)\xbf;\x8d\x86\x80\xeckh\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf3\xf1\xfa9\x18\xca4\xe2\xcf~\x84g\v\x1fM\x8e\xca\x16\r\xb3\x89$\xdc\xe5M4\xa1\xa0\x00\x00\u07d4\xf3\xf2O\u009e @?\xc0\xe8\xf5\xeb\xbbU4&\xf7\x82p\xa2\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf3\xfar5R\xa5\xd0Q.+b\xf4\x8d\xca{+\x81\x050[\x89\amA\xc6$\x94\x84\x00\x00\u07d4\xf3\xfeQ\xfd\xe3D\x13\xc73\x18\xb9\xc8T7\xfe~\x82\x0fV\x1a\x896b2\\\u044f\xe0\x00\x00\u07d4\xf4\x00\xf9=_\\~?\xc3\x03\x12\x9a\xc8\xfb\f/xd\a\xfa\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf4\v\x13O\xea\"\u01b2\x9c\x84W\xf4\x9f\x00\x0f\x9c\xdax\x9a\u06c9 \x86\xac5\x10R`\x00\x00\u07d4\xf4\x15W\xdf\u07f1\xa1\xbd\xce\xfe\xfe.\xba\x1e!\xfe\nJ\x99B\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf4\x17z\r\x85\u050b\x0e&B\x11\xce*\xa2\xef\xd3\xf1\xb4\u007f\b\x89\xc2\xcc\xca&\xb7\xe8\x0e\x80\x00\u07d4\xf4/\x90R1\xc7p\xf0\xa4\x06\xf2\xb7h\x87\u007f\xb4\x9e\xee\x0f!\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xf42\xb9\u06ef\x11\xbd\xbds\xb6Q\x9f\xc0\xa9\x04\x19\x87q\xaa\u0189\b=lz\xabc`\x00\x00\u07d4\xf4=\xa3\xa4\xe3\xf5\xfa\xb1\x04\u029b\xc1\xa0\xf7\xf3\xbbJV\xf3Q\x89lj\xccg\u05f1\xd4\x00\x00\xe0\x94\xf4G\x10\x8b\x98\xdfd\xb5~\x87\x103\x88\\\x1a\xd7\x1d\xb1\xa3\xf9\x8a\x01v\xf4\x9e\xad4\x83P\x80\x00\u07d4\xf4O\x85Q\xac\xe93r\a\x12\xc5\u0111\u0376\xf2\xf9Qsl\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u0794\xf4V\x05Z\x11\xab\x91\xfff\x8e.\xc9\"\x96\x1f*#\xe3\xdb%\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xf4V\xa7[\xb9\x96U\xa7A,\xe9}\xa0\x81\x81m\xfd\xb2\xb1\xf2\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf4[\x1d\xcb.A\xdc'\xff\xa0$\u06ad\xf6\x19\xc1\x11u\xc0\x87\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xf4c\xa9\f\xb3\xf1>\x1f\x06CB66\xbe\xab\x84\xc1#\xb0m\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf4h\x90n~\xdffJ\xb0\u063e=\x83\xebz\xb3\xf7\xff\xdcx\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xf4i\x80\u3929\u049ajn\x90`E7\xa3\x11K\xcb(\x97\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf4kk\x9c|\xb5R\x82\x9c\x1d=\xfd\x8f\xfb\x11\xaa\xba\xe7\x82\xf6\x89\x01#n\xfc\xbc\xbb4\x00\x00\u07d4\xf4v\xe1&\u007f\x86$|\xc9\b\x81o.z\xd58\x8c\x95-\xb0\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf4v\xf2\xcbr\b\xa3.\x05\x1f\xd9N\xa8f)\x92c\x82\x87\xa2\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xf4{\xb14\xda0\xa8\x12\xd0\x03\xaf\x8d\u0338\x88\xf4K\xbfW$\x8a\x01\x19Y\xb7\xfe3\x95X\x00\x00\u07d4\xf4\x83\xf6\a\xa2\x1f\xcc(\x10\n\x01\x8cV\x8f\xfb\xe1@8\x04\x10\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf4\x8e\x1f\x13\xf6\xafM\x84\xb3q\xd7\xdeK'=\x03\xa2c'\x8e\x89 \x86\xac5\x10R`\x00\x00\xe0\x94\xf4\x9cG\xb3\xef\xd8knj[\xc9A\x8d\x1f\x9f\xec\x81Ki\xef\x8a\x04<3\xc1\x93ud\x80\x00\x00\xe0\x94\xf4\x9fo\x9b\xaa\xbc\x01\x8c\x8f\x8e\x11\x9e\x01\x15\xf4\x91\xfc\x92\xa8\xa4\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf4\xa3g\xb1f\u0499\x1a+\xfd\xa9\xf5dc\xa0\x9f%,\x1b\x1d\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf4\xa5\x1f\xceJ\x1d[\x94\xb0q\x83\x89\xbaNx\x14\x13\x9c\xa78\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xf4\xa9\xd0\f\xef\xa9{zX\xef\x94\x17\xfcbg\xa5\x06\x909\xee\x89\x01.\x89(\u007f\xa7\x84\x00\x00\u07d4\xf4\xaa\xa3\xa6\x16>7\x06W{I\xc0v~\x94\x8ah\x1e\x16\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf4\xb1bn$\xf3\v\xca\xd9'!\xb2\x93r\x89U\xa6\xe7\x9c\xcd\x1d0\x00\x00\u07d4\xf5U\xa2{\xb1\xe2\xfdN,\u01c4\xca\ue493\x9f\xc0n/\u0249lk\x93[\x8b\xbd@\x00\x00\u07d4\xf5X\xa2\xb2\xdd&\u0755\x93\xaa\xe0E1\xfd<<\u00c5Kg\x89\n\xbb\xcdN\xf3wX\x00\x00\u07d4\xf5`H\xdd!\x81\u0523od\xfc\xec\xc6!T\x81\xe4*\xbc\x15\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf5dB\xf6\x0e!i\x13\x95\u043f\xfa\xa9\x19M\xca\xff\x12\u2dc9\x0e\x189\x8ev\x01\x90\x00\x00\u07d4\xf5yqJE\xeb\x8fR\xc3\xd5{\xbd\xef\xd2\xc1[./\x11\u07c9T\x91YV\xc4\t`\x00\x00\u07d4\xf5\x93\xc6R\x85\xeek\xbdf7\U000fe3c9\xad@\u0509\xf6U\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf5\x98\xdb.\t\xa8\xa5\xee}r\r+\\C\xbb\x12m\x11\xec\u0089\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xf5\x9d\xab\x1b\xf8\xdf\x112~a\xf9\xb7\xa1KV:\x96\xec5T\x8a\x01EB\xba\x12\xa37\xc0\x00\x00\xe0\x94\xf5\x9f\x9f\x02\xbb\u024e\xfe\t~\xab\xb7\x82\x10\x97\x90!\x89\x8b\xfd\x8a\x02\x1e\x17\x1a>\xc9\xf7,\x00\x00\u07d4\xf5\xa5E\x9f\xcd\xd5\xe5\xb2s\x83\r\xf8\x8e\xeaL\xb7}\xda\u07f9\x89\x04\t\xe5+H6\x9a\x00\x00\u07d4\xf5\xa7gj\xd1H\xae\x9c\x1e\xf8\xb6\xf5\xe5\xa0\xc2\xc4s\xbe\x85\v\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf5\xb0h\x98\x9d\xf2\x9c%5w\xd0@Z\xden\x0eu(\xf8\x9e\x89WG=\x05\u06ba\xe8\x00\x00\u07d4\xf5\xb6\xe9\x06\x1aN\xb0\x96\x16\aw\xe2gb\xcfH\xbd\u0635]\x89\r\xc5_\xdb\x17d{\x00\x00\u07d4\xf5\xcf\xfb\xbabN~\xb3!\xbc\x83\xc6\f\xa6\x81\x99\xb4\xe3fq\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf5\xd1ER\xb1\xdc\xe0\xd6\xdc\x1f2\r\xa6\xff\u02231\xcdo\f\x89Hz\x9a0E9D\x00\x00\xe0\x94\xf5\xd6\x1a\xc4\u0295G^[{\xff\xd5\xf2\xf6\x90\xb3\x16u\x96\x15\x8a\x06\x92\xae\x88\x97\b\x1d\x00\x00\x00\u07d4\xf5\xd9\xcf\x00\xd6X\xddEQzH\xa9\xd3\xf5\xf63T\x1aS=\x89\x06O_\xdfIOx\x00\x00\u07d4\xf5\xea\xdc\xd2\u0478ez\x12\x1f3\xc4X\xa8\xb1>v\xb6U&\x89\r\x8b\x0fZZ\xc2J\x00\x00\u07d4\xf6\a\xc2\x15\r>\x1b\x99\xf2O\xa1\xc7\xd5@\xad\xd3\\N\xbe\x1e\x89\xa7\xf1\xaa\a\xfc\x8f\xaa\x00\x00\u07d4\xf6\v\xd75T>k\xfd.\xa6\xf1\x1b\xffbs@\xbc\x03Z#\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf6\f\x1bE\xf1d\xb9X\x0e 'Z\\9\xe1\xd7\x1e5\xf8\x91\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xf6\x0fb\xd797\x95?\xef5\x16\x9e\x11\xd8r\xd2\xea1~\xec\x8a\x01!\xeah\xc1\x14\xe5\x10\x00\x00\u07d4\xf6\x12\x83\xb4\xbd\x85\x04\x05\x8c\xa3`\u94d9\x9bb\xcb\xc8\xcdg\x89\r\xd2\xd5\xfc\xf3\xbc\x9c\x00\x00\u07d4\xf6\x17\xb9g\xb9\xbdH_v\x95\xd2\xefQ\xfbw\x92\u0618\xf5\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf6\x18\u0671\x04A\x14\x80\xa8c\xe6#\xfcU#-\x1aOH\xaa\x89\x0eh\x9emD\xb1f\x80\x00\u07d4\xf6\"\u5126b>\xaa\xf9\x9f+\xe4\x9eS\x80\xc5\xcb\xcf\\\u0609\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf62\xad\xffI\r\xa4\xb7-\x126\xd0KQ\x0ft\xd2\xfa\xa3\u0349K\xe4\xe7&{j\xe0\x00\x00\u07d4\xf69\xac1\u069fg'\x1b\xd1\x04\x02\xb7eN\\\xe7c\xbdG\x89\x15\xaf\x0fB\xba\xf9&\x00\x00\u07d4\xf6:W\x9b\xc3\xea\u00a9I\x04\x10\x12\x8d\xbc\xeb\xe6\xd9\u0782C\x89P\xc5\xe7a\xa4D\b\x00\x00\u07d4\xf6E\xdd|\x89\x00\x93\xe8\xe4\u022a\x92\xa6\xbb55\"\xd3\u0718\x89\aC\x9f\xa2\t\x9eX\x00\x00\xe0\x94\xf6H\xea\x89\xc2u%q\x01r\x94Ny\xed\xff\x84x\x03\xb7u\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xf6JJ\xc8\xd5@\xa9(\x9ch\xd9`\xd5\xfb|\xc4Zw\x83\x1c\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf6N\xcf!\x17\x93\x1cmSZ1\x1eO\xfe\xae\xf9\u0514\x05\xb8\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xf6O\xe0\x93\x9a\x8d\x1e\xea*\x0e\u035a\x970\xfdyX\xe31\t\x89\x01\x1d\xe1\xe6\xdbE\f\x00\x00\u07d4\xf6V\x16\xbe\x9c\x8by~t\x15\"|\x918\xfa\xa0\x89\x17B\u05c9*\xd3s\xcef\x8e\x98\x00\x00\u07d4\xf6W\xfc\xbeh.\xb4\xe8\xdb\x15.\u03c9$V\x00\vQ=\x15\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf6X\x19\xacL\xc1L\x13\u007f\x05\xddyw\xc7\xda\xe0\x8d\x1aJ\xb5\x89\x05\x87\x88\u02d4\xb1\xd8\x00\x00\u07d4\xf6{\xb8\xe2\x11\x8b\xbc\u0550'fn\xed\xf6\x94>\xc9\xf8\x80\xa5\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf6\x84d\xbfd\xf2A\x13V\xe4\xd3%\x0e\xfe\xfe\\P\xa5\xf6[\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf6\x86x[\x89r\va\x14_\ua017\x8dj\u030e\v\xc1\x96\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf6\x8c^3\xfa\x97\x13\x9d\xf5\xb2\xe68\x86\xce4\xeb\xf3\u45dc\x89\xb3\xfaAi\xe2\xd8\xe0\x00\x00\u07d4\xf6\xa8cWW\xc5\xe8\xc14\xd2\r\x02\x8c\xf7x\u03c6\t\xe4j\x89O\x1dw/\xae\xc1|\x00\x00\u07d4\xf6\xb7\x82\xf4\xdc\xd7E\xa6\xc0\xe2\xe00`\x0e\x04\xa2K%\xe5B\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\xe0\x94\xf6\xbc7\xb1\u04a3x\x8dX\x9bm\xe2\x12\xdc\x17\x13\xb2\xf6\u738a\x01\x0f\f\xf0d\xddY \x00\x00\u07d4\xf6\xc3\u010a\x1a\xc0\xa3G\x99\xf0M\xb8n\u01e9u\xfewh\xf3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf6\xd2]?=\x84m#\x9fR_\xa8\xca\xc9{\xc45x\u06ec\x890\x92\u007ft\xc9\xde\x00\x00\x00\u07d4\xf6\xea\xacp2\u0512\xef\x17\xfd`\x95\xaf\xc1\x1dcOV\xb3\x82\x89\x1b\x1bk\u05efd\xc7\x00\x00\xe0\x94\xf6\xea\xd6}\xbf[~\xb13X\xe1\x0f6\x18\x9dS\xe6C\xcf\u03ca\bxg\x83&\xea\xc9\x00\x00\x00\u07d4\xf6\xf1\xa4C\t\x05\x1ck%\xe4}\xff\x90\x9b\x17\x9b\xb9\xabY\x1c\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xf7\x03(\xef\x97b_\xe7E\xfa\xa4\x9e\xe0\xf9\u052a;\r\xfbi\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf7\n\x99\x8aq{3\x8d\x1d\u0658T@\x9b\x1a3\x8d\ue930\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7\rcz\x84\\\x06\xdbl\u0711\xe67\x1c\xe7\xc48\x8ab\x8e\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\x15R\x13D\x98\x92tK\xc6\x0f.\x04@\a\x88\xbd\x04\x1f\u0749\x03\x9f\xba\xe8\xd0B\xdd\x00\x00\xe0\x94\xf7\x1bE4\xf2\x86\xe40\x93\xb1\xe1^\xfe\xa7I\xe7Y{\x8bW\x8a\x16\x1c\x13\xd34\x1c\x87(\x00\x00\u07d4\xf74\xec\x03rM\xde\xe5\xbbRy\xaa\x1a\xfc\xf6\x1b\f\xb4H\xa1\x89\xe5\xbf,\u0270\x97\x80\x00\x00\u07d4\xf76\u0716v\x00\x128\x8f\xe8\x8bf\xc0n\xfeW\xe0\xd7\xcf\n\x89q\xd7Z\xb9\xb9 P\x00\x00\u07d4\xf7:\xc4l ;\xe1S\x81\x11\xb1Q\xec\x82 \u01c6\xd8AD\x89\x0f\xf77x\x17\xb8+\x80\x00\u07d4\xf7=\xd9\xc1B\xb7\x1b\xce\x11\xd0n0\xe7\xe7\xd02\xf2\uc71e\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf7A\x8a\xa0\xe7\x13\xd2H\"\x87v\xb2\xe7CB\"\xaeu\u3949lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7Nn\x14S\x82\xb4\u06c2\x1f\xe0\xf2\u0643\x88\xf4V\t\u019f\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xf7P\f\x16o\x8b\xea/\x824v\x06\xe5\x02K\xe9\xe4\xf4\u0399\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7W\xfc\x87 \xd3\xc4\xfaRw\a^`\xbd\\A\x1a\xeb\xd9w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7[\xb3\x9cy\x97y\xeb\xc0J3m&\r\xa61F\xed\x98\u0409\x01Z\xf1\u05cbX\xc4\x00\x00\xe0\x94\xf7h\xf3!\xfdd3\xd9kO5M<\xc1e,\x172\xf5\u007f\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf7oi\xce\xe4\xfa\xa0\xa6;0\xae\x1ex\x81\xf4\xf7\x15ep\x10\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf7w6\x1a=\u062bb\xe5\xf1\xb9\xb0GV\x8c\xc0\xb5UpL\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf7|{\x84QI\xef\xba\x19\xe2a\xbc|u\x15y\b\xaf\xa9\x90\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf7\u007f\x95\x87\xffz-r\x95\xf1\xf5q\u0206\xbd3\x92jR|\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xf7\x82X\xc1$\x81\xbc\xdd\u06f7*\x8c\xa0\xc0C\tra\xc6\u0149\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\x98\xd1m\xa4\xe4`\xc4`\xcdH_\xae\x0f\xa0Y\x97\b\ub08965\u026d\xc5\u07a0\x00\x00\u07d4\xf7\xa1\xad\xe2\xd0\xf5)\x12=\x10U\xf1\x9b\x17\x91\x9fV!Ng\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf7\xac\xff\x93K\x84\xda\ti\xdc7\xa8\xfc\xf6C\xb7\xd7\xfb\xedA\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xf7\xb1Q\xcc^W\x1c\x17\xc7e9\xdb\xe9\x96L\xbbo\xe5\xdey\x89tq|\xfbh\x83\x10\x00\x00\u07d4\xf7\xb2\x9b\x82\x19\\\x88-\xabx\x97\u00ae\x95\xe7w\x10\xf5xu\x89w5Aa2\xdb\xfc\x00\x00\u07d4\xf7\xbcLD\x91\rZ\xed\xd6n\xd25U8\xa6\xb1\x93\xc3a\xec\x89\x05A\xde,-\x8db\x00\x00\u07d4\xf7\xc0\f\xdb\x1f\x02\x03\x10\u056c\xab{Ij\xaaD\xb7y\b^\x89Z\x87\xe7\xd7\xf5\xf6X\x00\x00\u07d4\xf7\xc1\xb4C\x96\x8b\x11{]\u0677UW/\xcd9\xca^\xc0K\x89\x18\xb9h\u0092\xf1\xb5\x00\x00\xe0\x94\xf7\xc5\x0f\x92*\xd1ka\xc6\u047a\xa0E\xed\x81h\x15\xba\u010f\x8a\x02\xa99j\x97\x84\xad}\x00\x00\u07d4\xf7\xc7\b\x01Pq\xd4\xfb\n:*\t\xa4]\x15c\x96\xe34\x9e\x89\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf7\xcb\u06e6\xbel\xfeh\xdb\xc2<+\x0f\xf50\xee\x05\"o\x84\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf7\xd0\xd3\x10\xac\xea\x18@a8\xba\xaa\xbb\xfe\x05q\xe8\r\xe8_\x89Hz\x9a0E9D\x00\x00\u07d4\xf7\u05ef LV\xf3\x1f\xd9C\x98\xe4\r\xf1\x96K\u063f\x12<\x89\b!\xd2!\xb5)\x1f\x80\x00\u07d4\xf7\xdc%\x11\x96\xfb\u02f7|\x94}|\x19F\xb0\xffe\x02\x1c\xea\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf7\xe4Z\x12\xaaq\x1cp\x9a\xce\xfe\x95\xf3;xa-*\xd2*\x8a\x0e\x06U\xe2\xf2k\xc9\x18\x00\x00\u07d4\xf7\xf4\x89\x8cLRm\x95_!\xf0U\xcbnG\xb9\x15\xe5\x19d\x89|\b`\xe5\xa8\r\xc0\x00\x00\u07d4\xf7\xf9\x1ez\xcb[\x81)\xa3\x06\x87|\xe3\x16\x8eoC\x8bf\xa1\x89\t\x8a}\x9b\x83\x14\xc0\x00\x00\u07d4\xf7\xfcE\xab\xf7oP\x88\xe2\u5d68\xd12\xf2\x8aMN\xc1\xc0\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\x06:\xf4\xcc\x1d\xd9a\x9a\xb5\u063f\xf3\xfc\xd1\xfa\xa8H\x82!\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\bnBf\x1e\xa9)\xd2\u0761\xablt\x8c\xe3\x05]\x11\x1e\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xf8\bw\x86\xb4-\xa0N\xd6\xd1\xe0\xfe&\xf6\xc0\xee\xfe\x1e\x9fZ\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xf8\r6\x19p/\xa5\x83\x8cH9\x18Y\xa89\xfb\x9c\xe7\x16\x0f\x89l\a\xa7\u0471np\x00\x00\u07d4\xf8\x14y\x9fm\xdfM\xcb)\xc7\xee\x87\x0eu\xf9\xcc-52m\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xf8\x15\xc1\n\x03-\x13\xc3K\x89v\xfan;\xd2\xc9\x13\x1a\x8b\xa9\x89Hz\x9a0E9D\x00\x00\u07d4\xf8\x16\"\xe5WW\xda\xeafu\x97]\xd958\xda}\x16\x99\x1e\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8$\xee3\x1eJ\xc3\xccXv\x939[W\xec\xf6%\xa6\xc0\u0089V\xc9]\xe8\xe8\xca\x1d\x00\x00\u07d4\xf8'\xd5n\xd2\xd3' \u052b\xf1\x03\xd6\xd0\xefM;\xcdU\x9b\x89\x01l\x80\x06W\x91\xa2\x80\x00\u07d4\xf8)\x85\x91R>P\xb1\x03\xf0\xb7\x01\xd6#\xcb\xf0\xf7EV\xf6\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf8H\xfc\xe9\xaba\x1c}\x99 n#\xfa\u019a\u0508\xb9O\xe1\x89\x02\xa1\x12\x9d\t6r\x00\x00\u07d4\xf8O\t\n\xdf?\x8d\xb7\u1533P\xfb\xb7u\x00i\x9ff\xfd\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf8Q\xb0\x10\xf63\xc4\n\xf1\xa8\xf0js\ubeabe\az\xb5\x89\xee\x86D/\xcd\x06\xc0\x00\x00\u07d4\xf8X\x17\x1a\x04\xd3W\xa1;IA\xc1n~U\xdd\u0514\x13)\x89\x02F\xa5!\x8f*\x00\x00\x00\u07d4\xf8[\xab\x1c\xb3q\x0f\xc0_\xa1\x9f\xfa\xc2.gR\x1a\v\xa2\x1d\x89l\x955\u007f\xa6\xb3l\x00\x00\u07d4\xf8j>\xa8\a\x1fp\x95\xc7\u06ca\x05\xaePz\x89)\u06f8v\x89\x126\xef\xcb\u02f3@\x00\x00\u07d4\xf8pL\x16\xd2\xfd[\xa3\xa2\xc0\x1d\x0e\xb2\x04\x84\xe6\xec\xfa1\t\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf8p\x99_\xe1\xe5\"2\x1duC7\xa4\\\f\x9d{8\x95\x1c\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf8s\xe5ze\xc9;n\x18\xcbu\xf0\xdc\a}[\x893\xdc\\\x89\n\xad\xec\x98?\xcf\xf4\x00\x00\u07d4\xf8ua\x9d\x8a#\xe4]\x89\x98\u0444\u0500\xc0t\x89p\x82*\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf8{\xb0{(\x9d\xf70\x1eT\xc0\xef\xdaj,\xf2\x91\xe8\x92\x00\x89K\xe4\xe7&{j\xe0\x00\x00\u0794\xf8\x89\x00\xdbsyU\xb1Q\x9b\x1a}\x17\n\x18\x86L\xe5\x90\xeb\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xf8\x8bX\xdb7B\vFL\v\xe8\x8bE\xee+\x95)\x0f\x8c\xfa\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf8\x96+u\xdb]$\xc7\xe8\xb7\xce\xf1\x06\x8c>g\u03bb0\xa5\x89\x0f-\xc7\xd4\u007f\x15`\x00\x00\u07d4\xf8\xa0e\xf2\x87\xd9\x1dw\xcdbj\xf3\x8f\xfa\"\r\x9bU*+\x89g\x8a\x93 b\xe4\x18\x00\x00\u07d4\xf8\xa4\x9c\xa29\f\x1fm\\\x0ebQ;\a\x95qt?|\u0189\xa2\xa1]\tQ\x9b\xe0\x00\x00\u07d4\xf8\xa5\f\xee.h\x8c\xee\u3b24\u0522\x97%\xd4\a,\u0103\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xacJ9\xb5<\x110x \x97;D\x13e\xcf\xfeYof\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xae\x85{g\xa4\xa2\x89:?\xbe|z\x87\xff\x1c\x01\u01a6\xe7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xf8\xbf\x9c\x04\x87NZw\xf3\x8fL8R~\x80\xc6v\xf7\xb8\x87\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xc7\xf3J8\xb3\x18\x01\xdaC\x064w\xb1+'\xd0\xf2\x03\xff\x89\x1a\u04ba\xbao\xefH\x00\x00\u07d4\xf8\xca3l\x8e\x91\xbd \xe3\x14\xc2\v-\xd4`\x8b\x9c\x8b\x94Y\x89-\u071b\u0173,x\x00\x00\u07d4\xf8\xd1t$\xc7g\xbe\xa3\x12\x05s\x9a+W\xa7'r\x14\uef89\x02F\xdd\xf9yvh\x00\x00\u07d4\xf8\xd5-\xcc_\x96\xcc(\x00{>\u02f4\t\xf7\xe2*dl\xaa\x89\b\x16\x90\xe1\x81(H\x00\x00\u07d4\xf8\xdc\xe8g\xf0\xa3\x9c[\xef\x9e\xeb\xa6\t\"\x9e\xfa\x02g\x8bl\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf8\xf2&\x14*B\x844\xab\x17\xa1\x86J%\x97\xf6J\xab/\x06\x89\tY\x8b/\xb2\xe9\xf2\x80\x00\u07d4\xf8\xf6d^\r\xeedK=\xad\x81\xd5q\uf6ef\x84\x00!\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9\x01\xc0\x0f\xc1\u06c8\xb6\x9cK\xc3%+\\\xa7\x0e\xa6\xee\\\xf6\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf9=[\xcb\x06D\xb0\xcc\xe5\xfc\u0763C\xf5\x16\x8f\xfa\xb2\x87}\x89\vb\a\xb6}&\xf9\x00\x00\u07d4\xf9W\x0e\x92L\x95\u07bbpa6\x97\x92\xcf.\xfe\u00a8-^\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xf9d \x86\xb1\xfb\xaea\xa6\x80M\xbe_\xb1^\xc2\u04b57\xf4\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9d\x88i\x85\x90\xdc;,UVB\xb8q4\x8d\xfa\x06z\u0549\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf9d\u064d(\x170\xba5\xb2\xe3\xa3\x14yn{B\xfe\xdfg\x89S\xb0\x87`\x98\xd8\f\x00\x00\u07d4\xf9e\ri\x89\xf1\x99\xab\x1c\xc4ycm\xed0\xf2A\x02\x1fe\x89.\x14\x1e\xa0\x81\xca\b\x00\x00\xe0\x94\xf9h\x83X$Y\x90\x8c\x82v'\xe8o(\xe6F\xf9\xc7\xfcz\x8a\x01\u0127\x877\xcd\u03f8\x00\x00\u07d4\xf9kL\x00voSsj\x85t\xf8\"\xe6GL/!\xda-\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xf9r\x9dH(,\x9e\x87\x16m^\xef-\x01\xed\xa9\xdb\xf7\x88!\x89\x05k\x83\xdd\xc7(T\x80\x00\u07d4\xf9v~N\xcbJY\x80Ru\b\u05fe\xc3\xd4^Ld\x9c\x13\x89g\x8a\x93 b\xe4\x18\x00\x00\xe0\x94\xf9x\xb0%\xb6B3U\\\xc3\xc1\x9a\xda\u007fA\x99\xc94\x8b\xf7\x8aT\xb4\v\x1f\x85+\xda\x00\x00\x00\u07d4\xf9{V\xeb\u0577z\xbc\x9f\xba\u02eb\u0514\xb9\xd2\xc2!\xcd\x03\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xf9\x81\x1f\xa1\x9d\xad\xbf\x02\x9f\x8b\xfeV\x9a\xdb\x18\"\x8c\x80H\x1a\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xf9\x82Ps\fLa\xc5\u007f\x12\x985\xf2h\b\x94yEB\xf3\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xf9\x894gr\x99^\xc1\x90o\xaf\xfe\xba*\u007f\xe7\u079ck\xab\x8a\x01je\x02\xf1Z\x1eT\x00\x00\u07d4\xf9\x98\xca4\x11s\nl\xd1\x0etU\xb0A\x0f\xb0\xf6\xd3\xff\x80\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xf9\x9a\xeeDKW\x83\xc0\x93\xcf\xff\xd1\xc4c,\xf9\x90\x9f\xbb\x91\x1d/\x81\x92\xf8B\t\x89\x90\xf54`\x8ar\x88\x00\x00\u07d4\xf9\xbf\xb5\x9dS\x8a\xfcHt\xd4\xf5\x94\x1b\b\xc9s\x0e8\xe2K\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\u07d4\xf9\xdd#\x90\b\x18/\xb5\x19\xfb0\xee\xdd \x93\xfe\xd1c\x9b\xe8\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xf9\u07ba\xec\xb5\xf39\xbe\xeaH\x94\xe5 K\xfa4\r\x06\u007f%\x89ZB\x84Fs\xb1d\x00\x00\xe0\x94\xf9\xe3tG@lA!\x97\xb2\u2bbc\x00\x1dn0\u024c`\x8a\x01\xc4y\xbbCI\xc0\xee\x00\x00\u07d4\xf9\xe7\"/\xaa\xf0\xf4\xda@\xc1\u0124\x0607:\t\xbe\u05f6\x89\x9bO\u0730\x94V$\x00\x00\u07d4\xf9\xec\xe0\"\xbc\xcd,\x924i\x11\xe7\x9d\xd5\x03\x03\xc0\x1e\x01\x88\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfa\x00\xc3v\xe8\x9c\x05\u81c1z\x9d\xd0t\x8d\x96\xf3A\xaa\x89\x89\x10M\r\x00\u04b7\xf6\x00\x00\u07d4\xfa\f\x1a\x98\x8c\x8a\x17\xad5(\xeb(\xb3@\x9d\xaaX\"_&\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xfa\x10_\x1a\x11\xb6\xe4\xb1\xf5`\x12\xa2y\"\xe2\xac-\xa4\x81/\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xfa\x14/\xe4~\u0697\xe6P;8k\x18\xa2\xbe\xdds\u0335\xb1\x89.\x15:\xd8\x15H\x10\x00\x00\u07d4\xfa\x14\xb5f#J\xbe\xe70B\xc3\x1d!qq\x82\u02e1J\xa1\x89\x11\xc7\xea\x16.x \x00\x00\u07d4\xfa\x19\xd6\xf7\xa5\x0fO\a\x98\x93\xd1g\xbf\x14\xe2\x1d\x00s\u0456\x89\x1c\xbb:?\xf0\x8d\b\x00\x00\u07d4\xfa\x1f\x19q\xa7u\xc3PO\xefPy\xf6@\xc2\u013c\xe7\xac\x05\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfa'\x9b\xfd\x87g\xf9V\xbf\u007f\xa0\xbdV`\x16\x8d\xa7V\x86\xbd\x89\x90\xf54`\x8ar\x88\x00\x00\xe0\x94\xfa'\xccI\xd0\vl\x98s6\xa8u\xae9\xdaX\xfb\x04\x1b.\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xfa(2\x99`=\x87X\xe8\u02b0\x82\x12],\x8f}DT)\x8a\x01[\xca\xcb\x1e\x05\x01\xae\x80\x00\u07d4\xfa+\xbc\xa1]?\u37ca2\x8e\x91\xf9\r\xa1Oz\xc6%=\x89\n\u05ce\xbcZ\xc6 \x00\x00\xe0\x94\xfa/\u049d\x03\xfe\xe9\xa0x\x93\xdf:&\x9fV\xb7/.\x1ed\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xfa3U2\x85\xa9sq\x9a\r_\x95o\xf8a\xb2\u061e\xd3\x04\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfa:\fK\x90?n\xa5.\xa7\xab{\x88c\xb6\xa6\x16\xadfP\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfa:\x1a\xa4H\x8b5\x1a\xa7V\f\xf5\xeec\n/\xd4\\2\"\x89/\xa4~j\xa74\r\x00\x00\u07d4\xfaA\tq\xad\"\x9c06\xf4\x1a\u03c5/*\u0259(\x19P\x89\u0633\x11\xa8\xdd\xfa|\x00\x00\u07d4\xfaD\xa8U\xe4\x04\xc8m\f\xa8\xef3$%\x1d\xfb4\x9cS\x9e\x89T\"S\xa1&\xce@\x00\x00\xe0\x94\xfaR\x01\xfe\x13B\xaf\x110{\x91B\xa0A$<\xa9./\t\x8a 8\x11j:\xc0C\x98\x00\x00\xe0\x94\xfa`\x86\x8a\xaf\xd4\xffL\\W\x91K\x8e\u054bBWs\u07e9\x8a\x01\xcf\xe5\xc8\b\xf3\x9f\xbc\x00\x00\u07d4\xfag\xb6{O7\xa0\x15\t\x15\x11\x0e\xde\a;\x05\xb8S\xbd\xa2\x89#\x19\xba\x94sq\xad\x00\x00\u07d4\xfah\xe0\xcb>\xdfQ\xf0\xa6\xf2\x11\u0272\xcb^\a<\x9b\xff\xe6\x89\x0f\xc969(\x01\xc0\x00\x00\xe0\x94\xfaj7\xf0\x18\xe9yg\x93\u007f\xc5\xe8a{\xa1\u05c6\xdd_w\x8a\x04<0\xfb\b\x84\xa9l\x00\x00\u07d4\xfav\x06C[5l\xee%{\xd2\xfc\xd3\xd9\xea\xcb<\xd1\xc4\xe1\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xfaz\xdff\v\x8d\x99\xce\x15\x93=|_\a/<\xbe\xb9\x9d3\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\xfa\x86\xca'\xbf(T\u0648p\x83\u007f\xb6\xf6\xdf\xe4\xbfdS\xfc\x89\x11u~\x85%\xcf\x14\x80\x00\u07d4\xfa\x8c\xf4\xe6'i\x8c]W\x88\xab\xb7\x88\x04\x17\xe7P#\x13\x99\x89\xe6\x1a6\x96\xee\xf6\x10\x00\x00\u07d4\xfa\x8e;\x1f\x13C9\x00s}\xaa\xf1\xf6)\x9cH\x87\xf8[_\x89&\u009eG\u0104L\x00\x00\u07d4\xfa\x9e\xc8\xef\xe0\x86\x86\xfaX\xc1\x813Xr\xbai\x85`\ucac9lj\xccg\u05f1\xd4\x00\x00\u07d4\xfa\xad\x90]\x84|{#A\x8a\xee\xcb\xe3\xad\u06cd\xd3\xf8\x92J\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xfa\xae\xba\x8f\xc0\xbb\xdaU<\xa7.0\xef=s.&\xe8 A\x89H\x8d(*\xaf\xc9\xf6\x80\x00\u07d4\xfa\xb4\x87P\r\xf2\x0f\xb8>\xbe\xd9\x16y\x1dV\x17r\xad\xbe\xbf\x89lkLM\xa6\u077e\x00\x00\u07d4\xfa\xc5\u0294u\x80x\xfb\xfc\xcd\x19\xdb5X\xda~\u8827h\x897(\xa6+\r\xcf\xf6\x00\x00\u07d4\xfa\xd9j\xb6\xacv\x8a\xd5\t\x94R\xacGw\xbd\x1aG\xed\u010f\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xfa\xe7g\x19\xd9~\xacA\x87\x04(\xe9@'\x9d\x97\xddW\xb2\xf6\x8a\x14\u06f2\x19\\\xa2(\x90\x00\x00\u07d4\xfa\u8053pG\x89Zf\f\xf2)v\x0f'\xe6h(\xd6C\x89\t\xdd\xc1\xe3\xb9\x01\x18\x00\x00\u07d4\xfa\xe9,\x13p\xe9\u115a]\xf8;V\xd0\xf5\x86\xaa;@L\x89\x05\u0174\xf3\xd8C\x98\x00\x00\xe0\x94\xfa\xf5\xf0\xb7\xb6\xd5X\xf5\t\r\x9e\xa1\xfb-B%\x9cX`x\x8a\x01Z\xff\xb8B\fkd\x00\x00\xe0\x94\xfb\x12o\x0e\xc7i\xf4\x9d\xce\xfc\xa2\xf2\x00(dQX0\x84\xb8\x8a\x01\x0f\xcb\xc25\x03\x96\xbf\x00\x00\xe0\x94\xfb\x13^\xb1Z\x8b\xacr\xb6\x99\x154*`\xbb\xc0k~\a|\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xfb\"<\x1e\"\xea\xc1&\x9b2\xee\x15jS\x85\x92.\xd3o\xb8\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb7\xcfkO\x81\xa9\xe2\"\xfb\xa2.\x9b\xd2KP\x98\xb73\u03c9\x02\x1auJm\xc5(\x00\x00\u07d4\xfb8`\xf4\x12\x1cC.\xbd\xc8\xecj\x031\xb1\xb7\ty.\x90\x89 \x8c9J\xf1\u0208\x00\x00\u07d4\xfb9\x18\x9a\xf8v\xe7b\xc7\x1dl>t\x18\x93\xdf\"l\xed\u0589\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfb:\v\rkjq\x8fo\xc0)*\x82]\xc9$z\x90\xa5\u0409\n\xd6\xdd\x19\x9e\x97[\x00\x00\xe0\x94\xfb?\xa1\xac\b\xab\xa9\xcc;\xf0\xfe\x9dH8 h\x8fe\xb4\x10\x8a\x06ZM\xa2]0\x16\xc0\x00\x00\u07d4\xfb?\xe0\x9b\xb86\x86\x15)\xd7Q\x8d\xa2v5\xf58PV\x15\x89K\xe3\x92\x16\xfd\xa0p\x00\x00\xe0\x94\xfbQ%\xbf\x0f^\xb0\xb6\xf0 \xe5k\xfc/\xdf=@,\t~\x8a\x01@a\xb9\xd7z^\x98\x00\x00\u07d4\xfbU\x18qL\xef\xc3m\x04\x86]\xe5\x91^\xf0\xffG\xdf\xe7C\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb_\xfa\xa0\xf7aW&5x\x91GX\x18\x93\x9d 7\u03d6\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfbh\\\x15\xe49\x96^\xf6&\xbf\r\x83L\u0468\x9f+V\x95\x89\u0556{\xe4\xfc?\x10\x00\x00\u07d4\xfbtK\x95\x1d\tK1\x02b\xc8\xf9\x86\xc8`\u07da\xb1\xdee\x89\x02\xd1\xc5\x15\xf1\xcbJ\x80\x00\u07d4\xfby\xab\u06d2\\U\xb9\xf9\x8e\xfe\xefd\xcf\xc9\xeba\xf5\x1b\xb1\x89a@\xc0V\xfb\n\xc8\x00\x00\u07d4\xfb\x81\x13\xf9M\x91s\xee\xfdZ0s\xf5\x16\x80:\x10\xb2\x86\xae\x89\x04V9\x18$O@\x00\x00\u07d4\xfb\x84,\xa2\xc5\xef\x139\x17\xa26\xa0\u052c@i\x01\x10\xb08\x89\x10\x96\x9ab\xbe\x15\x88\x00\x00\u07d4\xfb\x91\xfb\x1aiUS\xf0\u018e!'m\xec\xf0\xb89\t\xb8m\x89\x05l\x006\x17\xafx\x00\x00\u07d4\xfb\x94s\xcfw\x125\n\x1f\xa09Rs\xfc\x80V\aR\xe4\xfb\x89\x06\xaf!\x98\xba\x85\xaa\x00\x00\xe0\x94\xfb\x94\x9cd\u007f\xdc\xfd%\x14\xc7\u054e1\xf2\x8aS-\x8cX3\x8a\x04<3\xc1\x93ud\x80\x00\x00\u07d4\xfb\xa5HmS\xc6\xe2@IBA\xab\xf8~C\xc7`\rA:\x89k\xbfaIIH4\x00\x00\u07d4\xfb\xb1a\xfe\x87_\t)\nK&+\xc6\x01\x10\x84\x8f\r\"&\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfb\xbb\xeb\u03fe#^W\xdd#\x06\xad\x1a\x9e\u0141\xc7\xf9\xf4\x8f\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xfb\xc0\x1d\xb5NG\xcd\xc3\xc48iJ\xb7\x17\xa8V\xc2?\xe6\xe9\x8a\x01\xcaqP\xab\x17OG\x00\x00\xe0\x94\xfb\xcf\xccJ{\x0f&\xcf&\xe9\xf33!2\xe2\xfcj#\af\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfb\xe7\x16\"\xbc\xbd1\xc1\xa3iv\xe7\xe5\xf6p\xc0\u007f\xfe\x16\u0789\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfb\xed\xe3,4\x9f3\x00\xefL\xd3;M\xe7\xdc\x18\xe4C\xd3&\x89\xabM\xcf9\x9a:`\x00\x00\u07d4\xfb\xf2\x04\xc8\x13\xf86\xd89b\u01c7\fx\b\xca4\u007f\xd3>\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xfb\xf7Y3\xe0\x1bu\xb1T\xef\x06i\ak\xe8\u007fb\xdf\xfa\xe1\x8a\x10\x84cr\xf2I\xd4\xc0\x00\x00\u07d4\xfc\x00\x96\xb2\x1e\x95\xac\xb8\xd6\x19\xd1v\xa4\xa1\xd8\xd5)\xba\xdb\xef\x89\x14\xd9i;\xcb\xec\x02\x80\x00\xe0\x94\xfc\x00\xa4 \xa3a\a\xdf\xd5\xf4\x95\x12\x8a_\u5af2\xdb\x0f4\x8a\x01C\x17\x9d\x86\x91\x10 \x00\x00\xe0\x94\xfc\x01\x8ai\n\xd6tm\xbe:\u03d7\x12\xdd\xcaR\xb6%\x009\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\u07d4\xfc\x02s@3\xe5\u007fpQ~\n\xfc~\xe6$a\xf0o\xad\x8e\x89\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xfc\x0e\xe6\xf7\u00b3qJ\xe9\x91lEVf\x05\xb6V\xf3$A\x89_h\xe8\x13\x1e\u03c0\x00\x00\u07d4\xfc\x10\xb7\xa6{2h\xd53\x1b\xfbj\x14\xde\xf5\xeaJ\x16,\xa3\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfc\x15\u02d9\xa8\xd1\x03\v\x12w\n\xdd\x03:y\xee\r\f\x90\x8c\x89\x12\xfa\x00\xbdR\xe6$\x00\x00\u07d4\xfc)R\xb4\u011f\xed\u043c\x05(\xa3\bI^mj\x1cq\u0589lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xfc,\x1f\x88\x96\x1d\x01\x9c>\x9e\xa30\t\x15.\x06\x93\xfb\xf8\x8a\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\xe0\x94\xfc6\x11\x05\u0750\xf9\xed\xe5fI\x9di\xe9\x13\x03\x95\xf1*\u020aS\xa4\xfe/ N\x80\xe0\x00\x00\u07d4\xfc7/\xf6\x92|\xb3\x96\xd9\xcf)\x805\x00\x11\r\xa62\xbcR\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc9\xbeA\tK\x19\x97\xd2\x16\x9e\x82d\xc2\u00fa\xa6\u025b\u0109lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc=\"k\xb3jX\xf5&V\x88W\xb0\xbb\x12\xd1\t\xec\x93\x01\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfcC\x82\x9a\u01c7\xff\x88\xaa\xf1\x83\xba5*\xad\xbfZ\x15\xb1\x93\x89\u05ac\n+\x05R\xe0\x00\x00\u07d4\xfcI\xc1C\x9aA\u05b3\xcf&\xbbg\xe06R$\xe5\xe3\x8f_\x8966\u05ef^\u024e\x00\x00\u07d4\xfcU\x00\x82Q\x05\xcfq*1\x8a^\x9c;\xfci\u021d\f\x12\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\xe0\x94\xfcf\xfa\xba'\u007fK]\xe6J\xd4^\xb1\x9c1\xe0\f\xed>\u054a\x011\xbe\xb9%\xff\xd3 \x00\x00\xe0\x94\xfc~\"\xa5\x03\xecZ\xbe\x9b\b\xc5\v\xd1I\x99\xf5 \xfaH\x84\x8a\x01ZG}\xfb\xe1\xea\x14\x80\x00\u07d4\xfc\x82\x15\xa0\xa6\x99\x13\xf6*C\xbf\x1c\x85\x90\xb9\xdd\xcd\r\x8d\u06c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xfc\x98\x9c\xb4\x87\xbf\x1a}\x17\xe4\xc1\xb7\u0137\xaa\xfd\xdak\n\x8d\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\xe0\x94\xfc\x9b4td\xb2\xf9\x92\x9d\x80~\x03\x9d\xaeH\xd3\u064d\xe3y\x8a\x02\xf6\xf1\a\x80\xd2,\xc0\x00\x00\u07d4\xfc\xa4;\xbc#\xa0\xd3!\xba\x9eF\xb9)s\\\xe7\xd8\xef\f\x18\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfc\xa7>\xff\x87q\xc0\x10;\xa3\xcc\x1a\x9c%\x94H\xc7*\xbf\v\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfc\xad\xa3\x00(?k\xcc\x13J\x91Eg`\xb0\xd7}\xe4\x10\xe0\x89lk\x93[\x8b\xbd@\x00\x00\xe0\x94\xfc\xbc\\q\xac\xe7\x97AE\v\x01,\xf6\xb8\xd3\xf1}\xb6\x8ap\x8a\x02\x05\xb4\u07e1\xeetx\x00\x00\u07d4\xfc\xbd\x85\xfe\xeajuO\xcf4ID\x9e7\xff\x97\x84\xf7w<\x89\xa7J\xdai\xab\xd7x\x00\x00\xe0\x94\xfc\xc9\u0524&.z\x02z\xb7Q\x91\x10\xd8\x02\u0115\xce\xea9\x8a\x01YQ\x82\"K&H\x00\x00\xe0\x94\xfc\xcd\r\x1e\xce\xe2z\xdd\xea\x95\xf6\x85z\xee\xc8\u01e0K(\xee\x8a\x02\x1e\x19\xe0\u027a\xb2@\x00\x00\xe0\x94\xfc\u0434\x82|\xd2\b\xff\xbf^u\x9d\xba\x8c<\xc6\x1d\x8c,<\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfc\xe0\x89c\\\xe9z\xba\xc0kD\x81\x9b\xe5\xbb\n>.\v7\x89\x05\x03\x92\nv0\xa7\x80\x00\u07d4\xfc\xf1\x99\xf8\xb8T\"/\x18.N\x1d\t\x9dN2>*\xae\x01\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfc\xfc:P\x04\xd6xa?\v6\xa6B&\x9a\u007f7\x1c?j\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfd\x19\x1a5\x15}x\x13s\xfbA\x1b\xf9\xf2R\x90\x04|^\xef\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfd\x1f\xaa4{\x0f\u0300L-\xa8l6\xd5\xf1\u044bp\x87\xbb\x89\x02\xd6\xeb$z\x96\xf6\x00\x00\u07d4\xfd\x1f\xb5\xa8\x9a\x89\xa7!\xb8yph\xfb\xc4\u007f>\x9dR\xe1I\x89\f\u0435\x83\u007f\xc6X\x00\x00\u07d4\xfd OOJ\xba%%\xbar\x8a\xfd\xf7\x87\x92\xcb\u07b75\xae\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd'W\xcc5Q\xa0\x95\x87\x8d\x97\x87V\x15\xfe\fj2\xaa\x8a\x89 m\xb1R\x99\xbe\xac\x00\x00\u07d4\xfd(r\u045eW\x85<\xfa\x16\xef\xfe\x93\u0431\xd4{O\x93\xfb\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfd))'\x1e\x9d \x95\xa2dv~{\r\xf5.\xa0\xd1\xd4\x00\x89\xa2\xa1\xeb%\x1bZ\xe4\x00\x00\u07d4\xfd7z8Rr\x90\f\xb46\xa3\xbbyb\xcd\xff\xe9?]\xad\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd@$+\xb3Jp\x85^\xf0\xfd\x90\xf3\x80-\xec!6\xb3'\x89h\xa8u\a>)$\x00\x00\xe0\x94\xfdE,9i\xec\xe3\x80\x1cT \xf1\xcd\u02a1\xc7\x1e\xd2=\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\u07d4\xfdKU\x1fo\xdb\u0366\xc5\x11\xb5\xbb7\"P\xa6\xb7\x83\xe54\x89\x01\x1d\xe1\xe6\xdbE\f\x00\x00\u07d4\xfdK\x98\x95X\xae\x11\xbe\f;6\xe2\xd6\xf2\xa5J\x93C\xca.\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfdM\xe8\xe3t\x8a(\x9c\xf7\xd0`Q}\x9d88\x8d\xb0\x1f\xb8\x89\r\x8drkqw\xa8\x00\x00\u07d4\xfdZc\x15\u007f\x91O\u04d8\uac5c\x13}\xd9U\v\xb7q\\\x89\x05k\xc7^-c\x10\x00\x00\u07d4\xfd`\u04b5\xaf=5\xf7\xaa\xf0\u00d3\x05.y\xc4\xd8#\u0645\x89\x03\x0e\xb5\r.\x14\b\x00\x00\u07d4\xfdhm\xe5?\xa9\u007f\x99c\x9e%hT\x97 \xbcX\x8c\x9e\xfc\x89j\xc5\xc6-\x94\x86\a\x00\x00\u07d4\xfd~\u078fR@\xa0eA\xebi\x9dx,/\x9a\xfb!p\xf6\x89Hz\x9a0E9D\x00\x00\u07d4\xfd\x81+\u019f\xb1p\xefW\xe22~\x80\xaf\xfd\x14\xf8\xe4\xb6\u0489lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\x88\xd1\x14\"\x0f\b\x1c\xb3\xd5\xe1[\xe8\x15*\xb0sfWj\x89\x10CV\x1a\x88)0\x00\x00\u07d4\xfd\x91\x856\xa8\xef\xa6\xf6\xce\xfe\x1f\xa1\x159\x95\xfe\xf5\xe3=;\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xfd\x92\x0fr&\x82\xaf\xb5\xafE\x1b\x05D\xd4\xf4\x1b;\x9dWB\x89~R\x05j\x12?<\x00\x00\u07d4\xfd\x95y\xf1\x19\xbb\xc8\x19\xa0+a\u3348\x03\xc9B\xf2M2\x89\x05\xb9~\x90\x81\xd9@\x00\x00\u07d4\xfd\xa0\xce\x153\a\a\xf1\v\xce2\x01\x17- \x18\xb9\xdd\xeat\x89\x02\xd0A\xd7\x05\xa2\xc6\x00\x00\xe0\x94\xfd\xa3\x04(\x19\xaf>f)\x00\xe1\xb9+CX\xed\xa6\xe9%\x90\x8a\x19\a\xa2\x84\u054fc\xe0\x00\x00\u07d4\xfd\xa6\x81\x0e\xa5\xac\x98]o\xfb\xf1\xc5\x11\xf1\xc1B\xed\xcf\xdd\xf7\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfd\xb39D\xf26\x06\x15\xe5\xbe#\x95w\u0221\x9b\xa5-\x98\x87\x89 \x9d\x92/RY\xc5\x00\x00\u07d4\xfd\xbaSY\xf7\xec;\xc7p\xacI\x97]\x84N\xc9qbV\xf1\x8965\u026d\xc5\u07a0\x00\x00\xe0\x94\xfd\xc4\xd4vZ\x94/[\xf9i1\xa9\xe8\xccz\xb8\xb7W\xffL\x8a\x12lG\x8a\x0e>\xa8`\x00\x00\xe0\x94\xfd\xcd]\x80\xb1\x05\x89zW\xab\xc4xev\x8b)\x00RB\x95\x8a\x01Z\xf1\u05cbX\xc4\x00\x00\x00\u0794\xfd\xd1\x19_y}O5q}\x15\xe6\xf9\x81\n\x9a?\xf5T`\x88\xfc\x93c\x92\x80\x1c\x00\x00\u07d4\xfd\xd5\x02\xa7N\x81;\u03e3U\xce\xda<\x17ojhq\xaf\u007f\x89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfd\u357c\vm\\\xbbL\x1d\x8f\xea>\vK\xffc^\x9d\xb7\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\xea\xac*\xcf\x1d\x13\x8e\x19\xf2\xfc?\x9f\xb7E\x92\xe3\ud04a\x89$=M\x18\"\x9c\xa2\x00\x00\u07d4\xfd\xec\xc8-\xdf\xc5a\x92\xe2oV<=h\xcbTJ\x96\xbf\xed\x89\x17\xda:\x04\u01f3\xe0\x00\x00\u07d4\xfd\xf4#C\x01\x9b\v\fk\xf2`\xb1s\xaf\xab~E\xb9\xd6!\x89lj\xccg\u05f1\xd4\x00\x00\u07d4\xfd\xf4I\xf1\b\xc6\xfbOZ+\b\x1e\xed~E\u645eM%\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfd\xfda4\xc0J\x8a\xb7\xeb\x16\xf0\x06C\xf8\xfe\xd7\u06aa\ucc89\x15\xaf\x1dx\xb5\x8c@\x00\x00\u07d4\xfe\x00\xbfC\x99\x11\xa5S\x98-\xb68\x03\x92E\xbc\xf02\xdb\u0709\x15[\xd90\u007f\x9f\xe8\x00\x00\u07d4\xfe\x01n\xc1~\xc5\xf1\x0e;\xb9\x8f\xf4\xa1\xed\xa0E\x15v\x82\xab\x89\x14_T\x02\xe7\xb2\xe6\x00\x00\u07d4\xfe\x0e0\xe2\x14)\rt=\xd3\x0e\xb0\x82\xf1\xf0\xa5\"Z\xdea\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfe!\v\x8f\x04\xdcmOv!j\xcf\xcb\u055b\xa8;\xe9\xb60\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfe\"\xa0\xb3\x88f\x8d\x1a\xe2d>w\x1d\xac\xf3\x8aCB#\u0309\xd8\xdb^\xbd{&8\x00\x00\u07d4\xfe6&\x88\x84_\xa2D\u0300~K\x110\xeb7A\xa8\x05\x1e\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfe8'\xd5v0\u03c7a\xd5\x12y{\v\x85\x8eG\x8b\xbd\x12\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfeA\x8bB\x1a\x9cm76\x02y\x04u\xd20>\x11\xa7Y0\x897\b\xba\xed=h\x90\x00\x00\u07d4\xfeBI\x12yP\xe2\xf8\x96\xec\x0e~.=\x05Z\xab\x10U\x0f\x89$=M\x18\"\x9c\xa2\x00\x00\xe0\x94\xfeM\x84\x03!o\xd5qW+\xf1\xbd\xb0\x1d\x00W\x89x\u0588\x8a\x02\x15\xf85\xbcv\x9d\xa8\x00\x00\u07d4\xfeS\xb9I\x89\u0619d\xda aS\x95&\xbb\xe9y\xdd.\xa9\x89h\xa8u\a>)$\x00\x00\u07d4\xfeT\x9b\xbf\xe6G@\x18\x98\x92\x93%8\u06afF\u04b6\x1dO\x89\x02+\x1c\x8c\x12'\xa0\x00\x00\xe0\x94\xfea]\x97\\\b\x87\xe0\xc9\x11>\xc7)\x84 \xa7\x93\xaf\x8b\x96\x8a\x01\xb1\xaeMn.\xf5\x00\x00\x00\u07d4\xfee\xc4\x18\x8dy\"Wi\td D\xfd\xc5#\x95V\x01e\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfei\u007f\xf2,\xa5G\xbf\xc9^3\xd9`\xda`\\gc\xf3[\x89G\xd4\x11\x9f\xd9`\x94\x00\x00\u07d4\xfej\x89[y\\\xb4\xbf\x85\x90=<\xe0\x9cZ\xa49S\u04ff\x89\xb8Pz\x82\a( \x00\x00\u07d4\xfeo_B\xb6\x19;\x1a\xd1b\x06\u4bf5#\x9dM}\xb4^\x89]\u0212\xaa\x111\xc8\x00\x00\u07d4\xfep\x11\xb6\x98\xbf3q\x13-tE\xb1\x9e\xb5\xb0\x945j\xee\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x80\xe9#-\xea\xff\x19\xba\xf9\x98i\x88:K\xdf\x00\x04\xe5<\x89.b\xf2\ni\xbe@\x00\x00\u07d4\xfe\x8en6eW\r\xffz\x1b\xdaiz\xa5\x89\xc0\xb4\xe9\x02J\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x8f\x1f\u072b\u007f\xbe\u0266\xa3\xfc\xc5\aa\x96\x00P\\6\xa3\x89\x01\x11du\x9f\xfb2\x00\x00\u07d4\xfe\x91\xec\xcf+\xd5f\xaf\xa1\x16\x96\xc5\x04\x9f\xa8Lic\nR\x89i*\xe8\x89p\x81\xd0\x00\x00\u07d4\xfe\x96\xc4\xcd8\x15b@\x1a\xa3*\x86\xe6[\x9dR\xfa\x8a\xee'\x89\x8f\x1d\\\x1c\xae7@\x00\x00\u07d4\xfe\x98\xc6d\xc3\xe4G\xa9^i\xbdX!q\xb7\x17n\xa2\xa6\x85\x89\xd8\xd7&\xb7\x17z\x80\x00\x00\u07d4\xfe\x9a\xd1.\xf0]m\x90&\x1f\x96\xc84\n\x03\x81\x97M\xf4w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\x9c\x0f\xff\xef\xb8\x03\b\x12V\xc0\xcfMfY\xe6\xd3>\xb4\xfb\x89R\xd5B\x80O\x1c\xe0\x00\x00\u07d4\xfe\x9c\xfc;\xb2\x93\u0772\x85\xe6%\xf3X/t\xa6\xb0\xa5\xa6\u0349j\xcb=\xf2~\x1f\x88\x00\x00\xe0\x94\xfe\x9e\x11\x97\u05d7JvH\xdc\u01e01\x12\xa8\x8e\xdb\xc9\x04]\x8a\x01\n\xfc\x1a\xde;N\xd4\x00\x00\xe0\x94\xfe\xac\xa2\xactbK\xf3H\xda\u0258QC\xcf\xd6R\xa4\xbeU\x8a\x05\x89\u007f\u02f0)\x14\b\x80\x00\u07d4\xfe\xad\x18\x03\xe5\xe77\xa6\x8e\x18G-\x9a\xc7\x15\xf0\x99L\u00be\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\u07d4\xfe\xb8\xb8\xe2\xafqj\xe4\x1f\xc7\xc0K\xcf)T\x01VF\x1ek\x89TQt\xa5(\xa7z\x00\x00\u07d4\xfe\xb9-0\xbf\x01\xff\x9a\x19\x01flUsS+\xfa\a\xee\xec\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xfe\xbc1s\xbc\x90r\x13cT\x00+{O\xb3\xbf\xc5?\"\xf1\x89\x14\x0e\xc8\x0f\xa7\xee\x88\x00\x00\u07d4\xfe\xbdH\xd0\xff\xdb\xd5el\xd5\xe6\x866:a\x14R(\xf2y\x89\x97\xc9\xceL\xf6\xd5\xc0\x00\x00\u07d4\xfe\xbd\x9f\x81\xcfx\xbd_\xb6\u0139\xa2K\xd4\x14\xbb\x9b\xfaLN\x89k\xe1\x0f\xb8\xedn\x13\x80\x00\u07d4\xfe\xc0o\xe2{D\u01c4\xb29n\xc9/{\x92:\xd1~\x90w\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xfe\xc1NT\x85\xde+>\xef^t\xc4aF\u06ceEN\x035\x89\t\xb4\x1f\xbf\x9e\n\xec\x00\x00\u07d4\xfe\xd8Gm\x10\u0544\xb3\x8b\xfag7`\x0e\xf1\x9d5\xc4\x1e\u0609b\xa9\x92\xe5:\n\xf0\x00\x00\u07d4\xfe\xef;n\xab\xc9J\xff\xd31\f\x1cM\x0ee7^\x13\x11\x19\x89\x01\x15\x8eF\t\x13\xd0\x00\x00\u07d4\xfe\xf0\x9dp$?9\xed\x8c\xd8\x00\xbf\x96QG\x9e\x8fJ\xca<\x89\n\u05ce\xbcZ\xc6 \x00\x00\u07d4\xfe\xf3\xb3\u07ad\x1ai&\u051a\xa3+\x12\xc2*\xf5M\x9f\xf9\x85\x8965\u026d\xc5\u07a0\x00\x00\u07d4\xff\v|\xb7\x1d\xa9\xd4\xc1\xean\xcc(\xeb\xdaPLc\xf8/\u04498\x8a\x88]\xf2\xfcl\x00\x00\u07d4\xff\f\xc6\u73c9lk\x93[\x8b\xbd@\x00\x00\u07d4\xff'&)AH\xb8lx\xa97$\x97\xe4Y\x89\x8e\xd3\xfe\xe3\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xff=\xedz@\u04ef\xf0\u05e8\xc4_\xa6\x13j\xa0C=\xb4W\x89lh\xcc\u041b\x02,\x00\x00\u07d4\xff>\xeeW\xc3Mm\xae\x97\r\x8b1\x11\x17\xc55\x86\xcd5\x02\x89\\(=A\x03\x94\x10\x00\x00\u07d4\xff>\xf6\xba\x15\x1c!\xb5\x99\x86\xaed\xf6\xe8\"\x8b\u0262\xc73\x89lk\x93[\x8b\xbd@\x00\x00\u07d4\xffA\xd9\xe1\xb4\xef\xfe\x18\u0630\xd1\xf6?\xc4%_\xb4\xe0l=\x89Hz\x9a0E9D\x00\x00\u07d4\xffE\xcb4\xc9(6M\x9c\xc9\u063b\x0074ta\x8f\x06\xf3\x89\x05k\xc7^-c\x10\x00\x00\xe0\x94\xffI\xa7u\x81N\xc0\x00Q\xa7\x95\xa8u\xde$Y.\xa4\x00\u050a*Z\x05\x8f\u0095\xed\x00\x00\x00\u07d4\xffJ@\x8fP\xe9\xe7!F\xa2\x8c\xe4\xfc\x8d\x90'\x1f\x11n\x84\x89j\xcb=\xf2~\x1f\x88\x00\x00\u07d4\xffM\x9c\x84\x84\xc4\x10T\x89H\xa4\x01\xc2?\x01\xc2@\x01\xc2A\x01\xc2B\x01\xc2C\x01\xc2D\x01\xc2E\x01\xc2F\x01\xc2G\x01\xc2H\x01\xc2I\x01\xc2J\x01\xc2K\x01\xc2L\x01\xc2M\x01\xc2N\x01\xc2O\x01\xc2P\x01\xc2Q\x01\xc2R\x01\xc2S\x01\xc2T\x01\xc2U\x01\xc2V\x01\xc2W\x01\xc2X\x01\xc2Y\x01\xc2Z\x01\xc2[\x01\xc2\\\x01\xc2]\x01\xc2^\x01\xc2_\x01\xc2`\x01\xc2a\x01\xc2b\x01\xc2c\x01\xc2d\x01\xc2e\x01\xc2f\x01\xc2g\x01\xc2h\x01\xc2i\x01\xc2j\x01\xc2k\x01\xc2l\x01\xc2m\x01\xc2n\x01\xc2o\x01\xc2p\x01\xc2q\x01\xc2r\x01\xc2s\x01\xc2t\x01\xc2u\x01\xc2v\x01\xc2w\x01\xc2x\x01\xc2y\x01\xc2z\x01\xc2{\x01\xc2|\x01\xc2}\x01\xc2~\x01\xc2\u007f\x01\u00c1\x80\x01\u00c1\x81\x01\u00c1\x82\x01\u00c1\x83\x01\u00c1\x84\x01\u00c1\x85\x01\u00c1\x86\x01\u00c1\x87\x01\u00c1\x88\x01\u00c1\x89\x01\u00c1\x8a\x01\u00c1\x8b\x01\u00c1\x8c\x01\u00c1\x8d\x01\u00c1\x8e\x01\u00c1\x8f\x01\u00c1\x90\x01\u00c1\x91\x01\u00c1\x92\x01\u00c1\x93\x01\u00c1\x94\x01\u00c1\x95\x01\u00c1\x96\x01\u00c1\x97\x01\u00c1\x98\x01\u00c1\x99\x01\u00c1\x9a\x01\u00c1\x9b\x01\u00c1\x9c\x01\u00c1\x9d\x01\u00c1\x9e\x01\u00c1\x9f\x01\u00c1\xa0\x01\u00c1\xa1\x01\u00c1\xa2\x01\u00c1\xa3\x01\u00c1\xa4\x01\u00c1\xa5\x01\u00c1\xa6\x01\u00c1\xa7\x01\u00c1\xa8\x01\u00c1\xa9\x01\u00c1\xaa\x01\u00c1\xab\x01\u00c1\xac\x01\u00c1\xad\x01\u00c1\xae\x01\u00c1\xaf\x01\u00c1\xb0\x01\u00c1\xb1\x01\u00c1\xb2\x01\u00c1\xb3\x01\u00c1\xb4\x01\u00c1\xb5\x01\u00c1\xb6\x01\u00c1\xb7\x01\u00c1\xb8\x01\u00c1\xb9\x01\u00c1\xba\x01\u00c1\xbb\x01\u00c1\xbc\x01\u00c1\xbd\x01\u00c1\xbe\x01\u00c1\xbf\x01\u00c1\xc0\x01\u00c1\xc1\x01\u00c1\xc2\x01\u00c1\xc3\x01\u00c1\xc4\x01\u00c1\xc5\x01\u00c1\xc6\x01\u00c1\xc7\x01\u00c1\xc8\x01\u00c1\xc9\x01\u00c1\xca\x01\u00c1\xcb\x01\u00c1\xcc\x01\u00c1\xcd\x01\u00c1\xce\x01\u00c1\xcf\x01\u00c1\xd0\x01\u00c1\xd1\x01\u00c1\xd2\x01\u00c1\xd3\x01\u00c1\xd4\x01\u00c1\xd5\x01\u00c1\xd6\x01\u00c1\xd7\x01\u00c1\xd8\x01\u00c1\xd9\x01\u00c1\xda\x01\u00c1\xdb\x01\u00c1\xdc\x01\u00c1\xdd\x01\u00c1\xde\x01\u00c1\xdf\x01\u00c1\xe0\x01\u00c1\xe1\x01\u00c1\xe2\x01\u00c1\xe3\x01\u00c1\xe4\x01\u00c1\xe5\x01\u00c1\xe6\x01\u00c1\xe7\x01\u00c1\xe8\x01\u00c1\xe9\x01\u00c1\xea\x01\u00c1\xeb\x01\u00c1\xec\x01\u00c1\xed\x01\u00c1\xee\x01\u00c1\xef\x01\u00c1\xf0\x01\u00c1\xf1\x01\u00c1\xf2\x01\u00c1\xf3\x01\u00c1\xf4\x01\u00c1\xf5\x01\u00c1\xf6\x01\u00c1\xf7\x01\u00c1\xf8\x01\u00c1\xf9\x01\u00c1\xfa\x01\u00c1\xfb\x01\u00c1\xfc\x01\u00c1\xfd\x01\u00c1\xfe\x01\u00c1\xff\x01\xe0\x94L*\xe4\x82Y5\x05\xf0\x16<\xde\xfc\a>\x81\xc6<\xdaA\a\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe0\x94\xa8\xe8\xf1G2e\x8eKQ\xe8q\x191\x05:\x8ai\xba\xf2\xb1\x8a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\xe1\x94\u0665\x17\x9f\t\x1d\x85\x05\x1d<\x98'\x85\xef\xd1E\\\uc199\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe1\x94\u08bdBX\xd2v\x887\xba\xa2j(\xfeq\xdc\a\x9f\x84\u01cbJG\xe3\xc1$H\xf4\xad\x00\x00\x00" -const sepoliaAllocData = "\xf9\x01\xee\u0791i\x16\xa8{\x823?BE\x04f#\xb27\x94\xc6\\\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe1\x94\x10\xf5\xd4XT\xe08\a\x14\x85\xac\x9e@#\b\u03c0\xd2\xd2\xfe\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\u0794y\x9d2\x9e_X4\x19\x16|\xd7\"\x96$\x85\x92n3\x8fJ\x88\r\u0db3\xa7d\x00\x00\xe0\x94|\xf5\xb7\x9b\xfe)\x1ag\xab\x02\xb3\x93\xe4V\xcc\xc4\xc2f\xf7S\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x8b\u007f\tw\xbbO\x0f\xbepv\xfa\"\xbc$\xac\xa0CX?^\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa2\xa6\xd949\x14O\xfeM'\xc9\xe0\x88\xdc\u0637\x83\x94bc\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xaa\xec\x869DA\xf9\x15\xbc\xe3\xe6\xab9\x99w\xe9\x90o;i\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u1532\x1c3\xde\x1f\xab?\xa1T\x99\xc6+Y\xfe\f\xc3%\x00 \u044bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xbc\x11)Y6\xaay\u0554\x13\x9d\xe1\xb2\xe1&)AO;\u06ca\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xbe\xef2\xca[\x9a\x19\x8d'\xb4\xe0/LpC\x9f\xe6\x03V\u03ca\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\xd7\xd7lX\xb3\xa5\x19\xe9\xfal\xc4\xd2-\xc0\x17%\x9b\u011f\x1e\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xd7\xed\xdbx\xed)[<\x96)$\x0e\x89$\xfb\x8d\x88t\xdd\u060a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\u0665\x17\x9f\t\x1d\x85\x05\x1d<\x98'\x85\xef\xd1E\\\uc199\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xe2\xe2e\x90(\x147\x84\xd5W\xbc\xeco\xf3\xa0r\x10H\x88\n\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xf4|\xae\x1c\xf7\x9c\xa6u\x8b\xfcx}\xbd!\u6f7eq\x12\xb8\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00" -const holeskyAllocData = "\xf9,\x85\u0080\x01\xc2\x01\x01\xc2\x02\x01\xc2\x03\x01\xc2\x04\x01\xc2\x05\x01\xc2\x06\x01\xc2\a\x01\xc2\b\x01\xc2\t\x01\xc2\n\x01\xc2\v\x01\xc2\f\x01\xc2\r\x01\xc2\x0e\x01\xc2\x0f\x01\xc2\x10\x01\xc2\x11\x01\xc2\x12\x01\xc2\x13\x01\xc2\x14\x01\xc2\x15\x01\xc2\x16\x01\xc2\x17\x01\xc2\x18\x01\xc2\x19\x01\xc2\x1a\x01\xc2\x1b\x01\xc2\x1c\x01\xc2\x1d\x01\xc2\x1e\x01\xc2\x1f\x01\xc2 \x01\xc2!\x01\xc2\"\x01\xc2#\x01\xc2$\x01\xc2%\x01\xc2&\x01\xc2'\x01\xc2(\x01\xc2)\x01\xc2*\x01\xc2+\x01\xc2,\x01\xc2-\x01\xc2.\x01\xc2/\x01\xc20\x01\xc21\x01\xc22\x01\xc23\x01\xc24\x01\xc25\x01\xc26\x01\xc27\x01\xc28\x01\xc29\x01\xc2:\x01\xc2;\x01\xc2<\x01\xc2=\x01\xc2>\x01\xc2?\x01\xc2@\x01\xc2A\x01\xc2B\x01\xc2C\x01\xc2D\x01\xc2E\x01\xc2F\x01\xc2G\x01\xc2H\x01\xc2I\x01\xc2J\x01\xc2K\x01\xc2L\x01\xc2M\x01\xc2N\x01\xc2O\x01\xc2P\x01\xc2Q\x01\xc2R\x01\xc2S\x01\xc2T\x01\xc2U\x01\xc2V\x01\xc2W\x01\xc2X\x01\xc2Y\x01\xc2Z\x01\xc2[\x01\xc2\\\x01\xc2]\x01\xc2^\x01\xc2_\x01\xc2`\x01\xc2a\x01\xc2b\x01\xc2c\x01\xc2d\x01\xc2e\x01\xc2f\x01\xc2g\x01\xc2h\x01\xc2i\x01\xc2j\x01\xc2k\x01\xc2l\x01\xc2m\x01\xc2n\x01\xc2o\x01\xc2p\x01\xc2q\x01\xc2r\x01\xc2s\x01\xc2t\x01\xc2u\x01\xc2v\x01\xc2w\x01\xc2x\x01\xc2y\x01\xc2z\x01\xc2{\x01\xc2|\x01\xc2}\x01\xc2~\x01\xc2\x7f\x01\u00c1\x80\x01\u00c1\x81\x01\u00c1\x82\x01\u00c1\x83\x01\u00c1\x84\x01\u00c1\x85\x01\u00c1\x86\x01\u00c1\x87\x01\u00c1\x88\x01\u00c1\x89\x01\u00c1\x8a\x01\u00c1\x8b\x01\u00c1\x8c\x01\u00c1\x8d\x01\u00c1\x8e\x01\u00c1\x8f\x01\u00c1\x90\x01\u00c1\x91\x01\u00c1\x92\x01\u00c1\x93\x01\u00c1\x94\x01\u00c1\x95\x01\u00c1\x96\x01\u00c1\x97\x01\u00c1\x98\x01\u00c1\x99\x01\u00c1\x9a\x01\u00c1\x9b\x01\u00c1\x9c\x01\u00c1\x9d\x01\u00c1\x9e\x01\u00c1\x9f\x01\u00c1\xa0\x01\u00c1\xa1\x01\u00c1\xa2\x01\u00c1\xa3\x01\u00c1\xa4\x01\u00c1\xa5\x01\u00c1\xa6\x01\u00c1\xa7\x01\u00c1\xa8\x01\u00c1\xa9\x01\u00c1\xaa\x01\u00c1\xab\x01\u00c1\xac\x01\u00c1\xad\x01\u00c1\xae\x01\u00c1\xaf\x01\u00c1\xb0\x01\u00c1\xb1\x01\u00c1\xb2\x01\u00c1\xb3\x01\u00c1\xb4\x01\u00c1\xb5\x01\u00c1\xb6\x01\u00c1\xb7\x01\u00c1\xb8\x01\u00c1\xb9\x01\u00c1\xba\x01\u00c1\xbb\x01\u00c1\xbc\x01\u00c1\xbd\x01\u00c1\xbe\x01\u00c1\xbf\x01\u00c1\xc0\x01\u00c1\xc1\x01\u00c1\xc2\x01\u00c1\xc3\x01\u00c1\xc4\x01\u00c1\xc5\x01\u00c1\xc6\x01\u00c1\xc7\x01\u00c1\xc8\x01\u00c1\xc9\x01\u00c1\xca\x01\u00c1\xcb\x01\u00c1\xcc\x01\u00c1\xcd\x01\u00c1\xce\x01\u00c1\xcf\x01\u00c1\xd0\x01\u00c1\xd1\x01\u00c1\xd2\x01\u00c1\xd3\x01\u00c1\xd4\x01\u00c1\xd5\x01\u00c1\xd6\x01\u00c1\xd7\x01\u00c1\xd8\x01\u00c1\xd9\x01\u00c1\xda\x01\u00c1\xdb\x01\u00c1\xdc\x01\u00c1\xdd\x01\u00c1\xde\x01\u00c1\xdf\x01\u00c1\xe0\x01\u00c1\xe1\x01\u00c1\xe2\x01\u00c1\xe3\x01\u00c1\xe4\x01\u00c1\xe5\x01\u00c1\xe6\x01\u00c1\xe7\x01\u00c1\xe8\x01\u00c1\xe9\x01\u00c1\xea\x01\u00c1\xeb\x01\u00c1\xec\x01\u00c1\xed\x01\u00c1\xee\x01\u00c1\xef\x01\u00c1\xf0\x01\u00c1\xf1\x01\u00c1\xf2\x01\u00c1\xf3\x01\u00c1\xf4\x01\u00c1\xf5\x01\u00c1\xf6\x01\u00c1\xf7\x01\u00c1\xf8\x01\u00c1\xf9\x01\u00c1\xfa\x01\u00c1\xfb\x01\u00c1\xfc\x01\u00c1\xfd\x01\u00c1\xfe\x01\u00c1\xff\x01\u0791i\x16\xa8{\x823?BE\x04f#\xb27\x94\xc6\\\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94\v\xe9I\x92\x8f\xf1\x99\xc9\xeb\xa9\xe1\x10\xdb!\n\xa5\xc9N\xfa\u040b|\x13\xbcK,\x13\x8e\u0344h\xa0\x03\x7f\x05\x8a\x9d\xaf\xady\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xf9!2\x94BBBBBBBBBBBBBBBBBBBB\x80\xf9!\x19\x80\xb9\x18\xd6`\x80`@R`\x046\x10a\x00?W`\x005`\xe0\x1c\x80c\x01\xff\u0267\x14a\x00DW\x80c\"\x89Q\x18\x14a\x00\xa4W\x80cb\x1f\xd10\x14a\x01\xbaW\x80c\xc5\xf2\x89/\x14a\x02DW[`\x00\x80\xfd[4\x80\x15a\x00PW`\x00\x80\xfd[Pa\x00\x90`\x04\x806\x03` \x81\x10\x15a\x00gW`\x00\x80\xfd[P5\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16a\x02kV[`@\x80Q\x91\x15\x15\x82RQ\x90\x81\x90\x03` \x01\x90\xf3[a\x01\xb8`\x04\x806\x03`\x80\x81\x10\x15a\x00\xbaW`\x00\x80\xfd[\x81\x01\x90` \x81\x01\x815d\x01\x00\x00\x00\x00\x81\x11\x15a\x00\xd5W`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x00\xe7W`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01\tW`\x00\x80\xfd[\x91\x93\x90\x92\x90\x91` \x81\x01\x905d\x01\x00\x00\x00\x00\x81\x11\x15a\x01'W`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x019W`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01[W`\x00\x80\xfd[\x91\x93\x90\x92\x90\x91` \x81\x01\x905d\x01\x00\x00\x00\x00\x81\x11\x15a\x01yW`\x00\x80\xfd[\x82\x01\x83` \x82\x01\x11\x15a\x01\x8bW`\x00\x80\xfd[\x805\x90` \x01\x91\x84`\x01\x83\x02\x84\x01\x11d\x01\x00\x00\x00\x00\x83\x11\x17\x15a\x01\xadW`\x00\x80\xfd[\x91\x93P\x91P5a\x03\x04V[\x00[4\x80\x15a\x01\xc6W`\x00\x80\xfd[Pa\x01\xcfa\x10\xb5V[`@\x80Q` \x80\x82R\x83Q\x81\x83\x01R\x83Q\x91\x92\x83\x92\x90\x83\x01\x91\x85\x01\x90\x80\x83\x83`\x00[\x83\x81\x10\x15a\x02\tW\x81\x81\x01Q\x83\x82\x01R` \x01a\x01\xf1V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\x026W\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x92PPP`@Q\x80\x91\x03\x90\xf3[4\x80\x15a\x02PW`\x00\x80\xfd[Pa\x02Ya\x10\xc7V[`@\x80Q\x91\x82RQ\x90\x81\x90\x03` \x01\x90\xf3[`\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x16\x7f\x01\xff\u0267\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x80a\x02\xfeWP\x7f\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x16\x7f\x85d\t\a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14[\x92\x91PPV[`0\x86\x14a\x03]W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`&\x81R` \x01\x80a\x18\x05`&\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` \x84\x14a\x03\xb6W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`6\x81R` \x01\x80a\x17\x9c`6\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[``\x82\x14a\x04\x0fW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`)\x81R` \x01\x80a\x18x`)\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[g\r\u0db3\xa7d\x00\x004\x10\x15a\x04pW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`&\x81R` \x01\x80a\x18R`&\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[c;\x9a\xca\x004\x06\x15a\x04\xcdW`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`3\x81R` \x01\x80a\x17\xd2`3\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[c;\x9a\xca\x004\x04g\xff\xff\xff\xff\xff\xff\xff\xff\x81\x11\x15a\x055W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`'\x81R` \x01\x80a\x18+`'\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[``a\x05@\x82a\x14\xbaV[\x90P\x7fd\x9b\xbcb\xd0\xe3\x13B\xaf\xeaN\\\xd8-@I\xe7\xe1\xee\x91/\xc0\x88\x9a\xa7\x90\x80;\xe3\x908\u0149\x89\x89\x89\x85\x8a\x8aa\x05u` Ta\x14\xbaV[`@\x80Q`\xa0\x80\x82R\x81\x01\x89\x90R\x90\x81\x90` \x82\x01\x90\x82\x01``\x83\x01`\x80\x84\x01`\xc0\x85\x01\x8e\x8e\x80\x82\x847`\x00\x83\x82\x01R`\x1f\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x91\x01\x87\x81\x03\x86R\x8c\x81R` \x01\x90P\x8c\x8c\x80\x82\x847`\x00\x83\x82\x01\x81\x90R`\x1f\x90\x91\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x92\x01\x88\x81\x03\x86R\x8cQ\x81R\x8cQ` \x91\x82\x01\x93\x91\x8e\x01\x92P\x90\x81\x90\x84\x90\x84\x90[\x83\x81\x10\x15a\x06HW\x81\x81\x01Q\x83\x82\x01R` \x01a\x060V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\x06uW\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x86\x81\x03\x83R\x88\x81R` \x01\x89\x89\x80\x82\x847`\x00\x83\x82\x01\x81\x90R`\x1f\x90\x91\x01\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x16\x90\x92\x01\x88\x81\x03\x84R\x89Q\x81R\x89Q` \x91\x82\x01\x93\x91\x8b\x01\x92P\x90\x81\x90\x84\x90\x84\x90[\x83\x81\x10\x15a\x06\xefW\x81\x81\x01Q\x83\x82\x01R` \x01a\x06\xd7V[PPPP\x90P\x90\x81\x01\x90`\x1f\x16\x80\x15a\a\x1cW\x80\x82\x03\x80Q`\x01\x83` \x03a\x01\x00\n\x03\x19\x16\x81R` \x01\x91P[P\x9dPPPPPPPPPPPPPP`@Q\x80\x91\x03\x90\xa1`\x00`\x02\x8a\x8a`\x00`\x80\x1b`@Q` \x01\x80\x84\x84\x80\x82\x847\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x94\x16\x91\x90\x93\x01\x90\x81R`@\x80Q\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x81\x84\x03\x01\x81R`\x10\x90\x92\x01\x90\x81\x90R\x81Q\x91\x95P\x93P\x83\x92P` \x85\x01\x91P\x80\x83\x83[` \x83\x10a\a\xfcW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\a\xbfV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\bYW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\bnW`\x00\x80\xfd[PQ\x90P`\x00`\x02\x80a\b\x84`@\x84\x8a\x8ca\x16\xfeV[`@Q` \x01\x80\x83\x83\x80\x82\x847\x80\x83\x01\x92PPP\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\b\xf8W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\b\xbbV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\tUW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\tjW`\x00\x80\xfd[PQ`\x02a\t{\x89`@\x81\x8da\x16\xfeV[`@Q`\x00\x90` \x01\x80\x84\x84\x80\x82\x847\x91\x90\x91\x01\x92\x83RPP`@\x80Q\x80\x83\x03\x81R` \x92\x83\x01\x91\x82\x90R\x80Q\x90\x94P\x90\x92P\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\t\xf4W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\t\xb7V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\nQW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\nfW`\x00\x80\xfd[PQ`@\x80Q` \x81\x81\x01\x94\x90\x94R\x80\x82\x01\x92\x90\x92R\x80Q\x80\x83\x03\x82\x01\x81R``\x90\x92\x01\x90\x81\x90R\x81Q\x91\x92\x90\x91\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\n\xdaW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\n\x9dV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\v7W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\vLW`\x00\x80\xfd[PQ`@\x80Q` \x81\x01\x85\x81R\x92\x93P`\x00\x92`\x02\x92\x83\x92\x87\x92\x8f\x92\x8f\x92\x01\x83\x83\x80\x82\x847\x80\x83\x01\x92PPP\x93PPPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\v\xd9W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\v\x9cV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\f6W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\fKW`\x00\x80\xfd[PQ`@Q\x86Q`\x02\x91\x88\x91`\x00\x91\x88\x91` \x91\x82\x01\x91\x82\x91\x90\x86\x01\x90\x80\x83\x83[` \x83\x10a\f\xa9W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\flV[`\x01\x83` \x03a\x01\x00\n\x03\x80\x19\x82Q\x16\x81\x84Q\x16\x80\x82\x17\x85RPPPPPP\x90P\x01\x83g\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16g\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x81R`\x18\x01\x82\x81R` \x01\x93PPPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\rNW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\r\x11V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\r\xabW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\r\xc0W`\x00\x80\xfd[PQ`@\x80Q` \x81\x81\x01\x94\x90\x94R\x80\x82\x01\x92\x90\x92R\x80Q\x80\x83\x03\x82\x01\x81R``\x90\x92\x01\x90\x81\x90R\x81Q\x91\x92\x90\x91\x82\x91\x84\x01\x90\x80\x83\x83[` \x83\x10a\x0e4W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\r\xf7V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x0e\x91W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x0e\xa6W`\x00\x80\xfd[PQ\x90P\x85\x81\x14a\x0f\x02W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`T\x81R` \x01\x80a\x17H`T\x919``\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` Tc\xff\xff\xff\xff\x11a\x0f`W`@Q\x7f\b\xc3y\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x81R`\x04\x01\x80\x80` \x01\x82\x81\x03\x82R`!\x81R` \x01\x80a\x17'`!\x919`@\x01\x91PP`@Q\x80\x91\x03\x90\xfd[` \x80T`\x01\x01\x90\x81\x90U`\x00[` \x81\x10\x15a\x10\xa9W\x81`\x01\x16`\x01\x14\x15a\x0f\xa0W\x82`\x00\x82` \x81\x10a\x0f\x91W\xfe[\x01UPa\x10\xac\x95PPPPPPV[`\x02`\x00\x82` \x81\x10a\x0f\xafW\xfe[\x01T\x84`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x10%W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x0f\xe8V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x10\x82W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x10\x97W`\x00\x80\xfd[PQ\x92P`\x02\x82\x04\x91P`\x01\x01a\x0fnV[P\xfe[PPPPPPPV[``a\x10\xc2` Ta\x14\xbaV[\x90P\x90V[` T`\x00\x90\x81\x90\x81[` \x81\x10\x15a\x12\xf0W\x81`\x01\x16`\x01\x14\x15a\x11\xe6W`\x02`\x00\x82` \x81\x10a\x10\xf5W\xfe[\x01T\x84`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x11kW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x11.V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x11\xc8W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x11\xddW`\x00\x80\xfd[PQ\x92Pa\x12\xe2V[`\x02\x83`!\x83` \x81\x10a\x11\xf6W\xfe[\x01T`@Q` \x01\x80\x83\x81R` \x01\x82\x81R` \x01\x92PPP`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Q\x80\x82\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x12kW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x12.V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x12\xc8W=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x12\xddW`\x00\x80\xfd[PQ\x92P[`\x02\x82\x04\x91P`\x01\x01a\x10\xd1V[P`\x02\x82a\x12\xff` Ta\x14\xbaV[`\x00`@\x1b`@Q` \x01\x80\x84\x81R` \x01\x83\x80Q\x90` \x01\x90\x80\x83\x83[` \x83\x10a\x13ZW\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x13\x1dV[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x95\x90\x95\x16\x92\x01\x91\x82RP`@\x80Q\x80\x83\x03\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x01\x81R`\x18\x90\x92\x01\x90\x81\x90R\x81Q\x91\x95P\x93P\x83\x92\x85\x01\x91P\x80\x83\x83[` \x83\x10a\x14?W\x80Q\x82R\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x90\x92\x01\x91` \x91\x82\x01\x91\x01a\x14\x02V[Q\x81Q` \x93\x84\x03a\x01\x00\n\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x19\x90\x92\x16\x91\x16\x17\x90R`@Q\x91\x90\x93\x01\x94P\x91\x92PP\x80\x83\x03\x81\x85Z\xfa\x15\x80\x15a\x14\x9cW=`\x00\x80>=`\x00\xfd[PPP`@Q=` \x81\x10\x15a\x14\xb1W`\x00\x80\xfd[PQ\x92PPP\x90V[`@\x80Q`\b\x80\x82R\x81\x83\x01\x90\x92R``\x91` \x82\x01\x81\x806\x837\x01\x90PP\x90P`\xc0\x82\x90\x1b\x80`\a\x1a`\xf8\x1b\x82`\x00\x81Q\x81\x10a\x14\xf4W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x06\x1a`\xf8\x1b\x82`\x01\x81Q\x81\x10a\x157W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x05\x1a`\xf8\x1b\x82`\x02\x81Q\x81\x10a\x15zW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x04\x1a`\xf8\x1b\x82`\x03\x81Q\x81\x10a\x15\xbdW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x03\x1a`\xf8\x1b\x82`\x04\x81Q\x81\x10a\x16\x00W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x02\x1a`\xf8\x1b\x82`\x05\x81Q\x81\x10a\x16CW\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x01\x1a`\xf8\x1b\x82`\x06\x81Q\x81\x10a\x16\x86W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SP\x80`\x00\x1a`\xf8\x1b\x82`\a\x81Q\x81\x10a\x16\xc9W\xfe[` \x01\x01\x90~\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x19\x16\x90\x81`\x00\x1a\x90SPP\x91\x90PV[`\x00\x80\x85\x85\x11\x15a\x17\rW\x81\x82\xfd[\x83\x86\x11\x15a\x17\x19W\x81\x82\xfd[PP\x82\x01\x93\x91\x90\x92\x03\x91PV\xfeDepositContract: merkle tree fullDepositContract: reconstructed DepositData does not match supplied deposit_data_rootDepositContract: invalid withdrawal_credentials lengthDepositContract: deposit value not multiple of gweiDepositContract: invalid pubkey lengthDepositContract: deposit value too highDepositContract: deposit value too lowDepositContract: invalid signature length\xa2dipfsX\"\x12 \x1d\xd2o7\xa6!p0\t\xab\xf1nw\u6713\xdcP\u01dd\xb7\xf6\xcc7T>>\x0e=\xec\u0717dsolcC\x00\x06\v\x003\xf9\b<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\xa0\xf5\xa5\xfdB\xd1j 0'\x98\xefn\xd3\t\x97\x9bC\x00=# \xd9\xf0\xe8\xea\x981\xa9'Y\xfbK\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\xa0\xdbV\x11N\x00\xfd\xd4\xc1\xf8\\\x89+\xf3Z\u0268\x92\x89\xaa\xec\xb1\xeb\u0429l\xde`jt\x8b]q\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\xa0\u01c0\t\xfd\xf0\x7f\xc5j\x11\xf1\"7\x06X\xa3S\xaa\xa5B\xedc\xe4LK\xc1_\xf4\xcd\x10Z\xb3<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%\xa0Sm\x98\x83\x7f-\xd1e\xa5]^\xea\xe9\x14\x85\x95Dr\xd5o$m\xf2V\xbf<\xae\x195*\x12<\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\xa0\x9e\xfd\xe0R\xaa\x15B\x9f\xae\x05\xba\xd4\u0431\xd7\xc6M\xa6M\x03\u05e1\x85JX\x8c,\xb8C\f\r0\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\xa0\u060d\xdf\xee\xd4\x00\xa8uU\x96\xb2\x19B\xc1I~\x11L0.a\x18)\x0f\x91\xe6w)v\x04\x1f\xa1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\xa0\x87\xeb\r\u06e5~5\xf6\u0486g8\x02\xa4\xafYu\xe2%\x06\xc7\xcfLd\xbbk\xe5\xee\x11R\x7f,\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\xa0&\x84dv\xfd_\xc5J]C8Qg\xc9QD\xf2d?S<\xc8[\xb9\xd1kx/\x8d}\xb1\x93\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\xa0Pm\x86X-%$\x05\xb8@\x01\x87\x92\xca\u04bf\x12Y\xf1\xefZ\xa5\xf8\x87\xe1<\xb2\xf0\tOQ\xe1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\xa0\xff\xff\n\xd7\xe6Yw/\x954\xc1\x95\xc8\x15\xef\xc4\x01N\xf1\xe1\xda\xedD\x04\xc0c\x85\xd1\x11\x92\xe9+\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\xa0l\xf0A'\xdb\x05D\x1c\xd83\x10zR\xbe\x85(h\x89\x0eC\x17\xe6\xa0*\xb4v\x83\xaau\x96B \xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-\xa0\xb7\xd0_\x87_\x14\x00'\xefQ\x18\xa2${\xbb\x84\u038f/\x0f\x11#b0\x85\xda\xf7\x96\f2\x9f_\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.\xa0\xdfj\xf5\xf5\xbb\xdbk\xe9\uf2a6\x18\u4fc0s\x96\bg\x17\x1e)go\x8b(M\xeaj\b\xa8^\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/\xa0\xb5\x8d\x90\x0f^\x18.\x01t\u0285\x18.\xec\x9f:\t\xf6\xa6\xc0\xdfcw\xa5\x10\xd7\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x009\xa01 o\xa8\nP\xbbj\xbe)\bPX\xf1b\x12!*`\xee\xc8\xf0I\xfe\u02d2\xd8\xc8\xe0\xa8K\xc0\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\xa0!5+\xfe\xcb\xed\xdd\u94c3\x9faL=\xac\n>\xe3uC\xf9\xb4\x12\xb1a\x99\xdc\x15\x8e#\xb5D\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\xa0a\x9e1'$\xbbm|1S\xed\x9d\xe7\x91\xd7d\xa3f\xb3\x89\xaf\x13\u014b\xf8\xa8\xd9\x04\x81\xa4ge\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\xa0|\xdd)\x86&\x82Pb\x8d\f\x10\xe3\x85\u014ca\x91\xe6\xfb\xe0Q\x91\xbc\xc0O\x13?,\xear\xc1\xc4\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\xa0\x84\x890\xbd{\xa8\xca\xc5Fa\a!\x13\xfb'\x88i\xe0{\xb8X\x7f\x919)37M\x01{\xcb\xe1\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xa0\x88i\xff,\"\xb2\x8c\xc1\x05\x10\u06452\x92\x803(\xbeO\xb0\xe8\x04\x95\u8ecd'\x1f[\x88\x966\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xa0\xb5\xfe(\xe7\x9f\x1b\x85\x0f\x86X$l\u9da1\u7d1f\xc0m\xb7\x14>\x8f\xe0\xb4\xf2\xb0\xc5R:\\\xf8B\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xa0\x98^\x92\x9fp\xaf(\u043d\u0469\n\x80\x8f\x97\x7fY||w\x8cH\x9e\x98\u04fd\x89\x10\xd3\x1a\xc0\xf7\xe1\x94F#\x96\u677f\xa4U\xf4\x05\xf4\u0742\xf3\x01J\xf8\x00;r\x8b\xa5o\xa5\xb9\x90\x19\xa5\xc8\x00\x00\x00\xe0\x94I\xdf<\xca&p\xeb\rY\x11F\xb1cY\xfe3nGo)\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94K\xc6V\xb3M\xe28\x96\xfa`i\u0246/5[t\x04\x01\xaf\x8b\bE\x95\x16\x14\x01HJ\x00\x00\x00\xe0\x94M\v\x04\xb4\x05\u01b6,|\xfc:\xe5GYt~,\vFb\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94MIl\xcc(\x05\x8b\x1dt\xb7\xa1\x95Af>!\x15O\x9c\x84\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94P\x9avg\xac\x8d\x03 \xe3ar\xc1\x92Pja\x88\xaa\x84\xf6\x8b|\x13\xbcK,\x13\xfa<]\xc1\xaa\x19;\xc6\x03=\xfd\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94jz\xa9\xb8\x82\xd5\v\xb7\xbc]\xa1\xa2Dq\x9c\x99\xf1/\x06\xa3\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94l\xc99|;8s\x9d\xac\xbf\xaah\xea\xd5\xf5\xd7{\xa5\xf4U\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94s\xb2\xe0\xe5E\x10#\x9e\"\u0313o\vJm\xe1\xac\xf0\xab\u078bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94v,\xa6,\xa2T\x9a\xd8\x06v;:\xa1\xea1|B\x9b\xdb\u068a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94w\x8f_\x13\u013ex\xa3\xa4\xd7\x14\x1b\xcb&\x99\x97\x02\xf4\a\u03cbR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\x83M\xbfZ\x03\xe2\x9c%\xbcUE\x9c\u039c\x02\x1e\xeb\xe6v\xad\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\x87]%\xeeK\xc6\x04\xc7\x1b\xafb6\xa8H\x8f\"9\x9b\xedK\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u150d\xf7\x87\x8d5q\xbe\xf5\xe5\xa7D\xf9b\x87\xc8\xd2\x03\x86\xd7Z\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\x9eAZ\to\xf7vP\u0712]\xeaTe\x85\xb4\xad\xb3\"\xb6\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa0vke\xa4\xf7\xb1\xday\xa1\xafy\xaciTV\uf886D\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa2\x9b\x14JD\x9eAJG,`\u01ea\xf1\xaa\xff\xe3)\x02\x1d\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xa5S\x95Vk\vT9[2F\xf9j\v\xdcK\x8aH=\xf9\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xac\x9b\xa7/\xb6\x1a\xa7\xc3\x1a\x95\xdf\n\x8bn\xbaoA\xef\x87^\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xb0I\x8c\x15\x87\x9d\xb2\xeeTq\u0512l_\xaa%\u0260\x96\x83\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xb0J\xef*=-\x86\xb0\x10\x06\xcc\xd43\x9a.\x94=\x9cd\x80\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\u1531\x9f\xb4\xc1\xf2\x802~`\xed7\xb1\xdcn\xe7u3S\x93\x14\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xbb\x97{.\xe8\xa1\x11\u05c8\xb3G}$ x\u04387\xe7+\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xc2\x1c\xb9\u025c1m\x18c\x14/}\xd8m\xd5Im\x81\xa8\u058a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xc4s\xd4\x12\xdcR\xe3I\x86\"\t\x92L\x89\x81\xb2\xeeB\ah\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\u010e#\xc5\xf6\xe1\xea\v\xae\xf6S\a4\xed\u00d6\x8fy\xaf.\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe1\x94\xc6\xe2E\x99\x91\xbf\xe2|\xcam\x86r/5\xda#\xa1\xe4\u02d7\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xc9\xca+\xa9\xa2}\xe1\xdbX\x9d\x8c3\xab\x8e\u07e2\x11\x1b1\xfb\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xd1\xf7~L\x1cE\x18n\x86S\u0109\xf9\x0e\x00\x8asYr\x96\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe2\x94\u04d9NM2\x02\xdd#\xc8I}\x7fu\xbf\x16G\xd1\xda\x1b\xb1\x8c\x01\x9d\x97\x1eO\xe8@\x1et\x00\x00\x00\xe0\x94\u0726\u9d0e\xa8j\xeb\xfd\xf9\x92\x99I\x12@B)kn4\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xe0\x99\x1e\x84@A\xbeo\x11\xb9\x9d\xa5\xb1\x14\xb6\xbc\xf8N\xbdW\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\u08bdBX\xd2v\x887\xba\xa2j(\xfeq\xdc\a\x9f\x84\u01cbR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\xe0\x94\xea(\xd0\x02\x04/\u0649\x8d\r\xb0\x16\xbe\x97X\xee\xaf\xe3\\\x1e\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe0\x94\xef\xa7EO\x11\x16\x80yu\xa4u\vFi^\x96xP\xde]\x8a\xd3\xc2\x1b\xce\xcc\xed\xa1\x00\x00\x00\xe1\x94\xfb\xfdo\xa9\xf7:\u01a0X\xe0\x12Y\x03L(\x00\x1b\xef\x82G\x8bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00" diff --git a/builder/core/genesis_test.go b/builder/core/genesis_test.go deleted file mode 100644 index 61be0bd25..000000000 --- a/builder/core/genesis_test.go +++ /dev/null @@ -1,328 +0,0 @@ -// 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 core - -import ( - "bytes" - "encoding/json" - "math/big" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/pathdb" -) - -func TestInvalidCliqueConfig(t *testing.T) { - block := DefaultGoerliGenesisBlock() - block.ExtraData = []byte{} - db := rawdb.NewMemoryDatabase() - if _, err := block.Commit(db, triedb.NewDatabase(db, nil)); err == nil { - t.Fatal("Expected error on invalid clique config") - } -} - -func TestSetupGenesis(t *testing.T) { - testSetupGenesis(t, rawdb.HashScheme) - testSetupGenesis(t, rawdb.PathScheme) -} - -func testSetupGenesis(t *testing.T, scheme string) { - var ( - customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50") - customg = Genesis{ - Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)}, - Alloc: types.GenesisAlloc{ - {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, - }, - } - oldcustomg = customg - ) - oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)} - - tests := []struct { - name string - fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error) - wantConfig *params.ChainConfig - wantHash common.Hash - wantErr error - }{ - { - name: "genesis without ChainConfig", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis)) - }, - wantErr: errGenesisNoConfig, - wantConfig: params.AllEthashProtocolChanges, - }, - { - name: "no block in DB, genesis == nil", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) - }, - wantHash: params.MainnetGenesisHash, - wantConfig: params.MainnetChainConfig, - }, - { - name: "mainnet block in DB, genesis == nil", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme))) - return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil) - }, - wantHash: params.MainnetGenesisHash, - wantConfig: params.MainnetChainConfig, - }, - { - name: "custom block in DB, genesis == nil", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - tdb := triedb.NewDatabase(db, newDbConfig(scheme)) - customg.Commit(db, tdb) - return SetupGenesisBlock(db, tdb, nil) - }, - wantHash: customghash, - wantConfig: customg.Config, - }, - { - name: "custom block in DB, genesis == goerli", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - tdb := triedb.NewDatabase(db, newDbConfig(scheme)) - customg.Commit(db, tdb) - return SetupGenesisBlock(db, tdb, DefaultGoerliGenesisBlock()) - }, - wantErr: &GenesisMismatchError{Stored: customghash, New: params.GoerliGenesisHash}, - wantHash: params.GoerliGenesisHash, - wantConfig: params.GoerliChainConfig, - }, - { - name: "compatible config in DB", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - tdb := triedb.NewDatabase(db, newDbConfig(scheme)) - oldcustomg.Commit(db, tdb) - return SetupGenesisBlock(db, tdb, &customg) - }, - wantHash: customghash, - wantConfig: customg.Config, - }, - { - name: "incompatible config in DB", - fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - // Commit the 'old' genesis block with Homestead transition at #2. - // Advance to block #4, past the homestead transition block of customg. - tdb := triedb.NewDatabase(db, newDbConfig(scheme)) - oldcustomg.Commit(db, tdb) - - bc, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(scheme), &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil) - defer bc.Stop() - - _, blocks, _ := GenerateChainWithGenesis(&oldcustomg, ethash.NewFaker(), 4, nil) - bc.InsertChain(blocks) - - // This should return a compatibility error. - return SetupGenesisBlock(db, tdb, &customg) - }, - wantHash: customghash, - wantConfig: customg.Config, - wantErr: ¶ms.ConfigCompatError{ - What: "Homestead fork block", - StoredBlock: big.NewInt(2), - NewBlock: big.NewInt(3), - RewindToBlock: 1, - }, - }, - } - - for _, test := range tests { - db := rawdb.NewMemoryDatabase() - config, hash, err := test.fn(db) - // Check the return values. - if !reflect.DeepEqual(err, test.wantErr) { - spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} - t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) - } - if !reflect.DeepEqual(config, test.wantConfig) { - t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig) - } - if hash != test.wantHash { - t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex()) - } else if err == nil { - // Check database content. - stored := rawdb.ReadBlock(db, test.wantHash, 0) - if stored.Hash() != test.wantHash { - t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) - } - } - } -} - -// TestGenesisHashes checks the congruity of default genesis data to -// corresponding hardcoded genesis hash values. -func TestGenesisHashes(t *testing.T) { - for i, c := range []struct { - genesis *Genesis - want common.Hash - }{ - {DefaultGenesisBlock(), params.MainnetGenesisHash}, - {DefaultGoerliGenesisBlock(), params.GoerliGenesisHash}, - {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, - } { - // Test via MustCommit - db := rawdb.NewMemoryDatabase() - if have := c.genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)).Hash(); have != c.want { - t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) - } - // Test via ToBlock - if have := c.genesis.ToBlock().Hash(); have != c.want { - t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) - } - } -} - -func TestGenesis_Commit(t *testing.T) { - genesis := &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.TestChainConfig, - // difficulty is nil - } - - db := rawdb.NewMemoryDatabase() - genesisBlock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) - - if genesis.Difficulty != nil { - t.Fatalf("assumption wrong") - } - - // This value should have been set as default in the ToBlock method. - if genesisBlock.Difficulty().Cmp(params.GenesisDifficulty) != 0 { - t.Errorf("assumption wrong: want: %d, got: %v", params.GenesisDifficulty, genesisBlock.Difficulty()) - } - - // Expect the stored total difficulty to be the difficulty of the genesis block. - stored := rawdb.ReadTd(db, genesisBlock.Hash(), genesisBlock.NumberU64()) - - if stored.Cmp(genesisBlock.Difficulty()) != 0 { - t.Errorf("inequal difficulty; stored: %v, genesisBlock: %v", stored, genesisBlock.Difficulty()) - } -} - -func TestReadWriteGenesisAlloc(t *testing.T) { - var ( - db = rawdb.NewMemoryDatabase() - alloc = &types.GenesisAlloc{ - {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, - {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}}, - } - hash, _ = hashAlloc(alloc, false) - ) - blob, _ := json.Marshal(alloc) - rawdb.WriteGenesisStateSpec(db, hash, blob) - - var reload types.GenesisAlloc - err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash)) - if err != nil { - t.Fatalf("Failed to load genesis state %v", err) - } - if len(reload) != len(*alloc) { - t.Fatal("Unexpected genesis allocation") - } - for addr, account := range reload { - want, ok := (*alloc)[addr] - if !ok { - t.Fatal("Account is not found") - } - if !reflect.DeepEqual(want, account) { - t.Fatal("Unexpected account") - } - } -} - -func newDbConfig(scheme string) *triedb.Config { - if scheme == rawdb.HashScheme { - return triedb.HashDefaults - } - return &triedb.Config{PathDB: pathdb.Defaults} -} - -func TestVerkleGenesisCommit(t *testing.T) { - var verkleTime uint64 = 0 - verkleConfig := ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: false, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: nil, - ShanghaiTime: &verkleTime, - CancunTime: &verkleTime, - PragueTime: &verkleTime, - VerkleTime: &verkleTime, - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - Ethash: nil, - Clique: nil, - } - - genesis := &Genesis{ - BaseFee: big.NewInt(params.InitialBaseFee), - Config: verkleConfig, - Timestamp: verkleTime, - Difficulty: big.NewInt(0), - Alloc: types.GenesisAlloc{ - {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, - }, - } - - expected := common.Hex2Bytes("14398d42be3394ff8d50681816a4b7bf8d8283306f577faba2d5bc57498de23b") - got := genesis.ToBlock().Root().Bytes() - if !bytes.Equal(got, expected) { - t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got) - } - - db := rawdb.NewMemoryDatabase() - triedb := triedb.NewDatabase(db, &triedb.Config{IsVerkle: true, PathDB: pathdb.Defaults}) - block := genesis.MustCommit(db, triedb) - if !bytes.Equal(block.Root().Bytes(), expected) { - t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got) - } - - // Test that the trie is verkle - if !triedb.IsVerkle() { - t.Fatalf("expected trie to be verkle") - } - - if !rawdb.ExistsAccountTrieNode(db, nil) { - t.Fatal("could not find node") - } -} diff --git a/builder/core/headerchain.go b/builder/core/headerchain.go deleted file mode 100644 index 519a32ab8..000000000 --- a/builder/core/headerchain.go +++ /dev/null @@ -1,678 +0,0 @@ -// 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 core - -import ( - crand "crypto/rand" - "errors" - "fmt" - "math" - "math/big" - mrand "math/rand" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -const ( - headerCacheLimit = 512 - tdCacheLimit = 1024 - numberCacheLimit = 2048 -) - -// HeaderChain implements the basic block header chain logic that is shared by -// core.BlockChain and light.LightChain. It is not usable in itself, only as -// a part of either structure. -// -// HeaderChain is responsible for maintaining the header chain including the -// header query and updating. -// -// The components maintained by headerchain includes: (1) total difficulty -// (2) header (3) block hash -> number mapping (4) canonical number -> hash mapping -// and (5) head header flag. -// -// It is not thread safe either, the encapsulating chain structures should do -// the necessary mutex locking/unlocking. -type HeaderChain struct { - config *params.ChainConfig - chainDb ethdb.Database - genesisHeader *types.Header - - currentHeader atomic.Value // Current head of the header chain (may be above the block chain!) - currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time) - - headerCache *lru.Cache[common.Hash, *types.Header] - tdCache *lru.Cache[common.Hash, *big.Int] // most recent total difficulties - numberCache *lru.Cache[common.Hash, uint64] // most recent block numbers - - procInterrupt func() bool - - rand *mrand.Rand - engine consensus.Engine -} - -// NewHeaderChain creates a new HeaderChain structure. ProcInterrupt points -// to the parent's interrupt semaphore. -func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) { - // Seed a fast but crypto originating random generator - seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64)) - if err != nil { - return nil, err - } - hc := &HeaderChain{ - config: config, - chainDb: chainDb, - headerCache: lru.NewCache[common.Hash, *types.Header](headerCacheLimit), - tdCache: lru.NewCache[common.Hash, *big.Int](tdCacheLimit), - numberCache: lru.NewCache[common.Hash, uint64](numberCacheLimit), - procInterrupt: procInterrupt, - rand: mrand.New(mrand.NewSource(seed.Int64())), - engine: engine, - } - hc.genesisHeader = hc.GetHeaderByNumber(0) - if hc.genesisHeader == nil { - return nil, ErrNoGenesis - } - hc.currentHeader.Store(hc.genesisHeader) - if head := rawdb.ReadHeadBlockHash(chainDb); head != (common.Hash{}) { - if chead := hc.GetHeaderByHash(head); chead != nil { - hc.currentHeader.Store(chead) - } - } - hc.currentHeaderHash = hc.CurrentHeader().Hash() - headHeaderGauge.Update(hc.CurrentHeader().Number.Int64()) - return hc, nil -} - -// GetBlockNumber retrieves the block number belonging to the given hash -// from the cache or database -func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 { - if cached, ok := hc.numberCache.Get(hash); ok { - return &cached - } - number := rawdb.ReadHeaderNumber(hc.chainDb, hash) - if number != nil { - hc.numberCache.Add(hash, *number) - } - return number -} - -type headerWriteResult struct { - status WriteStatus - ignored int - imported int - lastHash common.Hash - lastHeader *types.Header -} - -// Reorg reorgs the local canonical chain into the specified chain. The reorg -// can be classified into two cases: (a) extend the local chain (b) switch the -// head to the given header. -func (hc *HeaderChain) Reorg(headers []*types.Header) error { - // Short circuit if nothing to reorg. - if len(headers) == 0 { - return nil - } - // If the parent of the (first) block is already the canon header, - // we don't have to go backwards to delete canon blocks, but simply - // pile them onto the existing chain. Otherwise, do the necessary - // reorgs. - var ( - first = headers[0] - last = headers[len(headers)-1] - batch = hc.chainDb.NewBatch() - ) - if first.ParentHash != hc.currentHeaderHash { - // Delete any canonical number assignments above the new head - for i := last.Number.Uint64() + 1; ; i++ { - hash := rawdb.ReadCanonicalHash(hc.chainDb, i) - if hash == (common.Hash{}) { - break - } - rawdb.DeleteCanonicalHash(batch, i) - } - // Overwrite any stale canonical number assignments, going - // backwards from the first header in this import until the - // cross link between two chains. - var ( - header = first - headNumber = header.Number.Uint64() - headHash = header.Hash() - ) - for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash { - rawdb.WriteCanonicalHash(batch, headHash, headNumber) - if headNumber == 0 { - break // It shouldn't be reached - } - headHash, headNumber = header.ParentHash, header.Number.Uint64()-1 - header = hc.GetHeader(headHash, headNumber) - if header == nil { - return fmt.Errorf("missing parent %d %x", headNumber, headHash) - } - } - } - // Extend the canonical chain with the new headers - for i := 0; i < len(headers)-1; i++ { - hash := headers[i+1].ParentHash // Save some extra hashing - num := headers[i].Number.Uint64() - rawdb.WriteCanonicalHash(batch, hash, num) - rawdb.WriteHeadHeaderHash(batch, hash) - } - // Write the last header - hash := headers[len(headers)-1].Hash() - num := headers[len(headers)-1].Number.Uint64() - rawdb.WriteCanonicalHash(batch, hash, num) - rawdb.WriteHeadHeaderHash(batch, hash) - - if err := batch.Write(); err != nil { - return err - } - // Last step update all in-memory head header markers - hc.currentHeaderHash = last.Hash() - hc.currentHeader.Store(types.CopyHeader(last)) - headHeaderGauge.Update(last.Number.Int64()) - return nil -} - -// WriteHeaders writes a chain of headers into the local chain, given that the -// parents are already known. The chain head header won't be updated in this -// function, the additional SetCanonical is expected in order to finish the entire -// procedure. -func (hc *HeaderChain) WriteHeaders(headers []*types.Header) (int, error) { - if len(headers) == 0 { - return 0, nil - } - ptd := hc.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1) - if ptd == nil { - return 0, consensus.ErrUnknownAncestor - } - var ( - newTD = new(big.Int).Set(ptd) // Total difficulty of inserted chain - inserted []rawdb.NumberHash // Ephemeral lookup of number/hash for the chain - parentKnown = true // Set to true to force hc.HasHeader check the first iteration - batch = hc.chainDb.NewBatch() - ) - for i, header := range headers { - var hash common.Hash - // The headers have already been validated at this point, so we already - // know that it's a contiguous chain, where - // headers[i].Hash() == headers[i+1].ParentHash - if i < len(headers)-1 { - hash = headers[i+1].ParentHash - } else { - hash = header.Hash() - } - number := header.Number.Uint64() - newTD.Add(newTD, header.Difficulty) - - // If the parent was not present, store it - // If the header is already known, skip it, otherwise store - alreadyKnown := parentKnown && hc.HasHeader(hash, number) - if !alreadyKnown { - // Irrelevant of the canonical status, write the TD and header to the database. - rawdb.WriteTd(batch, hash, number, newTD) - hc.tdCache.Add(hash, new(big.Int).Set(newTD)) - - rawdb.WriteHeader(batch, header) - inserted = append(inserted, rawdb.NumberHash{Number: number, Hash: hash}) - hc.headerCache.Add(hash, header) - hc.numberCache.Add(hash, number) - } - parentKnown = alreadyKnown - } - // Skip the slow disk write of all headers if interrupted. - if hc.procInterrupt() { - log.Debug("Premature abort during headers import") - return 0, errors.New("aborted") - } - // Commit to disk! - if err := batch.Write(); err != nil { - log.Crit("Failed to write headers", "error", err) - } - return len(inserted), nil -} - -// writeHeadersAndSetHead writes a batch of block headers and applies the last -// header as the chain head if the fork choicer says it's ok to update the chain. -// Note: This method is not concurrent-safe with inserting blocks simultaneously -// into the chain, as side effects caused by reorganisations cannot be emulated -// without the real blocks. Hence, writing headers directly should only be done -// in two scenarios: pure-header mode of operation (light clients), or properly -// separated header/block phases (non-archive clients). -func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *ForkChoice) (*headerWriteResult, error) { - inserted, err := hc.WriteHeaders(headers) - if err != nil { - return nil, err - } - var ( - lastHeader = headers[len(headers)-1] - lastHash = headers[len(headers)-1].Hash() - result = &headerWriteResult{ - status: NonStatTy, - ignored: len(headers) - inserted, - imported: inserted, - lastHash: lastHash, - lastHeader: lastHeader, - } - ) - // Ask the fork choicer if the reorg is necessary - if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil { - return nil, err - } else if !reorg { - if inserted != 0 { - result.status = SideStatTy - } - return result, nil - } - // Special case, all the inserted headers are already on the canonical - // header chain, skip the reorg operation. - if hc.GetCanonicalHash(lastHeader.Number.Uint64()) == lastHash && lastHeader.Number.Uint64() <= hc.CurrentHeader().Number.Uint64() { - return result, nil - } - // Apply the reorg operation - if err := hc.Reorg(headers); err != nil { - return nil, err - } - result.status = CanonStatTy - return result, nil -} - -func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header) (int, error) { - // Do a sanity check that the provided chain is actually ordered and linked - for i := 1; i < len(chain); i++ { - if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 { - hash := chain[i].Hash() - parentHash := chain[i-1].Hash() - // Chain broke ancestry, log a message (programming error) and skip insertion - log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", hash, - "parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", parentHash) - - return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])", i-1, chain[i-1].Number, - parentHash.Bytes()[:4], i, chain[i].Number, hash.Bytes()[:4], chain[i].ParentHash[:4]) - } - // If the header is a banned one, straight out abort - if BadHashes[chain[i].ParentHash] { - return i - 1, ErrBannedHash - } - // If it's the last header in the cunk, we need to check it too - if i == len(chain)-1 && BadHashes[chain[i].Hash()] { - return i, ErrBannedHash - } - } - // Start the parallel verifier - abort, results := hc.engine.VerifyHeaders(hc, chain) - defer close(abort) - - // Iterate over the headers and ensure they all check out - for i := range chain { - // If the chain is terminating, stop processing blocks - if hc.procInterrupt() { - log.Debug("Premature abort during headers verification") - return 0, errors.New("aborted") - } - // Otherwise wait for headers checks and ensure they pass - if err := <-results; err != nil { - return i, err - } - } - - return 0, nil -} - -// InsertHeaderChain inserts the given headers and does the reorganisations. -// -// The validity of the headers is NOT CHECKED by this method, i.e. they need to be -// validated by ValidateHeaderChain before calling InsertHeaderChain. -// -// This insert is all-or-nothing. If this returns an error, no headers were written, -// otherwise they were all processed successfully. -// -// The returned 'write status' says if the inserted headers are part of the canonical chain -// or a side chain. -func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time, forker *ForkChoice) (WriteStatus, error) { - if hc.procInterrupt() { - return 0, errors.New("aborted") - } - res, err := hc.writeHeadersAndSetHead(chain, forker) - if err != nil { - return 0, err - } - // Report some public statistics so the user has a clue what's going on - context := []interface{}{ - "count", res.imported, - "elapsed", common.PrettyDuration(time.Since(start)), - } - if last := res.lastHeader; last != nil { - context = append(context, "number", last.Number, "hash", res.lastHash) - if timestamp := time.Unix(int64(last.Time), 0); time.Since(timestamp) > time.Minute { - context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) - } - } - if res.ignored > 0 { - context = append(context, []interface{}{"ignored", res.ignored}...) - } - log.Debug("Imported new block headers", context...) - return res.status, err -} - -// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or -// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the -// number of blocks to be individually checked before we reach the canonical chain. -// -// Note: ancestor == 0 returns the same block, 1 returns its parent and so on. -func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { - if ancestor > number { - return common.Hash{}, 0 - } - if ancestor == 1 { - // in this case it is cheaper to just read the header - if header := hc.GetHeader(hash, number); header != nil { - return header.ParentHash, number - 1 - } - return common.Hash{}, 0 - } - for ancestor != 0 { - if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { - ancestorHash := rawdb.ReadCanonicalHash(hc.chainDb, number-ancestor) - if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash { - number -= ancestor - return ancestorHash, number - } - } - if *maxNonCanonical == 0 { - return common.Hash{}, 0 - } - *maxNonCanonical-- - ancestor-- - header := hc.GetHeader(hash, number) - if header == nil { - return common.Hash{}, 0 - } - hash = header.ParentHash - number-- - } - return hash, number -} - -// GetTd retrieves a block's total difficulty in the canonical chain from the -// database by hash and number, caching it if found. -func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int { - // Short circuit if the td's already in the cache, retrieve otherwise - if cached, ok := hc.tdCache.Get(hash); ok { - return cached - } - td := rawdb.ReadTd(hc.chainDb, hash, number) - if td == nil { - return nil - } - // Cache the found body for next time and return - hc.tdCache.Add(hash, td) - return td -} - -// GetHeader retrieves a block header from the database by hash and number, -// caching it if found. -func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header { - // Short circuit if the header's already in the cache, retrieve otherwise - if header, ok := hc.headerCache.Get(hash); ok { - return header - } - header := rawdb.ReadHeader(hc.chainDb, hash, number) - if header == nil { - return nil - } - // Cache the found header for next time and return - hc.headerCache.Add(hash, header) - return header -} - -// GetHeaderByHash retrieves a block header from the database by hash, caching it if -// found. -func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header { - number := hc.GetBlockNumber(hash) - if number == nil { - return nil - } - return hc.GetHeader(hash, *number) -} - -// HasHeader checks if a block header is present in the database or not. -// In theory, if header is present in the database, all relative components -// like td and hash->number should be present too. -func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool { - if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) { - return true - } - return rawdb.HasHeader(hc.chainDb, hash, number) -} - -// GetHeaderByNumber retrieves a block header from the database by number, -// caching it (associated with its hash) if found. -func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header { - hash := rawdb.ReadCanonicalHash(hc.chainDb, number) - if hash == (common.Hash{}) { - return nil - } - return hc.GetHeader(hash, number) -} - -// GetHeadersFrom returns a contiguous segment of headers, in rlp-form, going -// backwards from the given number. -// If the 'number' is higher than the highest local header, this method will -// return a best-effort response, containing the headers that we do have. -func (hc *HeaderChain) GetHeadersFrom(number, count uint64) []rlp.RawValue { - // If the request is for future headers, we still return the portion of - // headers that we are able to serve - if current := hc.CurrentHeader().Number.Uint64(); current < number { - if count > number-current { - count -= number - current - number = current - } else { - return nil - } - } - var headers []rlp.RawValue - // If we have some of the headers in cache already, use that before going to db. - hash := rawdb.ReadCanonicalHash(hc.chainDb, number) - if hash == (common.Hash{}) { - return nil - } - for count > 0 { - header, ok := hc.headerCache.Get(hash) - if !ok { - break - } - rlpData, _ := rlp.EncodeToBytes(header) - headers = append(headers, rlpData) - hash = header.ParentHash - count-- - number-- - } - // Read remaining from db - if count > 0 { - headers = append(headers, rawdb.ReadHeaderRange(hc.chainDb, number, count)...) - } - return headers -} - -func (hc *HeaderChain) GetCanonicalHash(number uint64) common.Hash { - return rawdb.ReadCanonicalHash(hc.chainDb, number) -} - -// CurrentHeader retrieves the current head header of the canonical chain. The -// header is retrieved from the HeaderChain's internal cache. -func (hc *HeaderChain) CurrentHeader() *types.Header { - return hc.currentHeader.Load().(*types.Header) -} - -// SetCurrentHeader sets the in-memory head header marker of the canonical chan -// as the given header. -func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { - hc.currentHeader.Store(head) - hc.currentHeaderHash = head.Hash() - headHeaderGauge.Update(head.Number.Int64()) -} - -type ( - // UpdateHeadBlocksCallback is a callback function that is called by SetHead - // before head header is updated. The method will return the actual block it - // updated the head to (missing state) and a flag if setHead should continue - // rewinding till that forcefully (exceeded ancient limits) - UpdateHeadBlocksCallback func(ethdb.KeyValueWriter, *types.Header) (*types.Header, bool) - - // DeleteBlockContentCallback is a callback function that is called by SetHead - // before each header is deleted. - DeleteBlockContentCallback func(ethdb.KeyValueWriter, common.Hash, uint64) -) - -// SetHead rewinds the local chain to a new head. Everything above the new head -// will be deleted and the new one set. -func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) { - hc.setHead(head, 0, updateFn, delFn) -} - -// SetHeadWithTimestamp rewinds the local chain to a new head timestamp. Everything -// above the new head will be deleted and the new one set. -func (hc *HeaderChain) SetHeadWithTimestamp(time uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) { - hc.setHead(0, time, updateFn, delFn) -} - -// setHead rewinds the local chain to a new head block or a head timestamp. -// Everything above the new head will be deleted and the new one set. -func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn UpdateHeadBlocksCallback, delFn DeleteBlockContentCallback) { - // Sanity check that there's no attempt to undo the genesis block. This is - // a fairly synthetic case where someone enables a timestamp based fork - // below the genesis timestamp. It's nice to not allow that instead of the - // entire chain getting deleted. - if headTime > 0 && hc.genesisHeader.Time > headTime { - // Note, a critical error is quite brutal, but we should really not reach - // this point. Since pre-timestamp based forks it was impossible to have - // a fork before block 0, the setHead would always work. With timestamp - // forks it becomes possible to specify below the genesis. That said, the - // only time we setHead via timestamp is with chain config changes on the - // startup, so failing hard there is ok. - log.Crit("Rejecting genesis rewind via timestamp", "target", headTime, "genesis", hc.genesisHeader.Time) - } - var ( - parentHash common.Hash - batch = hc.chainDb.NewBatch() - origin = true - ) - done := func(header *types.Header) bool { - if headTime > 0 { - return header.Time <= headTime - } - return header.Number.Uint64() <= headBlock - } - for hdr := hc.CurrentHeader(); hdr != nil && !done(hdr); hdr = hc.CurrentHeader() { - num := hdr.Number.Uint64() - - // Rewind chain to new head - parent := hc.GetHeader(hdr.ParentHash, num-1) - if parent == nil { - parent = hc.genesisHeader - } - parentHash = parent.Hash() - - // Notably, since geth has the possibility for setting the head to a low - // height which is even lower than ancient head. - // In order to ensure that the head is always no higher than the data in - // the database (ancient store or active store), we need to update head - // first then remove the relative data from the database. - // - // Update head first(head fast block, head full block) before deleting the data. - markerBatch := hc.chainDb.NewBatch() - if updateFn != nil { - newHead, force := updateFn(markerBatch, parent) - if force && ((headTime > 0 && newHead.Time < headTime) || (headTime == 0 && newHead.Number.Uint64() < headBlock)) { - log.Warn("Force rewinding till ancient limit", "head", newHead.Number.Uint64()) - headBlock, headTime = newHead.Number.Uint64(), 0 // Target timestamp passed, continue rewind in block mode (cleaner) - } - } - // Update head header then. - rawdb.WriteHeadHeaderHash(markerBatch, parentHash) - if err := markerBatch.Write(); err != nil { - log.Crit("Failed to update chain markers", "error", err) - } - hc.currentHeader.Store(parent) - hc.currentHeaderHash = parentHash - headHeaderGauge.Update(parent.Number.Int64()) - - // If this is the first iteration, wipe any leftover data upwards too so - // we don't end up with dangling daps in the database - var nums []uint64 - if origin { - for n := num + 1; len(rawdb.ReadAllHashes(hc.chainDb, n)) > 0; n++ { - nums = append([]uint64{n}, nums...) // suboptimal, but we don't really expect this path - } - origin = false - } - nums = append(nums, num) - - // Remove the related data from the database on all sidechains - for _, num := range nums { - // Gather all the side fork hashes - hashes := rawdb.ReadAllHashes(hc.chainDb, num) - if len(hashes) == 0 { - // No hashes in the database whatsoever, probably frozen already - hashes = append(hashes, hdr.Hash()) - } - for _, hash := range hashes { - if delFn != nil { - delFn(batch, hash, num) - } - rawdb.DeleteHeader(batch, hash, num) - rawdb.DeleteTd(batch, hash, num) - } - rawdb.DeleteCanonicalHash(batch, num) - } - } - // Flush all accumulated deletions. - if err := batch.Write(); err != nil { - log.Crit("Failed to rewind block", "error", err) - } - // Clear out any stale content from the caches - hc.headerCache.Purge() - hc.tdCache.Purge() - hc.numberCache.Purge() -} - -// SetGenesis sets a new genesis block header for the chain -func (hc *HeaderChain) SetGenesis(head *types.Header) { - hc.genesisHeader = head -} - -// Config retrieves the header chain's chain configuration. -func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config } - -// Engine retrieves the header chain's consensus engine. -func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine } - -// GetBlock implements consensus.ChainReader, and returns nil for every input as -// a header chain does not have blocks available for retrieval. -func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return nil -} diff --git a/builder/core/headerchain_test.go b/builder/core/headerchain_test.go deleted file mode 100644 index 25d9bfffc..000000000 --- a/builder/core/headerchain_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// 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 core - -import ( - "errors" - "fmt" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" -) - -func verifyUnbrokenCanonchain(hc *HeaderChain) error { - h := hc.CurrentHeader() - for { - canonHash := rawdb.ReadCanonicalHash(hc.chainDb, h.Number.Uint64()) - if exp := h.Hash(); canonHash != exp { - return fmt.Errorf("Canon hash chain broken, block %d got %x, expected %x", - h.Number, canonHash[:8], exp[:8]) - } - // Verify that we have the TD - if td := rawdb.ReadTd(hc.chainDb, canonHash, h.Number.Uint64()); td == nil { - return fmt.Errorf("Canon TD missing at block %d", h.Number) - } - if h.Number.Uint64() == 0 { - break - } - h = hc.GetHeader(h.ParentHash, h.Number.Uint64()-1) - } - return nil -} - -func testInsert(t *testing.T, hc *HeaderChain, chain []*types.Header, wantStatus WriteStatus, wantErr error, forker *ForkChoice) { - t.Helper() - - status, err := hc.InsertHeaderChain(chain, time.Now(), forker) - if status != wantStatus { - t.Errorf("wrong write status from InsertHeaderChain: got %v, want %v", status, wantStatus) - } - // Always verify that the header chain is unbroken - if err := verifyUnbrokenCanonchain(hc); err != nil { - t.Fatal(err) - } - if !errors.Is(err, wantErr) { - t.Fatalf("unexpected error from InsertHeaderChain: %v", err) - } -} - -// This test checks status reporting of InsertHeaderChain. -func TestHeaderInsertion(t *testing.T) { - var ( - db = rawdb.NewMemoryDatabase() - gspec = &Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: params.AllEthashProtocolChanges} - ) - gspec.Commit(db, triedb.NewDatabase(db, nil)) - hc, err := NewHeaderChain(db, gspec.Config, ethash.NewFaker(), func() bool { return false }) - if err != nil { - t.Fatal(err) - } - // chain A: G->A1->A2...A128 - genDb, chainA := makeHeaderChainWithGenesis(gspec, 128, ethash.NewFaker(), 10) - // chain B: G->A1->B1...B128 - chainB := makeHeaderChain(gspec.Config, chainA[0], 128, ethash.NewFaker(), genDb, 10) - - forker := NewForkChoice(hc, nil) - // Inserting 64 headers on an empty chain, expecting - // 1 callbacks, 1 canon-status, 0 sidestatus, - testInsert(t, hc, chainA[:64], CanonStatTy, nil, forker) - - // Inserting 64 identical headers, expecting - // 0 callbacks, 0 canon-status, 0 sidestatus, - testInsert(t, hc, chainA[:64], NonStatTy, nil, forker) - - // Inserting the same some old, some new headers - // 1 callbacks, 1 canon, 0 side - testInsert(t, hc, chainA[32:96], CanonStatTy, nil, forker) - - // Inserting side blocks, but not overtaking the canon chain - testInsert(t, hc, chainB[0:32], SideStatTy, nil, forker) - - // Inserting more side blocks, but we don't have the parent - testInsert(t, hc, chainB[34:36], NonStatTy, consensus.ErrUnknownAncestor, forker) - - // Inserting more sideblocks, overtaking the canon chain - testInsert(t, hc, chainB[32:97], CanonStatTy, nil, forker) - - // Inserting more A-headers, taking back the canonicality - testInsert(t, hc, chainA[90:100], CanonStatTy, nil, forker) - - // And B becomes canon again - testInsert(t, hc, chainB[97:107], CanonStatTy, nil, forker) - - // And B becomes even longer - testInsert(t, hc, chainB[107:128], CanonStatTy, nil, forker) -} diff --git a/builder/core/mkalloc.go b/builder/core/mkalloc.go deleted file mode 100644 index 12c40c14f..000000000 --- a/builder/core/mkalloc.go +++ /dev/null @@ -1,108 +0,0 @@ -// 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 . - -//go:build none -// +build none - -/* -The mkalloc tool creates the genesis allocation constants in genesis_alloc.go -It outputs a const declaration that contains an RLP-encoded list of (address, balance) tuples. - - go run mkalloc.go genesis.json -*/ -package main - -import ( - "encoding/json" - "fmt" - "math/big" - "os" - "strconv" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/exp/slices" -) - -type allocItem struct { - Addr *big.Int - Balance *big.Int - Misc *allocItemMisc `rlp:"optional"` -} - -type allocItemMisc struct { - Nonce uint64 - Code []byte - Slots []allocItemStorageItem -} - -type allocItemStorageItem struct { - Key common.Hash - Val common.Hash -} - -func makelist(g *core.Genesis) []allocItem { - items := make([]allocItem, 0, len(g.Alloc)) - for addr, account := range g.Alloc { - var misc *allocItemMisc - if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 { - misc = &allocItemMisc{ - Nonce: account.Nonce, - Code: account.Code, - Slots: make([]allocItemStorageItem, 0, len(account.Storage)), - } - for key, val := range account.Storage { - misc.Slots = append(misc.Slots, allocItemStorageItem{key, val}) - } - slices.SortFunc(misc.Slots, func(a, b allocItemStorageItem) int { - return a.Key.Cmp(b.Key) - }) - } - bigAddr := new(big.Int).SetBytes(addr.Bytes()) - items = append(items, allocItem{bigAddr, account.Balance, misc}) - } - slices.SortFunc(items, func(a, b allocItem) int { - return a.Addr.Cmp(b.Addr) - }) - return items -} - -func makealloc(g *core.Genesis) string { - a := makelist(g) - data, err := rlp.EncodeToBytes(a) - if err != nil { - panic(err) - } - return strconv.QuoteToASCII(string(data)) -} - -func main() { - if len(os.Args) != 2 { - fmt.Fprintln(os.Stderr, "Usage: mkalloc genesis.json") - os.Exit(1) - } - - g := new(core.Genesis) - file, err := os.Open(os.Args[1]) - if err != nil { - panic(err) - } - if err := json.NewDecoder(file).Decode(g); err != nil { - panic(err) - } - fmt.Println("const allocData =", makealloc(g)) -} diff --git a/builder/core/rawdb/accessors_chain.go b/builder/core/rawdb/accessors_chain.go deleted file mode 100644 index 964b3a311..000000000 --- a/builder/core/rawdb/accessors_chain.go +++ /dev/null @@ -1,967 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/exp/slices" -) - -// ReadCanonicalHash retrieves the hash assigned to a canonical block number. -func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - data, _ = reader.Ancient(ChainFreezerHashTable, number) - if len(data) == 0 { - // Get it by hash from leveldb - data, _ = db.Get(headerHashKey(number)) - } - return nil - }) - return common.BytesToHash(data) -} - -// WriteCanonicalHash stores the hash assigned to a canonical block number. -func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { - log.Crit("Failed to store number to hash mapping", "err", err) - } -} - -// DeleteCanonicalHash removes the number to hash canonical mapping. -func DeleteCanonicalHash(db ethdb.KeyValueWriter, number uint64) { - if err := db.Delete(headerHashKey(number)); err != nil { - log.Crit("Failed to delete number to hash mapping", "err", err) - } -} - -// ReadAllHashes retrieves all the hashes assigned to blocks at a certain heights, -// both canonical and reorged forks included. -func ReadAllHashes(db ethdb.Iteratee, number uint64) []common.Hash { - prefix := headerKeyPrefix(number) - - hashes := make([]common.Hash, 0, 1) - it := db.NewIterator(prefix, nil) - defer it.Release() - - for it.Next() { - if key := it.Key(); len(key) == len(prefix)+32 { - hashes = append(hashes, common.BytesToHash(key[len(key)-32:])) - } - } - return hashes -} - -type NumberHash struct { - Number uint64 - Hash common.Hash -} - -// ReadAllHashesInRange retrieves all the hashes assigned to blocks at certain -// heights, both canonical and reorged forks included. -// This method considers both limits to be _inclusive_. -func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash { - var ( - start = encodeBlockNumber(first) - keyLength = len(headerPrefix) + 8 + 32 - hashes = make([]*NumberHash, 0, 1+last-first) - it = db.NewIterator(headerPrefix, start) - ) - defer it.Release() - for it.Next() { - key := it.Key() - if len(key) != keyLength { - continue - } - num := binary.BigEndian.Uint64(key[len(headerPrefix) : len(headerPrefix)+8]) - if num > last { - break - } - hash := common.BytesToHash(key[len(key)-32:]) - hashes = append(hashes, &NumberHash{num, hash}) - } - return hashes -} - -// ReadAllCanonicalHashes retrieves all canonical number and hash mappings at the -// certain chain range. If the accumulated entries reaches the given threshold, -// abort the iteration and return the semi-finish result. -func ReadAllCanonicalHashes(db ethdb.Iteratee, from uint64, to uint64, limit int) ([]uint64, []common.Hash) { - // Short circuit if the limit is 0. - if limit == 0 { - return nil, nil - } - var ( - numbers []uint64 - hashes []common.Hash - ) - // Construct the key prefix of start point. - start, end := headerHashKey(from), headerHashKey(to) - it := db.NewIterator(nil, start) - defer it.Release() - - for it.Next() { - if bytes.Compare(it.Key(), end) >= 0 { - break - } - if key := it.Key(); len(key) == len(headerPrefix)+8+1 && bytes.Equal(key[len(key)-1:], headerHashSuffix) { - numbers = append(numbers, binary.BigEndian.Uint64(key[len(headerPrefix):len(headerPrefix)+8])) - hashes = append(hashes, common.BytesToHash(it.Value())) - // If the accumulated entries reaches the limit threshold, return. - if len(numbers) >= limit { - break - } - } - } - return numbers, hashes -} - -// ReadHeaderNumber returns the header number assigned to a hash. -func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) *uint64 { - data, _ := db.Get(headerNumberKey(hash)) - if len(data) != 8 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteHeaderNumber stores the hash->number mapping. -func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - key := headerNumberKey(hash) - enc := encodeBlockNumber(number) - if err := db.Put(key, enc); err != nil { - log.Crit("Failed to store hash to number mapping", "err", err) - } -} - -// DeleteHeaderNumber removes hash->number mapping. -func DeleteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(headerNumberKey(hash)); err != nil { - log.Crit("Failed to delete hash to number mapping", "err", err) - } -} - -// ReadHeadHeaderHash retrieves the hash of the current canonical head header. -func ReadHeadHeaderHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headHeaderKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteHeadHeaderHash stores the hash of the current canonical head header. -func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last header's hash", "err", err) - } -} - -// ReadHeadBlockHash retrieves the hash of the current canonical head block. -func ReadHeadBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headBlockKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteHeadBlockHash stores the head block's hash. -func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headBlockKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last block's hash", "err", err) - } -} - -// ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. -func ReadHeadFastBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headFastBlockKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteHeadFastBlockHash stores the hash of the current fast-sync head block. -func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last fast block's hash", "err", err) - } -} - -// ReadFinalizedBlockHash retrieves the hash of the finalized block. -func ReadFinalizedBlockHash(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(headFinalizedBlockKey) - if len(data) == 0 { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteFinalizedBlockHash stores the hash of the finalized block. -func WriteFinalizedBlockHash(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Put(headFinalizedBlockKey, hash.Bytes()); err != nil { - log.Crit("Failed to store last finalized block's hash", "err", err) - } -} - -// ReadLastPivotNumber retrieves the number of the last pivot block. If the node -// full synced, the last pivot will always be nil. -func ReadLastPivotNumber(db ethdb.KeyValueReader) *uint64 { - data, _ := db.Get(lastPivotKey) - if len(data) == 0 { - return nil - } - var pivot uint64 - if err := rlp.DecodeBytes(data, &pivot); err != nil { - log.Error("Invalid pivot block number in database", "err", err) - return nil - } - return &pivot -} - -// WriteLastPivotNumber stores the number of the last pivot block. -func WriteLastPivotNumber(db ethdb.KeyValueWriter, pivot uint64) { - enc, err := rlp.EncodeToBytes(pivot) - if err != nil { - log.Crit("Failed to encode pivot block number", "err", err) - } - if err := db.Put(lastPivotKey, enc); err != nil { - log.Crit("Failed to store pivot block number", "err", err) - } -} - -// ReadTxIndexTail retrieves the number of oldest indexed block -// whose transaction indices has been indexed. -func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 { - data, _ := db.Get(txIndexTailKey) - if len(data) != 8 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteTxIndexTail stores the number of oldest indexed block -// into database. -func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { - log.Crit("Failed to store the transaction index tail", "err", err) - } -} - -// ReadHeaderRange returns the rlp-encoded headers, starting at 'number', and going -// backwards towards genesis. This method assumes that the caller already has -// placed a cap on count, to prevent DoS issues. -// Since this method operates in head-towards-genesis mode, it will return an empty -// slice in case the head ('number') is missing. Hence, the caller must ensure that -// the head ('number') argument is actually an existing header. -// -// N.B: Since the input is a number, as opposed to a hash, it's implicit that -// this method only operates on canon headers. -func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValue { - var rlpHeaders []rlp.RawValue - if count == 0 { - return rlpHeaders - } - i := number - if count-1 > number { - // It's ok to request block 0, 1 item - count = number + 1 - } - limit, _ := db.Ancients() - // First read live blocks - if i >= limit { - // If we need to read live blocks, we need to figure out the hash first - hash := ReadCanonicalHash(db, number) - for ; i >= limit && count > 0; i-- { - if data, _ := db.Get(headerKey(i, hash)); len(data) > 0 { - rlpHeaders = append(rlpHeaders, data) - // Get the parent hash for next query - hash = types.HeaderParentHashFromRLP(data) - } else { - break // Maybe got moved to ancients - } - count-- - } - } - if count == 0 { - return rlpHeaders - } - // read remaining from ancients - data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, 0) - if err != nil { - log.Error("Failed to read headers from freezer", "err", err) - return rlpHeaders - } - if uint64(len(data)) != count { - log.Warn("Incomplete read of headers from freezer", "wanted", count, "read", len(data)) - return rlpHeaders - } - // The data is on the order [h, h+1, .., n] -- reordering needed - for i := range data { - rlpHeaders = append(rlpHeaders, data[len(data)-1-i]) - } - return rlpHeaders -} - -// ReadHeaderRLP retrieves a block header in its raw RLP database encoding. -func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - // First try to look up the data in ancient database. Extra hash - // comparison is necessary since ancient database only maintains - // the canonical data. - data, _ = reader.Ancient(ChainFreezerHeaderTable, number) - if len(data) > 0 && crypto.Keccak256Hash(data) == hash { - return nil - } - // If not, try reading from leveldb - data, _ = db.Get(headerKey(number, hash)) - return nil - }) - return data -} - -// HasHeader verifies the existence of a block header corresponding to the hash. -func HasHeader(db ethdb.Reader, hash common.Hash, number uint64) bool { - if isCanon(db, number, hash) { - return true - } - if has, err := db.Has(headerKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadHeader retrieves the block header corresponding to the hash. -func ReadHeader(db ethdb.Reader, hash common.Hash, number uint64) *types.Header { - data := ReadHeaderRLP(db, hash, number) - if len(data) == 0 { - return nil - } - header := new(types.Header) - if err := rlp.DecodeBytes(data, header); err != nil { - log.Error("Invalid block header RLP", "hash", hash, "err", err) - return nil - } - return header -} - -// WriteHeader stores a block header into the database and also stores the hash- -// to-number mapping. -func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { - var ( - hash = header.Hash() - number = header.Number.Uint64() - ) - // Write the hash -> number mapping - WriteHeaderNumber(db, hash, number) - - // Write the encoded header - data, err := rlp.EncodeToBytes(header) - if err != nil { - log.Crit("Failed to RLP encode header", "err", err) - } - key := headerKey(number, hash) - if err := db.Put(key, data); err != nil { - log.Crit("Failed to store header", "err", err) - } -} - -// DeleteHeader removes all block header data associated with a hash. -func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - deleteHeaderWithoutNumber(db, hash, number) - if err := db.Delete(headerNumberKey(hash)); err != nil { - log.Crit("Failed to delete hash to number mapping", "err", err) - } -} - -// deleteHeaderWithoutNumber removes only the block header but does not remove -// the hash to number mapping. -func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(headerKey(number, hash)); err != nil { - log.Crit("Failed to delete header", "err", err) - } -} - -// isCanon is an internal utility method, to check whether the given number/hash -// is part of the ancient (canon) set. -func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool { - h, err := reader.Ancient(ChainFreezerHashTable, number) - if err != nil { - return false - } - return bytes.Equal(h, hash[:]) -} - -// ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. -func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - // First try to look up the data in ancient database. Extra hash - // comparison is necessary since ancient database only maintains - // the canonical data. - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - // Check if the data is in ancients - if isCanon(reader, number, hash) { - data, _ = reader.Ancient(ChainFreezerBodiesTable, number) - return nil - } - // If not, try reading from leveldb - data, _ = db.Get(blockBodyKey(number, hash)) - return nil - }) - return data -} - -// ReadCanonicalBodyRLP retrieves the block body (transactions and uncles) for the canonical -// block at number, in RLP encoding. -func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - data, _ = reader.Ancient(ChainFreezerBodiesTable, number) - if len(data) > 0 { - return nil - } - // Block is not in ancients, read from leveldb by hash and number. - // Note: ReadCanonicalHash cannot be used here because it also - // calls ReadAncients internally. - hash, _ := db.Get(headerHashKey(number)) - data, _ = db.Get(blockBodyKey(number, common.BytesToHash(hash))) - return nil - }) - return data -} - -// WriteBodyRLP stores an RLP encoded block body into the database. -func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { - if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { - log.Crit("Failed to store block body", "err", err) - } -} - -// HasBody verifies the existence of a block body corresponding to the hash. -func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool { - if isCanon(db, number, hash) { - return true - } - if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadBody retrieves the block body corresponding to the hash. -func ReadBody(db ethdb.Reader, hash common.Hash, number uint64) *types.Body { - data := ReadBodyRLP(db, hash, number) - if len(data) == 0 { - return nil - } - body := new(types.Body) - if err := rlp.DecodeBytes(data, body); err != nil { - log.Error("Invalid block body RLP", "hash", hash, "err", err) - return nil - } - return body -} - -// WriteBody stores a block body into the database. -func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) { - data, err := rlp.EncodeToBytes(body) - if err != nil { - log.Crit("Failed to RLP encode body", "err", err) - } - WriteBodyRLP(db, hash, number, data) -} - -// DeleteBody removes all block body data associated with a hash. -func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockBodyKey(number, hash)); err != nil { - log.Crit("Failed to delete block body", "err", err) - } -} - -// ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. -func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - // Check if the data is in ancients - if isCanon(reader, number, hash) { - data, _ = reader.Ancient(ChainFreezerDifficultyTable, number) - return nil - } - // If not, try reading from leveldb - data, _ = db.Get(headerTDKey(number, hash)) - return nil - }) - return data -} - -// ReadTd retrieves a block's total difficulty corresponding to the hash. -func ReadTd(db ethdb.Reader, hash common.Hash, number uint64) *big.Int { - data := ReadTdRLP(db, hash, number) - if len(data) == 0 { - return nil - } - td := new(big.Int) - if err := rlp.DecodeBytes(data, td); err != nil { - log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) - return nil - } - return td -} - -// WriteTd stores the total difficulty of a block into the database. -func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) { - data, err := rlp.EncodeToBytes(td) - if err != nil { - log.Crit("Failed to RLP encode block total difficulty", "err", err) - } - if err := db.Put(headerTDKey(number, hash), data); err != nil { - log.Crit("Failed to store block total difficulty", "err", err) - } -} - -// DeleteTd removes all block total difficulty data associated with a hash. -func DeleteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(headerTDKey(number, hash)); err != nil { - log.Crit("Failed to delete block total difficulty", "err", err) - } -} - -// HasReceipts verifies the existence of all the transaction receipts belonging -// to a block. -func HasReceipts(db ethdb.Reader, hash common.Hash, number uint64) bool { - if isCanon(db, number, hash) { - return true - } - if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { - return false - } - return true -} - -// ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. -func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - var data []byte - db.ReadAncients(func(reader ethdb.AncientReaderOp) error { - // Check if the data is in ancients - if isCanon(reader, number, hash) { - data, _ = reader.Ancient(ChainFreezerReceiptTable, number) - return nil - } - // If not, try reading from leveldb - data, _ = db.Get(blockReceiptsKey(number, hash)) - return nil - }) - return data -} - -// ReadRawReceipts retrieves all the transaction receipts belonging to a block. -// The receipt metadata fields are not guaranteed to be populated, so they -// should not be used. Use ReadReceipts instead if the metadata is needed. -func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Receipts { - // Retrieve the flattened receipt slice - data := ReadReceiptsRLP(db, hash, number) - if len(data) == 0 { - return nil - } - // Convert the receipts from their storage form to their internal representation - storageReceipts := []*types.ReceiptForStorage{} - if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { - log.Error("Invalid receipt array RLP", "hash", hash, "err", err) - return nil - } - receipts := make(types.Receipts, len(storageReceipts)) - for i, storageReceipt := range storageReceipts { - receipts[i] = (*types.Receipt)(storageReceipt) - } - return receipts -} - -// ReadReceipts retrieves all the transaction receipts belonging to a block, including -// its corresponding metadata fields. If it is unable to populate these metadata -// fields then nil is returned. -// -// The current implementation populates these metadata fields by reading the receipts' -// corresponding block body, so if the block body is not found it will return nil even -// if the receipt itself is stored. -func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64, config *params.ChainConfig) types.Receipts { - // We're deriving many fields from the block body, retrieve beside the receipt - receipts := ReadRawReceipts(db, hash, number) - if receipts == nil { - return nil - } - body := ReadBody(db, hash, number) - if body == nil { - log.Error("Missing body but have receipt", "hash", hash, "number", number) - return nil - } - header := ReadHeader(db, hash, number) - - var baseFee *big.Int - if header == nil { - baseFee = big.NewInt(0) - } else { - baseFee = header.BaseFee - } - // Compute effective blob gas price. - var blobGasPrice *big.Int - if header != nil && header.ExcessBlobGas != nil { - blobGasPrice = eip4844.CalcBlobFee(*header.ExcessBlobGas) - } - if err := receipts.DeriveFields(config, hash, number, time, baseFee, blobGasPrice, body.Transactions); err != nil { - log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) - return nil - } - return receipts -} - -// WriteReceipts stores all the transaction receipts belonging to a block. -func WriteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) { - // Convert the receipts into their storage form and serialize them - storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) - for i, receipt := range receipts { - storageReceipts[i] = (*types.ReceiptForStorage)(receipt) - } - bytes, err := rlp.EncodeToBytes(storageReceipts) - if err != nil { - log.Crit("Failed to encode block receipts", "err", err) - } - // Store the flattened receipt slice - if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { - log.Crit("Failed to store block receipts", "err", err) - } -} - -// DeleteReceipts removes all receipt data associated with a block hash. -func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { - log.Crit("Failed to delete block receipts", "err", err) - } -} - -// storedReceiptRLP is the storage encoding of a receipt. -// Re-definition in core/types/receipt.go. -// TODO: Re-use the existing definition. -type storedReceiptRLP struct { - PostStateOrStatus []byte - CumulativeGasUsed uint64 - Logs []*types.Log -} - -// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps -// the list of logs. When decoding a stored receipt into this object we -// avoid creating the bloom filter. -type receiptLogs struct { - Logs []*types.Log -} - -// DecodeRLP implements rlp.Decoder. -func (r *receiptLogs) DecodeRLP(s *rlp.Stream) error { - var stored storedReceiptRLP - if err := s.Decode(&stored); err != nil { - return err - } - r.Logs = stored.Logs - return nil -} - -// DeriveLogFields fills the logs in receiptLogs with information such as block number, txhash, etc. -func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, txs types.Transactions) error { - logIndex := uint(0) - if len(txs) != len(receipts) { - return errors.New("transaction and receipt count mismatch") - } - for i := 0; i < len(receipts); i++ { - txHash := txs[i].Hash() - // The derived log fields can simply be set from the block and transaction - for j := 0; j < len(receipts[i].Logs); j++ { - receipts[i].Logs[j].BlockNumber = number - receipts[i].Logs[j].BlockHash = hash - receipts[i].Logs[j].TxHash = txHash - receipts[i].Logs[j].TxIndex = uint(i) - receipts[i].Logs[j].Index = logIndex - logIndex++ - } - } - return nil -} - -// ReadLogs retrieves the logs for all transactions in a block. In case -// receipts is not found, a nil is returned. -// Note: ReadLogs does not derive unstored log fields. -func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log { - // Retrieve the flattened receipt slice - data := ReadReceiptsRLP(db, hash, number) - if len(data) == 0 { - return nil - } - receipts := []*receiptLogs{} - if err := rlp.DecodeBytes(data, &receipts); err != nil { - log.Error("Invalid receipt array RLP", "hash", hash, "err", err) - return nil - } - - logs := make([][]*types.Log, len(receipts)) - for i, receipt := range receipts { - logs[i] = receipt.Logs - } - return logs -} - -// ReadBlock retrieves an entire block corresponding to the hash, assembling it -// back from the stored header and body. If either the header or body could not -// be retrieved nil is returned. -// -// Note, due to concurrent download of header and block body the header and thus -// canonical hash can be stored in the database but the body data not (yet). -func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block { - header := ReadHeader(db, hash, number) - if header == nil { - return nil - } - body := ReadBody(db, hash, number) - if body == nil { - return nil - } - return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles).WithWithdrawals(body.Withdrawals) -} - -// WriteBlock serializes a block into the database, header and body separately. -func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) { - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - WriteHeader(db, block.Header()) -} - -// WriteAncientBlocks writes entire block data into ancient store and returns the total written size. -func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []types.Receipts, td *big.Int) (int64, error) { - var ( - tdSum = new(big.Int).Set(td) - stReceipts []*types.ReceiptForStorage - ) - return db.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for i, block := range blocks { - // Convert receipts to storage format and sum up total difficulty. - stReceipts = stReceipts[:0] - for _, receipt := range receipts[i] { - stReceipts = append(stReceipts, (*types.ReceiptForStorage)(receipt)) - } - header := block.Header() - if i > 0 { - tdSum.Add(tdSum, header.Difficulty) - } - if err := writeAncientBlock(op, block, header, stReceipts, tdSum); err != nil { - return err - } - } - return nil - }) -} - -func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error { - num := block.NumberU64() - if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil { - return fmt.Errorf("can't add block %d hash: %v", num, err) - } - if err := op.Append(ChainFreezerHeaderTable, num, header); err != nil { - return fmt.Errorf("can't append block header %d: %v", num, err) - } - if err := op.Append(ChainFreezerBodiesTable, num, block.Body()); err != nil { - return fmt.Errorf("can't append block body %d: %v", num, err) - } - if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil { - return fmt.Errorf("can't append block %d receipts: %v", num, err) - } - if err := op.Append(ChainFreezerDifficultyTable, num, td); err != nil { - return fmt.Errorf("can't append block %d total difficulty: %v", num, err) - } - return nil -} - -// DeleteBlock removes all block data associated with a hash. -func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - DeleteReceipts(db, hash, number) - DeleteHeader(db, hash, number) - DeleteBody(db, hash, number) - DeleteTd(db, hash, number) -} - -// DeleteBlockWithoutNumber removes all block data associated with a hash, except -// the hash to number mapping. -func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - DeleteReceipts(db, hash, number) - deleteHeaderWithoutNumber(db, hash, number) - DeleteBody(db, hash, number) - DeleteTd(db, hash, number) -} - -const badBlockToKeep = 10 - -type badBlock struct { - Header *types.Header - Body *types.Body -} - -// ReadBadBlock retrieves the bad block with the corresponding block hash. -func ReadBadBlock(db ethdb.Reader, hash common.Hash) *types.Block { - blob, err := db.Get(badBlockKey) - if err != nil { - return nil - } - var badBlocks []*badBlock - if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { - return nil - } - for _, bad := range badBlocks { - if bad.Header.Hash() == hash { - return types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles).WithWithdrawals(bad.Body.Withdrawals) - } - } - return nil -} - -// ReadAllBadBlocks retrieves all the bad blocks in the database. -// All returned blocks are sorted in reverse order by number. -func ReadAllBadBlocks(db ethdb.Reader) []*types.Block { - blob, err := db.Get(badBlockKey) - if err != nil { - return nil - } - var badBlocks []*badBlock - if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { - return nil - } - var blocks []*types.Block - for _, bad := range badBlocks { - blocks = append(blocks, types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles).WithWithdrawals(bad.Body.Withdrawals)) - } - return blocks -} - -// WriteBadBlock serializes the bad block into the database. If the cumulated -// bad blocks exceeds the limitation, the oldest will be dropped. -func WriteBadBlock(db ethdb.KeyValueStore, block *types.Block) { - blob, err := db.Get(badBlockKey) - if err != nil { - log.Warn("Failed to load old bad blocks", "error", err) - } - var badBlocks []*badBlock - if len(blob) > 0 { - if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { - log.Crit("Failed to decode old bad blocks", "error", err) - } - } - for _, b := range badBlocks { - if b.Header.Number.Uint64() == block.NumberU64() && b.Header.Hash() == block.Hash() { - log.Info("Skip duplicated bad block", "number", block.NumberU64(), "hash", block.Hash()) - return - } - } - badBlocks = append(badBlocks, &badBlock{ - Header: block.Header(), - Body: block.Body(), - }) - slices.SortFunc(badBlocks, func(a, b *badBlock) int { - // Note: sorting in descending number order. - return -a.Header.Number.Cmp(b.Header.Number) - }) - if len(badBlocks) > badBlockToKeep { - badBlocks = badBlocks[:badBlockToKeep] - } - data, err := rlp.EncodeToBytes(badBlocks) - if err != nil { - log.Crit("Failed to encode bad blocks", "err", err) - } - if err := db.Put(badBlockKey, data); err != nil { - log.Crit("Failed to write bad blocks", "err", err) - } -} - -// DeleteBadBlocks deletes all the bad blocks from the database -func DeleteBadBlocks(db ethdb.KeyValueWriter) { - if err := db.Delete(badBlockKey); err != nil { - log.Crit("Failed to delete bad blocks", "err", err) - } -} - -// FindCommonAncestor returns the last common ancestor of two block headers -func FindCommonAncestor(db ethdb.Reader, a, b *types.Header) *types.Header { - for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { - a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) - if a == nil { - return nil - } - } - for an := a.Number.Uint64(); an < b.Number.Uint64(); { - b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) - if b == nil { - return nil - } - } - for a.Hash() != b.Hash() { - a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) - if a == nil { - return nil - } - b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) - if b == nil { - return nil - } - } - return a -} - -// ReadHeadHeader returns the current canonical head header. -func ReadHeadHeader(db ethdb.Reader) *types.Header { - headHeaderHash := ReadHeadHeaderHash(db) - if headHeaderHash == (common.Hash{}) { - return nil - } - headHeaderNumber := ReadHeaderNumber(db, headHeaderHash) - if headHeaderNumber == nil { - return nil - } - return ReadHeader(db, headHeaderHash, *headHeaderNumber) -} - -// ReadHeadBlock returns the current canonical head block. -func ReadHeadBlock(db ethdb.Reader) *types.Block { - headBlockHash := ReadHeadBlockHash(db) - if headBlockHash == (common.Hash{}) { - return nil - } - headBlockNumber := ReadHeaderNumber(db, headBlockHash) - if headBlockNumber == nil { - return nil - } - return ReadBlock(db, headBlockHash, *headBlockNumber) -} diff --git a/builder/core/rawdb/accessors_chain_test.go b/builder/core/rawdb/accessors_chain_test.go deleted file mode 100644 index a7ceb7299..000000000 --- a/builder/core/rawdb/accessors_chain_test.go +++ /dev/null @@ -1,933 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "bytes" - "encoding/hex" - "fmt" - "math/big" - "math/rand" - "os" - "reflect" - "testing" - - "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/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" -) - -// Tests block header storage and retrieval operations. -func TestHeaderStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test header to move around the database and make sure it's really new - header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")} - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { - t.Fatalf("Non existent header returned: %v", entry) - } - // Write and verify the header in the database - WriteHeader(db, header) - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil { - t.Fatalf("Stored header not found") - } else if entry.Hash() != header.Hash() { - t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header) - } - if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil { - t.Fatalf("Stored header RLP not found") - } else { - hasher := sha3.NewLegacyKeccak256() - hasher.Write(entry) - - if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() { - t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header) - } - } - // Delete the header and verify the execution - DeleteHeader(db, header.Hash(), header.Number.Uint64()) - if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil { - t.Fatalf("Deleted header returned: %v", entry) - } -} - -// Tests block body storage and retrieval operations. -func TestBodyStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test body to move around the database and make sure it's really new - body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}} - - hasher := sha3.NewLegacyKeccak256() - rlp.Encode(hasher, body) - hash := common.BytesToHash(hasher.Sum(nil)) - - if entry := ReadBody(db, hash, 0); entry != nil { - t.Fatalf("Non existent body returned: %v", entry) - } - // Write and verify the body in the database - WriteBody(db, hash, 0, body) - if entry := ReadBody(db, hash, 0); entry == nil { - t.Fatalf("Stored body not found") - } else if types.DeriveSha(types.Transactions(entry.Transactions), newTestHasher()) != types.DeriveSha(types.Transactions(body.Transactions), newTestHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) { - t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body) - } - if entry := ReadBodyRLP(db, hash, 0); entry == nil { - t.Fatalf("Stored body RLP not found") - } else { - hasher := sha3.NewLegacyKeccak256() - hasher.Write(entry) - - if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash { - t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body) - } - } - // Delete the body and verify the execution - DeleteBody(db, hash, 0) - if entry := ReadBody(db, hash, 0); entry != nil { - t.Fatalf("Deleted body returned: %v", entry) - } -} - -// Tests block storage and retrieval operations. -func TestBlockStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test block to move around the database and make sure it's really new - block := types.NewBlockWithHeader(&types.Header{ - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent header returned: %v", entry) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent body returned: %v", entry) - } - // Write and verify the block in the database - WriteBlock(db, block) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored block not found") - } else if entry.Hash() != block.Hash() { - t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored header not found") - } else if entry.Hash() != block.Header().Hash() { - t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header()) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored body not found") - } else if types.DeriveSha(types.Transactions(entry.Transactions), newTestHasher()) != types.DeriveSha(block.Transactions(), newTestHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) { - t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body()) - } - // Delete the block and verify the execution - DeleteBlock(db, block.Hash(), block.NumberU64()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted block returned: %v", entry) - } - if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted header returned: %v", entry) - } - if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Deleted body returned: %v", entry) - } -} - -// Tests that partial block contents don't get reassembled into full blocks. -func TestPartialBlockStorage(t *testing.T) { - db := NewMemoryDatabase() - block := types.NewBlockWithHeader(&types.Header{ - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - // Store a header and check that it's not recognized as a block - WriteHeader(db, block.Header()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - DeleteHeader(db, block.Hash(), block.NumberU64()) - - // Store a body and check that it's not recognized as a block - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - DeleteBody(db, block.Hash(), block.NumberU64()) - - // Store a header and a body separately and check reassembly - WriteHeader(db, block.Header()) - WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) - - if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil { - t.Fatalf("Stored block not found") - } else if entry.Hash() != block.Hash() { - t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) - } -} - -// Tests block storage and retrieval operations. -func TestBadBlockStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test block to move around the database and make sure it's really new - block := types.NewBlockWithHeader(&types.Header{ - Number: big.NewInt(1), - Extra: []byte("bad block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - if entry := ReadBadBlock(db, block.Hash()); entry != nil { - t.Fatalf("Non existent block returned: %v", entry) - } - // Write and verify the block in the database - WriteBadBlock(db, block) - if entry := ReadBadBlock(db, block.Hash()); entry == nil { - t.Fatalf("Stored block not found") - } else if entry.Hash() != block.Hash() { - t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block) - } - // Write one more bad block - blockTwo := types.NewBlockWithHeader(&types.Header{ - Number: big.NewInt(2), - Extra: []byte("bad block two"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - WriteBadBlock(db, blockTwo) - - // Write the block one again, should be filtered out. - WriteBadBlock(db, block) - badBlocks := ReadAllBadBlocks(db) - if len(badBlocks) != 2 { - t.Fatalf("Failed to load all bad blocks") - } - - // Write a bunch of bad blocks, all the blocks are should sorted - // in reverse order. The extra blocks should be truncated. - for _, n := range rand.Perm(100) { - block := types.NewBlockWithHeader(&types.Header{ - Number: big.NewInt(int64(n)), - Extra: []byte("bad block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - WriteBadBlock(db, block) - } - badBlocks = ReadAllBadBlocks(db) - if len(badBlocks) != badBlockToKeep { - t.Fatalf("The number of persised bad blocks in incorrect %d", len(badBlocks)) - } - for i := 0; i < len(badBlocks)-1; i++ { - if badBlocks[i].NumberU64() < badBlocks[i+1].NumberU64() { - t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, i+1, badBlocks[i].NumberU64(), badBlocks[i+1].NumberU64()) - } - } - - // Delete all bad blocks - DeleteBadBlocks(db) - badBlocks = ReadAllBadBlocks(db) - if len(badBlocks) != 0 { - t.Fatalf("Failed to delete bad blocks") - } -} - -// Tests block total difficulty storage and retrieval operations. -func TestTdStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test TD to move around the database and make sure it's really new - hash, td := common.Hash{}, big.NewInt(314) - if entry := ReadTd(db, hash, 0); entry != nil { - t.Fatalf("Non existent TD returned: %v", entry) - } - // Write and verify the TD in the database - WriteTd(db, hash, 0, td) - if entry := ReadTd(db, hash, 0); entry == nil { - t.Fatalf("Stored TD not found") - } else if entry.Cmp(td) != 0 { - t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td) - } - // Delete the TD and verify the execution - DeleteTd(db, hash, 0) - if entry := ReadTd(db, hash, 0); entry != nil { - t.Fatalf("Deleted TD returned: %v", entry) - } -} - -// Tests that canonical numbers can be mapped to hashes and retrieved. -func TestCanonicalMappingStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a test canonical number and assigned hash to move around - hash, number := common.Hash{0: 0xff}, uint64(314) - if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { - t.Fatalf("Non existent canonical mapping returned: %v", entry) - } - // Write and verify the TD in the database - WriteCanonicalHash(db, hash, number) - if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) { - t.Fatalf("Stored canonical mapping not found") - } else if entry != hash { - t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash) - } - // Delete the TD and verify the execution - DeleteCanonicalHash(db, number) - if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { - t.Fatalf("Deleted canonical mapping returned: %v", entry) - } -} - -// Tests that head headers and head blocks can be assigned, individually. -func TestHeadStorage(t *testing.T) { - db := NewMemoryDatabase() - - blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")}) - blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")}) - blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")}) - - // Check that no head entries are in a pristine database - if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) { - t.Fatalf("Non head header entry returned: %v", entry) - } - if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) { - t.Fatalf("Non head block entry returned: %v", entry) - } - if entry := ReadHeadFastBlockHash(db); entry != (common.Hash{}) { - t.Fatalf("Non fast head block entry returned: %v", entry) - } - // Assign separate entries for the head header and block - WriteHeadHeaderHash(db, blockHead.Hash()) - WriteHeadBlockHash(db, blockFull.Hash()) - WriteHeadFastBlockHash(db, blockFast.Hash()) - - // Check that both heads are present, and different (i.e. two heads maintained) - if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() { - t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash()) - } - if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() { - t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash()) - } - if entry := ReadHeadFastBlockHash(db); entry != blockFast.Hash() { - t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash()) - } -} - -// Tests that receipts associated with a single block can be stored and retrieved. -func TestBlockReceiptStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create a live block since we need metadata to reconstruct the receipt - tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) - tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil) - - body := &types.Body{Transactions: types.Transactions{tx1, tx2}} - - // Create the two receipts to manage afterwards - receipt1 := &types.Receipt{ - Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, - } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) - - receipt2 := &types.Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 2, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, - } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) - receipts := []*types.Receipt{receipt1, receipt2} - - // Check that no receipt entries are in a pristine database - hash := common.BytesToHash([]byte{0x03, 0x14}) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("non existent receipts returned: %v", rs) - } - // Insert the body that corresponds to the receipts - WriteBody(db, hash, 0, body) - - // Insert the receipt slice into the database and check presence - WriteReceipts(db, hash, 0, receipts) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 { - t.Fatalf("no receipts returned") - } else { - if err := checkReceiptsRLP(rs, receipts); err != nil { - t.Fatalf(err.Error()) - } - } - // Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed) - DeleteBody(db, hash, 0) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); rs != nil { - t.Fatalf("receipts returned when body was deleted: %v", rs) - } - // Ensure that receipts without metadata can be returned without the block body too - if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil { - t.Fatalf(err.Error()) - } - // Sanity check that body alone without the receipt is a full purge - WriteBody(db, hash, 0, body) - - DeleteReceipts(db, hash, 0) - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("deleted receipts returned: %v", rs) - } -} - -func checkReceiptsRLP(have, want types.Receipts) error { - if len(have) != len(want) { - return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want)) - } - for i := 0; i < len(want); i++ { - rlpHave, err := rlp.EncodeToBytes(have[i]) - if err != nil { - return err - } - rlpWant, err := rlp.EncodeToBytes(want[i]) - if err != nil { - return err - } - if !bytes.Equal(rlpHave, rlpWant) { - return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant)) - } - } - return nil -} - -func TestAncientStorage(t *testing.T) { - // Freezer style fast import the chain. - frdir := t.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) - if err != nil { - t.Fatalf("failed to create database with ancient backend") - } - defer db.Close() - - // Create a test block - block := types.NewBlockWithHeader(&types.Header{ - Number: big.NewInt(0), - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - }) - // Ensure nothing non-existent will be read - hash, number := block.Hash(), block.NumberU64() - if blob := ReadHeaderRLP(db, hash, number); len(blob) > 0 { - t.Fatalf("non existent header returned") - } - if blob := ReadBodyRLP(db, hash, number); len(blob) > 0 { - t.Fatalf("non existent body returned") - } - if blob := ReadReceiptsRLP(db, hash, number); len(blob) > 0 { - t.Fatalf("non existent receipts returned") - } - if blob := ReadTdRLP(db, hash, number); len(blob) > 0 { - t.Fatalf("non existent td returned") - } - - // Write and verify the header in the database - WriteAncientBlocks(db, []*types.Block{block}, []types.Receipts{nil}, big.NewInt(100)) - - if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 { - t.Fatalf("no header returned") - } - if blob := ReadBodyRLP(db, hash, number); len(blob) == 0 { - t.Fatalf("no body returned") - } - if blob := ReadReceiptsRLP(db, hash, number); len(blob) == 0 { - t.Fatalf("no receipts returned") - } - if blob := ReadTdRLP(db, hash, number); len(blob) == 0 { - t.Fatalf("no td returned") - } - - // Use a fake hash for data retrieval, nothing should be returned. - fakeHash := common.BytesToHash([]byte{0x01, 0x02, 0x03}) - if blob := ReadHeaderRLP(db, fakeHash, number); len(blob) != 0 { - t.Fatalf("invalid header returned") - } - if blob := ReadBodyRLP(db, fakeHash, number); len(blob) != 0 { - t.Fatalf("invalid body returned") - } - if blob := ReadReceiptsRLP(db, fakeHash, number); len(blob) != 0 { - t.Fatalf("invalid receipts returned") - } - if blob := ReadTdRLP(db, fakeHash, number); len(blob) != 0 { - t.Fatalf("invalid td returned") - } -} - -func TestCanonicalHashIteration(t *testing.T) { - var cases = []struct { - from, to uint64 - limit int - expect []uint64 - }{ - {1, 8, 0, nil}, - {1, 8, 1, []uint64{1}}, - {1, 8, 10, []uint64{1, 2, 3, 4, 5, 6, 7}}, - {1, 9, 10, []uint64{1, 2, 3, 4, 5, 6, 7, 8}}, - {2, 9, 10, []uint64{2, 3, 4, 5, 6, 7, 8}}, - {9, 10, 10, nil}, - } - // Test empty db iteration - db := NewMemoryDatabase() - numbers, _ := ReadAllCanonicalHashes(db, 0, 10, 10) - if len(numbers) != 0 { - t.Fatalf("No entry should be returned to iterate an empty db") - } - // Fill database with testing data. - for i := uint64(1); i <= 8; i++ { - WriteCanonicalHash(db, common.Hash{}, i) - WriteTd(db, common.Hash{}, i, big.NewInt(10)) // Write some interferential data - } - for i, c := range cases { - numbers, _ := ReadAllCanonicalHashes(db, c.from, c.to, c.limit) - if !reflect.DeepEqual(numbers, c.expect) { - t.Fatalf("Case %d failed, want %v, got %v", i, c.expect, numbers) - } - } -} - -func TestHashesInRange(t *testing.T) { - mkHeader := func(number, seq int) *types.Header { - h := types.Header{ - Difficulty: new(big.Int), - Number: big.NewInt(int64(number)), - GasLimit: uint64(seq), - } - return &h - } - db := NewMemoryDatabase() - // For each number, write N versions of that particular number - total := 0 - for i := 0; i < 15; i++ { - for ii := 0; ii < i; ii++ { - WriteHeader(db, mkHeader(i, ii)) - total++ - } - } - if have, want := len(ReadAllHashesInRange(db, 10, 10)), 10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 10, 9)), 0; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 0, 100)), total; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashesInRange(db, 9, 10)), 9+10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 10)), 10; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 16)), 0; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } - if have, want := len(ReadAllHashes(db, 1)), 1; have != want { - t.Fatalf("Wrong number of hashes read, want %d, got %d", want, have) - } -} - -// This measures the write speed of the WriteAncientBlocks operation. -func BenchmarkWriteAncientBlocks(b *testing.B) { - // Open freezer database. - frdir := b.TempDir() - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) - if err != nil { - b.Fatalf("failed to create database with ancient backend") - } - defer db.Close() - - // Create the data to insert. The blocks must have consecutive numbers, so we create - // all of them ahead of time. However, there is no need to create receipts - // individually for each block, just make one batch here and reuse it for all writes. - const batchSize = 128 - const blockTxs = 20 - allBlocks := makeTestBlocks(b.N, blockTxs) - batchReceipts := makeTestReceipts(batchSize, blockTxs) - b.ResetTimer() - - // The benchmark loop writes batches of blocks, but note that the total block count is - // b.N. This means the resulting ns/op measurement is the time it takes to write a - // single block and its associated data. - var td = big.NewInt(55) - var totalSize int64 - for i := 0; i < b.N; i += batchSize { - length := batchSize - if i+batchSize > b.N { - length = b.N - i - } - - blocks := allBlocks[i : i+length] - receipts := batchReceipts[:length] - writeSize, err := WriteAncientBlocks(db, blocks, receipts, td) - if err != nil { - b.Fatal(err) - } - totalSize += writeSize - } - - // Enable MB/s reporting. - b.SetBytes(totalSize / int64(b.N)) -} - -// makeTestBlocks creates fake blocks for the ancient write benchmark. -func makeTestBlocks(nblock int, txsPerBlock int) []*types.Block { - key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - signer := types.LatestSignerForChainID(big.NewInt(8)) - - // Create transactions. - txs := make([]*types.Transaction, txsPerBlock) - for i := 0; i < len(txs); i++ { - var err error - to := common.Address{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - txs[i], err = types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: 2, - GasPrice: big.NewInt(30000), - Gas: 0x45454545, - To: &to, - }) - if err != nil { - panic(err) - } - } - - // Create the blocks. - blocks := make([]*types.Block, nblock) - for i := 0; i < nblock; i++ { - header := &types.Header{ - Number: big.NewInt(int64(i)), - Extra: []byte("test block"), - } - blocks[i] = types.NewBlockWithHeader(header).WithBody(txs, nil) - blocks[i].Hash() // pre-cache the block hash - } - return blocks -} - -// makeTestReceipts creates fake receipts for the ancient write benchmark. -func makeTestReceipts(n int, nPerBlock int) []types.Receipts { - receipts := make([]*types.Receipt, nPerBlock) - for i := 0; i < len(receipts); i++ { - receipts[i] = &types.Receipt{ - Status: types.ReceiptStatusSuccessful, - CumulativeGasUsed: 0x888888888, - Logs: make([]*types.Log, 5), - } - } - allReceipts := make([]types.Receipts, n) - for i := 0; i < n; i++ { - allReceipts[i] = receipts - } - return allReceipts -} - -type fullLogRLP struct { - Address common.Address - Topics []common.Hash - Data []byte - BlockNumber uint64 - TxHash common.Hash - TxIndex uint - BlockHash common.Hash - Index uint -} - -func newFullLogRLP(l *types.Log) *fullLogRLP { - return &fullLogRLP{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: l.BlockNumber, - TxHash: l.TxHash, - TxIndex: l.TxIndex, - BlockHash: l.BlockHash, - Index: l.Index, - } -} - -// Tests that logs associated with a single block can be retrieved. -func TestReadLogs(t *testing.T) { - db := NewMemoryDatabase() - - // Create a live block since we need metadata to reconstruct the receipt - tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) - tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil) - - body := &types.Body{Transactions: types.Transactions{tx1, tx2}} - - // Create the two receipts to manage afterwards - receipt1 := &types.Receipt{ - Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - TxHash: tx1.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, - } - receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) - - receipt2 := &types.Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 2, - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - TxHash: tx2.Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 222222, - } - receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) - receipts := []*types.Receipt{receipt1, receipt2} - - hash := common.BytesToHash([]byte{0x03, 0x14}) - // Check that no receipt entries are in a pristine database - if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 { - t.Fatalf("non existent receipts returned: %v", rs) - } - // Insert the body that corresponds to the receipts - WriteBody(db, hash, 0, body) - - // Insert the receipt slice into the database and check presence - WriteReceipts(db, hash, 0, receipts) - - logs := ReadLogs(db, hash, 0) - if len(logs) == 0 { - t.Fatalf("no logs returned") - } - if have, want := len(logs), 2; have != want { - t.Fatalf("unexpected number of logs returned, have %d want %d", have, want) - } - if have, want := len(logs[0]), 2; have != want { - t.Fatalf("unexpected number of logs[0] returned, have %d want %d", have, want) - } - if have, want := len(logs[1]), 2; have != want { - t.Fatalf("unexpected number of logs[1] returned, have %d want %d", have, want) - } - - for i, pr := range receipts { - for j, pl := range pr.Logs { - rlpHave, err := rlp.EncodeToBytes(newFullLogRLP(logs[i][j])) - if err != nil { - t.Fatal(err) - } - rlpWant, err := rlp.EncodeToBytes(newFullLogRLP(pl)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(rlpHave, rlpWant) { - t.Fatalf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant)) - } - } - } -} - -func TestDeriveLogFields(t *testing.T) { - // Create a few transactions to have receipts for - to2 := common.HexToAddress("0x2") - to3 := common.HexToAddress("0x3") - txs := types.Transactions{ - types.NewTx(&types.LegacyTx{ - Nonce: 1, - Value: big.NewInt(1), - Gas: 1, - GasPrice: big.NewInt(1), - }), - types.NewTx(&types.LegacyTx{ - To: &to2, - Nonce: 2, - Value: big.NewInt(2), - Gas: 2, - GasPrice: big.NewInt(2), - }), - types.NewTx(&types.AccessListTx{ - To: &to3, - Nonce: 3, - Value: big.NewInt(3), - Gas: 3, - GasPrice: big.NewInt(3), - }), - } - // Create the corresponding receipts - receipts := []*receiptLogs{ - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - }, - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - }, - { - Logs: []*types.Log{ - {Address: common.BytesToAddress([]byte{0x33})}, - {Address: common.BytesToAddress([]byte{0x03, 0x33})}, - }, - }, - } - - // Derive log metadata fields - number := big.NewInt(1) - hash := common.BytesToHash([]byte{0x03, 0x14}) - if err := deriveLogFields(receipts, hash, number.Uint64(), txs); err != nil { - t.Fatal(err) - } - - // Iterate over all the computed fields and check that they're correct - logIndex := uint(0) - for i := range receipts { - for j := range receipts[i].Logs { - if receipts[i].Logs[j].BlockNumber != number.Uint64() { - t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64()) - } - if receipts[i].Logs[j].BlockHash != hash { - t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String()) - } - if receipts[i].Logs[j].TxHash != txs[i].Hash() { - t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) - } - if receipts[i].Logs[j].TxIndex != uint(i) { - t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i) - } - if receipts[i].Logs[j].Index != logIndex { - t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex) - } - logIndex++ - } - } -} - -func BenchmarkDecodeRLPLogs(b *testing.B) { - // Encoded receipts from block 0x14ee094309fbe8f70b65f45ebcc08fb33f126942d97464aad5eb91cfd1e2d269 - buf, err := os.ReadFile("testdata/stored_receipts.bin") - if err != nil { - b.Fatal(err) - } - b.Run("ReceiptForStorage", func(b *testing.B) { - b.ReportAllocs() - var r []*types.ReceiptForStorage - for i := 0; i < b.N; i++ { - if err := rlp.DecodeBytes(buf, &r); err != nil { - b.Fatal(err) - } - } - }) - b.Run("rlpLogs", func(b *testing.B) { - b.ReportAllocs() - var r []*receiptLogs - for i := 0; i < b.N; i++ { - if err := rlp.DecodeBytes(buf, &r); err != nil { - b.Fatal(err) - } - } - }) -} - -func TestHeadersRLPStorage(t *testing.T) { - // Have N headers in the freezer - frdir := t.TempDir() - - db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "", false) - if err != nil { - t.Fatalf("failed to create database with ancient backend") - } - defer db.Close() - // Create blocks - var chain []*types.Block - var pHash common.Hash - for i := 0; i < 100; i++ { - block := types.NewBlockWithHeader(&types.Header{ - Number: big.NewInt(int64(i)), - Extra: []byte("test block"), - UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyTxsHash, - ReceiptHash: types.EmptyReceiptsHash, - ParentHash: pHash, - }) - chain = append(chain, block) - pHash = block.Hash() - } - var receipts []types.Receipts = make([]types.Receipts, 100) - // Write first half to ancients - WriteAncientBlocks(db, chain[:50], receipts[:50], big.NewInt(100)) - // Write second half to db - for i := 50; i < 100; i++ { - WriteCanonicalHash(db, chain[i].Hash(), chain[i].NumberU64()) - WriteBlock(db, chain[i]) - } - checkSequence := func(from, amount int) { - headersRlp := ReadHeaderRange(db, uint64(from), uint64(amount)) - if have, want := len(headersRlp), amount; have != want { - t.Fatalf("have %d headers, want %d", have, want) - } - for i, headerRlp := range headersRlp { - var header types.Header - if err := rlp.DecodeBytes(headerRlp, &header); err != nil { - t.Fatal(err) - } - if have, want := header.Number.Uint64(), uint64(from-i); have != want { - t.Fatalf("wrong number, have %d want %d", have, want) - } - } - } - checkSequence(99, 20) // Latest block and 19 parents - checkSequence(99, 50) // Latest block -> all db blocks - checkSequence(99, 51) // Latest block -> one from ancients - checkSequence(99, 52) // Latest blocks -> two from ancients - checkSequence(50, 2) // One from db, one from ancients - checkSequence(49, 1) // One from ancients - checkSequence(49, 50) // All ancient ones - checkSequence(99, 100) // All blocks - checkSequence(0, 1) // Only genesis - checkSequence(1, 1) // Only block 1 - checkSequence(1, 2) // Genesis + block 1 -} diff --git a/builder/core/rawdb/accessors_indexes.go b/builder/core/rawdb/accessors_indexes.go deleted file mode 100644 index 4f2ef0a88..000000000 --- a/builder/core/rawdb/accessors_indexes.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -// ReadTxLookupEntry retrieves the positional metadata associated with a transaction -// hash to allow retrieving the transaction or receipt by hash. -func ReadTxLookupEntry(db ethdb.Reader, hash common.Hash) *uint64 { - data, _ := db.Get(txLookupKey(hash)) - if len(data) == 0 { - return nil - } - // Database v6 tx lookup just stores the block number - if len(data) < common.HashLength { - number := new(big.Int).SetBytes(data).Uint64() - return &number - } - // Database v4-v5 tx lookup format just stores the hash - if len(data) == common.HashLength { - return ReadHeaderNumber(db, common.BytesToHash(data)) - } - // Finally try database v3 tx lookup format - var entry LegacyTxLookupEntry - if err := rlp.DecodeBytes(data, &entry); err != nil { - log.Error("Invalid transaction lookup entry RLP", "hash", hash, "blob", data, "err", err) - return nil - } - return &entry.BlockIndex -} - -// writeTxLookupEntry stores a positional metadata for a transaction, -// enabling hash based transaction and receipt lookups. -func writeTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash, numberBytes []byte) { - if err := db.Put(txLookupKey(hash), numberBytes); err != nil { - log.Crit("Failed to store transaction lookup entry", "err", err) - } -} - -// WriteTxLookupEntries is identical to WriteTxLookupEntry, but it works on -// a list of hashes -func WriteTxLookupEntries(db ethdb.KeyValueWriter, number uint64, hashes []common.Hash) { - numberBytes := new(big.Int).SetUint64(number).Bytes() - for _, hash := range hashes { - writeTxLookupEntry(db, hash, numberBytes) - } -} - -// WriteTxLookupEntriesByBlock stores a positional metadata for every transaction from -// a block, enabling hash based transaction and receipt lookups. -func WriteTxLookupEntriesByBlock(db ethdb.KeyValueWriter, block *types.Block) { - numberBytes := block.Number().Bytes() - for _, tx := range block.Transactions() { - writeTxLookupEntry(db, tx.Hash(), numberBytes) - } -} - -// DeleteTxLookupEntry removes all transaction data associated with a hash. -func DeleteTxLookupEntry(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(txLookupKey(hash)); err != nil { - log.Crit("Failed to delete transaction lookup entry", "err", err) - } -} - -// DeleteTxLookupEntries removes all transaction lookups for a given block. -func DeleteTxLookupEntries(db ethdb.KeyValueWriter, hashes []common.Hash) { - for _, hash := range hashes { - DeleteTxLookupEntry(db, hash) - } -} - -// ReadTransaction retrieves a specific transaction from the database, along with -// its added positional metadata. -func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) { - blockNumber := ReadTxLookupEntry(db, hash) - if blockNumber == nil { - return nil, common.Hash{}, 0, 0 - } - blockHash := ReadCanonicalHash(db, *blockNumber) - if blockHash == (common.Hash{}) { - return nil, common.Hash{}, 0, 0 - } - body := ReadBody(db, blockHash, *blockNumber) - if body == nil { - log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash) - return nil, common.Hash{}, 0, 0 - } - for txIndex, tx := range body.Transactions { - if tx.Hash() == hash { - return tx, blockHash, *blockNumber, uint64(txIndex) - } - } - log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) - return nil, common.Hash{}, 0, 0 -} - -// ReadReceipt retrieves a specific transaction receipt from the database, along with -// its added positional metadata. -func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig) (*types.Receipt, common.Hash, uint64, uint64) { - // Retrieve the context of the receipt based on the transaction hash - blockNumber := ReadTxLookupEntry(db, hash) - if blockNumber == nil { - return nil, common.Hash{}, 0, 0 - } - blockHash := ReadCanonicalHash(db, *blockNumber) - if blockHash == (common.Hash{}) { - return nil, common.Hash{}, 0, 0 - } - blockHeader := ReadHeader(db, blockHash, *blockNumber) - if blockHeader == nil { - return nil, common.Hash{}, 0, 0 - } - // Read all the receipts from the block and return the one with the matching hash - receipts := ReadReceipts(db, blockHash, *blockNumber, blockHeader.Time, config) - for receiptIndex, receipt := range receipts { - if receipt.TxHash == hash { - return receipt, blockHash, *blockNumber, uint64(receiptIndex) - } - } - log.Error("Receipt not found", "number", *blockNumber, "hash", blockHash, "txhash", hash) - return nil, common.Hash{}, 0, 0 -} - -// ReadBloomBits retrieves the compressed bloom bit vector belonging to the given -// section and bit index from the. -func ReadBloomBits(db ethdb.KeyValueReader, bit uint, section uint64, head common.Hash) ([]byte, error) { - return db.Get(bloomBitsKey(bit, section, head)) -} - -// WriteBloomBits stores the compressed bloom bits vector belonging to the given -// section and bit index. -func WriteBloomBits(db ethdb.KeyValueWriter, bit uint, section uint64, head common.Hash, bits []byte) { - if err := db.Put(bloomBitsKey(bit, section, head), bits); err != nil { - log.Crit("Failed to store bloom bits", "err", err) - } -} - -// DeleteBloombits removes all compressed bloom bits vector belonging to the -// given section range and bit index. -func DeleteBloombits(db ethdb.Database, bit uint, from uint64, to uint64) { - start, end := bloomBitsKey(bit, from, common.Hash{}), bloomBitsKey(bit, to, common.Hash{}) - it := db.NewIterator(nil, start) - defer it.Release() - - for it.Next() { - if bytes.Compare(it.Key(), end) >= 0 { - break - } - if len(it.Key()) != len(bloomBitsPrefix)+2+8+32 { - continue - } - db.Delete(it.Key()) - } - if it.Error() != nil { - log.Crit("Failed to delete bloom bits", "err", it.Error()) - } -} diff --git a/builder/core/rawdb/accessors_indexes_test.go b/builder/core/rawdb/accessors_indexes_test.go deleted file mode 100644 index 124389ba7..000000000 --- a/builder/core/rawdb/accessors_indexes_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "bytes" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/blocktest" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -var newTestHasher = blocktest.NewHasher - -// Tests that positional lookup metadata can be stored and retrieved. -func TestLookupStorage(t *testing.T) { - tests := []struct { - name string - writeTxLookupEntriesByBlock func(ethdb.Writer, *types.Block) - }{ - { - "DatabaseV6", - func(db ethdb.Writer, block *types.Block) { - WriteTxLookupEntriesByBlock(db, block) - }, - }, - { - "DatabaseV4-V5", - func(db ethdb.Writer, block *types.Block) { - for _, tx := range block.Transactions() { - db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes()) - } - }, - }, - { - "DatabaseV3", - func(db ethdb.Writer, block *types.Block) { - for index, tx := range block.Transactions() { - entry := LegacyTxLookupEntry{ - BlockHash: block.Hash(), - BlockIndex: block.NumberU64(), - Index: uint64(index), - } - data, _ := rlp.EncodeToBytes(entry) - db.Put(txLookupKey(tx.Hash()), data) - } - }, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - db := NewMemoryDatabase() - - tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11}) - tx2 := types.NewTransaction(2, common.BytesToAddress([]byte{0x22}), big.NewInt(222), 2222, big.NewInt(22222), []byte{0x22, 0x22, 0x22}) - tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33}) - txs := []*types.Transaction{tx1, tx2, tx3} - - block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, newTestHasher()) - - // Check that no transactions entries are in a pristine database - for i, tx := range txs { - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { - t.Fatalf("tx #%d [%x]: non existent transaction returned: %v", i, tx.Hash(), txn) - } - } - // Insert all the transactions into the database, and verify contents - WriteCanonicalHash(db, block.Hash(), block.NumberU64()) - WriteBlock(db, block) - tc.writeTxLookupEntriesByBlock(db, block) - - for i, tx := range txs { - if txn, hash, number, index := ReadTransaction(db, tx.Hash()); txn == nil { - t.Fatalf("tx #%d [%x]: transaction not found", i, tx.Hash()) - } else { - if hash != block.Hash() || number != block.NumberU64() || index != uint64(i) { - t.Fatalf("tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v", i, tx.Hash(), hash, number, index, block.Hash(), block.NumberU64(), i) - } - if tx.Hash() != txn.Hash() { - t.Fatalf("tx #%d [%x]: transaction mismatch: have %v, want %v", i, tx.Hash(), txn, tx) - } - } - } - // Delete the transactions and check purge - for i, tx := range txs { - DeleteTxLookupEntry(db, tx.Hash()) - if txn, _, _, _ := ReadTransaction(db, tx.Hash()); txn != nil { - t.Fatalf("tx #%d [%x]: deleted transaction returned: %v", i, tx.Hash(), txn) - } - } - }) - } -} - -func TestDeleteBloomBits(t *testing.T) { - // Prepare testing data - db := NewMemoryDatabase() - for i := uint(0); i < 2; i++ { - for s := uint64(0); s < 2; s++ { - WriteBloomBits(db, i, s, params.MainnetGenesisHash, []byte{0x01, 0x02}) - WriteBloomBits(db, i, s, params.SepoliaGenesisHash, []byte{0x01, 0x02}) - } - } - check := func(bit uint, section uint64, head common.Hash, exist bool) { - bits, _ := ReadBloomBits(db, bit, section, head) - if exist && !bytes.Equal(bits, []byte{0x01, 0x02}) { - t.Fatalf("Bloombits mismatch") - } - if !exist && len(bits) > 0 { - t.Fatalf("Bloombits should be removed") - } - } - // Check the existence of written data. - check(0, 0, params.MainnetGenesisHash, true) - check(0, 0, params.SepoliaGenesisHash, true) - - // Check the existence of deleted data. - DeleteBloombits(db, 0, 0, 1) - check(0, 0, params.MainnetGenesisHash, false) - check(0, 0, params.SepoliaGenesisHash, false) - check(0, 1, params.MainnetGenesisHash, true) - check(0, 1, params.SepoliaGenesisHash, true) - - // Check the existence of deleted data. - DeleteBloombits(db, 0, 0, 2) - check(0, 0, params.MainnetGenesisHash, false) - check(0, 0, params.SepoliaGenesisHash, false) - check(0, 1, params.MainnetGenesisHash, false) - check(0, 1, params.SepoliaGenesisHash, false) - - // Bit1 shouldn't be affect. - check(1, 0, params.MainnetGenesisHash, true) - check(1, 0, params.SepoliaGenesisHash, true) - check(1, 1, params.MainnetGenesisHash, true) - check(1, 1, params.SepoliaGenesisHash, true) -} diff --git a/builder/core/rawdb/accessors_metadata.go b/builder/core/rawdb/accessors_metadata.go deleted file mode 100644 index 859566f72..000000000 --- a/builder/core/rawdb/accessors_metadata.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "encoding/json" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -// ReadDatabaseVersion retrieves the version number of the database. -func ReadDatabaseVersion(db ethdb.KeyValueReader) *uint64 { - var version uint64 - - enc, _ := db.Get(databaseVersionKey) - if len(enc) == 0 { - return nil - } - if err := rlp.DecodeBytes(enc, &version); err != nil { - return nil - } - - return &version -} - -// WriteDatabaseVersion stores the version number of the database -func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) { - enc, err := rlp.EncodeToBytes(version) - if err != nil { - log.Crit("Failed to encode database version", "err", err) - } - if err = db.Put(databaseVersionKey, enc); err != nil { - log.Crit("Failed to store the database version", "err", err) - } -} - -// ReadChainConfig retrieves the consensus settings based on the given genesis hash. -func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) *params.ChainConfig { - data, _ := db.Get(configKey(hash)) - if len(data) == 0 { - return nil - } - var config params.ChainConfig - if err := json.Unmarshal(data, &config); err != nil { - log.Error("Invalid chain config JSON", "hash", hash, "err", err) - return nil - } - return &config -} - -// WriteChainConfig writes the chain config settings to the database. -func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.ChainConfig) { - if cfg == nil { - return - } - data, err := json.Marshal(cfg) - if err != nil { - log.Crit("Failed to JSON encode chain config", "err", err) - } - if err := db.Put(configKey(hash), data); err != nil { - log.Crit("Failed to store chain config", "err", err) - } -} - -// ReadGenesisStateSpec retrieves the genesis state specification based on the -// given genesis (block-)hash. -func ReadGenesisStateSpec(db ethdb.KeyValueReader, blockhash common.Hash) []byte { - data, _ := db.Get(genesisStateSpecKey(blockhash)) - return data -} - -// WriteGenesisStateSpec writes the genesis state specification into the disk. -func WriteGenesisStateSpec(db ethdb.KeyValueWriter, blockhash common.Hash, data []byte) { - if err := db.Put(genesisStateSpecKey(blockhash), data); err != nil { - log.Crit("Failed to store genesis state", "err", err) - } -} - -// crashList is a list of unclean-shutdown-markers, for rlp-encoding to the -// database -type crashList struct { - Discarded uint64 // how many ucs have we deleted - Recent []uint64 // unix timestamps of 10 latest unclean shutdowns -} - -const crashesToKeep = 10 - -// PushUncleanShutdownMarker appends a new unclean shutdown marker and returns -// the previous data -// - a list of timestamps -// - a count of how many old unclean-shutdowns have been discarded -func PushUncleanShutdownMarker(db ethdb.KeyValueStore) ([]uint64, uint64, error) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err == nil { - if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - return nil, 0, err - } - } - var discarded = uncleanShutdowns.Discarded - var previous = make([]uint64, len(uncleanShutdowns.Recent)) - copy(previous, uncleanShutdowns.Recent) - // Add a new (but cap it) - uncleanShutdowns.Recent = append(uncleanShutdowns.Recent, uint64(time.Now().Unix())) - if count := len(uncleanShutdowns.Recent); count > crashesToKeep+1 { - numDel := count - (crashesToKeep + 1) - uncleanShutdowns.Recent = uncleanShutdowns.Recent[numDel:] - uncleanShutdowns.Discarded += uint64(numDel) - } - // And save it again - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to write unclean-shutdown marker", "err", err) - return nil, 0, err - } - return previous, discarded, nil -} - -// PopUncleanShutdownMarker removes the last unclean shutdown marker -func PopUncleanShutdownMarker(db ethdb.KeyValueStore) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err != nil { - log.Warn("Error reading unclean shutdown markers", "error", err) - } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - log.Error("Error decoding unclean shutdown markers", "error", err) // Should mos def _not_ happen - } - if l := len(uncleanShutdowns.Recent); l > 0 { - uncleanShutdowns.Recent = uncleanShutdowns.Recent[:l-1] - } - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to clear unclean-shutdown marker", "err", err) - } -} - -// UpdateUncleanShutdownMarker updates the last marker's timestamp to now. -func UpdateUncleanShutdownMarker(db ethdb.KeyValueStore) { - var uncleanShutdowns crashList - // Read old data - if data, err := db.Get(uncleanShutdownKey); err != nil { - log.Warn("Error reading unclean shutdown markers", "error", err) - } else if err := rlp.DecodeBytes(data, &uncleanShutdowns); err != nil { - log.Warn("Error decoding unclean shutdown markers", "error", err) - } - // This shouldn't happen because we push a marker on Backend instantiation - count := len(uncleanShutdowns.Recent) - if count == 0 { - log.Warn("No unclean shutdown marker to update") - return - } - uncleanShutdowns.Recent[count-1] = uint64(time.Now().Unix()) - data, _ := rlp.EncodeToBytes(uncleanShutdowns) - if err := db.Put(uncleanShutdownKey, data); err != nil { - log.Warn("Failed to write unclean-shutdown marker", "err", err) - } -} - -// ReadTransitionStatus retrieves the eth2 transition status from the database -func ReadTransitionStatus(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(transitionStatusKey) - return data -} - -// WriteTransitionStatus stores the eth2 transition status to the database -func WriteTransitionStatus(db ethdb.KeyValueWriter, data []byte) { - if err := db.Put(transitionStatusKey, data); err != nil { - log.Crit("Failed to store the eth2 transition status", "err", err) - } -} diff --git a/builder/core/rawdb/accessors_snapshot.go b/builder/core/rawdb/accessors_snapshot.go deleted file mode 100644 index 3c82b3f73..000000000 --- a/builder/core/rawdb/accessors_snapshot.go +++ /dev/null @@ -1,210 +0,0 @@ -// 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 rawdb - -import ( - "encoding/binary" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -// ReadSnapshotDisabled retrieves if the snapshot maintenance is disabled. -func ReadSnapshotDisabled(db ethdb.KeyValueReader) bool { - disabled, _ := db.Has(snapshotDisabledKey) - return disabled -} - -// WriteSnapshotDisabled stores the snapshot pause flag. -func WriteSnapshotDisabled(db ethdb.KeyValueWriter) { - if err := db.Put(snapshotDisabledKey, []byte("42")); err != nil { - log.Crit("Failed to store snapshot disabled flag", "err", err) - } -} - -// DeleteSnapshotDisabled deletes the flag keeping the snapshot maintenance disabled. -func DeleteSnapshotDisabled(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotDisabledKey); err != nil { - log.Crit("Failed to remove snapshot disabled flag", "err", err) - } -} - -// ReadSnapshotRoot retrieves the root of the block whose state is contained in -// the persisted snapshot. -func ReadSnapshotRoot(db ethdb.KeyValueReader) common.Hash { - data, _ := db.Get(SnapshotRootKey) - if len(data) != common.HashLength { - return common.Hash{} - } - return common.BytesToHash(data) -} - -// WriteSnapshotRoot stores the root of the block whose state is contained in -// the persisted snapshot. -func WriteSnapshotRoot(db ethdb.KeyValueWriter, root common.Hash) { - if err := db.Put(SnapshotRootKey, root[:]); err != nil { - log.Crit("Failed to store snapshot root", "err", err) - } -} - -// DeleteSnapshotRoot deletes the hash of the block whose state is contained in -// the persisted snapshot. Since snapshots are not immutable, this method can -// be used during updates, so a crash or failure will mark the entire snapshot -// invalid. -func DeleteSnapshotRoot(db ethdb.KeyValueWriter) { - if err := db.Delete(SnapshotRootKey); err != nil { - log.Crit("Failed to remove snapshot root", "err", err) - } -} - -// ReadAccountSnapshot retrieves the snapshot entry of an account trie leaf. -func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(accountSnapshotKey(hash)) - return data -} - -// WriteAccountSnapshot stores the snapshot entry of an account trie leaf. -func WriteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash, entry []byte) { - if err := db.Put(accountSnapshotKey(hash), entry); err != nil { - log.Crit("Failed to store account snapshot", "err", err) - } -} - -// DeleteAccountSnapshot removes the snapshot entry of an account trie leaf. -func DeleteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(accountSnapshotKey(hash)); err != nil { - log.Crit("Failed to delete account snapshot", "err", err) - } -} - -// ReadStorageSnapshot retrieves the snapshot entry of an storage trie leaf. -func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) []byte { - data, _ := db.Get(storageSnapshotKey(accountHash, storageHash)) - return data -} - -// WriteStorageSnapshot stores the snapshot entry of an storage trie leaf. -func WriteStorageSnapshot(db ethdb.KeyValueWriter, accountHash, storageHash common.Hash, entry []byte) { - if err := db.Put(storageSnapshotKey(accountHash, storageHash), entry); err != nil { - log.Crit("Failed to store storage snapshot", "err", err) - } -} - -// DeleteStorageSnapshot removes the snapshot entry of an storage trie leaf. -func DeleteStorageSnapshot(db ethdb.KeyValueWriter, accountHash, storageHash common.Hash) { - if err := db.Delete(storageSnapshotKey(accountHash, storageHash)); err != nil { - log.Crit("Failed to delete storage snapshot", "err", err) - } -} - -// IterateStorageSnapshots returns an iterator for walking the entire storage -// space of a specific account. -func IterateStorageSnapshots(db ethdb.Iteratee, accountHash common.Hash) ethdb.Iterator { - return NewKeyLengthIterator(db.NewIterator(storageSnapshotsKey(accountHash), nil), len(SnapshotStoragePrefix)+2*common.HashLength) -} - -// ReadSnapshotJournal retrieves the serialized in-memory diff layers saved at -// the last shutdown. The blob is expected to be max a few 10s of megabytes. -func ReadSnapshotJournal(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(snapshotJournalKey) - return data -} - -// WriteSnapshotJournal stores the serialized in-memory diff layers to save at -// shutdown. The blob is expected to be max a few 10s of megabytes. -func WriteSnapshotJournal(db ethdb.KeyValueWriter, journal []byte) { - if err := db.Put(snapshotJournalKey, journal); err != nil { - log.Crit("Failed to store snapshot journal", "err", err) - } -} - -// DeleteSnapshotJournal deletes the serialized in-memory diff layers saved at -// the last shutdown -func DeleteSnapshotJournal(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotJournalKey); err != nil { - log.Crit("Failed to remove snapshot journal", "err", err) - } -} - -// ReadSnapshotGenerator retrieves the serialized snapshot generator saved at -// the last shutdown. -func ReadSnapshotGenerator(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(snapshotGeneratorKey) - return data -} - -// WriteSnapshotGenerator stores the serialized snapshot generator to save at -// shutdown. -func WriteSnapshotGenerator(db ethdb.KeyValueWriter, generator []byte) { - if err := db.Put(snapshotGeneratorKey, generator); err != nil { - log.Crit("Failed to store snapshot generator", "err", err) - } -} - -// DeleteSnapshotGenerator deletes the serialized snapshot generator saved at -// the last shutdown -func DeleteSnapshotGenerator(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotGeneratorKey); err != nil { - log.Crit("Failed to remove snapshot generator", "err", err) - } -} - -// ReadSnapshotRecoveryNumber retrieves the block number of the last persisted -// snapshot layer. -func ReadSnapshotRecoveryNumber(db ethdb.KeyValueReader) *uint64 { - data, _ := db.Get(snapshotRecoveryKey) - if len(data) == 0 { - return nil - } - if len(data) != 8 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteSnapshotRecoveryNumber stores the block number of the last persisted -// snapshot layer. -func WriteSnapshotRecoveryNumber(db ethdb.KeyValueWriter, number uint64) { - var buf [8]byte - binary.BigEndian.PutUint64(buf[:], number) - if err := db.Put(snapshotRecoveryKey, buf[:]); err != nil { - log.Crit("Failed to store snapshot recovery number", "err", err) - } -} - -// DeleteSnapshotRecoveryNumber deletes the block number of the last persisted -// snapshot layer. -func DeleteSnapshotRecoveryNumber(db ethdb.KeyValueWriter) { - if err := db.Delete(snapshotRecoveryKey); err != nil { - log.Crit("Failed to remove snapshot recovery number", "err", err) - } -} - -// ReadSnapshotSyncStatus retrieves the serialized sync status saved at shutdown. -func ReadSnapshotSyncStatus(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(snapshotSyncStatusKey) - return data -} - -// WriteSnapshotSyncStatus stores the serialized sync status to save at shutdown. -func WriteSnapshotSyncStatus(db ethdb.KeyValueWriter, status []byte) { - if err := db.Put(snapshotSyncStatusKey, status); err != nil { - log.Crit("Failed to store snapshot sync status", "err", err) - } -} diff --git a/builder/core/rawdb/accessors_state.go b/builder/core/rawdb/accessors_state.go deleted file mode 100644 index 9ce58e7d2..000000000 --- a/builder/core/rawdb/accessors_state.go +++ /dev/null @@ -1,266 +0,0 @@ -// 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 rawdb - -import ( - "encoding/binary" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -// ReadPreimage retrieves a single preimage of the provided hash. -func ReadPreimage(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(preimageKey(hash)) - return data -} - -// WritePreimages writes the provided set of preimages to the database. -func WritePreimages(db ethdb.KeyValueWriter, preimages map[common.Hash][]byte) { - for hash, preimage := range preimages { - if err := db.Put(preimageKey(hash), preimage); err != nil { - log.Crit("Failed to store trie preimage", "err", err) - } - } - preimageCounter.Inc(int64(len(preimages))) - preimageHitCounter.Inc(int64(len(preimages))) -} - -// ReadCode retrieves the contract code of the provided code hash. -func ReadCode(db ethdb.KeyValueReader, hash common.Hash) []byte { - // Try with the prefixed code scheme first, if not then try with legacy - // scheme. - data := ReadCodeWithPrefix(db, hash) - if len(data) != 0 { - return data - } - data, _ = db.Get(hash.Bytes()) - return data -} - -// ReadCodeWithPrefix retrieves the contract code of the provided code hash. -// The main difference between this function and ReadCode is this function -// will only check the existence with latest scheme(with prefix). -func ReadCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, _ := db.Get(codeKey(hash)) - return data -} - -// HasCode checks if the contract code corresponding to the -// provided code hash is present in the db. -func HasCode(db ethdb.KeyValueReader, hash common.Hash) bool { - // Try with the prefixed code scheme first, if not then try with legacy - // scheme. - if ok := HasCodeWithPrefix(db, hash); ok { - return true - } - ok, _ := db.Has(hash.Bytes()) - return ok -} - -// HasCodeWithPrefix checks if the contract code corresponding to the -// provided code hash is present in the db. This function will only check -// presence using the prefix-scheme. -func HasCodeWithPrefix(db ethdb.KeyValueReader, hash common.Hash) bool { - ok, _ := db.Has(codeKey(hash)) - return ok -} - -// WriteCode writes the provided contract code database. -func WriteCode(db ethdb.KeyValueWriter, hash common.Hash, code []byte) { - if err := db.Put(codeKey(hash), code); err != nil { - log.Crit("Failed to store contract code", "err", err) - } -} - -// DeleteCode deletes the specified contract code from the database. -func DeleteCode(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(codeKey(hash)); err != nil { - log.Crit("Failed to delete contract code", "err", err) - } -} - -// ReadStateID retrieves the state id with the provided state root. -func ReadStateID(db ethdb.KeyValueReader, root common.Hash) *uint64 { - data, err := db.Get(stateIDKey(root)) - if err != nil || len(data) == 0 { - return nil - } - number := binary.BigEndian.Uint64(data) - return &number -} - -// WriteStateID writes the provided state lookup to database. -func WriteStateID(db ethdb.KeyValueWriter, root common.Hash, id uint64) { - var buff [8]byte - binary.BigEndian.PutUint64(buff[:], id) - if err := db.Put(stateIDKey(root), buff[:]); err != nil { - log.Crit("Failed to store state ID", "err", err) - } -} - -// DeleteStateID deletes the specified state lookup from the database. -func DeleteStateID(db ethdb.KeyValueWriter, root common.Hash) { - if err := db.Delete(stateIDKey(root)); err != nil { - log.Crit("Failed to delete state ID", "err", err) - } -} - -// ReadPersistentStateID retrieves the id of the persistent state from the database. -func ReadPersistentStateID(db ethdb.KeyValueReader) uint64 { - data, _ := db.Get(persistentStateIDKey) - if len(data) != 8 { - return 0 - } - return binary.BigEndian.Uint64(data) -} - -// WritePersistentStateID stores the id of the persistent state into database. -func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(persistentStateIDKey, encodeBlockNumber(number)); err != nil { - log.Crit("Failed to store the persistent state ID", "err", err) - } -} - -// ReadTrieJournal retrieves the serialized in-memory trie nodes of layers saved at -// the last shutdown. -func ReadTrieJournal(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(trieJournalKey) - return data -} - -// WriteTrieJournal stores the serialized in-memory trie nodes of layers to save at -// shutdown. -func WriteTrieJournal(db ethdb.KeyValueWriter, journal []byte) { - if err := db.Put(trieJournalKey, journal); err != nil { - log.Crit("Failed to store tries journal", "err", err) - } -} - -// DeleteTrieJournal deletes the serialized in-memory trie nodes of layers saved at -// the last shutdown. -func DeleteTrieJournal(db ethdb.KeyValueWriter) { - if err := db.Delete(trieJournalKey); err != nil { - log.Crit("Failed to remove tries journal", "err", err) - } -} - -// ReadStateHistoryMeta retrieves the metadata corresponding to the specified -// state history. Compute the position of state history in freezer by minus -// one since the id of first state history starts from one(zero for initial -// state). -func ReadStateHistoryMeta(db ethdb.AncientReaderOp, id uint64) []byte { - blob, err := db.Ancient(stateHistoryMeta, id-1) - if err != nil { - return nil - } - return blob -} - -// ReadStateHistoryMetaList retrieves a batch of meta objects with the specified -// start position and count. Compute the position of state history in freezer by -// minus one since the id of first state history starts from one(zero for initial -// state). -func ReadStateHistoryMetaList(db ethdb.AncientReaderOp, start uint64, count uint64) ([][]byte, error) { - return db.AncientRange(stateHistoryMeta, start-1, count, 0) -} - -// ReadStateAccountIndex retrieves the state root corresponding to the specified -// state history. Compute the position of state history in freezer by minus one -// since the id of first state history starts from one(zero for initial state). -func ReadStateAccountIndex(db ethdb.AncientReaderOp, id uint64) []byte { - blob, err := db.Ancient(stateHistoryAccountIndex, id-1) - if err != nil { - return nil - } - return blob -} - -// ReadStateStorageIndex retrieves the state root corresponding to the specified -// state history. Compute the position of state history in freezer by minus one -// since the id of first state history starts from one(zero for initial state). -func ReadStateStorageIndex(db ethdb.AncientReaderOp, id uint64) []byte { - blob, err := db.Ancient(stateHistoryStorageIndex, id-1) - if err != nil { - return nil - } - return blob -} - -// ReadStateAccountHistory retrieves the state root corresponding to the specified -// state history. Compute the position of state history in freezer by minus one -// since the id of first state history starts from one(zero for initial state). -func ReadStateAccountHistory(db ethdb.AncientReaderOp, id uint64) []byte { - blob, err := db.Ancient(stateHistoryAccountData, id-1) - if err != nil { - return nil - } - return blob -} - -// ReadStateStorageHistory retrieves the state root corresponding to the specified -// state history. Compute the position of state history in freezer by minus one -// since the id of first state history starts from one(zero for initial state). -func ReadStateStorageHistory(db ethdb.AncientReaderOp, id uint64) []byte { - blob, err := db.Ancient(stateHistoryStorageData, id-1) - if err != nil { - return nil - } - return blob -} - -// ReadStateHistory retrieves the state history from database with provided id. -// Compute the position of state history in freezer by minus one since the id -// of first state history starts from one(zero for initial state). -func ReadStateHistory(db ethdb.AncientReaderOp, id uint64) ([]byte, []byte, []byte, []byte, []byte, error) { - meta, err := db.Ancient(stateHistoryMeta, id-1) - if err != nil { - return nil, nil, nil, nil, nil, err - } - accountIndex, err := db.Ancient(stateHistoryAccountIndex, id-1) - if err != nil { - return nil, nil, nil, nil, nil, err - } - storageIndex, err := db.Ancient(stateHistoryStorageIndex, id-1) - if err != nil { - return nil, nil, nil, nil, nil, err - } - accountData, err := db.Ancient(stateHistoryAccountData, id-1) - if err != nil { - return nil, nil, nil, nil, nil, err - } - storageData, err := db.Ancient(stateHistoryStorageData, id-1) - if err != nil { - return nil, nil, nil, nil, nil, err - } - return meta, accountIndex, storageIndex, accountData, storageData, nil -} - -// WriteStateHistory writes the provided state history to database. Compute the -// position of state history in freezer by minus one since the id of first state -// history starts from one(zero for initial state). -func WriteStateHistory(db ethdb.AncientWriter, id uint64, meta []byte, accountIndex []byte, storageIndex []byte, accounts []byte, storages []byte) { - db.ModifyAncients(func(op ethdb.AncientWriteOp) error { - op.AppendRaw(stateHistoryMeta, id-1, meta) - op.AppendRaw(stateHistoryAccountIndex, id-1, accountIndex) - op.AppendRaw(stateHistoryStorageIndex, id-1, storageIndex) - op.AppendRaw(stateHistoryAccountData, id-1, accounts) - op.AppendRaw(stateHistoryStorageData, id-1, storages) - return nil - }) -} diff --git a/builder/core/rawdb/accessors_sync.go b/builder/core/rawdb/accessors_sync.go deleted file mode 100644 index 2dc08b3b7..000000000 --- a/builder/core/rawdb/accessors_sync.go +++ /dev/null @@ -1,100 +0,0 @@ -// 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 rawdb - -import ( - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// ReadSkeletonSyncStatus retrieves the serialized sync status saved at shutdown. -func ReadSkeletonSyncStatus(db ethdb.KeyValueReader) []byte { - data, _ := db.Get(skeletonSyncStatusKey) - return data -} - -// WriteSkeletonSyncStatus stores the serialized sync status to save at shutdown. -func WriteSkeletonSyncStatus(db ethdb.KeyValueWriter, status []byte) { - if err := db.Put(skeletonSyncStatusKey, status); err != nil { - log.Crit("Failed to store skeleton sync status", "err", err) - } -} - -// DeleteSkeletonSyncStatus deletes the serialized sync status saved at the last -// shutdown -func DeleteSkeletonSyncStatus(db ethdb.KeyValueWriter) { - if err := db.Delete(skeletonSyncStatusKey); err != nil { - log.Crit("Failed to remove skeleton sync status", "err", err) - } -} - -// ReadSkeletonHeader retrieves a block header from the skeleton sync store, -func ReadSkeletonHeader(db ethdb.KeyValueReader, number uint64) *types.Header { - data, _ := db.Get(skeletonHeaderKey(number)) - if len(data) == 0 { - return nil - } - header := new(types.Header) - if err := rlp.DecodeBytes(data, header); err != nil { - log.Error("Invalid skeleton header RLP", "number", number, "err", err) - return nil - } - return header -} - -// WriteSkeletonHeader stores a block header into the skeleton sync store. -func WriteSkeletonHeader(db ethdb.KeyValueWriter, header *types.Header) { - data, err := rlp.EncodeToBytes(header) - if err != nil { - log.Crit("Failed to RLP encode header", "err", err) - } - key := skeletonHeaderKey(header.Number.Uint64()) - if err := db.Put(key, data); err != nil { - log.Crit("Failed to store skeleton header", "err", err) - } -} - -// DeleteSkeletonHeader removes all block header data associated with a hash. -func DeleteSkeletonHeader(db ethdb.KeyValueWriter, number uint64) { - if err := db.Delete(skeletonHeaderKey(number)); err != nil { - log.Crit("Failed to delete skeleton header", "err", err) - } -} - -const ( - StateSyncUnknown = uint8(0) // flags the state snap sync is unknown - StateSyncRunning = uint8(1) // flags the state snap sync is not completed yet - StateSyncFinished = uint8(2) // flags the state snap sync is completed -) - -// ReadSnapSyncStatusFlag retrieves the state snap sync status flag. -func ReadSnapSyncStatusFlag(db ethdb.KeyValueReader) uint8 { - blob, err := db.Get(snapSyncStatusFlagKey) - if err != nil || len(blob) != 1 { - return StateSyncUnknown - } - return blob[0] -} - -// WriteSnapSyncStatusFlag stores the state snap sync status flag into database. -func WriteSnapSyncStatusFlag(db ethdb.KeyValueWriter, flag uint8) { - if err := db.Put(snapSyncStatusFlagKey, []byte{flag}); err != nil { - log.Crit("Failed to store sync status flag", "err", err) - } -} diff --git a/builder/core/rawdb/accessors_trie.go b/builder/core/rawdb/accessors_trie.go deleted file mode 100644 index ea3367db3..000000000 --- a/builder/core/rawdb/accessors_trie.go +++ /dev/null @@ -1,347 +0,0 @@ -// 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 rawdb - -import ( - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "golang.org/x/crypto/sha3" -) - -// HashScheme is the legacy hash-based state scheme with which trie nodes are -// stored in the disk with node hash as the database key. The advantage of this -// scheme is that different versions of trie nodes can be stored in disk, which -// is very beneficial for constructing archive nodes. The drawback is it will -// store different trie nodes on the same path to different locations on the disk -// with no data locality, and it's unfriendly for designing state pruning. -// -// Now this scheme is still kept for backward compatibility, and it will be used -// for archive node and some other tries(e.g. light trie). -const HashScheme = "hash" - -// PathScheme is the new path-based state scheme with which trie nodes are stored -// in the disk with node path as the database key. This scheme will only store one -// version of state data in the disk, which means that the state pruning operation -// is native. At the same time, this scheme will put adjacent trie nodes in the same -// area of the disk with good data locality property. But this scheme needs to rely -// on extra state diffs to survive deep reorg. -const PathScheme = "path" - -// hasher is used to compute the sha256 hash of the provided data. -type hasher struct{ sha crypto.KeccakState } - -var hasherPool = sync.Pool{ - New: func() interface{} { return &hasher{sha: sha3.NewLegacyKeccak256().(crypto.KeccakState)} }, -} - -func newHasher() *hasher { - return hasherPool.Get().(*hasher) -} - -func (h *hasher) hash(data []byte) common.Hash { - return crypto.HashData(h.sha, data) -} - -func (h *hasher) release() { - hasherPool.Put(h) -} - -// ReadAccountTrieNode retrieves the account trie node and the associated node -// hash with the specified node path. -func ReadAccountTrieNode(db ethdb.KeyValueReader, path []byte) ([]byte, common.Hash) { - data, err := db.Get(accountTrieNodeKey(path)) - if err != nil { - return nil, common.Hash{} - } - h := newHasher() - defer h.release() - return data, h.hash(data) -} - -// HasAccountTrieNode checks the account trie node presence with the specified -// node path and the associated node hash. -func HasAccountTrieNode(db ethdb.KeyValueReader, path []byte, hash common.Hash) bool { - data, err := db.Get(accountTrieNodeKey(path)) - if err != nil { - return false - } - h := newHasher() - defer h.release() - return h.hash(data) == hash -} - -// ExistsAccountTrieNode checks the presence of the account trie node with the -// specified node path, regardless of the node hash. -func ExistsAccountTrieNode(db ethdb.KeyValueReader, path []byte) bool { - has, err := db.Has(accountTrieNodeKey(path)) - if err != nil { - return false - } - return has -} - -// WriteAccountTrieNode writes the provided account trie node into database. -func WriteAccountTrieNode(db ethdb.KeyValueWriter, path []byte, node []byte) { - if err := db.Put(accountTrieNodeKey(path), node); err != nil { - log.Crit("Failed to store account trie node", "err", err) - } -} - -// DeleteAccountTrieNode deletes the specified account trie node from the database. -func DeleteAccountTrieNode(db ethdb.KeyValueWriter, path []byte) { - if err := db.Delete(accountTrieNodeKey(path)); err != nil { - log.Crit("Failed to delete account trie node", "err", err) - } -} - -// ReadStorageTrieNode retrieves the storage trie node and the associated node -// hash with the specified node path. -func ReadStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) ([]byte, common.Hash) { - data, err := db.Get(storageTrieNodeKey(accountHash, path)) - if err != nil { - return nil, common.Hash{} - } - h := newHasher() - defer h.release() - return data, h.hash(data) -} - -// HasStorageTrieNode checks the storage trie node presence with the provided -// node path and the associated node hash. -func HasStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte, hash common.Hash) bool { - data, err := db.Get(storageTrieNodeKey(accountHash, path)) - if err != nil { - return false - } - h := newHasher() - defer h.release() - return h.hash(data) == hash -} - -// ExistsStorageTrieNode checks the presence of the storage trie node with the -// specified account hash and node path, regardless of the node hash. -func ExistsStorageTrieNode(db ethdb.KeyValueReader, accountHash common.Hash, path []byte) bool { - has, err := db.Has(storageTrieNodeKey(accountHash, path)) - if err != nil { - return false - } - return has -} - -// WriteStorageTrieNode writes the provided storage trie node into database. -func WriteStorageTrieNode(db ethdb.KeyValueWriter, accountHash common.Hash, path []byte, node []byte) { - if err := db.Put(storageTrieNodeKey(accountHash, path), node); err != nil { - log.Crit("Failed to store storage trie node", "err", err) - } -} - -// DeleteStorageTrieNode deletes the specified storage trie node from the database. -func DeleteStorageTrieNode(db ethdb.KeyValueWriter, accountHash common.Hash, path []byte) { - if err := db.Delete(storageTrieNodeKey(accountHash, path)); err != nil { - log.Crit("Failed to delete storage trie node", "err", err) - } -} - -// ReadLegacyTrieNode retrieves the legacy trie node with the given -// associated node hash. -func ReadLegacyTrieNode(db ethdb.KeyValueReader, hash common.Hash) []byte { - data, err := db.Get(hash.Bytes()) - if err != nil { - return nil - } - return data -} - -// HasLegacyTrieNode checks if the trie node with the provided hash is present in db. -func HasLegacyTrieNode(db ethdb.KeyValueReader, hash common.Hash) bool { - ok, _ := db.Has(hash.Bytes()) - return ok -} - -// WriteLegacyTrieNode writes the provided legacy trie node to database. -func WriteLegacyTrieNode(db ethdb.KeyValueWriter, hash common.Hash, node []byte) { - if err := db.Put(hash.Bytes(), node); err != nil { - log.Crit("Failed to store legacy trie node", "err", err) - } -} - -// DeleteLegacyTrieNode deletes the specified legacy trie node from database. -func DeleteLegacyTrieNode(db ethdb.KeyValueWriter, hash common.Hash) { - if err := db.Delete(hash.Bytes()); err != nil { - log.Crit("Failed to delete legacy trie node", "err", err) - } -} - -// HasTrieNode checks the trie node presence with the provided node info and -// the associated node hash. -func HasTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash common.Hash, scheme string) bool { - switch scheme { - case HashScheme: - return HasLegacyTrieNode(db, hash) - case PathScheme: - if owner == (common.Hash{}) { - return HasAccountTrieNode(db, path, hash) - } - return HasStorageTrieNode(db, owner, path, hash) - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// ReadTrieNode retrieves the trie node from database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func ReadTrieNode(db ethdb.KeyValueReader, owner common.Hash, path []byte, hash common.Hash, scheme string) []byte { - switch scheme { - case HashScheme: - return ReadLegacyTrieNode(db, hash) - case PathScheme: - var ( - blob []byte - nHash common.Hash - ) - if owner == (common.Hash{}) { - blob, nHash = ReadAccountTrieNode(db, path) - } else { - blob, nHash = ReadStorageTrieNode(db, owner, path) - } - if nHash != hash { - return nil - } - return blob - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// WriteTrieNode writes the trie node into database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func WriteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, hash common.Hash, node []byte, scheme string) { - switch scheme { - case HashScheme: - WriteLegacyTrieNode(db, hash, node) - case PathScheme: - if owner == (common.Hash{}) { - WriteAccountTrieNode(db, path, node) - } else { - WriteStorageTrieNode(db, owner, path, node) - } - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// DeleteTrieNode deletes the trie node from database with the provided node info -// and associated node hash. -// hashScheme-based lookup requires the following: -// - hash -// -// pathScheme-based lookup requires the following: -// - owner -// - path -func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, hash common.Hash, scheme string) { - switch scheme { - case HashScheme: - DeleteLegacyTrieNode(db, hash) - case PathScheme: - if owner == (common.Hash{}) { - DeleteAccountTrieNode(db, path) - } else { - DeleteStorageTrieNode(db, owner, path) - } - default: - panic(fmt.Sprintf("Unknown scheme %v", scheme)) - } -} - -// ReadStateScheme reads the state scheme of persistent state, or none -// if the state is not present in database. -func ReadStateScheme(db ethdb.Reader) string { - // Check if state in path-based scheme is present - blob, _ := ReadAccountTrieNode(db, nil) - if len(blob) != 0 { - return PathScheme - } - // The root node might be deleted during the initial snap sync, check - // the persistent state id then. - if id := ReadPersistentStateID(db); id != 0 { - return PathScheme - } - // In a hash-based scheme, the genesis state is consistently stored - // on the disk. To assess the scheme of the persistent state, it - // suffices to inspect the scheme of the genesis state. - header := ReadHeader(db, ReadCanonicalHash(db, 0), 0) - if header == nil { - return "" // empty datadir - } - blob = ReadLegacyTrieNode(db, header.Root) - if len(blob) == 0 { - return "" // no state in disk - } - return HashScheme -} - -// ParseStateScheme checks if the specified state scheme is compatible with -// the stored state. -// -// - If the provided scheme is none, use the scheme consistent with persistent -// state, or fallback to hash-based scheme if state is empty. -// -// - If the provided scheme is hash, use hash-based scheme or error out if not -// compatible with persistent state scheme. -// -// - If the provided scheme is path: use path-based scheme or error out if not -// compatible with persistent state scheme. -func ParseStateScheme(provided string, disk ethdb.Database) (string, error) { - // If state scheme is not specified, use the scheme consistent - // with persistent state, or fallback to hash mode if database - // is empty. - stored := ReadStateScheme(disk) - if provided == "" { - if stored == "" { - // use default scheme for empty database, flip it when - // path mode is chosen as default - log.Info("State schema set to default", "scheme", "hash") - return HashScheme, nil - } - log.Info("State scheme set to already existing", "scheme", stored) - return stored, nil // reuse scheme of persistent scheme - } - // If state scheme is specified, ensure it's compatible with - // persistent state. - if stored == "" || provided == stored { - log.Info("State scheme set by user", "scheme", provided) - return provided, nil - } - return "", fmt.Errorf("incompatible state scheme, stored: %s, provided: %s", stored, provided) -} diff --git a/builder/core/rawdb/ancient_scheme.go b/builder/core/rawdb/ancient_scheme.go deleted file mode 100644 index e88867af0..000000000 --- a/builder/core/rawdb/ancient_scheme.go +++ /dev/null @@ -1,81 +0,0 @@ -// 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 rawdb - -import "path/filepath" - -// The list of table names of chain freezer. -const ( - // ChainFreezerHeaderTable indicates the name of the freezer header table. - ChainFreezerHeaderTable = "headers" - - // ChainFreezerHashTable indicates the name of the freezer canonical hash table. - ChainFreezerHashTable = "hashes" - - // ChainFreezerBodiesTable indicates the name of the freezer block body table. - ChainFreezerBodiesTable = "bodies" - - // ChainFreezerReceiptTable indicates the name of the freezer receipts table. - ChainFreezerReceiptTable = "receipts" - - // ChainFreezerDifficultyTable indicates the name of the freezer total difficulty table. - ChainFreezerDifficultyTable = "diffs" -) - -// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables. -// Hashes and difficulties don't compress well. -var chainFreezerNoSnappy = map[string]bool{ - ChainFreezerHeaderTable: false, - ChainFreezerHashTable: true, - ChainFreezerBodiesTable: false, - ChainFreezerReceiptTable: false, - ChainFreezerDifficultyTable: true, -} - -const ( - // stateHistoryTableSize defines the maximum size of freezer data files. - stateHistoryTableSize = 2 * 1000 * 1000 * 1000 - - // stateHistoryAccountIndex indicates the name of the freezer state history table. - stateHistoryMeta = "history.meta" - stateHistoryAccountIndex = "account.index" - stateHistoryStorageIndex = "storage.index" - stateHistoryAccountData = "account.data" - stateHistoryStorageData = "storage.data" -) - -var stateFreezerNoSnappy = map[string]bool{ - stateHistoryMeta: true, - stateHistoryAccountIndex: false, - stateHistoryStorageIndex: false, - stateHistoryAccountData: false, - stateHistoryStorageData: false, -} - -// The list of identifiers of ancient stores. -var ( - ChainFreezerName = "chain" // the folder name of chain segment ancient store. - StateFreezerName = "state" // the folder name of reverse diff ancient store. -) - -// freezers the collections of all builtin freezers. -var freezers = []string{ChainFreezerName, StateFreezerName} - -// NewStateFreezer initializes the freezer for state history. -func NewStateFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) { - return NewResettableFreezer(filepath.Join(ancientDir, StateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy) -} diff --git a/builder/core/rawdb/ancient_utils.go b/builder/core/rawdb/ancient_utils.go deleted file mode 100644 index 428cda544..000000000 --- a/builder/core/rawdb/ancient_utils.go +++ /dev/null @@ -1,149 +0,0 @@ -// 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 rawdb - -import ( - "fmt" - "path/filepath" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" -) - -type tableSize struct { - name string - size common.StorageSize -} - -// freezerInfo contains the basic information of the freezer. -type freezerInfo struct { - name string // The identifier of freezer - head uint64 // The number of last stored item in the freezer - tail uint64 // The number of first stored item in the freezer - sizes []tableSize // The storage size per table -} - -// count returns the number of stored items in the freezer. -func (info *freezerInfo) count() uint64 { - return info.head - info.tail + 1 -} - -// size returns the storage size of the entire freezer. -func (info *freezerInfo) size() common.StorageSize { - var total common.StorageSize - for _, table := range info.sizes { - total += table.size - } - return total -} - -func inspect(name string, order map[string]bool, reader ethdb.AncientReader) (freezerInfo, error) { - info := freezerInfo{name: name} - for t := range order { - size, err := reader.AncientSize(t) - if err != nil { - return freezerInfo{}, err - } - info.sizes = append(info.sizes, tableSize{name: t, size: common.StorageSize(size)}) - } - // Retrieve the number of last stored item - ancients, err := reader.Ancients() - if err != nil { - return freezerInfo{}, err - } - info.head = ancients - 1 - - // Retrieve the number of first stored item - tail, err := reader.Tail() - if err != nil { - return freezerInfo{}, err - } - info.tail = tail - return info, nil -} - -// inspectFreezers inspects all freezers registered in the system. -func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) { - var infos []freezerInfo - for _, freezer := range freezers { - switch freezer { - case ChainFreezerName: - info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db) - if err != nil { - return nil, err - } - infos = append(infos, info) - - case StateFreezerName: - if ReadStateScheme(db) != PathScheme { - continue - } - datadir, err := db.AncientDatadir() - if err != nil { - return nil, err - } - f, err := NewStateFreezer(datadir, true) - if err != nil { - return nil, err - } - defer f.Close() - - info, err := inspect(StateFreezerName, stateFreezerNoSnappy, f) - if err != nil { - return nil, err - } - infos = append(infos, info) - - default: - return nil, fmt.Errorf("unknown freezer, supported ones: %v", freezers) - } - } - return infos, nil -} - -// InspectFreezerTable dumps out the index of a specific freezer table. The passed -// ancient indicates the path of root ancient directory where the chain freezer can -// be opened. Start and end specify the range for dumping out indexes. -// Note this function can only be used for debugging purposes. -func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error { - var ( - path string - tables map[string]bool - ) - switch freezerName { - case ChainFreezerName: - path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy - case StateFreezerName: - path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy - default: - return fmt.Errorf("unknown freezer, supported ones: %v", freezers) - } - noSnappy, exist := tables[tableName] - if !exist { - var names []string - for name := range tables { - names = append(names, name) - } - return fmt.Errorf("unknown table, supported ones: %v", names) - } - table, err := newFreezerTable(path, tableName, noSnappy, true) - if err != nil { - return err - } - table.dumpIndexStdout(start, end) - return nil -} diff --git a/builder/core/rawdb/chain_freezer.go b/builder/core/rawdb/chain_freezer.go deleted file mode 100644 index bb2c409db..000000000 --- a/builder/core/rawdb/chain_freezer.go +++ /dev/null @@ -1,303 +0,0 @@ -// 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 rawdb - -import ( - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" -) - -const ( - // freezerRecheckInterval is the frequency to check the key-value database for - // chain progression that might permit new blocks to be frozen into immutable - // storage. - freezerRecheckInterval = time.Minute - - // freezerBatchLimit is the maximum number of blocks to freeze in one batch - // before doing an fsync and deleting it from the key-value store. - freezerBatchLimit = 30000 -) - -// chainFreezer is a wrapper of freezer with additional chain freezing feature. -// The background thread will keep moving ancient chain segments from key-value -// database to flat files for saving space on live database. -type chainFreezer struct { - threshold atomic.Uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests) - - *Freezer - quit chan struct{} - wg sync.WaitGroup - trigger chan chan struct{} // Manual blocking freeze trigger, test determinism -} - -// newChainFreezer initializes the freezer for ancient chain data. -func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFreezer, error) { - freezer, err := NewChainFreezer(datadir, namespace, readonly) - if err != nil { - return nil, err - } - cf := chainFreezer{ - Freezer: freezer, - quit: make(chan struct{}), - trigger: make(chan chan struct{}), - } - cf.threshold.Store(params.FullImmutabilityThreshold) - return &cf, nil -} - -// Close closes the chain freezer instance and terminates the background thread. -func (f *chainFreezer) Close() error { - select { - case <-f.quit: - default: - close(f.quit) - } - f.wg.Wait() - return f.Freezer.Close() -} - -// freeze is a background thread that periodically checks the blockchain for any -// import progress and moves ancient data from the fast database into the freezer. -// -// This functionality is deliberately broken off from block importing to avoid -// incurring additional data shuffling delays on block propagation. -func (f *chainFreezer) freeze(db ethdb.KeyValueStore) { - var ( - backoff bool - triggered chan struct{} // Used in tests - nfdb = &nofreezedb{KeyValueStore: db} - ) - timer := time.NewTimer(freezerRecheckInterval) - defer timer.Stop() - - for { - select { - case <-f.quit: - log.Info("Freezer shutting down") - return - default: - } - if backoff { - // If we were doing a manual trigger, notify it - if triggered != nil { - triggered <- struct{}{} - triggered = nil - } - select { - case <-timer.C: - backoff = false - timer.Reset(freezerRecheckInterval) - case triggered = <-f.trigger: - backoff = false - case <-f.quit: - return - } - } - // Retrieve the freezing threshold. - hash := ReadHeadBlockHash(nfdb) - if hash == (common.Hash{}) { - log.Debug("Current full block hash unavailable") // new chain, empty database - backoff = true - continue - } - number := ReadHeaderNumber(nfdb, hash) - threshold := f.threshold.Load() - frozen := f.frozen.Load() - switch { - case number == nil: - log.Error("Current full block number unavailable", "hash", hash) - backoff = true - continue - - case *number < threshold: - log.Debug("Current full block not old enough to freeze", "number", *number, "hash", hash, "delay", threshold) - backoff = true - continue - - case *number-threshold <= frozen: - log.Debug("Ancient blocks frozen already", "number", *number, "hash", hash, "frozen", frozen) - backoff = true - continue - } - head := ReadHeader(nfdb, hash, *number) - if head == nil { - log.Error("Current full block unavailable", "number", *number, "hash", hash) - backoff = true - continue - } - - // Seems we have data ready to be frozen, process in usable batches - var ( - start = time.Now() - first, _ = f.Ancients() - limit = *number - threshold - ) - if limit-first > freezerBatchLimit { - limit = first + freezerBatchLimit - } - ancients, err := f.freezeRange(nfdb, first, limit) - if err != nil { - log.Error("Error in block freeze operation", "err", err) - backoff = true - continue - } - - // Batch of blocks have been frozen, flush them before wiping from leveldb - if err := f.Sync(); err != nil { - log.Crit("Failed to flush frozen tables", "err", err) - } - - // Wipe out all data from the active database - batch := db.NewBatch() - for i := 0; i < len(ancients); i++ { - // Always keep the genesis block in active database - if first+uint64(i) != 0 { - DeleteBlockWithoutNumber(batch, ancients[i], first+uint64(i)) - DeleteCanonicalHash(batch, first+uint64(i)) - } - } - if err := batch.Write(); err != nil { - log.Crit("Failed to delete frozen canonical blocks", "err", err) - } - batch.Reset() - - // Wipe out side chains also and track dangling side chains - var dangling []common.Hash - frozen = f.frozen.Load() // Needs reload after during freezeRange - for number := first; number < frozen; number++ { - // Always keep the genesis block in active database - if number != 0 { - dangling = ReadAllHashes(db, number) - for _, hash := range dangling { - log.Trace("Deleting side chain", "number", number, "hash", hash) - DeleteBlock(batch, hash, number) - } - } - } - if err := batch.Write(); err != nil { - log.Crit("Failed to delete frozen side blocks", "err", err) - } - batch.Reset() - - // Step into the future and delete any dangling side chains - if frozen > 0 { - tip := frozen - for len(dangling) > 0 { - drop := make(map[common.Hash]struct{}) - for _, hash := range dangling { - log.Debug("Dangling parent from Freezer", "number", tip-1, "hash", hash) - drop[hash] = struct{}{} - } - children := ReadAllHashes(db, tip) - for i := 0; i < len(children); i++ { - // Dig up the child and ensure it's dangling - child := ReadHeader(nfdb, children[i], tip) - if child == nil { - log.Error("Missing dangling header", "number", tip, "hash", children[i]) - continue - } - if _, ok := drop[child.ParentHash]; !ok { - children = append(children[:i], children[i+1:]...) - i-- - continue - } - // Delete all block data associated with the child - log.Debug("Deleting dangling block", "number", tip, "hash", children[i], "parent", child.ParentHash) - DeleteBlock(batch, children[i], tip) - } - dangling = children - tip++ - } - if err := batch.Write(); err != nil { - log.Crit("Failed to delete dangling side blocks", "err", err) - } - } - - // Log something friendly for the user - context := []interface{}{ - "blocks", frozen - first, "elapsed", common.PrettyDuration(time.Since(start)), "number", frozen - 1, - } - if n := len(ancients); n > 0 { - context = append(context, []interface{}{"hash", ancients[n-1]}...) - } - log.Debug("Deep froze chain segment", context...) - - // Avoid database thrashing with tiny writes - if frozen-first < freezerBatchLimit { - backoff = true - } - } -} - -func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hashes []common.Hash, err error) { - hashes = make([]common.Hash, 0, limit-number) - - _, err = f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for ; number <= limit; number++ { - // Retrieve all the components of the canonical block. - hash := ReadCanonicalHash(nfdb, number) - if hash == (common.Hash{}) { - return fmt.Errorf("canonical hash missing, can't freeze block %d", number) - } - header := ReadHeaderRLP(nfdb, hash, number) - if len(header) == 0 { - return fmt.Errorf("block header missing, can't freeze block %d", number) - } - body := ReadBodyRLP(nfdb, hash, number) - if len(body) == 0 { - return fmt.Errorf("block body missing, can't freeze block %d", number) - } - receipts := ReadReceiptsRLP(nfdb, hash, number) - if len(receipts) == 0 { - return fmt.Errorf("block receipts missing, can't freeze block %d", number) - } - td := ReadTdRLP(nfdb, hash, number) - if len(td) == 0 { - return fmt.Errorf("total difficulty missing, can't freeze block %d", number) - } - - // Write to the batch. - if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil { - return fmt.Errorf("can't write hash to Freezer: %v", err) - } - if err := op.AppendRaw(ChainFreezerHeaderTable, number, header); err != nil { - return fmt.Errorf("can't write header to Freezer: %v", err) - } - if err := op.AppendRaw(ChainFreezerBodiesTable, number, body); err != nil { - return fmt.Errorf("can't write body to Freezer: %v", err) - } - if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil { - return fmt.Errorf("can't write receipts to Freezer: %v", err) - } - if err := op.AppendRaw(ChainFreezerDifficultyTable, number, td); err != nil { - return fmt.Errorf("can't write td to Freezer: %v", err) - } - - hashes = append(hashes, hash) - } - return nil - }) - - return hashes, err -} diff --git a/builder/core/rawdb/chain_iterator.go b/builder/core/rawdb/chain_iterator.go deleted file mode 100644 index 759e5913d..000000000 --- a/builder/core/rawdb/chain_iterator.go +++ /dev/null @@ -1,363 +0,0 @@ -// 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 rawdb - -import ( - "runtime" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// InitDatabaseFromFreezer reinitializes an empty database from a previous batch -// of frozen ancient blocks. The method iterates over all the frozen blocks and -// injects into the database the block hash->number mappings. -func InitDatabaseFromFreezer(db ethdb.Database) { - // If we can't access the freezer or it's empty, abort - frozen, err := db.Ancients() - if err != nil || frozen == 0 { - return - } - var ( - batch = db.NewBatch() - start = time.Now() - logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log - hash common.Hash - ) - for i := uint64(0); i < frozen; { - // We read 100K hashes at a time, for a total of 3.2M - count := uint64(100_000) - if i+count > frozen { - count = frozen - i - } - data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count) - if err != nil { - log.Crit("Failed to init database from freezer", "err", err) - } - for j, h := range data { - number := i + uint64(j) - hash = common.BytesToHash(h) - WriteHeaderNumber(batch, hash, number) - // If enough data was accumulated in memory or we're at the last block, dump to disk - if batch.ValueSize() > ethdb.IdealBatchSize { - if err := batch.Write(); err != nil { - log.Crit("Failed to write data to db", "err", err) - } - batch.Reset() - } - } - i += uint64(len(data)) - // If we've spent too much time already, notify the user of what we're doing - if time.Since(logged) > 8*time.Second { - log.Info("Initializing database from freezer", "total", frozen, "number", i, "hash", hash, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - if err := batch.Write(); err != nil { - log.Crit("Failed to write data to db", "err", err) - } - batch.Reset() - - WriteHeadHeaderHash(db, hash) - WriteHeadFastBlockHash(db, hash) - log.Info("Initialized database from freezer", "blocks", frozen, "elapsed", common.PrettyDuration(time.Since(start))) -} - -type blockTxHashes struct { - number uint64 - hashes []common.Hash -} - -// iterateTransactions iterates over all transactions in the (canon) block -// number(s) given, and yields the hashes on a channel. If there is a signal -// received from interrupt channel, the iteration will be aborted and result -// channel will be closed. -func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool, interrupt chan struct{}) chan *blockTxHashes { - // One thread sequentially reads data from db - type numberRlp struct { - number uint64 - rlp rlp.RawValue - } - if to == from { - return nil - } - threads := to - from - if cpus := runtime.NumCPU(); threads > uint64(cpus) { - threads = uint64(cpus) - } - var ( - rlpCh = make(chan *numberRlp, threads*2) // we send raw rlp over this channel - hashesCh = make(chan *blockTxHashes, threads*2) // send hashes over hashesCh - ) - // lookup runs in one instance - lookup := func() { - n, end := from, to - if reverse { - n, end = to-1, from-1 - } - defer close(rlpCh) - for n != end { - data := ReadCanonicalBodyRLP(db, n) - // Feed the block to the aggregator, or abort on interrupt - select { - case rlpCh <- &numberRlp{n, data}: - case <-interrupt: - return - } - if reverse { - n-- - } else { - n++ - } - } - } - // process runs in parallel - var nThreadsAlive atomic.Int32 - nThreadsAlive.Store(int32(threads)) - process := func() { - defer func() { - // Last processor closes the result channel - if nThreadsAlive.Add(-1) == 0 { - close(hashesCh) - } - }() - for data := range rlpCh { - var body types.Body - if err := rlp.DecodeBytes(data.rlp, &body); err != nil { - log.Warn("Failed to decode block body", "block", data.number, "error", err) - return - } - var hashes []common.Hash - for _, tx := range body.Transactions { - hashes = append(hashes, tx.Hash()) - } - result := &blockTxHashes{ - hashes: hashes, - number: data.number, - } - // Feed the block to the aggregator, or abort on interrupt - select { - case hashesCh <- result: - case <-interrupt: - return - } - } - } - go lookup() // start the sequential db accessor - for i := 0; i < int(threads); i++ { - go process() - } - return hashesCh -} - -// indexTransactions creates txlookup indices of the specified block range. -// -// This function iterates canonical chain in reverse order, it has one main advantage: -// We can write tx index tail flag periodically even without the whole indexing -// procedure is finished. So that we can resume indexing procedure next time quickly. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { - // short circuit for invalid range - if from >= to { - return - } - var ( - hashesCh = iterateTransactions(db, from, to, true, interrupt) - batch = db.NewBatch() - start = time.Now() - logged = start.Add(-7 * time.Second) - - // Since we iterate in reverse, we expect the first number to come - // in to be [to-1]. Therefore, setting lastNum to means that the - // queue gap-evaluation will work correctly - lastNum = to - queue = prque.New[int64, *blockTxHashes](nil) - blocks, txs = 0, 0 // for stats reporting - ) - for chanDelivery := range hashesCh { - // Push the delivery into the queue and process contiguous ranges. - // Since we iterate in reverse, so lower numbers have lower prio, and - // we can use the number directly as prio marker - queue.Push(chanDelivery, int64(chanDelivery.number)) - for !queue.Empty() { - // If the next available item is gapped, return - if _, priority := queue.Peek(); priority != int64(lastNum-1) { - break - } - // For testing - if hook != nil && !hook(lastNum-1) { - break - } - // Next block available, pop it off and index it - delivery := queue.PopItem() - lastNum = delivery.number - WriteTxLookupEntries(batch, delivery.number, delivery.hashes) - blocks++ - txs += len(delivery.hashes) - // If enough data was accumulated in memory or we're at the last block, dump to disk - if batch.ValueSize() > ethdb.IdealBatchSize { - WriteTxIndexTail(batch, lastNum) // Also write the tail here - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - batch.Reset() - } - // If we've spent too much time already, notify the user of what we're doing - if time.Since(logged) > 8*time.Second { - log.Info("Indexing transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "total", to-from, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - } - // Flush the new indexing tail and the last committed data. It can also happen - // that the last batch is empty because nothing to index, but the tail has to - // be flushed anyway. - WriteTxIndexTail(batch, lastNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - logger := log.Debug - if report { - logger = log.Info - } - select { - case <-interrupt: - logger("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start))) - default: - logger("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -// IndexTransactions creates txlookup indices of the specified block range. The from -// is included while to is excluded. -// -// This function iterates canonical chain in reverse order, it has one main advantage: -// We can write tx index tail flag periodically even without the whole indexing -// procedure is finished. So that we can resume indexing procedure next time quickly. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) { - indexTransactions(db, from, to, interrupt, nil, report) -} - -// indexTransactionsForTesting is the internal debug version with an additional hook. -func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) { - indexTransactions(db, from, to, interrupt, hook, false) -} - -// unindexTransactions removes txlookup indices of the specified block range. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) { - // short circuit for invalid range - if from >= to { - return - } - var ( - hashesCh = iterateTransactions(db, from, to, false, interrupt) - batch = db.NewBatch() - start = time.Now() - logged = start.Add(-7 * time.Second) - - // we expect the first number to come in to be [from]. Therefore, setting - // nextNum to from means that the queue gap-evaluation will work correctly - nextNum = from - queue = prque.New[int64, *blockTxHashes](nil) - blocks, txs = 0, 0 // for stats reporting - ) - // Otherwise spin up the concurrent iterator and unindexer - for delivery := range hashesCh { - // Push the delivery into the queue and process contiguous ranges. - queue.Push(delivery, -int64(delivery.number)) - for !queue.Empty() { - // If the next available item is gapped, return - if _, priority := queue.Peek(); -priority != int64(nextNum) { - break - } - // For testing - if hook != nil && !hook(nextNum) { - break - } - delivery := queue.PopItem() - nextNum = delivery.number + 1 - DeleteTxLookupEntries(batch, delivery.hashes) - txs += len(delivery.hashes) - blocks++ - - // If enough data was accumulated in memory or we're at the last block, dump to disk - // A batch counts the size of deletion as '1', so we need to flush more - // often than that. - if blocks%1000 == 0 { - WriteTxIndexTail(batch, nextNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - batch.Reset() - } - // If we've spent too much time already, notify the user of what we're doing - if time.Since(logged) > 8*time.Second { - log.Info("Unindexing transactions", "blocks", blocks, "txs", txs, "total", to-from, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - } - // Flush the new indexing tail and the last committed data. It can also happen - // that the last batch is empty because nothing to unindex, but the tail has to - // be flushed anyway. - WriteTxIndexTail(batch, nextNum) - if err := batch.Write(); err != nil { - log.Crit("Failed writing batch to db", "error", err) - return - } - logger := log.Debug - if report { - logger = log.Info - } - select { - case <-interrupt: - logger("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start))) - default: - logger("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start))) - } -} - -// UnindexTransactions removes txlookup indices of the specified block range. -// The from is included while to is excluded. -// -// There is a passed channel, the whole procedure will be interrupted if any -// signal received. -func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) { - unindexTransactions(db, from, to, interrupt, nil, report) -} - -// unindexTransactionsForTesting is the internal debug version with an additional hook. -func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) { - unindexTransactions(db, from, to, interrupt, hook, false) -} diff --git a/builder/core/rawdb/chain_iterator_test.go b/builder/core/rawdb/chain_iterator_test.go deleted file mode 100644 index 78b0a82e1..000000000 --- a/builder/core/rawdb/chain_iterator_test.go +++ /dev/null @@ -1,208 +0,0 @@ -// 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 rawdb - -import ( - "math/big" - "reflect" - "sort" - "sync" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -func TestChainIterator(t *testing.T) { - // Construct test chain db - chainDb := NewMemoryDatabase() - - var block *types.Block - var txs []*types.Transaction - to := common.BytesToAddress([]byte{0x11}) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher()) // Empty genesis block - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - for i := uint64(1); i <= 10; i++ { - var tx *types.Transaction - if i%2 == 0 { - tx = types.NewTx(&types.LegacyTx{ - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } else { - tx = types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1337), - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } - txs = append(txs, tx) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - } - - var cases = []struct { - from, to uint64 - reverse bool - expect []int - }{ - {0, 11, true, []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}, - {0, 0, true, nil}, - {0, 5, true, []int{4, 3, 2, 1, 0}}, - {10, 11, true, []int{10}}, - {0, 11, false, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}, - {0, 0, false, nil}, - {10, 11, false, []int{10}}, - } - for i, c := range cases { - var numbers []int - hashCh := iterateTransactions(chainDb, c.from, c.to, c.reverse, nil) - if hashCh != nil { - for h := range hashCh { - numbers = append(numbers, int(h.number)) - if len(h.hashes) > 0 { - if got, exp := h.hashes[0], txs[h.number-1].Hash(); got != exp { - t.Fatalf("block %d: hash wrong, got %x exp %x", h.number, got, exp) - } - } - } - } - if !c.reverse { - sort.Ints(numbers) - } else { - sort.Sort(sort.Reverse(sort.IntSlice(numbers))) - } - if !reflect.DeepEqual(numbers, c.expect) { - t.Fatalf("Case %d failed, visit element mismatch, want %v, got %v", i, c.expect, numbers) - } - } -} - -func TestIndexTransactions(t *testing.T) { - // Construct test chain db - chainDb := NewMemoryDatabase() - - var block *types.Block - var txs []*types.Transaction - to := common.BytesToAddress([]byte{0x11}) - - // Write empty genesis block - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - - for i := uint64(1); i <= 10; i++ { - var tx *types.Transaction - if i%2 == 0 { - tx = types.NewTx(&types.LegacyTx{ - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } else { - tx = types.NewTx(&types.AccessListTx{ - ChainID: big.NewInt(1337), - Nonce: i, - GasPrice: big.NewInt(11111), - Gas: 1111, - To: &to, - Value: big.NewInt(111), - Data: []byte{0x11, 0x11, 0x11}, - }) - } - txs = append(txs, tx) - block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher()) - WriteBlock(chainDb, block) - WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()) - } - // verify checks whether the tx indices in the range [from, to) - // is expected. - verify := func(from, to int, exist bool, tail uint64) { - for i := from; i < to; i++ { - if i == 0 { - continue - } - number := ReadTxLookupEntry(chainDb, txs[i-1].Hash()) - if exist && number == nil { - t.Fatalf("Transaction index %d missing", i) - } - if !exist && number != nil { - t.Fatalf("Transaction index %d is not deleted", i) - } - } - number := ReadTxIndexTail(chainDb) - if number == nil || *number != tail { - t.Fatalf("Transaction tail mismatch") - } - } - IndexTransactions(chainDb, 5, 11, nil, false) - verify(5, 11, true, 5) - verify(0, 5, false, 5) - - IndexTransactions(chainDb, 0, 5, nil, false) - verify(0, 11, true, 0) - - UnindexTransactions(chainDb, 0, 5, nil, false) - verify(5, 11, true, 5) - verify(0, 5, false, 5) - - UnindexTransactions(chainDb, 5, 11, nil, false) - verify(0, 11, false, 11) - - // Testing corner cases - signal := make(chan struct{}) - var once sync.Once - indexTransactionsForTesting(chainDb, 5, 11, signal, func(n uint64) bool { - if n <= 8 { - once.Do(func() { - close(signal) - }) - return false - } - return true - }) - verify(9, 11, true, 9) - verify(0, 9, false, 9) - IndexTransactions(chainDb, 0, 9, nil, false) - - signal = make(chan struct{}) - var once2 sync.Once - unindexTransactionsForTesting(chainDb, 0, 11, signal, func(n uint64) bool { - if n >= 8 { - once2.Do(func() { - close(signal) - }) - return false - } - return true - }) - verify(8, 11, true, 8) - verify(0, 8, false, 8) -} diff --git a/builder/core/rawdb/database.go b/builder/core/rawdb/database.go deleted file mode 100644 index 27a9ec741..000000000 --- a/builder/core/rawdb/database.go +++ /dev/null @@ -1,665 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "bytes" - "errors" - "fmt" - "os" - "path" - "path/filepath" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/leveldb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/ethdb/pebble" - "github.com/ethereum/go-ethereum/log" - "github.com/olekukonko/tablewriter" -) - -// freezerdb is a database wrapper that enables freezer data retrievals. -type freezerdb struct { - ancientRoot string - ethdb.KeyValueStore - ethdb.AncientStore -} - -// AncientDatadir returns the path of root ancient directory. -func (frdb *freezerdb) AncientDatadir() (string, error) { - return frdb.ancientRoot, nil -} - -// Close implements io.Closer, closing both the fast key-value store as well as -// the slow ancient tables. -func (frdb *freezerdb) Close() error { - var errs []error - if err := frdb.AncientStore.Close(); err != nil { - errs = append(errs, err) - } - if err := frdb.KeyValueStore.Close(); err != nil { - errs = append(errs, err) - } - if len(errs) != 0 { - return fmt.Errorf("%v", errs) - } - return nil -} - -// Freeze is a helper method used for external testing to trigger and block until -// a freeze cycle completes, without having to sleep for a minute to trigger the -// automatic background run. -func (frdb *freezerdb) Freeze(threshold uint64) error { - if frdb.AncientStore.(*chainFreezer).readonly { - return errReadOnly - } - // Set the freezer threshold to a temporary value - defer func(old uint64) { - frdb.AncientStore.(*chainFreezer).threshold.Store(old) - }(frdb.AncientStore.(*chainFreezer).threshold.Load()) - frdb.AncientStore.(*chainFreezer).threshold.Store(threshold) - - // Trigger a freeze cycle and block until it's done - trigger := make(chan struct{}, 1) - frdb.AncientStore.(*chainFreezer).trigger <- trigger - <-trigger - return nil -} - -// nofreezedb is a database wrapper that disables freezer data retrievals. -type nofreezedb struct { - ethdb.KeyValueStore -} - -// HasAncient returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) HasAncient(kind string, number uint64) (bool, error) { - return false, errNotSupported -} - -// Ancient returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) { - return nil, errNotSupported -} - -// AncientRange returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientRange(kind string, start, max, maxByteSize uint64) ([][]byte, error) { - return nil, errNotSupported -} - -// Ancients returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Ancients() (uint64, error) { - return 0, errNotSupported -} - -// Tail returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Tail() (uint64, error) { - return 0, errNotSupported -} - -// AncientSize returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientSize(kind string) (uint64, error) { - return 0, errNotSupported -} - -// ModifyAncients is not supported. -func (db *nofreezedb) ModifyAncients(func(ethdb.AncientWriteOp) error) (int64, error) { - return 0, errNotSupported -} - -// TruncateHead returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) TruncateHead(items uint64) (uint64, error) { - return 0, errNotSupported -} - -// TruncateTail returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) TruncateTail(items uint64) (uint64, error) { - return 0, errNotSupported -} - -// Sync returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) Sync() error { - return errNotSupported -} - -func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { - // Unlike other ancient-related methods, this method does not return - // errNotSupported when invoked. - // The reason for this is that the caller might want to do several things: - // 1. Check if something is in the freezer, - // 2. If not, check leveldb. - // - // This will work, since the ancient-checks inside 'fn' will return errors, - // and the leveldb work will continue. - // - // If we instead were to return errNotSupported here, then the caller would - // have to explicitly check for that, having an extra clause to do the - // non-ancient operations. - return fn(db) -} - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (db *nofreezedb) MigrateTable(kind string, convert convertLegacyFn) error { - return errNotSupported -} - -// AncientDatadir returns an error as we don't have a backing chain freezer. -func (db *nofreezedb) AncientDatadir() (string, error) { - return "", errNotSupported -} - -// NewDatabase creates a high level database on top of a given key-value data -// store without a freezer moving immutable chain segments into cold storage. -func NewDatabase(db ethdb.KeyValueStore) ethdb.Database { - return &nofreezedb{KeyValueStore: db} -} - -// resolveChainFreezerDir is a helper function which resolves the absolute path -// of chain freezer by considering backward compatibility. -func resolveChainFreezerDir(ancient string) string { - // Check if the chain freezer is already present in the specified - // sub folder, if not then two possibilities: - // - chain freezer is not initialized - // - chain freezer exists in legacy location (root ancient folder) - freezer := path.Join(ancient, ChainFreezerName) - if !common.FileExist(freezer) { - if !common.FileExist(ancient) { - // The entire ancient store is not initialized, still use the sub - // folder for initialization. - } else { - // Ancient root is already initialized, then we hold the assumption - // that chain freezer is also initialized and located in root folder. - // In this case fallback to legacy location. - freezer = ancient - log.Info("Found legacy ancient chain path", "location", ancient) - } - } - return freezer -} - -// NewDatabaseWithFreezer creates a high level database on top of a given key- -// value data store with a freezer moving immutable chain segments into cold -// storage. The passed ancient indicates the path of root ancient directory -// where the chain freezer can be opened. -func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly bool) (ethdb.Database, error) { - // Create the idle freezer instance - frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly) - if err != nil { - printChainMetadata(db) - return nil, err - } - // Since the freezer can be stored separately from the user's key-value database, - // there's a fairly high probability that the user requests invalid combinations - // of the freezer and database. Ensure that we don't shoot ourselves in the foot - // by serving up conflicting data, leading to both datastores getting corrupted. - // - // - If both the freezer and key-value store are empty (no genesis), we just - // initialized a new empty freezer, so everything's fine. - // - If the key-value store is empty, but the freezer is not, we need to make - // sure the user's genesis matches the freezer. That will be checked in the - // blockchain, since we don't have the genesis block here (nor should we at - // this point care, the key-value/freezer combo is valid). - // - If neither the key-value store nor the freezer is empty, cross validate - // the genesis hashes to make sure they are compatible. If they are, also - // ensure that there's no gap between the freezer and subsequently leveldb. - // - If the key-value store is not empty, but the freezer is, we might just be - // upgrading to the freezer release, or we might have had a small chain and - // not frozen anything yet. Ensure that no blocks are missing yet from the - // key-value store, since that would mean we already had an old freezer. - - // If the genesis hash is empty, we have a new key-value store, so nothing to - // validate in this method. If, however, the genesis hash is not nil, compare - // it to the freezer content. - if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 { - if frozen, _ := frdb.Ancients(); frozen > 0 { - // If the freezer already contains something, ensure that the genesis blocks - // match, otherwise we might mix up freezers across chains and destroy both - // the freezer and the key-value store. - frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0) - if err != nil { - printChainMetadata(db) - return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err) - } else if !bytes.Equal(kvgenesis, frgenesis) { - printChainMetadata(db) - return nil, fmt.Errorf("genesis mismatch: %#x (leveldb) != %#x (ancients)", kvgenesis, frgenesis) - } - // Key-value store and freezer belong to the same network. Ensure that they - // are contiguous, otherwise we might end up with a non-functional freezer. - if kvhash, _ := db.Get(headerHashKey(frozen)); len(kvhash) == 0 { - // Subsequent header after the freezer limit is missing from the database. - // Reject startup if the database has a more recent head. - if head := *ReadHeaderNumber(db, ReadHeadHeaderHash(db)); head > frozen-1 { - // Find the smallest block stored in the key-value store - // in range of [frozen, head] - var number uint64 - for number = frozen; number <= head; number++ { - if present, _ := db.Has(headerHashKey(number)); present { - break - } - } - // We are about to exit on error. Print database metadata before exiting - printChainMetadata(db) - return nil, fmt.Errorf("gap in the chain between ancients [0 - #%d] and leveldb [#%d - #%d] ", - frozen-1, number, head) - } - // Database contains only older data than the freezer, this happens if the - // state was wiped and reinited from an existing freezer. - } - // Otherwise, key-value store continues where the freezer left off, all is fine. - // We might have duplicate blocks (crash after freezer write but before key-value - // store deletion, but that's fine). - } else { - // If the freezer is empty, ensure nothing was moved yet from the key-value - // store, otherwise we'll end up missing data. We check block #1 to decide - // if we froze anything previously or not, but do take care of databases with - // only the genesis block. - if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) { - // Key-value store contains more data than the genesis block, make sure we - // didn't freeze anything yet. - if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { - printChainMetadata(db) - return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") - } - // Block #1 is still in the database, we're allowed to init a new freezer - } - // Otherwise, the head header is still the genesis, we're allowed to init a new - // freezer. - } - } - // Freezer is consistent with the key-value database, permit combining the two - if !frdb.readonly { - frdb.wg.Add(1) - go func() { - frdb.freeze(db) - frdb.wg.Done() - }() - } - return &freezerdb{ - ancientRoot: ancient, - KeyValueStore: db, - AncientStore: frdb, - }, nil -} - -// NewMemoryDatabase creates an ephemeral in-memory key-value database without a -// freezer moving immutable chain segments into cold storage. -func NewMemoryDatabase() ethdb.Database { - return NewDatabase(memorydb.New()) -} - -// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database -// with an initial starting capacity, but without a freezer moving immutable -// chain segments into cold storage. -func NewMemoryDatabaseWithCap(size int) ethdb.Database { - return NewDatabase(memorydb.NewWithCap(size)) -} - -// NewLevelDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewLevelDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) { - db, err := leveldb.New(file, cache, handles, namespace, readonly) - if err != nil { - return nil, err - } - log.Info("Using LevelDB as the backing database") - return NewDatabase(db), nil -} - -// NewPebbleDBDatabase creates a persistent key-value database without a freezer -// moving immutable chain segments into cold storage. -func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) { - db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral) - if err != nil { - return nil, err - } - return NewDatabase(db), nil -} - -const ( - dbPebble = "pebble" - dbLeveldb = "leveldb" -) - -// PreexistingDatabase checks the given data directory whether a database is already -// instantiated at that location, and if so, returns the type of database (or the -// empty string). -func PreexistingDatabase(path string) string { - if _, err := os.Stat(filepath.Join(path, "CURRENT")); err != nil { - return "" // No pre-existing db - } - if matches, err := filepath.Glob(filepath.Join(path, "OPTIONS*")); len(matches) > 0 || err != nil { - if err != nil { - panic(err) // only possible if the pattern is malformed - } - return dbPebble - } - return dbLeveldb -} - -// OpenOptions contains the options to apply when opening a database. -// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used. -type OpenOptions struct { - Type string // "leveldb" | "pebble" - Directory string // the datadir - AncientsDirectory string // the ancients-dir - Namespace string // the namespace for database relevant metrics - Cache int // the capacity(in megabytes) of the data caching - Handles int // number of files to be open simultaneously - ReadOnly bool - // Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of - // a crash is not important. This option should typically be used in tests. - Ephemeral bool -} - -// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble. -// -// type == null type != null -// +---------------------------------------- -// db is non-existent | pebble default | specified type -// db is existent | from db | specified type (if compatible) -func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) { - // Reject any unsupported database type - if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble { - return nil, fmt.Errorf("unknown db.engine %v", o.Type) - } - // Retrieve any pre-existing database's type and use that or the requested one - // as long as there's no conflict between the two types - existingDb := PreexistingDatabase(o.Directory) - if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb { - return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb) - } - if o.Type == dbPebble || existingDb == dbPebble { - log.Info("Using pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) - } - if o.Type == dbLeveldb || existingDb == dbLeveldb { - log.Info("Using leveldb as the backing database") - return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly) - } - // No pre-existing database, no user-requested one either. Default to Pebble. - log.Info("Defaulting to pebble as the backing database") - return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral) -} - -// Open opens both a disk-based key-value database such as leveldb or pebble, but also -// integrates it with a freezer database -- if the AncientDir option has been -// set on the provided OpenOptions. -// The passed o.AncientDir indicates the path of root ancient directory where -// the chain freezer can be opened. -func Open(o OpenOptions) (ethdb.Database, error) { - kvdb, err := openKeyValueDatabase(o) - if err != nil { - return nil, err - } - if len(o.AncientsDirectory) == 0 { - return kvdb, nil - } - frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly) - if err != nil { - kvdb.Close() - return nil, err - } - return frdb, nil -} - -type counter uint64 - -func (c counter) String() string { - return fmt.Sprintf("%d", c) -} - -func (c counter) Percentage(current uint64) string { - return fmt.Sprintf("%d", current*100/uint64(c)) -} - -// stat stores sizes and count for a parameter -type stat struct { - size common.StorageSize - count counter -} - -// Add size to the stat and increase the counter by 1 -func (s *stat) Add(size common.StorageSize) { - s.size += size - s.count++ -} - -func (s *stat) Size() string { - return s.size.String() -} - -func (s *stat) Count() string { - return s.count.String() -} - -// InspectDatabase traverses the entire database and checks the size -// of all different categories of data. -func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { - it := db.NewIterator(keyPrefix, keyStart) - defer it.Release() - - var ( - count int64 - start = time.Now() - logged = time.Now() - - // Key-value store statistics - headers stat - bodies stat - receipts stat - tds stat - numHashPairings stat - hashNumPairings stat - legacyTries stat - stateLookups stat - accountTries stat - storageTries stat - codes stat - txLookups stat - accountSnaps stat - storageSnaps stat - preimages stat - bloomBits stat - beaconHeaders stat - cliqueSnaps stat - - // Les statistic - chtTrieNodes stat - bloomTrieNodes stat - - // Meta- and unaccounted data - metadata stat - unaccounted stat - - // Totals - total common.StorageSize - ) - // Inspect key-value database first. - for it.Next() { - var ( - key = it.Key() - size = common.StorageSize(len(key) + len(it.Value())) - ) - total += size - switch { - case bytes.HasPrefix(key, headerPrefix) && len(key) == (len(headerPrefix)+8+common.HashLength): - headers.Add(size) - case bytes.HasPrefix(key, blockBodyPrefix) && len(key) == (len(blockBodyPrefix)+8+common.HashLength): - bodies.Add(size) - case bytes.HasPrefix(key, blockReceiptsPrefix) && len(key) == (len(blockReceiptsPrefix)+8+common.HashLength): - receipts.Add(size) - case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerTDSuffix): - tds.Add(size) - case bytes.HasPrefix(key, headerPrefix) && bytes.HasSuffix(key, headerHashSuffix): - numHashPairings.Add(size) - case bytes.HasPrefix(key, headerNumberPrefix) && len(key) == (len(headerNumberPrefix)+common.HashLength): - hashNumPairings.Add(size) - case IsLegacyTrieNode(key, it.Value()): - legacyTries.Add(size) - case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: - stateLookups.Add(size) - case IsAccountTrieNode(key): - accountTries.Add(size) - case IsStorageTrieNode(key): - storageTries.Add(size) - case bytes.HasPrefix(key, CodePrefix) && len(key) == len(CodePrefix)+common.HashLength: - codes.Add(size) - case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength): - txLookups.Add(size) - case bytes.HasPrefix(key, SnapshotAccountPrefix) && len(key) == (len(SnapshotAccountPrefix)+common.HashLength): - accountSnaps.Add(size) - case bytes.HasPrefix(key, SnapshotStoragePrefix) && len(key) == (len(SnapshotStoragePrefix)+2*common.HashLength): - storageSnaps.Add(size) - case bytes.HasPrefix(key, PreimagePrefix) && len(key) == (len(PreimagePrefix)+common.HashLength): - preimages.Add(size) - case bytes.HasPrefix(key, configPrefix) && len(key) == (len(configPrefix)+common.HashLength): - metadata.Add(size) - case bytes.HasPrefix(key, genesisPrefix) && len(key) == (len(genesisPrefix)+common.HashLength): - metadata.Add(size) - case bytes.HasPrefix(key, bloomBitsPrefix) && len(key) == (len(bloomBitsPrefix)+10+common.HashLength): - bloomBits.Add(size) - case bytes.HasPrefix(key, BloomBitsIndexPrefix): - bloomBits.Add(size) - case bytes.HasPrefix(key, skeletonHeaderPrefix) && len(key) == (len(skeletonHeaderPrefix)+8): - beaconHeaders.Add(size) - case bytes.HasPrefix(key, CliqueSnapshotPrefix) && len(key) == 7+common.HashLength: - cliqueSnaps.Add(size) - case bytes.HasPrefix(key, ChtTablePrefix) || - bytes.HasPrefix(key, ChtIndexTablePrefix) || - bytes.HasPrefix(key, ChtPrefix): // Canonical hash trie - chtTrieNodes.Add(size) - case bytes.HasPrefix(key, BloomTrieTablePrefix) || - bytes.HasPrefix(key, BloomTrieIndexPrefix) || - bytes.HasPrefix(key, BloomTriePrefix): // Bloomtrie sub - bloomTrieNodes.Add(size) - default: - var accounted bool - for _, meta := range [][]byte{ - databaseVersionKey, headHeaderKey, headBlockKey, headFastBlockKey, headFinalizedBlockKey, - lastPivotKey, fastTrieProgressKey, snapshotDisabledKey, SnapshotRootKey, snapshotJournalKey, - snapshotGeneratorKey, snapshotRecoveryKey, txIndexTailKey, fastTxLookupLimitKey, - uncleanShutdownKey, badBlockKey, transitionStatusKey, skeletonSyncStatusKey, - persistentStateIDKey, trieJournalKey, snapshotSyncStatusKey, snapSyncStatusFlagKey, - } { - if bytes.Equal(key, meta) { - metadata.Add(size) - accounted = true - break - } - } - if !accounted { - unaccounted.Add(size) - } - } - count++ - if count%1000 == 0 && time.Since(logged) > 8*time.Second { - log.Info("Inspecting database", "count", count, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - // Display the database statistic of key-value store. - stats := [][]string{ - {"Key-Value store", "Headers", headers.Size(), headers.Count()}, - {"Key-Value store", "Bodies", bodies.Size(), bodies.Count()}, - {"Key-Value store", "Receipt lists", receipts.Size(), receipts.Count()}, - {"Key-Value store", "Difficulties", tds.Size(), tds.Count()}, - {"Key-Value store", "Block number->hash", numHashPairings.Size(), numHashPairings.Count()}, - {"Key-Value store", "Block hash->number", hashNumPairings.Size(), hashNumPairings.Count()}, - {"Key-Value store", "Transaction index", txLookups.Size(), txLookups.Count()}, - {"Key-Value store", "Bloombit index", bloomBits.Size(), bloomBits.Count()}, - {"Key-Value store", "Contract codes", codes.Size(), codes.Count()}, - {"Key-Value store", "Hash trie nodes", legacyTries.Size(), legacyTries.Count()}, - {"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()}, - {"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()}, - {"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()}, - {"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()}, - {"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()}, - {"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()}, - {"Key-Value store", "Beacon sync headers", beaconHeaders.Size(), beaconHeaders.Count()}, - {"Key-Value store", "Clique snapshots", cliqueSnaps.Size(), cliqueSnaps.Count()}, - {"Key-Value store", "Singleton metadata", metadata.Size(), metadata.Count()}, - {"Light client", "CHT trie nodes", chtTrieNodes.Size(), chtTrieNodes.Count()}, - {"Light client", "Bloom trie nodes", bloomTrieNodes.Size(), bloomTrieNodes.Count()}, - } - // Inspect all registered append-only file store then. - ancients, err := inspectFreezers(db) - if err != nil { - return err - } - for _, ancient := range ancients { - for _, table := range ancient.sizes { - stats = append(stats, []string{ - fmt.Sprintf("Ancient store (%s)", strings.Title(ancient.name)), - strings.Title(table.name), - table.size.String(), - fmt.Sprintf("%d", ancient.count()), - }) - } - total += ancient.size() - } - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Database", "Category", "Size", "Items"}) - table.SetFooter([]string{"", "Total", total.String(), " "}) - table.AppendBulk(stats) - table.Render() - - if unaccounted.size > 0 { - log.Error("Database contains unaccounted data", "size", unaccounted.size, "count", unaccounted.count) - } - return nil -} - -// printChainMetadata prints out chain metadata to stderr. -func printChainMetadata(db ethdb.KeyValueStore) { - fmt.Fprintf(os.Stderr, "Chain metadata\n") - for _, v := range ReadChainMetadata(db) { - fmt.Fprintf(os.Stderr, " %s\n", strings.Join(v, ": ")) - } - fmt.Fprintf(os.Stderr, "\n\n") -} - -// ReadChainMetadata returns a set of key/value pairs that contains information -// about the database chain status. This can be used for diagnostic purposes -// when investigating the state of the node. -func ReadChainMetadata(db ethdb.KeyValueStore) [][]string { - pp := func(val *uint64) string { - if val == nil { - return "" - } - return fmt.Sprintf("%d (%#x)", *val, *val) - } - data := [][]string{ - {"databaseVersion", pp(ReadDatabaseVersion(db))}, - {"headBlockHash", fmt.Sprintf("%v", ReadHeadBlockHash(db))}, - {"headFastBlockHash", fmt.Sprintf("%v", ReadHeadFastBlockHash(db))}, - {"headHeaderHash", fmt.Sprintf("%v", ReadHeadHeaderHash(db))}, - {"lastPivotNumber", pp(ReadLastPivotNumber(db))}, - {"len(snapshotSyncStatus)", fmt.Sprintf("%d bytes", len(ReadSnapshotSyncStatus(db)))}, - {"snapshotDisabled", fmt.Sprintf("%v", ReadSnapshotDisabled(db))}, - {"snapshotJournal", fmt.Sprintf("%d bytes", len(ReadSnapshotJournal(db)))}, - {"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))}, - {"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))}, - {"txIndexTail", pp(ReadTxIndexTail(db))}, - } - if b := ReadSkeletonSyncStatus(db); b != nil { - data = append(data, []string{"SkeletonSyncStatus", string(b)}) - } - return data -} diff --git a/builder/core/rawdb/database_test.go b/builder/core/rawdb/database_test.go deleted file mode 100644 index a0d7b5ec6..000000000 --- a/builder/core/rawdb/database_test.go +++ /dev/null @@ -1,17 +0,0 @@ -// 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 rawdb diff --git a/builder/core/rawdb/freezer.go b/builder/core/rawdb/freezer.go deleted file mode 100644 index b7824ddc0..000000000 --- a/builder/core/rawdb/freezer.go +++ /dev/null @@ -1,509 +0,0 @@ -// 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 rawdb - -import ( - "errors" - "fmt" - "math" - "os" - "path/filepath" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/gofrs/flock" -) - -var ( - // errReadOnly is returned if the freezer is opened in read only mode. All the - // mutations are disallowed. - errReadOnly = errors.New("read only") - - // errUnknownTable is returned if the user attempts to read from a table that is - // not tracked by the freezer. - errUnknownTable = errors.New("unknown table") - - // errOutOrderInsertion is returned if the user attempts to inject out-of-order - // binary blobs into the freezer. - errOutOrderInsertion = errors.New("the append operation is out-order") - - // errSymlinkDatadir is returned if the ancient directory specified by user - // is a symbolic link. - errSymlinkDatadir = errors.New("symbolic link datadir is not supported") -) - -// freezerTableSize defines the maximum size of freezer data files. -const freezerTableSize = 2 * 1000 * 1000 * 1000 - -// Freezer is a memory mapped append-only database to store immutable ordered -// data into flat files: -// -// - The append-only nature ensures that disk writes are minimized. -// - The memory mapping ensures we can max out system memory for caching without -// reserving it for go-ethereum. This would also reduce the memory requirements -// of Geth, and thus also GC overhead. -type Freezer struct { - frozen atomic.Uint64 // Number of blocks already frozen - tail atomic.Uint64 // Number of the first stored item in the freezer - - // This lock synchronizes writers and the truncate operation, as well as - // the "atomic" (batched) read operations. - writeLock sync.RWMutex - writeBatch *freezerBatch - - readonly bool - tables map[string]*freezerTable // Data tables for storing everything - instanceLock *flock.Flock // File-system lock to prevent double opens - closeOnce sync.Once -} - -// NewChainFreezer is a small utility method around NewFreezer that sets the -// default parameters for the chain storage. -func NewChainFreezer(datadir string, namespace string, readonly bool) (*Freezer, error) { - return NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy) -} - -// NewFreezer creates a freezer instance for maintaining immutable ordered -// data according to the given parameters. -// -// The 'tables' argument defines the data tables. If the value of a map -// entry is true, snappy compression is disabled for the table. -func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*Freezer, error) { - // Create the initial freezer object - var ( - readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil) - writeMeter = metrics.NewRegisteredMeter(namespace+"ancient/write", nil) - sizeGauge = metrics.NewRegisteredGauge(namespace+"ancient/size", nil) - ) - // Ensure the datadir is not a symbolic link if it exists. - if info, err := os.Lstat(datadir); !os.IsNotExist(err) { - if info.Mode()&os.ModeSymlink != 0 { - log.Warn("Symbolic link ancient database is not supported", "path", datadir) - return nil, errSymlinkDatadir - } - } - flockFile := filepath.Join(datadir, "FLOCK") - if err := os.MkdirAll(filepath.Dir(flockFile), 0755); err != nil { - return nil, err - } - // Leveldb uses LOCK as the filelock filename. To prevent the - // name collision, we use FLOCK as the lock name. - lock := flock.New(flockFile) - tryLock := lock.TryLock - if readonly { - tryLock = lock.TryRLock - } - if locked, err := tryLock(); err != nil { - return nil, err - } else if !locked { - return nil, errors.New("locking failed") - } - // Open all the supported data tables - freezer := &Freezer{ - readonly: readonly, - tables: make(map[string]*freezerTable), - instanceLock: lock, - } - - // Create the tables. - for name, disableSnappy := range tables { - table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, maxTableSize, disableSnappy, readonly) - if err != nil { - for _, table := range freezer.tables { - table.Close() - } - lock.Unlock() - return nil, err - } - freezer.tables[name] = table - } - var err error - if freezer.readonly { - // In readonly mode only validate, don't truncate. - // validate also sets `freezer.frozen`. - err = freezer.validate() - } else { - // Truncate all tables to common length. - err = freezer.repair() - } - if err != nil { - for _, table := range freezer.tables { - table.Close() - } - lock.Unlock() - return nil, err - } - - // Create the write batch. - freezer.writeBatch = newFreezerBatch(freezer) - - log.Info("Opened ancient database", "database", datadir, "readonly", readonly) - return freezer, nil -} - -// Close terminates the chain freezer, unmapping all the data files. -func (f *Freezer) Close() error { - f.writeLock.Lock() - defer f.writeLock.Unlock() - - var errs []error - f.closeOnce.Do(func() { - for _, table := range f.tables { - if err := table.Close(); err != nil { - errs = append(errs, err) - } - } - if err := f.instanceLock.Unlock(); err != nil { - errs = append(errs, err) - } - }) - if errs != nil { - return fmt.Errorf("%v", errs) - } - return nil -} - -// HasAncient returns an indicator whether the specified ancient data exists -// in the freezer. -func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) { - if table := f.tables[kind]; table != nil { - return table.has(number), nil - } - return false, nil -} - -// Ancient retrieves an ancient binary blob from the append-only immutable files. -func (f *Freezer) Ancient(kind string, number uint64) ([]byte, error) { - if table := f.tables[kind]; table != nil { - return table.Retrieve(number) - } - return nil, errUnknownTable -} - -// AncientRange retrieves multiple items in sequence, starting from the index 'start'. -// It will return -// - at most 'count' items, -// - if maxBytes is specified: at least 1 item (even if exceeding the maxByteSize), -// but will otherwise return as many items as fit into maxByteSize. -// - if maxBytes is not specified, 'count' items will be returned if they are present. -func (f *Freezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - if table := f.tables[kind]; table != nil { - return table.RetrieveItems(start, count, maxBytes) - } - return nil, errUnknownTable -} - -// Ancients returns the length of the frozen items. -func (f *Freezer) Ancients() (uint64, error) { - return f.frozen.Load(), nil -} - -// Tail returns the number of first stored item in the freezer. -func (f *Freezer) Tail() (uint64, error) { - return f.tail.Load(), nil -} - -// AncientSize returns the ancient size of the specified category. -func (f *Freezer) AncientSize(kind string) (uint64, error) { - // This needs the write lock to avoid data races on table fields. - // Speed doesn't matter here, AncientSize is for debugging. - f.writeLock.RLock() - defer f.writeLock.RUnlock() - - if table := f.tables[kind]; table != nil { - return table.size() - } - return 0, errUnknownTable -} - -// ReadAncients runs the given read operation while ensuring that no writes take place -// on the underlying freezer. -func (f *Freezer) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { - f.writeLock.RLock() - defer f.writeLock.RUnlock() - - return fn(f) -} - -// ModifyAncients runs the given write operation. -func (f *Freezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (writeSize int64, err error) { - if f.readonly { - return 0, errReadOnly - } - f.writeLock.Lock() - defer f.writeLock.Unlock() - - // Roll back all tables to the starting position in case of error. - prevItem := f.frozen.Load() - defer func() { - if err != nil { - // The write operation has failed. Go back to the previous item position. - for name, table := range f.tables { - err := table.truncateHead(prevItem) - if err != nil { - log.Error("Freezer table roll-back failed", "table", name, "index", prevItem, "err", err) - } - } - } - }() - - f.writeBatch.reset() - if err := fn(f.writeBatch); err != nil { - return 0, err - } - item, writeSize, err := f.writeBatch.commit() - if err != nil { - return 0, err - } - f.frozen.Store(item) - return writeSize, nil -} - -// TruncateHead discards any recent data above the provided threshold number. -// It returns the previous head number. -func (f *Freezer) TruncateHead(items uint64) (uint64, error) { - if f.readonly { - return 0, errReadOnly - } - f.writeLock.Lock() - defer f.writeLock.Unlock() - - oitems := f.frozen.Load() - if oitems <= items { - return oitems, nil - } - for _, table := range f.tables { - if err := table.truncateHead(items); err != nil { - return 0, err - } - } - f.frozen.Store(items) - return oitems, nil -} - -// TruncateTail discards any recent data below the provided threshold number. -func (f *Freezer) TruncateTail(tail uint64) (uint64, error) { - if f.readonly { - return 0, errReadOnly - } - f.writeLock.Lock() - defer f.writeLock.Unlock() - - old := f.tail.Load() - if old >= tail { - return old, nil - } - for _, table := range f.tables { - if err := table.truncateTail(tail); err != nil { - return 0, err - } - } - f.tail.Store(tail) - return old, nil -} - -// Sync flushes all data tables to disk. -func (f *Freezer) Sync() error { - var errs []error - for _, table := range f.tables { - if err := table.Sync(); err != nil { - errs = append(errs, err) - } - } - if errs != nil { - return fmt.Errorf("%v", errs) - } - return nil -} - -// validate checks that every table has the same boundary. -// Used instead of `repair` in readonly mode. -func (f *Freezer) validate() error { - if len(f.tables) == 0 { - return nil - } - var ( - head uint64 - tail uint64 - name string - ) - // Hack to get boundary of any table - for kind, table := range f.tables { - head = table.items.Load() - tail = table.itemHidden.Load() - name = kind - break - } - // Now check every table against those boundaries. - for kind, table := range f.tables { - if head != table.items.Load() { - return fmt.Errorf("freezer tables %s and %s have differing head: %d != %d", kind, name, table.items.Load(), head) - } - if tail != table.itemHidden.Load() { - return fmt.Errorf("freezer tables %s and %s have differing tail: %d != %d", kind, name, table.itemHidden.Load(), tail) - } - } - f.frozen.Store(head) - f.tail.Store(tail) - return nil -} - -// repair truncates all data tables to the same length. -func (f *Freezer) repair() error { - var ( - head = uint64(math.MaxUint64) - tail = uint64(0) - ) - for _, table := range f.tables { - items := table.items.Load() - if head > items { - head = items - } - hidden := table.itemHidden.Load() - if hidden > tail { - tail = hidden - } - } - for _, table := range f.tables { - if err := table.truncateHead(head); err != nil { - return err - } - if err := table.truncateTail(tail); err != nil { - return err - } - } - f.frozen.Store(head) - f.tail.Store(tail) - return nil -} - -// convertLegacyFn takes a raw freezer entry in an older format and -// returns it in the new format. -type convertLegacyFn = func([]byte) ([]byte, error) - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error { - if f.readonly { - return errReadOnly - } - f.writeLock.Lock() - defer f.writeLock.Unlock() - - table, ok := f.tables[kind] - if !ok { - return errUnknownTable - } - // forEach iterates every entry in the table serially and in order, calling `fn` - // with the item as argument. If `fn` returns an error the iteration stops - // and that error will be returned. - forEach := func(t *freezerTable, offset uint64, fn func(uint64, []byte) error) error { - var ( - items = t.items.Load() - batchSize = uint64(1024) - maxBytes = uint64(1024 * 1024) - ) - for i := offset; i < items; { - if i+batchSize > items { - batchSize = items - i - } - data, err := t.RetrieveItems(i, batchSize, maxBytes) - if err != nil { - return err - } - for j, item := range data { - if err := fn(i+uint64(j), item); err != nil { - return err - } - } - i += uint64(len(data)) - } - return nil - } - // TODO(s1na): This is a sanity-check since as of now no process does tail-deletion. But the migration - // process assumes no deletion at tail and needs to be modified to account for that. - if table.itemOffset.Load() > 0 || table.itemHidden.Load() > 0 { - return errors.New("migration not supported for tail-deleted freezers") - } - ancientsPath := filepath.Dir(table.index.Name()) - // Set up new dir for the migrated table, the content of which - // we'll at the end move over to the ancients dir. - migrationPath := filepath.Join(ancientsPath, "migration") - newTable, err := newFreezerTable(migrationPath, kind, table.noCompression, false) - if err != nil { - return err - } - var ( - batch = newTable.newBatch() - out []byte - start = time.Now() - logged = time.Now() - offset = newTable.items.Load() - ) - if offset > 0 { - log.Info("found previous migration attempt", "migrated", offset) - } - // Iterate through entries and transform them - if err := forEach(table, offset, func(i uint64, blob []byte) error { - if i%10000 == 0 && time.Since(logged) > 16*time.Second { - log.Info("Processing legacy elements", "count", i, "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - out, err = convert(blob) - if err != nil { - return err - } - if err := batch.AppendRaw(i, out); err != nil { - return err - } - return nil - }); err != nil { - return err - } - if err := batch.commit(); err != nil { - return err - } - log.Info("Replacing old table files with migrated ones", "elapsed", common.PrettyDuration(time.Since(start))) - // Release and delete old table files. Note this won't - // delete the index file. - table.releaseFilesAfter(0, true) - - if err := newTable.Close(); err != nil { - return err - } - files, err := os.ReadDir(migrationPath) - if err != nil { - return err - } - // Move migrated files to ancients dir. - for _, f := range files { - // This will replace the old index file as a side-effect. - if err := os.Rename(filepath.Join(migrationPath, f.Name()), filepath.Join(ancientsPath, f.Name())); err != nil { - return err - } - } - // Delete by now empty dir. - if err := os.Remove(migrationPath); err != nil { - return err - } - return nil -} diff --git a/builder/core/rawdb/freezer_batch.go b/builder/core/rawdb/freezer_batch.go deleted file mode 100644 index 84a63a451..000000000 --- a/builder/core/rawdb/freezer_batch.go +++ /dev/null @@ -1,255 +0,0 @@ -// 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 rawdb - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/rlp" - "github.com/golang/snappy" -) - -// This is the maximum amount of data that will be buffered in memory -// for a single freezer table batch. -const freezerBatchBufferLimit = 2 * 1024 * 1024 - -// freezerBatch is a write operation of multiple items on a freezer. -type freezerBatch struct { - tables map[string]*freezerTableBatch -} - -func newFreezerBatch(f *Freezer) *freezerBatch { - batch := &freezerBatch{tables: make(map[string]*freezerTableBatch, len(f.tables))} - for kind, table := range f.tables { - batch.tables[kind] = table.newBatch() - } - return batch -} - -// Append adds an RLP-encoded item of the given kind. -func (batch *freezerBatch) Append(kind string, num uint64, item interface{}) error { - return batch.tables[kind].Append(num, item) -} - -// AppendRaw adds an item of the given kind. -func (batch *freezerBatch) AppendRaw(kind string, num uint64, item []byte) error { - return batch.tables[kind].AppendRaw(num, item) -} - -// reset initializes the batch. -func (batch *freezerBatch) reset() { - for _, tb := range batch.tables { - tb.reset() - } -} - -// commit is called at the end of a write operation and -// writes all remaining data to tables. -func (batch *freezerBatch) commit() (item uint64, writeSize int64, err error) { - // Check that count agrees on all batches. - item = uint64(math.MaxUint64) - for name, tb := range batch.tables { - if item < math.MaxUint64 && tb.curItem != item { - return 0, 0, fmt.Errorf("table %s is at item %d, want %d", name, tb.curItem, item) - } - item = tb.curItem - } - - // Commit all table batches. - for _, tb := range batch.tables { - if err := tb.commit(); err != nil { - return 0, 0, err - } - writeSize += tb.totalBytes - } - return item, writeSize, nil -} - -// freezerTableBatch is a batch for a freezer table. -type freezerTableBatch struct { - t *freezerTable - - sb *snappyBuffer - encBuffer writeBuffer - dataBuffer []byte - indexBuffer []byte - curItem uint64 // expected index of next append - totalBytes int64 // counts written bytes since reset -} - -// newBatch creates a new batch for the freezer table. -func (t *freezerTable) newBatch() *freezerTableBatch { - batch := &freezerTableBatch{t: t} - if !t.noCompression { - batch.sb = new(snappyBuffer) - } - batch.reset() - return batch -} - -// reset clears the batch for reuse. -func (batch *freezerTableBatch) reset() { - batch.dataBuffer = batch.dataBuffer[:0] - batch.indexBuffer = batch.indexBuffer[:0] - batch.curItem = batch.t.items.Load() - batch.totalBytes = 0 -} - -// Append rlp-encodes and adds data at the end of the freezer table. The item number is a -// precautionary parameter to ensure data correctness, but the table will reject already -// existing data. -func (batch *freezerTableBatch) Append(item uint64, data interface{}) error { - if item != batch.curItem { - return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem) - } - - // Encode the item. - batch.encBuffer.Reset() - if err := rlp.Encode(&batch.encBuffer, data); err != nil { - return err - } - encItem := batch.encBuffer.data - if batch.sb != nil { - encItem = batch.sb.compress(encItem) - } - return batch.appendItem(encItem) -} - -// AppendRaw injects a binary blob at the end of the freezer table. The item number is a -// precautionary parameter to ensure data correctness, but the table will reject already -// existing data. -func (batch *freezerTableBatch) AppendRaw(item uint64, blob []byte) error { - if item != batch.curItem { - return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem) - } - - encItem := blob - if batch.sb != nil { - encItem = batch.sb.compress(blob) - } - return batch.appendItem(encItem) -} - -func (batch *freezerTableBatch) appendItem(data []byte) error { - // Check if item fits into current data file. - itemSize := int64(len(data)) - itemOffset := batch.t.headBytes + int64(len(batch.dataBuffer)) - if itemOffset+itemSize > int64(batch.t.maxFileSize) { - // It doesn't fit, go to next file first. - if err := batch.commit(); err != nil { - return err - } - if err := batch.t.advanceHead(); err != nil { - return err - } - itemOffset = 0 - } - - // Put data to buffer. - batch.dataBuffer = append(batch.dataBuffer, data...) - batch.totalBytes += itemSize - - // Put index entry to buffer. - entry := indexEntry{filenum: batch.t.headId, offset: uint32(itemOffset + itemSize)} - batch.indexBuffer = entry.append(batch.indexBuffer) - batch.curItem++ - - return batch.maybeCommit() -} - -// maybeCommit writes the buffered data if the buffer is full enough. -func (batch *freezerTableBatch) maybeCommit() error { - if len(batch.dataBuffer) > freezerBatchBufferLimit { - return batch.commit() - } - return nil -} - -// commit writes the batched items to the backing freezerTable. -func (batch *freezerTableBatch) commit() error { - // Write data. The head file is fsync'd after write to ensure the - // data is truly transferred to disk. - _, err := batch.t.head.Write(batch.dataBuffer) - if err != nil { - return err - } - if err := batch.t.head.Sync(); err != nil { - return err - } - dataSize := int64(len(batch.dataBuffer)) - batch.dataBuffer = batch.dataBuffer[:0] - - // Write indices. The index file is fsync'd after write to ensure the - // data indexes are truly transferred to disk. - _, err = batch.t.index.Write(batch.indexBuffer) - if err != nil { - return err - } - if err := batch.t.index.Sync(); err != nil { - return err - } - indexSize := int64(len(batch.indexBuffer)) - batch.indexBuffer = batch.indexBuffer[:0] - - // Update headBytes of table. - batch.t.headBytes += dataSize - batch.t.items.Store(batch.curItem) - - // Update metrics. - batch.t.sizeGauge.Inc(dataSize + indexSize) - batch.t.writeMeter.Mark(dataSize + indexSize) - return nil -} - -// snappyBuffer writes snappy in block format, and can be reused. It is -// reset when WriteTo is called. -type snappyBuffer struct { - dst []byte -} - -// compress snappy-compresses the data. -func (s *snappyBuffer) compress(data []byte) []byte { - // The snappy library does not care what the capacity of the buffer is, - // but only checks the length. If the length is too small, it will - // allocate a brand new buffer. - // To avoid that, we check the required size here, and grow the size of the - // buffer to utilize the full capacity. - if n := snappy.MaxEncodedLen(len(data)); len(s.dst) < n { - if cap(s.dst) < n { - s.dst = make([]byte, n) - } - s.dst = s.dst[:n] - } - - s.dst = snappy.Encode(s.dst, data) - return s.dst -} - -// writeBuffer implements io.Writer for a byte slice. -type writeBuffer struct { - data []byte -} - -func (wb *writeBuffer) Write(data []byte) (int, error) { - wb.data = append(wb.data, data...) - return len(data), nil -} - -func (wb *writeBuffer) Reset() { - wb.data = wb.data[:0] -} diff --git a/builder/core/rawdb/freezer_meta.go b/builder/core/rawdb/freezer_meta.go deleted file mode 100644 index 9eef9df35..000000000 --- a/builder/core/rawdb/freezer_meta.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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 rawdb - -import ( - "io" - "os" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -const freezerVersion = 1 // The initial version tag of freezer table metadata - -// freezerTableMeta wraps all the metadata of the freezer table. -type freezerTableMeta struct { - // Version is the versioning descriptor of the freezer table. - Version uint16 - - // VirtualTail indicates how many items have been marked as deleted. - // Its value is equal to the number of items removed from the table - // plus the number of items hidden in the table, so it should never - // be lower than the "actual tail". - VirtualTail uint64 -} - -// newMetadata initializes the metadata object with the given virtual tail. -func newMetadata(tail uint64) *freezerTableMeta { - return &freezerTableMeta{ - Version: freezerVersion, - VirtualTail: tail, - } -} - -// readMetadata reads the metadata of the freezer table from the -// given metadata file. -func readMetadata(file *os.File) (*freezerTableMeta, error) { - _, err := file.Seek(0, io.SeekStart) - if err != nil { - return nil, err - } - var meta freezerTableMeta - if err := rlp.Decode(file, &meta); err != nil { - return nil, err - } - return &meta, nil -} - -// writeMetadata writes the metadata of the freezer table into the -// given metadata file. -func writeMetadata(file *os.File, meta *freezerTableMeta) error { - _, err := file.Seek(0, io.SeekStart) - if err != nil { - return err - } - return rlp.Encode(file, meta) -} - -// loadMetadata loads the metadata from the given metadata file. -// Initializes the metadata file with the given "actual tail" if -// it's empty. -func loadMetadata(file *os.File, tail uint64) (*freezerTableMeta, error) { - stat, err := file.Stat() - if err != nil { - return nil, err - } - // Write the metadata with the given actual tail into metadata file - // if it's non-existent. There are two possible scenarios here: - // - the freezer table is empty - // - the freezer table is legacy - // In both cases, write the meta into the file with the actual tail - // as the virtual tail. - if stat.Size() == 0 { - m := newMetadata(tail) - if err := writeMetadata(file, m); err != nil { - return nil, err - } - return m, nil - } - m, err := readMetadata(file) - if err != nil { - return nil, err - } - // Update the virtual tail with the given actual tail if it's even - // lower than it. Theoretically it shouldn't happen at all, print - // a warning here. - if m.VirtualTail < tail { - log.Warn("Updated virtual tail", "have", m.VirtualTail, "now", tail) - m.VirtualTail = tail - if err := writeMetadata(file, m); err != nil { - return nil, err - } - } - return m, nil -} diff --git a/builder/core/rawdb/freezer_meta_test.go b/builder/core/rawdb/freezer_meta_test.go deleted file mode 100644 index ba1a95e45..000000000 --- a/builder/core/rawdb/freezer_meta_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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 rawdb - -import ( - "os" - "testing" -) - -func TestReadWriteFreezerTableMeta(t *testing.T) { - f, err := os.CreateTemp(os.TempDir(), "*") - if err != nil { - t.Fatalf("Failed to create file %v", err) - } - err = writeMetadata(f, newMetadata(100)) - if err != nil { - t.Fatalf("Failed to write metadata %v", err) - } - meta, err := readMetadata(f) - if err != nil { - t.Fatalf("Failed to read metadata %v", err) - } - if meta.Version != freezerVersion { - t.Fatalf("Unexpected version field") - } - if meta.VirtualTail != uint64(100) { - t.Fatalf("Unexpected virtual tail field") - } -} - -func TestInitializeFreezerTableMeta(t *testing.T) { - f, err := os.CreateTemp(os.TempDir(), "*") - if err != nil { - t.Fatalf("Failed to create file %v", err) - } - meta, err := loadMetadata(f, uint64(100)) - if err != nil { - t.Fatalf("Failed to read metadata %v", err) - } - if meta.Version != freezerVersion { - t.Fatalf("Unexpected version field") - } - if meta.VirtualTail != uint64(100) { - t.Fatalf("Unexpected virtual tail field") - } -} diff --git a/builder/core/rawdb/freezer_resettable.go b/builder/core/rawdb/freezer_resettable.go deleted file mode 100644 index 7a8548973..000000000 --- a/builder/core/rawdb/freezer_resettable.go +++ /dev/null @@ -1,238 +0,0 @@ -// 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 rawdb - -import ( - "os" - "path/filepath" - "sync" - - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -const tmpSuffix = ".tmp" - -// freezerOpenFunc is the function used to open/create a freezer. -type freezerOpenFunc = func() (*Freezer, error) - -// ResettableFreezer is a wrapper of the freezer which makes the -// freezer resettable. -type ResettableFreezer struct { - freezer *Freezer - opener freezerOpenFunc - datadir string - lock sync.RWMutex -} - -// NewResettableFreezer creates a resettable freezer, note freezer is -// only resettable if the passed file directory is exclusively occupied -// by the freezer. And also the user-configurable ancient root directory -// is **not** supported for reset since it might be a mount and rename -// will cause a copy of hundreds of gigabyte into local directory. It -// needs some other file based solutions. -// -// The reset function will delete directory atomically and re-create the -// freezer from scratch. -func NewResettableFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*ResettableFreezer, error) { - if err := cleanup(datadir); err != nil { - return nil, err - } - opener := func() (*Freezer, error) { - return NewFreezer(datadir, namespace, readonly, maxTableSize, tables) - } - freezer, err := opener() - if err != nil { - return nil, err - } - return &ResettableFreezer{ - freezer: freezer, - opener: opener, - datadir: datadir, - }, nil -} - -// Reset deletes the file directory exclusively occupied by the freezer and -// recreate the freezer from scratch. The atomicity of directory deletion -// is guaranteed by the rename operation, the leftover directory will be -// cleaned up in next startup in case crash happens after rename. -func (f *ResettableFreezer) Reset() error { - f.lock.Lock() - defer f.lock.Unlock() - - if err := f.freezer.Close(); err != nil { - return err - } - tmp := tmpName(f.datadir) - if err := os.Rename(f.datadir, tmp); err != nil { - return err - } - if err := os.RemoveAll(tmp); err != nil { - return err - } - freezer, err := f.opener() - if err != nil { - return err - } - f.freezer = freezer - return nil -} - -// Close terminates the chain freezer, unmapping all the data files. -func (f *ResettableFreezer) Close() error { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.Close() -} - -// HasAncient returns an indicator whether the specified ancient data exists -// in the freezer -func (f *ResettableFreezer) HasAncient(kind string, number uint64) (bool, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.HasAncient(kind, number) -} - -// Ancient retrieves an ancient binary blob from the append-only immutable files. -func (f *ResettableFreezer) Ancient(kind string, number uint64) ([]byte, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.Ancient(kind, number) -} - -// AncientRange retrieves multiple items in sequence, starting from the index 'start'. -// It will return -// - at most 'count' items, -// - if maxBytes is specified: at least 1 item (even if exceeding the maxByteSize), -// but will otherwise return as many items as fit into maxByteSize. -// - if maxBytes is not specified, 'count' items will be returned if they are present. -func (f *ResettableFreezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.AncientRange(kind, start, count, maxBytes) -} - -// Ancients returns the length of the frozen items. -func (f *ResettableFreezer) Ancients() (uint64, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.Ancients() -} - -// Tail returns the number of first stored item in the freezer. -func (f *ResettableFreezer) Tail() (uint64, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.Tail() -} - -// AncientSize returns the ancient size of the specified category. -func (f *ResettableFreezer) AncientSize(kind string) (uint64, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.AncientSize(kind) -} - -// ReadAncients runs the given read operation while ensuring that no writes take place -// on the underlying freezer. -func (f *ResettableFreezer) ReadAncients(fn func(ethdb.AncientReaderOp) error) (err error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.ReadAncients(fn) -} - -// ModifyAncients runs the given write operation. -func (f *ResettableFreezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (writeSize int64, err error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.ModifyAncients(fn) -} - -// TruncateHead discards any recent data above the provided threshold number. -// It returns the previous head number. -func (f *ResettableFreezer) TruncateHead(items uint64) (uint64, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.TruncateHead(items) -} - -// TruncateTail discards any recent data below the provided threshold number. -// It returns the previous value -func (f *ResettableFreezer) TruncateTail(tail uint64) (uint64, error) { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.TruncateTail(tail) -} - -// Sync flushes all data tables to disk. -func (f *ResettableFreezer) Sync() error { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.Sync() -} - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (f *ResettableFreezer) MigrateTable(kind string, convert convertLegacyFn) error { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.freezer.MigrateTable(kind, convert) -} - -// cleanup removes the directory located in the specified path -// has the name with deletion marker suffix. -func cleanup(path string) error { - parent := filepath.Dir(path) - if _, err := os.Lstat(parent); os.IsNotExist(err) { - return nil - } - dir, err := os.Open(parent) - if err != nil { - return err - } - names, err := dir.Readdirnames(0) - if err != nil { - return err - } - if cerr := dir.Close(); cerr != nil { - return cerr - } - for _, name := range names { - if name == filepath.Base(path)+tmpSuffix { - log.Info("Removed leftover freezer directory", "name", name) - return os.RemoveAll(filepath.Join(parent, name)) - } - } - return nil -} - -func tmpName(path string) string { - return filepath.Join(filepath.Dir(path), filepath.Base(path)+tmpSuffix) -} diff --git a/builder/core/rawdb/freezer_resettable_test.go b/builder/core/rawdb/freezer_resettable_test.go deleted file mode 100644 index d741bc14e..000000000 --- a/builder/core/rawdb/freezer_resettable_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "os" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" -) - -func TestResetFreezer(t *testing.T) { - items := []struct { - id uint64 - blob []byte - }{ - {0, bytes.Repeat([]byte{0}, 2048)}, - {1, bytes.Repeat([]byte{1}, 2048)}, - {2, bytes.Repeat([]byte{2}, 2048)}, - } - f, _ := NewResettableFreezer(t.TempDir(), "", false, 2048, freezerTestTableDef) - defer f.Close() - - f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for _, item := range items { - op.AppendRaw("test", item.id, item.blob) - } - return nil - }) - for _, item := range items { - blob, _ := f.Ancient("test", item.id) - if !bytes.Equal(blob, item.blob) { - t.Fatal("Unexpected blob") - } - } - - // Reset freezer - f.Reset() - count, _ := f.Ancients() - if count != 0 { - t.Fatal("Failed to reset freezer") - } - for _, item := range items { - blob, _ := f.Ancient("test", item.id) - if len(blob) != 0 { - t.Fatal("Unexpected blob") - } - } - - // Fill the freezer - f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for _, item := range items { - op.AppendRaw("test", item.id, item.blob) - } - return nil - }) - for _, item := range items { - blob, _ := f.Ancient("test", item.id) - if !bytes.Equal(blob, item.blob) { - t.Fatal("Unexpected blob") - } - } -} - -func TestFreezerCleanup(t *testing.T) { - items := []struct { - id uint64 - blob []byte - }{ - {0, bytes.Repeat([]byte{0}, 2048)}, - {1, bytes.Repeat([]byte{1}, 2048)}, - {2, bytes.Repeat([]byte{2}, 2048)}, - } - datadir := t.TempDir() - f, _ := NewResettableFreezer(datadir, "", false, 2048, freezerTestTableDef) - f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for _, item := range items { - op.AppendRaw("test", item.id, item.blob) - } - return nil - }) - f.Close() - os.Rename(datadir, tmpName(datadir)) - - // Open the freezer again, trigger cleanup operation - f, _ = NewResettableFreezer(datadir, "", false, 2048, freezerTestTableDef) - f.Close() - - if _, err := os.Lstat(tmpName(datadir)); !os.IsNotExist(err) { - t.Fatal("Failed to cleanup leftover directory") - } -} diff --git a/builder/core/rawdb/freezer_table.go b/builder/core/rawdb/freezer_table.go deleted file mode 100644 index 4b9d510e8..000000000 --- a/builder/core/rawdb/freezer_table.go +++ /dev/null @@ -1,990 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "os" - "path/filepath" - "sync" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/golang/snappy" -) - -var ( - // errClosed is returned if an operation attempts to read from or write to the - // freezer table after it has already been closed. - errClosed = errors.New("closed") - - // errOutOfBounds is returned if the item requested is not contained within the - // freezer table. - errOutOfBounds = errors.New("out of bounds") - - // errNotSupported is returned if the database doesn't support the required operation. - errNotSupported = errors.New("this operation is not supported") -) - -// indexEntry contains the number/id of the file that the data resides in, as well as the -// offset within the file to the end of the data. -// In serialized form, the filenum is stored as uint16. -type indexEntry struct { - filenum uint32 // stored as uint16 ( 2 bytes ) - offset uint32 // stored as uint32 ( 4 bytes ) -} - -const indexEntrySize = 6 - -// unmarshalBinary deserializes binary b into the rawIndex entry. -func (i *indexEntry) unmarshalBinary(b []byte) { - i.filenum = uint32(binary.BigEndian.Uint16(b[:2])) - i.offset = binary.BigEndian.Uint32(b[2:6]) -} - -// append adds the encoded entry to the end of b. -func (i *indexEntry) append(b []byte) []byte { - offset := len(b) - out := append(b, make([]byte, indexEntrySize)...) - binary.BigEndian.PutUint16(out[offset:], uint16(i.filenum)) - binary.BigEndian.PutUint32(out[offset+2:], i.offset) - return out -} - -// bounds returns the start- and end- offsets, and the file number of where to -// read there data item marked by the two index entries. The two entries are -// assumed to be sequential. -func (i *indexEntry) bounds(end *indexEntry) (startOffset, endOffset, fileId uint32) { - if i.filenum != end.filenum { - // If a piece of data 'crosses' a data-file, - // it's actually in one piece on the second data-file. - // We return a zero-indexEntry for the second file as start - return 0, end.offset, end.filenum - } - return i.offset, end.offset, end.filenum -} - -// freezerTable represents a single chained data table within the freezer (e.g. blocks). -// It consists of a data file (snappy encoded arbitrary data blobs) and an indexEntry -// file (uncompressed 64 bit indices into the data file). -type freezerTable struct { - items atomic.Uint64 // Number of items stored in the table (including items removed from tail) - itemOffset atomic.Uint64 // Number of items removed from the table - - // itemHidden is the number of items marked as deleted. Tail deletion is - // only supported at file level which means the actual deletion will be - // delayed until the entire data file is marked as deleted. Before that - // these items will be hidden to prevent being visited again. The value - // should never be lower than itemOffset. - itemHidden atomic.Uint64 - - noCompression bool // if true, disables snappy compression. Note: does not work retroactively - readonly bool - maxFileSize uint32 // Max file size for data-files - name string - path string - - head *os.File // File descriptor for the data head of the table - index *os.File // File descriptor for the indexEntry file of the table - meta *os.File // File descriptor for metadata of the table - files map[uint32]*os.File // open files - headId uint32 // number of the currently active head file - tailId uint32 // number of the earliest file - - headBytes int64 // Number of bytes written to the head file - readMeter metrics.Meter // Meter for measuring the effective amount of data read - writeMeter metrics.Meter // Meter for measuring the effective amount of data written - sizeGauge metrics.Gauge // Gauge for tracking the combined size of all freezer tables - - logger log.Logger // Logger with database path and table name embedded - lock sync.RWMutex // Mutex protecting the data file descriptors -} - -// newFreezerTable opens the given path as a freezer table. -func newFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) { - return newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly) -} - -// newTable opens a freezer table, creating the data and index files if they are -// non-existent. Both files are truncated to the shortest common length to ensure -// they don't go out of sync. -func newTable(path string, name string, readMeter metrics.Meter, writeMeter metrics.Meter, sizeGauge metrics.Gauge, maxFilesize uint32, noCompression, readonly bool) (*freezerTable, error) { - // Ensure the containing directory exists and open the indexEntry file - if err := os.MkdirAll(path, 0755); err != nil { - return nil, err - } - var idxName string - if noCompression { - idxName = fmt.Sprintf("%s.ridx", name) // raw index file - } else { - idxName = fmt.Sprintf("%s.cidx", name) // compressed index file - } - var ( - err error - index *os.File - meta *os.File - ) - if readonly { - // Will fail if table index file or meta file is not existent - index, err = openFreezerFileForReadOnly(filepath.Join(path, idxName)) - if err != nil { - return nil, err - } - meta, err = openFreezerFileForReadOnly(filepath.Join(path, fmt.Sprintf("%s.meta", name))) - if err != nil { - return nil, err - } - } else { - index, err = openFreezerFileForAppend(filepath.Join(path, idxName)) - if err != nil { - return nil, err - } - meta, err = openFreezerFileForAppend(filepath.Join(path, fmt.Sprintf("%s.meta", name))) - if err != nil { - return nil, err - } - } - // Create the table and repair any past inconsistency - tab := &freezerTable{ - index: index, - meta: meta, - files: make(map[uint32]*os.File), - readMeter: readMeter, - writeMeter: writeMeter, - sizeGauge: sizeGauge, - name: name, - path: path, - logger: log.New("database", path, "table", name), - noCompression: noCompression, - readonly: readonly, - maxFileSize: maxFilesize, - } - if err := tab.repair(); err != nil { - tab.Close() - return nil, err - } - // Initialize the starting size counter - size, err := tab.sizeNolock() - if err != nil { - tab.Close() - return nil, err - } - tab.sizeGauge.Inc(int64(size)) - - return tab, nil -} - -// repair cross-checks the head and the index file and truncates them to -// be in sync with each other after a potential crash / data loss. -func (t *freezerTable) repair() error { - // Create a temporary offset buffer to init files with and read indexEntry into - buffer := make([]byte, indexEntrySize) - - // If we've just created the files, initialize the index with the 0 indexEntry - stat, err := t.index.Stat() - if err != nil { - return err - } - if stat.Size() == 0 { - if _, err := t.index.Write(buffer); err != nil { - return err - } - } - // Ensure the index is a multiple of indexEntrySize bytes - if overflow := stat.Size() % indexEntrySize; overflow != 0 { - if t.readonly { - return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize) - } - if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil { - return err - } // New file can't trigger this path - } - // Retrieve the file sizes and prepare for truncation - if stat, err = t.index.Stat(); err != nil { - return err - } - offsetsSize := stat.Size() - - // Open the head file - var ( - firstIndex indexEntry - lastIndex indexEntry - contentSize int64 - contentExp int64 - verbose bool - ) - // Read index zero, determine what file is the earliest - // and what item offset to use - t.index.ReadAt(buffer, 0) - firstIndex.unmarshalBinary(buffer) - - // Assign the tail fields with the first stored index. - // The total removed items is represented with an uint32, - // which is not enough in theory but enough in practice. - // TODO: use uint64 to represent total removed items. - t.tailId = firstIndex.filenum - t.itemOffset.Store(uint64(firstIndex.offset)) - - // Load metadata from the file - meta, err := loadMetadata(t.meta, t.itemOffset.Load()) - if err != nil { - return err - } - t.itemHidden.Store(meta.VirtualTail) - - // Read the last index, use the default value in case the freezer is empty - if offsetsSize == indexEntrySize { - lastIndex = indexEntry{filenum: t.tailId, offset: 0} - } else { - t.index.ReadAt(buffer, offsetsSize-indexEntrySize) - lastIndex.unmarshalBinary(buffer) - } - // Print an error log if the index is corrupted due to an incorrect - // last index item. While it is theoretically possible to have a zero offset - // by storing all zero-size items, it is highly unlikely to occur in practice. - if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 { - log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize) - } - if t.readonly { - t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly) - } else { - t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForAppend) - } - if err != nil { - return err - } - if stat, err = t.head.Stat(); err != nil { - return err - } - contentSize = stat.Size() - - // Keep truncating both files until they come in sync - contentExp = int64(lastIndex.offset) - for contentExp != contentSize { - if t.readonly { - return fmt.Errorf("freezer table(path: %s, name: %s, num: %d) is corrupted", t.path, t.name, lastIndex.filenum) - } - verbose = true - // Truncate the head file to the last offset pointer - if contentExp < contentSize { - t.logger.Warn("Truncating dangling head", "indexed", contentExp, "stored", contentSize) - if err := truncateFreezerFile(t.head, contentExp); err != nil { - return err - } - contentSize = contentExp - } - // Truncate the index to point within the head file - if contentExp > contentSize { - t.logger.Warn("Truncating dangling indexes", "indexes", offsetsSize/indexEntrySize, "indexed", contentExp, "stored", contentSize) - if err := truncateFreezerFile(t.index, offsetsSize-indexEntrySize); err != nil { - return err - } - offsetsSize -= indexEntrySize - - // Read the new head index, use the default value in case - // the freezer is already empty. - var newLastIndex indexEntry - if offsetsSize == indexEntrySize { - newLastIndex = indexEntry{filenum: t.tailId, offset: 0} - } else { - t.index.ReadAt(buffer, offsetsSize-indexEntrySize) - newLastIndex.unmarshalBinary(buffer) - } - // We might have slipped back into an earlier head-file here - if newLastIndex.filenum != lastIndex.filenum { - // Release earlier opened file - t.releaseFile(lastIndex.filenum) - if t.head, err = t.openFile(newLastIndex.filenum, openFreezerFileForAppend); err != nil { - return err - } - if stat, err = t.head.Stat(); err != nil { - // TODO, anything more we can do here? - // A data file has gone missing... - return err - } - contentSize = stat.Size() - } - lastIndex = newLastIndex - contentExp = int64(lastIndex.offset) - } - } - // Sync() fails for read-only files on windows. - if !t.readonly { - // Ensure all reparation changes have been written to disk - if err := t.index.Sync(); err != nil { - return err - } - if err := t.head.Sync(); err != nil { - return err - } - if err := t.meta.Sync(); err != nil { - return err - } - } - // Update the item and byte counters and return - t.items.Store(t.itemOffset.Load() + uint64(offsetsSize/indexEntrySize-1)) // last indexEntry points to the end of the data file - t.headBytes = contentSize - t.headId = lastIndex.filenum - - // Delete the leftover files because of head deletion - t.releaseFilesAfter(t.headId, true) - - // Delete the leftover files because of tail deletion - t.releaseFilesBefore(t.tailId, true) - - // Close opened files and preopen all files - if err := t.preopen(); err != nil { - return err - } - if verbose { - t.logger.Info("Chain freezer table opened", "items", t.items.Load(), "deleted", t.itemOffset.Load(), "hidden", t.itemHidden.Load(), "tailId", t.tailId, "headId", t.headId, "size", t.headBytes) - } else { - t.logger.Debug("Chain freezer table opened", "items", t.items.Load(), "size", common.StorageSize(t.headBytes)) - } - return nil -} - -// preopen opens all files that the freezer will need. This method should be called from an init-context, -// since it assumes that it doesn't have to bother with locking -// The rationale for doing preopen is to not have to do it from within Retrieve, thus not needing to ever -// obtain a write-lock within Retrieve. -func (t *freezerTable) preopen() (err error) { - // The repair might have already opened (some) files - t.releaseFilesAfter(0, false) - - // Open all except head in RDONLY - for i := t.tailId; i < t.headId; i++ { - if _, err = t.openFile(i, openFreezerFileForReadOnly); err != nil { - return err - } - } - if t.readonly { - t.head, err = t.openFile(t.headId, openFreezerFileForReadOnly) - } else { - // Open head in read/write - t.head, err = t.openFile(t.headId, openFreezerFileForAppend) - } - return err -} - -// truncateHead discards any recent data above the provided threshold number. -func (t *freezerTable) truncateHead(items uint64) error { - t.lock.Lock() - defer t.lock.Unlock() - - // Ensure the given truncate target falls in the correct range - existing := t.items.Load() - if existing <= items { - return nil - } - if items < t.itemHidden.Load() { - return errors.New("truncation below tail") - } - // We need to truncate, save the old size for metrics tracking - oldSize, err := t.sizeNolock() - if err != nil { - return err - } - // Something's out of sync, truncate the table's offset index - log := t.logger.Debug - if existing > items+1 { - log = t.logger.Warn // Only loud warn if we delete multiple items - } - log("Truncating freezer table", "items", existing, "limit", items) - - // Truncate the index file first, the tail position is also considered - // when calculating the new freezer table length. - length := items - t.itemOffset.Load() - if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil { - return err - } - if err := t.index.Sync(); err != nil { - return err - } - // Calculate the new expected size of the data file and truncate it - var expected indexEntry - if length == 0 { - expected = indexEntry{filenum: t.tailId, offset: 0} - } else { - buffer := make([]byte, indexEntrySize) - if _, err := t.index.ReadAt(buffer, int64(length*indexEntrySize)); err != nil { - return err - } - expected.unmarshalBinary(buffer) - } - // We might need to truncate back to older files - if expected.filenum != t.headId { - // If already open for reading, force-reopen for writing - t.releaseFile(expected.filenum) - newHead, err := t.openFile(expected.filenum, openFreezerFileForAppend) - if err != nil { - return err - } - // Release any files _after the current head -- both the previous head - // and any files which may have been opened for reading - t.releaseFilesAfter(expected.filenum, true) - - // Set back the historic head - t.head = newHead - t.headId = expected.filenum - } - if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil { - return err - } - if err := t.head.Sync(); err != nil { - return err - } - // All data files truncated, set internal counters and return - t.headBytes = int64(expected.offset) - t.items.Store(items) - - // Retrieve the new size and update the total size counter - newSize, err := t.sizeNolock() - if err != nil { - return err - } - t.sizeGauge.Dec(int64(oldSize - newSize)) - return nil -} - -// sizeHidden returns the total data size of hidden items in the freezer table. -// This function assumes the lock is already held. -func (t *freezerTable) sizeHidden() (uint64, error) { - hidden, offset := t.itemHidden.Load(), t.itemOffset.Load() - if hidden <= offset { - return 0, nil - } - indices, err := t.getIndices(hidden-1, 1) - if err != nil { - return 0, err - } - return uint64(indices[1].offset), nil -} - -// truncateTail discards any recent data before the provided threshold number. -func (t *freezerTable) truncateTail(items uint64) error { - t.lock.Lock() - defer t.lock.Unlock() - - // Ensure the given truncate target falls in the correct range - if t.itemHidden.Load() >= items { - return nil - } - if t.items.Load() < items { - return errors.New("truncation above head") - } - // Load the new tail index by the given new tail position - var ( - newTailId uint32 - buffer = make([]byte, indexEntrySize) - ) - if t.items.Load() == items { - newTailId = t.headId - } else { - offset := items - t.itemOffset.Load() - if _, err := t.index.ReadAt(buffer, int64((offset+1)*indexEntrySize)); err != nil { - return err - } - var newTail indexEntry - newTail.unmarshalBinary(buffer) - newTailId = newTail.filenum - } - // Save the old size for metrics tracking. This needs to be done - // before any updates to either itemHidden or itemOffset. - oldSize, err := t.sizeNolock() - if err != nil { - return err - } - // Update the virtual tail marker and hidden these entries in table. - t.itemHidden.Store(items) - if err := writeMetadata(t.meta, newMetadata(items)); err != nil { - return err - } - // Hidden items still fall in the current tail file, no data file - // can be dropped. - if t.tailId == newTailId { - return nil - } - // Hidden items fall in the incorrect range, returns the error. - if t.tailId > newTailId { - return fmt.Errorf("invalid index, tail-file %d, item-file %d", t.tailId, newTailId) - } - // Count how many items can be deleted from the file. - var ( - newDeleted = items - deleted = t.itemOffset.Load() - ) - // Hidden items exceed the current tail file, drop the relevant data files. - for current := items - 1; current >= deleted; current -= 1 { - if _, err := t.index.ReadAt(buffer, int64((current-deleted+1)*indexEntrySize)); err != nil { - return err - } - var pre indexEntry - pre.unmarshalBinary(buffer) - if pre.filenum != newTailId { - break - } - newDeleted = current - } - // Commit the changes of metadata file first before manipulating - // the indexes file. - if err := t.meta.Sync(); err != nil { - return err - } - // Close the index file before shorten it. - if err := t.index.Close(); err != nil { - return err - } - // Truncate the deleted index entries from the index file. - err = copyFrom(t.index.Name(), t.index.Name(), indexEntrySize*(newDeleted-deleted+1), func(f *os.File) error { - tailIndex := indexEntry{ - filenum: newTailId, - offset: uint32(newDeleted), - } - _, err := f.Write(tailIndex.append(nil)) - return err - }) - if err != nil { - return err - } - // Reopen the modified index file to load the changes - t.index, err = openFreezerFileForAppend(t.index.Name()) - if err != nil { - return err - } - // Sync the file to ensure changes are flushed to disk - if err := t.index.Sync(); err != nil { - return err - } - // Release any files before the current tail - t.tailId = newTailId - t.itemOffset.Store(newDeleted) - t.releaseFilesBefore(t.tailId, true) - - // Retrieve the new size and update the total size counter - newSize, err := t.sizeNolock() - if err != nil { - return err - } - t.sizeGauge.Dec(int64(oldSize - newSize)) - return nil -} - -// Close closes all opened files. -func (t *freezerTable) Close() error { - t.lock.Lock() - defer t.lock.Unlock() - - var errs []error - doClose := func(f *os.File, sync bool, close bool) { - if sync && !t.readonly { - if err := f.Sync(); err != nil { - errs = append(errs, err) - } - } - if close { - if err := f.Close(); err != nil { - errs = append(errs, err) - } - } - } - // Trying to fsync a file opened in rdonly causes "Access denied" - // error on Windows. - doClose(t.index, true, true) - doClose(t.meta, true, true) - - // The preopened non-head data-files are all opened in readonly. - // The head is opened in rw-mode, so we sync it here - but since it's also - // part of t.files, it will be closed in the loop below. - doClose(t.head, true, false) // sync but do not close - - for _, f := range t.files { - doClose(f, false, true) // close but do not sync - } - t.index = nil - t.meta = nil - t.head = nil - - if errs != nil { - return fmt.Errorf("%v", errs) - } - return nil -} - -// openFile assumes that the write-lock is held by the caller -func (t *freezerTable) openFile(num uint32, opener func(string) (*os.File, error)) (f *os.File, err error) { - var exist bool - if f, exist = t.files[num]; !exist { - var name string - if t.noCompression { - name = fmt.Sprintf("%s.%04d.rdat", t.name, num) - } else { - name = fmt.Sprintf("%s.%04d.cdat", t.name, num) - } - f, err = opener(filepath.Join(t.path, name)) - if err != nil { - return nil, err - } - t.files[num] = f - } - return f, err -} - -// releaseFile closes a file, and removes it from the open file cache. -// Assumes that the caller holds the write lock -func (t *freezerTable) releaseFile(num uint32) { - if f, exist := t.files[num]; exist { - delete(t.files, num) - f.Close() - } -} - -// releaseFilesAfter closes all open files with a higher number, and optionally also deletes the files -func (t *freezerTable) releaseFilesAfter(num uint32, remove bool) { - for fnum, f := range t.files { - if fnum > num { - delete(t.files, fnum) - f.Close() - if remove { - os.Remove(f.Name()) - } - } - } -} - -// releaseFilesBefore closes all open files with a lower number, and optionally also deletes the files -func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) { - for fnum, f := range t.files { - if fnum < num { - delete(t.files, fnum) - f.Close() - if remove { - os.Remove(f.Name()) - } - } - } -} - -// getIndices returns the index entries for the given from-item, covering 'count' items. -// N.B: The actual number of returned indices for N items will always be N+1 (unless an -// error is returned). -// OBS: This method assumes that the caller has already verified (and/or trimmed) the range -// so that the items are within bounds. If this method is used to read out of bounds, -// it will return error. -func (t *freezerTable) getIndices(from, count uint64) ([]*indexEntry, error) { - // Apply the table-offset - from = from - t.itemOffset.Load() - - // For reading N items, we need N+1 indices. - buffer := make([]byte, (count+1)*indexEntrySize) - if _, err := t.index.ReadAt(buffer, int64(from*indexEntrySize)); err != nil { - return nil, err - } - var ( - indices []*indexEntry - offset int - ) - for i := from; i <= from+count; i++ { - index := new(indexEntry) - index.unmarshalBinary(buffer[offset:]) - offset += indexEntrySize - indices = append(indices, index) - } - if from == 0 { - // Special case if we're reading the first item in the freezer. We assume that - // the first item always start from zero(regarding the deletion, we - // only support deletion by files, so that the assumption is held). - // This means we can use the first item metadata to carry information about - // the 'global' offset, for the deletion-case - indices[0].offset = 0 - indices[0].filenum = indices[1].filenum - } - return indices, nil -} - -// Retrieve looks up the data offset of an item with the given number and retrieves -// the raw binary blob from the data file. -func (t *freezerTable) Retrieve(item uint64) ([]byte, error) { - items, err := t.RetrieveItems(item, 1, 0) - if err != nil { - return nil, err - } - return items[0], nil -} - -// RetrieveItems returns multiple items in sequence, starting from the index 'start'. -// It will return at most 'max' items, but will abort earlier to respect the -// 'maxBytes' argument. However, if the 'maxBytes' is smaller than the size of one -// item, it _will_ return one element and possibly overflow the maxBytes. -func (t *freezerTable) RetrieveItems(start, count, maxBytes uint64) ([][]byte, error) { - // First we read the 'raw' data, which might be compressed. - diskData, sizes, err := t.retrieveItems(start, count, maxBytes) - if err != nil { - return nil, err - } - var ( - output = make([][]byte, 0, count) - offset int // offset for reading - outputSize int // size of uncompressed data - ) - // Now slice up the data and decompress. - for i, diskSize := range sizes { - item := diskData[offset : offset+diskSize] - offset += diskSize - decompressedSize := diskSize - if !t.noCompression { - decompressedSize, _ = snappy.DecodedLen(item) - } - if i > 0 && maxBytes != 0 && uint64(outputSize+decompressedSize) > maxBytes { - break - } - if !t.noCompression { - data, err := snappy.Decode(nil, item) - if err != nil { - return nil, err - } - output = append(output, data) - } else { - output = append(output, item) - } - outputSize += decompressedSize - } - return output, nil -} - -// retrieveItems reads up to 'count' items from the table. It reads at least -// one item, but otherwise avoids reading more than maxBytes bytes. Freezer -// will ignore the size limitation and continuously allocate memory to store -// data if maxBytes is 0. It returns the (potentially compressed) data, and -// the sizes. -func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []int, error) { - t.lock.RLock() - defer t.lock.RUnlock() - - // Ensure the table and the item are accessible - if t.index == nil || t.head == nil || t.meta == nil { - return nil, nil, errClosed - } - var ( - items = t.items.Load() // the total items(head + 1) - hidden = t.itemHidden.Load() // the number of hidden items - ) - // Ensure the start is written, not deleted from the tail, and that the - // caller actually wants something - if items <= start || hidden > start || count == 0 { - return nil, nil, errOutOfBounds - } - if start+count > items { - count = items - start - } - var output []byte // Buffer to read data into - if maxBytes != 0 { - output = make([]byte, 0, maxBytes) - } else { - output = make([]byte, 0, 1024) // initial buffer cap - } - // readData is a helper method to read a single data item from disk. - readData := func(fileId, start uint32, length int) error { - output = grow(output, length) - dataFile, exist := t.files[fileId] - if !exist { - return fmt.Errorf("missing data file %d", fileId) - } - if _, err := dataFile.ReadAt(output[len(output)-length:], int64(start)); err != nil { - return fmt.Errorf("%w, fileid: %d, start: %d, length: %d", err, fileId, start, length) - } - return nil - } - // Read all the indexes in one go - indices, err := t.getIndices(start, count) - if err != nil { - return nil, nil, err - } - var ( - sizes []int // The sizes for each element - totalSize = 0 // The total size of all data read so far - readStart = indices[0].offset // Where, in the file, to start reading - unreadSize = 0 // The size of the as-yet-unread data - ) - - for i, firstIndex := range indices[:len(indices)-1] { - secondIndex := indices[i+1] - // Determine the size of the item. - offset1, offset2, _ := firstIndex.bounds(secondIndex) - size := int(offset2 - offset1) - // Crossing a file boundary? - if secondIndex.filenum != firstIndex.filenum { - // If we have unread data in the first file, we need to do that read now. - if unreadSize > 0 { - if err := readData(firstIndex.filenum, readStart, unreadSize); err != nil { - return nil, nil, err - } - unreadSize = 0 - } - readStart = 0 - } - if i > 0 && uint64(totalSize+size) > maxBytes && maxBytes != 0 { - // About to break out due to byte limit being exceeded. We don't - // read this last item, but we need to do the deferred reads now. - if unreadSize > 0 { - if err := readData(secondIndex.filenum, readStart, unreadSize); err != nil { - return nil, nil, err - } - } - break - } - // Defer the read for later - unreadSize += size - totalSize += size - sizes = append(sizes, size) - if i == len(indices)-2 || (uint64(totalSize) > maxBytes && maxBytes != 0) { - // Last item, need to do the read now - if err := readData(secondIndex.filenum, readStart, unreadSize); err != nil { - return nil, nil, err - } - break - } - } - - // Update metrics. - t.readMeter.Mark(int64(totalSize)) - return output, sizes, nil -} - -// has returns an indicator whether the specified number data is still accessible -// in the freezer table. -func (t *freezerTable) has(number uint64) bool { - return t.items.Load() > number && t.itemHidden.Load() <= number -} - -// size returns the total data size in the freezer table. -func (t *freezerTable) size() (uint64, error) { - t.lock.RLock() - defer t.lock.RUnlock() - - return t.sizeNolock() -} - -// sizeNolock returns the total data size in the freezer table. This function -// assumes the lock is already held. -func (t *freezerTable) sizeNolock() (uint64, error) { - stat, err := t.index.Stat() - if err != nil { - return 0, err - } - hidden, err := t.sizeHidden() - if err != nil { - return 0, err - } - total := uint64(t.maxFileSize)*uint64(t.headId-t.tailId) + uint64(t.headBytes) + uint64(stat.Size()) - hidden - return total, nil -} - -// advanceHead should be called when the current head file would outgrow the file limits, -// and a new file must be opened. The caller of this method must hold the write-lock -// before calling this method. -func (t *freezerTable) advanceHead() error { - t.lock.Lock() - defer t.lock.Unlock() - - // We open the next file in truncated mode -- if this file already - // exists, we need to start over from scratch on it. - nextID := t.headId + 1 - newHead, err := t.openFile(nextID, openFreezerFileTruncated) - if err != nil { - return err - } - // Commit the contents of the old file to stable storage and - // tear it down. It will be re-opened in read-only mode. - if err := t.head.Sync(); err != nil { - return err - } - t.releaseFile(t.headId) - t.openFile(t.headId, openFreezerFileForReadOnly) - - // Swap out the current head. - t.head = newHead - t.headBytes = 0 - t.headId = nextID - return nil -} - -// Sync pushes any pending data from memory out to disk. This is an expensive -// operation, so use it with care. -func (t *freezerTable) Sync() error { - t.lock.Lock() - defer t.lock.Unlock() - if t.index == nil || t.head == nil || t.meta == nil { - return errClosed - } - var err error - trackError := func(e error) { - if e != nil && err == nil { - err = e - } - } - - trackError(t.index.Sync()) - trackError(t.meta.Sync()) - trackError(t.head.Sync()) - return err -} - -func (t *freezerTable) dumpIndexStdout(start, stop int64) { - t.dumpIndex(os.Stdout, start, stop) -} - -func (t *freezerTable) dumpIndexString(start, stop int64) string { - var out bytes.Buffer - out.WriteString("\n") - t.dumpIndex(&out, start, stop) - return out.String() -} - -func (t *freezerTable) dumpIndex(w io.Writer, start, stop int64) { - meta, err := readMetadata(t.meta) - if err != nil { - fmt.Fprintf(w, "Failed to decode freezer table %v\n", err) - return - } - fmt.Fprintf(w, "Version %d count %d, deleted %d, hidden %d\n", meta.Version, - t.items.Load(), t.itemOffset.Load(), t.itemHidden.Load()) - - buf := make([]byte, indexEntrySize) - - fmt.Fprintf(w, "| number | fileno | offset |\n") - fmt.Fprintf(w, "|--------|--------|--------|\n") - - for i := uint64(start); ; i++ { - if _, err := t.index.ReadAt(buf, int64((i+1)*indexEntrySize)); err != nil { - break - } - var entry indexEntry - entry.unmarshalBinary(buf) - fmt.Fprintf(w, "| %03d | %03d | %03d | \n", i, entry.filenum, entry.offset) - if stop > 0 && i >= uint64(stop) { - break - } - } - fmt.Fprintf(w, "|--------------------------|\n") -} diff --git a/builder/core/rawdb/freezer_table_test.go b/builder/core/rawdb/freezer_table_test.go deleted file mode 100644 index 91b4943e5..000000000 --- a/builder/core/rawdb/freezer_table_test.go +++ /dev/null @@ -1,1369 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "encoding/binary" - "fmt" - "math/rand" - "os" - "path/filepath" - "reflect" - "testing" - "testing/quick" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/metrics" - "github.com/stretchr/testify/require" -) - -// TestFreezerBasics test initializing a freezertable from scratch, writing to the table, -// and reading it back. -func TestFreezerBasics(t *testing.T) { - t.Parallel() - // set cutoff at 50 bytes - f, err := newTable(os.TempDir(), - fmt.Sprintf("unittest-%d", rand.Uint64()), - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - - // Write 15 bytes 255 times, results in 85 files - writeChunks(t, f, 255, 15) - - //print(t, f, 0) - //print(t, f, 1) - //print(t, f, 2) - // - //db[0] = 000000000000000000000000000000 - //db[1] = 010101010101010101010101010101 - //db[2] = 020202020202020202020202020202 - - for y := 0; y < 255; y++ { - exp := getChunk(15, y) - got, err := f.Retrieve(uint64(y)) - if err != nil { - t.Fatalf("reading item %d: %v", y, err) - } - if !bytes.Equal(got, exp) { - t.Fatalf("test %d, got \n%x != \n%x", y, got, exp) - } - } - // Check that we cannot read too far - _, err = f.Retrieve(uint64(255)) - if err != errOutOfBounds { - t.Fatal(err) - } -} - -// TestFreezerBasicsClosing tests same as TestFreezerBasics, but also closes and reopens the freezer between -// every operation -func TestFreezerBasicsClosing(t *testing.T) { - t.Parallel() - // set cutoff at 50 bytes - var ( - fname = fmt.Sprintf("basics-close-%d", rand.Uint64()) - rm, wm, sg = metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - f *freezerTable - err error - ) - f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - - // Write 15 bytes 255 times, results in 85 files. - // In-between writes, the table is closed and re-opened. - for x := 0; x < 255; x++ { - data := getChunk(15, x) - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(uint64(x), data)) - require.NoError(t, batch.commit()) - f.Close() - - f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - } - defer f.Close() - - for y := 0; y < 255; y++ { - exp := getChunk(15, y) - got, err := f.Retrieve(uint64(y)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(got, exp) { - t.Fatalf("test %d, got \n%x != \n%x", y, got, exp) - } - f.Close() - f, err = newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - } -} - -// TestFreezerRepairDanglingHead tests that we can recover if index entries are removed -func TestFreezerRepairDanglingHead(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("dangling_headtest-%d", rand.Uint64()) - - // Fill table - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 255 times - writeChunks(t, f, 255, 15) - - // The last item should be there - if _, err = f.Retrieve(0xfe); err != nil { - t.Fatal(err) - } - f.Close() - } - - // open the index - idxFile, err := os.OpenFile(filepath.Join(os.TempDir(), fmt.Sprintf("%s.ridx", fname)), os.O_RDWR, 0644) - if err != nil { - t.Fatalf("Failed to open index file: %v", err) - } - // Remove 4 bytes - stat, err := idxFile.Stat() - if err != nil { - t.Fatalf("Failed to stat index file: %v", err) - } - idxFile.Truncate(stat.Size() - 4) - idxFile.Close() - - // Now open it again - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // The last item should be missing - if _, err = f.Retrieve(0xff); err == nil { - t.Errorf("Expected error for missing index entry") - } - // The one before should still be there - if _, err = f.Retrieve(0xfd); err != nil { - t.Fatalf("Expected no error, got %v", err) - } - } -} - -// TestFreezerRepairDanglingHeadLarge tests that we can recover if very many index entries are removed -func TestFreezerRepairDanglingHeadLarge(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("dangling_headtest-%d", rand.Uint64()) - - // Fill a table and close it - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 255 times - writeChunks(t, f, 255, 15) - - // The last item should be there - if _, err = f.Retrieve(f.items.Load() - 1); err != nil { - t.Fatal(err) - } - f.Close() - } - - // open the index - idxFile, err := os.OpenFile(filepath.Join(os.TempDir(), fmt.Sprintf("%s.ridx", fname)), os.O_RDWR, 0644) - if err != nil { - t.Fatalf("Failed to open index file: %v", err) - } - // Remove everything but the first item, and leave data unaligned - // 0-indexEntry, 1-indexEntry, corrupt-indexEntry - idxFile.Truncate(2*indexEntrySize + indexEntrySize/2) - idxFile.Close() - - // Now open it again - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // The first item should be there - if _, err = f.Retrieve(0); err != nil { - t.Fatal(err) - } - // The second item should be missing - if _, err = f.Retrieve(1); err == nil { - t.Errorf("Expected error for missing index entry") - } - // We should now be able to store items again, from item = 1 - batch := f.newBatch() - for x := 1; x < 0xff; x++ { - require.NoError(t, batch.AppendRaw(uint64(x), getChunk(15, ^x))) - } - require.NoError(t, batch.commit()) - f.Close() - } - - // And if we open it, we should now be able to read all of them (new values) - { - f, _ := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - for y := 1; y < 255; y++ { - exp := getChunk(15, ^y) - got, err := f.Retrieve(uint64(y)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(got, exp) { - t.Fatalf("test %d, got \n%x != \n%x", y, got, exp) - } - } - } -} - -// TestSnappyDetection tests that we fail to open a snappy database and vice versa -func TestSnappyDetection(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("snappytest-%d", rand.Uint64()) - - // Open with snappy - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 255 times - writeChunks(t, f, 255, 15) - f.Close() - } - - // Open without snappy - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, false, false) - if err != nil { - t.Fatal(err) - } - if _, err = f.Retrieve(0); err == nil { - f.Close() - t.Fatalf("expected empty table") - } - } - - // Open with snappy - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // There should be 255 items - if _, err = f.Retrieve(0xfe); err != nil { - f.Close() - t.Fatalf("expected no error, got %v", err) - } - } -} - -func assertFileSize(f string, size int64) error { - stat, err := os.Stat(f) - if err != nil { - return err - } - if stat.Size() != size { - return fmt.Errorf("error, expected size %d, got %d", size, stat.Size()) - } - return nil -} - -// TestFreezerRepairDanglingIndex checks that if the index has more entries than there are data, -// the index is repaired -func TestFreezerRepairDanglingIndex(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("dangling_indextest-%d", rand.Uint64()) - - // Fill a table and close it - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 9 times : 150 bytes - writeChunks(t, f, 9, 15) - - // The last item should be there - if _, err = f.Retrieve(f.items.Load() - 1); err != nil { - f.Close() - t.Fatal(err) - } - f.Close() - // File sizes should be 45, 45, 45 : items[3, 3, 3) - } - - // Crop third file - fileToCrop := filepath.Join(os.TempDir(), fmt.Sprintf("%s.0002.rdat", fname)) - // Truncate third file: 45 ,45, 20 - { - if err := assertFileSize(fileToCrop, 45); err != nil { - t.Fatal(err) - } - file, err := os.OpenFile(fileToCrop, os.O_RDWR, 0644) - if err != nil { - t.Fatal(err) - } - file.Truncate(20) - file.Close() - } - - // Open db it again - // It should restore the file(s) to - // 45, 45, 15 - // with 3+3+1 items - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - if f.items.Load() != 7 { - t.Fatalf("expected %d items, got %d", 7, f.items.Load()) - } - if err := assertFileSize(fileToCrop, 15); err != nil { - t.Fatal(err) - } - } -} - -func TestFreezerTruncate(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("truncation-%d", rand.Uint64()) - - // Fill table - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 30 times - writeChunks(t, f, 30, 15) - - // The last item should be there - if _, err = f.Retrieve(f.items.Load() - 1); err != nil { - t.Fatal(err) - } - f.Close() - } - - // Reopen, truncate - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - f.truncateHead(10) // 150 bytes - if f.items.Load() != 10 { - t.Fatalf("expected %d items, got %d", 10, f.items.Load()) - } - // 45, 45, 45, 15 -- bytes should be 15 - if f.headBytes != 15 { - t.Fatalf("expected %d bytes, got %d", 15, f.headBytes) - } - } -} - -// TestFreezerRepairFirstFile tests a head file with the very first item only half-written. -// That will rewind the index, and _should_ truncate the head file -func TestFreezerRepairFirstFile(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("truncationfirst-%d", rand.Uint64()) - - // Fill table - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 80 bytes, splitting out into two files - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(0, getChunk(40, 0xFF))) - require.NoError(t, batch.AppendRaw(1, getChunk(40, 0xEE))) - require.NoError(t, batch.commit()) - - // The last item should be there - if _, err = f.Retrieve(1); err != nil { - t.Fatal(err) - } - f.Close() - } - - // Truncate the file in half - fileToCrop := filepath.Join(os.TempDir(), fmt.Sprintf("%s.0001.rdat", fname)) - { - if err := assertFileSize(fileToCrop, 40); err != nil { - t.Fatal(err) - } - file, err := os.OpenFile(fileToCrop, os.O_RDWR, 0644) - if err != nil { - t.Fatal(err) - } - file.Truncate(20) - file.Close() - } - - // Reopen - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - if f.items.Load() != 1 { - f.Close() - t.Fatalf("expected %d items, got %d", 0, f.items.Load()) - } - - // Write 40 bytes - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(1, getChunk(40, 0xDD))) - require.NoError(t, batch.commit()) - - f.Close() - - // Should have been truncated down to zero and then 40 written - if err := assertFileSize(fileToCrop, 40); err != nil { - t.Fatal(err) - } - } -} - -// TestFreezerReadAndTruncate tests: -// - we have a table open -// - do some reads, so files are open in readonly -// - truncate so those files are 'removed' -// - check that we did not keep the rdonly file descriptors -func TestFreezerReadAndTruncate(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("read_truncate-%d", rand.Uint64()) - - // Fill table - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 30 times - writeChunks(t, f, 30, 15) - - // The last item should be there - if _, err = f.Retrieve(f.items.Load() - 1); err != nil { - t.Fatal(err) - } - f.Close() - } - - // Reopen and read all files - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - if f.items.Load() != 30 { - f.Close() - t.Fatalf("expected %d items, got %d", 0, f.items.Load()) - } - for y := byte(0); y < 30; y++ { - f.Retrieve(uint64(y)) - } - - // Now, truncate back to zero - f.truncateHead(0) - - // Write the data again - batch := f.newBatch() - for x := 0; x < 30; x++ { - require.NoError(t, batch.AppendRaw(uint64(x), getChunk(15, ^x))) - } - require.NoError(t, batch.commit()) - f.Close() - } -} - -func TestFreezerOffset(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("offset-%d", rand.Uint64()) - - // Fill table - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - - // Write 6 x 20 bytes, splitting out into three files - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(0, getChunk(20, 0xFF))) - require.NoError(t, batch.AppendRaw(1, getChunk(20, 0xEE))) - - require.NoError(t, batch.AppendRaw(2, getChunk(20, 0xdd))) - require.NoError(t, batch.AppendRaw(3, getChunk(20, 0xcc))) - - require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xbb))) - require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xaa))) - require.NoError(t, batch.commit()) - - t.Log(f.dumpIndexString(0, 100)) - f.Close() - } - - // Now crop it. - { - // delete files 0 and 1 - for i := 0; i < 2; i++ { - p := filepath.Join(os.TempDir(), fmt.Sprintf("%v.%04d.rdat", fname, i)) - if err := os.Remove(p); err != nil { - t.Fatal(err) - } - } - // Read the index file - p := filepath.Join(os.TempDir(), fmt.Sprintf("%v.ridx", fname)) - indexFile, err := os.OpenFile(p, os.O_RDWR, 0644) - if err != nil { - t.Fatal(err) - } - indexBuf := make([]byte, 7*indexEntrySize) - indexFile.Read(indexBuf) - - // Update the index file, so that we store - // [ file = 2, offset = 4 ] at index zero - - zeroIndex := indexEntry{ - filenum: uint32(2), // First file is 2 - offset: uint32(4), // We have removed four items - } - buf := zeroIndex.append(nil) - - // Overwrite index zero - copy(indexBuf, buf) - - // Remove the four next indices by overwriting - copy(indexBuf[indexEntrySize:], indexBuf[indexEntrySize*5:]) - indexFile.WriteAt(indexBuf, 0) - - // Need to truncate the moved index items - indexFile.Truncate(indexEntrySize * (1 + 2)) - indexFile.Close() - } - - // Now open again - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - t.Log(f.dumpIndexString(0, 100)) - - // It should allow writing item 6. - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(6, getChunk(20, 0x99))) - require.NoError(t, batch.commit()) - - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - 2: errOutOfBounds, - 3: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x99), - }) - } - - // Edit the index again, with a much larger initial offset of 1M. - { - // Read the index file - p := filepath.Join(os.TempDir(), fmt.Sprintf("%v.ridx", fname)) - indexFile, err := os.OpenFile(p, os.O_RDWR, 0644) - if err != nil { - t.Fatal(err) - } - indexBuf := make([]byte, 3*indexEntrySize) - indexFile.Read(indexBuf) - - // Update the index file, so that we store - // [ file = 2, offset = 1M ] at index zero - - zeroIndex := indexEntry{ - offset: uint32(1000000), // We have removed 1M items - filenum: uint32(2), // First file is 2 - } - buf := zeroIndex.append(nil) - - // Overwrite index zero - copy(indexBuf, buf) - indexFile.WriteAt(indexBuf, 0) - indexFile.Close() - } - - // Check that existing items have been moved to index 1M. - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - t.Log(f.dumpIndexString(0, 100)) - - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - 2: errOutOfBounds, - 3: errOutOfBounds, - 999999: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 1000000: getChunk(20, 0xbb), - 1000001: getChunk(20, 0xaa), - }) - } -} - -func assertTableSize(t *testing.T, f *freezerTable, size int) { - t.Helper() - if got, err := f.size(); got != uint64(size) { - t.Fatalf("expected size of %d bytes, got %d, err: %v", size, got, err) - } -} - -func TestTruncateTail(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("truncate-tail-%d", rand.Uint64()) - - // Fill table - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - - // Write 7 x 20 bytes, splitting out into four files - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(0, getChunk(20, 0xFF))) - require.NoError(t, batch.AppendRaw(1, getChunk(20, 0xEE))) - require.NoError(t, batch.AppendRaw(2, getChunk(20, 0xdd))) - require.NoError(t, batch.AppendRaw(3, getChunk(20, 0xcc))) - require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xbb))) - require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xaa))) - require.NoError(t, batch.AppendRaw(6, getChunk(20, 0x11))) - require.NoError(t, batch.commit()) - - // nothing to do, all the items should still be there. - f.truncateTail(0) - fmt.Println(f.dumpIndexString(0, 1000)) - checkRetrieve(t, f, map[uint64][]byte{ - 0: getChunk(20, 0xFF), - 1: getChunk(20, 0xEE), - 2: getChunk(20, 0xdd), - 3: getChunk(20, 0xcc), - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - // maxFileSize*fileCount + headBytes + indexFileSize - hiddenBytes - expected := 20*7 + 48 - 0 - assertTableSize(t, f, expected) - - // truncate single element( item 0 ), deletion is only supported at file level - f.truncateTail(1) - fmt.Println(f.dumpIndexString(0, 1000)) - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 1: getChunk(20, 0xEE), - 2: getChunk(20, 0xdd), - 3: getChunk(20, 0xcc), - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - expected = 20*7 + 48 - 20 - assertTableSize(t, f, expected) - - // Reopen the table, the deletion information should be persisted as well - f.Close() - f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 1: getChunk(20, 0xEE), - 2: getChunk(20, 0xdd), - 3: getChunk(20, 0xcc), - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - - // truncate two elements( item 0, item 1 ), the file 0 should be deleted - f.truncateTail(2) - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 2: getChunk(20, 0xdd), - 3: getChunk(20, 0xcc), - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - expected = 20*5 + 36 - 0 - assertTableSize(t, f, expected) - - // Reopen the table, the above testing should still pass - f.Close() - f, err = newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - defer f.Close() - - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 2: getChunk(20, 0xdd), - 3: getChunk(20, 0xcc), - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - - // truncate 3 more elements( item 2, 3, 4), the file 1 should be deleted - // file 2 should only contain item 5 - f.truncateTail(5) - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - 2: errOutOfBounds, - 3: errOutOfBounds, - 4: errOutOfBounds, - }) - checkRetrieve(t, f, map[uint64][]byte{ - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) - expected = 20*3 + 24 - 20 - assertTableSize(t, f, expected) - - // truncate all, the entire freezer should be deleted - f.truncateTail(7) - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, - 1: errOutOfBounds, - 2: errOutOfBounds, - 3: errOutOfBounds, - 4: errOutOfBounds, - 5: errOutOfBounds, - 6: errOutOfBounds, - }) - expected = 12 - assertTableSize(t, f, expected) -} - -func TestTruncateHead(t *testing.T) { - t.Parallel() - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("truncate-head-blow-tail-%d", rand.Uint64()) - - // Fill table - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - - // Write 7 x 20 bytes, splitting out into four files - batch := f.newBatch() - require.NoError(t, batch.AppendRaw(0, getChunk(20, 0xFF))) - require.NoError(t, batch.AppendRaw(1, getChunk(20, 0xEE))) - require.NoError(t, batch.AppendRaw(2, getChunk(20, 0xdd))) - require.NoError(t, batch.AppendRaw(3, getChunk(20, 0xcc))) - require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xbb))) - require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xaa))) - require.NoError(t, batch.AppendRaw(6, getChunk(20, 0x11))) - require.NoError(t, batch.commit()) - - f.truncateTail(4) // Tail = 4 - - // NewHead is required to be 3, the entire table should be truncated - f.truncateHead(4) - checkRetrieveError(t, f, map[uint64]error{ - 0: errOutOfBounds, // Deleted by tail - 1: errOutOfBounds, // Deleted by tail - 2: errOutOfBounds, // Deleted by tail - 3: errOutOfBounds, // Deleted by tail - 4: errOutOfBounds, // Deleted by Head - 5: errOutOfBounds, // Deleted by Head - 6: errOutOfBounds, // Deleted by Head - }) - - // Append new items - batch = f.newBatch() - require.NoError(t, batch.AppendRaw(4, getChunk(20, 0xbb))) - require.NoError(t, batch.AppendRaw(5, getChunk(20, 0xaa))) - require.NoError(t, batch.AppendRaw(6, getChunk(20, 0x11))) - require.NoError(t, batch.commit()) - - checkRetrieve(t, f, map[uint64][]byte{ - 4: getChunk(20, 0xbb), - 5: getChunk(20, 0xaa), - 6: getChunk(20, 0x11), - }) -} - -func checkRetrieve(t *testing.T, f *freezerTable, items map[uint64][]byte) { - t.Helper() - - for item, wantBytes := range items { - value, err := f.Retrieve(item) - if err != nil { - t.Fatalf("can't get expected item %d: %v", item, err) - } - if !bytes.Equal(value, wantBytes) { - t.Fatalf("item %d has wrong value %x (want %x)", item, value, wantBytes) - } - } -} - -func checkRetrieveError(t *testing.T, f *freezerTable, items map[uint64]error) { - t.Helper() - - for item, wantError := range items { - value, err := f.Retrieve(item) - if err == nil { - t.Fatalf("unexpected value %x for item %d, want error %v", item, value, wantError) - } - if err != wantError { - t.Fatalf("wrong error for item %d: %v", item, err) - } - } -} - -// Gets a chunk of data, filled with 'b' -func getChunk(size int, b int) []byte { - data := make([]byte, size) - for i := range data { - data[i] = byte(b) - } - return data -} - -// TODO (?) -// - test that if we remove several head-files, as well as data last data-file, -// the index is truncated accordingly -// Right now, the freezer would fail on these conditions: -// 1. have data files d0, d1, d2, d3 -// 2. remove d2,d3 -// -// However, all 'normal' failure modes arising due to failing to sync() or save a file -// should be handled already, and the case described above can only (?) happen if an -// external process/user deletes files from the filesystem. - -func writeChunks(t *testing.T, ft *freezerTable, n int, length int) { - t.Helper() - - batch := ft.newBatch() - for i := 0; i < n; i++ { - if err := batch.AppendRaw(uint64(i), getChunk(length, i)); err != nil { - t.Fatalf("AppendRaw(%d, ...) returned error: %v", i, err) - } - } - if err := batch.commit(); err != nil { - t.Fatalf("Commit returned error: %v", err) - } -} - -// TestSequentialRead does some basic tests on the RetrieveItems. -func TestSequentialRead(t *testing.T) { - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("batchread-%d", rand.Uint64()) - { // Fill table - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - // Write 15 bytes 30 times - writeChunks(t, f, 30, 15) - f.dumpIndexStdout(0, 30) - f.Close() - } - { // Open it, iterate, verify iteration - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 50, true, false) - if err != nil { - t.Fatal(err) - } - items, err := f.RetrieveItems(0, 10000, 100000) - if err != nil { - t.Fatal(err) - } - if have, want := len(items), 30; have != want { - t.Fatalf("want %d items, have %d ", want, have) - } - for i, have := range items { - want := getChunk(15, i) - if !bytes.Equal(want, have) { - t.Fatalf("data corruption: have\n%x\n, want \n%x\n", have, want) - } - } - f.Close() - } - { // Open it, iterate, verify byte limit. The byte limit is less than item - // size, so each lookup should only return one item - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 40, true, false) - if err != nil { - t.Fatal(err) - } - items, err := f.RetrieveItems(0, 10000, 10) - if err != nil { - t.Fatal(err) - } - if have, want := len(items), 1; have != want { - t.Fatalf("want %d items, have %d ", want, have) - } - for i, have := range items { - want := getChunk(15, i) - if !bytes.Equal(want, have) { - t.Fatalf("data corruption: have\n%x\n, want \n%x\n", have, want) - } - } - f.Close() - } -} - -// TestSequentialReadByteLimit does some more advanced tests on batch reads. -// These tests check that when the byte limit hits, we correctly abort in time, -// but also properly do all the deferred reads for the previous data, regardless -// of whether the data crosses a file boundary or not. -func TestSequentialReadByteLimit(t *testing.T) { - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("batchread-2-%d", rand.Uint64()) - { // Fill table - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false) - if err != nil { - t.Fatal(err) - } - // Write 10 bytes 30 times, - // Splitting it at every 100 bytes (10 items) - writeChunks(t, f, 30, 10) - f.Close() - } - for i, tc := range []struct { - items uint64 - limit uint64 - want int - }{ - {9, 89, 8}, - {10, 99, 9}, - {11, 109, 10}, - {100, 89, 8}, - {100, 99, 9}, - {100, 109, 10}, - } { - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false) - if err != nil { - t.Fatal(err) - } - items, err := f.RetrieveItems(0, tc.items, tc.limit) - if err != nil { - t.Fatal(err) - } - if have, want := len(items), tc.want; have != want { - t.Fatalf("test %d: want %d items, have %d ", i, want, have) - } - for ii, have := range items { - want := getChunk(10, ii) - if !bytes.Equal(want, have) { - t.Fatalf("test %d: data corruption item %d: have\n%x\n, want \n%x\n", i, ii, have, want) - } - } - f.Close() - } - } -} - -// TestSequentialReadNoByteLimit tests the batch-read if maxBytes is not specified. -// Freezer should return the requested items regardless the size limitation. -func TestSequentialReadNoByteLimit(t *testing.T) { - rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge() - fname := fmt.Sprintf("batchread-3-%d", rand.Uint64()) - { // Fill table - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false) - if err != nil { - t.Fatal(err) - } - // Write 10 bytes 30 times, - // Splitting it at every 100 bytes (10 items) - writeChunks(t, f, 30, 10) - f.Close() - } - for i, tc := range []struct { - items uint64 - want int - }{ - {1, 1}, - {30, 30}, - {31, 30}, - } { - { - f, err := newTable(os.TempDir(), fname, rm, wm, sg, 100, true, false) - if err != nil { - t.Fatal(err) - } - items, err := f.RetrieveItems(0, tc.items, 0) - if err != nil { - t.Fatal(err) - } - if have, want := len(items), tc.want; have != want { - t.Fatalf("test %d: want %d items, have %d ", i, want, have) - } - for ii, have := range items { - want := getChunk(10, ii) - if !bytes.Equal(want, have) { - t.Fatalf("test %d: data corruption item %d: have\n%x\n, want \n%x\n", i, ii, have, want) - } - } - f.Close() - } - } -} - -func TestFreezerReadonly(t *testing.T) { - tmpdir := os.TempDir() - // Case 1: Check it fails on non-existent file. - _, err := newTable(tmpdir, - fmt.Sprintf("readonlytest-%d", rand.Uint64()), - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true) - if err == nil { - t.Fatal("readonly table instantiation should fail for non-existent table") - } - - // Case 2: Check that it fails on invalid index length. - fname := fmt.Sprintf("readonlytest-%d", rand.Uint64()) - idxFile, err := openFreezerFileForAppend(filepath.Join(tmpdir, fmt.Sprintf("%s.ridx", fname))) - if err != nil { - t.Errorf("Failed to open index file: %v\n", err) - } - // size should not be a multiple of indexEntrySize. - idxFile.Write(make([]byte, 17)) - idxFile.Close() - _, err = newTable(tmpdir, fname, - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true) - if err == nil { - t.Errorf("readonly table instantiation should fail for invalid index size") - } - - // Case 3: Open table non-readonly table to write some data. - // Then corrupt the head file and make sure opening the table - // again in readonly triggers an error. - fname = fmt.Sprintf("readonlytest-%d", rand.Uint64()) - f, err := newTable(tmpdir, fname, - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false) - if err != nil { - t.Fatalf("failed to instantiate table: %v", err) - } - writeChunks(t, f, 8, 32) - // Corrupt table file - if _, err := f.head.Write([]byte{1, 1}); err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } - _, err = newTable(tmpdir, fname, - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true) - if err == nil { - t.Errorf("readonly table instantiation should fail for corrupt table file") - } - - // Case 4: Write some data to a table and later re-open it as readonly. - // Should be successful. - fname = fmt.Sprintf("readonlytest-%d", rand.Uint64()) - f, err = newTable(tmpdir, fname, - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false) - if err != nil { - t.Fatalf("failed to instantiate table: %v\n", err) - } - writeChunks(t, f, 32, 128) - if err := f.Close(); err != nil { - t.Fatal(err) - } - f, err = newTable(tmpdir, fname, - metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, true) - if err != nil { - t.Fatal(err) - } - v, err := f.Retrieve(10) - if err != nil { - t.Fatal(err) - } - exp := getChunk(128, 10) - if !bytes.Equal(v, exp) { - t.Errorf("retrieved value is incorrect") - } - - // Case 5: Now write some data via a batch. - // This should fail either during AppendRaw or Commit - batch := f.newBatch() - writeErr := batch.AppendRaw(32, make([]byte, 1)) - if writeErr == nil { - writeErr = batch.commit() - } - if writeErr == nil { - t.Fatalf("Writing to readonly table should fail") - } -} - -// randTest performs random freezer table operations. -// Instances of this test are created by Generate. -type randTest []randTestStep - -type randTestStep struct { - op int - items []uint64 // for append and retrieve - blobs [][]byte // for append - target uint64 // for truncate(head/tail) - err error // for debugging -} - -const ( - opReload = iota - opAppend - opRetrieve - opTruncateHead - opTruncateHeadAll - opTruncateTail - opTruncateTailAll - opCheckAll - opMax // boundary value, not an actual op -) - -func getVals(first uint64, n int) [][]byte { - var ret [][]byte - for i := 0; i < n; i++ { - val := make([]byte, 8) - binary.BigEndian.PutUint64(val, first+uint64(i)) - ret = append(ret, val) - } - return ret -} - -func (randTest) Generate(r *rand.Rand, size int) reflect.Value { - var ( - deleted uint64 // The number of deleted items from tail - items []uint64 // The index of entries in table - - // getItems retrieves the indexes for items in table. - getItems = func(n int) []uint64 { - length := len(items) - if length == 0 { - return nil - } - var ret []uint64 - index := rand.Intn(length) - for i := index; len(ret) < n && i < length; i++ { - ret = append(ret, items[i]) - } - return ret - } - - // addItems appends the given length items into the table. - addItems = func(n int) []uint64 { - var first = deleted - if len(items) != 0 { - first = items[len(items)-1] + 1 - } - var ret []uint64 - for i := 0; i < n; i++ { - ret = append(ret, first+uint64(i)) - } - items = append(items, ret...) - return ret - } - ) - - var steps randTest - for i := 0; i < size; i++ { - step := randTestStep{op: r.Intn(opMax)} - switch step.op { - case opReload, opCheckAll: - case opAppend: - num := r.Intn(3) - step.items = addItems(num) - if len(step.items) == 0 { - step.blobs = nil - } else { - step.blobs = getVals(step.items[0], num) - } - case opRetrieve: - step.items = getItems(r.Intn(3)) - case opTruncateHead: - if len(items) == 0 { - step.target = deleted - } else { - index := r.Intn(len(items)) - items = items[:index] - step.target = deleted + uint64(index) - } - case opTruncateHeadAll: - step.target = deleted - items = items[:0] - case opTruncateTail: - if len(items) == 0 { - step.target = deleted - } else { - index := r.Intn(len(items)) - items = items[index:] - deleted += uint64(index) - step.target = deleted - } - case opTruncateTailAll: - step.target = deleted + uint64(len(items)) - items = items[:0] - deleted = step.target - } - steps = append(steps, step) - } - return reflect.ValueOf(steps) -} - -func runRandTest(rt randTest) bool { - fname := fmt.Sprintf("randtest-%d", rand.Uint64()) - f, err := newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false) - if err != nil { - panic("failed to initialize table") - } - var values [][]byte - for i, step := range rt { - switch step.op { - case opReload: - f.Close() - f, err = newTable(os.TempDir(), fname, metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge(), 50, true, false) - if err != nil { - rt[i].err = fmt.Errorf("failed to reload table %v", err) - } - case opCheckAll: - tail := f.itemHidden.Load() - head := f.items.Load() - - if tail == head { - continue - } - got, err := f.RetrieveItems(f.itemHidden.Load(), head-tail, 100000) - if err != nil { - rt[i].err = err - } else { - if !reflect.DeepEqual(got, values) { - rt[i].err = fmt.Errorf("mismatch on retrieved values %v %v", got, values) - } - } - - case opAppend: - batch := f.newBatch() - for i := 0; i < len(step.items); i++ { - batch.AppendRaw(step.items[i], step.blobs[i]) - } - batch.commit() - values = append(values, step.blobs...) - - case opRetrieve: - var blobs [][]byte - if len(step.items) == 0 { - continue - } - tail := f.itemHidden.Load() - for i := 0; i < len(step.items); i++ { - blobs = append(blobs, values[step.items[i]-tail]) - } - got, err := f.RetrieveItems(step.items[0], uint64(len(step.items)), 100000) - if err != nil { - rt[i].err = err - } else { - if !reflect.DeepEqual(got, blobs) { - rt[i].err = fmt.Errorf("mismatch on retrieved values %v %v %v", got, blobs, step.items) - } - } - - case opTruncateHead: - f.truncateHead(step.target) - - length := f.items.Load() - f.itemHidden.Load() - values = values[:length] - - case opTruncateHeadAll: - f.truncateHead(step.target) - values = nil - - case opTruncateTail: - prev := f.itemHidden.Load() - f.truncateTail(step.target) - - truncated := f.itemHidden.Load() - prev - values = values[truncated:] - - case opTruncateTailAll: - f.truncateTail(step.target) - values = nil - } - // Abort the test on error. - if rt[i].err != nil { - return false - } - } - f.Close() - return true -} - -func TestRandom(t *testing.T) { - if err := quick.Check(runRandTest, nil); err != nil { - if cerr, ok := err.(*quick.CheckError); ok { - t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In)) - } - t.Fatal(err) - } -} diff --git a/builder/core/rawdb/freezer_test.go b/builder/core/rawdb/freezer_test.go deleted file mode 100644 index b4bd6a382..000000000 --- a/builder/core/rawdb/freezer_test.go +++ /dev/null @@ -1,482 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "math/rand" - "os" - "path" - "sync" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" - "github.com/stretchr/testify/require" -) - -var freezerTestTableDef = map[string]bool{"test": true} - -func TestFreezerModify(t *testing.T) { - t.Parallel() - - // Create test data. - var valuesRaw [][]byte - var valuesRLP []*big.Int - for x := 0; x < 100; x++ { - v := getChunk(256, x) - valuesRaw = append(valuesRaw, v) - iv := big.NewInt(int64(x)) - iv = iv.Exp(iv, iv, nil) - valuesRLP = append(valuesRLP, iv) - } - - tables := map[string]bool{"raw": true, "rlp": false} - f, _ := newFreezerForTesting(t, tables) - defer f.Close() - - // Commit test data. - _, err := f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for i := range valuesRaw { - if err := op.AppendRaw("raw", uint64(i), valuesRaw[i]); err != nil { - return err - } - if err := op.Append("rlp", uint64(i), valuesRLP[i]); err != nil { - return err - } - } - return nil - }) - if err != nil { - t.Fatal("ModifyAncients failed:", err) - } - - // Dump indexes. - for _, table := range f.tables { - t.Log(table.name, "index:", table.dumpIndexString(0, int64(len(valuesRaw)))) - } - - // Read back test data. - checkAncientCount(t, f, "raw", uint64(len(valuesRaw))) - checkAncientCount(t, f, "rlp", uint64(len(valuesRLP))) - for i := range valuesRaw { - v, _ := f.Ancient("raw", uint64(i)) - if !bytes.Equal(v, valuesRaw[i]) { - t.Fatalf("wrong raw value at %d: %x", i, v) - } - ivEnc, _ := f.Ancient("rlp", uint64(i)) - want, _ := rlp.EncodeToBytes(valuesRLP[i]) - if !bytes.Equal(ivEnc, want) { - t.Fatalf("wrong RLP value at %d: %x", i, ivEnc) - } - } -} - -// This checks that ModifyAncients rolls back freezer updates -// when the function passed to it returns an error. -func TestFreezerModifyRollback(t *testing.T) { - t.Parallel() - - f, dir := newFreezerForTesting(t, freezerTestTableDef) - - theError := errors.New("oops") - _, err := f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - // Append three items. This creates two files immediately, - // because the table size limit of the test freezer is 2048. - require.NoError(t, op.AppendRaw("test", 0, make([]byte, 2048))) - require.NoError(t, op.AppendRaw("test", 1, make([]byte, 2048))) - require.NoError(t, op.AppendRaw("test", 2, make([]byte, 2048))) - return theError - }) - if err != theError { - t.Errorf("ModifyAncients returned wrong error %q", err) - } - checkAncientCount(t, f, "test", 0) - f.Close() - - // Reopen and check that the rolled-back data doesn't reappear. - tables := map[string]bool{"test": true} - f2, err := NewFreezer(dir, "", false, 2049, tables) - if err != nil { - t.Fatalf("can't reopen freezer after failed ModifyAncients: %v", err) - } - defer f2.Close() - checkAncientCount(t, f2, "test", 0) -} - -// This test runs ModifyAncients and Ancient concurrently with each other. -func TestFreezerConcurrentModifyRetrieve(t *testing.T) { - t.Parallel() - - f, _ := newFreezerForTesting(t, freezerTestTableDef) - defer f.Close() - - var ( - numReaders = 5 - writeBatchSize = uint64(50) - written = make(chan uint64, numReaders*6) - wg sync.WaitGroup - ) - wg.Add(numReaders + 1) - - // Launch the writer. It appends 10000 items in batches. - go func() { - defer wg.Done() - defer close(written) - for item := uint64(0); item < 10000; item += writeBatchSize { - _, err := f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for i := uint64(0); i < writeBatchSize; i++ { - item := item + i - value := getChunk(32, int(item)) - if err := op.AppendRaw("test", item, value); err != nil { - return err - } - } - return nil - }) - if err != nil { - panic(err) - } - for i := 0; i < numReaders; i++ { - written <- item + writeBatchSize - } - } - }() - - // Launch the readers. They read random items from the freezer up to the - // current frozen item count. - for i := 0; i < numReaders; i++ { - go func() { - defer wg.Done() - for frozen := range written { - for rc := 0; rc < 80; rc++ { - num := uint64(rand.Intn(int(frozen))) - value, err := f.Ancient("test", num) - if err != nil { - panic(fmt.Errorf("error reading %d (frozen %d): %v", num, frozen, err)) - } - if !bytes.Equal(value, getChunk(32, int(num))) { - panic(fmt.Errorf("wrong value at %d", num)) - } - } - } - }() - } - - wg.Wait() -} - -// This test runs ModifyAncients and TruncateHead concurrently with each other. -func TestFreezerConcurrentModifyTruncate(t *testing.T) { - f, _ := newFreezerForTesting(t, freezerTestTableDef) - defer f.Close() - - var item = make([]byte, 256) - - for i := 0; i < 10; i++ { - // First reset and write 100 items. - if _, err := f.TruncateHead(0); err != nil { - t.Fatal("truncate failed:", err) - } - _, err := f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for i := uint64(0); i < 100; i++ { - if err := op.AppendRaw("test", i, item); err != nil { - return err - } - } - return nil - }) - if err != nil { - t.Fatal("modify failed:", err) - } - checkAncientCount(t, f, "test", 100) - - // Now append 100 more items and truncate concurrently. - var ( - wg sync.WaitGroup - truncateErr error - modifyErr error - ) - wg.Add(3) - go func() { - _, modifyErr = f.ModifyAncients(func(op ethdb.AncientWriteOp) error { - for i := uint64(100); i < 200; i++ { - if err := op.AppendRaw("test", i, item); err != nil { - return err - } - } - return nil - }) - wg.Done() - }() - go func() { - _, truncateErr = f.TruncateHead(10) - wg.Done() - }() - go func() { - f.AncientSize("test") - wg.Done() - }() - wg.Wait() - - // Now check the outcome. If the truncate operation went through first, the append - // fails, otherwise it succeeds. In either case, the freezer should be positioned - // at 10 after both operations are done. - if truncateErr != nil { - t.Fatal("concurrent truncate failed:", err) - } - if !(errors.Is(modifyErr, nil) || errors.Is(modifyErr, errOutOrderInsertion)) { - t.Fatal("wrong error from concurrent modify:", modifyErr) - } - checkAncientCount(t, f, "test", 10) - } -} - -func TestFreezerReadonlyValidate(t *testing.T) { - tables := map[string]bool{"a": true, "b": true} - dir := t.TempDir() - // Open non-readonly freezer and fill individual tables - // with different amount of data. - f, err := NewFreezer(dir, "", false, 2049, tables) - if err != nil { - t.Fatal("can't open freezer", err) - } - var item = make([]byte, 1024) - aBatch := f.tables["a"].newBatch() - require.NoError(t, aBatch.AppendRaw(0, item)) - require.NoError(t, aBatch.AppendRaw(1, item)) - require.NoError(t, aBatch.AppendRaw(2, item)) - require.NoError(t, aBatch.commit()) - bBatch := f.tables["b"].newBatch() - require.NoError(t, bBatch.AppendRaw(0, item)) - require.NoError(t, bBatch.commit()) - if f.tables["a"].items.Load() != 3 { - t.Fatalf("unexpected number of items in table") - } - if f.tables["b"].items.Load() != 1 { - t.Fatalf("unexpected number of items in table") - } - require.NoError(t, f.Close()) - - // Re-openening as readonly should fail when validating - // table lengths. - _, err = NewFreezer(dir, "", true, 2049, tables) - if err == nil { - t.Fatal("readonly freezer should fail with differing table lengths") - } -} - -func TestFreezerConcurrentReadonly(t *testing.T) { - t.Parallel() - - tables := map[string]bool{"a": true} - dir := t.TempDir() - - f, err := NewFreezer(dir, "", false, 2049, tables) - if err != nil { - t.Fatal("can't open freezer", err) - } - var item = make([]byte, 1024) - batch := f.tables["a"].newBatch() - items := uint64(10) - for i := uint64(0); i < items; i++ { - require.NoError(t, batch.AppendRaw(i, item)) - } - require.NoError(t, batch.commit()) - if loaded := f.tables["a"].items.Load(); loaded != items { - t.Fatalf("unexpected number of items in table, want: %d, have: %d", items, loaded) - } - require.NoError(t, f.Close()) - - var ( - wg sync.WaitGroup - fs = make([]*Freezer, 5) - errs = make([]error, 5) - ) - for i := 0; i < 5; i++ { - wg.Add(1) - go func(i int) { - defer wg.Done() - - f, err := NewFreezer(dir, "", true, 2049, tables) - if err == nil { - fs[i] = f - } else { - errs[i] = err - } - }(i) - } - - wg.Wait() - - for i := range fs { - if err := errs[i]; err != nil { - t.Fatal("failed to open freezer", err) - } - require.NoError(t, fs[i].Close()) - } -} - -func newFreezerForTesting(t *testing.T, tables map[string]bool) (*Freezer, string) { - t.Helper() - - dir := t.TempDir() - // note: using low max table size here to ensure the tests actually - // switch between multiple files. - f, err := NewFreezer(dir, "", false, 2049, tables) - if err != nil { - t.Fatal("can't open freezer", err) - } - return f, dir -} - -// checkAncientCount verifies that the freezer contains n items. -func checkAncientCount(t *testing.T, f *Freezer, kind string, n uint64) { - t.Helper() - - if frozen, _ := f.Ancients(); frozen != n { - t.Fatalf("Ancients() returned %d, want %d", frozen, n) - } - - // Check at index n-1. - if n > 0 { - index := n - 1 - if ok, _ := f.HasAncient(kind, index); !ok { - t.Errorf("HasAncient(%q, %d) returned false unexpectedly", kind, index) - } - if _, err := f.Ancient(kind, index); err != nil { - t.Errorf("Ancient(%q, %d) returned unexpected error %q", kind, index, err) - } - } - - // Check at index n. - index := n - if ok, _ := f.HasAncient(kind, index); ok { - t.Errorf("HasAncient(%q, %d) returned true unexpectedly", kind, index) - } - if _, err := f.Ancient(kind, index); err == nil { - t.Errorf("Ancient(%q, %d) didn't return expected error", kind, index) - } else if err != errOutOfBounds { - t.Errorf("Ancient(%q, %d) returned unexpected error %q", kind, index, err) - } -} - -func TestRenameWindows(t *testing.T) { - var ( - fname = "file.bin" - fname2 = "file2.bin" - data = []byte{1, 2, 3, 4} - data2 = []byte{2, 3, 4, 5} - data3 = []byte{3, 5, 6, 7} - dataLen = 4 - ) - - // Create 2 temp dirs - dir1 := t.TempDir() - dir2 := t.TempDir() - - // Create file in dir1 and fill with data - f, err := os.Create(path.Join(dir1, fname)) - if err != nil { - t.Fatal(err) - } - f2, err := os.Create(path.Join(dir1, fname2)) - if err != nil { - t.Fatal(err) - } - f3, err := os.Create(path.Join(dir2, fname2)) - if err != nil { - t.Fatal(err) - } - if _, err := f.Write(data); err != nil { - t.Fatal(err) - } - if _, err := f2.Write(data2); err != nil { - t.Fatal(err) - } - if _, err := f3.Write(data3); err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } - if err := f2.Close(); err != nil { - t.Fatal(err) - } - if err := f3.Close(); err != nil { - t.Fatal(err) - } - if err := os.Rename(f.Name(), path.Join(dir2, fname)); err != nil { - t.Fatal(err) - } - if err := os.Rename(f2.Name(), path.Join(dir2, fname2)); err != nil { - t.Fatal(err) - } - - // Check file contents - f, err = os.Open(path.Join(dir2, fname)) - if err != nil { - t.Fatal(err) - } - defer f.Close() - defer os.Remove(f.Name()) - buf := make([]byte, dataLen) - if _, err := f.Read(buf); err != nil { - t.Fatal(err) - } - if !bytes.Equal(buf, data) { - t.Errorf("unexpected file contents. Got %v\n", buf) - } - - f, err = os.Open(path.Join(dir2, fname2)) - if err != nil { - t.Fatal(err) - } - defer f.Close() - defer os.Remove(f.Name()) - if _, err := f.Read(buf); err != nil { - t.Fatal(err) - } - if !bytes.Equal(buf, data2) { - t.Errorf("unexpected file contents. Got %v\n", buf) - } -} - -func TestFreezerCloseSync(t *testing.T) { - t.Parallel() - f, _ := newFreezerForTesting(t, map[string]bool{"a": true, "b": true}) - defer f.Close() - - // Now, close and sync. This mimics the behaviour if the node is shut down, - // just as the chain freezer is writing. - // 1: thread-1: chain treezer writes, via freezeRange (holds lock) - // 2: thread-2: Close called, waits for write to finish - // 3: thread-1: finishes writing, releases lock - // 4: thread-2: obtains lock, completes Close() - // 5: thread-1: calls f.Sync() - if err := f.Close(); err != nil { - t.Fatal(err) - } - if err := f.Sync(); err == nil { - t.Fatalf("want error, have nil") - } else if have, want := err.Error(), "[closed closed]"; have != want { - t.Fatalf("want %v, have %v", have, want) - } -} diff --git a/builder/core/rawdb/freezer_utils.go b/builder/core/rawdb/freezer_utils.go deleted file mode 100644 index 752e95ba6..000000000 --- a/builder/core/rawdb/freezer_utils.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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 rawdb - -import ( - "io" - "os" - "path/filepath" -) - -// copyFrom copies data from 'srcPath' at offset 'offset' into 'destPath'. -// The 'destPath' is created if it doesn't exist, otherwise it is overwritten. -// Before the copy is executed, there is a callback can be registered to -// manipulate the dest file. -// It is perfectly valid to have destPath == srcPath. -func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) error) error { - // Create a temp file in the same dir where we want it to wind up - f, err := os.CreateTemp(filepath.Dir(destPath), "*") - if err != nil { - return err - } - fname := f.Name() - - // Clean up the leftover file - defer func() { - if f != nil { - f.Close() - } - os.Remove(fname) - }() - // Apply the given function if it's not nil before we copy - // the content from the src. - if before != nil { - if err := before(f); err != nil { - return err - } - } - // Open the source file - src, err := os.Open(srcPath) - if err != nil { - return err - } - if _, err = src.Seek(int64(offset), 0); err != nil { - src.Close() - return err - } - // io.Copy uses 32K buffer internally. - _, err = io.Copy(f, src) - if err != nil { - src.Close() - return err - } - // Rename the temporary file to the specified dest name. - // src may be same as dest, so needs to be closed before - // we do the final move. - src.Close() - - if err := f.Close(); err != nil { - return err - } - f = nil - return os.Rename(fname, destPath) -} - -// openFreezerFileForAppend opens a freezer table file and seeks to the end -func openFreezerFileForAppend(filename string) (*os.File, error) { - // Open the file without the O_APPEND flag - // because it has differing behaviour during Truncate operations - // on different OS's - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644) - if err != nil { - return nil, err - } - // Seek to end for append - if _, err = file.Seek(0, io.SeekEnd); err != nil { - return nil, err - } - return file, nil -} - -// openFreezerFileForReadOnly opens a freezer table file for read only access -func openFreezerFileForReadOnly(filename string) (*os.File, error) { - return os.OpenFile(filename, os.O_RDONLY, 0644) -} - -// openFreezerFileTruncated opens a freezer table making sure it is truncated -func openFreezerFileTruncated(filename string) (*os.File, error) { - return os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) -} - -// truncateFreezerFile resizes a freezer table file and seeks to the end -func truncateFreezerFile(file *os.File, size int64) error { - if err := file.Truncate(size); err != nil { - return err - } - // Seek to end for append - if _, err := file.Seek(0, io.SeekEnd); err != nil { - return err - } - return nil -} - -// grow prepares the slice space for new item, and doubles the slice capacity -// if space is not enough. -func grow(buf []byte, n int) []byte { - if cap(buf)-len(buf) < n { - newcap := 2 * cap(buf) - if newcap-len(buf) < n { - newcap = len(buf) + n - } - nbuf := make([]byte, len(buf), newcap) - copy(nbuf, buf) - buf = nbuf - } - buf = buf[:len(buf)+n] - return buf -} diff --git a/builder/core/rawdb/freezer_utils_test.go b/builder/core/rawdb/freezer_utils_test.go deleted file mode 100644 index 829cbfb4f..000000000 --- a/builder/core/rawdb/freezer_utils_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "os" - "testing" -) - -func TestCopyFrom(t *testing.T) { - var ( - content = []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8} - prefix = []byte{0x9, 0xa, 0xb, 0xc, 0xd, 0xf} - ) - var cases = []struct { - src, dest string - offset uint64 - writePrefix bool - }{ - {"foo", "bar", 0, false}, - {"foo", "bar", 1, false}, - {"foo", "bar", 8, false}, - {"foo", "foo", 0, false}, - {"foo", "foo", 1, false}, - {"foo", "foo", 8, false}, - {"foo", "bar", 0, true}, - {"foo", "bar", 1, true}, - {"foo", "bar", 8, true}, - } - for _, c := range cases { - os.WriteFile(c.src, content, 0600) - - if err := copyFrom(c.src, c.dest, c.offset, func(f *os.File) error { - if !c.writePrefix { - return nil - } - f.Write(prefix) - return nil - }); err != nil { - os.Remove(c.src) - t.Fatalf("Failed to copy %v", err) - } - - blob, err := os.ReadFile(c.dest) - if err != nil { - os.Remove(c.src) - os.Remove(c.dest) - t.Fatalf("Failed to read %v", err) - } - want := content[c.offset:] - if c.writePrefix { - want = append(prefix, want...) - } - if !bytes.Equal(blob, want) { - t.Fatal("Unexpected value") - } - os.Remove(c.src) - os.Remove(c.dest) - } -} diff --git a/builder/core/rawdb/key_length_iterator.go b/builder/core/rawdb/key_length_iterator.go deleted file mode 100644 index d1c5af269..000000000 --- a/builder/core/rawdb/key_length_iterator.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 rawdb - -import "github.com/ethereum/go-ethereum/ethdb" - -// KeyLengthIterator is a wrapper for a database iterator that ensures only key-value pairs -// with a specific key length will be returned. -type KeyLengthIterator struct { - requiredKeyLength int - ethdb.Iterator -} - -// NewKeyLengthIterator returns a wrapped version of the iterator that will only return key-value -// pairs where keys with a specific key length will be returned. -func NewKeyLengthIterator(it ethdb.Iterator, keyLen int) ethdb.Iterator { - return &KeyLengthIterator{ - Iterator: it, - requiredKeyLength: keyLen, - } -} - -func (it *KeyLengthIterator) Next() bool { - // Return true as soon as a key with the required key length is discovered - for it.Iterator.Next() { - if len(it.Iterator.Key()) == it.requiredKeyLength { - return true - } - } - - // Return false when we exhaust the keys in the underlying iterator. - return false -} diff --git a/builder/core/rawdb/key_length_iterator_test.go b/builder/core/rawdb/key_length_iterator_test.go deleted file mode 100644 index 654efc5b5..000000000 --- a/builder/core/rawdb/key_length_iterator_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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 rawdb - -import ( - "encoding/binary" - "testing" -) - -func TestKeyLengthIterator(t *testing.T) { - db := NewMemoryDatabase() - - keyLen := 8 - expectedKeys := make(map[string]struct{}) - for i := 0; i < 100; i++ { - key := make([]byte, keyLen) - binary.BigEndian.PutUint64(key, uint64(i)) - if err := db.Put(key, []byte{0x1}); err != nil { - t.Fatal(err) - } - expectedKeys[string(key)] = struct{}{} - - longerKey := make([]byte, keyLen*2) - binary.BigEndian.PutUint64(longerKey, uint64(i)) - if err := db.Put(longerKey, []byte{0x1}); err != nil { - t.Fatal(err) - } - } - - it := NewKeyLengthIterator(db.NewIterator(nil, nil), keyLen) - for it.Next() { - key := it.Key() - _, exists := expectedKeys[string(key)] - if !exists { - t.Fatalf("Found unexpected key %d", binary.BigEndian.Uint64(key)) - } - delete(expectedKeys, string(key)) - if len(key) != keyLen { - t.Fatalf("Found unexpected key in key length iterator with length %d", len(key)) - } - } - - if len(expectedKeys) != 0 { - t.Fatalf("Expected all keys of length %d to be removed from expected keys during iteration", keyLen) - } -} diff --git a/builder/core/rawdb/schema.go b/builder/core/rawdb/schema.go deleted file mode 100644 index 11cf5b40f..000000000 --- a/builder/core/rawdb/schema.go +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2018 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 rawdb contains a collection of low level database accessors. -package rawdb - -import ( - "bytes" - "encoding/binary" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/metrics" -) - -// The fields below define the low level database schema prefixing. -var ( - // databaseVersionKey tracks the current database version. - databaseVersionKey = []byte("DatabaseVersion") - - // headHeaderKey tracks the latest known header's hash. - headHeaderKey = []byte("LastHeader") - - // headBlockKey tracks the latest known full block's hash. - headBlockKey = []byte("LastBlock") - - // headFastBlockKey tracks the latest known incomplete block's hash during fast sync. - headFastBlockKey = []byte("LastFast") - - // headFinalizedBlockKey tracks the latest known finalized block hash. - headFinalizedBlockKey = []byte("LastFinalized") - - // persistentStateIDKey tracks the id of latest stored state(for path-based only). - persistentStateIDKey = []byte("LastStateID") - - // lastPivotKey tracks the last pivot block used by fast sync (to reenable on sethead). - lastPivotKey = []byte("LastPivot") - - // fastTrieProgressKey tracks the number of trie entries imported during fast sync. - fastTrieProgressKey = []byte("TrieSync") - - // snapshotDisabledKey flags that the snapshot should not be maintained due to initial sync. - snapshotDisabledKey = []byte("SnapshotDisabled") - - // SnapshotRootKey tracks the hash of the last snapshot. - SnapshotRootKey = []byte("SnapshotRoot") - - // snapshotJournalKey tracks the in-memory diff layers across restarts. - snapshotJournalKey = []byte("SnapshotJournal") - - // snapshotGeneratorKey tracks the snapshot generation marker across restarts. - snapshotGeneratorKey = []byte("SnapshotGenerator") - - // snapshotRecoveryKey tracks the snapshot recovery marker across restarts. - snapshotRecoveryKey = []byte("SnapshotRecovery") - - // snapshotSyncStatusKey tracks the snapshot sync status across restarts. - snapshotSyncStatusKey = []byte("SnapshotSyncStatus") - - // skeletonSyncStatusKey tracks the skeleton sync status across restarts. - skeletonSyncStatusKey = []byte("SkeletonSyncStatus") - - // trieJournalKey tracks the in-memory trie node layers across restarts. - trieJournalKey = []byte("TrieJournal") - - // txIndexTailKey tracks the oldest block whose transactions have been indexed. - txIndexTailKey = []byte("TransactionIndexTail") - - // fastTxLookupLimitKey tracks the transaction lookup limit during fast sync. - // This flag is deprecated, it's kept to avoid reporting errors when inspect - // database. - fastTxLookupLimitKey = []byte("FastTransactionLookupLimit") - - // badBlockKey tracks the list of bad blocks seen by local - badBlockKey = []byte("InvalidBlock") - - // uncleanShutdownKey tracks the list of local crashes - uncleanShutdownKey = []byte("unclean-shutdown") // config prefix for the db - - // transitionStatusKey tracks the eth2 transition status. - transitionStatusKey = []byte("eth2-transition") - - // snapSyncStatusFlagKey flags that status of snap sync. - snapSyncStatusFlagKey = []byte("SnapSyncStatus") - - // Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes). - headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header - headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td - headerHashSuffix = []byte("n") // headerPrefix + num (uint64 big endian) + headerHashSuffix -> hash - headerNumberPrefix = []byte("H") // headerNumberPrefix + hash -> num (uint64 big endian) - - blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body - blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts - - txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata - bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits - SnapshotAccountPrefix = []byte("a") // SnapshotAccountPrefix + account hash -> account trie value - SnapshotStoragePrefix = []byte("o") // SnapshotStoragePrefix + account hash + storage hash -> storage trie value - CodePrefix = []byte("c") // CodePrefix + code hash -> account code - skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header - - // Path-based storage scheme of merkle patricia trie. - trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node - trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node - stateIDPrefix = []byte("L") // stateIDPrefix + state root -> state id - - PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage - configPrefix = []byte("ethereum-config-") // config prefix for the db - genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db - - // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress - BloomBitsIndexPrefix = []byte("iB") - - ChtPrefix = []byte("chtRootV2-") // ChtPrefix + chtNum (uint64 big endian) -> trie root hash - ChtTablePrefix = []byte("cht-") - ChtIndexTablePrefix = []byte("chtIndexV2-") - - BloomTriePrefix = []byte("bltRoot-") // BloomTriePrefix + bloomTrieNum (uint64 big endian) -> trie root hash - BloomTrieTablePrefix = []byte("blt-") - BloomTrieIndexPrefix = []byte("bltIndex-") - - CliqueSnapshotPrefix = []byte("clique-") - - BestUpdateKey = []byte("update-") // bigEndian64(syncPeriod) -> RLP(types.LightClientUpdate) (nextCommittee only referenced by root hash) - FixedCommitteeRootKey = []byte("fixedRoot-") // bigEndian64(syncPeriod) -> committee root hash - SyncCommitteeKey = []byte("committee-") // bigEndian64(syncPeriod) -> serialized committee - - preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) - preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) -) - -// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary -// fields. -type LegacyTxLookupEntry struct { - BlockHash common.Hash - BlockIndex uint64 - Index uint64 -} - -// encodeBlockNumber encodes a block number as big endian uint64 -func encodeBlockNumber(number uint64) []byte { - enc := make([]byte, 8) - binary.BigEndian.PutUint64(enc, number) - return enc -} - -// headerKeyPrefix = headerPrefix + num (uint64 big endian) -func headerKeyPrefix(number uint64) []byte { - return append(headerPrefix, encodeBlockNumber(number)...) -} - -// headerKey = headerPrefix + num (uint64 big endian) + hash -func headerKey(number uint64, hash common.Hash) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// headerTDKey = headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -func headerTDKey(number uint64, hash common.Hash) []byte { - return append(headerKey(number, hash), headerTDSuffix...) -} - -// headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix -func headerHashKey(number uint64) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) -} - -// headerNumberKey = headerNumberPrefix + hash -func headerNumberKey(hash common.Hash) []byte { - return append(headerNumberPrefix, hash.Bytes()...) -} - -// blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash -func blockBodyKey(number uint64, hash common.Hash) []byte { - return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash -func blockReceiptsKey(number uint64, hash common.Hash) []byte { - return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - -// txLookupKey = txLookupPrefix + hash -func txLookupKey(hash common.Hash) []byte { - return append(txLookupPrefix, hash.Bytes()...) -} - -// accountSnapshotKey = SnapshotAccountPrefix + hash -func accountSnapshotKey(hash common.Hash) []byte { - return append(SnapshotAccountPrefix, hash.Bytes()...) -} - -// storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash -func storageSnapshotKey(accountHash, storageHash common.Hash) []byte { - buf := make([]byte, len(SnapshotStoragePrefix)+common.HashLength+common.HashLength) - n := copy(buf, SnapshotStoragePrefix) - n += copy(buf[n:], accountHash.Bytes()) - copy(buf[n:], storageHash.Bytes()) - return buf -} - -// storageSnapshotsKey = SnapshotStoragePrefix + account hash + storage hash -func storageSnapshotsKey(accountHash common.Hash) []byte { - return append(SnapshotStoragePrefix, accountHash.Bytes()...) -} - -// bloomBitsKey = bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -func bloomBitsKey(bit uint, section uint64, hash common.Hash) []byte { - key := append(append(bloomBitsPrefix, make([]byte, 10)...), hash.Bytes()...) - - binary.BigEndian.PutUint16(key[1:], uint16(bit)) - binary.BigEndian.PutUint64(key[3:], section) - - return key -} - -// skeletonHeaderKey = skeletonHeaderPrefix + num (uint64 big endian) -func skeletonHeaderKey(number uint64) []byte { - return append(skeletonHeaderPrefix, encodeBlockNumber(number)...) -} - -// preimageKey = PreimagePrefix + hash -func preimageKey(hash common.Hash) []byte { - return append(PreimagePrefix, hash.Bytes()...) -} - -// codeKey = CodePrefix + hash -func codeKey(hash common.Hash) []byte { - return append(CodePrefix, hash.Bytes()...) -} - -// IsCodeKey reports whether the given byte slice is the key of contract code, -// if so return the raw code hash as well. -func IsCodeKey(key []byte) (bool, []byte) { - if bytes.HasPrefix(key, CodePrefix) && len(key) == common.HashLength+len(CodePrefix) { - return true, key[len(CodePrefix):] - } - return false, nil -} - -// configKey = configPrefix + hash -func configKey(hash common.Hash) []byte { - return append(configPrefix, hash.Bytes()...) -} - -// genesisStateSpecKey = genesisPrefix + hash -func genesisStateSpecKey(hash common.Hash) []byte { - return append(genesisPrefix, hash.Bytes()...) -} - -// stateIDKey = stateIDPrefix + root (32 bytes) -func stateIDKey(root common.Hash) []byte { - return append(stateIDPrefix, root.Bytes()...) -} - -// accountTrieNodeKey = trieNodeAccountPrefix + nodePath. -func accountTrieNodeKey(path []byte) []byte { - return append(trieNodeAccountPrefix, path...) -} - -// storageTrieNodeKey = trieNodeStoragePrefix + accountHash + nodePath. -func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte { - buf := make([]byte, len(trieNodeStoragePrefix)+common.HashLength+len(path)) - n := copy(buf, trieNodeStoragePrefix) - n += copy(buf[n:], accountHash.Bytes()) - copy(buf[n:], path) - return buf -} - -// IsLegacyTrieNode reports whether a provided database entry is a legacy trie -// node. The characteristics of legacy trie node are: -// - the key length is 32 bytes -// - the key is the hash of val -func IsLegacyTrieNode(key []byte, val []byte) bool { - if len(key) != common.HashLength { - return false - } - return bytes.Equal(key, crypto.Keccak256(val)) -} - -// ResolveAccountTrieNodeKey reports whether a provided database entry is an -// account trie node in path-based state scheme, and returns the resolved -// node path if so. -func ResolveAccountTrieNodeKey(key []byte) (bool, []byte) { - if !bytes.HasPrefix(key, trieNodeAccountPrefix) { - return false, nil - } - // The remaining key should only consist a hex node path - // whose length is in the range 0 to 64 (64 is excluded - // since leaves are always wrapped with shortNode). - if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 { - return false, nil - } - return true, key[len(trieNodeAccountPrefix):] -} - -// IsAccountTrieNode reports whether a provided database entry is an account -// trie node in path-based state scheme. -func IsAccountTrieNode(key []byte) bool { - ok, _ := ResolveAccountTrieNodeKey(key) - return ok -} - -// ResolveStorageTrieNode reports whether a provided database entry is a storage -// trie node in path-based state scheme, and returns the resolved account hash -// and node path if so. -func ResolveStorageTrieNode(key []byte) (bool, common.Hash, []byte) { - if !bytes.HasPrefix(key, trieNodeStoragePrefix) { - return false, common.Hash{}, nil - } - // The remaining key consists of 2 parts: - // - 32 bytes account hash - // - hex node path whose length is in the range 0 to 64 - if len(key) < len(trieNodeStoragePrefix)+common.HashLength { - return false, common.Hash{}, nil - } - if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 { - return false, common.Hash{}, nil - } - accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength]) - return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:] -} - -// IsStorageTrieNode reports whether a provided database entry is a storage -// trie node in path-based state scheme. -func IsStorageTrieNode(key []byte) bool { - ok, _, _ := ResolveStorageTrieNode(key) - return ok -} diff --git a/builder/core/rawdb/table.go b/builder/core/rawdb/table.go deleted file mode 100644 index 19e4ed5b5..000000000 --- a/builder/core/rawdb/table.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2018 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 rawdb - -import ( - "github.com/ethereum/go-ethereum/ethdb" -) - -// table is a wrapper around a database that prefixes each key access with a pre- -// configured string. -type table struct { - db ethdb.Database - prefix string -} - -// NewTable returns a database object that prefixes all keys with a given string. -func NewTable(db ethdb.Database, prefix string) ethdb.Database { - return &table{ - db: db, - prefix: prefix, - } -} - -// Close is a noop to implement the Database interface. -func (t *table) Close() error { - return nil -} - -// Has retrieves if a prefixed version of a key is present in the database. -func (t *table) Has(key []byte) (bool, error) { - return t.db.Has(append([]byte(t.prefix), key...)) -} - -// Get retrieves the given prefixed key if it's present in the database. -func (t *table) Get(key []byte) ([]byte, error) { - return t.db.Get(append([]byte(t.prefix), key...)) -} - -// HasAncient is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) HasAncient(kind string, number uint64) (bool, error) { - return t.db.HasAncient(kind, number) -} - -// Ancient is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Ancient(kind string, number uint64) ([]byte, error) { - return t.db.Ancient(kind, number) -} - -// AncientRange is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - return t.db.AncientRange(kind, start, count, maxBytes) -} - -// Ancients is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Ancients() (uint64, error) { - return t.db.Ancients() -} - -// Tail is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Tail() (uint64, error) { - return t.db.Tail() -} - -// AncientSize is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) AncientSize(kind string) (uint64, error) { - return t.db.AncientSize(kind) -} - -// ModifyAncients runs an ancient write operation on the underlying database. -func (t *table) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (int64, error) { - return t.db.ModifyAncients(fn) -} - -func (t *table) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { - return t.db.ReadAncients(fn) -} - -// TruncateHead is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) TruncateHead(items uint64) (uint64, error) { - return t.db.TruncateHead(items) -} - -// TruncateTail is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) TruncateTail(items uint64) (uint64, error) { - return t.db.TruncateTail(items) -} - -// Sync is a noop passthrough that just forwards the request to the underlying -// database. -func (t *table) Sync() error { - return t.db.Sync() -} - -// MigrateTable processes the entries in a given table in sequence -// converting them to a new format if they're of an old format. -func (t *table) MigrateTable(kind string, convert convertLegacyFn) error { - return t.db.MigrateTable(kind, convert) -} - -// AncientDatadir returns the ancient datadir of the underlying database. -func (t *table) AncientDatadir() (string, error) { - return t.db.AncientDatadir() -} - -// Put inserts the given value into the database at a prefixed version of the -// provided key. -func (t *table) Put(key []byte, value []byte) error { - return t.db.Put(append([]byte(t.prefix), key...), value) -} - -// Delete removes the given prefixed key from the database. -func (t *table) Delete(key []byte) error { - return t.db.Delete(append([]byte(t.prefix), key...)) -} - -// NewIterator creates a binary-alphabetical iterator over a subset -// of database content with a particular key prefix, starting at a particular -// initial key (or after, if it does not exist). -func (t *table) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - innerPrefix := append([]byte(t.prefix), prefix...) - iter := t.db.NewIterator(innerPrefix, start) - return &tableIterator{ - iter: iter, - prefix: t.prefix, - } -} - -// Stat returns a particular internal stat of the database. -func (t *table) Stat(property string) (string, error) { - return t.db.Stat(property) -} - -// Compact flattens the underlying data store for the given key range. In essence, -// deleted and overwritten versions are discarded, and the data is rearranged to -// reduce the cost of operations needed to access them. -// -// A nil start is treated as a key before all keys in the data store; a nil limit -// is treated as a key after all keys in the data store. If both is nil then it -// will compact entire data store. -func (t *table) Compact(start []byte, limit []byte) error { - // If no start was specified, use the table prefix as the first value - if start == nil { - start = []byte(t.prefix) - } else { - start = append([]byte(t.prefix), start...) - } - // If no limit was specified, use the first element not matching the prefix - // as the limit - if limit == nil { - limit = []byte(t.prefix) - for i := len(limit) - 1; i >= 0; i-- { - // Bump the current character, stopping if it doesn't overflow - limit[i]++ - if limit[i] > 0 { - break - } - // Character overflown, proceed to the next or nil if the last - if i == 0 { - limit = nil - } - } - } else { - limit = append([]byte(t.prefix), limit...) - } - // Range correctly calculated based on table prefix, delegate down - return t.db.Compact(start, limit) -} - -// NewBatch creates a write-only database that buffers changes to its host db -// until a final write is called, each operation prefixing all keys with the -// pre-configured string. -func (t *table) NewBatch() ethdb.Batch { - return &tableBatch{t.db.NewBatch(), t.prefix} -} - -// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -func (t *table) NewBatchWithSize(size int) ethdb.Batch { - return &tableBatch{t.db.NewBatchWithSize(size), t.prefix} -} - -// NewSnapshot creates a database snapshot based on the current state. -// The created snapshot will not be affected by all following mutations -// happened on the database. -func (t *table) NewSnapshot() (ethdb.Snapshot, error) { - return t.db.NewSnapshot() -} - -// tableBatch is a wrapper around a database batch that prefixes each key access -// with a pre-configured string. -type tableBatch struct { - batch ethdb.Batch - prefix string -} - -// Put inserts the given value into the batch for later committing. -func (b *tableBatch) Put(key, value []byte) error { - return b.batch.Put(append([]byte(b.prefix), key...), value) -} - -// Delete inserts a key removal into the batch for later committing. -func (b *tableBatch) Delete(key []byte) error { - return b.batch.Delete(append([]byte(b.prefix), key...)) -} - -// ValueSize retrieves the amount of data queued up for writing. -func (b *tableBatch) ValueSize() int { - return b.batch.ValueSize() -} - -// Write flushes any accumulated data to disk. -func (b *tableBatch) Write() error { - return b.batch.Write() -} - -// Reset resets the batch for reuse. -func (b *tableBatch) Reset() { - b.batch.Reset() -} - -// tableReplayer is a wrapper around a batch replayer which truncates -// the added prefix. -type tableReplayer struct { - w ethdb.KeyValueWriter - prefix string -} - -// Put implements the interface KeyValueWriter. -func (r *tableReplayer) Put(key []byte, value []byte) error { - trimmed := key[len(r.prefix):] - return r.w.Put(trimmed, value) -} - -// Delete implements the interface KeyValueWriter. -func (r *tableReplayer) Delete(key []byte) error { - trimmed := key[len(r.prefix):] - return r.w.Delete(trimmed) -} - -// Replay replays the batch contents. -func (b *tableBatch) Replay(w ethdb.KeyValueWriter) error { - return b.batch.Replay(&tableReplayer{w: w, prefix: b.prefix}) -} - -// tableIterator is a wrapper around a database iterator that prefixes each key access -// with a pre-configured string. -type tableIterator struct { - iter ethdb.Iterator - prefix string -} - -// Next moves the iterator to the next key/value pair. It returns whether the -// iterator is exhausted. -func (iter *tableIterator) Next() bool { - return iter.iter.Next() -} - -// Error returns any accumulated error. Exhausting all the key/value pairs -// is not considered to be an error. -func (iter *tableIterator) Error() error { - return iter.iter.Error() -} - -// Key returns the key of the current key/value pair, or nil if done. The caller -// should not modify the contents of the returned slice, and its contents may -// change on the next call to Next. -func (iter *tableIterator) Key() []byte { - key := iter.iter.Key() - if key == nil { - return nil - } - return key[len(iter.prefix):] -} - -// Value returns the value of the current key/value pair, or nil if done. The -// caller should not modify the contents of the returned slice, and its contents -// may change on the next call to Next. -func (iter *tableIterator) Value() []byte { - return iter.iter.Value() -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (iter *tableIterator) Release() { - iter.iter.Release() -} diff --git a/builder/core/rawdb/table_test.go b/builder/core/rawdb/table_test.go deleted file mode 100644 index aa6adf3e7..000000000 --- a/builder/core/rawdb/table_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// 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 rawdb - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" -) - -func TestTableDatabase(t *testing.T) { testTableDatabase(t, "prefix") } -func TestEmptyPrefixTableDatabase(t *testing.T) { testTableDatabase(t, "") } - -type testReplayer struct { - puts [][]byte - dels [][]byte -} - -func (r *testReplayer) Put(key []byte, value []byte) error { - r.puts = append(r.puts, key) - return nil -} - -func (r *testReplayer) Delete(key []byte) error { - r.dels = append(r.dels, key) - return nil -} - -func testTableDatabase(t *testing.T, prefix string) { - db := NewTable(NewMemoryDatabase(), prefix) - - var entries = []struct { - key []byte - value []byte - }{ - {[]byte{0x01, 0x02}, []byte{0x0a, 0x0b}}, - {[]byte{0x03, 0x04}, []byte{0x0c, 0x0d}}, - {[]byte{0x05, 0x06}, []byte{0x0e, 0x0f}}, - - {[]byte{0xff, 0xff, 0x01}, []byte{0x1a, 0x1b}}, - {[]byte{0xff, 0xff, 0x02}, []byte{0x1c, 0x1d}}, - {[]byte{0xff, 0xff, 0x03}, []byte{0x1e, 0x1f}}, - } - - // Test Put/Get operation - for _, entry := range entries { - db.Put(entry.key, entry.value) - } - for _, entry := range entries { - got, err := db.Get(entry.key) - if err != nil { - t.Fatalf("Failed to get value: %v", err) - } - if !bytes.Equal(got, entry.value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entry.value, got) - } - } - - // Test batch operation - db = NewTable(NewMemoryDatabase(), prefix) - batch := db.NewBatch() - for _, entry := range entries { - batch.Put(entry.key, entry.value) - } - batch.Write() - for _, entry := range entries { - got, err := db.Get(entry.key) - if err != nil { - t.Fatalf("Failed to get value: %v", err) - } - if !bytes.Equal(got, entry.value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entry.value, got) - } - } - - // Test batch replayer - r := &testReplayer{} - batch.Replay(r) - for index, entry := range entries { - got := r.puts[index] - if !bytes.Equal(got, entry.key) { - t.Fatalf("Key mismatch: want=%v, got=%v", entry.key, got) - } - } - - check := func(iter ethdb.Iterator, expCount, index int) { - count := 0 - for iter.Next() { - key, value := iter.Key(), iter.Value() - if !bytes.Equal(key, entries[index].key) { - t.Fatalf("Key mismatch: want=%v, got=%v", entries[index].key, key) - } - if !bytes.Equal(value, entries[index].value) { - t.Fatalf("Value mismatch: want=%v, got=%v", entries[index].value, value) - } - index += 1 - count++ - } - if count != expCount { - t.Fatalf("Wrong number of elems, exp %d got %d", expCount, count) - } - iter.Release() - } - // Test iterators - check(db.NewIterator(nil, nil), 6, 0) - // Test iterators with prefix - check(db.NewIterator([]byte{0xff, 0xff}, nil), 3, 3) - // Test iterators with start point - check(db.NewIterator(nil, []byte{0xff, 0xff, 0x02}), 2, 4) - // Test iterators with prefix and start point - check(db.NewIterator([]byte{0xee}, nil), 0, 0) - check(db.NewIterator(nil, []byte{0x00}), 6, 0) -} diff --git a/builder/core/rawdb/testdata/stored_receipts.bin b/builder/core/rawdb/testdata/stored_receipts.bin deleted file mode 100644 index 8204fae09..000000000 Binary files a/builder/core/rawdb/testdata/stored_receipts.bin and /dev/null differ diff --git a/builder/core/rlp_test.go b/builder/core/rlp_test.go deleted file mode 100644 index bc3740853..000000000 --- a/builder/core/rlp_test.go +++ /dev/null @@ -1,197 +0,0 @@ -// 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 core - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" -) - -func getBlock(transactions int, uncles int, dataSize int) *types.Block { - var ( - aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") - engine = ethash.NewFaker() - - // A sender who makes transactions, has some funds - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1_000_000_000_000_000_000) - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{address: {Balance: funds}}, - } - ) - // We need to generate as many blocks +1 as uncles - _, blocks, _ := GenerateChainWithGenesis(gspec, engine, uncles+1, - func(n int, b *BlockGen) { - if n == uncles { - // Add transactions and stuff on the last block - for i := 0; i < transactions; i++ { - tx, _ := types.SignTx(types.NewTransaction(uint64(i), aa, - big.NewInt(0), 50000, b.header.BaseFee, make([]byte, dataSize)), types.HomesteadSigner{}, key) - b.AddTx(tx) - } - for i := 0; i < uncles; i++ { - b.AddUncle(&types.Header{ParentHash: b.PrevBlock(n - 1 - i).Hash(), Number: big.NewInt(int64(n - i))}) - } - } - }) - block := blocks[len(blocks)-1] - return block -} - -// TestRlpIterator tests that individual transactions can be picked out -// from blocks without full unmarshalling/marshalling -func TestRlpIterator(t *testing.T) { - for _, tt := range []struct { - txs int - uncles int - datasize int - }{ - {0, 0, 0}, - {0, 2, 0}, - {10, 0, 0}, - {10, 2, 0}, - {10, 2, 50}, - } { - testRlpIterator(t, tt.txs, tt.uncles, tt.datasize) - } -} - -func testRlpIterator(t *testing.T, txs, uncles, datasize int) { - desc := fmt.Sprintf("%d txs [%d datasize] and %d uncles", txs, datasize, uncles) - bodyRlp, _ := rlp.EncodeToBytes(getBlock(txs, uncles, datasize).Body()) - it, err := rlp.NewListIterator(bodyRlp) - if err != nil { - t.Fatal(err) - } - // Check that txs exist - if !it.Next() { - t.Fatal("expected two elems, got zero") - } - txdata := it.Value() - // Check that uncles exist - if !it.Next() { - t.Fatal("expected two elems, got one") - } - // No more after that - if it.Next() { - t.Fatal("expected only two elems, got more") - } - txIt, err := rlp.NewListIterator(txdata) - if err != nil { - t.Fatal(err) - } - var gotHashes []common.Hash - var expHashes []common.Hash - for txIt.Next() { - gotHashes = append(gotHashes, crypto.Keccak256Hash(txIt.Value())) - } - - var expBody types.Body - err = rlp.DecodeBytes(bodyRlp, &expBody) - if err != nil { - t.Fatal(err) - } - for _, tx := range expBody.Transactions { - expHashes = append(expHashes, tx.Hash()) - } - if gotLen, expLen := len(gotHashes), len(expHashes); gotLen != expLen { - t.Fatalf("testcase %v: length wrong, got %d exp %d", desc, gotLen, expLen) - } - // also sanity check against input - if gotLen := len(gotHashes); gotLen != txs { - t.Fatalf("testcase %v: length wrong, got %d exp %d", desc, gotLen, txs) - } - for i, got := range gotHashes { - if exp := expHashes[i]; got != exp { - t.Errorf("testcase %v: hash wrong, got %x, exp %x", desc, got, exp) - } - } -} - -// BenchmarkHashing compares the speeds of hashing a rlp raw data directly -// without the unmarshalling/marshalling step -func BenchmarkHashing(b *testing.B) { - // Make a pretty fat block - var ( - bodyRlp []byte - blockRlp []byte - ) - { - block := getBlock(200, 2, 50) - bodyRlp, _ = rlp.EncodeToBytes(block.Body()) - blockRlp, _ = rlp.EncodeToBytes(block) - } - var got common.Hash - var hasher = sha3.NewLegacyKeccak256() - b.Run("iteratorhashing", func(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - var hash common.Hash - it, err := rlp.NewListIterator(bodyRlp) - if err != nil { - b.Fatal(err) - } - it.Next() - txs := it.Value() - txIt, err := rlp.NewListIterator(txs) - if err != nil { - b.Fatal(err) - } - for txIt.Next() { - hasher.Reset() - hasher.Write(txIt.Value()) - hasher.Sum(hash[:0]) - got = hash - } - } - }) - var exp common.Hash - b.Run("fullbodyhashing", func(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - var body types.Body - rlp.DecodeBytes(bodyRlp, &body) - for _, tx := range body.Transactions { - exp = tx.Hash() - } - } - }) - b.Run("fullblockhashing", func(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - var block types.Block - rlp.DecodeBytes(blockRlp, &block) - for _, tx := range block.Transactions() { - tx.Hash() - } - } - }) - if got != exp { - b.Fatalf("hash wrong, got %x exp %x", got, exp) - } -} diff --git a/builder/core/sbundle_sim.go b/builder/core/sbundle_sim.go deleted file mode 100644 index b56b63297..000000000 --- a/builder/core/sbundle_sim.go +++ /dev/null @@ -1,163 +0,0 @@ -package core - -import ( - "errors" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -var ( - ErrInvalidInclusion = errors.New("invalid inclusion") - - ErrTxFailed = errors.New("tx failed") - ErrNegativeProfit = errors.New("negative profit") - ErrInvalidBundle = errors.New("invalid bundle") - - SbundlePayoutMaxCostInt uint64 = 30_000 - SbundlePayoutMaxCost = uint256.NewInt(30_000) -) - -type SimBundleResult struct { - TotalProfit *uint256.Int - RefundableValue *uint256.Int - GasUsed uint64 - MevGasPrice *uint256.Int - BodyLogs []SimBundleBodyLogs - Revert []byte - ExecError string -} - -type SimBundleBodyLogs struct { - TxLogs []*types.Log `json:"txLogs,omitempty"` - BundleLogs []SimBundleBodyLogs `json:"bundleLogs,omitempty"` -} - -func NewSimBundleResult() SimBundleResult { - return SimBundleResult{ - TotalProfit: uint256.NewInt(0), - RefundableValue: uint256.NewInt(0), - GasUsed: 0, - MevGasPrice: uint256.NewInt(0), - BodyLogs: nil, - } -} - -// SimBundle simulates a bundle and returns the result -// Arguments are the same as in ApplyTransaction with the same change semantics: -// - statedb is modified -// - header is not modified -// - gp is modified -// - usedGas is modified (by txs that were applied) -// Payout transactions will not be applied to the state. -// GasUsed in return will include the gas that might be used by the payout txs. -func SimBundle(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, b *types.SBundle, txIdx int, usedGas *uint64, cfg vm.Config, logs bool) (SimBundleResult, error) { - res := NewSimBundleResult() - - currBlock := header.Number.Uint64() - if currBlock < b.Inclusion.BlockNumber || currBlock > b.Inclusion.MaxBlockNumber { - return res, ErrInvalidInclusion - } - - // extract constraints into convenient format - refundIdx := make([]bool, len(b.Body)) - refundPercents := make([]int, len(b.Body)) - for _, el := range b.Validity.Refund { - refundIdx[el.BodyIdx] = true - refundPercents[el.BodyIdx] = el.Percent - } - - var ( - coinbaseDelta = new(uint256.Int) - coinbaseBefore *uint256.Int - ) - for i, el := range b.Body { - coinbaseDelta.Set(common.U2560) - coinbaseBefore = statedb.GetBalance(header.Coinbase) - - if el.Tx != nil { - statedb.SetTxContext(el.Tx.Hash(), txIdx) - txIdx++ - receipt, result, err := ApplyTransactionWithResult(config, bc, author, gp, statedb, header, el.Tx, usedGas, cfg) - if err != nil { - return res, err - } - res.Revert = result.Revert() - if result.Err != nil { - res.ExecError = result.Err.Error() - } - if receipt.Status != types.ReceiptStatusSuccessful && !el.CanRevert { - return res, ErrTxFailed - } - res.GasUsed += receipt.GasUsed - if logs { - res.BodyLogs = append(res.BodyLogs, SimBundleBodyLogs{TxLogs: receipt.Logs}) - } - } else if el.Bundle != nil { - innerRes, err := SimBundle(config, bc, author, gp, statedb, header, el.Bundle, txIdx, usedGas, cfg, logs) - if err != nil { - return res, err - } - // basically return first exec error if exists, helpful for single-tx sbundles - if len(res.Revert) == 0 { - res.Revert = innerRes.Revert - } - if len(res.ExecError) == 0 { - res.ExecError = innerRes.ExecError - } - res.GasUsed += innerRes.GasUsed - if logs { - res.BodyLogs = append(res.BodyLogs, SimBundleBodyLogs{BundleLogs: innerRes.BodyLogs}) - } - } else { - return res, ErrInvalidBundle - } - - coinbaseAfter := statedb.GetBalance(header.Coinbase) - coinbaseDelta.Set(coinbaseAfter) - coinbaseDelta.Sub(coinbaseDelta, coinbaseBefore) - - res.TotalProfit.Add(res.TotalProfit, coinbaseDelta) - if !refundIdx[i] { - res.RefundableValue.Add(res.RefundableValue, coinbaseDelta) - } - } - - // estimate payout value and subtract from total profit - signer := types.MakeSigner(config, header.Number, header.Time) - for i, el := range refundPercents { - if !refundIdx[i] { - continue - } - // we pay tx cost out of the refundable value - - // cost - refundConfig, err := types.GetRefundConfig(&b.Body[i], signer) - if err != nil { - return res, err - } - payoutTxFee := new(uint256.Int).Mul(uint256.MustFromBig(header.BaseFee), SbundlePayoutMaxCost) - payoutTxFee.Mul(payoutTxFee, new(uint256.Int).SetUint64(uint64(len(refundConfig)))) - res.GasUsed += SbundlePayoutMaxCost.Uint64() * uint64(len(refundConfig)) - - // allocated refundable value - payoutValue := common.PercentOf(res.RefundableValue, el) - - if payoutTxFee.Cmp(payoutValue) > 0 { - return res, ErrNegativeProfit - } - - res.TotalProfit.Sub(res.TotalProfit, payoutValue) - } - - if res.TotalProfit.Sign() < 0 { - res.TotalProfit.Set(common.U2560) - return res, ErrNegativeProfit - } - res.MevGasPrice.Div(res.TotalProfit, new(uint256.Int).SetUint64(res.GasUsed)) - return res, nil -} diff --git a/builder/core/sender_cacher.go b/builder/core/sender_cacher.go deleted file mode 100644 index 4be53619e..000000000 --- a/builder/core/sender_cacher.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 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 core - -import ( - "runtime" - - "github.com/ethereum/go-ethereum/core/types" -) - -// SenderCacher is a concurrent transaction sender recoverer and cacher. -var SenderCacher = newTxSenderCacher(runtime.NumCPU()) - -// txSenderCacherRequest is a request for recovering transaction senders with a -// specific signature scheme and caching it into the transactions themselves. -// -// The inc field defines the number of transactions to skip after each recovery, -// which is used to feed the same underlying input array to different threads but -// ensure they process the early transactions fast. -type txSenderCacherRequest struct { - signer types.Signer - txs []*types.Transaction - inc int -} - -// txSenderCacher is a helper structure to concurrently ecrecover transaction -// senders from digital signatures on background threads. -type txSenderCacher struct { - threads int - tasks chan *txSenderCacherRequest -} - -// newTxSenderCacher creates a new transaction sender background cacher and starts -// as many processing goroutines as allowed by the GOMAXPROCS on construction. -func newTxSenderCacher(threads int) *txSenderCacher { - cacher := &txSenderCacher{ - tasks: make(chan *txSenderCacherRequest, threads), - threads: threads, - } - for i := 0; i < threads; i++ { - go cacher.cache() - } - return cacher -} - -// cache is an infinite loop, caching transaction senders from various forms of -// data structures. -func (cacher *txSenderCacher) cache() { - for task := range cacher.tasks { - for i := 0; i < len(task.txs); i += task.inc { - types.Sender(task.signer, task.txs[i]) - } - } -} - -// Recover recovers the senders from a batch of transactions and caches them -// back into the same data structures. There is no validation being done, nor -// any reaction to invalid signatures. That is up to calling code later. -func (cacher *txSenderCacher) Recover(signer types.Signer, txs []*types.Transaction) { - // If there's nothing to recover, abort - if len(txs) == 0 { - return - } - // Ensure we have meaningful task sizes and schedule the recoveries - tasks := cacher.threads - if len(txs) < tasks*4 { - tasks = (len(txs) + 3) / 4 - } - for i := 0; i < tasks; i++ { - cacher.tasks <- &txSenderCacherRequest{ - signer: signer, - txs: txs[i:], - inc: tasks, - } - } -} - -// RecoverFromBlocks recovers the senders from a batch of blocks and caches them -// back into the same data structures. There is no validation being done, nor -// any reaction to invalid signatures. That is up to calling code later. -func (cacher *txSenderCacher) RecoverFromBlocks(signer types.Signer, blocks []*types.Block) { - count := 0 - for _, block := range blocks { - count += len(block.Transactions()) - } - txs := make([]*types.Transaction, 0, count) - for _, block := range blocks { - txs = append(txs, block.Transactions()...) - } - cacher.Recover(signer, txs) -} diff --git a/builder/core/state/access_list.go b/builder/core/state/access_list.go deleted file mode 100644 index 419469134..000000000 --- a/builder/core/state/access_list.go +++ /dev/null @@ -1,136 +0,0 @@ -// 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 state - -import ( - "github.com/ethereum/go-ethereum/common" -) - -type accessList struct { - addresses map[common.Address]int - slots []map[common.Hash]struct{} -} - -// ContainsAddress returns true if the address is in the access list. -func (al *accessList) ContainsAddress(address common.Address) bool { - _, ok := al.addresses[address] - return ok -} - -// Contains checks if a slot within an account is present in the access list, returning -// separate flags for the presence of the account and the slot respectively. -func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { - idx, ok := al.addresses[address] - if !ok { - // no such address (and hence zero slots) - return false, false - } - if idx == -1 { - // address yes, but no slots - return true, false - } - _, slotPresent = al.slots[idx][slot] - return true, slotPresent -} - -// newAccessList creates a new accessList. -func newAccessList() *accessList { - return &accessList{ - addresses: make(map[common.Address]int), - } -} - -// Copy creates an independent copy of an accessList. -func (a *accessList) Copy() *accessList { - cp := newAccessList() - for k, v := range a.addresses { - cp.addresses[k] = v - } - cp.slots = make([]map[common.Hash]struct{}, len(a.slots)) - for i, slotMap := range a.slots { - newSlotmap := make(map[common.Hash]struct{}, len(slotMap)) - for k := range slotMap { - newSlotmap[k] = struct{}{} - } - cp.slots[i] = newSlotmap - } - return cp -} - -// AddAddress adds an address to the access list, and returns 'true' if the operation -// caused a change (addr was not previously in the list). -func (al *accessList) AddAddress(address common.Address) bool { - if _, present := al.addresses[address]; present { - return false - } - al.addresses[address] = -1 - return true -} - -// AddSlot adds the specified (addr, slot) combo to the access list. -// Return values are: -// - address added -// - slot added -// For any 'true' value returned, a corresponding journal entry must be made. -func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) { - idx, addrPresent := al.addresses[address] - if !addrPresent || idx == -1 { - // Address not present, or addr present but no slots there - al.addresses[address] = len(al.slots) - slotmap := map[common.Hash]struct{}{slot: {}} - al.slots = append(al.slots, slotmap) - return !addrPresent, true - } - // There is already an (address,slot) mapping - slotmap := al.slots[idx] - if _, ok := slotmap[slot]; !ok { - slotmap[slot] = struct{}{} - // Journal add slot change - return false, true - } - // No changes required - return false, false -} - -// DeleteSlot removes an (address, slot)-tuple from the access list. -// This operation needs to be performed in the same order as the addition happened. -// This method is meant to be used by the journal, which maintains ordering of -// operations. -func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) { - idx, addrOk := al.addresses[address] - // There are two ways this can fail - if !addrOk { - panic("reverting slot change, address not present in list") - } - slotmap := al.slots[idx] - delete(slotmap, slot) - // If that was the last (first) slot, remove it - // Since additions and rollbacks are always performed in order, - // we can delete the item without worrying about screwing up later indices - if len(slotmap) == 0 { - al.slots = al.slots[:idx] - al.addresses[address] = -1 - } -} - -// DeleteAddress removes an address from the access list. This operation -// needs to be performed in the same order as the addition happened. -// This method is meant to be used by the journal, which maintains ordering of -// operations. -func (al *accessList) DeleteAddress(address common.Address) { - delete(al.addresses, address) -} diff --git a/builder/core/state/database.go b/builder/core/state/database.go deleted file mode 100644 index 7520923ee..000000000 --- a/builder/core/state/database.go +++ /dev/null @@ -1,266 +0,0 @@ -// 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 state - -import ( - "errors" - "fmt" - - "github.com/crate-crypto/go-ipa/banderwagon" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/trie/utils" - "github.com/ethereum/go-ethereum/triedb" -) - -const ( - // Number of codehash->size associations to keep. - codeSizeCacheSize = 100000 - - // Cache size granted for caching clean code. - codeCacheSize = 64 * 1024 * 1024 - - // commitmentSize is the size of commitment stored in cache. - commitmentSize = banderwagon.UncompressedSize - - // Cache item granted for caching commitment results. - commitmentCacheItems = 64 * 1024 * 1024 / (commitmentSize + common.AddressLength) -) - -// Database wraps access to tries and contract code. -type Database interface { - // OpenTrie opens the main account trie. - OpenTrie(root common.Hash) (Trie, error) - - // OpenStorageTrie opens the storage trie of an account. - OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, trie Trie) (Trie, error) - - // CopyTrie returns an independent copy of the given trie. - CopyTrie(Trie) Trie - - // ContractCode retrieves a particular contract's code. - ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) - - // ContractCodeSize retrieves a particular contracts code's size. - ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) - - // DiskDB returns the underlying key-value disk database. - DiskDB() ethdb.KeyValueStore - - // TrieDB returns the underlying trie database for managing trie nodes. - TrieDB() *triedb.Database -} - -// Trie is a Ethereum Merkle Patricia trie. -type Trie interface { - // GetKey returns the sha3 preimage of a hashed key that was previously used - // to store a value. - // - // TODO(fjl): remove this when StateTrie is removed - GetKey([]byte) []byte - - // GetAccount abstracts an account read from the trie. It retrieves the - // account blob from the trie with provided account address and decodes it - // with associated decoding algorithm. If the specified account is not in - // the trie, nil will be returned. If the trie is corrupted(e.g. some nodes - // are missing or the account blob is incorrect for decoding), an error will - // be returned. - GetAccount(address common.Address) (*types.StateAccount, error) - - // GetStorage returns the value for key stored in the trie. The value bytes - // must not be modified by the caller. If a node was not found in the database, - // a trie.MissingNodeError is returned. - GetStorage(addr common.Address, key []byte) ([]byte, error) - - // UpdateAccount abstracts an account write to the trie. It encodes the - // provided account object with associated algorithm and then updates it - // in the trie with provided address. - UpdateAccount(address common.Address, account *types.StateAccount) error - - // UpdateStorage associates key with value in the trie. If value has length zero, - // any existing value is deleted from the trie. The value bytes must not be modified - // by the caller while they are stored in the trie. If a node was not found in the - // database, a trie.MissingNodeError is returned. - UpdateStorage(addr common.Address, key, value []byte) error - - // DeleteAccount abstracts an account deletion from the trie. - DeleteAccount(address common.Address) error - - // DeleteStorage removes any existing value for key from the trie. If a node - // was not found in the database, a trie.MissingNodeError is returned. - DeleteStorage(addr common.Address, key []byte) error - - // UpdateContractCode abstracts code write to the trie. It is expected - // to be moved to the stateWriter interface when the latter is ready. - UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error - - // Hash returns the root hash of the trie. It does not write to the database and - // can be used even if the trie doesn't have one. - Hash() common.Hash - - // Commit collects all dirty nodes in the trie and replace them with the - // corresponding node hash. All collected nodes(including dirty leaves if - // collectLeaf is true) will be encapsulated into a nodeset for return. - // The returned nodeset can be nil if the trie is clean(nothing to commit). - // Once the trie is committed, it's not usable anymore. A new trie must - // be created with new root and updated trie database for following usage - Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) - - // NodeIterator returns an iterator that returns nodes of the trie. Iteration - // starts at the key after the given start key. And error will be returned - // if fails to create node iterator. - NodeIterator(startKey []byte) (trie.NodeIterator, error) - - // Prove constructs a Merkle proof for key. The result contains all encoded nodes - // on the path to the value at key. The value itself is also included in the last - // node and can be retrieved by verifying the proof. - // - // If the trie does not contain a value for key, the returned proof contains all - // nodes of the longest existing prefix of the key (at least the root), ending - // with the node that proves the absence of the key. - Prove(key []byte, proofDb ethdb.KeyValueWriter) error -} - -// NewDatabase creates a backing store for state. The returned database is safe for -// concurrent use, but does not retain any recent trie nodes in memory. To keep some -// historical state in memory, use the NewDatabaseWithConfig constructor. -func NewDatabase(db ethdb.Database) Database { - return NewDatabaseWithConfig(db, nil) -} - -// NewDatabaseWithConfig creates a backing store for state. The returned database -// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a -// large memory cache. -func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database { - return &cachingDB{ - disk: db, - codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), - codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: triedb.NewDatabase(db, config), - } -} - -// NewDatabaseWithNodeDB creates a state database with an already initialized node database. -func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database { - return &cachingDB{ - disk: db, - codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize), - codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize), - triedb: triedb, - } -} - -type cachingDB struct { - disk ethdb.KeyValueStore - codeSizeCache *lru.Cache[common.Hash, int] - codeCache *lru.SizeConstrainedCache[common.Hash, []byte] - triedb *triedb.Database -} - -// OpenTrie opens the main account trie at a specific root hash. -func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { - if db.triedb.IsVerkle() { - return trie.NewVerkleTrie(root, db.triedb, utils.NewPointCache(commitmentCacheItems)) - } - tr, err := trie.NewStateTrie(trie.StateTrieID(root), db.triedb) - if err != nil { - return nil, err - } - return tr, nil -} - -// OpenStorageTrie opens the storage trie of an account. -func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, self Trie) (Trie, error) { - // In the verkle case, there is only one tree. But the two-tree structure - // is hardcoded in the codebase. So we need to return the same trie in this - // case. - if db.triedb.IsVerkle() { - return self, nil - } - tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) - if err != nil { - return nil, err - } - return tr, nil -} - -// CopyTrie returns an independent copy of the given trie. -func (db *cachingDB) CopyTrie(t Trie) Trie { - switch t := t.(type) { - case *trie.StateTrie: - return t.Copy() - default: - panic(fmt.Errorf("unknown trie type %T", t)) - } -} - -// ContractCode retrieves a particular contract's code. -func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) { - code, _ := db.codeCache.Get(codeHash) - if len(code) > 0 { - return code, nil - } - code = rawdb.ReadCode(db.disk, codeHash) - if len(code) > 0 { - db.codeCache.Add(codeHash, code) - db.codeSizeCache.Add(codeHash, len(code)) - return code, nil - } - return nil, errors.New("not found") -} - -// ContractCodeWithPrefix retrieves a particular contract's code. If the -// code can't be found in the cache, then check the existence with **new** -// db scheme. -func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) { - code, _ := db.codeCache.Get(codeHash) - if len(code) > 0 { - return code, nil - } - code = rawdb.ReadCodeWithPrefix(db.disk, codeHash) - if len(code) > 0 { - db.codeCache.Add(codeHash, code) - db.codeSizeCache.Add(codeHash, len(code)) - return code, nil - } - return nil, errors.New("not found") -} - -// ContractCodeSize retrieves a particular contracts code's size. -func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) { - if cached, ok := db.codeSizeCache.Get(codeHash); ok { - return cached, nil - } - code, err := db.ContractCode(addr, codeHash) - return len(code), err -} - -// DiskDB returns the underlying key-value disk database. -func (db *cachingDB) DiskDB() ethdb.KeyValueStore { - return db.disk -} - -// TrieDB retrieves any intermediate trie-node caching layer. -func (db *cachingDB) TrieDB() *triedb.Database { - return db.triedb -} diff --git a/builder/core/state/dump.go b/builder/core/state/dump.go deleted file mode 100644 index 55abb50f1..000000000 --- a/builder/core/state/dump.go +++ /dev/null @@ -1,235 +0,0 @@ -// 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 state - -import ( - "encoding/json" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -// DumpConfig is a set of options to control what portions of the state will be -// iterated and collected. -type DumpConfig struct { - SkipCode bool - SkipStorage bool - OnlyWithAddresses bool - Start []byte - Max uint64 -} - -// DumpCollector interface which the state trie calls during iteration -type DumpCollector interface { - // OnRoot is called with the state root - OnRoot(common.Hash) - // OnAccount is called once for each account in the trie - OnAccount(*common.Address, DumpAccount) -} - -// DumpAccount represents an account in the state. -type DumpAccount struct { - Balance string `json:"balance"` - Nonce uint64 `json:"nonce"` - Root hexutil.Bytes `json:"root"` - CodeHash hexutil.Bytes `json:"codeHash"` - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[common.Hash]string `json:"storage,omitempty"` - Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode - AddressHash hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key - -} - -// Dump represents the full dump in a collected format, as one large map. -type Dump struct { - Root string `json:"root"` - Accounts map[string]DumpAccount `json:"accounts"` - // Next can be set to represent that this dump is only partial, and Next - // is where an iterator should be positioned in order to continue the dump. - Next []byte `json:"next,omitempty"` // nil if no more accounts -} - -// OnRoot implements DumpCollector interface -func (d *Dump) OnRoot(root common.Hash) { - d.Root = fmt.Sprintf("%x", root) -} - -// OnAccount implements DumpCollector interface -func (d *Dump) OnAccount(addr *common.Address, account DumpAccount) { - if addr == nil { - d.Accounts[fmt.Sprintf("pre(%s)", account.AddressHash)] = account - } - if addr != nil { - d.Accounts[(*addr).String()] = account - } -} - -// iterativeDump is a DumpCollector-implementation which dumps output line-by-line iteratively. -type iterativeDump struct { - *json.Encoder -} - -// OnAccount implements DumpCollector interface -func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) { - dumpAccount := &DumpAccount{ - Balance: account.Balance, - Nonce: account.Nonce, - Root: account.Root, - CodeHash: account.CodeHash, - Code: account.Code, - Storage: account.Storage, - AddressHash: account.AddressHash, - Address: addr, - } - d.Encode(dumpAccount) -} - -// OnRoot implements DumpCollector interface -func (d iterativeDump) OnRoot(root common.Hash) { - d.Encode(struct { - Root common.Hash `json:"root"` - }{root}) -} - -// DumpToCollector iterates the state according to the given options and inserts -// the items into a collector for aggregation or serialization. -func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) { - // Sanitize the input to allow nil configs - if conf == nil { - conf = new(DumpConfig) - } - var ( - missingPreimages int - accounts uint64 - start = time.Now() - logged = time.Now() - ) - log.Info("Trie dumping started", "root", s.trie.Hash()) - c.OnRoot(s.trie.Hash()) - - trieIt, err := s.trie.NodeIterator(conf.Start) - if err != nil { - log.Error("Trie dumping error", "err", err) - return nil - } - it := trie.NewIterator(trieIt) - for it.Next() { - var data types.StateAccount - if err := rlp.DecodeBytes(it.Value, &data); err != nil { - panic(err) - } - var ( - account = DumpAccount{ - Balance: data.Balance.String(), - Nonce: data.Nonce, - Root: data.Root[:], - CodeHash: data.CodeHash, - AddressHash: it.Key, - } - address *common.Address - addr common.Address - addrBytes = s.trie.GetKey(it.Key) - ) - if addrBytes == nil { - missingPreimages++ - if conf.OnlyWithAddresses { - continue - } - } else { - addr = common.BytesToAddress(addrBytes) - address = &addr - account.Address = address - } - obj := newObject(s, addr, &data) - if !conf.SkipCode { - account.Code = obj.Code() - } - if !conf.SkipStorage { - account.Storage = make(map[common.Hash]string) - tr, err := obj.getTrie() - if err != nil { - log.Error("Failed to load storage trie", "err", err) - continue - } - trieIt, err := tr.NodeIterator(nil) - if err != nil { - log.Error("Failed to create trie iterator", "err", err) - continue - } - storageIt := trie.NewIterator(trieIt) - for storageIt.Next() { - _, content, _, err := rlp.Split(storageIt.Value) - if err != nil { - log.Error("Failed to decode the value returned by iterator", "error", err) - continue - } - account.Storage[common.BytesToHash(s.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(content) - } - } - c.OnAccount(address, account) - accounts++ - if time.Since(logged) > 8*time.Second { - log.Info("Trie dumping in progress", "at", it.Key, "accounts", accounts, - "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - if conf.Max > 0 && accounts >= conf.Max { - if it.Next() { - nextKey = it.Key - } - break - } - } - if missingPreimages > 0 { - log.Warn("Dump incomplete due to missing preimages", "missing", missingPreimages) - } - log.Info("Trie dumping complete", "accounts", accounts, - "elapsed", common.PrettyDuration(time.Since(start))) - - return nextKey -} - -// RawDump returns the state. If the processing is aborted e.g. due to options -// reaching Max, the `Next` key is set on the returned Dump. -func (s *StateDB) RawDump(opts *DumpConfig) Dump { - dump := &Dump{ - Accounts: make(map[string]DumpAccount), - } - dump.Next = s.DumpToCollector(dump, opts) - return *dump -} - -// Dump returns a JSON string representing the entire state as a single json-object -func (s *StateDB) Dump(opts *DumpConfig) []byte { - dump := s.RawDump(opts) - json, err := json.MarshalIndent(dump, "", " ") - if err != nil { - log.Error("Error dumping state", "err", err) - } - return json -} - -// IterativeDump dumps out accounts as json-objects, delimited by linebreaks on stdout -func (s *StateDB) IterativeDump(opts *DumpConfig, output *json.Encoder) { - s.DumpToCollector(iterativeDump{output}, opts) -} diff --git a/builder/core/state/iterator.go b/builder/core/state/iterator.go deleted file mode 100644 index dc84ce689..000000000 --- a/builder/core/state/iterator.go +++ /dev/null @@ -1,171 +0,0 @@ -// 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 state - -import ( - "bytes" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -// nodeIterator is an iterator to traverse the entire state trie post-order, -// including all of the contract code and contract state tries. Preimage is -// required in order to resolve the contract address. -type nodeIterator struct { - state *StateDB // State being iterated - - stateIt trie.NodeIterator // Primary iterator for the global state trie - dataIt trie.NodeIterator // Secondary iterator for the data trie of a contract - - accountHash common.Hash // Hash of the node containing the account - codeHash common.Hash // Hash of the contract source code - code []byte // Source code associated with a contract - - Hash common.Hash // Hash of the current entry being iterated (nil if not standalone) - Parent common.Hash // Hash of the first full ancestor node (nil if current is the root) - - Error error // Failure set in case of an internal error in the iterator -} - -// newNodeIterator creates an post-order state node iterator. -func newNodeIterator(state *StateDB) *nodeIterator { - return &nodeIterator{ - state: state, - } -} - -// Next moves the iterator to the next node, returning whether there are any -// further nodes. In case of an internal error this method returns false and -// sets the Error field to the encountered failure. -func (it *nodeIterator) Next() bool { - // If the iterator failed previously, don't do anything - if it.Error != nil { - return false - } - // Otherwise step forward with the iterator and report any errors - if err := it.step(); err != nil { - it.Error = err - return false - } - return it.retrieve() -} - -// step moves the iterator to the next entry of the state trie. -func (it *nodeIterator) step() error { - // Abort if we reached the end of the iteration - if it.state == nil { - return nil - } - // Initialize the iterator if we've just started - var err error - if it.stateIt == nil { - it.stateIt, err = it.state.trie.NodeIterator(nil) - if err != nil { - return err - } - } - // If we had data nodes previously, we surely have at least state nodes - if it.dataIt != nil { - if cont := it.dataIt.Next(true); !cont { - if it.dataIt.Error() != nil { - return it.dataIt.Error() - } - it.dataIt = nil - } - return nil - } - // If we had source code previously, discard that - if it.code != nil { - it.code = nil - return nil - } - // Step to the next state trie node, terminating if we're out of nodes - if cont := it.stateIt.Next(true); !cont { - if it.stateIt.Error() != nil { - return it.stateIt.Error() - } - it.state, it.stateIt = nil, nil - return nil - } - // If the state trie node is an internal entry, leave as is - if !it.stateIt.Leaf() { - return nil - } - // Otherwise we've reached an account node, initiate data iteration - var account types.StateAccount - if err := rlp.DecodeBytes(it.stateIt.LeafBlob(), &account); err != nil { - return err - } - // Lookup the preimage of account hash - preimage := it.state.trie.GetKey(it.stateIt.LeafKey()) - if preimage == nil { - return errors.New("account address is not available") - } - address := common.BytesToAddress(preimage) - - // Traverse the storage slots belong to the account - dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root, it.state.trie) - if err != nil { - return err - } - it.dataIt, err = dataTrie.NodeIterator(nil) - if err != nil { - return err - } - if !it.dataIt.Next(true) { - it.dataIt = nil - } - if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { - it.codeHash = common.BytesToHash(account.CodeHash) - it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.CodeHash)) - if err != nil { - return fmt.Errorf("code %x: %v", account.CodeHash, err) - } - } - it.accountHash = it.stateIt.Parent() - return nil -} - -// retrieve pulls and caches the current state entry the iterator is traversing. -// The method returns whether there are any more data left for inspection. -func (it *nodeIterator) retrieve() bool { - // Clear out any previously set values - it.Hash = common.Hash{} - - // If the iteration's done, return no available data - if it.state == nil { - return false - } - // Otherwise retrieve the current entry - switch { - case it.dataIt != nil: - it.Hash, it.Parent = it.dataIt.Hash(), it.dataIt.Parent() - if it.Parent == (common.Hash{}) { - it.Parent = it.accountHash - } - case it.code != nil: - it.Hash, it.Parent = it.codeHash, it.accountHash - case it.stateIt != nil: - it.Hash, it.Parent = it.stateIt.Hash(), it.stateIt.Parent() - } - return true -} diff --git a/builder/core/state/iterator_test.go b/builder/core/state/iterator_test.go deleted file mode 100644 index 73cc22490..000000000 --- a/builder/core/state/iterator_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2016 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 state - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/crypto" -) - -// Tests that the node iterator indeed walks over the entire database contents. -func TestNodeIteratorCoverage(t *testing.T) { - testNodeIteratorCoverage(t, rawdb.HashScheme) - testNodeIteratorCoverage(t, rawdb.PathScheme) -} - -func testNodeIteratorCoverage(t *testing.T, scheme string) { - // Create some arbitrary test state to iterate - db, sdb, ndb, root, _ := makeTestState(scheme) - ndb.Commit(root, false) - - state, err := New(root, sdb, nil) - if err != nil { - t.Fatalf("failed to create state trie at %x: %v", root, err) - } - // Gather all the node hashes found by the iterator - hashes := make(map[common.Hash]struct{}) - for it := newNodeIterator(state); it.Next(); { - if it.Hash != (common.Hash{}) { - hashes[it.Hash] = struct{}{} - } - } - // Check in-disk nodes - var ( - seenNodes = make(map[common.Hash]struct{}) - seenCodes = make(map[common.Hash]struct{}) - ) - it := db.NewIterator(nil, nil) - for it.Next() { - ok, hash := isTrieNode(scheme, it.Key(), it.Value()) - if !ok { - continue - } - seenNodes[hash] = struct{}{} - } - it.Release() - - // Check in-disk codes - it = db.NewIterator(nil, nil) - for it.Next() { - ok, hash := rawdb.IsCodeKey(it.Key()) - if !ok { - continue - } - if _, ok := hashes[common.BytesToHash(hash)]; !ok { - t.Errorf("state entry not reported %x", it.Key()) - } - seenCodes[common.BytesToHash(hash)] = struct{}{} - } - it.Release() - - // Cross check the iterated hashes and the database/nodepool content - for hash := range hashes { - _, ok := seenNodes[hash] - if !ok { - _, ok = seenCodes[hash] - } - if !ok { - t.Errorf("failed to retrieve reported node %x", hash) - } - } -} - -// isTrieNode is a helper function which reports if the provided -// database entry belongs to a trie node or not. -func isTrieNode(scheme string, key, val []byte) (bool, common.Hash) { - if scheme == rawdb.HashScheme { - if rawdb.IsLegacyTrieNode(key, val) { - return true, common.BytesToHash(key) - } - } else { - ok := rawdb.IsAccountTrieNode(key) - if ok { - return true, crypto.Keccak256Hash(val) - } - ok = rawdb.IsStorageTrieNode(key) - if ok { - return true, crypto.Keccak256Hash(val) - } - } - return false, common.Hash{} -} diff --git a/builder/core/state/journal.go b/builder/core/state/journal.go deleted file mode 100644 index 6cdc1fc86..000000000 --- a/builder/core/state/journal.go +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright 2016 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 state - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" -) - -// journalEntry is a modification entry in the state change journal that can be -// reverted on demand. -type journalEntry interface { - // revert undoes the changes introduced by this journal entry. - revert(*StateDB) - - // dirtied returns the Ethereum address modified by this journal entry. - dirtied() *common.Address -} - -// journal contains the list of state modifications applied since the last state -// commit. These are tracked to be able to be reverted in the case of an execution -// exception or request for reversal. -type journal struct { - entries []journalEntry // Current changes tracked by the journal - dirties map[common.Address]int // Dirty accounts and the number of changes -} - -// newJournal creates a new initialized journal. -func newJournal() *journal { - return &journal{ - dirties: make(map[common.Address]int), - } -} - -// append inserts a new modification entry to the end of the change journal. -func (j *journal) append(entry journalEntry) { - j.entries = append(j.entries, entry) - if addr := entry.dirtied(); addr != nil { - j.dirties[*addr]++ - } -} - -// revert undoes a batch of journalled modifications along with any reverted -// dirty handling too. -func (j *journal) revert(statedb *StateDB, snapshot int) { - for i := len(j.entries) - 1; i >= snapshot; i-- { - // Undo the changes made by the operation - j.entries[i].revert(statedb) - - // Drop any dirty tracking induced by the change - if addr := j.entries[i].dirtied(); addr != nil { - if j.dirties[*addr]--; j.dirties[*addr] == 0 { - delete(j.dirties, *addr) - } - } - } - j.entries = j.entries[:snapshot] -} - -// dirty explicitly sets an address to dirty, even if the change entries would -// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD -// precompile consensus exception. -func (j *journal) dirty(addr common.Address) { - j.dirties[addr]++ -} - -// length returns the current number of entries in the journal. -func (j *journal) length() int { - return len(j.entries) -} - -type ( - // Changes to the account trie. - createObjectChange struct { - account *common.Address - } - resetObjectChange struct { - account *common.Address - prev *stateObject - prevdestruct bool - prevAccount []byte - prevStorage map[common.Hash][]byte - - prevAccountOriginExist bool - prevAccountOrigin []byte - prevStorageOrigin map[common.Hash][]byte - } - selfDestructChange struct { - account *common.Address - prev bool // whether account had already self-destructed - prevbalance *uint256.Int - } - - // Changes to individual accounts. - balanceChange struct { - account *common.Address - prev *uint256.Int - } - nonceChange struct { - account *common.Address - prev uint64 - } - storageChange struct { - account *common.Address - key, prevalue common.Hash - } - codeChange struct { - account *common.Address - prevcode, prevhash []byte - } - - // Changes to other state values. - refundChange struct { - prev uint64 - } - addLogChange struct { - txhash common.Hash - } - addPreimageChange struct { - hash common.Hash - } - touchChange struct { - account *common.Address - } - // Changes to the access list - accessListAddAccountChange struct { - address *common.Address - } - accessListAddSlotChange struct { - address *common.Address - slot *common.Hash - } - - transientStorageChange struct { - account *common.Address - key, prevalue common.Hash - } -) - -func (ch createObjectChange) revert(s *StateDB) { - delete(s.stateObjects, *ch.account) - delete(s.stateObjectsDirty, *ch.account) -} - -func (ch createObjectChange) dirtied() *common.Address { - return ch.account -} - -func (ch resetObjectChange) revert(s *StateDB) { - s.setStateObject(ch.prev) - if !ch.prevdestruct { - delete(s.stateObjectsDestruct, ch.prev.address) - } - if ch.prevAccount != nil { - s.accounts[ch.prev.addrHash] = ch.prevAccount - } - if ch.prevStorage != nil { - s.storages[ch.prev.addrHash] = ch.prevStorage - } - if ch.prevAccountOriginExist { - s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin - } - if ch.prevStorageOrigin != nil { - s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin - } -} - -func (ch resetObjectChange) dirtied() *common.Address { - return ch.account -} - -func (ch selfDestructChange) revert(s *StateDB) { - obj := s.getStateObject(*ch.account) - if obj != nil { - obj.selfDestructed = ch.prev - obj.setBalance(ch.prevbalance) - } -} - -func (ch selfDestructChange) dirtied() *common.Address { - return ch.account -} - -var ripemd = common.HexToAddress("0000000000000000000000000000000000000003") - -func (ch touchChange) revert(s *StateDB) { -} - -func (ch touchChange) dirtied() *common.Address { - return ch.account -} - -func (ch balanceChange) revert(s *StateDB) { - s.getStateObject(*ch.account).setBalance(ch.prev) -} - -func (ch balanceChange) dirtied() *common.Address { - return ch.account -} - -func (ch nonceChange) revert(s *StateDB) { - s.getStateObject(*ch.account).setNonce(ch.prev) -} - -func (ch nonceChange) dirtied() *common.Address { - return ch.account -} - -func (ch codeChange) revert(s *StateDB) { - s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) -} - -func (ch codeChange) dirtied() *common.Address { - return ch.account -} - -func (ch storageChange) revert(s *StateDB) { - s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) -} - -func (ch storageChange) dirtied() *common.Address { - return ch.account -} - -func (ch transientStorageChange) revert(s *StateDB) { - s.setTransientState(*ch.account, ch.key, ch.prevalue) -} - -func (ch transientStorageChange) dirtied() *common.Address { - return nil -} - -func (ch refundChange) revert(s *StateDB) { - s.refund = ch.prev -} - -func (ch refundChange) dirtied() *common.Address { - return nil -} - -func (ch addLogChange) revert(s *StateDB) { - logs := s.logs[ch.txhash] - if len(logs) == 1 { - delete(s.logs, ch.txhash) - } else { - s.logs[ch.txhash] = logs[:len(logs)-1] - } - s.logSize-- -} - -func (ch addLogChange) dirtied() *common.Address { - return nil -} - -func (ch addPreimageChange) revert(s *StateDB) { - delete(s.preimages, ch.hash) -} - -func (ch addPreimageChange) dirtied() *common.Address { - return nil -} - -func (ch accessListAddAccountChange) revert(s *StateDB) { - /* - One important invariant here, is that whenever a (addr, slot) is added, if the - addr is not already present, the add causes two journal entries: - - one for the address, - - one for the (address,slot) - Therefore, when unrolling the change, we can always blindly delete the - (addr) at this point, since no storage adds can remain when come upon - a single (addr) change. - */ - s.accessList.DeleteAddress(*ch.address) -} - -func (ch accessListAddAccountChange) dirtied() *common.Address { - return nil -} - -func (ch accessListAddSlotChange) revert(s *StateDB) { - s.accessList.DeleteSlot(*ch.address, *ch.slot) -} - -func (ch accessListAddSlotChange) dirtied() *common.Address { - return nil -} diff --git a/builder/core/state/metrics.go b/builder/core/state/metrics.go deleted file mode 100644 index d487356fc..000000000 --- a/builder/core/state/metrics.go +++ /dev/null @@ -1,40 +0,0 @@ -// 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 state - -import "github.com/ethereum/go-ethereum/metrics" - -var ( - accountUpdatedMeter = metrics.NewRegisteredMeter("state/update/account", nil) - storageUpdatedMeter = metrics.NewRegisteredMeter("state/update/storage", nil) - accountDeletedMeter = metrics.NewRegisteredMeter("state/delete/account", nil) - storageDeletedMeter = metrics.NewRegisteredMeter("state/delete/storage", nil) - accountTrieUpdatedMeter = metrics.NewRegisteredMeter("state/update/accountnodes", nil) - storageTriesUpdatedMeter = metrics.NewRegisteredMeter("state/update/storagenodes", nil) - accountTrieDeletedMeter = metrics.NewRegisteredMeter("state/delete/accountnodes", nil) - storageTriesDeletedMeter = metrics.NewRegisteredMeter("state/delete/storagenodes", nil) - - stateCopyMeter = metrics.NewRegisteredMeter("state/copy", nil) - stateSnapshotMeter = metrics.NewRegisteredMeter("state/snapshot", nil) - - slotDeletionMaxCount = metrics.NewRegisteredGauge("state/delete/storage/max/slot", nil) - slotDeletionMaxSize = metrics.NewRegisteredGauge("state/delete/storage/max/size", nil) - slotDeletionTimer = metrics.NewRegisteredResettingTimer("state/delete/storage/timer", nil) - slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil) - slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil) - slotDeletionSkip = metrics.NewRegisteredGauge("state/delete/storage/skip", nil) -) diff --git a/builder/core/state/multi_tx_snapshot.go b/builder/core/state/multi_tx_snapshot.go deleted file mode 100644 index 670b6a684..000000000 --- a/builder/core/state/multi_tx_snapshot.go +++ /dev/null @@ -1,728 +0,0 @@ -package state - -import ( - "errors" - "fmt" - "reflect" - - "github.com/ethereum/go-ethereum/crypto" - "github.com/holiman/uint256" - - "github.com/ethereum/go-ethereum/common" -) - -// MultiTxSnapshot retains StateDB changes for multiple transactions. -type MultiTxSnapshot struct { - invalid bool - - numLogsAdded map[common.Hash]int - - prevObjects map[common.Address]*resetObjectChange - - accountStorage map[common.Address]map[common.Hash]*common.Hash - accountBalance map[common.Address]*uint256.Int - accountNonce map[common.Address]uint64 - accountCode map[common.Address][]byte - accountCodeHash map[common.Address][]byte - - accountSelfDestruct map[common.Address]bool - accountDeleted map[common.Address]bool - - accountNotPending map[common.Address]struct{} - accountNotDirty map[common.Address]struct{} - - // touched accounts are accounts that can be affected when snapshot is reverted - // we clear dirty storage for touched accounts when snapshot is reverted - touchedAccounts map[common.Address]struct{} - - // TODO: snapdestructs, snapaccount storage -} - -// NewMultiTxSnapshot creates a new MultiTxSnapshot -func NewMultiTxSnapshot() *MultiTxSnapshot { - multiTxSnapshot := newMultiTxSnapshot() - return &multiTxSnapshot -} - -func newMultiTxSnapshot() MultiTxSnapshot { - return MultiTxSnapshot{ - numLogsAdded: make(map[common.Hash]int), - prevObjects: make(map[common.Address]*resetObjectChange), - accountStorage: make(map[common.Address]map[common.Hash]*common.Hash), - accountBalance: make(map[common.Address]*uint256.Int), - accountNonce: make(map[common.Address]uint64), - accountCode: make(map[common.Address][]byte), - accountCodeHash: make(map[common.Address][]byte), - accountSelfDestruct: make(map[common.Address]bool), - accountDeleted: make(map[common.Address]bool), - accountNotPending: make(map[common.Address]struct{}), - accountNotDirty: make(map[common.Address]struct{}), - touchedAccounts: make(map[common.Address]struct{}), - } -} - -func (s MultiTxSnapshot) Copy() MultiTxSnapshot { - newSnapshot := newMultiTxSnapshot() - newSnapshot.invalid = s.invalid - - for txHash, numLogs := range s.numLogsAdded { - newSnapshot.numLogsAdded[txHash] = numLogs - } - - for address, object := range s.prevObjects { - newSnapshot.prevObjects[address] = object - } - - for address, storage := range s.accountStorage { - newSnapshot.accountStorage[address] = make(map[common.Hash]*common.Hash) - for key, value := range storage { - newSnapshot.accountStorage[address][key] = value - } - } - - for address, balance := range s.accountBalance { - newSnapshot.accountBalance[address] = balance - } - - for address, nonce := range s.accountNonce { - newSnapshot.accountNonce[address] = nonce - } - - for address, code := range s.accountCode { - newSnapshot.accountCode[address] = code - } - - for address, codeHash := range s.accountCodeHash { - newSnapshot.accountCodeHash[address] = codeHash - } - - for address, selfDestructed := range s.accountSelfDestruct { - newSnapshot.accountSelfDestruct[address] = selfDestructed - } - - for address, deleted := range s.accountDeleted { - newSnapshot.accountDeleted[address] = deleted - } - - for address := range s.accountNotPending { - newSnapshot.accountNotPending[address] = struct{}{} - } - - for address := range s.accountNotDirty { - newSnapshot.accountNotDirty[address] = struct{}{} - } - - for address := range s.touchedAccounts { - newSnapshot.touchedAccounts[address] = struct{}{} - } - - return newSnapshot -} - -// Equal returns true if the two MultiTxSnapshot are equal -func (s *MultiTxSnapshot) Equal(other *MultiTxSnapshot) bool { - if other == nil { - return false - } - if s.invalid != other.invalid { - return false - } - - visited := make(map[common.Address]bool) - for address, obj := range other.prevObjects { - current, exist := s.prevObjects[address] - if !exist { - return false - } - if current == nil && obj != nil { - return false - } - - if current != nil && obj == nil { - return false - } - - visited[address] = true - } - - for address, obj := range s.prevObjects { - if visited[address] { - continue - } - - otherObject, exist := other.prevObjects[address] - if !exist { - return false - } - - if otherObject == nil && obj != nil { - return false - } - - if otherObject != nil && obj == nil { - return false - } - } - - return reflect.DeepEqual(s.numLogsAdded, other.numLogsAdded) && - reflect.DeepEqual(s.accountStorage, other.accountStorage) && - reflect.DeepEqual(s.accountBalance, other.accountBalance) && - reflect.DeepEqual(s.accountNonce, other.accountNonce) && - reflect.DeepEqual(s.accountCode, other.accountCode) && - reflect.DeepEqual(s.accountCodeHash, other.accountCodeHash) && - reflect.DeepEqual(s.accountSelfDestruct, other.accountSelfDestruct) && - reflect.DeepEqual(s.accountDeleted, other.accountDeleted) && - reflect.DeepEqual(s.accountNotPending, other.accountNotPending) && - reflect.DeepEqual(s.accountNotDirty, other.accountNotDirty) && - reflect.DeepEqual(s.touchedAccounts, other.touchedAccounts) -} - -// updateFromJournal updates the snapshot with the changes from the journal. -func (s *MultiTxSnapshot) updateFromJournal(journal *journal) { - for _, journalEntry := range journal.entries { - switch entry := journalEntry.(type) { - case balanceChange: - s.updateBalanceChange(entry) - case nonceChange: - s.updateNonceChange(entry) - case codeChange: - s.updateCodeChange(entry) - case addLogChange: - s.numLogsAdded[entry.txhash]++ - case createObjectChange: - s.updateCreateObjectChange(entry) - case resetObjectChange: - s.updateResetObjectChange(entry) - case storageChange: - s.updatePendingStorage(*entry.account, entry.key, entry.prevalue, true) - case selfDestructChange: - s.updateSelfDestructChange(entry) - } - } -} - -// objectChanged returns whether the object was changed (in the set of prevObjects), which can happen -// because of self-destructs and deployments. -func (s *MultiTxSnapshot) objectChanged(address common.Address) bool { - _, ok := s.prevObjects[address] - return ok -} - -// updateBalanceChange updates the snapshot with the balance change. -func (s *MultiTxSnapshot) updateBalanceChange(change balanceChange) { - s.touchedAccounts[*change.account] = struct{}{} - if s.objectChanged(*change.account) { - return - } - if _, ok := s.accountBalance[*change.account]; !ok { - s.accountBalance[*change.account] = change.prev - } -} - -// updateNonceChange updates the snapshot with the nonce change. -func (s *MultiTxSnapshot) updateNonceChange(change nonceChange) { - s.touchedAccounts[*change.account] = struct{}{} - if s.objectChanged(*change.account) { - return - } - if _, ok := s.accountNonce[*change.account]; !ok { - s.accountNonce[*change.account] = change.prev - } -} - -// updateCodeChange updates the snapshot with the code change. -func (s *MultiTxSnapshot) updateCodeChange(change codeChange) { - s.touchedAccounts[*change.account] = struct{}{} - if s.objectChanged(*change.account) { - return - } - if _, ok := s.accountCode[*change.account]; !ok { - s.accountCode[*change.account] = change.prevcode - s.accountCodeHash[*change.account] = change.prevhash - } -} - -// updateResetObjectChange updates the snapshot with the reset object change. -func (s *MultiTxSnapshot) updateResetObjectChange(change resetObjectChange) { - s.touchedAccounts[change.prev.address] = struct{}{} - address := change.prev.address - if _, exists := s.prevObjects[address]; !exists { - s.prevObjects[address] = &resetObjectChange{ - account: change.account, - prev: change.prev, - prevdestruct: change.prevdestruct, - prevAccount: change.prevAccount, - prevStorage: change.prevStorage, - prevAccountOriginExist: change.prevAccountOriginExist, - prevAccountOrigin: change.prevAccountOrigin, - prevStorageOrigin: change.prevStorageOrigin, - } - } -} - -// updateCreateObjectChange updates the snapshot with the createObjectChange. -func (s *MultiTxSnapshot) updateCreateObjectChange(change createObjectChange) { - s.touchedAccounts[*change.account] = struct{}{} - if _, ok := s.prevObjects[*change.account]; !ok { - s.prevObjects[*change.account] = nil - } -} - -// updateSelfDestructChange updates the snapshot with the suicide change. -func (s *MultiTxSnapshot) updateSelfDestructChange(change selfDestructChange) { - s.touchedAccounts[*change.account] = struct{}{} - if s.objectChanged(*change.account) { - return - } - if _, ok := s.accountSelfDestruct[*change.account]; !ok { - s.accountSelfDestruct[*change.account] = change.prev - } - if _, ok := s.accountBalance[*change.account]; !ok { - s.accountBalance[*change.account] = change.prevbalance - } -} - -// updatePendingStorage updates the snapshot with the pending storage change. -func (s *MultiTxSnapshot) updatePendingStorage(address common.Address, key, value common.Hash, ok bool) { - s.touchedAccounts[address] = struct{}{} - if s.objectChanged(address) { - return - } - if _, exists := s.accountStorage[address]; !exists { - s.accountStorage[address] = make(map[common.Hash]*common.Hash) - } - if _, exists := s.accountStorage[address][key]; exists { - return - } - if ok { - s.accountStorage[address][key] = &value - } else { - s.accountStorage[address][key] = nil - } -} - -// updatePendingStatus updates the snapshot with previous pending status. -func (s *MultiTxSnapshot) updatePendingStatus(address common.Address, pending, dirty bool) { - s.touchedAccounts[address] = struct{}{} - if !pending { - s.accountNotPending[address] = struct{}{} - } - if !dirty { - s.accountNotDirty[address] = struct{}{} - } -} - -// updateObjectDeleted updates the snapshot with the object deletion. -func (s *MultiTxSnapshot) updateObjectDeleted(address common.Address, deleted bool) { - s.touchedAccounts[address] = struct{}{} - if s.objectChanged(address) { - return - } - if _, ok := s.accountDeleted[address]; !ok { - s.accountDeleted[address] = deleted - } -} - -// Merge merges the changes from another snapshot into the current snapshot. -// The operation assumes that the other snapshot is later (newer) than the current snapshot. -// Changes are merged such that older state is retained and not overwritten. -// In other words, this method performs a union operation on two snapshots, where -// older values are retained and any new values are added to the current snapshot. -func (s *MultiTxSnapshot) Merge(other *MultiTxSnapshot) error { - if other.invalid || s.invalid { - return errors.New("failed to merge snapshots - invalid snapshot found") - } - - // each snapshot increments the number of logs per transaction hash - // when we merge snapshots, the number of logs added per transaction are appended to current snapshot - for txHash, numLogs := range other.numLogsAdded { - s.numLogsAdded[txHash] += numLogs - } - - // prevObjects contain mapping of address to state objects - // if the current snapshot has previous object for same address, retain previous object - // otherwise, add new object from other snapshot - for address, object := range other.prevObjects { - if _, exist := s.prevObjects[address]; !exist { - s.prevObjects[address] = object - } - } - - // merge account storage - - // we want to retain any existing storage values for a given account, - // update storage keys if they do not exist for a given account's storage, - // and update pending storage for accounts that don't already exist in current snapshot - for address, storage := range other.accountStorage { - if s.objectChanged(address) { - continue - } - - if _, exist := s.accountStorage[address]; !exist { - s.accountStorage[address] = make(map[common.Hash]*common.Hash) - s.accountStorage[address] = storage - continue - } - - for key, value := range storage { - if _, exists := s.accountStorage[address][key]; !exists { - s.accountStorage[address][key] = value - } - } - } - - // add previous balance(s) for any addresses that don't exist in current snapshot - for address, balance := range other.accountBalance { - if s.objectChanged(address) { - continue - } - - if _, exist := s.accountBalance[address]; !exist { - s.accountBalance[address] = balance - } - } - - // add previous nonce for accounts that don't exist in current snapshot - for address, nonce := range other.accountNonce { - if s.objectChanged(address) { - continue - } - if _, exist := s.accountNonce[address]; !exist { - s.accountNonce[address] = nonce - } - } - - // add previous code for accounts not found in current snapshot - for address, code := range other.accountCode { - if s.objectChanged(address) { - continue - } - if _, exist := s.accountCode[address]; !exist { - if _, found := other.accountCodeHash[address]; !found { - // every codeChange has code and code hash set - - // should never reach this point unless there is programming error - panic("snapshot merge found code but no code hash for account address") - } - - s.accountCode[address] = code - s.accountCodeHash[address] = other.accountCodeHash[address] - } - } - - // add previous suicide for addresses not in current snapshot - for address, suicided := range other.accountSelfDestruct { - if s.objectChanged(address) { - continue - } - - if _, exist := s.accountSelfDestruct[address]; !exist { - s.accountSelfDestruct[address] = suicided - } else { - return errors.New("failed to merge snapshots - duplicate found for account suicide") - } - } - - // add previous account deletions if they don't exist - for address, deleted := range other.accountDeleted { - if s.objectChanged(address) { - continue - } - if _, exist := s.accountDeleted[address]; !exist { - s.accountDeleted[address] = deleted - } - } - - // add previous pending status if not found - for address := range other.accountNotPending { - if _, exist := s.accountNotPending[address]; !exist { - s.accountNotPending[address] = struct{}{} - } - } - - for address := range other.accountNotDirty { - if _, exist := s.accountNotDirty[address]; !exist { - s.accountNotDirty[address] = struct{}{} - } - } - - for address := range other.touchedAccounts { - s.touchedAccounts[address] = struct{}{} - } - - return nil -} - -// revertState reverts the state to the snapshot. -func (s *MultiTxSnapshot) revertState(st *StateDB) { - // remove all the logs added - for txhash, numLogs := range s.numLogsAdded { - lens := len(st.logs[txhash]) - if lens == numLogs { - delete(st.logs, txhash) - } else { - st.logs[txhash] = st.logs[txhash][:lens-numLogs] - } - st.logSize -= uint(numLogs) - } - - keccaker := crypto.NewKeccakState() - // restore the objects - for address, object := range s.prevObjects { - if object == nil { - delete(st.stateObjects, address) - delete(st.stateObjectsDestruct, address) - - addrHash := crypto.HashData(keccaker, address[:]) - delete(st.accounts, addrHash) - delete(st.storages, addrHash) - delete(st.accountsOrigin, address) - delete(st.storagesOrigin, address) - } else { - st.stateObjects[address] = object.prev - if object.prevAccount != nil { - st.accounts[object.prev.addrHash] = object.prevAccount - } - - if object.prevStorage != nil { - st.storages[object.prev.addrHash] = object.prevStorage - } - - if object.prevAccountOriginExist { - st.accountsOrigin[object.prev.address] = object.prevAccountOrigin - } - - if object.prevStorageOrigin != nil { - st.storagesOrigin[object.prev.address] = object.prevStorageOrigin - } - } - } - - // restore storage - for address, storage := range s.accountStorage { - st.stateObjects[address].dirtyStorage = make(Storage) - for key, value := range storage { - if value == nil { - if _, ok := st.stateObjects[address].pendingStorage[key]; !ok { - panic(fmt.Sprintf("storage key %x not found in pending storage", key)) - } - delete(st.stateObjects[address].pendingStorage, key) - } else { - if _, ok := st.stateObjects[address].pendingStorage[key]; !ok { - panic(fmt.Sprintf("storage key %x not found in pending storage", key)) - } - st.stateObjects[address].pendingStorage[key] = *value - } - } - } - - // restore balance - for address, balance := range s.accountBalance { - st.stateObjects[address].setBalance(balance) - } - // restore nonce - for address, nonce := range s.accountNonce { - st.stateObjects[address].setNonce(nonce) - } - // restore code - for address, code := range s.accountCode { - st.stateObjects[address].setCode(common.BytesToHash(s.accountCodeHash[address]), code) - } - // restore selfdestructed - for address, suicided := range s.accountSelfDestruct { - st.stateObjects[address].selfDestructed = suicided - } - // restore deleted - for address, deleted := range s.accountDeleted { - st.stateObjects[address].deleted = deleted - } - - // restore pending status - for address := range s.accountNotPending { - delete(st.stateObjectsPending, address) - } - for address := range s.accountNotDirty { - delete(st.stateObjectsDirty, address) - } - - // clean dirty state of touched accounts - for address := range s.touchedAccounts { - if obj, ok := st.stateObjects[address]; ok { - obj.dirtyStorage = make(Storage) - } - } -} - -// MultiTxSnapshotStack contains a list of snapshots for multiple transactions associated with a StateDB. -// Intended use is as follows: -// - Create a new snapshot and push on top of the stack -// - Apply transactions to state and update head snapshot with changes from journal -// - If any changes applied to state database are committed to trie, invalidate the head snapshot -// - If applied changes are not desired, revert the changes from the head snapshot and pop the snapshot from the stack -// - If applied changes are desired, commit the changes from the head snapshot by merging with previous entry -// and pop the snapshot from the stack -type MultiTxSnapshotStack struct { - snapshots []MultiTxSnapshot - state *StateDB -} - -// NewMultiTxSnapshotStack creates a new MultiTxSnapshotStack with a given StateDB. -func NewMultiTxSnapshotStack(state *StateDB) *MultiTxSnapshotStack { - return &MultiTxSnapshotStack{ - snapshots: make([]MultiTxSnapshot, 0), - state: state, - } -} - -// NewSnapshot creates a new snapshot and pushes it on top of the stack. -func (stack *MultiTxSnapshotStack) NewSnapshot() (*MultiTxSnapshot, error) { - if len(stack.snapshots) > 0 && stack.snapshots[len(stack.snapshots)-1].invalid { - return nil, errors.New("failed to create new multi-transaction snapshot - invalid snapshot found at head") - } - - snap := newMultiTxSnapshot() - stack.snapshots = append(stack.snapshots, snap) - return &snap, nil -} - -func (stack *MultiTxSnapshotStack) Copy(statedb *StateDB) *MultiTxSnapshotStack { - newStack := NewMultiTxSnapshotStack(statedb) - for _, snapshot := range stack.snapshots { - newStack.snapshots = append(newStack.snapshots, snapshot.Copy()) - } - return newStack -} - -// Peek returns the snapshot at the top of the stack. -func (stack *MultiTxSnapshotStack) Peek() *MultiTxSnapshot { - if len(stack.snapshots) == 0 { - return nil - } - return &stack.snapshots[len(stack.snapshots)-1] -} - -// Pop removes the snapshot at the top of the stack and returns it. -func (stack *MultiTxSnapshotStack) Pop() (*MultiTxSnapshot, error) { - size := len(stack.snapshots) - if size == 0 { - return nil, errors.New("failed to revert multi-transaction snapshot - does not exist") - } - - head := &stack.snapshots[size-1] - stack.snapshots = stack.snapshots[:size-1] - return head, nil -} - -// Revert rewinds the changes from the head snapshot and removes it from the stack. -func (stack *MultiTxSnapshotStack) Revert() (*MultiTxSnapshot, error) { - size := len(stack.snapshots) - if size == 0 { - return nil, errors.New("failed to revert multi-transaction snapshot - does not exist") - } - - head := &stack.snapshots[size-1] - if head.invalid { - return nil, errors.New("failed to revert multi-transaction snapshot - invalid snapshot found") - } - - head.revertState(stack.state) - stack.snapshots = stack.snapshots[:size-1] - return head, nil -} - -// RevertAll reverts all snapshots in the stack. -func (stack *MultiTxSnapshotStack) RevertAll() (snapshot *MultiTxSnapshot, err error) { - for len(stack.snapshots) > 0 { - if snapshot, err = stack.Revert(); err != nil { - break - } - } - return -} - -// Commit merges the changes from the head snapshot with the previous snapshot and removes it from the stack. -func (stack *MultiTxSnapshotStack) Commit() (*MultiTxSnapshot, error) { - if len(stack.snapshots) == 0 { - return nil, errors.New("failed to commit multi-transaction snapshot - does not exist") - } - - if len(stack.snapshots) == 1 { - return stack.Pop() - } - - var ( - head *MultiTxSnapshot - err error - ) - if head, err = stack.Pop(); err != nil { - return nil, err - } - - current := stack.Peek() - if err = current.Merge(head); err != nil { - return nil, err - } - - stack.snapshots[len(stack.snapshots)-1] = *current - return head, nil -} - -// Size returns the number of snapshots in the stack. -func (stack *MultiTxSnapshotStack) Size() int { - return len(stack.snapshots) -} - -// Invalidate invalidates the latest snapshot. This is used when state changes are committed to trie. -func (stack *MultiTxSnapshotStack) Invalidate() { - size := len(stack.snapshots) - if size == 0 { - return - } - - head := stack.snapshots[size-1] - head.invalid = true - stack.snapshots = stack.snapshots[:0] - stack.snapshots = append(stack.snapshots, head) -} - -// UpdatePendingStatus updates the pending status for an address. -func (stack *MultiTxSnapshotStack) UpdatePendingStatus(address common.Address, pending, dirty bool) { - if len(stack.snapshots) == 0 { - return - } - - current := stack.Peek() - current.updatePendingStatus(address, pending, dirty) - stack.snapshots[len(stack.snapshots)-1] = *current -} - -// UpdatePendingStorage updates the pending storage for an address. -func (stack *MultiTxSnapshotStack) UpdatePendingStorage(address common.Address, key, value common.Hash, ok bool) { - if len(stack.snapshots) == 0 { - return - } - - current := stack.Peek() - current.updatePendingStorage(address, key, value, ok) - stack.snapshots[len(stack.snapshots)-1] = *current -} - -// UpdateFromJournal updates the snapshot with the changes from the journal. -func (stack *MultiTxSnapshotStack) UpdateFromJournal(journal *journal) { - if len(stack.snapshots) == 0 { - return - } - - current := stack.Peek() - current.updateFromJournal(journal) - stack.snapshots[len(stack.snapshots)-1] = *current -} - -// UpdateObjectDeleted updates the snapshot with the object deletion. -func (stack *MultiTxSnapshotStack) UpdateObjectDeleted(address common.Address, deleted bool) { - if len(stack.snapshots) == 0 { - return - } - - current := stack.Peek() - current.updateObjectDeleted(address, deleted) - stack.snapshots[len(stack.snapshots)-1] = *current -} diff --git a/builder/core/state/multi_tx_snapshot_test.go b/builder/core/state/multi_tx_snapshot_test.go deleted file mode 100644 index f8d8fb841..000000000 --- a/builder/core/state/multi_tx_snapshot_test.go +++ /dev/null @@ -1,931 +0,0 @@ -package state - -import ( - "bytes" - "fmt" - "math/rand" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" -) - -var ( - addrs []common.Address - keys []common.Hash - - rng *rand.Rand -) - -func init() { - for i := 0; i < 20; i++ { - addrs = append(addrs, common.HexToAddress(fmt.Sprintf("0x%02x", i))) - } - for i := 0; i < 100; i++ { - keys = append(keys, common.HexToHash(fmt.Sprintf("0x%02x", i))) - } -} - -type observableAccountState struct { - address common.Address - balance *uint256.Int - nonce uint64 - code []byte - codeHash common.Hash - codeSize int - - state map[common.Hash]common.Hash - committedState map[common.Hash]common.Hash - - selfDestruct bool - exist bool - empty bool -} - -func getObservableAccountState(s *StateDB, address common.Address, storageKeys []common.Hash) *observableAccountState { - state := &observableAccountState{ - address: address, - balance: s.GetBalance(address), - nonce: s.GetNonce(address), - code: s.GetCode(address), - codeHash: s.GetCodeHash(address), - codeSize: s.GetCodeSize(address), - state: make(map[common.Hash]common.Hash), - committedState: make(map[common.Hash]common.Hash), - selfDestruct: s.HasSelfDestructed(address), - exist: s.Exist(address), - empty: s.Empty(address), - } - - for _, key := range storageKeys { - state.state[key] = s.GetState(address, key) - state.committedState[key] = s.GetCommittedState(address, key) - } - - return state -} - -func verifyObservableAccountState(s *StateDB, observed *observableAccountState) error { - if s.GetBalance(observed.address).Cmp(observed.balance) != 0 { - return fmt.Errorf("balance mismatch %v != %v", s.GetBalance(observed.address), observed.balance) - } - if s.GetNonce(observed.address) != observed.nonce { - return fmt.Errorf("nonce mismatch %v != %v", s.GetNonce(observed.address), observed.nonce) - } - if !bytes.Equal(s.GetCode(observed.address), observed.code) { - return fmt.Errorf("code mismatch %v != %v", s.GetCode(observed.address), observed.code) - } - if s.GetCodeHash(observed.address) != observed.codeHash { - return fmt.Errorf("code hash mismatch %v != %v", s.GetCodeHash(observed.address), observed.codeHash) - } - if s.GetCodeSize(observed.address) != observed.codeSize { - return fmt.Errorf("code size mismatch %v != %v", s.GetCodeSize(observed.address), observed.codeSize) - } - for key, value := range observed.state { - found := s.GetState(observed.address, key) - if found != value { - return fmt.Errorf("state mismatch [key: %s] value %v != %v", key.String(), found, value) - } - } - for key, value := range observed.committedState { - found := s.GetCommittedState(observed.address, key) - if found != value { - return fmt.Errorf("committed state mismatch %v != %v", found, value) - } - } - if s.HasSelfDestructed(observed.address) != observed.selfDestruct { - return fmt.Errorf("self destruct mismatch %v != %v", s.HasSelfDestructed(observed.address), observed.selfDestruct) - } - if s.Exist(observed.address) != observed.exist { - return fmt.Errorf("exist mismatch %v != %v", s.Exist(observed.address), observed.exist) - } - if s.Empty(observed.address) != observed.empty { - return fmt.Errorf("empty mismatch %v != %v", s.Empty(observed.address), observed.empty) - } - return nil -} - -func randomBytes(n int) []byte { - b := make([]byte, n) - _, err := rng.Read(b) - if err != nil { - panic(err) - } - return b -} - -func randomHash() common.Hash { - return common.BytesToHash(randomBytes(32)) -} - -func randFillAccountState(addr common.Address, s *StateDB) { - for i, key := range keys { - // Fill some keys with zero value, others with random value - if i%5 == 0 { - s.SetState(addr, key, common.BigToHash(common.Big0)) - } else { - s.SetState(addr, key, randomHash()) - } - } -} - -func genRandomAccountState(seed int64) map[common.Address]map[common.Hash]common.Hash { - rng = rand.New(rand.NewSource(seed)) - - state := make(map[common.Address]map[common.Hash]common.Hash) - - for _, addr := range addrs { - state[addr] = make(map[common.Hash]common.Hash) - for i, key := range keys { - if i%5 == 0 { - state[addr][key] = common.BigToHash(common.Big0) - } else { - state[addr][key] = randomHash() - } - } - } - - return state -} - -func randFillAccount(addr common.Address, s *StateDB) { - s.SetNonce(addr, rng.Uint64()) - s.SetBalance(addr, uint256.NewInt(rng.Uint64())) - s.SetCode(addr, randomBytes(rng.Intn(100))) - randFillAccountState(addr, s) -} - -func prepareInitialState(s *StateDB) { - // We neet to create realistic state for statedb - // for this we apply some changes - // 1. Before calling intermediateRoot - // 2. After calling intermediateRoot but before calling Finalise - rng = rand.New(rand.NewSource(0)) - - var beforeCommitHooks, afterCommitHooks []func(addr common.Address, s *StateDB) - addAccount := func(beforeCommit, afterCommit func(addr common.Address, s *StateDB)) { - beforeCommitHooks = append(beforeCommitHooks, beforeCommit) - afterCommitHooks = append(afterCommitHooks, afterCommit) - } - - addAccount(func(addr common.Address, s *StateDB) { - s.SetNonce(addr, rng.Uint64()) - }, nil) - addAccount(nil, func(addr common.Address, s *StateDB) { - s.SetNonce(addr, rng.Uint64()) - }) - addAccount(func(addr common.Address, s *StateDB) { - s.SetNonce(addr, rng.Uint64()) - }, func(addr common.Address, s *StateDB) { - s.SetNonce(addr, rng.Uint64()) - }) - - addAccount(func(addr common.Address, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(rng.Uint64())) - }, nil) - addAccount(nil, func(addr common.Address, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(rng.Uint64())) - }) - addAccount(func(addr common.Address, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(rng.Uint64())) - }, func(addr common.Address, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(rng.Uint64())) - }) - - addAccount(func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - }, nil) - addAccount(nil, func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - }) - addAccount(func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - s.SetCode(addr, nil) - }, func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - }) - addAccount(func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - s.SelfDestruct(addr) - }, func(addr common.Address, s *StateDB) { - s.SetCode(addr, randomBytes(rng.Intn(100))) - }) - - addAccount(func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - s.SelfDestruct(addr) - }, nil) - addAccount(nil, func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - s.SelfDestruct(addr) - }) - addAccount(func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - }, func(addr common.Address, s *StateDB) { - s.SelfDestruct(addr) - }) - addAccount(func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - s.SelfDestruct(addr) - }, func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - }) - addAccount(func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - s.SelfDestruct(addr) - }, func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - // calling it twice is possible - s.SelfDestruct(addr) - s.SelfDestruct(addr) - }) - - addAccount(func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - }, nil) - addAccount(nil, func(addr common.Address, s *StateDB) { - randFillAccount(addr, s) - }) - - for i, beforeHook := range beforeCommitHooks { - if beforeHook != nil { - beforeHook(addrs[i], s) - } - } - s.IntermediateRoot(true) - - for i, afterHook := range afterCommitHooks { - if afterHook != nil { - afterHook(addrs[i], s) - } - } - - s.Finalise(true) -} - -func testMultiTxSnapshot(t *testing.T, actions func(s *StateDB)) { - s := newStateEnv() - prepareInitialState(s.state) - - previousRefund := s.state.GetRefund() - - var obsStates []*observableAccountState - for _, account := range addrs { - obsStates = append(obsStates, getObservableAccountState(s.state, account, keys)) - } - - pendingAddressesBefore := make(map[common.Address]struct{}) - for k, v := range s.state.stateObjectsPending { - pendingAddressesBefore[k] = v - } - dirtyAddressesBefore := make(map[common.Address]struct{}) - for k, v := range s.state.stateObjectsDirty { - dirtyAddressesBefore[k] = v - } - - err := s.state.NewMultiTxSnapshot() - if err != nil { - t.Fatal("MultiTxSnapshot failed", err) - } - - if actions != nil { - actions(s.state) - } - - err = s.state.MultiTxSnapshotRevert() - if err != nil { - t.Fatal("MultiTxSnapshotRevert failed", err) - } - - for _, obsState := range obsStates { - err := verifyObservableAccountState(s.state, obsState) - if err != nil { - t.Error("state mismatch", "account", obsState.address, err) - } - } - - if s.state.GetRefund() != previousRefund { - t.Error("refund mismatch", "got", s.state.GetRefund(), "expected", previousRefund) - } - - if len(s.state.stateObjectsPending) != len(pendingAddressesBefore) { - t.Error("pending state objects count mismatch", "got", len(s.state.stateObjectsPending), "expected", len(pendingAddressesBefore)) - } - for k := range s.state.stateObjectsPending { - if _, ok := pendingAddressesBefore[k]; !ok { - t.Error("stateObjectsPending mismatch, before was nil", "address", k) - } - } - if len(s.state.stateObjectsDirty) != len(dirtyAddressesBefore) { - t.Error("dirty state objects count mismatch", "got", len(s.state.stateObjectsDirty), "expected", len(dirtyAddressesBefore)) - } - for k := range s.state.stateObjectsDirty { - if _, ok := dirtyAddressesBefore[k]; !ok { - t.Error("stateObjectsDirty mismatch, before was nil", "address", k) - } - } - - root := s.state.IntermediateRoot(true) - - cleanState := newStateEnv() - prepareInitialState(cleanState.state) - expectedRoot := cleanState.state.IntermediateRoot(true) - - if root != expectedRoot { - t.Error("root mismatch", "got", root, "expected", expectedRoot) - } -} - -func TestMultiTxSnapshotAccountChangesSimple(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - } - s.Finalise(true) - }) -} - -// This test verifies that dirty account storage is properly cleaned for accounts after revert -func TestMultiTxSnapshotAccountChangesRevertedByJournal(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetState(addr, common.HexToHash("0x01"), common.HexToHash("0x03")) - } - s.Finalise(true) - for _, addr := range addrs { - // we use normal snapshot here because it - // 1. does not mark an account dirty (even though we applied changes) - // 2. changes dirty, uncommitted state of the account - snap := s.Snapshot() - s.SetState(addr, common.HexToHash("0x01"), common.HexToHash("0x02")) - s.RevertToSnapshot(snap) - } - s.Finalise(true) - }) -} - -func TestMultiTxSnapshotRefund(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - } - s.Finalise(true) - }) -} - -func TestMultiTxSnapshotAccountChangesMultiTx(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - } - s.Finalise(true) - - for _, addr := range addrs { - s.SetNonce(addr, 79) - s.SetBalance(addr, uint256.NewInt(80)) - s.SetCode(addr, []byte{0x81}) - } - s.Finalise(true) - }) -} - -func TestMultiTxSnapshotAccountChangesSelfDestruct(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - } - s.Finalise(true) - - for _, addr := range addrs { - s.SelfDestruct(addr) - } - s.Finalise(true) - - for _, addr := range addrs { - s.SetNonce(addr, 79) - s.SetBalance(addr, uint256.NewInt(80)) - s.SetCode(addr, []byte{0x81}) - } - s.Finalise(true) - }) -} - -func TestMultiTxSnapshotAccountChangesEmptyAccount(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - } - s.Finalise(true) - - for _, addr := range addrs { - s.SetNonce(addr, 0) - s.SetBalance(addr, common.U2560) - s.SetCode(addr, nil) - } - s.Finalise(true) - - for _, addr := range addrs { - s.SetNonce(addr, 79) - s.SetBalance(addr, uint256.NewInt(80)) - s.SetCode(addr, []byte{0x81}) - } - s.Finalise(true) - }) -} - -func TestMultiTxSnapshotStateChanges(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - for _, addr := range addrs { - randFillAccountState(addr, s) - } - s.Finalise(true) - - for _, addr := range addrs { - randFillAccountState(addr, s) - } - s.Finalise(true) - }) -} - -func TestStackBasic(t *testing.T) { - for i := 0; i < 10; i++ { - testMultiTxSnapshot(t, func(s *StateDB) { - // when test starts, actions are performed after new snapshot is created - // we initialize additional snapshot on top of that - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("NewMultiTxSnapshot failed: %v", err) - t.FailNow() - } - - seed := rand.Int63() - stateMap := genRandomAccountState(seed) - for account, accountKeys := range stateMap { - for key, value := range accountKeys { - s.SetState(account, key, value) - } - } - s.Finalise(true) - - stack := s.multiTxSnapshotStack - - // the test starts with 1 snapshot, and we just created new one above - startSize := stack.Size() - if startSize != 2 { - t.Errorf("expected stack size to be 2, got %d", startSize) - t.FailNow() - } - - for _, addr := range addrs { - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("NewMultiTxSnapshot failed: %v", err) - t.FailNow() - } - randFillAccountState(addr, s) - s.Finalise(true) - } - afterAddrSize := stack.Size() - if afterAddrSize != startSize+len(addrs) { - t.Errorf("expected stack size to be %d, got %d", startSize+len(addrs), afterAddrSize) - t.FailNow() - } - - // the testMultiTxSnapshot subroutine calls MultiTxSnapshotRevert after applying actions - // we test here to make sure that the flattened commitments on the head of stack - // yield the same final root hash - // this ensures that we are properly flattening the stack on commit - for stack.Size() > 1 { - if _, err := stack.Commit(); err != nil { - t.Errorf("Commit failed: %v", err) - t.FailNow() - } - } - }) - } -} - -func TestStackSelfDestruct(t *testing.T) { - testMultiTxSnapshot(t, func(s *StateDB) { - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("NewMultiTxSnapshot failed: %v", err) - t.FailNow() - } - for _, addr := range addrs { - s.SetNonce(addr, 78) - s.SetBalance(addr, uint256.NewInt(79)) - s.SetCode(addr, []byte{0x80}) - s.Finalise(true) - } - - for _, addr := range addrs { - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("NewMultiTxSnapshot failed: %v", err) - t.FailNow() - } - s.SelfDestruct(addr) - } - stack := s.multiTxSnapshotStack - - // merge all the suicide operations - for stack.Size() > 1 { - if _, err := stack.Commit(); err != nil { - t.Errorf("Commit failed: %v", err) - t.FailNow() - } - } - s.Finalise(true) - - for _, addr := range addrs { - s.SetNonce(addr, 79) - s.SetBalance(addr, uint256.NewInt(80)) - s.SetCode(addr, []byte{0x81}) - } - s.Finalise(true) - }) -} - -func TestStackAgainstSingleSnap(t *testing.T) { - // we generate a random seed ten times to fuzz test multiple stack snapshots against single layer snapshot - for i := 0; i < 10; i++ { - testMultiTxSnapshot(t, func(s *StateDB) { - // Need to drop initial snapshot since copy requires empty snapshot stack - if err := s.MultiTxSnapshotRevert(); err != nil { - t.Fatalf("error reverting snapshot: %v", err) - } - original := s.Copy() - baselineStateDB := s.Copy() - - baselineRootHash, targetRootHash := baselineStateDB.originalRoot, s.originalRoot - - if !bytes.Equal(baselineRootHash.Bytes(), targetRootHash.Bytes()) { - t.Errorf("expected root hash to be %x, got %x", baselineRootHash, targetRootHash) - t.FailNow() - } - - // basic - add multiple snapshots and commit them, and compare them to single snapshot that has all - // state changes - - if err := baselineStateDB.NewMultiTxSnapshot(); err != nil { - t.Errorf("Error initializing snapshot: %v", err) - t.FailNow() - } - - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("Error initializing snapshot: %v", err) - t.FailNow() - } - - // we should be able to revert back to the same intermediate root hash - // for single snapshot and snapshot stack - seed := rand.Int63() - state := genRandomAccountState(seed) - for account, accountKeys := range state { - for key, value := range accountKeys { - baselineStateDB.SetState(account, key, value) - - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("Error initializing snapshot: %v", err) - t.FailNow() - } - s.SetState(account, key, value) - s.Finalise(true) - } - } - baselineStateDB.Finalise(true) - - // commit all but last snapshot - stack := s.multiTxSnapshotStack - for stack.Size() > 1 { - if _, err := stack.Commit(); err != nil { - t.Errorf("Commit failed: %v", err) - t.FailNow() - } - } - - var ( - baselineSnapshot = baselineStateDB.multiTxSnapshotStack.Peek() - targetSnapshot = s.multiTxSnapshotStack.Peek() - ) - if !targetSnapshot.Equal(baselineSnapshot) { - CompareAndPrintSnapshotMismatches(t, targetSnapshot, baselineSnapshot) - t.Errorf("expected snapshots to be equal") - t.FailNow() - } - - // revert back to previously calculated root hash - if err := baselineStateDB.MultiTxSnapshotRevert(); err != nil { - t.Errorf("MultiTxSnapshotRevert failed: %v", err) - t.FailNow() - } - - if err := s.MultiTxSnapshotRevert(); err != nil { - t.Errorf("MultiTxSnapshotRevert failed: %v", err) - t.FailNow() - } - - var err error - if targetRootHash, err = s.Commit(0, true); err != nil { - t.Errorf("Commit failed: %v", err) - t.FailNow() - } - - if baselineRootHash, err = baselineStateDB.Commit(0, true); err != nil { - t.Errorf("Commit failed: %v", err) - t.FailNow() - } - if !bytes.Equal(baselineRootHash.Bytes(), targetRootHash.Bytes()) { - t.Errorf("expected root hash to be %x, got %x", baselineRootHash, targetRootHash) - t.FailNow() - } - - *s = *original - if err := s.NewMultiTxSnapshot(); err != nil { - t.Errorf("Error initializing snapshot: %v", err) - t.FailNow() - } - }) - } -} - -func CompareAndPrintSnapshotMismatches(t *testing.T, target, other *MultiTxSnapshot) { - var out bytes.Buffer - if target.Equal(other) { - t.Logf("Snapshots are equal") - return - } - - if target.invalid != other.invalid { - out.WriteString(fmt.Sprintf("invalid: %v != %v\n", target.invalid, other.invalid)) - return - } - - // check log mismatch - visited := make(map[common.Hash]bool) - for address, logCount := range other.numLogsAdded { - targetLogCount, exists := target.numLogsAdded[address] - if !exists { - out.WriteString(fmt.Sprintf("target<>other numLogsAdded[missing]: %v\n", address)) - continue - } - if targetLogCount != logCount { - out.WriteString(fmt.Sprintf("target<>other numLogsAdded[%x]: %v != %v\n", address, targetLogCount, logCount)) - } - } - - for address, logCount := range target.numLogsAdded { - if visited[address] { - continue - } - - otherLogCount, exists := other.numLogsAdded[address] - if !exists { - out.WriteString(fmt.Sprintf("other<>target numLogsAdded[missing]: %v\n", address)) - continue - } - - if otherLogCount != logCount { - out.WriteString(fmt.Sprintf("other<>target numLogsAdded[%x]: %v != %v\n", address, otherLogCount, logCount)) - } - } - - // check previous objects mismatch - for address := range other.prevObjects { - // TODO: we only check existence, need to add RLP comparison - _, exists := target.prevObjects[address] - if !exists { - out.WriteString(fmt.Sprintf("target<>other prevObjects[missing]: %v\n", address.String())) - continue - } - } - - for address, obj := range target.prevObjects { - otherObj, exists := other.prevObjects[address] - if !exists { - out.WriteString(fmt.Sprintf("other<>target prevObjects[missing]: %v\n", address)) - continue - } - if !reflect.DeepEqual(otherObj, obj) { - out.WriteString(fmt.Sprintf("other<>target prevObjects[%x]: %v != %v\n", address, otherObj, obj)) - } - } - - // check account storage mismatch - for account, storage := range other.accountStorage { - targetStorage, exists := target.accountStorage[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountStorage[missing]: %v\n", account)) - continue - } - - for key, value := range storage { - targetValue, exists := targetStorage[key] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountStorage[%s][missing]: %v\n", account.String(), key.String())) - continue - } - if !reflect.DeepEqual(targetValue, value) { - out.WriteString(fmt.Sprintf("target<>other accountStorage[%s][%s]: %v != %v\n", account.String(), key.String(), targetValue.String(), value.String())) - } - } - } - - for account, storage := range target.accountStorage { - otherStorage, exists := other.accountStorage[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountStorage[missing]: %v\n", account)) - continue - } - - for key, value := range storage { - otherValue, exists := otherStorage[key] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountStorage[%s][missing]: %v\n", account.String(), key.String())) - continue - } - if !reflect.DeepEqual(otherValue, value) { - out.WriteString(fmt.Sprintf("other<>target accountStorage[%s][%s]: %v != %v\n", account.String(), key.String(), otherValue.String(), value.String())) - } - } - } - - // check account balance mismatch - for account, balance := range other.accountBalance { - targetBalance, exists := target.accountBalance[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountBalance[missing]: %v\n", account)) - continue - } - if !reflect.DeepEqual(targetBalance, balance) { - out.WriteString(fmt.Sprintf("target<>other accountBalance[%x]: %v != %v\n", account, targetBalance, balance)) - } - } - - for account, balance := range target.accountBalance { - otherBalance, exists := other.accountBalance[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountBalance[missing]: %v\n", account)) - continue - } - if !bytes.Equal(otherBalance.Bytes(), balance.Bytes()) { - out.WriteString(fmt.Sprintf("other<>target accountBalance[%x]: %v != %v\n", account, otherBalance, balance)) - } - } - - // check account nonce mismatch - for account, nonce := range other.accountNonce { - targetNonce, exists := target.accountNonce[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountNonce[missing]: %v\n", account)) - continue - } - if targetNonce != nonce { - out.WriteString(fmt.Sprintf("target<>other accountNonce[%x]: %v != %v\n", account, targetNonce, nonce)) - } - } - - for account, nonce := range target.accountNonce { - otherNonce, exists := other.accountNonce[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountNonce[missing]: %v\n", account)) - continue - } - if otherNonce != nonce { - out.WriteString(fmt.Sprintf("other<>target accountNonce[%x]: %v != %v\n", account, otherNonce, nonce)) - } - } - - // check account code mismatch - for account, code := range other.accountCode { - targetCode, exists := target.accountCode[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountCode[missing]: %v\n", account)) - continue - } - if !bytes.Equal(targetCode, code) { - out.WriteString(fmt.Sprintf("target<>other accountCode[%x]: %v != %v\n", account, targetCode, code)) - } - } - - for account, code := range target.accountCode { - otherCode, exists := other.accountCode[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountCode[missing]: %v\n", account)) - continue - } - if !bytes.Equal(otherCode, code) { - out.WriteString(fmt.Sprintf("other<>target accountCode[%x]: %v != %v\n", account, otherCode, code)) - } - } - - // check account codeHash mismatch - for account, codeHash := range other.accountCodeHash { - targetCodeHash, exists := target.accountCodeHash[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountCodeHash[missing]: %v\n", account)) - continue - } - if !bytes.Equal(targetCodeHash, codeHash) { - out.WriteString(fmt.Sprintf("target<>other accountCodeHash[%x]: %v != %v\n", account, targetCodeHash, codeHash)) - } - } - - for account, codeHash := range target.accountCodeHash { - otherCodeHash, exists := other.accountCodeHash[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountCodeHash[missing]: %v\n", account)) - continue - } - if !bytes.Equal(otherCodeHash, codeHash) { - out.WriteString(fmt.Sprintf("other<>target accountCodeHash[%x]: %v != %v\n", account, otherCodeHash, codeHash)) - } - } - - // check account suicide mismatch - for account, suicide := range other.accountSelfDestruct { - targetSuicide, exists := target.accountSelfDestruct[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountSuicided[missing]: %v\n", account)) - continue - } - - if targetSuicide != suicide { - out.WriteString(fmt.Sprintf("target<>other accountSuicided[%x]: %t != %t\n", account, targetSuicide, suicide)) - } - } - - for account, suicide := range target.accountSelfDestruct { - otherSuicide, exists := other.accountSelfDestruct[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountSuicided[missing]: %v\n", account)) - continue - } - - if otherSuicide != suicide { - out.WriteString(fmt.Sprintf("other<>target accountSuicided[%x]: %t != %t\n", account, otherSuicide, suicide)) - } - } - - // check account deletion mismatch - for account, del := range other.accountDeleted { - targetDelete, exists := target.accountDeleted[account] - if !exists { - out.WriteString(fmt.Sprintf("target<>other accountDeleted[missing]: %v\n", account)) - continue - } - - if targetDelete != del { - out.WriteString(fmt.Sprintf("target<>other accountDeleted[%x]: %v != %v\n", account, targetDelete, del)) - } - } - - for account, del := range target.accountDeleted { - otherDelete, exists := other.accountDeleted[account] - if !exists { - out.WriteString(fmt.Sprintf("other<>target accountDeleted[missing]: %v\n", account)) - continue - } - - if otherDelete != del { - out.WriteString(fmt.Sprintf("other<>target accountDeleted[%x]: %v != %v\n", account, otherDelete, del)) - } - } - - // check account not pending mismatch - for account := range other.accountNotPending { - if _, exists := target.accountNotPending[account]; !exists { - out.WriteString(fmt.Sprintf("target<>other accountNotPending[missing]: %v\n", account)) - } - } - - for account := range target.accountNotPending { - if _, exists := other.accountNotPending[account]; !exists { - out.WriteString(fmt.Sprintf("other<>target accountNotPending[missing]: %v\n", account)) - } - } - - // check account not dirty mismatch - for account := range other.accountNotDirty { - if _, exists := target.accountNotDirty[account]; !exists { - out.WriteString(fmt.Sprintf("target<>other accountNotDirty[missing]: %v\n", account)) - } - } - - for account := range target.accountNotDirty { - if _, exists := other.accountNotDirty[account]; !exists { - out.WriteString(fmt.Sprintf("other<>target accountNotDirty[missing]: %v\n", account)) - } - } - - fmt.Println(out.String()) - out.Reset() -} diff --git a/builder/core/state/pruner/bloom.go b/builder/core/state/pruner/bloom.go deleted file mode 100644 index dad2b5b2a..000000000 --- a/builder/core/state/pruner/bloom.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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 pruner - -import ( - "encoding/binary" - "errors" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/log" - bloomfilter "github.com/holiman/bloomfilter/v2" -) - -// stateBloomHash is used to convert a trie hash or contract code hash into a 64 bit mini hash. -func stateBloomHash(f []byte) uint64 { - return binary.BigEndian.Uint64(f) -} - -// stateBloom is a bloom filter used during the state conversion(snapshot->state). -// The keys of all generated entries will be recorded here so that in the pruning -// stage the entries belong to the specific version can be avoided for deletion. -// -// The false-positive is allowed here. The "false-positive" entries means they -// actually don't belong to the specific version but they are not deleted in the -// pruning. The downside of the false-positive allowance is we may leave some "dangling" -// nodes in the disk. But in practice the it's very unlike the dangling node is -// state root. So in theory this pruned state shouldn't be visited anymore. Another -// potential issue is for fast sync. If we do another fast sync upon the pruned -// database, it's problematic which will stop the expansion during the syncing. -// TODO address it @rjl493456442 @holiman @karalabe. -// -// After the entire state is generated, the bloom filter should be persisted into -// the disk. It indicates the whole generation procedure is finished. -type stateBloom struct { - bloom *bloomfilter.Filter -} - -// newStateBloomWithSize creates a brand new state bloom for state generation. -// The bloom filter will be created by the passing bloom filter size. According -// to the https://hur.st/bloomfilter/?n=600000000&p=&m=2048MB&k=4, the parameters -// are picked so that the false-positive rate for mainnet is low enough. -func newStateBloomWithSize(size uint64) (*stateBloom, error) { - bloom, err := bloomfilter.New(size*1024*1024*8, 4) - if err != nil { - return nil, err - } - log.Info("Initialized state bloom", "size", common.StorageSize(float64(bloom.M()/8))) - return &stateBloom{bloom: bloom}, nil -} - -// NewStateBloomFromDisk loads the state bloom from the given file. -// In this case the assumption is held the bloom filter is complete. -func NewStateBloomFromDisk(filename string) (*stateBloom, error) { - bloom, _, err := bloomfilter.ReadFile(filename) - if err != nil { - return nil, err - } - return &stateBloom{bloom: bloom}, nil -} - -// Commit flushes the bloom filter content into the disk and marks the bloom -// as complete. -func (bloom *stateBloom) Commit(filename, tempname string) error { - // Write the bloom out into a temporary file - _, err := bloom.bloom.WriteFile(tempname) - if err != nil { - return err - } - // Ensure the file is synced to disk - f, err := os.OpenFile(tempname, os.O_RDWR, 0666) - if err != nil { - return err - } - if err := f.Sync(); err != nil { - f.Close() - return err - } - f.Close() - - // Move the temporary file into it's final location - return os.Rename(tempname, filename) -} - -// Put implements the KeyValueWriter interface. But here only the key is needed. -func (bloom *stateBloom) Put(key []byte, value []byte) error { - // If the key length is not 32bytes, ensure it's contract code - // entry with new scheme. - if len(key) != common.HashLength { - isCode, codeKey := rawdb.IsCodeKey(key) - if !isCode { - return errors.New("invalid entry") - } - bloom.bloom.AddHash(stateBloomHash(codeKey)) - return nil - } - bloom.bloom.AddHash(stateBloomHash(key)) - return nil -} - -// Delete removes the key from the key-value data store. -func (bloom *stateBloom) Delete(key []byte) error { panic("not supported") } - -// Contain is the wrapper of the underlying contains function which -// reports whether the key is contained. -// - If it says yes, the key may be contained -// - If it says no, the key is definitely not contained. -func (bloom *stateBloom) Contain(key []byte) bool { - return bloom.bloom.ContainsHash(stateBloomHash(key)) -} diff --git a/builder/core/state/pruner/pruner.go b/builder/core/state/pruner/pruner.go deleted file mode 100644 index 59c580dac..000000000 --- a/builder/core/state/pruner/pruner.go +++ /dev/null @@ -1,493 +0,0 @@ -// 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 pruner - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "math" - "os" - "path/filepath" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" -) - -const ( - // stateBloomFilePrefix is the filename prefix of state bloom filter. - stateBloomFilePrefix = "statebloom" - - // stateBloomFilePrefix is the filename suffix of state bloom filter. - stateBloomFileSuffix = "bf.gz" - - // stateBloomFileTempSuffix is the filename suffix of state bloom filter - // while it is being written out to detect write aborts. - stateBloomFileTempSuffix = ".tmp" - - // rangeCompactionThreshold is the minimal deleted entry number for - // triggering range compaction. It's a quite arbitrary number but just - // to avoid triggering range compaction because of small deletion. - rangeCompactionThreshold = 100000 -) - -// Config includes all the configurations for pruning. -type Config struct { - Datadir string // The directory of the state database - BloomSize uint64 // The Megabytes of memory allocated to bloom-filter -} - -// Pruner is an offline tool to prune the stale state with the -// help of the snapshot. The workflow of pruner is very simple: -// -// - iterate the snapshot, reconstruct the relevant state -// - iterate the database, delete all other state entries which -// don't belong to the target state and the genesis state -// -// It can take several hours(around 2 hours for mainnet) to finish -// the whole pruning work. It's recommended to run this offline tool -// periodically in order to release the disk usage and improve the -// disk read performance to some extent. -type Pruner struct { - config Config - chainHeader *types.Header - db ethdb.Database - stateBloom *stateBloom - snaptree *snapshot.Tree -} - -// NewPruner creates the pruner instance. -func NewPruner(db ethdb.Database, config Config) (*Pruner, error) { - headBlock := rawdb.ReadHeadBlock(db) - if headBlock == nil { - return nil, errors.New("failed to load head block") - } - // Offline pruning is only supported in legacy hash based scheme. - triedb := triedb.NewDatabase(db, triedb.HashDefaults) - - snapconfig := snapshot.Config{ - CacheSize: 256, - Recovery: false, - NoBuild: true, - AsyncBuild: false, - } - snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root()) - if err != nil { - return nil, err // The relevant snapshot(s) might not exist - } - // Sanitize the bloom filter size if it's too small. - if config.BloomSize < 256 { - log.Warn("Sanitizing bloomfilter size", "provided(MB)", config.BloomSize, "updated(MB)", 256) - config.BloomSize = 256 - } - stateBloom, err := newStateBloomWithSize(config.BloomSize) - if err != nil { - return nil, err - } - return &Pruner{ - config: config, - chainHeader: headBlock.Header(), - db: db, - stateBloom: stateBloom, - snaptree: snaptree, - }, nil -} - -func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, stateBloom *stateBloom, bloomPath string, middleStateRoots map[common.Hash]struct{}, start time.Time) error { - // Delete all stale trie nodes in the disk. With the help of state bloom - // the trie nodes(and codes) belong to the active state will be filtered - // out. A very small part of stale tries will also be filtered because of - // the false-positive rate of bloom filter. But the assumption is held here - // that the false-positive is low enough(~0.05%). The probability of the - // dangling node is the state root is super low. So the dangling nodes in - // theory will never ever be visited again. - var ( - skipped, count int - size common.StorageSize - pstart = time.Now() - logged = time.Now() - batch = maindb.NewBatch() - iter = maindb.NewIterator(nil, nil) - ) - for iter.Next() { - key := iter.Key() - - // All state entries don't belong to specific state and genesis are deleted here - // - trie node - // - legacy contract code - // - new-scheme contract code - isCode, codeKey := rawdb.IsCodeKey(key) - if len(key) == common.HashLength || isCode { - checkKey := key - if isCode { - checkKey = codeKey - } - if _, exist := middleStateRoots[common.BytesToHash(checkKey)]; exist { - log.Debug("Forcibly delete the middle state roots", "hash", common.BytesToHash(checkKey)) - } else { - if stateBloom.Contain(checkKey) { - skipped += 1 - continue - } - } - count += 1 - size += common.StorageSize(len(key) + len(iter.Value())) - batch.Delete(key) - - var eta time.Duration // Realistically will never remain uninited - if done := binary.BigEndian.Uint64(key[:8]); done > 0 { - var ( - left = math.MaxUint64 - binary.BigEndian.Uint64(key[:8]) - speed = done/uint64(time.Since(pstart)/time.Millisecond+1) + 1 // +1s to avoid division by zero - ) - eta = time.Duration(left/speed) * time.Millisecond - } - if time.Since(logged) > 8*time.Second { - log.Info("Pruning state data", "nodes", count, "skipped", skipped, "size", size, - "elapsed", common.PrettyDuration(time.Since(pstart)), "eta", common.PrettyDuration(eta)) - logged = time.Now() - } - // Recreate the iterator after every batch commit in order - // to allow the underlying compactor to delete the entries. - if batch.ValueSize() >= ethdb.IdealBatchSize { - batch.Write() - batch.Reset() - - iter.Release() - iter = maindb.NewIterator(nil, key) - } - } - } - if batch.ValueSize() > 0 { - batch.Write() - batch.Reset() - } - iter.Release() - log.Info("Pruned state data", "nodes", count, "size", size, "elapsed", common.PrettyDuration(time.Since(pstart))) - - // Pruning is done, now drop the "useless" layers from the snapshot. - // Firstly, flushing the target layer into the disk. After that all - // diff layers below the target will all be merged into the disk. - if err := snaptree.Cap(root, 0); err != nil { - return err - } - // Secondly, flushing the snapshot journal into the disk. All diff - // layers upon are dropped silently. Eventually the entire snapshot - // tree is converted into a single disk layer with the pruning target - // as the root. - if _, err := snaptree.Journal(root); err != nil { - return err - } - // Delete the state bloom, it marks the entire pruning procedure is - // finished. If any crashes or manual exit happens before this, - // `RecoverPruning` will pick it up in the next restarts to redo all - // the things. - os.RemoveAll(bloomPath) - - // Start compactions, will remove the deleted data from the disk immediately. - // Note for small pruning, the compaction is skipped. - if count >= rangeCompactionThreshold { - cstart := time.Now() - for b := 0x00; b <= 0xf0; b += 0x10 { - var ( - start = []byte{byte(b)} - end = []byte{byte(b + 0x10)} - ) - if b == 0xf0 { - end = nil - } - log.Info("Compacting database", "range", fmt.Sprintf("%#x-%#x", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) - if err := maindb.Compact(start, end); err != nil { - log.Error("Database compaction failed", "error", err) - return err - } - } - log.Info("Database compaction finished", "elapsed", common.PrettyDuration(time.Since(cstart))) - } - log.Info("State pruning successful", "pruned", size, "elapsed", common.PrettyDuration(time.Since(start))) - return nil -} - -// Prune deletes all historical state nodes except the nodes belong to the -// specified state version. If user doesn't specify the state version, use -// the bottom-most snapshot diff layer as the target. -func (p *Pruner) Prune(root common.Hash) error { - // If the state bloom filter is already committed previously, - // reuse it for pruning instead of generating a new one. It's - // mandatory because a part of state may already be deleted, - // the recovery procedure is necessary. - _, stateBloomRoot, err := findBloomFilter(p.config.Datadir) - if err != nil { - return err - } - if stateBloomRoot != (common.Hash{}) { - return RecoverPruning(p.config.Datadir, p.db) - } - // If the target state root is not specified, use the HEAD-127 as the - // target. The reason for picking it is: - // - in most of the normal cases, the related state is available - // - the probability of this layer being reorg is very low - var layers []snapshot.Snapshot - if root == (common.Hash{}) { - // Retrieve all snapshot layers from the current HEAD. - // In theory there are 128 difflayers + 1 disk layer present, - // so 128 diff layers are expected to be returned. - layers = p.snaptree.Snapshots(p.chainHeader.Root, 128, true) - if len(layers) != 128 { - // Reject if the accumulated diff layers are less than 128. It - // means in most of normal cases, there is no associated state - // with bottom-most diff layer. - return fmt.Errorf("snapshot not old enough yet: need %d more blocks", 128-len(layers)) - } - // Use the bottom-most diff layer as the target - root = layers[len(layers)-1].Root() - } - // Ensure the root is really present. The weak assumption - // is the presence of root can indicate the presence of the - // entire trie. - if !rawdb.HasLegacyTrieNode(p.db, root) { - // The special case is for clique based networks(goerli - // and some other private networks), it's possible that two - // consecutive blocks will have same root. In this case snapshot - // difflayer won't be created. So HEAD-127 may not paired with - // head-127 layer. Instead the paired layer is higher than the - // bottom-most diff layer. Try to find the bottom-most snapshot - // layer with state available. - // - // Note HEAD and HEAD-1 is ignored. Usually there is the associated - // state available, but we don't want to use the topmost state - // as the pruning target. - var found bool - for i := len(layers) - 2; i >= 2; i-- { - if rawdb.HasLegacyTrieNode(p.db, layers[i].Root()) { - root = layers[i].Root() - found = true - log.Info("Selecting middle-layer as the pruning target", "root", root, "depth", i) - break - } - } - if !found { - if len(layers) > 0 { - return errors.New("no snapshot paired state") - } - return fmt.Errorf("associated state[%x] is not present", root) - } - } else { - if len(layers) > 0 { - log.Info("Selecting bottom-most difflayer as the pruning target", "root", root, "height", p.chainHeader.Number.Uint64()-127) - } else { - log.Info("Selecting user-specified state as the pruning target", "root", root) - } - } - // All the state roots of the middle layer should be forcibly pruned, - // otherwise the dangling state will be left. - middleRoots := make(map[common.Hash]struct{}) - for _, layer := range layers { - if layer.Root() == root { - break - } - middleRoots[layer.Root()] = struct{}{} - } - // Traverse the target state, re-construct the whole state trie and - // commit to the given bloom filter. - start := time.Now() - if err := snapshot.GenerateTrie(p.snaptree, root, p.db, p.stateBloom); err != nil { - return err - } - // Traverse the genesis, put all genesis state entries into the - // bloom filter too. - if err := extractGenesis(p.db, p.stateBloom); err != nil { - return err - } - filterName := bloomFilterName(p.config.Datadir, root) - - log.Info("Writing state bloom to disk", "name", filterName) - if err := p.stateBloom.Commit(filterName, filterName+stateBloomFileTempSuffix); err != nil { - return err - } - log.Info("State bloom filter committed", "name", filterName) - return prune(p.snaptree, root, p.db, p.stateBloom, filterName, middleRoots, start) -} - -// RecoverPruning will resume the pruning procedure during the system restart. -// This function is used in this case: user tries to prune state data, but the -// system was interrupted midway because of crash or manual-kill. In this case -// if the bloom filter for filtering active state is already constructed, the -// pruning can be resumed. What's more if the bloom filter is constructed, the -// pruning **has to be resumed**. Otherwise a lot of dangling nodes may be left -// in the disk. -func RecoverPruning(datadir string, db ethdb.Database) error { - stateBloomPath, stateBloomRoot, err := findBloomFilter(datadir) - if err != nil { - return err - } - if stateBloomPath == "" { - return nil // nothing to recover - } - headBlock := rawdb.ReadHeadBlock(db) - if headBlock == nil { - return errors.New("failed to load head block") - } - // Initialize the snapshot tree in recovery mode to handle this special case: - // - Users run the `prune-state` command multiple times - // - Neither these `prune-state` running is finished(e.g. interrupted manually) - // - The state bloom filter is already generated, a part of state is deleted, - // so that resuming the pruning here is mandatory - // - The state HEAD is rewound already because of multiple incomplete `prune-state` - // In this case, even the state HEAD is not exactly matched with snapshot, it - // still feasible to recover the pruning correctly. - snapconfig := snapshot.Config{ - CacheSize: 256, - Recovery: true, - NoBuild: true, - AsyncBuild: false, - } - // Offline pruning is only supported in legacy hash based scheme. - triedb := triedb.NewDatabase(db, triedb.HashDefaults) - snaptree, err := snapshot.New(snapconfig, db, triedb, headBlock.Root()) - if err != nil { - return err // The relevant snapshot(s) might not exist - } - stateBloom, err := NewStateBloomFromDisk(stateBloomPath) - if err != nil { - return err - } - log.Info("Loaded state bloom filter", "path", stateBloomPath) - - // All the state roots of the middle layers should be forcibly pruned, - // otherwise the dangling state will be left. - var ( - found bool - layers = snaptree.Snapshots(headBlock.Root(), 128, true) - middleRoots = make(map[common.Hash]struct{}) - ) - for _, layer := range layers { - if layer.Root() == stateBloomRoot { - found = true - break - } - middleRoots[layer.Root()] = struct{}{} - } - if !found { - log.Error("Pruning target state is not existent") - return errors.New("non-existent target state") - } - return prune(snaptree, stateBloomRoot, db, stateBloom, stateBloomPath, middleRoots, time.Now()) -} - -// extractGenesis loads the genesis state and commits all the state entries -// into the given bloomfilter. -func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error { - genesisHash := rawdb.ReadCanonicalHash(db, 0) - if genesisHash == (common.Hash{}) { - return errors.New("missing genesis hash") - } - genesis := rawdb.ReadBlock(db, genesisHash, 0) - if genesis == nil { - return errors.New("missing genesis block") - } - t, err := trie.NewStateTrie(trie.StateTrieID(genesis.Root()), triedb.NewDatabase(db, triedb.HashDefaults)) - if err != nil { - return err - } - accIter, err := t.NodeIterator(nil) - if err != nil { - return err - } - for accIter.Next(true) { - hash := accIter.Hash() - - // Embedded nodes don't have hash. - if hash != (common.Hash{}) { - stateBloom.Put(hash.Bytes(), nil) - } - // If it's a leaf node, yes we are touching an account, - // dig into the storage trie further. - if accIter.Leaf() { - var acc types.StateAccount - if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil { - return err - } - if acc.Root != types.EmptyRootHash { - id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root) - storageTrie, err := trie.NewStateTrie(id, triedb.NewDatabase(db, triedb.HashDefaults)) - if err != nil { - return err - } - storageIter, err := storageTrie.NodeIterator(nil) - if err != nil { - return err - } - for storageIter.Next(true) { - hash := storageIter.Hash() - if hash != (common.Hash{}) { - stateBloom.Put(hash.Bytes(), nil) - } - } - if storageIter.Error() != nil { - return storageIter.Error() - } - } - if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { - stateBloom.Put(acc.CodeHash, nil) - } - } - } - return accIter.Error() -} - -func bloomFilterName(datadir string, hash common.Hash) string { - return filepath.Join(datadir, fmt.Sprintf("%s.%s.%s", stateBloomFilePrefix, hash.Hex(), stateBloomFileSuffix)) -} - -func isBloomFilter(filename string) (bool, common.Hash) { - filename = filepath.Base(filename) - if strings.HasPrefix(filename, stateBloomFilePrefix) && strings.HasSuffix(filename, stateBloomFileSuffix) { - return true, common.HexToHash(filename[len(stateBloomFilePrefix)+1 : len(filename)-len(stateBloomFileSuffix)-1]) - } - return false, common.Hash{} -} - -func findBloomFilter(datadir string) (string, common.Hash, error) { - var ( - stateBloomPath string - stateBloomRoot common.Hash - ) - if err := filepath.Walk(datadir, func(path string, info os.FileInfo, err error) error { - if info != nil && !info.IsDir() { - ok, root := isBloomFilter(path) - if ok { - stateBloomPath = path - stateBloomRoot = root - } - } - return nil - }); err != nil { - return "", common.Hash{}, err - } - return stateBloomPath, stateBloomRoot, nil -} diff --git a/builder/core/state/snapshot/context.go b/builder/core/state/snapshot/context.go deleted file mode 100644 index 67d7e41a0..000000000 --- a/builder/core/state/snapshot/context.go +++ /dev/null @@ -1,241 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "encoding/binary" - "errors" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/log" -) - -const ( - snapAccount = "account" // Identifier of account snapshot generation - snapStorage = "storage" // Identifier of storage snapshot generation -) - -// generatorStats is a collection of statistics gathered by the snapshot generator -// for logging purposes. -type generatorStats struct { - origin uint64 // Origin prefix where generation started - start time.Time // Timestamp when generation started - accounts uint64 // Number of accounts indexed(generated or recovered) - slots uint64 // Number of storage slots indexed(generated or recovered) - dangling uint64 // Number of dangling storage slots - storage common.StorageSize // Total account and storage slot size(generation or recovery) -} - -// Log creates an contextual log with the given message and the context pulled -// from the internally maintained statistics. -func (gs *generatorStats) Log(msg string, root common.Hash, marker []byte) { - var ctx []interface{} - if root != (common.Hash{}) { - ctx = append(ctx, []interface{}{"root", root}...) - } - // Figure out whether we're after or within an account - switch len(marker) { - case common.HashLength: - ctx = append(ctx, []interface{}{"at", common.BytesToHash(marker)}...) - case 2 * common.HashLength: - ctx = append(ctx, []interface{}{ - "in", common.BytesToHash(marker[:common.HashLength]), - "at", common.BytesToHash(marker[common.HashLength:]), - }...) - } - // Add the usual measurements - ctx = append(ctx, []interface{}{ - "accounts", gs.accounts, - "slots", gs.slots, - "storage", gs.storage, - "dangling", gs.dangling, - "elapsed", common.PrettyDuration(time.Since(gs.start)), - }...) - // Calculate the estimated indexing time based on current stats - if len(marker) > 0 { - if done := binary.BigEndian.Uint64(marker[:8]) - gs.origin; done > 0 { - left := math.MaxUint64 - binary.BigEndian.Uint64(marker[:8]) - - speed := done/uint64(time.Since(gs.start)/time.Millisecond+1) + 1 // +1s to avoid division by zero - ctx = append(ctx, []interface{}{ - "eta", common.PrettyDuration(time.Duration(left/speed) * time.Millisecond), - }...) - } - } - log.Info(msg, ctx...) -} - -// generatorContext carries a few global values to be shared by all generation functions. -type generatorContext struct { - stats *generatorStats // Generation statistic collection - db ethdb.KeyValueStore // Key-value store containing the snapshot data - account *holdableIterator // Iterator of account snapshot data - storage *holdableIterator // Iterator of storage snapshot data - batch ethdb.Batch // Database batch for writing batch data atomically - logged time.Time // The timestamp when last generation progress was displayed -} - -// newGeneratorContext initializes the context for generation. -func newGeneratorContext(stats *generatorStats, db ethdb.KeyValueStore, accMarker []byte, storageMarker []byte) *generatorContext { - ctx := &generatorContext{ - stats: stats, - db: db, - batch: db.NewBatch(), - logged: time.Now(), - } - ctx.openIterator(snapAccount, accMarker) - ctx.openIterator(snapStorage, storageMarker) - return ctx -} - -// openIterator constructs global account and storage snapshot iterators -// at the interrupted position. These iterators should be reopened from time -// to time to avoid blocking leveldb compaction for a long time. -func (ctx *generatorContext) openIterator(kind string, start []byte) { - if kind == snapAccount { - iter := ctx.db.NewIterator(rawdb.SnapshotAccountPrefix, start) - ctx.account = newHoldableIterator(rawdb.NewKeyLengthIterator(iter, 1+common.HashLength)) - return - } - iter := ctx.db.NewIterator(rawdb.SnapshotStoragePrefix, start) - ctx.storage = newHoldableIterator(rawdb.NewKeyLengthIterator(iter, 1+2*common.HashLength)) -} - -// reopenIterator releases the specified snapshot iterator and re-open it -// in the next position. It's aimed for not blocking leveldb compaction. -func (ctx *generatorContext) reopenIterator(kind string) { - // Shift iterator one more step, so that we can reopen - // the iterator at the right position. - var iter = ctx.account - if kind == snapStorage { - iter = ctx.storage - } - hasNext := iter.Next() - if !hasNext { - // Iterator exhausted, release forever and create an already exhausted virtual iterator - iter.Release() - if kind == snapAccount { - ctx.account = newHoldableIterator(memorydb.New().NewIterator(nil, nil)) - return - } - ctx.storage = newHoldableIterator(memorydb.New().NewIterator(nil, nil)) - return - } - next := iter.Key() - iter.Release() - ctx.openIterator(kind, next[1:]) -} - -// close releases all the held resources. -func (ctx *generatorContext) close() { - ctx.account.Release() - ctx.storage.Release() -} - -// iterator returns the corresponding iterator specified by the kind. -func (ctx *generatorContext) iterator(kind string) *holdableIterator { - if kind == snapAccount { - return ctx.account - } - return ctx.storage -} - -// removeStorageBefore deletes all storage entries which are located before -// the specified account. When the iterator touches the storage entry which -// is located in or outside the given account, it stops and holds the current -// iterated element locally. -func (ctx *generatorContext) removeStorageBefore(account common.Hash) { - var ( - count uint64 - start = time.Now() - iter = ctx.storage - ) - for iter.Next() { - key := iter.Key() - if bytes.Compare(key[1:1+common.HashLength], account.Bytes()) >= 0 { - iter.Hold() - break - } - count++ - ctx.batch.Delete(key) - if ctx.batch.ValueSize() > ethdb.IdealBatchSize { - ctx.batch.Write() - ctx.batch.Reset() - } - } - ctx.stats.dangling += count - snapStorageCleanCounter.Inc(time.Since(start).Nanoseconds()) -} - -// removeStorageAt deletes all storage entries which are located in the specified -// account. When the iterator touches the storage entry which is outside the given -// account, it stops and holds the current iterated element locally. An error will -// be returned if the initial position of iterator is not in the given account. -func (ctx *generatorContext) removeStorageAt(account common.Hash) error { - var ( - count int64 - start = time.Now() - iter = ctx.storage - ) - for iter.Next() { - key := iter.Key() - cmp := bytes.Compare(key[1:1+common.HashLength], account.Bytes()) - if cmp < 0 { - return errors.New("invalid iterator position") - } - if cmp > 0 { - iter.Hold() - break - } - count++ - ctx.batch.Delete(key) - if ctx.batch.ValueSize() > ethdb.IdealBatchSize { - ctx.batch.Write() - ctx.batch.Reset() - } - } - snapWipedStorageMeter.Mark(count) - snapStorageCleanCounter.Inc(time.Since(start).Nanoseconds()) - return nil -} - -// removeStorageLeft deletes all storage entries which are located after -// the current iterator position. -func (ctx *generatorContext) removeStorageLeft() { - var ( - count uint64 - start = time.Now() - iter = ctx.storage - ) - for iter.Next() { - count++ - ctx.batch.Delete(iter.Key()) - if ctx.batch.ValueSize() > ethdb.IdealBatchSize { - ctx.batch.Write() - ctx.batch.Reset() - } - } - ctx.stats.dangling += count - snapDanglingStorageMeter.Mark(int64(count)) - snapStorageCleanCounter.Inc(time.Since(start).Nanoseconds()) -} diff --git a/builder/core/state/snapshot/conversion.go b/builder/core/state/snapshot/conversion.go deleted file mode 100644 index 681be7ebc..000000000 --- a/builder/core/state/snapshot/conversion.go +++ /dev/null @@ -1,376 +0,0 @@ -// 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 snapshot - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "runtime" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -// trieKV represents a trie key-value pair -type trieKV struct { - key common.Hash - value []byte -} - -type ( - // trieGeneratorFn is the interface of trie generation which can - // be implemented by different trie algorithm. - trieGeneratorFn func(db ethdb.KeyValueWriter, scheme string, owner common.Hash, in chan (trieKV), out chan (common.Hash)) - - // leafCallbackFn is the callback invoked at the leaves of the trie, - // returns the subtrie root with the specified subtrie identifier. - leafCallbackFn func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) -) - -// GenerateAccountTrieRoot takes an account iterator and reproduces the root hash. -func GenerateAccountTrieRoot(it AccountIterator) (common.Hash, error) { - return generateTrieRoot(nil, "", it, common.Hash{}, stackTrieGenerate, nil, newGenerateStats(), true) -} - -// GenerateStorageTrieRoot takes a storage iterator and reproduces the root hash. -func GenerateStorageTrieRoot(account common.Hash, it StorageIterator) (common.Hash, error) { - return generateTrieRoot(nil, "", it, account, stackTrieGenerate, nil, newGenerateStats(), true) -} - -// GenerateTrie takes the whole snapshot tree as the input, traverses all the -// accounts as well as the corresponding storages and regenerate the whole state -// (account trie + all storage tries). -func GenerateTrie(snaptree *Tree, root common.Hash, src ethdb.Database, dst ethdb.KeyValueWriter) error { - // Traverse all state by snapshot, re-generate the whole state trie - acctIt, err := snaptree.AccountIterator(root, common.Hash{}) - if err != nil { - return err // The required snapshot might not exist. - } - defer acctIt.Release() - - scheme := snaptree.triedb.Scheme() - got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { - // Migrate the code first, commit the contract code into the tmp db. - if codeHash != types.EmptyCodeHash { - code := rawdb.ReadCode(src, codeHash) - if len(code) == 0 { - return common.Hash{}, errors.New("failed to read contract code") - } - rawdb.WriteCode(dst, codeHash, code) - } - // Then migrate all storage trie nodes into the tmp db. - storageIt, err := snaptree.StorageIterator(root, accountHash, common.Hash{}) - if err != nil { - return common.Hash{}, err - } - defer storageIt.Release() - - hash, err := generateTrieRoot(dst, scheme, storageIt, accountHash, stackTrieGenerate, nil, stat, false) - if err != nil { - return common.Hash{}, err - } - return hash, nil - }, newGenerateStats(), true) - - if err != nil { - return err - } - if got != root { - return fmt.Errorf("state root hash mismatch: got %x, want %x", got, root) - } - return nil -} - -// generateStats is a collection of statistics gathered by the trie generator -// for logging purposes. -type generateStats struct { - head common.Hash - start time.Time - - accounts uint64 // Number of accounts done (including those being crawled) - slots uint64 // Number of storage slots done (including those being crawled) - - slotsStart map[common.Hash]time.Time // Start time for account slot crawling - slotsHead map[common.Hash]common.Hash // Slot head for accounts being crawled - - lock sync.RWMutex -} - -// newGenerateStats creates a new generator stats. -func newGenerateStats() *generateStats { - return &generateStats{ - slotsStart: make(map[common.Hash]time.Time), - slotsHead: make(map[common.Hash]common.Hash), - start: time.Now(), - } -} - -// progressAccounts updates the generator stats for the account range. -func (stat *generateStats) progressAccounts(account common.Hash, done uint64) { - stat.lock.Lock() - defer stat.lock.Unlock() - - stat.accounts += done - stat.head = account -} - -// finishAccounts updates the generator stats for the finished account range. -func (stat *generateStats) finishAccounts(done uint64) { - stat.lock.Lock() - defer stat.lock.Unlock() - - stat.accounts += done -} - -// progressContract updates the generator stats for a specific in-progress contract. -func (stat *generateStats) progressContract(account common.Hash, slot common.Hash, done uint64) { - stat.lock.Lock() - defer stat.lock.Unlock() - - stat.slots += done - stat.slotsHead[account] = slot - if _, ok := stat.slotsStart[account]; !ok { - stat.slotsStart[account] = time.Now() - } -} - -// finishContract updates the generator stats for a specific just-finished contract. -func (stat *generateStats) finishContract(account common.Hash, done uint64) { - stat.lock.Lock() - defer stat.lock.Unlock() - - stat.slots += done - delete(stat.slotsHead, account) - delete(stat.slotsStart, account) -} - -// report prints the cumulative progress statistic smartly. -func (stat *generateStats) report() { - stat.lock.RLock() - defer stat.lock.RUnlock() - - ctx := []interface{}{ - "accounts", stat.accounts, - "slots", stat.slots, - "elapsed", common.PrettyDuration(time.Since(stat.start)), - } - if stat.accounts > 0 { - // If there's progress on the account trie, estimate the time to finish crawling it - if done := binary.BigEndian.Uint64(stat.head[:8]) / stat.accounts; done > 0 { - var ( - left = (math.MaxUint64 - binary.BigEndian.Uint64(stat.head[:8])) / stat.accounts - speed = done/uint64(time.Since(stat.start)/time.Millisecond+1) + 1 // +1s to avoid division by zero - eta = time.Duration(left/speed) * time.Millisecond - ) - // If there are large contract crawls in progress, estimate their finish time - for acc, head := range stat.slotsHead { - start := stat.slotsStart[acc] - if done := binary.BigEndian.Uint64(head[:8]); done > 0 { - var ( - left = math.MaxUint64 - binary.BigEndian.Uint64(head[:8]) - speed = done/uint64(time.Since(start)/time.Millisecond+1) + 1 // +1s to avoid division by zero - ) - // Override the ETA if larger than the largest until now - if slotETA := time.Duration(left/speed) * time.Millisecond; eta < slotETA { - eta = slotETA - } - } - } - ctx = append(ctx, []interface{}{ - "eta", common.PrettyDuration(eta), - }...) - } - } - log.Info("Iterating state snapshot", ctx...) -} - -// reportDone prints the last log when the whole generation is finished. -func (stat *generateStats) reportDone() { - stat.lock.RLock() - defer stat.lock.RUnlock() - - var ctx []interface{} - ctx = append(ctx, []interface{}{"accounts", stat.accounts}...) - if stat.slots != 0 { - ctx = append(ctx, []interface{}{"slots", stat.slots}...) - } - ctx = append(ctx, []interface{}{"elapsed", common.PrettyDuration(time.Since(stat.start))}...) - log.Info("Iterated snapshot", ctx...) -} - -// runReport periodically prints the progress information. -func runReport(stats *generateStats, stop chan bool) { - timer := time.NewTimer(0) - defer timer.Stop() - - for { - select { - case <-timer.C: - stats.report() - timer.Reset(time.Second * 8) - case success := <-stop: - if success { - stats.reportDone() - } - return - } - } -} - -// generateTrieRoot generates the trie hash based on the snapshot iterator. -// It can be used for generating account trie, storage trie or even the -// whole state which connects the accounts and the corresponding storages. -func generateTrieRoot(db ethdb.KeyValueWriter, scheme string, it Iterator, account common.Hash, generatorFn trieGeneratorFn, leafCallback leafCallbackFn, stats *generateStats, report bool) (common.Hash, error) { - var ( - in = make(chan trieKV) // chan to pass leaves - out = make(chan common.Hash, 1) // chan to collect result - stoplog = make(chan bool, 1) // 1-size buffer, works when logging is not enabled - wg sync.WaitGroup - ) - // Spin up a go-routine for trie hash re-generation - wg.Add(1) - go func() { - defer wg.Done() - generatorFn(db, scheme, account, in, out) - }() - // Spin up a go-routine for progress logging - if report && stats != nil { - wg.Add(1) - go func() { - defer wg.Done() - runReport(stats, stoplog) - }() - } - // Create a semaphore to assign tasks and collect results through. We'll pre- - // fill it with nils, thus using the same channel for both limiting concurrent - // processing and gathering results. - threads := runtime.NumCPU() - results := make(chan error, threads) - for i := 0; i < threads; i++ { - results <- nil // fill the semaphore - } - // stop is a helper function to shutdown the background threads - // and return the re-generated trie hash. - stop := func(fail error) (common.Hash, error) { - close(in) - result := <-out - for i := 0; i < threads; i++ { - if err := <-results; err != nil && fail == nil { - fail = err - } - } - stoplog <- fail == nil - - wg.Wait() - return result, fail - } - var ( - logged = time.Now() - processed = uint64(0) - leaf trieKV - ) - // Start to feed leaves - for it.Next() { - if account == (common.Hash{}) { - var ( - err error - fullData []byte - ) - if leafCallback == nil { - fullData, err = types.FullAccountRLP(it.(AccountIterator).Account()) - if err != nil { - return stop(err) - } - } else { - // Wait until the semaphore allows us to continue, aborting if - // a sub-task failed - if err := <-results; err != nil { - results <- nil // stop will drain the results, add a noop back for this error we just consumed - return stop(err) - } - // Fetch the next account and process it concurrently - account, err := types.FullAccount(it.(AccountIterator).Account()) - if err != nil { - return stop(err) - } - go func(hash common.Hash) { - subroot, err := leafCallback(db, hash, common.BytesToHash(account.CodeHash), stats) - if err != nil { - results <- err - return - } - if account.Root != subroot { - results <- fmt.Errorf("invalid subroot(path %x), want %x, have %x", hash, account.Root, subroot) - return - } - results <- nil - }(it.Hash()) - fullData, err = rlp.EncodeToBytes(account) - if err != nil { - return stop(err) - } - } - leaf = trieKV{it.Hash(), fullData} - } else { - leaf = trieKV{it.Hash(), common.CopyBytes(it.(StorageIterator).Slot())} - } - in <- leaf - - // Accumulate the generation statistic if it's required. - processed++ - if time.Since(logged) > 3*time.Second && stats != nil { - if account == (common.Hash{}) { - stats.progressAccounts(it.Hash(), processed) - } else { - stats.progressContract(account, it.Hash(), processed) - } - logged, processed = time.Now(), 0 - } - } - // Commit the last part statistic. - if processed > 0 && stats != nil { - if account == (common.Hash{}) { - stats.finishAccounts(processed) - } else { - stats.finishContract(account, processed) - } - } - return stop(nil) -} - -func stackTrieGenerate(db ethdb.KeyValueWriter, scheme string, owner common.Hash, in chan trieKV, out chan common.Hash) { - options := trie.NewStackTrieOptions() - if db != nil { - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(db, owner, path, hash, blob, scheme) - }) - } - t := trie.NewStackTrie(options) - for leaf := range in { - t.Update(leaf.key[:], leaf.value) - } - out <- t.Commit() -} diff --git a/builder/core/state/snapshot/difflayer.go b/builder/core/state/snapshot/difflayer.go deleted file mode 100644 index 70c9f4418..000000000 --- a/builder/core/state/snapshot/difflayer.go +++ /dev/null @@ -1,543 +0,0 @@ -// 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 snapshot - -import ( - "encoding/binary" - "fmt" - "math" - "math/rand" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - bloomfilter "github.com/holiman/bloomfilter/v2" - "golang.org/x/exp/slices" -) - -var ( - // aggregatorMemoryLimit is the maximum size of the bottom-most diff layer - // that aggregates the writes from above until it's flushed into the disk - // layer. - // - // Note, bumping this up might drastically increase the size of the bloom - // filters that's stored in every diff layer. Don't do that without fully - // understanding all the implications. - aggregatorMemoryLimit = uint64(4 * 1024 * 1024) - - // aggregatorItemLimit is an approximate number of items that will end up - // in the aggregator layer before it's flushed out to disk. A plain account - // weighs around 14B (+hash), a storage slot 32B (+hash), a deleted slot - // 0B (+hash). Slots are mostly set/unset in lockstep, so that average at - // 16B (+hash). All in all, the average entry seems to be 15+32=47B. Use a - // smaller number to be on the safe side. - aggregatorItemLimit = aggregatorMemoryLimit / 42 - - // bloomTargetError is the target false positive rate when the aggregator - // layer is at its fullest. The actual value will probably move around up - // and down from this number, it's mostly a ballpark figure. - // - // Note, dropping this down might drastically increase the size of the bloom - // filters that's stored in every diff layer. Don't do that without fully - // understanding all the implications. - bloomTargetError = 0.02 - - // bloomSize is the ideal bloom filter size given the maximum number of items - // it's expected to hold and the target false positive error rate. - bloomSize = math.Ceil(float64(aggregatorItemLimit) * math.Log(bloomTargetError) / math.Log(1/math.Pow(2, math.Log(2)))) - - // bloomFuncs is the ideal number of bits a single entry should set in the - // bloom filter to keep its size to a minimum (given it's size and maximum - // entry count). - bloomFuncs = math.Round((bloomSize / float64(aggregatorItemLimit)) * math.Log(2)) - - // the bloom offsets are runtime constants which determines which part of the - // account/storage hash the hasher functions looks at, to determine the - // bloom key for an account/slot. This is randomized at init(), so that the - // global population of nodes do not all display the exact same behaviour with - // regards to bloom content - bloomDestructHasherOffset = 0 - bloomAccountHasherOffset = 0 - bloomStorageHasherOffset = 0 -) - -func init() { - // Init the bloom offsets in the range [0:24] (requires 8 bytes) - bloomDestructHasherOffset = rand.Intn(25) - bloomAccountHasherOffset = rand.Intn(25) - bloomStorageHasherOffset = rand.Intn(25) - - // The destruct and account blooms must be different, as the storage slots - // will check for destruction too for every bloom miss. It should not collide - // with modified accounts. - for bloomAccountHasherOffset == bloomDestructHasherOffset { - bloomAccountHasherOffset = rand.Intn(25) - } -} - -// diffLayer represents a collection of modifications made to a state snapshot -// after running a block on top. It contains one sorted list for the account trie -// and one-one list for each storage tries. -// -// The goal of a diff layer is to act as a journal, tracking recent modifications -// made to the state, that have not yet graduated into a semi-immutable state. -type diffLayer struct { - origin *diskLayer // Base disk layer to directly use on bloom misses - parent snapshot // Parent snapshot modified by this one, never nil - memory uint64 // Approximate guess as to how much memory we use - - root common.Hash // Root hash to which this snapshot diff belongs to - stale atomic.Bool // Signals that the layer became stale (state progressed) - - // destructSet is a very special helper marker. If an account is marked as - // deleted, then it's recorded in this set. However it's allowed that an account - // is included here but still available in other sets(e.g. storageData). The - // reason is the diff layer includes all the changes in a *block*. It can - // happen that in the tx_1, account A is self-destructed while in the tx_2 - // it's recreated. But we still need this marker to indicate the "old" A is - // deleted, all data in other set belongs to the "new" A. - destructSet map[common.Hash]struct{} // Keyed markers for deleted (and potentially) recreated accounts - accountList []common.Hash // List of account for iteration. If it exists, it's sorted, otherwise it's nil - accountData map[common.Hash][]byte // Keyed accounts for direct retrieval (nil means deleted) - storageList map[common.Hash][]common.Hash // List of storage slots for iterated retrievals, one per account. Any existing lists are sorted if non-nil - storageData map[common.Hash]map[common.Hash][]byte // Keyed storage slots for direct retrieval. one per account (nil means deleted) - - diffed *bloomfilter.Filter // Bloom filter tracking all the diffed items up to the disk layer - - lock sync.RWMutex -} - -// destructBloomHash is used to convert a destruct event into a 64 bit mini hash. -func destructBloomHash(h common.Hash) uint64 { - return binary.BigEndian.Uint64(h[bloomDestructHasherOffset : bloomDestructHasherOffset+8]) -} - -// accountBloomHash is used to convert an account hash into a 64 bit mini hash. -func accountBloomHash(h common.Hash) uint64 { - return binary.BigEndian.Uint64(h[bloomAccountHasherOffset : bloomAccountHasherOffset+8]) -} - -// storageBloomHash is used to convert an account hash and a storage hash into a 64 bit mini hash. -func storageBloomHash(h0, h1 common.Hash) uint64 { - return binary.BigEndian.Uint64(h0[bloomStorageHasherOffset:bloomStorageHasherOffset+8]) ^ - binary.BigEndian.Uint64(h1[bloomStorageHasherOffset:bloomStorageHasherOffset+8]) -} - -// newDiffLayer creates a new diff on top of an existing snapshot, whether that's a low -// level persistent database or a hierarchical diff already. -func newDiffLayer(parent snapshot, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer { - // Create the new layer with some pre-allocated data segments - dl := &diffLayer{ - parent: parent, - root: root, - destructSet: destructs, - accountData: accounts, - storageData: storage, - storageList: make(map[common.Hash][]common.Hash), - } - switch parent := parent.(type) { - case *diskLayer: - dl.rebloom(parent) - case *diffLayer: - dl.rebloom(parent.origin) - default: - panic("unknown parent type") - } - // Sanity check that accounts or storage slots are never nil - for accountHash, blob := range accounts { - if blob == nil { - panic(fmt.Sprintf("account %#x nil", accountHash)) - } - // Determine memory size and track the dirty writes - dl.memory += uint64(common.HashLength + len(blob)) - snapshotDirtyAccountWriteMeter.Mark(int64(len(blob))) - } - for accountHash, slots := range storage { - if slots == nil { - panic(fmt.Sprintf("storage %#x nil", accountHash)) - } - // Determine memory size and track the dirty writes - for _, data := range slots { - dl.memory += uint64(common.HashLength + len(data)) - snapshotDirtyStorageWriteMeter.Mark(int64(len(data))) - } - } - dl.memory += uint64(len(destructs) * common.HashLength) - return dl -} - -// rebloom discards the layer's current bloom and rebuilds it from scratch based -// on the parent's and the local diffs. -func (dl *diffLayer) rebloom(origin *diskLayer) { - dl.lock.Lock() - defer dl.lock.Unlock() - - defer func(start time.Time) { - snapshotBloomIndexTimer.Update(time.Since(start)) - }(time.Now()) - - // Inject the new origin that triggered the rebloom - dl.origin = origin - - // Retrieve the parent bloom or create a fresh empty one - if parent, ok := dl.parent.(*diffLayer); ok { - parent.lock.RLock() - dl.diffed, _ = parent.diffed.Copy() - parent.lock.RUnlock() - } else { - dl.diffed, _ = bloomfilter.New(uint64(bloomSize), uint64(bloomFuncs)) - } - // Iterate over all the accounts and storage slots and index them - for hash := range dl.destructSet { - dl.diffed.AddHash(destructBloomHash(hash)) - } - for hash := range dl.accountData { - dl.diffed.AddHash(accountBloomHash(hash)) - } - for accountHash, slots := range dl.storageData { - for storageHash := range slots { - dl.diffed.AddHash(storageBloomHash(accountHash, storageHash)) - } - } - // Calculate the current false positive rate and update the error rate meter. - // This is a bit cheating because subsequent layers will overwrite it, but it - // should be fine, we're only interested in ballpark figures. - k := float64(dl.diffed.K()) - n := float64(dl.diffed.N()) - m := float64(dl.diffed.M()) - snapshotBloomErrorGauge.Update(math.Pow(1.0-math.Exp((-k)*(n+0.5)/(m-1)), k)) -} - -// Root returns the root hash for which this snapshot was made. -func (dl *diffLayer) Root() common.Hash { - return dl.root -} - -// Parent returns the subsequent layer of a diff layer. -func (dl *diffLayer) Parent() snapshot { - dl.lock.RLock() - defer dl.lock.RUnlock() - - return dl.parent -} - -// Stale return whether this layer has become stale (was flattened across) or if -// it's still live. -func (dl *diffLayer) Stale() bool { - return dl.stale.Load() -} - -// Account directly retrieves the account associated with a particular hash in -// the snapshot slim data format. -func (dl *diffLayer) Account(hash common.Hash) (*types.SlimAccount, error) { - data, err := dl.AccountRLP(hash) - if err != nil { - return nil, err - } - if len(data) == 0 { // can be both nil and []byte{} - return nil, nil - } - account := new(types.SlimAccount) - if err := rlp.DecodeBytes(data, account); err != nil { - panic(err) - } - return account, nil -} - -// AccountRLP directly retrieves the account RLP associated with a particular -// hash in the snapshot slim data format. -// -// Note the returned account is not a copy, please don't modify it. -func (dl *diffLayer) AccountRLP(hash common.Hash) ([]byte, error) { - // Check staleness before reaching further. - dl.lock.RLock() - if dl.Stale() { - dl.lock.RUnlock() - return nil, ErrSnapshotStale - } - // Check the bloom filter first whether there's even a point in reaching into - // all the maps in all the layers below - hit := dl.diffed.ContainsHash(accountBloomHash(hash)) - if !hit { - hit = dl.diffed.ContainsHash(destructBloomHash(hash)) - } - var origin *diskLayer - if !hit { - origin = dl.origin // extract origin while holding the lock - } - dl.lock.RUnlock() - - // If the bloom filter misses, don't even bother with traversing the memory - // diff layers, reach straight into the bottom persistent disk layer - if origin != nil { - snapshotBloomAccountMissMeter.Mark(1) - return origin.AccountRLP(hash) - } - // The bloom filter hit, start poking in the internal maps - return dl.accountRLP(hash, 0) -} - -// accountRLP is an internal version of AccountRLP that skips the bloom filter -// checks and uses the internal maps to try and retrieve the data. It's meant -// to be used if a higher layer's bloom filter hit already. -func (dl *diffLayer) accountRLP(hash common.Hash, depth int) ([]byte, error) { - dl.lock.RLock() - defer dl.lock.RUnlock() - - // If the layer was flattened into, consider it invalid (any live reference to - // the original should be marked as unusable). - if dl.Stale() { - return nil, ErrSnapshotStale - } - // If the account is known locally, return it - if data, ok := dl.accountData[hash]; ok { - snapshotDirtyAccountHitMeter.Mark(1) - snapshotDirtyAccountHitDepthHist.Update(int64(depth)) - snapshotDirtyAccountReadMeter.Mark(int64(len(data))) - snapshotBloomAccountTrueHitMeter.Mark(1) - return data, nil - } - // If the account is known locally, but deleted, return it - if _, ok := dl.destructSet[hash]; ok { - snapshotDirtyAccountHitMeter.Mark(1) - snapshotDirtyAccountHitDepthHist.Update(int64(depth)) - snapshotDirtyAccountInexMeter.Mark(1) - snapshotBloomAccountTrueHitMeter.Mark(1) - return nil, nil - } - // Account unknown to this diff, resolve from parent - if diff, ok := dl.parent.(*diffLayer); ok { - return diff.accountRLP(hash, depth+1) - } - // Failed to resolve through diff layers, mark a bloom error and use the disk - snapshotBloomAccountFalseHitMeter.Mark(1) - return dl.parent.AccountRLP(hash) -} - -// Storage directly retrieves the storage data associated with a particular hash, -// within a particular account. If the slot is unknown to this diff, it's parent -// is consulted. -// -// Note the returned slot is not a copy, please don't modify it. -func (dl *diffLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error) { - // Check the bloom filter first whether there's even a point in reaching into - // all the maps in all the layers below - dl.lock.RLock() - // Check staleness before reaching further. - if dl.Stale() { - dl.lock.RUnlock() - return nil, ErrSnapshotStale - } - hit := dl.diffed.ContainsHash(storageBloomHash(accountHash, storageHash)) - if !hit { - hit = dl.diffed.ContainsHash(destructBloomHash(accountHash)) - } - var origin *diskLayer - if !hit { - origin = dl.origin // extract origin while holding the lock - } - dl.lock.RUnlock() - - // If the bloom filter misses, don't even bother with traversing the memory - // diff layers, reach straight into the bottom persistent disk layer - if origin != nil { - snapshotBloomStorageMissMeter.Mark(1) - return origin.Storage(accountHash, storageHash) - } - // The bloom filter hit, start poking in the internal maps - return dl.storage(accountHash, storageHash, 0) -} - -// storage is an internal version of Storage that skips the bloom filter checks -// and uses the internal maps to try and retrieve the data. It's meant to be -// used if a higher layer's bloom filter hit already. -func (dl *diffLayer) storage(accountHash, storageHash common.Hash, depth int) ([]byte, error) { - dl.lock.RLock() - defer dl.lock.RUnlock() - - // If the layer was flattened into, consider it invalid (any live reference to - // the original should be marked as unusable). - if dl.Stale() { - return nil, ErrSnapshotStale - } - // If the account is known locally, try to resolve the slot locally - if storage, ok := dl.storageData[accountHash]; ok { - if data, ok := storage[storageHash]; ok { - snapshotDirtyStorageHitMeter.Mark(1) - snapshotDirtyStorageHitDepthHist.Update(int64(depth)) - if n := len(data); n > 0 { - snapshotDirtyStorageReadMeter.Mark(int64(n)) - } else { - snapshotDirtyStorageInexMeter.Mark(1) - } - snapshotBloomStorageTrueHitMeter.Mark(1) - return data, nil - } - } - // If the account is known locally, but deleted, return an empty slot - if _, ok := dl.destructSet[accountHash]; ok { - snapshotDirtyStorageHitMeter.Mark(1) - snapshotDirtyStorageHitDepthHist.Update(int64(depth)) - snapshotDirtyStorageInexMeter.Mark(1) - snapshotBloomStorageTrueHitMeter.Mark(1) - return nil, nil - } - // Storage slot unknown to this diff, resolve from parent - if diff, ok := dl.parent.(*diffLayer); ok { - return diff.storage(accountHash, storageHash, depth+1) - } - // Failed to resolve through diff layers, mark a bloom error and use the disk - snapshotBloomStorageFalseHitMeter.Mark(1) - return dl.parent.Storage(accountHash, storageHash) -} - -// Update creates a new layer on top of the existing snapshot diff tree with -// the specified data items. -func (dl *diffLayer) Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer { - return newDiffLayer(dl, blockRoot, destructs, accounts, storage) -} - -// flatten pushes all data from this point downwards, flattening everything into -// a single diff at the bottom. Since usually the lowermost diff is the largest, -// the flattening builds up from there in reverse. -func (dl *diffLayer) flatten() snapshot { - // If the parent is not diff, we're the first in line, return unmodified - parent, ok := dl.parent.(*diffLayer) - if !ok { - return dl - } - // Parent is a diff, flatten it first (note, apart from weird corned cases, - // flatten will realistically only ever merge 1 layer, so there's no need to - // be smarter about grouping flattens together). - parent = parent.flatten().(*diffLayer) - - parent.lock.Lock() - defer parent.lock.Unlock() - - // Before actually writing all our data to the parent, first ensure that the - // parent hasn't been 'corrupted' by someone else already flattening into it - if parent.stale.Swap(true) { - panic("parent diff layer is stale") // we've flattened into the same parent from two children, boo - } - // Overwrite all the updated accounts blindly, merge the sorted list - for hash := range dl.destructSet { - parent.destructSet[hash] = struct{}{} - delete(parent.accountData, hash) - delete(parent.storageData, hash) - } - for hash, data := range dl.accountData { - parent.accountData[hash] = data - } - // Overwrite all the updated storage slots (individually) - for accountHash, storage := range dl.storageData { - // If storage didn't exist (or was deleted) in the parent, overwrite blindly - if _, ok := parent.storageData[accountHash]; !ok { - parent.storageData[accountHash] = storage - continue - } - // Storage exists in both parent and child, merge the slots - comboData := parent.storageData[accountHash] - for storageHash, data := range storage { - comboData[storageHash] = data - } - } - // Return the combo parent - return &diffLayer{ - parent: parent.parent, - origin: parent.origin, - root: dl.root, - destructSet: parent.destructSet, - accountData: parent.accountData, - storageData: parent.storageData, - storageList: make(map[common.Hash][]common.Hash), - diffed: dl.diffed, - memory: parent.memory + dl.memory, - } -} - -// AccountList returns a sorted list of all accounts in this diffLayer, including -// the deleted ones. -// -// Note, the returned slice is not a copy, so do not modify it. -func (dl *diffLayer) AccountList() []common.Hash { - // If an old list already exists, return it - dl.lock.RLock() - list := dl.accountList - dl.lock.RUnlock() - - if list != nil { - return list - } - // No old sorted account list exists, generate a new one - dl.lock.Lock() - defer dl.lock.Unlock() - - dl.accountList = make([]common.Hash, 0, len(dl.destructSet)+len(dl.accountData)) - for hash := range dl.accountData { - dl.accountList = append(dl.accountList, hash) - } - for hash := range dl.destructSet { - if _, ok := dl.accountData[hash]; !ok { - dl.accountList = append(dl.accountList, hash) - } - } - slices.SortFunc(dl.accountList, common.Hash.Cmp) - dl.memory += uint64(len(dl.accountList) * common.HashLength) - return dl.accountList -} - -// StorageList returns a sorted list of all storage slot hashes in this diffLayer -// for the given account. If the whole storage is destructed in this layer, then -// an additional flag *destructed = true* will be returned, otherwise the flag is -// false. Besides, the returned list will include the hash of deleted storage slot. -// Note a special case is an account is deleted in a prior tx but is recreated in -// the following tx with some storage slots set. In this case the returned list is -// not empty but the flag is true. -// -// Note, the returned slice is not a copy, so do not modify it. -func (dl *diffLayer) StorageList(accountHash common.Hash) ([]common.Hash, bool) { - dl.lock.RLock() - _, destructed := dl.destructSet[accountHash] - if _, ok := dl.storageData[accountHash]; !ok { - // Account not tracked by this layer - dl.lock.RUnlock() - return nil, destructed - } - // If an old list already exists, return it - if list, exist := dl.storageList[accountHash]; exist { - dl.lock.RUnlock() - return list, destructed // the cached list can't be nil - } - dl.lock.RUnlock() - - // No old sorted account list exists, generate a new one - dl.lock.Lock() - defer dl.lock.Unlock() - - storageMap := dl.storageData[accountHash] - storageList := make([]common.Hash, 0, len(storageMap)) - for k := range storageMap { - storageList = append(storageList, k) - } - slices.SortFunc(storageList, common.Hash.Cmp) - dl.storageList[accountHash] = storageList - dl.memory += uint64(len(dl.storageList)*common.HashLength + common.HashLength) - return storageList, destructed -} diff --git a/builder/core/state/snapshot/difflayer_test.go b/builder/core/state/snapshot/difflayer_test.go deleted file mode 100644 index 674a031b1..000000000 --- a/builder/core/state/snapshot/difflayer_test.go +++ /dev/null @@ -1,399 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - crand "crypto/rand" - "math/rand" - "testing" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb/memorydb" -) - -func copyDestructs(destructs map[common.Hash]struct{}) map[common.Hash]struct{} { - copy := make(map[common.Hash]struct{}) - for hash := range destructs { - copy[hash] = struct{}{} - } - return copy -} - -func copyAccounts(accounts map[common.Hash][]byte) map[common.Hash][]byte { - copy := make(map[common.Hash][]byte) - for hash, blob := range accounts { - copy[hash] = blob - } - return copy -} - -func copyStorage(storage map[common.Hash]map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { - copy := make(map[common.Hash]map[common.Hash][]byte) - for accHash, slots := range storage { - copy[accHash] = make(map[common.Hash][]byte) - for slotHash, blob := range slots { - copy[accHash][slotHash] = blob - } - } - return copy -} - -// TestMergeBasics tests some simple merges -func TestMergeBasics(t *testing.T) { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - // Fill up a parent - for i := 0; i < 100; i++ { - h := randomHash() - data := randomAccount() - - accounts[h] = data - if rand.Intn(4) == 0 { - destructs[h] = struct{}{} - } - if rand.Intn(2) == 0 { - accStorage := make(map[common.Hash][]byte) - value := make([]byte, 32) - crand.Read(value) - accStorage[randomHash()] = value - storage[h] = accStorage - } - } - // Add some (identical) layers on top - parent := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - child := newDiffLayer(parent, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - child = newDiffLayer(child, common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - // And flatten - merged := (child.flatten()).(*diffLayer) - - { // Check account lists - if have, want := len(merged.accountList), 0; have != want { - t.Errorf("accountList wrong: have %v, want %v", have, want) - } - if have, want := len(merged.AccountList()), len(accounts); have != want { - t.Errorf("AccountList() wrong: have %v, want %v", have, want) - } - if have, want := len(merged.accountList), len(accounts); have != want { - t.Errorf("accountList [2] wrong: have %v, want %v", have, want) - } - } - { // Check account drops - if have, want := len(merged.destructSet), len(destructs); have != want { - t.Errorf("accountDrop wrong: have %v, want %v", have, want) - } - } - { // Check storage lists - i := 0 - for aHash, sMap := range storage { - if have, want := len(merged.storageList), i; have != want { - t.Errorf("[1] storageList wrong: have %v, want %v", have, want) - } - list, _ := merged.StorageList(aHash) - if have, want := len(list), len(sMap); have != want { - t.Errorf("[2] StorageList() wrong: have %v, want %v", have, want) - } - if have, want := len(merged.storageList[aHash]), len(sMap); have != want { - t.Errorf("storageList wrong: have %v, want %v", have, want) - } - i++ - } - } -} - -// TestMergeDelete tests some deletion -func TestMergeDelete(t *testing.T) { - var ( - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - // Fill up a parent - h1 := common.HexToHash("0x01") - h2 := common.HexToHash("0x02") - - flipDrops := func() map[common.Hash]struct{} { - return map[common.Hash]struct{}{ - h2: {}, - } - } - flipAccs := func() map[common.Hash][]byte { - return map[common.Hash][]byte{ - h1: randomAccount(), - } - } - flopDrops := func() map[common.Hash]struct{} { - return map[common.Hash]struct{}{ - h1: {}, - } - } - flopAccs := func() map[common.Hash][]byte { - return map[common.Hash][]byte{ - h2: randomAccount(), - } - } - // Add some flipAccs-flopping layers on top - parent := newDiffLayer(emptyLayer(), common.Hash{}, flipDrops(), flipAccs(), storage) - child := parent.Update(common.Hash{}, flopDrops(), flopAccs(), storage) - child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage) - child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage) - child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage) - child = child.Update(common.Hash{}, flopDrops(), flopAccs(), storage) - child = child.Update(common.Hash{}, flipDrops(), flipAccs(), storage) - - if data, _ := child.Account(h1); data == nil { - t.Errorf("last diff layer: expected %x account to be non-nil", h1) - } - if data, _ := child.Account(h2); data != nil { - t.Errorf("last diff layer: expected %x account to be nil", h2) - } - if _, ok := child.destructSet[h1]; ok { - t.Errorf("last diff layer: expected %x drop to be missing", h1) - } - if _, ok := child.destructSet[h2]; !ok { - t.Errorf("last diff layer: expected %x drop to be present", h1) - } - // And flatten - merged := (child.flatten()).(*diffLayer) - - if data, _ := merged.Account(h1); data == nil { - t.Errorf("merged layer: expected %x account to be non-nil", h1) - } - if data, _ := merged.Account(h2); data != nil { - t.Errorf("merged layer: expected %x account to be nil", h2) - } - if _, ok := merged.destructSet[h1]; !ok { // Note, drops stay alive until persisted to disk! - t.Errorf("merged diff layer: expected %x drop to be present", h1) - } - if _, ok := merged.destructSet[h2]; !ok { // Note, drops stay alive until persisted to disk! - t.Errorf("merged diff layer: expected %x drop to be present", h1) - } - // If we add more granular metering of memory, we can enable this again, - // but it's not implemented for now - //if have, want := merged.memory, child.memory; have != want { - // t.Errorf("mem wrong: have %d, want %d", have, want) - //} -} - -// This tests that if we create a new account, and set a slot, and then merge -// it, the lists will be correct. -func TestInsertAndMerge(t *testing.T) { - // Fill up a parent - var ( - acc = common.HexToHash("0x01") - slot = common.HexToHash("0x02") - parent *diffLayer - child *diffLayer - ) - { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - parent = newDiffLayer(emptyLayer(), common.Hash{}, destructs, accounts, storage) - } - { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - accounts[acc] = randomAccount() - storage[acc] = make(map[common.Hash][]byte) - storage[acc][slot] = []byte{0x01} - child = newDiffLayer(parent, common.Hash{}, destructs, accounts, storage) - } - // And flatten - merged := (child.flatten()).(*diffLayer) - { // Check that slot value is present - have, _ := merged.Storage(acc, slot) - if want := []byte{0x01}; !bytes.Equal(have, want) { - t.Errorf("merged slot value wrong: have %x, want %x", have, want) - } - } -} - -func emptyLayer() *diskLayer { - return &diskLayer{ - diskdb: memorydb.New(), - cache: fastcache.New(500 * 1024), - } -} - -// BenchmarkSearch checks how long it takes to find a non-existing key -// BenchmarkSearch-6 200000 10481 ns/op (1K per layer) -// BenchmarkSearch-6 200000 10760 ns/op (10K per layer) -// BenchmarkSearch-6 100000 17866 ns/op -// -// BenchmarkSearch-6 500000 3723 ns/op (10k per layer, only top-level RLock() -func BenchmarkSearch(b *testing.B) { - // First, we set up 128 diff layers, with 1K items each - fill := func(parent snapshot) *diffLayer { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - for i := 0; i < 10000; i++ { - accounts[randomHash()] = randomAccount() - } - return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage) - } - var layer snapshot - layer = emptyLayer() - for i := 0; i < 128; i++ { - layer = fill(layer) - } - key := crypto.Keccak256Hash([]byte{0x13, 0x38}) - b.ResetTimer() - for i := 0; i < b.N; i++ { - layer.AccountRLP(key) - } -} - -// BenchmarkSearchSlot checks how long it takes to find a non-existing key -// - Number of layers: 128 -// - Each layers contains the account, with a couple of storage slots -// BenchmarkSearchSlot-6 100000 14554 ns/op -// BenchmarkSearchSlot-6 100000 22254 ns/op (when checking parent root using mutex) -// BenchmarkSearchSlot-6 100000 14551 ns/op (when checking parent number using atomic) -// With bloom filter: -// BenchmarkSearchSlot-6 3467835 351 ns/op -func BenchmarkSearchSlot(b *testing.B) { - // First, we set up 128 diff layers, with 1K items each - accountKey := crypto.Keccak256Hash([]byte{0x13, 0x37}) - storageKey := crypto.Keccak256Hash([]byte{0x13, 0x37}) - accountRLP := randomAccount() - fill := func(parent snapshot) *diffLayer { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - accounts[accountKey] = accountRLP - - accStorage := make(map[common.Hash][]byte) - for i := 0; i < 5; i++ { - value := make([]byte, 32) - crand.Read(value) - accStorage[randomHash()] = value - storage[accountKey] = accStorage - } - return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage) - } - var layer snapshot - layer = emptyLayer() - for i := 0; i < 128; i++ { - layer = fill(layer) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - layer.Storage(accountKey, storageKey) - } -} - -// With accountList and sorting -// BenchmarkFlatten-6 50 29890856 ns/op -// -// Without sorting and tracking accountList -// BenchmarkFlatten-6 300 5511511 ns/op -func BenchmarkFlatten(b *testing.B) { - fill := func(parent snapshot) *diffLayer { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - for i := 0; i < 100; i++ { - accountKey := randomHash() - accounts[accountKey] = randomAccount() - - accStorage := make(map[common.Hash][]byte) - for i := 0; i < 20; i++ { - value := make([]byte, 32) - crand.Read(value) - accStorage[randomHash()] = value - } - storage[accountKey] = accStorage - } - return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - b.StopTimer() - var layer snapshot - layer = emptyLayer() - for i := 1; i < 128; i++ { - layer = fill(layer) - } - b.StartTimer() - - for i := 1; i < 128; i++ { - dl, ok := layer.(*diffLayer) - if !ok { - break - } - layer = dl.flatten() - } - b.StopTimer() - } -} - -// This test writes ~324M of diff layers to disk, spread over -// - 128 individual layers, -// - each with 200 accounts -// - containing 200 slots -// -// BenchmarkJournal-6 1 1471373923 ns/ops -// BenchmarkJournal-6 1 1208083335 ns/op // bufio writer -func BenchmarkJournal(b *testing.B) { - fill := func(parent snapshot) *diffLayer { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - for i := 0; i < 200; i++ { - accountKey := randomHash() - accounts[accountKey] = randomAccount() - - accStorage := make(map[common.Hash][]byte) - for i := 0; i < 200; i++ { - value := make([]byte, 32) - crand.Read(value) - accStorage[randomHash()] = value - } - storage[accountKey] = accStorage - } - return newDiffLayer(parent, common.Hash{}, destructs, accounts, storage) - } - layer := snapshot(emptyLayer()) - for i := 1; i < 128; i++ { - layer = fill(layer) - } - b.ResetTimer() - - for i := 0; i < b.N; i++ { - layer.Journal(new(bytes.Buffer)) - } -} diff --git a/builder/core/state/snapshot/disklayer.go b/builder/core/state/snapshot/disklayer.go deleted file mode 100644 index f5518a204..000000000 --- a/builder/core/state/snapshot/disklayer.go +++ /dev/null @@ -1,177 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "sync" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/triedb" -) - -// diskLayer is a low level persistent snapshot built on top of a key-value store. -type diskLayer struct { - diskdb ethdb.KeyValueStore // Key-value store containing the base snapshot - triedb *triedb.Database // Trie node cache for reconstruction purposes - cache *fastcache.Cache // Cache to avoid hitting the disk for direct access - - root common.Hash // Root hash of the base snapshot - stale bool // Signals that the layer became stale (state progressed) - - genMarker []byte // Marker for the state that's indexed during initial layer generation - genPending chan struct{} // Notification channel when generation is done (test synchronicity) - genAbort chan chan *generatorStats // Notification channel to abort generating the snapshot in this layer - - lock sync.RWMutex -} - -// Release releases underlying resources; specifically the fastcache requires -// Reset() in order to not leak memory. -// OBS: It does not invoke Close on the diskdb -func (dl *diskLayer) Release() error { - if dl.cache != nil { - dl.cache.Reset() - } - return nil -} - -// Root returns root hash for which this snapshot was made. -func (dl *diskLayer) Root() common.Hash { - return dl.root -} - -// Parent always returns nil as there's no layer below the disk. -func (dl *diskLayer) Parent() snapshot { - return nil -} - -// Stale return whether this layer has become stale (was flattened across) or if -// it's still live. -func (dl *diskLayer) Stale() bool { - dl.lock.RLock() - defer dl.lock.RUnlock() - - return dl.stale -} - -// Account directly retrieves the account associated with a particular hash in -// the snapshot slim data format. -func (dl *diskLayer) Account(hash common.Hash) (*types.SlimAccount, error) { - data, err := dl.AccountRLP(hash) - if err != nil { - return nil, err - } - if len(data) == 0 { // can be both nil and []byte{} - return nil, nil - } - account := new(types.SlimAccount) - if err := rlp.DecodeBytes(data, account); err != nil { - panic(err) - } - return account, nil -} - -// AccountRLP directly retrieves the account RLP associated with a particular -// hash in the snapshot slim data format. -func (dl *diskLayer) AccountRLP(hash common.Hash) ([]byte, error) { - dl.lock.RLock() - defer dl.lock.RUnlock() - - // If the layer was flattened into, consider it invalid (any live reference to - // the original should be marked as unusable). - if dl.stale { - return nil, ErrSnapshotStale - } - // If the layer is being generated, ensure the requested hash has already been - // covered by the generator. - if dl.genMarker != nil && bytes.Compare(hash[:], dl.genMarker) > 0 { - return nil, ErrNotCoveredYet - } - // If we're in the disk layer, all diff layers missed - snapshotDirtyAccountMissMeter.Mark(1) - - // Try to retrieve the account from the memory cache - if blob, found := dl.cache.HasGet(nil, hash[:]); found { - snapshotCleanAccountHitMeter.Mark(1) - snapshotCleanAccountReadMeter.Mark(int64(len(blob))) - return blob, nil - } - // Cache doesn't contain account, pull from disk and cache for later - blob := rawdb.ReadAccountSnapshot(dl.diskdb, hash) - dl.cache.Set(hash[:], blob) - - snapshotCleanAccountMissMeter.Mark(1) - if n := len(blob); n > 0 { - snapshotCleanAccountWriteMeter.Mark(int64(n)) - } else { - snapshotCleanAccountInexMeter.Mark(1) - } - return blob, nil -} - -// Storage directly retrieves the storage data associated with a particular hash, -// within a particular account. -func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error) { - dl.lock.RLock() - defer dl.lock.RUnlock() - - // If the layer was flattened into, consider it invalid (any live reference to - // the original should be marked as unusable). - if dl.stale { - return nil, ErrSnapshotStale - } - key := append(accountHash[:], storageHash[:]...) - - // If the layer is being generated, ensure the requested hash has already been - // covered by the generator. - if dl.genMarker != nil && bytes.Compare(key, dl.genMarker) > 0 { - return nil, ErrNotCoveredYet - } - // If we're in the disk layer, all diff layers missed - snapshotDirtyStorageMissMeter.Mark(1) - - // Try to retrieve the storage slot from the memory cache - if blob, found := dl.cache.HasGet(nil, key); found { - snapshotCleanStorageHitMeter.Mark(1) - snapshotCleanStorageReadMeter.Mark(int64(len(blob))) - return blob, nil - } - // Cache doesn't contain storage slot, pull from disk and cache for later - blob := rawdb.ReadStorageSnapshot(dl.diskdb, accountHash, storageHash) - dl.cache.Set(key, blob) - - snapshotCleanStorageMissMeter.Mark(1) - if n := len(blob); n > 0 { - snapshotCleanStorageWriteMeter.Mark(int64(n)) - } else { - snapshotCleanStorageInexMeter.Mark(1) - } - return blob, nil -} - -// Update creates a new layer on top of the existing snapshot diff tree with -// the specified data items. Note, the maps are retained by the method to avoid -// copying everything. -func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer { - return newDiffLayer(dl, blockHash, destructs, accounts, storage) -} diff --git a/builder/core/state/snapshot/disklayer_test.go b/builder/core/state/snapshot/disklayer_test.go deleted file mode 100644 index 168458c40..000000000 --- a/builder/core/state/snapshot/disklayer_test.go +++ /dev/null @@ -1,574 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "testing" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/rlp" -) - -// reverse reverses the contents of a byte slice. It's used to update random accs -// with deterministic changes. -func reverse(blob []byte) []byte { - res := make([]byte, len(blob)) - for i, b := range blob { - res[len(blob)-1-i] = b - } - return res -} - -// Tests that merging something into a disk layer persists it into the database -// and invalidates any previously written and cached values. -func TestDiskMerge(t *testing.T) { - // Create some accounts in the disk layer - db := memorydb.New() - - var ( - accNoModNoCache = common.Hash{0x1} - accNoModCache = common.Hash{0x2} - accModNoCache = common.Hash{0x3} - accModCache = common.Hash{0x4} - accDelNoCache = common.Hash{0x5} - accDelCache = common.Hash{0x6} - conNoModNoCache = common.Hash{0x7} - conNoModNoCacheSlot = common.Hash{0x70} - conNoModCache = common.Hash{0x8} - conNoModCacheSlot = common.Hash{0x80} - conModNoCache = common.Hash{0x9} - conModNoCacheSlot = common.Hash{0x90} - conModCache = common.Hash{0xa} - conModCacheSlot = common.Hash{0xa0} - conDelNoCache = common.Hash{0xb} - conDelNoCacheSlot = common.Hash{0xb0} - conDelCache = common.Hash{0xc} - conDelCacheSlot = common.Hash{0xc0} - conNukeNoCache = common.Hash{0xd} - conNukeNoCacheSlot = common.Hash{0xd0} - conNukeCache = common.Hash{0xe} - conNukeCacheSlot = common.Hash{0xe0} - baseRoot = randomHash() - diffRoot = randomHash() - ) - - rawdb.WriteAccountSnapshot(db, accNoModNoCache, accNoModNoCache[:]) - rawdb.WriteAccountSnapshot(db, accNoModCache, accNoModCache[:]) - rawdb.WriteAccountSnapshot(db, accModNoCache, accModNoCache[:]) - rawdb.WriteAccountSnapshot(db, accModCache, accModCache[:]) - rawdb.WriteAccountSnapshot(db, accDelNoCache, accDelNoCache[:]) - rawdb.WriteAccountSnapshot(db, accDelCache, accDelCache[:]) - - rawdb.WriteAccountSnapshot(db, conNoModNoCache, conNoModNoCache[:]) - rawdb.WriteStorageSnapshot(db, conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conNoModCache, conNoModCache[:]) - rawdb.WriteStorageSnapshot(db, conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conModNoCache, conModNoCache[:]) - rawdb.WriteStorageSnapshot(db, conModNoCache, conModNoCacheSlot, conModNoCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conModCache, conModCache[:]) - rawdb.WriteStorageSnapshot(db, conModCache, conModCacheSlot, conModCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conDelNoCache, conDelNoCache[:]) - rawdb.WriteStorageSnapshot(db, conDelNoCache, conDelNoCacheSlot, conDelNoCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conDelCache, conDelCache[:]) - rawdb.WriteStorageSnapshot(db, conDelCache, conDelCacheSlot, conDelCacheSlot[:]) - - rawdb.WriteAccountSnapshot(db, conNukeNoCache, conNukeNoCache[:]) - rawdb.WriteStorageSnapshot(db, conNukeNoCache, conNukeNoCacheSlot, conNukeNoCacheSlot[:]) - rawdb.WriteAccountSnapshot(db, conNukeCache, conNukeCache[:]) - rawdb.WriteStorageSnapshot(db, conNukeCache, conNukeCacheSlot, conNukeCacheSlot[:]) - - rawdb.WriteSnapshotRoot(db, baseRoot) - - // Create a disk layer based on the above and cache in some data - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - baseRoot: &diskLayer{ - diskdb: db, - cache: fastcache.New(500 * 1024), - root: baseRoot, - }, - }, - } - base := snaps.Snapshot(baseRoot) - base.AccountRLP(accNoModCache) - base.AccountRLP(accModCache) - base.AccountRLP(accDelCache) - base.Storage(conNoModCache, conNoModCacheSlot) - base.Storage(conModCache, conModCacheSlot) - base.Storage(conDelCache, conDelCacheSlot) - base.Storage(conNukeCache, conNukeCacheSlot) - - // Modify or delete some accounts, flatten everything onto disk - if err := snaps.Update(diffRoot, baseRoot, map[common.Hash]struct{}{ - accDelNoCache: {}, - accDelCache: {}, - conNukeNoCache: {}, - conNukeCache: {}, - }, map[common.Hash][]byte{ - accModNoCache: reverse(accModNoCache[:]), - accModCache: reverse(accModCache[:]), - }, map[common.Hash]map[common.Hash][]byte{ - conModNoCache: {conModNoCacheSlot: reverse(conModNoCacheSlot[:])}, - conModCache: {conModCacheSlot: reverse(conModCacheSlot[:])}, - conDelNoCache: {conDelNoCacheSlot: nil}, - conDelCache: {conDelCacheSlot: nil}, - }); err != nil { - t.Fatalf("failed to update snapshot tree: %v", err) - } - if err := snaps.Cap(diffRoot, 0); err != nil { - t.Fatalf("failed to flatten snapshot tree: %v", err) - } - // Retrieve all the data through the disk layer and validate it - base = snaps.Snapshot(diffRoot) - if _, ok := base.(*diskLayer); !ok { - t.Fatalf("update not flattened into the disk layer") - } - - // assertAccount ensures that an account matches the given blob. - assertAccount := func(account common.Hash, data []byte) { - t.Helper() - blob, err := base.AccountRLP(account) - if err != nil { - t.Errorf("account access (%x) failed: %v", account, err) - } else if !bytes.Equal(blob, data) { - t.Errorf("account access (%x) mismatch: have %x, want %x", account, blob, data) - } - } - assertAccount(accNoModNoCache, accNoModNoCache[:]) - assertAccount(accNoModCache, accNoModCache[:]) - assertAccount(accModNoCache, reverse(accModNoCache[:])) - assertAccount(accModCache, reverse(accModCache[:])) - assertAccount(accDelNoCache, nil) - assertAccount(accDelCache, nil) - - // assertStorage ensures that a storage slot matches the given blob. - assertStorage := func(account common.Hash, slot common.Hash, data []byte) { - t.Helper() - blob, err := base.Storage(account, slot) - if err != nil { - t.Errorf("storage access (%x:%x) failed: %v", account, slot, err) - } else if !bytes.Equal(blob, data) { - t.Errorf("storage access (%x:%x) mismatch: have %x, want %x", account, slot, blob, data) - } - } - assertStorage(conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - assertStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - assertStorage(conModNoCache, conModNoCacheSlot, reverse(conModNoCacheSlot[:])) - assertStorage(conModCache, conModCacheSlot, reverse(conModCacheSlot[:])) - assertStorage(conDelNoCache, conDelNoCacheSlot, nil) - assertStorage(conDelCache, conDelCacheSlot, nil) - assertStorage(conNukeNoCache, conNukeNoCacheSlot, nil) - assertStorage(conNukeCache, conNukeCacheSlot, nil) - - // Retrieve all the data directly from the database and validate it - - // assertDatabaseAccount ensures that an account from the database matches the given blob. - assertDatabaseAccount := func(account common.Hash, data []byte) { - t.Helper() - if blob := rawdb.ReadAccountSnapshot(db, account); !bytes.Equal(blob, data) { - t.Errorf("account database access (%x) mismatch: have %x, want %x", account, blob, data) - } - } - assertDatabaseAccount(accNoModNoCache, accNoModNoCache[:]) - assertDatabaseAccount(accNoModCache, accNoModCache[:]) - assertDatabaseAccount(accModNoCache, reverse(accModNoCache[:])) - assertDatabaseAccount(accModCache, reverse(accModCache[:])) - assertDatabaseAccount(accDelNoCache, nil) - assertDatabaseAccount(accDelCache, nil) - - // assertDatabaseStorage ensures that a storage slot from the database matches the given blob. - assertDatabaseStorage := func(account common.Hash, slot common.Hash, data []byte) { - t.Helper() - if blob := rawdb.ReadStorageSnapshot(db, account, slot); !bytes.Equal(blob, data) { - t.Errorf("storage database access (%x:%x) mismatch: have %x, want %x", account, slot, blob, data) - } - } - assertDatabaseStorage(conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - assertDatabaseStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - assertDatabaseStorage(conModNoCache, conModNoCacheSlot, reverse(conModNoCacheSlot[:])) - assertDatabaseStorage(conModCache, conModCacheSlot, reverse(conModCacheSlot[:])) - assertDatabaseStorage(conDelNoCache, conDelNoCacheSlot, nil) - assertDatabaseStorage(conDelCache, conDelCacheSlot, nil) - assertDatabaseStorage(conNukeNoCache, conNukeNoCacheSlot, nil) - assertDatabaseStorage(conNukeCache, conNukeCacheSlot, nil) -} - -// Tests that merging something into a disk layer persists it into the database -// and invalidates any previously written and cached values, discarding anything -// after the in-progress generation marker. -func TestDiskPartialMerge(t *testing.T) { - // Iterate the test a few times to ensure we pick various internal orderings - // for the data slots as well as the progress marker. - for i := 0; i < 1024; i++ { - // Create some accounts in the disk layer - db := memorydb.New() - - var ( - accNoModNoCache = randomHash() - accNoModCache = randomHash() - accModNoCache = randomHash() - accModCache = randomHash() - accDelNoCache = randomHash() - accDelCache = randomHash() - conNoModNoCache = randomHash() - conNoModNoCacheSlot = randomHash() - conNoModCache = randomHash() - conNoModCacheSlot = randomHash() - conModNoCache = randomHash() - conModNoCacheSlot = randomHash() - conModCache = randomHash() - conModCacheSlot = randomHash() - conDelNoCache = randomHash() - conDelNoCacheSlot = randomHash() - conDelCache = randomHash() - conDelCacheSlot = randomHash() - conNukeNoCache = randomHash() - conNukeNoCacheSlot = randomHash() - conNukeCache = randomHash() - conNukeCacheSlot = randomHash() - baseRoot = randomHash() - diffRoot = randomHash() - genMarker = append(randomHash().Bytes(), randomHash().Bytes()...) - ) - - // insertAccount injects an account into the database if it's after the - // generator marker, drops the op otherwise. This is needed to seed the - // database with a valid starting snapshot. - insertAccount := func(account common.Hash, data []byte) { - if bytes.Compare(account[:], genMarker) <= 0 { - rawdb.WriteAccountSnapshot(db, account, data[:]) - } - } - insertAccount(accNoModNoCache, accNoModNoCache[:]) - insertAccount(accNoModCache, accNoModCache[:]) - insertAccount(accModNoCache, accModNoCache[:]) - insertAccount(accModCache, accModCache[:]) - insertAccount(accDelNoCache, accDelNoCache[:]) - insertAccount(accDelCache, accDelCache[:]) - - // insertStorage injects a storage slot into the database if it's after - // the generator marker, drops the op otherwise. This is needed to seed - // the database with a valid starting snapshot. - insertStorage := func(account common.Hash, slot common.Hash, data []byte) { - if bytes.Compare(append(account[:], slot[:]...), genMarker) <= 0 { - rawdb.WriteStorageSnapshot(db, account, slot, data[:]) - } - } - insertAccount(conNoModNoCache, conNoModNoCache[:]) - insertStorage(conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - insertAccount(conNoModCache, conNoModCache[:]) - insertStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - insertAccount(conModNoCache, conModNoCache[:]) - insertStorage(conModNoCache, conModNoCacheSlot, conModNoCacheSlot[:]) - insertAccount(conModCache, conModCache[:]) - insertStorage(conModCache, conModCacheSlot, conModCacheSlot[:]) - insertAccount(conDelNoCache, conDelNoCache[:]) - insertStorage(conDelNoCache, conDelNoCacheSlot, conDelNoCacheSlot[:]) - insertAccount(conDelCache, conDelCache[:]) - insertStorage(conDelCache, conDelCacheSlot, conDelCacheSlot[:]) - - insertAccount(conNukeNoCache, conNukeNoCache[:]) - insertStorage(conNukeNoCache, conNukeNoCacheSlot, conNukeNoCacheSlot[:]) - insertAccount(conNukeCache, conNukeCache[:]) - insertStorage(conNukeCache, conNukeCacheSlot, conNukeCacheSlot[:]) - - rawdb.WriteSnapshotRoot(db, baseRoot) - - // Create a disk layer based on the above using a random progress marker - // and cache in some data. - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - baseRoot: &diskLayer{ - diskdb: db, - cache: fastcache.New(500 * 1024), - root: baseRoot, - }, - }, - } - snaps.layers[baseRoot].(*diskLayer).genMarker = genMarker - base := snaps.Snapshot(baseRoot) - - // assertAccount ensures that an account matches the given blob if it's - // already covered by the disk snapshot, and errors out otherwise. - assertAccount := func(account common.Hash, data []byte) { - t.Helper() - blob, err := base.AccountRLP(account) - if bytes.Compare(account[:], genMarker) > 0 && err != ErrNotCoveredYet { - t.Fatalf("test %d: post-marker (%x) account access (%x) succeeded: %x", i, genMarker, account, blob) - } - if bytes.Compare(account[:], genMarker) <= 0 && !bytes.Equal(blob, data) { - t.Fatalf("test %d: pre-marker (%x) account access (%x) mismatch: have %x, want %x", i, genMarker, account, blob, data) - } - } - assertAccount(accNoModCache, accNoModCache[:]) - assertAccount(accModCache, accModCache[:]) - assertAccount(accDelCache, accDelCache[:]) - - // assertStorage ensures that a storage slot matches the given blob if - // it's already covered by the disk snapshot, and errors out otherwise. - assertStorage := func(account common.Hash, slot common.Hash, data []byte) { - t.Helper() - blob, err := base.Storage(account, slot) - if bytes.Compare(append(account[:], slot[:]...), genMarker) > 0 && err != ErrNotCoveredYet { - t.Fatalf("test %d: post-marker (%x) storage access (%x:%x) succeeded: %x", i, genMarker, account, slot, blob) - } - if bytes.Compare(append(account[:], slot[:]...), genMarker) <= 0 && !bytes.Equal(blob, data) { - t.Fatalf("test %d: pre-marker (%x) storage access (%x:%x) mismatch: have %x, want %x", i, genMarker, account, slot, blob, data) - } - } - assertStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - assertStorage(conModCache, conModCacheSlot, conModCacheSlot[:]) - assertStorage(conDelCache, conDelCacheSlot, conDelCacheSlot[:]) - assertStorage(conNukeCache, conNukeCacheSlot, conNukeCacheSlot[:]) - - // Modify or delete some accounts, flatten everything onto disk - if err := snaps.Update(diffRoot, baseRoot, map[common.Hash]struct{}{ - accDelNoCache: {}, - accDelCache: {}, - conNukeNoCache: {}, - conNukeCache: {}, - }, map[common.Hash][]byte{ - accModNoCache: reverse(accModNoCache[:]), - accModCache: reverse(accModCache[:]), - }, map[common.Hash]map[common.Hash][]byte{ - conModNoCache: {conModNoCacheSlot: reverse(conModNoCacheSlot[:])}, - conModCache: {conModCacheSlot: reverse(conModCacheSlot[:])}, - conDelNoCache: {conDelNoCacheSlot: nil}, - conDelCache: {conDelCacheSlot: nil}, - }); err != nil { - t.Fatalf("test %d: failed to update snapshot tree: %v", i, err) - } - if err := snaps.Cap(diffRoot, 0); err != nil { - t.Fatalf("test %d: failed to flatten snapshot tree: %v", i, err) - } - // Retrieve all the data through the disk layer and validate it - base = snaps.Snapshot(diffRoot) - if _, ok := base.(*diskLayer); !ok { - t.Fatalf("test %d: update not flattened into the disk layer", i) - } - assertAccount(accNoModNoCache, accNoModNoCache[:]) - assertAccount(accNoModCache, accNoModCache[:]) - assertAccount(accModNoCache, reverse(accModNoCache[:])) - assertAccount(accModCache, reverse(accModCache[:])) - assertAccount(accDelNoCache, nil) - assertAccount(accDelCache, nil) - - assertStorage(conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - assertStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - assertStorage(conModNoCache, conModNoCacheSlot, reverse(conModNoCacheSlot[:])) - assertStorage(conModCache, conModCacheSlot, reverse(conModCacheSlot[:])) - assertStorage(conDelNoCache, conDelNoCacheSlot, nil) - assertStorage(conDelCache, conDelCacheSlot, nil) - assertStorage(conNukeNoCache, conNukeNoCacheSlot, nil) - assertStorage(conNukeCache, conNukeCacheSlot, nil) - - // Retrieve all the data directly from the database and validate it - - // assertDatabaseAccount ensures that an account inside the database matches - // the given blob if it's already covered by the disk snapshot, and does not - // exist otherwise. - assertDatabaseAccount := func(account common.Hash, data []byte) { - t.Helper() - blob := rawdb.ReadAccountSnapshot(db, account) - if bytes.Compare(account[:], genMarker) > 0 && blob != nil { - t.Fatalf("test %d: post-marker (%x) account database access (%x) succeeded: %x", i, genMarker, account, blob) - } - if bytes.Compare(account[:], genMarker) <= 0 && !bytes.Equal(blob, data) { - t.Fatalf("test %d: pre-marker (%x) account database access (%x) mismatch: have %x, want %x", i, genMarker, account, blob, data) - } - } - assertDatabaseAccount(accNoModNoCache, accNoModNoCache[:]) - assertDatabaseAccount(accNoModCache, accNoModCache[:]) - assertDatabaseAccount(accModNoCache, reverse(accModNoCache[:])) - assertDatabaseAccount(accModCache, reverse(accModCache[:])) - assertDatabaseAccount(accDelNoCache, nil) - assertDatabaseAccount(accDelCache, nil) - - // assertDatabaseStorage ensures that a storage slot inside the database - // matches the given blob if it's already covered by the disk snapshot, - // and does not exist otherwise. - assertDatabaseStorage := func(account common.Hash, slot common.Hash, data []byte) { - t.Helper() - blob := rawdb.ReadStorageSnapshot(db, account, slot) - if bytes.Compare(append(account[:], slot[:]...), genMarker) > 0 && blob != nil { - t.Fatalf("test %d: post-marker (%x) storage database access (%x:%x) succeeded: %x", i, genMarker, account, slot, blob) - } - if bytes.Compare(append(account[:], slot[:]...), genMarker) <= 0 && !bytes.Equal(blob, data) { - t.Fatalf("test %d: pre-marker (%x) storage database access (%x:%x) mismatch: have %x, want %x", i, genMarker, account, slot, blob, data) - } - } - assertDatabaseStorage(conNoModNoCache, conNoModNoCacheSlot, conNoModNoCacheSlot[:]) - assertDatabaseStorage(conNoModCache, conNoModCacheSlot, conNoModCacheSlot[:]) - assertDatabaseStorage(conModNoCache, conModNoCacheSlot, reverse(conModNoCacheSlot[:])) - assertDatabaseStorage(conModCache, conModCacheSlot, reverse(conModCacheSlot[:])) - assertDatabaseStorage(conDelNoCache, conDelNoCacheSlot, nil) - assertDatabaseStorage(conDelCache, conDelCacheSlot, nil) - assertDatabaseStorage(conNukeNoCache, conNukeNoCacheSlot, nil) - assertDatabaseStorage(conNukeCache, conNukeCacheSlot, nil) - } -} - -// Tests that when the bottom-most diff layer is merged into the disk -// layer whether the corresponding generator is persisted correctly. -func TestDiskGeneratorPersistence(t *testing.T) { - var ( - accOne = randomHash() - accTwo = randomHash() - accOneSlotOne = randomHash() - accOneSlotTwo = randomHash() - - accThree = randomHash() - accThreeSlot = randomHash() - baseRoot = randomHash() - diffRoot = randomHash() - diffTwoRoot = randomHash() - genMarker = append(randomHash().Bytes(), randomHash().Bytes()...) - ) - // Testing scenario 1, the disk layer is still under the construction. - db := rawdb.NewMemoryDatabase() - - rawdb.WriteAccountSnapshot(db, accOne, accOne[:]) - rawdb.WriteStorageSnapshot(db, accOne, accOneSlotOne, accOneSlotOne[:]) - rawdb.WriteStorageSnapshot(db, accOne, accOneSlotTwo, accOneSlotTwo[:]) - rawdb.WriteSnapshotRoot(db, baseRoot) - - // Create a disk layer based on all above updates - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - baseRoot: &diskLayer{ - diskdb: db, - cache: fastcache.New(500 * 1024), - root: baseRoot, - genMarker: genMarker, - }, - }, - } - // Modify or delete some accounts, flatten everything onto disk - if err := snaps.Update(diffRoot, baseRoot, nil, map[common.Hash][]byte{ - accTwo: accTwo[:], - }, nil); err != nil { - t.Fatalf("failed to update snapshot tree: %v", err) - } - if err := snaps.Cap(diffRoot, 0); err != nil { - t.Fatalf("failed to flatten snapshot tree: %v", err) - } - blob := rawdb.ReadSnapshotGenerator(db) - var generator journalGenerator - if err := rlp.DecodeBytes(blob, &generator); err != nil { - t.Fatalf("Failed to decode snapshot generator %v", err) - } - if !bytes.Equal(generator.Marker, genMarker) { - t.Fatalf("Generator marker is not matched") - } - // Test scenario 2, the disk layer is fully generated - // Modify or delete some accounts, flatten everything onto disk - if err := snaps.Update(diffTwoRoot, diffRoot, nil, map[common.Hash][]byte{ - accThree: accThree.Bytes(), - }, map[common.Hash]map[common.Hash][]byte{ - accThree: {accThreeSlot: accThreeSlot.Bytes()}, - }); err != nil { - t.Fatalf("failed to update snapshot tree: %v", err) - } - diskLayer := snaps.layers[snaps.diskRoot()].(*diskLayer) - diskLayer.genMarker = nil // Construction finished - if err := snaps.Cap(diffTwoRoot, 0); err != nil { - t.Fatalf("failed to flatten snapshot tree: %v", err) - } - blob = rawdb.ReadSnapshotGenerator(db) - if err := rlp.DecodeBytes(blob, &generator); err != nil { - t.Fatalf("Failed to decode snapshot generator %v", err) - } - if len(generator.Marker) != 0 { - t.Fatalf("Failed to update snapshot generator") - } -} - -// Tests that merging something into a disk layer persists it into the database -// and invalidates any previously written and cached values, discarding anything -// after the in-progress generation marker. -// -// This test case is a tiny specialized case of TestDiskPartialMerge, which tests -// some very specific cornercases that random tests won't ever trigger. -func TestDiskMidAccountPartialMerge(t *testing.T) { - // TODO(@karalabe) ? -} - -// TestDiskSeek tests that seek-operations work on the disk layer -func TestDiskSeek(t *testing.T) { - // Create some accounts in the disk layer - db := rawdb.NewMemoryDatabase() - defer db.Close() - - // Fill even keys [0,2,4...] - for i := 0; i < 0xff; i += 2 { - acc := common.Hash{byte(i)} - rawdb.WriteAccountSnapshot(db, acc, acc[:]) - } - // Add an 'higher' key, with incorrect (higher) prefix - highKey := []byte{rawdb.SnapshotAccountPrefix[0] + 1} - db.Put(highKey, []byte{0xff, 0xff}) - - baseRoot := randomHash() - rawdb.WriteSnapshotRoot(db, baseRoot) - - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - baseRoot: &diskLayer{ - diskdb: db, - cache: fastcache.New(500 * 1024), - root: baseRoot, - }, - }, - } - // Test some different seek positions - type testcase struct { - pos byte - expkey byte - } - var cases = []testcase{ - {0xff, 0x55}, // this should exit immediately without checking key - {0x01, 0x02}, - {0xfe, 0xfe}, - {0xfd, 0xfe}, - {0x00, 0x00}, - } - for i, tc := range cases { - it, err := snaps.AccountIterator(baseRoot, common.Hash{tc.pos}) - if err != nil { - t.Fatalf("case %d, error: %v", i, err) - } - count := 0 - for it.Next() { - k, v, err := it.Hash()[0], it.Account()[0], it.Error() - if err != nil { - t.Fatalf("test %d, item %d, error: %v", i, count, err) - } - // First item in iterator should have the expected key - if count == 0 && k != tc.expkey { - t.Fatalf("test %d, item %d, got %v exp %v", i, count, k, tc.expkey) - } - count++ - if v != k { - t.Fatalf("test %d, item %d, value wrong, got %v exp %v", i, count, v, k) - } - } - } -} diff --git a/builder/core/state/snapshot/generate.go b/builder/core/state/snapshot/generate.go deleted file mode 100644 index 8de4b134d..000000000 --- a/builder/core/state/snapshot/generate.go +++ /dev/null @@ -1,750 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "errors" - "fmt" - "time" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/triedb" -) - -var ( - // accountCheckRange is the upper limit of the number of accounts involved in - // each range check. This is a value estimated based on experience. If this - // range is too large, the failure rate of range proof will increase. Otherwise, - // if the range is too small, the efficiency of the state recovery will decrease. - accountCheckRange = 128 - - // storageCheckRange is the upper limit of the number of storage slots involved - // in each range check. This is a value estimated based on experience. If this - // range is too large, the failure rate of range proof will increase. Otherwise, - // if the range is too small, the efficiency of the state recovery will decrease. - storageCheckRange = 1024 - - // errMissingTrie is returned if the target trie is missing while the generation - // is running. In this case the generation is aborted and wait the new signal. - errMissingTrie = errors.New("missing trie") -) - -// generateSnapshot regenerates a brand new snapshot based on an existing state -// database and head block asynchronously. The snapshot is returned immediately -// and generation is continued in the background until done. -func generateSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, cache int, root common.Hash) *diskLayer { - // Create a new disk layer with an initialized state marker at zero - var ( - stats = &generatorStats{start: time.Now()} - batch = diskdb.NewBatch() - genMarker = []byte{} // Initialized but empty! - ) - rawdb.WriteSnapshotRoot(batch, root) - journalProgress(batch, genMarker, stats) - if err := batch.Write(); err != nil { - log.Crit("Failed to write initialized state marker", "err", err) - } - base := &diskLayer{ - diskdb: diskdb, - triedb: triedb, - root: root, - cache: fastcache.New(cache * 1024 * 1024), - genMarker: genMarker, - genPending: make(chan struct{}), - genAbort: make(chan chan *generatorStats), - } - go base.generate(stats) - log.Debug("Start snapshot generation", "root", root) - return base -} - -// journalProgress persists the generator stats into the database to resume later. -func journalProgress(db ethdb.KeyValueWriter, marker []byte, stats *generatorStats) { - // Write out the generator marker. Note it's a standalone disk layer generator - // which is not mixed with journal. It's ok if the generator is persisted while - // journal is not. - entry := journalGenerator{ - Done: marker == nil, - Marker: marker, - } - if stats != nil { - entry.Accounts = stats.accounts - entry.Slots = stats.slots - entry.Storage = uint64(stats.storage) - } - blob, err := rlp.EncodeToBytes(entry) - if err != nil { - panic(err) // Cannot happen, here to catch dev errors - } - var logstr string - switch { - case marker == nil: - logstr = "done" - case bytes.Equal(marker, []byte{}): - logstr = "empty" - case len(marker) == common.HashLength: - logstr = fmt.Sprintf("%#x", marker) - default: - logstr = fmt.Sprintf("%#x:%#x", marker[:common.HashLength], marker[common.HashLength:]) - } - log.Debug("Journalled generator progress", "progress", logstr) - rawdb.WriteSnapshotGenerator(db, blob) -} - -// proofResult contains the output of range proving which can be used -// for further processing regardless if it is successful or not. -type proofResult struct { - keys [][]byte // The key set of all elements being iterated, even proving is failed - vals [][]byte // The val set of all elements being iterated, even proving is failed - diskMore bool // Set when the database has extra snapshot states since last iteration - trieMore bool // Set when the trie has extra snapshot states(only meaningful for successful proving) - proofErr error // Indicator whether the given state range is valid or not - tr *trie.Trie // The trie, in case the trie was resolved by the prover (may be nil) -} - -// valid returns the indicator that range proof is successful or not. -func (result *proofResult) valid() bool { - return result.proofErr == nil -} - -// last returns the last verified element key regardless of whether the range proof is -// successful or not. Nil is returned if nothing involved in the proving. -func (result *proofResult) last() []byte { - var last []byte - if len(result.keys) > 0 { - last = result.keys[len(result.keys)-1] - } - return last -} - -// forEach iterates all the visited elements and applies the given callback on them. -// The iteration is aborted if the callback returns non-nil error. -func (result *proofResult) forEach(callback func(key []byte, val []byte) error) error { - for i := 0; i < len(result.keys); i++ { - key, val := result.keys[i], result.vals[i] - if err := callback(key, val); err != nil { - return err - } - } - return nil -} - -// proveRange proves the snapshot segment with particular prefix is "valid". -// The iteration start point will be assigned if the iterator is restored from -// the last interruption. Max will be assigned in order to limit the maximum -// amount of data involved in each iteration. -// -// The proof result will be returned if the range proving is finished, otherwise -// the error will be returned to abort the entire procedure. -func (dl *diskLayer) proveRange(ctx *generatorContext, trieId *trie.ID, prefix []byte, kind string, origin []byte, max int, valueConvertFn func([]byte) ([]byte, error)) (*proofResult, error) { - var ( - keys [][]byte - vals [][]byte - proof = rawdb.NewMemoryDatabase() - diskMore = false - iter = ctx.iterator(kind) - start = time.Now() - min = append(prefix, origin...) - ) - for iter.Next() { - // Ensure the iterated item is always equal or larger than the given origin. - key := iter.Key() - if bytes.Compare(key, min) < 0 { - return nil, errors.New("invalid iteration position") - } - // Ensure the iterated item still fall in the specified prefix. If - // not which means the items in the specified area are all visited. - // Move the iterator a step back since we iterate one extra element - // out. - if !bytes.Equal(key[:len(prefix)], prefix) { - iter.Hold() - break - } - // Break if we've reached the max size, and signal that we're not - // done yet. Move the iterator a step back since we iterate one - // extra element out. - if len(keys) == max { - iter.Hold() - diskMore = true - break - } - keys = append(keys, common.CopyBytes(key[len(prefix):])) - - if valueConvertFn == nil { - vals = append(vals, common.CopyBytes(iter.Value())) - } else { - val, err := valueConvertFn(iter.Value()) - if err != nil { - // Special case, the state data is corrupted (invalid slim-format account), - // don't abort the entire procedure directly. Instead, let the fallback - // generation to heal the invalid data. - // - // Here append the original value to ensure that the number of key and - // value are aligned. - vals = append(vals, common.CopyBytes(iter.Value())) - log.Error("Failed to convert account state data", "err", err) - } else { - vals = append(vals, val) - } - } - } - // Update metrics for database iteration and merkle proving - if kind == snapStorage { - snapStorageSnapReadCounter.Inc(time.Since(start).Nanoseconds()) - } else { - snapAccountSnapReadCounter.Inc(time.Since(start).Nanoseconds()) - } - defer func(start time.Time) { - if kind == snapStorage { - snapStorageProveCounter.Inc(time.Since(start).Nanoseconds()) - } else { - snapAccountProveCounter.Inc(time.Since(start).Nanoseconds()) - } - }(time.Now()) - - // The snap state is exhausted, pass the entire key/val set for verification - root := trieId.Root - if origin == nil && !diskMore { - stackTr := trie.NewStackTrie(nil) - for i, key := range keys { - if err := stackTr.Update(key, vals[i]); err != nil { - return nil, err - } - } - if gotRoot := stackTr.Hash(); gotRoot != root { - return &proofResult{ - keys: keys, - vals: vals, - proofErr: fmt.Errorf("wrong root: have %#x want %#x", gotRoot, root), - }, nil - } - return &proofResult{keys: keys, vals: vals}, nil - } - // Snap state is chunked, generate edge proofs for verification. - tr, err := trie.New(trieId, dl.triedb) - if err != nil { - ctx.stats.Log("Trie missing, state snapshotting paused", dl.root, dl.genMarker) - return nil, errMissingTrie - } - // Generate the Merkle proofs for the first and last element - if origin == nil { - origin = common.Hash{}.Bytes() - } - if err := tr.Prove(origin, proof); err != nil { - log.Debug("Failed to prove range", "kind", kind, "origin", origin, "err", err) - return &proofResult{ - keys: keys, - vals: vals, - diskMore: diskMore, - proofErr: err, - tr: tr, - }, nil - } - if len(keys) > 0 { - if err := tr.Prove(keys[len(keys)-1], proof); err != nil { - log.Debug("Failed to prove range", "kind", kind, "last", keys[len(keys)-1], "err", err) - return &proofResult{ - keys: keys, - vals: vals, - diskMore: diskMore, - proofErr: err, - tr: tr, - }, nil - } - } - // Verify the snapshot segment with range prover, ensure that all flat states - // in this range correspond to merkle trie. - cont, err := trie.VerifyRangeProof(root, origin, keys, vals, proof) - return &proofResult{ - keys: keys, - vals: vals, - diskMore: diskMore, - trieMore: cont, - proofErr: err, - tr: tr}, - nil -} - -// onStateCallback is a function that is called by generateRange, when processing a range of -// accounts or storage slots. For each element, the callback is invoked. -// -// - If 'delete' is true, then this element (and potential slots) needs to be deleted from the snapshot. -// - If 'write' is true, then this element needs to be updated with the 'val'. -// - If 'write' is false, then this element is already correct, and needs no update. -// The 'val' is the canonical encoding of the value (not the slim format for accounts) -// -// However, for accounts, the storage trie of the account needs to be checked. Also, -// dangling storages(storage exists but the corresponding account is missing) need to -// be cleaned up. -type onStateCallback func(key []byte, val []byte, write bool, delete bool) error - -// generateRange generates the state segment with particular prefix. Generation can -// either verify the correctness of existing state through range-proof and skip -// generation, or iterate trie to regenerate state on demand. -func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefix []byte, kind string, origin []byte, max int, onState onStateCallback, valueConvertFn func([]byte) ([]byte, error)) (bool, []byte, error) { - // Use range prover to check the validity of the flat state in the range - result, err := dl.proveRange(ctx, trieId, prefix, kind, origin, max, valueConvertFn) - if err != nil { - return false, nil, err - } - last := result.last() - - // Construct contextual logger - logCtx := []interface{}{"kind", kind, "prefix", hexutil.Encode(prefix)} - if len(origin) > 0 { - logCtx = append(logCtx, "origin", hexutil.Encode(origin)) - } - logger := log.New(logCtx...) - - // The range prover says the range is correct, skip trie iteration - if result.valid() { - snapSuccessfulRangeProofMeter.Mark(1) - logger.Trace("Proved state range", "last", hexutil.Encode(last)) - - // The verification is passed, process each state with the given - // callback function. If this state represents a contract, the - // corresponding storage check will be performed in the callback - if err := result.forEach(func(key []byte, val []byte) error { return onState(key, val, false, false) }); err != nil { - return false, nil, err - } - // Only abort the iteration when both database and trie are exhausted - return !result.diskMore && !result.trieMore, last, nil - } - logger.Trace("Detected outdated state range", "last", hexutil.Encode(last), "err", result.proofErr) - snapFailedRangeProofMeter.Mark(1) - - // Special case, the entire trie is missing. In the original trie scheme, - // all the duplicated subtries will be filtered out (only one copy of data - // will be stored). While in the snapshot model, all the storage tries - // belong to different contracts will be kept even they are duplicated. - // Track it to a certain extent remove the noise data used for statistics. - if origin == nil && last == nil { - meter := snapMissallAccountMeter - if kind == snapStorage { - meter = snapMissallStorageMeter - } - meter.Mark(1) - } - // We use the snap data to build up a cache which can be used by the - // main account trie as a primary lookup when resolving hashes - var resolver trie.NodeResolver - if len(result.keys) > 0 { - mdb := rawdb.NewMemoryDatabase() - tdb := triedb.NewDatabase(mdb, triedb.HashDefaults) - defer tdb.Close() - snapTrie := trie.NewEmpty(tdb) - for i, key := range result.keys { - snapTrie.Update(key, result.vals[i]) - } - root, nodes, err := snapTrie.Commit(false) - if err != nil { - return false, nil, err - } - if nodes != nil { - tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) - tdb.Commit(root, false) - } - resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte { - return rawdb.ReadTrieNode(mdb, owner, path, hash, tdb.Scheme()) - } - } - // Construct the trie for state iteration, reuse the trie - // if it's already opened with some nodes resolved. - tr := result.tr - if tr == nil { - tr, err = trie.New(trieId, dl.triedb) - if err != nil { - ctx.stats.Log("Trie missing, state snapshotting paused", dl.root, dl.genMarker) - return false, nil, errMissingTrie - } - } - var ( - trieMore bool - kvkeys, kvvals = result.keys, result.vals - - // counters - count = 0 // number of states delivered by iterator - created = 0 // states created from the trie - updated = 0 // states updated from the trie - deleted = 0 // states not in trie, but were in snapshot - untouched = 0 // states already correct - - // timers - start = time.Now() - internal time.Duration - ) - nodeIt, err := tr.NodeIterator(origin) - if err != nil { - return false, nil, err - } - nodeIt.AddResolver(resolver) - iter := trie.NewIterator(nodeIt) - - for iter.Next() { - if last != nil && bytes.Compare(iter.Key, last) > 0 { - trieMore = true - break - } - count++ - write := true - created++ - for len(kvkeys) > 0 { - if cmp := bytes.Compare(kvkeys[0], iter.Key); cmp < 0 { - // delete the key - istart := time.Now() - if err := onState(kvkeys[0], nil, false, true); err != nil { - return false, nil, err - } - kvkeys = kvkeys[1:] - kvvals = kvvals[1:] - deleted++ - internal += time.Since(istart) - continue - } else if cmp == 0 { - // the snapshot key can be overwritten - created-- - if write = !bytes.Equal(kvvals[0], iter.Value); write { - updated++ - } else { - untouched++ - } - kvkeys = kvkeys[1:] - kvvals = kvvals[1:] - } - break - } - istart := time.Now() - if err := onState(iter.Key, iter.Value, write, false); err != nil { - return false, nil, err - } - internal += time.Since(istart) - } - if iter.Err != nil { - // Trie errors should never happen. Still, in case of a bug, expose the - // error here, as the outer code will presume errors are interrupts, not - // some deeper issues. - log.Error("State snapshotter failed to iterate trie", "err", iter.Err) - return false, nil, iter.Err - } - // Delete all stale snapshot states remaining - istart := time.Now() - for _, key := range kvkeys { - if err := onState(key, nil, false, true); err != nil { - return false, nil, err - } - deleted += 1 - } - internal += time.Since(istart) - - // Update metrics for counting trie iteration - if kind == snapStorage { - snapStorageTrieReadCounter.Inc((time.Since(start) - internal).Nanoseconds()) - } else { - snapAccountTrieReadCounter.Inc((time.Since(start) - internal).Nanoseconds()) - } - logger.Debug("Regenerated state range", "root", trieId.Root, "last", hexutil.Encode(last), - "count", count, "created", created, "updated", updated, "untouched", untouched, "deleted", deleted) - - // If there are either more trie items, or there are more snap items - // (in the next segment), then we need to keep working - return !trieMore && !result.diskMore, last, nil -} - -// checkAndFlush checks if an interruption signal is received or the -// batch size has exceeded the allowance. -func (dl *diskLayer) checkAndFlush(ctx *generatorContext, current []byte) error { - var abort chan *generatorStats - select { - case abort = <-dl.genAbort: - default: - } - if ctx.batch.ValueSize() > ethdb.IdealBatchSize || abort != nil { - if bytes.Compare(current, dl.genMarker) < 0 { - log.Error("Snapshot generator went backwards", "current", fmt.Sprintf("%x", current), "genMarker", fmt.Sprintf("%x", dl.genMarker)) - } - // Flush out the batch anyway no matter it's empty or not. - // It's possible that all the states are recovered and the - // generation indeed makes progress. - journalProgress(ctx.batch, current, ctx.stats) - - if err := ctx.batch.Write(); err != nil { - return err - } - ctx.batch.Reset() - - dl.lock.Lock() - dl.genMarker = current - dl.lock.Unlock() - - if abort != nil { - ctx.stats.Log("Aborting state snapshot generation", dl.root, current) - return newAbortErr(abort) // bubble up an error for interruption - } - // Don't hold the iterators too long, release them to let compactor works - ctx.reopenIterator(snapAccount) - ctx.reopenIterator(snapStorage) - } - if time.Since(ctx.logged) > 8*time.Second { - ctx.stats.Log("Generating state snapshot", dl.root, current) - ctx.logged = time.Now() - } - return nil -} - -// generateStorages generates the missing storage slots of the specific contract. -// It's supposed to restart the generation from the given origin position. -func generateStorages(ctx *generatorContext, dl *diskLayer, stateRoot common.Hash, account common.Hash, storageRoot common.Hash, storeMarker []byte) error { - onStorage := func(key []byte, val []byte, write bool, delete bool) error { - defer func(start time.Time) { - snapStorageWriteCounter.Inc(time.Since(start).Nanoseconds()) - }(time.Now()) - - if delete { - rawdb.DeleteStorageSnapshot(ctx.batch, account, common.BytesToHash(key)) - snapWipedStorageMeter.Mark(1) - return nil - } - if write { - rawdb.WriteStorageSnapshot(ctx.batch, account, common.BytesToHash(key), val) - snapGeneratedStorageMeter.Mark(1) - } else { - snapRecoveredStorageMeter.Mark(1) - } - ctx.stats.storage += common.StorageSize(1 + 2*common.HashLength + len(val)) - ctx.stats.slots++ - - // If we've exceeded our batch allowance or termination was requested, flush to disk - if err := dl.checkAndFlush(ctx, append(account[:], key...)); err != nil { - return err - } - return nil - } - // Loop for re-generating the missing storage slots. - var origin = common.CopyBytes(storeMarker) - for { - id := trie.StorageTrieID(stateRoot, account, storageRoot) - exhausted, last, err := dl.generateRange(ctx, id, append(rawdb.SnapshotStoragePrefix, account.Bytes()...), snapStorage, origin, storageCheckRange, onStorage, nil) - if err != nil { - return err // The procedure it aborted, either by external signal or internal error. - } - // Abort the procedure if the entire contract storage is generated - if exhausted { - break - } - if origin = increaseKey(last); origin == nil { - break // special case, the last is 0xffffffff...fff - } - } - return nil -} - -// generateAccounts generates the missing snapshot accounts as well as their -// storage slots in the main trie. It's supposed to restart the generation -// from the given origin position. -func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) error { - onAccount := func(key []byte, val []byte, write bool, delete bool) error { - // Make sure to clear all dangling storages before this account - account := common.BytesToHash(key) - ctx.removeStorageBefore(account) - - start := time.Now() - if delete { - rawdb.DeleteAccountSnapshot(ctx.batch, account) - snapWipedAccountMeter.Mark(1) - snapAccountWriteCounter.Inc(time.Since(start).Nanoseconds()) - - ctx.removeStorageAt(account) - return nil - } - // Retrieve the current account and flatten it into the internal format - var acc types.StateAccount - if err := rlp.DecodeBytes(val, &acc); err != nil { - log.Crit("Invalid account encountered during snapshot creation", "err", err) - } - // If the account is not yet in-progress, write it out - if accMarker == nil || !bytes.Equal(account[:], accMarker) { - dataLen := len(val) // Approximate size, saves us a round of RLP-encoding - if !write { - if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) { - dataLen -= 32 - } - if acc.Root == types.EmptyRootHash { - dataLen -= 32 - } - snapRecoveredAccountMeter.Mark(1) - } else { - data := types.SlimAccountRLP(acc) - dataLen = len(data) - rawdb.WriteAccountSnapshot(ctx.batch, account, data) - snapGeneratedAccountMeter.Mark(1) - } - ctx.stats.storage += common.StorageSize(1 + common.HashLength + dataLen) - ctx.stats.accounts++ - } - // If the snap generation goes here after interrupted, genMarker may go backward - // when last genMarker is consisted of accountHash and storageHash - marker := account[:] - if accMarker != nil && bytes.Equal(marker, accMarker) && len(dl.genMarker) > common.HashLength { - marker = dl.genMarker[:] - } - // If we've exceeded our batch allowance or termination was requested, flush to disk - if err := dl.checkAndFlush(ctx, marker); err != nil { - return err - } - snapAccountWriteCounter.Inc(time.Since(start).Nanoseconds()) // let's count flush time as well - - // If the iterated account is the contract, create a further loop to - // verify or regenerate the contract storage. - if acc.Root == types.EmptyRootHash { - ctx.removeStorageAt(account) - } else { - var storeMarker []byte - if accMarker != nil && bytes.Equal(account[:], accMarker) && len(dl.genMarker) > common.HashLength { - storeMarker = dl.genMarker[common.HashLength:] - } - if err := generateStorages(ctx, dl, dl.root, account, acc.Root, storeMarker); err != nil { - return err - } - } - // Some account processed, unmark the marker - accMarker = nil - return nil - } - // Always reset the initial account range as 1 whenever recover from the - // interruption. TODO(rjl493456442) can we remove it? - var accountRange = accountCheckRange - if len(accMarker) > 0 { - accountRange = 1 - } - origin := common.CopyBytes(accMarker) - for { - id := trie.StateTrieID(dl.root) - exhausted, last, err := dl.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountRange, onAccount, types.FullAccountRLP) - if err != nil { - return err // The procedure it aborted, either by external signal or internal error. - } - origin = increaseKey(last) - - // Last step, cleanup the storages after the last account. - // All the left storages should be treated as dangling. - if origin == nil || exhausted { - ctx.removeStorageLeft() - break - } - accountRange = accountCheckRange - } - return nil -} - -// generate is a background thread that iterates over the state and storage tries, -// constructing the state snapshot. All the arguments are purely for statistics -// gathering and logging, since the method surfs the blocks as they arrive, often -// being restarted. -func (dl *diskLayer) generate(stats *generatorStats) { - var ( - accMarker []byte - abort chan *generatorStats - ) - if len(dl.genMarker) > 0 { // []byte{} is the start, use nil for that - accMarker = dl.genMarker[:common.HashLength] - } - stats.Log("Resuming state snapshot generation", dl.root, dl.genMarker) - - // Initialize the global generator context. The snapshot iterators are - // opened at the interrupted position because the assumption is held - // that all the snapshot data are generated correctly before the marker. - // Even if the snapshot data is updated during the interruption (before - // or at the marker), the assumption is still held. - // For the account or storage slot at the interruption, they will be - // processed twice by the generator(they are already processed in the - // last run) but it's fine. - ctx := newGeneratorContext(stats, dl.diskdb, accMarker, dl.genMarker) - defer ctx.close() - - if err := generateAccounts(ctx, dl, accMarker); err != nil { - // Extract the received interruption signal if exists - if aerr, ok := err.(*abortErr); ok { - abort = aerr.abort - } - // Aborted by internal error, wait the signal - if abort == nil { - abort = <-dl.genAbort - } - abort <- stats - return - } - // Snapshot fully generated, set the marker to nil. - // Note even there is nothing to commit, persist the - // generator anyway to mark the snapshot is complete. - journalProgress(ctx.batch, nil, stats) - if err := ctx.batch.Write(); err != nil { - log.Error("Failed to flush batch", "err", err) - - abort = <-dl.genAbort - abort <- stats - return - } - ctx.batch.Reset() - - log.Info("Generated state snapshot", "accounts", stats.accounts, "slots", stats.slots, - "storage", stats.storage, "dangling", stats.dangling, "elapsed", common.PrettyDuration(time.Since(stats.start))) - - dl.lock.Lock() - dl.genMarker = nil - close(dl.genPending) - dl.lock.Unlock() - - // Someone will be looking for us, wait it out - abort = <-dl.genAbort - abort <- nil -} - -// increaseKey increase the input key by one bit. Return nil if the entire -// addition operation overflows. -func increaseKey(key []byte) []byte { - for i := len(key) - 1; i >= 0; i-- { - key[i]++ - if key[i] != 0x0 { - return key - } - } - return nil -} - -// abortErr wraps an interruption signal received to represent the -// generation is aborted by external processes. -type abortErr struct { - abort chan *generatorStats -} - -func newAbortErr(abort chan *generatorStats) error { - return &abortErr{abort: abort} -} - -func (err *abortErr) Error() string { - return "aborted" -} diff --git a/builder/core/state/snapshot/generate_test.go b/builder/core/state/snapshot/generate_test.go deleted file mode 100644 index da93ebc87..000000000 --- a/builder/core/state/snapshot/generate_test.go +++ /dev/null @@ -1,969 +0,0 @@ -// 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 snapshot - -import ( - "fmt" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" -) - -func hashData(input []byte) common.Hash { - var hasher = sha3.NewLegacyKeccak256() - var hash common.Hash - hasher.Reset() - hasher.Write(input) - hasher.Sum(hash[:0]) - return hash -} - -// Tests that snapshot generation from an empty database. -func TestGeneration(t *testing.T) { - testGeneration(t, rawdb.HashScheme) - testGeneration(t, rawdb.PathScheme) -} - -func testGeneration(t *testing.T, scheme string) { - // We can't use statedb to make a test trie (circular dependency), so make - // a fake one manually. We're going with a small account trie of 3 accounts, - // two of which also has the same 3-slot storage trie attached. - var helper = newHelper(scheme) - stRoot := helper.makeStorageTrie(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) - - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - - helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - - root, snap := helper.CommitAndGenerate() - if have, want := root, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"); have != want { - t.Fatalf("have %#x want %#x", have, want) - } - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation with existent flat state. -func TestGenerateExistentState(t *testing.T) { - testGenerateExistentState(t, rawdb.HashScheme) - testGenerateExistentState(t, rawdb.PathScheme) -} - -func testGenerateExistentState(t *testing.T, scheme string) { - // We can't use statedb to make a test trie (circular dependency), so make - // a fake one manually. We're going with a small account trie of 3 accounts, - // two of which also has the same 3-slot storage trie attached. - var helper = newHelper(scheme) - - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - - stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -func checkSnapRoot(t *testing.T, snap *diskLayer, trieRoot common.Hash) { - t.Helper() - - accIt := snap.AccountIterator(common.Hash{}) - defer accIt.Release() - - snapRoot, err := generateTrieRoot(nil, "", accIt, common.Hash{}, stackTrieGenerate, - func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { - storageIt, _ := snap.StorageIterator(accountHash, common.Hash{}) - defer storageIt.Release() - - hash, err := generateTrieRoot(nil, "", storageIt, accountHash, stackTrieGenerate, nil, stat, false) - if err != nil { - return common.Hash{}, err - } - return hash, nil - }, newGenerateStats(), true) - if err != nil { - t.Fatal(err) - } - if snapRoot != trieRoot { - t.Fatalf("snaproot: %#x != trieroot #%x", snapRoot, trieRoot) - } - if err := CheckDanglingStorage(snap.diskdb); err != nil { - t.Fatalf("Detected dangling storages: %v", err) - } -} - -type testHelper struct { - diskdb ethdb.Database - triedb *triedb.Database - accTrie *trie.StateTrie - nodes *trienode.MergedNodeSet -} - -func newHelper(scheme string) *testHelper { - diskdb := rawdb.NewMemoryDatabase() - config := &triedb.Config{} - if scheme == rawdb.PathScheme { - config.PathDB = &pathdb.Config{} // disable caching - } else { - config.HashDB = &hashdb.Config{} // disable caching - } - triedb := triedb.NewDatabase(diskdb, config) - accTrie, _ := trie.NewStateTrie(trie.StateTrieID(types.EmptyRootHash), triedb) - return &testHelper{ - diskdb: diskdb, - triedb: triedb, - accTrie: accTrie, - nodes: trienode.NewMergedNodeSet(), - } -} - -func (t *testHelper) addTrieAccount(acckey string, acc *types.StateAccount) { - val, _ := rlp.EncodeToBytes(acc) - t.accTrie.MustUpdate([]byte(acckey), val) -} - -func (t *testHelper) addSnapAccount(acckey string, acc *types.StateAccount) { - key := hashData([]byte(acckey)) - rawdb.WriteAccountSnapshot(t.diskdb, key, types.SlimAccountRLP(*acc)) -} - -func (t *testHelper) addAccount(acckey string, acc *types.StateAccount) { - t.addTrieAccount(acckey, acc) - t.addSnapAccount(acckey, acc) -} - -func (t *testHelper) addSnapStorage(accKey string, keys []string, vals []string) { - accHash := hashData([]byte(accKey)) - for i, key := range keys { - rawdb.WriteStorageSnapshot(t.diskdb, accHash, hashData([]byte(key)), []byte(vals[i])) - } -} - -func (t *testHelper) makeStorageTrie(owner common.Hash, keys []string, vals []string, commit bool) common.Hash { - id := trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash) - stTrie, _ := trie.NewStateTrie(id, t.triedb) - for i, k := range keys { - stTrie.MustUpdate([]byte(k), []byte(vals[i])) - } - if !commit { - return stTrie.Hash() - } - root, nodes, _ := stTrie.Commit(false) - if nodes != nil { - t.nodes.Merge(nodes) - } - return root -} - -func (t *testHelper) Commit() common.Hash { - root, nodes, _ := t.accTrie.Commit(true) - if nodes != nil { - t.nodes.Merge(nodes) - } - t.triedb.Update(root, types.EmptyRootHash, 0, t.nodes, nil) - t.triedb.Commit(root, false) - return root -} - -func (t *testHelper) CommitAndGenerate() (common.Hash, *diskLayer) { - root := t.Commit() - snap := generateSnapshot(t.diskdb, t.triedb, 16, root) - return root, snap -} - -// Tests that snapshot generation with existent flat state, where the flat state -// contains some errors: -// - the contract with empty storage root but has storage entries in the disk -// - the contract with non empty storage root but empty storage slots -// - the contract(non-empty storage) misses some storage slots -// - miss in the beginning -// - miss in the middle -// - miss in the end -// -// - the contract(non-empty storage) has wrong storage slots -// - wrong slots in the beginning -// - wrong slots in the middle -// - wrong slots in the end -// -// - the contract(non-empty storage) has extra storage slots -// - extra slots in the beginning -// - extra slots in the middle -// - extra slots in the end -func TestGenerateExistentStateWithWrongStorage(t *testing.T) { - testGenerateExistentStateWithWrongStorage(t, rawdb.HashScheme) - testGenerateExistentStateWithWrongStorage(t, rawdb.PathScheme) -} - -func testGenerateExistentStateWithWrongStorage(t *testing.T, scheme string) { - helper := newHelper(scheme) - - // Account one, empty root but non-empty database - helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Account two, non empty root but empty database - stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - - // Miss slots - { - // Account three, non empty root but misses slots in the beginning - helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) - - // Account four, non empty root but misses slots in the middle - helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) - - // Account five, non empty root but misses slots in the end - helper.makeStorageTrie(hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) - } - - // Wrong storage slots - { - // Account six, non empty root but wrong slots in the beginning - helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) - - // Account seven, non empty root but wrong slots in the middle - helper.makeStorageTrie(hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) - - // Account eight, non empty root but wrong slots in the end - helper.makeStorageTrie(hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-8", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) - - // Account 9, non empty root but rotated slots - helper.makeStorageTrie(hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-9", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) - } - - // Extra storage slots - { - // Account 10, non empty root but extra slots in the beginning - helper.makeStorageTrie(hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-10", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) - - // Account 11, non empty root but extra slots in the middle - helper.makeStorageTrie(hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-11", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) - - // Account 12, non empty root but extra slots in the end - helper.makeStorageTrie(hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-12", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) - } - - root, snap := helper.CommitAndGenerate() - t.Logf("Root: %#x\n", root) // Root = 0x8746cce9fd9c658b2cfd639878ed6584b7a2b3e73bb40f607fcfa156002429a0 - - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation with existent flat state, where the flat state -// contains some errors: -// - miss accounts -// - wrong accounts -// - extra accounts -func TestGenerateExistentStateWithWrongAccounts(t *testing.T) { - testGenerateExistentStateWithWrongAccounts(t, rawdb.HashScheme) - testGenerateExistentStateWithWrongAccounts(t, rawdb.PathScheme) -} - -func testGenerateExistentStateWithWrongAccounts(t *testing.T, scheme string) { - helper := newHelper(scheme) - - helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.makeStorageTrie(hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.makeStorageTrie(hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - stRoot := helper.makeStorageTrie(hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - - // Trie accounts [acc-1, acc-2, acc-3, acc-4, acc-6] - // Extra accounts [acc-0, acc-5, acc-7] - - // Missing accounts, only in the trie - { - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning - helper.addTrieAccount("acc-4", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle - helper.addTrieAccount("acc-6", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End - } - - // Wrong accounts - { - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) - - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addSnapAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - } - - // Extra accounts, only in the snap - { - helper.addSnapAccount("acc-0", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning - helper.addSnapAccount("acc-5", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: common.Hex2Bytes("0x1234")}) // Middle - helper.addSnapAccount("acc-7", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // after the end - } - - root, snap := helper.CommitAndGenerate() - t.Logf("Root: %#x\n", root) // Root = 0x825891472281463511e7ebcc7f109e4f9200c20fa384754e11fd605cd98464e8 - - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation errors out correctly in case of a missing trie -// node in the account trie. -func TestGenerateCorruptAccountTrie(t *testing.T) { - testGenerateCorruptAccountTrie(t, rawdb.HashScheme) - testGenerateCorruptAccountTrie(t, rawdb.PathScheme) -} - -func testGenerateCorruptAccountTrie(t *testing.T, scheme string) { - // We can't use statedb to make a test trie (circular dependency), so make - // a fake one manually. We're going with a small account trie of 3 accounts, - // without any storage slots to keep the test smaller. - helper := newHelper(scheme) - - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 - - root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 - - // Delete an account trie node and ensure the generator chokes - targetPath := []byte{0xc} - targetHash := common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7") - - rawdb.DeleteTrieNode(helper.diskdb, common.Hash{}, targetPath, targetHash, scheme) - - snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) - select { - case <-snap.genPending: - // Snapshot generation succeeded - t.Errorf("Snapshot generated against corrupt account trie") - - case <-time.After(time.Second): - // Not generated fast enough, hopefully blocked inside on missing trie node fail - } - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation errors out correctly in case of a missing root -// trie node for a storage trie. It's similar to internal corruption but it is -// handled differently inside the generator. -func TestGenerateMissingStorageTrie(t *testing.T) { - testGenerateMissingStorageTrie(t, rawdb.HashScheme) - testGenerateMissingStorageTrie(t, rawdb.PathScheme) -} - -func testGenerateMissingStorageTrie(t *testing.T, scheme string) { - // We can't use statedb to make a test trie (circular dependency), so make - // a fake one manually. We're going with a small account trie of 3 accounts, - // two of which also has the same 3-slot storage trie attached. - var ( - acc1 = hashData([]byte("acc-1")) - acc3 = hashData([]byte("acc-3")) - helper = newHelper(scheme) - ) - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 - stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 - - root := helper.Commit() - - // Delete storage trie root of account one and three. - rawdb.DeleteTrieNode(helper.diskdb, acc1, nil, stRoot, scheme) - rawdb.DeleteTrieNode(helper.diskdb, acc3, nil, stRoot, scheme) - - snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) - select { - case <-snap.genPending: - // Snapshot generation succeeded - t.Errorf("Snapshot generated against corrupt storage trie") - - case <-time.After(time.Second): - // Not generated fast enough, hopefully blocked inside on missing trie node fail - } - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation errors out correctly in case of a missing trie -// node in a storage trie. -func TestGenerateCorruptStorageTrie(t *testing.T) { - testGenerateCorruptStorageTrie(t, rawdb.HashScheme) - testGenerateCorruptStorageTrie(t, rawdb.PathScheme) -} - -func testGenerateCorruptStorageTrie(t *testing.T, scheme string) { - // We can't use statedb to make a test trie (circular dependency), so make - // a fake one manually. We're going with a small account trie of 3 accounts, - // two of which also has the same 3-slot storage trie attached. - helper := newHelper(scheme) - - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 - stRoot = helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 - - root := helper.Commit() - - // Delete a node in the storage trie. - targetPath := []byte{0x4} - targetHash := common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371") - rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-1")), targetPath, targetHash, scheme) - rawdb.DeleteTrieNode(helper.diskdb, hashData([]byte("acc-3")), targetPath, targetHash, scheme) - - snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) - select { - case <-snap.genPending: - // Snapshot generation succeeded - t.Errorf("Snapshot generated against corrupt storage trie") - - case <-time.After(time.Second): - // Not generated fast enough, hopefully blocked inside on missing trie node fail - } - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation when an extra account with storage exists in the snap state. -func TestGenerateWithExtraAccounts(t *testing.T) { - testGenerateWithExtraAccounts(t, rawdb.HashScheme) - testGenerateWithExtraAccounts(t, rawdb.PathScheme) -} - -func testGenerateWithExtraAccounts(t *testing.T, scheme string) { - helper := newHelper(scheme) - { - // Account one in the trie - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), - []string{"key-1", "key-2", "key-3", "key-4", "key-5"}, - []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, - true, - ) - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - - // Identical in the snap - key := hashData([]byte("acc-1")) - rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-4")), []byte("val-4")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-5")), []byte("val-5")) - } - { - // Account two exists only in the snapshot - stRoot := helper.makeStorageTrie(hashData([]byte("acc-2")), - []string{"key-1", "key-2", "key-3", "key-4", "key-5"}, - []string{"val-1", "val-2", "val-3", "val-4", "val-5"}, - true, - ) - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - key := hashData([]byte("acc-2")) - rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-1")), []byte("b-val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-2")), []byte("b-val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("b-key-3")), []byte("b-val-3")) - } - root := helper.Commit() - - // To verify the test: If we now inspect the snap db, there should exist extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data == nil { - t.Fatalf("expected snap storage to exist") - } - snap := generateSnapshot(helper.diskdb, helper.triedb, 16, root) - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop - // If we now inspect the snap db, there should exist no extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { - t.Fatalf("expected slot to be removed, got %v", string(data)) - } -} - -func enableLogging() { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) -} - -// Tests that snapshot generation when an extra account with storage exists in the snap state. -func TestGenerateWithManyExtraAccounts(t *testing.T) { - testGenerateWithManyExtraAccounts(t, rawdb.HashScheme) - testGenerateWithManyExtraAccounts(t, rawdb.PathScheme) -} - -func testGenerateWithManyExtraAccounts(t *testing.T, scheme string) { - if false { - enableLogging() - } - helper := newHelper(scheme) - { - // Account one in the trie - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), - []string{"key-1", "key-2", "key-3"}, - []string{"val-1", "val-2", "val-3"}, - true, - ) - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - helper.accTrie.MustUpdate([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e - - // Identical in the snap - key := hashData([]byte("acc-1")) - rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-1")), []byte("val-1")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-2")), []byte("val-2")) - rawdb.WriteStorageSnapshot(helper.diskdb, key, hashData([]byte("key-3")), []byte("val-3")) - } - { - // 100 accounts exist only in snapshot - for i := 0; i < 1000; i++ { - acc := &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - key := hashData([]byte(fmt.Sprintf("acc-%d", i))) - rawdb.WriteAccountSnapshot(helper.diskdb, key, val) - } - } - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests this case -// maxAccountRange 3 -// snapshot-accounts: 01, 02, 03, 04, 05, 06, 07 -// trie-accounts: 03, 07 -// -// We iterate three snapshot storage slots (max = 3) from the database. They are 0x01, 0x02, 0x03. -// The trie has a lot of deletions. -// So in trie, we iterate 2 entries 0x03, 0x07. We create the 0x07 in the database and abort the procedure, because the trie is exhausted. -// But in the database, we still have the stale storage slots 0x04, 0x05. They are not iterated yet, but the procedure is finished. -func TestGenerateWithExtraBeforeAndAfter(t *testing.T) { - testGenerateWithExtraBeforeAndAfter(t, rawdb.HashScheme) - testGenerateWithExtraBeforeAndAfter(t, rawdb.PathScheme) -} - -func testGenerateWithExtraBeforeAndAfter(t *testing.T, scheme string) { - accountCheckRange = 3 - if false { - enableLogging() - } - helper := newHelper(scheme) - { - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) - helper.accTrie.MustUpdate(common.HexToHash("0x07").Bytes(), val) - - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x01"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x06"), val) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x07"), val) - } - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// TestGenerateWithMalformedSnapdata tests what happes if we have some junk -// in the snapshot database, which cannot be parsed back to an account -func TestGenerateWithMalformedSnapdata(t *testing.T) { - testGenerateWithMalformedSnapdata(t, rawdb.HashScheme) - testGenerateWithMalformedSnapdata(t, rawdb.PathScheme) -} - -func testGenerateWithMalformedSnapdata(t *testing.T, scheme string) { - accountCheckRange = 3 - if false { - enableLogging() - } - helper := newHelper(scheme) - { - acc := &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()} - val, _ := rlp.EncodeToBytes(acc) - helper.accTrie.MustUpdate(common.HexToHash("0x03").Bytes(), val) - - junk := make([]byte, 100) - copy(junk, []byte{0xde, 0xad}) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x02"), junk) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x03"), junk) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x04"), junk) - rawdb.WriteAccountSnapshot(helper.diskdb, common.HexToHash("0x05"), junk) - } - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop - // If we now inspect the snap db, there should exist no extraneous storage items - if data := rawdb.ReadStorageSnapshot(helper.diskdb, hashData([]byte("acc-2")), hashData([]byte("b-key-1"))); data != nil { - t.Fatalf("expected slot to be removed, got %v", string(data)) - } -} - -func TestGenerateFromEmptySnap(t *testing.T) { - testGenerateFromEmptySnap(t, rawdb.HashScheme) - testGenerateFromEmptySnap(t, rawdb.PathScheme) -} - -func testGenerateFromEmptySnap(t *testing.T, scheme string) { - //enableLogging() - accountCheckRange = 10 - storageCheckRange = 20 - helper := newHelper(scheme) - // Add 1K accounts to the trie - for i := 0; i < 400; i++ { - stRoot := helper.makeStorageTrie(hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount(fmt.Sprintf("acc-%d", i), - &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - } - root, snap := helper.CommitAndGenerate() - t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 - - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation with existent flat state, where the flat state -// storage is correct, but incomplete. -// The incomplete part is on the second range -// snap: [ 0x01, 0x02, 0x03, 0x04] , [ 0x05, 0x06, 0x07, {missing}] (with storageCheck = 4) -// trie: 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 -// This hits a case where the snap verification passes, but there are more elements in the trie -// which we must also add. -func TestGenerateWithIncompleteStorage(t *testing.T) { - testGenerateWithIncompleteStorage(t, rawdb.HashScheme) - testGenerateWithIncompleteStorage(t, rawdb.PathScheme) -} - -func testGenerateWithIncompleteStorage(t *testing.T, scheme string) { - storageCheckRange = 4 - helper := newHelper(scheme) - stKeys := []string{"1", "2", "3", "4", "5", "6", "7", "8"} - stVals := []string{"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"} - // We add 8 accounts, each one is missing exactly one of the storage slots. This means - // we don't have to order the keys and figure out exactly which hash-key winds up - // on the sensitive spots at the boundaries - for i := 0; i < 8; i++ { - accKey := fmt.Sprintf("acc-%d", i) - stRoot := helper.makeStorageTrie(hashData([]byte(accKey)), stKeys, stVals, true) - helper.addAccount(accKey, &types.StateAccount{Balance: uint256.NewInt(uint64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - var moddedKeys []string - var moddedVals []string - for ii := 0; ii < 8; ii++ { - if ii != i { - moddedKeys = append(moddedKeys, stKeys[ii]) - moddedVals = append(moddedVals, stVals[ii]) - } - } - helper.addSnapStorage(accKey, moddedKeys, moddedVals) - } - root, snap := helper.CommitAndGenerate() - t.Logf("Root: %#x\n", root) // Root: 0xca73f6f05ba4ca3024ef340ef3dfca8fdabc1b677ff13f5a9571fd49c16e67ff - - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -func incKey(key []byte) []byte { - for i := len(key) - 1; i >= 0; i-- { - key[i]++ - if key[i] != 0x0 { - break - } - } - return key -} - -func decKey(key []byte) []byte { - for i := len(key) - 1; i >= 0; i-- { - key[i]-- - if key[i] != 0xff { - break - } - } - return key -} - -func populateDangling(disk ethdb.KeyValueStore) { - populate := func(accountHash common.Hash, keys []string, vals []string) { - for i, key := range keys { - rawdb.WriteStorageSnapshot(disk, accountHash, hashData([]byte(key)), []byte(vals[i])) - } - } - // Dangling storages of the "first" account - populate(common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Dangling storages of the "last" account - populate(common.HexToHash("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Dangling storages around the account 1 - hash := decKey(hashData([]byte("acc-1")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - hash = incKey(hashData([]byte("acc-1")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Dangling storages around the account 2 - hash = decKey(hashData([]byte("acc-2")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - hash = incKey(hashData([]byte("acc-2")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Dangling storages around the account 3 - hash = decKey(hashData([]byte("acc-3")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - hash = incKey(hashData([]byte("acc-3")).Bytes()) - populate(common.BytesToHash(hash), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - // Dangling storages of the random account - populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - populate(randomHash(), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) -} - -// Tests that snapshot generation with dangling storages. Dangling storage means -// the storage data is existent while the corresponding account data is missing. -// -// This test will populate some dangling storages to see if they can be cleaned up. -func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) { - testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.HashScheme) - testGenerateCompleteSnapshotWithDanglingStorage(t, rawdb.PathScheme) -} - -func testGenerateCompleteSnapshotWithDanglingStorage(t *testing.T, scheme string) { - var helper = newHelper(scheme) - - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(1), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - - helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - - helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) - - populateDangling(helper.diskdb) - - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} - -// Tests that snapshot generation with dangling storages. Dangling storage means -// the storage data is existent while the corresponding account data is missing. -// -// This test will populate some dangling storages to see if they can be cleaned up. -func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) { - testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.HashScheme) - testGenerateBrokenSnapshotWithDanglingStorage(t, rawdb.PathScheme) -} - -func testGenerateBrokenSnapshotWithDanglingStorage(t *testing.T, scheme string) { - var helper = newHelper(scheme) - - stRoot := helper.makeStorageTrie(hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-1", &types.StateAccount{Balance: uint256.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - helper.addTrieAccount("acc-2", &types.StateAccount{Balance: uint256.NewInt(2), Root: types.EmptyRootHash, CodeHash: types.EmptyCodeHash.Bytes()}) - - helper.makeStorageTrie(hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) - helper.addTrieAccount("acc-3", &types.StateAccount{Balance: uint256.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) - - populateDangling(helper.diskdb) - - root, snap := helper.CommitAndGenerate() - select { - case <-snap.genPending: - // Snapshot generation succeeded - - case <-time.After(3 * time.Second): - t.Errorf("Snapshot generation failed") - } - checkSnapRoot(t, snap, root) - - // Signal abortion to the generator and wait for it to tear down - stop := make(chan *generatorStats) - snap.genAbort <- stop - <-stop -} diff --git a/builder/core/state/snapshot/holdable_iterator.go b/builder/core/state/snapshot/holdable_iterator.go deleted file mode 100644 index 1e86ff9d8..000000000 --- a/builder/core/state/snapshot/holdable_iterator.go +++ /dev/null @@ -1,97 +0,0 @@ -// 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 snapshot - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" -) - -// holdableIterator is a wrapper of underlying database iterator. It extends -// the basic iterator interface by adding Hold which can hold the element -// locally where the iterator is currently located and serve it up next time. -type holdableIterator struct { - it ethdb.Iterator - key []byte - val []byte - atHeld bool -} - -// newHoldableIterator initializes the holdableIterator with the given iterator. -func newHoldableIterator(it ethdb.Iterator) *holdableIterator { - return &holdableIterator{it: it} -} - -// Hold holds the element locally where the iterator is currently located which -// can be served up next time. -func (it *holdableIterator) Hold() { - if it.it.Key() == nil { - return // nothing to hold - } - it.key = common.CopyBytes(it.it.Key()) - it.val = common.CopyBytes(it.it.Value()) - it.atHeld = false -} - -// Next moves the iterator to the next key/value pair. It returns whether the -// iterator is exhausted. -func (it *holdableIterator) Next() bool { - if !it.atHeld && it.key != nil { - it.atHeld = true - } else if it.atHeld { - it.atHeld = false - it.key = nil - it.val = nil - } - if it.key != nil { - return true // shifted to locally held value - } - return it.it.Next() -} - -// Error returns any accumulated error. Exhausting all the key/value pairs -// is not considered to be an error. -func (it *holdableIterator) Error() error { return it.it.Error() } - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (it *holdableIterator) Release() { - it.atHeld = false - it.key = nil - it.val = nil - it.it.Release() -} - -// Key returns the key of the current key/value pair, or nil if done. The caller -// should not modify the contents of the returned slice, and its contents may -// change on the next call to Next. -func (it *holdableIterator) Key() []byte { - if it.key != nil { - return it.key - } - return it.it.Key() -} - -// Value returns the value of the current key/value pair, or nil if done. The -// caller should not modify the contents of the returned slice, and its contents -// may change on the next call to Next. -func (it *holdableIterator) Value() []byte { - if it.val != nil { - return it.val - } - return it.it.Value() -} diff --git a/builder/core/state/snapshot/holdable_iterator_test.go b/builder/core/state/snapshot/holdable_iterator_test.go deleted file mode 100644 index ce4cf6bb8..000000000 --- a/builder/core/state/snapshot/holdable_iterator_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" -) - -func TestIteratorHold(t *testing.T) { - // Create the key-value data store - var ( - content = map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"} - order = []string{"k1", "k2", "k3"} - db = rawdb.NewMemoryDatabase() - ) - for key, val := range content { - if err := db.Put([]byte(key), []byte(val)); err != nil { - t.Fatalf("failed to insert item %s:%s into database: %v", key, val, err) - } - } - // Iterate over the database with the given configs and verify the results - it, idx := newHoldableIterator(db.NewIterator(nil, nil)), 0 - - // Nothing should be affected for calling Discard on non-initialized iterator - it.Hold() - - for it.Next() { - if len(content) <= idx { - t.Errorf("more items than expected: checking idx=%d (key %q), expecting len=%d", idx, it.Key(), len(order)) - break - } - if !bytes.Equal(it.Key(), []byte(order[idx])) { - t.Errorf("item %d: key mismatch: have %s, want %s", idx, string(it.Key()), order[idx]) - } - if !bytes.Equal(it.Value(), []byte(content[order[idx]])) { - t.Errorf("item %d: value mismatch: have %s, want %s", idx, string(it.Value()), content[order[idx]]) - } - // Should be safe to call discard multiple times - it.Hold() - it.Hold() - - // Shift iterator to the discarded element - it.Next() - if !bytes.Equal(it.Key(), []byte(order[idx])) { - t.Errorf("item %d: key mismatch: have %s, want %s", idx, string(it.Key()), order[idx]) - } - if !bytes.Equal(it.Value(), []byte(content[order[idx]])) { - t.Errorf("item %d: value mismatch: have %s, want %s", idx, string(it.Value()), content[order[idx]]) - } - - // Discard/Next combo should work always - it.Hold() - it.Next() - if !bytes.Equal(it.Key(), []byte(order[idx])) { - t.Errorf("item %d: key mismatch: have %s, want %s", idx, string(it.Key()), order[idx]) - } - if !bytes.Equal(it.Value(), []byte(content[order[idx]])) { - t.Errorf("item %d: value mismatch: have %s, want %s", idx, string(it.Value()), content[order[idx]]) - } - idx++ - } - if err := it.Error(); err != nil { - t.Errorf("iteration failed: %v", err) - } - if idx != len(order) { - t.Errorf("iteration terminated prematurely: have %d, want %d", idx, len(order)) - } - db.Close() -} - -func TestReopenIterator(t *testing.T) { - var ( - content = map[common.Hash]string{ - common.HexToHash("a1"): "v1", - common.HexToHash("a2"): "v2", - common.HexToHash("a3"): "v3", - common.HexToHash("a4"): "v4", - common.HexToHash("a5"): "v5", - common.HexToHash("a6"): "v6", - } - order = []common.Hash{ - common.HexToHash("a1"), - common.HexToHash("a2"), - common.HexToHash("a3"), - common.HexToHash("a4"), - common.HexToHash("a5"), - common.HexToHash("a6"), - } - db = rawdb.NewMemoryDatabase() - ) - for key, val := range content { - rawdb.WriteAccountSnapshot(db, key, []byte(val)) - } - checkVal := func(it *holdableIterator, index int) { - if !bytes.Equal(it.Key(), append(rawdb.SnapshotAccountPrefix, order[index].Bytes()...)) { - t.Fatalf("Unexpected data entry key, want %v got %v", order[index], it.Key()) - } - if !bytes.Equal(it.Value(), []byte(content[order[index]])) { - t.Fatalf("Unexpected data entry key, want %v got %v", []byte(content[order[index]]), it.Value()) - } - } - // Iterate over the database with the given configs and verify the results - ctx, idx := newGeneratorContext(&generatorStats{}, db, nil, nil), -1 - - idx++ - ctx.account.Next() - checkVal(ctx.account, idx) - - ctx.reopenIterator(snapAccount) - idx++ - ctx.account.Next() - checkVal(ctx.account, idx) - - // reopen twice - ctx.reopenIterator(snapAccount) - ctx.reopenIterator(snapAccount) - idx++ - ctx.account.Next() - checkVal(ctx.account, idx) - - // reopen iterator with held value - ctx.account.Next() - ctx.account.Hold() - ctx.reopenIterator(snapAccount) - idx++ - ctx.account.Next() - checkVal(ctx.account, idx) - - // reopen twice iterator with held value - ctx.account.Next() - ctx.account.Hold() - ctx.reopenIterator(snapAccount) - ctx.reopenIterator(snapAccount) - idx++ - ctx.account.Next() - checkVal(ctx.account, idx) - - // shift to the end and reopen - ctx.account.Next() // the end - ctx.reopenIterator(snapAccount) - ctx.account.Next() - if ctx.account.Key() != nil { - t.Fatal("Unexpected iterated entry") - } -} diff --git a/builder/core/state/snapshot/iterator.go b/builder/core/state/snapshot/iterator.go deleted file mode 100644 index c1a196c7f..000000000 --- a/builder/core/state/snapshot/iterator.go +++ /dev/null @@ -1,400 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "fmt" - "sort" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" -) - -// Iterator is an iterator to step over all the accounts or the specific -// storage in a snapshot which may or may not be composed of multiple layers. -type Iterator interface { - // Next steps the iterator forward one element, returning false if exhausted, - // or an error if iteration failed for some reason (e.g. root being iterated - // becomes stale and garbage collected). - Next() bool - - // Error returns any failure that occurred during iteration, which might have - // caused a premature iteration exit (e.g. snapshot stack becoming stale). - Error() error - - // Hash returns the hash of the account or storage slot the iterator is - // currently at. - Hash() common.Hash - - // Release releases associated resources. Release should always succeed and - // can be called multiple times without causing error. - Release() -} - -// AccountIterator is an iterator to step over all the accounts in a snapshot, -// which may or may not be composed of multiple layers. -type AccountIterator interface { - Iterator - - // Account returns the RLP encoded slim account the iterator is currently at. - // An error will be returned if the iterator becomes invalid - Account() []byte -} - -// StorageIterator is an iterator to step over the specific storage in a snapshot, -// which may or may not be composed of multiple layers. -type StorageIterator interface { - Iterator - - // Slot returns the storage slot the iterator is currently at. An error will - // be returned if the iterator becomes invalid - Slot() []byte -} - -// diffAccountIterator is an account iterator that steps over the accounts (both -// live and deleted) contained within a single diff layer. Higher order iterators -// will use the deleted accounts to skip deeper iterators. -type diffAccountIterator struct { - // curHash is the current hash the iterator is positioned on. The field is - // explicitly tracked since the referenced diff layer might go stale after - // the iterator was positioned and we don't want to fail accessing the old - // hash as long as the iterator is not touched any more. - curHash common.Hash - - layer *diffLayer // Live layer to retrieve values from - keys []common.Hash // Keys left in the layer to iterate - fail error // Any failures encountered (stale) -} - -// AccountIterator creates an account iterator over a single diff layer. -func (dl *diffLayer) AccountIterator(seek common.Hash) AccountIterator { - // Seek out the requested starting account - hashes := dl.AccountList() - index := sort.Search(len(hashes), func(i int) bool { - return bytes.Compare(seek[:], hashes[i][:]) <= 0 - }) - // Assemble and returned the already seeked iterator - return &diffAccountIterator{ - layer: dl, - keys: hashes[index:], - } -} - -// Next steps the iterator forward one element, returning false if exhausted. -func (it *diffAccountIterator) Next() bool { - // If the iterator was already stale, consider it a programmer error. Although - // we could just return false here, triggering this path would probably mean - // somebody forgot to check for Error, so lets blow up instead of undefined - // behavior that's hard to debug. - if it.fail != nil { - panic(fmt.Sprintf("called Next of failed iterator: %v", it.fail)) - } - // Stop iterating if all keys were exhausted - if len(it.keys) == 0 { - return false - } - if it.layer.Stale() { - it.fail, it.keys = ErrSnapshotStale, nil - return false - } - // Iterator seems to be still alive, retrieve and cache the live hash - it.curHash = it.keys[0] - // key cached, shift the iterator and notify the user of success - it.keys = it.keys[1:] - return true -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -func (it *diffAccountIterator) Error() error { - return it.fail -} - -// Hash returns the hash of the account the iterator is currently at. -func (it *diffAccountIterator) Hash() common.Hash { - return it.curHash -} - -// Account returns the RLP encoded slim account the iterator is currently at. -// This method may _fail_, if the underlying layer has been flattened between -// the call to Next and Account. That type of error will set it.Err. -// This method assumes that flattening does not delete elements from -// the accountdata mapping (writing nil into it is fine though), and will panic -// if elements have been deleted. -// -// Note the returned account is not a copy, please don't modify it. -func (it *diffAccountIterator) Account() []byte { - it.layer.lock.RLock() - blob, ok := it.layer.accountData[it.curHash] - if !ok { - if _, ok := it.layer.destructSet[it.curHash]; ok { - it.layer.lock.RUnlock() - return nil - } - panic(fmt.Sprintf("iterator referenced non-existent account: %x", it.curHash)) - } - it.layer.lock.RUnlock() - if it.layer.Stale() { - it.fail, it.keys = ErrSnapshotStale, nil - } - return blob -} - -// Release is a noop for diff account iterators as there are no held resources. -func (it *diffAccountIterator) Release() {} - -// diskAccountIterator is an account iterator that steps over the live accounts -// contained within a disk layer. -type diskAccountIterator struct { - layer *diskLayer - it ethdb.Iterator -} - -// AccountIterator creates an account iterator over a disk layer. -func (dl *diskLayer) AccountIterator(seek common.Hash) AccountIterator { - pos := common.TrimRightZeroes(seek[:]) - return &diskAccountIterator{ - layer: dl, - it: dl.diskdb.NewIterator(rawdb.SnapshotAccountPrefix, pos), - } -} - -// Next steps the iterator forward one element, returning false if exhausted. -func (it *diskAccountIterator) Next() bool { - // If the iterator was already exhausted, don't bother - if it.it == nil { - return false - } - // Try to advance the iterator and release it if we reached the end - for { - if !it.it.Next() { - it.it.Release() - it.it = nil - return false - } - if len(it.it.Key()) == len(rawdb.SnapshotAccountPrefix)+common.HashLength { - break - } - } - return true -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -// -// A diff layer is immutable after creation content wise and can always be fully -// iterated without error, so this method always returns nil. -func (it *diskAccountIterator) Error() error { - if it.it == nil { - return nil // Iterator is exhausted and released - } - return it.it.Error() -} - -// Hash returns the hash of the account the iterator is currently at. -func (it *diskAccountIterator) Hash() common.Hash { - return common.BytesToHash(it.it.Key()) // The prefix will be truncated -} - -// Account returns the RLP encoded slim account the iterator is currently at. -func (it *diskAccountIterator) Account() []byte { - return it.it.Value() -} - -// Release releases the database snapshot held during iteration. -func (it *diskAccountIterator) Release() { - // The iterator is auto-released on exhaustion, so make sure it's still alive - if it.it != nil { - it.it.Release() - it.it = nil - } -} - -// diffStorageIterator is a storage iterator that steps over the specific storage -// (both live and deleted) contained within a single diff layer. Higher order -// iterators will use the deleted slot to skip deeper iterators. -type diffStorageIterator struct { - // curHash is the current hash the iterator is positioned on. The field is - // explicitly tracked since the referenced diff layer might go stale after - // the iterator was positioned and we don't want to fail accessing the old - // hash as long as the iterator is not touched any more. - curHash common.Hash - account common.Hash - - layer *diffLayer // Live layer to retrieve values from - keys []common.Hash // Keys left in the layer to iterate - fail error // Any failures encountered (stale) -} - -// StorageIterator creates a storage iterator over a single diff layer. -// Except the storage iterator is returned, there is an additional flag -// "destructed" returned. If it's true then it means the whole storage is -// destructed in this layer(maybe recreated too), don't bother deeper layer -// for storage retrieval. -func (dl *diffLayer) StorageIterator(account common.Hash, seek common.Hash) (StorageIterator, bool) { - // Create the storage for this account even it's marked - // as destructed. The iterator is for the new one which - // just has the same address as the deleted one. - hashes, destructed := dl.StorageList(account) - index := sort.Search(len(hashes), func(i int) bool { - return bytes.Compare(seek[:], hashes[i][:]) <= 0 - }) - // Assemble and returned the already seeked iterator - return &diffStorageIterator{ - layer: dl, - account: account, - keys: hashes[index:], - }, destructed -} - -// Next steps the iterator forward one element, returning false if exhausted. -func (it *diffStorageIterator) Next() bool { - // If the iterator was already stale, consider it a programmer error. Although - // we could just return false here, triggering this path would probably mean - // somebody forgot to check for Error, so lets blow up instead of undefined - // behavior that's hard to debug. - if it.fail != nil { - panic(fmt.Sprintf("called Next of failed iterator: %v", it.fail)) - } - // Stop iterating if all keys were exhausted - if len(it.keys) == 0 { - return false - } - if it.layer.Stale() { - it.fail, it.keys = ErrSnapshotStale, nil - return false - } - // Iterator seems to be still alive, retrieve and cache the live hash - it.curHash = it.keys[0] - // key cached, shift the iterator and notify the user of success - it.keys = it.keys[1:] - return true -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -func (it *diffStorageIterator) Error() error { - return it.fail -} - -// Hash returns the hash of the storage slot the iterator is currently at. -func (it *diffStorageIterator) Hash() common.Hash { - return it.curHash -} - -// Slot returns the raw storage slot value the iterator is currently at. -// This method may _fail_, if the underlying layer has been flattened between -// the call to Next and Value. That type of error will set it.Err. -// This method assumes that flattening does not delete elements from -// the storage mapping (writing nil into it is fine though), and will panic -// if elements have been deleted. -// -// Note the returned slot is not a copy, please don't modify it. -func (it *diffStorageIterator) Slot() []byte { - it.layer.lock.RLock() - storage, ok := it.layer.storageData[it.account] - if !ok { - panic(fmt.Sprintf("iterator referenced non-existent account storage: %x", it.account)) - } - // Storage slot might be nil(deleted), but it must exist - blob, ok := storage[it.curHash] - if !ok { - panic(fmt.Sprintf("iterator referenced non-existent storage slot: %x", it.curHash)) - } - it.layer.lock.RUnlock() - if it.layer.Stale() { - it.fail, it.keys = ErrSnapshotStale, nil - } - return blob -} - -// Release is a noop for diff account iterators as there are no held resources. -func (it *diffStorageIterator) Release() {} - -// diskStorageIterator is a storage iterator that steps over the live storage -// contained within a disk layer. -type diskStorageIterator struct { - layer *diskLayer - account common.Hash - it ethdb.Iterator -} - -// StorageIterator creates a storage iterator over a disk layer. -// If the whole storage is destructed, then all entries in the disk -// layer are deleted already. So the "destructed" flag returned here -// is always false. -func (dl *diskLayer) StorageIterator(account common.Hash, seek common.Hash) (StorageIterator, bool) { - pos := common.TrimRightZeroes(seek[:]) - return &diskStorageIterator{ - layer: dl, - account: account, - it: dl.diskdb.NewIterator(append(rawdb.SnapshotStoragePrefix, account.Bytes()...), pos), - }, false -} - -// Next steps the iterator forward one element, returning false if exhausted. -func (it *diskStorageIterator) Next() bool { - // If the iterator was already exhausted, don't bother - if it.it == nil { - return false - } - // Try to advance the iterator and release it if we reached the end - for { - if !it.it.Next() { - it.it.Release() - it.it = nil - return false - } - if len(it.it.Key()) == len(rawdb.SnapshotStoragePrefix)+common.HashLength+common.HashLength { - break - } - } - return true -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -// -// A diff layer is immutable after creation content wise and can always be fully -// iterated without error, so this method always returns nil. -func (it *diskStorageIterator) Error() error { - if it.it == nil { - return nil // Iterator is exhausted and released - } - return it.it.Error() -} - -// Hash returns the hash of the storage slot the iterator is currently at. -func (it *diskStorageIterator) Hash() common.Hash { - return common.BytesToHash(it.it.Key()) // The prefix will be truncated -} - -// Slot returns the raw storage slot content the iterator is currently at. -func (it *diskStorageIterator) Slot() []byte { - return it.it.Value() -} - -// Release releases the database snapshot held during iteration. -func (it *diskStorageIterator) Release() { - // The iterator is auto-released on exhaustion, so make sure it's still alive - if it.it != nil { - it.it.Release() - it.it = nil - } -} diff --git a/builder/core/state/snapshot/iterator_binary.go b/builder/core/state/snapshot/iterator_binary.go deleted file mode 100644 index 22184b254..000000000 --- a/builder/core/state/snapshot/iterator_binary.go +++ /dev/null @@ -1,213 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - - "github.com/ethereum/go-ethereum/common" -) - -// binaryIterator is a simplistic iterator to step over the accounts or storage -// in a snapshot, which may or may not be composed of multiple layers. Performance -// wise this iterator is slow, it's meant for cross validating the fast one, -type binaryIterator struct { - a Iterator - b Iterator - aDone bool - bDone bool - accountIterator bool - k common.Hash - account common.Hash - fail error -} - -// initBinaryAccountIterator creates a simplistic iterator to step over all the -// accounts in a slow, but easily verifiable way. Note this function is used for -// initialization, use `newBinaryAccountIterator` as the API. -func (dl *diffLayer) initBinaryAccountIterator() Iterator { - parent, ok := dl.parent.(*diffLayer) - if !ok { - l := &binaryIterator{ - a: dl.AccountIterator(common.Hash{}), - b: dl.Parent().AccountIterator(common.Hash{}), - accountIterator: true, - } - l.aDone = !l.a.Next() - l.bDone = !l.b.Next() - return l - } - l := &binaryIterator{ - a: dl.AccountIterator(common.Hash{}), - b: parent.initBinaryAccountIterator(), - accountIterator: true, - } - l.aDone = !l.a.Next() - l.bDone = !l.b.Next() - return l -} - -// initBinaryStorageIterator creates a simplistic iterator to step over all the -// storage slots in a slow, but easily verifiable way. Note this function is used -// for initialization, use `newBinaryStorageIterator` as the API. -func (dl *diffLayer) initBinaryStorageIterator(account common.Hash) Iterator { - parent, ok := dl.parent.(*diffLayer) - if !ok { - // If the storage in this layer is already destructed, discard all - // deeper layers but still return an valid single-branch iterator. - a, destructed := dl.StorageIterator(account, common.Hash{}) - if destructed { - l := &binaryIterator{ - a: a, - account: account, - } - l.aDone = !l.a.Next() - l.bDone = true - return l - } - // The parent is disk layer, don't need to take care "destructed" - // anymore. - b, _ := dl.Parent().StorageIterator(account, common.Hash{}) - l := &binaryIterator{ - a: a, - b: b, - account: account, - } - l.aDone = !l.a.Next() - l.bDone = !l.b.Next() - return l - } - // If the storage in this layer is already destructed, discard all - // deeper layers but still return an valid single-branch iterator. - a, destructed := dl.StorageIterator(account, common.Hash{}) - if destructed { - l := &binaryIterator{ - a: a, - account: account, - } - l.aDone = !l.a.Next() - l.bDone = true - return l - } - l := &binaryIterator{ - a: a, - b: parent.initBinaryStorageIterator(account), - account: account, - } - l.aDone = !l.a.Next() - l.bDone = !l.b.Next() - return l -} - -// Next steps the iterator forward one element, returning false if exhausted, -// or an error if iteration failed for some reason (e.g. root being iterated -// becomes stale and garbage collected). -func (it *binaryIterator) Next() bool { - if it.aDone && it.bDone { - return false - } -first: - if it.aDone { - it.k = it.b.Hash() - it.bDone = !it.b.Next() - return true - } - if it.bDone { - it.k = it.a.Hash() - it.aDone = !it.a.Next() - return true - } - nextA, nextB := it.a.Hash(), it.b.Hash() - if diff := bytes.Compare(nextA[:], nextB[:]); diff < 0 { - it.aDone = !it.a.Next() - it.k = nextA - return true - } else if diff == 0 { - // Now we need to advance one of them - it.aDone = !it.a.Next() - goto first - } - it.bDone = !it.b.Next() - it.k = nextB - return true -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -func (it *binaryIterator) Error() error { - return it.fail -} - -// Hash returns the hash of the account the iterator is currently at. -func (it *binaryIterator) Hash() common.Hash { - return it.k -} - -// Account returns the RLP encoded slim account the iterator is currently at, or -// nil if the iterated snapshot stack became stale (you can check Error after -// to see if it failed or not). -// -// Note the returned account is not a copy, please don't modify it. -func (it *binaryIterator) Account() []byte { - if !it.accountIterator { - return nil - } - // The topmost iterator must be `diffAccountIterator` - blob, err := it.a.(*diffAccountIterator).layer.AccountRLP(it.k) - if err != nil { - it.fail = err - return nil - } - return blob -} - -// Slot returns the raw storage slot data the iterator is currently at, or -// nil if the iterated snapshot stack became stale (you can check Error after -// to see if it failed or not). -// -// Note the returned slot is not a copy, please don't modify it. -func (it *binaryIterator) Slot() []byte { - if it.accountIterator { - return nil - } - blob, err := it.a.(*diffStorageIterator).layer.Storage(it.account, it.k) - if err != nil { - it.fail = err - return nil - } - return blob -} - -// Release recursively releases all the iterators in the stack. -func (it *binaryIterator) Release() { - it.a.Release() - it.b.Release() -} - -// newBinaryAccountIterator creates a simplistic account iterator to step over -// all the accounts in a slow, but easily verifiable way. -func (dl *diffLayer) newBinaryAccountIterator() AccountIterator { - iter := dl.initBinaryAccountIterator() - return iter.(AccountIterator) -} - -// newBinaryStorageIterator creates a simplistic account iterator to step over -// all the storage slots in a slow, but easily verifiable way. -func (dl *diffLayer) newBinaryStorageIterator(account common.Hash) StorageIterator { - iter := dl.initBinaryStorageIterator(account) - return iter.(StorageIterator) -} diff --git a/builder/core/state/snapshot/iterator_fast.go b/builder/core/state/snapshot/iterator_fast.go deleted file mode 100644 index 0502d9cf8..000000000 --- a/builder/core/state/snapshot/iterator_fast.go +++ /dev/null @@ -1,344 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "fmt" - "sort" - - "github.com/ethereum/go-ethereum/common" - "golang.org/x/exp/slices" -) - -// weightedIterator is a iterator with an assigned weight. It is used to prioritise -// which account or storage slot is the correct one if multiple iterators find the -// same one (modified in multiple consecutive blocks). -type weightedIterator struct { - it Iterator - priority int -} - -func (it *weightedIterator) Cmp(other *weightedIterator) int { - // Order the iterators primarily by the account hashes - hashI := it.it.Hash() - hashJ := other.it.Hash() - - switch bytes.Compare(hashI[:], hashJ[:]) { - case -1: - return -1 - case 1: - return 1 - } - // Same account/storage-slot in multiple layers, split by priority - if it.priority < other.priority { - return -1 - } - if it.priority > other.priority { - return 1 - } - return 0 -} - -// fastIterator is a more optimized multi-layer iterator which maintains a -// direct mapping of all iterators leading down to the bottom layer. -type fastIterator struct { - tree *Tree // Snapshot tree to reinitialize stale sub-iterators with - root common.Hash // Root hash to reinitialize stale sub-iterators through - - curAccount []byte - curSlot []byte - - iterators []*weightedIterator - initiated bool - account bool - fail error -} - -// newFastIterator creates a new hierarchical account or storage iterator with one -// element per diff layer. The returned combo iterator can be used to walk over -// the entire snapshot diff stack simultaneously. -func newFastIterator(tree *Tree, root common.Hash, account common.Hash, seek common.Hash, accountIterator bool) (*fastIterator, error) { - snap := tree.Snapshot(root) - if snap == nil { - return nil, fmt.Errorf("unknown snapshot: %x", root) - } - fi := &fastIterator{ - tree: tree, - root: root, - account: accountIterator, - } - current := snap.(snapshot) - for depth := 0; current != nil; depth++ { - if accountIterator { - fi.iterators = append(fi.iterators, &weightedIterator{ - it: current.AccountIterator(seek), - priority: depth, - }) - } else { - // If the whole storage is destructed in this layer, don't - // bother deeper layer anymore. But we should still keep - // the iterator for this layer, since the iterator can contain - // some valid slots which belongs to the re-created account. - it, destructed := current.StorageIterator(account, seek) - fi.iterators = append(fi.iterators, &weightedIterator{ - it: it, - priority: depth, - }) - if destructed { - break - } - } - current = current.Parent() - } - fi.init() - return fi, nil -} - -// init walks over all the iterators and resolves any clashes between them, after -// which it prepares the stack for step-by-step iteration. -func (fi *fastIterator) init() { - // Track which account hashes are iterators positioned on - var positioned = make(map[common.Hash]int) - - // Position all iterators and track how many remain live - for i := 0; i < len(fi.iterators); i++ { - // Retrieve the first element and if it clashes with a previous iterator, - // advance either the current one or the old one. Repeat until nothing is - // clashing any more. - it := fi.iterators[i] - for { - // If the iterator is exhausted, drop it off the end - if !it.it.Next() { - it.it.Release() - last := len(fi.iterators) - 1 - - fi.iterators[i] = fi.iterators[last] - fi.iterators[last] = nil - fi.iterators = fi.iterators[:last] - - i-- - break - } - // The iterator is still alive, check for collisions with previous ones - hash := it.it.Hash() - if other, exist := positioned[hash]; !exist { - positioned[hash] = i - break - } else { - // Iterators collide, one needs to be progressed, use priority to - // determine which. - // - // This whole else-block can be avoided, if we instead - // do an initial priority-sort of the iterators. If we do that, - // then we'll only wind up here if a lower-priority (preferred) iterator - // has the same value, and then we will always just continue. - // However, it costs an extra sort, so it's probably not better - if fi.iterators[other].priority < it.priority { - // The 'it' should be progressed - continue - } else { - // The 'other' should be progressed, swap them - it = fi.iterators[other] - fi.iterators[other], fi.iterators[i] = fi.iterators[i], fi.iterators[other] - continue - } - } - } - } - // Re-sort the entire list - slices.SortFunc(fi.iterators, func(a, b *weightedIterator) int { return a.Cmp(b) }) - fi.initiated = false -} - -// Next steps the iterator forward one element, returning false if exhausted. -func (fi *fastIterator) Next() bool { - if len(fi.iterators) == 0 { - return false - } - if !fi.initiated { - // Don't forward first time -- we had to 'Next' once in order to - // do the sorting already - fi.initiated = true - if fi.account { - fi.curAccount = fi.iterators[0].it.(AccountIterator).Account() - } else { - fi.curSlot = fi.iterators[0].it.(StorageIterator).Slot() - } - if innerErr := fi.iterators[0].it.Error(); innerErr != nil { - fi.fail = innerErr - return false - } - if fi.curAccount != nil || fi.curSlot != nil { - return true - } - // Implicit else: we've hit a nil-account or nil-slot, and need to - // fall through to the loop below to land on something non-nil - } - // If an account or a slot is deleted in one of the layers, the key will - // still be there, but the actual value will be nil. However, the iterator - // should not export nil-values (but instead simply omit the key), so we - // need to loop here until we either - // - get a non-nil value, - // - hit an error, - // - or exhaust the iterator - for { - if !fi.next(0) { - return false // exhausted - } - if fi.account { - fi.curAccount = fi.iterators[0].it.(AccountIterator).Account() - } else { - fi.curSlot = fi.iterators[0].it.(StorageIterator).Slot() - } - if innerErr := fi.iterators[0].it.Error(); innerErr != nil { - fi.fail = innerErr - return false // error - } - if fi.curAccount != nil || fi.curSlot != nil { - break // non-nil value found - } - } - return true -} - -// next handles the next operation internally and should be invoked when we know -// that two elements in the list may have the same value. -// -// For example, if the iterated hashes become [2,3,5,5,8,9,10], then we should -// invoke next(3), which will call Next on elem 3 (the second '5') and will -// cascade along the list, applying the same operation if needed. -func (fi *fastIterator) next(idx int) bool { - // If this particular iterator got exhausted, remove it and return true (the - // next one is surely not exhausted yet, otherwise it would have been removed - // already). - if it := fi.iterators[idx].it; !it.Next() { - it.Release() - - fi.iterators = append(fi.iterators[:idx], fi.iterators[idx+1:]...) - return len(fi.iterators) > 0 - } - // If there's no one left to cascade into, return - if idx == len(fi.iterators)-1 { - return true - } - // We next-ed the iterator at 'idx', now we may have to re-sort that element - var ( - cur, next = fi.iterators[idx], fi.iterators[idx+1] - curHash, nextHash = cur.it.Hash(), next.it.Hash() - ) - if diff := bytes.Compare(curHash[:], nextHash[:]); diff < 0 { - // It is still in correct place - return true - } else if diff == 0 && cur.priority < next.priority { - // So still in correct place, but we need to iterate on the next - fi.next(idx + 1) - return true - } - // At this point, the iterator is in the wrong location, but the remaining - // list is sorted. Find out where to move the item. - clash := -1 - index := sort.Search(len(fi.iterators), func(n int) bool { - // The iterator always advances forward, so anything before the old slot - // is known to be behind us, so just skip them altogether. This actually - // is an important clause since the sort order got invalidated. - if n < idx { - return false - } - if n == len(fi.iterators)-1 { - // Can always place an elem last - return true - } - nextHash := fi.iterators[n+1].it.Hash() - if diff := bytes.Compare(curHash[:], nextHash[:]); diff < 0 { - return true - } else if diff > 0 { - return false - } - // The elem we're placing it next to has the same value, - // so whichever winds up on n+1 will need further iteration - clash = n + 1 - - return cur.priority < fi.iterators[n+1].priority - }) - fi.move(idx, index) - if clash != -1 { - fi.next(clash) - } - return true -} - -// move advances an iterator to another position in the list. -func (fi *fastIterator) move(index, newpos int) { - elem := fi.iterators[index] - copy(fi.iterators[index:], fi.iterators[index+1:newpos+1]) - fi.iterators[newpos] = elem -} - -// Error returns any failure that occurred during iteration, which might have -// caused a premature iteration exit (e.g. snapshot stack becoming stale). -func (fi *fastIterator) Error() error { - return fi.fail -} - -// Hash returns the current key -func (fi *fastIterator) Hash() common.Hash { - return fi.iterators[0].it.Hash() -} - -// Account returns the current account blob. -// Note the returned account is not a copy, please don't modify it. -func (fi *fastIterator) Account() []byte { - return fi.curAccount -} - -// Slot returns the current storage slot. -// Note the returned slot is not a copy, please don't modify it. -func (fi *fastIterator) Slot() []byte { - return fi.curSlot -} - -// Release iterates over all the remaining live layer iterators and releases each -// of them individually. -func (fi *fastIterator) Release() { - for _, it := range fi.iterators { - it.it.Release() - } - fi.iterators = nil -} - -// Debug is a convenience helper during testing -func (fi *fastIterator) Debug() { - for _, it := range fi.iterators { - fmt.Printf("[p=%v v=%v] ", it.priority, it.it.Hash()[0]) - } - fmt.Println() -} - -// newFastAccountIterator creates a new hierarchical account iterator with one -// element per diff layer. The returned combo iterator can be used to walk over -// the entire snapshot diff stack simultaneously. -func newFastAccountIterator(tree *Tree, root common.Hash, seek common.Hash) (AccountIterator, error) { - return newFastIterator(tree, root, common.Hash{}, seek, true) -} - -// newFastStorageIterator creates a new hierarchical storage iterator with one -// element per diff layer. The returned combo iterator can be used to walk over -// the entire snapshot diff stack simultaneously. -func newFastStorageIterator(tree *Tree, root common.Hash, account common.Hash, seek common.Hash) (StorageIterator, error) { - return newFastIterator(tree, root, account, seek, false) -} diff --git a/builder/core/state/snapshot/iterator_test.go b/builder/core/state/snapshot/iterator_test.go deleted file mode 100644 index 54614427a..000000000 --- a/builder/core/state/snapshot/iterator_test.go +++ /dev/null @@ -1,1047 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - crand "crypto/rand" - "encoding/binary" - "fmt" - "math/rand" - "testing" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" -) - -// TestAccountIteratorBasics tests some simple single-layer(diff and disk) iteration -func TestAccountIteratorBasics(t *testing.T) { - var ( - destructs = make(map[common.Hash]struct{}) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - // Fill up a parent - for i := 0; i < 100; i++ { - h := randomHash() - data := randomAccount() - - accounts[h] = data - if rand.Intn(4) == 0 { - destructs[h] = struct{}{} - } - if rand.Intn(2) == 0 { - accStorage := make(map[common.Hash][]byte) - value := make([]byte, 32) - crand.Read(value) - accStorage[randomHash()] = value - storage[h] = accStorage - } - } - // Add some (identical) layers on top - diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, copyDestructs(destructs), copyAccounts(accounts), copyStorage(storage)) - it := diffLayer.AccountIterator(common.Hash{}) - verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator - - diskLayer := diffToDisk(diffLayer) - it = diskLayer.AccountIterator(common.Hash{}) - verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator -} - -// TestStorageIteratorBasics tests some simple single-layer(diff and disk) iteration for storage -func TestStorageIteratorBasics(t *testing.T) { - var ( - nilStorage = make(map[common.Hash]int) - accounts = make(map[common.Hash][]byte) - storage = make(map[common.Hash]map[common.Hash][]byte) - ) - // Fill some random data - for i := 0; i < 10; i++ { - h := randomHash() - accounts[h] = randomAccount() - - accStorage := make(map[common.Hash][]byte) - value := make([]byte, 32) - - var nilstorage int - for i := 0; i < 100; i++ { - crand.Read(value) - if rand.Intn(2) == 0 { - accStorage[randomHash()] = common.CopyBytes(value) - } else { - accStorage[randomHash()] = nil // delete slot - nilstorage += 1 - } - } - storage[h] = accStorage - nilStorage[h] = nilstorage - } - // Add some (identical) layers on top - diffLayer := newDiffLayer(emptyLayer(), common.Hash{}, nil, copyAccounts(accounts), copyStorage(storage)) - for account := range accounts { - it, _ := diffLayer.StorageIterator(account, common.Hash{}) - verifyIterator(t, 100, it, verifyNothing) // Nil is allowed for single layer iterator - } - - diskLayer := diffToDisk(diffLayer) - for account := range accounts { - it, _ := diskLayer.StorageIterator(account, common.Hash{}) - verifyIterator(t, 100-nilStorage[account], it, verifyNothing) // Nil is allowed for single layer iterator - } -} - -type testIterator struct { - values []byte -} - -func newTestIterator(values ...byte) *testIterator { - return &testIterator{values} -} - -func (ti *testIterator) Seek(common.Hash) { - panic("implement me") -} - -func (ti *testIterator) Next() bool { - ti.values = ti.values[1:] - return len(ti.values) > 0 -} - -func (ti *testIterator) Error() error { - return nil -} - -func (ti *testIterator) Hash() common.Hash { - return common.BytesToHash([]byte{ti.values[0]}) -} - -func (ti *testIterator) Account() []byte { - return nil -} - -func (ti *testIterator) Slot() []byte { - return nil -} - -func (ti *testIterator) Release() {} - -func TestFastIteratorBasics(t *testing.T) { - type testCase struct { - lists [][]byte - expKeys []byte - } - for i, tc := range []testCase{ - {lists: [][]byte{{0, 1, 8}, {1, 2, 8}, {2, 9}, {4}, - {7, 14, 15}, {9, 13, 15, 16}}, - expKeys: []byte{0, 1, 2, 4, 7, 8, 9, 13, 14, 15, 16}}, - {lists: [][]byte{{0, 8}, {1, 2, 8}, {7, 14, 15}, {8, 9}, - {9, 10}, {10, 13, 15, 16}}, - expKeys: []byte{0, 1, 2, 7, 8, 9, 10, 13, 14, 15, 16}}, - } { - var iterators []*weightedIterator - for i, data := range tc.lists { - it := newTestIterator(data...) - iterators = append(iterators, &weightedIterator{it, i}) - } - fi := &fastIterator{ - iterators: iterators, - initiated: false, - } - count := 0 - for fi.Next() { - if got, exp := fi.Hash()[31], tc.expKeys[count]; exp != got { - t.Errorf("tc %d, [%d]: got %d exp %d", i, count, got, exp) - } - count++ - } - } -} - -type verifyContent int - -const ( - verifyNothing verifyContent = iota - verifyAccount - verifyStorage -) - -func verifyIterator(t *testing.T, expCount int, it Iterator, verify verifyContent) { - t.Helper() - - var ( - count = 0 - last = common.Hash{} - ) - for it.Next() { - hash := it.Hash() - if bytes.Compare(last[:], hash[:]) >= 0 { - t.Errorf("wrong order: %x >= %x", last, hash) - } - count++ - if verify == verifyAccount && len(it.(AccountIterator).Account()) == 0 { - t.Errorf("iterator returned nil-value for hash %x", hash) - } else if verify == verifyStorage && len(it.(StorageIterator).Slot()) == 0 { - t.Errorf("iterator returned nil-value for hash %x", hash) - } - last = hash - } - if count != expCount { - t.Errorf("iterator count mismatch: have %d, want %d", count, expCount) - } - if err := it.Error(); err != nil { - t.Errorf("iterator failed: %v", err) - } -} - -// TestAccountIteratorTraversal tests some simple multi-layer iteration. -func TestAccountIteratorTraversal(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Stack three diff layers on top with various overlaps - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xbb", "0xdd", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, - randomAccountSet("0xcc", "0xf0", "0xff"), nil) - - // Verify the single and multi-layer iterators - head := snaps.Snapshot(common.HexToHash("0x04")) - - verifyIterator(t, 3, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) - verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - - it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - verifyIterator(t, 7, it, verifyAccount) - it.Release() - - // Test after persist some bottom-most layers into the disk, - // the functionalities still work. - limit := aggregatorMemoryLimit - defer func() { - aggregatorMemoryLimit = limit - }() - aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk - snaps.Cap(common.HexToHash("0x04"), 2) - verifyIterator(t, 7, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - verifyIterator(t, 7, it, verifyAccount) - it.Release() -} - -func TestStorageIteratorTraversal(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Stack three diff layers on top with various overlaps - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x04", "0x05", "0x06"}}, nil)) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x02", "0x03"}}, nil)) - - // Verify the single and multi-layer iterators - head := snaps.Snapshot(common.HexToHash("0x04")) - - diffIter, _ := head.(snapshot).StorageIterator(common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 3, diffIter, verifyNothing) - verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) - - it, _ := snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 6, it, verifyStorage) - it.Release() - - // Test after persist some bottom-most layers into the disk, - // the functionalities still work. - limit := aggregatorMemoryLimit - defer func() { - aggregatorMemoryLimit = limit - }() - aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk - snaps.Cap(common.HexToHash("0x04"), 2) - verifyIterator(t, 6, head.(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 6, it, verifyStorage) - it.Release() -} - -// TestAccountIteratorTraversalValues tests some multi-layer iteration, where we -// also expect the correct values to show up. -func TestAccountIteratorTraversalValues(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Create a batch of account sets to seed subsequent layers with - var ( - a = make(map[common.Hash][]byte) - b = make(map[common.Hash][]byte) - c = make(map[common.Hash][]byte) - d = make(map[common.Hash][]byte) - e = make(map[common.Hash][]byte) - f = make(map[common.Hash][]byte) - g = make(map[common.Hash][]byte) - h = make(map[common.Hash][]byte) - ) - for i := byte(2); i < 0xff; i++ { - a[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 0, i)) - if i > 20 && i%2 == 0 { - b[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 1, i)) - } - if i%4 == 0 { - c[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 2, i)) - } - if i%7 == 0 { - d[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 3, i)) - } - if i%8 == 0 { - e[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 4, i)) - } - if i > 50 || i < 85 { - f[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 5, i)) - } - if i%64 == 0 { - g[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 6, i)) - } - if i%128 == 0 { - h[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 7, i)) - } - } - // Assemble a stack of snapshots from the account layers - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, a, nil) - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, b, nil) - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, c, nil) - snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, d, nil) - snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, e, nil) - snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, f, nil) - snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, g, nil) - snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, h, nil) - - it, _ := snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) - head := snaps.Snapshot(common.HexToHash("0x09")) - for it.Next() { - hash := it.Hash() - want, err := head.AccountRLP(hash) - if err != nil { - t.Fatalf("failed to retrieve expected account: %v", err) - } - if have := it.Account(); !bytes.Equal(want, have) { - t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) - } - } - it.Release() - - // Test after persist some bottom-most layers into the disk, - // the functionalities still work. - limit := aggregatorMemoryLimit - defer func() { - aggregatorMemoryLimit = limit - }() - aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk - snaps.Cap(common.HexToHash("0x09"), 2) - - it, _ = snaps.AccountIterator(common.HexToHash("0x09"), common.Hash{}) - for it.Next() { - hash := it.Hash() - want, err := head.AccountRLP(hash) - if err != nil { - t.Fatalf("failed to retrieve expected account: %v", err) - } - if have := it.Account(); !bytes.Equal(want, have) { - t.Fatalf("hash %x: account mismatch: have %x, want %x", hash, have, want) - } - } - it.Release() -} - -func TestStorageIteratorTraversalValues(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - wrapStorage := func(storage map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte { - return map[common.Hash]map[common.Hash][]byte{ - common.HexToHash("0xaa"): storage, - } - } - // Create a batch of storage sets to seed subsequent layers with - var ( - a = make(map[common.Hash][]byte) - b = make(map[common.Hash][]byte) - c = make(map[common.Hash][]byte) - d = make(map[common.Hash][]byte) - e = make(map[common.Hash][]byte) - f = make(map[common.Hash][]byte) - g = make(map[common.Hash][]byte) - h = make(map[common.Hash][]byte) - ) - for i := byte(2); i < 0xff; i++ { - a[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 0, i)) - if i > 20 && i%2 == 0 { - b[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 1, i)) - } - if i%4 == 0 { - c[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 2, i)) - } - if i%7 == 0 { - d[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 3, i)) - } - if i%8 == 0 { - e[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 4, i)) - } - if i > 50 || i < 85 { - f[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 5, i)) - } - if i%64 == 0 { - g[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 6, i)) - } - if i%128 == 0 { - h[common.Hash{i}] = []byte(fmt.Sprintf("layer-%d, key %d", 7, i)) - } - } - // Assemble a stack of snapshots from the account layers - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, randomAccountSet("0xaa"), wrapStorage(a)) - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, randomAccountSet("0xaa"), wrapStorage(b)) - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, randomAccountSet("0xaa"), wrapStorage(c)) - snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, randomAccountSet("0xaa"), wrapStorage(d)) - snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), nil, randomAccountSet("0xaa"), wrapStorage(e)) - snaps.Update(common.HexToHash("0x07"), common.HexToHash("0x06"), nil, randomAccountSet("0xaa"), wrapStorage(e)) - snaps.Update(common.HexToHash("0x08"), common.HexToHash("0x07"), nil, randomAccountSet("0xaa"), wrapStorage(g)) - snaps.Update(common.HexToHash("0x09"), common.HexToHash("0x08"), nil, randomAccountSet("0xaa"), wrapStorage(h)) - - it, _ := snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) - head := snaps.Snapshot(common.HexToHash("0x09")) - for it.Next() { - hash := it.Hash() - want, err := head.Storage(common.HexToHash("0xaa"), hash) - if err != nil { - t.Fatalf("failed to retrieve expected storage slot: %v", err) - } - if have := it.Slot(); !bytes.Equal(want, have) { - t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) - } - } - it.Release() - - // Test after persist some bottom-most layers into the disk, - // the functionalities still work. - limit := aggregatorMemoryLimit - defer func() { - aggregatorMemoryLimit = limit - }() - aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk - snaps.Cap(common.HexToHash("0x09"), 2) - - it, _ = snaps.StorageIterator(common.HexToHash("0x09"), common.HexToHash("0xaa"), common.Hash{}) - for it.Next() { - hash := it.Hash() - want, err := head.Storage(common.HexToHash("0xaa"), hash) - if err != nil { - t.Fatalf("failed to retrieve expected slot: %v", err) - } - if have := it.Slot(); !bytes.Equal(want, have) { - t.Fatalf("hash %x: slot mismatch: have %x, want %x", hash, have, want) - } - } - it.Release() -} - -// This testcase is notorious, all layers contain the exact same 200 accounts. -func TestAccountIteratorLargeTraversal(t *testing.T) { - // Create a custom account factory to recreate the same addresses - makeAccounts := func(num int) map[common.Hash][]byte { - accounts := make(map[common.Hash][]byte) - for i := 0; i < num; i++ { - h := common.Hash{} - binary.BigEndian.PutUint64(h[:], uint64(i+1)) - accounts[h] = randomAccount() - } - return accounts - } - // Build up a large stack of snapshots - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - for i := 1; i < 128; i++ { - snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) - } - // Iterate the entire stack and ensure everything is hit only once - head := snaps.Snapshot(common.HexToHash("0x80")) - verifyIterator(t, 200, head.(snapshot).AccountIterator(common.Hash{}), verifyNothing) - verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - - it, _ := snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) - verifyIterator(t, 200, it, verifyAccount) - it.Release() - - // Test after persist some bottom-most layers into the disk, - // the functionalities still work. - limit := aggregatorMemoryLimit - defer func() { - aggregatorMemoryLimit = limit - }() - aggregatorMemoryLimit = 0 // Force pushing the bottom-most layer into disk - snaps.Cap(common.HexToHash("0x80"), 2) - - verifyIterator(t, 200, head.(*diffLayer).newBinaryAccountIterator(), verifyAccount) - - it, _ = snaps.AccountIterator(common.HexToHash("0x80"), common.Hash{}) - verifyIterator(t, 200, it, verifyAccount) - it.Release() -} - -// TestAccountIteratorFlattening tests what happens when we -// - have a live iterator on child C (parent C1 -> C2 .. CN) -// - flattens C2 all the way into CN -// - continues iterating -func TestAccountIteratorFlattening(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Create a stack of diffs on top - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xbb", "0xdd", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, - randomAccountSet("0xcc", "0xf0", "0xff"), nil) - - // Create an iterator and flatten the data from underneath it - it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - defer it.Release() - - if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { - t.Fatalf("failed to flatten snapshot stack: %v", err) - } - //verifyIterator(t, 7, it) -} - -func TestAccountIteratorSeek(t *testing.T) { - // Create a snapshot stack with some initial data - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa", "0xee", "0xff", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xbb", "0xdd", "0xf0"), nil) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, - randomAccountSet("0xcc", "0xf0", "0xff"), nil) - - // Account set is now - // 02: aa, ee, f0, ff - // 03: aa, bb, dd, ee, f0 (, f0), ff - // 04: aa, bb, cc, dd, ee, f0 (, f0), ff (, ff) - // Construct various iterators and ensure their traversal is correct - it, _ := snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xdd")) - defer it.Release() - verifyIterator(t, 3, it, verifyAccount) // expected: ee, f0, ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xaa")) - defer it.Release() - verifyIterator(t, 4, it, verifyAccount) // expected: aa, ee, f0, ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff")) - defer it.Release() - verifyIterator(t, 1, it, verifyAccount) // expected: ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x02"), common.HexToHash("0xff1")) - defer it.Release() - verifyIterator(t, 0, it, verifyAccount) // expected: nothing - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xbb")) - defer it.Release() - verifyIterator(t, 6, it, verifyAccount) // expected: bb, cc, dd, ee, f0, ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xef")) - defer it.Release() - verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xf0")) - defer it.Release() - verifyIterator(t, 2, it, verifyAccount) // expected: f0, ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff")) - defer it.Release() - verifyIterator(t, 1, it, verifyAccount) // expected: ff - - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.HexToHash("0xff1")) - defer it.Release() - verifyIterator(t, 0, it, verifyAccount) // expected: nothing -} - -func TestStorageIteratorSeek(t *testing.T) { - // Create a snapshot stack with some initial data - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Stack three diff layers on top with various overlaps - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x05", "0x06"}}, nil)) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x05", "0x08"}}, nil)) - - // Account set is now - // 02: 01, 03, 05 - // 03: 01, 02, 03, 05 (, 05), 06 - // 04: 01(, 01), 02, 03, 05(, 05, 05), 06, 08 - // Construct various iterators and ensure their traversal is correct - it, _ := snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x01")) - defer it.Release() - verifyIterator(t, 3, it, verifyStorage) // expected: 01, 03, 05 - - it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x02")) - defer it.Release() - verifyIterator(t, 2, it, verifyStorage) // expected: 03, 05 - - it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x5")) - defer it.Release() - verifyIterator(t, 1, it, verifyStorage) // expected: 05 - - it, _ = snaps.StorageIterator(common.HexToHash("0x02"), common.HexToHash("0xaa"), common.HexToHash("0x6")) - defer it.Release() - verifyIterator(t, 0, it, verifyStorage) // expected: nothing - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x01")) - defer it.Release() - verifyIterator(t, 6, it, verifyStorage) // expected: 01, 02, 03, 05, 06, 08 - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x05")) - defer it.Release() - verifyIterator(t, 3, it, verifyStorage) // expected: 05, 06, 08 - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x08")) - defer it.Release() - verifyIterator(t, 1, it, verifyStorage) // expected: 08 - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.HexToHash("0x09")) - defer it.Release() - verifyIterator(t, 0, it, verifyStorage) // expected: nothing -} - -// TestAccountIteratorDeletions tests that the iterator behaves correct when there are -// deleted accounts (where the Account() value is nil). The iterator -// should not output any accounts or nil-values for those cases. -func TestAccountIteratorDeletions(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Stack three diff layers on top with various overlaps - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), - nil, randomAccountSet("0x11", "0x22", "0x33"), nil) - - deleted := common.HexToHash("0x22") - destructed := map[common.Hash]struct{}{ - deleted: {}, - } - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), - destructed, randomAccountSet("0x11", "0x33"), nil) - - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), - nil, randomAccountSet("0x33", "0x44", "0x55"), nil) - - // The output should be 11,33,44,55 - it, _ := snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - // Do a quick check - verifyIterator(t, 4, it, verifyAccount) - it.Release() - - // And a more detailed verification that we indeed do not see '0x22' - it, _ = snaps.AccountIterator(common.HexToHash("0x04"), common.Hash{}) - defer it.Release() - for it.Next() { - hash := it.Hash() - if it.Account() == nil { - t.Errorf("iterator returned nil-value for hash %x", hash) - } - if hash == deleted { - t.Errorf("expected deleted elem %x to not be returned by iterator", deleted) - } - } -} - -func TestStorageIteratorDeletions(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Stack three diff layers on top with various overlaps - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x01", "0x03", "0x05"}}, nil)) - - snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x02", "0x04", "0x06"}}, [][]string{{"0x01", "0x03"}})) - - // The output should be 02,04,05,06 - it, _ := snaps.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 4, it, verifyStorage) - it.Release() - - // The output should be 04,05,06 - it, _ = snaps.StorageIterator(common.HexToHash("0x03"), common.HexToHash("0xaa"), common.HexToHash("0x03")) - verifyIterator(t, 3, it, verifyStorage) - it.Release() - - // Destruct the whole storage - destructed := map[common.Hash]struct{}{ - common.HexToHash("0xaa"): {}, - } - snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), destructed, nil, nil) - - it, _ = snaps.StorageIterator(common.HexToHash("0x04"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 0, it, verifyStorage) - it.Release() - - // Re-insert the slots of the same account - snaps.Update(common.HexToHash("0x05"), common.HexToHash("0x04"), nil, - randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x07", "0x08", "0x09"}}, nil)) - - // The output should be 07,08,09 - it, _ = snaps.StorageIterator(common.HexToHash("0x05"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 3, it, verifyStorage) - it.Release() - - // Destruct the whole storage but re-create the account in the same layer - snaps.Update(common.HexToHash("0x06"), common.HexToHash("0x05"), destructed, randomAccountSet("0xaa"), randomStorageSet([]string{"0xaa"}, [][]string{{"0x11", "0x12"}}, nil)) - it, _ = snaps.StorageIterator(common.HexToHash("0x06"), common.HexToHash("0xaa"), common.Hash{}) - verifyIterator(t, 2, it, verifyStorage) // The output should be 11,12 - it.Release() - - verifyIterator(t, 2, snaps.Snapshot(common.HexToHash("0x06")).(*diffLayer).newBinaryStorageIterator(common.HexToHash("0xaa")), verifyStorage) -} - -// BenchmarkAccountIteratorTraversal is a bit a bit notorious -- all layers contain the -// exact same 200 accounts. That means that we need to process 2000 items, but -// only spit out 200 values eventually. -// -// The value-fetching benchmark is easy on the binary iterator, since it never has to reach -// down at any depth for retrieving the values -- all are on the topmost layer -// -// BenchmarkAccountIteratorTraversal/binary_iterator_keys-6 2239 483674 ns/op -// BenchmarkAccountIteratorTraversal/binary_iterator_values-6 2403 501810 ns/op -// BenchmarkAccountIteratorTraversal/fast_iterator_keys-6 1923 677966 ns/op -// BenchmarkAccountIteratorTraversal/fast_iterator_values-6 1741 649967 ns/op -func BenchmarkAccountIteratorTraversal(b *testing.B) { - // Create a custom account factory to recreate the same addresses - makeAccounts := func(num int) map[common.Hash][]byte { - accounts := make(map[common.Hash][]byte) - for i := 0; i < num; i++ { - h := common.Hash{} - binary.BigEndian.PutUint64(h[:], uint64(i+1)) - accounts[h] = randomAccount() - } - return accounts - } - // Build up a large stack of snapshots - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - for i := 1; i <= 100; i++ { - snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(200), nil) - } - // We call this once before the benchmark, so the creation of - // sorted accountlists are not included in the results. - head := snaps.Snapshot(common.HexToHash("0x65")) - head.(*diffLayer).newBinaryAccountIterator() - - b.Run("binary iterator keys", func(b *testing.B) { - for i := 0; i < b.N; i++ { - got := 0 - it := head.(*diffLayer).newBinaryAccountIterator() - for it.Next() { - got++ - } - if exp := 200; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("binary iterator values", func(b *testing.B) { - for i := 0; i < b.N; i++ { - got := 0 - it := head.(*diffLayer).newBinaryAccountIterator() - for it.Next() { - got++ - head.(*diffLayer).accountRLP(it.Hash(), 0) - } - if exp := 200; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("fast iterator keys", func(b *testing.B) { - for i := 0; i < b.N; i++ { - it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) - defer it.Release() - - got := 0 - for it.Next() { - got++ - } - if exp := 200; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("fast iterator values", func(b *testing.B) { - for i := 0; i < b.N; i++ { - it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) - defer it.Release() - - got := 0 - for it.Next() { - got++ - it.Account() - } - if exp := 200; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) -} - -// BenchmarkAccountIteratorLargeBaselayer is a pretty realistic benchmark, where -// the baselayer is a lot larger than the upper layer. -// -// This is heavy on the binary iterator, which in most cases will have to -// call recursively 100 times for the majority of the values -// -// BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(keys)-6 514 1971999 ns/op -// BenchmarkAccountIteratorLargeBaselayer/binary_iterator_(values)-6 61 18997492 ns/op -// BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(keys)-6 10000 114385 ns/op -// BenchmarkAccountIteratorLargeBaselayer/fast_iterator_(values)-6 4047 296823 ns/op -func BenchmarkAccountIteratorLargeBaselayer(b *testing.B) { - // Create a custom account factory to recreate the same addresses - makeAccounts := func(num int) map[common.Hash][]byte { - accounts := make(map[common.Hash][]byte) - for i := 0; i < num; i++ { - h := common.Hash{} - binary.BigEndian.PutUint64(h[:], uint64(i+1)) - accounts[h] = randomAccount() - } - return accounts - } - // Build up a large stack of snapshots - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, makeAccounts(2000), nil) - for i := 2; i <= 100; i++ { - snaps.Update(common.HexToHash(fmt.Sprintf("0x%02x", i+1)), common.HexToHash(fmt.Sprintf("0x%02x", i)), nil, makeAccounts(20), nil) - } - // We call this once before the benchmark, so the creation of - // sorted accountlists are not included in the results. - head := snaps.Snapshot(common.HexToHash("0x65")) - head.(*diffLayer).newBinaryAccountIterator() - - b.Run("binary iterator (keys)", func(b *testing.B) { - for i := 0; i < b.N; i++ { - got := 0 - it := head.(*diffLayer).newBinaryAccountIterator() - for it.Next() { - got++ - } - if exp := 2000; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("binary iterator (values)", func(b *testing.B) { - for i := 0; i < b.N; i++ { - got := 0 - it := head.(*diffLayer).newBinaryAccountIterator() - for it.Next() { - got++ - v := it.Hash() - head.(*diffLayer).accountRLP(v, 0) - } - if exp := 2000; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("fast iterator (keys)", func(b *testing.B) { - for i := 0; i < b.N; i++ { - it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) - defer it.Release() - - got := 0 - for it.Next() { - got++ - } - if exp := 2000; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) - b.Run("fast iterator (values)", func(b *testing.B) { - for i := 0; i < b.N; i++ { - it, _ := snaps.AccountIterator(common.HexToHash("0x65"), common.Hash{}) - defer it.Release() - - got := 0 - for it.Next() { - it.Account() - got++ - } - if exp := 2000; got != exp { - b.Errorf("iterator len wrong, expected %d, got %d", exp, got) - } - } - }) -} - -/* -func BenchmarkBinaryAccountIteration(b *testing.B) { - benchmarkAccountIteration(b, func(snap snapshot) AccountIterator { - return snap.(*diffLayer).newBinaryAccountIterator() - }) -} - -func BenchmarkFastAccountIteration(b *testing.B) { - benchmarkAccountIteration(b, newFastAccountIterator) -} - -func benchmarkAccountIteration(b *testing.B, iterator func(snap snapshot) AccountIterator) { - // Create a diff stack and randomize the accounts across them - layers := make([]map[common.Hash][]byte, 128) - for i := 0; i < len(layers); i++ { - layers[i] = make(map[common.Hash][]byte) - } - for i := 0; i < b.N; i++ { - depth := rand.Intn(len(layers)) - layers[depth][randomHash()] = randomAccount() - } - stack := snapshot(emptyLayer()) - for _, layer := range layers { - stack = stack.Update(common.Hash{}, layer, nil, nil) - } - // Reset the timers and report all the stats - it := iterator(stack) - - b.ResetTimer() - b.ReportAllocs() - - for it.Next() { - } -} -*/ diff --git a/builder/core/state/snapshot/journal.go b/builder/core/state/snapshot/journal.go deleted file mode 100644 index 8513e73dd..000000000 --- a/builder/core/state/snapshot/journal.go +++ /dev/null @@ -1,363 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "time" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/triedb" -) - -const journalVersion uint64 = 0 - -// journalGenerator is a disk layer entry containing the generator progress marker. -type journalGenerator struct { - // Indicator that whether the database was in progress of being wiped. - // It's deprecated but keep it here for background compatibility. - Wiping bool - - Done bool // Whether the generator finished creating the snapshot - Marker []byte - Accounts uint64 - Slots uint64 - Storage uint64 -} - -// journalDestruct is an account deletion entry in a diffLayer's disk journal. -type journalDestruct struct { - Hash common.Hash -} - -// journalAccount is an account entry in a diffLayer's disk journal. -type journalAccount struct { - Hash common.Hash - Blob []byte -} - -// journalStorage is an account's storage map in a diffLayer's disk journal. -type journalStorage struct { - Hash common.Hash - Keys []common.Hash - Vals [][]byte -} - -func ParseGeneratorStatus(generatorBlob []byte) string { - if len(generatorBlob) == 0 { - return "" - } - var generator journalGenerator - if err := rlp.DecodeBytes(generatorBlob, &generator); err != nil { - log.Warn("failed to decode snapshot generator", "err", err) - return "" - } - // Figure out whether we're after or within an account - var m string - switch marker := generator.Marker; len(marker) { - case common.HashLength: - m = fmt.Sprintf("at %#x", marker) - case 2 * common.HashLength: - m = fmt.Sprintf("in %#x at %#x", marker[:common.HashLength], marker[common.HashLength:]) - default: - m = fmt.Sprintf("%#x", marker) - } - return fmt.Sprintf(`Done: %v, Accounts: %d, Slots: %d, Storage: %d, Marker: %s`, - generator.Done, generator.Accounts, generator.Slots, generator.Storage, m) -} - -// loadAndParseJournal tries to parse the snapshot journal in latest format. -func loadAndParseJournal(db ethdb.KeyValueStore, base *diskLayer) (snapshot, journalGenerator, error) { - // Retrieve the disk layer generator. It must exist, no matter the - // snapshot is fully generated or not. Otherwise the entire disk - // layer is invalid. - generatorBlob := rawdb.ReadSnapshotGenerator(db) - if len(generatorBlob) == 0 { - return nil, journalGenerator{}, errors.New("missing snapshot generator") - } - var generator journalGenerator - if err := rlp.DecodeBytes(generatorBlob, &generator); err != nil { - return nil, journalGenerator{}, fmt.Errorf("failed to decode snapshot generator: %v", err) - } - // Retrieve the diff layer journal. It's possible that the journal is - // not existent, e.g. the disk layer is generating while that the Geth - // crashes without persisting the diff journal. - // So if there is no journal, or the journal is invalid(e.g. the journal - // is not matched with disk layer; or the it's the legacy-format journal, - // etc.), we just discard all diffs and try to recover them later. - var current snapshot = base - err := iterateJournal(db, func(parent common.Hash, root common.Hash, destructSet map[common.Hash]struct{}, accountData map[common.Hash][]byte, storageData map[common.Hash]map[common.Hash][]byte) error { - current = newDiffLayer(current, root, destructSet, accountData, storageData) - return nil - }) - if err != nil { - return base, generator, nil - } - return current, generator, nil -} - -// loadSnapshot loads a pre-existing state snapshot backed by a key-value store. -func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash, cache int, recovery bool, noBuild bool) (snapshot, bool, error) { - // If snapshotting is disabled (initial sync in progress), don't do anything, - // wait for the chain to permit us to do something meaningful - if rawdb.ReadSnapshotDisabled(diskdb) { - return nil, true, nil - } - // Retrieve the block number and hash of the snapshot, failing if no snapshot - // is present in the database (or crashed mid-update). - baseRoot := rawdb.ReadSnapshotRoot(diskdb) - if baseRoot == (common.Hash{}) { - return nil, false, errors.New("missing or corrupted snapshot") - } - base := &diskLayer{ - diskdb: diskdb, - triedb: triedb, - cache: fastcache.New(cache * 1024 * 1024), - root: baseRoot, - } - snapshot, generator, err := loadAndParseJournal(diskdb, base) - if err != nil { - log.Warn("Failed to load journal", "error", err) - return nil, false, err - } - // Entire snapshot journal loaded, sanity check the head. If the loaded - // snapshot is not matched with current state root, print a warning log - // or discard the entire snapshot it's legacy snapshot. - // - // Possible scenario: Geth was crashed without persisting journal and then - // restart, the head is rewound to the point with available state(trie) - // which is below the snapshot. In this case the snapshot can be recovered - // by re-executing blocks but right now it's unavailable. - if head := snapshot.Root(); head != root { - // If it's legacy snapshot, or it's new-format snapshot but - // it's not in recovery mode, returns the error here for - // rebuilding the entire snapshot forcibly. - if !recovery { - return nil, false, fmt.Errorf("head doesn't match snapshot: have %#x, want %#x", head, root) - } - // It's in snapshot recovery, the assumption is held that - // the disk layer is always higher than chain head. It can - // be eventually recovered when the chain head beyonds the - // disk layer. - log.Warn("Snapshot is not continuous with chain", "snaproot", head, "chainroot", root) - } - // Load the disk layer status from the generator if it's not complete - if !generator.Done { - base.genMarker = generator.Marker - if base.genMarker == nil { - base.genMarker = []byte{} - } - } - // Everything loaded correctly, resume any suspended operations - // if the background generation is allowed - if !generator.Done && !noBuild { - base.genPending = make(chan struct{}) - base.genAbort = make(chan chan *generatorStats) - - var origin uint64 - if len(generator.Marker) >= 8 { - origin = binary.BigEndian.Uint64(generator.Marker) - } - go base.generate(&generatorStats{ - origin: origin, - start: time.Now(), - accounts: generator.Accounts, - slots: generator.Slots, - storage: common.StorageSize(generator.Storage), - }) - } - return snapshot, false, nil -} - -// Journal terminates any in-progress snapshot generation, also implicitly pushing -// the progress into the database. -func (dl *diskLayer) Journal(buffer *bytes.Buffer) (common.Hash, error) { - // If the snapshot is currently being generated, abort it - var stats *generatorStats - if dl.genAbort != nil { - abort := make(chan *generatorStats) - dl.genAbort <- abort - - if stats = <-abort; stats != nil { - stats.Log("Journalling in-progress snapshot", dl.root, dl.genMarker) - } - } - // Ensure the layer didn't get stale - dl.lock.RLock() - defer dl.lock.RUnlock() - - if dl.stale { - return common.Hash{}, ErrSnapshotStale - } - // Ensure the generator stats is written even if none was ran this cycle - journalProgress(dl.diskdb, dl.genMarker, stats) - - log.Debug("Journalled disk layer", "root", dl.root) - return dl.root, nil -} - -// Journal writes the memory layer contents into a buffer to be stored in the -// database as the snapshot journal. -func (dl *diffLayer) Journal(buffer *bytes.Buffer) (common.Hash, error) { - // Journal the parent first - base, err := dl.parent.Journal(buffer) - if err != nil { - return common.Hash{}, err - } - // Ensure the layer didn't get stale - dl.lock.RLock() - defer dl.lock.RUnlock() - - if dl.Stale() { - return common.Hash{}, ErrSnapshotStale - } - // Everything below was journalled, persist this layer too - if err := rlp.Encode(buffer, dl.root); err != nil { - return common.Hash{}, err - } - destructs := make([]journalDestruct, 0, len(dl.destructSet)) - for hash := range dl.destructSet { - destructs = append(destructs, journalDestruct{Hash: hash}) - } - if err := rlp.Encode(buffer, destructs); err != nil { - return common.Hash{}, err - } - accounts := make([]journalAccount, 0, len(dl.accountData)) - for hash, blob := range dl.accountData { - accounts = append(accounts, journalAccount{Hash: hash, Blob: blob}) - } - if err := rlp.Encode(buffer, accounts); err != nil { - return common.Hash{}, err - } - storage := make([]journalStorage, 0, len(dl.storageData)) - for hash, slots := range dl.storageData { - keys := make([]common.Hash, 0, len(slots)) - vals := make([][]byte, 0, len(slots)) - for key, val := range slots { - keys = append(keys, key) - vals = append(vals, val) - } - storage = append(storage, journalStorage{Hash: hash, Keys: keys, Vals: vals}) - } - if err := rlp.Encode(buffer, storage); err != nil { - return common.Hash{}, err - } - log.Debug("Journalled diff layer", "root", dl.root, "parent", dl.parent.Root()) - return base, nil -} - -// journalCallback is a function which is invoked by iterateJournal, every -// time a difflayer is loaded from disk. -type journalCallback = func(parent common.Hash, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) error - -// iterateJournal iterates through the journalled difflayers, loading them from -// the database, and invoking the callback for each loaded layer. -// The order is incremental; starting with the bottom-most difflayer, going towards -// the most recent layer. -// This method returns error either if there was some error reading from disk, -// OR if the callback returns an error when invoked. -func iterateJournal(db ethdb.KeyValueReader, callback journalCallback) error { - journal := rawdb.ReadSnapshotJournal(db) - if len(journal) == 0 { - log.Warn("Loaded snapshot journal", "diffs", "missing") - return nil - } - r := rlp.NewStream(bytes.NewReader(journal), 0) - // Firstly, resolve the first element as the journal version - version, err := r.Uint64() - if err != nil { - log.Warn("Failed to resolve the journal version", "error", err) - return errors.New("failed to resolve journal version") - } - if version != journalVersion { - log.Warn("Discarded the snapshot journal with wrong version", "required", journalVersion, "got", version) - return errors.New("wrong journal version") - } - // Secondly, resolve the disk layer root, ensure it's continuous - // with disk layer. Note now we can ensure it's the snapshot journal - // correct version, so we expect everything can be resolved properly. - var parent common.Hash - if err := r.Decode(&parent); err != nil { - return errors.New("missing disk layer root") - } - if baseRoot := rawdb.ReadSnapshotRoot(db); baseRoot != parent { - log.Warn("Loaded snapshot journal", "diskroot", baseRoot, "diffs", "unmatched") - return errors.New("mismatched disk and diff layers") - } - for { - var ( - root common.Hash - destructs []journalDestruct - accounts []journalAccount - storage []journalStorage - destructSet = make(map[common.Hash]struct{}) - accountData = make(map[common.Hash][]byte) - storageData = make(map[common.Hash]map[common.Hash][]byte) - ) - // Read the next diff journal entry - if err := r.Decode(&root); err != nil { - // The first read may fail with EOF, marking the end of the journal - if errors.Is(err, io.EOF) { - return nil - } - return fmt.Errorf("load diff root: %v", err) - } - if err := r.Decode(&destructs); err != nil { - return fmt.Errorf("load diff destructs: %v", err) - } - if err := r.Decode(&accounts); err != nil { - return fmt.Errorf("load diff accounts: %v", err) - } - if err := r.Decode(&storage); err != nil { - return fmt.Errorf("load diff storage: %v", err) - } - for _, entry := range destructs { - destructSet[entry.Hash] = struct{}{} - } - for _, entry := range accounts { - if len(entry.Blob) > 0 { // RLP loses nil-ness, but `[]byte{}` is not a valid item, so reinterpret that - accountData[entry.Hash] = entry.Blob - } else { - accountData[entry.Hash] = nil - } - } - for _, entry := range storage { - slots := make(map[common.Hash][]byte) - for i, key := range entry.Keys { - if len(entry.Vals[i]) > 0 { // RLP loses nil-ness, but `[]byte{}` is not a valid item, so reinterpret that - slots[key] = entry.Vals[i] - } else { - slots[key] = nil - } - } - storageData[entry.Hash] = slots - } - if err := callback(parent, root, destructSet, accountData, storageData); err != nil { - return err - } - parent = root - } -} diff --git a/builder/core/state/snapshot/metrics.go b/builder/core/state/snapshot/metrics.go deleted file mode 100644 index b2e884588..000000000 --- a/builder/core/state/snapshot/metrics.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 snapshot - -import "github.com/ethereum/go-ethereum/metrics" - -// Metrics in generation -var ( - snapGeneratedAccountMeter = metrics.NewRegisteredMeter("state/snapshot/generation/account/generated", nil) - snapRecoveredAccountMeter = metrics.NewRegisteredMeter("state/snapshot/generation/account/recovered", nil) - snapWipedAccountMeter = metrics.NewRegisteredMeter("state/snapshot/generation/account/wiped", nil) - snapMissallAccountMeter = metrics.NewRegisteredMeter("state/snapshot/generation/account/missall", nil) - snapGeneratedStorageMeter = metrics.NewRegisteredMeter("state/snapshot/generation/storage/generated", nil) - snapRecoveredStorageMeter = metrics.NewRegisteredMeter("state/snapshot/generation/storage/recovered", nil) - snapWipedStorageMeter = metrics.NewRegisteredMeter("state/snapshot/generation/storage/wiped", nil) - snapMissallStorageMeter = metrics.NewRegisteredMeter("state/snapshot/generation/storage/missall", nil) - snapDanglingStorageMeter = metrics.NewRegisteredMeter("state/snapshot/generation/storage/dangling", nil) - snapSuccessfulRangeProofMeter = metrics.NewRegisteredMeter("state/snapshot/generation/proof/success", nil) - snapFailedRangeProofMeter = metrics.NewRegisteredMeter("state/snapshot/generation/proof/failure", nil) - - // snapAccountProveCounter measures time spent on the account proving - snapAccountProveCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/account/prove", nil) - // snapAccountTrieReadCounter measures time spent on the account trie iteration - snapAccountTrieReadCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/account/trieread", nil) - // snapAccountSnapReadCounter measures time spent on the snapshot account iteration - snapAccountSnapReadCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/account/snapread", nil) - // snapAccountWriteCounter measures time spent on writing/updating/deleting accounts - snapAccountWriteCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/account/write", nil) - // snapStorageProveCounter measures time spent on storage proving - snapStorageProveCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/prove", nil) - // snapStorageTrieReadCounter measures time spent on the storage trie iteration - snapStorageTrieReadCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/trieread", nil) - // snapStorageSnapReadCounter measures time spent on the snapshot storage iteration - snapStorageSnapReadCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/snapread", nil) - // snapStorageWriteCounter measures time spent on writing/updating storages - snapStorageWriteCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/write", nil) - // snapStorageCleanCounter measures time spent on deleting storages - snapStorageCleanCounter = metrics.NewRegisteredCounter("state/snapshot/generation/duration/storage/clean", nil) -) diff --git a/builder/core/state/snapshot/snapshot.go b/builder/core/state/snapshot/snapshot.go deleted file mode 100644 index 5c38cb725..000000000 --- a/builder/core/state/snapshot/snapshot.go +++ /dev/null @@ -1,887 +0,0 @@ -// 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 snapshot implements a journalled, dynamic state dump. -package snapshot - -import ( - "bytes" - "errors" - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/triedb" -) - -var ( - snapshotCleanAccountHitMeter = metrics.NewRegisteredMeter("state/snapshot/clean/account/hit", nil) - snapshotCleanAccountMissMeter = metrics.NewRegisteredMeter("state/snapshot/clean/account/miss", nil) - snapshotCleanAccountInexMeter = metrics.NewRegisteredMeter("state/snapshot/clean/account/inex", nil) - snapshotCleanAccountReadMeter = metrics.NewRegisteredMeter("state/snapshot/clean/account/read", nil) - snapshotCleanAccountWriteMeter = metrics.NewRegisteredMeter("state/snapshot/clean/account/write", nil) - - snapshotCleanStorageHitMeter = metrics.NewRegisteredMeter("state/snapshot/clean/storage/hit", nil) - snapshotCleanStorageMissMeter = metrics.NewRegisteredMeter("state/snapshot/clean/storage/miss", nil) - snapshotCleanStorageInexMeter = metrics.NewRegisteredMeter("state/snapshot/clean/storage/inex", nil) - snapshotCleanStorageReadMeter = metrics.NewRegisteredMeter("state/snapshot/clean/storage/read", nil) - snapshotCleanStorageWriteMeter = metrics.NewRegisteredMeter("state/snapshot/clean/storage/write", nil) - - snapshotDirtyAccountHitMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/account/hit", nil) - snapshotDirtyAccountMissMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/account/miss", nil) - snapshotDirtyAccountInexMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/account/inex", nil) - snapshotDirtyAccountReadMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/account/read", nil) - snapshotDirtyAccountWriteMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/account/write", nil) - - snapshotDirtyStorageHitMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/storage/hit", nil) - snapshotDirtyStorageMissMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/storage/miss", nil) - snapshotDirtyStorageInexMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/storage/inex", nil) - snapshotDirtyStorageReadMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/storage/read", nil) - snapshotDirtyStorageWriteMeter = metrics.NewRegisteredMeter("state/snapshot/dirty/storage/write", nil) - - snapshotDirtyAccountHitDepthHist = metrics.NewRegisteredHistogram("state/snapshot/dirty/account/hit/depth", nil, metrics.NewExpDecaySample(1028, 0.015)) - snapshotDirtyStorageHitDepthHist = metrics.NewRegisteredHistogram("state/snapshot/dirty/storage/hit/depth", nil, metrics.NewExpDecaySample(1028, 0.015)) - - snapshotFlushAccountItemMeter = metrics.NewRegisteredMeter("state/snapshot/flush/account/item", nil) - snapshotFlushAccountSizeMeter = metrics.NewRegisteredMeter("state/snapshot/flush/account/size", nil) - snapshotFlushStorageItemMeter = metrics.NewRegisteredMeter("state/snapshot/flush/storage/item", nil) - snapshotFlushStorageSizeMeter = metrics.NewRegisteredMeter("state/snapshot/flush/storage/size", nil) - - snapshotBloomIndexTimer = metrics.NewRegisteredResettingTimer("state/snapshot/bloom/index", nil) - snapshotBloomErrorGauge = metrics.NewRegisteredGaugeFloat64("state/snapshot/bloom/error", nil) - - snapshotBloomAccountTrueHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/account/truehit", nil) - snapshotBloomAccountFalseHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/account/falsehit", nil) - snapshotBloomAccountMissMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/account/miss", nil) - - snapshotBloomStorageTrueHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/storage/truehit", nil) - snapshotBloomStorageFalseHitMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/storage/falsehit", nil) - snapshotBloomStorageMissMeter = metrics.NewRegisteredMeter("state/snapshot/bloom/storage/miss", nil) - - // ErrSnapshotStale is returned from data accessors if the underlying snapshot - // layer had been invalidated due to the chain progressing forward far enough - // to not maintain the layer's original state. - ErrSnapshotStale = errors.New("snapshot stale") - - // ErrNotCoveredYet is returned from data accessors if the underlying snapshot - // is being generated currently and the requested data item is not yet in the - // range of accounts covered. - ErrNotCoveredYet = errors.New("not covered yet") - - // ErrNotConstructed is returned if the callers want to iterate the snapshot - // while the generation is not finished yet. - ErrNotConstructed = errors.New("snapshot is not constructed") - - // errSnapshotCycle is returned if a snapshot is attempted to be inserted - // that forms a cycle in the snapshot tree. - errSnapshotCycle = errors.New("snapshot cycle") -) - -// Snapshot represents the functionality supported by a snapshot storage layer. -type Snapshot interface { - // Root returns the root hash for which this snapshot was made. - Root() common.Hash - - // Account directly retrieves the account associated with a particular hash in - // the snapshot slim data format. - Account(hash common.Hash) (*types.SlimAccount, error) - - // AccountRLP directly retrieves the account RLP associated with a particular - // hash in the snapshot slim data format. - AccountRLP(hash common.Hash) ([]byte, error) - - // Storage directly retrieves the storage data associated with a particular hash, - // within a particular account. - Storage(accountHash, storageHash common.Hash) ([]byte, error) -} - -// snapshot is the internal version of the snapshot data layer that supports some -// additional methods compared to the public API. -type snapshot interface { - Snapshot - - // Parent returns the subsequent layer of a snapshot, or nil if the base was - // reached. - // - // Note, the method is an internal helper to avoid type switching between the - // disk and diff layers. There is no locking involved. - Parent() snapshot - - // Update creates a new layer on top of the existing snapshot diff tree with - // the specified data items. - // - // Note, the maps are retained by the method to avoid copying everything. - Update(blockRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer - - // Journal commits an entire diff hierarchy to disk into a single journal entry. - // This is meant to be used during shutdown to persist the snapshot without - // flattening everything down (bad for reorgs). - Journal(buffer *bytes.Buffer) (common.Hash, error) - - // Stale return whether this layer has become stale (was flattened across) or - // if it's still live. - Stale() bool - - // AccountIterator creates an account iterator over an arbitrary layer. - AccountIterator(seek common.Hash) AccountIterator - - // StorageIterator creates a storage iterator over an arbitrary layer. - StorageIterator(account common.Hash, seek common.Hash) (StorageIterator, bool) -} - -// Config includes the configurations for snapshots. -type Config struct { - CacheSize int // Megabytes permitted to use for read caches - Recovery bool // Indicator that the snapshots is in the recovery mode - NoBuild bool // Indicator that the snapshots generation is disallowed - AsyncBuild bool // The snapshot generation is allowed to be constructed asynchronously -} - -// Tree is an Ethereum state snapshot tree. It consists of one persistent base -// layer backed by a key-value store, on top of which arbitrarily many in-memory -// diff layers are topped. The memory diffs can form a tree with branching, but -// the disk layer is singleton and common to all. If a reorg goes deeper than the -// disk layer, everything needs to be deleted. -// -// The goal of a state snapshot is twofold: to allow direct access to account and -// storage data to avoid expensive multi-level trie lookups; and to allow sorted, -// cheap iteration of the account/storage tries for sync aid. -type Tree struct { - config Config // Snapshots configurations - diskdb ethdb.KeyValueStore // Persistent database to store the snapshot - triedb *triedb.Database // In-memory cache to access the trie through - layers map[common.Hash]snapshot // Collection of all known layers - lock sync.RWMutex - - // Test hooks - onFlatten func() // Hook invoked when the bottom most diff layers are flattened -} - -// New attempts to load an already existing snapshot from a persistent key-value -// store (with a number of memory layers from a journal), ensuring that the head -// of the snapshot matches the expected one. -// -// If the snapshot is missing or the disk layer is broken, the snapshot will be -// reconstructed using both the existing data and the state trie. -// The repair happens on a background thread. -// -// If the memory layers in the journal do not match the disk layer (e.g. there is -// a gap) or the journal is missing, there are two repair cases: -// -// - if the 'recovery' parameter is true, memory diff-layers and the disk-layer -// will all be kept. This case happens when the snapshot is 'ahead' of the -// state trie. -// - otherwise, the entire snapshot is considered invalid and will be recreated on -// a background thread. -func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, root common.Hash) (*Tree, error) { - // Create a new, empty snapshot tree - snap := &Tree{ - config: config, - diskdb: diskdb, - triedb: triedb, - layers: make(map[common.Hash]snapshot), - } - // Attempt to load a previously persisted snapshot and rebuild one if failed - head, disabled, err := loadSnapshot(diskdb, triedb, root, config.CacheSize, config.Recovery, config.NoBuild) - if disabled { - log.Warn("Snapshot maintenance disabled (syncing)") - return snap, nil - } - // Create the building waiter iff the background generation is allowed - if !config.NoBuild && !config.AsyncBuild { - defer snap.waitBuild() - } - if err != nil { - log.Warn("Failed to load snapshot", "err", err) - if !config.NoBuild { - snap.Rebuild(root) - return snap, nil - } - return nil, err // Bail out the error, don't rebuild automatically. - } - // Existing snapshot loaded, seed all the layers - for head != nil { - snap.layers[head.Root()] = head - head = head.Parent() - } - return snap, nil -} - -// waitBuild blocks until the snapshot finishes rebuilding. This method is meant -// to be used by tests to ensure we're testing what we believe we are. -func (t *Tree) waitBuild() { - // Find the rebuild termination channel - var done chan struct{} - - t.lock.RLock() - for _, layer := range t.layers { - if layer, ok := layer.(*diskLayer); ok { - done = layer.genPending - break - } - } - t.lock.RUnlock() - - // Wait until the snapshot is generated - if done != nil { - <-done - } -} - -// Disable interrupts any pending snapshot generator, deletes all the snapshot -// layers in memory and marks snapshots disabled globally. In order to resume -// the snapshot functionality, the caller must invoke Rebuild. -func (t *Tree) Disable() { - // Interrupt any live snapshot layers - t.lock.Lock() - defer t.lock.Unlock() - - for _, layer := range t.layers { - switch layer := layer.(type) { - case *diskLayer: - - layer.lock.RLock() - generating := layer.genMarker != nil - layer.lock.RUnlock() - if !generating { - // Generator is already aborted or finished - break - } - // If the base layer is generating, abort it - if layer.genAbort != nil { - abort := make(chan *generatorStats) - layer.genAbort <- abort - <-abort - } - // Layer should be inactive now, mark it as stale - layer.lock.Lock() - layer.stale = true - layer.lock.Unlock() - - case *diffLayer: - // If the layer is a simple diff, simply mark as stale - layer.lock.Lock() - layer.stale.Store(true) - layer.lock.Unlock() - - default: - panic(fmt.Sprintf("unknown layer type: %T", layer)) - } - } - t.layers = map[common.Hash]snapshot{} - - // Delete all snapshot liveness information from the database - batch := t.diskdb.NewBatch() - - rawdb.WriteSnapshotDisabled(batch) - rawdb.DeleteSnapshotRoot(batch) - rawdb.DeleteSnapshotJournal(batch) - rawdb.DeleteSnapshotGenerator(batch) - rawdb.DeleteSnapshotRecoveryNumber(batch) - // Note, we don't delete the sync progress - - if err := batch.Write(); err != nil { - log.Crit("Failed to disable snapshots", "err", err) - } -} - -// Snapshot retrieves a snapshot belonging to the given block root, or nil if no -// snapshot is maintained for that block. -func (t *Tree) Snapshot(blockRoot common.Hash) Snapshot { - t.lock.RLock() - defer t.lock.RUnlock() - - return t.layers[blockRoot] -} - -// Snapshots returns all visited layers from the topmost layer with specific -// root and traverses downward. The layer amount is limited by the given number. -// If nodisk is set, then disk layer is excluded. -func (t *Tree) Snapshots(root common.Hash, limits int, nodisk bool) []Snapshot { - t.lock.RLock() - defer t.lock.RUnlock() - - if limits == 0 { - return nil - } - layer := t.layers[root] - if layer == nil { - return nil - } - var ret []Snapshot - for { - if _, isdisk := layer.(*diskLayer); isdisk && nodisk { - break - } - ret = append(ret, layer) - limits -= 1 - if limits == 0 { - break - } - parent := layer.Parent() - if parent == nil { - break - } - layer = parent - } - return ret -} - -// Update adds a new snapshot into the tree, if that can be linked to an existing -// old parent. It is disallowed to insert a disk layer (the origin of all). -func (t *Tree) Update(blockRoot common.Hash, parentRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) error { - // Reject noop updates to avoid self-loops in the snapshot tree. This is a - // special case that can only happen for Clique networks where empty blocks - // don't modify the state (0 block subsidy). - // - // Although we could silently ignore this internally, it should be the caller's - // responsibility to avoid even attempting to insert such a snapshot. - if blockRoot == parentRoot { - return errSnapshotCycle - } - // Generate a new snapshot on top of the parent - parent := t.Snapshot(parentRoot) - if parent == nil { - return fmt.Errorf("parent [%#x] snapshot missing", parentRoot) - } - snap := parent.(snapshot).Update(blockRoot, destructs, accounts, storage) - - // Save the new snapshot for later - t.lock.Lock() - defer t.lock.Unlock() - - t.layers[snap.root] = snap - return nil -} - -// Cap traverses downwards the snapshot tree from a head block hash until the -// number of allowed layers are crossed. All layers beyond the permitted number -// are flattened downwards. -// -// Note, the final diff layer count in general will be one more than the amount -// requested. This happens because the bottom-most diff layer is the accumulator -// which may or may not overflow and cascade to disk. Since this last layer's -// survival is only known *after* capping, we need to omit it from the count if -// we want to ensure that *at least* the requested number of diff layers remain. -func (t *Tree) Cap(root common.Hash, layers int) error { - // Retrieve the head snapshot to cap from - snap := t.Snapshot(root) - if snap == nil { - return fmt.Errorf("snapshot [%#x] missing", root) - } - diff, ok := snap.(*diffLayer) - if !ok { - return fmt.Errorf("snapshot [%#x] is disk layer", root) - } - // If the generator is still running, use a more aggressive cap - diff.origin.lock.RLock() - if diff.origin.genMarker != nil && layers > 8 { - layers = 8 - } - diff.origin.lock.RUnlock() - - // Run the internal capping and discard all stale layers - t.lock.Lock() - defer t.lock.Unlock() - - // Flattening the bottom-most diff layer requires special casing since there's - // no child to rewire to the grandparent. In that case we can fake a temporary - // child for the capping and then remove it. - if layers == 0 { - // If full commit was requested, flatten the diffs and merge onto disk - diff.lock.RLock() - base := diffToDisk(diff.flatten().(*diffLayer)) - diff.lock.RUnlock() - - // Replace the entire snapshot tree with the flat base - t.layers = map[common.Hash]snapshot{base.root: base} - return nil - } - persisted := t.cap(diff, layers) - - // Remove any layer that is stale or links into a stale layer - children := make(map[common.Hash][]common.Hash) - for root, snap := range t.layers { - if diff, ok := snap.(*diffLayer); ok { - parent := diff.parent.Root() - children[parent] = append(children[parent], root) - } - } - var remove func(root common.Hash) - remove = func(root common.Hash) { - delete(t.layers, root) - for _, child := range children[root] { - remove(child) - } - delete(children, root) - } - for root, snap := range t.layers { - if snap.Stale() { - remove(root) - } - } - // If the disk layer was modified, regenerate all the cumulative blooms - if persisted != nil { - var rebloom func(root common.Hash) - rebloom = func(root common.Hash) { - if diff, ok := t.layers[root].(*diffLayer); ok { - diff.rebloom(persisted) - } - for _, child := range children[root] { - rebloom(child) - } - } - rebloom(persisted.root) - } - return nil -} - -// cap traverses downwards the diff tree until the number of allowed layers are -// crossed. All diffs beyond the permitted number are flattened downwards. If the -// layer limit is reached, memory cap is also enforced (but not before). -// -// The method returns the new disk layer if diffs were persisted into it. -// -// Note, the final diff layer count in general will be one more than the amount -// requested. This happens because the bottom-most diff layer is the accumulator -// which may or may not overflow and cascade to disk. Since this last layer's -// survival is only known *after* capping, we need to omit it from the count if -// we want to ensure that *at least* the requested number of diff layers remain. -func (t *Tree) cap(diff *diffLayer, layers int) *diskLayer { - // Dive until we run out of layers or reach the persistent database - for i := 0; i < layers-1; i++ { - // If we still have diff layers below, continue down - if parent, ok := diff.parent.(*diffLayer); ok { - diff = parent - } else { - // Diff stack too shallow, return without modifications - return nil - } - } - // We're out of layers, flatten anything below, stopping if it's the disk or if - // the memory limit is not yet exceeded. - switch parent := diff.parent.(type) { - case *diskLayer: - return nil - - case *diffLayer: - // Hold the write lock until the flattened parent is linked correctly. - // Otherwise, the stale layer may be accessed by external reads in the - // meantime. - diff.lock.Lock() - defer diff.lock.Unlock() - - // Flatten the parent into the grandparent. The flattening internally obtains a - // write lock on grandparent. - flattened := parent.flatten().(*diffLayer) - t.layers[flattened.root] = flattened - - // Invoke the hook if it's registered. Ugly hack. - if t.onFlatten != nil { - t.onFlatten() - } - diff.parent = flattened - if flattened.memory < aggregatorMemoryLimit { - // Accumulator layer is smaller than the limit, so we can abort, unless - // there's a snapshot being generated currently. In that case, the trie - // will move from underneath the generator so we **must** merge all the - // partial data down into the snapshot and restart the generation. - if flattened.parent.(*diskLayer).genAbort == nil { - return nil - } - } - default: - panic(fmt.Sprintf("unknown data layer: %T", parent)) - } - // If the bottom-most layer is larger than our memory cap, persist to disk - bottom := diff.parent.(*diffLayer) - - bottom.lock.RLock() - base := diffToDisk(bottom) - bottom.lock.RUnlock() - - t.layers[base.root] = base - diff.parent = base - return base -} - -// diffToDisk merges a bottom-most diff into the persistent disk layer underneath -// it. The method will panic if called onto a non-bottom-most diff layer. -// -// The disk layer persistence should be operated in an atomic way. All updates should -// be discarded if the whole transition if not finished. -func diffToDisk(bottom *diffLayer) *diskLayer { - var ( - base = bottom.parent.(*diskLayer) - batch = base.diskdb.NewBatch() - stats *generatorStats - ) - // If the disk layer is running a snapshot generator, abort it - if base.genAbort != nil { - abort := make(chan *generatorStats) - base.genAbort <- abort - stats = <-abort - } - // Put the deletion in the batch writer, flush all updates in the final step. - rawdb.DeleteSnapshotRoot(batch) - - // Mark the original base as stale as we're going to create a new wrapper - base.lock.Lock() - if base.stale { - panic("parent disk layer is stale") // we've committed into the same base from two children, boo - } - base.stale = true - base.lock.Unlock() - - // Destroy all the destructed accounts from the database - for hash := range bottom.destructSet { - // Skip any account not covered yet by the snapshot - if base.genMarker != nil && bytes.Compare(hash[:], base.genMarker) > 0 { - continue - } - // Remove all storage slots - rawdb.DeleteAccountSnapshot(batch, hash) - base.cache.Set(hash[:], nil) - - it := rawdb.IterateStorageSnapshots(base.diskdb, hash) - for it.Next() { - key := it.Key() - batch.Delete(key) - base.cache.Del(key[1:]) - snapshotFlushStorageItemMeter.Mark(1) - - // Ensure we don't delete too much data blindly (contract can be - // huge). It's ok to flush, the root will go missing in case of a - // crash and we'll detect and regenerate the snapshot. - if batch.ValueSize() > 64*1024*1024 { - if err := batch.Write(); err != nil { - log.Crit("Failed to write storage deletions", "err", err) - } - batch.Reset() - } - } - it.Release() - } - // Push all updated accounts into the database - for hash, data := range bottom.accountData { - // Skip any account not covered yet by the snapshot - if base.genMarker != nil && bytes.Compare(hash[:], base.genMarker) > 0 { - continue - } - // Push the account to disk - rawdb.WriteAccountSnapshot(batch, hash, data) - base.cache.Set(hash[:], data) - snapshotCleanAccountWriteMeter.Mark(int64(len(data))) - - snapshotFlushAccountItemMeter.Mark(1) - snapshotFlushAccountSizeMeter.Mark(int64(len(data))) - - // Ensure we don't write too much data blindly. It's ok to flush, the - // root will go missing in case of a crash and we'll detect and regen - // the snapshot. - if batch.ValueSize() > 64*1024*1024 { - if err := batch.Write(); err != nil { - log.Crit("Failed to write storage deletions", "err", err) - } - batch.Reset() - } - } - // Push all the storage slots into the database - for accountHash, storage := range bottom.storageData { - // Skip any account not covered yet by the snapshot - if base.genMarker != nil && bytes.Compare(accountHash[:], base.genMarker) > 0 { - continue - } - // Generation might be mid-account, track that case too - midAccount := base.genMarker != nil && bytes.Equal(accountHash[:], base.genMarker[:common.HashLength]) - - for storageHash, data := range storage { - // Skip any slot not covered yet by the snapshot - if midAccount && bytes.Compare(storageHash[:], base.genMarker[common.HashLength:]) > 0 { - continue - } - if len(data) > 0 { - rawdb.WriteStorageSnapshot(batch, accountHash, storageHash, data) - base.cache.Set(append(accountHash[:], storageHash[:]...), data) - snapshotCleanStorageWriteMeter.Mark(int64(len(data))) - } else { - rawdb.DeleteStorageSnapshot(batch, accountHash, storageHash) - base.cache.Set(append(accountHash[:], storageHash[:]...), nil) - } - snapshotFlushStorageItemMeter.Mark(1) - snapshotFlushStorageSizeMeter.Mark(int64(len(data))) - } - } - // Update the snapshot block marker and write any remainder data - rawdb.WriteSnapshotRoot(batch, bottom.root) - - // Write out the generator progress marker and report - journalProgress(batch, base.genMarker, stats) - - // Flush all the updates in the single db operation. Ensure the - // disk layer transition is atomic. - if err := batch.Write(); err != nil { - log.Crit("Failed to write leftover snapshot", "err", err) - } - log.Debug("Journalled disk layer", "root", bottom.root, "complete", base.genMarker == nil) - res := &diskLayer{ - root: bottom.root, - cache: base.cache, - diskdb: base.diskdb, - triedb: base.triedb, - genMarker: base.genMarker, - genPending: base.genPending, - } - // If snapshot generation hasn't finished yet, port over all the starts and - // continue where the previous round left off. - // - // Note, the `base.genAbort` comparison is not used normally, it's checked - // to allow the tests to play with the marker without triggering this path. - if base.genMarker != nil && base.genAbort != nil { - res.genMarker = base.genMarker - res.genAbort = make(chan chan *generatorStats) - go res.generate(stats) - } - return res -} - -// Release releases resources -func (t *Tree) Release() { - if dl := t.disklayer(); dl != nil { - dl.Release() - } -} - -// Journal commits an entire diff hierarchy to disk into a single journal entry. -// This is meant to be used during shutdown to persist the snapshot without -// flattening everything down (bad for reorgs). -// -// The method returns the root hash of the base layer that needs to be persisted -// to disk as a trie too to allow continuing any pending generation op. -func (t *Tree) Journal(root common.Hash) (common.Hash, error) { - // Retrieve the head snapshot to journal from var snap snapshot - snap := t.Snapshot(root) - if snap == nil { - return common.Hash{}, fmt.Errorf("snapshot [%#x] missing", root) - } - // Run the journaling - t.lock.Lock() - defer t.lock.Unlock() - - // Firstly write out the metadata of journal - journal := new(bytes.Buffer) - if err := rlp.Encode(journal, journalVersion); err != nil { - return common.Hash{}, err - } - diskroot := t.diskRoot() - if diskroot == (common.Hash{}) { - return common.Hash{}, errors.New("invalid disk root") - } - // Secondly write out the disk layer root, ensure the - // diff journal is continuous with disk. - if err := rlp.Encode(journal, diskroot); err != nil { - return common.Hash{}, err - } - // Finally write out the journal of each layer in reverse order. - base, err := snap.(snapshot).Journal(journal) - if err != nil { - return common.Hash{}, err - } - // Store the journal into the database and return - rawdb.WriteSnapshotJournal(t.diskdb, journal.Bytes()) - return base, nil -} - -// Rebuild wipes all available snapshot data from the persistent database and -// discard all caches and diff layers. Afterwards, it starts a new snapshot -// generator with the given root hash. -func (t *Tree) Rebuild(root common.Hash) { - t.lock.Lock() - defer t.lock.Unlock() - - // Firstly delete any recovery flag in the database. Because now we are - // building a brand new snapshot. Also reenable the snapshot feature. - rawdb.DeleteSnapshotRecoveryNumber(t.diskdb) - rawdb.DeleteSnapshotDisabled(t.diskdb) - - // Iterate over and mark all layers stale - for _, layer := range t.layers { - switch layer := layer.(type) { - case *diskLayer: - // If the base layer is generating, abort it and save - if layer.genAbort != nil { - abort := make(chan *generatorStats) - layer.genAbort <- abort - <-abort - } - // Layer should be inactive now, mark it as stale - layer.lock.Lock() - layer.stale = true - layer.lock.Unlock() - - case *diffLayer: - // If the layer is a simple diff, simply mark as stale - layer.lock.Lock() - layer.stale.Store(true) - layer.lock.Unlock() - - default: - panic(fmt.Sprintf("unknown layer type: %T", layer)) - } - } - // Start generating a new snapshot from scratch on a background thread. The - // generator will run a wiper first if there's not one running right now. - log.Info("Rebuilding state snapshot") - t.layers = map[common.Hash]snapshot{ - root: generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root), - } -} - -// AccountIterator creates a new account iterator for the specified root hash and -// seeks to a starting account hash. -func (t *Tree) AccountIterator(root common.Hash, seek common.Hash) (AccountIterator, error) { - ok, err := t.generating() - if err != nil { - return nil, err - } - if ok { - return nil, ErrNotConstructed - } - return newFastAccountIterator(t, root, seek) -} - -// StorageIterator creates a new storage iterator for the specified root hash and -// account. The iterator will be move to the specific start position. -func (t *Tree) StorageIterator(root common.Hash, account common.Hash, seek common.Hash) (StorageIterator, error) { - ok, err := t.generating() - if err != nil { - return nil, err - } - if ok { - return nil, ErrNotConstructed - } - return newFastStorageIterator(t, root, account, seek) -} - -// Verify iterates the whole state(all the accounts as well as the corresponding storages) -// with the specific root and compares the re-computed hash with the original one. -func (t *Tree) Verify(root common.Hash) error { - acctIt, err := t.AccountIterator(root, common.Hash{}) - if err != nil { - return err - } - defer acctIt.Release() - - got, err := generateTrieRoot(nil, "", acctIt, common.Hash{}, stackTrieGenerate, func(db ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { - storageIt, err := t.StorageIterator(root, accountHash, common.Hash{}) - if err != nil { - return common.Hash{}, err - } - defer storageIt.Release() - - hash, err := generateTrieRoot(nil, "", storageIt, accountHash, stackTrieGenerate, nil, stat, false) - if err != nil { - return common.Hash{}, err - } - return hash, nil - }, newGenerateStats(), true) - - if err != nil { - return err - } - if got != root { - return fmt.Errorf("state root hash mismatch: got %x, want %x", got, root) - } - return nil -} - -// disklayer is an internal helper function to return the disk layer. -// The lock of snapTree is assumed to be held already. -func (t *Tree) disklayer() *diskLayer { - var snap snapshot - for _, s := range t.layers { - snap = s - break - } - if snap == nil { - return nil - } - switch layer := snap.(type) { - case *diskLayer: - return layer - case *diffLayer: - return layer.origin - default: - panic(fmt.Sprintf("%T: undefined layer", snap)) - } -} - -// diskRoot is a internal helper function to return the disk layer root. -// The lock of snapTree is assumed to be held already. -func (t *Tree) diskRoot() common.Hash { - disklayer := t.disklayer() - if disklayer == nil { - return common.Hash{} - } - return disklayer.Root() -} - -// generating is an internal helper function which reports whether the snapshot -// is still under the construction. -func (t *Tree) generating() (bool, error) { - t.lock.Lock() - defer t.lock.Unlock() - - layer := t.disklayer() - if layer == nil { - return false, errors.New("disk layer is missing") - } - layer.lock.RLock() - defer layer.lock.RUnlock() - return layer.genMarker != nil, nil -} - -// DiskRoot is a external helper function to return the disk layer root. -func (t *Tree) DiskRoot() common.Hash { - t.lock.Lock() - defer t.lock.Unlock() - - return t.diskRoot() -} - -// Size returns the memory usage of the diff layers above the disk layer and the -// dirty nodes buffered in the disk layer. Currently, the implementation uses a -// special diff layer (the first) as an aggregator simulating a dirty buffer, so -// the second return will always be 0. However, this will be made consistent with -// the pathdb, which will require a second return. -func (t *Tree) Size() (diffs common.StorageSize, buf common.StorageSize) { - t.lock.RLock() - defer t.lock.RUnlock() - - var size common.StorageSize - for _, layer := range t.layers { - if layer, ok := layer.(*diffLayer); ok { - size += common.StorageSize(layer.memory) - } - } - return size, 0 -} diff --git a/builder/core/state/snapshot/snapshot_test.go b/builder/core/state/snapshot/snapshot_test.go deleted file mode 100644 index a9ab3eaea..000000000 --- a/builder/core/state/snapshot/snapshot_test.go +++ /dev/null @@ -1,491 +0,0 @@ -// 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 snapshot - -import ( - crand "crypto/rand" - "encoding/binary" - "fmt" - "math/rand" - "testing" - "time" - - "github.com/VictoriaMetrics/fastcache" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/uint256" -) - -// randomHash generates a random blob of data and returns it as a hash. -func randomHash() common.Hash { - var hash common.Hash - if n, err := crand.Read(hash[:]); n != common.HashLength || err != nil { - panic(err) - } - return hash -} - -// randomAccount generates a random account and returns it RLP encoded. -func randomAccount() []byte { - a := &types.StateAccount{ - Balance: uint256.NewInt(rand.Uint64()), - Nonce: rand.Uint64(), - Root: randomHash(), - CodeHash: types.EmptyCodeHash[:], - } - data, _ := rlp.EncodeToBytes(a) - return data -} - -// randomAccountSet generates a set of random accounts with the given strings as -// the account address hashes. -func randomAccountSet(hashes ...string) map[common.Hash][]byte { - accounts := make(map[common.Hash][]byte) - for _, hash := range hashes { - accounts[common.HexToHash(hash)] = randomAccount() - } - return accounts -} - -// randomStorageSet generates a set of random slots with the given strings as -// the slot addresses. -func randomStorageSet(accounts []string, hashes [][]string, nilStorage [][]string) map[common.Hash]map[common.Hash][]byte { - storages := make(map[common.Hash]map[common.Hash][]byte) - for index, account := range accounts { - storages[common.HexToHash(account)] = make(map[common.Hash][]byte) - - if index < len(hashes) { - hashes := hashes[index] - for _, hash := range hashes { - storages[common.HexToHash(account)][common.HexToHash(hash)] = randomHash().Bytes() - } - } - if index < len(nilStorage) { - nils := nilStorage[index] - for _, hash := range nils { - storages[common.HexToHash(account)][common.HexToHash(hash)] = nil - } - } - } - return storages -} - -// Tests that if a disk layer becomes stale, no active external references will -// be returned with junk data. This version of the test flattens every diff layer -// to check internal corner case around the bottom-most memory accumulator. -func TestDiskLayerExternalInvalidationFullFlatten(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Retrieve a reference to the base and commit a diff on top - ref := snaps.Snapshot(base.root) - - accounts := map[common.Hash][]byte{ - common.HexToHash("0xa1"): randomAccount(), - } - if err := snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if n := len(snaps.layers); n != 2 { - t.Errorf("pre-cap layer count mismatch: have %d, want %d", n, 2) - } - // Commit the diff layer onto the disk and ensure it's persisted - if err := snaps.Cap(common.HexToHash("0x02"), 0); err != nil { - t.Fatalf("failed to merge diff layer onto disk: %v", err) - } - // Since the base layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { - t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) - } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { - t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) - } - if n := len(snaps.layers); n != 1 { - t.Errorf("post-cap layer count mismatch: have %d, want %d", n, 1) - fmt.Println(snaps.layers) - } -} - -// Tests that if a disk layer becomes stale, no active external references will -// be returned with junk data. This version of the test retains the bottom diff -// layer to check the usual mode of operation where the accumulator is retained. -func TestDiskLayerExternalInvalidationPartialFlatten(t *testing.T) { - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Retrieve a reference to the base and commit two diffs on top - ref := snaps.Snapshot(base.root) - - accounts := map[common.Hash][]byte{ - common.HexToHash("0xa1"): randomAccount(), - } - if err := snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if err := snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if n := len(snaps.layers); n != 3 { - t.Errorf("pre-cap layer count mismatch: have %d, want %d", n, 3) - } - // Commit the diff layer onto the disk and ensure it's persisted - defer func(memcap uint64) { aggregatorMemoryLimit = memcap }(aggregatorMemoryLimit) - aggregatorMemoryLimit = 0 - - if err := snaps.Cap(common.HexToHash("0x03"), 1); err != nil { - t.Fatalf("failed to merge accumulator onto disk: %v", err) - } - // Since the base layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { - t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) - } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { - t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) - } - if n := len(snaps.layers); n != 2 { - t.Errorf("post-cap layer count mismatch: have %d, want %d", n, 2) - fmt.Println(snaps.layers) - } -} - -// Tests that if a diff layer becomes stale, no active external references will -// be returned with junk data. This version of the test retains the bottom diff -// layer to check the usual mode of operation where the accumulator is retained. -func TestDiffLayerExternalInvalidationPartialFlatten(t *testing.T) { - // Un-commenting this triggers the bloom set to be deterministic. The values below - // were used to trigger the flaw described in https://github.com/ethereum/go-ethereum/issues/27254. - // bloomDestructHasherOffset, bloomAccountHasherOffset, bloomStorageHasherOffset = 14, 24, 5 - - // Create an empty base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Commit three diffs on top and retrieve a reference to the bottommost - accounts := map[common.Hash][]byte{ - common.HexToHash("0xa1"): randomAccount(), - } - if err := snaps.Update(common.HexToHash("0x02"), common.HexToHash("0x01"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if err := snaps.Update(common.HexToHash("0x03"), common.HexToHash("0x02"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if err := snaps.Update(common.HexToHash("0x04"), common.HexToHash("0x03"), nil, accounts, nil); err != nil { - t.Fatalf("failed to create a diff layer: %v", err) - } - if n := len(snaps.layers); n != 4 { - t.Errorf("pre-cap layer count mismatch: have %d, want %d", n, 4) - } - ref := snaps.Snapshot(common.HexToHash("0x02")) - - // Doing a Cap operation with many allowed layers should be a no-op - exp := len(snaps.layers) - if err := snaps.Cap(common.HexToHash("0x04"), 2000); err != nil { - t.Fatalf("failed to flatten diff layer into accumulator: %v", err) - } - if got := len(snaps.layers); got != exp { - t.Errorf("layers modified, got %d exp %d", got, exp) - } - // Flatten the diff layer into the bottom accumulator - if err := snaps.Cap(common.HexToHash("0x04"), 1); err != nil { - t.Fatalf("failed to flatten diff layer into accumulator: %v", err) - } - // Since the accumulator diff layer was modified, ensure that data retrievals on the external reference fail - if acc, err := ref.Account(common.HexToHash("0x01")); err != ErrSnapshotStale { - t.Errorf("stale reference returned account: %#x (err: %v)", acc, err) - } - if slot, err := ref.Storage(common.HexToHash("0xa1"), common.HexToHash("0xb1")); err != ErrSnapshotStale { - t.Errorf("stale reference returned storage slot: %#x (err: %v)", slot, err) - } - if n := len(snaps.layers); n != 3 { - t.Errorf("post-cap layer count mismatch: have %d, want %d", n, 3) - fmt.Println(snaps.layers) - } -} - -// TestPostCapBasicDataAccess tests some functionality regarding capping/flattening. -func TestPostCapBasicDataAccess(t *testing.T) { - // setAccount is a helper to construct a random account entry and assign it to - // an account slot in a snapshot - setAccount := func(accKey string) map[common.Hash][]byte { - return map[common.Hash][]byte{ - common.HexToHash(accKey): randomAccount(), - } - } - // Create a starting base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // The lowest difflayer - snaps.Update(common.HexToHash("0xa1"), common.HexToHash("0x01"), nil, setAccount("0xa1"), nil) - snaps.Update(common.HexToHash("0xa2"), common.HexToHash("0xa1"), nil, setAccount("0xa2"), nil) - snaps.Update(common.HexToHash("0xb2"), common.HexToHash("0xa1"), nil, setAccount("0xb2"), nil) - - snaps.Update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil) - snaps.Update(common.HexToHash("0xb3"), common.HexToHash("0xb2"), nil, setAccount("0xb3"), nil) - - // checkExist verifies if an account exists in a snapshot - checkExist := func(layer *diffLayer, key string) error { - if data, _ := layer.Account(common.HexToHash(key)); data == nil { - return fmt.Errorf("expected %x to exist, got nil", common.HexToHash(key)) - } - return nil - } - // shouldErr checks that an account access errors as expected - shouldErr := func(layer *diffLayer, key string) error { - if data, err := layer.Account(common.HexToHash(key)); err == nil { - return fmt.Errorf("expected error, got data %x", data) - } - return nil - } - // check basics - snap := snaps.Snapshot(common.HexToHash("0xb3")).(*diffLayer) - - if err := checkExist(snap, "0xa1"); err != nil { - t.Error(err) - } - if err := checkExist(snap, "0xb2"); err != nil { - t.Error(err) - } - if err := checkExist(snap, "0xb3"); err != nil { - t.Error(err) - } - // Cap to a bad root should fail - if err := snaps.Cap(common.HexToHash("0x1337"), 0); err == nil { - t.Errorf("expected error, got none") - } - // Now, merge the a-chain - snaps.Cap(common.HexToHash("0xa3"), 0) - - // At this point, a2 got merged into a1. Thus, a1 is now modified, and as a1 is - // the parent of b2, b2 should no longer be able to iterate into parent. - - // These should still be accessible - if err := checkExist(snap, "0xb2"); err != nil { - t.Error(err) - } - if err := checkExist(snap, "0xb3"); err != nil { - t.Error(err) - } - // But these would need iteration into the modified parent - if err := shouldErr(snap, "0xa1"); err != nil { - t.Error(err) - } - if err := shouldErr(snap, "0xa2"); err != nil { - t.Error(err) - } - if err := shouldErr(snap, "0xa3"); err != nil { - t.Error(err) - } - // Now, merge it again, just for fun. It should now error, since a3 - // is a disk layer - if err := snaps.Cap(common.HexToHash("0xa3"), 0); err == nil { - t.Error("expected error capping the disk layer, got none") - } -} - -// TestSnaphots tests the functionality for retrieving the snapshot -// with given head root and the desired depth. -func TestSnaphots(t *testing.T) { - // setAccount is a helper to construct a random account entry and assign it to - // an account slot in a snapshot - setAccount := func(accKey string) map[common.Hash][]byte { - return map[common.Hash][]byte{ - common.HexToHash(accKey): randomAccount(), - } - } - makeRoot := func(height uint64) common.Hash { - var buffer [8]byte - binary.BigEndian.PutUint64(buffer[:], height) - return common.BytesToHash(buffer[:]) - } - // Create a starting base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: makeRoot(1), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // Construct the snapshots with 129 layers, flattening whatever's above that - var ( - last = common.HexToHash("0x01") - head common.Hash - ) - for i := 0; i < 129; i++ { - head = makeRoot(uint64(i + 2)) - snaps.Update(head, last, nil, setAccount(fmt.Sprintf("%d", i+2)), nil) - last = head - snaps.Cap(head, 128) // 130 layers (128 diffs + 1 accumulator + 1 disk) - } - var cases = []struct { - headRoot common.Hash - limit int - nodisk bool - expected int - expectBottom common.Hash - }{ - {head, 0, false, 0, common.Hash{}}, - {head, 64, false, 64, makeRoot(129 + 2 - 64)}, - {head, 128, false, 128, makeRoot(3)}, // Normal diff layers, no accumulator - {head, 129, true, 129, makeRoot(2)}, // All diff layers, including accumulator - {head, 130, false, 130, makeRoot(1)}, // All diff layers + disk layer - } - for i, c := range cases { - layers := snaps.Snapshots(c.headRoot, c.limit, c.nodisk) - if len(layers) != c.expected { - t.Errorf("non-overflow test %d: returned snapshot layers are mismatched, want %v, got %v", i, c.expected, len(layers)) - } - if len(layers) == 0 { - continue - } - bottommost := layers[len(layers)-1] - if bottommost.Root() != c.expectBottom { - t.Errorf("non-overflow test %d: snapshot mismatch, want %v, get %v", i, c.expectBottom, bottommost.Root()) - } - } - // Above we've tested the normal capping, which leaves the accumulator live. - // Test that if the bottommost accumulator diff layer overflows the allowed - // memory limit, the snapshot tree gets capped to one less layer. - // Commit the diff layer onto the disk and ensure it's persisted - defer func(memcap uint64) { aggregatorMemoryLimit = memcap }(aggregatorMemoryLimit) - aggregatorMemoryLimit = 0 - - snaps.Cap(head, 128) // 129 (128 diffs + 1 overflown accumulator + 1 disk) - - cases = []struct { - headRoot common.Hash - limit int - nodisk bool - expected int - expectBottom common.Hash - }{ - {head, 0, false, 0, common.Hash{}}, - {head, 64, false, 64, makeRoot(129 + 2 - 64)}, - {head, 128, false, 128, makeRoot(3)}, // All diff layers, accumulator was flattened - {head, 129, true, 128, makeRoot(3)}, // All diff layers, accumulator was flattened - {head, 130, false, 129, makeRoot(2)}, // All diff layers + disk layer - } - for i, c := range cases { - layers := snaps.Snapshots(c.headRoot, c.limit, c.nodisk) - if len(layers) != c.expected { - t.Errorf("overflow test %d: returned snapshot layers are mismatched, want %v, got %v", i, c.expected, len(layers)) - } - if len(layers) == 0 { - continue - } - bottommost := layers[len(layers)-1] - if bottommost.Root() != c.expectBottom { - t.Errorf("overflow test %d: snapshot mismatch, want %v, get %v", i, c.expectBottom, bottommost.Root()) - } - } -} - -// TestReadStateDuringFlattening tests the scenario that, during the -// bottom diff layers are merging which tags these as stale, the read -// happens via a pre-created top snapshot layer which tries to access -// the state in these stale layers. Ensure this read can retrieve the -// right state back(block until the flattening is finished) instead of -// an unexpected error(snapshot layer is stale). -func TestReadStateDuringFlattening(t *testing.T) { - // setAccount is a helper to construct a random account entry and assign it to - // an account slot in a snapshot - setAccount := func(accKey string) map[common.Hash][]byte { - return map[common.Hash][]byte{ - common.HexToHash(accKey): randomAccount(), - } - } - // Create a starting base layer and a snapshot tree out of it - base := &diskLayer{ - diskdb: rawdb.NewMemoryDatabase(), - root: common.HexToHash("0x01"), - cache: fastcache.New(1024 * 500), - } - snaps := &Tree{ - layers: map[common.Hash]snapshot{ - base.root: base, - }, - } - // 4 layers in total, 3 diff layers and 1 disk layers - snaps.Update(common.HexToHash("0xa1"), common.HexToHash("0x01"), nil, setAccount("0xa1"), nil) - snaps.Update(common.HexToHash("0xa2"), common.HexToHash("0xa1"), nil, setAccount("0xa2"), nil) - snaps.Update(common.HexToHash("0xa3"), common.HexToHash("0xa2"), nil, setAccount("0xa3"), nil) - - // Obtain the topmost snapshot handler for state accessing - snap := snaps.Snapshot(common.HexToHash("0xa3")) - - // Register the testing hook to access the state after flattening - var result = make(chan *types.SlimAccount) - snaps.onFlatten = func() { - // Spin up a thread to read the account from the pre-created - // snapshot handler. It's expected to be blocked. - go func() { - account, _ := snap.Account(common.HexToHash("0xa1")) - result <- account - }() - select { - case res := <-result: - t.Fatalf("Unexpected return %v", res) - case <-time.NewTimer(time.Millisecond * 300).C: - } - } - // Cap the snap tree, which will mark the bottom-most layer as stale. - snaps.Cap(common.HexToHash("0xa3"), 1) - select { - case account := <-result: - if account == nil { - t.Fatal("Failed to retrieve account") - } - case <-time.NewTimer(time.Millisecond * 300).C: - t.Fatal("Unexpected blocker") - } -} diff --git a/builder/core/state/snapshot/utils.go b/builder/core/state/snapshot/utils.go deleted file mode 100644 index 62f073d2e..000000000 --- a/builder/core/state/snapshot/utils.go +++ /dev/null @@ -1,152 +0,0 @@ -// 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 snapshot - -import ( - "bytes" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -// CheckDanglingStorage iterates the snap storage data, and verifies that all -// storage also has corresponding account data. -func CheckDanglingStorage(chaindb ethdb.KeyValueStore) error { - if err := checkDanglingDiskStorage(chaindb); err != nil { - log.Error("Database check error", "err", err) - } - return checkDanglingMemStorage(chaindb) -} - -// checkDanglingDiskStorage checks if there is any 'dangling' storage data in the -// disk-backed snapshot layer. -func checkDanglingDiskStorage(chaindb ethdb.KeyValueStore) error { - var ( - lastReport = time.Now() - start = time.Now() - lastKey []byte - it = rawdb.NewKeyLengthIterator(chaindb.NewIterator(rawdb.SnapshotStoragePrefix, nil), 1+2*common.HashLength) - ) - log.Info("Checking dangling snapshot disk storage") - - defer it.Release() - for it.Next() { - k := it.Key() - accKey := k[1:33] - if bytes.Equal(accKey, lastKey) { - // No need to look up for every slot - continue - } - lastKey = common.CopyBytes(accKey) - if time.Since(lastReport) > time.Second*8 { - log.Info("Iterating snap storage", "at", fmt.Sprintf("%#x", accKey), "elapsed", common.PrettyDuration(time.Since(start))) - lastReport = time.Now() - } - if data := rawdb.ReadAccountSnapshot(chaindb, common.BytesToHash(accKey)); len(data) == 0 { - log.Warn("Dangling storage - missing account", "account", fmt.Sprintf("%#x", accKey), "storagekey", fmt.Sprintf("%#x", k)) - return fmt.Errorf("dangling snapshot storage account %#x", accKey) - } - } - log.Info("Verified the snapshot disk storage", "time", common.PrettyDuration(time.Since(start)), "err", it.Error()) - return nil -} - -// checkDanglingMemStorage checks if there is any 'dangling' storage in the journalled -// snapshot difflayers. -func checkDanglingMemStorage(db ethdb.KeyValueStore) error { - start := time.Now() - log.Info("Checking dangling journalled storage") - err := iterateJournal(db, func(pRoot, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) error { - for accHash := range storage { - if _, ok := accounts[accHash]; !ok { - log.Error("Dangling storage - missing account", "account", fmt.Sprintf("%#x", accHash), "root", root) - } - } - return nil - }) - if err != nil { - log.Info("Failed to resolve snapshot journal", "err", err) - return err - } - log.Info("Verified the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start))) - return nil -} - -// CheckJournalAccount shows information about an account, from the disk layer and -// up through the diff layers. -func CheckJournalAccount(db ethdb.KeyValueStore, hash common.Hash) error { - // Look up the disk layer first - baseRoot := rawdb.ReadSnapshotRoot(db) - fmt.Printf("Disklayer: Root: %x\n", baseRoot) - if data := rawdb.ReadAccountSnapshot(db, hash); data != nil { - account, err := types.FullAccount(data) - if err != nil { - panic(err) - } - fmt.Printf("\taccount.nonce: %d\n", account.Nonce) - fmt.Printf("\taccount.balance: %x\n", account.Balance) - fmt.Printf("\taccount.root: %x\n", account.Root) - fmt.Printf("\taccount.codehash: %x\n", account.CodeHash) - } - // Check storage - { - it := rawdb.NewKeyLengthIterator(db.NewIterator(append(rawdb.SnapshotStoragePrefix, hash.Bytes()...), nil), 1+2*common.HashLength) - fmt.Printf("\tStorage:\n") - for it.Next() { - slot := it.Key()[33:] - fmt.Printf("\t\t%x: %x\n", slot, it.Value()) - } - it.Release() - } - var depth = 0 - - return iterateJournal(db, func(pRoot, root common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) error { - _, a := accounts[hash] - _, b := destructs[hash] - _, c := storage[hash] - depth++ - if !a && !b && !c { - return nil - } - fmt.Printf("Disklayer+%d: Root: %x, parent %x\n", depth, root, pRoot) - if data, ok := accounts[hash]; ok { - account, err := types.FullAccount(data) - if err != nil { - panic(err) - } - fmt.Printf("\taccount.nonce: %d\n", account.Nonce) - fmt.Printf("\taccount.balance: %x\n", account.Balance) - fmt.Printf("\taccount.root: %x\n", account.Root) - fmt.Printf("\taccount.codehash: %x\n", account.CodeHash) - } - if _, ok := destructs[hash]; ok { - fmt.Printf("\t Destructed!") - } - if data, ok := storage[hash]; ok { - fmt.Printf("\tStorage\n") - for k, v := range data { - fmt.Printf("\t\t%x: %x\n", k, v) - } - } - return nil - }) -} diff --git a/builder/core/state/state_object.go b/builder/core/state/state_object.go deleted file mode 100644 index 3503e54e8..000000000 --- a/builder/core/state/state_object.go +++ /dev/null @@ -1,549 +0,0 @@ -// 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 state - -import ( - "bytes" - "fmt" - "io" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/holiman/uint256" -) - -type Code []byte - -func (c Code) String() string { - return string(c) //strings.Join(Disassemble(c), " ") -} - -type Storage map[common.Hash]common.Hash - -func (s Storage) String() (str string) { - for key, value := range s { - str += fmt.Sprintf("%X : %X\n", key, value) - } - return -} - -func (s Storage) Copy() Storage { - cpy := make(Storage, len(s)) - for key, value := range s { - cpy[key] = value - } - return cpy -} - -// stateObject represents an Ethereum account which is being modified. -// -// The usage pattern is as follows: -// - First you need to obtain a state object. -// - Account values as well as storages can be accessed and modified through the object. -// - Finally, call commit to return the changes of storage trie and update account data. -type stateObject struct { - db *StateDB - address common.Address // address of ethereum account - addrHash common.Hash // hash of ethereum address of the account - origin *types.StateAccount // Account original data without any change applied, nil means it was not existent - data types.StateAccount // Account data with all mutations applied in the scope of block - - // Write caches. - trie Trie // storage trie, which becomes non-nil on first access - code Code // contract bytecode, which gets set when code is loaded - - originStorage Storage // Storage cache of original entries to dedup rewrites - pendingStorage Storage // Storage entries that need to be flushed to disk, at the end of an entire block - dirtyStorage Storage // Storage entries that have been modified in the current transaction execution, reset for every transaction - - // Cache flags. - dirtyCode bool // true if the code was updated - - // Flag whether the account was marked as self-destructed. The self-destructed account - // is still accessible in the scope of same transaction. - selfDestructed bool - - // Flag whether the account was marked as deleted. A self-destructed account - // or an account that is considered as empty will be marked as deleted at - // the end of transaction and no longer accessible anymore. - deleted bool - - // Flag whether the object was created in the current transaction - created bool -} - -// empty returns whether the account is considered empty. -func (s *stateObject) empty() bool { - return s.data.Nonce == 0 && s.data.Balance.IsZero() && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) -} - -// newObject creates a state object. -func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject { - var ( - origin = acct - created = acct == nil // true if the account was not existent - ) - if acct == nil { - acct = types.NewEmptyStateAccount() - } - return &stateObject{ - db: db, - address: address, - addrHash: crypto.Keccak256Hash(address[:]), - origin: origin, - data: *acct, - originStorage: make(Storage), - pendingStorage: make(Storage), - dirtyStorage: make(Storage), - created: created, - } -} - -// EncodeRLP implements rlp.Encoder. -func (s *stateObject) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, &s.data) -} - -func (s *stateObject) markSelfdestructed() { - s.selfDestructed = true -} - -func (s *stateObject) touch() { - s.db.journal.append(touchChange{ - account: &s.address, - }) - if s.address == ripemd { - // Explicitly put it in the dirty-cache, which is otherwise generated from - // flattened journals. - s.db.journal.dirty(s.address) - } -} - -// getTrie returns the associated storage trie. The trie will be opened -// if it's not loaded previously. An error will be returned if trie can't -// be loaded. -func (s *stateObject) getTrie() (Trie, error) { - if s.trie == nil { - // Try fetching from prefetcher first - if s.data.Root != types.EmptyRootHash && s.db.prefetcher != nil { - // When the miner is creating the pending state, there is no prefetcher - s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root) - } - if s.trie == nil { - tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root, s.db.trie) - if err != nil { - return nil, err - } - s.trie = tr - } - } - return s.trie, nil -} - -// GetState retrieves a value from the account storage trie. -func (s *stateObject) GetState(key common.Hash) common.Hash { - // If we have a dirty value for this state entry, return it - value, dirty := s.dirtyStorage[key] - if dirty { - return value - } - // Otherwise return the entry's original value - return s.GetCommittedState(key) -} - -// GetCommittedState retrieves a value from the committed account storage trie. -func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { - // If we have a pending write or clean cached, return that - if value, pending := s.pendingStorage[key]; pending { - return value - } - if value, cached := s.originStorage[key]; cached { - return value - } - // If the object was destructed in *this* block (and potentially resurrected), - // the storage has been cleared out, and we should *not* consult the previous - // database about any storage values. The only possible alternatives are: - // 1) resurrect happened, and new slot values were set -- those should - // have been handles via pendingStorage above. - // 2) we don't have new values, and can deliver empty response back - if _, destructed := s.db.stateObjectsDestruct[s.address]; destructed { - return common.Hash{} - } - // If no live objects are available, attempt to use snapshots - var ( - enc []byte - err error - value common.Hash - ) - if s.db.snap != nil { - start := time.Now() - enc, err = s.db.snap.Storage(s.addrHash, crypto.Keccak256Hash(key.Bytes())) - if metrics.EnabledExpensive { - s.db.SnapshotStorageReads += time.Since(start) - } - if len(enc) > 0 { - _, content, _, err := rlp.Split(enc) - if err != nil { - s.db.setError(err) - } - value.SetBytes(content) - } - } - // If the snapshot is unavailable or reading from it fails, load from the database. - if s.db.snap == nil || err != nil { - start := time.Now() - tr, err := s.getTrie() - if err != nil { - s.db.setError(err) - return common.Hash{} - } - val, err := tr.GetStorage(s.address, key.Bytes()) - if metrics.EnabledExpensive { - s.db.StorageReads += time.Since(start) - } - if err != nil { - s.db.setError(err) - return common.Hash{} - } - value.SetBytes(val) - } - s.originStorage[key] = value - return value -} - -// SetState updates a value in account storage. -func (s *stateObject) SetState(key, value common.Hash) { - // If the new value is the same as old, don't set - prev := s.GetState(key) - if prev == value { - return - } - // New value is different, update and journal the change - s.db.journal.append(storageChange{ - account: &s.address, - key: key, - prevalue: prev, - }) - s.setState(key, value) -} - -func (s *stateObject) setState(key, value common.Hash) { - s.dirtyStorage[key] = value -} - -// finalise moves all dirty storage slots into the pending area to be hashed or -// committed later. It is invoked at the end of every transaction. -func (s *stateObject) finalise(prefetch bool) { - slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) - for key, value := range s.dirtyStorage { - prev, ok := s.pendingStorage[key] - s.db.multiTxSnapshotStack.UpdatePendingStorage(s.address, key, prev, ok) - - s.pendingStorage[key] = value - if value != s.originStorage[key] { - slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure - } - } - if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash { - s.db.prefetcher.prefetch(s.addrHash, s.data.Root, s.address, slotsToPrefetch) - } - if len(s.dirtyStorage) > 0 { - s.dirtyStorage = make(Storage) - } -} - -// updateTrie is responsible for persisting cached storage changes into the -// object's storage trie. In case the storage trie is not yet loaded, this -// function will load the trie automatically. If any issues arise during the -// loading or updating of the trie, an error will be returned. Furthermore, -// this function will return the mutated storage trie, or nil if there is no -// storage change at all. -func (s *stateObject) updateTrie() (Trie, error) { - // Make sure all dirty slots are finalized into the pending storage area - s.finalise(false) - - // Short circuit if nothing changed, don't bother with hashing anything - if len(s.pendingStorage) == 0 { - return s.trie, nil - } - // Track the amount of time wasted on updating the storage trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) - } - // The snapshot storage map for the object - var ( - storage map[common.Hash][]byte - origin map[common.Hash][]byte - ) - tr, err := s.getTrie() - if err != nil { - s.db.setError(err) - return nil, err - } - // Insert all the pending storage updates into the trie - usedStorage := make([][]byte, 0, len(s.pendingStorage)) - for key, value := range s.pendingStorage { - // Skip noop changes, persist actual changes - if value == s.originStorage[key] { - continue - } - prev := s.originStorage[key] - s.originStorage[key] = value - - var encoded []byte // rlp-encoded value to be used by the snapshot - if (value == common.Hash{}) { - if err := tr.DeleteStorage(s.address, key[:]); err != nil { - s.db.setError(err) - return nil, err - } - s.db.StorageDeleted += 1 - } else { - // Encoding []byte cannot fail, ok to ignore the error. - trimmed := common.TrimLeftZeroes(value[:]) - encoded, _ = rlp.EncodeToBytes(trimmed) - if err := tr.UpdateStorage(s.address, key[:], trimmed); err != nil { - s.db.setError(err) - return nil, err - } - s.db.StorageUpdated += 1 - } - // Cache the mutated storage slots until commit - if storage == nil { - if storage = s.db.storages[s.addrHash]; storage == nil { - storage = make(map[common.Hash][]byte) - s.db.storages[s.addrHash] = storage - } - } - khash := crypto.HashData(s.db.hasher, key[:]) - storage[khash] = encoded // encoded will be nil if it's deleted - - // Cache the original value of mutated storage slots - if origin == nil { - if origin = s.db.storagesOrigin[s.address]; origin == nil { - origin = make(map[common.Hash][]byte) - s.db.storagesOrigin[s.address] = origin - } - } - // Track the original value of slot only if it's mutated first time - if _, ok := origin[khash]; !ok { - if prev == (common.Hash{}) { - origin[khash] = nil // nil if it was not present previously - } else { - // Encoding []byte cannot fail, ok to ignore the error. - b, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(prev[:])) - origin[khash] = b - } - } - // Cache the items for preloading - usedStorage = append(usedStorage, common.CopyBytes(key[:])) // Copy needed for closure - } - if s.db.prefetcher != nil { - s.db.prefetcher.used(s.addrHash, s.data.Root, usedStorage) - } - s.pendingStorage = make(Storage) // reset pending map - return tr, nil -} - -// updateRoot flushes all cached storage mutations to trie, recalculating the -// new storage trie root. -func (s *stateObject) updateRoot() { - // Flush cached storage mutations into trie, short circuit if any error - // is occurred or there is not change in the trie. - tr, err := s.updateTrie() - if err != nil || tr == nil { - return - } - // Track the amount of time wasted on hashing the storage trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) - } - s.data.Root = tr.Hash() -} - -// commit obtains a set of dirty storage trie nodes and updates the account data. -// The returned set can be nil if nothing to commit. This function assumes all -// storage mutations have already been flushed into trie by updateRoot. -func (s *stateObject) commit() (*trienode.NodeSet, error) { - // Short circuit if trie is not even loaded, don't bother with committing anything - if s.trie == nil { - s.origin = s.data.Copy() - return nil, nil - } - // Track the amount of time wasted on committing the storage trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) - } - // The trie is currently in an open state and could potentially contain - // cached mutations. Call commit to acquire a set of nodes that have been - // modified, the set can be nil if nothing to commit. - root, nodes, err := s.trie.Commit(false) - if err != nil { - return nil, err - } - s.data.Root = root - - // Update original account data after commit - s.origin = s.data.Copy() - return nodes, nil -} - -// AddBalance adds amount to s's balance. -// It is used to add funds to the destination account of a transfer. -func (s *stateObject) AddBalance(amount *uint256.Int) { - // EIP161: We must check emptiness for the objects such that the account - // clearing (0,0,0 objects) can take effect. - if amount.IsZero() { - if s.empty() { - s.touch() - } - return - } - s.SetBalance(new(uint256.Int).Add(s.Balance(), amount)) -} - -// SubBalance removes amount from s's balance. -// It is used to remove funds from the origin account of a transfer. -func (s *stateObject) SubBalance(amount *uint256.Int) { - if amount.IsZero() { - return - } - s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount)) -} - -func (s *stateObject) SetBalance(amount *uint256.Int) { - s.db.journal.append(balanceChange{ - account: &s.address, - prev: new(uint256.Int).Set(s.data.Balance), - }) - s.setBalance(amount) -} - -func (s *stateObject) setBalance(amount *uint256.Int) { - s.data.Balance = amount -} - -func (s *stateObject) deepCopy(db *StateDB) *stateObject { - obj := &stateObject{ - db: db, - address: s.address, - addrHash: s.addrHash, - origin: s.origin, - data: s.data, - } - if s.trie != nil { - obj.trie = db.db.CopyTrie(s.trie) - } - obj.code = s.code - obj.dirtyStorage = s.dirtyStorage.Copy() - obj.originStorage = s.originStorage.Copy() - obj.pendingStorage = s.pendingStorage.Copy() - obj.selfDestructed = s.selfDestructed - obj.dirtyCode = s.dirtyCode - obj.deleted = s.deleted - return obj -} - -// -// Attribute accessors -// - -// Address returns the address of the contract/account -func (s *stateObject) Address() common.Address { - return s.address -} - -// Code returns the contract code associated with this object, if any. -func (s *stateObject) Code() []byte { - if s.code != nil { - return s.code - } - if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { - return nil - } - code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.CodeHash())) - if err != nil { - s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) - } - s.code = code - return code -} - -// CodeSize returns the size of the contract code associated with this object, -// or zero if none. This method is an almost mirror of Code, but uses a cache -// inside the database to avoid loading codes seen recently. -func (s *stateObject) CodeSize() int { - if s.code != nil { - return len(s.code) - } - if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) { - return 0 - } - size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.CodeHash())) - if err != nil { - s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err)) - } - return size -} - -func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { - prevcode := s.Code() - s.db.journal.append(codeChange{ - account: &s.address, - prevhash: s.CodeHash(), - prevcode: prevcode, - }) - s.setCode(codeHash, code) -} - -func (s *stateObject) setCode(codeHash common.Hash, code []byte) { - s.code = code - s.data.CodeHash = codeHash[:] - s.dirtyCode = true -} - -func (s *stateObject) SetNonce(nonce uint64) { - s.db.journal.append(nonceChange{ - account: &s.address, - prev: s.data.Nonce, - }) - s.setNonce(nonce) -} - -func (s *stateObject) setNonce(nonce uint64) { - s.data.Nonce = nonce -} - -func (s *stateObject) CodeHash() []byte { - return s.data.CodeHash -} - -func (s *stateObject) Balance() *uint256.Int { - return s.data.Balance -} - -func (s *stateObject) Nonce() uint64 { - return s.data.Nonce -} - -func (s *stateObject) Root() common.Hash { - return s.data.Root -} diff --git a/builder/core/state/state_object_test.go b/builder/core/state/state_object_test.go deleted file mode 100644 index 42fd77802..000000000 --- a/builder/core/state/state_object_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// 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 state - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func BenchmarkCutOriginal(b *testing.B) { - value := common.HexToHash("0x01") - for i := 0; i < b.N; i++ { - bytes.TrimLeft(value[:], "\x00") - } -} - -func BenchmarkCutsetterFn(b *testing.B) { - value := common.HexToHash("0x01") - cutSetFn := func(r rune) bool { return r == 0 } - for i := 0; i < b.N; i++ { - bytes.TrimLeftFunc(value[:], cutSetFn) - } -} - -func BenchmarkCutCustomTrim(b *testing.B) { - value := common.HexToHash("0x01") - for i := 0; i < b.N; i++ { - common.TrimLeftZeroes(value[:]) - } -} diff --git a/builder/core/state/state_test.go b/builder/core/state/state_test.go deleted file mode 100644 index 9be610f96..000000000 --- a/builder/core/state/state_test.go +++ /dev/null @@ -1,298 +0,0 @@ -// 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 state - -import ( - "bytes" - "encoding/json" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/triedb" - "github.com/holiman/uint256" -) - -type stateEnv struct { - db ethdb.Database - state *StateDB -} - -func newStateEnv() *stateEnv { - db := rawdb.NewMemoryDatabase() - sdb, _ := New(types.EmptyRootHash, NewDatabase(db), nil) - return &stateEnv{db: db, state: sdb} -} - -func TestDump(t *testing.T) { - db := rawdb.NewMemoryDatabase() - tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true}) - sdb, _ := New(types.EmptyRootHash, tdb, nil) - s := &stateEnv{db: db, state: sdb} - - // generate a few entries - obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) - obj1.AddBalance(uint256.NewInt(22)) - obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) - obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) - obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) - obj3.SetBalance(uint256.NewInt(44)) - - // write some of them to the trie - s.state.updateStateObject(obj1) - s.state.updateStateObject(obj2) - root, _ := s.state.Commit(0, false) - - // check that DumpToCollector contains the state objects that are in trie - s.state, _ = New(root, tdb, nil) - got := string(s.state.Dump(nil)) - want := `{ - "root": "71edff0130dd2385947095001c73d9e28d862fc286fca2b922ca6f6f3cddfdd2", - "accounts": { - "0x0000000000000000000000000000000000000001": { - "balance": "22", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "address": "0x0000000000000000000000000000000000000001", - "key": "0x1468288056310c82aa4c01a7e12a10f8111a0560e72b700555479031b86c357d" - }, - "0x0000000000000000000000000000000000000002": { - "balance": "44", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "address": "0x0000000000000000000000000000000000000002", - "key": "0xd52688a8f926c816ca1e079067caba944f158e764817b83fc43594370ca9cf62" - }, - "0x0000000000000000000000000000000000000102": { - "balance": "0", - "nonce": 0, - "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "codeHash": "0x87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3", - "code": "0x03030303030303", - "address": "0x0000000000000000000000000000000000000102", - "key": "0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1" - } - } -}` - if got != want { - t.Errorf("DumpToCollector mismatch:\ngot: %s\nwant: %s\n", got, want) - } -} - -func TestIterativeDump(t *testing.T) { - db := rawdb.NewMemoryDatabase() - tdb := NewDatabaseWithConfig(db, &triedb.Config{Preimages: true}) - sdb, _ := New(types.EmptyRootHash, tdb, nil) - s := &stateEnv{db: db, state: sdb} - - // generate a few entries - obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) - obj1.AddBalance(uint256.NewInt(22)) - obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) - obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) - obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) - obj3.SetBalance(uint256.NewInt(44)) - obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00})) - obj4.AddBalance(uint256.NewInt(1337)) - - // write some of them to the trie - s.state.updateStateObject(obj1) - s.state.updateStateObject(obj2) - root, _ := s.state.Commit(0, false) - s.state, _ = New(root, tdb, nil) - - b := &bytes.Buffer{} - s.state.IterativeDump(nil, json.NewEncoder(b)) - // check that DumpToCollector contains the state objects that are in trie - got := b.String() - want := `{"root":"0xd5710ea8166b7b04bc2bfb129d7db12931cee82f75ca8e2d075b4884322bf3de"} -{"balance":"22","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000001","key":"0x1468288056310c82aa4c01a7e12a10f8111a0560e72b700555479031b86c357d"} -{"balance":"1337","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000000","key":"0x5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a"} -{"balance":"0","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0x87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3","code":"0x03030303030303","address":"0x0000000000000000000000000000000000000102","key":"0xa17eacbc25cda025e81db9c5c62868822c73ce097cee2a63e33a2e41268358a1"} -{"balance":"44","nonce":0,"root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","address":"0x0000000000000000000000000000000000000002","key":"0xd52688a8f926c816ca1e079067caba944f158e764817b83fc43594370ca9cf62"} -` - if got != want { - t.Errorf("DumpToCollector mismatch:\ngot: %s\nwant: %s\n", got, want) - } -} - -func TestNull(t *testing.T) { - s := newStateEnv() - address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") - s.state.CreateAccount(address) - //value := common.FromHex("0x823140710bf13990e4500136726d8b55") - var value common.Hash - - s.state.SetState(address, common.Hash{}, value) - s.state.Commit(0, false) - - if value := s.state.GetState(address, common.Hash{}); value != (common.Hash{}) { - t.Errorf("expected empty current value, got %x", value) - } - if value := s.state.GetCommittedState(address, common.Hash{}); value != (common.Hash{}) { - t.Errorf("expected empty committed value, got %x", value) - } -} - -func TestSnapshot(t *testing.T) { - stateobjaddr := common.BytesToAddress([]byte("aa")) - var storageaddr common.Hash - data1 := common.BytesToHash([]byte{42}) - data2 := common.BytesToHash([]byte{43}) - s := newStateEnv() - - // snapshot the genesis state - genesis := s.state.Snapshot() - - // set initial state object value - s.state.SetState(stateobjaddr, storageaddr, data1) - snapshot := s.state.Snapshot() - - // set a new state object value, revert it and ensure correct content - s.state.SetState(stateobjaddr, storageaddr, data2) - s.state.RevertToSnapshot(snapshot) - - if v := s.state.GetState(stateobjaddr, storageaddr); v != data1 { - t.Errorf("wrong storage value %v, want %v", v, data1) - } - if v := s.state.GetCommittedState(stateobjaddr, storageaddr); v != (common.Hash{}) { - t.Errorf("wrong committed storage value %v, want %v", v, common.Hash{}) - } - - // revert up to the genesis state and ensure correct content - s.state.RevertToSnapshot(genesis) - if v := s.state.GetState(stateobjaddr, storageaddr); v != (common.Hash{}) { - t.Errorf("wrong storage value %v, want %v", v, common.Hash{}) - } - if v := s.state.GetCommittedState(stateobjaddr, storageaddr); v != (common.Hash{}) { - t.Errorf("wrong committed storage value %v, want %v", v, common.Hash{}) - } -} - -func TestSnapshotEmpty(t *testing.T) { - s := newStateEnv() - s.state.RevertToSnapshot(s.state.Snapshot()) -} - -func TestSnapshot2(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - stateobjaddr0 := common.BytesToAddress([]byte("so0")) - stateobjaddr1 := common.BytesToAddress([]byte("so1")) - var storageaddr common.Hash - - data0 := common.BytesToHash([]byte{17}) - data1 := common.BytesToHash([]byte{18}) - - state.SetState(stateobjaddr0, storageaddr, data0) - state.SetState(stateobjaddr1, storageaddr, data1) - - // db, trie are already non-empty values - so0 := state.getStateObject(stateobjaddr0) - so0.SetBalance(uint256.NewInt(42)) - so0.SetNonce(43) - so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) - so0.selfDestructed = false - so0.deleted = false - state.setStateObject(so0) - - root, _ := state.Commit(0, false) - state, _ = New(root, state.db, state.snaps) - - // and one with deleted == true - so1 := state.getStateObject(stateobjaddr1) - so1.SetBalance(uint256.NewInt(52)) - so1.SetNonce(53) - so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'}) - so1.selfDestructed = true - so1.deleted = true - state.setStateObject(so1) - - so1 = state.getStateObject(stateobjaddr1) - if so1 != nil { - t.Fatalf("deleted object not nil when getting") - } - - snapshot := state.Snapshot() - state.RevertToSnapshot(snapshot) - - so0Restored := state.getStateObject(stateobjaddr0) - // Update lazily-loaded values before comparing. - so0Restored.GetState(storageaddr) - so0Restored.Code() - // non-deleted is equal (restored) - compareStateObjects(so0Restored, so0, t) - - // deleted should be nil, both before and after restore of state copy - so1Restored := state.getStateObject(stateobjaddr1) - if so1Restored != nil { - t.Fatalf("deleted object not nil after restoring snapshot: %+v", so1Restored) - } -} - -func compareStateObjects(so0, so1 *stateObject, t *testing.T) { - if so0.Address() != so1.Address() { - t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address) - } - if so0.Balance().Cmp(so1.Balance()) != 0 { - t.Fatalf("Balance mismatch: have %v, want %v", so0.Balance(), so1.Balance()) - } - if so0.Nonce() != so1.Nonce() { - t.Fatalf("Nonce mismatch: have %v, want %v", so0.Nonce(), so1.Nonce()) - } - if so0.data.Root != so1.data.Root { - t.Errorf("Root mismatch: have %x, want %x", so0.data.Root[:], so1.data.Root[:]) - } - if !bytes.Equal(so0.CodeHash(), so1.CodeHash()) { - t.Fatalf("CodeHash mismatch: have %v, want %v", so0.CodeHash(), so1.CodeHash()) - } - if !bytes.Equal(so0.code, so1.code) { - t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code) - } - - if len(so1.dirtyStorage) != len(so0.dirtyStorage) { - t.Errorf("Dirty storage size mismatch: have %d, want %d", len(so1.dirtyStorage), len(so0.dirtyStorage)) - } - for k, v := range so1.dirtyStorage { - if so0.dirtyStorage[k] != v { - t.Errorf("Dirty storage key %x mismatch: have %v, want %v", k, so0.dirtyStorage[k], v) - } - } - for k, v := range so0.dirtyStorage { - if so1.dirtyStorage[k] != v { - t.Errorf("Dirty storage key %x mismatch: have %v, want none.", k, v) - } - } - if len(so1.originStorage) != len(so0.originStorage) { - t.Errorf("Origin storage size mismatch: have %d, want %d", len(so1.originStorage), len(so0.originStorage)) - } - for k, v := range so1.originStorage { - if so0.originStorage[k] != v { - t.Errorf("Origin storage key %x mismatch: have %v, want %v", k, so0.originStorage[k], v) - } - } - for k, v := range so0.originStorage { - if so1.originStorage[k] != v { - t.Errorf("Origin storage key %x mismatch: have %v, want none.", k, v) - } - } -} diff --git a/builder/core/state/statedb.go b/builder/core/state/statedb.go deleted file mode 100644 index 432eb33a4..000000000 --- a/builder/core/state/statedb.go +++ /dev/null @@ -1,1460 +0,0 @@ -// 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 state provides a caching layer atop the Ethereum state trie. -package state - -import ( - "fmt" - "sort" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/trie/triestate" - "github.com/holiman/uint256" -) - -const ( - // storageDeleteLimit denotes the highest permissible memory allocation - // employed for contract storage deletion. - storageDeleteLimit = 512 * 1024 * 1024 -) - -type revision struct { - id int - journalIndex int -} - -// StateDB structs within the ethereum protocol are used to store anything -// within the merkle trie. StateDBs take care of caching and storing -// nested states. It's the general query interface to retrieve: -// -// * Contracts -// * Accounts -// -// Once the state is committed, tries cached in stateDB (including account -// trie, storage tries) will no longer be functional. A new state instance -// must be created with new root and updated database for accessing post- -// commit states. -type StateDB struct { - db Database - prefetcher *triePrefetcher - trie Trie - hasher crypto.KeccakState - snaps *snapshot.Tree // Nil if snapshot is not available - snap snapshot.Snapshot // Nil if snapshot is not available - - // originalRoot is the pre-state root, before any changes were made. - // It will be updated when the Commit is called. - originalRoot common.Hash - - // These maps hold the state changes (including the corresponding - // original value) that occurred in this **block**. - accounts map[common.Hash][]byte // The mutated accounts in 'slim RLP' encoding - storages map[common.Hash]map[common.Hash][]byte // The mutated slots in prefix-zero trimmed rlp format - accountsOrigin map[common.Address][]byte // The original value of mutated accounts in 'slim RLP' encoding - storagesOrigin map[common.Address]map[common.Hash][]byte // The original value of mutated slots in prefix-zero trimmed rlp format - - // This map holds 'live' objects, which will get modified while processing - // a state transition. - stateObjects map[common.Address]*stateObject - stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie - stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution - stateObjectsDestruct map[common.Address]*types.StateAccount // State objects destructed in the block along with its previous value - - // DB error. - // State objects are used by the consensus core and VM which are - // unable to deal with database-level errors. Any error that occurs - // during a database read is memoized here and will eventually be - // returned by StateDB.Commit. Notably, this error is also shared - // by all cached state objects in case the database failure occurs - // when accessing state of accounts. - dbErr error - - // The refund counter, also used by state transitioning. - refund uint64 - - // The tx context and all occurred logs in the scope of transaction. - thash common.Hash - txIndex int - logs map[common.Hash][]*types.Log - logSize uint - - // Preimages occurred seen by VM in the scope of block. - preimages map[common.Hash][]byte - - // Per-transaction access list - accessList *accessList - - // Transient storage - transientStorage transientStorage - - // Journal of state modifications. This is the backbone of - // Snapshot and RevertToSnapshot. - journal *journal - validRevisions []revision - nextRevisionId int - - // Multi-Transaction Snapshot Stack - multiTxSnapshotStack *MultiTxSnapshotStack - - // Measurements gathered during execution for debugging purposes - AccountReads time.Duration - AccountHashes time.Duration - AccountUpdates time.Duration - AccountCommits time.Duration - StorageReads time.Duration - StorageHashes time.Duration - StorageUpdates time.Duration - StorageCommits time.Duration - SnapshotAccountReads time.Duration - SnapshotStorageReads time.Duration - SnapshotCommits time.Duration - TrieDBCommits time.Duration - - AccountUpdated int - StorageUpdated int - AccountDeleted int - StorageDeleted int - - // Testing hooks - onCommit func(states *triestate.Set) // Hook invoked when commit is performed -} - -// New creates a new state from a given trie. -func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) { - tr, err := db.OpenTrie(root) - if err != nil { - return nil, err - } - sdb := &StateDB{ - db: db, - trie: tr, - originalRoot: root, - snaps: snaps, - accounts: make(map[common.Hash][]byte), - storages: make(map[common.Hash]map[common.Hash][]byte), - accountsOrigin: make(map[common.Address][]byte), - storagesOrigin: make(map[common.Address]map[common.Hash][]byte), - stateObjects: make(map[common.Address]*stateObject), - stateObjectsPending: make(map[common.Address]struct{}), - stateObjectsDirty: make(map[common.Address]struct{}), - stateObjectsDestruct: make(map[common.Address]*types.StateAccount), - logs: make(map[common.Hash][]*types.Log), - preimages: make(map[common.Hash][]byte), - journal: newJournal(), - accessList: newAccessList(), - transientStorage: newTransientStorage(), - hasher: crypto.NewKeccakState(), - } - - sdb.multiTxSnapshotStack = NewMultiTxSnapshotStack(sdb) - if sdb.snaps != nil { - sdb.snap = sdb.snaps.Snapshot(root) - } - return sdb, nil -} - -// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the -// state trie concurrently while the state is mutated so that when we reach the -// commit phase, most of the needed data is already hot. -func (s *StateDB) StartPrefetcher(namespace string) { - if s.prefetcher != nil { - s.prefetcher.close() - s.prefetcher = nil - } - if s.snap != nil { - s.prefetcher = newTriePrefetcher(s.db, s.originalRoot, namespace) - } -} - -// StopPrefetcher terminates a running prefetcher and reports any leftover stats -// from the gathered metrics. -func (s *StateDB) StopPrefetcher() { - if s.prefetcher != nil { - s.prefetcher.close() - s.prefetcher = nil - } -} - -// setError remembers the first non-nil error it is called with. -func (s *StateDB) setError(err error) { - if s.dbErr == nil { - s.dbErr = err - } -} - -// Error returns the memorized database failure occurred earlier. -func (s *StateDB) Error() error { - return s.dbErr -} - -func (s *StateDB) AddLog(log *types.Log) { - s.journal.append(addLogChange{txhash: s.thash}) - - log.TxHash = s.thash - log.TxIndex = uint(s.txIndex) - log.Index = s.logSize - s.logs[s.thash] = append(s.logs[s.thash], log) - s.logSize++ -} - -// GetLogs returns the logs matching the specified transaction hash, and annotates -// them with the given blockNumber and blockHash. -func (s *StateDB) GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log { - logs := s.logs[hash] - for _, l := range logs { - l.BlockNumber = blockNumber - l.BlockHash = blockHash - } - return logs -} - -func (s *StateDB) Logs() []*types.Log { - var logs []*types.Log - for _, lgs := range s.logs { - logs = append(logs, lgs...) - } - return logs -} - -// AddPreimage records a SHA3 preimage seen by the VM. -func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) { - if _, ok := s.preimages[hash]; !ok { - s.journal.append(addPreimageChange{hash: hash}) - pi := make([]byte, len(preimage)) - copy(pi, preimage) - s.preimages[hash] = pi - } -} - -// Preimages returns a list of SHA3 preimages that have been submitted. -func (s *StateDB) Preimages() map[common.Hash][]byte { - return s.preimages -} - -// AddRefund adds gas to the refund counter -func (s *StateDB) AddRefund(gas uint64) { - s.journal.append(refundChange{prev: s.refund}) - s.refund += gas -} - -// SubRefund removes gas from the refund counter. -// This method will panic if the refund counter goes below zero -func (s *StateDB) SubRefund(gas uint64) { - s.journal.append(refundChange{prev: s.refund}) - if gas > s.refund { - panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund)) - } - s.refund -= gas -} - -// Exist reports whether the given account address exists in the state. -// Notably this also returns true for self-destructed accounts. -func (s *StateDB) Exist(addr common.Address) bool { - return s.getStateObject(addr) != nil -} - -// Empty returns whether the state object is either non-existent -// or empty according to the EIP161 specification (balance = nonce = code = 0) -func (s *StateDB) Empty(addr common.Address) bool { - so := s.getStateObject(addr) - return so == nil || so.empty() -} - -// GetBalance retrieves the balance from the given address or 0 if object not found -func (s *StateDB) GetBalance(addr common.Address) *uint256.Int { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Balance() - } - return common.U2560 -} - -// GetNonce retrieves the nonce from the given address or 0 if object not found -func (s *StateDB) GetNonce(addr common.Address) uint64 { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Nonce() - } - - return 0 -} - -// GetStorageRoot retrieves the storage root from the given address or empty -// if object not found. -func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Root() - } - return common.Hash{} -} - -// TxIndex returns the current transaction index set by Prepare. -func (s *StateDB) TxIndex() int { - return s.txIndex -} - -func (s *StateDB) GetCode(addr common.Address) []byte { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Code() - } - return nil -} - -func (s *StateDB) GetCodeSize(addr common.Address) int { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.CodeSize() - } - return 0 -} - -func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return common.BytesToHash(stateObject.CodeHash()) - } - return common.Hash{} -} - -// GetState retrieves a value from the given account's storage trie. -func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.GetState(hash) - } - return common.Hash{} -} - -// GetCommittedState retrieves a value from the given account's committed storage trie. -func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.GetCommittedState(hash) - } - return common.Hash{} -} - -// Database retrieves the low level database supporting the lower level trie ops. -func (s *StateDB) Database() Database { - return s.db -} - -func (s *StateDB) HasSelfDestructed(addr common.Address) bool { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.selfDestructed - } - return false -} - -/* - * SETTERS - */ - -// AddBalance adds amount to the account associated with addr. -func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.AddBalance(amount) - } -} - -// SubBalance subtracts amount from the account associated with addr. -func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SubBalance(amount) - } -} - -func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetBalance(amount) - } -} - -func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetNonce(nonce) - } -} - -func (s *StateDB) SetCode(addr common.Address, code []byte) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetCode(crypto.Keccak256Hash(code), code) - } -} - -func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { - stateObject := s.getOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetState(key, value) - } -} - -// SetStorage replaces the entire storage for the specified account with given -// storage. This function should only be used for debugging and the mutations -// must be discarded afterwards. -func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) { - // SetStorage needs to wipe existing storage. We achieve this by pretending - // that the account self-destructed earlier in this block, by flagging - // it in stateObjectsDestruct. The effect of doing so is that storage lookups - // will not hit disk, since it is assumed that the disk-data is belonging - // to a previous incarnation of the object. - // - // TODO(rjl493456442) this function should only be supported by 'unwritable' - // state and all mutations made should all be discarded afterwards. - if _, ok := s.stateObjectsDestruct[addr]; !ok { - s.stateObjectsDestruct[addr] = nil - } - stateObject := s.getOrNewStateObject(addr) - for k, v := range storage { - stateObject.SetState(k, v) - } -} - -// SelfDestruct marks the given account as selfdestructed. -// This clears the account balance. -// -// The account's state object is still available until the state is committed, -// getStateObject will return a non-nil account after SelfDestruct. -func (s *StateDB) SelfDestruct(addr common.Address) { - stateObject := s.getStateObject(addr) - if stateObject == nil { - return - } - s.journal.append(selfDestructChange{ - account: &addr, - prev: stateObject.selfDestructed, - prevbalance: new(uint256.Int).Set(stateObject.Balance()), - }) - stateObject.markSelfdestructed() - stateObject.data.Balance = new(uint256.Int) -} - -func (s *StateDB) Selfdestruct6780(addr common.Address) { - stateObject := s.getStateObject(addr) - if stateObject == nil { - return - } - - if stateObject.created { - s.SelfDestruct(addr) - } -} - -// SetTransientState sets transient storage for a given account. It -// adds the change to the journal so that it can be rolled back -// to its previous value if there is a revert. -func (s *StateDB) SetTransientState(addr common.Address, key, value common.Hash) { - prev := s.GetTransientState(addr, key) - if prev == value { - return - } - s.journal.append(transientStorageChange{ - account: &addr, - key: key, - prevalue: prev, - }) - s.setTransientState(addr, key, value) -} - -// setTransientState is a lower level setter for transient storage. It -// is called during a revert to prevent modifications to the journal. -func (s *StateDB) setTransientState(addr common.Address, key, value common.Hash) { - s.transientStorage.Set(addr, key, value) -} - -// GetTransientState gets transient storage for a given account. -func (s *StateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { - return s.transientStorage.Get(addr, key) -} - -// -// Setting, updating & deleting state object methods. -// - -// updateStateObject writes the given object to the trie. -func (s *StateDB) updateStateObject(obj *stateObject) { - // Track the amount of time wasted on updating the account from the trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) - } - // Encode the account and update the account trie - addr := obj.Address() - if err := s.trie.UpdateAccount(addr, &obj.data); err != nil { - s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err)) - } - if obj.dirtyCode { - s.trie.UpdateContractCode(obj.Address(), common.BytesToHash(obj.CodeHash()), obj.code) - } - // Cache the data until commit. Note, this update mechanism is not symmetric - // to the deletion, because whereas it is enough to track account updates - // at commit time, deletions need tracking at transaction boundary level to - // ensure we capture state clearing. - s.accounts[obj.addrHash] = types.SlimAccountRLP(obj.data) - - // Track the original value of mutated account, nil means it was not present. - // Skip if it has been tracked (because updateStateObject may be called - // multiple times in a block). - if _, ok := s.accountsOrigin[obj.address]; !ok { - if obj.origin == nil { - s.accountsOrigin[obj.address] = nil - } else { - s.accountsOrigin[obj.address] = types.SlimAccountRLP(*obj.origin) - } - } -} - -// deleteStateObject removes the given object from the state trie. -func (s *StateDB) deleteStateObject(obj *stateObject) { - // Track the amount of time wasted on deleting the account from the trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) - } - // Delete the account from the trie - addr := obj.Address() - if err := s.trie.DeleteAccount(addr); err != nil { - s.setError(fmt.Errorf("deleteStateObject (%x) error: %v", addr[:], err)) - } -} - -// getStateObject retrieves a state object given by the address, returning nil if -// the object is not found or was deleted in this execution context. If you need -// to differentiate between non-existent/just-deleted, use getDeletedStateObject. -func (s *StateDB) getStateObject(addr common.Address) *stateObject { - if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { - return obj - } - return nil -} - -// getDeletedStateObject is similar to getStateObject, but instead of returning -// nil for a deleted state object, it returns the actual object with the deleted -// flag set. This is needed by the state journal to revert to the correct s- -// destructed object instead of wiping all knowledge about the state object. -func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { - // Prefer live objects if any is available - if obj := s.stateObjects[addr]; obj != nil { - return obj - } - // If no live objects are available, attempt to use snapshots - var data *types.StateAccount - if s.snap != nil { - start := time.Now() - acc, err := s.snap.Account(crypto.HashData(s.hasher, addr.Bytes())) - if metrics.EnabledExpensive { - s.SnapshotAccountReads += time.Since(start) - } - if err == nil { - if acc == nil { - return nil - } - data = &types.StateAccount{ - Nonce: acc.Nonce, - Balance: acc.Balance, - CodeHash: acc.CodeHash, - Root: common.BytesToHash(acc.Root), - } - if len(data.CodeHash) == 0 { - data.CodeHash = types.EmptyCodeHash.Bytes() - } - if data.Root == (common.Hash{}) { - data.Root = types.EmptyRootHash - } - } - } - // If snapshot unavailable or reading from it failed, load from the database - if data == nil { - start := time.Now() - var err error - data, err = s.trie.GetAccount(addr) - if metrics.EnabledExpensive { - s.AccountReads += time.Since(start) - } - if err != nil { - s.setError(fmt.Errorf("getDeleteStateObject (%x) error: %w", addr.Bytes(), err)) - return nil - } - if data == nil { - return nil - } - } - // Insert into the live set - obj := newObject(s, addr, data) - s.setStateObject(obj) - return obj -} - -func (s *StateDB) setStateObject(object *stateObject) { - s.stateObjects[object.Address()] = object -} - -// getOrNewStateObject retrieves a state object or create a new state object if nil. -func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject { - stateObject := s.getStateObject(addr) - if stateObject == nil { - stateObject, _ = s.createObject(addr) - } - return stateObject -} - -// createObject creates a new state object. If there is an existing account with -// the given address, it is overwritten and returned as the second return value. -func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { - prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! - newobj = newObject(s, addr, nil) - if prev == nil { - s.journal.append(createObjectChange{account: &addr}) - } else { - // The original account should be marked as destructed and all cached - // account and storage data should be cleared as well. Note, it must - // be done here, otherwise the destruction event of "original account" - // will be lost. - _, prevdestruct := s.stateObjectsDestruct[prev.address] - if !prevdestruct { - s.stateObjectsDestruct[prev.address] = prev.origin - } - // There may be some cached account/storage data already since IntermediateRoot - // will be called for each transaction before byzantium fork which will always - // cache the latest account/storage data. - prevAccount, ok := s.accountsOrigin[prev.address] - s.journal.append(resetObjectChange{ - account: &addr, - prev: prev, - prevdestruct: prevdestruct, - prevAccount: s.accounts[prev.addrHash], - prevStorage: s.storages[prev.addrHash], - prevAccountOriginExist: ok, - prevAccountOrigin: prevAccount, - prevStorageOrigin: s.storagesOrigin[prev.address], - }) - delete(s.accounts, prev.addrHash) - delete(s.storages, prev.addrHash) - delete(s.accountsOrigin, prev.address) - delete(s.storagesOrigin, prev.address) - } - s.setStateObject(newobj) - if prev != nil && !prev.deleted { - return newobj, prev - } - return newobj, nil -} - -// CreateAccount explicitly creates a state object. If a state object with the address -// already exists the balance is carried over to the new account. -// -// CreateAccount is called during the EVM CREATE operation. The situation might arise that -// a contract does the following: -// -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) -// -// Carrying over the balance ensures that Ether doesn't disappear. -func (s *StateDB) CreateAccount(addr common.Address) { - newObj, prev := s.createObject(addr) - if prev != nil { - newObj.setBalance(prev.data.Balance) - } -} - -// Copy creates a deep, independent copy of the state. -// Snapshots of the copied state cannot be applied to the copy. -func (s *StateDB) Copy() *StateDB { - // Copy all the basic fields, initialize the memory ones - state := &StateDB{ - db: s.db, - trie: s.db.CopyTrie(s.trie), - originalRoot: s.originalRoot, - accounts: make(map[common.Hash][]byte), - storages: make(map[common.Hash]map[common.Hash][]byte), - accountsOrigin: make(map[common.Address][]byte), - storagesOrigin: make(map[common.Address]map[common.Hash][]byte), - stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), - stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), - stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), - stateObjectsDestruct: make(map[common.Address]*types.StateAccount, len(s.stateObjectsDestruct)), - refund: s.refund, - logs: make(map[common.Hash][]*types.Log, len(s.logs)), - logSize: s.logSize, - preimages: make(map[common.Hash][]byte, len(s.preimages)), - journal: newJournal(), - hasher: crypto.NewKeccakState(), - - // In order for the block producer to be able to use and make additions - // to the snapshot tree, we need to copy that as well. Otherwise, any - // block mined by ourselves will cause gaps in the tree, and force the - // miner to operate trie-backed only. - snaps: s.snaps, - snap: s.snap, - } - // Initialize copy of multi-transaction snapshot stack for the copied state - state.multiTxSnapshotStack = s.multiTxSnapshotStack.Copy(state) - // Copy the dirty states, logs, and preimages - for addr := range s.journal.dirties { - // As documented [here](https://github.com/ethereum/go-ethereum/pull/16485#issuecomment-380438527), - // and in the Finalise-method, there is a case where an object is in the journal but not - // in the stateObjects: OOG after touch on ripeMD prior to Byzantium. Thus, we need to check for - // nil - if object, exist := s.stateObjects[addr]; exist { - // Even though the original object is dirty, we are not copying the journal, - // so we need to make sure that any side-effect the journal would have caused - // during a commit (or similar op) is already applied to the copy. - state.stateObjects[addr] = object.deepCopy(state) - - state.stateObjectsDirty[addr] = struct{}{} // Mark the copy dirty to force internal (code/state) commits - state.stateObjectsPending[addr] = struct{}{} // Mark the copy pending to force external (account) commits - } - } - // Above, we don't copy the actual journal. This means that if the copy - // is copied, the loop above will be a no-op, since the copy's journal - // is empty. Thus, here we iterate over stateObjects, to enable copies - // of copies. - for addr := range s.stateObjectsPending { - if _, exist := state.stateObjects[addr]; !exist { - state.stateObjects[addr] = s.stateObjects[addr].deepCopy(state) - } - state.stateObjectsPending[addr] = struct{}{} - } - for addr := range s.stateObjectsDirty { - if _, exist := state.stateObjects[addr]; !exist { - state.stateObjects[addr] = s.stateObjects[addr].deepCopy(state) - } - state.stateObjectsDirty[addr] = struct{}{} - } - // Deep copy the destruction markers. - for addr, value := range s.stateObjectsDestruct { - state.stateObjectsDestruct[addr] = value - } - // Deep copy the state changes made in the scope of block - // along with their original values. - state.accounts = copySet(s.accounts) - state.storages = copy2DSet(s.storages) - state.accountsOrigin = copySet(state.accountsOrigin) - state.storagesOrigin = copy2DSet(state.storagesOrigin) - - // Deep copy the logs occurred in the scope of block - for hash, logs := range s.logs { - cpy := make([]*types.Log, len(logs)) - for i, l := range logs { - cpy[i] = new(types.Log) - *cpy[i] = *l - } - state.logs[hash] = cpy - } - // Deep copy the preimages occurred in the scope of block - for hash, preimage := range s.preimages { - state.preimages[hash] = preimage - } - // Do we need to copy the access list and transient storage? - // In practice: No. At the start of a transaction, these two lists are empty. - // In practice, we only ever copy state _between_ transactions/blocks, never - // in the middle of a transaction. However, it doesn't cost us much to copy - // empty lists, so we do it anyway to not blow up if we ever decide copy them - // in the middle of a transaction. - state.accessList = s.accessList.Copy() - state.transientStorage = s.transientStorage.Copy() - - // If there's a prefetcher running, make an inactive copy of it that can - // only access data but does not actively preload (since the user will not - // know that they need to explicitly terminate an active copy). - if s.prefetcher != nil { - state.prefetcher = s.prefetcher.copy() - } - - if metrics.EnabledBuilder { - stateCopyMeter.Mark(1) - } - - return state -} - -// Snapshot returns an identifier for the current revision of the state. -func (s *StateDB) Snapshot() int { - id := s.nextRevisionId - s.nextRevisionId++ - s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()}) - - if metrics.EnabledBuilder { - stateSnapshotMeter.Mark(1) - } - - return id -} - -// RevertToSnapshot reverts all state changes made since the given revision. -func (s *StateDB) RevertToSnapshot(revid int) { - // Find the snapshot in the stack of valid snapshots. - idx := sort.Search(len(s.validRevisions), func(i int) bool { - return s.validRevisions[i].id >= revid - }) - if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid { - panic(fmt.Errorf("revision id %v cannot be reverted", revid)) - } - snapshot := s.validRevisions[idx].journalIndex - - // Replay the journal to undo changes and remove invalidated snapshots - s.journal.revert(s, snapshot) - s.validRevisions = s.validRevisions[:idx] -} - -// GetRefund returns the current value of the refund counter. -func (s *StateDB) GetRefund() uint64 { - return s.refund -} - -// Finalise finalises the state by removing the destructed objects and clears -// the journal as well as the refunds. Finalise, however, will not push any updates -// into the tries just yet. Only IntermediateRoot or Commit will do that. -func (s *StateDB) Finalise(deleteEmptyObjects bool) { - s.multiTxSnapshotStack.UpdateFromJournal(s.journal) - - addressesToPrefetch := make([][]byte, 0, len(s.journal.dirties)) - for addr := range s.journal.dirties { - obj, exist := s.stateObjects[addr] - if !exist { - // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 - // That tx goes out of gas, and although the notion of 'touched' does not exist there, the - // touch-event will still be recorded in the journal. Since ripeMD is a special snowflake, - // it will persist in the journal even though the journal is reverted. In this special circumstance, - // it may exist in `s.journal.dirties` but not in `s.stateObjects`. - // Thus, we can safely ignore it here - continue - } - if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) { - s.multiTxSnapshotStack.UpdateObjectDeleted(obj.address, obj.deleted) - - obj.deleted = true - - // We need to maintain account deletions explicitly (will remain - // set indefinitely). Note only the first occurred self-destruct - // event is tracked. - if _, ok := s.stateObjectsDestruct[obj.address]; !ok { - s.stateObjectsDestruct[obj.address] = obj.origin - } - // Note, we can't do this only at the end of a block because multiple - // transactions within the same block might self destruct and then - // resurrect an account; but the snapshotter needs both events. - delete(s.accounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a resurrect) - delete(s.storages, obj.addrHash) // Clear out any previously updated storage data (may be recreated via a resurrect) - delete(s.accountsOrigin, obj.address) // Clear out any previously updated account data (may be recreated via a resurrect) - delete(s.storagesOrigin, obj.address) // Clear out any previously updated storage data (may be recreated via a resurrect) - } else { - obj.finalise(true) // Prefetch slots in the background - } - - if s.multiTxSnapshotStack.Size() > 0 { - _, wasPending := s.stateObjectsPending[addr] - _, wasDirty := s.stateObjectsDirty[addr] - s.multiTxSnapshotStack.UpdatePendingStatus(addr, wasPending, wasDirty) - } - obj.created = false - s.stateObjectsPending[addr] = struct{}{} - s.stateObjectsDirty[addr] = struct{}{} - - // At this point, also ship the address off to the precacher. The precacher - // will start loading tries, and when the change is eventually committed, - // the commit-phase will be a lot faster - addressesToPrefetch = append(addressesToPrefetch, common.CopyBytes(addr[:])) // Copy needed for closure - } - if s.prefetcher != nil && len(addressesToPrefetch) > 0 { - s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch) - } - // Invalidate journal because reverting across transactions is not allowed. - s.clearJournalAndRefund() -} - -// IntermediateRoot computes the current root hash of the state trie. -// It is called in between transactions to get the root hash that -// goes into transaction receipts. -func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { - // Finalise all the dirty storage states and write them into the tries - s.Finalise(deleteEmptyObjects) - - // Intermediate root writes updates to the trie, which will cause - // in memory multi-transaction snapshot to be incompatible with the committed state, so we invalidate. - s.multiTxSnapshotStack.Invalidate() - - // If there was a trie prefetcher operating, it gets aborted and irrevocably - // modified after we start retrieving tries. Remove it from the statedb after - // this round of use. - // - // This is weird pre-byzantium since the first tx runs with a prefetcher and - // the remainder without, but pre-byzantium even the initial prefetcher is - // useless, so no sleep lost. - prefetcher := s.prefetcher - if s.prefetcher != nil { - defer func() { - s.prefetcher.close() - s.prefetcher = nil - }() - } - // Although naively it makes sense to retrieve the account trie and then do - // the contract storage and account updates sequentially, that short circuits - // the account prefetcher. Instead, let's process all the storage updates - // first, giving the account prefetches just a few more milliseconds of time - // to pull useful data from disk. - for addr := range s.stateObjectsPending { - if obj := s.stateObjects[addr]; !obj.deleted { - obj.updateRoot() - } - } - // Now we're about to start to write changes to the trie. The trie is so far - // _untouched_. We can check with the prefetcher, if it can give us a trie - // which has the same root, but also has some content loaded into it. - if prefetcher != nil { - if trie := prefetcher.trie(common.Hash{}, s.originalRoot); trie != nil { - s.trie = trie - } - } - usedAddrs := make([][]byte, 0, len(s.stateObjectsPending)) - for addr := range s.stateObjectsPending { - if obj := s.stateObjects[addr]; obj.deleted { - s.deleteStateObject(obj) - s.AccountDeleted += 1 - } else { - s.updateStateObject(obj) - s.AccountUpdated += 1 - } - usedAddrs = append(usedAddrs, common.CopyBytes(addr[:])) // Copy needed for closure - } - if prefetcher != nil { - prefetcher.used(common.Hash{}, s.originalRoot, usedAddrs) - } - if len(s.stateObjectsPending) > 0 { - s.stateObjectsPending = make(map[common.Address]struct{}) - } - // Track the amount of time wasted on hashing the account trie - if metrics.EnabledExpensive { - defer func(start time.Time) { s.AccountHashes += time.Since(start) }(time.Now()) - } - return s.trie.Hash() -} - -// SetTxContext sets the current transaction hash and index which are -// used when the EVM emits new state logs. It should be invoked before -// transaction execution. -func (s *StateDB) SetTxContext(thash common.Hash, ti int) { - s.thash = thash - s.txIndex = ti -} - -func (s *StateDB) clearJournalAndRefund() { - if len(s.journal.entries) > 0 { - s.journal = newJournal() - s.refund = 0 - } - s.validRevisions = s.validRevisions[:0] // Snapshots can be created without journal entries -} - -// fastDeleteStorage is the function that efficiently deletes the storage trie -// of a specific account. It leverages the associated state snapshot for fast -// storage iteration and constructs trie node deletion markers by creating -// stack trie with iterated slots. -func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) { - iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{}) - if err != nil { - return false, 0, nil, nil, err - } - defer iter.Release() - - var ( - size common.StorageSize - nodes = trienode.NewNodeSet(addrHash) - slots = make(map[common.Hash][]byte) - ) - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - nodes.AddNode(path, trienode.NewDeleted()) - size += common.StorageSize(len(path)) - }) - stack := trie.NewStackTrie(options) - for iter.Next() { - if size > storageDeleteLimit { - return true, size, nil, nil, nil - } - slot := common.CopyBytes(iter.Slot()) - if err := iter.Error(); err != nil { // error might occur after Slot function - return false, 0, nil, nil, err - } - size += common.StorageSize(common.HashLength + len(slot)) - slots[iter.Hash()] = slot - - if err := stack.Update(iter.Hash().Bytes(), slot); err != nil { - return false, 0, nil, nil, err - } - } - if err := iter.Error(); err != nil { // error might occur during iteration - return false, 0, nil, nil, err - } - if stack.Hash() != root { - return false, 0, nil, nil, fmt.Errorf("snapshot is not matched, exp %x, got %x", root, stack.Hash()) - } - return false, size, slots, nodes, nil -} - -// slowDeleteStorage serves as a less-efficient alternative to "fastDeleteStorage," -// employed when the associated state snapshot is not available. It iterates the -// storage slots along with all internal trie nodes via trie directly. -func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) { - tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root, s.trie) - if err != nil { - return false, 0, nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err) - } - it, err := tr.NodeIterator(nil) - if err != nil { - return false, 0, nil, nil, fmt.Errorf("failed to open storage iterator, err: %w", err) - } - var ( - size common.StorageSize - nodes = trienode.NewNodeSet(addrHash) - slots = make(map[common.Hash][]byte) - ) - for it.Next(true) { - if size > storageDeleteLimit { - return true, size, nil, nil, nil - } - if it.Leaf() { - slots[common.BytesToHash(it.LeafKey())] = common.CopyBytes(it.LeafBlob()) - size += common.StorageSize(common.HashLength + len(it.LeafBlob())) - continue - } - if it.Hash() == (common.Hash{}) { - continue - } - size += common.StorageSize(len(it.Path())) - nodes.AddNode(it.Path(), trienode.NewDeleted()) - } - if err := it.Error(); err != nil { - return false, 0, nil, nil, err - } - return false, size, slots, nodes, nil -} - -// deleteStorage is designed to delete the storage trie of a designated account. -// It could potentially be terminated if the storage size is excessively large, -// potentially leading to an out-of-memory panic. The function will make an attempt -// to utilize an efficient strategy if the associated state snapshot is reachable; -// otherwise, it will resort to a less-efficient approach. -func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (bool, map[common.Hash][]byte, *trienode.NodeSet, error) { - var ( - start = time.Now() - err error - aborted bool - size common.StorageSize - slots map[common.Hash][]byte - nodes *trienode.NodeSet - ) - // The fast approach can be failed if the snapshot is not fully - // generated, or it's internally corrupted. Fallback to the slow - // one just in case. - if s.snap != nil { - aborted, size, slots, nodes, err = s.fastDeleteStorage(addrHash, root) - } - if s.snap == nil || err != nil { - aborted, size, slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root) - } - if err != nil { - return false, nil, nil, err - } - if metrics.EnabledExpensive { - if aborted { - slotDeletionSkip.Inc(1) - } - n := int64(len(slots)) - - slotDeletionMaxCount.UpdateIfGt(int64(len(slots))) - slotDeletionMaxSize.UpdateIfGt(int64(size)) - - slotDeletionTimer.UpdateSince(start) - slotDeletionCount.Mark(n) - slotDeletionSize.Mark(int64(size)) - } - return aborted, slots, nodes, nil -} - -// handleDestruction processes all destruction markers and deletes the account -// and associated storage slots if necessary. There are four possible situations -// here: -// -// - the account was not existent and be marked as destructed -// -// - the account was not existent and be marked as destructed, -// however, it's resurrected later in the same block. -// -// - the account was existent and be marked as destructed -// -// - the account was existent and be marked as destructed, -// however it's resurrected later in the same block. -// -// In case (a), nothing needs be deleted, nil to nil transition can be ignored. -// -// In case (b), nothing needs be deleted, nil is used as the original value for -// newly created account and storages -// -// In case (c), **original** account along with its storages should be deleted, -// with their values be tracked as original value. -// -// In case (d), **original** account along with its storages should be deleted, -// with their values be tracked as original value. -func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.Address]struct{}, error) { - // Short circuit if geth is running with hash mode. This procedure can consume - // considerable time and storage deletion isn't supported in hash mode, thus - // preemptively avoiding unnecessary expenses. - incomplete := make(map[common.Address]struct{}) - if s.db.TrieDB().Scheme() == rawdb.HashScheme { - return incomplete, nil - } - for addr, prev := range s.stateObjectsDestruct { - // The original account was non-existing, and it's marked as destructed - // in the scope of block. It can be case (a) or (b). - // - for (a), skip it without doing anything. - // - for (b), track account's original value as nil. It may overwrite - // the data cached in s.accountsOrigin set by 'updateStateObject'. - addrHash := crypto.Keccak256Hash(addr[:]) - if prev == nil { - if _, ok := s.accounts[addrHash]; ok { - s.accountsOrigin[addr] = nil // case (b) - } - continue - } - // It can overwrite the data in s.accountsOrigin set by 'updateStateObject'. - s.accountsOrigin[addr] = types.SlimAccountRLP(*prev) // case (c) or (d) - - // Short circuit if the storage was empty. - if prev.Root == types.EmptyRootHash { - continue - } - // Remove storage slots belong to the account. - aborted, slots, set, err := s.deleteStorage(addr, addrHash, prev.Root) - if err != nil { - return nil, fmt.Errorf("failed to delete storage, err: %w", err) - } - // The storage is too huge to handle, skip it but mark as incomplete. - // For case (d), the account is resurrected might with a few slots - // created. In this case, wipe the entire storage state diff because - // of aborted deletion. - if aborted { - incomplete[addr] = struct{}{} - delete(s.storagesOrigin, addr) - continue - } - if s.storagesOrigin[addr] == nil { - s.storagesOrigin[addr] = slots - } else { - // It can overwrite the data in s.storagesOrigin[addrHash] set by - // 'object.updateTrie'. - for key, val := range slots { - s.storagesOrigin[addr][key] = val - } - } - if err := nodes.Merge(set); err != nil { - return nil, err - } - } - return incomplete, nil -} - -// Commit writes the state to the underlying in-memory trie database. -// Once the state is committed, tries cached in stateDB (including account -// trie, storage tries) will no longer be functional. A new state instance -// must be created with new root and updated database for accessing post- -// commit states. -// -// The associated block number of the state transition is also provided -// for more chain context. -func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) { - // Short circuit in case any database failure occurred earlier. - if s.dbErr != nil { - return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr) - } - // Finalize any pending changes and merge everything into the tries - s.IntermediateRoot(deleteEmptyObjects) - - // Commit objects to the trie, measuring the elapsed time - var ( - accountTrieNodesUpdated int - accountTrieNodesDeleted int - storageTrieNodesUpdated int - storageTrieNodesDeleted int - nodes = trienode.NewMergedNodeSet() - codeWriter = s.db.DiskDB().NewBatch() - ) - // Handle all state deletions first - incomplete, err := s.handleDestruction(nodes) - if err != nil { - return common.Hash{}, err - } - // Handle all state updates afterwards - for addr := range s.stateObjectsDirty { - obj := s.stateObjects[addr] - if obj.deleted { - continue - } - // Write any contract code associated with the state object - if obj.code != nil && obj.dirtyCode { - rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code) - obj.dirtyCode = false - } - // Write any storage changes in the state object to its storage trie - set, err := obj.commit() - if err != nil { - return common.Hash{}, err - } - // Merge the dirty nodes of storage trie into global set. It is possible - // that the account was destructed and then resurrected in the same block. - // In this case, the node set is shared by both accounts. - if set != nil { - if err := nodes.Merge(set); err != nil { - return common.Hash{}, err - } - updates, deleted := set.Size() - storageTrieNodesUpdated += updates - storageTrieNodesDeleted += deleted - } - } - if codeWriter.ValueSize() > 0 { - if err := codeWriter.Write(); err != nil { - log.Crit("Failed to commit dirty codes", "error", err) - } - } - // Write the account trie changes, measuring the amount of wasted time - var start time.Time - if metrics.EnabledExpensive { - start = time.Now() - } - root, set, err := s.trie.Commit(true) - if err != nil { - return common.Hash{}, err - } - // Merge the dirty nodes of account trie into global set - if set != nil { - if err := nodes.Merge(set); err != nil { - return common.Hash{}, err - } - accountTrieNodesUpdated, accountTrieNodesDeleted = set.Size() - } - if metrics.EnabledExpensive { - s.AccountCommits += time.Since(start) - - accountUpdatedMeter.Mark(int64(s.AccountUpdated)) - storageUpdatedMeter.Mark(int64(s.StorageUpdated)) - accountDeletedMeter.Mark(int64(s.AccountDeleted)) - storageDeletedMeter.Mark(int64(s.StorageDeleted)) - accountTrieUpdatedMeter.Mark(int64(accountTrieNodesUpdated)) - accountTrieDeletedMeter.Mark(int64(accountTrieNodesDeleted)) - storageTriesUpdatedMeter.Mark(int64(storageTrieNodesUpdated)) - storageTriesDeletedMeter.Mark(int64(storageTrieNodesDeleted)) - s.AccountUpdated, s.AccountDeleted = 0, 0 - s.StorageUpdated, s.StorageDeleted = 0, 0 - } - // If snapshotting is enabled, update the snapshot tree with this new version - if s.snap != nil { - start := time.Now() - // Only update if there's a state transition (skip empty Clique blocks) - if parent := s.snap.Root(); parent != root { - if err := s.snaps.Update(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages); err != nil { - log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err) - } - // Keep 128 diff layers in the memory, persistent layer is 129th. - // - head layer is paired with HEAD state - // - head-1 layer is paired with HEAD-1 state - // - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state - if err := s.snaps.Cap(root, 128); err != nil { - log.Warn("Failed to cap snapshot tree", "root", root, "layers", 128, "err", err) - } - } - if metrics.EnabledExpensive { - s.SnapshotCommits += time.Since(start) - } - s.snap = nil - } - if root == (common.Hash{}) { - root = types.EmptyRootHash - } - origin := s.originalRoot - if origin == (common.Hash{}) { - origin = types.EmptyRootHash - } - if root != origin { - start := time.Now() - set := triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete) - if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil { - return common.Hash{}, err - } - s.originalRoot = root - if metrics.EnabledExpensive { - s.TrieDBCommits += time.Since(start) - } - if s.onCommit != nil { - s.onCommit(set) - } - } - // Clear all internal flags at the end of commit operation. - s.accounts = make(map[common.Hash][]byte) - s.storages = make(map[common.Hash]map[common.Hash][]byte) - s.accountsOrigin = make(map[common.Address][]byte) - s.storagesOrigin = make(map[common.Address]map[common.Hash][]byte) - s.stateObjectsDirty = make(map[common.Address]struct{}) - s.stateObjectsDestruct = make(map[common.Address]*types.StateAccount) - return root, nil -} - -// Prepare handles the preparatory steps for executing a state transition with. -// This method must be invoked before state transition. -// -// Berlin fork: -// - Add sender to access list (2929) -// - Add destination to access list (2929) -// - Add precompiles to access list (2929) -// - Add the contents of the optional tx access list (2930) -// -// Potential EIPs: -// - Reset access list (Berlin) -// - Add coinbase to access list (EIP-3651) -// - Reset transient storage (EIP-1153) -func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { - if rules.IsBerlin { - // Clear out any leftover from previous executions - al := newAccessList() - s.accessList = al - - al.AddAddress(sender) - if dst != nil { - al.AddAddress(*dst) - // If it's a create-tx, the destination will be added inside evm.create - } - for _, addr := range precompiles { - al.AddAddress(addr) - } - for _, el := range list { - al.AddAddress(el.Address) - for _, key := range el.StorageKeys { - al.AddSlot(el.Address, key) - } - } - if rules.IsShanghai { // EIP-3651: warm coinbase - al.AddAddress(coinbase) - } - } - // Reset transient storage at the beginning of transaction execution - s.transientStorage = newTransientStorage() -} - -// AddAddressToAccessList adds the given address to the access list -func (s *StateDB) AddAddressToAccessList(addr common.Address) { - if s.accessList.AddAddress(addr) { - s.journal.append(accessListAddAccountChange{&addr}) - } -} - -// AddSlotToAccessList adds the given (address, slot)-tuple to the access list -func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { - addrMod, slotMod := s.accessList.AddSlot(addr, slot) - if addrMod { - // In practice, this should not happen, since there is no way to enter the - // scope of 'address' without having the 'address' become already added - // to the access list (via call-variant, create, etc). - // Better safe than sorry, though - s.journal.append(accessListAddAccountChange{&addr}) - } - if slotMod { - s.journal.append(accessListAddSlotChange{ - address: &addr, - slot: &slot, - }) - } -} - -// AddressInAccessList returns true if the given address is in the access list. -func (s *StateDB) AddressInAccessList(addr common.Address) bool { - return s.accessList.ContainsAddress(addr) -} - -// SlotInAccessList returns true if the given (address, slot)-tuple is in the access list. -func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { - return s.accessList.Contains(addr, slot) -} - -// convertAccountSet converts a provided account set from address keyed to hash keyed. -func (s *StateDB) convertAccountSet(set map[common.Address]*types.StateAccount) map[common.Hash]struct{} { - ret := make(map[common.Hash]struct{}, len(set)) - for addr := range set { - obj, exist := s.stateObjects[addr] - if !exist { - ret[crypto.Keccak256Hash(addr[:])] = struct{}{} - } else { - ret[obj.addrHash] = struct{}{} - } - } - return ret -} - -func (s *StateDB) NewMultiTxSnapshot() (err error) { - _, err = s.multiTxSnapshotStack.NewSnapshot() - return -} - -func (s *StateDB) MultiTxSnapshotRevert() (err error) { - _, err = s.multiTxSnapshotStack.Revert() - return -} - -func (s *StateDB) MultiTxSnapshotCommit() (err error) { - _, err = s.multiTxSnapshotStack.Commit() - return -} - -func (s *StateDB) MultiTxSnapshotStackSize() int { - return s.multiTxSnapshotStack.Size() -} - -// copySet returns a deep-copied set. -func copySet[k comparable](set map[k][]byte) map[k][]byte { - copied := make(map[k][]byte, len(set)) - for key, val := range set { - copied[key] = common.CopyBytes(val) - } - return copied -} - -// copy2DSet returns a two-dimensional deep-copied set. -func copy2DSet[k comparable](set map[k]map[common.Hash][]byte) map[k]map[common.Hash][]byte { - copied := make(map[k]map[common.Hash][]byte, len(set)) - for addr, subset := range set { - copied[addr] = make(map[common.Hash][]byte, len(subset)) - for key, val := range subset { - copied[addr][key] = common.CopyBytes(val) - } - } - return copied -} diff --git a/builder/core/state/statedb_fuzz_test.go b/builder/core/state/statedb_fuzz_test.go deleted file mode 100644 index b416bcf1f..000000000 --- a/builder/core/state/statedb_fuzz_test.go +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2023 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 state - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "strings" - "testing" - "testing/quick" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/triestate" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" -) - -// A stateTest checks that the state changes are correctly captured. Instances -// of this test with pseudorandom content are created by Generate. -// -// The test works as follows: -// -// A list of states are created by applying actions. The state changes between -// each state instance are tracked and be verified. -type stateTest struct { - addrs []common.Address // all account addresses - actions [][]testAction // modifications to the state, grouped by block - chunk int // The number of actions per chunk - err error // failure details are reported through this field -} - -// newStateTestAction creates a random action that changes state. -func newStateTestAction(addr common.Address, r *rand.Rand, index int) testAction { - actions := []testAction{ - { - name: "SetBalance", - fn: func(a testAction, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(uint64(a.args[0]))) - }, - args: make([]int64, 1), - }, - { - name: "SetNonce", - fn: func(a testAction, s *StateDB) { - s.SetNonce(addr, uint64(a.args[0])) - }, - args: make([]int64, 1), - }, - { - name: "SetState", - fn: func(a testAction, s *StateDB) { - var key, val common.Hash - binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) - binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) - s.SetState(addr, key, val) - }, - args: make([]int64, 2), - }, - { - name: "SetCode", - fn: func(a testAction, s *StateDB) { - code := make([]byte, 16) - binary.BigEndian.PutUint64(code, uint64(a.args[0])) - binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) - s.SetCode(addr, code) - }, - args: make([]int64, 2), - }, - { - name: "CreateAccount", - fn: func(a testAction, s *StateDB) { - s.CreateAccount(addr) - }, - }, - { - name: "Selfdestruct", - fn: func(a testAction, s *StateDB) { - s.SelfDestruct(addr) - }, - }, - } - var nonRandom = index != -1 - if index == -1 { - index = r.Intn(len(actions)) - } - action := actions[index] - var names []string - if !action.noAddr { - names = append(names, addr.Hex()) - } - for i := range action.args { - if nonRandom { - action.args[i] = rand.Int63n(10000) + 1 // set balance to non-zero - } else { - action.args[i] = rand.Int63n(10000) - } - names = append(names, fmt.Sprint(action.args[i])) - } - action.name += " " + strings.Join(names, ", ") - return action -} - -// Generate returns a new snapshot test of the given size. All randomness is -// derived from r. -func (*stateTest) Generate(r *rand.Rand, size int) reflect.Value { - addrs := make([]common.Address, 5) - for i := range addrs { - addrs[i][0] = byte(i) - } - actions := make([][]testAction, rand.Intn(5)+1) - - for i := 0; i < len(actions); i++ { - actions[i] = make([]testAction, size) - for j := range actions[i] { - if j == 0 { - // Always include a set balance action to make sure - // the state changes are not empty. - actions[i][j] = newStateTestAction(common.HexToAddress("0xdeadbeef"), r, 0) - continue - } - actions[i][j] = newStateTestAction(addrs[r.Intn(len(addrs))], r, -1) - } - } - chunk := int(math.Sqrt(float64(size))) - if size > 0 && chunk == 0 { - chunk = 1 - } - return reflect.ValueOf(&stateTest{ - addrs: addrs, - actions: actions, - chunk: chunk, - }) -} - -func (test *stateTest) String() string { - out := new(bytes.Buffer) - for i, actions := range test.actions { - fmt.Fprintf(out, "---- block %d ----\n", i) - for j, action := range actions { - if j%test.chunk == 0 { - fmt.Fprintf(out, "---- transaction %d ----\n", j/test.chunk) - } - fmt.Fprintf(out, "%4d: %s\n", j%test.chunk, action.name) - } - } - return out.String() -} - -func (test *stateTest) run() bool { - var ( - roots []common.Hash - accountList []map[common.Address][]byte - storageList []map[common.Address]map[common.Hash][]byte - onCommit = func(states *triestate.Set) { - accountList = append(accountList, copySet(states.Accounts)) - storageList = append(storageList, copy2DSet(states.Storages)) - } - disk = rawdb.NewMemoryDatabase() - tdb = triedb.NewDatabase(disk, &triedb.Config{PathDB: pathdb.Defaults}) - sdb = NewDatabaseWithNodeDB(disk, tdb) - byzantium = rand.Intn(2) == 0 - ) - defer disk.Close() - defer tdb.Close() - - var snaps *snapshot.Tree - if rand.Intn(3) == 0 { - snaps, _ = snapshot.New(snapshot.Config{ - CacheSize: 1, - Recovery: false, - NoBuild: false, - AsyncBuild: false, - }, disk, tdb, types.EmptyRootHash) - } - for i, actions := range test.actions { - root := types.EmptyRootHash - if i != 0 { - root = roots[len(roots)-1] - } - state, err := New(root, sdb, snaps) - if err != nil { - panic(err) - } - state.onCommit = onCommit - - for i, action := range actions { - if i%test.chunk == 0 && i != 0 { - if byzantium { - state.Finalise(true) // call finalise at the transaction boundary - } else { - state.IntermediateRoot(true) // call intermediateRoot at the transaction boundary - } - } - action.fn(action, state) - } - if byzantium { - state.Finalise(true) // call finalise at the transaction boundary - } else { - state.IntermediateRoot(true) // call intermediateRoot at the transaction boundary - } - nroot, err := state.Commit(0, true) // call commit at the block boundary - if err != nil { - panic(err) - } - if nroot == root { - return true // filter out non-change state transition - } - roots = append(roots, nroot) - } - for i := 0; i < len(test.actions); i++ { - root := types.EmptyRootHash - if i != 0 { - root = roots[i-1] - } - test.err = test.verify(root, roots[i], tdb, accountList[i], storageList[i]) - if test.err != nil { - return false - } - } - return true -} - -// verifyAccountCreation this function is called once the state diff says that -// specific account was not present. A serial of checks will be performed to -// ensure the state diff is correct, includes: -// -// - the account was indeed not present in trie -// - the account is present in new trie, nil->nil is regarded as invalid -// - the slots transition is correct -func (test *stateTest) verifyAccountCreation(next common.Hash, db *triedb.Database, otr, ntr *trie.Trie, addr common.Address, slots map[common.Hash][]byte) error { - // Verify account change - addrHash := crypto.Keccak256Hash(addr.Bytes()) - oBlob, err := otr.Get(addrHash.Bytes()) - if err != nil { - return err - } - nBlob, err := ntr.Get(addrHash.Bytes()) - if err != nil { - return err - } - if len(oBlob) != 0 { - return fmt.Errorf("unexpected account in old trie, %x", addrHash) - } - if len(nBlob) == 0 { - return fmt.Errorf("missing account in new trie, %x", addrHash) - } - - // Verify storage changes - var nAcct types.StateAccount - if err := rlp.DecodeBytes(nBlob, &nAcct); err != nil { - return err - } - // Account has no slot, empty slot set is expected - if nAcct.Root == types.EmptyRootHash { - if len(slots) != 0 { - return fmt.Errorf("unexpected slot changes %x", addrHash) - } - return nil - } - // Account has slots, ensure all new slots are contained - st, err := trie.New(trie.StorageTrieID(next, addrHash, nAcct.Root), db) - if err != nil { - return err - } - for key, val := range slots { - st.Update(key.Bytes(), val) - } - if st.Hash() != types.EmptyRootHash { - return errors.New("invalid slot changes") - } - return nil -} - -// verifyAccountUpdate this function is called once the state diff says that -// specific account was present. A serial of checks will be performed to -// ensure the state diff is correct, includes: -// -// - the account was indeed present in trie -// - the account in old trie matches the provided value -// - the slots transition is correct -func (test *stateTest) verifyAccountUpdate(next common.Hash, db *triedb.Database, otr, ntr *trie.Trie, addr common.Address, origin []byte, slots map[common.Hash][]byte) error { - // Verify account change - addrHash := crypto.Keccak256Hash(addr.Bytes()) - oBlob, err := otr.Get(addrHash.Bytes()) - if err != nil { - return err - } - nBlob, err := ntr.Get(addrHash.Bytes()) - if err != nil { - return err - } - if len(oBlob) == 0 { - return fmt.Errorf("missing account in old trie, %x", addrHash) - } - full, err := types.FullAccountRLP(origin) - if err != nil { - return err - } - if !bytes.Equal(full, oBlob) { - return fmt.Errorf("account value is not matched, %x", addrHash) - } - - // Decode accounts - var ( - oAcct types.StateAccount - nAcct types.StateAccount - nRoot common.Hash - ) - if err := rlp.DecodeBytes(oBlob, &oAcct); err != nil { - return err - } - if len(nBlob) == 0 { - nRoot = types.EmptyRootHash - } else { - if err := rlp.DecodeBytes(nBlob, &nAcct); err != nil { - return err - } - nRoot = nAcct.Root - } - - // Verify storage - st, err := trie.New(trie.StorageTrieID(next, addrHash, nRoot), db) - if err != nil { - return err - } - for key, val := range slots { - st.Update(key.Bytes(), val) - } - if st.Hash() != oAcct.Root { - return errors.New("invalid slot changes") - } - return nil -} - -func (test *stateTest) verify(root common.Hash, next common.Hash, db *triedb.Database, accountsOrigin map[common.Address][]byte, storagesOrigin map[common.Address]map[common.Hash][]byte) error { - otr, err := trie.New(trie.StateTrieID(root), db) - if err != nil { - return err - } - ntr, err := trie.New(trie.StateTrieID(next), db) - if err != nil { - return err - } - for addr, account := range accountsOrigin { - var err error - if len(account) == 0 { - err = test.verifyAccountCreation(next, db, otr, ntr, addr, storagesOrigin[addr]) - } else { - err = test.verifyAccountUpdate(next, db, otr, ntr, addr, accountsOrigin[addr], storagesOrigin[addr]) - } - if err != nil { - return err - } - } - return nil -} - -func TestStateChanges(t *testing.T) { - config := &quick.Config{MaxCount: 1000} - err := quick.Check((*stateTest).run, config) - if cerr, ok := err.(*quick.CheckError); ok { - test := cerr.In[0].(*stateTest) - t.Errorf("%v:\n%s", test.err, test) - } else if err != nil { - t.Error(err) - } -} diff --git a/builder/core/state/statedb_test.go b/builder/core/state/statedb_test.go deleted file mode 100644 index cd86a7f4b..000000000 --- a/builder/core/state/statedb_test.go +++ /dev/null @@ -1,1191 +0,0 @@ -// Copyright 2016 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 state - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "strings" - "sync" - "testing" - "testing/quick" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" -) - -// Tests that updating a state trie does not leak any database writes prior to -// actually committing the state. -func TestUpdateLeaks(t *testing.T) { - // Create an empty state database - var ( - db = rawdb.NewMemoryDatabase() - tdb = triedb.NewDatabase(db, nil) - ) - state, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(db, tdb), nil) - - // Update it with some accounts - for i := byte(0); i < 255; i++ { - addr := common.BytesToAddress([]byte{i}) - state.AddBalance(addr, uint256.NewInt(uint64(11*i))) - state.SetNonce(addr, uint64(42*i)) - if i%2 == 0 { - state.SetState(addr, common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) - } - if i%3 == 0 { - state.SetCode(addr, []byte{i, i, i, i, i}) - } - } - - root := state.IntermediateRoot(false) - if err := tdb.Commit(root, false); err != nil { - t.Errorf("can not commit trie %v to persistent database", root.Hex()) - } - - // Ensure that no data was leaked into the database - it := db.NewIterator(nil, nil) - for it.Next() { - t.Errorf("State leaked into database: %x -> %x", it.Key(), it.Value()) - } - it.Release() -} - -// Tests that no intermediate state of an object is stored into the database, -// only the one right before the commit. -func TestIntermediateLeaks(t *testing.T) { - // Create two state databases, one transitioning to the final state, the other final from the beginning - transDb := rawdb.NewMemoryDatabase() - finalDb := rawdb.NewMemoryDatabase() - transNdb := triedb.NewDatabase(transDb, nil) - finalNdb := triedb.NewDatabase(finalDb, nil) - transState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(transDb, transNdb), nil) - finalState, _ := New(types.EmptyRootHash, NewDatabaseWithNodeDB(finalDb, finalNdb), nil) - - modify := func(state *StateDB, addr common.Address, i, tweak byte) { - state.SetBalance(addr, uint256.NewInt(uint64(11*i)+uint64(tweak))) - state.SetNonce(addr, uint64(42*i+tweak)) - if i%2 == 0 { - state.SetState(addr, common.Hash{i, i, i, 0}, common.Hash{}) - state.SetState(addr, common.Hash{i, i, i, tweak}, common.Hash{i, i, i, i, tweak}) - } - if i%3 == 0 { - state.SetCode(addr, []byte{i, i, i, i, i, tweak}) - } - } - - // Modify the transient state. - for i := byte(0); i < 255; i++ { - modify(transState, common.Address{i}, i, 0) - } - // Write modifications to trie. - transState.IntermediateRoot(false) - - // Overwrite all the data with new values in the transient database. - for i := byte(0); i < 255; i++ { - modify(transState, common.Address{i}, i, 99) - modify(finalState, common.Address{i}, i, 99) - } - - // Commit and cross check the databases. - transRoot, err := transState.Commit(0, false) - if err != nil { - t.Fatalf("failed to commit transition state: %v", err) - } - if err = transNdb.Commit(transRoot, false); err != nil { - t.Errorf("can not commit trie %v to persistent database", transRoot.Hex()) - } - - finalRoot, err := finalState.Commit(0, false) - if err != nil { - t.Fatalf("failed to commit final state: %v", err) - } - if err = finalNdb.Commit(finalRoot, false); err != nil { - t.Errorf("can not commit trie %v to persistent database", finalRoot.Hex()) - } - - it := finalDb.NewIterator(nil, nil) - for it.Next() { - key, fvalue := it.Key(), it.Value() - tvalue, err := transDb.Get(key) - if err != nil { - t.Errorf("entry missing from the transition database: %x -> %x", key, fvalue) - } - if !bytes.Equal(fvalue, tvalue) { - t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue) - } - } - it.Release() - - it = transDb.NewIterator(nil, nil) - for it.Next() { - key, tvalue := it.Key(), it.Value() - fvalue, err := finalDb.Get(key) - if err != nil { - t.Errorf("extra entry in the transition database: %x -> %x", key, it.Value()) - } - if !bytes.Equal(fvalue, tvalue) { - t.Errorf("value mismatch at key %x: %x in transition database, %x in final database", key, tvalue, fvalue) - } - } -} - -// TestCopy tests that copying a StateDB object indeed makes the original and -// the copy independent of each other. This test is a regression test against -// https://github.com/ethereum/go-ethereum/pull/15549. -func TestCopy(t *testing.T) { - // Create a random state test to copy and modify "independently" - orig, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - for i := byte(0); i < 255; i++ { - obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - obj.AddBalance(uint256.NewInt(uint64(i))) - orig.updateStateObject(obj) - } - orig.Finalise(false) - - // Copy the state - copy := orig.Copy() - - // Copy the copy state - ccopy := copy.Copy() - - // modify all in memory - for i := byte(0); i < 255; i++ { - origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i})) - ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i})) - - origObj.AddBalance(uint256.NewInt(2 * uint64(i))) - copyObj.AddBalance(uint256.NewInt(3 * uint64(i))) - ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i))) - - orig.updateStateObject(origObj) - copy.updateStateObject(copyObj) - ccopy.updateStateObject(copyObj) - } - - // Finalise the changes on all concurrently - finalise := func(wg *sync.WaitGroup, db *StateDB) { - defer wg.Done() - db.Finalise(true) - } - - var wg sync.WaitGroup - wg.Add(3) - go finalise(&wg, orig) - go finalise(&wg, copy) - go finalise(&wg, ccopy) - wg.Wait() - - // Verify that the three states have been updated independently - for i := byte(0); i < 255; i++ { - origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) - copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i})) - ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i})) - - if want := uint256.NewInt(3 * uint64(i)); origObj.Balance().Cmp(want) != 0 { - t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want) - } - if want := uint256.NewInt(4 * uint64(i)); copyObj.Balance().Cmp(want) != 0 { - t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, copyObj.Balance(), want) - } - if want := uint256.NewInt(5 * uint64(i)); ccopyObj.Balance().Cmp(want) != 0 { - t.Errorf("copy obj %d: balance mismatch: have %v, want %v", i, ccopyObj.Balance(), want) - } - } -} - -func TestSnapshotRandom(t *testing.T) { - config := &quick.Config{MaxCount: 1000} - err := quick.Check((*snapshotTest).run, config) - if cerr, ok := err.(*quick.CheckError); ok { - test := cerr.In[0].(*snapshotTest) - t.Errorf("%v:\n%s", test.err, test) - } else if err != nil { - t.Error(err) - } -} - -// A snapshotTest checks that reverting StateDB snapshots properly undoes all changes -// captured by the snapshot. Instances of this test with pseudorandom content are created -// by Generate. -// -// The test works as follows: -// -// A new state is created and all actions are applied to it. Several snapshots are taken -// in between actions. The test then reverts each snapshot. For each snapshot the actions -// leading up to it are replayed on a fresh, empty state. The behaviour of all public -// accessor methods on the reverted state must match the return value of the equivalent -// methods on the replayed state. -type snapshotTest struct { - addrs []common.Address // all account addresses - actions []testAction // modifications to the state - snapshots []int // actions indexes at which snapshot is taken - err error // failure details are reported through this field -} - -type testAction struct { - name string - fn func(testAction, *StateDB) - args []int64 - noAddr bool -} - -// newTestAction creates a random action that changes state. -func newTestAction(addr common.Address, r *rand.Rand) testAction { - actions := []testAction{ - { - name: "SetBalance", - fn: func(a testAction, s *StateDB) { - s.SetBalance(addr, uint256.NewInt(uint64(a.args[0]))) - }, - args: make([]int64, 1), - }, - { - name: "AddBalance", - fn: func(a testAction, s *StateDB) { - s.AddBalance(addr, uint256.NewInt(uint64(a.args[0]))) - }, - args: make([]int64, 1), - }, - { - name: "SetNonce", - fn: func(a testAction, s *StateDB) { - s.SetNonce(addr, uint64(a.args[0])) - }, - args: make([]int64, 1), - }, - { - name: "SetState", - fn: func(a testAction, s *StateDB) { - var key, val common.Hash - binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) - binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) - s.SetState(addr, key, val) - }, - args: make([]int64, 2), - }, - { - name: "SetCode", - fn: func(a testAction, s *StateDB) { - code := make([]byte, 16) - binary.BigEndian.PutUint64(code, uint64(a.args[0])) - binary.BigEndian.PutUint64(code[8:], uint64(a.args[1])) - s.SetCode(addr, code) - }, - args: make([]int64, 2), - }, - { - name: "CreateAccount", - fn: func(a testAction, s *StateDB) { - s.CreateAccount(addr) - }, - }, - { - name: "SelfDestruct", - fn: func(a testAction, s *StateDB) { - s.SelfDestruct(addr) - }, - }, - { - name: "AddRefund", - fn: func(a testAction, s *StateDB) { - s.AddRefund(uint64(a.args[0])) - }, - args: make([]int64, 1), - noAddr: true, - }, - { - name: "AddLog", - fn: func(a testAction, s *StateDB) { - data := make([]byte, 2) - binary.BigEndian.PutUint16(data, uint16(a.args[0])) - s.AddLog(&types.Log{Address: addr, Data: data}) - }, - args: make([]int64, 1), - }, - { - name: "AddPreimage", - fn: func(a testAction, s *StateDB) { - preimage := []byte{1} - hash := common.BytesToHash(preimage) - s.AddPreimage(hash, preimage) - }, - args: make([]int64, 1), - }, - { - name: "AddAddressToAccessList", - fn: func(a testAction, s *StateDB) { - s.AddAddressToAccessList(addr) - }, - }, - { - name: "AddSlotToAccessList", - fn: func(a testAction, s *StateDB) { - s.AddSlotToAccessList(addr, - common.Hash{byte(a.args[0])}) - }, - args: make([]int64, 1), - }, - { - name: "SetTransientState", - fn: func(a testAction, s *StateDB) { - var key, val common.Hash - binary.BigEndian.PutUint16(key[:], uint16(a.args[0])) - binary.BigEndian.PutUint16(val[:], uint16(a.args[1])) - s.SetTransientState(addr, key, val) - }, - args: make([]int64, 2), - }, - } - action := actions[r.Intn(len(actions))] - var nameargs []string - if !action.noAddr { - nameargs = append(nameargs, addr.Hex()) - } - for i := range action.args { - action.args[i] = rand.Int63n(100) - nameargs = append(nameargs, fmt.Sprint(action.args[i])) - } - action.name += strings.Join(nameargs, ", ") - return action -} - -// Generate returns a new snapshot test of the given size. All randomness is -// derived from r. -func (*snapshotTest) Generate(r *rand.Rand, size int) reflect.Value { - // Generate random actions. - addrs := make([]common.Address, 50) - for i := range addrs { - addrs[i][0] = byte(i) - } - actions := make([]testAction, size) - for i := range actions { - addr := addrs[r.Intn(len(addrs))] - actions[i] = newTestAction(addr, r) - } - // Generate snapshot indexes. - nsnapshots := int(math.Sqrt(float64(size))) - if size > 0 && nsnapshots == 0 { - nsnapshots = 1 - } - snapshots := make([]int, nsnapshots) - snaplen := len(actions) / nsnapshots - for i := range snapshots { - // Try to place the snapshots some number of actions apart from each other. - snapshots[i] = (i * snaplen) + r.Intn(snaplen) - } - return reflect.ValueOf(&snapshotTest{addrs, actions, snapshots, nil}) -} - -func (test *snapshotTest) String() string { - out := new(bytes.Buffer) - sindex := 0 - for i, action := range test.actions { - if len(test.snapshots) > sindex && i == test.snapshots[sindex] { - fmt.Fprintf(out, "---- snapshot %d ----\n", sindex) - sindex++ - } - fmt.Fprintf(out, "%4d: %s\n", i, action.name) - } - return out.String() -} - -func (test *snapshotTest) run() bool { - // Run all actions and create snapshots. - var ( - state, _ = New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - snapshotRevs = make([]int, len(test.snapshots)) - sindex = 0 - checkstates = make([]*StateDB, len(test.snapshots)) - ) - for i, action := range test.actions { - if len(test.snapshots) > sindex && i == test.snapshots[sindex] { - snapshotRevs[sindex] = state.Snapshot() - checkstates[sindex] = state.Copy() - sindex++ - } - action.fn(action, state) - } - // Revert all snapshots in reverse order. Each revert must yield a state - // that is equivalent to fresh state with all actions up the snapshot applied. - for sindex--; sindex >= 0; sindex-- { - state.RevertToSnapshot(snapshotRevs[sindex]) - if err := test.checkEqual(state, checkstates[sindex]); err != nil { - test.err = fmt.Errorf("state mismatch after revert to snapshot %d\n%v", sindex, err) - return false - } - } - return true -} - -func forEachStorage(s *StateDB, addr common.Address, cb func(key, value common.Hash) bool) error { - so := s.getStateObject(addr) - if so == nil { - return nil - } - tr, err := so.getTrie() - if err != nil { - return err - } - trieIt, err := tr.NodeIterator(nil) - if err != nil { - return err - } - it := trie.NewIterator(trieIt) - - for it.Next() { - key := common.BytesToHash(s.trie.GetKey(it.Key)) - if value, dirty := so.dirtyStorage[key]; dirty { - if !cb(key, value) { - return nil - } - continue - } - - if len(it.Value) > 0 { - _, content, _, err := rlp.Split(it.Value) - if err != nil { - return err - } - if !cb(key, common.BytesToHash(content)) { - return nil - } - } - } - return nil -} - -// checkEqual checks that methods of state and checkstate return the same values. -func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { - for _, addr := range test.addrs { - var err error - checkeq := func(op string, a, b interface{}) bool { - if err == nil && !reflect.DeepEqual(a, b) { - err = fmt.Errorf("got %s(%s) == %v, want %v", op, addr.Hex(), a, b) - return false - } - return true - } - // Check basic accessor methods. - checkeq("Exist", state.Exist(addr), checkstate.Exist(addr)) - checkeq("HasSelfdestructed", state.HasSelfDestructed(addr), checkstate.HasSelfDestructed(addr)) - checkeq("GetBalance", state.GetBalance(addr), checkstate.GetBalance(addr)) - checkeq("GetNonce", state.GetNonce(addr), checkstate.GetNonce(addr)) - checkeq("GetCode", state.GetCode(addr), checkstate.GetCode(addr)) - checkeq("GetCodeHash", state.GetCodeHash(addr), checkstate.GetCodeHash(addr)) - checkeq("GetCodeSize", state.GetCodeSize(addr), checkstate.GetCodeSize(addr)) - // Check storage. - if obj := state.getStateObject(addr); obj != nil { - forEachStorage(state, addr, func(key, value common.Hash) bool { - return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) - }) - forEachStorage(checkstate, addr, func(key, value common.Hash) bool { - return checkeq("GetState("+key.Hex()+")", checkstate.GetState(addr, key), value) - }) - } - if err != nil { - return err - } - } - - if state.GetRefund() != checkstate.GetRefund() { - return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", - state.GetRefund(), checkstate.GetRefund()) - } - if !reflect.DeepEqual(state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{})) { - return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", - state.GetLogs(common.Hash{}, 0, common.Hash{}), checkstate.GetLogs(common.Hash{}, 0, common.Hash{})) - } - return nil -} - -func TestTouchDelete(t *testing.T) { - s := newStateEnv() - s.state.getOrNewStateObject(common.Address{}) - root, _ := s.state.Commit(0, false) - s.state, _ = New(root, s.state.db, s.state.snaps) - - snapshot := s.state.Snapshot() - s.state.AddBalance(common.Address{}, new(uint256.Int)) - - if len(s.state.journal.dirties) != 1 { - t.Fatal("expected one dirty state object") - } - s.state.RevertToSnapshot(snapshot) - if len(s.state.journal.dirties) != 0 { - t.Fatal("expected no dirty state object") - } -} - -// TestCopyOfCopy tests that modified objects are carried over to the copy, and the copy of the copy. -// See https://github.com/ethereum/go-ethereum/pull/15225#issuecomment-380191512 -func TestCopyOfCopy(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - addr := common.HexToAddress("aaaa") - state.SetBalance(addr, uint256.NewInt(42)) - - if got := state.Copy().GetBalance(addr).Uint64(); got != 42 { - t.Fatalf("1st copy fail, expected 42, got %v", got) - } - if got := state.Copy().Copy().GetBalance(addr).Uint64(); got != 42 { - t.Fatalf("2nd copy fail, expected 42, got %v", got) - } -} - -// Tests a regression where committing a copy lost some internal meta information, -// leading to corrupted subsequent copies. -// -// See https://github.com/ethereum/go-ethereum/issues/20106. -func TestCopyCommitCopy(t *testing.T) { - tdb := NewDatabase(rawdb.NewMemoryDatabase()) - state, _ := New(types.EmptyRootHash, tdb, nil) - - // Create an account and check if the retrieved balance is correct - addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") - skey := common.HexToHash("aaa") - sval := common.HexToHash("bbb") - - state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata - state.SetState(addr, skey, sval) // Change the storage trie - - if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) - } - if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := state.GetState(addr, skey); val != sval { - t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the non-committed state database and check pre/post commit balance - copyOne := state.Copy() - if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) - } - if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("first copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := copyOne.GetState(addr, skey); val != sval { - t.Fatalf("first copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("first copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the copy and check the balance once more - copyTwo := copyOne.Copy() - if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("second copy balance mismatch: have %v, want %v", balance, 42) - } - if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("second copy code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := copyTwo.GetState(addr, skey); val != sval { - t.Fatalf("second copy non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("second copy committed storage slot mismatch: have %x, want %x", val, sval) - } - // Commit state, ensure states can be loaded from disk - root, _ := state.Commit(0, false) - state, _ = New(root, tdb, nil) - if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42) - } - if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("state post-commit code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := state.GetState(addr, skey); val != sval { - t.Fatalf("state post-commit non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := state.GetCommittedState(addr, skey); val != sval { - t.Fatalf("state post-commit committed storage slot mismatch: have %x, want %x", val, sval) - } -} - -// Tests a regression where committing a copy lost some internal meta information, -// leading to corrupted subsequent copies. -// -// See https://github.com/ethereum/go-ethereum/issues/20106. -func TestCopyCopyCommitCopy(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - // Create an account and check if the retrieved balance is correct - addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") - skey := common.HexToHash("aaa") - sval := common.HexToHash("bbb") - - state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata - state.SetState(addr, skey, sval) // Change the storage trie - - if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) - } - if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := state.GetState(addr, skey); val != sval { - t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the non-committed state database and check pre/post commit balance - copyOne := state.Copy() - if balance := copyOne.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("first copy balance mismatch: have %v, want %v", balance, 42) - } - if code := copyOne.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("first copy code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := copyOne.GetState(addr, skey); val != sval { - t.Fatalf("first copy non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := copyOne.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the copy and check the balance once more - copyTwo := copyOne.Copy() - if balance := copyTwo.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) - } - if code := copyTwo.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("second copy pre-commit code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := copyTwo.GetState(addr, skey); val != sval { - t.Fatalf("second copy pre-commit non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := copyTwo.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("second copy pre-commit committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the copy-copy and check the balance once more - copyThree := copyTwo.Copy() - if balance := copyThree.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("third copy balance mismatch: have %v, want %v", balance, 42) - } - if code := copyThree.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("third copy code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := copyThree.GetState(addr, skey); val != sval { - t.Fatalf("third copy non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := copyThree.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("third copy committed storage slot mismatch: have %x, want %x", val, sval) - } -} - -// TestCommitCopy tests the copy from a committed state is not functional. -func TestCommitCopy(t *testing.T) { - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - // Create an account and check if the retrieved balance is correct - addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") - skey := common.HexToHash("aaa") - sval := common.HexToHash("bbb") - - state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata - state.SetState(addr, skey, sval) // Change the storage trie - - if balance := state.GetBalance(addr); balance.Cmp(uint256.NewInt(42)) != 0 { - t.Fatalf("initial balance mismatch: have %v, want %v", balance, 42) - } - if code := state.GetCode(addr); !bytes.Equal(code, []byte("hello")) { - t.Fatalf("initial code mismatch: have %x, want %x", code, []byte("hello")) - } - if val := state.GetState(addr, skey); val != sval { - t.Fatalf("initial non-committed storage slot mismatch: have %x, want %x", val, sval) - } - if val := state.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) - } - // Copy the committed state database, the copied one is not functional. - state.Commit(0, true) - copied := state.Copy() - if balance := copied.GetBalance(addr); balance.Cmp(uint256.NewInt(0)) != 0 { - t.Fatalf("unexpected balance: have %v", balance) - } - if code := copied.GetCode(addr); code != nil { - t.Fatalf("unexpected code: have %x", code) - } - if val := copied.GetState(addr, skey); val != (common.Hash{}) { - t.Fatalf("unexpected storage slot: have %x", val) - } - if val := copied.GetCommittedState(addr, skey); val != (common.Hash{}) { - t.Fatalf("unexpected storage slot: have %x", val) - } - if !errors.Is(copied.Error(), trie.ErrCommitted) { - t.Fatalf("unexpected state error, %v", copied.Error()) - } -} - -// TestDeleteCreateRevert tests a weird state transition corner case that we hit -// while changing the internals of StateDB. The workflow is that a contract is -// self-destructed, then in a follow-up transaction (but same block) it's created -// again and the transaction reverted. -// -// The original StateDB implementation flushed dirty objects to the tries after -// each transaction, so this works ok. The rework accumulated writes in memory -// first, but the journal wiped the entire state object on create-revert. -func TestDeleteCreateRevert(t *testing.T) { - // Create an initial state with a single contract - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - addr := common.BytesToAddress([]byte("so")) - state.SetBalance(addr, uint256.NewInt(1)) - - root, _ := state.Commit(0, false) - state, _ = New(root, state.db, state.snaps) - - // Simulate self-destructing in one transaction, then create-reverting in another - state.SelfDestruct(addr) - state.Finalise(true) - - id := state.Snapshot() - state.SetBalance(addr, uint256.NewInt(2)) - state.RevertToSnapshot(id) - - // Commit the entire state and make sure we don't crash and have the correct state - root, _ = state.Commit(0, true) - state, _ = New(root, state.db, state.snaps) - - if state.getStateObject(addr) != nil { - t.Fatalf("self-destructed contract came alive") - } -} - -// TestMissingTrieNodes tests that if the StateDB fails to load parts of the trie, -// the Commit operation fails with an error -// If we are missing trie nodes, we should not continue writing to the trie -func TestMissingTrieNodes(t *testing.T) { - testMissingTrieNodes(t, rawdb.HashScheme) - testMissingTrieNodes(t, rawdb.PathScheme) -} - -func testMissingTrieNodes(t *testing.T, scheme string) { - // Create an initial state with a few accounts - var ( - tdb *triedb.Database - memDb = rawdb.NewMemoryDatabase() - ) - if scheme == rawdb.PathScheme { - tdb = triedb.NewDatabase(memDb, &triedb.Config{PathDB: &pathdb.Config{ - CleanCacheSize: 0, - DirtyCacheSize: 0, - }}) // disable caching - } else { - tdb = triedb.NewDatabase(memDb, &triedb.Config{HashDB: &hashdb.Config{ - CleanCacheSize: 0, - }}) // disable caching - } - db := NewDatabaseWithNodeDB(memDb, tdb) - - var root common.Hash - state, _ := New(types.EmptyRootHash, db, nil) - addr := common.BytesToAddress([]byte("so")) - { - state.SetBalance(addr, uint256.NewInt(1)) - state.SetCode(addr, []byte{1, 2, 3}) - a2 := common.BytesToAddress([]byte("another")) - state.SetBalance(a2, uint256.NewInt(100)) - state.SetCode(a2, []byte{1, 2, 4}) - root, _ = state.Commit(0, false) - t.Logf("root: %x", root) - // force-flush - tdb.Commit(root, false) - } - // Create a new state on the old root - state, _ = New(root, db, nil) - // Now we clear out the memdb - it := memDb.NewIterator(nil, nil) - for it.Next() { - k := it.Key() - // Leave the root intact - if !bytes.Equal(k, root[:]) { - t.Logf("key: %x", k) - memDb.Delete(k) - } - } - balance := state.GetBalance(addr) - // The removed elem should lead to it returning zero balance - if exp, got := uint64(0), balance.Uint64(); got != exp { - t.Errorf("expected %d, got %d", exp, got) - } - // Modify the state - state.SetBalance(addr, uint256.NewInt(2)) - root, err := state.Commit(0, false) - if err == nil { - t.Fatalf("expected error, got root :%x", root) - } -} - -func TestStateDBAccessList(t *testing.T) { - // Some helpers - addr := func(a string) common.Address { - return common.HexToAddress(a) - } - slot := func(a string) common.Hash { - return common.HexToHash(a) - } - - memDb := rawdb.NewMemoryDatabase() - db := NewDatabase(memDb) - state, _ := New(types.EmptyRootHash, db, nil) - state.accessList = newAccessList() - - verifyAddrs := func(astrings ...string) { - t.Helper() - // convert to common.Address form - var addresses []common.Address - var addressMap = make(map[common.Address]struct{}) - for _, astring := range astrings { - address := addr(astring) - addresses = append(addresses, address) - addressMap[address] = struct{}{} - } - // Check that the given addresses are in the access list - for _, address := range addresses { - if !state.AddressInAccessList(address) { - t.Fatalf("expected %x to be in access list", address) - } - } - // Check that only the expected addresses are present in the access list - for address := range state.accessList.addresses { - if _, exist := addressMap[address]; !exist { - t.Fatalf("extra address %x in access list", address) - } - } - } - verifySlots := func(addrString string, slotStrings ...string) { - if !state.AddressInAccessList(addr(addrString)) { - t.Fatalf("scope missing address/slots %v", addrString) - } - var address = addr(addrString) - // convert to common.Hash form - var slots []common.Hash - var slotMap = make(map[common.Hash]struct{}) - for _, slotString := range slotStrings { - s := slot(slotString) - slots = append(slots, s) - slotMap[s] = struct{}{} - } - // Check that the expected items are in the access list - for i, s := range slots { - if _, slotPresent := state.SlotInAccessList(address, s); !slotPresent { - t.Fatalf("input %d: scope missing slot %v (address %v)", i, s, addrString) - } - } - // Check that no extra elements are in the access list - index := state.accessList.addresses[address] - if index >= 0 { - stateSlots := state.accessList.slots[index] - for s := range stateSlots { - if _, slotPresent := slotMap[s]; !slotPresent { - t.Fatalf("scope has extra slot %v (address %v)", s, addrString) - } - } - } - } - - state.AddAddressToAccessList(addr("aa")) // 1 - state.AddSlotToAccessList(addr("bb"), slot("01")) // 2,3 - state.AddSlotToAccessList(addr("bb"), slot("02")) // 4 - verifyAddrs("aa", "bb") - verifySlots("bb", "01", "02") - - // Make a copy - stateCopy1 := state.Copy() - if exp, got := 4, state.journal.length(); exp != got { - t.Fatalf("journal length mismatch: have %d, want %d", got, exp) - } - - // same again, should cause no journal entries - state.AddSlotToAccessList(addr("bb"), slot("01")) - state.AddSlotToAccessList(addr("bb"), slot("02")) - state.AddAddressToAccessList(addr("aa")) - if exp, got := 4, state.journal.length(); exp != got { - t.Fatalf("journal length mismatch: have %d, want %d", got, exp) - } - // some new ones - state.AddSlotToAccessList(addr("bb"), slot("03")) // 5 - state.AddSlotToAccessList(addr("aa"), slot("01")) // 6 - state.AddSlotToAccessList(addr("cc"), slot("01")) // 7,8 - state.AddAddressToAccessList(addr("cc")) - if exp, got := 8, state.journal.length(); exp != got { - t.Fatalf("journal length mismatch: have %d, want %d", got, exp) - } - - verifyAddrs("aa", "bb", "cc") - verifySlots("aa", "01") - verifySlots("bb", "01", "02", "03") - verifySlots("cc", "01") - - // now start rolling back changes - state.journal.revert(state, 7) - if _, ok := state.SlotInAccessList(addr("cc"), slot("01")); ok { - t.Fatalf("slot present, expected missing") - } - verifyAddrs("aa", "bb", "cc") - verifySlots("aa", "01") - verifySlots("bb", "01", "02", "03") - - state.journal.revert(state, 6) - if state.AddressInAccessList(addr("cc")) { - t.Fatalf("addr present, expected missing") - } - verifyAddrs("aa", "bb") - verifySlots("aa", "01") - verifySlots("bb", "01", "02", "03") - - state.journal.revert(state, 5) - if _, ok := state.SlotInAccessList(addr("aa"), slot("01")); ok { - t.Fatalf("slot present, expected missing") - } - verifyAddrs("aa", "bb") - verifySlots("bb", "01", "02", "03") - - state.journal.revert(state, 4) - if _, ok := state.SlotInAccessList(addr("bb"), slot("03")); ok { - t.Fatalf("slot present, expected missing") - } - verifyAddrs("aa", "bb") - verifySlots("bb", "01", "02") - - state.journal.revert(state, 3) - if _, ok := state.SlotInAccessList(addr("bb"), slot("02")); ok { - t.Fatalf("slot present, expected missing") - } - verifyAddrs("aa", "bb") - verifySlots("bb", "01") - - state.journal.revert(state, 2) - if _, ok := state.SlotInAccessList(addr("bb"), slot("01")); ok { - t.Fatalf("slot present, expected missing") - } - verifyAddrs("aa", "bb") - - state.journal.revert(state, 1) - if state.AddressInAccessList(addr("bb")) { - t.Fatalf("addr present, expected missing") - } - verifyAddrs("aa") - - state.journal.revert(state, 0) - if state.AddressInAccessList(addr("aa")) { - t.Fatalf("addr present, expected missing") - } - if got, exp := len(state.accessList.addresses), 0; got != exp { - t.Fatalf("expected empty, got %d", got) - } - if got, exp := len(state.accessList.slots), 0; got != exp { - t.Fatalf("expected empty, got %d", got) - } - // Check the copy - // Make a copy - state = stateCopy1 - verifyAddrs("aa", "bb") - verifySlots("bb", "01", "02") - if got, exp := len(state.accessList.addresses), 2; got != exp { - t.Fatalf("expected empty, got %d", got) - } - if got, exp := len(state.accessList.slots), 1; got != exp { - t.Fatalf("expected empty, got %d", got) - } -} - -// Tests that account and storage tries are flushed in the correct order and that -// no data loss occurs. -func TestFlushOrderDataLoss(t *testing.T) { - // Create a state trie with many accounts and slots - var ( - memdb = rawdb.NewMemoryDatabase() - triedb = triedb.NewDatabase(memdb, nil) - statedb = NewDatabaseWithNodeDB(memdb, triedb) - state, _ = New(types.EmptyRootHash, statedb, nil) - ) - for a := byte(0); a < 10; a++ { - state.CreateAccount(common.Address{a}) - for s := byte(0); s < 10; s++ { - state.SetState(common.Address{a}, common.Hash{a, s}, common.Hash{a, s}) - } - } - root, err := state.Commit(0, false) - if err != nil { - t.Fatalf("failed to commit state trie: %v", err) - } - triedb.Reference(root, common.Hash{}) - if err := triedb.Cap(1024); err != nil { - t.Fatalf("failed to cap trie dirty cache: %v", err) - } - if err := triedb.Commit(root, false); err != nil { - t.Fatalf("failed to commit state trie: %v", err) - } - // Reopen the state trie from flushed disk and verify it - state, err = New(root, NewDatabase(memdb), nil) - if err != nil { - t.Fatalf("failed to reopen state trie: %v", err) - } - for a := byte(0); a < 10; a++ { - for s := byte(0); s < 10; s++ { - if have := state.GetState(common.Address{a}, common.Hash{a, s}); have != (common.Hash{a, s}) { - t.Errorf("account %d: slot %d: state mismatch: have %x, want %x", a, s, have, common.Hash{a, s}) - } - } - } -} - -func TestStateDBTransientStorage(t *testing.T) { - memDb := rawdb.NewMemoryDatabase() - db := NewDatabase(memDb) - state, _ := New(types.EmptyRootHash, db, nil) - - key := common.Hash{0x01} - value := common.Hash{0x02} - addr := common.Address{} - - state.SetTransientState(addr, key, value) - if exp, got := 1, state.journal.length(); exp != got { - t.Fatalf("journal length mismatch: have %d, want %d", got, exp) - } - // the retrieved value should equal what was set - if got := state.GetTransientState(addr, key); got != value { - t.Fatalf("transient storage mismatch: have %x, want %x", got, value) - } - - // revert the transient state being set and then check that the - // value is now the empty hash - state.journal.revert(state, 0) - if got, exp := state.GetTransientState(addr, key), (common.Hash{}); exp != got { - t.Fatalf("transient storage mismatch: have %x, want %x", got, exp) - } - - // set transient state and then copy the statedb and ensure that - // the transient state is copied - state.SetTransientState(addr, key, value) - cpy := state.Copy() - if got := cpy.GetTransientState(addr, key); got != value { - t.Fatalf("transient storage mismatch: have %x, want %x", got, value) - } -} - -func TestResetObject(t *testing.T) { - var ( - disk = rawdb.NewMemoryDatabase() - tdb = triedb.NewDatabase(disk, nil) - db = NewDatabaseWithNodeDB(disk, tdb) - snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) - state, _ = New(types.EmptyRootHash, db, snaps) - addr = common.HexToAddress("0x1") - slotA = common.HexToHash("0x1") - slotB = common.HexToHash("0x2") - ) - // Initialize account with balance and storage in first transaction. - state.SetBalance(addr, uint256.NewInt(1)) - state.SetState(addr, slotA, common.BytesToHash([]byte{0x1})) - state.IntermediateRoot(true) - - // Reset account and mutate balance and storages - state.CreateAccount(addr) - state.SetBalance(addr, uint256.NewInt(2)) - state.SetState(addr, slotB, common.BytesToHash([]byte{0x2})) - root, _ := state.Commit(0, true) - - // Ensure the original account is wiped properly - snap := snaps.Snapshot(root) - slot, _ := snap.Storage(crypto.Keccak256Hash(addr.Bytes()), crypto.Keccak256Hash(slotA.Bytes())) - if len(slot) != 0 { - t.Fatalf("Unexpected storage slot") - } - slot, _ = snap.Storage(crypto.Keccak256Hash(addr.Bytes()), crypto.Keccak256Hash(slotB.Bytes())) - if !bytes.Equal(slot, []byte{0x2}) { - t.Fatalf("Unexpected storage slot value %v", slot) - } -} - -func TestDeleteStorage(t *testing.T) { - var ( - disk = rawdb.NewMemoryDatabase() - tdb = triedb.NewDatabase(disk, nil) - db = NewDatabaseWithNodeDB(disk, tdb) - snaps, _ = snapshot.New(snapshot.Config{CacheSize: 10}, disk, tdb, types.EmptyRootHash) - state, _ = New(types.EmptyRootHash, db, snaps) - addr = common.HexToAddress("0x1") - ) - // Initialize account and populate storage - state.SetBalance(addr, uint256.NewInt(1)) - state.CreateAccount(addr) - for i := 0; i < 1000; i++ { - slot := common.Hash(uint256.NewInt(uint64(i)).Bytes32()) - value := common.Hash(uint256.NewInt(uint64(10 * i)).Bytes32()) - state.SetState(addr, slot, value) - } - root, _ := state.Commit(0, true) - // Init phase done, create two states, one with snap and one without - fastState, _ := New(root, db, snaps) - slowState, _ := New(root, db, nil) - - obj := fastState.getOrNewStateObject(addr) - storageRoot := obj.data.Root - - _, _, fastNodes, err := fastState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot) - if err != nil { - t.Fatal(err) - } - - _, _, slowNodes, err := slowState.deleteStorage(addr, crypto.Keccak256Hash(addr[:]), storageRoot) - if err != nil { - t.Fatal(err) - } - check := func(set *trienode.NodeSet) string { - var a []string - set.ForEachWithOrder(func(path string, n *trienode.Node) { - if n.Hash != (common.Hash{}) { - t.Fatal("delete should have empty hashes") - } - if len(n.Blob) != 0 { - t.Fatal("delete should have have empty blobs") - } - a = append(a, fmt.Sprintf("%x", path)) - }) - return strings.Join(a, ",") - } - slowRes := check(slowNodes) - fastRes := check(fastNodes) - if slowRes != fastRes { - t.Fatalf("difference found:\nfast: %v\nslow: %v\n", fastRes, slowRes) - } -} diff --git a/builder/core/state/sync.go b/builder/core/state/sync.go deleted file mode 100644 index 411b54eab..000000000 --- a/builder/core/state/sync.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 state - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -// NewStateSync creates a new state trie download scheduler. -func NewStateSync(root common.Hash, database ethdb.KeyValueReader, onLeaf func(keys [][]byte, leaf []byte) error, scheme string) *trie.Sync { - // Register the storage slot callback if the external callback is specified. - var onSlot func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error - if onLeaf != nil { - onSlot = func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error { - return onLeaf(keys, leaf) - } - } - // Register the account callback to connect the state trie and the storage - // trie belongs to the contract. - var syncer *trie.Sync - onAccount := func(keys [][]byte, path []byte, leaf []byte, parent common.Hash, parentPath []byte) error { - if onLeaf != nil { - if err := onLeaf(keys, leaf); err != nil { - return err - } - } - var obj types.StateAccount - if err := rlp.DecodeBytes(leaf, &obj); err != nil { - return err - } - syncer.AddSubTrie(obj.Root, path, parent, parentPath, onSlot) - syncer.AddCodeEntry(common.BytesToHash(obj.CodeHash), path, parent, parentPath) - return nil - } - syncer = trie.NewSync(root, database, onAccount, scheme) - return syncer -} diff --git a/builder/core/state/sync_test.go b/builder/core/state/sync_test.go deleted file mode 100644 index 052c16657..000000000 --- a/builder/core/state/sync_test.go +++ /dev/null @@ -1,747 +0,0 @@ -// 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 state - -import ( - "bytes" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/hashdb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" -) - -// testAccount is the data associated with an account used by the state tests. -type testAccount struct { - address common.Address - balance *uint256.Int - nonce uint64 - code []byte -} - -// makeTestState create a sample test state to test node-wise reconstruction. -func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, common.Hash, []*testAccount) { - // Create an empty state - config := &triedb.Config{Preimages: true} - if scheme == rawdb.PathScheme { - config.PathDB = pathdb.Defaults - } else { - config.HashDB = hashdb.Defaults - } - db := rawdb.NewMemoryDatabase() - nodeDb := triedb.NewDatabase(db, config) - sdb := NewDatabaseWithNodeDB(db, nodeDb) - state, _ := New(types.EmptyRootHash, sdb, nil) - - // Fill it with some arbitrary data - var accounts []*testAccount - for i := byte(0); i < 96; i++ { - obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i})) - acc := &testAccount{address: common.BytesToAddress([]byte{i})} - - obj.AddBalance(uint256.NewInt(uint64(11 * i))) - acc.balance = uint256.NewInt(uint64(11 * i)) - - obj.SetNonce(uint64(42 * i)) - acc.nonce = uint64(42 * i) - - if i%3 == 0 { - obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i}) - acc.code = []byte{i, i, i, i, i} - } - if i%5 == 0 { - for j := byte(0); j < 5; j++ { - hash := crypto.Keccak256Hash([]byte{i, i, i, i, i, j, j}) - obj.SetState(hash, hash) - } - } - accounts = append(accounts, acc) - } - root, _ := state.Commit(0, false) - - // Return the generated state - return db, sdb, nodeDb, root, accounts -} - -// checkStateAccounts cross references a reconstructed state with an expected -// account array. -func checkStateAccounts(t *testing.T, db ethdb.Database, scheme string, root common.Hash, accounts []*testAccount) { - var config triedb.Config - if scheme == rawdb.PathScheme { - config.PathDB = pathdb.Defaults - } - // Check root availability and state contents - state, err := New(root, NewDatabaseWithConfig(db, &config), nil) - if err != nil { - t.Fatalf("failed to create state trie at %x: %v", root, err) - } - if err := checkStateConsistency(db, scheme, root); err != nil { - t.Fatalf("inconsistent state trie at %x: %v", root, err) - } - for i, acc := range accounts { - if balance := state.GetBalance(acc.address); balance.Cmp(acc.balance) != 0 { - t.Errorf("account %d: balance mismatch: have %v, want %v", i, balance, acc.balance) - } - if nonce := state.GetNonce(acc.address); nonce != acc.nonce { - t.Errorf("account %d: nonce mismatch: have %v, want %v", i, nonce, acc.nonce) - } - if code := state.GetCode(acc.address); !bytes.Equal(code, acc.code) { - t.Errorf("account %d: code mismatch: have %x, want %x", i, code, acc.code) - } - } -} - -// checkStateConsistency checks that all data of a state root is present. -func checkStateConsistency(db ethdb.Database, scheme string, root common.Hash) error { - config := &triedb.Config{Preimages: true} - if scheme == rawdb.PathScheme { - config.PathDB = pathdb.Defaults - } - state, err := New(root, NewDatabaseWithConfig(db, config), nil) - if err != nil { - return err - } - it := newNodeIterator(state) - for it.Next() { - } - return it.Error -} - -// Tests that an empty state is not scheduled for syncing. -func TestEmptyStateSync(t *testing.T) { - dbA := triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil) - dbB := triedb.NewDatabase(rawdb.NewMemoryDatabase(), &triedb.Config{PathDB: pathdb.Defaults}) - - sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbA.Scheme()) - if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { - t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) - } - sync = NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, dbB.Scheme()) - if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { - t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) - } -} - -// Tests that given a root hash, a state can sync iteratively on a single thread, -// requesting retrieval tasks and returning all of them in one go. -func TestIterativeStateSyncIndividual(t *testing.T) { - testIterativeStateSync(t, 1, false, false, rawdb.HashScheme) - testIterativeStateSync(t, 1, false, false, rawdb.PathScheme) -} -func TestIterativeStateSyncBatched(t *testing.T) { - testIterativeStateSync(t, 100, false, false, rawdb.HashScheme) - testIterativeStateSync(t, 100, false, false, rawdb.PathScheme) -} -func TestIterativeStateSyncIndividualFromDisk(t *testing.T) { - testIterativeStateSync(t, 1, true, false, rawdb.HashScheme) - testIterativeStateSync(t, 1, true, false, rawdb.PathScheme) -} -func TestIterativeStateSyncBatchedFromDisk(t *testing.T) { - testIterativeStateSync(t, 100, true, false, rawdb.HashScheme) - testIterativeStateSync(t, 100, true, false, rawdb.PathScheme) -} -func TestIterativeStateSyncIndividualByPath(t *testing.T) { - testIterativeStateSync(t, 1, false, true, rawdb.HashScheme) - testIterativeStateSync(t, 1, false, true, rawdb.PathScheme) -} -func TestIterativeStateSyncBatchedByPath(t *testing.T) { - testIterativeStateSync(t, 100, false, true, rawdb.HashScheme) - testIterativeStateSync(t, 100, false, true, rawdb.PathScheme) -} - -// stateElement represents the element in the state trie(bytecode or trie node). -type stateElement struct { - path string - hash common.Hash - code common.Hash - syncPath trie.SyncPath -} - -func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, scheme string) { - // Create a random state to copy - srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) - if commit { - ndb.Commit(srcRoot, false) - } - srcTrie, _ := trie.New(trie.StateTrieID(srcRoot), ndb) - - // Create a destination state and sync with the scheduler - dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme()) - - var ( - nodeElements []stateElement - codeElements []stateElement - ) - paths, nodes, codes := sched.Missing(count) - for i := 0; i < len(paths); i++ { - nodeElements = append(nodeElements, stateElement{ - path: paths[i], - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(paths[i])), - }) - } - for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{code: codes[i]}) - } - reader, err := ndb.Reader(srcRoot) - if err != nil { - t.Fatalf("state is not existent, %#x", srcRoot) - } - for len(nodeElements)+len(codeElements) > 0 { - var ( - nodeResults = make([]trie.NodeSyncResult, len(nodeElements)) - codeResults = make([]trie.CodeSyncResult, len(codeElements)) - ) - for i, element := range codeElements { - data, err := srcDb.ContractCode(common.Address{}, element.code) - if err != nil { - t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code) - } - codeResults[i] = trie.CodeSyncResult{Hash: element.code, Data: data} - } - for i, node := range nodeElements { - if bypath { - if len(node.syncPath) == 1 { - data, _, err := srcTrie.GetNode(node.syncPath[0]) - if err != nil { - t.Fatalf("failed to retrieve node data for path %x: %v", node.syncPath[0], err) - } - nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data} - } else { - var acc types.StateAccount - if err := rlp.DecodeBytes(srcTrie.MustGet(node.syncPath[0]), &acc); err != nil { - t.Fatalf("failed to decode account on path %x: %v", node.syncPath[0], err) - } - id := trie.StorageTrieID(srcRoot, common.BytesToHash(node.syncPath[0]), acc.Root) - stTrie, err := trie.New(id, ndb) - if err != nil { - t.Fatalf("failed to retrieve storage trie for path %x: %v", node.syncPath[1], err) - } - data, _, err := stTrie.GetNode(node.syncPath[1]) - if err != nil { - t.Fatalf("failed to retrieve node data for path %x: %v", node.syncPath[1], err) - } - nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data} - } - } else { - owner, inner := trie.ResolvePath([]byte(node.path)) - data, err := reader.Node(owner, inner, node.hash) - if err != nil { - t.Fatalf("failed to retrieve node data for key %v", []byte(node.path)) - } - nodeResults[i] = trie.NodeSyncResult{Path: node.path, Data: data} - } - } - for _, result := range codeResults { - if err := sched.ProcessCode(result); err != nil { - t.Errorf("failed to process result %v", err) - } - } - for _, result := range nodeResults { - if err := sched.ProcessNode(result); err != nil { - t.Errorf("failed to process result %v", err) - } - } - batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { - t.Fatalf("failed to commit data: %v", err) - } - batch.Write() - - paths, nodes, codes = sched.Missing(count) - nodeElements = nodeElements[:0] - for i := 0; i < len(paths); i++ { - nodeElements = append(nodeElements, stateElement{ - path: paths[i], - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(paths[i])), - }) - } - codeElements = codeElements[:0] - for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{ - code: codes[i], - }) - } - } - // Copy the preimages from source db in order to traverse the state. - srcDb.TrieDB().WritePreimages() - copyPreimages(srcDisk, dstDb) - - // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) -} - -// Tests that the trie scheduler can correctly reconstruct the state even if only -// partial results are returned, and the others sent only later. -func TestIterativeDelayedStateSync(t *testing.T) { - testIterativeDelayedStateSync(t, rawdb.HashScheme) - testIterativeDelayedStateSync(t, rawdb.PathScheme) -} - -func testIterativeDelayedStateSync(t *testing.T, scheme string) { - // Create a random state to copy - srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) - - // Create a destination state and sync with the scheduler - dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme()) - - var ( - nodeElements []stateElement - codeElements []stateElement - ) - paths, nodes, codes := sched.Missing(0) - for i := 0; i < len(paths); i++ { - nodeElements = append(nodeElements, stateElement{ - path: paths[i], - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(paths[i])), - }) - } - for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{code: codes[i]}) - } - reader, err := ndb.Reader(srcRoot) - if err != nil { - t.Fatalf("state is not existent, %#x", srcRoot) - } - for len(nodeElements)+len(codeElements) > 0 { - // Sync only half of the scheduled nodes - var nodeProcessed int - var codeProcessed int - if len(codeElements) > 0 { - codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1) - for i, element := range codeElements[:len(codeResults)] { - data, err := srcDb.ContractCode(common.Address{}, element.code) - if err != nil { - t.Fatalf("failed to retrieve contract bytecode for %x", element.code) - } - codeResults[i] = trie.CodeSyncResult{Hash: element.code, Data: data} - } - for _, result := range codeResults { - if err := sched.ProcessCode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - codeProcessed = len(codeResults) - } - if len(nodeElements) > 0 { - nodeResults := make([]trie.NodeSyncResult, len(nodeElements)/2+1) - for i, element := range nodeElements[:len(nodeResults)] { - owner, inner := trie.ResolvePath([]byte(element.path)) - data, err := reader.Node(owner, inner, element.hash) - if err != nil { - t.Fatalf("failed to retrieve contract bytecode for %x", element.code) - } - nodeResults[i] = trie.NodeSyncResult{Path: element.path, Data: data} - } - for _, result := range nodeResults { - if err := sched.ProcessNode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - nodeProcessed = len(nodeResults) - } - batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { - t.Fatalf("failed to commit data: %v", err) - } - batch.Write() - - paths, nodes, codes = sched.Missing(0) - nodeElements = nodeElements[nodeProcessed:] - for i := 0; i < len(paths); i++ { - nodeElements = append(nodeElements, stateElement{ - path: paths[i], - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(paths[i])), - }) - } - codeElements = codeElements[codeProcessed:] - for i := 0; i < len(codes); i++ { - codeElements = append(codeElements, stateElement{ - code: codes[i], - }) - } - } - // Copy the preimages from source db in order to traverse the state. - srcDb.TrieDB().WritePreimages() - copyPreimages(srcDisk, dstDb) - - // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) -} - -// Tests that given a root hash, a trie can sync iteratively on a single thread, -// requesting retrieval tasks and returning all of them in one go, however in a -// random order. -func TestIterativeRandomStateSyncIndividual(t *testing.T) { - testIterativeRandomStateSync(t, 1, rawdb.HashScheme) - testIterativeRandomStateSync(t, 1, rawdb.PathScheme) -} -func TestIterativeRandomStateSyncBatched(t *testing.T) { - testIterativeRandomStateSync(t, 100, rawdb.HashScheme) - testIterativeRandomStateSync(t, 100, rawdb.PathScheme) -} - -func testIterativeRandomStateSync(t *testing.T, count int, scheme string) { - // Create a random state to copy - srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) - - // Create a destination state and sync with the scheduler - dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme()) - - nodeQueue := make(map[string]stateElement) - codeQueue := make(map[common.Hash]struct{}) - paths, nodes, codes := sched.Missing(count) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - reader, err := ndb.Reader(srcRoot) - if err != nil { - t.Fatalf("state is not existent, %#x", srcRoot) - } - for len(nodeQueue)+len(codeQueue) > 0 { - // Fetch all the queued nodes in a random order - if len(codeQueue) > 0 { - results := make([]trie.CodeSyncResult, 0, len(codeQueue)) - for hash := range codeQueue { - data, err := srcDb.ContractCode(common.Address{}, hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x", hash) - } - results = append(results, trie.CodeSyncResult{Hash: hash, Data: data}) - } - for _, result := range results { - if err := sched.ProcessCode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - if len(nodeQueue) > 0 { - results := make([]trie.NodeSyncResult, 0, len(nodeQueue)) - for path, element := range nodeQueue { - owner, inner := trie.ResolvePath([]byte(element.path)) - data, err := reader.Node(owner, inner, element.hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x %v %v", element.hash, []byte(element.path), element.path) - } - results = append(results, trie.NodeSyncResult{Path: path, Data: data}) - } - for _, result := range results { - if err := sched.ProcessNode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { - t.Fatalf("failed to commit data: %v", err) - } - batch.Write() - - nodeQueue = make(map[string]stateElement) - codeQueue = make(map[common.Hash]struct{}) - paths, nodes, codes := sched.Missing(count) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - } - // Copy the preimages from source db in order to traverse the state. - srcDb.TrieDB().WritePreimages() - copyPreimages(srcDisk, dstDb) - - // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) -} - -// Tests that the trie scheduler can correctly reconstruct the state even if only -// partial results are returned (Even those randomly), others sent only later. -func TestIterativeRandomDelayedStateSync(t *testing.T) { - testIterativeRandomDelayedStateSync(t, rawdb.HashScheme) - testIterativeRandomDelayedStateSync(t, rawdb.PathScheme) -} - -func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) { - // Create a random state to copy - srcDisk, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) - - // Create a destination state and sync with the scheduler - dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme()) - - nodeQueue := make(map[string]stateElement) - codeQueue := make(map[common.Hash]struct{}) - paths, nodes, codes := sched.Missing(0) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - reader, err := ndb.Reader(srcRoot) - if err != nil { - t.Fatalf("state is not existent, %#x", srcRoot) - } - for len(nodeQueue)+len(codeQueue) > 0 { - // Sync only half of the scheduled nodes, even those in random order - if len(codeQueue) > 0 { - results := make([]trie.CodeSyncResult, 0, len(codeQueue)/2+1) - for hash := range codeQueue { - delete(codeQueue, hash) - - data, err := srcDb.ContractCode(common.Address{}, hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x", hash) - } - results = append(results, trie.CodeSyncResult{Hash: hash, Data: data}) - - if len(results) >= cap(results) { - break - } - } - for _, result := range results { - if err := sched.ProcessCode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - if len(nodeQueue) > 0 { - results := make([]trie.NodeSyncResult, 0, len(nodeQueue)/2+1) - for path, element := range nodeQueue { - delete(nodeQueue, path) - - owner, inner := trie.ResolvePath([]byte(element.path)) - data, err := reader.Node(owner, inner, element.hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x", element.hash) - } - results = append(results, trie.NodeSyncResult{Path: path, Data: data}) - - if len(results) >= cap(results) { - break - } - } - // Feed the retrieved results back and queue new tasks - for _, result := range results { - if err := sched.ProcessNode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { - t.Fatalf("failed to commit data: %v", err) - } - batch.Write() - - paths, nodes, codes := sched.Missing(0) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - } - // Copy the preimages from source db in order to traverse the state. - srcDb.TrieDB().WritePreimages() - copyPreimages(srcDisk, dstDb) - - // Cross check that the two states are in sync - checkStateAccounts(t, dstDb, ndb.Scheme(), srcRoot, srcAccounts) -} - -// Tests that at any point in time during a sync, only complete sub-tries are in -// the database. -func TestIncompleteStateSync(t *testing.T) { - testIncompleteStateSync(t, rawdb.HashScheme) - testIncompleteStateSync(t, rawdb.PathScheme) -} - -func testIncompleteStateSync(t *testing.T, scheme string) { - // Create a random state to copy - db, srcDb, ndb, srcRoot, srcAccounts := makeTestState(scheme) - - // isCodeLookup to save some hashing - var isCode = make(map[common.Hash]struct{}) - for _, acc := range srcAccounts { - if len(acc.code) > 0 { - isCode[crypto.Keccak256Hash(acc.code)] = struct{}{} - } - } - isCode[types.EmptyCodeHash] = struct{}{} - - // Create a destination state and sync with the scheduler - dstDb := rawdb.NewMemoryDatabase() - sched := NewStateSync(srcRoot, dstDb, nil, ndb.Scheme()) - - var ( - addedCodes []common.Hash - addedPaths []string - addedHashes []common.Hash - ) - reader, err := ndb.Reader(srcRoot) - if err != nil { - t.Fatalf("state is not available %x", srcRoot) - } - nodeQueue := make(map[string]stateElement) - codeQueue := make(map[common.Hash]struct{}) - paths, nodes, codes := sched.Missing(1) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - for len(nodeQueue)+len(codeQueue) > 0 { - // Fetch a batch of state nodes - if len(codeQueue) > 0 { - results := make([]trie.CodeSyncResult, 0, len(codeQueue)) - for hash := range codeQueue { - data, err := srcDb.ContractCode(common.Address{}, hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x", hash) - } - results = append(results, trie.CodeSyncResult{Hash: hash, Data: data}) - addedCodes = append(addedCodes, hash) - } - // Process each of the state nodes - for _, result := range results { - if err := sched.ProcessCode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - if len(nodeQueue) > 0 { - results := make([]trie.NodeSyncResult, 0, len(nodeQueue)) - for path, element := range nodeQueue { - owner, inner := trie.ResolvePath([]byte(element.path)) - data, err := reader.Node(owner, inner, element.hash) - if err != nil { - t.Fatalf("failed to retrieve node data for %x", element.hash) - } - results = append(results, trie.NodeSyncResult{Path: path, Data: data}) - - if element.hash != srcRoot { - addedPaths = append(addedPaths, element.path) - addedHashes = append(addedHashes, element.hash) - } - } - // Process each of the state nodes - for _, result := range results { - if err := sched.ProcessNode(result); err != nil { - t.Fatalf("failed to process result %v", err) - } - } - } - batch := dstDb.NewBatch() - if err := sched.Commit(batch); err != nil { - t.Fatalf("failed to commit data: %v", err) - } - batch.Write() - - // Fetch the next batch to retrieve - nodeQueue = make(map[string]stateElement) - codeQueue = make(map[common.Hash]struct{}) - paths, nodes, codes := sched.Missing(1) - for i, path := range paths { - nodeQueue[path] = stateElement{ - path: path, - hash: nodes[i], - syncPath: trie.NewSyncPath([]byte(path)), - } - } - for _, hash := range codes { - codeQueue[hash] = struct{}{} - } - } - // Copy the preimages from source db in order to traverse the state. - srcDb.TrieDB().WritePreimages() - copyPreimages(db, dstDb) - - // Sanity check that removing any node from the database is detected - for _, node := range addedCodes { - val := rawdb.ReadCode(dstDb, node) - rawdb.DeleteCode(dstDb, node) - if err := checkStateConsistency(dstDb, ndb.Scheme(), srcRoot); err == nil { - t.Errorf("trie inconsistency not caught, missing: %x", node) - } - rawdb.WriteCode(dstDb, node, val) - } - for i, path := range addedPaths { - owner, inner := trie.ResolvePath([]byte(path)) - hash := addedHashes[i] - val := rawdb.ReadTrieNode(dstDb, owner, inner, hash, scheme) - if val == nil { - t.Error("missing trie node") - } - rawdb.DeleteTrieNode(dstDb, owner, inner, hash, scheme) - if err := checkStateConsistency(dstDb, scheme, srcRoot); err == nil { - t.Errorf("trie inconsistency not caught, missing: %v", path) - } - rawdb.WriteTrieNode(dstDb, owner, inner, hash, val, scheme) - } -} - -func copyPreimages(srcDb, dstDb ethdb.Database) { - it := srcDb.NewIterator(rawdb.PreimagePrefix, nil) - defer it.Release() - - preimages := make(map[common.Hash][]byte) - for it.Next() { - hash := it.Key()[len(rawdb.PreimagePrefix):] - preimages[common.BytesToHash(hash)] = common.CopyBytes(it.Value()) - } - rawdb.WritePreimages(dstDb, preimages) -} diff --git a/builder/core/state/transient_storage.go b/builder/core/state/transient_storage.go deleted file mode 100644 index 66e563efa..000000000 --- a/builder/core/state/transient_storage.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 state - -import ( - "github.com/ethereum/go-ethereum/common" -) - -// transientStorage is a representation of EIP-1153 "Transient Storage". -type transientStorage map[common.Address]Storage - -// newTransientStorage creates a new instance of a transientStorage. -func newTransientStorage() transientStorage { - return make(transientStorage) -} - -// Set sets the transient-storage `value` for `key` at the given `addr`. -func (t transientStorage) Set(addr common.Address, key, value common.Hash) { - if _, ok := t[addr]; !ok { - t[addr] = make(Storage) - } - t[addr][key] = value -} - -// Get gets the transient storage for `key` at the given `addr`. -func (t transientStorage) Get(addr common.Address, key common.Hash) common.Hash { - val, ok := t[addr] - if !ok { - return common.Hash{} - } - return val[key] -} - -// Copy does a deep copy of the transientStorage -func (t transientStorage) Copy() transientStorage { - storage := make(transientStorage) - for key, value := range t { - storage[key] = value.Copy() - } - return storage -} diff --git a/builder/core/state/trie_prefetcher.go b/builder/core/state/trie_prefetcher.go deleted file mode 100644 index c2a49417d..000000000 --- a/builder/core/state/trie_prefetcher.go +++ /dev/null @@ -1,365 +0,0 @@ -// 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 state - -import ( - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" -) - -var ( - // triePrefetchMetricsPrefix is the prefix under which to publish the metrics. - triePrefetchMetricsPrefix = "trie/prefetch/" -) - -// triePrefetcher is an active prefetcher, which receives accounts or storage -// items and does trie-loading of them. The goal is to get as much useful content -// into the caches as possible. -// -// Note, the prefetcher's API is not thread safe. -type triePrefetcher struct { - db Database // Database to fetch trie nodes through - root common.Hash // Root hash of the account trie for metrics - fetches map[string]Trie // Partially or fully fetched tries. Only populated for inactive copies. - fetchers map[string]*subfetcher // Subfetchers for each trie - - deliveryMissMeter metrics.Meter - accountLoadMeter metrics.Meter - accountDupMeter metrics.Meter - accountSkipMeter metrics.Meter - accountWasteMeter metrics.Meter - storageLoadMeter metrics.Meter - storageDupMeter metrics.Meter - storageSkipMeter metrics.Meter - storageWasteMeter metrics.Meter -} - -func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePrefetcher { - prefix := triePrefetchMetricsPrefix + namespace - p := &triePrefetcher{ - db: db, - root: root, - fetchers: make(map[string]*subfetcher), // Active prefetchers use the fetchers map - - deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil), - accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil), - accountDupMeter: metrics.GetOrRegisterMeter(prefix+"/account/dup", nil), - accountSkipMeter: metrics.GetOrRegisterMeter(prefix+"/account/skip", nil), - accountWasteMeter: metrics.GetOrRegisterMeter(prefix+"/account/waste", nil), - storageLoadMeter: metrics.GetOrRegisterMeter(prefix+"/storage/load", nil), - storageDupMeter: metrics.GetOrRegisterMeter(prefix+"/storage/dup", nil), - storageSkipMeter: metrics.GetOrRegisterMeter(prefix+"/storage/skip", nil), - storageWasteMeter: metrics.GetOrRegisterMeter(prefix+"/storage/waste", nil), - } - return p -} - -// close iterates over all the subfetchers, aborts any that were left spinning -// and reports the stats to the metrics subsystem. -func (p *triePrefetcher) close() { - for _, fetcher := range p.fetchers { - fetcher.abort() // safe to do multiple times - - if metrics.Enabled { - if fetcher.root == p.root { - p.accountLoadMeter.Mark(int64(len(fetcher.seen))) - p.accountDupMeter.Mark(int64(fetcher.dups)) - p.accountSkipMeter.Mark(int64(len(fetcher.tasks))) - - for _, key := range fetcher.used { - delete(fetcher.seen, string(key)) - } - p.accountWasteMeter.Mark(int64(len(fetcher.seen))) - } else { - p.storageLoadMeter.Mark(int64(len(fetcher.seen))) - p.storageDupMeter.Mark(int64(fetcher.dups)) - p.storageSkipMeter.Mark(int64(len(fetcher.tasks))) - - for _, key := range fetcher.used { - delete(fetcher.seen, string(key)) - } - p.storageWasteMeter.Mark(int64(len(fetcher.seen))) - } - } - } - // Clear out all fetchers (will crash on a second call, deliberate) - p.fetchers = nil -} - -// copy creates a deep-but-inactive copy of the trie prefetcher. Any trie data -// already loaded will be copied over, but no goroutines will be started. This -// is mostly used in the miner which creates a copy of it's actively mutated -// state to be sealed while it may further mutate the state. -func (p *triePrefetcher) copy() *triePrefetcher { - copy := &triePrefetcher{ - db: p.db, - root: p.root, - fetches: make(map[string]Trie), // Active prefetchers use the fetches map - - deliveryMissMeter: p.deliveryMissMeter, - accountLoadMeter: p.accountLoadMeter, - accountDupMeter: p.accountDupMeter, - accountSkipMeter: p.accountSkipMeter, - accountWasteMeter: p.accountWasteMeter, - storageLoadMeter: p.storageLoadMeter, - storageDupMeter: p.storageDupMeter, - storageSkipMeter: p.storageSkipMeter, - storageWasteMeter: p.storageWasteMeter, - } - // If the prefetcher is already a copy, duplicate the data - if p.fetches != nil { - for root, fetch := range p.fetches { - if fetch == nil { - continue - } - copy.fetches[root] = p.db.CopyTrie(fetch) - } - return copy - } - // Otherwise we're copying an active fetcher, retrieve the current states - for id, fetcher := range p.fetchers { - copy.fetches[id] = fetcher.peek() - } - return copy -} - -// prefetch schedules a batch of trie items to prefetch. -func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte) { - // If the prefetcher is an inactive one, bail out - if p.fetches != nil { - return - } - // Active fetcher, schedule the retrievals - id := p.trieID(owner, root) - fetcher := p.fetchers[id] - if fetcher == nil { - fetcher = newSubfetcher(p.db, p.root, owner, root, addr) - p.fetchers[id] = fetcher - } - fetcher.schedule(keys) -} - -// trie returns the trie matching the root hash, or nil if the prefetcher doesn't -// have it. -func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie { - // If the prefetcher is inactive, return from existing deep copies - id := p.trieID(owner, root) - if p.fetches != nil { - trie := p.fetches[id] - if trie == nil { - p.deliveryMissMeter.Mark(1) - return nil - } - return p.db.CopyTrie(trie) - } - // Otherwise the prefetcher is active, bail if no trie was prefetched for this root - fetcher := p.fetchers[id] - if fetcher == nil { - p.deliveryMissMeter.Mark(1) - return nil - } - // Interrupt the prefetcher if it's by any chance still running and return - // a copy of any pre-loaded trie. - fetcher.abort() // safe to do multiple times - - trie := fetcher.peek() - if trie == nil { - p.deliveryMissMeter.Mark(1) - return nil - } - return trie -} - -// used marks a batch of state items used to allow creating statistics as to -// how useful or wasteful the prefetcher is. -func (p *triePrefetcher) used(owner common.Hash, root common.Hash, used [][]byte) { - if fetcher := p.fetchers[p.trieID(owner, root)]; fetcher != nil { - fetcher.used = used - } -} - -// trieID returns an unique trie identifier consists the trie owner and root hash. -func (p *triePrefetcher) trieID(owner common.Hash, root common.Hash) string { - trieID := make([]byte, common.HashLength*2) - copy(trieID, owner.Bytes()) - copy(trieID[common.HashLength:], root.Bytes()) - return string(trieID) -} - -// subfetcher is a trie fetcher goroutine responsible for pulling entries for a -// single trie. It is spawned when a new root is encountered and lives until the -// main prefetcher is paused and either all requested items are processed or if -// the trie being worked on is retrieved from the prefetcher. -type subfetcher struct { - db Database // Database to load trie nodes through - state common.Hash // Root hash of the state to prefetch - owner common.Hash // Owner of the trie, usually account hash - root common.Hash // Root hash of the trie to prefetch - addr common.Address // Address of the account that the trie belongs to - trie Trie // Trie being populated with nodes - - tasks [][]byte // Items queued up for retrieval - lock sync.Mutex // Lock protecting the task queue - - wake chan struct{} // Wake channel if a new task is scheduled - stop chan struct{} // Channel to interrupt processing - term chan struct{} // Channel to signal interruption - copy chan chan Trie // Channel to request a copy of the current trie - - seen map[string]struct{} // Tracks the entries already loaded - dups int // Number of duplicate preload tasks - used [][]byte // Tracks the entries used in the end -} - -// newSubfetcher creates a goroutine to prefetch state items belonging to a -// particular root hash. -func newSubfetcher(db Database, state common.Hash, owner common.Hash, root common.Hash, addr common.Address) *subfetcher { - sf := &subfetcher{ - db: db, - state: state, - owner: owner, - root: root, - addr: addr, - wake: make(chan struct{}, 1), - stop: make(chan struct{}), - term: make(chan struct{}), - copy: make(chan chan Trie), - seen: make(map[string]struct{}), - } - go sf.loop() - return sf -} - -// schedule adds a batch of trie keys to the queue to prefetch. -func (sf *subfetcher) schedule(keys [][]byte) { - // Append the tasks to the current queue - sf.lock.Lock() - sf.tasks = append(sf.tasks, keys...) - sf.lock.Unlock() - - // Notify the prefetcher, it's fine if it's already terminated - select { - case sf.wake <- struct{}{}: - default: - } -} - -// peek tries to retrieve a deep copy of the fetcher's trie in whatever form it -// is currently. -func (sf *subfetcher) peek() Trie { - ch := make(chan Trie) - select { - case sf.copy <- ch: - // Subfetcher still alive, return copy from it - return <-ch - - case <-sf.term: - // Subfetcher already terminated, return a copy directly - if sf.trie == nil { - return nil - } - return sf.db.CopyTrie(sf.trie) - } -} - -// abort interrupts the subfetcher immediately. It is safe to call abort multiple -// times but it is not thread safe. -func (sf *subfetcher) abort() { - select { - case <-sf.stop: - default: - close(sf.stop) - } - <-sf.term -} - -// loop waits for new tasks to be scheduled and keeps loading them until it runs -// out of tasks or its underlying trie is retrieved for committing. -func (sf *subfetcher) loop() { - // No matter how the loop stops, signal anyone waiting that it's terminated - defer close(sf.term) - - // Start by opening the trie and stop processing if it fails - if sf.owner == (common.Hash{}) { - trie, err := sf.db.OpenTrie(sf.root) - if err != nil { - log.Warn("Trie prefetcher failed opening trie", "root", sf.root, "err", err) - return - } - sf.trie = trie - } else { - // The trie argument can be nil as verkle doesn't support prefetching - // yet. TODO FIX IT(rjl493456442), otherwise code will panic here. - trie, err := sf.db.OpenStorageTrie(sf.state, sf.addr, sf.root, nil) - if err != nil { - log.Warn("Trie prefetcher failed opening trie", "root", sf.root, "err", err) - return - } - sf.trie = trie - } - // Trie opened successfully, keep prefetching items - for { - select { - case <-sf.wake: - // Subfetcher was woken up, retrieve any tasks to avoid spinning the lock - sf.lock.Lock() - tasks := sf.tasks - sf.tasks = nil - sf.lock.Unlock() - - // Prefetch any tasks until the loop is interrupted - for i, task := range tasks { - select { - case <-sf.stop: - // If termination is requested, add any leftover back and return - sf.lock.Lock() - sf.tasks = append(sf.tasks, tasks[i:]...) - sf.lock.Unlock() - return - - case ch := <-sf.copy: - // Somebody wants a copy of the current trie, grant them - ch <- sf.db.CopyTrie(sf.trie) - - default: - // No termination request yet, prefetch the next entry - if _, ok := sf.seen[string(task)]; ok { - sf.dups++ - } else { - if len(task) == common.AddressLength { - sf.trie.GetAccount(common.BytesToAddress(task)) - } else { - sf.trie.GetStorage(sf.addr, task) - } - sf.seen[string(task)] = struct{}{} - } - } - } - - case ch := <-sf.copy: - // Somebody wants a copy of the current trie, grant them - ch <- sf.db.CopyTrie(sf.trie) - - case <-sf.stop: - // Termination is requested, abort and leave remaining tasks - return - } - } -} diff --git a/builder/core/state/trie_prefetcher_test.go b/builder/core/state/trie_prefetcher_test.go deleted file mode 100644 index 711ec8325..000000000 --- a/builder/core/state/trie_prefetcher_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// 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 state - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/holiman/uint256" -) - -func filledStateDB() *StateDB { - state, _ := New(types.EmptyRootHash, NewDatabase(rawdb.NewMemoryDatabase()), nil) - - // Create an account and check if the retrieved balance is correct - addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe") - skey := common.HexToHash("aaa") - sval := common.HexToHash("bbb") - - state.SetBalance(addr, uint256.NewInt(42)) // Change the account trie - state.SetCode(addr, []byte("hello")) // Change an external metadata - state.SetState(addr, skey, sval) // Change the storage trie - for i := 0; i < 100; i++ { - sk := common.BigToHash(big.NewInt(int64(i))) - state.SetState(addr, sk, sk) // Change the storage trie - } - return state -} - -func TestCopyAndClose(t *testing.T) { - db := filledStateDB() - prefetcher := newTriePrefetcher(db.db, db.originalRoot, "") - skey := common.HexToHash("aaa") - prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - time.Sleep(1 * time.Second) - a := prefetcher.trie(common.Hash{}, db.originalRoot) - prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - b := prefetcher.trie(common.Hash{}, db.originalRoot) - cpy := prefetcher.copy() - cpy.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - cpy.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - c := cpy.trie(common.Hash{}, db.originalRoot) - prefetcher.close() - cpy2 := cpy.copy() - cpy2.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - d := cpy2.trie(common.Hash{}, db.originalRoot) - cpy.close() - cpy2.close() - if a.Hash() != b.Hash() || a.Hash() != c.Hash() || a.Hash() != d.Hash() { - t.Fatalf("Invalid trie, hashes should be equal: %v %v %v %v", a.Hash(), b.Hash(), c.Hash(), d.Hash()) - } -} - -func TestUseAfterClose(t *testing.T) { - db := filledStateDB() - prefetcher := newTriePrefetcher(db.db, db.originalRoot, "") - skey := common.HexToHash("aaa") - prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - a := prefetcher.trie(common.Hash{}, db.originalRoot) - prefetcher.close() - b := prefetcher.trie(common.Hash{}, db.originalRoot) - if a == nil { - t.Fatal("Prefetching before close should not return nil") - } - if b != nil { - t.Fatal("Trie after close should return nil") - } -} - -func TestCopyClose(t *testing.T) { - db := filledStateDB() - prefetcher := newTriePrefetcher(db.db, db.originalRoot, "") - skey := common.HexToHash("aaa") - prefetcher.prefetch(common.Hash{}, db.originalRoot, common.Address{}, [][]byte{skey.Bytes()}) - cpy := prefetcher.copy() - a := prefetcher.trie(common.Hash{}, db.originalRoot) - b := cpy.trie(common.Hash{}, db.originalRoot) - prefetcher.close() - c := prefetcher.trie(common.Hash{}, db.originalRoot) - d := cpy.trie(common.Hash{}, db.originalRoot) - if a == nil { - t.Fatal("Prefetching before close should not return nil") - } - if b == nil { - t.Fatal("Copy trie should return nil") - } - if c != nil { - t.Fatal("Trie after close should return nil") - } - if d == nil { - t.Fatal("Copy trie should not return nil") - } -} diff --git a/builder/core/state_prefetcher.go b/builder/core/state_prefetcher.go deleted file mode 100644 index ff867309d..000000000 --- a/builder/core/state_prefetcher.go +++ /dev/null @@ -1,94 +0,0 @@ -// 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 core - -import ( - "sync/atomic" - - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" -) - -// statePrefetcher is a basic Prefetcher, which blindly executes a block on top -// of an arbitrary state with the goal of prefetching potentially useful state -// data from disk before the main block processor start executing. -type statePrefetcher struct { - config *params.ChainConfig // Chain configuration options - bc *BlockChain // Canonical block chain - engine consensus.Engine // Consensus engine used for block rewards -} - -// newStatePrefetcher initialises a new statePrefetcher. -func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *statePrefetcher { - return &statePrefetcher{ - config: config, - bc: bc, - engine: engine, - } -} - -// Prefetch processes the state changes according to the Ethereum rules by running -// the transaction messages using the statedb, but any changes are discarded. The -// only goal is to pre-cache transaction signatures and state trie nodes. -func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) { - var ( - header = block.Header() - gaspool = new(GasPool).AddGas(block.GasLimit()) - blockContext = NewEVMBlockContext(header, p.bc, nil) - evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) - signer = types.MakeSigner(p.config, header.Number, header.Time) - ) - // Iterate over and process the individual transactions - byzantium := p.config.IsByzantium(block.Number()) - for i, tx := range block.Transactions() { - // If block precaching was interrupted, abort - if interrupt != nil && interrupt.Load() { - return - } - // Convert the transaction into an executable message and pre-cache its sender - msg, err := TransactionToMessage(tx, signer, header.BaseFee) - if err != nil { - return // Also invalid block, bail out - } - statedb.SetTxContext(tx.Hash(), i) - if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil { - return // Ugh, something went horribly wrong, bail out - } - // If we're pre-byzantium, pre-load trie nodes for the intermediate root - if !byzantium { - statedb.IntermediateRoot(true) - } - } - // If were post-byzantium, pre-load trie nodes for the final root hash - if byzantium { - statedb.IntermediateRoot(true) - } -} - -// precacheTransaction attempts to apply a transaction to the given state database -// and uses the input parameters for its environment. The goal is not to execute -// the transaction successfully, rather to warm up touched data slots. -func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { - // Update the evm with the new transaction context. - evm.Reset(NewEVMTxContext(msg), statedb) - // Add addresses to access list if applicable - _, err := ApplyMessage(evm, msg, gaspool) - return err -} diff --git a/builder/core/state_processor.go b/builder/core/state_processor.go deleted file mode 100644 index 30e8035d4..000000000 --- a/builder/core/state_processor.go +++ /dev/null @@ -1,261 +0,0 @@ -// 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 core - -import ( - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -// StateProcessor is a basic Processor, which takes care of transitioning -// state from one point to another. -// -// StateProcessor implements Processor. -type StateProcessor struct { - config *params.ChainConfig // Chain configuration options - bc *BlockChain // Canonical block chain - engine consensus.Engine // Consensus engine used for block rewards -} - -// NewStateProcessor initialises a new StateProcessor. -func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor { - return &StateProcessor{ - config: config, - bc: bc, - engine: engine, - } -} - -// Process processes the state changes according to the Ethereum rules by running -// the transaction messages using the statedb and applying any rewards to both -// the processor (coinbase) and any included uncles. -// -// Process returns the receipts and logs accumulated during the process and -// returns the amount of gas that was used in the process. If any of the -// transactions failed to execute due to insufficient gas it will return an error. -func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { - var ( - receipts types.Receipts - usedGas = new(uint64) - header = block.Header() - blockHash = block.Hash() - blockNumber = block.Number() - allLogs []*types.Log - gp = new(GasPool).AddGas(block.GasLimit()) - ) - // Mutate the block and state according to any hard-fork specs - if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { - misc.ApplyDAOHardFork(statedb) - } - var ( - context = NewEVMBlockContext(header, p.bc, nil) - vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) - signer = types.MakeSigner(p.config, header.Number, header.Time) - ) - if beaconRoot := block.BeaconRoot(); beaconRoot != nil { - ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) - } - // Iterate over and process the individual transactions - for i, tx := range block.Transactions() { - msg, err := TransactionToMessage(tx, signer, header.BaseFee) - if err != nil { - return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) - } - statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, nil) - if err != nil { - return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) - } - receipts = append(receipts, receipt) - allLogs = append(allLogs, receipt.Logs...) - } - // Fail if Shanghai not enabled and len(withdrawals) is non-zero. - withdrawals := block.Withdrawals() - if len(withdrawals) > 0 && !p.config.IsShanghai(block.Number(), block.Time()) { - return nil, nil, 0, errors.New("withdrawals before shanghai") - } - // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals) - - return receipts, allLogs, *usedGas, nil -} - -func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM, preFinalizeHook func() error) (*types.Receipt, error) { - // Create a new context to be used in the EVM environment. - txContext := NewEVMTxContext(msg) - evm.Reset(txContext, statedb) - - snapshot := statedb.Snapshot() - // Apply the transaction to the current state (included in the env). - result, err := ApplyMessage(evm, msg, gp) - if err != nil { - return nil, err - } - if preFinalizeHook != nil { - err = preFinalizeHook() - if err != nil { - statedb.RevertToSnapshot(snapshot) - return nil, err - } - } - - // Update the state with pending changes. - var root []byte - if config.IsByzantium(blockNumber) { - statedb.Finalise(true) - } else { - root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes() - } - *usedGas += result.UsedGas - - // Create a new receipt for the transaction, storing the intermediate root and gas used - // by the tx. - receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas} - if result.Failed() { - receipt.Status = types.ReceiptStatusFailed - } else { - receipt.Status = types.ReceiptStatusSuccessful - } - receipt.TxHash = tx.Hash() - receipt.GasUsed = result.UsedGas - - if tx.Type() == types.BlobTxType { - receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob) - receipt.BlobGasPrice = evm.Context.BlobBaseFee - } - - // If the transaction created a contract, store the creation address in the receipt. - if msg.To == nil { - receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) - } - - // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = blockHash - receipt.BlockNumber = blockNumber - receipt.TransactionIndex = uint(statedb.TxIndex()) - return receipt, err -} - -func applyTransactionWithResult(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, *ExecutionResult, error) { - // Create a new context to be used in the EVM environment. - txContext := NewEVMTxContext(msg) - evm.Reset(txContext, statedb) - - // Apply the transaction to the current state (included in the env). - result, err := ApplyMessage(evm, msg, gp) - if err != nil { - return nil, nil, err - } - - // Update the state with pending changes. - var root []byte - if config.IsByzantium(blockNumber) { - statedb.Finalise(true) - } else { - root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes() - } - *usedGas += result.UsedGas - - // Create a new receipt for the transaction, storing the intermediate root and gas used - // by the tx. - receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas} - if result.Failed() { - receipt.Status = types.ReceiptStatusFailed - } else { - receipt.Status = types.ReceiptStatusSuccessful - } - receipt.TxHash = tx.Hash() - receipt.GasUsed = result.UsedGas - - if tx.Type() == types.BlobTxType { - receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob) - receipt.BlobGasPrice = evm.Context.BlobBaseFee - } - - // If the transaction created a contract, store the creation address in the receipt. - if msg.To == nil { - receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce()) - } - - // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = blockHash - receipt.BlockNumber = blockNumber - receipt.TransactionIndex = uint(statedb.TxIndex()) - return receipt, result, err -} - -// ApplyTransaction attempts to apply a transaction to the given state database -// and uses the input parameters for its environment. It returns the receipt -// for the transaction, gas used and an error if the transaction failed, -// indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, preFinalizeHook func() error) (*types.Receipt, error) { - msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) - if err != nil { - return nil, err - } - // Create a new context to be used in the EVM environment - blockContext := NewEVMBlockContext(header, bc, author) - txContext := NewEVMTxContext(msg) - vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg) - return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, preFinalizeHook) -} - -func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, *ExecutionResult, error) { - msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) - if err != nil { - return nil, nil, err - } - // Create a new context to be used in the EVM environment - blockContext := NewEVMBlockContext(header, bc, author) - txContext := NewEVMTxContext(msg) - vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg) - return applyTransactionWithResult(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) -} - -// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root -// contract. This method is exported to be used in tests. -func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { - // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with - // the new root - msg := &Message{ - From: params.SystemAddress, - GasLimit: 30_000_000, - GasPrice: common.Big0, - GasFeeCap: common.Big0, - GasTipCap: common.Big0, - To: ¶ms.BeaconRootsStorageAddress, - Data: beaconRoot[:], - } - vmenv.Reset(NewEVMTxContext(msg), statedb) - statedb.AddAddressToAccessList(params.BeaconRootsStorageAddress) - _, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) - statedb.Finalise(true) -} diff --git a/builder/core/state_processor_test.go b/builder/core/state_processor_test.go deleted file mode 100644 index 7718c0cde..000000000 --- a/builder/core/state_processor_test.go +++ /dev/null @@ -1,424 +0,0 @@ -// 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 core - -import ( - "crypto/ecdsa" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" -) - -func u64(val uint64) *uint64 { return &val } - -// TestStateProcessorErrors tests the output from the 'core' errors -// as defined in core/error.go. These errors are generated when the -// blockchain imports bad blocks, meaning blocks which have valid headers but -// contain invalid transactions -func TestStateProcessorErrors(t *testing.T) { - var ( - config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - Ethash: new(params.EthashConfig), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - ShanghaiTime: new(uint64), - CancunTime: new(uint64), - } - signer = types.LatestSigner(config) - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020") - ) - var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction { - tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key) - return tx - } - var mkDynamicTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction { - tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ - Nonce: nonce, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Gas: gasLimit, - To: &to, - Value: big.NewInt(0), - }), signer, key1) - return tx - } - var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction { - tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ - Nonce: nonce, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Gas: gasLimit, - Value: big.NewInt(0), - Data: data, - }), signer, key1) - return tx - } - var mkBlobTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap, blobGasFeeCap *big.Int, hashes []common.Hash) *types.Transaction { - tx, err := types.SignTx(types.NewTx(&types.BlobTx{ - Nonce: nonce, - GasTipCap: uint256.MustFromBig(gasTipCap), - GasFeeCap: uint256.MustFromBig(gasFeeCap), - Gas: gasLimit, - To: to, - BlobHashes: hashes, - BlobFeeCap: uint256.MustFromBig(blobGasFeeCap), - Value: new(uint256.Int), - }), signer, key1) - if err != nil { - t.Fatal(err) - } - return tx - } - - { // Tests against a 'recent' chain definition - var ( - db = rawdb.NewMemoryDatabase() - gspec = &Genesis{ - Config: config, - Alloc: types.GenesisAlloc{ - common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: 0, - }, - common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): types.Account{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: math.MaxUint64, - }, - }, - } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) - tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} - ) - - defer blockchain.Stop() - bigNumber := new(big.Int).SetBytes(common.MaxHash.Bytes()) - tooBigNumber := new(big.Int).Set(bigNumber) - tooBigNumber.Add(tooBigNumber, common.Big1) - for i, tt := range []struct { - txs []*types.Transaction - want string - }{ - { // ErrNonceTooLow - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), - makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), - }, - want: "could not apply tx 1 [0x0026256b3939ed97e2c4a6f3fce8ecf83bdcfa6d507c47838c308a1fb0436f62]: nonce too low: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 0 state: 1", - }, - { // ErrNonceTooHigh - txs: []*types.Transaction{ - makeTx(key1, 100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0xdebad714ca7f363bd0d8121c4518ad48fa469ca81b0a081be3d10c17460f751b]: nonce too high: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 100 state: 0", - }, - { // ErrNonceMax - txs: []*types.Transaction{ - makeTx(key2, math.MaxUint64, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0x84ea18d60eb2bb3b040e3add0eb72f757727122cc257dd858c67cb6591a85986]: nonce has max value: address 0xfd0810DD14796680f72adf1a371963d0745BCc64, nonce: 18446744073709551615", - }, - { // ErrGasLimitReached - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", - }, - { // ErrInsufficientFundsForTransfer - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000", - }, - { // ErrInsufficientFunds - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(900000000000000000), nil), - }, - want: "could not apply tx 0 [0x4a69690c4b0cd85e64d0d9ea06302455b01e10a83db964d60281739752003440]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 18900000000000000000000", - }, - // ErrGasUintOverflow - // One missing 'core' error is ErrGasUintOverflow: "gas uint64 overflow", - // In order to trigger that one, we'd have to allocate a _huge_ chunk of data, such that the - // multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment - { // ErrIntrinsicGas - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0xcf3b049a0b516cb4f9274b3e2a264359e2ba53b2fb64b7bda2c634d5c9d01fca]: intrinsic gas too low: have 20000, want 21000", - }, - { // ErrGasLimitReached - txs: []*types.Transaction{ - makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil), - }, - want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached", - }, - { // ErrFeeCapTooLow - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(0), big.NewInt(0)), - }, - want: "could not apply tx 0 [0xc4ab868fef0c82ae0387b742aee87907f2d0fc528fc6ea0a021459fb0fc4a4a8]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 0, baseFee: 875000000", - }, - { // ErrTipVeryHigh - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, tooBigNumber, big.NewInt(1)), - }, - want: "could not apply tx 0 [0x15b8391b9981f266b32f3ab7da564bbeb3d6c21628364ea9b32a21139f89f712]: max priority fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas bit length: 257", - }, - { // ErrFeeCapVeryHigh - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), tooBigNumber), - }, - want: "could not apply tx 0 [0x48bc299b83fdb345c57478f239e89814bb3063eb4e4b49f3b6057a69255c16bd]: max fee per gas higher than 2^256-1: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas bit length: 257", - }, - { // ErrTipAboveFeeCap - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(2), big.NewInt(1)), - }, - want: "could not apply tx 0 [0xf987a31ff0c71895780a7612f965a0c8b056deb54e020bb44fa478092f14c9b4]: max priority fee per gas higher than max fee per gas: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxPriorityFeePerGas: 2, maxFeePerGas: 1", - }, - { // ErrInsufficientFunds - // Available balance: 1000000000000000000 - // Effective cost: 18375000021000 - // FeeCap * gas: 1050000000000000000 - // This test is designed to have the effective cost be covered by the balance, but - // the extended requirement on FeeCap*gas < balance to fail - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(50000000000000)), - }, - want: "could not apply tx 0 [0x413603cd096a87f41b1660d3ed3e27d62e1da78eac138961c0a1314ed43bd129]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1050000000000000000", - }, - { // Another ErrInsufficientFunds, this one to ensure that feecap/tip of max u256 is allowed - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas, bigNumber, bigNumber), - }, - want: "could not apply tx 0 [0xd82a0c2519acfeac9a948258c47e784acd20651d9d80f9a1c67b4137651c3a24]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 required balance exceeds 256 bits", - }, - { // ErrMaxInitCodeSizeExceeded - txs: []*types.Transaction{ - mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]), - }, - want: "could not apply tx 0 [0xd491405f06c92d118dd3208376fcee18a57c54bc52063ee4a26b1cf296857c25]: max initcode size exceeded: code size 49153 limit 49152", - }, - { // ErrIntrinsicGas: Not enough gas to cover init code - txs: []*types.Transaction{ - mkDynamicCreationTx(0, 54299, common.Big0, big.NewInt(params.InitialBaseFee), make([]byte, 320)), - }, - want: "could not apply tx 0 [0xfd49536a9b323769d8472fcb3ebb3689b707a349379baee3e2ee3fe7baae06a1]: intrinsic gas too low: have 54299, want 54300", - }, - { // ErrBlobFeeCapTooLow - txs: []*types.Transaction{ - mkBlobTx(0, common.Address{}, params.TxGas, big.NewInt(1), big.NewInt(1), big.NewInt(0), []common.Hash{(common.Hash{1})}), - }, - want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000", - }, - } { - block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) - _, err := blockchain.InsertChain(types.Blocks{block}) - if err == nil { - t.Fatal("block imported without errors") - } - if have, want := err.Error(), tt.want; have != want { - t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) - } - } - } - - // ErrTxTypeNotSupported, For this, we need an older chain - { - var ( - db = rawdb.NewMemoryDatabase() - gspec = &Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - }, - Alloc: types.GenesisAlloc{ - common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: 0, - }, - }, - } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - ) - defer blockchain.Stop() - for i, tt := range []struct { - txs []*types.Transaction - want string - }{ - { // ErrTxTypeNotSupported - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), - }, - want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported", - }, - } { - block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) - _, err := blockchain.InsertChain(types.Blocks{block}) - if err == nil { - t.Fatal("block imported without errors") - } - if have, want := err.Error(), tt.want; have != want { - t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) - } - } - } - - // ErrSenderNoEOA, for this we need the sender to have contract code - { - var ( - db = rawdb.NewMemoryDatabase() - gspec = &Genesis{ - Config: config, - Alloc: types.GenesisAlloc{ - common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): types.Account{ - Balance: big.NewInt(1000000000000000000), // 1 ether - Nonce: 0, - Code: common.FromHex("0xB0B0FACE"), - }, - }, - } - blockchain, _ = NewBlockChain(db, nil, gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil, nil) - ) - defer blockchain.Stop() - for i, tt := range []struct { - txs []*types.Transaction - want string - }{ - { // ErrSenderNoEOA - txs: []*types.Transaction{ - mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)), - }, - want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", - }, - } { - block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) - _, err := blockchain.InsertChain(types.Blocks{block}) - if err == nil { - t.Fatal("block imported without errors") - } - if have, want := err.Error(), tt.want; have != want { - t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want) - } - } - } -} - -// GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be -// valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently -// valid to be considered for import: -// - valid pow (fake), ancestry, difficulty, gaslimit etc -func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block { - difficulty := big.NewInt(0) - if !config.TerminalTotalDifficultyPassed { - fakeChainReader := newChainMaker(nil, config, engine) - difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{ - Number: parent.Number(), - Time: parent.Time(), - Difficulty: parent.Difficulty(), - UncleHash: parent.UncleHash(), - }) - } - - header := &types.Header{ - ParentHash: parent.Hash(), - Coinbase: parent.Coinbase(), - Difficulty: difficulty, - GasLimit: parent.GasLimit(), - Number: new(big.Int).Add(parent.Number(), common.Big1), - Time: parent.Time() + 10, - UncleHash: types.EmptyUncleHash, - } - if config.IsLondon(header.Number) { - header.BaseFee = eip1559.CalcBaseFee(config, parent.Header()) - } - if config.IsShanghai(header.Number, header.Time) { - header.WithdrawalsHash = &types.EmptyWithdrawalsHash - } - var receipts []*types.Receipt - // The post-state result doesn't need to be correct (this is a bad block), but we do need something there - // Preferably something unique. So let's use a combo of blocknum + txhash - hasher := sha3.NewLegacyKeccak256() - hasher.Write(header.Number.Bytes()) - var cumulativeGas uint64 - var nBlobs int - for _, tx := range txs { - txh := tx.Hash() - hasher.Write(txh[:]) - receipt := types.NewReceipt(nil, false, cumulativeGas+tx.Gas()) - receipt.TxHash = tx.Hash() - receipt.GasUsed = tx.Gas() - receipts = append(receipts, receipt) - cumulativeGas += tx.Gas() - nBlobs += len(tx.BlobHashes()) - } - header.Root = common.BytesToHash(hasher.Sum(nil)) - if config.IsCancun(header.Number, header.Time) { - var pExcess, pUsed = uint64(0), uint64(0) - if parent.ExcessBlobGas() != nil { - pExcess = *parent.ExcessBlobGas() - pUsed = *parent.BlobGasUsed() - } - excess := eip4844.CalcExcessBlobGas(pExcess, pUsed) - used := uint64(nBlobs * params.BlobTxBlobGasPerBlob) - header.ExcessBlobGas = &excess - header.BlobGasUsed = &used - - beaconRoot := common.HexToHash("0xbeac00") - header.ParentBeaconRoot = &beaconRoot - } - // Assemble and return the final block for sealing - if config.IsShanghai(header.Number, header.Time) { - return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil)) - } - return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) -} diff --git a/builder/core/state_transition.go b/builder/core/state_transition.go deleted file mode 100644 index 9c4f76d1c..000000000 --- a/builder/core/state_transition.go +++ /dev/null @@ -1,498 +0,0 @@ -// 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 core - -import ( - "fmt" - "math" - "math/big" - - "github.com/ethereum/go-ethereum/common" - cmath "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -// ExecutionResult includes all output after executing given evm -// message no matter the execution itself is successful or not. -type ExecutionResult struct { - UsedGas uint64 // Total used gas, not including the refunded gas - RefundedGas uint64 // Total gas refunded after execution - Err error // Any error encountered during the execution(listed in core/vm/errors.go) - ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode) -} - -// Unwrap returns the internal evm error which allows us for further -// analysis outside. -func (result *ExecutionResult) Unwrap() error { - return result.Err -} - -// Failed returns the indicator whether the execution is successful or not -func (result *ExecutionResult) Failed() bool { return result.Err != nil } - -// Return is a helper function to help caller distinguish between revert reason -// and function return. Return returns the data after execution if no error occurs. -func (result *ExecutionResult) Return() []byte { - if result.Err != nil { - return nil - } - return common.CopyBytes(result.ReturnData) -} - -// Revert returns the concrete revert reason if the execution is aborted by `REVERT` -// opcode. Note the reason can be nil if no data supplied with revert opcode. -func (result *ExecutionResult) Revert() []byte { - if result.Err != vm.ErrExecutionReverted { - return nil - } - return common.CopyBytes(result.ReturnData) -} - -// IntrinsicGas computes the 'intrinsic gas' for a message with the given data. -func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028, isEIP3860 bool) (uint64, error) { - // Set the starting gas for the raw transaction - var gas uint64 - if isContractCreation && isHomestead { - gas = params.TxGasContractCreation - } else { - gas = params.TxGas - } - dataLen := uint64(len(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 data { - if byt != 0 { - nz++ - } - } - // Make sure we don't exceed uint64 for all data combinations - nonZeroGas := params.TxDataNonZeroGasFrontier - if isEIP2028 { - nonZeroGas = params.TxDataNonZeroGasEIP2028 - } - if (math.MaxUint64-gas)/nonZeroGas < nz { - return 0, ErrGasUintOverflow - } - gas += nz * nonZeroGas - - z := dataLen - nz - if (math.MaxUint64-gas)/params.TxDataZeroGas < z { - return 0, ErrGasUintOverflow - } - gas += z * params.TxDataZeroGas - - if isContractCreation && isEIP3860 { - lenWords := toWordSize(dataLen) - if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords { - return 0, ErrGasUintOverflow - } - gas += lenWords * params.InitCodeWordGas - } - } - if accessList != nil { - gas += uint64(len(accessList)) * params.TxAccessListAddressGas - gas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas - } - return gas, nil -} - -// toWordSize returns the ceiled word size required for init code payment calculation. -func toWordSize(size uint64) uint64 { - if size > math.MaxUint64-31 { - return math.MaxUint64/32 + 1 - } - - return (size + 31) / 32 -} - -// A Message contains the data derived from a single transaction that is relevant to state -// processing. -type Message struct { - To *common.Address - From common.Address - Nonce uint64 - Value *big.Int - GasLimit uint64 - GasPrice *big.Int - GasFeeCap *big.Int - GasTipCap *big.Int - Data []byte - AccessList types.AccessList - BlobGasFeeCap *big.Int - BlobHashes []common.Hash - - // When SkipAccountChecks is true, the message nonce is not checked against the - // account nonce in state. It also disables checking that the sender is an EOA. - // This field will be set to true for operations like RPC eth_call. - SkipAccountChecks bool -} - -// TransactionToMessage converts a transaction into a Message. -func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) { - msg := &Message{ - Nonce: tx.Nonce(), - GasLimit: tx.Gas(), - GasPrice: new(big.Int).Set(tx.GasPrice()), - GasFeeCap: new(big.Int).Set(tx.GasFeeCap()), - GasTipCap: new(big.Int).Set(tx.GasTipCap()), - To: tx.To(), - Value: tx.Value(), - Data: tx.Data(), - AccessList: tx.AccessList(), - SkipAccountChecks: false, - BlobHashes: tx.BlobHashes(), - BlobGasFeeCap: tx.BlobGasFeeCap(), - } - // If baseFee provided, set gasPrice to effectiveGasPrice. - if baseFee != nil { - msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap) - } - var err error - msg.From, err = types.Sender(s, tx) - return msg, err -} - -// ApplyMessage computes the new state by applying the given message -// against the old state within the environment. -// -// ApplyMessage returns the bytes returned by any EVM execution (if it took place), -// the gas used (which includes gas refunds) and an error if it failed. An error always -// indicates a core error meaning that the message would always fail for that particular -// state and would never be accepted within a block. -func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) { - return NewStateTransition(evm, msg, gp).TransitionDb() -} - -// StateTransition represents a state transition. -// -// == The State Transitioning Model -// -// A state transition is a change made when a transaction is applied to the current world -// state. The state transitioning model does all the necessary work to work out a valid new -// state root. -// -// 1. Nonce handling -// 2. Pre pay gas -// 3. Create a new state object if the recipient is nil -// 4. Value transfer -// -// == If contract creation == -// -// 4a. Attempt to run transaction data -// 4b. If valid, use result as code for the new state object -// -// == end == -// -// 5. Run Script section -// 6. Derive new state root -type StateTransition struct { - gp *GasPool - msg *Message - gasRemaining uint64 - initialGas uint64 - state vm.StateDB - evm *vm.EVM -} - -// NewStateTransition initialises and returns a new state transition object. -func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition { - return &StateTransition{ - gp: gp, - evm: evm, - msg: msg, - state: evm.StateDB, - } -} - -// to returns the recipient of the message. -func (st *StateTransition) to() common.Address { - if st.msg == nil || st.msg.To == nil /* contract creation */ { - return common.Address{} - } - return *st.msg.To -} - -func (st *StateTransition) buyGas() error { - mgval := new(big.Int).SetUint64(st.msg.GasLimit) - mgval = mgval.Mul(mgval, st.msg.GasPrice) - balanceCheck := new(big.Int).Set(mgval) - if st.msg.GasFeeCap != nil { - balanceCheck.SetUint64(st.msg.GasLimit) - balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) - balanceCheck.Add(balanceCheck, st.msg.Value) - } - if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { - if blobGas := st.blobGasUsed(); blobGas > 0 { - // Check that the user has enough funds to cover blobGasUsed * tx.BlobGasFeeCap - blobBalanceCheck := new(big.Int).SetUint64(blobGas) - blobBalanceCheck.Mul(blobBalanceCheck, st.msg.BlobGasFeeCap) - balanceCheck.Add(balanceCheck, blobBalanceCheck) - // Pay for blobGasUsed * actual blob fee - blobFee := new(big.Int).SetUint64(blobGas) - blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee) - mgval.Add(mgval, blobFee) - } - } - balanceCheckU256, overflow := uint256.FromBig(balanceCheck) - if overflow { - return fmt.Errorf("%w: address %v required balance exceeds 256 bits", ErrInsufficientFunds, st.msg.From.Hex()) - } - if have, want := st.state.GetBalance(st.msg.From), balanceCheckU256; have.Cmp(want) < 0 { - return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) - } - if err := st.gp.SubGas(st.msg.GasLimit); err != nil { - return err - } - st.gasRemaining += st.msg.GasLimit - - st.initialGas = st.msg.GasLimit - mgvalU256, _ := uint256.FromBig(mgval) - st.state.SubBalance(st.msg.From, mgvalU256) - return nil -} - -func (st *StateTransition) preCheck() error { - // Only check transactions that are not fake - msg := st.msg - if !msg.SkipAccountChecks { - // Make sure this transaction's nonce is correct. - stNonce := st.state.GetNonce(msg.From) - if msgNonce := msg.Nonce; stNonce < msgNonce { - return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, - msg.From.Hex(), msgNonce, stNonce) - } else if stNonce > msgNonce { - return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, - msg.From.Hex(), msgNonce, stNonce) - } else if stNonce+1 < stNonce { - return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax, - msg.From.Hex(), stNonce) - } - // Make sure the sender is an EOA - codeHash := st.state.GetCodeHash(msg.From) - if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash { - return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, - msg.From.Hex(), codeHash) - } - } - // Make sure that transaction gasFeeCap is greater than the baseFee (post london) - if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { - // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) - skipCheck := st.evm.Config.NoBaseFee && msg.GasFeeCap.BitLen() == 0 && msg.GasTipCap.BitLen() == 0 - if !skipCheck { - if l := msg.GasFeeCap.BitLen(); l > 256 { - return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, - msg.From.Hex(), l) - } - if l := msg.GasTipCap.BitLen(); l > 256 { - return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, - msg.From.Hex(), l) - } - if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { - return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, - msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap) - } - // This will panic if baseFee is nil, but basefee presence is verified - // as part of header validation. - if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { - return fmt.Errorf("%w: address %v, maxFeePerGas: %s, baseFee: %s", ErrFeeCapTooLow, - msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) - } - } - } - // Check the blob version validity - if msg.BlobHashes != nil { - // The to field of a blob tx type is mandatory, and a `BlobTx` transaction internally - // has it as a non-nillable value, so any msg derived from blob transaction has it non-nil. - // However, messages created through RPC (eth_call) don't have this restriction. - if msg.To == nil { - return ErrBlobTxCreate - } - if len(msg.BlobHashes) == 0 { - return ErrMissingBlobHashes - } - for i, hash := range msg.BlobHashes { - if !kzg4844.IsValidVersionedHash(hash[:]) { - return fmt.Errorf("blob %d has invalid hash version", i) - } - } - } - // Check that the user is paying at least the current blob fee - if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { - if st.blobGasUsed() > 0 { - // Skip the checks if gas fields are zero and blobBaseFee was explicitly disabled (eth_call) - skipCheck := st.evm.Config.NoBaseFee && msg.BlobGasFeeCap.BitLen() == 0 - if !skipCheck { - // This will panic if blobBaseFee is nil, but blobBaseFee presence - // is verified as part of header validation. - if msg.BlobGasFeeCap.Cmp(st.evm.Context.BlobBaseFee) < 0 { - return fmt.Errorf("%w: address %v blobGasFeeCap: %v, blobBaseFee: %v", ErrBlobFeeCapTooLow, - msg.From.Hex(), msg.BlobGasFeeCap, st.evm.Context.BlobBaseFee) - } - } - } - } - return st.buyGas() -} - -// TransitionDb will transition the state by applying the current message and -// returning the evm execution result with following fields. -// -// - used gas: total gas used (including gas being refunded) -// - returndata: the returned data from evm -// - concrete execution error: various EVM errors which abort the execution, e.g. -// ErrOutOfGas, ErrExecutionReverted -// -// However if any consensus issue encountered, return the error directly with -// nil evm execution result. -func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { - // First check this message satisfies all consensus rules before - // applying the message. The rules include these clauses - // - // 1. the nonce of the message caller is correct - // 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) - // 3. the amount of gas required is available in the block - // 4. the purchased gas is enough to cover intrinsic usage - // 5. there is no overflow when calculating intrinsic gas - // 6. caller has enough balance to cover asset transfer for **topmost** call - - // Check clauses 1-3, buy gas if everything is correct - if err := st.preCheck(); err != nil { - return nil, err - } - - if tracer := st.evm.Config.Tracer; tracer != nil { - tracer.CaptureTxStart(st.initialGas) - defer func() { - tracer.CaptureTxEnd(st.gasRemaining) - }() - } - - var ( - msg = st.msg - sender = vm.AccountRef(msg.From) - rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) - contractCreation = msg.To == nil - ) - - // Check clauses 4-5, subtract intrinsic gas if everything is correct - gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) - if err != nil { - return nil, err - } - if st.gasRemaining < gas { - return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas) - } - st.gasRemaining -= gas - - // Check clause 6 - value, overflow := uint256.FromBig(msg.Value) - if overflow { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) - } - if !value.IsZero() && !st.evm.Context.CanTransfer(st.state, msg.From, value) { - return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) - } - - // Check whether the init code size has been exceeded. - if rules.IsShanghai && contractCreation && len(msg.Data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) - } - - // Execute the preparatory steps for state transition which includes: - // - prepare accessList(post-berlin) - // - reset transient storage(eip 1153) - st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) - - var ( - ret []byte - vmerr error // vm errors do not effect consensus and are therefore not assigned to err - ) - if contractCreation { - ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) - } else { - // Increment the nonce for the next transaction - st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1) - ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value) - } - - var gasRefund uint64 - if !rules.IsLondon { - // Before EIP-3529: refunds were capped to gasUsed / 2 - gasRefund = st.refundGas(params.RefundQuotient) - } else { - // After EIP-3529: refunds are capped to gasUsed / 5 - gasRefund = st.refundGas(params.RefundQuotientEIP3529) - } - effectiveTip := msg.GasPrice - if rules.IsLondon { - effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) - } - effectiveTipU256, _ := uint256.FromBig(effectiveTip) - - if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 { - // Skip fee payment when NoBaseFee is set and the fee fields - // are 0. This avoids a negative effectiveTip being applied to - // the coinbase when simulating calls. - } else { - fee := new(uint256.Int).SetUint64(st.gasUsed()) - fee.Mul(fee, effectiveTipU256) - st.state.AddBalance(st.evm.Context.Coinbase, fee) - } - - return &ExecutionResult{ - UsedGas: st.gasUsed(), - RefundedGas: gasRefund, - Err: vmerr, - ReturnData: ret, - }, nil -} - -func (st *StateTransition) refundGas(refundQuotient uint64) uint64 { - // Apply refund counter, capped to a refund quotient - refund := st.gasUsed() / refundQuotient - if refund > st.state.GetRefund() { - refund = st.state.GetRefund() - } - st.gasRemaining += refund - - // Return ETH for remaining gas, exchanged at the original rate. - remaining := uint256.NewInt(st.gasRemaining) - remaining = remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice)) - st.state.AddBalance(st.msg.From, remaining) - - // Also return remaining gas to the block gas counter so it is - // available for the next transaction. - st.gp.AddGas(st.gasRemaining) - - return refund -} - -// gasUsed returns the amount of gas used up by the state transition. -func (st *StateTransition) gasUsed() uint64 { - return st.initialGas - st.gasRemaining -} - -// blobGasUsed returns the amount of blob gas used by the message. -func (st *StateTransition) blobGasUsed() uint64 { - return uint64(len(st.msg.BlobHashes) * params.BlobTxBlobGasPerBlob) -} diff --git a/builder/core/txindexer.go b/builder/core/txindexer.go deleted file mode 100644 index 70fe5f332..000000000 --- a/builder/core/txindexer.go +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2024 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 core - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -// TxIndexProgress is the struct describing the progress for transaction indexing. -type TxIndexProgress struct { - Indexed uint64 // number of blocks whose transactions are indexed - Remaining uint64 // number of blocks whose transactions are not indexed yet -} - -// Done returns an indicator if the transaction indexing is finished. -func (progress TxIndexProgress) Done() bool { - return progress.Remaining == 0 -} - -// txIndexer is the module responsible for maintaining transaction indexes -// according to the configured indexing range by users. -type txIndexer struct { - // limit is the maximum number of blocks from head whose tx indexes - // are reserved: - // * 0: means the entire chain should be indexed - // * N: means the latest N blocks [HEAD-N+1, HEAD] should be indexed - // and all others shouldn't. - limit uint64 - db ethdb.Database - progress chan chan TxIndexProgress - term chan chan struct{} - closed chan struct{} -} - -// newTxIndexer initializes the transaction indexer. -func newTxIndexer(limit uint64, chain *BlockChain) *txIndexer { - indexer := &txIndexer{ - limit: limit, - db: chain.db, - progress: make(chan chan TxIndexProgress), - term: make(chan chan struct{}), - closed: make(chan struct{}), - } - go indexer.loop(chain) - - var msg string - if limit == 0 { - msg = "entire chain" - } else { - msg = fmt.Sprintf("last %d blocks", limit) - } - log.Info("Initialized transaction indexer", "range", msg) - - return indexer -} - -// run executes the scheduled indexing/unindexing task in a separate thread. -// If the stop channel is closed, the task should be terminated as soon as -// possible, the done channel will be closed once the task is finished. -func (indexer *txIndexer) run(tail *uint64, head uint64, stop chan struct{}, done chan struct{}) { - defer func() { close(done) }() - - // Short circuit if chain is empty and nothing to index. - if head == 0 { - return - } - // The tail flag is not existent, it means the node is just initialized - // and all blocks in the chain (part of them may from ancient store) are - // not indexed yet, index the chain according to the configured limit. - if tail == nil { - from := uint64(0) - if indexer.limit != 0 && head >= indexer.limit { - from = head - indexer.limit + 1 - } - rawdb.IndexTransactions(indexer.db, from, head+1, stop, true) - return - } - // The tail flag is existent (which means indexes in [tail, head] should be - // present), while the whole chain are requested for indexing. - if indexer.limit == 0 || head < indexer.limit { - if *tail > 0 { - // It can happen when chain is rewound to a historical point which - // is even lower than the indexes tail, recap the indexing target - // to new head to avoid reading non-existent block bodies. - end := *tail - if end > head+1 { - end = head + 1 - } - rawdb.IndexTransactions(indexer.db, 0, end, stop, true) - } - return - } - // The tail flag is existent, adjust the index range according to configured - // limit and the latest chain head. - if head-indexer.limit+1 < *tail { - // Reindex a part of missing indices and rewind index tail to HEAD-limit - rawdb.IndexTransactions(indexer.db, head-indexer.limit+1, *tail, stop, true) - } else { - // Unindex a part of stale indices and forward index tail to HEAD-limit - rawdb.UnindexTransactions(indexer.db, *tail, head-indexer.limit+1, stop, false) - } -} - -// loop is the scheduler of the indexer, assigning indexing/unindexing tasks depending -// on the received chain event. -func (indexer *txIndexer) loop(chain *BlockChain) { - defer close(indexer.closed) - - // Listening to chain events and manipulate the transaction indexes. - var ( - stop chan struct{} // Non-nil if background routine is active. - done chan struct{} // Non-nil if background routine is active. - lastHead uint64 // The latest announced chain head (whose tx indexes are assumed created) - lastTail = rawdb.ReadTxIndexTail(indexer.db) // The oldest indexed block, nil means nothing indexed - - headCh = make(chan ChainHeadEvent) - sub = chain.SubscribeChainHeadEvent(headCh) - ) - defer sub.Unsubscribe() - - // Launch the initial processing if chain is not empty (head != genesis). - // This step is useful in these scenarios that chain has no progress. - if head := rawdb.ReadHeadBlock(indexer.db); head != nil && head.Number().Uint64() != 0 { - stop = make(chan struct{}) - done = make(chan struct{}) - lastHead = head.Number().Uint64() - go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.NumberU64(), stop, done) - } - for { - select { - case head := <-headCh: - if done == nil { - stop = make(chan struct{}) - done = make(chan struct{}) - go indexer.run(rawdb.ReadTxIndexTail(indexer.db), head.Block.NumberU64(), stop, done) - } - lastHead = head.Block.NumberU64() - case <-done: - stop = nil - done = nil - lastTail = rawdb.ReadTxIndexTail(indexer.db) - case ch := <-indexer.progress: - ch <- indexer.report(lastHead, lastTail) - case ch := <-indexer.term: - if stop != nil { - close(stop) - } - if done != nil { - log.Info("Waiting background transaction indexer to exit") - <-done - } - close(ch) - return - } - } -} - -// report returns the tx indexing progress. -func (indexer *txIndexer) report(head uint64, tail *uint64) TxIndexProgress { - total := indexer.limit - if indexer.limit == 0 || total > head { - total = head + 1 // genesis included - } - var indexed uint64 - if tail != nil { - indexed = head - *tail + 1 - } - // The value of indexed might be larger than total if some blocks need - // to be unindexed, avoiding a negative remaining. - var remaining uint64 - if indexed < total { - remaining = total - indexed - } - return TxIndexProgress{ - Indexed: indexed, - Remaining: remaining, - } -} - -// txIndexProgress retrieves the tx indexing progress, or an error if the -// background tx indexer is already stopped. -func (indexer *txIndexer) txIndexProgress() (TxIndexProgress, error) { - ch := make(chan TxIndexProgress, 1) - select { - case indexer.progress <- ch: - return <-ch, nil - case <-indexer.closed: - return TxIndexProgress{}, errors.New("indexer is closed") - } -} - -// close shutdown the indexer. Safe to be called for multiple times. -func (indexer *txIndexer) close() { - ch := make(chan struct{}) - select { - case indexer.term <- ch: - <-ch - case <-indexer.closed: - } -} diff --git a/builder/core/txindexer_test.go b/builder/core/txindexer_test.go deleted file mode 100644 index 7b5ff1f20..000000000 --- a/builder/core/txindexer_test.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2024 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 core - -import ( - "math/big" - "os" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/params" -) - -// TestTxIndexer tests the functionalities for managing transaction indexes. -func TestTxIndexer(t *testing.T) { - var ( - testBankKey, _ = crypto.GenerateKey() - testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) - testBankFunds = big.NewInt(1000000000000000000) - - gspec = &Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - engine = ethash.NewFaker() - nonce = uint64(0) - chainHead = uint64(128) - ) - _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, int(chainHead), func(i int, gen *BlockGen) { - tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey) - gen.AddTx(tx) - nonce += 1 - }) - - // verifyIndexes checks if the transaction indexes are present or not - // of the specified block. - verifyIndexes := func(db ethdb.Database, number uint64, exist bool) { - if number == 0 { - return - } - block := blocks[number-1] - for _, tx := range block.Transactions() { - lookup := rawdb.ReadTxLookupEntry(db, tx.Hash()) - if exist && lookup == nil { - t.Fatalf("missing %d %x", number, tx.Hash().Hex()) - } - if !exist && lookup != nil { - t.Fatalf("unexpected %d %x", number, tx.Hash().Hex()) - } - } - } - verify := func(db ethdb.Database, expTail uint64, indexer *txIndexer) { - tail := rawdb.ReadTxIndexTail(db) - if tail == nil { - t.Fatal("Failed to write tx index tail") - } - if *tail != expTail { - t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail) - } - if *tail != 0 { - for number := uint64(0); number < *tail; number += 1 { - verifyIndexes(db, number, false) - } - } - for number := *tail; number <= chainHead; number += 1 { - verifyIndexes(db, number, true) - } - progress := indexer.report(chainHead, tail) - if !progress.Done() { - t.Fatalf("Expect fully indexed") - } - } - - var cases = []struct { - limitA uint64 - tailA uint64 - limitB uint64 - tailB uint64 - limitC uint64 - tailC uint64 - }{ - { - // LimitA: 0 - // TailA: 0 - // - // all blocks are indexed - limitA: 0, - tailA: 0, - - // LimitB: 1 - // TailB: 128 - // - // block-128 is indexed - limitB: 1, - tailB: 128, - - // LimitB: 64 - // TailB: 65 - // - // block [65, 128] are indexed - limitC: 64, - tailC: 65, - }, - { - // LimitA: 64 - // TailA: 65 - // - // block [65, 128] are indexed - limitA: 64, - tailA: 65, - - // LimitB: 1 - // TailB: 128 - // - // block-128 is indexed - limitB: 1, - tailB: 128, - - // LimitB: 64 - // TailB: 65 - // - // block [65, 128] are indexed - limitC: 64, - tailC: 65, - }, - { - // LimitA: 127 - // TailA: 2 - // - // block [2, 128] are indexed - limitA: 127, - tailA: 2, - - // LimitB: 1 - // TailB: 128 - // - // block-128 is indexed - limitB: 1, - tailB: 128, - - // LimitB: 64 - // TailB: 65 - // - // block [65, 128] are indexed - limitC: 64, - tailC: 65, - }, - { - // LimitA: 128 - // TailA: 1 - // - // block [2, 128] are indexed - limitA: 128, - tailA: 1, - - // LimitB: 1 - // TailB: 128 - // - // block-128 is indexed - limitB: 1, - tailB: 128, - - // LimitB: 64 - // TailB: 65 - // - // block [65, 128] are indexed - limitC: 64, - tailC: 65, - }, - { - // LimitA: 129 - // TailA: 0 - // - // block [0, 128] are indexed - limitA: 129, - tailA: 0, - - // LimitB: 1 - // TailB: 128 - // - // block-128 is indexed - limitB: 1, - tailB: 128, - - // LimitB: 64 - // TailB: 65 - // - // block [65, 128] are indexed - limitC: 64, - tailC: 65, - }, - } - for _, c := range cases { - frdir := t.TempDir() - db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) - rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), big.NewInt(0)) - - // Index the initial blocks from ancient store - indexer := &txIndexer{ - limit: c.limitA, - db: db, - progress: make(chan chan TxIndexProgress), - } - indexer.run(nil, 128, make(chan struct{}), make(chan struct{})) - verify(db, c.tailA, indexer) - - indexer.limit = c.limitB - indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{})) - verify(db, c.tailB, indexer) - - indexer.limit = c.limitC - indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{})) - verify(db, c.tailC, indexer) - - // Recover all indexes - indexer.limit = 0 - indexer.run(rawdb.ReadTxIndexTail(db), 128, make(chan struct{}), make(chan struct{})) - verify(db, 0, indexer) - - db.Close() - os.RemoveAll(frdir) - } -} diff --git a/builder/core/txpool/blobpool/blobpool.go b/builder/core/txpool/blobpool/blobpool.go deleted file mode 100644 index 1fe22c6c4..000000000 --- a/builder/core/txpool/blobpool/blobpool.go +++ /dev/null @@ -1,1667 +0,0 @@ -// 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 blobpool implements the EIP-4844 blob transaction pool. -package blobpool - -import ( - "container/heap" - "errors" - "fmt" - "math" - "math/big" - "os" - "path/filepath" - "sort" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/billy" - "github.com/holiman/uint256" -) - -const ( - // blobSize is the protocol constrained byte size of a single blob in a - // transaction. There can be multiple of these embedded into a single tx. - blobSize = params.BlobTxFieldElementsPerBlob * params.BlobTxBytesPerFieldElement - - // maxBlobsPerTransaction is the maximum number of blobs a single transaction - // is allowed to contain. Whilst the spec states it's unlimited, the block - // data slots are protocol bound, which implicitly also limit this. - maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob - - // txAvgSize is an approximate byte size of a transaction metadata to avoid - // tiny overflows causing all txs to move a shelf higher, wasting disk space. - txAvgSize = 4 * 1024 - - // txMaxSize is the maximum size a single transaction can have, outside - // the included blobs. Since blob transactions are pulled instead of pushed, - // and only a small metadata is kept in ram, the rest is on disk, there is - // no critical limit that should be enforced. Still, capping it to some sane - // limit can never hurt. - txMaxSize = 1024 * 1024 - - // maxTxsPerAccount is the maximum number of blob transactions admitted from - // a single account. The limit is enforced to minimize the DoS potential of - // a private tx cancelling publicly propagated blobs. - // - // Note, transactions resurrected by a reorg are also subject to this limit, - // so pushing it down too aggressively might make resurrections non-functional. - maxTxsPerAccount = 16 - - // pendingTransactionStore is the subfolder containing the currently queued - // blob transactions. - pendingTransactionStore = "queue" - - // limboedTransactionStore is the subfolder containing the currently included - // but not yet finalized transaction blobs. - limboedTransactionStore = "limbo" -) - -// blobTxMeta is the minimal subset of types.BlobTx necessary to validate and -// schedule the blob transactions into the following blocks. Only ever add the -// bare minimum needed fields to keep the size down (and thus number of entries -// larger with the same memory consumption). -type blobTxMeta struct { - hash common.Hash // Transaction hash to maintain the lookup table - id uint64 // Storage ID in the pool's persistent store - size uint32 // Byte size in the pool's persistent store - - nonce uint64 // Needed to prioritize inclusion order within an account - costCap *uint256.Int // Needed to validate cumulative balance sufficiency - execTipCap *uint256.Int // Needed to prioritize inclusion order across accounts and validate replacement price bump - execFeeCap *uint256.Int // Needed to validate replacement price bump - blobFeeCap *uint256.Int // Needed to validate replacement price bump - execGas uint64 // Needed to check inclusion validity before reading the blob - blobGas uint64 // Needed to check inclusion validity before reading the blob - - basefeeJumps float64 // Absolute number of 1559 fee adjustments needed to reach the tx's fee cap - blobfeeJumps float64 // Absolute number of 4844 fee adjustments needed to reach the tx's blob fee cap - - evictionExecTip *uint256.Int // Worst gas tip across all previous nonces - evictionExecFeeJumps float64 // Worst base fee (converted to fee jumps) across all previous nonces - evictionBlobFeeJumps float64 // Worse blob fee (converted to fee jumps) across all previous nonces -} - -// newBlobTxMeta retrieves the indexed metadata fields from a blob transaction -// and assembles a helper struct to track in memory. -func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta { - meta := &blobTxMeta{ - hash: tx.Hash(), - id: id, - size: size, - nonce: tx.Nonce(), - costCap: uint256.MustFromBig(tx.Cost()), - execTipCap: uint256.MustFromBig(tx.GasTipCap()), - execFeeCap: uint256.MustFromBig(tx.GasFeeCap()), - blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()), - execGas: tx.Gas(), - blobGas: tx.BlobGas(), - } - meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap) - meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap) - - return meta -} - -// BlobPool is the transaction pool dedicated to EIP-4844 blob transactions. -// -// Blob transactions are special snowflakes that are designed for a very specific -// purpose (rollups) and are expected to adhere to that specific use case. These -// behavioural expectations allow us to design a transaction pool that is more robust -// (i.e. resending issues) and more resilient to DoS attacks (e.g. replace-flush -// attacks) than the generic tx pool. These improvements will also mean, however, -// that we enforce a significantly more aggressive strategy on entering and exiting -// the pool: -// -// - Blob transactions are large. With the initial design aiming for 128KB blobs, -// we must ensure that these only traverse the network the absolute minimum -// number of times. Broadcasting to sqrt(peers) is out of the question, rather -// these should only ever be announced and the remote side should request it if -// it wants to. -// -// - Block blob-space is limited. With blocks being capped to a few blob txs, we -// can make use of the very low expected churn rate within the pool. Notably, -// we should be able to use a persistent disk backend for the pool, solving -// the tx resend issue that plagues the generic tx pool, as long as there's no -// artificial churn (i.e. pool wars). -// -// - Purpose of blobs are layer-2s. Layer-2s are meant to use blob transactions to -// commit to their own current state, which is independent of Ethereum mainnet -// (state, txs). This means that there's no reason for blob tx cancellation or -// replacement, apart from a potential basefee / miner tip adjustment. -// -// - Replacements are expensive. Given their size, propagating a replacement -// blob transaction to an existing one should be aggressively discouraged. -// Whilst generic transactions can start at 1 Wei gas cost and require a 10% -// fee bump to replace, we suggest requiring a higher min cost (e.g. 1 gwei) -// and a more aggressive bump (100%). -// -// - Cancellation is prohibitive. Evicting an already propagated blob tx is a huge -// DoS vector. As such, a) replacement (higher-fee) blob txs mustn't invalidate -// already propagated (future) blob txs (cumulative fee); b) nonce-gapped blob -// txs are disallowed; c) the presence of blob transactions exclude non-blob -// transactions. -// -// - Malicious cancellations are possible. Although the pool might prevent txs -// that cancel blobs, blocks might contain such transaction (malicious miner -// or flashbotter). The pool should cap the total number of blob transactions -// per account as to prevent propagating too much data before cancelling it -// via a normal transaction. It should nonetheless be high enough to support -// resurrecting reorged transactions. Perhaps 4-16. -// -// - Local txs are meaningless. Mining pools historically used local transactions -// for payouts or for backdoor deals. With 1559 in place, the basefee usually -// dominates the final price, so 0 or non-0 tip doesn't change much. Blob txs -// retain the 1559 2D gas pricing (and introduce on top a dynamic blob gas fee), -// so locality is moot. With a disk backed blob pool avoiding the resend issue, -// there's also no need to save own transactions for later. -// -// - No-blob blob-txs are bad. Theoretically there's no strong reason to disallow -// blob txs containing 0 blobs. In practice, admitting such txs into the pool -// breaks the low-churn invariant as blob constraints don't apply anymore. Even -// though we could accept blocks containing such txs, a reorg would require moving -// them back into the blob pool, which can break invariants. -// -// - Dropping blobs needs delay. When normal transactions are included, they -// are immediately evicted from the pool since they are contained in the -// including block. Blobs however are not included in the execution chain, -// so a mini reorg cannot re-pool "lost" blob transactions. To support reorgs, -// blobs are retained on disk until they are finalised. -// -// - Blobs can arrive via flashbots. Blocks might contain blob transactions we -// have never seen on the network. Since we cannot recover them from blocks -// either, the engine_newPayload needs to give them to us, and we cache them -// until finality to support reorgs without tx losses. -// -// Whilst some constraints above might sound overly aggressive, the general idea is -// that the blob pool should work robustly for its intended use case and whilst -// anyone is free to use blob transactions for arbitrary non-rollup use cases, -// they should not be allowed to run amok the network. -// -// Implementation wise there are a few interesting design choices: -// -// - Adding a transaction to the pool blocks until persisted to disk. This is -// viable because TPS is low (2-4 blobs per block initially, maybe 8-16 at -// peak), so natural churn is a couple MB per block. Replacements doing O(n) -// updates are forbidden and transaction propagation is pull based (i.e. no -// pileup of pending data). -// -// - When transactions are chosen for inclusion, the primary criteria is the -// signer tip (and having a basefee/data fee high enough of course). However, -// same-tip transactions will be split by their basefee/datafee, preferring -// those that are closer to the current network limits. The idea being that -// very relaxed ones can be included even if the fees go up, when the closer -// ones could already be invalid. -// -// When the pool eventually reaches saturation, some old transactions - that may -// never execute - will need to be evicted in favor of newer ones. The eviction -// strategy is quite complex: -// -// - Exceeding capacity evicts the highest-nonce of the account with the lowest -// paying blob transaction anywhere in the pooled nonce-sequence, as that tx -// would be executed the furthest in the future and is thus blocking anything -// after it. The smallest is deliberately not evicted to avoid a nonce-gap. -// -// - Analogously, if the pool is full, the consideration price of a new tx for -// evicting an old one is the smallest price in the entire nonce-sequence of -// the account. This avoids malicious users DoSing the pool with seemingly -// high paying transactions hidden behind a low-paying blocked one. -// -// - Since blob transactions have 3 price parameters: execution tip, execution -// fee cap and data fee cap, there's no singular parameter to create a total -// price ordering on. What's more, since the base fee and blob fee can move -// independently of one another, there's no pre-defined way to combine them -// into a stable order either. This leads to a multi-dimensional problem to -// solve after every block. -// -// - The first observation is that comparing 1559 base fees or 4844 blob fees -// needs to happen in the context of their dynamism. Since these fees jump -// up or down in ~1.125 multipliers (at max) across blocks, comparing fees -// in two transactions should be based on log1.125(fee) to eliminate noise. -// -// - The second observation is that the basefee and blobfee move independently, -// so there's no way to split mixed txs on their own (A has higher base fee, -// B has higher blob fee). Rather than look at the absolute fees, the useful -// metric is the max time it can take to exceed the transaction's fee caps. -// Specifically, we're interested in the number of jumps needed to go from -// the current fee to the transaction's cap: -// -// jumps = log1.125(txfee) - log1.125(basefee) -// -// - The third observation is that the base fee tends to hover around rather -// than swing wildly. The number of jumps needed from the current fee starts -// to get less relevant the higher it is. To remove the noise here too, the -// pool will use log(jumps) as the delta for comparing transactions. -// -// delta = sign(jumps) * log(abs(jumps)) -// -// - To establish a total order, we need to reduce the dimensionality of the -// two base fees (log jumps) to a single value. The interesting aspect from -// the pool's perspective is how fast will a tx get executable (fees going -// down, crossing the smaller negative jump counter) or non-executable (fees -// going up, crossing the smaller positive jump counter). As such, the pool -// cares only about the min of the two delta values for eviction priority. -// -// priority = min(deltaBasefee, deltaBlobfee) -// -// - The above very aggressive dimensionality and noise reduction should result -// in transaction being grouped into a small number of buckets, the further -// the fees the larger the buckets. This is good because it allows us to use -// the miner tip meaningfully as a splitter. -// -// - For the scenario where the pool does not contain non-executable blob txs -// anymore, it does not make sense to grant a later eviction priority to txs -// with high fee caps since it could enable pool wars. As such, any positive -// priority will be grouped together. -// -// priority = min(deltaBasefee, deltaBlobfee, 0) -// -// Optimisation tradeoffs: -// -// - Eviction relies on 3 fee minimums per account (exec tip, exec cap and blob -// cap). Maintaining these values across all transactions from the account is -// problematic as each transaction replacement or inclusion would require a -// rescan of all other transactions to recalculate the minimum. Instead, the -// pool maintains a rolling minimum across the nonce range. Updating all the -// minimums will need to be done only starting at the swapped in/out nonce -// and leading up to the first no-change. -type BlobPool struct { - config Config // Pool configuration - reserve txpool.AddressReserver // Address reserver to ensure exclusivity across subpools - - store billy.Database // Persistent data store for the tx metadata and blobs - stored uint64 // Useful data size of all transactions on disk - limbo *limbo // Persistent data store for the non-finalized blobs - - signer types.Signer // Transaction signer to use for sender recovery - chain BlockChain // Chain object to access the state through - - head *types.Header // Current head of the chain - state *state.StateDB // Current state at the head of the chain - gasTip *uint256.Int // Currently accepted minimum gas tip - - lookup map[common.Hash]uint64 // Lookup table mapping hashes to tx billy entries - index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce - spent map[common.Address]*uint256.Int // Expenditure tracking for individual accounts - evict *evictHeap // Heap of cheapest accounts for eviction when full - - discoverFeed event.Feed // Event feed to send out new tx events on pool discovery (reorg excluded) - insertFeed event.Feed // Event feed to send out new tx events on pool inclusion (reorg included) - - lock sync.RWMutex // Mutex protecting the pool during reorg handling - - privateTxs *types.TimestampedTxHashSet -} - -// New creates a new blob transaction pool to gather, sort and filter inbound -// blob transactions from the network. -func New(config Config, chain BlockChain) *BlobPool { - // Sanitize the input to ensure no vulnerable gas prices are set - config = (&config).sanitize() - - // Create the transaction pool with its initial settings - return &BlobPool{ - config: config, - signer: types.LatestSigner(chain.Config()), - chain: chain, - lookup: make(map[common.Hash]uint64), - index: make(map[common.Address][]*blobTxMeta), - spent: make(map[common.Address]*uint256.Int), - privateTxs: types.NewExpiringTxHashSet(config.PrivateTxLifetime), - } -} - -// Filter returns whether the given transaction can be consumed by the blob pool. -func (p *BlobPool) Filter(tx *types.Transaction) bool { - return tx.Type() == types.BlobTxType -} - -// Init sets the gas price needed to keep a transaction in the pool and the chain -// head to allow balance / nonce checks. The transaction journal will be loaded -// from disk and filtered based on the provided starting settings. -func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error { - p.reserve = reserve - - var ( - queuedir string - limbodir string - ) - if p.config.Datadir != "" { - queuedir = filepath.Join(p.config.Datadir, pendingTransactionStore) - if err := os.MkdirAll(queuedir, 0700); err != nil { - return err - } - limbodir = filepath.Join(p.config.Datadir, limboedTransactionStore) - if err := os.MkdirAll(limbodir, 0700); err != nil { - return err - } - } - // Initialize the state with head block, or fallback to empty one in - // case the head state is not available (might occur when node is not - // fully synced). - state, err := p.chain.StateAt(head.Root) - if err != nil { - state, err = p.chain.StateAt(types.EmptyRootHash) - } - if err != nil { - return err - } - p.head, p.state = head, state - - // Index all transactions on disk and delete anything unprocessable - var fails []uint64 - index := func(id uint64, size uint32, blob []byte) { - if p.parseTransaction(id, size, blob) != nil { - fails = append(fails, id) - } - } - store, err := billy.Open(billy.Options{Path: queuedir, Repair: true}, newSlotter(), index) - if err != nil { - return err - } - p.store = store - - if len(fails) > 0 { - log.Warn("Dropping invalidated blob transactions", "ids", fails) - dropInvalidMeter.Mark(int64(len(fails))) - - for _, id := range fails { - if err := p.store.Delete(id); err != nil { - p.Close() - return err - } - } - } - // Sort the indexed transactions by nonce and delete anything gapped, create - // the eviction heap of anyone still standing - for addr := range p.index { - p.recheck(addr, nil) - } - var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), p.head)) - blobfee = uint256.NewInt(params.BlobTxMinBlobGasprice) - ) - if p.head.ExcessBlobGas != nil { - blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*p.head.ExcessBlobGas)) - } - p.evict = newPriceHeap(basefee, blobfee, &p.index) - - // Pool initialized, attach the blob limbo to it to track blobs included - // recently but not yet finalized - p.limbo, err = newLimbo(limbodir) - if err != nil { - p.Close() - return err - } - // Set the configured gas tip, triggering a filtering of anything just loaded - basefeeGauge.Update(int64(basefee.Uint64())) - blobfeeGauge.Update(int64(blobfee.Uint64())) - - p.SetGasTip(new(big.Int).SetUint64(gasTip)) - - // Since the user might have modified their pool's capacity, evict anything - // above the current allowance - for p.stored > p.config.Datacap { - p.drop() - } - // Update the metrics and return the constructed pool - datacapGauge.Update(int64(p.config.Datacap)) - p.updateStorageMetrics() - return nil -} - -// Close closes down the underlying persistent store. -func (p *BlobPool) Close() error { - var errs []error - if p.limbo != nil { // Close might be invoked due to error in constructor, before p,limbo is set - if err := p.limbo.Close(); err != nil { - errs = append(errs, err) - } - } - if err := p.store.Close(); err != nil { - errs = append(errs, err) - } - switch { - case errs == nil: - return nil - case len(errs) == 1: - return errs[0] - default: - return fmt.Errorf("%v", errs) - } -} - -// parseTransaction is a callback method on pool creation that gets called for -// each transaction on disk to create the in-memory metadata index. -func (p *BlobPool) parseTransaction(id uint64, size uint32, blob []byte) error { - tx := new(types.Transaction) - if err := rlp.DecodeBytes(blob, tx); err != nil { - // This path is impossible unless the disk data representation changes - // across restarts. For that ever improbable case, recover gracefully - // by ignoring this data entry. - log.Error("Failed to decode blob pool entry", "id", id, "err", err) - return err - } - if tx.BlobTxSidecar() == nil { - log.Error("Missing sidecar in blob pool entry", "id", id, "hash", tx.Hash()) - return errors.New("missing blob sidecar") - } - - meta := newBlobTxMeta(id, size, tx) - if _, exists := p.lookup[meta.hash]; exists { - // This path is only possible after a crash, where deleted items are not - // removed via the normal shutdown-startup procedure and thus may get - // partially resurrected. - log.Error("Rejecting duplicate blob pool entry", "id", id, "hash", tx.Hash()) - return errors.New("duplicate blob entry") - } - sender, err := p.signer.Sender(tx) - if err != nil { - // This path is impossible unless the signature validity changes across - // restarts. For that ever improbable case, recover gracefully by ignoring - // this data entry. - log.Error("Failed to recover blob tx sender", "id", id, "hash", tx.Hash(), "err", err) - return err - } - if _, ok := p.index[sender]; !ok { - if err := p.reserve(sender, true); err != nil { - return err - } - p.index[sender] = []*blobTxMeta{} - p.spent[sender] = new(uint256.Int) - } - p.index[sender] = append(p.index[sender], meta) - p.spent[sender] = new(uint256.Int).Add(p.spent[sender], meta.costCap) - - p.lookup[meta.hash] = meta.id - p.stored += uint64(meta.size) - - return nil -} - -// recheck verifies the pool's content for a specific account and drops anything -// that does not fit anymore (dangling or filled nonce, overdraft). -func (p *BlobPool) recheck(addr common.Address, inclusions map[common.Hash]uint64) { - // Sort the transactions belonging to the account so reinjects can be simpler - txs := p.index[addr] - if inclusions != nil && txs == nil { // during reorgs, we might find new accounts - return - } - sort.Slice(txs, func(i, j int) bool { - return txs[i].nonce < txs[j].nonce - }) - // If there is a gap between the chain state and the blob pool, drop - // all the transactions as they are non-executable. Similarly, if the - // entire tx range was included, drop all. - var ( - next = p.state.GetNonce(addr) - gapped = txs[0].nonce > next - filled = txs[len(txs)-1].nonce < next - ) - if gapped || filled { - var ( - ids []uint64 - nonces []uint64 - ) - for i := 0; i < len(txs); i++ { - ids = append(ids, txs[i].id) - nonces = append(nonces, txs[i].nonce) - - p.stored -= uint64(txs[i].size) - delete(p.lookup, txs[i].hash) - - // Included transactions blobs need to be moved to the limbo - if filled && inclusions != nil { - p.privateTxs.Remove(txs[i].hash) - p.offload(addr, txs[i].nonce, txs[i].id, inclusions) - } - } - delete(p.index, addr) - delete(p.spent, addr) - if inclusions != nil { // only during reorgs will the heap be initialized - heap.Remove(p.evict, p.evict.index[addr]) - } - p.reserve(addr, false) - - if gapped { - log.Warn("Dropping dangling blob transactions", "from", addr, "missing", next, "drop", nonces, "ids", ids) - dropDanglingMeter.Mark(int64(len(ids))) - } else { - log.Trace("Dropping filled blob transactions", "from", addr, "filled", nonces, "ids", ids) - dropFilledMeter.Mark(int64(len(ids))) - } - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - } - return - } - // If there is overlap between the chain state and the blob pool, drop - // anything below the current state - if txs[0].nonce < next { - var ( - ids []uint64 - nonces []uint64 - ) - for txs[0].nonce < next { - ids = append(ids, txs[0].id) - nonces = append(nonces, txs[0].nonce) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[0].costCap) - p.stored -= uint64(txs[0].size) - delete(p.lookup, txs[0].hash) - - // Included transactions blobs need to be moved to the limbo - if inclusions != nil { - p.privateTxs.Remove(txs[0].hash) - p.offload(addr, txs[0].nonce, txs[0].id, inclusions) - } - txs = txs[1:] - } - log.Trace("Dropping overlapped blob transactions", "from", addr, "overlapped", nonces, "ids", ids, "left", len(txs)) - dropOverlappedMeter.Mark(int64(len(ids))) - - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - } - p.index[addr] = txs - } - // Iterate over the transactions to initialize their eviction thresholds - // and to detect any nonce gaps - txs[0].evictionExecTip = txs[0].execTipCap - txs[0].evictionExecFeeJumps = txs[0].basefeeJumps - txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps - - for i := 1; i < len(txs); i++ { - // If there's no nonce gap, initialize the eviction thresholds as the - // minimum between the cumulative thresholds and the current tx fees - if txs[i].nonce == txs[i-1].nonce+1 { - txs[i].evictionExecTip = txs[i-1].evictionExecTip - if txs[i].evictionExecTip.Cmp(txs[i].execTipCap) > 0 { - txs[i].evictionExecTip = txs[i].execTipCap - } - txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps - if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps { - txs[i].evictionExecFeeJumps = txs[i].basefeeJumps - } - txs[i].evictionBlobFeeJumps = txs[i-1].evictionBlobFeeJumps - if txs[i].evictionBlobFeeJumps > txs[i].blobfeeJumps { - txs[i].evictionBlobFeeJumps = txs[i].blobfeeJumps - } - continue - } - // Sanity check that there's no double nonce. This case would generally - // be a coding error, so better know about it. - // - // Also, Billy behind the blobpool does not journal deletes. A process - // crash would result in previously deleted entities being resurrected. - // That could potentially cause a duplicate nonce to appear. - if txs[i].nonce == txs[i-1].nonce { - id := p.lookup[txs[i].hash] - - log.Error("Dropping repeat nonce blob transaction", "from", addr, "nonce", txs[i].nonce, "id", id) - dropRepeatedMeter.Mark(1) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].costCap) - p.stored -= uint64(txs[i].size) - delete(p.lookup, txs[i].hash) - - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - txs = append(txs[:i], txs[i+1:]...) - p.index[addr] = txs - - i-- - continue - } - // Otherwise if there's a nonce gap evict all later transactions - var ( - ids []uint64 - nonces []uint64 - ) - for j := i; j < len(txs); j++ { - ids = append(ids, txs[j].id) - nonces = append(nonces, txs[j].nonce) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[j].costCap) - p.stored -= uint64(txs[j].size) - delete(p.lookup, txs[j].hash) - } - txs = txs[:i] - - log.Error("Dropping gapped blob transactions", "from", addr, "missing", txs[i-1].nonce+1, "drop", nonces, "ids", ids) - dropGappedMeter.Mark(int64(len(ids))) - - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - } - p.index[addr] = txs - break - } - // Ensure that there's no over-draft, this is expected to happen when some - // transactions get included without publishing on the network - var ( - balance = p.state.GetBalance(addr) - spent = p.spent[addr] - ) - if spent.Cmp(balance) > 0 { - // Evict the highest nonce transactions until the pending set falls under - // the account's available balance - var ( - ids []uint64 - nonces []uint64 - ) - for p.spent[addr].Cmp(balance) > 0 { - last := txs[len(txs)-1] - txs[len(txs)-1] = nil - txs = txs[:len(txs)-1] - - ids = append(ids, last.id) - nonces = append(nonces, last.nonce) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.costCap) - p.stored -= uint64(last.size) - delete(p.lookup, last.hash) - } - if len(txs) == 0 { - delete(p.index, addr) - delete(p.spent, addr) - if inclusions != nil { // only during reorgs will the heap be initialized - heap.Remove(p.evict, p.evict.index[addr]) - } - p.reserve(addr, false) - } else { - p.index[addr] = txs - } - log.Warn("Dropping overdrafted blob transactions", "from", addr, "balance", balance, "spent", spent, "drop", nonces, "ids", ids) - dropOverdraftedMeter.Mark(int64(len(ids))) - - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - } - } - // Sanity check that no account can have more queued transactions than the - // DoS protection threshold. - if len(txs) > maxTxsPerAccount { - // Evict the highest nonce transactions until the pending set falls under - // the account's transaction cap - var ( - ids []uint64 - nonces []uint64 - ) - for len(txs) > maxTxsPerAccount { - last := txs[len(txs)-1] - txs[len(txs)-1] = nil - txs = txs[:len(txs)-1] - - ids = append(ids, last.id) - nonces = append(nonces, last.nonce) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], last.costCap) - p.stored -= uint64(last.size) - delete(p.lookup, last.hash) - } - p.index[addr] = txs - - log.Warn("Dropping overcapped blob transactions", "from", addr, "kept", len(txs), "drop", nonces, "ids", ids) - dropOvercappedMeter.Mark(int64(len(ids))) - - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete blob transaction", "from", addr, "id", id, "err", err) - } - } - } - // Included cheap transactions might have left the remaining ones better from - // an eviction point, fix any potential issues in the heap. - if _, ok := p.index[addr]; ok && inclusions != nil { - heap.Fix(p.evict, p.evict.index[addr]) - } -} - -// offload removes a tracked blob transaction from the pool and moves it into the -// limbo for tracking until finality. -// -// The method may log errors for various unexpected scenarios but will not return -// any of it since there's no clear error case. Some errors may be due to coding -// issues, others caused by signers mining MEV stuff or swapping transactions. In -// all cases, the pool needs to continue operating. -func (p *BlobPool) offload(addr common.Address, nonce uint64, id uint64, inclusions map[common.Hash]uint64) { - data, err := p.store.Get(id) - if err != nil { - log.Error("Blobs missing for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err) - return - } - var tx types.Transaction - if err = rlp.DecodeBytes(data, &tx); err != nil { - log.Error("Blobs corrupted for included transaction", "from", addr, "nonce", nonce, "id", id, "err", err) - return - } - block, ok := inclusions[tx.Hash()] - if !ok { - log.Warn("Blob transaction swapped out by signer", "from", addr, "nonce", nonce, "id", id) - return - } - if err := p.limbo.push(&tx, block); err != nil { - log.Warn("Failed to offload blob tx into limbo", "err", err) - return - } -} - -// Reset implements txpool.SubPool, allowing the blob pool's internal state to be -// kept in sync with the main transaction pool's internal state. -func (p *BlobPool) Reset(oldHead, newHead *types.Header) { - waitStart := time.Now() - p.lock.Lock() - resetwaitHist.Update(time.Since(waitStart).Nanoseconds()) - defer p.lock.Unlock() - - defer func(start time.Time) { - resettimeHist.Update(time.Since(start).Nanoseconds()) - }(time.Now()) - - statedb, err := p.chain.StateAt(newHead.Root) - if err != nil { - log.Error("Failed to reset blobpool state", "err", err) - return - } - p.head = newHead - p.state = statedb - - // Run the reorg between the old and new head and figure out which accounts - // need to be rechecked and which transactions need to be readded - if reinject, inclusions := p.reorg(oldHead, newHead); reinject != nil { - var adds []*types.Transaction - for addr, txs := range reinject { - // Blindly push all the lost transactions back into the pool - for _, tx := range txs { - if err := p.reinject(addr, tx.Hash()); err == nil { - adds = append(adds, tx.WithoutBlobTxSidecar()) - } - } - // Recheck the account's pooled transactions to drop included and - // invalidated ones - p.recheck(addr, inclusions) - } - if len(adds) > 0 { - p.insertFeed.Send(core.NewTxsEvent{Txs: adds}) - } - } - // Flush out any blobs from limbo that are older than the latest finality - if p.chain.Config().IsCancun(p.head.Number, p.head.Time) { - p.limbo.finalize(p.chain.CurrentFinalBlock()) - } - // Reset the price heap for the new set of basefee/blobfee pairs - var ( - basefee = uint256.MustFromBig(eip1559.CalcBaseFee(p.chain.Config(), newHead)) - blobfee = uint256.MustFromBig(big.NewInt(params.BlobTxMinBlobGasprice)) - ) - if newHead.ExcessBlobGas != nil { - blobfee = uint256.MustFromBig(eip4844.CalcBlobFee(*newHead.ExcessBlobGas)) - } - p.evict.reinit(basefee, blobfee, false) - - basefeeGauge.Update(int64(basefee.Uint64())) - blobfeeGauge.Update(int64(blobfee.Uint64())) - p.updateStorageMetrics() - - p.privateTxs.Prune() -} - -// reorg assembles all the transactors and missing transactions between an old -// and new head to figure out which account's tx set needs to be rechecked and -// which transactions need to be requeued. -// -// The transactionblock inclusion infos are also returned to allow tracking any -// just-included blocks by block number in the limbo. -func (p *BlobPool) reorg(oldHead, newHead *types.Header) (map[common.Address][]*types.Transaction, map[common.Hash]uint64) { - // If the pool was not yet initialized, don't do anything - if oldHead == nil { - return nil, nil - } - // If the reorg is too deep, avoid doing it (will happen during snap sync) - oldNum := oldHead.Number.Uint64() - newNum := newHead.Number.Uint64() - - if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { - return nil, nil - } - // Reorg seems shallow enough to pull in all transactions into memory - var ( - transactors = make(map[common.Address]struct{}) - discarded = make(map[common.Address][]*types.Transaction) - included = make(map[common.Address][]*types.Transaction) - inclusions = make(map[common.Hash]uint64) - - rem = p.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) - add = p.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) - ) - if add == nil { - // if the new head is nil, it means that something happened between - // the firing of newhead-event and _now_: most likely a - // reorg caused by sync-reversion or explicit sethead back to an - // earlier block. - log.Warn("Blobpool reset with missing new head", "number", newHead.Number, "hash", newHead.Hash()) - return nil, nil - } - if rem == nil { - // This can happen if a setHead is performed, where we simply discard - // the old head from the chain. If that is the case, we don't have the - // lost transactions anymore, and there's nothing to add. - if newNum >= oldNum { - // If we reorged to a same or higher number, then it's not a case - // of setHead - log.Warn("Blobpool reset with missing old head", - "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) - return nil, nil - } - // If the reorg ended up on a lower number, it's indicative of setHead - // being the cause - log.Debug("Skipping blobpool reset caused by setHead", - "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) - return nil, nil - } - // Both old and new blocks exist, traverse through the progression chain - // and accumulate the transactors and transactions - for rem.NumberU64() > add.NumberU64() { - for _, tx := range rem.Transactions() { - from, _ := p.signer.Sender(tx) - - discarded[from] = append(discarded[from], tx) - transactors[from] = struct{}{} - } - if rem = p.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by blobpool", "block", oldHead.Number, "hash", oldHead.Hash()) - return nil, nil - } - } - for add.NumberU64() > rem.NumberU64() { - for _, tx := range add.Transactions() { - from, _ := p.signer.Sender(tx) - - included[from] = append(included[from], tx) - inclusions[tx.Hash()] = add.NumberU64() - transactors[from] = struct{}{} - } - if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by blobpool", "block", newHead.Number, "hash", newHead.Hash()) - return nil, nil - } - } - for rem.Hash() != add.Hash() { - for _, tx := range rem.Transactions() { - from, _ := p.signer.Sender(tx) - - discarded[from] = append(discarded[from], tx) - transactors[from] = struct{}{} - } - if rem = p.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by blobpool", "block", oldHead.Number, "hash", oldHead.Hash()) - return nil, nil - } - for _, tx := range add.Transactions() { - from, _ := p.signer.Sender(tx) - - included[from] = append(included[from], tx) - inclusions[tx.Hash()] = add.NumberU64() - transactors[from] = struct{}{} - } - if add = p.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by blobpool", "block", newHead.Number, "hash", newHead.Hash()) - return nil, nil - } - } - // Generate the set of transactions per address to pull back into the pool, - // also updating the rest along the way - reinject := make(map[common.Address][]*types.Transaction) - for addr := range transactors { - // Generate the set that was lost to reinject into the pool - lost := make([]*types.Transaction, 0, len(discarded[addr])) - for _, tx := range types.TxDifference(discarded[addr], included[addr]) { - if p.Filter(tx) && !p.IsPrivateTxHash(tx.Hash()) { - lost = append(lost, tx) - } - } - reinject[addr] = lost - - // Update the set that was already reincluded to track the blocks in limbo - for _, tx := range types.TxDifference(included[addr], discarded[addr]) { - if p.Filter(tx) { - p.limbo.update(tx.Hash(), inclusions[tx.Hash()]) - } - } - } - return reinject, inclusions -} - -// reinject blindly pushes a transaction previously included in the chain - and -// just reorged out - into the pool. The transaction is assumed valid (having -// been in the chain), thus the only validation needed is nonce sorting and over- -// draft checks after injection. -// -// Note, the method will not initialize the eviction cache values as those will -// be done once for all transactions belonging to an account after all individual -// transactions are injected back into the pool. -func (p *BlobPool) reinject(addr common.Address, txhash common.Hash) error { - // Retrieve the associated blob from the limbo. Without the blobs, we cannot - // add the transaction back into the pool as it is not mineable. - tx, err := p.limbo.pull(txhash) - if err != nil { - log.Error("Blobs unavailable, dropping reorged tx", "err", err) - return err - } - // TODO: seems like an easy optimization here would be getting the serialized tx - // from limbo instead of re-serializing it here. - - // Serialize the transaction back into the primary datastore. - blob, err := rlp.EncodeToBytes(tx) - if err != nil { - log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) - return err - } - id, err := p.store.Put(blob) - if err != nil { - log.Error("Failed to write transaction into storage", "hash", tx.Hash(), "err", err) - return err - } - - // Update the indices and metrics - meta := newBlobTxMeta(id, p.store.Size(id), tx) - if _, ok := p.index[addr]; !ok { - if err := p.reserve(addr, true); err != nil { - log.Warn("Failed to reserve account for blob pool", "tx", tx.Hash(), "from", addr, "err", err) - return err - } - p.index[addr] = []*blobTxMeta{meta} - p.spent[addr] = meta.costCap - p.evict.Push(addr) - } else { - p.index[addr] = append(p.index[addr], meta) - p.spent[addr] = new(uint256.Int).Add(p.spent[addr], meta.costCap) - } - p.lookup[meta.hash] = meta.id - p.stored += uint64(meta.size) - return nil -} - -// SetGasTip implements txpool.SubPool, allowing the blob pool's gas requirements -// to be kept in sync with the main transaction pool's gas requirements. -func (p *BlobPool) SetGasTip(tip *big.Int) { - p.lock.Lock() - defer p.lock.Unlock() - - // Store the new minimum gas tip - old := p.gasTip - p.gasTip = uint256.MustFromBig(tip) - - // If the min miner fee increased, remove transactions below the new threshold - if old == nil || p.gasTip.Cmp(old) > 0 { - for addr, txs := range p.index { - for i, tx := range txs { - if tx.execTipCap.Cmp(p.gasTip) < 0 { - // Drop the offending transaction - var ( - ids = []uint64{tx.id} - nonces = []uint64{tx.nonce} - ) - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], txs[i].costCap) - p.stored -= uint64(tx.size) - delete(p.lookup, tx.hash) - txs[i] = nil - - // Drop everything afterwards, no gaps allowed - for j, tx := range txs[i+1:] { - ids = append(ids, tx.id) - nonces = append(nonces, tx.nonce) - - p.spent[addr] = new(uint256.Int).Sub(p.spent[addr], tx.costCap) - p.stored -= uint64(tx.size) - delete(p.lookup, tx.hash) - txs[i+1+j] = nil - } - // Clear out the dropped transactions from the index - if i > 0 { - p.index[addr] = txs[:i] - heap.Fix(p.evict, p.evict.index[addr]) - } else { - delete(p.index, addr) - delete(p.spent, addr) - - heap.Remove(p.evict, p.evict.index[addr]) - p.reserve(addr, false) - } - // Clear out the transactions from the data store - log.Warn("Dropping underpriced blob transaction", "from", addr, "rejected", tx.nonce, "tip", tx.execTipCap, "want", tip, "drop", nonces, "ids", ids) - dropUnderpricedMeter.Mark(int64(len(ids))) - - for _, id := range ids { - if err := p.store.Delete(id); err != nil { - log.Error("Failed to delete dropped transaction", "id", id, "err", err) - } - } - break - } - } - } - } - log.Debug("Blobpool tip threshold updated", "tip", tip) - pooltipGauge.Update(tip.Int64()) - p.updateStorageMetrics() -} - -// validateTx checks whether a transaction is valid according to the consensus -// rules and adheres to some heuristic limits of the local node (price and size). -func (p *BlobPool) validateTx(tx *types.Transaction) error { - // Ensure the transaction adheres to basic pool filters (type, size, tip) and - // consensus rules - baseOpts := &txpool.ValidationOptions{ - Config: p.chain.Config(), - Accept: 1 << types.BlobTxType, - MaxSize: txMaxSize, - MinTip: p.gasTip.ToBig(), - } - if err := txpool.ValidateTransaction(tx, p.head, p.signer, baseOpts); err != nil { - return err - } - // Ensure the transaction adheres to the stateful pool filters (nonce, balance) - stateOpts := &txpool.ValidationOptionsWithState{ - State: p.state, - - FirstNonceGap: func(addr common.Address) uint64 { - // Nonce gaps are not permitted in the blob pool, the first gap will - // be the next nonce shifted by however many transactions we already - // have pooled. - return p.state.GetNonce(addr) + uint64(len(p.index[addr])) - }, - UsedAndLeftSlots: func(addr common.Address) (int, int) { - have := len(p.index[addr]) - if have >= maxTxsPerAccount { - return have, 0 - } - return have, maxTxsPerAccount - have - }, - ExistingExpenditure: func(addr common.Address) *big.Int { - if spent := p.spent[addr]; spent != nil { - return spent.ToBig() - } - return new(big.Int) - }, - ExistingCost: func(addr common.Address, nonce uint64) *big.Int { - next := p.state.GetNonce(addr) - if uint64(len(p.index[addr])) > nonce-next { - return p.index[addr][int(tx.Nonce()-next)].costCap.ToBig() - } - return nil - }, - } - if err := txpool.ValidateTransactionWithState(tx, p.signer, stateOpts); err != nil { - return err - } - // If the transaction replaces an existing one, ensure that price bumps are - // adhered to. - var ( - from, _ = p.signer.Sender(tx) // already validated above - next = p.state.GetNonce(from) - ) - if uint64(len(p.index[from])) > tx.Nonce()-next { - // Account can support the replacement, but the price bump must also be met - prev := p.index[from][int(tx.Nonce()-next)] - switch { - case tx.GasFeeCapIntCmp(prev.execFeeCap.ToBig()) <= 0: - return fmt.Errorf("%w: new tx gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.execFeeCap) - case tx.GasTipCapIntCmp(prev.execTipCap.ToBig()) <= 0: - return fmt.Errorf("%w: new tx gas tip cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.execTipCap) - case tx.BlobGasFeeCapIntCmp(prev.blobFeeCap.ToBig()) <= 0: - return fmt.Errorf("%w: new tx blob gas fee cap %v <= %v queued", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.blobFeeCap) - } - var ( - multiplier = uint256.NewInt(100 + p.config.PriceBump) - onehundred = uint256.NewInt(100) - - minGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.execFeeCap), onehundred) - minGasTipCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.execTipCap), onehundred) - minBlobGasFeeCap = new(uint256.Int).Div(new(uint256.Int).Mul(multiplier, prev.blobFeeCap), onehundred) - ) - switch { - case tx.GasFeeCapIntCmp(minGasFeeCap.ToBig()) < 0: - return fmt.Errorf("%w: new tx gas fee cap %v <= %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasFeeCap(), prev.execFeeCap, p.config.PriceBump) - case tx.GasTipCapIntCmp(minGasTipCap.ToBig()) < 0: - return fmt.Errorf("%w: new tx gas tip cap %v <= %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.GasTipCap(), prev.execTipCap, p.config.PriceBump) - case tx.BlobGasFeeCapIntCmp(minBlobGasFeeCap.ToBig()) < 0: - return fmt.Errorf("%w: new tx blob gas fee cap %v <= %v queued + %d%% replacement penalty", txpool.ErrReplaceUnderpriced, tx.BlobGasFeeCap(), prev.blobFeeCap, p.config.PriceBump) - } - } - return nil -} - -// Has returns an indicator whether subpool has a transaction cached with the -// given hash. -func (p *BlobPool) Has(hash common.Hash) bool { - p.lock.RLock() - defer p.lock.RUnlock() - - _, ok := p.lookup[hash] - return ok -} - -// Get returns a transaction if it is contained in the pool, or nil otherwise. -func (p *BlobPool) Get(hash common.Hash) *types.Transaction { - // Track the amount of time waiting to retrieve a fully resolved blob tx from - // the pool and the amount of time actually spent on pulling the data from disk. - getStart := time.Now() - p.lock.RLock() - getwaitHist.Update(time.Since(getStart).Nanoseconds()) - defer p.lock.RUnlock() - - defer func(start time.Time) { - gettimeHist.Update(time.Since(start).Nanoseconds()) - }(time.Now()) - - // Pull the blob from disk and return an assembled response - id, ok := p.lookup[hash] - if !ok { - return nil - } - data, err := p.store.Get(id) - if err != nil { - log.Error("Tracked blob transaction missing from store", "hash", hash, "id", id, "err", err) - return nil - } - item := new(types.Transaction) - if err = rlp.DecodeBytes(data, item); err != nil { - log.Error("Blobs corrupted for traced transaction", "hash", hash, "id", id, "err", err) - return nil - } - return item -} - -// Add inserts a set of blob transactions into the pool if they pass validation (both -// consensus validity and pool restrictions). -func (p *BlobPool) Add(txs []*types.Transaction, local bool, sync bool, private bool) []error { - var ( - adds = make([]*types.Transaction, 0, len(txs)) - errs = make([]error, len(txs)) - ) - for i, tx := range txs { - errs[i] = p.add(tx, private) - if errs[i] == nil && !private { - adds = append(adds, tx.WithoutBlobTxSidecar()) - } - } - if len(adds) > 0 { - p.discoverFeed.Send(core.NewTxsEvent{Txs: adds}) - p.insertFeed.Send(core.NewTxsEvent{Txs: adds}) - } - return errs -} - -// Add inserts a new blob transaction into the pool if it passes validation (both -// consensus validity and pool restrictions). -func (p *BlobPool) add(tx *types.Transaction, private bool) (err error) { - // The blob pool blocks on adding a transaction. This is because blob txs are - // only even pulled from the network, so this method will act as the overload - // protection for fetches. - waitStart := time.Now() - p.lock.Lock() - addwaitHist.Update(time.Since(waitStart).Nanoseconds()) - defer p.lock.Unlock() - - defer func(start time.Time) { - addtimeHist.Update(time.Since(start).Nanoseconds()) - }(time.Now()) - - // Ensure the transaction is valid from all perspectives - if err := p.validateTx(tx); err != nil { - log.Trace("Transaction validation failed", "hash", tx.Hash(), "err", err) - switch { - case errors.Is(err, txpool.ErrUnderpriced): - addUnderpricedMeter.Mark(1) - case errors.Is(err, core.ErrNonceTooLow): - addStaleMeter.Mark(1) - case errors.Is(err, core.ErrNonceTooHigh): - addGappedMeter.Mark(1) - case errors.Is(err, core.ErrInsufficientFunds): - addOverdraftedMeter.Mark(1) - case errors.Is(err, txpool.ErrAccountLimitExceeded): - addOvercappedMeter.Mark(1) - case errors.Is(err, txpool.ErrReplaceUnderpriced): - addNoreplaceMeter.Mark(1) - default: - addInvalidMeter.Mark(1) - } - return err - } - // If the address is not yet known, request exclusivity to track the account - // only by this subpool until all transactions are evicted - from, _ := types.Sender(p.signer, tx) // already validated above - if _, ok := p.index[from]; !ok { - if err := p.reserve(from, true); err != nil { - addNonExclusiveMeter.Mark(1) - return err - } - defer func() { - // If the transaction is rejected by some post-validation check, remove - // the lock on the reservation set. - // - // Note, `err` here is the named error return, which will be initialized - // by a return statement before running deferred methods. Take care with - // removing or subscoping err as it will break this clause. - if err != nil { - p.reserve(from, false) - } - }() - } - // Transaction permitted into the pool from a nonce and cost perspective, - // insert it into the database and update the indices - blob, err := rlp.EncodeToBytes(tx) - if err != nil { - log.Error("Failed to encode transaction for storage", "hash", tx.Hash(), "err", err) - return err - } - id, err := p.store.Put(blob) - if err != nil { - return err - } - meta := newBlobTxMeta(id, p.store.Size(id), tx) - - // Track private transactions, so they don't get leaked to the public mempool - if private { - p.privateTxs.Add(tx.Hash()) - } - - var ( - next = p.state.GetNonce(from) - offset = int(tx.Nonce() - next) - newacc = false - ) - var oldEvictionExecFeeJumps, oldEvictionBlobFeeJumps float64 - if txs, ok := p.index[from]; ok { - oldEvictionExecFeeJumps = txs[len(txs)-1].evictionExecFeeJumps - oldEvictionBlobFeeJumps = txs[len(txs)-1].evictionBlobFeeJumps - } - if len(p.index[from]) > offset { - // Transaction replaces a previously queued one - dropReplacedMeter.Mark(1) - - prev := p.index[from][offset] - if err := p.store.Delete(prev.id); err != nil { - // Shitty situation, but try to recover gracefully instead of going boom - log.Error("Failed to delete replaced transaction", "id", prev.id, "err", err) - } - // Update the transaction index - p.index[from][offset] = meta - p.spent[from] = new(uint256.Int).Sub(p.spent[from], prev.costCap) - p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.costCap) - - delete(p.lookup, prev.hash) - p.lookup[meta.hash] = meta.id - p.stored += uint64(meta.size) - uint64(prev.size) - } else { - // Transaction extends previously scheduled ones - p.index[from] = append(p.index[from], meta) - if _, ok := p.spent[from]; !ok { - p.spent[from] = new(uint256.Int) - newacc = true - } - p.spent[from] = new(uint256.Int).Add(p.spent[from], meta.costCap) - p.lookup[meta.hash] = meta.id - p.stored += uint64(meta.size) - } - // Recompute the rolling eviction fields. In case of a replacement, this will - // recompute all subsequent fields. In case of an append, this will only do - // the fresh calculation. - txs := p.index[from] - - for i := offset; i < len(txs); i++ { - // The first transaction will always use itself - if i == 0 { - txs[0].evictionExecTip = txs[0].execTipCap - txs[0].evictionExecFeeJumps = txs[0].basefeeJumps - txs[0].evictionBlobFeeJumps = txs[0].blobfeeJumps - - continue - } - // Subsequent transactions will use a rolling calculation - txs[i].evictionExecTip = txs[i-1].evictionExecTip - if txs[i].evictionExecTip.Cmp(txs[i].execTipCap) > 0 { - txs[i].evictionExecTip = txs[i].execTipCap - } - txs[i].evictionExecFeeJumps = txs[i-1].evictionExecFeeJumps - if txs[i].evictionExecFeeJumps > txs[i].basefeeJumps { - txs[i].evictionExecFeeJumps = txs[i].basefeeJumps - } - txs[i].evictionBlobFeeJumps = txs[i-1].evictionBlobFeeJumps - if txs[i].evictionBlobFeeJumps > txs[i].blobfeeJumps { - txs[i].evictionBlobFeeJumps = txs[i].blobfeeJumps - } - } - // Update the eviction heap with the new information: - // - If the transaction is from a new account, add it to the heap - // - If the account had a singleton tx replaced, update the heap (new price caps) - // - If the account has a transaction replaced or appended, update the heap if significantly changed - switch { - case newacc: - heap.Push(p.evict, from) - - case len(txs) == 1: // 1 tx and not a new acc, must be replacement - heap.Fix(p.evict, p.evict.index[from]) - - default: // replacement or new append - evictionExecFeeDiff := oldEvictionExecFeeJumps - txs[len(txs)-1].evictionExecFeeJumps - evictionBlobFeeDiff := oldEvictionBlobFeeJumps - txs[len(txs)-1].evictionBlobFeeJumps - - if math.Abs(evictionExecFeeDiff) > 0.001 || math.Abs(evictionBlobFeeDiff) > 0.001 { // need math.Abs, can go up and down - heap.Fix(p.evict, p.evict.index[from]) - } - } - // If the pool went over the allowed data limit, evict transactions until - // we're again below the threshold - for p.stored > p.config.Datacap { - p.drop() - } - p.updateStorageMetrics() - - addValidMeter.Mark(1) - return nil -} - -// drop removes the worst transaction from the pool. It is primarily used when a -// freshly added transaction overflows the pool and needs to evict something. The -// method is also called on startup if the user resizes their storage, might be an -// expensive run but it should be fine-ish. -func (p *BlobPool) drop() { - // Peek at the account with the worse transaction set to evict from (Go's heap - // stores the minimum at index zero of the heap slice) and retrieve it's last - // transaction. - var ( - from = p.evict.addrs[0] // cannot call drop on empty pool - - txs = p.index[from] - drop = txs[len(txs)-1] - last = len(txs) == 1 - ) - // Remove the transaction from the pool's index - if last { - delete(p.index, from) - delete(p.spent, from) - p.reserve(from, false) - } else { - txs[len(txs)-1] = nil - txs = txs[:len(txs)-1] - - p.index[from] = txs - p.spent[from] = new(uint256.Int).Sub(p.spent[from], drop.costCap) - } - p.stored -= uint64(drop.size) - delete(p.lookup, drop.hash) - - // Remove the transaction from the pool's eviction heap: - // - If the entire account was dropped, pop off the address - // - Otherwise, if the new tail has better eviction caps, fix the heap - if last { - heap.Pop(p.evict) - } else { - tail := txs[len(txs)-1] // new tail, surely exists - - evictionExecFeeDiff := tail.evictionExecFeeJumps - drop.evictionExecFeeJumps - evictionBlobFeeDiff := tail.evictionBlobFeeJumps - drop.evictionBlobFeeJumps - - if evictionExecFeeDiff > 0.001 || evictionBlobFeeDiff > 0.001 { // no need for math.Abs, monotonic decreasing - heap.Fix(p.evict, 0) - } - } - // Remove the transaction from the data store - log.Debug("Evicting overflown blob transaction", "from", from, "evicted", drop.nonce, "id", drop.id) - dropOverflownMeter.Mark(1) - - if err := p.store.Delete(drop.id); err != nil { - log.Error("Failed to drop evicted transaction", "id", drop.id, "err", err) - } -} - -// Pending retrieves all currently processable transactions, grouped by origin -// account and sorted by nonce. -// -// The transactions can also be pre-filtered by the dynamic fee components to -// reduce allocations and load on downstream subsystems. -func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { - // If only plain transactions are requested, this pool is unsuitable as it - // contains none, don't even bother. - if filter.OnlyPlainTxs { - return nil - } - // Track the amount of time waiting to retrieve the list of pending blob txs - // from the pool and the amount of time actually spent on assembling the data. - // The latter will be pretty much moot, but we've kept it to have symmetric - // across all user operations. - pendStart := time.Now() - p.lock.RLock() - pendwaitHist.Update(time.Since(pendStart).Nanoseconds()) - defer p.lock.RUnlock() - - execStart := time.Now() - defer func() { - pendtimeHist.Update(time.Since(execStart).Nanoseconds()) - }() - - pending := make(map[common.Address][]*txpool.LazyTransaction, len(p.index)) - for addr, txs := range p.index { - lazies := make([]*txpool.LazyTransaction, 0, len(txs)) - for _, tx := range txs { - // If transaction filtering was requested, discard badly priced ones - if filter.MinTip != nil && filter.BaseFee != nil { - if tx.execFeeCap.Lt(filter.BaseFee) { - break // basefee too low, cannot be included, discard rest of txs from the account - } - tip := new(uint256.Int).Sub(tx.execFeeCap, filter.BaseFee) - if tip.Gt(tx.execTipCap) { - tip = tx.execTipCap - } - if tip.Lt(filter.MinTip) { - break // allowed or remaining tip too low, cannot be included, discard rest of txs from the account - } - } - if filter.BlobFee != nil { - if tx.blobFeeCap.Lt(filter.BlobFee) { - break // blobfee too low, cannot be included, discard rest of txs from the account - } - } - // Transaction was accepted according to the filter, append to the pending list - lazies = append(lazies, &txpool.LazyTransaction{ - Pool: p, - Hash: tx.hash, - Time: execStart, // TODO(karalabe): Maybe save these and use that? - GasFeeCap: tx.execFeeCap, - GasTipCap: tx.execTipCap, - Gas: tx.execGas, - BlobGas: tx.blobGas, - }) - } - if len(lazies) > 0 { - pending[addr] = lazies - } - } - return pending -} - -// updateStorageMetrics retrieves a bunch of stats from the data store and pushes -// them out as metrics. -func (p *BlobPool) updateStorageMetrics() { - stats := p.store.Infos() - - var ( - dataused uint64 - datareal uint64 - slotused uint64 - - oversizedDataused uint64 - oversizedDatagaps uint64 - oversizedSlotused uint64 - oversizedSlotgaps uint64 - ) - for _, shelf := range stats.Shelves { - slotDataused := shelf.FilledSlots * uint64(shelf.SlotSize) - slotDatagaps := shelf.GappedSlots * uint64(shelf.SlotSize) - - dataused += slotDataused - datareal += slotDataused + slotDatagaps - slotused += shelf.FilledSlots - - metrics.GetOrRegisterGauge(fmt.Sprintf(shelfDatausedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(slotDataused)) - metrics.GetOrRegisterGauge(fmt.Sprintf(shelfDatagapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(slotDatagaps)) - metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotusedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.FilledSlots)) - metrics.GetOrRegisterGauge(fmt.Sprintf(shelfSlotgapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.GappedSlots)) - - if shelf.SlotSize/blobSize > maxBlobsPerTransaction { - oversizedDataused += slotDataused - oversizedDatagaps += slotDatagaps - oversizedSlotused += shelf.FilledSlots - oversizedSlotgaps += shelf.GappedSlots - } - } - datausedGauge.Update(int64(dataused)) - datarealGauge.Update(int64(datareal)) - slotusedGauge.Update(int64(slotused)) - - oversizedDatausedGauge.Update(int64(oversizedDataused)) - oversizedDatagapsGauge.Update(int64(oversizedDatagaps)) - oversizedSlotusedGauge.Update(int64(oversizedSlotused)) - oversizedSlotgapsGauge.Update(int64(oversizedSlotgaps)) - - p.updateLimboMetrics() -} - -// updateLimboMetrics retrieves a bunch of stats from the limbo store and pushes -// them out as metrics. -func (p *BlobPool) updateLimboMetrics() { - stats := p.limbo.store.Infos() - - var ( - dataused uint64 - datareal uint64 - slotused uint64 - ) - for _, shelf := range stats.Shelves { - slotDataused := shelf.FilledSlots * uint64(shelf.SlotSize) - slotDatagaps := shelf.GappedSlots * uint64(shelf.SlotSize) - - dataused += slotDataused - datareal += slotDataused + slotDatagaps - slotused += shelf.FilledSlots - - metrics.GetOrRegisterGauge(fmt.Sprintf(limboShelfDatausedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(slotDataused)) - metrics.GetOrRegisterGauge(fmt.Sprintf(limboShelfDatagapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(slotDatagaps)) - metrics.GetOrRegisterGauge(fmt.Sprintf(limboShelfSlotusedGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.FilledSlots)) - metrics.GetOrRegisterGauge(fmt.Sprintf(limboShelfSlotgapsGaugeName, shelf.SlotSize/blobSize), nil).Update(int64(shelf.GappedSlots)) - } - limboDatausedGauge.Update(int64(dataused)) - limboDatarealGauge.Update(int64(datareal)) - limboSlotusedGauge.Update(int64(slotused)) -} - -// SubscribeTransactions registers a subscription for new transaction events, -// supporting feeding only newly seen or also resurrected transactions. -func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { - if reorgs { - return p.insertFeed.Subscribe(ch) - } else { - return p.discoverFeed.Subscribe(ch) - } -} - -// Nonce returns the next nonce of an account, with all transactions executable -// by the pool already applied on top. -func (p *BlobPool) Nonce(addr common.Address) uint64 { - p.lock.Lock() - defer p.lock.Unlock() - - if txs, ok := p.index[addr]; ok { - return txs[len(txs)-1].nonce + 1 - } - return p.state.GetNonce(addr) -} - -// Stats retrieves the current pool stats, namely the number of pending and the -// number of queued (non-executable) transactions. -func (p *BlobPool) Stats() (int, int) { - p.lock.Lock() - defer p.lock.Unlock() - - var pending int - for _, txs := range p.index { - pending += len(txs) - } - return pending, 0 // No non-executable txs in the blob pool -} - -// Content retrieves the data content of the transaction pool, returning all the -// pending as well as queued transactions, grouped by account and sorted by nonce. -// -// For the blob pool, this method will return nothing for now. -// TODO(karalabe): Abstract out the returned metadata. -func (p *BlobPool) Content() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { - return make(map[common.Address][]*types.Transaction), make(map[common.Address][]*types.Transaction) -} - -// ContentFrom retrieves the data content of the transaction pool, returning the -// pending as well as queued transactions of this address, grouped by nonce. -// -// For the blob pool, this method will return nothing for now. -// TODO(karalabe): Abstract out the returned metadata. -func (p *BlobPool) ContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { - return []*types.Transaction{}, []*types.Transaction{} -} - -// Locals retrieves the accounts currently considered local by the pool. -// -// There is no notion of local accounts in the blob pool. -func (p *BlobPool) Locals() []common.Address { - return []common.Address{} -} - -// Status returns the known status (unknown/pending/queued) of a transaction -// identified by their hashes. -func (p *BlobPool) Status(hash common.Hash) txpool.TxStatus { - if p.Has(hash) { - return txpool.TxStatusPending - } - return txpool.TxStatusUnknown -} - -func (p *BlobPool) IsPrivateTxHash(hash common.Hash) bool { - return p.privateTxs.Contains(hash) -} diff --git a/builder/core/txpool/blobpool/blobpool_test.go b/builder/core/txpool/blobpool/blobpool_test.go deleted file mode 100644 index 37980484a..000000000 --- a/builder/core/txpool/blobpool/blobpool_test.go +++ /dev/null @@ -1,1370 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "bytes" - "crypto/ecdsa" - "crypto/sha256" - "errors" - "math" - "math/big" - "os" - "path/filepath" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/billy" - "github.com/holiman/uint256" -) - -var ( - emptyBlob = kzg4844.Blob{} - emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) - emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) - emptyBlobVHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit) -) - -// Chain configuration with Cancun enabled. -// -// TODO(karalabe): replace with params.MainnetChainConfig after Cancun. -var testChainConfig *params.ChainConfig - -func init() { - testChainConfig = new(params.ChainConfig) - *testChainConfig = *params.MainnetChainConfig - - testChainConfig.CancunTime = new(uint64) - *testChainConfig.CancunTime = uint64(time.Now().Unix()) -} - -// testBlockChain is a mock of the live chain for testing the pool. -type testBlockChain struct { - config *params.ChainConfig - basefee *uint256.Int - blobfee *uint256.Int - statedb *state.StateDB -} - -func (bc *testBlockChain) Config() *params.ChainConfig { - return bc.config -} - -func (bc *testBlockChain) CurrentBlock() *types.Header { - // Yolo, life is too short to invert mist.CalcBaseFee and misc.CalcBlobFee, - // just binary search it them. - - // The base fee at 5714 ETH translates into the 21000 base gas higher than - // mainnet ether existence, use that as a cap for the tests. - var ( - blockNumber = new(big.Int).Add(bc.config.LondonBlock, big.NewInt(1)) - blockTime = *bc.config.CancunTime + 1 - gasLimit = uint64(30_000_000) - ) - lo := new(big.Int) - hi := new(big.Int).Mul(big.NewInt(5714), new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) - - for new(big.Int).Add(lo, big.NewInt(1)).Cmp(hi) != 0 { - mid := new(big.Int).Add(lo, hi) - mid.Div(mid, big.NewInt(2)) - - if eip1559.CalcBaseFee(bc.config, &types.Header{ - Number: blockNumber, - GasLimit: gasLimit, - GasUsed: 0, - BaseFee: mid, - }).Cmp(bc.basefee.ToBig()) > 0 { - hi = mid - } else { - lo = mid - } - } - baseFee := lo - - // The excess blob gas at 2^27 translates into a blob fee higher than mainnet - // ether existence, use that as a cap for the tests. - lo = new(big.Int) - hi = new(big.Int).Exp(big.NewInt(2), big.NewInt(27), nil) - - for new(big.Int).Add(lo, big.NewInt(1)).Cmp(hi) != 0 { - mid := new(big.Int).Add(lo, hi) - mid.Div(mid, big.NewInt(2)) - - if eip4844.CalcBlobFee(mid.Uint64()).Cmp(bc.blobfee.ToBig()) > 0 { - hi = mid - } else { - lo = mid - } - } - excessBlobGas := lo.Uint64() - - return &types.Header{ - Number: blockNumber, - Time: blockTime, - GasLimit: gasLimit, - BaseFee: baseFee, - ExcessBlobGas: &excessBlobGas, - } -} - -func (bc *testBlockChain) CurrentFinalBlock() *types.Header { - return &types.Header{ - Number: big.NewInt(0), - } -} - -func (bt *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return nil -} - -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { - return bc.statedb, nil -} - -// makeAddressReserver is a utility method to sanity check that accounts are -// properly reserved by the blobpool (no duplicate reserves or unreserves). -func makeAddressReserver() txpool.AddressReserver { - var ( - reserved = make(map[common.Address]struct{}) - lock sync.Mutex - ) - return func(addr common.Address, reserve bool) error { - lock.Lock() - defer lock.Unlock() - - _, exists := reserved[addr] - if reserve { - if exists { - panic("already reserved") - } - reserved[addr] = struct{}{} - return nil - } - if !exists { - panic("not reserved") - } - delete(reserved, addr) - return nil - } -} - -// makeTx is a utility method to construct a random blob transaction and sign it -// with a valid key, only setting the interesting fields from the perspective of -// the blob pool. -func makeTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64, key *ecdsa.PrivateKey) *types.Transaction { - blobtx := makeUnsignedTx(nonce, gasTipCap, gasFeeCap, blobFeeCap) - return types.MustSignNewTx(key, types.LatestSigner(testChainConfig), blobtx) -} - -// makeUnsignedTx is a utility method to construct a random blob transaction -// without signing it. -func makeUnsignedTx(nonce uint64, gasTipCap uint64, gasFeeCap uint64, blobFeeCap uint64) *types.BlobTx { - return &types.BlobTx{ - ChainID: uint256.MustFromBig(testChainConfig.ChainID), - Nonce: nonce, - GasTipCap: uint256.NewInt(gasTipCap), - GasFeeCap: uint256.NewInt(gasFeeCap), - Gas: 21000, - BlobFeeCap: uint256.NewInt(blobFeeCap), - BlobHashes: []common.Hash{emptyBlobVHash}, - Value: uint256.NewInt(100), - Sidecar: &types.BlobTxSidecar{ - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, - } -} - -// verifyPoolInternals iterates over all the transactions in the pool and checks -// that sort orders, calculated fields, cumulated fields are correct. -func verifyPoolInternals(t *testing.T, pool *BlobPool) { - // Mark this method as a helper to remove from stack traces - t.Helper() - - // Verify that all items in the index are present in the lookup and nothing more - seen := make(map[common.Hash]struct{}) - for addr, txs := range pool.index { - for _, tx := range txs { - if _, ok := seen[tx.hash]; ok { - t.Errorf("duplicate hash #%x in transaction index: address %s, nonce %d", tx.hash, addr, tx.nonce) - } - seen[tx.hash] = struct{}{} - } - } - for hash, id := range pool.lookup { - if _, ok := seen[hash]; !ok { - t.Errorf("lookup entry missing from transaction index: hash #%x, id %d", hash, id) - } - delete(seen, hash) - } - for hash := range seen { - t.Errorf("indexed transaction hash #%x missing from lookup table", hash) - } - // Verify that transactions are sorted per account and contain no nonce gaps - for addr, txs := range pool.index { - for i := 1; i < len(txs); i++ { - if txs[i].nonce != txs[i-1].nonce+1 { - t.Errorf("addr %v, tx %d nonce mismatch: have %d, want %d", addr, i, txs[i].nonce, txs[i-1].nonce+1) - } - } - } - // Verify that calculated evacuation thresholds are correct - for addr, txs := range pool.index { - if !txs[0].evictionExecTip.Eq(txs[0].execTipCap) { - t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, 0, txs[0].evictionExecTip, txs[0].execTipCap) - } - if math.Abs(txs[0].evictionExecFeeJumps-txs[0].basefeeJumps) > 0.001 { - t.Errorf("addr %v, tx %d eviction execution fee jumps mismatch: have %f, want %f", addr, 0, txs[0].evictionExecFeeJumps, txs[0].basefeeJumps) - } - if math.Abs(txs[0].evictionBlobFeeJumps-txs[0].blobfeeJumps) > 0.001 { - t.Errorf("addr %v, tx %d eviction blob fee jumps mismatch: have %f, want %f", addr, 0, txs[0].evictionBlobFeeJumps, txs[0].blobfeeJumps) - } - for i := 1; i < len(txs); i++ { - wantExecTip := txs[i-1].evictionExecTip - if wantExecTip.Gt(txs[i].execTipCap) { - wantExecTip = txs[i].execTipCap - } - if !txs[i].evictionExecTip.Eq(wantExecTip) { - t.Errorf("addr %v, tx %d eviction execution tip mismatch: have %d, want %d", addr, i, txs[i].evictionExecTip, wantExecTip) - } - - wantExecFeeJumps := txs[i-1].evictionExecFeeJumps - if wantExecFeeJumps > txs[i].basefeeJumps { - wantExecFeeJumps = txs[i].basefeeJumps - } - if math.Abs(txs[i].evictionExecFeeJumps-wantExecFeeJumps) > 0.001 { - t.Errorf("addr %v, tx %d eviction execution fee jumps mismatch: have %f, want %f", addr, i, txs[i].evictionExecFeeJumps, wantExecFeeJumps) - } - - wantBlobFeeJumps := txs[i-1].evictionBlobFeeJumps - if wantBlobFeeJumps > txs[i].blobfeeJumps { - wantBlobFeeJumps = txs[i].blobfeeJumps - } - if math.Abs(txs[i].evictionBlobFeeJumps-wantBlobFeeJumps) > 0.001 { - t.Errorf("addr %v, tx %d eviction blob fee jumps mismatch: have %f, want %f", addr, i, txs[i].evictionBlobFeeJumps, wantBlobFeeJumps) - } - } - } - // Verify that account balance accumulations are correct - for addr, txs := range pool.index { - spent := new(uint256.Int) - for _, tx := range txs { - spent.Add(spent, tx.costCap) - } - if !pool.spent[addr].Eq(spent) { - t.Errorf("addr %v expenditure mismatch: have %d, want %d", addr, pool.spent[addr], spent) - } - } - // Verify that pool storage size is correct - var stored uint64 - for _, txs := range pool.index { - for _, tx := range txs { - stored += uint64(tx.size) - } - } - if pool.stored != stored { - t.Errorf("pool storage mismatch: have %d, want %d", pool.stored, stored) - } - // Verify the price heap internals - verifyHeapInternals(t, pool.evict) -} - -// Tests that transactions can be loaded from disk on startup and that they are -// correctly discarded if invalid. -// -// - 1. A transaction that cannot be decoded must be dropped -// - 2. A transaction that cannot be recovered (bad signature) must be dropped -// - 3. All transactions after a nonce gap must be dropped -// - 4. All transactions after an already included nonce must be dropped -// - 5. All transactions after an underpriced one (including it) must be dropped -// - 6. All transactions after an overdrafting sequence must be dropped -// - 7. All transactions exceeding the per-account limit must be dropped -// -// Furthermore, some strange corner-cases can also occur after a crash, as Billy's -// simplicity also allows it to resurrect past deleted entities: -// -// - 8. Fully duplicate transactions (matching hash) must be dropped -// - 9. Duplicate nonces from the same account must be dropped -func TestOpenDrops(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) - - // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) - - os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) - store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil) - - // Insert a malformed transaction to verify that decoding errors (or format - // changes) are handled gracefully (case 1) - malformed, _ := store.Put([]byte("this is a badly encoded transaction")) - - // Insert a transaction with a bad signature to verify that stale junk after - // potential hard-forks can get evicted (case 2) - tx := types.NewTx(&types.BlobTx{ - ChainID: uint256.MustFromBig(testChainConfig.ChainID), - GasTipCap: new(uint256.Int), - GasFeeCap: new(uint256.Int), - Gas: 0, - Value: new(uint256.Int), - Data: nil, - BlobFeeCap: new(uint256.Int), - V: new(uint256.Int), - R: new(uint256.Int), - S: new(uint256.Int), - }) - blob, _ := rlp.EncodeToBytes(tx) - badsig, _ := store.Put(blob) - - // Insert a sequence of transactions with a nonce gap in between to verify - // that anything gapped will get evicted (case 3). - var ( - gapper, _ = crypto.GenerateKey() - - valids = make(map[uint64]struct{}) - gapped = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 3, 4, 6, 7} { // first gap at #2, another at #5 - tx := makeTx(nonce, 1, 1, 1, gapper) - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - if nonce < 2 { - valids[id] = struct{}{} - } else { - gapped[id] = struct{}{} - } - } - // Insert a sequence of transactions with a gapped starting nonce to verify - // that the entire set will get dropped (case 3). - var ( - dangler, _ = crypto.GenerateKey() - dangling = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{1, 2, 3} { // first gap at #0, all set dangling - tx := makeTx(nonce, 1, 1, 1, dangler) - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - dangling[id] = struct{}{} - } - // Insert a sequence of transactions with already passed nonces to veirfy - // that the entire set will get dropped (case 4). - var ( - filler, _ = crypto.GenerateKey() - filled = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2} { // account nonce at 3, all set filled - tx := makeTx(nonce, 1, 1, 1, filler) - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - filled[id] = struct{}{} - } - // Insert a sequence of transactions with partially passed nonces to verify - // that the included part of the set will get dropped (case 4). - var ( - overlapper, _ = crypto.GenerateKey() - overlapped = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2, 3} { // account nonce at 2, half filled - tx := makeTx(nonce, 1, 1, 1, overlapper) - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - if nonce >= 2 { - valids[id] = struct{}{} - } else { - overlapped[id] = struct{}{} - } - } - // Insert a sequence of transactions with an underpriced first to verify that - // the entire set will get dropped (case 5). - var ( - underpayer, _ = crypto.GenerateKey() - underpaid = make(map[uint64]struct{}) - ) - for i := 0; i < 5; i++ { // make #0 underpriced - var tx *types.Transaction - if i == 0 { - tx = makeTx(uint64(i), 0, 0, 0, underpayer) - } else { - tx = makeTx(uint64(i), 1, 1, 1, underpayer) - } - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - underpaid[id] = struct{}{} - } - - // Insert a sequence of transactions with an underpriced in between to verify - // that it and anything newly gapped will get evicted (case 5). - var ( - outpricer, _ = crypto.GenerateKey() - outpriced = make(map[uint64]struct{}) - ) - for i := 0; i < 5; i++ { // make #2 underpriced - var tx *types.Transaction - if i == 2 { - tx = makeTx(uint64(i), 0, 0, 0, outpricer) - } else { - tx = makeTx(uint64(i), 1, 1, 1, outpricer) - } - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - if i < 2 { - valids[id] = struct{}{} - } else { - outpriced[id] = struct{}{} - } - } - // Insert a sequence of transactions fully overdrafted to verify that the - // entire set will get invalidated (case 6). - var ( - exceeder, _ = crypto.GenerateKey() - exceeded = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2} { // nonce 0 overdrafts the account - var tx *types.Transaction - if nonce == 0 { - tx = makeTx(nonce, 1, 100, 1, exceeder) - } else { - tx = makeTx(nonce, 1, 1, 1, exceeder) - } - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - exceeded[id] = struct{}{} - } - // Insert a sequence of transactions partially overdrafted to verify that part - // of the set will get invalidated (case 6). - var ( - overdrafter, _ = crypto.GenerateKey() - overdrafted = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2} { // nonce 1 overdrafts the account - var tx *types.Transaction - if nonce == 1 { - tx = makeTx(nonce, 1, 100, 1, overdrafter) - } else { - tx = makeTx(nonce, 1, 1, 1, overdrafter) - } - blob, _ := rlp.EncodeToBytes(tx) - - id, _ := store.Put(blob) - if nonce < 1 { - valids[id] = struct{}{} - } else { - overdrafted[id] = struct{}{} - } - } - // Insert a sequence of transactions overflowing the account cap to verify - // that part of the set will get invalidated (case 7). - var ( - overcapper, _ = crypto.GenerateKey() - overcapped = make(map[uint64]struct{}) - ) - for nonce := uint64(0); nonce < maxTxsPerAccount+3; nonce++ { - blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, 1, 1, overcapper)) - - id, _ := store.Put(blob) - if nonce < maxTxsPerAccount { - valids[id] = struct{}{} - } else { - overcapped[id] = struct{}{} - } - } - // Insert a batch of duplicated transactions to verify that only one of each - // version will remain (case 8). - var ( - duplicater, _ = crypto.GenerateKey() - duplicated = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2} { - blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, 1, 1, duplicater)) - - for i := 0; i < int(nonce)+1; i++ { - id, _ := store.Put(blob) - if i == 0 { - valids[id] = struct{}{} - } else { - duplicated[id] = struct{}{} - } - } - } - // Insert a batch of duplicated nonces to verify that only one of each will - // remain (case 9). - var ( - repeater, _ = crypto.GenerateKey() - repeated = make(map[uint64]struct{}) - ) - for _, nonce := range []uint64{0, 1, 2} { - for i := 0; i < int(nonce)+1; i++ { - blob, _ := rlp.EncodeToBytes(makeTx(nonce, 1, uint64(i)+1 /* unique hashes */, 1, repeater)) - - id, _ := store.Put(blob) - if i == 0 { - valids[id] = struct{}{} - } else { - repeated[id] = struct{}{} - } - } - } - store.Close() - - // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - statedb.AddBalance(crypto.PubkeyToAddress(gapper.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(dangler.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(filler.PublicKey), uint256.NewInt(1000000)) - statedb.SetNonce(crypto.PubkeyToAddress(filler.PublicKey), 3) - statedb.AddBalance(crypto.PubkeyToAddress(overlapper.PublicKey), uint256.NewInt(1000000)) - statedb.SetNonce(crypto.PubkeyToAddress(overlapper.PublicKey), 2) - statedb.AddBalance(crypto.PubkeyToAddress(underpayer.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(outpricer.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(exceeder.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(overdrafter.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(overcapper.PublicKey), uint256.NewInt(10000000)) - statedb.AddBalance(crypto.PubkeyToAddress(duplicater.PublicKey), uint256.NewInt(1000000)) - statedb.AddBalance(crypto.PubkeyToAddress(repeater.PublicKey), uint256.NewInt(1000000)) - statedb.Commit(0, true) - - chain := &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(params.InitialBaseFee), - blobfee: uint256.NewInt(params.BlobTxMinBlobGasprice), - statedb: statedb, - } - pool := New(Config{Datadir: storage}, chain) - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - t.Fatalf("failed to create blob pool: %v", err) - } - defer pool.Close() - - // Verify that the malformed (case 1), badly signed (case 2) and gapped (case - // 3) txs have been deleted from the pool - alive := make(map[uint64]struct{}) - for _, txs := range pool.index { - for _, tx := range txs { - switch tx.id { - case malformed: - t.Errorf("malformed RLP transaction remained in storage") - case badsig: - t.Errorf("invalidly signed transaction remained in storage") - default: - if _, ok := dangling[tx.id]; ok { - t.Errorf("dangling transaction remained in storage: %d", tx.id) - } else if _, ok := filled[tx.id]; ok { - t.Errorf("filled transaction remained in storage: %d", tx.id) - } else if _, ok := overlapped[tx.id]; ok { - t.Errorf("overlapped transaction remained in storage: %d", tx.id) - } else if _, ok := gapped[tx.id]; ok { - t.Errorf("gapped transaction remained in storage: %d", tx.id) - } else if _, ok := underpaid[tx.id]; ok { - t.Errorf("underpaid transaction remained in storage: %d", tx.id) - } else if _, ok := outpriced[tx.id]; ok { - t.Errorf("outpriced transaction remained in storage: %d", tx.id) - } else if _, ok := exceeded[tx.id]; ok { - t.Errorf("fully overdrafted transaction remained in storage: %d", tx.id) - } else if _, ok := overdrafted[tx.id]; ok { - t.Errorf("partially overdrafted transaction remained in storage: %d", tx.id) - } else if _, ok := overcapped[tx.id]; ok { - t.Errorf("overcapped transaction remained in storage: %d", tx.id) - } else if _, ok := duplicated[tx.id]; ok { - t.Errorf("duplicated transaction remained in storage: %d", tx.id) - } else if _, ok := repeated[tx.id]; ok { - t.Errorf("repeated nonce transaction remained in storage: %d", tx.id) - } else { - alive[tx.id] = struct{}{} - } - } - } - } - // Verify that the rest of the transactions remained alive - if len(alive) != len(valids) { - t.Errorf("valid transaction count mismatch: have %d, want %d", len(alive), len(valids)) - } - for id := range alive { - if _, ok := valids[id]; !ok { - t.Errorf("extra transaction %d", id) - } - } - for id := range valids { - if _, ok := alive[id]; !ok { - t.Errorf("missing transaction %d", id) - } - } - // Verify all the calculated pool internals. Interestingly, this is **not** - // a duplication of the above checks, this actually validates the verifier - // using the above already hard coded checks. - // - // Do not remove this, nor alter the above to be generic. - verifyPoolInternals(t, pool) -} - -// Tests that transactions loaded from disk are indexed correctly. -// -// - 1. Transactions must be grouped by sender, sorted by nonce -// - 2. Eviction thresholds are calculated correctly for the sequences -// - 3. Balance usage of an account is totals across all transactions -func TestOpenIndex(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) - - // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) - - os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) - store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil) - - // Insert a sequence of transactions with varying price points to check that - // the cumulative minimum will be maintained. - var ( - key, _ = crypto.GenerateKey() - addr = crypto.PubkeyToAddress(key.PublicKey) - - txExecTipCaps = []uint64{10, 25, 5, 7, 1, 100} - txExecFeeCaps = []uint64{100, 90, 200, 10, 80, 300} - txBlobFeeCaps = []uint64{55, 66, 77, 33, 22, 11} - - //basefeeJumps = []float64{39.098, 38.204, 44.983, 19.549, 37.204, 48.426} // log 1.125 (exec fee cap) - //blobfeeJumps = []float64{34.023, 35.570, 36.879, 29.686, 26.243, 20.358} // log 1.125 (blob fee cap) - - evictExecTipCaps = []uint64{10, 10, 5, 5, 1, 1} - evictExecFeeJumps = []float64{39.098, 38.204, 38.204, 19.549, 19.549, 19.549} // min(log 1.125 (exec fee cap)) - evictBlobFeeJumps = []float64{34.023, 34.023, 34.023, 29.686, 26.243, 20.358} // min(log 1.125 (blob fee cap)) - - totalSpent = uint256.NewInt(21000*(100+90+200+10+80+300) + blobSize*(55+66+77+33+22+11) + 100*6) // 21000 gas x price + 128KB x blobprice + value - ) - for _, i := range []int{5, 3, 4, 2, 0, 1} { // Randomize the tx insertion order to force sorting on load - tx := makeTx(uint64(i), txExecTipCaps[i], txExecFeeCaps[i], txBlobFeeCaps[i], key) - blob, _ := rlp.EncodeToBytes(tx) - store.Put(blob) - } - store.Close() - - // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - statedb.AddBalance(addr, uint256.NewInt(1_000_000_000)) - statedb.Commit(0, true) - - chain := &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(params.InitialBaseFee), - blobfee: uint256.NewInt(params.BlobTxMinBlobGasprice), - statedb: statedb, - } - pool := New(Config{Datadir: storage}, chain) - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - t.Fatalf("failed to create blob pool: %v", err) - } - defer pool.Close() - - // Verify that the transactions have been sorted by nonce (case 1) - for i := 0; i < len(pool.index[addr]); i++ { - if pool.index[addr][i].nonce != uint64(i) { - t.Errorf("tx %d nonce mismatch: have %d, want %d", i, pool.index[addr][i].nonce, uint64(i)) - } - } - // Verify that the cumulative fee minimums have been correctly calculated (case 2) - for i, cap := range evictExecTipCaps { - if !pool.index[addr][i].evictionExecTip.Eq(uint256.NewInt(cap)) { - t.Errorf("eviction tip cap %d mismatch: have %d, want %d", i, pool.index[addr][i].evictionExecTip, cap) - } - } - for i, jumps := range evictExecFeeJumps { - if math.Abs(pool.index[addr][i].evictionExecFeeJumps-jumps) > 0.001 { - t.Errorf("eviction fee cap jumps %d mismatch: have %f, want %f", i, pool.index[addr][i].evictionExecFeeJumps, jumps) - } - } - for i, jumps := range evictBlobFeeJumps { - if math.Abs(pool.index[addr][i].evictionBlobFeeJumps-jumps) > 0.001 { - t.Errorf("eviction blob fee cap jumps %d mismatch: have %f, want %f", i, pool.index[addr][i].evictionBlobFeeJumps, jumps) - } - } - // Verify that the balance usage has been correctly calculated (case 3) - if !pool.spent[addr].Eq(totalSpent) { - t.Errorf("expenditure mismatch: have %d, want %d", pool.spent[addr], totalSpent) - } - // Verify all the calculated pool internals. Interestingly, this is **not** - // a duplication of the above checks, this actually validates the verifier - // using the above already hard coded checks. - // - // Do not remove this, nor alter the above to be generic. - verifyPoolInternals(t, pool) -} - -// Tests that after indexing all the loaded transactions from disk, a price heap -// is correctly constructed based on the head basefee and blobfee. -func TestOpenHeap(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) - - // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) - - os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) - store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil) - - // Insert a few transactions from a few accounts. To remove randomness from - // the heap initialization, use a deterministic account/tx/priority ordering. - var ( - key1, _ = crypto.GenerateKey() - key2, _ = crypto.GenerateKey() - key3, _ = crypto.GenerateKey() - - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - addr3 = crypto.PubkeyToAddress(key3.PublicKey) - ) - if bytes.Compare(addr1[:], addr2[:]) > 0 { - key1, addr1, key2, addr2 = key2, addr2, key1, addr1 - } - if bytes.Compare(addr1[:], addr3[:]) > 0 { - key1, addr1, key3, addr3 = key3, addr3, key1, addr1 - } - if bytes.Compare(addr2[:], addr3[:]) > 0 { - key2, addr2, key3, addr3 = key3, addr3, key2, addr2 - } - var ( - tx1 = makeTx(0, 1, 1000, 90, key1) - tx2 = makeTx(0, 1, 800, 70, key2) - tx3 = makeTx(0, 1, 1500, 110, key3) - - blob1, _ = rlp.EncodeToBytes(tx1) - blob2, _ = rlp.EncodeToBytes(tx2) - blob3, _ = rlp.EncodeToBytes(tx3) - - heapOrder = []common.Address{addr2, addr1, addr3} - heapIndex = map[common.Address]int{addr2: 0, addr1: 1, addr3: 2} - ) - store.Put(blob1) - store.Put(blob2) - store.Put(blob3) - store.Close() - - // Create a blob pool out of the pre-seeded data - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000)) - statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000)) - statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000)) - statedb.Commit(0, true) - - chain := &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(1050), - blobfee: uint256.NewInt(105), - statedb: statedb, - } - pool := New(Config{Datadir: storage}, chain) - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - t.Fatalf("failed to create blob pool: %v", err) - } - defer pool.Close() - - // Verify that the heap's internal state matches the expectations - for i, addr := range pool.evict.addrs { - if addr != heapOrder[i] { - t.Errorf("slot %d mismatch: have %v, want %v", i, addr, heapOrder[i]) - } - } - for addr, i := range pool.evict.index { - if i != heapIndex[addr] { - t.Errorf("index for %v mismatch: have %d, want %d", addr, i, heapIndex[addr]) - } - } - // Verify all the calculated pool internals. Interestingly, this is **not** - // a duplication of the above checks, this actually validates the verifier - // using the above already hard coded checks. - // - // Do not remove this, nor alter the above to be generic. - verifyPoolInternals(t, pool) -} - -// Tests that after the pool's previous state is loaded back, any transactions -// over the new storage cap will get dropped. -func TestOpenCap(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) - - // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) - - os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) - store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil) - - // Insert a few transactions from a few accounts - var ( - key1, _ = crypto.GenerateKey() - key2, _ = crypto.GenerateKey() - key3, _ = crypto.GenerateKey() - - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = crypto.PubkeyToAddress(key2.PublicKey) - addr3 = crypto.PubkeyToAddress(key3.PublicKey) - - tx1 = makeTx(0, 1, 1000, 100, key1) - tx2 = makeTx(0, 1, 800, 70, key2) - tx3 = makeTx(0, 1, 1500, 110, key3) - - blob1, _ = rlp.EncodeToBytes(tx1) - blob2, _ = rlp.EncodeToBytes(tx2) - blob3, _ = rlp.EncodeToBytes(tx3) - - keep = []common.Address{addr1, addr3} - drop = []common.Address{addr2} - size = uint64(2 * (txAvgSize + blobSize)) - ) - store.Put(blob1) - store.Put(blob2) - store.Put(blob3) - store.Close() - - // Verify pool capping twice: first by reducing the data cap, then restarting - // with a high cap to ensure everything was persisted previously - for _, datacap := range []uint64{2 * (txAvgSize + blobSize), 100 * (txAvgSize + blobSize)} { - // Create a blob pool out of the pre-seeded data, but cap it to 2 blob transaction - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - statedb.AddBalance(addr1, uint256.NewInt(1_000_000_000)) - statedb.AddBalance(addr2, uint256.NewInt(1_000_000_000)) - statedb.AddBalance(addr3, uint256.NewInt(1_000_000_000)) - statedb.Commit(0, true) - - chain := &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(1050), - blobfee: uint256.NewInt(105), - statedb: statedb, - } - pool := New(Config{Datadir: storage, Datacap: datacap}, chain) - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - t.Fatalf("failed to create blob pool: %v", err) - } - // Verify that enough transactions have been dropped to get the pool's size - // under the requested limit - if len(pool.index) != len(keep) { - t.Errorf("tracked account count mismatch: have %d, want %d", len(pool.index), len(keep)) - } - for _, addr := range keep { - if _, ok := pool.index[addr]; !ok { - t.Errorf("expected account %v missing from pool", addr) - } - } - for _, addr := range drop { - if _, ok := pool.index[addr]; ok { - t.Errorf("unexpected account %v present in pool", addr) - } - } - if pool.stored != size { - t.Errorf("pool stored size mismatch: have %v, want %v", pool.stored, size) - } - // Verify all the calculated pool internals. Interestingly, this is **not** - // a duplication of the above checks, this actually validates the verifier - // using the above already hard coded checks. - // - // Do not remove this, nor alter the above to be generic. - verifyPoolInternals(t, pool) - - pool.Close() - } -} - -// Tests that adding transaction will correctly store it in the persistent store -// and update all the indices. -// -// Note, this tests mostly checks the pool transaction shuffling logic or things -// specific to the blob pool. It does not do an exhaustive transaction validity -// check. -func TestAdd(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelTrace, true))) - - // seed is a helper tumpe to seed an initial state db and pool - type seed struct { - balance uint64 - nonce uint64 - txs []*types.BlobTx - } - - // addtx is a helper sender/tx tuple to represent a new tx addition - type addtx struct { - from string - tx *types.BlobTx - err error - } - - tests := []struct { - seeds map[string]seed - adds []addtx - }{ - // Transactions from new accounts should be accepted if their initial - // nonce matches the expected one from the statedb. Higher or lower must - // be rejected. - { - seeds: map[string]seed{ - "alice": {balance: 21100 + blobSize}, - "bob": {balance: 21100 + blobSize, nonce: 1}, - "claire": {balance: 21100 + blobSize}, - "dave": {balance: 21100 + blobSize, nonce: 1}, - }, - adds: []addtx{ - { // New account, no previous txs: accept nonce 0 - from: "alice", - tx: makeUnsignedTx(0, 1, 1, 1), - err: nil, - }, - { // Old account, 1 tx in chain, 0 pending: accept nonce 1 - from: "bob", - tx: makeUnsignedTx(1, 1, 1, 1), - err: nil, - }, - { // New account, no previous txs: reject nonce 1 - from: "claire", - tx: makeUnsignedTx(1, 1, 1, 1), - err: core.ErrNonceTooHigh, - }, - { // Old account, 1 tx in chain, 0 pending: reject nonce 0 - from: "dave", - tx: makeUnsignedTx(0, 1, 1, 1), - err: core.ErrNonceTooLow, - }, - { // Old account, 1 tx in chain, 0 pending: reject nonce 2 - from: "dave", - tx: makeUnsignedTx(2, 1, 1, 1), - err: core.ErrNonceTooHigh, - }, - }, - }, - // Transactions from already pooled accounts should only be accepted if - // the nonces are contiguous (ignore prices for now, will check later) - { - seeds: map[string]seed{ - "alice": { - balance: 1000000, - txs: []*types.BlobTx{ - makeUnsignedTx(0, 1, 1, 1), - }, - }, - "bob": { - balance: 1000000, - nonce: 1, - txs: []*types.BlobTx{ - makeUnsignedTx(1, 1, 1, 1), - }, - }, - }, - adds: []addtx{ - { // New account, 1 tx pending: reject replacement nonce 0 (ignore price for now) - from: "alice", - tx: makeUnsignedTx(0, 1, 1, 1), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 1 tx pending: accept nonce 1 - from: "alice", - tx: makeUnsignedTx(1, 1, 1, 1), - err: nil, - }, - { // New account, 2 txs pending: reject nonce 3 - from: "alice", - tx: makeUnsignedTx(3, 1, 1, 1), - err: core.ErrNonceTooHigh, - }, - { // New account, 2 txs pending: accept nonce 2 - from: "alice", - tx: makeUnsignedTx(2, 1, 1, 1), - err: nil, - }, - { // New account, 3 txs pending: accept nonce 3 now - from: "alice", - tx: makeUnsignedTx(3, 1, 1, 1), - err: nil, - }, - { // Old account, 1 tx in chain, 1 tx pending: reject replacement nonce 1 (ignore price for now) - from: "bob", - tx: makeUnsignedTx(1, 1, 1, 1), - err: txpool.ErrReplaceUnderpriced, - }, - { // Old account, 1 tx in chain, 1 tx pending: accept nonce 2 (ignore price for now) - from: "bob", - tx: makeUnsignedTx(2, 1, 1, 1), - err: nil, - }, - }, - }, - // Transactions should only be accepted into the pool if the cumulative - // expenditure doesn't overflow the account balance - { - seeds: map[string]seed{ - "alice": {balance: 63299 + 3*blobSize}, // 3 tx - 1 wei - }, - adds: []addtx{ - { // New account, no previous txs: accept nonce 0 with 21100 wei spend - from: "alice", - tx: makeUnsignedTx(0, 1, 1, 1), - err: nil, - }, - { // New account, 1 pooled tx with 21100 wei spent: accept nonce 1 with 21100 wei spend - from: "alice", - tx: makeUnsignedTx(1, 1, 1, 1), - err: nil, - }, - { // New account, 2 pooled tx with 42200 wei spent: reject nonce 2 with 21100 wei spend (1 wei overflow) - from: "alice", - tx: makeUnsignedTx(2, 1, 1, 1), - err: core.ErrInsufficientFunds, - }, - }, - }, - // Transactions should only be accepted into the pool if the total count - // from the same account doesn't overflow the pool limits - { - seeds: map[string]seed{ - "alice": {balance: 10000000}, - }, - adds: []addtx{ - { // New account, no previous txs, 16 slots left: accept nonce 0 - from: "alice", - tx: makeUnsignedTx(0, 1, 1, 1), - err: nil, - }, - { // New account, 1 pooled tx, 15 slots left: accept nonce 1 - from: "alice", - tx: makeUnsignedTx(1, 1, 1, 1), - err: nil, - }, - { // New account, 2 pooled tx, 14 slots left: accept nonce 2 - from: "alice", - tx: makeUnsignedTx(2, 1, 1, 1), - err: nil, - }, - { // New account, 3 pooled tx, 13 slots left: accept nonce 3 - from: "alice", - tx: makeUnsignedTx(3, 1, 1, 1), - err: nil, - }, - { // New account, 4 pooled tx, 12 slots left: accept nonce 4 - from: "alice", - tx: makeUnsignedTx(4, 1, 1, 1), - err: nil, - }, - { // New account, 5 pooled tx, 11 slots left: accept nonce 5 - from: "alice", - tx: makeUnsignedTx(5, 1, 1, 1), - err: nil, - }, - { // New account, 6 pooled tx, 10 slots left: accept nonce 6 - from: "alice", - tx: makeUnsignedTx(6, 1, 1, 1), - err: nil, - }, - { // New account, 7 pooled tx, 9 slots left: accept nonce 7 - from: "alice", - tx: makeUnsignedTx(7, 1, 1, 1), - err: nil, - }, - { // New account, 8 pooled tx, 8 slots left: accept nonce 8 - from: "alice", - tx: makeUnsignedTx(8, 1, 1, 1), - err: nil, - }, - { // New account, 9 pooled tx, 7 slots left: accept nonce 9 - from: "alice", - tx: makeUnsignedTx(9, 1, 1, 1), - err: nil, - }, - { // New account, 10 pooled tx, 6 slots left: accept nonce 10 - from: "alice", - tx: makeUnsignedTx(10, 1, 1, 1), - err: nil, - }, - { // New account, 11 pooled tx, 5 slots left: accept nonce 11 - from: "alice", - tx: makeUnsignedTx(11, 1, 1, 1), - err: nil, - }, - { // New account, 12 pooled tx, 4 slots left: accept nonce 12 - from: "alice", - tx: makeUnsignedTx(12, 1, 1, 1), - err: nil, - }, - { // New account, 13 pooled tx, 3 slots left: accept nonce 13 - from: "alice", - tx: makeUnsignedTx(13, 1, 1, 1), - err: nil, - }, - { // New account, 14 pooled tx, 2 slots left: accept nonce 14 - from: "alice", - tx: makeUnsignedTx(14, 1, 1, 1), - err: nil, - }, - { // New account, 15 pooled tx, 1 slots left: accept nonce 15 - from: "alice", - tx: makeUnsignedTx(15, 1, 1, 1), - err: nil, - }, - { // New account, 16 pooled tx, 0 slots left: accept nonce 15 replacement - from: "alice", - tx: makeUnsignedTx(15, 10, 10, 10), - err: nil, - }, - { // New account, 16 pooled tx, 0 slots left: reject nonce 16 with overcap - from: "alice", - tx: makeUnsignedTx(16, 1, 1, 1), - err: txpool.ErrAccountLimitExceeded, - }, - }, - }, - // Previously existing transactions should be allowed to be replaced iff - // the new cumulative expenditure can be covered by the account and the - // prices are bumped all around (no percentage check here). - { - seeds: map[string]seed{ - "alice": {balance: 2*100 + 5*21000 + 3*blobSize}, - }, - adds: []addtx{ - { // New account, no previous txs: reject nonce 0 with 341172 wei spend - from: "alice", - tx: makeUnsignedTx(0, 1, 20, 1), - err: core.ErrInsufficientFunds, - }, - { // New account, no previous txs: accept nonce 0 with 173172 wei spend - from: "alice", - tx: makeUnsignedTx(0, 1, 2, 1), - err: nil, - }, - { // New account, 1 pooled tx with 173172 wei spent: accept nonce 1 with 152172 wei spend - from: "alice", - tx: makeUnsignedTx(1, 1, 1, 1), - err: nil, - }, - { // New account, 2 pooled tx with 325344 wei spent: reject nonce 0 with 599684 wei spend (173072 extra) (would overflow balance at nonce 1) - from: "alice", - tx: makeUnsignedTx(0, 2, 5, 2), - err: core.ErrInsufficientFunds, - }, - { // New account, 2 pooled tx with 325344 wei spent: reject nonce 0 with no-gastip-bump - from: "alice", - tx: makeUnsignedTx(0, 1, 3, 2), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 2 pooled tx with 325344 wei spent: reject nonce 0 with no-gascap-bump - from: "alice", - tx: makeUnsignedTx(0, 2, 2, 2), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 2 pooled tx with 325344 wei spent: reject nonce 0 with no-blobcap-bump - from: "alice", - tx: makeUnsignedTx(0, 2, 4, 1), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 2 pooled tx with 325344 wei spent: accept nonce 0 with 84100 wei spend (42000 extra) - from: "alice", - tx: makeUnsignedTx(0, 2, 4, 2), - err: nil, - }, - }, - }, - // Previously existing transactions should be allowed to be replaced iff - // the new prices are bumped by a sufficient amount. - { - seeds: map[string]seed{ - "alice": {balance: 100 + 8*21000 + 4*blobSize}, - }, - adds: []addtx{ - { // New account, no previous txs: accept nonce 0 - from: "alice", - tx: makeUnsignedTx(0, 2, 4, 2), - err: nil, - }, - { // New account, 1 pooled tx: reject nonce 0 with low-gastip-bump - from: "alice", - tx: makeUnsignedTx(0, 3, 8, 4), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 1 pooled tx: reject nonce 0 with low-gascap-bump - from: "alice", - tx: makeUnsignedTx(0, 4, 6, 4), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 1 pooled tx: reject nonce 0 with low-blobcap-bump - from: "alice", - tx: makeUnsignedTx(0, 4, 8, 3), - err: txpool.ErrReplaceUnderpriced, - }, - { // New account, 1 pooled tx: accept nonce 0 with all-bumps - from: "alice", - tx: makeUnsignedTx(0, 4, 8, 4), - err: nil, - }, - }, - }, - // Blob transactions that don't meet the min blob gas price should be rejected - { - seeds: map[string]seed{ - "alice": {balance: 10000000}, - }, - adds: []addtx{ - { // New account, no previous txs, nonce 0, but blob fee cap too low - from: "alice", - tx: makeUnsignedTx(0, 1, 1, 0), - err: txpool.ErrUnderpriced, - }, - { // Same as above but blob fee cap equals minimum, should be accepted - from: "alice", - tx: makeUnsignedTx(0, 1, 1, params.BlobTxMinBlobGasprice), - err: nil, - }, - }, - }, - } - for i, tt := range tests { - // Create a temporary folder for the persistent backend - storage, _ := os.MkdirTemp("", "blobpool-") - defer os.RemoveAll(storage) // late defer, still ok - - os.MkdirAll(filepath.Join(storage, pendingTransactionStore), 0700) - store, _ := billy.Open(billy.Options{Path: filepath.Join(storage, pendingTransactionStore)}, newSlotter(), nil) - - // Insert the seed transactions for the pool startup - var ( - keys = make(map[string]*ecdsa.PrivateKey) - addrs = make(map[string]common.Address) - ) - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - for acc, seed := range tt.seeds { - // Generate a new random key/address for the seed account - keys[acc], _ = crypto.GenerateKey() - addrs[acc] = crypto.PubkeyToAddress(keys[acc].PublicKey) - - // Seed the state database with this account - statedb.AddBalance(addrs[acc], new(uint256.Int).SetUint64(seed.balance)) - statedb.SetNonce(addrs[acc], seed.nonce) - - // Sign the seed transactions and store them in the data store - for _, tx := range seed.txs { - signed := types.MustSignNewTx(keys[acc], types.LatestSigner(testChainConfig), tx) - blob, _ := rlp.EncodeToBytes(signed) - store.Put(blob) - } - } - statedb.Commit(0, true) - store.Close() - - // Create a blob pool out of the pre-seeded dats - chain := &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(1050), - blobfee: uint256.NewInt(105), - statedb: statedb, - } - pool := New(Config{Datadir: storage}, chain) - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - t.Fatalf("test %d: failed to create blob pool: %v", i, err) - } - verifyPoolInternals(t, pool) - - // Add each transaction one by one, verifying the pool internals in between - for j, add := range tt.adds { - signed, _ := types.SignNewTx(keys[add.from], types.LatestSigner(testChainConfig), add.tx) - if err := pool.add(signed, false); !errors.Is(err, add.err) { - t.Errorf("test %d, tx %d: adding transaction error mismatch: have %v, want %v", i, j, err, add.err) - } - verifyPoolInternals(t, pool) - } - // Verify the pool internals and close down the test - verifyPoolInternals(t, pool) - pool.Close() - } -} - -// Benchmarks the time it takes to assemble the lazy pending transaction list -// from the pool contents. -func BenchmarkPoolPending100Mb(b *testing.B) { benchmarkPoolPending(b, 100_000_000) } -func BenchmarkPoolPending1GB(b *testing.B) { benchmarkPoolPending(b, 1_000_000_000) } -func BenchmarkPoolPending10GB(b *testing.B) { benchmarkPoolPending(b, 10_000_000_000) } - -func benchmarkPoolPending(b *testing.B, datacap uint64) { - // Calculate the maximum number of transaction that would fit into the pool - // and generate a set of random accounts to seed them with. - capacity := datacap / params.BlobTxBlobGasPerBlob - - var ( - basefee = uint64(1050) - blobfee = uint64(105) - signer = types.LatestSigner(testChainConfig) - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) - chain = &testBlockChain{ - config: testChainConfig, - basefee: uint256.NewInt(basefee), - blobfee: uint256.NewInt(blobfee), - statedb: statedb, - } - pool = New(Config{Datadir: ""}, chain) - ) - - if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil { - b.Fatalf("failed to create blob pool: %v", err) - } - // Fill the pool up with one random transaction from each account with the - // same price and everything to maximize the worst case scenario - for i := 0; i < int(capacity); i++ { - blobtx := makeUnsignedTx(0, 10, basefee+10, blobfee) - blobtx.R = uint256.NewInt(1) - blobtx.S = uint256.NewInt(uint64(100 + i)) - blobtx.V = uint256.NewInt(0) - tx := types.NewTx(blobtx) - addr, err := types.Sender(signer, tx) - if err != nil { - b.Fatal(err) - } - statedb.AddBalance(addr, uint256.NewInt(1_000_000_000)) - pool.add(tx, false) - } - statedb.Commit(0, true) - defer pool.Close() - - // Benchmark assembling the pending - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - p := pool.Pending(txpool.PendingFilter{ - MinTip: uint256.NewInt(1), - BaseFee: chain.basefee, - BlobFee: chain.blobfee, - }) - if len(p) != int(capacity) { - b.Fatalf("have %d want %d", len(p), capacity) - } - } -} diff --git a/builder/core/txpool/blobpool/config.go b/builder/core/txpool/blobpool/config.go deleted file mode 100644 index bb27bcf6b..000000000 --- a/builder/core/txpool/blobpool/config.go +++ /dev/null @@ -1,58 +0,0 @@ -// 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 blobpool - -import ( - "time" - - "github.com/ethereum/go-ethereum/log" -) - -// Config are the configuration parameters of the blob transaction pool. -type Config struct { - Datadir string // Data directory containing the currently executable blobs - Datacap uint64 // Soft-cap of database storage (hard cap is larger due to overhead) - PriceBump uint64 // Minimum price bump percentage to replace an already existing nonce - PrivateTxLifetime time.Duration // Maximum amount of time to keep private transactions private -} - -// DefaultConfig contains the default configurations for the transaction pool. -var DefaultConfig = Config{ - Datadir: "blobpool", - Datacap: 10 * 1024 * 1024 * 1024 / 4, // TODO(karalabe): /4 handicap for rollout, gradually bump back up to 10GB - PriceBump: 100, // either have patience or be aggressive, no mushy ground - PrivateTxLifetime: 3 * 24 * time.Hour, -} - -// sanitize checks the provided user configurations and changes anything that's -// unreasonable or unworkable. -func (config *Config) sanitize() Config { - conf := *config - if conf.Datacap < 1 { - log.Warn("Sanitizing invalid blobpool storage cap", "provided", conf.Datacap, "updated", DefaultConfig.Datacap) - conf.Datacap = DefaultConfig.Datacap - } - if conf.PriceBump < 1 { - log.Warn("Sanitizing invalid blobpool price bump", "provided", conf.PriceBump, "updated", DefaultConfig.PriceBump) - conf.PriceBump = DefaultConfig.PriceBump - } - if conf.PrivateTxLifetime < 1 { - log.Warn("Sanitizing invalid txpool private tx lifetime", "provided", conf.PrivateTxLifetime, "updated", DefaultConfig.PrivateTxLifetime) - conf.PrivateTxLifetime = DefaultConfig.PrivateTxLifetime - } - return conf -} diff --git a/builder/core/txpool/blobpool/evictheap.go b/builder/core/txpool/blobpool/evictheap.go deleted file mode 100644 index bc4543a35..000000000 --- a/builder/core/txpool/blobpool/evictheap.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "bytes" - "container/heap" - "math" - "sort" - - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" -) - -// evictHeap is a helper data structure to keep track of the cheapest bottleneck -// transaction from each account to determine which account to evict from. -// -// The heap internally tracks a slice of cheapest transactions from each account -// and a mapping from addresses to indices for direct removals/updates. -// -// The goal of the heap is to decide which account has the worst bottleneck to -// evict transactions from. -type evictHeap struct { - metas *map[common.Address][]*blobTxMeta // Pointer to the blob pool's index for price retrievals - - basefeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the base fee - blobfeeJumps float64 // Pre-calculated absolute dynamic fee jumps for the blob fee - - addrs []common.Address // Heap of addresses to retrieve the cheapest out of - index map[common.Address]int // Indices into the heap for replacements -} - -// newPriceHeap creates a new heap of cheapest accounts in the blob pool to evict -// from in case of over saturation. -func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index *map[common.Address][]*blobTxMeta) *evictHeap { - heap := &evictHeap{ - metas: index, - index: make(map[common.Address]int), - } - // Populate the heap in account sort order. Not really needed in practice, - // but it makes the heap initialization deterministic and less annoying to - // test in unit tests. - addrs := make([]common.Address, 0, len(*index)) - for addr := range *index { - addrs = append(addrs, addr) - } - sort.Slice(addrs, func(i, j int) bool { return bytes.Compare(addrs[i][:], addrs[j][:]) < 0 }) - - for _, addr := range addrs { - heap.index[addr] = len(heap.addrs) - heap.addrs = append(heap.addrs, addr) - } - heap.reinit(basefee, blobfee, true) - return heap -} - -// reinit updates the pre-calculated dynamic fee jumps in the price heap and runs -// the sorting algorithm from scratch on the entire heap. -func (h *evictHeap) reinit(basefee *uint256.Int, blobfee *uint256.Int, force bool) { - // If the update is mostly the same as the old, don't sort pointlessly - basefeeJumps := dynamicFeeJumps(basefee) - blobfeeJumps := dynamicFeeJumps(blobfee) - - if !force && math.Abs(h.basefeeJumps-basefeeJumps) < 0.01 && math.Abs(h.blobfeeJumps-blobfeeJumps) < 0.01 { // TODO(karalabe): 0.01 enough, maybe should be smaller? Maybe this optimization is moot? - return - } - // One or both of the dynamic fees jumped, resort the pool - h.basefeeJumps = basefeeJumps - h.blobfeeJumps = blobfeeJumps - - heap.Init(h) -} - -// Len implements sort.Interface as part of heap.Interface, returning the number -// of accounts in the pool which can be considered for eviction. -func (h *evictHeap) Len() int { - return len(h.addrs) -} - -// Less implements sort.Interface as part of heap.Interface, returning which of -// the two requested accounts has a cheaper bottleneck. -func (h *evictHeap) Less(i, j int) bool { - txsI := (*(h.metas))[h.addrs[i]] - txsJ := (*(h.metas))[h.addrs[j]] - - lastI := txsI[len(txsI)-1] - lastJ := txsJ[len(txsJ)-1] - - prioI := evictionPriority(h.basefeeJumps, lastI.evictionExecFeeJumps, h.blobfeeJumps, lastI.evictionBlobFeeJumps) - if prioI > 0 { - prioI = 0 - } - prioJ := evictionPriority(h.basefeeJumps, lastJ.evictionExecFeeJumps, h.blobfeeJumps, lastJ.evictionBlobFeeJumps) - if prioJ > 0 { - prioJ = 0 - } - if prioI == prioJ { - return lastI.evictionExecTip.Lt(lastJ.evictionExecTip) - } - return prioI < prioJ -} - -// Swap implements sort.Interface as part of heap.Interface, maintaining both the -// order of the accounts according to the heap, and the account->item slot mapping -// for replacements. -func (h *evictHeap) Swap(i, j int) { - h.index[h.addrs[i]], h.index[h.addrs[j]] = h.index[h.addrs[j]], h.index[h.addrs[i]] - h.addrs[i], h.addrs[j] = h.addrs[j], h.addrs[i] -} - -// Push implements heap.Interface, appending an item to the end of the account -// ordering as well as the address to item slot mapping. -func (h *evictHeap) Push(x any) { - h.index[x.(common.Address)] = len(h.addrs) - h.addrs = append(h.addrs, x.(common.Address)) -} - -// Pop implements heap.Interface, removing and returning the last element of the -// heap. -// -// Note, use `heap.Pop`, not `evictHeap.Pop`. This method is used by Go's heap, -// to provide the functionality, it does not embed it. -func (h *evictHeap) Pop() any { - // Remove the last element from the heap - size := len(h.addrs) - addr := h.addrs[size-1] - h.addrs = h.addrs[:size-1] - - // Unindex the removed element and return - delete(h.index, addr) - return addr -} diff --git a/builder/core/txpool/blobpool/evictheap_test.go b/builder/core/txpool/blobpool/evictheap_test.go deleted file mode 100644 index 01b136551..000000000 --- a/builder/core/txpool/blobpool/evictheap_test.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "container/heap" - mrand "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -var rand = mrand.New(mrand.NewSource(1)) - -// verifyHeapInternals verifies that all accounts present in the index are also -// present in the heap and internals are consistent across various indices. -func verifyHeapInternals(t *testing.T, evict *evictHeap) { - t.Helper() - - // Ensure that all accounts are present in the heap and no extras - seen := make(map[common.Address]struct{}) - for i, addr := range evict.addrs { - seen[addr] = struct{}{} - if _, ok := (*evict.metas)[addr]; !ok { - t.Errorf("heap contains unexpected address at slot %d: %v", i, addr) - } - } - for addr := range *evict.metas { - if _, ok := seen[addr]; !ok { - t.Errorf("heap is missing required address %v", addr) - } - } - if len(evict.addrs) != len(*evict.metas) { - t.Errorf("heap size %d mismatches metadata size %d", len(evict.addrs), len(*evict.metas)) - } - // Ensure that all accounts are present in the heap order index and no extras - have := make([]common.Address, len(evict.index)) - for addr, i := range evict.index { - have[i] = addr - } - if len(have) != len(evict.addrs) { - t.Errorf("heap index size %d mismatches heap size %d", len(have), len(evict.addrs)) - } - for i := 0; i < len(have) && i < len(evict.addrs); i++ { - if have[i] != evict.addrs[i] { - t.Errorf("heap index for slot %d mismatches: have %v, want %v", i, have[i], evict.addrs[i]) - } - } -} - -// Tests that the price heap can correctly sort its set of transactions based on -// an input base- and blob fee. -func TestPriceHeapSorting(t *testing.T) { - tests := []struct { - execTips []uint64 - execFees []uint64 - blobFees []uint64 - - basefee uint64 - blobfee uint64 - - order []int - }{ - // If everything is above the basefee and blobfee, order by miner tip - { - execTips: []uint64{1, 0, 2}, - execFees: []uint64{1, 2, 3}, - blobFees: []uint64{3, 2, 1}, - basefee: 0, - blobfee: 0, - order: []int{1, 0, 2}, - }, - // If only basefees are used (blob fee matches with network), return the - // ones the furthest below the current basefee, splitting same ones with - // the tip. Anything above the basefee should be split by tip. - { - execTips: []uint64{100, 50, 100, 50, 1, 2, 3}, - execFees: []uint64{1000, 1000, 500, 500, 2000, 2000, 2000}, - blobFees: []uint64{0, 0, 0, 0, 0, 0, 0}, - basefee: 1999, - blobfee: 0, - order: []int{3, 2, 1, 0, 4, 5, 6}, - }, - // If only blobfees are used (base fee matches with network), return the - // ones the furthest below the current blobfee, splitting same ones with - // the tip. Anything above the blobfee should be split by tip. - { - execTips: []uint64{100, 50, 100, 50, 1, 2, 3}, - execFees: []uint64{0, 0, 0, 0, 0, 0, 0}, - blobFees: []uint64{1000, 1000, 500, 500, 2000, 2000, 2000}, - basefee: 0, - blobfee: 1999, - order: []int{3, 2, 1, 0, 4, 5, 6}, - }, - // If both basefee and blobfee is specified, sort by the larger distance - // of the two from the current network conditions, splitting same (loglog) - // ones via the tip. - // - // Basefee: 1000 - // Blobfee: 100 - // - // Tx #0: (800, 80) - 2 jumps below both => priority -1 - // Tx #1: (630, 63) - 4 jumps below both => priority -2 - // Tx #2: (800, 63) - 2 jumps below basefee, 4 jumps below blobfee => priority -2 (blob penalty dominates) - // Tx #3: (630, 80) - 4 jumps below basefee, 2 jumps below blobfee => priority -2 (base penalty dominates) - // - // Txs 1, 2, 3 share the same priority, split via tip, prefer 0 as the best - { - execTips: []uint64{1, 2, 3, 4}, - execFees: []uint64{800, 630, 800, 630}, - blobFees: []uint64{80, 63, 63, 80}, - basefee: 1000, - blobfee: 100, - order: []int{1, 2, 3, 0}, - }, - } - for i, tt := range tests { - // Create an index of the transactions - index := make(map[common.Address][]*blobTxMeta) - for j := byte(0); j < byte(len(tt.execTips)); j++ { - addr := common.Address{j} - - var ( - execTip = uint256.NewInt(tt.execTips[j]) - execFee = uint256.NewInt(tt.execFees[j]) - blobFee = uint256.NewInt(tt.blobFees[j]) - - basefeeJumps = dynamicFeeJumps(execFee) - blobfeeJumps = dynamicFeeJumps(blobFee) - ) - index[addr] = []*blobTxMeta{{ - id: uint64(j), - size: 128 * 1024, - nonce: 0, - execTipCap: execTip, - execFeeCap: execFee, - blobFeeCap: blobFee, - basefeeJumps: basefeeJumps, - blobfeeJumps: blobfeeJumps, - evictionExecTip: execTip, - evictionExecFeeJumps: basefeeJumps, - evictionBlobFeeJumps: blobfeeJumps, - }} - } - // Create a price heap and check the pop order - priceheap := newPriceHeap(uint256.NewInt(tt.basefee), uint256.NewInt(tt.blobfee), &index) - verifyHeapInternals(t, priceheap) - - for j := 0; j < len(tt.order); j++ { - if next := heap.Pop(priceheap); int(next.(common.Address)[0]) != tt.order[j] { - t.Errorf("test %d, item %d: order mismatch: have %d, want %d", i, j, next.(common.Address)[0], tt.order[j]) - } else { - delete(index, next.(common.Address)) // remove to simulate a correct pool for the test - } - verifyHeapInternals(t, priceheap) - } - } -} - -// Benchmarks reheaping the entire set of accounts in the blob pool. -func BenchmarkPriceHeapReinit1MB(b *testing.B) { benchmarkPriceHeapReinit(b, 1024*1024) } -func BenchmarkPriceHeapReinit10MB(b *testing.B) { benchmarkPriceHeapReinit(b, 10*1024*1024) } -func BenchmarkPriceHeapReinit100MB(b *testing.B) { benchmarkPriceHeapReinit(b, 100*1024*1024) } -func BenchmarkPriceHeapReinit1GB(b *testing.B) { benchmarkPriceHeapReinit(b, 1024*1024*1024) } -func BenchmarkPriceHeapReinit10GB(b *testing.B) { benchmarkPriceHeapReinit(b, 10*1024*1024*1024) } -func BenchmarkPriceHeapReinit25GB(b *testing.B) { benchmarkPriceHeapReinit(b, 25*1024*1024*1024) } -func BenchmarkPriceHeapReinit50GB(b *testing.B) { benchmarkPriceHeapReinit(b, 50*1024*1024*1024) } -func BenchmarkPriceHeapReinit100GB(b *testing.B) { benchmarkPriceHeapReinit(b, 100*1024*1024*1024) } - -func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) { - // Calculate how many unique transactions we can fit into the provided disk - // data cap - blobs := datacap / (params.BlobTxBytesPerFieldElement * params.BlobTxFieldElementsPerBlob) - - // Create a random set of transactions with random fees. Use a separate account - // for each transaction to make it worse case. - index := make(map[common.Address][]*blobTxMeta) - for i := 0; i < int(blobs); i++ { - var addr common.Address - rand.Read(addr[:]) - - var ( - execTip = uint256.NewInt(rand.Uint64()) - execFee = uint256.NewInt(rand.Uint64()) - blobFee = uint256.NewInt(rand.Uint64()) - - basefeeJumps = dynamicFeeJumps(execFee) - blobfeeJumps = dynamicFeeJumps(blobFee) - ) - index[addr] = []*blobTxMeta{{ - id: uint64(i), - size: 128 * 1024, - nonce: 0, - execTipCap: execTip, - execFeeCap: execFee, - blobFeeCap: blobFee, - basefeeJumps: basefeeJumps, - blobfeeJumps: blobfeeJumps, - evictionExecTip: execTip, - evictionExecFeeJumps: basefeeJumps, - evictionBlobFeeJumps: blobfeeJumps, - }} - } - // Create a price heap and reinit it over and over - heap := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), &index) - - basefees := make([]*uint256.Int, b.N) - blobfees := make([]*uint256.Int, b.N) - for i := 0; i < b.N; i++ { - basefees[i] = uint256.NewInt(rand.Uint64()) - blobfees[i] = uint256.NewInt(rand.Uint64()) - } - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - heap.reinit(basefees[i], blobfees[i], true) - } -} - -// Benchmarks overflowing the heap over and over (add and then drop). -func BenchmarkPriceHeapOverflow1MB(b *testing.B) { benchmarkPriceHeapOverflow(b, 1024*1024) } -func BenchmarkPriceHeapOverflow10MB(b *testing.B) { benchmarkPriceHeapOverflow(b, 10*1024*1024) } -func BenchmarkPriceHeapOverflow100MB(b *testing.B) { benchmarkPriceHeapOverflow(b, 100*1024*1024) } -func BenchmarkPriceHeapOverflow1GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 1024*1024*1024) } -func BenchmarkPriceHeapOverflow10GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 10*1024*1024*1024) } -func BenchmarkPriceHeapOverflow25GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 25*1024*1024*1024) } -func BenchmarkPriceHeapOverflow50GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 50*1024*1024*1024) } -func BenchmarkPriceHeapOverflow100GB(b *testing.B) { benchmarkPriceHeapOverflow(b, 100*1024*1024*1024) } - -func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) { - // Calculate how many unique transactions we can fit into the provided disk - // data cap - blobs := datacap / (params.BlobTxBytesPerFieldElement * params.BlobTxFieldElementsPerBlob) - - // Create a random set of transactions with random fees. Use a separate account - // for each transaction to make it worse case. - index := make(map[common.Address][]*blobTxMeta) - for i := 0; i < int(blobs); i++ { - var addr common.Address - rand.Read(addr[:]) - - var ( - execTip = uint256.NewInt(rand.Uint64()) - execFee = uint256.NewInt(rand.Uint64()) - blobFee = uint256.NewInt(rand.Uint64()) - - basefeeJumps = dynamicFeeJumps(execFee) - blobfeeJumps = dynamicFeeJumps(blobFee) - ) - index[addr] = []*blobTxMeta{{ - id: uint64(i), - size: 128 * 1024, - nonce: 0, - execTipCap: execTip, - execFeeCap: execFee, - blobFeeCap: blobFee, - basefeeJumps: basefeeJumps, - blobfeeJumps: blobfeeJumps, - evictionExecTip: execTip, - evictionExecFeeJumps: basefeeJumps, - evictionBlobFeeJumps: blobfeeJumps, - }} - } - // Create a price heap and overflow it over and over - evict := newPriceHeap(uint256.NewInt(rand.Uint64()), uint256.NewInt(rand.Uint64()), &index) - var ( - addrs = make([]common.Address, b.N) - metas = make([]*blobTxMeta, b.N) - ) - for i := 0; i < b.N; i++ { - rand.Read(addrs[i][:]) - - var ( - execTip = uint256.NewInt(rand.Uint64()) - execFee = uint256.NewInt(rand.Uint64()) - blobFee = uint256.NewInt(rand.Uint64()) - - basefeeJumps = dynamicFeeJumps(execFee) - blobfeeJumps = dynamicFeeJumps(blobFee) - ) - metas[i] = &blobTxMeta{ - id: uint64(int(blobs) + i), - size: 128 * 1024, - nonce: 0, - execTipCap: execTip, - execFeeCap: execFee, - blobFeeCap: blobFee, - basefeeJumps: basefeeJumps, - blobfeeJumps: blobfeeJumps, - evictionExecTip: execTip, - evictionExecFeeJumps: basefeeJumps, - evictionBlobFeeJumps: blobfeeJumps, - } - } - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - index[addrs[i]] = []*blobTxMeta{metas[i]} - heap.Push(evict, addrs[i]) - - drop := heap.Pop(evict) - delete(index, drop.(common.Address)) - } -} diff --git a/builder/core/txpool/blobpool/interface.go b/builder/core/txpool/blobpool/interface.go deleted file mode 100644 index 6f296a54b..000000000 --- a/builder/core/txpool/blobpool/interface.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -// BlockChain defines the minimal set of methods needed to back a blob pool with -// a chain. Exists to allow mocking the live chain out of tests. -type BlockChain interface { - // Config retrieves the chain's fork configuration. - Config() *params.ChainConfig - - // CurrentBlock returns the current head of the chain. - CurrentBlock() *types.Header - - // CurrentFinalBlock returns the current block below which blobs should not - // be maintained anymore for reorg purposes. - CurrentFinalBlock() *types.Header - - // GetBlock retrieves a specific block, used during pool resets. - GetBlock(hash common.Hash, number uint64) *types.Block - - // StateAt returns a state database for a given root hash (generally the head). - StateAt(root common.Hash) (*state.StateDB, error) -} diff --git a/builder/core/txpool/blobpool/limbo.go b/builder/core/txpool/blobpool/limbo.go deleted file mode 100644 index ec754f689..000000000 --- a/builder/core/txpool/blobpool/limbo.go +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "errors" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/billy" -) - -// limboBlob is a wrapper around an opaque blobset that also contains the tx hash -// to which it belongs as well as the block number in which it was included for -// finality eviction. -type limboBlob struct { - TxHash common.Hash // Owner transaction's hash to support resurrecting reorged txs - Block uint64 // Block in which the blob transaction was included - Tx *types.Transaction -} - -// limbo is a light, indexed database to temporarily store recently included -// blobs until they are finalized. The purpose is to support small reorgs, which -// would require pulling back up old blobs (which aren't part of the chain). -// -// TODO(karalabe): Currently updating the inclusion block of a blob needs a full db rewrite. Can we do without? -type limbo struct { - store billy.Database // Persistent data store for limboed blobs - - index map[common.Hash]uint64 // Mappings from tx hashes to datastore ids - groups map[uint64]map[uint64]common.Hash // Set of txs included in past blocks -} - -// newLimbo opens and indexes a set of limboed blob transactions. -func newLimbo(datadir string) (*limbo, error) { - l := &limbo{ - index: make(map[common.Hash]uint64), - groups: make(map[uint64]map[uint64]common.Hash), - } - // Index all limboed blobs on disk and delete anything unprocessable - var fails []uint64 - index := func(id uint64, size uint32, data []byte) { - if l.parseBlob(id, data) != nil { - fails = append(fails, id) - } - } - store, err := billy.Open(billy.Options{Path: datadir}, newSlotter(), index) - if err != nil { - return nil, err - } - l.store = store - - if len(fails) > 0 { - log.Warn("Dropping invalidated limboed blobs", "ids", fails) - for _, id := range fails { - if err := l.store.Delete(id); err != nil { - l.Close() - return nil, err - } - } - } - return l, nil -} - -// Close closes down the underlying persistent store. -func (l *limbo) Close() error { - return l.store.Close() -} - -// parseBlob is a callback method on limbo creation that gets called for each -// limboed blob on disk to create the in-memory metadata index. -func (l *limbo) parseBlob(id uint64, data []byte) error { - item := new(limboBlob) - if err := rlp.DecodeBytes(data, item); err != nil { - // This path is impossible unless the disk data representation changes - // across restarts. For that ever improbable case, recover gracefully - // by ignoring this data entry. - log.Error("Failed to decode blob limbo entry", "id", id, "err", err) - return err - } - if _, ok := l.index[item.TxHash]; ok { - // This path is impossible, unless due to a programming error a blob gets - // inserted into the limbo which was already part of if. Recover gracefully - // by ignoring this data entry. - log.Error("Dropping duplicate blob limbo entry", "owner", item.TxHash, "id", id) - return errors.New("duplicate blob") - } - l.index[item.TxHash] = id - - if _, ok := l.groups[item.Block]; !ok { - l.groups[item.Block] = make(map[uint64]common.Hash) - } - l.groups[item.Block][id] = item.TxHash - - return nil -} - -// finalize evicts all blobs belonging to a recently finalized block or older. -func (l *limbo) finalize(final *types.Header) { - // Just in case there's no final block yet (network not yet merged, weird - // restart, sethead, etc), fail gracefully. - if final == nil { - log.Error("Nil finalized block cannot evict old blobs") - return - } - for block, ids := range l.groups { - if block > final.Number.Uint64() { - continue - } - for id, owner := range ids { - if err := l.store.Delete(id); err != nil { - log.Error("Failed to drop finalized blob", "block", block, "id", id, "err", err) - } - delete(l.index, owner) - } - delete(l.groups, block) - } -} - -// push stores a new blob transaction into the limbo, waiting until finality for -// it to be automatically evicted. -func (l *limbo) push(tx *types.Transaction, block uint64) error { - // If the blobs are already tracked by the limbo, consider it a programming - // error. There's not much to do against it, but be loud. - if _, ok := l.index[tx.Hash()]; ok { - log.Error("Limbo cannot push already tracked blobs", "tx", tx) - return errors.New("already tracked blob transaction") - } - if err := l.setAndIndex(tx, block); err != nil { - log.Error("Failed to set and index limboed blobs", "tx", tx, "err", err) - return err - } - return nil -} - -// pull retrieves a previously pushed set of blobs back from the limbo, removing -// it at the same time. This method should be used when a previously included blob -// transaction gets reorged out. -func (l *limbo) pull(tx common.Hash) (*types.Transaction, error) { - // If the blobs are not tracked by the limbo, there's not much to do. This - // can happen for example if a blob transaction is mined without pushing it - // into the network first. - id, ok := l.index[tx] - if !ok { - log.Trace("Limbo cannot pull non-tracked blobs", "tx", tx) - return nil, errors.New("unseen blob transaction") - } - item, err := l.getAndDrop(id) - if err != nil { - log.Error("Failed to get and drop limboed blobs", "tx", tx, "id", id, "err", err) - return nil, err - } - return item.Tx, nil -} - -// update changes the block number under which a blob transaction is tracked. This -// method should be used when a reorg changes a transaction's inclusion block. -// -// The method may log errors for various unexpected scenarios but will not return -// any of it since there's no clear error case. Some errors may be due to coding -// issues, others caused by signers mining MEV stuff or swapping transactions. In -// all cases, the pool needs to continue operating. -func (l *limbo) update(txhash common.Hash, block uint64) { - // If the blobs are not tracked by the limbo, there's not much to do. This - // can happen for example if a blob transaction is mined without pushing it - // into the network first. - id, ok := l.index[txhash] - if !ok { - log.Trace("Limbo cannot update non-tracked blobs", "tx", txhash) - return - } - // If there was no change in the blob's inclusion block, don't mess around - // with heavy database operations. - if _, ok := l.groups[block][id]; ok { - log.Trace("Blob transaction unchanged in limbo", "tx", txhash, "block", block) - return - } - // Retrieve the old blobs from the data store and write them back with a new - // block number. IF anything fails, there's not much to do, go on. - item, err := l.getAndDrop(id) - if err != nil { - log.Error("Failed to get and drop limboed blobs", "tx", txhash, "id", id, "err", err) - return - } - if err := l.setAndIndex(item.Tx, block); err != nil { - log.Error("Failed to set and index limboed blobs", "tx", txhash, "err", err) - return - } - log.Trace("Blob transaction updated in limbo", "tx", txhash, "old-block", item.Block, "new-block", block) -} - -// getAndDrop retrieves a blob item from the limbo store and deletes it both from -// the store and indices. -func (l *limbo) getAndDrop(id uint64) (*limboBlob, error) { - data, err := l.store.Get(id) - if err != nil { - return nil, err - } - item := new(limboBlob) - if err = rlp.DecodeBytes(data, item); err != nil { - return nil, err - } - delete(l.index, item.TxHash) - delete(l.groups[item.Block], id) - if len(l.groups[item.Block]) == 0 { - delete(l.groups, item.Block) - } - if err := l.store.Delete(id); err != nil { - return nil, err - } - return item, nil -} - -// setAndIndex assembles a limbo blob database entry and stores it, also updating -// the in-memory indices. -func (l *limbo) setAndIndex(tx *types.Transaction, block uint64) error { - txhash := tx.Hash() - item := &limboBlob{ - TxHash: txhash, - Block: block, - Tx: tx, - } - data, err := rlp.EncodeToBytes(item) - if err != nil { - panic(err) // cannot happen runtime, dev error - } - id, err := l.store.Put(data) - if err != nil { - return err - } - l.index[txhash] = id - if _, ok := l.groups[block]; !ok { - l.groups[block] = make(map[uint64]common.Hash) - } - l.groups[block][id] = txhash - return nil -} diff --git a/builder/core/txpool/blobpool/metrics.go b/builder/core/txpool/blobpool/metrics.go deleted file mode 100644 index 52419ade0..000000000 --- a/builder/core/txpool/blobpool/metrics.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2023 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 blobpool - -import "github.com/ethereum/go-ethereum/metrics" - -var ( - // datacapGauge tracks the user's configured capacity for the blob pool. It - // is mostly a way to expose/debug issues. - datacapGauge = metrics.NewRegisteredGauge("blobpool/datacap", nil) - - // The below metrics track the per-datastore metrics for the primary blob - // store and the temporary limbo store. - datausedGauge = metrics.NewRegisteredGauge("blobpool/dataused", nil) - datarealGauge = metrics.NewRegisteredGauge("blobpool/datareal", nil) - slotusedGauge = metrics.NewRegisteredGauge("blobpool/slotused", nil) - - limboDatausedGauge = metrics.NewRegisteredGauge("blobpool/limbo/dataused", nil) - limboDatarealGauge = metrics.NewRegisteredGauge("blobpool/limbo/datareal", nil) - limboSlotusedGauge = metrics.NewRegisteredGauge("blobpool/limbo/slotused", nil) - - // The below metrics track the per-shelf metrics for the primary blob store - // and the temporary limbo store. - shelfDatausedGaugeName = "blobpool/shelf_%d/dataused" - shelfDatagapsGaugeName = "blobpool/shelf_%d/datagaps" - shelfSlotusedGaugeName = "blobpool/shelf_%d/slotused" - shelfSlotgapsGaugeName = "blobpool/shelf_%d/slotgaps" - - limboShelfDatausedGaugeName = "blobpool/limbo/shelf_%d/dataused" - limboShelfDatagapsGaugeName = "blobpool/limbo/shelf_%d/datagaps" - limboShelfSlotusedGaugeName = "blobpool/limbo/shelf_%d/slotused" - limboShelfSlotgapsGaugeName = "blobpool/limbo/shelf_%d/slotgaps" - - // The oversized metrics aggregate the shelf stats above the max blob count - // limits to track transactions that are just huge, but don't contain blobs. - // - // There are no oversized data in the limbo, it only contains blobs and some - // constant metadata. - oversizedDatausedGauge = metrics.NewRegisteredGauge("blobpool/oversized/dataused", nil) - oversizedDatagapsGauge = metrics.NewRegisteredGauge("blobpool/oversized/datagaps", nil) - oversizedSlotusedGauge = metrics.NewRegisteredGauge("blobpool/oversized/slotused", nil) - oversizedSlotgapsGauge = metrics.NewRegisteredGauge("blobpool/oversized/slotgaps", nil) - - // basefeeGauge and blobfeeGauge track the current network 1559 base fee and - // 4844 blob fee respectively. - basefeeGauge = metrics.NewRegisteredGauge("blobpool/basefee", nil) - blobfeeGauge = metrics.NewRegisteredGauge("blobpool/blobfee", nil) - - // pooltipGauge is the configurable miner tip to permit a transaction into - // the pool. - pooltipGauge = metrics.NewRegisteredGauge("blobpool/pooltip", nil) - - // addwait/time, resetwait/time and getwait/time track the rough health of - // the pool and whether it's capable of keeping up with the load from the - // network. - addwaitHist = metrics.NewRegisteredHistogram("blobpool/addwait", nil, metrics.NewExpDecaySample(1028, 0.015)) - addtimeHist = metrics.NewRegisteredHistogram("blobpool/addtime", nil, metrics.NewExpDecaySample(1028, 0.015)) - getwaitHist = metrics.NewRegisteredHistogram("blobpool/getwait", nil, metrics.NewExpDecaySample(1028, 0.015)) - gettimeHist = metrics.NewRegisteredHistogram("blobpool/gettime", nil, metrics.NewExpDecaySample(1028, 0.015)) - pendwaitHist = metrics.NewRegisteredHistogram("blobpool/pendwait", nil, metrics.NewExpDecaySample(1028, 0.015)) - pendtimeHist = metrics.NewRegisteredHistogram("blobpool/pendtime", nil, metrics.NewExpDecaySample(1028, 0.015)) - resetwaitHist = metrics.NewRegisteredHistogram("blobpool/resetwait", nil, metrics.NewExpDecaySample(1028, 0.015)) - resettimeHist = metrics.NewRegisteredHistogram("blobpool/resettime", nil, metrics.NewExpDecaySample(1028, 0.015)) - - // The below metrics track various cases where transactions are dropped out - // of the pool. Most are exceptional, some are chain progression and some - // threshold cappings. - dropInvalidMeter = metrics.NewRegisteredMeter("blobpool/drop/invalid", nil) // Invalid transaction, consensus change or bugfix, neutral-ish - dropDanglingMeter = metrics.NewRegisteredMeter("blobpool/drop/dangling", nil) // First nonce gapped, bad - dropFilledMeter = metrics.NewRegisteredMeter("blobpool/drop/filled", nil) // State full-overlap, chain progress, ok - dropOverlappedMeter = metrics.NewRegisteredMeter("blobpool/drop/overlapped", nil) // State partial-overlap, chain progress, ok - dropRepeatedMeter = metrics.NewRegisteredMeter("blobpool/drop/repeated", nil) // Repeated nonce, bad - dropGappedMeter = metrics.NewRegisteredMeter("blobpool/drop/gapped", nil) // Non-first nonce gapped, bad - dropOverdraftedMeter = metrics.NewRegisteredMeter("blobpool/drop/overdrafted", nil) // Balance exceeded, bad - dropOvercappedMeter = metrics.NewRegisteredMeter("blobpool/drop/overcapped", nil) // Per-account cap exceeded, bad - dropOverflownMeter = metrics.NewRegisteredMeter("blobpool/drop/overflown", nil) // Global disk cap exceeded, neutral-ish - dropUnderpricedMeter = metrics.NewRegisteredMeter("blobpool/drop/underpriced", nil) // Gas tip changed, neutral - dropReplacedMeter = metrics.NewRegisteredMeter("blobpool/drop/replaced", nil) // Transaction replaced, neutral - - // The below metrics track various outcomes of transactions being added to - // the pool. - addInvalidMeter = metrics.NewRegisteredMeter("blobpool/add/invalid", nil) // Invalid transaction, reject, neutral - addUnderpricedMeter = metrics.NewRegisteredMeter("blobpool/add/underpriced", nil) // Gas tip too low, neutral - addStaleMeter = metrics.NewRegisteredMeter("blobpool/add/stale", nil) // Nonce already filled, reject, bad-ish - addGappedMeter = metrics.NewRegisteredMeter("blobpool/add/gapped", nil) // Nonce gapped, reject, bad-ish - addOverdraftedMeter = metrics.NewRegisteredMeter("blobpool/add/overdrafted", nil) // Balance exceeded, reject, neutral - addOvercappedMeter = metrics.NewRegisteredMeter("blobpool/add/overcapped", nil) // Per-account cap exceeded, reject, neutral - addNoreplaceMeter = metrics.NewRegisteredMeter("blobpool/add/noreplace", nil) // Replacement fees or tips too low, neutral - addNonExclusiveMeter = metrics.NewRegisteredMeter("blobpool/add/nonexclusive", nil) // Plain transaction from same account exists, reject, neutral - addValidMeter = metrics.NewRegisteredMeter("blobpool/add/valid", nil) // Valid transaction, add, neutral -) diff --git a/builder/core/txpool/blobpool/priority.go b/builder/core/txpool/blobpool/priority.go deleted file mode 100644 index a8332bd9b..000000000 --- a/builder/core/txpool/blobpool/priority.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "math" - "math/bits" - - "github.com/holiman/uint256" -) - -// log2_1_125 is used in the eviction priority calculation. -var log2_1_125 = math.Log2(1.125) - -// evictionPriority calculates the eviction priority based on the algorithm -// described in the BlobPool docs for both fee components. -// -// This method takes about 8ns on a very recent laptop CPU, recalculating about -// 125 million transaction priority values per second. -func evictionPriority(basefeeJumps float64, txBasefeeJumps, blobfeeJumps, txBlobfeeJumps float64) int { - var ( - basefeePriority = evictionPriority1D(basefeeJumps, txBasefeeJumps) - blobfeePriority = evictionPriority1D(blobfeeJumps, txBlobfeeJumps) - ) - if basefeePriority < blobfeePriority { - return basefeePriority - } - return blobfeePriority -} - -// evictionPriority1D calculates the eviction priority based on the algorithm -// described in the BlobPool docs for a single fee component. -func evictionPriority1D(basefeeJumps float64, txfeeJumps float64) int { - jumps := txfeeJumps - basefeeJumps - if int(jumps) == 0 { - return 0 // can't log2 0 - } - if jumps < 0 { - return -intLog2(uint(-math.Floor(jumps))) - } - return intLog2(uint(math.Ceil(jumps))) -} - -// dynamicFeeJumps calculates the log1.125(fee), namely the number of fee jumps -// needed to reach the requested one. We only use it when calculating the jumps -// between 2 fees, so it doesn't matter from what exact number with returns. -// it returns the result from (0, 1, 1.125). -// -// This method is very expensive, taking about 75ns on a very recent laptop CPU, -// but the result does not change with the lifetime of a transaction, so it can -// be cached. -func dynamicFeeJumps(fee *uint256.Int) float64 { - if fee.IsZero() { - return 0 // can't log2 zero, should never happen outside tests, but don't choke - } - return math.Log2(fee.Float64()) / log2_1_125 -} - -// intLog2 is a helper to calculate the integral part of a log2 of an unsigned -// integer. It is a very specific calculation that's not particularly useful in -// general, but it's what we need here (it's fast). -func intLog2(n uint) int { - switch { - case n == 0: - panic("log2(0) is undefined") - - case n < 2048: - return bits.UintSize - bits.LeadingZeros(n) - 1 - - default: - // The input is log1.125(uint256) = log2(uint256) / log2(1.125). At the - // most extreme, log2(uint256) will be a bit below 257, and the constant - // log2(1.125) ~= 0.17. The larges input thus is ~257 / ~0.17 ~= ~1511. - panic("dynamic fee jump diffs cannot reach this") - } -} diff --git a/builder/core/txpool/blobpool/priority_test.go b/builder/core/txpool/blobpool/priority_test.go deleted file mode 100644 index cf0e0454a..000000000 --- a/builder/core/txpool/blobpool/priority_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2023 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 blobpool - -import ( - "testing" - - "github.com/holiman/uint256" -) - -// Tests that the priority fees are calculated correctly as the log2 of the fee -// jumps needed to go from the base fee to the tx's fee cap. -func TestPriorityCalculation(t *testing.T) { - tests := []struct { - basefee uint64 - txfee uint64 - result int - }{ - {basefee: 7, txfee: 10, result: 2}, // 3.02 jumps, 4 ceil, 2 log2 - {basefee: 17_200_000_000, txfee: 17_200_000_000, result: 0}, // 0 jumps, special case 0 log2 - {basefee: 9_853_941_692, txfee: 11_085_092_510, result: 0}, // 0.99 jumps, 1 ceil, 0 log2 - {basefee: 11_544_106_391, txfee: 10_356_781_100, result: 0}, // -0.92 jumps, -1 floor, 0 log2 - {basefee: 17_200_000_000, txfee: 7, result: -7}, // -183.57 jumps, -184 floor, -7 log2 - {basefee: 7, txfee: 17_200_000_000, result: 7}, // 183.57 jumps, 184 ceil, 7 log2 - } - for i, tt := range tests { - var ( - baseJumps = dynamicFeeJumps(uint256.NewInt(tt.basefee)) - feeJumps = dynamicFeeJumps(uint256.NewInt(tt.txfee)) - ) - if prio := evictionPriority1D(baseJumps, feeJumps); prio != tt.result { - t.Errorf("test %d priority mismatch: have %d, want %d", i, prio, tt.result) - } - } -} - -// Benchmarks how many dynamic fee jump values can be done. -func BenchmarkDynamicFeeJumpCalculation(b *testing.B) { - fees := make([]*uint256.Int, b.N) - for i := 0; i < b.N; i++ { - fees[i] = uint256.NewInt(rand.Uint64()) - } - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - dynamicFeeJumps(fees[i]) - } -} - -// Benchmarks how many priority recalculations can be done. -func BenchmarkPriorityCalculation(b *testing.B) { - // The basefee and blob fee is constant for all transactions across a block, - // so we can assume their absolute jump counts can be pre-computed. - basefee := uint256.NewInt(17_200_000_000) // 17.2 Gwei is the 22.03.2023 zero-emission basefee, random number - blobfee := uint256.NewInt(123_456_789_000) // Completely random, no idea what this will be - - basefeeJumps := dynamicFeeJumps(basefee) - blobfeeJumps := dynamicFeeJumps(blobfee) - - // The transaction's fee cap and blob fee cap are constant across the life - // of the transaction, so we can pre-calculate and cache them. - txBasefeeJumps := make([]float64, b.N) - txBlobfeeJumps := make([]float64, b.N) - for i := 0; i < b.N; i++ { - txBasefeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rand.Uint64())) - txBlobfeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rand.Uint64())) - } - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - evictionPriority(basefeeJumps, txBasefeeJumps[i], blobfeeJumps, txBlobfeeJumps[i]) - } -} diff --git a/builder/core/txpool/blobpool/slotter.go b/builder/core/txpool/blobpool/slotter.go deleted file mode 100644 index 35349c344..000000000 --- a/builder/core/txpool/blobpool/slotter.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2023 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 blobpool - -// newSlotter creates a helper method for the Billy datastore that returns the -// individual shelf sizes used to store transactions in. -// -// The slotter will create shelves for each possible blob count + some tx metadata -// wiggle room, up to the max permitted limits. -// -// The slotter also creates a shelf for 0-blob transactions. Whilst those are not -// allowed in the current protocol, having an empty shelf is not a relevant use -// of resources, but it makes stress testing with junk transactions simpler. -func newSlotter() func() (uint32, bool) { - slotsize := uint32(txAvgSize) - slotsize -= uint32(blobSize) // underflows, it's ok, will overflow back in the first return - - return func() (size uint32, done bool) { - slotsize += blobSize - finished := slotsize > maxBlobsPerTransaction*blobSize+txMaxSize - - return slotsize, finished - } -} diff --git a/builder/core/txpool/blobpool/slotter_test.go b/builder/core/txpool/blobpool/slotter_test.go deleted file mode 100644 index a7b43b4d2..000000000 --- a/builder/core/txpool/blobpool/slotter_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2023 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 blobpool - -import "testing" - -// Tests that the slotter creates the expected database shelves. -func TestNewSlotter(t *testing.T) { - // Generate the database shelve sizes - slotter := newSlotter() - - var shelves []uint32 - for { - shelf, done := slotter() - shelves = append(shelves, shelf) - if done { - break - } - } - // Compare the database shelves to the expected ones - want := []uint32{ - 0*blobSize + txAvgSize, // 0 blob + some expected tx infos - 1*blobSize + txAvgSize, // 1 blob + some expected tx infos - 2*blobSize + txAvgSize, // 2 blob + some expected tx infos (could be fewer blobs and more tx data) - 3*blobSize + txAvgSize, // 3 blob + some expected tx infos (could be fewer blobs and more tx data) - 4*blobSize + txAvgSize, // 4 blob + some expected tx infos (could be fewer blobs and more tx data) - 5*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 6*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 7*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 8*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 9*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 10*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 11*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 12*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 13*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos < 4 blobs + max tx metadata size - 14*blobSize + txAvgSize, // 1-6 blobs + unexpectedly large tx infos >= 4 blobs + max tx metadata size - } - if len(shelves) != len(want) { - t.Errorf("shelves count mismatch: have %d, want %d", len(shelves), len(want)) - } - for i := 0; i < len(shelves) && i < len(want); i++ { - if shelves[i] != want[i] { - t.Errorf("shelf %d mismatch: have %d, want %d", i, shelves[i], want[i]) - } - } -} diff --git a/builder/core/txpool/errors.go b/builder/core/txpool/errors.go deleted file mode 100644 index 3a6a91397..000000000 --- a/builder/core/txpool/errors.go +++ /dev/null @@ -1,63 +0,0 @@ -// 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 txpool - -import "errors" - -var ( - // ErrAlreadyKnown is returned if the transactions is already contained - // within the pool. - ErrAlreadyKnown = errors.New("already known") - - // ErrInvalidSender is returned if the transaction contains an invalid signature. - ErrInvalidSender = errors.New("invalid sender") - - // ErrUnderpriced is returned if a transaction's gas price is below the minimum - // configured for the transaction pool. - ErrUnderpriced = errors.New("transaction underpriced") - - // ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced - // with a different one without the required price bump. - ErrReplaceUnderpriced = errors.New("replacement transaction underpriced") - - // ErrAccountLimitExceeded is returned if a transaction would exceed the number - // allowed by a pool for a single account. - ErrAccountLimitExceeded = errors.New("account limit exceeded") - - // ErrGasLimit is returned if a transaction's requested gas limit exceeds the - // maximum allowance of the current block. - ErrGasLimit = errors.New("exceeds block gas limit") - - // ErrNegativeValue is a sanity error to ensure no one is able to specify a - // transaction with a negative value. - ErrNegativeValue = errors.New("negative value") - - // 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") - - // ErrFutureReplacePending is returned if a future transaction replaces a pending - // one. Future transactions should only be able to replace other future transactions. - ErrFutureReplacePending = errors.New("future transaction tries to replace pending") - - // ErrAlreadyReserved is returned if the sender address has a pending transaction - // in a different subpool. For example, this error is returned in response to any - // input transaction of non-blob type when a blob transaction from this sender - // remains pending (and vice-versa). - ErrAlreadyReserved = errors.New("address already reserved") -) diff --git a/builder/core/txpool/legacypool/journal.go b/builder/core/txpool/legacypool/journal.go deleted file mode 100644 index 899ed00bc..000000000 --- a/builder/core/txpool/legacypool/journal.go +++ /dev/null @@ -1,186 +0,0 @@ -// 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 legacypool - -import ( - "errors" - "io" - "io/fs" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" -) - -// errNoActiveJournal is returned if a transaction is attempted to be inserted -// into the journal, but no such file is currently open. -var errNoActiveJournal = errors.New("no active journal") - -// devNull is a WriteCloser that just discards anything written into it. Its -// goal is to allow the transaction journal to write into a fake journal when -// loading transactions on startup without printing warnings due to no file -// being read for write. -type devNull struct{} - -func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil } -func (*devNull) Close() error { return nil } - -// journal is a rotating log of transactions with the aim of storing locally -// created transactions to allow non-executed ones to survive node restarts. -type journal struct { - path string // Filesystem path to store the transactions at - writer io.WriteCloser // Output stream to write new transactions into -} - -// newTxJournal creates a new transaction journal to -func newTxJournal(path string) *journal { - return &journal{ - path: path, - } -} - -// load parses a transaction journal dump from disk, loading its contents into -// the specified pool. -func (journal *journal) load(add func([]*types.Transaction) []error) error { - // Open the journal for loading any past transactions - input, err := os.Open(journal.path) - if errors.Is(err, fs.ErrNotExist) { - // Skip the parsing if the journal file doesn't exist at all - return nil - } - if err != nil { - return err - } - defer input.Close() - - // Temporarily discard any journal additions (don't double add on load) - journal.writer = new(devNull) - defer func() { journal.writer = nil }() - - // Inject all transactions from the journal into the pool - stream := rlp.NewStream(input, 0) - total, dropped := 0, 0 - - // Create a method to load a limited batch of transactions and bump the - // appropriate progress counters. Then use this method to load all the - // journaled transactions in small-ish batches. - loadBatch := func(txs types.Transactions) { - for _, err := range add(txs) { - if err != nil { - log.Debug("Failed to add journaled transaction", "err", err) - dropped++ - } - } - } - var ( - failure error - batch types.Transactions - ) - for { - // Parse the next transaction and terminate on error - tx := new(types.Transaction) - if err = stream.Decode(tx); err != nil { - if err != io.EOF { - failure = err - } - if batch.Len() > 0 { - loadBatch(batch) - } - break - } - // New transaction parsed, queue up for later, import if threshold is reached - total++ - - if batch = append(batch, tx); batch.Len() > 1024 { - loadBatch(batch) - batch = batch[:0] - } - } - log.Info("Loaded local transaction journal", "transactions", total, "dropped", dropped) - - return failure -} - -// insert adds the specified transaction to the local disk journal. -func (journal *journal) insert(tx *types.Transaction) error { - if journal.writer == nil { - return errNoActiveJournal - } - if err := rlp.Encode(journal.writer, tx); err != nil { - return err - } - return nil -} - -// rotate regenerates the transaction journal based on the current contents of -// the transaction pool. -func (journal *journal) rotate(all map[common.Address]types.Transactions) error { - // Close the current journal (if any is open) - if journal.writer != nil { - if err := journal.writer.Close(); err != nil { - return err - } - journal.writer = nil - } - // Generate a new journal with the contents of the current pool - replacement, err := os.OpenFile(journal.path+".new", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return err - } - journaled := 0 - for _, txs := range all { - for _, tx := range txs { - if err = rlp.Encode(replacement, tx); err != nil { - replacement.Close() - return err - } - } - journaled += len(txs) - } - replacement.Close() - - // Replace the live journal with the newly generated one - if err = os.Rename(journal.path+".new", journal.path); err != nil { - return err - } - sink, err := os.OpenFile(journal.path, os.O_WRONLY|os.O_APPEND, 0644) - if err != nil { - return err - } - journal.writer = sink - - logger := log.Info - if len(all) == 0 { - logger = log.Debug - } - logger("Regenerated local transaction journal", "transactions", journaled, "accounts", len(all)) - - return nil -} - -// close flushes the transaction journal contents to disk and closes the file. -func (journal *journal) close() error { - var err error - - if journal.writer != nil { - err = journal.writer.Close() - journal.writer = nil - } - return err -} diff --git a/builder/core/txpool/legacypool/legacypool.go b/builder/core/txpool/legacypool/legacypool.go deleted file mode 100644 index 3df2dc9cf..000000000 --- a/builder/core/txpool/legacypool/legacypool.go +++ /dev/null @@ -1,1994 +0,0 @@ -// 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 legacypool implements the normal EVM execution transaction pool. -package legacypool - -import ( - "errors" - "math" - "math/big" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -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 -) - -var ( - // ErrTxPoolOverflow is returned if the transaction pool is full and can't accept - // another remote transaction. - ErrTxPoolOverflow = errors.New("txpool is full") -) - -var ( - evictionInterval = time.Minute // Time interval to check for evictable transactions - statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats - privateTxCleanupInterval = 1 * time.Hour -) - -var ( - // Metrics for the pending pool - pendingDiscardMeter = metrics.NewRegisteredMeter("txpool/pending/discard", nil) - pendingReplaceMeter = metrics.NewRegisteredMeter("txpool/pending/replace", nil) - pendingRateLimitMeter = metrics.NewRegisteredMeter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting - pendingNofundsMeter = metrics.NewRegisteredMeter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds - - // Metrics for the queued pool - queuedDiscardMeter = metrics.NewRegisteredMeter("txpool/queued/discard", nil) - queuedReplaceMeter = metrics.NewRegisteredMeter("txpool/queued/replace", nil) - queuedRateLimitMeter = metrics.NewRegisteredMeter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting - queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds - queuedEvictionMeter = metrics.NewRegisteredMeter("txpool/queued/eviction", nil) // Dropped due to lifetime - - // General tx metrics - knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil) - validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil) - invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) - underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) - overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil) - - // throttleTxMeter counts how many transactions are rejected due to too-many-changes between - // txpool reorgs. - throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil) - // reorgDurationTimer measures how long time a txpool reorg takes. - reorgDurationTimer = metrics.NewRegisteredTimer("txpool/reorgtime", nil) - // dropBetweenReorgHistogram counts how many drops we experience between two reorg runs. It is expected - // that this number is pretty low, since txpool reorgs happen very frequently. - dropBetweenReorgHistogram = metrics.NewRegisteredHistogram("txpool/dropbetweenreorg", nil, metrics.NewExpDecaySample(1028, 0.015)) - - pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) - queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) - localGauge = metrics.NewRegisteredGauge("txpool/local", nil) - slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) - - reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil) -) - -// BlockChain defines the minimal set of methods needed to back a tx pool with -// a chain. Exists to allow mocking the live chain out of tests. -type BlockChain interface { - // Config retrieves the chain's fork configuration. - Config() *params.ChainConfig - - // CurrentBlock returns the current head of the chain. - CurrentBlock() *types.Header - - // GetBlock retrieves a specific block, used during pool resets. - GetBlock(hash common.Hash, number uint64) *types.Block - - // StateAt returns a state database for a given root hash (generally the head). - StateAt(root common.Hash) (*state.StateDB, error) -} - -// Config are the configuration parameters of the transaction pool. -type Config struct { - Locals []common.Address // Addresses that should be treated by default as local - NoLocals bool // Whether local transaction handling should be disabled - Journal string // Journal of local transactions to survive node restarts - Rejournal time.Duration // Time interval to regenerate the local transaction journal - - PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool - PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce) - - AccountSlots uint64 // Number of executable transaction slots guaranteed per account - GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts - AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account - GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts - - Lifetime time.Duration // Maximum amount of time non-executable transaction are queued - PrivateTxLifetime time.Duration // Maximum amount of time to keep private transactions private -} - -// DefaultConfig contains the default configurations for the transaction pool. -var DefaultConfig = Config{ - Journal: "transactions.rlp", - Rejournal: time.Hour, - - PriceLimit: 1, - PriceBump: 10, - - AccountSlots: 16, - GlobalSlots: 4096 + 1024, // urgent + floating queue capacity with 4:1 ratio - AccountQueue: 64, - GlobalQueue: 1024, - - Lifetime: 3 * time.Hour, - PrivateTxLifetime: 3 * 24 * time.Hour, -} - -// sanitize checks the provided user configurations and changes anything that's -// unreasonable or unworkable. -func (config *Config) sanitize() Config { - conf := *config - if conf.Rejournal < time.Second { - log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second) - conf.Rejournal = time.Second - } - if conf.PriceLimit < 1 { - log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultConfig.PriceLimit) - conf.PriceLimit = DefaultConfig.PriceLimit - } - if conf.PriceBump < 1 { - log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultConfig.PriceBump) - conf.PriceBump = DefaultConfig.PriceBump - } - if conf.AccountSlots < 1 { - log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultConfig.AccountSlots) - conf.AccountSlots = DefaultConfig.AccountSlots - } - if conf.GlobalSlots < 1 { - log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultConfig.GlobalSlots) - conf.GlobalSlots = DefaultConfig.GlobalSlots - } - if conf.AccountQueue < 1 { - log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultConfig.AccountQueue) - conf.AccountQueue = DefaultConfig.AccountQueue - } - if conf.GlobalQueue < 1 { - log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultConfig.GlobalQueue) - conf.GlobalQueue = DefaultConfig.GlobalQueue - } - if conf.Lifetime < 1 { - log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultConfig.Lifetime) - conf.Lifetime = DefaultConfig.Lifetime - } - if conf.PrivateTxLifetime < 1 { - log.Warn("Sanitizing invalid txpool private tx lifetime", "provided", conf.PrivateTxLifetime, "updated", DefaultConfig.PrivateTxLifetime) - conf.PrivateTxLifetime = DefaultConfig.PrivateTxLifetime - } - return conf -} - -// LegacyPool contains all currently known transactions. Transactions -// enter the pool when they are received from the network or submitted -// locally. They exit the pool when they are included in the blockchain. -// -// The pool separates processable transactions (which can be applied to the -// current state) and future transactions. Transactions move between those -// two states over time as they are received and processed. -type LegacyPool struct { - config Config - chainconfig *params.ChainConfig - chain BlockChain - gasTip atomic.Pointer[uint256.Int] - txFeed event.Feed - signer types.Signer - mu sync.RWMutex - - currentHead atomic.Pointer[types.Header] // Current head of the blockchain - currentState *state.StateDB // Current state in the blockchain head - pendingNonces *noncer // Pending state tracking virtual nonces - - locals *accountSet // Set of local transaction to exempt from eviction rules - journal *journal // Journal of local transaction to back up to disk - - reserve txpool.AddressReserver // Address reserver to ensure exclusivity across subpools - pending map[common.Address]*list // All currently processable transactions - queue map[common.Address]*list // Queued but non-processable transactions - beats map[common.Address]time.Time // Last heartbeat from each known account - all *lookup // All transactions to allow lookups - priced *pricedList // All transactions sorted by price - - reqResetCh chan *txpoolResetRequest - reqPromoteCh chan *accountSet - queueTxEventCh chan *types.Transaction - reorgDoneCh chan chan struct{} - reorgShutdownCh chan struct{} // requests shutdown of scheduleReorgLoop - wg sync.WaitGroup // tracks loop, scheduleReorgLoop - initDoneCh chan struct{} // is closed once the pool is initialized (for tests) - - changesSinceReorg int // A counter for how many drops we've performed in-between reorg. - - privateTxs *types.TimestampedTxHashSet -} - -type txpoolResetRequest struct { - oldHead, newHead *types.Header -} - -// New creates a new transaction pool to gather, sort and filter inbound -// transactions from the network. -func New(config Config, chain BlockChain) *LegacyPool { - // Sanitize the input to ensure no vulnerable gas prices are set - config = (&config).sanitize() - - // Create the transaction pool with its initial settings - pool := &LegacyPool{ - config: config, - chain: chain, - chainconfig: chain.Config(), - signer: types.LatestSigner(chain.Config()), - pending: make(map[common.Address]*list), - queue: make(map[common.Address]*list), - beats: make(map[common.Address]time.Time), - all: newLookup(), - reqResetCh: make(chan *txpoolResetRequest), - reqPromoteCh: make(chan *accountSet), - queueTxEventCh: make(chan *types.Transaction), - reorgDoneCh: make(chan chan struct{}), - reorgShutdownCh: make(chan struct{}), - initDoneCh: make(chan struct{}), - privateTxs: types.NewExpiringTxHashSet(config.PrivateTxLifetime), - } - pool.locals = newAccountSet(pool.signer) - for _, addr := range config.Locals { - log.Info("Setting new local account", "address", addr) - pool.locals.add(addr) - } - pool.priced = newPricedList(pool.all) - - if !config.NoLocals && config.Journal != "" { - pool.journal = newTxJournal(config.Journal) - } - return pool -} - -// Filter returns whether the given transaction can be consumed by the legacy -// pool, specifically, whether it is a Legacy, AccessList or Dynamic transaction. -func (pool *LegacyPool) Filter(tx *types.Transaction) bool { - switch tx.Type() { - case types.LegacyTxType, types.AccessListTxType, types.DynamicFeeTxType: - return true - default: - return false - } -} - -// Init sets the gas price needed to keep a transaction in the pool and the chain -// head to allow balance / nonce checks. The transaction journal will be loaded -// from disk and filtered based on the provided starting settings. The internal -// goroutines will be spun up and the pool deemed operational afterwards. -func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error { - // Set the address reserver to request exclusive access to pooled accounts - pool.reserve = reserve - - // Set the basic pool parameters - pool.gasTip.Store(uint256.NewInt(gasTip)) - - // Initialize the state with head block, or fallback to empty one in - // case the head state is not available (might occur when node is not - // fully synced). - statedb, err := pool.chain.StateAt(head.Root) - if err != nil { - statedb, err = pool.chain.StateAt(types.EmptyRootHash) - } - if err != nil { - return err - } - pool.currentHead.Store(head) - pool.currentState = statedb - pool.pendingNonces = newNoncer(statedb) - - // Start the reorg loop early, so it can handle requests generated during - // journal loading. - pool.wg.Add(1) - go pool.scheduleReorgLoop() - - // If local transactions and journaling is enabled, load from disk - if pool.journal != nil { - if err := pool.journal.load(pool.addLocals); err != nil { - log.Warn("Failed to load transaction journal", "err", err) - } - if err := pool.journal.rotate(pool.local()); err != nil { - log.Warn("Failed to rotate transaction journal", "err", err) - } - } - pool.wg.Add(1) - go pool.loop() - return nil -} - -// loop is the transaction pool's main event loop, waiting for and reacting to -// outside blockchain events as well as for various reporting and transaction -// eviction events. -func (pool *LegacyPool) loop() { - defer pool.wg.Done() - - var ( - prevPending, prevQueued, prevStales int - - // Start the stats reporting and transaction eviction tickers - report = time.NewTicker(statsReportInterval) - evict = time.NewTicker(evictionInterval) - journal = time.NewTicker(pool.config.Rejournal) - privateTx = time.NewTicker(privateTxCleanupInterval) - ) - defer report.Stop() - defer evict.Stop() - defer journal.Stop() - defer privateTx.Stop() - - // Notify tests that the init phase is done - close(pool.initDoneCh) - for { - select { - // Handle pool shutdown - case <-pool.reorgShutdownCh: - return - - // Handle stats reporting ticks - case <-report.C: - pool.mu.RLock() - pending, queued := pool.stats() - pool.mu.RUnlock() - stales := int(pool.priced.stales.Load()) - - if pending != prevPending || queued != prevQueued || stales != prevStales { - log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) - prevPending, prevQueued, prevStales = pending, queued, stales - } - - // Handle inactive account transaction eviction - case <-evict.C: - pool.mu.Lock() - for addr := range pool.queue { - // Skip local transactions from the eviction mechanism - if pool.locals.contains(addr) { - continue - } - // Any non-locals old enough should be removed - if time.Since(pool.beats[addr]) > pool.config.Lifetime { - list := pool.queue[addr].Flatten() - for _, tx := range list { - pool.removeTx(tx.Hash(), true, true) - } - queuedEvictionMeter.Mark(int64(len(list))) - } - } - pool.mu.Unlock() - - // Handle local transaction journal rotation - case <-journal.C: - if pool.journal != nil { - pool.mu.Lock() - if err := pool.journal.rotate(pool.local()); err != nil { - log.Warn("Failed to rotate local tx journal", "err", err) - } - pool.mu.Unlock() - } - // Remove stale hashes that must be kept private - case <-privateTx.C: - pool.privateTxs.Prune() - } - } -} - -// Close terminates the transaction pool. -func (pool *LegacyPool) Close() error { - // Terminate the pool reorger and return - close(pool.reorgShutdownCh) - pool.wg.Wait() - - if pool.journal != nil { - pool.journal.close() - } - log.Info("Transaction pool stopped") - return nil -} - -// Reset implements txpool.SubPool, allowing the legacy pool's internal state to be -// kept in sync with the main transaction pool's internal state. -func (pool *LegacyPool) Reset(oldHead, newHead *types.Header) { - wait := pool.requestReset(oldHead, newHead) - <-wait -} - -// SubscribeTransactions registers a subscription for new transaction events, -// supporting feeding only newly seen or also resurrected transactions. -func (pool *LegacyPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { - // The legacy pool has a very messed up internal shuffling, so it's kind of - // hard to separate newly discovered transaction from resurrected ones. This - // is because the new txs are added to the queue, resurrected ones too and - // reorgs run lazily, so separating the two would need a marker. - return pool.txFeed.Subscribe(ch) -} - -// IsPrivateTxHash indicates whether the transaction should be shared with peers -func (pool *LegacyPool) IsPrivateTxHash(hash common.Hash) bool { - return pool.privateTxs.Contains(hash) -} - -// SetGasTip updates the minimum gas tip required by the transaction pool for a -// new transaction, and drops all transactions below this threshold. -func (pool *LegacyPool) SetGasTip(tip *big.Int) { - pool.mu.Lock() - defer pool.mu.Unlock() - - var ( - newTip = uint256.MustFromBig(tip) - old = pool.gasTip.Load() - ) - pool.gasTip.Store(newTip) - // If the min miner fee increased, remove transactions below the new threshold - if newTip.Cmp(old) > 0 { - // pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead - drop := pool.all.RemotesBelowTip(tip) - for _, tx := range drop { - pool.removeTx(tx.Hash(), false, true) - } - pool.priced.Removed(len(drop)) - } - log.Info("Legacy pool tip threshold updated", "tip", newTip) -} - -// Nonce returns the next nonce of an account, with all transactions executable -// by the pool already applied on top. -func (pool *LegacyPool) Nonce(addr common.Address) uint64 { - pool.mu.RLock() - defer pool.mu.RUnlock() - - return pool.pendingNonces.get(addr) -} - -// Stats retrieves the current pool stats, namely the number of pending and the -// number of queued (non-executable) transactions. -func (pool *LegacyPool) Stats() (int, int) { - pool.mu.RLock() - defer pool.mu.RUnlock() - - return pool.stats() -} - -// stats retrieves the current pool stats, namely the number of pending and the -// number of queued (non-executable) transactions. -func (pool *LegacyPool) stats() (int, int) { - pending := 0 - for _, list := range pool.pending { - pending += list.Len() - } - queued := 0 - for _, list := range pool.queue { - queued += list.Len() - } - return pending, queued -} - -// Content retrieves the data content of the transaction pool, returning all the -// pending as well as queued transactions, grouped by account and sorted by nonce. -func (pool *LegacyPool) Content() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { - pool.mu.Lock() - defer pool.mu.Unlock() - - pending := make(map[common.Address][]*types.Transaction, len(pool.pending)) - for addr, list := range pool.pending { - pending[addr] = list.Flatten() - } - queued := make(map[common.Address][]*types.Transaction, len(pool.queue)) - for addr, list := range pool.queue { - queued[addr] = list.Flatten() - } - return pending, queued -} - -// ContentFrom retrieves the data content of the transaction pool, returning the -// pending as well as queued transactions of this address, grouped by nonce. -func (pool *LegacyPool) ContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { - pool.mu.RLock() - defer pool.mu.RUnlock() - - var pending []*types.Transaction - if list, ok := pool.pending[addr]; ok { - pending = list.Flatten() - } - var queued []*types.Transaction - if list, ok := pool.queue[addr]; ok { - queued = list.Flatten() - } - return pending, queued -} - -// Pending retrieves all currently processable transactions, grouped by origin -// account and sorted by nonce. -// -// The transactions can also be pre-filtered by the dynamic fee components to -// reduce allocations and load on downstream subsystems. -func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { - // If only blob transactions are requested, this pool is unsuitable as it - // contains none, don't even bother. - if filter.OnlyBlobTxs { - return nil - } - pool.mu.Lock() - defer pool.mu.Unlock() - - // Convert the new uint256.Int types to the old big.Int ones used by the legacy pool - var ( - minTipBig *big.Int - baseFeeBig *big.Int - ) - if filter.MinTip != nil { - minTipBig = filter.MinTip.ToBig() - } - if filter.BaseFee != nil { - baseFeeBig = filter.BaseFee.ToBig() - } - pending := make(map[common.Address][]*txpool.LazyTransaction, len(pool.pending)) - for addr, list := range pool.pending { - txs := list.Flatten() - - // If the miner requests tip enforcement, cap the lists now - if minTipBig != nil && !pool.locals.contains(addr) { - for i, tx := range txs { - if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 { - txs = txs[:i] - break - } - } - } - if len(txs) > 0 { - lazies := make([]*txpool.LazyTransaction, len(txs)) - for i := 0; i < len(txs); i++ { - lazies[i] = &txpool.LazyTransaction{ - Pool: pool, - Hash: txs[i].Hash(), - Tx: txs[i], - Time: txs[i].Time(), - GasFeeCap: uint256.MustFromBig(txs[i].GasFeeCap()), - GasTipCap: uint256.MustFromBig(txs[i].GasTipCap()), - Gas: txs[i].Gas(), - BlobGas: txs[i].BlobGas(), - GasPrice: uint256.MustFromBig(txs[i].GasPrice()), - } - } - pending[addr] = lazies - } - } - return pending -} - -// Locals retrieves the accounts currently considered local by the pool. -func (pool *LegacyPool) Locals() []common.Address { - pool.mu.Lock() - defer pool.mu.Unlock() - - return pool.locals.flatten() -} - -// local retrieves all currently known local transactions, grouped by origin -// account and sorted by nonce. The returned transaction set is a copy and can be -// freely modified by calling code. -func (pool *LegacyPool) local() map[common.Address]types.Transactions { - txs := make(map[common.Address]types.Transactions) - for addr := range pool.locals.accounts { - if pending := pool.pending[addr]; pending != nil { - txs[addr] = append(txs[addr], pending.Flatten()...) - } - if queued := pool.queue[addr]; queued != nil { - txs[addr] = append(txs[addr], queued.Flatten()...) - } - } - return txs -} - -// validateTxBasics checks whether a transaction is valid according to the consensus -// rules, but does not check state-dependent validation such as sufficient balance. -// This check is meant as an early check which only needs to be performed once, -// and does not require the pool mutex to be held. -func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) error { - opts := &txpool.ValidationOptions{ - Config: pool.chainconfig, - Accept: 0 | - 1< pool.config.GlobalSlots+pool.config.GlobalQueue { - // If the new transaction is underpriced, don't accept it - if !isLocal && pool.priced.Underpriced(tx) { - log.Trace("Discarding underpriced transaction", "hash", hash, "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) - underpricedTxMeter.Mark(1) - return false, txpool.ErrUnderpriced - } - - // We're about to replace a transaction. The reorg does a more thorough - // analysis of what to remove and how, but it runs async. We don't want to - // do too many replacements between reorg-runs, so we cap the number of - // replacements to 25% of the slots - if pool.changesSinceReorg > int(pool.config.GlobalSlots/4) { - throttleTxMeter.Mark(1) - return false, ErrTxPoolOverflow - } - - // New transaction is better than our worse ones, make room for it. - // If it's a local transaction, forcibly discard all available transactions. - // Otherwise if we can't make enough room for new one, abort the operation. - drop, success := pool.priced.Discard(pool.all.Slots()-int(pool.config.GlobalSlots+pool.config.GlobalQueue)+numSlots(tx), isLocal) - - // Special case, we still can't make the room for the new remote one. - if !isLocal && !success { - log.Trace("Discarding overflown transaction", "hash", hash) - overflowedTxMeter.Mark(1) - return false, ErrTxPoolOverflow - } - - // If the new transaction is a future transaction it should never churn pending transactions - if !isLocal && pool.isGapped(from, tx) { - var replacesPending bool - for _, dropTx := range drop { - dropSender, _ := types.Sender(pool.signer, dropTx) - if list := pool.pending[dropSender]; list != nil && list.Contains(dropTx.Nonce()) { - replacesPending = true - break - } - } - // Add all transactions back to the priced queue - if replacesPending { - for _, dropTx := range drop { - pool.priced.Put(dropTx, false) - } - log.Trace("Discarding future transaction replacing pending tx", "hash", hash) - return false, txpool.ErrFutureReplacePending - } - } - - // Kick out the underpriced remote transactions. - for _, tx := range drop { - log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) - underpricedTxMeter.Mark(1) - - sender, _ := types.Sender(pool.signer, tx) - dropped := pool.removeTx(tx.Hash(), false, sender != from) // Don't unreserve the sender of the tx being added if last from the acc - - pool.changesSinceReorg += dropped - } - } - - // Try to replace an existing transaction in the pending pool - if list := pool.pending[from]; list != nil && list.Contains(tx.Nonce()) { - // Nonce already pending, check if required price bump is met - inserted, old := list.Add(tx, pool.config.PriceBump) - if !inserted { - pendingDiscardMeter.Mark(1) - return false, txpool.ErrReplaceUnderpriced - } - // New transaction is better, replace old one - if old != nil { - pool.all.Remove(old.Hash()) - pool.priced.Removed(1) - pendingReplaceMeter.Mark(1) - } - pool.all.Add(tx, isLocal) - pool.priced.Put(tx, isLocal) - pool.journalTx(from, tx) - pool.queueTxEvent(tx) - log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) - - // Successful promotion, bump the heartbeat - pool.beats[from] = time.Now() - return old != nil, nil - } - // New transaction isn't replacing a pending one, push into queue - replaced, err = pool.enqueueTx(hash, tx, isLocal, true) - if err != nil { - return false, err - } - // Mark local addresses and journal local transactions - if local && !pool.locals.contains(from) { - log.Info("Setting new local account", "address", from) - pool.locals.add(from) - pool.priced.Removed(pool.all.RemoteToLocals(pool.locals)) // Migrate the remotes if it's marked as local first time. - } - if isLocal { - localGauge.Inc(1) - } - pool.journalTx(from, tx) - - log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To()) - return replaced, nil -} - -// isGapped reports whether the given transaction is immediately executable. -func (pool *LegacyPool) isGapped(from common.Address, tx *types.Transaction) bool { - // Short circuit if transaction falls within the scope of the pending list - // or matches the next pending nonce which can be promoted as an executable - // transaction afterwards. Note, the tx staleness is already checked in - // 'validateTx' function previously. - next := pool.pendingNonces.get(from) - if tx.Nonce() <= next { - return false - } - // The transaction has a nonce gap with pending list, it's only considered - // as executable if transactions in queue can fill up the nonce gap. - queue, ok := pool.queue[from] - if !ok { - return true - } - for nonce := next; nonce < tx.Nonce(); nonce++ { - if !queue.Contains(nonce) { - return true // txs in queue can't fill up the nonce gap - } - } - return false -} - -// enqueueTx inserts a new transaction into the non-executable transaction queue. -// -// Note, this method assumes the pool lock is held! -func (pool *LegacyPool) enqueueTx(hash common.Hash, tx *types.Transaction, local bool, addAll bool) (bool, error) { - // Try to insert the transaction into the future queue - from, _ := types.Sender(pool.signer, tx) // already validated - if pool.queue[from] == nil { - pool.queue[from] = newList(false) - } - inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) - if !inserted { - // An older transaction was better, discard this - queuedDiscardMeter.Mark(1) - return false, txpool.ErrReplaceUnderpriced - } - // Discard any previous transaction and mark this - if old != nil { - pool.all.Remove(old.Hash()) - pool.priced.Removed(1) - queuedReplaceMeter.Mark(1) - } else { - // Nothing was replaced, bump the queued counter - queuedGauge.Inc(1) - } - // If the transaction isn't in lookup set but it's expected to be there, - // show the error log. - if pool.all.Get(hash) == nil && !addAll { - log.Error("Missing transaction in lookup set, please report the issue", "hash", hash) - } - if addAll { - pool.all.Add(tx, local) - pool.priced.Put(tx, local) - } - // If we never record the heartbeat, do it right now. - if _, exist := pool.beats[from]; !exist { - pool.beats[from] = time.Now() - } - return old != nil, nil -} - -// journalTx adds the specified transaction to the local disk journal if it is -// deemed to have been sent from a local account. -func (pool *LegacyPool) journalTx(from common.Address, tx *types.Transaction) { - // Only journal if it's enabled and the transaction is local - if pool.journal == nil || !pool.locals.contains(from) { - return - } - if err := pool.journal.insert(tx); err != nil { - log.Warn("Failed to journal local transaction", "err", err) - } -} - -// promoteTx adds a transaction to the pending (processable) list of transactions -// and returns whether it was inserted or an older was better. -// -// Note, this method assumes the pool lock is held! -func (pool *LegacyPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool { - // Try to insert the transaction into the pending queue - if pool.pending[addr] == nil { - pool.pending[addr] = newList(true) - } - list := pool.pending[addr] - - inserted, old := list.Add(tx, pool.config.PriceBump) - if !inserted { - // An older transaction was better, discard this - pool.all.Remove(hash) - pool.priced.Removed(1) - pendingDiscardMeter.Mark(1) - return false - } - // Otherwise discard any previous transaction and mark this - if old != nil { - pool.all.Remove(old.Hash()) - pool.priced.Removed(1) - pendingReplaceMeter.Mark(1) - } else { - // Nothing was replaced, bump the pending counter - pendingGauge.Inc(1) - } - // Set the potentially new pending nonce and notify any subsystems of the new tx - pool.pendingNonces.set(addr, tx.Nonce()+1) - - // Successful promotion, bump the heartbeat - pool.beats[addr] = time.Now() - return true -} - -// addLocals enqueues a batch of transactions into the pool if they are valid, marking the -// senders as local ones, ensuring they go around the local pricing constraints. -// -// This method is used to add transactions from the RPC API and performs synchronous pool -// reorganization and event propagation. -func (pool *LegacyPool) addLocals(txs []*types.Transaction) []error { - return pool.Add(txs, !pool.config.NoLocals, true, false) -} - -// addLocal enqueues a single local transaction into the pool if it is valid. This is -// a convenience wrapper around addLocals. -func (pool *LegacyPool) addLocal(tx *types.Transaction) error { - return pool.addLocals([]*types.Transaction{tx})[0] -} - -// addRemotes enqueues a batch of transactions into the pool if they are valid. If the -// senders are not among the locally tracked ones, full pricing constraints will apply. -// -// This method is used to add transactions from the p2p network and does not wait for pool -// reorganization and internal event propagation. -func (pool *LegacyPool) addRemotes(txs []*types.Transaction) []error { - return pool.Add(txs, false, false, false) -} - -// addRemote enqueues a single transaction into the pool if it is valid. This is a convenience -// wrapper around addRemotes. -func (pool *LegacyPool) addRemote(tx *types.Transaction) error { - return pool.addRemotes([]*types.Transaction{tx})[0] -} - -// addRemotesSync is like addRemotes, but waits for pool reorganization. Tests use this method. -func (pool *LegacyPool) addRemotesSync(txs []*types.Transaction) []error { - return pool.Add(txs, false, true, false) -} - -// This is like addRemotes with a single transaction, but waits for pool reorganization. Tests use this method. -func (pool *LegacyPool) addRemoteSync(tx *types.Transaction) error { - return pool.Add([]*types.Transaction{tx}, false, true, false)[0] -} - -// Add enqueues a batch of transactions into the pool if they are valid. Depending -// on the local flag, full pricing constraints will or will not be applied. -// -// If sync is set, the method will block until all internal maintenance related -// to the add is finished. Only use this during tests for determinism! -func (pool *LegacyPool) Add(txs []*types.Transaction, local, sync bool, private bool) []error { - // Do not treat as local if local transactions have been disabled - local = local && !pool.config.NoLocals - - // Filter out known ones without obtaining the pool lock or recovering signatures - var ( - errs = make([]error, len(txs)) - news = make([]*types.Transaction, 0, len(txs)) - ) - for i, tx := range txs { - // If the transaction is known, pre-set the error slot - if pool.all.Get(tx.Hash()) != nil { - errs[i] = txpool.ErrAlreadyKnown - knownTxMeter.Mark(1) - continue - } - // Exclude transactions with basic errors, e.g invalid signatures and - // insufficient intrinsic gas as soon as possible and cache senders - // in transactions before obtaining lock - if err := pool.validateTxBasics(tx, local); err != nil { - errs[i] = err - log.Trace("Discarding invalid transaction", "hash", tx.Hash(), "err", err) - invalidTxMeter.Mark(1) - continue - } - // Accumulate all unknown transactions for deeper processing - news = append(news, tx) - } - if len(news) == 0 { - return errs - } - - // Track private transactions, so they don't get leaked to the public mempool - if private { - for _, tx := range news { - pool.privateTxs.Add(tx.Hash()) - } - } - - // Process all the new transaction and merge any errors into the original slice - pool.mu.Lock() - newErrs, dirtyAddrs := pool.addTxsLocked(news, local) - pool.mu.Unlock() - - var nilSlot = 0 - for _, err := range newErrs { - for errs[nilSlot] != nil { - nilSlot++ - } - errs[nilSlot] = err - nilSlot++ - } - // Reorg the pool internals if needed and return - done := pool.requestPromoteExecutables(dirtyAddrs) - if sync { - <-done - } - return errs -} - -// addTxsLocked attempts to queue a batch of transactions if they are valid. -// The transaction pool lock must be held. -func (pool *LegacyPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error, *accountSet) { - dirty := newAccountSet(pool.signer) - errs := make([]error, len(txs)) - for i, tx := range txs { - replaced, err := pool.add(tx, local) - errs[i] = err - if err == nil && !replaced { - dirty.addTx(tx) - } - } - validTxMeter.Mark(int64(len(dirty.accounts))) - return errs, dirty -} - -// Status returns the status (unknown/pending/queued) of a batch of transactions -// identified by their hashes. -func (pool *LegacyPool) Status(hash common.Hash) txpool.TxStatus { - tx := pool.get(hash) - if tx == nil { - return txpool.TxStatusUnknown - } - from, _ := types.Sender(pool.signer, tx) // already validated - - pool.mu.RLock() - defer pool.mu.RUnlock() - - if txList := pool.pending[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { - return txpool.TxStatusPending - } else if txList := pool.queue[from]; txList != nil && txList.txs.items[tx.Nonce()] != nil { - return txpool.TxStatusQueued - } - return txpool.TxStatusUnknown -} - -// Get returns a transaction if it is contained in the pool and nil otherwise. -func (pool *LegacyPool) Get(hash common.Hash) *types.Transaction { - tx := pool.get(hash) - if tx == nil { - return nil - } - return tx -} - -// get returns a transaction if it is contained in the pool and nil otherwise. -func (pool *LegacyPool) get(hash common.Hash) *types.Transaction { - return pool.all.Get(hash) -} - -// Has returns an indicator whether txpool has a transaction cached with the -// given hash. -func (pool *LegacyPool) Has(hash common.Hash) bool { - return pool.all.Get(hash) != nil -} - -// removeTx removes a single transaction from the queue, moving all subsequent -// transactions back to the future queue. -// -// In unreserve is false, the account will not be relinquished to the main txpool -// even if there are no more references to it. This is used to handle a race when -// a tx being added, and it evicts a previously scheduled tx from the same account, -// which could lead to a premature release of the lock. -// -// Returns the number of transactions removed from the pending queue. -func (pool *LegacyPool) removeTx(hash common.Hash, outofbound bool, unreserve bool) int { - // Fetch the transaction we wish to delete - tx := pool.all.Get(hash) - if tx == nil { - return 0 - } - addr, _ := types.Sender(pool.signer, tx) // already validated during insertion - - // If after deletion there are no more transactions belonging to this account, - // relinquish the address reservation. It's a bit convoluted do this, via a - // defer, but it's safer vs. the many return pathways. - if unreserve { - defer func() { - var ( - _, hasPending = pool.pending[addr] - _, hasQueued = pool.queue[addr] - ) - if !hasPending && !hasQueued { - pool.reserve(addr, false) - } - }() - } - // Remove it from the list of known transactions - pool.all.Remove(hash) - if outofbound { - pool.priced.Removed(1) - } - if pool.locals.contains(addr) { - localGauge.Dec(1) - } - // Remove the transaction from the pending lists and reset the account nonce - if pending := pool.pending[addr]; pending != nil { - if removed, invalids := pending.Remove(tx); removed { - // If no more pending transactions are left, remove the list - if pending.Empty() { - delete(pool.pending, addr) - } - // Postpone any invalidated transactions - for _, tx := range invalids { - // Internal shuffle shouldn't touch the lookup set. - pool.enqueueTx(tx.Hash(), tx, false, false) - } - // Update the account nonce if needed - pool.pendingNonces.setIfLower(addr, tx.Nonce()) - // Reduce the pending counter - pendingGauge.Dec(int64(1 + len(invalids))) - return 1 + len(invalids) - } - } - // Transaction is in the future queue - if future := pool.queue[addr]; future != nil { - if removed, _ := future.Remove(tx); removed { - // Reduce the queued counter - queuedGauge.Dec(1) - } - if future.Empty() { - delete(pool.queue, addr) - delete(pool.beats, addr) - } - } - return 0 -} - -// requestReset requests a pool reset to the new head block. -// The returned channel is closed when the reset has occurred. -func (pool *LegacyPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} { - select { - case pool.reqResetCh <- &txpoolResetRequest{oldHead, newHead}: - return <-pool.reorgDoneCh - case <-pool.reorgShutdownCh: - return pool.reorgShutdownCh - } -} - -// requestPromoteExecutables requests transaction promotion checks for the given addresses. -// The returned channel is closed when the promotion checks have occurred. -func (pool *LegacyPool) requestPromoteExecutables(set *accountSet) chan struct{} { - select { - case pool.reqPromoteCh <- set: - return <-pool.reorgDoneCh - case <-pool.reorgShutdownCh: - return pool.reorgShutdownCh - } -} - -// queueTxEvent enqueues a transaction event to be sent in the next reorg run. -func (pool *LegacyPool) queueTxEvent(tx *types.Transaction) { - select { - case pool.queueTxEventCh <- tx: - case <-pool.reorgShutdownCh: - } -} - -// scheduleReorgLoop schedules runs of reset and promoteExecutables. Code above should not -// call those methods directly, but request them being run using requestReset and -// requestPromoteExecutables instead. -func (pool *LegacyPool) scheduleReorgLoop() { - defer pool.wg.Done() - - var ( - curDone chan struct{} // non-nil while runReorg is active - nextDone = make(chan struct{}) - launchNextRun bool - reset *txpoolResetRequest - dirtyAccounts *accountSet - queuedEvents = make(map[common.Address]*sortedMap) - ) - for { - // Launch next background reorg if needed - if curDone == nil && launchNextRun { - // Run the background reorg and announcements - go pool.runReorg(nextDone, reset, dirtyAccounts, queuedEvents) - - // Prepare everything for the next round of reorg - curDone, nextDone = nextDone, make(chan struct{}) - launchNextRun = false - - reset, dirtyAccounts = nil, nil - queuedEvents = make(map[common.Address]*sortedMap) - } - - select { - case req := <-pool.reqResetCh: - // Reset request: update head if request is already pending. - if reset == nil { - reset = req - } else { - reset.newHead = req.newHead - } - launchNextRun = true - pool.reorgDoneCh <- nextDone - - case req := <-pool.reqPromoteCh: - // Promote request: update address set if request is already pending. - if dirtyAccounts == nil { - dirtyAccounts = req - } else { - dirtyAccounts.merge(req) - } - launchNextRun = true - pool.reorgDoneCh <- nextDone - - case tx := <-pool.queueTxEventCh: - // Queue up the event, but don't schedule a reorg. It's up to the caller to - // request one later if they want the events sent. - addr, _ := types.Sender(pool.signer, tx) - if _, ok := queuedEvents[addr]; !ok { - queuedEvents[addr] = newSortedMap() - } - queuedEvents[addr].Put(tx) - - case <-curDone: - curDone = nil - - case <-pool.reorgShutdownCh: - // Wait for current run to finish. - if curDone != nil { - <-curDone - } - close(nextDone) - return - } - } -} - -// runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop. -func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*sortedMap) { - defer func(t0 time.Time) { - reorgDurationTimer.Update(time.Since(t0)) - }(time.Now()) - defer close(done) - - var promoteAddrs []common.Address - if dirtyAccounts != nil && reset == nil { - // Only dirty accounts need to be promoted, unless we're resetting. - // For resets, all addresses in the tx queue will be promoted and - // the flatten operation can be avoided. - promoteAddrs = dirtyAccounts.flatten() - } - pool.mu.Lock() - if reset != nil { - // Reset from the old head to the new, rescheduling any reorged transactions - pool.reset(reset.oldHead, reset.newHead) - - // Nonces were reset, discard any events that became stale - for addr := range events { - events[addr].Forward(pool.pendingNonces.get(addr)) - if events[addr].Len() == 0 { - delete(events, addr) - } - } - // Reset needs promote for all addresses - promoteAddrs = make([]common.Address, 0, len(pool.queue)) - for addr := range pool.queue { - promoteAddrs = append(promoteAddrs, addr) - } - } - // Check for pending transactions for every account that sent new ones - promoted := pool.promoteExecutables(promoteAddrs) - - // If a new block appeared, validate the pool of pending transactions. This will - // remove any transaction that has been included in the block or was invalidated - // because of another transaction (e.g. higher gas price). - if reset != nil { - pool.demoteUnexecutables() - if reset.newHead != nil { - if pool.chainconfig.IsLondon(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { - pendingBaseFee := eip1559.CalcBaseFee(pool.chainconfig, reset.newHead) - pool.priced.SetBaseFee(pendingBaseFee) - } else { - pool.priced.Reheap() - } - } - // Update all accounts to the latest known pending nonce - nonces := make(map[common.Address]uint64, len(pool.pending)) - for addr, list := range pool.pending { - highestPending := list.LastElement() - nonces[addr] = highestPending.Nonce() + 1 - } - pool.pendingNonces.setAll(nonces) - } - // Ensure pool.queue and pool.pending sizes stay within the configured limits. - pool.truncatePending() - pool.truncateQueue() - - dropBetweenReorgHistogram.Update(int64(pool.changesSinceReorg)) - pool.changesSinceReorg = 0 // Reset change counter - pool.mu.Unlock() - - // Notify subsystems for newly added transactions - for _, tx := range promoted { - addr, _ := types.Sender(pool.signer, tx) - if _, ok := events[addr]; !ok { - events[addr] = newSortedMap() - } - events[addr].Put(tx) - } - if len(events) > 0 { - var txs []*types.Transaction - for _, set := range events { - for _, tx := range set.Flatten() { - if !pool.IsPrivateTxHash(tx.Hash()) { - txs = append(txs, tx) - } - } - } - pool.txFeed.Send(core.NewTxsEvent{Txs: txs}) - } -} - -// reset retrieves the current state of the blockchain and ensures the content -// of the transaction pool is valid with regard to the chain state. -func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { - // If we're reorging an old state, reinject all dropped transactions - var reinject types.Transactions - - if oldHead != nil && oldHead.Hash() != newHead.ParentHash { - // If the reorg is too deep, avoid doing it (will happen during fast sync) - oldNum := oldHead.Number.Uint64() - newNum := newHead.Number.Uint64() - - if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { - log.Debug("Skipping deep transaction reorg", "depth", depth) - } else { - // Reorg seems shallow enough to pull in all transactions into memory - var ( - rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) - add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) - ) - if rem == nil { - // This can happen if a setHead is performed, where we simply discard the old - // head from the chain. - // If that is the case, we don't have the lost transactions anymore, and - // there's nothing to add - if newNum >= oldNum { - // If we reorged to a same or higher number, then it's not a case of setHead - log.Warn("Transaction pool reset with missing old head", - "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) - return - } - // If the reorg ended up on a lower number, it's indicative of setHead being the cause - log.Debug("Skipping transaction reset caused by setHead", - "old", oldHead.Hash(), "oldnum", oldNum, "new", newHead.Hash(), "newnum", newNum) - // We still need to update the current state s.th. the lost transactions can be readded by the user - } else { - if add == nil { - // if the new head is nil, it means that something happened between - // the firing of newhead-event and _now_: most likely a - // reorg caused by sync-reversion or explicit sethead back to an - // earlier block. - log.Warn("Transaction pool reset with missing new head", "number", newHead.Number, "hash", newHead.Hash()) - return - } - var discarded, included types.Transactions - for rem.NumberU64() > add.NumberU64() { - discarded = append(discarded, rem.Transactions()...) - if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) - return - } - } - for add.NumberU64() > rem.NumberU64() { - included = append(included, add.Transactions()...) - if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) - return - } - } - for rem.Hash() != add.Hash() { - discarded = append(discarded, rem.Transactions()...) - if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { - log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) - return - } - included = append(included, add.Transactions()...) - if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { - log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) - return - } - } - lost := make([]*types.Transaction, 0, len(discarded)) - for _, tx := range types.TxDifference(discarded, included) { - if pool.Filter(tx) { - lost = append(lost, tx) - } - } - reinject = lost - } - } - } - // Initialize the internal state to the current head - if newHead == nil { - newHead = pool.chain.CurrentBlock() // Special case during testing - } - statedb, err := pool.chain.StateAt(newHead.Root) - if err != nil { - log.Error("Failed to reset txpool state", "err", err) - return - } - pool.currentHead.Store(newHead) - pool.currentState = statedb - pool.pendingNonces = newNoncer(statedb) - - // Inject any transactions discarded due to reorgs - log.Debug("Reinjecting stale transactions", "count", len(reinject)) - core.SenderCacher.Recover(pool.signer, reinject) - pool.addTxsLocked(reinject, false) -} - -// promoteExecutables moves transactions that have become processable from the -// future queue to the set of pending transactions. During this process, all -// invalidated transactions (low nonce, low balance) are deleted. -func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.Transaction { - // Track the promoted transactions to broadcast them at once - var promoted []*types.Transaction - - // Iterate over all accounts and promote any executable transactions - gasLimit := pool.currentHead.Load().GasLimit - for _, addr := range accounts { - list := pool.queue[addr] - if list == nil { - continue // Just in case someone calls with a non existing account - } - // Drop all transactions that are deemed too old (low nonce) - forwards := list.Forward(pool.currentState.GetNonce(addr)) - for _, tx := range forwards { - hash := tx.Hash() - pool.all.Remove(hash) - pool.privateTxs.Remove(hash) - } - log.Trace("Removed old queued transactions", "count", len(forwards)) - // Drop all transactions that are too costly (low balance or out of gas) - drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit) - for _, tx := range drops { - hash := tx.Hash() - pool.all.Remove(hash) - } - log.Trace("Removed unpayable queued transactions", "count", len(drops)) - queuedNofundsMeter.Mark(int64(len(drops))) - - // Gather all executable transactions and promote them - readies := list.Ready(pool.pendingNonces.get(addr)) - for _, tx := range readies { - hash := tx.Hash() - if pool.promoteTx(addr, hash, tx) { - promoted = append(promoted, tx) - } - } - log.Trace("Promoted queued transactions", "count", len(promoted)) - queuedGauge.Dec(int64(len(readies))) - - // Drop all transactions over the allowed limit - var caps types.Transactions - if !pool.locals.contains(addr) { - caps = list.Cap(int(pool.config.AccountQueue)) - for _, tx := range caps { - hash := tx.Hash() - pool.all.Remove(hash) - log.Trace("Removed cap-exceeding queued transaction", "hash", hash) - } - queuedRateLimitMeter.Mark(int64(len(caps))) - } - // Mark all the items dropped as removed - pool.priced.Removed(len(forwards) + len(drops) + len(caps)) - queuedGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) - if pool.locals.contains(addr) { - localGauge.Dec(int64(len(forwards) + len(drops) + len(caps))) - } - // Delete the entire queue entry if it became empty. - if list.Empty() { - delete(pool.queue, addr) - delete(pool.beats, addr) - if _, ok := pool.pending[addr]; !ok { - pool.reserve(addr, false) - } - } - } - return promoted -} - -// truncatePending removes transactions from the pending queue if the pool is above the -// pending limit. The algorithm tries to reduce transaction counts by an approximately -// equal number for all for accounts with many pending transactions. -func (pool *LegacyPool) truncatePending() { - pending := uint64(0) - for _, list := range pool.pending { - pending += uint64(list.Len()) - } - if pending <= pool.config.GlobalSlots { - return - } - - pendingBeforeCap := pending - // Assemble a spam order to penalize large transactors first - spammers := prque.New[int64, common.Address](nil) - for addr, list := range pool.pending { - // Only evict transactions from high rollers - if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { - spammers.Push(addr, int64(list.Len())) - } - } - // Gradually drop transactions from offenders - offenders := []common.Address{} - for pending > pool.config.GlobalSlots && !spammers.Empty() { - // Retrieve the next offender if not local address - offender, _ := spammers.Pop() - offenders = append(offenders, offender) - - // Equalize balances until all the same or below threshold - if len(offenders) > 1 { - // Calculate the equalization threshold for all current offenders - threshold := pool.pending[offender].Len() - - // Iteratively reduce all offenders until below limit or threshold reached - for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { - for i := 0; i < len(offenders)-1; i++ { - list := pool.pending[offenders[i]] - - caps := list.Cap(list.Len() - 1) - for _, tx := range caps { - // Drop the transaction from the global pools too - hash := tx.Hash() - pool.all.Remove(hash) - - // Update the account nonce to the dropped transaction - pool.pendingNonces.setIfLower(offenders[i], tx.Nonce()) - log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) - } - pool.priced.Removed(len(caps)) - pendingGauge.Dec(int64(len(caps))) - if pool.locals.contains(offenders[i]) { - localGauge.Dec(int64(len(caps))) - } - pending-- - } - } - } - } - - // If still above threshold, reduce to limit or min allowance - if pending > pool.config.GlobalSlots && len(offenders) > 0 { - for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { - for _, addr := range offenders { - list := pool.pending[addr] - - caps := list.Cap(list.Len() - 1) - for _, tx := range caps { - // Drop the transaction from the global pools too - hash := tx.Hash() - pool.all.Remove(hash) - - // Update the account nonce to the dropped transaction - pool.pendingNonces.setIfLower(addr, tx.Nonce()) - log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) - } - pool.priced.Removed(len(caps)) - pendingGauge.Dec(int64(len(caps))) - if pool.locals.contains(addr) { - localGauge.Dec(int64(len(caps))) - } - pending-- - } - } - } - pendingRateLimitMeter.Mark(int64(pendingBeforeCap - pending)) -} - -// truncateQueue drops the oldest transactions in the queue if the pool is above the global queue limit. -func (pool *LegacyPool) truncateQueue() { - queued := uint64(0) - for _, list := range pool.queue { - queued += uint64(list.Len()) - } - if queued <= pool.config.GlobalQueue { - return - } - - // Sort all accounts with queued transactions by heartbeat - addresses := make(addressesByHeartbeat, 0, len(pool.queue)) - for addr := range pool.queue { - if !pool.locals.contains(addr) { // don't drop locals - addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) - } - } - sort.Sort(sort.Reverse(addresses)) - - // Drop transactions until the total is below the limit or only locals remain - for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { - addr := addresses[len(addresses)-1] - list := pool.queue[addr.address] - - addresses = addresses[:len(addresses)-1] - - // Drop all transactions if they are less than the overflow - if size := uint64(list.Len()); size <= drop { - for _, tx := range list.Flatten() { - pool.removeTx(tx.Hash(), true, true) - } - drop -= size - queuedRateLimitMeter.Mark(int64(size)) - continue - } - // Otherwise drop only last few transactions - txs := list.Flatten() - for i := len(txs) - 1; i >= 0 && drop > 0; i-- { - pool.removeTx(txs[i].Hash(), true, true) - drop-- - queuedRateLimitMeter.Mark(1) - } - } -} - -// demoteUnexecutables removes invalid and processed transactions from the pools -// executable/pending queue and any subsequent transactions that become unexecutable -// are moved back into the future queue. -// -// Note: transactions are not marked as removed in the priced list because re-heaping -// is always explicitly triggered by SetBaseFee and it would be unnecessary and wasteful -// to trigger a re-heap is this function -func (pool *LegacyPool) demoteUnexecutables() { - // Iterate over all accounts and demote any non-executable transactions - gasLimit := pool.currentHead.Load().GasLimit - for addr, list := range pool.pending { - nonce := pool.currentState.GetNonce(addr) - - // Drop all transactions that are deemed too old (low nonce) - olds := list.Forward(nonce) - for _, tx := range olds { - hash := tx.Hash() - pool.all.Remove(hash) - log.Trace("Removed old pending transaction", "hash", hash) - } - // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later - drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit) - for _, tx := range drops { - hash := tx.Hash() - log.Trace("Removed unpayable pending transaction", "hash", hash) - pool.all.Remove(hash) - } - pendingNofundsMeter.Mark(int64(len(drops))) - - for _, tx := range invalids { - hash := tx.Hash() - log.Trace("Demoting pending transaction", "hash", hash) - - // Internal shuffle shouldn't touch the lookup set. - pool.enqueueTx(hash, tx, false, false) - } - pendingGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) - if pool.locals.contains(addr) { - localGauge.Dec(int64(len(olds) + len(drops) + len(invalids))) - } - // If there's a gap in front, alert (should never happen) and postpone all transactions - if list.Len() > 0 && list.txs.Get(nonce) == nil { - gapped := list.Cap(0) - for _, tx := range gapped { - hash := tx.Hash() - log.Error("Demoting invalidated transaction", "hash", hash) - - // Internal shuffle shouldn't touch the lookup set. - pool.enqueueTx(hash, tx, false, false) - } - pendingGauge.Dec(int64(len(gapped))) - } - // Delete the entire pending entry if it became empty. - if list.Empty() { - delete(pool.pending, addr) - if _, ok := pool.queue[addr]; !ok { - pool.reserve(addr, false) - } - } - } -} - -// addressByHeartbeat is an account address tagged with its last activity timestamp. -type addressByHeartbeat struct { - address common.Address - heartbeat time.Time -} - -type addressesByHeartbeat []addressByHeartbeat - -func (a addressesByHeartbeat) Len() int { return len(a) } -func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) } -func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] } - -// accountSet is simply a set of addresses to check for existence, and a signer -// capable of deriving addresses from transactions. -type accountSet struct { - accounts map[common.Address]struct{} - signer types.Signer - cache *[]common.Address -} - -// newAccountSet creates a new address set with an associated signer for sender -// derivations. -func newAccountSet(signer types.Signer, addrs ...common.Address) *accountSet { - as := &accountSet{ - accounts: make(map[common.Address]struct{}, len(addrs)), - signer: signer, - } - for _, addr := range addrs { - as.add(addr) - } - return as -} - -// contains checks if a given address is contained within the set. -func (as *accountSet) contains(addr common.Address) bool { - _, exist := as.accounts[addr] - return exist -} - -// containsTx checks if the sender of a given tx is within the set. If the sender -// cannot be derived, this method returns false. -func (as *accountSet) containsTx(tx *types.Transaction) bool { - if addr, err := types.Sender(as.signer, tx); err == nil { - return as.contains(addr) - } - return false -} - -// add inserts a new address into the set to track. -func (as *accountSet) add(addr common.Address) { - as.accounts[addr] = struct{}{} - as.cache = nil -} - -// addTx adds the sender of tx into the set. -func (as *accountSet) addTx(tx *types.Transaction) { - if addr, err := types.Sender(as.signer, tx); err == nil { - as.add(addr) - } -} - -// flatten returns the list of addresses within this set, also caching it for later -// reuse. The returned slice should not be changed! -func (as *accountSet) flatten() []common.Address { - if as.cache == nil { - accounts := make([]common.Address, 0, len(as.accounts)) - for account := range as.accounts { - accounts = append(accounts, account) - } - as.cache = &accounts - } - return *as.cache -} - -// merge adds all addresses from the 'other' set into 'as'. -func (as *accountSet) merge(other *accountSet) { - for addr := range other.accounts { - as.accounts[addr] = struct{}{} - } - as.cache = nil -} - -// lookup is used internally by LegacyPool to track transactions while allowing -// lookup without mutex contention. -// -// Note, although this type is properly protected against concurrent access, it -// is **not** a type that should ever be mutated or even exposed outside of the -// transaction pool, since its internal state is tightly coupled with the pools -// internal mechanisms. The sole purpose of the type is to permit out-of-bound -// peeking into the pool in LegacyPool.Get without having to acquire the widely scoped -// LegacyPool.mu mutex. -// -// This lookup set combines the notion of "local transactions", which is useful -// to build upper-level structure. -type lookup struct { - slots int - lock sync.RWMutex - locals map[common.Hash]*types.Transaction - remotes map[common.Hash]*types.Transaction -} - -// newLookup returns a new lookup structure. -func newLookup() *lookup { - return &lookup{ - locals: make(map[common.Hash]*types.Transaction), - remotes: make(map[common.Hash]*types.Transaction), - } -} - -// Range calls f on each key and value present in the map. The callback passed -// should return the indicator whether the iteration needs to be continued. -// Callers need to specify which set (or both) to be iterated. -func (t *lookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) { - t.lock.RLock() - defer t.lock.RUnlock() - - if local { - for key, value := range t.locals { - if !f(key, value, true) { - return - } - } - } - if remote { - for key, value := range t.remotes { - if !f(key, value, false) { - return - } - } - } -} - -// Get returns a transaction if it exists in the lookup, or nil if not found. -func (t *lookup) Get(hash common.Hash) *types.Transaction { - t.lock.RLock() - defer t.lock.RUnlock() - - if tx := t.locals[hash]; tx != nil { - return tx - } - return t.remotes[hash] -} - -// GetLocal returns a transaction if it exists in the lookup, or nil if not found. -func (t *lookup) GetLocal(hash common.Hash) *types.Transaction { - t.lock.RLock() - defer t.lock.RUnlock() - - return t.locals[hash] -} - -// GetRemote returns a transaction if it exists in the lookup, or nil if not found. -func (t *lookup) GetRemote(hash common.Hash) *types.Transaction { - t.lock.RLock() - defer t.lock.RUnlock() - - return t.remotes[hash] -} - -// Count returns the current number of transactions in the lookup. -func (t *lookup) Count() int { - t.lock.RLock() - defer t.lock.RUnlock() - - return len(t.locals) + len(t.remotes) -} - -// LocalCount returns the current number of local transactions in the lookup. -func (t *lookup) LocalCount() int { - t.lock.RLock() - defer t.lock.RUnlock() - - return len(t.locals) -} - -// RemoteCount returns the current number of remote transactions in the lookup. -func (t *lookup) RemoteCount() int { - t.lock.RLock() - defer t.lock.RUnlock() - - return len(t.remotes) -} - -// Slots returns the current number of slots used in the lookup. -func (t *lookup) Slots() int { - t.lock.RLock() - defer t.lock.RUnlock() - - return t.slots -} - -// Add adds a transaction to the lookup. -func (t *lookup) Add(tx *types.Transaction, local bool) { - t.lock.Lock() - defer t.lock.Unlock() - - t.slots += numSlots(tx) - slotsGauge.Update(int64(t.slots)) - - if local { - t.locals[tx.Hash()] = tx - } else { - t.remotes[tx.Hash()] = tx - } -} - -// Remove removes a transaction from the lookup. -func (t *lookup) Remove(hash common.Hash) { - t.lock.Lock() - defer t.lock.Unlock() - - tx, ok := t.locals[hash] - if !ok { - tx, ok = t.remotes[hash] - } - if !ok { - log.Error("No transaction found to be deleted", "hash", hash) - return - } - t.slots -= numSlots(tx) - slotsGauge.Update(int64(t.slots)) - - delete(t.locals, hash) - delete(t.remotes, hash) -} - -// RemoteToLocals migrates the transactions belongs to the given locals to locals -// set. The assumption is held the locals set is thread-safe to be used. -func (t *lookup) RemoteToLocals(locals *accountSet) int { - t.lock.Lock() - defer t.lock.Unlock() - - var migrated int - for hash, tx := range t.remotes { - if locals.containsTx(tx) { - t.locals[hash] = tx - delete(t.remotes, hash) - migrated += 1 - } - } - return migrated -} - -// RemotesBelowTip finds all remote transactions below the given tip threshold. -func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions { - found := make(types.Transactions, 0, 128) - t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool { - if tx.GasTipCapIntCmp(threshold) < 0 { - found = append(found, tx) - } - return true - }, false, true) // Only iterate remotes - return found -} - -// numSlots calculates the number of slots needed for a single transaction. -func numSlots(tx *types.Transaction) int { - return int((tx.Size() + txSlotSize - 1) / txSlotSize) -} diff --git a/builder/core/txpool/legacypool/legacypool2_test.go b/builder/core/txpool/legacypool/legacypool2_test.go deleted file mode 100644 index c8d3a76b8..000000000 --- a/builder/core/txpool/legacypool/legacypool2_test.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2023 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 legacypool - -import ( - "crypto/ecdsa" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/event" - "github.com/holiman/uint256" -) - -func pricedValuedTransaction(nonce uint64, value int64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(value), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) - return tx -} - -func count(t *testing.T, pool *LegacyPool) (pending int, queued int) { - t.Helper() - pending, queued = pool.stats() - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - return pending, queued -} - -func fillPool(t testing.TB, pool *LegacyPool) { - t.Helper() - // Create a number of test accounts, fund them and make transactions - executableTxs := types.Transactions{} - nonExecutableTxs := types.Transactions{} - for i := 0; i < 384; i++ { - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(10000000000)) - // Add executable ones - for j := 0; j < int(pool.config.AccountSlots); j++ { - executableTxs = append(executableTxs, pricedTransaction(uint64(j), 100000, big.NewInt(300), key)) - } - } - // Import the batch and verify that limits have been enforced - pool.addRemotesSync(executableTxs) - pool.addRemotesSync(nonExecutableTxs) - pending, queued := pool.Stats() - slots := pool.all.Slots() - // sanity-check that the test prerequisites are ok (pending full) - if have, want := pending, slots; have != want { - t.Fatalf("have %d, want %d", have, want) - } - if have, want := queued, 0; have != want { - t.Fatalf("have %d, want %d", have, want) - } - - t.Logf("pool.config: GlobalSlots=%d, GlobalQueue=%d\n", pool.config.GlobalSlots, pool.config.GlobalQueue) - t.Logf("pending: %d queued: %d, all: %d\n", pending, queued, slots) -} - -// Tests that if a batch high-priced of non-executables arrive, they do not kick out -// executable transactions -func TestTransactionFutureAttack(t *testing.T) { - t.Parallel() - - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - config := testTxPoolConfig - config.GlobalQueue = 100 - config.GlobalSlots = 100 - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - fillPool(t, pool) - pending, _ := pool.Stats() - // Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops - { - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000)) - futureTxs := types.Transactions{} - for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ { - futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 100000, big.NewInt(500), key)) - } - for i := 0; i < 5; i++ { - pool.addRemotesSync(futureTxs) - newPending, newQueued := count(t, pool) - t.Logf("pending: %d queued: %d, all: %d\n", newPending, newQueued, pool.all.Slots()) - } - } - newPending, _ := pool.Stats() - // Pending should not have been touched - if have, want := newPending, pending; have < want { - t.Errorf("wrong pending-count, have %d, want %d (GlobalSlots: %d)", - have, want, pool.config.GlobalSlots) - } -} - -// Tests that if a batch high-priced of non-executables arrive, they do not kick out -// executable transactions -func TestTransactionFuture1559(t *testing.T) { - t.Parallel() - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts, fund them and make transactions - fillPool(t, pool) - pending, _ := pool.Stats() - - // Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops - { - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000)) - futureTxs := types.Transactions{} - for j := 0; j < int(pool.config.GlobalSlots+pool.config.GlobalQueue); j++ { - futureTxs = append(futureTxs, dynamicFeeTx(1000+uint64(j), 100000, big.NewInt(200), big.NewInt(101), key)) - } - pool.addRemotesSync(futureTxs) - } - newPending, _ := pool.Stats() - // Pending should not have been touched - if have, want := newPending, pending; have != want { - t.Errorf("Wrong pending-count, have %d, want %d (GlobalSlots: %d)", - have, want, pool.config.GlobalSlots) - } -} - -// Tests that if a batch of balance-overdraft txs arrive, they do not kick out -// executable transactions -func TestTransactionZAttack(t *testing.T) { - t.Parallel() - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - // Create a number of test accounts, fund them and make transactions - fillPool(t, pool) - - countInvalidPending := func() int { - t.Helper() - var ivpendingNum int - pendingtxs, _ := pool.Content() - for account, txs := range pendingtxs { - cur_balance := new(big.Int).Set(pool.currentState.GetBalance(account).ToBig()) - for _, tx := range txs { - if cur_balance.Cmp(tx.Value()) <= 0 { - ivpendingNum++ - } else { - cur_balance.Sub(cur_balance, tx.Value()) - } - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - return ivpendingNum - } - ivPending := countInvalidPending() - t.Logf("invalid pending: %d\n", ivPending) - - // Now, DETER-Z attack starts, let's add a bunch of expensive non-executables (from N accounts) along with balance-overdraft txs (from one account), and see if the pending-count drops - for j := 0; j < int(pool.config.GlobalQueue); j++ { - futureTxs := types.Transactions{} - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000)) - futureTxs = append(futureTxs, pricedTransaction(1000+uint64(j), 21000, big.NewInt(500), key)) - pool.addRemotesSync(futureTxs) - } - - overDraftTxs := types.Transactions{} - { - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000)) - for j := 0; j < int(pool.config.GlobalSlots); j++ { - overDraftTxs = append(overDraftTxs, pricedValuedTransaction(uint64(j), 600000000000, 21000, big.NewInt(500), key)) - } - } - pool.addRemotesSync(overDraftTxs) - pool.addRemotesSync(overDraftTxs) - pool.addRemotesSync(overDraftTxs) - pool.addRemotesSync(overDraftTxs) - pool.addRemotesSync(overDraftTxs) - - newPending, newQueued := count(t, pool) - newIvPending := countInvalidPending() - t.Logf("pool.all.Slots(): %d\n", pool.all.Slots()) - t.Logf("pending: %d queued: %d, all: %d\n", newPending, newQueued, pool.all.Slots()) - t.Logf("invalid pending: %d\n", newIvPending) - - // Pending should not have been touched - if newIvPending != ivPending { - t.Errorf("Wrong invalid pending-count, have %d, want %d (GlobalSlots: %d, queued: %d)", - newIvPending, ivPending, pool.config.GlobalSlots, newQueued) - } -} - -func BenchmarkFutureAttack(b *testing.B) { - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - config := testTxPoolConfig - config.GlobalQueue = 100 - config.GlobalSlots = 100 - pool := New(config, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - fillPool(b, pool) - - key, _ := crypto.GenerateKey() - pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), uint256.NewInt(100000000000)) - futureTxs := types.Transactions{} - - for n := 0; n < b.N; n++ { - futureTxs = append(futureTxs, pricedTransaction(1000+uint64(n), 100000, big.NewInt(500), key)) - } - b.ResetTimer() - for i := 0; i < 5; i++ { - pool.addRemotesSync(futureTxs) - } -} diff --git a/builder/core/txpool/legacypool/legacypool_test.go b/builder/core/txpool/legacypool/legacypool_test.go deleted file mode 100644 index 95f64f096..000000000 --- a/builder/core/txpool/legacypool/legacypool_test.go +++ /dev/null @@ -1,2788 +0,0 @@ -// 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 legacypool - -import ( - "context" - "crypto/ecdsa" - crand "crypto/rand" - "errors" - "fmt" - "math/big" - "math/rand" - "os" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/test_utils" - "github.com/ethereum/go-ethereum/trie" - "github.com/google/uuid" - "github.com/holiman/uint256" - "github.com/stretchr/testify/require" -) - -var ( - // testTxPoolConfig is a transaction pool configuration without stateful disk - // sideeffects used during testing. - testTxPoolConfig Config - - // eip1559Config is a chain config with EIP-1559 enabled at block 0. - eip1559Config *params.ChainConfig -) - -func init() { - testTxPoolConfig = DefaultConfig - testTxPoolConfig.Journal = "" - - cpy := *params.TestChainConfig - eip1559Config = &cpy - eip1559Config.BerlinBlock = common.Big0 - eip1559Config.LondonBlock = common.Big0 -} - -type testBlockChain struct { - config *params.ChainConfig - gasLimit atomic.Uint64 - statedb *state.StateDB - chainHeadFeed *event.Feed -} - -func newTestBlockChain(config *params.ChainConfig, gasLimit uint64, statedb *state.StateDB, chainHeadFeed *event.Feed) *testBlockChain { - bc := testBlockChain{config: config, statedb: statedb, chainHeadFeed: new(event.Feed)} - bc.gasLimit.Store(gasLimit) - return &bc -} - -func (bc *testBlockChain) Config() *params.ChainConfig { - return bc.config -} - -func (bc *testBlockChain) CurrentBlock() *types.Header { - return &types.Header{ - Number: new(big.Int), - GasLimit: bc.gasLimit.Load(), - } -} - -func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { - return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) -} - -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { - return bc.statedb, nil -} - -func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - return bc.chainHeadFeed.Subscribe(ch) -} - -func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction { - return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) -} - -func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) - return tx -} - -func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { - data := make([]byte, bytes) - crand.Read(data) - - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) - return tx -} - -func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int, key *ecdsa.PrivateKey) *types.Transaction { - tx, _ := types.SignNewTx(key, types.LatestSignerForChainID(params.TestChainConfig.ChainID), &types.DynamicFeeTx{ - ChainID: params.TestChainConfig.ChainID, - Nonce: nonce, - GasTipCap: tip, - GasFeeCap: gasFee, - Gas: gaslimit, - To: &common.Address{}, - Value: big.NewInt(100), - Data: nil, - AccessList: nil, - }) - return tx -} - -func makeAddressReserver() txpool.AddressReserver { - var ( - reserved = make(map[common.Address]struct{}) - lock sync.Mutex - ) - return func(addr common.Address, reserve bool) error { - lock.Lock() - defer lock.Unlock() - - _, exists := reserved[addr] - if reserve { - if exists { - panic("already reserved") - } - reserved[addr] = struct{}{} - return nil - } - if !exists { - panic("not reserved") - } - delete(reserved, addr) - return nil - } -} - -func setupPool() (*LegacyPool, *ecdsa.PrivateKey) { - return setupPoolWithConfig(params.TestChainConfig) -} - -func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) - - key, _ := crypto.GenerateKey() - pool := New(testTxPoolConfig, blockchain) - if err := pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()); err != nil { - panic(err) - } - // wait for the pool to initialize - <-pool.initDoneCh - return pool, key -} - -// validatePoolInternals checks various consistency invariants within the pool. -func validatePoolInternals(pool *LegacyPool) error { - pool.mu.RLock() - defer pool.mu.RUnlock() - - // Ensure the total transaction set is consistent with pending + queued - pending, queued := pool.stats() - if total := pool.all.Count(); total != pending+queued { - return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) - } - pool.priced.Reheap() - priced, remote := pool.priced.urgent.Len()+pool.priced.floating.Len(), pool.all.RemoteCount() - if priced != remote { - return fmt.Errorf("total priced transaction count %d != %d", priced, remote) - } - // Ensure the next nonce to assign is the correct one - for addr, txs := range pool.pending { - // Find the last transaction - var last uint64 - for nonce := range txs.txs.items { - if last < nonce { - last = nonce - } - } - if nonce := pool.pendingNonces.get(addr); nonce != last+1 { - return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) - } - } - return nil -} - -// validateEvents checks that the correct number of transaction addition events -// were fired on the pool's event feed. -func validateEvents(events chan core.NewTxsEvent, count int) error { - var received []*types.Transaction - - for len(received) < count { - select { - case ev := <-events: - received = append(received, ev.Txs...) - case <-time.After(time.Second): - return fmt.Errorf("event #%d not fired", len(received)) - } - } - if len(received) > count { - return fmt.Errorf("more than %d events fired: %v", count, received[count:]) - } - select { - case ev := <-events: - return fmt.Errorf("more than %d events fired: %v", count, ev.Txs) - - case <-time.After(50 * time.Millisecond): - // This branch should be "default", but it's a data race between goroutines, - // reading the event channel and pushing into it, so better wait a bit ensuring - // really nothing gets injected. - } - return nil -} - -func deriveSender(tx *types.Transaction) (common.Address, error) { - return types.Sender(types.HomesteadSigner{}, tx) -} - -type testChain struct { - *testBlockChain - address common.Address - trigger *bool -} - -// testChain.State() is used multiple times to reset the pending state. -// when simulate is true it will create a state that indicates -// that tx0 and tx1 are included in the chain. -func (c *testChain) State() (*state.StateDB, error) { - // delay "state change" by one. The tx pool fetches the - // state multiple times and by delaying it a bit we simulate - // a state change between those fetches. - stdb := c.statedb - if *c.trigger { - c.statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - // simulate that the new head block included tx0 and tx1 - c.statedb.SetNonce(c.address, 2) - c.statedb.SetBalance(c.address, new(uint256.Int).SetUint64(params.Ether)) - *c.trigger = false - } - return stdb, nil -} - -// This test simulates a scenario where a new block is imported during a -// state reset and tests whether the pending state is in sync with the -// block head event that initiated the resetState(). -func TestStateChangeDuringReset(t *testing.T) { - t.Parallel() - - var ( - key, _ = crypto.GenerateKey() - address = crypto.PubkeyToAddress(key.PublicKey) - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - trigger = false - ) - - // setup pool with 2 transaction in it - statedb.SetBalance(address, new(uint256.Int).SetUint64(params.Ether)) - blockchain := &testChain{newTestBlockChain(params.TestChainConfig, 1000000000, statedb, new(event.Feed)), address, &trigger} - - tx0 := transaction(0, 100000, key) - tx1 := transaction(1, 100000, key) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - nonce := pool.Nonce(address) - if nonce != 0 { - t.Fatalf("Invalid nonce, want 0, got %d", nonce) - } - - pool.addRemotesSync([]*types.Transaction{tx0, tx1}) - - nonce = pool.Nonce(address) - if nonce != 2 { - t.Fatalf("Invalid nonce, want 2, got %d", nonce) - } - - // trigger state change in the background - trigger = true - <-pool.requestReset(nil, nil) - - nonce = pool.Nonce(address) - if nonce != 2 { - t.Fatalf("Invalid nonce, want 2, got %d", nonce) - } -} - -func testAddBalance(pool *LegacyPool, addr common.Address, amount *big.Int) { - pool.mu.Lock() - pool.currentState.AddBalance(addr, uint256.MustFromBig(amount)) - pool.mu.Unlock() -} - -func testSetNonce(pool *LegacyPool, addr common.Address, nonce uint64) { - pool.mu.Lock() - pool.currentState.SetNonce(addr, nonce) - pool.mu.Unlock() -} - -func TestInvalidTransactions(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - tx := transaction(0, 100, key) - from, _ := deriveSender(tx) - - // Intrinsic gas too low - testAddBalance(pool, from, big.NewInt(1)) - if err, want := pool.addRemote(tx), core.ErrIntrinsicGas; !errors.Is(err, want) { - t.Errorf("want %v have %v", want, err) - } - - // Insufficient funds - tx = transaction(0, 100000, key) - if err, want := pool.addRemote(tx), core.ErrInsufficientFunds; !errors.Is(err, want) { - t.Errorf("want %v have %v", want, err) - } - - testSetNonce(pool, from, 1) - testAddBalance(pool, from, big.NewInt(0xffffffffffffff)) - tx = transaction(0, 100000, key) - if err, want := pool.addRemote(tx), core.ErrNonceTooLow; !errors.Is(err, want) { - t.Errorf("want %v have %v", want, err) - } - - tx = transaction(1, 100000, key) - pool.gasTip.Store(uint256.NewInt(1000)) - if err, want := pool.addRemote(tx), txpool.ErrUnderpriced; !errors.Is(err, want) { - t.Errorf("want %v have %v", want, err) - } - if err := pool.addLocal(tx); err != nil { - t.Error("expected", nil, "got", err) - } -} - -func TestQueue(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - tx := transaction(0, 100, key) - from, _ := deriveSender(tx) - testAddBalance(pool, from, big.NewInt(1000)) - <-pool.requestReset(nil, nil) - - pool.enqueueTx(tx.Hash(), tx, false, true) - <-pool.requestPromoteExecutables(newAccountSet(pool.signer, from)) - if len(pool.pending) != 1 { - t.Error("expected valid txs to be 1 is", len(pool.pending)) - } - - tx = transaction(1, 100, key) - from, _ = deriveSender(tx) - testSetNonce(pool, from, 2) - pool.enqueueTx(tx.Hash(), tx, false, true) - - <-pool.requestPromoteExecutables(newAccountSet(pool.signer, from)) - if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { - t.Error("expected transaction to be in tx pool") - } - if len(pool.queue) > 0 { - t.Error("expected transaction queue to be empty. is", len(pool.queue)) - } -} - -func TestQueue2(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - tx1 := transaction(0, 100, key) - tx2 := transaction(10, 100, key) - tx3 := transaction(11, 100, key) - from, _ := deriveSender(tx1) - testAddBalance(pool, from, big.NewInt(1000)) - pool.reset(nil, nil) - - pool.enqueueTx(tx1.Hash(), tx1, false, true) - pool.enqueueTx(tx2.Hash(), tx2, false, true) - pool.enqueueTx(tx3.Hash(), tx3, false, true) - - pool.promoteExecutables([]common.Address{from}) - if len(pool.pending) != 1 { - t.Error("expected pending length to be 1, got", len(pool.pending)) - } - if pool.queue[from].Len() != 2 { - t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) - } -} - -func TestNegativeValue(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) - from, _ := deriveSender(tx) - testAddBalance(pool, from, big.NewInt(1)) - if err := pool.addRemote(tx); err != txpool.ErrNegativeValue { - t.Error("expected", txpool.ErrNegativeValue, "got", err) - } -} - -func TestTipAboveFeeCap(t *testing.T) { - t.Parallel() - - pool, key := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) - - if err := pool.addRemote(tx); err != core.ErrTipAboveFeeCap { - t.Error("expected", core.ErrTipAboveFeeCap, "got", err) - } -} - -func TestVeryHighValues(t *testing.T) { - t.Parallel() - - pool, key := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - veryBigNumber := big.NewInt(1) - veryBigNumber.Lsh(veryBigNumber, 300) - - tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key) - if err := pool.addRemote(tx); err != core.ErrTipVeryHigh { - t.Error("expected", core.ErrTipVeryHigh, "got", err) - } - - tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key) - if err := pool.addRemote(tx2); err != core.ErrFeeCapVeryHigh { - t.Error("expected", core.ErrFeeCapVeryHigh, "got", err) - } -} - -func TestChainFork(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - addr := crypto.PubkeyToAddress(key.PublicKey) - resetState := func() { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.AddBalance(addr, uint256.NewInt(100000000000000)) - - pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) - <-pool.requestReset(nil, nil) - } - resetState() - - tx := transaction(0, 100000, key) - if _, err := pool.add(tx, false); err != nil { - t.Error("didn't expect error", err) - } - pool.removeTx(tx.Hash(), true, true) - - // reset the pool's internal state - resetState() - if _, err := pool.add(tx, false); err != nil { - t.Error("didn't expect error", err) - } -} - -func TestDoubleNonce(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - addr := crypto.PubkeyToAddress(key.PublicKey) - resetState := func() { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.AddBalance(addr, uint256.NewInt(100000000000000)) - - pool.chain = newTestBlockChain(pool.chainconfig, 1000000, statedb, new(event.Feed)) - <-pool.requestReset(nil, nil) - } - resetState() - - signer := types.HomesteadSigner{} - tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key) - tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key) - tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) - - // Add the first two transaction, ensure higher priced stays only - if replace, err := pool.add(tx1, false); err != nil || replace { - t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) - } - if replace, err := pool.add(tx2, false); err != nil || !replace { - t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) - } - <-pool.requestPromoteExecutables(newAccountSet(signer, addr)) - if pool.pending[addr].Len() != 1 { - t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) - } - if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { - t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) - } - - // Add the third transaction and ensure it's not saved (smaller price) - pool.add(tx3, false) - <-pool.requestPromoteExecutables(newAccountSet(signer, addr)) - if pool.pending[addr].Len() != 1 { - t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) - } - if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { - t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) - } - // Ensure the total transaction count is correct - if pool.all.Count() != 1 { - t.Error("expected 1 total transactions, got", pool.all.Count()) - } -} - -func TestMissingNonce(t *testing.T) { - t.Parallel() - - pool, key := setupPool() - defer pool.Close() - - addr := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, addr, big.NewInt(100000000000000)) - tx := transaction(1, 100000, key) - if _, err := pool.add(tx, false); err != nil { - t.Error("didn't expect error", err) - } - if len(pool.pending) != 0 { - t.Error("expected 0 pending transactions, got", len(pool.pending)) - } - if pool.queue[addr].Len() != 1 { - t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) - } - if pool.all.Count() != 1 { - t.Error("expected 1 total transactions, got", pool.all.Count()) - } -} - -func TestNonceRecovery(t *testing.T) { - t.Parallel() - - const n = 10 - pool, key := setupPool() - defer pool.Close() - - addr := crypto.PubkeyToAddress(key.PublicKey) - testSetNonce(pool, addr, n) - testAddBalance(pool, addr, big.NewInt(100000000000000)) - <-pool.requestReset(nil, nil) - - tx := transaction(n, 100000, key) - if err := pool.addRemote(tx); err != nil { - t.Error(err) - } - // simulate some weird re-order of transactions and missing nonce(s) - testSetNonce(pool, addr, n-1) - <-pool.requestReset(nil, nil) - if fn := pool.Nonce(addr); fn != n-1 { - t.Errorf("expected nonce to be %d, got %d", n-1, fn) - } -} - -// Tests that if an account runs out of funds, any pending and queued transactions -// are dropped. -func TestDropping(t *testing.T) { - t.Parallel() - - // Create a test account and fund it - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000)) - - // Add some pending and some queued transactions - var ( - tx0 = transaction(0, 100, key) - tx1 = transaction(1, 200, key) - tx2 = transaction(2, 300, key) - tx10 = transaction(10, 100, key) - tx11 = transaction(11, 200, key) - tx12 = transaction(12, 300, key) - ) - pool.all.Add(tx0, false) - pool.priced.Put(tx0, false) - pool.promoteTx(account, tx0.Hash(), tx0) - - pool.all.Add(tx1, false) - pool.priced.Put(tx1, false) - pool.promoteTx(account, tx1.Hash(), tx1) - - pool.all.Add(tx2, false) - pool.priced.Put(tx2, false) - pool.promoteTx(account, tx2.Hash(), tx2) - - pool.enqueueTx(tx10.Hash(), tx10, false, true) - pool.enqueueTx(tx11.Hash(), tx11, false, true) - pool.enqueueTx(tx12.Hash(), tx12, false, true) - - // Check that pre and post validations leave the pool as is - if pool.pending[account].Len() != 3 { - t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) - } - if pool.queue[account].Len() != 3 { - t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) - } - if pool.all.Count() != 6 { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) - } - <-pool.requestReset(nil, nil) - if pool.pending[account].Len() != 3 { - t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) - } - if pool.queue[account].Len() != 3 { - t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) - } - if pool.all.Count() != 6 { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) - } - // Reduce the balance of the account, and check that invalidated transactions are dropped - testAddBalance(pool, account, big.NewInt(-650)) - <-pool.requestReset(nil, nil) - - if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { - t.Errorf("funded pending transaction missing: %v", tx0) - } - if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { - t.Errorf("funded pending transaction missing: %v", tx0) - } - if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { - t.Errorf("out-of-fund pending transaction present: %v", tx1) - } - if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { - t.Errorf("funded queued transaction missing: %v", tx10) - } - if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { - t.Errorf("funded queued transaction missing: %v", tx10) - } - if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { - t.Errorf("out-of-fund queued transaction present: %v", tx11) - } - if pool.all.Count() != 4 { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 4) - } - // Reduce the block gas limit, check that invalidated transactions are dropped - pool.chain.(*testBlockChain).gasLimit.Store(100) - <-pool.requestReset(nil, nil) - - if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { - t.Errorf("funded pending transaction missing: %v", tx0) - } - if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { - t.Errorf("over-gased pending transaction present: %v", tx1) - } - if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { - t.Errorf("funded queued transaction missing: %v", tx10) - } - if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { - t.Errorf("over-gased queued transaction present: %v", tx11) - } - if pool.all.Count() != 2 { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 2) - } -} - -// Tests that if a transaction is dropped from the current pending pool (e.g. out -// of fund), all consecutive (still valid, but not executable) transactions are -// postponed back into the future queue to prevent broadcasting them. -func TestPostponing(t *testing.T) { - t.Parallel() - - // Create the pool to test the postponing with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create two test accounts to produce different gap profiles with - keys := make([]*ecdsa.PrivateKey, 2) - accs := make([]common.Address, len(keys)) - - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey) - - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100)) - } - // Add a batch consecutive pending transactions for validation - txs := []*types.Transaction{} - for i, key := range keys { - for j := 0; j < 100; j++ { - var tx *types.Transaction - if (i+j)%2 == 0 { - tx = transaction(uint64(j), 25000, key) - } else { - tx = transaction(uint64(j), 50000, key) - } - txs = append(txs, tx) - } - } - for i, err := range pool.addRemotesSync(txs) { - if err != nil { - t.Fatalf("tx %d: failed to add transactions: %v", i, err) - } - } - // Check that pre and post validations leave the pool as is - if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { - t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) - } - if len(pool.queue) != 0 { - t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) - } - if pool.all.Count() != len(txs) { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) - } - <-pool.requestReset(nil, nil) - if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { - t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) - } - if len(pool.queue) != 0 { - t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) - } - if pool.all.Count() != len(txs) { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) - } - // Reduce the balance of the account, and check that transactions are reorganised - for _, addr := range accs { - testAddBalance(pool, addr, big.NewInt(-1)) - } - <-pool.requestReset(nil, nil) - - // The first account's first transaction remains valid, check that subsequent - // ones are either filtered out, or queued up for later. - if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok { - t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0]) - } - if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok { - t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0]) - } - for i, tx := range txs[1:100] { - if i%2 == 1 { - if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { - t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) - } - if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok { - t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) - } - } else { - if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { - t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) - } - if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok { - t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) - } - } - } - // The second account's first transaction got invalid, check that all transactions - // are either filtered out, or queued up for later. - if pool.pending[accs[1]] != nil { - t.Errorf("invalidated account still has pending transactions") - } - for i, tx := range txs[100:] { - if i%2 == 1 { - if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok { - t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx) - } - } else { - if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok { - t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx) - } - } - } - if pool.all.Count() != len(txs)/2 { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)/2) - } -} - -// Tests that if the transaction pool has both executable and non-executable -// transactions from an origin account, filling the nonce gap moves all queued -// ones into the pending pool. -func TestGapFilling(t *testing.T) { - t.Parallel() - - // Create a test account and fund it - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a pending and a queued transaction with a nonce-gap in between - pool.addRemotesSync([]*types.Transaction{ - transaction(0, 100000, key), - transaction(2, 100000, key), - }) - pending, queued := pool.Stats() - if pending != 1 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) - } - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - if err := validateEvents(events, 1); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Fill the nonce gap and ensure all transactions become pending - if err := pool.addRemoteSync(transaction(1, 100000, key)); err != nil { - t.Fatalf("failed to add gapped transaction: %v", err) - } - pending, queued = pool.Stats() - if pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("gap-filling event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that if the transaction count belonging to a single account goes above -// some threshold, the higher transactions are dropped to prevent DOS attacks. -func TestQueueAccountLimiting(t *testing.T) { - t.Parallel() - - // Create a test account and fund it - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) - - // Keep queuing up transactions and make sure all above a limit are dropped - for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { - if err := pool.addRemoteSync(transaction(i, 100000, key)); err != nil { - t.Fatalf("tx %d: failed to add transaction: %v", i, err) - } - if len(pool.pending) != 0 { - t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) - } - if i <= testTxPoolConfig.AccountQueue { - if pool.queue[account].Len() != int(i) { - t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) - } - } else { - if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) { - t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue) - } - } - } - if pool.all.Count() != int(testTxPoolConfig.AccountQueue) { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue) - } -} - -// Tests that if the transaction count belonging to multiple accounts go above -// some threshold, the higher transactions are dropped to prevent DOS attacks. -// -// This logic should not hold for local transactions, unless the local tracking -// mechanism is disabled. -func TestQueueGlobalLimiting(t *testing.T) { - testQueueGlobalLimiting(t, false) -} -func TestQueueGlobalLimitingNoLocals(t *testing.T) { - testQueueGlobalLimiting(t, true) -} - -func testQueueGlobalLimiting(t *testing.T, nolocals bool) { - t.Parallel() - - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.NoLocals = nolocals - config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) - - pool := New(config, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts and fund them (last one will be the local) - keys := make([]*ecdsa.PrivateKey, 5) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - local := keys[len(keys)-1] - - // Generate and queue a batch of transactions - nonces := make(map[common.Address]uint64) - - txs := make(types.Transactions, 0, 3*config.GlobalQueue) - for len(txs) < cap(txs) { - key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account - addr := crypto.PubkeyToAddress(key.PublicKey) - - txs = append(txs, transaction(nonces[addr]+1, 100000, key)) - nonces[addr]++ - } - // Import the batch and verify that limits have been enforced - pool.addRemotesSync(txs) - - queued := 0 - for addr, list := range pool.queue { - if list.Len() > int(config.AccountQueue) { - t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) - } - queued += list.Len() - } - if queued > int(config.GlobalQueue) { - t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) - } - // Generate a batch of transactions from the local account and import them - txs = txs[:0] - for i := uint64(0); i < 3*config.GlobalQueue; i++ { - txs = append(txs, transaction(i+1, 100000, local)) - } - pool.addLocals(txs) - - // If locals are disabled, the previous eviction algorithm should apply here too - if nolocals { - queued := 0 - for addr, list := range pool.queue { - if list.Len() > int(config.AccountQueue) { - t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) - } - queued += list.Len() - } - if queued > int(config.GlobalQueue) { - t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) - } - } else { - // Local exemptions are enabled, make sure the local account owned the queue - if len(pool.queue) != 1 { - t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) - } - // Also ensure no local transactions are ever dropped, even if above global limits - if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { - t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) - } - } -} - -// Tests that if an account remains idle for a prolonged amount of time, any -// non-executable transactions queued up are dropped to prevent wasting resources -// on shuffling them around. -// -// This logic should not hold for local transactions, unless the local tracking -// mechanism is disabled. -func TestQueueTimeLimiting(t *testing.T) { - testQueueTimeLimiting(t, false) -} -func TestQueueTimeLimitingNoLocals(t *testing.T) { - testQueueTimeLimiting(t, true) -} - -func testQueueTimeLimiting(t *testing.T, nolocals bool) { - // Reduce the eviction interval to a testable amount - defer func(old time.Duration) { evictionInterval = old }(evictionInterval) - evictionInterval = time.Millisecond * 100 - - // Create the pool to test the non-expiration enforcement - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.Lifetime = time.Second - config.NoLocals = nolocals - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create two test accounts to ensure remotes expire but locals do not - local, _ := crypto.GenerateKey() - remote, _ := crypto.GenerateKey() - - testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) - testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) - - // Add the two transactions and ensure they both are queued up - if err := pool.addLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add local transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - pending, queued := pool.Stats() - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // Allow the eviction interval to run - time.Sleep(2 * evictionInterval) - - // Transactions should not be evicted from the queue yet since lifetime duration has not passed - pending, queued = pool.Stats() - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains - time.Sleep(2 * config.Lifetime) - - pending, queued = pool.Stats() - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - if nolocals { - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - } else { - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // remove current transactions and increase nonce to prepare for a reset and cleanup - statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2) - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) - <-pool.requestReset(nil, nil) - - // make sure queue, pending are cleared - pending, queued = pool.Stats() - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // Queue gapped transactions - if err := pool.addLocal(pricedTransaction(4, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - if err := pool.addRemoteSync(pricedTransaction(4, 100000, big.NewInt(1), remote)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - time.Sleep(5 * evictionInterval) // A half lifetime pass - - // Queue executable transactions, the life cycle should be restarted. - if err := pool.addLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), remote)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - time.Sleep(6 * evictionInterval) - - // All gapped transactions shouldn't be kicked out - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // The whole life time pass after last promotion, kick out stale transactions - time.Sleep(2 * config.Lifetime) - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if nolocals { - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - } else { - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that even if the transaction count belonging to a single account goes -// above some threshold, as long as the transactions are executable, they are -// accepted. -func TestPendingLimiting(t *testing.T) { - t.Parallel() - - // Create a test account and fund it - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000000000)) - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Keep queuing up transactions and make sure all above a limit are dropped - for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { - if err := pool.addRemoteSync(transaction(i, 100000, key)); err != nil { - t.Fatalf("tx %d: failed to add transaction: %v", i, err) - } - if pool.pending[account].Len() != int(i)+1 { - t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) - } - if len(pool.queue) != 0 { - t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) - } - } - if pool.all.Count() != int(testTxPoolConfig.AccountQueue+5) { - t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue+5) - } - if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { - t.Fatalf("event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that if the transaction count belonging to multiple accounts go above -// some hard threshold, the higher transactions are dropped to prevent DOS -// attacks. -func TestPendingGlobalLimiting(t *testing.T) { - t.Parallel() - - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.GlobalSlots = config.AccountSlots * 10 - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 5) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions - nonces := make(map[common.Address]uint64) - - txs := types.Transactions{} - for _, key := range keys { - addr := crypto.PubkeyToAddress(key.PublicKey) - for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { - txs = append(txs, transaction(nonces[addr], 100000, key)) - nonces[addr]++ - } - } - // Import the batch and verify that limits have been enforced - pool.addRemotesSync(txs) - - pending := 0 - for _, list := range pool.pending { - pending += list.Len() - } - if pending > int(config.GlobalSlots) { - t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Test the limit on transaction size is enforced correctly. -// This test verifies every transaction having allowed size -// is added to the pool, and longer transactions are rejected. -func TestAllowedTxSize(t *testing.T) { - t.Parallel() - - // Create a test account and fund it - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000000)) - - // Compute maximal data size for transactions (lower bound). - // - // It is assumed the fields in the transaction (except of the data) are: - // - nonce <= 32 bytes - // - gasTip <= 32 bytes - // - gasLimit <= 32 bytes - // - recipient == 20 bytes - // - value <= 32 bytes - // - signature == 65 bytes - // All those fields are summed up to at most 213 bytes. - baseSize := uint64(213) - dataSize := txMaxSize - baseSize - // Try adding a transaction with maximal allowed size - tx := pricedDataTransaction(0, pool.currentHead.Load().GasLimit, big.NewInt(1), key, dataSize) - if err := pool.addRemoteSync(tx); err != nil { - t.Fatalf("failed to add transaction of size %d, close to maximal: %v", int(tx.Size()), err) - } - // Try adding a transaction with random allowed size - if err := pool.addRemoteSync(pricedDataTransaction(1, pool.currentHead.Load().GasLimit, big.NewInt(1), key, uint64(rand.Intn(int(dataSize))))); err != nil { - t.Fatalf("failed to add transaction of random allowed size: %v", err) - } - // Try adding a transaction of minimal not allowed size - if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, txMaxSize)); err == nil { - t.Fatalf("expected rejection on slightly oversize transaction") - } - // Try adding a transaction of random not allowed size - if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentHead.Load().GasLimit, big.NewInt(1), key, dataSize+1+uint64(rand.Intn(10*txMaxSize)))); err == nil { - t.Fatalf("expected rejection on oversize transaction") - } - // Run some sanity checks on the pool internals - pending, queued := pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that if transactions start being capped, transactions are also removed from 'all' -func TestCapClearsFromAll(t *testing.T) { - t.Parallel() - - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.AccountSlots = 2 - config.AccountQueue = 2 - config.GlobalSlots = 8 - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts and fund them - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, addr, big.NewInt(1000000)) - - txs := types.Transactions{} - for j := 0; j < int(config.GlobalSlots)*2; j++ { - txs = append(txs, transaction(uint64(j), 100000, key)) - } - // Import the batch and verify that limits have been enforced - pool.addRemotes(txs) - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that if the transaction count belonging to multiple accounts go above -// some hard threshold, if they are under the minimum guaranteed slot count then -// the transactions are still kept. -func TestPendingMinimumAllowance(t *testing.T) { - t.Parallel() - - // Create the pool to test the limit enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.GlobalSlots = 1 - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 5) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions - nonces := make(map[common.Address]uint64) - - txs := types.Transactions{} - for _, key := range keys { - addr := crypto.PubkeyToAddress(key.PublicKey) - for j := 0; j < int(config.AccountSlots)*2; j++ { - txs = append(txs, transaction(nonces[addr], 100000, key)) - nonces[addr]++ - } - } - // Import the batch and verify that limits have been enforced - pool.addRemotesSync(txs) - - for addr, list := range pool.pending { - if list.Len() != int(config.AccountSlots) { - t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that setting the transaction pool gas price to a higher value correctly -// discards everything cheaper than that and moves any gapped transactions back -// from the pending pool to the queue. -// -// Note, local transactions are never allowed to be dropped. -func TestRepricing(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 4) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions, both pending and queued - txs := types.Transactions{} - - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) - - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1])) - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1])) - - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2])) - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) - txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2])) - - ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3]) - - // Import the batch and that both pending and queued transactions match up - pool.addRemotesSync(txs) - pool.addLocal(ltx) - - pending, queued := pool.Stats() - if pending != 7 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) - } - if queued != 3 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) - } - if err := validateEvents(events, 7); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Reprice the pool and check that underpriced transactions get dropped - pool.SetGasTip(big.NewInt(2)) - - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 5 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) - } - if err := validateEvents(events, 0); err != nil { - t.Fatalf("reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Check that we can't add the old transactions back - if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - if err := validateEvents(events, 0); err != nil { - t.Fatalf("post-reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // However we can add local underpriced transactions - tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3]) - if err := pool.addLocal(tx); err != nil { - t.Fatalf("failed to add underpriced local transaction: %v", err) - } - if pending, _ = pool.Stats(); pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if err := validateEvents(events, 1); err != nil { - t.Fatalf("post-reprice local event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // And we can fill gaps with properly priced transactions - if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil { - t.Fatalf("failed to add pending transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil { - t.Fatalf("failed to add pending transaction: %v", err) - } - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil { - t.Fatalf("failed to add queued transaction: %v", err) - } - if err := validateEvents(events, 5); err != nil { - t.Fatalf("post-reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -func TestMinGasPriceEnforced(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 10000000, statedb, new(event.Feed)) - - txPoolConfig := DefaultConfig - txPoolConfig.NoLocals = true - pool := New(txPoolConfig, blockchain) - pool.Init(txPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - key, _ := crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000)) - - tx := pricedTransaction(0, 100000, big.NewInt(2), key) - pool.SetGasTip(big.NewInt(tx.GasPrice().Int64() + 1)) - - if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("Min tip not enforced") - } - - if err := pool.Add([]*types.Transaction{tx}, true, false, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("Min tip not enforced") - } - - tx = dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), key) - pool.SetGasTip(big.NewInt(tx.GasTipCap().Int64() + 1)) - - if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("Min tip not enforced") - } - - if err := pool.Add([]*types.Transaction{tx}, true, false, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("Min tip not enforced") - } - // Make sure the tx is accepted if locals are enabled - pool.config.NoLocals = false - if err := pool.Add([]*types.Transaction{tx}, true, false, false)[0]; err != nil { - t.Fatalf("Min tip enforced with locals enabled, error: %v", err) - } -} - -// Tests that setting the transaction pool gas price to a higher value correctly -// discards everything cheaper (legacy & dynamic fee) than that and moves any -// gapped transactions back from the pending pool to the queue. -// -// Note, local transactions are never allowed to be dropped. -func TestRepricingDynamicFee(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - pool, _ := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 4) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions, both pending and queued - txs := types.Transactions{} - - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) - - txs = append(txs, dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[1])) - txs = append(txs, dynamicFeeTx(1, 100000, big.NewInt(3), big.NewInt(2), keys[1])) - txs = append(txs, dynamicFeeTx(2, 100000, big.NewInt(3), big.NewInt(2), keys[1])) - - txs = append(txs, dynamicFeeTx(1, 100000, big.NewInt(2), big.NewInt(2), keys[2])) - txs = append(txs, dynamicFeeTx(2, 100000, big.NewInt(1), big.NewInt(1), keys[2])) - txs = append(txs, dynamicFeeTx(3, 100000, big.NewInt(2), big.NewInt(2), keys[2])) - - ltx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[3]) - - // Import the batch and that both pending and queued transactions match up - pool.addRemotesSync(txs) - pool.addLocal(ltx) - - pending, queued := pool.Stats() - if pending != 7 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) - } - if queued != 3 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) - } - if err := validateEvents(events, 7); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Reprice the pool and check that underpriced transactions get dropped - pool.SetGasTip(big.NewInt(2)) - - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 5 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) - } - if err := validateEvents(events, 0); err != nil { - t.Fatalf("reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Check that we can't add the old transactions back - tx := pricedTransaction(1, 100000, big.NewInt(1), keys[0]) - if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - tx = dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[1]) - if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - tx = dynamicFeeTx(2, 100000, big.NewInt(1), big.NewInt(1), keys[2]) - if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - if err := validateEvents(events, 0); err != nil { - t.Fatalf("post-reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // However we can add local underpriced transactions - tx = dynamicFeeTx(1, 100000, big.NewInt(1), big.NewInt(1), keys[3]) - if err := pool.addLocal(tx); err != nil { - t.Fatalf("failed to add underpriced local transaction: %v", err) - } - if pending, _ = pool.Stats(); pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if err := validateEvents(events, 1); err != nil { - t.Fatalf("post-reprice local event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // And we can fill gaps with properly priced transactions - tx = pricedTransaction(1, 100000, big.NewInt(2), keys[0]) - if err := pool.addRemote(tx); err != nil { - t.Fatalf("failed to add pending transaction: %v", err) - } - tx = dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[1]) - if err := pool.addRemote(tx); err != nil { - t.Fatalf("failed to add pending transaction: %v", err) - } - tx = dynamicFeeTx(2, 100000, big.NewInt(2), big.NewInt(2), keys[2]) - if err := pool.addRemoteSync(tx); err != nil { - t.Fatalf("failed to add queued transaction: %v", err) - } - if err := validateEvents(events, 5); err != nil { - t.Fatalf("post-reprice event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that setting the transaction pool gas price to a higher value does not -// remove local transactions (legacy & dynamic fee). -func TestRepricingKeepsLocals(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 3) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(100000*1000000)) - } - // Create transaction (both pending and queued) with a linearly growing gasprice - for i := uint64(0); i < 500; i++ { - // Add pending transaction. - pendingTx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2]) - if err := pool.addLocal(pendingTx); err != nil { - t.Fatal(err) - } - // Add queued transaction. - queuedTx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2]) - if err := pool.addLocal(queuedTx); err != nil { - t.Fatal(err) - } - - // Add pending dynamic fee transaction. - pendingTx = dynamicFeeTx(i, 100000, big.NewInt(int64(i)+1), big.NewInt(int64(i)), keys[1]) - if err := pool.addLocal(pendingTx); err != nil { - t.Fatal(err) - } - // Add queued dynamic fee transaction. - queuedTx = dynamicFeeTx(i+501, 100000, big.NewInt(int64(i)+1), big.NewInt(int64(i)), keys[1]) - if err := pool.addLocal(queuedTx); err != nil { - t.Fatal(err) - } - } - pending, queued := pool.Stats() - expPending, expQueued := 1000, 1000 - validate := func() { - pending, queued = pool.Stats() - if pending != expPending { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) - } - if queued != expQueued { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) - } - - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - } - validate() - - // Reprice the pool and check that nothing is dropped - pool.SetGasTip(big.NewInt(2)) - validate() - - pool.SetGasTip(big.NewInt(2)) - pool.SetGasTip(big.NewInt(4)) - pool.SetGasTip(big.NewInt(8)) - pool.SetGasTip(big.NewInt(100)) - validate() -} - -// Tests that when the pool reaches its global transaction limit, underpriced -// transactions are gradually shifted out for more expensive ones and any gapped -// pending transactions are moved into the queue. -// -// Note, local transactions are never allowed to be dropped. -func TestUnderpricing(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.GlobalSlots = 2 - config.GlobalQueue = 2 - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 5) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions, both pending and queued - txs := types.Transactions{} - - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) - - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) - - ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) - - // Import the batch and that both pending and queued transactions match up - pool.addRemotes(txs) - pool.addLocal(ltx) - - pending, queued := pool.Stats() - if pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - if err := validateEvents(events, 3); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Ensure that adding an underpriced transaction on block limit fails - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); !errors.Is(err, txpool.ErrUnderpriced) { - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - // Replace a future transaction with a future transaction - if err := pool.addRemoteSync(pricedTransaction(1, 100000, big.NewInt(2), keys[1])); err != nil { // +K1:1 => -K1:1 => Pend K0:0, K0:1, K2:0; Que K1:1 - t.Fatalf("failed to add well priced transaction: %v", err) - } - // Ensure that adding high priced transactions drops cheap ones, but not own - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { // +K1:0 => -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que - - t.Fatalf("failed to add well priced transaction: %v", err) - } - if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil { // +K1:2 => -K0:0 => Pend K1:0, K2:0; Que K0:1 K1:2 - t.Fatalf("failed to add well priced transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil { // +K1:3 => -K0:1 => Pend K1:0, K2:0; Que K1:2 K1:3 - t.Fatalf("failed to add well priced transaction: %v", err) - } - // Ensure that replacing a pending transaction with a future transaction fails - if err := pool.addRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending { - t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending) - } - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("additional event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Ensure that adding local transactions can push out even higher priced ones - ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2]) - if err := pool.addLocal(ltx); err != nil { - t.Fatalf("failed to append underpriced local transaction: %v", err) - } - ltx = pricedTransaction(0, 100000, big.NewInt(0), keys[3]) - if err := pool.addLocal(ltx); err != nil { - t.Fatalf("failed to add new underpriced local transaction: %v", err) - } - pending, queued = pool.Stats() - if pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("local event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that more expensive transactions push out cheap ones from the pool, but -// without producing instability by creating gaps that start jumping transactions -// back and forth between queued/pending. -func TestStableUnderpricing(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.GlobalSlots = 128 - config.GlobalQueue = 0 - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 2) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Fill up the entire queue with the same transaction price points - txs := types.Transactions{} - for i := uint64(0); i < config.GlobalSlots; i++ { - txs = append(txs, pricedTransaction(i, 100000, big.NewInt(1), keys[0])) - } - pool.addRemotesSync(txs) - - pending, queued := pool.Stats() - if pending != int(config.GlobalSlots) { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validateEvents(events, int(config.GlobalSlots)); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { - t.Fatalf("failed to add well priced transaction: %v", err) - } - pending, queued = pool.Stats() - if pending != int(config.GlobalSlots) { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validateEvents(events, 1); err != nil { - t.Fatalf("additional event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that when the pool reaches its global transaction limit, underpriced -// transactions (legacy & dynamic fee) are gradually shifted out for more -// expensive ones and any gapped pending transactions are moved into the queue. -// -// Note, local transactions are never allowed to be dropped. -func TestUnderpricingDynamicFee(t *testing.T) { - t.Parallel() - - pool, _ := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - pool.config.GlobalSlots = 2 - pool.config.GlobalQueue = 2 - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 4) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - - // Generate and queue a batch of transactions, both pending and queued - txs := types.Transactions{} - - txs = append(txs, dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[0])) - txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) - txs = append(txs, dynamicFeeTx(1, 100000, big.NewInt(2), big.NewInt(1), keys[1])) - - ltx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[2]) - - // Import the batch and that both pending and queued transactions match up - pool.addRemotes(txs) // Pend K0:0, K0:1; Que K1:1 - pool.addLocal(ltx) // +K2:0 => Pend K0:0, K0:1, K2:0; Que K1:1 - - pending, queued := pool.Stats() - if pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - if err := validateEvents(events, 3); err != nil { - t.Fatalf("original event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - - // Ensure that adding an underpriced transaction fails - tx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[1]) - if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrUnderpriced) { // Pend K0:0, K0:1, K2:0; Que K1:1 - t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced) - } - - // Ensure that adding high priced transactions drops cheap ones, but not own - tx = pricedTransaction(0, 100000, big.NewInt(2), keys[1]) - if err := pool.addRemote(tx); err != nil { // +K1:0, -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que - - t.Fatalf("failed to add well priced transaction: %v", err) - } - - tx = pricedTransaction(1, 100000, big.NewInt(3), keys[1]) - if err := pool.addRemoteSync(tx); err != nil { // +K1:2, -K0:1 => Pend K0:0 K1:0, K2:0; Que K1:2 - t.Fatalf("failed to add well priced transaction: %v", err) - } - tx = dynamicFeeTx(2, 100000, big.NewInt(4), big.NewInt(1), keys[1]) - if err := pool.addRemoteSync(tx); err != nil { // +K1:3, -K1:0 => Pend K0:0 K2:0; Que K1:2 K1:3 - t.Fatalf("failed to add well priced transaction: %v", err) - } - pending, queued = pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("additional event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Ensure that adding local transactions can push out even higher priced ones - ltx = dynamicFeeTx(1, 100000, big.NewInt(0), big.NewInt(0), keys[2]) - if err := pool.addLocal(ltx); err != nil { - t.Fatalf("failed to append underpriced local transaction: %v", err) - } - ltx = dynamicFeeTx(0, 100000, big.NewInt(0), big.NewInt(0), keys[3]) - if err := pool.addLocal(ltx); err != nil { - t.Fatalf("failed to add new underpriced local transaction: %v", err) - } - pending, queued = pool.Stats() - if pending != 3 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) - } - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("local event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests whether highest fee cap transaction is retained after a batch of high effective -// tip transactions are added and vice versa -func TestDualHeapEviction(t *testing.T) { - t.Parallel() - - pool, _ := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - pool.config.GlobalSlots = 10 - pool.config.GlobalQueue = 10 - - var ( - highTip, highCap *types.Transaction - baseFee int - ) - - check := func(tx *types.Transaction, name string) { - if pool.all.GetRemote(tx.Hash()) == nil { - t.Fatalf("highest %s transaction evicted from the pool", name) - } - } - - add := func(urgent bool) { - for i := 0; i < 20; i++ { - var tx *types.Transaction - // Create a test accounts and fund it - key, _ := crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000000)) - if urgent { - tx = dynamicFeeTx(0, 100000, big.NewInt(int64(baseFee+1+i)), big.NewInt(int64(1+i)), key) - highTip = tx - } else { - tx = dynamicFeeTx(0, 100000, big.NewInt(int64(baseFee+200+i)), big.NewInt(1), key) - highCap = tx - } - pool.addRemotesSync([]*types.Transaction{tx}) - } - pending, queued := pool.Stats() - if pending+queued != 20 { - t.Fatalf("transaction count mismatch: have %d, want %d", pending+queued, 10) - } - } - - add(false) - for baseFee = 0; baseFee <= 1000; baseFee += 100 { - pool.priced.SetBaseFee(big.NewInt(int64(baseFee))) - add(true) - check(highCap, "fee cap") - add(false) - check(highTip, "effective tip") - } - - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that the pool rejects duplicate transactions. -func TestDeduplication(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create a test account to add transactions with - key, _ := crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) - - // Create a batch of transactions and add a few of them - txs := make([]*types.Transaction, 16) - for i := 0; i < len(txs); i++ { - txs[i] = pricedTransaction(uint64(i), 100000, big.NewInt(1), key) - } - var firsts []*types.Transaction - for i := 0; i < len(txs); i += 2 { - firsts = append(firsts, txs[i]) - } - errs := pool.addRemotesSync(firsts) - if len(errs) != len(firsts) { - t.Fatalf("first add mismatching result count: have %d, want %d", len(errs), len(firsts)) - } - for i, err := range errs { - if err != nil { - t.Errorf("add %d failed: %v", i, err) - } - } - pending, queued := pool.Stats() - if pending != 1 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) - } - if queued != len(txs)/2-1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, len(txs)/2-1) - } - // Try to add all of them now and ensure previous ones error out as knowns - errs = pool.addRemotesSync(txs) - if len(errs) != len(txs) { - t.Fatalf("all add mismatching result count: have %d, want %d", len(errs), len(txs)) - } - for i, err := range errs { - if i%2 == 0 && err == nil { - t.Errorf("add %d succeeded, should have failed as known", i) - } - if i%2 == 1 && err != nil { - t.Errorf("add %d failed: %v", i, err) - } - } - pending, queued = pool.Stats() - if pending != len(txs) { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, len(txs)) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that the pool rejects replacement transactions that don't meet the minimum -// price bump required. -func TestReplacement(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Create a test account to add transactions with - key, _ := crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) - - // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) - price := int64(100) - threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 - - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { - t.Fatalf("failed to add original cheap pending transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) - } - if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { - t.Fatalf("failed to replace original cheap pending transaction: %v", err) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("cheap replacement event firing failed: %v", err) - } - - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { - t.Fatalf("failed to add original proper pending transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) - } - if err := pool.addRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { - t.Fatalf("failed to replace original proper pending transaction: %v", err) - } - if err := validateEvents(events, 2); err != nil { - t.Fatalf("proper replacement event firing failed: %v", err) - } - - // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) - if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { - t.Fatalf("failed to add original cheap queued transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) - } - if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { - t.Fatalf("failed to replace original cheap queued transaction: %v", err) - } - - if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { - t.Fatalf("failed to add original proper queued transaction: %v", err) - } - if err := pool.addRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, txpool.ErrReplaceUnderpriced) - } - if err := pool.addRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { - t.Fatalf("failed to replace original proper queued transaction: %v", err) - } - - if err := validateEvents(events, 0); err != nil { - t.Fatalf("queued replacement event firing failed: %v", err) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that the pool rejects replacement dynamic fee transactions that don't -// meet the minimum price bump required. -func TestReplacementDynamicFee(t *testing.T) { - t.Parallel() - - // Create the pool to test the pricing enforcement with - pool, key := setupPoolWithConfig(eip1559Config) - defer pool.Close() - testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) - - // Keep track of transaction events to ensure all executables get announced - events := make(chan core.NewTxsEvent, 32) - sub := pool.txFeed.Subscribe(events) - defer sub.Unsubscribe() - - // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) - gasFeeCap := int64(100) - feeCapThreshold := (gasFeeCap * (100 + int64(testTxPoolConfig.PriceBump))) / 100 - gasTipCap := int64(60) - tipThreshold := (gasTipCap * (100 + int64(testTxPoolConfig.PriceBump))) / 100 - - // Run the following identical checks for both the pending and queue pools: - // 1. Send initial tx => accept - // 2. Don't bump tip or fee cap => discard - // 3. Bump both more than min => accept - // 4. Check events match expected (2 new executable txs during pending, 0 during queue) - // 5. Send new tx with larger tip and gasFeeCap => accept - // 6. Bump tip max allowed so it's still underpriced => discard - // 7. Bump fee cap max allowed so it's still underpriced => discard - // 8. Bump tip min for acceptance => discard - // 9. Bump feecap min for acceptance => discard - // 10. Bump feecap and tip min for acceptance => accept - // 11. Check events match expected (2 new executable txs during pending, 0 during queue) - stages := []string{"pending", "queued"} - for _, stage := range stages { - // Since state is empty, 0 nonce txs are "executable" and can go - // into pending immediately. 2 nonce txs are "gapped" - nonce := uint64(0) - if stage == "queued" { - nonce = 2 - } - - // 1. Send initial tx => accept - tx := dynamicFeeTx(nonce, 100000, big.NewInt(2), big.NewInt(1), key) - if err := pool.addRemoteSync(tx); err != nil { - t.Fatalf("failed to add original cheap %s transaction: %v", stage, err) - } - // 2. Don't bump tip or feecap => discard - tx = dynamicFeeTx(nonce, 100001, big.NewInt(2), big.NewInt(1), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original cheap %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) - } - // 3. Bump both more than min => accept - tx = dynamicFeeTx(nonce, 100000, big.NewInt(3), big.NewInt(2), key) - if err := pool.addRemote(tx); err != nil { - t.Fatalf("failed to replace original cheap %s transaction: %v", stage, err) - } - // 4. Check events match expected (2 new executable txs during pending, 0 during queue) - count := 2 - if stage == "queued" { - count = 0 - } - if err := validateEvents(events, count); err != nil { - t.Fatalf("cheap %s replacement event firing failed: %v", stage, err) - } - // 5. Send new tx with larger tip and feeCap => accept - tx = dynamicFeeTx(nonce, 100000, big.NewInt(gasFeeCap), big.NewInt(gasTipCap), key) - if err := pool.addRemoteSync(tx); err != nil { - t.Fatalf("failed to add original proper %s transaction: %v", stage, err) - } - // 6. Bump tip max allowed so it's still underpriced => discard - tx = dynamicFeeTx(nonce, 100000, big.NewInt(gasFeeCap), big.NewInt(tipThreshold-1), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) - } - // 7. Bump fee cap max allowed so it's still underpriced => discard - tx = dynamicFeeTx(nonce, 100000, big.NewInt(feeCapThreshold-1), big.NewInt(gasTipCap), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) - } - // 8. Bump tip min for acceptance => accept - tx = dynamicFeeTx(nonce, 100000, big.NewInt(gasFeeCap), big.NewInt(tipThreshold), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) - } - // 9. Bump fee cap min for acceptance => accept - tx = dynamicFeeTx(nonce, 100000, big.NewInt(feeCapThreshold), big.NewInt(gasTipCap), key) - if err := pool.addRemote(tx); err != txpool.ErrReplaceUnderpriced { - t.Fatalf("original proper %s transaction replacement error mismatch: have %v, want %v", stage, err, txpool.ErrReplaceUnderpriced) - } - // 10. Check events match expected (3 new executable txs during pending, 0 during queue) - tx = dynamicFeeTx(nonce, 100000, big.NewInt(feeCapThreshold), big.NewInt(tipThreshold), key) - if err := pool.addRemote(tx); err != nil { - t.Fatalf("failed to replace original cheap %s transaction: %v", stage, err) - } - // 11. Check events match expected (3 new executable txs during pending, 0 during queue) - count = 2 - if stage == "queued" { - count = 0 - } - if err := validateEvents(events, count); err != nil { - t.Fatalf("replacement %s event firing failed: %v", stage, err) - } - } - - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } -} - -// Tests that local transactions are journaled to disk, but remote transactions -// get discarded between restarts. -func TestJournaling(t *testing.T) { testJournaling(t, false) } -func TestJournalingNoLocals(t *testing.T) { testJournaling(t, true) } - -func testJournaling(t *testing.T, nolocals bool) { - t.Parallel() - - // Create a temporary file for the journal - file, err := os.CreateTemp("", "") - if err != nil { - t.Fatalf("failed to create temporary journal: %v", err) - } - journal := file.Name() - defer os.Remove(journal) - - // Clean up the temporary file, we only need the path for now - file.Close() - os.Remove(journal) - - // Create the original pool to inject transaction into the journal - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - config := testTxPoolConfig - config.NoLocals = nolocals - config.Journal = journal - config.Rejournal = time.Second - - pool := New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - - // Create two test accounts to ensure remotes expire but locals do not - local, _ := crypto.GenerateKey() - remote, _ := crypto.GenerateKey() - - testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) - testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) - - // Add three local and a remote transactions and ensure they are queued up - if err := pool.addLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add local transaction: %v", err) - } - if err := pool.addLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add local transaction: %v", err) - } - if err := pool.addLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { - t.Fatalf("failed to add local transaction: %v", err) - } - if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil { - t.Fatalf("failed to add remote transaction: %v", err) - } - pending, queued := pool.Stats() - if pending != 4 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) - } - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive - pool.Close() - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) - blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool = New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - - pending, queued = pool.Stats() - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - if nolocals { - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - } else { - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Bump the nonce temporarily and ensure the newly invalidated transaction is removed - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) - <-pool.requestReset(nil, nil) - time.Sleep(2 * config.Rejournal) - pool.Close() - - statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) - blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - pool = New(config, blockchain) - pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - - pending, queued = pool.Stats() - if pending != 0 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) - } - if nolocals { - if queued != 0 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) - } - } else { - if queued != 1 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) - } - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - pool.Close() -} - -// TestStatusCheck tests that the pool can correctly retrieve the -// pending status of individual transactions. -func TestStatusCheck(t *testing.T) { - t.Parallel() - - // Create the pool to test the status retrievals with - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()) - defer pool.Close() - - // Create the test accounts to check various transaction statuses with - keys := make([]*ecdsa.PrivateKey, 3) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - // Generate and queue a batch of transactions, both pending and queued - txs := types.Transactions{} - - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only - txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) - txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only - - // Import the transaction and ensure they are correctly added - pool.addRemotesSync(txs) - - pending, queued := pool.Stats() - if pending != 2 { - t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) - } - if queued != 2 { - t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) - } - if err := validatePoolInternals(pool); err != nil { - t.Fatalf("pool internal state corrupted: %v", err) - } - // Retrieve the status of each transaction and validate them - hashes := make([]common.Hash, len(txs)) - for i, tx := range txs { - hashes[i] = tx.Hash() - } - hashes = append(hashes, common.Hash{}) - expect := []txpool.TxStatus{txpool.TxStatusPending, txpool.TxStatusPending, txpool.TxStatusQueued, txpool.TxStatusQueued, txpool.TxStatusUnknown} - - for i := 0; i < len(hashes); i++ { - if status := pool.Status(hashes[i]); status != expect[i] { - t.Errorf("transaction %d: status mismatch: have %v, want %v", i, status, expect[i]) - } - } -} - -// Test the transaction slots consumption is computed correctly -func TestSlotCount(t *testing.T) { - t.Parallel() - - key, _ := crypto.GenerateKey() - - // Check that an empty transaction consumes a single slot - smallTx := pricedDataTransaction(0, 0, big.NewInt(0), key, 0) - if slots := numSlots(smallTx); slots != 1 { - t.Fatalf("small transactions slot count mismatch: have %d want %d", slots, 1) - } - // Check that a large transaction consumes the correct number of slots - bigTx := pricedDataTransaction(0, 0, big.NewInt(0), key, uint64(10*txSlotSize)) - if slots := numSlots(bigTx); slots != 11 { - t.Fatalf("big transactions slot count mismatch: have %d want %d", slots, 11) - } -} - -// TODO: test bundle cancellations -func TestBundleCancellations(t *testing.T) { - // Create the pool to test the status retrievals with - statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := newTestBlockChain(params.TestChainConfig, 100, statedb, new(event.Feed)) - - pool := New(testTxPoolConfig, blockchain) - txpool, err := txpool.New(testTxPoolConfig.PriceLimit, blockchain, []txpool.SubPool{pool}) - fetcher := &mockFetcher{make(map[int64]error), make(map[int64][]types.LatestUuidBundle)} - txpool.RegisterBundleFetcher(fetcher) - - fetcher.resps[1] = nil - bundles, ccBundles := txpool.MevBundles(big.NewInt(1), 20) - require.Equal(t, []types.MevBundle(nil), bundles) - require.Equal(t, []types.MevBundle(nil), <-ccBundles) - - bundle01_uuid1_signer1 := types.MevBundle{ - BlockNumber: big.NewInt(1), - Uuid: uuid.New(), - SigningAddress: common.Address{0x01}, - Hash: common.Hash{0xf0}, - } - bundle02_no_uuid_signer2 := types.MevBundle{ - BlockNumber: big.NewInt(1), - Uuid: types.EmptyUUID, - SigningAddress: common.Address{0x02}, - Hash: common.Hash{0xf1}, - } - bundle03_uuid1_signer1 := types.MevBundle{ - BlockNumber: big.NewInt(1), - Uuid: bundle01_uuid1_signer1.Uuid, - SigningAddress: common.Address{0x01}, - Hash: common.Hash{0xf3}, - } - bundle03_uuid1_signer2 := types.MevBundle{ - BlockNumber: big.NewInt(1), - Uuid: bundle01_uuid1_signer1.Uuid, - SigningAddress: common.Address{0x02}, - Hash: common.Hash{0xf3}, - } - - txpool.AddMevBundles([]types.MevBundle{ - bundle01_uuid1_signer1, bundle02_no_uuid_signer2, bundle03_uuid1_signer1, bundle03_uuid1_signer2, - }) - require.NoError(t, err) - - // Ignores uuid bundle since fetcher does not return it, passes non-uuid bundle - bundles, ccBundles = txpool.MevBundles(big.NewInt(1), 20) - require.Equal(t, []types.MevBundle{bundle02_no_uuid_signer2}, bundles) - cr := test_utils.RequireChan(ccBundles, time.Millisecond) - require.False(t, cr.Timeout) - require.Equal(t, []types.MevBundle{}, cr.Value) - - fetcher.resps[1] = append(fetcher.resps[1], types.LatestUuidBundle{ - Uuid: bundle01_uuid1_signer1.Uuid, - SigningAddress: bundle01_uuid1_signer1.SigningAddress, - BundleHash: bundle01_uuid1_signer1.Hash, - }) - - // Passes non-uuid bundle and only the bundle exactly matching the fetcher resp - bundles, ccBundles = txpool.MevBundles(big.NewInt(1), 20) - require.Equal(t, []types.MevBundle{bundle02_no_uuid_signer2}, bundles) - cr = test_utils.RequireChan(ccBundles, time.Millisecond) - require.False(t, cr.Timeout) - require.Equal(t, []types.MevBundle{bundle01_uuid1_signer1}, cr.Value) - - fetcher.resps[1] = []types.LatestUuidBundle{ - { - Uuid: bundle03_uuid1_signer1.Uuid, - SigningAddress: bundle03_uuid1_signer1.SigningAddress, - BundleHash: bundle03_uuid1_signer1.Hash, - }, - } - - // Passes non-uuid bundle and only the bundle exactly matching the fetcher resp - bundles, ccBundles = txpool.MevBundles(big.NewInt(1), 20) - require.Equal(t, []types.MevBundle{bundle02_no_uuid_signer2}, bundles) - cr = test_utils.RequireChan(ccBundles, time.Millisecond) - require.False(t, cr.Timeout) - require.Equal(t, []types.MevBundle{bundle03_uuid1_signer1}, cr.Value) - - fetcher.resps[1] = append(fetcher.resps[1], types.LatestUuidBundle{ - Uuid: bundle03_uuid1_signer2.Uuid, - SigningAddress: bundle03_uuid1_signer2.SigningAddress, - BundleHash: bundle03_uuid1_signer2.Hash, - }) - - // Passes non-uuid bundle and both bundles exactly matching the fetcher resp for the same hash - bundles, ccBundles = txpool.MevBundles(big.NewInt(1), 20) - require.Equal(t, []types.MevBundle{bundle02_no_uuid_signer2}, bundles) - cr = test_utils.RequireChan(ccBundles, time.Millisecond) - require.False(t, cr.Timeout) - require.Equal(t, []types.MevBundle{bundle03_uuid1_signer1, bundle03_uuid1_signer2}, cr.Value) -} - -type mockFetcher struct { - errorResps map[int64]error - resps map[int64][]types.LatestUuidBundle -} - -func (f *mockFetcher) GetLatestUuidBundles(_ context.Context, blockNum int64) ([]types.LatestUuidBundle, error) { - if err, found := f.errorResps[blockNum]; found { - return nil, err - } - - if resp, found := f.resps[blockNum]; found { - return resp, nil - } - - return nil, errors.New("unexpected block number") -} - -// Benchmarks the speed of validating the contents of the pending queue of the -// transaction pool. -func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } -func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } -func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } - -func benchmarkPendingDemotion(b *testing.B, size int) { - // Add a batch of transactions to a pool one by one - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) - - for i := 0; i < size; i++ { - tx := transaction(uint64(i), 100000, key) - pool.promoteTx(account, tx.Hash(), tx) - } - // Benchmark the speed of pool validation - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.demoteUnexecutables() - } -} - -// Benchmarks the speed of scheduling the contents of the future queue of the -// transaction pool. -func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } -func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } -func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } - -func benchmarkFuturePromotion(b *testing.B, size int) { - // Add a batch of transactions to a pool one by one - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000)) - - for i := 0; i < size; i++ { - tx := transaction(uint64(1+i), 100000, key) - pool.enqueueTx(tx.Hash(), tx, false, true) - } - // Benchmark the speed of pool validation - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.promoteExecutables(nil) - } -} - -// Benchmarks the speed of batched transaction insertion. -func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, false) } -func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, false) } -func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, false) } - -func BenchmarkBatchLocalInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, true) } -func BenchmarkBatchLocalInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, true) } -func BenchmarkBatchLocalInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, true) } - -func benchmarkBatchInsert(b *testing.B, size int, local bool) { - // Generate a batch of transactions to enqueue into the pool - pool, key := setupPool() - defer pool.Close() - - account := crypto.PubkeyToAddress(key.PublicKey) - testAddBalance(pool, account, big.NewInt(1000000000000000000)) - - batches := make([]types.Transactions, b.N) - for i := 0; i < b.N; i++ { - batches[i] = make(types.Transactions, size) - for j := 0; j < size; j++ { - batches[i][j] = transaction(uint64(size*i+j), 100000, key) - } - } - // Benchmark importing the transactions into the queue - b.ResetTimer() - for _, batch := range batches { - if local { - pool.addLocals(batch) - } else { - pool.addRemotes(batch) - } - } -} - -func BenchmarkInsertRemoteWithAllLocals(b *testing.B) { - // Allocate keys for testing - key, _ := crypto.GenerateKey() - account := crypto.PubkeyToAddress(key.PublicKey) - - remoteKey, _ := crypto.GenerateKey() - remoteAddr := crypto.PubkeyToAddress(remoteKey.PublicKey) - - locals := make([]*types.Transaction, 4096+1024) // Occupy all slots - for i := 0; i < len(locals); i++ { - locals[i] = transaction(uint64(i), 100000, key) - } - remotes := make([]*types.Transaction, 1000) - for i := 0; i < len(remotes); i++ { - remotes[i] = pricedTransaction(uint64(i), 100000, big.NewInt(2), remoteKey) // Higher gasprice - } - // Benchmark importing the transactions into the queue - b.ResetTimer() - for i := 0; i < b.N; i++ { - b.StopTimer() - pool, _ := setupPool() - testAddBalance(pool, account, big.NewInt(100000000)) - for _, local := range locals { - pool.addLocal(local) - } - b.StartTimer() - // Assign a high enough balance for testing - testAddBalance(pool, remoteAddr, big.NewInt(100000000)) - for i := 0; i < len(remotes); i++ { - pool.addRemotes([]*types.Transaction{remotes[i]}) - } - pool.Close() - } -} - -// Benchmarks the speed of batch transaction insertion in case of multiple accounts. -func BenchmarkMultiAccountBatchInsert(b *testing.B) { - // Generate a batch of transactions to enqueue into the pool - pool, _ := setupPool() - defer pool.Close() - b.ReportAllocs() - batches := make(types.Transactions, b.N) - for i := 0; i < b.N; i++ { - key, _ := crypto.GenerateKey() - account := crypto.PubkeyToAddress(key.PublicKey) - pool.currentState.AddBalance(account, uint256.NewInt(1000000)) - tx := transaction(uint64(0), 100000, key) - batches[i] = tx - } - // Benchmark importing the transactions into the queue - b.ResetTimer() - for _, tx := range batches { - pool.addRemotesSync([]*types.Transaction{tx}) - } -} diff --git a/builder/core/txpool/legacypool/list.go b/builder/core/txpool/legacypool/list.go deleted file mode 100644 index 7db9c98ac..000000000 --- a/builder/core/txpool/legacypool/list.go +++ /dev/null @@ -1,687 +0,0 @@ -// Copyright 2016 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 legacypool - -import ( - "container/heap" - "math" - "math/big" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/holiman/uint256" - "golang.org/x/exp/slices" -) - -// nonceHeap is a heap.Interface implementation over 64bit unsigned integers for -// retrieving sorted transactions from the possibly gapped future queue. -type nonceHeap []uint64 - -func (h nonceHeap) Len() int { return len(h) } -func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] } -func (h nonceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } - -func (h *nonceHeap) Push(x interface{}) { - *h = append(*h, x.(uint64)) -} - -func (h *nonceHeap) Pop() interface{} { - old := *h - n := len(old) - x := old[n-1] - old[n-1] = 0 - *h = old[0 : n-1] - return x -} - -// sortedMap is a nonce->transaction hash map with a heap based index to allow -// iterating over the contents in a nonce-incrementing way. -type sortedMap struct { - items map[uint64]*types.Transaction // Hash map storing the transaction data - index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode) - cache types.Transactions // Cache of the transactions already sorted - cacheMu sync.Mutex // Mutex covering the cache -} - -// newSortedMap creates a new nonce-sorted transaction map. -func newSortedMap() *sortedMap { - return &sortedMap{ - items: make(map[uint64]*types.Transaction), - index: new(nonceHeap), - } -} - -// Get retrieves the current transactions associated with the given nonce. -func (m *sortedMap) Get(nonce uint64) *types.Transaction { - return m.items[nonce] -} - -// Put inserts a new transaction into the map, also updating the map's nonce -// index. If a transaction already exists with the same nonce, it's overwritten. -func (m *sortedMap) Put(tx *types.Transaction) { - nonce := tx.Nonce() - if m.items[nonce] == nil { - heap.Push(m.index, nonce) - } - m.cacheMu.Lock() - m.items[nonce], m.cache = tx, nil - m.cacheMu.Unlock() -} - -// Forward removes all transactions from the map with a nonce lower than the -// provided threshold. Every removed transaction is returned for any post-removal -// maintenance. -func (m *sortedMap) Forward(threshold uint64) types.Transactions { - var removed types.Transactions - - // Pop off heap items until the threshold is reached - for m.index.Len() > 0 && (*m.index)[0] < threshold { - nonce := heap.Pop(m.index).(uint64) - removed = append(removed, m.items[nonce]) - delete(m.items, nonce) - } - // If we had a cached order, shift the front - m.cacheMu.Lock() - if m.cache != nil { - m.cache = m.cache[len(removed):] - } - m.cacheMu.Unlock() - return removed -} - -// Filter iterates over the list of transactions and removes all of them for which -// the specified function evaluates to true. -// Filter, as opposed to 'filter', re-initialises the heap after the operation is done. -// If you want to do several consecutive filterings, it's therefore better to first -// do a .filter(func1) followed by .Filter(func2) or reheap() -func (m *sortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions { - removed := m.filter(filter) - // If transactions were removed, the heap and cache are ruined - if len(removed) > 0 { - m.reheap() - } - return removed -} - -func (m *sortedMap) reheap() { - *m.index = make([]uint64, 0, len(m.items)) - for nonce := range m.items { - *m.index = append(*m.index, nonce) - } - heap.Init(m.index) - m.cacheMu.Lock() - m.cache = nil - m.cacheMu.Unlock() -} - -// filter is identical to Filter, but **does not** regenerate the heap. This method -// should only be used if followed immediately by a call to Filter or reheap() -func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transactions { - var removed types.Transactions - - // Collect all the transactions to filter out - for nonce, tx := range m.items { - if filter(tx) { - removed = append(removed, tx) - delete(m.items, nonce) - } - } - if len(removed) > 0 { - m.cacheMu.Lock() - m.cache = nil - m.cacheMu.Unlock() - } - return removed -} - -// Cap places a hard limit on the number of items, returning all transactions -// exceeding that limit. -func (m *sortedMap) Cap(threshold int) types.Transactions { - // Short circuit if the number of items is under the limit - if len(m.items) <= threshold { - return nil - } - // Otherwise gather and drop the highest nonce'd transactions - var drops types.Transactions - slices.Sort(*m.index) - for size := len(m.items); size > threshold; size-- { - drops = append(drops, m.items[(*m.index)[size-1]]) - delete(m.items, (*m.index)[size-1]) - } - *m.index = (*m.index)[:threshold] - // The sorted m.index slice is still a valid heap, so there is no need to - // reheap after deleting tail items. - - // If we had a cache, shift the back - m.cacheMu.Lock() - if m.cache != nil { - m.cache = m.cache[:len(m.cache)-len(drops)] - } - m.cacheMu.Unlock() - return drops -} - -// Remove deletes a transaction from the maintained map, returning whether the -// transaction was found. -func (m *sortedMap) Remove(nonce uint64) bool { - // Short circuit if no transaction is present - _, ok := m.items[nonce] - if !ok { - return false - } - // Otherwise delete the transaction and fix the heap index - for i := 0; i < m.index.Len(); i++ { - if (*m.index)[i] == nonce { - heap.Remove(m.index, i) - break - } - } - delete(m.items, nonce) - m.cacheMu.Lock() - m.cache = nil - m.cacheMu.Unlock() - - return true -} - -// Ready retrieves a sequentially increasing list of transactions starting at the -// provided nonce that is ready for processing. The returned transactions will be -// removed from the list. -// -// Note, all transactions with nonces lower than start will also be returned to -// prevent getting into an invalid state. This is not something that should ever -// happen but better to be self correcting than failing! -func (m *sortedMap) Ready(start uint64) types.Transactions { - // Short circuit if no transactions are available - if m.index.Len() == 0 || (*m.index)[0] > start { - return nil - } - // Otherwise start accumulating incremental transactions - var ready types.Transactions - for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ { - ready = append(ready, m.items[next]) - delete(m.items, next) - heap.Pop(m.index) - } - m.cacheMu.Lock() - m.cache = nil - m.cacheMu.Unlock() - - return ready -} - -// Len returns the length of the transaction map. -func (m *sortedMap) Len() int { - return len(m.items) -} - -func (m *sortedMap) flatten() types.Transactions { - m.cacheMu.Lock() - defer m.cacheMu.Unlock() - // If the sorting was not cached yet, create and cache it - if m.cache == nil { - m.cache = make(types.Transactions, 0, len(m.items)) - for _, tx := range m.items { - m.cache = append(m.cache, tx) - } - sort.Sort(types.TxByNonce(m.cache)) - } - return m.cache -} - -// Flatten creates a nonce-sorted slice of transactions based on the loosely -// sorted internal representation. The result of the sorting is cached in case -// it's requested again before any modifications are made to the contents. -func (m *sortedMap) Flatten() types.Transactions { - cache := m.flatten() - // Copy the cache to prevent accidental modification - txs := make(types.Transactions, len(cache)) - copy(txs, cache) - return txs -} - -// LastElement returns the last element of a flattened list, thus, the -// transaction with the highest nonce -func (m *sortedMap) LastElement() *types.Transaction { - cache := m.flatten() - return cache[len(cache)-1] -} - -// list is a "list" of transactions belonging to an account, sorted by account -// nonce. The same type can be used both for storing contiguous transactions for -// the executable/pending queue; and for storing gapped transactions for the non- -// executable/future queue, with minor behavioral changes. -type list struct { - strict bool // Whether nonces are strictly continuous or not - txs *sortedMap // Heap indexed sorted hash map of the transactions - - costcap *uint256.Int // Price of the highest costing transaction (reset only if exceeds balance) - gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit) - totalcost *uint256.Int // Total cost of all transactions in the list -} - -// newList creates a new transaction list for maintaining nonce-indexable fast, -// gapped, sortable transaction lists. -func newList(strict bool) *list { - return &list{ - strict: strict, - txs: newSortedMap(), - costcap: new(uint256.Int), - totalcost: new(uint256.Int), - } -} - -// Contains returns whether the list contains a transaction -// with the provided nonce. -func (l *list) Contains(nonce uint64) bool { - return l.txs.Get(nonce) != nil -} - -// Add tries to insert a new transaction into the list, returning whether the -// transaction was accepted, and if yes, any previous transaction it replaced. -// -// If the new transaction is accepted into the list, the lists' cost and gas -// thresholds are also potentially updated. -func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) { - // If there's an older better transaction, abort - old := l.txs.Get(tx.Nonce()) - if old != nil { - if old.GasFeeCapCmp(tx) >= 0 || old.GasTipCapCmp(tx) >= 0 { - return false, nil - } - // thresholdFeeCap = oldFC * (100 + priceBump) / 100 - a := big.NewInt(100 + int64(priceBump)) - aFeeCap := new(big.Int).Mul(a, old.GasFeeCap()) - aTip := a.Mul(a, old.GasTipCap()) - - // thresholdTip = oldTip * (100 + priceBump) / 100 - b := big.NewInt(100) - thresholdFeeCap := aFeeCap.Div(aFeeCap, b) - thresholdTip := aTip.Div(aTip, b) - - // We have to ensure that both the new fee cap and tip are higher than the - // old ones as well as checking the percentage threshold to ensure that - // this is accurate for low (Wei-level) gas price replacements. - if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 { - return false, nil - } - // Old is being replaced, subtract old cost - l.subTotalCost([]*types.Transaction{old}) - } - // Add new tx cost to totalcost - cost, overflow := uint256.FromBig(tx.Cost()) - if overflow { - return false, nil - } - l.totalcost.Add(l.totalcost, cost) - - // Otherwise overwrite the old transaction with the current one - l.txs.Put(tx) - if l.costcap.Cmp(cost) < 0 { - l.costcap = cost - } - if gas := tx.Gas(); l.gascap < gas { - l.gascap = gas - } - return true, old -} - -// Forward removes all transactions from the list with a nonce lower than the -// provided threshold. Every removed transaction is returned for any post-removal -// maintenance. -func (l *list) Forward(threshold uint64) types.Transactions { - txs := l.txs.Forward(threshold) - l.subTotalCost(txs) - return txs -} - -// Filter removes all transactions from the list with a cost or gas limit higher -// than the provided thresholds. Every removed transaction is returned for any -// post-removal maintenance. Strict-mode invalidated transactions are also -// returned. -// -// This method uses the cached costcap and gascap to quickly decide if there's even -// a point in calculating all the costs or if the balance covers all. If the threshold -// is lower than the costgas cap, the caps will be reset to a new high after removing -// the newly invalidated transactions. -func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactions, types.Transactions) { - // If all transactions are below the threshold, short circuit - if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit { - return nil, nil - } - l.costcap = new(uint256.Int).Set(costLimit) // Lower the caps to the thresholds - l.gascap = gasLimit - - // Filter out all the transactions above the account's funds - removed := l.txs.Filter(func(tx *types.Transaction) bool { - return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit.ToBig()) > 0 - }) - - if len(removed) == 0 { - return nil, nil - } - var invalids types.Transactions - // If the list was strict, filter anything above the lowest nonce - if l.strict { - lowest := uint64(math.MaxUint64) - for _, tx := range removed { - if nonce := tx.Nonce(); lowest > nonce { - lowest = nonce - } - } - invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) - } - // Reset total cost - l.subTotalCost(removed) - l.subTotalCost(invalids) - l.txs.reheap() - return removed, invalids -} - -// Cap places a hard limit on the number of items, returning all transactions -// exceeding that limit. -func (l *list) Cap(threshold int) types.Transactions { - txs := l.txs.Cap(threshold) - l.subTotalCost(txs) - return txs -} - -// Remove deletes a transaction from the maintained list, returning whether the -// transaction was found, and also returning any transaction invalidated due to -// the deletion (strict mode only). -func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) { - // Remove the transaction from the set - nonce := tx.Nonce() - if removed := l.txs.Remove(nonce); !removed { - return false, nil - } - l.subTotalCost([]*types.Transaction{tx}) - // In strict mode, filter out non-executable transactions - if l.strict { - txs := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce }) - l.subTotalCost(txs) - return true, txs - } - return true, nil -} - -// Ready retrieves a sequentially increasing list of transactions starting at the -// provided nonce that is ready for processing. The returned transactions will be -// removed from the list. -// -// Note, all transactions with nonces lower than start will also be returned to -// prevent getting into an invalid state. This is not something that should ever -// happen but better to be self correcting than failing! -func (l *list) Ready(start uint64) types.Transactions { - txs := l.txs.Ready(start) - l.subTotalCost(txs) - return txs -} - -// Len returns the length of the transaction list. -func (l *list) Len() int { - return l.txs.Len() -} - -// Empty returns whether the list of transactions is empty or not. -func (l *list) Empty() bool { - return l.Len() == 0 -} - -// Flatten creates a nonce-sorted slice of transactions based on the loosely -// sorted internal representation. The result of the sorting is cached in case -// it's requested again before any modifications are made to the contents. -func (l *list) Flatten() types.Transactions { - return l.txs.Flatten() -} - -// LastElement returns the last element of a flattened list, thus, the -// transaction with the highest nonce -func (l *list) LastElement() *types.Transaction { - return l.txs.LastElement() -} - -// subTotalCost subtracts the cost of the given transactions from the -// total cost of all transactions. -func (l *list) subTotalCost(txs []*types.Transaction) { - for _, tx := range txs { - _, underflow := l.totalcost.SubOverflow(l.totalcost, uint256.MustFromBig(tx.Cost())) - if underflow { - panic("totalcost underflow") - } - } -} - -// priceHeap is a heap.Interface implementation over transactions for retrieving -// price-sorted transactions to discard when the pool fills up. If baseFee is set -// then the heap is sorted based on the effective tip based on the given base fee. -// If baseFee is nil then the sorting is based on gasFeeCap. -type priceHeap struct { - baseFee *big.Int // heap should always be re-sorted after baseFee is changed - list []*types.Transaction -} - -func (h *priceHeap) Len() int { return len(h.list) } -func (h *priceHeap) Swap(i, j int) { h.list[i], h.list[j] = h.list[j], h.list[i] } - -func (h *priceHeap) Less(i, j int) bool { - switch h.cmp(h.list[i], h.list[j]) { - case -1: - return true - case 1: - return false - default: - return h.list[i].Nonce() > h.list[j].Nonce() - } -} - -func (h *priceHeap) cmp(a, b *types.Transaction) int { - if h.baseFee != nil { - // Compare effective tips if baseFee is specified - if c := a.EffectiveGasTipCmp(b, h.baseFee); c != 0 { - return c - } - } - // Compare fee caps if baseFee is not specified or effective tips are equal - if c := a.GasFeeCapCmp(b); c != 0 { - return c - } - // Compare tips if effective tips and fee caps are equal - return a.GasTipCapCmp(b) -} - -func (h *priceHeap) Push(x interface{}) { - tx := x.(*types.Transaction) - h.list = append(h.list, tx) -} - -func (h *priceHeap) Pop() interface{} { - old := h.list - n := len(old) - x := old[n-1] - old[n-1] = nil - h.list = old[0 : n-1] - return x -} - -// pricedList is a price-sorted heap to allow operating on transactions pool -// contents in a price-incrementing way. It's built upon the all transactions -// in txpool but only interested in the remote part. It means only remote transactions -// will be considered for tracking, sorting, eviction, etc. -// -// Two heaps are used for sorting: the urgent heap (based on effective tip in the next -// block) and the floating heap (based on gasFeeCap). Always the bigger heap is chosen for -// eviction. Transactions evicted from the urgent heap are first demoted into the floating heap. -// In some cases (during a congestion, when blocks are full) the urgent heap can provide -// better candidates for inclusion while in other cases (at the top of the baseFee peak) -// the floating heap is better. When baseFee is decreasing they behave similarly. -type pricedList struct { - // Number of stale price points to (re-heap trigger). - stales atomic.Int64 - - all *lookup // Pointer to the map of all transactions - urgent, floating priceHeap // Heaps of prices of all the stored **remote** transactions - reheapMu sync.Mutex // Mutex asserts that only one routine is reheaping the list -} - -const ( - // urgentRatio : floatingRatio is the capacity ratio of the two queues - urgentRatio = 4 - floatingRatio = 1 -) - -// newPricedList creates a new price-sorted transaction heap. -func newPricedList(all *lookup) *pricedList { - return &pricedList{ - all: all, - } -} - -// Put inserts a new transaction into the heap. -func (l *pricedList) Put(tx *types.Transaction, local bool) { - if local { - return - } - // Insert every new transaction to the urgent heap first; Discard will balance the heaps - heap.Push(&l.urgent, tx) -} - -// Removed notifies the prices transaction list that an old transaction dropped -// from the pool. The list will just keep a counter of stale objects and update -// the heap if a large enough ratio of transactions go stale. -func (l *pricedList) Removed(count int) { - // Bump the stale counter, but exit if still too low (< 25%) - stales := l.stales.Add(int64(count)) - if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 { - return - } - // Seems we've reached a critical number of stale transactions, reheap - l.Reheap() -} - -// Underpriced checks whether a transaction is cheaper than (or as cheap as) the -// lowest priced (remote) transaction currently being tracked. -func (l *pricedList) Underpriced(tx *types.Transaction) bool { - // Note: with two queues, being underpriced is defined as being worse than the worst item - // in all non-empty queues if there is any. If both queues are empty then nothing is underpriced. - return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) && - (l.underpricedFor(&l.floating, tx) || len(l.floating.list) == 0) && - (len(l.urgent.list) != 0 || len(l.floating.list) != 0) -} - -// underpricedFor checks whether a transaction is cheaper than (or as cheap as) the -// lowest priced (remote) transaction in the given heap. -func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool { - // Discard stale price points if found at the heap start - for len(h.list) > 0 { - head := h.list[0] - if l.all.GetRemote(head.Hash()) == nil { // Removed or migrated - l.stales.Add(-1) - heap.Pop(h) - continue - } - break - } - // Check if the transaction is underpriced or not - if len(h.list) == 0 { - return false // There is no remote transaction at all. - } - // If the remote transaction is even cheaper than the - // cheapest one tracked locally, reject it. - return h.cmp(h.list[0], tx) >= 0 -} - -// Discard finds a number of most underpriced transactions, removes them from the -// priced list and returns them for further removal from the entire pool. -// If noPending is set to true, we will only consider the floating list -// -// Note local transaction won't be considered for eviction. -func (l *pricedList) Discard(slots int, force bool) (types.Transactions, bool) { - drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop - for slots > 0 { - if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio { - // Discard stale transactions if found during cleanup - tx := heap.Pop(&l.urgent).(*types.Transaction) - if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated - l.stales.Add(-1) - continue - } - // Non stale transaction found, move to floating heap - heap.Push(&l.floating, tx) - } else { - if len(l.floating.list) == 0 { - // Stop if both heaps are empty - break - } - // Discard stale transactions if found during cleanup - tx := heap.Pop(&l.floating).(*types.Transaction) - if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated - l.stales.Add(-1) - continue - } - // Non stale transaction found, discard it - drop = append(drop, tx) - slots -= numSlots(tx) - } - } - // If we still can't make enough room for the new transaction - if slots > 0 && !force { - for _, tx := range drop { - heap.Push(&l.urgent, tx) - } - return nil, false - } - return drop, true -} - -// Reheap forcibly rebuilds the heap based on the current remote transaction set. -func (l *pricedList) Reheap() { - l.reheapMu.Lock() - defer l.reheapMu.Unlock() - start := time.Now() - l.stales.Store(0) - l.urgent.list = make([]*types.Transaction, 0, l.all.RemoteCount()) - l.all.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool { - l.urgent.list = append(l.urgent.list, tx) - return true - }, false, true) // Only iterate remotes - heap.Init(&l.urgent) - - // balance out the two heaps by moving the worse half of transactions into the - // floating heap - // Note: Discard would also do this before the first eviction but Reheap can do - // is more efficiently. Also, Underpriced would work suboptimally the first time - // if the floating queue was empty. - floatingCount := len(l.urgent.list) * floatingRatio / (urgentRatio + floatingRatio) - l.floating.list = make([]*types.Transaction, floatingCount) - for i := 0; i < floatingCount; i++ { - l.floating.list[i] = heap.Pop(&l.urgent).(*types.Transaction) - } - heap.Init(&l.floating) - reheapTimer.Update(time.Since(start)) -} - -// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not -// necessary to call right before SetBaseFee when processing a new block. -func (l *pricedList) SetBaseFee(baseFee *big.Int) { - l.urgent.baseFee = baseFee - l.Reheap() -} diff --git a/builder/core/txpool/legacypool/list_test.go b/builder/core/txpool/legacypool/list_test.go deleted file mode 100644 index 8587c66f7..000000000 --- a/builder/core/txpool/legacypool/list_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2016 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 legacypool - -import ( - "math/big" - "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/holiman/uint256" -) - -// Tests that transactions can be added to strict lists and list contents and -// nonce boundaries are correctly maintained. -func TestStrictListAdd(t *testing.T) { - // Generate a list of transactions to insert - key, _ := crypto.GenerateKey() - - txs := make(types.Transactions, 1024) - for i := 0; i < len(txs); i++ { - txs[i] = transaction(uint64(i), 0, key) - } - // Insert the transactions in a random order - list := newList(true) - for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], DefaultConfig.PriceBump) - } - // Verify internal state - if len(list.txs.items) != len(txs) { - t.Errorf("transaction count mismatch: have %d, want %d", len(list.txs.items), len(txs)) - } - for i, tx := range txs { - if list.txs.items[tx.Nonce()] != tx { - t.Errorf("item %d: transaction mismatch: have %v, want %v", i, list.txs.items[tx.Nonce()], tx) - } - } -} - -// TestListAddVeryExpensive tests adding txs which exceed 256 bits in cost. It is -// expected that the list does not panic. -func TestListAddVeryExpensive(t *testing.T) { - key, _ := crypto.GenerateKey() - list := newList(true) - for i := 0; i < 3; i++ { - value := big.NewInt(100) - gasprice, _ := new(big.Int).SetString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0) - gaslimit := uint64(i) - tx, _ := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, value, gaslimit, gasprice, nil), types.HomesteadSigner{}, key) - t.Logf("cost: %x bitlen: %d\n", tx.Cost(), tx.Cost().BitLen()) - list.Add(tx, DefaultConfig.PriceBump) - } -} - -func BenchmarkListAdd(b *testing.B) { - // Generate a list of transactions to insert - key, _ := crypto.GenerateKey() - - txs := make(types.Transactions, 100000) - for i := 0; i < len(txs); i++ { - txs[i] = transaction(uint64(i), 0, key) - } - // Insert the transactions in a random order - priceLimit := uint256.NewInt(DefaultConfig.PriceLimit) - b.ResetTimer() - for i := 0; i < b.N; i++ { - list := newList(true) - for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], DefaultConfig.PriceBump) - list.Filter(priceLimit, DefaultConfig.PriceBump) - } - } -} - -func BenchmarkListCapOneTx(b *testing.B) { - // Generate a list of transactions to insert - key, _ := crypto.GenerateKey() - - txs := make(types.Transactions, 32) - for i := 0; i < len(txs); i++ { - txs[i] = transaction(uint64(i), 0, key) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - list := newList(true) - // Insert the transactions in a random order - for _, v := range rand.Perm(len(txs)) { - list.Add(txs[v], DefaultConfig.PriceBump) - } - b.StartTimer() - list.Cap(list.Len() - 1) - b.StopTimer() - } -} diff --git a/builder/core/txpool/legacypool/noncer.go b/builder/core/txpool/legacypool/noncer.go deleted file mode 100644 index 2c65dd2ca..000000000 --- a/builder/core/txpool/legacypool/noncer.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 legacypool - -import ( - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" -) - -// noncer is a tiny virtual state database to manage the executable nonces of -// accounts in the pool, falling back to reading from a real state database if -// an account is unknown. -type noncer struct { - fallback *state.StateDB - nonces map[common.Address]uint64 - lock sync.Mutex -} - -// newNoncer creates a new virtual state database to track the pool nonces. -func newNoncer(statedb *state.StateDB) *noncer { - return &noncer{ - fallback: statedb.Copy(), - nonces: make(map[common.Address]uint64), - } -} - -// get returns the current nonce of an account, falling back to a real state -// database if the account is unknown. -func (txn *noncer) get(addr common.Address) uint64 { - // We use mutex for get operation is the underlying - // state will mutate db even for read access. - txn.lock.Lock() - defer txn.lock.Unlock() - - if _, ok := txn.nonces[addr]; !ok { - if nonce := txn.fallback.GetNonce(addr); nonce != 0 { - txn.nonces[addr] = nonce - } - } - return txn.nonces[addr] -} - -// set inserts a new virtual nonce into the virtual state database to be returned -// whenever the pool requests it instead of reaching into the real state database. -func (txn *noncer) set(addr common.Address, nonce uint64) { - txn.lock.Lock() - defer txn.lock.Unlock() - - txn.nonces[addr] = nonce -} - -// setIfLower updates a new virtual nonce into the virtual state database if the -// new one is lower. -func (txn *noncer) setIfLower(addr common.Address, nonce uint64) { - txn.lock.Lock() - defer txn.lock.Unlock() - - if _, ok := txn.nonces[addr]; !ok { - if nonce := txn.fallback.GetNonce(addr); nonce != 0 { - txn.nonces[addr] = nonce - } - } - if txn.nonces[addr] <= nonce { - return - } - txn.nonces[addr] = nonce -} - -// setAll sets the nonces for all accounts to the given map. -func (txn *noncer) setAll(all map[common.Address]uint64) { - txn.lock.Lock() - defer txn.lock.Unlock() - - txn.nonces = all -} diff --git a/builder/core/txpool/sbundle_pool.go b/builder/core/txpool/sbundle_pool.go deleted file mode 100644 index 3dad850a7..000000000 --- a/builder/core/txpool/sbundle_pool.go +++ /dev/null @@ -1,237 +0,0 @@ -package txpool - -// TODO: cancel sbundles, fetch them from the db - -import ( - "errors" - "math/big" - "sync" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -const ( - maxSBundleRange = 30 - maxSBundleNesting = 1 - - // 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 - // blobTxMaxSize is the maximum size a single transaction can have, outside - // the included blobs. Since blob transactions are pulled instead of pushed, - // and only a small metadata is kept in ram, the rest is on disk, there is - // no critical limit that should be enforced. Still, capping it to some sane - // limit can never hurt. - blobTxMaxSize = 1024 * 1024 -) - -var ( - ErrInvalidInclusion = errors.New("invalid inclusion") - ErrBundleTooDeep = errors.New("bundle too deep") - ErrInvalidBody = errors.New("invalid body") - ErrInvalidConstraints = errors.New("invalid constraints") -) - -type SBundlePool struct { - mu sync.Mutex - - bundles map[common.Hash]*types.SBundle - byBlock map[uint64][]*types.SBundle - - // bundles that were cancelled and their max valid block - cancelled map[common.Hash]struct{} - cancelledMaxBlock map[uint64][]common.Hash - - signer types.Signer - - chainconfig *params.ChainConfig - currentHead atomic.Pointer[types.Header] -} - -func NewSBundlePool(chainConfig *params.ChainConfig) *SBundlePool { - return &SBundlePool{ - bundles: make(map[common.Hash]*types.SBundle), - byBlock: make(map[uint64][]*types.SBundle), - cancelled: make(map[common.Hash]struct{}), - cancelledMaxBlock: make(map[uint64][]common.Hash), - signer: types.LatestSigner(chainConfig), - chainconfig: chainConfig, - } -} - -func (p *SBundlePool) ResetPoolData(head *types.Header) { - p.mu.Lock() - defer p.mu.Unlock() - - p.currentHead.Store(head) -} - -func (p *SBundlePool) Add(bundle *types.SBundle) error { - p.mu.Lock() - defer p.mu.Unlock() - - if _, ok := p.bundles[bundle.Hash()]; ok { - return nil - } - - if err := p.validateSBundle(0, bundle); err != nil { - return err - } - - p.bundles[bundle.Hash()] = bundle - for b := bundle.Inclusion.BlockNumber; b <= bundle.Inclusion.MaxBlockNumber; b++ { - p.byBlock[b] = append(p.byBlock[b], bundle) - } - return nil -} - -func (p *SBundlePool) GetSBundles(nextBlock uint64) []*types.SBundle { - p.mu.Lock() - defer p.mu.Unlock() - - // remove old blocks - for b, el := range p.byBlock { - if b < nextBlock { - for _, bundle := range el { - if bundle.Inclusion.MaxBlockNumber < nextBlock { - delete(p.bundles, bundle.Hash()) - } - delete(p.bundles, bundle.Hash()) - } - delete(p.byBlock, b) - } - } - - // remove expired cancelled bundles - for b, el := range p.cancelledMaxBlock { - if b < nextBlock { - for _, hash := range el { - delete(p.cancelled, hash) - } - delete(p.cancelledMaxBlock, b) - } - } - - // filter cancelled bundles and dependent bundles - var res []*types.SBundle - for _, bundle := range p.byBlock[nextBlock] { - if isBundleCancelled(bundle, p.cancelled) { - continue - } - res = append(res, bundle) - } - - return res -} - -func (p *SBundlePool) validateSBundle(level int, b *types.SBundle) error { - if level > maxSBundleNesting { - return ErrBundleTooDeep - } - // inclusion - if b.Inclusion.BlockNumber > b.Inclusion.MaxBlockNumber { - return ErrInvalidInclusion - } - if b.Inclusion.MaxBlockNumber-b.Inclusion.BlockNumber > maxSBundleRange { - return ErrInvalidInclusion - } - - // body - for _, el := range b.Body { - if el.Tx != nil { - if err := p.validateTx(el.Tx); err != nil { - return err - } - } else if el.Bundle != nil { - if err := p.validateSBundle(level+1, el.Bundle); err != nil { - return err - } - } else { - return ErrInvalidBody - } - } - - // constraints - if len(b.Validity.Refund) > len(b.Body) { - return ErrInvalidConstraints - } - - usedConstraints := make([]bool, len(b.Body)) - totalRefundPercent := 0 - for _, el := range b.Validity.Refund { - if el.BodyIdx >= len(b.Body) { - return ErrInvalidConstraints - } - if usedConstraints[el.BodyIdx] { - return ErrInvalidConstraints - } - usedConstraints[el.BodyIdx] = true - totalRefundPercent += el.Percent - } - if totalRefundPercent > 100 { - return ErrInvalidConstraints - } - - return nil -} - -// same as core/tx_pool.go but we don't check for gas price and nonce -func (p *SBundlePool) validateTx(tx *types.Transaction) error { - opts := &ValidationOptions{ - Config: p.chainconfig, - MinTip: new(big.Int), - } - - if tx.Type() == types.BlobTxType { - opts.MaxSize = blobTxMaxSize - opts.Accept = 1 << types.BlobTxType - } else { - opts.MaxSize = txMaxSize - opts.Accept = 0 | - 1<. - -package txpool - -import ( - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/holiman/uint256" -) - -// LazyTransaction contains a small subset of the transaction properties that is -// enough for the miner and other APIs to handle large batches of transactions; -// and supports pulling up the entire transaction when really needed. -type LazyTransaction struct { - Pool LazyResolver // Transaction resolver to pull the real transaction up - Hash common.Hash // Transaction hash to pull up if needed - Tx *types.Transaction // Transaction if already resolved - - Time time.Time // Time when the transaction was first seen - GasFeeCap *uint256.Int // Maximum fee per gas the transaction may consume - GasTipCap *uint256.Int // Maximum miner tip per gas the transaction can pay - - Gas uint64 // Amount of gas required by the transaction - BlobGas uint64 // Amount of blob gas required by the transaction - GasPrice *uint256.Int // Gas price of the transaction -} - -// Resolve retrieves the full transaction belonging to a lazy handle if it is still -// maintained by the transaction pool. -// -// Note, the method will *not* cache the retrieved transaction if the original -// pool has not cached it. The idea being, that if the tx was too big to insert -// originally, silently saving it will cause more trouble down the line (and -// indeed seems to have caused a memory bloat in the original implementation -// which did just that). -func (ltx *LazyTransaction) Resolve() *types.Transaction { - if ltx.Tx != nil { - return ltx.Tx - } - return ltx.Pool.Get(ltx.Hash) -} - -// LazyResolver is a minimal interface needed for a transaction pool to satisfy -// resolving lazy transactions. It's mostly a helper to avoid the entire sub- -// pool being injected into the lazy transaction. -type LazyResolver interface { - // Get returns a transaction if it is contained in the pool, or nil otherwise. - Get(hash common.Hash) *types.Transaction -} - -type MockLazyResolver struct { - Transactions map[common.Hash]*types.Transaction -} - -func (m *MockLazyResolver) Get(hash common.Hash) *types.Transaction { - return m.Transactions[hash] -} - -// AddressReserver is passed by the main transaction pool to subpools, so they -// may request (and relinquish) exclusive access to certain addresses. -type AddressReserver func(addr common.Address, reserve bool) error - -// PendingFilter is a collection of filter rules to allow retrieving a subset -// of transactions for announcement or mining. -// -// Note, the entries here are not arbitrary useful filters, rather each one has -// a very specific call site in mind and each one can be evaluated very cheaply -// by the pool implementations. Only add new ones that satisfy those constraints. -type PendingFilter struct { - MinTip *uint256.Int // Minimum miner tip required to include a transaction - BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction - BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction - - OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling) - OnlyBlobTxs bool // Return only blob transactions (block blob-space filling) -} - -// SubPool represents a specialized transaction pool that lives on its own (e.g. -// blob pool). Since independent of how many specialized pools we have, they do -// need to be updated in lockstep and assemble into one coherent view for block -// production, this interface defines the common methods that allow the primary -// transaction pool to manage the subpools. -type SubPool interface { - // Filter is a selector used to decide whether a transaction would be added - // to this particular subpool. - Filter(tx *types.Transaction) bool - - // Init sets the base parameters of the subpool, allowing it to load any saved - // transactions from disk and also permitting internal maintenance routines to - // start up. - // - // These should not be passed as a constructor argument - nor should the pools - // start by themselves - in order to keep multiple subpools in lockstep with - // one another. - Init(gasTip uint64, head *types.Header, reserve AddressReserver) error - - // Close terminates any background processing threads and releases any held - // resources. - Close() error - - // Reset retrieves the current state of the blockchain and ensures the content - // of the transaction pool is valid with regard to the chain state. - Reset(oldHead, newHead *types.Header) - - // SetGasTip updates the minimum price required by the subpool for a new - // transaction, and drops all transactions below this threshold. - SetGasTip(tip *big.Int) - - // Has returns an indicator whether subpool has a transaction cached with the - // given hash. - Has(hash common.Hash) bool - - // Get returns a transaction if it is contained in the pool, or nil otherwise. - Get(hash common.Hash) *types.Transaction - - // Add enqueues a batch of transactions into the pool if they are valid. Due - // to the large transaction churn, add may postpone fully integrating the tx - // to a later point to batch multiple ones together. - Add(txs []*types.Transaction, local bool, sync bool, private bool) []error - - IsPrivateTxHash(hash common.Hash) bool - - // Pending retrieves all currently processable transactions, grouped by origin - // account and sorted by nonce. - // - // The transactions can also be pre-filtered by the dynamic fee components to - // reduce allocations and load on downstream subsystems. - Pending(filter PendingFilter) map[common.Address][]*LazyTransaction - - // SubscribeTransactions subscribes to new transaction events. The subscriber - // can decide whether to receive notifications only for newly seen transactions - // or also for reorged out ones. - SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription - - // Nonce returns the next nonce of an account, with all transactions executable - // by the pool already applied on top. - Nonce(addr common.Address) uint64 - - // Stats retrieves the current pool stats, namely the number of pending and the - // number of queued (non-executable) transactions. - Stats() (int, int) - - // Content retrieves the data content of the transaction pool, returning all the - // pending as well as queued transactions, grouped by account and sorted by nonce. - Content() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) - - // ContentFrom retrieves the data content of the transaction pool, returning the - // pending as well as queued transactions of this address, grouped by nonce. - ContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) - - // Locals retrieves the accounts currently considered local by the pool. - Locals() []common.Address - - // Status returns the known status (unknown/pending/queued) of a transaction - // identified by their hashes. - Status(hash common.Hash) TxStatus -} diff --git a/builder/core/txpool/txpool.go b/builder/core/txpool/txpool.go deleted file mode 100644 index 2b07b8d03..000000000 --- a/builder/core/txpool/txpool.go +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright 2023 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 txpool - -import ( - "context" - "errors" - "fmt" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" - "github.com/google/uuid" - "golang.org/x/crypto/sha3" -) - -// TxStatus is the current status of a transaction as seen by the pool. -type TxStatus uint - -const ( - TxStatusUnknown TxStatus = iota - TxStatusQueued - TxStatusPending - TxStatusIncluded -) - -var ( - // reservationsGaugeName is the prefix of a per-subpool address reservation - // metric. - // - // This is mostly a sanity metric to ensure there's no bug that would make - // some subpool hog all the reservations due to mis-accounting. - reservationsGaugeName = "txpool/reservations" -) - -type IFetcher interface { - GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error) -} - -// BlockChain defines the minimal set of methods needed to back a tx pool with -// a chain. Exists to allow mocking the live chain out of tests. -type BlockChain interface { - // Config retrieves the chain's fork configuration. - Config() *params.ChainConfig - - // CurrentBlock returns the current head of the chain. - CurrentBlock() *types.Header - - // SubscribeChainHeadEvent subscribes to new blocks being added to the chain. - SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription -} - -// TxPool is an aggregator for various transaction specific pools, collectively -// tracking all the transactions deemed interesting by the node. Transactions -// enter the pool when they are received from the network or submitted locally. -// They exit the pool when they are included in the blockchain or evicted due to -// resource constraints. -type TxPool struct { - subpools []SubPool // List of subpools for specialized transaction handling - - reservations map[common.Address]SubPool // Map with the account to pool reservations - reserveLock sync.Mutex // Lock protecting the account reservations - - subs event.SubscriptionScope // Subscription scope to unsubscribe all on shutdown - quit chan chan error // Quit channel to tear down the head updater - term chan struct{} // Termination channel to detect a closed pool - - sync chan chan error // Testing / simulator channel to block until internal reset is done - - bundleLock sync.RWMutex // Mutex protecting the pool when adding bundles - mevBundles []types.MevBundle - bundleFetcher IFetcher - sbundles *SBundlePool -} - -// New creates a new transaction pool to gather, sort and filter inbound -// transactions from the network. -func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) { - // Retrieve the current head so that all subpools and this main coordinator - // pool will have the same starting state, even if the chain moves forward - // during initialization. - head := chain.CurrentBlock() - - pool := &TxPool{ - subpools: subpools, - reservations: make(map[common.Address]SubPool), - quit: make(chan chan error), - term: make(chan struct{}), - sync: make(chan chan error), - sbundles: NewSBundlePool(chain.Config()), - } - for i, subpool := range subpools { - if err := subpool.Init(gasTip, head, pool.reserver(i, subpool)); err != nil { - for j := i - 1; j >= 0; j-- { - subpools[j].Close() - } - return nil, err - } - } - - pool.sbundles.ResetPoolData(head) - - go pool.loop(head, chain) - return pool, nil -} - -// reserver is a method to create an address reservation callback to exclusively -// assign/deassign addresses to/from subpools. This can ensure that at any point -// in time, only a single subpool is able to manage an account, avoiding cross -// subpool eviction issues and nonce conflicts. -func (p *TxPool) reserver(id int, subpool SubPool) AddressReserver { - return func(addr common.Address, reserve bool) error { - p.reserveLock.Lock() - defer p.reserveLock.Unlock() - - owner, exists := p.reservations[addr] - if reserve { - // Double reservations are forbidden even from the same pool to - // avoid subtle bugs in the long term. - if exists { - if owner == subpool { - log.Error("pool attempted to reserve already-owned address", "address", addr) - return nil // Ignore fault to give the pool a chance to recover while the bug gets fixed - } - return ErrAlreadyReserved - } - p.reservations[addr] = subpool - if metrics.Enabled { - m := fmt.Sprintf("%s/%d", reservationsGaugeName, id) - metrics.GetOrRegisterGauge(m, nil).Inc(1) - } - return nil - } - // Ensure subpools only attempt to unreserve their own owned addresses, - // otherwise flag as a programming error. - if !exists { - log.Error("pool attempted to unreserve non-reserved address", "address", addr) - return errors.New("address not reserved") - } - if subpool != owner { - log.Error("pool attempted to unreserve non-owned address", "address", addr) - return errors.New("address not owned") - } - delete(p.reservations, addr) - if metrics.Enabled { - m := fmt.Sprintf("%s/%d", reservationsGaugeName, id) - metrics.GetOrRegisterGauge(m, nil).Dec(1) - } - return nil - } -} - -// Close terminates the transaction pool and all its subpools. -func (p *TxPool) Close() error { - var errs []error - - // Terminate the reset loop and wait for it to finish - errc := make(chan error) - p.quit <- errc - if err := <-errc; err != nil { - errs = append(errs, err) - } - // Terminate each subpool - for _, subpool := range p.subpools { - if err := subpool.Close(); err != nil { - errs = append(errs, err) - } - } - // Unsubscribe anyone still listening for tx events - p.subs.Close() - - if len(errs) > 0 { - return fmt.Errorf("subpool close errors: %v", errs) - } - return nil -} - -// loop is the transaction pool's main event loop, waiting for and reacting to -// outside blockchain events as well as for various reporting and transaction -// eviction events. -func (p *TxPool) loop(head *types.Header, chain BlockChain) { - // Close the termination marker when the pool stops - defer close(p.term) - - // Subscribe to chain head events to trigger subpool resets - var ( - newHeadCh = make(chan core.ChainHeadEvent) - newHeadSub = chain.SubscribeChainHeadEvent(newHeadCh) - ) - defer newHeadSub.Unsubscribe() - - // Track the previous and current head to feed to an idle reset - var ( - oldHead = head - newHead = oldHead - ) - // Consume chain head events and start resets when none is running - var ( - resetBusy = make(chan struct{}, 1) // Allow 1 reset to run concurrently - resetDone = make(chan *types.Header) - - resetForced bool // Whether a forced reset was requested, only used in simulator mode - resetWaiter chan error // Channel waiting on a forced reset, only used in simulator mode - ) - // Notify the live reset waiter to not block if the txpool is closed. - defer func() { - if resetWaiter != nil { - resetWaiter <- errors.New("pool already terminated") - resetWaiter = nil - } - }() - var errc chan error - for errc == nil { - // Something interesting might have happened, run a reset if there is - // one needed but none is running. The resetter will run on its own - // goroutine to allow chain head events to be consumed contiguously. - if newHead != oldHead || resetForced { - // Try to inject a busy marker and start a reset if successful - select { - case resetBusy <- struct{}{}: - // Busy marker injected, start a new subpool reset - go func(oldHead, newHead *types.Header) { - for _, subpool := range p.subpools { - subpool.Reset(oldHead, newHead) - } - p.sbundles.ResetPoolData(newHead) - resetDone <- newHead - }(oldHead, newHead) - - // If the reset operation was explicitly requested, consider it - // being fulfilled and drop the request marker. If it was not, - // this is a noop. - resetForced = false - - default: - // Reset already running, wait until it finishes. - // - // Note, this will not drop any forced reset request. If a forced - // reset was requested, but we were busy, then when the currently - // running reset finishes, a new one will be spun up. - } - } - // Wait for the next chain head event or a previous reset finish - select { - case event := <-newHeadCh: - // Chain moved forward, store the head for later consumption - newHead = event.Block.Header() - - case head := <-resetDone: - // Previous reset finished, update the old head and allow a new reset - oldHead = head - <-resetBusy - - // If someone is waiting for a reset to finish, notify them, unless - // the forced op is still pending. In that case, wait another round - // of resets. - if resetWaiter != nil && !resetForced { - resetWaiter <- nil - resetWaiter = nil - } - - case errc = <-p.quit: - // Termination requested, break out on the next loop round - - case syncc := <-p.sync: - // Transaction pool is running inside a simulator, and we are about - // to create a new block. Request a forced sync operation to ensure - // that any running reset operation finishes to make block imports - // deterministic. On top of that, run a new reset operation to make - // transaction insertions deterministic instead of being stuck in a - // queue waiting for a reset. - resetForced = true - resetWaiter = syncc - } - } - // Notify the closer of termination (no error possible for now) - errc <- nil -} - -// SetGasTip updates the minimum gas tip required by the transaction pool for a -// new transaction, and drops all transactions below this threshold. -func (p *TxPool) SetGasTip(tip *big.Int) { - for _, subpool := range p.subpools { - subpool.SetGasTip(tip) - } -} - -// Has returns an indicator whether the pool has a transaction cached with the -// given hash. -func (p *TxPool) Has(hash common.Hash) bool { - for _, subpool := range p.subpools { - if subpool.Has(hash) { - return true - } - } - return false -} - -// Get returns a transaction if it is contained in the pool, or nil otherwise. -func (p *TxPool) Get(hash common.Hash) *types.Transaction { - for _, subpool := range p.subpools { - if tx := subpool.Get(hash); tx != nil { - return tx - } - } - return nil -} - -// Add enqueues a batch of transactions into the pool if they are valid. Due -// to the large transaction churn, add may postpone fully integrating the tx -// to a later point to batch multiple ones together. -func (p *TxPool) Add(txs []*types.Transaction, local bool, sync bool, private bool) []error { - // Split the input transactions between the subpools. It shouldn't really - // happen that we receive merged batches, but better graceful than strange - // errors. - // - // We also need to track how the transactions were split across the subpools, - // so we can piece back the returned errors into the original order. - txsets := make([][]*types.Transaction, len(p.subpools)) - splits := make([]int, len(txs)) - - for i, tx := range txs { - // Mark this transaction belonging to no-subpool - splits[i] = -1 - - // Try to find a subpool that accepts the transaction - for j, subpool := range p.subpools { - if subpool.Filter(tx) { - txsets[j] = append(txsets[j], tx) - splits[i] = j - break - } - } - } - // Add the transactions split apart to the individual subpools and piece - // back the errors into the original sort order. - errsets := make([][]error, len(p.subpools)) - for i := 0; i < len(p.subpools); i++ { - errsets[i] = p.subpools[i].Add(txsets[i], local, sync, private) - } - errs := make([]error, len(txs)) - for i, split := range splits { - // If the transaction was rejected by all subpools, mark it unsupported - if split == -1 { - errs[i] = core.ErrTxTypeNotSupported - continue - } - // Find which subpool handled it and pull in the corresponding error - errs[i] = errsets[split][0] - errsets[split] = errsets[split][1:] - } - return errs -} - -// Pending retrieves all currently processable transactions, grouped by origin -// account and sorted by nonce. -// -// The transactions can also be pre-filtered by the dynamic fee components to -// reduce allocations and load on downstream subsystems. -func (p *TxPool) Pending(filter PendingFilter) map[common.Address][]*LazyTransaction { - txs := make(map[common.Address][]*LazyTransaction) - for _, subpool := range p.subpools { - for addr, set := range subpool.Pending(filter) { - txs[addr] = set - } - } - return txs -} - -// SubscribeTransactions registers a subscription for new transaction events, -// supporting feeding only newly seen or also resurrected transactions. -func (p *TxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { - subs := make([]event.Subscription, len(p.subpools)) - for i, subpool := range p.subpools { - subs[i] = subpool.SubscribeTransactions(ch, reorgs) - } - return p.subs.Track(event.JoinSubscriptions(subs...)) -} - -// Nonce returns the next nonce of an account, with all transactions executable -// by the pool already applied on top. -func (p *TxPool) Nonce(addr common.Address) uint64 { - // Since (for now) accounts are unique to subpools, only one pool will have - // (at max) a non-state nonce. To avoid stateful lookups, just return the - // highest nonce for now. - var nonce uint64 - for _, subpool := range p.subpools { - if next := subpool.Nonce(addr); nonce < next { - nonce = next - } - } - return nonce -} - -// Stats retrieves the current pool stats, namely the number of pending and the -// number of queued (non-executable) transactions. -func (p *TxPool) Stats() (int, int) { - var runnable, blocked int - for _, subpool := range p.subpools { - run, block := subpool.Stats() - - runnable += run - blocked += block - } - return runnable, blocked -} - -// Content retrieves the data content of the transaction pool, returning all the -// pending as well as queued transactions, grouped by account and sorted by nonce. -func (p *TxPool) Content() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { - var ( - runnable = make(map[common.Address][]*types.Transaction) - blocked = make(map[common.Address][]*types.Transaction) - ) - for _, subpool := range p.subpools { - run, block := subpool.Content() - - for addr, txs := range run { - runnable[addr] = txs - } - for addr, txs := range block { - blocked[addr] = txs - } - } - return runnable, blocked -} - -// ContentFrom retrieves the data content of the transaction pool, returning the -// pending as well as queued transactions of this address, grouped by nonce. -func (p *TxPool) ContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { - for _, subpool := range p.subpools { - run, block := subpool.ContentFrom(addr) - if len(run) != 0 || len(block) != 0 { - return run, block - } - } - return []*types.Transaction{}, []*types.Transaction{} -} - -// Locals retrieves the accounts currently considered local by the pool. -func (p *TxPool) Locals() []common.Address { - // Retrieve the locals from each subpool and deduplicate them - locals := make(map[common.Address]struct{}) - for _, subpool := range p.subpools { - for _, local := range subpool.Locals() { - locals[local] = struct{}{} - } - } - // Flatten and return the deduplicated local set - flat := make([]common.Address, 0, len(locals)) - for local := range locals { - flat = append(flat, local) - } - return flat -} - -// Status returns the known status (unknown/pending/queued) of a transaction -// identified by its hash. -func (p *TxPool) Status(hash common.Hash) TxStatus { - for _, subpool := range p.subpools { - if status := subpool.Status(hash); status != TxStatusUnknown { - return status - } - } - return TxStatusUnknown -} - -// Sync is a helper method for unit tests or simulator runs where the chain events -// are arriving in quick succession, without any time in between them to run the -// internal background reset operations. This method will run an explicit reset -// operation to ensure the pool stabilises, thus avoiding flakey behavior. -// -// Note, do not use this in production / live code. In live code, the pool is -// meant to reset on a separate thread to avoid DoS vectors. -func (p *TxPool) Sync() error { - sync := make(chan error) - select { - case p.sync <- sync: - return <-sync - case <-p.term: - return errors.New("pool already terminated") - } -} - -func (p *TxPool) IsPrivateTxHash(hash common.Hash) bool { - for _, subpool := range p.subpools { - if subpool.IsPrivateTxHash(hash) { - return true - } - } - return false -} - -// MevBundle methods - -// AddMevBundle enqueues a bundle of transactions into the pool if they are valid. -func (p *TxPool) AddMevBundle(txs []*types.Transaction, blockNumber *big.Int, replacementUuid uuid.UUID, signingAddress common.Address, minTimestamp, maxTimestamp uint64, revertingTxHashes []common.Hash) error { - bundleHasher := sha3.NewLegacyKeccak256() - for _, tx := range txs { - _, err := bundleHasher.Write(tx.Hash().Bytes()) - if err != nil { - return err - } - } - bundleHash := common.BytesToHash(bundleHasher.Sum(nil)) - - p.bundleLock.Lock() - defer p.bundleLock.Unlock() - - p.mevBundles = append(p.mevBundles, types.MevBundle{ - Txs: txs, - BlockNumber: blockNumber, - Uuid: replacementUuid, - SigningAddress: signingAddress, - MinTimestamp: minTimestamp, - MaxTimestamp: maxTimestamp, - RevertingTxHashes: revertingTxHashes, - Hash: bundleHash, - }) - return nil -} - -func (p *TxPool) AddMevBundles(bundles []types.MevBundle) { - p.bundleLock.Lock() - defer p.bundleLock.Unlock() - - p.mevBundles = append(p.mevBundles, bundles...) -} - -// MevBundles returns a list of bundles valid for the given blockNumber/blockTimestamp -// also prunes bundles that are outdated -// Returns regular bundles and a function resolving to current cancellable bundles -func (p *TxPool) MevBundles(blockNumber *big.Int, blockTimestamp uint64) ([]types.MevBundle, chan []types.MevBundle) { - p.bundleLock.Lock() - defer p.bundleLock.Unlock() - - ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) - lubCh, errCh := p.fetchLatestCancellableBundles(ctx, blockNumber) - - // returned values - var ret []types.MevBundle - // rolled over values - var bundles []types.MevBundle - // (uuid, signingAddress) -> list of bundles - var uuidBundles = make(map[uuidBundleKey][]types.MevBundle) - - for _, bundle := range p.mevBundles { - // Prune outdated bundles - if (bundle.MaxTimestamp != 0 && blockTimestamp > bundle.MaxTimestamp) || blockNumber.Cmp(bundle.BlockNumber) > 0 { - continue - } - - // Roll over future bundles - if (bundle.MinTimestamp != 0 && blockTimestamp < bundle.MinTimestamp) || blockNumber.Cmp(bundle.BlockNumber) < 0 { - bundles = append(bundles, bundle) - continue - } - - // keep the bundles around internally until they need to be pruned - bundles = append(bundles, bundle) - - // TODO: omit duplicates - - // do not append to the return quite yet, check the DB for the latest bundle for that uuid - if bundle.Uuid != types.EmptyUUID { - ubk := uuidBundleKey{bundle.Uuid, bundle.SigningAddress} - uuidBundles[ubk] = append(uuidBundles[ubk], bundle) - continue - } - - // return the ones which are in time - ret = append(ret, bundle) - } - - p.mevBundles = bundles - - cancellableBundlesCh := make(chan []types.MevBundle, 1) - go func() { - cancellableBundlesCh <- resolveCancellableBundles(lubCh, errCh, uuidBundles) - cancel() - }() - - return ret, cancellableBundlesCh -} - -func (p *TxPool) AddSBundle(bundle *types.SBundle) error { - return p.sbundles.Add(bundle) -} - -func (p *TxPool) CancelSBundles(hashes []common.Hash) { - p.sbundles.Cancel(hashes) -} - -func (p *TxPool) GetSBundles(block *big.Int) []*types.SBundle { - return p.sbundles.GetSBundles(block.Uint64()) -} - -// Bundle Fetcher methods -func (p *TxPool) RegisterBundleFetcher(fetcher IFetcher) { - p.bundleLock.Lock() - defer p.bundleLock.Unlock() - - p.bundleFetcher = fetcher -} - -type uuidBundleKey struct { - Uuid uuid.UUID - SigningAddress common.Address -} - -func (p *TxPool) fetchLatestCancellableBundles(ctx context.Context, blockNumber *big.Int) (chan []types.LatestUuidBundle, chan error) { - if p.bundleFetcher == nil { - return nil, nil - } - errCh := make(chan error, 1) - lubCh := make(chan []types.LatestUuidBundle, 1) - go func(blockNum int64) { - lub, err := p.bundleFetcher.GetLatestUuidBundles(ctx, blockNum) - errCh <- err - lubCh <- lub - }(blockNumber.Int64()) - return lubCh, errCh -} - -func resolveCancellableBundles(lubCh chan []types.LatestUuidBundle, errCh chan error, uuidBundles map[uuidBundleKey][]types.MevBundle) []types.MevBundle { - if lubCh == nil || errCh == nil { - return nil - } - - if len(uuidBundles) == 0 { - return nil - } - - err := <-errCh - if err != nil { - log.Error("could not fetch latest bundles uuid map", "err", err) - return nil - } - - currentCancellableBundles := []types.MevBundle{} - - log.Trace("Processing uuid bundles", "uuidBundles", uuidBundles) - - lubs := <-lubCh -LubLoop: - for _, lub := range lubs { - ubk := uuidBundleKey{lub.Uuid, lub.SigningAddress} - bundles, found := uuidBundles[ubk] - if !found { - log.Trace("missing uuid bundle", "ubk", ubk) - continue - } - - // If lub has bundle_uuid set, and we can find corresponding bundle we prefer it, if not we fallback to bundle_hash equivalence - if lub.BundleUUID != types.EmptyUUID { - for _, bundle := range bundles { - if bundle.ComputeUUID() == lub.BundleUUID { - log.Trace("adding uuid bundle", "bundle hash", bundle.Hash.String(), "lub", lub) - currentCancellableBundles = append(currentCancellableBundles, bundle) - continue LubLoop - } - } - } - - for _, bundle := range bundles { - if bundle.Hash == lub.BundleHash { - log.Trace("adding uuid bundle", "bundle hash", bundle.Hash.String(), "lub", lub) - currentCancellableBundles = append(currentCancellableBundles, bundle) - break - } - } - } - return currentCancellableBundles -} diff --git a/builder/core/txpool/txpool_test.go b/builder/core/txpool/txpool_test.go deleted file mode 100644 index 9d92d7133..000000000 --- a/builder/core/txpool/txpool_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package txpool - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/google/uuid" - "github.com/stretchr/testify/require" -) - -// Tests that cancellable bundle prefers latest with the same bundle_uuid, but fallbacks to bundle_hash equality -func TestCancellableBundles(t *testing.T) { - mb1 := types.MevBundle{ - Txs: nil, - BlockNumber: big.NewInt(1), - Uuid: uuid.MustParse("2fa47a9c-1eb2-4189-b1b0-d79bf2d0fc83"), - SigningAddress: common.HexToAddress("0x1"), - MinTimestamp: 0, - MaxTimestamp: 0, - RevertingTxHashes: []common.Hash{common.HexToHash("0x111")}, - Hash: common.HexToHash("0x2"), - } - muid1 := mb1.ComputeUUID() - - mb2 := types.MevBundle{ - Txs: nil, - BlockNumber: big.NewInt(1), - Uuid: uuid.MustParse("2fa47a9c-1eb2-4189-b1b0-d79bf2d0fc83"), - SigningAddress: common.HexToAddress("0x1"), - MinTimestamp: 0, - MaxTimestamp: 0, - RevertingTxHashes: nil, - Hash: common.HexToHash("0x2"), - } - muid2 := mb2.ComputeUUID() - _ = muid2 - - mb3 := types.MevBundle{ - Txs: nil, - BlockNumber: big.NewInt(1), - Uuid: uuid.MustParse("e2b1132f-7948-4227-aac4-041e9192110a"), - SigningAddress: common.HexToAddress("0x1"), - MinTimestamp: 0, - MaxTimestamp: 0, - RevertingTxHashes: nil, - Hash: common.HexToHash("0x3"), - } - - lubCh := make(chan []types.LatestUuidBundle, 1) - errCh := make(chan error, 1) - go func() { - lub1 := types.LatestUuidBundle{ - Uuid: uuid.MustParse("2fa47a9c-1eb2-4189-b1b0-d79bf2d0fc83"), - SigningAddress: common.HexToAddress("0x1"), - BundleHash: common.HexToHash("0x2"), - BundleUUID: muid1, - } - lub2 := types.LatestUuidBundle{ - Uuid: uuid.MustParse("e2b1132f-7948-4227-aac4-041e9192110a"), - SigningAddress: common.HexToAddress("0x1"), - BundleHash: common.HexToHash("0x3"), - } - lubCh <- []types.LatestUuidBundle{lub1, lub2} - errCh <- nil - }() - - uuidBundles := make(map[uuidBundleKey][]types.MevBundle) - firstUuidBK := uuidBundleKey{ - Uuid: uuid.MustParse("2fa47a9c-1eb2-4189-b1b0-d79bf2d0fc83"), - SigningAddress: common.HexToAddress("0x1"), - } - secondUuidBK := uuidBundleKey{ - Uuid: uuid.MustParse("e2b1132f-7948-4227-aac4-041e9192110a"), - SigningAddress: common.HexToAddress("0x1"), - } - - uuidBundles[firstUuidBK] = []types.MevBundle{mb1, mb2} - uuidBundles[secondUuidBK] = []types.MevBundle{mb3} - - mbs := resolveCancellableBundles(lubCh, errCh, uuidBundles) - require.Equal(t, mbs[0], mb1) - require.Equal(t, mbs[1], mb3) -} diff --git a/builder/core/txpool/validation.go b/builder/core/txpool/validation.go deleted file mode 100644 index 8913859e8..000000000 --- a/builder/core/txpool/validation.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2023 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 txpool - -import ( - "crypto/sha256" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" -) - -var ( - // blobTxMinBlobGasPrice is the big.Int version of the configured protocol - // parameter to avoid constucting a new big integer for every transaction. - blobTxMinBlobGasPrice = big.NewInt(params.BlobTxMinBlobGasprice) -) - -// ValidationOptions define certain differences between transaction validation -// across the different pools without having to duplicate those checks. -type ValidationOptions struct { - Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules - - Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool - MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle - MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool -} - -// ValidateTransaction is a helper method to check whether a transaction is valid -// according to the consensus rules, but does not check state-dependent validation -// (balance, nonce, etc). -// -// This check is public to allow different transaction pools to check the basic -// rules without duplicating code and running the risk of missed updates. -func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types.Signer, opts *ValidationOptions) error { - // Ensure transactions not implemented by the calling pool are rejected - if opts.Accept&(1< opts.MaxSize { - return fmt.Errorf("%w: transaction size %v, limit %v", ErrOversizedData, tx.Size(), opts.MaxSize) - } - // Ensure only transactions that have been enabled are accepted - if !opts.Config.IsBerlin(head.Number) && tx.Type() != types.LegacyTxType { - return fmt.Errorf("%w: type %d rejected, pool not yet in Berlin", core.ErrTxTypeNotSupported, tx.Type()) - } - if !opts.Config.IsLondon(head.Number) && tx.Type() == types.DynamicFeeTxType { - return fmt.Errorf("%w: type %d rejected, pool not yet in London", core.ErrTxTypeNotSupported, tx.Type()) - } - if !opts.Config.IsCancun(head.Number, head.Time) && tx.Type() == types.BlobTxType { - return fmt.Errorf("%w: type %d rejected, pool not yet in Cancun", core.ErrTxTypeNotSupported, tx.Type()) - } - // Check whether the init code size has been exceeded - if opts.Config.IsShanghai(head.Number, head.Time) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) - } - // Transactions can't be negative. This may never happen using RLP decoded - // transactions but may occur for transactions created using the RPC. - if tx.Value().Sign() < 0 { - return ErrNegativeValue - } - // Ensure the transaction doesn't exceed the current block limit gas - if head.GasLimit < tx.Gas() { - return ErrGasLimit - } - // Sanity check for extremely large numbers (supported by RLP or RPC) - if tx.GasFeeCap().BitLen() > 256 { - return core.ErrFeeCapVeryHigh - } - if tx.GasTipCap().BitLen() > 256 { - return core.ErrTipVeryHigh - } - // Ensure gasFeeCap is greater than or equal to gasTipCap - if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 { - return core.ErrTipAboveFeeCap - } - // Make sure the transaction is signed properly - if _, err := types.Sender(signer, tx); err != nil { - return ErrInvalidSender - } - // Ensure the transaction has more gas than the bare minimum needed to cover - // the transaction metadata - intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time)) - if err != nil { - return err - } - if tx.Gas() < intrGas { - return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), intrGas) - } - // Ensure the gasprice is high enough to cover the requirement of the calling pool - if tx.GasTipCapIntCmp(opts.MinTip) < 0 { - return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrUnderpriced, tx.GasTipCap(), opts.MinTip) - } - if tx.Type() == types.BlobTxType { - // Ensure the blob fee cap satisfies the minimum blob gas price - if tx.BlobGasFeeCapIntCmp(blobTxMinBlobGasPrice) < 0 { - return fmt.Errorf("%w: blob fee cap %v, minimum needed %v", ErrUnderpriced, tx.BlobGasFeeCap(), blobTxMinBlobGasPrice) - } - sidecar := tx.BlobTxSidecar() - if sidecar == nil { - return fmt.Errorf("missing sidecar in blob transaction") - } - // Ensure the number of items in the blob transaction and various side - // data match up before doing any expensive validations - hashes := tx.BlobHashes() - if len(hashes) == 0 { - return fmt.Errorf("blobless blob transaction") - } - if len(hashes) > params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob { - return fmt.Errorf("too many blobs in transaction: have %d, permitted %d", len(hashes), params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob) - } - // Ensure commitments, proofs and hashes are valid - if err := validateBlobSidecar(hashes, sidecar); err != nil { - return err - } - } - return nil -} - -func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) error { - if len(sidecar.Blobs) != len(hashes) { - return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(sidecar.Blobs), len(hashes)) - } - if len(sidecar.Commitments) != len(hashes) { - return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(sidecar.Commitments), len(hashes)) - } - if len(sidecar.Proofs) != len(hashes) { - return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(sidecar.Proofs), len(hashes)) - } - // Blob quantities match up, validate that the provers match with the - // transaction hash before getting to the cryptography - hasher := sha256.New() - for i, vhash := range hashes { - computed := kzg4844.CalcBlobHashV1(hasher, &sidecar.Commitments[i]) - if vhash != computed { - return fmt.Errorf("blob %d: computed hash %#x mismatches transaction one %#x", i, computed, vhash) - } - } - // Blob commitments match with the hashes in the transaction, verify the - // blobs themselves via KZG - for i := range sidecar.Blobs { - if err := kzg4844.VerifyBlobProof(sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil { - return fmt.Errorf("invalid blob %d: %v", i, err) - } - } - return nil -} - -// ValidationOptionsWithState define certain differences between stateful transaction -// validation across the different pools without having to duplicate those checks. -type ValidationOptionsWithState struct { - State *state.StateDB // State database to check nonces and balances against - - // FirstNonceGap is an optional callback to retrieve the first nonce gap in - // the list of pooled transactions of a specific account. If this method is - // set, nonce gaps will be checked and forbidden. If this method is not set, - // nonce gaps will be ignored and permitted. - FirstNonceGap func(addr common.Address) uint64 - - // UsedAndLeftSlots is a mandatory callback to retrieve the number of tx slots - // used and the number still permitted for an account. New transactions will - // be rejected once the number of remaining slots reaches zero. - UsedAndLeftSlots func(addr common.Address) (int, int) - - // ExistingExpenditure is a mandatory callback to retrieve the cumulative - // cost of the already pooled transactions to check for overdrafts. - ExistingExpenditure func(addr common.Address) *big.Int - - // ExistingCost is a mandatory callback to retrieve an already pooled - // transaction's cost with the given nonce to check for overdrafts. - ExistingCost func(addr common.Address, nonce uint64) *big.Int -} - -// ValidateTransactionWithState is a helper method to check whether a transaction -// is valid according to the pool's internal state checks (balance, nonce, gaps). -// -// This check is public to allow different transaction pools to check the stateful -// rules without duplicating code and running the risk of missed updates. -func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, opts *ValidationOptionsWithState) error { - // Ensure the transaction adheres to nonce ordering - from, err := signer.Sender(tx) // already validated (and cached), but cleaner to check - if err != nil { - log.Error("Transaction sender recovery failed", "err", err) - return err - } - next := opts.State.GetNonce(from) - if next > tx.Nonce() { - return fmt.Errorf("%w: next nonce %v, tx nonce %v", core.ErrNonceTooLow, next, tx.Nonce()) - } - // Ensure the transaction doesn't produce a nonce gap in pools that do not - // support arbitrary orderings - if opts.FirstNonceGap != nil { - if gap := opts.FirstNonceGap(from); gap < tx.Nonce() { - return fmt.Errorf("%w: tx nonce %v, gapped nonce %v", core.ErrNonceTooHigh, tx.Nonce(), gap) - } - } - // Ensure the transactor has enough funds to cover the transaction costs - var ( - balance = opts.State.GetBalance(from).ToBig() - cost = tx.Cost() - ) - if balance.Cmp(cost) < 0 { - return fmt.Errorf("%w: balance %v, tx cost %v, overshot %v", core.ErrInsufficientFunds, balance, cost, new(big.Int).Sub(cost, balance)) - } - // Ensure the transactor has enough funds to cover for replacements or nonce - // expansions without overdrafts - spent := opts.ExistingExpenditure(from) - if prev := opts.ExistingCost(from, tx.Nonce()); prev != nil { - bump := new(big.Int).Sub(cost, prev) - need := new(big.Int).Add(spent, bump) - if balance.Cmp(need) < 0 { - return fmt.Errorf("%w: balance %v, queued cost %v, tx bumped %v, overshot %v", core.ErrInsufficientFunds, balance, spent, bump, new(big.Int).Sub(need, balance)) - } - } else { - need := new(big.Int).Add(spent, cost) - if balance.Cmp(need) < 0 { - return fmt.Errorf("%w: balance %v, queued cost %v, tx cost %v, overshot %v", core.ErrInsufficientFunds, balance, spent, cost, new(big.Int).Sub(need, balance)) - } - // Transaction takes a new nonce value out of the pool. Ensure it doesn't - // overflow the number of permitted transactions from a single account - // (i.e. max cancellable via out-of-bound transaction). - if used, left := opts.UsedAndLeftSlots(from); left <= 0 { - return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used) - } - } - return nil -} diff --git a/builder/core/types.go b/builder/core/types.go deleted file mode 100644 index 36eb0d1de..000000000 --- a/builder/core/types.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 core - -import ( - "sync/atomic" - - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" -) - -// Validator is an interface which defines the standard for block validation. It -// is only responsible for validating block contents, as the header validation is -// done by the specific consensus engines. -type Validator interface { - // ValidateBody validates the given block's content. - ValidateBody(block *types.Block) error - - // ValidateState validates the given statedb and optionally the receipts and - // gas used. - ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error -} - -// Prefetcher is an interface for pre-caching transaction signatures and state. -type Prefetcher interface { - // Prefetch processes the state changes according to the Ethereum rules by running - // the transaction messages using the statedb, but any changes are discarded. The - // only goal is to pre-cache transaction signatures and state trie nodes. - Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) -} - -// Processor is an interface for processing blocks using a given initial state. -type Processor interface { - // Process processes the state changes according to the Ethereum rules by running - // the transaction messages using the statedb and applying any rewards to both - // the processor (coinbase) and any included uncles. - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) -} diff --git a/builder/core/types/account.go b/builder/core/types/account.go deleted file mode 100644 index bb0f4ca02..000000000 --- a/builder/core/types/account.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2024 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 types - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" -) - -//go:generate go run github.com/fjl/gencodec -type Account -field-override accountMarshaling -out gen_account.go - -// Account represents an Ethereum account and its attached data. -// This type is used to specify accounts in the genesis block state, and -// is also useful for JSON encoding/decoding of accounts. -type Account struct { - Code []byte `json:"code,omitempty"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty"` - Balance *big.Int `json:"balance" gencodec:"required"` - Nonce uint64 `json:"nonce,omitempty"` - - // used in tests - PrivateKey []byte `json:"secretKey,omitempty"` -} - -type accountMarshaling struct { - Code hexutil.Bytes - Balance *math.HexOrDecimal256 - Nonce math.HexOrDecimal64 - Storage map[storageJSON]storageJSON - PrivateKey hexutil.Bytes -} - -// storageJSON represents a 256 bit byte array, but allows less than 256 bits when -// unmarshaling from hex. -type storageJSON common.Hash - -func (h *storageJSON) UnmarshalText(text []byte) error { - text = bytes.TrimPrefix(text, []byte("0x")) - if len(text) > 64 { - return fmt.Errorf("too many hex characters in storage key/value %q", text) - } - offset := len(h) - len(text)/2 // pad on the left - if _, err := hex.Decode(h[offset:], text); err != nil { - return fmt.Errorf("invalid hex storage key/value %q", text) - } - return nil -} - -func (h storageJSON) MarshalText() ([]byte, error) { - return hexutil.Bytes(h[:]).MarshalText() -} - -// GenesisAlloc specifies the initial state of a genesis block. -type GenesisAlloc map[common.Address]Account - -func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { - m := make(map[common.UnprefixedAddress]Account) - if err := json.Unmarshal(data, &m); err != nil { - return err - } - *ga = make(GenesisAlloc) - for addr, a := range m { - (*ga)[common.Address(addr)] = a - } - return nil -} diff --git a/builder/core/types/block.go b/builder/core/types/block.go deleted file mode 100644 index 1a357baa3..000000000 --- a/builder/core/types/block.go +++ /dev/null @@ -1,514 +0,0 @@ -// 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 types contains data types related to Ethereum consensus. -package types - -import ( - "encoding/binary" - "fmt" - "io" - "math/big" - "reflect" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rlp" -) - -// A BlockNonce is a 64-bit hash which proves (combined with the -// mix-hash) that a sufficient amount of computation has been carried -// out on a block. -type BlockNonce [8]byte - -// EncodeNonce converts the given integer to a block nonce. -func EncodeNonce(i uint64) BlockNonce { - var n BlockNonce - binary.BigEndian.PutUint64(n[:], i) - return n -} - -// Uint64 returns the integer value of a block nonce. -func (n BlockNonce) Uint64() uint64 { - return binary.BigEndian.Uint64(n[:]) -} - -// MarshalText encodes n as a hex string with 0x prefix. -func (n BlockNonce) MarshalText() ([]byte, error) { - return hexutil.Bytes(n[:]).MarshalText() -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (n *BlockNonce) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("BlockNonce", input, n[:]) -} - -//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go -//go:generate go run ../../rlp/rlpgen -type Header -out gen_header_rlp.go - -// Header represents a block header in the Ethereum blockchain. -type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *big.Int `json:"difficulty" gencodec:"required"` - Number *big.Int `json:"number" gencodec:"required"` - GasLimit uint64 `json:"gasLimit" gencodec:"required"` - GasUsed uint64 `json:"gasUsed" gencodec:"required"` - Time uint64 `json:"timestamp" gencodec:"required"` - Extra []byte `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - - // BaseFee was added by EIP-1559 and is ignored in legacy headers. - BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"` - - // WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers. - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - - // BlobGasUsed was added by EIP-4844 and is ignored in legacy headers. - BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` - - // ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers. - ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` - - // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` -} - -// field type overrides for gencodec -type headerMarshaling struct { - Difficulty *hexutil.Big - Number *hexutil.Big - GasLimit hexutil.Uint64 - GasUsed hexutil.Uint64 - Time hexutil.Uint64 - Extra hexutil.Bytes - BaseFee *hexutil.Big - Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON - BlobGasUsed *hexutil.Uint64 - ExcessBlobGas *hexutil.Uint64 -} - -// Hash returns the block hash of the header, which is simply the keccak256 hash of its -// RLP encoding. -func (h *Header) Hash() common.Hash { - return rlpHash(h) -} - -var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) - -// Size returns the approximate memory used by all internal contents. It is used -// to approximate and limit the memory consumption of various caches. -func (h *Header) Size() common.StorageSize { - var baseFeeBits int - if h.BaseFee != nil { - baseFeeBits = h.BaseFee.BitLen() - } - return headerSize + common.StorageSize(len(h.Extra)+(h.Difficulty.BitLen()+h.Number.BitLen()+baseFeeBits)/8) -} - -// SanityCheck checks a few basic things -- these checks are way beyond what -// any 'sane' production values should hold, and can mainly be used to prevent -// that the unbounded fields are stuffed with junk data to add processing -// overhead -func (h *Header) SanityCheck() error { - if h.Number != nil && !h.Number.IsUint64() { - return fmt.Errorf("too large block number: bitlen %d", h.Number.BitLen()) - } - if h.Difficulty != nil { - if diffLen := h.Difficulty.BitLen(); diffLen > 80 { - return fmt.Errorf("too large block difficulty: bitlen %d", diffLen) - } - } - if eLen := len(h.Extra); eLen > 100*1024 { - return fmt.Errorf("too large block extradata: size %d", eLen) - } - if h.BaseFee != nil { - if bfLen := h.BaseFee.BitLen(); bfLen > 256 { - return fmt.Errorf("too large base fee: bitlen %d", bfLen) - } - } - return nil -} - -// EmptyBody returns true if there is no additional 'body' to complete the header -// that is: no transactions, no uncles and no withdrawals. -func (h *Header) EmptyBody() bool { - if h.WithdrawalsHash != nil { - return h.TxHash == EmptyTxsHash && *h.WithdrawalsHash == EmptyWithdrawalsHash - } - return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash -} - -// EmptyReceipts returns true if there are no receipts for this header/block. -func (h *Header) EmptyReceipts() bool { - return h.ReceiptHash == EmptyReceiptsHash -} - -// Body is a simple (mutable, non-safe) data container for storing and moving -// a block's data contents (transactions and uncles) together. -type Body struct { - Transactions []*Transaction - Uncles []*Header - Withdrawals []*Withdrawal `rlp:"optional"` -} - -// Block represents an Ethereum block. -// -// Note the Block type tries to be 'immutable', and contains certain caches that rely -// on that. The rules around block immutability are as follows: -// -// - We copy all data when the block is constructed. This makes references held inside -// the block independent of whatever value was passed in. -// -// - We copy all header data on access. This is because any change to the header would mess -// up the cached hash and size values in the block. Calling code is expected to take -// advantage of this to avoid over-allocating! -// -// - When new body data is attached to the block, a shallow copy of the block is returned. -// This ensures block modifications are race-free. -// -// - We do not copy body data on access because it does not affect the caches, and also -// because it would be too expensive. -type Block struct { - header *Header - uncles []*Header - transactions Transactions - withdrawals Withdrawals - - // caches - hash atomic.Value - size atomic.Value - - // These fields are used by package eth to track - // inter-peer block relay. - ReceivedAt time.Time - ReceivedFrom interface{} -} - -// "external" block encoding. used for eth protocol, etc. -type extblock struct { - Header *Header - Txs []*Transaction - Uncles []*Header - Withdrawals []*Withdrawal `rlp:"optional"` -} - -// NewBlock creates a new block. The input data is copied, changes to header and to the -// field values will not affect the block. -// -// The values of TxHash, UncleHash, ReceiptHash and Bloom in header -// are ignored and set to values derived from the given txs, uncles -// and receipts. -func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, hasher TrieHasher) *Block { - b := &Block{header: CopyHeader(header)} - - // TODO: panic if len(txs) != len(receipts) - if len(txs) == 0 { - b.header.TxHash = EmptyTxsHash - } else { - b.header.TxHash = DeriveSha(Transactions(txs), hasher) - b.transactions = make(Transactions, len(txs)) - copy(b.transactions, txs) - } - - if len(receipts) == 0 { - b.header.ReceiptHash = EmptyReceiptsHash - } else { - b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) - b.header.Bloom = CreateBloom(receipts) - } - - if len(uncles) == 0 { - b.header.UncleHash = EmptyUncleHash - } else { - b.header.UncleHash = CalcUncleHash(uncles) - b.uncles = make([]*Header, len(uncles)) - for i := range uncles { - b.uncles[i] = CopyHeader(uncles[i]) - } - } - - return b -} - -// NewBlockWithWithdrawals creates a new block with withdrawals. The input data is copied, -// changes to header and to the field values will not affect the block. -// -// The values of TxHash, UncleHash, ReceiptHash and Bloom in header are ignored and set to -// values derived from the given txs, uncles and receipts. -func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal, hasher TrieHasher) *Block { - b := NewBlock(header, txs, uncles, receipts, hasher) - - if withdrawals == nil { - b.header.WithdrawalsHash = nil - } else if len(withdrawals) == 0 { - b.header.WithdrawalsHash = &EmptyWithdrawalsHash - } else { - h := DeriveSha(Withdrawals(withdrawals), hasher) - b.header.WithdrawalsHash = &h - } - - return b.WithWithdrawals(withdrawals) -} - -// CopyHeader creates a deep copy of a block header. -func CopyHeader(h *Header) *Header { - cpy := *h - if cpy.Difficulty = new(big.Int); h.Difficulty != nil { - cpy.Difficulty.Set(h.Difficulty) - } - if cpy.Number = new(big.Int); h.Number != nil { - cpy.Number.Set(h.Number) - } - if h.BaseFee != nil { - cpy.BaseFee = new(big.Int).Set(h.BaseFee) - } - if len(h.Extra) > 0 { - cpy.Extra = make([]byte, len(h.Extra)) - copy(cpy.Extra, h.Extra) - } - if h.WithdrawalsHash != nil { - cpy.WithdrawalsHash = new(common.Hash) - *cpy.WithdrawalsHash = *h.WithdrawalsHash - } - if h.ExcessBlobGas != nil { - cpy.ExcessBlobGas = new(uint64) - *cpy.ExcessBlobGas = *h.ExcessBlobGas - } - if h.BlobGasUsed != nil { - cpy.BlobGasUsed = new(uint64) - *cpy.BlobGasUsed = *h.BlobGasUsed - } - if h.ParentBeaconRoot != nil { - cpy.ParentBeaconRoot = new(common.Hash) - *cpy.ParentBeaconRoot = *h.ParentBeaconRoot - } - return &cpy -} - -// DecodeRLP decodes a block from RLP. -func (b *Block) DecodeRLP(s *rlp.Stream) error { - var eb extblock - _, size, _ := s.Kind() - if err := s.Decode(&eb); err != nil { - return err - } - b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals - b.size.Store(rlp.ListSize(size)) - return nil -} - -// EncodeRLP serializes a block as RLP. -func (b *Block) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, &extblock{ - Header: b.header, - Txs: b.transactions, - Uncles: b.uncles, - Withdrawals: b.withdrawals, - }) -} - -// Body returns the non-header content of the block. -// Note the returned data is not an independent copy. -func (b *Block) Body() *Body { - return &Body{b.transactions, b.uncles, b.withdrawals} -} - -// Accessors for body data. These do not return a copy because the content -// of the body slices does not affect the cached hash/size in block. - -func (b *Block) Uncles() []*Header { return b.uncles } -func (b *Block) Transactions() Transactions { return b.transactions } -func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } - -func (b *Block) Transaction(hash common.Hash) *Transaction { - for _, transaction := range b.transactions { - if transaction.Hash() == hash { - return transaction - } - } - return nil -} - -// Header returns the block header (as a copy). -func (b *Block) Header() *Header { - return CopyHeader(b.header) -} - -// Header value accessors. These do copy! - -func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } -func (b *Block) GasLimit() uint64 { return b.header.GasLimit } -func (b *Block) GasUsed() uint64 { return b.header.GasUsed } -func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } -func (b *Block) Time() uint64 { return b.header.Time } - -func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } -func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } -func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } -func (b *Block) Bloom() Bloom { return b.header.Bloom } -func (b *Block) Coinbase() common.Address { return b.header.Coinbase } -func (b *Block) Root() common.Hash { return b.header.Root } -func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } -func (b *Block) TxHash() common.Hash { return b.header.TxHash } -func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash } -func (b *Block) UncleHash() common.Hash { return b.header.UncleHash } -func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } - -func (b *Block) BaseFee() *big.Int { - if b.header.BaseFee == nil { - return nil - } - return new(big.Int).Set(b.header.BaseFee) -} - -func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot } - -func (b *Block) ExcessBlobGas() *uint64 { - var excessBlobGas *uint64 - if b.header.ExcessBlobGas != nil { - excessBlobGas = new(uint64) - *excessBlobGas = *b.header.ExcessBlobGas - } - return excessBlobGas -} - -func (b *Block) BlobGasUsed() *uint64 { - var blobGasUsed *uint64 - if b.header.BlobGasUsed != nil { - blobGasUsed = new(uint64) - *blobGasUsed = *b.header.BlobGasUsed - } - return blobGasUsed -} - -// Size returns the true RLP encoded storage size of the block, either by encoding -// and returning it, or returning a previously cached value. -func (b *Block) Size() uint64 { - if size := b.size.Load(); size != nil { - return size.(uint64) - } - c := writeCounter(0) - rlp.Encode(&c, b) - b.size.Store(uint64(c)) - return uint64(c) -} - -// SanityCheck can be used to prevent that unbounded fields are -// stuffed with junk data to add processing overhead -func (b *Block) SanityCheck() error { - return b.header.SanityCheck() -} - -type writeCounter uint64 - -func (c *writeCounter) Write(b []byte) (int, error) { - *c += writeCounter(len(b)) - return len(b), nil -} - -func CalcUncleHash(uncles []*Header) common.Hash { - if len(uncles) == 0 { - return EmptyUncleHash - } - return rlpHash(uncles) -} - -// NewBlockWithHeader creates a block with the given header data. The -// header data is copied, changes to header and to the field values -// will not affect the block. -func NewBlockWithHeader(header *Header) *Block { - return &Block{header: CopyHeader(header)} -} - -// WithSeal returns a new block with the data from b but the header replaced with -// the sealed one. -func (b *Block) WithSeal(header *Header) *Block { - return &Block{ - header: CopyHeader(header), - transactions: b.transactions, - uncles: b.uncles, - withdrawals: b.withdrawals, - } -} - -// WithBody returns a copy of the block with the given transaction and uncle contents. -func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block { - block := &Block{ - header: b.header, - transactions: make([]*Transaction, len(transactions)), - uncles: make([]*Header, len(uncles)), - withdrawals: b.withdrawals, - } - copy(block.transactions, transactions) - for i := range uncles { - block.uncles[i] = CopyHeader(uncles[i]) - } - return block -} - -// WithWithdrawals returns a copy of the block containing the given withdrawals. -func (b *Block) WithWithdrawals(withdrawals []*Withdrawal) *Block { - block := &Block{ - header: b.header, - transactions: b.transactions, - uncles: b.uncles, - } - if withdrawals != nil { - block.withdrawals = make([]*Withdrawal, len(withdrawals)) - copy(block.withdrawals, withdrawals) - } - return block -} - -// Hash returns the keccak256 hash of b's header. -// The hash is computed on the first call and cached thereafter. -func (b *Block) Hash() common.Hash { - if hash := b.hash.Load(); hash != nil { - return hash.(common.Hash) - } - v := b.header.Hash() - b.hash.Store(v) - return v -} - -type Blocks []*Block - -// HeaderParentHashFromRLP returns the parentHash of an RLP-encoded -// header. If 'header' is invalid, the zero hash is returned. -func HeaderParentHashFromRLP(header []byte) common.Hash { - // parentHash is the first list element. - listContent, _, err := rlp.SplitList(header) - if err != nil { - return common.Hash{} - } - parentHash, _, err := rlp.SplitString(listContent) - if err != nil { - return common.Hash{} - } - if len(parentHash) != 32 { - return common.Hash{} - } - return common.BytesToHash(parentHash) -} diff --git a/builder/core/types/block_test.go b/builder/core/types/block_test.go deleted file mode 100644 index cf0b1dd85..000000000 --- a/builder/core/types/block_test.go +++ /dev/null @@ -1,319 +0,0 @@ -// 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 types - -import ( - "bytes" - "math/big" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/blocktest" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -// from bcValidBlockTest.json, "SimpleTx" -func TestBlockEncoding(t *testing.T) { - blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0") - var block Block - if err := rlp.DecodeBytes(blockEnc, &block); err != nil { - t.Fatal("decode error: ", err) - } - - check := func(f string, got, want interface{}) { - if !reflect.DeepEqual(got, want) { - t.Errorf("%s mismatch: got %v, want %v", f, got, want) - } - } - check("Difficulty", block.Difficulty(), big.NewInt(131072)) - check("GasLimit", block.GasLimit(), uint64(3141592)) - check("GasUsed", block.GasUsed(), uint64(21000)) - check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1")) - check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) - check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) - check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e")) - check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4)) - check("Time", block.Time(), uint64(1426516743)) - check("Size", block.Size(), uint64(len(blockEnc))) - - tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) - tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) - check("len(Transactions)", len(block.Transactions()), 1) - check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash()) - ourBlockEnc, err := rlp.EncodeToBytes(&block) - if err != nil { - t.Fatal("encode error: ", err) - } - if !bytes.Equal(ourBlockEnc, blockEnc) { - t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc) - } -} - -func TestEIP1559BlockEncoding(t *testing.T) { - blockEnc := common.FromHex("f9030bf901fea083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4843b9aca00f90106f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b8a302f8a0018080843b9aca008301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000080a0fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b0a06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a8c0") - var block Block - if err := rlp.DecodeBytes(blockEnc, &block); err != nil { - t.Fatal("decode error: ", err) - } - - check := func(f string, got, want interface{}) { - if !reflect.DeepEqual(got, want) { - t.Errorf("%s mismatch: got %v, want %v", f, got, want) - } - } - - check("Difficulty", block.Difficulty(), big.NewInt(131072)) - check("GasLimit", block.GasLimit(), uint64(3141592)) - check("GasUsed", block.GasUsed(), uint64(21000)) - check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1")) - check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) - check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) - check("Hash", block.Hash(), common.HexToHash("c7252048cd273fe0dac09650027d07f0e3da4ee0675ebbb26627cea92729c372")) - check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4)) - check("Time", block.Time(), uint64(1426516743)) - check("Size", block.Size(), uint64(len(blockEnc))) - check("BaseFee", block.BaseFee(), new(big.Int).SetUint64(params.InitialBaseFee)) - - tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), 50000, big.NewInt(10), nil) - tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100")) - - addr := common.HexToAddress("0x0000000000000000000000000000000000000001") - accesses := AccessList{AccessTuple{ - Address: addr, - StorageKeys: []common.Hash{ - {0}, - }, - }} - to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - txdata := &DynamicFeeTx{ - ChainID: big.NewInt(1), - Nonce: 0, - To: &to, - Gas: 123457, - GasFeeCap: new(big.Int).Set(block.BaseFee()), - GasTipCap: big.NewInt(0), - AccessList: accesses, - Data: []byte{}, - } - tx2 := NewTx(txdata) - tx2, err := tx2.WithSignature(LatestSignerForChainID(big.NewInt(1)), common.Hex2Bytes("fe38ca4e44a30002ac54af7cf922a6ac2ba11b7d22f548e8ecb3f51f41cb31b06de6a5cbae13c0c856e33acf021b51819636cfc009d39eafb9f606d546e305a800")) - if err != nil { - t.Fatal("invalid signature error: ", err) - } - - check("len(Transactions)", len(block.Transactions()), 2) - check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash()) - check("Transactions[1].Hash", block.Transactions()[1].Hash(), tx2.Hash()) - check("Transactions[1].Type", block.Transactions()[1].Type(), tx2.Type()) - ourBlockEnc, err := rlp.EncodeToBytes(&block) - if err != nil { - t.Fatal("encode error: ", err) - } - if !bytes.Equal(ourBlockEnc, blockEnc) { - t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc) - } -} - -func TestEIP2718BlockEncoding(t *testing.T) { - blockEnc := common.FromHex("f90319f90211a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a0e6e49996c7ec59f7a23d22b83239a60151512c65613bf84a0d7da336399ebc4aa0cafe75574d59780665a97fbfd11365c7545aa8f1abf4e5e12e8243334ef7286bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000820200832fefd882a410845506eb0796636f6f6c65737420626c6f636b206f6e20636861696ea0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f90101f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1b89e01f89b01800a8301e24194095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f7940000000000000000000000000000000000000001e1a0000000000000000000000000000000000000000000000000000000000000000001a03dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335a0476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef14c0") - var block Block - if err := rlp.DecodeBytes(blockEnc, &block); err != nil { - t.Fatal("decode error: ", err) - } - - check := func(f string, got, want interface{}) { - if !reflect.DeepEqual(got, want) { - t.Errorf("%s mismatch: got %v, want %v", f, got, want) - } - } - check("Difficulty", block.Difficulty(), big.NewInt(131072)) - check("GasLimit", block.GasLimit(), uint64(3141592)) - check("GasUsed", block.GasUsed(), uint64(42000)) - check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1")) - check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498")) - check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017")) - check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4)) - check("Time", block.Time(), uint64(1426516743)) - check("Size", block.Size(), uint64(len(blockEnc))) - - // Create legacy tx. - to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - tx1 := NewTx(&LegacyTx{ - Nonce: 0, - To: &to, - Value: big.NewInt(10), - Gas: 50000, - GasPrice: big.NewInt(10), - }) - sig := common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100") - tx1, _ = tx1.WithSignature(HomesteadSigner{}, sig) - - // Create ACL tx. - addr := common.HexToAddress("0x0000000000000000000000000000000000000001") - tx2 := NewTx(&AccessListTx{ - ChainID: big.NewInt(1), - Nonce: 0, - To: &to, - Gas: 123457, - GasPrice: big.NewInt(10), - AccessList: AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}}, - }) - sig2 := common.Hex2Bytes("3dbacc8d0259f2508625e97fdfc57cd85fdd16e5821bc2c10bdd1a52649e8335476e10695b183a87b0aa292a7f4b78ef0c3fbe62aa2c42c84e1d9c3da159ef1401") - tx2, _ = tx2.WithSignature(NewEIP2930Signer(big.NewInt(1)), sig2) - - check("len(Transactions)", len(block.Transactions()), 2) - check("Transactions[0].Hash", block.Transactions()[0].Hash(), tx1.Hash()) - check("Transactions[1].Hash", block.Transactions()[1].Hash(), tx2.Hash()) - check("Transactions[1].Type()", block.Transactions()[1].Type(), uint8(AccessListTxType)) - - ourBlockEnc, err := rlp.EncodeToBytes(&block) - if err != nil { - t.Fatal("encode error: ", err) - } - if !bytes.Equal(ourBlockEnc, blockEnc) { - t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc) - } -} - -func TestUncleHash(t *testing.T) { - uncles := make([]*Header, 0) - h := CalcUncleHash(uncles) - exp := common.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - if h != exp { - t.Fatalf("empty uncle hash is wrong, got %x != %x", h, exp) - } -} - -var benchBuffer = bytes.NewBuffer(make([]byte, 0, 32000)) - -func BenchmarkEncodeBlock(b *testing.B) { - block := makeBenchBlock() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - benchBuffer.Reset() - if err := rlp.Encode(benchBuffer, block); err != nil { - b.Fatal(err) - } - } -} - -func makeBenchBlock() *Block { - var ( - key, _ = crypto.GenerateKey() - txs = make([]*Transaction, 70) - receipts = make([]*Receipt, len(txs)) - signer = LatestSigner(params.TestChainConfig) - uncles = make([]*Header, 3) - ) - header := &Header{ - Difficulty: math.BigPow(11, 11), - Number: math.BigPow(2, 9), - GasLimit: 12345678, - GasUsed: 1476322, - Time: 9876543, - Extra: []byte("coolest block on chain"), - } - for i := range txs { - amount := math.BigPow(2, int64(i)) - price := big.NewInt(300000) - data := make([]byte, 100) - tx := NewTransaction(uint64(i), common.Address{}, amount, 123457, price, data) - signedTx, err := SignTx(tx, signer, key) - if err != nil { - panic(err) - } - txs[i] = signedTx - receipts[i] = NewReceipt(make([]byte, 32), false, tx.Gas()) - } - for i := range uncles { - uncles[i] = &Header{ - Difficulty: math.BigPow(11, 11), - Number: math.BigPow(2, 9), - GasLimit: 12345678, - GasUsed: 1476322, - Time: 9876543, - Extra: []byte("benchmark uncle"), - } - } - return NewBlock(header, txs, uncles, receipts, blocktest.NewHasher()) -} - -func TestRlpDecodeParentHash(t *testing.T) { - // A minimum one - want := common.HexToHash("0x112233445566778899001122334455667788990011223344556677889900aabb") - if rlpData, err := rlp.EncodeToBytes(&Header{ParentHash: want}); err != nil { - t.Fatal(err) - } else { - if have := HeaderParentHashFromRLP(rlpData); have != want { - t.Fatalf("have %x, want %x", have, want) - } - } - // And a maximum one - // | Difficulty | dynamic| *big.Int | 0x5ad3c2c71bbff854908 (current mainnet TD: 76 bits) | - // | Number | dynamic| *big.Int | 64 bits | - // | Extra | dynamic| []byte | 65+32 byte (clique) | - // | BaseFee | dynamic| *big.Int | 64 bits | - mainnetTd := new(big.Int) - mainnetTd.SetString("5ad3c2c71bbff854908", 16) - if rlpData, err := rlp.EncodeToBytes(&Header{ - ParentHash: want, - Difficulty: mainnetTd, - Number: new(big.Int).SetUint64(math.MaxUint64), - Extra: make([]byte, 65+32), - BaseFee: new(big.Int).SetUint64(math.MaxUint64), - }); err != nil { - t.Fatal(err) - } else { - if have := HeaderParentHashFromRLP(rlpData); have != want { - t.Fatalf("have %x, want %x", have, want) - } - } - // Also test a very very large header. - { - // The rlp-encoding of the header belowCauses _total_ length of 65540, - // which is the first to blow the fast-path. - h := &Header{ - ParentHash: want, - Extra: make([]byte, 65041), - } - if rlpData, err := rlp.EncodeToBytes(h); err != nil { - t.Fatal(err) - } else { - if have := HeaderParentHashFromRLP(rlpData); have != want { - t.Fatalf("have %x, want %x", have, want) - } - } - } - { - // Test some invalid erroneous stuff - for i, rlpData := range [][]byte{ - nil, - common.FromHex("0x"), - common.FromHex("0x01"), - common.FromHex("0x3031323334"), - } { - if have, want := HeaderParentHashFromRLP(rlpData), (common.Hash{}); have != want { - t.Fatalf("invalid %d: have %x, want %x", i, have, want) - } - } - } -} diff --git a/builder/core/types/bloom9.go b/builder/core/types/bloom9.go deleted file mode 100644 index a560a2072..000000000 --- a/builder/core/types/bloom9.go +++ /dev/null @@ -1,160 +0,0 @@ -// 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 types - -import ( - "encoding/binary" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto" -) - -type bytesBacked interface { - Bytes() []byte -} - -const ( - // BloomByteLength represents the number of bytes used in a header log bloom. - BloomByteLength = 256 - - // BloomBitLength represents the number of bits used in a header log bloom. - BloomBitLength = 8 * BloomByteLength -) - -// Bloom represents a 2048 bit bloom filter. -type Bloom [BloomByteLength]byte - -// BytesToBloom converts a byte slice to a bloom filter. -// It panics if b is not of suitable size. -func BytesToBloom(b []byte) Bloom { - var bloom Bloom - bloom.SetBytes(b) - return bloom -} - -// SetBytes sets the content of b to the given bytes. -// It panics if d is not of suitable size. -func (b *Bloom) SetBytes(d []byte) { - if len(b) < len(d) { - panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d))) - } - copy(b[BloomByteLength-len(d):], d) -} - -// Add adds d to the filter. Future calls of Test(d) will return true. -func (b *Bloom) Add(d []byte) { - b.add(d, make([]byte, 6)) -} - -// add is internal version of Add, which takes a scratch buffer for reuse (needs to be at least 6 bytes) -func (b *Bloom) add(d []byte, buf []byte) { - i1, v1, i2, v2, i3, v3 := bloomValues(d, buf) - b[i1] |= v1 - b[i2] |= v2 - b[i3] |= v3 -} - -// Big converts b to a big integer. -// Note: Converting a bloom filter to a big.Int and then calling GetBytes -// does not return the same bytes, since big.Int will trim leading zeroes -func (b Bloom) Big() *big.Int { - return new(big.Int).SetBytes(b[:]) -} - -// Bytes returns the backing byte slice of the bloom -func (b Bloom) Bytes() []byte { - return b[:] -} - -// Test checks if the given topic is present in the bloom filter -func (b Bloom) Test(topic []byte) bool { - i1, v1, i2, v2, i3, v3 := bloomValues(topic, make([]byte, 6)) - return v1 == v1&b[i1] && - v2 == v2&b[i2] && - v3 == v3&b[i3] -} - -// MarshalText encodes b as a hex string with 0x prefix. -func (b Bloom) MarshalText() ([]byte, error) { - return hexutil.Bytes(b[:]).MarshalText() -} - -// UnmarshalText b as a hex string with 0x prefix. -func (b *Bloom) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedText("Bloom", input, b[:]) -} - -// CreateBloom creates a bloom filter out of the give Receipts (+Logs) -func CreateBloom(receipts Receipts) Bloom { - buf := make([]byte, 6) - var bin Bloom - for _, receipt := range receipts { - for _, log := range receipt.Logs { - bin.add(log.Address.Bytes(), buf) - for _, b := range log.Topics { - bin.add(b[:], buf) - } - } - } - return bin -} - -// LogsBloom returns the bloom bytes for the given logs -func LogsBloom(logs []*Log) []byte { - buf := make([]byte, 6) - var bin Bloom - for _, log := range logs { - bin.add(log.Address.Bytes(), buf) - for _, b := range log.Topics { - bin.add(b[:], buf) - } - } - return bin[:] -} - -// Bloom9 returns the bloom filter for the given data -func Bloom9(data []byte) []byte { - var b Bloom - b.SetBytes(data) - return b.Bytes() -} - -// bloomValues returns the bytes (index-value pairs) to set for the given data -func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) { - sha := hasherPool.Get().(crypto.KeccakState) - sha.Reset() - sha.Write(data) - sha.Read(hashbuf) - hasherPool.Put(sha) - // The actual bits to flip - v1 := byte(1 << (hashbuf[1] & 0x7)) - v2 := byte(1 << (hashbuf[3] & 0x7)) - v3 := byte(1 << (hashbuf[5] & 0x7)) - // The indices for the bytes to OR in - i1 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf)&0x7ff)>>3) - 1 - i2 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[2:])&0x7ff)>>3) - 1 - i3 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[4:])&0x7ff)>>3) - 1 - - return i1, v1, i2, v2, i3, v3 -} - -// BloomLookup is a convenience-method to check presence in the bloom filter -func BloomLookup(bin Bloom, topic bytesBacked) bool { - return bin.Test(topic.Bytes()) -} diff --git a/builder/core/types/bloom9_test.go b/builder/core/types/bloom9_test.go deleted file mode 100644 index d3178d112..000000000 --- a/builder/core/types/bloom9_test.go +++ /dev/null @@ -1,155 +0,0 @@ -// 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 types - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -func TestBloom(t *testing.T) { - positive := []string{ - "testtest", - "test", - "hallo", - "other", - } - negative := []string{ - "tes", - "lo", - } - - var bloom Bloom - for _, data := range positive { - bloom.Add([]byte(data)) - } - - for _, data := range positive { - if !bloom.Test([]byte(data)) { - t.Error("expected", data, "to test true") - } - } - for _, data := range negative { - if bloom.Test([]byte(data)) { - t.Error("did not expect", data, "to test true") - } - } -} - -// TestBloomExtensively does some more thorough tests -func TestBloomExtensively(t *testing.T) { - var exp = common.HexToHash("c8d3ca65cdb4874300a9e39475508f23ed6da09fdbc487f89a2dcf50b09eb263") - var b Bloom - // Add 100 "random" things - for i := 0; i < 100; i++ { - data := fmt.Sprintf("xxxxxxxxxx data %d yyyyyyyyyyyyyy", i) - b.Add([]byte(data)) - //b.Add(new(big.Int).SetBytes([]byte(data))) - } - got := crypto.Keccak256Hash(b.Bytes()) - if got != exp { - t.Errorf("Got %x, exp %x", got, exp) - } - var b2 Bloom - b2.SetBytes(b.Bytes()) - got2 := crypto.Keccak256Hash(b2.Bytes()) - if got != got2 { - t.Errorf("Got %x, exp %x", got, got2) - } -} - -func BenchmarkBloom9(b *testing.B) { - test := []byte("testestestest") - for i := 0; i < b.N; i++ { - Bloom9(test) - } -} - -func BenchmarkBloom9Lookup(b *testing.B) { - toTest := []byte("testtest") - bloom := new(Bloom) - for i := 0; i < b.N; i++ { - bloom.Test(toTest) - } -} - -func BenchmarkCreateBloom(b *testing.B) { - var txs = Transactions{ - NewContractCreation(1, big.NewInt(1), 1, big.NewInt(1), nil), - NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil), - } - var rSmall = Receipts{ - &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - {Address: common.BytesToAddress([]byte{0x11})}, - {Address: common.BytesToAddress([]byte{0x01, 0x11})}, - }, - TxHash: txs[0].Hash(), - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 1, - }, - &Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 3, - Logs: []*Log{ - {Address: common.BytesToAddress([]byte{0x22})}, - {Address: common.BytesToAddress([]byte{0x02, 0x22})}, - }, - TxHash: txs[1].Hash(), - ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), - GasUsed: 2, - }, - } - - var rLarge = make(Receipts, 200) - // Fill it with 200 receipts x 2 logs - for i := 0; i < 200; i += 2 { - copy(rLarge[i:], rSmall) - } - b.Run("small", func(b *testing.B) { - b.ReportAllocs() - var bl Bloom - for i := 0; i < b.N; i++ { - bl = CreateBloom(rSmall) - } - b.StopTimer() - var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") - got := crypto.Keccak256Hash(bl.Bytes()) - if got != exp { - b.Errorf("Got %x, exp %x", got, exp) - } - }) - b.Run("large", func(b *testing.B) { - b.ReportAllocs() - var bl Bloom - for i := 0; i < b.N; i++ { - bl = CreateBloom(rLarge) - } - b.StopTimer() - var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") - got := crypto.Keccak256Hash(bl.Bytes()) - if got != exp { - b.Errorf("Got %x, exp %x", got, exp) - } - }) -} diff --git a/builder/core/types/builder.go b/builder/core/types/builder.go deleted file mode 100644 index 03370ae24..000000000 --- a/builder/core/types/builder.go +++ /dev/null @@ -1,35 +0,0 @@ -package types - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "golang.org/x/exp/slices" -) - -type BuilderPayloadAttributes struct { - Timestamp hexutil.Uint64 `json:"timestamp"` - Random common.Hash `json:"prevRandao"` - SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient,omitempty"` - Slot uint64 `json:"slot"` - HeadHash common.Hash `json:"blockHash"` - Withdrawals Withdrawals `json:"withdrawals"` - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` - GasLimit uint64 -} - -func (attrs *BuilderPayloadAttributes) Equal(other *BuilderPayloadAttributes) bool { - if attrs.Timestamp != other.Timestamp || - attrs.Random != other.Random || - attrs.SuggestedFeeRecipient != other.SuggestedFeeRecipient || - attrs.Slot != other.Slot || - attrs.HeadHash != other.HeadHash || - attrs.GasLimit != other.GasLimit || - attrs.ParentBeaconBlockRoot != other.ParentBeaconBlockRoot { - return false - } - - if !slices.Equal(attrs.Withdrawals, other.Withdrawals) { - return false - } - return true -} diff --git a/builder/core/types/constraints.go b/builder/core/types/constraints.go deleted file mode 100644 index e587b4755..000000000 --- a/builder/core/types/constraints.go +++ /dev/null @@ -1,62 +0,0 @@ -package types - -import ( - "sort" - - "github.com/ethereum/go-ethereum/common" -) - -// NOTE: not the greatest place for this type but given that it uses -// `common.Hash`, `Transaction` and it's used in both the builder -// package and the miner package, here it's a good place for now - -type ( - HashToConstraintDecoded = map[common.Hash]*ConstraintDecoded - ConstraintDecoded struct { - Index *uint64 - Tx *Transaction - } -) - -// ParseConstraintsDecoded receives a map of constraints and returns -// - a slice of constraints sorted by index -// - a slice of constraints without index sorted by nonce and hash -// - the total gas required by the constraints -// - the total blob gas required by the constraints -func ParseConstraintsDecoded(constraints HashToConstraintDecoded) ([]*ConstraintDecoded, []*ConstraintDecoded, uint64, uint64) { - // Here we initialize and track the constraints left to be executed along - // with their gas requirements - constraintsOrderedByIndex := make([]*ConstraintDecoded, 0, len(constraints)) - constraintsWithoutIndex := make([]*ConstraintDecoded, 0, len(constraints)) - constraintsTotalGasLeft := uint64(0) - constraintsTotalBlobGasLeft := uint64(0) - - for _, constraint := range constraints { - if constraint.Index == nil { - constraintsWithoutIndex = append(constraintsWithoutIndex, constraint) - } else { - constraintsOrderedByIndex = append(constraintsOrderedByIndex, constraint) - } - constraintsTotalGasLeft += constraint.Tx.Gas() - constraintsTotalBlobGasLeft += constraint.Tx.BlobGas() - } - - // Sorts the constraints by index ascending - sort.Slice(constraintsOrderedByIndex, func(i, j int) bool { - // By assumption, all constraints here have a non-nil index - return *constraintsOrderedByIndex[i].Index < *constraintsOrderedByIndex[j].Index - }) - - // Sorts the unindexed constraints by nonce ascending and by hash - sort.Slice(constraintsWithoutIndex, func(i, j int) bool { - iNonce := constraintsWithoutIndex[i].Tx.Nonce() - jNonce := constraintsWithoutIndex[j].Tx.Nonce() - // Sort by hash - if iNonce == jNonce { - return constraintsWithoutIndex[i].Tx.Hash().Cmp(constraintsWithoutIndex[j].Tx.Hash()) < 0 - } - return iNonce < jNonce - }) - - return constraintsOrderedByIndex, constraintsWithoutIndex, constraintsTotalGasLeft, constraintsTotalBlobGasLeft -} diff --git a/builder/core/types/gen_access_tuple.go b/builder/core/types/gen_access_tuple.go deleted file mode 100644 index d740b7098..000000000 --- a/builder/core/types/gen_access_tuple.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - - "github.com/ethereum/go-ethereum/common" -) - -// MarshalJSON marshals as JSON. -func (a AccessTuple) MarshalJSON() ([]byte, error) { - type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` - } - var enc AccessTuple - enc.Address = a.Address - enc.StorageKeys = a.StorageKeys - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (a *AccessTuple) UnmarshalJSON(input []byte) error { - type AccessTuple struct { - Address *common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` - } - var dec AccessTuple - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Address == nil { - return errors.New("missing required field 'address' for AccessTuple") - } - a.Address = *dec.Address - if dec.StorageKeys == nil { - return errors.New("missing required field 'storageKeys' for AccessTuple") - } - a.StorageKeys = dec.StorageKeys - return nil -} diff --git a/builder/core/types/gen_account.go b/builder/core/types/gen_account.go deleted file mode 100644 index 4e475896a..000000000 --- a/builder/core/types/gen_account.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" -) - -var _ = (*accountMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (a Account) MarshalJSON() ([]byte, error) { - type Account struct { - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey hexutil.Bytes `json:"secretKey,omitempty"` - } - var enc Account - enc.Code = a.Code - if a.Storage != nil { - enc.Storage = make(map[storageJSON]storageJSON, len(a.Storage)) - for k, v := range a.Storage { - enc.Storage[storageJSON(k)] = storageJSON(v) - } - } - enc.Balance = (*math.HexOrDecimal256)(a.Balance) - enc.Nonce = math.HexOrDecimal64(a.Nonce) - enc.PrivateKey = a.PrivateKey - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (a *Account) UnmarshalJSON(input []byte) error { - type Account struct { - Code *hexutil.Bytes `json:"code,omitempty"` - Storage map[storageJSON]storageJSON `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` - PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"` - } - var dec Account - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Code != nil { - a.Code = *dec.Code - } - if dec.Storage != nil { - a.Storage = make(map[common.Hash]common.Hash, len(dec.Storage)) - for k, v := range dec.Storage { - a.Storage[common.Hash(k)] = common.Hash(v) - } - } - if dec.Balance == nil { - return errors.New("missing required field 'balance' for Account") - } - a.Balance = (*big.Int)(dec.Balance) - if dec.Nonce != nil { - a.Nonce = uint64(*dec.Nonce) - } - if dec.PrivateKey != nil { - a.PrivateKey = *dec.PrivateKey - } - return nil -} diff --git a/builder/core/types/gen_account_rlp.go b/builder/core/types/gen_account_rlp.go deleted file mode 100644 index 3d2f67ab0..000000000 --- a/builder/core/types/gen_account_rlp.go +++ /dev/null @@ -1,24 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package types - -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) - -func (obj *StateAccount) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(obj.Nonce) - if obj.Balance == nil { - w.Write(rlp.EmptyString) - } else { - w.WriteUint256(obj.Balance) - } - w.WriteBytes(obj.Root[:]) - w.WriteBytes(obj.CodeHash) - w.ListEnd(_tmp0) - return w.Flush() -} diff --git a/builder/core/types/gen_header_json.go b/builder/core/types/gen_header_json.go deleted file mode 100644 index fb1f915d0..000000000 --- a/builder/core/types/gen_header_json.go +++ /dev/null @@ -1,167 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*headerMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (h Header) MarshalJSON() ([]byte, error) { - type Header struct { - ParentHash common.Hash `json:"parentHash" gencodec:"required"` - UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner"` - Root common.Hash `json:"stateRoot" gencodec:"required"` - TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest common.Hash `json:"mixHash"` - Nonce BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - Hash common.Hash `json:"hash"` - } - var enc Header - enc.ParentHash = h.ParentHash - enc.UncleHash = h.UncleHash - enc.Coinbase = h.Coinbase - enc.Root = h.Root - enc.TxHash = h.TxHash - enc.ReceiptHash = h.ReceiptHash - enc.Bloom = h.Bloom - enc.Difficulty = (*hexutil.Big)(h.Difficulty) - enc.Number = (*hexutil.Big)(h.Number) - enc.GasLimit = hexutil.Uint64(h.GasLimit) - enc.GasUsed = hexutil.Uint64(h.GasUsed) - enc.Time = hexutil.Uint64(h.Time) - enc.Extra = h.Extra - enc.MixDigest = h.MixDigest - enc.Nonce = h.Nonce - enc.BaseFee = (*hexutil.Big)(h.BaseFee) - enc.WithdrawalsHash = h.WithdrawalsHash - enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed) - enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas) - enc.ParentBeaconRoot = h.ParentBeaconRoot - enc.Hash = h.Hash() - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (h *Header) UnmarshalJSON(input []byte) error { - type Header struct { - ParentHash *common.Hash `json:"parentHash" gencodec:"required"` - UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase *common.Address `json:"miner"` - Root *common.Hash `json:"stateRoot" gencodec:"required"` - TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` - ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` - Bloom *Bloom `json:"logsBloom" gencodec:"required"` - Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` - Number *hexutil.Big `json:"number" gencodec:"required"` - GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Extra *hexutil.Bytes `json:"extraData" gencodec:"required"` - MixDigest *common.Hash `json:"mixHash"` - Nonce *BlockNonce `json:"nonce"` - BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"` - WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"` - ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` - } - var dec Header - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.ParentHash == nil { - return errors.New("missing required field 'parentHash' for Header") - } - h.ParentHash = *dec.ParentHash - if dec.UncleHash == nil { - return errors.New("missing required field 'sha3Uncles' for Header") - } - h.UncleHash = *dec.UncleHash - if dec.Coinbase != nil { - h.Coinbase = *dec.Coinbase - } - if dec.Root == nil { - return errors.New("missing required field 'stateRoot' for Header") - } - h.Root = *dec.Root - if dec.TxHash == nil { - return errors.New("missing required field 'transactionsRoot' for Header") - } - h.TxHash = *dec.TxHash - if dec.ReceiptHash == nil { - return errors.New("missing required field 'receiptsRoot' for Header") - } - h.ReceiptHash = *dec.ReceiptHash - if dec.Bloom == nil { - return errors.New("missing required field 'logsBloom' for Header") - } - h.Bloom = *dec.Bloom - if dec.Difficulty == nil { - return errors.New("missing required field 'difficulty' for Header") - } - h.Difficulty = (*big.Int)(dec.Difficulty) - if dec.Number == nil { - return errors.New("missing required field 'number' for Header") - } - h.Number = (*big.Int)(dec.Number) - if dec.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for Header") - } - h.GasLimit = uint64(*dec.GasLimit) - if dec.GasUsed == nil { - return errors.New("missing required field 'gasUsed' for Header") - } - h.GasUsed = uint64(*dec.GasUsed) - if dec.Time == nil { - return errors.New("missing required field 'timestamp' for Header") - } - h.Time = uint64(*dec.Time) - if dec.Extra == nil { - return errors.New("missing required field 'extraData' for Header") - } - h.Extra = *dec.Extra - if dec.MixDigest != nil { - h.MixDigest = *dec.MixDigest - } - if dec.Nonce != nil { - h.Nonce = *dec.Nonce - } - if dec.BaseFee != nil { - h.BaseFee = (*big.Int)(dec.BaseFee) - } - if dec.WithdrawalsHash != nil { - h.WithdrawalsHash = dec.WithdrawalsHash - } - if dec.BlobGasUsed != nil { - h.BlobGasUsed = (*uint64)(dec.BlobGasUsed) - } - if dec.ExcessBlobGas != nil { - h.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) - } - if dec.ParentBeaconRoot != nil { - h.ParentBeaconRoot = dec.ParentBeaconRoot - } - return nil -} diff --git a/builder/core/types/gen_header_rlp.go b/builder/core/types/gen_header_rlp.go deleted file mode 100644 index e6da0d065..000000000 --- a/builder/core/types/gen_header_rlp.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package types - -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) - -func (obj *Header) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteBytes(obj.ParentHash[:]) - w.WriteBytes(obj.UncleHash[:]) - w.WriteBytes(obj.Coinbase[:]) - w.WriteBytes(obj.Root[:]) - w.WriteBytes(obj.TxHash[:]) - w.WriteBytes(obj.ReceiptHash[:]) - w.WriteBytes(obj.Bloom[:]) - if obj.Difficulty == nil { - w.Write(rlp.EmptyString) - } else { - if obj.Difficulty.Sign() == -1 { - return rlp.ErrNegativeBigInt - } - w.WriteBigInt(obj.Difficulty) - } - if obj.Number == nil { - w.Write(rlp.EmptyString) - } else { - if obj.Number.Sign() == -1 { - return rlp.ErrNegativeBigInt - } - w.WriteBigInt(obj.Number) - } - w.WriteUint64(obj.GasLimit) - w.WriteUint64(obj.GasUsed) - w.WriteUint64(obj.Time) - w.WriteBytes(obj.Extra) - w.WriteBytes(obj.MixDigest[:]) - w.WriteBytes(obj.Nonce[:]) - _tmp1 := obj.BaseFee != nil - _tmp2 := obj.WithdrawalsHash != nil - _tmp3 := obj.BlobGasUsed != nil - _tmp4 := obj.ExcessBlobGas != nil - _tmp5 := obj.ParentBeaconRoot != nil - if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 { - if obj.BaseFee == nil { - w.Write(rlp.EmptyString) - } else { - if obj.BaseFee.Sign() == -1 { - return rlp.ErrNegativeBigInt - } - w.WriteBigInt(obj.BaseFee) - } - } - if _tmp2 || _tmp3 || _tmp4 || _tmp5 { - if obj.WithdrawalsHash == nil { - w.Write([]byte{0x80}) - } else { - w.WriteBytes(obj.WithdrawalsHash[:]) - } - } - if _tmp3 || _tmp4 || _tmp5 { - if obj.BlobGasUsed == nil { - w.Write([]byte{0x80}) - } else { - w.WriteUint64((*obj.BlobGasUsed)) - } - } - if _tmp4 || _tmp5 { - if obj.ExcessBlobGas == nil { - w.Write([]byte{0x80}) - } else { - w.WriteUint64((*obj.ExcessBlobGas)) - } - } - if _tmp5 { - if obj.ParentBeaconRoot == nil { - w.Write([]byte{0x80}) - } else { - w.WriteBytes(obj.ParentBeaconRoot[:]) - } - } - w.ListEnd(_tmp0) - return w.Flush() -} diff --git a/builder/core/types/gen_log_json.go b/builder/core/types/gen_log_json.go deleted file mode 100644 index 3ffa9c2fe..000000000 --- a/builder/core/types/gen_log_json.go +++ /dev/null @@ -1,90 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*logMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (l Log) MarshalJSON() ([]byte, error) { - type Log struct { - Address common.Address `json:"address" gencodec:"required"` - Topics []common.Hash `json:"topics" gencodec:"required"` - Data hexutil.Bytes `json:"data" gencodec:"required"` - BlockNumber hexutil.Uint64 `json:"blockNumber" rlp:"-"` - TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` - TxIndex hexutil.Uint `json:"transactionIndex" rlp:"-"` - BlockHash common.Hash `json:"blockHash" rlp:"-"` - Index hexutil.Uint `json:"logIndex" rlp:"-"` - Removed bool `json:"removed" rlp:"-"` - } - var enc Log - enc.Address = l.Address - enc.Topics = l.Topics - enc.Data = l.Data - enc.BlockNumber = hexutil.Uint64(l.BlockNumber) - enc.TxHash = l.TxHash - enc.TxIndex = hexutil.Uint(l.TxIndex) - enc.BlockHash = l.BlockHash - enc.Index = hexutil.Uint(l.Index) - enc.Removed = l.Removed - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (l *Log) UnmarshalJSON(input []byte) error { - type Log struct { - Address *common.Address `json:"address" gencodec:"required"` - Topics []common.Hash `json:"topics" gencodec:"required"` - Data *hexutil.Bytes `json:"data" gencodec:"required"` - BlockNumber *hexutil.Uint64 `json:"blockNumber" rlp:"-"` - TxHash *common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` - TxIndex *hexutil.Uint `json:"transactionIndex" rlp:"-"` - BlockHash *common.Hash `json:"blockHash" rlp:"-"` - Index *hexutil.Uint `json:"logIndex" rlp:"-"` - Removed *bool `json:"removed" rlp:"-"` - } - var dec Log - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Address == nil { - return errors.New("missing required field 'address' for Log") - } - l.Address = *dec.Address - if dec.Topics == nil { - return errors.New("missing required field 'topics' for Log") - } - l.Topics = dec.Topics - if dec.Data == nil { - return errors.New("missing required field 'data' for Log") - } - l.Data = *dec.Data - if dec.BlockNumber != nil { - l.BlockNumber = uint64(*dec.BlockNumber) - } - if dec.TxHash == nil { - return errors.New("missing required field 'transactionHash' for Log") - } - l.TxHash = *dec.TxHash - if dec.TxIndex != nil { - l.TxIndex = uint(*dec.TxIndex) - } - if dec.BlockHash != nil { - l.BlockHash = *dec.BlockHash - } - if dec.Index != nil { - l.Index = uint(*dec.Index) - } - if dec.Removed != nil { - l.Removed = *dec.Removed - } - return nil -} diff --git a/builder/core/types/gen_log_rlp.go b/builder/core/types/gen_log_rlp.go deleted file mode 100644 index 89f2083d4..000000000 --- a/builder/core/types/gen_log_rlp.go +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package types - -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) - -func (obj *Log) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteBytes(obj.Address[:]) - _tmp1 := w.List() - for _, _tmp2 := range obj.Topics { - w.WriteBytes(_tmp2[:]) - } - w.ListEnd(_tmp1) - w.WriteBytes(obj.Data) - w.ListEnd(_tmp0) - return w.Flush() -} diff --git a/builder/core/types/gen_receipt_json.go b/builder/core/types/gen_receipt_json.go deleted file mode 100644 index 4c641a972..000000000 --- a/builder/core/types/gen_receipt_json.go +++ /dev/null @@ -1,128 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*receiptMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (r Receipt) MarshalJSON() ([]byte, error) { - type Receipt struct { - Type hexutil.Uint64 `json:"type,omitempty"` - PostState hexutil.Bytes `json:"root"` - Status hexutil.Uint64 `json:"status"` - CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Logs []*Log `json:"logs" gencodec:"required"` - TxHash common.Hash `json:"transactionHash" gencodec:"required"` - ContractAddress common.Address `json:"contractAddress"` - GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"` - BlobGasUsed hexutil.Uint64 `json:"blobGasUsed,omitempty"` - BlobGasPrice *hexutil.Big `json:"blobGasPrice,omitempty"` - BlockHash common.Hash `json:"blockHash,omitempty"` - BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` - TransactionIndex hexutil.Uint `json:"transactionIndex"` - } - var enc Receipt - enc.Type = hexutil.Uint64(r.Type) - enc.PostState = r.PostState - enc.Status = hexutil.Uint64(r.Status) - enc.CumulativeGasUsed = hexutil.Uint64(r.CumulativeGasUsed) - enc.Bloom = r.Bloom - enc.Logs = r.Logs - enc.TxHash = r.TxHash - enc.ContractAddress = r.ContractAddress - enc.GasUsed = hexutil.Uint64(r.GasUsed) - enc.EffectiveGasPrice = (*hexutil.Big)(r.EffectiveGasPrice) - enc.BlobGasUsed = hexutil.Uint64(r.BlobGasUsed) - enc.BlobGasPrice = (*hexutil.Big)(r.BlobGasPrice) - enc.BlockHash = r.BlockHash - enc.BlockNumber = (*hexutil.Big)(r.BlockNumber) - enc.TransactionIndex = hexutil.Uint(r.TransactionIndex) - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (r *Receipt) UnmarshalJSON(input []byte) error { - type Receipt struct { - Type *hexutil.Uint64 `json:"type,omitempty"` - PostState *hexutil.Bytes `json:"root"` - Status *hexutil.Uint64 `json:"status"` - CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"` - Bloom *Bloom `json:"logsBloom" gencodec:"required"` - Logs []*Log `json:"logs" gencodec:"required"` - TxHash *common.Hash `json:"transactionHash" gencodec:"required"` - ContractAddress *common.Address `json:"contractAddress"` - GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"` - EffectiveGasPrice *hexutil.Big `json:"effectiveGasPrice"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed,omitempty"` - BlobGasPrice *hexutil.Big `json:"blobGasPrice,omitempty"` - BlockHash *common.Hash `json:"blockHash,omitempty"` - BlockNumber *hexutil.Big `json:"blockNumber,omitempty"` - TransactionIndex *hexutil.Uint `json:"transactionIndex"` - } - var dec Receipt - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Type != nil { - r.Type = uint8(*dec.Type) - } - if dec.PostState != nil { - r.PostState = *dec.PostState - } - if dec.Status != nil { - r.Status = uint64(*dec.Status) - } - if dec.CumulativeGasUsed == nil { - return errors.New("missing required field 'cumulativeGasUsed' for Receipt") - } - r.CumulativeGasUsed = uint64(*dec.CumulativeGasUsed) - if dec.Bloom == nil { - return errors.New("missing required field 'logsBloom' for Receipt") - } - r.Bloom = *dec.Bloom - if dec.Logs == nil { - return errors.New("missing required field 'logs' for Receipt") - } - r.Logs = dec.Logs - if dec.TxHash == nil { - return errors.New("missing required field 'transactionHash' for Receipt") - } - r.TxHash = *dec.TxHash - if dec.ContractAddress != nil { - r.ContractAddress = *dec.ContractAddress - } - if dec.GasUsed == nil { - return errors.New("missing required field 'gasUsed' for Receipt") - } - r.GasUsed = uint64(*dec.GasUsed) - if dec.EffectiveGasPrice != nil { - r.EffectiveGasPrice = (*big.Int)(dec.EffectiveGasPrice) - } - if dec.BlobGasUsed != nil { - r.BlobGasUsed = uint64(*dec.BlobGasUsed) - } - if dec.BlobGasPrice != nil { - r.BlobGasPrice = (*big.Int)(dec.BlobGasPrice) - } - if dec.BlockHash != nil { - r.BlockHash = *dec.BlockHash - } - if dec.BlockNumber != nil { - r.BlockNumber = (*big.Int)(dec.BlockNumber) - } - if dec.TransactionIndex != nil { - r.TransactionIndex = uint(*dec.TransactionIndex) - } - return nil -} diff --git a/builder/core/types/gen_withdrawal_json.go b/builder/core/types/gen_withdrawal_json.go deleted file mode 100644 index 983a7f7a1..000000000 --- a/builder/core/types/gen_withdrawal_json.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package types - -import ( - "encoding/json" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var _ = (*withdrawalMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (w Withdrawal) MarshalJSON() ([]byte, error) { - type Withdrawal struct { - Index hexutil.Uint64 `json:"index"` - Validator hexutil.Uint64 `json:"validatorIndex"` - Address common.Address `json:"address"` - Amount hexutil.Uint64 `json:"amount"` - } - var enc Withdrawal - enc.Index = hexutil.Uint64(w.Index) - enc.Validator = hexutil.Uint64(w.Validator) - enc.Address = w.Address - enc.Amount = hexutil.Uint64(w.Amount) - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (w *Withdrawal) UnmarshalJSON(input []byte) error { - type Withdrawal struct { - Index *hexutil.Uint64 `json:"index"` - Validator *hexutil.Uint64 `json:"validatorIndex"` - Address *common.Address `json:"address"` - Amount *hexutil.Uint64 `json:"amount"` - } - var dec Withdrawal - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Index != nil { - w.Index = uint64(*dec.Index) - } - if dec.Validator != nil { - w.Validator = uint64(*dec.Validator) - } - if dec.Address != nil { - w.Address = *dec.Address - } - if dec.Amount != nil { - w.Amount = uint64(*dec.Amount) - } - return nil -} diff --git a/builder/core/types/gen_withdrawal_rlp.go b/builder/core/types/gen_withdrawal_rlp.go deleted file mode 100644 index 7d8b9bad0..000000000 --- a/builder/core/types/gen_withdrawal_rlp.go +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by rlpgen. DO NOT EDIT. - -package types - -import ( - "io" - - "github.com/ethereum/go-ethereum/rlp" -) - -func (obj *Withdrawal) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - _tmp0 := w.List() - w.WriteUint64(obj.Index) - w.WriteUint64(obj.Validator) - w.WriteBytes(obj.Address[:]) - w.WriteUint64(obj.Amount) - w.ListEnd(_tmp0) - return w.Flush() -} diff --git a/builder/core/types/hashes.go b/builder/core/types/hashes.go deleted file mode 100644 index 43e9130fd..000000000 --- a/builder/core/types/hashes.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2023 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 types - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/log" -) - -var ( - // EmptyRootHash is the known root hash of an empty merkle trie. - EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyUncleHash is the known hash of the empty uncle set. - EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 - - // EmptyCodeHash is the known hash of the empty EVM bytecode. - EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 - - // EmptyTxsHash is the known hash of the empty transaction set. - EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyReceiptsHash is the known hash of the empty receipt set. - EmptyReceiptsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyWithdrawalsHash is the known hash of the empty withdrawal set. - EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyVerkleHash is the known hash of an empty verkle trie. - EmptyVerkleHash = common.Hash{} -) - -// TrieRootHash returns the hash itself if it's non-empty or the predefined -// emptyHash one instead. -func TrieRootHash(hash common.Hash) common.Hash { - if hash == (common.Hash{}) { - log.Error("Zero trie root hash!") - return EmptyRootHash - } - return hash -} diff --git a/builder/core/types/hashing.go b/builder/core/types/hashing.go deleted file mode 100644 index 224d7a87e..000000000 --- a/builder/core/types/hashing.go +++ /dev/null @@ -1,134 +0,0 @@ -// 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 types - -import ( - "bytes" - "fmt" - "math" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" -) - -// hasherPool holds LegacyKeccak256 hashers for rlpHash. -var hasherPool = sync.Pool{ - New: func() interface{} { return sha3.NewLegacyKeccak256() }, -} - -// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. -var encodeBufferPool = sync.Pool{ - New: func() interface{} { return new(bytes.Buffer) }, -} - -// getPooledBuffer retrieves a buffer from the pool and creates a byte slice of the -// requested size from it. -// -// The caller should return the *bytes.Buffer object back into encodeBufferPool after use! -// The returned byte slice must not be used after returning the buffer. -func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) { - if size > math.MaxInt { - return nil, nil, fmt.Errorf("can't get buffer of size %d", size) - } - buf := encodeBufferPool.Get().(*bytes.Buffer) - buf.Reset() - buf.Grow(int(size)) - b := buf.Bytes()[:int(size)] - return b, buf, nil -} - -// rlpHash encodes x and hashes the encoded bytes. -func rlpHash(x interface{}) (h common.Hash) { - sha := hasherPool.Get().(crypto.KeccakState) - defer hasherPool.Put(sha) - sha.Reset() - rlp.Encode(sha, x) - sha.Read(h[:]) - return h -} - -// prefixedRlpHash writes the prefix into the hasher before rlp-encoding x. -// It's used for typed transactions. -func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) { - sha := hasherPool.Get().(crypto.KeccakState) - defer hasherPool.Put(sha) - sha.Reset() - sha.Write([]byte{prefix}) - rlp.Encode(sha, x) - sha.Read(h[:]) - return h -} - -// TrieHasher is the tool used to calculate the hash of derivable list. -// This is internal, do not use. -type TrieHasher interface { - Reset() - Update([]byte, []byte) error - Hash() common.Hash -} - -// DerivableList is the input to DeriveSha. -// It is implemented by the 'Transactions' and 'Receipts' types. -// This is internal, do not use these methods. -type DerivableList interface { - Len() int - EncodeIndex(int, *bytes.Buffer) -} - -func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte { - buf.Reset() - list.EncodeIndex(i, buf) - // It's really unfortunate that we need to perform this copy. - // StackTrie holds onto the values until Hash is called, so the values - // written to it must not alias. - return common.CopyBytes(buf.Bytes()) -} - -// DeriveSha creates the tree hashes of transactions, receipts, and withdrawals in a block header. -func DeriveSha(list DerivableList, hasher TrieHasher) common.Hash { - hasher.Reset() - - valueBuf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(valueBuf) - - // StackTrie requires values to be inserted in increasing hash order, which is not the - // order that `list` provides hashes in. This insertion sequence ensures that the - // order is correct. - // - // The error returned by hasher is omitted because hasher will produce an incorrect - // hash in case any error occurs. - var indexBuf []byte - for i := 1; i < list.Len() && i <= 0x7f; i++ { - indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) - value := encodeForDerive(list, i, valueBuf) - hasher.Update(indexBuf, value) - } - if list.Len() > 0 { - indexBuf = rlp.AppendUint64(indexBuf[:0], 0) - value := encodeForDerive(list, 0, valueBuf) - hasher.Update(indexBuf, value) - } - for i := 0x80; i < list.Len(); i++ { - indexBuf = rlp.AppendUint64(indexBuf[:0], uint64(i)) - value := encodeForDerive(list, i, valueBuf) - hasher.Update(indexBuf, value) - } - return hasher.Hash() -} diff --git a/builder/core/types/hashing_test.go b/builder/core/types/hashing_test.go deleted file mode 100644 index a6949414f..000000000 --- a/builder/core/types/hashing_test.go +++ /dev/null @@ -1,231 +0,0 @@ -// 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 types_test - -import ( - "bytes" - "fmt" - "io" - "math/big" - mrand "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" -) - -func TestDeriveSha(t *testing.T) { - txs, err := genTxs(0) - if err != nil { - t.Fatal(err) - } - for len(txs) < 1000 { - exp := types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))) - got := types.DeriveSha(txs, trie.NewStackTrie(nil)) - if !bytes.Equal(got[:], exp[:]) { - t.Fatalf("%d txs: got %x exp %x", len(txs), got, exp) - } - newTxs, err := genTxs(uint64(len(txs) + 1)) - if err != nil { - t.Fatal(err) - } - txs = append(txs, newTxs...) - } -} - -// TestEIP2718DeriveSha tests that the input to the DeriveSha function is correct. -func TestEIP2718DeriveSha(t *testing.T) { - for _, tc := range []struct { - rlpData string - exp string - }{ - { - rlpData: "0xb8a701f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9", - exp: "01 01f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9\n80 01f8a486796f6c6f763380843b9aca008262d4948a8eafb1cf62bfbeb1741769dae1a9dd479961928080f838f7940000000000000000000000000000000000001337e1a0000000000000000000000000000000000000000000000000000000000000000080a0775101f92dcca278a56bfe4d613428624a1ebfc3cd9e0bcc1de80c41455b9021a06c9deac205afe7b124907d4ba54a9f46161498bd3990b90d175aac12c9a40ee9\n", - }, - } { - d := &hashToHumanReadable{} - var t1, t2 types.Transaction - rlp.DecodeBytes(common.FromHex(tc.rlpData), &t1) - rlp.DecodeBytes(common.FromHex(tc.rlpData), &t2) - txs := types.Transactions{&t1, &t2} - types.DeriveSha(txs, d) - if tc.exp != string(d.data) { - t.Fatalf("Want\n%v\nhave:\n%v", tc.exp, string(d.data)) - } - } -} - -func BenchmarkDeriveSha200(b *testing.B) { - txs, err := genTxs(200) - if err != nil { - b.Fatal(err) - } - var exp common.Hash - var got common.Hash - b.Run("std_trie", func(b *testing.B) { - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - exp = types.DeriveSha(txs, trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))) - } - }) - - b.Run("stack_trie", func(b *testing.B) { - b.ResetTimer() - b.ReportAllocs() - for i := 0; i < b.N; i++ { - got = types.DeriveSha(txs, trie.NewStackTrie(nil)) - } - }) - if got != exp { - b.Errorf("got %x exp %x", got, exp) - } -} - -func TestFuzzDeriveSha(t *testing.T) { - // increase this for longer runs -- it's set to quite low for travis - rndSeed := mrand.Int() - for i := 0; i < 10; i++ { - seed := rndSeed + i - exp := types.DeriveSha(newDummy(i), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))) - got := types.DeriveSha(newDummy(i), trie.NewStackTrie(nil)) - if !bytes.Equal(got[:], exp[:]) { - printList(newDummy(seed)) - t.Fatalf("seed %d: got %x exp %x", seed, got, exp) - } - } -} - -// TestDerivableList contains testcases found via fuzzing -func TestDerivableList(t *testing.T) { - type tcase []string - tcs := []tcase{ - { - "0xc041", - }, - { - "0xf04cf757812428b0763112efb33b6f4fad7deb445e", - "0xf04cf757812428b0763112efb33b6f4fad7deb445e", - }, - { - "0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d", - "0x6cd850eca0a7ac46bb1748d7b9cb88aa3bd21c57d852c28198ad8fa422c4595032e88a4494b4778b36b944fe47a52b8c5cd312910139dfcb4147ab8e972cc456bcb063f25dd78f54c4d34679e03142c42c662af52947d45bdb6e555751334ace76a5080ab5a0256a1d259855dfc5c0b8023b25befbb13fd3684f9f755cbd3d63544c78ee2001452dd54633a7593ade0b183891a0a4e9c7844e1254005fbe592b1b89149a502c24b6e1dca44c158aebedf01beae9c30cabe16a", - "0x14abd5c47c0be87b0454596baad2", - "0xca410605310cdc3bb8d4977ae4f0143df54a724ed873457e2272f39d66e0460e971d9d", - }, - } - for i, tc := range tcs[1:] { - exp := types.DeriveSha(flatList(tc), trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))) - got := types.DeriveSha(flatList(tc), trie.NewStackTrie(nil)) - if !bytes.Equal(got[:], exp[:]) { - t.Fatalf("case %d: got %x exp %x", i, got, exp) - } - } -} - -func genTxs(num uint64) (types.Transactions, error) { - key, err := crypto.HexToECDSA("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") - if err != nil { - return nil, err - } - var addr = crypto.PubkeyToAddress(key.PublicKey) - newTx := func(i uint64) (*types.Transaction, error) { - signer := types.NewEIP155Signer(big.NewInt(18)) - utx := types.NewTransaction(i, addr, new(big.Int), 0, new(big.Int).SetUint64(10000000), nil) - tx, err := types.SignTx(utx, signer, key) - return tx, err - } - var txs types.Transactions - for i := uint64(0); i < num; i++ { - tx, err := newTx(i) - if err != nil { - return nil, err - } - txs = append(txs, tx) - } - return txs, nil -} - -type dummyDerivableList struct { - len int - seed int -} - -func newDummy(seed int) *dummyDerivableList { - d := &dummyDerivableList{} - src := mrand.NewSource(int64(seed)) - // don't use lists longer than 4K items - d.len = int(src.Int63() & 0x0FFF) - d.seed = seed - return d -} - -func (d *dummyDerivableList) Len() int { - return d.len -} - -func (d *dummyDerivableList) EncodeIndex(i int, w *bytes.Buffer) { - src := mrand.NewSource(int64(d.seed + i)) - // max item size 256, at least 1 byte per item - size := 1 + src.Int63()&0x00FF - io.CopyN(w, mrand.New(src), size) -} - -func printList(l types.DerivableList) { - fmt.Printf("list length: %d\n", l.Len()) - fmt.Printf("{\n") - for i := 0; i < l.Len(); i++ { - var buf bytes.Buffer - l.EncodeIndex(i, &buf) - fmt.Printf("\"%#x\",\n", buf.Bytes()) - } - fmt.Printf("},\n") -} - -type flatList []string - -func (f flatList) Len() int { - return len(f) -} -func (f flatList) EncodeIndex(i int, w *bytes.Buffer) { - w.Write(hexutil.MustDecode(f[i])) -} - -type hashToHumanReadable struct { - data []byte -} - -func (d *hashToHumanReadable) Reset() { - d.data = make([]byte, 0) -} - -func (d *hashToHumanReadable) Update(i []byte, i2 []byte) error { - l := fmt.Sprintf("%x %x\n", i, i2) - d.data = append(d.data, []byte(l)...) - return nil -} - -func (d *hashToHumanReadable) Hash() common.Hash { - return common.Hash{} -} diff --git a/builder/core/types/log.go b/builder/core/types/log.go deleted file mode 100644 index 54c7ff637..000000000 --- a/builder/core/types/log.go +++ /dev/null @@ -1,61 +0,0 @@ -// 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 types - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -//go:generate go run ../../rlp/rlpgen -type Log -out gen_log_rlp.go -//go:generate go run github.com/fjl/gencodec -type Log -field-override logMarshaling -out gen_log_json.go - -// Log represents a contract log event. These events are generated by the LOG opcode and -// stored/indexed by the node. -type Log struct { - // Consensus fields: - // address of the contract that generated the event - Address common.Address `json:"address" gencodec:"required"` - // list of topics provided by the contract. - Topics []common.Hash `json:"topics" gencodec:"required"` - // supplied by the contract, usually ABI-encoded - Data []byte `json:"data" gencodec:"required"` - - // Derived fields. These fields are filled in by the node - // but not secured by consensus. - // block in which the transaction was included - BlockNumber uint64 `json:"blockNumber" rlp:"-"` - // hash of the transaction - TxHash common.Hash `json:"transactionHash" gencodec:"required" rlp:"-"` - // index of the transaction in the block - TxIndex uint `json:"transactionIndex" rlp:"-"` - // hash of the block in which the transaction was included - BlockHash common.Hash `json:"blockHash" rlp:"-"` - // index of the log in the block - Index uint `json:"logIndex" rlp:"-"` - - // The Removed field is true if this log was reverted due to a chain reorganisation. - // You must pay attention to this field if you receive logs through a filter query. - Removed bool `json:"removed" rlp:"-"` -} - -type logMarshaling struct { - Data hexutil.Bytes - BlockNumber hexutil.Uint64 - TxIndex hexutil.Uint - Index hexutil.Uint -} diff --git a/builder/core/types/log_test.go b/builder/core/types/log_test.go deleted file mode 100644 index 02eef3ecd..000000000 --- a/builder/core/types/log_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2016 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 types - -import ( - "encoding/json" - "errors" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var unmarshalLogTests = map[string]struct { - input string - want *Log - wantError error -}{ - "ok": { - input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x000000000000000000000000000000000000000000000001a055690d9db80000","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`, - want: &Log{ - Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"), - BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"), - BlockNumber: 2019236, - Data: hexutil.MustDecode("0x000000000000000000000000000000000000000000000001a055690d9db80000"), - Index: 2, - TxIndex: 3, - TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"), - Topics: []common.Hash{ - common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), - common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"), - }, - }, - }, - "empty data": { - input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`, - want: &Log{ - Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"), - BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"), - BlockNumber: 2019236, - Data: []byte{}, - Index: 2, - TxIndex: 3, - TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"), - Topics: []common.Hash{ - common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), - common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"), - }, - }, - }, - "missing block fields (pending logs)": { - input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","data":"0x","logIndex":"0x0","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`, - want: &Log{ - Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"), - BlockHash: common.Hash{}, - BlockNumber: 0, - Data: []byte{}, - Index: 0, - TxIndex: 3, - TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"), - Topics: []common.Hash{ - common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), - }, - }, - }, - "Removed: true": { - input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3","removed":true}`, - want: &Log{ - Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"), - BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"), - BlockNumber: 2019236, - Data: []byte{}, - Index: 2, - TxIndex: 3, - TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"), - Topics: []common.Hash{ - common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), - }, - Removed: true, - }, - }, - "missing data": { - input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`, - wantError: errors.New("missing required field 'data' for Log"), - }, -} - -func TestUnmarshalLog(t *testing.T) { - dumper := spew.ConfigState{DisableMethods: true, Indent: " "} - for name, test := range unmarshalLogTests { - var log *Log - err := json.Unmarshal([]byte(test.input), &log) - checkError(t, name, err, test.wantError) - if test.wantError == nil && err == nil { - if !reflect.DeepEqual(log, test.want) { - t.Errorf("test %q:\nGOT %sWANT %s", name, dumper.Sdump(log), dumper.Sdump(test.want)) - } - } - } -} - -func checkError(t *testing.T, testname string, got, want error) bool { - if got == nil { - if want != nil { - t.Errorf("test %q: got no error, want %q", testname, want) - return false - } - return true - } - if want == nil { - t.Errorf("test %q: unexpected error %q", testname, got) - } else if got.Error() != want.Error() { - t.Errorf("test %q: got error %q, want %q", testname, got, want) - } - return false -} diff --git a/builder/core/types/receipt.go b/builder/core/types/receipt.go deleted file mode 100644 index 4f96fde59..000000000 --- a/builder/core/types/receipt.go +++ /dev/null @@ -1,377 +0,0 @@ -// 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 types - -import ( - "bytes" - "errors" - "fmt" - "io" - "math/big" - "unsafe" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -//go:generate go run github.com/fjl/gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go - -var ( - receiptStatusFailedRLP = []byte{} - receiptStatusSuccessfulRLP = []byte{0x01} -) - -var errShortTypedReceipt = errors.New("typed receipt too short") - -const ( - // ReceiptStatusFailed is the status code of a transaction if execution failed. - ReceiptStatusFailed = uint64(0) - - // ReceiptStatusSuccessful is the status code of a transaction if execution succeeded. - ReceiptStatusSuccessful = uint64(1) -) - -// Receipt represents the results of a transaction. -type Receipt struct { - // Consensus fields: These fields are defined by the Yellow Paper - Type uint8 `json:"type,omitempty"` - PostState []byte `json:"root"` - Status uint64 `json:"status"` - CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"` - Bloom Bloom `json:"logsBloom" gencodec:"required"` - Logs []*Log `json:"logs" gencodec:"required"` - - // Implementation fields: These fields are added by geth when processing a transaction. - TxHash common.Hash `json:"transactionHash" gencodec:"required"` - ContractAddress common.Address `json:"contractAddress"` - GasUsed uint64 `json:"gasUsed" gencodec:"required"` - EffectiveGasPrice *big.Int `json:"effectiveGasPrice"` // required, but tag omitted for backwards compatibility - BlobGasUsed uint64 `json:"blobGasUsed,omitempty"` - BlobGasPrice *big.Int `json:"blobGasPrice,omitempty"` - - // Inclusion information: These fields provide information about the inclusion of the - // transaction corresponding to this receipt. - BlockHash common.Hash `json:"blockHash,omitempty"` - BlockNumber *big.Int `json:"blockNumber,omitempty"` - TransactionIndex uint `json:"transactionIndex"` -} - -type receiptMarshaling struct { - Type hexutil.Uint64 - PostState hexutil.Bytes - Status hexutil.Uint64 - CumulativeGasUsed hexutil.Uint64 - GasUsed hexutil.Uint64 - EffectiveGasPrice *hexutil.Big - BlobGasUsed hexutil.Uint64 - BlobGasPrice *hexutil.Big - BlockNumber *hexutil.Big - TransactionIndex hexutil.Uint -} - -// receiptRLP is the consensus encoding of a receipt. -type receiptRLP struct { - PostStateOrStatus []byte - CumulativeGasUsed uint64 - Bloom Bloom - Logs []*Log -} - -// storedReceiptRLP is the storage encoding of a receipt. -type storedReceiptRLP struct { - PostStateOrStatus []byte - CumulativeGasUsed uint64 - Logs []*Log -} - -// NewReceipt creates a barebone transaction receipt, copying the init fields. -// Deprecated: create receipts using a struct literal instead. -func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt { - r := &Receipt{ - Type: LegacyTxType, - PostState: common.CopyBytes(root), - CumulativeGasUsed: cumulativeGasUsed, - } - if failed { - r.Status = ReceiptStatusFailed - } else { - r.Status = ReceiptStatusSuccessful - } - return r -} - -// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt -// into an RLP stream. If no post state is present, byzantium fork is assumed. -func (r *Receipt) EncodeRLP(w io.Writer) error { - data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs} - if r.Type == LegacyTxType { - return rlp.Encode(w, data) - } - buf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(buf) - buf.Reset() - if err := r.encodeTyped(data, buf); err != nil { - return err - } - return rlp.Encode(w, buf.Bytes()) -} - -// encodeTyped writes the canonical encoding of a typed receipt to w. -func (r *Receipt) encodeTyped(data *receiptRLP, w *bytes.Buffer) error { - w.WriteByte(r.Type) - return rlp.Encode(w, data) -} - -// MarshalBinary returns the consensus encoding of the receipt. -func (r *Receipt) MarshalBinary() ([]byte, error) { - if r.Type == LegacyTxType { - return rlp.EncodeToBytes(r) - } - data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs} - var buf bytes.Buffer - err := r.encodeTyped(data, &buf) - return buf.Bytes(), err -} - -// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt -// from an RLP stream. -func (r *Receipt) DecodeRLP(s *rlp.Stream) error { - kind, size, err := s.Kind() - switch { - case err != nil: - return err - case kind == rlp.List: - // It's a legacy receipt. - var dec receiptRLP - if err := s.Decode(&dec); err != nil { - return err - } - r.Type = LegacyTxType - return r.setFromRLP(dec) - case kind == rlp.Byte: - return errShortTypedReceipt - default: - // It's an EIP-2718 typed tx receipt. - b, buf, err := getPooledBuffer(size) - if err != nil { - return err - } - defer encodeBufferPool.Put(buf) - if err := s.ReadBytes(b); err != nil { - return err - } - return r.decodeTyped(b) - } -} - -// UnmarshalBinary decodes the consensus encoding of receipts. -// It supports legacy RLP receipts and EIP-2718 typed receipts. -func (r *Receipt) UnmarshalBinary(b []byte) error { - if len(b) > 0 && b[0] > 0x7f { - // It's a legacy receipt decode the RLP - var data receiptRLP - err := rlp.DecodeBytes(b, &data) - if err != nil { - return err - } - r.Type = LegacyTxType - return r.setFromRLP(data) - } - // It's an EIP2718 typed transaction envelope. - return r.decodeTyped(b) -} - -// decodeTyped decodes a typed receipt from the canonical format. -func (r *Receipt) decodeTyped(b []byte) error { - if len(b) <= 1 { - return errShortTypedReceipt - } - switch b[0] { - case DynamicFeeTxType, AccessListTxType, BlobTxType: - var data receiptRLP - err := rlp.DecodeBytes(b[1:], &data) - if err != nil { - return err - } - r.Type = b[0] - return r.setFromRLP(data) - default: - return ErrTxTypeNotSupported - } -} - -func (r *Receipt) setFromRLP(data receiptRLP) error { - r.CumulativeGasUsed, r.Bloom, r.Logs = data.CumulativeGasUsed, data.Bloom, data.Logs - return r.setStatus(data.PostStateOrStatus) -} - -func (r *Receipt) setStatus(postStateOrStatus []byte) error { - switch { - case bytes.Equal(postStateOrStatus, receiptStatusSuccessfulRLP): - r.Status = ReceiptStatusSuccessful - case bytes.Equal(postStateOrStatus, receiptStatusFailedRLP): - r.Status = ReceiptStatusFailed - case len(postStateOrStatus) == len(common.Hash{}): - r.PostState = postStateOrStatus - default: - return fmt.Errorf("invalid receipt status %x", postStateOrStatus) - } - return nil -} - -func (r *Receipt) statusEncoding() []byte { - if len(r.PostState) == 0 { - if r.Status == ReceiptStatusFailed { - return receiptStatusFailedRLP - } - return receiptStatusSuccessfulRLP - } - return r.PostState -} - -// Size returns the approximate memory used by all internal contents. It is used -// to approximate and limit the memory consumption of various caches. -func (r *Receipt) Size() common.StorageSize { - size := common.StorageSize(unsafe.Sizeof(*r)) + common.StorageSize(len(r.PostState)) - size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{})) - for _, log := range r.Logs { - size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data)) - } - return size -} - -// ReceiptForStorage is a wrapper around a Receipt with RLP serialization -// that omits the Bloom field and deserialization that re-computes it. -type ReceiptForStorage Receipt - -// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt -// into an RLP stream. -func (r *ReceiptForStorage) EncodeRLP(_w io.Writer) error { - w := rlp.NewEncoderBuffer(_w) - outerList := w.List() - w.WriteBytes((*Receipt)(r).statusEncoding()) - w.WriteUint64(r.CumulativeGasUsed) - logList := w.List() - for _, log := range r.Logs { - if err := log.EncodeRLP(w); err != nil { - return err - } - } - w.ListEnd(logList) - w.ListEnd(outerList) - return w.Flush() -} - -// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation -// fields of a receipt from an RLP stream. -func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { - var stored storedReceiptRLP - if err := s.Decode(&stored); err != nil { - return err - } - if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { - return err - } - r.CumulativeGasUsed = stored.CumulativeGasUsed - r.Logs = stored.Logs - r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) - - return nil -} - -// Receipts implements DerivableList for receipts. -type Receipts []*Receipt - -// Len returns the number of receipts in this list. -func (rs Receipts) Len() int { return len(rs) } - -// EncodeIndex encodes the i'th receipt to w. -func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { - r := rs[i] - data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs} - if r.Type == LegacyTxType { - rlp.Encode(w, data) - return - } - w.WriteByte(r.Type) - switch r.Type { - case AccessListTxType, DynamicFeeTxType, BlobTxType: - rlp.Encode(w, data) - default: - // For unsupported types, write nothing. Since this is for - // DeriveSha, the error will be caught matching the derived hash - // to the block. - } -} - -// DeriveFields fills the receipts with their computed fields based on consensus -// data and contextual infos like containing block and transactions. -func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, baseFee *big.Int, blobGasPrice *big.Int, txs []*Transaction) error { - signer := MakeSigner(config, new(big.Int).SetUint64(number), time) - - logIndex := uint(0) - if len(txs) != len(rs) { - return errors.New("transaction and receipt count mismatch") - } - for i := 0; i < len(rs); i++ { - // The transaction type and hash can be retrieved from the transaction itself - rs[i].Type = txs[i].Type() - rs[i].TxHash = txs[i].Hash() - rs[i].EffectiveGasPrice = txs[i].inner.effectiveGasPrice(new(big.Int), baseFee) - - // EIP-4844 blob transaction fields - if txs[i].Type() == BlobTxType { - rs[i].BlobGasUsed = txs[i].BlobGas() - rs[i].BlobGasPrice = blobGasPrice - } - - // block location fields - rs[i].BlockHash = hash - rs[i].BlockNumber = new(big.Int).SetUint64(number) - rs[i].TransactionIndex = uint(i) - - // The contract address can be derived from the transaction itself - if txs[i].To() == nil { - // Deriving the signer is expensive, only do if it's actually needed - from, _ := Sender(signer, txs[i]) - rs[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) - } else { - rs[i].ContractAddress = common.Address{} - } - - // The used gas can be calculated based on previous r - if i == 0 { - rs[i].GasUsed = rs[i].CumulativeGasUsed - } else { - rs[i].GasUsed = rs[i].CumulativeGasUsed - rs[i-1].CumulativeGasUsed - } - - // The derived log fields can simply be set from the block and transaction - for j := 0; j < len(rs[i].Logs); j++ { - rs[i].Logs[j].BlockNumber = number - rs[i].Logs[j].BlockHash = hash - rs[i].Logs[j].TxHash = rs[i].TxHash - rs[i].Logs[j].TxIndex = uint(i) - rs[i].Logs[j].Index = logIndex - logIndex++ - } - } - return nil -} diff --git a/builder/core/types/receipt_test.go b/builder/core/types/receipt_test.go deleted file mode 100644 index a7b264447..000000000 --- a/builder/core/types/receipt_test.go +++ /dev/null @@ -1,529 +0,0 @@ -// 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 types - -import ( - "bytes" - "encoding/json" - "math" - "math/big" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/uint256" - "github.com/kylelemons/godebug/diff" -) - -var ( - legacyReceipt = &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - { - Address: common.BytesToAddress([]byte{0x01, 0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - }, - } - accessListReceipt = &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - { - Address: common.BytesToAddress([]byte{0x01, 0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - }, - Type: AccessListTxType, - } - eip1559Receipt = &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - { - Address: common.BytesToAddress([]byte{0x01, 0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - }, - Type: DynamicFeeTxType, - } - - // Create a few transactions to have receipts for - to2 = common.HexToAddress("0x2") - to3 = common.HexToAddress("0x3") - to4 = common.HexToAddress("0x4") - to5 = common.HexToAddress("0x5") - to6 = common.HexToAddress("0x6") - to7 = common.HexToAddress("0x7") - txs = Transactions{ - NewTx(&LegacyTx{ - Nonce: 1, - Value: big.NewInt(1), - Gas: 1, - GasPrice: big.NewInt(11), - }), - NewTx(&LegacyTx{ - To: &to2, - Nonce: 2, - Value: big.NewInt(2), - Gas: 2, - GasPrice: big.NewInt(22), - }), - NewTx(&AccessListTx{ - To: &to3, - Nonce: 3, - Value: big.NewInt(3), - Gas: 3, - GasPrice: big.NewInt(33), - }), - // EIP-1559 transactions. - NewTx(&DynamicFeeTx{ - To: &to4, - Nonce: 4, - Value: big.NewInt(4), - Gas: 4, - GasTipCap: big.NewInt(44), - GasFeeCap: big.NewInt(1044), - }), - NewTx(&DynamicFeeTx{ - To: &to5, - Nonce: 5, - Value: big.NewInt(5), - Gas: 5, - GasTipCap: big.NewInt(55), - GasFeeCap: big.NewInt(1055), - }), - // EIP-4844 transactions. - NewTx(&BlobTx{ - To: to6, - Nonce: 6, - Value: uint256.NewInt(6), - Gas: 6, - GasTipCap: uint256.NewInt(66), - GasFeeCap: uint256.NewInt(1066), - BlobFeeCap: uint256.NewInt(100066), - BlobHashes: []common.Hash{{}}, - }), - NewTx(&BlobTx{ - To: to7, - Nonce: 7, - Value: uint256.NewInt(7), - Gas: 7, - GasTipCap: uint256.NewInt(77), - GasFeeCap: uint256.NewInt(1077), - BlobFeeCap: uint256.NewInt(100077), - BlobHashes: []common.Hash{{}, {}, {}}, - }), - } - - blockNumber = big.NewInt(1) - blockTime = uint64(2) - blockHash = common.BytesToHash([]byte{0x03, 0x14}) - - // Create the corresponding receipts - receipts = Receipts{ - &Receipt{ - Status: ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 0, - }, - { - Address: common.BytesToAddress([]byte{0x01, 0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[0].Hash(), - TxIndex: 0, - BlockHash: blockHash, - Index: 1, - }, - }, - // derived fields: - TxHash: txs[0].Hash(), - ContractAddress: common.HexToAddress("0x5a443704dd4b594b382c22a083e2bd3090a6fef3"), - GasUsed: 1, - EffectiveGasPrice: big.NewInt(11), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 0, - }, - &Receipt{ - PostState: common.Hash{2}.Bytes(), - CumulativeGasUsed: 3, - Logs: []*Log{ - { - Address: common.BytesToAddress([]byte{0x22}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 2, - }, - { - Address: common.BytesToAddress([]byte{0x02, 0x22}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - // derived fields: - BlockNumber: blockNumber.Uint64(), - TxHash: txs[1].Hash(), - TxIndex: 1, - BlockHash: blockHash, - Index: 3, - }, - }, - // derived fields: - TxHash: txs[1].Hash(), - GasUsed: 2, - EffectiveGasPrice: big.NewInt(22), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 1, - }, - &Receipt{ - Type: AccessListTxType, - PostState: common.Hash{3}.Bytes(), - CumulativeGasUsed: 6, - Logs: []*Log{}, - // derived fields: - TxHash: txs[2].Hash(), - GasUsed: 3, - EffectiveGasPrice: big.NewInt(33), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 2, - }, - &Receipt{ - Type: DynamicFeeTxType, - PostState: common.Hash{4}.Bytes(), - CumulativeGasUsed: 10, - Logs: []*Log{}, - // derived fields: - TxHash: txs[3].Hash(), - GasUsed: 4, - EffectiveGasPrice: big.NewInt(1044), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 3, - }, - &Receipt{ - Type: DynamicFeeTxType, - PostState: common.Hash{5}.Bytes(), - CumulativeGasUsed: 15, - Logs: []*Log{}, - // derived fields: - TxHash: txs[4].Hash(), - GasUsed: 5, - EffectiveGasPrice: big.NewInt(1055), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 4, - }, - &Receipt{ - Type: BlobTxType, - PostState: common.Hash{6}.Bytes(), - CumulativeGasUsed: 21, - Logs: []*Log{}, - // derived fields: - TxHash: txs[5].Hash(), - GasUsed: 6, - EffectiveGasPrice: big.NewInt(1066), - BlobGasUsed: params.BlobTxBlobGasPerBlob, - BlobGasPrice: big.NewInt(920), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 5, - }, - &Receipt{ - Type: BlobTxType, - PostState: common.Hash{7}.Bytes(), - CumulativeGasUsed: 28, - Logs: []*Log{}, - // derived fields: - TxHash: txs[6].Hash(), - GasUsed: 7, - EffectiveGasPrice: big.NewInt(1077), - BlobGasUsed: 3 * params.BlobTxBlobGasPerBlob, - BlobGasPrice: big.NewInt(920), - BlockHash: blockHash, - BlockNumber: blockNumber, - TransactionIndex: 6, - }, - } -) - -func TestDecodeEmptyTypedReceipt(t *testing.T) { - input := []byte{0x80} - var r Receipt - err := rlp.DecodeBytes(input, &r) - if err != errShortTypedReceipt { - t.Fatal("wrong error:", err) - } -} - -// Tests that receipt data can be correctly derived from the contextual infos -func TestDeriveFields(t *testing.T) { - // Re-derive receipts. - basefee := big.NewInt(1000) - blobGasPrice := big.NewInt(920) - derivedReceipts := clearComputedFieldsOnReceipts(receipts) - err := Receipts(derivedReceipts).DeriveFields(params.TestChainConfig, blockHash, blockNumber.Uint64(), blockTime, basefee, blobGasPrice, txs) - if err != nil { - t.Fatalf("DeriveFields(...) = %v, want ", err) - } - - // Check diff of receipts against derivedReceipts. - r1, err := json.MarshalIndent(receipts, "", " ") - if err != nil { - t.Fatal("error marshaling input receipts:", err) - } - - r2, err := json.MarshalIndent(derivedReceipts, "", " ") - if err != nil { - t.Fatal("error marshaling derived receipts:", err) - } - d := diff.Diff(string(r1), string(r2)) - if d != "" { - t.Fatal("receipts differ:", d) - } -} - -// Test that we can marshal/unmarshal receipts to/from json without errors. -// This also confirms that our test receipts contain all the required fields. -func TestReceiptJSON(t *testing.T) { - for i := range receipts { - b, err := receipts[i].MarshalJSON() - if err != nil { - t.Fatal("error marshaling receipt to json:", err) - } - r := Receipt{} - err = r.UnmarshalJSON(b) - if err != nil { - t.Fatal("error unmarshaling receipt from json:", err) - } - } -} - -// Test we can still parse receipt without EffectiveGasPrice for backwards compatibility, even -// though it is required per the spec. -func TestEffectiveGasPriceNotRequired(t *testing.T) { - r := *receipts[0] - r.EffectiveGasPrice = nil - b, err := r.MarshalJSON() - if err != nil { - t.Fatal("error marshaling receipt to json:", err) - } - r2 := Receipt{} - err = r2.UnmarshalJSON(b) - if err != nil { - t.Fatal("error unmarshaling receipt from json:", err) - } -} - -// TestTypedReceiptEncodingDecoding reproduces a flaw that existed in the receipt -// rlp decoder, which failed due to a shadowing error. -func TestTypedReceiptEncodingDecoding(t *testing.T) { - var payload = common.FromHex("f9043eb9010c01f90108018262d4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010c01f901080182cd14b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f901090183013754b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f90109018301a194b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0") - check := func(bundle []*Receipt) { - t.Helper() - for i, receipt := range bundle { - if got, want := receipt.Type, uint8(1); got != want { - t.Fatalf("bundle %d: got %x, want %x", i, got, want) - } - } - } - { - var bundle []*Receipt - rlp.DecodeBytes(payload, &bundle) - check(bundle) - } - { - var bundle []*Receipt - r := bytes.NewReader(payload) - s := rlp.NewStream(r, uint64(len(payload))) - if err := s.Decode(&bundle); err != nil { - t.Fatal(err) - } - check(bundle) - } -} - -func TestReceiptMarshalBinary(t *testing.T) { - // Legacy Receipt - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) - have, err := legacyReceipt.MarshalBinary() - if err != nil { - t.Fatalf("marshal binary error: %v", err) - } - legacyReceipts := Receipts{legacyReceipt} - buf := new(bytes.Buffer) - legacyReceipts.EncodeIndex(0, buf) - haveEncodeIndex := buf.Bytes() - if !bytes.Equal(have, haveEncodeIndex) { - t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex) - } - buf.Reset() - if err := legacyReceipt.EncodeRLP(buf); err != nil { - t.Fatalf("encode rlp error: %v", err) - } - haveRLPEncode := buf.Bytes() - if !bytes.Equal(have, haveRLPEncode) { - t.Errorf("BinaryMarshal and EncodeRLP mismatch for legacy tx, got %x want %x", have, haveRLPEncode) - } - legacyWant := common.FromHex("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - if !bytes.Equal(have, legacyWant) { - t.Errorf("encoded RLP mismatch, got %x want %x", have, legacyWant) - } - - // 2930 Receipt - buf.Reset() - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) - have, err = accessListReceipt.MarshalBinary() - if err != nil { - t.Fatalf("marshal binary error: %v", err) - } - accessListReceipts := Receipts{accessListReceipt} - accessListReceipts.EncodeIndex(0, buf) - haveEncodeIndex = buf.Bytes() - if !bytes.Equal(have, haveEncodeIndex) { - t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex) - } - accessListWant := common.FromHex("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - if !bytes.Equal(have, accessListWant) { - t.Errorf("encoded RLP mismatch, got %x want %x", have, accessListWant) - } - - // 1559 Receipt - buf.Reset() - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) - have, err = eip1559Receipt.MarshalBinary() - if err != nil { - t.Fatalf("marshal binary error: %v", err) - } - eip1559Receipts := Receipts{eip1559Receipt} - eip1559Receipts.EncodeIndex(0, buf) - haveEncodeIndex = buf.Bytes() - if !bytes.Equal(have, haveEncodeIndex) { - t.Errorf("BinaryMarshal and EncodeIndex mismatch, got %x want %x", have, haveEncodeIndex) - } - eip1559Want := common.FromHex("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - if !bytes.Equal(have, eip1559Want) { - t.Errorf("encoded RLP mismatch, got %x want %x", have, eip1559Want) - } -} - -func TestReceiptUnmarshalBinary(t *testing.T) { - // Legacy Receipt - legacyBinary := common.FromHex("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - gotLegacyReceipt := new(Receipt) - if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil { - t.Fatalf("unmarshal binary error: %v", err) - } - legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) - if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) { - t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt) - } - - // 2930 Receipt - accessListBinary := common.FromHex("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - gotAccessListReceipt := new(Receipt) - if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil { - t.Fatalf("unmarshal binary error: %v", err) - } - accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) - if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) { - t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt) - } - - // 1559 Receipt - eip1559RctBinary := common.FromHex("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff") - got1559Receipt := new(Receipt) - if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil { - t.Fatalf("unmarshal binary error: %v", err) - } - eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) - if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) { - t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt) - } -} - -func clearComputedFieldsOnReceipts(receipts []*Receipt) []*Receipt { - r := make([]*Receipt, len(receipts)) - for i, receipt := range receipts { - r[i] = clearComputedFieldsOnReceipt(receipt) - } - return r -} - -func clearComputedFieldsOnReceipt(receipt *Receipt) *Receipt { - cpy := *receipt - cpy.TxHash = common.Hash{0xff, 0xff, 0x11} - cpy.BlockHash = common.Hash{0xff, 0xff, 0x22} - cpy.BlockNumber = big.NewInt(math.MaxUint32) - cpy.TransactionIndex = math.MaxUint32 - cpy.ContractAddress = common.Address{0xff, 0xff, 0x33} - cpy.GasUsed = 0xffffffff - cpy.Logs = clearComputedFieldsOnLogs(receipt.Logs) - cpy.EffectiveGasPrice = big.NewInt(0) - cpy.BlobGasUsed = 0 - cpy.BlobGasPrice = nil - return &cpy -} - -func clearComputedFieldsOnLogs(logs []*Log) []*Log { - l := make([]*Log, len(logs)) - for i, log := range logs { - cpy := *log - cpy.BlockNumber = math.MaxUint32 - cpy.BlockHash = common.Hash{} - cpy.TxHash = common.Hash{} - cpy.TxIndex = math.MaxUint32 - cpy.Index = math.MaxUint32 - l[i] = &cpy - } - return l -} diff --git a/builder/core/types/rlp_fuzzer_test.go b/builder/core/types/rlp_fuzzer_test.go deleted file mode 100644 index a3b9f7243..000000000 --- a/builder/core/types/rlp_fuzzer_test.go +++ /dev/null @@ -1,147 +0,0 @@ -// 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 types - -import ( - "bytes" - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/uint256" -) - -func decodeEncode(input []byte, val interface{}) error { - if err := rlp.DecodeBytes(input, val); err != nil { - // not valid rlp, nothing to do - return nil - } - // If it _were_ valid rlp, we can encode it again - output, err := rlp.EncodeToBytes(val) - if err != nil { - return err - } - if !bytes.Equal(input, output) { - return fmt.Errorf("encode-decode is not equal, \ninput : %x\noutput: %x", input, output) - } - return nil -} - -func FuzzRLP(f *testing.F) { - f.Fuzz(fuzzRlp) -} - -func fuzzRlp(t *testing.T, input []byte) { - if len(input) == 0 || len(input) > 500*1024 { - return - } - rlp.Split(input) - if elems, _, err := rlp.SplitList(input); err == nil { - rlp.CountValues(elems) - } - rlp.NewStream(bytes.NewReader(input), 0).Decode(new(interface{})) - if err := decodeEncode(input, new(interface{})); err != nil { - t.Fatal(err) - } - { - var v struct { - Int uint - String string - Bytes []byte - } - if err := decodeEncode(input, &v); err != nil { - t.Fatal(err) - } - } - { - type Types struct { - Bool bool - Raw rlp.RawValue - Slice []*Types - Iface []interface{} - } - var v Types - if err := decodeEncode(input, &v); err != nil { - t.Fatal(err) - } - } - { - type AllTypes struct { - Int uint - String string - Bytes []byte - Bool bool - Raw rlp.RawValue - Slice []*AllTypes - Array [3]*AllTypes - Iface []interface{} - } - var v AllTypes - if err := decodeEncode(input, &v); err != nil { - t.Fatal(err) - } - } - { - if err := decodeEncode(input, [10]byte{}); err != nil { - t.Fatal(err) - } - } - { - var v struct { - Byte [10]byte - Rool [10]bool - } - if err := decodeEncode(input, &v); err != nil { - t.Fatal(err) - } - } - { - var h Header - if err := decodeEncode(input, &h); err != nil { - t.Fatal(err) - } - var b Block - if err := decodeEncode(input, &b); err != nil { - t.Fatal(err) - } - var tx Transaction - if err := decodeEncode(input, &tx); err != nil { - t.Fatal(err) - } - var txs Transactions - if err := decodeEncode(input, &txs); err != nil { - t.Fatal(err) - } - var rs Receipts - if err := decodeEncode(input, &rs); err != nil { - t.Fatal(err) - } - } - { - var v struct { - AnIntPtr *big.Int - AnInt big.Int - AnU256Ptr *uint256.Int - AnU256 uint256.Int - NotAnU256 [4]uint64 - } - if err := decodeEncode(input, &v); err != nil { - t.Fatal(err) - } - } -} diff --git a/builder/core/types/sbundle.go b/builder/core/types/sbundle.go deleted file mode 100644 index 27567ce89..000000000 --- a/builder/core/types/sbundle.go +++ /dev/null @@ -1,116 +0,0 @@ -package types - -import ( - "errors" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" -) - -var ( - ErrIncorrectRefundConfig = errors.New("incorrect refund config") -) - -// SBundle is a bundle of transactions that must be executed atomically -// unlike ordinary bundle it also supports refunds -type SBundle struct { - Inclusion BundleInclusion - Body []BundleBody - Validity BundleValidity - - hash atomic.Value -} - -type BundleInclusion struct { - BlockNumber uint64 - MaxBlockNumber uint64 -} - -type BundleBody struct { - Tx *Transaction - Bundle *SBundle - CanRevert bool -} - -type BundleValidity struct { - Refund []RefundConstraint `json:"refund,omitempty"` - RefundConfig []RefundConfig `json:"refundConfig,omitempty"` -} - -type RefundConstraint struct { - BodyIdx int `json:"bodyIdx"` - Percent int `json:"percent"` -} - -type RefundConfig struct { - Address common.Address `json:"address"` - Percent int `json:"percent"` -} - -type BundlePrivacy struct { - RefundAddress common.Address -} - -func (b *SBundle) Hash() common.Hash { - if hash := b.hash.Load(); hash != nil { - return hash.(common.Hash) - } - - bodyHashes := make([]common.Hash, len(b.Body)) - for i, body := range b.Body { - if body.Tx != nil { - bodyHashes[i] = body.Tx.Hash() - } else if body.Bundle != nil { - bodyHashes[i] = body.Bundle.Hash() - } - } - - var h common.Hash - if len(bodyHashes) == 1 { - h = bodyHashes[0] - } else { - hasher := sha3.NewLegacyKeccak256() - for _, h := range bodyHashes { - hasher.Write(h[:]) - } - h = common.BytesToHash(hasher.Sum(nil)) - } - b.hash.Store(h) - return h -} - -type SimSBundle struct { - Bundle *SBundle - // MevGasPrice = (total coinbase profit) / (gas used) - MevGasPrice *uint256.Int - Profit *uint256.Int -} - -func GetRefundConfig(body *BundleBody, signer Signer) ([]RefundConfig, error) { - if body.Tx != nil { - address, err := signer.Sender(body.Tx) - if err != nil { - return nil, err - } - return []RefundConfig{{Address: address, Percent: 100}}, nil - } - if bundle := body.Bundle; bundle != nil { - if len(bundle.Validity.RefundConfig) > 0 { - return bundle.Validity.RefundConfig, nil - } else { - if len(bundle.Body) == 0 { - return nil, ErrIncorrectRefundConfig - } - return GetRefundConfig(&bundle.Body[0], signer) - } - } - return nil, ErrIncorrectRefundConfig -} - -// UsedSBundle is a bundle that was used in the block building -type UsedSBundle struct { - Bundle *SBundle - Success bool -} diff --git a/builder/core/types/state_account.go b/builder/core/types/state_account.go deleted file mode 100644 index 52ef843b3..000000000 --- a/builder/core/types/state_account.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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 types - -import ( - "bytes" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/uint256" -) - -//go:generate go run ../../rlp/rlpgen -type StateAccount -out gen_account_rlp.go - -// StateAccount is the Ethereum consensus representation of accounts. -// These objects are stored in the main account trie. -type StateAccount struct { - Nonce uint64 - Balance *uint256.Int - Root common.Hash // merkle root of the storage trie - CodeHash []byte -} - -// NewEmptyStateAccount constructs an empty state account. -func NewEmptyStateAccount() *StateAccount { - return &StateAccount{ - Balance: new(uint256.Int), - Root: EmptyRootHash, - CodeHash: EmptyCodeHash.Bytes(), - } -} - -// Copy returns a deep-copied state account object. -func (acct *StateAccount) Copy() *StateAccount { - var balance *uint256.Int - if acct.Balance != nil { - balance = new(uint256.Int).Set(acct.Balance) - } - return &StateAccount{ - Nonce: acct.Nonce, - Balance: balance, - Root: acct.Root, - CodeHash: common.CopyBytes(acct.CodeHash), - } -} - -// SlimAccount is a modified version of an Account, where the root is replaced -// with a byte slice. This format can be used to represent full-consensus format -// or slim format which replaces the empty root and code hash as nil byte slice. -type SlimAccount struct { - Nonce uint64 - Balance *uint256.Int - Root []byte // Nil if root equals to types.EmptyRootHash - CodeHash []byte // Nil if hash equals to types.EmptyCodeHash -} - -// SlimAccountRLP encodes the state account in 'slim RLP' format. -func SlimAccountRLP(account StateAccount) []byte { - slim := SlimAccount{ - Nonce: account.Nonce, - Balance: account.Balance, - } - if account.Root != EmptyRootHash { - slim.Root = account.Root[:] - } - if !bytes.Equal(account.CodeHash, EmptyCodeHash[:]) { - slim.CodeHash = account.CodeHash - } - data, err := rlp.EncodeToBytes(slim) - if err != nil { - panic(err) - } - return data -} - -// FullAccount decodes the data on the 'slim RLP' format and returns -// the consensus format account. -func FullAccount(data []byte) (*StateAccount, error) { - var slim SlimAccount - if err := rlp.DecodeBytes(data, &slim); err != nil { - return nil, err - } - var account StateAccount - account.Nonce, account.Balance = slim.Nonce, slim.Balance - - // Interpret the storage root and code hash in slim format. - if len(slim.Root) == 0 { - account.Root = EmptyRootHash - } else { - account.Root = common.BytesToHash(slim.Root) - } - if len(slim.CodeHash) == 0 { - account.CodeHash = EmptyCodeHash[:] - } else { - account.CodeHash = slim.CodeHash - } - return &account, nil -} - -// FullAccountRLP converts data on the 'slim RLP' format into the full RLP-format. -func FullAccountRLP(data []byte) ([]byte, error) { - account, err := FullAccount(data) - if err != nil { - return nil, err - } - return rlp.EncodeToBytes(account) -} diff --git a/builder/core/types/transaction.go b/builder/core/types/transaction.go deleted file mode 100644 index 96c6e5c57..000000000 --- a/builder/core/types/transaction.go +++ /dev/null @@ -1,705 +0,0 @@ -// 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 types - -import ( - "bytes" - "crypto/sha256" - "encoding/binary" - "errors" - "fmt" - "io" - "math/big" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" - "github.com/google/uuid" - "github.com/holiman/uint256" -) - -var ( - ErrInvalidSig = errors.New("invalid transaction v, r, s values") - ErrUnexpectedProtection = errors.New("transaction type does not supported EIP-155 protected signatures") - ErrInvalidTxType = errors.New("transaction type not valid in this context") - ErrTxTypeNotSupported = errors.New("transaction type not supported") - ErrGasFeeCapTooLow = errors.New("fee cap less than base fee") - errShortTypedTx = errors.New("typed transaction too short") - errInvalidYParity = errors.New("'yParity' field must be 0 or 1") - errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match") - errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction") -) - -// Transaction types. -const ( - LegacyTxType = 0x00 - AccessListTxType = 0x01 - DynamicFeeTxType = 0x02 - BlobTxType = 0x03 -) - -// Transaction is an Ethereum transaction. -type Transaction struct { - inner TxData // Consensus contents of a transaction - time time.Time // Time first seen locally (spam avoidance) - - // caches - hash atomic.Value - size atomic.Value - from atomic.Value -} - -// NewTx creates a new transaction. -func NewTx(inner TxData) *Transaction { - tx := new(Transaction) - tx.setDecoded(inner.copy(), 0) - return tx -} - -// TxData is the underlying data of a transaction. -// -// This is implemented by DynamicFeeTx, LegacyTx and AccessListTx. -type TxData interface { - txType() byte // returns the type ID - copy() TxData // creates a deep copy and initializes all fields - - chainID() *big.Int - accessList() AccessList - data() []byte - gas() uint64 - gasPrice() *big.Int - gasTipCap() *big.Int - gasFeeCap() *big.Int - value() *big.Int - nonce() uint64 - to() *common.Address - - rawSignatureValues() (v, r, s *big.Int) - setSignatureValues(chainID, v, r, s *big.Int) - - // effectiveGasPrice computes the gas price paid by the transaction, given - // the inclusion block baseFee. - // - // Unlike other TxData methods, the returned *big.Int should be an independent - // copy of the computed value, i.e. callers are allowed to mutate the result. - // Method implementations can use 'dst' to store the result. - effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int - - encode(*bytes.Buffer) error - decode([]byte) error -} - -// EncodeRLP implements rlp.Encoder -func (tx *Transaction) EncodeRLP(w io.Writer) error { - if tx.Type() == LegacyTxType { - return rlp.Encode(w, tx.inner) - } - // It's an EIP-2718 typed TX envelope. - buf := encodeBufferPool.Get().(*bytes.Buffer) - defer encodeBufferPool.Put(buf) - buf.Reset() - if err := tx.encodeTyped(buf); err != nil { - return err - } - return rlp.Encode(w, buf.Bytes()) -} - -// encodeTyped writes the canonical encoding of a typed transaction to w. -func (tx *Transaction) encodeTyped(w *bytes.Buffer) error { - w.WriteByte(tx.Type()) - return tx.inner.encode(w) -} - -// MarshalBinary returns the canonical encoding of the transaction. -// For legacy transactions, it returns the RLP encoding. For EIP-2718 typed -// transactions, it returns the type and payload. -func (tx *Transaction) MarshalBinary() ([]byte, error) { - if tx.Type() == LegacyTxType { - return rlp.EncodeToBytes(tx.inner) - } - var buf bytes.Buffer - err := tx.encodeTyped(&buf) - return buf.Bytes(), err -} - -// DecodeRLP implements rlp.Decoder -func (tx *Transaction) DecodeRLP(s *rlp.Stream) error { - kind, size, err := s.Kind() - switch { - case err != nil: - return err - case kind == rlp.List: - // It's a legacy transaction. - var inner LegacyTx - err := s.Decode(&inner) - if err == nil { - tx.setDecoded(&inner, rlp.ListSize(size)) - } - return err - case kind == rlp.Byte: - return errShortTypedTx - default: - // It's an EIP-2718 typed TX envelope. - // First read the tx payload bytes into a temporary buffer. - b, buf, err := getPooledBuffer(size) - if err != nil { - return err - } - defer encodeBufferPool.Put(buf) - if err := s.ReadBytes(b); err != nil { - return err - } - // Now decode the inner transaction. - inner, err := tx.decodeTyped(b) - if err == nil { - tx.setDecoded(inner, size) - } - return err - } -} - -// UnmarshalBinary decodes the canonical encoding of transactions. -// It supports legacy RLP transactions and EIP-2718 typed transactions. -func (tx *Transaction) UnmarshalBinary(b []byte) error { - if len(b) > 0 && b[0] > 0x7f { - // It's a legacy transaction. - var data LegacyTx - err := rlp.DecodeBytes(b, &data) - if err != nil { - return err - } - tx.setDecoded(&data, uint64(len(b))) - return nil - } - // It's an EIP-2718 typed transaction envelope. - inner, err := tx.decodeTyped(b) - if err != nil { - return err - } - tx.setDecoded(inner, uint64(len(b))) - return nil -} - -// decodeTyped decodes a typed transaction from the canonical format. -func (tx *Transaction) decodeTyped(b []byte) (TxData, error) { - if len(b) <= 1 { - return nil, errShortTypedTx - } - var inner TxData - switch b[0] { - case AccessListTxType: - inner = new(AccessListTx) - case DynamicFeeTxType: - inner = new(DynamicFeeTx) - case BlobTxType: - inner = new(BlobTx) - default: - return nil, ErrTxTypeNotSupported - } - err := inner.decode(b[1:]) - return inner, err -} - -// setDecoded sets the inner transaction and size after decoding. -func (tx *Transaction) setDecoded(inner TxData, size uint64) { - tx.inner = inner - tx.time = time.Now() - if size > 0 { - tx.size.Store(size) - } -} - -func sanityCheckSignature(v *big.Int, r *big.Int, s *big.Int, maybeProtected bool) error { - if isProtectedV(v) && !maybeProtected { - return ErrUnexpectedProtection - } - - var plainV byte - if isProtectedV(v) { - chainID := deriveChainId(v).Uint64() - plainV = byte(v.Uint64() - 35 - 2*chainID) - } else if maybeProtected { - // Only EIP-155 signatures can be optionally protected. Since - // we determined this v value is not protected, it must be a - // raw 27 or 28. - plainV = byte(v.Uint64() - 27) - } else { - // If the signature is not optionally protected, we assume it - // must already be equal to the recovery id. - plainV = byte(v.Uint64()) - } - if !crypto.ValidateSignatureValues(plainV, r, s, false) { - return ErrInvalidSig - } - - return nil -} - -func isProtectedV(V *big.Int) bool { - if V.BitLen() <= 8 { - v := V.Uint64() - return v != 27 && v != 28 && v != 1 && v != 0 - } - // anything not 27 or 28 is considered protected - return true -} - -// Protected says whether the transaction is replay-protected. -func (tx *Transaction) Protected() bool { - switch tx := tx.inner.(type) { - case *LegacyTx: - return tx.V != nil && isProtectedV(tx.V) - default: - return true - } -} - -// Type returns the transaction type. -func (tx *Transaction) Type() uint8 { - return tx.inner.txType() -} - -// ChainId returns the EIP155 chain ID of the transaction. The return value will always be -// non-nil. For legacy transactions which are not replay-protected, the return value is -// zero. -func (tx *Transaction) ChainId() *big.Int { - return tx.inner.chainID() -} - -// Data returns the input data of the transaction. -func (tx *Transaction) Data() []byte { return tx.inner.data() } - -// AccessList returns the access list of the transaction. -func (tx *Transaction) AccessList() AccessList { return tx.inner.accessList() } - -// Gas returns the gas limit of the transaction. -func (tx *Transaction) Gas() uint64 { return tx.inner.gas() } - -// GasPrice returns the gas price of the transaction. -func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.inner.gasPrice()) } - -// GasTipCap returns the gasTipCap per gas of the transaction. -func (tx *Transaction) GasTipCap() *big.Int { return new(big.Int).Set(tx.inner.gasTipCap()) } - -// GasFeeCap returns the fee cap per gas of the transaction. -func (tx *Transaction) GasFeeCap() *big.Int { return new(big.Int).Set(tx.inner.gasFeeCap()) } - -// Value returns the ether amount of the transaction. -func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.inner.value()) } - -// Nonce returns the sender account nonce of the transaction. -func (tx *Transaction) Nonce() uint64 { return tx.inner.nonce() } - -// To returns the recipient address of the transaction. -// For contract-creation transactions, To returns nil. -func (tx *Transaction) To() *common.Address { - return copyAddressPtr(tx.inner.to()) -} - -// Cost returns (gas * gasPrice) + (blobGas * blobGasPrice) + value. -func (tx *Transaction) Cost() *big.Int { - total := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) - if tx.Type() == BlobTxType { - total.Add(total, new(big.Int).Mul(tx.BlobGasFeeCap(), new(big.Int).SetUint64(tx.BlobGas()))) - } - total.Add(total, tx.Value()) - return total -} - -// RawSignatureValues returns the V, R, S signature values of the transaction. -// The return values should not be modified by the caller. -// The return values may be nil or zero, if the transaction is unsigned. -func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) { - return tx.inner.rawSignatureValues() -} - -// GasFeeCapCmp compares the fee cap of two transactions. -func (tx *Transaction) GasFeeCapCmp(other *Transaction) int { - return tx.inner.gasFeeCap().Cmp(other.inner.gasFeeCap()) -} - -// GasFeeCapIntCmp compares the fee cap of the transaction against the given fee cap. -func (tx *Transaction) GasFeeCapIntCmp(other *big.Int) int { - return tx.inner.gasFeeCap().Cmp(other) -} - -// GasTipCapCmp compares the gasTipCap of two transactions. -func (tx *Transaction) GasTipCapCmp(other *Transaction) int { - return tx.inner.gasTipCap().Cmp(other.inner.gasTipCap()) -} - -// GasTipCapIntCmp compares the gasTipCap of the transaction against the given gasTipCap. -func (tx *Transaction) GasTipCapIntCmp(other *big.Int) int { - return tx.inner.gasTipCap().Cmp(other) -} - -// EffectiveGasTip returns the effective miner gasTipCap for the given base fee. -// Note: if the effective gasTipCap is negative, this method returns both error -// the actual negative value, _and_ ErrGasFeeCapTooLow -func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) { - if baseFee == nil { - return tx.GasTipCap(), nil - } - var err error - gasFeeCap := tx.GasFeeCap() - if gasFeeCap.Cmp(baseFee) == -1 { - err = ErrGasFeeCapTooLow - } - return math.BigMin(tx.GasTipCap(), gasFeeCap.Sub(gasFeeCap, baseFee)), err -} - -// EffectiveGasTipValue is identical to EffectiveGasTip, but does not return an -// error in case the effective gasTipCap is negative -func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int { - effectiveTip, _ := tx.EffectiveGasTip(baseFee) - return effectiveTip -} - -// EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee. -func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *big.Int) int { - if baseFee == nil { - return tx.GasTipCapCmp(other) - } - return tx.EffectiveGasTipValue(baseFee).Cmp(other.EffectiveGasTipValue(baseFee)) -} - -// EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap. -func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) int { - if baseFee == nil { - return tx.GasTipCapIntCmp(other) - } - return tx.EffectiveGasTipValue(baseFee).Cmp(other) -} - -// BlobGas returns the blob gas limit of the transaction for blob transactions, 0 otherwise. -func (tx *Transaction) BlobGas() uint64 { - if blobtx, ok := tx.inner.(*BlobTx); ok { - return blobtx.blobGas() - } - return 0 -} - -// BlobGasFeeCap returns the blob gas fee cap per blob gas of the transaction for blob transactions, nil otherwise. -func (tx *Transaction) BlobGasFeeCap() *big.Int { - if blobtx, ok := tx.inner.(*BlobTx); ok { - return blobtx.BlobFeeCap.ToBig() - } - return nil -} - -// BlobHashes returns the hashes of the blob commitments for blob transactions, nil otherwise. -func (tx *Transaction) BlobHashes() []common.Hash { - if blobtx, ok := tx.inner.(*BlobTx); ok { - return blobtx.BlobHashes - } - return nil -} - -// BlobTxSidecar returns the sidecar of a blob transaction, nil otherwise. -func (tx *Transaction) BlobTxSidecar() *BlobTxSidecar { - if blobtx, ok := tx.inner.(*BlobTx); ok { - return blobtx.Sidecar - } - return nil -} - -// BlobGasFeeCapCmp compares the blob fee cap of two transactions. -func (tx *Transaction) BlobGasFeeCapCmp(other *Transaction) int { - return tx.BlobGasFeeCap().Cmp(other.BlobGasFeeCap()) -} - -// BlobGasFeeCapIntCmp compares the blob fee cap of the transaction against the given blob fee cap. -func (tx *Transaction) BlobGasFeeCapIntCmp(other *big.Int) int { - return tx.BlobGasFeeCap().Cmp(other) -} - -// WithoutBlobTxSidecar returns a copy of tx with the blob sidecar removed. -func (tx *Transaction) WithoutBlobTxSidecar() *Transaction { - blobtx, ok := tx.inner.(*BlobTx) - if !ok { - return tx - } - cpy := &Transaction{ - inner: blobtx.withoutSidecar(), - time: tx.time, - } - // Note: tx.size cache not carried over because the sidecar is included in size! - if h := tx.hash.Load(); h != nil { - cpy.hash.Store(h) - } - if f := tx.from.Load(); f != nil { - cpy.from.Store(f) - } - return cpy -} - -// SetTime sets the decoding time of a transaction. This is used by tests to set -// arbitrary times and by persistent transaction pools when loading old txs from -// disk. -func (tx *Transaction) SetTime(t time.Time) { - tx.time = t -} - -// Time returns the time when the transaction was first seen on the network. It -// is a heuristic to prefer mining older txs vs new all other things equal. -func (tx *Transaction) Time() time.Time { - return tx.time -} - -// Hash returns the transaction hash. -func (tx *Transaction) Hash() common.Hash { - if hash := tx.hash.Load(); hash != nil { - return hash.(common.Hash) - } - - var h common.Hash - if tx.Type() == LegacyTxType { - h = rlpHash(tx.inner) - } else { - h = prefixedRlpHash(tx.Type(), tx.inner) - } - tx.hash.Store(h) - return h -} - -// Size returns the true encoded storage size of the transaction, either by encoding -// and returning it, or returning a previously cached value. -func (tx *Transaction) Size() uint64 { - if size := tx.size.Load(); size != nil { - return size.(uint64) - } - - // Cache miss, encode and cache. - // Note we rely on the assumption that all tx.inner values are RLP-encoded! - c := writeCounter(0) - rlp.Encode(&c, &tx.inner) - size := uint64(c) - - // For blob transactions, add the size of the blob content and the outer list of the - // tx + sidecar encoding. - if sc := tx.BlobTxSidecar(); sc != nil { - size += rlp.ListSize(sc.encodedSize()) - } - - // For typed transactions, the encoding also includes the leading type byte. - if tx.Type() != LegacyTxType { - size += 1 - } - - tx.size.Store(size) - return size -} - -// WithSignature returns a new transaction with the given signature. -// This signature needs to be in the [R || S || V] format where V is 0 or 1. -func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) { - r, s, v, err := signer.SignatureValues(tx, sig) - if err != nil { - return nil, err - } - if r == nil || s == nil || v == nil { - return nil, fmt.Errorf("%w: r: %s, s: %s, v: %s", ErrInvalidSig, r, s, v) - } - cpy := tx.inner.copy() - cpy.setSignatureValues(signer.ChainID(), v, r, s) - return &Transaction{inner: cpy, time: tx.time}, nil -} - -// Transactions implements DerivableList for transactions. -type Transactions []*Transaction - -// Len returns the length of s. -func (s Transactions) Len() int { return len(s) } - -// EncodeIndex encodes the i'th transaction to w. Note that this does not check for errors -// because we assume that *Transaction will only ever contain valid txs that were either -// constructed by decoding or via public API in this package. -func (s Transactions) EncodeIndex(i int, w *bytes.Buffer) { - tx := s[i] - if tx.Type() == LegacyTxType { - rlp.Encode(w, tx.inner) - } else { - tx.encodeTyped(w) - } -} - -// TxDifference returns a new set which is the difference between a and b. -func TxDifference(a, b Transactions) Transactions { - keep := make(Transactions, 0, len(a)) - - remove := make(map[common.Hash]struct{}) - for _, tx := range b { - remove[tx.Hash()] = struct{}{} - } - - for _, tx := range a { - if _, ok := remove[tx.Hash()]; !ok { - keep = append(keep, tx) - } - } - - return keep -} - -// HashDifference returns a new set which is the difference between a and b. -func HashDifference(a, b []common.Hash) []common.Hash { - keep := make([]common.Hash, 0, len(a)) - - remove := make(map[common.Hash]struct{}) - for _, hash := range b { - remove[hash] = struct{}{} - } - - for _, hash := range a { - if _, ok := remove[hash]; !ok { - keep = append(keep, hash) - } - } - - return keep -} - -// TxByNonce implements the sort interface to allow sorting a list of transactions -// by their nonces. This is usually only useful for sorting transactions from a -// single account, otherwise a nonce comparison doesn't make much sense. -type TxByNonce Transactions - -func (s TxByNonce) Len() int { return len(s) } -func (s TxByNonce) Less(i, j int) bool { return s[i].Nonce() < s[j].Nonce() } -func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -// copyAddressPtr copies an address. -func copyAddressPtr(a *common.Address) *common.Address { - if a == nil { - return nil - } - cpy := *a - return &cpy -} - -var EmptyUUID uuid.UUID - -type LatestUuidBundle struct { - Uuid uuid.UUID - SigningAddress common.Address - BundleHash common.Hash - BundleUUID uuid.UUID -} - -type MevBundle struct { - Txs Transactions - BlockNumber *big.Int - Uuid uuid.UUID - SigningAddress common.Address - MinTimestamp uint64 - MaxTimestamp uint64 - RevertingTxHashes []common.Hash - Hash common.Hash -} - -func (b *MevBundle) UniquePayload() []byte { - var buf []byte - buf = binary.AppendVarint(buf, b.BlockNumber.Int64()) - buf = append(buf, b.Hash[:]...) - sort.Slice(b.RevertingTxHashes, func(i, j int) bool { - return bytes.Compare(b.RevertingTxHashes[i][:], b.RevertingTxHashes[j][:]) <= 0 - }) - for _, txHash := range b.RevertingTxHashes { - buf = append(buf, txHash[:]...) - } - return buf -} - -func (b *MevBundle) ComputeUUID() uuid.UUID { - return uuid.NewHash(sha256.New(), uuid.Nil, b.UniquePayload(), 5) -} - -func (b *MevBundle) RevertingHash(hash common.Hash) bool { - for _, revHash := range b.RevertingTxHashes { - if revHash == hash { - return true - } - } - return false -} - -type SimulatedBundle struct { - MevGasPrice *uint256.Int - TotalEth *uint256.Int - EthSentToCoinbase *uint256.Int - TotalGasUsed uint64 - OriginalBundle MevBundle -} - -type TimestampedTxHashSet struct { - lock sync.RWMutex - timestamps map[common.Hash]time.Time - ttl time.Duration -} - -func NewExpiringTxHashSet(ttl time.Duration) *TimestampedTxHashSet { - s := &TimestampedTxHashSet{ - timestamps: make(map[common.Hash]time.Time), - ttl: ttl, - } - - return s -} - -func (s *TimestampedTxHashSet) Add(hash common.Hash) { - s.lock.Lock() - defer s.lock.Unlock() - - _, ok := s.timestamps[hash] - if !ok { - s.timestamps[hash] = time.Now().Add(s.ttl) - } -} - -func (s *TimestampedTxHashSet) Contains(hash common.Hash) bool { - s.lock.RLock() - defer s.lock.RUnlock() - _, ok := s.timestamps[hash] - return ok -} - -func (s *TimestampedTxHashSet) Remove(hash common.Hash) { - s.lock.Lock() - defer s.lock.Unlock() - - _, ok := s.timestamps[hash] - if ok { - delete(s.timestamps, hash) - } -} - -func (s *TimestampedTxHashSet) Prune() { - s.lock.Lock() - defer s.lock.Unlock() - - now := time.Now() - for hash, ts := range s.timestamps { - if ts.Before(now) { - delete(s.timestamps, hash) - } - } -} diff --git a/builder/core/types/transaction_marshalling.go b/builder/core/types/transaction_marshalling.go deleted file mode 100644 index 4d5b2bcdd..000000000 --- a/builder/core/types/transaction_marshalling.go +++ /dev/null @@ -1,421 +0,0 @@ -// 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 types - -import ( - "encoding/json" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/holiman/uint256" -) - -// txJSON is the JSON representation of transactions. -type txJSON struct { - Type hexutil.Uint64 `json:"type"` - - ChainID *hexutil.Big `json:"chainId,omitempty"` - Nonce *hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - Gas *hexutil.Uint64 `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` - MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` - MaxFeePerBlobGas *hexutil.Big `json:"maxFeePerBlobGas,omitempty"` - Value *hexutil.Big `json:"value"` - Input *hexutil.Bytes `json:"input"` - AccessList *AccessList `json:"accessList,omitempty"` - BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` - YParity *hexutil.Uint64 `json:"yParity,omitempty"` - - // Blob transaction sidecar encoding: - Blobs []kzg4844.Blob `json:"blobs,omitempty"` - Commitments []kzg4844.Commitment `json:"commitments,omitempty"` - Proofs []kzg4844.Proof `json:"proofs,omitempty"` - - // Only used for encoding: - Hash common.Hash `json:"hash"` -} - -// yParityValue returns the YParity value from JSON. For backwards-compatibility reasons, -// this can be given in the 'v' field or the 'yParity' field. If both exist, they must match. -func (tx *txJSON) yParityValue() (*big.Int, error) { - if tx.YParity != nil { - val := uint64(*tx.YParity) - if val != 0 && val != 1 { - return nil, errInvalidYParity - } - bigval := new(big.Int).SetUint64(val) - if tx.V != nil && tx.V.ToInt().Cmp(bigval) != 0 { - return nil, errVYParityMismatch - } - return bigval, nil - } - if tx.V != nil { - return tx.V.ToInt(), nil - } - return nil, errVYParityMissing -} - -// MarshalJSON marshals as JSON with a hash. -func (tx *Transaction) MarshalJSON() ([]byte, error) { - var enc txJSON - // These are set for all tx types. - enc.Hash = tx.Hash() - enc.Type = hexutil.Uint64(tx.Type()) - - // Other fields are set conditionally depending on tx type. - switch itx := tx.inner.(type) { - case *LegacyTx: - enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() - enc.Gas = (*hexutil.Uint64)(&itx.Gas) - enc.GasPrice = (*hexutil.Big)(itx.GasPrice) - enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.V = (*hexutil.Big)(itx.V) - enc.R = (*hexutil.Big)(itx.R) - enc.S = (*hexutil.Big)(itx.S) - if tx.Protected() { - enc.ChainID = (*hexutil.Big)(tx.ChainId()) - } - - case *AccessListTx: - enc.ChainID = (*hexutil.Big)(itx.ChainID) - enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() - enc.Gas = (*hexutil.Uint64)(&itx.Gas) - enc.GasPrice = (*hexutil.Big)(itx.GasPrice) - enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList - enc.V = (*hexutil.Big)(itx.V) - enc.R = (*hexutil.Big)(itx.R) - enc.S = (*hexutil.Big)(itx.S) - yparity := itx.V.Uint64() - enc.YParity = (*hexutil.Uint64)(&yparity) - - case *DynamicFeeTx: - enc.ChainID = (*hexutil.Big)(itx.ChainID) - enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.To = tx.To() - enc.Gas = (*hexutil.Uint64)(&itx.Gas) - enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap) - enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap) - enc.Value = (*hexutil.Big)(itx.Value) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList - enc.V = (*hexutil.Big)(itx.V) - enc.R = (*hexutil.Big)(itx.R) - enc.S = (*hexutil.Big)(itx.S) - yparity := itx.V.Uint64() - enc.YParity = (*hexutil.Uint64)(&yparity) - - case *BlobTx: - enc.ChainID = (*hexutil.Big)(itx.ChainID.ToBig()) - enc.Nonce = (*hexutil.Uint64)(&itx.Nonce) - enc.Gas = (*hexutil.Uint64)(&itx.Gas) - enc.MaxFeePerGas = (*hexutil.Big)(itx.GasFeeCap.ToBig()) - enc.MaxPriorityFeePerGas = (*hexutil.Big)(itx.GasTipCap.ToBig()) - enc.MaxFeePerBlobGas = (*hexutil.Big)(itx.BlobFeeCap.ToBig()) - enc.Value = (*hexutil.Big)(itx.Value.ToBig()) - enc.Input = (*hexutil.Bytes)(&itx.Data) - enc.AccessList = &itx.AccessList - enc.BlobVersionedHashes = itx.BlobHashes - enc.To = tx.To() - enc.V = (*hexutil.Big)(itx.V.ToBig()) - enc.R = (*hexutil.Big)(itx.R.ToBig()) - enc.S = (*hexutil.Big)(itx.S.ToBig()) - yparity := itx.V.Uint64() - enc.YParity = (*hexutil.Uint64)(&yparity) - if sidecar := itx.Sidecar; sidecar != nil { - enc.Blobs = itx.Sidecar.Blobs - enc.Commitments = itx.Sidecar.Commitments - enc.Proofs = itx.Sidecar.Proofs - } - } - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (tx *Transaction) UnmarshalJSON(input []byte) error { - var dec txJSON - err := json.Unmarshal(input, &dec) - if err != nil { - return err - } - - // Decode / verify fields according to transaction type. - var inner TxData - switch dec.Type { - case LegacyTxType: - var itx LegacyTx - inner = &itx - if dec.Nonce == nil { - return errors.New("missing required field 'nonce' in transaction") - } - itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' in transaction") - } - itx.Gas = uint64(*dec.Gas) - if dec.GasPrice == nil { - return errors.New("missing required field 'gasPrice' in transaction") - } - itx.GasPrice = (*big.Int)(dec.GasPrice) - if dec.Value == nil { - return errors.New("missing required field 'value' in transaction") - } - itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { - return errors.New("missing required field 'input' in transaction") - } - itx.Data = *dec.Input - - // signature R - if dec.R == nil { - return errors.New("missing required field 'r' in transaction") - } - itx.R = (*big.Int)(dec.R) - // signature S - if dec.S == nil { - return errors.New("missing required field 's' in transaction") - } - itx.S = (*big.Int)(dec.S) - // signature V - if dec.V == nil { - return errors.New("missing required field 'v' in transaction") - } - itx.V = (*big.Int)(dec.V) - if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 { - if err := sanityCheckSignature(itx.V, itx.R, itx.S, true); err != nil { - return err - } - } - - case AccessListTxType: - var itx AccessListTx - inner = &itx - if dec.ChainID == nil { - return errors.New("missing required field 'chainId' in transaction") - } - itx.ChainID = (*big.Int)(dec.ChainID) - if dec.Nonce == nil { - return errors.New("missing required field 'nonce' in transaction") - } - itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' in transaction") - } - itx.Gas = uint64(*dec.Gas) - if dec.GasPrice == nil { - return errors.New("missing required field 'gasPrice' in transaction") - } - itx.GasPrice = (*big.Int)(dec.GasPrice) - if dec.Value == nil { - return errors.New("missing required field 'value' in transaction") - } - itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { - return errors.New("missing required field 'input' in transaction") - } - itx.Data = *dec.Input - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } - - // signature R - if dec.R == nil { - return errors.New("missing required field 'r' in transaction") - } - itx.R = (*big.Int)(dec.R) - // signature S - if dec.S == nil { - return errors.New("missing required field 's' in transaction") - } - itx.S = (*big.Int)(dec.S) - // signature V - itx.V, err = dec.yParityValue() - if err != nil { - return err - } - if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 { - if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil { - return err - } - } - - case DynamicFeeTxType: - var itx DynamicFeeTx - inner = &itx - if dec.ChainID == nil { - return errors.New("missing required field 'chainId' in transaction") - } - itx.ChainID = (*big.Int)(dec.ChainID) - if dec.Nonce == nil { - return errors.New("missing required field 'nonce' in transaction") - } - itx.Nonce = uint64(*dec.Nonce) - if dec.To != nil { - itx.To = dec.To - } - if dec.Gas == nil { - return errors.New("missing required field 'gas' for txdata") - } - itx.Gas = uint64(*dec.Gas) - if dec.MaxPriorityFeePerGas == nil { - return errors.New("missing required field 'maxPriorityFeePerGas' for txdata") - } - itx.GasTipCap = (*big.Int)(dec.MaxPriorityFeePerGas) - if dec.MaxFeePerGas == nil { - return errors.New("missing required field 'maxFeePerGas' for txdata") - } - itx.GasFeeCap = (*big.Int)(dec.MaxFeePerGas) - if dec.Value == nil { - return errors.New("missing required field 'value' in transaction") - } - itx.Value = (*big.Int)(dec.Value) - if dec.Input == nil { - return errors.New("missing required field 'input' in transaction") - } - itx.Data = *dec.Input - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } - - // signature R - if dec.R == nil { - return errors.New("missing required field 'r' in transaction") - } - itx.R = (*big.Int)(dec.R) - // signature S - if dec.S == nil { - return errors.New("missing required field 's' in transaction") - } - itx.S = (*big.Int)(dec.S) - // signature V - itx.V, err = dec.yParityValue() - if err != nil { - return err - } - if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 { - if err := sanityCheckSignature(itx.V, itx.R, itx.S, false); err != nil { - return err - } - } - - case BlobTxType: - var itx BlobTx - inner = &itx - if dec.ChainID == nil { - return errors.New("missing required field 'chainId' in transaction") - } - itx.ChainID = uint256.MustFromBig((*big.Int)(dec.ChainID)) - if dec.Nonce == nil { - return errors.New("missing required field 'nonce' in transaction") - } - itx.Nonce = uint64(*dec.Nonce) - if dec.To == nil { - return errors.New("missing required field 'to' in transaction") - } - itx.To = *dec.To - if dec.Gas == nil { - return errors.New("missing required field 'gas' for txdata") - } - itx.Gas = uint64(*dec.Gas) - if dec.MaxPriorityFeePerGas == nil { - return errors.New("missing required field 'maxPriorityFeePerGas' for txdata") - } - itx.GasTipCap = uint256.MustFromBig((*big.Int)(dec.MaxPriorityFeePerGas)) - if dec.MaxFeePerGas == nil { - return errors.New("missing required field 'maxFeePerGas' for txdata") - } - itx.GasFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerGas)) - if dec.MaxFeePerBlobGas == nil { - return errors.New("missing required field 'maxFeePerBlobGas' for txdata") - } - itx.BlobFeeCap = uint256.MustFromBig((*big.Int)(dec.MaxFeePerBlobGas)) - if dec.Value == nil { - return errors.New("missing required field 'value' in transaction") - } - itx.Value = uint256.MustFromBig((*big.Int)(dec.Value)) - if dec.Input == nil { - return errors.New("missing required field 'input' in transaction") - } - itx.Data = *dec.Input - if dec.AccessList != nil { - itx.AccessList = *dec.AccessList - } - if dec.BlobVersionedHashes == nil { - return errors.New("missing required field 'blobVersionedHashes' in transaction") - } - itx.BlobHashes = dec.BlobVersionedHashes - - // signature R - var overflow bool - if dec.R == nil { - return errors.New("missing required field 'r' in transaction") - } - itx.R, overflow = uint256.FromBig((*big.Int)(dec.R)) - if overflow { - return errors.New("'r' value overflows uint256") - } - // signature S - if dec.S == nil { - return errors.New("missing required field 's' in transaction") - } - itx.S, overflow = uint256.FromBig((*big.Int)(dec.S)) - if overflow { - return errors.New("'s' value overflows uint256") - } - // signature V - vbig, err := dec.yParityValue() - if err != nil { - return err - } - itx.V, overflow = uint256.FromBig(vbig) - if overflow { - return errors.New("'v' value overflows uint256") - } - if itx.V.Sign() != 0 || itx.R.Sign() != 0 || itx.S.Sign() != 0 { - if err := sanityCheckSignature(vbig, itx.R.ToBig(), itx.S.ToBig(), false); err != nil { - return err - } - } - - default: - return ErrTxTypeNotSupported - } - - // Now set the inner transaction. - tx.setDecoded(inner, 0) - - // TODO: check hash here? - return nil -} diff --git a/builder/core/types/transaction_signing.go b/builder/core/types/transaction_signing.go deleted file mode 100644 index 9e26642f7..000000000 --- a/builder/core/types/transaction_signing.go +++ /dev/null @@ -1,584 +0,0 @@ -// Copyright 2016 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 types - -import ( - "crypto/ecdsa" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -var ErrInvalidChainId = errors.New("invalid chain id for signer") - -// sigCache is used to cache the derived sender and contains -// the signer used to derive it. -type sigCache struct { - signer Signer - from common.Address -} - -// MakeSigner returns a Signer based on the given chain config and block number. -func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer { - var signer Signer - switch { - case config.IsCancun(blockNumber, blockTime): - signer = NewCancunSigner(config.ChainID) - case config.IsLondon(blockNumber): - signer = NewLondonSigner(config.ChainID) - case config.IsBerlin(blockNumber): - signer = NewEIP2930Signer(config.ChainID) - case config.IsEIP155(blockNumber): - signer = NewEIP155Signer(config.ChainID) - case config.IsHomestead(blockNumber): - signer = HomesteadSigner{} - default: - signer = FrontierSigner{} - } - return signer -} - -// LatestSigner returns the 'most permissive' Signer available for the given chain -// configuration. Specifically, this enables support of all types of transactions -// when their respective forks are scheduled to occur at any block number (or time) -// in the chain config. -// -// Use this in transaction-handling code where the current block number is unknown. If you -// have the current block number available, use MakeSigner instead. -func LatestSigner(config *params.ChainConfig) Signer { - if config.ChainID != nil { - if config.CancunTime != nil { - return NewCancunSigner(config.ChainID) - } - if config.LondonBlock != nil { - return NewLondonSigner(config.ChainID) - } - if config.BerlinBlock != nil { - return NewEIP2930Signer(config.ChainID) - } - if config.EIP155Block != nil { - return NewEIP155Signer(config.ChainID) - } - } - return HomesteadSigner{} -} - -// LatestSignerForChainID returns the 'most permissive' Signer available. Specifically, -// this enables support for EIP-155 replay protection and all implemented EIP-2718 -// transaction types if chainID is non-nil. -// -// Use this in transaction-handling code where the current block number and fork -// configuration are unknown. If you have a ChainConfig, use LatestSigner instead. -// If you have a ChainConfig and know the current block number, use MakeSigner instead. -func LatestSignerForChainID(chainID *big.Int) Signer { - if chainID == nil { - return HomesteadSigner{} - } - return NewCancunSigner(chainID) -} - -// SignTx signs the transaction using the given signer and private key. -func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, error) { - h := s.Hash(tx) - sig, err := crypto.Sign(h[:], prv) - if err != nil { - return nil, err - } - return tx.WithSignature(s, sig) -} - -// SignNewTx creates a transaction and signs it. -func SignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) (*Transaction, error) { - tx := NewTx(txdata) - h := s.Hash(tx) - sig, err := crypto.Sign(h[:], prv) - if err != nil { - return nil, err - } - return tx.WithSignature(s, sig) -} - -// MustSignNewTx creates a transaction and signs it. -// This panics if the transaction cannot be signed. -func MustSignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) *Transaction { - tx, err := SignNewTx(prv, s, txdata) - if err != nil { - panic(err) - } - return tx -} - -// Sender returns the address derived from the signature (V, R, S) using secp256k1 -// elliptic curve and an error if it failed deriving or upon an incorrect -// signature. -// -// Sender may cache the address, allowing it to be used regardless of -// signing method. The cache is invalidated if the cached signer does -// not match the signer used in the current call. -func Sender(signer Signer, tx *Transaction) (common.Address, error) { - if sc := tx.from.Load(); sc != nil { - sigCache := sc.(sigCache) - // If the signer used to derive from in a previous - // call is not the same as used current, invalidate - // the cache. - if sigCache.signer.Equal(signer) { - return sigCache.from, nil - } - } - - addr, err := signer.Sender(tx) - if err != nil { - return common.Address{}, err - } - tx.from.Store(sigCache{signer: signer, from: addr}) - return addr, nil -} - -// Signer encapsulates transaction signature handling. The name of this type is slightly -// misleading because Signers don't actually sign, they're just for validating and -// processing of signatures. -// -// Note that this interface is not a stable API and may change at any time to accommodate -// new protocol rules. -type Signer interface { - // Sender returns the sender address of the transaction. - Sender(tx *Transaction) (common.Address, error) - - // SignatureValues returns the raw R, S, V values corresponding to the - // given signature. - SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) - ChainID() *big.Int - - // Hash returns 'signature hash', i.e. the transaction hash that is signed by the - // private key. This hash does not uniquely identify the transaction. - Hash(tx *Transaction) common.Hash - - // Equal returns true if the given signer is the same as the receiver. - Equal(Signer) bool -} - -type cancunSigner struct{ londonSigner } - -// NewCancunSigner returns a signer that accepts -// - EIP-4844 blob transactions -// - EIP-1559 dynamic fee transactions -// - EIP-2930 access list transactions, -// - EIP-155 replay protected transactions, and -// - legacy Homestead transactions. -func NewCancunSigner(chainId *big.Int) Signer { - return cancunSigner{londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}} -} - -func (s cancunSigner) Sender(tx *Transaction) (common.Address, error) { - if tx.Type() != BlobTxType { - return s.londonSigner.Sender(tx) - } - V, R, S := tx.RawSignatureValues() - // Blob txs are defined to use 0 and 1 as their recovery - // id, add 27 to become equivalent to unprotected Homestead signatures. - V = new(big.Int).Add(V, big.NewInt(27)) - if tx.ChainId().Cmp(s.chainId) != 0 { - return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) - } - return recoverPlain(s.Hash(tx), R, S, V, true) -} - -func (s cancunSigner) Equal(s2 Signer) bool { - x, ok := s2.(cancunSigner) - return ok && x.chainId.Cmp(s.chainId) == 0 -} - -func (s cancunSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { - txdata, ok := tx.inner.(*BlobTx) - if !ok { - return s.londonSigner.SignatureValues(tx, sig) - } - // Check that chain ID of tx matches the signer. We also accept ID zero here, - // because it indicates that the chain ID was not specified in the tx. - if txdata.ChainID.Sign() != 0 && txdata.ChainID.ToBig().Cmp(s.chainId) != 0 { - return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) - } - R, S, _ = decodeSignature(sig) - V = big.NewInt(int64(sig[64])) - return R, S, V, nil -} - -// Hash returns the hash to be signed by the sender. -// It does not uniquely identify the transaction. -func (s cancunSigner) Hash(tx *Transaction) common.Hash { - if tx.Type() != BlobTxType { - return s.londonSigner.Hash(tx) - } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - tx.BlobGasFeeCap(), - tx.BlobHashes(), - }) -} - -type londonSigner struct{ eip2930Signer } - -// NewLondonSigner returns a signer that accepts -// - EIP-1559 dynamic fee transactions -// - EIP-2930 access list transactions, -// - EIP-155 replay protected transactions, and -// - legacy Homestead transactions. -func NewLondonSigner(chainId *big.Int) Signer { - return londonSigner{eip2930Signer{NewEIP155Signer(chainId)}} -} - -func (s londonSigner) Sender(tx *Transaction) (common.Address, error) { - if tx.Type() != DynamicFeeTxType { - return s.eip2930Signer.Sender(tx) - } - V, R, S := tx.RawSignatureValues() - // DynamicFee txs are defined to use 0 and 1 as their recovery - // id, add 27 to become equivalent to unprotected Homestead signatures. - V = new(big.Int).Add(V, big.NewInt(27)) - if tx.ChainId().Cmp(s.chainId) != 0 { - return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) - } - return recoverPlain(s.Hash(tx), R, S, V, true) -} - -func (s londonSigner) Equal(s2 Signer) bool { - x, ok := s2.(londonSigner) - return ok && x.chainId.Cmp(s.chainId) == 0 -} - -func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { - txdata, ok := tx.inner.(*DynamicFeeTx) - if !ok { - return s.eip2930Signer.SignatureValues(tx, sig) - } - // Check that chain ID of tx matches the signer. We also accept ID zero here, - // because it indicates that the chain ID was not specified in the tx. - if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 { - return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) - } - R, S, _ = decodeSignature(sig) - V = big.NewInt(int64(sig[64])) - return R, S, V, nil -} - -// Hash returns the hash to be signed by the sender. -// It does not uniquely identify the transaction. -func (s londonSigner) Hash(tx *Transaction) common.Hash { - if tx.Type() != DynamicFeeTxType { - return s.eip2930Signer.Hash(tx) - } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - }) -} - -type eip2930Signer struct{ EIP155Signer } - -// NewEIP2930Signer returns a signer that accepts EIP-2930 access list transactions, -// EIP-155 replay protected transactions, and legacy Homestead transactions. -func NewEIP2930Signer(chainId *big.Int) Signer { - return eip2930Signer{NewEIP155Signer(chainId)} -} - -func (s eip2930Signer) ChainID() *big.Int { - return s.chainId -} - -func (s eip2930Signer) Equal(s2 Signer) bool { - x, ok := s2.(eip2930Signer) - return ok && x.chainId.Cmp(s.chainId) == 0 -} - -func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) { - V, R, S := tx.RawSignatureValues() - switch tx.Type() { - case LegacyTxType: - return s.EIP155Signer.Sender(tx) - case AccessListTxType: - // AL txs are defined to use 0 and 1 as their recovery - // id, add 27 to become equivalent to unprotected Homestead signatures. - V = new(big.Int).Add(V, big.NewInt(27)) - default: - return common.Address{}, ErrTxTypeNotSupported - } - if tx.ChainId().Cmp(s.chainId) != 0 { - return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) - } - return recoverPlain(s.Hash(tx), R, S, V, true) -} - -func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { - switch txdata := tx.inner.(type) { - case *LegacyTx: - return s.EIP155Signer.SignatureValues(tx, sig) - case *AccessListTx: - // Check that chain ID of tx matches the signer. We also accept ID zero here, - // because it indicates that the chain ID was not specified in the tx. - if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 { - return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) - } - R, S, _ = decodeSignature(sig) - V = big.NewInt(int64(sig[64])) - default: - return nil, nil, nil, ErrTxTypeNotSupported - } - return R, S, V, nil -} - -// Hash returns the hash to be signed by the sender. -// It does not uniquely identify the transaction. -func (s eip2930Signer) Hash(tx *Transaction) common.Hash { - switch tx.Type() { - case LegacyTxType: - return s.EIP155Signer.Hash(tx) - case AccessListTxType: - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - }) - default: - // This _should_ not happen, but in case someone sends in a bad - // json struct via RPC, it's probably more prudent to return an - // empty hash instead of killing the node with a panic - //panic("Unsupported transaction type: %d", tx.typ) - return common.Hash{} - } -} - -// EIP155Signer implements Signer using the EIP-155 rules. This accepts transactions which -// are replay-protected as well as unprotected homestead transactions. -type EIP155Signer struct { - chainId, chainIdMul *big.Int -} - -func NewEIP155Signer(chainId *big.Int) EIP155Signer { - if chainId == nil { - chainId = new(big.Int) - } - return EIP155Signer{ - chainId: chainId, - chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)), - } -} - -func (s EIP155Signer) ChainID() *big.Int { - return s.chainId -} - -func (s EIP155Signer) Equal(s2 Signer) bool { - eip155, ok := s2.(EIP155Signer) - return ok && eip155.chainId.Cmp(s.chainId) == 0 -} - -var big8 = big.NewInt(8) - -func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) { - if tx.Type() != LegacyTxType { - return common.Address{}, ErrTxTypeNotSupported - } - if !tx.Protected() { - return HomesteadSigner{}.Sender(tx) - } - if tx.ChainId().Cmp(s.chainId) != 0 { - return common.Address{}, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) - } - V, R, S := tx.RawSignatureValues() - V = new(big.Int).Sub(V, s.chainIdMul) - V.Sub(V, big8) - return recoverPlain(s.Hash(tx), R, S, V, true) -} - -// SignatureValues returns signature values. This signature -// needs to be in the [R || S || V] format where V is 0 or 1. -func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { - if tx.Type() != LegacyTxType { - return nil, nil, nil, ErrTxTypeNotSupported - } - R, S, V = decodeSignature(sig) - if s.chainId.Sign() != 0 { - V = big.NewInt(int64(sig[64] + 35)) - V.Add(V, s.chainIdMul) - } - return R, S, V, nil -} - -// Hash returns the hash to be signed by the sender. -// It does not uniquely identify the transaction. -func (s EIP155Signer) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - s.chainId, uint(0), uint(0), - }) -} - -// HomesteadSigner implements Signer interface using the -// homestead rules. -type HomesteadSigner struct{ FrontierSigner } - -func (s HomesteadSigner) ChainID() *big.Int { - return nil -} - -func (s HomesteadSigner) Equal(s2 Signer) bool { - _, ok := s2.(HomesteadSigner) - return ok -} - -// SignatureValues returns signature values. This signature -// needs to be in the [R || S || V] format where V is 0 or 1. -func (hs HomesteadSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - return hs.FrontierSigner.SignatureValues(tx, sig) -} - -func (hs HomesteadSigner) Sender(tx *Transaction) (common.Address, error) { - if tx.Type() != LegacyTxType { - return common.Address{}, ErrTxTypeNotSupported - } - v, r, s := tx.RawSignatureValues() - return recoverPlain(hs.Hash(tx), r, s, v, true) -} - -// FrontierSigner implements Signer interface using the -// frontier rules. -type FrontierSigner struct{} - -func (s FrontierSigner) ChainID() *big.Int { - return nil -} - -func (s FrontierSigner) Equal(s2 Signer) bool { - _, ok := s2.(FrontierSigner) - return ok -} - -func (fs FrontierSigner) Sender(tx *Transaction) (common.Address, error) { - if tx.Type() != LegacyTxType { - return common.Address{}, ErrTxTypeNotSupported - } - v, r, s := tx.RawSignatureValues() - return recoverPlain(fs.Hash(tx), r, s, v, false) -} - -// SignatureValues returns signature values. This signature -// needs to be in the [R || S || V] format where V is 0 or 1. -func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - if tx.Type() != LegacyTxType { - return nil, nil, nil, ErrTxTypeNotSupported - } - r, s, v = decodeSignature(sig) - return r, s, v, nil -} - -// Hash returns the hash to be signed by the sender. -// It does not uniquely identify the transaction. -func (fs FrontierSigner) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - }) -} - -func decodeSignature(sig []byte) (r, s, v *big.Int) { - if len(sig) != crypto.SignatureLength { - panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)) - } - r = new(big.Int).SetBytes(sig[:32]) - s = new(big.Int).SetBytes(sig[32:64]) - v = new(big.Int).SetBytes([]byte{sig[64] + 27}) - return r, s, v -} - -func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) { - if Vb.BitLen() > 8 { - return common.Address{}, ErrInvalidSig - } - V := byte(Vb.Uint64() - 27) - if !crypto.ValidateSignatureValues(V, R, S, homestead) { - return common.Address{}, ErrInvalidSig - } - // encode the signature in uncompressed format - r, s := R.Bytes(), S.Bytes() - sig := make([]byte, crypto.SignatureLength) - copy(sig[32-len(r):32], r) - copy(sig[64-len(s):64], s) - sig[64] = V - // recover the public key from the signature - pub, err := crypto.Ecrecover(sighash[:], sig) - if err != nil { - return common.Address{}, err - } - if len(pub) == 0 || pub[0] != 4 { - return common.Address{}, errors.New("invalid public key") - } - var addr common.Address - copy(addr[:], crypto.Keccak256(pub[1:])[12:]) - return addr, nil -} - -// deriveChainId derives the chain id from the given v parameter -func deriveChainId(v *big.Int) *big.Int { - if v.BitLen() <= 64 { - v := v.Uint64() - if v == 27 || v == 28 { - return new(big.Int) - } - return new(big.Int).SetUint64((v - 35) / 2) - } - v = new(big.Int).Sub(v, big.NewInt(35)) - return v.Div(v, big.NewInt(2)) -} diff --git a/builder/core/types/transaction_signing_test.go b/builder/core/types/transaction_signing_test.go deleted file mode 100644 index b66577f7e..000000000 --- a/builder/core/types/transaction_signing_test.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2016 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 types - -import ( - "errors" - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" -) - -func TestEIP155Signing(t *testing.T) { - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - signer := NewEIP155Signer(big.NewInt(18)) - tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key) - if err != nil { - t.Fatal(err) - } - - from, err := Sender(signer, tx) - if err != nil { - t.Fatal(err) - } - if from != addr { - t.Errorf("expected from and address to be equal. Got %x want %x", from, addr) - } -} - -func TestEIP155ChainId(t *testing.T) { - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - signer := NewEIP155Signer(big.NewInt(18)) - tx, err := SignTx(NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil), signer, key) - if err != nil { - t.Fatal(err) - } - if !tx.Protected() { - t.Fatal("expected tx to be protected") - } - - if tx.ChainId().Cmp(signer.chainId) != 0 { - t.Error("expected chainId to be", signer.chainId, "got", tx.ChainId()) - } - - tx = NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil) - tx, err = SignTx(tx, HomesteadSigner{}, key) - if err != nil { - t.Fatal(err) - } - - if tx.Protected() { - t.Error("didn't expect tx to be protected") - } - - if tx.ChainId().Sign() != 0 { - t.Error("expected chain id to be 0 got", tx.ChainId()) - } -} - -func TestEIP155SigningVitalik(t *testing.T) { - // Test vectors come from http://vitalik.ca/files/eip155_testvec.txt - for i, test := range []struct { - txRlp, addr string - }{ - {"f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"}, - {"f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112"}, - {"f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be"}, - {"f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0"}, - {"f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554"}, - {"f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4"}, - {"f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35"}, - {"f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332"}, - {"f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029"}, - {"f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f"}, - } { - signer := NewEIP155Signer(big.NewInt(1)) - - var tx *Transaction - err := rlp.DecodeBytes(common.Hex2Bytes(test.txRlp), &tx) - if err != nil { - t.Errorf("%d: %v", i, err) - continue - } - - from, err := Sender(signer, tx) - if err != nil { - t.Errorf("%d: %v", i, err) - continue - } - - addr := common.HexToAddress(test.addr) - if from != addr { - t.Errorf("%d: expected %x got %x", i, addr, from) - } - } -} - -func TestChainId(t *testing.T) { - key, _ := defaultTestKey() - - tx := NewTransaction(0, common.Address{}, new(big.Int), 0, new(big.Int), nil) - - var err error - tx, err = SignTx(tx, NewEIP155Signer(big.NewInt(1)), key) - if err != nil { - t.Fatal(err) - } - - _, err = Sender(NewEIP155Signer(big.NewInt(2)), tx) - if !errors.Is(err, ErrInvalidChainId) { - t.Error("expected error:", ErrInvalidChainId, err) - } - - _, err = Sender(NewEIP155Signer(big.NewInt(1)), tx) - if err != nil { - t.Error("expected no error") - } -} - -type nilSigner struct { - v, r, s *big.Int - Signer -} - -func (ns *nilSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { - return ns.v, ns.r, ns.s, nil -} - -// TestNilSigner ensures a faulty Signer implementation does not result in nil signature values or panics. -func TestNilSigner(t *testing.T) { - key, _ := crypto.GenerateKey() - innerSigner := LatestSignerForChainID(big.NewInt(1)) - for i, signer := range []Signer{ - &nilSigner{v: nil, r: nil, s: nil, Signer: innerSigner}, - &nilSigner{v: big.NewInt(1), r: big.NewInt(1), s: nil, Signer: innerSigner}, - &nilSigner{v: big.NewInt(1), r: nil, s: big.NewInt(1), Signer: innerSigner}, - &nilSigner{v: nil, r: big.NewInt(1), s: big.NewInt(1), Signer: innerSigner}, - } { - t.Run(fmt.Sprintf("signer_%d", i), func(t *testing.T) { - t.Run("legacy", func(t *testing.T) { - legacyTx := createTestLegacyTxInner() - _, err := SignNewTx(key, signer, legacyTx) - if !errors.Is(err, ErrInvalidSig) { - t.Fatal("expected signature values error, no nil result or panic") - } - }) - // test Blob tx specifically, since the signature value types changed - t.Run("blobtx", func(t *testing.T) { - blobtx := createEmptyBlobTxInner(false) - _, err := SignNewTx(key, signer, blobtx) - if !errors.Is(err, ErrInvalidSig) { - t.Fatal("expected signature values error, no nil result or panic") - } - }) - }) - } -} - -func createTestLegacyTxInner() *LegacyTx { - return &LegacyTx{ - Nonce: uint64(0), - To: nil, - Value: big.NewInt(0), - Gas: params.TxGas, - GasPrice: big.NewInt(params.GWei), - Data: nil, - } -} diff --git a/builder/core/types/transaction_test.go b/builder/core/types/transaction_test.go deleted file mode 100644 index 76a010d2e..000000000 --- a/builder/core/types/transaction_test.go +++ /dev/null @@ -1,547 +0,0 @@ -// 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 types - -import ( - "bytes" - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "math/big" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" -) - -// The values in those tests are from the Transaction Tests -// at github.com/ethereum/tests. -var ( - testAddr = common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b") - - emptyTx = NewTransaction( - 0, - common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), - big.NewInt(0), 0, big.NewInt(0), - nil, - ) - - rightvrsTx, _ = NewTransaction( - 3, - testAddr, - big.NewInt(10), - 2000, - big.NewInt(1), - common.FromHex("5544"), - ).WithSignature( - HomesteadSigner{}, - common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"), - ) - - emptyEip2718Tx = NewTx(&AccessListTx{ - ChainID: big.NewInt(1), - Nonce: 3, - To: &testAddr, - Value: big.NewInt(10), - Gas: 25000, - GasPrice: big.NewInt(1), - Data: common.FromHex("5544"), - }) - - signedEip2718Tx, _ = emptyEip2718Tx.WithSignature( - NewEIP2930Signer(big.NewInt(1)), - common.Hex2Bytes("c9519f4f2b30335884581971573fadf60c6204f59a911df35ee8a540456b266032f1e8e2c5dd761f9e4f88f41c8310aeaba26a8bfcdacfedfa12ec3862d3752101"), - ) -) - -func TestDecodeEmptyTypedTx(t *testing.T) { - input := []byte{0x80} - var tx Transaction - err := rlp.DecodeBytes(input, &tx) - if err != errShortTypedTx { - t.Fatal("wrong error:", err) - } -} - -func TestTransactionSigHash(t *testing.T) { - var homestead HomesteadSigner - if homestead.Hash(emptyTx) != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") { - t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash()) - } - if homestead.Hash(rightvrsTx) != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") { - t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash()) - } -} - -func TestTransactionEncode(t *testing.T) { - txb, err := rlp.EncodeToBytes(rightvrsTx) - if err != nil { - t.Fatalf("encode error: %v", err) - } - should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3") - if !bytes.Equal(txb, should) { - t.Errorf("encoded RLP mismatch, got %x", txb) - } -} - -func TestEIP2718TransactionSigHash(t *testing.T) { - s := NewEIP2930Signer(big.NewInt(1)) - if s.Hash(emptyEip2718Tx) != common.HexToHash("49b486f0ec0a60dfbbca2d30cb07c9e8ffb2a2ff41f29a1ab6737475f6ff69f3") { - t.Errorf("empty EIP-2718 transaction hash mismatch, got %x", s.Hash(emptyEip2718Tx)) - } - if s.Hash(signedEip2718Tx) != common.HexToHash("49b486f0ec0a60dfbbca2d30cb07c9e8ffb2a2ff41f29a1ab6737475f6ff69f3") { - t.Errorf("signed EIP-2718 transaction hash mismatch, got %x", s.Hash(signedEip2718Tx)) - } -} - -// This test checks signature operations on access list transactions. -func TestEIP2930Signer(t *testing.T) { - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - keyAddr = crypto.PubkeyToAddress(key.PublicKey) - signer1 = NewEIP2930Signer(big.NewInt(1)) - signer2 = NewEIP2930Signer(big.NewInt(2)) - tx0 = NewTx(&AccessListTx{Nonce: 1}) - tx1 = NewTx(&AccessListTx{ChainID: big.NewInt(1), Nonce: 1}) - tx2, _ = SignNewTx(key, signer2, &AccessListTx{ChainID: big.NewInt(2), Nonce: 1}) - ) - - tests := []struct { - tx *Transaction - signer Signer - wantSignerHash common.Hash - wantSenderErr error - wantSignErr error - wantHash common.Hash // after signing - }{ - { - tx: tx0, - signer: signer1, - wantSignerHash: common.HexToHash("846ad7672f2a3a40c1f959cd4a8ad21786d620077084d84c8d7c077714caa139"), - wantSenderErr: ErrInvalidChainId, - wantHash: common.HexToHash("1ccd12d8bbdb96ea391af49a35ab641e219b2dd638dea375f2bc94dd290f2549"), - }, - { - tx: tx1, - signer: signer1, - wantSenderErr: ErrInvalidSig, - wantSignerHash: common.HexToHash("846ad7672f2a3a40c1f959cd4a8ad21786d620077084d84c8d7c077714caa139"), - wantHash: common.HexToHash("1ccd12d8bbdb96ea391af49a35ab641e219b2dd638dea375f2bc94dd290f2549"), - }, - { - // This checks what happens when trying to sign an unsigned tx for the wrong chain. - tx: tx1, - signer: signer2, - wantSenderErr: ErrInvalidChainId, - wantSignerHash: common.HexToHash("367967247499343401261d718ed5aa4c9486583e4d89251afce47f4a33c33362"), - wantSignErr: ErrInvalidChainId, - }, - { - // This checks what happens when trying to re-sign a signed tx for the wrong chain. - tx: tx2, - signer: signer1, - wantSenderErr: ErrInvalidChainId, - wantSignerHash: common.HexToHash("846ad7672f2a3a40c1f959cd4a8ad21786d620077084d84c8d7c077714caa139"), - wantSignErr: ErrInvalidChainId, - }, - } - - for i, test := range tests { - sigHash := test.signer.Hash(test.tx) - if sigHash != test.wantSignerHash { - t.Errorf("test %d: wrong sig hash: got %x, want %x", i, sigHash, test.wantSignerHash) - } - sender, err := Sender(test.signer, test.tx) - if !errors.Is(err, test.wantSenderErr) { - t.Errorf("test %d: wrong Sender error %q", i, err) - } - if err == nil && sender != keyAddr { - t.Errorf("test %d: wrong sender address %x", i, sender) - } - signedTx, err := SignTx(test.tx, test.signer, key) - if !errors.Is(err, test.wantSignErr) { - t.Fatalf("test %d: wrong SignTx error %q", i, err) - } - if signedTx != nil { - if signedTx.Hash() != test.wantHash { - t.Errorf("test %d: wrong tx hash after signing: got %x, want %x", i, signedTx.Hash(), test.wantHash) - } - } - } -} - -func TestEIP2718TransactionEncode(t *testing.T) { - // RLP representation - { - have, err := rlp.EncodeToBytes(signedEip2718Tx) - if err != nil { - t.Fatalf("encode error: %v", err) - } - want := common.FromHex("b86601f8630103018261a894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a825544c001a0c9519f4f2b30335884581971573fadf60c6204f59a911df35ee8a540456b2660a032f1e8e2c5dd761f9e4f88f41c8310aeaba26a8bfcdacfedfa12ec3862d37521") - if !bytes.Equal(have, want) { - t.Errorf("encoded RLP mismatch, got %x", have) - } - } - // Binary representation - { - have, err := signedEip2718Tx.MarshalBinary() - if err != nil { - t.Fatalf("encode error: %v", err) - } - want := common.FromHex("01f8630103018261a894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a825544c001a0c9519f4f2b30335884581971573fadf60c6204f59a911df35ee8a540456b2660a032f1e8e2c5dd761f9e4f88f41c8310aeaba26a8bfcdacfedfa12ec3862d37521") - if !bytes.Equal(have, want) { - t.Errorf("encoded RLP mismatch, got %x", have) - } - } -} - -func decodeTx(data []byte) (*Transaction, error) { - var tx Transaction - t, err := &tx, rlp.DecodeBytes(data, &tx) - return t, err -} - -func defaultTestKey() (*ecdsa.PrivateKey, common.Address) { - key, _ := crypto.HexToECDSA("45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") - addr := crypto.PubkeyToAddress(key.PublicKey) - return key, addr -} - -func TestRecipientEmpty(t *testing.T) { - _, addr := defaultTestKey() - tx, err := decodeTx(common.Hex2Bytes("f8498080808080011ca09b16de9d5bdee2cf56c28d16275a4da68cd30273e2525f3959f5d62557489921a0372ebd8fb3345f7db7b5a86d42e24d36e983e259b0664ceb8c227ec9af572f3d")) - if err != nil { - t.Fatal(err) - } - - from, err := Sender(HomesteadSigner{}, tx) - if err != nil { - t.Fatal(err) - } - if addr != from { - t.Fatal("derived address doesn't match") - } -} - -func TestRecipientNormal(t *testing.T) { - _, addr := defaultTestKey() - - tx, err := decodeTx(common.Hex2Bytes("f85d80808094000000000000000000000000000000000000000080011ca0527c0d8f5c63f7b9f41324a7c8a563ee1190bcbf0dac8ab446291bdbf32f5c79a0552c4ef0a09a04395074dab9ed34d3fbfb843c2f2546cc30fe89ec143ca94ca6")) - if err != nil { - t.Fatal(err) - } - - from, err := Sender(HomesteadSigner{}, tx) - if err != nil { - t.Fatal(err) - } - if addr != from { - t.Fatal("derived address doesn't match") - } -} - -// TestTransactionCoding tests serializing/de-serializing to/from rlp and JSON. -func TestTransactionCoding(t *testing.T) { - key, err := crypto.GenerateKey() - if err != nil { - t.Fatalf("could not generate key: %v", err) - } - var ( - signer = NewEIP2930Signer(common.Big1) - addr = common.HexToAddress("0x0000000000000000000000000000000000000001") - recipient = common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87") - accesses = AccessList{{Address: addr, StorageKeys: []common.Hash{{0}}}} - ) - for i := uint64(0); i < 500; i++ { - var txdata TxData - switch i % 5 { - case 0: - // Legacy tx. - txdata = &LegacyTx{ - Nonce: i, - To: &recipient, - Gas: 1, - GasPrice: big.NewInt(2), - Data: []byte("abcdef"), - } - case 1: - // Legacy tx contract creation. - txdata = &LegacyTx{ - Nonce: i, - Gas: 1, - GasPrice: big.NewInt(2), - Data: []byte("abcdef"), - } - case 2: - // Tx with non-zero access list. - txdata = &AccessListTx{ - ChainID: big.NewInt(1), - Nonce: i, - To: &recipient, - Gas: 123457, - GasPrice: big.NewInt(10), - AccessList: accesses, - Data: []byte("abcdef"), - } - case 3: - // Tx with empty access list. - txdata = &AccessListTx{ - ChainID: big.NewInt(1), - Nonce: i, - To: &recipient, - Gas: 123457, - GasPrice: big.NewInt(10), - Data: []byte("abcdef"), - } - case 4: - // Contract creation with access list. - txdata = &AccessListTx{ - ChainID: big.NewInt(1), - Nonce: i, - Gas: 123457, - GasPrice: big.NewInt(10), - AccessList: accesses, - } - } - tx, err := SignNewTx(key, signer, txdata) - if err != nil { - t.Fatalf("could not sign transaction: %v", err) - } - // RLP - parsedTx, err := encodeDecodeBinary(tx) - if err != nil { - t.Fatal(err) - } - if err := assertEqual(parsedTx, tx); err != nil { - t.Fatal(err) - } - - // JSON - parsedTx, err = encodeDecodeJSON(tx) - if err != nil { - t.Fatal(err) - } - if err := assertEqual(parsedTx, tx); err != nil { - t.Fatal(err) - } - } -} - -func encodeDecodeJSON(tx *Transaction) (*Transaction, error) { - data, err := json.Marshal(tx) - if err != nil { - return nil, fmt.Errorf("json encoding failed: %v", err) - } - var parsedTx = &Transaction{} - if err := json.Unmarshal(data, &parsedTx); err != nil { - return nil, fmt.Errorf("json decoding failed: %v", err) - } - return parsedTx, nil -} - -func encodeDecodeBinary(tx *Transaction) (*Transaction, error) { - data, err := tx.MarshalBinary() - if err != nil { - return nil, fmt.Errorf("rlp encoding failed: %v", err) - } - var parsedTx = &Transaction{} - if err := parsedTx.UnmarshalBinary(data); err != nil { - return nil, fmt.Errorf("rlp decoding failed: %v", err) - } - return parsedTx, nil -} - -func assertEqual(orig *Transaction, cpy *Transaction) error { - // compare nonce, price, gaslimit, recipient, amount, payload, V, R, S - if want, got := orig.Hash(), cpy.Hash(); want != got { - return fmt.Errorf("parsed tx differs from original tx, want %v, got %v", want, got) - } - if want, got := orig.ChainId(), cpy.ChainId(); want.Cmp(got) != 0 { - return fmt.Errorf("invalid chain id, want %d, got %d", want, got) - } - if orig.AccessList() != nil { - if !reflect.DeepEqual(orig.AccessList(), cpy.AccessList()) { - return errors.New("access list wrong!") - } - } - return nil -} - -func TestTransactionSizes(t *testing.T) { - signer := NewLondonSigner(big.NewInt(123)) - key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - to := common.HexToAddress("0x01") - for i, txdata := range []TxData{ - &AccessListTx{ - ChainID: big.NewInt(123), - Nonce: 0, - To: nil, - Value: big.NewInt(1000), - Gas: 21000, - GasPrice: big.NewInt(100000), - }, - &LegacyTx{ - Nonce: 1, - GasPrice: big.NewInt(500), - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - }, - &AccessListTx{ - ChainID: big.NewInt(123), - Nonce: 1, - GasPrice: big.NewInt(500), - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - AccessList: AccessList{ - AccessTuple{ - Address: common.HexToAddress("0x01"), - StorageKeys: []common.Hash{common.HexToHash("0x01")}, - }}, - }, - &DynamicFeeTx{ - ChainID: big.NewInt(123), - Nonce: 1, - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - GasTipCap: big.NewInt(500), - GasFeeCap: big.NewInt(500), - }, - } { - tx, err := SignNewTx(key, signer, txdata) - if err != nil { - t.Fatalf("test %d: %v", i, err) - } - bin, _ := tx.MarshalBinary() - - // Check initial calc - if have, want := int(tx.Size()), len(bin); have != want { - t.Errorf("test %d: size wrong, have %d want %d", i, have, want) - } - // Check cached version too - if have, want := int(tx.Size()), len(bin); have != want { - t.Errorf("test %d: (cached) size wrong, have %d want %d", i, have, want) - } - // Check unmarshalled version too - utx := new(Transaction) - if err := utx.UnmarshalBinary(bin); err != nil { - t.Fatalf("test %d: failed to unmarshal tx: %v", i, err) - } - if have, want := int(utx.Size()), len(bin); have != want { - t.Errorf("test %d: (unmarshalled) size wrong, have %d want %d", i, have, want) - } - } -} - -func TestYParityJSONUnmarshalling(t *testing.T) { - baseJson := map[string]interface{}{ - // type is filled in by the test - "chainId": "0x7", - "nonce": "0x0", - "to": "0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425", - "gas": "0x124f8", - "gasPrice": "0x693d4ca8", - "maxPriorityFeePerGas": "0x3b9aca00", - "maxFeePerGas": "0x6fc23ac00", - "maxFeePerBlobGas": "0x3b9aca00", - "value": "0x0", - "input": "0x", - "accessList": []interface{}{}, - "blobVersionedHashes": []string{ - "0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014", - }, - - // v and yParity are filled in by the test - "r": "0x2a922afc784d07e98012da29f2f37cae1f73eda78aa8805d3df6ee5dbb41ec1", - "s": "0x4f1f75ae6bcdf4970b4f305da1a15d8c5ddb21f555444beab77c9af2baab14", - } - - tests := []struct { - name string - v string - yParity string - wantErr error - }{ - // Valid v and yParity - {"valid v and yParity, 0x0", "0x0", "0x0", nil}, - {"valid v and yParity, 0x1", "0x1", "0x1", nil}, - - // Valid v, missing yParity - {"valid v, missing yParity, 0x0", "0x0", "", nil}, - {"valid v, missing yParity, 0x1", "0x1", "", nil}, - - // Valid yParity, missing v - {"valid yParity, missing v, 0x0", "", "0x0", nil}, - {"valid yParity, missing v, 0x1", "", "0x1", nil}, - - // Invalid yParity - {"invalid yParity, 0x2", "", "0x2", errInvalidYParity}, - - // Conflicting v and yParity - {"conflicting v and yParity", "0x1", "0x0", errVYParityMismatch}, - - // Missing v and yParity - {"missing v and yParity", "", "", errVYParityMissing}, - } - - // Run for all types that accept yParity - t.Parallel() - for _, txType := range []uint64{ - AccessListTxType, - DynamicFeeTxType, - BlobTxType, - } { - txType := txType - for _, test := range tests { - test := test - t.Run(fmt.Sprintf("txType=%d: %s", txType, test.name), func(t *testing.T) { - // Copy the base json - testJson := make(map[string]interface{}) - for k, v := range baseJson { - testJson[k] = v - } - - // Set v, yParity and type - if test.v != "" { - testJson["v"] = test.v - } - if test.yParity != "" { - testJson["yParity"] = test.yParity - } - testJson["type"] = fmt.Sprintf("0x%x", txType) - - // Marshal the JSON - jsonBytes, err := json.Marshal(testJson) - if err != nil { - t.Fatal(err) - } - - // Unmarshal the tx - var tx Transaction - err = tx.UnmarshalJSON(jsonBytes) - if err != test.wantErr { - t.Fatalf("wrong error: got %v, want %v", err, test.wantErr) - } - }) - } - } -} diff --git a/builder/core/types/tx_access_list.go b/builder/core/types/tx_access_list.go deleted file mode 100644 index 730a77b75..000000000 --- a/builder/core/types/tx_access_list.go +++ /dev/null @@ -1,129 +0,0 @@ -// 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 types - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rlp" -) - -//go:generate go run github.com/fjl/gencodec -type AccessTuple -out gen_access_tuple.go - -// AccessList is an EIP-2930 access list. -type AccessList []AccessTuple - -// AccessTuple is the element type of an access list. -type AccessTuple struct { - Address common.Address `json:"address" gencodec:"required"` - StorageKeys []common.Hash `json:"storageKeys" gencodec:"required"` -} - -// StorageKeys returns the total number of storage keys in the access list. -func (al AccessList) StorageKeys() int { - sum := 0 - for _, tuple := range al { - sum += len(tuple.StorageKeys) - } - return sum -} - -// AccessListTx is the data of EIP-2930 access list transactions. -type AccessListTx struct { - ChainID *big.Int // destination chain ID - Nonce uint64 // nonce of sender account - GasPrice *big.Int // wei per gas - Gas uint64 // gas limit - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int // wei amount - Data []byte // contract invocation input data - AccessList AccessList // EIP-2930 access list - V, R, S *big.Int // signature values -} - -// copy creates a deep copy of the transaction data and initializes all fields. -func (tx *AccessListTx) copy() TxData { - cpy := &AccessListTx{ - Nonce: tx.Nonce, - To: copyAddressPtr(tx.To), - Data: common.CopyBytes(tx.Data), - Gas: tx.Gas, - // These are copied below. - AccessList: make(AccessList, len(tx.AccessList)), - Value: new(big.Int), - ChainID: new(big.Int), - GasPrice: new(big.Int), - V: new(big.Int), - R: new(big.Int), - S: new(big.Int), - } - copy(cpy.AccessList, tx.AccessList) - if tx.Value != nil { - cpy.Value.Set(tx.Value) - } - if tx.ChainID != nil { - cpy.ChainID.Set(tx.ChainID) - } - if tx.GasPrice != nil { - cpy.GasPrice.Set(tx.GasPrice) - } - if tx.V != nil { - cpy.V.Set(tx.V) - } - if tx.R != nil { - cpy.R.Set(tx.R) - } - if tx.S != nil { - cpy.S.Set(tx.S) - } - return cpy -} - -// accessors for innerTx. -func (tx *AccessListTx) txType() byte { return AccessListTxType } -func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } -func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } -func (tx *AccessListTx) data() []byte { return tx.Data } -func (tx *AccessListTx) gas() uint64 { return tx.Gas } -func (tx *AccessListTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *AccessListTx) value() *big.Int { return tx.Value } -func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } -func (tx *AccessListTx) to() *common.Address { return tx.To } - -func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { - return dst.Set(tx.GasPrice) -} - -func (tx *AccessListTx) rawSignatureValues() (v, r, s *big.Int) { - return tx.V, tx.R, tx.S -} - -func (tx *AccessListTx) setSignatureValues(chainID, v, r, s *big.Int) { - tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s -} - -func (tx *AccessListTx) encode(b *bytes.Buffer) error { - return rlp.Encode(b, tx) -} - -func (tx *AccessListTx) decode(input []byte) error { - return rlp.DecodeBytes(input, tx) -} diff --git a/builder/core/types/tx_blob.go b/builder/core/types/tx_blob.go deleted file mode 100644 index 25a85695e..000000000 --- a/builder/core/types/tx_blob.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2023 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 types - -import ( - "bytes" - "crypto/sha256" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/holiman/uint256" -) - -// BlobTx represents an EIP-4844 transaction. -type BlobTx struct { - ChainID *uint256.Int - Nonce uint64 - GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas - GasFeeCap *uint256.Int // a.k.a. maxFeePerGas - Gas uint64 - To common.Address - Value *uint256.Int - Data []byte - AccessList AccessList - BlobFeeCap *uint256.Int // a.k.a. maxFeePerBlobGas - BlobHashes []common.Hash - - // A blob transaction can optionally contain blobs. This field must be set when BlobTx - // is used to create a transaction for signing. - Sidecar *BlobTxSidecar `rlp:"-"` - - // Signature values - V *uint256.Int `json:"v" gencodec:"required"` - R *uint256.Int `json:"r" gencodec:"required"` - S *uint256.Int `json:"s" gencodec:"required"` -} - -// BlobTxSidecar contains the blobs of a blob transaction. -type BlobTxSidecar struct { - Blobs []kzg4844.Blob // Blobs needed by the blob pool - Commitments []kzg4844.Commitment // Commitments needed by the blob pool - Proofs []kzg4844.Proof // Proofs needed by the blob pool -} - -// BlobHashes computes the blob hashes of the given blobs. -func (sc *BlobTxSidecar) BlobHashes() []common.Hash { - hasher := sha256.New() - h := make([]common.Hash, len(sc.Commitments)) - for i := range sc.Blobs { - h[i] = kzg4844.CalcBlobHashV1(hasher, &sc.Commitments[i]) - } - return h -} - -// encodedSize computes the RLP size of the sidecar elements. This does NOT return the -// encoded size of the BlobTxSidecar, it's just a helper for tx.Size(). -func (sc *BlobTxSidecar) encodedSize() uint64 { - var blobs, commitments, proofs uint64 - for i := range sc.Blobs { - blobs += rlp.BytesSize(sc.Blobs[i][:]) - } - for i := range sc.Commitments { - commitments += rlp.BytesSize(sc.Commitments[i][:]) - } - for i := range sc.Proofs { - proofs += rlp.BytesSize(sc.Proofs[i][:]) - } - return rlp.ListSize(blobs) + rlp.ListSize(commitments) + rlp.ListSize(proofs) -} - -// blobTxWithBlobs is used for encoding of transactions when blobs are present. -type blobTxWithBlobs struct { - BlobTx *BlobTx - Blobs []kzg4844.Blob - Commitments []kzg4844.Commitment - Proofs []kzg4844.Proof -} - -// copy creates a deep copy of the transaction data and initializes all fields. -func (tx *BlobTx) copy() TxData { - cpy := &BlobTx{ - Nonce: tx.Nonce, - To: tx.To, - Data: common.CopyBytes(tx.Data), - Gas: tx.Gas, - // These are copied below. - AccessList: make(AccessList, len(tx.AccessList)), - BlobHashes: make([]common.Hash, len(tx.BlobHashes)), - Value: new(uint256.Int), - ChainID: new(uint256.Int), - GasTipCap: new(uint256.Int), - GasFeeCap: new(uint256.Int), - BlobFeeCap: new(uint256.Int), - V: new(uint256.Int), - R: new(uint256.Int), - S: new(uint256.Int), - } - copy(cpy.AccessList, tx.AccessList) - copy(cpy.BlobHashes, tx.BlobHashes) - - if tx.Value != nil { - cpy.Value.Set(tx.Value) - } - if tx.ChainID != nil { - cpy.ChainID.Set(tx.ChainID) - } - if tx.GasTipCap != nil { - cpy.GasTipCap.Set(tx.GasTipCap) - } - if tx.GasFeeCap != nil { - cpy.GasFeeCap.Set(tx.GasFeeCap) - } - if tx.BlobFeeCap != nil { - cpy.BlobFeeCap.Set(tx.BlobFeeCap) - } - if tx.V != nil { - cpy.V.Set(tx.V) - } - if tx.R != nil { - cpy.R.Set(tx.R) - } - if tx.S != nil { - cpy.S.Set(tx.S) - } - if tx.Sidecar != nil { - cpy.Sidecar = &BlobTxSidecar{ - Blobs: append([]kzg4844.Blob(nil), tx.Sidecar.Blobs...), - Commitments: append([]kzg4844.Commitment(nil), tx.Sidecar.Commitments...), - Proofs: append([]kzg4844.Proof(nil), tx.Sidecar.Proofs...), - } - } - return cpy -} - -// accessors for innerTx. -func (tx *BlobTx) txType() byte { return BlobTxType } -func (tx *BlobTx) chainID() *big.Int { return tx.ChainID.ToBig() } -func (tx *BlobTx) accessList() AccessList { return tx.AccessList } -func (tx *BlobTx) data() []byte { return tx.Data } -func (tx *BlobTx) gas() uint64 { return tx.Gas } -func (tx *BlobTx) gasFeeCap() *big.Int { return tx.GasFeeCap.ToBig() } -func (tx *BlobTx) gasTipCap() *big.Int { return tx.GasTipCap.ToBig() } -func (tx *BlobTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() } -func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() } -func (tx *BlobTx) nonce() uint64 { return tx.Nonce } -func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp } -func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) } - -func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { - if baseFee == nil { - return dst.Set(tx.GasFeeCap.ToBig()) - } - tip := dst.Sub(tx.GasFeeCap.ToBig(), baseFee) - if tip.Cmp(tx.GasTipCap.ToBig()) > 0 { - tip.Set(tx.GasTipCap.ToBig()) - } - return tip.Add(tip, baseFee) -} - -func (tx *BlobTx) rawSignatureValues() (v, r, s *big.Int) { - return tx.V.ToBig(), tx.R.ToBig(), tx.S.ToBig() -} - -func (tx *BlobTx) setSignatureValues(chainID, v, r, s *big.Int) { - tx.ChainID.SetFromBig(chainID) - tx.V.SetFromBig(v) - tx.R.SetFromBig(r) - tx.S.SetFromBig(s) -} - -func (tx *BlobTx) withoutSidecar() *BlobTx { - cpy := *tx - cpy.Sidecar = nil - return &cpy -} - -func (tx *BlobTx) encode(b *bytes.Buffer) error { - if tx.Sidecar == nil { - return rlp.Encode(b, tx) - } - inner := &blobTxWithBlobs{ - BlobTx: tx, - Blobs: tx.Sidecar.Blobs, - Commitments: tx.Sidecar.Commitments, - Proofs: tx.Sidecar.Proofs, - } - return rlp.Encode(b, inner) -} - -func (tx *BlobTx) decode(input []byte) error { - // Here we need to support two formats: the network protocol encoding of the tx (with - // blobs) or the canonical encoding without blobs. - // - // The two encodings can be distinguished by checking whether the first element of the - // input list is itself a list. - - outerList, _, err := rlp.SplitList(input) - if err != nil { - return err - } - firstElemKind, _, _, err := rlp.Split(outerList) - if err != nil { - return err - } - - if firstElemKind != rlp.List { - return rlp.DecodeBytes(input, tx) - } - // It's a tx with blobs. - var inner blobTxWithBlobs - if err := rlp.DecodeBytes(input, &inner); err != nil { - return err - } - *tx = *inner.BlobTx - tx.Sidecar = &BlobTxSidecar{ - Blobs: inner.Blobs, - Commitments: inner.Commitments, - Proofs: inner.Proofs, - } - return nil -} diff --git a/builder/core/types/tx_blob_test.go b/builder/core/types/tx_blob_test.go deleted file mode 100644 index 25d09e31c..000000000 --- a/builder/core/types/tx_blob_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package types - -import ( - "crypto/ecdsa" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/holiman/uint256" -) - -// This test verifies that tx.Hash() is not affected by presence of a BlobTxSidecar. -func TestBlobTxHashing(t *testing.T) { - key, _ := crypto.GenerateKey() - withBlobs := createEmptyBlobTx(key, true) - withBlobsStripped := withBlobs.WithoutBlobTxSidecar() - withoutBlobs := createEmptyBlobTx(key, false) - - hash := withBlobs.Hash() - t.Log("tx hash:", hash) - - if h := withBlobsStripped.Hash(); h != hash { - t.Fatal("wrong tx hash after WithoutBlobTxSidecar:", h) - } - if h := withoutBlobs.Hash(); h != hash { - t.Fatal("wrong tx hash on tx created without sidecar:", h) - } -} - -// This test verifies that tx.Size() takes BlobTxSidecar into account. -func TestBlobTxSize(t *testing.T) { - key, _ := crypto.GenerateKey() - withBlobs := createEmptyBlobTx(key, true) - withBlobsStripped := withBlobs.WithoutBlobTxSidecar() - withoutBlobs := createEmptyBlobTx(key, false) - - withBlobsEnc, _ := withBlobs.MarshalBinary() - withoutBlobsEnc, _ := withoutBlobs.MarshalBinary() - - size := withBlobs.Size() - t.Log("size with blobs:", size) - - sizeNoBlobs := withoutBlobs.Size() - t.Log("size without blobs:", sizeNoBlobs) - - if size != uint64(len(withBlobsEnc)) { - t.Error("wrong size with blobs:", size, "encoded length:", len(withBlobsEnc)) - } - if sizeNoBlobs != uint64(len(withoutBlobsEnc)) { - t.Error("wrong size without blobs:", sizeNoBlobs, "encoded length:", len(withoutBlobsEnc)) - } - if sizeNoBlobs >= size { - t.Error("size without blobs >= size with blobs") - } - if sz := withBlobsStripped.Size(); sz != sizeNoBlobs { - t.Fatal("wrong size on tx after WithoutBlobTxSidecar:", sz) - } -} - -var ( - emptyBlob = kzg4844.Blob{} - emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) - emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) -) - -func createEmptyBlobTx(key *ecdsa.PrivateKey, withSidecar bool) *Transaction { - blobtx := createEmptyBlobTxInner(withSidecar) - signer := NewCancunSigner(blobtx.ChainID.ToBig()) - return MustSignNewTx(key, signer, blobtx) -} - -func createEmptyBlobTxInner(withSidecar bool) *BlobTx { - sidecar := &BlobTxSidecar{ - Blobs: []kzg4844.Blob{emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - } - blobtx := &BlobTx{ - ChainID: uint256.NewInt(1), - Nonce: 5, - GasTipCap: uint256.NewInt(22), - GasFeeCap: uint256.NewInt(5), - Gas: 25000, - To: common.Address{0x03, 0x04, 0x05}, - Value: uint256.NewInt(99), - Data: make([]byte, 50), - BlobFeeCap: uint256.NewInt(15), - BlobHashes: sidecar.BlobHashes(), - } - if withSidecar { - blobtx.Sidecar = sidecar - } - return blobtx -} diff --git a/builder/core/types/tx_dynamic_fee.go b/builder/core/types/tx_dynamic_fee.go deleted file mode 100644 index 8b5b514fd..000000000 --- a/builder/core/types/tx_dynamic_fee.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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 types - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rlp" -) - -// DynamicFeeTx represents an EIP-1559 transaction. -type DynamicFeeTx struct { - ChainID *big.Int - Nonce uint64 - GasTipCap *big.Int // a.k.a. maxPriorityFeePerGas - GasFeeCap *big.Int // a.k.a. maxFeePerGas - Gas uint64 - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int - Data []byte - AccessList AccessList - - // Signature values - V *big.Int `json:"v" gencodec:"required"` - R *big.Int `json:"r" gencodec:"required"` - S *big.Int `json:"s" gencodec:"required"` -} - -// copy creates a deep copy of the transaction data and initializes all fields. -func (tx *DynamicFeeTx) copy() TxData { - cpy := &DynamicFeeTx{ - Nonce: tx.Nonce, - To: copyAddressPtr(tx.To), - Data: common.CopyBytes(tx.Data), - Gas: tx.Gas, - // These are copied below. - AccessList: make(AccessList, len(tx.AccessList)), - Value: new(big.Int), - ChainID: new(big.Int), - GasTipCap: new(big.Int), - GasFeeCap: new(big.Int), - V: new(big.Int), - R: new(big.Int), - S: new(big.Int), - } - copy(cpy.AccessList, tx.AccessList) - if tx.Value != nil { - cpy.Value.Set(tx.Value) - } - if tx.ChainID != nil { - cpy.ChainID.Set(tx.ChainID) - } - if tx.GasTipCap != nil { - cpy.GasTipCap.Set(tx.GasTipCap) - } - if tx.GasFeeCap != nil { - cpy.GasFeeCap.Set(tx.GasFeeCap) - } - if tx.V != nil { - cpy.V.Set(tx.V) - } - if tx.R != nil { - cpy.R.Set(tx.R) - } - if tx.S != nil { - cpy.S.Set(tx.S) - } - return cpy -} - -// accessors for innerTx. -func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } -func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } -func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } -func (tx *DynamicFeeTx) data() []byte { return tx.Data } -func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } -func (tx *DynamicFeeTx) gasFeeCap() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) gasTipCap() *big.Int { return tx.GasTipCap } -func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap } -func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } -func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } -func (tx *DynamicFeeTx) to() *common.Address { return tx.To } - -func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { - if baseFee == nil { - return dst.Set(tx.GasFeeCap) - } - tip := dst.Sub(tx.GasFeeCap, baseFee) - if tip.Cmp(tx.GasTipCap) > 0 { - tip.Set(tx.GasTipCap) - } - return tip.Add(tip, baseFee) -} - -func (tx *DynamicFeeTx) rawSignatureValues() (v, r, s *big.Int) { - return tx.V, tx.R, tx.S -} - -func (tx *DynamicFeeTx) setSignatureValues(chainID, v, r, s *big.Int) { - tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s -} - -func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error { - return rlp.Encode(b, tx) -} - -func (tx *DynamicFeeTx) decode(input []byte) error { - return rlp.DecodeBytes(input, tx) -} diff --git a/builder/core/types/tx_legacy.go b/builder/core/types/tx_legacy.go deleted file mode 100644 index 71025b78f..000000000 --- a/builder/core/types/tx_legacy.go +++ /dev/null @@ -1,125 +0,0 @@ -// 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 types - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -// LegacyTx is the transaction data of the original Ethereum transactions. -type LegacyTx struct { - Nonce uint64 // nonce of sender account - GasPrice *big.Int // wei per gas - Gas uint64 // gas limit - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int // wei amount - Data []byte // contract invocation input data - V, R, S *big.Int // signature values -} - -// NewTransaction creates an unsigned legacy transaction. -// Deprecated: use NewTx instead. -func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction { - return NewTx(&LegacyTx{ - Nonce: nonce, - To: &to, - Value: amount, - Gas: gasLimit, - GasPrice: gasPrice, - Data: data, - }) -} - -// NewContractCreation creates an unsigned legacy transaction. -// Deprecated: use NewTx instead. -func NewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction { - return NewTx(&LegacyTx{ - Nonce: nonce, - Value: amount, - Gas: gasLimit, - GasPrice: gasPrice, - Data: data, - }) -} - -// copy creates a deep copy of the transaction data and initializes all fields. -func (tx *LegacyTx) copy() TxData { - cpy := &LegacyTx{ - Nonce: tx.Nonce, - To: copyAddressPtr(tx.To), - Data: common.CopyBytes(tx.Data), - Gas: tx.Gas, - // These are initialized below. - Value: new(big.Int), - GasPrice: new(big.Int), - V: new(big.Int), - R: new(big.Int), - S: new(big.Int), - } - if tx.Value != nil { - cpy.Value.Set(tx.Value) - } - if tx.GasPrice != nil { - cpy.GasPrice.Set(tx.GasPrice) - } - if tx.V != nil { - cpy.V.Set(tx.V) - } - if tx.R != nil { - cpy.R.Set(tx.R) - } - if tx.S != nil { - cpy.S.Set(tx.S) - } - return cpy -} - -// accessors for innerTx. -func (tx *LegacyTx) txType() byte { return LegacyTxType } -func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } -func (tx *LegacyTx) accessList() AccessList { return nil } -func (tx *LegacyTx) data() []byte { return tx.Data } -func (tx *LegacyTx) gas() uint64 { return tx.Gas } -func (tx *LegacyTx) gasPrice() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasTipCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice } -func (tx *LegacyTx) value() *big.Int { return tx.Value } -func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } -func (tx *LegacyTx) to() *common.Address { return tx.To } - -func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { - return dst.Set(tx.GasPrice) -} - -func (tx *LegacyTx) rawSignatureValues() (v, r, s *big.Int) { - return tx.V, tx.R, tx.S -} - -func (tx *LegacyTx) setSignatureValues(chainID, v, r, s *big.Int) { - tx.V, tx.R, tx.S = v, r, s -} - -func (tx *LegacyTx) encode(*bytes.Buffer) error { - panic("encode called on LegacyTx") -} - -func (tx *LegacyTx) decode([]byte) error { - panic("decode called on LegacyTx)") -} diff --git a/builder/core/types/types_test.go b/builder/core/types/types_test.go deleted file mode 100644 index 1fb386d5d..000000000 --- a/builder/core/types/types_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// 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 types - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" -) - -type devnull struct{ len int } - -func (d *devnull) Write(p []byte) (int, error) { - d.len += len(p) - return len(p), nil -} - -func BenchmarkEncodeRLP(b *testing.B) { - benchRLP(b, true) -} - -func BenchmarkDecodeRLP(b *testing.B) { - benchRLP(b, false) -} - -func benchRLP(b *testing.B, encode bool) { - key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - to := common.HexToAddress("0x00000000000000000000000000000000deadbeef") - signer := NewLondonSigner(big.NewInt(1337)) - for _, tc := range []struct { - name string - obj interface{} - }{ - { - "legacy-header", - &Header{ - Difficulty: big.NewInt(10000000000), - Number: big.NewInt(1000), - GasLimit: 8_000_000, - GasUsed: 8_000_000, - Time: 555, - Extra: make([]byte, 32), - }, - }, - { - "london-header", - &Header{ - Difficulty: big.NewInt(10000000000), - Number: big.NewInt(1000), - GasLimit: 8_000_000, - GasUsed: 8_000_000, - Time: 555, - Extra: make([]byte, 32), - BaseFee: big.NewInt(10000000000), - }, - }, - { - "receipt-for-storage", - &ReceiptForStorage{ - Status: ReceiptStatusSuccessful, - CumulativeGasUsed: 0x888888888, - Logs: make([]*Log, 0), - }, - }, - { - "receipt-full", - &Receipt{ - Status: ReceiptStatusSuccessful, - CumulativeGasUsed: 0x888888888, - Logs: make([]*Log, 0), - }, - }, - { - "legacy-transaction", - MustSignNewTx(key, signer, - &LegacyTx{ - Nonce: 1, - GasPrice: big.NewInt(500), - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - }), - }, - { - "access-transaction", - MustSignNewTx(key, signer, - &AccessListTx{ - Nonce: 1, - GasPrice: big.NewInt(500), - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - }), - }, - { - "1559-transaction", - MustSignNewTx(key, signer, - &DynamicFeeTx{ - Nonce: 1, - Gas: 1000000, - To: &to, - Value: big.NewInt(1), - GasTipCap: big.NewInt(500), - GasFeeCap: big.NewInt(500), - }), - }, - } { - if encode { - b.Run(tc.name, func(b *testing.B) { - b.ReportAllocs() - var null = &devnull{} - for i := 0; i < b.N; i++ { - rlp.Encode(null, tc.obj) - } - b.SetBytes(int64(null.len / b.N)) - }) - } else { - data, _ := rlp.EncodeToBytes(tc.obj) - // Test decoding - b.Run(tc.name, func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - if err := rlp.DecodeBytes(data, tc.obj); err != nil { - b.Fatal(err) - } - } - b.SetBytes(int64(len(data))) - }) - } - } -} diff --git a/builder/core/types/withdrawal.go b/builder/core/types/withdrawal.go deleted file mode 100644 index d1ad918f9..000000000 --- a/builder/core/types/withdrawal.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 types - -import ( - "bytes" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rlp" -) - -//go:generate go run github.com/fjl/gencodec -type Withdrawal -field-override withdrawalMarshaling -out gen_withdrawal_json.go -//go:generate go run ../../rlp/rlpgen -type Withdrawal -out gen_withdrawal_rlp.go - -// Withdrawal represents a validator withdrawal from the consensus layer. -type Withdrawal struct { - Index uint64 `json:"index"` // monotonically increasing identifier issued by consensus layer - Validator uint64 `json:"validatorIndex"` // index of validator associated with withdrawal - Address common.Address `json:"address"` // target address for withdrawn ether - Amount uint64 `json:"amount"` // value of withdrawal in Gwei -} - -// field type overrides for gencodec -type withdrawalMarshaling struct { - Index hexutil.Uint64 - Validator hexutil.Uint64 - Amount hexutil.Uint64 -} - -// Withdrawals implements DerivableList for withdrawals. -type Withdrawals []*Withdrawal - -// Len returns the length of s. -func (s Withdrawals) Len() int { return len(s) } - -// EncodeIndex encodes the i'th withdrawal to w. Note that this does not check for errors -// because we assume that *Withdrawal will only ever contain valid withdrawals that were either -// constructed by decoding or via public API in this package. -func (s Withdrawals) EncodeIndex(i int, w *bytes.Buffer) { - rlp.Encode(w, s[i]) -} diff --git a/builder/core/vm/analysis.go b/builder/core/vm/analysis.go deleted file mode 100644 index 38af9084a..000000000 --- a/builder/core/vm/analysis.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 vm - -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 set bits on 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/builder/core/vm/analysis_test.go b/builder/core/vm/analysis_test.go deleted file mode 100644 index 398861f8a..000000000 --- a/builder/core/vm/analysis_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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 vm - -import ( - "math/bits" - "testing" - - "github.com/ethereum/go-ethereum/crypto" -) - -func TestJumpDestAnalysis(t *testing.T) { - tests := []struct { - code []byte - exp byte - which int - }{ - {[]byte{byte(PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0}, - {[]byte{byte(PUSH1), byte(PUSH1), byte(PUSH1), byte(PUSH1)}, 0b0000_1010, 0}, - {[]byte{0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1)}, 0b0101_0100, 0}, - {[]byte{byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0}, - {[]byte{byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1}, - {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), byte(PUSH2), byte(PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0}, - {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, - {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0}, - {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1}, - {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0}, - {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1}, - {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2}, - {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b1111_1110, 0}, - {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b0000_0101, 1}, - {[]byte{byte(PUSH32)}, 0b1111_1110, 0}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 1}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 2}, - {[]byte{byte(PUSH32)}, 0b1111_1111, 3}, - {[]byte{byte(PUSH32)}, 0b0000_0001, 4}, - } - for i, test := range tests { - ret := codeBitmap(test.code) - if ret[test.which] != test.exp { - t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which]) - } - } -} - -const analysisCodeSize = 1200 * 1024 - -func BenchmarkJumpdestAnalysis_1200k(bench *testing.B) { - // 1.4 ms - code := make([]byte, analysisCodeSize) - bench.SetBytes(analysisCodeSize) - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - codeBitmap(code) - } - bench.StopTimer() -} -func BenchmarkJumpdestHashing_1200k(bench *testing.B) { - // 4 ms - code := make([]byte, analysisCodeSize) - bench.SetBytes(analysisCodeSize) - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - crypto.Keccak256Hash(code) - } - bench.StopTimer() -} - -func BenchmarkJumpdestOpAnalysis(bench *testing.B) { - var op OpCode - bencher := func(b *testing.B) { - code := make([]byte, analysisCodeSize) - b.SetBytes(analysisCodeSize) - for i := range code { - code[i] = byte(op) - } - bits := make(bitvec, len(code)/8+1+4) - b.ResetTimer() - for i := 0; i < b.N; i++ { - for j := range bits { - bits[j] = 0 - } - codeBitmapInternal(code, bits) - } - } - for op = PUSH1; op <= PUSH32; op++ { - bench.Run(op.String(), bencher) - } - op = JUMPDEST - bench.Run(op.String(), bencher) - op = STOP - bench.Run(op.String(), bencher) -} diff --git a/builder/core/vm/common.go b/builder/core/vm/common.go deleted file mode 100644 index 90ba4a4ad..000000000 --- a/builder/core/vm/common.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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 vm - -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/builder/core/vm/contract.go b/builder/core/vm/contract.go deleted file mode 100644 index 16b669ebc..000000000 --- a/builder/core/vm/contract.go +++ /dev/null @@ -1,192 +0,0 @@ -// 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 vm - -import ( - "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 -// its 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 an 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 *uint256.Int -} - -// NewContract returns a new contract environment for the execution of EVM. -func NewContract(caller ContractRef, object ContractRef, value *uint256.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() *uint256.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/builder/core/vm/contracts.go b/builder/core/vm/contracts.go deleted file mode 100644 index 33a867654..000000000 --- a/builder/core/vm/contracts.go +++ /dev/null @@ -1,1136 +0,0 @@ -// 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 vm - -import ( - "crypto/sha256" - "encoding/binary" - "errors" - "fmt" - "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/crypto/kzg4844" - "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{}, -} - -// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum -// contracts used in the Cancun release. -var PrecompiledContractsCancun = 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{}, - common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, -} - -// 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 ( - PrecompiledAddressesCancun []common.Address - 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) - } - for k := range PrecompiledContractsCancun { - PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) - } -} - -// ActivePrecompiles returns the precompiles enabled with the current configuration. -func ActivePrecompiles(rules params.Rules) []common.Address { - switch { - case rules.IsCancun: - return PrecompiledAddressesCancun - 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 ( - 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 -} - -// kzgPointEvaluation implements the EIP-4844 point evaluation precompile. -type kzgPointEvaluation struct{} - -// RequiredGas estimates the gas required for running the point evaluation precompile. -func (b *kzgPointEvaluation) RequiredGas(input []byte) uint64 { - return params.BlobTxPointEvaluationPrecompileGas -} - -const ( - blobVerifyInputLength = 192 // Max input length for the point evaluation precompile. - blobCommitmentVersionKZG uint8 = 0x01 // Version byte for the point evaluation precompile. - blobPrecompileReturnValue = "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001" -) - -var ( - errBlobVerifyInvalidInputLength = errors.New("invalid input length") - errBlobVerifyMismatchedVersion = errors.New("mismatched versioned hash") - errBlobVerifyKZGProof = errors.New("error verifying kzg proof") -) - -// Run executes the point evaluation precompile. -func (b *kzgPointEvaluation) Run(input []byte) ([]byte, error) { - if len(input) != blobVerifyInputLength { - return nil, errBlobVerifyInvalidInputLength - } - // versioned hash: first 32 bytes - var versionedHash common.Hash - copy(versionedHash[:], input[:]) - - var ( - point kzg4844.Point - claim kzg4844.Claim - ) - // Evaluation point: next 32 bytes - copy(point[:], input[32:]) - // Expected output: next 32 bytes - copy(claim[:], input[64:]) - - // input kzg point: next 48 bytes - var commitment kzg4844.Commitment - copy(commitment[:], input[96:]) - if kZGToVersionedHash(commitment) != versionedHash { - return nil, errBlobVerifyMismatchedVersion - } - - // Proof: next 48 bytes - var proof kzg4844.Proof - copy(proof[:], input[144:]) - - if err := kzg4844.VerifyProof(commitment, point, claim, proof); err != nil { - return nil, fmt.Errorf("%w: %v", errBlobVerifyKZGProof, err) - } - - return common.Hex2Bytes(blobPrecompileReturnValue), nil -} - -// kZGToVersionedHash implements kzg_to_versioned_hash from EIP-4844 -func kZGToVersionedHash(kzg kzg4844.Commitment) common.Hash { - h := sha256.Sum256(kzg[:]) - h[0] = blobCommitmentVersionKZG - - return h -} diff --git a/builder/core/vm/contracts_fuzz_test.go b/builder/core/vm/contracts_fuzz_test.go deleted file mode 100644 index 87c1fff7c..000000000 --- a/builder/core/vm/contracts_fuzz_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2023 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 vm - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func FuzzPrecompiledContracts(f *testing.F) { - // Create list of addresses - var addrs []common.Address - for k := range allPrecompiles { - addrs = append(addrs, k) - } - f.Fuzz(func(t *testing.T, addr uint8, input []byte) { - a := addrs[int(addr)%len(addrs)] - p := allPrecompiles[a] - gas := p.RequiredGas(input) - if gas > 10_000_000 { - return - } - inWant := string(input) - RunPrecompiledContract(p, input, gas) - if inHave := string(input); inWant != inHave { - t.Errorf("Precompiled %v modified input data", a) - } - }) -} diff --git a/builder/core/vm/contracts_test.go b/builder/core/vm/contracts_test.go deleted file mode 100644 index fc30541d4..000000000 --- a/builder/core/vm/contracts_test.go +++ /dev/null @@ -1,397 +0,0 @@ -// 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 vm - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" -) - -// precompiledTest defines the input/output pairs for precompiled contract tests. -type precompiledTest struct { - Input, Expected string - Gas uint64 - Name string - NoBenchmark bool // Benchmark primarily the worst-cases -} - -// precompiledFailureTest defines the input/error pairs for precompiled -// contract failure tests. -type precompiledFailureTest struct { - Input string - ExpectedError string - Name string -} - -// allPrecompiles does not map to the actual set of precompiles, as it also contains -// repriced versions of precompiles at certain slots -var allPrecompiles = 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{0xf5}): &bigModExp{eip2565: true}, - common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, - common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, - - common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{}, - common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1Mul{}, - common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G1MultiExp{}, - common.BytesToAddress([]byte{0x0f, 0x0d}): &bls12381G2Add{}, - common.BytesToAddress([]byte{0x0f, 0x0e}): &bls12381G2Mul{}, - common.BytesToAddress([]byte{0x0f, 0x0f}): &bls12381G2MultiExp{}, - common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381Pairing{}, - common.BytesToAddress([]byte{0x0f, 0x11}): &bls12381MapG1{}, - common.BytesToAddress([]byte{0x0f, 0x12}): &bls12381MapG2{}, -} - -// EIP-152 test vectors -var blake2FMalformedInputTests = []precompiledFailureTest{ - { - Input: "", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 0: empty input", - }, - { - Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 1: less than 213 bytes input", - }, - { - Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - ExpectedError: errBlake2FInvalidInputLength.Error(), - Name: "vector 2: more than 213 bytes input", - }, - { - Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002", - ExpectedError: errBlake2FInvalidFinalFlag.Error(), - Name: "vector 3: malformed final block indicator flag", - }, -} - -func testPrecompiled(addr string, test precompiledTest, t *testing.T) { - p := allPrecompiles[common.HexToAddress(addr)] - in := common.Hex2Bytes(test.Input) - gas := p.RequiredGas(in) - t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { - if res, _, err := RunPrecompiledContract(p, in, gas); err != nil { - t.Error(err) - } else if common.Bytes2Hex(res) != test.Expected { - t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)) - } - if expGas := test.Gas; expGas != gas { - t.Errorf("%v: gas wrong, expected %d, got %d", test.Name, expGas, gas) - } - // Verify that the precompile did not touch the input buffer - exp := common.Hex2Bytes(test.Input) - if !bytes.Equal(in, exp) { - t.Errorf("Precompiled %v modified input data", addr) - } - }) -} - -func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) { - p := allPrecompiles[common.HexToAddress(addr)] - in := common.Hex2Bytes(test.Input) - gas := p.RequiredGas(in) - 1 - - t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) { - _, _, err := RunPrecompiledContract(p, in, gas) - if err.Error() != "out of gas" { - t.Errorf("Expected error [out of gas], got [%v]", err) - } - // Verify that the precompile did not touch the input buffer - exp := common.Hex2Bytes(test.Input) - if !bytes.Equal(in, exp) { - t.Errorf("Precompiled %v modified input data", addr) - } - }) -} - -func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing.T) { - p := allPrecompiles[common.HexToAddress(addr)] - in := common.Hex2Bytes(test.Input) - gas := p.RequiredGas(in) - t.Run(test.Name, func(t *testing.T) { - _, _, err := RunPrecompiledContract(p, in, gas) - if err.Error() != test.ExpectedError { - t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err) - } - // Verify that the precompile did not touch the input buffer - exp := common.Hex2Bytes(test.Input) - if !bytes.Equal(in, exp) { - t.Errorf("Precompiled %v modified input data", addr) - } - }) -} - -func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) { - if test.NoBenchmark { - return - } - p := allPrecompiles[common.HexToAddress(addr)] - in := common.Hex2Bytes(test.Input) - reqGas := p.RequiredGas(in) - - var ( - res []byte - err error - data = make([]byte, len(in)) - ) - - bench.Run(fmt.Sprintf("%s-Gas=%d", test.Name, reqGas), func(bench *testing.B) { - bench.ReportAllocs() - start := time.Now() - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - copy(data, in) - res, _, err = RunPrecompiledContract(p, data, reqGas) - } - bench.StopTimer() - elapsed := uint64(time.Since(start)) - if elapsed < 1 { - elapsed = 1 - } - gasUsed := reqGas * uint64(bench.N) - bench.ReportMetric(float64(reqGas), "gas/op") - // Keep it as uint64, multiply 100 to get two digit float later - mgasps := (100 * 1000 * gasUsed) / elapsed - bench.ReportMetric(float64(mgasps)/100, "mgas/s") - //Check if it is correct - if err != nil { - bench.Error(err) - return - } - if common.Bytes2Hex(res) != test.Expected { - bench.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)) - return - } - }) -} - -// Benchmarks the sample inputs from the ECRECOVER precompile. -func BenchmarkPrecompiledEcrecover(bench *testing.B) { - t := precompiledTest{ - Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - Expected: "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d", - Name: "", - } - benchmarkPrecompiled("01", t, bench) -} - -// Benchmarks the sample inputs from the SHA256 precompile. -func BenchmarkPrecompiledSha256(bench *testing.B) { - t := precompiledTest{ - Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - Expected: "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d", - Name: "128", - } - benchmarkPrecompiled("02", t, bench) -} - -// Benchmarks the sample inputs from the RIPEMD precompile. -func BenchmarkPrecompiledRipeMD(bench *testing.B) { - t := precompiledTest{ - Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - Expected: "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6", - Name: "128", - } - benchmarkPrecompiled("03", t, bench) -} - -// Benchmarks the sample inputs from the identity precompile. -func BenchmarkPrecompiledIdentity(bench *testing.B) { - t := precompiledTest{ - Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - Expected: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - Name: "128", - } - benchmarkPrecompiled("04", t, bench) -} - -// Tests the sample inputs from the ModExp EIP 198. -func TestPrecompiledModExp(t *testing.T) { testJson("modexp", "05", t) } -func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) } - -func TestPrecompiledModExpEip2565(t *testing.T) { testJson("modexp_eip2565", "f5", t) } -func BenchmarkPrecompiledModExpEip2565(b *testing.B) { benchJson("modexp_eip2565", "f5", b) } - -// Tests the sample inputs from the elliptic curve addition EIP 213. -func TestPrecompiledBn256Add(t *testing.T) { testJson("bn256Add", "06", t) } -func BenchmarkPrecompiledBn256Add(b *testing.B) { benchJson("bn256Add", "06", b) } - -// Tests OOG -func TestPrecompiledModExpOOG(t *testing.T) { - modexpTests, err := loadJson("modexp") - if err != nil { - t.Fatal(err) - } - for _, test := range modexpTests { - testPrecompiledOOG("05", test, t) - } -} - -// Tests the sample inputs from the elliptic curve scalar multiplication EIP 213. -func TestPrecompiledBn256ScalarMul(t *testing.T) { testJson("bn256ScalarMul", "07", t) } -func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMul", "07", b) } - -// Tests the sample inputs from the elliptic curve pairing check EIP 197. -func TestPrecompiledBn256Pairing(t *testing.T) { testJson("bn256Pairing", "08", t) } -func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) } - -func TestPrecompiledBlake2F(t *testing.T) { testJson("blake2F", "09", t) } -func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", b) } - -func TestPrecompileBlake2FMalformedInput(t *testing.T) { - for _, test := range blake2FMalformedInputTests { - testPrecompiledFailure("09", test, t) - } -} - -func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) } - -func testJson(name, addr string, t *testing.T) { - tests, err := loadJson(name) - if err != nil { - t.Fatal(err) - } - for _, test := range tests { - testPrecompiled(addr, test, t) - } -} - -func testJsonFail(name, addr string, t *testing.T) { - tests, err := loadJsonFail(name) - if err != nil { - t.Fatal(err) - } - for _, test := range tests { - testPrecompiledFailure(addr, test, t) - } -} - -func benchJson(name, addr string, b *testing.B) { - tests, err := loadJson(name) - if err != nil { - b.Fatal(err) - } - for _, test := range tests { - benchmarkPrecompiled(addr, test, b) - } -} - -func TestPrecompiledBLS12381G1Add(t *testing.T) { testJson("blsG1Add", "f0a", t) } -func TestPrecompiledBLS12381G1Mul(t *testing.T) { testJson("blsG1Mul", "f0b", t) } -func TestPrecompiledBLS12381G1MultiExp(t *testing.T) { testJson("blsG1MultiExp", "f0c", t) } -func TestPrecompiledBLS12381G2Add(t *testing.T) { testJson("blsG2Add", "f0d", t) } -func TestPrecompiledBLS12381G2Mul(t *testing.T) { testJson("blsG2Mul", "f0e", t) } -func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", "f0f", t) } -func TestPrecompiledBLS12381Pairing(t *testing.T) { testJson("blsPairing", "f10", t) } -func TestPrecompiledBLS12381MapG1(t *testing.T) { testJson("blsMapG1", "f11", t) } -func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "f12", t) } - -func TestPrecompiledPointEvaluation(t *testing.T) { testJson("pointEvaluation", "0a", t) } - -func BenchmarkPrecompiledBLS12381G1Add(b *testing.B) { benchJson("blsG1Add", "f0a", b) } -func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B) { benchJson("blsG1Mul", "f0b", b) } -func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "f0c", b) } -func BenchmarkPrecompiledBLS12381G2Add(b *testing.B) { benchJson("blsG2Add", "f0d", b) } -func BenchmarkPrecompiledBLS12381G2Mul(b *testing.B) { benchJson("blsG2Mul", "f0e", b) } -func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2MultiExp", "f0f", b) } -func BenchmarkPrecompiledBLS12381Pairing(b *testing.B) { benchJson("blsPairing", "f10", b) } -func BenchmarkPrecompiledBLS12381MapG1(b *testing.B) { benchJson("blsMapG1", "f11", b) } -func BenchmarkPrecompiledBLS12381MapG2(b *testing.B) { benchJson("blsMapG2", "f12", b) } - -// Failure tests -func TestPrecompiledBLS12381G1AddFail(t *testing.T) { testJsonFail("blsG1Add", "f0a", t) } -func TestPrecompiledBLS12381G1MulFail(t *testing.T) { testJsonFail("blsG1Mul", "f0b", t) } -func TestPrecompiledBLS12381G1MultiExpFail(t *testing.T) { testJsonFail("blsG1MultiExp", "f0c", t) } -func TestPrecompiledBLS12381G2AddFail(t *testing.T) { testJsonFail("blsG2Add", "f0d", t) } -func TestPrecompiledBLS12381G2MulFail(t *testing.T) { testJsonFail("blsG2Mul", "f0e", t) } -func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2MultiExp", "f0f", t) } -func TestPrecompiledBLS12381PairingFail(t *testing.T) { testJsonFail("blsPairing", "f10", t) } -func TestPrecompiledBLS12381MapG1Fail(t *testing.T) { testJsonFail("blsMapG1", "f11", t) } -func TestPrecompiledBLS12381MapG2Fail(t *testing.T) { testJsonFail("blsMapG2", "f12", t) } - -func loadJson(name string) ([]precompiledTest, error) { - data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name)) - if err != nil { - return nil, err - } - var testcases []precompiledTest - err = json.Unmarshal(data, &testcases) - return testcases, err -} - -func loadJsonFail(name string) ([]precompiledFailureTest, error) { - data, err := os.ReadFile(fmt.Sprintf("testdata/precompiles/fail-%v.json", name)) - if err != nil { - return nil, err - } - var testcases []precompiledFailureTest - err = json.Unmarshal(data, &testcases) - return testcases, err -} - -// BenchmarkPrecompiledBLS12381G1MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas. -func BenchmarkPrecompiledBLS12381G1MultiExpWorstCase(b *testing.B) { - task := "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be1" + - "0000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9" + - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - input := task - for i := 0; i < 4787; i++ { - input = input + task - } - testcase := precompiledTest{ - Input: input, - Expected: "0000000000000000000000000000000005a6310ea6f2a598023ae48819afc292b4dfcb40aabad24a0c2cb6c19769465691859eeb2a764342a810c5038d700f18000000000000000000000000000000001268ac944437d15923dc0aec00daa9250252e43e4b35ec7a19d01f0d6cd27f6e139d80dae16ba1c79cc7f57055a93ff5", - Name: "WorstCaseG1", - NoBenchmark: false, - } - benchmarkPrecompiled("0c", testcase, b) -} - -// BenchmarkPrecompiledBLS12381G2MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas. -func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) { - task := "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f" + - "000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b99" + - "00000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b" + - "000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7" + - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - input := task - for i := 0; i < 1040; i++ { - input = input + task - } - - testcase := precompiledTest{ - Input: input, - Expected: "0000000000000000000000000000000018f5ea0c8b086095cfe23f6bb1d90d45de929292006dba8cdedd6d3203af3c6bbfd592e93ecb2b2c81004961fdcbb46c00000000000000000000000000000000076873199175664f1b6493a43c02234f49dc66f077d3007823e0343ad92e30bd7dc209013435ca9f197aca44d88e9dac000000000000000000000000000000000e6f07f4b23b511eac1e2682a0fc224c15d80e122a3e222d00a41fab15eba645a700b9ae84f331ae4ed873678e2e6c9b000000000000000000000000000000000bcb4849e460612aaed79617255fd30c03f51cf03d2ed4163ca810c13e1954b1e8663157b957a601829bb272a4e6c7b8", - Name: "WorstCaseG2", - NoBenchmark: false, - } - benchmarkPrecompiled("0f", testcase, b) -} diff --git a/builder/core/vm/doc.go b/builder/core/vm/doc.go deleted file mode 100644 index 5864d0cfa..000000000 --- a/builder/core/vm/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// 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 vm implements the Ethereum Virtual Machine. - -The vm package implements one EVM, a byte code VM. The BC (Byte Code) VM loops -over a set of bytes and executes them according to the set of rules defined -in the Ethereum yellow paper. -*/ -package vm diff --git a/builder/core/vm/eips.go b/builder/core/vm/eips.go deleted file mode 100644 index 9f06b2818..000000000 --- a/builder/core/vm/eips.go +++ /dev/null @@ -1,321 +0,0 @@ -// 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 vm - -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){ - 5656: enable5656, - 6780: enable6780, - 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 := 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 -} - -// enable3860 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 -} - -// enable5656 enables EIP-5656 (MCOPY opcode) -// https://eips.ethereum.org/EIPS/eip-5656 -func enable5656(jt *JumpTable) { - jt[MCOPY] = &operation{ - execute: opMcopy, - constantGas: GasFastestStep, - dynamicGas: gasMcopy, - minStack: minStack(3, 0), - maxStack: maxStack(3, 0), - memorySize: memoryMcopy, - } -} - -// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656) -func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - var ( - dst = scope.Stack.pop() - src = scope.Stack.pop() - length = scope.Stack.pop() - ) - // These values are checked for overflow during memory expansion calculation - // (the memorySize function on the opcode). - scope.Memory.Copy(dst.Uint64(), src.Uint64(), length.Uint64()) - return nil, nil -} - -// opBlobHash implements the BLOBHASH opcode -func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - index := scope.Stack.peek() - if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) { - blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()] - index.SetBytes32(blobHash[:]) - } else { - index.Clear() - } - return nil, nil -} - -// opBlobBaseFee implements BLOBBASEFEE opcode -func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee) - scope.Stack.push(blobBaseFee) - return nil, nil -} - -// enable4844 applies EIP-4844 (BLOBHASH opcode) -func enable4844(jt *JumpTable) { - jt[BLOBHASH] = &operation{ - execute: opBlobHash, - constantGas: GasFastestStep, - minStack: minStack(1, 1), - maxStack: maxStack(1, 1), - } -} - -// enable7516 applies EIP-7516 (BLOBBASEFEE opcode) -func enable7516(jt *JumpTable) { - jt[BLOBBASEFEE] = &operation{ - execute: opBlobBaseFee, - constantGas: GasQuickStep, - minStack: minStack(0, 1), - maxStack: maxStack(0, 1), - } -} - -// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT) -func enable6780(jt *JumpTable) { - jt[SELFDESTRUCT] = &operation{ - execute: opSelfdestruct6780, - dynamicGas: gasSelfdestructEIP3529, - constantGas: params.SelfdestructGasEIP150, - minStack: minStack(1, 0), - maxStack: maxStack(1, 0), - } -} diff --git a/builder/core/vm/errors.go b/builder/core/vm/errors.go deleted file mode 100644 index fbbf19e17..000000000 --- a/builder/core/vm/errors.go +++ /dev/null @@ -1,73 +0,0 @@ -// 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 vm - -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/builder/core/vm/evm.go b/builder/core/vm/evm.go deleted file mode 100644 index 16cc85490..000000000 --- a/builder/core/vm/evm.go +++ /dev/null @@ -1,529 +0,0 @@ -// 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 vm - -import ( - "math/big" - "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" -) - -type ( - // CanTransferFunc is the signature of a transfer guard function - CanTransferFunc func(StateDB, common.Address, *uint256.Int) bool - // TransferFunc is the signature of a transfer function - TransferFunc func(StateDB, common.Address, common.Address, *uint256.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 -) - -func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { - var precompiles map[common.Address]PrecompiledContract - switch { - case evm.chainRules.IsCancun: - precompiles = PrecompiledContractsCancun - 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 (0 if vm runs with NoBaseFee flag and 0 gas price) - BlobBaseFee *big.Int // Provides information for BLOBBASEFEE (0 if vm runs with NoBaseFee flag and 0 blob gas price) - 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 (and is used to zero the basefee if NoBaseFee is set) - BlobHashes []common.Hash // Provides information for BLOBHASH - BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set -} - -// EVM 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 EVM should never be reused and is not thread safe. -type EVM struct { - // Context provides auxiliary blockchain related information - Context BlockContext - TxContext - // StateDB gives access to the underlying state - StateDB StateDB - // 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 - chainRules params.Rules - // 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 - abort atomic.Bool - // 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 -} - -// NewEVM returns a new EVM. The returned EVM is not thread safe and should -// only ever be used *once*. -func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { - // If basefee tracking is disabled (eth_call, eth_estimateGas, etc), and no - // gas prices were specified, lower the basefee to 0 to avoid breaking EVM - // invariants (basefee < feecap) - if config.NoBaseFee { - if txCtx.GasPrice.BitLen() == 0 { - blockCtx.BaseFee = new(big.Int) - } - if txCtx.BlobFeeCap != nil && txCtx.BlobFeeCap.BitLen() == 0 { - blockCtx.BlobBaseFee = new(big.Int) - } - } - evm := &EVM{ - Context: blockCtx, - TxContext: txCtx, - StateDB: statedb, - Config: config, - chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), - } - evm.interpreter = NewEVMInterpreter(evm) - return evm -} - -// Reset resets the EVM with a new transaction context.Reset -// This is not threadsafe and should only be done very cautiously. -func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) { - evm.TxContext = txCtx - evm.StateDB = statedb -} - -// Cancel cancels any running EVM operation. This may be called concurrently and -// it's safe to be called multiple times. -func (evm *EVM) Cancel() { - evm.abort.Store(true) -} - -// Cancelled returns true if Cancel has been called -func (evm *EVM) Cancelled() bool { - return evm.abort.Load() -} - -// Interpreter returns the current interpreter -func (evm *EVM) Interpreter() *EVMInterpreter { - return evm.interpreter -} - -// 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 *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.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.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { - return nil, gas, ErrInsufficientBalance - } - snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompile(addr) - debug := evm.Config.Tracer != nil - - if !evm.StateDB.Exist(addr) { - if !isPrecompile && evm.chainRules.IsEIP158 && value.IsZero() { - // Calling a non existing account, don't do anything, but ping the tracer - if debug { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig()) - evm.Config.Tracer.CaptureEnd(ret, 0, nil) - } else { - evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value.ToBig()) - 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 debug { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value.ToBig()) - 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.ToBig()) - 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 *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.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.Tracer != nil { - evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value.ToBig()) - 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 *EVM) 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.Tracer != nil { - // 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.ToBig()) - 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 *EVM) 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, new(uint256.Int)) - - // Invoke tracer hooks that signal entering/exiting a call frame - if evm.Config.Tracer != nil { - 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(uint256.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 *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.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 != types.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.Tracer != nil { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value.ToBig()) - } else { - evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig()) - } - } - - 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.Tracer != nil { - 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 -} - -// Create creates a new contract using code as deployment code. -func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.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 *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.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 *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } diff --git a/builder/core/vm/gas.go b/builder/core/vm/gas.go deleted file mode 100644 index 5cf1d852d..000000000 --- a/builder/core/vm/gas.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 vm - -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/builder/core/vm/gas_table.go b/builder/core/vm/gas_table.go deleted file mode 100644 index 4b141d8f9..000000000 --- a/builder/core/vm/gas_table.go +++ /dev/null @@ -1,479 +0,0 @@ -// 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 vm - -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) -// MCOPY (stack position 2) -// EXTCODECOPY (stack position 3) -// RETURNDATACOPY (stack position 2) -func memoryCopierGas(stackpos int) gasFunc { - return func(evm *EVM, 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) - gasMcopy = memoryCopierGas(2) - gasExtCodeCopy = memoryCopierGas(3) - gasReturnDataCopy = memoryCopierGas(2) -) - -func gasSStore(evm *EVM, 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 scenarios 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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.HasSelfDestructed(contract.Address()) { - evm.StateDB.AddRefund(params.SelfdestructRefundGas) - } - return gas, nil -} diff --git a/builder/core/vm/gas_table_test.go b/builder/core/vm/gas_table_test.go deleted file mode 100644 index 4a2545b6e..000000000 --- a/builder/core/vm/gas_table_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// 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 vm - -import ( - "bytes" - "math" - "math/big" - "sort" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -func TestMemoryGasCost(t *testing.T) { - tests := []struct { - size uint64 - cost uint64 - overflow bool - }{ - {0x1fffffffe0, 36028809887088637, false}, - {0x1fffffffe1, 0, true}, - } - for i, tt := range tests { - v, err := memoryGasCost(&Memory{}, tt.size) - if (err == ErrGasUintOverflow) != tt.overflow { - t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow) - } - if v != tt.cost { - t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost) - } - } -} - -var eip2200Tests = []struct { - original byte - gaspool uint64 - input string - used uint64 - refund uint64 - failure error -}{ - {0, math.MaxUint64, "0x60006000556000600055", 1612, 0, nil}, // 0 -> 0 -> 0 - {0, math.MaxUint64, "0x60006000556001600055", 20812, 0, nil}, // 0 -> 0 -> 1 - {0, math.MaxUint64, "0x60016000556000600055", 20812, 19200, nil}, // 0 -> 1 -> 0 - {0, math.MaxUint64, "0x60016000556002600055", 20812, 0, nil}, // 0 -> 1 -> 2 - {0, math.MaxUint64, "0x60016000556001600055", 20812, 0, nil}, // 0 -> 1 -> 1 - {1, math.MaxUint64, "0x60006000556000600055", 5812, 15000, nil}, // 1 -> 0 -> 0 - {1, math.MaxUint64, "0x60006000556001600055", 5812, 4200, nil}, // 1 -> 0 -> 1 - {1, math.MaxUint64, "0x60006000556002600055", 5812, 0, nil}, // 1 -> 0 -> 2 - {1, math.MaxUint64, "0x60026000556000600055", 5812, 15000, nil}, // 1 -> 2 -> 0 - {1, math.MaxUint64, "0x60026000556003600055", 5812, 0, nil}, // 1 -> 2 -> 3 - {1, math.MaxUint64, "0x60026000556001600055", 5812, 4200, nil}, // 1 -> 2 -> 1 - {1, math.MaxUint64, "0x60026000556002600055", 5812, 0, nil}, // 1 -> 2 -> 2 - {1, math.MaxUint64, "0x60016000556000600055", 5812, 15000, nil}, // 1 -> 1 -> 0 - {1, math.MaxUint64, "0x60016000556002600055", 5812, 0, nil}, // 1 -> 1 -> 2 - {1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1 - {0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1 - {1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0 - {1, 2306, "0x6001600055", 2306, 0, ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH) - {1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH) -} - -func TestEIP2200(t *testing.T) { - for i, tt := range eip2200Tests { - address := common.BytesToAddress([]byte("contract")) - - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.CreateAccount(address) - statedb.SetCode(address, hexutil.MustDecode(tt.input)) - statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original})) - statedb.Finalise(true) // Push the state into the "original" slot - - vmctx := BlockContext{ - CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true }, - Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {}, - } - vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}}) - - _, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int)) - if err != tt.failure { - t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure) - } - if used := tt.gaspool - gas; used != tt.used { - t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used) - } - if refund := vmenv.StateDB.GetRefund(); refund != tt.refund { - t.Errorf("test %d: gas refund mismatch: have %v, want %v", i, refund, tt.refund) - } - } -} - -var createGasTests = []struct { - code string - eip3860 bool - gasUsed uint64 - minimumGas uint64 -}{ - // legacy create(0, 0, 0xc000) without 3860 used - {"0x61C00060006000f0" + "600052" + "60206000F3", false, 41237, 41237}, - // legacy create(0, 0, 0xc000) _with_ 3860 - {"0x61C00060006000f0" + "600052" + "60206000F3", true, 44309, 44309}, - // create2(0, 0, 0xc001, 0) without 3860 - {"0x600061C00160006000f5" + "600052" + "60206000F3", false, 50471, 50471}, - // create2(0, 0, 0xc001, 0) (too large), with 3860 - {"0x600061C00160006000f5" + "600052" + "60206000F3", true, 32012, 100_000}, - // create2(0, 0, 0xc000, 0) - // This case is trying to deploy code at (within) the limit - {"0x600061C00060006000f5" + "600052" + "60206000F3", true, 53528, 53528}, - // create2(0, 0, 0xc001, 0) - // This case is trying to deploy code exceeding the limit - {"0x600061C00160006000f5" + "600052" + "60206000F3", true, 32024, 100000}, -} - -func TestCreateGas(t *testing.T) { - for i, tt := range createGasTests { - var gasUsed = uint64(0) - doCheck := func(testGas int) bool { - address := common.BytesToAddress([]byte("contract")) - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.CreateAccount(address) - statedb.SetCode(address, hexutil.MustDecode(tt.code)) - statedb.Finalise(true) - vmctx := BlockContext{ - CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true }, - Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {}, - BlockNumber: big.NewInt(0), - } - config := Config{} - if tt.eip3860 { - config.ExtraEips = []int{3860} - } - - vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config) - var startGas = uint64(testGas) - ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int)) - if err != nil { - return false - } - gasUsed = startGas - gas - if len(ret) != 32 { - t.Fatalf("test %d: expected 32 bytes returned, have %d", i, len(ret)) - } - if bytes.Equal(ret, make([]byte, 32)) { - // Failure - return false - } - return true - } - minGas := sort.Search(100_000, doCheck) - if uint64(minGas) != tt.minimumGas { - t.Fatalf("test %d: min gas error, want %d, have %d", i, tt.minimumGas, minGas) - } - // If the deployment succeeded, we also check the gas used - if minGas < 100_000 { - if gasUsed != tt.gasUsed { - t.Errorf("test %d: gas used mismatch: have %v, want %v", i, gasUsed, tt.gasUsed) - } - } - } -} diff --git a/builder/core/vm/instructions.go b/builder/core/vm/instructions.go deleted file mode 100644 index b8055de6b..000000000 --- a/builder/core/vm/instructions.go +++ /dev/null @@ -1,915 +0,0 @@ -// 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 vm - -import ( - "math" - - "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.Set(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) { - scope.Stack.push(scope.Contract.value) - 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) { - scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code)))) - 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 = math.MaxUint64 - } - 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 = math.MaxUint64 - } - 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 self-destructed -// 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 interpreter.evm.abort.Load() { - 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 interpreter.evm.abort.Load() { - 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) - - res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value) - // 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 - res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas, - &endowment, &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 - } - if !value.IsZero() { - gas += params.CallStipend - } - ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value) - - 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())) - - if !value.IsZero() { - gas += params.CallStipend - } - - ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, &value) - 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.SelfDestruct(scope.Contract.Address()) - if tracer := interpreter.evm.Config.Tracer; tracer != nil { - tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) - tracer.CaptureExit([]byte{}, 0, nil) - } - return nil, errStopToken -} - -func opSelfdestruct6780(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.SubBalance(scope.Contract.Address(), balance) - interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) - interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address()) - if tracer := interpreter.evm.Config.Tracer; tracer != nil { - tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) - 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/builder/core/vm/instructions_test.go b/builder/core/vm/instructions_test.go deleted file mode 100644 index 8653864d1..000000000 --- a/builder/core/vm/instructions_test.go +++ /dev/null @@ -1,930 +0,0 @@ -// 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 vm - -import ( - "bytes" - "encoding/json" - "fmt" - "math/big" - "os" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -type TwoOperandTestcase struct { - X string - Y string - Expected string -} - -type twoOperandParams struct { - x string - y string -} - -var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" -var commonParams []*twoOperandParams -var twoOpMethods map[string]executionFunc - -type contractRef struct { - addr common.Address -} - -func (c contractRef) Address() common.Address { - return c.addr -} - -func init() { - // Params is a list of common edgecases that should be used for some common tests - params := []string{ - "0000000000000000000000000000000000000000000000000000000000000000", // 0 - "0000000000000000000000000000000000000000000000000000000000000001", // +1 - "0000000000000000000000000000000000000000000000000000000000000005", // +5 - "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", // + max -1 - "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // + max - "8000000000000000000000000000000000000000000000000000000000000000", // - max - "8000000000000000000000000000000000000000000000000000000000000001", // - max+1 - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", // - 5 - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // - 1 - } - // Params are combined so each param is used on each 'side' - commonParams = make([]*twoOperandParams, len(params)*len(params)) - for i, x := range params { - for j, y := range params { - commonParams[i*len(params)+j] = &twoOperandParams{x, y} - } - } - twoOpMethods = map[string]executionFunc{ - "add": opAdd, - "sub": opSub, - "mul": opMul, - "div": opDiv, - "sdiv": opSdiv, - "mod": opMod, - "smod": opSmod, - "exp": opExp, - "signext": opSignExtend, - "lt": opLt, - "gt": opGt, - "slt": opSlt, - "sgt": opSgt, - "eq": opEq, - "and": opAnd, - "or": opOr, - "xor": opXor, - "byte": opByte, - "shl": opSHL, - "shr": opSHR, - "sar": opSAR, - } -} - -func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) - evmInterpreter = env.interpreter - ) - - for i, test := range tests { - x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X)) - y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y)) - expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected)) - stack.push(x) - stack.push(y) - opFn(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data)) - } - actual := stack.pop() - - if actual.Cmp(expected) != 0 { - t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, actual) - } - } -} - -func TestByteOp(t *testing.T) { - tests := []TwoOperandTestcase{ - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", "00", "AB"}, - {"ABCDEF0908070605040302010000000000000000000000000000000000000000", "01", "CD"}, - {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "00", "00"}, - {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", "01", "CD"}, - {"0000000000000000000000000000000000000000000000000000000000102030", "1F", "30"}, - {"0000000000000000000000000000000000000000000000000000000000102030", "1E", "20"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "20", "00"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"}, - } - testTwoOperandOp(t, tests, opByte, "byte") -} - -func TestSHL(t *testing.T) { - // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shl-shift-left - tests := []TwoOperandTestcase{ - {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000002"}, - {"0000000000000000000000000000000000000000000000000000000000000001", "ff", "8000000000000000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000001", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000001", "0101", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "8000000000000000000000000000000000000000000000000000000000000000"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, - } - testTwoOperandOp(t, tests, opSHL, "shl") -} - -func TestSHR(t *testing.T) { - // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#shr-logical-shift-right - tests := []TwoOperandTestcase{ - {"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "01", "4000000000000000000000000000000000000000000000000000000000000000"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "ff", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "0101", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, - } - testTwoOperandOp(t, tests, opSHR, "shr") -} - -func TestSAR(t *testing.T) { - // Testcases from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-145.md#sar-arithmetic-shift-right - tests := []TwoOperandTestcase{ - {"0000000000000000000000000000000000000000000000000000000000000001", "00", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"0000000000000000000000000000000000000000000000000000000000000001", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "01", "c000000000000000000000000000000000000000000000000000000000000000"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"8000000000000000000000000000000000000000000000000000000000000000", "0101", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - {"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"4000000000000000000000000000000000000000000000000000000000000000", "fe", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "f8", "000000000000000000000000000000000000000000000000000000000000007f"}, - {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "fe", "0000000000000000000000000000000000000000000000000000000000000001"}, - {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", "0000000000000000000000000000000000000000000000000000000000000000"}, - {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"}, - } - - testTwoOperandOp(t, tests, opSAR, "sar") -} - -func TestAddMod(t *testing.T) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - evmInterpreter = NewEVMInterpreter(env) - pc = uint64(0) - ) - tests := []struct { - x string - y string - z string - expected string - }{ - {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - }, - } - // x + y = 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd - // in 256 bit repr, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd - - for i, test := range tests { - x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.x)) - y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y)) - z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z)) - expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected)) - stack.push(z) - stack.push(y) - stack.push(x) - opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - actual := stack.pop() - if actual.Cmp(expected) != 0 { - t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual) - } - } -} - -// utility function to fill the json-file with testcases -// Enable this test to generate the 'testcases_xx.json' files -func TestWriteExpectedValues(t *testing.T) { - t.Skip("Enable this test to create json test cases.") - - // getResult is a convenience function to generate the expected values - getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) - interpreter = env.interpreter - ) - result := make([]TwoOperandTestcase, len(args)) - for i, param := range args { - x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x)) - y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y)) - stack.push(x) - stack.push(y) - opFn(&pc, interpreter, &ScopeContext{nil, stack, nil}) - actual := stack.pop() - result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)} - } - return result - } - - for name, method := range twoOpMethods { - data, err := json.Marshal(getResult(commonParams, method)) - if err != nil { - t.Fatal(err) - } - _ = os.WriteFile(fmt.Sprintf("testdata/testcases_%v.json", name), data, 0644) - if err != nil { - t.Fatal(err) - } - } -} - -// TestJsonTestcases runs through all the testcases defined as json-files -func TestJsonTestcases(t *testing.T) { - for name := range twoOpMethods { - data, err := os.ReadFile(fmt.Sprintf("testdata/testcases_%v.json", name)) - if err != nil { - t.Fatal("Failed to read file", err) - } - var testcases []TwoOperandTestcase - json.Unmarshal(data, &testcases) - testTwoOperandOp(t, testcases, twoOpMethods[name], name) - } -} - -func opBenchmark(bench *testing.B, op executionFunc, args ...string) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - scope = &ScopeContext{nil, stack, nil} - evmInterpreter = NewEVMInterpreter(env) - ) - - env.interpreter = evmInterpreter - // convert args - intArgs := make([]*uint256.Int, len(args)) - for i, arg := range args { - intArgs[i] = new(uint256.Int).SetBytes(common.Hex2Bytes(arg)) - } - pc := uint64(0) - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - for _, arg := range intArgs { - stack.push(arg) - } - op(&pc, evmInterpreter, scope) - stack.pop() - } - bench.StopTimer() - - for i, arg := range args { - want := new(uint256.Int).SetBytes(common.Hex2Bytes(arg)) - if have := intArgs[i]; !want.Eq(have) { - bench.Fatalf("input #%d mutated, have %x want %x", i, have, want) - } - } -} - -func BenchmarkOpAdd64(b *testing.B) { - x := "ffffffff" - y := "fd37f3e2bba2c4f" - - opBenchmark(b, opAdd, x, y) -} - -func BenchmarkOpAdd128(b *testing.B) { - x := "ffffffffffffffff" - y := "f5470b43c6549b016288e9a65629687" - - opBenchmark(b, opAdd, x, y) -} - -func BenchmarkOpAdd256(b *testing.B) { - x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9" - y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57" - - opBenchmark(b, opAdd, x, y) -} - -func BenchmarkOpSub64(b *testing.B) { - x := "51022b6317003a9d" - y := "a20456c62e00753a" - - opBenchmark(b, opSub, x, y) -} - -func BenchmarkOpSub128(b *testing.B) { - x := "4dde30faaacdc14d00327aac314e915d" - y := "9bbc61f5559b829a0064f558629d22ba" - - opBenchmark(b, opSub, x, y) -} - -func BenchmarkOpSub256(b *testing.B) { - x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37" - y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e" - - opBenchmark(b, opSub, x, y) -} - -func BenchmarkOpMul(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opMul, x, y) -} - -func BenchmarkOpDiv256(b *testing.B) { - x := "ff3f9014f20db29ae04af2c2d265de17" - y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" - opBenchmark(b, opDiv, x, y) -} - -func BenchmarkOpDiv128(b *testing.B) { - x := "fdedc7f10142ff97" - y := "fbdfda0e2ce356173d1993d5f70a2b11" - opBenchmark(b, opDiv, x, y) -} - -func BenchmarkOpDiv64(b *testing.B) { - x := "fcb34eb3" - y := "f97180878e839129" - opBenchmark(b, opDiv, x, y) -} - -func BenchmarkOpSdiv(b *testing.B) { - x := "ff3f9014f20db29ae04af2c2d265de17" - y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" - - opBenchmark(b, opSdiv, x, y) -} - -func BenchmarkOpMod(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opMod, x, y) -} - -func BenchmarkOpSmod(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opSmod, x, y) -} - -func BenchmarkOpExp(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opExp, x, y) -} - -func BenchmarkOpSignExtend(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opSignExtend, x, y) -} - -func BenchmarkOpLt(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opLt, x, y) -} - -func BenchmarkOpGt(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opGt, x, y) -} - -func BenchmarkOpSlt(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opSlt, x, y) -} - -func BenchmarkOpSgt(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opSgt, x, y) -} - -func BenchmarkOpEq(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opEq, x, y) -} -func BenchmarkOpEq2(b *testing.B) { - x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe" - opBenchmark(b, opEq, x, y) -} -func BenchmarkOpAnd(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opAnd, x, y) -} - -func BenchmarkOpOr(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opOr, x, y) -} - -func BenchmarkOpXor(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opXor, x, y) -} - -func BenchmarkOpByte(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - - opBenchmark(b, opByte, x, y) -} - -func BenchmarkOpAddmod(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - z := alphabetSoup - - opBenchmark(b, opAddmod, x, y, z) -} - -func BenchmarkOpMulmod(b *testing.B) { - x := alphabetSoup - y := alphabetSoup - z := alphabetSoup - - opBenchmark(b, opMulmod, x, y, z) -} - -func BenchmarkOpSHL(b *testing.B) { - x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - y := "ff" - - opBenchmark(b, opSHL, x, y) -} -func BenchmarkOpSHR(b *testing.B) { - x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - y := "ff" - - opBenchmark(b, opSHR, x, y) -} -func BenchmarkOpSAR(b *testing.B) { - x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - y := "ff" - - opBenchmark(b, opSAR, x, y) -} -func BenchmarkOpIsZero(b *testing.B) { - x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff" - opBenchmark(b, opIszero, x) -} - -func TestOpMstore(t *testing.T) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) - ) - - env.interpreter = evmInterpreter - mem.Resize(64) - pc := uint64(0) - v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" - stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) - stack.push(new(uint256.Int)) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) - if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v { - t.Fatalf("Mstore fail, got %v, expected %v", got, v) - } - stack.push(new(uint256.Int).SetUint64(0x1)) - stack.push(new(uint256.Int)) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) - if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { - t.Fatalf("Mstore failed to overwrite previous value") - } -} - -func BenchmarkOpMstore(bench *testing.B) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) - ) - - env.interpreter = evmInterpreter - mem.Resize(64) - pc := uint64(0) - memStart := new(uint256.Int) - value := new(uint256.Int).SetUint64(0x1337) - - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - stack.push(value) - stack.push(memStart) - opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) - } -} - -func TestOpTstore(t *testing.T) { - var ( - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) - caller = common.Address{} - to = common.Address{1} - contractRef = contractRef{caller} - contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0) - scopeContext = ScopeContext{mem, stack, contract} - value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") - ) - - // Add a stateObject for the caller and the contract being called - statedb.CreateAccount(caller) - statedb.CreateAccount(to) - - env.interpreter = evmInterpreter - pc := uint64(0) - // push the value to the stack - stack.push(new(uint256.Int).SetBytes(value)) - // push the location to the stack - stack.push(new(uint256.Int)) - opTstore(&pc, evmInterpreter, &scopeContext) - // there should be no elements on the stack after TSTORE - if stack.len() != 0 { - t.Fatal("stack wrong size") - } - // push the location to the stack - stack.push(new(uint256.Int)) - opTload(&pc, evmInterpreter, &scopeContext) - // there should be one element on the stack after TLOAD - if stack.len() != 1 { - t.Fatal("stack wrong size") - } - val := stack.peek() - if !bytes.Equal(val.Bytes(), value) { - t.Fatal("incorrect element read from transient storage") - } -} - -func BenchmarkOpKeccak256(bench *testing.B) { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() - evmInterpreter = NewEVMInterpreter(env) - ) - env.interpreter = evmInterpreter - mem.Resize(32) - pc := uint64(0) - start := new(uint256.Int) - - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - stack.push(uint256.NewInt(32)) - stack.push(start) - opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) - } -} - -func TestCreate2Addreses(t *testing.T) { - type testcase struct { - origin string - salt string - code string - expected string - } - - for i, tt := range []testcase{ - { - origin: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000", - code: "0x00", - expected: "0x4d1a2e2bb4f88f0250f26ffff098b0b30b26bf38", - }, - { - origin: "0xdeadbeef00000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000", - code: "0x00", - expected: "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3", - }, - { - origin: "0xdeadbeef00000000000000000000000000000000", - salt: "0xfeed000000000000000000000000000000000000", - code: "0x00", - expected: "0xD04116cDd17beBE565EB2422F2497E06cC1C9833", - }, - { - origin: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000", - code: "0xdeadbeef", - expected: "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e", - }, - { - origin: "0x00000000000000000000000000000000deadbeef", - salt: "0xcafebabe", - code: "0xdeadbeef", - expected: "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7", - }, - { - origin: "0x00000000000000000000000000000000deadbeef", - salt: "0xcafebabe", - code: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - expected: "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C", - }, - { - origin: "0x0000000000000000000000000000000000000000", - salt: "0x0000000000000000000000000000000000000000", - code: "0x", - expected: "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0", - }, - } { - origin := common.BytesToAddress(common.FromHex(tt.origin)) - salt := common.BytesToHash(common.FromHex(tt.salt)) - code := common.FromHex(tt.code) - codeHash := crypto.Keccak256(code) - address := crypto.CreateAddress2(origin, salt, codeHash) - /* - stack := newstack() - // salt, but we don't need that for this test - stack.push(big.NewInt(int64(len(code)))) //size - stack.push(big.NewInt(0)) // memstart - stack.push(big.NewInt(0)) // value - gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0) - fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String()) - */ - expected := common.BytesToAddress(common.FromHex(tt.expected)) - if !bytes.Equal(expected.Bytes(), address.Bytes()) { - t.Errorf("test %d: expected %s, got %s", i, expected.String(), address.String()) - } - } -} - -func TestRandom(t *testing.T) { - type testcase struct { - name string - random common.Hash - } - - for _, tt := range []testcase{ - {name: "empty hash", random: common.Hash{}}, - {name: "1", random: common.Hash{0}}, - {name: "emptyCodeHash", random: types.EmptyCodeHash}, - {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, - } { - var ( - env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) - evmInterpreter = env.interpreter - ) - opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) - } - actual := stack.pop() - expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes())) - if overflow { - t.Errorf("Testcase %v: invalid overflow", tt.name) - } - if actual.Cmp(expected) != 0 { - t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual) - } - } -} - -func TestBlobHash(t *testing.T) { - type testcase struct { - name string - idx uint64 - expect common.Hash - hashes []common.Hash - } - var ( - zero = common.Hash{0} - one = common.Hash{1} - two = common.Hash{2} - three = common.Hash{3} - ) - for _, tt := range []testcase{ - {name: "[{1}]", idx: 0, expect: one, hashes: []common.Hash{one}}, - {name: "[1,{2},3]", idx: 2, expect: three, hashes: []common.Hash{one, two, three}}, - {name: "out-of-bounds (empty)", idx: 10, expect: zero, hashes: []common.Hash{}}, - {name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}}, - {name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil}, - } { - var ( - env = NewEVM(BlockContext{}, TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) - evmInterpreter = env.interpreter - ) - stack.push(uint256.NewInt(tt.idx)) - opBlobHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) - if len(stack.data) != 1 { - t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data)) - } - actual := stack.pop() - expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes())) - if overflow { - t.Errorf("Testcase %v: invalid overflow", tt.name) - } - if actual.Cmp(expected) != 0 { - t.Errorf("Testcase %v: expected %x, got %x", tt.name, expected, actual) - } - } -} - -func TestOpMCopy(t *testing.T) { - // Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases - for i, tc := range []struct { - dst, src, len string - pre string - want string - wantGas uint64 - }{ - { // MCOPY 0 32 32 - copy 32 bytes from offset 32 to offset 0. - dst: "0x0", src: "0x20", len: "0x20", - pre: "0000000000000000000000000000000000000000000000000000000000000000 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", - want: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", - wantGas: 6, - }, - - { // MCOPY 0 0 32 - copy 32 bytes from offset 0 to offset 0. - dst: "0x0", src: "0x0", len: "0x20", - pre: "0101010101010101010101010101010101010101010101010101010101010101", - want: "0101010101010101010101010101010101010101010101010101010101010101", - wantGas: 6, - }, - { // MCOPY 0 1 8 - copy 8 bytes from offset 1 to offset 0 (overlapping). - dst: "0x0", src: "0x1", len: "0x8", - pre: "000102030405060708 000000000000000000000000000000000000000000000000", - want: "010203040506070808 000000000000000000000000000000000000000000000000", - wantGas: 6, - }, - { // MCOPY 1 0 8 - copy 8 bytes from offset 0 to offset 1 (overlapping). - dst: "0x1", src: "0x0", len: "0x8", - pre: "000102030405060708 000000000000000000000000000000000000000000000000", - want: "000001020304050607 000000000000000000000000000000000000000000000000", - wantGas: 6, - }, - // Tests below are not in the EIP, but maybe should be added - { // MCOPY 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds index(overlapping). - dst: "0xFFFFFFFFFFFF", src: "0xFFFFFFFFFFFF", len: "0x0", - pre: "11", - want: "11", - wantGas: 3, - }, - { // MCOPY 0xFFFFFFFFFFFF 0 0 - copy zero bytes from start of mem to out-of-bounds. - dst: "0xFFFFFFFFFFFF", src: "0x0", len: "0x0", - pre: "11", - want: "11", - wantGas: 3, - }, - { // MCOPY 0 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds to start of mem - dst: "0x0", src: "0xFFFFFFFFFFFF", len: "0x0", - pre: "11", - want: "11", - wantGas: 3, - }, - { // MCOPY - copy 1 from space outside of uint64 space - dst: "0x0", src: "0x10000000000000000", len: "0x1", - pre: "0", - }, - { // MCOPY - copy 1 from 0 to space outside of uint64 - dst: "0x10000000000000000", src: "0x0", len: "0x1", - pre: "0", - }, - { // MCOPY - copy nothing from 0 to space outside of uint64 - dst: "0x10000000000000000", src: "0x0", len: "0x0", - pre: "", - want: "", - wantGas: 3, - }, - { // MCOPY - copy 1 from 0x20 to 0x10, with no prior allocated mem - dst: "0x10", src: "0x20", len: "0x1", - pre: "", - // 64 bytes - want: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - wantGas: 12, - }, - { // MCOPY - copy 1 from 0x19 to 0x10, with no prior allocated mem - dst: "0x10", src: "0x19", len: "0x1", - pre: "", - // 32 bytes - want: "0x0000000000000000000000000000000000000000000000000000000000000000", - wantGas: 9, - }, - } { - var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) - evmInterpreter = env.interpreter - ) - data := common.FromHex(strings.ReplaceAll(tc.pre, " ", "")) - // Set pre - mem := NewMemory() - mem.Resize(uint64(len(data))) - mem.Set(0, uint64(len(data)), data) - // Push stack args - len, _ := uint256.FromHex(tc.len) - src, _ := uint256.FromHex(tc.src) - dst, _ := uint256.FromHex(tc.dst) - - stack.push(len) - stack.push(src) - stack.push(dst) - wantErr := (tc.wantGas == 0) - // Calc mem expansion - var memorySize uint64 - if memSize, overflow := memoryMcopy(stack); overflow { - if wantErr { - continue - } - t.Errorf("overflow") - } else { - var overflow bool - if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { - t.Error(ErrGasUintOverflow) - } - } - // and the dynamic cost - var haveGas uint64 - if dynamicCost, err := gasMcopy(env, nil, stack, mem, memorySize); err != nil { - t.Error(err) - } else { - haveGas = GasFastestStep + dynamicCost - } - // Expand mem - if memorySize > 0 { - mem.Resize(memorySize) - } - // Do the copy - opMcopy(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) - want := common.FromHex(strings.ReplaceAll(tc.want, " ", "")) - if have := mem.store; !bytes.Equal(want, have) { - t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have) - } - wantGas := tc.wantGas - if haveGas != wantGas { - t.Errorf("case %d: gas wrong, want %d have %d\n", i, wantGas, haveGas) - } - } -} diff --git a/builder/core/vm/interface.go b/builder/core/vm/interface.go deleted file mode 100644 index 25bfa0672..000000000 --- a/builder/core/vm/interface.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 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 vm - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -// StateDB is an EVM database for full state querying. -type StateDB interface { - CreateAccount(common.Address) - - SubBalance(common.Address, *uint256.Int) - AddBalance(common.Address, *uint256.Int) - GetBalance(common.Address) *uint256.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) - - SelfDestruct(common.Address) - HasSelfDestructed(common.Address) bool - - Selfdestruct6780(common.Address) - - // Exist reports whether the given account exists in state. - // Notably this should also return true for self-destructed 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 *EVM, 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 *EVM, 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 *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) - // Create creates a new contract - Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) -} diff --git a/builder/core/vm/interpreter.go b/builder/core/vm/interpreter.go deleted file mode 100644 index 1968289f4..000000000 --- a/builder/core/vm/interpreter.go +++ /dev/null @@ -1,242 +0,0 @@ -// 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 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 { - 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 *EVM - table *JumpTable - - hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes - hasherBuf common.Hash // Keccak256 hasher result array shared across 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 *EVM) *EVMInterpreter { - // If jump table was not initialised we set the default one. - var table *JumpTable - switch { - case evm.chainRules.IsCancun: - table = &cancunInstructionSet - 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 - debug = in.evm.Config.Tracer != nil - ) - // Don't move this deferred function, it's placed before the capturestate-deferred method, - // so that it gets executed _after_: the capturestate needs the stacks before - // they are returned to the pools - defer func() { - returnStack(stack) - }() - contract.Input = input - - if 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 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 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 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++ - } - - if err == errStopToken { - err = nil // clear stop token error - } - - return res, err -} diff --git a/builder/core/vm/interpreter_test.go b/builder/core/vm/interpreter_test.go deleted file mode 100644 index ff4977d72..000000000 --- a/builder/core/vm/interpreter_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// 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 vm - -import ( - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -var loopInterruptTests = []string{ - // infinite loop using JUMP: push(2) jumpdest dup1 jump - "60025b8056", - // infinite loop using JUMPI: push(1) push(4) jumpdest dup2 dup2 jumpi - "600160045b818157", -} - -func TestLoopInterrupt(t *testing.T) { - address := common.BytesToAddress([]byte("contract")) - vmctx := BlockContext{ - Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {}, - } - - for i, tt := range loopInterruptTests { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.CreateAccount(address) - statedb.SetCode(address, common.Hex2Bytes(tt)) - statedb.Finalise(true) - - evm := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{}) - - errChannel := make(chan error) - timeout := make(chan bool) - - go func(evm *EVM) { - _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int)) - errChannel <- err - }(evm) - - go func() { - <-time.After(time.Second) - timeout <- true - }() - - evm.Cancel() - - select { - case <-timeout: - t.Errorf("test %d timed out", i) - case err := <-errChannel: - if err != nil { - t.Errorf("test %d failure: %v", i, err) - } - } - } -} diff --git a/builder/core/vm/jump_table.go b/builder/core/vm/jump_table.go deleted file mode 100644 index 65716f944..000000000 --- a/builder/core/vm/jump_table.go +++ /dev/null @@ -1,1076 +0,0 @@ -// 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 vm - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/params" -) - -type ( - executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) - gasFunc func(*EVM, *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() - cancunInstructionSet = newCancunInstructionSet() -) - -// 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 newCancunInstructionSet() JumpTable { - instructionSet := newShanghaiInstructionSet() - enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode) - enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode) - enable1153(&instructionSet) // EIP-1153 "Transient Storage" - enable5656(&instructionSet) // EIP-5656 (MCOPY opcode) - enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction - return validate(instructionSet) -} - -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) // Gas cost increases for state access opcodes 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/builder/core/vm/jump_table_export.go b/builder/core/vm/jump_table_export.go deleted file mode 100644 index b74109da0..000000000 --- a/builder/core/vm/jump_table_export.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2023 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 vm - -import ( - "errors" - - "github.com/ethereum/go-ethereum/params" -) - -// LookupInstructionSet returns the instruction set for the fork configured by -// the rules. -func LookupInstructionSet(rules params.Rules) (JumpTable, error) { - switch { - case rules.IsVerkle: - return newCancunInstructionSet(), errors.New("verkle-fork not defined yet") - case rules.IsPrague: - return newCancunInstructionSet(), errors.New("prague-fork not defined yet") - case rules.IsCancun: - return newCancunInstructionSet(), nil - case rules.IsShanghai: - return newShanghaiInstructionSet(), nil - case rules.IsMerge: - return newMergeInstructionSet(), nil - case rules.IsLondon: - return newLondonInstructionSet(), nil - case rules.IsBerlin: - return newBerlinInstructionSet(), nil - case rules.IsIstanbul: - return newIstanbulInstructionSet(), nil - case rules.IsConstantinople: - return newConstantinopleInstructionSet(), nil - case rules.IsByzantium: - return newByzantiumInstructionSet(), nil - case rules.IsEIP158: - return newSpuriousDragonInstructionSet(), nil - case rules.IsEIP150: - return newTangerineWhistleInstructionSet(), nil - case rules.IsHomestead: - return newHomesteadInstructionSet(), nil - } - return newFrontierInstructionSet(), nil -} - -// Stack returns the minimum and maximum stack requirements. -func (op *operation) Stack() (int, int) { - return op.minStack, op.maxStack -} - -// HasCost returns true if the opcode has a cost. Opcodes which do _not_ have -// a cost assigned are one of two things: -// - undefined, a.k.a invalid opcodes, -// - the STOP opcode. -// This method can thus be used to check if an opcode is "Invalid (or STOP)". -func (op *operation) HasCost() bool { - // Ideally, we'd check this: - // return op.execute == opUndefined - // However, go-lang does now allow that. So we'll just check some other - // 'indicators' that this is an invalid op. Alas, STOP is impossible to - // filter out - return op.dynamicGas != nil || op.constantGas != 0 -} diff --git a/builder/core/vm/jump_table_test.go b/builder/core/vm/jump_table_test.go deleted file mode 100644 index 02558035c..000000000 --- a/builder/core/vm/jump_table_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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 vm - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -// TestJumpTableCopy tests that deep copy is necessary to prevent modify shared jump table -func TestJumpTableCopy(t *testing.T) { - tbl := newMergeInstructionSet() - require.Equal(t, uint64(0), tbl[SLOAD].constantGas) - - // a deep copy won't modify the shared jump table - deepCopy := copyJumpTable(&tbl) - deepCopy[SLOAD].constantGas = 100 - require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas) - require.Equal(t, uint64(0), tbl[SLOAD].constantGas) -} diff --git a/builder/core/vm/logger.go b/builder/core/vm/logger.go deleted file mode 100644 index 2667908a8..000000000 --- a/builder/core/vm/logger.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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 vm - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -// EVMLogger is used to collect execution traces from an EVM transaction -// execution. CaptureState is called for each step of the VM with the -// current VM state. -// Note that reference types are actual VM data structures; make copies -// if you need to retain them beyond the current call. -type EVMLogger interface { - // Transaction level - CaptureTxStart(gasLimit uint64) - CaptureTxEnd(restGas uint64) - // Top call frame - CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) - CaptureEnd(output []byte, gasUsed uint64, err error) - // Rest of call frames - 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 - 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/builder/core/vm/memory.go b/builder/core/vm/memory.go deleted file mode 100644 index e0202fd7c..000000000 --- a/builder/core/vm/memory.go +++ /dev/null @@ -1,116 +0,0 @@ -// 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 vm - -import ( - "github.com/holiman/uint256" -) - -// Memory implements a simple memory model for the ethereum virtual machine. -type Memory struct { - store []byte - lastGasCost uint64 -} - -// NewMemory returns a new memory model. -func NewMemory() *Memory { - return &Memory{} -} - -// Set sets offset + size to value -func (m *Memory) Set(offset, size uint64, value []byte) { - // It's possible the offset is greater than 0 and size equals 0. This is because - // the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP) - if size > 0 { - // length of store may never be less than offset + size. - // The store should be resized PRIOR to setting the memory - if offset+size > uint64(len(m.store)) { - panic("invalid memory: store empty") - } - copy(m.store[offset:offset+size], value) - } -} - -// Set32 sets the 32 bytes starting at offset to the value of val, left-padded with zeroes to -// 32 bytes. -func (m *Memory) Set32(offset uint64, val *uint256.Int) { - // length of store may never be less than offset + size. - // The store should be resized PRIOR to setting the memory - if offset+32 > uint64(len(m.store)) { - panic("invalid memory: store empty") - } - // Fill in relevant bits - b32 := val.Bytes32() - copy(m.store[offset:], b32[:]) -} - -// Resize resizes the memory to size -func (m *Memory) Resize(size uint64) { - if uint64(m.Len()) < size { - m.store = append(m.store, make([]byte, size-uint64(m.Len()))...) - } -} - -// GetCopy returns offset + size as a new slice -func (m *Memory) GetCopy(offset, size int64) (cpy []byte) { - if size == 0 { - return nil - } - - if len(m.store) > int(offset) { - cpy = make([]byte, size) - copy(cpy, m.store[offset:offset+size]) - - return - } - - return -} - -// GetPtr returns the offset + size -func (m *Memory) GetPtr(offset, size int64) []byte { - if size == 0 { - return nil - } - - if len(m.store) > int(offset) { - return m.store[offset : offset+size] - } - - return nil -} - -// Len returns the length of the backing slice -func (m *Memory) Len() int { - return len(m.store) -} - -// Data returns the backing slice -func (m *Memory) Data() []byte { - return m.store -} - -// Copy copies data from the src position slice into the dst position. -// The source and destination may overlap. -// OBS: This operation assumes that any necessary memory expansion has already been performed, -// and this method may panic otherwise. -func (m *Memory) Copy(dst, src, len uint64) { - if len == 0 { - return - } - copy(m.store[dst:], m.store[src:src+len]) -} diff --git a/builder/core/vm/memory_table.go b/builder/core/vm/memory_table.go deleted file mode 100644 index 61a910a03..000000000 --- a/builder/core/vm/memory_table.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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 vm - -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 memoryMcopy(stack *Stack) (uint64, bool) { - mStart := stack.Back(0) // stack[0]: dest - if stack.Back(1).Gt(mStart) { - mStart = stack.Back(1) // stack[1]: source - } - return calcMemSize64(mStart, stack.Back(2)) // stack[2]: length -} - -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/builder/core/vm/memory_test.go b/builder/core/vm/memory_test.go deleted file mode 100644 index ba36f8023..000000000 --- a/builder/core/vm/memory_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package vm - -import ( - "bytes" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func TestMemoryCopy(t *testing.T) { - // Test cases from https://eips.ethereum.org/EIPS/eip-5656#test-cases - for i, tc := range []struct { - dst, src, len uint64 - pre string - want string - }{ - { // MCOPY 0 32 32 - copy 32 bytes from offset 32 to offset 0. - 0, 32, 32, - "0000000000000000000000000000000000000000000000000000000000000000 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", - }, - - { // MCOPY 0 0 32 - copy 32 bytes from offset 0 to offset 0. - 0, 0, 32, - "0101010101010101010101010101010101010101010101010101010101010101", - "0101010101010101010101010101010101010101010101010101010101010101", - }, - { // MCOPY 0 1 8 - copy 8 bytes from offset 1 to offset 0 (overlapping). - 0, 1, 8, - "000102030405060708 000000000000000000000000000000000000000000000000", - "010203040506070808 000000000000000000000000000000000000000000000000", - }, - { // MCOPY 1 0 8 - copy 8 bytes from offset 0 to offset 1 (overlapping). - 1, 0, 8, - "000102030405060708 000000000000000000000000000000000000000000000000", - "000001020304050607 000000000000000000000000000000000000000000000000", - }, - // Tests below are not in the EIP, but maybe should be added - { // MCOPY 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds index(overlapping). - 0xFFFFFFFFFFFF, 0xFFFFFFFFFFFF, 0, - "11", - "11", - }, - { // MCOPY 0xFFFFFFFFFFFF 0 0 - copy zero bytes from start of mem to out-of-bounds. - 0xFFFFFFFFFFFF, 0, 0, - "11", - "11", - }, - { // MCOPY 0 0xFFFFFFFFFFFF 0 - copy zero bytes from out-of-bounds to start of mem - 0, 0xFFFFFFFFFFFF, 0, - "11", - "11", - }, - } { - m := NewMemory() - // Clean spaces - data := common.FromHex(strings.ReplaceAll(tc.pre, " ", "")) - // Set pre - m.Resize(uint64(len(data))) - m.Set(0, uint64(len(data)), data) - // Do the copy - m.Copy(tc.dst, tc.src, tc.len) - want := common.FromHex(strings.ReplaceAll(tc.want, " ", "")) - if have := m.store; !bytes.Equal(want, have) { - t.Errorf("case %d: want: %#x\nhave: %#x\n", i, want, have) - } - } -} diff --git a/builder/core/vm/opcodes.go b/builder/core/vm/opcodes.go deleted file mode 100644 index 2b9231fe1..000000000 --- a/builder/core/vm/opcodes.go +++ /dev/null @@ -1,562 +0,0 @@ -// 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 vm - -import ( - "fmt" -) - -// OpCode is an EVM opcode -type OpCode byte - -// IsPush specifies if an opcode is a PUSH opcode. -func (op OpCode) IsPush() bool { - return PUSH0 <= op && op <= PUSH32 -} - -// 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 -) - -// 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 -) - -// 0x20 range - crypto. -const ( - KECCAK256 OpCode = 0x20 -) - -// 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 -) - -// 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 - BLOBHASH OpCode = 0x49 - BLOBBASEFEE OpCode = 0x4a -) - -// 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 - TLOAD OpCode = 0x5c - TSTORE OpCode = 0x5d - MCOPY OpCode = 0x5e - PUSH0 OpCode = 0x5f -) - -// 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 -) - -// 0x80 range - dups. -const ( - DUP1 = 0x80 + iota - DUP2 - DUP3 - DUP4 - DUP5 - DUP6 - DUP7 - DUP8 - DUP9 - DUP10 - DUP11 - DUP12 - DUP13 - DUP14 - DUP15 - DUP16 -) - -// 0x90 range - swaps. -const ( - SWAP1 = 0x90 + iota - SWAP2 - SWAP3 - SWAP4 - SWAP5 - SWAP6 - SWAP7 - SWAP8 - SWAP9 - SWAP10 - SWAP11 - SWAP12 - SWAP13 - SWAP14 - SWAP15 - SWAP16 -) - -// 0xa0 range - logging ops. -const ( - LOG0 OpCode = 0xa0 + iota - LOG1 - LOG2 - LOG3 - LOG4 -) - -// 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 -) - -var opCodeToString = [256]string{ - // 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", - CALLER: "CALLER", - CALLVALUE: "CALLVALUE", - CALLDATALOAD: "CALLDATALOAD", - CALLDATASIZE: "CALLDATASIZE", - CALLDATACOPY: "CALLDATACOPY", - CODESIZE: "CODESIZE", - CODECOPY: "CODECOPY", - GASPRICE: "GASPRICE", - EXTCODESIZE: "EXTCODESIZE", - EXTCODECOPY: "EXTCODECOPY", - RETURNDATASIZE: "RETURNDATASIZE", - RETURNDATACOPY: "RETURNDATACOPY", - EXTCODEHASH: "EXTCODEHASH", - - // 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", - BLOBHASH: "BLOBHASH", - BLOBBASEFEE: "BLOBBASEFEE", - - // 0x50 range - 'storage' and execution. - POP: "POP", - MLOAD: "MLOAD", - MSTORE: "MSTORE", - MSTORE8: "MSTORE8", - SLOAD: "SLOAD", - SSTORE: "SSTORE", - JUMP: "JUMP", - JUMPI: "JUMPI", - PC: "PC", - MSIZE: "MSIZE", - GAS: "GAS", - JUMPDEST: "JUMPDEST", - TLOAD: "TLOAD", - TSTORE: "TSTORE", - MCOPY: "MCOPY", - PUSH0: "PUSH0", - - // 0x60 range - pushes. - 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", - - // 0x80 - dups. - 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", - - // 0x90 - swaps. - 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", - - // 0xa0 range - logging ops. - LOG0: "LOG0", - LOG1: "LOG1", - LOG2: "LOG2", - LOG3: "LOG3", - LOG4: "LOG4", - - // 0xf0 range - closures. - 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 { - if s := opCodeToString[op]; s != "" { - return s - } - return fmt.Sprintf("opcode %#x not defined", int(op)) -} - -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, - "BLOBHASH": BLOBHASH, - "BLOBBASEFEE": BLOBBASEFEE, - "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, - "TLOAD": TLOAD, - "TSTORE": TSTORE, - "MCOPY": MCOPY, - "PUSH0": PUSH0, - "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/builder/core/vm/operations_acl.go b/builder/core/vm/operations_acl.go deleted file mode 100644 index f420a2410..000000000 --- a/builder/core/vm/operations_acl.go +++ /dev/null @@ -1,249 +0,0 @@ -// 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 vm - -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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 *EVM, 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 - - var overflow bool - if gas, overflow = math.SafeAdd(gas, coldCost); overflow { - return 0, ErrGasUintOverflow - } - return gas, nil - } -} - -var ( - gasCallEIP2929 = makeCallVariantGasCallEIP2929(gasCall) - gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall) - gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall) - gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode) - gasSelfdestructEIP2929 = makeSelfdestructGasFn(true) - // gasSelfdestructEIP3529 implements the changes in EIP-3529 (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) - - // gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529 - // 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-3529 -func makeSelfdestructGasFn(refundsEnabled bool) gasFunc { - gasFunc := func(evm *EVM, 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.HasSelfDestructed(contract.Address()) { - evm.StateDB.AddRefund(params.SelfdestructRefundGas) - } - return gas, nil - } - return gasFunc -} diff --git a/builder/core/vm/runtime/doc.go b/builder/core/vm/runtime/doc.go deleted file mode 100644 index a3b464a7d..000000000 --- a/builder/core/vm/runtime/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -// 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 runtime provides a basic execution model for executing EVM code. -package runtime diff --git a/builder/core/vm/runtime/env.go b/builder/core/vm/runtime/env.go deleted file mode 100644 index 34335b8e9..000000000 --- a/builder/core/vm/runtime/env.go +++ /dev/null @@ -1,46 +0,0 @@ -// 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 runtime - -import ( - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/vm" -) - -func NewEnv(cfg *Config) *vm.EVM { - txContext := vm.TxContext{ - Origin: cfg.Origin, - GasPrice: cfg.GasPrice, - BlobHashes: cfg.BlobHashes, - BlobFeeCap: cfg.BlobFeeCap, - } - blockContext := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - GetHash: cfg.GetHashFn, - Coinbase: cfg.Coinbase, - BlockNumber: cfg.BlockNumber, - Time: cfg.Time, - Difficulty: cfg.Difficulty, - GasLimit: cfg.GasLimit, - BaseFee: cfg.BaseFee, - BlobBaseFee: cfg.BlobBaseFee, - Random: cfg.Random, - } - - return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig) -} diff --git a/builder/core/vm/runtime/runtime.go b/builder/core/vm/runtime/runtime.go deleted file mode 100644 index 46f2bb5d5..000000000 --- a/builder/core/vm/runtime/runtime.go +++ /dev/null @@ -1,201 +0,0 @@ -// 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 runtime - -import ( - "math" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -// Config is a basic type specifying certain configuration flags for running -// the EVM. -type Config struct { - ChainConfig *params.ChainConfig - Difficulty *big.Int - Origin common.Address - Coinbase common.Address - BlockNumber *big.Int - Time uint64 - GasLimit uint64 - GasPrice *big.Int - Value *big.Int - Debug bool - EVMConfig vm.Config - BaseFee *big.Int - BlobBaseFee *big.Int - BlobHashes []common.Hash - BlobFeeCap *big.Int - Random *common.Hash - - State *state.StateDB - GetHashFn func(n uint64) common.Hash -} - -// sets defaults on the config -func setDefaults(cfg *Config) { - if cfg.ChainConfig == nil { - cfg.ChainConfig = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: new(big.Int), - DAOForkBlock: new(big.Int), - DAOForkSupport: false, - EIP150Block: new(big.Int), - EIP155Block: new(big.Int), - EIP158Block: new(big.Int), - ByzantiumBlock: new(big.Int), - ConstantinopleBlock: new(big.Int), - PetersburgBlock: new(big.Int), - IstanbulBlock: new(big.Int), - MuirGlacierBlock: new(big.Int), - BerlinBlock: new(big.Int), - LondonBlock: new(big.Int), - } - } - - if cfg.Difficulty == nil { - cfg.Difficulty = new(big.Int) - } - if cfg.GasLimit == 0 { - cfg.GasLimit = math.MaxUint64 - } - if cfg.GasPrice == nil { - cfg.GasPrice = new(big.Int) - } - if cfg.Value == nil { - cfg.Value = new(big.Int) - } - if cfg.BlockNumber == nil { - cfg.BlockNumber = new(big.Int) - } - if cfg.GetHashFn == nil { - cfg.GetHashFn = func(n uint64) common.Hash { - return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String()))) - } - } - if cfg.BaseFee == nil { - cfg.BaseFee = big.NewInt(params.InitialBaseFee) - } - if cfg.BlobBaseFee == nil { - cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice) - } -} - -// Execute executes the code using the input as call data during the execution. -// It returns the EVM's return value, the new state and an error if it failed. -// -// Execute sets up an in-memory, temporary, environment for the execution of -// the given code. It makes sure that it's restored to its original state afterwards. -func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { - if cfg == nil { - cfg = new(Config) - } - setDefaults(cfg) - - if cfg.State == nil { - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - } - var ( - address = common.BytesToAddress([]byte("contract")) - vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) - ) - // Execute the preparatory steps for state transition which includes: - // - prepare accessList(post-berlin) - // - reset transient storage(eip 1153) - cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) - cfg.State.CreateAccount(address) - // set the receiver's (the executing contract) code for execution. - cfg.State.SetCode(address, code) - // Call the code with the given configuration. - ret, _, err := vmenv.Call( - sender, - common.BytesToAddress([]byte("contract")), - input, - cfg.GasLimit, - uint256.MustFromBig(cfg.Value), - ) - return ret, cfg.State, err -} - -// Create executes the code using the EVM create method -func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { - if cfg == nil { - cfg = new(Config) - } - setDefaults(cfg) - - if cfg.State == nil { - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - } - var ( - vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) - ) - // Execute the preparatory steps for state transition which includes: - // - prepare accessList(post-berlin) - // - reset transient storage(eip 1153) - cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil) - // Call the code with the given configuration. - code, address, leftOverGas, err := vmenv.Create( - sender, - input, - cfg.GasLimit, - uint256.MustFromBig(cfg.Value), - ) - return code, address, leftOverGas, err -} - -// Call executes the code given by the contract's address. It will return the -// EVM's return value or an error if it failed. -// -// Call, unlike Execute, requires a config and also requires the State field to -// be set. -func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) { - setDefaults(cfg) - - var ( - vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) - statedb = cfg.State - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) - ) - // Execute the preparatory steps for state transition which includes: - // - prepare accessList(post-berlin) - // - reset transient storage(eip 1153) - statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) - - // Call the code with the given configuration. - ret, leftOverGas, err := vmenv.Call( - sender, - address, - input, - cfg.GasLimit, - uint256.MustFromBig(cfg.Value), - ) - return ret, leftOverGas, err -} diff --git a/builder/core/vm/runtime/runtime_example_test.go b/builder/core/vm/runtime/runtime_example_test.go deleted file mode 100644 index b7d0ddc38..000000000 --- a/builder/core/vm/runtime/runtime_example_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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 runtime_test - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm/runtime" -) - -func ExampleExecute() { - ret, _, err := runtime.Execute(common.Hex2Bytes("6060604052600a8060106000396000f360606040526008565b00"), nil, nil) - if err != nil { - fmt.Println(err) - } - fmt.Println(ret) - // Output: - // [96 96 96 64 82 96 8 86 91 0] -} diff --git a/builder/core/vm/runtime/runtime_fuzz_test.go b/builder/core/vm/runtime/runtime_fuzz_test.go deleted file mode 100644 index 8a4d31d81..000000000 --- a/builder/core/vm/runtime/runtime_fuzz_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2023 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 runtime - -import ( - "testing" -) - -func FuzzVmRuntime(f *testing.F) { - f.Fuzz(func(t *testing.T, code, input []byte) { - Execute(code, input, &Config{ - GasLimit: 12000000, - }) - }) -} diff --git a/builder/core/vm/runtime/runtime_test.go b/builder/core/vm/runtime/runtime_test.go deleted file mode 100644 index b9e3c8ed6..000000000 --- a/builder/core/vm/runtime/runtime_test.go +++ /dev/null @@ -1,915 +0,0 @@ -// 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 runtime - -import ( - "fmt" - "math/big" - "os" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/asm" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/params" - - // force-load js tracers to trigger registration - _ "github.com/ethereum/go-ethereum/eth/tracers/js" - "github.com/holiman/uint256" -) - -func TestDefaults(t *testing.T) { - cfg := new(Config) - setDefaults(cfg) - - if cfg.Difficulty == nil { - t.Error("expected difficulty to be non nil") - } - - if cfg.GasLimit == 0 { - t.Error("didn't expect gaslimit to be zero") - } - if cfg.GasPrice == nil { - t.Error("expected time to be non nil") - } - if cfg.Value == nil { - t.Error("expected time to be non nil") - } - if cfg.GetHashFn == nil { - t.Error("expected time to be non nil") - } - if cfg.BlockNumber == nil { - t.Error("expected block number to be non nil") - } -} - -func TestEVM(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Fatalf("crashed with: %v", r) - } - }() - - Execute([]byte{ - byte(vm.DIFFICULTY), - byte(vm.TIMESTAMP), - byte(vm.GASLIMIT), - byte(vm.PUSH1), - byte(vm.ORIGIN), - byte(vm.BLOCKHASH), - byte(vm.COINBASE), - }, nil, nil) -} - -func TestExecute(t *testing.T) { - ret, _, err := Execute([]byte{ - byte(vm.PUSH1), 10, - byte(vm.PUSH1), 0, - byte(vm.MSTORE), - byte(vm.PUSH1), 32, - byte(vm.PUSH1), 0, - byte(vm.RETURN), - }, nil, nil) - if err != nil { - t.Fatal("didn't expect error", err) - } - - num := new(big.Int).SetBytes(ret) - if num.Cmp(big.NewInt(10)) != 0 { - t.Error("Expected 10, got", num) - } -} - -func TestCall(t *testing.T) { - state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - address := common.HexToAddress("0x0a") - state.SetCode(address, []byte{ - byte(vm.PUSH1), 10, - byte(vm.PUSH1), 0, - byte(vm.MSTORE), - byte(vm.PUSH1), 32, - byte(vm.PUSH1), 0, - byte(vm.RETURN), - }) - - ret, _, err := Call(address, nil, &Config{State: state}) - if err != nil { - t.Fatal("didn't expect error", err) - } - - num := new(big.Int).SetBytes(ret) - if num.Cmp(big.NewInt(10)) != 0 { - t.Error("Expected 10, got", num) - } -} - -func BenchmarkCall(b *testing.B) { - var definition = `[{"constant":true,"inputs":[],"name":"seller","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"abort","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"refund","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"buyer","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmReceived","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"name":"","type":"uint8"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmPurchase","outputs":[],"type":"function"},{"inputs":[],"type":"constructor"},{"anonymous":false,"inputs":[],"name":"Aborted","type":"event"},{"anonymous":false,"inputs":[],"name":"PurchaseConfirmed","type":"event"},{"anonymous":false,"inputs":[],"name":"ItemReceived","type":"event"},{"anonymous":false,"inputs":[],"name":"Refunded","type":"event"}]` - - var code = common.Hex2Bytes("6060604052361561006c5760e060020a600035046308551a53811461007457806335a063b4146100865780633fa4f245146100a6578063590e1ae3146100af5780637150d8ae146100cf57806373fac6f0146100e1578063c19d93fb146100fe578063d696069714610112575b610131610002565b610133600154600160a060020a031681565b610131600154600160a060020a0390811633919091161461015057610002565b61014660005481565b610131600154600160a060020a039081163391909116146102d557610002565b610133600254600160a060020a031681565b610131600254600160a060020a0333811691161461023757610002565b61014660025460ff60a060020a9091041681565b61013160025460009060ff60a060020a9091041681146101cc57610002565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60025460009060a060020a900460ff16811461016b57610002565b600154600160a060020a03908116908290301631606082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf9250a150565b80546002023414806101dd57610002565b6002805460a060020a60ff021973ffffffffffffffffffffffffffffffffffffffff1990911633171660a060020a1790557fd5d55c8a68912e9a110618df8d5e2e83b8d83211c57a8ddd1203df92885dc881826060a15050565b60025460019060a060020a900460ff16811461025257610002565b60025460008054600160a060020a0390921691606082818181858883f150508354604051600160a060020a0391821694503090911631915082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517fe89152acd703c9d8c7d28829d443260b411454d45394e7995815140c8cbcbcf79250a150565b60025460019060a060020a900460ff1681146102f057610002565b6002805460008054600160a060020a0390921692909102606082818181858883f150508354604051600160a060020a0391821694503090911631915082818181858883f150506002805460a060020a60ff02191660a160020a179055506040517f8616bbbbad963e4e65b1366f1d75dfb63f9e9704bbbf91fb01bec70849906cf79250a15056") - - abi, err := abi.JSON(strings.NewReader(definition)) - if err != nil { - b.Fatal(err) - } - - cpurchase, err := abi.Pack("confirmPurchase") - if err != nil { - b.Fatal(err) - } - creceived, err := abi.Pack("confirmReceived") - if err != nil { - b.Fatal(err) - } - refund, err := abi.Pack("refund") - if err != nil { - b.Fatal(err) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - for j := 0; j < 400; j++ { - Execute(code, cpurchase, nil) - Execute(code, creceived, nil) - Execute(code, refund, nil) - } - } -} -func benchmarkEVM_Create(bench *testing.B, code string) { - var ( - statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - sender = common.BytesToAddress([]byte("sender")) - receiver = common.BytesToAddress([]byte("receiver")) - ) - - statedb.CreateAccount(sender) - statedb.SetCode(receiver, common.FromHex(code)) - runtimeConfig := Config{ - Origin: sender, - State: statedb, - GasLimit: 10000000, - Difficulty: big.NewInt(0x200000), - Time: 0, - Coinbase: common.Address{}, - BlockNumber: new(big.Int).SetUint64(1), - ChainConfig: ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: new(big.Int), - ByzantiumBlock: new(big.Int), - ConstantinopleBlock: new(big.Int), - DAOForkBlock: new(big.Int), - DAOForkSupport: false, - EIP150Block: new(big.Int), - EIP155Block: new(big.Int), - EIP158Block: new(big.Int), - }, - EVMConfig: vm.Config{}, - } - // Warm up the intpools and stuff - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - Call(receiver, []byte{}, &runtimeConfig) - } - bench.StopTimer() -} - -func BenchmarkEVM_CREATE_500(bench *testing.B) { - // initcode size 500K, repeatedly calls CREATE and then modifies the mem contents - benchmarkEVM_Create(bench, "5b6207a120600080f0600152600056") -} -func BenchmarkEVM_CREATE2_500(bench *testing.B) { - // initcode size 500K, repeatedly calls CREATE2 and then modifies the mem contents - benchmarkEVM_Create(bench, "5b586207a120600080f5600152600056") -} -func BenchmarkEVM_CREATE_1200(bench *testing.B) { - // initcode size 1200K, repeatedly calls CREATE and then modifies the mem contents - benchmarkEVM_Create(bench, "5b62124f80600080f0600152600056") -} -func BenchmarkEVM_CREATE2_1200(bench *testing.B) { - // initcode size 1200K, repeatedly calls CREATE2 and then modifies the mem contents - benchmarkEVM_Create(bench, "5b5862124f80600080f5600152600056") -} - -func fakeHeader(n uint64, parentHash common.Hash) *types.Header { - header := types.Header{ - Coinbase: common.HexToAddress("0x00000000000000000000000000000000deadbeef"), - Number: big.NewInt(int64(n)), - ParentHash: parentHash, - Time: 1000, - Nonce: types.BlockNonce{0x1}, - Extra: []byte{}, - Difficulty: big.NewInt(0), - GasLimit: 100000, - } - return &header -} - -type dummyChain struct { - counter int -} - -// Engine retrieves the chain's consensus engine. -func (d *dummyChain) Engine() consensus.Engine { - return nil -} - -// GetHeader returns the hash corresponding to their hash. -func (d *dummyChain) GetHeader(h common.Hash, n uint64) *types.Header { - d.counter++ - parentHash := common.Hash{} - s := common.LeftPadBytes(big.NewInt(int64(n-1)).Bytes(), 32) - copy(parentHash[:], s) - - //parentHash := common.Hash{byte(n - 1)} - //fmt.Printf("GetHeader(%x, %d) => header with parent %x\n", h, n, parentHash) - return fakeHeader(n, parentHash) -} - -// TestBlockhash tests the blockhash operation. It's a bit special, since it internally -// requires access to a chain reader. -func TestBlockhash(t *testing.T) { - // Current head - n := uint64(1000) - parentHash := common.Hash{} - s := common.LeftPadBytes(big.NewInt(int64(n-1)).Bytes(), 32) - copy(parentHash[:], s) - header := fakeHeader(n, parentHash) - - // This is the contract we're using. It requests the blockhash for current num (should be all zeroes), - // then iteratively fetches all blockhashes back to n-260. - // It returns - // 1. the first (should be zero) - // 2. the second (should be the parent hash) - // 3. the last non-zero hash - // By making the chain reader return hashes which correlate to the number, we can - // verify that it obtained the right hashes where it should - - /* - - pragma solidity ^0.5.3; - contract Hasher{ - - function test() public view returns (bytes32, bytes32, bytes32){ - uint256 x = block.number; - bytes32 first; - bytes32 last; - bytes32 zero; - zero = blockhash(x); // Should be zeroes - first = blockhash(x-1); - for(uint256 i = 2 ; i < 260; i++){ - bytes32 hash = blockhash(x - i); - if (uint256(hash) != 0){ - last = hash; - } - } - return (zero, first, last); - } - } - - */ - // The contract above - data := common.Hex2Bytes("6080604052348015600f57600080fd5b50600436106045576000357c010000000000000000000000000000000000000000000000000000000090048063f8a8fd6d14604a575b600080fd5b60506074565b60405180848152602001838152602001828152602001935050505060405180910390f35b600080600080439050600080600083409050600184034092506000600290505b61010481101560c35760008186034090506000816001900414151560b6578093505b5080806001019150506094565b508083839650965096505050505090919256fea165627a7a72305820462d71b510c1725ff35946c20b415b0d50b468ea157c8c77dff9466c9cb85f560029") - // The method call to 'test()' - input := common.Hex2Bytes("f8a8fd6d") - chain := &dummyChain{} - ret, _, err := Execute(data, input, &Config{ - GetHashFn: core.GetHashFn(header, chain), - BlockNumber: new(big.Int).Set(header.Number), - }) - if err != nil { - t.Fatalf("expected no error, got %v", err) - } - if len(ret) != 96 { - t.Fatalf("expected returndata to be 96 bytes, got %d", len(ret)) - } - - zero := new(big.Int).SetBytes(ret[0:32]) - first := new(big.Int).SetBytes(ret[32:64]) - last := new(big.Int).SetBytes(ret[64:96]) - if zero.BitLen() != 0 { - t.Fatalf("expected zeroes, got %x", ret[0:32]) - } - if first.Uint64() != 999 { - t.Fatalf("second block should be 999, got %d (%x)", first, ret[32:64]) - } - if last.Uint64() != 744 { - t.Fatalf("last block should be 744, got %d (%x)", last, ret[64:96]) - } - if exp, got := 255, chain.counter; exp != got { - t.Errorf("suboptimal; too much chain iteration, expected %d, got %d", exp, got) - } -} - -// benchmarkNonModifyingCode benchmarks code, but if the code modifies the -// state, this should not be used, since it does not reset the state between runs. -func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) { - cfg := new(Config) - setDefaults(cfg) - cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - cfg.GasLimit = gas - if len(tracerCode) > 0 { - tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil) - if err != nil { - b.Fatal(err) - } - cfg.EVMConfig = vm.Config{ - Tracer: tracer, - } - } - var ( - destination = common.BytesToAddress([]byte("contract")) - vmenv = NewEnv(cfg) - sender = vm.AccountRef(cfg.Origin) - ) - cfg.State.CreateAccount(destination) - eoa := common.HexToAddress("E0") - { - cfg.State.CreateAccount(eoa) - cfg.State.SetNonce(eoa, 100) - } - reverting := common.HexToAddress("EE") - { - cfg.State.CreateAccount(reverting) - cfg.State.SetCode(reverting, []byte{ - byte(vm.PUSH1), 0x00, - byte(vm.PUSH1), 0x00, - byte(vm.REVERT), - }) - } - - //cfg.State.CreateAccount(cfg.Origin) - // set the receiver's (the executing contract) code for execution. - cfg.State.SetCode(destination, code) - vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value)) - - b.Run(name, func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value)) - } - }) -} - -// BenchmarkSimpleLoop test a pretty simple loop which loops until OOG -// 55 ms -func BenchmarkSimpleLoop(b *testing.B) { - staticCallIdentity := []byte{ - byte(vm.JUMPDEST), // [ count ] - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.PUSH1), 0x4, // address of identity - byte(vm.GAS), // gas - byte(vm.STATICCALL), - byte(vm.POP), // pop return value - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - callIdentity := []byte{ - byte(vm.JUMPDEST), // [ count ] - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.DUP1), // value - byte(vm.PUSH1), 0x4, // address of identity - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), // pop return value - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - callInexistant := []byte{ - byte(vm.JUMPDEST), // [ count ] - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.DUP1), // value - byte(vm.PUSH1), 0xff, // address of existing contract - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), // pop return value - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - callEOA := []byte{ - byte(vm.JUMPDEST), // [ count ] - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.DUP1), // value - byte(vm.PUSH1), 0xE0, // address of EOA - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), // pop return value - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - loopingCode := []byte{ - byte(vm.JUMPDEST), // [ count ] - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.DUP1), // out insize - byte(vm.DUP1), // in offset - byte(vm.PUSH1), 0x4, // address of identity - byte(vm.GAS), // gas - - byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP), byte(vm.POP), - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - callRevertingContractWithInput := []byte{ - byte(vm.JUMPDEST), // - // push args for the call - byte(vm.PUSH1), 0, // out size - byte(vm.DUP1), // out offset - byte(vm.PUSH1), 0x20, // in size - byte(vm.PUSH1), 0x00, // in offset - byte(vm.PUSH1), 0x00, // value - byte(vm.PUSH1), 0xEE, // address of reverting contract - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), // pop return value - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - //tracer := logger.NewJSONLogger(nil, os.Stdout) - //Execute(loopingCode, nil, &Config{ - // EVMConfig: vm.Config{ - // Debug: true, - // Tracer: tracer, - // }}) - // 100M gas - benchmarkNonModifyingCode(100000000, staticCallIdentity, "staticcall-identity-100M", "", b) - benchmarkNonModifyingCode(100000000, callIdentity, "call-identity-100M", "", b) - benchmarkNonModifyingCode(100000000, loopingCode, "loop-100M", "", b) - benchmarkNonModifyingCode(100000000, callInexistant, "call-nonexist-100M", "", b) - benchmarkNonModifyingCode(100000000, callEOA, "call-EOA-100M", "", b) - benchmarkNonModifyingCode(100000000, callRevertingContractWithInput, "call-reverting-100M", "", b) - - //benchmarkNonModifyingCode(10000000, staticCallIdentity, "staticcall-identity-10M", b) - //benchmarkNonModifyingCode(10000000, loopingCode, "loop-10M", b) -} - -// TestEip2929Cases contains various testcases that are used for -// EIP-2929 about gas repricings -func TestEip2929Cases(t *testing.T) { - t.Skip("Test only useful for generating documentation") - id := 1 - prettyPrint := func(comment string, code []byte) { - instrs := make([]string, 0) - it := asm.NewInstructionIterator(code) - for it.Next() { - if it.Arg() != nil && 0 < len(it.Arg()) { - instrs = append(instrs, fmt.Sprintf("%v %#x", it.Op(), it.Arg())) - } else { - instrs = append(instrs, fmt.Sprintf("%v", it.Op())) - } - } - ops := strings.Join(instrs, ", ") - fmt.Printf("### Case %d\n\n", id) - id++ - fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\nOperations: \n```\n%v\n```\n\n", - comment, - code, ops) - Execute(code, nil, &Config{ - EVMConfig: vm.Config{ - Tracer: logger.NewMarkdownLogger(nil, os.Stdout), - ExtraEips: []int{2929}, - }, - }) - } - - { // First eip testcase - code := []byte{ - // Three checks against a precompile - byte(vm.PUSH1), 1, byte(vm.EXTCODEHASH), byte(vm.POP), - byte(vm.PUSH1), 2, byte(vm.EXTCODESIZE), byte(vm.POP), - byte(vm.PUSH1), 3, byte(vm.BALANCE), byte(vm.POP), - // Three checks against a non-precompile - byte(vm.PUSH1), 0xf1, byte(vm.EXTCODEHASH), byte(vm.POP), - byte(vm.PUSH1), 0xf2, byte(vm.EXTCODESIZE), byte(vm.POP), - byte(vm.PUSH1), 0xf3, byte(vm.BALANCE), byte(vm.POP), - // Same three checks (should be cheaper) - byte(vm.PUSH1), 0xf2, byte(vm.EXTCODEHASH), byte(vm.POP), - byte(vm.PUSH1), 0xf3, byte(vm.EXTCODESIZE), byte(vm.POP), - byte(vm.PUSH1), 0xf1, byte(vm.BALANCE), byte(vm.POP), - // Check the origin, and the 'this' - byte(vm.ORIGIN), byte(vm.BALANCE), byte(vm.POP), - byte(vm.ADDRESS), byte(vm.BALANCE), byte(vm.POP), - - byte(vm.STOP), - } - prettyPrint("This checks `EXT`(codehash,codesize,balance) of precompiles, which should be `100`, "+ - "and later checks the same operations twice against some non-precompiles. "+ - "Those are cheaper second time they are accessed. Lastly, it checks the `BALANCE` of `origin` and `this`.", code) - } - - { // EXTCODECOPY - code := []byte{ - // extcodecopy( 0xff,0,0,0,0) - byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, //length, codeoffset, memoffset - byte(vm.PUSH1), 0xff, byte(vm.EXTCODECOPY), - // extcodecopy( 0xff,0,0,0,0) - byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, //length, codeoffset, memoffset - byte(vm.PUSH1), 0xff, byte(vm.EXTCODECOPY), - // extcodecopy( this,0,0,0,0) - byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, //length, codeoffset, memoffset - byte(vm.ADDRESS), byte(vm.EXTCODECOPY), - - byte(vm.STOP), - } - prettyPrint("This checks `extcodecopy( 0xff,0,0,0,0)` twice, (should be expensive first time), "+ - "and then does `extcodecopy( this,0,0,0,0)`.", code) - } - - { // SLOAD + SSTORE - code := []byte{ - - // Add slot `0x1` to access list - byte(vm.PUSH1), 0x01, byte(vm.SLOAD), byte(vm.POP), // SLOAD( 0x1) (add to access list) - // Write to `0x1` which is already in access list - byte(vm.PUSH1), 0x11, byte(vm.PUSH1), 0x01, byte(vm.SSTORE), // SSTORE( loc: 0x01, val: 0x11) - // Write to `0x2` which is not in access list - byte(vm.PUSH1), 0x11, byte(vm.PUSH1), 0x02, byte(vm.SSTORE), // SSTORE( loc: 0x02, val: 0x11) - // Write again to `0x2` - byte(vm.PUSH1), 0x11, byte(vm.PUSH1), 0x02, byte(vm.SSTORE), // SSTORE( loc: 0x02, val: 0x11) - // Read slot in access list (0x2) - byte(vm.PUSH1), 0x02, byte(vm.SLOAD), // SLOAD( 0x2) - // Read slot in access list (0x1) - byte(vm.PUSH1), 0x01, byte(vm.SLOAD), // SLOAD( 0x1) - } - prettyPrint("This checks `sload( 0x1)` followed by `sstore(loc: 0x01, val:0x11)`, then 'naked' sstore:"+ - "`sstore(loc: 0x02, val:0x11)` twice, and `sload(0x2)`, `sload(0x1)`. ", code) - } - { // Call variants - code := []byte{ - // identity precompile - byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0x04, byte(vm.PUSH1), 0x0, byte(vm.CALL), byte(vm.POP), - - // random account - call 1 - byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.PUSH1), 0x0, byte(vm.CALL), byte(vm.POP), - - // random account - call 2 - byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.PUSH1), 0x0, byte(vm.STATICCALL), byte(vm.POP), - } - prettyPrint("This calls the `identity`-precompile (cheap), then calls an account (expensive) and `staticcall`s the same"+ - "account (cheap)", code) - } -} - -// TestColdAccountAccessCost test that the cold account access cost is reported -// correctly -// see: https://github.com/ethereum/go-ethereum/issues/22649 -func TestColdAccountAccessCost(t *testing.T) { - for i, tc := range []struct { - code []byte - step int - want uint64 - }{ - { // EXTCODEHASH(0xff) - code: []byte{byte(vm.PUSH1), 0xFF, byte(vm.EXTCODEHASH), byte(vm.POP)}, - step: 1, - want: 2600, - }, - { // BALANCE(0xff) - code: []byte{byte(vm.PUSH1), 0xFF, byte(vm.BALANCE), byte(vm.POP)}, - step: 1, - want: 2600, - }, - { // CALL(0xff) - code: []byte{ - byte(vm.PUSH1), 0x0, - byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.CALL), byte(vm.POP), - }, - step: 7, - want: 2855, - }, - { // CALLCODE(0xff) - code: []byte{ - byte(vm.PUSH1), 0x0, - byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.CALLCODE), byte(vm.POP), - }, - step: 7, - want: 2855, - }, - { // DELEGATECALL(0xff) - code: []byte{ - byte(vm.PUSH1), 0x0, - byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.DELEGATECALL), byte(vm.POP), - }, - step: 6, - want: 2855, - }, - { // STATICCALL(0xff) - code: []byte{ - byte(vm.PUSH1), 0x0, - byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), - byte(vm.PUSH1), 0xff, byte(vm.DUP1), byte(vm.STATICCALL), byte(vm.POP), - }, - step: 6, - want: 2855, - }, - { // SELFDESTRUCT(0xff) - code: []byte{ - byte(vm.PUSH1), 0xff, byte(vm.SELFDESTRUCT), - }, - step: 1, - want: 7600, - }, - } { - tracer := logger.NewStructLogger(nil) - Execute(tc.code, nil, &Config{ - EVMConfig: vm.Config{ - Tracer: tracer, - }, - }) - have := tracer.StructLogs()[tc.step].GasCost - if want := tc.want; have != want { - for ii, op := range tracer.StructLogs() { - t.Logf("%d: %v %d", ii, op.OpName(), op.GasCost) - } - t.Fatalf("testcase %d, gas report wrong, step %d, have %d want %d", i, tc.step, have, want) - } - } -} - -func TestRuntimeJSTracer(t *testing.T) { - jsTracers := []string{ - `{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0, - step: function() { this.steps++}, - fault: function() {}, - result: function() { - return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",") - }, - enter: function(frame) { - this.enters++; - this.enterGas = frame.getGas(); - }, - exit: function(res) { - this.exits++; - this.gasUsed = res.getGasUsed(); - }}`, - `{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, steps:0, - fault: function() {}, - result: function() { - return [this.enters, this.exits,this.enterGas,this.gasUsed, this.steps].join(",") - }, - enter: function(frame) { - this.enters++; - this.enterGas = frame.getGas(); - }, - exit: function(res) { - this.exits++; - this.gasUsed = res.getGasUsed(); - }}`} - tests := []struct { - code []byte - // One result per tracer - results []string - }{ - { - // CREATE - code: []byte{ - // Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes) - byte(vm.PUSH5), - // Init code: PUSH1 0, PUSH1 0, RETURN (3 steps) - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN), - byte(vm.PUSH1), 0, - byte(vm.MSTORE), - // length, offset, value - byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0, - byte(vm.CREATE), - byte(vm.POP), - }, - results: []string{`"1,1,952855,6,12"`, `"1,1,952855,6,0"`}, - }, - { - // CREATE2 - code: []byte{ - // Store initcode in memory at 0x00 (5 bytes left-padded to 32 bytes) - byte(vm.PUSH5), - // Init code: PUSH1 0, PUSH1 0, RETURN (3 steps) - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN), - byte(vm.PUSH1), 0, - byte(vm.MSTORE), - // salt, length, offset, value - byte(vm.PUSH1), 1, byte(vm.PUSH1), 5, byte(vm.PUSH1), 27, byte(vm.PUSH1), 0, - byte(vm.CREATE2), - byte(vm.POP), - }, - results: []string{`"1,1,952846,6,13"`, `"1,1,952846,6,0"`}, - }, - { - // CALL - code: []byte{ - // outsize, outoffset, insize, inoffset - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0, // value - byte(vm.PUSH1), 0xbb, //address - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), - }, - results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`}, - }, - { - // CALLCODE - code: []byte{ - // outsize, outoffset, insize, inoffset - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0, // value - byte(vm.PUSH1), 0xcc, //address - byte(vm.GAS), // gas - byte(vm.CALLCODE), - byte(vm.POP), - }, - results: []string{`"1,1,981796,6,13"`, `"1,1,981796,6,0"`}, - }, - { - // STATICCALL - code: []byte{ - // outsize, outoffset, insize, inoffset - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0xdd, //address - byte(vm.GAS), // gas - byte(vm.STATICCALL), - byte(vm.POP), - }, - results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`}, - }, - { - // DELEGATECALL - code: []byte{ - // outsize, outoffset, insize, inoffset - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0xee, //address - byte(vm.GAS), // gas - byte(vm.DELEGATECALL), - byte(vm.POP), - }, - results: []string{`"1,1,981799,6,12"`, `"1,1,981799,6,0"`}, - }, - { - // CALL self-destructing contract - code: []byte{ - // outsize, outoffset, insize, inoffset - byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0, // value - byte(vm.PUSH1), 0xff, //address - byte(vm.GAS), // gas - byte(vm.CALL), - byte(vm.POP), - }, - results: []string{`"2,2,0,5003,12"`, `"2,2,0,5003,0"`}, - }, - } - calleeCode := []byte{ - byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0, - byte(vm.RETURN), - } - depressedCode := []byte{ - byte(vm.PUSH1), 0xaa, - byte(vm.SELFDESTRUCT), - } - main := common.HexToAddress("0xaa") - for i, jsTracer := range jsTracers { - for j, tc := range tests { - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - statedb.SetCode(main, tc.code) - statedb.SetCode(common.HexToAddress("0xbb"), calleeCode) - statedb.SetCode(common.HexToAddress("0xcc"), calleeCode) - statedb.SetCode(common.HexToAddress("0xdd"), calleeCode) - statedb.SetCode(common.HexToAddress("0xee"), calleeCode) - statedb.SetCode(common.HexToAddress("0xff"), depressedCode) - - tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil) - if err != nil { - t.Fatal(err) - } - _, _, err = Call(main, nil, &Config{ - GasLimit: 1000000, - State: statedb, - EVMConfig: vm.Config{ - Tracer: tracer, - }}) - if err != nil { - t.Fatal("didn't expect error", err) - } - res, err := tracer.GetResult() - if err != nil { - t.Fatal(err) - } - if have, want := string(res), tc.results[i]; have != want { - t.Errorf("wrong result for tracer %d testcase %d, have \n%v\nwant\n%v\n", i, j, have, want) - } - } - } -} - -func TestJSTracerCreateTx(t *testing.T) { - jsTracer := ` - {enters: 0, exits: 0, - step: function() {}, - fault: function() {}, - result: function() { return [this.enters, this.exits].join(",") }, - enter: function(frame) { this.enters++ }, - exit: function(res) { this.exits++ }}` - code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)} - - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil) - if err != nil { - t.Fatal(err) - } - _, _, _, err = Create(code, &Config{ - State: statedb, - EVMConfig: vm.Config{ - Tracer: tracer, - }}) - if err != nil { - t.Fatal(err) - } - - res, err := tracer.GetResult() - if err != nil { - t.Fatal(err) - } - if have, want := string(res), `"0,0"`; have != want { - t.Errorf("wrong result for tracer, have \n%v\nwant\n%v\n", have, want) - } -} - -func BenchmarkTracerStepVsCallFrame(b *testing.B) { - // Simply pushes and pops some values in a loop - code := []byte{ - byte(vm.JUMPDEST), - byte(vm.PUSH1), 0, - byte(vm.PUSH1), 0, - byte(vm.POP), - byte(vm.POP), - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - - stepTracer := ` - { - step: function() {}, - fault: function() {}, - result: function() {}, - }` - callFrameTracer := ` - { - enter: function() {}, - exit: function() {}, - fault: function() {}, - result: function() {}, - }` - - benchmarkNonModifyingCode(10000000, code, "tracer-step-10M", stepTracer, b) - benchmarkNonModifyingCode(10000000, code, "tracer-call-frame-10M", callFrameTracer, b) -} diff --git a/builder/core/vm/stack.go b/builder/core/vm/stack.go deleted file mode 100644 index e1a957e24..000000000 --- a/builder/core/vm/stack.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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 vm - -import ( - "sync" - - "github.com/holiman/uint256" -) - -var stackPool = sync.Pool{ - New: func() interface{} { - return &Stack{data: make([]uint256.Int, 0, 16)} - }, -} - -// Stack is an object for basic stack operations. Items popped to the stack are -// expected to be changed and modified. stack does not take care of adding newly -// initialised objects. -type Stack struct { - data []uint256.Int -} - -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 -} - -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] -} diff --git a/builder/core/vm/stack_table.go b/builder/core/vm/stack_table.go deleted file mode 100644 index 10c12901a..000000000 --- a/builder/core/vm/stack_table.go +++ /dev/null @@ -1,42 +0,0 @@ -// 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 vm - -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/builder/core/vm/testdata/precompiles/blake2F.json b/builder/core/vm/testdata/precompiles/blake2F.json deleted file mode 100644 index a25f9ae50..000000000 --- a/builder/core/vm/testdata/precompiles/blake2F.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "Input": "0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "Expected": "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b", - "Name": "vector 4", - "Gas": 0, - "NoBenchmark": false - }, - { - "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "Expected": "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", - "Name": "vector 5", - "Gas": 12, - "NoBenchmark": false - }, - { - "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000", - "Expected": "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735", - "Name": "vector 6", - "Gas": 12, - "NoBenchmark": false - }, - { - "Input": "0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "Expected": "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421", - "Name": "vector 7", - "Gas": 1, - "NoBenchmark": false - }, - { - "Input": "007A120048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "Expected": "6d2ce9e534d50e18ff866ae92d70cceba79bbcd14c63819fe48752c8aca87a4bb7dcc230d22a4047f0486cfcfb50a17b24b2899eb8fca370f22240adb5170189", - "Name": "vector 8", - "Gas": 8000000, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsG1Add.json b/builder/core/vm/testdata/precompiles/blsG1Add.json deleted file mode 100644 index 184d765aa..000000000 --- a/builder/core/vm/testdata/precompiles/blsG1Add.json +++ /dev/null @@ -1,730 +0,0 @@ -[ - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28", - "Name": "bls_g1add_(g1+g1=2*g1)", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d280000000000000000000000000000000009ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e522400000000000000000000000000000000032b80d3a6f5b09f8a84623389c5f80ca69a0cddabc3097f9d9c27310fd43be6e745256c634af45ca3473b0590ae30d1", - "Expected": "0000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e2", - "Name": "bls_g1add_(2*g1+3*g1=5*g1)", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "Name": "bls_g1add_(inf+g1=g1)", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g1add_(inf+inf=inf)", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee000000000000000000000000000000000001101098f5c39893765766af4512a0c74e1bb89bc7e6fdf14e3e7337d257cc0f94658179d83320b99f31ff94cd2bac0000000000000000000000000000000003e1a9f9f44ca2cdab4f43a1a3ee3470fdf90b2fc228eb3b709fcd72f014838ac82a6d797aeefed9a0804b22ed1ce8f7", - "Expected": "000000000000000000000000000000001466e1373ae4a7e7ba885c5f0c3ccfa48cdb50661646ac6b779952f466ac9fc92730dcaed9be831cd1f8c4fefffd5209000000000000000000000000000000000c1fb750d2285d4ca0378e1e8cdbf6044151867c34a711b73ae818aee6dbe9e886f53d7928cc6ed9c851e0422f609b11", - "Name": "matter_g1_add_0", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed2000000000000000000000000000000000441e7f7f96198e4c23bd5eb16f1a7f045dbc8c53219ab2bcea91d3a027e2dfe659feac64905f8b9add7e4bfc91bec2b0000000000000000000000000000000005fc51bb1b40c87cd4292d4b66f8ca5ce4ef9abd2b69d4464b4879064203bda7c9fc3f896a3844ebc713f7bb20951d95", - "Expected": "0000000000000000000000000000000016b8ab56b45a9294466809b8e858c1ad15ad0d52cfcb62f8f5753dc94cee1de6efaaebce10701e3ec2ecaa9551024ea600000000000000000000000000000000124571eec37c0b1361023188d66ec17c1ec230d31b515e0e81e599ec19e40c8a7c8cdea9735bc3d8b4e37ca7e5dd71f6", - "Name": "matter_g1_add_1", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f00000000000000000000000000000000114c3f11ba0b47551fa28f09f148936d6b290dc9f2d0534a83c32b0b849ab921ce6bcaa4ff3c917707798d9c74f2084f00000000000000000000000000000000149dc028207fb04a7795d94ea65e21f9952e445000eb954531ee519efde6901675d3d2446614d243efb77a9cfe0ca3ae", - "Expected": "0000000000000000000000000000000002ce7a08719448494857102da464bc65a47c95c77819af325055a23ac50b626df4732daf63feb9a663d71b7c9b8f2c510000000000000000000000000000000016117e87e9b55bd4bd5763d69d5240d30745e014b9aef87c498f9a9e3286ec4d5927df7cd5a2e54ac4179e78645acf27", - "Name": "matter_g1_add_2", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e4000000000000000000000000000000000c3d564ac1fe12f18f528c3750583ab6af8973bff3eded7bb4778c32805d9b17846cc7c687af0f46bc87de7748ab72980000000000000000000000000000000002f164c131cbd5afc85692c246157d38dc4bbb2959d2edfa6daf0a8b17c7a898aad53b400e8bdc2b29bf6688ee863db7", - "Expected": "0000000000000000000000000000000015510826f50b88fa369caf062ecdf8b03a67e660a35b219b44437a5583b5a9adf76991dce7bff9afc50257f847299504000000000000000000000000000000000a83e879895a1b47dbd6cd25ce8b719e7490cfe021614f7539e841fc2f9c09f071e386676de60b6579aa4bf6d37b13dd", - "Name": "matter_g1_add_3", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d30000000000000000000000000000000019fe3a64361fea14936ff0b3e630471494d0c0b9423e6a004184a2965221c18849b5ed0eb2708a587323d8d6c6735a90000000000000000000000000000000000340823d314703e5efeb0a65c23069199d7dfff8793aaacb98cdcd6177fc8e61ab3294c57bf13b4406266715752ef3e6", - "Expected": "00000000000000000000000000000000010b1c96d3910f56b0bf54da5ae8c7ab674a07f8143b61fed660e7309e626dc73eaa2b11886cdb82e2b6735e7802cc860000000000000000000000000000000002dabbbedd72872c2c012e7e893d2f3df1834c43873315488d814ddd6bfcca6758a18aa6bd02a0f3aed962cb51f0a222", - "Name": "matter_g1_add_4", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90000000000000000000000000000000001461565b03a86df363d1854b4af74879115dffabeddfa879e2c8db9aa414fb291a076c3bdf0beee82d9c094ea8dc381a000000000000000000000000000000000e19d51ab619ee2daf25ea5bfa51eb217eabcfe0b5cb0358fd2fa105fd7cb0f5203816b990df6fda4e0e8d541be9bcf6", - "Expected": "000000000000000000000000000000000cb40d0bf86a627d3973f1e7846484ffd0bc4943b42a54ff9527c285fed3c056b947a9b6115824cabafe13cd1af8181c00000000000000000000000000000000076255fc12f1a9dbd232025815238baaa6a3977fd87594e8d1606caec0d37b916e1e43ee2d2953d75a40a7ba416df237", - "Name": "matter_g1_add_5", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1b0000000000000000000000000000000019cabba3e09ad34cc3d125e0eb41b527aa48a4562c2b7637467b2dbc71c373897d50eed1bc75b2bde8904ece5626d6e400000000000000000000000000000000056b0746f820cff527358c86479dc924a10b9f7cae24cd495625a4159c8b71a8c3ad1a15ebf22d3561cd4b74e8a6e48b", - "Expected": "000000000000000000000000000000000e115e0b61c1f1b25cc10a7b3bd21cf696b1433a0c366c2e1bca3c26b09482c6eced8c8ecfa69ce6b9b3b4419779262e00000000000000000000000000000000077b85daf61b9f947e81633e3bc64e697bc6c1d873f2c21e5c4c3a11302d4d5ef4c3ff5519564729aaf2a50a3c9f1196", - "Name": "matter_g1_add_6", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442a0000000000000000000000000000000011f649ee35ff8114060fc5e4df9ac828293f6212a9857ca31cb3e9ce49aa1212154a9808f1e763bc989b6d5ba7cf09390000000000000000000000000000000019af81eca7452f58c1a6e99fab50dc0d5eeebc7712153e717a14a31cffdfd0a923dbd585e652704a174905605a2e8b9d", - "Expected": "000000000000000000000000000000000013e37a8950a659265b285c6fb56930fb77759d9d40298acac2714b97b83ec7692a7d1c4ccb83f074384db9eedd809c0000000000000000000000000000000003215d524d6419214568ba42a31502f2a58a97d0139c66908e9d71755f5a7666567aafe30ea84d89308f06768f28a648", - "Name": "matter_g1_add_7", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795000000000000000000000000000000000d713e148769fac2efd380886f8566c6d4662dd38317bb7e68744c4339efaedbab88435ce3dc289afaa7ecb37df37a5300000000000000000000000000000000129d9cd031b31c77a4e68093dcdbb585feba786207aa115d9cf120fe4f19ca31a0dca9c692bd0f53721d60a55c333129", - "Expected": "00000000000000000000000000000000029405b9615e14bdac8b5666bbc5f3843d4bca17c97bed66d164f1b58d2a148f0f506d645d665a40e60d53fe29375ed400000000000000000000000000000000162761f1712814e474beb2289cc50519253d680699b530c2a6477f727ccc75a19681b82e490f441f91a3c611eeb0e9e2", - "Name": "matter_g1_add_8", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a1900000000000000000000000000000000006d92bcb599edca426ff4ceeb154ebf133c2dea210c7db0441f74bd37c8d239149c8b5056ace0bfefb1db04b42664f530000000000000000000000000000000008522fc155eef6d5746283808091f91b427f2a96ac248850f9e3d7aadd14848101c965663fd4a63aea1153d71918435a", - "Expected": "000000000000000000000000000000000cfaa8df9437c0b6f344a0c8dcbc7529a07aec0d7632ace89af6796b6b960b014f78dd10e987a993fb8a95cc909822ec0000000000000000000000000000000007475f115f6eb35f78ba9a2b71a44ccb6bbc1e980b8cd369c5c469565f3fb798bc907353cf47f524ba715deaedf379cb", - "Name": "matter_g1_add_9", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac9430000000000000000000000000000000016380d03b7c5cc3301ffcb2cf7c28c9bde54fc22ba2b36ec293739d8eb674678c8e6461e34c1704747817c8f8341499a000000000000000000000000000000000ec6667aa5c6a769a64c180d277a341926376c39376480dc69fcad9a8d3b540238eb39d05aaa8e3ca15fc2c3ab696047", - "Expected": "0000000000000000000000000000000011541d798b4b5069e2541fa5410dad03fd02784332e72658c7b0fa96c586142a967addc11a7a82bfcee33bd5d07066b900000000000000000000000000000000195b3fcb94ab7beb908208283b4e5d19c0af90fca4c76268f3c703859dea7d038aca976927f48839ebc7310869c724aa", - "Name": "matter_g1_add_10", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e00000000000000000000000000000000065eb0770ab40199658bf87db6c6b52cd8c6c843a3e40dd60433d4d79971ff31296c9e00a5d553df7c81ade533379f4b0000000000000000000000000000000017a6f6137ddd90c15cf5e415f040260e15287d8d2254c6bfee88938caec9e5a048ff34f10607d1345ba1f09f30441ef4", - "Expected": "0000000000000000000000000000000006b0853b3d41fc2d7b27da0bb2d6eb76be32530b59f8f537d227a6eb78364c7c0760447494a8bba69ef4b256dbef750200000000000000000000000000000000166e55ba2d20d94da474d4a085c14245147705e252e2a76ae696c7e37d75cde6a77fea738cef045182d5e628924dc0bb", - "Name": "matter_g1_add_11", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276b0000000000000000000000000000000006a3f7eb0e42567210cc1ba5e6f8c42d02f1eef325b6483fef49ba186f59ab69ca2284715b736086d2a0a1f0ea224b40000000000000000000000000000000000bc08427fda31a6cfbe657a8c71c73894a33700e93e411d42f1471160c403b939b535070b68d60a4dc50e47493da63dc", - "Expected": "000000000000000000000000000000000c35d4cd5d43e9cf52c15d46fef521666a1e1ab9f0b4a77b8e78882e9fab40f3f988597f202c5bd176c011a56a1887d4000000000000000000000000000000000ae2b5c24928a00c02daddf03fade45344f250dcf4c12eda06c39645b4d56147cb239d95b06fd719d4dc20fe332a6fce", - "Name": "matter_g1_add_12", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a578768100000000000000000000000000000000068e79aea45b7199ec4b6f26e01e88ec76533743639ce76df66937fff9e7de3edf6700d227f10f43e073afcc63e2eddc00000000000000000000000000000000039c0b6d9e9681401aeb57a94cedc0709a0eff423ace9253eb00ae75e21cabeb626b52ef4368e6a4592aed9689c6fca4", - "Expected": "0000000000000000000000000000000013bad27dafa20f03863454c30bd5ae6b202c9c7310875da302d4693fc1c2b78cca502b1ff851b183c4b2564c5d3eb4dc0000000000000000000000000000000000552b322b3d672704382b5d8b214c225b4f7868f9c5ae0766b7cdb181f97ed90a4892235915ffbc0daf3e14ec98a606", - "Name": "matter_g1_add_13", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f7680000000000000000000000000000000000adac9bb98bb6f35a8f941dbff39dfd307b6a4d5756ccae103c814564e3d3993a8866ff91581ccdd7686c1dce0b19f700000000000000000000000000000000083d235e0579032ca47f65b6ae007ce8ffd2f1a890ce3bc45ebd0df6673ad530d2f42125d543cb0c51ba0c28345729d8", - "Expected": "000000000000000000000000000000000b5513e42f5217490f395a8cb3673a4fc35142575f770af75ecf7a4fcd97eee215c4298fc4feab51915137cbdb814839000000000000000000000000000000000e9d4db04b233b0b12a7ff620faefef906aeb2b15481ce1609dad50eb6a7d0c09a850375599c501296219fb7b288e305", - "Name": "matter_g1_add_14", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931d000000000000000000000000000000000d5bb4fa8b494c0adf4b695477d4a05f0ce48f7f971ef53952f685e9fb69dc8db1603e4a58292ddab7129bb5911d6cea0000000000000000000000000000000004a568c556641f0e0a2f44124b77ba70e4e560d7e030f1a21eff41eeec0d3c437b43488c535cdabf19a70acc777bacca", - "Expected": "000000000000000000000000000000000c27ef4ebf37fd629370508f4cd062b74faa355b305d2ee60c7f4d67dd741363f18a7bbd368cdb17e848f372a5e33a6f0000000000000000000000000000000000ed833df28988944115502f554636e0b436cccf845341e21191e82d5b662482f32c24df492da4c605a0f9e0f8b00604", - "Name": "matter_g1_add_15", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d500000000000000000000000000000000091ee883cb9ea2c933f6645f0f4c535a826d95b6da6847b4fe2349342bd4bd496e0dd546df7a7a17a4b9fb8349e5064f000000000000000000000000000000000902d7e72242a5e6b068ca82d0cb71dc0f51335dbd302941045319f9a06777518b56a6e0b0b0c9fd8f1edf6b114ad331", - "Expected": "00000000000000000000000000000000122cce99f623944dfebffcdf6b0a0a3696162f35053e5952dddc2537421c60da9fe931579d1c4fc2e31082b6c25f96b500000000000000000000000000000000011366ffa91dc0b7da8b7c1839ea84d49299310f5c1ca244012eed0dd363dbcf4ad5813b8e3fb49361ef05ea8cb18ffe", - "Name": "matter_g1_add_16", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debe0000000000000000000000000000000000d3d4f11bc79b8425b77d25698b7e151d360ebb22c3a6afdb227de72fe432dcd6f0276b4fd3f1fcc2da5b59865053930000000000000000000000000000000015ac432071dc23148765f198ed7ea2234662745a96032c215cd9d7cf0ad8dafb8d52f209983fe98aaa2243ecc2073f1b", - "Expected": "000000000000000000000000000000000113ccf11264ff04448f8c58b279a6a49acb386750c2051eab2c90fa8b8e03d7c5b9e87eccf36b4b3f79446b80be7b1d0000000000000000000000000000000004358a1fabfe803f4c787a671196b593981a837ee78587225fb21d5a883b98a15b912862763b94d18b971cb7e37dbcf0", - "Name": "matter_g1_add_17", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb600000000000000000000000000000000034f725766897ed76394145da2f02c92c66794a51fd5ae07bd7cc60c013d7a48ebf1b07faf669dfed74d82d07e48d1150000000000000000000000000000000018f4926a3d0f740988da25379199ecb849250239ad7efcfef7ffaa43bc1373166c0448cc30dcdbd75ceb71f76f883ea7", - "Expected": "00000000000000000000000000000000167336aeeb9e447348156936849d518faee314c291c84d732fa3c1bd3951559230d94230e37a08e28e689e9d1fef05770000000000000000000000000000000005366535f7a68996e066ab80c55bb372a15fb0ed6634585b88fe7cafbf818fbfebbf6f6ddd9ca0ff72137594a1e84b35", - "Name": "matter_g1_add_18", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154b00000000000000000000000000000000079e5a154cf84190b6c735bc8cd968559182166568649b813732e4fb4c5c428c8b38e8265d4ef04990c49aa1381f51c8000000000000000000000000000000000ae08e682ef92b4986a5ac5d4f094ad0919c826a97efe8d8120a96877766eae5828803804a0cae67df9822fd18622aae", - "Expected": "000000000000000000000000000000000a3d66cf87b1ce8c5683d71a6de4bf829d094041240f56d9071aa84ff189a06940e8e1935127e23a970c78ca73c28bf6000000000000000000000000000000000b2adda87740873c0c59e3ebde44d33834773f0fe69e2f5e7ede99c4f928978a5caaede7262e45fd22136a394b3f7858", - "Name": "matter_g1_add_19", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af0000000000000000000000000000000008cefd0fd289d6964a962051c2c2ad98dab178612663548370dd5f007c5264fece368468d3ca8318a381b443c68c4cc7000000000000000000000000000000000708d118d44c1cb5609667fd51df9e58cacce8b65565ef20ad1649a3e1b9453e4fb37af67c95387de008d4c2114e5b95", - "Expected": "0000000000000000000000000000000004b2311897264fe08972d62872d3679225d9880a16f2f3d7dd59412226e5e3f4f2aa8a69d283a2dc5b93e022293f0ee1000000000000000000000000000000000f03e18cef3f9a86e6b842272f2c7ee48d0ad23bfc7f1d5a9a796d88e5d5ac31326db5fe90de8f0690c70ae6e0155039", - "Name": "matter_g1_add_20", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719290000000000000000000000000000000008e5afc16d909eb9d8bdaaf229ad291f34f7baf5247bbd4cc938278f1349adb4b0f0aacd14799c01d0ca2ed38c937d600000000000000000000000000000000006cf972c64e20403c82fee901c90eaa5547460d57cce2565fd091ff9bc55e24584595c9182298f148882d6949c36c9d5", - "Expected": "000000000000000000000000000000000caf46f480ae2ea8e700f7913c505d5150c4629c9137e917357d2a4ba8a7a1c63b8f6e2978293755952fbed7f0ad8d6d0000000000000000000000000000000002e62e715b72eebbc7c366a2390318f73e69203a9533e72340aab568f65105129ffc9889a8bc00a692494d93688c7ec0", - "Name": "matter_g1_add_21", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0000000000000000000000000000000013a6439e0ec0fabe93f6c772e102b96b1f692971d7181c386f7f8a360daca6e5f99772e1a736f1e72a17148d90b08efe0000000000000000000000000000000010f27477f3171dcf74498e940fc324596ef5ec6792be590028c2963385d84ef8c4bbb12c6eb3f06b1afb6809a2cb0358", - "Expected": "000000000000000000000000000000000dea57d1fc19f994e6bdda9478a400b0ada23aed167bfe7a16ef79b6aa020403a04d554303c0b2a9c5a38f85cf6f3800000000000000000000000000000000000b8d76ccd41ba81a835775185bbf1d6bf94b031d94d5c78b3b97beb24cf246b0c25c4c309e2c06ae9896ed800169eeee", - "Name": "matter_g1_add_22", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff320000000000000000000000000000000005728a219d128bc0a1f851f228e2bf604a72400c393cfb0d3484456b6b28a2c5061198656f0e106bbe257d849be159040000000000000000000000000000000011f6d08baa91fb2c8b36191d5b2318e355f8964cc8112838394ba1ded84b075de58d90452601dcfc9aa8a275cfec695d", - "Expected": "0000000000000000000000000000000012e6d6c518c15cfd3020181ff3f829e29140b3b507b99251cc7f31795128adec817750296bce413bac18b9a80f69ca5000000000000000000000000000000000131ee9b748f6f1eb790adeb9edd0e79d89a9908368f5a6bb82ee0c913061cdfffe75d9ba411a49aa3f9194ee6d4d08a9", - "Name": "matter_g1_add_23", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f200000000000000000000000000000000171696781ba195f330241584e42fb112adf9b8437b54ad17d410892b45c7d334e8734e25862604d1b679097590b8ab0a000000000000000000000000000000001879328fdf0d1fb79afd920e0b0a386828be5b8e0e6024dfeea800ffcb5c65f9044061af26d639d4dcc27bcb5ba1481a", - "Expected": "00000000000000000000000000000000111c416d5bd018a77f3317e3fbf4b03d8e19658f2b810dc9c17863310dfb09e1c4ffdbb7c98951d357f1c3d93c5d0745000000000000000000000000000000000af0a252bff336d5eb3a406778557ef67d91776a9c788be9a76cff7727f519a70fc7809f1a50a58d29185cb9722624fd", - "Name": "matter_g1_add_24", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c2000000000000000000000000000000000231b0d6189a4faad082ce4a69398c1734fcf35d222b7bce22b14571033a1066b049ae3cd3bd6c8cec5bec743955cdd600000000000000000000000000000000037375237fb71536564ea693ab316ae11722aadd7cab12b17b926c8a31bd13c4565619e8c894bffb960e632896856bbe", - "Expected": "000000000000000000000000000000000d2b9c677417f4e9b38af6393718f55a27dbd23c730796c50472bc476ebf52172559b10f6ceb81e644ec2d0a41b3bb01000000000000000000000000000000001697f241ff6eceb05d9ada4be7d7078ecbbffa64dd4fb43ead0692eef270cb7cc31513ee4bf38a1b1154fe008a8b836a", - "Name": "matter_g1_add_25", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd10000000000000000000000000000000015653d1c5184736cdc78838be953390d12b307d268b394136b917b0462d5e31b8f1b9d96cce8f7a1203c2cae93db6a4000000000000000000000000000000000060efeece033ac711d500c1156e4b6dce3243156170c94bc948fd7beae7b28a31463a44872ca22ca49dc5d4d4dd27d1c", - "Expected": "0000000000000000000000000000000003996050756117eeab27a5e4fa9acdde2a1161d6fbfff2601a1c7329f900e93a29f55a8073f85be8f7c2a4d0323e95cc00000000000000000000000000000000010b195a132c1cba2f1a6a73f2507baa079e9b5cb8894ea78bebc16d4151ee56fe562b16e2741f3ab1e8640cdad83180", - "Name": "matter_g1_add_26", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc0000000000000000000000000000000018adb42928304cbc310a229306a205e7c21cdb31b9e5daf0ff6bb9437acee80cd8cf02b35dab823155d60f8a83fde5cc0000000000000000000000000000000018b57460c81cab43235be79c8c90dcda40fafcaf69e4e767133aee56308a6df07eac71275597dd8ed6607ffb9151ed9a", - "Expected": "0000000000000000000000000000000003c7a7ee3d1b73cf1f0213404363bf3c0de4425ab97d679ed51448e877b7537400f148f14eba588ed241fea34e56d465000000000000000000000000000000000c581b5070e6bb8582b7ee2cd312dfeb5aaf0b0da95cf5a22a505ffba21fc204e26a5e17311d1f47113653ff13349f57", - "Name": "matter_g1_add_27", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da00000000000000000000000000000000001da65df8574a864ab454e5f2fa929405501bb73c3162a600979a1145586079361c89839cc0c5a07f1135c94bf059f9c0000000000000000000000000000000002560df402c0550662a2c4c463ad428ab6e60297fbc42a6484107e397ae016b58494d1c46ac4952027aa8c0896c50be3", - "Expected": "000000000000000000000000000000000d7a539b679e5858271a6f9cf20108410eb5d5d2b1a905e09a8aa20318efbe9175450385d78389f08f836f5634f7a2f0000000000000000000000000000000000fb624e5f6c4c814b7d73eb63b70237c5de7d90d19ac81cac776d86171a8d307d3cc8c56da14f444fe8cf329ab7e63dd", - "Name": "matter_g1_add_28", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e0530000000000000000000000000000000005311c11f4d0bb8542f3b60247c1441656608e5ac5c363f4d62127cecb88800a771767cf23a0e7c45f698ffa5015061f0000000000000000000000000000000018f7f1d23c8b0566a6a1fcb58d3a5c6fd422573840eb04660c3c6ba65762ed1becc756ac6300e9ce4f5bfb962e963419", - "Expected": "0000000000000000000000000000000000849bbc7b0226b18abbcb4c9a9e78dca2f5f75a2cbb983bd95ff3a95b427b1a01fd909ce36384c49eb88ffb8ff77bb000000000000000000000000000000000087d8d28d92305b5313ca533a6b47f454ddce1c2d0fa3574b255128ef0b145fa4158beb07e4f0d50d6b7b90ea8a8ea8a", - "Name": "matter_g1_add_29", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265e000000000000000000000000000000000c8e293f730253128399e5c39ab18c3f040b6cd9df10d794a28d2a428a9256ea1a71cf53022bd1be11f501805e0ddda40000000000000000000000000000000003e60c2291be46900930f710969f79f27e76cf710efefc243236428db2fed93719edeeb64ada0edf6346a0411f2a4cb8", - "Expected": "00000000000000000000000000000000191084201608f706ea1f7c51dd5b593dda87b15d2c594b52829db66ce3beab6b30899d1d285bdb9590335949ceda5f050000000000000000000000000000000000d3460622c7f1d849658a20a7ae7b05e5afae1f01e871cad52ef632cc831b0529a3066f7b81248a7728d231e51fc4ad", - "Name": "matter_g1_add_30", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc80000000000000000000000000000000013267db8fdf8f488a2806fead5cffdcbb7b1b4b7681a2b67d322cd7f5985c65d088c70cdc2638e679ed678cae3cc63c80000000000000000000000000000000007757233ad6d38d488c3d9d8252b41e4ab7ee54e4ef4bbf171402df57c14f9977dd3583c6c8f9b5171b368d61f082447", - "Expected": "000000000000000000000000000000000c06fef6639ab7dceb44dc648ca6a7d614739e40e6486ee9fc01ecc55af580d98abc026c630a95878da7b6d5701d755c0000000000000000000000000000000007c9a7f2bc7fa1f65c9e3a1e463eb4e3283e47bb5490938edb12abf6c8f5a9b56d8ce7a81a60df67db8c399a9a1df1d4", - "Name": "matter_g1_add_31", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17000000000000000000000000000000001975bc52669187f27a86096ae6bf2d60178706105d15bce8fe782759f14e449bc97cb1570e87eec5f12214a9ae0e0170000000000000000000000000000000000ca6106d6e6487a3b6f00fc2af769d21cb3b83b5dc03db19e4824fc28fd9b3d9f7a986e79f05c02b3a914ff26c7a78d6", - "Expected": "0000000000000000000000000000000002fbf4fba68ae416b42a99f3b26916dea464d662cebce55f4545481e5ab92d3c40f3e189504b54db4c9cd51ecdd60e8d0000000000000000000000000000000008e81e094c6d4ded718ef63c5edfacb2d258f48ccfa37562950c607299bb2dca18e680a620dff8c72dedc89b4e9d4759", - "Name": "matter_g1_add_32", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f00000000000000000000000000000000109f6168a719add6ea1a14f9dc95345e325d6b0e56da2f4ecff8408536446894069fa61e81bdaebfc96b13b402fad865000000000000000000000000000000001806aa27c576f4c4fa8a6db49d577cd8f257a8450e89b061cbc7773c0b5434f06bacf12b479abf6847f537c4cbefcb46", - "Expected": "0000000000000000000000000000000014e0bd4397b90a3f96240daf835d5fb05da28a64538f4bf42d9e7925a571f831c6e663910aa37dcc265ddd7938d83045000000000000000000000000000000001695d405d4f8ba385ebf4ad25fb3f34c65977217e90d6e5ed5085b3e5b0b143194f82e6c25766d28ad6c63114ca9dcdf", - "Name": "matter_g1_add_33", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af0000000000000000000000000000000019d3623a7866933e2d73214ceb2e56097a1b047db5943c3ecb846890aa02250126e90fc76a729a952cef895bd154cc7d000000000000000000000000000000000e87c376bbd695a356ef72226ac7ef6a550d99e9693d8485770a686e568ae28c038ee201d3f2ea38362046236ade91cd", - "Expected": "000000000000000000000000000000000ffeab47985bd9b3e10ce27c6636bbda336dcf540cd37eccc3faec2adff2d97dd126633bd83a7d3c8c73c3623bdf0ba2000000000000000000000000000000001992eca4b1e924b360d57ca98b543ab496a8b55bd288d23f03bcc1b22f6bc76d95b12f47c3e305812097253c73b876dd", - "Name": "matter_g1_add_34", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c300000000000000000000000000000000163aaecf83d6c77a5d7417e73f5cf9d71a6aedfd194b2f3b53c608d06a228190f4f79ac57b029d77504c72744df4ecc0000000000000000000000000000000000416e6f9ca188d16daa2c28acd6a594f8fcb990eaa26e60ca2a34dfcad7ad76c425b241acedf674d48d298d0df0f824d", - "Expected": "000000000000000000000000000000001812bcb26fa05e0ab5176e703699ab16f5ef8917a33a9626ae6ff20f2a6f4a9d5e2afe3a11f57061cbaa992e1f30477f000000000000000000000000000000000680acf0b632cb48017cb80baa93753d030aa4b49957178d8a10d1d1a27bbdc89ac6811a91868b2c181c5c0b9b6caf86", - "Name": "matter_g1_add_35", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000000aba7362eee717d03ef2d4f0fef2763822115fcc8fb9e2e8243683b6c1cde799ebc78f23812e557de2cc38e2b4a2e56700000000000000000000000000000000170833db69b3f067cf5c4c4690857e6711c9e3fcad91ca7cd045e9d2f38c7b31236960e8718f5dd4c8bfb4de76c6c9b9", - "Expected": "00000000000000000000000000000000196ffe76a4b726fa8dd720cc1cd04c040724cb18ec10915e312eaa90d124100b08f0ce3a7fc888f46914319a3d7581f4000000000000000000000000000000000e2612357059ca6dbb64efb98ef19370560c9e83e2aad7ab2d9015e2444fe4d8c796b5577584aac9f63258beb5ae863c", - "Name": "matter_g1_add_36", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da8257721808000000000000000000000000000000000a98ae36c690f2e3be8100f43678be5a1064390e210328dd23f61f5a496b87398db2798580edeabc6273fb9537fa12880000000000000000000000000000000009aedf77bb969592c6552ae0121a1c74de78ba222b6cd08623c7a34708a12763b5ff7969cf761ccd25adc1b65da0f02d", - "Expected": "00000000000000000000000000000000072334ec8349fc38b99d6dea0b4259c03cd96c1438c90ef0da6321df2495892de031a53c23838ca2b260774fa09b5461000000000000000000000000000000000e4535767c2477c4f87c087540c836eeffcd0c45960841f9c3561a8a5f8e61ab98b183b11192b8e7ea1c9c7717336243", - "Name": "matter_g1_add_37", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e00000000000000000000000000000000015c3c056ec904ce865d073f8f70ef2d4b5adb5b9238deaa5e167d32f45cad4901aa6d87efa2338c633e7853ce4c19185000000000000000000000000000000000a15f1aa6e662f21d7127351a1655821c943c4cf590e3c9e60c9ab968b4a835f87fb8d87eee6331ee4e194e5f1ea91f4", - "Expected": "000000000000000000000000000000000140fb6dcf872d0a3bff3e32a0cb4a7fb7e60ee4fb476bb120c4ce068e169d72e1c167d7fda321280d5855983d5a9af800000000000000000000000000000000108f54a4ec3ba26dd614f4d94c5c82652583906986158ad40ffea54c17703fa4b0bd7806633e1c0318d06e8dc7d41cde", - "Name": "matter_g1_add_38", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb000000000000000000000000000000000307841cb33e0f188103a83334a828fa864cea09c264d5f4343246f64ab244add4610c9ccd64c001816e5074fe84013f000000000000000000000000000000000e15bbeb6fff7f1435097828f5d64c448bbc800f31a5b7428436dcffd68abc92682f2b01744d7c60540e0cd1b57ab5d4", - "Expected": "000000000000000000000000000000000a1b50660ed9120fff1e5c4abb401e4691a09f41780ca188cea4b1c2d77002f08ce28eb1caa41ee3fe73169e3651bb7f00000000000000000000000000000000125439ac3b45c698a98063ab911364bd3c6dd2a69435d00d6edf89fc5566b33038e960a125e5e52141abb605587942fe", - "Name": "matter_g1_add_39", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000013866438b089d39de5a3ca2a624d72c241a54cbdcf5b2a67ebdd2db8373b112a814e74662bd52e37748ffbfc21782a5000000000000000000000000000000000d55454a22d5c2ef82611ef9cb6533e2f08668577764afc5bb9b7dfe32abd5d333147774fb1001dd24889775de57d305", - "Expected": "000000000000000000000000000000000037b4e8846b423335711ac12f91e2419de772216509d6b9deb9c27fd1c1ee5851b3e032bf3bcac3dd8e93f3dce8a91b00000000000000000000000000000000113a1bf4be1103e858c3be282effafd5e2384f4d1073350f7073b0a415ecf9e7a3bfb55c951c0b2c25c6bab35454ecf0", - "Name": "matter_g1_add_40", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f180320000000000000000000000000000000017440fd557df23286da15f9a96bb88cfbc79589b1c157af13baf02c65227dc0a5bdec6f2f300083ff91dae395ed8cb75000000000000000000000000000000000ad09b4290842cc599d346110fdb39ededbb1d651568579564e274465f07b8f77eeaf00fece0c10db69c2125de8ab394", - "Expected": "0000000000000000000000000000000007c158b4e21566742f7e4e39a672bd383e27864505acef4ef8c26f8b0a9db418f9c088b555b8e9eb25acf9859b1207b40000000000000000000000000000000016e06a1ace89f992d582af0de7662ef91c0a98f574306f6f6d0d8d5e80166638d2deef70105cce2e9b20faa9d6315510", - "Name": "matter_g1_add_41", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0000000000000000000000000000000000d7ccc3a4efdfe1a92a88e453933b8216016091f1b9d575faf18a5b3abf90daf077813167a3f4acce7359472dee544bb00000000000000000000000000000000128008c075ab176100e755cbb8de5b9ff0e9a78114f862d26ed030d9c1d1dea1c21ec8ae4d82a84d3ff5ae4c1cd6f339", - "Expected": "000000000000000000000000000000000b84f9de79c748e37797c629cb78b86b4b736b199f161b30147b5dacf6eabe0b54afce40d5dacfe9a8ee8da5ef5b49de0000000000000000000000000000000010277ad094bb9a3b96379b1366dd90125b51a21ebeb4f776a81d9d9c1f37ab58c32a884a26fa32c83783ed0eef42b820", - "Name": "matter_g1_add_42", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e00000000000000000000000000000000008da4a93d5ffcdaa0adc736a59f0c187ae3bf11ecb5e9e6f6aedea976a47757739042200b4c4593c2dd5db555425531000000000000000000000000000000000a6fdb2d4160c6c35223daa6fa10d0b1073de07fe4f2eba28e65ed049ff8d8852ed0538b30759fe7a0d944009ddf9a6f", - "Expected": "000000000000000000000000000000000d740bd1effd8674250618af0358ad0b83bbc787f0264af9c2ada72fa5431be909e82155da1de0211f46fb307e9949f0000000000000000000000000000000000ddf62c91d587a14b64feef07da52c081b40fbbf9a0f2eae8b66022e0850fc94de6a467e7e4f580c7f2c806f6c6ed8cf", - "Name": "matter_g1_add_43", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d790000000000000000000000000000000003258d7931a1d72ab6344c7e96c0dbd435a7909fe68cc679c08ca9b62f7a6a04863082cbcfdbe9a736625d895e4f3bdb0000000000000000000000000000000009ee3e470e2b2cebc955ba3444b7e478f887138e36c13bd68490689122627269ea5e7ce22dd9c69792394a24187103d6", - "Expected": "000000000000000000000000000000000af674691f5d87655f0066188fac5013f31b4169a0181d3feb7ac3beae0d9a3429d4125f099ee344f644a2de8b941f9f00000000000000000000000000000000042a9603b8e4a6c37d59ede3a1398f5f80c5298da66de575a204ee28811d9f7c7c0dd40cef3769bd72a2156b9eb620c8", - "Name": "matter_g1_add_44", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820000000000000000000000000000000001833807f1ced52399305419450355499a63411837ee61ad681559d59561db18511eb1e8ad3161e7fe30016b560d18b8f00000000000000000000000000000000198b11b31586e17964a4a4ccdee85703163d2106481833e71f26327a589bafb43578d08d87f6cb19c7a04b4ca92392bf", - "Expected": "000000000000000000000000000000001081c3359a0fadfe7850ce878182859e3dd77028772da7bcac9f6451ac6455739c22627889673db626bbea70aa3648d50000000000000000000000000000000000f4e8766f976fa49a0b05ef3f06f56d92fe6452ff05c3fac455f9c16efadf1b81a44d2921bed73511dda81d6fc7478e", - "Name": "matter_g1_add_45", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000007dc719ae9e3f1e11d3ed4747a546a7b973ccb1967adb1b3066645a8bde9632bcfa3530e768f088ddbc022b169e67cbf000000000000000000000000000000000bbf9cf884b19c84045da1cead7dcd9fdbf39d764ff1ad60d83ed1e4fd0ce0554f0fb618203952cf02a7c4ba466c66b8", - "Expected": "000000000000000000000000000000000f60d66fd1ed5eb04f9619d6458c522cc49f5ace111aff2b61903b112559972f80ac615591463abf2b944c4f99d4c03e000000000000000000000000000000000001a1abfa869be2cda6bd7e05454a8735e1b638db7e1b3715708539c2d14ade53069c7e68b36d3b08cff80837028b7d", - "Name": "matter_g1_add_46", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd0000000000000000000000000000000014b78c66c4acecdd913ba73cc4ab573c64b404a9494d29d4a2ba02393d9b8fdaba47bb7e76d32586df3a00e03ae2896700000000000000000000000000000000025c371cd8b72592a45dc521336a891202c5f96954812b1095ba2ea6bb11aad7b6941a44d68fe9b44e4e5fd06bd541d4", - "Expected": "0000000000000000000000000000000015b164c854a2277658f5d08e04887d896a082c6c20895c8809ed4b349da8492d6fa0333ace6059a1f0d37e92ae9bad30000000000000000000000000000000001510d176ddba09ab60bb452188c2705ef154f449bed26abf0255897673a625637b5761355b17676748f67844a61d4e9f", - "Name": "matter_g1_add_47", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe900000000000000000000000000000000104ee0990ba4194916f670f44e254200971b67a18ed45b25c17be49df66e4f9b934bac8c1552ecc25bdaa3af55952076000000000000000000000000000000000591094d9d89afe025ca1832d7f3e60444f83e72403a434b42216b6c4213980d29e4ef0c64ae497006de550c1faa9425", - "Expected": "0000000000000000000000000000000006db0cc24ffec8aa11aecc43e9b76a418daac51d51f3de437090c1bcaabace19f7f8b5ceb6277d6b32b7f3b239a90c4700000000000000000000000000000000069e01f60ca7468c6b9a247c79d18cf3d88bf5d1d62c76abf9237408edeba05dea744205ac5b501920f519bb847bb711", - "Name": "matter_g1_add_48", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a0000000000000000000000000000000004840d028d0c0f056aeb37b7a8505325081e9822ef26046f2da72f2155c20987dd51f4b5577c5395e24288b71d2ce5140000000000000000000000000000000015f231a233e997633c1d6492e0df358fb658ae29d0f53928c8a0578484c899a699178ca3223772210063aa08991c3fff", - "Expected": "000000000000000000000000000000000fa72bf2d7d564cc4982b9f2cdca743d2ac14f0f1be4218dbafb8b93a9277e55273487a5d2857fd3f731ac4ee469a6a1000000000000000000000000000000000fce44f886453c6ca5ebde9af41d2be92d1126e9897d72978a179dd7eebeed6242b6e9718604ab0c9369529a0426a575", - "Name": "matter_g1_add_49", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece1738220000000000000000000000000000000004877b97faa1d05d61ab65001110bf190d442cabcd6d4d1b9c1f0e513309aebd278f84a80354dfdef875769d00ec2c7500000000000000000000000000000000187066cccb5008bc2ffd0bcd1b227a5a0fe0cd4984316ba3cfd5113c4632a04c56cbda8d48993bd0dd50e9b7ce2b7ee9", - "Expected": "0000000000000000000000000000000019ecd38afacc6b281b2515270157328e18039d51574bae0f7e0ef16c3f6da89f55ddee9e3bbb450ad51fe11edfd9f18d00000000000000000000000000000000088a5e292761bbf7a914a9f723de099035e91bd3c1fe9cd50728a4ceaa4fd3953683f30aa8e70ba0eb23919092aa9e22", - "Name": "matter_g1_add_50", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000001881f5aba0603b0a256e03e5dc507598dd63682ce80a29e0fa141b2afdadf6168e98221e4ee45d378cee0416baaadc49000000000000000000000000000000000070d255101319dd3a0f8ca3a0856188428c09de15475d6b70d70a405e45ab379a5b1f2e55f84bd7fe5dd12aeedce670", - "Expected": "0000000000000000000000000000000011ccd455d5e3eba94567a17bcd777559b4ff1afa66fd6f05f99c69937404290a2f1c83cfd6c2c25886ebff4934332c0e0000000000000000000000000000000010920aa3d5974df25530610ef466adce3d51fd6a508d4b1111739c586dfd7ba9040836e075fd812fe111d92f25b67f51", - "Name": "matter_g1_add_51", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf000000000000000000000000000000000b53e5339f25bcd31afd091362874b5042c0b762ed7425341331630addbc4dccc299936e1acdf89823c36867d46c6f28000000000000000000000000000000000fc3c6b522268511dd52826dd1aee707413d925ee51aeb0e5d69c0e3eb697fabbc14783b5007e240cc0c53c299a40ada", - "Expected": "00000000000000000000000000000000060773b9b8f3babdba3db27089b7be3e6e287a635dbae19576039d34ae18a0e6413278bfa280570f6329ae05cdb693fd00000000000000000000000000000000075fb9527f99a8c8db41e67baaf1deafffd2c134badb1b3478a26b5501b31dca858fad6f0d52f412d5631ecfa72eece4", - "Name": "matter_g1_add_52", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000001693f4ebab3fed548784264196fb01cf55311399f47cdad74a9543bda5d1ca682a00ee04bb0b3954d5a0f00ceef97a750000000000000000000000000000000017f4019c23bd68e84d889857c417b17aa96c780fec3c1ed6ca75100cc70c97a8bb8272ad4c6de896d76dc2a1b09c7a61", - "Expected": "000000000000000000000000000000000a3ea8afdc83794f18f9a9427bcd60a355196925d38fdf74ab09d4a08279647b2da6f1fbe30948a785497d6c6dddc2a9000000000000000000000000000000001263c88f1ca3e574cafac21641432d45ee01e1b05eba95716565922abe28c7f0fb004c255afcbfa10cf7959bbe6b00d7", - "Name": "matter_g1_add_53", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000005d5602e05499a435effff3812744b582b0cd7c68f1c88faa3c268515c8b14f3c041b8ae322fe526b2406e7c25d84e61000000000000000000000000000000001038eaf49e74e19111e4456ebba01dc4d22c7e23a303d5dec821da832e90a1b07b1a6b8034137f1bfdcddeb58053a170", - "Expected": "0000000000000000000000000000000019258ea5023ce73343dcd201ec9be68ec1ee1cb4e5b9964309d801c2bc523343c8ebc4f8393a403c7881e5928f29db14000000000000000000000000000000001423bf52daefb432162ce2bd9ef78b256ff3b24d0a84766b87119489fd56ecf6156b2884c8a7e1220e493469723cd7f8", - "Name": "matter_g1_add_54", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000002626f28d421d9d1c28f5e1eb5a51ada9610dbdd62cd33c4078d2fdfc18dbd092e2847cf705ba5fcd8c1a60c1cc34a3b0000000000000000000000000000000001f7b8cfdb7e406c920f5fdecae45fb4be736f209480ccb455f972c6b1a1aebdd5ba116903c46ded72ce37cd8836e871", - "Expected": "00000000000000000000000000000000081d674f5b9c7c64673c39fe33f4f3d77271e826dcb4dfd2591062e47c931237e8539ef9c886c9e112eccc50da4f63fd00000000000000000000000000000000141b700695839110ed4ced5f8a3f4fd64a8086805358ab4a5abd2705592e616cd95ff01271212ca9014dcb68d8157ba0", - "Name": "matter_g1_add_55", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df91000000000000000000000000000000000259e307eacb1bc45a13811b02a7aeaaf4dc2bb405dcd88069bb6ec1c08a78905516169bd3440a36921764df0ef3a85b000000000000000000000000000000001263372b675124f6cc19ca16842ba069c5697dbf57730875fe72c864a81189d7d16fe126b5d24953a0524f96dbac5183", - "Expected": "000000000000000000000000000000001908aa3a640817e31a4213156fbd4fd39ab39eb931091670a0e06399def71a689e67286f90d38ce9f97cb85f6488d9c8000000000000000000000000000000000764e46b6b82aa2f8862d28e9d543a751a9de855645377b9633cc098c2110ec6ed4fd30f0044ea5868c93f950f6cfd24", - "Name": "matter_g1_add_56", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000a138203c916cb8425663db3bbff37f239a5745be885784b8e035a4f40c47954c48873f6d5aa06d579e213282fe789fa0000000000000000000000000000000016897b8adbc3a3a0dccd809f7311ba1f84f76e218c58af243c0aa29a1bb150ed719191d1ced802d4372e717c1c97570a", - "Expected": "0000000000000000000000000000000004ad79769fd10081ebaaed9e2131de5d8738d9ef143b6d0fa6e106bd82cfd53bbc9fab08c422aa03d03896a0fb2460d0000000000000000000000000000000000bb79356c2d477dfbcb1b0e417df7cb79affbe151c1f03fa60b1372d7d82fd53b2160afdd88be1bf0e9dc99596366055", - "Name": "matter_g1_add_57", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29460000000000000000000000000000000019f60f2cf585bdbc36947f760a15fa16c54cf46435cc5707def410202a3f4fa61b577ab2481e058b0345982d3e3d1666000000000000000000000000000000000a70b7bbc55e1f3e11e9eb7efd79d4e396742de48d911ddff8dd0a7cf10422423d5e68021948e1448e92c2e07c194776", - "Expected": "000000000000000000000000000000000a87e7e115ccdf3c2c1a2716491d449c3f8329e73d264088f4af444d43cf05f8be0410da273ce7eeb32969830195b7e70000000000000000000000000000000010a973d6e4bd85105bf311eb0dcfdc0a5d38dba1c099206b60f2e2df4791fd58846bf19d83769506e1561212920b4895", - "Name": "matter_g1_add_58", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000109bd6e0636a7f96ffe2ce8e109171efaacfcd60189c7050259ddedd15dd257e11f2585bbd84e4a3f4d8fc5fbc0289cf0000000000000000000000000000000019b420d778da53aed81b48f2c9b9eb399e771edd5e124a41577452b409ca2503e2798cd25d791f489352fc7b7268ae23", - "Expected": "00000000000000000000000000000000162bd29f2de10002c1c446bd9583e89751fb91703ad564e7951d41673e28d214729aa9b4b9875c397989df197c912d5f0000000000000000000000000000000004d393181871c93714afab6c33c16f68ec391fbfcad606ac65cc1d070949c099e21f710e2fe0dd4e4f50f99ea2167a7e", - "Name": "matter_g1_add_59", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000012bb529b45ad7875784b62a7281d025002f15e7f86cc33555e7472df60da2cb15d37c8bf628142818c0711ee9047fb4d000000000000000000000000000000000baa801623312d95e2b51ce86373fea516007e468f265d974c2327c1779830db180bed6dbe8a64f0959aad26eaafb8d9", - "Expected": "0000000000000000000000000000000010c4b328d264893099d89ba81b0765d0642bf36b0ac043be090c7b4f7987d21a906228c3c208c4ec5123d577efb0771f0000000000000000000000000000000016d08ce3bf755da7d4bae5f4b06b37845c17a717329c547e941be93325a04e9a5095d3f6e6c6f9ec3b1a740f59d88919", - "Name": "matter_g1_add_60", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000002c9e50f37ff0db2676637be8a6275fce7948ae700df1e9e6a0861a8af942b6032cca2c3be8b8d95d4b4b36171b4b0d400000000000000000000000000000000050f1a9b2416bbda35bac9c8fdd4a91c12e7ee8e035973f79bd35e418fd88fa603761e2b36736c13f1d7a582984bd15e", - "Expected": "000000000000000000000000000000000f798f8d5c21cbce7e9cfcbb708c3800bf5c22773ec5b44590cdbb6f720ccddf05a9f5d5e6a51f704f7c295c291df29f000000000000000000000000000000001483903fde5a968dba6924dfac3933cd39f757e2f89120f4ca9d03aaaf9e18252bdb5c5d3939471666b8a42aeb31b4ed", - "Name": "matter_g1_add_61", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec000000000000000000000000000000000332cdc97c1611c043dac5fd0014cfeaee4879fee3f1ad36cddf43d76162108e2dc71f181407171da0ceec4165bcd9760000000000000000000000000000000015b96a13732a726bad5860446a8f7e3f40458e865229bd924181aa671d16b2df2171669a3faa3977f0ee27920a2c5270", - "Expected": "0000000000000000000000000000000001c762175f885a8d7cb0be11866bd370c97fb50d4277ab15b5531dacd08da0145e037d82be3a46a4ee4116305b807de6000000000000000000000000000000000bb6c4065723eaf84d432c9fde8ce05f80de7fe3baed26cf9d1662939baac9320da69c7fe956acdd085f725178fe1b97", - "Name": "matter_g1_add_62", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c50000000000000000000000000000000003ebca978ea429eedad3a2c782816929724fc7529fbf78ea5738f2ca049aab56c1773f625df2698433d55db7f5fc8ca2000000000000000000000000000000000d2477f57b21ed471a40566f99b7c2d84ce6b82eaf83a6c87a7c21f3242959c8423d4113b7fd8449277b363303bb17b0", - "Expected": "00000000000000000000000000000000071dc0f985703bd8335093779de651b524c02faca5fc967766abd3f6f59176d2046d7a14d18c0b757b8c9802e44ebcd300000000000000000000000000000000154e5cb66be8979ee276e8e0f240557e3f7dc074c497293af589256652da21d66a6e6b00ca5bfa6f89963fbd5bc6cf48", - "Name": "matter_g1_add_63", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001461afe277bf0e1754c12a8aabbe60262758941281f23496c2eeb714f8c01fd3793faf15139ae173be6c3ff5d534d2bc00000000000000000000000000000000148ad14901be55baa302fa166e5d81cc741d67a98a7052618d77294c12aea56e2d04b7e497662debc714096c433e844e", - "Expected": "0000000000000000000000000000000012c4dd169f55dfb5634bc4866f7cbd110648b5392ace6042b5f64aba3278f24085227521b7834864f00d01ec9998dd6800000000000000000000000000000000102d7a495850195424677853da01d70caeb6c0af5270bcfffbc2d4252c0f3680518cd8d2a0a6dbbbc7b52923a5b26562", - "Name": "matter_g1_add_64", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002218b4498c91e0fe66417fe835e03c2896d858a10338e92a461c9d76bcecd66df209771ae02c7dcace119596018f83c000000000000000000000000000000001990233c0bae1c21ba9b0e18e09b03aeb3680539c2b2ef8c9a95a3e94cf6e7c344730bf7a499d0f9f1b77345926fef2d", - "Expected": "0000000000000000000000000000000010c50bd0f5169ebd65ee1f9cd2341fa18dd5254b33d2f7da0c644327677fe99b5d655dd5bfdb705b50d4df9cfce33d1400000000000000000000000000000000088e47ffbbc80c69ec3c5f2abe644a483f62df3e7c17aa2ff025553d1aaf3c884a44506eff069f4c41d622df84bbafa1", - "Name": "matter_g1_add_65", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7000000000000000000000000000000000160e0f540d64a3cedba9cf1e97b727be716bbfa97fbf980686c86e086833dc7a3028758be237de7be488e1c1c368fe100000000000000000000000000000000108250b265bd78f5e52f14ef11515d80af71e4d201389693a5c3ef202cf9d974628421d73666ead30481547582f7abaf", - "Expected": "00000000000000000000000000000000168af33c85ae6e650375ed29b91218198edd9135683f6a1428211acdcbf16bdf86f0a95575e47ee0969587a10fa9f3c90000000000000000000000000000000012d9f5d692c870b3da951b6d07797c186a8ddc89b9f08a1c0b8f0f119f10ca0b155e8df5424cf48900ad3bf09ce6872a", - "Name": "matter_g1_add_66", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d20000000000000000000000000000000002fa19b32a825608ab46b5c681c16ae23ebefd804bb06079059e3f2c7686fe1a74c9406f8581d29ff78f39221d995bfd000000000000000000000000000000000b41ea8a18c64de43301320eaf52d923a1f1d36812c92c6e8b34420eff031e05a037eed47b9fe701fd6a03eb045f2ca7", - "Expected": "000000000000000000000000000000000b99587f721a490b503a973591b2bb76152919269d80347aeba85d2912b864a3f67b868c34aee834ecc8cd82ac1373db0000000000000000000000000000000007767bb0ca3047eee40b83bf14d444e63d98e9fc6c4121bdf04ea7148bcfaf3819b70dcebd9a941134e5c649da8f8d80", - "Name": "matter_g1_add_67", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000002a540b681a6113a54249c0bbb47faf7c79e8da746260f71fbf83e60f18c17e5d6c8a7474badafee646fe74217a86ca4000000000000000000000000000000000fe2db7736129b35dc4958ffd0de7115359857fb9480b03a751c4fceb9ae1b2b05855398badffc517ae52c67f6394e2a", - "Expected": "000000000000000000000000000000000bc719a8397a035fc3587d32d7ef4b4cfd63d4a5619ab78301d59659208f86df9e247e5d12650acc51a3bca3827063a900000000000000000000000000000000150d5519380a65b1909b0d84da374484675d99b00b254d03e423e634a012b286e3fe074e9b0a7bb24ff52d327249a01b", - "Name": "matter_g1_add_68", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787900000000000000000000000000000000019d917eb431ce0c066f80742fe7b48f5e008cffa55ee5d02a2a585cc7a105a32bbf47bdff44f8a855ade38184a8279e0000000000000000000000000000000012ee762e29d91a4fc70bc7a2fb296a1dcdd05c90368286cca352b3d5fffc76e3b838e14ea005773c461075beddf414d8", - "Expected": "0000000000000000000000000000000008197403ab10f32d873974c937ef4c27fbdb0f505c4df8ac96504705d4851cf951fb0263335e477063884527b21edf160000000000000000000000000000000005396f1affa20ca8530b519a4d5d400969f0c8c8731ecc0944e8086388e89a7ff7c16d9a2a90780972c4762b88a0f0af", - "Name": "matter_g1_add_69", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000d280fe0b8297311751de20adf5e2d9e97f0c1bfe0cd430514cfddbafd5cdcb8c61bd8af4176cc3394f51f2de64b152400000000000000000000000000000000039f511e890187f28c7a0b2bd695ae665e89b0544c325a44b9109da52cc6908d81e1a27163a353ab275d683860c2e007", - "Expected": "0000000000000000000000000000000002baea63055f72646189bdd133153dd83026f95afad5ce2cffbee3f74c8d47d5480094b2b58b0936c78aa33cd9a8f72f0000000000000000000000000000000013e600456a2d76f5a760059e0ba987b881c6bc10d6161f388d7a9d8b2031921054edfec46afbd80b1364d8e8f6a5a7a2", - "Name": "matter_g1_add_70", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000015bad24d12b5d68558e961a17dbc3e1686e1b918e6192ebe6f3f71c925177e61d0162e018ac81126099effa0cadfa185000000000000000000000000000000000de73182569184b3d79dcfa8c27f46ec7a31fe8a3fd73fe26eec37a088461192bdbcf4d4b37b33b6177d6fde015d1631", - "Expected": "000000000000000000000000000000000ced641c930387432d512861eefbf2d6131017154f99a0d3d24da880dfd2aaae91c2d9634053fab8b85fc11a7884d30600000000000000000000000000000000122071c0e87fae5031c850dccc4777c3ec9d8463bbc4ed84364d4261bc9d38f696a4320d53eea926a75ed9fcc9789a07", - "Name": "matter_g1_add_71", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b256730000000000000000000000000000000015cdf7dafedce64aba34e1f18c57b28f297629c07ee96b732029b545cf5ea6afdf926daa6a48d1250c67aa2a8b797d370000000000000000000000000000000004867352f86267dbe8e32806e4ed02f1487e036051068f8e06d02e8dea6d3773b422e065d2db27c89ea69246d0185351", - "Expected": "000000000000000000000000000000000e2c633351d627a075acd1e373bec96ba41b047f0307201f4b7c9978c1a72243d0b18113604cc421b8f66d76ec9b1360000000000000000000000000000000000844e258d602bf9aaa35ce46c4c91c80dd9337053d8ab22c1163a0571fcd1488a2ef57476e2b66dd9c26963b28284d11", - "Name": "matter_g1_add_72", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000077eb801bcde78e9dd73b58d2429a907ea0f5600a8005093d471be373bba23ea70bf828c766ccced6a46db84b440053f00000000000000000000000000000000101af9df2939089d72e42fe2dc3de3e32be8f4526a2263ebd872d0080ed4a152107bb3d2f56176bf72d5ae8bd0c30a3f", - "Expected": "0000000000000000000000000000000010205c6be10a5fc5390b0e5ae47a8a822c8e9a7a96f113d081cde477ec0de7bf0e8385e61780b2335e4297edb35bcc6d000000000000000000000000000000001796af180463ed70cf330791c8201ee3f0fe52993f64819291bda33017285fcc3a515669b3d48a411276c849fa021f6f", - "Name": "matter_g1_add_73", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0000000000000000000000000000000019b09bb7dddd11c5d0e304dac120b920601dd3a3505e478c88850cc701c17eb02aa7bfb20e4017a62fc4fb544d4f9e8f00000000000000000000000000000000048ad536cf89576d4cce83ef065bc16c47f1a28ae27bd71d30d8f2177a9c6f8b2ed0cdf872ead71bc5a1252bccb4a7e0", - "Expected": "000000000000000000000000000000000fb047098a1996a625cd19021f81ea79895e038756878d8772aaee9b6bbb66930e474dcc04579ad58f4877b742a890900000000000000000000000000000000017da74a4caefc55794a36eda7938371f42265cc1f2d87d41883152db82873daeb59642e8e663afddd4f24536a1f52b3f", - "Name": "matter_g1_add_74", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa30000000000000000000000000000000005f84f9afa2a4a80ea1be03770cb26ac94bec65cf9cb3412a07683df41bb267c2b561b744b34779635218527484633e30000000000000000000000000000000013ce1d1764961d1b0dff236c1f64eabec2ce5a8526edf6b0bccb9ea412e5a91880db24510435cf297fcc1b774b318b65", - "Expected": "000000000000000000000000000000000f4ca788dc52b7c8c0cb3419ab62c26db9fb434321fc6830837333c2bb53b9f31138eecccc3c33461297f99a810e24ad0000000000000000000000000000000006785d4f9cdf42264c00fdc4452883b9050eb56e2f6e46c7b8fc8d937dfe4d3ad5072d969a47c4811b36d3887256d0b9", - "Name": "matter_g1_add_75", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000f0dd7a15dfc39dc2df47cf09761498b0b363157d8443356e768567f5a6d5913c2a67f12d93df2dcf50756bb686836b100000000000000000000000000000000055914dbda5b115222e738d94fbd430440c99bcc6d2c6cf7225c77756ffadf765b2d83447d395e876b5f6134563ed914", - "Expected": "000000000000000000000000000000000ac0f0f62202d09cede55ca77b7344b46fd831b41015eb357cac07f0fa49c2564c2e9d5c591630226677446a9100757c000000000000000000000000000000000ca21d0128ef933fc1a48c1b4967f56912513e63a416d86ad40c0a4590b2edf88e4e8a286338b8b176d8b341ea480277", - "Name": "matter_g1_add_76", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb211000000000000000000000000000000000a6ff5f01a97c0f3c89ac0a460861dc9040f00693bfae22d81ea9a46b6c570436f0688ed0deef5cdcc5e2142f195b5c000000000000000000000000000000000193a17880edffe5b2ebedf0dc25e479cac3b136db9b6b24009ea0a9ca526d6dd9714d10d64c999d4334baa081b9f2fbe", - "Expected": "000000000000000000000000000000000b728d4ae4b45fae9a9e242524e95e44f175356726da50f46236f690eec17fdd5edce5df1253383378dc8f9c1fee98ae00000000000000000000000000000000131d28a5eab968c45ddc86b82f220dcdeab7c009c7c61986ee4e55045c024e1bcbe76a4e35000b5699ccec5858ba427e", - "Name": "matter_g1_add_77", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a000000000000000000000000000000000b35fcf625cde78fba1b70904acb97d7eb449d968e8013855d44292e9c3b0df3cfbcace6f292ec3c7717e25490bb4c67000000000000000000000000000000000af57abd87df55034c32dbe68bd1c0b47139fc2c3a8887b7c151e57b57c9002070337c8dcb2ce2687f9f007d48dd68c1", - "Expected": "00000000000000000000000000000000178a19966b5b0fa70c138be7f5ea51d5399c7b8dcc5171cbef82ecb1451aeccbd1ed29170a27f404ebf6daa2ec99bd69000000000000000000000000000000000b1b748494806175030f6b5e2977c58982bd6ec6662d69237f0521351653c772a40035f2504ac8949fb448a901379fd6", - "Name": "matter_g1_add_78", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b00000000000000000000000000000000177a51fcc81580ccb7a8873fa93eaf860ca8fedde13cdf3eb53f11e66a1c1e934b82ee9251f711c5c479f33a22770c47000000000000000000000000000000000a0edc9a58f4bb414aa0aeec7bfa6076fb62bdbaee987192c18855adf4e813e7103b943e1dddc24754acfa90600a5750", - "Expected": "0000000000000000000000000000000019195049a2d457709e284c84c72a211224efc4d7d46d25c9a537eea94149b06506df02a2a4e0a6428263e9605eaaacb500000000000000000000000000000000061139f9a70ce7cd87ed3a701163bde247382295f557b47a3a0a880d2780f015e8ac753eb3243f9ad138f92c3a2257c5", - "Name": "matter_g1_add_79", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d000000000000000000000000000000001552982822e0b64a6204b27da0e192873bb5bd2997784ff0b6ed53801b402501a665c17f0a379fd946ab1adfae43c6af000000000000000000000000000000000938359655fe135dd2a390f83e27273feb68387ba94f2b6f7c15389f8272d64231ebe9c8271de90ff2358d935359ba85", - "Expected": "00000000000000000000000000000000168f958a40e85341d90012e134976d1a5839e807948410cc0c81a50961552c052bb784c50da4c734f6aa583777c22b28000000000000000000000000000000000d26998bac6ec11bc5fcf6fe7262c984d6500cd5b21af979048b940e20054f8d759f8a011f3e09d01d10f9cf8ab150e1", - "Name": "matter_g1_add_80", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d50000000000000000000000000000000000d94885dcc21b0b98821b6861a4d094e9eb5d5adcf7ca4275c5b759abbf9a9910f3b38073183d54a0569ecbbc1e9826400000000000000000000000000000000034a54b4bbb3f128608a866f5f5c554cf6ad7899f6650ca663a5bd5f1a3e4471e35a2440644c0e4e0a56080936b46d12", - "Expected": "000000000000000000000000000000000d4734ab1bbcf9e30cf142a7aa9e8cde1b3c88d92397b8d7d48c7a7402561feee58a810abf67776e1890489efe7f8ec20000000000000000000000000000000005be9e4af0c0c183c43601339f162345f7c013f5941167cd925057e91c4641e19091a20123a36f2e803142833c0bc1ef", - "Name": "matter_g1_add_81", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000014f16cbb17e7f63284d8a75968a4c8fc8ee7f37233ed656d696477c507c23e7c7eaf54001f44c93deb14c298aa6f94c00000000000000000000000000000000169bde83e861889c50b2138c76531a5866235d515a6fee4da7aaf8e8b903f2848a9fe7bbd55eac7f1c58ce3a88e7249d", - "Expected": "000000000000000000000000000000001400f774b2d932c6b990da6e1b3493685e8f51d429e0c53e9af1b4a2d3876781b790bca4a1bc28ce0240ea21be24a2350000000000000000000000000000000004993fcf5723b7e02095d4ba73ff3194bbe36027bc9099b57084c91c7e7d50b76331bfb06d3c678d3e401bc3f7fcc577", - "Name": "matter_g1_add_82", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000009acc4b4678b4b645fde47d1b75a5dda8caf6696ad2bf312dd5c12d7f3ab50b95152f5fe59842650c8a1a785f345c3ab000000000000000000000000000000000b672989004fe54f4d645e40cd29a21418151134fd2b90a68185040ceff141ced7f7ece1fdd9137c32589fa04b105a0e", - "Expected": "000000000000000000000000000000000fcb0ab180a69b0a230d9dba98099fdce4969f82fc7e7ad93352a7c8dd448bb0ba9c7d62f53d5dc80506bc36190d9bc700000000000000000000000000000000047b7306f4a53c21d42993c50f2365486d02dac495f2dee4f8971a4af308396fce6c90f3cfde857bf7a2c6bf5d0d8aa7", - "Name": "matter_g1_add_83", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6000000000000000000000000000000000198e12ade128447a240e03e024183c401d605cab1ed81f0f5bb7bc4c7cc9c889a2a01f59c0e37a0767a927719e5a95d000000000000000000000000000000001946e39fee9b76ce552108b339b9b24d11e43d3275ac19d2d4bc745c409bdc3f7c473a60c4d3a4d2cc3b598ae0d66880", - "Expected": "00000000000000000000000000000000050b45f896fa40099cda8b1f20ab88644915c16f926589cd709e00149b12922347fa7122175424cd44e8875f217b9ad7000000000000000000000000000000001122b7e9b1509efe5616368b14085bdd36fb7adb85cd5a7f23e327548986f5298c045a602b6ee1265d53a4432a4a3c0e", - "Name": "matter_g1_add_84", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac47388620000000000000000000000000000000009c48aa2681b3005b24075bb3a122ac100cbaca872f761f4398edaba9dd9da6d04d4a4925028297dfe5f77c2b0b5c821000000000000000000000000000000000ea95c646fb68aa458e69c267a6ca640a6a24d40bdca0161246e4521d13c46facfc1ac86dfc0a804cfa6665cebeec822", - "Expected": "0000000000000000000000000000000005325a499aec678ada9eb673d366fe0475e885d5188e2fb687a96949e8f782852fba962197976b868ec083c512bfb66b000000000000000000000000000000000c4d6fcacc8d82401882bee355b37930d83e3cea2e4a7bc133e65a3e0af919b25fc3f30c333873da9406845ce42dbb87", - "Name": "matter_g1_add_85", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae80000000000000000000000000000000008e8799a6cc0339e94e861692c81eee53e8a7b326523d5344b416bfbce04290585ef56018834cfd93d234bfa2943369f000000000000000000000000000000000fa1b01aab0878adad693ec769fb68640931c355b3802c51d4a3772300be5b16ceecdc8328a229b3b9f3639170db96f8", - "Expected": "000000000000000000000000000000000685ec14da61c48bcb697966aca9e27601db43f0fb1f32e026fb33738eecfbb7012aa1ca3acf36a21fa846730245add70000000000000000000000000000000003fc52a1c3342b12271bbc178545bb20e96e8f1fde673e51f3d27ab5cb42e60aca49c6077e0f687be59b2d25cda9718e", - "Name": "matter_g1_add_86", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000bb3a76287fb98fe668cb0a5de603c768340ee6b7f9f686a22da3a86926d8734d2c565c41f94f08fa3ef0e665f4ccb520000000000000000000000000000000016c02dbfb307c96d5b9c144672fe62f3e9cd78991844f246945ee484cbdef2a4c1b001a017cafb3acc57b35f7c08dc44", - "Expected": "00000000000000000000000000000000021796fd6ef624eed7049b8a5c50415cc86104b2367f2966eb3a9f5b7c4833b9470ef558457426f87756d526d94d8dfe000000000000000000000000000000000f492dca3f0a89102b503d7a7d5b197946348e195954d23b8ab9ab7704b3bccecaa2123b8386662f95cd4cfdbbb7a64d", - "Name": "matter_g1_add_87", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f00000000000000000000000000000000127420ff97df415e336cf3e24c39c161fad630c45c7ccef80f1831c4f5ed54da12f2c49a161e72bc70285fa0498e46d00000000000000000000000000000000013e605c21014f72364f8bff392ce64a10078ea537237fa282d5dd252ba1677b84b8c15d7925e54a4ab36f1feb13d3064", - "Expected": "000000000000000000000000000000000ae916770455b0a63717e81802f5a7fcfbcc3e260b7adeca02a61a520c338d495eea29c4f070fd6efc1b8d23eb285e4c00000000000000000000000000000000134784e092744df573ba78f7d6f3cf1ed19491a0fc7ddfa02d3ca043bcf102fd40c33ac44b03a947308e3cc7af41c2df", - "Name": "matter_g1_add_88", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab40000000000000000000000000000000016f41e8b098839944adc12481e5f965657a4faedd4f4cdea51a9597a6a0356989e791a686d3d2ee6232ab93683259c6b000000000000000000000000000000000d27b4a56b2cc2216e61eb41061f9a586a704652704906f7fe0eab869ba00d34205ea66f7a02d337d08b916598494e52", - "Expected": "0000000000000000000000000000000012842c9d7f4309f6e40124a071d317f5597de419db0d5a8e5324a517f7b61dfdeea2fb4503ad7cdd8deb8aaa5c412554000000000000000000000000000000000ace4d9f98ee6e8a4416ef14d64f26dc49e102e69eced46ef829a352e58e8c1a7e1f083e3f4fc07f24ccd1685dedf215", - "Name": "matter_g1_add_89", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000019e7c8d182e3b674dfa21539613f7de5d4872d4f4732307a5c6d95ada7e81a01bc25bda34e0b46634e0b0b32cd47e8ec0000000000000000000000000000000008149237de73ab46d5c20dfd85b07f593c0caf2e2e364335450e3ebb478a9f6b9ac0af89174dffd92eda2783a5271f01", - "Expected": "000000000000000000000000000000000875289fdaead079a283aafe4de7035c88662642b6bba389b17583f8e3b5801dada6e46bd897af961997665e6ed4a55700000000000000000000000000000000050a6b9c1db35865df0a042d27a042ff4b8d3bec2fba6a3a28a71c5a574620dc05cda0e70932ce9b8966e4592220c147", - "Name": "matter_g1_add_90", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6000000000000000000000000000000000c0f33f2d76366af661d6fa58a8b5aab207d35ce03899e495f7ddccedf201d9816f270468b207413a2ca70380c798fc60000000000000000000000000000000002a7dc7e2b163e65cadf93b5d682982288c8f36d08b1db8e0b1cb40cd3c7231f3f1672da42b4679f35db2076a8de5b42", - "Expected": "0000000000000000000000000000000019ea92820dcd442358db359146797aa82beff6154946b1ea14dccae05e8252b776b817dc044a20764e3514cd22799c0b000000000000000000000000000000000ed929fef2cb11e8b6b9b5d52bfde82080eda747f0c82f33b9cb87019476f0c128e6b918a4486172dee2884ba538ae5d", - "Name": "matter_g1_add_91", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000118fb45274a6b0ca9fe2654821e3b30caa46444f7c64b1921cf16dfd56a43916947d4fb6968d718a59a30ed38d65ce3000000000000000000000000000000000110e8e73e640bbea6927cd770baaf887c8e0e0c58260bca489c39b6dd7a24ab8c0c0a2495133d8ff8c7afb9790b37faa", - "Expected": "0000000000000000000000000000000009452bd0a167683e30c673ffd4e750c66a81edf309a8d2d6dd915c358b30b0ffc001c4165b1b17bf157a0f966bfd91d00000000000000000000000000000000015df0b1ee359dd3e35a7b2c33edbb8e92b18804ae3359a369c6a529f5561298e6be9a3498c9477f33353124af7e91968", - "Name": "matter_g1_add_92", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000005dcb54cdf9635db275540c16307fc9f07b4ca5cd91e3977e4b95b58e8103e40ed9fa74752b2a43d95b6acb6f5fcbf440000000000000000000000000000000007ef8457752a47864ef2698176a53990e4822421ecf83b2716251e3ce69151ab2767d4a6611a0a6e0e40a57164ffb94e", - "Expected": "0000000000000000000000000000000011f1ac702a06699dd64b63ebdd8b5381578f63b603c63c3a47413fe764af239ab7024712320f3ea3daefa6bd3cd3dfe9000000000000000000000000000000000918bb83a22b4fc66247e007c17155c4c2ec6326131c10fe04a5f9b82ddeca3d21c7c397a70a3949fda4d766540c85ff", - "Name": "matter_g1_add_93", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35850000000000000000000000000000000006d3335e092616363e94436bb68be89667c706564ba687f4a3494fcf7da62fd9ad8ae68cb76524926c261983711a14ad000000000000000000000000000000000f085a3d013592c402a380e2e8d9019864a775e7b8e8b94603c8cc1eb1def1e91075fd5675f76534397e2a7d76c2331e", - "Expected": "000000000000000000000000000000000344951ccb5e60d1838f7793fcf8b765f5f252b69e1cfdb4bd3c20692c8ffa01afbda6950974a65f6ac74afb9da5942e0000000000000000000000000000000014f5f0e6b99a04d1c5c2adf96c53dd41f8c01aab8db4f0e6d7fc5eab27f6c03c429632db4e1c21467c09d8a54066a4d3", - "Name": "matter_g1_add_94", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b0000000000000000000000000000000019e2ed6e9757e2339d013078fac91c966045f7a1416a56135d75e603c2021a8bebf4acbf6c0d5ba911f66510e9a7ad1a0000000000000000000000000000000008b8585444ffb3bd4fb6ee23e8128142aa72fd574a506151a0eea8979cbd694e03897caba63771b0490d46063bc5bb57", - "Expected": "000000000000000000000000000000000a449fb0da911c544887b24860bc5fcaaf054041cc80f16bbb44c796520bee454d0d06f84fd5aa179a44fd4fac9f144a000000000000000000000000000000000fca81401349089caaef9156a86c64271c77235c9efd136dcfad9894450b076cb3dd1a05bfa1e62ef904435eee5d2250", - "Name": "matter_g1_add_95", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65000000000000000000000000000000000f4a256b4288386545957a3ba28278c0ce69a8a412febfed1f952ca13e673822bacb6b7751ea75893b680ea363aab66400000000000000000000000000000000152379d006e74798199f83b0c6c22a98440ef653d7f0a8c5e3026bcdabec8be59a3cc291ba05860bd0639c5c5f5bee26", - "Expected": "000000000000000000000000000000000c427721953e139d4f12ad2a3f8f91a4caa49875a87001b619c8a6e909a7da8ddd9dd026bf56d5f85d49fd17527106a800000000000000000000000000000000018add2816914ef51a289e707ba0224fcf0b7bcfa4001487e90dbdce53f1b596e1f5872de32fcee6f63bce4484ccbef7", - "Name": "matter_g1_add_96", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d220000000000000000000000000000000012dae9aee13ed6ad52fe664bf7d2d0a1f134f0951d0d7ce5184e223bde164f6860967f9aaaa44fa6654d77d026c52d2a000000000000000000000000000000000f71889d64ec2f7da7319994883eb8bd1c753e6cdd3495036b630c35f07118a1bc10568c411ecbdf468a9cdaa9b4811b", - "Expected": "000000000000000000000000000000000275b8efb3a3e43e2a24d0cda238154520f0a2b265f168bfc502b9cd4a07b930756961ae7e4fe3f01a5473d36ce3356200000000000000000000000000000000113403d5a968f01ba127dd8ef6c8d7b783a10d039a6b69c617032eba7122e9297f3ce2360c829ae64fdc9794695bf173", - "Name": "matter_g1_add_97", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe54850000000000000000000000000000000004e9dd69012ab596b5d3f1f8e4593b448685fcec4ab3394008178b137b762ddf9150cbb8dbb74c8af45bd8baab9a6c4f000000000000000000000000000000001132b66a2127885774062732127951f051c9c3c9b5aba02406e3f3cd4ecfe2dbf6614ebaca3bfe9efbe4f6e5b15ba0f5", - "Expected": "000000000000000000000000000000000594c808954bb930bd038806500c9e3fd6460a83554e945baeeec2354a3805f046c76aea62c249080f16ae8e70f8fa6b00000000000000000000000000000000046924a32fb3f2df9a52615e45eeea2fa3ac0e2ccd38458194ada6b4d993ecdc0f441e41d0ea37599254a06aef68b9ae", - "Name": "matter_g1_add_98", - "Gas": 600, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b50000000000000000000000000000000017a81b957a12adf474a2913e8636f169ea9cd10be62c16b88f95f5caf661f158a032a9f7d249fdf2765caa1564bed0570000000000000000000000000000000017fbf2abc62dc2678b65d509e19c9c9c5d961c72565649a078da8dff98be6236ef314e9ff8022f639ff565353345c230", - "Expected": "00000000000000000000000000000000002c8bc5f39b2c9fea01372429e92a9c945fad152da67174f4e478fdead734d50f6e2da867c235f1f2f11bdfee67d2a7000000000000000000000000000000000c1dd27aad9f5d48c4824da3071daedf0c7a0e2a0b0ed39c50c9d25e61334a9c96765e049542ccaa00e0eccb316eec08", - "Name": "matter_g1_add_99", - "Gas": 600, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsG1Mul.json b/builder/core/vm/testdata/precompiles/blsG1Mul.json deleted file mode 100644 index 0e166a29c..000000000 --- a/builder/core/vm/testdata/precompiles/blsG1Mul.json +++ /dev/null @@ -1,730 +0,0 @@ -[ - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g1mul_(0*g1=inf)", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g1mul_(x*inf=inf)", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g1mul_(1*g1=g1)", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000011", - "Expected": "000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436", - "Name": "bls_g1mul_(17*g1)", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992feeb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e", - "Expected": "000000000000000000000000000000000f1f230329be03ac700ba718bc43c8ee59a4b2d1e20c7de95b22df14e7867eae4658ed2f2dfed4f775d4dcedb4235cf00000000000000000000000000000000012924104fdb82fb074cfc868bdd22012694b5bae2c0141851a5d6a97d8bc6f22ecb2f6ddec18cba6483f2e73faa5b942", - "Name": "matter_g1_mul_0", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed24d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d", - "Expected": "00000000000000000000000000000000195592b927f3f1783a0c7b5117702cb09fa4f95bb2d35aa2a70fe89ba84aa4f385bdb2bfd4e1aaffbb0bfa002ac0e51b000000000000000000000000000000000607f070f4ae567633d019a63d0411a07d767bd7b6fe258c3ba1e720279e94c31f23166b806eabdb830bb632b003ca8b", - "Name": "matter_g1_mul_1", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1", - "Expected": "0000000000000000000000000000000014f9bc24d65e3a2d046dbae935781596fb277359ba785808fd9ff7fd135ba8c1ddc27d97a16cc844427afbf4f8fc75a60000000000000000000000000000000017e3a485f84e2f2bdcf3255fe939945abe60dca5e0ae55eae9675dcc8d73e06d00b440a27ab4dc21c37f0bd492d70cf4", - "Name": "matter_g1_mul_2", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e44c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a", - "Expected": "000000000000000000000000000000000827517654873d535010e589eaf22f646cf7626144ca04738286de1f1d345342d5ae0eab9cd37ced9a3db90e569301720000000000000000000000000000000002a474c2443d71b0231d2b2b874a6aeac0452dd75da88e6f27949edafc7d094cb1577a79f4e643db42edcaecc17d66da", - "Name": "matter_g1_mul_3", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d38964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89", - "Expected": "000000000000000000000000000000000d7e5794c88c549970383454d98f9b7cebb7fdf8545256f1a5e42a61aa1d61193f02075dc6314b650da14f3776da6ead0000000000000000000000000000000002054faff236d38d2307aa6cbbc696d50f5b3ffead1be2df97a05ebbcbc9e02eaf153f311a1e141eb95d411c0ec6e981", - "Name": "matter_g1_mul_4", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944", - "Expected": "000000000000000000000000000000000ff16ff83b45eae09d858f8fe443c3f0e0b7418a87ac27bb00f7eea343d20a4a7f5c0fcc56da9b792fe12bd38d0d43c600000000000000000000000000000000042a815a4a5dca00bd1791889491c882a21f0fe0a53809d83740407455cf9c980c5547961f9ebe61871a4896dace7fbd", - "Name": "matter_g1_mul_5", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1baaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1", - "Expected": "0000000000000000000000000000000009e425f5bdc7df5c2a72303918e5a3c7d2fdeeb071179c533f83cdcf38dbbdb1ec5f4ebc85f3ed80757641ee3f8a8637000000000000000000000000000000000819a3e81e9ac2baacdc778225129e16344107517157ab2a7bc5e3480938585c55fd2dd7185f52251f5ab191f162cf5d", - "Name": "matter_g1_mul_6", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442adac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c", - "Expected": "0000000000000000000000000000000015e6bea7ecf15d91bde67231f794397502c087960fab36d905137ce2608172b5a5def065cf7ee567ca7fb08a22adecf80000000000000000000000000000000001eed472d6138fbc56e10edb62563c086fdeb9acf6de957f2367db7f1c80d2c23197c09039ed55e65cb56de9fb9be64d", - "Name": "matter_g1_mul_7", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795bb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108", - "Expected": "000000000000000000000000000000000220a71ad70fcf7e47df60381fbd1aba33c03a3f8537ba2029ad8e99b63c8677e0183f0b5bb2a5e1b23bc56693adb45c0000000000000000000000000000000017f26ac6ffc79ded7c08e08673336402f47ab48ef9ee2e46e3265e5cbb790cfc86f41bd1b578c5891eb052d11197c850", - "Name": "matter_g1_mul_8", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a190fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f8187672", - "Expected": "0000000000000000000000000000000006b27724c4898b4f71be9727b773709a7905997d06a41ee618b7dcf864d7457bb3241046f0139c1d678b6ba6226f090f000000000000000000000000000000000b20cabf58f9c29897e20e91a9b482f5f867bef45ce0941cb8850aaa2022182298a1a24655a4b905f436520cc42a30cd", - "Name": "matter_g1_mul_9", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac943b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea", - "Expected": "0000000000000000000000000000000004745f9877b3a0851df5bb770a54c69d5355cdadddc9d961e2bfdb3d0531d3d0f780f462335289be29ad4c62cb1250a00000000000000000000000000000000011034a094f59212c29e3f91c48df670e7a4021e4586645d250ee74a90f4b7b51510a5048dba3b555511c327ed211f81f", - "Name": "matter_g1_mul_10", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e3b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76", - "Expected": "000000000000000000000000000000000841c1538c1a3b54418c1c5557a5815c9ed74f6e1c8ed70e1ad424220dc522c530e2e48affe6cb3190abb25af84b91a300000000000000000000000000000000167490a2aa6c8796736cbd364a4d18007ecfee403bde5dc13c611a214610e85af314ddddbf05ea129e027e0ae8d89b36", - "Name": "matter_g1_mul_11", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276bdd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c", - "Expected": "000000000000000000000000000000000ea1f952d65dbb9a40209aa89e367d9d75e1b4c3a70a609efda5fbe7f5c5483163671da425545d3f1afb817c6d8c59a0000000000000000000000000000000000cd537dc11cc63dd15c8ff74d15961390eaee59b2d5697b18c1ea6d534d71551f5e195e8a0793140d821dde97dc77623", - "Name": "matter_g1_mul_12", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a57876817010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a", - "Expected": "0000000000000000000000000000000004c92b7cf9199f47008dd561e624c822a067c57fdea9d016f79e6c7956dda9df0e36b4e78715f3da1319af9f4f1fb160000000000000000000000000000000000d2851d68617567ad5308f69dc5dbbf37603c2ba48cb3759b70fc4301fdce3bdc9fca076e2ae09562396c1b8558ccdcc", - "Name": "matter_g1_mul_13", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f76894c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a659054", - "Expected": "0000000000000000000000000000000006ed98add25d64f7488ed270e0899ee3633c84b73de26557c552017e7cda4cba1228c15e87efb5a740284dddb8cc80de000000000000000000000000000000000b363e14b0285fbd24eaacfe80b992d8df1abfe83991cc55b0484076385374bc87d9c7860177f06143c600503ac54577", - "Name": "matter_g1_mul_14", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931db3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746", - "Expected": "00000000000000000000000000000000164671460621354cd352d93ca7de51828b3e6db0a37d2894a0ac475a5facdbc3ca5909d3bd7553271dadaa68b7474e2c00000000000000000000000000000000188827c6e2f4e9796c71703ba53ba2ded71bd6e8280e047fb6ea440b8dcafa7c4252d26bee1780ac67790e0d603c8ca7", - "Name": "matter_g1_mul_15", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d507f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf", - "Expected": "00000000000000000000000000000000023b2129ac67abc79966102ba223b982d40ca83e9b1ce33dff681c751b3f0c692f8bf19fa0394eae190767899829d1d10000000000000000000000000000000015449c6b5ee2c9f8b28e9732c9ebf6ffee5048263f7b5050a5ac9a76b034931a5c034f91d24b461636f5b116e37a26a5", - "Name": "matter_g1_mul_16", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da", - "Expected": "0000000000000000000000000000000004edac7b03b5861d178bb4aa34e795c776fd95e7c0980f19d111ef208ca4854f73a3ddc219bb6bca173dec67b0e863a00000000000000000000000000000000004dbff672368f86e048c3e33cbe90aba570484b4ca2221f7f6adaa1738c369f4c02c0a10118e84ea8e53cfbaa10fa48b", - "Name": "matter_g1_mul_17", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed833", - "Expected": "00000000000000000000000000000000169d637c52c31e4c62c9563a508869f7bb5adc7defedb5f4ba9f3eabe517fa8c0be2e44d656e50903dcab67a6a44984d00000000000000000000000000000000192b39d5cddac36940d896a738e25c25217768e1d0ca712968718b8fd9ad492bae63063b3cb168368c3df196306b6a1e", - "Name": "matter_g1_mul_18", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154bd411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f", - "Expected": "000000000000000000000000000000001608c3bfb131eae485545b7d19b8f42de18dcea6a0db3279eac2b7c008fbead54046bf13dd63835abe9c63110e12526c000000000000000000000000000000000abb41b2f17cfcc2292c5bf559b38af3b25db40121c6a5627997f65765eee1743c204f1161abe3f71ac1fe4de6aec1d7", - "Name": "matter_g1_mul_19", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af6bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc", - "Expected": "0000000000000000000000000000000016e3125ae97a2b1184e2c6dfe5d9459ac567c686e65674f3b0513df6de5e80d1efbff3c254e509eec3f951b0835b5829000000000000000000000000000000001889481258d3e898ed4e4a43e74c0eda5ba26c0b7525973ca86b896969240ac5928ba58bc86ec17a47f2469d023682dc", - "Name": "matter_g1_mul_20", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719292a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52", - "Expected": "0000000000000000000000000000000017d8c0aa81ca6a1e4de8d0b8b3a13b1d6350f79ee8439da97a5d564d435f4d40bde99138b67284beffbb176daee92352000000000000000000000000000000000a04e0bee6b9681db56604a6dd5e41c072e84f8ee9cb4054410eb610472b96c09802a1d70e325c40c7ab7e248eb2e3e4", - "Name": "matter_g1_mul_21", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1", - "Expected": "00000000000000000000000000000000089ae9fc5cdba1a24ca87fe4f1207d1a36c494d842eed330069f988d3bc8554af1deee3a5c59b5e74729097acc1185fb00000000000000000000000000000000002fd95001da3011b48067d351ec8667c2b2390b23fa0948896725292311dbae71b51d6d5d57e173970bc992d11fdd11", - "Name": "matter_g1_mul_22", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff327064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e9", - "Expected": "000000000000000000000000000000000548e7564e09c2bad9859dd63dd1045878c9b257015558b18cf5911d1763325e411c1fb8af52e8766fa7adae83eea12700000000000000000000000000000000111235351d136905fd19fa726eb6626085875c33c98067a01fde9688a5b2c289cb8e3f5d6a85d0829200a355c82f423e", - "Name": "matter_g1_mul_23", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b", - "Expected": "00000000000000000000000000000000165504769c7ab0d28b39f38f3bd09cd47c63b74c57d39935d1c03e262f9da0e8b0b9264b0d8e2908423fe5c74288c208000000000000000000000000000000001680df1d577bbbb66ffa10258bca54b74cd90a7b3f3d50472e70e18ef54b7a4412e9eb93e39b9b312e3e8e00a52e4067", - "Name": "matter_g1_mul_24", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c23176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a6", - "Expected": "00000000000000000000000000000000087a52e8eadd5461e202a640024fa17e201a9f0a2984be3fecfdeef86abed72d059e8879d0be8789f2a6db0d2cf55d3400000000000000000000000000000000196fe307db05207661a5a5f8f7fb24d8fea18ef91941ea7febbc18819f49f73aef9dd1bdf4fd605e031dc04f16fa92e3", - "Name": "matter_g1_mul_25", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd1d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36", - "Expected": "000000000000000000000000000000000301caf675cd5359bcc274b6141bb6ac53ab6a86a38ad4f8c3233cc9c1a77723eb0de4a2014e556185947dc1ef6624e3000000000000000000000000000000000136d286e623637f12c8b86cd9fad2bed8479ace5189e064a4e12e6e641447dfb0399757026126ad2d169c05011f5031", - "Name": "matter_g1_mul_26", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc9915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc", - "Expected": "0000000000000000000000000000000004ce73cde58c9af5d1f76e100849b0ba3d3cc6491e76b39cf4d7b681fed0686396440f6a721f73b31fb14b4c7624c176000000000000000000000000000000000e26b15c1051d7b049e82476a30545cfa4bf0a2075681d7028797c528712c7fba7a59145c9dd9ca9f5e9b1ac8a68b126", - "Name": "matter_g1_mul_27", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da05061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792", - "Expected": "00000000000000000000000000000000028a89c904f63eb8e68096bd2001458a4b9b32556c93fab5e52ab26ed73d62f0489d6bf1906a62c8148d50d30222a65f0000000000000000000000000000000007e54f21e2ac6d5287289ed9e2a15d457b5dac22ef36c19cb28a6cf9a0d11c981bf6549ddaf7ddc0a59b3d3a4698d975", - "Name": "matter_g1_mul_28", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053f396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c", - "Expected": "0000000000000000000000000000000008c39ee7c8d86a56ad1a9dbe005b4f0d44849d6fea6bbeb0732de725ad561befd49d465a134bd1a63a39eadbb6e0bce1000000000000000000000000000000000d5c892c92817fa24afb0a0fb319ad21e309edfb6300397a215e34eb3aadf91cb41b4ab1c5273bfea6eaf33982c75eba", - "Name": "matter_g1_mul_29", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265ef0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa", - "Expected": "000000000000000000000000000000000ba1650840e24c0f99ddd10a6c3341661e5c96b2e95cb6bda3340e7a0167c906e2f0ccbac6f0be2d7dbb3f9370a5ec960000000000000000000000000000000011638a3d9a81c0fe2ebb547808db758c7cfa8648b4835fb8c4931fd622da3a001fbce9a21d61f98f35b1e907913ffd25", - "Name": "matter_g1_mul_30", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c", - "Expected": "0000000000000000000000000000000000eccc25cfd8c5a58b330a74b92af0c2b932772eacfe898ff3d391fad5dfba52a3940e8edfc9bef5c4de670207c8585100000000000000000000000000000000095ae48a94c92c332915b0c07511bb0d54c316ff3a0dd2509a18a21320b506bbefa76a459260efdf4c045404f02e114d", - "Name": "matter_g1_mul_31", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd", - "Expected": "0000000000000000000000000000000017a7f3b439a98885994a6832b6394b0ec9968f665b5810da58e3ece3d8e8694c482a15d3129732b43d4b7008660f19c000000000000000000000000000000000195299086d3b9448b26fe830522d520d132ed59744e677e6eb114ba7d7045019a0d0386cf817701ca3afad2a0487a689", - "Name": "matter_g1_mul_32", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3fc00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc45", - "Expected": "00000000000000000000000000000000063c123a3cdb92469e7e57a18eaf3e7cab1d85d64cbcb52499d2e611e6ba71c717b0ebaf4cc9208b18c925a5ec167b78000000000000000000000000000000000fa5e78ae10ed8a4dee9440bfc7637d903404749681f85bcb62444d921c4fd809a646ffe3bb7c70dc906d07c62381415", - "Name": "matter_g1_mul_33", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9aff661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b", - "Expected": "00000000000000000000000000000000192b1497c71eb894a7509bbdaf308428e4d5899edb15f9e6e45a88340f55e1b76ee0901a830b66114deccda63a913a6b0000000000000000000000000000000017d58bd474a61ca0ceb23ec392dc08abe5697b8394fd60440cf787f15cddab36aa99c2ec2341bcc06dc1771b5f0fa139", - "Name": "matter_g1_mul_34", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c3346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca", - "Expected": "0000000000000000000000000000000015f72ad769cbaa2bbce0aecef9559b825ba4ec17ec5be2d9f0dbc7184383eb3e201de5163e71f1e71655acd5ee1fb30000000000000000000000000000000000194d27d9045b9760e66b578af24b282d9aeb28eb51206d2e18dc04bcb6df90553a846736afd92b23aa004f8de90bbf9f", - "Name": "matter_g1_mul_35", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db39a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc", - "Expected": "00000000000000000000000000000000146f12001844bb0ec185e773175634f2e56bfa7190caa851ad16443b629b375ce3967b0c936d30dac2f126343722ce5e00000000000000000000000000000000080e8e90ed0d259ad803269711e511577769f7886b425f9b7857dc90ab36438cbd7435f6eecf2328f5fb6eb56f370163", - "Name": "matter_g1_mul_36", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218082c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447", - "Expected": "000000000000000000000000000000001344d2c2bc5ef45dc69597e948ed6021d84f7bf2c36119869a3f84288f3bdd6fc3a0de2b9e2564a930c2207c1ee36a0e000000000000000000000000000000000dc4d15ae09642ffa17d77510fb1ad4bf9e06084e9d352f4e234ea35f33458df4f23a209e29da42c41fb9a3cec3e8242", - "Name": "matter_g1_mul_37", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d4828", - "Expected": "00000000000000000000000000000000084f2ed8573d5d04e41909d5c8ed3feb88f572726fc86d17d466276342f01503f7c8552498f8a7e96c875c4928b808f2000000000000000000000000000000000b618ca81b6ee891690099459634e011b5f59fb5c96488b0205139a65c77f15af135b3528a5ca3b794e7b2991d2434d6", - "Name": "matter_g1_mul_38", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcbd4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a", - "Expected": "0000000000000000000000000000000014733ee8425f42a30010366e4585cbbbdde6ed602a639bd299e63c113db3d797fa01075e24a042a060a043c9e1fa79f40000000000000000000000000000000013b44e1932681d238c52e959e1e3daa7a2e1ac67252ebea0cae90e8249f85b61812b9e09203d38d96f4916837b3693c8", - "Name": "matter_g1_mul_39", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6341776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb", - "Expected": "000000000000000000000000000000000ba15476a1346fbe9be2720721b592ce7c111b95f0b8738495e6c28487e12fcad60006314dfe68789e60f4df2db14eec000000000000000000000000000000000b44b9a9f695c94ad206717daa3128b672924d0db83ae0d47b62b3c79428f6fe151a65a39ae411e18b128d6796b67bbc", - "Name": "matter_g1_mul_40", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425", - "Expected": "00000000000000000000000000000000070dfc697f7068180a7a792604d7b8453dbd393c993be9829a263ad5864c3575d3fb235692ab12a4dfa4221bc6e0c6d600000000000000000000000000000000123a9d9b83e2ca7c95de9602116b1e14d48175073e1fe766458e3fd4b6676f120adfcc5c497febe2f7ff68b1e3508e3c", - "Name": "matter_g1_mul_41", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0e7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96", - "Expected": "000000000000000000000000000000000dcad6e29cda2332dff09377460c7a2b9d908ee53ab13f648cd892bf68a44ffcc8cd5d501f8b068f506b506d01d3f4430000000000000000000000000000000003aa625a60932474ca3f914a3e0aa8384533723f824b12c686a64863a734d96ba13670c8b355b52b0c01b49fbffb6149", - "Name": "matter_g1_mul_42", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5ec26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc", - "Expected": "00000000000000000000000000000000023909bac6048bff0373d27a06dbbb8aba8ddbada93f4fea65c983598307f3c3a8cbe163462484ebb88165c6b6da41590000000000000000000000000000000002162d8a498670158c23daebb724168b5379d9124b064de871674a3ecd15e6b546366287563928a1e279fb1eb2ea0ba4", - "Name": "matter_g1_mul_43", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79bba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca", - "Expected": "000000000000000000000000000000000f79050036c4bb6c6b8e91abb300dc49a75b32faaaeb258661c905b4d936f4096d59de89b911de294603a0e3443fada5000000000000000000000000000000000985105497cd87d5ae2698479da55f6be9bc2cf5a2093b651d7305b67e36343debaf19c266ccb55c23f3de55bdae23a6", - "Name": "matter_g1_mul_44", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a", - "Expected": "0000000000000000000000000000000017901e77745a98c09d6740597c40f27df841cca6dd95653a1da6d8eb1c57d5ebffa6a7b894369b6b419c61462697080b0000000000000000000000000000000001732540a1bfa4a1a851106209ce4807d7c0a33816d3742ad5e2729229f3403940e03b93121b79bb94c24f7e60539ece", - "Name": "matter_g1_mul_45", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b81158f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4", - "Expected": "000000000000000000000000000000000f990d646495fff77d090f4a69b8af0e1762982b53ef8ae9bb955ad8b894942b85c7726587c9fd956ad58eb9e3ca25630000000000000000000000000000000007b7315e1f93cfba8076cf539aae01fd3bbe1cf92daa168a6fd6a2e7c969d35c51fe7eba04f1e0dd3e2020635f2c4f09", - "Name": "matter_g1_mul_46", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556", - "Expected": "000000000000000000000000000000000de9d7e58919ba6386f32af53ccf36cb0b834855ac8dcc19af3c3c9522c3db2985e51ba36067b61181cb0fe8b47d853a0000000000000000000000000000000010ff0800ed1b4067f8c920462f7abd7361dac2371716f7b8648d64a71cc7d53265db6d80b26b9efddd572a2273ab1b17", - "Name": "matter_g1_mul_47", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7", - "Expected": "0000000000000000000000000000000011a11cc098144fe9bd42ec8845be76b6cae4b3001a79f4bbbf9f20e8ac8bca5b37ef8006c958318c3894aac7d6bf77e8000000000000000000000000000000000d5c1e6b78c40a356a35bfabfd66a81924d2eae6d428b5caacf8f3992ab980640e857e756e649ca83f5aa4bda7cd00b7", - "Name": "matter_g1_mul_48", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193ab473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602", - "Expected": "0000000000000000000000000000000002e72f4568780fb41858edc3f5796f7936a30ee9ddc7b5034d9341614d301c7906238bfde3bcb77f063fe652a43b88270000000000000000000000000000000006f971f4a8ac554df7ae7ecdfab724410f1948af994d760c5f5977961f891ba4f4e76b27c3f0e5a1471ad017e91a9af7", - "Name": "matter_g1_mul_49", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013", - "Expected": "0000000000000000000000000000000014b9ef8878af80f824748389d608bc9d0ffbca96230ed590d8e351586607a614f2658e348ac172f3184c1e5fde50f550000000000000000000000000000000000630f0556407c140d0a05b10ea65de48e4866e040455ebcd54fb6ed6996a6a3ac7a94a6818ba424936fa505c2c364124", - "Name": "matter_g1_mul_50", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10ca9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc8", - "Expected": "000000000000000000000000000000000e66c8be115a941ef7adf4490faea39149a3d812c29d4afb36febe3f813c7390a715f838dda90cd73556f89abf3949120000000000000000000000000000000015d85c185cb86af3ca1c526ffa6e9459a9c699c5a4d57278f33b14691e980e0f86b9239e626fc4064890cb610f10e496", - "Name": "matter_g1_mul_51", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bff228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b", - "Expected": "0000000000000000000000000000000009db6ac72cdcf1f69c6593bc183aaa2b3980ff78a4417e23243f81243987ec6f2636641c9e9c738c7af2a1e9f94149d0000000000000000000000000000000000ca7537c04c06607e42403e84e7d9e55b2a06c730ec342f16d03689bb684918e85f637e7a6279d95cb7774f106139d0f", - "Name": "matter_g1_mul_52", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b29431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb511244", - "Expected": "000000000000000000000000000000000620b092ea8cb718ae9669da4ff2faf639fb5e657b7759fdf292e6d841b51545afbabf95a98601847f64fc7367f872ff000000000000000000000000000000000a14bfc0e328310d62f116652b1de3a18282b122e0e3965619a099466986a546b73696274e12bd395224018a48b3d80d", - "Name": "matter_g1_mul_53", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b2051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d83", - "Expected": "000000000000000000000000000000000a633928be3f3bb4c94cf4d8d7a8169779f8bd4bad31ede895937e8e8b0ddea956d255776141541ef5791aa3a0bc6d360000000000000000000000000000000003dc3b703753a7b8ccf7676b04cac8021aa311233a99e8d5290655d2f84555dedff62f9f81322307b538c3f3458f6313", - "Name": "matter_g1_mul_54", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751ab96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f852", - "Expected": "0000000000000000000000000000000014911a8b41cb65cb7ccb940a472cfa58861f1a506a4f719888eb35d48ed9774ea0a0dc3ba38760253bedb4a1acd0963a00000000000000000000000000000000031388c90440f22cc63a1e9450256e5cfcf2f7448641ac66b43d542c4b77e9c590b957efdb1c6d75846b3faccf033276", - "Name": "matter_g1_mul_55", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df9178176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c", - "Expected": "000000000000000000000000000000001968070c01f0aeeb42ab71730f5b78ec122c10ca9dac1764ff5e916fc85a5eb5ed406c03263c57858fb03b15ac0035550000000000000000000000000000000012ecfee330e1cc8006c73e9d41ac1947b67f8704d12faf8c0c05c2519dca68be7bdf88a58eb4825b35a1d270554d6ce9", - "Name": "matter_g1_mul_56", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c049c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0", - "Expected": "000000000000000000000000000000001469e7ab4c3740701927da2b0e34508a73387aea671857b042dabbc65cb849f8c8ed0b7f8c8e37f80aeee98ba953f4e4000000000000000000000000000000000674212f9f8e1419608ccf1a0447533fbd6fda87a35cb9fb39c8a7daf5d12f450c12bfac9e9f872b2643b1f8f201439a", - "Name": "matter_g1_mul_57", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29462ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45", - "Expected": "0000000000000000000000000000000009c756aec59a68832728b1133a69f0794f6a082e2f0f161e488078bec7420a0da19e812def625df9b12aa36d94d8a38600000000000000000000000000000000014aa28b18771ca07b7627446eb60d53bf4837541da661a0e5cadcfeaf58f5a650a39ac304f48e45d9b714cead9ba5d2", - "Name": "matter_g1_mul_58", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d3184fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f", - "Expected": "00000000000000000000000000000000153548fb1d7f1721c7fbdfeb167e1c060a90aab8f7b6572f4a2707de91b03a7b5e68f792a18d940167ae83d1380d6653000000000000000000000000000000000113bb747eab3987cd195e9eb755735698993332d517890f4e3285bf7274f8579ffcf84908a4758f0bb932021f2c76d6", - "Name": "matter_g1_mul_59", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae928a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d", - "Expected": "0000000000000000000000000000000014ca98181489c96227f8052a77730ab446615cb7b2b00a600cdd7defe8b3ee1cd53a6d98892ffccda5fd4916e0cf5886000000000000000000000000000000001567c3207cbd42c0445ea96b464dbd9099b85f5df1932d152436c936623d92fdeb009e69919368134501fa9363a0b1c4", - "Name": "matter_g1_mul_60", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b170d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a", - "Expected": "00000000000000000000000000000000139d093364c313d400603dba5a79479d566245a397f88aae748e110e09e7ab6dd271b8c37a90b86f6b48490ec1d0d8f3000000000000000000000000000000001099d4cb400f2d786dd2dd5d162580d2113c8405f51e8a619a6894d86a7f7ceb237289808acffa274069c24ee27c860c", - "Name": "matter_g1_mul_61", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ecdbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997", - "Expected": "000000000000000000000000000000001247d4d3b1625ffccd350a9fc9759295637e91d9167d9bc72bbc1b60b1abb71dc29595b49ee1edc778f5219416bcd0cf000000000000000000000000000000000dfc69cdd0e4e126208b76a4e5fb8d032ae93031dde7da9bb1358507d4480881576c5d7cb7f0b3fa3032c0151650f2da", - "Name": "matter_g1_mul_62", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a", - "Expected": "000000000000000000000000000000000150849c60273de83f9ce2016238c273359ecf486adeacc4450e1d1a6cb79fc0d0fb38974489375d5763da8a5f4e743e00000000000000000000000000000000157ec6c2dd68dc5fb3cef4e935fedb74e1f0e856f1d75890bf995a08ed6b53b52e2e0d412ae190365b139101e7fe040f", - "Name": "matter_g1_mul_63", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d", - "Expected": "00000000000000000000000000000000024b59fbec5240fbdf3fb4e565bbec20f26edbc2a1bf7ecaaeb5278ed9fe13d1e360fa298e2d3f9b2880b00aff827f620000000000000000000000000000000013ca56975d9fd667bab347ed67fb96a433d57836ca4069976e12459152e1369154bd095a15980880e21fd02b1d7e3156", - "Name": "matter_g1_mul_64", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616", - "Expected": "000000000000000000000000000000000aaff66eca5ddce81533afa27e2db1c25a2c6f0dc1dd7c2236d4c89cb9d2539e109cd1362dbfee86397156c3703d44e60000000000000000000000000000000013598d8ef4470998aec290e941576f5e94d696f7f0be40e3131b516a1679c5b0eba74dc9ae00ecb8f115e4613a50f3bb", - "Name": "matter_g1_mul_65", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af", - "Expected": "00000000000000000000000000000000163cf5475fae000c38e59754cd29f1290ab2d6550552e9186555d1ce2960b7dca5834e0347699d2869b8c9bc42f6f717000000000000000000000000000000000b21bd3bfe50e0536135a910359527f80c130a08029c24f990c82f02727def21973a20a2021c95aaa3a7c8a980b44f33", - "Name": "matter_g1_mul_66", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d245111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145", - "Expected": "000000000000000000000000000000000bc3667c38602e7e1c018cc62933c013a9e78c375b50ba06f0c3d34fead5ec8a9658702a0856625a712520ac99afde230000000000000000000000000000000015c6b5487a52b41ae1a4634c8675f7b847aa5d319ee9eec0c92fc06d8e92e1cacc90ee394f8c90ce3e2c00307f53dec6", - "Name": "matter_g1_mul_67", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531fc07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a", - "Expected": "000000000000000000000000000000001358e1724cb3ec4028a63e4252eff164defaa41b21042037ea9a1e06bc1a0a1e838afc1965ee665de3da0163d22682420000000000000000000000000000000019828e11831e3e4216d843ed3446345edb357b2082b7947fe71932dfd894543928ddddd8649d32b4f1349f63f60bf095", - "Name": "matter_g1_mul_68", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787929b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0", - "Expected": "00000000000000000000000000000000130e09c096ce8ba86ae71a817426d929c7f9f8bfe00e76668b0041e935d1531d6f58e5eb743df3cf86fe88bdfda8c8a300000000000000000000000000000000187b25d8216fa3851bb6fbace998bf3f23dea80dd6e1cd94bb6a72d335702694804c6ef3d350519c5e781f941bb72f92", - "Name": "matter_g1_mul_69", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a63d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258", - "Expected": "0000000000000000000000000000000011e61e5158d9a7c59a5007732a76e27d14602e15159e8f62bd13be8b44c96736af5a77495c3da55c8244af6e60eb4f2c0000000000000000000000000000000008deda8447009898c89c6766e8add105892992585724d520c38d0d4f8c833f88d8c331e11b291b6def6847bfa9629d2b", - "Name": "matter_g1_mul_70", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f57a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e", - "Expected": "000000000000000000000000000000001182f2e45f06a729f82442ddb372f2eb8dbfccf12edd8df0764072c9f14cbe001893d932e89b948a643981ea8aa4fa41000000000000000000000000000000000910335dbdbef74b844a6f3b879d14c23c711ff2362213636ddab7eb1a44cd4b687659f8dd521c134b56bc4eed0ec5bc", - "Name": "matter_g1_mul_71", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567381b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83", - "Expected": "0000000000000000000000000000000019576d68ce66218d4c9e2e6fa9985451eea46ce60b11a74cf5ea9dbb9d0e8741d11436dfd77b0a8b490f4882cc5b416b00000000000000000000000000000000088ba5153e91738f7524034a2609848652a7e416fc68537ab2c16b6699f69695c62e5724dfda2f3b4f90277f5005bfa7", - "Name": "matter_g1_mul_72", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc3ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de07", - "Expected": "0000000000000000000000000000000005720fd4bff4da704edb7e317e3d41f1d1f45e3c1f22c1b98ee0b6875af414f6f58793e8ffd5c89bcec2af711973ca1600000000000000000000000000000000051441e34eed472766186a44b2028d86eebadd597cb7e3fa4f935d30aa043f11fb18670b31f0a3b8aa23bc8f05361064", - "Name": "matter_g1_mul_73", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6", - "Expected": "00000000000000000000000000000000141a0eb238edd1cdb670737d94f658fef728691620f9c6d98e34ed8bd166b38ae6912b5bd90ea21b091766ad27d689480000000000000000000000000000000002d0e7d2584586ab2f08cbd419df3defab53a287ca467b6b081e474711a23608831c1507bac4f328750731b99a06c6da", - "Name": "matter_g1_mul_74", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa3ac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c79659", - "Expected": "000000000000000000000000000000001227b7021e9d3dc8bcbf5b346fc503f7f8576965769c5e22bb70056eef03c84b8c80290ae9ce20345770290c55549bce00000000000000000000000000000000188ddbbfb4ad2d34a8d3dc0ec92b70b63caa73ad7dea0cc9740bac2309b4bb11107912bd086379746e9a9bcd26d4db58", - "Name": "matter_g1_mul_75", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c88586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d", - "Expected": "00000000000000000000000000000000187cb196679b6baf78a7908c37d7f31a9fcefa90b7cf165d0748a358e6dd86fc5c2d91ff1c4429a563b5962b821cbb01000000000000000000000000000000000d94711dc6efed34385579532f59964ab18b9debeac96044f3eec14cb36965f380d21d39c246e972aa2d5891ce417e9f", - "Name": "matter_g1_mul_76", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb2116e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712", - "Expected": "000000000000000000000000000000001405c27eb28f58e7f66988a300df376f3536723e2ba5934d843ae629669485015c90a8da60ef5c00c63c0b08a00203a70000000000000000000000000000000000a62dc83ce27987849070a6022ab6a06186e2527f39ae94d5a23d2e4d234a465d50e03b0d7d175ed7f53ced0c3bbc8f", - "Name": "matter_g1_mul_77", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a85cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a72", - "Expected": "00000000000000000000000000000000142fa228919f71f75df073927d03d9204b36a5177b4ab7bc995b59ff312034f7ff916635e27abbe775379aafc24a35c30000000000000000000000000000000014429fb137cf912995ca785902877e6675105b252a64282412798f883063824fc31cd79b356ea4e4822363b948ec27d1", - "Name": "matter_g1_mul_78", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6", - "Expected": "000000000000000000000000000000000cf0aa7969ec44cc21bc8cca97fc8a581aecb63054c4fa3b7b69d28e0e2e901fa51c42a629145d9126e63aefe7978c8b00000000000000000000000000000000199d565f26b9c6496a4115eefc75f1066480f498a50314b396685a3ade8e50ab03c7f56316be2bcc02dff8b11ad5e4d9", - "Name": "matter_g1_mul_79", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b", - "Expected": "0000000000000000000000000000000000bf4256ce2a2a976e35a9eb266d11dc53d043f6fcafb47eee06e120457ea56decab47ef22b251c6cce17df9a7d91e3300000000000000000000000000000000152c438e11fe1d661eea7c631e04e02eb9204ebe52cbceca1ab6a9b4c889a1ebdda01d7505df29fe2204ef5787749a63", - "Name": "matter_g1_mul_80", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d506e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a4035", - "Expected": "0000000000000000000000000000000007754a49dcdde1354412d3fe2e108675fde8a1df069c86be54c4bec46338a0952aeed50842c2486ac652202c26a1861c00000000000000000000000000000000023fe3f5e6786e339002e14ac5c9fdaac3c012526b33da9ed314cdb145f9279a71e306f5d51243a0f0dcdf59bc5d55ed", - "Name": "matter_g1_mul_81", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad51a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff", - "Expected": "00000000000000000000000000000000141464b4326b0353aa99674bbd98853b926aa580c1e03673297bcbe9094eb1d795331d16d883e0583ed0551f064d7a0f0000000000000000000000000000000002dbbfb86c4d313bdbc8ebd266c190e38645016aca22261665dc850b0d7db8b240aacebec8af097724e5291ff43e6f90", - "Name": "matter_g1_mul_82", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a9251bd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b", - "Expected": "00000000000000000000000000000000118ab56a65ca63becc8aea3f11b370c705f32418d51fb1b1ab64bdb8f0125de2a760cf21e7ffd4d99e9d7cde1368791c00000000000000000000000000000000047674c8f3627527dbb41f51fa52c0fe3a921d07466cb2b5484e4c8094556cae247347a0a1a98499510d1ce5067480ac", - "Name": "matter_g1_mul_83", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6a300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d", - "Expected": "0000000000000000000000000000000000d76cf9fa103355e6f5cd4baa3420e694f252249aa6171569b70cb43c906eae9b60bb79b41af8dc714bd917638bf538000000000000000000000000000000000b9272015e64f292d7b76867714a55d7223bb026f354b20109e81122fa13fd0426bb3aec705b477e7b9560c5a99c9d60", - "Name": "matter_g1_mul_84", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886233e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33", - "Expected": "0000000000000000000000000000000007c87e6d92bd41b7fa6a6ca890bf0b58304875a79af7959d9226a5be2f4ac2b4531fd09712eb6299c23d7c1c5ba3997f00000000000000000000000000000000164fb86eafac39e06c2403e315bff96faecc57474bfc964736b1850696ecfedbaa0795e537b8f541159d479ac5b52560", - "Name": "matter_g1_mul_85", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8c48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f", - "Expected": "000000000000000000000000000000000fb01ce0567f09dc44fd473009d2467c8c16da5ea7b39a1f1dba7b3656cadd6bdf2bf68f96a43252d92e428c1d2785490000000000000000000000000000000008b4fa645f3c56459a17c912c82ca36165e730807282cabeadd9c6c4a12c8a592cbac265021ef62c60eb60df3ff61061", - "Name": "matter_g1_mul_86", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f594228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c", - "Expected": "000000000000000000000000000000000b9c328c8a18113e1d1f783432c857015eaefa724fa2c441d5ef76b158ee6fe0cd1775b0c6db7600754cbf25fea528fe0000000000000000000000000000000019d30c3557af1da2ca169e70625732d9a4396b51f3b4988a9aba1be62538fd51c167c83e921f4876224d361afc90eaf8", - "Name": "matter_g1_mul_87", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82fa417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1", - "Expected": "00000000000000000000000000000000041054430741e889d4cd8e7efa41547eb624bd775fd9fb64cf9e3dc2c6df27c95ffb8d76933ac4fa1952a5820ff88512000000000000000000000000000000000e8a28f5c622482b296a43ddb607e0f25635664fa849f3d6840ed7118892106a787bc07806dfd83935754d2057f2eff8", - "Name": "matter_g1_mul_88", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab446561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb", - "Expected": "000000000000000000000000000000000da2286b44e7e90e19d51c3c41bef375c54688b07afffbd7c528589dbf7f012e1fd248b9067a3faae9f1c6b626a5c90b000000000000000000000000000000000bfa0a482b0fc445f7b99c52a48116383bb70d5f2ebec5b7715796fbd0da744d0467584bfc1c8a42ace833d57c167a24", - "Name": "matter_g1_mul_89", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c2cf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf", - "Expected": "00000000000000000000000000000000148a7e9b0b4fde322f1177ced0bba34abec4a3e500afb86f9ae0a71bd75004e9c631d4cb26798bf963f7aa367f74630c00000000000000000000000000000000097f4c0893f9beadd66e4cfc6976dd277e527b1e31443e07554dacca52390066a4b37a7f0824cbaf51d3a555d696881b", - "Name": "matter_g1_mul_90", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5", - "Expected": "0000000000000000000000000000000003e1d921b5e0280f7370d55967e716bdacb7521547e22190e89862dbfcce02dfe7fa7927a70e7bc33448b9321de3d8ae000000000000000000000000000000001163f78de4af8494666c64d47d68a0feb0905c42ddfa024398401202d1fe0d6672bd1bd4222a8d106668ba4617683485", - "Name": "matter_g1_mul_91", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e40ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e", - "Expected": "000000000000000000000000000000000a94a186b96acbee87f9c1745dc301229ec750c6967262e629924227c6680b1d404e4b23d998611ad0e415610dc8edd900000000000000000000000000000000014da21c0f6930a79c8afbe42f73e048236b6d9f9ef8f270733fa1cb1012377eab37ddf2b9c742fea44020caeb95beb9", - "Name": "matter_g1_mul_92", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefbae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be5", - "Expected": "0000000000000000000000000000000015cc6c31dfa9482c6341f816786562481bc3a4db4a4a00807a9c7c676eb32b9dc7e002ed4971f26c1dddea00d78721b5000000000000000000000000000000001303660b6bcac611b2d41a4f7ac9ecf3f0b4292f83f2fdeba300a060131322ee3c2da3ca3539114114ec8a76dee6a5ac", - "Name": "matter_g1_mul_93", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35851268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0", - "Expected": "0000000000000000000000000000000009f1903e9a7d275487a503b9c968cd86823fe6667c09593b60ac2c88f306e20ccde32eebb5942a03fabde9195c5c500200000000000000000000000000000000179b41dbc2ede95ba7dad512329aeca9ca3bfd4da4b9620070d76d8fe8b49ad7fa92358070dd5098a2eaff490641edbb", - "Name": "matter_g1_mul_94", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728bf9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169", - "Expected": "000000000000000000000000000000000f9736431073987708757d61927a45cfec471c8366776e140f62d805afd948fd132c4a5f4049de3a1474d0cb52c3c25e000000000000000000000000000000001515b057952696810a90dce1ee8464fd6370e8af5434a99333eacd1fb2884f6e8c568f887030a4957ff6d24ca02f4657", - "Name": "matter_g1_mul_95", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b4", - "Expected": "00000000000000000000000000000000195460b2d59df32f9f41eaef1139d45f0cb8f35a7982c38d356a8a8412f25e600580026d2d908b0493edba5dbea85f5c0000000000000000000000000000000004b339d62b3cd4cc966c6b4038adb302f997a16d8a6dfebd153295de08e57d1513cf0f16d82dc450e4d6f52621a42fb4", - "Name": "matter_g1_mul_96", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d22d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125", - "Expected": "0000000000000000000000000000000012cf2bcb79668067b7a265672ca614405868cf189ee9789b9e1e3186d231176dab5fea86cc5865392db8c75fc5d124c900000000000000000000000000000000121bf40feea00e151b718157b8c024f126762d84cff20aac08e7f2a027ab88b33e134a410c2af279a39618f7d21482a0", - "Name": "matter_g1_mul_97", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe5485041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b", - "Expected": "0000000000000000000000000000000013a530f94e7600820dbd8aabefde2acb8b3c74e833457102fbd297317eb532c0622636ef9e9376fac1637dc745fe895000000000000000000000000000000000139eb14d3b69be977413c832bfda234348186d46fe177154e34fe204f62ac79f4b0f59bbef39b0676d81ea42a0946fb3", - "Name": "matter_g1_mul_98", - "Gas": 12000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b57cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf", - "Expected": "000000000000000000000000000000000bf700422a382546a74376b0292f3a49ceff5597f0d2b726b1ff099bcda7ba92238a21db12eff5c314a29dd2387bec850000000000000000000000000000000005e22e3c772f3634b1ccf4e311241977eb20e7269540ef22d379de26ab80c58461dfa3b67848e0d584fb11de1917949a", - "Name": "matter_g1_mul_99", - "Gas": 12000, - "NoBenchmark": false - } -] diff --git a/builder/core/vm/testdata/precompiles/blsG1MultiExp.json b/builder/core/vm/testdata/precompiles/blsG1MultiExp.json deleted file mode 100644 index 62b91f6f4..000000000 --- a/builder/core/vm/testdata/precompiles/blsG1MultiExp.json +++ /dev/null @@ -1,723 +0,0 @@ -[ - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000011", - "Expected": "000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436", - "Name": "bls_g1multiexp_single", - "Gas": 14400, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000e12039459c60491672b6a6282355d8765ba6272387fb91a3e9604fa2a81450cf16b870bb446fc3a3e0a187fff6f89450000000000000000000000000000000018b6c1ed9f45d3cbc0b01b9d038dcecacbd702eb26469a0eb3905bd421461712f67f782b4735849644c1772c93fe3d09000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000147b327c8a15b39634a426af70c062b50632a744eddd41b5a4686414ef4cd9746bb11d0a53c6c2ff21bbcf331e07ac9200000000000000000000000000000000078c2e9782fa5d9ab4e728684382717aa2b8fad61b5f5e7cf3baa0bc9465f57342bb7c6d7b232e70eebcdbf70f903a450000000000000000000000000000000000000000000000000000000000000034", - "Expected": "000000000000000000000000000000001339b4f51923efe38905f590ba2031a2e7154f0adb34a498dfde8fb0f1ccf6862ae5e3070967056385055a666f1b6fc70000000000000000000000000000000009fb423f7e7850ef9c4c11a119bb7161fe1d11ac5527051b29fe8f73ad4262c84c37b0f1b9f0e163a9682c22c7f98c80", - "Name": "bls_g1multiexp_multiple", - "Gas": 27504, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000000000000000000000000000000020590000000000000000000000000000000009ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e522400000000000000000000000000000000032b80d3a6f5b09f8a84623389c5f80ca69a0cddabc3097f9d9c27310fd43be6e745256c634af45ca3473b0590ae30d100000000000000000000000000000000000000000000000000000000000b7fa3000000000000000000000000000000000c9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b6000000000000000000000000000000000143be6d078c2b79a7d4f1d1b21486a030ec93f56aa54e1de880db5a66dd833a652a95bee27c824084006cb5644cbd43f0000000000000000000000000000000000000000000000000000000004165ef10000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e20000000000000000000000000000000000000000000000000000000173f3bfab0000000000000000000000000000000006e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb9090000000000000000000000000000000017d81038f7d60bee9110d9c0d6d1102fe2d998c957f28e31ec284cc04134df8e47e8f82ff3af2e60a6d9688a4563477c0000000000000000000000000000000000000000000000000000008437a521c9000000000000000000000000000000001928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb700000000000000000000000000000000108dadbaa4b636445639d5ae3089b3c43a8a1d47818edd1839d7383959a41c10fdc66849cfa1b08c5a11ec7e28981a1c00000000000000000000000000000000000000000000000000002effc7b3027300000000000000000000000000000000085ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf0000000000000000000000000000000019e7dfab8a794b6abb9f84e57739de172a63415273f460d1607fa6a74f0acd97d9671b801dd1fd4f18232dd1259359a10000000000000000000000000000000000000000000000000010b4ebfca1dee10000000000000000000000000000000019cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a577930000000000000000000000000000000007481b1f261aabacf45c6e4fc278055441bfaf99f604d1f835c0752ac9742b4522c9f5c77db40989e7da608505d4861600000000000000000000000000000000000000000000000005f04fe2cd8a39fb000000000000000000000000000000000f81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed0000000000000000000000000000000011af629591ec86916d6ce37877b743fe209a3af61147996c1df7fd1c47b03181cd806fd31c3071b739e4deb234bd9e190000000000000000000000000000000000000000000000021c6c659f10229c390000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a900000000000000000000000000000000000000000000000c01a881f8abc4d8843000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf10000000000000000000000000000000000000000000044496e633650ef8f6fd100000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000000000000018461a3d444ec527fcbf4b0000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb54117000000000000000000000000000000000000000008a0eb53c748001536d7ffa9000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a700000000000000000000000000000000000000031133a6c7d698078a7ec7e11300000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb300000000000000000000000000000000000001171d5c4909480aae3b110d01c1000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc75843600000000000000000000000000000000000063376fcdf64c9bcbeeff0f9f9f9b000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f535800000000000000000000000000000000002344b4be368d3b617df4aa8dbdbc19000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000c896c3f9d64341ba7c5f8a06271dce3000000000000000000000000000000000272e9d1d50a4aea7d8f0583948090d0888be5777f2846800b8281139cd4aa9eee05f89b069857a3e77ccfaae1615f9c0000000000000000000000000000000016ab25d6a997bcac8999d481633caa41606894aae9770cdb54aac65ac0a454dd0346b3428fefd837b1e3f654f8217f4a0000000000000000000000000000000474d97a9cf29e85d4a35f6102fe7984b1000000000000000000000000000000001780e853f8ce7eda772c6691d25e220ca1d2ab0db51a7824b700620f7ac94c06639e91c98bb6abd78128f0ec845df8ef00000000000000000000000000000000095bc13d5a05c686e20d7b904db4931272d84d051a516fbb23acf7981d39bffa3943d08a9be01fc48e5241cd8b775ddd00000000000000000000000000000195894e95ca3e59929612e77c1075322aeb000000000000000000000000000000000b48aa2cc6f4a0bb63b5d67be54ac3aed10326dda304c5aeb9e942b40d6e7610478377680ab90e092ef1895e62786008000000000000000000000000000000000f6fc00c0697119a34363c0294acf608eca3c680d80183a59c89b45a66dc750f818a27e3a6e136d69e7580a8afca001b00000000000000000000000000009027ceef3ee429d71b58b84919d9a8d54189000000000000000000000000000000000c8b694b04d98a749a0763c72fc020ef61b2bb3f63ebb182cb2e568f6a8b9ca3ae013ae78317599e7e7ba2a528ec754a000000000000000000000000000000000951b70c206350e1edc2aefdfaa95318368c151e01e468b9fb1cf7c3c6575e4f06c135715cc5e51e1b492d19adf9bee000000000000000000000000000333e268f0b5b1adf76b88981fc305f03ce4bb3000000000000000000000000000000001717182463fbe215168e6762abcbb55c5c65290f2b5a2af616f8a6f50d625b46164178a11622d21913efdfa4b800648d0000000000000000000000000000000008531aa42aa092a91e0894d84ff0bcec0d37cede43dec85cca80ffad335d6f69da18335869ba1174f73bb37501404d6f000000000000000000000000123717b4d909628d6f3398e134a531c65a54e8a1000000000000000000000000000000000cb58c81ae0cae2e9d4d446b730922239923c345744eee58efaadb36e9a0925545b18a987acf0bad469035b291e37269000000000000000000000000000000001678cefdd942f60480b5f69738a6a4cea5e1a9239d1bd5f701ad96c2dd1fd252f0aeea219bddcda4bc8f83983a282aff00000000000000000000000679956d49265608468757580db6b8b1821c2eb13b", - "Expected": "0000000000000000000000000000000005548dad0613ef8804a347152e8267acdbbcab98a795fc0da2d9df5c8ec37e0eb32e82950fbe5f8ec330b8bffafe13e40000000000000000000000000000000014e94dbbf60d89b3f68a5a076fcbd7cc0b683eae228f5d5036ee61012996ae2d347cec19dbd4eab547fadecdb31c078a", - "Name": "bls_g1multiexp_larger", - "Gas": 89400, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992feeb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed24d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be10000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e44c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d38964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f90787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1baaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e10000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442adac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795bb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd1080000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a190fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f81876720000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac943b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e3b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c760000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276bdd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a57876817010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f76894c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a65905400000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931db3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746", - "Expected": "000000000000000000000000000000000b370fc4ca67fb0c3c270b1b4c4816ef953cd9f7cf6ad20e88099c40aace9c4bb3f4cd215e5796f65080c69c9f4d2a0f0000000000000000000000000000000007203220935ddc0190e2d7a99ec3f9231da550768373f9a5933dffd366f48146f8ea5fe5dee6539d925288083bb5a8f1", - "Name": "matter_g1_multiexp_0", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d507f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed8330000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154bd411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af6bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719292a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b10000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff327064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e90000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c23176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a600000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd1d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc9915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da05061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b2087920000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053f396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265ef0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c", - "Expected": "0000000000000000000000000000000017479d99909c144a5a5fdfd71721f4a2ee90b2b9654e069a38b460945b9291fc74e6922a7dbab9bb12b4bff9e2d0175b0000000000000000000000000000000015cfff11afe08d76944c9f810017ecf78b8ed54096078195d65a5418f660cf9b2024646a8532e349eac5d32d59c829db", - "Name": "matter_g1_multiexp_1", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff17d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3fc00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc4500000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9aff661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c3346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db39a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218082c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d48280000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcbd4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6341776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f0e7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5ec26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79bba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e820705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b81158f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa40000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556", - "Expected": "0000000000000000000000000000000001c143e5d7bba56a959b94955f8eaab82a92a2e2b355baac7da0b57281645c689486059fb590ef2576a7a03a7c57e85d00000000000000000000000000000000182b1e16004c7e6f55923dd0b1dfa7346d1243996070db78f45c4c0a2cef95e93c6373903b5e0dc63f171c8164c2fb5a", - "Name": "matter_g1_multiexp_2", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac700000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193ab473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c0130000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10ca9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc80000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bff228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b29431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb51124400000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b2051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d830000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751ab96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f8520000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df9178176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c049c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e29462ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d3184fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae928a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b170d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ecdbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad9970000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a", - "Expected": "000000000000000000000000000000000b2997ce4cb01abbb0ae6d28099d20e1f08c33351a6f0dce417a279789d6c581d4bc5a4a261e37e6df31a6928040d1f60000000000000000000000000000000003068e73dbbab6fddfd3c1e4fbf58bab58f15e1630c8c236faf3048be840abe316084aad7dd4ca6ee9d353ea8db536d6", - "Name": "matter_g1_multiexp_3", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f7a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d245111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d1450000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531fc07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e787929b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a63d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf542580000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f57a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567381b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc3ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de0700000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa3ac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c796590000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c88586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb2116e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a85cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a720000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6", - "Expected": "000000000000000000000000000000000ed96265e66875001ebbe888571ded16799d0bf5a6bad0abaca75b94bebf3023487a29fbe26a68f1cc90485df379845d0000000000000000000000000000000001be40cb29d8b722f91515f7e18372f7a0f77bc3ef2852c59e7533aeb67cc4cc4aab0b8e87f9a4982806124462ae94ec", - "Name": "matter_g1_multiexp_4", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d506e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a403500000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad51a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a9251bd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f6a300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886233e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8c48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f594228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82fa417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab446561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c2cf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a6f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e40ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefbae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be50000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c35851268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728bf9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169", - "Expected": "0000000000000000000000000000000008644b6d6adf9d5b6b50d4759363901ea94218881fac2006ea391c41fed2a94645eeb3359df803d740710f0f7842b985000000000000000000000000000000001168ff1897eb699e475b8ca2930ae9ccff139d534c7cc606c7bafec0ed23a6e55c6ddb1efbb1b5f75044d0a7e122d204", - "Name": "matter_g1_multiexp_5", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b767f399e4ebea34fd6b6b7f32a77f4a36841a12fc79e68910a963175d28cb634eeb8dc6e0533c662223c36b728cce2000000000000000000000000000000000cb3827fd6ac2c84f24f64789adac53439b4eba89409e12fbca0917faa6b7109aa831d16ca03191a124738228095ed65070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b400000000000000000000000000000000150b75e9e9c03ada40b607f3d648bd6c40269aba3a1a992986dc005c9fde80bb1605266add0819641a0ca702d67bceed00000000000000000000000000000000083b43df032654f2dce90c8049ae4872a39f9cd860f08512930f43898e0f1e5625a5620818788797f3ca68134bc27d22d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125000000000000000000000000000000000cba419694214e95a3605a9b748854d16c8e6e1ee151c907487d8189acfac1361b790a5e78f43593152027295adf8df400000000000000000000000000000000110813ff6e0ddf3427e2a514d3f0bfbadcaf9dbf039e0f93fb9643d1e62bc2469fe84cd9ff0d585bdd1037255bbe5485041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b000000000000000000000000000000000106df8eba767e90cce0eabdaacc24d8e226c6865012ef8cb1460de5a319d443fdc6b4f4e58fb668943e0528b1809da10000000000000000000000000000000019789f464c95c179af18704c0b67b881991880f75ee7b03b9feafa3eafcd0f7d30a17fdd9cf439ff7fe683adca2083b57cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf00000000000000000000000000000000107e1fea76b5f2be2d12e11082fe690f01bfe6cefe22ce67de968e410ef51a6192b5b28a89f222db7e5b5fd5b8bc7c4000000000000000000000000000000000014028a700cbde8bce295c564dfbd73294f9bb65db3db9d38312cdc31410ceaf7151ff5d9420de2a5bc8f0d609893c0612adc8edb64db5bf0ed6724f3b54140ed6c81ca65ef9d1b38c8bca6a62bfd3c6000000000000000000000000000000000a57058bc228914bbb3e3e8f6a73842533432e0cf226cc02990b9b99a74b0acbad498036d8fb72a163590c75b6041d060000000000000000000000000000000016d275fe8c7e37058f287e1646c28ad1b4a675c0eef9671cf95dfa25617e2f2d515b2fbc04cfdffd5d487b255dfca245d1535bfcd68e8136808edf89967fbbf76b7f58d1a8ac95ebd4944b9e440f20b20000000000000000000000000000000016b6ecca57c78d6595e6b55b9360bd946b2f0061b98d931d82b03ed747998285e093c978015f0b775867ad0d8b4a1f82000000000000000000000000000000000b584f6f00bbcb2432b6cfbd4f6c88e228658887b5278e461ede804fc8a65dc6c997de30efc65b4f43e3d96717b938644c576996d90abde581afb58903cde4b9443eeb65e21b0d68c578e04c8f28f3d3000000000000000000000000000000000d1eac060ddc0a327396051c8c4dcccb77d11da05678d0720dec020d8aa29cb8ac959184417267cd7386feb1c81146a70000000000000000000000000000000003f8b5667ee4707958ecb93a1772849d5d8a4d42a2367ca058b160dbafa8ac0b98d5ea216fd18130237a1f17ce905feb3c558cc615b1c61c9a42b8b0ab4668ffcfc9e95bbe958e72e7a5500058e6b0bd00000000000000000000000000000000180152247144900b015c3db2d8b26d45a57930a5ca988c1fbf74b63b48afa149347a343f3fc6b1f31ddd6de079391efa000000000000000000000000000000000b6f3ae16d2a580ae06634455302db85fa94d71def14c84cbacc5ef98335d6d87faacff7a9bc14dea342a6a80d9bdfd661301b4957a468e2817db5914ff102bc96460a2c5c15e78bd42884b1223fa71a000000000000000000000000000000001918c4f95a0d0931ac3f254cd61c10cadce5cb9e1ef352edc8e5944c8aa8ecd90c403ed764ef42f646c7ec5e3126a140000000000000000000000000000000000ed644cd065411c63c7d054a57344e7a909e1d0a6b414bccbd356f15d16fc1b42c681cb6b36b143e91b31866387fa94395cd2686d24a5bdda0bcb118a2c0eb5ccfe411ec452e1beb3adbda7e93ea367c00000000000000000000000000000000070dfa1dda5ba02e94b29a63f8eb571ed7e8b0d037a0203af9a8350dacec092be1bfe33f4134b2afac77b9a36f95208000000000000000000000000000000000019e11a80ce3f9b3321cc6fd1ea2b314bf0c71d0dde80cd5b4de5f0d974597f57036613829dc777a6f6ecd6f9bef2f85fb81d555d1e2df92cdb487a888fbedad976dce54b5c46a39893edeac21a12d6e000000000000000000000000000000000584b7ea99ce0398473167289d34314c60ba913338b0bb690cfbb013496d24854863237a4d716437dc6ae33326240bd800000000000000000000000000000000065964a064e4da56471c9aed383e6eb38b58b9110a2cbf991d6dee869d2f1307cf7273d203d941ead90ed67c923dfcd5bfeed84bd95fb955d1b1045c059ffd051324dc8966e504164e54f76f02eb1b860000000000000000000000000000000007d6061bdf40745ef7573917e0e19f240b6e917f7cd4c47e01969b9afdc6af4e3c93e0f1dc2d15790bc2e6f182c01f680000000000000000000000000000000014625d3f2825121a907b570e9aeececcf81137f40ca6d0c00d709ba9931e403c0c2ed262a8f4c2b24305dcd3185b81b0e3b308b95f6d496e6d5b910b6aabef8d9f868471653e8254ab4d49d593180d2500000000000000000000000000000000087b5d6595554184fee36be472a0ddb9ac7f9beb20817647fa9978b2e0c3549ece4f061b58054e9191ff3f120c12077b00000000000000000000000000000000168d8d995c1fd032ca7b0aef2ad5c37ef7c7cef8b61ab8fcb5ea2d449455bc75b1b85631fd2ff8f5ca4e5880f36905ded4ea92e0e776be341c8444d4040ec121a2847256c5c9bc918adb28618548b048000000000000000000000000000000000f44cda026dc5e30eb06f12307bd582b271ee695fa68fbff48674c0499dcc875d617471830958e31bcd2c883e97a9e590000000000000000000000000000000002977682ca8ca450df2ac3c3880b1235e0ad8436a36364d319903fe2ca2664e05a70840aaf2d62531cd8c4ba4bfae9124c07f5188e4c6270a7e9e2f551683c4f9dc943ffc7ec279d15816a7f4910b8d300000000000000000000000000000000107dd39f779801f608cceb4784134894d2d9aee37cf328bb764d8afcb6d1e0f1387b36bf5b7b335099849278eac44e8200000000000000000000000000000000045c985714b519061a9c8d8c9665b582abdc4116a48a70e0d3c4a7709568aaf011aa8ecb893ca483878404b3f8b22e41a819a0438efd7ec0c1e3eea07ba201af6a832fecec818adbb781ad0c23e81dae", - "Expected": "0000000000000000000000000000000005605f40a1116742ed53aaf7092715355ba8e41d5d49909f79ec9580955c4a9e696fa30df37e4044de4d23fa1c4121530000000000000000000000000000000015acbfdf914883d16918f980aedc2dfddc428ef8e9897776443ec3cb091f6cbeea31634ef5ed061792710d5d2c87b8b1", - "Name": "matter_g1_multiexp_6", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001696e814de192623543f822a22344258c8ef9b92c178c4bf2404b38f39151828bf518a868cde3db5cffb745f1bf0023900000000000000000000000000000000125bd1df30f4799271a9db03842f98ccb5a5c3acbe813b8324fefd06e3c8ec4e2c0be8c2d24328a2d1169bf6ea0ce46fb15af019ea2de662bf187930caea19d0aa07a74b49fa7d1819a539e06e4c69ff00000000000000000000000000000000138dc5c034135105c8899eeb61ab54a84cf02919e5650f34518f941aea5bbb6f9df3ee6bb2056d0b9e060158140f990a000000000000000000000000000000000eec8442c8656ebc4696ee13273b12f3e362862acc3b8ec6f2b53f58f74ea23b33c79fbbd2058ad205f4932db2e87ae9064a6af51c1d499c4c28556ad1255af7467bc750bf2db2842d626647bdb334610000000000000000000000000000000008f7f45310b5638221cfc9dece18010034c00b3cf170535008d60dc7ed6ff90bfe87e03d94e9a38201699f0742d8973500000000000000000000000000000000185b62a19864e21e1bef19fbbc21863c75f558bcbfa1b948bf939876188f4fbff5d5f4f756e0ec5348e194bb4f70706ca3daea5a083af43711fcb09282b66882ae5b5b8e1714e9186f33ac0dfe48b7ca0000000000000000000000000000000019269dcdf3772ae4969b68a0b4f87c5097aa8bcc9e6155638c3de94fc22b4965386be28e059bcea69f993cc388ea9a79000000000000000000000000000000000b95f44ad9f14cb5e3b9a338d0e4345153c4ad0d42aa00a4c12df117b89d9cf8bb556041d49f94b8f63108f03c56a449bd682acd154f6e16a583ca4968d28471653375ef79df078b17b2cd9634258dc10000000000000000000000000000000011c86d420b6d8820af8a3ef511d79aed7c82ee08df993a5ba479b29ef2f968919444a7c48a24ec33522e1206bb9ab784000000000000000000000000000000000f4a47f3f14a25108c2c9262466d14e3a8d1f21bd2d3d6f28f03f35bf23a4b5b494a7cafe6ed5f39195e07b1692bb6da562223d3fae1d303a01ee4642fb4cc70f21937ba7fe377260fe82262a8455a7700000000000000000000000000000000091d9fb6493f4441c6e57a5a58210a6b78e86f1a9d204094ba6fecf2c146522cf842219c900d7cb95366cf7e411ff4a00000000000000000000000000000000015254260fb67e88d0067ba7006a49814c74a5369837dc5279c0fd19c8826813c922793c96e0f708092158ac297a368ddaf1d0fdab6185e1c3f9f621ddc169ba92584db0b40b6ace7ed563eee0090629f00000000000000000000000000000000027910712cefec94f0fd4de6aa70ccc408e64d5de6b473086009c525fb6d058ea03bc99f7ab49cdbad3a42bc8ec0999d000000000000000000000000000000000c0b0bedbad83ebf6af4f5757035b8292fadae4bfbef9f3bfcadd21dd796d7e3ecdf9685ca6d4d649b2f0702a3280d40e910487c91f3839d5961f02a67f3b357206e406ba207dde969498e40d4a26e88000000000000000000000000000000000b0ae8987464ea0b77201d468db7256b135a5cebea92dddb3aff10e451568e714f1c418b6d53903b89bc71109180b8c20000000000000000000000000000000003050becb4625f8e3ab2cf13dd1eb8f7eefc7e14c16934b87661adbf0139631108d241bcb1fb24c5b989f6d424cac883396d32c2c9ef685120995d2244756bd45591618597306193422f3b5df4b075d2000000000000000000000000000000000dba43568347a96f26f2633d9fc0fb4610428a8d4992c2734b20928bf974bf642a5122995884cf11b76126ba66522c8c000000000000000000000000000000000b9bb25b0db32149736b671ceed44df71f36a33c15ed821f591098ecd873355cfb8a39fc7c7378a19d84a5b232227ab92087e21d775fbc2c20dda715e46c9c4970394e40e991c78ecc13a2a5d0b0f30f0000000000000000000000000000000018d46d1a9ec91cc7983b29ac83fe9101c0ca36276d40743d2a6010d574fe1c16ebd9d7f0c83cad5ec2b2f652d3e6cfa500000000000000000000000000000000185f6367fcfa70e7a005c1739c0d0a19b5ec8de766037ec92840e66e2e9db18ba2356676899763183222f9957f48f300f44043002a94560d725da2ac44f30cc5f14f52dff5671c6689efebd803b1df7a0000000000000000000000000000000016677511c781b2b97456c3059c19b3e12a865cc21ad71cf06979bee1a3128682a4a86f3e07cdbc9ff7b5aa7a9899653600000000000000000000000000000000006307c89ac36a88c6921c020d32530fb69338afbb33929e231fa704f0454d642c47a3b8d320b4266283a8571944d0558624c83d846ad2e53f3f8ff5ffd3fca8723e6cd431e89ca29a4d662e82004b600000000000000000000000000000000015a9b215eaed682e4704cd3b1265962ae0e24555a16612ac762040e1fb9b412eacec5130a6f6a31eb670806be7ed775f000000000000000000000000000000000f60035910c438c177a27e6141d0ddae706d3e852d61e37cf8bb2f03550feeefa7213545e3af5ea614c91b51bc2fb378b2b2a8a42887ca6dff5b5364d88962068496bee79cbe74de0e8a06209feb3832000000000000000000000000000000000077b7a4c4644b21ac3ef56db1163f7b2e07a817cfd9d4c6830a97d0ae0b620e0b235376d590162c378899ba12eadb5900000000000000000000000000000000022beafe4b4ab44434c9dabae45a395b5b8da15da2fc2e723c1b30b5efc95e880846844f27eb47dfae8657fa27ab64ef88ecb5976f63a38d7f3d8c8ec441b705563c5e3d899870ab5d2ff84467fffefb000000000000000000000000000000000324928100db98f5a1af039a8e1b63099214982f1729ba633b51166da97e861426bb91283b386ed4b465d791e63928ce00000000000000000000000000000000178823756c0facbd4b1cab22f346ea7d1dce0ab687263265350c9939d52abcb5a5000b3395f8268a38027410675e8baf951f4960d6614b098249eb9420077ea5ad11e38d1694f4df33719d1127338f440000000000000000000000000000000008828eea92c3245eea4d60ee385734d3237e4e346e52c5de8b24c82325819be6984da4f0c1ecfc6ded5d0539a6f1f1490000000000000000000000000000000017169bab8970f47a303d2487e3af707eddaf7c4453e9d2d6bbaf953e74947b5fd40663173edd55c0d6aad7884f69a0967056c7d93d8453be369831dc0575df6438db488780d518a53d19b8f5d22d506a000000000000000000000000000000000787474664b2803e78489de6c5d5f1938e784e552bca4c32196cfe121380aad591c9fe4d9230dbe976b3ed3b3044b8630000000000000000000000000000000000c026547c94cea37793fee439c359cbeb2b985a33559ab25d1b55773c24faaf4fe511fbf7df085bf5c1715c79469cc28aa982de1583c25307e9e2c8cf2469a0b1076c6be2fbf12caa8584f34988221a", - "Expected": "000000000000000000000000000000000a7153c6173dc27b6a241c046a2a9bc25b85c4621667d0a10550cf7a090a8fb914725201876a5bd2af09d4fefdede3890000000000000000000000000000000007aeec94a64ac629673f3be3cf660f471e3e928de0884300ca8271d42c92b965c86bfe76df61d0645e955f40cbe3751e", - "Name": "matter_g1_multiexp_7", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015fec2d82f5286d2067b07d83cd1c131d3fe18628101c3e45caab07f3c775c97e1533836830959cd7e434fc3fc392203000000000000000000000000000000001050e1396a5053c902441cb33003d9c54e6b631a80e3c132dfd37805bfe87cc2ddc495200268fba0376c5fa071fad230a18ca15f0d931619363f5ee56bd7657b2298f228cae8d185c9d062910193e9c4000000000000000000000000000000000fbcd07180f265688329d72ca68cde644a580cc9d698e40f69380065110ff5a61149e4aa9f67056e0e1603bfb9b5b3ce0000000000000000000000000000000006f363a9addd63a59035cad90cd52213665069f540b6c6cb41cfff5711376885e3242b596d051a59f681941bafeca53eb54274927eb29fea0cdc464271c918826d5249b2180a52a5020480d1020c9795000000000000000000000000000000001164abfa75cb4d711ad811c4df430ecbd6329968ab003fa680d235ab34a9565e5c08add76cf412f132b54812671da7a900000000000000000000000000000000141c9858dd17dbb027dde22dd65f6a7cd38a1999eb7977cde87ad762425e364e1395851b1cdb41094551e530d891b0d15849bffc842c21277be88dfae0040c54b072ff526731947cbec0cfe963f2d0dd000000000000000000000000000000000b95d221c628a77bb75ee5942c9df4b700268c90c4e6330ab5533d13d59826c81aeef7621ef6145f48bef9607d280ad2000000000000000000000000000000000b2ae1b6f916d77c31e4421f8d0241201bdab5339f95eae0e9491b4da5e226f8eb3f754d40be3b446ad6d18f28158b08aeff769da1b62fde321d46c66f8ee7f2129446d805ab7f7bd586268de8f57c4300000000000000000000000000000000128989e92641f3c3a914c13e986aea1bad2c87a8c28cf156bbc68bcbb134b25cd672832f2a988f60d2ecaaa1b83159e50000000000000000000000000000000000106dc95373dfcc85d9de6b5b609554b67e8683f90ea13156c8318aa8de0a2355a721b3bd77a6329264ae671c05af4a52c9e56cfe957b924c9c0294e1c1f12474331c662c8e86288c97e6a8b8b5b2020000000000000000000000000000000009fd9fc9ecc0d1521696bfe7624360d11111523a4ee0e30432a468dbaf1c101691fa527aac5ab531be822ae914b0afad0000000000000000000000000000000016b317ad68ec471b0ad67be2c489c9f5bb0d8bb6b5ef909ea975cb17f5964564d5f1a61d32d60c457923e4680a218b9bdecec569d223c724d162250ed1d074ed9f4080aaae3f44b77df05292be48ebd9000000000000000000000000000000000b982f33980dea4d89b577c9f849f8b8d9cb0c7efec7e17284d45c855638fe9ab2e5bdc52ba79d06a9133f66bf0ea2b5000000000000000000000000000000000c252a2e2769d3250479091050133808a1b0fd20af2b41cdeebe7cfcf7e3a92b9ab17cdf4d370f9fc391981db76de39c915ac9453b831c41becd3c1f412cdf5379e9cd5c80bc6df92ecfc5005356d2aa000000000000000000000000000000001769e8b5fda96ef205750826f34fdda3587efddc86f69d37001c62938a90efc23a3ae150d223ef4bf3766ab7d86d80df0000000000000000000000000000000009ee24ab483300764bccba33b55b8889b084288ffda23d157f650df34125fd803624d88f2bd0c3c3ca51bcb57b9f4dcb58fa60bc7cff4edde18301af2348faa69ed4f31d437decb7d4fe51142d179e6000000000000000000000000000000000146001b68cd902fbb4548c3e7cfae9cf3c8916e462f1becb9918c8de42483ef65f418d6e93200e8ec95528928916bdb10000000000000000000000000000000008bef4996b8120613292dc76dcc77b07b24d4498d6bd35f5dfb80ad241ad97bd161cb2c5c96fb250b70f8aec1aee5b56c29be0b271d4e22d39e9e06db9e50845515880f30c5bfac80bca39a2d8d61ea00000000000000000000000000000000019d02e168efb5769416132b0457ee1ca74bd5737f9364623bb270e8218c96e71dc49403584aa0a7e6c15bf6948ddb956000000000000000000000000000000000510c0917796c7ef2e100c7656591d04c3c5968d688b36b93dd690b0a8ea55694157fead964b85a5eef1815cd5932819dc8c2e971a3a4b9909dcc5cc6a0de50286294ee15f441521e0f1d2c3ad3a76e9000000000000000000000000000000000dd05e53ee40f051037c88fd28364aba276c793047007a20f893d13222c35b24e14f6c74004c3d8070405621380553af00000000000000000000000000000000191d7f1863ab7bc4ad1ebab359499f4df75b8c7a58fae8fe7cca530c7a56e5ee1617b343765960ca4bdc0245ff997a9221c9ae0132a4886820115e71e280d33378a04344f635c769fffe91e89fa7ea470000000000000000000000000000000013320367c29a4f1527e8c0f3047f776d7c892d08988c402c55e90e84b07ed7f0932c3b5fd19f8d133aa839ebd90f6428000000000000000000000000000000000f8396d819d7aabefda680c8ad51c7f907911dc4da7c5fbb7e599e7f3b758c5e7c9e9ab4de1700f72f109d7206c1be0ee1067c01d5565d0f387516d9721f7f4e5253d5af8353db4a55500e20a95f3c96000000000000000000000000000000001413f6a4ec8b21a459a4aa33ea9d92614857df629ec16990939fbb8ab11fcc919a25a10423ded219ca5b94f71377dc2c0000000000000000000000000000000014a3320275a64ede5e1221c78b421c1e4474bd499263aa21e97af103d7cb62335faf4b85b5983c5865599b709e95efc4a23bf766a1e1c068e6e8e4b60391583ac197ade53caf0f8a43c53d1bae9f13e500000000000000000000000000000000057c3c7e4cf799d716483f1e8bd4e6ec91ad9566379683c54204ce46a0e5635fd9852b0a83328386643b2017b9b551f90000000000000000000000000000000010e3d5725beabfa7e4843eeb5bcbf6e7a54b4b82fd1768a3c276bba8fb7dd25dcca7e20e74231e2f7cdf0ff50cb9cf7c2c505d4fd8287a897e01517ddbd7d7ea9d26ae4f58fbca172e5265e2b62858b60000000000000000000000000000000009d85ce8e918ddbcc47494c4b194649fdbc8de31f5f3299ea4bec7c68ff56c7f6ae916c85118553b6a6634ef9b8820f50000000000000000000000000000000000c9a680e6389d447a4884b4e134a3e025f8679edcba56bf8ea2061a00e34d38c325319a8a5efb556fc2536886e225912908006c06ceb9188651c59d434988cb5b51a5a75772ba71875444c65ddf0f4f000000000000000000000000000000000f34c8793a9ec6c34c704159d18e385dc9a127e0a9b5f95667f58e68f5ddaa272f68f5fb55e105010fb656954f25927c000000000000000000000000000000000fa1d9379fbd273b05aaa8ef5397eae24cc14f83118b2584085312986c192d2c5e3a0fd8fe5c2d82be2ee5b006413a2be8e8724c80f3527de5f0b2b98ecdf0b8d0471e63c0763a89da8a21a70dbf8399", - "Expected": "000000000000000000000000000000001223d94bca6cb3225511b4e28797ddbf1b1e2d059c6f7c5e852331f381c578016671b5390dff3898f9048e5868b253de00000000000000000000000000000000093eb1c50064251cf043e7c7af7518b883a8f760deac99f6e10c3dc941fed718f2293ec2cecaba6d58060374bce11a8f", - "Name": "matter_g1_multiexp_8", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001429e7011c17bff6df1b3237a06bae78d427720af641d2614f32cfef8c537d5ae9315c0b179af0a114a486e2eff7bc470000000000000000000000000000000003b9caa69b5495dd33139d14146919f9344efe2416b665dc262bd09ab91f3f07d1fb5eaa3c3a94606e74ee747114f347e14282bc687a00264b4e4678ff238d5205f6b6fcc10040d9b4393e93f76297a80000000000000000000000000000000012b481abfcf8ecfcaed39a4277492641c420acb65ec809a7d55892091c7f76f82c02e7baf2a648cdd5cdac45113b11e90000000000000000000000000000000015d32649850a5c99a787ceb894a66b58066c9257dafc4a6cfad2887e7a19f8af69f8d1fa69258289e417954d064e63eb5307650d6cfc681508fc7b8dcb5291837582eba6588132f46ab8fba674a1f5af0000000000000000000000000000000006038134150b97e785f33b0accd0d1991c7b97aee1acf9bf671188f61a846a9603f2d3f56d2edc0564d1ea7967e112460000000000000000000000000000000019434ad4fe571da11e2de03c891d19ea2729f4bb7b7863ae0bb8f18b53852ad4dbbbe682da2c8568fbe96c6c9a7236dc7d6a25511ba63f0b7ebd2189cfc4c551083ac92b144e30dd81d27e59dd86e2260000000000000000000000000000000013786032ab493b5026cf23fdcc468ecc486cc8179c9510d99a503031d1fe39f9caedb2d42dcdfa17173e693e2344bd05000000000000000000000000000000000f1deaaefeedfac7f708092bbe3005be7c4b56499bdeb8fc742b72be7ffe4d8ca90e605502f1863d89a41ed794e06586eac8e5cf13de6db37982390c8b6b0474795f479584960748b7ffed881285e2df000000000000000000000000000000000aff14b235c3569586e67cf5113ac0ab32d442a1c07cd9e249149d719dbd64f8ec1b07c4241af135d3869eae05ddc0a40000000000000000000000000000000013d960e93447cf6df8bb48db45532d567dd2b0756dd674625657e5364f81b4bb94bf436b54bfe9afe8eb5f4bd1be90732c134652c27da0a0272b0783551ae44db6bf592ff299b48c50c550367d470b5b000000000000000000000000000000000f85e9736fd9d3f9a839f701b6d8a6724af55ea74d28f101f97229f4b406016e50f54a0b3d2087117f352bcc28b53d5e000000000000000000000000000000000b2717e98f9fca574ad9202bd76ff6e53c74c342d1b6049fe66310040217563a4e5df460f264769418cfdc443dc31e008dca9ff432bb483ad726bd20cf96b07ab6f07170a1449f0f1b50ddc6e1a02538000000000000000000000000000000000ed8e6113d657b2d3283e50e9d054e612793fcdebfc31c53ef4f417e63c76234900c627b7e8c433addbeb6a79bcc5d380000000000000000000000000000000012f0a3095ae16b5535192a932f188c62c3cf01d2184f8e299794bcba86d4573e423a0eda4e17b4b512c5e06367e470f6146433a0738ab1b044e059f49a8af8d85546d0e34eaa0edf2b2a6ee466c0def80000000000000000000000000000000002fa5630b261e07326fb51aa2bd897ab49e0b960f769e3207906a530fd759a53db8ae17fa79c8e8c889a923fb38888770000000000000000000000000000000013d49d032b888aeba7e652b200c91042f409a6a824d1aaa04bc402f94233385254a2d1f8605d15d04013ab0de9e40a94de0399ce1ed861c0ebce1d4e811ea0a3d87e21a54ae34e6b5e1284cbb9497368000000000000000000000000000000001495234b14a93a24881f3b4425dfd82b49aa1828746b06822097c8338da57db37ddc836a9abc46f7a0cd17ec08d36fef0000000000000000000000000000000013b868cdd5ed7bf90018873ae2ec84e4bc71d002483831ab7a4a19bf18feabaa210a729ebae606ea18ce16458e997497c2b034594fa53a0951e2116db1b063345fa42dc8c870e1146f1b00f626dbcfdf000000000000000000000000000000000f223490fde3ae0d7b94412b3aa86030e5d9dca805f6ab5b025ce8e9648aa02067fd29ab9a1915c2df7b2186f35a2c74000000000000000000000000000000000aa747ff7e24cf6d1dd2c4fe9db8c031b78830e98cab27cf765fd874fe6b7731c13af69559748c81f3915f9f3a6c63bac1e6d9c5f8911014f0f540211af5184d96fdfd47c03bf2d7bbbb3bf1a330017b00000000000000000000000000000000134f8ec87b5572c062f6f3b43ee896c2e019356214ad397f703a839d39215bec954f02d3f81e3442586ba9762bb9690e000000000000000000000000000000000218735ec0b5bf9b59dee7cfc70ec4c6f21aa129d604fffe824b7ed6b6346dc242757abbe98c19c02d5235da448e331d6df5a133d3332e1f79f41201f8cb2c8c8d4d1ab0f640c4de6bd6e34884a77aa2000000000000000000000000000000001510f39616d7f576980055d0547c603d882dbe85dd0b634577fae134f210736007345d035d815306db660de4a07fc24300000000000000000000000000000000064d356ad7bd2edcd3622b1fc225fe319f86b5f7da875cd57fe5adc5bdb6443c5b09d676950e2d069bd4303b8f9206928e7219a9d431c597fe9700d43da8b545072f5a27a9f1af99053ac0494087dca10000000000000000000000000000000014d4184d69d34b8e509f3fc7e7033d76b10ba913d6109bdf842be4c49cc0c29576adae2f75e6fa054bd989e26bda58170000000000000000000000000000000019d0b70eb45a353166bfaabcb661b46eb1b7d8a59a903cbf9e43ceb6ece492e78d7f1765922e981903153072a08bde098efb8a7a5e48d5f4a011a4aa0dbab22ede62c903414d005d507ea3d77bd47a6c00000000000000000000000000000000087bc015b995ff8a840fbbf23db2cdaa8bb2dcbc38e12b588bdc4186a77409fa2a4cd74347f568c5b516879b70552df9000000000000000000000000000000000b15f04955dc27d19ad2a97a99e0890e6d3ad17d29f6b30f866f8cb3ee7789038abcc24c63d4525860e64593af02e39f47f53e2c06664e1daffd7d9b114e12d4190d5d0fa2244d61a13da915c39b8d530000000000000000000000000000000013eb2ed1d78059beb34c3fce731d42ba28c485dbc74916e373424917d60bc8c402e331e8aa2fdf70360049740e670da7000000000000000000000000000000000eaf5b5e47a2312410035d87aba7196f3f0b65abfaac28ac80accc9d87a1115b7f175e59ea2394198a2876568986fbebfb109d9a0a7b62c7c452bdf0a2853c4bf65e5439fdc83aedec8c0bf73a16b5580000000000000000000000000000000012d7a2e92adfff3d37ad21dd26299188e25b628a9e9d7b54d2eb8a886e80de812a32db9816964f2c0ad25d9f0aa6ae9e000000000000000000000000000000000c7084afff475bdc0a4ec265a3cb3f87d862270b6263a47d869786495abdd4316f6f154b997224d3a895010ce04151c34b0a931b894fbe61115fcf52be51d44afdcb96c94117c75adffcd8729b0a699a", - "Expected": "0000000000000000000000000000000019c9d9833332c6dd40c200d53b30e92f1595c22568b31882e24b8fb17be41f4d2f9692ca1e63106c59ba574f8b0764c9000000000000000000000000000000001414165b510abdf0d4a32236cdbe51fe2b5c9a31942710a07bb5664592a3f1b5c821edea44bd7fe185cb53b11d6407df", - "Name": "matter_g1_multiexp_9", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000038e60d2dae22dee4dad0d9e0658741c13d165d3718c763270292602852625ac83c5ebc1a6d86c181686cd01a1891b520000000000000000000000000000000007299913b59e2d245fa489d92873b7d2bc8921191a34a0d7f6c5774757ea4eb3d667ff8f3e9293f0d2354ef03cb6592b68ce22e379ddb8352d12eb597c179c7089c6388542909876c69ee377b14054e7000000000000000000000000000000000b07454ff91e3f9707880c1713c69f8a44d70040b44d96ac74d196853c62f264ccbe6d9c8945905092d9bef665e45bf9000000000000000000000000000000000405c965e2e8cb5e85ef9e18927c7e86e63e7aeb49f45b3428089010f34eef9ff37eb005e6b86e20236dc870661dd68c61529338195b665f1b80c4b95b7c3a26a7229884be1f4be9d49e1274a9ec3f81000000000000000000000000000000000557c7f55246759b901e4e8478aac7b80d37edd5d6be057e5aeafe3d8da008e48c96c17ab1093a6a4fb39cbe9364fdff00000000000000000000000000000000158908f112d7cdcf867f1a5b05062b92972c2947be213ede3a7fed7a477fd57e69e1de82164f7cbd53a3f4f4bad551d744d740a72e6c8b5632314408022093618321c8c0a8cf2fcd9ebacbe43505a01c0000000000000000000000000000000001701edcc472ffbbf157b1f239968924bb91825754bd4fda9f13450162e82932b8f5f39e54ec5975dbe7dc744d6d676a0000000000000000000000000000000017d13c1f6d64af2a808c3ba20792af9ee9c626235ceb9ced3c7acb4bc864ba47e55e0945a430da47da1e87f015dc024724872a78e340ccb077259aae65d6c448fe6bfb64daf4e2b6ecce2cc9525e35a700000000000000000000000000000000011231262d0fcf5a4b92cc1ed62aa66a55be739eab1316219ed2bb8d3e939e25b840b75f914cdd3f07b3f57bbc07c23e0000000000000000000000000000000001eabe4a5782244ceaa57ea0b58ed1334dcb94e449b7fb905805cefb786e83af66ded006cadc651a7b2cb07c3e3fceb401a1d84826bf78f493417a06a800d58dba688800026638316fcf9ae534436fc000000000000000000000000000000000045bb823151b691e26b0e706b8abb248ecd87107a88c728e7a627a962aca7f85d4c88df949b3c53e2d32ef18f60675350000000000000000000000000000000003342b2d1a75300ae9ffbae66326936b19c7e59fc6f597ff09f2e5d50c1942f161dcbcbba00e4a46d87ab51074320132c5a3268a8ab5a12214b266aaa4eb562aa05dd19575a7f3ba2d549a25f1900cb800000000000000000000000000000000043d72d26ee669ae8e47eaa74199feb37d51f5c99151a8f854362469e5acb2c5f6d2c208e7d674efa189fb90275b835e0000000000000000000000000000000019e6f1b3137bdb49c534902abbf42893fd576a211b93c831dee90723c7daeecdceccd3eb981537d4fe729d6e48d70d6ae62a7b00d2be967df04ef56121c95c8736efa95e1faa0196e1f4485da82b3c3c000000000000000000000000000000000837b6a981e486865dc4d6d0c123230ced707e2518277cbfd0be747a8c9c76be6aff8b06df76f7c801fa34d11141354900000000000000000000000000000000011d745300b20c5ff1e607ef3a42ac31cc55e8be979b091aac0396748e607f00f30ff579321f2e660e90e8e5f9efd4f77a883bf845d1ed04e0664d814cf0b49cf8c3e8b8594ae5d2834c753851ed7803000000000000000000000000000000000740837b02d2923815914ee9cfad663eb7246ec8c56e632cdc2dce25b6e475dbb6a75ed2ca6790f5f83fd1a274832e8d00000000000000000000000000000000188034daa9801ea182b712da519f7524cbb9f641146bc0fbf77e72ecd066bd577672c1ccf28a2c4d3cb9854cb2b9e7c80f474e8f4051c4e91124c14895fe9e2516b315d805b79013caf830524fce888000000000000000000000000000000000014ddfffbffd0317ba7e248f648cbc98fac2be9f0cc31d6476f41527c25fe8d078207965eb2382ee1e0f08a38fbff7c10000000000000000000000000000000003e492f3667da69d44b35899f425af2ba51130aa6341bcc0d4d9646cc96b090061acece81ed16c7e75fa452818748b119b3a5790750825ab75ab7422f833c671b95c6c58619189db66a6215ce907381c0000000000000000000000000000000005107fd2b5b483173992b0f2f51dc24bdba94b5174c063b52c33a8cf84ce3adefe0efe08e6bf4de3e68189e495b39c6d000000000000000000000000000000000605e8540f1c7f5790c306643a68606581a16a60d33607064dad5572947c93f3846f66afae10a66cd33621c6a2dae30c6607a48ba3fa5c033a1ef90260ada14ee50c95e5167bf801ddbd3acb77c3b3880000000000000000000000000000000012eb811b231a07e27e997900be274f73720afe3b0626104a9d5aed39a3931595f2ad57cf6e8f12d5110cf38fc8e7f244000000000000000000000000000000000abf1b8abe848b91333b4bb226b81a33aff5b8f7af70108538a3c706da182476a42e0e5c2fcdf694c8a12f62a996c86c030db724eadd2f487d31dd4354b5c0321a7983aead21759807bd893217c4d4050000000000000000000000000000000009d2b5044a8fe22a957b6d1eb20454db2cff51e7ebb6357b3c6b95387b1fd810b94eab4aef4f0a0aec4e6a693903dab60000000000000000000000000000000012ccb794eb1174735b5f7700ef95ccb67691cd3673d601dbf6b2e2469521f1b2ed283f2f98a9cd601867de4640c9517988e71d0be8fd050f6dbb8b2fb3ae2a9e593bef7a5163255aabeb07282e8793e30000000000000000000000000000000003eb6e7ab6dbf66614ff5b55ed36243e1d9baa317f01aacbd7f3a015bddfd818c6764c0802e97a42063a18edd9dd091d0000000000000000000000000000000018571d50a947e56f63b26a4377678c838de7b315e655104eeee48b7d5e6f5ee5d876b3ebdebcbde4080e022cc88c995326989184bb87a586b8752733f9ce9ea06422c6a898f0f402cbcf760a7a21c95c000000000000000000000000000000000906d5a1691dcb7dfd5d78f0688e95de2e2f06cdc70f8760e43a562365939d3fa23ddaaddfd1ddfbd3bc9777783a7ab600000000000000000000000000000000168422a6171f5ae44b645b6b6e73011494dc75e98793db2424bab311990eb7730a9a45234afb78aeff7778503cf4e5a03d1dd9cc44b30a4623a4d14861688cb678bbb8b2f8ae3ba140f60e64c05514b10000000000000000000000000000000011c20d0c6140e0e11d3ffb8c28c6bd80ec495d057775f6dc331c98b0b0aba17568e1ba773771c703068dcc6747187767000000000000000000000000000000000f88fde780460bd75f46f593cf6fd0aa25ad14cccc061d9ae2cd8c20398f24e76ef614008efc9ffe1d1884df1122111b5639d80f55e24e05e3d943340e324f6738a593a915a6bddb40f01bf12f73daef", - "Expected": "00000000000000000000000000000000018ed322f140a351069f18d039ebded8630fd019e8c6c401dc760ec5cc6536bc2f52a6cd5400dca0caae95e4b9282967000000000000000000000000000000000b9666fbbe91ec8bd670b2a64571a34d689eac44c5b63a43f60da08df51b003d85c03f0eab3e2042b1175af3501de8b5", - "Name": "matter_g1_multiexp_10", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b42381a83d4472a3a7a18d2ba5266bcca254fade1170c6f55d442aa2a7674008fb35c58d5a638280e0ff7531617a768000000000000000000000000000000000eb5de05b5cdf9f95c5a3ad30ce068d5491006640be4c7f02b7498963b5769d516efb9a117c60c1c5fb71617d42c977142fe1e5b3c0245e5cfaa1ee8dd8ccc4ea8878ce2272d152fd8b24032297ac01800000000000000000000000000000000163ee62f1ea9219b921ae7ed0f121426fe9fb8fc0056916c81ea9e713f1a16e3f2bec6ed0e3e552a7173f8dffcde82bb000000000000000000000000000000000f5fa0e4980d3d2b92e98e76e5d67815ce55858852f03ec7b8809b02d4b1e9e1a6c8b06bd481d9d153acc68378e779fa253bdc5565b6ebc219a75ab74dc5ffd304c94e67160389f87111899ac07a71b7000000000000000000000000000000000cfbefb41304008b0e7341451f13d65681f0726544f14fd1c0d02433d3c34a4769f1456960cfdb11b6bcf016b906228d0000000000000000000000000000000001adf387f4feeb3845b12449fd5294802ed30ae211d0837eff1b22c3fedf538ec7119c1fe69ed7d595f7c0fdcd54f684acbf64f93f6f85805517ddf0358ecfea1fd58a3666b8dd9d3773a28590fb8a13000000000000000000000000000000000d736d3b8b586e09d6ecb1ee2d7eb28bd68aec60234e90611da8f1e1aedebd9c74718d41a89186a4a5dcc3f7cc81e99e00000000000000000000000000000000000ec0e89da57affa4686494e8e0f5517f11532f6e294215bd060c370fc64c26e34ee1e2d77cf341226daf84791f5e3cd9d3f97893eb4f14f21f68110f612a444815fbf2f76b8399ba6045c8a44270df0000000000000000000000000000000008fef795f8bfb6de5feee020a9363adb1c26fb521439e405570b4e997f55af5783968b24d2e95144bcb6b38e4ef9497c0000000000000000000000000000000004d4e31720644e8828faeaeff38985ffa4fa2f7bdaa476b5c4d7eee81c89491eedd3f4262effe118a4c204eb555abfbd05fb554531f53b8cef8d93566df80878baa96f92bb54aec19445980b1a1f6c3400000000000000000000000000000000195f8fc4b1ca0c7041810b02bbc38b8bcd0711dccfd80de2b2f357f4a732e65492d57f455e99fc810d6f86eeab0ac101000000000000000000000000000000000e3010ed298656b91b5aa342f6be7250cf5504fc3aa26a2c7f46f90e852fd7799d96a85b25e6066b7d24794648a81331d79ba2c485f0aa0e35212fd7fecf970258903bd2427c4c8b97c2c425ee11909900000000000000000000000000000000192cc18dff89d9a94e6f0498419ceb9f21d70e42a1b9b64bea093d67075d499184d7b2106f74d31ccd1863beeb7be0a9000000000000000000000000000000000b80e940dce71be82106640d99c121dd21e99ba459f0dc8b1f11cdffaa0d8ab295b9711c23de1f4bc35120a89948b91a44c7017258bb979cc9bb8acbd3a3e62eac7aa152db46cd7398ef07edd031e4f6000000000000000000000000000000000b53f55edb182dd08e2c9d0ee43aa3d734143b54686295410f80086d3aebf6fc681d1150e808d684f47b0eb23fcaf629000000000000000000000000000000000d73442636f4d5dd1374cfc7ab29b995420995bee9808aec29ef7d1aac08c0ee51a0390330a863295af6129b7e8171d82583e821328ae90a7db16b20525228e8d915bc8d46a642cb0a06dfb64168cf1c0000000000000000000000000000000002bd8316507e6eded2034cf268b2b4660211e6bea2e82b3e3a0902bcda0f9ae9980b401f36178f681691ee7c10dc4ecf000000000000000000000000000000000e9af98fdbd02ef62ae90f1e87c4e7a8eb2089204b1c58dc6e59fa32d001c97f22740d8a13ccab23b5a8842b693504a8506f22d323a740553d6107e651c192c1dc6e0a0161a82351f125f08c77e53fdb000000000000000000000000000000000aef5a5d5b46d340fccdfad359b0499a5c62ff4e5d9b9d6f7a5fd6a97e96820b7fd226e7a2aabaea392869a40cd38e1d000000000000000000000000000000000865d32d825149d26b60969ca567ca85af5e280b835cf541b20b0a4db83309dd2b5700f802ed9106af73b912dcf9630b7f1bc0e1ebff8f935330c35573f9fc3b900606da9cca9a36b425977af47c7ca600000000000000000000000000000000153310de30b7a485753dd8443f8638c12b21083f6133a1c093648bcb566b33f73631c6fc558f32abeb0d6df8430e61a900000000000000000000000000000000005be397e9f77556ad952dba0540f46cbc7db910d5203cb976e168a7be3a3b8557c5f08d51cca9379552694a291d67fb4429b85fae16200da6eb8f62e95e027c24aa6ee2a145f6ef225139f29aaca29c000000000000000000000000000000000cc75210c78f2e7903b7c33379a6ab412e92f35de51a152cfd2f4a5d122f9e558b617d8a09670990b7f056e95eb058ab0000000000000000000000000000000000aee8eda7c1bedd39f97efc60af110e64662b9990257beff15ef5e7856e5ea388df058ed8aa6dd93cf5a81ba48cb88854a852baf21df9f4ec8d711a48e6ffb36be8c09c8c60eaa090876236b2eae37a000000000000000000000000000000000f396976e55dc0c46fc4543a8dbf690b8da7b6010a03e04c9010f01abe1b3beab8870be0b6a2c6d6afdf85c6fd38d8b70000000000000000000000000000000006c60eeaa2d94b571df8a6291c2b12b2ce9f17f414264e4af2a006d6aef2d70436ef0978139751d4ccafce200f16f06113814a3c6386b19f7b93c2c4e0eb1568e8bd3f0012a1ae1357b127c33808aa04000000000000000000000000000000000543f8d9faa2b3cac2518f1462c297595ca10d8415143c8ff3feecfa58b648d0dd0c25156287b2f29f3b6f9a60f02701000000000000000000000000000000000be673141c496cdeab5ba8604e081ed3006828c7c877d8990efd29798c1ceae3093e052f1f928fac0c5cf84174283844aba0fb0440b2461ef64af6ec5f15db381714fce1da6e03ca962cfc94bba26d74000000000000000000000000000000001342f79c96ba0a29de9a77cc2e10314bf2e15a7d192a90af9c025e2f23ff30fe49cf239b180cfb6f8c35f95c115777390000000000000000000000000000000011f0bfb11be253b3680817af2b929de9ccf06dc574d17cf6680643b87e5fadd06b54224f155c1393c870c2dd01d6bb07c01749cac36dbbdba5662687fd1ea5391ef9d0bbd24e05bb5904a20fa6a1e11e00000000000000000000000000000000183eab3c2a127818862c6cb42bfbc9d59c51043dcc28c68d3fea08331323c9dd50cc34a4ef66a97f98684a5d9a982a1d000000000000000000000000000000000228f8f774bb68f966f3ffab5d0928a59707d6fb4f6ca84fed831a8212f71085cdc27b1d52909bdc005b3250f26cff3b9680fbd6e6c7b1b14b000d3d18bf93242c74662ef108d711d85d8d442e415ffd", - "Expected": "0000000000000000000000000000000017ddd94df17d52e842abacf3467f4461e345cbb680ae624f98c6885e40b17940bc240da17ed0a1a45f13f2ce4ab8dc100000000000000000000000000000000005ea5144aa5d5393b98db4d23477011638dba465a542dc28691ee2807ffc08413938ffb74e16c7afc507f85d76acbcd1", - "Name": "matter_g1_multiexp_11", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000023977b65312306b1a746b94bebbe79ccef0342ce833684a273d8baf74e0ee71104d6c453acf02d0c4f3909144b1a3b700000000000000000000000000000000050494df74705eddbf97da56a21bd673e2b0d3a9cc157168b8b413a89359c9c48f09e756f8e6ecc67811d4bd8043bba91ddff10527bb64de6ee2e3ab4959ebef9e7a6964b7482f9fae396b2b9b0cff9e0000000000000000000000000000000015862e2e3cb73ed2ba6b0b69dd9fc4c308c0a79e5cca2d2a42fe94e9b029b22b5b6aefe0503798d78d4599dd5c201cd0000000000000000000000000000000000c49723dfa37fb1592722b14e6c75110cf2252ad5170131bb72fa35bc359470bbda292fc2a459dab89900eb251e848e12943fa2957d267019309f4fe5b6725379d893dcc270ff7f35b3811ad1d8d12b1000000000000000000000000000000000af2d03791884033b8293fb636b0c569d9b008b075c6c71ddd7b0c3f5e139a17e1fbb18144d1ecf491d2fc40b7369c0d000000000000000000000000000000000d680b707e32626219fba862cbb18e39e03a8b9ac78f7bde619049748f7f0e49cc0223f1111dfc1f5c851229e62a9cdc1551a3c2d0391fd8dedade892e8e2171e652d2a9b52f2288451c55f77fac788a000000000000000000000000000000000b442117cecac25834a442ef457061634d863875c10e1809a3b9464eef6760f074e06c046a74bfb34f4d16255cd4f62a0000000000000000000000000000000000febea79eb8102b2632b6fe3151d9d972d5dded2893a117a6cd7e2bb662f042131cf06d04ca5c88c8535155910f9e008eb2fa94a5c97c28d95008dd1fe60137b34c2e763292d1b86993c02790b8c91f000000000000000000000000000000000d355c97dcf055181b8c523bbdf7eabbf064159c15532bef1e1be56146d72c08eb5d6994a3be7d6f4a4ef204f0e6d8dd000000000000000000000000000000000cd6d4e6df1ef7cd5fcd360e8aac511a3aea1f3e29536c193f4c3a2ff0f3ca16ebec620cecddfa8f27732eacbea75500f72ae1def6c988f9242bff0e683b8d2a5c1aecfd6ebb9442131ec5b5b825d0f600000000000000000000000000000000072ff95f5cd9416eac2cd83781acf856a0bfa567a079bd3cc909eeaf5a3fb31090e3e2ccc3acd44b6b04b47b5b8609a7000000000000000000000000000000000b7a39ab3ec7de26c86eee5d8737c7ae7e5969b03457b7b7b5720e3492ce254a63e031fc477361606a24821830d27271331451748146f0564ab0d91b09db87e8a6ba8b14f8329bc041911616195f9fc0000000000000000000000000000000000886babc1acee93b5f96e4a0700805982657d15170c77468c77000f21978f0cc154a265de2f766d6f7f8600f378b219c0000000000000000000000000000000013cc47f0a1e5f7315e6ddb9003dbf901824e419854d234676e4a8593bc5ad4c15e8c59ee6985d0b729e7d095e9b7642416d298bf591bd927aee24a37c5ba508c3bc121f5150fcd1a70c1f27a79da7d73000000000000000000000000000000000567f08c96b8431a133cb284144f6ec8f7c68722f18ec257b4def0a18a754507eb477f405b8c256adb797f45ed2755050000000000000000000000000000000004945b59bc84df7b793dc759bc2a3352b3eecc5cd59bea7a9560c06ef25828ad2e9ccdc6b3beab7a71a702b829208b8556be810c3fa86e35bc935fc2b27971c9c41d03c8ab7b6c8869db90b6e0986ef4000000000000000000000000000000000584ae62e22e0c2fd733cf2093f7a1f3c763453cc34a7a7a4548d8fd43c95f13be06da4e41f257f6d38e6e6921ad0f6e000000000000000000000000000000000dc803ba6a45298075a8cf45939a61760de44d22407da6ac0d63939918daa6f78e8d0b7cd794256f992cc89b8622e737aea4445926775a6baffb4dbeb249dfe3b3e0c29f2a579927f540d8f6451553ef00000000000000000000000000000000090848e332eec39e026eac0e6416d1ecd5aee8b4d82712b6c113da1e7d38901470743af43bae951d4141592f6057caec00000000000000000000000000000000140f8aa557213d49097ef315a18ae7e62924a97c71139555baf08c70674031934b629a457f75bd801af579f9fe9395579ee0e58d08779add74b68dd75e82df172b719cb5a772b0bbb34d3401b9f212ea000000000000000000000000000000000e29d6fd73f56b4546358967d7f0080e6cad97531e3d672a91a6dd121f35cdf0f452dfee1ad98b7c832c2878b495f3c100000000000000000000000000000000050fe9818b36baa8ccef166247bc673baa8424e19a19b199ea5e9d0baf56fd68cb339fdf5d041b31545e28bb2b8fe32c773d07cb9d20744a2c3ac88082a8d6606acdc892666753793a2b8bb81116cc6d000000000000000000000000000000000c13e5062ec580886d09c87c7cc72f7f19227eca99b0092a7e9759672ed1405d21fbdc8985847fa1b57129ac40bb036b0000000000000000000000000000000007d6407d32f846088759be5369c5ab66d2f512f00c93eefaca86a86bf7b1e3ef39ab85fb6c317c28c4e331a19b927650f6bb1445e9146b117bd0c95b009fba670a5391874dd314cefc884bdb0a4eba6800000000000000000000000000000000112839aa4daa7b0d614dc6a555731cd4b595a0495f2a2f0f1a3b3fa1b603c36348e265145583e8bdfa8a2a26c1f822f1000000000000000000000000000000000383bcca42f2513ce42342f4bab5377ec276bf0f1910718c7203d450f15c5b6a3648a82e4cd1222109171030eaf05292d4158de4e23d793ba77c24a70f0ad07314927fff34361b0d74b25e8922512d7a0000000000000000000000000000000010aa255df04dde054fc069473dbbcde9c68dbd71048b195df2b23e5471e5cd39eab5658ce689ca09db80c72e099907120000000000000000000000000000000013cfb46746c9bd13aa88a24ef3097b35ee2302e76b19ed001baee8cbe5b19c2620043efeaf81697ce48af0717a1066eec629ef41d5a2ce49fd81930406f19e760a47074e159ce372dd67e7ea46ad706b000000000000000000000000000000001888735aecb7125b08f2a840957887fb5be0517788a8931fdb8d280579776c5ad70e6454303ba23908bc6fb864a4ea290000000000000000000000000000000019479631b9c711f700ff2353aac97cd0ddbf14669cc046e686ef19ff0bea0aa74b4bf771882f7226de0d4fe356301912c718651715ab786b4855092ed21be41b499b7824d0bcf68ad31b31ee4cb730d50000000000000000000000000000000003233c1edded239fd465f7f7833251b98ffed6180b56676bcbe2ed361438d26db671c03a6454a4fda34111e358eb2cb10000000000000000000000000000000003cc9768ad0576a34550b913a895e2687481c6adb3371bad5cc8f9792c61aec555a52bcb267c337649fa00293c9b4af3c685a2872c4980518fe60c61e2276ef53c007166f7eceb355b4cd533f42c00b7", - "Expected": "00000000000000000000000000000000117879988edc3cc57fe19ab04eee6f9e94a30811b809afe922d63bc3d785a3a581b69512180beb89402410a4d8abf6620000000000000000000000000000000000beda376a5f1499882c560961f8b0cfc44c712d6691677ea24db18b138af8a21a5a4fcb9cf5814473b0ef7c00719700", - "Name": "matter_g1_multiexp_12", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bc83829ec8e98081abac2fa8e0572e819b570b2499d4cd1e6748f48c350c392f5d52c672dd0bbcdf1469414d7ce929c00000000000000000000000000000000007d1574eb65b391475b49857766c808fa95ac2a78755d8d740d2df90bfa9aab3dd5c850d536c9794f6cfa2f004b4550c067ecd54e9ef59996493f846ecca63bbd7ec28da586f0b8d41bfdc6d97a35cb00000000000000000000000000000000022e4ed74f98d69a9bb1037a307eed57210d3ca92648ca9c54546c7b57102558ab12f5d2bb46502ba3c07529f64b72b30000000000000000000000000000000005ea660c44a9d36696a899ed1bbef1d951656f2eae553f4f124ac9cee3d7de13556a7884ffc07e20d5afb7bdb9c6f1638b5112baca5e0f2bfb885c5041189612918d203a117d886bcb3b27df7e64d17d000000000000000000000000000000000f6f9411caaf7bbed9b05368ed8bbc35a0439a5c1ae417215d10adaab203aa0a607642aa8b94f4846add8f5f8db755530000000000000000000000000000000012eba1de04ecff3405596452a4f5830bc6c8af2ab0e84115a8a04a2cf60400eb741e8eda78ef733338494fd4e7b16f812db7ad39ec8129e9e9206bd46cec6a8ad3362ade1beaa97befe148f6c67a9c2b0000000000000000000000000000000009898acf9cacee1f5750d54798a4c31796fc471a17c9d2ddbd00262f5a82e3ca968c3e02334c29aeae9b16d8916def1600000000000000000000000000000000017f5a3907bc14b6cf182af2778c88704fc6b02d2b47bbbd6e40a448a89ad1455f868dba330452112973ab69489534ece2400a11d9a67041824b97a96f0ea9da8848e7990373655d76e8bd4eb84df5dc000000000000000000000000000000000e782486684a6c3fd7f5977fa40038e8a9ac0a8611e79c18ea5328248be9ad4d95c63ba9ce41d3b4d85701283369063f000000000000000000000000000000000a98e9f649d2431991dbad1cc7f4ea0c89a58bd7e75e4a5bf7d9a728943363777c1cf84bdb1853a976e4e66a6d3fa8cbaa2d17c409ade92566ddb3913806723d41067540a36a9c283bdacb273c5b258a000000000000000000000000000000001171bd468b4d40e77b8264e082cf7a168d88ec3c21adb6c33f215e82f5ff3d0d2314e0fb12d7ec93aca92532debde74500000000000000000000000000000000099bc823a44c54fd379798eed2559d95275b324481c248d452a02755e1b5a48a7b0694b637dce4c21ad7d73a63cef2a3e5e3d21862b64e09a0893ece646de60cd66aa483662125ffabc46cc52f1cdefa00000000000000000000000000000000190f9d82f079757ad752b17b419c63ca09e3c8a23d0f56b1e738dc8ff4d588a4a2360687679e51bd75615c18c49103c400000000000000000000000000000000191b91de53dc0807b537540e81d9219daee48ad27de9e5ab2980dcc09062b80dad2a0a9024c5b0465e04e6ea2b225d0249510ab1b7850badf58cacad67fe47135f6524f0d160f3013e8ff1c881e469e4000000000000000000000000000000000c8f48d3dacefba0e1719f74867b539a65d640d2372ad38bcfc43548f7ad3d8a04337878529119b9175068b511efb04c0000000000000000000000000000000003c7b5c11985fd7ff7c75e2cdd8670f75de655aa81f6b99206ed8a344f86ae85d2fb14bce434a25a5ee25c903c238341713aa69664a8c721cefa7d6dd3fe9f92432b4d350621d5297805fcabb21ff8c600000000000000000000000000000000055e115a8a7edec3a443354b381f584ba13a5802520c54b51ade1bfc7c93c96c7cd66254738929aea2e88edf2895d82f0000000000000000000000000000000001bdf3f4b489cc22c6f57a1eba23d3348c5567d0dd1cc82924873813b92a0d0b2b90727589028b9844d351e13c6e3868c040d8bf0a787346560fa3b100b2dd9adb3f7ee716b8103abdd9609363345ae400000000000000000000000000000000041fd1625afa48a446454d6613c17cc6a65b3ec8b8f2125c0eb7b8e5d07968397d43969a6579226f496d9b24dbb71b820000000000000000000000000000000006131c506f243b5ac40354f826ac1838839eee9f61301aabd88e499d40e57df3122edc8b36f0a8b16b72f9ac783efd3e17b811aeac4fb7d91abc655f8a4392176f9060346073c957ef903e25d10935a000000000000000000000000000000000113a08cd0728cb3bab3886681d8cd4e5f14b3a4a7979f9929ed4d8dc77de6a65f7bbbf8a282818ea3f21e6ea59ab1f5100000000000000000000000000000000032e95b26193c9768cc9967c9710c7695f57fce8a4e089f290526842963504cc8c99981bed3cc7d827eedcf686c813c3bd1f096026159218836a46b9801a4f0c43189324d20220aca777b826eaf25752000000000000000000000000000000000ac19ea5cb7169ffa2741bbef922e0ba307e2bff5eb67fbd2c1545bcfebb79948489605f3c6c072444093e996594c95700000000000000000000000000000000111c277e16440fc3f0cfe16bb81b927cf76553fad040c1825210fa145240abb0bfc8a40a016db15844b8830d4d725da3f221dedfc21098ff9a9507e493d0fdb1efa6029fcdab23a016515078c76f7627000000000000000000000000000000000906df246466ac720b1db9445902aeba8ff5c747133b037f29b33880b3f511621a0241fcc46adb0532682feb4e8819bb00000000000000000000000000000000145b356e384183788358353a69c49332ca137e9faf30bbcd7a67434a980c27630c3f21781a36fe73e82459318b59331bba5b30d1397bf28100f108b84e05107ddd6cae2e82f1973ce187e8c3a7d02f3e0000000000000000000000000000000003f2f02b7ab2d2165836349ef8f53e42d223f4f6a892e7b72db93362de3929fcbda5edc4606766fe26ddfda9d09b283b000000000000000000000000000000000feb10a6ba91dddb0829cd6b95a78958fd55cdb120a7237a2842df1a2007530775848c3976804824698a4370fb022bdc19aadc83d1db9140af303c0492d2b9bb9e2b53ddb62cd2132bdf8ef62aaed683000000000000000000000000000000001433eeb265f1d57027a80189806d071edb1f5ccb97da0b5e00dc75eb88304ef2eed287f5d74264245684a1677a23b3f5000000000000000000000000000000000be2d2b5fd307192ef8a0b2b4dc9970c112a236a71ee899a0a5147012a206a0274d34901594f54bdaae26f2552da481b87eb6fc40b00246910626ab66bfbac96ea09242d1d70496466e4d681942050700000000000000000000000000000000011b50012e0d92c0f74e3b6e83d60bf77e710dc03baeedc949c1af218bcb87ca1528a745aa819a5b615ac355dec360eed0000000000000000000000000000000013cd46e3cbe008dcec36e64285173b7d545359c23fea32d3a1fa2918c5c5d671a87d90791b70a740564c0f731fbb32013bb5926f36808c0024ea7388998b4cc8c6c48d32917f6456b39d514143c6eded", - "Expected": "000000000000000000000000000000000cd7a2b89d286a421808305db523aca962c3f253f6defcfee9b74bd7f00b3ca8521b520376659d584b03fc5dd736d3f800000000000000000000000000000000117b8b8a8e299cb0fe3eee45651069a21988a2421b1d349529cbaf7362425349148fa043581e5fd275cc94a4fce44732", - "Name": "matter_g1_multiexp_13", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016b98dda34f703f90438f5c2624c1ccc870b18cf8eb964800ec97179f67f82c521b1cccb1b81ebd3484da1349e4c0cc3000000000000000000000000000000000c743850f15041ed9023ce296570036f96db4a510903a0e7971592348651b44afc0091c8f0d6e86bbed8bd3f6b28072af44b0204792359895b448bfe6ffaedc14d54a6d72be7a49718c0a933807a399d0000000000000000000000000000000007df1648d65d140c775f729e7739a807a7f430de0711671807a7154a8e5723a2b9137175d47bc319ca659faca10af23d00000000000000000000000000000000199ebb99b555fa438587b9badcf5d7858029e905b97229f1de4ecc1940ccac59503e0e1a99c9571d50ba39ac3619699bde25977e7426cd5652559626ff8b195ab7ec679de987a6a22a6a0e366759dea0000000000000000000000000000000000027b64caa979063b420cff77cd259e54bf86498f87e7297651f9bbad6087a8b4b704b27746db53f8869d080a22363c90000000000000000000000000000000003239455ad4ab885727a25b0cae5115d87ac9ccfd93120ffded5130ac683b3b2485fb358e3aca3b6cac4bb3da5b4210d2e7ae497b44f531fe203a599622954804c06d5348dc17eb1537e750006584b210000000000000000000000000000000002f14454852a72159581b8a931d863c65170fa9280cb811c697fd067a505910d17fcb71b27963c2a6a02264aa0e1fa04000000000000000000000000000000000303f0857d990e90e19a076d2d331f5eb7fbcf102dbf8d4cb29f159fa2277eb413c0c10c3b501cefd9ca581ca62876c5e073adfb5ab96730c53015a4ab6210a35a37b2331ff5123e00798c33e040a91300000000000000000000000000000000192b3fcf7dd2534f226ad51f40e7256064eb788e7c91b1155908fb752ed4e854fda44af13f0c681fcb818eb4202eb64100000000000000000000000000000000125b51b4cf8e9427db9baeee0417b02c2d296ec4adfd437667238ffe5137b85b40fca4fa705f81d0b4b6d788a8456f1fe6e752d40d411f1ee6e67f48109c9a059226b446601047a2189ab815a3fe13c400000000000000000000000000000000130798c851758638c03f90f9181814eba97c5f93de85a71bbcc360bc53e4491e8fea38ff8c94061cd5008b0333ff26af0000000000000000000000000000000014758dbfcbbf0e1c78fb3ad4945bd300a74f2555338a009d807e2cf0e5fe582729556bd3ecb79db131ed9a72c3362c37e657fda33cf4ed1aa89dbc19d58fbe3043acb5795dfb8c0cb97620f16f8f243500000000000000000000000000000000093318a1c189c8957c9736a56a4b3e8da13bc8a303303bbc106148a0a7f319e30f5dcd11787dcd3424255c7a02cd3e760000000000000000000000000000000015f0767a3a1e3c448ecbd4ac8c4c70db6daec95a1e4b3a69cb5dc10fb43f8ad030e360832f7726cb166e0fe5fad0c860c73458e18d6f832f362dec7c49140e6523ead045131a1b719b0c836c1ef13a79000000000000000000000000000000000c7143093aea0143c58e2c459472f44b6b759a3f036aefced481eef6fb3a1b2af72ae4cc4de06af2a8a99e27cf9cae140000000000000000000000000000000019f44d1120d82e50f7da3c1e87a47d3433152b7141e9085eb54e04f30f5931d067f9ad559cf5d092dbaece723e6a724138cb0a2b191f538b30187dc730a8c665bbfce8186883500baaa6c3242a0d14740000000000000000000000000000000012a171d46d2bbfab83d02e023f5edb18e353ea82174d1a1653952bbba234c7de4fd5ed212c81f795e8c7a0b81e37087a0000000000000000000000000000000015dd85eecde306a845917187c404cee066038a764beaca9a58b859873b06652800291506b4c995581866a3c2bd7f19618a27de64d41d13ab67c1f7b1a7390ab4dbba7d219dfeb31255f9401d5b3c62f800000000000000000000000000000000176e512a4122ef10ca1fe6626cd2c839d4c573bede92092e5ca55b0bb936de9b62297b2a598a033e9a7e49ba9aabb9190000000000000000000000000000000013bf0f4c0dee3c9298192748497803a906e4192333b1ca61deff010a63eb8e4cbd63c7bd5b5546540e71bcac6000eb5380030798960729d63db70b8bc3c0030e80d9b8ae766e3330128557e6c34442f600000000000000000000000000000000066bb65bbc3f8ed9cdd5cfcdb121274427ab7dff904551a60be48f8197c84400d54ec27ed25c2a09687f1067c10edae5000000000000000000000000000000000afe1e97e1dcee30959a6411328f0d69134bb4c3a0d5ac53b87f254593f7cecf3070eaa9e19de76ebc6e1052a41ccca00d32b6969af54dd345f42320ea96def3c6f4dfd4e22a82686b7a3c57a0df5250000000000000000000000000000000001439b3031d7272f92c7072c6b44dd3a1c328251d34e1fcafc5f864b7072086168fa6f398d6334fe7fc56d6fc0e776eb600000000000000000000000000000000090885199f56df470628357ad224e19c29dc435ac54b8c17a7df5cdd24c3fdfb136952063dcb446ffe271ab5775bbc51969848f1b8b36bd28967b762168edb451322e2f0c4b99b7f9112c9a66093fb3f0000000000000000000000000000000011a0c8f7d76a36e605f193efdb5f7899d7db5b89ab0603dd6184e69a7e51f0d7e12f466fbc917cc5b6dd6d4a0bac16c30000000000000000000000000000000015dfa17cdd22984bec570d2ca24a5ac373f6f174b66aed70a15ec892caaf92c73ad3d7ef11b2f4a0104df8ec5397f5e9957ee08a513c5e22bbec04722575a9b4f3a1343db0ae5beef4e66fbbe1ac90440000000000000000000000000000000004bfe701f6645589925b34c1117cf62752b4e242e38bf056ef36515338a5c3698f561d65b237123677d926c1616618ec0000000000000000000000000000000011892535443daffffce0867dee36b7bc711006bc0963e6a061066b889adcde877a8dd3661250b6bc48064ed9dea304168e0cf0f590f77d13819001916d2c58a654d0b9d3c47c842f2d649cb2570dc0d50000000000000000000000000000000017666cd38f1e7139fd032a79776301e4eef7fc22c144900c711f1568634d9712b2e3566bcfdd152faeef20b47cf6cf7100000000000000000000000000000000150c30df0eb5945ab96603b0f36120a4f697b6958a9929f6dd8d1b8a34a1d1d3f1a34bddf9ff7f1e105ca23ac34b6f7671a8c2a479dec43d644ec4113142e666bcefd6d729d4faccbc147effa836ddab00000000000000000000000000000000107f9378f695524614ba000d6fd1b72c5eafc4ee60c5ba36ddb72814936403fded547f8d15083186f7f5f5d94c1ce18300000000000000000000000000000000140bc17d86038d4fed0580582f55d90259b460ddaeb37a70063d09d83f5fb6c803f8b467927758cb7cc52a2a6f8a84ba2d2d59a7f138327a20263d6338d2a92fa5a2f741daefe9aa81d06f20a6fe3641", - "Expected": "00000000000000000000000000000000179ba87e1596396fb5cf88f91f56e3fd6f01dda6f95363be3365bd42960ed620b7648863524c22663bad20d128d22f4c0000000000000000000000000000000001ad84c4e62b0494bab4f2ec2931d2331d88502674a1bf58b765eeb022f3d6fbe8f8546818d965a8be79a94be86292c8", - "Name": "matter_g1_multiexp_14", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007eefedc0360b258ca2bc9add8e23b9d535f35332e7a35952fd832d7fe3d448aac08a01073876a21914a501dbca513850000000000000000000000000000000016188049abc44154b244c6af4e115caa14a977efcdd524ad78e5dce010f2f48259708d14454630eabf2318bb271315007740a826d524fdb7969776bede5ada468a0115229152907cb2b050760c18c8e20000000000000000000000000000000010a19a7cae27e432b77c77d26653c6f17507413a5037621bdb096fa4f33e68dd86d5aa3b52fa54655730fd88415c3eea00000000000000000000000000000000031925aae4540280dd6d08fc53478fbf05b0ec784d04abd04c3a8dadb04ad9adebe87101c6401ebb4a808104b3d7e88fd226f56bf3935ea95d976fde5790ba0584e5bbc78b37279aed8e50389899b9e9000000000000000000000000000000000447e249cb49d64494fb1f1b18c94a44791fd8d4957bac13df1f992480f72a14c3aec517184700d87200092e866d60ee0000000000000000000000000000000018a12284086bf2f64297a65f6c8b55b4ff3b791372b88aed9085152e24b1214655a74a182e131d7023f949c8cd9602dbc133e1989ac82e4d1c9852a6c7156a34b05784a58231d59e3cc875ac5834d5c8000000000000000000000000000000000780d3f5c10ab7932e3e3b45c942d1ee2a12f28070674d9c666016d084613f3ffbcccfb576fb7779feb2d0e614106c990000000000000000000000000000000000ea320730367c89cf162305c69ad594d8730d71a910f53143770f50024bdbc40b7d2486b1eec63b1ac7dbaeb51ef9640fdae1b53f6442c4378774a981c90d282d5f8793feb2334470c873491e41740f00000000000000000000000000000000049ff517593107482da6805fe4ab49cfe9cf71c9a95eba00091511719eb76db98f71f089a701c6c136b398a40dccfee700000000000000000000000000000000038d1566f1057bb2da7813c39374b79149e598e1651dc3541a445264693495dea35a6515dd2173f7de43964dd5e8257d70f1de7cc5e6a2cf7dd4b6e60ada67ca47e7b9417bb5f599048fb0c9b2abf33d00000000000000000000000000000000016baae36e71ce87a6dd7136f7572788c256ef88cb73e550641f14a557828e06ad64f001fe78d69465fed92b67e8dec3000000000000000000000000000000000613a6b87249bfdfd01016ce920aaf902de85c066c2d64c866ca0a93950a1a971cc561560a4122d9a766e38f9dca9239ca82cffdf59b742a736ae9a6d36f7840c46c20c126ec054f47ad52a22948d721000000000000000000000000000000001921d310700ff4e2868a28dd29ae6e0216bc27ee9463cc8dd2823a1b4670abe973859e86719142525ae5c76e2df0bae0000000000000000000000000000000000b4b4952e96be92ba6c78037e529c197c9404cfb67af04f39d24045c742b34a700057b2cedb3193dad70e64944642c01fad69492cab4ec7eb89ed37f1e7fe898ff49ffac4ef2aeb75d9c6b544109a08f0000000000000000000000000000000001dae69033cf21e6e1618efba143426df1501250c82f214ecc9ccbf957e685d9831533cf7f747fc22309227aca1d1a2200000000000000000000000000000000114abe65155656679b89a11c7961435ea9f77fe2f957833dfb61b8538695e2569e509f0ee2c0bfff75f83d9399a3d49b5af71c9baaf54967683f8553f72abf789da465041ee5a92c9ce1ad562c91c4d700000000000000000000000000000000128e019ff92e7171d3c791bd4cf75b0f47c2a9d8722b4a8279f1178db6dddf8a4c00083a935168518a1c26a56b23624f0000000000000000000000000000000008d0c5f3300e73682f4756e6ff1d6722dde576beb587301ded34427d6935e59e76cc8a8cb0ea5f659db9ad5435851e53c7effc9a7fe773a420ca430c58bb94e7baf26b9a97b618a15e7a18b31e5914f1000000000000000000000000000000001110168c2dc1c2f0df0dc645970c0feb03bd644fdbe1576d5e5a8090282bcb81ac9be738d18e72a31ceeb5ba826b40290000000000000000000000000000000013fccd2429da394be698812af6c3288e89a26f0244327cd38bc85d5c3bb934004bfe24449534b7d271add7a279bdc8512d5a3d0370f4a58c21016d208609f1d3e7cdf43abdb85199bfc67dd12f589b8a000000000000000000000000000000000199b9c9772a8c1bb0c015c467098bd38b5f73e5d0b3f627c8279b8dc853fa2952faad01e7be353a2762b8144cc1614c000000000000000000000000000000000f781597005df947eaccca59939253b936d1ae84805ec27dde0dc707a4583af408672addb2eea607a14faec9dabe61ae3549b86ed3fb880269be22b9cb8be6f24385bb5e24bba81bce9fd5b72ce2ab710000000000000000000000000000000014bd5d22e4bd2f7b8df4add90446650fd83d72d531395fb35dfcff72eca0886ded935e7a0e3fc99a7dd07efa1ed60c3f00000000000000000000000000000000122cfac9ae5c98dd162576c92e9acb4582b9eb67117bfbf4074654fc8bc473793a7139995666447a7663f3af1446dc35c8f6dd56906fa13144dc87c31b53186b0683cad220ab2de89d2fb515bb269cbc000000000000000000000000000000000f67ef1eff6875abb96378e5a7b1602b5dc553554987589b9953c4401fefdcc5cd7b196a1a65cb3daaa13f9fdd703835000000000000000000000000000000000f58ef60be74af52c23662e6b405f1d5c359b2ce9d15b5e139460e10da0e31161fb52f529c7b406e52c6f600d5670f3c9ec934eddc44729d05f193ac927fbcb022288ffb2bc7d4f46d1bfcc7efacef940000000000000000000000000000000000b7dc680fbfff55bf0cf276a864f448d5a9feef303d2416e7d87d6d669456b951a8769026bbba545685e1f92277b182000000000000000000000000000000000c36a14d5693b0d9d91d831c0581d1f4ee801f86e5c32f10cc400f66b58f247594c30f0059b4ea79995d6f9d90b0009ebd211ec887635ca841c4608fd00bdc0f5fd0f6365dcdfd7d6f4c36f4b25b5b1b0000000000000000000000000000000014dd947a01add8294f97a84850e6dd11ed4a513e7656daac5b725cff501446e95e3b966492e028ec23fe1238b53d99ea0000000000000000000000000000000003d9726342018f802df12fc867998b6016743739a2a4f47e1f6f50992e4fe23a6bacfea0e7ed5be570eb8242ec4101ec10bce61d4e35770e7737636c0f9a664eefa948662d3d22d1f1708fa48d3043de0000000000000000000000000000000014182228dbd223cb5b601521608bd7f87659f86a7a01233d4158484024730925e3d841e05e07f2a330b9495fb028db6d0000000000000000000000000000000002e0ad163d40a56215a774751434d19ea17341f41701d41e521983ff753ed76c435c6e2b543510e47060edaaa06d29f665c86930c1d142985bf85ce70bbad170947e850e5c6ac7803fc45980dd37a57d", - "Expected": "000000000000000000000000000000001364f0b671bbcf69b3a101dd758ce54434d59fd053591cb744841ba2061bbe2be91cc9f2cbe1ec058119ec8a5e909024000000000000000000000000000000000cf5be1c16fd10ff97a154826067ab7cfd7b78ca5ad0a2e2117155f1ee126286019f8a1049b86095887e79ba67216a33", - "Name": "matter_g1_multiexp_15", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010040f531866c4e6fdc255e2a7ebcea89ffc36d44e265d5129f8be44b07f00646a7810662723546ed158b2cef146c7120000000000000000000000000000000016d6a5e46b2067c29e11d00b6b6ae9f0987afb4e9357c1d223fb2962589c3527f94d4e01f2ce6a7c57f971756163e48108e559e394a9c1ff07a45bb3e022f9c212eea4ee5b77db1c5b93ce72c0512b790000000000000000000000000000000002b6e3a234119f0f06a2b049d952230da40590a84d241ff76483169428e787093ae88c4040c64f2f1e3aa5be2c37db3b000000000000000000000000000000000732aea9a2ac5612ac350b474d9d267dd1ffa822cead992d3eb411efcb6992d196d66868a0e1f89dd47da584d075d4f55e55826db8d12169a31ca27beec80554954f522b56f7994c62bdb527c2438d5d0000000000000000000000000000000014c3187e04024d719560e36b5a63228a685f085aa080c82244a3a704aa2ed68b219d1c699e49dc1fd648e904ae638e3d000000000000000000000000000000001911df5a9f709b8434856c14fe4111935156a984a5e8cc27081059840167c3daf468a290461bf6cbd2ea4fa21255d7c11362e8e39ec661cb3c5af64e0001cc94701194344a7404f1ecf7df0d5633eff9000000000000000000000000000000000216ba7fa8afa06136b054c11bbd978209017dc4d8c8a2b05fa717a97f4d88abd9efc1e9879de709b87d7de65c859b65000000000000000000000000000000001797c34bdde358ba5533d5bb531915545e3ba359ea1fd66d9dc2ce06f7cdb64684bf11e5bc02097f3b957957c986de1074d3d66cde7c4c8a4499708a0c6f7c4da458eb970b6ca87e23601c702365b6de0000000000000000000000000000000013343f0b79485528b8a5ca5e0780e8925ea7277970843ce3699046673a41c977dd0cbbc97273ed47a1a105a0017853340000000000000000000000000000000010f3232b511b8d529f91f1ab613af1e2443947fb2e29c4f98d1dbab1aeb965079f64281d0b10e58e26a4bc0577943873389e0d43f2006449fe2de506dcdba4cd0e6077e2228f7d8b6ec9d8a4129c494f0000000000000000000000000000000005aa017b9381423c9d00982fffb93a7cf9bceceaaf31895a17ce3a9bc42bc5b6f5c69679ebc91c9e5cdaf7651cf78621000000000000000000000000000000000c77e86d84377ceab757a0da9bcea401b3db29e8e577da793da0d5338eb471315315171ec4bab4e9dab36f4ec6d907a85f8dc332cb31e43bc2e551356cb8d1533c6e567d34622667e7e4e3ddef352f03000000000000000000000000000000001971e5758027516443fb373a8ba8cb98b78fd5d16b42a83becd2a9b06e8ca7d255fd687cdf10de7dfc6bee5cfd199b1f0000000000000000000000000000000013465b45ed2469c2dc6ef4b4b8ac90b9b30c793425093898203d3b13d76cf4b8e0836c6fe57e637a6eb08bffa3bb55250dc7052044251fd360538fa6d5dec9fcee53faf2f07de5d8df212d04f968a0b6000000000000000000000000000000000c14833dd82daba173eeb40c29912c0edacff741bc3ab03ae4911c334cf91d5832a8847d7e175934f61089f523b77fdc0000000000000000000000000000000013820819e27a27009ee44a5cf02e995bb317ee49b6068d2e9f4c5f072d233a6808d0feb61958e047f70b2bb1a5426319c579dd4f361fed9084d9c66a3ec4c6af5293710ba5299df3abc4cbaf5802b53600000000000000000000000000000000105a1323577a38bc9495090b4d023a9dfed8b510a9a6d755f7ad6af72eedf1c92e6a5172cf68608d8dac34242d1e0eb200000000000000000000000000000000147d889d919a58de8aad3b4735359201c47d8961a1dbd321061a81c67b1a05c6732782975445d9c1f2aed12b0b7306f469f0f3c3f516ae34fbecf45f4636c22acffbee765952b332c0f3d8cadb9c93f1000000000000000000000000000000001335049a2ed3629ca83f041e4ccedede286445e4b79f3afe225bbee6273e0cc84b32b91c54991dd072c54ecf0d6c538e00000000000000000000000000000000098220fab5661a40cf34782efcd62ede159c82dba8c6e9f032f7216b888ad85fca1031c4622547a03f14185b3eb6d0d576618f1954730111e572937cf0c9f7b3298a11d18cd890cb419f732c766bc6210000000000000000000000000000000018799254b6fe847f53e2892343dc77efa3717bccb3589b776584fcc9e934deb3b8fa4c1ac0709ce505ca4d1504ed822c0000000000000000000000000000000017b98c35564c9d67b77bfec8ce23310c93167a5f75a4680420e8d71d8851f4061d897fd86b52d4a8cdde391c5b21a63afbb9f2400ed1dec7ea63d2b26bb3e9c2acf70117e3026626f6f88a0787617788000000000000000000000000000000000499468c8da336124bb89285a81eb76fb05e4ac2bde68d2f78f1de8926109631ee3e33eeebf686c7f6b7b4d68d13d2fc0000000000000000000000000000000001ac43e7c6d46e88d88a195180df6a3a91b3aabbe54f88c8b39168ead4b9847a031561828b0076b9b94c8fc7cc0c4636a0170d7b7604b8951a95d49b6697e2d0cd2a41c3671d8f96e936cca911dd516d0000000000000000000000000000000006690b59efd7c3e7f9477cc35fc5e13a5dc7f485100ecde7771e7bbd9f79f72719cd45cc9e0e791b7b5dee6f0252c53d0000000000000000000000000000000008b6f82c8514f7804a1d75f347f08334064b81ff95765355550c53098e19a4a5fe59c6a9611f4795981047754a6304792c2afc06f19e627e9ec0edf1083823d30ac569346040965e1c92e0c15011c90b0000000000000000000000000000000000ca51cd2fbe8d015a2e80bb4a24f52abfe6b99b1fbf1b656d4398f76e8e73e7a441dcacb43a4bd0a1dd45df2ed03a4e0000000000000000000000000000000006269d0e0f77f3ac5af8f70905ddb323362ec5de91a1eb90bf3773457a2bc2d018942e58c04013b83a7764b6639ea87c141d0ff346e46a20c2498a74f910e9bb2d5d8530afc7ba47c3525861c9e8c59200000000000000000000000000000000122f6c35f7b1456952b56a5f90ef9066a191a4164d4b2f81965bf7318d485c725141576e5a1164c3c17a8bc387c9262800000000000000000000000000000000086bcc20a2f0f0afd4ce845243061e1c12eb238f2d3fd711000f259c31d826c2bb56617479139cd611d35b6548a438101d688a1aca2a837e0a353039294a9988a7111ac134a6a8a68e4f881e7486025c00000000000000000000000000000000008ee124fb457671b65c0f9f550ce1ef196c3bf13a5403a3a21a801cb1a335012b43cbdab33a1ace7f84a998a4322ae20000000000000000000000000000000005b0067f853d9dec4dee3b2834679b9145bba170f22b7e1dbbb6ca3dd98abe4f41673b283f9c43f2cc7ee2305b874a0e1b59c33ff02791031e7a9424c781ff17a209d132af06f5b825df363fbd902cd4", - "Expected": "0000000000000000000000000000000016dbe06af92533e96177581a7a349811e0a3d3826241c4ca047411d5b24c76dcb6849df7f4ca050286b2d84afd71ec9f0000000000000000000000000000000012dc4fc05526d6dd6da27b117294da4e9473a34699871b7bc9f02937a8308c57b5387a6fde0dd09e8a01702a8b97c4cd", - "Name": "matter_g1_multiexp_16", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001394f8d94cccdaf982b1c6a8080be6bbb65c9352a961cd5daf2f817a17bd8d5e3e086c6f54f6068691f3edc4378215350000000000000000000000000000000013560d0482e6ef2fc19cf274f85bc3d14236273dd8af86107839882dc26dbe897a7de90ab5457ca440498265bb59e59358fef5bc887b7caf72f2a533fe1455ae523841bd49b4adf16cfe87edc6f573eb000000000000000000000000000000000bfc36885481f9ea9aa275c1b4a774fd01476c6f956fe75b5f6e73199928b1928108658e35dad50b298307598582443a00000000000000000000000000000000161f833b58de4db4de0af0fd17ddf81ba20e4b6ca21dd80852cb992afce9857e6cf99cc580664a970e9c6928d13dffba73b243b83d44158a66eb6d31e7c4ae1f4b3ddbba81b2cf9a654ca7c4ea2147ad00000000000000000000000000000000042489a05aecc0fc139c0ef0c703860ed36f8bdf50e4c772487c0d27b46b395f6417ae34ee98290a40b3b765d5a41d430000000000000000000000000000000018fdc2c8ac7aa01ae6dbf84412de8a47c3c504f2abed060c63190265babf779384dd6e3330e91198f5bce5a103bdcd701ea87af09f6e62111c48993c408efd3db9ebe218ac68f61a461ad9ec1306873d0000000000000000000000000000000005a44b3af7b95c7869d74c7084d0e556a67b39090b7a62fe51fa833cee316044a26d4e383695ecd3bb1715d0693f2f1a00000000000000000000000000000000112fafd6d6f1da250d12817711bc999217d16d7a6a923b5e11cb91a333898fb27f7b89885567d33b39923d7a664960eca691b9635e38a46e2469811405ef6325ae7ef88a67c1d1c5b05806da329f27e000000000000000000000000000000000197317f509ddb9d536845443d7966314eca15f20cfcbf3ff2f8701d94974e35cc0957855e0085b3f85c7da512ea882910000000000000000000000000000000018b1ddc196607122be575ebc923dee96823fb4f8ed05fd8639b1af06ddff25398e67709809b642d4d9c21dd8ab6e65470d9a35f474325d0f065442805cab3beae4a186b252ebae54a567dec6695588f1000000000000000000000000000000000c7ed49a60aa90f074af9f7fb19f6e27ec4a83ce2ed77a44c70c8e0bec02318bbe44a212c505efed3550ab6a1ea2c6d50000000000000000000000000000000013c0a772ce2c97522607b1b05cd9a89e930b6371202b69eddd108237f1495eb1c6ca65549c5ab030cc4f7e3ff4492fe9c20e998acda67d406a238f16bc2b3066a6d69d2436577b8900a180e6a71b0a01000000000000000000000000000000000fd64797f2bdd429e6f5217858cb14d78b7054b178b74696b8bc8ec9f9ede70bd03c36c824a3f775ee2f8cd6be7e2ca2000000000000000000000000000000000f675a8a43da599a09ae2367240870636ed385eb280cc199fb7c4ee575f5e3c5fe0b302566cde70b956f3c2b20fdf09c6fb773cde356e2edac3afd2bf703b59161162dc1e915873ecf606dfc0e6efec500000000000000000000000000000000065856fe1dcbef934cef47b177ecb7df76cc8796624400d5c0518aa9438bcadf397234808d099bed89ab674560ffbb1800000000000000000000000000000000071b2ff64379ed3e20cda000602c3504616dd673aebbe7690e797d6428ecfbdb29f11138169f3462dffd319cad68b96ebffc1a58dd06752a2a77abab835d089599b4781ae51ab998ff3c5b68329068bf00000000000000000000000000000000094d6e0bae02b4e7541a27111092737e7b27fe742fd0400672953d8fd787482195a2cb59a91e8584be002976c3c3e9b8000000000000000000000000000000000c2146b68ef535ed9efbed7fd02ea5cf6ba8cc20ad8bce17c06e5d595282f6e7453e2cd267181e477f511cd4fd56e8b157f35cfd74f62fa39f919400f4d692855a4b4e9f91920e4306ebb2e772a484f40000000000000000000000000000000003925e9f1e24531f9f26547108671a6a0fcf58aa6ef2bcf9f4f64b659782b93187bdf2988029de9f51e5d41cbbc4744d000000000000000000000000000000001975210e2c8bbd2431288a42f9cf5d6bd6c6afa2eb05caebe740c0a1f680b9cced0f32f8f84e368563183b97aeb6e7ef2d1f3709700634653374fba5a94d69163ef616a72a63d462afd9f01c9ddba8400000000000000000000000000000000004a2ac3d53c193265889f6c3802d7c68b938ebb6298dbfa14d1a9f515647482c84ebbb3855686b544d4299554473f1d60000000000000000000000000000000003283688bec2b8ff2e34565f8e254d579f57f9c0fe0e8521129088099a5005dfa9d565d52a75a2b26148205dae83aa6a614ed9a08dfd406df00719d5eeacfb0a96413b608974fd0aa1d4c6176b968dc00000000000000000000000000000000001b82af64f984294882fef7e5ba880ed8b0a36a90a5e9680ddfc5d86e65aafc3899a7d63e2a420113ba29412a025a0970000000000000000000000000000000012b11a5bf0f7895e329c2c6bb3d1737aeb5fe9f32a96262d8268c74687a460c47a89e252e607032576e7b67f5ad655b87c1dd2e5e5f630fb1d07e8934dd3ab029917e7775e401c0bcf7e1fd83aef72840000000000000000000000000000000003ad0dbf936f79659ccab765a61633ebb648503a774e92b24967aa8f8e45c5e26f03acbc7984a45e089ce68c5566664c0000000000000000000000000000000011686f58262dca9399d95cf2828b50b216e1df251b61c77f952c21374bcdacd99d26891fe5f335afb7ec76ce7d95b43f64e9d16cb61f2bcdef30cf544d97e078fccb999b96a1da0eeaa0bf232f01995f000000000000000000000000000000000ddfea60c169079c0fb4b9c3ca539e43b7f184f31cfa2eeb942acd2a84b472597c83fb52544479f326bd1207b4e872f000000000000000000000000000000000102108e827cf4473ba1382a2fa8f3b904f20a40657784d54e3a91fcf2703dc6fbcfb7f4b0e04c3a53a24a6e14b5735f435bca9082d66c06761f702dd439faa4957caa70ce0343268787f41a2f4bc0cbf000000000000000000000000000000001286a578ce3829f289cb98aa41cb6bd7274aecbe15b5087d8c16d575fd991878b06c88f17fd4bd905c4576494ca9f8fe0000000000000000000000000000000018e3cffb0746cf70aa79053ac579c1adbb09ed5b6a8b5e7b84951460e551e9bb62f2c1968e37ba34f7633e60a5f1f2a97980eac6c8db86ef83748d10b210835e53baf8cc9f607915df272b6e28ac6b28000000000000000000000000000000000ad648d5e0a45c8208fb9b6adcb3c47cf0e20ca906c4fdb31e5c2f0678fa3ddb6e27848a39e8035cfd9eb91aeea824200000000000000000000000000000000005ea40be38d82e2b256bd5e26e71dc642e06145d94c1ca4fcfd6e63e2bbbd7b7aa153b498793e94ed1d89691195b4aa3a256ebae4b204b3888d7bd244bbff26431ab5890098870f13800bb3be3e842ca", - "Expected": "0000000000000000000000000000000013a9e1e306a5cfd461a1df4f2097f0beb079a845a959ca3a6d3e229198c75d29daeb5e7b65603397353cf800e0a10d820000000000000000000000000000000016532afaf2b6d884a5b593cb8dbc38b4e2bbe522ac69b745fe9938834d66e2393653e31b052a803f3f901abdcb352eae", - "Name": "matter_g1_multiexp_17", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a187eff5afd944ea8731afffb4aefde4046b812b47e7cd99687ce40a5af90d6a4a2c7e2c9ce515a229e6c99ce46933a000000000000000000000000000000000121183879453793d954c99cbb007ff428c721d0e0b9cef192dbb177696ab9d575d3ade2cd56964428adfbdfbafba7505805f2e8013007c4f6d8abf441728eda8d742ea2f1df545f85d092f50ca8275c00000000000000000000000000000000196b029b6a808602b09dd4597db611f19bb911b3acb5dce08bad8676cae9910865355cca0a109bb8d7b60359da6d0544000000000000000000000000000000000cf045d01c1a6d6ae397b39833243ad3cc310be9220f71a248032e9325c7186ce3ea40fbcdae5258410e1a513b69713e502d777b25f3112ba2264022e2f28dfb6e5d5239ba097e9d815928be44b6a62a0000000000000000000000000000000000c6578ed0ccdfea63fe924d0a30c4aa7d65d9f85ea832733013c0ac225f039bd6f94b4acf634a01ac67b7165a810db8000000000000000000000000000000000624981245bedf55b95217691d9dfbc16d0d83476f8c09a46f9541d77c29ff978ded7fb7fed7272701e385e016647463e7d64b471cca34ab0c91f61ff26719c7186dfcdef13895d37ead407873736a74000000000000000000000000000000000a406d8da1910d9ae8e52ac70f1fbb85954ff7590863ba9f6e00861160f83defd24e99be31ec63489a483fa77d84ffaf00000000000000000000000000000000170bac083f0f6f4ff5edbacc5cedbdfa314de364e86486cac0e656d27e6a4880ea3f76ebe0f69927299bbe4a734e0482e5723630020fdb48e44adda735943c91ad7d1e12f3c32d823833eacfcc8b02ba000000000000000000000000000000000b8a583c24eba7a27a05bcc606a10a306ec07401ddb8de8e9bf206250ab7cc720903bd81a2c17a9e075ecf0ef99ad65a0000000000000000000000000000000006d5c7e9faf830ebd0154dc1c366b84445a85f0ebfc13b5339294752f4d1dc352e0e4204d9d64abed83e8297325de2556e9e37bd811b76133c12268d325ebbd6656e7ed718cd777458867dc98b1b3bc500000000000000000000000000000000122735cbd1927c40688662c740db5cb78425942985ea69c729061a6ba749c78d4fc3d894d07c285aea9ee104f59581690000000000000000000000000000000007c18425af769864f403c39ce3df4f07d4b7319342457d0dee30ce4bab013b754e2ab7492f2dbcd5bac2ec1ca2e0220f7d46516db284a3938e672ad3c6bd40313d77c5d643ffcc59e3f55ad983cdc0ed00000000000000000000000000000000039c8c0453627d13ca0e174f5a27525f8a0054ced2b9e7d92c0ba7bcf06c78c1e1632db35abe2a81f72b986934ade66300000000000000000000000000000000134876b42096d986e6004364e176e23f81637f8ffd3dd86097f480d25aca9ce3a96c9dc73b651106b4de307c002dad95586cf63c5e52b44aaa79cdda6dd6fa92c6fce11d867b2ff5a04c9e44e0b3930000000000000000000000000000000000032e727809658a52f60a973d32bf47bff5fc45404e6652facc1801d52188dc7db79ac1bff415a6c3e49e417f205422c7000000000000000000000000000000000c83d3e5ed78c1304f42afcc0143f959ca24348510e241c3e79ed5eff8742a89b4ce131e63544b9497c2a1712999a18cefaac96bc5f686d6b952e7082236622b737fda0dd3900bec71654bdebc8ba2e4000000000000000000000000000000000c2bb8dd01510ffe473715d7714e47dc8fff0f24af49405e55a9537a617dbf425950ca3df681f1fb2a3721afdc5a4d730000000000000000000000000000000019fcf0bdc8cf0f14c4b8eff44ce2646feecb3ab0555f530f579cb2764badb6445166598824f7b0c46a857865ade1278239d6045573dafd09ab2a0d8ab6e97b0ade43bd79d820749ecf19cf7d99792ca80000000000000000000000000000000011a463b5221e4c3abd9652917379564ed2830907464235fb6f9038f1d3a4f0f8cf9f6ccbbf66c86e216975b2d372400d000000000000000000000000000000000f0e9d5050d539f9211ff7d3cf3f0e7108c5580b634b122810c78d8fe047ac709bbb06ab1501e08f0e58093ba8208e0d4c4a2ff4ce4b633ec8fe0bfea42ccc329b7d3fbce96c26989b3c7a391c9e806a0000000000000000000000000000000010b293dd411de6a5cc464e919d290d6bdb51952a7a68cc27aee3ec80808bf05a50763fd4c17f25e94e655997bc948860000000000000000000000000000000000f18c7ab95bd74d9095ea9ea66b2b14987157162b8b8a313a781ce58b05d2307db4e853733a45344923488ae9dce1a459af09ef1f27cb83189e4e13f3801c08d3a2adc8b5f88717954ee84499defc0c40000000000000000000000000000000013ca27fdf920f901634156567835601ac0b84efdc79d7d979c2156041bac04f3297c1799d3b0641df33da9647e604b87000000000000000000000000000000001527cf040f6c84496ceb57df9c9ebda89c394eef034e40f5e6b540e931775ab91a4aebbf6078922da479ff397cc5271ac72c1dc1efefb775a1bda754ff17389a6b6b6bb25e22697847d24a117eb8974b00000000000000000000000000000000197c0e4474e27fcaf203819563b86e725778409c7d6792fe41820c495e412382fefda97b7df560885082c70f9d522024000000000000000000000000000000000b14b9d40bf866d933a15e16f06ec16b502ea8e7084d68c74418414fd281a6da50bc443647fdba348b26b4a3490d0ac4b4a0c7c2e611a24c722975ae882dcb4b45e6f6b41cfc87e8c766beefd5b10bfd000000000000000000000000000000000a254b07ca0f2c9219fc0dfb49bdd7901999cc85161f741500a3ae8be566e64f8a5fb3e59985444206a2cd02ed4ee99d000000000000000000000000000000001726739e92da7bf5a6d2dfbf96fee6028fc7022cb1be2f838ec1b9bd08ef141f4b24e093fcbd99080721063f8b7c98dc986d48aa5b00fc16c36dcad061d10937b55ec4deee63cc2841b7ebab84f910d2000000000000000000000000000000001133389c12bf1d2e232cfef1a8303a733edb0dc4fa26acedbb288166fd232b79f67cbe76227ab2eb517f1c3126b929a30000000000000000000000000000000001ca6bf5c18255bb3c533ece833964320bee7c3da4af56d876058edd15f89b0ef147fba11e1d539d528e4bc452e17df8979d4df836daac0960fbbb8919d2f90c3457cc987153def711d6e8a12fb14363000000000000000000000000000000000d0caaa05d3a01c89d6efad96f5957f1f9338136119e8530853a58c0698583d834fb0f045e212e6889d8baaa49815c790000000000000000000000000000000009e7fd124160f6ba3afa752b2557f1c4b5f4010a6d4a3c8a8bfe350c6b6e198b9e3d11f2ec7dc6a02dad4c07bcd4bb1d25ae495ba75cdd0bfe200ee24d813e1aa93c100ce861c9ed7fa5537e11778990", - "Expected": "00000000000000000000000000000000138cea47ce2ea638f06c26d24ce87073f98b023b800245b6fc74fc2851d79a402b49c54e5df4e1aa98e33801d3fbb965000000000000000000000000000000001558e37121ec3710ff5e6c2a4e418c803a5b83cdeec98c8216b8dac7890ce17bff08a95ca2aacb40eccc761c8a31e8c0", - "Name": "matter_g1_multiexp_18", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001920ce210ffc78b2c053eb2106acf1e238ac5160b50187fe816010e8a95ec632a7fd29565aefa4bec90d87701c2610dd000000000000000000000000000000000322ce646a20e23a1a68361806cf072ae3d6310f4055f5289ace0036a90b5c7ada537e614780156f6a103ed726e15b4fbb2a329761a3d6a2e4d9d63d7bbf7fc6fd321ec0344cc4d7d1b6565c475ee967000000000000000000000000000000000a1ee4319282f43ab9cecccf2c7f5e08f35a6c7e7bdc8dd2f4d642e8968aff377791a5d1e2b2152c59a8f36d9bbe04ed0000000000000000000000000000000012e60ad9f99f55859f2529ce02b8b41f8565705455cdfeef3cb315903ffbf29fabffc2546359007a36ba579b6dd06c2043cbc3dd7ec63ac63618a9e5da1f9c3fb952c6fc6972dfec6caf1a415a0aa79e00000000000000000000000000000000000c2aa9516360c840b7f88ce0cfaa0ebec502bc9cb9304c1a4d895089a2344bdb6623638e730cf30c66d977e077423a000000000000000000000000000000001163f60b32213940c9cfdeb2c86d5ccf61c0a714436b3d0923ec338ce7bd35542726a87a1311c8072fd589499c26521d733a3a84eddaf3af8c5009646a899f6ae8cf233f535e360e29e2952088ebd7b600000000000000000000000000000000116aa02028755dd5195ce0b2d3234d31b07b557a52330fdb50064a18015ae630f427a4512dff06f93ae67c4fd0c1e10f00000000000000000000000000000000117d4a68064b3f11d88ce976ed43ceeb742ba6f473645995a2773121b2b8edb8fa2715f51c8be109f8d91c44e8943e7c5112b5912aa3cba657d8de3dc8138fec92b391d5f988b82e19f16fe52fafea7100000000000000000000000000000000166cbdb131fadd6c4e7a94af82ce4fc4805dc34aacb0d6cd89e69cef0b9071b112ea4a7d9d03e3dd961b5d833b84195c0000000000000000000000000000000010736a73e2283849595569db9a5b0b9cabf2182c3d8c40a39fa32abe52dd6038edfb8176f64ec12671e3411dd69397585683e0b33b5463bc71283f0625269b2b33ead69c1eb7b23a996c31c514d06937000000000000000000000000000000000ec2405173e541945011d09092cc3a71d9dd1ff54451127181bb2d5b50876a148e59f298ee30ec5473c520be0a53d61f000000000000000000000000000000001239198a5b1f6f57bce914583c3bac476a922e56d2bb30da4912acd31cbf307bc258f22fd9f6a0073ec48dfdaa4799bb5bcc597c5ed7f79173942a0250e618c93cd0917b37b5f354d63a2c02a576080c0000000000000000000000000000000000232940188006769a382a4958383aa6702b2cbfb9c2907a989938ac618f23e241767b021e8ae11c23617ab393d4f85a0000000000000000000000000000000016a672061fe76ed943e36b2d6fa4aadf579db96eba5e4c60cda2884ddcbb0f37668638a3167d8858cd296917eaeff8e0f2613a8e50fbc6683ecdd7c7fd38b4caa8e5dc9778909fc8680a58b16ebf40da00000000000000000000000000000000066fe1f7cb3d67c20a1ba29a52c0c86d6a2aca176630ff20d45632398a39404619e55b8ade69e0cb0b7a6f363c3b2d4d000000000000000000000000000000000aa25dbff2a8c1f1d0982a709fbe88563813e918c8f25f0da9c5d0dcf3abc257f7e32def4efbf74035aee1ee350cd4fa57a747bc919991ef9b7b10388bf3f301fd910f807ccd31e322be46580a71b7c60000000000000000000000000000000001e54b0e8f34cbfbc20c9feffc555036857c31f453a1bbcffe67bb71d0d6b2b278b2ec5d6ab6648b397c9255a1139993000000000000000000000000000000000bb6d6c1a41675b3394f5b9cf14ddfe73c188592916f24240edcf0940fdab1d1fc04a11bea4af90d0d9f6734a743b38086ba09829f4bbb383e2e131d554c42edf1065022975655c07df2b3445a3e6cbb00000000000000000000000000000000099f521ecae704ed5a37ac90dd4beb4fa21ac197d467185c8329ad7b87c02943a228285b109178bbc2606e89699403ce000000000000000000000000000000000a95a85f84e76ebace78bbedbd13c6b79a6339dba246596e0695aac18d2b14b370c033e62a01caf8484dced0ebe8a76a03fd5e91f590fbe171aa3f006617b20ad645626c970c2351e048b2ac377321360000000000000000000000000000000005b8ba4c7d3c83fbe9bcbcbf60b0b3ce42b52ca19a5a322fb18bc20f81c2fcac23e1f62b9fd6edde5ffa2e37f685e06a0000000000000000000000000000000008c03604012e4dff47923a2a43382edde86c76754a1073ba51fa3a2ec7011268ffcd1452d46786682ab2ee4848210cc635ee16785c004dd2a01920c52d3244e2160fec2d17a519974d4331527cc62791000000000000000000000000000000000869a2ec19afbe70ad0a15532f776f56da5d7a7dd5b75194d0c65d0304c69a6d0363c0ff3b549e8d15171fae18ea13f8000000000000000000000000000000000389d0e6c9d73bd98202191b5b213fbe77bcf527faf98f4d25c9dd3ea2cec8f3b1e8f261d9fc8baf7b1c21dfd102f99104a6d6e29336015d99e107cd312e300bd54f815c785f6008c47c99fa0084527000000000000000000000000000000000138a4f53b8fcaea11869a6208e7498238dd80be79cde96885e6e5226315deedc98a17f8d75df733ab6f15dc24efb5c5b000000000000000000000000000000000d25d69d6d5a9c597fbec8aa7fbbe579dd86c5fd3747378e984c20b34e018b83f889bef3069c693a91ff552fff1fb8a403f9cd3873dc6243748e16e4806f8eaa339edcfdbf4408a8e41a3df80c98162100000000000000000000000000000000192e8e186cc9159d2207b0af2dca495e9d0c82fb376041360ea80562e470168b52a3326553902fd6f5a43ead32eb968e000000000000000000000000000000000fcac12d18fdfb661a12d112fc3414839bd34aa244ce0cb40be79718ec37a014b43856e5e4b003f4816e04ce612e63ca34135a2e7853c74725bdaee1ceadead7b4c7d729650df6544bd525c05c942342000000000000000000000000000000000b860984aed11a63656e3390f5e94695d8cd9367ad7961c65d714637c68ad88a3602699ed3f627f0fbc5782ff18775af000000000000000000000000000000000ed00636e74e8163645c43b8b31f05228da7c42aa332ca250270e5f14b3660fbadb8e8957f52592d942b1cc1bd2eb0a50033fdcb731830951dc3c4b33f06310eca51762cb7279039b3d7d9ace93c5f2a000000000000000000000000000000000b162c0897755fa47053e45ee1b298404818ca282a7b5818364c292a6052703502656e536f2dfb470730e9bef0d7cbf6000000000000000000000000000000001924ea42eddcddda067126534e8b862f0e16dc0cc296ea892115a9ca9734fa03d019e90263be2c909528129a12a68d874c8112ebfe12bf44e84796e8b0cd03a93d2164d6edf1f06a5c520330a177da87", - "Expected": "00000000000000000000000000000000056604e75c1069b4a061ea72cae2cfcba90130f6db6d9c268649089ce4ae1cbd80120a086e3f066f2584f5b2233b468c0000000000000000000000000000000018c5e93590b89119ad7d44f80cce5ecd97d4a4d3010a19fd02a58342752b166a1b82dbbad30d6f3404b330dba6a57454", - "Name": "matter_g1_multiexp_19", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015f9de55b3b45c16d59adda55d9f5059e765ddc06d22d6e68c099358d8df0229c6fe368384a0486af1cc9e532f78817a0000000000000000000000000000000018b992d73dd4c602afd82ad0845ee2c6662c860c5b7be197c62a8a20e91764004b5293ea40602574e91c313e8103e7a1dbb32a4fd8b9dc58a382a7e436e23f49a134915372553eee8c605436221acc8000000000000000000000000000000000157a9795cf9a45d2ea5e0312783829cddce176c63eb16195e7994b0688f9f30a4f2b2113e955bc66dcf05b5441521889000000000000000000000000000000000dd9365359ce805327b8f627f02ef5458cdc806bba246dbb21065c89e7ac6093004d214145cf3dec605195f14f1a49d357df9664d3e17d9d46a886efde4e37e38859893113558843bc019699eeed8ec0000000000000000000000000000000000066d9a54dbb5fe64835523e8ae05bb70b1934e389db0ee7547da60e4af965c7eee14a148f2e3269f01e8a545480db610000000000000000000000000000000017d6a22dffc3eac4366d0d35bfdd053d73d7b3392e7f52fe04e7e481783db3232f85687d2341358d2148fb3af7e9315de2b433b7a95c26e598002cc00b7904816d59baaba79bae7c6a7c26dcc48a487e0000000000000000000000000000000008be91d2752203afba19d8f3660118f83dbf851a6d2c54af389ef979121c55426d0761812de72a79d46c66dfcd00d5cb000000000000000000000000000000000269b050e36718ef4ebbc89bd88106a4043b267d974439855b6027f7fc3441518c39af6d3fee46e87d399d3ef03c63c82897583b53567bcfdbc63ae3e864a9cda24bb732694a6b27415c5212c7f45a94000000000000000000000000000000000dc976bbec5c5791688499da28c1d120e8a68eb5511ddf54525c047378016f68e8590b95f05cfeffba56c3daeb0729dd000000000000000000000000000000000af6e02afcbb707fd4d8bdcb5e73e1db56d7a2eb02258b91ec4a5c46c4627525220c11e6e379077677e1b733e2df60e02f7ff17e54d759eb9c51e16cf6f12d645bf2d091427416b4edbe1dd21947b4d900000000000000000000000000000000119b86eced2222d203b6428907269b950bcbc1519859c013349b1c7acf486d3da5c4b35319e6b1ba8ae815e4ea14a6900000000000000000000000000000000015c342be097ba679319b83a68164f6820e2ceece3a90d1ec296514f0ccab6e454a0fc444d599a812bb4d78e656e8897fce0a097efee666c22d1dd0ae8c8e11283aae781e1deadceb3ebbcbc5e5280a610000000000000000000000000000000002da8de95ee2ee1be2f3ba8afd8f52a4fd0e352c295e92aa8fe9a08a03b6170222f5d6cabc9b9d9bf2835128c6ece3e9000000000000000000000000000000000fddd2b5faaff49cec261eaa8d093b410e024e1620863b6b9bd882088b59afdd4445a4971f31738e2afeafb36900b2d47b2baa349884b54b542e3993210ef002f70c6467c7d512801f0003da789c00580000000000000000000000000000000012060c8cab190beadf40a2e3d927d7cff21c475dad04d64c718d02ead9e351a27be81a3c5a71c6c95aa7d7e287070356000000000000000000000000000000000233ee868716db87f46d546aa1a7e4d3e70b2592efa0104d9f4fab1680c627484a33346406f61499e3971157a6dfbf972b94d087c3ea101649ed57ff308dd3ae0d25a1ad8884763cea1b0b7c56a3834e000000000000000000000000000000000cb9c4b59eb8bbbfb8aa2e9ed72eab69735a0154645d68428f0bda762d3b061b0659b31a907f531a55c0906532c539e6000000000000000000000000000000001806c7e8a8d95a34403ec78b43dbfe0bb09014fbe0e019f8c3b6ffd91a75d5e361a6794996e975309fa716b6c6a933784f8c35b920a35b71dcf8d15a8a826e5a7c2a2c4f1ac2c2e3a6d100363e7f541800000000000000000000000000000000131a492451e5c0ff787a233f72766339d7dae09f2e17c6bec9faeb08e4e48d6407b12adf2dffa3911395d5f25980c9650000000000000000000000000000000001f14d5268c422f94657a20ca02be7d007ea88e1a352753b2fdcceca5275a7ac101c0ecfc075735eec82b8fa6bd61c980ae6101fac82c10267770e74a0ee16b5be6eae2d455d742303a3c624d52aa726000000000000000000000000000000000d988d419d559b1b487297cec19386f28659fbc5f121750b6bbe941794954e82e67c15a9a00334527d85e9be706bc2960000000000000000000000000000000004c222c037fedce38f42da2b08f06614ec9b166cc6428e3c4cad8ffa440af3d8fca7b9e4aff727eb0890effbc2b88060002fb31d0372e7730499b26d617b53ea04821c6eae922326d755a0df31b559ae000000000000000000000000000000000fc9786ef5291943cfd885238090be47632c10cc46df48f6bb5250a7a85690f1c90f5f5bae03a71d7c52634cd0deff340000000000000000000000000000000019b4ec13ad67e058906a3559cc683511715b25e52f39a591b22177e2dd235e042832f740269544de112d9100c1ae49d9aa846e68337f4e9c99dde506a3af792732342e3b836376d4816557fc1fc9b916000000000000000000000000000000000570b5e7b74c04db066d0aa751c9f763f59c6121e4e2ca4eec222277049143fb2e5fa39ac0fb41cd85310e4504f662ef000000000000000000000000000000000b522af535ca2b9db0cff08bf8ba19862e8f964b6210ee19f0cfccae8972150ae41ae1b8ddce4b1d2733c7dd47bc4c87df9035283f1afc294ee68b2668870aa45e483d208483d9e967b11990cb55d860000000000000000000000000000000000892cc60eeaa0ab6584ef2731538a84c6a1e8dcc2efa9591ef1321442684ca9fd953553268ac4ed44bf50004683793550000000000000000000000000000000010234542eb7231f4356c34e11e7b4f08b4cb405a31aa87f961d4eaddbdaf5ba6227b2764e7c7c9ba76bac7da3b19f6014005df80aa522e889e7720a9f2e44e6e7e19c3160ea282ec87a4b446d7b1c45f0000000000000000000000000000000005f3ff7ed08cfc6bfc8f5b55e2b368cd7e9f4a508ab46c7a383b2123b0346b81c39ba1304d628448c65d8c86bec682760000000000000000000000000000000001cbd3457f6925d5b8db7a785587d0dc6e2ad2ff5a6683dd11c8946e953dee72bd52760cc977987cd06a2679c74f9b64893c9daec43032946a9e892dce960e07d29b304000378145148b9a24afd15157000000000000000000000000000000000aa17bed794d72f8ac77989ce1b78550da54b4920ef6ac4ee0e83bb3cac5431cc7fb5c300c021045d4d391c67963feab000000000000000000000000000000001300e87daa3c36d87138628ad9aac5ec7d62e979c83c5ee4ce9a375fdabc745fc5874578945395ae128022eb98c6d8e4f685e6bb7713f8fe202c05dfd18003eff261456026a5185ee9e68aa821fe7c5b", - "Expected": "0000000000000000000000000000000010a773006edb1a84341f2971f9226841142b26bcc4af52bc8b000f165f6c59d094aa2eab1b83b3623c6c09145b5bf6120000000000000000000000000000000000130a0242c95fb2b858256de2fe27df7f5736765f880673300e3506a5e756b3b563e52b481c51a003bac76d04f56c5a", - "Name": "matter_g1_multiexp_20", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000090ef8b0781c66698848215b3aa84f7be47f86a9d95bf5a1ebe9c3dd6615d4fb4c6425f9e0029fa3d7b94052ef8bb252000000000000000000000000000000000cd1927ed1bfac35325d69fc924f4045c5af9fa5b0a18fbf6c658a3a6d405ac1159d1c82934aa116a98cceb382dde2ee94b3c88e51af5822177b85978526036a426c9ca1077d594618ebb8fac4cdfc89000000000000000000000000000000000dfb10a6b4e5980400bc275ba5cd8211b8a6bb6cce026546b9459805ba48f46a429ba683ad3f96ace4a4ffd6cfdecafd0000000000000000000000000000000001f643a6d83f235edd9dea19f0f2ecb98a82ba295d8ad45f75be5c0d5b1a1522c5d9f5ed812d47da6e5fe8d7924648fc6e456b39f4efe6581657f5c701c696fde8acb59e856943f15cdd639c1fa68ed7000000000000000000000000000000001824ddc80e263475b6ae3b73ef5613c7334b2f71c95d64cbb84dd489851580e767be29e7c7b47d53668a0ee3e6bcb03e00000000000000000000000000000000073f6ee13c3b05c466d35ac49c33e5ffebe5e8325f8f06b893042734bcaa4a1bc76da272602664c2aff48e731cea0304e5d306f46a31c14de7b2940104d0a4424ebaff805a81f1c4a910566057c81604000000000000000000000000000000000abe490a12162aa01307e814684261566302501f589c655b3cb840876259112a1924b1ee723e0c81d6cc6b19535d52f20000000000000000000000000000000006a2205d02f58dff40715070cfd635aa5e68553eea8718090e5f6a96dfb0a2f5a23e11ba92d38a7cee16ce67aaf5de194ff6d13bb0967945ff3b6fbbc104296805e4fedc3c25bb55b75cc997834de6b700000000000000000000000000000000180b5eb4201b4f10f605b4a7f5f5e25783bbd7c9e354238dacbd29563cdf119c832b4ca5c908329d5087d5c8c6786d68000000000000000000000000000000000ac5f56013acf364ce736c455a88a4b2615ca40fc67251039eb99df3cf6423fb85695cc035b6a9b47ef15db7406880bcde4fb2dea292b76d8130e6aa8aff5edf0097de935b252d42a777d4d9b8615ef1000000000000000000000000000000001963e29f92f6f72be2afa4635221b0d2f6afe9ada4582bd7ca4b77eb77fc4503578f38fb49aa1838751db8cf1ca0b0cd0000000000000000000000000000000009856a48f12966554afbcde1971499ee3ae40c9c5c3aef13bc415fddb97545ed84d5f50d2a26b9c16c4403a487dca614bac5c50a3a8a37111114c22839c88ce4072940c06f0d8b6d53fed155d0399ed70000000000000000000000000000000006cb805ab137fc56763f73867a7ee5635448a8a66bbeaa9ff07554db3d07aa38542884006744f6719f4cfab1392039820000000000000000000000000000000005e6f6f14f7aedc757cc458ba363fb5d97ee0dc092cf6866083722d4535e1b852c1d99d0c7c57e96a644de4b431c7f9bc3f37387bad1af3a896a7e66a80dfce2df1709fa252b6fbe4334d02bdced4329000000000000000000000000000000001045bd19d4fba8380467df25a777b1ed2850b7f5c5ff5501c048339c2f71278b2c97e4815973303e9eef283378cd8f470000000000000000000000000000000003278c7c8aa02c15275cbbdfc49f6286d6e7fb208a71a4da390c0c853684d7b4d8a6ab24953075a6a45f79fe0c9b910b70fbf5da3959a49fab7e97b3df3f2a38d16d714dd798a1f04ec2cbf84fce76910000000000000000000000000000000007af4aafeee0372e88786c6025a710fad46252a8df870b56bc1d8a39497c2422bc01aebfb567b5b68273ac59b5cc8d6f000000000000000000000000000000000dfe4a8471e42dceabb609b983b59dfd9869f29fdde01a168c07247252a9be6555a823a61487778597e0ae305da4205fe538bcefab5d8d0be5fc143e632e86fc065af3f2f621f293b914980abfd6a0c70000000000000000000000000000000005f847129487acc07fffe21e2d0aa6275a586f051c06e2575f3bf8549ad9f6c2678c541d0dc7bdf909b7cff683ecc5bc00000000000000000000000000000000163451ea5122e16ee62d58d6ccaf8cd981a29aa820d77967e69478127a76092e9bd0dc9f24a27ddca5b40b1fe8ce18b130b921d8cd2ca46aa6f3e0dc6ff08d77972fb0a248bd39e90a1e9f32be9e892a000000000000000000000000000000000faa1804b1f65a6ca75d032186b5dda63799a5fff3ffcf1f53eeb04bb5ce08be40fac13295937f34666e0f0be3bdfd9c0000000000000000000000000000000016a9086134daa2a1374fd8eb74ea65858ebe8b2990bb92972121ac68bd6bd77916203a1033ac4b163d863d9120bea0a33a5ccd9436b15d4d04a8ee9894c116190062c4e7cfabb047b585f3aa1eeb4605000000000000000000000000000000000a2ad31568d9778b306525e275bc4f525d86c04dbb98f48e72adae813ce9d02dc6d826a813ffa5b9f9d014e92de42c520000000000000000000000000000000014e928d48c4ca7640a5f5c55c8ae756fb6f03bc1a8e4e907ba89865ce610fbd919a024e86969c52a4216d84b37673cb5c7a5bf2cfedd7048be7ac7d2ff19d4f8bf0a94295ebdc5e792393e0e4bc27d5600000000000000000000000000000000041fc07f8759995530350fdb8712304083da882a5e4df8188cdad48a3df91a5f1bcc1b2a25fb3c9b59e2c935d579a9d1000000000000000000000000000000001925153fa12217d98007963237a665e56570cc666651c29729445adab3963d599a4eab996b192be1d49c7429d9f0cfe43563651d5f5729a0ffca6b383d884823aa3b0215fa057bffd8142199a16e4ffe00000000000000000000000000000000006c45218eaa27435aff594c2601276950bb99fb3c1756dbec76e609d163b2593933b5ecd5fd8544d4bd2d145821831c000000000000000000000000000000000a43ab2ea73a8e1131e184fbe9004aaea198a3dab575d3516b422c275f20c7a6e5d41bca0aa3dfe7ec761dca0ba6687d833323c3a668541ceba18375531c3781dd98525b49dafce4c4b3188c90f3f4b5000000000000000000000000000000000d17ec8ed30bbca5766def9fa375219503bf2f7322d2cc36a38fcc8471fd9d11d2a30ef004e39cac4d1ed2d33a66f7d200000000000000000000000000000000108e6c9ef3a5a41662fa16488243af3419e2d8e78c0311446186c96f20d9c15a60b5470eb95e0e58143a3c71a7565b05d422e21fbffa7d55270eca9c96bbefa29dd915aca266071673e970daa0ca9c050000000000000000000000000000000017f498e192905962fdaf41120027d49267523bee9de8e412161cec69c62d2586752d1da3d15e89446b5941a2f321beb60000000000000000000000000000000015e9e4eb30296ca3355ba9c5eee343fe7edcbf5bd110ca5be12f55191d0f07b563881f52e65588a8f4b3e03dfce6566e3ba7ea9ffda87131452b24a9efcdc91d1262d0d7550e5a6b787eace3577159b0", - "Expected": "0000000000000000000000000000000008b5f4f55def15b4590e978384fa0aa87e088916de20ff0fbd688ab3a13138f32d1e89cddc72acdf69fd86aaed6cbc4200000000000000000000000000000000022a02016f38156fcff83fceed881f96fe14e5d3410b4fc50e607d8a23ca986351ce48d6af970590f68aa2ad7181c9e8", - "Name": "matter_g1_multiexp_21", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001155a7d2cf81ee4f8d65c835ef422075a9453bb85b3566ec0545c1198b93749beffffbad14ededaa5bc6443736f77bb800000000000000000000000000000000073e4df0ea06345dba9fe772710ab71153e57152c74bd05d8cd4229c5ba1301f7e654f3fbb2a45526f1bc3b09c72366f16aa2cadacb129598aa459bb2e6b7fb26d1bcb7a49617b6ef8e57018c3db1f51000000000000000000000000000000001238e5a46f24e0f00d2b45bfad87f96140ce10d774f4a17c3df224b58693afa7cd0655e5ab202998f4f8b4b5e22cb82d0000000000000000000000000000000012628d85d982086640b09f046c5bf07b1cf718b5b4b20bd99d64382bbd8bd0112230609d78ecdc742cf1ebd24f1750ef8c02014d5392d30863a12102d1c9315839b5611dccfdb489207f918662513850000000000000000000000000000000001363b85a95432193800bdf353de1a5764cc2333b0369ca7dd539f230bffe81dce11288a289e0842f2db62a89e6f6af1a0000000000000000000000000000000003dc043b958167a900cbca116b097724e64d49897f8fb6a31df99e100be837e873328f5113a28c9fb510017d28d90d30d960ff678e1b46ada4f866adf354ba8c1514df10ebe7d88d2c8de117ef5ea24900000000000000000000000000000000175aef023d9375ae90e9f562f88e0a4affdd399c3755c1b22494445d4e7d96899aa4d5f77ab9392051de4cb7e400ca830000000000000000000000000000000018e3eab56eae429c09f9eed67492181279704d947cff0f1c9a4919dff5e6fe07fedcaf5dae854dba6719194f9fccde1704753af76295f72295645243ffc87ffc2110c9d8dfd20b464760ad965d7a97940000000000000000000000000000000018d7001b1d4a67d22399c5f9b3262183a47b6fc81786f8f7b78e80fdafb3c0c175756e602c92855e8ff9d99d4116e3a40000000000000000000000000000000018451928599da4a14442910a5bf125d97f0b67af4194797b3f54ecc9ef0be840a1e0ede13e1415391f57044d71fae2efd1b8760cc40d093912fb073c5012f910ae90f0a979cfe6d81c603adbb98289030000000000000000000000000000000013ca19bea2e93c748cd2adf682a123416823a2473148e59d87da33cabba8e0ff2516e5b2bc9a8fcea9dc4240b20133ad000000000000000000000000000000000433fa5475709a7b70044f88a5949064e32014f1d64826abbf60789380db6d5ccfa750a868d9902e4646bae766e241acab79d640b042664b23667d6c60ef9a5d59de72aee57a78d75752b350ce56d8da000000000000000000000000000000001236e6ebf0b704a18f85281b09a9552e8a478c66e59c9f5d53eb6ff1f606fd667a6f0bfe239970892c9c295a378fe389000000000000000000000000000000000cc5c1039850f3333981b1cd6457a466dde93e2355c2052cc325e18604f59cb22588b6d892685fd7843938fc1b5b8d8a1d1a2965e995bd4380d4ec52fe8e65e7fd99b1ca9f4f0c656adf7051c4b9a99a00000000000000000000000000000000003f86a5cabfe7792de25b9d8c58a283c5cef56e23dbf713851b42fc0d66481ce1946d1c632e38b9de1a55ffa0bd7f5a000000000000000000000000000000000f548b05782ebe160d487c622f8378786712cb5b68545ede95b34b08698f600e02e918fa2253a8be2c1b773cc74c41042cfbf2abd851d2c1f55c56d4f8b11b196c020c2584cb03764580d410d66784d40000000000000000000000000000000015a4bfb53e57dcf53483fca1b4dad7f788e48fedf8bbd7ac40b1707c35a57011a0c7f77ce6626821221e59d8185b9ca40000000000000000000000000000000005618adc16eb9771bfe731dea180e7e2b3b0c9537806349e653a586dea4633aaff7fa7e7ff165fa16ae0013c9672a783214edaf16742762baa58a3d22d5bb2305cb03a1326adc68adcd268428f82a1e000000000000000000000000000000000039895bd3ef87c094c9cb1ec77229d615e76dbf0f3bbd399948a70714d6835b570e54f46f94197657dc94d36c4a49093000000000000000000000000000000000f1c6f8b06ea4378234e99d16fcc439a64cad45a7f8ec567755febdeeeaea4f4b133af18a4c00b3778090c5857739b66c1f38916d6bdd5d379967dcd058ebce5887ef2bccd5fb7c2bcd758e374a195e20000000000000000000000000000000003007275e93f828b96d060e775f2b92d191d6da44b1441bd0aaeccc5abcfc7d2b5e9cfaf7b8497016ec992b13455af2c0000000000000000000000000000000015c1320efcddd0709a12a75049633dd871747e51f099e40908542a3e426d7a29b6633f5e69a4c0b5c32ad0269a969bbf1cb8c8303157f23987f8a2d206f3add697b9d0a303393008429e93cd35711f7400000000000000000000000000000000068dbddbfea897bc2b20b6f967aeafb0ef759082f55a180b3eda87174d0e036761f1be1c682d1a4c33f5113a6ff4e2240000000000000000000000000000000004ad9da407bd80ef365df2eb763ee35ae06074dae0eec7e2a36e57df4b3e5ac333e373cc60c1986543c0c23f3124253561ca9ab9c3df673b7ff8be098cdadd8354c17becdf82e7e99ce264174653007a0000000000000000000000000000000007f506a54adb1f763d55278419d4c18ca581b28ee369f33b848be495dbcce72c76533b809d70e26dda71316cfc3a1c73000000000000000000000000000000000a6c574799ba920ac58d6cea6d0f8ae249ef5310609904965bf86fbf88269530badbeededfcaa03892f1ad6b76818ec4681a0861df30946911d789a5da1f5b89c38fa1a8c0407b608122a18be05955da000000000000000000000000000000001424ab1e7a30035c4ee7d5bdcd8ef87a0aac284a36259742b68a5997e7dd3f2e5065e2238f2e29a23ac5ae9bce3bedc1000000000000000000000000000000001530257b63872851431a0bf5397dff45d6c201da58d7b779318beb70a5ee2a93142e4c5c43c3d65ddc65fe2df1af18906f0798b448ea0d10c84e2a8896f153b1ac3b84c5fed6a4ba6c932260bf01d34e000000000000000000000000000000000bdc58489ffec3668363be0a3e45ca2115bd5cd1745f86f1842ab82ae31b08a1f285e88dd4e0c7b94778f42d495b1f9c0000000000000000000000000000000006f4d2a07ebc588a8f9993ec6048092b6dad82c25275c922b2842253a8fe24e191cad4fab51621198147c6d1bfabeb0ba8b7de8f34053facf1338b54cfbe38dad73121a0429663f484277af9a230abe6000000000000000000000000000000000096e94b43a1dae483b49c1a616c010c25b660ec3566fb7d9c295d3b43c60ba4967b3f0abcc0634de5cf3fba14169fea00000000000000000000000000000000026146a58d55ba4cef1cfbc1db6efd46400b78f508ecc0b2eede8834eeb741b68ade43ef2300fdfae18c02b86e3386768823cdb73dd076ad95679a9d7b11145c12a81b825477f799300d1fd761417c2b", - "Expected": "00000000000000000000000000000000143fd63e2576a606ec59d017e6582711718a542dd0a4c84566fa4312b2d2bbb2d71c1e0ab8e4e214ef2376706a20e3130000000000000000000000000000000001e97699fd2e0badc3a97f6cc55bcf729142aaa13c51f9b155e5904382ed0d94fbe1d2553d602a71ac7ff39189848a52", - "Name": "matter_g1_multiexp_22", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000023a2a3e6e1c1cc57b2295c664ac26abd0f5bbecc0ed8e9850f90b04484c0cf048a76477ddde84e90cc452429e28b78e00000000000000000000000000000000194aa1d8332fd8120ed518f27fd827e3c955c2cbb2cae8d5e677f55963565dfdd232c83a38826621e8e66565f8e200b39f2e54f21b7f2116c30d6e444ca82fe800435cbbd72a98a6d22bac92039c540700000000000000000000000000000000124adb0352af8f18a631cb0078ec7daf00c2186e04d3ee47882d557b0e9e7fda0e0d258393ded20288789085583a97dd00000000000000000000000000000000053f94d0889a5122b6dfb1da2d7f13a836b9be039f127a011991c360c941e5dab8cb3c7ff3d7e128e52dfeb776aeedafc8cecea241dd6a924c9b9cc3d390fbf40ab897208ce9d3e4a148b2c30c25e7eb0000000000000000000000000000000009dee1a168c00632903b93fcf330b28ec7dcb8d6fba65f369237ef873ecaddd60a2d1af6e5b087f07a103f096aeb5e600000000000000000000000000000000006f90048b72dc28cf4cb40585925e62275d44df95fcbf1206e2bc762a455dea5fc6b830420d49b2415d259f8d5ed3ab7e428fab2c596f23bc3c9e9855b74295f52caf73cb7371c93c65370583f7fef4c000000000000000000000000000000001750fc7241cee9d71d95f0023dbc4b1f41ce794e9e7822a29a84c93b9374ccf0f11f931795fb824bb5c9fdb4f9e7bd9c000000000000000000000000000000000a0e6e6c76088200a345531f589ed883203e35c8ad8413575bf961b1e8d6716829f632e72fe90947dfa46745c9ffdefdf7d3d755410f77a0e4b2fad0f184fa9312b559785fb04c6020432465799ebe2200000000000000000000000000000000141d878adfaa6a3982cd0de93b4d64ba840a07c026ca443d6d4c2b6c36cf882e109d80df63b1626c112f9a89809788080000000000000000000000000000000005a5888d22a2f654a58d9a03c68d59cde9ab5e5356b2288033ba58fe2dbacf533e59344bdf30eed07698261d6269fc70557b05efdd02ac9d8e1453c82a321d798f3106bd18764140faede610ae01fa80000000000000000000000000000000000afb5e198ea80997e7cace2d5b271e3907525b6383e9d45d8a7717317655a79bec3a48800149d6bbb11a838b1338079200000000000000000000000000000000060dee81112b7e0bde192c9d382b1eb695f3a1b0b9ef7ae33b1c5ef8ad9134c23b4f473103df15a97bd6de007b828fe63313884abc4d430c06ae843d263f2efc1bba35f6cc270de05551e1f86096bb75000000000000000000000000000000000a9327207fa94bdffaac0a8741955968ee2278dc0fd17e99c6f4717e8b0db2ce7915b1b028c81d48380cdef05ecd5a7e0000000000000000000000000000000006c24bd6aa5f9c41bd4551afaa6baf5bab1729b7012951fd0ddaf2c6dd03ddc2030d49dc92073540503718a44260fb028faea236e782a8fbe27ab15f051ed007a61e25247f1f259b9300974f521f30c800000000000000000000000000000000195d0a7f5a351dff02a805fa08b2a793d9e0c74ae95fbf2f42bfefae8aeb0deccadeb9a2dbad7285c015ce14724879ba000000000000000000000000000000000e177a86f6aebee8bad62d77703d1d34a1b708e84216437c02e0694fe722414f2ef2577c1d39a45b4cfe6c73f411b1b413994f5645c6ce83741e48ae472674921bb2d9b8abb7d04ddbbb85a3f2f7f090000000000000000000000000000000000bc7fbda14f76ed98e78eb84033b65f286527ef76ba56dae43a094a23067e10798065674daa14f912ee13dece4f36b17000000000000000000000000000000000f69104995530de05660aa048993c4e08576488deaa177520676c9cd53034ef101fa3911e40933975aa958efbb1b931f81eda24db328588e8c670ab70431ddeebb0749b431bc1bfbd992c91f35d59b180000000000000000000000000000000001c3bfedaa15025440c6cd32115555fbbec439a9a2fbf706ef21e06a534af3f43baf46897158e211ea8821a5e32f932e000000000000000000000000000000000fe08cc9ff0fc601e5609ca139ae0ebe58faf8d2e2f4f3d0a1231382a15ebdc8f67271b556cc24fc5408daf3c7f74f875bf25b5070829e3d5a66ad24ba9930f3ad64767c51e432b51bdbe2fab470688d00000000000000000000000000000000032c376b26551a064cace577ef53077cde48c284af5633152c89ee109e880b511c0b90db1b30d6d9700037489f6984af00000000000000000000000000000000059c013cde62f10f39175335b76adc5cf7330ffa75d770d908ac7e0fba6faa7b9453e8d0215f0589af872b2e648ec1d0a9535c082e11b366cda0000d8ed0f92ee30fd2c4364c163a718518321c5e85d20000000000000000000000000000000009cb943167f21d9399b184f0bc0c2aca58dcf8e702614ffaf5407644ffa9eda85efa12dd23e756c5ccb5bbb25abe57e9000000000000000000000000000000000d4f59115321181962452c6f3c1e086cbfbc155f2c3019e51e73fd193e9b11ec891b2dfbd95198b318e4513c62cd51bc2c4cb49adce0292e259e92b229bf7965864a945de86eda3ce0bc9f1a6dc8b7b2000000000000000000000000000000000637e1dae04d31282c2278e087eac9ba8506d3c1349c6b98485cf32805bcad002e37d55667f1cc8e5e11f35b4d228cba000000000000000000000000000000000778c3a40e79d6288d3a93580c8f8bef7591acfac2c734018d61aea5dac020360ad4c69b4422f7320b87ff22e30d9a6a5e927f57aa85b2df54b4bddaa041d43766c8929c8b9146d723806ee0cf04227500000000000000000000000000000000069a54448ac1c9ee754fc28c9b671e84a67e884492f8e84e09e49cbcbcaf07fffed42820b1de61cdd0bf6314a2f4a1e20000000000000000000000000000000008f5512a1a70d3a61ee7fd6750813a29c47410b7ddd62db0426b3caf9cd7c31029638499c2e27e5922810cb9bb130723606ee8a5fdd9890b8017f6c432a45517d65328f13f3a2bb42d7115c02929db7a00000000000000000000000000000000078356cf80bc64c0e03da2198da5971b01341024a620ef4a455291b7a694ac3d91fe6f19299d725cdf7506e0485485da0000000000000000000000000000000015af5f875422c1e3ec6bfc5e57ed793f368799c2e068669656294be0de25eb772aebbc61358b410fa9ef79c72f309c84c1a77ccb4b32a762d60b37827ad6c3448c33af6af861c131adb5920ba3c2b8510000000000000000000000000000000019699fb3c6af71eae16b8ee123870888d646ac71dd31d0bb3ca365f728a6687540851c8539dee5c34f16871ca244ac6b000000000000000000000000000000000e68a278bee81ea53d4a52e84c8f534a0fb8c065bbcad9f3727917402746b4d1f611ba5064f0c3cea6f4d7fe84948dfd47cde609c38eabf457cdbd1e0c5366bf523dd5801d66a0282bc187d80417f455", - "Expected": "0000000000000000000000000000000009057b093eae9c7ab2455b447a681857d588819c94b1cdffc0e315987b095edba1ca727043667749c56591429f9173b900000000000000000000000000000000157bac2835d2f972fd1269039a7b6159b7a81a1bf4327cfbd3be8b7c779631e8beea634ffefd9771c910c612d6925384", - "Name": "matter_g1_multiexp_23", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015b6687a34084292423eb600bacc585b4e686251892b16a52d0783b1490a82f68f4eba5eefd36d147c4ec442d2eddf8b00000000000000000000000000000000151f59108d7383351b426ba8bebcf2a04976550aa2d10d5f89d5ed7c3bbd3473ebfa29c1706560866c8596f7549085cc3c79fe6374bf8f91bf7851ff935a124b54fdb5db498d2d37939fcd43bb93d29a00000000000000000000000000000000064e3333f828b1e54d201c043bb0f327d8c9af2cb96fbf587dcfbd55547d76784de0981a0ac86b65f4b8e45b19abc66f00000000000000000000000000000000172b76a242fb2bd9070ad26497a5c190d08472d3fbffa83dafc53d2bf612bf805691bc8f850da8c230ca0b8bd4fab818a59fcd2baa47621ebd90c5cd12b89f2a533ae86d537fbb61a14b1a80982c9257000000000000000000000000000000000158e81d92b789696efcdbd6e3e7c16386d6e5259a247991118dfbb3674643fb97a82fe404832cdbcbb58156c9548e59000000000000000000000000000000000fa0d18e57d64db246ee52980218c3eda5fb7b1029e1c76c9894548df52f69725fb7ff090417ae05957a652029d0a37019ef9fdfc5f0c4ac41255eb172d485317c124211498a8b9a74c0bfda15b986c500000000000000000000000000000000027a07cd6b7cf0219b57110edf07d758ea40b1cca42270b341b2bc33c78fb9cf52acc31676811032d3f618898a0d13330000000000000000000000000000000000e1212938244e425860646cd0258b65556360e832d4f2262984f4e307023896714731a2db10004e5509a1dc25f49ab7b8ba028831f429d027319a92fc0f30def8b97a43da456ddc79443d9f8df72cc1000000000000000000000000000000000bd589682a8510471ab1be8c348ed0d242548f0a5b85ee9eaab5af164367be21684ce2329a64a6afdc6a30ecc5bbb51b0000000000000000000000000000000008c8af9dd0e06a08f2da0ab7cdfc20100b94c04c7e6773a0351bc0e0ea503a69e5f25f250f0bbc5c7685795b279ae151edf8a6d86471f58c69c1a5e7518c69c34165e72ce84fbe0b7f69d9c2717e5d4d0000000000000000000000000000000015865d51ca8131cd5d2b0cb11c2f06e39b7e167ddf504d5772d478d48463668c4f7dabed00cbaca414b6ba96224c95cc00000000000000000000000000000000042fee2fb44ab45d310ab00896170a638940edb2df9a0f06c077bd00d203966d49694c82cd59c378445ae0577471221c0dbaac3f5e25ca3d1d50ebb31258ec4450feca1e02c84672ef15c49b4de2cebd0000000000000000000000000000000017257c7d5c733cb6e9ea1bc93bda4f36b98375147a119c376996beb6f0bd030c997ac52b1556d01152991738dc640788000000000000000000000000000000001155b29f473d9abd15514a0ae1cbd0b6a4ef394aa65f4fadfd3e9551c1d8420fac28acd5337fc5d114c092bd45e9e30d109ccbb8fcd4d4651b84f4708799d84ad0a717aedaf5a76d2970a7b93bd23d370000000000000000000000000000000009802bef3feb5688df77c86c74214451e4613d0260fdc5ed6e763226d3eea8a583c7dcf29eaf4c0bf16c907ceda76db9000000000000000000000000000000001447b1f7ac05cf8dce7e81de516d7303b310316f49ed5ef3f40f03db17926ff5f6656d859367805c889e07919224a6436326fded2b8a3fbf7637bc25bd201d20e3d4d724806cfa678ee039a39c24e86a0000000000000000000000000000000000057b59f849f0237ad511a75b66a77e79ae062025e5019eb71b7b7ad94a96c2905e25afe4357506b2472f99bc71a8ca000000000000000000000000000000000f10b6ad9fdb4f346c5b4a499722e377c7649a800bb95306dd7e2ab7542e59455ea5541f2d75e7cfb1da5dd03bf037a1e005efa8ee75dec8a013029292976e107a507ec09e3c34fb4baf2979fb759f1d000000000000000000000000000000000e0725ff4149698aa757e794590ce446a1589d9a574587575ef64d6a3c935fbd78fb60c7c840d7ef42eee8d72a5ce341000000000000000000000000000000000f0478a776be354e29bf8bd2710a8529cd01da31853d04ea722225bde560f2d9da302ce4f2634c9385ffeae379324b743917f8baf17f71222166cb9b6c4beb2e57d0d054cba3f7fd3a28cd3dc4b409490000000000000000000000000000000003103b0553facf8f3cd18967a758b73111a4a9987b0ceca3a20d6657a7e365be3925f63bd09990e33e1162bbffb63278000000000000000000000000000000000998a34ba445dbefe6023e737f3e35cc6416289185a26611301721db3a24f80dd784b001a2f2a745ffc3d0da5a9e6204f0f73e1b62561f5b0fbc409e6534ad9e37d1c0724b35cdd3f94bf6489e500fbf00000000000000000000000000000000041e13fb55bc9ed069c6d625ee08122efb0212f525b319b88197450ed1a60fc7283f61083ff263e4df10499b689498670000000000000000000000000000000010d931f006adaf737afd1ed2d1a631f519e6d1e9e22166c24830e92e3571e9f138ba901f5ac2f03192c9701067e7906b3ea24fb6447f2493c78a267daa158eabb70c1b60af8175d0d4594c99122cb442000000000000000000000000000000000bc0d401197ce816b692c5ac3ea539cc9658de56e48b4c3ac78631f3c529d4fa2a656f66098a702b4307fc56e147f962000000000000000000000000000000000d89fa2bbf3ad409a9ee7b7097662113b94fab95c98bd47a70fc2707a6aff23bf39944aad5509aba34930d7343762f6e5ed307c01d9e29a0571de07c62d5fcfc80749f02b8dbaaee9f69dc9263e9918800000000000000000000000000000000103cc442deeb800c14c9b3071c13d354d8c36d187e580073d150f4936ff178817dce67ee276d1633e003e66985c038cd00000000000000000000000000000000188b34fb0a4fc2408d8c70eab6df4c6c42d92ac5e43827044db526d4208acad4561c1310115448bc00feb9ee7cfdc40a877f31ddcb55d961bf9bc09903bd927451390922d647d589302855141cf5cef500000000000000000000000000000000145220a2f8fc61b2973d219042580a0edfcbd73a6bb6feea3655dd33bde8a25e0fb841a3b038049e554315100e6724c50000000000000000000000000000000018bf41cf4ce164819a8b00e630401f0332f5caa08b03bda27c205e8fcc5ea7a3374b591a4adc581f492cb07445c8995f145c1442ab82241f56c27dec2cd4dbfa9fc3cf1ab72bc521ab32a82346f8f607000000000000000000000000000000001416a39ffccdb10f65e5f06c8d7af68fbe894a0778e7270ab167ae2a5e917fb0eef1ef1b9fd45c991a45dc92a223ceaa000000000000000000000000000000000755c58a0692f8ff860430c5f75fa35366391f7e5313936e04230a1fcf1142c81b01e68fb3c888effddc0a498f264da9de4d1470f6cbce027465b4dc2a3deaca14e34218910aa76cb45d47139b31df88", - "Expected": "000000000000000000000000000000000d73a7edcbb7163795dbb5a5b4daca733e07f6498d336a5dea1a61c9edee346f74676afe0d6d39c39caa1fa7660ab311000000000000000000000000000000000f3d573970077a17967ecc0fc5e2e7dd4b6ce910f1891f444e36761e2ee3a72fce399993405761de29f9563f74d8b1c7", - "Name": "matter_g1_multiexp_24", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008c2f928feb8b65e521b7218b029a4f54022a28a18845614b3b2de93035228c282c73ce172997e6af93a402e35158ce3000000000000000000000000000000000ca2dd2c06221058a4a7a06438f035ddbd96f6b39fe80c0029f41246a2c8a4410961555e43d9b3d5d87dceb8d0be1ef42576b42e0728db912a78eec2b7b4c96575e341e86a7592a07a660c11e00448390000000000000000000000000000000010d919a48f588429918f1b2f05ba6e897c45b12d905615e045c1969ee8a7d9ae262551f546b7de764266d3ab656c3137000000000000000000000000000000000a40d6f247315e0440b0b8195fe5f7a7dfdb2e1be9e593f7933691fd22789ae94bcb6bfebf3b84afaef7cae9fd539b5379f9205ef0e3a85199c60ad9267349fdc7b6fba4cb765ab21750eb3dcfc48d8b0000000000000000000000000000000005eaa990ca9d57885e6ee3eee10b6e2dde6e1652a743c62ebce4871ebd2d3c8e4915418aea4f4285ba375ad1923b70a200000000000000000000000000000000159919c720eefd062ba8d72fd3befd953e1272695471315ff500830c9b5b60ce5f94bd6e966828d69f7f268bb423dfd7300679b7be7c71224247e8034f5d30a63f8707d92d843a703f0fa93160f65715000000000000000000000000000000000b7244995b7819857f716288dc59eee9ba5ac7bfe010937ea0b67ee71388a3792e5b7feb6890a436db4f1b26df18b38c0000000000000000000000000000000009a0b73360bc0ca3b632c0116f21ffdaecf37e4d6c904c98d6225a08d7caadf5024ad6b457cf31b924118ea147ff10fb0454b01910548432a0f706818a98151e38ff9e854f1faa95ad41a7239b5cc4910000000000000000000000000000000005c2bd45375084cbc4bfebf41709a87c2a8d52256a5e4bc162501bc119394186fd624c5d3d6749708be2811da2c84c15000000000000000000000000000000001626cfa6e87e41c2f0960d6d2b8e303ff8de00c78d1e788f32cdf548a5ca00db1f3a3c082f051b4bca93788243d9b0973685617371b27ba8898ce7f30776d817ff09ef68a9d6721d4a923ed244ae8206000000000000000000000000000000000f736c8cab0794e3751a9e13027a8e4ded1308c23be3d75b373780eb69f130654121435c53b62a929cad39c605637ce10000000000000000000000000000000015b1edb73501789811fc09fe0156344a7a4eab1f04d1fabc24f36e2ddef7c2ccf9643699cfc654b7169d8e371c14e8c660cb5aa2a0cd1e8c3fdc06a3a1f6f9b6d52a8cc2e98c85b8e258f72d03efc2540000000000000000000000000000000018dbc414f9e1c66af803b0c228a3fe77c94c29239e529cee652099d80795c460a507538eea6c94e99b78779fc0f3f33400000000000000000000000000000000151bf39a8e3e85b9361a9472e95cafc3ae11f7d0b952714d2836b903910a8c701e0c3832b8c88592bb8507694d9109b5addb1fe778c84242953db87d2307b40eeb776f17767c3a4311b5d2ffd738f151000000000000000000000000000000001241319f49e1bcc2d3f3eaca51d2e4c395241e2c5d8f32749a168e4af17570793fe086610432db1f93fcbbb95ced8b49000000000000000000000000000000000d90602dfcefc3860a78a8f51432a7608a7c483fcd86c0ee6a70f8ac723537825c14736240cbcf903c94d04e24e8ecc928416b4b4e965a5f024723fbad6ef2f65a1381e70201e26ccb40188dc3d0fae800000000000000000000000000000000024f26ba0c3295002418f7839b774cd305cecc3c2cfe20974343dafbfa6677c2fa6be5c546a1fe81458678c3548d8d6a000000000000000000000000000000000fc8ac2bf4585e8ac8454e3e424e858e1d67cb6b9a7181e26af803d8895717796f20abdfce0dfb390bbc0c7b16c70ffb78077a51f88236dba6d16d7fd681c631510106b0eb7448df456eb9ce758e74cb0000000000000000000000000000000005f24bd878cf5832ebcf008835f12f9dfbc78b2f6e46ee384b419928aae0e754d86809d360b0afc01bd8f2f8d79a685d0000000000000000000000000000000004aafc9a20f52d1c78a17e7824062a1e7165362ff265dddd4c3458c7810a8e59104d36035c93284988eb708ba196d6a2871716e790e1a0120fd26d169b8ffe3fcc0d03683dcdba7d2f953f05444076ce000000000000000000000000000000000375313e7ab999d174735b5290bf9ea333a62387996bf4df3dc33d9a5212ac0645789ef4153223d488aa2fbbcfe808f00000000000000000000000000000000014b792fb5bc39dbfe409356bd75b195d7023bf6f715a4102cf36ef05b52fb2284cc0739fe5ad628a760049c3624a3f2876ed0a27553db6ac6d3959ff4c9bc5807fb7d4f0a56095ed2bbe31dbfa41827700000000000000000000000000000000006ae2c85b2b267c86320c4cdc56b1a09e25f0f68dd208e898ac5b1c0645aca3dd8000eb544eb666f4256806123480800000000000000000000000000000000006670390bd47829d3c31cf2da8fdbbb64b92b47c78d3ab638727ea834ea6203e45a9a023060056c69c1fb567c35b671795ce72b30d989889c8779c4056e441bbcd93629efc2877d36d27f670711e21c40000000000000000000000000000000011c78f1b6d0ecc5523dc089852d95dee641222c743dfd09ff2e56d008ce523762bbd9c7bec6c18e9885b7022131ad30b00000000000000000000000000000000066a1aa8af751eac5dbaf2d3ae285e0cc7a975c1787178f550a42e8ba89fa74a1b18f27716eb7ccc4f21b7957cffd8e806d220f64de05bdd6e1140c1e409fdc13f43bd31cd94e633be38ecf22ebd77db000000000000000000000000000000000cbc0fe6b4956c0f7b9fdd36ea14a4d8284468c280605a31536636114759ece1339f06e050260bbf936b560586e7d12c000000000000000000000000000000001213bfe642bf78554d91820c362b73b7059cf20a0aefa5855f9e61a0490d165f6f61416e135473e2de54bf97cc14b8f6257da8ac7d23c5ed965d8bfc76a642a36ea6ec4c45baf6882021372e8643f0980000000000000000000000000000000007cac206b2d123cbe9375f5c913939b25886a51c857271a59cc2fae2e9d669af0ada833c72366f78be265ff9db049d0e0000000000000000000000000000000002db3f65b6fe7c6688f8d3741e448ac6ff322b8769277572f0198dd6ee8a99397aaeb9addd0892286a9ec6028bf9678863d017ba8c7ed138b1bc70141abc5cdc3afbccd8b1db5a6b5f775efa62b8dbc3000000000000000000000000000000000a60331f8e8b26e97366c0e4cfea158e78ac72d63f219e1abbb670675bea008609f7154752438d9c7758b2a2e076da7b000000000000000000000000000000000d40d90f498a2855ba35f1c4bb3c5409b87062d7857bd97dd37d6e5fa53c94c78319c6b16bdcbf2610ba379d50d131e47a16e23e37ecffd514d47199cff249415a6d366fdfaa82450f0744520258955c", - "Expected": "000000000000000000000000000000000ddd3c7964bf51207485b0575afb6430cf801bae388ff78a69b8173c27431e0593584f9e755b99a5b2ed3113b3fc0082000000000000000000000000000000001735fb40978d364be3521ada17c3ae74b2a738b412906fdf425bdf13ec09e5acdf29013b03fbabe889fa261302a7ca42", - "Name": "matter_g1_multiexp_25", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c52993730e412fec923e33f3da42adadb5d87290ac4448d7df9b401e28b3c7fe7f49c7b7e4bad5412c815931416303e000000000000000000000000000000000db71c91975e41b3f12e303bd8ad15f7c9836b146073946129ba3815bc3217b6116a2a03137608cdab8807d5834eb12026a9bd0a71fd58edf81459152782733536e960d27e35f9f84d00da256bdc118c0000000000000000000000000000000009657686875d82eaf4f93f3e710c467ced1348b60aa47658992771195660c4b96798cfec584ace3bc64040666de71f8f000000000000000000000000000000001375f7e985d987df508321c3d0aa7e7a06cdb78117248e19c3344dc443da319f49c00ff605c057d1ecd942e8b04a5e4ef1e168ab93674bd7f2bf73318a48ef17ef4464fbefd39f77c17ebfdb24d679b6000000000000000000000000000000000da69e098b5e2c8be2ba699f20fa38cd27b9c78025e071ecb2d9fba3bc84b1e673eed79f1887fcad9bfd5b0516236a1f0000000000000000000000000000000016c4ca4d9f15716b7efe6f9e61aaad880423243b2d5ffc96804fc70f29b633dc16474f7194b5e3ca12ab5a1627da580f97fb0d947d71a1b032070a12588b85065c19affd0db53e466f194f04f58dba2e0000000000000000000000000000000005370f5c60fb3bc36ee208e8c185613390748452cf6191bfad06c9bcb52501873bff63892066e0afcb01a0204cbc951b0000000000000000000000000000000003c7a2a97cf7be433864541082bd04467bbb42b2ab708866c8520a6582cce5225af13acb887b6b6a8d627c90e43f6e7b640f850bad2f22049f2f8aaf3ee57564fb38a847e428e252f003eaac465f7d67000000000000000000000000000000001820666eb1abd6144df2f21f2d46096410274e346ba862aca0e62d293fc64a6fd213dca4ddc1a4e414796f59db4d6104000000000000000000000000000000000a2521c021f2fb7beb76a2ff4c7ce96cf1d05823ad8edd9b2021eb39c08e0c7caff505ea76bcff8f6afb6e8c2e81d2f68bf91051da5bce0a51bcba6f4e1b3c9063743646f4e75e3e5a8cbc84e8112af4000000000000000000000000000000000e756ad1ccf0404e110a778f66ade3d10464bf8902f646f7d7ff38d15ef890bbc6d61d48122ba6edb799630a62ae084a0000000000000000000000000000000005b322f44f07d3db292c43f9ddf9ac9e44e8d16c07537bf563c98e02c2705eefc1013e627567ac2a03698268707cd84e8da771e0e827a52a2f7e79e0e5d93ebae04c1ed78cab87d4353f24ffc52099b3000000000000000000000000000000000420b819a63b7ff7ce541661c5fa8cb107cf00ae678981b3fc1b568174ae3864a8241f1e9b656cadeeba232156e66feb00000000000000000000000000000000136fe878b886bc14fed061cd8ff1fa2d85f05bab922bf18a1f09b55c331e7cc9bf0f9860e9112c2f6242b6d1124851dbd6cff707bff10fd53ffeff8e9400966d8ffba6d4ad6a8e7e456df10f8f5ebed2000000000000000000000000000000000b73d3549a6b2f76741aa39ee9bc2bda8cd55759bbedaa9ecc5802310b054b01670dc803938aaea547389d7b0ceda469000000000000000000000000000000000227fc49bdf53bc4f916714ea9789b526aa53efa1eb032c4030519608c62434443847cac82a13e2dd2eb48f73473d8e1e00831cce307cb44e8dbd5edf24f1535b837277160d2cf6daa4e862e57fe73b100000000000000000000000000000000167cdb86301937bff18287eb0b00f5224e674953d70258065e5e8370016cac8194ec8c2f44330adaea44426aaefac7d70000000000000000000000000000000007e9128bb015f01aa725796d7b7851f9c2819a8a578bc7d3af02f7328c922c26335ae9f87756f52409c446852bc710ada8168d56385722f339a5b27fc25a88034d348e3d533ff4dc99d28536c1c09a770000000000000000000000000000000018bd46832b101d12f95b21332b7259719c1f94c056118d877324656d285f73a4fe2cf637cc62a45647db92ba9d6c7d18000000000000000000000000000000000fe58fe2c19ee903d82da6da8713863423f10edb954606b6c56326eb8eea6c66cab63b0c816479f8107612391072c634b929ae82ded73a4876c041d2e52fa811882fb8e22690a27cb4ad3ca05169bbf00000000000000000000000000000000012db7fda36505d19a2c6ba5072044154f444eaaf3e12cce81ea74f28e691e4b7a730095667a71308db5e8322e80fc66a000000000000000000000000000000000fd0f22b05bf82688ac72e9ede526bf806695ff430ff3c750c2946d58ef90c778e4c5693d152e39fb1837bb10cf5f3be36999c516d4acdfbcd488d39e3073db9db6cdd0c0fd1d29d58294ace6d2d199f00000000000000000000000000000000116ba7b6faedd465fd4d1e5f42ae80c133a1d158614894ba663f87137f6108ae03b8e80bf32852ccce78b776dc224c760000000000000000000000000000000004c3702ff7fd9c74169ea76c00efb7b475d45efb12e1b5b700d47a970ed9f95f46e4c0ac66cd12fe79d62898b24b54a0fd0bc405e3970dc2bbd7dfe0c54b7c64543fc241000adeef4f7aa2f1dd2506770000000000000000000000000000000016254d89b0e2a8315253434d5444000d9b56b8f43d3c20d17fd26da4c8e7432d6e463b71a5b2a1a7f559a908d73abf6a000000000000000000000000000000000170c490fe3962fbfaaea1707bd28ecdd46ba29b5d8a0a35baf7fea4eaa47694e680e47e8a9f07d25078274074e232dcc36afa3c8581df069292d53b8ce3e35ca136a0b3f95a894958105fde9c77e39d0000000000000000000000000000000007a7fd283d64efef7094fbd6162da2fd56399765b559674c18d1cf6df51036007ad6c9af62bee534388ea093d3cdc3c90000000000000000000000000000000012fcf920eeec2c1728f3e620fdab1f8a0b99c6219f44b0fd19d0f7f4a15d1636fce7b4701f9c3963cff9b030c3759fb20f0a2bd678c5858be2a49ca54de8716fdeec84e1935b8f44545c740417efa7e40000000000000000000000000000000009bcf0b2d49ce38914ea877832eaa3f1034cec429cd9fe0d06ef36691ac8ac6b69a712792e31afc700872d08c2e0fa48000000000000000000000000000000000f5fd9d2d4710d1cc6c13c88ae602f584a7b671df91cd544697070eff3342d80d750e15e09358125d15fbf8a1ae8df93c8e420db340ef2c1b5c6a71645e303eee95cd93228770b639287b14b6a5c59ba00000000000000000000000000000000053fc59a0b84028cbb3a97dc3124927d6a0eab1c58d4c6d143462bf73c0c847712bf22557a1181750146fe63e9c9668b000000000000000000000000000000000c1fa8c1539ae702bc9441085a89790a5dcac9b18925cdb1e21b95c9f7286795e8f36e7a8b4c3f4dcfa12454624911675398541eb5a03271e2ab5ec2aeb2da80e634f63a050c25de98ad13e9d63d09bc", - "Expected": "00000000000000000000000000000000085e4232f0daeddb9e1ec8731855cf855d7dbc05d4b82d10b77a53306ee7a38ebf45bdeef1981325a61ecd754944c84d00000000000000000000000000000000061e32056ac411c3917684356a6ab3c7068f55d30ebcf8cfe446c68267923e4fb98596aded9740dc7944847a2e617fea", - "Name": "matter_g1_multiexp_26", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000070bcf49d6d066afa9b008fa22fd52f63b68a648bfbb5cb3eefd6feae666f3fd0b9a8447f427d5a9db52ba49854db7cc000000000000000000000000000000000947d708a02cd0a18342bc04639e8d126fc4c97acb497aa507e1c4c3912b04bdca886b75b9b9e1c5ca745acd090433119f99387baca30b9cf63ad10c445daa142fcae1ab3c0a366a068bb5efc9abb3a9000000000000000000000000000000001023942a16150e6497289627dbb0205a7c34afc704232ef214a6609125e90260d68b7c60600cd6f4859ddcad46c015580000000000000000000000000000000002da96265b7460ea6a8d51122bbd2442c6784d4f5bcf6d8b0b6eee6ec82e4d03c9265887f88c106792795837c02ed76e4283a1773995bbc97a6df107082fed4ba40e2d30c5472a25a7643ca9e78b8b8b000000000000000000000000000000000d5be6f99bb9a2379d1e542ece048164fa5d14e0c6c459180717b3da46e8446e9def576635ac1124e1390196fe97f39e000000000000000000000000000000001482d8339b402e3bffe61aaa298c8bae4286f1fbfc877a66e21cfe239bbee383d701d95a6c2b8193d67df5a551bb7aba7f4202d670fc3b48eaa92e925f48821d2ae057d90c5f184edcce9ea900ab51a6000000000000000000000000000000001969dbab76e6a158506b9dd38c647d4a670a21458a9552d903ac686855fe021a7dcabc91e712aa252de369c9234fdb59000000000000000000000000000000000b60179a6fa6146aa6e57b097f20944c123916c6722fd7e606aa34b8da579f6c126dcbb251da7917076a83e2e4b02d32a76cd8d292a7053c449cb98f13cf768c6e37da9d702af28c16dceacfaf9cdef5000000000000000000000000000000000e5fa0feaca8dca2a6b4a42e4a291383ec867f12b85593360f8caec45d31109373dc16d985a4702e3b5684774699e6b5000000000000000000000000000000000ae96f4a4ac0d0a6fe6aabcf902eb0765aee9ac81ad09e7e097d649b0c0165de6ad7e5ffd4ae7d8a272034f28c85ad6f97b7bf8acdfbb148814afee1df79aea17261dad6f78772111a6dcb021d8c79d00000000000000000000000000000000006391a93eb14641ff145f690c626ca412af266d50b903f7465d9a9b678025a35a68bf1962bb5ffe76ea07989a7d807920000000000000000000000000000000001a90846cba7c708bf8b4bcdb3415e17e80ffc9b48820d3307362327b29eca0d1bb7fcac9c09d09fa309829679080b36efdbd5953bc33bfba09fe7b3ee22c46c3a86f557e4b5f272853e67fd95a0f9b0000000000000000000000000000000000c9cc9547fd49cb22986f7a1dc1da89b05f5e7c0d3cf2179f22002df9fa2c586bb3f1496c0c60f8ba36b631fe74c8fcf0000000000000000000000000000000014f8e4e8c5a12b61caf4325d1e4a8505409d722e4eb16d51be5f01f863e5dc1ca68df1b83f546d22fc116f1654a3b30e9a331bb218b99fd38451483a10e8add23c9641b975af3897670884efef90d45200000000000000000000000000000000123292cef01012c3723b4713a345ea7648bdd8b8edaf76f149f1afb993f196f57b3315d86a374fb78a34486ea10e0c26000000000000000000000000000000000ee2389f669431df6697d79ba16d3e4d9bb4264c9ac146a772de6a9a8ac94760cdde7f613a4ae6592509b04b1f8233cce9301dc826bfe2988cf93c29ca9f01421b75ba63c5ed2cee1599122012ada36e000000000000000000000000000000001284787a11e0164bb197f69702d0d746975bd96a3b9221841c7193676861e97e11077b74e69f744c521ddb40689f9685000000000000000000000000000000000eb6c4c25fa1322f7c829691d938f87ba6bcce850404bab57cc3be8c3d0abcf123be8922af9967b83789fe64e2cb35f40a1cb530e8b828542fa4114de6aa936bd2be5ef3a9b7a0e20e475022381d62d400000000000000000000000000000000069f8970964efa22facc786291d6ffe860929121595fa713f4a12f9e99d8508d7d20f7d19c51514538d1ce89d2adb78500000000000000000000000000000000122bc9405ccae4e409c1aa22b36db314a19ef6e67a572f7ea67c247085205302ad12ef7f83d3616279892ccd3c456980cf2f0c33bd044e8c4468b4b7e137ae294c178e7b6c9f19878331fb93220db2cb0000000000000000000000000000000017b92fbdb00429846fb30633a2c3f383d32d0bd433d5a46e27d3c7bd6880948f89bf70b3f1639a18d308ba80b7209df00000000000000000000000000000000012374e8e7c1fdaa4ad4a2d8607afb62ce939bed23ea42a51fbac995e2c3026c2daaa338be160dbec2602a0fdaa1e9897e5f460dacc592bb947ff6f1c15b8464824aa5c957a645a763138ac1581ac576800000000000000000000000000000000004850419631e3de2617bb6b51ef19bf14dcc9f4c7b24ae817cb239342081947f1799080cafaf51ed687b9dabb2f3581000000000000000000000000000000001108a0463d38d617d0a778bf9478ab44050ec290e442ac41e23b526089ab5aabd5819a8f08f903343e93177ce4042c82f26a9736f728e16d7b8ce0cc59e2ccc848c181459fff4321982c08e9cac57946000000000000000000000000000000000c9ef168fadf7a056e6cceef0430f65a57b0f2c3372a5d3c533871c91cf81c40d3459cfdb5f1f66f53b2d8d50124ed15000000000000000000000000000000000483ebcdc219c4c361735aa0ea96c00c4908b9db62ed8cb565d25a7fa664829bcacc37a5608a3c3ea3a42ecf74708ee9ccf0a9be4775d65bbfc894f8ca66fa6f69d4249ea7f6b076fe193f2805e64f94000000000000000000000000000000000f7232dfd8367af413dd078f9d5f47b8c76c38b3ccc4110fd59764265e6a368fd4609b52c21f8e6db2c73908d4ac0b3d0000000000000000000000000000000018433b00ede4de21cd6a1c78c5d280af98b814f0a60c625f0a8f355be43d8d99346282b6d9911c4d4074fe827b55d726fc6bfb37cbfb10a1ffdfcb91d9a52883cb9a606f4ffa8849a6e07386dc9bb3400000000000000000000000000000000015b0ef81908ae275b2d5c3cbc563b8424ee0be0e1f2fb77f67749a79b7730d33028a136d133825da14448b05bda1409d000000000000000000000000000000000461c575bf65c6c5754a214c2e72d6d24df2cc228ae1c9f99d75eebf9cf48f20945a6483185337aa7c0096543dc0a527d94959e16f6d780628694075ba5aa1a476d89d8fffcf4b4ab7e6343c011fee920000000000000000000000000000000006e7385d061bafef2c731ffedd01758f153e2635c7f2bc42ea2efe29931697a1c50e4a13ac420572afc523b7316190cf0000000000000000000000000000000018ad5dac1577c9cc1e9ed30ab277dd381a6babc17e86538570abac44573a8c2439d97cbc370cd2b5d2c6509a18dbc96f122f3a5e940ee7e5038421619daffb8a6f433605f37e78d863f814b51b2ec4e2", - "Expected": "00000000000000000000000000000000020da97236c2405d3f1bf4e937d8285014a190bbc59a17b7163a292a2b825f086db5d371776988d1aa2d7529a64d2a4e0000000000000000000000000000000016cf6d7b831a81d0c487bfc3380a1dc8a1bdada61426a457993f7d6c9c8fee9ee4959324bf7a2425b070aeace3cdaff6", - "Name": "matter_g1_multiexp_27", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017df783852d1f1f9c6dcf1975ed2dfacf3dc0cf942cbd7243a0cea7907ddb289f378ae59b30661d06d0702792ea9e9e2000000000000000000000000000000001717bc4192402e587400b4e7243db7e79fead2f878079c3af998b3a683a0539aad5d6c1e5da6e0a00ffbd10a2d891ff2b3908c739d505a1d6fa85a6dfb7a155202710b45861f1a8a7ac7bb3274a180cb0000000000000000000000000000000018c9cc123fd18d50a7c878b31622a3727864fa61d784285b990fd116567c69dbc7ed872866db2166c7af1812157af9040000000000000000000000000000000000f38e55466a6d1cc2512c1282f74f5c0c19777365819e48606c0a86d2c6aab8938475d15a74f24db868802fe935f6107e0e27a8a416eb38c989a66b84f037a5a24ef3358e20cd553f037a0a2461d310000000000000000000000000000000000816580c761a2f54c386cf60b1417d51a310bb7569a50b475f8d45f13ed6c1f11640079b5d6119270d616e77a489069d000000000000000000000000000000000d9af7b25803b611351f00daa88464e49b277de8d8fe22284a9001a13ed63ff931937d27ee19ba4000ebc212fe03a0390a3cbab01c34856b892aacdabe63d0a0c241ebc137a88c83ad22cf38997b211b00000000000000000000000000000000032fbde9d988ef200df573dc99b087a8ffbec95349256989774194dabea55d970ba303657837bdcdce3b59eb54669c86000000000000000000000000000000000d65e89d8df2a189761e04d35c9f4d3a5292d1dc0d083bc9a982a131b07df6250cc969a3534808959b583923bf02125cb386bebe0e49b7f07b0ac61b15306c2515a1ad6fd76a1825dd29a60e845c0e4a000000000000000000000000000000000ed3f47ea234f8fdc16e97eec7f4521941c37acccdfc422fefc6df9c1127ed293998945fb1bdce89ea18b9ec2b6e5175000000000000000000000000000000000a066fb6f1d69b88495bcb0f0eeaad2a41d5c6764e2dcac2ddb4ac340cda72d7b51b7901c758df15ea16e4e46c7053298902a82d33993a10c56b2fa3333cabf1c5d47a9c78354d58f70ce4807cf20628000000000000000000000000000000000ca7faa768ce5ddb6d668436e2e1692893d07afdf7466c00bc8c963b80cf0d44f6eb9a2070a7bd889ef692a81f9d76d8000000000000000000000000000000000f86fb53e3f061cbe777c7aeb63402616c428216a0c65d5d5a13cce1dc31567a4051420d54b4fc93c6bf263601046712426a4e2317fee033a226a91a52a5830f9ac2cf5f329feb6bdb382438b8a39f2a0000000000000000000000000000000011113946d8ed7e5e545ecd0ef30de293206f3ac50e6010fa7a1cb0371f47aab2d8775c51172c4dbacb05414e65fdae10000000000000000000000000000000000022a7b8af616e4076f625f8151d748f4f49e6dbe439ec695b854544f8a498c7e261c366a4c81be5b9cad85a4eb07c36de0390c05fb0dc9b4a3f76b51cf952a11b909ce13f9abc9fed6a349b8efa98ad000000000000000000000000000000000d863702db9f9e43ea311fdd7e0d87495ed0bbbddaedd3333108704417521b3da4b8ff0bf904710b0200453ecb2948620000000000000000000000000000000016a520d1162c7070030fea7702420de2a6e0f255c28a89bbcaf663c0d6761d201f07d86adf5ea6589e27bf844abf85a57431db9e576643f93505b5b25836218759e736c0d650a5221a652338b0073eb6000000000000000000000000000000001357cc987a4ee7c7bc063ec8cbaecbea0ace4b80e3af01f74d23801d5d37326ab5732222f60ad864cdc8c5dfd3edb37f000000000000000000000000000000000094fbbc2936e1730a1abeb42e58818ffe6dd97bed27a1e4fc090388d943763b055301852222503a2d2a9dedf69b3da26745a32591e359efa41e9ea93a016d2eedf1da112cddbf31818e8d687b36af2e000000000000000000000000000000000672e9a4eb4e8be8efab0595bcb7a6fdf269db71dcb585c12f9d7c1a8414b6e11d91373959d47a4c64a8890766f68671000000000000000000000000000000000203f3804abe330bca60b7bf9925a626eeae79d58ce7c71658b2fceb8cc93da9d455b6d59bb58bdc23b58238d4f01948ed37a5f4bfca6b77ff9e4f7e03bfed52ecf02a8f84ed3da6da2787a4ee81ad9b000000000000000000000000000000000c4e95c27fd983c31fcacb578a688c2fe055516735b5f1ea1415c5cd29592e7720eb2f548071fa3ac642b70e339757dd00000000000000000000000000000000067ab19ad1c97a773164e812771aac69fd5d199e4f60eb28c7aa5f09dd9b3adea959ab4ad47683d27394714eab4a40d281633dd6e729bc17ddc596cb1f17dc6f0e50c052a0b8c5a4c83900d918a9eb560000000000000000000000000000000003da3fcadcafc5eff08a736e4cacb1d6617c3f0850ffe33ff1648f783a4467163d1ddda082ba0b54e678b171b1f79618000000000000000000000000000000000a273fbd5fe99df4f724fb20ae0fee994823d374979ec7ff23dbe148f6977145de9a1f20eda777cbfe0fa4cf8c2a8949c6b019d29219b57404baa955f66cf1b2ee6571ad5b80d471ff6db569e32a1a5000000000000000000000000000000000015b74087be4a98f4c5cb442e4e893d4d92602b1ad36d0f038f232ce25b53e19816f44122e8f5c821b40a0cb36897fef0000000000000000000000000000000017e50b1e84c7e767171edbddc397653c35b34141bd69ca7123792d6f20532f6daa5ed18615bb364b72744f96d4a730be6a76411ce02b4dfc84ddf62ed26508a2dfa5edb5a98a6a20dd69e8b8e7ad2f5900000000000000000000000000000000131517851372c44894bf433d5162d0da394b87a9554e9d4f6174d5712dbf69f756c5da1534eed80f8596f906f36799a100000000000000000000000000000000130a4583c7529129831ad621cd1e04a8fcfeed67ea96db4932809ac140a089e6252bcd101f17d4653555b1bdd9ea3a9b5906098e4ad7e4eb2e996075c7cd660fbc399bc942f9080404b9d0758c4ae14c0000000000000000000000000000000002b8d72148ed7076656128040e7dec82ecfc2d5ed05050b27361a85d0fae6d90de6dc32dbeaebac039187e3883ab238d0000000000000000000000000000000004021fbb748bdffca854bfc5de8f69a9bec478181477d3c6e41a7da2fab3100f7e2737ce958c046d6447370d47e373ad94ef8c281a9be3766fe784ae017d93f608dc2cb97cbb7dd3e3814b5ade845d370000000000000000000000000000000015d1c5bda34c6fafa52dd3801d94a04c53a3acbe43cdd128de3a346739df5afc6dba58d63c7cc09d18589c41d9679cff0000000000000000000000000000000014367ab7f03febf90be2279a87890527935725880ae3d418ec055004f312fa0c42c8f6fbc9c319117f6ce600d86910f16feced33019b3b66d335f2118cd22b2952cdf9757fb3a0cff55b7c4f245fb438", - "Expected": "00000000000000000000000000000000130db02ba2d24a3d70439503b089e6da4cde7b5c51b1d69774b38ae0f265aeb8996e50ef077ec12199ffa3d000adbf38000000000000000000000000000000000de25ad8eb2142051fb2c97175cb4cb2984ddcab65dcfacb76cfe60f6a47083a22dac4f6e06e357a194249b7363210be", - "Name": "matter_g1_multiexp_28", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016785db77cadde48a4ed0d2f8aa9f91bed9387a4766c3566217afec80b180461c8e1017297888e9c5896e509a26137b000000000000000000000000000000000025b26ffb3fa42b1a9e974eb23ada4b9329d670e38970e7abc937463e522887d777934895be0cfbf13d213b3b737a5f6cb5e7df372d346fd13faa90b0d6961372ce2f32ec379e5e50e7ed8a13942cd9d000000000000000000000000000000000d90bd38049f2a8de869d8a748c9ff3120542f38fca6e8d5fbbff86baaabf0f19dbf449cf23c043dfea322d99837f7110000000000000000000000000000000000ede89c8bb8299726ec685765f10167c5b844e427d3c15da6ec2c1d97de174819d52caa96d5cc938e93dd09bbd1e0d813a5fa1674c20c97d08608d200f3f7611010e6a25a790853ed4ba0c5aacf111b0000000000000000000000000000000019e1e2706e878e60bf6fada47a4d4028750cb27749bcf8fff531ec75d1ff9b3a1b5e0bf19e2758899c3d8bc96a18a0540000000000000000000000000000000004b5f00109eb4832ffc9108740f0728ac059c613654a771beaaa028fef06b6cadb9dd182cc573d7ada1dcaf307a8bca4ace10870acf190b373c19ce615e20e5cb96d3c6be3ec155f2b29825f8476b77400000000000000000000000000000000013844937de287b98db2b9631d8e36bc36ded8bbb3ebb2005ea5ab39a4844fa354b62feb7433b8fd3e72aa89ac8e4ff50000000000000000000000000000000005603183a5fb09ffcf6faabcb5042328496f8b0f83e8fe9031f9dddfefef43ee4525d1afe859177d4b9f966599005bdb8d9e38d9383f09cf0f8a8077f1d1dba091ff0abdf7e77c3b65c2df48d6c6f5360000000000000000000000000000000008ad6b2bb88897a2e53d4fb9910b6244faaa045ef32a2fd223adbe6e0b1a5c1683dca69c0e9515dccf7e4589f1e69bff0000000000000000000000000000000013564245d53366d8468b51f88becc288b695879a70c3c753933092904b9fa5e64e39be30edf1f5e9de7eb29c4b3cdfebabeffecf9b404c6bb2e2d0c78fbb8609a38e3d3187587c3848e8f9781b7e9f440000000000000000000000000000000003b587bba9173011da620ff930befccb7b43093052636d6632fb6e9b59b8d127ffa0b7829b59873ae347eccf0e6c86c5000000000000000000000000000000000363be6dee6dd9a1271b24ff84c6557adc62738805b31714c9f7208c320aff220c02b222b96c62af96f1eb42b5299a63adfe53846c0038203d8b8df0cb636aec7d4ed7f78b0b0c1734be448bace08f340000000000000000000000000000000009b403c5fe094f6ec4e4b9b7d098c3ca6fcd838e46a885506ebe8cb3d8b29849a8f3d8f9550f6d33315e69f6c1a6654a000000000000000000000000000000000714a7aee8bd6d754b9bf0292be50836e13ae886f7952c61afb1b45a02a2c378d6d22eb3eb882206a3141e43658a068c06e9d4e41b628be51690b86aa8938db066c052f3adff774d35eee1e332312d3f00000000000000000000000000000000115f7928ee8b8e47af2739dd70bbccbbd8c4c4f9b92868b981e407887b448745514b67164df86126a7aa53af9ea7a0ab000000000000000000000000000000000772b21e2bdc688f0b883a2ec5accd48a13ff3917d1c5ca8896faffca7e4097021ae3c348bfc2e8174db93e079979967b3d349b1546a8c235d60c41408c969a0fd42425f8b5ddc1fa5102d2821bde2c60000000000000000000000000000000011bbf90f59d646617a6d074f5938f64232550e189c6d8105bcb67a3607e13b4668701f64933de602e5daf7b0f4f50c8300000000000000000000000000000000153ff6cb6a6dc6b6ec086e2ea8122d23e2c6abb8d59c7535fcbdfa721ba505d7e9113cfac69e1d81611c72e872071bdd29b83950e79750e9827ed92856e4d1e1b5f0b47c6bbf3611a1fef8f2fc47659c000000000000000000000000000000001897421ca9a740a1f03d67ed31b3922d7f6067287b4addef6689303571b49bae574c343e967dc0f270aa4f91381609520000000000000000000000000000000007ab14771a4e256ec4009aa03af8caedbec4b3ab21d6499041ec58afe17175a656a7600c4bdac42c92efc9d2d21b48bb6b5ac07fb4a184dfed685b93d2265cebd02a3296a3b0416cc6a115242079752e0000000000000000000000000000000005e4061b14fa76d4c02d77adc7e07881dbcb023dca9dbfd1301cb3252410d54db87816a6403d18c2ea8c18027674133600000000000000000000000000000000079d3ca06d0878a569a3984858cac6daf967bacb3fd540187e47dc2c0790d6cfffd1ae1f377c75910f0b9a17d2cde2bb3a7a25ad9f02bf51fd73550ccde12374d9b151f2f6fe535bfaa43efc391f7897000000000000000000000000000000000e2814ce8e1011c37f6f7c38ee9543c65d0d40282793dec81b195b2d4f4b55f2d2b68416eedc6aba6e31b2234c3f08b90000000000000000000000000000000006ddeccda49ae15e5574bce201589758d7ab8baaf1348c30111e997154b6ba413c03e939e288fd95d808017387f1882947944c8c814f143f746175ba0b2d75e2ae73730a265d869763f0e986c088bfcd000000000000000000000000000000000b78dc15a4f413ea9c8b347cd82c278cec530a28d239694d051812c4af08b5be888064f54d2fa2278ca4734549cdd41b000000000000000000000000000000000a8c5ecc1541fd79771037e247357599146fc46b852536529b841bf4b21978a85dd09c01baf8878bc2b6bd8e36bb93c030f33b187df3516866f259ff959d57fa9c53323d5c851fdabb96e5ea470518ac00000000000000000000000000000000172140620e46db480b2a9f1b7f9d0b374c0fa19145e3349906aba351686e0b75305db408fca3465fd263d06157ea471d000000000000000000000000000000000c20ddfb4502ad34e0934812913e222fd9aa201b9e10b4af688031d2202663e9c044cf3374ede037ef0c7aaa82428ccc4da8401050f30459e026a207ca631f0684a10813c64ee86dbdf06b7b29cd97860000000000000000000000000000000009d75caf6ffb593ff15d5635502abd9ef88675210aaf98a73bfea25888c90b63de14501459a038f07ca502b2b0eb98ea00000000000000000000000000000000091c4826870da1d2d7da43fabda1311384f24bc6d7693ab92f59cb76a06ea129911abdc22addd72181c3ecaa15dffc884d940555d48649f30026f70450b2caf2b8f7148b28bfd4349458ae89c323512e0000000000000000000000000000000011e977de99564d61c5e0d1654ceca0d0d63dc09a6dadf6baac980bbb97f38513459b391e40c09329d22be015fcdafa6700000000000000000000000000000000119164ddb3240c59428f11ef8c7e0469d219a591b926296f394048dd59a62a21ee2dbcca55f79df5cac6b784a2e06bc5e140e30424d2cccc91be1fd3a62d9ee49c9d64fa062d9350b3fa567ec21bb06b", - "Expected": "00000000000000000000000000000000073edf80ee80c7d1675d05f8bed28da759098f44730bcde3ca1a9a8e286ff1791fbf22bc36de06d88b20f7f1422dbe38000000000000000000000000000000000d52fe400f41b902f8801063c0f3e793bf643c027676e0a1ad3860e5455bdde58d988b929582823e5d7ee0af8987c551", - "Name": "matter_g1_multiexp_29", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004663e332c105837eebfb9ecaf524a8f7f4d651f3eeae6909824eaaa6250c9f7fc212f98c6b3d4c08c5198477f240a8300000000000000000000000000000000057144a8578437c9a10a7801fb179e417e9bbe1b85e9dd8e2208943978cdd77a8345d682ba83950e174c6cd39c9eb936a57b2c351a7946a20cbae1fd789ecc5f77376b09e911749831e9b5680185b1530000000000000000000000000000000017c44ab586ecd185de616da02f99ee799487b32baf2470871865baa2b2e3ca20f61e6c82d741853b71c5578199d46afb000000000000000000000000000000000c77154ab5f0ba817b30672367bf1e19f9e53a95d7fcc4565f82f604a07d5eedba2182cf1bcca2371af4d1bd09146cb98fbff9f8ac4ad10718d46a857ba28f182263bf2d13c8b6a00902af737dea56160000000000000000000000000000000002df334ee40a5aa144d3727ec6c19d8dac476c01935e7ddbfc164112e35cca9180ffdae5e56f1fb31741c327b5733d6b0000000000000000000000000000000006c1721530a765ce427eacc4e5679c42591d5d1443f0a1bca8a87dd19d6a33b731db6561c50a35511735324c5f402858b061de16f4f609c6947733b58c6444fa9549721fd9a2459652e8e4b8c69b5d6100000000000000000000000000000000016682e225b46618ff794f2da02a82e40193289c9df4ed6985b4daca3e9ce9ac6e8ce84a3fd6776119ae1a2e84f62e73000000000000000000000000000000000e383f55e44fa8528e80fdf391f2804f7b7f3367e0db07b78647e9ceeba5fb151a5b867bafb2d9c07a6a572ee71c2714355ed5b57b28451ad98fbacd5ae87551b7304e4ef5cf7b7dc443a66432406f9a00000000000000000000000000000000176de8a3ee21e803ec6fd42f7f297daeaf1541c08c5c359e286ba65b78d7c31a0a630a2c73d2e886cfcb289783f30cf20000000000000000000000000000000010645db8d7d42e004c4f76bb2fe8b99a3177624ce0c1f465e67f3767bb57ca80ebadb12fba65bd021106e17adcd8553430b6eeb01874ff4b0fb07dc9f23d8e45455c1480eba7fb3033942214e85a77200000000000000000000000000000000006c151767d1066f9567ed86f7759a6f425a9a130a4530a2dec0913e4efe2485dd4b0105f453e90bf27cbeee5d0482af40000000000000000000000000000000019a081fb1fe2893f1919628cb8a3b332ef072971fe6ea7fbaf79d327440274a589045db5d3f06d6dc32d6bc7038c528b89a697a0e8d2cf512edd2a3c3df354eb30a3eaf697779dd9270234b367c2b5ff000000000000000000000000000000000d19d55d1fa04f886078bba50e09ece3a394f3413745785c16d17c5936941345e42e4ac50cba055d79f2d813c69e0b20000000000000000000000000000000000ba513864132f44be3056d3d3d1fe8d10b8be954e785e3d07f816875a3454fb6d44c1a6da8c9644648b46dc7d8a0b67120b72463d54ac1d8f1b3f56f0f98861768b05d5174cf1883dd8eb0410420d5620000000000000000000000000000000019cb4ac7844effff88b242db9908bd8773d91cbd8e076127493c548350bb9f8230d57a3e9c4e4b212e5686bee925d80a00000000000000000000000000000000021e94fbe9881b2f5ce2e8d777a33336fa21c24818cc1b6b699f0bf5cf1f22d7b9fe85be05d09509b88391f78eadf14e3de7997113708f9d092836c2b0b59abf710d8401baea6de73ee0689436f035fe000000000000000000000000000000000c6429ad7548acf43bd9e7fd9ccbb09b5b9b4474937bcca985a2d00c62cc8b72e07e725a5d447e2a92a6bb9fff0c50c100000000000000000000000000000000135ae562ac2225bdfcbed36817c8deadf892da1f8982f4bf53271320bb4e702022128dfbf9e48fc6623648878020c1a67fc3d0560432dbb721f8a0610f0db31dfdfea8cd5ebe8da3fe3b8ac5358dd4400000000000000000000000000000000004a813c60a1988f7983f6ac644a66369153319e3bceda90fcef6fdf3e53ceb04b2c5d240cc65aaeb2530e8931f1a962b00000000000000000000000000000000141411938210cef5576dacba6d521bc46b13ce9c1f2a9aa41a0e9b56639995b69b6198f2a406ca5e471cb0a48233985ff0b271f02031a126f8632e30d8b17cc5b57de7b8b873e0971ff392d4246a40f400000000000000000000000000000000041855bc5957b8649451b7d91ef58fe8e0770b113ea3009815e60cb36c9b7ab797b4448d3747fa9b64b7fb50af906b6d00000000000000000000000000000000048f78b763a88fb7122e117ea4946a631be83b5ae456f0c77a16f3f2b546802bea7117eb27e23a5db65d616966bf2630f8b5c136aa5e2d670edcfb5bee9ff6095d85a332ad55763fe1e5e8babd145c070000000000000000000000000000000003ca70d52cbfe2c097c17bd300f4baba1d03951c6dae613bfbbd53f68598a71d80a285af1a16365b5b82991599ae8fd0000000000000000000000000000000000ff454d717d8518415f23ced167ad7ad1ec76c437e29fef81b5604e8bc628b320fa39c192f32aa6201c2b5b4035cfddc285193e7c10646a4601787edfad3d76e19d5b013a0a954873d92bd5293d3258200000000000000000000000000000000098363ac967c6800b28c28afe92c1379574ec11e0585a0319273aaa6b92322563ad56144437569f3b9cd70ba9e7f9e030000000000000000000000000000000006e4aa226ef031c07150bb231046f36b8ced6b795b3e3f25f707435abc214f14e0c420c699f9c880e8d647ba85d467ef35bb2175fff61894ccbb69d90375df627e925f1ac430a349e75580dd39546e440000000000000000000000000000000001ced5366374fd923b3196d8f6e35900b80d01eeaa6ac41bf7d05d1fb7d47810eb8cd2d1ab793126edbe863be4c1224200000000000000000000000000000000010b27a94ae8413494e0560a10ac71554ff502be7e86cd9760b0d4ea7d1df926cf7ff1661b7902fb93ebcfd1542619caa25856e5fb9547c48d41783bf2cd13493a1fd71e56b9c7e62af84a1f6cdae1c800000000000000000000000000000000120ffc413256888669dce253043ace9a8c924f2996d73ef3a64d76d88dab415c870071a22b97da222361dc02d91cb25e000000000000000000000000000000000940f2259f4fadc3bfbed20ed2b80bdd86f30a846d6167661339e15548f6e57030fcd0be99496fa406a2d025077a4a4e1155c0b9c4185025310e8020eb52abb6f2f1780da15e4ba81f3c9a88ed1b4a640000000000000000000000000000000003ea26434b5bc703c242cc5e84e17be5c7777758f0b232feccef6d200db9a03f10df46cf0eead48064f8dbbccccc3369000000000000000000000000000000000649df5d665a64565079201123e954e78f07177739d082c2bd0aabddcc13f9fec6ef082a1348a369e446b82181e52aadc5610b2707ce84ce67e82d5c0e5f5cd2c90925aefc1e39468ca86475012df045", - "Expected": "00000000000000000000000000000000110fac33d46271daf3924995a4798b3f62c79562d3b44f736b91add9f2af779a614d4b12a9c0d7c60bcb1f104b35474c000000000000000000000000000000001592121fbb147085613d1b647cb0e4a7b895bfd4e5391b45bcb287975bbf0e5218078d3e88f8383a506550ae07c9d167", - "Name": "matter_g1_multiexp_30", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000033f3c31337bc48622d27a9a3224a2acdb5c538a59b497a4a85840c81cff667ed0a0e4e3f4bb23a9ae53c1e79ea54cbb000000000000000000000000000000000cf0dc22af4530260cde26aa0eedc83a0ec3ae87d024e6907f3d22070e1054b3d4f24d5ace7218ed44763af6ec3f25ee32fac970e52778cc90396a5ba92ab98e26499eb1ff17d4bc4c1f78b64887d3f1000000000000000000000000000000000935dce5baf85335575af5a6801b36647727c3e28f224cf25227bfaa52fd646d6fdf0f24466631a93506a58b5f2df9b70000000000000000000000000000000007e032c51e2d9aa53a3120e5777a14963af8a9fc65dadf5da779c5ade6aa043ff496cf4f33e2672dc5e10c4a06dad86a6583bac9672a77f2fe62bea4364aacf62d5e10eb3a757fa0595a81f76543e86300000000000000000000000000000000178e7b4d05c4b7762b474649b38a5ce999c67ea677fee77115ce7e55207d87a82b6d05516ab41c2bac294fc382c0e12400000000000000000000000000000000126e5aef1a9729c73278b805cf102934239d1f706bb3fc3a81f3726feb4b3d2fd8de69fff2f20d5e5217edabb645e8df5a8e1d77c9e42a187054c938a8a5b4bafa834021b727036ed3941b1c1deb9d030000000000000000000000000000000014760b82d3b4949c67d38c6d9172e12bacd52ed49f442d781aeccb7c0444407629e3b7d5d5e1be996940966785940e46000000000000000000000000000000000aa2d6391e40e50ab9ece25786a42e8dc657e9112683279b143be5665bca43746244c27352d3600dc62c2c1c7776924339c02150e4e89b25563985c7802c0c43d00c721d521b54e767c1f509f584bf2b0000000000000000000000000000000003f7c65aeca3fe6e67c91e1f284be35149276a9d9c0c1907010d8ce26d5c88f2a68b632530a31e41388cfc97529485f40000000000000000000000000000000012b9322902ed50ae50e3bb3e07eddec3245df27f193fa88a7685795990a5fecfa4be4b5bf8b0702897cfa369d614eb942196ec0e9d2f572856217521fcc5e2869f16d5ec5fe76f7d350698f55ff0c5650000000000000000000000000000000013995f89bc17b99384e389c9a768fa4bc37526606966a74a370c9f964cd9d3a7dff9d6be2319d2c8c9d5ac1b6f5140b20000000000000000000000000000000017b32d8800e21a4553a1a15ddbee029788f58023164e65b25086e0dbe2ee0c16e519dcc4753c322b50c24edc305cc26d8df5017c9c35604f061a7095d976d08bb3570ef8fb518cb606cd39a3060157ab0000000000000000000000000000000017601971d5328ca817108dc9899c9c3b88aeca2ac5c03f70662c9bf6bf3e06d25fa4b7150e0838c21c9b089c7102a17700000000000000000000000000000000198db85ed42c61e1137fa50c8b2a3ad2eca4e9dfde3553b8ff7ee3aa6389d73c80d500c883e52be5cb9fe8f828bba84f7b82e7e565f8a521d1a9d0ecafc029f76b70042e1ec36c20e3789b49c7e50ef0000000000000000000000000000000000c830262d029435b1b857e7e3cd118e8a6825e3e413f5a5f67b37da686f442577c0beca3e86c13ef6924472305ab54b10000000000000000000000000000000003d35dcd36ea7352d453041e821dea655422ae01a50731698af020234e3ddd38140c24ba2af296a964f4f5896bc0af8c8260c1b7a249ba215f0dc127a41876f858b20f4422140bb7695c8f98e4c474d00000000000000000000000000000000009830bb211c58fdb25fb97a4ba226ab03516911e7b7d98f25b94c827774592b5d5c56edfe3c3040454def1429f81c4fb0000000000000000000000000000000003f34873ad16852f435cec18f977db00f786b7860c580ae0dcff8f03a8a1edbb417f01e0dbeaf035b6f60b733f38a564cd68d2b074d038ee0d9887168dc16805ed55df26329a4c0e062c2124a6e50667000000000000000000000000000000001718cef19fe02a179385ba031f23d28e20e7f57ee82db31e632cc3530d17291e54e8a01564963835c724056c53f9853b0000000000000000000000000000000016c44ed6c85628341789e80e1d95a10399b6ac126319bba3c66bdfe6a40f2b06b721a0867c30be1356656cd36e6370aa2a40c2e796148ed1c539b0584b90cb386844fdcde5d3766cbfb1d1b58626fcd10000000000000000000000000000000011267a6e9adc4b547ea0f42ff6cc9b35a40c3cdfd7ea3c4169fe1efdf533341969cc591f26fe9a48a44e544c515339310000000000000000000000000000000013d878f761efaacf28677577c93d825336698772044266d469b934332412bde9ad5deeee4c1f534a9fd89e799584d3394a1e176fb26983e549aefff9aeb220f50e071222073422dc2c44abd85528ee280000000000000000000000000000000004ca71357762ac2e9bc1f53919ee2c19d071fbd3918f5948f32ecc78be1e65672d12afb4d4a8df41a038bd5448bb0a04000000000000000000000000000000000b80b54ce782afbdad1cfbd57a852f629c0452346d5b898062a8abf12c73bf79296564d3fdb867ddd81156697a00f03ba62e07bb97ca3805ba2d30f39f44e70a7b2917889c26b84bac8f9739bdf764090000000000000000000000000000000009cc641fda19b0e33065a35e74a7ac28ca1bd3bb8a7fd350244ad0cd5dc89d91e7b2865e78ba24e112589e298e6c5cb40000000000000000000000000000000009c3ce4324dacb1e2ca82f4ce6a7ed1292f204f4f7b2c5e0086843546c5c00d16be4e7bd9c979ecd3af590b40b0d70a4a14278fe7a08174660c08323de272b2110047a1d1d8bd0e3c7d76dde030e00a60000000000000000000000000000000016ed972bad2d24d80332c4aeb1dc012ae4fc30a11597df1ca73114945c20e337d1c424e636d403141c737103a4dc02470000000000000000000000000000000009ab2d22c0161247a3c4eee341027a97009ea95bfd45fd186e15feaaabcfc09fd39dfeddb2d3631b943958620555fed81f516ab5b36a59e6300a54d17363ffebba35fa0c64cadb21e541af5078545b40000000000000000000000000000000001721e0fe2ebc0be63df10f4b9db3faa5c5fc3ada0bfea176c4fcd1cbb696779c03602cbcc1da3917dfc09af72fa3cee200000000000000000000000000000000192e3e3b5b9b087aba72b852319c200451a4976a4e7cd817eec04c007c8a2f800fe0bf7834d22a21c1989ad8c6ef73973bcdb23f9568e409271b5f907fd64b0cd81939a52a6db38fd8d95de76213f7b5000000000000000000000000000000000159c5a01e76ee666e8e22aafc77e27705a633bd3d1dbaca92117e4b80f917a3bfe80b36d3fc7721ed2fb8434558c780000000000000000000000000000000000c8c356e19c759e1eaacab45b4fd2e0b42dadf6aa2ee8c051b8ef4de0c4e583fadfd86ff6bbfca1eed42a29afa470c8c1b716b02b3e94600867e019be166f4532d264e0aa65d723dc0e117aded59245d", - "Expected": "0000000000000000000000000000000010f2b9ae629ef12f213e6408c94601482c4c3cd0ee33e3418c86f0b8092d1a1ab7d2600140f6e1231297c3bee4a48a9400000000000000000000000000000000018446e6fc72ffb3c6c25d6aee2d9a8bfafec7b4f63dd3f98fde09c088876c7f4d30cc0ee31985526712228766ad91d9", - "Name": "matter_g1_multiexp_31", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000de77471af6d857548f26f2ccea9c33f50db361c59b097fa481887b5a5deb4fcbaa25ec1008b131fedd3711d4d3ba029000000000000000000000000000000001037ee7b2005032974767d672e14be86177621db0ad5d7df5faa966b0e7db6319ead334358142feb370f60cec698f3d1bcfdf0495e49dbb8a8f9a0dc517351f39a6d823dcd42715f329dc78400bd74fc0000000000000000000000000000000000ae57db1c0d1575c49f8b049667e1c8ba0ca863fa56ee58a34ac1ae780c92418ec50294b666a0f99e0efcb2686a4d27000000000000000000000000000000000aa08900fcc4f9b551229b7a8a59aa9b337100c68703ef60597f6acaaa7c1ce910e643549dd0c328a7fa17e44b68de1cf095238bcee61ec1317c0f98ad4f8f9b39c5940cf37a8a3a676787d9dda994380000000000000000000000000000000016cf186f3a0ee77c7e990ec0784d99510320114793fd7a672d5f739e9b0f1186faaa9d5914860d66173696c603173b3000000000000000000000000000000000124f5c20e988b460c261d274251841cadf5c99a12c9ae8b4b3baa7fea8b592192dac3506860b15289df704cdba1dfdbfe45a6d64cac817cd479a501c77b6720c6777c6026dbee471b490fee9f242a67000000000000000000000000000000000166434c1551befa708de9201c02cfe18020d18ed881ac4d154f5e560995f302b57b1694740f76232307ec0ff729b2709000000000000000000000000000000000a961fa3c19068590b4c252c0429414ef393ee071b02a4ef15f6a5c722a73d145c8e058ebe1997058b38ce7961860da954868215022673de608cb43a3cb74ef2073ffff34c54fbb43f19b22a02bcc2ad000000000000000000000000000000001618c78e4962162f253729c4cbe326e7ea7dfd6d5cdac1b17353135485d434fe7c4d857df673793e9d12ee65dcad4bb50000000000000000000000000000000016921790d30423d878255c44966b316f9c29dde6695d66a97139fbc6fba9c4df9e291c308effc424e5e2134680846fc37068c3ba82e52fce0223a9f28c1d42681c7863c94797d1786c1adbc3e6d10dbb00000000000000000000000000000000128a8a8584726a4aa2cab71853f843f49efa79071a8ed0a6ed2c7913fbb85e254184d457163fe647d0ad719d04e6857100000000000000000000000000000000158d36271e87ac2879fdd3f1fe8ff306126adb340ed93406951e372a7f7f3deb1c347ccf598f2e007d92f502038bd4960042b8005283c7b91ef4b3ff7e20a91349c8c3d1301c9b54b901e8348a7d186e00000000000000000000000000000000047e63ded02c49b7126a1023f1ed4a0af20c2d5e95718f474e4171c0fa888d7fb53b6a2bfcd47893aef6657f31071167000000000000000000000000000000001404e16f51ea45098d5bfa00ece3df841a3a6630bff2b02a8063ff9af5c3f149e504f04e1fc9d9bf35324569e8b2e1730a3eb64ce8fe140d94956b0685f91a5462dba1a90093e803dc617559a66d20da000000000000000000000000000000001866eb045ddc4e29fa612a31a34355ecaaa8482cd0885bbfbc5cc0b3870a86a2b4c3f15da23638dc03619cae6b721f1800000000000000000000000000000000086aeb6a413db889a86bb3fe036486b4e26dd614aabf575f8d63614a300df8a528c9f6d47d59daad59d840f591063b22ec88ed0eac8d0f2f618530e91cdb9ea36b8d56c1001a6792a09e11ff65fc02aa0000000000000000000000000000000001765c386f85f7282251b6054f03a3941d44f9a8ea2814a49f75519f9fc985133937e2c9e06b59441a6d9a95c806d6b10000000000000000000000000000000011db74b6bd144f9a0d48185a3e9f4adbc79131764b6e82f11823f1bec92245a55d82e6d949f3378ea6605ec84f0613285f03e53ff983fe4886a3dfc03a353fb77927d7a0d1998a1c55ca7421a4bdac6f000000000000000000000000000000000bc9a01aee9eb527491f7334959b0f4275492afa38044f0e6dd222a3704f440b5ae2120e8e2798179634c65f3d674413000000000000000000000000000000000ff19f94b6802a4788c4fd84f66b9be03fb1417544d56d0e473caae0f9b9124c622e6298624fa1d53886fb5ba8b470fdcc1b04dc356bd348211ccc4c50d12cb382660a4f9526539c2a0c52b021ed2165000000000000000000000000000000000df5ceaa6ca501d1869b51f035c19c0f3f9db39c739f882a380930cbde7737790b25a2c01e65ed477755c2beb16e97f300000000000000000000000000000000148458f4ff4fcf8559b9f8a2ee4e486febff21d91fe4bc3c77988007cf700186894f1c1fa18ee3c4595a462712750d3097b584ee05c27d45390aba36772ed49d571837567e95f1fd3ba3fc1ba591672700000000000000000000000000000000029b16c9578701febf6662da833091deee23e647a15f16895fc057a37c153fa738efb1742c4bfcf27eda953a07aa01c3000000000000000000000000000000000196d74cfb1e6472b7ab67a664a7c46ad0377c2b465e12d94b035b4b79c7e358475339e09690557e4b280cc84391eb84752542cd551cafc5d50852526ba0a23d274317e1e4a6e75c0d19319e5853b8b6000000000000000000000000000000000e005ebdde060ed0233d1b1d6344b8d21f8cc1ceb6d4fcca389303e1c44c5964a4521dac8ce225e2e4909c4b2a47f622000000000000000000000000000000000fb3185aca9683a81d41a17b3a6048e75549d589354d4652756a4663cb25b9fbca1bcb9158e2ed73765d03be4e2b570f2f76a0fa585828f79553fbf3baac6a2776b782de66dedd6b734f9342e734ee300000000000000000000000000000000004df18eeff223e3a255e6652c3d14a6dad17c76e0597b43a6679a85f78d4bbaac1e2fc0ccf6a89149dc18045169345860000000000000000000000000000000019d60ee8b23308fdcfbb26ed30fda1dda5c6841b46fcd902e6c34dd268fdb1426e215d21bf650a340b284d5c7516efd3f638e6a70917c89811851109296a7225f9c7c5b3d7fe6d6ba6c7d1ee77db44580000000000000000000000000000000006b084e91066f299e44a0c37cf65c30009006ddda34d4151b0c18a5545d67f2bc76df0bf9a78fd2b771795c8d041655d000000000000000000000000000000000262ba1d9dbb009f779e2a584ed313d78e4ac69a811e071c10e21027138234a32deceab16a33767fdc4a78062cd23ec71c4ac944341dc68fee586d221db2a8167e833f18f012afa7c3844def6dfb26bc0000000000000000000000000000000009aafc73979c000236c08e089828880f54645b5ff4c1dcfea0ff41ffe8e3fce8ba0dbcebf0d4205bb6616a737b6d3542000000000000000000000000000000001399a2072604d50f92ee186924ce32c4e887803dc258b7495aa2f3d2187571045db7f360d2614b198f83bc8024b06559b0eedaee9347b10ab7b346fbc16c10cc9db486f561f88b756c269ebbba23a7f4", - "Expected": "000000000000000000000000000000000365ffdbc48aabd8f0e786634b9a853cb8312bf295543bd280c1a0a9f7d0f8ba95b3aebe31987ffab1f69a504edeac2400000000000000000000000000000000150af5ab7e9b1bc60cda3ceeada36abf9bb43f1182659d8d72281c1f1cdba73fe7d6e52abaa7506b89ef43f092f25bba", - "Name": "matter_g1_multiexp_32", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000012a651f467e9a1c1cc99c82e16cab2cef53b77268d968dcc73c5008e103d2e4d19aef4cdffa24b9474fcb393a48d6a70000000000000000000000000000000005d202cf9bc8c0124c0f817465eee7d4b1219071cfde50ce2cf8951efcc21fa19c762a1a8630eb7b8dd90cd03b8bbb0484adc8cfd2e42abc2f0e0d7e9c4b378f73731905760bfeeef01c94f8d5c3cacd00000000000000000000000000000000060650b71c97950ce5cd6b6bfdad46d66df454c5aae1ea313a70e7fc841e06f64a31edaaced17d8de56f1ee75f5263540000000000000000000000000000000018a211f44acc52e92ab5eb1ce304d80532fd4dacce60370dc62d9ffdebbf749689620798429b5ad1d8293c1967a43c12bbd5d4a15998d733326ce23cced86ec5d5b410c29ee98a4de19f2662c3933dd10000000000000000000000000000000000f51ac340d512becf5d7a515111f63123e9bc940242ba42be9f464b89847a8cca9d93360851e3d047de4ee667a6baf0000000000000000000000000000000000dd7e71b516b3752c5be5ee5f3908c17e3e019b46422f24659596a42e569ba9e8711b1e8f8329cfbb990942f258cce103717aadf16301a9c8741d65c86ad7f849101e30b7b1a344643b100a8582a6ad10000000000000000000000000000000015d542246cc0b46bbf5571c3173abfcf10ba447e5ec962b5f712ea7de3974c2873df1979c9d6432bc88d02588a3730f00000000000000000000000000000000005e1611597c12a4c7aaa25bd9ab1b6d30c58bd1fce3d87d66a03f25d6ed110c84c3e902ff5475795b5159126debf6cb522788b3597da7b9b106203dd0ea97527aa8f5149754bbb0c10bb6eca8a46d9400000000000000000000000000000000018f565b38ce775e6b40581f757935efca255311b872fea3bfafa0662620ad5a02a7e8ce48c17daf45668c95ab0487c4e0000000000000000000000000000000010686971b402783c1e7d60126cf484fd01b871944179adc4b28de5d72e5b8823b48d382a8b69f6b4681c74961ca2a3843c21276fc1371060c226424eb9886de6897b15b075fc5a51aab4710e9dddd3840000000000000000000000000000000008d42e31cb4c514e450f56488208444481db0beb5807c6f1c2d82ee09c9413cd6726dccd72e0b8ab6f6ce6492921b14f0000000000000000000000000000000012143ca6dcc3bc9edb5b10c3a47a5130e393986dc5e83d1eb61d9b193ca28193101eadf00916a3cdcf7b6c1369b17038ccbce4e92cf377f67244995badc72db0b80fe37c9b7d443595156fa41abea17a00000000000000000000000000000000101eb8b48df43c3e01c1508aa9d3dbfe168e7458cef2ff61c15d5b4e8dd11be6b9a76966c01682fb07368f22362f355a0000000000000000000000000000000000babbb820a5a8e0bbbae1e2455d54b97f6771ff914fe33a007734d5072a993df31c6a2726c8b03a8c2dcf48a73959a8ff79345f31c107841ae388f6cf116d10bc696aec4933de56bb9affe7e20c649f0000000000000000000000000000000002fe8c461de25f5e6c5a082fbc4ecab5a37dbba9255ebaa0b5d245735edd27550968c2558ed24f7bee99092228e37c8a0000000000000000000000000000000012513b2fb62725aaf948403c13f11a6d7461c70cce3e4f912c8d2cc9f2a8676d9bb37face3770e7c0121bad6af6302d121cf773387d5351aeab99971eaa3b207fa6a318ad60f1c3e16b7f68251f9c91000000000000000000000000000000000175c93838001f4c67a3e0e5dd7eded26a8818b2e492eab2e0e6f8b421e3d3611561c8b933010a3c5ff96128631f4e88700000000000000000000000000000000136292092a366a73a5609cb1e7fa403c59825e99c8c91a37b289ed779c4a3db71370a4bda2cf8509cc9d4b4731b4f52d2d69cfed6bb2d33fedcbd215dd4e9632a3cf86a4b2716406305f6a85e6090a05000000000000000000000000000000000d03e1d6dc4bf59262fe3bc3e163565110b751c534e57c621b4be59bac28d6e8bb379cd4afa3740797dadf32194fde310000000000000000000000000000000014ee46a0cf13e795c8a46399ae63e1b812f237eea725539265e13d3ad1a663374dd566df450fc1191512ba978736e5b779cabae288f8a9a8cd54523c20825b8fb07886bbf0ba0c5c807956f268af4fa10000000000000000000000000000000003cefffd8fa01842c36dd9fe1c57efef3278eebe5d1020582c3d13ced75d24177127da37eb59e9b46b4a0a19421a5aef0000000000000000000000000000000016c258ffb2edb299fcc04ad309ee5d8a8f186db5f3af8011d42b22b23687c2e814e2a8d366f3cc61d7c89bd9619523b31973977d8e8c592f9063c5a14a658990f9c3405643089eb58324cd3f05b5b5e400000000000000000000000000000000097b6535843436f879ce659b6ac9563d81ac0262b9a861bbb367bf8244a35a5de51f3060d05cb2174cb41c8c3dbd8dfb0000000000000000000000000000000012dc9607e0ebf73e3577ba1ab39437b03215e366cf1ecffeae4ad4c7919a63f62e45103db65de4c9e3281d7604b07f24a610bfd375a7b8d0b034c17c8fa27d4366b06c681131fa7daaeeeb08e25c2ca60000000000000000000000000000000004479ec5d5ba2f1c661df8e4f85320d0e754372e0c463098b0ad7477f7373f309c674dfd31c7f08cccbbf4bbd17c23d7000000000000000000000000000000000470cabd9f5c4bb8b1a370888d8f0f486387a89efb92912072fb0907a1e64f3327e9beaddeaff44c502414632243d6fb99ffe1dc2d7526338462860501d75380a5ed9d53e675125342afb6652a97437b00000000000000000000000000000000038101da3c35dff20a878300bcf69e393b77873a971838581daa9d096b00bd6fec3dceca882a02d397a90c816fb415a4000000000000000000000000000000001184246344c03be6103acd745b3ed37d8f67ebf0caecb00cb2528e0da9aa3f352a4677dd6b832c042d6e1235da7521fbfdd97465982b58e69993711a6a64134bc4e76b88ba1948af91ba3339e9b9d3e90000000000000000000000000000000000cf99121ecf9b02cbd006348b16f9d80f64ae3c946c4802ec6bc056bf6e95e01b80cf3fd10ab1d30260a402b7c46f880000000000000000000000000000000015f35fe1ec8c258095394ab2b021d63ce54ed4bfe14cc5666f5ea4d5a0461d535b8bce3263913c1b4e6db6996cdc037d786a2a3974c84752b32f29707805c71992d5d473f4b7bc1f0757d126607a1c07000000000000000000000000000000000e83f4b1d3eb8d45ec0fd9a4ef001e5bfdcfb9c99a6d1dd4b4e8043b4d11f5c6fd65296a33c7fd26a4e30dbbe1869090000000000000000000000000000000001197b11d6747280b37769946549ad9d4a1ff1006ac726d7cd322cdb4e3cf86906c7ed371e770fd95ab4fbaa1b7b514d985d33a7fbe6ac6eb42eb932dfbbca2f771ffad5e80fde686e5df9d34e9f83ad6", - "Expected": "0000000000000000000000000000000012f496f031f5c1b594256e272520ab98f3733fc9c481e7ec8de8ba70f493065eb25b681a3959994d37aec979c22c6c3b00000000000000000000000000000000015dbaf471eeef9307d8dccceaee179d8c9072b052af66fbf049ad1d346e08bb555238a763e903541fc72d9edc30ec30", - "Name": "matter_g1_multiexp_33", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b632afb8deb955e64fb4ff5aac396152e23b11a3f326df0d77b3ec078934cfd5e486244aebb44cbd1599f594991a26d000000000000000000000000000000000519f9de5a5b1623e4524be68b5ba0f997addb4da78adcc9c3d5910009a261fdf8b0efbb6e2a085e74112ac4e2106ef319582dfd9cb80d44c17c5f62360e62f6736d186194f0f8483e34d8d18d832d370000000000000000000000000000000005456d9312825dcfe5501b2c38aa610a767bd38f46cdc8acd92f0c8206a9c2f9b8f65c8baedffdec5e69f03fd3adc4c40000000000000000000000000000000009b2dab21ba4e4b4c284a623994b92ed5fff0fc198bd154fcfac9abe5f05b830066b44894ac6f92bb2f61bc88a7867a8ac0bd9b8746fd02aa70d8b8a2b5d3be46baecf9449d8cd3d620cf9efb3c615d10000000000000000000000000000000009f55a987011dcfc796df284c7bd758c3024d4f09edb3884dc087de26fc1df0f71067d44fde07fab9334971b4a0bace000000000000000000000000000000000003a4ee3e9ac2632cc81cbd4ba397d44f738ee390a4af6ecd65079f412bdd8c4a37d5413d0d9a7dbeda8a1267d6d843b069d889881d5bb87dd65a9a02a7fe239bdb55ee54a6310bc987e7c5772404d7d00000000000000000000000000000000173c7db310b54a4a720074dee01dc0e5f84b606c9c3ea0962bd4610b569f478d7a5221feaa944054cf7395e578d730d8000000000000000000000000000000001697f0e16c49b223dec9e0fa429e68dbaf96b004a561aa3e37158064ceb9232c1cd21156c053fb89ddb230deaa7f8336be658348e299bbf2438a0c013f86eeeb69a013b8004a4996189472f3372b326c000000000000000000000000000000000ab7f085b711171f999d0c4a46cc7c8cd8a429f6bd90d1b860c01066bd0d193f1c1441ae5aa97d690569807749ed69e1000000000000000000000000000000000824841eab90d56a1810c129b8f27d0068fbb7e3536d6e56cdfdd9eb553e283c5d0ab1c418869e886fafce53697520859b9d0ec92ae7df3f52a95747659f8fa3ca2cd01e8d7ef6de384111246886bafb000000000000000000000000000000000bbc8c5b5e4373e76457fa45acfd3f1151735457b0fae06e1d3e6e5dfeb35815aed44bbe6395039481ce02d2aa2c502900000000000000000000000000000000089ac22ebc582bb71a60c88638747e2243096e8d193fa1863089698fbf6805128f9e32636d6f954ff03bfb6c5bcb0060d2ffdf1237b4e03c219806f2dea745c94bf08924e1b9f11deeedf0db19da6f3f00000000000000000000000000000000001fea43c3029447965718c8e76100875acc8fb4da66f7a4f7fc5260de3844aa9e9a89ae4d9baa11c118b9f851fd63de000000000000000000000000000000000844aecf4a3ebfd8b711dfa9efaf1a57d635f46fb980903e362d4ad55d48c4289a3fb1f439e6b7d8f88cc51867d6b462cca0751c9534cee7f14d11b7c8ccbb2c537a799df59f850bb125c6362d72e9c4000000000000000000000000000000001384e33086ebe795cde3c951de9b48f3f0fa2f627524cf0c4e3691599b62d4611c6a84897298c287d162825c3f153a75000000000000000000000000000000000a04af7cc41c2d3663444c8aaabeaf70dd146dec114458b3d1dbc95cee99ba89a4c5a38f2974622292e3236fe2aede6d17f890a1120daca4a1bc1bc0fa7529f0a87b5fd6ec385f12b270bc0f1a5281b400000000000000000000000000000000158820954aaf8e6387cc0e8e528723e0875f5f719a46ae5cd9d967674815a2d9679aea9b5736f882d37e2dd26b7db17f00000000000000000000000000000000058cb933f8dbac61a22477cdb3f52c9e3de6f060dd51aada35b6f8480a53e8eec8f82800e89ccaa2d2eb1dfb4352f16561ca18257d9d989ec13d4f158b18ec17d59344f4558b6dae6c0aa0c2f37affb50000000000000000000000000000000000a7c9c1bf574503a884ecde5e921da80b299c4efe674a2d5c841e6036adaf7c1156393116c2c0b9827978d43f1e3e440000000000000000000000000000000005cf22e56bf4a46504ecedb072fe5e18096f9da550065612a1d00cf79c65384dea1bf59cb7c52de905a04f1886f36c8a0fc004ed8a135ad97cdd1bc4d0c3ccd15e65031ad7e3cc13ef2c260958bc43be0000000000000000000000000000000018e344838e2efd9363911898f27882f67454dc3b1bbc71f1d99e787bbd6a1ec9744876156ed8db2ccd826f2b4fa784050000000000000000000000000000000005528854a8568ec6491c79aae1df15d965cde683c9ea400b470105117f2bf3b41d2f958a8dea5f866a55e60fd06c1f07d8cfaa1037e2c81c6973b221dc7badf25ebe3fb4b42bbdef1124265df2c7ccc400000000000000000000000000000000047dfb6a6125ff02e12c4a9d88ebcdf8a4375367e1473f5a0d99152bf0a4055138aa9a83d98d7f74d9fb8888f643cac00000000000000000000000000000000019d0bf5162ca55d8113a97cc3255d090c6924362e6e05083fc323dafc3b12e898cd600d2730acf8cf5cdfd4420962881c25ecc5d37659ebb0c9e21ea2f8fddc518e3d8faa99627b21faf105445f69d7d000000000000000000000000000000000e132de353cb09b69ab369c616718b9cf492cdb9d3002593319a6e7b61c7d90f94808b75d8c7e3b9d7a811d01baa47a1000000000000000000000000000000000d636abffa063379e2084cfc09da5ee04d40d8e74ba0247a01be414cce820024766195520f1d2eaa90fe254e12a4d86026cbb32382902d9b1963779070d749cbc4df1e7605f840819f2c04aaf89c732f0000000000000000000000000000000013f2367ff71430cb541557f79c5ae8a0d9053d82341d83037c1f73a52585255b205706227de4e87d6ea2ca602483d2170000000000000000000000000000000011f3f4e882de30b40bc160e69fc2bf4f7c588cc83bb9dce3467accec7c47714e2b326be001a36c42ba39c7f56b72d6fc699aa549077a80ff8732b5fc9df148a90f405bccc14bf7305266836566b7a98b0000000000000000000000000000000014bcf3f26683234584d79b436cc608462f1e2c20b5ecc5019988d8e30137859a4b6d0e1135dd5bbea0781b8ed3f0653700000000000000000000000000000000090ef29bf63ca97ae8388588227e1d1a0653c43b16a35a63f2ab4f0b11fd8005d9a85d30a7406491d983f347e4dfb9f140e2de1a2901f1380a383a741d79fbb0a041da5d7bfb92edab74cd483edf9523000000000000000000000000000000001817fac61301ea6a43d7968b22616b836ecd1f20e5883e9b475c18353b066f93bd68a8274d0b6ea4480d8e314766dff7000000000000000000000000000000000c52fc676604061338bf0712fc1606dd09783a1f9a5250e3417056e3c39e59a28c7707d5225808414279ab61e49b6081062b323592118868d547e83b731d15ba2c7bdb1ee4fdf73600c2584f1db0b45d", - "Expected": "0000000000000000000000000000000018410462829b3a72024468ddcbc42d59a99a70296024654f99b591ce016304537c525513defb655417ba3c0f5e614aa8000000000000000000000000000000001416a19f73407c262f5e464021eeae1d1f10c3ae5e45f132a2f402a75cfbe409651d3795e482b15d29037e2f7105255b", - "Name": "matter_g1_multiexp_34", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018e6f25220e4b4011a0291424b4062930f5df45eaf1581d9591560fd77e630411e0abd57f9973d4542741de5cf3132e7000000000000000000000000000000000b31f903e7fc36327e404973b90efe5a5d2249770170ea1e58839e19d8aee99743be012b6e8a3fa73efc6bdc08be372f764ab6f4c43630d5e79e8c474d76d8973a7b7bd1c7f1a985333cf1a6be5ccff20000000000000000000000000000000005dc07fa620d476d8f64358c920a401f8b08abf739befe1c266fb307b959f37542140e398c33b082d09f9f53cedf6f810000000000000000000000000000000019d8e51a28c936b5037424a7ffa8cae75496131eeb2b2d5034e4e882c1c91f6bbabc9ce4fb2fe4be3da4eba46326a3603280f1b1e78d2339f64b5b2f2bd77aa24623b79fe2c9debab4212f4ff564983b0000000000000000000000000000000006f5f80dcfe8be87d057e2162788f7599e55b69ee8c6bb6a47c505aa324ddb5ffddacfcff35cef3dee6264ef73d6a353000000000000000000000000000000001056081108195d4d27af7332215c0b444c9f63c7574eefa81046e1d064825492e2dfc5bf2ab5847a37e6b253d9dda9fdd4d27ff9d03ab9120ac2adfeb36b070015f0e90782255ddc9111704c5fb111770000000000000000000000000000000008db431907692896f9e6e254a6eac1a0ba5f9cb84563da69c3601aff1370b7a5a98edf5a5fbab06abfb4496c777bd83f0000000000000000000000000000000018a3bc407fc42236c4429f241fa760c6513614653e8b02835480dbe1152763bc6a1a7fe076e8bb44ddc04322cc906e1ac66d5291311c7cdd1f33e5365ec0689608b3569427a8f6a9cd0b94b671472e66000000000000000000000000000000000cf32da94af97001664607c7840631a8df02a008fe262c6dc649a3eff34a42dcb98884212bf3e979629c98cbe5fc457f0000000000000000000000000000000019b3b4d82326ec1aaa3de3b2f8e329ac0243d3f6bf9356886be4033aadd0398a5c58c68510de29f92a7ca910d851da244b718a5129659250640e333f4567043ca749063e63d87efd86a9995adfd3b845000000000000000000000000000000001504d90c52af16b5f88357c87d4be7c329855ccad6f6633af0fcf4341fae54aa4b1ddc1aa22fe1ac12e9d850a05a9ffa0000000000000000000000000000000012ea642b96304316451dcece5a6bb324d197e31f56ef3f1a17c973742322d08f443b7cd156787f8291b52c0a6f78b4b1708891f45d7bee38fe382820260061e212c6cb9a8572b4d1854f3ab09409b05a000000000000000000000000000000000fc61e9589a2dd7f6dfd613225d80a70ceb977bdb518b5a16e415f887eb73fe9fa5c9130d5fc6deb4ad153c5de0907d6000000000000000000000000000000000a0fd7de87139581e9b1ab707e25c186640db92875a7822d61d8c476c40ea07bff000cbfe6975076434d0b703695740685ac0f94f300b004c7f20aafcfd9129d6c2590749504a3f08c4cc708fa30100300000000000000000000000000000000188901f19a776ebd2ddad60209f4545ca9b0a038b0b3c67b6f5e35d61f8cc2a297d51450663c4af182079d3ab6b01d2000000000000000000000000000000000151b9eaaa281acd803abd71ee4098b4ff6535e5081a33cc68ecca54eb9f1a8f94f3b1b21440f33b8648ec456dc1cf7f3fdbb634bc0f99c5795f3c4d6a0efcda7f71427f1eaa1c5411caa6cb05ee314780000000000000000000000000000000008ce8bd24052a8e1472bb64cc215974e20bb16d502b3a8113cd6e3e9a2bb7c3fccd45ff711518e8430221f40859374ba000000000000000000000000000000000aac2e8db9123be3e82905a0fe780daf4a841f6f961428b9b431c3ba2ac31e8c06118402bfc7fd15fbe3ada0ec8bbb2af5e4695c01849259fb969183de385ef30c2403e081067c2d9b6b5522c73fcf2000000000000000000000000000000000017c580f501a1c4823483ae718371432a8a69e16e42dc0b15bb8e01729b6707ec20b898e3835bba40d7e8802d9438281000000000000000000000000000000000bcc167264fb9d6c27272c2280d8e89f9655ac7e6408694a3a4ca6fd0b46d1d7e3cf608bc2ac343806c5de42ae7a99e80ea6fd588db5efc5fb2248634cca683d39d610886b59eb3077fa9612c368d7690000000000000000000000000000000017ae89082d6f531bb7905068a9c00017ba8ac8867c6e467fcd3e88e9229ba5b21ff4d0a5ce937b75b3d5dfbbe35f2e7000000000000000000000000000000000005bda8d641b782ed51c416d0ebb1cc7c8f623d49b741a7cb93b3514e71d5b9102ba2e6c768661686c2af2acedf466e4dc2060a3421c5a8336c80983c9a160345901a496c3a74fc5248fca081d099539000000000000000000000000000000000150ed2c2b2d1b0b87badd0dda44325000a6fe98d335e03f0d4d147b20d4738e1e0f0ae0ddb2783bef283684e631ff45000000000000000000000000000000000ec1fa174f3f42cdb0fb67a520da161d9a9d1e53a5b0735738580fa3e80550c95cc3a1cf67fed67dc2eee1597e469fe0e27e4afc3e6d59d0f5871b35eb83b46cf15da6c326e88dd8edf84031f58e23f900000000000000000000000000000000111f184636052719c6df1541c100d5a21d573370fa7afd18f5ddd1d86842169eeb02c494b33f2bb2f54278530729bfbe0000000000000000000000000000000016be03c9764aa34c898dcaacabd1493610f55efd36ca0b35eb48e89c7968e7a720d545b18fdb95954e01596856d42975cc7efff04f143e2d038de153861da5e04016a7eb17fbe6365de13069d088b1a100000000000000000000000000000000114fa84ccbe9552a2ce2368f1778a1fd3c67303d8036fe4ba171ba9f2f6039aec1a59fea1b8efae88c01bb50e53950440000000000000000000000000000000017a51bf70c41571f36d003c0715238b6c8fd64185f616cd9076b730ad16caf364a75fe68de246249a42cfe013606874709a2c3dbb4ee4f485dc60dfbd94a358a7c62204c021f2d7b140187ee9ffdc4ce000000000000000000000000000000001450fe1500a6fa9d966a0c905167a414d59a3f8a064089f09db047241e9abc31d9e41ef73558eed741541414731f838a0000000000000000000000000000000017e61d4092537ec48683f86b72123637df25a5fd926e5703f993678a798dbe635ea29303f8b4d9ac76231a71cf515a70d9b15c065497392e4b477a556ad620d44e671137cfd570d53590b7528f8ff680000000000000000000000000000000000e72f0c855fce66335533c05ae30031cbde78ef07571eb1b645fa3ac5f3a7d76a4d60cf078145617c5a7ccb16266bbee0000000000000000000000000000000005b3981900432b193985f28a88a72ca9958b4628e5ff9d2cf8b0b23184e2bd433d495636de3d56711f207719fdd3fd2f9e2a72eff2ec29a65b417767e7090b73c2fb530de6c8f4e4ba30543946423b12", - "Expected": "00000000000000000000000000000000110feb31a1c40d570d7281ed9f0c0ac8418f4a7aeb6be3221b130945becc15bb353ea63623ec7dba2844d3f527c167e6000000000000000000000000000000000d76c7aed58945a7fe52f37eec3be7cbd4438645a649a04859a487e9e2d4c82bfc76f7ba990f825302861d82a748c8f2", - "Name": "matter_g1_multiexp_35", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000030c6580a3dc73be106748d070b24d9231c382df143fb4bb8ad45e4723b40f90724b7e54510da1b2bee523a29aeb58100000000000000000000000000000000010cb3562fa1b0a3778393412994e46028367ed52dd62a1d446fa02b50acd48a784ab49141778bee5036b7d3a95c9ec217b9aa7e0bfaf135ff24720773ccd1e0a46fab6d678d91a14de137061e145fb9d000000000000000000000000000000001972db503f6d70a0b247eeac7fef277098604e54465309967b68d24ec1cece802d8c4b699eabb72e03736902d41fd5b60000000000000000000000000000000007f30233f9043927a629b11e7da48f895fce86b31911ff5c511c7b50642c296d37a3078e2e12f1adfe668731d0e6810ec6733c9bb7bd195622b96c4181e8c8837d1912fbadf77d6029f7fc44d793b4800000000000000000000000000000000011ab9fd98e42539382c85bf76b563478fae8cca90ba1beb0be56b405da8326e6f1348b94eba61fa29c78645f8eb96f8b000000000000000000000000000000000f30617240632d129ceb69de1d69a23c9bdf950819608deac0600d1d1fd730a3a6d22dcfd635b25154b5ac7e22b20c70410bb66334c677397d04f59eade9630463065cd7da3c9d50580c7d66bbaf487d0000000000000000000000000000000007556b86cbfa9f186f38fb1a8adce4c08f93f874bcb36ba61df5750c7927cec8896bf831c0150c249067ddada2e914bf0000000000000000000000000000000016ecf045f13c78de8aa18c2ddd1714bfc532ba8ff5b7851b58240cfede20f032067e943486df628995b8f3845289eb02d97a16fc5b2c70829b15f73615286eba334de1f520b5f0f6a83d2578399cc0b30000000000000000000000000000000011379452e627dbed2ef1c74eb917b95b3933b8fad8295235cdbd6a4394d9b75cd3598c930d48c2d4abbf1558c65e97490000000000000000000000000000000005e7044829ae3f9b073e4a2237de96b0a1bbec3a30dc39c839573eff77321b1e0a49d555f0e31b8aa096f83f5945026bbdbac08202bbe5df1229e99c76c1727f7789e0f8c2002f0a2c195bdfc00acb360000000000000000000000000000000015f8f0f22c1553ca663ce7e9ac00514eb53443f6c4869f985dceb118ee60a88a4826e9dc7fdbf61e77cbc93768fbfde0000000000000000000000000000000001646ecc89754ac57d7d6fe9b871692d65057f23d397a410bcb07ef3df0a3c3fad9eca515f0d0dcf0610edbdaf4cdb5d743da827b812ec6ac23b00208cbad0f2e8b3a32434aa61dde029683c34c1ab1900000000000000000000000000000000003a18dcef4939e154aa790b0ce8265f27cfff48d5fec149d91307759eaddf601c788da6ed8124764bad940f117751b0e000000000000000000000000000000001813f4650490f3839fdc9f96ef744ea93a9fd86f8a43d767259c2e0abafe308fec2bc6b9d62c1dd7b5ab1aebc19586e93c7a8f7bf434ce5e63ac9365448da8663745f66689b4b04968f9b8b1b68058930000000000000000000000000000000006490f351e78a40c0cdb827aed3869db293c7d654b43d69ad1c9b3b536b1fbac67d50a835878171974669a30ae9ad1bd00000000000000000000000000000000041816bf846528e23eb129689a87c2325f1b8edf237c530eaf578a908fa0a2604baa19d6e0b4a5801280c27285896d5a51f2e2bcfa6ebf84d3ad83c57257b9032e5d62a8663ed5d77afce00f33382bc600000000000000000000000000000000064be79c5d382c6dab72bbf28defddf14cc7cdbb23eced6bd93abed078175668d4dd66d0b3abc6384165d26bd86680f9000000000000000000000000000000000fa4c8be5d20d16bee7bd5bacc0b0086875a14a119b4888bc408850c0a099603fe3f79d334e45bdc9130132ea15a180f6d8b15ec8908bfe008414757c0c7f79b3079f9db86d91ac3ec8f38ae2c94d48b000000000000000000000000000000000182f23242108b022ecc1d156a97f1a5fea2cc2e059dcc82273212f37c312ab77886c1adc370bdcc6ee05cfec957db970000000000000000000000000000000014ceefb3ca54bfde172e0455d34f1f462208df69328782b7961ade821ab91e7b3ed5426b4065fad10cc8fc88c90d8e87f4723e85076d48389c3fb5a5df16b6bc6f7a69ca701632b1159677bd8a6f7bb10000000000000000000000000000000009339b95b043903f2a3b5926a27e57cd0c45e7955946718e7dfebb01f18e9d7a2002c670769c4674773a835311f2e58e000000000000000000000000000000000ba94f6b625c507934f633d5420654056a939c68899c41e3f337f7b927fe82191d39905b349870ba0c41c8bfc97d64a9a632938a6df169fb64daa55d2f874ef7629d5be41dfa0d50827c082333f0fca00000000000000000000000000000000007604b5eb3218140b94732a601da577da3cfebe04dc7dcd94396c1a6704a0ef5a5bbd0c31c196f2876e1a4bb7490629700000000000000000000000000000000193098ff839d38c9bbda43944d7b0a3ec9d0d6732519d4cfbec506d29801780813b2faab46658c4383b2f26c477580af283a4da7f71bde54d4b7e28b2b23e2eb05d8b025e77e15810625d71faca6d6e500000000000000000000000000000000022ca1a16df42ba543a118212a75eca13707ee01eb3ce27d3659b1fedd99b9fae859f4eaa51e9be9107704276b578a0c00000000000000000000000000000000012d60cf33701caf11be6c9e3ebbddb9c7066dec3821a2e0f9e5b94e029dfea4063bebd4b2fe18c2442311c2bddc7c08d402b71c1fc5c3f3a4ed9edc73457a27ea427f83a784796e01b7a1451b3305b00000000000000000000000000000000011d4918642919c801fff0962062a387a4dffe693ec09cd3d0286a18e3a22c84fc09e8396ca82e6054d8535cd888179230000000000000000000000000000000016a1f0c7fec5647dcce688d3e4e526749bbf23c1fcd9e9168ace47399f9198c9b3a6b8aeca68febde1b7beeea0641aa2310bc47acb3aba7eaa490ec104ed9b2985f65c7347f69fdc67b76f6f43846a990000000000000000000000000000000017203c37b21375a524bcc906843a0045229c5531ca23177dc88026e83723db21d9a8b5e52cc0be1d232818ed9abd496800000000000000000000000000000000097b4d7fdfa442dcdb64e405965439ebe70e4e71cc8e13e299fcc0b5dd88c67d6d0dfd254ab9b545e66295e2f3df14dd91b88ce9888e5dcfef70d6f960a456dbabc792571f2a98746b7d833e7fab9850000000000000000000000000000000000fc4198a87e789015a1e44935321677e84356aa9e06592f9cdbd149d13ac312980f3048dcb9bd02779a3b10fd24ec98b0000000000000000000000000000000011425345ae1139647f93fc13eea0e920c491a49998430a339cd9d4260479a427515109753e70811be4cfb3b96db5c78b3e82cc1261ac3864266379b4d518e25c05bc492a8946b38b8a64acf47aeec4b8", - "Expected": "0000000000000000000000000000000011cd4c4507778871fd7b28aaf79274178df83f3e53c256dbe7a52df884d28df6a0d87d20238a15f489546a459195ace0000000000000000000000000000000000439a672492225fc09e46bb178a5d38956ae237d9f7d187d4cee14597facf2c06d7e70be5ce20e1f1389e4da6321e455", - "Name": "matter_g1_multiexp_36", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003790fe37a3aa78cdeafa76bdbebfebb22ab5f1e09e4e488418568fa307a5db18f9d93126b0d3cdd6a28abe3a4648f6e00000000000000000000000000000000043244b9c78fa56c611bf72bd6a17148abe76fd0efbd25085d7b46c90318ed591c5975f79653b98440f5f7c04cae4d7ea2a1148f1ba719b2da92c418fd137efe21a44dd4cce013ab36e57d97dfed92990000000000000000000000000000000008e8fcaf6d2056c6e144295d437f7f1422f6af7a1b62e0b8073141b2992b6ba865822aa2d9fe439aa1d896b2a6d231c4000000000000000000000000000000000bc693fcd2021972914747e48c600c444bf69ca8e1386655bb5d987608d648965c754668ae0a72c2439ba0ed98e5e581fec5d6167d7777169348cf81ad3eab5153f8f2f18fb5935c5ee5e3a759f9b5af0000000000000000000000000000000004e877b9032e168650ec3502ba65118aa0a8013b995a647210c1c36a6e6c702a93caef674d03d82da1f7c5d7ddfa0d0200000000000000000000000000000000063dd22dcd667c8288ca5b172e34b4eb783403105523c0467139b814e048fa21245879a5e9188a1a87d26fba52a9f601da609e1c8fa42a993ff355a70d44dfeebc71a801daa36acd437daec5d7b645d10000000000000000000000000000000018cb2fffa3181bb665dedf1d60de6096e8c5ce43287cbd86c2df5a5d42d0129c73cd281c085fc562b7afdf52f0a680c80000000000000000000000000000000007f9884780460ea018351b4ccb5a120d44312056b96c5ba77cc38789627d20500d6b7e69dbf6ab49d6bee998a6aded67bc5f7f5d096247ababa51852724ce9ddcc6acc7ab6180beaa1cda97dba94b4ea000000000000000000000000000000000bccad9f23b4c1231eb07df139548b66714a064dbec4ac6ac43ce18671144f2bf7ed99f16442b9f6600e1122c58f52e50000000000000000000000000000000013646b3c310a4b3f279e17f45fc8104d2c9d00f698b869479a5a0e1c2131e3f3a9dce86115ccd539bbd4346261c5a75f3222b41a59f9551e91572ae00582e1e41989ff5f8e2cd1ee1a78f55c2b28ecb4000000000000000000000000000000000d02250115596126e858a63a7082a8c8f8ebe055653f5a60c855ddbbe3ed05792d08e5cc348094b8dfa4584037be597c000000000000000000000000000000000f68ec7da947cd0a57177fb91d12a820ef8574f4c524fe54b9420f9ba4944759c92d5919d6dc8030fc663c34519b64c37431e5c1fe5f8d38c759bc48e8207695a3cdf07d4c1fd02f1009088539085da1000000000000000000000000000000001960580ae965c37c2ec219dd0753749bd70ac2f0c4a3837418023c5142caf7b4dbf592554a6dd95872e018e912e3a20b000000000000000000000000000000001210b4093a07616543ac2034faa9c4a93b5f4cc3daffef2d8450b1a1770948de56c5bdbfdc9f1dc9af5e20778c1e8e6cd474e755f6ce9045baaed65c80f5a686547089e8cdf4ad2b7c2ce7c255cb5c73000000000000000000000000000000001955d93fc0f3ce0563ca4f4ffae0257297002001a3eb941cb9d3bf82b8d7f97657ad7168bd386636aaf45398745d5158000000000000000000000000000000000cc7a0babdf499322e060f2c83897fa7b6c3e7b4f56de3a18c823e0ffd87545a3dd68947df8cd8d3de5795ef7cb05391976c8775b0eaa1e4aa384d222efc476305c7ea2d625cf5c67ea4368d7a9fccd1000000000000000000000000000000000d451eb31b21eff2c18b52b882e1eac68a524e3db43f233a9d08139667cd0173e3c716f29085c599a09f19019fcf447f0000000000000000000000000000000015852c483c8545fbf0932c99b1944ac58b37228d15284c7be5f5259bb8002abd57b26c244846652a862d46016221eab19db274233c46caaa9c99690fd00fcbfa4eaaad7c41f8ae84313448c787165f6500000000000000000000000000000000044e70861dec38d2b5ac7fec042c6b931d4e0a072073333f03ec4382fe40919b29378cac920836b1641e5e2db053c5c2000000000000000000000000000000000c422a91c81a99caa32666511c0ae4decc67cd94e85260b49760ac9e97894b0eb434d39c3884aa4614360b79681403f94ac9f9ed46ae5aca33af9ba1c0fa5a2138d4ca02b962fd1d02b4636114ce1997000000000000000000000000000000000af002ec82c5ac0dc87e1ac27f4cd052eab67bda318557c70fcc2edbdc071ac4a3fcae90f73ee514cdf8a543ef59050d00000000000000000000000000000000109f720464ff2eb2978d66370041206abd9ef0c6ce79d51f7d233c49b72da520612e59c39f3a775e288ba2220fac1563ab300ee55e90ac046dbd772da788dacddf72c559d9378b39507987a9774301b0000000000000000000000000000000000f62e7d0aa954742a2018d42dd9cd76f041d9ac46ce659f4e192053a1d0c9b23fad78a06f61d2c90eb7b4d1bfe6d951a000000000000000000000000000000000ad5a5ce7b66928d8e6e3806a25425bbf2bc63f8ec87002a913c28ab702b83b6ba590b41a0691daa5b921a12375ef47b275b22db781d5e8fd07f36788bc1219c4b4a13554c28d92a381adae111b265730000000000000000000000000000000008b836a23836624b39e3b3388027093125749a5edd5df50ee0cadf1d485c9dac9c2569a82484269fe7af02334369a29b0000000000000000000000000000000015232caa0c064d8d1bb7fdcd23c0eba21685fc4671e9f04cd1dbaa0382aa4e9d87aea42a99cca22205367d7b2261defaec69b95dccdbf193d9ee4c51615c0b7be5ac6bed3f2559f0cb2755c634839ce7000000000000000000000000000000000875311ab0cde9a925383dc84e4ee8e1610b2f5af0e1f530aed4155cb8ef0b5050d907277f55d8dd542a89e4e0990bc30000000000000000000000000000000002c7a0d315bedb602f8ec558648ffa69831b9fdb6c14fdd44e636ff00777f2f8ae4aa23aca1b261460e6dfd87e7e501131e2bf1816a84c190eaa850ecfe1a9376123e0d0732d90ac3537668f8f18b9f7000000000000000000000000000000000f9531c4998aafabc26e1ab588a97a78c236a854c3fc92424320a37a236d5181d34f8e5533aaaab2a6ea3385acc85f6300000000000000000000000000000000130350be432fd7d68940fd5f54649820ff5b3d015448d48d1f4db3a05ab0405a73ccfc8eea1966abce35833b5d03bf79f4087feda4bd8205d96cd0bf6eee44c27a6669d7ae8e16c731849cfbb2324e1e0000000000000000000000000000000010fefde43b2cbdab52ba664e12c7a6ff29f647942e16ba5a0d41701754ec63bf199ac8e710ae8dc6a033abbcaed3e05c0000000000000000000000000000000002189172e607876a6e1664fddb990009dd5c7a8412d60f7dcb235ed1825c756598bc67f8d5d383c2570a880492d4ee1967b81583fcdc9afe5f35974dc9b6310ee8e1c92031a49c08b05555fc0d33517f", - "Expected": "000000000000000000000000000000000765877938c1a8170e2c2fda55241e3c64f7485bbca218f4a2026d00ef4708d014fe4194048da8e994cae1088694d1b4000000000000000000000000000000000b32833dc9a39e1e73578b21f75136be6c6aa2b4128b0e6ff4fe099f7b7a8ba8f2b769f68d32ab4d1f37793aca8ecfc9", - "Name": "matter_g1_multiexp_37", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab94114b3ecf9535261a0726a9bc0e0907385d56206b61b7a42f643d46296c4022bedae90d761d3c002dceaa9167fed0000000000000000000000000000000008e67942ab2b9aaf2f6f865b7e957a25dd7ab8d8a0cba02fb1648e4c7f15ce00f4f5d09199a583f38425bc62d32ddde69f3c65c2c25c6c37aa45b1104745cb8ec511a165ffdb7e304f5478aa3add4d7e000000000000000000000000000000000e53abd9ff27231fbb09155f794e5d126c490314016e31c0b12bd1d2af97a705bc267f92e20b64c91d9af1bbf5e45b92000000000000000000000000000000000ce7d0cc6656108aa7005a56d15a497009c90871f01eb38f1bdc82edcbe4945a2f2b67c9b812aee42cc9a9bf9ee84bc08fd50c46bade91a13d6dc5a06ee62e5e89e0ae7ee885e5516ca6c2dacc36f6f30000000000000000000000000000000018c2688f573d4849b6d19e711ef4d14659c2c580eb938434a3b2afb8c20c522423db4c7fffa42eee9ee907a6492b77ad0000000000000000000000000000000016a7e69d5539263fd6b7eb893d476a00efb8cf09f21a54e9ff0d1c11e9f3651eac8a5db31b40598af6c943f864ff60ba128db1a106328916ca5d63c0b5722642febed26f00a89430d52ec3eae25a019b0000000000000000000000000000000002380f3260c7289ab2005f7b1d7f572565ec938bd894bbb0047ced0b652fa2e74aef19c9fe6bc1fd469b2a4640245777000000000000000000000000000000000f32ca31e6bbb72a02f4b0da0e1627dab9cf1195fd7f48613c89b06c702e662478b24d8b3730321f803ae3a307fd498bd45665afb6a864893e389511a0f7b2df74c9e45a86fb69f6bd79854e3a88c2060000000000000000000000000000000001892b0d219ebabc3be00f45b00be55ae486eb79b1e41aa7dc8457aa0812e7276c21024c79646128fcb2b3c517aa41c3000000000000000000000000000000000793bed9530c814fa0d0ed1684614c1e6968dec931868a64372dc1b648b1f99ccce20fffec7d485a226033601b92a7f228f5fd09c2c1819adf8e6d0e0f4e4681babff46757edeff3839e9691888c132200000000000000000000000000000000173f49cbbe6304aa41513d3742b89c6b07a91be50264350d71bc03fb9efe4faac4a19e2591795ff4a7e67fef7a85ed430000000000000000000000000000000019bb5dcc59ddf055f099a1c3949bb50972c4cfd035d4d829dde4ae94ff9669983e9b1a7edccfc2436648dc942862676fe6e61390ef88f20591570ec1fe71c3ed769ee8e234c7cc7303a4cdc065717736000000000000000000000000000000000e3daf60e4929b4a237caeab203f86e6eed0ac630a8b955a03460a7e609398d076c660401f8d2bd9601e5bb5e315e1e400000000000000000000000000000000058b20160ca2232cb8b6cc63c5a8e11613afb9776e22d93f687e7ba005b099531f9693f65f153db01f20c8e9bdd7839ea83c5af2f9d10c06552ea7d1749cbfa7574b238433c1c0e4788efd0cafeffa57000000000000000000000000000000000c89f1ebd19fb920b6748b15192829d58820ee4995cab9035ad6bfd8dedadbc6352058806a7d45fecefce40133261f360000000000000000000000000000000019151260431a35d124fe44116d86ea99e3f3aa14e2eb09be8193dbaa8f26fb0ae2451ca1c70610233d3f0af9d2e33fca4bcc88d85a5a8a29dfad37ba97ab3a5defde4ec356146db8d10f33bfb36ddd3700000000000000000000000000000000162b48d56f439ff56197fad444dc460cc6432722b9b86c7abbbfa383ae1546e160716d94e442183196816084da90bf77000000000000000000000000000000001278d0796c26110f66930ea9248078c222a0590a031df30c62fe6beeefa70deb0c8287b0d204a911c147cb6344632bf329d5d818e62c9791c320e01a3164e142d9804e9caa7f96b4c3b76baff38ee2e6000000000000000000000000000000000f4fdfa45aa3b5d1838b4dc8a2dc6250c069806ec3c551ac961da5b44eb58d962d843a1c17ebf89bd653e9e44d16300200000000000000000000000000000000052ad9ce994c837596339dcfb73ee25bf8326657633fb5861039f197249d425e35c238dcebb287b77f41bfe7f4db5c9b971c8aad41e401ab6c49dccba28ef26acf4961978e94e633b72c581ac03621e400000000000000000000000000000000185c62a080df61ddc97ab56d2286ceec655172b6c863b509a1a92eeb0719060528ad3a3365ad5e7c0858167ac2c6d22100000000000000000000000000000000126b489e107dfdf4a4638069944d1b1297db734e5da1964086114f9f62081527d7d3f6032c2f29e75b4e1ccf5b3776d4659ff910eea5280dc5c24c542516053637a5dbea576a94a22acefc902e56568e000000000000000000000000000000000f884244e098975b837a58ae0218e7e2606821c95f51d114a483ed5d31a59c9b9cb3b1db029a0286eb95686e0457afd8000000000000000000000000000000000caab7f67feea4752d3822979a770a28c879f5e8f916b72dc71a3b14820ce170fd229fdb61596d9e89b4be8f515c470e12ff32d44eb442a711250875d86a401d0dccc95e5ee39bec71738fd812d487c600000000000000000000000000000000155d3e886cce6f257513529e40c21b5657ef1ff1f4e71bc32b968db3e05652b1ac780da573fe1a1b94b7fef86e7c260f000000000000000000000000000000001184cf09544ec2826d0101d2b79095da6e5f77d453203c52ea17b6476360ccf166ef092eccf86dbe3a260f7fd25a2794666b820fae2459b98f9bff20275a3c96ddcaf98a78f3f5fa4a2c0a26cea79352000000000000000000000000000000001523e919446b532593b8e70cff1206e8910444c01399c0dbad932b596cd0b9c2e40983ddb38eeff4fbd5e8d2b15bdc780000000000000000000000000000000004be8fdc3a3296e543701ce8c1184a983a2932f33913d6d733f5baa3a783382739b697fab4a3d6f9ac5b85ffbbc78a3540a9181633a146d7f307ca7606cd45b8e721c46b955a6989d421baafd8e401390000000000000000000000000000000018d20e7846239f472ef42c78454b6c335979ec563ecbbc3a93176a7be9dde603e6f21afbb68058035958ef7392dff3f20000000000000000000000000000000011ae4de8a7e1a958a1186bda4890d282773788f7d5fc5432393ac9deaba8bccb5db952547f6aae49b8a90c813c5a93a4662ac80797c633d8b9c8907acc2960ebdcb5bdad82d9fceb4411d5173b7411fd0000000000000000000000000000000010641c99a359d16dc3e3f68547288c944d44c7c3e6177fe94428ddcf3c86937a3fe1f41a31eeab551e11cffac012e1fc000000000000000000000000000000000f407b01737dca388d0793521b667757d70e626ea0ba3b051f522639e752280b5657b1b97beae3105489161ae95a470059401af15d9b83e2ad68cc8e2ad1508391516ba0b26fcc5ec6eda8b318a374b6", - "Expected": "0000000000000000000000000000000010084535f50807f287eabff2fdb83d34ca30454e4cd747cc3818a9dfd80c30fb3bf2f9f771d435b79a2d36105266f0c1000000000000000000000000000000001663a611323246a963856a92d52947e72dc123dfbeaeb9a3ede6147246814630e5304b50a6585894843790f5d4c818c3", - "Name": "matter_g1_multiexp_38", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005315310b8412d62f5d63fd996e8c6b14aaad5a6c83eb3505a28fa6bbe469f7a7cfcf10b49382aad4d6764859ef4910e0000000000000000000000000000000012fbfd9ee8bc712354fa3b73e57fcbb07231aeac980e99d5843fdabc081a159bfc6507911212adafc162dfc21a5afb739c351c585d1920b8cfb89a5bcd72fe041b17f7bd091ba505b287778b0be4e87c0000000000000000000000000000000014e14689a5ef5b9ee89369c5c0de07fbb7980f37294a0e7570191b73f4406ec4bd9bf4ca2521f8d90157e9c3c7d4211900000000000000000000000000000000040d06da8127e64a71532afc8846bd7eb6fd5e845ca0f1d96effe0b12a2f8afb121d7fbe89f632262ba0e382e8204701ec42da11e95cebbeed0ebaecd31be24801fdec8b81f4046fea52f553c4e7910b000000000000000000000000000000000c5ece364affb6af365a4c7506389694b9a10f3ad6798c326852fe85a892014b6901d097aa8910256f47ca1d4667b5a20000000000000000000000000000000003f300682da34e22416f1ca2bc3430e3b153c95773c8c76660603a0ecddc20ba570545d9307a6b0910eb406aa14d196bdfdd8996780460757702e34ad98f5f64a8c1e0bc8851d6c97f02749b8f77cd03000000000000000000000000000000000ad0508c3b4fcc1cc608d002b66bc703cc16182a6e83794e4f3739238c3e02fbb6387ceb445791d54321ea52f779a35d0000000000000000000000000000000009a442ba572cdd9e658080fdf1753670c27e88fa894c307eaeded6ead17799365d1cefd1fd13f0dc321c0e881a4965d3f256ff23b38b3b986a62074c5a3e05e86ead9431fcdeb67512f6d502fcefe3c30000000000000000000000000000000018825670284d3dcaa90a678ff37f23e8ba36307f3c1146a8f6c782f7b43ce16f281dd346962904684c22c1980a772ffc000000000000000000000000000000000d65166eaa6b4ed79b5ddcd7b44f06ca1bf8b960211bcb17d5a26a8595a1ae1aecee9945a674b92384ad05f2f0f64fb6c01b3c8bb0acb17198bde9adce3b0f7ed4cd8615f837aee928524b0984c99d0e00000000000000000000000000000000098da5d9289f26b61486e3ea52b0145a47847ff2b9f1d2756e363e5ea0bab27a98fd01d633a46ab48aa1d2f1d2886f9100000000000000000000000000000000191412a43858276e4d7e69542f9e6ba4fa9bc0a8784df590aeb1e0d65ffb56cce0031916af640dc3e57662f5e5203436458f882b63c99ada33d8215111a6df21c8f7424eb2fe9f429256201d099413c10000000000000000000000000000000013a279c27bf2234542f4ac0e4c2676b41b3cdfa1b55d5c0eca1c686589c37ac63139a7f532910fefe275a08ce2d37fe50000000000000000000000000000000002f56719390112560fda45943509729fef3eed60215190ca1f90143a4d2ae6b41aeaff7edf027f27857d56bae1900ecc804d7a35e5731b111a6904e0998d90ce86cf612914152fe3d2fca0201a41166a0000000000000000000000000000000016489ce6e2b8298e2fe0836556875156502d36aaac621e45514ef03db87631cfcd308285fdcf8ca7ae8bf65bf53a37b3000000000000000000000000000000000b6c8fe0db4492a309148c54465ca06c59c7b71e4418d8fc1874cc338df40fc1355a523387187402b04f5d01b5e5b82b6f1629a801db6bb4066588ed79f75223120728c3a57f7129d88f7f877149223300000000000000000000000000000000065358f885a974a1f64ffd526e5ced18ae5ebab2ed6c9719c9f879adc940292ad124fe5b6c8278c82a33d1ab2a1916130000000000000000000000000000000010d019536f727f8ae098dd9ccb6344417042855fc6722443218d83127cd2b07a6816698dc1a48776d2cbbc937f83163dfe80ddbcaeb784e24975b9a42801c89bdfb842cbde5fbc0c3d70c0632cfcdab80000000000000000000000000000000004248c5eb514980da698bc5146fd3743f5b1a458dbb17edd38f65c294e48bbd55e0d9afb3b39df2e82085fbc03e5655c000000000000000000000000000000001830c1d21ff8cd1ad8467ae0a8d2a34367e7c44829f7530263ef3d7d5bd9eef76b756f475448c308f4c03453f54b43cc1aeff13de7bcc4bc2ac1b37e28ce466805757dda29c9c743eaea9da33f47f4fd000000000000000000000000000000000dbb72f9afde915110f2483c09291595c369f0b4ce2c91779da9266c9f74764da4976a221c4997cb940302ce0e59ac080000000000000000000000000000000012de4b2ca14004be2c64ada45e9a0ba7989ea0e22d0407088a092cad87b4e26b33d5d8f96fe6831e085c6fd27901af61c4984739882bd2f882e12660815b96d2af7812d7ae87f5be034b88e9e04fa289000000000000000000000000000000001387a1edcc34afa05541e15e2355d3cdefbfe22ab7481e1f194e461521894b97b2e18c9fbab1eb5d8e508a0bdae08b5a0000000000000000000000000000000016c4ed675f20aaf2c825de5bc4c11ce1e85a0b91b08577080108ab7b52bb674f78943a5f619f557b96a72206cc1bd447e7f33141d383a1a927b7645656ff7a5795901a997e27003c5672ae4fbab4aecf000000000000000000000000000000000498481301a55b2d1dc95f8115534b1baade13c2cc4d5bdce1fe8cb1734004600a2359e5dd1c61c7338275e2f4fdf455000000000000000000000000000000000a3d2ee413b7e6c0e32e51dcb7d124be92990b7e4307b9b459da1db20f85f4a35964b7987933634fb62a07f797b00b27fba4674313a9727aa4b733832a0e06666d3e38184836edf786317de9dd055cbf000000000000000000000000000000000a885ed8c3ab46b60a7d2e198b6e8d069ca8f7e0692f2b8ce99df2f44979b6045fc17991bfc27867be79e2055cc8aeac000000000000000000000000000000001728864f0fda8476fda4df08fb6aa9e40a01dbf19a4d22c4fa0c319d8496d405f0a5f9c79ffbdd5a4c1b617326f3d774dc0c4d0e34d8a16b3bfb51ffc9b3c353817e8e357c608b5075c173204963606e0000000000000000000000000000000016edd94f91c43f15818752660e4737071d44edcec5d5de426141966a9880bb894f3566e98a05232b9717bf85d66a57c6000000000000000000000000000000000a789ee6ecb80e2ab9c6e7a945ae4839c620f9a7bf430ce09b57a64479d5a10a1ec0a721678b5bece737f0dce97a3a56e4e31f5b6629463311b9d3c8333c33c5b2e79761ffff9863acd9d636e1a9586a0000000000000000000000000000000008affb2247059dd4bd1498c8e229dcba313b156e2f420fa55331e7eac93d44af55a6c02bf2101d90955b95ff6fcb411d0000000000000000000000000000000004759596f12f17d7bad24723ccd6f86c646a39beb2aad35ae5a219ef57e1ce6eb310b2098130489421709bc20b4a53d703f256e58f60307ac1888a1b0b14b56c7435213e271eecc79b4a6f88d102be4c", - "Expected": "000000000000000000000000000000000f841cf3d8897108b4a57a7802a3cf8a43ae31e711a6258991b6d5b3851e9e0d759fb90899e462828ff9cf996bbe9ec70000000000000000000000000000000016fa655a67f441e967d3137f6ea8f6cf636fc1a7bb662b1e22f87397e0c77f34e015e6bc124291647727102a12561dd8", - "Name": "matter_g1_multiexp_39", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c98e02c9f7784d0dbcb4a49c97a9365cd069817d57cea3042cb4198180b95d141c5ba4d383de188f06faf8f845f78110000000000000000000000000000000014be6f602cd67fc2d147925cd6c90457dd253db766c4b8f737cfca02ae15b47d5798c621091c4be71fec75e0b8b1c00feb850f01feb55bb99e4accee0aea8fe6ed0bd29b2ca942ffe09456733aff10ea00000000000000000000000000000000077bb03ccd915742dcf3c2640ec61f05bbd70987d2dbe9641e0e34ebed3600703e8f9c382e77f99b70c47f54496bb6840000000000000000000000000000000015ad452396c23e820d1e8a8a9cd7557062ca9c627cc7439d43c528e0170e2760e7761c9cd872141543834c89c75537d72b373fd7e5806d227ca1f49ab0a7f8be2b5950906c8974de9f2cb4e13ed20a9a0000000000000000000000000000000008eeb6c2c00a9f95c5b238290b06a67c1cbe0e96da246537c29c0efa36b53230c3c5d91e3fa9d129743e5a9d87e81d0e000000000000000000000000000000000ede1011370a956f240419cdb8a0c8ae869c3d583d938ec32e29c5ece68ec8be0e69296ff0c97aacba59991d65a25563babde7f3fdf9fba868b5eac61337be0d73517ac3f06c39b4eaceeb27ab6311db00000000000000000000000000000000179776b08cf2da01a94bfe7be4b89b3308330cf797906f85889b63487115b386c68c8518158342747377fbda82a6d2240000000000000000000000000000000003e51d69bfdb73a2abb469b379e2b4825423d2a2cf2cec62e2313a76d260be1b0f2892bf82e5435e88205ecc9424275d5ba1635cf82b25b2d7e466717f5716c33f5f3e826bdedf19dbc1d95ff0c8052e000000000000000000000000000000000af478b121104742d0cd13473d1b7f647437d980999cbe7aa8d2246148d970136f6194df1785027ce944cf9ba00aa4f500000000000000000000000000000000170e9f798184188cc21b0950e0f3a570398a97405dc87a2e077af96799960a938f363d216474422d8f4762fe5893ece61a0a832e5bbdf897553c1aed35fab43aa3f4510c1782115e14e5d56229de2dff0000000000000000000000000000000005817e3812f73d3d236e45664af8a4abd2d4a44f741c3c1866588c2bdd88b11741b1c272b68e20800abf3adad7125a400000000000000000000000000000000008dc859c2323f0d2dcab76bd8454209c86685a971d531a32b00985eb822d33691c2524fe25d14ca386047a4976b9e7159b75e0582e9ad7aa4a02ed5ffa22e55570c9f20e6a24e2186e8a2a2f838fa453000000000000000000000000000000000ee06092a2ba4c33f5c9dc6062d50e3b133c7fde5c81056f74a2d869e8f92310f07629db9cc2b755f12016cb7894aac10000000000000000000000000000000011714a54e236d1e13f9b649a0aaa80cff9e093342c71a8dc9ff1e2d4e95b0f6b4219ed847ba6620d23feded7d95944183b7252f8f3cc6341d490c5c4464bb36e012f1b05057f405aa907ebb2c983f6460000000000000000000000000000000017f6061908e62edbb8fc5498eec23a51c861815bc1b437b7383dabf303e6a45d52e73f8363addac61974043afacb02ef000000000000000000000000000000000f3fc04d17d801741f3583e072110b327a3488135659fab2e8b1d2aecf4694f6d168bdd60624713a7c2c3314f8309079f10427f6e461e7b63b781e116a4d5136ddc79ff86b71fa754f00c797c035412b000000000000000000000000000000000db7d958b44ac5ff3bdb4991dbcdcbeab36bc6d21d9e0c8fbb1eb66601df227a6367ccc783a92c534a30b17be462b95d000000000000000000000000000000000424eb0d9da831c658ff048d3e9ee43a900bd1ac98bee97be073ea55be1dfd07d425e0906779f0e3459fc69d316599e56440c89f8b10ce15806938b7ad65ece194d2fa3cc8d7d5591bc1d52d010896af000000000000000000000000000000000c9cf785be01b7f4bfb0140004873d0db4c8b1387dac0fec42c6ae1a72123ea5cdd2b8c98c69b78d617b16c48ebfff2b0000000000000000000000000000000015c4856f183d26d13196739d9b9c971af111b4905b669f3e46bbc8d8c4281cad1be05e9ac28de0a98031923fcd1f5aae43f1bb26469b778edd10127e634fed4d749e25b41d8eba86eff2c068c33e714f0000000000000000000000000000000001802675ef47f9660d5969dbfce973c8bb3e6b2a2717fac9a509fb3c7ddb272db86f283992eb3167145f2e496002fb1f0000000000000000000000000000000014a5b5d966ff72e036c51686dc6a9f39a487ab8adab6fa4a906f28acc67d64576fbb3a00cefb7720f42ffcd62fc8adefa40251ec7a7e9f7cc29948b122010d9745752df3f4a9c67427a8b58122ad4e7e00000000000000000000000000000000076ed600ed860f16ec5dbae3f09471302bf85fde7702b3376b0d670f93560e77699bed969e7001570f44dc5e37aaa830000000000000000000000000000000000c993a8b08d2eb00bcee05e1c09e8a37834fac53643643402f60fbfe2cc7d795f5c68f3d6a32c8604c37211585830426e03e5eb477506c397bc1a5204b30872085a36b65b7a8df3e0e187f3022736329000000000000000000000000000000000eaeaec30bd8d8dd9ad4d38ff97e08706ffbe51388a93967cf16155b10d218e5b1213c29c8054cb778a0d3ad22d32eb200000000000000000000000000000000079e5f2bf405cf2dc79984ddb3f813a07225729d4cae8ddf7536e9240fbd0480f6b66321749a6a9286cb07758482e7f865cb04110bbfcdf00616c2826e253f61cf955756e94dffcbb6001f59ae4a93c10000000000000000000000000000000009a0933829c2a3f2c3e93f58551e7572ecf6eaa7857aa899a7ff0eeb15ccd601559b9ff844a177568632bc0ddd6e80a5000000000000000000000000000000000b69f23cc1556385897bb7457a706cdd8539a3ed3e7fa504ffbd95abba1e824dc77911efd1ad0a9c37e1a41a76ad38d13ce1bb7cf7d7a55f0624bf5c4c35327b178923d88be748a9b079720c27b500e6000000000000000000000000000000000d3c4cfdc03ef5fa066be3c26744032e5a2045746cd303b6df542a6133c671f4d25dfbd889840fd624125b63839a1aaf000000000000000000000000000000000102fd619ac946e99c765010a4ac392ab907c37b31f628d6d58c0ade093ef394a7547de36ca0630820f4b5d857dce449e2b4c64b363efef0c5525b0337bf407879755f060af451075f4345dea7e681a3000000000000000000000000000000001589cebd579c2cd31226245f1dd3e428a76c7d0012f8dfac4dd3428a716d05a0a79763f0061d3b5846dc29a8a006a37c000000000000000000000000000000000bdf3425e6cbe628f9223930cb74ace4358e12e5d367a3604edb05cf0f0cbde84346ef45597bd61592500583827524144c85e47ebe2c26e0aa25661d3353b5d88c632182aaecb35303d8d47f01308a0d", - "Expected": "000000000000000000000000000000000555fd5a7818bbaa7e786f11eaf6f8620b9686b76c6293fd91690a4d181c0b470295313294589daaac429607b0020c9d0000000000000000000000000000000009c3a53113a657a5f7e30ec28056455f700cc7c3d40cbe4219dac00980675023bfb7462e634c8a131493f12725a27d5a", - "Name": "matter_g1_multiexp_40", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002d49464783e5ff91aa0dbf6827315dd308e778b3da5833cfca3b6431ae784193d915a566142ef347b6ca024b6f1695e00000000000000000000000000000000029051d39ea4369a837d4cc8cec1eb8f9e7f9c3a247dcf99dc75eeae43378b4b9c4175aaa5eb3f7abdb1afc15bc2076d5bc589e7d89994400c511789cbcaea19b077e0b02d625e549bc6f2673ce40128000000000000000000000000000000001363b8347ef6754f61520942fa8cdd07e6dc2b72cd40ae41a23622be239ee25834482533ea7edb9cfd5a4e21e4f33f020000000000000000000000000000000004495e8d41b145ca7f5268e66c03528c8d976cd650d815257906e46c1f9a0827e0e79f5a8c2906ec96718538e1da3b1d2c3d2a0cba111642a6354c117d494be805cad5b5c486bc47906a2d37a9cd9f850000000000000000000000000000000007735147af3bbef7cf0c4a7c8f1dea302a5e4edf01d42c1e484f7fb1f4b8fa23b8a7a16fbece9270d8786016836bc979000000000000000000000000000000000053406bb3d2a4cf37924643a186a56844a4e77ea4c9e9e2c707b5f947ef956369f400e448930aef7135449f8cc51ae1530ff74626657262fb49460b2c6981155871f2eb5562581a74f968233c3cbe3d00000000000000000000000000000000133b92eb9f9a3c6cba655d5f26f396dac467b6444657eb0a811dc6a58ba1898f24b336f4fe9b11c1e0795891b00b6c150000000000000000000000000000000018952f3a7f8aa78a8c5e5bd96ecd5d2b2f237916d8e2982c40cb7498423f12c6ddd3cf1afee75a3e2cd773bad7ac3bf6d182ac912b005e90ab81d4f2a906da8309a69576a8afaa160fad2540ec04991300000000000000000000000000000000051453a8b81b0b0a1566540b3026e40676ea48e3c5aff89ec4fe3b36c61aea27ebe01fe8a811fd3ff73eae0a67027cfc00000000000000000000000000000000090b399b1e5af056b428a4c270eb204df4999e53807d34ca750f30b292cd38030491c3d1b0e08600f40a16f707b4903242a002a460b51429e25f85ec4abaa580ac1a14315b1627bd52349b7b81a641d600000000000000000000000000000000142bcc3458437416506631c4dda54572b5d66093ff23f152957350a3aaa462000ab000cb8e9c9b23a17149b5d012adb0000000000000000000000000000000000734c0fe1df24449ef498fbb60558010093cbc8a14ae068aba2f70bd7718e30450411a81499a895e3d84079a9dbb19557a650dd3765032ac139d1b54ec7a5457c9e3caefa6af45d198433e5949d149ad0000000000000000000000000000000010a7a3380a6d8b2bbf212da72eefb57d2fc2305ce222e8d908bb572600bef7ff55b1df6a9af717e1345967cc18e779ac000000000000000000000000000000000c5a3aa84b489c879eddd3c20df6d510edb5e9ac5c1a2e42b770571ceec315d560235b27468299e2e60af3ac1283be12bbedc44d54349cff199befba9531dd4120a51e2b830a3e356e68cff31bbe365b000000000000000000000000000000000035471ee35c187e24cf0d113c0ca1ab6322528153d0687b15953c39290ec295c0dd4197b72448f2a692537064ede8fb0000000000000000000000000000000002717020e3369b288314a42fd8ab6c6ddf7007480ebc4fa094ff7c4c4b750f477917caf071d2f1897a826fe870c2b7dabef3956ac71bfe97029b8e3f85923c2fdf9cf1ea6582b68d5a4eabc6b044c80d000000000000000000000000000000000b501cef8ea57ae253de63d81998768e115d58b353ac1ed6e90d24f8c39a31bac1a5be1b535a1dfe05e72d80d1db8b0a000000000000000000000000000000000a3b62c001c4b725f7cc861fa042c31fde4e77b3b0610df63dcbb7e89d3fd746919c2bd8ee4d623838a05d42b6932383392f5b4291fbb18a93248e830b08fadbaad6434040c02b45cade73b77f22c2bc0000000000000000000000000000000011cda0c937d8fb2b21174ff3a5b88aa5e1c9a8ce6eaf26cac9fb3ee7f3ad20e74ebbe2d1bd9f4faa3acc43b6e6d0d70b00000000000000000000000000000000195257a442c8e39ee6b72cedaefab0034f48bb988a3355ad07b3e3e314800b2ce30267dad6ef3fd9dccd7d2318dbce0a20a96f963375d7a294b584f2da699a6a00eb5781f46830987346cf4fe922a2f6000000000000000000000000000000001630ea3c7f910ee8574f29d652e86fe3125c306218a894df0b4688ba582ea7d597d7e62cc2e7c78dc2db289f587f10ce000000000000000000000000000000000d2ecfe74480518ad4f5ded701afa68040246a08df1b8dcfe6fdffe77e33c6bbd37192c6c41c6ab5af506ba58d8b3fe4115cb4646c8996239f4fdda8c27a335361f0a19550d6eb0225c008408c4725880000000000000000000000000000000017a910c111d7a0f7e7a3d48b1cd358e2a1213edc077034b06d1e96beedef80473ec17d1c10bc2d33d4fd2a8c052d926900000000000000000000000000000000040167897293a68c980bc34b3f79802b95186200b40b4763fee9cdce8afc681ee916042d619cd51361e6e02688b4915ac8a8d98c93c392aefb64ce0c7ea455ba14c48bfbad0e3dc38d43abbc3276caab000000000000000000000000000000000dbca3203ee6c7fe8d6504ad2041aad2681b889996bbe28ff1282cd20da563dcd5c9fea5fd03072134019f579e4ef7af0000000000000000000000000000000001317a861403866494eef2bf59519f2d324586e93a0037d07312dd8df4ab844525afdf4b70f9e21a6e0230bcde35db4d8221622734dc6ccf6c7b84b387a3dfecafe187dab70ba373b4416ce3c505bef200000000000000000000000000000000069ea1da08dce1c1239d49411861d3e8ee7e6082d9bf8ff0aad1cbebdea6dbf82fb0d6332ae436327440b71ce6535ed500000000000000000000000000000000079904ab7b16de5812ea3eae39d790aad32db02c9cbf7b8a3a8d4222d3baf710ba1cc5bcdcf4fc9e2c4567992fa911edd3d1f427a25f5df025fa71244cb92dda9391d65b04756c41de0f67ea072c375d00000000000000000000000000000000173ca2615b65e574bd77c8cf55bb116462a7ab9ad4a3879f0eefe03f1a6c0d30feed076e0fb21fc60ee9f270af180cda00000000000000000000000000000000179351092d68e7e0d428811cd4503a57bab9a4072f1bd27b5e8445ec0058eb46af58c4752601b53714b816a4bd386048b55c943fd9b11f2fb8a89f6c08a6eabe9434062354d845f1ac740e6043443f8b0000000000000000000000000000000016c9d1fc1790a15985028a38e57c87cf010c87bdeb2a288a055b4b08497abd1d616fa8b28d6da8cc23047e9f8bbe6bec00000000000000000000000000000000089601933b759bb565d849c3837570feb39d442461d764a22f993a695fe1c55283b8c7db02694aa66032512d44dc88867b0c1d54e51b8572256aeb72bb032a5011a3e8ec5ad7e8b6e0397b9f6fc64c9f", - "Expected": "0000000000000000000000000000000018bda18912ce64106fd3d54ec2024a1d3e4a807d7bb8aaff7b515d75c9934d4729c14a4a72ca7654ca811a69f09d170b0000000000000000000000000000000011478fbc5c03470d9cfbf3decf9416e1dbea8a696636b94244c5c637e43f81eaed0210b1cbcdd291094e8581dba3548e", - "Name": "matter_g1_multiexp_41", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000446af4281a01e0a20b7428d06b63b89573912955971be4a5cddca514708419640f8a7f95b50ef8714a04e1fd81bec64000000000000000000000000000000000087b94d8493239047a5cef74dc20d7708d7e3365018df80624cc5511483c3a5d9b14ac3d4aa391da60980397e4fb1e96f082a5ffb8baa38ffd684a4a70114343a1e723bfcbfeb57d0a85ad5e592d74100000000000000000000000000000000033e5eb4bae80d55f512a48b44054d0efb8af1f9870fddd99df00f31dd437025381df3f4023ca217ba924a961864223e000000000000000000000000000000000f6d7a7371eddf7283890d59bea3c61fc3bff19eb7fa333ae713fb9a73c4971354474986ef5a9a81ca8c5b38bb67f58d5160286a6d23c30595809dab6ee6523d7d235114d1b295087e024b4f6ffc80e50000000000000000000000000000000013d4e9518d398fc0add8233fe58c198d65966844fe286fe657891245fba8f37665e2bc40e4e70886667c9e2c0a1c245300000000000000000000000000000000089562c10b287d4d66b2b694d29fbac936f700de78525e9be59a83543593b42c5c577910e7ba1b67d840d88e7a3e53fdbbca29b94b6583d46753473143d13a7aadb0b18d6d35d7423b8a004991fa1ce50000000000000000000000000000000005762727639503eb63854e5fd3de33bcdd80227e16de19cd7cfaa10b7863915e490087dbb980b6dae5114df7d56716d300000000000000000000000000000000104306b38970a94b5c8839ff282883b7c88c7ef45a7ed49a02b322a16521faf2b881e2dfe22da3f4472e2bea9fc40d7e607c80069dab2a16e39370de32df20534aca46565cf573159a93c64f1f0c4a1a00000000000000000000000000000000056e61b51113719c1829d4ae4361f79c543961de801b1a62ebbc3cff04b0722be241236d4e1b2dcf7c309ab9735334a700000000000000000000000000000000031ddb45e491ba2d719b1f72f54640c63e281dbf6ff84eba2eaa2b781d87e243e7bf84d7151f27556156970dc8a2407f41c1f256e866d218b3ec20c132446945177d518573ae3f0e739ebcc8821bfbc700000000000000000000000000000000029eff96206ff45ea9bd0be2b83cdb660d6bb2d236971517b962faa54535f01097327a00154bf35dbe47841eb36417020000000000000000000000000000000013734f1218c3c34d2780920806c5ad211128352d8a41c2a1035594f470ae347e372914827775094164a5db9d0b2a1ef7c72a47e2267010c532d676ee3c3ebfb2be2b7569f6f7a22f76733d7773ed383c000000000000000000000000000000000f3aa9f069b07cc935a974ad4eeb47e8b0083397928e8102651ee54f53005625c359d82fc8b5dbe1c76f650cdccc2ee2000000000000000000000000000000000e2bf6a8c4234d118676a29f12daf244ad9aa562faa970d2d63feb074946ca70da039e2de104f1524b1a8f3897f053f4c52f48e84a68d99124e678dabaf376c956dbe9603974283a9efc7c27e830e959000000000000000000000000000000000795a2b6b27209b48c00cc8d37864f14c6be66d6a41038122a28186d7bbcc4b02f531aaabd000fc93c685ceeb67bc3c500000000000000000000000000000000143926b42a6654e439fd01883f1ceb524cd8b5b1f2e3eed3e905f6e948736790cc1325d1b04e30247e4971b75939a766e4fe662495bffd8ace4c1ddb39e612b361bf90a0f1bdf6c7fde2bcf63df1bbd200000000000000000000000000000000074096150c9e04c082a1aea20c785b3a7396568e43707c42c512575a97db8127c8c1e0548d640dff8821d7d235f268340000000000000000000000000000000012dde2f1d15c04292bb5da4c467cd674ddb43e401799257524cf3097d0dda1f3c9f2f0637cfee914a4c66d737f9e3278651e67e96f64b80f4978fdc1cac90be538774e34c2f619f8b8e60cd2aa20f269000000000000000000000000000000000109196dc59d6ec06fc4c774f665612c11bc3e826ca4ba528a15c6290f733f3aa1fc441bd896021471e1e85943fc9ec2000000000000000000000000000000000aa0d17d44bf354e48275ee3e4f06291e242402469be6f4cd4a62ad3871d878c1d27a8d06974c5c1138281802368edb01a6ecd3db89a7f07344b5728efffd35a11f7380c740669f746fdf565905a1ca000000000000000000000000000000000067458ca402c19488e2515037abf9323ab8288e0e11f7cdee18b3da50cfa377435cfde1f63dcdc451ce65a05641cae370000000000000000000000000000000010ed9c895629bdafae66ea176388be4e4ce45cb13ecbe0869ce57f0f48852b6b8c47bcc4a14fc5327f1df372ad9f5d4a7db5ef4c1c174c2e5ffe5555f54f4e845c463bb5105381fb39eddc01103b1bf7000000000000000000000000000000000f393c5fc8e5f1cbc7b59742e5b6236c9d1d262d0b736c1bc188ebf58f954bf2835cc70617062a01459c139f328c912d0000000000000000000000000000000015501635aa7565045ef59067e0ae91a5ec4871485ba411425987d540bcd7b5782aa7164dd631e4c7896b3949cb115f9a14018f14c50d40d3324952ec22ed247c13c4cf10eacd32c3671757bd12b041e600000000000000000000000000000000174b0620cb49d8b1a5798c3746046c2888c8e96664dc7bda5b4e90336517448eef534469a40086703d9a835d2a94930500000000000000000000000000000000033db9968fd6322e7bbb9de572e8c92b5e3717a9496803e3f6ef8dd796dc6487909ff318ad6d4d91297ae6f2daf07bcbed4a28dc3acaf2220ba56d026b292a7d017bcbe358dedc57556cf638517bbb14000000000000000000000000000000000449ee22d2c23ec02fdf1751bb59feafef9291d6d56f7120612948875afdea56453e081c5c5086205ea83f0b8cd541ca0000000000000000000000000000000006114d6d8ef1e4c6d79b23a2b91e5577323107d90523001cf7d6d18a0ecf3b414d4fe1a3eb831a6d907fce9d22030bcc30fb17a38b7d0888eb02394eed26406bce9e92779251bdbcb432153a550c0850000000000000000000000000000000000c2082409ec14f6121de6ebdc06656a28dfc5e439a0278593dc6aa845e8091d8caaef45ea1ad05aa12e3c1533275a663000000000000000000000000000000000a2ad9980247640d44d3b37c7b7b2c1b57592ac12cfe9aabca4f88ba90c8b3221a2b9f5e4ce19ffcdbbaf99ffc584219980b5873a5d0f78c3b8582581349498fa997fe3c6b1abe0edaed594253359d8700000000000000000000000000000000108ea3fbf78237f0e90d4addb69f25eadb0f21c89d92774b4fdcbc97632f1622ab4ab408fee95e735281ea5da5c2c8130000000000000000000000000000000012338527c7932a737daab3f8de98b9f2aab59aa1b12e84d3674a8ddbc1f86a8a9e7eb0ba854e9564407aedd489b6016c619f5719c320320a3c45dcd6207575e0d8527c458c56d3decf1d12ead8a985a1", - "Expected": "000000000000000000000000000000000aaf02063d6b5b395b75faae4039cf2eebb69053f1f161242b47854cf07786788930f3be2598520c178301ae0bd13ab80000000000000000000000000000000019574e1de9161a11e804d8077973c5ca70ff7925c847d870cd2bc985a8724d41331fec6c1cb341f7509a37371db9e4be", - "Name": "matter_g1_multiexp_42", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000048708595ff4f08cfa2b1c101ec7b3538a2e6044157bf39a63255b5540211105f680464be5b03256f9153a90a4e62d44000000000000000000000000000000000f2fad0353cd8fbcf0ba75a403209094d88d8c8d068eb0c7077b8263fd9f7bff8d6234d75ac4da232667b5c566604706119d33d32affaadbf6c2b6243bb7b344a971270b488cf887334fcb15de2818cc000000000000000000000000000000000866fb774b231d82a4508ff9b017ab836936299954b2b404affea65f315b62da34c76019192f5c9a447dba8cc1b9075d0000000000000000000000000000000004e050fb7a17bc738a55f1ceba48920c62648a27cf438b770a66166522fb0929069fa6f2b2b742ed689f554e9023ec14f1d832b355d7e0ac3653431528ad0a8f6819daaa19292a00c910ff0ff39f46d5000000000000000000000000000000001710b342a52b0781d1ea18a9f07d54fb18e9c90e44815cc7509aca3a5c9ca3cca6bc32ff6ff726cfa353faca4f097e9f0000000000000000000000000000000017fd38b122a7ac39533af597b462224b86370f6e6814ca1ea71d961b9c7cf94b952fd75502031cde0851773b2c6b0108e6dcfa50f6129544835b5a4568954264ea68d9e2e5d4370ee31026997a3fbfe90000000000000000000000000000000001fd243a3c69dd5e7ef19cfbd9b7cecd475e88d7be85dd3a8f48eb46d5dca39d05aa4b43c0c700b6632ebc0b4cb3baeb0000000000000000000000000000000008ebf24e9d2de0fd82c69e0ddd1625da0367c2e9f975118dd2ba5606d77de377be10515d9eb921be5136ed25fa6b27abf7822767391d3b2331e8e1b81c659c6e0262f7355063decedabac9797a84f0f400000000000000000000000000000000021f919adb62791296db3a0b81f03b87c01d94ca312f55cd94364eaa654bc47684d7b0336a3afe813ef1aefc7dd0ced2000000000000000000000000000000000b40dd6bc2fbfa2ed277d88f77aded330c54c1c46a781ccd039b270ee9b799a70855ddb1201dae29a1b124dde1e6acaab1ba1cd6a4a6c433624dec63547119c0d492e3f38afb04e5153d82e400631aef00000000000000000000000000000000054f284874c53bc914040e6751ddd444604d34a38314d8057fa0f77978150fce0add250a6bd8693ede79c9f6b2e025de00000000000000000000000000000000045f6579793d166198d73ccd03da2e907efdb31b54b0b0fe3e2f1e02edd7d9cc0c08af089330d53aedb60aa7cafb0e0ca41e184bcaa0721caa4114d6393ae2251fed84aef57c7927a170145308bb136700000000000000000000000000000000189aa0df86ba479009d4bfb8608c31d3d49f52f1bf758e5c05ee9e5a673bfa15e1c6c37a978c4c431ea035cb7948297500000000000000000000000000000000120c90261fe77d6f41a42a170b28df1c9e6e0cc4bae247303f399d3be7c6ce8319a43e7d551fe554783ec5ccaeba3bb363cb451d8eb3565274793925a1869ca5a25fb19639449c71a761809f785568de0000000000000000000000000000000005e990869491ce375477b586b63641ec71adf226c631a14ebfae3514718ce546987c17c9ef41f9005c10eb04909a74ee00000000000000000000000000000000141b8edf812a2918dc9a2242301a7e7f6433a83298be9312cb48f0d3f0c819a4368ca961a0b6f09f9e077cca6111657e6a2f94d55f784ebfc6b6260327372217d6a5b9637ea5f9afc1a65f99c221c29f0000000000000000000000000000000010f3f93de5573e42ced8278a7a12b58086c04f8b862e11f256f26731560e606ab81d61a1090857eada5f8eb3afc363c400000000000000000000000000000000111915ab2711479677489dad7695cb02626a0525ae9ca51b5271d5fb6ff438d99730369654240b05b5d47fe00847c6327d889a3362f551b88e63463b7f0cc334fab3fdd302b630e419e362ec1eaaeec0000000000000000000000000000000000ca6c2f2191cf86c596b439de0e0df79b441de41c7661d4b80723f14337a379bed9b97958d225700f06f8be5401399e10000000000000000000000000000000015904391fc3cb879147c2b5192641c4ddde11ca8129c3a03b82f5f824b2ae60b3a33c925112d2de94ba3eee10761da528bdd400ad873cd6ec546bff698171942d536b94e69dfef4bbf316a471d4b45cd000000000000000000000000000000000fefa6dadbcd8edf2861c6ff4f5eb501a76507b1fdc1b8cc992226a7e5ee17ea343cff89426c409bc36c2aa3a8f5793600000000000000000000000000000000166706cd1ae090a41ea211d1333d360a1e34dde717979295a0d6a870932f31158e43ca041d1978815aadbf761275953163b496a64cfd15410192aee9912f869deea5a08eebd6b160667e12fdf23c44510000000000000000000000000000000008f02061fbfe82eacd770520b46ab49bc29bf358468adcf904854e39b30ec4e363e80f18eeec8064947bd8612c37493a00000000000000000000000000000000138888a1fd168e9c94959cf026605691b4100a828c3a75ce95f3dbeba2a21d8a44dfaaad834dbafe28c12154f41f652e70de38cb4627f53509eadb0918e562c6fa68a4cbdfa9f7578a8aaa8182f531500000000000000000000000000000000002a07974c00de6936c31202e2b0c76c30ad15b6c42393d5c5d2b1e0d5eaba8b5680d3837a8029283f572d43d2944e4b10000000000000000000000000000000013fa3f905a5618b7aa3ee5ed37055f0472fa361fbe07733f9c500657338c62bd4cc3b0b89e8223894f365a58100ee35416732c583e8049a5de38642cebab774d90d5f87601e3599ffc9af692ba532e620000000000000000000000000000000000775861019fd75c201b3a23141c8e962948ce38fb0f15cf9d08d56ce0dc574300e0a6ed90a7c50b8c71a1a9c466d16200000000000000000000000000000000066ea30b3a1bd410e3c70b1173b91d3eb9fd0be55b2d583c4be627c3aa9cab1b2a5fe13ccb37d781965b1b121079916c4a037e7562adfbad6b1ac48b8e4b6f277a788ea2f4416ed2900ed2791f09bc24000000000000000000000000000000000ec3ae37e6e5b0c623534f5c02d998bad139394daa28aced4b9f781a5ca671a02f1638cddd3bfb5124f9c5c830cdd9e20000000000000000000000000000000002688ab0be331d6f8246a54749c54fc111d2f7414ddcb1f3b42724e5bf14cb8ff3546a3b9be6115d91f62af8c3eed35efa878f6a2e18b88d6badc5b42775e92c17974f3a18817b7769d44ceecac46b890000000000000000000000000000000005d5e2230d538b05b690e878c03d793fc70c391e853b0ae3609f81a7f24aa6d5a67f3138308328783888645d1d84a15c000000000000000000000000000000000d625eed47e245ee74aeb91fbd72981c4f2afd53deff7ab478f32e2a8635431d9ab9848f7912dfa4bdf8ee7201ff418bc4f1a7d2b66e6202c957a649384cb277dbba769afd60708b457613f0f3372515", - "Expected": "0000000000000000000000000000000007cff832bedad3caa9c91ac59292828e79811f91c51c4799e2752ac0c12e2c47a2a07ad0521097af7e4a939f3fd230b70000000000000000000000000000000015037ed0ec4981737fa94f276aa9a4325a2267b90f34844f14a92d677060a23e23e3ff0b3df77e7e67e85c23b28cd44e", - "Name": "matter_g1_multiexp_43", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006984b92b5b868004f39ebf04f41084d03704732363e65c823e5ad4a0a3fb4c983ff9375249bdcc2f46650921031bc1d0000000000000000000000000000000019b9d69589cd29a9909af5a303586aed5e33650331b9866a6d959b8580ca8312ad0e96c7214ad50db7502f50ecdcdafb0241da9d8505208b4d3ba2521a42f28df7d06fc212e9e84931cbd30ae3ba2e1500000000000000000000000000000000173433f7025400852ffdfec020a44b545b365158ba8f919f434fcd995c0d84509c77d8a05405c79953b8cb667047690e0000000000000000000000000000000017d73ee336ea56efa64038b31d5abb6650c4c6f7efe67add40d09faf93fdd9fae44732bb69dbfb0dc8267c4d01d8aaae6fecab1334668102e47f1e7139059c1d715a1851a026a1580f93c2daa3f08a2700000000000000000000000000000000184ef5b6e309fee5030e2cd8c6c3ec49b1cfb09cc9cfb349ed47e17409d9c478e8e54f285a3b3a4025464162b172d33f0000000000000000000000000000000009b78ea5d2fd2113a4bbcbbe6d0108bcf27b60ff435b5b587e91155eb0ac6ea35c27f276b7e11fe5fb59508454fd8bd24e2023c64a3b51cc3d82e262f83260ed4a5e9e3238b85077852fd501b52aceed000000000000000000000000000000000d0b8aca446806ab51b4a49049cede15587aae742ce7d80c2a05d255429c945d1337b4fa7ecb8f2c3b7c0b0299a41ad8000000000000000000000000000000000bce866df7061aa4319336ba1f876254a8e0faf3faf2f9ffdafd0ebd7d7d0c854c61b476583207818f484ccf7faf90fddc0a88f0aeb2b082dea6b50d591018330c2276830ed554840c10772403561ed70000000000000000000000000000000007018908a64fe5795ad178b8bb1c8540ccc5c78ddccf4e6cbae72bfb84e794d23172998d29e568b186cacfd025962a010000000000000000000000000000000004751f7d225407a8d68b4a196e32cb4c0bc6a9ed9f2093e4242b268d6c5df978b8595d8940f59be860b66310bf8a5460f68c9e76d9d8914f14007c968a31089041e67312c6a3e5d30e65efa55894ba74000000000000000000000000000000000f61d66b0539c7ce56da9308d0ccfa9245158541b2d1b14c381ba53471ae9944ef3ec9f4eaf52c95d5d0bda92d6b9a47000000000000000000000000000000000612e57aaddc6eedd9b8a08b991bebe6f5cdf7805c2cd4de5853856f11eaee94c4c2e0799254f98348cef63236cbae3980eb90c6cc25b3a48d93b94b698eff513da37210ba79d22d76a270aa97fd5107000000000000000000000000000000000b8a8cf0fa6ea9f3154eb35994cfe2f7af4252adb8f26d718163f2bbee3cf1bfca400f4d3582fd5fd407083e0bb48ccc000000000000000000000000000000000c3251d0d9e8520b3e7b43acdef58c75348786654103fc770c7ffef8593b169bba3eaa2686791f919fc70f40a171bda8067bfd893b12c79e13659ee9b5f22de71d806a85410c9a23dc43363915a606b10000000000000000000000000000000008138d173e3e8f5e63f6aef89cf2437690dd0c848435f6032f943ef6cbca87bd2a622f9aca825b7caefb497450dee4c200000000000000000000000000000000183379ed3c9a6a6904e169c68d627bb828a05a93e38ea3b7886db2fe6d1015319d3887136180ab7dbddaa26b1fb3335f34abb11f7ed6d73fb81ce2777acd6bbe8839112c527ef4ad88b094cabdb4742a00000000000000000000000000000000083f8fe152f7edcde2c81107eacee9c58ce22b5aeb10eac15e7df1657a813c98b182433655380c9e8ac18efff2188b5900000000000000000000000000000000100b06f6129bd9063d2841f4c244adf2dfead83e23f3b1586126623ec35674ecd6422efa0e86ed0502a83549551afebd8d6693acb1eb73f6ed1bb4f74f1062f720a7f2c0ecf2b5a944ff89feb2688e1900000000000000000000000000000000072c644635936a91dcaee40e3b4794e634c315a39a9cb5cb99ef6784b332fdcfaafdc80e228cd19d0104d5796f584c350000000000000000000000000000000002318bea9077484e9c1937dfa63774b5ecf6fc63ff06e5cb653553d5111a981c09c907069ffe11b5704ea60a9987328329ca1b157e6a2b5b88d7467e851282491ed30382ba217b82ea5cc9ca0c698693000000000000000000000000000000000aa7249112c7897c9b1f95a7d8299790a25d155dc9ef7b1ad6dd7b186bcddfacd4c77ee95e634b5f283c8caebc00b9c30000000000000000000000000000000012e31211b2bc88c568e08157da9c3e3220dcd563cebe44653ff4d62f8c306ee9136832704272317342f634e66e8e66a240bb53575662fa0b726469da01c39df389efde3936d2eee18d7035704130ad6d0000000000000000000000000000000003a5576b3663114b410276a8c537a93f790276754913df727ec6c0a684ab3c705ec04b8bac882bb9c5223702860885520000000000000000000000000000000002221eb21003c6512428cccf8a9c775df9b72ed8810dada5c92463e6cfa3d619f22a22e314b9b8882c9e2f609b73353a1574a30a575138c44881c1c126be214c6b68335d7338875b8a398196f27510d700000000000000000000000000000000111829f79d4ec1a80533f76f32503cae2842981e29ddf9a376d16ecd7037d3e0dd1f8cc84d512fbb39d58564c019a559000000000000000000000000000000001808e65ee7f31a1fc15d187eebd76c63a3158469099bd6acddb0cc96354072f636651137d060efd850fb599a6965044e6dd51553c4119255b31cb0aaad7391694f7dd29420420b513699747bee819a99000000000000000000000000000000001274417dae37cd33b2a3e086f327df292b6f997e5c93e71add346d6e5f6ded135c8d6047978c10c5c38752006b7f76910000000000000000000000000000000014f867c58d3be7b09891f087f47c1bcdf82c16f899ba960d8a0db4a5eb66efde12dbee75e77816cf9afd4877d9d08f32d88f049ab3ee2b01af449abce08ca14ea3b065f06a8665ae3510b4c04f423082000000000000000000000000000000000d98fa6b2371f65f6f0b62133d1a294a7faa9949c7df16818657a9757fbd8381222cbea98a72a951e4b2b69b216f705b0000000000000000000000000000000016331e8f0661228b1e5f4df59a09de5133d16e06e1628afaf8b2a1160961ed9738400078bd79cb5bada5f99748ba220b19d6e227185c538b122858ad5ae594720fa7f743f5805552152a213ebea64aeb0000000000000000000000000000000018f129d1799d9b46dcea6d239679eb64f144adbe1a9561044355cf66b4b1158513406ef4423468b5ae446c4128dc03d8000000000000000000000000000000001669ead3f97913fe5448bda1bb0be354fff223e51bda5eba9743526e964247211e9cccf75e6f99c6abb5b8912af94f5d3f53123f01c4d0d4c18dd72ea87ebb5fcb559df255773fa0165f1432c229deb6", - "Expected": "0000000000000000000000000000000013426d2d18267fa615975295d2029d2e5730fc845556d501c8c6ff8442cf0f3c7facfc329f6703043bb2d45acc1639130000000000000000000000000000000012fea8316f8eb7cd655aaf9cff8e395592360eb6d62bd42f6e1d1e27b9b54bfb7be5b56791d5ba55a798f073f9b5634d", - "Name": "matter_g1_multiexp_44", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018eef275d602fb152cee956b04313bdbc8f0079da7bd8d6841fbff1f63a9626f17ea3f7a8332023fd9793ed2eff3990f000000000000000000000000000000000c41214c40c5c65e79f561b59d7ae103cf8c60f78c2b0a16d96a2e714eb30eeb0cf748044bdca077c4be5f4ed155ec50cdf2bbbad52a3f5c0b3959d46a8c42f6f5250a93c3dcc636712a4a2baed289c90000000000000000000000000000000001e5db25f5964e3a5030005152fbe9c00252e37dba6febdb7441046f734d4b86d60334d91960b09bd32d258b7ca2662b000000000000000000000000000000000949bfe49b0256a01da76f5c2270cd0b6ae70fdbeb55f932895d0e72d94eb6db236a8ea40d419ec6d9354c611b8010a918adf5d8fbdf81f8e4bf2f622e2d481fb2dea06a1aaa289ce4f6e783eb9a98dd00000000000000000000000000000000158addae39a79638dbd1a7cc280e0a24d18a4914ce4e290f8f79c147c4e817d95a01bf6b074ef8e819a124cf4e3bf088000000000000000000000000000000000bd2f13538d08742b3bc7b1cca9cb9e059b4bcff76b49a189f506b4bde56d8a58fe0bec2f8425ba5d574dcbc5efe0e93650e995b73b63d068fd54f596cd9669fc3061f0c1da77ae7d0f5bec012f9ba69000000000000000000000000000000000f8615d47e4327d862fa64ff4b9be14df2cad729b816ac7bdcddcb32500b6523af3303fe36c0e93b638992c671958d5c0000000000000000000000000000000011aa78c5d0073fb9b34235555bb2e3f27e55a1d576ad4e3f63974cfcb2646c6ebfd6e595d46613987c0c8e86846845dc3350d4f13e25052b1162dad3ace76e5cda71680fdc89460d8fa88c0d157df426000000000000000000000000000000000fe66db078653da2fcd1490a36db9371039f3630bfa4d574cb700b19697c7194e8e44453e16ae71db6c9001e18392a76000000000000000000000000000000000cc69605c26212c6a088b9a5c2cf6024e46f035e4c64da67383f294d6186bedc18922ac891f742165e3f09fb1720d476283f0256766690c88df6cf7c968b9a96121d26d19672ce9adc84b699476a32db000000000000000000000000000000000a280b29948ccda96a2a05ceb9fca703dd63c65ebe18a0002cf1c63b8f64282cf9d3d4d73ba3a13426f253d09f83ebbe00000000000000000000000000000000146f604d1e90c4a14aa6599ff5c6389e426232a2dff39334f3390006f021f83500300b7b0f1585ad591acb1e0baadcd7145cdeae7fd3f7455dfd2ea9a064c135f0a0a36990ea34929e292e4cdfa0f4720000000000000000000000000000000000be58255d1f227af95dc9a818204d687064d62166c16f1de052aca69a37ae98c2a73a9a9cc6cf187128e5b86969e2810000000000000000000000000000000003f1155d7e91220bf0b80943a16a9f41e4def1d5f8ce44d95dc2f9099019a1d5e770158338ec248eeda7c5af412890cdd9cdaa979ab08b454dcb961e3cc4bb18f706bed93a72a9c1e105cd69c0b691af00000000000000000000000000000000077c3ebd0169da81bf07ab1bfb8770732e4182a30504cbdc8fb1abc49f31d698c17f68de1a6d8bada62e98e09bcb22130000000000000000000000000000000000d677a33c1590cb55c9c78afa455fe2b349c465e90537a73906343aef577afbfacc8e157ea6f834ff959f3dea5941bcf262f9f7a26353193939bfbbdc50ee35614a3c099776f08b21e0c4c97521eb8e000000000000000000000000000000000aa0a3898520c5bc19d7f3a8e0710585dd08419b39d9bdcfe12f7baa6b4cecb50bc0d6e877ccc2518e4d0254934669ec000000000000000000000000000000001376af22bb714adbd16d8d41ab503066fbe78f799aa8c1d8958eda9e4c8c6fbe119e592f655e0c3f93455e8acd8a2bc14f0d2915e82c9a69f9e9af64a2c5cacf61ead492bf69912a35ad6a316f9914a80000000000000000000000000000000011b1300312d0ad0352ea153746f051816693008f2d0b980974bc354996ebb664e910350e28770192f59c053f3f2bf00500000000000000000000000000000000125d87c441a1dd88f489514b1d550387aaba857d5a6bef20acfdc0afdbba3e98c2e0aee0528cb78970395a9da853ffba25ed3f13198b69604c08b414562f67a67aa8dd4a7bd3c066874182d21ed9004d0000000000000000000000000000000006a05ac512adc0dccb74c7b4c2187763a6ba8db9e290cb0efd1325b7a463e0e14a3e7463b5cedd732527dbd131246c6a0000000000000000000000000000000001c1b41b6d5c823c05a5d6db55d7068409f5fec25986db6e2689dc6ec3e0d85749db6deb737445c5feacd69925c5dfc44ae188cc115e9d492be64abefa4bd4c93b61dd42a7d213e1100b8108611a616300000000000000000000000000000000143d22823412da99f7b87a794662bded7b7ebad9742e4d6fffd471b1bdc748c6f1b5bb395cd0a79c7291b9e8081825ba000000000000000000000000000000000f2b98d54e293befed0a97667791ae35494084229b2a25494fbd7295a04f03173a52efb8ff9033c4615ad1185d4e9032eede725a693277356ce71ffd7814a77fcc30eeb3a2b8863fb91ca03da1cbe37a00000000000000000000000000000000172919c33fd97de83b30740356c2bb2a9c97c3616d9f80a8d8266e07a1de21ad974ea796d3cf56660fc4e0df263a27c80000000000000000000000000000000019afdfd10bb736e8a6596db59f4f9a8244e585fa81ae315a768c8d91716de32d42fb75a57da238dc597885f083049a769d0618f898594b23ee3754fe390d6bdfa7d47fe749d6819e306935c1eab6b046000000000000000000000000000000000a944d2667a10dc5892760cd3e13289785f0a5a461068d70960e6546a0543474f92d68ecfa96efd19619d976af2ee491000000000000000000000000000000000a88a16dba3fa6cb5ef21015b18a14956ec9ec29650929fbd0308fa59ac4aa389aa2e306a3a68fc04e062367a72b3f861e1c9420cfa91026286d7f986b538c13e8c97893995485308c69f053927f96220000000000000000000000000000000014118a990f2649838954ab911e795c453ecd0d700077a5fffd1a4f303087074d595caf1b20399578ff1e23a2cada7e5200000000000000000000000000000000145bf8164b82ca5f8f93d89ca65a894c6d15e38da2cda296a94aa1a1efddc4d2663b8f09efc3b2d78510c4dceef8558fe5095ed9a9181aee392888e3194ebf9c4a6d87b503f4668bb6cc0d290880a44f0000000000000000000000000000000012db33b91d99f44cdc785470e67a781b4a72ae2dcfe4555efe5b7527b9a76de8e492c4dc7793ad948cb46070eb1cc5be000000000000000000000000000000000ecf06e454ea574dbb9ba6209577425a58267d01f29f8706d06018a9caac994d2dbc9c6ca9fe3ec01aed9aa2ab886c60dcece8ee33d3bf3188574e94a889794077035ee92473b7266d92a3c018771b4c", - "Expected": "00000000000000000000000000000000003747597e0f9bc39306319018fd08bc936c4d37cc6f84ef296df5a36cebf0aa46ed35ed215ba89a247174fd72fc7c1c00000000000000000000000000000000150f973b61f26aca79a3f7d1705999308a96136b08673322b4729f16b471e38f27e66996e2921cfad0cf889878c2ce27", - "Name": "matter_g1_multiexp_45", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000046e955a4631d1a490f92cd40ee0a31c096210ead2b307a7aac60e84efc04898da5d4d9767f1303ad5652a0e377f0738000000000000000000000000000000000afd054be493fb26c7826c9c1f62365ebb28ed853bd3a45d266f4c690a24e179b2eea5261adb0bc50dd184c165231d2eaddc845ad867f1e2664ef0e78bced8ff6904c5836e7c63ea3a9c858fd7b710b6000000000000000000000000000000000ec3c20a24a5f9fa7c5754007407d1aaddaeccf3f7956914ed3b06dbcff7f15c6d487a3b71fa9aeb61352698a93ed14f00000000000000000000000000000000086f3cdb1e21cf60a7a57e7ea7e00b4698a837916eb1f6ac1c6cf97ef2abd48292ecfa471ba7d9b8688b6f0dcfb6af62c78cfc6a30cea34d3d3505f4f897631f67ba77913734f6c2895d871fd6d5581c000000000000000000000000000000000769b870411b65a1a86dfdbbd7dbb65feb708f9f90ee73153e42f7141cc660c50f41835ee44f58c7ffa136b944e84dcf0000000000000000000000000000000005f0480b4a35dacd304d8feca77f8580f66396a6434af09b98d57fd4f9f781012f3900407a49f4e0aca8d3ebddd2a7bea1e40df9e1f7c84633cb3dc2223296887de7281ea66c5e1f2d5816334f7b280a000000000000000000000000000000000208f1b01599c969333ddf9accadb24f1c8239f82f5beca72d0d6d823b59a3b8c450e25a2da32b5a8cf8c0f47137e04000000000000000000000000000000000054051408658f025572a45c731e81f3fb88d741a632f1e2acadc48a1f257a69481c9c11e655c226d8e0623d34fc9fc158810b9ce0020904dc1903338089c30e616ed0be03741572ce46946883874f4ea0000000000000000000000000000000001738659b582e3667cee963fbea8cf695daa6b811dd808e724ae77db2060f248accf645db52f9838802c5322d993488e000000000000000000000000000000000a36fe571929153dd774fdcbaff2b924cd3f0ab4aced47d22a2662ac6f415b89372406c4ea5a0a466d4a4c5cfb02ad7d93e7702da2ff9f3f14586a9ae80c8713743d61b915a7c379c1faa1b151406a9a000000000000000000000000000000000c70dbc5f707fb949a2e0cd57e0ba6a5d28a2d85affcb55bdc9fd24a3fe395bd78b7431175a629475c0932b769b55d6e000000000000000000000000000000000a49fcd19bde4473bb98384bd63e96508b539fb80e1e0cd9fc9aedaacba0c36d705ad16a47f345c083401c6640675823eca54e365faa35d2c9be259b53a1157b180a373813382f47c9154af18a2d83270000000000000000000000000000000011236c10b9622f4e3d468d91ba9c6c072be74aea66f5bd77411193bf2358a03fd47d029dc7b50343ef72fe9bc08c7ea3000000000000000000000000000000000b923cf7f612e800c2c52b51203e12a72d6f106c0d047d1317711954cb33d44678f509da27f03dcfa1d4482a9cc2eceeabe2079ecb3618de3accdf291d9479bec32bca1f9fe87b00b64a12d735f5b9a5000000000000000000000000000000000883a868a58809bbe3ec9df32f8b963030d71a3ae97250ee9aa8446a8b1a4428324f22fddbe77b338ca58de26b1ad73f000000000000000000000000000000000a49fcca1f052e82fef8913b64268a33ef1d2ee213ce96e60a3a1842aa304c63cce711bba8f523302d9252e3def20e3fc541a44756ebda14aea95f1a1d05e7366dc0285305116b907fc89e777ce45f79000000000000000000000000000000000d1ed017ef4702bcd3bfbbcff36000af6a1d26ab363e68ea5629027e0b90352bf1d8e03c13a7955da6c15507cc1c9f47000000000000000000000000000000000e09830e54fe9eddd416479a1740f6f1b7693f2d153d322f27779b16bb6451d7657df85a55da75a4aee0a2e33b3a46e637d521d31de52681f1d9bbf64a12f9bc8fe0ac61aaef14d7e8d048ff09e6578b0000000000000000000000000000000001f902e2947de38842c207b9029743da51ad0dffb61615b22c73d88739d80c926c07f97507ca3bb830c66661b397dc1f000000000000000000000000000000000d8a1d29f87b3335287142baf613fceebe9d4765d29e46bbc9e459af5450256295538b49081d849f3253f07357451b6e4904a876d4ac1341e88fc4808508c89c19dd74aa8fb1dd7673cbc2d28e7d920e000000000000000000000000000000001846aeb64ead3a9b6da3b6f5de234fdc98442bbdc402af2d016c9dd25de8f9ca09269a3f01a812187ab7427b2bf31603000000000000000000000000000000001775e3fa3bd35f96faaaf9c3ce1d2391f89340f8d533e41a1d637fde7a2cd7ad997e50a6e9437468a1d5940e4004bc9068911b04d8155f90c7c5c0cb519ee6ff14c0ae27ece0374f30fa148235e8cb490000000000000000000000000000000008aff7ad8d3e83ecbf5c3fa2cc9a5328531b1dd6e30b2aa618aa087281202de8f4d356586d64082fb039db4c9ce6c3e40000000000000000000000000000000014196e8ec67e5f0093da2b1233331bf1e90a8fe1db52b2629c0d25e3c181d595c03bbab3b399c87236d2353f1ea6bfe9481e894ecd52a252cc76547513e2cf0a5cc6b20c3dc9c64c7f34f29a488258ef00000000000000000000000000000000018ad28e8d8c1d9dfd8f8cf4e60214446a988285005d92e38d46ba32f619e982cf96ab10b605b1e378d7b46b54282ff300000000000000000000000000000000029807f431a2101ac341241af021ee35c47e0ffa1975c982f75c10ebf3ab9081d294578288a5c308abb074b3e3c756c672780ab3c48c8a102469799ba2f70d2fd9d324cf558a8c8b49e2ecdb71ae1c9b0000000000000000000000000000000008cf05c3d3bbcc63ee761f7cab1494299a3e2274ebaebedcbae5b35ff33bca129d79f73ea77152f19cc67fc66ff774040000000000000000000000000000000009ab576dbf0e8cead9450eea0a506c83f12d09fd2267715a76eb46602756859146e96920174dde3a361636986a3d38e084ae1de8aaf498bd2d91bd828bc64e56482b225322b86529da703f47289c6567000000000000000000000000000000000006f62bad30339a1a912280ba5d982bdf0d3c04ad9051555eabc32eef501e80d996f183a990ebd17301ede13db85f6b000000000000000000000000000000000b0c4bb1a10f8a281b83384ee05be2d65d6dfcec36253b9101cec7f1193f8fe3d29333034de96dc62d18a97153ce1d153256548db55ee9de70ebf6fa347d81bc50494b937ab1c3079977234a34cbfcfd0000000000000000000000000000000010afb2bdbea9f6eb0c75ddb0a4404116498920557a5d416c6d855978e47aa90da70f29519ab244079762fbf965edcd070000000000000000000000000000000000b8b62a1e52eb3805056576810721cfcdb5b0d94759a11862cd7b0a88e3ddadc0efaeccfb89662860e187f8af2039f8575ae146524544307ee51e58a654d7324983a87e1b37d46cea1a4ec34114b44b", - "Expected": "000000000000000000000000000000001422eeff2bf06ecd67e0b310e7201773577a899fab8ee7c5b6ef5ce1021c9371e106c49a6b607cb3d58852f0e671000e0000000000000000000000000000000017ff4ceafb7c286f2036e6bf47a15e6695beacc7b988dc35f8521459203f69975d297160dc67fb88c4ed2fd7b61ccc0f", - "Name": "matter_g1_multiexp_46", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008fae47827bf8786df7e9f8cb38a8e01354ed4417a05332e45a94f93a5ec61f11d517f5554d5444001ef2991f2e7eed60000000000000000000000000000000005cd17cc813442f45e7c2fc542a6359b16db4de7749677b1575f12ed694514b3569b722ab257f7678a230ca3ccb6e0ed1129275f3ab3125db33d43b36c7de0ad60a6e9cb4457aa03275caea9635f0b070000000000000000000000000000000005aaeaf87735d9e9895e8703177faf8b11bea34aaa045852c57e9b86f6283332ab633f3e6947b84784733f6f73b289580000000000000000000000000000000004957220d5264c0ff61dbeeb0d0d51278386227a9386756a042df89fff5ff9a4d3e3e52293cc94ed729d00ed3e70b1a32dbcfd8680258eee451db60f3f42f02f388f87440d00badb0a725964042515c900000000000000000000000000000000049bec519df011ae5f19c85afb3301f41f71119ea6cd9eaffa9a00f9cb901681eec5f3f694ef9b4fe768a25a55afec560000000000000000000000000000000011414953ff3fec28aabaf3d62236d6a972da12c42102911a3ee8e88e188970a11487df719a739201b31fcda4e52d7c515a6f194abeb6b7c1c561aa820bba658f0277870e2a32f972f9d18ca361929b010000000000000000000000000000000003e5345484f59b269fa25b659e9a43573d4191c3c02f5f94534bfcd63d9abd57b2f3ab92f9fc746a852b185a6ae2c778000000000000000000000000000000000b7d7648096606b0c3fb93627e484eca017b95b27a8098e5dd332bb45171793570c69fdc16caf5b16e65f68c817de3bb579450b7aa155a3ab61e47e337ddbcd17b197de2dbb76008cfaa09d3fc806be4000000000000000000000000000000000c6afd550c55cc41cea88e670443d97c6419a295918dfde1d5490718f18ccaf8fa0cb68c42fa2cf583284cc70bfb0a11000000000000000000000000000000000f88ec67e9ba0e169ebf93fffed1fb14dd1aa3e1a2fa614a140c1a2147fcf051457cba68043efdb1b851bace84078fd64be94f96ec4a3d4e028644c63b2577a9ef849b403acc55e42432c3063a918d1600000000000000000000000000000000143a1884ecb4121e2c1c0cf2998b690d7f01aa3deec1a2ae5542647a3721f7be47c21ca071f92d74d9c3d9027b56d9c300000000000000000000000000000000113b01f060d10d95776b35c2b294216f768a323aececb308d3de24299dc12e55fac82c3134519456660a3465abeeb5950983e6618e9e4208cfbaf647592e42b2d30de9e74e4943fb2bb49109a66302aa000000000000000000000000000000000019a5620f3241d03d63ccaffdfabf7e99e784399929cfc3218d6b828d7ce137c9c6cf3ae830630fcef3cfdff705490e000000000000000000000000000000000114347768e5c8109c1bd47623eb51764d4b3f63f333677bfc28b143fcc1142f4d9094b2355408cd8c412a37a4579e0706615e300a924ab962e0b7fd0b044cae9516d96de603ee80695718c27d7fba0c00000000000000000000000000000000043c0f4b09396d4b14deb7c5027ef6cd2d426fa4f93d4ba9c3647031d557a759e3426c113fa3949cadb8b98a64bd69880000000000000000000000000000000017efb6ab8b2eaa0768bb740cc8a4e5ecbad81087cec2a307e5f53b5f431d19e3467dee84df6c6453ad4566ffa2380c9ad77d3e9e64e00b9356cceb62209ad48fc89e69e2214aad2edeba18122727363900000000000000000000000000000000140f0efabdc88a109da948494a9fca5ff790ccd6c629a088cac62e043e00e38c4281e49173ea0e423152c5b944d80ac10000000000000000000000000000000006d3d01cd44e56a4cd62d88a22c701b42c116082e92abb629e64040f57a240d71718927aedbd8ddef910198e1bb09c6841f75c89ec973f65b11786e186f4d42ee2e85c40f29745d9f428af08a39d5681000000000000000000000000000000000f20ace44f4b981adbb3035e450a656ce3d8464fbe4c45b9f7035c00aef11e389cccef660dddc025786d4f9216ef60c1000000000000000000000000000000000d5fb0a9e9ab03893a9ec61675af29e88bb30f3b61e05d7c5a3d823159bf8e641ad894ebedba4bd681df789e0c3d2547c70cfb76a04d1a9e0d937292e5553ef371e20d5d3dd33611edc0da178e2e4a16000000000000000000000000000000000dd38f99872751b4571253940ca588424190bae80434a3126a7ab5ad1383c55ad769e09179d148d151506e5cf5007b3f00000000000000000000000000000000032b2b9a8b13acb6589fea9e8b8d2535285bb32ab0e519cf8c63ea3e25d58cea7f9fb27481adcb9475abadd6f1384f4f8db878b7f5fe817599add432ecf262f19d80ac834bb0a0f983728f6e2c189c88000000000000000000000000000000000c696064b7c9653cce986e119686b2e01216faf8098d494bdf6d302c4d176b24b05bfbd70b9ea3ecc16312f899f887180000000000000000000000000000000001b5b8d333dbf1d84feaab7737d3af13d3995d3ea976d9ea1cf1d005090a809fa6c210a6363495c2b22902442fc5080b70751fe88ad289c91dfcd3c3c61ce1e33f4146f03fc0dc77cde9b32b51c75fc000000000000000000000000000000000082bc6c7ff7924b88b4a6cda58295d050bbe8087670bc6036b5bad53247b803306ea596ee0689d805e7b4de65a634eeb0000000000000000000000000000000010a79825c716dce1572e6e8886f1c698d730327f195871db7a9b6690e9ba1dc38e8d92b34ee32b33705edc021f42349184bf139cc0b6ac94697b7dc278063a74e478d47528da3f84f55fb0adfd851d09000000000000000000000000000000000cbd4ac75eb0928f366d3b99e05799bf3d9dbf187e557f211af5ae514101961ba750e81ede07cb5a14c49884a9b55b980000000000000000000000000000000004fdb80f44f89e6cb44b950735703653152466f30a410109a24b555c4e6907b2c1d4f54c9c0d2b7954002a74f1b65e23d19d9496e7ebca44354d5c6e1f6b8211eb06ca23a6444c307f92f5bc6dcc2dbe0000000000000000000000000000000019a41f73feae98fd65e365912f5bc6c86142380b2633feaba440a6c635ce2bcf7f871f1f033f93f9f8668360da3898090000000000000000000000000000000005bd1afda6a52adb550fd9bb59826bcf492cdaae8e9600e517d77832a8f3ae8777756421fe7640aae0bf07518ff695a66940e3509e1fb090fa787fdf633a74380cd5de722678826224641e46a6e920df000000000000000000000000000000000ce2a96c1ac3e2cd01ee4a20258436b62dfc2efb96a7148cf887c25d635aded48d18d38da7347abeaf72d73d613fafcd000000000000000000000000000000001773ef3bc5044059bdb5100430d4936f328cf876a48bd30784c8d3767a119bdbd5f1f97d78d52afadc42ebc85f912f0f7b27d21c1d6e06d9fba7b61fb87d364a7a6252c70b8ace2d3679ed87ce0fcf7e", - "Expected": "0000000000000000000000000000000013fcc5da42975bad80f3447a1ba05d9c6a51383921164ea3e93e983e24055f6398fe773b0e7a50d98568d49de36e295c00000000000000000000000000000000188455bd9ca4a0d3174cc8f0794d8c35356f697e62265d9e3d8e72bb2d1450caf5bf79dc5ba78a363a23d2ad58891165", - "Name": "matter_g1_multiexp_47", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000466047055d438bbdade1bbb00a7bca3ec0ce30b042e56afb9a25de1407d5937038e01e3c07595f46bd00cc8202d2200000000000000000000000000000000016bcc696716c21293b68d4f29d9cf675d447b726d579628417cc457043186d54f27c28b47d2e430041f9417ba323109dfacfcdf87c6ca0506b070abff83ce7812181c31729cc534497aa8dabe2433513000000000000000000000000000000000e8eb8fa4c0c2c86d0e571cd4708361e606c9fe789b60e099278d35d169424721bc789a6048774d739a5ceff56adc668000000000000000000000000000000000ddb7d2e6094f1940dc0f41509bd430163b220aeed1b8c0a2b90e37f791410a35d682b75223b32febc95500c7006f6626546fa692d9cd61895526282193c90148099e2afa54f7903a5431f932bd5fa06000000000000000000000000000000001080ce47aa1c38db9c71d1834c0b5d59676b0d938ba55a62daaf50911d23e286b3b813c7261bfc19e95f3bc8ea3b91fc000000000000000000000000000000000bebf539c3c03dd260d579aa853c28ae582b9c904ba2c56bb1239aebbfae10c05d9e33c8e1c2bf90553025d3279572fba9c1460c1cbb2a552e3452d5c5535868ee9c2952ec3fdb52dd826c16ae3d00bc000000000000000000000000000000000ba078b44f92e90fca4981c66e89c5490b34f92e4026d826c2076a995269e4d4fcab419a508b530793c465531a631ead0000000000000000000000000000000007c19bb972c27c00b5b1a8731ed7dc9af8270187cd26b1b9d65cbc96688fe2f0ae86ffe753a50b4500a46c01a75a93032c36204b6a005a64819b06804eb94c311d78977b557e7acfa82e147b4d6ec62f0000000000000000000000000000000009b70de2dbfe9af8ae771ad5bf0ff962c9f906a3637f992b08946c864b3d1dc996a2ff918ecb3c9648ef9188b15b624c00000000000000000000000000000000186a9f4c06ce9d5a969b959e4b17d4428393d02d0e7259fcbfab8898481bc97582ccd0e1d87d1735e28dde10a99b683e9160c5a553479a10996704c3eda8e57be88eaaf5d1efc8371e7e10d7d106e4810000000000000000000000000000000005b7dcbe86bb6e6b328325141c1da77f8af531bf1463bf3c8c94812784314fb13e457fa461c1c51aef0721c5d6ceb5e9000000000000000000000000000000000d9d1ac39a5ecd61670c1b0d061d93a198eca1d294d2e64c3f9e0a872e7c93212ce7835ae0a7fc2a42ab5c02192d70715e5a50e5dbabb7a56897935683f80a5b16dbef3c23461e241fbdfceea38e3ee2000000000000000000000000000000000741769993f2dcf5869b8153bbbff2e6e5d429fd2d862bdd590fc50a8f186bfb105f5d57f736b07d919bf0dff0cf4094000000000000000000000000000000001917c91f954f68c6406d6dc716dacf729a8c4a0de73e04cf0ce554eac40d750fd25b289127023af299c6f63372c01b7d4a95b293daa2761cc456b9667517f499c4d9eb9eb1d82237e7a7819b5d44f7a2000000000000000000000000000000000bb29ce10d6e571e62611364143e08a60eee5ccb13dcb77f17fde5829ae5fc025b309c98f892aec1fdedb7d1920e658c000000000000000000000000000000000ab6fe2dd5eb1b90f15a3632749c351ec871038f0550dc54cf1bf2575f80ecb8a3c0d3c1a333bdd803e22fb6bd3e64bc5e22ef32d111261dfcb5a2e8d23c8d920f013bd9602bbef45e6d4e0909abdef20000000000000000000000000000000004fe17772d4205d7b1d0cce0db3404119707893e20f6b27138918d2cb0e4de49cd5df1258103c1fac903c1a443cb62530000000000000000000000000000000014d8246911dc40ecea823f02c0e17e690a5f66848223218dd1735cadca1a0ae89d7afbdc727158257d2cb248323c55316e687c0ac8fab70de2416642afa1553bb38183d2914050602874491057f78786000000000000000000000000000000000784a1b282846404f71227064ff1a97766781900136d4b7ac73bab19cf8e03b449ddd35360fdb6dcdac80e335ac5cd1600000000000000000000000000000000074fc137d93decad1cbd4b753fe9ef3b8b3445c12e358450ff494a1fbd6e192ad7a4812358d85f6e3cefedea3aadaac6428f1a27ea15135f044643dc36a3f9c2b4446a3136bb11f696b0a430a7454b3f000000000000000000000000000000001661e6d386aa6516f08decbbac9c1c3411ae9cae62b05037dd626a2e2273eece64615c54a4d73e09814d497067f9e6e30000000000000000000000000000000007543030f8995237f65cec9b69b0356a29133d8be27b5f79aea580955042242c2bc1c6a01539b6b55ec9af96db60b394ae21ad8a6c9d75b51133e81ec34d66ca70a52529c5c3a2307b0e8d6f1c5e7d9700000000000000000000000000000000148597902b3ffe4ba8a5f9012e699a3cf189f58275557d98d132b72d3c34e5faa0953ec8cb10b0228a23803b70836e200000000000000000000000000000000008741bbe372a1e5a697e7059a9e80de8a012b0cc7b12c14bea098c16cfea154204d4e27753f1a8fae0e618223da14fdd88a23b118179ee2c34ad030993a2d2d70375311b95254c44254a32508abcb612000000000000000000000000000000000cfbbd4632e8998ba59721686310ec115b98ef470c3c4bbe427495d6d95d06ec6180e64b509c4c06e32862e17939a2cf00000000000000000000000000000000060042078794f4539a9b3e3127632c3c8b46322a669605d1774e995c5d82287d3d9be51690b4b5df6de8d55b20941dc630eac099ededf0087275d1af828bbf79ef7fb0e77179a068f2ebfe4c749a98c90000000000000000000000000000000007e67da2f320e1ef0d3afbd50634aff753a2e2104ddc03244a0c79eeb117ed1beb7316f7c5e116bbde47c53d47e725b3000000000000000000000000000000000b5399ef864331db729724870b431d8dcd8d3279cd00a59de2fdc15bbdff2035794025edafa21fce97836e93b41aae067e8dcbf708682225fe3f71b7a687da23de5ed188e40585be05533580121325770000000000000000000000000000000014bd7f0effe81cb626f92422ae7900bafa7f4c2d51d4ee6926eff68b60c7f41e667a57bb0506f7c36d3549cf154f6cf300000000000000000000000000000000050aecd688a63075feacfd29d1ab6430176dbc5ba6d406636a6650427a9e0b0d51df51d8dca27665b0b6c60e08d5b087532cd42a9b698a2c2d22b1a620a7ec60daa9d1eb8ac36894603be7bb9b5e37be0000000000000000000000000000000009252c5f7f7f3b36c5dd32991641c9f8244579960fd2d07a8641b82c5cb1768a36f4e5ad623319ef3f7d0c670fee58430000000000000000000000000000000018e432d33e506ce42bf3d873e36ed6ede0c9de44203cdd453cf91c42fc2ddaadaadd2e3870c5f5c171cfe76862ce44dc3ccd5e19892765e549a63238e664c732af781fddea558a117cb927bc4a1aceb5", - "Expected": "0000000000000000000000000000000008b38b298fe2dfaed042b35ce73c76ece7537fe5181ce647de756349a8dc48d3296e243fc7613abb10e254e2b0197d7a0000000000000000000000000000000018d59a69b976b1bacdffbea68d523da3fd0d2910db0a509760bce56bcba36a55fbfe11cdc14cad50e6951ffdabf97a64", - "Name": "matter_g1_multiexp_48", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005d929298c9361736ef5f7c83b6a851c344d72b7bb92a8201d629bf9bc1e66e4db6dc9df64ffb41a11eeeba10be52ec40000000000000000000000000000000007962e1b1b823b770b44eab51b3b84fd7e0e57a2a3f7eb1ad9c3ab02677376cee08b0a2977552a0f9399584b576f17f148da17551b2369b723bf932173a9167663f8389d2461b763d6a061df78d7ff1c0000000000000000000000000000000013283d9b3cb5ca4c3a39517adf466d2b7fc90f4895a24effca7ebaee4df8735c69993c7cf2483c3480cd2df4be04366f000000000000000000000000000000000fc94dee82225161feb78f2a7c951c41f43ff3c1109a824b56c01854688feb86e240c9fa48534809354e74ca8360cda4def52379c8b9e7c24d971c3456b85b51a63ab03761ec66c8dfac1018833e05940000000000000000000000000000000000fb727cd02c5f69af676f9cfa68cc4363cbfe5343e304ff5180ed1f57e6928fb808539276feeb1e492ae2455f65de0b00000000000000000000000000000000082d09bb2e1f1585933e1b9076711803e71c2236ff78e83f5dae6ad492c1d723120ef64eb25c8e91486d102c2297c9e5b2225be6985b9c8fa59a2890da56427612a4334937761e24a33d37f0f951a794000000000000000000000000000000000882f34897651c59970934848ba13e815710b4952dc0ee1abd0e04ed82ab399ccfb16ec966d010eab51e5fe514af91ae0000000000000000000000000000000017a32754dbdae7a2541eddba29cb8ca85a0c6d189f9bbbfa24d477e9f1ec2ab8f7dd2a5aa7a596d3a2af916ecfbdb2c2a64ce8ad619276bc7a00cb49faf6cc84b917ae6b37654363f5719a727a220291000000000000000000000000000000000db9ec112ddb4a9c6e371440d0c79bf043c5a3c6c6bd613dc031ce9b81b49a32b006a165ef29a8e05f019b76b3cf520c0000000000000000000000000000000002485dbc3c3e2aeafcf18dfecd842ec48b2e79d3bf7936917df759a9ca2e25fc3f137eb88a701f5fee1ccbb06d5cb08c0b891d638d7e76e0dcb230b1f9a7c3b35b35193c43a6c86f345f5a5bc9c708f500000000000000000000000000000000100d1fb78f53423c8cd60de5d39a004ee1c99b2fdf6847a62c73c33bb3d317ec06afd6424359481f8ff2d0730cfc9095000000000000000000000000000000000211cda7659f1e848c931ba1f65ca9c6021067ca01cdc8e87f5c742006f6dae39645553b69a4ae00ab6eca16afd0bda7571175eb91888222085fc2dfe0f4401ed6a1fc5df86c0c6b8e44fba6454305bf00000000000000000000000000000000004b07c2cb575e2499e333140e48446fdaa00368a74b87e607e285781b42eec39d1578d2e34701ed28488f160e9e50680000000000000000000000000000000001c2d66d28031aa91f6aacfdd80d222b4a0bc699a9b58b7f5d68bb9ed0a297ffbec3a6ba968f225732879f2f9907ca3954c9e7f7ca14c66b8431e25e6eddb4f20507d03bf124eb607957ca2f43a0c17b000000000000000000000000000000000bfa7f8b7783780a2b0f5b9f1b10da77cb5904618b8c8a1d062fc94aedb0fce090d8c4e65515c0d05a471f2261d0063c000000000000000000000000000000000f45747e4b0bffddaa13c7e03b6930ec474735b6a0e779d3722330828ca26a07bb731a5d4884ed3eecc710356a00a897000579e1ad83015c8f02a9db5c38d0220368a80b309ee45bb952cac824817b6b000000000000000000000000000000001245cf167d097de0753d29ce6018b7777b1befe43b5709e8217b9f380d958e3e9298347673dce432e57338b313e84950000000000000000000000000000000000d697bf8ec405e252588e3ef6d979bfa60ba174da03266c3a2efdac176c1ec1341d737b16d53bda6ddf8be6e1f433ff6909a45c8b78350e3ca21697e9f56d5fc8fc2a01817b78a7f5daeda487768ed1e000000000000000000000000000000000152d7f1e704619bbac7e594be6e105120b76d9bbc711ea40beb1063c2996fad70bc8f77a915411f3601e75af2f2059b000000000000000000000000000000001622a6467c13c534ff1fabaee8b29452d689e7f9e118e050cb91328b8078ef97fc82321b80d28d0c02f2b0a7b66f04a36d4e2277da617f0ad530b6209df6264e1288122b1b4d92da04fe334be17bd8320000000000000000000000000000000001c118fddc8df59e2d4ef9865d69cc044fcf870f296b009a2a471b1f74692f99e392b455b8b03d079b1f39b09e5fb720000000000000000000000000000000000032c05dc9eef5b55857956919f7a51b5f5225a45ca12d80208231304e66c77b24707a934cb9814108b44427e658d143dcba6bed6b8c42240c01df5fa0ea81dd96168c6d98ee9d5d4653edfa5172eb280000000000000000000000000000000012da4a2c89951f85757c59a2630bde25c30af955448c972d256f1a6a259793c7b2bdc3f8734f4e312897cb6a3550800d00000000000000000000000000000000199939ffbde7b14b5f23eef23d4a660bf3f561aed38205e68d091ddef9679df9230a59e8cb03212df2e99788fa2595bc23d168e01657e5c2da89a27e513bcbc6620b8c6082bd39880619bfe2b3a7317d0000000000000000000000000000000017a61df7581a341f21da2d1768fb41bb89847c88b2a0d7b61aa3275e376a46672dcb919eebf20b242ce83493c83335680000000000000000000000000000000013edc932b7755115f530d1d044c4afe71807a6b9810f555432910b54b0fef441b4618652fc4bc2ac5b789a75d2d276aa2a76fafc5e8e33852bbeb7ab8229305be84f5474427e0c6d2ed35c7bfe99faa1000000000000000000000000000000000c73683f328a0aa252c10bc3fae9e786ccf183f1b606a4596094fbe10630d4418a527509c93d23e62dba263d86f88951000000000000000000000000000000000260c9dd70a1ddb422491a20293c18e4749427cbe9841aaa3370533b6e5d6fcf882f8bd68b7161434bcd5060716fdb97e3c7e4e95167faed1391e269785918a207490c6d186bf2537c02e52e414d564e000000000000000000000000000000000bad0e395f46f714ac9d40865d588c06adb54b12439bb408a9d546b0a8ba5b3098c242cf5c17d1e40dcf7b384e81b444000000000000000000000000000000000e595304cd73c8c2a0bd1dff70e89edfab22be69bafa16877ecf669ab1e1160c9719952bb6103f31f2ff028cae0f0ea45d335e3d96a9b25be7f3916e92fffd75abeef5b91a1ec577ced52a96f6a9b10c0000000000000000000000000000000011f0037c9bc2bf953a3eb7d8a0a3c8d991e6eaa5f13dc1978a31f0eddb550432c70aad096cc0b904ee540e5d2d1ee4730000000000000000000000000000000004f8616cc7476fd0b95f7bbb7fbcda389aab60a88ffba3c819868f7ed6cf08e7c0c7da0958bcd957e0429b9a7fe120bafa563a70780837ffcf9a84456f0b4f6eda0d60cce6a8538ba10960eaf17362fc", - "Expected": "000000000000000000000000000000000e87aa419d686c55b1ed8ebf6e48d8f218d7198edcbc7db0dc3bb9581bb8dbf891dc383f27717536dc5fb7265ce1ffd8000000000000000000000000000000000a00646bc197307a7416aa9e35db9ce7eb81d762a065cf8d2e07f6470e424d7d59021be049b36eba2e44750a902f3124", - "Name": "matter_g1_multiexp_49", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005d5e69a8876b82b1de0b2d2a0d808c739b361d1cadf3ebc9c6096afbc19169f237774be6882caeffe47e86e3b8a33710000000000000000000000000000000017bf0fa8c247af0078d486e1961577d7977d0b4258ada3e158822d995188ee374d900c4d8b1ef4887fb03d8f6a4bf1776e2ee781da12b984e7a08730a60f50c41cdd7c7c8b3f1f30f721923ddc34fb79000000000000000000000000000000000e6ee0b0c7bb7c3f62284efda6bdbaf38bb5a72b4435b76928c5640fedbf9d4144358a20629403359fef5bcb99a795eb000000000000000000000000000000000e72324fb2decb0b0c7fa18061a41bddd6e2c55f901554de9be8ac7b2263631fee8bc77773318f6b13b2db7eb1ad0f3cd51e0b65be993ddd2892ab8f47eab78352b177be4b3fb68f47c65f5c59fa866000000000000000000000000000000000102df0d54108666e7aa611fec5c09b72d269c72e6fcee7787ece5f33153a3999ba5f22adfafa461aeda64e113b795dbc000000000000000000000000000000000b77ab3de0a2d91b8c24a47a27fbc5b2281cea40d87872010b94e895d9589880385f82ff53fad55af4f4e462df1c9ef6fed4dd284df98923bfc3c41496d6e64a10815a8c474275e0cdbc9ed26e92b0ae0000000000000000000000000000000018e8fa3c5bd83b51b1af197f0dee78e5c912c742df0cae1b59ac44fb2b903ad5ee1fe9750a034d18141f09a2b8298f850000000000000000000000000000000001526a80337eb938420cf2e825e5bcf3152e90e448ae3b40ee61929117d35f694eb5ce9133b2cc664c520fa9da8ed65a7c36ec97c1eafc8a20a772fb7887d75568047ea32458b9ce74ad9ca0581299490000000000000000000000000000000007f11b03e06ca74a35cf702f19fe29facac855d7f5adac59bbb8c058b1eff7d4748c886eb08600e0484aa976269e5d0c0000000000000000000000000000000010a5b0f723371690f6ccc5fb346874e58071167947d45e54f9d5edd035f2d68b4ef9e301f26ef671634121ae6145e44e41b2c0354d2f7d92b05043f193b718d78b457ae76e19069c8e1c2b77d7999d65000000000000000000000000000000000db2e2ef96ea61075e063629eb031235543e8f39f012fd006e143eb137524976c5a81eb26996a4ec3619a7fda051df6d0000000000000000000000000000000015d39e93da2b392dec64c58e73740376552e69caf87ce9162801466e75dd1e25b7d5762099112b21411e8d8bc18806fe5615370a76bb0a5f64d61b97bdb045b9669f6a0b7644b101d21a50483d8b04dc000000000000000000000000000000000e048ef3ee3bf3c41cc10b89b7d0f8b3f27c89fa0ab25542653155dfb7f8a7e8488a737bf2f6dab558910c9ae98aea33000000000000000000000000000000001357eb0945e2c4933b358970184a21b3369dd7a43a88841e94c3a388681f338770fdc3a32862c3a52eb251721b2979e9bcc38cfd3c6bdd32ed1d583f2bd14e175d61448c627f195559b751aab1ecf7cb000000000000000000000000000000000c6321bbc74b6b3a9f0c9470461c80b1713a5092871dc54dd022d3ade73845852315b3e85b53b74ce2b31d1780939d13000000000000000000000000000000000cdef7351c2923faedb211e79a44e0e02ebceb8103cec2ed7541a54bfafe3967791edbeb6d4b0da1ee37b9a5d77ac8f194c41471a2e4edf0f688c2f032036d41ef5f8a966871dd099dcdbced8b37e1c4000000000000000000000000000000000b925015af89d42f155eb1f5104db1128faa23101fb9bc1a9757266a2717d50e908c64c502a8d19bb1e8c01dad554e41000000000000000000000000000000000fc8c5cbacca685c24188e8f936637c7c8010f6126e9b9b49e7d38191af1246c2a3cf7ca45bce6f1e11c404919da61c3dd297b192f1c907914ef949fd27a5ea5659aab659b83239c4433f7a4e24529f20000000000000000000000000000000013fa1374d37396bc60386d07a441a7d21fb808e3b2ea0c39ca78a6dd70c473a8feb972e2981e50cab6288dd80c40c06a000000000000000000000000000000000f35c2a2897b35cd7417aac29ade18f86d56ba24848aed78a31513d5115bd964ac6711c5f71736490195bd97d2d5b507d30fdb174a3f5c06b78cbaee5b6e7a4c90551083d78c5164de6bb45ee5de23c1000000000000000000000000000000000799d71ab5145a8a4726cc5567d99b344971eb8bd6248e41aae02bacc358f967475f64169e1828a66905e4373cf5c9670000000000000000000000000000000017c680c55af98789584e073c3caf32373f58bea6ef7f839f1d5c39e512058360efe80a884ef5822bd5fee34869d028d5aafc42f7fe6854866cb954367fa65c8072bd1b60173a2d45077421d6e25f2bb3000000000000000000000000000000000b4be422e3d3e96f6a6821c55bd2a37ba57de1bb59c8f4855b1f4b6906259de6be1c1be40523d5370ccc426b89478a350000000000000000000000000000000019212f598150b576c17c32a8f374db52c19431d7a60b99379f570189b3fa15edc75b807adabbed712268087cd9b89a8a106da5f98d5e7cd9f4a1c8d6e50ea2236c2abdf1e08a0eca54555a59bcadbc6a0000000000000000000000000000000009df46395e64ce38bc79acee751484ce1bac53c5e5233d3545df2ec776440e3f5b04239d6de10bdb086aa3c462fc6e820000000000000000000000000000000009a5c816b2abdcca7a916b1eb015b3d1c01f766e01264b5139e5a34a82a874c1efa8ef097d23b9e9441916a2f5bb17b4c971deeba2f757970bcd4f5548a2767bd6c43e63f4c5fc4b157ef060a1f45aae000000000000000000000000000000000023537e0238470f4d513d56d4ef8e244e3d853b3b10a893928547675c6b2d409ef6bbfaa299a726eb472067c48f056c000000000000000000000000000000000b48f21e01e72bb6ec384a1e8ab35db6ca032e4476f37a3282214efe483b672c34989e6d5c99f69473eb19e472d984bea5262a021977dd79ab96606eb24a7c5ed650300dd68bc79f4b8378f58c6eed490000000000000000000000000000000013f1ad33a2016874de5265565049722929528a1c66b84c1876f4e4396f22fb2583d025c481d4d9aa2877e0062e842d7c0000000000000000000000000000000008a11522b3e6982a4b46ab6f1f6b07d33443780c914d4bcd50ef7ebcbec6ad944ab88b82640971e890a363dd92c71531083b3720c20044fa41712039b6e9e776197391ef393c0935a0e9990fbc1b7a460000000000000000000000000000000019dfc9ca394e105c6ad51b130aab8a043ee58f26a0d8efa5beee59eb1543c2c3d33abb5cf2b23b0882a409d32f845b1400000000000000000000000000000000143e219edb6fad7dbd64e6aa82fafd05ed92bb46e526468cc3bc0d60c89319d3fa2032b5a617691ca2f136c9f7904225d6f846581848f5dbb9e8d220b881d0327c4f3f5d4b79fb2c4dcbdb9bcf44b02d", - "Expected": "00000000000000000000000000000000027cfeeac9c1606a0942a95068faed1405a5cc9b5e631c25a0010ea14cae5b7a51b406fd0b8a9d9ea7be9a8c0f76c86c00000000000000000000000000000000106c07dd0d4e6f44fb1c3451942bf10060d16980f50b63005936e35b5add71e1352c48d1048e5d77cda79a09f86ff213", - "Name": "matter_g1_multiexp_50", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000065d5c6ad252823540ff4a4639cd42443a3cccd808d40d8bd71379ef939b47c3027ba5593167b4dae93b62b2bd498f910000000000000000000000000000000012623162c0f025b16dfc1c7e5fa02f8af7b7fb0f2d42d6fa0fb01af45621f00faa4ed6da6f33c609448bc027cd6a4fd367c44f7c8513472b51f96d526422bac628aad4c40c521cd7cf9e86eaf92838fd0000000000000000000000000000000008b3c274f83f49cada0a1bbf0f56f6fe0f8a0873cf13efa42ff65dd6fda913102c2034a31a1a92cd154210d27b0120450000000000000000000000000000000001521dda1b2c9b42d7dc9822c64bec62e71c629d61e796165d9a18f8ab44056914fe5c8809f21663bfc70e310ddf5d952d6f95d4b6216e4226f78e4fa5011c9becf98fe45a17dfd740fdd0ef36d8ba9400000000000000000000000000000000109f72caac5abd41a228bd82b6649fab639e4d22cb3a9a060ff7577de61f33d32217a73014f5cc2c2a76582a6b751ae200000000000000000000000000000000059d0e9e64b10cefe03daa146c00c5040381ce6ac63886b5fcf19a0555a22a395a0cbe8b49c510c9bb7a308813fb482958c25d36216b811ee42d0ba629ab7a0f9ce7edd7234620c28e37bb3df3f042e70000000000000000000000000000000001c5e132707520c525045a08626e014a84d8da23dc27b6320d5915e328c3bb0df3618cbd7ace26834920d4a8757368050000000000000000000000000000000008f5127405631bed295596639ec6091e97f16ce5a3062831102be951aec98c9ad34721489f65e731026029ae3eb13aaa50a5c6bb6b87fbe5ebfb0d182d425ee173973c6f2085c556b0fe60219b9f3c3200000000000000000000000000000000146124bfbb9a3d253670be419f80998382895ad6237138044c55764f0d6fc07da5b70cbe17af3ad0c4b0dbe33f869e490000000000000000000000000000000011cadf640e78298347115e6110d3ed63dcbd251c48d3e21cfba4bd6859b0310041e67d212b54e63be6d68d2e7fccd83b3b4bdeaf6643ed159f4a3e23c33ac486b33e1edbc5a097a47a6c2c753e5299d20000000000000000000000000000000012ab7e51b87512007e1baf2f3c3473cebb553bc2ea3d3146358688ea3167817a449ab9a7e0b090e00f47846da7f46340000000000000000000000000000000000702c1e0df68bee2666abb90bd593a17a6f9dad02a7d66102add9f3a525a1b4f1fefa3abe262852fd5ca357d2e1f02fd1d18596bc392dd0b71e1216bbb20a0e5e2559a46789c36a146cb78c5aa8e39210000000000000000000000000000000014635c8b9cacbe976733bcb1245eea410008082f240cc8d8246200abc0eeb6b7444f38da3ad93b1e029b06cbb12d42f7000000000000000000000000000000000d9aa00397e1799a82d73040122515b98be82052b784a4b385417f6e260e555c7c0c48a32ca1fb28224f75f887fa4bf86fb3669c0789ba6a5b00f14c14fe2edd15d37a742c9e36cae9ac010e632d75a40000000000000000000000000000000009a0efefb9daaaba4b2beabf6c381c27df7c32d4021a4d722118886405414837cde5c55933de23ff6769a0a42933bdd700000000000000000000000000000000101c9941d98dc8a146a75f2fa48a8650b25ae8f6d943323b1c10360cfdcbebe220494660f4d6f7921fea006942e122ac06c2988dd6b8e9aa116eea4e1f63dacf100019844d37d163c047567e8e118862000000000000000000000000000000000e5b403702a229f36c9b83bab9335cbb4e39fe8f5e9a5aa4bace70361dd05c87ae356a40720c4a8214765d028cd161ec0000000000000000000000000000000006e447c61bce31b4843530e504fa1324657eba731a272ddae680c202a7d017ffdf0ad0656dc0984a1fa297f5e32c2740fbf8322f706b1972f73fe4e22a3dad29c4ede09163561b2810cfc3eb2ffbc7ab00000000000000000000000000000000135fb22eca115779ad1295f8c7f149a6eb4fe046df664ddaee976a15e11a7a59db5e2c44b4a82c8ca1d17c0043f41ee0000000000000000000000000000000000fd9c1dceb20e85ef80bc9ee44e483cd0e2714882734a561ebbd0982d6d08e9c41484ee99790c20e83d051dad0a1b1e04a46618381ba6b991b2edfdeafa67aef1cfea066fbffdba24db25385963326bf00000000000000000000000000000000040f65cac81c01f04db3e331659d6bbaac8fa01581b1bbfa62891c1bc95a67182d254650019dfa3171e16ce37deef29a000000000000000000000000000000000afd5e22abd5d5cf78764262a91aadcb8b807b2aafecb2aa3d3ba5a187304208e212e5df46a4dc48d6150a733075bbaacd05fce871e4ff11e7a4e834061c65a0aab7bfa8a0128d460a493337c6e63ebf00000000000000000000000000000000051046cbe6862c5e37cd2f3c14dfc2825d5c32de69b40f29140fd31405615edf6c116d384bdf1552a33fb00c6c65cd97000000000000000000000000000000000a61a19fdfc994105f03aa3e1b907f5177409664b2e50243cf7e0e6e7e74c7bfce582929e5670a351b3d7b4034f101ffaba9e37ae0dbb733af820743d8e307fc02a3ce9b40032b16d0e9466903de9caa0000000000000000000000000000000013b76183fa2e01d10a3ecea5be65ffbcb04724ed30e4655e26a7ac94d5861f0f308b7d4577789d2f4892eb89202d84100000000000000000000000000000000012c3fbed77d9c37c47c838899aaea0fb6585eec54801c3ff2b486086e33040aca6baf6192c33af59f7db1d489ddf7d086ef151662cba4952416eaadebfe5e0fa0ca1d31380e1540c2d5e0181af9e317c00000000000000000000000000000000195c1bf8dc0114a472cb4daa31be44f22a162d22f2968b7909374fbc4d0883614d2911475cc3ba242844ef1c046885e70000000000000000000000000000000000d03e5bc3acdd01d174e1d2308e3f1ff3f103db8e2804210da44c47229bd983ac127295558dc5560c0fb2ea34def196f0a3851bd52ca52919dfd21efa6efc56f6dd5060ad969360b1a731e8f38f0f5d0000000000000000000000000000000001261cc24d5e69fe8a7747fce45086499ad54f7c138fe76fa665517c58e475683c5a219df303810745dc554fa3c096f300000000000000000000000000000000122fc4c068c079827635d29e944366516c1d7cdb1ff62968d847f4882da8a4919b59e57690f6e0f6aaf083af0a04b2ca32b41960417047a2258b6e9e228f3cc1130b296cafbb75f58731a81fcfe8c83a00000000000000000000000000000000050b5493fdadda15e15b2ad6104274da831753b1cd247f1dacffb6f896b9db7190bfae2ca202907d36b979b668540ea400000000000000000000000000000000141245d4556c7f1032d0ccd606e3a2d3338ad753fd7d0a3c1b8ab38e94d8618e85c22a269428537abe003f8de89f2c1171a6f7f091a6a21dbfffcec2eecaa22d05252b60bf91b56811a833dde3fcfde6", - "Expected": "0000000000000000000000000000000008bfa9c347d937e2ff2d77ce7127b1af4e7adad5f1aa6d71c6226b64c62c955fb0dd0e36a5e87472d6979b656c8a740e00000000000000000000000000000000032de435000391e441ecb7e777741fc72f4676f64cfaca6fadf030e12ea6374a7fa988c443a38595def0b434b185c75a", - "Name": "matter_g1_multiexp_51", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d0296528c7b2516ea73cf14c5625a4296c311fc2e09722f3b381279da52ba9482e43d3fdc1694b96c3f62b7d98d6951000000000000000000000000000000000da2aaba37d0955c5fcf31152926f2fb345deba744241bf66511da5f4ad9fab8a1cffa270c4e838c39b34bc28fbc08b02e56b63fc6ba87cf021c2f92baec248756ddae0a4f070df840db281283a4c9b200000000000000000000000000000000175c976baf0205ee7326c84c49cbd2d7c3db91d1ec92d87cca896ea09a7cfe4ef8ca45873f86e28afc4b525356a68cba000000000000000000000000000000000c442d3edb8b614407e0d138417f8a6c028b29dc1beb5825c928dff3a08820c5a8ed5de643068bf4d239bbcc2dcd0b7612a50af55f47fdaf176d4885e4910c54428c8ef433ea0cb1d009ea7778355947000000000000000000000000000000000f45bf893109177d3c336915c5e28c338ea28468cbe215ee6fc6f6e3c9aa9e0b7120586e42c5c087b55fb5789a4a9eb2000000000000000000000000000000000b6ad0cffaf555f081ec7a6fb354d6b20950fb6fee059f2f571430f86a7cb9996b5f655bc7cddd14f3f8ed37c7fd278889a012158b3c18e19471fca6d5aba5fd004a337d49ddef5db177da187c8cf1c8000000000000000000000000000000001944f2fa08357307df2271f4bb57cd07a998df56425f7b8563902aaa0330070ce260b6d86fc38a5c6a284788d9cc0ed700000000000000000000000000000000165d8134931f7a4cbeb5114a10e44172aa6a0c250989dbd88282f92fc238a8e1e21221b04b239cfc597e2b74700c626d27dd109f6df1d9851dae28bcb9e552c6b1e1b2dfb331aa955d3d0b6c4862253d000000000000000000000000000000000c7a02cbcc758fa7b1ea5fd30b3b88cdda7c8661b3712ba5bf924b441e056fb9bea804bbfa1850c21cad891ee253ff7100000000000000000000000000000000012202a151fcb86875b4dd2dbeafe5ca484b63408ba01440007164fa2a2b7ebbe9d7f738f382a010508408d26a57c566ca96785c1ab66cc5c8e434f59cc1ddf76bd78b6fe660f7cf74cfb79d7f2c7f840000000000000000000000000000000017d02a3ec6d45e9b49ddc8d1bdee168f71c32ba26d4de8c1bdb328cb4c46286328387aac8785eb5a7c71d0ed59810f4e000000000000000000000000000000000d23ee9c9fc914404ff46d0f6ee86984862e97a777ab516c2b84f5b5a7c1807d64e93fe57db53c7b95257fe46a7a15495aabd1fba36142bd768339e091b15b7f5b4ea609b57947a7187c498bd9833c2900000000000000000000000000000000040ca6ea6cae1be17996106cacbc5d9f1962203fd25917dec2c053816f3200b9853b218a07db690d8261ae3cc85679bc00000000000000000000000000000000097e8f4b5a24b010382888ebd7ab7cb71f471bca00c1499486cfbf1bc5ba6af169ac27e1ed8cf31b5d9600361ad13663fbe608fefa5472c7d1611abfa402d2eddb1e54542f45d4012db8ac6d1e5016100000000000000000000000000000000016f95e3e24941c2745c009437c1b2f5ebf690c9c76e269f877bbf73ddc6b15c6132d424c26a3c7bdd9c5302dcbab171f000000000000000000000000000000000cfca2fd001c0da52f231a60288b22a134c7e16aac8745129c351dd96fa37b72a9ef3d93d5e8e45cb5fab9e73ff188e128d57066cce439d8d0385f647ed5e9b29e8fd0528c1ed8455f37dcd81f4b6224000000000000000000000000000000000e2bdbc906c10b04c5fc1e867af43bea7ca43cdbc43cc3574a47b2b0670716a92fd863d4f423f3392ec8849e74850eb9000000000000000000000000000000000ae76847a2524be3a04bf85e096a1ca4cd3674459698fe326db2d71799c8906022e15bcadfbc9ddcd43dbee3443842a81208d8d328014a6b2c8b2b9edc70589cdd63d38f4e70abb41cff1b7693bf9a2900000000000000000000000000000000035d66b8b8b64bb0d3d1ba6bc1bd34c326ce6abac3a97188f82be38d1756f14a63bfedd531d5e19813b668012f77763300000000000000000000000000000000060851234e4cfa8c168db199bea8cbc337e685b565a6faf67e07c463632a6a163a2d22acf9fc6bc6a1f7ead5d288fcccd3a2044ed4f938c17684413625bdd281f685abea2e375bece77c03d697c82cc20000000000000000000000000000000010e398f6c9ded2fef3cd95cbef681c5335a1e9d08c05dc05b6391f65941cb3a79df9e1cc4ebd3fce82d36cc628b7f65c0000000000000000000000000000000016dede30728c57650952e9425b6da1ec8ee5702e783c69936eaf6857f199bd9ffae569db3cbd61483d48188633fef7ed7fd81e27a577b5e79929614c069d6d52146a6183822d25cf1ef84d8afcc1f6b40000000000000000000000000000000005eb3a914a78b4bb3041a32397bdba3edf6943ed474ac8efbf9c84a6cdae5d65a8f55ce4ad141b846f1bcb5df1206417000000000000000000000000000000000c20828a5d8abc2c8f72809348e770649bdf4bc0991f45979501f31d9f31e028731a8ccf07f0cc51bf8b59632897c540c5d47ce35d4ede84a83c9860322f582ec00c872b4b035d5d340981fc29884f1300000000000000000000000000000000122cf863d9ddfdc627a0993dc7ca5810e84ab254ff8147a220d436043c0a695b0cceaa374842c335c14b6ebb273472d800000000000000000000000000000000150fc0b14e30ee797e3b9202533c681ca9e6b1b43347cfa11da59ceab439c9e5cbc038a50917cd9167a0fd591d8175e484ae256d47de2d49b1e755cb0e972f3b614f3e7ba779c65ce175ca3811021a7f0000000000000000000000000000000002ec5aa74588f6a7fd8076b9a846ff3542543dc7a3c798c423326eb06ef92edb8c35583785cfff21f903f08f692d6293000000000000000000000000000000000df140c1539cd3d94b5f9d0aafc38294d1738c5b3c1880d8864e83909b152de0a469742cd31e5e8f5838ad793ea32649a09d0136d4dbb3abfabcac55db48b1ce302067f413283fc1a21744f1c16ef7b5000000000000000000000000000000000a440f227be209dd1bb816a4dd8c1abbdbd03d97c243ac6e48c4efcabef4d7a4b5bf65ea7bea6f4a1da985bbb9fac626000000000000000000000000000000001431a99e1243e57054d2b43217286b35bbf37afff72b163ad40dd4ca92439f4b513284551b0fb137f968f9f59a540cac650a6fba1a5eace6b455ee780ff266c324f49801832640856a80098f0eed0b7b000000000000000000000000000000000b99ae325f1fcf4f3c83f251183871d1b6048a43d15da80650e0b5c1b671031cc9af63a478b5939210356c4c2dcc7aa1000000000000000000000000000000001382d6f0550aad61dccb47a66d004ab3801445d55dd320a6ccf03577b1c1c915022a955e7f3fccbbdd20e4175bd0ae38282cb1f8f6d6dd81e7c49176503a76837a96d7f2b084d29d11dd9c6548cf0a57", - "Expected": "000000000000000000000000000000000c62c70aac1893222d967bde4fdffc565cc65fe29387825224b8571367ae8fa857b63c32033faa564f6e12d409b5cc060000000000000000000000000000000015cb57fcbc876f5aeca01d90d55ea777aa1421547e8aff0de69fe5527c9a575f9cecd1235a37648c7509d9bebb4e6800", - "Name": "matter_g1_multiexp_52", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000123fa54665de1ad1eb74d400f93b70f8502bd9386a164ef9ac7549b3693525e3fd077b2b2d8b15ab0c6cd5da30f8317800000000000000000000000000000000185921a0fb38ec1eb6804002b3bcbd4d4bc759885e9c1fafe275d51840434382df783518ce768ae40e736ad2ca8fc8803d7f8fbaa4225f3008649eebf42315785ccda2b9ce922170e606876881825cb9000000000000000000000000000000000eb30c8da4c7eb16d797f24b5d8e210dfaa68684939cad598518298c84214ad769f6a2634fc290c2c267c8f3a2872f020000000000000000000000000000000006452f211931b8d7ccd8777b2407e5cb073097ae9b309f1e95633f39d1a5a7f5843a6e87473b4b9c1bbfc17971108e3de71e6cb3d4e19f4a70a4465df6eec6326f558ee1cb99aa540ad2a73c363a133900000000000000000000000000000000162c0325ae75a81c92a8885f14e2f7b9b8bfb249fb9a352d0007cd8bdfce2d8024f1e4674614cd0afbded99472d547000000000000000000000000000000000010d8497a5f31cda80af22bfa6695b4e2c8fb5557ee74581a33fbd0cf8cb2e0b4ca3ecc42487cf957ea81a5388d9871fcbdb2b3c3b8e91540dc2724537526fd8c0d4b85d2cc20323d71fa5a4f61b3f12a0000000000000000000000000000000013270ce7a1b4abe3026d245df9b93061a435ed00d0464d8de14675247c7f2f1cbb6e21c8282e71d2fa28eca1e3f5863c000000000000000000000000000000000b87656d14cfe98c2d3f34b03de0b9f08207b00aaf6c5a4a6b9b4989744581772a2d6d1923c3d07b784853f7b2d789b9ef0c8574167a3bd3b794f057ed01865ea69c38023dbddb0afdc55dd9523ebab700000000000000000000000000000000067296630285ec7da7cfdeedd387d52d905ec39e183b87479c8f0fba967e840f8394cb518dba4f4b7d4e2cdc00ca62c3000000000000000000000000000000000ed41fe0f04e0c63f3fd7ec7560d24974fd06a1566e8f129f580251227cb9b7e10ed6e60c2e7449721d5332709f465973ccc75501428d3be8bb469ed0f2df7dec10e1d205e11a907cc30c4a76eee3cc00000000000000000000000000000000006f7bbdc3c8fe2f7da9533a3f8a3c48c630d6cf567c75dcf89e13852f7a8691e2625ca24517ad3b59ed3513f7d3b4fb20000000000000000000000000000000000a2e63715ec49b06a78e014b98effbb03f99ce61b464c66108cf18ea49def3e1f035a8b88f37b453b31357d2a2a48f4e5e403f555fbc800f1342275f18a73dbb679bd31873ee87617090912a52d6a55000000000000000000000000000000000a9e51eaf24d2d0fcb7f1dc7ad985ecd4da3ecd19fb75591467edb0f7fc7bcef67c1c272f39c31ef36bbc73d7ea6034d000000000000000000000000000000000332dedca239f4d1272db77dc388e07005d90f44311aa889b42e931d08c2669c3f4aeecd9052d3f2585b2a4e41c8abbf97ea57a38598204c15bf65e7270a175460510848540ca4004286f3ca09eb5926000000000000000000000000000000000c6b189ddc86e2d6722ebabc445190cf94bb4c54135aae2601c957e062d351d0c9fff19cbeb45cfc5dd05eb3543a660000000000000000000000000000000000133794839bae14fa041004f173506fff511526313da5a8f4e32c895751a22ecf01cfba564006037326187b899aed596ac54dd8cbe68d5151e4428d35ec2d5b5cc7f5e455207c0788a695c2d7fff67352000000000000000000000000000000000a15343698b916965009f1894c8b74a790d59bc39b7f0de01095275ec002c97c66e7a6a970b4b9091cdc54abdff1cdb800000000000000000000000000000000045f084e0a7c0014e58c9988e72e1861bdb4f962ff9869d444d5ba4094178d52f9c2aa511feb6e8717098cc1f09d49eb47ee5651c127d7c8ef65ec68fcd97d1dc228bffb5bf1278aed3eef8115a5ae72000000000000000000000000000000001656928ad3ee67675951e2d2ddd6a7d9c629a3148face6d1269f79c3d0699f95350e83a6ec20aa3be78a2794c3f250160000000000000000000000000000000001b8c9e4c818774dbd2416193e795a429a22881abc94ebd9a8b42bc4d7069a9778e4bdf7270180784d914bc6be99b41c14ab6a1d0d3f87e7c9df0c14b6fd2f9d0cd755d5fce5f40bdc8174790901549b0000000000000000000000000000000013d779138ab03fafee1e4bfa2a290c4f20d2b57854a5133cf5ad7817bd32bbf2945a02b4fd5c8489e704e60ee937f962000000000000000000000000000000000aa058528a4f9bb583295ace843feac4dbce24a22ea6bf412be019f590c621bdfc7562e8dd49afcc337cab474d9abd0129b12cff5a72f27e15032844fae50e3cabbe31a69568bc4b5cfa884f62e7e2040000000000000000000000000000000014f30fdaf2f81f9d941af33d53e2d9e3162f62f47c60164e9b5ea3a5cf3a681a80b66ebfea391331c231abc4341cb94b000000000000000000000000000000001854addff23c2f53a21a6d39c72f91ef0e8d9a6d6468f319200466f78854c41be3e914bf7f966f00e185b44108af30f092c1b10d980826351c3d193a0f54a7dd78a3995efb02fe5b4525fca8791b1c4f00000000000000000000000000000000188a1934a28c7571ee94f1aa5c161be611939e52156bff158170d5e12a6480e3b9d1528082cc2e537ae1734b1847f8f8000000000000000000000000000000001728b57eca86cc8fcd9dfc65a8f5f055d51d300d8781839d744a1b81a0233221cd353f642b3507703880eb0a33afa05c8f715f35fc967837facb515ebff3df502223c29e7089fe6d2e9120bd3ecfcd120000000000000000000000000000000006c99e6c8b554d748a3526da79e8a867efde15ec50ff62e43f691748996dc087dbc538cf65820ca065f3adb5884e2f0c000000000000000000000000000000000c577c42243b95b4a613c485026306513685cce294333b72388d6968019d04214ed4bbbd5b64bce78fc380115a4b067ca9e49fcb12c0b1e9bcdbda52e9852ee0e98fa0d43f7476b3d65ef5370c9460a3000000000000000000000000000000000d7b48e69a9807c6fc867f59c894d5bbfeeeacff500a3ad4528ed4848f5ce501baf8959f822c259b712236529dff0b0a000000000000000000000000000000000e7d7932084a0416a4bafe237c923d1390dc6662e7842829ab6747024378f284af07ccde9cf80042bec56e7429ab3acd80b0d6316c5d62d41fb0399256c5c46ebe2a12eaad835d2c7177bb7325e21d3b000000000000000000000000000000000a1f74acb627d1814ef90b2d756bf76383075134c1b34dc126094238eadebd780c1ab8a3d1f4d9566dbef1c706d931920000000000000000000000000000000009bf8c2fc78b1f7af25941bf429059e9f86b34a36ff865b33e918c8435a766d897df83005c54871ad0d3e82308e368501b96434f34fa3e00ee0cfe548a2d2ca29a848cf1c52f940685caa9a227e32a61", - "Expected": "000000000000000000000000000000000a912d7d352bdd182a8b431672b496ecbf18276da61d6a8eb066c41783b7cf3df287796b34b165db186e815c8847b3ea0000000000000000000000000000000002881de241ed8109f544f3a6262eac1aae69de7a7e9953812eede9e63a970225646f5c441b7de80106d53cb6dbb43f10", - "Name": "matter_g1_multiexp_53", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018896a4d84c1ec1a20e1b0e33f159de4d82b55b6d27d863ec7cbefc2d9c180beed2285aadb34d29ceea681689dab06ce0000000000000000000000000000000013398b5f6f2c0c9095af94796572d603de02d41c599e09d3e254b326fa1575e0c6a2b7263a196c5150440daffb0d60e810e0acc22c43080ab9cea11a60866feedd57664bbe6c3f0366beff177f6631850000000000000000000000000000000015b31d591dedde69dcfe9c23df11782c090c443e505d2edfa217121a1d51b6883d782917b2a082a41ce698ecd95ba95b00000000000000000000000000000000164b18eaf53165842e50112c4a8490b8246376b58bb6c188fc929160f49cb0b68ad2f13dbeac8466fca75e6f72a398b8cab0c230c354cbf1a3c13c23a36ae5f2d5d084d7aaeb427c580cb6b9bfd9df600000000000000000000000000000000012876e247618c76af5221a50780803ab64970fea8bdeefcdc1ef4c9a160718fbaed9dc6691502433295d54d4030ee157000000000000000000000000000000000cfd8dbbeecfd176cce05ca1663930be8cf3b300a287ed053e36f64618a14850a3e813582da1f54ac7e96ff61ae57c86290608899cce4b3d25f57519cc881eb748e9ee7e27f7b21d69f5d8ab3650c3e800000000000000000000000000000000085c5db53c4abe188f44f084bf17084d3ae409b753089636d3c528162c2816b9b9ef3c0c8c05e88189407d7ca95d40f9000000000000000000000000000000000015d9ab325a8ae365f173821829aa395db9211015903c08491375f82853d9084d8aa2e35c2634a296ba14b50e34c1feb71debbd9f3be5d6e65e837bd78605d5653fe63025c320cf49c035ae66d8ff570000000000000000000000000000000014bc3ba096662dc560e88ea6b7b4363c427d038fe85a49ab8d9d63524940f26106447ad6e3d7495ca562c98b64d445880000000000000000000000000000000018bf745fde497914d81d1e3ab96630f24f6ed27ebf1208f7a46ad9fb893a3f183982c0acfc001984de34f617841524f9250f62ee2c2972e751b36d95a578efd2fa5e0a2c1e29475a3cee48a28080cb0b0000000000000000000000000000000019b15da994067a017c3040830b5e5f7eb77ce0cf0674e96b209b80c54f1307cb04799624647fd1fb990c61092682ef730000000000000000000000000000000002248d31211c2a37df59a0a4ddb0cc7880dea316519ab7baf1c614b26e2673f03b00e387fd537aee442cfc94f734aad8ad08c3d2c36085212542427c1760c72f22838be5286402ef87403f816f4fec950000000000000000000000000000000003a499813ed2a3878ffc11d27dba4d55837d1114049a72444b6db0c8a7d23a53af765d66b5017695efa39bcf7d1c97ba00000000000000000000000000000000011fb1a989afe2b093fa2ae3c0405483bb1a52c21226acbdf2a52e2e5fd5f7404776551c2deee87f431ff39dfb031d716ffa16b6fc4cc9509a2b8d8434fa0f4f38b4cb4eb1bf7f545f9f43b9190cad890000000000000000000000000000000014540330ba54d2f16a9bdec93a0b7ccd58ecb44361c67f209d36d2a42b5d5a4f9b9dce0701ad0677d6d6ca83a256e8460000000000000000000000000000000001a64d5b128c07848ec579df1d26755e5d2f70cf123013ac249a4d188b0eb56cd74cb12f7de2db69b3a0f9f4ece2c4201271d29abc5f972809461a1afa5eb186dff5e28f20311a1d8416f8d54fc4b2d90000000000000000000000000000000017783e019baea183ee5d9e1f671a23108e403a22580f5c203dd6ff72dc0adaf802d031a236e72463e0fa2c5f7c6e68b300000000000000000000000000000000132d32bae3b92b7212dd7db16c87360274a409f46199f66e572bdb21c4af24af62758978e6d01af60f5fb87481d9f4f23ce55b3b32ad29dca1a0c99771fc8f7179851995d5eac804458edede9b8dbcd00000000000000000000000000000000000a625f252a8185bea7f1b73d1c7c9b1fc7f4ea5cdd017afbe9e56e7c12d58d893ddc387b7c2870f4a975b613bef0129000000000000000000000000000000000aff6dcf60f78bc908fc4c2466270065766792a05d8629fc7f5d2b61ce4882644947fcc3600d63bd5f49fea5574616bcc6fa7aeb016b3e3f599846af83f426b9ab85b6857f901c49554d03d27a390f5c0000000000000000000000000000000008ee6e9521f32feaa034b533c0b7c749f60d84adb53d6943d3974fb4b92ce3cb3f67fbf52fff27802c893cb97e587b930000000000000000000000000000000012000b50d1c9628f822c41d56b29e21f3f496f00bcf05edb234ffda56767bb33dfae736aa9fb9a84ccb6a0e21131c5887275a8d16c02389795d54ebdcb70a39fa885320d00cd4e5aa15967916e46c6150000000000000000000000000000000014d9d3051d073d24701f01631408b7dd1d37f0855baa64a13c493c15f7acf36da116595fb3d69dc386cc611c998f9ea9000000000000000000000000000000000b33438dc1f84da6ae50b1aa76fc52f5ba0e547fb15e8f655db9e0e26d6aed15c5cc4e48412d089d1ca6fb7a550f8eecdbec9767ed2dbde21fd8f315ed6292b5b0b1bb6daf2b62665c34daed00a679cb0000000000000000000000000000000008935c4cfe2a1620a0c895feecd91ea7fdcca3bb06fa514bafee38ea5819b7372e75a106904b9c9e8af268c9f5e5a45700000000000000000000000000000000114e9944fbfc05ee1ed75603bb9b79301a1f90d3b5209ea14989fdd16f5deeb01e3474da2b4692a3e0b9625d3bf9b4b2ff634fd89223733f407c242e52f034691036c7ca69f30e6cd444c561de9ebdaf00000000000000000000000000000000105268fff23696890182b5ec307b38ee1cf28336e1c3fa28b9b697998567035323ccc91e974f63c55c928f64fabc2ca0000000000000000000000000000000000ac2f8c91fa31e2d950385509b86d512c80f0d1c73d223f71b26040d58822e4269a85e82ae390441853f8169177943aa461d349e9711fa701b92b62dd3e3569d1203b6a35ac8600367a4df9a9484bdb0000000000000000000000000000000000d5a5c94375029e5511a6c6ca40108377db43e4e0b03cceaf9fb77fac7906f71019c1a85591719bfa5d9349f1089ba0d00000000000000000000000000000000163bdfc6d40c96bd24a3b83f89037ec9e4191b533e36dc699a32c854291b0823b3f071464654eed00f08a691aa68636bcc110fd7a6ae46ef78c0e26183e707eb5e0a2944e3afc09e435d56e91584b93d0000000000000000000000000000000011654611997b772db3111d2d4edf92b83689451b1e7594a7a4bd40d85820df6a1ab090f6a1959acb322323eef27fbd86000000000000000000000000000000000b905fec9e379cfba09fd502197305ae39b48facdb01f52afbcdf159c5674234ac9723643830ab8e2639e7a0d6bd979267de5b9bee26b26b28f81d96e880a3f07dd04eb56c15314f1a789436e01adcda", - "Expected": "0000000000000000000000000000000004de1528d78645a4055ea348ef2618b85f8214c1dbd21ee08ad164abc02cbb2927202302dcd142c65e12934dec409e18000000000000000000000000000000000de34a6fbb73c7152f1636e5c02c75dbbc5910c763bb790d78bb56e48cbc6380bcc2ca14cc11ae139fe009135c81b243", - "Name": "matter_g1_multiexp_54", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000184094ad33f83f5b229643d9808f5b3b7f3e50306788f8485472405c79e57e489549c0901c3d1694b5f61f74d87afe9600000000000000000000000000000000007ec616b56868e00563d8e8bdd36de3b5d1e314be0d81c4ee97fabab1641c89cc21e70153a4d3d4e788b04ffaf07bad624ab43047c02e30ba2ec671511d06f869bf736a9866192c5f2eea6c065acea40000000000000000000000000000000017e7c08cfedb74bf88c1a80762be0e0754a86e5482c27b41240f4ffa9d014e9e8560e172519031eecccd897b869c365f00000000000000000000000000000000115ff96d404829597f16b9b97f8ff71a8eaca1a76bbcb72d53803d35335d8a8c1cea58559136f9b254c28262aa907414edfdf850c0d3e3903404fe3e0f523cd230cabc45946c4fcb6d0e5e05e388c235000000000000000000000000000000000b5450038d49c91e4e5a40a31f1f75923c7e1599695b829d9975ba7d845ab20ed5a62a7238d6a6479b2c6f9249068aed0000000000000000000000000000000013066cb8ef171bdfa11e70ddf83eb2447c4169fe38e008be5787c38b1b8a946fc474e07795765ca17fd5bcf64150fb04feb34852ce0f3b5730962023418ad6cb860716dcb526dc53e8ab6a74a6a3910b000000000000000000000000000000000f19fc0ba8a0ec5a2cdb9844002601f580e0eb9b2265c86f6efc4b633079d43461d6bf241ccbf422eb9d7c00ecca88570000000000000000000000000000000012e744ae937ff9e8e4f611fbd1c9896bd31bb1ca36b948d9be89960fee6c0cbab3264aacb916ae3596f110cc1b26bfedcf25e64093bd92a8fb394511215a3fa674db86d7329ac5ea70ec77d24d4ac58e0000000000000000000000000000000006ca09ce8c07e89e9e51e208b5d32b5ab61f0de60484d9185a26911b56a728a7473b70313fd18c893ed3453719b074450000000000000000000000000000000003d372a5477fe7fd84a58f6f2eda8f5c61aa0c357c7fc1708f7616b8cdff249e7d2910d753c2e531a278f5853fc065970b40db4f9e5c27a3208899f4f536880b97f4c69e7d889c0726d87c3fa27e097500000000000000000000000000000000152ea2fd1934c32c3c8e27a6ffb278741b899c5e296549380d019307875629d57ae44580a944babeecef73753e30c92600000000000000000000000000000000161a77844c90a6e83ed2c40c937de21fbd714a5cde60015a71bd4c960e894d3cb54a8d1e4bb4cb0a1985d4469814a991730bc7f68d8d371d0bc51d95f8a5899249b8db5cba0d21fd88ba6f86d8691659000000000000000000000000000000000a959b12e3af03cd4629f5f6f412b7084eec6aa55369e2dd2f355c93ea984ea6f2a7a01e6a10146849503d230fb08f7300000000000000000000000000000000161340908a38e4ff5373df643e3cfdc459d872b5cfd41ab34fd3297b10c37dbf3088fc23fb71f2a1751a121bcf51ee36ef06360717cfcab15be966cba2836b97deeedd20a52f88c73e2a583b64c8e5f00000000000000000000000000000000013e31a4f0cc29a5ff7f4df39db999c95eac789656bc9c6b91d0209b8a5ec2dbab698048fefb75a3dfa48066ed5743215000000000000000000000000000000001851e72741707cf96f887d13e01981f1e3db5834185eedaafdea99eeb11dcd3e90a9985f40886b60ee2a779b141bb62082b7d8b8b9345bf13d0e113b662141f5ebfc5888a5ef8ea06f7d5d137324ebef000000000000000000000000000000001501f155cf6f053631ebac7d2c57cbb101a750f98b6e11df79dbb24ec8804535b1b24942022aa64713fc60adb2017bff0000000000000000000000000000000012a08f9b1ab90531a26221b70751efa598b4046a5482c01d72f506ffbb3430d35016848755674d01e16bb78a44f8b6882396fe15751bca2c4a651445cef236a865269849908df53551802dd378b892cc0000000000000000000000000000000008fe1ea18cd8e1d2c620356430ca43782f844a2efa6a285a7c9c086e972b12735faf6237447759bd93d98b6dc7c42344000000000000000000000000000000001731f36e811c640f44adce6bb68fd71065f440eeada278ebcabfb9bf0291e551ed302c592aa4ba7e3a502cf58e3eede69a5897c9596223ca4d6628ca1f793a000aa21a739a37faa28637692b754148f80000000000000000000000000000000018e3a4176b543f2152bd7f72ca358af6226f77b5e10f3f9006c8bbe4283776ac31e6d10e838e89e8090215a133e2cc510000000000000000000000000000000000f88c3eab9ab32fc165083ba1650736e04b4e8740591f6e3ffbf684fb359fc8d82513c25a9ecf4d46faaa14d9f13a3ff20a2973faf886556e5329363bd9b9c96424fcf2e953df90bfd011ec07bc66eb0000000000000000000000000000000016fb47b4497cdcc75c0547f4234ce94f45d160e7bbe199902b2af5a5896e7d46cdc866d0fd730f568449032fc3a2df4b0000000000000000000000000000000016c2da30ef51e6728c09c3b29a7abdbb104f1a4fcc8960248b9773d2ea7f1bd161bf17203a271edfb235e8b0be437957f4ddb773155a27badba330ae5d26096f350e9ca2811feb227c4eee09d2baf32f000000000000000000000000000000001992edcbf32707e92506e5cd12662e730bc96b5f33bb88c5569fe6b266aecf63548be20b03fefaa078231b17424ac98d000000000000000000000000000000000f6179cb8878214222c2353a60e0ee210c86e306e335e929050543f084ce7c7ef56ca8444eee59856f4107e0d8cf997b52e4030b5a4bfa767ae20cdea7f464dd2dba51c9c698556d24b8f3d4d1afc82e000000000000000000000000000000000d3ff341e9b3821ac23ff7a87cc9dec3fba38ab8f2bc0f58e4c0135a9d66c6d6731ad8bb97468ca44538ca7f26fdfeea00000000000000000000000000000000053240b8429fb290453de18000ac58df56b5bf3c279e35d9cae8b350b932b0545b6c19ec7ff186c2123731d971146df1d32e0429e7934faa526475c5c7fb977c3030ed74e145eba21af2d2cc8461580f0000000000000000000000000000000004b424dab429bb3d22d18b52c4f9412a65eb7e8ec40b5e308f65fe6c0da1a1ab55a629ef8ed57adf108d146b46e6261e00000000000000000000000000000000057b7d5285194693a7ec1ed9ee3dfbe8598d9acb670baf03bf77c7799227ea788052de690e229b0d28c0a6cd79d22b0c1f700d651c67ca5b8d95fad1a8e412befdf691b074956bb8092938bda2ad2694000000000000000000000000000000000ffc202d826607947dd8f63b227a06d8c6b04848dd102da57723fe20e9b06b7c125f0ab2d2f53e14cbe95f1031624f99000000000000000000000000000000000880400b425ffe1b63214509f9acb0255d089e9de8e4eb643fa3b0383aed760f4c00babadd32f48af724a2c80a8223b383052a3bd7a13bb1ccc22b9519c7ab12d2dec67924fd9f15f96069de22e7b692", - "Expected": "0000000000000000000000000000000013c0b89e259f71ae41cc73ffa3c900ccea45a8a655353db6eb17a87582b00bfb971ba91d48526d934b95e9bb6a0fb5a200000000000000000000000000000000042a78ec26bc1ac4165c36d84588ca132b7366a3fb548801810da041213ee84c7e6aaf5ba02ac051cc1c5be5dfce0ea5", - "Name": "matter_g1_multiexp_55", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000083ddce067e21b219535e477f77ba100fb86744b1b82b4ccd0c72aac69025038e719ed173e70805c025b19bf7ba5908a000000000000000000000000000000000a9eb816ed60bbe55d4833c0e91ee73669aad116ff793d941223c17c86fea3ea434172c3214a4620d4090915cfb15d11c40774f67a651ad70f17393b386e9ea9e81682ffd78db7fbc17cc5084f3c705200000000000000000000000000000000050bdd7d98b9df55ec0ab87e757de009c804880f06be3ce13c5e051c3080df45bedad4f074812a698f50d6774cd5921b000000000000000000000000000000000a8dde7b81feef753cf16f0818f29256391276847cb832bc2940bddb329b249af4970684e95fc02e702f09a84e7737dfccf1e36e063a5fdd4b735dc18bf07703b80c6b72f987c05641612d7ce73562c0000000000000000000000000000000000d989e383d1c6e48d14332a72a8efd89260fed65a47c4baabeb0c0cd8322e26ade95b8be9f532b4813153cc39e7a9402000000000000000000000000000000000f6f7ba41c95beccbf59ca1ebb1dd43348c51de617a09ab8a2d67d3f7065d3f4699b1fc31197275e5b895f92dd106d667ea75dd2f54fa6413ba77f10a11e12abea3a4b947116e1e7c9334a0a37c396310000000000000000000000000000000013f3c3eec6fd2d4c830458cf58d5e18f0367675c47d38fd5ddce1e8be3d6ab04f71d09852b987d2db64652b3255e874d0000000000000000000000000000000009c0000761e1fe517eb32bc3da4f7a933e77db6f960f5405b64d9088776b6ee8e23743cb4a1779e8d0d93787ca029d7c6855c61bb7d72b022c16290c6d3ca9c1255cede8e0b827b43e40fbf018403978000000000000000000000000000000000c7a5bc0249717c1e39a4eea37de1b423960b409f5e0b3877e90d5278cabee197948383936739ee3f25b4bbf7f32e18900000000000000000000000000000000113d6fdda1f4b2a20d98e1d458920658c762303ee69fd7273a8830728f79be00358b3f3000927bc4d26352e5b9e6652b7fa8503101f392a6c6c27300b6992af3fcc48d47f73db67615a44de883770d4f00000000000000000000000000000000108fb7a97ce429fc3ba1ca54ae841309e2ccce748dca953cb7dd9dee3ad9d919e3f8ab635b294b94b939cd80d3435b5e0000000000000000000000000000000003af838ba4ec485ec2a17e6f592fd832d05133952f273d1b472800b210c96cc503caadc17b38d3d1e978606786d9ffcddd947617bcb7ca1c8fda0d49e6d950a84d60230bc2411d42ac32e3651f48524b0000000000000000000000000000000004cef28329ccf221ad7ab2b851e869bd433116753e0d8bf38d22ca46fbdc71fd9d96aeb9c0df69c47905a99c96fef0aa0000000000000000000000000000000012ef5c40d8b6469d9f3921eaa99446fe494a55994551fd1996c453a4e5cb4a2cbabe20671ff51639710a5e45a57271aab4cbbc6d537ed2b69c2c32c84f3cea3d2db180b64861859368e98aca32bceea6000000000000000000000000000000000c81313e8b5689935fc01b5f999de2fbe9852bdccf484edd0771e8427f2a194e29d0af09db1152fcd91c8f7b665f6929000000000000000000000000000000000f37dc7f87b8de48441861ce0c88b1a24f22aef2c321ddbf385cedec7810c20c7fee3d2c5a04b5390a5fc24612e4b3e9457bcb8c44a2d9d1facb39ba7ec8ede5d5962b3256d9fc2e68a1ee5a733ccbd10000000000000000000000000000000004ebf9f75e92ec4fb7168bf71215c9ea8ec17dd9ab392c9810316a30a33b4ace8d93ab75356baaeb51a7f47b4370915d000000000000000000000000000000001307c68414b73db43bcd9062580f7c814c3c34545ad5d943685ed8df26acd457823ed628e4b215875a9008a406fadb5619f254dbf75f1c42046343b0060e71302bf6c94ca2fb8aec74fe7a47a3c9c3ff000000000000000000000000000000000cb5860f081e314d4fa3bf70a5eb18d6fb7f5257a708f1b1726b539115050754724ffd6a34d3b5c95359f40f41f2390e000000000000000000000000000000000c392d8603c2ef93d2765d98c695dbda8e4b64ed90c4771a4e69fa00a77d788981132336f870a3a93765902fd8fe8763f08cf27a47d89ae6e2ffb27870d613b9ae586857e4ea00670944a2883ba325af0000000000000000000000000000000011c802516f42e267c0f9db096fdfff77d676eb301ef1ad440b6c2129c5b5722c420f6e479443cbf43d48803f7e32d8470000000000000000000000000000000004a5ef232d3582724c3eda67cf2e69b26ce44bd927555359820efc3fc67912df560edfc4d119c5595e1ab1fd7e2a262f50aa333bb6b44086fe6211e89cb70b8467eccc228c09aaa1d589cfc24771a11b000000000000000000000000000000000eef1e6400dbda287910c117ba17eee1137377e262f7f5cf13710b521bd26eca2aa9731b0a1cf182a0d57a329369125400000000000000000000000000000000188e925365fe7cb96875e85f711d8ce233cadbcdd4c892eac52d9c77f98082662410db4cb6b24889b21f162eecd10f42d9f7f74a5ccbd01afd985d3259739023cd012cd67fba3a4ab5597e94d8fad434000000000000000000000000000000001307849ed4d685815c670477ac54826e94465aed0b70df9683d09ddc62597e7a0a7a4b2839fbec735eeba08bbd3e821c0000000000000000000000000000000005dd74ee1018ff2280c3dd8faec3c97bbd00bbb7cfbcb849bb003b590a999b6bb3a973ec96bd9d825206eb353086283485c00be7e66e318bed8e66cc41e7fd0593004bbca20f0dbc28efe4441acfc9ae000000000000000000000000000000000458181a1019a65c34835eeca4898b88b0351da7422bb5982616c90740e8773b5a03272646f26c3a5801c6c16be33ec900000000000000000000000000000000101c2091a08179eb0be41e20a545f5b53b8ee39365dc9b57f12d75b2beebdad488d63e857ba5187c8f92af447f72896ebacef63d90ad11bbdf0c5fa2db2838c238ad3049a3f47b7f67361825efbc6526000000000000000000000000000000000cb8c637a9b8f053d5104b582ca03ecba768425c639fef23c4b624f31523e0ac669183639991728135474ca19e0335160000000000000000000000000000000009e0798589417cff12eef14f00e415c51c30fc26461e92c4e3fb4a5ab1a653ae791f05f4cde0cfe2132c377175cec1c2473fa3d16e6431da14b8639d4fe316692db087a167a2c4f07307e770bb9e35ae0000000000000000000000000000000008400ba7dce60413ff085c0904066b8e9e9ae290781132e739a5a8c7bcbda322fe1c8d0fdb0e9b0abe44ff99d4ca22ee0000000000000000000000000000000008b54feb64f59541ba3b7c6f86d24b69fa30ba057db890cc6d958e3a7de8bd379257c90a413050f7789ded9ee7b28bbd2774741f87af1d6942dc4ed79b70b2d706f3db6b6d083eef0475334ef1e2410a", - "Expected": "0000000000000000000000000000000017377baed9953cc7fe1868baa9e2f6c87edfab1700bd1f60e2644bb97cbe2dd1fe031a986fde6555930d4c464399f1f6000000000000000000000000000000000ff69a282658b49c270e829b326502d83a82dade820de50764a7df957e94e7c0a1f0e3d9084b45d9a875134bedc4a0bf", - "Name": "matter_g1_multiexp_56", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000d1de82c29aaa76b17079b2e1000005bf37df08de2c5ba7a0f9a14870e0ac327f46f59a116c72db57cf5110aeed6c76000000000000000000000000000000000a8ff0afd1cd7f541775567134a889d82727e893e4f57d1b5981fabd4bbff59dd3d3995a181efc9b5fc078eb3d4cd0e7d10ffdd3797ad13e65a1115cab6529d0f87b91eb41d6265e694eed8f026672140000000000000000000000000000000018120f0d0dc908dce4adbe50b24b66ce12e710fd35e5a8a8c357dd80c078d6854f20b12d40279b9d6a895460d8989cda00000000000000000000000000000000064f4e282ec5cac74e1a12f678391730663c83afcc0b415fd21475875762de2224e389d607cba84788a16d622d2ef5c13e5da5568a9427e0cbd7973a34c147ac2f3577d06f68280caecf8588ebf1591a000000000000000000000000000000000dae339b418871e2f31ed380824412acbe44e6c73ede9b4c52c054924297aaee1f7da749374d7ca44b138acb85dc182f00000000000000000000000000000000155cfb670ac94e7d5a095d2797cbbb5b8ad3e037fd246246f8e8c2278f5d4e53a773e6518ebc3ea5aeec6383d6fbb62c145b5f1f156f3c823cc129568e7602694107608c1f9545edaa897df58d27b18f000000000000000000000000000000000c1f7aeb05294c1b496de11f743c0c7aa4255211e1e36389bc93dc8d0e73fdb9af7bfbcef2c196a95d1d449b9983b2020000000000000000000000000000000011251668e9edb38ad147f22cbab7d280d436d11039d9fb823a19dffedf2c6a484f112560623cde7e5525c85b4f5d06accf6760be82cefac2843265be5fc0fd6d308c1ed06fc684c4693de25372f09ed0000000000000000000000000000000000ad488f5b9934adcdc834558c8db1d62574e1ffcd03da30eed865042abae4dc03d69010e7e591d9f0a8e421d22cab23a0000000000000000000000000000000002cb0a8e0713dd3c4833af74767ce46aca6c1efdfe75d09a50fce4df2eee3fbc031357691e23ceee810d30004d03f6b9d9fca4d166149ac9e6159ce95a06f790a96243662373637f0c6a59764b77b45e000000000000000000000000000000000465d95750a3c688f560ab9ca6fd1f77457592a0d5f54c17904a222010444d048df2be3dd402f046b1375d75de446d2500000000000000000000000000000000166289d948aa518167e72591a011b3f5ce209bd32ce091543bbdee1e8776269347ed711e1e9f1193f818e3045761a75141733039312347a0c9d760c1bb9a1209a34a02b359a9c52a57eddced157586700000000000000000000000000000000012abc4f1c56f9ac3760acec3d79b77e9ac71bbfe4d2a90cf43da3607c99035e550a4d0fda734bcfcb16ad08f773535d400000000000000000000000000000000030953a6099532f7ac352eff43569914c3f8d736b8aca89f778b4a67c754ada78e121dff664feb751532a41c8081380eb21b18d883ef62084ce4bd353d7434d7e220e9cf6bd0e8d0bed1ad0a4ad94c7e000000000000000000000000000000000138cb559d92b392e94cdd8666605cb5b05e585dccfc023bb6f1abe82fad35c108fca7a41afa49a801700dd8ef89eb3b0000000000000000000000000000000018cf89ad3e05492ac8699ba0723d5ce43e81b0166fc33653c967da921faef37f3ee2e8e3f71f983774966ca183e05f9eeafb6aa11296facbc13936bd2ba09a2cf9bbd9dab6ec8cc5f73d78c90b471a3000000000000000000000000000000000129c48a05e3d6bfab6e6f5200fbb90fbb743b045509b129e3622929712939c5d15126a09f1a650489c8afde7ace8baea000000000000000000000000000000000abff3803d605dbd63bb8453e304335a943bebd224d2d8067d76f5591cc6a2b954b9156a243b0c23d08424fb9edb52383d39a61323c07f9f4656a6c5e6ba139da8175ebfb8a641de50cfa2290884662900000000000000000000000000000000194e6f217b863339824d95c77253ddef4ab97d9744d10392d399b1f165170bb8c13ef1b7cbd995c1c1dc2a9d1b87f0da0000000000000000000000000000000019fbdffa8df167a5e891d09aa1e79049d377014e58523c0eb453f5f072a468809dca8ce0aa22b45bad4f8853d985be1df6374d0849a4471eca96c5e715b10505c4c49664f341d04705fc688c8479cda40000000000000000000000000000000006f0b72c2a934e430e4b773a61317007f1ef02c5f978b3565d623b6590b6cfec22f98b49f9d7f7efcc6913c139fb27a60000000000000000000000000000000018ea7df5f807d4c4981a9159d73d83ea84359d6aa00a5ef019b0dc307d096676c0d16c6b167fc55e14329a858c044c5c0b7cb52b99abe10d1367f8d3def38221c18657a1114ceaa1c0673ab13a6e108700000000000000000000000000000000130fae66f6b4e1a9b0b39906fac847f1285a7d37bdb0d3ddc2c2bfcc6320ccbad2ef1f119f2663e3a45dbff005a469a10000000000000000000000000000000019ba2ae0c371256e4c3dd6f9ae2568386d3a8bd90a57ff982294eae9194494add18958dd516ca9dda6a0b334391cc211f49b1fa80a321d4d100069b2c4b94cbda255d8e9f1a7f14ddf4762b76e4a386f000000000000000000000000000000001152651000a16809ec599f2fe9f330b0782685f6302254450884f0ee61ee2dc2cc9211f69d5d9dbcd7fe3345542a0159000000000000000000000000000000000b5c017e7ef71eb089188ed85331815b40c37abb6ff73d76f40fd8dcc6d2120c6a52df0da042b2b63dfd0da7db2bbca9ad3625b0839cc1ab8c9798b2e9706ba6d7aa623f3c0ce0985bccb2ee5c05a3130000000000000000000000000000000003a6f178d8c63765b2c8df834ebf7e96a4f451c6e05692f96b71c8be2a6e9af17a5cfd8b263eaa254592ea9a898488bf00000000000000000000000000000000185537df1a10c4c12fbcff08de45b349a90b0cc8cd17827df87abe160e84b661d58a1fd03c669015b991225ba08e171e150e53fb45ba8ce5ca917010f26451220be51141fe21cfc1cc06a5557e8e7afc00000000000000000000000000000000085475c2fd70cb7caaaa7c5c1fb17e2346903a962fa68536240d041f2f8cd3a7b83aa79a77f713bc31f7becd347d18d7000000000000000000000000000000000c98414bc318b350113186db9e965a238f1f181b00a2265638d914d263e4a71ff643907ed8dca814e5b8d5713baa8dc9d69ec73df67feb970f1c7a3880ee84d948eab4d8672a6c1481d61efc6cd7100200000000000000000000000000000000001064b94e868fa82c892dd244c6247063a276cc651e22d09695ac6e73d20bb801a189e8fcef8a711ed471fa3b2c7d19000000000000000000000000000000001561503962d7314fe41f7b2d34eadcc985fa748cc98479a06749692a00a46fb2fe5b5a68f7001a0f89f20f7f42f4463c38f8acba4782dfbc02a14d4b1d7b2b0a582f9bd75642169707a475b1a7d2d7e0", - "Expected": "0000000000000000000000000000000003e62892118f11065ebc66c58c86e2f0d3c79541aca8db33bd0e12f034f0e106a76f0aecd537539cf2d793cf823ebbbe000000000000000000000000000000000067e42ecf23e1b0590c30106b0720c806ca71fca0601b499025b58f137ff22aabdc6cc5eeef232fc9a20fb9c2bdee16", - "Name": "matter_g1_multiexp_57", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000184a661b34e18b637bca53ba60c891da69fe743d5336d92e811649094c15ecf2445736d0c1577bba4eb729aa7204b44f00000000000000000000000000000000129a348f7fa726585badc23f5dabf49ae095d300056b219bce0ce15f1f6a9fc5c8ebaae56362c3501af3f3de19515143cacfb05e5d10c41b06a487e9f8afa38759eeb55f0a5bc8640164bbb081c1fd2a000000000000000000000000000000000badd515b1e0959e77e0f00c7420b46bda5fcb6db59cbd431a1b0ca68c291c6dfe89ece299434f83a980613fe73ab7d3000000000000000000000000000000001266343ad330fcb2cc8242e30a8085cf6995ebd810780115ef881516d4227c6051564d7343e4a5d6bfd210e2e40b91069a0b88d946231cc484550a87a548719f0a543c0698411f230a966cf602dc4de300000000000000000000000000000000085e7c22d51db0a45d8db7d5365de9541eb87b81c237fc47cd25c297da4435b4c9b8212c76c929b7c8f32e8d9b11374c000000000000000000000000000000000a4b0f905b48145f1831e453d0372b7861f7be6e413182153cf77d737450a58f378652255cb4516a482d166233dc88c574e3b5ff944bbbbf808f1f469a3380ee7dc37ebecdd8fcdbbd2f2561e0dcd68e00000000000000000000000000000000086b97f87625356425a79db717f940debc7a7e932370ea315d1f94b1ead853e3ab6edea6302b6b5b0eb4e4bb3c7fd14e000000000000000000000000000000000fde70203ac7a82901250e9798ef1c671f8d5f878fa3bc83556437b9b98e77f7fe7d3a0f31b8cf05ff6332df0424136fc23064970a4ae4ae648a79edb193d98208418d3489e9b5b8517ebe99cc32b4d7000000000000000000000000000000000e629b2d9a57bf96cdc6871ee7dd7675257cf62dd10028201448d8e5b1c0abe777190a868fee83ff5d067252312e82dc0000000000000000000000000000000002102d461c9522542acc185349ea93810c3e2412ebb427f8556b947efe198d616fe00818bedc22765f697507d7678dad972fb60ccab83b6ce042c09ead82fea3d2cb891e21ddc5af7b5d8e334d5a32640000000000000000000000000000000015727f52d46099c0ba041be660ca312204afb0f927fdcf0f1afa4cd3448cf3e9fb76bce7ce0da8b4c0048f76f0e7b1410000000000000000000000000000000009dc4e213faf0a8216061b59dd35a135b364431e2be37e42d065a42fc8e42eb8669d32a5f5ecdfd9234487479543471bdb68c389b94c82f006fdc637696d8085b24897177d2992f504d4bcf5ff04d173000000000000000000000000000000000afb691289f877e1de6fbeb38cee0e36fabf3daf904256d5d6db6e96ce555a9304219bad41400ab6278727e5fe2faffa00000000000000000000000000000000165a54d6db7332b12224d59d8b677517190744c039d9bb401c2e3c4437dbf230b67308fa2d5ae2bf5de282c9ae38a3fa4510c100005f2306f4b474d3843b4a79d04f0171afc5c66df70f631b0481dd3300000000000000000000000000000000032dbd300fa383541e5c40c849addae3def5a4f5392c44b9e96981dbcedd02252f9bfe4100de9954ab34fae9b2ec21ce00000000000000000000000000000000185e62adc2a44462019c86028c617ddf59a6b1c16071624de5ca755f936e73c47cba00f552d2d79baf60a1796dee009edc682a2be4d67852d119795988c52230d8273648cc176ddc012a4b4da5a8636b0000000000000000000000000000000008a574ccaa24ef76112a25b990b5d3b462ff9c43589c9efbb617b45a87bc26eca6dfc6c9e58a12650c202a06d3c86fe60000000000000000000000000000000011f41e39dc0f0bdde1b9e1879741824b20d9237dd7b462272115e8ed44a1e6b7bf82e8ae481204dd8662418fadc63bbf8af6b200fc8e6a57a954226d9a0254c8bcbbc55fd6c3db5cf8532323d4c50b4b000000000000000000000000000000000efa7f183cdfcb25cc5516bdb45c409581b6f2a5bd8ce8092dbf9050a20b2ff57c6add39e96a6f1c8d2134a5a37778c7000000000000000000000000000000000a8213977e8512648b6aeafff2cefcd17a14a052791d20236a78e0b462dcac81db74f1625e787540d7dc279846983f647e2036f73e8cd5e42ad86914e192dd969465aed0c3b752986b84a0c2444c90b8000000000000000000000000000000000287e0add9dcf33f37a10a5ee89cef5240313af0bf0dc183d0c3d6b919c88b979c932c7f141ec5faf012a7f33fe56fa4000000000000000000000000000000001313f591d1da8f6baff044857d2c04f01935b493f5b951cd3538054756d33a52f71be92ef908f016c133aafeb9b9ad2470cd5c1545e76027c389645da1089fa88f675b5b6ef9217b584d7202b797f85200000000000000000000000000000000192d02ab0a323e85e9fa6f553eaafe0d8ca2de63f0fec8139e24805f0785cc85b39908756ab4eb39354ecd8d9440d5260000000000000000000000000000000013997cf706bc8d40b019c2dacf6a7d269e0ffdf8bbc1b4b39e75b48ca5e5e6eba0007b8c55b59530b34b7ebb4c657c57244041bcfc21ede8023ad80b6d4af4b2777c0204ca5f61854e6da34ff5e1145f000000000000000000000000000000000a61b3cc7913e45c132cfb06a26fdb1882bd700b32361572fc79a3d2c432644392f341cc70905b86cad2ce52c30e2ace0000000000000000000000000000000011bb3d958600993ec04d9f98ea3f29df0dacbfe6557b36bed865c564595a64132e4036b6240c97cdb38a60533d5a08baad7572da641373708bef008057aa5af1cc76ccb882bacc50a77b37d7047b1bf30000000000000000000000000000000003d2bc11fa699b284b37d1b45c8dd6b41436a7b2fa09cef316821516801afaa4e1282d717d4eb3d46e54c0208548dd9100000000000000000000000000000000123f8cdf2bcd7d6eab31975ddd610afa79c3c95fed2a6348fa6872b74a6e2816509c71f11d1f272dddb59bafc0f48fc454b51c78093cafcb57c4c1f172d08257c379a9caeb5b5478cacb4887119a08c6000000000000000000000000000000000982c1cbcc39867c7c8c4512392af1489a5e6aa01ecf56abf4cd9050a33536feeb1866421958b929096d2c3f6923891700000000000000000000000000000000104ba4defb74b35d15db80df1f4029650f00b306d702b5934c1705d226886d4bd22b6c88e71b862109f8dceacde3c6d2ae3bbf55186a89740af4da6c073d8c0e331542a2c972a49dd3bf65261dda6e490000000000000000000000000000000006e5fc17bdc786eef8cf2140bd8002ea859619d319126fcc5053be9c28526e14e0bc8eb924fa242305069226d766f71c0000000000000000000000000000000017ee60b0dc932806dfefdff2cdf00efc4d5c81a1e84ce48a25db1d49ca26232d4e4cc1f37b34c80375597587dc183b4259b43915b15c509ab8930979312dea2ec9cfa9f679b004ee526aa5dbb25759a4", - "Expected": "000000000000000000000000000000000c3dbdef90052dd5bdb70f15963091c8fccb5b8720a16140ec96dda18eb6cf003b6f5f7c244d25cf6da34f2a1703a9d800000000000000000000000000000000187456c5af42c3de3d5e08936e8a3f411fd6458d017ec508e48f2b634319155428733634e22883492d7612b2bc38158c", - "Name": "matter_g1_multiexp_58", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005a912b6b2b00c2b2c90ab1aef8c9240831ea9ff2ac3a92753054f159f5ee4eadab8ef57eb5972e3169ff9649b886daa000000000000000000000000000000000981b901734dfb3b5f63bcff802536492664ac13dc695960ad89342ea865ac67d00da7130833126a33573d55a9baf128a53d5989b63ee5f157cc44c684ccc7cb4c74338b12fbfb534ea33db341fa6b46000000000000000000000000000000000b052881b3e27d232ec980dd99bd0ece4e861cecff2496472caffd741f2954718d605de98d9c27dd3ff473ff12b238400000000000000000000000000000000004de4bb9e5a4cef93662cee72259b88f7ccf8a495b733e868d76cc25e04c53a65a83c853c98a25f7a551641d54ecd9534d840680013af06920dd06bacc0ce95cf0cf79e8ccc0b10027f2d28c1d0049980000000000000000000000000000000016e4d257db25c08a68943e6e0065b375422fc817539d2874279e2b41428da449627e6e04087fd448f651a23fb01816ba000000000000000000000000000000000e80d041b65789b3289a94848ca4b1109028c9fb314e652486e650221945ef4224ca03a693e062b06036898eb664fc211b67d661ebc9008669bb4e5cffef81a32baabd71667a72f1d202ced823f09c74000000000000000000000000000000000542fcc8d668a827daf3726bd71d7ddeabc440a6fd0c08a4730803be6e76613cc0265252c41123146a5d7aeae93f485f00000000000000000000000000000000109a61920ccf34a0a71f51f4fe7c882b3d6fe449a8c67711dda64f9eb684b4a28cce6e8bfcd6f3cb599adbd0771a132dee495199ebdebda02179432d42d5d9c76eead4d4993cd09a93d46cac997716a50000000000000000000000000000000000a65c746a1206b1250598823b9b6fe5df3dfbee21cd31000e50140893875d1ad9fcd4fe12bce0758544ad8cb4cf5ba700000000000000000000000000000000038c25d3c35fb34151428d2f6bb8a459f834902334d195da214ee9fae4bc6099d225588a001f8fddacadeff0d3d215463e038e473d6f965751ebc5f69eea6f37be88cf001de0c4e4b700823d8326f17500000000000000000000000000000000158f2288a667f475c736dce9e404ed37b18d677f984b6d9dafb051b87901e6fc60289161bfcfa46a3fdbea7b4cc3f795000000000000000000000000000000000d7faf96c636ee38347b0046d333e72d601e20b018d554d50ed63e30c62db7fa20e29b3ea57b1f31e0d7544ad711c96aab2af2590309c9b9177e4f6f0fa06339fa720cf1c9fc7c001785d7145a3c9030000000000000000000000000000000001933815ab2d8b6cef8790f87dd9750bc2b7a75a9d6c425a3e84cd109f5f5ea866e171dfc212f6f8641252e9421fe3aaa000000000000000000000000000000000f8ba799ca5dd885046a4ffce1d26688d0bc6936f3a5a943dd54f89d991500908c81ec4f9b116e73f74d46b67731421bc9551f12084ad7d4ce346f841fef785d644821b5c2d3c8db3145fc26e65666bc000000000000000000000000000000000d4ba404254175cdf5c47c08ec158ad83b6ff5b8dd32b8cb9753fa157726271f343cc0cf5231e7e31583877d2591930000000000000000000000000000000000191f45fc4b8c94519d13ab28e5f84e22dae2f82550b44be737728a695865973ff5060a639e3f03904d74717963dcd764ef5823541696ecb88d0c71e00a15282c40d4826220a202be09c47fd6891b93ba0000000000000000000000000000000014d348b7dbace24bfcb258c853b19fcc1637d7ed9b0ec00d4124cdf6d608c6849e8d2f9858afa83ff356380afa1376fe0000000000000000000000000000000008c509beae3cc22f0da64bccd2e0387c05d7613460942d25182605b3eae6ce052540142d5975733cb6554e6da9f473b6e32d695dd02323d40ac1eb9452cc53376ef941237563b1ee380c9824a565008d000000000000000000000000000000000ef9aac66681015bdd9bf287caff9aee89225e30a7976e9f503a1712fa863c8d6d46a80952a1d94d96a5e0496f64ce5b0000000000000000000000000000000016c66018f43bf585195b256ca106f47077f977701d97f42564223817ade0a520aa3d7f06d868f1e91705232b1d2440d9f5e23ff8acf88d18e53bb31476f10fef288e20e818431f9f0d2ffe1265e8ea8200000000000000000000000000000000042d1d00a946085dc6329e852342573db7dda7385e6a50a2660a924ed6202968e787559fc58a162a775bcb115bf1fcf800000000000000000000000000000000162b52027b08b7d91fe0814c7be69414121cfd452f4d0407a2300bdfe9ba81a4561af74d8067e929b71a92947eac4fce71927817449ba5f053d0ed1e567b53b1179c6b62a554c8be6764d7ce203f74e4000000000000000000000000000000001598949030cc21d76a9c69305f023bad3cc761d5f857bbccec4de6b0f7557395efb2d126382731aca994a5020039acf5000000000000000000000000000000000dbea8852edc6bef41dd317e7d70eb2a5416d5087ec5207af3f5b3fec39a416dd9ccf4cfb5400cca152f173e66df05f75ce5d6f0e44a20d0a0e2f1cc523455b001dbeef772d84b2599daec66b285027f00000000000000000000000000000000081e898b02838558c1c9d7ef9f86fefe512e2e7364ad824506c886b4cbe947657c5480353e4f72e237da013d81e5eeb10000000000000000000000000000000005353bf2dafb1b9b4f2cf58e16645aa3fb759eef6eb8f516db068d2768851e7724fda5cb85241aee62b4404de2862dfbd37f7bca1a59f65982294755ddf8af7f1c953b6e482fee854e0d89e9b269e0e900000000000000000000000000000000028453aa48ad0302804f9cac568467668b1dc0dce2cbbaf280810ead2c0a94e156420f4fd2566ee7f629e57c3741b8960000000000000000000000000000000001cfc5ed80924f7088ce6a5414372d13fd8f6eb3dd83c66d8b8e4dd1d4db2bbbbbc6ffac00e3a880d8a8fb5dc07fb23f06d0535e3728b9e358d9ea82df4f1137db7a02f79c0cd0dd672e24092bf7f6b4000000000000000000000000000000000a236833fafc3da813b95f4562804361aaabcd8166780a4646734e4b65e3a1924c075d402404b52adda4902bac7a2cbe000000000000000000000000000000000def6beaad6a180998c4c70f9a8dd0d948a79524b31fa44874908058e9e58caec2e23d5a0787f1ca05a359ca276c840ff56d6810620e8da932c202628c2fa9f0a9f3fda3aa07c262924aa51685d2c9af00000000000000000000000000000000188bb3e69bdf0a5f31ad16751a12c767c86df80f53f6688ad74cb2fb32b81bbf9d60be1182ea1b6c0d6fd12ef73e253e00000000000000000000000000000000139ce5ffa569548f1bb877c3d573136a8eb12e7c69cd21a70526f8724bc67e0b37cf7149dac3f78377ae7d5bf4882a6771e7f672ad398f5c02c989b475d12ce86e6e242d36784308e56178f2a6a1517c", - "Expected": "0000000000000000000000000000000006e5af407ada013abf1451bc9d5c08e5ba9cddebff0cb77175b152fc19bbdc48e1498673ae4698dc74d039a671ecdcd9000000000000000000000000000000000c8783b3ce25445209b9f1d8bd3ba539c01d230c07c4fdff38ec902467d5f7e9e8e660d8997939684e119fdfcc963836", - "Name": "matter_g1_multiexp_59", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001731f73d2ef1f87fe1752c9d6428de241ba71506c76f31aa9697d1c436af51de363405f60110e8e69ab268280c20f92d0000000000000000000000000000000001ec6ede05f60685e39acc7e105f60602f0fa3c4a6da7342da755eb34aeaa5adbbac4c13197a2c93314ec79f5da8b90177f9a79850b2fd5a281b22f52de085f12bd34e56808496e1c1388804f534d2da00000000000000000000000000000000158d295d41540fb1a27d8200ddf51fbb9d31a70fcb639c42b7fafae4a95b90ab1ca777125092aefe20f856e3291e528d0000000000000000000000000000000019670ff04a77cfd367c5f0c14218b5d95ea2eae8577da10f27d96e58039b7dd7e9f7f75c32f99dae0920509733ff9c96630c1fdad9338fa5236f817bada168a737dd3685b327fb59d8a37329920af4cb00000000000000000000000000000000052f8e8098f9e83eaaec1c2638aad30b043c2359f2551a02b2b95816e1c55d37bbfa6e284f280f15dc174d5f03a7698400000000000000000000000000000000034bc698f07544952274c21f416d8f1281ccdcf6bf53ad352afb15a3412879a10b37e6b8b9fc5f46ad715f9ce7b46e3d0969599bed4899c3c47e1d4081027203c73233536cc6e45aaa78a4f1150a5162000000000000000000000000000000000c2e014d5068adce3049cc326d36ef92f294700ab64bfe170260727117f098727cef2e28dc10fe473a46c98867c618400000000000000000000000000000000005b3ea9c12179a47f7e69690f3303ccae614e06878189b40264f02e9bb26284dde846d704121340723bfd1fe5696410dddd438de35651328de7183dd38820ea2983488ba31d401094e59cacfcd1d031900000000000000000000000000000000119e9fe8723883d9ae8c61efdd3ae961795d79409750dd39aa6f0f8727ca2429856f977697c4f81894061da278a0f9a9000000000000000000000000000000001438a4dca0c786062aa9cb21e26b87e92f90dcc0bfa014f654b1734cf7cdb8a2e62fd3836a802a9917539dd068c6b4b1191f2b2cc76d848e456d07c84c0826a8861981dc84bdc671bc9b5882d387a41a00000000000000000000000000000000012872f4dca3a9f3fcb07d67c76836c23eba3f7957bb77950a4b43ad9c7ee54f53187a742b13e026f8234df9e91659c400000000000000000000000000000000078b9d597bd9b5ed2f7e0d5f8e4a518012591b855c5352fa1450704a33c3cbd5695a0f8da235411aa99aada88086f643aa76094782d0c06f2080d699b81aa04a60891046e0053d2fa757c7029df8f8480000000000000000000000000000000006c414c6611e00c6e98b370bacf2ffbd7ebeae890278a0e951d6aff7dd3e5fb90f82b4e65dd007a3289f97a9600786a9000000000000000000000000000000000cae4750f99ba13f03d3e0769cccc879a4832210d6a2f25b2696099c0cb184398b7d432e801d23200166a4c53a3e70f3049a751a406657dacceb3721461417571a0104e11c1e00805becf71ee77eadf100000000000000000000000000000000122f404ddd6b34938d8e57d9d6ee78c3fdc1b771dd7392944ae88c625f81df63915a87ac63dbb69adf8fdf856a92bffd00000000000000000000000000000000197c20bf1392d4d68efc6ac3bd5d8b53b360e305a501dcfc2e350e3738503ebd44a574e478757240236762db2f23d4310502d56084d1be7179fb735e233978a5a3c2756d780cc0ea6a8aa92b1d1f7c4f0000000000000000000000000000000019195a36dfc449c19b172ec061b4825e4de85fd5b9c633c953ba7a5617973e61abd0de3d59d441f49264a0dd2e781b20000000000000000000000000000000001430f743ee98a2b2f37d9ecf2a7d4dd4963707fd4cd6ccfdff55c3eb189aba2fb295877bc2d3db9032af26eff6485e459787a6720b8db1b4f0e1d535833ed20b519a0e4d2e9fef75022aafef52371375000000000000000000000000000000000be5d90e5fa172a2034667160f635ffc190fa495aa9af51b648125c29bcf9b4b31fea7a7e4b49d91b4a8d081c9aa2d3d000000000000000000000000000000001721ebb02265f698528ae1bdc5bd4500d7612bcab9ea939f552ffd8e9dec1d267dfd25ad4d3531676e2ecde3d2170c4810b47b662e8cc8dd005bdc81dc6d98d0eb98f86b46c0c8f24481af9120e84a820000000000000000000000000000000012b7607bd9f1701ed002b6f72b2e832dad7c9b2bb6eb6368fbe78c48bdfa17b2546574d7876425cca7986fa6839b6da2000000000000000000000000000000001975f41ed7cf252a658e80634872ac495e4b518349487930610906bd396f7fe4af3c97acd0ed3b3f265917560b13e6ef072460e3c5349c8fec9944dc99762625262e84c70f10d0a92077a351335127470000000000000000000000000000000014ddf2cedfda66e12e999d0b280883c546e00dddc0bd17817d6df90b7a614c472cb2840b133eabdc7be39b63e50cd9ae000000000000000000000000000000000b86e0559e27a6061aafc091f93b744a8273032f0e8b1c8b7071baf3ac7008a8173b71f51b27efccba27cb018b25257ff3177c4d865caebf1ef6565bc85e0b0bd51365a6f321e26b97cce887bc3f44d60000000000000000000000000000000010f691744e7094b801c180810b24f6a29c21a13514bcaa6303ae49067bdd001213f13c6f980c51b050a684b525c2dabe000000000000000000000000000000000e4e4cc3769cd3e0e458ded43b5c7c481c17efd3283972919212b877c21aa7abd31cf86ee2bdfd3cf0ef6d730c0907db393654ef7ad8687c8878c55a8240ae9df04805d3e2f194e960d5e498ae3ca177000000000000000000000000000000000b5e86c2be33255bf6f2f2aa8b17109467543168c0bb92a9ce19bb64c5f84188b2e9f93ac85d948c76989d9d4dc9eafc000000000000000000000000000000000c5244fe670dcb16d7994b7db8f933ff98744e5c6dc124e057c05d2697881115a99f983be480e30ae3e0ce75081b261edb9f942124a381b150f00a59e4579d0a2b7b728f62715633288fd03d01dd12dd000000000000000000000000000000000df7f56643536b20f65cae1ce4c67c6bb6def8c9b514d6edc92673ae743a2f4e4906aaf7e3b048f88f08a4f5c9f85c8000000000000000000000000000000000176cd183f547a3f38a86d604f8e76261755f72e7222f3734a456a3bf7029590848970e8836b3570e9a4f3500e54fa3008e6eb65778a328cf899f66581ac7a4a89e0e824c15573bc68c02cdaad89cdf240000000000000000000000000000000003737e58505d0f4c6890c7e03d5f252aa682c110f5bf5dfe8bcee9393104393f4a6a22c34c773e1dcb78881a31b33a71000000000000000000000000000000001988ab3430de7a463dcc2156db572c43b68e58ac2ee26f1ee1bf8e9889f6cd3250e5d7f9464a8eabb127306af39c13140940e3620c59504062e4e98b5d4c8cbccdb017c47a094d06253743c29465731c", - "Expected": "000000000000000000000000000000000d541103aa046ef53761e929d50c88796b90b3284668a2a75ecd461ade103f086fc443a3681b6440e6b8a8b9558870f20000000000000000000000000000000014120e26b160a37f8e18faf541bb863ebb425fbd0eb072268a12657b6e5ff62d4c0e504691b3d09b710741820f747b85", - "Name": "matter_g1_multiexp_60", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015c91ab58aad72af3364a3d05e2893c756a273b2c731ef421c0552dffcb32fdc4296bb79afcae2d3c8aec6e0dcd27c17000000000000000000000000000000001901b4fec7a1324a34fe403dcc51656145fcbeb4eac94f955f4fcc5ad6a016eaa436878e85dcebd8992e1a177c5bdbf80f2f697ef6783390724e04b81d0e18dde6533eea9f72c1e10bc72c7b954659660000000000000000000000000000000016df7578f74b1ccdfd537a074d71f2dbdd581f1a2f78875a7d4e1c3cb772aad0d02bf4935f7b08aa5163e82e5a747bdb00000000000000000000000000000000053931dd0624377808705d3fc6e12c4894414c8f6a5662ffd71251bc7725e6d23b7781286b8be1e35eb615bb1efeee9c34680b934e67bd7518f0d6a3a809dc7faf845eb71d0247291d61053d5cbe0ba200000000000000000000000000000000056f0c5d78c5d4e97fcc7d6c3132dc4cd802eaa1bf18921d039274104b56e8a701c25de6ad33e57997b2e8491d7cedee000000000000000000000000000000000c87632eb73c464f53c15ec127cc5c72fe6a413e74313e80395b55e122108e2984eee6f53742ce4445f455108002398fefc024dbceb522c02b88810ada9a814bfd085fb63d570663a64bc0658e5ad02200000000000000000000000000000000040f1ed7a9f7c70a546088822088c476f8954681f3741cffb7e6614dcefe2963253599acbd263b988af3764331a273030000000000000000000000000000000007f9d150a4b34b9a6f872f9bbec4d2e0795d02c5411d6b3a844ab95ea87f9330662c8b0789e12a8f6dafa2f7cf2f13a12c136f00c97a515076f6a0b63faf7e378f2cf04f8a90ac942fd70e25e683cbe70000000000000000000000000000000002890e211b1969c72a15c0f24b21dbf672b2cd33ba9ab79790c07f0734709bf13bbef4f54bf17db9629cd7abfcf1fc2f000000000000000000000000000000000010f13eb17ab7ccaa0bf32b8d4d38760b72fa0fbbabe04017d9d8283f6dcc5500a336339400bdfca06749f7c1e08f748b033f2270ad2416d03dedd4bafb78ddc598810768fafd349a42438923ddfc93000000000000000000000000000000000f7e328026c07b116dcb8950273579e0c4af027bd3aa442a41d279b1b7d87d672154d2513669428e8f401db490404e6d0000000000000000000000000000000004208901e02756c5a2430200d562c0ddec0224446b3fca62cc98e9efcfb3508f50794301b026d47eb99aee210dd2f898202d0d506bbcd56c92bfc6fbab36bc96716de1af02aa166e7db2e2a0a4c19cd7000000000000000000000000000000001309e8c1cd6ca596ab2c9605ed0e356cfb97c4079518b0241d40a3e0e4769a8e58c0ec6a7bda173fc427aaedaa275ff7000000000000000000000000000000000143b1d1bb451cd56d800d71a747173e56b75cbd6fd28ff4abacbc1dd87653abcae715882af29c29a1631850694c5aff8329762dde1c4c91043a740a8b9639e83e809f749fc8c4853966cb2ea520620a0000000000000000000000000000000013bf8880a6c95a8791b8ec37c2188e4c0c2cf188e2fba01a9e7e4b81116b10da49415a0588385156e4bbd45b168467e3000000000000000000000000000000000be052be3f3278259b6e01d9d81afb4d4215b0b738378e56719403e2ed31bb6e15e47c9986aac19f79001a76f35e4162ea46572fdb37fe282203172c147715bf0a16e02a62bc79f33cbfe36703c95a730000000000000000000000000000000013b27128d2e8bde36f11503986c226a1613ba0779de9b25686284d12bd995c83e0db9eb0b2ea759ee81bce0ed2c0c2ad00000000000000000000000000000000128d6ea67c8cc9ce6eb93111780989b4b33afff45a5075691026ebcc607e61b7a48e2549ce8286cfe4a72b182073f373b9e49472b9b74cefe5a951febe595b0020c43fd54150445fcdc4292c5ffe65f600000000000000000000000000000000137033427de6a6d23e0a2fc17d396114f8f4ca3e56e42936c96029c5b829b3b8b7ea46fa47fa39f6e5dbcd804873d3ab000000000000000000000000000000001986563cad41be453d14ea3f166c2ef2d89ada32a345554ea7c7141f6b1306af815579d7399c73039d1696fb62edcf80b6bfa1ec877010aeab030b96e80d2e27b45a93c6a99e2aeb3ccef22527c6e472000000000000000000000000000000000f0878d6eda3d119eafa0e5cd0260cd5c9bed5fd3251f0eda5a6aab6b475ad8982b55a0c8c07b6921de77c4e23478f2f00000000000000000000000000000000181d4cc9e77cc1e21145457948923cee50db145dde59520e6ddc2da13c3380188856c220cbace98f7ac4bcd7dcbfb1812810705458845232e851b33fdbcaab01966b8ed53b455873a966c1d6b8936389000000000000000000000000000000001267b7c2a91132c46ec835a5c2ea1f1c1021449d4ab3c14355777f1b7771787ca8b72b61563dc7587db6318c2661551f000000000000000000000000000000000d9f7257977b3f207e889678b72b584b84bf736bc23081d1267145a886e2dd6b669bcfd8b58414def71c27cae868f39a175fa4954e56dabfd1808f93d2686e0b4fd285bcb78b80d15e10e63ea8c7b6460000000000000000000000000000000017c223749282ef77696136edd0b30041b7743e40c2cadf8b491c2dee0730554e39ecdce41e45d647340e73bfe77407d900000000000000000000000000000000025924e40885fe566166bd4c5de6e5bdb3ab993c154ce908afeded5614cbb0c00e6ddd648263f17ebb3d81bd6a4f79afe7dda7e5373d0e0afc3da1507416f47ea8b467a5b6c2fbde484aec8777ab7559000000000000000000000000000000000730c41758d12795c7e5540e4204e43c75a01dc6263833f8db435117429ddff6cf4fbffd6cc27f553b8524710aee9ab000000000000000000000000000000000154c3ac230c725594a3c985b7ad71d98c172de8764926e74f6932f5a5d40543b5060c5d604877e3a8df093927b0b171c6aa731f9393d2bb32adf04f19884dd1a5e7aa36e46408b847222a153da95aea50000000000000000000000000000000005c6852bd3eb4db383e9aa8c74f4c158888ada1c9ba07ab8c7b4abe9c05bca51f0065a29a814892303a42a6f2736043800000000000000000000000000000000086d733e758dd4f0f911df6cae3d678dee3500a53d8a364986d88c50576ca6bdcd10fd31f3cebc7a35f43de1d90ee4bc985f367919b0f3c667b1c1cacedeb0be1f9cb175c899992ef55f14e9b7aa6ad10000000000000000000000000000000008445e5c464c4e10fb0a10c97023c5a9b169d042971597eff4380821e44430e3790683c7c66afb89921f06199c72c87f0000000000000000000000000000000017e55467ed664833131b82a2875e22fc5b29a3808639e90741b731d4efc0420b4934fc75ebc2048e8196be55a600f9bca3041cc52c6f1bf62dee4c61b1c5e35b72ebff7e8e89b05353388b551eb10010", - "Expected": "0000000000000000000000000000000004f03dd7334a0dfbc7cd3b74a8e06ccf23fad0802e44c95712e920a2b227f09ac3d62429f40bef8241abe41575cc541c000000000000000000000000000000001092b20e8618beabaee18b4752a5b320307d22fea2125b3d23c6ad178f0cf2af7a1a1c0af3cfc669929087235e2f8960", - "Name": "matter_g1_multiexp_61", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121d2cecb2c9892d69e6a15561688edb5020dc39fba96eac835c0577ef017191572f8bba780a608c41d53544d24a306100000000000000000000000000000000080c59704a5ef9251654458bebe25d949bd5c7793c438a50019a9a7cf26036f014fa3f024edb767d233dc09710d53daa709a2e80dd96eb12edc481e3d58893bd0d789a499d5289072d58c2ea80b036cb000000000000000000000000000000000012be549d6b4efbe6e8c17393390f3cf190abe4621a16e951203747dc7faf6d6ac831582fefaff20c952502fe43e2020000000000000000000000000000000003112e26ed614405376dc1af80b9f1984439c0b67863f5cee6d3c44f74f320e66574aa1501376cf8f924efd83655a72b9ff35bc510c86a9e72c3e9c6b49d2abca546f7a62330156ec09c6fe6847a400e0000000000000000000000000000000013b6249bc071ab2f9f048531e6bd27a1b8a45d34c66623268402bb37f6be2d71bb5127461221089ffead4a9f6c708f0200000000000000000000000000000000016a321e986c6301240b1e9258423bb8f38012ad533b42cb487384d9af63713d4b84c383ebd4512145b3e518e0c935b1391dd27628d0808d4a0773509737597230d7849418540e1fe4498fd70d39d16c00000000000000000000000000000000069ae7a90e9402d4f9f1b4a8a799fd5bec30002683692a700ac3a25f8f0a8ef9fa9e6f34844a6c320877f4b4883f36e7000000000000000000000000000000001214fee37b448c79b5c3097dfb65f8b181f16f0daf54861d4e5e7297db7981f2ea20622d12acfac04c066fcd23169f0294f11b10e4c45f15d811e3db4b947ee6414e262965d7b5c23a731b019e63d5130000000000000000000000000000000006e8cf07f48627571ab5fd1a6f988723465ea3f741b71b9aa9156c50e13d5481d66f7fe4006a54cb283c6d43eecb4ff9000000000000000000000000000000000ade4e4a949e6dcb45cfedf2eeb91abe406cccbbc7b4c7804b77d04fd7cbd91fd44f0053196bb344fb8ac1ffa37c83d470f7a0ee05cfc3f63d46a3151c20da53604628bac70d7b521b3be65d7b2abedf0000000000000000000000000000000006b130d66b74b99a2048127c24899ea6ccb0a53c4404f36371f30fc1ea99d02853d4555385a9fa022a552b85422daa71000000000000000000000000000000001824d4d0eebb0178947adf316258d297698ef4575d8ebc2bd300558df914fea04f0269fe67205db1e3dbbae74c0db22bbd991eb5e8ac8ad7cbf8fe64a5889b715a2409305f2366b278adcd2144d7be8c0000000000000000000000000000000012ba5b9c8a86cb99337a7c4955b1a1b459c8a1a7eb6ea908bf27d5f7e41d5f3423c1ff44b4615c689df14709c703e9ae0000000000000000000000000000000008627851a30e33fecf67dff807bfc5430a77d0a85f1e4f8b790b2b072fb7b86d5e81b934ce197fdac6aea60414a616541a9caeccc2a2058c2f5a271c09036d73320f9bcb31b7296a796ef94ca4599757000000000000000000000000000000001051ddad286eaf9c9ae5b3757c53e324acfcb6a1a7d5b490eb9479e337c9824bf619167bf8f2aa5c7f175da534e91a10000000000000000000000000000000000754b16cc6cc813c5c4d44eb4488b04abb659d89cf0dae5fd5f59f257cb396e139443a99b71079c5aa10f8f48465fc398ed4eec02c2af286ae19ad5f05642587cb9ad93196756d269c783a11f23393bd00000000000000000000000000000000035732a9fc03435f3dc3e31af693b1d1ae79110cd46d07541a35b956b928cb4a2de2a16cb8295aa8e8d0c74556b8189a000000000000000000000000000000000d4e762f40fcf43635151631fd6238ab3e1dcf578dcc84d462dbfadcdb621be918f1f0a7015377b5ff9c182494ae149c26f20eee9bd019f9e0f5c794e22e770128737198b5f5dbaf5b7d18040443a0bc0000000000000000000000000000000018f1eb31d3d4e915cd1e0cec33b4838da1401c6667d8ea25209e4c5683dce96b1d7adb4feae7fdb80144c30145d7f35c00000000000000000000000000000000050693e8b9c90d12af4ded25e05df86a3e233425e2f77c7ca9e99b0868eb8d9337186113b078f8083a4273c9411ac1dfc470a66cd3428a44a7d095ef410126257175597a333cd36ce6c9822d1ee9bb38000000000000000000000000000000000e1ca58d3eb507f977257ed8bdff474a05dee19a00818754e3a85f1cec882b8e3e0296d5c3788b101da669a716772936000000000000000000000000000000000532526ecf42eb00da76db02ab6236dc51a346f0a1271f1e9d721a40a4569d46fdb63e0211f7986b98475d81998dbf8be53fa8fb708204e619c221b8ecee14fdbcb1f94731ac2c858787ab33906c92690000000000000000000000000000000017bcd6bf54d51fa12356f3428f02ad8ca31131a77951459d32c554e2dc2487be1bb9f10450e5d1f38af3cc7de1096a9a000000000000000000000000000000000b7b5ffa4d08175916fcc542660c85063e8420987b2e16ed2ef9464adf928a4c0b8e6d5dc870b4f00de8bbec6f0dbae3abf8de43c54ed59b936e1d55032eab5c9d9e04e83e4696d969c24167b4239f6200000000000000000000000000000000151e2e32203b03a054459fe391ff4a4e962ba5e10ff93a1592043ad968c9f968a6e50b5943e50815268a4abe055a1a4a0000000000000000000000000000000004bd116c6857c2f4efa087272df160b765dfdbb842a342f9cd3e5cff006030f32e5a8b60acd8a376378096743000b2fe95f59041329b6c3e6aef01d3410836852f79cc436fcf23199e0985c56f65c4f0000000000000000000000000000000000ab6c3210ca0b70b2b3bb916f31e17b8632513b15a99c7cc61cd21181152bfc6ba6ebaf8e96a05d0d2d42a9dd3b61a53000000000000000000000000000000001308a33fccdd6cc8990c21fe7ed03bca42e3ae24bf07aebfe6878c2c8316a7a52477c929fc7c67a3a13ed811a2adda7b740e4a207ab5dd4a0621fd65697f5d30b8ee1440a5f5c5e74a0dbc6b6391c1b00000000000000000000000000000000010db7de8485e5504211088ada8924386b36b7dee37170f73469bc77212d56c3dce9802c7599c83c5cc5b18883cca5845000000000000000000000000000000000ae8d817daba71325b57f81301c17f401a6870a13506de2a443602ed44b6b0824e6cb763ef556908f9b3f30010f86394f49a3f82d25c6e0d69207e6dff010d56f0d99b28fd986c5711878dcb6665b1f50000000000000000000000000000000000fc19f1ad220ef5bd76cdd7d3ca08539a97514bb21429af5b1774d4c58a7e4ae137505fc240dd0ec01d1a9eb06a157c0000000000000000000000000000000017ce712d74d68568a945fbe2e0b21c180c58e9297f1f4dbfb0775a133832d4d8aa0688f031385190324f1e8ed65bd5378390fa1b452f887ef3afc7129ad8ceb9a8397f7625c2b249d7442566814ae0a9", - "Expected": "0000000000000000000000000000000016cd97de498b8809f4de87bcd5a66c41c231653fdec9bc1ebae0ab3b8c56258430bb13bf400f5f971a1ec558ee66ef02000000000000000000000000000000000cf57701a5038ec26e4027c3cc5a8cc298c2d86e9425ae027dacea92d4d475130487b2743c64459990e88768d8b7a4e0", - "Name": "matter_g1_multiexp_62", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016fb67277c28b5665f1b7aaeb1bd70f679b507a6b30f956a1fdc0d522e430cb4a9c089093cfd14714f25cc9498f89b610000000000000000000000000000000018ddf06c643bd77c953a0bde77e80e77334410d76910dfb587922e6dff23e821ebbee2dd546e65591726f9743defaf9a414ca9894bc15e6bca798544138689b2471f8171a5dc48eccfa36c83af142b7d0000000000000000000000000000000011d630f01000c6e1279f330893a18b903b7246031d7d05d80d4172b08e1da182594cd42934de3d1418445a76bc9c8189000000000000000000000000000000000c3e335aba4402bd3c711569e466293c15d89f4893ba91d8690e4eaf4c7962da458471e8c7f22c417abec313c2fd223399eac8ce85a1bc70c725a2f04aea3749d75d22c0df7c0755a5e76ab4d82ef942000000000000000000000000000000000c38e3a1c95f0faa10980976f83d85954813faea27c120fc3102de51096f6c3ce89fc4155c6fc878fbd18ffb32092d7800000000000000000000000000000000178d0c64b3b7da5b6f57c69bccbf73e329b18e29e9187a7af31b9b8e480b210dd36589540d77b3041472d9612b05693a49b25140d7967b0438e49f59a6b04b75bc8745b84d7350605be548c6b4b3aeee00000000000000000000000000000000146c5b46bb4194ec04b5b63f09e8066f24e350cc62fce016b8a25ae57877614162f2733a5df8909eeed2df30374004ba000000000000000000000000000000000cbb312823ea25bdbfc4afd00cb65748401b47ab7dbd5a40905162c1ea676268745af11a2770509eb74aad45663f7f5b6e30a51d55a1ac94089d0f3217c3a2182da6b02ce70ce7dd8e2d4e938bfefa9d000000000000000000000000000000000ef489c4443175873e33111e9ebb3140ca0796f13ce8d34b30d8fcb7b9130ea0574754e800fa0ad15d71c35a3584e11e0000000000000000000000000000000018bd8ba66d5b67537a03030f5ae56c01e640021ec2524a2cb4b2005ba267e737d27916dde1e94d1f15b6d3e1d480ad82d3da3db6492ff36102747d9d663bc6e9cf8f75b1cf77044989c7af3f11d66ae700000000000000000000000000000000182acbf5e02a0b1344779f7ced01961f418fa8ce94f939025110823e5d5116d771328362498324e1067a3419062341aa00000000000000000000000000000000174d3a7754b18715722a07ecff5ee3b7f30606c3c573770c88703b6e0abd9ff4aa4bd2879c4c0512f879af95554f47316de8753f3df8be42b6d6ab578096426f852de4ff545d2e4ac12c3943b044b43800000000000000000000000000000000178c3a28f9333be85ff364329fe897660261092d9bddb36687cdbf5a7a450f27060a3aceaf45fb8acfd123116f195d8c0000000000000000000000000000000015e0a930af79ad263b115dc733560752cbc4453f111550fe3e9448b6818a75babbd0044b9b4f133bcbf16f8fb7586055a28f7ef4b12c5097a15fa6394a4dcc3ceed6cf3c6240ec2ac949bc21a9f6447f0000000000000000000000000000000007fbd9b191af6a797c68ca85df2100b898e3a4d9569c717e3d02c259eb4dff3a1ea948e56001f33a3ee1c74eb966b6260000000000000000000000000000000003b892510d5073bc3597f8f513908077814a7efda2df6051c08f7347433703496e522d70ad4093f76a3e5288044ba5dca3d0eff3368b10d00566f35391bf43c9d204a4444b7eb91017f1b2d8a762d90c0000000000000000000000000000000015d26d3ee6fc5f98584c206466d2c1a4323f597e0ad665b289e76184770e81856482c9f45ff8c891622d8de353b172e80000000000000000000000000000000017fe0582d363a30677bca1feb6d7f16be6b07d6e5d6b2a2080d07ca306d5cf733103f20403ceb486ec703277804e7971b90d76e660389e570bef756e9785e39b9748aecd7a34556bac8399aa5564d12d00000000000000000000000000000000108de390a69c6001124820072eb5d9ed9eb5b5a6199c33db1ab0239c447e009df4296f5324660e7ea1133df0c8e6a9de00000000000000000000000000000000040e7b3392a116c7289644f393bfb24d84b76d8378c042d86cb4af861af42374b709cb0ff5341e3ae9d21271c32c0a5914f18dae096e4de75de3da284a5755efe51e912e180020a20adf1f5de43cb5180000000000000000000000000000000001ed57bfdd0542efe8734b0af448c025eba4d60053b7b45baf682cd310f4c2ea07e708bccaed390c2b061c89c2855c9e000000000000000000000000000000001496190ccfc4bf428706ac344ed691fbcc7b9d6a456f2653f0da421a44653d4b1e9e967954b847a4e6014df15ef48719e32d4645ce0172000fd74f30937261de89753caa716dd03a8b3269747f2349a100000000000000000000000000000000147e5056444c7ea97a319bc71a3ee4188f68b517b92c64f556d22382389c5bab95110728cbb7d525499cc3b2d70541b1000000000000000000000000000000000f05b91c8d05b31ef6497595ecee6a6766f03a006b4c2da408f4d7b7601915cef64be69735c269007fa23e5f91fb07148c8722e3e929ba21f1ed6c51fe5ad4940fb13d63e0293893135d0da5e6e038930000000000000000000000000000000011b1b7c28754f3dc8b21dc823fe02d617374bdb9b96dbca572eaf8897f98ce9409ce8a63eafcf5308d8236bc3c18b4960000000000000000000000000000000012360ef03ee4dbf0bad68232b8454a26b666d827bebac03da314b2631a45cd365248316f72e991004d0158f89ba5811839bef6ccc893f6eed62e68f5f2a07812f2d3066b89653431e7e39e8596bc36520000000000000000000000000000000008b563f6f97fee7e2852b44d8e39ca314963b517116733924d2f57d9c4f202b47fb3fdb85fbca42ffedcee290050ef0f0000000000000000000000000000000016112f264c2b3c838b02b78822d27f6351860d10da3ccb763c1650420bf22755938cb45c7566a2df0e4aea4f0281262ac395ba8f2553e3eced8a42b221a710a5cd2a5ffe5834d3084dc260ae0f51698e000000000000000000000000000000000a8397b009cac789cfd496f4f1237e92ae570f67b4bfe7e8c80171bb9d9cb53201c2ce112473b74646a4948d7c10c338000000000000000000000000000000000092b7425031fc7c328e3be114916a06305b62ffec8e7e93a591fc5f4f9022333cc664057ff6983677cfb998defe249553ef5568a766b6c39854ba059f3130b75d7fd870bfac2b00b626e2d71c4968e1000000000000000000000000000000000df6739202d9f1f13145b697d5b78ccb84845710923a0f3bfd5a3f337e200b3ce5390aa185ddbbe8088462926a7f4b40000000000000000000000000000000000d00ec3648b2e5790ca7b05ff32c6bd3249296bd693f520f6d8385f15dbaa9f808d770f9ba28efdc4aa6bcf862c17c4abadefc3880ca8dcff10b8b763f7d15f88965c2261b72ba879e3540a90c59effa", - "Expected": "0000000000000000000000000000000002665808cfac4b9befb1f285c590d639132adf9d36a4fd460de0b3347303aa056a14780deaaa02072fbb08e1dea06b940000000000000000000000000000000001ef22acce32662085c53b2080df9354903f151089faffa43c5f6a1a306d2254fad240bb1ba3dba4927ea5640347bac4", - "Name": "matter_g1_multiexp_63", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000194b906ed067bab0e26b9ff4c0ecd909c6aa23b5cab3a90d1761840b784bd2af6e9f9ca570ba6643d4781885553f3e4b000000000000000000000000000000000e8a480cf75e20cceb6e1d9db5594d19849aee6d45bb3ca7c0311bfbff8263420e0278b7e814088abb69e73bab6368a92c1a5abbddc02f453519563d6b6e05959d8de5feb493f7c58ea5e548cfec2df60000000000000000000000000000000019ab570a48bf15ce6f007b528d7113cf423e1c04d9af9497dac47a69deaff52dc9fc4d202649fced07378b84fa1b0054000000000000000000000000000000000e3c2971aefe89a629600a243c7967ef001ee17f9ac452a8131ea44815ecb6596f4fca4f47a316f62234851dc485fc50b406eb0c097237556228f3a48b7e770c1707fd583b91b4b6b70f398b7dbb0d3c0000000000000000000000000000000001250315bb81e9ef7de73e709f18003018fc1c55f694c0e28152fdb244b07dd2d7812c3ecc4ba362fdda0707d02d697b00000000000000000000000000000000188a852c5850f471d4ed207d5782518f189cd08d63279c4cf19c76122df0e4663217f1cc8374c7a02d99bf6d59a80457ccc30cf1db4c6be6dbc5830ee37b5782c6dad215334163a9d9e4deb962186f80000000000000000000000000000000000df12b5c659c17c808d8e875a1b9c125396cdc3d8a2bd6f99def15d9fdd1fc7fcbb309333cce1b778612d6114bba63b500000000000000000000000000000000019f11577152bcb0229e168a8e97804e8e00a58fc236c8ae59c575c07d6a3c1864b7c8132f245aeec55d999d54745cab99461c0f12019b344a7f322900b64fe81e0d8a052c0ff5e977f58753b1b6edc60000000000000000000000000000000004b007a33b0ddefa5ca9379614f698dbdbbfc6bf8bedaa485dc360cc759ffa4ace304fc64071e8f228a8882d5bbdce22000000000000000000000000000000000927e9f018b8cbc2f21b72f0f19994705197d4b6ab3f03e231e51b9cb3d899fd8f8b71feadf3c9be61994936535c61e8338ef9fa825e47b46483ed8fd2df64bc7b56da8aecbae704b7eff2e7d426f27d0000000000000000000000000000000005decc41dadef7dc4ebd8911af09974686531907e41dfa16c857fc3a2451b96069d06ce1159d47e6f1c97cdd932486d4000000000000000000000000000000000151d369a147cae5d78eaf7ed99623675491f20aa2cec9700053f853551208fa21e085962342072c96d79233bacc7adc1dd6656a34f3b12e5568b9c348fbf4ecf50d65a89e63ec0936591f01e6cc7a4a000000000000000000000000000000000fd41ed8d5b7e5ca6a6feae98592217dbe676accaf6e73062d9de9eced8af59563f7f441a50ffbb591b8a987c47988f80000000000000000000000000000000001199e002504726f2ce429cdb3da304f9b54a933c1937e8dc39a3a416d068cf46f411b207d9c6862a50962516b2867ea5202f32528e795e0fbe6deb4ef6e45efc70019520b01fa1d71d5505e42faa69a0000000000000000000000000000000017cc9741662834dcee7af988d3e4de2c30d4f9e90f2b3f7ad07f756acc793c58acb2a04c2726129d0f0c959f1d3154650000000000000000000000000000000008052061afea4c307df56a72530effa73b34beea4d731b1562de1e985ef455d39b0d6c57008ec092241262dd611ec598a2b39f2b893be03ab4da77ed518ef35b2e24278d707a20b67ab4d1e5972f97220000000000000000000000000000000019adb959f4807d3bf7e0616a8a3c02e9babc94b8ee9f8898f2ddbc8fed7a5bd88e83c70c5a98afa823a0f46560e32198000000000000000000000000000000001189adca458e0ef67fc686b5a94986be37c414cffcea5b4fd44430c8d5902512d84200007a93104048160ca3f5bbb9a8892eb7c361f05e114a645caffce9437b7b43fa01dd66c1e75b30f3abd0209bcf0000000000000000000000000000000013d55a4b466ddafa04c5690628dc29deb0ae9115a4549767b2aa22b8aa02a13f1db82dc86fa3df85a6a15463fb0e7903000000000000000000000000000000001488a03340fadc9e8f7552273699870ad444ea513cc7bb91259ffa7cdd5e7377d8fb5510adc2502fb8124d7914af85d5fdafc3f57d6116163f1da9e70ea645243c5911cc4ad4a969a57c46c6b5c73acf000000000000000000000000000000000a847c98ccbccdec67192529c3da593f1d6de5d7dc0bf4452e4f09e93c2c406d6eaea30431ba95568c92938150a00a05000000000000000000000000000000001201397edaef2f9b89dba7f67b22088cb954f95b9db3d1c11bd77aa0dc94def6283af2866a64f0028fdd87b587669f31660a77b2be50eb72fd108644d913b9253209972fdec2d107213ba47357c96e9e00000000000000000000000000000000017f76412c8e679676eb464204348d591221ba17a1c90a22b2482991deee6b61edd7520ed10b0105426a15fa3282cbff000000000000000000000000000000000c65a821d170a9726e947868d861717e8cbcd2438e4d4b8ffcee38eaf033f8f3a57af68ab6314a52952a305db54ecb361ca575cca348dee9adfe68f8a78d39bb998205da2a5285c12141a77ee7af84090000000000000000000000000000000000b14fc1d34bd7d85fa96a4d12ee99a6d327347dc63608f94bd750e2096dcf11066e384ba3c68610c70dabae795e668c0000000000000000000000000000000004f3ac3e885cadfaa565b1ec15cb81e3fd4d561b2a8d92a9287bd0de893563676118d34a9ef3bb3112aa534605219feb2e1e4537f855eb478274992cba4e3f50fd9e944f6246cd52dd1517b55bd7f71f000000000000000000000000000000000979231339f20ffaa38ed21cfcef923fc9a4ff77f7d6fb4df212a530ff456a32f50a77d2e7f6d87c4a58270c006e68070000000000000000000000000000000011ff95871a91385ffeafd8a609a0c562bbeba71a110081e5db6c8035d8176067a528f4d1c6d7dad43b3bb8d090077e1357f9a729aa01c8bf0271052202a077913a9e0c87201a367845f9b271c130e95d000000000000000000000000000000000e2c7c67fd50bd2cc8ab18808a69d62bc2d3f110ef49a02259163f8fb152da6ca9cc771d1221d7719f9bc349e68594120000000000000000000000000000000008393769453eec7639d66525d6e875bbde7a4a28c434c82571468d496c4313e12414f929139c482569c003a6c0dccadf3017593cf311989ed8fedff72bb1f14f72cfe5bb7446ace5274d8ded54c1372f0000000000000000000000000000000012cfa8448935a292911ae6fc175f3049eae5e30d714b3439f55be9970ca959f218157097bf9837125bc8f772968b0d52000000000000000000000000000000001747193c5402daffffe4b1ba9034231321d01966befa174f526014d6c27fe3683eedefea8690b95c8f71fef1152929bd08bbe9e7a307e380c238ec1f8e2010a95fff8b03923ecd9b012f99e56c77a5cd", - "Expected": "000000000000000000000000000000000bedee9e836b3e046bba7fca7632d09a5a25fe1f0fd25cc6ae1d1e07d98ec52742a60bf346285488dc84b2360e0db58900000000000000000000000000000000071ef77988eea20a38fe33564689a39a7113b1715dddc1b212c6edab6bdea8de54089eb7b49b63296792bb2f4aa68733", - "Name": "matter_g1_multiexp_64", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000b7db363585b0061a4707a2ee67d6d7220e9209b4eb9a59c02aa6e177c948057826780f292dbdd824d67ca9f78864cb000000000000000000000000000000000a31f49bfddb5c48730e1cd429f128a540ff44b6a5031e7975ec0c6661f9f3f2b79ccd2d13cc1b50d50ef9c7f658d412cc5e9d01f6ea67dc3f943d57d9d8b5791d823592f7fae6719804c1ca097e651d000000000000000000000000000000000d4fb266e9fb18590037394b18971cad5840bf89047dc11e52c90284642be7e27007c62a1e331a2f90ae67313efcbc0000000000000000000000000000000000047b518cd6a7d7c4d262d1f9f5f11480e30c626d45fee2d6caa274aa1353035a3c42ba96b5875de36442aa5d4b92d6d257b8fcb85e4dbc1969805d814e75b2b80f5cd1e5562bfc1e28becf731aadfc58000000000000000000000000000000000cdc9bca5cc807710948d5189dfadca2cdfa6fca5496234f13024efd84a37070a2fd51a609c4ed6aab54f8687ac9700200000000000000000000000000000000011bc450e4222090603ccfaf7c1dee67bbd59aadafc3810d3aaa8362fe43f48952320e25bebef482c5d21a541400df5a03edc53ced9ec5d7f302216fd30a81c3554a3fd04994f62b5e3da74c8b71bb870000000000000000000000000000000000015d20abf274edf0c9d45c2675e4af7987e98005b2a0d128ba7df6b16b88784a7134d37d0da2da02557f88d26de33f00000000000000000000000000000000190adb20cb0f5902f7e92f79dd6e7d214eb892834611ef222e9a80ade4c7cf96e0b5f9382b61715e1701c7e9cc4f4ba5976568ab779e335b8dc67a64f15b947e69cd3896ff393f51fbd3c3e3a157543f0000000000000000000000000000000017dcf175327086e058e4696d689f2e8a167aca5616f2317b7673850a2272fd5742b70eb362b37874d573cfefa25ce3ce000000000000000000000000000000000e5e1af08f6174641aaf4f1584ac40d53c393314dcb1c405263e8689558445196371e2858a4f44d605550fe0f15962223aa5eeded490a17b1cfa66d409811741643b7beacf312b9d6c8e7e7e63579c830000000000000000000000000000000008456d980ecc64b04a203d61bdb78bad67b4568b2dd9a123634cefbd7f7077cd9a4c038c0aa3654915c12242dc594b37000000000000000000000000000000000adbd582b0a8ac28ab21961476e163255089c2d362bfe9daa7007a2c9d8d261593eab22a6bdaa9740da81efaa24cc3d5f9f1f9313bf966ea3b8f09bbe9dcb66a7f9e3e94e2024c49a72ccbbe03fe4662000000000000000000000000000000000b02d326ecb5c04ccea4cc3d29f82117f3d97f788b8e70cbb346d43d27e674540c7a94d242d290e55d992eebac546c9b0000000000000000000000000000000013901f8dd68285d73093c30b37419ef8e4b28371474a040a2ea293f7274ec4d6ced0f32686405205324740884306e3a693be64fc3763d06111961bb208a2b858aa1ff181781dda630ca41f0d45ef2a9000000000000000000000000000000000181bf2fe4bc67a1d10335a0ca9427f603610646de485a7cf039f0706c0a0858ea694db3b3e5ca85317c98b5cd75865420000000000000000000000000000000014b1b652e2ec7d05956705f692860b83713c5cc98c6532b3df50259f27f92d485e8df846883a4af4e46020ae54038d955d2a2b6008a3b4a4cb3a8c28864214c7fbe154fedab1f9ff8c96eab6a5f28fd3000000000000000000000000000000001084f77ef23ac990b43363db38d652f0e6dc04a4bc395c8018083fae6fa6e42f463af7748d71f65b14f94632ca0eaaae0000000000000000000000000000000004ebfd75ecc9cea5e49082e1adacf6b50e4f14600d9343f6459900605c5f36ee51e95408a3005c0c1093e41794c282a0854e742ef7c76ad438cbf30c30103741f57ebbcdca4d6c4f14e554dd1ed81b2400000000000000000000000000000000062a062d2ccf5c131e1278a63e713ebcf8a221e429b52b3a7688f7e68a12558fd0f584e03835daa3988233d6a84010310000000000000000000000000000000013e9330d29635892fbe0742d1a8c96ef527b78ae389385a366b6dcc6a04b8cd1d5b8bbb79ea649179e78fc061d23cafd6f4f00b2494a32844e01d0827ca78b06f5eb40b6769f36a04f20eea229c305f9000000000000000000000000000000000b131e0623b7f30bad70145cc4964257053f2ead992d28aa5b24c04bc316d479d077af0ff409cd395a86b808bd3e4f02000000000000000000000000000000000380fe6e79e5e0a399365d73244f2962facda8b7b381c111508819309ec5b1d3d8783067245dca26641a966969dcd0ab191e47a0b0c72bd17319063abde7df51498cf0c980c46946bf80ae4c9864e2e20000000000000000000000000000000014971f46efae601309f3d16c15ab5c46ac48d2199431fd959cbf4efb768ebcc4f410fd66de04d3280659004a6b54e64700000000000000000000000000000000113e6438dd8088e73eed84d24ec286a45ca51f0fda88c7ae3f1e6a2195f6b11877e606773bb9a8db19dc92c3b0729754b7baf8816db56c0a602cfb4caa9089136ebde05722ad4838671e45ada5c716f20000000000000000000000000000000006fceb59d8baea4a10aa9f1e825631e28bdd379189eb464a3c6d2482319a09337a78173f9207a58ce15bb1c518b39328000000000000000000000000000000001609e1ff34ad2e4bea4cfc4a993d8d52a1a8676679c91544ded432adfd7fdb5c016f8d825af1c6b8207170d05c10e04a7d9ac1699117bb9b8b90e2fb709eff4ea0f7882bdf6acc6885c9458703cbfb3500000000000000000000000000000000069e48b113b822cdfc02f2f0efa02724193a5f032dea902b189290db91c6e4550fb33e2915eaa8e56ef329d6c61a0d95000000000000000000000000000000001426fa2fe7c160e8e32c3252383a7c7967b3515c3f76eeefaa5c76f02b3308d86ab95f9a3a0dfacfa6dc12eed2f3a5e8a22b6c1a24eff71f0fc64b6aee8d3d2dd0827756f5c959f68f1216c2dea58503000000000000000000000000000000000c173c6c949a7f21df4431025ce16c18b1008c75b8b1b23d03122c7c6ef714b5741804ec7aa5ac40f6b72a1a74ca5c340000000000000000000000000000000001b32d54f8f9839dc39e08bc6a5f0efc5db9bdf487a60004ee135c30efda577d187d9b9e68bdcdad558f2028d66e935cc0431e6877166686239f014008959332d9d009a801be6a1e68c2de52ee264bfc00000000000000000000000000000000037d1cbe4534b82ee79b2c957a6eb19d18dd3f3f6faf3313b0ce12a98953190aeb55f9d494bbac4f56ca6986c65f7668000000000000000000000000000000000734f505be94516149bcd6302a2c9f2f9b952c9e614c8e90b5466073a7e734ca203fcca242cb97abe1c532d7f59a783aaf833a784d22b99537236fb07ab7b59918783e35b89fc9692d7f76a03e024c94", - "Expected": "0000000000000000000000000000000012de1cacd791ab81eb49d2e259f36abfd90e8c7ed4f9f23a4c95cb48cc7bf9df233951291342d1266d016a7fcc6b9d53000000000000000000000000000000001938d574d02b8802a45ddf8488340f2397e93125678400cfbd8e64cc3805704bd5f85f8fb2f64a96ec1089b03d9d1c24", - "Name": "matter_g1_multiexp_65", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017387ec261c6dea7bbcaf4537182de1620adaa5842cf52c8b5b6cd851ca3c27abafa584547db7366455281d82d3f83ea000000000000000000000000000000000246dc1cc9773db7151e05d131398146b28850e97f6b13694d696be374095fb153b206723afcafddd4b3b56bb15bf778b16c1bc60e1a9be9a82c93b7e0311e7516a57d687d8907599918df77b3b6caf3000000000000000000000000000000000a909dad5029834df0202c298a577f897a376b205812d79e0bb58b91ca11262a766dc396f69fd2b199dbfa52670515ea0000000000000000000000000000000003737873dec25f011b24543071a61590646e4319a2128eed87d40193a22c47b1a6c0f807ba3115a7e45823e5a4bb433dcf301dfca76a83c70552c9cbc9c80cb20f0d82a70a9d887b04b150fa0764ce2e0000000000000000000000000000000002b959df6a1badcd306209c1f3c4c496cbfe4f00995cb4403b04ffa6b9f2c8dd9875a2747354a653a74fbb605eea50b00000000000000000000000000000000004d6b15939c8e282a5995c8c0b67fcba3171b35ecc039fcf32d1e96671698d8a9fd2cbcaa7019cfd01e56d68cac64fe51cfb94c4e029a2126a9cf5561c677687f52059e4b7f8b7e7e73e5b1dd7f421290000000000000000000000000000000006be65e97560a40394d9295fac0029a0c889bf803f09926359a1ac40deb7777cea7dc5d2c4a9600328605fb994f87b5600000000000000000000000000000000128249d2137f7ab1c5622a8eb1c59ee8ed792fe6b09e4d868c9d9ba900a8d28bde5b783ca591f79e1d729c99e10d5cf6d8386fe6f4303959e58165b422e98c4813b1bad7808594473e4e66df09698cf00000000000000000000000000000000002244c1e55324a4aeaa07c414cd3f9872290e729c1cf1c05a5b1de3443e12b2335cd36f0e84f11f04b62af37005ce0ad00000000000000000000000000000000151684aed084d38aba7127434ea73e63219c4f5b4b92017142d19d0330417fb2806e31440e0bb7c9fca2bc8dec73072f02e1c432f3b55ae87ab815647f196be3e138b2f6e9fe7acb9459650246187eb90000000000000000000000000000000009f0c959d995af6cd0d45750cb35a28461d0f791e59b2975ba4edbd7db015858b41b3b7c5c2da0a4c6a5d7b4e855329d0000000000000000000000000000000012d495ae3096c2399149afd00f640f8840c3f8e5dda5835b62ef0dd8bb7303f522692efa72c37190bf6808ed3d4fe8e89b0cc0ac499dffd627f5d19b87817dcd67e87561d5244a4b5698265f8c5b767e000000000000000000000000000000000334cef31670360b5ac7550b55cb03b770660ee79816a2742c059b2ed6cd9d5c53c5ca54793a9912ddd7603d975c3f58000000000000000000000000000000000144f221db562b0daefb20238a527a10ff1ccc279eda86723668f8ada40b41a2825f82f5ee5d619fb193b9c2b4180d932f3875f81fd39c9b3ec74eb269903dba4173d8eb0e41a196d3131252207ffa0400000000000000000000000000000000037f14fb2d51b25cc04768d50fe26c1e156a3478b80e32da980f7e8d5692a4cf282f75e5d8be325ccb4223c7ec2c04af0000000000000000000000000000000004eaf2c069c96dcf18051a2c1d7ea876af67bf344070415894c07b3dd69330d8ca18e1313ff57d83b70e5cda3c9ea8582d8d4341822dba68c6fd58cfebd07b134c1d0c4e32ff63f7d59addff4df1ec3200000000000000000000000000000000104c1f5bdf874c91020d410d8fe74834cf15f341b86e66ac693003766484cffaef2c57fab5888f02f5ebfe1b9ef2fffd0000000000000000000000000000000014a2f6d185c2989ecbb766179c0b0d0713ea9714da2ac555bebf0522ff00766ea7e39c8237f8515224fd096d2b1ede34efa3dab1d7cdf949bd938ca6ac371f953b3bbef1aec7ae76bda37db4c940b3d80000000000000000000000000000000003ebae6a494d46ade2dc7d4630a420b519df7086b57a33da178616d4242fc20e4d02d38b5d00675d2cfdb51adc1921f6000000000000000000000000000000000edc56e6eb4aa8556225d928408702042d49cf3e1410e1c78d8ed5832ecae449d17c9d8f2a89ffbfaf01bfcc85ebc1669848d3c53632dc461619c8c522013b83550ef3dc7fda197ba37c9cfe4340f5a50000000000000000000000000000000000f96864832e7a9602196f0abba78f456300796d5afc18b0ff0c5c23b61865256fe5cfb960bcc8f73231c21b1084cf04000000000000000000000000000000000c59dcca2249b5b01c1b54be0e4114ae8228bc150e5ac7593bdf96136cd7cdd7562eb936ddc5c9e42bd93abe91bac5b0cbfd192e917f2e0c4d6253c4e4755f30812149d1ce1ee4ae5540faf1dbfbc13a000000000000000000000000000000000422c390e56fa27e3d7d5da1b2ef00a29d5340026becefc095d4cfe830208d3b94cbf5ae6f4506ae45d04764acc8044c000000000000000000000000000000000d1cc7c147cbedefa854fb9764352a9689fd157cb2540fe070ad7f6f3eaf761b4670ab9334de4002fa811aa7a01aaad479eaf11b3a30c7771ce63cec214416d798de20432670280d997b2f0631007d6300000000000000000000000000000000018000e31f0ca43417865a1cc128f33383106f5bea71015e9e77cc5320cc3e5704e437ae8d84d96f2c4530c41bfad29b0000000000000000000000000000000011a74c3779c8f351d39db6745210972f4f299009afff643e944f30dbc4367e17271c688e1858e6f79b6636787fa56e6b43077447b67f65e16a8aeb3564b2d13822e478dfb4a82a15a1c8fb7cc8170cc90000000000000000000000000000000002a6c7367526da989ae093350b7c1ee9013f977d6e75563f996e1f15cd4279932a3e4060a26262f27403966a7e0111f200000000000000000000000000000000038a85281b09e5e68d7e31bfc323c9c250b42248cbae47f9c018d72f3e69ec572779d7f8fc6ed3f027499741565274e5eb64479b496c17d0587f6f26c62752881b6a9228643e8c43f21c441eeb643107000000000000000000000000000000000b788a0d47da0daa1f0d802d340e68f9bdb5ddf91875732b4ae82f1a89ebb5787ec1c9f539b82e3c94c36a5df4ddb4ad0000000000000000000000000000000016f46ff55e9f1e19a332ba4ba43d66d2a11a2728a484a719ddfc9e223b54224db55af162e73a8f5c3355f0127a6b7cb652b42f75aebdad1bf433917c025800c4f4e985cc077db3ba36f7484f95764e89000000000000000000000000000000000379d868d91304b24e19694937402bb685f064ec5a89b49e243e2ab7eff5ca0a2023af9828c4ce9f768a1d6488c10e110000000000000000000000000000000011a9b9432ab253d47e8dff776c8b5810ecf7f7aae2ff36ce06b87436b4e20c22596c7713def3886549a36bb535a96fd1e83106e9ea63791eb192e7a035bee27bd049b3a37f080076146eeeea6a769384", - "Expected": "0000000000000000000000000000000001a50ddc4d4542aae264dce69f5f5e93353a9eba30b177b33c2f74ef61149a301599beecc4d0f78078dbb9638eea526200000000000000000000000000000000160a2fd67df885232b06d3dead7ffca93cf0434a3e9a5412ed3b4c342819b44aad5385bf5ab60bc2b7191722d1372183", - "Name": "matter_g1_multiexp_66", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008788a699276abcc2d8e4a35a9d0ddcbd8006a809799374ffd56ee8afa1a89461602d92fae6eba7fdd4045ba34d917e5000000000000000000000000000000000c8e03ca0da00c6829e2d7c49360e67e46ce12e0c99cb3d957119bd9c8bcac8e03cf32ec71db2a18568157f4b44cd4dca4d710d2f632e3ed0ef69fa0219e16ba30d3efee99386f1a5c921f4548ebf64b0000000000000000000000000000000001373b4a0653f48c205b36bc50541a43abfcf35974a584953bbc40f5cabdc3ac2047bb86267cdad1e8f00766682d2e6f000000000000000000000000000000000faa8c977b4db7a3c9e65d9cd5af4ffd2d7d67fb038d92c1096124312a98d94e6dc3f3b8de73eeb057cdeec4bc0e0482bd9ae4597aaf582857b40096360ced0f044ea172551c6f9fe3a15e0ce290b56b0000000000000000000000000000000012dddf5b96d0dfd2fd619b634b086ba5d5f25a53e93938559a7adef7b988749ca27d14f2ddbf5a9e7e6c1914403a45b900000000000000000000000000000000044b5c8041fa805cf2ec5a243814308369e5af534729cc9608fd17583a48132809f507cdb5b76fd6597fcababa865ddaefbcb4bad99b419820eec388f6f62ac8d87866d7beae6d431dfa48d4243b4a4b0000000000000000000000000000000017c5807458fbb875593ebfe83c49ac2493ddaa15671a59032528e0464360c64bf564f9727959108940ccbdb8d01f329e00000000000000000000000000000000121dcb798111976daed483f4efc95f968f5212cdfaaf0497eab0419a1b55c7ee4e2ea26716d0c1a8aded4804228b8ad860d89acf5b49fd1f70fc54756c4bc1972cd8818e36efc37b422ba6a9318fa134000000000000000000000000000000000717296a20594f940a05ed3ce4bf2b7779c428b33a297087e08b2283b33228a7d4d5b9c49a71ce036d6f2a078d8344540000000000000000000000000000000000fc78f64a461fb66ca081ff4d67369058e57e5ae0e284562161fc3244bae0b9c70ea6abb2d0da6cea4942530c64ea0e386af376b9b393dde994da419d1f7aab60023546647f7b069ede939386bd6ee8000000000000000000000000000000000584bbc0c537e7f37ee64604a134d5fc21d838c51a89c608ff9e3684357ed7f931fbd4fa4a5a56d20304d6f6f072316600000000000000000000000000000000191ea3bf1016b6402dca2856845017dc49c74d06bc3c5f10de379e04302c469015f205cfc97fa142727ba7e2439c15575ffca78eea65c00e1128f8dcfc96b39af1c4472b461ba5262307003bc972023d000000000000000000000000000000000f1ff007860ac58bb04d992d639a5f882c3c647e76e2d6d96888a55648f81ad8b7edb3dc2b0e56b6f2dadca73db7cbda000000000000000000000000000000000fbb952eff64505e02e0ab34875d7a79c72ab724cea7cd8f28df2578b50f78601b9a9eb4170e1b7e8d94d9db252e23c592837b4314e63ef5a153ea2ec4bd373cc3cecfa3e892c3a12aaac8ddcaf5905c00000000000000000000000000000000011dad65f38b4c24527ce87f8893c8331a32a3d058cddcdec9f8708a3bd1e31871cbdcf944ec14d5f101b8d138b2a46c0000000000000000000000000000000012a6981c5100177e643dc421c5917896455107c5995b1e969bb18b4b2752700a18281f732530af9684db180290dcb138127ef2309c699a3602b0d86a070baef0eef90f539aac3cb6ff42cb19f284bd99000000000000000000000000000000000bb4dccab7abf3f5393a338a3a07fc20d337ba2ec3b33227e8c9a832900f347d582d88cab123dab489daf471191538b20000000000000000000000000000000008589985e2952db000968a793cc0fb5bd1764ab1ecdc6f278a11dd4a1de87823016e14e9fdd682e6c489192b154cb997ba0f9a93c2fe35877ddccee5da39ce5ae60a6a19e72481319e3b3fa2eac6148900000000000000000000000000000000056fd39f2a5356870a3ebfedf35769710c16b2f2eb4a061c936f6de4f9001990769795b1c756d7c67623ce3931ea1b5a000000000000000000000000000000000b7fcba295d34fc38739c4b36689653731fa46e6029bf8e38ccb6af5ae08ffc09c86abe0de62230844a66cbde876f52663da2f227d636f10e814e360c2156e686e26ce3401dfd15f47c4ed277d05353f000000000000000000000000000000000039b08e7110b0d17c41709378f75844379c662f7f3dc480bead6bd4996de2d8889f458aabca142d50ba0e34c0c327970000000000000000000000000000000013363b0da7c7dd343ffcf6cc5e9ddb5b51480b04a472c38f90ee08cc97507f5dd665e15a160860c6df4dfec154c1504bef79e3b6ce752d140c3dfb2007a08221d989038c921efff3bc4e150a6155a33e00000000000000000000000000000000034edf693e1b201be14c496860d508d12d9180b62cf3bd2407b8ff95b93da67dc0c4c43344614dfed516d7828ffda4b20000000000000000000000000000000015246f388664b1d817fd17831f85d84cdaf31212f093820835f201c3fe6ac99d67cdcfdda3c2d74d75d5114e32c65cd7bc08091af8b8c6ea5c26f1a7d795132521350d774042d3a8c0523e86fdd23a3f000000000000000000000000000000000982b8886abbfe18cfaf4c0e16c2e7045973f5efa27e5cdb56443a22f5434e2456cad041bba3e6deafb072e5fc40f10f0000000000000000000000000000000016a45f684caf0eec143cf8f31ed5111750d8c4f1092651a471cb88cf534e81df117e3b0e8238270d3b03aeedf04d7a9f70363101b87d685aa7314f6569fca0775bc6aaffabe136e6c336e8fa43dedb8a0000000000000000000000000000000016d13da2900e2b2ef8f6ae295bf16d100d451ac4709455c55323988c71ea6aef694de0fa5a33cdd7fa2512d3548e39a70000000000000000000000000000000005795677001cab950d1a7b802bb14f9203036f15fb335daa5f0b0ece4bcfcd3b31b581b439da46452e4e688f16685e37997ff3852cd97c3a65bce9083ff66197fd5c70894641195514d556102f091e88000000000000000000000000000000000b7d422ac85798cb5ef5548805bd6d3de20ada4994fc38355e92cbf0d0c9da356a5e9e1674a50a017643f652f71226e8000000000000000000000000000000001715616f53a501acbaaec470121caac29827b6b7bfd7e689d8e48822d2c464ae50158662e69c1c232ecd09f5ec946a7a5ff95dfa306f91196849d752569b35812e1db7946708cd06df9db9ee75447bc30000000000000000000000000000000010e7530ba600fa531878ad0f798a0ede2d025f149ca980bcdbb0e4316e8d2e7d2b248619369e36d21dfd766aba5918070000000000000000000000000000000000ecfa746f1cadbed34fc1ee3483307de400ded69af4a7dbb598802b7908495519b0cd4c1fa98c9cd8e82daf8b3e836e03c4308f0467520343825a91c0421f9c9c9d06957fa2fc051970f14085339e26", - "Expected": "0000000000000000000000000000000016bbc2dfb25ff6cb9cd03b0cc91f53c6ed9be933746d59e78c7251080856cf47c12bbecda442840675b03a812aaa5d98000000000000000000000000000000000555b0683640ef1795c918f5d10e8b3e07a09030fbf26eb34bebfbeac34e13c93ecf53d54dec5c8654cdedab2fd60570", - "Name": "matter_g1_multiexp_67", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f08b9765910d97ac42bc31d4b4c8bad5f3db3fe5374f11ae1c08af41ee226bbb4b0869b039fa81a935025de11b1d1fe000000000000000000000000000000000ea29999ba91652e2e6dfdf77595b44da8e5cddf2e3ae6c782dbf1f972717833d03478bb8651bc0cc7946d813371aaba2849fab097a4f71bdfcfaf435994a0c6ac3671a4a9ed0402010be83ff95228fd000000000000000000000000000000000997b39892bfe0c67c296135573975801ddb99d06de02d96853f44336fdaa25dcfe253708583f415d882115ec68dbaed000000000000000000000000000000000a88e2f75817ce91c7dbe365d67aca52186b5e94c735e5893bef6aabc61f015f854f9bd110d3201be6f35147f9f9b8fce6558521e301eabf09e80a509b46cf8ec118ee8586f4e46a7313a96dc37ba6990000000000000000000000000000000012a730eaf214a874448e654a06604c4b9218f163b979bd3700b7a7fa3856b814c380532afce59b6253344da5bffd684600000000000000000000000000000000182fb293f9a63c705501aa0ec7ca72698d7d4d50af3a0f68ee849cd3f82ac24aca2e2ee813f68e708991a97e58f2d03d8f2f7c525fc0f353700fa823a5d32a93189699206c5ba5ed271a158ebb47674b0000000000000000000000000000000015bbe08935721cc6199f9255379589a4512c178bbedf69c82a0d9cba22b285730d4f27a3629d92574b2c24dbe09300de0000000000000000000000000000000007aba01238f2c4ef0192fea78fbccf2e669f802a2822baf067632daadbc1d07e70095c14bae959a0f706092b0be10335c7e8adc0f0a042a32c733b5c3356cf4a7d648be51c1d78534ca65dd43a0c13e40000000000000000000000000000000011727d6d6cff667f5bdec92a3b502f9d9fbcded2ef12ac058ac51ccb4064443b7a2671e9ffa2fefd9b121d89bb4ded1e000000000000000000000000000000000960f8ac1e52246529fcc6f8f7cbaf42677297c00022d312e0deb5fc45d3685bb33fd68c193758258439864ba4a073e5650081a6720845a20164ef7c06ce1e73286a32dd64efbe57fe46765008dc9dd50000000000000000000000000000000014b3a9296c87b54f8f51b935a8d9ec0af44d711e3109e75fe34f07d0705e9ebf0ba5e81dd8b7e3c4b4f862570637a7f80000000000000000000000000000000005b834857b8629cdbf514e5ac2e0e2a45e4374c287bab5e4c163d669e7b1a36c72cec1ab7d857e28f2633a6e5f298f55c067d18b95591f7f14261f95513e1990f5a4f6908f94a015a93fe379726d5120000000000000000000000000000000000ad8c626ba39823a33d17a4f06cf17d29e9e0ae3f28db0b369fa0bb4b7343115fb3ded39862381822c3b2d74ab7f70e800000000000000000000000000000000117230d8da035f40c181b50c12370f159748955f63ee1eb61e8242e476575e9aaf16bd43b7e79a35ab4e2da20f43fd92b448bb01a1963bf74e0fbf99329005af8e932074358d855ff43c213e02bf26bd00000000000000000000000000000000027764a17af5328811b305c21b0fecc54a3f225eaaedbf453ea4c0724fdbd481873d84b1a7ffbdc7f1cb07c2d1efaf5c000000000000000000000000000000001090ec8d750ceecf682de76d4794f9a8bbbf3a3f4ab591fe882613c1b6db0912696974a1f2ce349bd8c79acb4891719d441fc4cb1ea8f86af8839aa40c35c0706f3a159b4bc902347009f744b73cee350000000000000000000000000000000015e707430eae84b75946f21e1fb0b6ede203b843671911923efd9674421a92ff13cd900bee1b27d70b8e8cbeccb165930000000000000000000000000000000001263ed28f531d8197606a038d7d7c3e1d732690cd69f52533470f6fbef193be5e63d5af0dee3aa8a73a23253533f8223020a1ab853ef2018976e43cce2724105a2526b28d23b0226c49ff3d4a03d40c0000000000000000000000000000000007fe70102db7df6529f732b5cc2b1caef0fe03af9824a5097922dc0b07e5ff32bc195fbdfd7b5e4b2bbcd75b1badc6ef0000000000000000000000000000000011b40afd78bb5e835227e5a08f94f7c70b06dc010f5a710a025f589521543eaff27d789d4de10fd4020879b45bc0a9dc82702398b8c95c3a8cd163a8a3cb2a7a04030ef99404c325115e9a9312e8c1bf000000000000000000000000000000000e4df86963d375710c681c5b3910fe79446e73e00613bd554ee20f47fa9e2b0cfb6c14a29ed6dab0a56c49708fc624d80000000000000000000000000000000010029bbd62162cbca140c56354ea070ae3f1028e438c70dce31e7bc8691541e59e9168e9b689c19d177d4fd68f8b1081338468a325384a9367c90bd0450816a22849b845aadaf187c27b3f09800e791b00000000000000000000000000000000097f3f61b164193da313d88429a4f34b0ef2f864ad8fdf7183c3e1da02dcbf0ddeba9bc04a7594516e6255ed59527e110000000000000000000000000000000008133f297b8da5dac5e1ac3db3073587b92a5d821949968c125e5c9c79a19b5945ab47fb0ce5d6f4269231596b157826d29136cbc4764346e7ae1af92fe64560f453821f96f32a42a2006b6edee7502100000000000000000000000000000000028cacc78001b805c3e43e92fb8c4477778ce81fca9068240e0088e344cc8201ed5bba52e7ee09d5ea6f982f30d6ea2e0000000000000000000000000000000012c5db0995324657574a27c48313674d2ad3aa931cee78ade96408c5e04e6f5f8eae88018511ff156bcc787970ec40ab675a59418f1462247d3bddda5937553e96d854b5df64a68145a193b2b1a7eb25000000000000000000000000000000001768f68b0ec15fdd37c3ad9445e53a582ab5546f9eeec590b84e11f5a72585eada71129d1b93a72b334bec4df57ea4c40000000000000000000000000000000004d6e137e66243b56bbaaac98717061b36545c1c3e24801e6e054bdaaa6d28d641821a51233175f5e5823b7d2b7b42cc544a345719b40f973398a6fdaa2044037cacd7f6c361921c62053cd51f2e5ff70000000000000000000000000000000008caba9658e420fa17950c995efd00447bd5074af9b57122240d4e709229d382e371d7de867005745a35a2a7d68fee8200000000000000000000000000000000072e0c25435616f157284b48fc8da4a3fdaefc4f6d484e071cbe648fedf30b5da4457852d7715741615317e21110d4c2bb38b4cd72eb18c3ac87860aa58b4b439712562f742f112b5d769415e9c19d0a0000000000000000000000000000000016c418a3b3f054188d6891ddadb19c00ec629a3ae0f49cb1b6801a9db0afb1b5e473c75cc8e9f352adf7ce8ac738ae0100000000000000000000000000000000110b8099a39e40541dab01e10314a0cc10fd2277c8766c7c73d32d7d0c6edd3ed3984c8bce249de4776920dfa28ee86994a849f6fb5a53bd5957e53ade1baee05702185b4d0fbb7c1cc0f46cb75614fc", - "Expected": "0000000000000000000000000000000011104fff0cde20e65e73185321d26defcbce9c9d3c27923a2366730c1b560da80066734c61e0c42bac1da45787f39e2500000000000000000000000000000000066efa830182669715da4dbafc6434be27a2e95140cb39738fa75cfba2b5786d27fd727df4e9b0195b49be2dcb9c2c1c", - "Name": "matter_g1_multiexp_68", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000188c13fde41e3c7d84ef3b5d1fa869dff4bf02cc8448ae49c6b72cc005bd06916a5d0a74fd770bbdd3d2c58839840095000000000000000000000000000000001637ed432b4ac6b5021aac0c9d5f084e1f6c541c101a3d650861f7d860572795f04e986c4a890ea0ec049da7c6025fa3f5b9d270fe31c772e9a0bb409d9f08a07887f045f906f30e2653d293b6c2c27700000000000000000000000000000000063a1afe2f64f1d04f7a5aa727cbd0e9dd9b66234120118db1f8fc3b90ae50cf493c3c4a48949441cc1e46488972d39e00000000000000000000000000000000049261c42dea531a6e8fd82f77605ad0cc9addb23e429f03f1aaf2fb8d9dddaa89101bd5b5b169dce793de9bcafc3b5ddcbf4fe86140c50618598be9185830bc1da11429162afe0528f00eb6698ec0880000000000000000000000000000000012ecb0f3bb6fbb4802479611a25781ab09c81ff7175170805ebadbc5f25d2c40bcaca855ece57f481160d49af008d2b3000000000000000000000000000000000bc4bccd65e010b69676d3c226057528dbe08271d65f83a918b06969c1d5303cb7383645fc19548eadb83649ecc54a551d7fb7121ef0baa85046567014620e1adfb9e8b3bc95adccbf2e0b0ea8f37c67000000000000000000000000000000000e3dfb86c2eefe0b25f117484a9d693702496124fd0dda80830a4e917bc418a793519dc269fd4932236f73506ecc949300000000000000000000000000000000140faa4b38ace6e80e5d3fdd57079c215792672ce651563eb013a90e66665dccf6bfc9f9df145d34894e3972eb524f86310d3b0535e78d803b477e5dc26c71bb18acfe66bd5ba5892d924d265afd6a160000000000000000000000000000000016e70554f8580b8e9c5e421c6a6495df7df846ad67d5d4334e9aa89f7e3fae505a2d335d21624e66aa542dccf38081e0000000000000000000000000000000001090383d5f42c056c291a4c4c6127315849c647783a556aba3dc41c52545549d67560bdd697fd1f47dace750483ec9b72fc9417e65cb76aa0093a7deb3d38c111c68f461a4aac57d8f09189f94407ee8000000000000000000000000000000000e8ba15ec58e5de08935384a3674418942311beff3887d7b5b81da0d03348791e4b17a06397e33e988ac6719f4d6f5c300000000000000000000000000000000159841665c915844ed85abdec0c1e78f178df2511da4d3be989f27063a8e572fe746b20e3aff056a63f4832d82a7cc75aa0b2d714aff175a0be2ba9e675a2be8936c42f15e304a146622a95dd6b3e3ef00000000000000000000000000000000167848a43b68c8f4c205613e1440f940735d7d44eb1b046e63ce50fe8d7acc5b2c020fa936d6e07347a7858be57870e5000000000000000000000000000000000aed7f9b7108aa4e7445be41bba256667ce7587a867b9b8ca70d3c42155521ea3bebbfe01bab038969721364eb758be10227c3510ed6e4c7f84b11ddd2d6caa55e0e79ed59e1cc0cb325d55b5d145aa8000000000000000000000000000000000699a81c47bcab8342b11a207af072cededbadd374aa79f6b401e4bd5d429a0443234522a8955b3a62a21ef6697410270000000000000000000000000000000008ec25a0e0dc6a3c8906a1b3413f522440d56f67fb780545fa022026c6faae016108cb6eb23d6d6d519a4aa790327ae6ad930000a9f82e082d408999b396aca2b0e435a66faba1d95e10fa0abc0625cc0000000000000000000000000000000009c2158ea44c3b590df30e15f97ebda263670c1bba0d97ceda7ea674af0e61f0b5928fe0bdcd8f18efe5340525259b4c0000000000000000000000000000000019a5534906413fdacde78ffb03e6564d8beaa155f86e4f19be2188854a8709e82d2ade21621934c1aef8be723ea91a141a6799cab8964c7b79b80e76be237ef49c2bdef5c99a38ea873af6e9d49790ec000000000000000000000000000000000165b15830a84e786d563cc3c5117a3e7dbe9dda178bafd225503467ea4c9aa894294c4fda58734eba9864796974a016000000000000000000000000000000001285a2be50f38fa6a068b75386d468d8fc1c11405291e794d5aa5157cc81d7d66c1095f2fd9289f1306f74596e9b5c21b206dbfd70e4b24bcc09ad35ce7b3aa62d17f18347f2bc5f15730202909c93770000000000000000000000000000000019d5819c1c4f10c83ca6f1596e6cf9901611c1407d6d7abab989333b37a8c21cc3deb039722a51e2dec161c38f3ce74200000000000000000000000000000000136d05ff33253260cbbfea0390e78cf66845afb4ddd0b684b928da017fbdf6b0e840431064e6e6d5bc8e417a74c811ab3a607a7301bb7dc5b9c82d956ebb0bc54568d0654d725d4d5f13ceb6231e862e000000000000000000000000000000000593e66a323cf3efa13fe19cde7a3c254c90b23bc836e1f437f4a4b85790f325f0746147aeb1d0447022bb138178bff50000000000000000000000000000000011a4b1222d0b49a27e66cd34a12f252296ecd1aeda435035f06c059aa3e6ba69acd1ae6d7da394f32ab78538f4e50a351231e0fbbc2d98bfd1039a889acac471110d568b0a24ddf5eb3501adcbaac6fa000000000000000000000000000000000613bef17f6b6b39f9f6bde785a82d2e4c368ef231d8cb89940059ac2c16bdd707170b660c0faef9e927ff7a72f6712e000000000000000000000000000000000fc85913ebe30f0af146df556c6984ab442b286fa70ee00d39a802f4c76c3e41cee68802982ea42fb25d4bb04593c0b5393c5c10d4bc4cd1567bca6960051f818e5c53704ce44dc4582767fef1092a870000000000000000000000000000000003da5997b7b3677f6cb03fe969e328549b1c0b083a6df457a70f1276d10e01d65feaa5a36cfad19dbe41cad9eba2fe73000000000000000000000000000000000345176bf6a03a49ae0b6d89d07548ed47dd67dd620e5e29066d09a00a7e3bd4b7fcb79b114a046dcc0c705068f71b50d412195e347b680430c4528987859a1552ba8383cdc075c437ef19db6eff6e1a00000000000000000000000000000000105ed7acf8c7c116842dc159553499aac7b8beb36dfd7eb717c571ad4ee1f86b82b736b72c2936925afdc3c739e0ad56000000000000000000000000000000000618b8fbf8a2aa2d1030c6304655b1df3cf8e8260b7b2d97639bd857d58606d0eceff7ff0fc1a811396552719407daee5b6701bc11c1ef3c9389710e4dd090e3db481c5400ecb91655c20694207a71f1000000000000000000000000000000000eabffb8ece92d4b22ee47560984b3efc33913953dcdf5e22771bb8db2cd8eceea21a2b14d70b1d467d692371ff499a300000000000000000000000000000000143282a2cc502f477be295d5fb2ec847cc988e43f72be848464eb4c1dcd0b1ab66a6cc30dd4b465050f6c37e8b8e08a7ab45b07c059738ead9709bf36ab20b09fd3368f7aa12c6d9f3acf3f145c83fa5", - "Expected": "000000000000000000000000000000000378217eb65cf5ff48e40ebbfbf03c307aabb63955f755a93bfbea0c176e90dc986a8202c6ea4e9ecea176068cfc62440000000000000000000000000000000012ac5e1a0c75ac5b96af3959a65eed134dac6b35559cd923facd2062ee06cb3ae2018db7d27dad2927b3e9c2e3dada33", - "Name": "matter_g1_multiexp_69", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d6ab2022d950cd2ad2f0087a079e435634a1e24008d12a349836cb7297defe857cadf3adf061e8b55ece662dd36ca280000000000000000000000000000000007682f1ced1ac2aca6ee9de682c7a6743fd32264eb0a087eb1df7c520c5748cd598be45213b398b073dccbb6bd67b44c3ca13f8540eaf45ffdab5182883d32a1d35e7cd956092221cc40232efde6cd1e000000000000000000000000000000000927b5590892a4b897ff2d6ef6d5abe32bec8233bc5f35ea9ace2ec516037a8f3d162b0161c91d4e06d80d73528a6ba400000000000000000000000000000000064d3d8340eea43bb2d54dd6f5d9d49fc2275ca1ae7212329a11ed9a94c70c80584cb6ccc1eb653f001a1c1c4306e702b3c8b045ef559b76005875bce09a66b36f295070a73ec8dc66c86bca51fa5d4d000000000000000000000000000000000322791d0e53364128288e40b621e6c47324dafcf86e9a8590a79eddc8d3e6c9d74cf9721115550e7e33868ced39cc4700000000000000000000000000000000112a246f82756d88f30e74b3f5df21e18ffc9cccd713e6509572338ccb4f52cbc0c3a6d5b5c112e304f90ffb9179238521953ea264f74bf64378a339461bff41c5193e17913c67be7e2a249c9737b8250000000000000000000000000000000010bdece8fbaa604439e942e2c78aa5904cc1a0532d5bbf624794d3f10f4b64df30838799e374982feaa7346c039c08ad000000000000000000000000000000001085372e79e1046c870b1d49a2a8ea83bcddd6bb8718c7cb340dd3032739319c54eb947d518c7e17d6e603dd3539f269505655d72f1128ac0204539f0d823f076cb3a57a7e74e896b5019c9161d6486a000000000000000000000000000000001551cb2abe299a01cfba81bb306457b662ad57858a30d55e0ae0c0f5851483123c388ba06ead8ec4fad0b1e4f69ddd6b00000000000000000000000000000000159e5ffc459d38a6b1e49b30647939f37c0d4fc02b83f9dbac123d64535752977005e0cb1232ebaa7cf0bfdc203ccaeac4c861cde3f445e3a78d1498d98b2b947056cf578652e19be88da4a786af196f0000000000000000000000000000000004111e81afa9fd09e39df891cbb99d9b62205777bebee33b2914e24570db46f75db5dbe2e9831c50f9717dc317f05ceb000000000000000000000000000000000a999eb350750cd505ea9de43945cfb0c9c4ea412cb0f0e769e62e47d08f8d50392d3a5e821f1e9c947990e6398b5ec699762c5189cf154e24238e4b157caa1d8759002f69b289cfbf3f24f5dabf20bb000000000000000000000000000000001496d3b0062e9e7166d777d90553545ee7dfdbdacb355fa7ecfecd65bcb96321aec0fd835b32c8bce462c87a2b52a58f000000000000000000000000000000000ef77e6ddce1e0eae50a1c663374c31a0c5846d6c2d777bb2f4831ecc806ac28591c3ab0222a6cc7821a45ddde1ce23e298b5f6b43074b8f0807086b03f5028709209310474c35c7ee232eec8579147c00000000000000000000000000000000194bd82f02047bc08871e431ebde41327a60e838d3a1ce6eb5470ba21a9b863025c8663f7d509a73847ed41515fdd3ac0000000000000000000000000000000006c9303814ddedc68b0047b5b2f0333cf226908dcb14ccc0aae4e14456a0c83eb4f498d559a649bb64bc78900a788a4b177bfb0218ecd8cdbc6dd9484e74e41be6971ec2911bacc8b53b9b4b8c70e573000000000000000000000000000000000736fc761eca44cd197ec6fc680de349f96e5294e42648825ce9262fef91766a8d7a084e5b598b5b47d947548e0c61860000000000000000000000000000000018eedf050da521b9af0ce2007cd664e2760320056e14ddb162db5cae78ed7ec859bad03fc60caa06081f0c24bb130ea4cac52219796226385aebf9e85f5f179362d4149c33582a97b7d2aeb05a8e6a990000000000000000000000000000000018a8e4887f0c08dfb7a741858580a1e0ba7e7ee1959284ad0955beb186e84a5d503ffe4000d5a8641575540b6b7a3885000000000000000000000000000000001946ae0b124fb60fb4dd32181783564dfb8ed0616a220d5650fcc1f6968ff70dc74535c71b0cf1019eb038c19cef0caae03afb2efea85fcd035cb4ba09977b2e1c84a0d98edf88e9f8d2c4f116d0f5030000000000000000000000000000000003cc2093935fcacc3fbe4429868c7b31fe8c8b12c1184e2181dc8da4d56b9b3ace85ad8d6b850deccd047eb002acc8fe0000000000000000000000000000000008cebb95902576d96a3a257ccfe76bc727174e08d70492dbc2132b9d5f534de3b6a7baac2d90338278064565aa67b22c804dec43760dab29c161b8f4bddc52379a17f3168f684267cfbbc3505e32d5f10000000000000000000000000000000003a03e6c183afe6aae9bee030f46086032e9d81fe337e7e1c77ac6c903fb33154bebdc15e81422f057ba1853c1f7cf110000000000000000000000000000000011f5e4fff35ad1d6e2d2d4e30ddeac28432eaf13fc7c35f5a90f7f8a17de0f61bee21529b3db3633c178006f5c5fc403ed2d3daf616df3f0061f58c925e9dfbbf6e9cbfd4b0b3896a596919fb3d243db000000000000000000000000000000001986f950d86f35d45dfeba6c3e484a6da296ccda2314d03adc37bdaaab374aa9011e07e6c8fe056e66b9204c5e16fc990000000000000000000000000000000003220ebcac8189b30f6efe6051a2be1001b85a7f94d9ce289bf6e04edfdf2ff17b17702a1ce116445d763ed1c0dee645e16797ed90581fd8c3cef1f30abaed10997f13461374ea649b29101959fd50640000000000000000000000000000000001000e0934c04c36c621d9b308565cc75ff58f6c1c778b8e0926b4d22d58025edf8a853139667ab3d3616c33d8a98afd0000000000000000000000000000000008776b843fa3b1449a0879616b3a37bd5eff5c809c077fb0274fccd67d645439a79a410fe2c2db44f52887ea7f20c6062f9f29432638c033ca84422b12ca80ac4ae85fa30ff56c913c5737aeb2c84d04000000000000000000000000000000000e7b037fccbb3fed299960355ff2c6a51562814ac797ed6b4b770ec565bae5ac998eeba19819cf2b3d4e91591e7f051f000000000000000000000000000000000143dd07288b59a279de228ea59aecfba3275a87fd8307252e6b5d567bde87088a8a8f52da57cba4c0fa0e2aed423241e6f1e5df7ff90c4a4fb9a071c0caf3a3997569538ab9837ed41d9d0a8d730537000000000000000000000000000000000b41b673bab477cdb21ae5f1c04922f2b8216d7a1423a6f6b86d4c33f0b4def9c553faca2798cba20a31ee7d71422b21000000000000000000000000000000000b64686b90964104f8e79bf9527f452d25c3c8e9d53e715d884e795d26e391dbf510d72fb2850fe66e35d31444814e650cf3283195707c30880e50ff5ef605b561c3c3c354fbe8108f93b36f212f9ef5", - "Expected": "000000000000000000000000000000001673148063c4f68c59d371410a8ef20cc4516c579523e2d7d2ba04b03fc5a481a30fdc6b9ebaee1138b28a9463011227000000000000000000000000000000000067e9b23610ac41d41e0bfcabc455342360d4ae4c75fa0303631e97f702b9cb660b84b5d422e8e9a74890b803c944ea", - "Name": "matter_g1_multiexp_70", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014cf7c57711c1708096cd33a9efd4f907112a3d4e5bad1767ddc6fb408cb7ac3f866143000154d1270c07b4294480543000000000000000000000000000000000a20191e6786d94721067d6942731110df277047541383ef9847fed9e4b8599723fd7cd7e2ca2186d56986feb8dd24d72063b046a71c2674e35466657a85d8e02253b42517b033619e31a53665917212000000000000000000000000000000000cdb0c20ac2c22a458d2370662d665005cdd8c662e318bb8652a2123f2d65d21c8e150daf51d7874c69bc039bb6163710000000000000000000000000000000008480687d726eefe93d5484ca375557e109fc64f60666e1b8aaf440100aa15e76aab6f821fde170046d2714d8986a1fe92fa325cd07502c6576dfb93ee952fedb304022656597bf3bb03a2bbc471b32a0000000000000000000000000000000011f20086905f64c21bec021e5726c05158f892658cd69536945a3337a8075994caf4fa16fe66b85e3e0ec71ae5b4c09c0000000000000000000000000000000006d71057aeaf26fc685bfc0ca071126a81224692b3eb90e37a1941782b8f65d45b6a31567c6e3d2935d38e9e02ba08654484e688799c3f0a3bbe00cec7322fba6245570685cd7df0d744473b72f03df80000000000000000000000000000000005a186d0ceb2535037b22a6455c49b6227e54c6e6dcdd98f46d996f23301b208a87c4bcd0608972961b67c523f01c99100000000000000000000000000000000142367fb02fc6b2cf52a78e4cb1157d273e9fe13ca721e0fa725f2a6dd0b4897ffe7affa25925da47fe851362700c31bfae2ef61a024e4d8c4ae277f6b1d834193df655ffb315da67afa4ee4ddcb7fbd000000000000000000000000000000000a758981a1524501c48ffc9990b738d51ebe38a0ba07b2b049110c7aa439253bfb0491a66cc42eb241a47d5e963db75500000000000000000000000000000000082adfa66bb46b97f14dec70b970469478d73d30216201e7467a927ae4ab9d93747b07ea69c406dfef789226afc4240a3168a1007abd42bc398e317484149f2fa61174243fd1748deec6cc75e7c720a2000000000000000000000000000000000de8dddf04e0c2d9ef1887ea598030f2bf3bc7bd98b8b218d19f661ec4c9a47cb087639f72fbe97afe9617acb162bd1a00000000000000000000000000000000127e78f1f41df717e5f76692b9ecf21ec0fbaf9b1d56e51b37cea02143f3b91eb1f16a65046527339dc65d29435a2874f1525bba87baee35023d0976b4a2d87524ba74158f000e5501c6d06aed04adda0000000000000000000000000000000009c37c64ffe9bbf264c475076ccbe6638653574ea84b30f4eb2601f1990f73fb5708af6007f21e4dd52f23ef5041cb3600000000000000000000000000000000170177e891c421ac91eac0dfff8bb397d7fc531e0fbd275c17cb4d894d18278a40a6c3093b92fc537244798f24eea4e92d3d7c014416f33724acaa46412348d350f93d334588d39c77dc0b8ffcb4cb1d000000000000000000000000000000000178d45abe2415895e0a550005c76522962c0ef0193cc7475a52f4d9cec9d4789406b7afa2872485722ec034df4446d90000000000000000000000000000000005e4253dde4284944b2083e07b04940cc72cb24d9866c953564bc0e847b72da59888e7a08cde7aa7c0753cda94a6e97c53bfbb1670b7045b6df689871d5d012dc93e8be65faa4a98a51db8501a4b7677000000000000000000000000000000000e48f11dee27507acd407ce1b810cfa8d0ff4414380fe26aba6c608784ef756d605c8c3ba92592ce342baef8aa927bd90000000000000000000000000000000000e604525ab4ed10f3a9a688774c6b27e679fe456190e67689959da296b650dbfb75610dcf54b30ab891c40784a9b90ff944ee8d294d189226a6cff17456e2201d17d4dfcb78f58f8501870377a6e43100000000000000000000000000000000199b1367bc3aec710e82f98d3564debe9e01ef2beb878935df4ea98e3725391e873d2661e2a27d778bd29ce6f66a9b24000000000000000000000000000000000e77a3ca6bc4584cc1c3df35b18402b75936f68f0f70193708da21649b6def59f1baec4d6d1a2733c369cb5d9a6b39347de53613b7a31583ccb214726482b770029c0ed42f9528fa74da7d2d1dd915e10000000000000000000000000000000016ee4a1a3f99134ef55398e96b86a21708388c3ddbd86746745e24bafb062a6283c5bdd771f15eb501df6a19920162d4000000000000000000000000000000001001936f457d8241a4929aec1d3769bd1955433b340481936f9443c63a6c6ddb3be4f4e1ffbf62a5c4b154fa9f8acba3b0a9750cdfe0910c544668bc9b11ecdedf1b757ff69b61fcc838c502c2911bbc0000000000000000000000000000000019aad23ac037d496eeedaeac9248842b0dec15478f62ab61d000a402cbdcc240186248ed931fe3eaae5a1d7153d3e135000000000000000000000000000000000fc1c74c4d8488edd92b42ca7c27e22a4776761829b06efb0d1b2cfa37738efb276cc5121d926665b99497841afcbd394aadecb1111ff43894123648eea9e57685dcb7a25553233a374479c24f2f88990000000000000000000000000000000014c557c44a90fa9d958d2e701cb2aac1c0204246fae4ba7b060e74e5d4ff50630fdca918c47323f5d0eff118c7595a040000000000000000000000000000000015821312dfed1e0bc2cfb23536baceb7ceb45c6c5a5f15ce0d4d67ef261a30ab8154b873513e2c44f652b93989cb6f1badde66cf749daf69a30f41ca00d251f7f1e93b0e7f916a1ba6b994d946b12ca00000000000000000000000000000000001ce81da6511eae9d2e155efb4f999a5d75faa99eed8fe784c7a398bf4b0e135bd0e8be8d9dfa2aa8ce9c63e091cb44b000000000000000000000000000000000695ff4e598b9e469bc62dffa214418536a6f49fa5f05680e09783b2f29bbfec5d43d42c969ad3b62c25c6192e328419b2f9b44c73a1a6dfba6462e1202166b63727f45dc3b8b3b73b5d06459a1beec20000000000000000000000000000000002f155e83bcd838ee8840996a3d8b0bef77334b0e8e75c8e4278411ae1012bae06959e8394dc4d1fd4ed5f07804b41870000000000000000000000000000000004daf1423e319b18dc57753d39777bb127b651f5294fe03a15dc4974eef8cffe337704c7f867fcb4c2fbac382e444a2b0cdc89e668f7cbd53a2ef6597a48b93d7d9a78950d4f821f3935edf72649e00000000000000000000000000000000000162f530647fc6290626d74753efe315e64dca2d73571dbd4416dbb41b07e8ddba40b3dbe170922c64fabbd937c961b1400000000000000000000000000000000021ac62abe15b0f1318063428d89f22d2090050b913973de571871125a391affb1cd595f9c596c9dbeb6025fc8392e48e23b377ed80bc90a4645df09e825509eebf57f59d7a2aa1b9121ace80926ccf7", - "Expected": "00000000000000000000000000000000127c2a1365d966520de7aef12e66e55d807b1a3e2305ccd5a78547fad6e6112d60a206412bf56866ca1b0af1b422c7230000000000000000000000000000000003a613a2e2abca1f42d3ed594a3b99a6cc51207b249aee2b5829aafb1327cc7bbf99604473b4048c4b2033e1befbf14a", - "Name": "matter_g1_multiexp_71", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fd31933662cde0814cea424436ddeb6a668e20b69259424a652bab722aac70b3582cb641d53bff963ead87ef5dfe1090000000000000000000000000000000007d17925b0309fd8c92e52c1ad67937efffa7ae3c783177a82f1133c8e3aee2b8fe71095b6b88b01576c5203d7dc8c3f75888762fd1de395fa80b6d8a751f280eca568de2947e953feac343fd6bd592d000000000000000000000000000000001782f625bc3b25168b1f5b388b7963b9d158c09abbc0bc4c0bf5332e1817fc083d3d55124532fee2665c536b6923fe3b00000000000000000000000000000000118650bcb2d32f4e83257cfebbe8209c2c9062ab0eb805ae2977f79ef48af6fd78e7512b331933edd087054273eab52c18ce7941da132adec1eee8d81facdb5012a15ddfe0cd6751ebbf66ce6c4950430000000000000000000000000000000014a69e56a173ed13a9e2568a8af49d74c74dd67609ca58744f96f9213197b45de6468d69ed084ed8b1b29104322ac517000000000000000000000000000000000739671cdbdf98251ed4bf13d23c675500cb66344731ea6aa66ffe401dd6daa8157676fc46b413378b8325ed4cfe804a24a0497c642dce3937d883ee25b0ea577c729366c7d67e2e5ff1ccde3b19a5dc0000000000000000000000000000000005c95d722f8e50603951c21421e8532eae710929e976d76f28c050fb2b093618489c5f892198ca822d3f287fea6eb83200000000000000000000000000000000077a07fe1348e4b6b2a46f444137eb86bf7c58e320afda3d75769a9839fefd9142cfcb75da1d1aa0e7ce84b880ff1b3fe4e0ad0d478ccf5381470a3fc9b882639dde4a0147c7c82e50bb93431b07a135000000000000000000000000000000000efd66388da0825c846b6437b13ce5014b94b20cd3a713bdbb41a80892820ea7b12b6f6720fc7aa6e6756d496ef5ffdc0000000000000000000000000000000000adeb6281219c324d14ab4dc29841d52f3f21b512ef0a784454a01358747684afe22b34d4ff1ed29ea013d47d9059c838573db9346a3c8de41af54048cc51a0edcb86f36372859d0d794f7560c8525b0000000000000000000000000000000010367597f1deb2ca9338b59ddcd8d02440ce8cc34c71a6ff93205375077c00f3f1c22e00ebc9fb60de7475400976e1860000000000000000000000000000000017d148179e9671959bf03fa1c95ab608fe2fb8b9b1a650f524a070d7857dbb8b14a67a813ba1b22e4b71df52e46c42c002257ed12262d00e78bde574a9ebd2664484a446c03fe8cbb855bf92e56bc163000000000000000000000000000000000797e0eff7ff579b0c5161c8ee06a2b99ab44e515045e83438952226046bbb4adf3c8d0538a0bcfe27a533444e2bfc9f000000000000000000000000000000000c556867cb0238505da3b55321df66611e6a018be4e181a1ec121dd55c509d501558af880a2bcc71fcc641edcffdb13076b9d21a3da0359a377c11a6d0a18bce7ea81d4128dc1e7618e6c35b9149d5c8000000000000000000000000000000001357812e6d93272645cacde880754514ee42aea3690d9d5d67e3bb5ee4444b7a3473ea2af0fc563d246b4c3e8ab5525200000000000000000000000000000000176c413594ca45019a174848f765f69e138e70dde1e184515c6f3012df4c5fa39a28a7e202c6c563db7681b0c4f8b3a9c9cd895d5d1ae0ae704e240c10d8ed4a01b319598d7885f7c3fffcd9b491f5fd000000000000000000000000000000000c5f9145b11f6af0895eca18ba6338408ce40ae1b25f8c04b40c0410a6c69b0144541e2ca1d4303c4c55fc407ca11b1a0000000000000000000000000000000010f2a09fd8b6cffae5a06bf50597a9c0d496bf5529c8925c1141cdb25ffd3afc6b51cb5d21d97c99a8d27281c657bd842467604875028997efdf5139180a8d530a1e9f18c62ddac7753cc370bf25254b0000000000000000000000000000000000c16911df03f532313d162bae1eb57c947059fb5d776ce3bfa661bad92ebacb51154697593e2321bbf85d43ae7ea567000000000000000000000000000000000564ac0f20388ca3bd483033994bf76b1ba135e229487e0c8aa10dfdec1887c62651f4cc0c05622de6356edbfd9abfef2f47637b64d28fb4facc31d5bed34b22e7b270431f54a689cd0fabd205e001ae0000000000000000000000000000000001f6de29a7cf8a89e3cb5befc926eeef59270b929edb68e9b0cd96feb5286e130f1f7c0e0d46cf2a411e499be21d47a00000000000000000000000000000000002b4c8ff1040a843a0e1d691adead4fe3d5306f89f83724a891abffec3c742a3416fe54c27c97bd131730ad364373ed0474c3ac61d4fbece967fbd0599c9a92c3fe0e53899861f044308b0ea8df137880000000000000000000000000000000005d07fdc2e2afd92d5f0f1ab6541313b5a58868d1707ff0cc9e4ccdea0c105cf9cf1f6e52d0dfd22c70aee1f7835ee90000000000000000000000000000000001229bfa1d5c5e4aa5ed0f6753dcb40952fc5446b0c5d0d90b22a7b2abc388cc18e8ef74bb2370b6ccf036f09040f62dceaf9da65e0e1752a982601e9a070a7cc77d5007eb641fffbb78d2a1b02dcffec0000000000000000000000000000000019f4a0cb264a617986898fbfb53d1bde9cd82c092ad86e608750ffa990d6926644c717f6a63279f8061b066f0c4e86fd00000000000000000000000000000000082f1b79a9ccf56b743e14caf0cf18b94f1978d164d9a95fbf87ce15c3a9b414b098fb09654c23ed2981249233e8baae5158bfe535fbc342e31f32ab4723c0d9fe95a2c64cc4e59bd41d13a08ac811780000000000000000000000000000000011c516cfd059a1b8ff75df3b9b6b135c2a52371f1a0dad631e96d8673f1b26daff9e776e9dfb225e9881635a28dd34c5000000000000000000000000000000000bb0dfd476dab29ccc80781a92f5a998b8ba2464d76df001440240957eb1237d9d210be62c9187d7f17891e837d52635d66f5a8f37a7c6a32088897abfaf5a98bd4722c411bf4b52f0f5b5648e89df29000000000000000000000000000000000928c4d78abffa6517742e617ff8efcf59b48efe0b55eaca1d93a434b84c42f29683952dd08546dc1b88bb63a35b49c7000000000000000000000000000000000d63b1f625ca9d33aaf51f8251a088642211a474deac9931c3ff8ad45f80782f62f71f014505606cc4a96f91c79a25709acdd24190589ae7823a42e8b59598eca12bf13b97aa9a0eec17f5f79a01e8df00000000000000000000000000000000131c7e90e794b09da6c4936747e6509f94a467f38ac7f4bfd0c5da88d1733d1b6871a9df498b265c65695ab3ca889f9e00000000000000000000000000000000190e566597ec19df03c473b8ff4ec0cf24168f47c89525b31b1f3592bc7f87540caa8f91e2eb2f415c05502f72673dbd0291be87a213b0a24c92df5ce42381ca378dc4b9aeb4cb9b6918263bea827bf8", - "Expected": "0000000000000000000000000000000015610fcdfe0bc92be1f3ea82eb0b0512ed5f448e0000951fdcb0e637ecca602f715674aab1b7555c8f8bdf886d3aa62b000000000000000000000000000000000103c3ceee1b45d9d8912887c40ca16dcaabab3dabf56b8f77cb3186b267a74a5193048ce4165c419cf727d6e9925ac3", - "Name": "matter_g1_multiexp_72", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cda9f382fd65f5ab92cc560477f1e3b69d0efe355e40ad3bcaf258509b6ca5e179deed8348836b0e723d5f7ca4c43ea00000000000000000000000000000000037011fda0d188f8d17436d21b9bce522cc9f8e4f473965803b242694f403ecee29d2abccbf56ab0a1f2fe5831c14380b14c6a38cc998df3583228080ea10f215a6e6a4b02ddb6d43e8f459d494a1ec1000000000000000000000000000000000f591bf508a5076b26dd8ea3b0f7a92889131142b34cba3f35a9b861cc6deeca7378d5728c0af9503441144bfc82038b00000000000000000000000000000000156067cc00e82414150bc05ca2d0c0ce1c19e5276e00434754616c9021120bbf9d1c00df6a42b76c3ffeb6e32f8fc3eefee8614394c8109338432ec72f2d9babba06f1e7b826b0f2558c3247c923b2350000000000000000000000000000000002a8128978ebfb99e20ac99ff5b3088e8eb95a7b6b354d46e775dd1662a27d5adc9513467690f377d4a13766276bf87d0000000000000000000000000000000012ba903800e9641de498d8e286c7ee48b48f7d36255823b88a24cfb67f8d2b7b6411ba3304819f588fff0d730cf130e428728d06cd90050e44a827b44f14ea35e83c9b58ce4c3a7a45aed6f31c94fb96000000000000000000000000000000000b107e62453c7181b26a3accaa624a612b7498ccc50eaf0d47bbf350b3c8c54e940266cde786c608e42f59d793e45eb000000000000000000000000000000000194c2c3717a8284051a29586e540bd9e456c0169eab0412699865c12226521796a55d598f60280cdcf37b54a24c931040fda665c40d1da93b1f132070e0b7c8c2c0ea0e66993b5a3d7419a33d118d25f0000000000000000000000000000000013228e1a6346683320d8acad4a5cb1c23cfebdb9d9c451ab81335d27e8b82297b38e1fe2fd02651a8dce3838144cf650000000000000000000000000000000000c6d54add7bdaf9ff8158680f35be7f51dcd5c26a698750c7eab857140b6329157bb7aca8d7c68f107ed9f68b3a076aac14f014117a74f21e0b698a257ae8e3d6091ba76bff7912abb6bd94d41886d050000000000000000000000000000000006e1e7c15fd14ff3bab1e9b8f8b7d6244c707744708db629ef4146b8cefe68c505ea034c180fcff95a452f7e1e5433e1000000000000000000000000000000000735faa57e1c4349be51395bac55a331a04851b41d2ec98072c5ac38eb7bb03e00ed64bcf32c3eac8b34cc6e26769c3ad81a1239ad2c945f1c560fd1674ac7e87d49aa41a1f4a5bfffeab1147c0ef7c60000000000000000000000000000000018008132dcbd9455c3932155a0b0c58066bec4803eafb0a2cc30a93b0a335738b52e6cff60b379fb04b5aad342baf11800000000000000000000000000000000149ea542cf34141fface44046aee2f6c436218374d095bdd46638ebc804bb0c9a7e1e3b01c0470bb6efc7749b8f70eb73a02689cfd2c353fc1b4d3913f5a43745fffe6a87a7c223ec3b25b321584a75c0000000000000000000000000000000003f12b0eb97856f3ead3d46a8321481351471e558add0ac4e1f285e7ee8a1f2ca88ffedbc8ed21df31d599e80b8f0e94000000000000000000000000000000001315ca27c955f3826da43745809fb1759f0f5d5674e4d94118bf2f2ea0411c7d9cbc65f054c41ffbdf196ef24eb9afc55af95ab3fd062088ffbef6ed887fd39aa1d527fe7633b876187ae12e736fcf2f000000000000000000000000000000000cca2b061959fb70d383f7e247c131f51920e048dc136036cc301f1ae6ce13809551d0a8074cc05409d124e2df6536d0000000000000000000000000000000000a9692e0263b563cda35f8497d182fc05e78e7bf88267aaebea1f5f41bd1cadb39c61431bfcaef208adcc9118d4dfb546541c6cf8217c2a95792900e8fc39581b177a57ca00162c57131ea4fb80a4c600000000000000000000000000000000005bfb5a43e3643846f92310e9d5439deeb4fdd6b5dfd3de2ab3a40b9b8b3461136b03c5601add616dd87b9a72e81856a000000000000000000000000000000000212c6c42e24a3f11c30b7751f37c0101b8a071a3d56f2d10b6c9f4f84ae12079d8c4f2d216cdc7ee93abf8b9d6973394b7c3f3c4ed10bced85f36fd6dac2646c65d3c810e6d2d116c38aa5e10b29c2d0000000000000000000000000000000008adf951da1f0b64c17f84031985bd1f3561ab44c80c339c4c753a7c2080e0f57c41b79b6cccb75662e8642ae0a94451000000000000000000000000000000000d9082079fa53008a03f58b87fe0aceb121c6c004493f3da7ab37f3236942c8ac01fc28db26b87bd2546f93b12577ee57e33f394e96d17efa30d34f57eecc45d7b4ca150a31b8d0484578151d6e65c2b0000000000000000000000000000000000f352ce042cbbf1adcc42030ba8e0dfc76b4ca313e82a5c5105ec56266977dc83626c9a9b3b5c25ef459a6feb2722140000000000000000000000000000000009443440da963a7e64d90e4642861f3f5399835fc2fdefa7e87708c033848170eb02407a6a9edadad27cb02793055140fde92a31e571ec03e509ac8a70ed5788869854eef0bf578efe6c5e6468315553000000000000000000000000000000001699cd7355b0a0be2946f8f49648bb04a90c6bc8ee7fa258a357455864022db999793771a2e66adf3cea5a54ada82d6e000000000000000000000000000000000a3ebfef4ba72cbccab5e93155429a14fd61c106ed6d2c0db0694c4733b6f1730cc9f34a5e9598c60e189b8e4943efb56f7de01ad0f7b4dcaee1123bb80a71d3bc1e63ca577a12b14ae2a11d8c0fde46000000000000000000000000000000000be5ac701c69b81cd75fddb8da92066cfc9d0d2aa7f01495afd87e44076f9f022179b7d4b4781d0b5c6c52b498b63dd80000000000000000000000000000000006f2fd1ca9a34fb09d922a76943b43505f2aad16489a138668f08b9f388c67e46a4d5df7387a1c3aa23c76954913abfae2c69d21d40813ee40a718f0ead36b51f3a50e9e4e4b2de8acd33add62bfc1d20000000000000000000000000000000019489b41d8b1f2e8ac09cf3f0930e092afd74405e213454c458cfe44e5f393a88713b62715097a1aaf01a188e8ab07c00000000000000000000000000000000018471d616eb66f1dcfaf84b7d49f632e0a5306888e44c70710bb61d4afd440e5f692eefad842b5d37762cab649fbef34762d89025196aec4f87da2fcc5a9188b4dc7b1c014dd1d705223bf9fe1e7a7d1000000000000000000000000000000001088372334c452709f81b57f5e5c148e0f88dc29dc9a118abd6911c46ee83d0c6b58ec9b854c15f519d33d281ac9e21d000000000000000000000000000000000394a7e49f32e4f7d27f276892002ad034dccc8263591b5d941eb2a5e60097e757ea67dcdc5242b755fce30c3b3b64cdffb9f3e1d43aece3af1f59319a8228cd81e668b1e250d03350958dcac9e23843", - "Expected": "0000000000000000000000000000000009e68140307d9309c32763e4de857372a61733060ac582922e3822e46c28f67bea87a75bd98248466e8938abdc4ef54b00000000000000000000000000000000187dccf66e6d0593ac8caf6723033db545c43cb90a5f5486418325860b692ffdf8dcf23da9103dc65336d3cec2577a4d", - "Name": "matter_g1_multiexp_73", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000083dad213737f1789595316285a77c859c469b9bd0cf08c61884456e4fc5ef0947847186bd420af252d822419b1de3ef000000000000000000000000000000000795a6ced1d34d91bf5ddbe77fee452699a1b32daac270b4e8661259dcacbb9c8c3776043f2e149773427fe109818c87be285a119dc8cb32b1a0c5380af736114a32e9d1ca870abdf278dfa84444f70e0000000000000000000000000000000005db83053f9824116b9d14ce0173c2243a4a8506e161db7f97408dd6fa77b65d0e0a32e95062699f7aa85cc9be448dcb000000000000000000000000000000000f20953295dde557a078c981f0b988cd9da8c7469fb7fa3361f2386c7dd609bf80ccf91cefd797eb3a4f849b2cec4370bc0535bd504d7b9658e459c2e79b86bf4e718baa82b8d6e624fba0eb141c726000000000000000000000000000000000000bc3e40ec1b6e863f75e4adbcb8b504026d0634d1d3769f7795ed2956bd450e68aebb1a9d11a71fbe5b51bc79d97aa000000000000000000000000000000001703e1fde7f2c740ca3224c1994282e633292f86095be38dde3673b78729db84bca33ee820532aa92bfd32728d9756404f3fa09243c01748954d84f4deeb460f3ef78f9c34296c6a092952bc463d72840000000000000000000000000000000009622c13e8924441b0043770faaead6db793ab818532c7323d9ee9a8d118cfd2a578e1c13723c8bbdd049b1d8aaad9ed0000000000000000000000000000000009da68565c05aa28648c0d0a0e185335b4e58903982fd361fb57f544c1f253a55e8a233b341537d78c4f229ec5f935a85d84733ccc41f71a11d61852fa336df566109c5538c2c5f5cf2af961e93797fd0000000000000000000000000000000005818b813993d7c346cd70190e1e6410974e64e08fb0a70721a0ee430dcb0d92d302943836343e274b26c69030226c0d000000000000000000000000000000000ee84b6b251c9d4f7e7abf843c73f0456968e23e79c54d8742cd5967737b9cf9ae8c6030722134c376c7c9433b749563feeb95c32362014caedf2a9e066a775e2db0d1322edc86759faa99bd70c05b580000000000000000000000000000000006870d696789986991a222b988c3623ffb51ce96ee35140e817887ea37068ec77d8131a97579f2ea29a5b45ab55ec5d90000000000000000000000000000000016b203c189343e67e10928c2a45259593cedb1a016491e94435a0823522010469729bd69af9c3bd6f4e71e96c7d8ca72edee2ea28b93b2daf4ff927991769a9c69ba16490b5676074e64f5e91fa994a600000000000000000000000000000000191a7f7469739ef4da1fcfed877b875c4b0af45df7aa9055b7d5f0c1360e4c4b7b67958d03125fade281c663923670040000000000000000000000000000000014d5256c242839e0951390f00affb226ee6c906214d8d7dca7e4fba7eaa8b1944fe4f1f93bf6ebb21b4a8585e000a76b7a07e50c1fbf1b388e9264c762798c31fe76761508d070f06adc63130df07641000000000000000000000000000000001968eb742dc0e128c94c1f0dab2ff3b0d300966537293ea16856e5f3ce5e12164d9c52fa59e08481bce84f3f87dae8f100000000000000000000000000000000098ec0e7bc53314fc8729f4688b99c3d87e7e2770877a30898c37c68a5e0a4459851b8fa390cab18e7cf0d325d906ce4f0056903b4508cffb6334bb5f645cb553a8cc61ea6765283f933686f172f8360000000000000000000000000000000000064ef5e6fe9de3e86ccc7a8b809cbdd945eef98e8e6cfa82dc64ba94070cc107090427c13ddd3bf25d542696d5de44500000000000000000000000000000000116b4babfc4b1a7a36405f597d4afb478c024805495e1a412a3ad5e9ec5f01dc47411ee6e81a9477677b89291e91c2b68031f363c8b0062b34d48f4c2e5bdba884005e52f77ac04c2f29dc7ef10fac0c0000000000000000000000000000000014d07ad766b50a6150a50decabc56f04559d1b196b713be88b5543a673ee3f4499e42b58c532e38dca0101f639aaa9fe0000000000000000000000000000000001678e7e66f44cff05163ce249df65063c4ea2d2517a31f42dfe76f67041d7927ad4b0efa4b30c33156b14f5127af190cb146e27a9d36dc698e1982afc945af9500fc5aeba719d06d0c4e4eb245034c6000000000000000000000000000000000745f042a917dca8e35c8f0301612ce198f75144e145a3c3041f4ecf893360eb0b7fdfaeefe78733bb88010d6a7b9bb3000000000000000000000000000000000e8879142826593a2f1214eee206ba69b7962e9a10ba014af5daccc1e4a2d3c893fa47eb533cd0c0a9fc1c09d389db19d983f98fe5112a55c23591bf4e259d072f893944741d9941a00f907749e3c9990000000000000000000000000000000009da4fdf5b86facd674ffe6d91d03674ebfa3aeff5ca2a659777be20109946b1bbd759d4dc2d9e859d587ce50ec3bf01000000000000000000000000000000000924985f655b00fec0bdacfc6914eedab676a962e21ffedd83be646dc17f5cdcdd3f43a9ad7ff9d976e4828b4dd219b7a62f99ac46f986f2f29f0ad3da0310f061e691955c711850a2816ad7464614a700000000000000000000000000000000187414507425106691a2dac49fea1eaa14783b2a5b79a945fee44957619793be1a68aa110867ea405a076d30568ecf3800000000000000000000000000000000034e932247b81bda0a54568f2887824028d69767b9131c106a4d204c0b2bfb929b9ed7b3fce1e354e405aeca8a28d92e7ee01b0c9c6a6ca1fdac35d89c803bee3595f03d9d200affc5292d8a7c6720b800000000000000000000000000000000027361b6341bf8985d79b6dde029a9ee54ef441894f34d60a3324edb502bdc78ef60789e5ce342c240db0fa91bbbfd00000000000000000000000000000000000bea3c850bc9d0860241fc6de65c203d5a11e6425faa503c37641522fba6fcd31643209329e6ad75a3dc5e4a4790db4a297fc700698c56877be6764f48a836d210bb33e99b5735da9837882269af9b45000000000000000000000000000000000fc7095889f943697577c8867b411ac925ea7182e47a7cd19387dcdd48fad5e558de3d80e3036992ba5fb8dd7925774700000000000000000000000000000000160f1fbb346c48a6cab0105d343c55b3714899e931e7b4e0abe68c4fc7067189181afb9c040d41e4c1f7c4e2f1b8a63b1b7ac02db15cebb8af459290c35eb5a86cf98b86d8336764c6bdda6698b49b64000000000000000000000000000000000bf1740d01ece251c0f0ee4f798872eda7f5a4ad3152d86db12844ffa88ca52835799f0b2601ed1bae6d4850cc889940000000000000000000000000000000000557f274109f745af6cd965d6e706b9ea1fa3c295cbbdb203ebf049c1070595ab820efad6652b1f1ba4e2d331b5bc6da5d1a3f78a2c2ab7b85cee68ee670f50a176e988a341303afb7722917f442fab6", - "Expected": "000000000000000000000000000000000c57ca082c662618951201a98d88170a9aa076fd1fc48c8ababdcbb09b63c793725261acd370d03d28ea47c0ef176f1500000000000000000000000000000000110234e4c6a99c6d1ef8b43fa897990d605af9b469045dcd0ead52b03f9f90dc441f7fe5e624349788746802e4f74015", - "Name": "matter_g1_multiexp_74", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ca64fb3ced1d15f94e9b234e6f6fe59d805eb0b50ae29c9b31514ea5c6e79542688e871de6ace893868fa0eafdf46890000000000000000000000000000000019c60ebb5ca4e605e3b0eabdec53f566c9b96a143631be93250260560e47a2ff6b073e432cb1f9104ff913616e7d81c834aaf86eb77ce03f1d8eacab84d5ff98a565fd33a9a2c40f2a19d7c041a7e2a60000000000000000000000000000000010c867a070e161939458694cd4015b76bc4c76eea884d9dd309d6642436a82bc76ab57b2c0e2d3ca61f34645db65f2460000000000000000000000000000000014d9df8b34369bb23fbeac29aa8c35b346992d847fc2b9e3b96345f4a2245fa8eed505daf17edb4090726052be75662308ab2065f1d2278caece0939cbbab4bcbe3eacdc80cfae6e4500a5195883de000000000000000000000000000000000017ffdfa10cc8e1a8b3751312e5bcd09772462618b8bbdca59a60701a96dab651fee0dc755969e1c3a1d2aa4c11e48d6d0000000000000000000000000000000005c2aadea5a4b11077a2a1641eef2d3bc40c2d8001e9853e44bcead87cd968ce41ca50644ea0fe1d0ec4c2d7eda9dcd058c69b55bac97a633f3ed7816e77e2a26cccc029f7e7429c86145ca4645eb4150000000000000000000000000000000012bb9b8a1537c2856d4b2bbcc6fdec6d69eb6196d795bb0f1f49d8a886076e7fb424f63400134622941b2b88ea61b8e30000000000000000000000000000000017206fbf293f1ca1f2a0971b920e702ea39996058111ac2c041c12f58f67037a3840955e1185b413859a6f845b333b58ae7faf23e841bd53683521cb3cf215577fa51f0f751714b6aafe5c740f66208c0000000000000000000000000000000005eadaee4c48dca28f9469e882ca8ccb71f82bf1f2cb5b7f50b2e63a05e78415b3c5d0767a27f19a0b1c88400116e5310000000000000000000000000000000017e95e480a145b5e897c7a1ecc1b21c5a000248f87e74bfecc21a3cf8a06c04fd075612a62145ac089f208e567e4e12072022cdd6d942158bad47a53a9b0c3be910a41036874975724a5cdd22c0128710000000000000000000000000000000007b834503ed3e1cb74738db29c91f415beeb3ac5b75bb2cbf11f4a9cd1608ea6080dd1bd50c195dbf5ab6808fe9d6594000000000000000000000000000000000eb32afb90ecf9923ec22a483ffeca3a15d358013e64e521aa42d3db1ed0397e07a85321492e0693f8f041f4f8346c6c800ae0b956e38bc34cce55bb7e88f1370a30fc8ed0e3f1126c68c30792a2cabc0000000000000000000000000000000018f208e26fd7c03313df686e27bb6ea09d9a998764e805fe6182ee221cb9ff1552e4db5feb91b3b2fa595bc32f81898e00000000000000000000000000000000137c06c3f9eb27f1c0546b3c7ce879218a309dc37c0590fc3e151d9f7fd5963f0fda201faab489dce0043c3180abf753a57c3322133d6ffac661c888995e7cb067ca1309f3e9178a266f1a410a79c0130000000000000000000000000000000016fa49bb488a35ecbfa9e714235790cf6e7c3ea46e6a9a424f59c63d018206740e9467b0575077e86091ad6e0f9f56b6000000000000000000000000000000000197185b7c82ab9e6dc8e2a71c94dde328c923eedc6e305d8f36f4b636e7662e501917b89b33877cb2094b523c969dfeebe67f3d067b0d011abb31588d1b2fa9fdf8a56bc46b1a0196e926d4ec7304050000000000000000000000000000000006b797e2bb8c0c2a5a6ef8d9f08241d42299efc8af049245c254a2e4bfd122a01954bc596750942bf7ee467b22bcc528000000000000000000000000000000000a655491c6381e81473c23565082544d9f223042c82e241b1cb8ba48e847d98a373fc68b762a600489cbbca612defc61fa1d6d0d1876a67337d66c596fbcd7eb22ee308e4a5f66cedff584f1441be6a7000000000000000000000000000000000d7b7ba451334d1391a51142c4b7cecf0032fa6d28fa7f36d2d43ba39c6418946244da3cedeb2bdfadd453eb4d54d05b00000000000000000000000000000000127655a7acb4e3271a188cfd287cc1af890756e340eb4648bf3ea3e469644e6d21f63e64f81ccb55b9b1e0a62ddf58b5f0c4ac919efdf3d0e649126da7f8ca3daa30b6ca6f3be6854c0f447a63cf211000000000000000000000000000000000129442dedea08bee8661b558bdf8c22dd391900a501f1841c77359b20c1a1ff8838829baafd2a6ab5eff31e3f9ee884c000000000000000000000000000000000ed7c27bfcfbf9b41c833fc0d8573d7b28a6d788ea3cff4d96900559cc63969ac1d5fd366fa705357626eacf402c2ec560d8bf380bc2223efc779a747c0a36f8c2b18c3e821e96163bae14b18f3739f90000000000000000000000000000000013a11df012f8a55c263c5c55df0fb682e685a5feef160d77d26db7125ed08e6605f3d67878ec78fd064487f30228f4cf0000000000000000000000000000000019292997c874c72ce7c432f20da1a338e9dc433f9257b7353f99b5b531a9997bc3a3405b0aba89ab5a2f1cda98dd8199006c3a7b5ae971e4b0ec34a1007a02cf8c55f067115ba00c5967f70a7dcef9d600000000000000000000000000000000006a56b816898a1fc9954495b711c493ace881e3989207b2f862dc41c5fe346fc2eee18adfbb9db67e774055561af00600000000000000000000000000000000013971cff1e9a6ce35a7ae40118a007518bbdc5df5939a90fb263a9c345a70f4eef2f94ec671ac6964390d0478cfbf728f29e330b48230de23e0393bf1614cd26685cafb899db5a164497955d3e98be40000000000000000000000000000000004962ef115a4288177df2f0e4665e5d1976fd027f7f87a24ccdd0584e265e2f5cf0a7490dc7824f5eb26c9569bde9d6e000000000000000000000000000000001544f43d961320d59c65563d5f04341a8ec3e6e64fc2dba7e953652232d615c90eef2c859525fed99ae6ede2c39f510a861ffae8f62572938925593f7271a56e0f559b56bf97c454c38547a2185e2ce70000000000000000000000000000000004b250ff8bea739fd73b3c3463617eaaf3b6bb9db11c2b915f7435996bb4cff3561fc268d2cf0db1705711de522382200000000000000000000000000000000001c428a889955fbb5fcba993f2defa5906ac7b6a3fee6c07f52de8d54b0665cbea84e89a0af3523213fd19f7d37944012dd907071c2d39fe710215d174452459cc31d36007a1b5570a27ca2e42c8be5500000000000000000000000000000000106fab277085c88a7d664587f67aac8de95aae908177dc513fa24c8115fa23db44eafa7075b036242306002ee6918da80000000000000000000000000000000009e832e0d01bb5e89460e2cab772c308da07414ff8b880288c7b55d6390360924b806c71c9f9762d84d8d3cb3c2f6a6199893c06db2dab559f2c374df4298707dc1815e55034dce920ae7b1df2ec8d23", - "Expected": "0000000000000000000000000000000010224cb0e43534025f8ba7a7c426355a2091473ab16a752a9819d8e5f3eb5b1b5c0891b1c0cc0017655dd8aa7102cea80000000000000000000000000000000004313278c1bbc33ae2c3010c50be0120bb3ec794d9ff77fe97154438606e5f6f04c1dbf8dc01b827643a31899342e1ed", - "Name": "matter_g1_multiexp_75", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001812b7bdac748d2c0f05f10edaccd351e35347a4a582671762c0567f55e411839ec0a776c18cd71cc6de0c3a3b8bba820000000000000000000000000000000011afad9a48c42d8c3bf74dde15d7b744c6c141ea57e133c9dde7fd762636115e0296a647fc3fbca8144048721902973fd8555388bcc6791802ddb6c0f4cde44f45ac0b5d7ecd918bc34fb9fdedb65b94000000000000000000000000000000000f4900ffdc92661bb33e7561d08ce7757ae71a2b5ebdf6427922454044c6c6695e249069e83f3053e8a8a0adb5d3d3d2000000000000000000000000000000000be84ebce32bce4d58557422c7a8c4020d1bc643a99b00231a4d4a06d5dcb56bba61ead26fbf07079e9457dd4364ab6d33e5999498978d14c9de06f7beb2fd870f6f16dc42125fa496606e65c7466c0f0000000000000000000000000000000017399488c58e24c6e1f5e9a04291930595389536480ee6dc493cafa7f0e85410bccbe5c5841a1a0e495830be7e32c0da000000000000000000000000000000001055ca833e53172ac1d2d3d7c6fd625dcc72556e8d49bb487a83e56deabee4fb672b6cf7787d1231c760c2b7e9d4e55e7894a51dcfe5a8fa4da1745a696c870b353fb03a31238b8744840a78084bde48000000000000000000000000000000000c57fc0c785d6b81d4831ba71bf27f9af318a730a9502917a68397678c7ba22f21335ca2fff5bd495676faa418fe21a9000000000000000000000000000000001012cef9cbc88b838492b6a0074e0e5d24635d36d669288acebfe446157a202443fbaa5241b288fe418e1fa50eb3e65cfb6a294589c816e18859cec34262df6490a2af6acc7daa3de861198c5bcf4b13000000000000000000000000000000000a2a4bd7c7a79c2336b05bd5e0558736697c435477d4d0dc790033366ffcdecac3bb9cf48d1341835f7a42e17af833c9000000000000000000000000000000000ba384bfc6aaa8402ff869d78973c68ccc36c20a839da8d570b6890614f692f3a3316f0eb45e4afee0cca078cded752e83c4a3460caa35fc0e7342dd2da5c7b6aae818eeaf5a2cbf4794387180b95dfa00000000000000000000000000000000143e594b8762b4f821a6cd294251a114e248974494bd16a66f27192d3c2dc56c19d886b6305d420f8b81b22a2ce4faf10000000000000000000000000000000012fff0d7edf98633e1b10ba09b3c70fa0ea8674120160933689115275da6f95a8cae1ec665f89ef3c5454dd91d291ba4d2b65c1580bb46e3a4cd9d9c4eb7dc998168c66982448abf3a4e08cd12f612b100000000000000000000000000000000159734584d9cceceb9a27808a5bbc1be9acc15c6d2edad81759312898be4efaf85420cbd004102f7b051c83b27bc3fba000000000000000000000000000000000eaaf5b8e35ea5d52bbba19087520a96348b418159e043d3b39c451fb77d5b98aeaa43cacacadf3e6ebb503f49c5ad4c120892aded230949b83bfb2dbac054b83a9dbb852bd0ad85dd1d7f715852306f000000000000000000000000000000000c62de2a514ba6a74f66312553218cfcf49828b6f01ed05561b54d5f2a87806694ada45b80429e60fb985d9cc39e9c4600000000000000000000000000000000146b134c46ef783488e0f2d6d9b7039971e8ab7f3c29fbb2635bed84b44013159f483df0e7f0afd038b64f9e5cd105726af9777a58539e5aa8b1fce0994e0e1cdb5877d93ed4db715c5aaf74d6a8bb1a00000000000000000000000000000000189f02eda06f2d39974098d874325e4711a3f4dddf78c1b9ffb025425c8abe6dbcf5a01de0ebc802816fd67b0a9882fb000000000000000000000000000000000b378df4be4566190679691561aabd7182e68dba4ba05cc67ae19cef483fae99f4cc54540b5a5180c3854f5a82b6fdd0f37e2ed8e96921a0f9bff8b43d432b382d7b59938e269c381351ea49b8c1ba2b0000000000000000000000000000000011c0ed482c1a1f030fff7395db725633a60875028e2a7763a1ac801f00a8f4aff5e19e556516df899cf5e798197f6880000000000000000000000000000000000fa7faf03f2f636ab340a9d27d9b5a66fb8daa9c083a32904a4407d408cd3a14c17734d7a14abe3655979230e1a93e4d23f4a77a2c34a370a9b59ab1cfad77212e433464d0195f0d2fd20c69141389f500000000000000000000000000000000101f93857688bc4e4da2c5407d8bc68b9304d27c89a44daf7cebeef81ab96d89c83ac34ccd0dcd87297929551810e47f000000000000000000000000000000000457eef8e4d47638f83aa2165c0f2581e6a0886595f03fc41319d6ba71da0193a4cf9f52c39c79327a69037b11a382f696c59b0bc6dbf66f42cfee34413cc4cbdae7a61e232757c75474818591764d6f00000000000000000000000000000000110957948a78ad9c04b7abea4d1caff1de20b5615909c2f5b8ab7a1dbd02b9cf2ebfaaf3b21908aeeae55e47b9a21b7500000000000000000000000000000000168f08d45ec66fd4c9a94d82d9533aeaa251186478851a421f097d00506fe6dc0392114115e3e66d8874e0aa4b15cca281c180924f1d982bf4b6a2bb1cac590cdfe84198fdecd87364e163dd988f9b1c0000000000000000000000000000000015fe358a596150d9eabe6f18e06d562f9e6c42e9df7ad9ef57be8c47c5764e408efbedf136059d0e04f81d4838713a83000000000000000000000000000000000ff7a343274892ba23daff40f5f8c56db9a4788483c16a4a0495a1f696d3304c6276ab5a6d7b3cbdce14e9711b033582e44748b9eb1f44b5fb143cc8deaad23047bc5ecb8059705e7905c37625d5e2d30000000000000000000000000000000010d66f27b2da2ffe49b7540da57c25f0d36de0c43d04da9b123c153ba3eb63f3d26d28d4cc4cfef2c0652010be2f9eb10000000000000000000000000000000004d4cf53935c01bca14c75d1be55e7473d17de6c5a2d69813df90c7612aa4815ca6ea982222793ce66bd1c69f6e456feae04d7723b7c9cb0574ba744bfed8f8a347ab740bdab99136aa71a6d635d0d980000000000000000000000000000000008ece81bc19694eb40ac3ed089d8fb0cbed88371c7e314ece92547151165a017b0a5db4eac06bb2679a8d82b296f522b0000000000000000000000000000000017732041d736996351f132c92fa7249483612bcd79532156694314834c04d3b99579d44628c52eda270ec7c3ca7c3e576a794685a342ff25dd706e4df725e3466889d8f08a27ed2f32523b117f01a84e00000000000000000000000000000000026b3730efe162d58adc8d4845706f9bfe8ff54116b518d6c3b2bc6418997a44e98071e83566a905973a2d512878cf1d000000000000000000000000000000001449b0e28d1c43ced7cd687a550ff7669df47e80d3f2ee621b791848f1f7d6cf6272e39c66e8a69c81aeb67b06c630b2ed3f23c51953e46d400802dde46c374178ef379d5c1b04d25449891f0d5623e5", - "Expected": "000000000000000000000000000000000154edd700b8cda3a0532b2d6e81cded6a9662547b7d638f229ac44975d3b4b2f19816eb664e6208f33bf6f8d070fa58000000000000000000000000000000000a41ce7605d7ec592ec3a030307391ac64be5df9a7f8ff9b7ba15f7f6931353fb824ae8aa76b31466b7e06cb89fbc1e6", - "Name": "matter_g1_multiexp_76", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001227a5d20faf2f8d9242e1a7bea89b5d7c41c3e0d8f2629b4004269f9babd2521a97cc23075e13a53f4c66a82970ee76000000000000000000000000000000001726ad8abed312a369001f53270b5e7ad8f3f2a031804ac055ed4ddb2f40eadf9142416efbc90e84f499e07a307994db8c8e071da1ae8f615631759cf33fdb876ab289a6bcfa6fba2693a58f8601dfd1000000000000000000000000000000000a07b5276098f9b3767908192f91473c554eaed23b810d3b464a3677089c45e2263600cc8d84766c7c67d9b5e6a057cb00000000000000000000000000000000175af857d5b53d195a17ae246208b55f35f4ff193545ea5a725a70f11fdd34ad2fe22431cec7835d4fe3c401c82a93fd8371fff9230243d2e6cb6bdc4cd97260a8cf0362d18b9ba8df512d2a6f5563dc000000000000000000000000000000000039e109e0c2ccb5e6cb4c5451125047bbb854488ddd74fc4360430fd80f16db3498a8be9514099d3ad50ed4376bb5e50000000000000000000000000000000003dec8af7f6805ff9df65c39262959c3c80f271d2f0e53e7e719fbb16080d7d90a1211a6b4d0513c771ddad7d3dc009063016c9a9cfbf336ebda090d3f2a1a1b265787e1917f0148f82a9c0b66b21dc10000000000000000000000000000000015a00f549c3a050a5ffa8427bd0c8b90a788c6f9150728b037232ce1148c02bce908f60ee367b70d0c9642114d6e657d0000000000000000000000000000000016831ffba7d7d0bc239563e9e62990af4f740e57ca56d0d8826a9738338e9a1d2e8dc2b8869d62090b06f5a3f68bbcd36c9f679167d5fbb29250834c9f65d3025606e2af20aedec309718f95ba01e90c00000000000000000000000000000000165e447cc890b383b46f251531cb6d29cee835fe2a0fbe14c65f0998b2911ba86337ba79decd2701a4db1916e01ff4bb00000000000000000000000000000000007bfb52f3d4a281238eb65565af329b3e043e412588ae00342144d168d903cdc9131775ddcb5217ff692b0f922504ddaaa3300f5a2fafab132f5f4662c1d288210e7502ca2472d060aeea6f2eab2d71000000000000000000000000000000000ef8ba702c88495b63ac012fd9ce54b4a7ed67b5f7d25bcbedf951455fcfa95a8c7775c5ccc875ca5bafb9bfa1af738e000000000000000000000000000000000e53e18a3e7d294b508ec4084cf57557dd1a96ece8eac9873d35e4f1ee812a1380bf56569e5e797ef54202b1ea69291df6608f7c036c8fdc335601ac55e869215eb4e626f52bae813d45b827df2afd4900000000000000000000000000000000021ef16de941ce6394ebd484f6b9de12787aef9e7921292106e6c1b18b8de5c640e448f53abd536953b07dc41db21ec0000000000000000000000000000000000a5d482a1c20571e03501b89d2bb4c6d3251bf0b015f23ecfec87dd7cfde705f946c311483ffc84381609c394c83513a0cd68c59b1371c7063dee5732182961be90b95247511a5b564d7eee8d2c7c6470000000000000000000000000000000019c277726fc9c53de1ef3aa2ae6e15b360a98b4a2b27f9057f91eae5b2a308b2f5d618d8e458839d1d60105e4888e7920000000000000000000000000000000012ea8dedac124f05ff58ac72fc967e325e00e83aeedf956adee447720f491ba1bcee564f52e4f0e53faa106ed8088d4cea52329555d9b79eb1fd6d186df80b25245ba9225553f402cfa6037592f0b10f0000000000000000000000000000000000483da14288400f7b27d712ad849fd7c068db47709f78b297c746ab3e15f17f20130b415c9a1b024bd5b24f74428f0e0000000000000000000000000000000006746bb7d3a38fd833187a16d5500d394303e2edf7d5341d787257a9f811411a5cd586b300b7b4398f9d266bcc27d9cecaf39f2a517d432d1653c37fd9a6c4a8a811107dae428f4b2af3b12e4b6acea3000000000000000000000000000000001700795ca26c2cf7dbdb64034e45362295b7e9c60753d728bf689239b0ad7073b29fb872aff047605509ecd10cbd4fd2000000000000000000000000000000000266a09604de2ccb74c5d97dfe4e9a74cf89d3612de9b2d2d39dfa3362b500be127b83566a61df49e639d548a0ecfea7ff0bad6dae80d5f47dd8c208fef0f3046cf1040112d18c596eeb934762977cdc00000000000000000000000000000000146b2b839ff63d376db418a51890c46b0e3df6848a5a39a26a02673e93ea8dec5079e89a333c85785eb0cd1d67b1e101000000000000000000000000000000000f57e8e4cdf2670dc35a12072923d334523e7ccaca66795e3a762bdda8efe5424f88ef7e4c48b0d6760234ddaad4d7370d0c40e5d422685c5c83716380eed82392ae1dc6074a7edb5759fa34a61db2d0000000000000000000000000000000001989144efb1979a42399f93fa80bdf256316f6365bd82b89e0e2371de79ce9de2435a6cfe9704ed710bdfcbc8cc2bcb000000000000000000000000000000000084230cca1eb5defbf2f2ee29fb2c47b417919f220c25bdd2a017b514840466a45b2c00047e9628852d48a057d6335ad7e93a16a443d5f981a02f0b6866536dadd276abc0998bedd76b168ebc8e31b8200000000000000000000000000000000128df806a651c43c7e0a3b2c5833bf158ea40953fb0efb02620cc4ecfc4c32a409a8bd9e98e82812b54d027b6346afc70000000000000000000000000000000005e28760f1e574aff9664e373622147c08538ed45cdad72a546e4b5840758f5ed442f8cf24cb0ba35902e64d084406f32a1d13a64c03585715908744481c79f340b5bdcdd88d685ab8b91722ee7ab719000000000000000000000000000000000289520e710e7ce4a8a671cb00a015dcf40ee2a69309cb89b514f6fb2c6e8fc92a49905893e3e0e9567956fcc86dd89c000000000000000000000000000000000d1329a4174f802680dfe8410fb45e23f96eef4649579ca8e29b3040de33cd6bc485d1339afac9593097c70a0312f5162bc6979fa2e386abec058683c6d74de31af3cac21283cd5e4244d7edd94da96000000000000000000000000000000000175f1ed2dcd584f9c59c9c747ea1841792bfd9a64747f84dfe32e256ab5a48eb2dcaa337990089c86b3dd589d276e2ce0000000000000000000000000000000014d8bb6e278ae9bd9df2609690286be593eeb668f5e2adfe880e1d34276ec3bf4ab5514c7898a6504da63e0ecfa49d020f1937936cc3766184e47f39acfe5af4497e8edf77ab34083135a9ced61d25ed0000000000000000000000000000000018adcc61d9162790bd8c19be058afcce08104a952b15efc276af8a8807a4d2edcf8557aa03a297ca01d6a3869160148b0000000000000000000000000000000004338e5f7a12f2ffdc8158a51b14dd36934f01d7fbfe45e18276f2432b1b8210ba6bc5f246a52646bdbf99ed91f2f48f639a8b60a1849c71688a11e612b315439161717f525b5deabbce75808470166e", - "Expected": "000000000000000000000000000000000c1f9b78641053cdbdd6545691d1a5238389614524365bcddb07f9b9c6c654e58a40047084532b8473c7d541ebb187ee00000000000000000000000000000000028eb1aeec5e4672c41eccb45b356529e5331bb5fb0ca8f9e10b20a2ef1ea911f03af896ecf7575613bce5eb8a0b0837", - "Name": "matter_g1_multiexp_77", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001242be79cbeb2176ecadb07d205d532bdaaaa26bf9103371f2c4d86ed1df72ba8b6d5c76b7aef25c743ec4f43e5237fa000000000000000000000000000000000d2de7792d0655ebcbdc123ed6093ba68948b8ea156a31b9f23d1abd948f4b2ef2f27a3cbf72b9e5b3e966576e9ffbd5f3efcda934ec9d2ab05f25d618e5a483e830d0452a88e980589fcd7cfc39e5d8000000000000000000000000000000000fa50f78e45b1b7b61f8508bb5842bf59d0f41f2a8192cccec6e56125ff94b402dc47d3bc7762f3196a163fb148105820000000000000000000000000000000002933cca4d82c6f89ff8db5f9239ef8fee2efdfdfa22e0b4d0fbe223910b08060a77eb4328a05ddd31d205861db090ae4507a696cc57c0bc49fb4d1686752c71c9c816d7d09bd66910b23810d475aa02000000000000000000000000000000000c15db9d1dcf646bb4c169490256050ad5e408d1f45221a9b4bf02f7651fe93ffb892c98d19d730bdf3971281c9e2e3e00000000000000000000000000000000150a6d1978ec63013ef3dd3b258ea3a716c1e564469d2aba343f3d15c30cf287b706b9eef8363351cccb79ecdf5aa189518c1259f23de4cecd5e3a40abef5662b497ebaf16240f40ecd651d2ba50af07000000000000000000000000000000000f7e810001b9e3a11a535f6744a0dd357cffa585baabf065f1e72c9bab5484829a94159c72ff2221406c8b15de465f8c0000000000000000000000000000000009d48808fbf21370420cad4df7a269e1eeac98d2aa5ad5890ff362d91cca5ab1b57fb079caaba3a135c15515e98c6b175561616c195ccc1345421d8a6efec48f0a4dc8e89ee89599839efaf95c38655100000000000000000000000000000000191dcaf13a62fd6de0bdd16151b3c27f54b40ad82da1299164da87d0cb7b4c769f941c39fb4b68a8915fa95a5ddc0e900000000000000000000000000000000008b0ad7fa07edefa61ad026d42df18273b6628b65a4e655a98b705f588494d06c37153ecdadff83d94739bc254d6d8f837c77734125181c72454bb2d37c3725cf1f9b6d6f42b721bca469fec154b3e260000000000000000000000000000000005e3001f37e840a9edba48b3b436dce520203b0b36c3871933464be1c41178f7a8af9b14000b713ee8fc0faf5cc1a870000000000000000000000000000000001732dba0dbadbe7db31ea6af17520d791feced0a7bca298b932f51f3dbcb355699db533cfc8b61d35d1a346ea5de8032981483aa66e04351f4340fd2b461165b9a9983e91c148da78d3c8e0c69e77de400000000000000000000000000000000072e4d38aa0e168255f1d69ef129642b4b1b57289e630455b147574b03d17e3cf0f32326afb7c45da468e0d8c2276da9000000000000000000000000000000000b60685ad05be8453d5d272c73365d645dab6c50c820c1fb7fb50d82eebf9b03ad3c8f711140ddaafb2bb128b7be2e6c9913da6f756005ca8ab900ab686484483af07df768209a16d807f8b88b9334d3000000000000000000000000000000001401e023aac71de3398f89893102efa8760cedf47938a655983d73ca8d394a239f37959e629cd908b4e4f5e55955b153000000000000000000000000000000001458e304efcf48594d7094d30a804742b08ec94ae479cf5d4e0575828ad92cfe8e11847d6078f5eeea4308a8f0644172188fb33fb359f21bc5bdfc85d39676c2ca0a1e619bf8a8e8de62da8818bd6cfe000000000000000000000000000000000d446202ebd7a7995a4e8aa7fcbaf6c4c4591c4bc40b374720752a150b452b461f59b775e3088733ca967854413a9f0a000000000000000000000000000000000d5fcb5510c0f7ee77c7584631149cd494a5fc496b325ba93ac5f801e34c815fe562be4758212f32ab0978930d142adf5525ab4c4468a2ec0beecdb7fb072f28260ebb3d9da1a4c274b2c11a087e814a0000000000000000000000000000000000e034e4027e846a8608680995860b2673854d8fdf0e61e2663d7e0d904b6725ff28bb4593e7bf5e2c252d9c9710e39c0000000000000000000000000000000010bbf60b95669468e5dbdfe912dfeae9945f44454df62ec116b097b867b14c402349af692490269797a30639177151945ab5a55a5cfc49cf6c36b5718e108f8d006bf7fa1ec3dc7a7f9c02a2d1e3fc5700000000000000000000000000000000095e1315b3568e8a069dee00c3676d5d6ad94a2164795ca5f1418cff4a25052e741530c0df6d50c5cbcdd55a084227f3000000000000000000000000000000001993b036a3225289827691296b51ea4e42735af0506b317932b6719a381a59c89871a2a394f4a9de0aba3bb9a2b881f86ce7aa7dcd01c1b7059ad3cc0ebf5d19ceaae633160a968c33aac5dc6adb94280000000000000000000000000000000010aad99bc8570d83847a2a2688fa61d5d0ecc978ae842715a084d99392db343f581290478bc1bfeb8bb692e0d6fd58ec0000000000000000000000000000000004f82c0527d3e9329a6b460f1d781f881073b87711771699e9cc8c4229d5112d91d4357380c12c120313d2c9eb7bb427854bce63dcdc0cf408b43690abbbbdacda5f3ebd9d9e462f89f9f50a9f7bd44b0000000000000000000000000000000008ec7244587110fd3fa0e1888427fbb3942d0885e002e4f846fb749bfc4a82bd7edd15cf81af454354006a2ea85234f6000000000000000000000000000000000fc7a19df5adfb5a154f32b9022e54b1560237f4319160c9c945b7bf4b55e45fc86616d3ec3cecc177c9f6bc54dd2cdb7603824b834a83c1c408243b51cd2c2d31e2ee763d69e2ad6d369bb6aa2396fd00000000000000000000000000000000037ab89247516909dceeb59abb90d6968ddc3ef3abffac93c68757f3c9309d145cf9350e4d8f85db810cc5f156f8f126000000000000000000000000000000000289168c6dfdc25ea10e1839e10ddffbb25522be7ff80ef321241c6cc887fc7a42586dd9c1686c6c5c2e4caff0278155923c86e91c48582f19409b962be361da5936db02b6862eefc288f9a32d5f5476000000000000000000000000000000000523020b4c34e867e75cdc668e541cfa25f2afc35573b2db083987fc585a487f1eafbac1c4267d2fdfdc5d2f94c51a84000000000000000000000000000000001581bf2744d78d680c9bb38a3f0fee76b6f0231f011b3f7ab3fd59c1ec6c99fac518857dafd410bce2e8610c6e5efbb1e1b3071b561a80aaaadb5cc24b348a2b6012340d3aebcca7e2f56983a8a13bf9000000000000000000000000000000000615745e737980a923e87c3ef72330f55e38434b3974c1cc997a9d1136527de9bc21dfa73ea0d33d27324a53f12bf6f9000000000000000000000000000000001164b6ac376ef24ce3cba8e2ae74eb58437bbbedf68b4d0b6e8b7e213a789c8c3b7f173bbe52150faed93fa83bce0a9db6863b755d3dee61328a60f585531c436663bbeab9afaffac49b6f0b57614eaa", - "Expected": "0000000000000000000000000000000016e6cb1f899ee8f3db4b934c1facb3928b08fabdce74f569a06ae6eeab201925f6acb1a47ffef3c608fed32c949786a7000000000000000000000000000000001796fe817d2e4a69b4e8c539f6f2179a802cb02caaeedcdb316b3ec6571c13c349e115a7a05b296d6b182c8a618ed918", - "Name": "matter_g1_multiexp_78", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cd7cca90c8742e7f541981a13b177a4e639195af5f15cee2ce37b01d50fb8478a3f0d0abe4312a4d92a201b4dbb030e0000000000000000000000000000000018e2a69bd1cd9bb7ea75ceedf28ac9c9514e8d28223af69dc991e46a03d8d272d267842f30552583a1f08a07188058ce13ca0cfc742607bee58988df361d7cd5d809ba4fddb209c898cd555369fff5660000000000000000000000000000000011cbbf1ee7e9cf8deae286ba67ab0eeddabd2471d2ea15e86c77c4f2f23ce38e17ac3f3e3c2a40a1640bb3485be4e59600000000000000000000000000000000108e9f887f86f03dcbd515501f69a5983b4a6d707c26b69cb9ea7a387c5a914612ef645cbe81bf29ba91d209e839c72abcca8ab454fbc576a2b910f140b23c23b14301c19e1f47989d78eeecf279862a0000000000000000000000000000000015c1856c661396f8e3a477932e1eea7e124b2e9ae0dfb1df67c4b3928c462cfbb3220c4c2fbd755fb6435e144a2b937e0000000000000000000000000000000011b114659fa71c3ac2412d5c2cc1e184f05a45871e5ab08fbe5eff68ef9e457c4f3e2bb4f16d10e91f7ee2231bc3266359f82ceeb6160d3256228d7a41fb3caa6f305b23142ab979e728356a13309e27000000000000000000000000000000000b693c93d4f06be5bc8a84157c6f407c3db14175c56310e7d041118ec869f3992f75809b209f6dd01085991deaae2a96000000000000000000000000000000000ee21d90cc3825b401e6d452e27814672d849386eccec7be992581b1fb9f4ff4f3892d63e124bd669603e6269f099452995f7d2038ad02deddca34399e5b5653fa471d998c52bd52241840cdb9202b2c00000000000000000000000000000000013b40cfe91492dc53089325be73b5d404288e8056e30cfe4bf3feb6b854eb7d0efa3ac4afa822162ac16608555ccc92000000000000000000000000000000000576146711dfa2ee08bf08121c30fe63ef0ca4448b28076eaba9298ab925c615a56d497044be803f73e9586763aad52497b67e68bfe2d7fc256e6aa610dd91dc1b02c64186d24702ad8fa9f715b582a50000000000000000000000000000000009d66d52069b0d23faa33818a8c9bfc812ae6938dd02604e98a422f50c085a5641a46272dc9c8801a9c76cdfc2020a0c0000000000000000000000000000000004dba0f971336c813933bc6386e55044f5e3d3e5cf38ede5811b4e775fb41cd09d7f136d9de6fc36f2f435b8cdfdc26198115b9f84e3ed6947bd6f0e3c65361cf360a65bc059515da852a72ec5cd17810000000000000000000000000000000005ae8fd5c52fff0b80a2c5c4fca4bccad28f580c94edb7e28ca2ce2390cc2fe476a2b11f63c3c8759847e647d5fe5d1f000000000000000000000000000000000edbff5012f6efde3a9bcad65c805b1c4ac0899fbba5fd760513c673ce8ad18d3baf28acb3344f511fd4d9785afea33c27370e1037b709015e0bf178a41ac55774a813368e11ef7a764eb48abe75dbf50000000000000000000000000000000009d003d4213a46812ea1565bd9a6f0f3da1e69e289f026e619911354cd7444dfbfff1d842e3d9c61c305b2154851b29500000000000000000000000000000000070a1387dd16f9d8b4306ecfe0e9ba7aaa5959ec917e06da4ddf90c992fc569a56c61f6372bd26e21f5cbe7d720b68c66bf5fb297948e0ddc60ba26e49ef2892ca008e64a22ff2bb21ff70c56112f7100000000000000000000000000000000008fccb033a3e10a0015b11ffe2ed5f4c96ea2262d06ca4b0eabbc15c9b299a5220444345c65e7092501b56599980bd0d00000000000000000000000000000000127583566286e52f2f2c7809cea1170a49993f171c1c217b82c17983e02b7e69cb8c948725c7a613c41f96e80c3f1aa96b488b6b63cb8bf34efeedd9f95dff4d3d8c067c0d807bd1e20bd267748275d000000000000000000000000000000000084501b09915fa13908466d6bd50a7e0d8b39893bfcec9c6876b7ed8effd100b8f0a459d754efb6b110af2becd882cfd000000000000000000000000000000000373669b2a03d3da4e907da24c61f5e7928c5fcef4e6c9ad4303fc4cc2cb641212680f7c33605212de8914caa58732f44f661845e91de1c09f581c7612a25bfa0889f77c2add31b493b37d20bcce110700000000000000000000000000000000010608a9f87f46e528d782ef81493625f9a47134832eecca6471d2113060703750b679e64179e7a1c1c81311c38c493400000000000000000000000000000000032a0c82e42be6203415638e6cca4dc1621f87f030a9d742bc77862f4f10ceb44f1ecd377acec6587be0fdc33d8c17c98b3bf8d5e529912b1b6e445f592a6d151c6f5d01d3b021a31a2669df4ce02aa300000000000000000000000000000000126f62cc3033b7235be5778289fc568a1c474b70cba2d35a0b9fdab5cf239a2d4fb03f0bedfa84425b142c04284da058000000000000000000000000000000000dc1f91754d582f57b413fde9b837cbfe3430582b0964620b02bf854c6f666914157d44a165f16ca1d7204f35caa7b0630e1c8f222019b877e66df0b6201b5bfc5b6c10aae340c55e74410a536ffb9b20000000000000000000000000000000016d277ee7864b3af3102190cc99db1cff9fd1b1d6e7fc039040149c5944e7837895532ae41b4db50e29a5d6bad7ceb630000000000000000000000000000000016c3f6e29114782c84734cb927d1a89b7755c3a8fbc99076ce3ae17f7f1d088e5fb9757237773fd4e14c2855ec12b93723a258d66f2296fa1c71065cf23c994eb8c6c35d35120d16790fec791ad215fe000000000000000000000000000000000dc8f59e410ef7145d636d2c7d43fc4b1c903d6c8c0efc3ae162293c7c65c48182f9a25c4e5f111635881533cc558cf7000000000000000000000000000000000082dcb0872d815465131953c69e260e3a9ae44d16975f361b5effe13ab1d61c18f050108e73f50871221faf28fd79771ef4055b85f37b548dac2b64608d99ca293548bebe1e24355393520c34eda60a0000000000000000000000000000000002536653a945e03329279f382937d72bddd71ff8f19053e1fb19ef83d9751eaf101676249ac65fc61a0cbacbfca3cfac000000000000000000000000000000000806ebe4d62e62904ead05f814dfa6e8a392b887bab4aee61552c6f93ea5ffec6593e9078a33f4cefc96393a667c934c212529248c51c95b5b26961f27e6d44ef1c2b9233bb2ed32c3eee79ca6c6eb750000000000000000000000000000000018fe7f7093e0313737b8e0c6ba2fb0c93afe1e8241bc769f14cebbfdb4c73aa578fe3d37ce1221f21aca8af9ab99201c000000000000000000000000000000000ea0f2ff4c8ed0a51fc8fedaa056a369c5e97e347c6883b215d0f7e019960c0178a7962415c220766c16f4596d4b9d8ce9888dd839d9b8c236394c44d358f452a4588ae65d24ffe2bd345fc745de9d37", - "Expected": "00000000000000000000000000000000184197d1ebcdaa25c041e95424bb891fc9eb38160cb0d91e702ac283280c6df697ae85674eccbd0fb130b6f2e1c193b00000000000000000000000000000000015593ed27279ca601616dfcdc493b8c7bd68260f97f8a9f10c03cf871b17cf8f492518d2f8569d60056721723a0172dc", - "Name": "matter_g1_multiexp_79", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c31653abd67897b3bf8f046712b12d35ada1799d1c18071182fb61273b7bc506779ff2d774576a725f2f1035431c82000000000000000000000000000000000011b2fab972f183c75df3bfb7968dcdfeed0755f71ec118e56c61203e97064355200c5f016b9ed66040fc886062dc58f812322dc2a7d5faa9e4877638faf8492d84e0f4c4c65ca3aadcb7eafed2106400000000000000000000000000000000030d7e368c99113318a6657deb3c89424b9acbc5e3568e03dbf629333ed3a5cb45ce6988a3e5ef79e5ee91aa6b990b1d0000000000000000000000000000000002700af33eedebc8a4847d6772cf615413149e6d98ba3b36c96e43c8d97619cb01117570f263bb2f7579c7da67f40a25c1f6d538c5b4ae15c84581f8fd4c61160ed395816557fde197e1a013ba41ba0f0000000000000000000000000000000008cbea0d07e870d679cd20b4ad088bf3c5c23e83266b20e816f69bb918824c9bb4d0b3216f8da5a5cdc6f43359e02d06000000000000000000000000000000000d1c9949921e37e73f95b0e4c444e390bb71fef0d893d1b341b9338321bff4a23d1da4ffdd5d7148fa9fe9cc52ebbfa8f2f6a4713eb692f7667fba2a3dc35363c3ba163519d95757daddefae11a958530000000000000000000000000000000003111c080876670db10abfc439b17b32f9e96758b057d3344c7823af1b0320037906b1a9d8fc42cab9e9e0e8449aa997000000000000000000000000000000000e0c7d19a0362a173b70b6fee3d3feb541c7d2ccca71f1f01f8bd105a18024fab05e0a6d448153139f2777b189ba0fe41022e50c3fe7b2a65aab79de6d9e47c457d197e145592dd0611b1dc39941513b0000000000000000000000000000000018bcaa4869a5c6ae46e6f5fd5fcf835965d21d48871010245e722bead79d844e96e10558d71e425377f4adacb3f74074000000000000000000000000000000000414d616a4207e7cf79352dbf7f319bf554f043710cbeb48aa502235db7d30f4983b5381269f34ad6ad4fd5ff56d9586b80011c7a4aa905d4db6d4f6ae46eac9eb8bb18613d4ac5e5567990d7e8fdd96000000000000000000000000000000000c86dc8b8f38d1e4281269ca252adde9f0fe933d4cc051c7aad55f96252d1e6f9eb6f4f876e153c11b61714d985d318c0000000000000000000000000000000014113f8e2c3ac4919de334eb5c04c909b88df39998e58883a5393a4d760cb6d07c65eae053a7b2100ff3028a786782bff397789685a736375ead2312874174795586e12b230669a90d072fa636128c7d0000000000000000000000000000000009b4437230d9dae44852d88dba2655070162501702998ea5a035cd88eecb64ad7c9ccaf696545dff98d778cd7400943f000000000000000000000000000000000706b196155640680b257a537c836507d95e6d5cb7f163ca340dc0f8b80859721b7b2a2ba51dd4d72ccc4c3cb91030c928e325fea39d61269c576626984f85ea43cd683b08c3ce111aac0005adda39c50000000000000000000000000000000017bf848757da8e7ce5e5e69574a9b31d35eb628102897922d4c996443fbc970374ebd601b96b3ca9412c13f50943c7590000000000000000000000000000000014741c0b49e4f02630a6cc1a723cae1a6a9862158bdcf996b46a9614dd34527a859db0b5718788eaf2caa059671f3c683cfd9bc41303803a0b4edd121b818a126bece309dfee4133aa5314cb8a91d08d000000000000000000000000000000001269325967fc68b78cee64d0386e1fa6ecaca1f85d672f8b63831a1adfcbdbb40461a77ee0e59b1fcccb7c1d543f08a100000000000000000000000000000000053a22e8c4219e4d68a961c2127201a23443d8fddb02e3756cfdf74e616dd4abe73c4ac498ff5f6a68d730c0050b79e18e08fed30e422868f37c422d1efdcc93912d55b0a731479af863dca4705e0c500000000000000000000000000000000018248505148876ab5a5ec3be7e3a6cbac30798d52f437bea7e966921723e6a4a30a0e53518e109d1683f3a4b3432136e000000000000000000000000000000000120602fd461206973e62ec8a3f1cfedddc1e9f9e1769ac06e2a1024a9af19d402f40ffe30f9cf77b8704497d3cba4a3674ecdf795b48d62f0db0f9cce057fe570d15c78f2eb7a77b66e4895a45804880000000000000000000000000000000009cf2460e5121b15d177b8ad803c045529933d1abf62205d04726b67d64fee85e2008b5098ceddc42d5c8d95d39147600000000000000000000000000000000012749abe2d8b47bd9c899b6726ccc749bab2786e9568d32299f0e659664ba1efe764944c4087c549e2bb717c87c6b876288fc80d07393f629ef2732879332a253b49d26ca7b2bef7cc49ee40530b2b340000000000000000000000000000000008d764f80994fd37a21f6923d7fef255145ea875c892888d45efb7a37310182b04d2c16d4d91a2e7c41164706afdb617000000000000000000000000000000001156c016a289989510f1c8b39bd6a8c358a1c5611bd2286e9f15983f984e89e061e60717f1b700abaed57076e148a8a956e69f4ce8fbd8f86f546fd6d129f9760edce7c5e178dffaf987bf565e9bb7e9000000000000000000000000000000000734cd0d73ef7d79fa501b98b7211d551127abf68c473c1c72c591180b605c938ef71f66c422bf2a8bcf16c6c8946c050000000000000000000000000000000008ded96a9fce61040c1acc71d6496cf72590c63c3514c4f1f77d4582635af9eccdfab2e60749ed24fd3b6e30e3576c58ab40e86212189e6f5925df810141c132eab20c123166cd8d3c6f40f5dcf1b1cd000000000000000000000000000000000df9ecaab534bbe9c8531f813a95a7733df6a4c8785575c5ee89647941a6984cdb5a33d2eced340c683339c18f5da32b0000000000000000000000000000000003632b2377ab368bc9f735609452e0ec9fadd6f261cd5352e0a5ed6a37b25ff7a49fe57452e79e7330661b81d7d80a64b96a5b6129c58113bca713e6905c026c0bfdb6d679c203cbe2b256b0a49ecece0000000000000000000000000000000006bc4871c0271394c9d6099667ff68e1dbfa9980976075bf81fc18f1875fc91b50a0e3be622882c90b1594419da7dbcd00000000000000000000000000000000168e1dfde47d19280dc213bba9fbb61fdce41f81d4b25b2a7abae0404bbd7a413cdd89611966a7f9bc32617dca51f369d9d8147c4453cdeed971242d316e350abead3dd08e93ee54738a4a5aed23affb000000000000000000000000000000000132a2a6832653eac18e2fcb2c336292dc7990fa1a004404973029a227c9871181ffdd88a74adc3edc7a8308dee803fa000000000000000000000000000000000b230c171d5739fed98d32a3b27584bb0128434401e9e05ae09a4dcd7a017d1cefe7a46dad2db5addfb389feb9c846181ba8e52986d3bb0421eb53b18ca8c21b9f7e631f16b99ec56748baeb541b32e5", - "Expected": "000000000000000000000000000000000cc6517e655697449988bef516e60c8202fa48c3573967491ea2ff2db9fa0de3f542f656228a5b90d7fc1e5eaa8b06d7000000000000000000000000000000001191ca6ef2791726a31f77b0431ebe170d8fb595cf6e6b9b33b7fb0d4acbecf2d171884c392832d2a91832e982c5c0f4", - "Name": "matter_g1_multiexp_80", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000111de2b65f5f94851aee2861910898b74dacf013591772902239ff7f71a9cf84919bc4a84d6936f9552e97314eb52e7d000000000000000000000000000000000db96af045180bd4d88dc8c40f8cd918d2195c2f3651c176c1ee3ccb583a7363e2c2c900f2a54f26a881938cba98565f7d39b55aadd47afa3cd35cb85a89e729ca236ada965b99f64ab302a84952babd0000000000000000000000000000000000e48144181d956ebb37d72c38c062958f73de8944995c7e7568997b04ec19949b348fd80e810632462ce43c7c6571ae000000000000000000000000000000000b4a19556d8c21206c4198059adf5ac2b8a0e08c948a8a4d7465bd31c5ce5887a069df5f80b1df89ab868ca53e16c730c41ece17a6d8b4a22994227b37a9d73e17a88859683afd5d226e113246e70cb10000000000000000000000000000000010547f218e33dd9f9425c8e7be4136e65ee3dc23e0cdfd5f1caa8986162cc13b77d30259b6b9c359ab0faac9ba29bda00000000000000000000000000000000006729e532ba87a77d1e458663690110cf63eea96f8e41a5a338493ff71b68e78e78b9c929006c0410c3739b15ff2810069700dfa3b6e5fba735d1fec3b3adc90719ec301c406ac40673f4e5677da3227000000000000000000000000000000000d3630086b7e0c068c60192be8724ab4d18409fa6ddcbed02b52fa776e84e2115457c40cac7e903047fc435114150d5c000000000000000000000000000000001066ce26d2e940899e80e9c0e515ce9d5810a4048925a7ddfe0cbb24b3d8d654c6835c6872fff5a988f525c648661cbc19e8eed297661c06c92075629e163e80a08835254f7af8c0f179400be114ba7b000000000000000000000000000000000ae73f595bc9d22c8c959eedec4d1301a13c9b8c643f4335160bab4a99886694d112ed6fbfbf082629b76d1e2509ed280000000000000000000000000000000013dc07950689ba36736838714eeb28ff3be77ef8ba181718ea7b5229e01d4e036c98eb9ff7a867c017857c029f7f13e3199ca6fb7f6df8a2e72971c5738ad75d84935e922587acf3a6b6debf3c37bb5e0000000000000000000000000000000016e11b169dc405035037a10180fb368988498b6e209ad62260c7ef45e9bffedbb0587fe282d193bbf88311f3d2880cf500000000000000000000000000000000090a277517ea7a1a7cbd68598aa1e16977cc57c8d095f66a7cd3f67814c2b8f35e17e20d7a26fa67274dc5aecbe778648159c6b98bce6ed31c30957280d8f7820e9376093d1ec9ac68ce0777d02b084b0000000000000000000000000000000002ea8cba4bcbaeed7feaac63caf21645ddc97daf9250ae29994fd04e798f94dab33bac6e08eef8e6c20f122bc5f88996000000000000000000000000000000000f7a0f6ac02bc9821a883393c8265ba748f9d7c3ea763037bde3bb0178067e93aea4dc70d25e5bcda642d06f41a7f18bef1bc580e0b52b10b049f07d5115a60ba96d14a39e48ddee3c219f11c3b2a82a000000000000000000000000000000001618ee9c413dcf713699b7910989c20bffc5ba1ca03e973005f49084aba558797e7f9ec20cb86f308d737b97c08f42a6000000000000000000000000000000000db1daa5ed21250c696ca4da3e82f6623c54d643d773286811e21c09e9ef7c9ecb9d84d90b9c76ea9f65e04a29f82750d06f6ed682c56611fd060ed2b3b1dc48974769ed6dc504ca3e0b9f68b77e63c50000000000000000000000000000000012aece7d9e7384ae79e047ca4b4fe72fe541a825530d6c38b9a8fbbf8b801883ccbc3cae7c33e4d811198a7b7876c92d0000000000000000000000000000000013fb42fb1b4e7785c1b66364de150d1e38fd9fe3d8f209b7c168beacf4b26c35fe0fbb4a41f30adabe4314b20b16319561d7b314ae9d9e78f628ec5a207d12e2dcb690688d256fe46e0affdfcc9775ae00000000000000000000000000000000033fce20f9202b89411dbeea59a5b1c632435eaf29e2739163b0837ef9278ee3903ae569931e70f79a9af5a2abd29749000000000000000000000000000000000a50360c73c3f735f97d7d71b21b2831f7d7fb59c594e85b604dbb79ccc884349cba8eab9ce613ed60416994322916db03a0c47621401fc20d2c78f7e30814de9a6f838d4328a5b5be628b833c31a6fd0000000000000000000000000000000014d9a7dbc453effa7a76c774a289957b0ccd72994e568c0de345b482ed2b6db9a3a3e56e0fda159c25acb43b4a6765d5000000000000000000000000000000000b916f28e3fdc62d296e421b1684efd4e9a4b523f79dfaecc00872a1d17724e1e07e2386b4bc6d76b157ae94559d0bcde4ac6a5e740e073c5ef8af389e70c2cb8ee8c4c04c2ab4c48c579e83e181005b0000000000000000000000000000000012a4670c5c2847bb188464dafe41360f00621ceb3b5da0a3dcc16732f4baeb0491664ed8c2f95ff9b44e2b77e698eb3800000000000000000000000000000000077b561ed2fe5c91b30a12a2df71e76cc4ac882301d1975c3cb176e22874e28868655db9d0c91003442b0277eff52669c1e20d8003fec60f68c03942185fed934ebc197c2863174442d1a1c8d1424d31000000000000000000000000000000000570e1a0fe7f82c0d3cf38d90f77634f8dc2bf9b58ac473d9bcbe7242a4bb76d11f36083c90588a680004c077e957a9e00000000000000000000000000000000038ac2b58a16af0a3a0070faabe3969025440d9781e3ebc22ff873dab532d6ca1b0bbf21f32eb9728a322c158f5390fa7713ea72a2ee99442232472ab3dea9307a02fa1279129d994af5588af4fe7af40000000000000000000000000000000004a3a287fe4401c48d7dc804363941b5836cfad6490b00dcb0ee830e876fa05a42d6e2b036a4e213bbf5b6ae5a4e31ee000000000000000000000000000000001877a91254211b2af54ea910d9efdf4b4e829fda5bf6b0c2dc849903c357bfc6f55b45c7437ba538ab6cc795b71e95796f128420cf6ab4616a05b287191105f25c7212f2c39c3230fa56bc27cd06ebfd00000000000000000000000000000000159bf4b0dc89cfc9d1687d8552489b5c3e2ed059164197028bc67c51ad18b341d04e4b8be660880a76a44ef11e785ab5000000000000000000000000000000001643a41fe4104ab0bb96200472ca67064635bb728e6d909fc0026216a90083eb612f11bd5983cf4d7fe664f1c527b96a12bacb3419c34369dbfd1c968334f76bc50885028758a975cc812a04e6feabd60000000000000000000000000000000003dc904709f1da618b6a623888015a875b11e5baa5c10eb6d750354c09359b180858bf29d24bae18e7c78c81465659aa000000000000000000000000000000000c61dabb7085a1937782433ec46b0a063a34e102ae9a6b6bae7d82c94e93c3cd05afe19f0673f729761462bcd0d9ca5e5b00f26af6f59620c7130a6d12cf2091b5f52a6b638484fc1f242dc1773be256", - "Expected": "00000000000000000000000000000000109dbdd05f92274f3edb0232b827a4abbe115bd4d51f8a1e7b8ee609511125ecf35ca60991e75a0b7973c4085b7d4bca000000000000000000000000000000000e14a168decb6893e9c447b4366247d997701471a33bf8f762bde44473d516d857d1825255d8b4cee8d04736cb369758", - "Name": "matter_g1_multiexp_81", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009b85ef81b184c6383ff4e2695a8c261ab252ebd81bdb518001f110b2ba72fbf5014214f816c9453319934d8a010aa0d0000000000000000000000000000000013ce486b15a77cede98a46f66ae51d17713bef6dafbb2ff34c8f441271d52f4fa27fb88c5695f4af6d43e32333e68130acc5a8ec806f2f273120457865582b08697904a2c6510bfe9ea21eaf682fa4fd0000000000000000000000000000000006a10f5973fd2aa312ce8f30ba5caad0ae6028bca5c186e4fd55ff4e3f5ce00220b94683e440b09a9fcee238af140699000000000000000000000000000000000ae8e9db6953ce2461bac3be78bebf6c4df8bc57bc7de375aa652d793bdb0899477464097514f0fe2d0badc9027baf3898c15a259b4dbb8c300a39f0af558a9827112f6b4c5eae3d43bbfe057eb113cf000000000000000000000000000000000c0c430ee1e9112d901b82e43a25ce4e5b61c81ed7ac7220d88bd10d44d28c1bd20fc8e1ad85f9b6eb43fc232594b4f1000000000000000000000000000000001233dee860032e2f9a67d7b3d61cea99f18b91620b76f8bd178295ac4fc3b8d0db4c4ff602085c7a897435a283e2a4eda0e68bdc97fd642581f7e62ecf134df2c05570713c96fa733d3db96ace88f0f000000000000000000000000000000000061e9d3a919bdbdc42500b7daec837506bf0841caf35aaac34a3670517a59bf52343b47b46e8212208cd6fdca6b7140c000000000000000000000000000000000b87f7efb446cdba6e619d5fc04ca8dce8e57f6a76faa4a773c03ddc0666ce2d83682f24d8463d9331ae58e8afcc5641e5512cac411cd103fcd7497fdf47d1221999bcecdba30467f06ec356483484fe000000000000000000000000000000001606311f79e836a03da5cacc4e1c3930695372f8f679c8f910627f86af15d1612d653c76d88b9d33f848f94bb63fa1ce000000000000000000000000000000000075b5d9626107a486079315a85991f3d77461b45e5c8aca6876287f624694c8ef1a4f5f0a5b65eefa8d6a4746fd2e5fa32f6861298bcfd4668653544b4551d7357d64f733365a5f08ebf297a09fd4ca0000000000000000000000000000000012bc152cb7df01fd9ca35142806664fdbacb881adcf443051abac7c979d09a1c887fcfb8cad281f376ea3f6693812914000000000000000000000000000000000e32d4d6aa1f5046382c1d5e6e2f97319e8c6887b850b3cee498c482e35319a4f062be80f7f48ff3d1160ea6b18cf67824301fc5c3ab842d7f6a278fcd32249f1daf86a31dd254ab9a21941fffca98a1000000000000000000000000000000001599c2c489535375270f0d1f370c6416c83c4043dbdb4999256f187e29c198b1f6c5bd1a52c997f01ebd3622c40feb63000000000000000000000000000000000b60ea3ee221eeac4a8a364eb52ee08579cf5a907aa5642971bd5523dee5dc6d6584ab993d33d9b8ad9de4a1a4f0cbb117a920aef58100de67c482ae1fabf7ec87cf3447bde1e19d9aaff82569570674000000000000000000000000000000000b85c776ed6c9c78001ec7bf3412be495f40b0978d0582ad4f86ed54464fe562f9e699f727f36b2fc753f4328f0b2c6b0000000000000000000000000000000006e11a826fb4a8f0ac32f5c52a531508ad1363bf9b09919ccdb61ef25baa7718a4829fdd10fb6b680321cb7ef12d0c01d76d5eebc3d099448ce4a8ea6dec047b0f062c6361ddb9e95ec898442423a3180000000000000000000000000000000013539f96257faa2ae642c15f9c04e8fa7b2d6d095f7ca285e0dd90f022ec4a8fd74cf48557afdb57bace088b017b8ec20000000000000000000000000000000006cbc3e4291f373ee280eaface275e0334e46e54f65efc4e18b4ebb8ed1e61941d9c859903b56ed0d4aa3f4f3152b5b4cd4cc1453dec7ae335db989886fc0964ee73e12bab69ce1f1458d1416471176a000000000000000000000000000000000675b4dab12db428a14afd8e696a64c0bb352bbcbecdcf2b064428b489194112f1cea4a383788e0bb0e97b7f88b817700000000000000000000000000000000013273075195b02abac630211c5870727a42e11bd96a2e2c6057d0c96bb60b73db72dec3135122865cd520c525588664a6d207c08e51d64a9a47f5353faac77fbb184e1123d38e39bbada85534cbcd3150000000000000000000000000000000000cb4629e659d5c2d91c5f909bbeb3381271ebde4f8486f76c1903e86efa78da06af752404ebddb3fc5d1a09ed28b3aa0000000000000000000000000000000019202a57e95d8d2623851973c324d1ed64b48b15388e052761493b1cdd6f3b54c6f47d2b312edec23e9da4c815f02e172e1910b704d39b6a64cc7a44e44ba3e8b7e64ddfa90dfa6b5ef571f9ff7d7f0b000000000000000000000000000000000a80bc4a39d62ca891044795e2b78f4eb82a3bf38c4ccb2e6d24ced4526db7c57ebf8b1951af0707af5ae5929f727c290000000000000000000000000000000001cbe991b082e840d8bd505a2eeeadf034f8f8c2bb530c742d7953089da1447e090d82399bc332127f14f1521c95f0042eda0eb154d5f9b0e25a828c6f77541701004cd0293c61ae4d36aa3038d0f18400000000000000000000000000000000112e7894d90a5cba2a8bdd0fa750d6e57c0a9938ca30526eb5289b4a59f92bddb33f59ca22a51d1bae03b850999180fa0000000000000000000000000000000016cf6b093a188ccbf1a000aa860fc794546ab0cf261784e7b7bc5750848f685d629ba55f71f2266edcf24d27667d2720caf6dcd51a851eb200c7f5fc3e106ac5ffc432f756b942b1b9a5dde31cb2a3760000000000000000000000000000000005e2b8ac9124e8ccb6665842d77a2e9398e5b3519fa4fddfc4b10acb5eefceceb1cd6cc733e300ff95ea80d09e3bbeba000000000000000000000000000000001273d1990fa922276859d3921bbd49a452c821a9746c747734692d12c6f7d45533c0a7692d1a2d95e2d2be6dbfb3f6ad106d4a893a68b7fcb8be96faedef65181c239dc2cd752c85ae7800ca84fc2dfd000000000000000000000000000000000dd2c7410b5f5ee63ad2a9ff3a96df2bad103caabe00a9892cc9b2ed2cc3bbbb53724b2ab63cabc44da7097b619f34c3000000000000000000000000000000000f695edd4b67f81f09fa89104c81717577cdd16db30901f4f04ac97e2e0749a80d34422bdfa85b5cdb65c042d90515742b9e1cfbf140f4a3b1d06be656ad6ee5169a9cfa7cbe6efbf8173843d406acd300000000000000000000000000000000113c8f77a2409e0c7ad34186119833605f924545821895a283ec83bb6cc38c549a356b205c24f65be66fa627a378eae30000000000000000000000000000000013038ad87e3b3eb6545a0b5f7eec060895deafaf509ff6687024ada75f700d466df86ae5f95463c05f19750c0ce6cf56dbc68f77d40330ad5b8cfcda42edf57899454571c6c6465c4107e662a269aeb5", - "Expected": "0000000000000000000000000000000015a7b2803cd9b078d457d3b7c62a2418f19c0cfa006739cf3878844c9e1ea115fa982a02fa6fa0cef74404bcf145952f0000000000000000000000000000000018ea40f019b9226cb0428356483f842ad73140a8da065889d81e35a564e99aacc5d5d833d35fd15713ec76c65f9d3307", - "Name": "matter_g1_multiexp_82", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000163b380ea90b97146aa11c64b34de710e41b2ad54036a1a98659046f0e051e5961f30ea5ad78d8052f4a5d2a8388c28d0000000000000000000000000000000012afed5aa2e8c75e437fd796067e0c610a8a4c2f3368752413e6f179bbd4db25b18d5b3f8502186259a6368dd4321148ebb3c942d3a1a15cee806fdb0fc3635483743a5b0ee9c40a48700bad5da53ae70000000000000000000000000000000001bd4abe425f0418c86716516075a3ad09812650908cf383ec1396cbb6929bbc791f5cf65dbd95b51690b58ae3cab3f20000000000000000000000000000000008264362c7fa8021dec396c8355197ce4ef70e7b8894fe23d881d34b9a1b883cba1eba0e54d928b4eaa27aabde0df9b3c193d751c4f24f4808621979f07f03b2eabba75f08bb49682b9df2da7a85a77300000000000000000000000000000000032112872b64559a03629b7ec8b32344b7d5f044670f6099d8e8b1a1d47223f9a42a072975c821d03b30d0994d782d830000000000000000000000000000000016042f6baa48d7c571e1f6c7cf3c7a0887bc4e2b2de51bae133d266dcad23c579e03d3284c09c83a54eff7f2151ce5b3dee4eef524f133183b4af95e4445f3ee5084b96c32e284ebebc5b87f3d76150b00000000000000000000000000000000028ea1499ad8761d908d863849ab4bbc155edeb03a7ef4bb93e96e25ab11c6dd0c21a6f06537a688189f08a00aa33171000000000000000000000000000000000ca3ee57dbe627ae681b12e0de4ed602bc3c09558444f38b0dee27320708549491a4482f7f101e8a722ef85e3fd742a5da514f21c8eab0edb2405e673297bb595edc21027890ad680f1663fd960ce4780000000000000000000000000000000018f397d7c84b8125844e874ea31d18b8705a75027d5324390e2eb7c9962d9de07add34a436db21a34fa7fc7898ef04aa000000000000000000000000000000001591f2cbc58c0841e5eeb8d9c75d8dfa0f2dc5e479d136905abb772a6170d131c0f2c9e8e55ffa215a4bd732c2fd85556aeac9a669c962817c01069cffbd948d9d8ce764e92859f31fdaf85f5aefab7700000000000000000000000000000000135452f0f8d4559ba041dbd2ac45f15416070b1674c9d8094556a289716814d2a4efe14857aaccb82c5ada5d6f0d15ca000000000000000000000000000000000f1c47592319db60db724c9d0649d0d713320be7dcc28e7318517ef80a3fda71fd1f4b722633ed7ab7df06218ee593e940273bda92c9b1b677edd905d76d75875e5b77841befb2bcaf1fca7674dffd5a00000000000000000000000000000000003c75767678539abf7a62dcad5f90a3b4a54354fa70206e789a1f9b5daeb5fb6d9aa222476c68cf9db8a0789d7ad43d00000000000000000000000000000000139bcede61bcead99ef0d9554ee1c19db1869fe041671c199246824a923f5fd94e1da04fa17ec921bf6e82b14f126702b77e16276f9464fa2063230d6c1a4152553536c610062f18565c030e80b5cb5400000000000000000000000000000000020aadb198678aab5a71cd6dc33bd64c47be6d080d24f2f1bab7239808c10867ddcec65e27977b9eabef64455cac25e800000000000000000000000000000000141e58a9f8c9bd92d2de58bf3bbe77a48fae9290815915d7980f4835d805486d678ceee9676ab4fdca51d0fff411ab1b0be15b654ce22ae4e32987babc4863ffe2bd8a459d0f01f68fe84a75326889900000000000000000000000000000000017abf5f132e8e466d2cae445d75978645c3b24284e1b7df7773c256ffc342d1484976ea1046aeb5307f735a69e2fd20a00000000000000000000000000000000087ce2fc44b9ed797f29c352393a8ea109281514490fbc7dc489acb55753fd5c577c4af0ca6c267c83408cd95b355e26c8f1fe94bce21966427380b6d357a3599e9db03a7694159335ffba26fe29e4650000000000000000000000000000000000b106b2b94858155849ec36741c7fef4d97ac704baa6752e8230e172da7208b7e9f187ef0a6cf054d00f2cac99235b8000000000000000000000000000000000d94c6e2349941a20884b9c2d702237c5b5ca2ed277bfc79e53452f1cd6f9f49360215d20fa06df238a7ad4ea253c93ec6d34471ed00035a484f97f4e8123d40ca23b017b94df65540a5551b905e57b30000000000000000000000000000000019b33665a81d0ceecd43f003eb34e1292945da1361adf118f36aa5acb71bd821a6732758a4aa6988e29d4cb70004df45000000000000000000000000000000000f3a244e578c66a9263f020e2f6ce49dd655c7e40a992c44cee40e1c874588e464f6254ba644e46adf348a26025d6d3ef3abd467168bf5e57f71017b5779bdd400dbf416f34f105fe747ea2f8cf4a2100000000000000000000000000000000015618db18e00670281adb20c975f4774aaf169a653d5f583ff6966113fa773075db78507847586fcae82d6a468302706000000000000000000000000000000000301b18d0fe7d0db7793c62b3da072f4cc2fc3425583537110306e31cf63b228cb8c285029044c7b9439c1227d4c7ace2809801eb18d38a61ef8a80f13086d6b1f85ba751cdb8d17fbb9ad5f8d0f835c00000000000000000000000000000000053001a82260b26e34e05a203c8233095da1da58c5f804da9cd6cffce07170e39044394f379173e1340da055066d320f000000000000000000000000000000000bfa2bc7fa0476eeffae4df98bd814db751eeac1dc67205c7629c9921928b55c70c2abe242728bc078bc2685690a38503521c9cf035b094d754db994fce3161842a9509ec8288699680c0ac7761eac680000000000000000000000000000000019a7f78102671f6d84ece4a5bdc54e59cbeab60a8c6c15a708e0169f42a52e98bbc1f8ff52f34959befc859d308fea250000000000000000000000000000000016b5d76caac944612d1dc687c6dbaf10ba60a12b491b17b6c1c876a5dff933c4bd9c6f923e2ca4cd1dab38fb06dfab6a9c8c2998d141b9cd3a82507b6dd97e8d32e9e759169c575eb484e9a1559427da0000000000000000000000000000000007741d8f72a5ddeea2fe82fbce4b3d0aae61e1ab9243ae6a3200711051ac74f30a4dadb597130fd8389353c230b6b7d3000000000000000000000000000000001809f1cc2fc23be0f05b3d12e6891a6aacea121e6db77400638031065d75c7b3fd9a02ded481eb3893b2449aadcf53d6dc83c1ea9e4f4fc12a7190e6c71c4f35d1a676d39e30fe688a05820dd98966400000000000000000000000000000000013d9fdf041ecc7f2c728fefbd6e9da3169d872406b6fa77a52e342fa8852358b02bb2ae7ac77f83e2b25f0120603d0e7000000000000000000000000000000000101ae8e945d31a98c4dc3ba0e01592285c0c92721372bee6b138d9148883970708ad5e585a1b81d82ab0656a3b03a2c00be1b9098f1873ce155a66899877c7b48ddda363ae1d2353cb3816f1ab15ef0", - "Expected": "00000000000000000000000000000000193115466c33711b07826d2a021792b7c238ae67e3bcba00b24026503d818f912c5635f85e85402e3a6b2a8152027afc00000000000000000000000000000000157fcd63d3a0e48e25ca0196b7ade453fcefea33f09123434f418cd1d65bba65a789e4c7d6ddc92d4fe8aaf6bffb1ef8", - "Name": "matter_g1_multiexp_83", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019f625f232faeac09266c2c4881f92c980db551ea236dc1250189c1e71dbeb151cf74e43b4d5f465c6ad92d75457d10500000000000000000000000000000000175ceb7cef0f8144fd4dd82428bade99833023125d34fb296f198673f4848bbbee343f2f2137b55b5f8c5f74032c1ccaa9cbdaa0ddbf854861eac6621255b2102e5343666c735d0384049d5680d105d4000000000000000000000000000000001353a419548d05e568f36adf72d40ba8b30be9a78732660331a5196b0f81b52330ed70e5c635acfa9ffbf083e46c8ea40000000000000000000000000000000013ca17c0dba35a747bcd314d87d1c6558e9f569955aba3d958cc5736db78d16132c9dc8f93d5eaea749a0452c13139da92073d958260a55b70b580f3ee27c42553b5b858b66f6928fe74b4de91c34bda0000000000000000000000000000000019a1bdc1f5a43fe746df46a7559bfa0bc5292f574fc424b134fb8b2d971e191b3c5d222d39515dd145819d56d5379d12000000000000000000000000000000000a08d0b7c7f5d71222e984bf574cdb7de76a7b3c61ab5a3ec202b295c62366dd958ffd5bb5a5c6c84584342bc76199c62117f11d78dfead915a94f11fa7e904a96204ddf1835d3501639b83cd5f716f50000000000000000000000000000000000f2c85f34994643712207fc431219b925f4e701732fce95bfb387ac26ff95c9b10408d24aae5005e437bbae924816b2000000000000000000000000000000000d4377368df00dcde448d8399ceb7508a8fa1c17e9d9a5e09c4fd7c09c253529c07068e4484c7e7c6d3ed6fd3ca777fd9087caa1e89e48f05bad1d720477199410941a6105f911d589e1f94a851e0715000000000000000000000000000000000d1483ef230a2ce75a59e07f83091291d2524b5d043db8d5583914a6775ce2c80368d9441aa2dd53061a8d9121a025ac0000000000000000000000000000000019100e75a72e07391db9574b3fc4aa1c669436fa802a1a5d71146c5f4b7fe118a5ee71a9df50ff67633f161fd151b947255603b470c056b3dfb3acae0dd45bcb3d014765a5181760336deeabff3f00be0000000000000000000000000000000003a88ed50b36d92aa4411afd0a340497962c7740d629edabd505d6023ecb8f9daf0e5bd8ab9dca26ed2ae3ecdfd98b680000000000000000000000000000000013d9d64ab16ce9401988db4855b26b994da09481a339c2a2597401adb72c80718a4df242776f09ed208a8f34ef7f67e6e0eab0e2486316956291feb44de6389b20f8bafe9cc890d86d27a598bab0f3c40000000000000000000000000000000013b16751ff7f6af64c06f9ae6f59e1eb6c3ac76355e6192e6eb44bd1a9f866705eadf0d2907e2458462ad731523bd340000000000000000000000000000000000ae691a4fbf3d0fc72c0e14d4b31fc19c52ca07a81db0ba93949c56a9b75433257d784f7bf0611259dba8af77403f536fb9436456262e5149d02b33a1078e198bbb681699b3f485625784df444bfff670000000000000000000000000000000008ea61aba918d691a0d04582e1f48d671df39bc7de29a6ecc17b31a32d485fb1dbf499e01a9aae5ea21be5d6ff9808de000000000000000000000000000000000f7e8863a541be553b36b8424ba6ad057986a9f78454aea770449a23de70fea8eee6bf8aa30e96e90df9a373917452f70e2724d3501e3d79b85266fd83a2a6156eeb48e749a61676a1c92ab9bdd6b8990000000000000000000000000000000010d41968ddccbb34b3faee226750e99301ac068d8e6f13e72962b53fa2d019da108af82bdadb3cfeecfb85f53607400b000000000000000000000000000000000a90e50ac4e0c39f579a19d49e6f64de6bdd5d6a3f9a91ab654f5be01b258af8709ce1c5a994501177d1c70b25e474a9a49344fe6ea9274a103f323f3d9381e91ae48233dd579944e12afdeaf854000f000000000000000000000000000000000e85db21593e8d3d86df87ceeea7d7853758d69e15edd53fd7da52f0328805db785aa9aa5db25417d76d796200a37d1d0000000000000000000000000000000015d76c5317e1c8cc5a58a0cf0700ff73d92e7f60f4094030716bb8c657d5c75262825fc0683a88278018b4899a1c1ffeb44aeaf3ba8b03e7ef7201415de7365365b828f2c1a38d09153e51432d35b9a70000000000000000000000000000000014c9d6aa24bb34080b9a99d31e1bb431e911b2ccda3c8dae9c2c2114abca597b3849c5b3dca756d0f9ff97616c0b724600000000000000000000000000000000050224129c08fbb2f2d16596f83e2d09a09526851c4d52e8d5f0afdae7001af0006edce648efe7d94b6712d012817ff753961d33104649cbfccecc7eaf33b7a2a486c77dca363ffc9fbc9ce4e8c1adff000000000000000000000000000000000da4574f20849e04bafbc41bd361e8f4411815b9e7c2fdaa9a3ee70d4f608f89166dbe9e1cf4ff0fc9ae98f27e115c24000000000000000000000000000000001463727b23e6afc17101cca45de7d08b78358605c7b1ca089fc52f6a3c46f590210083103e51a122ed0768be2adeddefa04e97c20b42dc265271740f27f1a833bc5b324bcb843a8f9f8a68231c663d57000000000000000000000000000000001363808474ae9481f54d40fd35ed90c23d4349403d43af0dd603f1db6f5fd5ad8b77d21426977b78f1f5397df17f0bfd000000000000000000000000000000000118560d0cb0eb2fcd3b2d51fb2aa379112b3075e1d4c20757ec241a4877af271700d3412a8fd6f3f5a3dbdf4dc8cdc9b688426bbe9ae054acb6c1fdd4195f8a113727f5617642a5b3c0c65566e2252700000000000000000000000000000000040c13a6f53ca485a578c6f3f49d917b774f7b2d1b15ed3e748a47b0bc0be8a7809f0ccf509f09121fdebcf8af46023b0000000000000000000000000000000014fc7869df366473b2c4adc2c0b12acfffeffaf22b4856bed6ec6d15f0f080596b81f3aceab9360e99f35ee7c43f1e2fcf365a86a8d08db5cd95f239a2f3d22279556975ecc3baae0b774b0323dbb1b600000000000000000000000000000000177b54249c613f044b40a11047778c86f09b20ab387ecb8165c83b36a1af046936623fb00764740a90aa232b7f7ae6bc00000000000000000000000000000000040a52fc58007717d6e1dd8486cfccb1f75827c2feb2b7d59b927c4bd23e5ea80d120875f611bed4b7c12b8a5c929475528715199c9f47fd6337b6b0e807e230b1397885fded024431c70e453f55f365000000000000000000000000000000001918e41c557305934aa72aaa361d15843ca77c747ac16cb4c251a2f0d7c218b60a5588b0e5fb3573e8186a48d725e50f000000000000000000000000000000000cc4fa5302c177f9ef018445ab722e568347f4f970dd893e3227756dde9dc8cce3eb2bbbb4c3cd98af0ed4a45c022cf1c32e8643f38f8177b788b8c2bdc25b668308d914fce35c6f9023a769334a51d1", - "Expected": "0000000000000000000000000000000016da14ee1ec80ebf06c0622a500a8eb5a560dfa3439a8e53a19b51c6c4576c31a5486c4c49a8050cc1dc30287f33b5b40000000000000000000000000000000003b04355b2d78266675927706874bb7fa67d441886972a8190a45398942622f09ece67ea74d49bd97827fee82d4a7a37", - "Name": "matter_g1_multiexp_84", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e0ae8df03e4d6e36e1c156a35425a3b8189b56e8ce90045d16cfebf7fdd973d207db6391dcd007c311af34f495cfe0c00000000000000000000000000000000198e58d5278b2a82606af16a9af3f023b7182b6b5b2d685fb667714e9fb5c7a3fd5c98dbcc84ee31fcbeaa8f832d7c854f8bfa3d47ed33a05fe3da738797f18ca5d5b8658055de5a9f85bafe6078f7fe0000000000000000000000000000000007a130c85d67f97fd0dc2159d35be8984bfbe94c28d9d96bca8bab844dffd9a6eb3052c619646a4e564c0d47864b31cb000000000000000000000000000000000e2b8362ef5fa5be398a3589413ea69e98b15cdccd203119b79d96405c2c9ae9ca8eecc7533512a25421e1748ec3a1b74b0d302be94d437b8055586aa77ec1fe616e30552b4d7d3471ea219c148be069000000000000000000000000000000000acec379756a1fe9fa72f03da4dfa18de1fad19281f262ff39fec77684f0798b6d8aa895db93dab58165b67a875572cf000000000000000000000000000000000a246df19a23260961ea578a68ab4ae8811f9f391f673eab2b6fdd56dae8ff3b059e5b69052c9216529603e7eaf4ff306765d7f1079b142e513e604d577e7caf82cacae59fb98c6f8990522372dc906f00000000000000000000000000000000001bf749b61d7081f1e6141380deb6a5517d64e8c290363306fa23d6ba3b4e72ef53933f15ae77060758287a5a5c2bd4000000000000000000000000000000001661c564a5bc4dd852f35660d1e7c8193d76a48d1f0f3dff25adf312e28ebe9ce8972366ab224a95a7c1f6146b9f22412eeee02d9309af8c74c78e21836f4e6a7a6df5406617e2b4e9d300e37d8a2bfa000000000000000000000000000000000462a37cc68530a1c45001cda667e1ec10283b826b52986adec03db59a266cafc18ff76a666c9de9fc2384c5e336404b0000000000000000000000000000000010736bad21840f49466d9db82f01a922f4d6ab71f8d8ae246765300531b2f806663da2a8c16c644cf871a877b210b9e3f8449caedd55f0a08825cc1a9e985201c8a7a54d1c4dd96f0ac54214743941810000000000000000000000000000000013ee85b0c8f999c9d0682bf3f18a553b64aed8addf87e4baba55c6ad88de9c9955b82155caa83b8b6b7961d88c16c7dd0000000000000000000000000000000011bbe00b5ddab0b579375e2014021e3bfb1e11b7ccfd774b8679896c0ee34d1d19890fe5cf10e33e3332283b3a3dceaa28ec5f9dc48931da70ba0cfa7251953e24c4c95cd019e00ac6fda095c1302a01000000000000000000000000000000000fc3750c957b3eb656ad552c3997755bf28a54fe4aefafde15619133ae04a47f7c65122c86ef36fedac0c8e0d93c3836000000000000000000000000000000000f7f21014b7a9f07c2212af1b85395ef3072b84ee5e59ae675f6fdb9cac858b6213a264a202e29b45a57c69be5259470dc6046b43e6982f11f39412cbdef14f8e330d37fbe6dfa9ddf3656b86f4f60e7000000000000000000000000000000000d1fdcb6768654b6bc1b4d885039f1649066db8037f212b2d699c02606257388000b0543d25aace7cd1426462ec25c6b000000000000000000000000000000001386eb9bb7d8be5cb9e74a37759458091c44eb814dc3afbdf017a891359831ffcaad85d00d8e100886cb5624562ea0390adf4625ec80149b7810767c985c2aa0187987b3649cab8c59a892404ff2aeb2000000000000000000000000000000000f4d6551f5587cdb4d92e13e3749f977f5bd35b5b71667edd79b5006d4b0943331a0b417f669c6125edc42099bea22be00000000000000000000000000000000041b8ec8547b710bf2c15ff41ea779f996db7996911a5b4ae9f23073e02b2c252592229af738f684e9cdf48aaba0512a345fd17367ecb06b29d764b22dc1e262ba1a339b6f0e0c77384245e3d41cda970000000000000000000000000000000000c4a3756f2affd338f688ee90501f4bf4be43a4549ad8ea6aea69e5a4be015c97ef088da1a39d1103f866f1675f401900000000000000000000000000000000023e5d0bc92794536d59425c4bdf18dc5a208841953e5d45ae91f25d3c61bf66e704a8ca62a574ffefaea854fd23b8d65ce5e62dd15958e6298cdf4a4e899e53644a48494d04fa6d1f73f2dbd645817c0000000000000000000000000000000010129a00ea1c30e98c40a6c86090327d0a9b6c25b488cb0e369bc5a0e0658ec9ac9305e5d1469dd43395f72ef8a0e7e80000000000000000000000000000000006d2f5d4f3f8169f722427dbdee62f45f9791e55988910fefe188d6535fa15e2aab8de5130e81183e6ca25a8009be66f853396021d32530351deec5c266a65519471dce2087485781f33a1423755ef3800000000000000000000000000000000005364313c0d2220ed57bf22cee05b77a53c24c97addae502c7b3275a19522b8ae8167194929770191b96b957b19e5550000000000000000000000000000000016ca50cc1aef3890dd338c8a89b906812ce26e0ef9035d1a026f686b0eecab718f6b0ba401556423ddc99d96dd812d566dfc62eb59bb84b3b6599bf3ce7af229096a8fd5925d4743a5ea386a26c9a6d00000000000000000000000000000000007dc52982caf2f5efa3e1a21e22cb8fc53cd0355f2777272806710a96a22f8e896d001bec053acac6241c7637df158a30000000000000000000000000000000017e9f4fb0adb96150095ad5f0d464549d1489d04c4556576865ed3045e0c477beea3115a6ce63910f797fef29f75bad521d35ee6d29ee4816b91d1664b5957767b4b8066775b37c3b3d08729c949d6e5000000000000000000000000000000000695feaefc8fa22f81bd48a41e6c85acf38fa542e96a7562b8d65834c2f64cf5770ab6731ca85b0c5a80a73622acb83a0000000000000000000000000000000003df65226205511218c263af6fe33a09fa3db22e636da54dd967741657e9da6367fefc5e33a370947f2003dc139765083d283067bac390f556891a531dfacfc4795358229bc9a651c0aa71d601bdd56d000000000000000000000000000000001588a4aaee74856a9d41305023b7eee367648085516c8135fca8c0a6c9cbdecdb2d7b44317286f3a06f92b9eee2470170000000000000000000000000000000005aa06c47bdbcaea82e910b8a2c43c13c23bdfe1897efb2a57d622f5251f0db6293ad21d988c3ee30e33f3a40865fadf873724ba35e4e8b731db36f5067aeafd33f2e966977bd0962fd57cd5ccbfe87b00000000000000000000000000000000140d9a251d355cc6a8ff9fdf2223df59747eed11ad140297b6189a8d49a711ec748447ddcc45733a3c36a48da8cd46880000000000000000000000000000000008ce7046871c0b7f781c667958ff22da6ef5447bd319b2df36c9fae9f5597c020c12c7fbc733cb75ca8f9d9dfd942954cc5934c02b63797010cc8474e90fa5dc88d73dbe5f9be605bf335057fba47ea3", - "Expected": "000000000000000000000000000000000f1abe4dabd68ac4443ff50c0ecc5425ad60973dfbd2b29462254ad618b303dda061d80b28117803159ba503214b9ccd000000000000000000000000000000000d3da8a424576cdfc147e18fab66de0d1f93c05c0dcb08d9d5b2a9f5dcda76600b771991bf2d67061ea5b96d20a45c14", - "Name": "matter_g1_multiexp_85", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004d4ad5e9acfcabc0b93eb9ea59a778a37d7beca03e285382d10d97803ad63e11aa2e3cd1eabf72383d93528e309c28b000000000000000000000000000000000855cbcccda0476699ad3de8d58b4502f9e61bce8d7db37e9fd26ac4649a4cb831cbb74ecf044ae6014c21148382cca3864a1ee754f6b0a86923e5501d54e6f47d7ab9e1483294ce98be13b7db52937100000000000000000000000000000000156e86fc66a8b684327a4de77c31abaebbaf2ee5f0c4d5f9238c7d4683f08dc78d59fcdc25928d180a6f292bee23a523000000000000000000000000000000000f64634ec7de1fc93959639991df42e7dc621380f4433fd7efeff72ce75f6ac7738396a912f78ecfe70bfc4d0ac4239093064d187f7d21b8b0a7092943de13b96c2e1ac9b578637a6e64331e2d40f539000000000000000000000000000000000ae2c40a49f6539bb257fd759c2fcc9f7b09d00059c7a7fd41422ce39aa0792413894bc716d66dc79092223b63de6ad80000000000000000000000000000000017a82c6a853fe29f98129998708f0d4d2b09fb22b07474395050d87cfe4d3bbf94967e05861c20680dabf3f4367135a75e676b40c09f80be5d9398a9ec20cb811cf6819a130445203d792a4d34fc3e950000000000000000000000000000000013b950aa9b7675322d7b39e81b13b14f2480155f74bdc5793425a02f7de41dc1ebefe4f07accd3719feecfe366e93c440000000000000000000000000000000003378e83277e4b02c3b517d3a8cfbf2d2a6585d028c723b2a263e6ba17faf14bb9aea301cbfdfb73f84709e2af99867693f63a87972dd11f5239c35ce269e4b9239e3ae906ab117f1f045d3acfd16ca00000000000000000000000000000000004d87c87f8f05a0999c712756bcaa0572b70264166b16eea7fc4785a59cfca18d5b819f0e65e193dd7ec38d0756b84f20000000000000000000000000000000012f64e2dfa3f00ad8f7f68e08b24aae83a049390fbdbaf570a7973d8516dc90e9c5c9211130d5c6c09f5b29183e24201145e3456d5ca6aa5910430e5a19567c327b757377aef98c4f46fe9a1f52cdc5e000000000000000000000000000000000851a636dfc668d1c5d5467774deaa78283a6f56cc514420fb2b6c58ec831add57b5203e31377a57adcfd9097a1cde2e0000000000000000000000000000000008828c34d4e712bdd5133e220167f3424491b9f47dfd95406bc833b3b030037c0ac0d2c84b06b4a2891c8181359af350ce27de5d3a5ef941d058a458f3ad2a386f1d66945789e51fa330fd65da4cd5080000000000000000000000000000000011021119ccb1cedf88be6f72d3999df899efc4dc28f828831be911582b61894aa37302f84ae9269b97b03a2e30d66c93000000000000000000000000000000000c373df4c0cc1d8a75cf2b9a99b5889811d3ed42850f55480d891b2f44769a371fa4894cb5bf78b7e995b4912cf47dad87bf5c4624e86aaead712987f313e5db8f2fe6787fc33481ed6e5c4d3e96d5be0000000000000000000000000000000005bbd2831bb4eb8ace45ed719056b95dcf5bda8831bc1495f763ff5e82be9708a004a00ecd102d4fd084579d892e5da40000000000000000000000000000000004de171bf5fab4c89783ad1d0cc9fe697b827f023ea1660b0fa2cab108fbcdc80837d46f292b6062761dd865bd1f905f68cfa3fd0692c9ce56538bf70e77e2a47534d9472ac702c53f2dbe68217d53df0000000000000000000000000000000018b36452aa579eab36db9b0417c999fa334292bc7174bb88e4bb14025a20c86437d5cace5369b90640c81edbf2d60f2b0000000000000000000000000000000014278d1cc3fd07e947419a6a0d7f7bd5f9e13fbd63779ffadc150e3d5efdd1a3f6f6e5ba8516066b75e1925282d0e644a36b13ef742bfe88882a4e635b5fdbd9b079e1adf3423dd4962835c68c9617c5000000000000000000000000000000001365922301de7c81b839e970775854881955f35ef7f718643a97e54746b9d9867ced3fb7525caf5b5bd0d382de02fedd00000000000000000000000000000000000d37c4e106e51c4cb65fef8460846eab04fae7e5ae1d1dbaa1e0bfb2eab7f2e27a9cd5c3cc942e38b021ef71827a0224c54daa7de8446e5a26cdbd6741cc90bfd26c544fdf221d47d509c978723c3b0000000000000000000000000000000003b9de0464ac24606ae840185d2ca6cc78773b674688a028161341b88907213e275d7dbcb8d8bca15b483922a09297170000000000000000000000000000000012ee2a578c09b7563508d0d94ce6ed75d277ebd89a7f1d6095f8992c0794b4de12e33ee24547c271e17b7a045eb3bf5b17ff7a416011549f144a3a65238d62395f4f76afc09496902c064b27739c6d0a0000000000000000000000000000000005b7aa071b76f93c765f946b96a972c1d11a2c44244355e90cd77ff069b930b2e8171f7cb1ba29f7ca6e62d88cb83c1b0000000000000000000000000000000012cabb25e52f00f89f2758790f9a81d0e336ccd7bdff06a79552a346d1966f54a5157130e5aa8db175aa64a431e19e494615de9bd7aebf1acedd9d40fddda34e4a85bc253c5e92c20d984f6c4cec533c000000000000000000000000000000000dadebc30ac3e033f433d8d012ffc70adc146f4d9574e5431360fb4a8ff0891c8a9f38a8754984a385d704086c320ca90000000000000000000000000000000000238439bc4e8c7dabe260c7b40d317014463c4728d79f521e7e321346747e9aa65bc6b32ee5920969c34421bb99bee9d38f1a0417a5a366dd2d8f5ce229afb6f34c1b663ad6eb1d9ff12f38412f00f700000000000000000000000000000000029df69b4ad5cae9fd974da7f58e4c55e83c61eaf011b5f22e1308b56e2c31530c170b304d39eb3e8a3009b67b308c6700000000000000000000000000000000140451659b4d6eaf05db63be5a7b0341612747eea7536b958b0620bdfd7b9918e8bb76c05eb2a528bf4727e38605f99a364da9c6b07aada98107447afbb189626180c5eef31f7f2cf26d5d76ab0c745900000000000000000000000000000000062493361a1a862e63eb8f20b0610a78d30ac8595e4c6c3487cf3add7cc38613870c2ecd0cb5a869110a99b76fb9055b000000000000000000000000000000000d8918e018ac5490c91cf2574e6a6962b69c17883caf2caa473de172b14961780fb237236b56a236ce8c674dc9001547031aa8d860e3b598ad0c4e9f93f26d153f8a8d8d0dd614ba868ed055c517532f00000000000000000000000000000000016470ccd107b2afb9ca03a0efb958bbc165304871e683fd606d2e78f65e34885668c6ccb655d4fa98f5776280e63cb3000000000000000000000000000000000982eaaa34f9301fe0ba1915cc5632329715c506528860701f5e52d1d77b8fabc89706af2c4ab3b729251b9472cde96f290c467c4827c9252b82ff523633ba116c52d15df9cd4e3121ff0e9f754ced5f", - "Expected": "00000000000000000000000000000000112fdd661f948495ae2b9200d959ddc873c53c96ee4ec175f6748e62d76d61d6b15970d3a3a52ae9bda30a822ada25b8000000000000000000000000000000000f5b38208d69b5b842bc22ec9d91eb6b653acea5cb16569c61bfe0921f2d8ad613239e87d48c6a9b29ed6a5f43578987", - "Name": "matter_g1_multiexp_86", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a9494f10e6187fa12d88e350ab84ab5bbf999554924e781d6470e700c3da78e411b8627459b3359d7363b088bbeb0da0000000000000000000000000000000017edbf1108591996f28ae17beadfd6b52340236c2741bf8474dd7471c19c1f62a0f28e8d8692cf3e700ddd86a931dcab4aaa57782608de34c6334ce5039c67767f6da7b315dcfc772f03aaf3dd1e67b900000000000000000000000000000000052f9c6ecc29239c614936bf9ecdfec677afe80de019230180d0fe529a2e82b9e15d6e081b02475e2bf812cea3ba6c640000000000000000000000000000000003dd0afc91516b50d9027c0b132453fab92b165c08428fd5c2cb994646b6b1cd5b82b7c3f7924e4a5cf8b45575e8dfdc22c1cde67b0e8ec7217c6ec72f36d8a1e73794297819de9ef6f1e52acbd3ec4a000000000000000000000000000000000da6e13230b2236b2bdf671bd5f3f8bb47bfc637d6e3f1796b555a95e51b86d04fd310f3d3198dee604baf48f69ce0950000000000000000000000000000000018d209b03f61056147d6734003daa776011b70a57e1ab17d3b92e2565b31a846d8fb7c3fc6fa1fff04552800b73affab895341f4363b688c4e9660fb0cd17f6c111a5c92e732205fab0d0da0175f683200000000000000000000000000000000116c72b5bd9d30182463c592adb8f73c16d22bb4a22832b8d47b683da5f4b8179d4c80d361ce69f92a393027ab29c18900000000000000000000000000000000026dab8d729338903d46a219004fada41eb666a9a90d8ba115f53da9e89a7bc5d824d7f4071c8859df52b3ede7b7dfaf4c5718fed7503c5e2a97fd6ab0294d6c42b1d35067e9d5ec1077176a4bd3126f0000000000000000000000000000000004e0627475a0d4da458475dbbebd6c36f4ce771bc2b2a8c6adfe9d372ffed05afbea207476af26974476c0cf51a9267900000000000000000000000000000000199ebe83e44a269752d92629810d0c5402f53a1bee03ccafe0b3299a9968ec45abdb5a74a6d90cb026cd9b28cfd2b89f6d055ad484f5054e8bd0d073cd556deba05418ef1235d08ecbf8717b550933fa000000000000000000000000000000000b4918f4bfad81349edcb45439e148af7af6664094412c9a51b887271cc3c46e34147c8a306a19f08922bda9c7146c61000000000000000000000000000000000afc3d1a7c4b6d899149801cb74a7e64a126631b3e758a73feda92a2867c53fd3efd9adf025ca6f6c762029c57706b0b4cccbb062c27a67ae2783ab65a47ce166330cfced1f11b85f87483e0250b1384000000000000000000000000000000000a093eeb354ddfc5ea3090b20312788923c5db9d78905dd31d5bf15cd83521f2f186fd284de0858270eea05d21801aae0000000000000000000000000000000011d047410dbf6df20f81971327b38996484e0862a9f71879ff63462e189471c1ba391496753456f0b5379a3b36380e1296111cb1181f048f51349aa2953bba2af50f7b7b5d2328d435bd63a7df5cfe5c0000000000000000000000000000000003d8e8e3a442f911e23b353e9efe396b746360254c14216c752fad17d96d440988d5a25f044afd37f12d74c89c8cb2d700000000000000000000000000000000179ba95a3d3b5ddd3d181e2312385f4ad7232d9af0c28f375e2036157e4603c1a01aa6c9c91496bb28508e5885bc2e599d7f0c0c7e927bed3fb930fe2d0109f58678969ac8e14fabdf4ccdd0823f706d000000000000000000000000000000000f56dfaafea0ce3152458b7252fac14ea64483e1d4a00a44f95bf3932eda2f2c51f0239e6a7a503cfdbbdd88aef2f4880000000000000000000000000000000010e02e9be7c1b795ebaa84f83bd27eba4f12dd49b146db0d788e37835338d352445e82060dd595f616b4f6d2d03cf4c911ce517fad2609f2ab8d44ae6263623a7903b2cbec683570949a96fad78fc6d300000000000000000000000000000000010ccd262b0cda9ad39177d31be0725b83e935c690fa8e07bc7f24e26f8b03122173f4ba43fe8ac933a7fed79f4496c8000000000000000000000000000000000318da543dfb04005a3cf6d93d6bc4058b4b93c4cd84ef978e6a30dd85d60e5e359b4f518842e73d182567ec4fb236b8b17d28cbcb9efde6d9cdc4c9cda385ce598ac8468d4fc94cc8e98ca3bfadf4400000000000000000000000000000000003dbf6c0676cec0202e328bf408a8fcc38758db1adba3e8184cb3904ed204b7e18db2183f5a1833737ad8eb089afcafc0000000000000000000000000000000014d9add10a0c739dec7fd09c57b3e959f3b7551eab8423ec5bcab4b14e63b7a27f128758d63f8e43a22eeec7bcaddd41a9516e93416bc7b0f3c5ef5da6112abb73fc285a14093ed19d8eddf2411691190000000000000000000000000000000014d0230f7d5c51e6fff6490c61972e2564bc31fea4a6d1f293424934f75629cb96f189c80ab32a79b2e988582d0283960000000000000000000000000000000011813cbbc0cae4cf6a8d5d58859f1c3b75ac53819129f92abe0ba9123a1a277b55231e1a24745d0d2ba6242ee758113c87fed462636eb57506f870ed1c8f66e211758327f4c19bf909a6419312c5894500000000000000000000000000000000006adb1e972755f04cc57170d19414e6930d0e6d42c09f587e490593a5c01ce6e827a6dd1e21570ba11c7e4277d532e0000000000000000000000000000000000ef599058025f40c9f77ef858aaf314faaf8d72277cd319a84a9d7038d81b76aa260df0516dd38633b22f9d3996e4761c373d64034c78482d6673c6906553151887c8aa28ab2930659671b8cb98a595700000000000000000000000000000000008190fa5e3d23c0186ba502a5892b76cf8faf2c15c91ee39d51b269b6bf4bd3e7ea395787d989c1a14ad88f3702cd6d00000000000000000000000000000000118d2d1b28f9180155277b80f1a7937dc7fe6be3b00cbf6a7ddfd08cf653ed11a4ddaa44576e70b27cacb7646a100d03f29c901f9769a42610958a8cd53eaacd9e5c4656106fab536052518b49899117000000000000000000000000000000000d28e7ef8433f8d5399ce3cb847f2633392bf44ae9fb2d402ed8e7e6a22de35c39e4f09ea0fe673ae3cb652f75ec80bb000000000000000000000000000000000ebf2ed9df06e2d5688d0ea812b7f9de78fe292584476b20bd62066977f5e221dbbd8f552547f06a3e821a53aeab83c1125c12599e84b7e648aab52cd68fcca7f1a5f56c854f3c36e0445ab7e2df2b740000000000000000000000000000000000e162f9ba960f452c269bd2f9f06e8bf1ffe737788d6364b1f75ea2788fda7e265dcaa907e45bc6ef7a31c4791b470e0000000000000000000000000000000008a778bcedb58f562c7b69ef3073c81866a395d6408829816be3172e1e825ca6b88f156ed2b2ac5a8784fac62b893896bb9a1d051e33a617c25e17b7ca8ae6b02f16c759cae0df7fbd403372eb2407f6", - "Expected": "0000000000000000000000000000000003f6acb4e1f7856413fe9317bc7cffa45f2053ae62e3b5e2b82ad57b48cbeb4110f53dfcace08bbb1955c21b50fc636f00000000000000000000000000000000172cf1d257572562f9fc390f96f2c39dc5809765b0b94240a554f8bbcc44e3658f22e81d1e6c43742ef24882934cbbed", - "Name": "matter_g1_multiexp_87", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000013d3d80910d9f43a707ba389b03bda49b65081f65096bdef3942f0bde2122ea575abf810f400d47ced92c45dc73837000000000000000000000000000000000755b4f5a055c718f268cf3a74533fe8e8ebf37aff3045b58927ee6ee7a862c8c1cd61f00dfdaf6cccabf981fff16c7908c35887835bf4497d673936f40ed44145c5d5009fae16eb0f3ee9168831abf7000000000000000000000000000000001530565bb621f7cd530c0eeb4cc41c2587ef8123c552aed339f80711c157e1595baa140434385d0977e9aed2629ea76b000000000000000000000000000000001806c5a90120fe65450e84ee0a56e0176e944a3fffdd2c83bf15d7dca875790d2f842eb31f640456a1221e44035ad33ca0154f7f8d52319c9e5cd59052e91b84640efe83ac814d95370e46aff4334cf400000000000000000000000000000000143723a10965da7b47bed0d0b5bdb6bfef5b748f6e185ff2efb73c5756d41d77b8c217a6d92245ae36e0add4d743e7e9000000000000000000000000000000001274e8842cc812435a576b2ac19edb84f72d08cffa129d7f4e44be5cc88b3449ecaa719b4d76aaecf08ddd30f7b184ddc252ac28ea29b5459cd2ae5bce4bf08a102280c093b9962cafb481016a212709000000000000000000000000000000000379e08cc1f47014f7eede433abbe881818c0c3a9cb02bad8cc86242aeb9f9542aedb67313f494fd19971a0a15d4ee1a0000000000000000000000000000000004e83a0e52981faf6a787d0600ccc457ddf3bb81c76117265c1bd011e5b4f3237383e97dad3b019623521b3c94d67df36d3bb5ee3410dfad575b0fbe71ac5df2048f74b52e777fe0955d6e244d434f3b0000000000000000000000000000000009ec14585b72733f621a58f35ab30580f131c93db491d4d704c8da2a7a0a1146e144575083bd963238434e2af48d3d57000000000000000000000000000000000ebd1a1c160ba7c8e3c20745bbde05f08d7f3189ecaa831d05c6a34562d6d3ccaa92472c67bdebeac8494658abf2c0405c30684c596976bf46384e6afb2bad6f821c4a62338d7a6eb204ed75070b197300000000000000000000000000000000084b7f967b141c94df69804a723169f69e05629c97a7a8c60b140787f3361ac87458372c91e04c08da2d01fa96056ef8000000000000000000000000000000000d731a1a900551ca569b8066af85176b934b94332679aa59924eb7d9a5fd776a55b4d7e5ef2413c53c244c848694b06411009058bb8e23b0a4294b5cae63aff10265e729d3601d85dd7f1e8063ce260a0000000000000000000000000000000001847861de1064a4226435ca43c1cfbc5d4660fcac177654cf5d497ba9aa5a6322f1156adafba852633e111576698bd00000000000000000000000000000000005ba738972bf139d91f0a426c96fcbb3b77a01af0f2316f2427a20882b5f355772fd6d6016ed77c31c13f88b26c628763e5489447bb9a5b661bcff2d9a4153a5aad975abdec380301b6d4ce019bf2cdf000000000000000000000000000000000148907d2335e046c50fe213b717fedac86eb3920099526a62b4466749d435f5ce11a45032b60bd5d7b26799adc63f830000000000000000000000000000000004bdc2bab60cf6df6dfd25c16f04edd96d5021b97ef38cad02cc1fc7f12494098eb793d99d15b327185718f81ec0ea620444d520ee01d87407747a4ac37abb7bd4e4c4f1735ca7458cc2e4dcb1d6297c00000000000000000000000000000000145ea0ffc3b24a623d74c27b84a390be062542795eb93a2f71f9358b44b76b93dfc0a2ae507f07a8a07edeed2410e5c10000000000000000000000000000000000d407c6c245316b5cc6b62efcd082829354d7e9e69ad739ae0ee55e6096ea08a48c59ded4595032093c32634576aa132035cab8f8120ea8e91389707a290db4ee69875d7429c6857e74e8bd40dc736000000000000000000000000000000000123f333f3554eac47c8daa1d4b362e42de1834ba9f55e4fee138eaf1a057036aa6ff9f50cddc78dabd3d5557b05b8bd1000000000000000000000000000000000116d786097bcac320327d7d56aa734d76d48a677e9c02ecc0bce550d75082c319f568d94b41e1c57c6075ee994e33304bec711286827f0941ffbb451a8eba871239341a60e3aaef23487175c9d2e826000000000000000000000000000000001012b1790e287a6328cbbcf80eaceb2c518a70e80cfe17143a41c4045e8c6c5317aafcb34f4f56494b401a8a9f21b5fa000000000000000000000000000000000613a88e513248538c1b767ba4d3667bca7aeee7974f691b7e4f012ea9b2b32603eddab0943229f53324c51838d18fe3369d91a4d575d4c142b98a53115a792ec50a290608ad316465487762e83f3a86000000000000000000000000000000000c31aa6f315a1102ea973d13e858d079221087edf178d98fb05701ed0a159309fed05942626b29ade066f8cef465535000000000000000000000000000000000177a3468b7de9612a93b9f2bb3f07acf505f56c63f798b4dfc38a25d0fc133c862e90ec8b40dc94004cfdcc9da197ee7ee472561535a7710db521976cef0c92a4ed89861ecb397cbcfafa477756e8e12000000000000000000000000000000000092095e7a431ff3a8e51e26c24dd4a5fed6d4a4a169b5ef79e8822611da8aca5d7c27139a911d5473442db9ee1529bd000000000000000000000000000000000c59f5a649682e864a792ad50fad57b7cd14cbb19d1feadc3536515f01053fab26950f56bb78d5a51f4368e73c19062f2cfdcb8240f183abec526344e8ceca6a007c35b757928803f854225d3a6ca3610000000000000000000000000000000003930511780f28217a125f524ddef656581a4ba2d461730f0837d1846d63258a02e659b25b882a3c3d077c880a64e3cd0000000000000000000000000000000019c682245c941c76605502785b1f79d37f65cf9ec61a4558092973bb2514de4e5852fc757c2fc7eac1b01d414248acdd60659743dc1977a698371cc302b7579b6d7d13632a31b47df369365fb02aff7900000000000000000000000000000000000edf518026cbf2dcca1d46340c24fa947261bcef36e3c8d026a09068a10a5afdb0964b54b70bb3b27e27c4d2e0bf9b0000000000000000000000000000000005cf718694ca47202be8c0afd56c88742e2b467d01e7b2330de778c434a57610fe7b8bd6071836a58f5d6b2876cff05a652a5d4fdf6d6703c857fc7b10a741b95fbce91fe823d827cc7203be3b3bce0a0000000000000000000000000000000013db13bf10b6d8b1ce5dccec98745dab635b8bc81d03601785185cccddfe2dfb3f3f9f6ed16d2c1a7a6bd63264b094d60000000000000000000000000000000001080522766b6cb5c90e6e0ae11ab4ded3db3ea3c7e69d00f29155283f7b25f762eb35bfeedf00caa83dcf04f22ee72976a30abda185e7d280804952fc0c074ad907fea2aa54da4c3190895270169b20", - "Expected": "000000000000000000000000000000001975e01d64d38cb8f852b4177104388aba62c167da2a8530bc59f510a990ed57be0c6ddfc92622234a121ca407853dbb000000000000000000000000000000000de737b9097065462dda93321d5881430f50631f6f3deabca4c41cd491f1e441139bf8ceb598393ab2a3424b0acf290e", - "Name": "matter_g1_multiexp_88", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001624f6ef9638cdc5f0b16b47ac8c5465cb479333a4ee4caaf6d2b656464d8f84387f01bc1811924312e6cc1e29a590c300000000000000000000000000000000012b3bcce18f60c4b2159df93a2d536bdcadd675439371acce011ac5b542fe1bcf89161fc3b3644679a395aed31dab569f4db766964c7855daea58d1205fe8da572aef06e0ca64912cec7c87bcb2f51f0000000000000000000000000000000005d49b4ea69c41ffa7727b98db08ab3fd3ca0c0261ef04b426ef29e724bd6158b3f3242cb915cf0992f2a631fd9b4421000000000000000000000000000000000f635c26698cf5dffbe25ff496f80c5de6b181f94a907204b79b548c1fee8c7dd426b49e9eb9eb0b17e34a26628c38e71deebc727d98bdec47b5a1fc48916dca1e42345ff5474a5fd6cab0ae99e9f1080000000000000000000000000000000003a80767130cd3c3fff0610f215337bc1b4a88886778fc0dcb6bd3cf7bee48f4c23c974c8883e2cf32fb01a84f9e148f00000000000000000000000000000000173f518f3349c1f704fd200747158940ecc395b04b4c476f406cc27836df182c3f1b707aa05767ff1bc75de42dba2a824b964d74259c216c1eccd7f2b52ffa5fcf151d47bd69bd2768e6466b32eb4fe50000000000000000000000000000000011874da4371ee8bddb34bc92fee6bf51226878e4550aa33313a434b75243c1f2296c1d62d9f31f6ffe2735f4f26a8082000000000000000000000000000000000f82551ba2b803e35c7118f4294626c151c7137eb4b97aa5265ce383f7ebc5ff5fe381776eee724aebb963d2bcb3d9f6124ceb1dbc8004a4b1f8b422d394b0480bca7c0f38aafd8f06ba090a98a1d3c60000000000000000000000000000000010501308d1a05e69700111431a0ca99aa41a991555b9a53df9c38413c67fa1b1836853bda93bbd8679e7724b3141a8d0000000000000000000000000000000000b033cfca384e480f73a4f8f79ceea706d7390e5b702305b79e30890e158ede03814d1a0dffcc3608fcb9926c5c65eb65a2bf15b2ed08b33056a0733c920741f86730dcda9c06aa0e3c135a844cef916000000000000000000000000000000000c7bf31a1f30f8e0de1a4a77b8b6c115d1a5d825b51875cba3db857a9cd2c589696ce2abe5a87acf8d6604c1f1f89ab70000000000000000000000000000000019ad7a6190a69fe1df07d55f8c792fc72cf2be11bbdd83c06325682bdfb5c31efef11fcb819d39f25bb1978570a250218c3c919f31d72ab414f91938089430bbbeaa53ad7a73224fd3f204b80fa1ab870000000000000000000000000000000012befada1cdf63d34ee2334ba2e42d7e69ffed71a39714e7ed89a86fd5cc1c65a01340c986abc37e7e3ac5a22a2bcc860000000000000000000000000000000006e5b16316867dc33a9770aa2283691f379581ff2b0b7986003174d4862d8b73bcc3f325c9a90097328f881b15f877c7f749063165c6db0eb038cb9f1a573de25bf377e1fee94f31df5987f7b2450aff0000000000000000000000000000000008e763f110c9415b63baf27236f1c0975e7bebc04bdaf47ea0d3a2709a455ea48ffefb7551a73c9d599bc5c9fbbca78f000000000000000000000000000000001492e70f2831c87222f7d7a9d00842870b77aa68e87b8cdc9d8ba61f86adce6ea514bf5b8f9d66937b1b640c43b02fac22d292cbcb836843acdd5a3fb404024174cd5c1cef632d1b9b6a73f2c5f705a3000000000000000000000000000000001685898af1ad3bfd350980872e6438048f6cb37398ceab33d7bae1d621b5b2859e6a07b4e4db891af37e29881cf573ad000000000000000000000000000000001084663fadcf81b9818c999c26a84c6f9a3a1f71a0a2982b5c6d01c56c2974656c08e4ba7833d1ef8bcf9af53d2f0732e816dd1bfe025685f2eff0856f9c162d73a58fdeae0dfbeb5ce076e9f9ec1a700000000000000000000000000000000013b077eb9130821bcecfe9b366c7a14f4487121095d325e74de44ea206078a6b1ac7d29a4e80f75c7714b6053cf2995a000000000000000000000000000000000b825b95b52382195416477f0bce73f06167db02bbcb91944e9e7534f804973bb363adca8b5ad80e77b70f4f1b9654d004f117d41a011d36f55d0cb53d4f98de3b1a6cb55dc8a76b29d393bc21826ea00000000000000000000000000000000014c48b3b2fb994920957b046643bfff19533dbe533df980dc60d9c852a3d07b8cf67454820a89ec9c7ea73a209f911ef0000000000000000000000000000000019b19e64d977d40b95050e4af365541b6c815534dc4abba7ea0af4b0a7e6bff0495fbb347250f5b5a48020ac20ea61cb6b6f5ee0549b28a1bb317cb020ae0e031dbc381075772ff582718fa49db486d20000000000000000000000000000000017fe39b732e6b815bde4078cba9f926e117349e3e49fcfb6308a0a09296fa27da4580d8fd18b0ecfd0ca68312cc0e5c10000000000000000000000000000000018a4eda1862c5c296de2eea0e720ba13f8a60defc65870f0112ab394e8160d6e1a0beff5db8c450d8770792b7efcccba05edf9812adf95c9844b2da06f75d96e742c0620d1cb0d47dfd9b68d0bb76128000000000000000000000000000000000e65750f3b9690f25b5bf80de0d76da21752a0daa8ce01b2bd8d172577f6c7d46c119ed20e73617ea163575705343c4c0000000000000000000000000000000019d0f934decb53a477b37d894d6e651a8a4f25b9375bac6b6d3483ee8d85f56b8374bacf74bb8550bd26b3d326962666f64a71e4e7652860038df67c99d97b1e5a063370e65217531253419bf2e6365b000000000000000000000000000000000907fe95f32e22ed75f94d96c191bcb19f88355bb84f91a8a535441da04dc211376435ccc60ad2089835b51e79f24b5900000000000000000000000000000000071e35d64ffa38024f4ccf7c4a713e22d8fb4b8450ba7b05ec5e759c2f8ea30e7d9e71ec2c90b8c667370131de785116059bebd962501b8381b67c22055ba01667d916932713d7ca427cd80d8f76b419000000000000000000000000000000000ccc90617f386ee2a76da43a745972066955c8e346d3de214834ea79423e7d95a008a6c119d640491d515b801034452f0000000000000000000000000000000002588711ccd23b65cf2f63b2d602b1d7dbf97cdbdb159e02e3bdf84fa65685e14d4832cde3662950a7fcfd11e68ad40a47b3448b9b404e184f7ff20466aef3dbd4e08375673ca31fdb303c88243fface0000000000000000000000000000000003b5acf5f4e39fcb32a267034c5e905eb3df32f2f6f7150d94cd17bf16e3a9fff9dfdf75a966040a6af5a623787a40170000000000000000000000000000000018e4b8d163e5176bc9a45da14fabbac696ae6870717bf5f6c00b5c73dadefbe329d86a761935b18e81d65ab6c48e241567d9d30b38b252a0661c12dc69127ac380f3f756144801633e99bc2ffa2f463c", - "Expected": "000000000000000000000000000000000905fd0b04e8db7657431b5f69f1d896e79ecee300cd67ea8fbedcf51b0389506da0669c28ac8158d5357a61fbc3976a0000000000000000000000000000000003235ff6d1acbceb35cd29c5fe524a452064a6e51d1480ce1e57c538b2ab6ec4f98c3bac676817e25e2d92e701ba881b", - "Name": "matter_g1_multiexp_89", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000688d6eaa2964e33cebae16623e228256937ce9a7721c4fbc85233ffb3edad5d6349d9c8a00c16faa0efd9c54827f46a0000000000000000000000000000000019fa249ce7be07208cdac9f9927163bb1b79b40b320623fc1a08a299d5500cacdc55386ce451173f683a9ce3f006c1e4aaea75e63204e177d404898aa51555767f813c3f3ed283405ed1ee829b04c85c00000000000000000000000000000000078eef7d7951f257b17c579fec05f3efe332534b2f56a953a701a8b92664b9a0b37959f7c3dbd77ac18a5e72d174b9f20000000000000000000000000000000017cb59169aee6caa1dbc3c47c29f977a44a81d33f1cd298d5df3e9469c8543d919b985e1b588a96a9268cef03876effbdb48a90ddcd791e6a9debfabcb1c71c88e7ad98f9e739ee752b381b28d7656f200000000000000000000000000000000025bae0252e5d83a3b76f2a861ebb1312bd344e3eaaed5e7169de248137a929ab94156be11e9b16ff312180d856d93900000000000000000000000000000000013c207c57a4876f6bd6e8e87eed0021d5e6b2aa3b2a323572fc2ad521e807c366fe31ec285c8412f89328cdf09dcbc99ad1795823d3834496b0a1c2c07431f9d76071db77834005fa1228393ad4ce3f4000000000000000000000000000000000ea93e5fe055ed1ce77de5d298fafdc4201418489b64d10c447de3973c1b98c184c0cae1d95831742f3d50613c5cd8c40000000000000000000000000000000004f2f3d0a5caac826632ee95dd1aafe181976552abdcc7db737f5693f3d08d3c4a85365e05e369365a37ef1b3df5cbca36d56e38fe63e573b02203be04ef9e1a044e1754eb2db50c6f9804abc4a40f460000000000000000000000000000000004c8b69c09f67ad17e8fb9fea4b7532c7c5bf3edb7669e26eea4f9c8f0bc10b0b1895acdee731da5999318d83095ef5900000000000000000000000000000000054f950a1ae65dfcd40eca15e5fbae984e7672a23ec030eea0cbc0424cc8073186b8442e0d71d6a4a77cee37c1108f941a6b36f4674ab19202037d59fd8e14369e5d3d71acc3c76985b813d81ca6e24a000000000000000000000000000000000b69b6b7b6cb1569ccbcea029dc71560d54b8bb88bd33af1c12a09d867fbeada2e58585385f1fe508a0dcdf8d2143f71000000000000000000000000000000000277561e6ac810ddf4c46288a065e5441ae0fe2d7ee79ebd6cea8712281a36f812c0bf49c21beb63a1f5cb670dd37d03ad85286877fa7e5a9a61dba9df5ce35083beca7c2f5ecad13d226fa32b9720e9000000000000000000000000000000000c0f4206d4cd564be1efcbdf57f99ce43b97d3e170017fe352ed3ec60862f87730d4d9d9d56ea0aac4f586d2f1786df900000000000000000000000000000000073202e8c73d14469d15a392589db79f3897b72bdb2b788da9012c7aaa167a157f85f3431161d35f45bdfe0f2255b6378fa5387c5712832b52c9c72e10c6f69e9c1c5b278aa379140e75e404c4f50a2c00000000000000000000000000000000191cae6012ca07ddf511ed586ef19e9f0d913d081cd752f033c9f74c334c6f5d075b4f6ec85467caea7836f51d0159af0000000000000000000000000000000016e65314e34e1c7ad577a36eff992abe6f26fc5349d12db12394bac648cbc1452cc366aff69e8cc4e2e5bc85db237a863023298162ebe7f4ae6aee45a8a6ba602c3942a8bd6b35636fc6b85596a582e0000000000000000000000000000000000bf583ae5e3a7827610d91c0d2433c8d358fbc12c016c59be8454c039197971f90191737993bfd08aa96d7838b7ce6dc00000000000000000000000000000000046fc386c5b456bafe03fc84b4f98939f9c736ac74cac507ea036d2443066090118138547766f637537425f64be9691b8ff2430d2f82c6d5e7424836ecea15af0ba2d0bd6498e65c65b6cd281a7b8f28000000000000000000000000000000000f08b3868ea056ff8e82fb7e22a6522985e92df1df9db77f787bcb3ed701bf8c90badcfd94e9d3e3b3b68ec497b9fcc700000000000000000000000000000000002e6f5e9eb44fcc7aa96a43856a707f5a82cb4c14c99b21df09e666d4802d15fb50d535184b63ae246d4ad77b6c4851415eea22058493dbf6ac248fd2ad8b4734ebe33761f2177089a3feda396001c000000000000000000000000000000000167e13cc54e9e9866bddff0c37e942ef8393a588ed3c2e90da12d0a8360edd6c3980bde808ff16588a57100d1a8898fd0000000000000000000000000000000014b21a7a106640b55cfeb19d3c23aabcf1c0be78fa554613e68404978b78e5d34b6b6378c2e87d0b8bf1cf3444d0db31ff79e3ef5d32a751b713180be37d44ae55c59c5a8121c132c5098ff972d8a9740000000000000000000000000000000002e8053215ae6894e8df09394353fe98b38fe4b17b9f20c7b48c4baad91519587f63b863e4de79be71672e1fb00d337a000000000000000000000000000000000c2ef9251a148f1ba8cd75a60ee18ba6328e1c3a6780c790cba3bc91a2145f44cb8bda5257c03890d5c5674e4d09296d039bc7274a3ab172285d853d368da0950203a48ef61b3c7564644762279c1ff3000000000000000000000000000000000aa7fdd550eabb1b734db00400304be9663c008d322d67fc771a85991bca6413ec07ab3adc3cb40d390fd41021434b97000000000000000000000000000000001994d9be11443f0a95a2ba4f7240a9dbaaffbc70256aebc0f10c322fc5b120feb2cd8492d02c60578f8becd7a8e589c92c47d0b1fd24c1c66a3cb0deb7d51ea19f0fc492f637ed5d4d03e102cbdd05550000000000000000000000000000000012b3574c35288c63930be8024afcc91194b30d2b486edae832dcb34778886af5816f7478df166f0a7e4752d8c12423e30000000000000000000000000000000012cd382d17ea10ad3fbfb40fdf4f3814a19384e302542a0f5731920443e4498a1f8f4d89086764beff079583a672b93bab4aca860ae4bc20d33808533c9a70108b153bc4b2256003ad4bbc11dc92898500000000000000000000000000000000117294ca9961249be6570ea760bb1e562cbd587f78be482263e4228171d9ee3d970b234455912299933689096f4afbd000000000000000000000000000000000029f88a99c750a388eca5dc6939082280ddefbf7d23997cca3653aaaa03a3ee4677fa8291641ad1f46fee0f8f1268140297500a2747f9a68b2d8d9ca5b0390369d919897c53d422cb76c5a283c38669e000000000000000000000000000000001006f64c279f074bf036897ded9deaf9b4ca380a9a7542490be675355c3979b2925be09ac4613fd6b7a4a8bb9e357f70000000000000000000000000000000001537e170e8dd88a92a6bfedcef69bb370f7bc1f32c36d203f5b6859be9b60fcb4d1e3948687ac7791d867e7c200967eea87ca4cf226c212c80f3db5e4e781ad7391fb73b1124d01cf893169d1c50ca99", - "Expected": "000000000000000000000000000000000603f6b2d8b806c5e399c686878eba299131204084e2c31c38640d757e8a6e5b318da785d54ec8335398610e9e3956280000000000000000000000000000000002abafc5839180e8aff2bbac4db043e8839ea25d8fcb7f6faba2a1c0a567863f256f820e846e49b3296a754650ca9b4e", - "Name": "matter_g1_multiexp_90", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a2eba2e26da82458a494738fcc816405760f4991616d729415ee502d13951c319be796cf35d88a8e00e17fa3c58126900000000000000000000000000000000117f6b75a6e25a786e860df05505f8e107b23c6f4338b2f87ac8740554304046f7cbb43f2193da35350e5fb39077ff3f9abfe7e05e8a210604355a77f64386a01323407d9f25397769cc6dd141bc6643000000000000000000000000000000000f6e3064df312fc97c4f30d3cab398f7921453b933d428a4162a37af5ea27c79d5b21d1d305a9609c994e61e56db226a0000000000000000000000000000000011edcb47b9d5339d08f24be87e52eabbdf701ab15f7799a5ae26cfca9d49e0e9107d9d1f09c711039d096a5745b89c9164be08e7c2fd15ac0116ca941b85615c6deb38fe85e2c0fd22997e394b8a6769000000000000000000000000000000000d6bf9e905e907ed86f5d3a4cdf61c527ef43ea0befcf6bb7eb1bb790b3dbdb83e0b958836669827251da94db1d07c420000000000000000000000000000000007f85bbbc54af3eb9e1c7e4c4700b4c784b8d2e6b2ff6a981a534317766790942898b4eabbb8d6c893180a436faf88870c391dff1c0c303c77b2a1fff24f50250dc793338f7d7f8f1d54bf7d87ab37da000000000000000000000000000000000b17bd374136dc1717cff915f7c898e049e892ced4ba57a16752a6dd875cf1cf9a2005dec3e3bc6f87b7a257d5ce7ca6000000000000000000000000000000000874999db06d15bd4b2f60e9b61d195747d12f38b75b74f3089d5b47735e9dcf79ebce22505399e16492c4a6e0f83abba2d728e013e5fc3e1ca24c105a0c268cbb4f152a97e318f3aae33186ea6bc93a00000000000000000000000000000000179108aa8a7d8443f69b7c906f9a4869ff4c724aaac4fccb5f52cddec86e32180b3ab2f66ba76d57f69416b70334a0f80000000000000000000000000000000007f83a847f4c7e7b35fd091249120bc59719ede5b6db083b33f5ea6249f9e13457511db006f416e0fb9614b8d22d51e1e8da0c8da19dc441f53c54551579fec5d820ce2e3599824b24b7c5bf1847c589000000000000000000000000000000000154b40b3bcd0ef04a5e1a550215c238adf07f92757c227e4d32e42893ee8e7e4fa9d7169005220d89b11253cffbdbd10000000000000000000000000000000018daff3cf04f648e59d00df4b86d8ea5dc74adbbc6fe4f080ea7a84dc6443d8923517a11f264f700e209af9bc52f759c76e90965adfc2fe52e4341895e6b6154fd7a097e052b59e4935c8267a6f0e63800000000000000000000000000000000163cb54e83a9935be82161939360356f7f0cd0219f446fd243d05f6333c68a1aca8f5d2dfa2b54dbc07f81f756ed6bd7000000000000000000000000000000001667e7a040817e83896d62adfc4a9f3d329e87f7d598217c7d2195c5b0c3eb58047d4b9bb640e3959f7ad1242e10783f7f3f352c7b7a9e2eb6c87edfc99e2df3148966760168f6abb13ee482f223a01d000000000000000000000000000000000222ed79e925d64fb58bf0cf105a2087c538c9538070bd742f7acf5e00ab371766d286fbccb3e708bda2d227523a40cc00000000000000000000000000000000126a9569e9ba97e5c41cf11af3a601560d037f1594f2e352ac86c744542618e9d2b6def0c7d3bb6a3707b80cdcb60f15d35c4286f19a9fe8117e37132ce4ce76e28afee25ecca2f66de3cd5e1c83235f0000000000000000000000000000000003786245c244c9508ba94e994dd510a7485f4aed711c75a2f509cf01b784eb12ce2f3907156aa15675e36b4b2587e9770000000000000000000000000000000018de0e75256cfcfa2df959f1491d87dd5414a1b51b6ff02ed5034394ea636fd0bc5d3b3a3b84fa7156ca7f97aa65feea3c2b40b7968a39fe8e4f24acc25b6c727887c3c44cc89cf62eb14a78ae47e86800000000000000000000000000000000026828a6409635184cb929a5b3fbb881ef013e8342cc9b5123ac82e7ce24fe7aa6a507ec3c017bba10126ad9bab5e63800000000000000000000000000000000132cf4a23eac460fb1a3db9aa43b542ae55d19f6bb2f408c399a570c1e479c4dd0462f9573c95c953bee07a51c543c4e10325465403dbd4898beb740884cc325923ec3e1d7483540377d8bbd02c1138200000000000000000000000000000000035220c800af6a330df6b6b6cbde47abef2e5fafedbb7a0feb84a317ca3cdb79eed934847694e85e2873ef97b31b6ba10000000000000000000000000000000011edd4c17352914beccd8c062aa7b95b913f35892c7cc5dd8f736a31a33d33a98d8f9b4be97ffe608531eb7c9643f32109545b90dbe35b0d5764bc72d45717e0c3aca6aa77c73178fa8a3ee9fec9cdb30000000000000000000000000000000012148b58f805c38bb862dd9847f12aad21d1ed760a022d2f619a0a077a0bd79fbbd6c066f0f6c58517ee9e912c60a37d0000000000000000000000000000000018dd847881616f7410f29d4e68854ded4e97b31d5112fd46437739ed62e6d78fab89b078581d052266b7c2ce403d3a79eef0f8014102664a300ea9a30fdc7afeae3cc338fd45cd421a1bfea98e304c81000000000000000000000000000000000e36ce625adc496ac94b53552effd651a73ed0c69abedda36e88d408ca7bee73777fd87b4f55e2e8b567c2fddbcff3d50000000000000000000000000000000008a209510caa720f20cecdfc9b0bd71d3fd4015627d0227a027aeb9992ec8030056a5046feadaf149d2392fc98fd60bfc8f1e08cdd72ed200253211e3b9947cb2a5fa24079b6920b4a4d3f1fd78146e8000000000000000000000000000000001373edf053517ee79eccbf02cce4b4b67d6efc53917b7cd548379c3f78b447ae5dc331285a28bc2aa5863befe2d26f4b000000000000000000000000000000000fce7f982bb8e937802fef7b3fac517054e6c9b288b03ad6497734d78d4b9074e22b1acef45938a08440948dd8b88683a7e25b1a60b6c6080ccf1bfdc37aabbc2bf92079d9356844f7f12867b3e2b2800000000000000000000000000000000001ac8ab3b3918836a5ba14e3d7c44eb8a0d909dbfaa2772cb9d7f8f517963662b5d4209e9a5d44ca0ed897412792792800000000000000000000000000000000169f8127198935f06d26ad8e4ca3ae5b95ad967aac69f7958fe9fb9c5b1f0e98e596fb73a0d8bf90174ca21a02a3e2c2dcb456eaad2b7c71ca32277206c1a1dbfa7e0e84950cbf14aadd455fb58e398a000000000000000000000000000000000c1cfb4660400ad5d7ba2f394cefa878c6a8fc214823dab539c0aa6d08f36ff1bd706be273f25ec5f1abfb06bb57e8160000000000000000000000000000000012ff9bad1a1d71fc49e96950c74d388229d4e4c68f7fcfafa42329ae06d4dd3091b5b1c95f6498743393b6e3ee794e4ea6e7b19245341fdfc5927cdae57f59de5f3fc8c37f8653e5aaca87db682034ce", - "Expected": "000000000000000000000000000000000630b9d9da596e60b15251aa74de850ee74c7804414e3e4d7113cb3d5ad6b985e436aa67bed66c36f135050d66f91f75000000000000000000000000000000000ab084fa126c573ed007f983e01737453b3dcc99ead0a74cc0e8d7cdad89ce81489384b311b7ec4c34736e9520b37e1e", - "Name": "matter_g1_multiexp_91", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015fec44912af2bcd34f1ad42ed24b6ce430f6d07b311d65ffd8b6d726ca23f5bc4b7437d158a36bd1790e806fd5ab448000000000000000000000000000000000c4a4de9940c7c26999773a396a8f9a6ff4b86f0525189426529d9cca037d504385dcbf1c89eefb5ae2cbbb394be42fc92898d9cbad829a5346c0925c15b585de18869adfe796e46cbd56828540571b7000000000000000000000000000000000fa1258cb0d8a37009e8c56228bbd11aa854a4695bfe96ce205efc1c9f32bff8afb64df0fb7863512ff8db6b091f146200000000000000000000000000000000188f128e662e8d28be612c8a17cfbf28b965340487df40bd3f0312187d027cd23b50e713e21f8595bc790ab8011919cfc193fe87634fb0bdaa1700466881b557c470a62464e8521be311a95dff65eca6000000000000000000000000000000000c7b39bc2477597e37910b1888ba0afe5ed03e809618bca0e543add93519909b6cdd6281e2afa65a9b45627dc1c6334a000000000000000000000000000000001335cbe866b3139dbe22266c4ed5f9fdbc15a1b338a290a590c03811b6448244027c12d118e6f829dcd352a419bdd8283dd9c99a5aea019436e3c91030d03ebefbf6ea6ac69222f1870fadae32f55ae600000000000000000000000000000000178ea2552d03f645fc3060a61b35af6e3e12095ec65b2e9972a5e346ac1019593298925a887e59a94af2adfac7a8361d0000000000000000000000000000000013996dc427ba51c4ec1f67b30c95659f35c8e71a225bf357f636fbfb428140f9b9e5602eda78bb38e87e3ab77495e505e74ab390c3f73c62eb1435226e9b4f9b921ea1918a61a614b9bdbe9eebd1cd790000000000000000000000000000000013555f26c2e10b79f8f2a4c397dfda0d8839a35a7cc15673ee5da34578f3fc4d38bd0331a5c42665bf40fb2cf693f31e000000000000000000000000000000000bb16b5b1dacac465a751a68b99def392a69a293377a22194fa4d4d6662b912d3ad804cbe51a4ec4792229de57923ea14dee3e2bfae3820f611c30df232c1d9c6bf58d40b3530858c79f840720d78d7200000000000000000000000000000000120183e73d23355da316783eb47ca687ecd34d85e800aa65d2c95aa5f8eb730a33d3273307cc05d81fdafcee5138a080000000000000000000000000000000000171f5e63fd3c71200720cba782ab863ace945cf405a2f961baf39ffab2d3283c26347ba297d16c3f2567814c6f9914e795fc8e20dd30622876a94afce1c1a76e3b689d6848903c21103cfce6a8a956800000000000000000000000000000000095ae1795306c8a8c48730987a842a05fcb263d1f9ea49d3f3c0ae70c7ff636fa4e7fa33a35637059c0b11b1b1adc6e000000000000000000000000000000000185e08447394763607d6efd8660118429469a1f6e7edd03a7a3e12ef99c2a15670d1f7ca664a8a14f52814db9810ea2b25b49f325e76733eb3c1a2cee5467157b2ee80987abae43d2c4b93e5157f08380000000000000000000000000000000012b0afa7f55ff9131a9399cdf0fbf2da69dae7cd504a0160665f0cd74a02163b8ad7ab05cebf3195495a1637134cee450000000000000000000000000000000002a130747763c25b9b6c0436390da91f02c9d5b24178318717024390a841baadae6a9f933e7f87f7965fc96bb498ade5df49b30dd6aff459f64906eb1a9c9b2067d4f1b75057874b2fee17923bcb906e0000000000000000000000000000000018911ed6adc5f48db7221656c622c6cb981b1ac1bffd64e30662035c0daf4bc5accbd53cdb1fe8eb60628262584de15a000000000000000000000000000000000b753d21d823d1050f109683c7c153514dd06663ed0ce118e388d18d36686e94588159e5afbeaa492d021a700caf2dfa959e0a33b1fa12e0ba960761b09921b81746b8df23e808a8de09e7f5cbe2bf41000000000000000000000000000000001107292ce4d57209e9c1e2c396688ccbe005699de4e77b1a221f9004585ae6cf8f901da6811ad85a88cd85cb819d040a0000000000000000000000000000000012cbe9c273a8a9c1404abe51af4a647f6c89e7e177efc04233586d70df6dad3aacc9ce2a9fbdcf2ee5c73396fe4e498d26ca68383528f6a871c237ae5214b49c18c4f3e2f3ef5dfba39e69eb181143d7000000000000000000000000000000000297e52ddc42a7da1025d43f46df11009ee035a9ac45e09a0902ba86fcfc5a4bb4c35ae8b0e0c9b86a8ed7e5ab751947000000000000000000000000000000000319c082c39ce4e59b952941dd7d14f3fec39a9eaccdf7bb41a2b935f876ebbb6778c90e1919c1e5804df91abd3bd9d5f1f95a9d1d4e8e7d0f17a954177253709d988c3a77c77d35b8bf70294bb358c2000000000000000000000000000000000ea5a9d96509cc5675e165e3a7c9f99a8c6b7be9c33fe5fba895a2d96a68e922271c90badf3c41b3ff52f359f5c6dae300000000000000000000000000000000106614bf5ae42409881f4889a82c6a3bc8000bcdec23b093ebf29b24cad128aaa7aa17566c4293f67af010e9b5950028b481f986998d863c98e55a7661136a8f19d7d4c57f6036cd642ae16c82cdcfb300000000000000000000000000000000145447f37207ac8d58c706af0b900dfc1f2638f840a0b44fa65245b5e671ffc6c008951ee17217e010ea6cd5e8477d4900000000000000000000000000000000187c607539f8d2b6afd15efa353e2fd1580cee48c469992785f02b3ea3396db5359e0d6743ff8d41648fd8680a4a8c2bad872848d72367467094675a819f9aa6107183aa0c8685d5d84c27b3aaab33c10000000000000000000000000000000012a022fc2dd9c201e9d86a0983fed4a71abd086068b8ab8c9586cf51230acafb084d559239d86a3713aef4b87a04c09b0000000000000000000000000000000017e02d69776c705bdeb9fe06d412a67601c6763a19c840f15f96de0fecf782e3a44118def54286cd52227361f0db3bf93c2c60541fe17fa8e71d58184a055fa8b1dd0bfd16ac2baa912b4472c6056122000000000000000000000000000000000e09d94291ce5e8310871aad89e0744e6b319b4fb1089048b0181cb9e885aec881fb7577fe0e80222793068deed473560000000000000000000000000000000017c8676e4b8216a98d9e9a05891ccb74e64d72a5ae76dba1b5ab2d1c4eb8291cdefe7753abc5fa59efc4a4834f815488ff07c19ad4f10ab47e73b6698f9febf3f28087614759e082e6e717588c1caff70000000000000000000000000000000008902b3f9b3ed6f0dba21e5d6bfc13fac8f003b3e11de4b883024c3eca0d2c4614604d598d31d9e328c7ee4a9d9be6100000000000000000000000000000000017a918bcd38986300bbc7a401e09b9ae20ccd382280b4e79294b6c8ae7bb1dbe2f72a582e0125381ef2b4fe24998e72f240c881fdbfc414d3e85ead1cdf166ed6929d0b2ccbc35f0811473757b6b41af", - "Expected": "0000000000000000000000000000000015e9fb1d1a586288f07f399b87c37a085df405bcf88505a7d2b0ae6609d4baef7ec358f70edf838d3bb7291c6e5a413c000000000000000000000000000000000cc7d7e2d372183766a842f5c14c1f2a528d502f1bc5dbf5dfc9d812c56503a0b7cf1e6f052e998aaf45cfe24a261551", - "Name": "matter_g1_multiexp_92", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002cdb1466c13290ff0c55c38ca6afe33efdcd09ddbdf7461d6bdb3e36fb5d8be851458620a0bf54932c4ddc1778c97bd0000000000000000000000000000000012755c81c142c5051ec64de7c89719cb59d9003fd8785ed5b36993123418e49cd3afab18b599deb72c969936633a956114d5455ff1717bdd545f4daa37e145121e7bd9636d7a2b65633e5ca5a63f2d9800000000000000000000000000000000067b3a33aaf3fc4b885035e60ba7f3afc7ccfff469cde1a67f48fd8cdf4b15b7beb9e2fbb13daa9283598aaeaff5014d000000000000000000000000000000000bf43cb79d63db544b2db14ec18c11bb9114db93662e8e6e7858d3e4a99cc332890ce90775b6c190d5ed418571fb907d82cd8da62bd901355a60b37ca14ce65d427bcf9551203cae7c346a49b4fa86260000000000000000000000000000000019329a66132ba7ceaf5c030fb4ae9a599895aab7df2a27fd92b55e3a52b99ac51107e798175f2af83991eb63147901d30000000000000000000000000000000005c71bf6552c314dda4bf9f2b4fd8aa368c9e88c0cbf4b1c2bef9137d608738636f40579a360bcaee1a3f12274687063ea2c7fc2050e9c1ebd05d15f197b4b1be61c6820c8d27ade57d85109d7f9824900000000000000000000000000000000048a258134ed95f91070684d04b83634c2d4c16601ad259d41e7d27292897a4d4ac76eb73425583ab1718b91f151019e0000000000000000000000000000000013a0b600765fb760919bf273a7b88bba568350ef82fc382babafd40a7e006e6808a03160f3747878368d8f6b31c619b1e3bf7e661d54796c71437354d7d3182770f10ab450827512a423d3dc82d5b43d00000000000000000000000000000000069d94fe286a9d39b64756e79669add0f66db69ead7db5b5c2fa1a9e5338aaa9051457a3a744c3b08d3afec8b87d2e9b00000000000000000000000000000000105028835bbeff46cb7d9be4b21f07670dc5589603d0d695355591ef5f7ba28c04c8e6dc40f0bdda031bb54a5710b4c0d3a364e7b217dfd649d1e08f76393372d8768bb0fc85c79ef4652417ef1637fc0000000000000000000000000000000015e6aab154e33627f92560e3def26d936a8876c52490732c807749cc28e34cb98fe8f86addb30e129f8149c504d1dcaa0000000000000000000000000000000005f6040a129df2340f3c3fd0935c02cfe162fe1afb58dba7699e7e08851b3a3c3fba36745bbc769aaf01a4f9a401d038eef7b05d5c725ed31269ae9c56dc7ae35048af39ab114319680d4af69be7e7c3000000000000000000000000000000000db5640083674fc75c0b0d1b2d6eb2b03cafa2e63d7a65c894d9a76b196d92916ce85c708c6c451aad65e0b439033d9b000000000000000000000000000000000ac8d6b508ff6797668ded6ceba4680443516d601a155cff48a51297e321417bbffa6eee042255e9ec054d837bffe628acecaee3dd4dc11e341b3dd0073842d90f641d4dd467a6596f337a6147bd30a90000000000000000000000000000000011daaf23ab5fc0ad7abbe7d5f1dc26c8ce388491cc049f01f287eb9b133e52f33d40f8693921d330ae57853539ee30c20000000000000000000000000000000017594ae7ac7f6e4f02df862b6d4ff946ac1a47085b554ebaa720ad3291f576ba720dd455829600f930e3964a44e5c7f30cba585b847bec40515a257cb839c7e5d677d17b7313c258e83d630e65cfb5d200000000000000000000000000000000174b5b9d4ef01fc9d0f05a03612210690d7d57ccb772aa53175f11b9623388de8019ff2ae1d564e7b30ee06bafc37a84000000000000000000000000000000000e4c03b8dc45b0567e9ddaa0a085d169799d2a595c03f2ac679fd858cd59341393e6a0f62dfac0e53598af4758843673b8cd305c650d2e1cfa91ef0aca9dd0d785d7570d6fb67e61fb9b6817116a054400000000000000000000000000000000197f0ad6576bdddb48c58adb1c9b2115cd9b38368dacbea9220d6a86bb621dba93325b676071e38aed2338273c98c4100000000000000000000000000000000011514f08bb28c37f078a47b6a0d53b311d5975c8a3c8e2c24a25f34bfdcbea53bcfa14b7f23adeb20bf440c87a251a66825e5f9d81273f306a065fd064ae24bc2c5ce8dbff6b22128753663a218da8a3000000000000000000000000000000000aa5f3a29c47fed2e4a87bb4c2a46a5a17102535aba9426235d42f00007e35d1c902b43c1068af279cc9a1b689a0dadb00000000000000000000000000000000056d9729f8faa8e12027b993e8dc41a340d61c64e4388c3166482ddecbef8d04085d6ae3764f0d9cfe76288929749235307ff9660ad0c24cbb139486638a2556687f88fb93a290a1d174bf87d780b3fd00000000000000000000000000000000070e376dd57cc8e2146d49ff08c6c6ada6302c36c4eefc3003f0cc3d75040d73599c7e0c2fb9f7e24484c37262f0eb330000000000000000000000000000000016a272b79edcb7e7fa92400bd55fc937d6389f1f0d3d2168656815845d92ab1e7b555fd4ea311802a62cb6c94bdc5d58bfa8ee3b44c70ba2512c00a1aaecede2180b08ac3ac8c550d70407f0c12e027d000000000000000000000000000000000bba6375b28ead3d49197ec9d3662e34c70735ed0f987f05f439da164afcbe98f25d2ce7a5e1e32515eaa4cb7f5a1f98000000000000000000000000000000000b1ec74ff999ac5a7a3ff2c91e93e5f0edf5f296b063d80bca22fa64198a798fa6b6385d25cde65b789454bc2674231058aa85b50e5f4ffe375599cbb912f41d35acbb85a324880148f9b9003c4265bd0000000000000000000000000000000012fadbd9c50f2e8518dc15d95a59ccec0c9886488ed4601b3fddb2bddd77a4bc861f2862c9c4666622e42a5dda7138ad000000000000000000000000000000000b2aa31218a13b4ab0b00d1b76a9ac7bb3d7e6473a29f2f0d137ca63bf7f152954e52182d32d3de31df0e6ef0d102c9e6810c6cd59b14ef4f6a4c2702cc53c65b3dc84988372c1195980417c583fd7ff000000000000000000000000000000000076846443079520c5b1600d5faa5a6d500998ae355c84b9393c79f83f1a2485b1809058bc53cf5f8a1a46bde6cf2e300000000000000000000000000000000012027dd1a4fbf6078b70c507fc2cdc0fefc9a0166694c796eb26e9838195e68fc76297e66e2a0e9e069274d110efb095c5ebc09190ba3df49d8ea55cfd18370b9d443f9d9084cf84f2236ef4723d2d4700000000000000000000000000000000183c019c306c08401b4f2c1d852b29dc47b56bce8cddfdb66d4e3d5385e4bc75bb9806da1eab476ee02e25ca2b4d41c900000000000000000000000000000000066d56711b80dc8725e112e4e2af6c939977aa66c931c6febb21735d78f5afca4bbaddd77387e52dd5bc9c29cf26923613a56b176fc835b7e825c817d432b9ec6d51b0a66483dfbf12166ee979b664cc", - "Expected": "000000000000000000000000000000000f75ea9863e14f6151c452f7a4268b099f97d076b249d02d72caf5d52635bca3c686070d4a4bf997b753c283c82cec600000000000000000000000000000000014402b3e738bee3bda4e62c077e9d355ad8a71b0830ec0e67a4fe6dc59b1f3f7809ca7d07184f53c5afed32db327598d", - "Name": "matter_g1_multiexp_93", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000107072809eaa84dfeba5a95f94aecc2c985c9e5dbc49a741811fe4b2393ba7f6597ac99d8e80c0fbf715a164099e9d5100000000000000000000000000000000124d1694bad88200cde42f1e7721f3390df8dbe4745715a2f0b6f11cfc78996c6f342693acefe88b3d83736cac6e3e05dedf65658ec3cca48fd48e844337159af090c5d1f5e9d713ac6d0fe1e1f193d200000000000000000000000000000000188a853e19d512149800bb0aabcec450561e5ad08b5159e0879422cca1f957ee15bad2b881979d7c8551eb19693bddf3000000000000000000000000000000000dc097932535d21656842615f08e7016f55752556da3be69027d0dea621ef46cc65e335873e041a3dee6c7e5b7589dd5db65ad6bcd6f485eefebda0badfc64e9e7dfe7e911f3ccf4f4fb9528dfebdae6000000000000000000000000000000000d3a53b9865082b23226042f69ca71b99978fd6dc3c8553e33ddb12542d05b026345a23c2b24dbd934be2ba3cd585162000000000000000000000000000000000b0832950405431722c23cc78bf0b9f33c6e2dfecf10e6d503c8c96ca9732c7e7a29251fa5b5b161d14b7155a50846886e0fa09884a7ff4c801ea0722cf6bfa58a46fc3d36058e8c395ea8fe56d9fca40000000000000000000000000000000014e19a8a203bd2e9e9601cf6feeac5699a3b2d2129b6e756b9b5a7af0cd9228083de8c9a2a0ebacd636ab1b662c8c0c7000000000000000000000000000000000faf049bd6532cdad26403b269d7dbdcab6c147ce0ddd6285ad9ae0e8ddab4b6706bbf038fddd7f63e6dc9a766928ec327a3377d7b9ff3aee2ce1194a22d7115b09a9fd53fcfa5e7f76bd9fdd35559610000000000000000000000000000000007e2e69d6c96b1841340c48e8ab070c67054b574bd5778a8e38a9873241baf8b85deb73695873fdd9e3387fb1fec3b6b000000000000000000000000000000000fd151202c399636a360cc014c90caabaf3b01d5a6114e078eb2473bc2fff94f1c24597e39a3d2298a2e9210726bb48e446a62ef5760c995cb3cd0984d607c232c1eb0df5516a501ce448a189a3134d8000000000000000000000000000000000ad0e842dd19673bfb8534ee20591a9076268eb203940212f702131fc6a3e7b226a84324954eb4bcfa8a007669d2317a000000000000000000000000000000000693801615c5282a327ae034c3a1480de0e1c471a412f194178a59582509ac6fe8ea22c8ec8e98034348ac465527f4b35f0c1a7c2dd281f7d2f006497f99f65d6a1e22f1d9aacb08724b3576aa19e19f000000000000000000000000000000000ac9f4f22670b52e0e85a37bcdd729b40c45fcbd6e8aa78626752d736771ede9c570991e347134f95385bd77e404e4700000000000000000000000000000000005964a351f406083b14726ced542fc6d95dcb8bccbd41aa3ca9cf0395d8d29143b897c66c78e2fe56eedf17d4d6f6c1f94c1476ae0a62c502aa096a371e30ca885dc13fc417e3dc9bc00bcdf516764100000000000000000000000000000000018e270b6208be13c23cabf52e31a156209abcd7bab03694fcb7035b453bce8464fa1e090d59a1139fe451d8c699669c800000000000000000000000000000000158dcfe7736f4fc63071a70923d81db9f7d2a03512724dc41ca47a873132da66eb0eda58134312fdaa63ecba7ab529acb677bc9f1f7572f808e969aa50efc519192ab8653c71090e5cf8cdeb1a3544dd0000000000000000000000000000000000a614d7a53b7a06e71aea4014f9b951bc19747cd8822da50f7993c0821e05100dc5fc8d043b2cbe7cc4dcae9837679d0000000000000000000000000000000004e0495281282aeeea480fa47f53f8b521a7df4c5619d4e58f730fe346a6deb3d501ec8b55b581489f28b4d991ebd90cf5ca580a25a5c87015f57f7c23cc51a0beb5926c84d44659e45512da51aa0cf4000000000000000000000000000000000edd664ad8b77d86bda4ba772f677d34c9341ce2b4d2af4b2680383bce0fd4468e936841dd57753d06c50a3357a47eea00000000000000000000000000000000063eacafb540655984104f60569720625e4499f048ec7849577caf240634ffc42612ca7ca92c17e3e50aa627059cddf2fa1cc45c35e266a82899d8ea0c9c1f96f96140eace41a8758a87975b088f0231000000000000000000000000000000000a9d9bea7d8a058cf254d2b7e10f6d2e8244cf131c6f87c4e25b5febcac352d02b1b45ba347e0b891c8b08e7b5dec82d0000000000000000000000000000000001d256cedcde615d01e15cf526c4a8bc8b565055567aa1de1847b524fa49b4b9f654f5b66cda0a78f414848aab42b05c93d2908aa9266844eb265c2b1c17f8357a5ff039836ba83c837909f6a9d0bc03000000000000000000000000000000001519b05b59250c72c9db7f425954694b29b36af21d9293a36d7bcd1ffb53d0ec55a3ceb7980580ce6f9fb6a0faa7bf3f0000000000000000000000000000000009e7d045b69e2dccad22dac427f5938974a6394c9fef84633fb5f90a0d09d437219f1b7ef7e7bb03eed106948eeb560d3b94325aad8a2c80971a781bf6f6bebad63ee37405ab7e903fb7094beef14d060000000000000000000000000000000017cac7707469b98c6b4d24fecf6d818dce6c8b9eb44bb08d6e475e385c30fafc81551e74ee98cc854d38d77d15459e750000000000000000000000000000000019d5bea3e48fa7bd273233bd6325bbe38267e4950dca4fd9ad051f487e7933a366469107258d69f0603b2f9a8dea2e4f5143a8e734824840346078aec03d6760564870c5ee2b2dc13f8a39ac452be9f5000000000000000000000000000000000b993d9303ecc19122654d5cb10d488af5411c451b39b1e19e7a104477da50324472076c55c4557576a9e5d7755a381900000000000000000000000000000000172b34e576f0539e32c5025b3a8f25b5bf407f3f3dda863b194a9fd97d3a6facc00902c95fe076b91713bec162f61cbf0dbee37fea759c2a58cf360c654f85298e8ff44b3f900e8229c3f838345d053b00000000000000000000000000000000170d799ffc4c0abf6c582b41732308665d790900ef07a74183826e48c9f0fc500b09109b2b13b2b33cc17e6e639d2969000000000000000000000000000000001943fe62329fcb67a45b5155da7f950ee12fcfe0e8e9ee15868409ae44adaa5f03c330206d7d97fa733c9e93957755a0b92f9db82d0976f4c379622c4028002ede2ab17f647bca3bbfb159045cdb342b00000000000000000000000000000000078681739039a022499219b298799027a341be64204a34a97a8115e5e10486420c18664825b764fd7bb931343c2558a60000000000000000000000000000000003313d3482f952c6f9cd4ec2f2b61f28ecf7d8cc7e60f17e9aac8e63ab25dd6bf2da2d67805debce0dad8fe37a36625298df4ba50cd5cb5a02d5f50b3ba23e5f5b0172a46cc315a0a94fed05551a68af", - "Expected": "0000000000000000000000000000000010aaf24dce0b05179769031ab81db339cda85cf68963640b888d3aca310a6de690150166c0943d658e51524981a1f391000000000000000000000000000000000d1af37c2bdca5886d73567cb00d5a9859755267800d7239cf39c291ba83b1c67e6a3532a2d8e8590c1bf2d845001038", - "Name": "matter_g1_multiexp_94", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019401d9118a5c2b0c6ae40507cae6180083258eb6c45cb8bf2fd5d2703c95fb07c031c82d0568a395e18015fe0a48a2b000000000000000000000000000000000511b992882f75fe98131fd35276b7a1de527b94718549bb4f5c9980917b6301a86e45fb7c7e3ea99e54158e49c7e60ee49662df81f6bd455ee554704ff0c7d5a589d91e017d7ab4c500d36378c17c89000000000000000000000000000000000d886eedf2a2b33a50dae5ca6f41237c9425b0a4daf08bf4789a3ea8c7f598d53257916d9c03df0d63f12a1a804fe0990000000000000000000000000000000012cb777812e76378f04fdaf2cea12456aa9e11b4c3ab0f12e63fe7ab11c716562b07b3864cb9dabb7970c81bc1da324c79eb26c79d78ab84c4d7e48e56889a601fda17901037a74fd79355e7536f39530000000000000000000000000000000009f09107ccfc5c4ac9b7e0058d6a0c4d7dc4309134d5fb972de3156a554211d4a2fbe639bb8a93d86091137671ab8447000000000000000000000000000000000b7f9955092221c8a2f09c6a9ffe6483ec0f8a0f6c555ec1772c260fb62c4ada6dc7beb92e29620afd15466b5f025cbed2918ddc2bfb7f7cb3d7e74b43b9a972c5b51ac20ea83f41d5b51034b5714c0b0000000000000000000000000000000009a22492a1b78342b919f7b5c8fcdddac408cdd3e8af4d6de5a4b1e510fa3b7e0e6887bcbe074fa839f2d0dc892db631000000000000000000000000000000000e5eac3a77c7a3e89e9324abcc0203046948f3d62e40156a5e1b1d9a274d408d6cb49e06b8cfcd21b596923f86c02c6be9a8159fd7915c15db69355514d9dd26c66fbd14af969ee576401b1b782fc6d30000000000000000000000000000000019914b405a24e72896b3d231582f0075fa7e59b0d0bc796d790754902238943ba634dce66131260efbb5dfc3925a1d54000000000000000000000000000000000352a5a986c500e41d2fa4f65e5a917061b3f9449c1e720caac187c6bfd4ce14f1b49ad414864a1510894530cfb4a768c818ce6e33e581595e83cf8d33a62edc26ed38c22f20c6949a94e2652bb954cc0000000000000000000000000000000019567f8de70c4cbbb25335e69154ce48d4106c8c9d0027e17c67777dedf758203b0a8fa3863d4e7812311f6cde36a6640000000000000000000000000000000009947f7401d03fa8b0801b130b43f729d6a71c04edfaf7b9d3265f82b039131fa09f20f9b4565d21939ab7dc7dd3477e9ab338e94b31d22947dbeb20fce3150127249d2db6107d95bdd032eb24c496450000000000000000000000000000000003c42ae9653d1d1f00d79f8b1a0c53d0f2d7f3ca52ca1960a621fc1bead7ab31cf6e5bf30c5cf7877c83b33b6b5b54d6000000000000000000000000000000001221117f45dea3fa1f832bb8280512841ad1798b76f1dd16dc320ea7c86473f6f8c98ce007ebc3ebc39e7a860be987fe96acb797236dbd0316fdd355f07b9b45c9bc626f73105e87c376af4d7dc075d30000000000000000000000000000000004340b7dbe7c27014add4ecbdf310de758ea5dd1100508a96501ae3caf9955c877113971a61f66e3691d09f0a259d4ac0000000000000000000000000000000001d5f83065f6d178b4dbbe0f00f0a88edf0a90021601bddc2cc27fb0ccccce7e48c6283a1e641408a20de15219b5553e60bc12a8b34e717b2c410d026660c14182250d7c66f8f88dd4cc94e550421caf0000000000000000000000000000000017679efa923688425fa9cff1f8e89ae681245371017f574f4a655aa780bd11009579d7daa47249f503592bf0ab79e67b0000000000000000000000000000000018f57a1ee533981c8df24895ad174228330ea361448ed63e522637df44cc1b888e969ee94d7b44bd532b655123f8f5d8537f0f732fee8b882d254a81704d2310c05dde186232f3cffc05401fa9830215000000000000000000000000000000000bf47631b34b2694ff7fc5d1e25de2195e606daafec34fc2c8ec86c0a325214d874002422810a81cff654eda187076eb000000000000000000000000000000000931c54d05eb43195c3ff6b396e324b5878c3fd507637c316c62b3b6e2d3d84cff9f33cd1046f1939187979330d3fc431a22bc0bec2501a505cc8e00a24792bb380ed451ab6f56fde07ace8b6c9348a200000000000000000000000000000000138adb70a3dce09176914deb0be17821cd0212c6ab554f7e200804dcade06c6cb5f7b084a1d6ac0ef8eeabc7cabe7717000000000000000000000000000000000a4422c569aced58938abb7bdbdefdb27cb06677c1066d17f98a59f847928d1bf2343acf8b5d1717aa38cf81959ac1acc7b10c801fb9d929432cbbe994b404d3baa5633628f396d20d047fe2c2ac2914000000000000000000000000000000000fd9ff095adf9e3f666d3141717ac4a96deb5b4f92dcee35be1d305031d06d51ecabf863a41cfd8dcda0fc94ecf79982000000000000000000000000000000000fb55855aab9e557046ed53421cd3627b519859e26338328d7da249fdfa6a07fa533f748eb5dd564f9922ad911121b2784f2f3f31d9869799ed8bfc2cb129dbbeeb096d771730ae2863c4ddece66158d000000000000000000000000000000001054ff028d2e2875330e3d0ffc52e2a83ee2ad2adf024ee294f695113d9d645f0be2a3d3c70f758f43f2deeb542aae810000000000000000000000000000000009a5e96cd08d3ee4e740e2f7b94a4e390ab5f6f572c4a1b2d927a7ef2365557ab9be65b8e2388fb571a3765892a96445c62206fadb762c23bf77f69f69bd492674bb92edb39248ad2a432f819304e6ea000000000000000000000000000000000bb1de70113edd86e5304248fa2f857f1620dc8a6bb28680f537e04029aee158e2ead4e0eaa373b812f6ca988dc40e7f0000000000000000000000000000000012118b670c9df77af087ad01e3b766d4a2b7c2b2a319cd733ed6c02ec36d9002036964fc442db992bf730c57a7d0a407a6f950de53d07fda75ab43f73982c2684edb06317568df15b8712dff2ef782830000000000000000000000000000000001968aed17e572c0d99e4e9262f239771976dcd9d7df19c20bfa94aefe1d4f3a3117bbfa4a6e329bc6b9552731446dd10000000000000000000000000000000004e64ce59b928e8cac2f744bef119018de8395b712013b0c69855fbf2bdc6a750a947b1a81c9df959c78367ed0e1575d95a373fab5176d124f783a36eb2346dddd5c4eba9e24e4c0cdc4f925e2e24cc9000000000000000000000000000000000148cd980512e0aa153adbdef262f098b1ece801ee4024b5561e261d39b495165851781d519d75f83dc5f298d40b4e9e0000000000000000000000000000000001dd43f37950976e50071226b6aa47c229085807ce9634e6583f5a2d47eb8547d4de0669b16a2771791c9ccdb4289cd9319d855218eee020f9cf8e4c0b6004902f0b16eedba8a1c911476af34f65dd40", - "Expected": "00000000000000000000000000000000059c7ca50efe2d0a64b55a560a08976b437c350860f9599fd30370d1cbbeacae147144c216cb3e63afb2ddcf34282a5f0000000000000000000000000000000018f42ef2fb8eb6cc8c31600a3be37ece06ee567ce0c8b8c7a54c910041b8c25b2d94a94722904de079737f06e817f380", - "Name": "matter_g1_multiexp_95", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000172bbfff135f33357b0dd0e8545da99c4ee74d6414724c2aa66ffc85f3a9d0e35ac80850436745a12ca6f1c4ae5c0ecb00000000000000000000000000000000152dac882023cce1a3e1fd4d8d5aedcdf6acb2ca9628a94ce92a4a551b1b7268589b52b2c90af6e4be9631eebc2ef8a62a397c2f19a8c4e66df0e062f179be2f45a0c5e104588222a1a78447512f299b000000000000000000000000000000000c40d04b3002c21b041ea8b8ce967056435fadb479fe1fe20c373b2e2c5b568b7a38d031424bc835bdbd85af8ed1d0380000000000000000000000000000000005e7357194364947c8dc32fd74757a3f3014e914dc25f42b2dd86230ca4f86981476e6f10b1559694bc17d014cd243d7f193d5a575c80a3e7599923bf5a8ba8a48e8f98322d1d8eb1da42e446d518c1b000000000000000000000000000000001474002c92db026ff5bce69eddf1d8ff8e6d2ab9427bb82377911597fafa4d60256836c094cd513a52a3a09797afbf5300000000000000000000000000000000176a7b311a333c2d4f6eec66e8c889ecd7becca75fb35a38bcccae52f10ff69630393fb7d87c3b6d97cd648be099c56507f2013742ddf2d35448feb80b6b7aaf2925d3975ce28ed2b1ac789886ae26e40000000000000000000000000000000009ecbdc4836c6c0cb4ccd014f9e582112bce0d0ab047115f38ed5dd51c54de5a43321e85c9b3e9af5fae0caaf2493fcf00000000000000000000000000000000034425e05f0adb1577f7b1bf9b9b50a76bc894f5ff0e9a8d190412eeeaf80d0bb96f21478fe8adea327f69c9137f57094e637a80a4eb1b2caba68b6828aa18f956c62baa7c5e9e591a15156c5abb6050000000000000000000000000000000000ec3d4fe1b5e1c26de1558d7dc51eba3b6c37ec037de184e8a6f481ae20b830c92221593e1bbe4ee76a85cb10b33e18b000000000000000000000000000000000e51f811e16f00626d934e69024b55dc29fa4ea363916cd8f44f928fda6e3ca4947eb15de24ce1952c39e9ac52d2739d27671631f9afd9d2e86f263f5c17c3c11c7f6e43efb6d75cb2cb8250094f2289000000000000000000000000000000001205dfd803ff3688c2023913aecb10c138be4d03756e2f05a63627973f511c2635571469d4f630758627f7977b418729000000000000000000000000000000001186b9c0d2b2073b495ef9c233c275922bdbf4691e8be085051c09e245242526b13b7051782a80726b381a72b5ef9d5ec2decb1f482f3eb48e7f52b89f6452b659812ef79bb42fb25f03aa9969faf9bc000000000000000000000000000000000413f6ee9bb25469af4298dde67f0a4a26d2f528848ac6646764703922c78d65e046204f891ac94b0b4c425110fe986e0000000000000000000000000000000011860881aa871fa3a6693b23fd7b1da0bcaaf044058ea0700b786f12f1074c615577e572e33faf8b3562bc285632696d911eb1de54fa8ccb746336b681504fd08f995c864a8dae2aa866862f81f0e7850000000000000000000000000000000000010e8fe8fd7863c2807a4bd717fc4646a0e4f99598b9c6c2cf0547d039d58290a367e4ad851c7a67e8dd546d5e328200000000000000000000000000000000063ea10e84e4f5824ad7b9b68398c9154ab25ddc4043a4990d80e09dd94a890dbabf9c3d93b13c4f40bd7b1ff32b14b2fd0a61dbcb0c657e824cbcf4670a31a95ecbd47a9b93812cd5124f3ac9450c1b0000000000000000000000000000000011cbc725705b809ad69c5ebb55ade0039989728e7103b684feb35c8142b100175235c2b395e37a20aa40845ebe2dabcf00000000000000000000000000000000057b5b5a5cf5f5bce985295f8a50252967aa54e934e87855097eb083a59863aba19ffcec4354a5a831b747175ba10e878118e9c70cc5def8e7d258e05273937c514131f39e0cc9fd2a3620dbffc7ce3c00000000000000000000000000000000041043cea626d6ab553b95c6e09de597454a3a3d1b8a75fc9ecb3afe15bdd8b5e73b8012ead8777df8957701fc9c9022000000000000000000000000000000000185da96dd1d54bb7ca5d7dc2fbe4cbd8ac95f06fe85a7a26e5e0e6353f6a6daf73b74117ee62be4f3fb268fb4c86275c445931b79e2b826aca02d1bfbb00c2dfb6d30ac2ef97a4ded18243b1afce773000000000000000000000000000000000a06b91559964aa8e8628946bfb720047915ddf08d24fa34f7b241e16bb163ef67f1e84fd205485d17725a8386a7016a000000000000000000000000000000000ec787cf5134bbd832d2a7dc1ed87b8c824552d92fdb30a790e1c73b22c753540a9747eecaf14dbf867d9667b7b852c7982ae6de98df906922e660d461009ba6c04cc6497f3645a66385c775b21b210b00000000000000000000000000000000053bfa3bd311c1780afa1862de6ae8a475b8eb9c61fcee2b63dbb6556022d703bc7eb204fb038056c654dfb940e7039400000000000000000000000000000000074ab5797d3c39804dfd5359b69a4bdd2b738670d13662eb2c112eefbc0f90da85dd1a4b6e0613785fc66b100d129202000674ac5d09c6c599173bbe9a43726c120c3a60a96d43954727a2f33ac4320d000000000000000000000000000000000cd50ddae4f053bf5b7b3237701bdee2f5167e09d824d260e89ea498fb3b593e5053b781c159302b0433ead35f072c850000000000000000000000000000000001abe8539a4215a3b7b78c79c306dcef7334c83f571f4d6836e1c1839a65c8cfa9a0811395e3c4bea26b22ac2175757e773f8e9637886d795b75e7ecaee512005c1780e7ab17b9f20ae9232595478bb20000000000000000000000000000000001e6e0709869922c36e073fdf1404a973e0467cab3a04a806361e743d67468f0d66de28f6c0c7b8cf92954330485db0500000000000000000000000000000000084e96298cca174344b7b86052426f9316a15b4031b9e42677253fd9355b1c99ed9ca3eb3949005078ba228d4167f8b0759d0bab12ac790cc3a16e88f1a108e670681f117d4fc7d01f8c5a2d6ca7fe8e0000000000000000000000000000000002c5e399eab947a52660807752ca662212cf3a201c1127dab3586cae88f8ab6dd23deb0312387178e0e9526bc8fc7b8d000000000000000000000000000000000ad86b21dbf58098fc4f758d7ec9204bb16cbbe680b58fa42821456d4fa508e42b53c8988dc0d9a4d6f6a782a5fb90b6cce865074a8a41f8a3f40228046c5be68bdb50ced10bb73ac8472f052530293800000000000000000000000000000000181f41dfee6effe70a28e4c53bb6cec52f232caee076f680fd63d73cae24b44709fc63ee3782a36278edcceeb7b32415000000000000000000000000000000000088d9011a9db9294bb4451e9981e84efa595462e26e5dbe14e9c84a8c5ddeca94f49857cf3b8a70e6a4047ad76d234585e2f9597c9b687150864e90ab042f4f012a54d92cf9d2ece09e4a081ec9773f", - "Expected": "000000000000000000000000000000001170d9938910ce68e56f9e84be6f6ad284a244adbf26daf8d42f6411c9794b707454ec9300442fcb7a0f08eb91edf86800000000000000000000000000000000043679c7a917148d141a785e65b0a067e35a016c24bf7639ba374e21a817819ad67d317ee70852bd13a1fc3a373a38d2", - "Name": "matter_g1_multiexp_96", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d9cb39df5b28781d33d996039da8c94cd810bb85aa5868008b4267ad2a8670924d4b3ad7898b33689aab2211bb9bdc00000000000000000000000000000000007a8a6f888722e4717acbfc42ef1907206db31603c403e0a8c1ac0af9b37e63124d4645a506265487e5f9eda09c8baf85431a1df7678e49ee049b75ea968ca255ef456dd58cce57b64edffac1ac223c000000000000000000000000000000000db6af04eccb3ceedc11378406a26613aebbbc2201a9ea2089848c7af3b34e46a3421d5704242c4b333f72180f6baa0200000000000000000000000000000000105f40c8b702f0989a9e20f72ff6a4f7310d81787e87638c33a61985f02116e106218d64976d50bcc61cf5bcbbff7c9eb6ccbc0b600f11f1b89061d94c6fbdc9b1d389244fb29a5d140dab8842d44eaa000000000000000000000000000000000a77e39abdc9d64d72ea4b321e3310a145feaa5d342bc1a5b16c0143dd01caeda4f18909acccb3cb5b43ad999a94f91b0000000000000000000000000000000016fc4a4f6b488fd1f45a158d941d7aeb5d431821589ee845c64eb198ff10931d586f8a0678237be2a394f5976d895bc854dfe31190469897c30ac3736ab166220dd3702df5bc897835347713d03a8d04000000000000000000000000000000000d0ddfc05bc9f89eed488752d64698bf00633c83cc37931d95a599d6be6e4c5d611a4151839133e86f74bb91aed1703b000000000000000000000000000000000be3dbea501c822730ab0176f64903931aa46b0179c59556ee7e1ba54605ed8da2eafed7eb2254a7ddc34e553a9b6d59eff1ceff9e5184dd9fea44da4f07529823dc9b100f776cef6f6881120f7de11a0000000000000000000000000000000004d6f288744016f15b21da736283af2ed1f45df12067a3a70391f66fff3ce3953a51169eba6288cabd84ffe7f597c9fc000000000000000000000000000000000f6556a63def531a940269b073ea98be79558d832123dd681bb4446d4c11e2fed59a2f97904797abb07ba53e0d48e923b273e4c6266c1f5cf022902fe1310d2191af91c47995486342bc61cd361eab850000000000000000000000000000000013e692a13e79c734f3758780fbdabff86fe5936bf6c60f2f155ec4d1c49cdefb97dc02c1f1e4280c5ebb055914d93f9d00000000000000000000000000000000060898a9365ae49697e5ac23e320261eda04d818c5f1153f647844b1910bb3430d3c06df9a64af8ff9dd25c18cbfa79d1342b5cd4ad3179f406941ef6ea15d0aecdf9f6d96dc334c39b7dca89d256d4f000000000000000000000000000000000a2a4d92ad63dade4d666ea949dd64d5886eaa3c7ce466677356ce9f65520591c1aab590b48e9fe1eaa0f0f3e306cefc0000000000000000000000000000000002a2bfc836409b33bbe078a5f89c5142411bde621e9117ddf9f81f37bd546c3e2ba94975ab4652fa0858d5a2361592715b36620f65ed84fc0bb344b4b73f4eba4b1680a47b28b47f6d10f9ee8239812500000000000000000000000000000000075d3ebb18437feb21f94ad5e2ce96cbaea2f6d68885483ed54ee67f2dbcf8cfa39f405afb46e45d08cb804a7aee3b8e000000000000000000000000000000000d42851366ed4694730b7c58450c3f9ebd365f15fa4dfa3fd226d180aaa921a0d897278506ede76b85decddc9580a365249ca9bcf879a770b0a054422a6ea97ae795118ae45532c1523c842696de6d17000000000000000000000000000000001722e05d33728260ebf5e4b48104cb2c89b4bc3073767e56fda373bc0e29261c9a5c53e5768b453b116494c1109cba2000000000000000000000000000000000030e4da8620007236b89103b215e54751ba2f2dce19b0304997f450791880ad34f3e43cc4e6852aa599fd65ef72dd9a5c014a0aa616e809b674390b4553bf2d9bf325e73d3a935eba94488dddee4e895000000000000000000000000000000000c4e7e44e8e0387bd99311343d2ff3a080ddad557c8639aad64c4f6e47d64f48b91f9de2e33b4b9c182a87efce5d4e0e000000000000000000000000000000000e7cb49fd7aca3daef3c0329c950c832e1d007f21a4f950f367eb37b5d7433f5d6f1ab1c206232b2ee32137b56b53967ab722a1c20f068b6955a44073914c418a082345796912ca634e79983a24ec4bb0000000000000000000000000000000014026b8dae20a1913ecb45359e9ceb317137244e16a036ac760b47363f2d389ef6cb12cd5f5fb9e8e31ccd39bf114f8b000000000000000000000000000000000f07f9e76789dd937b85e02a9c346f81e87637bd03bd5f98a9b18ad6d109100b540aaadf1fec048530bcfa35dbb5b8ae8b314f83cc3ad501caa44b4c3ca8cf68c70ff6920f445d3a7ada212b6a19ba3e000000000000000000000000000000000a0249c354052094cae5a3d77313360a8956839af614184696b5b7fbd2af6555c6ae14a150220f01d624484b9096eaa700000000000000000000000000000000043098df38ab37f42175cc9f9fa9ecbde75bb344776ed078632b3d8bbfbf04103adde27ef0d361177bb3814cbb8bc54994ffab83099c69845cc87727d459ae300a5725ec53176424ab0ec8bd3f80eaff0000000000000000000000000000000011e90effb7ae193b47afffe6fcaa0a28c358222cbb087ce479b7fe88d25386c5a9c9527899d7633eaaed9d982d3ed4e100000000000000000000000000000000174877f80e5e9daf2cc219545ce67b904319f75c0284e41552662512727c1e05b364364c4c8835c1c9c6fe028ae45895b1d80be637e2abd98d0433150e14b629d98fc0918c7dfc179204669ab465e90300000000000000000000000000000000170e754e54f64090c4c7520bfed82665b44728904092fe3a4fb2fd2d3667ccd4ecb796e5ed9fc4dafd315c0b6dc22b86000000000000000000000000000000001081e62ee7c502159f7a8e28c5ee45fb7fc5b301f3a081899bce10096c74d1bf7834d12cb7fb1301b986e9c6f7501d53e670a57ce4dcfa680e60ef33ba99c437e4fdb160ea1012de36f4b59613a6af85000000000000000000000000000000001434584d8d1cb34eb29fd1c95871f218f4dc46f8b2ddabafdc7049e88f54fa4b80c88960a76411e365aa65cbf77f01ce000000000000000000000000000000000e4e2e1318c5907a07a7ff154b07e959d681a69c066585ba046b8889d417d01c503b32a924500944d43e68d7da8da35d54a999fdf391d3944318c54680e69b58ce3778683b6f2c607d64450ed32c6d89000000000000000000000000000000000945a9d0603a3bd0278fce30f0cf97274319a760291fea5aee143c364cc0bc60e59dcd1093aca1a3ef64696ec47845e1000000000000000000000000000000000a77cc690d55763a94aa48c210610833427ed3176b6dca184598755f539359bc7302f8dc2cc941d447d9b5b68fa716b70563ae7b444cca7ebaba36b8d59aaa5c0e6c1454a4a2907866247e752e640a7d", - "Expected": "000000000000000000000000000000000ac708f97c9e9fef4482af7b95c59c2ce6b8826f6b046b5a29ee2224ad66648a8d1f9959ff434c77394199fbe75780db000000000000000000000000000000000983fb55837062305d7fbcfe8c76cce1c431067a97392923720a6c4f963839d7d2661e2a8dacad1f151f505748239798", - "Name": "matter_g1_multiexp_97", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ae003001e3173dbd17f4d6598fcdaba9966f1e22a06ce747f7d2a06b2bd37579d093242a4940bd816ced07ec1917365000000000000000000000000000000000b27db470845f285c792da64e870b818a7598fb820313e075ec72e78f59f3903cb0860b749bfc67540a8bc80e844a8de5b59d128b5ac47106b4114cf225dceb621d177141ef5783943f40a54ad94e9900000000000000000000000000000000018a33b2c2f1ea187672612b51c8dfdd9e86674df58ff4f77ff3f71628e7aafbb80ad22f34ab4203c42bd39a4f73c3d6d0000000000000000000000000000000017c3a68d8782a479ba9aa829e3f261a3e1b832595fe3922d800349bdc2bf58e0c1b523eb0924bf0996e38aa83267f570a057c0405e24b7373f67197b2109b633a02589711b6a92ff49ca024f893d7ecc0000000000000000000000000000000015347adf6539116167ee71557b78d8fe13373512ca7d8d365179e25ae8ed2c6a65e1f643cb0ed677a2f44eab809d5b640000000000000000000000000000000002360dbbe0b7f8e97f6aec4b20a7e6525d83056975a4228901b4f19259c9ff2d2ee00da9bb9085232fdf843e5d305561677b05905180182427efeb848b2ba2eafbabc7519ab33db14de0746afb6071910000000000000000000000000000000005b62380515d49aa1427800077a11a8f01ff00fe7df53a13a9266910e4038167ab747bbd0705fc25ae2cb0e2451c893c0000000000000000000000000000000008de7bcad1c67d7f1fb5cfb9d20ac2134006618ce0d22f4120f5396bf8164c0effb0e3ebba7959e9dde757973080a9cc53e7f69582f4c106ee5bfccba1d5f557736c1b75b6e3777cfde47d552e6bdcac00000000000000000000000000000000185bee837e3212323dc40fd471ed9a1a58f2aebfcf7f07ab761d40bc1ed77b385a134c99385d07e75c5f8c51d6496482000000000000000000000000000000000d7d42e4e18040da671799f981d404085fed490182d397685498e80967cb9c080a766d5c8822152d78920fb388b979f534c87bfb629b817e7ab97def7400b0a83e47af8d628787ff814733fdf34ba8d50000000000000000000000000000000012961da3be1ecc774fc9df2dcd87c337ee50a99df7c4821fe08da7327276a24d754be95b6e916d5c63926b6e44b74310000000000000000000000000000000000e44d11949fe33bc3a0ddfcc74c5b0fa79cebfc0d4a00a574ad7659c7a5e72c728ae4ee031af57e9135a3eabd93686edbebb60069acf431e1671e3d00e4da0d70fa11ed4099b21d45a2b811f99dd9cca000000000000000000000000000000000f03c013d5554584c2030ea02cb451ae508fe6dcba72bf7c49cb47a25d3d65eabb2fe043b9ea90e03571aa7b64be8b11000000000000000000000000000000001479789662864eabf677d2a541e48e5ce70f35a2cd6c0a476d4179d02955a51123e75c650888e514aecc85d67781c8c18b1ee2765e762f1b8c2451270cd5a755758fd733d7922a537aa9f1fd7d0c959600000000000000000000000000000000139bf8fb623dd156a3fcc46eca51e61155cf58e2dfe8edfe717effdd4418c833db7fde2031ef27edb4a70f9d60d67440000000000000000000000000000000000c352a16159eeca4dc9a86601973c02e39f2a11c8a0955ad52236d7e46dbc405147258ea8558505bef0f09ba92527c76d5009fd559714d5692de5500ec8cae9c04ae1ab1c7c6e08c8738ef22da19ceca0000000000000000000000000000000005b8c4c2782a2a2a3abe4f99e60db6ff4179399aef4b9e305fe037e1a14a4c03ff59be1e91f55e5bf316356bbaf876af000000000000000000000000000000000eae605cef3beee4a176a0589f2676b3e212edcd7ac5834ece3066bbbb587bdb6bbe46663acfd9d8aba2251a238004106330c755ef708d8eb129475785f24be9e7836385ac918c60ad36e80e2f3281b8000000000000000000000000000000001038258f67b0097ec51adee244cc15d63c4d3bf1b3b3e64ef8ae6ac15a7c4195fe97bfe8c5a42981a2463ed1b39032de000000000000000000000000000000000a6f27fc1f2dca48f6e26456de5d9fb840e4ed3fd9ff12372e51130d7c439f4ceb4fa929da2dfa3ca271d34e9aa0985ec2431888d05cae840dde4c26911db1893659fdc345d5433556d9bf75e51fe374000000000000000000000000000000000373fbfebce5c599172ab017e8f4f9813b0e6aef3031faf61c336aa7d6b64c8986827a27605b476bfc1057a0388f864d00000000000000000000000000000000079ec2c41547d98277c60dc46a61ddda51c9df65a8ad2d0a64d483eb245986de36eea2509cf7949c5fb05a77f9cf3bacc9a72369cda74e5c86c6559cbc4f4db1b3ab24c5150c7decea862ede3c02c505000000000000000000000000000000000d50821953bbbdb494e48c59c940c5f2ac2b902f4c2ba2b2ad50960a51ed7eb1a9d592bb903a03b0b90d8817d10848ba000000000000000000000000000000000bf0898bd20e08205aa218e529db578d5118ae411159ed372eb8968cd773ebb1619f92107d2948020bb3c721ea63159dc2f50989b04fc29c4c4a0090fb11e860c15f89a66f3bb8281e4678ba63ff3f9a0000000000000000000000000000000006bab55b7648be3eaec947694311289f17258876d74a7d92f22b7807d007fe142a71210684593b1aabf74579eb1b1c17000000000000000000000000000000001016b28dadfe9b65d86a1f843f7ff4b774eab74431b68b079527c2387ee6cac69e95ca564346fc54237edd3d2d31f6ed9fc9abf1c76ff11ab538f46ce768ba597eb5f2f63073ec67e8de10aa1d666720000000000000000000000000000000000c0d5ae44a0863ef3d6d32f1d8f32f2c5b89112652e2e3d6ce620479882fafd73cd3627f9f11315020c8fc9341c7fb4800000000000000000000000000000000197067de9d61733dc0367d91f55a57ae268d5e7babe7882c1fbcf03cc38de7a2dc41acfa16bac0ae63418fc349b9471cd4167723682bc0e7476797b3be5e14b8de3e4e23b4ca33c50a2096cda8766dd7000000000000000000000000000000000c3964c79741fe8093ccf2f3d118b33897a18d920ca242ae153118bc17bf0102fd19a9e4000698b256930a2f415305180000000000000000000000000000000003ce4a6877879ee56299ed27f634571126d9f8ca8ccb1e67100064e7efb435cacb1ada74d7c7529b495957ce7a5dfe709644c3727f78dd12811092190d5d10adcd5b9fc581dd783c97d4e7b5130f309a0000000000000000000000000000000018e6260c0cd6cf806ee82a047c51a85e0d7023883cfb05993ee81220e0871b122c12e65bb99b20787322d93b82089e98000000000000000000000000000000000d5b66fc46b7fb60fe8efb6659bbe948c6776d7780633f007123c5c49f5fbe7e3defc0f3d896333d0ca01244f2b6effe0df9846c84354ab7f947caca7800e12e38d8e6651527e6831f4d8b1bd66c4f3d", - "Expected": "000000000000000000000000000000000c7aa8aaa848c068104b88d0757551612285327ba5fbe35ccb4eacb1bc96a341786e4548f5f86f6ded789b712a4be74b0000000000000000000000000000000015c9aefc358834f21ec85092cd69df37e0036ea6ddf23a3ca052a669446b183e5340ec7ce894ff6575f5e6531947c84a", - "Name": "matter_g1_multiexp_98", - "Gas": 64128, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004acd4cb6bcfed3219c3aee9368feeb58d77a7ec81d19bea11402015f4bd0ee2d7afd86fa7ae9dd320910ca28eb6d98f0000000000000000000000000000000009fe1b0094c0c2ae80a3c5accfed5d212ce39f867aa2150b781c193a0053aecb04d06e005fbfa0a24595e5968d024be18a71abe11a893fce872f6b8a020b6d84241df03eb934b50cbf3571df4800a8330000000000000000000000000000000018cf9bf39549c35e94211b4e2d0a0157d73e1ce8a17cd724eb33c38281dac07e12eec61b27b440b220c4f21915a73a52000000000000000000000000000000000fca6d956989db84dcfe58b0310fc21b5bdc82a32838c8d9cae912d683dd9c67f68e15b3fbf9d7b430ba239c8904fdd2bbf28e5bca314391550d3a0fce50b1220965860e72c8c3865a2d4c599d31d3f1000000000000000000000000000000001897956bc232fd5a9b0ed1b533bebef8ddd9e97002513eec71d67ce1086ba8473f2c013af7d8ac548290453d9f71bd5a000000000000000000000000000000000796da5c8ac165d416c8fa36d84e11bcaa80c1bbfe18efde4b4b2c71d6d00fa24f3d51eac312cad9e854f094dcb6ec7458b208a6845aeb2bf31999042c59b7b130a7ce5297e88023953b1aef63616fe4000000000000000000000000000000000302240769257e92899da03fcc4abe1ad3944b74c3046e790e4e950f2958426b5fdc691401a1c8a531f42185d382fe5b000000000000000000000000000000000053750b58b6d2fbacae94e22b397261e541eb4abf4715b3f528dbfc3388122918b1b4b506f2fef89ea936efdef0105b3b53b6cf9e0ce1661c4960283be790abf956c2d6433529b8f3a32b92b227aebe000000000000000000000000000000000168a635a14f61734372f4bdd2fd564d77afa8588e1828d88c4c90bb50f57473b2c20585dc0e93726b84e73c61f29ef1000000000000000000000000000000000e6e92355e59304ad35b1dbfbb98db803d5fadabdef4fb1b2a54080ec9a33a7147ebb4d5219acabd949337bebbffa793b049228435ade4c4c565e65f39f13a84c747c312afcdaff352560b9fb3cfebcc000000000000000000000000000000001797bf2ac9b490cd43a346fdc64bfb22301a0a0e371bb4df8ec02342b4fcc99af43b4735665c6b1386fa04a3dc5406e3000000000000000000000000000000000fcc20f4aec04b7896ddfd86f58c2e1e9dc6f863ec3b477572c073c0f4fb07ee8dc0d5a843321446445b6e7846fbc5d556197f5ad17062d2ecbdc8887bcdd32e5ed4c48cefd9e14d622a0b800d9703300000000000000000000000000000000013ddb8ff149222a5a0a997c0b89aeee36a6ff2540de3cba8bfe6a2a64fb505f13ad956a3882082ab85bfbe72f3a3a6b600000000000000000000000000000000102c1a1085f60cd5326966a2dda0872290e1658002ff3ed95c47cc0345565076bdecdeab7082bcfb439cf7f3e445faaf721d9d7fe10104cafcad71307e785321ab87b2b69593535caecbf0e166cfda5b00000000000000000000000000000000189515e637d404ce6db58d24774609cf946074aa22066d808dc022824a26b381bf09148005c61156a976154b025d71c90000000000000000000000000000000009102e313c4517cdd3d07a66e0013eeafc996c21fbf5f0f3e7d232ad5adb781cce1657bd5750193cfc0357ff55bd012a461531ecb61365908019c1e8074a4c322df2b356eea3f3eea9aa1e0e1fc5525e0000000000000000000000000000000002e166e475ff083faad64667b683e546b2358f945b8656f9c2f3f6e87a40dc3fc087dd94874bec1c4bd5929b7c96024a00000000000000000000000000000000022bb4ba4be638d8c14a16c94522c41cd3b3ad917daa454f820b8fa35e5a48c676266feece6986e8fe920b2a5e43e4b3569c1c1ae2d18bbe36ed50db1bf30957802b09a982fbed49d4968815552e010d0000000000000000000000000000000004947bd8ea8cc3b116fb7320c573fff0f107913c18cfdba2e7e9a4c8715e334a431156f384548508df8950d681163aee0000000000000000000000000000000001e9e7494c295248184503344b8ac7bfcff41a4561de03d78691ac47980f14aa47c1eaa3cca80103f0f2ba14a2842aea2061d33b2f7e786effbd2e93101a56ba1bb62c1a773a08b72ca82f5183bea35b0000000000000000000000000000000004789b01538cfc54cad0e99538e874d13eaa7f07199af29d460927c3e622c74e0bb4185afa12c53446f56033348c332f00000000000000000000000000000000154291a8bdefbc91445ef1fe123f326b8aad652c8c54502920d4dfa912c2f42d784fbc5a16d08468d2d6ee56e7e8eaa24129b150752d2d5551a622231ab067931678454aaeb23f76168219406f0d50ee00000000000000000000000000000000029048f227fe8d1b7247a82cfd3e1b4b60cdce6b52de42c4b96641bf8fc5ba9b077e33bd4c4fce9a51b63a6a2451b427000000000000000000000000000000000c83518e1b7700d68966d592cb2e3295a2db5226eb6fef972c8a84721d1e49a30e4a8ee3494ed4bbcd2a6877e1ba597d366c32d5d3c132f32a6ac3cfe1dabb649c59ae224338f747ad98b193e83467290000000000000000000000000000000003e96431aae4330d3d204093b7af21343ace4f1960de951eeaebea51e778b1fee43ecddc46667d096edbc5ff4735586400000000000000000000000000000000183a282f4b0513be661b1b38eb5f02b51aadc591745e0bd5d2d4e5545739e26470a9ec20d78ec284268d9c54c8e4f7b6d997516cac28a3968ac6946b5bffaace0856a52e38fdcca11ddfa16cf5a568f5000000000000000000000000000000000904c85edd36dfa18ddb4e1809607708142f3c0861570f2bc8fff14c462675661f2111c10a01557fb21f7f38957bdd840000000000000000000000000000000012a3a37f34ebb23d4c9268ec9e1d53aed4747aaace497695e6ea8fdbdedd58031cb479003e8bec0d14aa1d062fa30f2ce881ec65fdc2f58e46d3ee45a06d0c5ac844ee5b62872c7ba21f6b48621a337100000000000000000000000000000000148532bffbbf8bb1688f6448854214b4273b9d5adf132aa9142c1605d1882879678b6cc70638713b9438532d427f447c0000000000000000000000000000000010971ee30d83719e10e91aad3f1f201fe35ba1a057531b1905bca3a8391a3786cd077ee0f104305eafb3c94f4546da9edcd9b95e49473277a665ca0f9a8309df9ed6ee4f25d803aa967fb8f688273e65000000000000000000000000000000000f73574aa5a06ea569de88e48fcb96e822039af296684933c1b417dde95e08d2ac9c6ad4d525b0734e24807ee99ba88a000000000000000000000000000000000523deae09e75121a6d89b45161f69f0733a9e43d88d8527a03cca8cc126aeb7a680cfaf291554403723e20440b79437334582482a9038ab906880e43a4a9d39e73b6c63604eba0c8f6399eb5c288638", - "Expected": "000000000000000000000000000000000db91871e4cd84b3b58216b6c2e77a9521f3080182e78d3f66fe33f313013f06aec2dc5a6d483f35fadebde873bff9490000000000000000000000000000000003b9685de062b09b9e277ad5cd664d28af59064448af2b1b2b2357df6fc88e3ee7e0ac837100e0b7593944e8db43ab0f", - "Name": "matter_g1_multiexp_99", - "Gas": 64128, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsG2Add.json b/builder/core/vm/testdata/precompiles/blsG2Add.json deleted file mode 100644 index 64ca2006d..000000000 --- a/builder/core/vm/testdata/precompiles/blsG2Add.json +++ /dev/null @@ -1,730 +0,0 @@ -[ - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3", - "Name": "bls_g2add_(g2+g2=2*g2)", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf300000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e849", - "Expected": "000000000000000000000000000000000411a5de6730ffece671a9f21d65028cc0f1102378de124562cb1ff49db6f004fcd14d683024b0548eff3d1468df26880000000000000000000000000000000000fb837804dba8213329db46608b6c121d973363c1234a86dd183baff112709cf97096c5e9a1a770ee9d7dc641a894d60000000000000000000000000000000019b5e8f5d4a72f2b75811ac084a7f814317360bac52f6aab15eed416b4ef9938e0bdc4865cc2c4d0fd947e7c6925fd1400000000000000000000000000000000093567b4228be17ee62d11a254edd041ee4b953bffb8b8c7f925bd6662b4298bac2822b446f5b5de3b893e1be5aa4986", - "Name": "bls_g2add_(2*g2+3*g2=5*g2)", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "Name": "bls_g2add_(inf+g2=g2)", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g2add_(inf+inf=inf)", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2df0000000000000000000000000000000017c9fcf0504e62d3553b2f089b64574150aa5117bd3d2e89a8c1ed59bb7f70fb83215975ef31976e757abf60a75a1d9f0000000000000000000000000000000008f5a53d704298fe0cfc955e020442874fe87d5c729c7126abbdcbed355eef6c8f07277bee6d49d56c4ebaf334848624000000000000000000000000000000001302dcc50c6ce4c28086f8e1b43f9f65543cf598be440123816765ab6bc93f62bceda80045fbcad8598d4f32d03ee8fa000000000000000000000000000000000bbb4eb37628d60b035a3e0c45c0ea8c4abef5a6ddc5625e0560097ef9caab208221062e81cd77ef72162923a1906a40", - "Expected": "000000000000000000000000000000000a9b880c2c13da05bdeda62ea8f61e5fc2bf0b7aa5cc31eaf512bef7c5073d9e9927084b512e818dbf05eab697ba0661000000000000000000000000000000000b963b527aa3ec36813b108f2294115f732c878ac28551b5490615b436406773b5bb6a3f002be0e54db0bcebe40cb2e2000000000000000000000000000000000bd6e9060b42e36b57d88bc95b8b993da2d9d5acd95b73bad0509c2324212bcf7a94a46901932c0750535d00008a34f7000000000000000000000000000000000a374afd32bc3bb20c22a8864ce0dafe298bda17260b9d1d598a80830400c3fd4e8a8f677630eae5d4aa0a76a434e0ba", - "Name": "matter_g2_add_0", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d938800000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633", - "Expected": "000000000000000000000000000000001963e94d1501b6038de347037236c18a0a0c8cec677e48fc514e9fc9753a7d8dcf0acc4b3b64572cb571aebbe0b696640000000000000000000000000000000000d9739acc3a60f6dffb26f9b5f1fd114a21f2983deea192663c53e012b9f8e1cabd4942ad039badbd4745ddc0a26a91000000000000000000000000000000000b4206dcdb80d62195febb6773acab25fa2c09a2e4be9416ca019faeb72f1fad1dfdc51e8cea39b371a045b18947d40a00000000000000000000000000000000100758b888fa27e9258ddd5d83409e8aeac576874bc399b33b8bc50d77fce5358cb091d42f9a1b1ed09be3f200959989", - "Name": "matter_g2_add_1", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc000000000000000000000000000000000a69d6d9f79e19b38e6bf5a245dc820bddbdfe038d50932f76d0e4629d759f8ca6d573fcfc39256305daedf452f9fdf40000000000000000000000000000000015f5949369e58487afcecf8018775d1b0a73e913bf77e13d2e5a843bbbeba7d1978ca27ae8bfc87d30f567dd396b980e00000000000000000000000000000000182198bb38a0353b8db25389e56ab0d8679a1bda008a65dad77e4c95bc6804f6311eb16c761e1a5e2a5f87cfada49fa4000000000000000000000000000000000eb5483959e98c30e71db52615f63521378b156f142d46f3bb285b94aef39d80feacec335b797c5a68dc17ba89d43e0f", - "Expected": "00000000000000000000000000000000079e4fc2190d3441fa76c2d925d23b81e353e09e9138fdde51234195e564a32c98aa0d240f051298bf966d17adc2d6fb000000000000000000000000000000000aa327776fa7e15000dd548fcdc3a1cc6f9d0ab33046dd4240a3002962131b738ffed579945a348c795cfcb33682cf3b00000000000000000000000000000000179232ec56602d1ff79861cbfa2edece34b296541483aa65fe0cb493f520b7722cfffbe04294dd054770a38bf75d927b000000000000000000000000000000001826b88a6b411330757bb304a380487a02f7cf421115b84b3f468d11a83dbf304ce7a5661f4f01299d3c7865305a0006", - "Name": "matter_g2_add_2", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf49000000000000000000000000000000000286f09f931c07507ba4aafb7d43befe0b1d25b27ecc9199b19a9dc20bc7ec0329479ef224e00dece67ec0d61f1ca5ae0000000000000000000000000000000014e6ed154b5552be5c463b730b2134f83e0071dcdadfaa68e6c7c7f6e17dabb7daf06e409177bc4b38cfdb8248157618000000000000000000000000000000000f145e998dc6eb0c2b2be87db62949c7bfa63e8b01c8634248010fd623cfaec5d6c6c193331440957d333bf0c988b7b10000000000000000000000000000000002a1ab3eea343cfdea5779f64b3bddbf0769aded60e54a7507338f044310ba239430663394f110e560594d6042a99f1c", - "Expected": "000000000000000000000000000000000f69e3616e7122bf78230461bb1f4b194988adc6149372691d8794d0086fba0870a2255a2c79cc3426e7ba4d032fc2ab00000000000000000000000000000000174752301e05dcd62f7a3ae3357344e64d1c94835b2b742ac24449ee2728d693a0df10c3beaeb45d1b4af4ac2bdbb8b200000000000000000000000000000000051a761a3ceb275ec28a2a269b5ded1d9fd11a617c958e73c07de3a92ac480aa82c7d2a1852d291804e734526277f5740000000000000000000000000000000009bec9045ea89d5d16588e3373cc977f6d975d0e2213b171403a9b2ca460b3b2e1106b474185516d4200655b17a179a1", - "Name": "matter_g2_add_3", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e000000000000000000000000000000000d1007ca90451229d3780d66d3aed7c9d8fc82e9d45549e8586600e38eb6763f3c466e2f6ba6ba1dafd8f00cc452dda20000000000000000000000000000000001d017d920a262b6d6597bab532f83270f41526409510e80278d1c3595ceabb9ceba8ae32b1817297ff78ea7a0d252e8000000000000000000000000000000000935b7a59d2e51bbb2f9b54ccb06ebee9d189fa82f0e97d10c8020badb3de7fe15731b5895faed8cad92ae76e2e1b649000000000000000000000000000000000792dadd48a20040ad43facedc109747411895180813349d41d0e5b389176bfb15895d41665be8d1afa80835ef818eca", - "Expected": "000000000000000000000000000000000c079610e6f8770d65352f911863b6cb4fcb25cacc4a42f75e34e29e977c93244a6241cf3d5bd1040ce7d8987996f87e0000000000000000000000000000000010d08d8f6fa8ee7042c0891ea0c3b9b59a79da52cf3a91627c79d456212e3f6f39e1f69aa0053bbdb4076a3f7d05e5dc00000000000000000000000000000000069047218b0ac1e07650ac8f4a1b9235f68408f543517c4ae3c0ec47c79b468713c704ff3680edc8abd1bbed7a5fa75d00000000000000000000000000000000137737706162e02cfa75ce2154d57c9a3520818cc04626654824769ad92ff7977942f3881a28284ea47c14f353772d0b", - "Name": "matter_g2_add_4", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e200000000000000000000000000000000095353ad699b89ac82ca7ef631775b2b3a6e3ed8dd320440cdb929baa428e63cb902a83857cc0e2621470544c69e84aa000000000000000000000000000000000892559ade1060b0eef2cbc1c74de62a7ff076a3621e5f0f159672a549f1201f2ffb3ac12c8b12cb86ae3e386c33e219000000000000000000000000000000000750df4632a7126ddb08658a4001f949b9764d9cc43a9393cc55d8fdbb15d4a1186dd87a6433d111888a7804540ad9fc0000000000000000000000000000000017554bd444665df044b91b0b2614017bbfcd7acc7f8c5a16cea2861235578ce2b27dcced9fba234999fa478cd3f6e42d", - "Expected": "0000000000000000000000000000000004dd5dfe38fa70625216ecfec60ea8d38602552726f0fdfb8f392362ce845fe0fda76894d0e456796e08462bb941579f00000000000000000000000000000000195a85cd0685f4053ee539de7e04fccd2380819b291f89cbcd63d5a0015b3214500284a7c6568a71f52bbdbc38be410a00000000000000000000000000000000107c211bad49c7dd8555e30f2500c67e7175eb98a8494f3d5309c65a93cce89572b7b5489428eaf3f0a5c1be323c5352000000000000000000000000000000000c11f978150ac35722679cf79443b3706d288c968116ddedc1f1d0fca8cd746e3c92dc006330be14886c53c41feebbf9", - "Name": "matter_g2_add_5", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46e00000000000000000000000000000000175dadb6ee656ec6aebf8d0e5edaee3f119c74e0ea64e374be9e8ab9fd3d085fceeedf4ed8de676ebe9065d83b0542ad0000000000000000000000000000000005cd6a875329c23e4918976cf997e93e403957acfc999f8159a630d21ab6f1762925c063784237262bedc82402ad81bb0000000000000000000000000000000003274bcb8db35e50164d136c2a98b5a6d2fb5f9767d0ee11c1358bf7ca5ed96d9122f8c1051ba3c658cc89777d03dfa5000000000000000000000000000000000380a240443dff85b6542f75db28b87c39e278cdb8d9627efbbc63b229e6ce783f6fb0114c8e91c2fd6ea71c95bb99a4", - "Expected": "000000000000000000000000000000000fb33caed4de22cf341bb3e04d41c0198b064c1d371a24f5cf59595ab4a1edfd379916a40cc405d35f0603b2f8fb987400000000000000000000000000000000131ad6172c20b3a1cc2542db037de1324086fd9cd140ae97987980f260023d91b24504181af6fcbcfa242f48e99559320000000000000000000000000000000004a0404c00789459395f5344544041785d10f2fe74d4bf484966f5e9b6b4c4c8cb113a811a4fa82a1cdf8e3242bb418900000000000000000000000000000000086ba6a914f3f07bdc6750fcf6baf76124a17964bf9eb9a12982e8a28ca04360da3544b69436d5663e4e94bf7189529b", - "Name": "matter_g2_add_6", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12000000000000000000000000000000000834cf1b4149d100c41b1bca0495e455002eb6596bddcb94ae48d0c65957e8b313372f8e0d6e57504664b266f38293150000000000000000000000000000000000de2875fbd14760bac4c2cc7d3f239177efe9f7f61f767be420d44f24c9fb863efd60dcd732986db8c5b72470617ea60000000000000000000000000000000000bc9535ebf11c2dcc8c7d3bcd09d7d14035635fccb5fddb7df29ce8855e79f99809781d6ffbbcb33d1227314609abee00000000000000000000000000000000039bbfb4d969d702255e3be7f255a97529a19687ce38cb70637c37894d4102591feef428b0afe8c9ef50310ae3b83091", - "Expected": "0000000000000000000000000000000019c8a1a206c0006a3033377abba4c31c55710a094d8c9dcef7560818e90411861ce7d189e2763f8fe69bf75e719e4efe000000000000000000000000000000000cccc6bba8691c210aa0a67d26584a359fab94041d853160abd9669893c0d398c805cc37fa3c33bc5ee5ff915b985c45000000000000000000000000000000000e353c1993c36763acec2a75495560e743d099b565f3de195e011afcacff3d60502801f47695da7dd589af81e772eb7800000000000000000000000000000000100c6123cf08eab6c59d78b414fa504ed10c204851289b0598b40ac31971fa12cfda4ef7cd2d64f9797d4d2b193e0bd2", - "Name": "matter_g2_add_7", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5b000000000000000000000000000000000fc09c241899fa6e8cc3b31830e9c9f2777d2bc6758260c9f6af5fce56c9dc1a8daedb5bcb7d7669005ccf6bfacf71050000000000000000000000000000000018e95921a76bc37308e2f10afb36a812b622afe19c8db84465ab8b3293c7d371948ee0578dbb025eed7ed60686109aa0000000000000000000000000000000001558cdfbac6ea2c4c1f4b9a2e809b19e9f4ba47b78d2b18185ed8c97c2f9c2990beadc78b85c123b4c3c08d5c5b3bbef000000000000000000000000000000000ea4dfdd12b9a4b9a3172671a6eafed7508af296813ec5700b697d9239ae484bcf7ab630e5b6830d6d95675be5174bb2", - "Expected": "0000000000000000000000000000000009fc3870f88288c680b43d63d3bb5305b99fe461e59c07be981b8819fbee0d1fdfae0c037e830fbbabc40cedac7919720000000000000000000000000000000018bdd4903da4d14fa28af4c2cddcb708238cf68673ce77a04a3926c4aaf17d39a831c5401e84dd042d6adf595a1763710000000000000000000000000000000002c398f0e8ad9752f4aded980bc5de2d91118db06818d815c11e818ead47e7065823737db8e304bae32969cab065d1ff00000000000000000000000000000000180642a633c3aa402e5c0b18fcb6fe8c115575b863abda59b5d91997ab01014faefc975d0aee994f98cf37ce79eb95aa", - "Name": "matter_g2_add_8", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb815960000000000000000000000000000000000b36d8fb9bd156f618ab8049d41dfe0698218764c0abb10e12fae43c8810b8e2a5201364e2778f6f433b199bb8f9a6800000000000000000000000000000000000707eb15411b63722b4308c0ed4288320078d2463ae659ad4fb3f9ef8124f379df92d64e077403e50727388adb59ac00000000000000000000000000000000158e1249d5b91614924acb23899c6bae408697dec0982c10d0459746499f4e6739afb9d5129568106ed1a1caefeaa9640000000000000000000000000000000019e841562e4aa75321143f8ce1e5ec6158fa5cb8b98c839a486188260c18ee8a7600930f23aa39eac2eb520d6a0fba90", - "Expected": "00000000000000000000000000000000199600699a6108599c638df8f965d73b5de4ca74598df281ec95c539de2c7eff9767569692d8e0ad120fcbb3d9335b95000000000000000000000000000000000c42b11e2585ba93521b3c968e9dee07e4f5168c11087d8d750795555a105df70c969bfa79b1ab4e5fc8d81657235d08000000000000000000000000000000001370daa4699daa99e9940fe04f69150e6f752798cbc0e66c91c3bd46149d935c1815f32d7f14b510e16d475044eda9cc0000000000000000000000000000000016c7a00be10de5732795cc3ee2951e58cb9d42f9b05d02fbff1b83fab5d3ad830cb8178092b76172108d7a53afe8c539", - "Name": "matter_g2_add_9", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e97795505419600000000000000000000000000000000186a9661d6fb539e8687ac214301b2d7623caedd76f4055089befba6ef2c96263d810921ad7783d229f82783c9def424000000000000000000000000000000000447f3e20caa1f99fbaccab7bde2bd37fe77cea691ebf2b9499f95bbbb77afe72b7039eb0c05970b61360fcf8ade73730000000000000000000000000000000005e11f828eda86c10a1d7929def547ac06885da278afae59c5d95453caf0a2d8ed186fa7c6d0a7ab6e9142cfa4b338190000000000000000000000000000000003d954e61b6ab71042b19e804efccd4956b56662f27f70a9255cec0c464b86c0e83721ad3785dec62dd4a9dd3d6d5d53", - "Expected": "000000000000000000000000000000000669cc8a3acae17f99f805afb9012a38851a9e8d4fd9895a9946c29fc859849c24d7ab7b6278c449cfbc5f1d7ea1fdbd0000000000000000000000000000000007a9095be808d0ebc99bce94e851d2a7cd3e1977b923064ab5bbed2347cf18f3343e60120fa051d12fe27da3146cb423000000000000000000000000000000000f1e7f75887651f67457f6dc064d7c11934035d15fe4dc40bab970160ed1b1aa230a3fb84dc1da08770d847c0216347a000000000000000000000000000000000efbc62ade1678cd70eb38c644038bf19e52b0859f65747068d9f3124762d951e4a6ff05f34b6d14919774f8409adff5", - "Name": "matter_g2_add_10", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a90000000000000000000000000000000002b94534aa0ba923bda34cbe92b3cd7a3e263741b120240ff5bdb8b718f094d3867e3fcabeab4a7be39c8f8c4fdd10d900000000000000000000000000000000048711cf6a82534d64d072355cb8fe647808e7e8b2d9ac9ed52eb7fe121647a721dd1234c71ecd163d91701eb7331cac00000000000000000000000000000000141ef2e23a1ecc7ef2ed3ea915492e79cfffe60b5e0de8441e878bd0653843d79c724e3c5ebe2321361df99f8932ddc200000000000000000000000000000000085513b4009f29b3e00a91c2c4be418368560802ba4194cbd2f4fa3d72a55fcae547014434514a8b2a8fe3e0b28d2773", - "Expected": "000000000000000000000000000000000e25a38d0ce2aabd2538c95ed463f226e3f29ce7f10e1be27af2d3db741926d557178c4b125af8789b40480d8beec0890000000000000000000000000000000002a94b7c57fe2783d055a537004a3b67e41f5374da0813094f5944fbabf4d27eb576dc8b21ccc15f8339df14ff8785220000000000000000000000000000000008b9efd8abfa4fd71a8eafdba9df38360ef0b0a117c0052528d1c24df5032635eebc7b201439f5de858514666c68cd270000000000000000000000000000000012a2fde51f6f4a98435c325dc3b1ae846bc33a5ffb3b13fbe3fde2f74dec0aa815fa8e42392b3dbf798cf547fdb4db0d", - "Name": "matter_g2_add_11", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b381731734598360000000000000000000000000000000009143507a24313ee33401955fc46562c9b20c9917df3b40ccbd7ed43b1349d4551cfd98a4976d6fec5fc289460c8d89900000000000000000000000000000000060566b79df5cc975e669da8ca3a7fa91bf3f5c9fb871c3d62f4a3e79dbc341b89d38b588e5414bc385d5e3cbf3ab9310000000000000000000000000000000016bf40b8cc4c01a87aafae0c4439b623a51ba9a383756a550b69d627d6f45209f0d87e4f9be9edff35c986f7b9c49e3f000000000000000000000000000000001842d9172bce51a164fbdbdb108d0faae07e4642f21c80e40ac31e737657472ae3dfe552b65349629c210a068c4afc0e", - "Expected": "00000000000000000000000000000000067265782d58b04a2ef3dd419cee506e076e49d1119e28db1df7f0e22cba9bbdabc560084cda50bc8db3915fa9c489a30000000000000000000000000000000012448a61fb2f6fd8e355111b671f0e888304284b72d5688091f2ed00edf7ccb7e5bd8a733a910d6964dde07d393798470000000000000000000000000000000005f687356ff6c634eb46613be8e98540107e706714434faff54510234d4aff42ef7752e154aed63fa8ff905ec0af628f00000000000000000000000000000000180dca84a37c964b30f5cd11a090e54acea102f1b884319f8d1252a37bda005512ffc39dec8e33af0dde0d37993f846f", - "Name": "matter_g2_add_12", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b000000000000000000000000000000000ab19bbddd661e9db8fe4cb307ecebdc5e03efbb95c5b44716c7075bd60efcfc67de0bfd7c46ad989a613946c90a4c1000000000000000000000000000000000120800e7f344cda816299fa37f603ade06beb3b10907f5af896d6b4e42f7f865b756f14164db84411c56cb2ea81f60be000000000000000000000000000000000f688ddd257e66362af1437b6922d3397a7c3dd6dea6bca8ebd6375e75bf2de40bc287cbf3434388191e56b92949c83b0000000000000000000000000000000005252465784aff8c1c707da58b5808c69583bf852d68f96912bc53f8dae4536b09ccbbd25a49d9e744118992b92b6792", - "Expected": "0000000000000000000000000000000012a29d35c9af52f172787c90c5a3e77ed29d66feabf5d7bdd6bfc14dd9a05d402976b84d44647628c908d1816f4e7100000000000000000000000000000000000caf3c372e36de557ecd7eba02e6a79b1b4cff30343119df7a23662c8512095e051ae2dc27e577635c74a260be2b084c0000000000000000000000000000000002ceca293a58bc9beb4ee9a0679eab037f5cf7b326d65c0efeefdbf384ad8e4bc08a3a75a02e6b9cba8963e65d6e76ef0000000000000000000000000000000004631773a6590bc89b49a75bbbe2e732f9466ba259ef7a04ae69b6aa5d5a2621c1918eb213101f6f7eeee4656a7b1472", - "Name": "matter_g2_add_13", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd3000000000000000000000000000000000e3165efe00f69aee84ac56d2161f07c017abfaadeaad34f8c96799d68bae0e6f9b557bbf9137e7826f49f29c58d1ef9000000000000000000000000000000000de0dce7ea371ad60f21f2cb61cb582b5072408a7efc91edf05b36a1a3b58fd9e6cf808d75157eedccc8f1c93a8ae07d0000000000000000000000000000000016d911943d80427385ebac1d1b293914a9e4dd9db06c1d6a758192d63c8fc9368e02eae7fb0e3a7859408f215cfa76ca0000000000000000000000000000000007bfdc6afb8acec625e50ecbc08a5cdb7862b795866323679885ba5cba3fd51f181078e03fe35e96e6383c077eed1bf5", - "Expected": "0000000000000000000000000000000017f155ed9911ec56d71d63d57556de071ebe89be36e6bc9943ec068a70dd5a6f045dfb9fde5c1e29d52c9fc17579452e000000000000000000000000000000000a60d62ea549edf4b11f62f2321f39d41bf11f3c4f858dc7db85b1dab1b7644e27eeb1d022d6082f59c65155068d2c390000000000000000000000000000000009d309145fad15860e556ec4b4aecb415865954247c2034d5bc96026e4d6f7612af6e2db99f4e462acee2b303134b91b000000000000000000000000000000000114ed157e3d020c5397cba7e10cb864aabb47461f166a6724614e689274ae74c505fb6ebfe3e88da0d6c272a15a0527", - "Name": "matter_g2_add_14", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bd000000000000000000000000000000000a68dccbe3452731f075580fe6102b8ee5265007ee19c56d95bcb096a3a6ac444f4145b980f41afcb0a865853b279bc600000000000000000000000000000000164767ea55a9038ac2dd254d8c8a4970dba93dacdf5416aecaa407914719cab165e7a32784b2c41652a86358737d831f000000000000000000000000000000000da9441fbc6578c85fdeca49082c9ebbf183de894d67c65158380ee56132d3cdb44b100d72b6d3b82688defb75d2aa390000000000000000000000000000000017d570e4f6e46550679d5d12c347414da207060f594620e2f8db66df8e0b06c912290b207a268e782d4b45db19a199db", - "Expected": "00000000000000000000000000000000118e0c81f9157395578f0fb83b179721de2af3326d13189cb8f43911d8c3268a11fd9702f09f14c115bbdc43d5fbc08b0000000000000000000000000000000016a548df8c87f432c31e4e32c3e5b4d48d6f29fbe391d1181174be9dddee450e7e96bffe8c9f23692ccc080116592944000000000000000000000000000000000eef72a5c698c58f1d2ae9415da256b54d7b1ac37a1d1b88727c0afcfd854a41973c6cb10ecbc3a90050fe3d8d3ce8780000000000000000000000000000000019b16ca8f955dfd21830a3f7fafcc97d7de977bafe1983892988aaedd430d22674d97897d24c1643e99bfa6256df4bf7", - "Name": "matter_g2_add_15", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca800000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e", - "Expected": "000000000000000000000000000000000f2bf3f69276d390c9fc2c15e9f5f5d0b3cf9a6eb028c44811b481f376ab60e17d33a04b78348e46eaa94332c5f16ff8000000000000000000000000000000000bedd0437fb3f4baef87e56f33c77fcdff6a5512571cf11fd9605697abd8763315f1fe4bccf04acc6e971d6aeefd9c1500000000000000000000000000000000067c3ff69733baae2fb4ab77cddb7563047c428b40a257a375f8cf8c9d230a6619f7932b86e0836fff0c1c60d2c4dfd900000000000000000000000000000000057526faed8d62aa10e89add5a338320c748ca1f96ba5ceb579efec69d17475571fc4ce6fce3a93398ea88340f0e969d", - "Name": "matter_g2_add_16", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91be0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f9", - "Expected": "0000000000000000000000000000000004fc19f8fe47e6acd37567016704b07f906e8741fcb196f697e1fc24b0204292693ff424bf1c5e407f5bcba5a3b1ab85000000000000000000000000000000001816f992c3c461fa6d2014ced382a35b0d70e61927d72b4d661434efff3dafe2f4b6cc91bb1a5dbf809f10f3ed7f36de000000000000000000000000000000000dadf7f7223ccedbeffef31c97df7e01f99299da71b589c8828b65715012aa343d7e041dacc57b34a6b5f84523a7938100000000000000000000000000000000167f7e73e22df81bd2a7a6f14e940a401bf414e5d18b3aa610b2a82ca8f46aecb5721d0092b27f8968b2302c37957268", - "Name": "matter_g2_add_17", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae7", - "Expected": "00000000000000000000000000000000041a5783c748247f05457d30d16f93431e9046a236d5025cc07a27b9f2abaaa556e2df65cf0f0015107253fe94d8b4dd000000000000000000000000000000000193638bf69c7508c4b12808a62e89883c34f97ded6e1b5dcc3f28191e5c7fd901a72a85ae386acccc9865f8144b1bd500000000000000000000000000000000180e8184ab583da58b77b8a4d108a366dff3e3b336ebc5c9153fa815188edc95e7067ef25f7d79526c295d634bc98f5100000000000000000000000000000000125b147100f6df0cede8e22151b3423b1dd364899fdee103c71a44388ff002a367627a2342e15833644bcde61f2ef6b6", - "Name": "matter_g2_add_18", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a7915780", - "Expected": "00000000000000000000000000000000095fda8adf3981f4468fb82aa0ccf80e55138c922c6422cd8e67f53ee63e7a390bc345469e9211a1f8d810cf4ba27d0a0000000000000000000000000000000015c19b6af21f75e8e53fcefbae1c8d7f97853a8aae5fa62e606cfc92ae71890702ef9dc5609d3ca8fefd415fbd820c04000000000000000000000000000000000007b7e908766d34c5d99cb7cc76d5d5ea83c29ae1d9b83b163741bc9962e293926b1e251b546ce0c1268def728da78100000000000000000000000000000000084fbd6253211f7d66d52b7f14360729d54b2f94c52f2b76e521dc3961c40b4f19944923f64c6425a44eb158a9727a4f", - "Name": "matter_g2_add_19", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e170000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e", - "Expected": "00000000000000000000000000000000121e7f2eb906d0b31b8ce5cc46638428b6ee57a1ee70e4ec3c2bc044230b9b86875abe0862145b442c0e34308efc690f00000000000000000000000000000000139120d0a10b82737561d0b3fda01b6df69d9beb7dbabf3ddda036f9b4c317f3ac1eaf400013fe5ad664bea44a73b336000000000000000000000000000000000a923184b381027d8cb3f82708802b204566b2b8bb6a72767aa396324d8a26b4e0f0cb92fd1914d77a4e9af2f1ec31e3000000000000000000000000000000000409732f2225cb5e5c002bef17512519eb1a18bf6c3d7f834d0c7ac8a38433c88b550b3f443d259313eb1133620ebf0c", - "Name": "matter_g2_add_20", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b710000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd67", - "Expected": "0000000000000000000000000000000006a200642d5cece5eaacacb36000b4b897e8d8c661c8282f90495002aa515c7638183cf1e80a0b35e953adb92b6bb845000000000000000000000000000000000e88d4cda34e98df4d727fda79b67961b5b8efb1b125ef2a8eafc481a2cb2fa1530e59a091f31c25cc49d38f545491ff00000000000000000000000000000000082f38c1a1c35981f537547dc3b59331ab8c5e8dd261df58fe6f0c44ef1e65d0cdc1980e1a62f6248f38d0afe91e5627000000000000000000000000000000000eda1002e202e9ee4df5354cb87760d4df32eba1eafdad27cb0636879370a8f93be0bf2a30f15f2fbcd7e52c1bdf6b05", - "Name": "matter_g2_add_21", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4", - "Expected": "000000000000000000000000000000001341cf3316152ae8d57ea2194224f04756690133d2e02d077dc271aa577278e346e0ff66e8a49ff8c983fd34546e1f6f0000000000000000000000000000000016c9093da650643f4b4061e1c6e55da6ebaf9f234bef8325aeecad3863a0a2f53e1cdb2d54aa8b075ce6e6632fb4cd660000000000000000000000000000000011eaf3dee010bf2a16c5fbb1f7aa559cd4d831f087d9dfad4e157a6d2b6495e370d9791cbaaae19339a65726ebfc3b910000000000000000000000000000000008476d793305204be414819fce2ca70754a532682876277bc0586514f2096ba9998ae848c722ead6722d5af9395ff77f", - "Name": "matter_g2_add_22", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa097000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa", - "Expected": "0000000000000000000000000000000009792d98ab9b90c2467ad0d070ea44f382ec7ad5290a59d889313c5a55d7b8e837333ad7ecfd97221d405cd6c549dc8e0000000000000000000000000000000002b92dd07b61faec23f48b8a7893dae29509fefd688a978bc2e870d4cd6f963d708a0611b4aa65f5644fbc6ba4c5e66b0000000000000000000000000000000011e46a283946a8e033afbf7c14ce3162a05867809d7de94a090c8cc2cdca8bb79add21f6e2fa8d7f39ea6d26cd37ea850000000000000000000000000000000000fddb7cdf1f1126e7a6780e4892601121b289a386ebce0caf96cd392ddc57c47e3f9284889fd8a18fb330d6c40bdf67", - "Name": "matter_g2_add_23", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e", - "Expected": "00000000000000000000000000000000054dedc002c5f2da8c6e0a0146bfe5c83200b276b074e6d6f2c397e1208f152d3ea3e8f0da7da62cfd2a028d4c94fe5b0000000000000000000000000000000012ff307f86e266e7a212484a169d3e81df98217c6f715176913b0d383cbe4e790212da7feca0cea66df09d92544fae010000000000000000000000000000000009c211438dcf8ccb664b535e73eff304b92aa2f568aeaeb8e10ec142f92b211bb8147b250dad77d508cfe353667b6f150000000000000000000000000000000009d1734f4ecc88fd56f412f9243c387b9da659faa3fe7295580a6b7519b1980bd074339fa9b0bef44dcdd0cf0c4a629b", - "Name": "matter_g2_add_24", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac900000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f", - "Expected": "000000000000000000000000000000000896a38ce734c550c178786092292e737d44fa5f503d6d3b66c75e6bb70b59d1db9e8baa1ea3e256e2dfd8a942311e75000000000000000000000000000000001231db96a35229a4c7507b0ec193491446a0b43115c27d18b3715fcd4aea14d4e5c99db5934e73bb0b86f1bb91ee96fa0000000000000000000000000000000000d6f95d5637b29ea889c028dacdcb484d8ccdb243da4d5ff49e5ad82f234d414dc1484e9ed6cba1b5940eaabd3066860000000000000000000000000000000007de052fbb76902e06e1783fa8afcbb54a5069b4c5e9cee78d43da2cf76f24843a740a9eec6fe9b8f9bc4ac9baea77a5", - "Name": "matter_g2_add_25", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b8592390800000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f", - "Expected": "00000000000000000000000000000000156914a9137e52abd4579599dea4c0f857eed0457ee1d80635d3a6ccf0c766ba8ab1b6f989711fbdf125c4ff06b597ea000000000000000000000000000000000c60184e8ab32019ce20d2d137130f657c8964406fe4abb26da232c9c5dbfab243837d700c88d6b9ea4b8f0a2f514281000000000000000000000000000000000dc3e6e3acb898552791431859943d0a83fb4ccd62e4ab2a971370a93a99a9dfcdbe4c42535aa063354e0f2cd48308c300000000000000000000000000000000025be02da875d4990d1f0be626ce634c4856ea91f88f636bc27e313e73897c9c13a1e3ae70c1227dfd4fba97f521d6af", - "Name": "matter_g2_add_26", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a300000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352", - "Expected": "0000000000000000000000000000000010124c1c1c10868b570d2969ebc3bf5cd6bfab13ddc93f0fd2b8a1742eb8e04d31063bb81c52b92e253128d4cb4413a60000000000000000000000000000000013f89997cd2ddae00cbf24cb66a92146c553c6fae41cdfaef14d49078729f239ad2661937dd0d4d6ffd7076b03e0aa84000000000000000000000000000000000ba2ecf990cd846c95b35ab60d4f97f5814c8189190df9d521b3dae462f2d44db006a0daecf6b82c1459006bf82ef7c90000000000000000000000000000000016dc129b83cca5b3c699628d081306c5fa61faf9dda5e92894931714037628fb829c595bf64d4a7fa295f136ae244601", - "Name": "matter_g2_add_27", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e055086016000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a6", - "Expected": "000000000000000000000000000000000a66f36f2437db57473bd8b7670994f1cfeb8b43c0ceae358e63a5e4e52b737fce6b3d24cc4de593bcd44c63f2c5935900000000000000000000000000000000070b7ad970f03a38c8a31452cf11422159cd3331d746031781a5861e26f54efbaba63dcb1db8bab997eada9c3dac39cc000000000000000000000000000000000ba4a9d7350adca1ae64e722df11baeea77c5fb75c5b52c8c46b9d863a70bfed1ec47888e907213f4ed4dcaedd37f20f0000000000000000000000000000000008a64244f1870a1dbcc4bd4d5c9eb5cd5225713dc73aa22bc46b1cea36c88a66f85251a8a9ba7279c88bd5dd37a06f7b", - "Name": "matter_g2_add_28", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3ff000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b59294703", - "Expected": "00000000000000000000000000000000079f89f2defd1f97efe0ba1db28523abc88cdf66efd39918a600a07c5ed5b72ab9d3354a172735e7749b5f6814a48f4f0000000000000000000000000000000009e361b8609be8057e5b3c99eaa1727fdac17edc59239af17f55d72c8b8daa89726f4ae240c742ec4b02fbd89d45c46400000000000000000000000000000000121b475a2ab50357ce80fe01fc461195029de20f61474b0773d80434253adfc268a775e1a0e3b7df5e85d1ff8c5008960000000000000000000000000000000019a76aef4e04136b1ad0d03586a3d8608ac4573715f18d5fd6907d03e5fec7c5659e15c19fd87f242da972b651dff5fa", - "Name": "matter_g2_add_29", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b200000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb", - "Expected": "000000000000000000000000000000000383ab7a17cc57e239e874af3f1aaabba0e64625b848676712f05f56132dbbd1cadfabeb3fe1f461daba3f1720057ddd00000000000000000000000000000000096967e9b3747f1b8e344535eaa0c51e70bc77412bfaa2a7ce76f11f570c9febb8f4227316866a416a50436d098e6f9a000000000000000000000000000000001079452b7519a7b090d668d54c266335b1cdd1080ed867dd17a2476b11c2617da829bf740e51cb7dfd60d73ed02c0c6700000000000000000000000000000000015fc3a972e05cbd9014882cfe6f2f16d0291c403bf28b05056ac625e4f71dfb1295c85d73145ef554614e6eb2d5bf02", - "Name": "matter_g2_add_30", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c053345501324233", - "Expected": "0000000000000000000000000000000013f8cdab447ef9be450b87f941c96d4e93d5efd811d80c6a910965728f7dc496dec132f3fbeee5d1e84ed7c24ca9c2a8000000000000000000000000000000001537d5caa13ddfac93f0f86729c743d9a68175a78c730528b581fb54b1f4d020473b3b766e3882a485ce5d02ab381c33000000000000000000000000000000000b370903684ede24f3df80e3834ed414a765cdbad98f20c49bef8663a82a468d3911d6bbcdc021e22c252e83a857e55800000000000000000000000000000000100cc8d05f071904753776c6092a38db84c5de751bf93216131a0f9a50bf78a722344a14b3be2a9207568d1f669d208d", - "Name": "matter_g2_add_31", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f860000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce", - "Expected": "0000000000000000000000000000000003c5498b8c2d4765a270254dc927c6edf02acf0759540ddad951ea8c097bddb949ea0bf19942accd615bef21e8572dff0000000000000000000000000000000004c17bb648909bdddab4dd86560cb6b341e96f58c515ce471281f226181bded16b358b56d72e363f9ec491b8a9dcd92c000000000000000000000000000000001828973958204f8ab8cd13f5af5f3529f368a149bfe931a8002b61a61895457fbcb0cc6874631bb55799c884b998d8b9000000000000000000000000000000000f61460bf61bbf3ce38917850bfd3cece1e3955ce29d200c6f8aa89076c70919c02668678edc0bcf94efc9e9ff6a650e", - "Name": "matter_g2_add_32", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac5", - "Expected": "0000000000000000000000000000000002c6104b3494fdef86d53f87bea68d313188c0908b935fb3b9f636ccd401c6e9cbd33bfcdd437e1a0150d0e4b9c3a881000000000000000000000000000000000bdc88396f807d1ba8d4d6e284d008b5e40445ce32c23a0178824fdbb6db3c5aede7687eaa2f12249125cded57052ad2000000000000000000000000000000000c7004365c1d3027997b55bd258dfc61ae07a762666fba2a14aa2ca116673fc03a6f694c069f53cd915fef6d37513101000000000000000000000000000000000ec17688d8f53e2c92502091c859cef4fe9a57ae984cb1e72686bf1f0656b10246293cae4b96214a38dc76cf2709bd59", - "Name": "matter_g2_add_33", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c99739", - "Expected": "000000000000000000000000000000000a44e6a48ea0a95667f607ee66290cb0094c964baed779bd6656941db28e30a7e9effe49a617be9ab376af4f535cc28f000000000000000000000000000000001933b87310bf5fa60b1abcd13bb7ac3f2ec0a278f6a0a70c953a2905ac1d3bc5a70cf1da885af45d1c7680bb4f7ff74c000000000000000000000000000000000597ce9f1bf7efacdcb0250427d0341e142226aaea060983175ea149912c5c4f3019fe87be6d87d186a8f562fc3059eb00000000000000000000000000000000198b5a891722a237a5e23e3004798c8d3f069af3267152508e283b4549fc5e8388330343f80e606eba30af51c99c7020", - "Name": "matter_g2_add_34", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe20000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0", - "Expected": "00000000000000000000000000000000047c2ccda315b9c013e87bc9168b3b8dd6d463403f1cefd824fa9f93a99f4c4f98fac5f97e4237f76b1ec91042f99bd600000000000000000000000000000000036861fd0a69cbc851741475905441b51af12c5b2aaee6ce9a27a01a43db810be9c7d6fa401406e98e327703404b83a5000000000000000000000000000000000310cbdf53f6cf8d87e2d178869bee4359a8dd666986d869761a79963680a33ea3ecefd40a1e558acae5ded2ca04447300000000000000000000000000000000108bbb28c73ed7e76a51a78e4d15a2c88c25e05c7127ae89d4347cda00be231b5e70e0b0562caddd4a7083efa4516722", - "Name": "matter_g2_add_35", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a84486000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c", - "Expected": "00000000000000000000000000000000137d23ed3fa0d7e5928af8d1f4bdfdef08e0b4c0f3bf6f51ed28960ce9805eb8fb254233bb18cbfecbadba95e112fdb80000000000000000000000000000000018615147d7a8cce1dfed6de25cf2fb52f54a243bed4913e20e66673f47ecddad9c5e4ff9653f522180de4b90ddb3ad17000000000000000000000000000000001521f12116b13f785b5211aaf438aa6668bbfa318cf0ed6d91aae963f6f00d32cc5f25d3a02bd902ccc25f847ee2db830000000000000000000000000000000014263b23396f4facdacf13c79864157823db724350bc640abf8fb6d62663cec1069eef9db56817660510e2417b51c616", - "Name": "matter_g2_add_36", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e370000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d05712", - "Expected": "000000000000000000000000000000000038f9df6c14f84b8ef8045010c8973e5c2f8d2e37268f6a674298de7b15cae82361ebbfaa00ea1cb2653c5d00886b45000000000000000000000000000000001376f7e2d5621aa9d6f7ce45ed11de7e0e1095ebeea976f78eb83189c6852ee199840c14059c233bc3d40efbeeb5eb36000000000000000000000000000000000c7b0e53adf4f0fc5172f903e3fc479539348241edc3e277f30ae6b4fc419aadcfb73a8f8a09a1ae1dd885a6250de0040000000000000000000000000000000007a00b57ecc8b056436ecacd7e0fd346b906b15042e9a700f54f8c3b1d251c566e0c55bd34f7a9e30f1566b7f2ab16dd", - "Name": "matter_g2_add_37", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4", - "Expected": "0000000000000000000000000000000012662e19e41bfacc0c792f5183596bc7f1986f9bea72c626e187d72111b6ef3f36f5afeeb640cfda99b7044c0d0b846900000000000000000000000000000000050ba08e1b9fe95dc67e6ee1ce60664b291c80fdb59729cdea75dfd18f22fb88f837b439fd119c46c996787d3008194b0000000000000000000000000000000004ea0f488fece967675abdd3c42f8fec25b547cfc45d42fba14bbc55ad7e1a75296a679113d0671cef0aec0c2165f4a0000000000000000000000000000000000f617f51800b09150a7560505079c785ab45cea4705992fc0325edaf4ceb30e1f0bec35a31898db5f810685e55634076", - "Name": "matter_g2_add_38", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb300000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc", - "Expected": "0000000000000000000000000000000019c774e968049bde2188e844c3413203bfe2c4355edc8cbc2cf6f977c34c0a42a206194e6eecba3c97b24558048f3aa700000000000000000000000000000000081ccf6f111575a946341759b9faa13f3608998fbf4ea3b547804737e30fc7e33495caaf2aa328b19bd48315c5c7f9e2000000000000000000000000000000000a4098536041cfb808176c7cd8e980eda613a2b390e8d63d607caaac26db02fccad6d87412b90cb4b3e186bf9ccd31be000000000000000000000000000000000d3c784c6587b9f786c06099a62aa639f40535b512ac2440912f04dfcd1cb5851b7378f381fcdf02d4e58312eb7e442f", - "Name": "matter_g2_add_39", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05500000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6", - "Expected": "0000000000000000000000000000000016fc7c743c5ba747640a6494fb3c30caad5a1e9719a1994d0ca73bd1645fec118a2887acc8876d105102241c10274cd300000000000000000000000000000000058a42a0095a7388fba7ce71dbef4ecfd2018c3fcdde14afd2be26588de4689d8de757e1e3ff22645fb8c17aa60265850000000000000000000000000000000010bb622f649e346834b95e82f93ae83c71c0a65df7842c4ba88df7f6eccb0217ca9377167a6d14777e0474c24821f8d70000000000000000000000000000000010c180c685ea3d0146eb82c007fec3efd129880f18f838f1cd2f80181f5a4884d6b5cc8247430fb0c1701a57f9d1d485", - "Name": "matter_g2_add_40", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d03", - "Expected": "0000000000000000000000000000000019419b635c3742cecffee02ee7e2b1f18ee9ff15e647ca0abc4398ddc421ae7e0444e3c1ec377def9e832d8e64fd40e2000000000000000000000000000000000d9b4abfdaf3b4c7bf00fa07579befa10a3418d8fa0f3a9c31e59ae48b0de50fc8e6d583aaa4d0fe6048bdd1a9c60eb60000000000000000000000000000000003c96d57034ec97c4abef1c2c81f4d4b0f4b6eb1e9dc5464bcab28572555b9b874df80325941501c3766fd7e06bfe7360000000000000000000000000000000002dbb3d72385b562ddcb9a80400ab3770f00d22b880cce2fce1641042b9da669b22b2fbc97617648c25ab644e661e2fe", - "Name": "matter_g2_add_41", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbc00000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d", - "Expected": "000000000000000000000000000000000d32b00154a5fe75c576c098419744ac36b911ee800f94bd598ff9b6adcaa39c836bc158c5d6af72c9e715a242d0fe710000000000000000000000000000000006e057c13885d6c05f5d92061fdc4d532f10d31d472c371e71367fef7c5fdd3741e665321d1119b895660fba3770431b000000000000000000000000000000000bfe695c3364e15479741e974f838649e789a76d073e552aaa60981fbc6d185eb7b297fd59e51535965214a02f5cd67e0000000000000000000000000000000014f0a27412248e3163e5f82fed02a25d953b336b0201692f08a3e8e9a9d223b736c70c1a39826a0888fb02a314e223fd", - "Name": "matter_g2_add_42", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6ea0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47", - "Expected": "000000000000000000000000000000001566022247ce012b7de92c8495876b4de91c36448f4f7e00f6e154185d38a735e701dda989ae9e37d332a5e60af5d06b00000000000000000000000000000000065aa42560df7990df2098827a55ceaabf3ec592c53d2f20e5dddc1481ee64381accbc8e58601428d33589b3af78a4b70000000000000000000000000000000002d9b0cf8bfd1adf76bca80ca351a4340f02434090518807e07ed76440497042f13a0cd7a9c30086872d6f145808fb290000000000000000000000000000000015daaa131431e3e78a6221091640811fcf88c835ac975a041a7ab50bc1d06b80e6a3c9ae77d2390fd14cc9bb009b47cc", - "Name": "matter_g2_add_43", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710be000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf", - "Expected": "000000000000000000000000000000001290bff629c93d992ad2cc709317c48980b0e56a32fe239258c7aec75e4523e0bc0b81319e100d10568a44847869a8d000000000000000000000000000000000055d9098e08eabdf2b883df35efebec9f6afb16d651ebaca1067e2129146268664ec51c8a4f28f13a250f3e9883053780000000000000000000000000000000002424dab6f0d18ea8bdded2a72bcf87c13307d27d53e8ec35e91eeab97fcf3398135fd436c530c609fd47a3508472bad000000000000000000000000000000000b25d0db1e28b98d4f9d3c77c0b71489c51186105d93be7fc2cf8c72b8abd8959340114635e705e698b0f257855ea4bc", - "Name": "matter_g2_add_44", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be100000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2", - "Expected": "000000000000000000000000000000000cb2998b4e634bc83b5585b0683b7b561f260eefb826719bdc3c95e8ae51f8f7b442d75d69e0f9228dacde2ce80ef4e60000000000000000000000000000000014d30d1c02122143868ea01b454a4f33432d875f8ba66e6bb1e02fc161bb5f9298e673339a9183a15759f8b94b519cad000000000000000000000000000000001068bf3c768e8c9e9058805050394ea820b5f60bea6d271f8e1fb665d3b7931ab0cc03dff4cbd24577b2c254a956e8200000000000000000000000000000000008b7f4148bd1f4926d2a84497b60a48701057ea08855bb9a2f838d2464e66360a59d058d9072f1416023cc72045af558", - "Name": "matter_g2_add_45", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da900000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb", - "Expected": "000000000000000000000000000000000a7843a1d67360b8a6976aeda2e4e98f1ea229a4d84b947dcf5ed8215173d5cf783920a7714f5b048778df30f01a0bed00000000000000000000000000000000035663ceafda9e5bfe934cff725b36b258f12afe749f907a560a06da4abf8380853f8de31adf14d62cdb310d8740e29b000000000000000000000000000000000f210d576aa5d4cdf5aefd8e55be099c422debc217ddf0151b8801f7d16456c97d1e134b40e6d71d296ee2518e50af9d000000000000000000000000000000000219efb35c68540c6bb0ef224e68dae6f7d48425c2908440072f5f63eec3c8e750b559c73e33464d0b5cdabb50fc4d3d", - "Name": "matter_g2_add_46", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee", - "Expected": "000000000000000000000000000000000ce704e650605f747cbc0bc76e82de8569ba7b3d897eac2bf5f79aba17ef4c989731e959c0bc0b7988000a9b0aef39430000000000000000000000000000000003cd3f3d978d6c85d98812ea0e3d21149bf4151ad1bef966ced124ad62dc7cde55f16e8d08bb1ad54d3a23bb73795d8f0000000000000000000000000000000019d37a20fcf6244c2898b271535e3b8f279eaac5d8fb1ba142096da383488eba28a21d038d7a9d3f9e8a008d6d3ee1d20000000000000000000000000000000001ba9c1720a4ef07ec752efa1ddb629505b3586af415c916fb0ed2953cd8943d9343268f438db860f0bced3e690a66b0", - "Name": "matter_g2_add_47", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c70000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb9", - "Expected": "00000000000000000000000000000000160d8b4bef36fc3d09af09dcc8357067c22e421f3811deea66faec42a2f00fa4aceca8725cf99062613126a9fd7bf7210000000000000000000000000000000004e8691a42c8f3ce0e7c0470446689e9d2b3cf57d55fad7387d624857f977cb9c6864c87bb4b6a2c17538478ac5fb5960000000000000000000000000000000015e20f6baef033efbd38081d5a10eeb3c67d89ebe5cd652110b778313c9e86cffb45231616d5b67e9ec8b7be15980aa9000000000000000000000000000000000af75dc221050256015fecc2bd8113b42afc9c624e5d28d7ff8312af499e34a603d66a4304f263729b440b6266538316", - "Name": "matter_g2_add_48", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c6", - "Expected": "0000000000000000000000000000000013edd8f016f6af49e9bc461ca14c438a32eaa3d1270a5acec99a666aba3f0a7e7eccea81720971cf4432bfa94cd18392000000000000000000000000000000000dbea5617e44c82da828844a5a4a1426d43422fd0158204a99f53cf9821f82f0bb0130a2123297a6941f695e172d9c5e0000000000000000000000000000000005f65a445e9f2d57dff2b210209f9faeb1c8b446454de4724d990aab20bd68362dd7ceb5b95de361c129855abba83f7e000000000000000000000000000000001219ecae79d62d3039e642369353993b1ece049331f06be256f06b01a1c3b0c617221c8d8f0bf4b6a0abe1191a3ee8e2", - "Name": "matter_g2_add_49", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307", - "Expected": "00000000000000000000000000000000158da32df45fe3e9102010bfd7faf3fde936bb8e52f68262ef479ee825a0d7169ff753aa042883a5403103a9bdafd2be000000000000000000000000000000001800a5776a47f52d2af08144364a6cd7442a0e2fc214a2d8d285a29bb7bd3a0293e89f0a1856223a527100d0abf12899000000000000000000000000000000000a6079d18ff3367c47fa61a57a967b782f3529bee93f452ecebd4f5c404b3e1769c100da9b8aee4258b5191ae1dad9a90000000000000000000000000000000011d3188a927e8f13aecf7f8637be6ddbbce309393a94fef77923c286244f8531d3e137e031d8c1af829891425afd53a3", - "Name": "matter_g2_add_50", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52d000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc26", - "Expected": "0000000000000000000000000000000019294d87be784f0f8fa29de80d45a697bcb694b32f3f6d7641d4b08d8a7ebdad0ef78ba5ccafd6b7f240e1cbde019c51000000000000000000000000000000000645f7851644e1e7e255d0b3dca769b987ec3ff2c9eda42cab65dc39be2f9858c31f307d59f6a2caf9dd932d873d2b08000000000000000000000000000000000e8e93f39ce05a11d40f3b52262980c79ecc52939dd02b94df3e5034a57061d040b0c8894189f4626f37bee485712dd00000000000000000000000000000000001e0b7c9c3d7456b2c0ad842083e9ce2a00da91cb1aaba371ff4b9370f0f2c08f4b53b8e5a3030c99b2957cbe5f9e967", - "Name": "matter_g2_add_51", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d761800000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb34150", - "Expected": "00000000000000000000000000000000040f355021ba50c9a3b2b4267668ac8d76dd88991be984ab5bab9c96faed6dcc6e8eac78ed29cd6f7d687dd55cc5d5b70000000000000000000000000000000017853cf0a39332e3c7d75b08b2940d693ac7cfdac46719787c22b55a2ab1036d6f95b68075f1c585942843aa486f17bf0000000000000000000000000000000008696feb333417a7262e8976d1546b6d0a9d5970095485b18efcdee8993b16f42e6dbfdd08d30c45fe4af6a5e203de07000000000000000000000000000000000ec26926720243124ca505c0e04923f3cf5eeca2abfdaf4388960b87c6c1713fc54cdd1c825e2ea359cc67b3bebfa2f9", - "Name": "matter_g2_add_52", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e69000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b1", - "Expected": "000000000000000000000000000000000f3dd56c416db1c06fd27e18fb852c9e1662fed42005e253230a7a8f7c3e0b8ce637666e1d20952c219cd2068d6865f1000000000000000000000000000000000aff045afcbefcdcb5255805a86e8af3de881e5482188c487d15ad1b799cf551c1d48c7665028b05ceb2e82e15ea4ae5000000000000000000000000000000000e0e6ed04926aed1f8c6a4e13227bf2a99d9d6d349a9c86214373be693db702a0011b4423defdb7d842bcb6f722c70b100000000000000000000000000000000148b1af285c65b12eef498f1c9e57a673e7a3803088c56e32aaae13dad3977dda8d3e27809094f8d8ed607239610a1a6", - "Name": "matter_g2_add_53", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df10000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e", - "Expected": "000000000000000000000000000000001220b3da7e7d03823458bcdcee82db56957e5aec335e9b543ebb0f3cf4fe3cf6ecacb6198c886b9abbdaa42f528b4963000000000000000000000000000000000138233b166547e9e9ee9d11048e2d2579b2b111af5cab372d36159c4c45e28d836d733a1265e8833da64f461c0a32cd00000000000000000000000000000000005f860a0c72034f1a928501d9f549e5c2a9dc72670272fbf35a0b301025c0fc751d55ef6fc2c5bf7ff42df7693f3dca0000000000000000000000000000000012c73105adf97bc0dfec1f56153c57c6fdb9d68341f4397b72f5b6c667873ff7ed5cc841451b391e33290cec256395c7", - "Name": "matter_g2_add_54", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0f0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e6", - "Expected": "00000000000000000000000000000000014933a0923416428b5fe5be7120bf399ab62ca091b07d03da3fd2ff080b9c411c3cda3bfef40c8450ae31c412dc5feb000000000000000000000000000000000214229a73780d4f260364649e9eb2ed751ad3f687a832a3738ca2cc81a3acf12757651e88c4bcd79239bc0b0c40e5a6000000000000000000000000000000000548f20fa375e578084e085ee71df5f8ddaec1db03a1415938d9521b5d9c914b5295835fc07263cdbf49d7802551156a00000000000000000000000000000000063ecd9efe55229a76fc848728e940183c23bf47363cb34c5a49837e6df8a5f0dc29d7108cd10ea08e82ccf017d246d1", - "Name": "matter_g2_add_55", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a330000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c32", - "Expected": "0000000000000000000000000000000008a71a08d2c4e2ba3d8774dcb42d3e96c7f72d36fb3b880a4049b078d8257a7a9a51b0b34c093568baf4aa6de70e709d000000000000000000000000000000000daf83b5ad4b91b557982fc4b9b7dbed2998aa39fc4658ba671f5f27b3888dfec7602949cf626c9e6ef21171acb185600000000000000000000000000000000013a7ffca291d9ba8790ca0462c54c147aa22e03a2413b756f27583155932aee65060924e46db321b3fd6f22ff7f54041000000000000000000000000000000000289d7de10285285279aee024e52476fa6fca85550f7af183a161e395d72e1339b629c64127f96bc85858d80e73dcbe1", - "Name": "matter_g2_add_56", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a6000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95", - "Expected": "000000000000000000000000000000000a4ed8d613cfe4f5dbda1d0c6812d0edee45ffc2667323c3828f8ce4ab55c119e92a82f2c3d06afe3adaa4aaccc18f8d000000000000000000000000000000000fe10c5e185f3f8ba81c93754132d76e05eb3543d8aaa8a2d0c98833ce5fa9e2b84420d6e3412e005cf89d11f5400a510000000000000000000000000000000004ac5f8cc614e3833b3b6dd9eee9ac29501002ba9054554314a4c516bfc8cec870995e811f7892811346574f3c58b2ec000000000000000000000000000000000a6bed54d8ed4ccb09211ae7773c604edc6ce51a05c9acc94e8167026906d387af681fb33a40e72e85cb076e072db7d9", - "Name": "matter_g2_add_57", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f254000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150", - "Expected": "0000000000000000000000000000000004d145ad2575313a922667b897052063139eef8c61dd375eb055c4a5c52cfbed35391a85df915e1eea50d000b9b6bb5700000000000000000000000000000000071cc73c16a234e99faba9b04fafaca1a943f2bdbb68dcae0a1742acfca1f90c5f69464aba42be6c18be31f79ce30791000000000000000000000000000000000bf725a2f4d7d33c66fefeefce13fb5649a68a93fb7086c943a7bd5663b5788a5ceaad7fd2a219ade832dfb3c0022a5a000000000000000000000000000000000fef4a2610610afef43da2161b86b25a8f6e30ed90053d57f5ee0a10effcdd2af769d32ef6843804b2b6590f95eccb4c", - "Name": "matter_g2_add_58", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c5600000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b", - "Expected": "00000000000000000000000000000000151ec7c35a67b878420e198ee7bf359d0668ab61ba1a0bc2e5e57b1b7b18838a015464f9910b659fb7d1e10af2801d86000000000000000000000000000000000511536f34067fe931c6e829e22443eb838f0c938eeef6f839eb322d72e2011dd1c33c504dd044e3cd721065d7075b520000000000000000000000000000000010c486f846242024f9bf40d805c8e33ecf1b44cfaa04455d5584db7ebc32c0d29e8742c61886d4ebae93f22c518ea87300000000000000000000000000000000072e184c836a853fd1153eabb1b645bd35ef72eefde4a52db169acdf2d8d68499398599cb4002994c6f4936de1da75ef", - "Name": "matter_g2_add_59", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87310000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421", - "Expected": "000000000000000000000000000000000642f215b772d17a3aa45ee3aee607321c02b4f7a7df3884259a25ce78c73e9536d46333fa388e506fdc79c708bfd9de00000000000000000000000000000000145864ce36521fdb641761be541a27bbd3f4797b923a870148bef1d5b4b0d463c0a7c8ef07954dad464510d836105e05000000000000000000000000000000000ca038e667fe68111b583dfaa95f88d3b9e46c0798abccd1476071435067e6c0e2fa81d25db6e1175e60efa1705538b9000000000000000000000000000000000cf1cb1b155e4ea47077c42a1a99c3f11f8b27516a808b5e73498ee12363652bb46eab7e55de93513cc2d6272f26a537", - "Name": "matter_g2_add_60", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab71960000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d400629", - "Expected": "00000000000000000000000000000000128c909854a20ccf9e8e396b617b36f233909a5f6c3524c93cc659d22afe0e7058a438a5ee4345bed914288c64802e29000000000000000000000000000000000239fc43718cd27855ee5450cc9be5be5d9bca8188c22601242a1bb4269ca0fe62ad5e12b2c65558cd3dfc89ea31205f000000000000000000000000000000000a0aec9527febbd35bf041a901b0b35e5e0d48a2d6d733bb557d0767798369a7ccf2f1c278710eb764f721821f9aeea300000000000000000000000000000000194931bad52daa16a648ccf1ba9a4768e5e2900fee4f9bf46ae07d1aa605aabbfe96684f5d2233c0b254cb4ad5517775", - "Name": "matter_g2_add_61", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f20000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d", - "Expected": "00000000000000000000000000000000189ee5ac642bfd0b612058f96e63acb1feb6b4dce125bf0ea1e56e846775af1a8b0864d4ece6bd96c3b5dbb04e2f6c33000000000000000000000000000000000073d57ab79314e38267ee8015de3156f2c1d5dfcb6655a150b9ab4a3bc9eeddf7b37b3681c49611e02abb012770b3f5000000000000000000000000000000000cfa1363275c7bc5bbb9bb7c03e7bb7f6d6d365e39fccbe62cfe0bb93280527c9ea99079fdf9871abed035b62079856b0000000000000000000000000000000010048e4e96f26710d254110650de36460be2a8302badfc2da8b26147da498e4620e79b4329033fc3f3a9c99b1e12aad4", - "Name": "matter_g2_add_62", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e", - "Expected": "0000000000000000000000000000000005889133be5f447013d779f2b9b0033667c5af87e1c8a16d239ca3ed238920004d87e00119ded46658026c26988ee63a000000000000000000000000000000000d4ed8fd88f7e1394f2b5a65588bf1c461a292acafdb77703c2790ef249f2de695524293c826252c94967a3ea4a3a28500000000000000000000000000000000001b5ff0aa278c7e87a89d4748aef13b516c49b7dc9f7cd5e0448dc6fd860a7a8af7183a198eebe6c7dd549fef806db00000000000000000000000000000000003c9e40ed44427cc3cf886ca2db341ae31f015c542b857f6702d25cb5036e3e6abeb8d4bf9a0e203281ab85ad89ce0da", - "Name": "matter_g2_add_63", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f", - "Expected": "00000000000000000000000000000000093b692a68536b16913ef38c3bba7b19ba94a6af1c36a2e54b8ac1754a29c29882107cde142deb95365af00f2d1f537e000000000000000000000000000000001035e70852f38f860a1a04f33081e84f3ed17d83ad894a6800e7b8b9259067b755fe7e08d4c1b297c6d53064ab8209590000000000000000000000000000000013d38db0d8575131865bd7acb6cbe994812bdd8bc7f51b810bc382a6eb379d442c47be20a2c8e751fb08ccce8fea68690000000000000000000000000000000000bd114951193e3bd58cd0025e0b0c807ea073b1c1f7bb04a2a00771b6442e70ea20e1124572ef5b74d2bd87c93c82f5", - "Name": "matter_g2_add_64", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d", - "Expected": "0000000000000000000000000000000006db1eef1f614613ada8383e63d631484015224902ca38f58ee384a70af0a0575b0e7063675d2dd997ed8a140e2598470000000000000000000000000000000010d7b833f050f18ff4e3a8d0df227a9494dad9cbde88f68802b23e87387622a5333dfb7bcdcbfe2d4d137cb532ef4a150000000000000000000000000000000000c9c40ba972ee0be2823625a23345fe352d701cc8bf9a153d5a55c205ef1b7e5544d0a7f65aaa24bde8d77cb4c31ab3000000000000000000000000000000000402f170c4c3ebb9b1e7d64765b66ba9b8d45b2ea9fe9517626f38e00a11d180e1f8872bf80f6322bdf3a8dd90732ae9", - "Name": "matter_g2_add_65", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad300000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0", - "Expected": "0000000000000000000000000000000002dccab673b26be02d2c645c82a2c73290f0eb053e07d4f81d4d315d9483e57c58b65cfabeb0172934b9fbb52ad519210000000000000000000000000000000011c34a27c850fe319fe89399e7680064caf6dcbad171c3a23c45b9883ee06ccc3482b2b81e5777759ff81b16bcc1b0f500000000000000000000000000000000119adca3e2b052c045124f021fceb03c979e6eec0a270c7f4ab13674e461839a4d3a10fd48da4e9ae750a238a2649ace000000000000000000000000000000000fb5210677e1096cb5448bcda16646d6dd29ff8a0765c5aa51d83fc952a5ab8063aa96e97f33abf701cb8688c989c363", - "Name": "matter_g2_add_66", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0800000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec27508", - "Expected": "00000000000000000000000000000000056489b2248ba672501069ab6742016cc8ab2af50a119239bbd3c0a4b9b56e014402b78bf62b2b37bf4645c3bd3d95b800000000000000000000000000000000046956432001feaba6d230da27a72e8db5c8eb3d52f00616f87b55c951217095f337a302562cda789e5714c4391ac27000000000000000000000000000000000172c2a583c9563fe02d43b2b767c4ee4e3990fbabe4ac536d64cfcf059f0e38672876289bc86915b6344eb398fbc4ddb0000000000000000000000000000000008915b0edade80caee9b386e4a560ff4b9dce33946ee992649466315786e139e3ce241ebbdfa7ee28fad7e6214e65666", - "Name": "matter_g2_add_67", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e1090000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f", - "Expected": "0000000000000000000000000000000005b81843ef3f98c6a6686f1fbd26f77248497ec3d41aff4be5968d13ba86f86309b0ec4792d74220ad8ef147bdee9aa90000000000000000000000000000000019825376b243f3e374b6e9e7e51e0c969bc72b39cde1dfa09187a3c7c5c2c752ee16fa5a4c8fcf94464287419b3a3845000000000000000000000000000000001308cc0c77219034a9fc3018f1d668a41e6959476aaaa5461ec73d7155c6a68fb08e1fdf8140e18270cd338c266a83f4000000000000000000000000000000000fee2a6e245e3bb570c3b605f7ad805bcd68e9a1f2bb2282f92e2a2e83b69e275b21b923f33a65defa8c4224934aa588", - "Name": "matter_g2_add_68", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b", - "Expected": "00000000000000000000000000000000166414455bcd0e8e40397f4cafa9628d1a092beaef62d35211cf49779ba98df5c1d692f650c1fcf0893a9d4ae1926b1c0000000000000000000000000000000003dd898d0725ee899b913042da8566a1379aeb4dd5f0222ac784205b4e74f32858ae490f981801b166a01fb96266dbeb0000000000000000000000000000000019f0fe4f12b113b337361b977aff7cc7dce50bf37c2609b9f311ce340d30225de178999b73345ef49625518e52aa4d7800000000000000000000000000000000090bc07c6270901d706a8d28d512b07fd0e03013d94d4e43eafbee59677998bfb7c2a58aa93571fb49c35518b6331bca", - "Name": "matter_g2_add_69", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b22000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d", - "Expected": "0000000000000000000000000000000019ce0f31d9ebaed0ea1d12d4e232bd3ad48373fa465af44f1c8015102b624d2f8330d1323fb2fec524e83de0f6699ad7000000000000000000000000000000000915d65fef96562ea3b76f3152aa1b8e445ef50fa66dc487ad0c04cfd7a33b5ee48aed919eb81fe83b1f4dca59b4990d000000000000000000000000000000000e4731ec887261f29475523f7dfc5d21cbbc1b883439701a33cd58bd24f5d447267707c2b60ea38b04510be7dd10d72b00000000000000000000000000000000146a679d7a81aac5952645b2635f24b96393529ab9571ecc1078c4c20a77e59acc4591b9f45df00428250c5e31b1a8e9", - "Name": "matter_g2_add_70", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f", - "Expected": "0000000000000000000000000000000016790155e57f7103d9e325a1f3a64c0b8a1875365eaa0c01c515538b64bd8265e8392e755a2f7314c37ec09026f13d290000000000000000000000000000000007bfe690fc4ab166b29de35e341e8faec4bc3c2d4ea2d42c9f4166c0d748b92b743ba646c86ff9e570612c75bcd522a9000000000000000000000000000000000c11b9ccf990162b772099fdb4266716b11dcf46c5abd12d03caf222c571e2a9e28cfb47e11db05162967ad4b430930e0000000000000000000000000000000000bafe02785607bae144d9ef5391fef02b9f2fd5dcd436e2506bd40866d8726eb83c223e09c00f3b8895181c6710912f", - "Name": "matter_g2_add_71", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a00000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd", - "Expected": "000000000000000000000000000000000965966a8a463de1f3bc49d9873668e87f54d95612231458dc8b885681cee8e2835482b4bfc476153c41b206f427cbb400000000000000000000000000000000183639fa14dd74c33e8696496a3ee269160f88e5daca4fdc468724d9b6af8e7d0706867cdb1bcc608029b89b94c531a800000000000000000000000000000000026257fc32efaf241c7712b0a7e9f881763d8fa0711a452d9b71ea25e973bffd88433cba768f1e5b3ea15bdae9cb9428000000000000000000000000000000001527afbb6594dc0f472673606fb8f4797fc855bde4d308ac1acdaa26f19a70f80f2d2bbf3498b53b887b79fd6273231d", - "Name": "matter_g2_add_72", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db100000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3", - "Expected": "000000000000000000000000000000000018123e82a5572e6b6c62d5db07448838df9db7f7d15dac1adba1fd924892c8bb3c417354e838f706564a9ac282c2ac0000000000000000000000000000000016613fc38997d39b2761aed3485de4d7c273e8392e434185605e968ed942b9d4712cd0d538ed5ed1317870d0cafcae27000000000000000000000000000000000354365566b6e43f8b7f4b94a6343146f35ba3abf61a204e9c976b1ad1a90d4d493494c957def69ff270371c1c8d953100000000000000000000000000000000066adbadf1b69dd16cf19349c82e362be4a3768551599b81a4853ca524a24326e6c9dcc38b5a60ed6fdeb3cc4e7973bc", - "Name": "matter_g2_add_73", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d", - "Expected": "0000000000000000000000000000000018ba8af47c5cfa552374cb1b25ada1ac785381f2da0501f86c9e7b11cd4417e64095a5c4bdc2480ee10d215ae2296063000000000000000000000000000000000a2e09eff98280f6a9863d8b8faf8871b44650496eac1aaf90fc2b256f88e937101407d722c95fa76846776d4e6bf0dd0000000000000000000000000000000003824f5bf25fa4aec5a9e044703e5564122bec11da155c01ba8ab8344265516c1063983235863d826f68bac455327c65000000000000000000000000000000000ea72f8c6768736800b141b477610e37477d926acaffaa1951a5bfebb042c94c065e984a8812430153d529dbf07ce2bc", - "Name": "matter_g2_add_74", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296fe00000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6", - "Expected": "0000000000000000000000000000000009f1339cff0b58b00a871add058929ffebdc58cd1bd8a9c2c965c63e1843945b28138008cca8bf7b7cc9afb69a11767100000000000000000000000000000000011f65b337710a4043e1fa58bb41d80d505e2aee434b6978129c80fa1b124db89e61617e89bc0e596507566f4a484e9f0000000000000000000000000000000017560f768496ed583b3522c4a013f8b96073197e5b53e9041db6dc935a266111e21d8c54fa33b7bda944a573f6e1f07d000000000000000000000000000000000168a0742af91f42058e6501e122b6fc50dc966c2f5981372704694544aaa68fba2b6483752fa2464526d5072f84d8dd", - "Name": "matter_g2_add_75", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb519000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be", - "Expected": "0000000000000000000000000000000005daf8338637bddeba63c788d78faa622e014efb84d3ac1d655d15af06317fe31d1782b2990354bd507632844cc87f2700000000000000000000000000000000185550250e2d9eec798e8b8c483dc37e2a917b304a6036e8ee518a0738d6bf946d99f6b7ee352b1a259aa894d53a8e1300000000000000000000000000000000105a4865d66ed4bc4f51dc52ffcf284615593d573b6beac490c3ee8e08ab83a529c8dd062d762d1d70b9b3290b6e8bd50000000000000000000000000000000014f598e5d0e40090f29aec1ecaccbebbf2a2d6889bbb9439798924db41b70c0cacdcf1e8ff6906f61943e9a8a1ae4fb5", - "Name": "matter_g2_add_76", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c", - "Expected": "0000000000000000000000000000000006b63929ce97554659ae731d60d11abe858383e39a67007877f68233cba8179777c0dfe511fc730448da3f1c4347f85c0000000000000000000000000000000016d4df414c287b0871c69f9745a9ae68ea3a1ff41ecd17d87623338bb8750bf12be52caa81537bacee06cebb86f894890000000000000000000000000000000007ad72c98e2428b90bead3616f1b31b26e978cd3f9b6b759ad53056098c18932c48ba78d3da112d7a738d7a9ba21d84e0000000000000000000000000000000010dfcfc53d0458296686fd7e0555593e0378d2cb176d456abebfd8322012bc9b408bb180d4237679985457e689131705", - "Name": "matter_g2_add_77", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94600000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3", - "Expected": "0000000000000000000000000000000009b166f124b5b85875834b5b0c088ab79a2dcf262240b284f57722e78b6eb56a192cd32544c1bb93ef492fe6d7a6216b00000000000000000000000000000000189b9792982b51b13cc3fc1691e0569b6c8d998168d3a3376e63ca60de4b30a84ce8d04fb265bdcf73f158d8e316bdda0000000000000000000000000000000005b99948b635750040b5b59568f0e8bacbfd512db2ae52c5032cd23eac18ad58d83b8f78cd26ae979ce2abeae8e1f3c3000000000000000000000000000000000d0b6561a49c358101b30f714563bfefc72e0febea857b1ce78cfeb9508b0108c2089c9b35cd694bc8c0ea8afc8d047e", - "Name": "matter_g2_add_78", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a88", - "Expected": "000000000000000000000000000000000bbb59d3e6b0b4d86ffc89bbfcf543a5b8ff922f1999a1e06c501a734b19dabd54632132c865c53e5287f69f06942a58000000000000000000000000000000000a3bb94431530879a7fb46b317d4f3d65b5a790739b396c78521a20e1cfad9c44248c9576be11c70970a49a1914ceffd00000000000000000000000000000000198df068ac5d3cfb9bd6896ab64495f4b9933a72872679ac3a46764478f043e9fddf17a7ef85fb72a8dc1a722804198400000000000000000000000000000000155c1a9db0c90634a6d214e996b13252bd4db3a4ab84ca7456ac3e7899e6fa096904a90f1150026307a1cac8de00c6df", - "Name": "matter_g2_add_79", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d70000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff148", - "Expected": "0000000000000000000000000000000010684ea0303f0e76b60eb96c470e1f0466f1f2b073bbedc1a0c0df1d2f6c66d77cb90ef9bfa4fef6a6a9eff8f5c66f9b0000000000000000000000000000000010e7ced79bbf01ae9f65d26894c73a905514296f19561ab4d00c0cde31737d01e7b4e8b8e6050054a7a17e8acb74d49d00000000000000000000000000000000174f771a98e262825ff2db7571f5f5475007d2f73a2c265f24e2929671bd173596b8b163abd46b868a644dd464dcc7cc0000000000000000000000000000000001cbffc9bb3195672ea2d998b169f853d3d4b4e147379329b1bbe69ce76d08ad78f87fdd876af227a050c31884fda084", - "Name": "matter_g2_add_80", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d527500000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f", - "Expected": "000000000000000000000000000000000fa306f630d06c801e0203525c75fd6065bd12bcb3c4d45c7e02b597f85a53fae1e65a969feedca75068433547e4632d0000000000000000000000000000000004b1bdbc29f19f6484ea4648c70eaa47cf5bb07bbc255bb72dcf68a7b661de433dafb682d51321369cd3372288b2b9c400000000000000000000000000000000136671654b24e1ff2e8223ba747ded51f5c826b6e2c0f02e2865fc35d15045f41952835800406f60f966d1f241914726000000000000000000000000000000001007b5e8ed7f0d25091dd959d89732e9df02561a829ce013f5ad1adb8d6d828a8ce87b52d39fda1b5dc2b581ca420e22", - "Name": "matter_g2_add_81", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae452300000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf", - "Expected": "000000000000000000000000000000000fb74d9ad4de11df81c48d10b9a14fde8353ac47dc902b4420be4c086332be480552e26fc42b7c0f30e34f740bf9a4e6000000000000000000000000000000000612a7e23bbb525f91084b122dd4cfce4074c9e6eedaa7cddb58a14e0b1eccc2f08296baea3eb3e003e576fab7c557ea0000000000000000000000000000000016dea145df47a2c5262893c273c6158ee14d44c3740981c161624a6e9ebb982a52c1eab6160c3849f2bf3821d953f4c3000000000000000000000000000000000e920661772b8b737f1a663badead0e89aec4cbb86e6dece5d4db8a673e75b844bfe81662dff671658cb8386c16a7f3c", - "Name": "matter_g2_add_82", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627c0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77", - "Expected": "0000000000000000000000000000000015930559743b21acaf390b557fb960d3021f3cde80630d8867a063d445f860c8a01037057de1929be16d879416b12a6c000000000000000000000000000000000c6074c54c83f717700f61c5b6bfc641502121b59b196a1f8c5f2945e5db1bca0d7a94fdae96bfeeb6204c8c3f4d048a000000000000000000000000000000000b3a78454479c0990e4c65e4f831606c7eeeaef0faa86596350c9e43e84ae959a0f32c8d03d1f631d9b2ecd046efcda6000000000000000000000000000000000aff797d7572f20b06bac75bcf8cef879df11599ba7f8b86eaa28692d1239cff22841b66e28662309e81a6a599e79ddb", - "Name": "matter_g2_add_83", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ad0000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee41", - "Expected": "000000000000000000000000000000000351bad2f1fd9adc84280515c2d9e538b69dd63ac93514987ecace75d6bc4585199b742eae0d357d587924333721a1d90000000000000000000000000000000003e495b544aaf19a6415d5558170b8686968dc922367c5c8c212fa1f2785535fe0e71498b98b9a39c8b1f2384956170a000000000000000000000000000000000c7040f34872eea5f98ddc78737dd01fdafe75081cf66ad5c7c900674fa90257105b4f4fc59103dd5b92727a072ae462000000000000000000000000000000001312bdd27ef038d4a89b12c86281975bb34b435d42642fe0732709baf55e9a0ecc0ede8a4775a33e880aa2e1fa7b7ed3", - "Name": "matter_g2_add_84", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa800000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f", - "Expected": "000000000000000000000000000000000d521781f60198341d116fa5cd9e2b5c2fe51f91f6c8318f351df007c96086f6c3baa5cd2b9b4f442305695dd9b01ac70000000000000000000000000000000013454fc15b1d182bc98d75947547b3bbebef6d5e2d38ed7c67d76eee8da89ea2be19280af4760282fa7576412d5f2107000000000000000000000000000000000d866015c84de74c24dde252542d0d3823f435203c71cda140af235d88f3f4b736e9d75ec32c09ab73bf74083e76866e00000000000000000000000000000000147dfb5f53a9cc61b6788c911dd8649c09cfffbbba368c1872a31cfe3bd6d6427d7b00163d39f8e0b81fc4c40dc60b87", - "Name": "matter_g2_add_85", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bf000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c", - "Expected": "00000000000000000000000000000000059fffdf2d79b4a297f6912e3035cf0b07db9372f3485150e00d60bbe2e7d86f45b5c2ef062dd92c7e8b1e2be5e9bd140000000000000000000000000000000016acdc57e7231b020268373ddc8b8a7318ead02a8c7181165ab045208409373eaf57ace9a6db1fdedcaa477c7a0ff6f40000000000000000000000000000000012fe630f7de8ef5a129b99faff2de080849bf3b59aae1af042c29b1cc49c8825a4f28c4ccffedc6d568f306416b5bb90000000000000000000000000000000000d86ab3e49ffdc7c2485ecbd00256af83e7f3f064d212ea91245d86ca75e3c7f28b42fa9496a5ccc0514cffc60c9fb83", - "Name": "matter_g2_add_86", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e84000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb1", - "Expected": "0000000000000000000000000000000012ba9a8fcb69d15eff147f663a5d7927b6f3f79330eb9ee625e0100b146597554debfcf97a3afb51387a73554522ed0e000000000000000000000000000000000a63a990d6454d4db6d58642eb3489f79e517fbbcabc06f2eaa00c4b6f9a07aae97991f169d90af3461b7a62db276e00000000000000000000000000000000000a95203a1628a6ae2551df832f7ab94ffcdbf985e4c9744e244214c8e8b8079af05a9321d1e49b7240c2bdeeb7b783280000000000000000000000000000000001ec747203be73526d3f943e0af814dbede34020144bf247eef9a6ac2cfc83ef63f18a73d3baae18bfd8d5e83d0519de", - "Name": "matter_g2_add_87", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbe0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc", - "Expected": "000000000000000000000000000000000eefda9046a950c232c6244a79c33e7135d0896bc57839a4f971030220e3ca8196cd0ad75269f3cb5586a384dcd17f9f00000000000000000000000000000000195ce623693996f5ce9e45b4e285adb969e6771e6b0701fb5c95715523c8cb93aa641583821a3b360ad6f4ea1aedcc9f000000000000000000000000000000001553a4d0f965d26fbaba56294591935bed63c84abfedbb9d5c61f3d43484ea71600935fe3c8b6b137d7a9074d907e86c000000000000000000000000000000001673c42c88e4acf8ca38680694b80458f988403a4bd667468506452303000d13649c4f610b738a94ff88b65053731c08", - "Name": "matter_g2_add_88", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba800000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed", - "Expected": "0000000000000000000000000000000007145ce58cbe48405392edda6022ba8942df055ab582ac402e7c9a0a951cc6a38cd147903f042273e736f30849996cd10000000000000000000000000000000011b457ba464ce818a34a11afc3c0007908091fb528836691e6eccaa9a23ea90cdc746769c4b7ec73efb1f2878413c3b70000000000000000000000000000000019ca519fa6a91cb7e83704daa9b92da9bb70b003f9e9bfe9f323430bfec9b19b01005aa9fcd19d5b1ac59dbdab0c0d84000000000000000000000000000000000ae356f5e5de0d7662bab8d947662bf87d792a3438ed477cf6ed4b27c935b1dd76a5aac446d4dc36db544d4aea40b505", - "Name": "matter_g2_add_89", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591c0000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c5", - "Expected": "00000000000000000000000000000000135c42c10ef97279e3d152b18cbb8dac11ca8c805dd1d80818851424f592e7522589ec7df6748b5c72d0808399e629cc00000000000000000000000000000000083ddf3843434937e05ba9e101096371fd8fb34f226bcd517716200003ab9855f7aea94980c57a6b933494cc57afc562000000000000000000000000000000000be9215d936a49538442189c9a0bd3be07d4b0b1d14aa45afcdebc1fde17d33b66f7dc36da1ea5411549577f5a1967ff00000000000000000000000000000000176a4a4962c4af75a712e5093ec2cd5cb5c0433aa0657809dffbc0bc02b1ce303ac084f39a5721d482d41412d391317c", - "Name": "matter_g2_add_90", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff200000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de", - "Expected": "000000000000000000000000000000000bcd916c5888735aa593466e6ab908a05af528f34a7901fb60feb1f51737c73612436c192dfdecf927019724ab2a9b7900000000000000000000000000000000187d4ccf6c22381d0c40c9d7820ff8efe6298c6dad0caa25402412661737cb482dba2719c3a50ec08cd022230952dfc600000000000000000000000000000000164510d4f2cf1e14e039561f1baf82bea678d0065e378d5bb7443fa782e6ab2a3bf7e4ea125d6415a8277c60f5346468000000000000000000000000000000000281f2e28b73eca4db9966456b75de9ae3830c74ac928fc4c36b4aeaaffd47ee587d948f68056df2826ca2775415a53a", - "Name": "matter_g2_add_91", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5400000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157", - "Expected": "000000000000000000000000000000000cceccfefe04f94e0b67b29b5df8007930665006cb5a59504c3656b8c0bfb52324cdf50fa2722ce15b0ded0efa7fc85f000000000000000000000000000000000cdf34c330c0125f524f0711197639f8aca3e7c435f8c5ea30b78e9622c4bb72a7e584980cb4c3c6ecdd0689daf36b6a0000000000000000000000000000000004b1505d7fb65f6c06ef23aef85b16f3d991218187c5782fb635ba805da463cec9cfdd670c53d680c603adb827a4460a000000000000000000000000000000001104af6bef6482ae64b3b6b39664ec06c39bc18fa91b7b4e5bfcd444c827bab30ef548b28ef5487582d88fbc6d7983cd", - "Name": "matter_g2_add_92", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a70000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc0", - "Expected": "000000000000000000000000000000000e1ef3003fe3181f690224cbc7008856e1251430ce3cff56a1965c89a892604398f5101d1bec7ff1590b0cc3d23b854600000000000000000000000000000000185b4d4b5fd8313c31542bd1bac034046ddc705b41a034a00570181503a6ea4c2d808bba0478900064270fadf3d655920000000000000000000000000000000005bed63ab9898b89f92027c04ba256569e6285c851753e12760129c98899bcbab34b62172906a1ea4cb056d4d0a5717c000000000000000000000000000000000961129a3e212c7412018d7407d7ad16412feba8c138f4f6ba69daa1a25c6b23f3466bfde6f5f0d09ab67248a2abdc68", - "Name": "matter_g2_add_93", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa2000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc01204", - "Expected": "0000000000000000000000000000000001504c47ab0c410b32d5f1fe3d3996dbf1b21c5ef5aa3a2862a9d561b419f818f0b32b8e931c65fffc393ce7beec70ee000000000000000000000000000000000217e9fddd2551a171a13183ae3aba6bc5ce99e8f3587b92a7cffc738b478d8293b8c71989cabf9a55c5f5077249345d0000000000000000000000000000000003874de865d93650a95af4e153fe557c45bfdc4837bd6e209b8f05ad12b8fdee6432675cd92fd739b7e98e56e7ef16b60000000000000000000000000000000011303c0c7ec1f434cdf07c110da5f0bcd85935c3a0ce9fdf5546ca61edbc2d478562dbd9aa45a5f8d96e033feac2fdd6", - "Name": "matter_g2_add_94", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99d000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6", - "Expected": "00000000000000000000000000000000101ed22b16502de0d83303134a97db17ce956faedf47256a9ac86004bcd3ed112a71328a58f98a85977a7f22eb1352c3000000000000000000000000000000000e841a88d10493f301af54c5fe07a31ef90de106a6c87d5631b6967fd017f561a56176a5f3544dbb34b9f94040ebd2770000000000000000000000000000000001bde3c0076f26973651cedd3da97c7eda24451bda856026d1e22d3b65c66a3fcbfbf506b4b664b5fc06fca2d712d8a8000000000000000000000000000000000ce553ee3b7d5389798cdc5af8569aaf477b5b74ca1138454dc61badcf3ecf5e0ee8457e374b5735d0b8408b04fdbcdd", - "Name": "matter_g2_add_95", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d00000000000000000000000000000000030dfbb89bbe5c14a7a55e68edc4fc38eaee9fb539a6b2f941264c7dc295da5712b0af0f2bbcdb74f785dc9ba038b0aa00000000000000000000000000000000132b4e02fda605a69251a4a6289c47536f9735dd90908ed1fb619b3ab808b3a1f1ca3fcc8f4b35c9864ae311c15747f80000000000000000000000000000000005858ece0bb09e55e012450551025ad2a6d93a15d29619433742851a62d987e7f8bfa6c6faed76493a27060ef5f51805000000000000000000000000000000000dd6b393e6d1b8d546e3f5ce69bc1737399e6ababc628f25734030e10d82b5e9370edfb5da15566d80e23d2fbf8aad5f", - "Expected": "00000000000000000000000000000000182f90f5d3ce3f5ff2d91430376144583247def83b3e83524094d57c0f1be98b1c4946964deccc25fc303d6450edfbac000000000000000000000000000000001844806f711735c5ca18ca48e559a9e327b87b91d22a5ef161da7874668130e21a9499728fbc2c88366bdb59f8ced0cf000000000000000000000000000000000815e7cff14b4ceaf26d1cda5c267f432fad294b6baa239b65d886ffb039321f9e24330ae738a35298c6d1ec1ce1c95f000000000000000000000000000000001188a4a2f0920ddeccde1a47a0636aa7c404fd77fb9c828e4fdb5406df80ee6c258c2d4a89dae5e2a2b05210df9100d7", - "Name": "matter_g2_add_96", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e740000000000000000000000000000000017032b16be8656cf23bfe0abc8c9e6aade223fa9bea6fe25f95a025da79cea6adf38536eae3859b25ad1af1756b639cd0000000000000000000000000000000010975ed27cefbb43bafad0fd14c87ada8e84525e1d199fdf1e77caa0b718214b33e547a42a040ee3bfd51621a20d22fd00000000000000000000000000000000133d29aa41f92de37523d281eebfe91103f017e5fb390f6bad9a2a4419fa4702bfa04847edbca1da96eb1ad563a92c8a00000000000000000000000000000000014af850de7e800ebee4be1a33c7e3b30aa94106db7defa148568ca3c8d82edc97ab5769ac40162d3728687cdac201a5", - "Expected": "000000000000000000000000000000000cf42f2ccff2e0cdda7e5f1d7652680650b4afa523c8f9a554ec18b905c837a189fff73982cbccf903ea492ea902b87f000000000000000000000000000000000d38219770f669557cdb623f2476b5f3f7478422b016123bf86a17bf75848548d1a1ce96a292637b8d52481321d80fbe00000000000000000000000000000000170d8722b824e3291b570ba8e4f9279c1dccdefb95cb5b7a94d27ad8a93513737f12d18ef3153c4e12b530bc457af34100000000000000000000000000000000021aee9e5f578328caee3177a4e08303c3b5533e288dcb75f94992db3520a6da16f4201e60367240b29c48d175942cef", - "Name": "matter_g2_add_97", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d55300000000000000000000000000000000185aefe71f24281e5b03dd41e6d6d45fbc8975beb175118de7568bff0a9ccf917e9df97dc26bca16e8da06b0e9a8e7bb000000000000000000000000000000000015b326d401b827fdf556e4a24a3dd6c8036b1c849751b5ae3c3728cad88f931b06e3a345523a723481193f7afeb67800000000000000000000000000000000054ca16b4c87293002c31e64ad303e8f040e11de8b45c5fb9aca9dbec59b29dfda8532a8ef5ae6a92ac8ea90ee4303e0000000000000000000000000000000000b65a233a7731366cf24c801724265215a8626b1290d86c60bf1e74b021b0b44d7d6552f936fac7b5e60cf1feaa1d82f", - "Expected": "0000000000000000000000000000000010d1b2f595166929347e06c1debefead06334f554dc31f320cb844abdb1810b5f7c4b933ff8072dc03d303f4a6d0d09b0000000000000000000000000000000013ab41dfca0a7cb0c58c2c19e02f675a94d9e73312cfe2999dbac34e6a80bff9472506b48690f24ad3171ad495f445420000000000000000000000000000000015bfd0db53fd4da538caa3aee7a90a669cb84460365696ee79b190d09a6d4c3f08965de7fff4efeae435db52b97d213b000000000000000000000000000000000182ffc4304b911b47b092ab678edd63ed5f5e8a9069daf9247f3bf9c0dd149cc9992728a13b0a236fc9b37714b35882", - "Name": "matter_g2_add_98", - "Gas": 4500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db400000000000000000000000000000000085dd8bfc00ba517dc8d7ddb49d711d35bd36f9fe3843689019e779624a032d2f023533b8184b73042d1a1953d2885e50000000000000000000000000000000009ba8d5d36e6efe02097a3206bbed68529f0cb9875ab81deafd886d9243bfec8b403d2abe713a2ec929b93305dd2da220000000000000000000000000000000007f8f90ebb2771136a92023901ca85e87fb7c8b1a40f88ae564a124bdd0ff0bc27ea98612a817e2c871fb4bcea3bb06600000000000000000000000000000000152de417d02f1d14e5899201db8fd5db8ecb40ea8d415dcdedce8ac70c28d851db68e9aef94506a50ec28145547a2d68", - "Expected": "0000000000000000000000000000000017555399f979745302f08210de5311a6401b6b181100b3bc6b6d450f0f62079d2f02d7badcb164f50dfc46a975cbd6720000000000000000000000000000000014aea86c06e4c1fbf0711a8cfced2544c7624abc7ae7906cd992bdf575a702540c45c2117e221446ba09960cbc9048ac0000000000000000000000000000000002fac56960c4989a84e02ce36e8970c2e847ee45579d31ca77f042bf96505af574af822da084ae64b22ff876610ba9a5000000000000000000000000000000000a481cfea2aef8975c80a297ce5a185dacd25649d41f8466d3c63d786e3c264a8e4ccab5ef6b80ab1260e86ab6d5b3f3", - "Name": "matter_g2_add_99", - "Gas": 4500, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsG2Mul.json b/builder/core/vm/testdata/precompiles/blsG2Mul.json deleted file mode 100644 index 886b0c6ad..000000000 --- a/builder/core/vm/testdata/precompiles/blsG2Mul.json +++ /dev/null @@ -1,730 +0,0 @@ -[ - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g2mul_(0*g2=inf)", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g2mul_(x*inf=inf)", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_g2mul_(1*g2=g2)", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000011", - "Expected": "000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d536944", - "Name": "bls_g2mul_(17*g2)", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2dfb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e", - "Expected": "0000000000000000000000000000000006334ba1e361fd94bbd98f44b75ae9ec00ecb4d3467b5528870b1a1fa9a7d04449f12af90bd4c7a1e3f29e717d6d19d3000000000000000000000000000000000bf4cc1626393956915845ea7ca43d30a59c7196fbe309f2d5ee6de7e40c191d29821dd6aae46abecf634b904de8f7490000000000000000000000000000000014aeb09e252cc74610ab956057d4ac5af95cbea8a6baba9e5062643dc037d6841044cb38b22d7dfb978fe0b58f94cc3a0000000000000000000000000000000000fdcd73452fc1ced1c06e6271410a48dea05afbe889a692905e1baab8d72418c62531aab8b74842b51016f0a9cbb93d", - "Name": "matter_g2_mul_0", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d93884d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d", - "Expected": "0000000000000000000000000000000010e70bef8eb893377e7ff92168d7acef11c9efab990fbded728b173b94e1d99e471a8357f16625d353287086543551850000000000000000000000000000000014043c1f00221c439e5febd12724a9224bccf0389914461644daf329208e869b1bf149880dccebccd440b1748d15e944000000000000000000000000000000000f7dee1e7d122e410b29a9eb011ee700c2f230cf8f611e196ec66e153c1fc331175532a8f9b060b573bddaa705430c2e000000000000000000000000000000000e1f659470eab7c0741bc8777ac9fc8dcd11a6f1b30ffb4265e96b879e795a4dbf851d1149429dcab95464e89f334627", - "Name": "matter_g2_mul_1", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1", - "Expected": "00000000000000000000000000000000119a5147fe9ddca7123f721b5662c1a44b0964c37a214cdf3a4fd34166e3b25210344e65220c38ec84d0e3b5ccc7e46d000000000000000000000000000000001642dad5dacf4295b871fe9b2787f0861f158807b2b6c01c2dce12ab053c9472bd3cb98de5dc33f40053ff45ce5c9af40000000000000000000000000000000005bb5761602b6639f2ecaf79f2d1f853fbdf75f4b3852b90808b858993a83f8a0da8a2ce7072aa91e3b6b3ffd0b3d1e20000000000000000000000000000000000a75143b9551d4ae41fb8bd71fdba7826b994c65904d9189a5ac5130a59cbb9d8dee0e016735565148fc49823d3969e", - "Name": "matter_g2_mul_2", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf494c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a", - "Expected": "0000000000000000000000000000000017ebc9446f8c8e17dfeddab9188d0c808565da29c0bdbbc4138a44ca3196c4564853be28286b66660cda36832d6940010000000000000000000000000000000007f29a9583b4ae83d3913dcd72590a3f20f39eb5a6d36663c1ef433058e76550085b9c01bf797d98d0eef45cc22ff8c50000000000000000000000000000000016eeaeb123b12d1913ff1e50f974228c79f2b995609d2e3835c8e1d68773b0cd484df57b86111cdb75de1e19eaf062e500000000000000000000000000000000002f5688c1286aed42309896bd65d1826dc64dda615238fa9043669806968b8e0e1e3e77ef192b7df540aaf0ed282a9a", - "Name": "matter_g2_mul_3", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e8964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b89", - "Expected": "00000000000000000000000000000000042d0c1941ae0ed5e8787437ad5e2753bba02185317848e8ec2e425ac954e0efb1bca534725adfe87e8507851ee337af0000000000000000000000000000000002db55ae8126cbe86327aab880381a81205e33a351d172c883b9cc184799866a8db5a6b4321496e05d3ef62d00416d9a0000000000000000000000000000000012c45444403dd62d7be3e7658dd85909204751dd7d085f6edd38c0aa9185d3c32407d8c95bba371b380f788d0dc48e0900000000000000000000000000000000111421c6dd0db595ab731adfb4bc76c84a61197cb023b6f17e7176c443f20a4b6f8cd0a00cfa61e831ed20b3c6a84d98", - "Name": "matter_g2_mul_4", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e2787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c944", - "Expected": "000000000000000000000000000000000ccdb2a0b670f199a9b61198e6a2ce2117075733e6a1568c53ca493dc3674c6ae85be2491d2ed983f52e2c7040824afc0000000000000000000000000000000004f52450d7e041c561c00200d5b142b32f2df2e2156e4f6c15d6c00e185e135037a1ed6be15e2ed920daa00e2f9bc8da000000000000000000000000000000000f39c38c18f03ce6baf1d016cf32d7387269940280f2e8d21db4da33dbd2d24ebb93ae3dff9f79b015eee25813d677c700000000000000000000000000000000189df61f7f1025fa6fdd0a4708ff1d53db7d414019c4828de2520af3d36776062350061c2261e46e746a6475fdeccb2b", - "Name": "matter_g2_mul_5", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46eaaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1", - "Expected": "000000000000000000000000000000001388a59c57ec8ca5e68b99631abdafca1b71352ac35003a55bbc415b48b8171857adda31123ec86a6ed9e1060d56aa67000000000000000000000000000000001471913b1ab5bcf9336665d3d44232b4e58da70285b7b8eb1dfd7c54442afb28c339f56e6389f89b84db0879e1ee058300000000000000000000000000000000022101b4de40b7180ea17bb36bad0a668a8def3e7361a96fbfabcfc4cdbe6f607ee4ee80d0eb2418b848ad056520092900000000000000000000000000000000103cda694792af5a51e04b6422600a0ea6f50808ca54423cd4f59dfba633daa5afea49c85b900f52e182610efb62fe7d", - "Name": "matter_g2_mul_6", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12dac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c", - "Expected": "000000000000000000000000000000000cf5cb957a752ce9187940f63b13080790348814debf84b91e74fd6e822c2735941d61d50d492439475bb3ea7aa849ec00000000000000000000000000000000012e546ff33dee9875510a68301f46d89e6175f5cd9a6e179fb8599a580e9478fb8d92038982551dd29041d8185c7474000000000000000000000000000000000d52fb57bf2996dbbacdbcb4088df38e77e25598b91bcd5e41eaa27b1398eac150586b142f068d5b498e0ce458d3e8950000000000000000000000000000000012295e1d1039abe7a5fea51a04a34e9e8d44a0f24b8c032680703c119d54274d3bc2e548854021ab027b693e43964314", - "Name": "matter_g2_mul_7", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5bbb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108", - "Expected": "0000000000000000000000000000000008e4c57309339400ac9b6b5df16972c272d47cf69ba7baf89afa4f4e72703999c5885253cc35686f6c8d277399da2a390000000000000000000000000000000018ad4e1f105f16b0dbb4eb089c51e709c25e407e54b64346224b1abbe15d62fabb231e36a69eb05a9ba7860f772634200000000000000000000000000000000019994d20a7ecc0f234ccb6b1793fa7d1ece64b3e157c579fb05a8c6cfcdd6f5456ac1f4c1beadb69206988ab543bb8bb000000000000000000000000000000000d435e74bed382442ab83ec90dffb91336137932524bfcf9753fa5ddfe038d0b98a045c8ec9deb53172e5662d3fd67e6", - "Name": "matter_g2_mul_8", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb81596fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f8187672", - "Expected": "000000000000000000000000000000001425890b6c46c5a07a79127de4ddbb751227dca4481ab7c2f601bf22b8f6a149767c73bfbf57ee399c0f2d0b12852a0a0000000000000000000000000000000012cce15f53fdfffb5f71de3567b0c0adea65b9321c85677c574787f7048c1bb5e2dc985b65fbc48115aa129e6000fe4100000000000000000000000000000000041398497f975289fb9fc6ffe671a19fdcd3753c82ffd3b2084574107bf7fadc8de462507f4484c32df39967c3751a480000000000000000000000000000000007514a7f246006e714d4a8cbb4e89d81b951b5c41a05bcf35f61283e888074fb3686fb6ecc1a66e491ea1e1ce0738102", - "Name": "matter_g2_mul_9", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e977955054196b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea", - "Expected": "000000000000000000000000000000000b24adeb2ca184c9646cb39f45e0cf8711e10bf308ddae06519562b0af3b43be44c2fcb90622726f7446ed690551d30e00000000000000000000000000000000069467c3edc19416067f572c51740ba8e0e7380121ade98e38ce26d907a2bf3a4e82af2bd195b6c3b7c9b29218880531000000000000000000000000000000000eb8c90d0727511be53ffcb6f3b144c07983ed4b76d31ab003e45b37c7bc1066910f5e29f5adad5757af979dd0d8351d0000000000000000000000000000000004760f8d814189dcd893949797a3c4f56f2b60964bba3a4fc741e7ead05eb886787b2502fc64b20363eeba44e65d0ca0", - "Name": "matter_g2_mul_10", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a93b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76", - "Expected": "00000000000000000000000000000000048ea2c854a0df7b10a2147db6eabcb16eba340644f737fc99663d1ef26d8ed688c2baaa7d7699c5f540d7605eb48485000000000000000000000000000000000c959efb835d48d3e7a8ce643764f27c365f6248a88e39092e3a6498f04ed851c55b796dacd62ae73d7edf23aa45fefc00000000000000000000000000000000114337b8caa68cea6f22a25c0ce3b247cadae24c63fb02c6a98a728b54f97b12b1473c8e23f55338326b9575a637bb2e00000000000000000000000000000000033167b0668ec650581815cefab61d13661f4cbc6e01711af0aefb699e1979b551d0031c603ee5f6dd4f716ea7aa4a6e", - "Name": "matter_g2_mul_11", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b38173173459836dd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c", - "Expected": "00000000000000000000000000000000142f6b71471f3665ee6269cf598fc3587a62523f9753eec48a2461a2e313e376828cf6d1a9ffc9e64353c8a668718736000000000000000000000000000000000153647cc4a5aeb8ea52f845c415651e167ace9f331c1d73eccbbe20a4014f9e1158c281495206de4b841839438a595500000000000000000000000000000000151d07c3f83217e63b332a6c47e91ef2418e9c658353f8b644f23266f5fbc727562f0935b4d892db947cfbd0757ed61500000000000000000000000000000000035bce4bd2d8261e21476c325cb68e581f20513eb5e0e6a0ddbfd4ac4674bc323590b6f52d0cd50010c13642e7e03daa", - "Name": "matter_g2_mul_12", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b7010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a", - "Expected": "0000000000000000000000000000000014e83f87e7f66d8ed880ca46a76a5d3bbbacf2dafe1ee055f04af568738f4c6ddf2a93e1810b616da6f64f25c35a7b5a0000000000000000000000000000000003d14447254b61168d36f92710f95f7100cc8f278b0bc9528da763a18a5386b3f5b83b96f4dc426e4b0fbe755bc986790000000000000000000000000000000017f1a79ed64abfe5e960fda02cf3330e6ef5612c1b8639386959f86c970adb797bf077a468273d37996a65685f75ac30000000000000000000000000000000000d973499a7bf7132541c0976bf2e9bb26a2b6cfa5bda720352fa7a180a6b8fe95befcc13de5a2efe58be934cf7d8e664", - "Name": "matter_g2_mul_13", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd394c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a659054", - "Expected": "0000000000000000000000000000000018bb69dd6db0beb468242265c382de5ac342d465b5f72d4e5a24c67a48272d9a1f3af28e0bd3712e16a854c5d91c616b00000000000000000000000000000000072fbcc86b7dee9c2dc177dbabdbbbddb630c98ac3bf3737fd22f99e2b2b690175d9c5aa4b577f78c545dc6a5d2d03c900000000000000000000000000000000161c4218143ab1f0387f19bccdcd08f9caeb2d1331ca890741799ff1b40533076b6a96a910714176c770b25d2c17715300000000000000000000000000000000063098cd9d1eeb899724b40a2d10ac951ba0277db09aad639957f58541dd391fffadc5d97833bb9666b054e12debfa92", - "Name": "matter_g2_mul_14", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bdb3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746", - "Expected": "000000000000000000000000000000000e43672f1bc25e7e0e64a3fd26cb246bdbd6fb5c9084afdc87c888634916e6a6cc9a351cc67a6ac77ab8e132ed6cbee3000000000000000000000000000000000dee9612527c8ee9c574a4c51f5d3504ccf1d5781b59c78ea15294332c6acfdcc7bc68853e70f1f72524c930e4c3d2eb0000000000000000000000000000000017eba629eb14a0636926275f1c2109318ce8818d8171c69fd371751b6de47bda5b00a0b0e3765d05bab7b8dea9add90900000000000000000000000000000000052f0a4cd9b91695e1e58ead1da1480fef08cecef63896aa51ab16da373b99b3b91767a374645ac5932d9c7fd21d4636", - "Name": "matter_g2_mul_15", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca807f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf", - "Expected": "0000000000000000000000000000000019b7ea673dad96c8352870136ea262c9ed105550cb403eb1e64ad598b2145fe1b95e5d61f1b5a6ebec47568c67b68086000000000000000000000000000000000f06ff9bcf2ba284e705b12ef2311f1a9b867ed742ee0737567b5c878547b18394b82c2bb97e16586515728245692cef0000000000000000000000000000000019dfd2d8fc4f2c989c7e1016e147f336174c84d380bab992bf1adbffe96d93d4d2d1d1dacdba3adfaf283b184478229800000000000000000000000000000000068d230422006004cd88ab0dd46a84af3905c7a1d329446cc23c1c5adb401a86a9fa76aaf577f77c2678cd8de8685ed4", - "Name": "matter_g2_mul_16", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91bebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da", - "Expected": "0000000000000000000000000000000015ffdd83355978ebfc386e13987effac0137ec628fff1667ede29cfcbd05e31cf8323959dd0247c20cf28978dc242c790000000000000000000000000000000016b1f810da2ae3c2ffbb6b83c47ef03eb0f298ff4c304ab0dd7b97207949d62858458d789c86c0cd474c34fa720ad3b70000000000000000000000000000000002a2e1463d5e795e6a25998a848b079363efc7d0337c3803385f4f17f11726b04108adfd87a811d709cbb6750c969526000000000000000000000000000000000289a3f472799c06a84bb1f377a36bad910220e1017884545159fe1b2505e8e7473882fcf324ba0d9125495bcbbc7226", - "Name": "matter_g2_mul_17", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed833", - "Expected": "000000000000000000000000000000000b02ddcfbf391a2d6953261c786945093b09377352473a86cfac6456a811233809434b566b9301eea3105eb86922efcc0000000000000000000000000000000015430deba91113b841303120f0738012d77207e9408474998df5e68d0d61f1a64afb947ff93116ae766ca5325046e263000000000000000000000000000000000ab7094055919f6f707b458cda552f25104d95e4ec8d020ea4c17ac1d7efef5c4c3a769120718f1d5171eb8630a3018200000000000000000000000000000000161e7209f8c98e511a698fbf01735798cb632ae1afe00870654ffa0ba93a549edf4b97d60f03974ab0964cd39298401f", - "Name": "matter_g2_mul_18", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31d411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f", - "Expected": "0000000000000000000000000000000006cb218607a1f66ce361c89fd20edc3f00421611adc9aa52ec35d45e023174962c863f740ac36c984c2b466cfc4827a900000000000000000000000000000000152b22d46e9660da8b1be4c5b14da613731e750ff7eebaf879f7074bf3c33e1528a2c8479e0178707e3855b49f85f045000000000000000000000000000000000c928cf78cee2c8b9da8215d33d189c5636df1e8e9bdaf143aba7ed40f29490ca2328b4a20cfc56f62e4ce49d9e77f14000000000000000000000000000000001574b7a9c3931933160ad4eb17400b6297210db47bca034bc1b5d17a0cb8c41834636b9123e625e5eb0b01738cd6b9af", - "Name": "matter_g2_mul_19", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e176bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc", - "Expected": "0000000000000000000000000000000003e17452a80996203fdc4037db072c452f9eb2dae689c77c88b299d7ba266d111ab2b9c4b24149968d72cd143a34fc4e0000000000000000000000000000000014a057d7a50c9b0f34712ff8008770080bfa671650fef43c82726257da180dfb9672b266d4c54d65fdc677d917e6c5b80000000000000000000000000000000013b452c980bfc4a484637b578be100753aee9dda9487d5ee5c017c689dda838fc673804369328192d780d60a9a3de0f700000000000000000000000000000000103aa86d1807de242a6d4fa4a49be6c91cd757df5808501acfca44940733c6a524b851ac962b99a9be41bfc8d6254478", - "Name": "matter_g2_mul_20", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b712a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c52", - "Expected": "0000000000000000000000000000000007c616472f9ac60f749979c6f870b587425d514395ed07558ed287fccabc77f0c90872f3885d0780bcdfffedd124eb3d0000000000000000000000000000000019531e9c25e84a2a968a85d9f1ab61a372ebc59ba5bb7a2bbb3c0d6e4c9d04061b28fdc719735e97ccd5f7243a58cdc70000000000000000000000000000000007772d3cff12bbee916a6569edce0c6dbc2bd8a794919a4dd7bc37024c8273245210511b8f6da551fe626b7b840833f300000000000000000000000000000000186a3e858a83a7ea1bfdaac65c2df1076059aaa193961559792373886c68acd2f9fca61b166a0ee55084a6ea122ec3e8", - "Name": "matter_g2_mul_21", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1", - "Expected": "0000000000000000000000000000000008adebaa95d10b9fc0f1a1f0d52dd6741517d2ba23e3f9e7a9221039684ae226ea602dbb50df0efd44b2b5bf7495c0b50000000000000000000000000000000008e276e78ead2473602d37cb9f2f589f9c60514a1fc5c215acf487bf57c935467d29945d3d671b41a8e47c9495dbf5c9000000000000000000000000000000000fab06240cb8cbe9afcc4ebebde50c2881e4bc4d4f2ed09a1065e3620e6344fb3c5f3019250ca4edaeae4902abb7400d0000000000000000000000000000000003fa6c48ead374be1dd45c8417ca8234c15ddefc5039151e6cd7fb27f866e134cef2f59ac9b2ec1b26896eaec9213549", - "Name": "matter_g2_mul_22", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa0977064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e9", - "Expected": "000000000000000000000000000000001412bdb48546014adf3c4eac4dbe79ba700f90c8030b063828fb01be5977bd73107533a4e8030c8d9cbdde9bcf10649a00000000000000000000000000000000126d3e1006abfeddd810cb1e12c898cf5f543e414438e600ce4c94cd8dbd1e17c0f3b9831add397feda74362eeace6fb0000000000000000000000000000000005b3159638afa34f219513cbcbc51567b16fd5598b85e6ae0d232021133cec25a6269250df2ab7b5ace726e9e2fbf0b0000000000000000000000000000000000c35bfdd1c10e903da6d41e9afbe65b0cd66addd7893fde41dfda8e543a93938cdeab52cc9bbdbe61f93d651bd1c923d", - "Name": "matter_g2_mul_23", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b", - "Expected": "000000000000000000000000000000000bcc781f144bc148687875789fd8c54dd820170984b6f8ae75855f7e45619c1d2ff85c330b7743e447b5fc831dce9277000000000000000000000000000000001409aaf3c94c9a6b5123c82a7f311af7c2f60e9b197d49fb5b010f84faff972151b383a83c106de43454f8097005f6c800000000000000000000000000000000064a91226da8b9cb587030f1f4afb0d422a51e4d55212f26c621abc06fc0c57a473a9be75518a5f4f9a7f8d4aaba69830000000000000000000000000000000002cf239343bb77865ceabfcc1fe34cc9be4a1ebc3a70f16f8b7cb84eed5843524f95673b01466d6cbb0d8d9dc00793e6", - "Name": "matter_g2_mul_24", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac93176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a6", - "Expected": "0000000000000000000000000000000006bbdabfe104b62d22e78bc8f3446a86cd5f10c4c5a54501140768b55a7e6940b9952c9a90a14d8fdc7c04600195cd6500000000000000000000000000000000172e718c926cd393bf303984518432693c304a2758174dabba303ff4c0289b5bf5376b61e8821abab322d53e88f71d480000000000000000000000000000000000a2f84fbdb5b05107a0a340e81b56ddf6d03c23848448f841dc44f07cbf8a575289cf6d53986f581fddb0f2d07e38d70000000000000000000000000000000005cbc10f143a9a1fe23f670a4c47d385f5c7069d8c46580322d6939122b2d39d185d6a8c2e51e88a1d40fd2e82d08b8f", - "Name": "matter_g2_mul_25", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b859239080d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36", - "Expected": "0000000000000000000000000000000011769e191fe258ffd1922295a9fe877ad5a52fde6e343730f8f5ec6cdcd584f8ed1dbe0f55b5dd81f5f78b7437f02abd000000000000000000000000000000001253689089e9192d10a45342214425de36740c120e49f596d24658941ce2b2ecfb50e879be0125e3d159088f88e234f10000000000000000000000000000000017b642d1b5a953f47fff8f0649263f16f41a0ec0397d5a81571174aeb85431c352e2bf6bafa6894d2e6cdb5eafff16d40000000000000000000000000000000017b3438d0ddbd2ace1e63802013b5bac00d31889dcb2d9653a6f6412d157aad2fc45267322a62129087380bec65ec169", - "Name": "matter_g2_mul_26", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a39915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc", - "Expected": "00000000000000000000000000000000089a07bf63b8029e0506393828d8593b94b73c750815552f9a3c74ef7470b5810bc27212ba02ca6fdcd97e1e28a52a1e00000000000000000000000000000000051a93291d4b912f0a594d45c0264a9073663a9ec75e6ee81e13e79383d96e9330bab845fd1e5163e5b28c41c4a854c40000000000000000000000000000000016610bf2b2006207046e489294a132937edbdf95caf508f0df3bf8502e641aab9c44903cde75cff3c1f86873e06cc58c0000000000000000000000000000000005d33669fd8a6256dc55f513bb93cce8bae62a593eb8903cb7d7902a7727efb8fb4bb2e5058441c30b99f146ff5394c3", - "Name": "matter_g2_mul_27", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e0550860165061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792", - "Expected": "0000000000000000000000000000000005aa23543088a9a833d773a71275e73fc3081e13c907b8a04a330df7d6c06618fe69e644e0ee55869e364d3561e40f300000000000000000000000000000000010eef9238d2c520f32243f07161f3e35b15fc949b9401baa1a9c5df7d50b2cb3bdd237747735b235862bb57322fd9d090000000000000000000000000000000012dcc16496c95e39ecfd8f0514b5ab2569d89826d957478cdecd4e827095034e974039b37e767a0f25bf057ed715aeb00000000000000000000000000000000000d0593865fd2172ebf1b94c7511ab7d433a276bf833515146adb6d79b6e09d7c18f4c7f4d3241c14d01a4ad0f31580f", - "Name": "matter_g2_mul_28", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3fff396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c", - "Expected": "0000000000000000000000000000000015785bae0c27680cca2097ab52306207a61ba9903723f574091ef5e57c2e871e076d7f46e6e39f65a01e183e7bd822f000000000000000000000000000000000071110a384248664db46f21d87b455a3ad3c43782c68304ce17f52cc8579fb2e3378995d6eb3b8c97665e5fb7de665fd0000000000000000000000000000000019153a01c2b3c5d481474a71e5c67f27fae3232a0c8f1655ddd4da6b4c79870bfb0b6beb4af8c54aaf7e9251ad41d639000000000000000000000000000000000c58375439a93e0763467c6a11dada3e579ec53a968c9b9c1a446cf3224ea0c89c9ec218a8b78de91fc12f087e722f94", - "Name": "matter_g2_mul_29", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b2f0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa", - "Expected": "0000000000000000000000000000000004c7495c03fc3fb4d0fd4e0e660d6424de9e060eac72eee3608ba95bac294a3a62d246f42dcf3b575ee1cf8e20a9106100000000000000000000000000000000091140aee42a9dc875f87f3ba29beff95138790140f8bb522c6c15281b3545995f9c13b0b73ae691317e674295db6526000000000000000000000000000000000a945a215b2861427e0fbbfc6fea04e79edeaa1eb87df5db8e5e017cf98fde7b8d5a04a1b2129a4aadd2e3924ecc0bb2000000000000000000000000000000000a43f8d3d92a03b7bd4c8a34ce31729ea0b8e6b051c30241dca2db31a02b6e537071a914d8f0876f944dfdb613540c6d", - "Name": "matter_g2_mul_30", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c", - "Expected": "000000000000000000000000000000001821e14e70e12c7caf2a1ab651eb81dd61c4e1eec9a02fe4124abb865a7029e066f03b62e6ecfcf0fbae5151272b524f00000000000000000000000000000000044ac4a7399d6a67e7ee8cde3f5fe20b0a745462c870926f0ce8554061eba5bd62a8a08c798d8bfe30fba5567d47c7ec00000000000000000000000000000000178b8f061ad9282b3b2057f20c115c91df994ac40aacd05b7669e934bc7d650a0cd88f9fe17d7b766e34bed587ead58200000000000000000000000000000000188311eea279ddcf75f8dd82643ca3efd560ddbe6c8f2696cf7da03e65cc90d97b9f9ce99e29269644d8b881e624cca6", - "Name": "matter_g2_mul_31", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f86d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd", - "Expected": "0000000000000000000000000000000012496dd3c1278b55bde81f6944c4bdb71869f5e5e21db7b1425ea32fa1dbc8c301e7f5e68cd7629c91650265d1361e690000000000000000000000000000000004a1251591efdbdbeda21eb89165ca61a2e090a73426451b6933d939161364c4064a67a90f859a7713fb6a9c5321d5a200000000000000000000000000000000163bcd07d030fd6ab8a8e0bf39b136dcb34f03925c3fdadf55e94a90bfde0ecde5c51d2f4d06954aa6a96c913f2ab4610000000000000000000000000000000016dc065a852ef9e038d93cc583b4a71db9b96a7e7a819dc530598f1ae256368438f52e4b709f15f56279b9c7f9db8785", - "Name": "matter_g2_mul_32", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045c00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc45", - "Expected": "000000000000000000000000000000000a2397fb3a3891d1703eb2112357c5fb8acb070ba9f3a39050be6f05b49b8d2488e94adfbf849c8b4a42e287077e9fff000000000000000000000000000000000cf2c02a97addbc1584091e411f9a07135f1fcf989dfc8ae29155ac90b214ce20dc11a1fc75dfb697694891d934abf0f0000000000000000000000000000000018fd4af647bf0456aff9ef80969613829f8eb837205df552aadca46bc3bf9838e0ff2515d3fe869f80d78e2357091d8b0000000000000000000000000000000003c5671ea4723498359f29d49ebe974099da3dd59d21065a721f7a4f14dc7fb1de3a67a707bfa4bad7058312632c6113", - "Name": "matter_g2_mul_33", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820f661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b", - "Expected": "0000000000000000000000000000000000676bd7ce63d8b58cc1e5399ced9b495baba4cef9503c44760f92d6d9e092d6d5308fa88144491eda6c571a8c308786000000000000000000000000000000000605cebb4c20bc9dff0258f75a825f55f23a32cd0804dce56bf3cf2f19a3504f0345e0f1b839d4d5920aab19b363ae19000000000000000000000000000000001512f95f60a6dc79dd9261c321328ab8e22ff314e7582d8de83aa3bf280805cba8ba6d359a620fa6f0564396a45ca9760000000000000000000000000000000005837474ba78e0700c77141d70af1d8fb95a97cbadc95996faa93c2e81b7c8877d08d5287f83219a24bc0080e630e39a", - "Name": "matter_g2_mul_34", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe2346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca", - "Expected": "0000000000000000000000000000000010b2a9b32e431c11ceb474942bbbd6915a3cff64a74d67570fadeb7447c5abcf1bb35c822d4441565322ebf75e61f64c000000000000000000000000000000000b75a0212232af0a59440482a1f953cc29bcd35272ef407925eccd70c1dc4705dc1e97d2da604996d3c52155d05d77500000000000000000000000000000000018751bc59f5907cbd7f1d503bc5aa266f4109fd3133a1c4c2e58e4a17250a40053b4489da4825b4c368b0f4947baa6240000000000000000000000000000000019b41fa1af9488596b09c587fc33e044d51674eb6087c647d5a762d85e38a587eb5482687d9346a1a701bd3a8bd36a61", - "Name": "matter_g2_mul_35", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a8448639a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc", - "Expected": "00000000000000000000000000000000054836eb7ef9edbe914bc16d1498e0bc3c978bbed2518802c2f8e1c0b59fee482cce0ae8e805c33861d4cd595f6b8bf40000000000000000000000000000000007dda36d55aa7a890aeaecf2528a390c98d9ecfc8a5c78c2a6def30de55b90ae408ab770cf9a9a4663ba601c4f5765a00000000000000000000000000000000007ff7b24c8ed9fca572069e72b1e93978cea87a0fac7ba60f54aa573d881f21b73012b010e9c0fc9324aa7697bae0c4a0000000000000000000000000000000002d9773bf294efe64021e755e4dd2936a5060bbea5688b6369ffa3b94eadcc58cc3986c74ff365301be1e6c785939b69", - "Name": "matter_g2_mul_36", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e372c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447", - "Expected": "000000000000000000000000000000000902c1082ff09bf93b91c9ef5e447bd6832fec9297cdb065f11fc5ee626e6e8834cb5d74775c586609a0394e6114e8820000000000000000000000000000000018e414a40c27430b98246fef556e74dd3dd7adc601e3c05b79f8c29169780a173be9a725df3318d71b6e82abf97930bd000000000000000000000000000000000f924fa88f43c86ec98b34379b9a649c7564ef0dc596c95df19522fd50fb3a37cae031e891a7a7aa6a5e6a9062c3726a0000000000000000000000000000000006bd3340412f64d02d0cb3ac44d1f31cdb1906e56dbfb66d86b60a74cd26c1e241963fcd8bba4109c428db0bb083e81f", - "Name": "matter_g2_mul_37", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d4828", - "Expected": "0000000000000000000000000000000001415fbd8afeeb5796460a9095f14a8f3f6fe0374d4cc4160f030710a6d4d3a92febcf4dad770de3a3ba1a2efbd858210000000000000000000000000000000015792220c7e53262b56224d230a8a4b32019c77548704ec16da5ce167854305e6cdb9924c248f222d6fe95a8383af7890000000000000000000000000000000001694329d8e0f41256b703a8bb6548f1d9e0749a55c124c9b60361b4cb1daee24fcf272327ba598022a92815764fc8570000000000000000000000000000000003350658842c5b6fc5561a14df27d950a00c5bcc13d6d9d014bfd6dc95ec1a030594625f41d439b90b05275a0ffefdb1", - "Name": "matter_g2_mul_38", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb3d4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a", - "Expected": "00000000000000000000000000000000054c6cb26c8b0a9a4700e0b95348e6fb1190c577eba03a44e84fe7744c543321d02c4d8f55c03f984b44ffbd899ac53a000000000000000000000000000000000e7ab8da5d573cb88a78f6a6ad2b307bf867777f79a643b6ec89d9cb208711c85d7d2cf8f8ac69a8b322000fc7866024000000000000000000000000000000000fbc5926b9dcd9e4d1ca1a2b43dab5c98aa20b37aff0868c54441de44eb014e5283010642717fafaa95000f4313e14840000000000000000000000000000000003671ee05bc20bead72f2306203dad55cf20b13d3bb2cca079bf4391411b85ed4df55e1426645d73b6935889d4450c58", - "Name": "matter_g2_mul_39", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05541776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb", - "Expected": "0000000000000000000000000000000013fdd394635f42a926a2324b8cb870b5995772ef4e25ebc1da41dc5bf724f747da8d95a28dd703b5ed65ada5555c8b5b00000000000000000000000000000000118fd550962d1de8f1e60c312643ec7cd306f0bbcc932739270595537c8d290ca7e20b962fcde570bd2ed7ea43009fe70000000000000000000000000000000018b25fef4b75fc7649a489d078311dfb6da9909f472de7bd9bee9c3ee353f345c83119269ab797fabdbede41e0fe6169000000000000000000000000000000000b7c2a73741f6944ef4ce8fa20b2900612645c224818b7faccf6597827fa07f7262295f42be5f34a751a6400495f7eaf", - "Name": "matter_g2_mul_40", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c425", - "Expected": "00000000000000000000000000000000177d29de8a81db2e515d4241e5f7e3d35de22bbcf9aaa616b057cbf2dab57ab8d98213cdec82a2034964f3e1def8a4e3000000000000000000000000000000000a0cce8113eecb064a60ee2c470dfae8b3921f8da2c7ad8dc918b355ff44542b007add28a44848fa8d8f8671617431ff0000000000000000000000000000000010470fcc723286327e951e758fd0474de394778d0c1ec5fe6f263dea1957c60f05dc8f9d82b3c6a7d73b3e783f35ade500000000000000000000000000000000098a6ed331f03da7ccc9148f07b19b132152e15d9fdaee5cc092524b33795edf2b458b4e8383c5e29affd3f025094033", - "Name": "matter_g2_mul_41", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbce7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96", - "Expected": "0000000000000000000000000000000018a1f1a60172a65abc8f2d855ee7510c1e0af9bada084325027bd493ae86ea2c62c15ace7f63562a82cb80ee7095661b000000000000000000000000000000001736b977fb52eb1b466cec3d42df7e89047784f0e8362eb6425e37adb1e84d0438f5a6e82c7b31d59b0959a5f4aaf9310000000000000000000000000000000013ea0f849830f8e48161e840295637d8596b32eb576560289620b797b14bd395d835e8140b69039c904ef1d07a82127b000000000000000000000000000000000d7f58873701c138cb7e18ffc36cd0e47b07d70448ddd9fdc4b947003fb29cba0775916c752d531e527ab744c277e5da", - "Name": "matter_g2_mul_42", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6eac26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc", - "Expected": "000000000000000000000000000000000290fb3f38937ce4439ceaa21cf3b31db8a22f9f5ad9db0fd7d38ca978192bc05d41152f8f86ca7b2ee0bb58e125f57f000000000000000000000000000000001775913fc24699bf08f25fb946fc6527178ebb821c654b7bc69f6f86b5168fc42057a5d3bfdc53b3d57fa1ac05f7a0930000000000000000000000000000000017b9043cde8dbf500ad90463250a49f56b35713f2fd9a35d8391fc36c78c083e39674592a98cb857194ef9e73a62a397000000000000000000000000000000000e5e62e39433d443e7d2d32754d2ca2556cf6deea45e5076ac040e3d6de14e9965c53f8c65bd98ae7d17ad3a26f3accb", - "Name": "matter_g2_mul_43", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710bebba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca", - "Expected": "000000000000000000000000000000000d9927347a9ac9b0290e68143fbc6a5f4476604c3fa5ae87e729a03ca055e4c6543f9245a4592e195180d88781e46ac900000000000000000000000000000000175e0ee8de4002b18f32f70f1bfa9e0be87288cddf1c436428c2969884112bef5db19e041cbaeb23596e25cabea3777300000000000000000000000000000000074ed9e981818102b9ba818d478ba27033eb38e3fa19cdeb9f5820e59a64dc451342a160359c54bc8ec7d866b62080ef000000000000000000000000000000000a853930020bf01e20816d3aed242e00792b0d0e78fb15403fc3cc255f0dbd99ea6ae1d59d5978e562be4862b3317324", - "Name": "matter_g2_mul_44", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be1705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a", - "Expected": "000000000000000000000000000000000e9c290ba8a22f7bb3f7dfdcc9f5a221a5ce838d4fa85a00473a4dd830bacf583dd91a6a6f78d2ebb54a4c1bb217f793000000000000000000000000000000000dc51b0ae8bda6d28c51016764fc028258171d7c7646393228692aef7f1dda4a83e53553f63d6ba996d4c0a802bc967f0000000000000000000000000000000014ab155029dd35206811be9ca4efbf762a1673367e6b57528f79eb50008ce7c3b49a2d25da0ae68ac4030ab4bcc0daba0000000000000000000000000000000008cd743bb52e7908aa973c8518eaded75fc2858f4edb25fb7f2e09900f0abd3ac87e93cf1068bbe0c7d99619aa7a6b76", - "Name": "matter_g2_mul_45", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da90f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4", - "Expected": "000000000000000000000000000000001746a449993b0684740630f3f0e46eddfa135371e33e8de4dfe553c78845399e63bb3da48798b35df48d27e1f991954400000000000000000000000000000000057e0fb1113968858981c9803166d8b3eacc91bfad320ea0e610fbc5b276da1b46d74fcc54183ba61d1b2fe6743097c90000000000000000000000000000000000b3a178ae3b739cae3e80f3f44db42d8c465a5cfe4943b449d4c3b7f4ad153916c6cf4fdfece14a00b271222c72764300000000000000000000000000000000041c8b293ded0c647f2e4d6f9b35304179b723c3e6e421a5cb103e561d1655b92e74877ce22c99f22a3700c3aba9ebb9", - "Name": "matter_g2_mul_46", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556", - "Expected": "000000000000000000000000000000001103cc395acf81772955bda38f951a81c5a6a476c0b5e1543616a5a7a7be22dd487ab2a8586524891300adec5225b4020000000000000000000000000000000003479a08e2811ae9aab0301d66ada470935984d7466201f3fb28c610c0b5f67e7305f5ad3514cec5f30b51d0aae775d40000000000000000000000000000000005ea37a6d20c1ad0978da68ded3a5bfcc5ad8fe81e39b525fe7d1f2b2b1ab0be7ada80173b1d0b7fe1e06ab6354e64b10000000000000000000000000000000008f2093151a285dac511df1755e99a652a1cad0af3a019650fbdead1421ba8e84afc9eb0a4fea651f365d72f031a0ca6", - "Name": "matter_g2_mul_47", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7", - "Expected": "0000000000000000000000000000000019f79677ea0e011e5c9a892a407646798b05be05337c73135cb771abf101f450bbffd08e125f077f5ea989decc009b9f000000000000000000000000000000000ed15f35966024cf1de2926108151e976dcb0d51b2736b0877d79de81f6fccb9dd299d14855f4e257cae33ab7455b95100000000000000000000000000000000125e2fabb5cc95c0a7890e9ff2b70102a97a03f2d11d915cf4332dd049a467333e12ebb27955c0310ebdfe2afb3173ee0000000000000000000000000000000011718167000f9b749f1615610a30023db4b986364da5bbdc4506c726624a073548a94307b282590cd8a43b4900a1afb2", - "Name": "matter_g2_mul_48", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28b473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602", - "Expected": "0000000000000000000000000000000005af8fd9e79568b46fc42b2c1bac62d115365834e509dab032f66425b7a571a4bd3bf702299d3c5f36c372750b3281f30000000000000000000000000000000018499089f306b3c9f7a645ca2f9aabc4e57c046992fff87e832e21e21875c6adaca050ea8bd7043afec3a36ecf8eafae0000000000000000000000000000000000827fa0f46134e2dff80088129841f0469ec7360fd8b9864e9ed99c5fd3458e6360661ab4c671846681d491b8b823d200000000000000000000000000000000120f829e8d0ffc360a14eabaf52bc653b1e90a36c0a8af806ca745fa306a9739e31435039a377e0748caf5e80c2b0b09", - "Name": "matter_g2_mul_49", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013", - "Expected": "000000000000000000000000000000001745500b00e5ebc6f71c779ba0b0f8d6601a065c550ca19de9562455423d2ccb507e659b0dce982faa841267fb1a27d90000000000000000000000000000000009c36b54f12d130868ff9b9b61b714fb1067dc91637c09614c51b5aafa2cbe3ca7dce0f3e366d4200cbf603ad4fd630000000000000000000000000000000000172e543708bb853712d81c000c9f9f2378e628b4d13b074317e95deeae98e11e7f917f91e02a0b18cfe9b25f1b83f16700000000000000000000000000000000189fc572ff6a8c6606ba0cea7da7040898d9ee85a58f12fade8c5a22031ff26c2f9cc612bc6e1b82a0999fa93c6fdfca", - "Name": "matter_g2_mul_50", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52da9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc8", - "Expected": "00000000000000000000000000000000013c6f777df97ad3ddab9b7486d54d1bacb3b40ad3035b47a25a66c02e8866955e27a8ee52872c8222ff7466c1310bad0000000000000000000000000000000014a5eb510d7c743e824f4daab21c43db4d6de8ab2e825d13ae0e186aaba828d7b4a2343a11011a8ec4ea82f456e394a70000000000000000000000000000000017a55d3827b78a9c5ea792b705eba7777df74951930791b17ff5b861e98a4488f83007c073c3e904ed4ee328b6f6171c0000000000000000000000000000000019bae02f8d6f1e31dfa09f4feedd5217ade66f6e8248aa98b273574f72aef83d5048534ed38acab9e0eb4c64f4389af4", - "Name": "matter_g2_mul_51", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d7618f228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b", - "Expected": "0000000000000000000000000000000006490c327790b4c451f93197d7db24211a3b4b5f573a6df409206b4bbfc36bd10d2d0c989889efffd8f4daa4a68b211c00000000000000000000000000000000168f224738db3f07af77494f52ea5e957812a1acd62615f0eaa95c1d363cfceff29be9cf3be5329bb41175a0231ced4f000000000000000000000000000000000321f06b55f7dbfd4900b329c914f9ab9be2794e51e54498e18f83ece5bfd205131fbc254bfbf624d57ec2954b05f6f00000000000000000000000000000000018ec54f3e09bb2a6b112b575f9481bf1c85666133051e9c0ab53369d14eb90e27d2ed02dcda1250d5d539df0d0cda37c", - "Name": "matter_g2_mul_52", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e699431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb511244", - "Expected": "0000000000000000000000000000000001641b4ad10da5089164809d82ae47f74e27eaebffc2a2ca3c1b924fc69c1ea80ba3da78c78e86957f6a24e7f75dcada0000000000000000000000000000000014e781e4fe79ea1654460f4b0daddaffb29b287efd8168cb20d7ac6c729f684c5f2a7cfa87885accee3a797febc904c200000000000000000000000000000000001c9a44547f0c5b1f4df190285644c5a31df61e3de7da085835ebda917d5e4163f2deea9a83d641a4759fa3108567ad0000000000000000000000000000000014c3d2a79d80687fd6e6aa423257644fa5d0cf641aaf6a7c5675a810767904166fabd9a2ced0727e3badb932e46fd181", - "Name": "matter_g2_mul_53", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df12051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d83", - "Expected": "00000000000000000000000000000000129554de7de9a2b73340d94d96f0356a2d1c0524cfb007d76a75f462872e831f45553de05f5b6a1f9eeae37af7f6b4c9000000000000000000000000000000000b1ea2a649ca13a3dc7882f2423036670f68aa05792a8fcd72524420e37381a9ca80dfea701fa5e6da57afa534059617000000000000000000000000000000000b7ff27aba408f9759b5109600cff66c03cdb4bfb3dff64a4838d0516fa46bfcf429fcf9d5cbf74a27f70fdccdb1238c0000000000000000000000000000000005a99aec88967fe775c691d443e2dbd45080eec97e686ee6d7b32e801efe6563315bfafd5c7622d0543519cae4417029", - "Name": "matter_g2_mul_54", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0fb96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f852", - "Expected": "0000000000000000000000000000000007997a499b2194cab634750a189cca6783ff17d866d66f5998603f8639d2242e8039222c65b0d14001167a9b09afb58a0000000000000000000000000000000015050fe6b335884a225efcfea4acd025cfc05e8f5fe9a0e22a0c91b55664c118d79887de91f1ae6cbc081f6f55f0067000000000000000000000000000000000195b23c4c2c087082c30600ff00485d169dbd360643d163f1db363f270cd7d4f177c36b4c291d50da4101e67b229d0de000000000000000000000000000000000df596ba2350ff7d3e75b4cbe5f8d6b2cc0e14b3bd6dc021936e3371ba64031f6266fb1d2951801309f22bfb1c4b27e4", - "Name": "matter_g2_mul_55", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a3378176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c", - "Expected": "0000000000000000000000000000000001fa243b548f8f5c2e5d7736ca6fa95b74dbfd31f95fd532b94f81a255c73e7c0e000e20f9ca6750cb0dfdcd2c1aea8a00000000000000000000000000000000132a893a2326bf61962e1855331a53667e6279ed7358bc84c4a7c218b6cff1d3f449954f56daea72bc2779c60f1113400000000000000000000000000000000000091dd23c75dd8266f556bf27ba54c95c3ccab06168e4e6d0747239722afb20f3db27454c6db3a88daab0ef10659a66000000000000000000000000000000000d3b2e3fd358aa3dae983e87b5d1fce6d5688e66ced6e3a2c96b8d48041557295d5932af6532c13965d4b383fb252518", - "Name": "matter_g2_mul_56", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a69c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da0", - "Expected": "0000000000000000000000000000000005095d1becff61df906815842112c6508d6cade4ef5f4b7418f5f01e8c5a383addc1c572237613dfbbb88bcff80e4a44000000000000000000000000000000000bd2561e7bfbda8a48ee038855e37b03fee805689452e9afaf0da4185e0c194e407ce7149b713c689d25f953da36dd1f0000000000000000000000000000000015ba3ae4d4238175425ac5dcbd9e6e9e055b8c1b7752931b524fb546f7bee8723ef2e69351450c6d1ba3c366a22355e20000000000000000000000000000000008c17d77dcfda00a1d75ea0087c58e74263ce5ce4066e979c66397de8e236708831c3a9ca6b35ade8038a28930655eb6", - "Name": "matter_g2_mul_57", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f2542ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd45", - "Expected": "0000000000000000000000000000000005cabaf39b93d7fe15ef6a7a3031df58219bce702a5a77162551a3d916c22e8ec9af2aa20659e7c4ce5f6382a5f82726000000000000000000000000000000000dcefe1a48d8c239164b54771118f7520ac11a7a6b72d8e17be1cd788cad2f26d3a0d9113e6536426800a744be9f0d4000000000000000000000000000000000199d95a44a4334c87aed273a0184be9602ba443d5b8d34f3495b04e927f4687fb88487f586395c7babb4f218fdbecf8c0000000000000000000000000000000010972032f9cb3e8f45447bdd06df82656fbd3ce38a9f7564c6e5d62ea3596c9b7e0a94046f1c65bf0452ca25b15a885c", - "Name": "matter_g2_mul_58", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c56fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f", - "Expected": "000000000000000000000000000000000f250b5e47ef616be106a3334e2f516061eec8f7ac69f08f6dfaedecd76fb1c9685ecdac2c3ddd534e3947d007ab177000000000000000000000000000000000073819a6de38303725aa3a9e5a7a9122b4d1e60ee8deb3554b5e06ef5e60d71517c2279c5066af003b32cdf83b7fcdf200000000000000000000000000000000070721107ac6dac198f7ed1a7f84697cbbc3199a220d1aaf82e6f015963bad863f99190f18a482f730254cef753ba22d00000000000000000000000000000000169910eb30b8fe1ad8f84c4a132c6c74a6ff06ed6e792af3baa6619e3c8aa6cc3e6f687299467ec9554f9e91bee77aa8", - "Name": "matter_g2_mul_59", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87318a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d", - "Expected": "00000000000000000000000000000000106e892e336b2155909946ab73b980ea761cfe8c48b13ae8a5302eacea08b9cef3e60d5b33c6ec4033218ae5761433dd0000000000000000000000000000000015daeaee59f3b4cc26d3da745661e74db8fe1ea115d50ba49ef5e6151a9ac2f3135f0232235cac7a53e1e8a70eaf0476000000000000000000000000000000000ff494d17c735b934c2c7fb8f413103188fdb116fa8f4d4e43262968ab0fa1bdec23b0d4d8b1c2defe624092de36610d0000000000000000000000000000000008f70b7e9f2d7083774fbce3bff58a1c73fbcbcd9cb049cba71c0c3f0c363517c8956240bcacdfb7934d4c67b1bfdd2b", - "Name": "matter_g2_mul_60", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab7196d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a", - "Expected": "00000000000000000000000000000000098f32b35e3b7dc1862ca1ca3c76d009f016c6b91c227f2cebe8f1fe87567d936bf1c54103bec31b3552c077c0242fb40000000000000000000000000000000005380a66d48d348487624a15b63d2ecf6976b5b599901101ea8b1f57736649b4397f6679ecab0ae29573695a921ac475000000000000000000000000000000001710c368f70a2b9cc92ec65c4c2ca35fd63440eb350f488e7c6646f9c42bf680eb62a887d533a91e47988221b46c868200000000000000000000000000000000033c3327da938dbe4630dbe16838229d7d427f3adf18dee6fa26b1c8067838922c1bce78cce08d590ee1acf2baebc7df", - "Name": "matter_g2_mul_61", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f2dbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997", - "Expected": "000000000000000000000000000000000404587c60a4bbd8b5b929ca2ec2a9ff2ba4733f4f2877478a669b238d65ca130cba398899f2910d6de04615f8ffc99f000000000000000000000000000000000940659b3e6de7c3d8de9169a28e68dad433bda78de0991fe4a1d404e5f4babcba9d57c7f3d638aef264642f87c61fc8000000000000000000000000000000001676ce240e1ff70ab03f94f3ba3acd31725ec306ce1fd707e29ec22cf91746216dd998d03ba13a79dedf878fae38d68e00000000000000000000000000000000098a81422511f77191ee15d402614c86f9447ab78a89cc348414108f36857a1929f2b92ced78752ab3604f276861803e", - "Name": "matter_g2_mul_62", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a", - "Expected": "0000000000000000000000000000000010a4ba6952d22a51dbb6762a3f9bd09712c2be5a98bf0ef298d7a7e3a9735ab0d3bf39e40b334895c73a36c218ad24b50000000000000000000000000000000002860f38ef61b497bdaf4faeee7b406007981c17246cfa36cee906452ae85e1c1c6385898ebadc3b4ef8887fff25b8240000000000000000000000000000000002dbbca9034fb17c3f37727d44c027cdf47c36f3f628ea9385fc9fc371d23f22d983656caafbf1cd1f8bdeff4ad7669d000000000000000000000000000000000b7e71b65765c4113a7884771952268a9fe10576f745038912e6877c78372cd261220793b888c43accba1646e902fe14", - "Name": "matter_g2_mul_63", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d", - "Expected": "000000000000000000000000000000000e9c1a6d591be4da37fd6dc283b8d899b625ccc96371dd3d7731aca66cd2a978810497171f2aeded64fa2b10e480de2100000000000000000000000000000000006d2ad7287847255002480627782d513eaf1f68a3d583d4762fc156b8eb40deae6969fa8a7d8f8aae923800091386a00000000000000000000000000000000003c7eae0eda08df9b9eee2605a44fbb486e3bf2e409aaa1c8f38c06f969ff1f74338004b01288dce99be26a837e45d3a00000000000000000000000000000000178174d2f569a9392eddd2715ceba8762c5bcc6325217db5e5f970d6fde069d0e48a824e5b6ca017891de175c92f6b29", - "Name": "matter_g2_mul_64", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e3616", - "Expected": "000000000000000000000000000000000ce12c9010b4c4afbddb459c1b46063a8488277948188b4ec0b739e1cebb5653681d0e43a0d2c6b3f842bfc609bbdee3000000000000000000000000000000001123f60cedddaf4385e63758d64d4facdc443854176ec199ca0df0a9c258517f2512594f2441a4b9a68aa9a2b4a1f4bb0000000000000000000000000000000007cc6f77d181d13bd9736ee23a33b25b0bd969760642ee19004e095ebb8e2b3c0e09321eb15a2f7961803c0fb10b6ffd00000000000000000000000000000000004d8dbf2f0c14b07ebed2b9cb4bc87df78ac8a34ef0b05cbc2c6fb8e8156415399fa52dfb968ef0e6ec697030fb003c", - "Name": "matter_g2_mul_65", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad3a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af", - "Expected": "00000000000000000000000000000000172805bc715a8cfb2e25c384214f4005aa6d3b809a0ad95322209851ef92151526a9d01a914c4d7f0c120b9bf3837010000000000000000000000000000000000473ceaa092a5ac12f38b4065477672deacc08e553d8e9e6391bac0d9ca50015934cdbc340deb05aca916cf50c7915b30000000000000000000000000000000012e85461fbd26c2d0235acf5c8665750656819bb939e8fae77a8d526ca23443aee395a985cdd4b1eb700311fb87e91a7000000000000000000000000000000000246d45fdd88448c93bedf4799becfc7c80e67abd483f2a0aa41e8bbb3f38cbc900314436364f1db6e1d88595544517a", - "Name": "matter_g2_mul_66", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0845111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145", - "Expected": "00000000000000000000000000000000122e1f2081cbde0055fc34d2fe61307bc333b35a1e0772a0cd6fb25338c89824bcf2f066bc7b571b2fb314ca7f45106c00000000000000000000000000000000027ed81b54372d858a6ba2faa65fdc132efbca6ddcd56c3625bd9267cf0ae04f6d342209b995060f584be8d40020669500000000000000000000000000000000002a03427a093a3000a1bed9eba91a82dc2f2fcea1a16a1fb8af29c4988b589abe6a505ec87a82864b3c683beaa6420f00000000000000000000000000000000134bf64871d69a72e42766c2903fb4589b84d7772a62f7d2f8f8d02a914f4d3a278c680c626ef4d69de8aa88b57589a7", - "Name": "matter_g2_mul_67", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e109c07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a", - "Expected": "0000000000000000000000000000000018fa44efeabbd1cc47dd9b1a1195ca921c99c77ed43a44502aad27b6c663f5ce2623382c3ddf208f42e3eea741281f4300000000000000000000000000000000138d11e497e3c5656bc8fc0ae4322a0bfb6fc20e249a47a103b164aa3d9fdbf7df4b1e3b0842b4b12568a31992a151f000000000000000000000000000000000182490d6ae35c1208c0d608984df4988d057f3ce5a25073c77cd5b224a5892768badb1ad5cef8f41d1d2022573098c320000000000000000000000000000000002a6e0523781ccdebb75063dc7ad1a9526f9ff8ea1364bae487914f254c0eebcbb2cfc3715fecb9599bfc2f5feaa62d2", - "Name": "matter_g2_mul_68", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c29b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd0", - "Expected": "000000000000000000000000000000000dc7488491433d5b3924105c01ffed4f30b755d7253d867fda595e7d80197823e56e4d182d5ecc72d8ef1ba9bca15a310000000000000000000000000000000007bfeeadd6fc468ef6340a2b394c155bf50808cb11e89adb0de5499fbdde91760e9531c1deb23050286a15e5910f1d5a000000000000000000000000000000000f096db706b08485fd577f37b7bd232b5a10c3f80c25bcf82f7a3b666c6efaac8e856bfe5f7dafb7457e33eadcb4133d0000000000000000000000000000000004460d1f25159ce6df59efbd7c693355af4634dadeaee2ced68124b2a887698c10e9c4b40c4f4f9c8444acb881ceff65", - "Name": "matter_g2_mul_69", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b2263d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258", - "Expected": "000000000000000000000000000000000f1aa4a7a22c568c41270d24824138bf9ffc763a5356b7c0bc1d051a0a0db12616700d9214972b63eeb2a398d27dc83f00000000000000000000000000000000020d0c2ff8f93db6b415c2a01712034e46bdeb6e665a5177a3877db9f5401d3dccb99907ef843062e394c1428983725a00000000000000000000000000000000088abeb6fc3ead45d5b261b7d684f168ca8f5f163cf338863e6b102dc40e2cd0ede97c47460ad6f560c27e95c8b71ca8000000000000000000000000000000000ca2e5cec212d581c737928512118e2f51a0d74070f40a998b7b06d22b9fc754bb2fa5499308058be9ab81521d057414", - "Name": "matter_g2_mul_70", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c67a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e", - "Expected": "000000000000000000000000000000000cfa23c46881893f6c50d238a83669deb520a7fffab4f912f77df7cca43f6827a1a0ae0b3f36c8f116ecefa33b8bf37a0000000000000000000000000000000014b7e5c18d2f9bfe15b0c1af3bc6e230039a341e135837d123e91cde9cbcda298c66b93f692232c912e5d7d3d6331c430000000000000000000000000000000009c8984999ecd3a4144ccb925d3e5cae5c1662dfbf8871013b1cb2946482fcb075c489c61b8d6261f2574b44da3fc1ce00000000000000000000000000000000196e7feab383211e4825cf98219c63bf9f45a72d66030219cb585d5d25237a01a97f00e122db6a51325022e69e7d8cdb", - "Name": "matter_g2_mul_71", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a81b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83", - "Expected": "00000000000000000000000000000000005c0282830934ea09c9f51b52cb6dee75b874b155c63076dbac2cbbf220863d55557ff1b7d681fa185435df1522f49d000000000000000000000000000000000a1680ebbb185c8e7d8a197a523a7a5e618f97c46670622034d312b3eeef140150e03b00ae3dff8d9f1d872f3d3dca380000000000000000000000000000000019bd2eb4bc25f5aa6bce206f0683dbbbbb002098a118fcfb060c1353a310c2baa1063a782bafcf6ff6bb8edaf6f1597a00000000000000000000000000000000082edf49a0435e0b9f3dc7f207711d66004ae688b18f5b62fd1596899ee8edfaac7da38973d81f12200018fbe8151572", - "Name": "matter_g2_mul_72", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db1ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de07", - "Expected": "000000000000000000000000000000000b8a715c1c2792a30f7ad752a808b621c34af1fb7f1e3392a36ca9481a019108a21e3ef338a1d05f2f23ac3e2cc42ed500000000000000000000000000000000101375c9de592031c55a7a62189fd3fa3c565abf7c64724796dca3b1c7a6e6834a16ef1c4e2afd6ce2e69487260f0028000000000000000000000000000000000cd385ec8245431d3b1aff88453db7f66a5d7888a5c1e0dd0abe9ac7db752933a343b8be53b7bfffb704768ef0a3dc5c0000000000000000000000000000000015d55c8cddb8715e25fa260d1e1fa672ff76eca7c80d19d00678fb9d08759b810cf266ef0a7e9dd749a576ce07240fa7", - "Name": "matter_g2_mul_73", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b6", - "Expected": "000000000000000000000000000000001311de31229f1825d0bd2c9d726fd71e05828a20406a4705ea65f441537486338022bac4e552bf3c25e15717bee00ba400000000000000000000000000000000052e082cbe36c854a028a041981fed87d39fb218a88208aa1096e260a3932a1155db7f306c32d133070b0a5bb6d161760000000000000000000000000000000003269d4afd20002873f4305018a4432c1925eea28486d657cb458198ff2df9d304bdfc7455233243b1712d8663591d460000000000000000000000000000000013376fb98929cbe7f7d090d1c9d5c4f6332bbf25470aa03c35a70481931e4bc91c937029a5e11d2a3418eab698361227", - "Name": "matter_g2_mul_74", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296feac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c79659", - "Expected": "00000000000000000000000000000000021166263d1a443d5b2eee9aeca3678ae4c2b44d556a7cb9631d47e4fa3bb05ecb94d6582f4ca0cd787027fb5f2efab60000000000000000000000000000000015335d034d1a0ce78e1246a16e35e0075f73d4a392da1e05c11388084cf80bf31d499e57c48f4be6e72d3abc7b387ec6000000000000000000000000000000000deac4ae1900a4e1814624fb4b8c7a3149fa9cff2ca97f02e7d6765e034a1532a7b8475ef7aef5ebb851063cf4b9e79500000000000000000000000000000000161e3af03f226278a07ff3b08e5788f6c5029b2c8293e7a7e3ae11c4d78676b60dc0208cec6b82e1714d976007fbb389", - "Name": "matter_g2_mul_75", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb5198586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d", - "Expected": "00000000000000000000000000000000120b4434babedbd8ff295a6e2ed5fc7af0548d7e60663110050be797584c0cb638988201ae7707cbedf0c8b3dc5ced85000000000000000000000000000000000d2de0a260bdd241a145e3f68a6de48da4c65107a500e02bfeae6ae7dc428026c7c3e9bdda9a3069d2744705df2eda9b0000000000000000000000000000000018a237906c0e277541c4f00c4c2feba7cb2c9b87709c18b62b7c36d78fc118cfd65c127765e01dc0ae5875b9552bb45300000000000000000000000000000000197485daf54e98e097b6bca24b0738682969256decbf3ebc05f6982e4608829f37e2877937b3f26b88efc3deeb4bfacb", - "Name": "matter_g2_mul_76", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d6e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712", - "Expected": "0000000000000000000000000000000005de82540aa67c69b962d292133b09e6593961da8944ce02557141abd19ac471f766b4083db85c67a44b65dad2202488000000000000000000000000000000000cd999bf3cb004074fe9f355cd8dfaa7b9d3439d902fddd2fd0688419b5b7f8c4300ab26b658936a90c0b8e1488249d1000000000000000000000000000000000f97ae779429a5afaf7a3343586eea84a4e76f00a1852ce42a4940babd565bc8d61bf72fca9b123922f1ccfb1db8c06b000000000000000000000000000000000935960fa941c27e74234a07857ee680f53c31047235c6152d1669724bdef37ba642cf4e0dd355443ea470e6430def8d", - "Name": "matter_g2_mul_77", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94685cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a72", - "Expected": "0000000000000000000000000000000001b0aba02b0e907c03d2f4003083c824ce60f2f55f70dc6ec7c7f81f3d0ef4bf533b4c94833e36e8aa7aeec18b7255de0000000000000000000000000000000004fc227a6ae303f3006f75193cef7c653e6bddd28fdb843b41c7d39966a701ba8fcf611efa71abf059d7d98833480e69000000000000000000000000000000001077fddd0bf3d5c80eec653916f9095e900cf165315d74a872219285f62b5412536e43c4cdbc120ec5c7753318852dfe000000000000000000000000000000000ccd90e01c1d4a00f0d9e29a88e8134f2cf68162da66bd343645a998730190114a6921c9b048dda58b60b42a133287f2", - "Name": "matter_g2_mul_78", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6", - "Expected": "00000000000000000000000000000000185520023714580a3f235e24316478b8260565ffabd39670811519066844e131e337bd62ed2069bc6d2305e6638e539700000000000000000000000000000000055fc74cc7cd3fc393d5b5ab2419414effb783ff4da2516e5465a4acc195339c7b5238be4e0744b3d7fdbce46ca7f5dd0000000000000000000000000000000005f584a0311c02d611c15163529130a2fb3dc853083e7225b791ce5ff32d5ef7039c80edfff317ce9ddeef84443b5a51000000000000000000000000000000000f9d5acb355f767cc6286cc09f6df232532f9a0e9e4ed1fe28788abecb200e22066c23f3ac6c49c47071cbb023e70183", - "Name": "matter_g2_mul_79", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d7535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b", - "Expected": "000000000000000000000000000000000ceb56d75f3aa1548c50d7780ea1e33c3d069b2f37e7f96be6a8ec03266fa8d0868822afb3b2e54750722266f6032a8000000000000000000000000000000000080f15b7f9f2c22f1afacf558267b5b84f3a6d199fd3349eefa2e46c4f332849c0955d19d4513151dc0f3b566c0058440000000000000000000000000000000013305f8ff6080f7da05c28155c0c2bc1c78d855cdcff0bb2c6b82cd5107d7a070d0830e6705f6832ed5baf75a659c8870000000000000000000000000000000018f4e136859b4ceb230450f9abde0325a4d59db98279d7fbab710305ff53250dae1c8789cccc27586c9b9df5c0c4722e", - "Name": "matter_g2_mul_80", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d52756e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a4035", - "Expected": "0000000000000000000000000000000002a0214be95f020c70221fb4fb6856af7ce3845a4b607340f85127b52f8a204efcd94a152835860a4ddeef84946671b1000000000000000000000000000000001767777740a9922a91c39a36e2cdfcd544df902b31812ffc88418dab7321f73406ab142055b5bb264c187f2d4f2d6f9d00000000000000000000000000000000026e6941364c74997506df0f9fbe6b2769839e8b7c7293f4e63d13bd7bee90ff779cf82adc2f23c569d1e13826cdb0e4000000000000000000000000000000001618ab2ffd4b823b9c9776baf849641240109b7a4c4e9269f3df69a06f85a777cb4463b456023b7001adac93243c26f5", - "Name": "matter_g2_mul_81", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae4523a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff", - "Expected": "00000000000000000000000000000000054ce66b9b0b3cff6637d6cfdd788719d4e33516b98402d8fba54725309307711fb576299ba99104d4e7df0deac9ea2500000000000000000000000000000000055e06ff52cda9116a98ad3709f788d39db53844b7db58a57af52848ce1c59ec2a1f083efe79c5994b9291a2d1020fb900000000000000000000000000000000040c9ad63698ec78d06b41bdd6f5eed089b67f106348f9300f822a2d61ea1e5d2ddda0efd1025825c99cb0e243573f7700000000000000000000000000000000195dd00c48186f8d1337ca857aea02c4d199d638133e9cbd2dfc5f633502f656343746ec2a416465c3c0d4e9d53fd097", - "Name": "matter_g2_mul_82", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627cbd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b", - "Expected": "000000000000000000000000000000001141b59af8fe6cafdf2e247fcb0ee4642a9b4022b6d71163ec9b6ac2f7d10ee3c5c0173ac686b03cd6a7086b039ec786000000000000000000000000000000000f05ba6973c5d865ac5c037583b65eb4eac826b5a04a7ebed1e10bec6ec7dca93b1c2eba70ee0189fd552d5023f2a87c0000000000000000000000000000000002e54475940985ad2115223c5ea3a4c95890f3e9992e3e1a6df2170ab77143bcc5d29b9dcd1ed3bf16e545e9be21a8640000000000000000000000000000000019acc4705955761518cea482b83e3726dea8d1f66a5f19b06cd7ff95828e15d1b139077e0d274b0e6fb86c027844d97f", - "Name": "matter_g2_mul_83", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ada300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d", - "Expected": "0000000000000000000000000000000016fb5839fde95111742255b33f040c41dbd0f142d1daa8abc7c63008ba9f63f07381d9d6128240ae9b6cac5befad84e5000000000000000000000000000000000389a11727c356b8f3bdb6a73bc2f6d2d73d33d287365283359521dcac64f17810bd58c0ec5bef4db253bf630bdd9599000000000000000000000000000000000629a8af1bd0c1b1b6d7e447bb779663d7bae8e895e09418bc350e644d7022fa877496f30e2018f5dd1c9683b2715adf000000000000000000000000000000001950185d2574fe0c8277e3f93f59dc5628ec3487911ba9c3194a2f716116ff0bb9a39dde802dcfaa61633ad7657a578f", - "Name": "matter_g2_mul_84", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa833e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b33", - "Expected": "000000000000000000000000000000000024c03edb9b54034eacca4b321d51397348c57f406b074b16a9d6215e03f842380f5358f5c095fcf5bf3cabcbabdc260000000000000000000000000000000014e62dc442135d729f65090475fb408ebae132cdf2c2932582af887ed54696f3cd15b163f11285b99e8d8f809aa2e65d000000000000000000000000000000000438a2c99df216c67d92b99d9ee8cbd0e9751e538074d146767bde9675ae3a05bdae051efcdc6bbddeb1b7a8288370ed0000000000000000000000000000000007c462a8f5720e442e1917bf75fc3c3dafab6c39c80d0b93d81d1db4080f6e199be092b4b025e7b02efce4f30d00299a", - "Name": "matter_g2_mul_85", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bfc48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f", - "Expected": "000000000000000000000000000000000e8137c15436264b5960c27d0c22be7fc5d56a12f43b3832ad0d7f5abddbaaccefd140e2f7c476b99e6fd9b3a52743600000000000000000000000000000000019ee3caa56f0329a2e2acb8907b3edb21f4eee73e312352796b51282e097f9b10af61805d5c222332888737c7f8e227d0000000000000000000000000000000012cb9c610391940fed7882a5cba08eba4226c36eca8a2ed22fb5e752e0a1a5ec556673e47013258b499268f1de77bdf100000000000000000000000000000000031b769f606fa25b81a982db86a1cd442ed738019e7e64728ecf485cddcc17d9dc271146196178740b9f05f56627b061", - "Name": "matter_g2_mul_86", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e844228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c", - "Expected": "00000000000000000000000000000000080807a0570b628549629d2eeee39de773badaccefb76e01efaecb0ef0356f535d32c3947f0613bc7d847ef8c8778f02000000000000000000000000000000000e8c091ea30465d204ace72015cbef29645206390fd92ba7c4aa0fecae4ecee53c0b06e1fece99511efd8c7e9cff1a8c000000000000000000000000000000000c881c678c94d80164bb3295acf4341fe6c726ca64a1a015c890450e719b85720f41f80369f99ad3e7e3169ede0113e00000000000000000000000000000000008a2fe01a7100afda40091eb0b2b14cd00b7a4d8bb5cf9d9a3847970a94f2035fec7f292c04c38d7e49890e612830aeb", - "Name": "matter_g2_mul_87", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbea417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f1", - "Expected": "000000000000000000000000000000000d17f6d9460566d0543df2666d6ade685565e668521a87fabc58148343085415fee92c32907311c9d04713c34bf7690d00000000000000000000000000000000185da28f07b86885031ff5cda913a85b0e4d07673f456ecf2a9f0fd1b21d99e22442f9b705039252d57380b6a42912050000000000000000000000000000000014a4bde5973ef43691b61b3c0f6c2fdb4bcd6ea88e53e2787a7d93ad6e05ee2e69f2799712520f72b3c577ee278008ec000000000000000000000000000000000d92a565b3d8d0fded054a75198b31c521e3223650cdf762fbf7b851f7ac0fc66b8c86c20b905117585704c23b27e7db", - "Name": "matter_g2_mul_88", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba846561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb", - "Expected": "0000000000000000000000000000000008b1ebd753364a5a0a6296ab48b348f91668525c0d5f7edc4f2d29844592f34a209f9e77f94ebb38ba76bdb3f96063ec000000000000000000000000000000001062e0ff0a67372207052e2520d8b2823764a5075c94011afd6c60288e187ec77e08db01c95dfa195f2409b58c9dc4e5000000000000000000000000000000000cc2b87b613d97a716586f371c457fa869c2b8d1fa1cf4b9e8c34bae23e0544752b997df4711d0712ec11d3a9d96ac2600000000000000000000000000000000140eae891c87c2026f0b1293df2bd8ae2dcb0ab3f8de74676f37c905334ac1f53fe4b75511691dcf108fca51abcd524c", - "Name": "matter_g2_mul_89", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591ccf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf", - "Expected": "000000000000000000000000000000000276a138edecfc9378be4e241d64cbb48bfa6fd4fb1788f8bda870d5ec8b2132fc9ec888ef84c43a50b7de0527def36800000000000000000000000000000000153e90d52c747859f88223555bc8bc4e8b6fc846fe7028de728a4dfa085c6e350f9f1d12b9dca4ca8e07377648544400000000000000000000000000000000000cef00e7217da6df0a6d85f40be69f154300c423e86e54e513b2491e65002e308445238082da69aa9e5e83b5f4fc17dd0000000000000000000000000000000008da1da2a0d1da9d2158b9408dd9b0eaf414d237b8219fa7661e40c1a88eac2f9735d0dd6ad67b85aab85952369e8287", - "Name": "matter_g2_mul_90", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff2f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5", - "Expected": "000000000000000000000000000000001484993096c210c7bebbc4c0bda24b44a70e982b2528215c0e8578ea55f1181472758caf935aa0a3d6820cdad753e2f90000000000000000000000000000000011802324a6e03c3174bbe7261ecf3812c1a97e1be27269214f232274a3bf82775d47c5fdd70fe1c57155068b296d394200000000000000000000000000000000050f43c874c1cfb5fda81059cb7b4808492632fa20369dcfb611e503ded81a49dacff253e31d7e27ee84bab79e3c5d53000000000000000000000000000000000ef945b6f210fb09bf0ad5bbd4b5a6630f43304ddcb396807c967eb5146741f7432bfdcbd7e5f3d29917781efb62e6ff", - "Name": "matter_g2_mul_91", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5440ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e", - "Expected": "00000000000000000000000000000000028233bf12e8dbd8510f119be30ea1fc13b755c6ee3ca2a3637a3bf8f73776c9d1fe231b713396ffc579ef9320a05b150000000000000000000000000000000018e7c00b8047d64ca0c5df54486439c5fb3d1414c2f71cf8a3ed591b7c45bf18b37473daeeadcb625eda638885ddb9870000000000000000000000000000000018b89c9b6bf9ece36f1eac08fc35ffc9f7f964a0a9b19d495ae1361fb4bc98aef8770efb47d9961aff694b878d659818000000000000000000000000000000000eb2fda2c29c6761e35ca4c9772bb232ea0d297582af4f50ef76c0b74fefd414b535e356c069f54ef5224225e95be6e7", - "Name": "matter_g2_mul_92", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a7ae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be5", - "Expected": "000000000000000000000000000000001239935827fb2a269ab064a3ae2bff2555f89bb3a71a47ae815ef755fc1363a89d20326855cfdd0e13f6c85f727bbe120000000000000000000000000000000012fbba047478b5f5b07a582200271a0c331d6f76864f9b6c6ef8ae6b0965eda481eddaf72c7a887b21719164c633d39600000000000000000000000000000000017eb4353b413437244983554a639a9253d105395ff9652504df7700d879cd9a32d5f0824b1eaa532bcf2fea34f8f08800000000000000000000000000000000054ea45475c01ea0557fd143b21c7bdcab6d287bf6bf4f88b6fb06e02ac6fc5ba96f323bb1fda3a1c4d8f42d01d267b2", - "Name": "matter_g2_mul_93", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa21268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c0", - "Expected": "0000000000000000000000000000000015a145e379b7ecf4566a039b753f91e8ad75d9e9c9a20725ce34a900eb9a1bdf66cabee2100208d7792a963d1fb8c02f0000000000000000000000000000000007f0ca14fc4e34bbdf5008d632dd112c7368e037ce019b7c4ec412000ac02302c85ae64f9ab495361fa5b620e46420aa0000000000000000000000000000000017c00a08bba18426dda40e773d79733030b5b3b199a62436ed06b773fd1f10688e8af00e8a223cdf242bd1ebbedbf634000000000000000000000000000000000a17365cd9f7655793682b72e342227048da0cff88f6ace33ddab548ba126017e4b7f7439373a893e3b5803e662814b8", - "Name": "matter_g2_mul_94", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99df9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169", - "Expected": "000000000000000000000000000000000081b4dc78b74250a82da9d803876add659411cfb467860b2ac6f0f68929d6377deb71d6acc9ea8fc8c1286b8f92056e0000000000000000000000000000000002c5fde71346a255ee9dc896f654eb2e0c66f4cb4c51541d2bbccf2463ecf0085a22b9d2bdc5bef39d80c4477824f116000000000000000000000000000000000ebda0cd8bf6ac7e86a1bdbe44ed1e15f8ffa1fff92afd67fb564306882f35037b61cf0d93f278f15149c04a2e83041f000000000000000000000000000000000fc38aa811f5ec015f10a99bf175f1479d4983c9d2180a5e3da88b4e9b62ef50560ff0a6c2fb7bda4c46c54551f8390e", - "Name": "matter_g2_mul_95", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b4", - "Expected": "0000000000000000000000000000000007b46fcfb2cd8efe32754306ff2f503d7434168c1c3cbd7c80470cc5a5c8bda10a80bfc0129da349724d2d6431c5ac90000000000000000000000000000000000e1078f4f4ca993d90accbfc036219507bd22d00930ffcfe1227780c00914fcff845698b2541510daf59cc83d8b947e7000000000000000000000000000000000b7c6d9951570e685d3a71b19a38f5485f974f85fe8cd4b4c196d33a18750b278b6d374483d81dc3e15c9b8b9b5dfdd6000000000000000000000000000000001003a239ea4a2f213f0f646bdb62cbe4f98cfaf7298d8b2e0eaa07bf3f939e779caab5ffa0033467c5b297166df657d7", - "Name": "matter_g2_mul_96", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e74d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e125", - "Expected": "0000000000000000000000000000000000ea29b1e059560fec21c3692d4e632a45c88a807c953fa23dbedb271b049d7fc717333b498ed12573a896f872e795dc000000000000000000000000000000000de0d10c47df92010a6635e3403dd6e91a1bf35bfcae82c1008998e86aa2d18a6cfd3f2f1207fde3bb39b723ec4d3ca60000000000000000000000000000000005e2aef9cd37430b15e5e76b2c7870630d255f630c12e865caefe308a39833e00319406746dbb2af3ed32135e91eed49000000000000000000000000000000000c229fad41b0d27ad7b5db33188fa70b97f22e323e429ef65fcf98f5339e908c31df8859b863356e0fc90538c5c49cf2", - "Name": "matter_g2_mul_97", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d553041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b", - "Expected": "000000000000000000000000000000000444a00cfd258bd46f659b09eef17be9929008d3d1c65e46cdc762eeaa2f0b52abfd636e6094e21983fad8171194c71a00000000000000000000000000000000090833e68614be5bf298e04e44527480cb35128bbdecae15eb95d6931a718f66869ddb68352130b4dd8a921ab3f26d080000000000000000000000000000000000994015b1b55340c3839d48320d178b2ffaa0bbff038f7aa63d4dff41a217582fae9613bc537fdeac8d0670c0cf479a000000000000000000000000000000000fc486e2a1680c10ca28d4c3bb22dbccc9572036512645bf868e7693ae4591569c973f9ea26342a573e23a06c2fb4b70", - "Name": "matter_g2_mul_98", - "Gas": 55000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db47cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf", - "Expected": "000000000000000000000000000000001375bd5ee66c330796bd8381a26cefa3f40f8cc8de42d4d59a7adbcd3852e6d632422e6ad9a06a6e497b23b17b1df87500000000000000000000000000000000165d8e7be17ecae9bf51a773da705aea42536d0fa3a2206267da50451f5104ee241811dd0e6710a80c38df77b126c009000000000000000000000000000000001559572407aff34969f83c394d2b095a7ae9f53a8e6c923910f256bb87b6ec076fa6acb85465102fd24d34031f88f7510000000000000000000000000000000015ff9ba89b55ef75f63732dec1e64106d7a912a6657fcc970dd011a03b5364117cca46d6cbafbc0c5049db10fa83fe6d", - "Name": "matter_g2_mul_99", - "Gas": 55000, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsG2MultiExp.json b/builder/core/vm/testdata/precompiles/blsG2MultiExp.json deleted file mode 100644 index b5b63625a..000000000 --- a/builder/core/vm/testdata/precompiles/blsG2MultiExp.json +++ /dev/null @@ -1,723 +0,0 @@ -[ - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000011", - "Expected": "000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d536944", - "Name": "bls_g2multiexp_single", - "Gas": 66000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000019d5f05b4f134bb37d89a03e87c8b729e6bdc062f3ae0ddc5265b270e40a6a5691f51ff60b764ea760651caf395101840000000000000000000000000000000015532df6a12b7c160a0831ef8321b18feb6ce7997c0718b205873608085be3afeec5b5d5251a0f85f7f5b7271271e0660000000000000000000000000000000004623ac0df1e019d337dc9488c17ef9e214dc33c63f96a90fea288e836dbd85079cb3cec42ae693e9c16af3c3204d86e0000000000000000000000000000000011ba77f71923c1b6a711a48fa4085c4885290079448a4b597030cc84aa14647136513cec6d11c4453ca74e906bbca1e1000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000176a7158b310c9ff1bfc21b81903de99c90440792ebe6d9637652ee34acf53b43c2f31738bbc96d71dcadbbf0e3190af000000000000000000000000000000000a592641967934a97e012f7d6412c4f6ff0f177a1b466b9b49c9deb7498decc80d0c809448aa9fa6fbbb6f537515703000000000000000000000000000000000031d84356ef619e688a10247f122e1aa0d3def3e35f94043f64c634198421487ca96af5f0160384bba92bd5494506c4d000000000000000000000000000000000db8fefe735779489c957785fa8e45d24e086ef0c2aba2e3adba888f0aeee51385a82898524c443f017ee40be635048c0000000000000000000000000000000000000000000000000000000000000034", - "Expected": "00000000000000000000000000000000158d8ef3d5cdc8a1b5ce170f6eeadec450ca05952ea7457a638b8ff8b687c047799eb3dd89c2e3c6ca6c29290b64f5ab000000000000000000000000000000000807d135b6b007a101e97f5875e233b41f12bd2ffd77fe1195418a73a4c061248118ea1049aeea44750cd5ec83bcc1ae000000000000000000000000000000000f04136354f45a85a53fb68527bc8fbc7e8c1a0056878012b548a97bfdabcbd3fb8eb3ff187fbe65e1ce233afd2825050000000000000000000000000000000007b15428114e2ea094ba1e64df4c244f80aa2f75bbbf21a407bc84e80bf2a5ad787d02ae8a90cc1c137f0d898edb1684", - "Name": "bls_g2multiexp_multiple", - "Gas": 126060, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3000000000000000000000000000000000000000000000000000000000000205900000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e84900000000000000000000000000000000000000000000000000000000000b7fa3000000000000000000000000000000000e7a30979a8853a077454eb63b8dcee75f106221b262886bb8e01b0abb043368da82f60899cc1412e33e4120195fc55700000000000000000000000000000000070227d3f13684fdb7ce31b8065ba3acb35f7bde6fe2ddfefa359f8b35d08a9ab9537b43e24f4ffb720b5a0bda2a82f2000000000000000000000000000000000701377cb7da22789d032737eabcea2b2eee6bb4634c4365864511a43c2caad50422993ccd3e99636eb8a5f189454b18000000000000000000000000000000000782c14e2c4ee61cbe7be6e462a66b2e3509f42d53ff333efc9bfe9a00307cd2f68b007606446d98a75fb808a405d8b90000000000000000000000000000000000000000000000000000000004165ef1000000000000000000000000000000000411a5de6730ffece671a9f21d65028cc0f1102378de124562cb1ff49db6f004fcd14d683024b0548eff3d1468df26880000000000000000000000000000000000fb837804dba8213329db46608b6c121d973363c1234a86dd183baff112709cf97096c5e9a1a770ee9d7dc641a894d60000000000000000000000000000000019b5e8f5d4a72f2b75811ac084a7f814317360bac52f6aab15eed416b4ef9938e0bdc4865cc2c4d0fd947e7c6925fd1400000000000000000000000000000000093567b4228be17ee62d11a254edd041ee4b953bffb8b8c7f925bd6662b4298bac2822b446f5b5de3b893e1be5aa49860000000000000000000000000000000000000000000000000000000173f3bfab0000000000000000000000000000000019e384121b7d70927c49e6d044fd8517c36bc6ed2813a8956dd64f049869e8a77f7e46930240e6984abe26fa6a89658f0000000000000000000000000000000003f4b4e761936d90fd5f55f99087138a07a69755ad4a46e4dd1c2cfe6d11371e1cc033111a0595e3bba98d0f538db4510000000000000000000000000000000017a31a4fccfb5f768a2157517c77a4f8aaf0dee8f260d96e02e1175a8754d09600923beae02a019afc327b65a2fdbbfc00000000000000000000000000000000088bb5832f4a4a452edda646ebaa2853a54205d56329960b44b2450070734724a74daaa401879bad142132316e9b34010000000000000000000000000000000000000000000000000000008437a521c900000000000000000000000000000000049cd1dbb2d2c3581e54c088135fef36505a6823d61b859437bfc79b617030dc8b40e32bad1fa85b9c0f368af6d38d3c000000000000000000000000000000000d0273f6bf31ed37c3b8d68083ec3d8e20b5f2cc170fa24b9b5be35b34ed013f9a921f1cad1644d4bdb14674247234c80000000000000000000000000000000008b7ae4dbf802c17a6648842922c9467e460a71c88d393ee7af356da123a2f3619e80c3bdcc8e2b1da52f8cd9913ccdd0000000000000000000000000000000005ecf93654b7a1885695aaeeb7caf41b0239dc45e1022be55d37111af2aecef87799638bec572de86a7437898efa702000000000000000000000000000000000000000000000000000002effc7b302730000000000000000000000000000000002142a58bae275564a6d63cb6bd6266ca66bef07a6ab8ca37b9d0ba2d4effbccfd89c169649f7d0e8a3eb006846579ad0000000000000000000000000000000012be651a5fa620340d418834526d37a8c932652345400b4cd9d43c8f41c080f41a6d9558118ebeab9d4268bb73e850e10000000000000000000000000000000015f4b235c209d89ce833f8f296e4cfb748e8abce6990ce1a5a914b9416c08e0d3a26db89625915c821a5f152b7fa592e0000000000000000000000000000000006fcacb3ee6650a1044852d61c9c20bedc8ee90aad97de8e24670a9ef57483e678db11dd95428915088d76e30cb01a370000000000000000000000000000000000000000000000000010b4ebfca1dee100000000000000000000000000000000018405e4b67f957b6465ead9f5afc47832d45643dc3aa03af7314c6cf980fa23dd3bb8db3358693ad06011f6a6b1a5ff000000000000000000000000000000000c48e0d4f9404ae0a7f10774c55a9e838bb09d3bae85b5eaa6b16b0f4dc2354368117f3799c37f3f7126d8b54d3f83930000000000000000000000000000000007e61f4ec5bc9e2cc8ca471ce4ed40e729b1790cd2c0d9c1cb50e615ec7f346636e77e1cf632c881c07c5385898607620000000000000000000000000000000011dfaf9281901dd356fc5dfece21898a93d9ad9e4e246dd6e18d3ee46d58ab7e77401a3e8d04057e5638ed74fb95688100000000000000000000000000000000000000000000000005f04fe2cd8a39fb000000000000000000000000000000001796abe0d9e4a703962be528e6a5cb65c60725886f925db0e2a89107ec248bb39fa332bc63bd91d28ae66e0dfce8f754000000000000000000000000000000000fb665f5a7559cb0fa1300048a0e6f1ab5547226e86f8e752dd13c28eda4168492e3d3bf2f8a6b230dd57f79b1afa9910000000000000000000000000000000003422dbbe4a06a4c6c9fdf35e54f74b4ab1528abb7249e99898e6fd7affebc7aef95bf82d328dc01d63c25f6a735c35d0000000000000000000000000000000010aa5504b469427eb3584a286191149f5c3c5a745f338278dd95337cd2336d3c4e7532d98eb189fa543824953e7c1c170000000000000000000000000000000000000000000000021c6c659f10229c390000000000000000000000000000000009303f04d568e289a35102b6df883d5ed620355c0eb5d02236718cdaf99fba6e19ef5cee2996268eb9a53ae1ee09bce3000000000000000000000000000000000190be857d602284393305bfe0a29e29a6982ed3f04ccaabafb7e59cdc7eda85c22bc3e8690355c7a0fb7590ae40f1b00000000000000000000000000000000016efd497a0c5c6b59a1fdf2b590eb67a7da8cbe72f49084e7050783ff12a783cad1859e1a0b0ec8ff784c703617670330000000000000000000000000000000017a957ea4d53f4fc8412cb015ae91b38445cdb3e7078d875c465c941e0d9a852c78d90b31b6b6010efe8bd5117e831630000000000000000000000000000000000000000000000c01a881f8abc4d8843000000000000000000000000000000000173ed58056bec9874464d3f23c3e7d3d429d6c8a167fc7f39368830eca839d0eb8260d64ca823f6c785c71f85893d8400000000000000000000000000000000123372d7d4c91a249df8f3e4f8e669087b252ab5d8cf2529a87e4ed3622e4158cf17dc44b473d5debd273261383e8a0f0000000000000000000000000000000000c500eb55ab86381a1725f339f686c7e38ce9113493736f57e999badc661b5b8494d220ded0711e841228a389abdb820000000000000000000000000000000010a4025d823c4262367c53f50e67cffa046e4a1e7c69ff30373772e49ecb310de3b313d83cc41f40a00205722f233e270000000000000000000000000000000000000000000044496e633650ef8f6fd100000000000000000000000000000000152110e866f1a6e8c5348f6e005dbd93de671b7d0fbfa04d6614bcdd27a3cb2a70f0deacb3608ba95226268481a0be7c000000000000000000000000000000000bf78a97086750eb166986ed8e428ca1d23ae3bbf8b2ee67451d7dd84445311e8bc8ab558b0bc008199f577195fc39b7000000000000000000000000000000000845be51ad0d708657bfb0da8eec64cd7779c50d90b59a3ac6a2045cad0561d654af9a84dd105cea5409d2adf286b561000000000000000000000000000000000a298f69fd652551e12219252baacab101768fc6651309450e49c7d3bb52b7547f218d12de64961aa7f059025b8e0cb500000000000000000000000000000000000000000018461a3d444ec527fcbf4b000000000000000000000000000000000027513925b419f6c581788578379995290ab9478e08ecd1999d5e1a05c58144d2f9f06fb8c7fd1586f3ef6a973a3ed7000000000000000000000000000000001292b2ce751f6f859ec7882e14083eac9841b035f9d5ed938a81579dbce07dec2c0202b7f6b25226831cd9c578e893d00000000000000000000000000000000017f36da49414d7706209d52840250eea6f33970fd7eac448ee122f24c62f6a6e09757aa29761160be0f65ba3ce7a153a00000000000000000000000000000000086d471f958f3ff679805751b183fb6310e871ba72bbdefd59c58e95ea62de0820d5affe601757e318abaa5a0c2715bd000000000000000000000000000000000000000008a0eb53c748001536d7ffa900000000000000000000000000000000090721a089bbbb130c21a529be0ede9271a91a2dde9cb2a8e091a19fd2c0a40c390ac2bda8304085c2d6e38e520eae44000000000000000000000000000000000cc64109c67b342b6dbcf86cb60fca7ad378ed6398d89076ed108685c57a07d26e40ed3d5c4b3560b21e519db5875d49000000000000000000000000000000000b0ddd488f5a6f61f087cdbf011b50209a4460c8aa8c5f48c0b30d9cf6cf24259f4e7badc42e1b7a33352949ae566fc100000000000000000000000000000000038430e8db04d205d81aa1632d23919c06f89260c7ac5850bd8b780f8388e53db3a3ddfe98cc55d1c686e582f85b0c8900000000000000000000000000000000000000031133a6c7d698078a7ec7e113000000000000000000000000000000001800ecc167bb714100f31e7610cd3fd010ca299b394c01b1a89afd11b051e92989f6336db5e6d3212f6b04673526d83900000000000000000000000000000000070401d9bba01c0445e0a682406b099f21d16d9c348cc97156769084055ca328a145c134b8c8b58f019d62882b2965de000000000000000000000000000000000287f071bda99b0318e386b27a492a6823a9664084b12acddeda34cb53f827a362ba97c0e652c37bd9d6023041d8c8d8000000000000000000000000000000000fa708ca7dd917541cd02281e525d3367b5ebf5e9353103e1f83f3b894d03d8be7e4d819c123492788855d1fdb63f2e000000000000000000000000000000000000001171d5c4909480aae3b110d01c1000000000000000000000000000000000ef786ebdcda12e142a32f091307f2fedf52f6c36beb278b0007a03ad81bf9fee3710a04928e43e541d02c9be44722e8000000000000000000000000000000000d05ceb0be53d2624a796a7a033aec59d9463c18d672c451ec4f2e679daef882cab7d8dd88789065156a1340ca9d426500000000000000000000000000000000118ed350274bc45e63eaaa4b8ddf119b3bf38418b5b9748597edfc456d9bc3e864ec7283426e840fd29fa84e7d89c934000000000000000000000000000000001594b866a28946b6d444bf0481558812769ea3222f5dfc961ca33e78e0ea62ee8ba63fd1ece9cc3e315abfa96d53694400000000000000000000000000000000000063376fcdf64c9bcbeeff0f9f9f9b0000000000000000000000000000000004b6570b4a6affe97649b0dd7a0ad0df160b37c332a8a7348dd3994cc6b1eb65623b4a9f0a3f320e7278844e261546530000000000000000000000000000000005f8fb4cf5e5313f403f15c59c79b9cebaec78291f2053c49d6427f40f2db2aa659d3a8fed7c7b07b7a5680c7b95ab5800000000000000000000000000000000045cba5ec3fa9acd1b11e1f28a01ebc028f89f96f814513453c553f58785baca8abd4150f334b405fabb925b71f4f4dd0000000000000000000000000000000013daf00b8f53af776c2e8c08d55d164aa15027611188e294230477dc1c926102088f0451222fd2eff9802db8b884ab9c00000000000000000000000000000000002344b4be368d3b617df4aa8dbdbc190000000000000000000000000000000002b29192945df0a74eed138e431962f1d39978202d247335ffbf29d8a02e982c69e96b58d7d92528baf5c422ed633f1f000000000000000000000000000000000d52c7a82fece99279de7a49439c0ff8463a637cc6003320275d69549442c95184fd75ee5e7122e5575af7432e5159290000000000000000000000000000000006ddbaad6cc16c9e62b0da9ab0196dffe92253fcfb2df9aa2076d3f16b3284997d6558cc4432d2aa1705452c4e951e6e00000000000000000000000000000000175f906a99c9d65c4647807879e5eb781532db184d28a326ef9691f8738af067b6a80147bd69327d219fad7c850a7545000000000000000000000000000000000c896c3f9d64341ba7c5f8a06271dce3000000000000000000000000000000000c86c92c9598dde7e6fc5e05d70a34c7a14cff5f400f33cf6cc26e6bf6d9a0bbc421c00f3360721f51974d76be43bd38000000000000000000000000000000001137d93502ef32471f47890a181d7823b3a86dbfcadcc930ae53952f528d617e742a52e4f243c615cc28163dc31bd80600000000000000000000000000000000088f7f8bcbc6dfcc8005b8308cd4780d574d8530e95e7831e52eb2c9a88b846852e111a8389e3d3a67accf78b08326d200000000000000000000000000000000149e43fc675dd3bde8b89cfeb29456f130bbf674cea0266bd1b2e7de23f9a7294096327b452728411ca58acc949777fa0000000000000000000000000000000474d97a9cf29e85d4a35f6102fe7984b100000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f00000000000000000000000000000195894e95ca3e59929612e77c1075322aeb00000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000009027ceef3ee429d71b58b84919d9a8d5418900000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab1600000000000000000000000000333e268f0b5b1adf76b88981fc305f03ce4bb30000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000123717b4d909628d6f3398e134a531c65a54e8a10000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000679956d49265608468757580db6b8b1821c2eb13b", - "Expected": "000000000000000000000000000000000728c5e6e69b9103d82358cb6ba3a45a677df1c3eb3cdccf694fd71cee94f1e591b8021b0eef638cd9a1d878937b5b2d000000000000000000000000000000000ba9bcf9ccef956f2af8dc4c3fbf1cc8f3f284b04ae8710af6ef4fb36301254c777d4461858fb38fdeeb72c0d8589af5000000000000000000000000000000000224b80a57d30bce4c752664f3b5b5e3443aefa6d4e95dc334821f754b8b8d8fda4e73d03cbd4070d43b18324a686b500000000000000000000000000000000016909a02214c6c0f6682895aa99cf6cf0a22eab6f0b574437ef9c36e9df32ac3b8c5adb9f6b8827df0ccf51b16f824df", - "Name": "bls_g2multiexp_larger", - "Gas": 409750, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000039b10ccd664da6f273ea134bb55ee48f09ba585a7e2bb95b5aec610631ac49810d5d616f67ba0147e6d1be476ea220e0000000000000000000000000000000000fbcdff4e48e07d1f73ec42fe7eb026f5c30407cfd2f22bbbfe5b2a09e8a7bb4884178cb6afd1c95f80e646929d30040000000000000000000000000000000001ed3b0e71acb0adbf44643374edbf4405af87cfc0507db7e8978889c6c3afbe9754d1182e98ac3060d64994d31ef576000000000000000000000000000000001681a2bf65b83be5a2ca50430949b6e2a099977482e9405b593f34d2ed877a3f0d1bddc37d0cec4d59d7df74b2b8f2dfb3c940fe79b6966489b527955de7599194a9ac69a6ff58b8d99e7b1084f0464e0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d93884d0e25bf3f6fc9f4da25d21fdc71773f1947b7a8a775b8177f7eca990b05b71d0000000000000000000000000000000003632695b09dbf86163909d2bb25995b36ad1d137cf252860fd4bb6c95749e19eb0c1383e9d2f93f2791cb0cf6c8ed9d000000000000000000000000000000001688a855609b0bbff4452d146396558ff18777f329fd4f76a96859dabfc6a6f6977c2496280dbe3b1f8923990c1d6407000000000000000000000000000000000c8567fee05d05af279adc67179468a29d7520b067dbb348ee315a99504f70a206538b81a457cce855f4851ad48b7e80000000000000000000000000000000001238dcdfa80ea46e1500026ea5feadb421de4409f4992ffbf5ae59fa67fd82f38452642a50261b849e74b4a33eed70cc973f40c12c92b703d7b7848ef8b4466d40823aad3943a312b57432b91ff68be1000000000000000000000000000000000149704960cccf9d5ea414c73871e896b1d4cf0a946b0db72f5f2c5df98d2ec4f3adbbc14c78047961bc9620cb6cfb5900000000000000000000000000000000140c5d25e534fb1bfdc19ba4cecaabe619f6e0cd3d60b0f17dafd7bcd27b286d4f4477d00c5e1af22ee1a0c67fbf177c00000000000000000000000000000000029a1727041590b8459890de736df15c00d80ab007c3aee692ddcdf75790c9806d198e9f4502bec2f0a623491c3f877d0000000000000000000000000000000008a94c98baa9409151030d4fae2bd4a64c6f11ea3c99b9661fdaed226b9a7c2a7d609be34afda5d18b8911b6e015bf494c51f97bcdda93904ae26991b471e9ea942e2b5b8ed26055da11c58bc7b5002a000000000000000000000000000000001156d478661337478ab0cbc877a99d9e4d9824a2b3f605d41404d6b557b3ffabbf42635b0bbcb854cf9ed8b8637561a8000000000000000000000000000000001147ed317d5642e699787a7b47e6795c9a8943a34a694007e44f8654ba96390cf19f010dcf695e22c21874022c6ce291000000000000000000000000000000000c6dccdf920fd5e7fae284115511952633744c6ad94120d9cae6acda8a7c23c48bd912cba6c38de5159587e1e6cad519000000000000000000000000000000001944227d462bc2e5dcc6f6db0f83dad411ba8895262836f975b2b91e06fd0e2138862162acc04e9e65050b34ccbd1a4e8964d5867927bc3e35a0b4c457482373969bff5edff8a781d65573e07fd87b890000000000000000000000000000000019c31e3ab8cc9c920aa8f56371f133b6cb8d7b0b74b23c0c7201aca79e5ae69dc01f1f74d2492dcb081895b17d106b4e000000000000000000000000000000001789b0d371bd63077ccde3dbbebf3531368feb775bced187fb31cc6821481664600978e323ff21085b8c08e0f21daf72000000000000000000000000000000000009eacfe8f4a2a9bae6573424d07f42bd6af8a9d55f71476a7e3c7a4b2b898550c1e72ec13afd4eff22421a03af1d31000000000000000000000000000000000410bd4ea74dcfa33f2976aa1b571c67cbb596ab10f76a8aaf4548f1097e55b3373bff02683f806cb84e1e0e877819e2787c38b944eadbd03fd3187f450571740f6cd00e5b2e560165846eb800e5c94400000000000000000000000000000000147f09986691f2e57073378e8bfd58804241eed7934f6adfe6d0a6bac4da0b738495778a303e52113e1c80e698476d50000000000000000000000000000000000762348b84c92a8ca6de319cf1f8f11db296a71b90fe13e1e4bcd25903829c00a5d2ad4b1c8d98c37eaad7e042ab023d0000000000000000000000000000000011d1d94530d4a2daf0e902a5c3382cd135938557f94b04bccea5e16ea089c5e020e13524c854a316662bd68784fe31f300000000000000000000000000000000070828522bec75b6a492fd9bca7b54dac6fbbf4f0bc3179d312bb65c647439e3868e4d5b21af5a64c93aeee8a9b7e46eaaee7ae2a237e8e53560c79e7baa9adf9c00a0ea4d6f514e7a6832eb15cef1e1000000000000000000000000000000000690a0869204c8dced5ba0ce13554b2703a3f18afb8fa8fa1c457d79c58fdc25471ae85bafad52e506fc1917fc3becff0000000000000000000000000000000010f7dbb16f8571ede1cec79e3f9ea03ae6468d7285984713f19607f5cab902b9a6b7cbcfd900be5c2e407cc093ea0e6700000000000000000000000000000000151caf87968433cb1f85fc1854c57049be22c26497a86bfbd66a2b3af121d894dba8004a17c6ff96a5843c2719fa32d10000000000000000000000000000000011f0270f2b039409f70392879bcc2c67c836c100cf9883d3dc48d7adbcd52037d270539e863a951acd47ecaa1ca4db12dac6ed3ef45c1d7d3028f0f89e5458797996d3294b95bebe049b76c7d0db317c0000000000000000000000000000000017fae043c8fd4c520a90d4a6bd95f5b0484acc279b899e7b1d8f7f7831cc6ba37cd5965c4dc674768f5805842d433af30000000000000000000000000000000008ddd7b41b8fa4d29fb931830f29b46f4015ec202d51cb969d7c832aafc0995c875cd45eff4a083e2d5ecb5ad185b64f0000000000000000000000000000000015d384ab7e52420b83a69827257cb52b00f0199ed2240a142812b46cf67e92b99942ac59fb9f9efd7dd822f5a36c799f00000000000000000000000000000000074b3a16a9cc4be9da0ac8e2e7003d9c1ec89244d2c33441b31af76716cce439f805843a9a44701203231efdca551d5bbb30985756c3ca075114c92f231575d6befafe4084517f1166a47376867bd108000000000000000000000000000000000e25365988664e8b6ade2e5a40da49c11ff1e084cc0f8dca51f0d0578555d39e3617c8cadb2abc2633b28c5895ab0a9e00000000000000000000000000000000169f5fd768152169c403475dee475576fd2cc3788179453b0039ff3cb1b7a5a0fff8f82d03f56e65cad579218486c3b600000000000000000000000000000000087ccd7f92032febc1f75c7115111ede4acbb2e429cbccf3959524d0b79c449d431ff65485e1aecb442b53fec80ecb4000000000000000000000000000000000135d63f264360003b2eb28f126c6621a40088c6eb15acc4aea89d6068e9d5a47f842aa4b4300f5cda5cc5831edb81596fb730105809f64ea522983d6bbb62f7e2e8cbf702685e9be10e2ef71f818767200000000000000000000000000000000159da74f15e4c614b418997f81a1b8a3d9eb8dd80d94b5bad664bff271bb0f2d8f3c4ceb947dc6300d5003a2f7d7a829000000000000000000000000000000000cdd4d1d4666f385dd54052cf5c1966328403251bebb29f0d553a9a96b5ade350c8493270e9b5282d8a06f9fa8d7b1d900000000000000000000000000000000189f8d3c94fdaa72cc67a7f93d35f91e22206ff9e97eed9601196c28d45b69c802ae92bcbf582754717b0355e08d37c000000000000000000000000000000000054b0a282610f108fc7f6736b8c22c8778d082bf4b0d0abca5a228198eba6a868910dd5c5c440036968e977955054196b6a9408625b0ca8fcbfb21d34eec2d8e24e9a30d2d3b32d7a37d110b13afbfea000000000000000000000000000000000f29b0d2b6e3466668e1328048e8dbc782c1111ab8cbe718c85d58ded992d97ca8ba20b9d048feb6ed0aa1b4139d02d3000000000000000000000000000000000d1f0dae940b99fbfc6e4a58480cac8c4e6b2fe33ce6f39c7ac1671046ce94d9e16cba2bb62c6749ef73d45bea21501a000000000000000000000000000000001902ccece1c0c763fd06934a76d1f2f056563ae6d8592bafd589cfebd6f057726fd908614ccd6518a21c66ecc2f78b660000000000000000000000000000000017f6b113f8872c3187d20b0c765d73b850b54244a719cf461fb318796c0b8f310b5490959f9d9187f99c8ed3e25e42a93b77283d0a7bb9e17a27e66851792fdd605cc0a339028b8985390fd024374c76000000000000000000000000000000000576b8cf1e69efdc277465c344cadf7f8cceffacbeca83821f3ff81717308b97f4ac046f1926e7c2eb42677d7afc257c000000000000000000000000000000000cc1524531e96f3c00e4250dd351aedb5a4c3184aff52ec8c13d470068f5967f3674fe173ee239933e67501a9decc6680000000000000000000000000000000001610cfcaea414c241b44cf6f3cc319dcb51d6b8de29c8a6869ff7c1ebb7b747d881e922b42e8fab96bde7cf23e8e4cd0000000000000000000000000000000017d4444dc8b6893b681cf10dac8169054f9d2f61d3dd5fd785ae7afa49d18ebbde9ce8dde5641adc6b38173173459836dd994eae929aee7428fdda2e44f8cb12b10b91c83b22abc8bbb561310b62257c000000000000000000000000000000000ca8f961f86ee6c46fc88fbbf721ba760186f13cd4cce743f19dc60a89fd985cb3feee34dcc4656735a326f515a729e400000000000000000000000000000000174baf466b809b1155d524050f7ee58c7c5cf728c674e0ce549f5551047a4479ca15bdf69b403b03fa74eb1b26bbff6c0000000000000000000000000000000000e8c8b587c171b1b292779abfef57202ed29e7fe94ade9634ec5a2b3b4692a4f3c15468e3f6418b144674be70780d5b000000000000000000000000000000001865e99cf97d88bdf56dae32314eb32295c39a1e755cd7d1478bea8520b9ff21c39b683b92ae15568420c390c42b123b7010b134989c8368c7f831f9dd9f9a890e2c1435681107414f2e8637153bbf6a0000000000000000000000000000000017eccd446f10018219a1bd111b8786cf9febd49f9e7e754e82dd155ead59b819f0f20e42f4635d5044ec5d550d847623000000000000000000000000000000000403969d2b8f914ff2ea3bf902782642e2c6157bd2a343acf60ff9125b48b558d990a74c6d4d6398e7a3cc2a16037346000000000000000000000000000000000bd45f61f142bd78619fb520715320eb5e6ebafa8b078ce796ba62fe1a549d5fb9df57e92d8d2795988eb6ae18cf9d9300000000000000000000000000000000097db1314e064b8e670ec286958f17065bce644cf240ab1b1b220504560d36a0b43fc18453ff3a2bb315e219965f5bd394c68bc8d91ac8c489ee87dbfc4b94c93c8bbd5fc04c27db8b02303f3a65905400000000000000000000000000000000018244ab39a716e252cbfb986c7958b371e29ea9190010d1f5e1cfdb6ce4822d4055c37cd411fc9a0c46d728f2c13ecf0000000000000000000000000000000001985d3c667c8d68c9adb92bdc7a8af959c17146544997d97116120a0f55366bd7ad7ffa28d93ee51222ff9222779675000000000000000000000000000000000c70fd4e3c8f2a451f83fb6c046431b38251b7bae44cf8d36df69a03e2d3ce6137498523fcf0bcf29b5d69e8f265e24d00000000000000000000000000000000047b9163a218f7654a72e0d7c651a2cf7fd95e9784a59e0bf119d081de6c0465d374a55fbc1eff9828c9fd29abf4c4bdb3682accc3939283b870357cf83683350baf73aa0d3d68bda82a0f6ae7e51746", - "Expected": "00000000000000000000000000000000083ad744b34f6393bc983222b004657494232c5d9fbc978d76e2377a28a34c4528da5d91cbc0977dc953397a6d21eca20000000000000000000000000000000015aec6526e151cf5b8403353517dfb9a162087a698b71f32b266d3c5c936a83975d5567c25b3a5994042ec1379c8e526000000000000000000000000000000000e3647185d1a20efad19f975729908840dc33909a583600f7915025f906aef9c022fd34e618170b11178aaa824ae36b300000000000000000000000000000000159576d1d53f6cd12c39d651697e11798321f17cd287118d7ebeabf68281bc03109ee103ee8ef2ef93c71dd1dcbaf1e0", - "Name": "matter_g2_multiexp_0", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000eb3c91515d4a41209a73564741a8ccf901a624df9db22e195a5d02d24b7bc0a12756b15b8d006cb991a7e088eaef1000000000000000000000000000000000704ce8afc808b0161f6f61b22d990d713ae398779e6e74e9b5771daf006ce0bba3a8088edf75156f0e48b92ee8409b00000000000000000000000000000000018fe81e05aff0620f4bdbe4a715e015650497afab62921eba0ab86b649e5a2fd3d54041868928519f537e36448688a0d00000000000000000000000000000000162bd97161201ea3c26f8dd1204a9c6b61b762bdf573cb5d20b6b255f30208ca7d96aa47b46fb8c6bf0922075f1c1ca807f80a5e502f63375d672379584e11e41d58d2ed58f3e5c3f67d9ea1138493cf00000000000000000000000000000000135aee0e30fbcad798738c10d4aebcdf50c89ce516325f655fe763dce54ffedf94dd74168611e5ae879b5bf5598d62dc000000000000000000000000000000000c728e672cd8b3bf9341bca929c34118b566cd3a80452d7015bee9d5cdc001b1f5c678d4b2cc4f7cac353e7bf326ca1e0000000000000000000000000000000014809aa22e2051e463fba6d49fbb060d0c7f599a0fc5409d34e71f34817e7beb1251810ae6eee1848c60796fb8647dea00000000000000000000000000000000145a4de777d86025d50e12f9a6615ecb9bdd41489992d1b643dd9aa549acbc63b04b0bdfd14b6e45c70f165e9a8c91bebb169138f94093d5c1c6b253cc001ce8baf78858dae053173fa812d2d1c800da00000000000000000000000000000000009a58b7116dbd6f550f8ca98071813130ecaa9ea86d5275eebc36860690fa048c9ebeb46600b2b63e847bff3e38ed0d00000000000000000000000000000000113ffc0932c041e0e34b2540c485eb74f5029b339cb60bc88a8a749310f33f330dea137e5f340044fd689264af66696d0000000000000000000000000000000002642da3c2c7b6688aba0b19ab29ac72e35caafa044863c364ea8833fca850289de52c0963bc33d7bba40cb5f568718a000000000000000000000000000000000552d35ca054da2f148c119454f6760607b351f2441921a2be17da2cc10902d71571c5554f132e60df79679428fa07e3e40608bdaf3e7764358a64a920cbb33ab4d571c7b3092e1ae11d9697f82ed8330000000000000000000000000000000018fbbcba3d4b1e548ceaec4a48db62a2420ff29a67af332ee7ea3f902f84e6c375fd33abc33d945c5bca25603979f9a400000000000000000000000000000000072ff416994364bdc6535f36c82212afa822cd94fade69f11eb38dbdcd37c7e22af55fe05e6a826dad822073656eaac10000000000000000000000000000000017bba179b847278a4878b6faeaab3b1f4bd7540d22817cd9aff95557497f8b9d286657b6162c0f89f7820becc637dd550000000000000000000000000000000018e2bfed71aa9b11fefca2f0db8bd9b8c69540267de50bec4fc90a6e9741891465c9761d19282e1100b3707eeb598b31d411519f2a33b07f65e7d721950e0f0d5161c71a402810e46817627a17c56c0f0000000000000000000000000000000019efd37727dfaedf697fcda7a59847dbda8ca7cdc92f34e68691d682e20ae6545ac104d6660fdb8f64a051e69298eae8000000000000000000000000000000001225ace0fdce456dd888c9672503b68ef77b2d11caf1265a767a6ea14911e3ca03fc153f18dfe9d95e0cc68b7b8a3a8d0000000000000000000000000000000008a6b059c1c4da046cc0b1b5d7f33270aceffa607daf6d0d078c06f940604e1a0b4adf01a4091306e3c7eddcf3d95101000000000000000000000000000000000f79bae5260a2f114ffbb9273f3049d3ebb002500a57ee0a7d157d86957f43f87a2e026fb9892dacaadca5ee04fc8e176bb3f9e512311699f110a5e6ae57e0a7d2caaa8f94e41ca71e4af069a93d08cc0000000000000000000000000000000016d2b73eeceee17d3bff3aacac9df9ac1c4248d9ea7d6a503a757f7bb22fa6970bb6f5cb5ec154785f7252e1508b382e00000000000000000000000000000000081edc68bbd8db7b10be06ee23d090bd54f9ca07ef24dfed7df7bb05f8cc26e6889dbd40ea203fd5cca5cb588199f9e40000000000000000000000000000000010d3478508619ea9493b4330e2fb9150024cd32dc1378f824788a884a4a30fbf39c630f465557bf0c6d69b4cbecf89f9000000000000000000000000000000000f20c9b134db5d8b7756800c031bf5962fc560ba95d4bd9157b16179f1a37ae08696a2be455ad8d018aead6adcc69b712a0c988d97e86dccaeb8bd4e27f9e30fad5d5742202cdde17d800642db633c520000000000000000000000000000000003dce67181d23af9729e9fb0653d7f79c890fba27de42fada93123e112c4a468fa889921192db8047d86e4db77c60266000000000000000000000000000000000869a1e39d42d9bb0cc0568fdad16abbdac3194af893ebd8dd8f8c2c3c855abefa5fc215412168acadc88e658e83f5570000000000000000000000000000000001ef139a75194f3c4b1378c2b66dd304d179460bac0a289405cd8faa3ff66a7b6e54eb7b8742a68150b1e098630135c40000000000000000000000000000000003892b5a645af916be2c6c7fc0bb08fb5f39341d3c68598940554e1be11e1be75af920db0c8710ed13c78edbf683f17d0b299c14892e0519b0accfa17e1a758c8aae54794fb61549f1396395c967e1b1000000000000000000000000000000000264dd4b477f5db65edad28c7153ed919a863c5c5661e0125c5429b323e055fd69c33142dfc6ed9c87082e2be4675e1f00000000000000000000000000000000046ea088a2ec94d3a1f1f97949f1ebc49690c453d316cc46534fa253b34b30323b6071d147d64bb94e02fb4db07bb0c400000000000000000000000000000000013692a33bb1348486eec40a9e93a4ea3810c7b4d3188cd07e235a2c898aa87ee0d17682fd24f4d978f9fb028fd26e2900000000000000000000000000000000115f8b64c00cd5cd344a7b5edc0ef0bb85a3e8f0f9dfb28f8ffe12db3e0d222c2d45dcdba0fbdc161c5d558bc71aa0977064d43d6802ad4c3794705065f870263fef19b81604839c9dea8648388094e900000000000000000000000000000000014c83d58d90db4821a0411fab45f83fbc05f7d0d7a67ce75da3ae568978d15f4c1886c6fa6086675c0045efb30d818400000000000000000000000000000000001e68691123451f4c3df6dae62c6a63855ec3597aae33a8a10ee274e902e9aab1460cc9c79726312df0ee0ce90c8d3c00000000000000000000000000000000018a39eb3e3c6c7fb8ee304e55d15e209afe2fe278dda93552a7b9f51fbd778da1502eb6775cbc3f832f8320fa0686240000000000000000000000000000000017c15910fad1ca5749aa82a5a2fa98b0ebb37e92912547fb1741f18c34e0d5fc3a307b928636c25f0320d71cb9d31062686285a0e22f177fe3adbfc435e9c1786752dcf3c11b723539789b0cdeb0647b000000000000000000000000000000000fa96d9fe01c18732e8d6454df9bb1f482c4b9add837ce9c354c72d49c2d44ec694674aaf0e6d6a095cab7ebb57ccd9a0000000000000000000000000000000001f8ffe3fb7e9e311e0f6949c07c26a0febb181e37b2268bb5e125fc3a100323740d1ebaa5e635dba3770fdc2ce4ee860000000000000000000000000000000012ac42095fdb677720ab3f14bf0afc55c95b43d28d922a5f8cb0bd841306b978751d24546e3a6474976961d0768f29e9000000000000000000000000000000000baf9804d99039c9fe966a696c64bdacc9673b0906b4deab108d34fbbaa3b0905d50892278570564017b96828c7e1ac93176b6724cf984632daf95c869d56838ab2baef94be3a4bd15df2dd8e49a90a60000000000000000000000000000000014ce6d88a7c5c782562aa101550f1af487296adebd9dae8252698ba04fbd58b92e2216de6ffd474d5992f97d9f22800d000000000000000000000000000000000ce92a04f5c8a99ca0e93992448222519fc454bda5d1d8638a7bfde968386e4ba0dcd1da59cd81d4c4dca3e584be0275000000000000000000000000000000000cb570796f5c8f7b8aa02e76cb8e870d3365fe4dce5df07ec286a0a821f922b4003d5b69c0f1588206d9544013e268c400000000000000000000000000000000098056a033d9cdae86aac02de3a444471854b909680719154b44d4f55f30087294e39e57643c692d6da725b859239080d76db3dcb659eaf6c086be6b414a494dea4bd30aef8450ae639f473148c05b36000000000000000000000000000000001214aacb0a5e6b7a40369a83c07fa8cf1786ce7cbde2b5a501d9c1292532df7822d4fde10a31fc0cecce3a7cfe3311850000000000000000000000000000000004f9669d8fe4f884ae93b2505710e6e45b19b7aa5df8cdd811f09e547efc27d21024cba05e2dc9d057055f30ec72d9df000000000000000000000000000000000a852b821b31cd27eca19712a636aa05ef2cd82c36ac1c2ca240edc7d0172b42a72c42d3cba583a5b5129ac1c9486e270000000000000000000000000000000007bd8419e791a5cea04993509e91a980d3ae4987a5b322400b6e4a4f2b636891a1c7ba4de96b53426dd556532403d5a39915646de2449b3cb78d142b6018f3da7a16769722ec2c7185aedafe2699a8bc0000000000000000000000000000000005ef88bf38b2f998dec7302cde829076e6cf69df23aa0bf6bbb39fc0d3d8b5eafba74efb928b1de0eeb3d86ec82612300000000000000000000000000000000011f47e9583997b19c36616e4bf78d6ddd6d67937f493986250ff02aef6e6e7ff074559af2f20a5bf1d67158e4a199cdb000000000000000000000000000000000007777c8eb259a836e6459b7bdb642f878d869fdcb31b105d01f280938ef5377f2775874c099dcd394abe70f17d595b000000000000000000000000000000001607379d1cd34e2d0ed765a339b21433e9aa489609b92414c6b5a05d796085269c288d739717def9db3502e0550860165061073223f066e35242772385c67aaefb3f7ea7df244d73369db1ea0b208792000000000000000000000000000000000d6e3068c082b68312141aa68f1540ea1415e93e7f1762b6f06ff408a9995542da1c727a13355c19f8f418a44de1a95d000000000000000000000000000000000dcfcf2ab12b1a0e521ab402aaa4d32ff649a5a97892eb6ad98487c3c73c35601c313b8130ad12e9098d16eed3bcc2e00000000000000000000000000000000013777b1eefa4af03dc44e4e054eb7a3a980a9c55644900b80346be84b970e1754d1f4ab771adc9249e4accf88a23fb400000000000000000000000000000000002f53b231f1209c6f8b52f99a78bc2147c951ac89b341495f4a60a6572985ce2bc823625099ec214bc9ceedb2deea3fff396ee22209271ea0bda10fb5e2584e7536e8bb1d00a0dd7b852b0aa653cd86c00000000000000000000000000000000161c595d151a765c7dee03c9210414cdffab84b9078b4b98f9df09be5ec299b8f6322c692214f00ede97958f235c352b00000000000000000000000000000000106883e0937cb869e579b513bde8f61020fcf26be38f8b98eae3885cedec2e028970415fc653cf10e64727b7f6232e06000000000000000000000000000000000f351a82b733af31af453904874b7ca6252957a1ab51ec7f7b6fff85bbf3331f870a7e72a81594a9930859237e7a154d0000000000000000000000000000000012fcf20d1750901f2cfed64fd362f010ee64fafe9ddab406cc352b65829b929881a50514d53247d1cca7d6995d0bc9b2f0d3d4cf46265fc0f69e093181f8b02114e492485696c671b648450c4fcd97aa000000000000000000000000000000000047f92d6306bed1cb840f58fd57b5b71a5df7f86dbfa55a36636cb495e08715cd57f2f3e7cd99a1efc28b1d684de1cb0000000000000000000000000000000000f4eb02d687a1a6105b4dbd740e2c7924689d558e6cbfee768dd303cc8dd0fd887f5eec24b54feccf00f473ca3f54ad000000000000000000000000000000000edad68c4d536912816cf6ef039c3dd0535dc52189583270b3b038e2c67b213d943bf384ce69c4a9dc526d7ef309f25a0000000000000000000000000000000006ff4a6b5129ef026d1d5704bf7fc0b474de92b5cf39722f165e73f4e7612d6d3bb40743e4b7b42d0dad5d5d6a2d4881915b717562844d59623bc582f1a95fc678cf0d39af32560c6c06e3a74023c89c", - "Expected": "000000000000000000000000000000000153da66acafe91b6f13cd739ed3342197310e4824e7aef2e3414654c2678b8d09b296c3f928f3cc489893420031ab800000000000000000000000000000000010f501a96b86343a7c8d8c1250577cc9be6ffec81b5175ed07bd14988c5bbf7f2f3e7111df7d941d0cd267ea191d6ac70000000000000000000000000000000015e0d88894f7f83aacb6710f6c03ae60db8844dd3beec160fdb1df746b1f38a5e23def0893a0b39bee47c97af6535fcb000000000000000000000000000000000bcc275115e87f2f88c4afe8bf4faed46e6ad0c0357884356a26120591ba283f06b464c4853217865b1d2301965f2bd4", - "Name": "matter_g2_multiexp_1", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b32e613cb38b41dcdf3c8bb9187d731546977fbffd79fa7f66e3d6aaf9e1af6eca2fcdc260c8f90818d7148ba2f4960000000000000000000000000000000007e4d26606a47c874c20e8480a9f5815e5b577bccd783b775d10309eeb3d2102c7a0abc3324679e44362f09e7a4ada67000000000000000000000000000000000cb6f12ac8b49cfa36b957591293c87b21af0a949c55a28a90ab0fce88fb5cb7645e20ab2edd284f0ad1377dd95ac10e0000000000000000000000000000000014c96b5dcbd3150eeaea5c2bc27750cf88b30a91933a3233a4d1d9b357a80cc20d135e43a344e718dff5c79045c31f86d5c1c9fa11c36b86430cbb1f3ec10ebbe3787d0f5641d6d7fb96c810eda202dd0000000000000000000000000000000001ca1141ba9542c56de8991b313c6ae42fcecb6751b0b81b8cb21ed70d5008f7ffe831766b89880a7fa6dfdb09a2cda3000000000000000000000000000000000e6766b17db165bba564ac63ab88d3f8f5eded07a40b48644e60d3223d30458e7dabe404cab8d6f9fe135712ef0b1a43000000000000000000000000000000000dda3e6c87382fa762510e5cac721fd2b654f002f5b9a3767a8c6d651ccc582e80e3f68d6913cda30f9f51ebcfc7c98600000000000000000000000000000000059a7dac5bb6b504f2bd603d486700fe22c14f25254537b2c9079c2b45d36c7ce56854c5699cc7649b533194f51a9045c00eb20fe7c292f3ad820a074d8b3d8d24506612752d8677c2d6ca24f556cc4500000000000000000000000000000000090f4b85961ce97cf7f99c342d3627105d790f611e19721a43d8a0febd67ae393d77a02b999108efb56f0397dac22703000000000000000000000000000000001112f23595d1613c47486eadc37f9b1ac3b3c3973b3fe964d3b67c3996fe2eacd9df5c287b0cea8e9475d146fabcf9e70000000000000000000000000000000018f46f7ba3c9af34c1025c2d460f0be966e68944928dbd55cc7fe00e5def598d80b0e3801e48a74963c974ab4727a52100000000000000000000000000000000096845338d5cd2ac44e097607d6a1a05c241eda1941991ae9edbba965d9029032c46da7218b5b2338e6c58898bc4a820f661d7b30fb11bef70e15b257d7073885468a380862202b2d705a84827644b5b000000000000000000000000000000000aafe45ea7cb8b450a51263eebc28c1ded662972bee512e24fddaf64f43b74b66032523b3b104a4e9f6b62394436c6710000000000000000000000000000000015cb27e1fedfba2d1679f78a388f90b22bbf3e7d090f0ba972fa8e72f6e31c446f628fff929953712ef6e425d16eba5c000000000000000000000000000000000df9931893cae713042bf722db6ce394b6f346587278a154c271d8511e690417eb6dc47efbcebb7c2fb9e77f1de9fde800000000000000000000000000000000106ffa395ef170c99bb5742428ae88fa4fd7a94476985c099e3b700b7403d083281fb71a19640c6bc2321e27bcb33fe2346ce87c847376c8967cc18297e6007dcfacb6424e1d273930f38bb0e88fc5ca0000000000000000000000000000000010b1f8b1c492a56936da905b8738affba6bd29ae5fffd40ba6b31325181d3b489a81b23dcb69f6e71bd29bfb388e5a8f00000000000000000000000000000000116a115303b4774da59844e457844232d088062d920db67b2a8450a194be7e5340ebd4d106454fd9a03c8f50dbb1e119000000000000000000000000000000000eb521edd61b38006cffc43ab72d395d669dec196846fa4d6d43521da6c2fc3bf0994ce7556a3cffec7751b3bc5703ff00000000000000000000000000000000073cea36eccaa1c78deefb6029903c2b6598301bdefa9759719c3b590fcc5a6a4d3d4d19f552b33f4a3126a6e6a8448639a142c443a666499a880aa1cb9f523411bbc8e5554de099ab485b6c2c2e57cc000000000000000000000000000000000e3925fa085db73c1e67b29ae90f8773f83be5ec684402e8e2360ffee8a8368911e584843e42b0d470de78591df6ea6300000000000000000000000000000000075c7efdeeb16609b4a47ea442af4d75238fb7534fd96cb236a7886809d6adc2b62c8ff72bdb041bc51c1a71b68219e300000000000000000000000000000000088b4eb0dd185e51b737d797334590e982b7b0a5f109fc7d0524b2465c2c0457964eba5a6d2d4d99fb628f21f15a776c000000000000000000000000000000000fc79f6b38f3356972669290eeadcd992a22bc1191606b663a1e148aa58db3938f0fc65e536bc5811c50d9c7f03d3e372c01b7795c2d16b5bbbb1e107be36cc91b25130888956b0cdd344de9b4659447000000000000000000000000000000000b87c47605fc060a8e3677e84ce9d14b9309360a13c80d040c625fbf0108f829300cc1fca409a0f9c96311cd4a9a21e60000000000000000000000000000000014c4088f1e7935cf6a1d2475b84497ce6a250ee2c0c991fe51a2f2836388a354824b02d9cf215328dfce3f546713e21100000000000000000000000000000000120e59be3ecf35674eac6cdc559599b273f13f28a529770fa156f8e519734c451eefb35023639f32049cd19ea0d945a3000000000000000000000000000000000f97755b62a8cb8f861ea02c77819f0b58181aecf612d92180ba9b475f0b4888b922c57f6a1c619dd5514620a1cfd9e2c712943d8795a6104f024b9701c70b09cdee9494755bbab0576e2c7f7c9d48280000000000000000000000000000000005860cfb6be6720118623d2d8ba05e686df22744b948421dd3cc1b1691e00d9b5d00d00195b4acf7a7b043f764f3f1c70000000000000000000000000000000012632a3313dd611e8d969bddd556c2d79ff387603462ac78ded3a842981697bdac34ee6f1f4744ed2ff16100874ac24000000000000000000000000000000000112b94c317586e343acadeca611c485c3ea172bc10dd39158c1e678007130062a921b53826d7be6286963ff822f1066c00000000000000000000000000000000040de8c0dadd2a6c2a7ea0fa43e1a5f2f5a6be3fcb0de6875d8cef1ee2daad87125d12f6869c4dd3d931b296f1df2fb3d4d77f6246c57d398c57848db8d3f986c475a41a23d424cd3cc2b362c1b99f2a0000000000000000000000000000000006fcd2c4fe848e9462ba1112baad39031c210952adbdd06293a622ffe2d1c6e4fcc8773ec8913717018b97bcb9a554fd00000000000000000000000000000000130a97442f3273b7b35464545e7351faf71ead9b8996c63889a45945ed82bba29bff5014776c6185219a5234d8475c92000000000000000000000000000000000491d571bac5487b866022a0714be11b38bfb296233845cc434a50be1d35f516b8c6b046fe3d0a8f4f95ac20eddea01b0000000000000000000000000000000017e34b04e6fdf152c848f2432b7bd84b3dba3915f06eb77efb8035750aca9d89e92e1d1bc4871105c440d639e8d8b05541776ed9d1029918af4c5113a6110139b8bd7f938caa204373a28ddaa51430eb000000000000000000000000000000000f1b8df4e8fdfe32eaf227f5af9f2befc85073468f10b81d32d0e126fe2b0cc8e8adb8afcac73213b6ed95e8e843b97c00000000000000000000000000000000004e3fb435ae0fb2d8bd091f250aefe5922b353a64e16abd75627737f3bc56639f8b40652cae69c73ff1969925b0afdf000000000000000000000000000000001003aed7cfb00efce49d6b1a8eba27df87479a4d37bd7fda6121549483b669a1a761204b0dd28262bf27e5c8e180540f00000000000000000000000000000000114fbca7caf782b3296d0b26b4c362bf50acaecb8bc5726b2c99f904ec3d092d5d40991d0d30c8e79fddaa45f04a75d3fa64411438542922a7bac10806efaa633d31d37c0b223314a8b6221155b9c4250000000000000000000000000000000017faf481fd4cb0c373d21d7caad40e93d9a86e62d26136892fbcc6f6e48205543aff00c45e82fdd1d3e0e733de91e7000000000000000000000000000000000012e14fcb9ad4d9d15347cf004745ed4bd92097eeeb41c4cbcb728a234616363589d8f5ad4cbb61d31a8aa27627723c7e000000000000000000000000000000001513dad1ff27e053902e779e35d04cab648939317830144ea775c435a4b55e13fa2fef03a1256abf5c187487c25a774f00000000000000000000000000000000139da29de8587c7d0ca9237c37a116387385e9cea453b9e2003a37ede7aa0a3f4c1df55255897f5975b662be33622dbce7002f41c6acab677a0ad023bad2a61b11c1b7221d944018b5ce60bb61e87e96000000000000000000000000000000000c118b147ee3489f30c6ecc0256a314ab674110588e8b69ca6d265fc270c3e5b767817f861140cca5d7c6be4012d1ffe0000000000000000000000000000000014800790654726959fd876b035bade0da744fb36ee5b304f228663a531345120267c55ac19fd66022752010e5bea7cb30000000000000000000000000000000000193ab7ac2f151750356b6e178557460c9c2672b1736d19a20e3fa28082479ca60021aa68edf2524f1aa826ee70b65a0000000000000000000000000000000015cee9ac55ab45abbc57d0ea6ec9ee49f6c59f6b94f99589dbc08ee877d3a261ad77f5473fedd72ed7206647eeafb6eac26e55f09b787c0542878e4d720027d9ea465f829a4e0164cf618c5d9cde49bc000000000000000000000000000000000ef203fab794a0ef29eb2ebf00076134e5932e27c99d6d445695b9df2afe7563602e318caf5d44724a21790ca0ab0d180000000000000000000000000000000013b9b1b1d3e98b61b0f1a0ef3a1a4ceed57b6c01849a4ad66a86332b3d27022cfccadd3567e6709d2de5b23b23dba43f000000000000000000000000000000000c1fbace49684f4be32ef6178ac3a95ea3f50b11494340fb73dc5391d50bcacafb3bf0f2631fea9c4ec47327d644489500000000000000000000000000000000040f82812855aa3e3aaba826d5810c1049cf44e86e44e23cc6da437971b529d2f2676c73e1fb9da52640c981fbd710bebba67cc47e38a129ab1140fbcf0386ddba2feefc919aacdce6059a27a1e2efca00000000000000000000000000000000060d7a718dd02b147c265f71eb136d1f31781b12a41866b4f86d7374b93dd10058c192cc0fba928373b1526e1a5d7d7f000000000000000000000000000000000cf29275373c0573ef22bf87919faf5444847203c7dc6d2e18986152cc294be04a5b1a4b0536797158113a15276c4fc6000000000000000000000000000000001016d5b9d4d200d7b4b7cc3836b85d6697fe14db350badba9978c7b56983dd1a7e572640ee0372b0a4e2079ff4c1abf2000000000000000000000000000000000f2768d104d895473ddf8c6b3cd0e7c22458d0037eca6365c766879a07c95037ee0de00d32c974d767080935abbe0be1705fb566367d9fc142c4194b0525c16672b843aac1160f9056ebb115e80d377a0000000000000000000000000000000017b9ca4349fecaa43ce911c0b256680edb8a0906ef5460fc4d2004579336df1e19560fe960a7a7cd74bb6e8272e08960000000000000000000000000000000000d5b96dae738db59cc67a51c61bec6deaeefaaa51e3259243fa4b142ef59676231229ae386ce699fbe18c4c00bf9d49400000000000000000000000000000000111b79f4b68dad16550a13334d09dc38336a75a5da23a17b5064e2d591aa3dab4c2e982a9f730a7633070504663a24610000000000000000000000000000000018f6d3616a7eaf17c805a88c9710039644d01b61aefebf76717ddcda6f4bb34aa15702de1e92bdb27b27f3409638da90f7bfd990cc4dac62a0d730f56b4eb1c1ad77ca9cd58b089c23c2f6efa00b7fa4000000000000000000000000000000000aeb5c087644595d0912879f61959d2731ff55260c682ed2bc5fc55c13964ef7c1f70aeb55876d2264d558c31371ca69000000000000000000000000000000000e173848f4570525b03a2b2c86f4dcdb8b28dd6d18c1354cad31028eb1b8b44432c2346edaace093e3954c7fa6d338a4000000000000000000000000000000001949b0902506d111ef6318edcd7a58ca4d69f5804a028aee73c3786cb2db168c6a73b77194f7a021ae6ae43ac78ade340000000000000000000000000000000017c5e28ba6103d97e2f3d3611c0c78f06406e0da8a49ae29c7d460b52f75136920784cd500aa3593858b877697eb8424807c5a41ae2baa1e10ebee15363d1d4569f731d77a418998108f5dfae0e90556", - "Expected": "0000000000000000000000000000000013b49054c3957d1e77ba2dc3ef75775bab9f0e9f76b33ff22e244e897b8ab80ee0749c81eceea259e99b5d2a72251e5f0000000000000000000000000000000012e017e4354ef86f73ec51921cbfdd01e3113cff044a049bdd34e36401712420790cf718bd28afa280ad12104c1851ed00000000000000000000000000000000097f28bee5d903e3c6de14e834d5beea5c847c3106742978e586ba7e913f8b631a69c473aa10e19df9795ebfa3ea6a98000000000000000000000000000000001953493daf65b974b549bb98e735da44b543d6fcfd97176fdc7f6f03617d90e6bb952a607fa8e5791df5dc1c9bba2286", - "Name": "matter_g2_multiexp_2", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b9900000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7a7e300bcb3c740fd1f693d4c8915c4c46dcb627f6de6e4847f123623cd23bac7000000000000000000000000000000000f20a07526a082e88630a0256d134a8a5e8ada07b1cead39ee838dcbb30904e9016107fcbdf1f8ba182308dbe0b043d20000000000000000000000000000000014fb7732f67abf60c03ac902577532d0acadb5f3db0d6397a42ba693526ad74f2c61a0195bdc9704aaaf12e65aa6d88b000000000000000000000000000000000018cec4fb81c85d304588d11f8b9c51f5a053df11463e5812a1b2e6c7144522ba36bb91adf219892d0007cee470032e000000000000000000000000000000000b8e52d958a12a9037e8be9bc0d5045cade2d6ea05c6e68462b3a30b5d4ea34e5fbad173761e4e216b2e6958c8983b28b473df5e282565a0783d23e65e283a103ebbddb5c884183cceb62fc32d0e9602000000000000000000000000000000001468cb35a60898ed129f30c261b8431df6a154c250ec16d85a22f8717593b2c21853d123da86d977a7938c5ed74ef23500000000000000000000000000000000011f4e28e31b5f9e6877192a5e632d8c1ed7ca0c42e6e9902ca68f1c2de0f648c6064436012c5c7b14bb8d1078e02f2c000000000000000000000000000000000b25114b2697ca7eb1e6effdd1054893a188fd382d387ec098f846c1137a9b9baad01653b963a0b0bf3cb50c3ce3563d000000000000000000000000000000000c1d241cb03e642c1752b1e1886472477c19a2801ec032dc220c3243952f882094119bb92b621b654b766bc900d2d4f7a048ef7cf5d1f6f625ee3aba091147c389ebebc5b8f3d285e16ef4e8afe5c013000000000000000000000000000000000c80d4474390fa791ea5f2f16b41506d8ae13ee0993c8d31a07712687298ee7978a724999500c42400d2f788a5a36067000000000000000000000000000000000592705cc5a8875750a4e6ceb42aa3bef5593eda9e8212702a2e08ea70277a2a66526bc5237be33c8449301544da35e60000000000000000000000000000000000facabfbd15284c6433f17b0e6035d4fdd84d3ad2dd30a27d52809652ff6e7a684d7724697919100567ad0c3e1a26320000000000000000000000000000000006a0fc4e2af69ce15a356656f5d182a2cf213d76a6047a05a1a3375909d245f5316b91333d2141c0817438f0d87bb52da9b63c6bf36997118d58600c1e429c105a379b9e8b0de934ab9f433a4fa63dc80000000000000000000000000000000003f629618e1fc3018bb836301ccdc59022f0a25cc9c5de6e4c31fa08feea525c83256235e4ec8364e77e5df478f5f62c000000000000000000000000000000001120d6af221ba6f4351bbee4c2c664a769adb17872646df2c408f70c99ea991ffced4eab50fa98be1bb9426915f125930000000000000000000000000000000015cd16b028ce3d58b10aeb84b783475d894ab3f0cfdf7104ebb4f3417a038107128f07518dce548271061cb8c97e88af0000000000000000000000000000000018379875b68bc26107f9a068e5034f29dc2ae7e8830f8e9ecddc53fe7991206646cda33d37b31a47a977b46be58d7618f228da17f49667c113d2bc2a2c8a338f80be68496f5145b4be21a5786ca6d46b00000000000000000000000000000000036570783711b381830e35878fbeb187b84884a9a0e88c38e84124515b470e6ac18157e1499026b27f4f731a961eaf330000000000000000000000000000000008382838c18d56c046a8db495babf8d14c915622d7917ebe10cf7da7ecb65f174cddb9e70d0262ada961b396c5511b410000000000000000000000000000000015f63ce982aa581dad5c71fc79251b7f6336c4e78a4a0f4cb6f87167cabd31cbec987d7af4f11dc6d693a0b0774864130000000000000000000000000000000015c001372fe0530a3f50fb8b30e75ff4b264d673e0448211d082c7a9018f583b4d01790019874596c59c68768cfa3e699431e18a462fba704216b516e819fb3392e315b0c92a7411a329cdafeb51124400000000000000000000000000000000074d78cdd35ea17a3013e2301fe9f80f2d20d270a25fdead37eed7697a52d152612543781763e6035fa5452ab12cce25000000000000000000000000000000000e572236e1c203a1c0f99e6ec978458c1a143a6a650eee27cfbe406bb2858fe5f30222f468d119703c2f442bc644ff3000000000000000000000000000000000125384343fe132e16a9fc15efe1b3a9e47289e0afc4b44d492e33a6216edbc96d66c1ca66944a8296e7695f27f414c5b00000000000000000000000000000000084c2cbf0d7c932c3098ded7c70d4411eed882feb0f79e0f7f1c31f5fccb6d53fb57de179c3ba5754bc5e532c3784df12051041bd2f12f6e6e29924139770fe209b7bbdbcd6c0bcabbf5021a7dff2d830000000000000000000000000000000004d46066439c3ac559cce863c58316883651023990180470d2efd06e443a7caf3a514b54f15ce6e850d32779215bcf4a0000000000000000000000000000000019ce904b6c9c3de59f7d5017f60f1978d60c564f94a0f1964c24c876d1139a7ffbeb6d0d4884bbfaf5f2f189af6904a50000000000000000000000000000000015f1989719e69be95f25dda9358fb98aae2819e0deb7e2d291e2c01e85ba26a9da421896c6b6e2ed20f609b533154694000000000000000000000000000000000b287cfcf1dd7c6d735c1358dff15393ddd6c82e7a33c5d8005c4234cdf823c76a4725fd74cad74b3ec51df67f09af0fb96df57a600dc3b5aabff5b1034886d24f6fcf035bcacaaec738deb2cfb8f85200000000000000000000000000000000006b37e2226957d639fcb0bcd6c20b3c7b8372e7347a14b970e01c67c1859fa97c754ce588d0f835ecc053549d963ab4000000000000000000000000000000000c6a5fae8be3a32e3f70a4202a1ab6d97183964b9f7b9a084c49922cd9e0e952b0bb66c5580f0e0c417e079493bcdb4e0000000000000000000000000000000017b6132f11adc0d5d693ae7f3a0f89f5779708083eba23e03b0c9265e4e60624e1fb6940e8ee49d31618fa6389b1b50b0000000000000000000000000000000000a45c5f6df71359648aecb6434bad1619c39f10e279a02b3cc9725d0256bcd126843fc9ed29cbe02a32cbbe79774a3378176412b07eb7f423f23ffeaa0ee642590e0b7016bc063f3fffa93e1e35484c000000000000000000000000000000000ffed009c78ba9af8cd33af7b7697ae4dff863bb92365055baedd2299b7f5b5e8abb84ed434f7223c3e309ca53c08aca0000000000000000000000000000000003b2370c837dd6291818efe7c9af62dd51295c418739ecc509d42c92e2c97d12a9fa582946e176e8153fc9a273140b2f0000000000000000000000000000000001e63438e8b4a0462cfdff64a281ab4a7f48d51b51325817139f8ee683484f8695f1defc0c3efcca81d5fbff06cf9c54000000000000000000000000000000000192fc391cdc1ed6ddbd317f2f366f2ce25ba27b8c0f09c733e7bc0c0697544399a3a4f1186d139a8f6399ffa88e89a69c4b5627d84e153f3a4ecc14ddd6baaf1d62253a0f88d3af51be18d991976da000000000000000000000000000000000002e105e0eaa418d58019a849b89accf665a94ffb0bdf308a11b99b521de7af8ddb150c0e3b2e9c54cf5456b6105bc81000000000000000000000000000000000691a3b3986fbe1c0ea22329364454f37f645d6abe9310e883b9191ce512347e074e18e28b88c2adcc76190a549b80b40000000000000000000000000000000003f3a37a763c8d0d99a3fe36923843a22cb0fa18ced48493b2510fc99afe5b7699bbaa6c2ecdad8aaf72969354f121a1000000000000000000000000000000000f4bbae00205f54eb10c83d928d908fbae342b76050e33c51b6e282e02b3c1f132a4728dee4ea95455c25fdfc112f2542ed270764791aff081f1dc8051d22b8e18803a7e310393f21bb4a495a445cd450000000000000000000000000000000009a3e98fe4a98582ce9f274965f376cb45e8583775dbadf626cb1327c1f8a25b293b97e7f8f31ff72ba7e8e769ff25ef0000000000000000000000000000000018e4785ccb76c4897087c8a4242ddc744c6a0a53a4a844254153c23d6f16d4ddb945252d13f93101613f4eb0b1e2b8320000000000000000000000000000000011b81d344eac04d3471b1edde5e51f31f97bea3396580839fa094db58cf6bee371bbdc045fb60c3ee5c6cd5d3f6d3c4700000000000000000000000000000000073476bc5b1d52ff4ca89c3afc099417f473543fab6e59cf9de8a19705dc4bf2a210b1e6de4dfbde035c312be0c70c56fbfb7606b64eef0460b8f33a0be54451fb655ce0b81db89eb7862f392450354f000000000000000000000000000000000c414b95b298b9c673001173ba7e5ee3e03926f28068481cfa0b469ab556f8fceba9fd0a815180ae0b82c265fd4c6b7e00000000000000000000000000000000054a242c1cc1a9c710bc23305d09c2d613ee8eb3840b37943bfe83f9c1db456ab4436ad319fcdd8684db129d76c95320000000000000000000000000000000001683711c0c7f02e67374f190eed1ce6559479d6d199f43fb5b0ce7df7774a5cb21c86b3b3498855d9b69c5763acd8c4300000000000000000000000000000000062f87085dfec847af518bd71c078f994b090c3b27c6eaad79772ab58afa43993db52fb08649a32629d61c3db12c87318a29fcc442d0c2446697e94dc47181dca7a314f9073c06aba6dc55aa79978d7d00000000000000000000000000000000083eea9b5b2d5ac5f7ef51ca889a4317322d098a408a741827fb3419eb12a51c07c788c2798cb37635e224e99bbc894c000000000000000000000000000000001312ec00f4b3a4305700b44b3f215779a9a8bfcf5b5d3a7f237a33c5484099ec9bc5c8537fae768e2c0ec62168f383d6000000000000000000000000000000000cf1d5d05d11e1d07074dd34211d0f00eae1df4dc550c55bd2fdafaffa1ad36abd5da30c5d3a5aa2845b1d95a5cb571e0000000000000000000000000000000015223baa9f2ea4b04fdb05b05bf3a94dcabc5e64189aeee39c380de9a34fe6b4253f5795f70bbe51b80e1aec1eab7196d5b468797b4af1978983faebe59a28f34956dacf5b7f65d25548bcedb518f45a0000000000000000000000000000000011a960cf1978aa2ce1731b857fd91d2f59d4b8d7c6871ef6f4f85aeff549a2f397949d11a4793926fe7be37f3a83d11c0000000000000000000000000000000001954f056834d6e3b16043ef1acd0a47a353300257446e9a1db7e58bd0d7c4bc9ceb3db51ae01cfed9de99621e96934c0000000000000000000000000000000002e2fe460e71b65595ed93a0010e5ccd1a2c16fc4e0d345e7226c947f29720d2f3f54282f79cec086d3fb1999b9629b300000000000000000000000000000000060dd8a7ccb613f1521168a8a322aef9f84d9708a893f704f4fc9a19e2493f25620a47e0fff1bc1e212e65e92873b4f2dbc6afcdd409e5d50d7b655580f1144de77f3efe5d6268032eccab7deaaad997000000000000000000000000000000001472caba61c2f1fe4b1d0912b114c25de103ef4351668f22f3a158d7a347539a7b6656044bd490f036ca3e29dbdded370000000000000000000000000000000015f8cdf7786410b409f218164063c99e77d8f72f03882a6c9430ec725ae574547d3ea3cf30c3ad2c9c3febe6c30b1272000000000000000000000000000000000ccbbed85c2809433fbcf22d6490457dab800b21cb4de414c7dd1804a0bdeb7142f8ffbb2de921c2c9eabee6a6351026000000000000000000000000000000000a404f42c48e3ca408d3f92079b99805004da928f128206d8904ecd7fcb14121c7d9a9e7fb69accaff921315ef3d5372807347519f114e78f99617f6b147ca833bff7be962c9b1e1f32b5babe6067d7a", - "Expected": "0000000000000000000000000000000000fada9f43b29abe15693d047adc277814cb94694cab3be56b92312ab7666649b8e9d92aad81f8e487be0f74b9ce8c250000000000000000000000000000000007f6891775811a325cd7f548011ad4c705ca0327ea0484d938ce061c913a7ee6978293c3258c4b865d5c2325816c39990000000000000000000000000000000016761f859beb90ea03aa35e954d112da02daa8e76de80297afde9c29cbfe8ef4d42dad535917685a99b2a91b1f952ae50000000000000000000000000000000012a4f24ab88341dfb8a60c19993b8abea96dbd7033d3686c40903728b4fd4da7d07961f2584b51e9e6c05976d555757e", - "Name": "matter_g2_multiexp_3", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b52f05365c4df20a7290aee71a7e030615d1a2a971167884d835c24e756a0faf6ed0552341c561446c7fd3d5e887d830000000000000000000000000000000018718ef172c045cbf0bb132059754b62414097eef640a781db6ad521af5a24d78c622d9402033fa939f70aad0510a1ac0000000000000000000000000000000017e969e44b4910304b350b5d442bb6a0b71e1f226cb4603cc8b4dd48614622f3f4e1ddecb1894046649d40f261d94e030000000000000000000000000000000004dacaeb9e05b9d60ce56c17312a092cb988bff426b8a718cdff860186935507a06eddbc4a1a29e4ef88db83fc4b6e77830630695c8dabe9aded1b5365bf93770aab7e9ef4140a2bbde2f0a7b109724d0000000000000000000000000000000019829d5799eed5a081042e4646d46fb6bead6d3b9893a4240867b25ed6af6a3e154514f244466d80e3b9311e060bbd7100000000000000000000000000000000156157a654db2813cb9c1b4da0a3ee192fad076bb2767020fc5fc00e967c1a35a367ffa375703e1181b3705ace9dd28000000000000000000000000000000000093385a6a9dd0ab996df54b23f47f4a49b3f379e11bc8331016ecee6161fcddd22f6d49fbb21f098873f1e17424dedca000000000000000000000000000000000d5b5b0f2ce81e755b4030b33fe3a8bdee38c2c60ed3b4a88bffb9207cb762c0a5c699ff424c000ab080d763abc5438d184ef5eceadfd77b3a4092696ec34d0551c88e434567638623740b7d5f9e36160000000000000000000000000000000003af8c25bdbd0dc1cc344d55366f15555709a74e1f0d8d7050cb6b487759db6200401b7868fca3c2ad26e6362a30e6250000000000000000000000000000000013f8b6ffe30f9a133fafe64461d305cc6b2cf5aededf68ba396d4e00df651531c750a3d94dd77bc5c6713b939b18fa19000000000000000000000000000000000dde97855d7728f409d873b83b6879b45ace5b73f317687fbf478e594a959ce21d4d751db646ceb20432e8311e67404f000000000000000000000000000000000fea997323cf29710cf0e3d44ce682e039d6cbda155e43c94dc8cefc5e94000de4b9525123b9615b5f1019a46ef37ad3a80d9efab033e920061cee8f8d7ea6023cc05f08340642613628b39e7b7fd0af000000000000000000000000000000000cdf60e3bb018407eab162822468255bcffd54cad9127054bd1c30705a4ebf1afc7f539cca6ba4cd070b44410ec751150000000000000000000000000000000009a2e3e5993b6a7007dedbbd21737a8c0aef3ecd4607953c4a24bb3fed97ccae01ae1cec024443f300b570a66e9ac3bf0000000000000000000000000000000008a21fed19e9ec2a741ade7767b0c9f39b79c3fbe34aadc9eb3043583768d893bf927d26231759290c7dd9c4f158d5a10000000000000000000000000000000018eef4ff88d63149d2632c9db586a4af0606644b16c82fbb0a3b869f1ff924c59acc8efbfde7bc604497ff68939cdd0845111c860f6f5725f99b225c53b9fe1a70150e7ce922bfe214900aaa2790d145000000000000000000000000000000000f5d47911596c46c0c08cac5f5e7f6d0609874da4ac1bd4e0e59c393273a5fe31a756c7cfff2a01d19e79d209d7c6d3e000000000000000000000000000000001010f864eb6624132d4436d18db7f5b34727060dc426c109886be88031e3c155490cb3fb09e1fbccb7912875477c6d840000000000000000000000000000000005cfbf1c2ae1b80a8c7cfb2cefedd907b0552794f4fda101ca1a723b18de8cbce30eb54287e1847cee3f416cd8b45f2c00000000000000000000000000000000084fa63781f7eba9c7e911ae5866d485bc7e90603541c55d1ffad8b3cf7547fd57fb24b14002560e58410b828513e109c07041840216d60ff445cf53b273a46016c8ecefefb53550f8bafc79966f863a00000000000000000000000000000000124870cfa469136c638e0cbf15802f2699aacb66d7e4c2965c6759dbca4b7e47941ad9ec37a84db1afeeeaa65a7418e4000000000000000000000000000000000d4503049a6a53536bdf41dd832a6ecf3f10554887da7e389cf940394e1d88db94369b7947436546eb6c6e82c48dfb9900000000000000000000000000000000053f9a6e1f05b67cf553073358009a172e2ab8b43572a974da1f3de85a29103b13d7e67b2a359297172d27dba5c61439000000000000000000000000000000000abc29f50ddc1c113c73700b9b9796890cbf48818ba981fdab2db27ef1c58f4c2e4595b99eae397d40990ce2f6c9317c29b031b82dc8c9f4ea9524793b54207d4e13a548d73297f2aa6241aff57abfd00000000000000000000000000000000007d2aae9794b7a7de97f7146c0ee8415e09e56fd42535bce6773cadd6f7ac09c4eafe2e926cb7014377e54c703eaa9dd00000000000000000000000000000000172a4a33ccf99eb0473b2c44d30bd53159afae0c7706ad128bccf6258974d5e5761f9be43e618cdbd96027aede7fd5860000000000000000000000000000000012601bce2171c6e4c2968a3efdf1491285f9e4ab37cf973ab5c8e224ad5b40e1b6459ac89090c73deb8fc79fec7fb8e200000000000000000000000000000000112a6443116e6f98ab348e57daa3971b5fa506e40515e1611fbed3e7dd64c5c1e991e0d2539a70eb93e3da0f573d6b2263d26ae92119c7b06d83d7e2922e06559b1740eae315c6623d3e543c9bf54258000000000000000000000000000000000030372914b83644fa4db1958831e9335c72ab7a811fb337696221a3290e4c54bc10c2225f8fdc3a9f62632ba2f1594500000000000000000000000000000000114205926609470b6022d24046a1997c048e6d2cf6043397892c967692161c0ceedf409bf5e1199a64eabb1ff8de23640000000000000000000000000000000017cdecbe73779855b7b94920d4bc8ad057ce51c5481a5579650df8a5bbc421030d2ac44568217c4dbb13d7c639760236000000000000000000000000000000000f194fa814bfa7396697bd812d9449d06fc61b580d7a86429fdd1ad376e21ceca139356d7d13964c3c684563675711c67a02c61a7a75342ee7f0745886c0ea2a73c21500aef8078d21d20b7216c2990e0000000000000000000000000000000015d4ae1521acf897344c3a76261754ff99742585af4a0ee86dc473a88fd408091404df1da9d8bb291db68bc9c07d6b2b0000000000000000000000000000000008ce160213875c661163990f3f7ac219ea295db5e828354864517ea8689ec15d35c6df78ff14cb276e0c97ffd7fbc09a00000000000000000000000000000000038a3ee211e777d6d6b7ca6c7a0d2130f1a071c030eebec412c3a0f14c3584e7c5cf15de254a8f141a8210a90249ee5a0000000000000000000000000000000019f7ec6b2fcd8b3190ab37a6e843340d3f3fc092f5772a042edbd5bdc967b96e8a1dc9e435b8463496aa1301f87d0e5a81b0c87102055dc2901826875d5e85a794befd93fccca2b9c0a1f70ef5610d83000000000000000000000000000000000fa7f8fbfa1d4ef5f001a451c55ed261dee344025e599884b29d086e15665867932120d33bee579d5eb1b7e6c7299f310000000000000000000000000000000001f06356f793350b17b47a623059a068800ca1eab6089c7c146182990063e8e23bbf40d95a42bf6e976224b680b75bfd0000000000000000000000000000000008807f6606d2302450bfd8b38fd4147b851ff59762c1ff48f9442c4d7b77a32c5e023821eb47fca839a27fde60e5f61d000000000000000000000000000000000c5b92f1ca9c20d4b6b11d794a5853824cff20d9267a20a7aaa4bed8bfdc728c4d4d50feb8f0b569757b97f473138db1ebf66fce49c6beb12737fe05e3adc0a51ecfa9144ccf6253088dd1a7a483de070000000000000000000000000000000001191410ec6c5ff628bd25d35965f5e9fa7f3c3d8c0a9a1ee7ae37437a97c25e221110d892e2c7a0e9c8e386774eadb80000000000000000000000000000000003be30c25a18cdab139277232d8888f6d13112c9556895af8030f1893114d5845d895df9afe3c6f9ff7ffb1919adea9200000000000000000000000000000000197f6b4e38be0358a3f1722664c61e62587ecf5467f8aadc3a236b47682a75cb76bafb18a5c556b321d5da49cd4bfd4e0000000000000000000000000000000002e4ebf7f22d929b7421a600e67fa2e64a59edd87a2e2eb9dce1f06d3c793f1a812bcdd510e654d44fb4c1de8c64ba9f0305523dc79dc4b905e65587fbd095ed57aa42403d2df5dd489db8f50c99e9b60000000000000000000000000000000011c6f1dbccde640f63ad7d40089779d01075e26269421b4ce12fa5341f58ee9110f17d08dc1052426f2d00da2dd70b4f000000000000000000000000000000000740b147bcdf06705971c113a5cc12fb37345dd59f2cbb5ff500ce2b347fc5a8199cb3007a871670d5093f28979cfade00000000000000000000000000000000046563ea98b5e85b3c42222d5e0d8481e6aefaf077a1b99f2b4eefb397ec846aa3659aacda569054c9c8b9b69750272b000000000000000000000000000000000812d887943506d68e3525ced9b979354539b7b14003a3169e0084c26326b92be67346920c9a99ef0f9638e8991296feac23d04ee3acc757aae6795532ce4c9f34534e506a4d843a26b052a040c796590000000000000000000000000000000004c8078fe8567013e8d05a546934026cdeee7d485e30d739407db16fefaef53ed7bff0f9adaaf064aff014ac919d91c600000000000000000000000000000000107cc17f485af7f22e07cf14c5cad6368323f720511fc9dda677b360567f769e47a77f61274927ef9b7be48a77357ec40000000000000000000000000000000001487f0880a6cbdac33ca35b9b65e4ead9d8c2e9180c993bdb2052060325aff8c62668c643f0cd9b4bb1f06a3dc74285000000000000000000000000000000000d4b2d062e31fabe8d2a329dbd6417673a519f455739d140246f2b3e43e20f390088c08e545bf0419d796ac71aebb5198586d7ad8fc3e4fb42981a4415224c0d976ebe1c342e9bc1cd66d35168bae33d000000000000000000000000000000000811e9b0acfc10830c074c5a4d9f4d9382461eb523a61dda0b77f1c43b285fc5c1ef3a1fafd923addc9a6e904505a255000000000000000000000000000000001113102d015dbb509f0b8d0d0ebb4d3711c4f0e1e3d55fb0af247dd24be4fec9d6fe3ad73fbdcfe206891bcebefee4dd000000000000000000000000000000000085aae9e58fb97b96ca3c089acab7bdbd0c3adae141bf61075f5c13145b0d07113f1075dfb959bc7c2d3d3b3a06ab2a000000000000000000000000000000000bb5eac8125807c10270d94e5bcf278241d6fa82f68e41b5529b28aebc88870af55881db526f7bd221a8c4c0b29a1b7d6e7db0fbd2a7327c85054b4c0de9727dc0b051058f8bb4ecb1dcc7f825781712000000000000000000000000000000001335276775545fbb4c701beb57cb34312108c9f1d46b4aa4b09a16faf0e648b4e80848bf5e75ed8730715f0107afc9820000000000000000000000000000000006ffff8736bab41b4ee5681b741a81fc870e648001027161144254d04c678e4f954e9f191bd8b26201aec681cbf0654b00000000000000000000000000000000026ede90d14fa0885baad21f9631bae058573251cbef5757bb8cfad061f3bdc78834fa5862dea19a2236c014b0f1652e0000000000000000000000000000000009844d0cf7f6f3401145d8d720defa577ca46b49e04e39c4c139ec6811a574e7dd5ce3acd00d1ce9496f10dd15c6d94685cc8d88273d4aa822f44a447cc22f5a58c420bcfe757a459772825619669a720000000000000000000000000000000010192b925fca096682acf138833b12d96bf97c9a2e69e4266eaaae1785b9008f36082e23e2d42341427edce24449935f000000000000000000000000000000000d5b24a94adadbf542aa663114096bc670e1b6c99f3b661f55de121922452534faed7f68d6b431fcf6f3e379d7acf6b6000000000000000000000000000000000acdbcae49206b749d8c0d21017a33e689ebe26804d1fe7c863a2ea4210c3559805dcf73685702bc56e644b4e02614a9000000000000000000000000000000000092309d684fcdf44bfa321d473060dc2d8a8c66c51419894a3fbadbf1b56179c31dff25403b970d543f1dd0e19e56cf5b6e462d809f8bf1a62f276dcb27e42d9aa0ce33fc4e149e87181aca70a4ccc6", - "Expected": "000000000000000000000000000000000b219032a2461a5fd1e43361c46beeae92e30247acadcdd241692abe81691c295ba38a1f0a2a45ae76b1b95d7d0fdc460000000000000000000000000000000016905f64e581aafe928520adc27c24703e7adeb36dfbb416a159cdb9b9a26c9cef0821ccf52f5ea5253b7c9d78769e9d0000000000000000000000000000000015cfff195b2123aa140f963628c41deaf19dfff44d26a38de4547c3d15edef10fe9f65b1802dc374d7ba8fb62117c8880000000000000000000000000000000018dc725cc8d8919a7414b7866fdc54c4467b0f87cf99fc9b36cd65c0ec526e32649f9c57495657a93487f1f2f5769168", - "Name": "matter_g2_multiexp_4", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014441b14765eee30e8131a7ef62c3b59370f2f6f0dda20fb2a3654fa09492bf695de1d1a8f250bfde3c7d2ed805ffaeb0000000000000000000000000000000019d813f8be2519e89d42a9fd3fef09d44a996d6a4713a9c224bee10f0ebb196370d6231fad810edf9cb4c875f08357890000000000000000000000000000000001a5abea13e909bbefdb51ddc699614366f271b2f6490ac8efcca7759833f3feae11057ab1b9ea32311e7b6ea6de110c0000000000000000000000000000000003ac2bf3c5486ca176e34ec5212165cbe04fc9e8c375e3e999a31fe014eb824ea3f2d06b9cf8b86ce3a76960cf2eb4d7535b53ab5f1c596eb966f57867e021d0f3b099e17bf384479c959794b17d6a4b000000000000000000000000000000000598e111dcfeaaae66d1522be2a21131350577253a3f33bdd74a04b0bfba2940e73b62fefa8f0c34c4aa91b633f6bdfd0000000000000000000000000000000017fefff7d94afbeceb33714e9b5480c3a2f3eabf9d7f6e8507ae54cb65f69b21cd7d04d23f24e3a272c589f572b91864000000000000000000000000000000001652e3f5a99ba8dfbcd1f90de955ef527947642054be603c1b84b24bebb579b78e2a0be426ec21d32783a0e55f0178dc000000000000000000000000000000000a6c9ec91e8bc86ab198416cbc76239f0ac0b903f40310ee1f2066b01b08191538ca913c2736f53f23ef37fea13d52756e0512ecbc5a1b02ab19bc9bee4d3d9c721278e07b7a6e389c4d6443232a403500000000000000000000000000000000072e022c168461905f798e87425f2eebb517e473cef98c255d0fe434863ef5811920af65bc946b29d489b5dee1066c56000000000000000000000000000000000e7a9872caa82d191f6014c845e1b3ee4ea1ee89852b546a2c85ddbfa3c1d4ce99002e3d7732ccb8cfbd57d550285ab400000000000000000000000000000000144be65db373f6401d76e0ee64e51076b861e8fca596dd6a7f3b5735c23b0cd13248404fa0969ecaa701663a1032f48a0000000000000000000000000000000014c9e9c5cffc4518889f7742440053678ff1d9fb1a1a103d0c1f762b10655bd5849ce98f4bc5eae80bdd9e767aae4523a79fd15e80b694122dddb01f836460b3eff99e61ea6309d6b395c94fb5a43dff000000000000000000000000000000000948d0f0c20715f8658e1f2b4f9d32d851e584287225a2f47735a1f4c241b07f8d7c5dd8c13bcdf84e97d49817d4d88a0000000000000000000000000000000013c064548cb756b48600dd535af8eb5b9138f984bac0391df2e90a204fcb6c36017df910031864d802a2ff719856b336000000000000000000000000000000000000b7eeb7c9a01be88e573f196c2a531635baecbc8cff9af385455af3757301436686596ec7fe3618af26953c49f7450000000000000000000000000000000001332f4dbd5461ab9e2c8b3c19c6ff407a071018c92d2c17c1d1d481c24565276c0f55eee8692016c1fd76d70f44627cbd012914a96253926fdaabec06944ffcdb4637a05e3e78a9bcf1b21b68b9dd9b000000000000000000000000000000000d3ee70610b5029a28e586f0f3e65bb19a263db3438710fcb8073e1b25f83db50eb5bbb9d75cb20952a225023f747baa000000000000000000000000000000000682f7d5cf9d182b20ee88683f3915e8c9b03074a373e573aa57232de4e997bf155acf680e365aa0988989dfad102b2e00000000000000000000000000000000143962963e230a9154dc328f9583f5be6923a3b10ee7b1d0cd5f5cbff13913d8ff78ca315be7387900a50b94449884c0000000000000000000000000000000000f4f934b42452d41cc20d7b1ec547bcbcbcc10f215364ccf2b864db23a09d06e94c7a87165dcb691f4975323486757ada300c7e1041d94df0e0201e1135fa6eafc98bd33b2dfbe4c59b546a52538c07d0000000000000000000000000000000005f0fd4080e26971ab16d33aeae04220ae23781da3179e38190082f1d167514bd73bc8ef976a2f333570e9f56a6c05e6000000000000000000000000000000000e159905d29b52ba61575c3a263093017783e1028b3701ccf060c165ba33a765b5265a9b1681c1759bfe2c9c401275e9000000000000000000000000000000000c5ac0bc29a49a7c37d772954da850e6b5e301e230552be9a94017d770ebe2cf4dcfaf104633623e024aef6db57892900000000000000000000000000000000002228e7f42a9409acab49cca82cacf306f6c6c29fd9f7e2ed12fef2d16383cdb7bb2b39ad598b301072c615232db1fa833e9cdb10fc117afb17803b61a2bca7de1d190a325639eb23743f51f28294b3300000000000000000000000000000000180569ce03e4a0155285e733adb18fbca71225507a7adf01cb8e8648891525305e92087f58378f4fd8455d5632ad660e0000000000000000000000000000000011ab84e42f10154e306a568d7cf7bc381000f0add0500cb508f695a3b283ea69d140aa0ad48fce2d2d6fcafe60761078000000000000000000000000000000001136c3016474d6f475609606e8d0269fcdab9fd3188a512681cbc41eedeadfa3b3d9355e5b4503e8b5c3665e49fdf3ab0000000000000000000000000000000003f56cba1b9cb4302099b16b09c2602dfab80d1151685ef78e5054cd454b319adf8b5998053a5b9fddcffa020595e3bfc48b98edd9c229037751d02e58f3d4234d9a3b0ad9ae4947ae14beebb274746f0000000000000000000000000000000004d79dab9eef873f3415d66172bab7166ce0c71f322529bdeffa915c1b0d3fcd645c91dd3450ba61593ffecb95edb91e000000000000000000000000000000000d611a207d3222bba199fa083d0459675cb5fa00839fb4c9034ad868fc1e79d653c18651771431d6fb6b6b5ce8cf6f7a000000000000000000000000000000000ce802ecb106a4f0ca4efdcc058dd0e29deb6a5d30a2c15c8eda896bcdd3ac19053c10105328d239b26c5ddbdb3a95fc0000000000000000000000000000000001073e142621ecbeff6f81453660362545751f992ffeec3a83477fed3e6215a709ffe0d17b65d3369f8f3913bf000e844228758d2cf8105f2ef11d83018157a3119a44874dc34d5f0bddb533f50df52c000000000000000000000000000000000bd84f04b3858b1138b1b429c7216d5d1b1e99c1e0fec26440d59b1ad79788c2d5583122c2ad769fcaa6d10d816a1f1e000000000000000000000000000000000387977ed1ce5da51dca230531bba53d17d3de5d593ec576cabfe6463d5164d7153025dbd4cb3525c4145c4f6b85fc76000000000000000000000000000000000a19c943a90fec6921367a2edc5bc38a5c59839cdb650766a2d2d068242463dd4460bd1d0e7a7fb0e3d2104704b8b3730000000000000000000000000000000011d99d44b200feebe00bd42809e3f67a23cce88a07165416cbfaf4db14420f99e54d62db4280d2c99ca0bc3dc41eddbea417c96f0cf4355a78513c77cdc676a7b09125802c8045756da867e0025a36f10000000000000000000000000000000006a186aa584a466a860849c78e4922889c95a4ac6f39c99029fbb422c43d699a8baa51aa4ef51ff99557babeb3e9506800000000000000000000000000000000065fb15b5a0923bdb52dbefc7e9f1a898e32f17d610bac829235446fc5e1913fffc8176e0fbd33091505761f1d06d8920000000000000000000000000000000008bd358698fd073f660ed608462cfcef1da9a59b10905f1d98c4fe66958e56802814906430c10fc25a4d351d91f91cb0000000000000000000000000000000000a53638b1b6c6eeff468e099446300ca7c7bd899c6494682d14fdabfa9cead0bb37a0325d99e7d0ba6341cfa1d257ba846561328b7689b0a89014823537cf9eeaca6ea5c56a3e58d2abfc2ee455dfccb000000000000000000000000000000001070b98c6348a67e996626ec2752f45e4c007e9c9668459a777c03fab633c10236a1c5be99f3fd950542d5648ef9e88400000000000000000000000000000000073a564401cb1a3a53334c0a55da261814d27b86ebf40b02a76b20973ba2db92e42c138ca7790261c2d70401c984bf470000000000000000000000000000000004212d8a9e4b01f5c6814a88561c2c6143eea61327b031a2e0e4bd056c12dd7098fdfe4d1511bb441ad42b55b584a7bc0000000000000000000000000000000005c5d23824b0fe05eb962194550681c57c1566b315efa8ebc90b3593d7d86ad18328baab8118c9f47eccc0757588591ccf6c3fcd4b9e6b72853934b306a078b1f2fb17879db4a0a93d484abbc2b746cf000000000000000000000000000000000b1b3053774ad5515a20bd4c556d2b3ba95fe74fd0c955069c7f933dfd718ede90ac295f5a675f1c29dcd9701978353700000000000000000000000000000000145746ce88686021a0635bf6f0aa2f77c48bdb364cf4ffa804a57f95bd69d24eead05fbee24021c1ef57e1c7c7b894b00000000000000000000000000000000010ec4795a0762b86f3b83de1198698af67fd1b1be3ddef48f35cf82bc96d886fbb4c75064f51a9cfc5f61630c95d0ad1000000000000000000000000000000001465e31f58892466b8ae4b76a239d9f8d1ecb1834886344013cd1df0be13591798868d224d38213a6d75b02a1fde0ff2f6787b565e8d71be6fdb0c97c4659389c800a2047f668b366214adc716f402d5000000000000000000000000000000000f39e731e6ddb7496448c912ae314e833d28208252c7f8e27bcf7eeaf1da6e2310538b4ef0d55401c6552e91fd70691600000000000000000000000000000000069d3612f924961f827497028737000513548ad8e104acee28f014e730d4752a583cb9a893e6169b71966a1c4a4ad2dc00000000000000000000000000000000090899907edcbd336bd4fdad0dd67c578ced4481a25b864b32aef920842689a2c23265277a6e1d4a1dc1b5047a9f79a000000000000000000000000000000000055ba64e2502baf68e46c759fca30247a080464eda2b32e7cfe539e545d6aac6dafb731c2c45749e50513979cecbeb5440ed91f6ceb2ccf87e4106a16227a3cd7b2821b4f3a6e629001f78ba1aa7346e00000000000000000000000000000000042f1c8b9fe81cdcabea047d0998a1354ce09d62a14f1d0e9d188e2f35f2e1845c2b090c5e157595b33108c67e6c184c0000000000000000000000000000000018e69d3564d4ccc0306e1e6b227b0f961aa9afcad59d4ee1737f980dc876609c59a4c6a3506f987467beba0764b857000000000000000000000000000000000012ce5883156588cfe0f4838f819f985b09f1eab40a5ea8e30fc5d70d029a01a4537641248f4c21dd203909e0170737c80000000000000000000000000000000002888eb9778a4045feb5899dda258657b9f41345731ba630fbbf186b3be4b58ffc7f48abb65b693b573a73f85440a7a7ae8ddfcdb4748981acb9b2037c017174a140f2457fb0148fe807fd194a9f7be500000000000000000000000000000000051982b46a819c74105cb36da871fb2415328a1531d155856f6551bd043eca62ddb61f24af429edda830fda31e22cd340000000000000000000000000000000006449e5bcdb5619aac542f6633ee3e06a4fd56a3e1ce4034efc608131ff6ead70ca63e70f494f519d5c577ae7119c8c200000000000000000000000000000000153f4f5dddd5801fbf7f88a735b9170d24d5b63861d50cde9644579dcff277cdb0d5fbfc3b3b819a1172de05afb9135b0000000000000000000000000000000010fdea84983fe6c08cdc4b4ccd462bae2ba791ab5209363b10b3ef342c9a5e92184e9d8be1419e3d88402bc05bad5fa21268803aeb58a2d57fc797358fb456d5cf96afecb1ee0d2b90782aa0d652b8c00000000000000000000000000000000009b011f793d9a939d916d058ffe91b58138820a646cc450389b3074ae3715d06ddec1075afecda71c65c7ca085210c740000000000000000000000000000000003d4d20f4b93c1e90a0a06bd534d8b4fd64e4c4aba77ae42cf4c5b2bd95f8b02ec4069ea246ff46404e6c9eac632fbac00000000000000000000000000000000051e88c3adfd4d6a02d3f03812362a6cfba3a6c69b9aeef75b51106cc7f1750293d61e31f0ea29b5d7aa56debb6d2aff00000000000000000000000000000000086d9c4ea6769cdf49ffbbf7351023b4aea640e8c90f9291222fd0b5984bca4d481bf7e10df921406a34804e6a09f99df9a8a4e5c65973b785c1e2637937de239bb0fde34b786dceea66f6bb12eb4169", - "Expected": "0000000000000000000000000000000007638fa4e8823dacb40ece440f8f1e57cc5c3851f94357a5325207db92380dd57a7c8709e4d00b670e8af1b77368285a0000000000000000000000000000000005b66a6e6b13ea0eb367a61ffe7c620d9edf5563cb4cc0cdfa68b99d9691cf9a40efd967c1e880238eec313eaf4c92ad0000000000000000000000000000000004f7156c69ea88a71a0af2922d1caca24055d40df058eef02bbf95d864156f62fb0e17d9fccd193840c36ad8449bb4f7000000000000000000000000000000000b8f46fd695c5d96d939d42c65c3b709d32f134710a67909dc4bb43d752521a8d4f0465d0590f30f06ce42bf5f8cac28", - "Name": "matter_g2_multiexp_5", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010d48bf523f3909cf90aa58a9517ef5421f1212accd5e8a0f830aeb15a587e215ca9c340bb846b1d0474e43840b2af79000000000000000000000000000000000cc1a3976caf97b9d59f448f6d9f413eef8904f360c0cf912fe942b38d7fcc637a17038973a133608ae769d3e389b18a00000000000000000000000000000000069a6122c6f0ec68834b7617c755a7eb33a80a25acf95859da5ff03316447182f122d20d993b04e79b6fe859b7adf5a8000000000000000000000000000000000058c6f8c297524319bae6722e0a957d1ba0f75ee3a8aaf06148641c67925d15780e419a38ed7e07410e82769da74f2d070e7e2ae2751a1f71962726a31f77553c2da38f4fecda435b6e5459d5e833b400000000000000000000000000000000156ca5e80be8c8c03a5506ce9abd22a9d4958c372678c0caf6f1329898507dfcb1f06a9464cf080bc6881fa5b7df1ebe00000000000000000000000000000000088174d486b4086b931010da298a399e15b60a113e08f571e096d3a4e94b57b3a684711318796eeca9319119b201abb30000000000000000000000000000000000b96ff68505c088cc03a1c2dc363b05bc8544728a12b29569bed137780523123eb17e68f4632383c252d81bca0c5ca9000000000000000000000000000000000486fc6e5224c5fad56234c41856e60bee4a6c1046f673bf7d5c1bbb603b141fc91074da5f9d3d41b796a2ebcebd9e74d16aa883a20307f5436354bab32b4633e83178f33626af3edb14f82724b8e12500000000000000000000000000000000121fe97c62e068988ebff21d8129d52aa903afdbb62862c7fd99564d9ad72182ab1f3a1100223ae486cd76f6938e123f000000000000000000000000000000000968ddedb04f52140160061828b5f88dfd09aaf37df625ee6f66b9500d6608df31c7edf86296eccf8f9918b051a5e4df000000000000000000000000000000000b7491cb8f6252e3861d7160feb0afdd736d27886863ec0909a7cc711a9b71aace18b17a00a2999dd57ca1a74f148516000000000000000000000000000000000fdb280093ef45b12b694ca3390a865ee18e4c04b231e2c98cc28706d4cefaf4e654582ee03f34ecf1dfa9674489d553041390a2209b80f7c64d14965cc2f515d5fbdf37953f75c4a0203bf0d9fb674b0000000000000000000000000000000010d001a09cf5dc3276482185f26ef3f75d28cd6d2667eb08a7fe06c03b99f3b6c4d82390739b6867a314291cc642a8b2000000000000000000000000000000000587846a460b1f37c2e7f491f9a097b4e86e1943d9cd0999313f65627b3907f09b5d5ac1be376a313a959dd136f7e9b3000000000000000000000000000000000af439695556e86b102926d3b40e3e54cc84464e120de3b4e3c5541a6a5bca44151fb0594009663764c1824518b13f020000000000000000000000000000000003bfd9418c1e57269e222152d321b83ae090f216cb422956dd1fcc464f68526cb4a05cdaefc7bbe6e81d4ffe27d64db47cf23dee8d95d94046678f3bdb4b0ea3d4e3a1a2f07f582e2a98ad6eb7562cbf00000000000000000000000000000000196f78b64fcc342ba4f4edf34a3080ec950532a5de21a875dd061f09351def5ba3b85745a561e38117a14c20d33a14610000000000000000000000000000000003929c2bc55f323d57dc3529bcf6644e61c941b72b424d69969c1cde7a804d157045bbf6d5b79a3e6686509e11ecdac0000000000000000000000000000000000f6b659818510cde463c52cf00bd99da045c80af4d5cd0e55f9bdd81f34169fe869c519f37a98ff20c56db554469087600000000000000000000000000000000129709e97757724e765f6600c2b1928286efab55ec8d16876a2a3210bf9d31cc5425265d0576a2d5469cbd9a6c8c27c012adc8edb64db5bf0ed6724f3b54140ed6c81ca65ef9d1b38c8bca6a62bfd3c60000000000000000000000000000000009f5f167c9b61a0ef76415fcceff04f3fa57071c2d79f443ef8a7e6049cb1352f650ebd8f358904bb432d42772c29afd000000000000000000000000000000001524a875d73e03c53b92465bafca582479110611bac6a98fc7d76966e9781308a10cb202289c0776cf5c36515733ccf900000000000000000000000000000000002b1acace94a6fe196b217a9aff413fe0bcb55122ce9e344942843e5afba0d5f2cd0bba14c9c8cb9dd1c3e9024918fc0000000000000000000000000000000018e4f85c7663e596182603862adb559635fdf16ba35fbce7278680ea289f871bcf6755d85654b2a37ae77a37e77ba06ed1535bfcd68e8136808edf89967fbbf76b7f58d1a8ac95ebd4944b9e440f20b20000000000000000000000000000000018ee4b4855f866781f38a618c2fe4214c63034620ea5b72361079b0a5c2b2d6fb9ea73fa202db3a2678cf07219cde81100000000000000000000000000000000180870513afef93870ca64e2363fa1aa43a599db97f3b807ada1c25ae331c80b8ead5cd69b6f5a65a083606591de90ff0000000000000000000000000000000010afd546703baa35a9eabaeb45d301bd5be115557bbb4ff2a0e493668ee790e947eeafcaa923f62ca00b8e635994e39b000000000000000000000000000000001089996b218aacde4ccfca4d2f66d79fe161d962baaf2d6696e1a76ea40af4ae7195e8cf9f6417ffd054f20b65ddfb104c576996d90abde581afb58903cde4b9443eeb65e21b0d68c578e04c8f28f3d30000000000000000000000000000000011757ad74a3fb341c8eb6862978ab3fb5e8cfc8fdbda7d82756532a890d61919cce931872ff339843805e00d8c62ec4200000000000000000000000000000000060783a06e93e82cb08e5dc1aa31202ba11676511300e186ae8e45248b7fdec3b7d5b6849f8b79b8f78ad84f36218544000000000000000000000000000000000ecfd8ab18066fe3408fd20f2a4478156e9a19a09b58da76486c9f6a013d861960b6b99bf49cbecfa8c9d01d5615c1bc000000000000000000000000000000000b45709845d35d7b560745375df79fb95df15e85b96cc1b98cc832c74621339c609018d153bff93f2f5493a52b7326073c558cc615b1c61c9a42b8b0ab4668ffcfc9e95bbe958e72e7a5500058e6b0bd0000000000000000000000000000000003f9de90222619216852356052e9819d7c6e8ff91e0c6f1d8cec832770ed9001db4569fbf579ab16964d76ae7d1b89e900000000000000000000000000000000010b7cf8f0d283cc22942ed73c599115763dcfc1ddc98d87979fc3dce2f33ca3531cc2909d94f86736dda2a4e94a4f0c000000000000000000000000000000000b0aa4d947644cbc7df8d1927cdec66a68862e5a806e25554f27cc1a3701f429fc7097497ad0419e21cc403b472c8ea900000000000000000000000000000000146270ecb66e1763437b824f2ae122f72f20eb93fb30474691a0a192ceb932b1dee111fa44954075335ab360d31ee68d61301b4957a468e2817db5914ff102bc96460a2c5c15e78bd42884b1223fa71a000000000000000000000000000000000c977cb8de4b6e2e33d916f74eb4e42f089d22b54b59fac9aab0e4cafc8aa2b0f8c55d7251662b3499ea140e322dbbff00000000000000000000000000000000106944a9c2d2ecd08e109de29095f3460128bb751051a1f079acb58b6a60b0bb5f52e63d47b688f4a382a77c3b039eb5000000000000000000000000000000000d2f8be1c78995d54fbccab61f816b6ec52dd19aee6aeedc0e4bde2898b2d07c2925da0440a38c4c965a823fff10389f00000000000000000000000000000000183b5d15b243cc5d9584842ab1a0a1e01ad87268728d72aa8c0d7ec6e7069063a11fdd1525d2b30b35e4568da7c44c5495cd2686d24a5bdda0bcb118a2c0eb5ccfe411ec452e1beb3adbda7e93ea367c000000000000000000000000000000000f65ad4c21fddadcc49a8f7bc281d2b7901707f51a67122179fe97da46ea5e1bc6e70d68eb4eb6776307510a67e972620000000000000000000000000000000009003dc68cb0cdec4a502436718f066348f1957ae65ecca8d32c5fd776215cb9a098c0ffe56c92d79dd68d251f49f13e00000000000000000000000000000000038ecf0bb98ff2e84b388c58059ba0de0cff3d5881ecf01d668495ce81b76b00323c665ba88309af5552b7950cc8c08f000000000000000000000000000000001924aa0f460659f552458fb469467a2925fcb2420d4fa6249310456853be3d08bd5c37a3f0a9d6e94e434391d20cccedfb81d555d1e2df92cdb487a888fbedad976dce54b5c46a39893edeac21a12d6e00000000000000000000000000000000189c3ee691387fbbcffdb147c880218c3e5c0bf78c44461ac1bd3ecd5d4b85225e46cdb068049607fedfcca14882e289000000000000000000000000000000000260efc08531083db2839d1413c90968e87d79bc1a2c730f0020e40beb92e84b73ef43e80f7c61e1a30c0cee11b3cb370000000000000000000000000000000005c852ca0aae2c575c65ef18b624f50a32c007d299f24a3ec6cacbcef1d6e3bdba9650fd7d639bdc60a3e107ee9c013c000000000000000000000000000000000321c01a9de69d6b89db4ed88dd48261ee28facc5e26511fb2833fa45edfb58051c8c3ce9501e8b4c3cab9c456705889bfeed84bd95fb955d1b1045c059ffd051324dc8966e504164e54f76f02eb1b8600000000000000000000000000000000183d50635b22e4d620130e0d4008e3bfffae5dadd7e34f4496899ca54eb4d9e3e95c54ae1d9664609c58d02ee5eff65500000000000000000000000000000000029e3b4496a379464302b1476a4549db371f5d6721704b1d6bd35e2344d7679f8a61a0c3b12f287fd86fd247f9652cea0000000000000000000000000000000012c6a3793fd23e955708f5aeb4d6efb670d25a38a67813ecc72f899cd5f926ab7ef198bf6d591328383aaf54f756c66b000000000000000000000000000000001914d3e4b6ea96bb91333468fe8f3bb74636e9a4f2ed198e9ff01b49ba02791d5bd63224f6a38538aceb777168bef688e3b308b95f6d496e6d5b910b6aabef8d9f868471653e8254ab4d49d593180d250000000000000000000000000000000007457f2601621a99050d8993244f026b9a62ff7055b325e6f1edd1cf54065785f003cf7c8a4bb1f7bdf14e220e490ada000000000000000000000000000000000928eb76b428dde37546a27f3d77605c293738f448fbdd6d618747b0de04004aa4419cc5601600419c6e1d470c15982e0000000000000000000000000000000008074e9f5473492dd2e536f7b305be4e5c564cfc9218934d03dde6dc5118064ebaa5c26fdd1123a9c31336c37c1234900000000000000000000000000000000002bba1f9b7da6abd2b322c8f11c749b2a284552eab25a77d21b38b028da477a3ffec1901a015e81fe2893576a41e4c0bd4ea92e0e776be341c8444d4040ec121a2847256c5c9bc918adb28618548b0480000000000000000000000000000000003760958eac45397eca1a1d951a80265a728dc3c584f7dae111e7ce04248885321b69b334b00cdb0334a362676c2d32f000000000000000000000000000000001031e4a63129ec40da5fe9dacfe148a67662eaa00e1fd5c30336462371c167348a10e50f4dc18469a1a6b76485f77e12000000000000000000000000000000001412dbf993c557323426b486f18a91d16b4baa2c497b30fb332a710ac901c96d46a577d04ea87afb08258aa6d204a1c9000000000000000000000000000000000da015ca09ac0c3245c090f39852218f46fea62198fba35ebc4a7f14887943c3bd1bbbfbfa300611e45f419b33988e404c07f5188e4c6270a7e9e2f551683c4f9dc943ffc7ec279d15816a7f4910b8d30000000000000000000000000000000015c9121f72e2425cc8aa4c878907628dfe75a903b7f756b9e13728372cba598859d20a92a8297d95e1fbe25fd1cd968300000000000000000000000000000000025a3faebfa53918efa733949f914be08b791794bd4963f0c3fd78df48b14ad214374b08299327575c0731b54eafed76000000000000000000000000000000000771782ecd9980da521618af2f9eb55d91d67b20ba615c7b3cb1a48d483ca405fe99a1cdd17e4dc7aeffce586987d41900000000000000000000000000000000136000da90a76d538f336608ce877be943025b4c8bf15880ea9c1c001c20c954292d362dac9783b7bf66b8d51ddaf0f2a819a0438efd7ec0c1e3eea07ba201af6a832fecec818adbb781ad0c23e81dae", - "Expected": "0000000000000000000000000000000014cb24001bd933b1d5866cc3de9f4b8479fe23e4fc26dd210f9d06e7a05449b9f5ac4e2f48fb847599f625824336bf1e00000000000000000000000000000000033fdb2e899427f1cb9757022c5b614f08c64b53583486148b7431311a6f15aea3b968913fd5f3e9b624705351074be600000000000000000000000000000000035420be9c7ae3203d0dec61ecea70e22e62f50368be870e74f9a7349453647a7f61d2a42cec6522164cca0c7081d4de000000000000000000000000000000000fea43388e9f6e31d419c7f9fbb9839b4cec04163a7b401d8f7de73a4560fbfef4e272f1db9c9d5b37693378f139452a", - "Name": "matter_g2_multiexp_6", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000039dc2b60389f6c893c44072f4db23e7df4c2f299d6b70b70784d9370d9ff8e5413872c227074d429db999d30dc9499a000000000000000000000000000000001702273db356abe7a3f91a9fe4bf56584f13de4069a91daa6c0b552089bef60da98d32c615aa5610842dd8a507f9477c00000000000000000000000000000000095285e8c508ff12da79e16e0391dadbe9a823c586a049e729596864c3cae117305c05f009f9e8ac032abaec8a63f8de00000000000000000000000000000000078fc70e926decf7aa4c2e4b395e88f367757dc47a4cedcd5e632c456a4c160393837196af474948ce6ad53f830ce8aeb15af019ea2de662bf187930caea19d0aa07a74b49fa7d1819a539e06e4c69ff000000000000000000000000000000000cc3cb5e7b033cff3e5cb01ba29ce8e9f4a93e836ddea7d417f7b07ba8aa71a0efae2e1d7a8ec70bdff12d84d229245200000000000000000000000000000000019ce3c830505324b9bc7cda1fbb328150d71310f06a8424dba861d67a7bc0428beaaf697646d22cae9e00477cc8066f000000000000000000000000000000000f6ff67efefa5636b104a0351c90fd3e89a32b8a9beb0d123d3d6ae42eb5e8bbc19c7a972e27762daf852259c65fce6f0000000000000000000000000000000018d98c43fe5b13b701749f4a5dc25f0e713d241d573639fcc73429226bb131d448283338a909670066045c65789bf9e7064a6af51c1d499c4c28556ad1255af7467bc750bf2db2842d626647bdb3346100000000000000000000000000000000003cf82958d68429503265dcc7d88a3763cca32baefe3c8d32564cf30e8e6b8255d4a9f6a76bce1da473b50287deda74000000000000000000000000000000000bfa9cde6c06b2a2ff8f877ca90b3827d0aa0408c4ccbed23ad461433dad71017d4dd387f49c5febdeafa17d06ba784e000000000000000000000000000000001770fe70513533d91c83449ea52964cd8b449aa81f71e71995db5b19ceddef18e2919439c80e10086e670be669696e4f00000000000000000000000000000000194c20491c9d5ed827cd9d370b9bbec55e4a7b1c34ddd1d80201e7019d9487a747b4fa57b480dbdd09af73aa4f5fa0e9a3daea5a083af43711fcb09282b66882ae5b5b8e1714e9186f33ac0dfe48b7ca000000000000000000000000000000000a79d9e0ff43249ff54526c5e1cd55a9bce93adf272508871326c933d526602dc9dae5b6f129a0f1c38139ed1c39be5c000000000000000000000000000000001458b554e0387c1ddb9dee9f4e9fba9c81c15807f496442f4b7210267912b9439a19f95dc80a1e09a0e5cfe750f43c8800000000000000000000000000000000012c06b19ed4e8d5d1b9fed56bc5bdaa3bf0112db997e33aa14899d53e1bddd6aa91dce7e9d25473b66b8578d398981f0000000000000000000000000000000015369b2228e728894f2fd7c2d8c41ac3550da4f297de445cc0f0ef7134c478f526987643cb5408a0bbb79f5f983c085ebd682acd154f6e16a583ca4968d28471653375ef79df078b17b2cd9634258dc10000000000000000000000000000000016649a8231407074af5ffa93f9db5a2ddce8785be8ee77149602d6afa24ab30b26d2f74bdb5f7464333924a817e242e50000000000000000000000000000000001b990f5ed0b23e113042ff004236646c6eacacd99d1d73fe0c3d9351ce8d622327e827b2c0556802c5657f8f06062a4000000000000000000000000000000000f002a2a5ca90285f9b2fd429721c2daffcae5fe48c571ebacaf475606f96cc8350ce88a850ed75e5aae59d445249bf00000000000000000000000000000000015157fe1a767dabc185a8dc8fea3cb208fd995ecd9acab762638faa987f8367ff7c1a60b657be6e9461acc9df16381e5562223d3fae1d303a01ee4642fb4cc70f21937ba7fe377260fe82262a8455a7700000000000000000000000000000000073884ffbe6deff99cb4b0ae1c0e91e2f4a8c2c7296339b1d7e117d5d47ab055743d643155680740befb379a1dcab666000000000000000000000000000000001995bdc23991dd4cbd973e915a16691fb860490bb54011384c553dd14afc37fe673d13950c1e7eaa29c324fd9304624c0000000000000000000000000000000012197a19a498cd94ecbb3a409337b04e76e1a52715c40203add20eb80f7eac66f3386242d51bea34ea016d778248836f00000000000000000000000000000000101069ff0af2ac4dc7a5bf7bf7b56d82a310d67cebc41a9abf1e1af489e1acef3e726fe9571b4382777573712663e26caf1d0fdab6185e1c3f9f621ddc169ba92584db0b40b6ace7ed563eee0090629f000000000000000000000000000000000849b88e7ff52d8136a120f924b20b45ea9ae654a0fa037b62f3c275f0661091038a4c1d6ce7d50512e628b6b397c9f6000000000000000000000000000000000e50e82e9b368f2e316d41febab6b0f626d6588b7217b4e28eedbdf50a4abc9039be9e66c97790d12cdedc90873993e2000000000000000000000000000000000bc5d2bdf06fda1e1d1f5c5eaa7988dfdd790bf4d952f5d3a532bb59edf619dafcbc29274fd3661a35a3f15933b1849300000000000000000000000000000000162e5ce45499e620d0977fa26a291a8e75943c4b5a2a80be395ac9b89767ea5a06606d6b75ee4c8a286d2ea5a197baa5e910487c91f3839d5961f02a67f3b357206e406ba207dde969498e40d4a26e880000000000000000000000000000000005c11afc970544b96fc1a4cbb27259e19b5fd588d1be1c8f19eb4f111882292a463c951521388cb8cb743e5a4a1b57cb00000000000000000000000000000000013dc433dadc122376b75fedc923386a7ba5a363678fcf9edf165a50e160dadcc151b6f402648193d9ef960f5e401030000000000000000000000000000000001893af155aca343bc29989ec2b5a583d020a7558c7663accf6f3e40d0a8eb98ac548e933eb8e2d5fe3550927acc2ed4900000000000000000000000000000000043a79bcbaf07bffe6c6890d95c7e74d127446bdea51a0ba3adb164ea39684bb3ac552020ca28b86e34692c9b36f4384396d32c2c9ef685120995d2244756bd45591618597306193422f3b5df4b075d2000000000000000000000000000000000e6946ddc8a9d73e5b140af80cc91b31b9a226a945a9574f0629566f7ee7650730c5ed758cc30442770ed1602b84175c000000000000000000000000000000000da0abb9f5bfcad73b3f24903e9ef887c660447332e5457e4a5764f6628c04d6fe903679b8dc8bb3aaacde410812286a000000000000000000000000000000000656016c01d3405dce9f7d40e47976bc8a84abc370e7e42849dd0bd93ef1da0bc88e428efea43dfea37dd834cf246d69000000000000000000000000000000001939b2c92c8299d7ec1dbeb9f291c5e1c9481e10df10e6ba18ae695a780aec5a185ed4c7e82dc2bb5af87a74552c2ea32087e21d775fbc2c20dda715e46c9c4970394e40e991c78ecc13a2a5d0b0f30f0000000000000000000000000000000000942901572722e5005a9ef5f948c8cd6f557be8d114d2810d3cca29933a94de3c7658e7e28675c2a49f138d9c98c524000000000000000000000000000000001908e8b815e95ec07a90861ce53f545f0cd44aacc47df40c24d6cbc61e7b28fb91cfb1cb3c67b6c5b38c34fcb2ca35710000000000000000000000000000000017bad3616d8e510e325d9166790239c8c817c68ba7fb937fd5fb70a4219265edf6625b52ff26f0a34c0bf481c482b2c600000000000000000000000000000000023ff8a50a9c0e9ee829ec81972386ea012df5e8476d8c342df6b98fa1faa1382ae921c2f1018a918868672450355c44f44043002a94560d725da2ac44f30cc5f14f52dff5671c6689efebd803b1df7a0000000000000000000000000000000014675ab3efd44bffae321791e6fb35a24b9c07405d9985c685795df2db183ee9dadf18c76cf4095e1e0695dc2c08c4c4000000000000000000000000000000000835f2cf09647061ced2bdf4211bdaea408148100f864f47ff76c0c63a43e44e8ddd9e01709b6ad129bd574d71a1a63c000000000000000000000000000000001017eaeaa6eba76923ff27e5848e5f3b09e7b2b9d55b2cb7068f39defa8628d1c8cedcbb0e1cb5810febc4ccea712b7100000000000000000000000000000000054c873449c738383e9fc2f0f74a6334904171fdb704f5ac35a483ba19a8f661187d36fb35014af9ecf88225466c86e48624c83d846ad2e53f3f8ff5ffd3fca8723e6cd431e89ca29a4d662e82004b60000000000000000000000000000000000439ae88636244d5e09607960fb033e4217343899d044b21e61335425b94a5067c941e83e5a77f4b0690e1de037325090000000000000000000000000000000003a67653818cece3ff0390d097f1bfbea9ba954a85710f5c24d1de1893f25f2863991fb9f330e60cad725708e70384b4000000000000000000000000000000000243394c3459a3af236189ec6155418c1916b854a20b980ca1044b48e23b725dab7c60a48e89f642423c805c117e64870000000000000000000000000000000004c8c9fd9f278dfe9f5e24e0f5b42699bb9751b56520827afc2fae8393c690a63f10e92f77c4a10b0c161408da9bf505b2b2a8a42887ca6dff5b5364d88962068496bee79cbe74de0e8a06209feb38320000000000000000000000000000000011ba67024503301ec72bfad101a48708e3521c8a23c6bf2994078690041cf7eb75675cf5f20c8e82d11145e31751a2300000000000000000000000000000000008ace953ed2eaef19595cc7c9fb1806d26cbf1e888075e3985b28f8d93b9c0b4c820c8e8b50fd4e0b23923d428da3efa00000000000000000000000000000000054ee6f7247296e0748d0b52148a97b930e69991a242767d80bd6434d42b0865a64d3ce60953fd2631aef873d8b2acf3000000000000000000000000000000000077748b724301a8bc48efd1cd66086e727e9872e4efdaf55ba90ad1bed7e229a9cfb79013333b50efb46090ac0bdab488ecb5976f63a38d7f3d8c8ec441b705563c5e3d899870ab5d2ff84467fffefb0000000000000000000000000000000005008a1d62dad51132ad38a226e8abd7421392414acda61111c728713a2ece284b04d75c2bc58d355bb1d3061415010200000000000000000000000000000000189725b7fc48b8a648237021e9a2334247f1cf18ca50008b813978db01667ba08f00b23b3aa0e015f549ff2d5e5c535f0000000000000000000000000000000010483cf2310f64cf0baf556cb2f2828a1c15922547bec03cdb182a316aa86b5473f03373cf7e59a9a78f73193c1caf520000000000000000000000000000000007f635394301441bdc57dd1f4f97656f4218ebb139c13a17e12839091e2e81327f3353c56880c608de824a07a17b2bdd951f4960d6614b098249eb9420077ea5ad11e38d1694f4df33719d1127338f44000000000000000000000000000000000daf4090a229a1ce946064cda1c4b19c88100c8785c69f2eeec3aed12065787ab0abd797ceed07617d55a9c70ac3020c0000000000000000000000000000000011d77fc28355f61037cae3a8342bdf8d11e963495ba3b5d67055f790b1fd632b23565cad77a3d9968d364e4e2a553c9d000000000000000000000000000000001038d7e8fedea873c864b79d1cf8045485299a2bd4d26c5ab5c8d4a073e2c3fcb38cb230dc6ab7e8e228cabc6ed97da50000000000000000000000000000000009de9209ed14d62625ffbf770e8c528594aeddcaf1aaeedb4f3ca973e7b9f9f1a40370cc74b154f3bc641665d8e4d96b7056c7d93d8453be369831dc0575df6438db488780d518a53d19b8f5d22d506a000000000000000000000000000000000a6b0dc04591cbbb1b82a059e08b488fd66edca0f2d264c352f81cb6ec45e50f0af16917fa4727ee9888f84b6c888c60000000000000000000000000000000001369ae16bb0743f65cdfc8082dbe0d588cf8aa5406a095c3deefc27eb3ed462dda9dd4921cde6a1d878a805cd144515800000000000000000000000000000000124e08d4de6e831229005663df4e4bd5bb7af56dfb13244c50410e6d0aea420ba19208bf1a774207e0e0170ad3a9b4f60000000000000000000000000000000011b2973743034a2c362281b11a1ac1c89f59ace09f0a53afb0c2ceb061726c7aaefe274f6dc04e5d0dea2b687a00609a8aa982de1583c25307e9e2c8cf2469a0b1076c6be2fbf12caa8584f34988221a", - "Expected": "00000000000000000000000000000000136ff52e440da609b6b73aa838f2eb9791221291b7b14d902458aa7aa9e37114c573edbe8cef7a98dd07275a8c3fd650000000000000000000000000000000000ba625eb47be09ac8cd1e2ec9015640f416af0e3e0e79d39ccac600ea08bdae7a2bc9144f13168a8cec03ce66b9daadb00000000000000000000000000000000095c51e81b5881b009b28006286c704ce3b002e4ca50ac8ea8e574d1e9665a5b1efdd60568d4a4a656ca6a2d1750a39900000000000000000000000000000000143c0c4b3b720fcd0b044a6f420961e2b7eb5f9f1b0d200de56ca8b02709d819f47f0a6ea7d6b49c4f30520586a45616", - "Name": "matter_g2_multiexp_7", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000da4cf56fdbaa9004bf8ffa12d5cfb3f296ba5262dab079c91bdbadd6e41ee5f89912bffd5df1643146bce1f0e021b3d00000000000000000000000000000000150227356e48f29443a0ab4536e7a2f86f9e63840e23bbf1b091a59f52c27978bd6a15b29b105132298de45e51134da50000000000000000000000000000000017f5271c97d84f55f8b7ee0d73267bb69cdc7565c470a4b531f9dcd29596eaedf46e61bd79e71e5ade7d000c1c1d81bc000000000000000000000000000000001322812590e6c22bd90511ed72553c1cdb0ba83487b00e3adcb01a9abb438f365ca23fae9ee4a953544253696ddb0bf1a18ca15f0d931619363f5ee56bd7657b2298f228cae8d185c9d062910193e9c40000000000000000000000000000000007c59f94693320b01b56b36f8d1c39fc9e01bad289577738e648771d8940778276cdbfd59f07926e516fcebb70592de0000000000000000000000000000000000aa71d6dcb0b225526eb92b79891ef920634a007b87986fc0f776f85195ad7ec2d84b9bc684add947df8ff42c33b034d000000000000000000000000000000001362cbd6cca3d5c1ec68928be38aca5de1f224e7cd4f5c3ab1c2cd589bbd7c31022d4adc51720bedf2580d2acfa0f06400000000000000000000000000000000162bf0f38e19ddca9aaa370f988be9b35461d2a0f46143e8663f1fa549d0afa1596f029cf2f800b027b90d1eda6ae8a2b54274927eb29fea0cdc464271c918826d5249b2180a52a5020480d1020c9795000000000000000000000000000000000eb12a92fe65f79c646ba508fa615d09d86e582c3337ae16f66cd3bd74a9caa9dc17defb4b4e67ad62f0665c9ad1b6cf00000000000000000000000000000000058b6ce2582c46c0fc108a37e1d2713ff21ec8b1d8c18da0e69f0dfec7f2f327043e174e16d9d64f9ed4d3818a302bea00000000000000000000000000000000068192bd2ebc0a23092bb98c23f5792e179913c4ff1f23eb27296a77e83729803764b8db3b7ba4fe154ca467475eefb2000000000000000000000000000000000482b16e876aa90da6da35e0d7495a04d5b0a1d084c61821f23e1ad63cb1e66ef5975a3cef9ecdf2e696e9d9b50bf9b65849bffc842c21277be88dfae0040c54b072ff526731947cbec0cfe963f2d0dd000000000000000000000000000000000b712fffce3e63362bcc246da566a14139a3d12807ba83ab3520b0aa3aa20cecd5718e2b7e00f24e6fa705315bc2175800000000000000000000000000000000057a66fb12f27e4a5268e56805fe2b61b5ef019b31fcdd861e2b0beecdffe1a3a69e8d193815f97740324aaa40ce34a8000000000000000000000000000000001080a9e1133f37288dbc3835e45b6611fe84ec4790e23e5ff84a2f72bfa2837f55cae9177e5a3a918adde777b7298a9200000000000000000000000000000000142dcaefd73d7f6342e87fff8c6cd161389b6049fa077f35076eadd2b4aa66f3a1819bf8272cac1c28cc02bb6440dc42aeff769da1b62fde321d46c66f8ee7f2129446d805ab7f7bd586268de8f57c4300000000000000000000000000000000034c0f8249d6aefe4cdbf84d151ea9f84add42ade087048bbbf9de4a412cc805dd9b608fdcfa34fa224066b5f06d18630000000000000000000000000000000009e235ce5eb936bae00d3fecead8859e6d909da3d57bbe0a8aefaa5efdc94969a1cb2e12642c0099bca4e7bbf9833469000000000000000000000000000000000b6fbab498c2706f0efdb4effaf79218cf4b652a5205eabeb84f05a060da8cd18c8154a3d37594485ba50a8228f27f6800000000000000000000000000000000130ab70e17dc73f773df99cbe3f978bcd3fcb92a8226a1450239d209cc6969e2cecdc0bf3cbbe9a9c1de072bffbccaa952c9e56cfe957b924c9c0294e1c1f12474331c662c8e86288c97e6a8b8b5b20200000000000000000000000000000000031a2c10e95b841ecfcbddee4b458385e5650dec9a2d1e50216d9fc261a9829eb5fe894e47f171c8fd2f4d5d89771341000000000000000000000000000000001378471c7f770672ee82b70fc87af5ccacdf8995df9ce48aa9fc2f638105a2fdfa48b615970665ae4869f1e2dc7988e8000000000000000000000000000000001969517c503df5560628555a8780138e4c340d9d49d8fac4a8a11c894d283d49fd06aa81e9f0db8f015d9372762dad75000000000000000000000000000000000f5c2d9b7fc33167a6e9b5a5fb8c5d16ca009282edc05cbc8a048b835b16ba33515c226174d6ce5f9836581611ab403bdecec569d223c724d162250ed1d074ed9f4080aaae3f44b77df05292be48ebd90000000000000000000000000000000000a6a32f2006c4b7804e99011d934ac91b1b3fa6f5d02c574cecd6570bde1e998f135449dfc148aaa8fb8757d0a7299b00000000000000000000000000000000198beb461b59f57b85d858b730fcf853d967a1592e5e5787fd81c6a3d9d9b40c1cd7912cae21a47aaf78df5540604cb4000000000000000000000000000000000955701e84721866683b4eaba82c2df8a89bc906fb0a3cde565d314cd7278b0c56936205cc8ada10b03e69b93c48067b0000000000000000000000000000000004740253653a0d6cb15c76e145dc0b1f811bdc964f7d595b6027bb012b42409deaa8da83e6ddc3f0f7b4b237eb62b537915ac9453b831c41becd3c1f412cdf5379e9cd5c80bc6df92ecfc5005356d2aa000000000000000000000000000000000f88e1e30674934bf1062ac619f1834f35f804a958e82121255f8087ae08f10525e740ee53d7514e0ee7c49e324513c700000000000000000000000000000000019d554645696b7beae881ef62297283c5b68ad3fa9a84a47c29cb53449d33d6ee7a5a3cb83b6acb75cd41ac3f52fec40000000000000000000000000000000004b32776966e52e8a72c88a689d6c56833296d384e2059d8f615ccd3616972074987f839b4689d5610a88addcd836d930000000000000000000000000000000000fd4d21b00d81ec993d2350f1fe360576fa983754a7159c2e81024a00931d84e419e8b5231ba8cf8f05a0ee6ccea7e558fa60bc7cff4edde18301af2348faa69ed4f31d437decb7d4fe51142d179e6000000000000000000000000000000000177830cf34186191fa295b7f279bc819d8a53452e2114dbfe709971584ec7a2da7453aae3e64f4b14c261e22314027c3000000000000000000000000000000000ebf2aac35fe070403a4b7a5c2f102c67300bfd68af7863b45185b37ade1bc53d46772062189f348647e74c77caca4a600000000000000000000000000000000128dc7846b2dc5c453ba5fe4675d0c22f4d7089624ede05b0910c34ae623d4671979fd73455b35b61a57c51fe2895adf0000000000000000000000000000000008e33a3c3735be035b550613c712b220595a83c1953b24b3efd38c5913fc23df823e00ae5a1c2ea8a8eebbb93c5c721dc29be0b271d4e22d39e9e06db9e50845515880f30c5bfac80bca39a2d8d61ea0000000000000000000000000000000000a060a957a8da4384e3436110657110653685bb621c32810b6516c690a00c13e37f70185958beb0ed886aae5cdd611a7000000000000000000000000000000000b5afbc85e274049985eac230b2aede7b2df1485c9539a4a4eb6aea406d0f6515ad8bbece7155fb0dfb2123919fb8af9000000000000000000000000000000000afa722987390440a33d5103445dcef42cc4a3c461daa076d56fd38e0b220016ed2bb8e99b9a8da4af96b7da64ba90950000000000000000000000000000000013ea6b8d327191e53bc71fe43fda305a4a0584cad04048afc0480f179955cb27f2ac8791d847036470ffeb47aae36877dc8c2e971a3a4b9909dcc5cc6a0de50286294ee15f441521e0f1d2c3ad3a76e900000000000000000000000000000000032b490f795ac3242b8c7185c9e19f0440ecee3a65263dd4e4c9a431571deb7339bc6e2d73ec43750f6f027bcfd674c400000000000000000000000000000000076ab4ab3e8ed6ea3b882fde5cacb3bd094567288699e11f368c3f60f4283c5bcee7b4c5debeac541ead983f5936d9f80000000000000000000000000000000012aa2060e421f4f4249e83ca0ae1752dfa2b7ca958821841a18f05071a35fb9c1448619bd96f8a7adb2202d3ffda8eb30000000000000000000000000000000008b24f29ee7571f31ff86574e654a5d849acbe92653ae1a1d2baf4c9ca6e67da4937bfda51a70931a6e60d90162efb4f21c9ae0132a4886820115e71e280d33378a04344f635c769fffe91e89fa7ea47000000000000000000000000000000000c8b41e5c47babd6ea113c0ad9f45a75d1ef6bd313b768ac01e6f581ef6630ada623c1a27d4aadf543af4055de7f6b73000000000000000000000000000000000a0f73af06f8f0115bf17f7c5db0a6bdea77a8e3d8fd0b52b0d4e2c558f1331f655dc272c86d98bf166b532ec8e45285000000000000000000000000000000000499b55964186bcc6986e7744c52babf47e274e47a202abf6f816bc748baf846df2b5ced2a5f61fbb0aa2047bbaf82db000000000000000000000000000000000d6c2a9a3fa5d0524f772cca2c7e72a5f2da1a6a1b9550997e7a6cac5b6b6c37693a01d30bebe4b9c742b63bd31487a1e1067c01d5565d0f387516d9721f7f4e5253d5af8353db4a55500e20a95f3c9600000000000000000000000000000000143220e1cd08ffaa6db4795ed4aa35f3b12cce724fcad005367328972f2364f34096e32f1f1cb7a4287ab636d0030322000000000000000000000000000000000f2de47a37a55edbb75ff0bcc446611d690d7f9efdd09ca1ebb6f1d64a330bed420bcc85aed8b95316fcac3aa7d1f2230000000000000000000000000000000016afb044b8b8c64547e000f80b25576aa329a4319dcd4f1bbe15d12e6f3bbdddbb52140e6297c637311ef0c7a31cafab0000000000000000000000000000000019e6803c07fbaa075093f6a69f9dde05ba3d3f58e67389d7f096e56df49f8270008ed422b64fcdadf7cbbc8334037682a23bf766a1e1c068e6e8e4b60391583ac197ade53caf0f8a43c53d1bae9f13e500000000000000000000000000000000134125416c7908cb4454ce6aadb30df46042ef2a6b4b69b19fafcb9ebafe8b5579046725590266cfd10fa26e1b5ff3dc00000000000000000000000000000000073f4147cce24e13b9eefad7c69b457acf126bf278a58a26a7c7c6b482edea6dca9725d7e5e4138b4ec81bc2505ce2e60000000000000000000000000000000006125caac1061cd6c556f4cfc122df8e949622a46ca707b48ef088ee5623df058bada1bc0cce1399f0be1ee86225f13000000000000000000000000000000000146e398c161e29c90c8a4fc44bfd5b3dba6f9e80ead561fa3d91ca5f416e06318dddcfe5147ab5def858fb025a1562352c505d4fd8287a897e01517ddbd7d7ea9d26ae4f58fbca172e5265e2b62858b6000000000000000000000000000000000944942effc77ad02c5ddb052acf86f3a9dc4127dd032181450295464b49ac1dc0047790acb378221fbeebd4c92886820000000000000000000000000000000018e1d201b38d88665696ee6cef11fb19f7daa7f11c5a5ccc73e6b66ac7b89df8437c9f07132ec8b69e13f63424ad694c000000000000000000000000000000001463117fdcf17f28956a42677b3ff431cc17ccbde067b91ecd6fae51e1e24ba8d594ea368d041656022611ad3ed44a6e0000000000000000000000000000000009715cc5add17395b7ddbcb961269fc5d4739d799fe9554b3c9e9f59c895ca5df8ec75bda05cbef3e6a165f7987e78662908006c06ceb9188651c59d434988cb5b51a5a75772ba71875444c65ddf0f4f00000000000000000000000000000000007c07cf1ac9b8b28e3d2f1f4ce22b8ee46e99914ba20c7362c679559a1618a906c6ea65c475ebbeca4947019cb6fbec0000000000000000000000000000000008b29f72cda71e0bc2246ead57b2f758b741b9232d87be75331275a5cd63afc9aa98b0e42c1b82cc258e93c97e596a81000000000000000000000000000000001512548a4bbd537a4d5baf673fb76ea7e35b2977216e7b29a6375e1f92049d7b7d5fd5d8b4ae6191f5592b738e149a5f000000000000000000000000000000000cc9d646428135296919808c6ac10c142e769bf71bc1490196dfdd4e1fc7b84e58155bfdbe77a9e684622ffd83e97ad3e8e8724c80f3527de5f0b2b98ecdf0b8d0471e63c0763a89da8a21a70dbf8399", - "Expected": "000000000000000000000000000000000ae9da7d12d0a03cca3b41ad869f762784cacb988eac7ce904ec9ff47824e058e2e211e2285f9fe2aed0b4385949b4540000000000000000000000000000000005b0c873d20f7be1410d39885ce4f79884eb6ae2b2f27510d6f6874dacf2a66c64e56b7aacac61ec88261624936e695700000000000000000000000000000000076c6076175ad748dd68fee64431e5e4ad013797de4528287e7226c3df90233799ed5c8b36848c1a2e1c02591a013d270000000000000000000000000000000001f7f6972121d38ee2d10c621a38448ed12271f7e0e9e4567fe1b5fcb469c7906196fe92c66c37f8c5abc91160fea8ae", - "Name": "matter_g2_multiexp_8", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000139cbf360b10e59c20dd4155af2023d5dfe0681c62351dd541cbed41b6a328aa44b862d1985b132a4d4ca61c95b61ebf0000000000000000000000000000000004af6b5a0f7a02d5c93304be0d31959bb4b1a7a5838dc3f9cf50180c4eaf3d32e68c006263d75f9735c8f0b5f811d3cb000000000000000000000000000000001644937e5ff3b8d2005a2f3b0984917837d44412362a121be481526173a4c61e20d61076aa10b4072b79743c5f7f4c4f0000000000000000000000000000000009bd399b55a59550dd876f35e54a5803058228bd6ab6c9a66e438cae473c63816c96bdf378ad426a236b58b90e737831e14282bc687a00264b4e4678ff238d5205f6b6fcc10040d9b4393e93f76297a8000000000000000000000000000000000f343e5118d7dc3a38e9975a5f40084ee5f2305e45a8aed28ef105f76345d9f5646b4f3924b92978846b4e605b78fdf400000000000000000000000000000000017e61a2ecf9b3403b43f5a10a97cf5088b4f98e5a4513b0912ea7ecef44e6809f10dee60367cf2fe3e903dd68c2a97c00000000000000000000000000000000039f37f414338cab0e12f99b2aa1e3c02cbdee3406d1bd17c359ba899b7cdcff605f894530895aecb469f41628c3da120000000000000000000000000000000001b78bf69f1b7168d735fb4b7b135fe70db79f50e792eedea23f83cee9b48e092536c2ed146c7499cf047c5b4f0a08735307650d6cfc681508fc7b8dcb5291837582eba6588132f46ab8fba674a1f5af000000000000000000000000000000001342346f1b553e29e661c9f6c0a24d8f788db98262d6af86af55d313a37eeabed1183e367ee3d83faa3f284b260e786c000000000000000000000000000000000960c8af3f7e6587cf83baae447491e73cf41e637e1efd730e3acd9793717e57b85530584942e7a030bad3b91a76996300000000000000000000000000000000166daca4ee2cb9516b5178cefef0553115dec8157f6194d24d191cfe6340406071883c89246c0cd5f89bbd5d0f1ee15b00000000000000000000000000000000187f668086b9b6307899d301bdbfec915cf24ac0be10d6897b0677e4f1de6a241f3dfb19225644858be0941530e67d0f7d6a25511ba63f0b7ebd2189cfc4c551083ac92b144e30dd81d27e59dd86e22600000000000000000000000000000000032c3783e701bcb651aef40c91682eda03f9d90f252740612c85a5727f8bcc41a886b328d5ce787031c08ace235ff465000000000000000000000000000000000b0eca06f9fb69ebb46d0af56d3d934b333514d7f31208b4ee2fb92009e6041749028a78246a0adc324034a94503e80d0000000000000000000000000000000019eb24ed35f6c7ae53047814cab14d51ae6cf336d140a17e794d5cf18450b7fac3e6f990e12d340291459197bd353861000000000000000000000000000000001983a596485e657deaedf01614dcd5f4ec515c0050e8068ea02c9833d0b165c0f467107a50da0d8cd43bfcb59db6e710eac8e5cf13de6db37982390c8b6b0474795f479584960748b7ffed881285e2df0000000000000000000000000000000002f1c29ffdf7bf20fb8a13363393d5f1cca5dd9af82888f0102030fdda641abd5532ffaa2669c0c4159a989cef1c5bdb000000000000000000000000000000000bd548079899d49cd368bf5c246aa168fc8c777bb84a7930258502c8424a4b68e1ab20dc9ef39c307e52bcafadb0c8e100000000000000000000000000000000070c18918f037d5fa1aa005e2c80ce6a80b4b24d33ce72a2bd824f9a061af1db236f04d6041314310b31b805b8a674800000000000000000000000000000000014422b173840da655aac6ea4b7a04313d5d0675bcd565258c73039f879176e51ec0c8a9deba9c78c33179a5ba54492012c134652c27da0a0272b0783551ae44db6bf592ff299b48c50c550367d470b5b000000000000000000000000000000000a1be8e39a47dbe0bd19b8108a5bdac582e1d11ef7fe28df1f12da52924e734e1d591e8e33ec20c6d5af5bc8c1161fca000000000000000000000000000000000eaa7a7cec93b8d5eb933103b52a35b3d58214feb8e2de0bba3a0e57e7993a9df0dcf8089142f57f8e0d1d303588ce9d000000000000000000000000000000000089fbfb389ba448eb77722994178ee3cfd15a27be4ed6f4d4ab6ea1a4c10d6ee8424beb17d08190fb18ab8498d4a4fb000000000000000000000000000000000ab02df2eb474735e28c45b915299230ce159816419fe9c99a7da397b7210590705262ee14c2a244f4922c35bcb119338dca9ff432bb483ad726bd20cf96b07ab6f07170a1449f0f1b50ddc6e1a0253800000000000000000000000000000000006508fbef44d36cdc6fb37b6324810ab2a1d94e39abdf09d530df34714168105e23a7d6f7fd9caf31f263b658f16b76000000000000000000000000000000000b5bb1802813f9f8a16991d41275ae6d18532e3dcd2eae091da7256aaddd501855e775b779959fcef2822685725cd43b00000000000000000000000000000000052146ee63ae277911fe491420651a96994a30c7d1b19bab32eded008a125369baed2ec5a963bfd863a83c29bc1afb23000000000000000000000000000000000a180d79335347a8be350a92491760c6bf1fd56604d4d99a1c49bcbe50b2d04b7cdde55b4aea8ddda4bfeb8e79ab6ce4146433a0738ab1b044e059f49a8af8d85546d0e34eaa0edf2b2a6ee466c0def80000000000000000000000000000000015dcdc17a9afbf88b54af22ed2168329bc43ba50d374c0507c790f37f9669d0af167328d50d322a827d45f39724d2b2600000000000000000000000000000000169b83f2567e921a4319fc03b2a7eeefd2aed79914bf608d9e0a54aa71b9cb3e09f1cbfbadaa520c0f77f547fd407ea50000000000000000000000000000000009b7a8ff8388c85a0fe3860f26b09b81b5dc51e00a8961fdba96eb462e1334e9e28a2cdc4be49dd8b96c548c64921718000000000000000000000000000000000243782436fe7cb20a3242a3a21402a43a2c4fcbe77cc7182ee3cc04f4795c269d8a64ddd25e89ba4fc796747b608092de0399ce1ed861c0ebce1d4e811ea0a3d87e21a54ae34e6b5e1284cbb94973680000000000000000000000000000000013ce6856b6df48e4c9e3fc0be0aca5b139e1b874de6ddc148c1c23a846d61e7a531cc889bab99706668a3b69d32b9160000000000000000000000000000000000a459676071c7f3065a6dd7632edd5842db34aeda8fa0e7d7a8ea29f842ebcf2c5fdfa74ee7685caa51481c4f46952240000000000000000000000000000000010c1d9ebf7bed9195cf0bfefad6ba45f1bd19a9a7d340b7c630b9953923efe4907bd75a3da066fe3d49d656f3ed91d2800000000000000000000000000000000039189de73332d5b5a160c296a195cb9d8a736cca23a92948d513da7e4fc46e1ed9c207e86751b3cf1310d8a7284877ec2b034594fa53a0951e2116db1b063345fa42dc8c870e1146f1b00f626dbcfdf00000000000000000000000000000000129821e97c65ad3801c011792f4c099e19919d7d03bf9fcba30b3735586bb7ead7d4f9bd10bc5f0e5cf1dae82d5651ef00000000000000000000000000000000038cfbe45bbdc494988a2dc72dea6a7e36652f5e5a2ecad41b4aeceec05dc4a389e54cd3aab349adbe32e65206eb481b000000000000000000000000000000000bbab53f2be2c471d6e9cbad719a73c00b582d0983e25e1969c0be1faa56b1dfa5b7b55797b3340cf8c7eabc560fac71000000000000000000000000000000000b0db19410e552a2f7889c2204a93c5cfc71c360329e3be3171e88fc7aa1e993a5d089c28b1a8f8fc80d93ba194c63ccc1e6d9c5f8911014f0f540211af5184d96fdfd47c03bf2d7bbbb3bf1a330017b0000000000000000000000000000000019320bb8d29b7b5a7130b87a39e87e271b96656b5a2749f13208520634009c26f9829401d3e21cee5a757782c6bbf9ca0000000000000000000000000000000009b37068d72463e72f3a89b9093c1b09f01770e647b5ff7daa50e0679bb76404cf7729d5575a39f5b9b3b371893967df0000000000000000000000000000000019ff29e41db50c736e12f62d76a28f4ca4f6b0f4f61aee00cc0e9dd4e5a75c0ca965b82698f704c604bb309aa5b457f100000000000000000000000000000000062c352a554dc4bb96b459378c21ec6446e15b868221b2fb745d31dece854bc281bc22827d84ea3b0fecfe5d156712ce6df5a133d3332e1f79f41201f8cb2c8c8d4d1ab0f640c4de6bd6e34884a77aa200000000000000000000000000000000021c52e82b0012537b57fd92fc276e8de842a59355cc15d69a52effcfaa7cc43dbda0c34e1b9af44c2db8e9356b9c71e000000000000000000000000000000000371a6da5dd39092b6108f631a0f4c4401464a109ea1e5d14e262c8a9577e1421d41734d2c3ed73645cc13ef3988e9e90000000000000000000000000000000004054159263ee60f6b1882ad7c376c738c7ed87e6b34dfb4be2fd7aa29ede414c2c6c3ff098c53f22a1c1cd836a6b0600000000000000000000000000000000012d7af6b57c688e1ce90e9f2796b0e525e775fcb6be65f5d2fbe3d1ce1e5d948dcb098c98d495a6e3dd813527b4635258e7219a9d431c597fe9700d43da8b545072f5a27a9f1af99053ac0494087dca1000000000000000000000000000000000e53128fa5392dbae9e40ab1ff0149d5b577d9d30dcb85eb5e4fcdc17c7daf2ff1d6fafd4a1aba88d2e7aeb45a01afc60000000000000000000000000000000012972781f214511e9b78d276767b1b64bfe5b43215c7680c0063b6974f703b209b2929470dbae16f9767a7cba5311fec000000000000000000000000000000000cf6b37c5a60851d03752f68eaeaf37ac67c661f644cf507c5458cb5404d0ce903c92ef66a657b25ce07e5cf5d956929000000000000000000000000000000001835f202705c8b984a4c7a6cd219c718ab27a96671574cf7cb618235d19e9046a15212e0da6233f15f18bbe192df29c38efb8a7a5e48d5f4a011a4aa0dbab22ede62c903414d005d507ea3d77bd47a6c000000000000000000000000000000000d01c6e8e34e646911391b012680f0dd8f4b8d77c10192ac09ce57b6524f0eb8c7f83ff8f26d856e0945d7a909eb790000000000000000000000000000000000070fca42e34dacce0051f9e26c7c0dc328fe652110976df6df77af04202831dd095715af1714b60a99f2177e86a3443d000000000000000000000000000000000063ba43df0155373df59b009a8083b9f62004327b16ad455037487c5b8325e7eaf57a4d05c533e284004be6de79ad1e000000000000000000000000000000000870c2e5a7d26ba54bf0d45ddf0a4c3011152dd12a5e01a80e42bc4dcc784c7ffdb66f9d6d69ac445c1d9aa29586245147f53e2c06664e1daffd7d9b114e12d4190d5d0fa2244d61a13da915c39b8d53000000000000000000000000000000000d84ca02ffb6d3cf6eb27a143ece73d5bf006ff61569f0eab00c5a512c5b46e1fc21e8031d1a578010c9582d75e1faa8000000000000000000000000000000000a41249cf01ecd23d06f6a3bb8573186fe47e5165ec0d447df62bfc236f4c203b4feb8e2a4785648af86646cfb0c4e32000000000000000000000000000000000244fa6caa86fd27e044145557697ea89baf718746711c8dde334a2c5ae3c73d7a0e04fed6289ddfaf26e47a9d26b09e0000000000000000000000000000000017db897060c0a8e3e5d8eca9970407b46dc2c2ca0c004d50a171450852f585268bfa8a379acd01b6d4685e04c0b8c106fb109d9a0a7b62c7c452bdf0a2853c4bf65e5439fdc83aedec8c0bf73a16b55800000000000000000000000000000000071e13963e20eb1dfb671aa4a090973e4a4b7ad3578f8630db8a865847be46c796e6f9e095a9ce558b93d702f8f8572a000000000000000000000000000000000dfc4c89ceaad07e3b4c35d96e8534122ae48421cd4443de478ddf9a8867ffdab279ad745e55c87b731afa7700bbdb110000000000000000000000000000000015dd6b0c26f6821177d0cfebb7f1481a971e7601fb24ea365a0c3127a5b1042eab69446de05b61cb6ac0576752f87aa900000000000000000000000000000000156326c52bc78c82f5cb4aec5de35e3c128c5561dc80da2cb24d68a7e912b1f2dac2078508fdd4ec38769102c082f0f74b0a931b894fbe61115fcf52be51d44afdcb96c94117c75adffcd8729b0a699a", - "Expected": "000000000000000000000000000000000b537dc10a6f518122665f7d78326a4728a2889325e5be7da7e25e4752c680fd786cdaadfcc426343a9844efbbce8f2300000000000000000000000000000000085ba3a04aa8cea82b95dd994f5b3bdf0dcf63f13909aca2c2d61e4275a7ea22445c953b927ebc6b0987e98b553469d40000000000000000000000000000000019cec2e9fab640cc88073bd39e46cd571324904b1950fa8f626e2725936d80daacce2487f46ad23fa8af9c6ca0367fdb0000000000000000000000000000000007039a0e11cbb8bd940eaf4a192bb94ff8c6d6c79f775fa67821b5ba411641c09dfe9fac4cf45eb5fae52d2fc4beb6bf", - "Name": "matter_g2_multiexp_9", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f73a297cd6444809aa11b0756167e71986ab31b52b57d3c0aac5637129b8702ff21ec649541e79644c27f0017c8ae3f0000000000000000000000000000000016f96d6ba02aab604dd918cc799cee61cda4c0164ed9f07d4932fc4ac3eeb92b1e6b40dd7b18cd8d26056b486e57ed290000000000000000000000000000000012156f3ca3aa1e79014dfd92fbb6c785cf0ee449a8920b89ad04355e0fb7c8ea804bbad082b4edc9abd3b24ab0df2b61000000000000000000000000000000000d51b5f62a6e70816d7671bcfc52f11bdac6221a23287286af78605b99ae8bd0c722e485bd0381b958a85f61e05de68368ce22e379ddb8352d12eb597c179c7089c6388542909876c69ee377b14054e7000000000000000000000000000000000acc52d0fca02c3228cd2e5202c4eda297b8227bf4e64308226bc487e5b64738efa4c07a3738397f90251ea9a1a9da29000000000000000000000000000000000b85b853826a28777a5767d5b1966ce12fa8999ceff5d6deab5c947fd19d19de9c103bb920bad615186d132ec22187320000000000000000000000000000000006b5a83827dc7b3580579ab7976a70ee160b712580919b6f5d4e180165e50f5a1698fa7cc63846eb1f5e6df955c3eefe0000000000000000000000000000000006c2957d8adc55931900145388583e5c2d5f6bd784e022702801c38534d2c92c6df9f95d022aa6d800e1e458eb7f313061529338195b665f1b80c4b95b7c3a26a7229884be1f4be9d49e1274a9ec3f810000000000000000000000000000000014e4c5991f9f2ee262019c1344a0843756157dc85aecb15718217a2fbe23fe0843992dcd3953ebe79acd85517acece0e00000000000000000000000000000000076a18fe710aca2875bc102f21782c9649f107684a4edcb0c4538f1a2890a2ae5b46a182d5470e620375327965b6d37700000000000000000000000000000000142a0fb19b28a034d326121458628356561e50cd3a471ee78bade0733597b8b90f647f5199d4b5b1ee6be4e1870bcd310000000000000000000000000000000018f8b5933848813cc2c1a0f079b095d565e7875ba6693eaa10967d496fb47257c9c674f301349dd8f2d22f8857f9d5ca44d740a72e6c8b5632314408022093618321c8c0a8cf2fcd9ebacbe43505a01c000000000000000000000000000000000db331d2b965dbc053b01a61e671d2ee6b04b072b6494e482f48f12221f23e3b1ccebf48046d92b4be2e4283c77f51380000000000000000000000000000000016704f3e1ce14f49df400592ce29627833ed1dbb91ae5f00779eef94fe9ab313c3e7c8da940085034e1a49158043599d000000000000000000000000000000001956d492f5764c6de0b8e9a716766c762620ebd3265a95b47a8ad2c0614c337692108800e22abbe321d77a6cc17f4b880000000000000000000000000000000017149865739d6aed0f2a4c3c71c2d02f8080d9339025b03f89a37a165fe6e5a4cbd489b5fc90bb2cc432e5baab213c8424872a78e340ccb077259aae65d6c448fe6bfb64daf4e2b6ecce2cc9525e35a700000000000000000000000000000000036804da102cce975f980ed5a69e0464241b5de87238f9892c77fc2b6e5ceb00d7a37a45b5520fce5f094f8b9510f49b00000000000000000000000000000000049da8b6c974f2d680a80d2007333f15702f1517d3dc11395662ca1db945c795bf64167840c4df0fda68a69e127b2d590000000000000000000000000000000000e94cc66f1ffb2112e37cbd5b4feb7d65032c2e57260504a42816aeac85648558f6997ef12028655103a8cb9de1297d000000000000000000000000000000000abf7703ddf6995d5c29124ba9a3f890854fe0622d547a4f24d6a60b036ec9e58f7ec2deca5a71e1fce2210cf810e2f901a1d84826bf78f493417a06a800d58dba688800026638316fcf9ae534436fc00000000000000000000000000000000008d22e456c643ce680f5ea14553a9c249a43d4f92d94135dfec85bc58967ec01135507bd8ac3954b5876c5bebcc1179800000000000000000000000000000000022029d4abec7fc9ab3bfddf2f462660bef7449c4093144d9b7d6f9e84f4f1c947855ca6e09bbb3bee4db096978ae0dd0000000000000000000000000000000014beddf6a3fbcd621e2a592e1c87952ed277163ebf390896f7c668944d6e0a026d3df74b0fc877ed560527a80b981d1e000000000000000000000000000000001414af918645ce0d4d1f670333fedf286b01213408019e327d3cb9321f06fae311b598c2f78bb578e85692e6cb787a52c5a3268a8ab5a12214b266aaa4eb562aa05dd19575a7f3ba2d549a25f1900cb800000000000000000000000000000000129f1e25d96b8c879710a81b727b31d27ce9887c245bf908a3768f3606870ca6bfa70dbf5135819d36582d55f230e94c000000000000000000000000000000000e91eaa33e7cacce4e1d6d0fe905c72221b534a72cd51e1de79a25ef0c06ab454a849a241c023b0f82aa07de28e35869000000000000000000000000000000001379e390f2f0f3636312465469b532d876529d58dda8b024b6b81d242af47b5720af4360d5a3172ad80fd9fd8a14ba2d000000000000000000000000000000000775992d5a8ae0640af845fae03dd0b2197699f413f90f6130d21db0dab042324094b36acda26ed86c65821d2d8a29d9e62a7b00d2be967df04ef56121c95c8736efa95e1faa0196e1f4485da82b3c3c000000000000000000000000000000000f5420156358ddbabf31fcc94678866f899e38747e79dba8ae280704c4b199a03eb423ceed18b5cba7e7ce84583c84a0000000000000000000000000000000001127669ef3ba3785a859aa4e942e8fc3181f2703b0ece6ddbee8830d7ffbfe498794f1ca2e67c3ad39ebd33e838dbc5300000000000000000000000000000000138113386846310db8e21fb8bfe40035cd89e51736b491d5f2d3cf5672e6836c25f62eab80f25ab49d16dbb83796aa5d000000000000000000000000000000001711d74ef4995b473239a574fb8ea6edc6eb7a88793a093df4652da240d069c5bf9249b58e9b1e11f7d6619cdc28a5787a883bf845d1ed04e0664d814cf0b49cf8c3e8b8594ae5d2834c753851ed7803000000000000000000000000000000000d32ccc6598af8156f1c5b35e69e7c7f57f9fe18748510605a2a81b4ee09882bf3fb26abf50206cd57c77924ebeda8010000000000000000000000000000000009043d364e0637c60223f9a5db8c50e983746fdf4c9f7986d27f5f4f3a6df487592ea42078f14efcb3eb1b7e81d058eb000000000000000000000000000000000233495c4961e71cffc2abcde4007c0d587687aea905f3ac5758d0f8d9020197adb6f9d7b86a542b8efffb05dce997130000000000000000000000000000000015b084e773e66ab1459825b6e6dba055a96e4dc1d94ac0b640e906e0a9f12d2124a58537c458e6e1b571311b93acc26c0f474e8f4051c4e91124c14895fe9e2516b315d805b79013caf830524fce8880000000000000000000000000000000000e4b859c679a90c03ea4d4b0b3d38211f685db053aede0f7f359f712e1ae808185758546877502d57200da2c2137f37100000000000000000000000000000000173b24ca19436b51aae22838674c41c752536eada3197de6efc98303eceb3e6e8e47ee6679e61e3cb5c8c734c96c98720000000000000000000000000000000005232b8c97a4860a23999d6ed6d173d300ed50b77c7b3ceb4e8407d9d6877a6004e2f76c553bf458b7cfd8d1e6fd364e0000000000000000000000000000000018a115201e3f4eb308c16656b3ca0635e6284169cee3f28101903ce1cab0659c3d83a449918df6e58e8af2e001036b8d9b3a5790750825ab75ab7422f833c671b95c6c58619189db66a6215ce907381c000000000000000000000000000000000131232788aa3038a6b8a055a896af4f8129e3dd3397dfd90ce86b3e09a775e5b5e19f4387f4c02200a36bc2a1e09d98000000000000000000000000000000000eb8cc0455cbaae97dfd05c1246d3d5ee58c286d263184ae342f5c0ef432355a574bb9fb8ec67634f999b6d1419f2b6900000000000000000000000000000000188b8a85a6b255408f074b3cab66b95e0e1a1b5b8965034246dcc196f2bb84aca3a78907409826370bd65cd4c4d0bcf30000000000000000000000000000000009603984f6d9876e9c235621fa817efe45727fd8c4f76abb7b0796ae721701161b39ff7cab4c57850014e7f1750954ab6607a48ba3fa5c033a1ef90260ada14ee50c95e5167bf801ddbd3acb77c3b3880000000000000000000000000000000009003b42c08b5c7d3ee9f6abb96e08e6f537da25cd0cf7eb85a49067746c03566e133b54153380286ef5725db5b41058000000000000000000000000000000000f09b7b754c255e0e3b8435ade64d6960285759495659dfdb9b117806397baf8d3c87e30bee02c9e1b22fa3efcc58f300000000000000000000000000000000003582c08a8de4bbd20ebfa833517a75682618fba2702b6c71a4785f70dbdede4e86ad8e04aae1f50a6bb75842ab74aea000000000000000000000000000000000ec013f22e64a4d4fb6f964e8319feb1ddbcfb71329186545d9b9d7f97d1f6a56c8aad03d20e9c30966ca932e1f2bc67030db724eadd2f487d31dd4354b5c0321a7983aead21759807bd893217c4d40500000000000000000000000000000000025809fb06c8a31f31ca5b4a5c795bc93355c78d9a2a4c1d707e32ff2a71d94cc1bf7b709cd5d6a183cb05fb6b5f360c00000000000000000000000000000000127bd8c9ee6388905ffe59bb0fec0e42b4aa44be74e5961dc2353e474baabfea86c41c6173db413ee28681a6bfd3ccbc00000000000000000000000000000000181f40dd8581b9adb2981dbcae27c7e906138569ff41a833ed3e6ee4fb0baccf2ccbe5b28ae2ff8e08c4f534116b58c40000000000000000000000000000000005cdd822cb47f35f31e0cbc26f6c957d51c6880369af94fd84daa1f1ca95e41e240b910f031585842fd2dfb170d618aa88e71d0be8fd050f6dbb8b2fb3ae2a9e593bef7a5163255aabeb07282e8793e30000000000000000000000000000000004a06984a3916820368076ab8cad6ffffded2cf1e67ac33f539ea8fc7a79580c1969e55b2a2fe3b31de912d6606c20780000000000000000000000000000000008a1152a581b6fad2a23aa8b0b51cbe523e701193207c896d08b99a672dc047498e565a568b79f8f9188767ba95212be0000000000000000000000000000000003539e82e5b88ef660b6593fdfd9591ec23e7109642f4aea0570f1f8f8e00822d2af277632ba74910459535b35ad47120000000000000000000000000000000015d3441f621c7e6922c489e474f80ebeefbef66cc59e4350b6f803e409034b7f498be2dedc97d902590fc1e296fe983c26989184bb87a586b8752733f9ce9ea06422c6a898f0f402cbcf760a7a21c95c000000000000000000000000000000000f775e13276c2e32dfde955009422557f332fb42dd9ccc3246d2b080e3ec44d910aa734478899698a9b04f6fb1a8f922000000000000000000000000000000000460ee4df6dd0184bcdae6d53cb66967c2213fa878a829c3196664f8d594ca6d60bb2a56f93bda3b0d2e6aac0a1a222d000000000000000000000000000000000fc9bf81d4cc80ba4e4df7307f976c2ec1ea2415df3c263cc970583824cd83703aa994daaa6e5c20450da2ba90a242830000000000000000000000000000000011f08ecbda9a192b232e8330ccbccb16a26bcf4791707f2cf52c2e11a8b3993221666563a772d82f4665804275b03b613d1dd9cc44b30a4623a4d14861688cb678bbb8b2f8ae3ba140f60e64c05514b100000000000000000000000000000000027fe7ca0fdf1cab9a52e304e55350195492abecce4289b0f1c02235412bb012803e7eb59e23c665ea86dd4f74c35c440000000000000000000000000000000011301ecfc78ada92885bcba8af75da6cbcb448e0c49511f3ea306f4ab944f5bc114e72f473cdadee2d0e84021905c5300000000000000000000000000000000010eea529fd3162ad7b49638a70f6f2c26a6844251b2c2f9f8ba54cd334914e84e5a1ba9c7b4e7a8b9cff1a909db78bc8000000000000000000000000000000000b8a6235a7310d52fc8050bcc484e6ecf299099e193f91bea9db31fae71fbd14978984a9e6de10939d0fbba96314b0a55639d80f55e24e05e3d943340e324f6738a593a915a6bddb40f01bf12f73daef", - "Expected": "000000000000000000000000000000000de312093622aabdc7523cd72f568060f4236c7287d61c3372bf81d9bfebfda2795c3182d508f0268d8f445f6ea0a5f3000000000000000000000000000000000b027f117583406916a8f139d47227bbea28502ed0df91cf0841345435376c944a587c3b4bd60f8ae0be7c7bad1c8199000000000000000000000000000000000e9a7b96136b26b0044b11288d35969c17146241aa529e581a8fcf000c33fcfff2dfe1e55c0fb63f6032d0b6b0cf81180000000000000000000000000000000002a442e740ee390d87ec657fc218b76adad7f6a766cbe8f34f4824ecd1587deb3706af77a95c1d5f8e79eab1dc482c45", - "Name": "matter_g2_multiexp_10", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f54bcf1637d03854cc2b785e52bde25de7e45308048ed8ec0169069c2124871782bd9d26471014d039c9aa022e1a99d00000000000000000000000000000000106698139b096a5a79d43321ea64adb783011f04e5779625c9f77e5c390b46ef0d249387e978e64529bba2db8d7aef2f000000000000000000000000000000001668d5261a4ba37d79c76f44eae9ce2aa3e216c5fbf6cd2e90c6a73cebd8b59600303afce70de3e83a08c20de4609b100000000000000000000000000000000004b1b122cb55e688f8297913b84d466c6f3d99c09f4b039660238c8bcd0b7f6977851a6ea4b1deb01346db06d75180c142fe1e5b3c0245e5cfaa1ee8dd8ccc4ea8878ce2272d152fd8b24032297ac01800000000000000000000000000000000192a28dbc40d5ceee4d33b5c2778cacf8c3ed7d3227e7ea0d6fbaa7cd4a81134b63415f4f1960656b1fed15023ce3a4400000000000000000000000000000000138f296c45594a930b949756d0ae14dc9a720bb2bd9e93c7895268121a086a9d55c10135962a172c02da1eabfcb8caa20000000000000000000000000000000001605ef8182fa13a09a6b7661472296af2b0fdcfd7b051e7cf1d9e6d7c7f4ad9521d7732733399bfd5d09a088f25d215000000000000000000000000000000001928f2e5d47d7273e035114cbdeabaca724409a56056b4e95a4ca3b2222716b3a5368da3ed406d73f43e9571d1e04902253bdc5565b6ebc219a75ab74dc5ffd304c94e67160389f87111899ac07a71b70000000000000000000000000000000009b35f132a903579d82cae6a321c1ec7fb0281c3e82e9af05c3b2830ecb4a941da5b1637c1bf0fe9a39fcc9ceb0d09d8000000000000000000000000000000000eef9c0846064c866ae07b3709091b8bd48bb6b20f995b44fb49e030b5cb6d78b7f8201704b53697190a5e36e9a4541c000000000000000000000000000000000a98a5d0d5640d6399a3580036f0e5cd693a7cfaa26438a00767d5ffc0777b83c516316d9cd4597cf8601544038f4d9a000000000000000000000000000000000e59541068a62f105a0d26a5f79fa5fa8b41b2211f1fe674d84dd853663962d64a7f70e785b51ac3cc07267c73400fe6acbf64f93f6f85805517ddf0358ecfea1fd58a3666b8dd9d3773a28590fb8a13000000000000000000000000000000000157f58b1c7152a7f931bccd9a79073967ec28855a6d74fb8727f59c5e3728fbf07a5032dccb28eb8d8b24229f2dc1880000000000000000000000000000000019f41bbbb853edc1fe3ee82f901e613107dd4ba1d880284ee95a2c4cfb2220ec1408f8bff14defe59775136bc75b4a1f0000000000000000000000000000000015538789157505a0798aa36fdd171e0bb14bdac75339b35805807c18bf9175d877360748f97a8570754af0e28e89df660000000000000000000000000000000010500aaa99216aa979acd66c5b0cea2a6a973f1cd10c412e823c61cb897bce54d783a6c0acee22cf9052166a4bb5adb8d9d3f97893eb4f14f21f68110f612a444815fbf2f76b8399ba6045c8a44270df000000000000000000000000000000000439729e13e6a9b5baafdaac65783ce79a5972791610a333224e61104d15c746d7cf8350e619f0f72cb73635f6795c5f00000000000000000000000000000000092e3c976a4a5424b09e50e6513a9e1f427356ce161e742be31f0e589e9ff862460d41281f0bb2d27b1837a70a5938fc000000000000000000000000000000000e0e51e92ac3cabfd999cd72b67cfc488e150b11b18f9a31b1c2338fd4f2c58937521b5a107752c342e67666b99fc42500000000000000000000000000000000023d8884aa3f556e98e006960293230ac966ad18f3f715e6ab31a6bf0872c04e6f115fb1608cd87ffb369ff31012a11705fb554531f53b8cef8d93566df80878baa96f92bb54aec19445980b1a1f6c34000000000000000000000000000000000be33bc145611afdbadc636e9d7cb7e3a9c92c32f6944a2b7b5f44c248a0754c174e3286ad307fcdb2ea02a3578aa588000000000000000000000000000000000457de1fa8642d302065319b1d32009c64e7d941fb43d1b3cf455248664b1db516379df87aee05a651c132eab8aaccb5000000000000000000000000000000000a711f3bf1bda60ca49271e8a3143330cf924328d3ac6f7a802c15be1d7413e300f398274f338e6bfd0225cd8ba25fff000000000000000000000000000000000a786c5c7b4f1701e292aaad9b2e47bb883409aae0c44ae813ba48f401f4e2146ea0b1d85f2ce862b6ac9ad3015d4b14d79ba2c485f0aa0e35212fd7fecf970258903bd2427c4c8b97c2c425ee1190990000000000000000000000000000000007d03697e195a6b714fc9785b49e54e219694250cf5fe77553434eeced15422de3985f8c736996c1763d4b9248a7a7e00000000000000000000000000000000015841a70a168d2f356a8ad929e2d1433b782351f4833c51b50f3a1af48a85468c2ec02699550d21bd919203df73abeeb00000000000000000000000000000000170902520080c46faae2bf35de396d56921bd0279fc889f0187adbabb9ae52b849269d8097d5b3f331dd5a817f9b2ff40000000000000000000000000000000016846a000f037eaf5953b7c4b477e441ca4fa738895aa24dfb0ef01a4c8fc21a318d40a9424e151380084578ca413b3344c7017258bb979cc9bb8acbd3a3e62eac7aa152db46cd7398ef07edd031e4f60000000000000000000000000000000001a50509bfb12040c0271b231c566d13510e6ba84448e59685f5bfbf5b008fdc64cd5e9456beabd23ac011b071e3a5fc0000000000000000000000000000000014a964c9faf1752170ca40cff1b9b4fa17f8d2b56a4c4bd7ffabb65798771cd624ba61ee43160e70731fb9b07af8ecc2000000000000000000000000000000001822ceaae7bd0a734f57b67e4834cfb00a6b415459d81c7d380a2e5b5c795eb1b6d63ddffb1131cdfdf0d76852c75a70000000000000000000000000000000000c5a1575b30e5470151ba055f577a0ea49cff869614c50194829e53a3e1a95847fa387a0f45d537cabef3a5925e61c432583e821328ae90a7db16b20525228e8d915bc8d46a642cb0a06dfb64168cf1c0000000000000000000000000000000018cab86a0d70fa30b4df3e05a91eef57f6505cbe4bb7284de56d420ef3bf315be9249eedfae92561c643bac2c92301ee00000000000000000000000000000000098ca598ccdffa9bc9d464d51b46ed8a8f22a87ef408cfa45fa7f78ae2dcb9f861d9d6a571f6fa702a71e783ee3395cb000000000000000000000000000000000c073c0a323c3051c302c0558463a5c030539d74b440fdcb16b42ad5ec097e10c16bd9a651d149dd719fb1fb865420a9000000000000000000000000000000000164e622bfb8ecd5eaf691abad9db38ccc64ff0fa1784d26db8c8fbebc929bc6d4dd471321e01233d55fb4a9661780b5506f22d323a740553d6107e651c192c1dc6e0a0161a82351f125f08c77e53fdb000000000000000000000000000000000fa48147388181e8d0033004118848c50c6425f2e5f91945a17abcff4d11928d298c092d60184e75e67c7ddb9eaa8255000000000000000000000000000000000c535bc54df050c1ba8d858a346d3a644e03fe24873b7dc3e23518d44b06fcb3f52b4be6f11d3b66f0180a0a95dddf680000000000000000000000000000000015e279a2893c205dadc8e1cdebd9c85454cd4b5d7537f984c8f9d451f8316620279357e218fef87339f1728fa317fad5000000000000000000000000000000000316e343ba68c8a762f4c8f2a5c20f16abc4a7a8365556c1625df832219670619b6dc70727e9bd9a64ed491dc22cb9d57f1bc0e1ebff8f935330c35573f9fc3b900606da9cca9a36b425977af47c7ca60000000000000000000000000000000011dc72100cdf676e41f21015fa7c57897da8260609467ffd38c17868a4dcd2bd5d4d72e89cd0db2de83618222ea3b5cd0000000000000000000000000000000007e074f73287faf304f618478566b91c8e191b229ab40743081342e676be09c2523681cf7ca6f7a396f8589a4ae18a6d000000000000000000000000000000000ff753a16c16bf0dd1de9fa9316694214aea6f99b81f66b6bffd58837c00d7f5632ed5f8f4cdf32ec59c29241ed5e28b000000000000000000000000000000000851e26675814612bcfa639fe567633e1960578a0c8d2e6568418f633eebc109e6c8af97e77bb28ddd47c6bba8a7ba724429b85fae16200da6eb8f62e95e027c24aa6ee2a145f6ef225139f29aaca29c0000000000000000000000000000000009eb2f172db0fe9ac0332381d929fa200a97047f6e732570d23fe27f5ea3013fdc52fd0b5ee74a4387af44647b75f956000000000000000000000000000000001355f8e1cf45443855f2d62dba0fe45b2bfc4e0d06aa7aec7e4f7f9c4e25b33d9c46a01c224517bac9a1390a9806ed4f00000000000000000000000000000000179d47a62a5c847f47341b1ba58f2c3b073c5282f925f57efed1fc43db04185955075255e4e4f6c209757ddae59101dd000000000000000000000000000000000ef5f74d4b13754ceb3b468879f1a8befb8bbbdbb143eceabf2dc8e68fe6cc8e1ea4f3eca1b23a1175c9f5f5c4c20d3454a852baf21df9f4ec8d711a48e6ffb36be8c09c8c60eaa090876236b2eae37a0000000000000000000000000000000005b70a4d5b91b85971aef26b1521e12904b7ad224f25e31ec6ef59856cc702043a3eb975bf21dc8e4fc55171a3865bbd0000000000000000000000000000000007cf7c3e75a837545b53ca3e175a275dc6fe42fb88678aad45910d150ea9c6c94eba615429540348bb2ba8efacbb20e60000000000000000000000000000000002eacb469f5f8ee6c9f557a6ddcc854e955c5b9203b4ca5dd2e097d3e021479e13629863eb5ff17db46a17d3b0227f58000000000000000000000000000000000905e66f3a051b304b110a8682169fa749ba0de7763d3af7edc3e40f2d22ce7b6aa00cd06d2c82d74f3a9709d955f44e13814a3c6386b19f7b93c2c4e0eb1568e8bd3f0012a1ae1357b127c33808aa0400000000000000000000000000000000060ac9ce51426d360eff0d911d9f97a86494340bc5c5ba31ef146b55ad3633ec57a700f04b0cb9d4e91e13c2cc5e68a8000000000000000000000000000000000df205ed85e27c25ce27270384d7c3e58c4e0a9f214d74cddfbc7904eb3115e7bf204375df7558c3e65f7a81a942c5160000000000000000000000000000000007a220d42ca8906013479442d7204457b3ff37c9ee70d64f9f6858ba788b7fc13b71d33ad527c6fc673ad8940b0f01cc000000000000000000000000000000000ad481ef549de13b174d82fe88fa57b7e31ecd8999bcdb0c7a8735ab619a13b1e684b9473f0c59c734567cc08c76ecd6aba0fb0440b2461ef64af6ec5f15db381714fce1da6e03ca962cfc94bba26d74000000000000000000000000000000000366f604228e2dff2348a462c56e0043037d1b415ffaf155e72c559d185c6b0a0d125585d060f159a8cdad959af631f5000000000000000000000000000000000f69e829a0995914ac122299d4424b4e2e120fa4913939d2f18f9d1496e7255d00ff0829c20521ef47bb0dee06c28dab000000000000000000000000000000000a3efb4a376281a60f5246d8fc10bc23cbb9cb71037f8f57271a9b01f5e0340a562f9acf0e9a95b8c65ab7a5cd95520a0000000000000000000000000000000004a4ec86e2b04bcb35c7840d85cd1dfaa88e17ffb557ac591640ed8e563cac891793b92e349a7903c6c1f88d26a01c88c01749cac36dbbdba5662687fd1ea5391ef9d0bbd24e05bb5904a20fa6a1e11e000000000000000000000000000000000f5bcc27c243ef65dfbfc0de6d431706ab20d6cf6408ca989a2bc1c52b78ab63de6f58b70bfcaf6878a2746f249b6b160000000000000000000000000000000016a4c9e8ad0634e8afa8606a1a7bd1d8cc0815dfc6906b6e6446e0ceddba4a4a2df979d27cd07b8982a12550bc700fce00000000000000000000000000000000051f8d972362caf0a8a39045bb468112f2e73afa392079f8a4dc4c3a3cbb8dc224c21b6633a5ffbad08796ba2f8df44b000000000000000000000000000000001825aeffda04705ded9c702ba30d24b9fe8eb7cb106ee5d4e4ba029dcb57bc42c74e74e92ef8360cf130590b838645429680fbd6e6c7b1b14b000d3d18bf93242c74662ef108d711d85d8d442e415ffd", - "Expected": "000000000000000000000000000000000d0ab61b29ddea1aee0ca4e81b5369f37cf45be383f64ba0b1a5a74b790d7264016ee671959444c94b8e6291c5158ea90000000000000000000000000000000000152bf3709c56b3add8e3396d17abcfebbcfeb230529ea8144d6a120a0a6aa83cb284e40ffb9fd9a96f8a2f7244212400000000000000000000000000000000041f516a7cb2a7137746d028b0739c79ffd8f7535f20ba3728ede32504fe058baaf684cc7677967aa46777818b1fb6630000000000000000000000000000000009f1035729c55cf6ee090983a54d8c0574bf96342901f471a2e5380f11f235a075b0e157c38c456b6eeeaa10b87d3afe", - "Name": "matter_g2_multiexp_11", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011ada4731ae7df493e405383603a8d79ef77f3fd14fe7b8bd9d2afe068998cb712e84927d5e6ea6e94d7f10270fd193b0000000000000000000000000000000008a14eddf88826dc3be792a0c1f7395efdf91454cec7e26c89f6beda37b194b706dbdde8745129e821b6f4b4ea6118490000000000000000000000000000000011c29513e8a826e6b3eefaa20ad841605d04b813cca282fe02dca0f588b9a579b2195b0b080cb6d12c1a7881008117f8000000000000000000000000000000000689c67d05ca379367fec99439e3806f827218ffaae995bf38dd8e2919fb2e751f426525cc2c6ead3b9aff2e377fc99e1ddff10527bb64de6ee2e3ab4959ebef9e7a6964b7482f9fae396b2b9b0cff9e000000000000000000000000000000000dd683a8e4ad54b1a95826a3000750c6e3cb250ab5d6add63c21b182d736b220d917d4e70044ec7101c3bf8ac620e1dd000000000000000000000000000000000f3e411cc6800b304fda1373ffa60c7718e20bf3e2e5f9784a81b47e398888b366e1f04f48f5aa070a661b5e2148d4fa000000000000000000000000000000000b0f8d0b695e000158ba80881a9256ed9dda5a7f53b550bf3b5c67ab160060fcbf5ce07fe38253ce037abedf4c6f08d1000000000000000000000000000000000bb92d407c457e9ea7b9851770d2743758e162dc9cdff2dd54b8271c046f642729cd2f10576013adac84a46d38623b932943fa2957d267019309f4fe5b6725379d893dcc270ff7f35b3811ad1d8d12b100000000000000000000000000000000023e880685aa69b3480bf2b7f2aed1181e094322da9e79c9263d50a49ba4fca713740bdb55886fc81c81a51045b35139000000000000000000000000000000001707049fb8b7ad278be2949b9eae2e28bde9de1d9eb964eae582541c2d7a8afc4c1489624a0919047a167028b8c77e3c00000000000000000000000000000000062dbb2bfce2f67c32b87ec2fa01ebf7deddfcbeda2fcf0ef094b1be77b7411f657e745350b6d2da16fc83a96f6f20e500000000000000000000000000000000062daeba038c7bc379f56ac371745b91fdfd5b4cbbe50d9619bf1d077f3cde966f81f9b851ebd206f2609a780b6dbd681551a3c2d0391fd8dedade892e8e2171e652d2a9b52f2288451c55f77fac788a000000000000000000000000000000000b553826dd9e2252c9da74c2bf1bf850df3f9c37439859f93df3fbceb7cca4fd949dcaa7fff31c9e06f41e51ae0b30bc00000000000000000000000000000000187810711ea5911a437a62e2ca483983bf2535ff9301a1cfe1b4d41902ef689f8d86f817a2a7c77128e4ce1ef6b037d60000000000000000000000000000000010170cf5f2ce08211cfc41bf54cfaa16584f833f7b97b2f6bc436eecc56ef44463690ea1f5c8c2a8f69d93a25206282b0000000000000000000000000000000001e627a68dbab6b0d05c85e49b966a769461ec38c38fd94992839bd0d46e06410fa7a48d418d65a8285f7852e8af4b318eb2fa94a5c97c28d95008dd1fe60137b34c2e763292d1b86993c02790b8c91f0000000000000000000000000000000011ebe2edc3de58a57aa9ab4d6626d7b93235ed24efc3d75c1ecae376c00beffc5e89ec509d243f693d327f7a4551921f00000000000000000000000000000000088ca2fe0651e4d8f3958454640a58ea1cdd804bfd2700bb1bb8e26ac50f2d7fc8c292f94b0bccef5735c4548025735400000000000000000000000000000000154936de8932279cd39ae803a5d814864953f647a5334bad958222de765250e4bc847e02979689dc9cfe1993486b5750000000000000000000000000000000000c7ce07c9746c6d72dae11e243acbe12dc23423f870f3130b244eef34524d547fe0b2c4b704ecb6b2e6c32f5675ce67ff72ae1def6c988f9242bff0e683b8d2a5c1aecfd6ebb9442131ec5b5b825d0f600000000000000000000000000000000031ea855125d75321a2a86a93e72fb3869dede7531dbcc1cb07ea2a352f3c6cd913275d0d43ccc370f4539f668f205f50000000000000000000000000000000006c4cadb11361f164f5899c6b57c0c6d8af365d902f4575c9d2d14dfd880501ce9ce218544b44bf07f0f04ed68e8f315000000000000000000000000000000000131332638026fd25b1a849c984f9dedd71e64fb52a61968666ba80238673077ac00b9e09817426ceac8c308f475303c000000000000000000000000000000000c7634af796e7aea4d4d83c9972fc822dad951d2473210ad82706ae0aa023ea85c1c467bdda68881094ad2a4f54cb33f331451748146f0564ab0d91b09db87e8a6ba8b14f8329bc041911616195f9fc0000000000000000000000000000000000fcdbf0083065e13deee2020bb6e47cb9e482df3768ce569f1f7c0e1c6083c97d9f08444e67857c2dce40e4a7b8d50cf00000000000000000000000000000000010f246e8ffccc2e752049f638617e122773a6f10220cdcc0603d24f1a94ca7c100f8ee2d9bc7c0a931fa0385eee456f000000000000000000000000000000000f8b68941df75cac3d4b6b3bee43fb357c8f4e56309d8509fdc62620a085d7ee58f52c7dff28525a449cabfd3b7ab3dc00000000000000000000000000000000019f934ef0c7c40786b073d38cb3e4623544cad59cb63440d4a6e76944d491f6b982e3a5e84124996634687d4618418316d298bf591bd927aee24a37c5ba508c3bc121f5150fcd1a70c1f27a79da7d73000000000000000000000000000000000c0208c1f3653fb3a5e2acbbb42f2598b22db1a714d616ee6bb501c3338e80db34d517c7086d43ddc77e0134dc5a4f290000000000000000000000000000000000a528245342e44e36f8e02e7259749e63ecfb38cb0609075e871701f2b3bb0765277b78d28cc3ecb7aa8c9e3b27eaf10000000000000000000000000000000010446583a905864064400f9ef168a122d179d46a058525c9be8a65a5d2ac5e967d51185d4964f81a5571123717210d050000000000000000000000000000000017da91a1d0358271b11a0aa524341ba1ee8c31bed15efc4c9183d60c6e1842ec4383070a09914fda991a63d55efa8f2156be810c3fa86e35bc935fc2b27971c9c41d03c8ab7b6c8869db90b6e0986ef400000000000000000000000000000000176c64efbfc9958b9c8e71b55e9fdf525d4e5a0265ff01ba95bcd5c6093bd063726f8e277d00b138fa4d8c8f80afc4e200000000000000000000000000000000183eaa6c3c605828852ab5e8a9432bcb87411dd18d574cc2491f1a280e7a267ff9ccc80b06c22e95107a72f22ba2fafc0000000000000000000000000000000013319d3a8564ffcd6fc7accdded740127ef205e8299b390d21e96b2609cbb463569c878f36191d43927868b06dcb912b0000000000000000000000000000000000fbde0ad8e89f5458007ef6ba0f01d0aba04217e06745a5571eedaf544443150f59117b56937f533b4974e5d57c41cbaea4445926775a6baffb4dbeb249dfe3b3e0c29f2a579927f540d8f6451553ef000000000000000000000000000000000c044a5116e175ca1d1ae59d400de24e4f47132251b4b3dccdf458623c36b4d3d83abc644a2247ac4d0e3f195d12e7b000000000000000000000000000000000048dff6bf65f158b19b992167ff8adb5c858a154bd68bf0c84e41351bf47a8f870cc735d1be5d9afc62bbcda2fcdb1c20000000000000000000000000000000008c5539746d2610eea22e79b3fe5b33a47fd3bf9991d34c6f9d824a46458480b735c0051d7b4e4909fdb1f2a1a4e4b3a000000000000000000000000000000001936558ac97acd903a29d07c4aea399227ea13fd6dea820813c5519412c157e1a477fcfbab60a787c6b3834eac4522889ee0e58d08779add74b68dd75e82df172b719cb5a772b0bbb34d3401b9f212ea0000000000000000000000000000000017d978d60fc89b0429c1a6424231fe9274cedad5d78d9c4ac5aa2dd5e70e8238a0bb1904bb4b6ee5de5cd1ac514c62a8000000000000000000000000000000000d4ce85a95dbc40f405f4e7ebf9121cdcd22766737c39618ad0fb3e10a6e53be1faceaa96073b2a877ab808483ec9b6f0000000000000000000000000000000016c61599ae4da787fa6db233fc28f5c56f7133d403901800ab5fa19d058fb27ecb34ca2e56ffa7628ed004c9e62092700000000000000000000000000000000001e64e4adfdafbb423b1b9f8973738c690713911f68f658d234e57dc35b9554e0f7ba345dd7920b429a12b9c74775222773d07cb9d20744a2c3ac88082a8d6606acdc892666753793a2b8bb81116cc6d000000000000000000000000000000000908ebe27a1bdf0b9e56325c00ea3814527005793ea97eafec541c01cf2d7c909d2521a5fd475589a31e297cecfd5e7000000000000000000000000000000000017e3c40c60cd369ce5a90f6c4aff14896cf73fe06432e71940bd8086e36c2353d6bf9dd414bcf92889887e2d49fbbf5000000000000000000000000000000000ded856e5b2b139487b3816351584f06582a933af2bd4573a89aab0a41af01ec1cb928a7d8035228302032d399bc7caa000000000000000000000000000000000833b77c5d5c98ad95a144c0f167fd3bd62b03f4ad721561ed1d84c7137dcb19521f781bdd3ddc22afdd52c75146e101f6bb1445e9146b117bd0c95b009fba670a5391874dd314cefc884bdb0a4eba680000000000000000000000000000000005c6f28c5ebd981fff3aacd70eb18f134bffdc8507d1a3aa153e5787b68fba7f4a94c43045d2676aaa992754783ae87800000000000000000000000000000000148ff39e8062bd488accfead42a684f781c4ee579af6204b5b8dabad9022b029139b1f3670fc270710ced9a53253850c000000000000000000000000000000000ff50eca1a92f123e2534b3289f37ffd5d4e05f7678017ac20e35c2deca054dbe376c5529cddb5e58973f5c60914f251000000000000000000000000000000000b58298ba9496fe32891f4c1cff25395ac5a447205cedaadda4dcb929260ee55781916ef5e4e39793fa2831142111226d4158de4e23d793ba77c24a70f0ad07314927fff34361b0d74b25e8922512d7a00000000000000000000000000000000184d156f881f7d10d2f196b7599db85ee826c9c95383978ed68918756f642a2ed1c951503251b0778dcc39598d79fc8a000000000000000000000000000000000952168761380e8fc90a4966e94b8d2b88a784f6e607c99d9af1aa902506f59d6879153339fdb7b8acda178b9bce4ef90000000000000000000000000000000009997621d4e17c76b7798ef2f99d3c0a7519cce278cf718789cd8227b2b1459af7fbbc93078aa0aa361167b1d1c9363600000000000000000000000000000000005369eb3a77d2e26f9907a2d930f39dbb87634346cf10525733aac8ea10eb918d4043d2a05ff8e80b9c69a670e17f15c629ef41d5a2ce49fd81930406f19e760a47074e159ce372dd67e7ea46ad706b0000000000000000000000000000000019bdb390c66f7d28cfaa91bcb34c5c55bf93a9f2345ea396f18ed33ff2221a39cf68c5514fe091f7882e82470efb1fee0000000000000000000000000000000002d0b48d2c0377b0dffca247b7625f9901f86e2161626b4154bc25d6c643a48e9addd260298bedaa80e42caa5b9fc5b10000000000000000000000000000000018a2b0a760652e546eeb42e857ca48f59741eed91822c17692e9c41358b213c82537c9c6898713a13a241cca627a7dc400000000000000000000000000000000079c02f41fca45a56d9d8e305141b4fe8f98d102197e7864065d342e6b07f65b62632e0c12660f37de4d698c0df3d0f3c718651715ab786b4855092ed21be41b499b7824d0bcf68ad31b31ee4cb730d5000000000000000000000000000000000c0448fd4ebe9b5615653336fe0a618fa281b0fd7d72a8f956a5fde84f7d356b6be853bf823436bc0b61a603636db9ef000000000000000000000000000000000dc4f2b4d810c4290e263098576cac393fce137cc901b3be23507cecbda7d86d18022cf8e1a7df4b1298520ae5c9314c000000000000000000000000000000000a39413967b558dd8a6b2bed972687d984fb9abd0662a266680f8c90f1897e2aca1ba37b41d7d3fd47406bc5fa3c5b7f0000000000000000000000000000000000550fcbe5bb75afdd8d5f387798a8e83a8dbb6da4918c24eb2e5d2d8acd3512f6649a4ac9c8d3e6794e6f4f8a87687bc685a2872c4980518fe60c61e2276ef53c007166f7eceb355b4cd533f42c00b7", - "Expected": "000000000000000000000000000000001654e242002aafa89c6fdb9e8fe2c197ad2f8aad11868568dd39d68ca35919f94308a80303655bc83fd130de6f9723a900000000000000000000000000000000062b5a064840a5a28b4991ae949f9508586447ad5e8c463593503c0e5857c5233b7ce7ac03e555c2675f2e320e8cee6a0000000000000000000000000000000017d65fbd7caa69629f66be8b201f53baee5ef2957a3c04fe384ae82959105342b52483eba6bcc1442763c677f515f6cf0000000000000000000000000000000002ef8f8ed1114cc9d299e59003c61d62edf8971d65b1b621779bd7b270c4123eb629f56dfa2e2723501588a0caf1847c", - "Name": "matter_g2_multiexp_12", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001392409b92282bccbdaa0268e1173e60911754eb3cdc28a52e93f4d82ec99026f314dfdc59b39a4f988100f9c30cbd1e0000000000000000000000000000000016b3c555d5c196551ba715c6c334a668bcae80f5a17f038038d35dce34843f79968a90e2102f0faa22a93d3240b58d490000000000000000000000000000000002daf83727fdf45dcc1a15adf47de3f8a1724cf4d34116f52106a9e6b22dc24a288e89b940cc57e5a6bb87ee70f680a5000000000000000000000000000000000446009fa3555e4a056a820efa7da52117c15eb105af57985d8e9b33b0b22fde6aef9bad30480c2b8c1246519795f61fc067ecd54e9ef59996493f846ecca63bbd7ec28da586f0b8d41bfdc6d97a35cb00000000000000000000000000000000000372ead514d53007690843484c966361661816e0d3949b868176d7a9bea42064f49113a74f2572a6dca7afa0642fa5000000000000000000000000000000001199d3ea66fad87074e62a0b77d3fb962db17dd948f30c38f5beb0e44e1cd11d9172b878128e9a64a08394f13cd786f60000000000000000000000000000000018b7db157bb326ee2f72d4df2b1e0ddf0a90401ccfca1d4ffd6379c62acf5d6e4176a23ded2f81653038d56d848b4fbb000000000000000000000000000000000a932cc9740812c8bde33b68d94220690e0f55618b7e51d3e3fc29d0cb9a8d42b8f8e1efbba5984c3c1007c9a80fae408b5112baca5e0f2bfb885c5041189612918d203a117d886bcb3b27df7e64d17d0000000000000000000000000000000015798d10386f6d24caed3859875be5fb1a43ac753f725f28da6b3583bd9c0e404d36265c2305d7d194e2ad84bfd2bafe000000000000000000000000000000000ef2ea5f3b6e03e3c9693d6db60019f2efa4ea586bdb7623f03bd035c603e8996ef2ea7cf745aa31f60679ca04f93875000000000000000000000000000000001792a66785a3087a80c4b8652c1e4db8f602cf75c1a6955f480a977f92ea262965dad84061f6045177c831dc4a3bf8400000000000000000000000000000000006ea3862318974d6347639ec0d70afe748f4edf32b9e437fd98f38eaf72168a153cac180c2d67bac8a358e3a4d57a2b32db7ad39ec8129e9e9206bd46cec6a8ad3362ade1beaa97befe148f6c67a9c2b00000000000000000000000000000000000974da7500df70d888d5876e7c61bfffcdf830b49bdd40edf65a2ff476e9add35eaf9451a2166e9781805192ffd7ac000000000000000000000000000000000cb2e7152b5b40758b18caea356dd8e095f400282881207c4b79d10d741756e526be261b98b726d5cefb668dcf73a0a00000000000000000000000000000000014aeebb995d464f4d77bbb72f15d9078936b5ab68eb8022bdd97d050576dbe46e6010eb72250c8ccf2a59138efb38f9d000000000000000000000000000000000cf7162768e8eb50e21d3c0a076c7bac4920c70f334336037fb40e57e0efa91eb025356ac3f0988a6b127408a02eb53fe2400a11d9a67041824b97a96f0ea9da8848e7990373655d76e8bd4eb84df5dc000000000000000000000000000000000b1d6214796b4775c2b50e634a549ed104e6ebc0e032967b17eece6cf88c93aac23059f263faf3c3f38463270320135c0000000000000000000000000000000013ffa3894a36226664ff53ba9256d39c6312303f5cbda6847b4f68c56134b7d731e74bd711014fe374f909a081a7d02a000000000000000000000000000000000ae4590cdcb1367392635d0f8dc6b9557abd16290fd1abca6da354646d8585a7c9432978dc616e5fc38cd71d55f139c200000000000000000000000000000000124a7b5574ef52359b4beabcc56d3286db8c8fe4ca4718f75da28d89a8a95efb878c18b48360dbcb6fb50a9f18f0d559aa2d17c409ade92566ddb3913806723d41067540a36a9c283bdacb273c5b258a00000000000000000000000000000000148ab0e847ecac963f0156da025dbc52e765cd8827fd55ba2969da6775649529226ab13ab8537ad0b89e8f1ebc8648ea000000000000000000000000000000001395b1adb6a56b91c3621a4ac5886a7b13ec00f1c74d5317eb74a766eae655e09e269ec48cdf740abc38f4d6fe52dd0f000000000000000000000000000000000f70f77f07ef2909033665bc05cfeea7df6ed55f2f0b1b87d9f247b6c07c7e22f516840efe68005c3953a2702573a9b400000000000000000000000000000000166a334a711416cab180cc498308487b281711f2d1b832c410ebb4c591af54b154fc8c8d7ac9a49a241f7a3840acbc75e5e3d21862b64e09a0893ece646de60cd66aa483662125ffabc46cc52f1cdefa0000000000000000000000000000000008c19bcbdc2ef26a30dd88f3e35dc7fbb3c81c0224cbcd6b12c90883f3973bd7089636f997e5f213fbdcb79514c551c600000000000000000000000000000000058620cba8ed5b738167e809cf71392aadfe8f384a4cf397d10f674cfa914e9e02bb1518e42f16806214fec52d880f6100000000000000000000000000000000048ac1120d26e4173bb33a58c0ce86329cdbe9df6a6f268c8d5ee4f1d6110f9d81cd50c46256198a2462d50be3e781270000000000000000000000000000000010af13ba791d554720f5075d46d03b55c0c1dccd679cef5a7d439ae868d3ff2780cc3ab151feb72b8b92905a205e630449510ab1b7850badf58cacad67fe47135f6524f0d160f3013e8ff1c881e469e40000000000000000000000000000000005c30a126c94b87c54270d0f23a486c3b36a8b491bbd805ae0d5f2bea818a87ff5aaed2d5e6317b786ab5a23f1cb48da000000000000000000000000000000000eb2d4663eca7f8433f10e84984781a57fffcb8f9535518721521ddfc7a4958778915ea3c57bef399a453b8ebc10befb00000000000000000000000000000000161947f57d97a858e5b3e918dbb22dbf28629e51e81335a9bf105d0fd660ef80087c8d69d8db9841cc69fbb5e7f81487000000000000000000000000000000000c52b6a559928fe4ad984a0569c081f3f71eed3d5b0d3c14d1a23afa45594e0fbd94143348390bee178720fc603145ab713aa69664a8c721cefa7d6dd3fe9f92432b4d350621d5297805fcabb21ff8c600000000000000000000000000000000071aa47d392e1a7787b37c52acedbb4632d5549fc11b79919bab7d22f1bbf1c3a239df622b8824b07f6e35e627283b8500000000000000000000000000000000198e72e05388021919dfc1b2a58ca72bf7655cc6c9b62abe3b45cc782ccfd4a2334780e451b8a6b7c311887036813fe4000000000000000000000000000000000e20cbedbafd96c42612e146debae48c7fab4846b20ad0848c4c42c6aa0603e72f94dfc938ed9e3a9886d221ccbdef70000000000000000000000000000000000c861d1878e63e313e672bebdadd3fdbb691cff5fecbc24da895febce2eef0a3c774a8a9d751498e4fc8e2b71daeb40dc040d8bf0a787346560fa3b100b2dd9adb3f7ee716b8103abdd9609363345ae40000000000000000000000000000000005f7cd2205fa2e17fb9896efe3fbe110e1fa59db1ae5f8d6b5f4510abb4da867933d4fe3caaadc4457dcbb35f1b9c62b00000000000000000000000000000000126f2ef6022a7211fa865c1dbdd5b84d96cddff424b06647acc462408f2d31f34ce898d76e1e124db7c39e08dab0bff6000000000000000000000000000000000987f916ad6f718695f3c40703c59ca93eba38931b45d7c33c64c9f75556f075b744dfff8a5f21489b3db6c3846ba09e0000000000000000000000000000000013011b8c72f3853738e22957f742b05ec428ab0da28901800f787b7c3678449acd0359fee93c40c69623aa4acfc0a81017b811aeac4fb7d91abc655f8a4392176f9060346073c957ef903e25d10935a00000000000000000000000000000000014b88c0586fa18333ab11a79acab8e12c6257f82a4ed16d929768a60a3a5d780a22101c32ea9b0099aa2816f18a0351a000000000000000000000000000000000de0fde69efd2cea7ae08d6d2443883002e0b4e11da253222429f6ecc67ba8d282eee84d7f46e0ad00b039a2c2ad226f000000000000000000000000000000000aedfa0a5a8b7577dcc1094469233f8b07e6fc32af26841894d498d70c6a9a046ad636086def948d21e39833c5b6c5a70000000000000000000000000000000010ec6aa0efba4995582585bb67f997f60741648156324696312d17656baf6aeb3e2db0d1a272912fab2fe81d139e971cbd1f096026159218836a46b9801a4f0c43189324d20220aca777b826eaf2575200000000000000000000000000000000004a847c06abc8ae7ce6e6ff0ab856889dd3e9697a75e3cd4d2af9e06d4c2fc48c0562289348ff52f4d9855ad03d83aa00000000000000000000000000000000075673bc79bafa9a64de6bb0e9dd9fa29cdc9c82e90a7348593eec673cbbf22b1eca436ecf767d45852ed888a3f23949000000000000000000000000000000000f3f8543d1e667404b4564dddba4d7c11d13881fcd8ad774c8eab8fc599f55147c353cd6e163cd7b9d5da55ebc13c2e800000000000000000000000000000000069edec7e7d26962d88a89dfad213daa36046bb2851e5d67adbaa227220f29f83ea67cd3747e6724f148dac28308604cf221dedfc21098ff9a9507e493d0fdb1efa6029fcdab23a016515078c76f7627000000000000000000000000000000000c945e83822896974116663d3e2769f3df5a70d55b8392c1f6966e330951f3cc5688742d4588648a6988b928b9fe00100000000000000000000000000000000003e94b7ff7c71d633ce69bb44d0ba1bfc7c27a5ee618e703aef81a45ad61771a2fa8e3dadddf7c8038f1f65ad7513801000000000000000000000000000000001727d768c1b51066d2af87a9da3e24ea2a75b0f75b8ece70727f9f54ab77d841e7ae01c9c0760f4186d02a28d6f8ddfb0000000000000000000000000000000000a273f9395cd49b646e90fd2526d5c93fd46c7366b715546529c9edf5cb3d274c9947c21a03add3e7b20612636a6745ba5b30d1397bf28100f108b84e05107ddd6cae2e82f1973ce187e8c3a7d02f3e000000000000000000000000000000000c996c16a16879bd3194ac366bbd11b5863123ce6fdabeafe56407600e5d49c92ba68ac1256e1515dc9256de14ac26de0000000000000000000000000000000018c584d8a4f14900b2fee70b50b700199ec2372b731dd1380f42ec7fd3d01f0c9a007554059b85946c1c4f4e2fc504ad00000000000000000000000000000000073d6c7d671762e5398e4c9d57f6b68c3d97dfe0d01783f124256fac236f03b774db58b79cb4d5558e1ebf18bb9e19680000000000000000000000000000000008eb2b95e17fdda916b08ff2819cecd2eb031f41c8299b308339b7d9836382ced75e8eb1514a70356882d3a43227a9bc19aadc83d1db9140af303c0492d2b9bb9e2b53ddb62cd2132bdf8ef62aaed683000000000000000000000000000000001029fc28cd502caf3ea3619f6fd04bf457e6a452b5cad680ec2d4f8222a5ac2daa92b880bda76016973494e605ab28c60000000000000000000000000000000002c672c7571b5d8e99de6e47e0a2eb71c6d9bd12baf2b083e6f88598b32c4644d1486aef582c5936e622058bb141db1700000000000000000000000000000000033cda383a77d5b3adbb0809e834993c56717f81f8c66ad2d97f2b298d5a46f7b29a74d35da09271b7053a05af096393000000000000000000000000000000000132da041c6e3e1d68bbd2223f8531eabde8e180b36b2cd0ed4fca248f255cf3eeccdc5f61e1c581ce54edcfb2b73e0787eb6fc40b00246910626ab66bfbac96ea09242d1d70496466e4d681942050700000000000000000000000000000000009721f22bc49f68d703a4dfccc3bae791caaf0d73892bafa6e9da465ddaf0fb1a069ffdd55306acff2407da64c1c5a0200000000000000000000000000000000056c0a4804a19aeaf1b4fe52064e43de8e5d41a8d77de054e2cfdff078eaf468d123d7317818d1bad1bf3469c0070b680000000000000000000000000000000007f1f318aed043d9ad7bdd53eb6a8c3167240fca75925b04795210700463c93a66ed64851195df1bafbbe4227d7db5ff0000000000000000000000000000000007b8945e258311e7672e842b91b540fec9ef4a79296956a5cba3749c0ad95ed83d7b0b48384ffb3188459e997b86695d3bb5926f36808c0024ea7388998b4cc8c6c48d32917f6456b39d514143c6eded", - "Expected": "00000000000000000000000000000000086a1ab4c19c27f70aa422e8292752c50b365d6fe3eba21e8f2ed51f283df0446020834ad27c18b5c7285d1156049bef0000000000000000000000000000000007288f40fde69bd350ce1f4d0f68e645f42de319cc032250b76fe4fa305341e244e5b2366751d5311105e3ccd30e701c0000000000000000000000000000000011d0c487c4eceaeac009b694931f8eafaf8eecd6028f14a4de33d2940bbb747025eecd509564721b50b7186910f81949000000000000000000000000000000000366f0c901fb859b4bae006fbcc9ec7e456eedc7366c899f68090fbd457c37b03ab99ae982872c7888b65c1a056c134c", - "Name": "matter_g2_multiexp_13", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000072f3f03bb09ca30239dd8302b05e0d9dc4e43ea33e865864a82578c35eafcf6868bf0cd9431b92b76f00990b780ffa400000000000000000000000000000000170b76cfb7944ea5ea055aeedaface3e8f0fa4d0ff657fb9d5311f3af6e736da84a5e2bef5188e20f76fb42591267fd9000000000000000000000000000000000d85300009165a8da9cb8e590f7f8d372e4264df150b1551185c80e49dbedaaf872ef69c5763fc3713d0c087c89f21050000000000000000000000000000000003ba59b682174ee61630df95c8e2b1c48ffc8f7f8508c21f3bbe8f7bb3266521fcc06c8f90fe5126d872707872db6d59f44b0204792359895b448bfe6ffaedc14d54a6d72be7a49718c0a933807a399d0000000000000000000000000000000004e8f16480c2f080a13b9f2b66e6480132d76c4ef76e8bac995a8e33280073ed5610865260e154b32f75f527d89620b3000000000000000000000000000000000f9ca48d732a8055d22fbebf3d2bc1e1c9c815c184f594ad2337731709317ea6a205478ba05ee9271d35a19dcad4db5b00000000000000000000000000000000078013b9290284e7ad528a1bb9a2a64b3ef43964c7226ddff8ca16ab17b4a2e8a2a7d921ba924a718587954f586a954800000000000000000000000000000000004aa76bb1122116cc0c04d65265d8652f08b411632a732a9e66d7932801b77c4ad398d582e446968f7f4966e9167894de25977e7426cd5652559626ff8b195ab7ec679de987a6a22a6a0e366759dea000000000000000000000000000000000145de5d101498bfc7c57830eea2931663ca1165ec85b77654c866b04ba6a28bfe710c1aac9876a68cc6ca119708eaf0500000000000000000000000000000000096f9df9d5723e8379f2d09c76a3fd059be47d2c2ed8905d333b2464f72153c5f50b6345980626358839ac691c26c967000000000000000000000000000000001788ffa765c19758da6eb6c38e793190c64d4a7b116576f6827fc090b0f65304988f6a95cf4397f82b7691fc43960ee8000000000000000000000000000000000746e040d7aafdb06a31ba3d7b590dd28f0678badc261a93dc7bd9a605047ec67ba86b2b6dd72637a449872674d6b5982e7ae497b44f531fe203a599622954804c06d5348dc17eb1537e750006584b21000000000000000000000000000000000d8f3cfe1cbd2629f3899313cff16ca3d8f964ec1cc0508341936a7b3b49240db1116b2c3de28f9bc45cdfacdb5fd98c000000000000000000000000000000000fa642ed31293e44211b34bb28bd5b389ae6d0510cdab46c89756f31795506fccbdacafdff21b0127e80557e5ba9afdd000000000000000000000000000000000715a8951cb358b0d8cc63377799a9a61ecc85dac795d726fe60e429d492c9ca843be2a2633c17f830f199335e5d7741000000000000000000000000000000000b88a23fdac7d35fc135b45d7565854bf010a75f072b32c57ca4d0979c111aadd84c71df6792dbdc8e975ecd46a15df2e073adfb5ab96730c53015a4ab6210a35a37b2331ff5123e00798c33e040a913000000000000000000000000000000001171be5820b5a19c045abea399f2b8ab9905d2aa367c6c8c0f84eac132d26150b759a9c029414f1c8f7e4880214446c200000000000000000000000000000000147f0877321f2709183f0b617a7c5ce898db508a3ced4148cc9f7af011fe8040e90885ce817aa956d9f5d19dd968f6220000000000000000000000000000000000acb005c11481b214a17e3cca02c2af266e4c8cd928e3c4e221d866e9f296a2e913bf34c4e051c7503a5e4e7cd7449900000000000000000000000000000000125f45d0af1c010cdf8438bff0f406007853e566fa646df40a581f65496197755eeebaf4f0f77e1e936f399dc4c6c020e6e752d40d411f1ee6e67f48109c9a059226b446601047a2189ab815a3fe13c40000000000000000000000000000000019cce3f872af5cc515ac4cd7825a5318ead5b464d50349909a70b415a8950206974ee0d4203f208d8e6d14690158f5720000000000000000000000000000000002e08e8accede11afe3e2d085f35c08d7d414c26a9caa992d5a090a43c9b0c0cc1471f3693f9d342a973da65189c888b0000000000000000000000000000000008a984ad2ca60c492cff2e95d541d71e33b269b10d3df107c0513dad5af511c51806068da6cc7226df1cf5e5a2fbe707000000000000000000000000000000000fcd3ad75bb0a5c046cf83be3d973bb3685bc717d7b8262fb8205935db6e632472496907f7c965fc6b52042ce69999f9e657fda33cf4ed1aa89dbc19d58fbe3043acb5795dfb8c0cb97620f16f8f24350000000000000000000000000000000014ccaf7594d8ff6157f9439ba63480d3d07f44e62a86caaea510d0ec456cd8c6c4b42cf9e38713213eb4942ed45df2ca0000000000000000000000000000000015c2061c532cda006addd2fd6ebbae458197d55fb336f75ca7decc05dc6d421a65495b71ed11874aaf24a0ec13a7c65000000000000000000000000000000000101f953aed7f23b5b6208032f05b818e0147079b7764aa3134dd9e4a316bbef0309ac378ca3cff3bdeab9ca56cb78e60000000000000000000000000000000000c76a2bc721a4d3ead95af79ec24be9b7624bc80d7debc07e388e52ec621082b9a69f48d157b168af4aa73629697f784c73458e18d6f832f362dec7c49140e6523ead045131a1b719b0c836c1ef13a79000000000000000000000000000000000761832bb5b530b80c668234ab5996bdc225c0c696ea07dcc61c330320404827ada9d58d658e230fcb39a96b339b830e0000000000000000000000000000000001198b85418421d96ebfbf436193b411a3a89c206d006291bd23254ed5fe12ccdad15725a34d962005c0ae60e202bb86000000000000000000000000000000000c1d7ab83b1d2ad57a407e248492773a357c06b83c16c6ce1490e84bc4a3cbae395f160181d2bcca3edc34b764754ab0000000000000000000000000000000000f1e9f0cf96d7671763739b6c37fd442f0e816c49d9c8e001d322397e9d6741dbf8769ef9eb83d08ab024294e279a02838cb0a2b191f538b30187dc730a8c665bbfce8186883500baaa6c3242a0d147400000000000000000000000000000000063049bc3282934e29f3bb3dee432bdad6193a5d2247270e88887cac565f4b986e1b3b2af5387cfca64f0d50bc0ee1640000000000000000000000000000000019f0f05fc7f8bf2f0b8ed375690b53b6dafd0a07c49fa55d36e040798334700a3aafc4995bb90de9c4dc0e077ee18b58000000000000000000000000000000000fbe702d148609dc8feb3ac11c5eac8e32a2f7221aa135cc33a585e9f4c97afa1658d8962fd96e26e0c4c1d5108229ef00000000000000000000000000000000061fe418d3b440e84728091a4996119b515118900f54a6f2da2ad5592f48ebc17bba50b59ecf435de3cb892a123ae9d18a27de64d41d13ab67c1f7b1a7390ab4dbba7d219dfeb31255f9401d5b3c62f80000000000000000000000000000000011e8ecf1e341f0146c59a79a8428bb01d2399d3f87d90d057f63e6cb9837432154d17975f70df175a016735caf85120a0000000000000000000000000000000002a5bd53e4f4c5b9682e1af1f7e09dd305e7342d1688f62885b5e59f173a9fc731cec481559ad693030004a5fbd90a9d000000000000000000000000000000000f9601f95e12bf05c35deb204558d44a60fd630c05f4060b7bd9ff943946e8eab507422afe00a3e7706b8ed013f712c20000000000000000000000000000000003bf6fecc0c7414a69c2b48e2c16e88d988ea8ae9d8b59017ecb89394732a20e4321cb5e4fb071aec7d2736220a4553780030798960729d63db70b8bc3c0030e80d9b8ae766e3330128557e6c34442f6000000000000000000000000000000000549f6464b657eac28f838c6a8bcfcb7a189d6b3b9712e19c1a23503ac209da5f2ad4df83acd505b0231f00eb88515c70000000000000000000000000000000001bf4a46dfdd70542e9d8cd6d6215174cba28f9adbff31c02482ca38205cb4afa2f7fd65ecf57b39e4ee5cee320e33800000000000000000000000000000000012d04a693d565f96566b7c313c47d272fef0ecc828493b0841d58f6bf690a77cb72824a656442e288460ecca7cf05504000000000000000000000000000000000b33eefd5df8b098e6505cbe655a483ab5c6e417a4ed55420beab95e8614c8538dca9296a7848d6aa0495a173df6d0b80d32b6969af54dd345f42320ea96def3c6f4dfd4e22a82686b7a3c57a0df5250000000000000000000000000000000000fdd9702ed88aa857254c3ba50b484bfc324e583659c57055e4b09eb1662af2f70b547a1eec139193a0d3c75b565d3b200000000000000000000000000000000193df0fbc5f24065008b5e98c4c4bf9f1e743a6ee60c3700ae4a9108639e540384eaf1f9d7a60b8b6a5d79e1f34949f50000000000000000000000000000000001022f8a254d17e448cadfad35b7a54dd2fb319c8f9ba219874bd8280a5077301ff4332d731a75646cd93bbf31331154000000000000000000000000000000000ca1eb350844ddd0a65a4ad56e1a96821de2c6633a4a45be976577c223e367853e2b1ecf2cc40b8595ba5591ae8e40f3969848f1b8b36bd28967b762168edb451322e2f0c4b99b7f9112c9a66093fb3f0000000000000000000000000000000001f9cda056a0f8803be581634562e975223b5311f4752b189cb6bd6df1ca5e3824bbd2889b9b93da59e4f08d482734240000000000000000000000000000000009f43c25de25c5d76ee1a03691aa434de6a063bb3a1133b045797a279346fc938dd2636abf0c4bbcb528c9c28d3105c40000000000000000000000000000000012afc29245da8bcd3c0d96c4ee61617cd9ecf42a47c2ee822003af26aeb4e4de8e432ffb6b2d8241090b814401a8676100000000000000000000000000000000053edfd98742dc70d510f1836fcffa6a3ba9ffd4904c7f5559b48e49dd21071401362d0b39bc0d786b7ee2e84a76af0d957ee08a513c5e22bbec04722575a9b4f3a1343db0ae5beef4e66fbbe1ac90440000000000000000000000000000000001dc3f016ea1a74ae50c21c1955ca1eb4a911026a1e72b316c7bbdc708caef63f0c1efecbecce8901d65bbfcaae429da0000000000000000000000000000000016ce9301888808323c9baf6402d7073fb85ebcd389334cc69d7947e345748ee44b2d6aab3ef818beb21b54a19ae4f5b5000000000000000000000000000000000c49817753eb6459cdb4bc737d3710b5f044bc544c8d92c8ef138ec9d83889664267e1a5691f4bc3fa235ecca2a973a500000000000000000000000000000000074a8450e35f1da18e6de05960e21b7059ece8972c36f000bba9e24488730a44ce3ce200c437e06703addb3b442a790a8e0cf0f590f77d13819001916d2c58a654d0b9d3c47c842f2d649cb2570dc0d5000000000000000000000000000000000bc1f2e9af093ae8235c93af098e692e697ea0ab4c8f53019a6e950f7072b56d5eef6b3237710f1dd1cd1970668d06d0000000000000000000000000000000000d9a63f7a13ff9755c6a3832e3c4c852919514523092367fab7886cac317e564d57fb4042ef40e696edce868e697c45700000000000000000000000000000000129a30657466460db13575dca367105c27d631eead330319b084adfac591f5b3b94988925d778e6d4645d1d2816baad00000000000000000000000000000000005ad64d6e761a9a301589547929f4952ccbfead278cbf6658255a075966340f185d5f356679fb02ff2197468ed7de19a71a8c2a479dec43d644ec4113142e666bcefd6d729d4faccbc147effa836ddab00000000000000000000000000000000077d1e5b35c224e2cdc849c02e800c0b80d1c19f3d74d9eec34c40f56bbdb9e2b5d2ef274991dca843755f91a50826fd0000000000000000000000000000000014f3b653e0df0c608b75dee3496a7af04a828e6fc5604f16ed49c39686ec757e96adb0a667853006a8331c3d63ae4ec2000000000000000000000000000000000aae011375b337940f2a53d9091d3581e8197e79251b19c7fba01de987721a9d6fa694b7978f0abf877f46ec26147c98000000000000000000000000000000000aaffbd468a2eb86a3cff59e2e9b7ab88286d2bdd19c2e789b1a68810f0cdc76171a2661ab54e81b17643ff0275eafd72d2d59a7f138327a20263d6338d2a92fa5a2f741daefe9aa81d06f20a6fe3641", - "Expected": "0000000000000000000000000000000010a2434fd3150f6b9b491d3a51226bdd457504077ef2ed5a11ceaa8284900d1b84039a34d5239a863809369bf20a704c0000000000000000000000000000000007934f34fd50a98225fe6578d3f34ae5e5ef5e104bb9cb398b2ca4f09048ec39cf52e7fdbac48d45212e9e4c1dcc6e120000000000000000000000000000000013ee70f1b52cb8b07ad957a7565b3e3c56306392cf7b5aa29047b23e5b41fb3239ac3611bcb16ba7c7ffc4213e3d9cc800000000000000000000000000000000035840f8ecf56359dc3239945720ad08702b4ea8d0fa9bea3bfb234431df4618e960a1eea87da72ba4d9443f14bb87a3", - "Name": "matter_g2_multiexp_14", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d04bb9b75bc8078ccfa85e27d32e137ff5f05f9241b19ea835bba2fffc9255a4a3028c0caf9c32d3d27666e1394fe820000000000000000000000000000000013f59c3d8aaee34230cd7715a32e4a45487b9b16ce68d178f95461229a4d0fbe7d31edc7208a7338eed08e65847f8f29000000000000000000000000000000000d63ca2bafaa54e93ea54846b26f88b4c6749953f9cd00c670914cca279b794c1fb5e2664fce44b8c04f01c68698a8b9000000000000000000000000000000000b5188b4b7ef78d3662baa01b1813b4a0b0f855e11397584a460d56f594f11ff2e5d708a23a8e64d0ab337c7076872527740a826d524fdb7969776bede5ada468a0115229152907cb2b050760c18c8e20000000000000000000000000000000019bae57568c879cd743f7def43b6b994f29782c6a0c74734f35b97042a916da00daaea34f321481e6cc4749e23297c1c000000000000000000000000000000001853fd11d4688b027146a07edea647502e80750de4e5e2d105faad3f71ccc90badcc750f76f1b02db3bc0a1a635b2bbb000000000000000000000000000000000b1e45b90e6a7032179236f13f01ab664c32ee5728414ac0d6b9d79510e8c5bd0f5b62e6c59c1a3c88998bf45636cbab000000000000000000000000000000000ed16c2f88b5b8d29d7e01633e2876322caeb740251b034e5e898919f836ae73f0296c62253a0329ee8f71fdb5cac3a1d226f56bf3935ea95d976fde5790ba0584e5bbc78b37279aed8e50389899b9e9000000000000000000000000000000001455764f99e5eb0e0371e89f88bfee1c43224b9b5202746bd151f72336285556acc5ff36bd8ff87378249e82214cc5e500000000000000000000000000000000007fcee74e5335d96714e4d1a7c6f5c211b1a460efa283e0d0578c6c1f56dbd252198eebf0625362973c40d95fd890d3000000000000000000000000000000000ede26cf87e604507230ad996788e85799cc07245cf7191a6c3cecf0bfd5747b3a277cfbe41252808df6da19f005de9a000000000000000000000000000000001855991a4dd78dfc6088e6a43a64b56c8d86a0278b899bc8a1979a40a287979dee567217b006ca71374156a96b79c176c133e1989ac82e4d1c9852a6c7156a34b05784a58231d59e3cc875ac5834d5c8000000000000000000000000000000000cd032a7dfed029af020bfa249e6adccaaf5bcd2ccf33736281c4fce9c6e2b2e87fa828cc20301269d8e0579ffb866a1000000000000000000000000000000000765c4d6c4062cfbf7e24f9772dcd812f7e707f2b0ccf9043faf10018326834934df121924abb74d736b0da47554794a000000000000000000000000000000001540fa51e4580ff73e58def90a6f19557dec3c8306e2317ba0c25ece3eb4f8c39beb57741b3c4b9b8554fd2597743ce6000000000000000000000000000000000d875c822d0ce50dd638254cd4aad5dea1443813689a940d72cfa5db9309b171299ca3d69b137dfd37f0b7538a0852750fdae1b53f6442c4378774a981c90d282d5f8793feb2334470c873491e41740f0000000000000000000000000000000011c230689175cc672c25f3c56ef4eaf2bc5766ce424f6c596b40ab24fdbfa56a955205419c149058dffa4d86a48ad35d00000000000000000000000000000000078d493ce3a8038134541ae5f2a82b5e0590218a499dfd78c7a9c06b92307003fb62d6414d6c04b22f2877c3de0b65ca0000000000000000000000000000000001d53c22a622c5d91df934783f8c0cb7e370043ecaf99a0554987e6c5120a0e5f4ede023a9ad988d30d945a2132ba5770000000000000000000000000000000015b1f36a00fee95e13443c9f6e67935a840cedc7c3fb7833ece8e180991909922f59d4f4ecbbf23f16bf5ee7f0b5851b70f1de7cc5e6a2cf7dd4b6e60ada67ca47e7b9417bb5f599048fb0c9b2abf33d0000000000000000000000000000000014adff1607236910597a951ae169a7f56d6a3b4e0f44ac63a247716bbbf61feff7865d075f79e4108cda6c0731fdcfef000000000000000000000000000000000d740b13885c268da876898b77914bf4a002beef5bd2a3edefbf366e45ebcdf593ec6d9ab21e983fcae9a0832986182d0000000000000000000000000000000002a0827e812e983898351d9f03f660317d41669b0fa378e5c7667b73df299ddc4a32a529ca887a53245d7e1f946623b3000000000000000000000000000000000bf09a2de1a8ccf24a8a65dda72adcb96535ea7235de87f05d27341738b0b4ab16afbc5b37c97e255118dea9bf180ec2ca82cffdf59b742a736ae9a6d36f7840c46c20c126ec054f47ad52a22948d7210000000000000000000000000000000015fbbf7e8c26e2f41be32daee2c81390b9bc4413aabb053e3a88bc6117377bc16011e81ed167370b72f84f0e77c2b8680000000000000000000000000000000013d48a27d06ff00048b19879493a5f8ca52b7154be2fcb468b9de9edd1395750434b0e95ae6dd941e84fd6d8918455bc0000000000000000000000000000000012fd2bc91286dd46d68d87a3f8793db997ee684dec6b2de1c4202e5e7eb0e4a8a21222e3dcf80e1ae4a3a92474107d330000000000000000000000000000000004d8b71978c9025dabb3d1b1b3c7f4f13f166514b8b356fd064842269a36c6f1c07f150c03510af7d0913103afda4a68fad69492cab4ec7eb89ed37f1e7fe898ff49ffac4ef2aeb75d9c6b544109a08f0000000000000000000000000000000007d679ac21bd4634b415ef8e0e3670a8a1d673f6a4f7f3786b92d55458af980b035e4dab165a3b773ff3469fdd9d5135000000000000000000000000000000000fdb82db6e1096e73322050f828ba41b3012496a4fc4cb481f11fee338243aae20b205ee06887e28f6ba6dad00445f9d0000000000000000000000000000000017e6894b48f60b3d9b4184d58ab9554851e285a1d445b4d97cb1a7ed5a984ade8b0f62ab11ca75fdb280cc0e526108ca000000000000000000000000000000000c03b61690cdd9a4c6c83d03749db72c8946c21a944fb292866cf3a2dd1bf3dcd95743227709740ce8124319d0a540555af71c9baaf54967683f8553f72abf789da465041ee5a92c9ce1ad562c91c4d7000000000000000000000000000000000289f850c4834153f36bfc4855f89e9437a172c35a856117f8b841e5ad4ef973d3aa33fa73d8dbba4b9b2101708006bd000000000000000000000000000000000700025f22c0460613c05f8941f8a79a4319325c37c2b8f099cd910df5c0c27121a9de0e40adc7ba0fda61ea637b47d600000000000000000000000000000000069e17e00d4d726e8eaca8235c88967a7c093c70e5a46b1863ad097acbe233554048838a0a486a72cbed7001c83a27db00000000000000000000000000000000016ce4afb84c1a9e0216f23bcd2dda0bbada6a4acca78e1e0d765a5290f6f4929f6d0eeaf1306fed3c9766ca7c7268acc7effc9a7fe773a420ca430c58bb94e7baf26b9a97b618a15e7a18b31e5914f10000000000000000000000000000000018ca46a89dadcd3b54f60fdf9a7b97c95b9e0668ed9329bbe4121e588a1ba773c9d086dc35b699d65487f428c00ad8c30000000000000000000000000000000003ada6835a93310d0ada01bd7fd6778bd07e718d1ce05aee2b4990bf32322fa94ca898a531ec6e3b8cd7ae3bdc77e0b70000000000000000000000000000000004a8abd2b9f7449213e63ecdb435e5e13fe2aaa31a2c38673a6adb5e96f4dd383dacab391787f6c17579c78a1cefa5450000000000000000000000000000000002a8768d98ccda80149a767e9b5a3b0bbbc0ab4b5f696522c8f1c664f1d27f2f0a6690531672ba2070355c0e77095dc02d5a3d0370f4a58c21016d208609f1d3e7cdf43abdb85199bfc67dd12f589b8a00000000000000000000000000000000048fb58924bd5952d3bd7b1cd57a1dae6c1034df3a420c1151737f88760e4b0e78fa3f891a0dc32fcb50f89e67b0f08300000000000000000000000000000000073e9723c80eae7685db774d3e2bced53a52f24504fc3aff98e2becf8d59c6e83373ed024ec1ca50101d2d613abd286e0000000000000000000000000000000003b64c8e9a1341bc6a444a871843b3add7dbf04bd1810e1d6da7d31c7c2b7a264c362ac9a366dc8d93bcd9392c6056f000000000000000000000000000000000064462d424e54f50e9849a2bba1b0caae966a8618fda0f8965b1a841dd2173872a44a18ace1e2aecc8e3546a9558d7013549b86ed3fb880269be22b9cb8be6f24385bb5e24bba81bce9fd5b72ce2ab71000000000000000000000000000000000c40c8da9281a8b43478c28b2fe59a3cbad0a818e2077d40cfe44624dc2e46f72d4489cccf63eb8460d02f895e78edf5000000000000000000000000000000000735d768f6ac999a47c88bc2f3375f01052259dc69011480e468d8963ea8eda74726c4ef32c8feba52878eaf5c0147730000000000000000000000000000000010adb3ad214b17b963586a10701934727edf05fcbdc94d98255632647d73536decd0c91363840e1b55f29f7d32f650410000000000000000000000000000000019349045e6fd25960c03336888679cb53409027f35a1f211b40d24ebf724866c085a978ffa3a91d989da1a7902bca018c8f6dd56906fa13144dc87c31b53186b0683cad220ab2de89d2fb515bb269cbc000000000000000000000000000000000a5d2dcc05e218b0633e0a965b6d69a3c6c1c7837e1fff7ff75cc9ee93a112f8e34cbc95bd9dd8fe6ed22f2e9221aa110000000000000000000000000000000017d2e5d2c0578b1ec26b57c3305b209c979bba6925756892f031a7462ec44e8a4a2527e6aa2fc13bae91dcacb8c7a30f000000000000000000000000000000000d437edb45ace50700db548db68b9e8376b3039fa00cb98dd00cd197c14d0f92c8a3945127c43b10b34bef7894fa43410000000000000000000000000000000010d5a2e442a2eb35aa85fdaecf094c1e1f307dc9bcc540693d7206cc4e0d050ab900f17fbdd0754b59bd2aae705c60149ec934eddc44729d05f193ac927fbcb022288ffb2bc7d4f46d1bfcc7efacef940000000000000000000000000000000016c36464b426c3066aead1aaaf65ca637e93279e8ccc9d838b9b3ff1aa7b896f36de506efc2b0864763cb6ecca4926f30000000000000000000000000000000006d88d5764fc854ed7d7cf1c0e210496ce347bd887da2a149a09679469e98c453d85115afdd2fc4987b64a88c4a6f0a200000000000000000000000000000000053edcc0ca4c205423ee6a7031939379e552bd2d2657f8f25370c9f0ea0a947e77f18b5f218f98d12d720667844f3795000000000000000000000000000000001292909190854cee4499faa602af99dc49d1354a71278b439e983bd89e6c504fa5fcaaafb6ea26dbeba9850bcdfc1f69bd211ec887635ca841c4608fd00bdc0f5fd0f6365dcdfd7d6f4c36f4b25b5b1b000000000000000000000000000000000997e79a7549ada9ee0233b3bf9289df3ff797595f4b5eb2e7dda6977ca981c1c4a2b91b924812b95418f1b1d9d0cb830000000000000000000000000000000000256b830e80f238e8494387429d727a91cf5d323ea87f7dc143058c05e11858796adcdc677429d1db4dc2415cf23808000000000000000000000000000000000cab529c6b86beacc57c874f07108d1df7d98fbd59fce44c48afe9eb2dff823f4869b620bbafc121b4ead2cf244974de0000000000000000000000000000000002774906c1a0acd87de224a9450617db37f8f36a0a192f5daa2774eff0b73aa79b4804342999df761f8572974c697c6010bce61d4e35770e7737636c0f9a664eefa948662d3d22d1f1708fa48d3043de0000000000000000000000000000000012abd02540073017011e186586023adfca36fae454350b2015a796b7991eece65b63964fcdf581b4b51dbd7ddd506ec3000000000000000000000000000000000ccd3f2d9280908d4b30e924e4a862810a92e1a880cb56e842a94a2a5120956e8713f548ca279d66d06ab23e4976e54e0000000000000000000000000000000000c052ed00fde2cab515694d8c004de910e62d07c462345ffcfbd3904a0171b970bc58d99c5833059315283004f3390e00000000000000000000000000000000008fc4860366074ec0c7aed2c6ffae7c93ae0a81067edd8911b4c53393ebc0f23243823aa7aa2b2e987cb510f6e0a55a65c86930c1d142985bf85ce70bbad170947e850e5c6ac7803fc45980dd37a57d", - "Expected": "0000000000000000000000000000000006ced307065868b6d082bd205bfbaea3b0a8cfdccf831bf154563b5a942154622b0d7689819b337479480d19aedd85e4000000000000000000000000000000000c0f04fbb26cf85c2c22763f3e78fe255d8d1f45ea47232ab58f5b785ad9f2458b0b28f3cdc25c4dfcb47d59957ae10700000000000000000000000000000000120e38740eebbc3eeea9beea483e70d6a9c30a5abd61b86e5f94bf65ffb40fb92c8d246edbeca425ace175f79c9c8afd000000000000000000000000000000000d5a503a26e50f9be34c2e64e4a80402ca6e17f09db1b334a9c1f6318f3e7e63b3847a7ca38ae6aa7c96ff94bf5de842", - "Name": "matter_g2_multiexp_15", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000036480931a5a585ea54b6dbb01759eb1d86804e3f03326188c71f859613722e662c453096431171a49eecf8653f14d470000000000000000000000000000000015fcd6a30b9d59a90d8595ca1758eed7d6810d2916638dc2cb637aa09b16b5ba4920df7d21fc0b923453a6c7d32f056b0000000000000000000000000000000019aa4d8e98808c2fc1273d383e836876b087ad5a7d01743bded01314bc62ced94052d75d312a18839c1b33faa9e2e5160000000000000000000000000000000015747ce0f1171c0d0ff1fee9dbb2e5673b9db0b0c3618cc8bda474f378db58ea42184f907593f3d6fc2fa215cabb7b2308e559e394a9c1ff07a45bb3e022f9c212eea4ee5b77db1c5b93ce72c0512b79000000000000000000000000000000000222640c1d64948daac3ff93e86ecc96bcf9c93559266529a37ef1372a81952431673d69f1220e07b8aa0a4f3164c83b000000000000000000000000000000000db593156078821cd0ce0270e8a444d0d204dce0583774496620bd4752839f3451e505aeb3db568048739c7e71d279b40000000000000000000000000000000019932ad2c7e857c2dd51f7846534050b9243e388260cd47a91444fa050a9154eca88ab4d29a37def16d4a11d35683f2f0000000000000000000000000000000004d15ec653a72256ac6b616e9870b0acc7d46286893c0eec523dc27bbcf5fe596204cbf83ce71c2690af67b3616794225e55826db8d12169a31ca27beec80554954f522b56f7994c62bdb527c2438d5d00000000000000000000000000000000180622bfa9a1c452f343ed21a3e9c6fdf76589cebfb9a3f0a53782a3e7c9d066294e10699c386b5d0525003289f0ec580000000000000000000000000000000006615ff63c856302dba6d4e25d1070fe873e0c4950ee5ba8bbbd4b94ceeb181f1ee450acfd22f21010b88f0b88375777000000000000000000000000000000000cfd3940b5eeefa92d775792affa34371d13f3098ede3007e06510344ac8483debadd5a2baebafb5ddcb45a9449768b200000000000000000000000000000000145be0107a1e3acecc89a116668f9887579ed7a72abed3f4236930edd3f18974465c99ada86c4980c88768824216170f1362e8e39ec661cb3c5af64e0001cc94701194344a7404f1ecf7df0d5633eff9000000000000000000000000000000000820e74e6d0333b6b36590ebae78960d019065f1681ce68a2a01a2522496c840c668575a57f9fd0f50b87f928a41b0de000000000000000000000000000000000dee60d90e96019cf2bb552d016419e92dd358ff97039a61838b0a89ccbbd537f2b435cd11f7b6e75a4ec6675964e7fd0000000000000000000000000000000002ca767de9fbf8af7c73d41a07e1c0e38e3fc971472e11928b65393a27354b2d732012dc57f498f94c0b933565a7493200000000000000000000000000000000134fe97b24e153f0e9a27d3fe7b89999c6a19e353325e0746ead013198b8e00ca6472fcbd2a112aecb9ddf671aaedd9174d3d66cde7c4c8a4499708a0c6f7c4da458eb970b6ca87e23601c702365b6de00000000000000000000000000000000031a9c29323196ef31030ba73827d228e56fd5209eeef0803a189e0c0e5b186ca1f342483eeac99e1e1b12cf490856460000000000000000000000000000000010deea45a01370602bf57a1f81413e8d3b337d7a1a33f9525e4ff7003454d1da2cfb1a9b42c4a654320f91fe7d04b6200000000000000000000000000000000002bafb7b7452a173a3971c2ba1768061a043307d2c32767056f18c1bf8b066176937876a87055e54675876bc1b2d2fc3000000000000000000000000000000000b5c77dba3b4136a7efaa8c2e28f39e88afbf26a7313b52ad6e390da4d948209d96e39aa08eb52200dfb890d7e88b46a389e0d43f2006449fe2de506dcdba4cd0e6077e2228f7d8b6ec9d8a4129c494f0000000000000000000000000000000018bd1ea5ee8e39c43d442e9c6fd22706e582cd80051f18334c4db2ea91ab019f54bc0074c8f0e52e50367197a797e7520000000000000000000000000000000005c0bcd1b047fdbdff25b138248bf4da4c013beff7dd3030c348d6b2b8724a147cbc44d570db5c4b273c94d0b99bc2290000000000000000000000000000000018e033935c20be5940863f7e9e39fcbdc29ba031e58c10beea90cc48e9da9988fdbf108bcbd87948058f386928f81fa800000000000000000000000000000000107d179204db7b288315e8aed7b92ebfe53b7ad2366d5d7944b3df68d9d9faad023e477213f85214047645bc05fd4cde5f8dc332cb31e43bc2e551356cb8d1533c6e567d34622667e7e4e3ddef352f03000000000000000000000000000000000a7b364fbd3bac7e2f2e7ee501db2d248bd73a76c2a12a3e51718b56ca9a8ded14b83b8cf0b5bd46f0c26896a65fdb15000000000000000000000000000000000eafea7128fe20ddf740a6396bf18ff5f2652a0317ea9b6e934927c3ee95b59c7dcd51f7c895b3989d40ae5f78ca508f000000000000000000000000000000000bdce57be904236a8df532c2c0072165b5cbd4103e9061fcfc0a45a67e4b25d11b9f816f63fc0eac4d6d3e10d2764c4a0000000000000000000000000000000012419f94ddbd8275054f8f89fdc27a74afca2eef314393236fca65705354e5cc0a470818999c96b5087997813823e9be0dc7052044251fd360538fa6d5dec9fcee53faf2f07de5d8df212d04f968a0b60000000000000000000000000000000011e4010d0cd7855a92cd5d4954ad735363c0c2ab00053db5e078f34e772969d8c492892329cb95ea8893b4b7ff7aaa5e0000000000000000000000000000000013badc54d90a19b84d76b30fef8e3ad2cb268204fdaa50ae951b63e48aec9cc6d585751dd48e4a8d4659b835f38f8da8000000000000000000000000000000000460728f686b9b15cc19ef135af71312e174860284c3f0e7a84cf85a5c934e2bb6cadee8e482d88afe788a796605f79d0000000000000000000000000000000019a50c06ba307d83452a30fbd862270652cf5c7a09b150fcea858a8102ce3b1e9ec13b6abfb323d63d2c4edf209c7cafc579dd4f361fed9084d9c66a3ec4c6af5293710ba5299df3abc4cbaf5802b5360000000000000000000000000000000009faa74f66ec0384f0458893c0026f73688c764e8df9ce056a88a2ed0b84ed8f88d1b683443a3269a3db838f8aeb808a000000000000000000000000000000000949c4be2708c1aac86aff39290ab6a8e0f332e7a098bbd64227a175473d9dfe136e07548b282f69a94a15e2c32dada10000000000000000000000000000000014f2c7c7da781e2f50803e3a948381c3c439b127949f79824df1e5722c206efccd6c0ec5dd75ef63d8b1fa301c83356900000000000000000000000000000000176753460d241f38aff41bafdad51688ab0dc9a5fb3643977c7b9d282ad4532fcca1e725715227780ec28bf1c32bbc1d69f0f3c3f516ae34fbecf45f4636c22acffbee765952b332c0f3d8cadb9c93f10000000000000000000000000000000011982264c8c078518cd0adb05034761224e9063654904e06fb5e5a6eeb1f45e4ff3da661f1232693b79336215dcc0cc40000000000000000000000000000000010c96c872160d2de03a16e85f2828d0cf2dd16a3389effacce46b5b5eecfea1042a77de653da5a1c0380a84c435723fd000000000000000000000000000000000a4ad2d9956bd407c555b26c192c6bf59bf89e40d9c6f9c90780bba313a39db71a73e7633397d47a3f58f61c81edee77000000000000000000000000000000000a7f912530d27a7bf74e01d8e48890cc66f72d14950554991ed1edfc504062ff6bd3cb6941bb398df9fde3cefd33fc0676618f1954730111e572937cf0c9f7b3298a11d18cd890cb419f732c766bc6210000000000000000000000000000000015bc12aa9ecf417fa5bace8d9e5dc4a418555eeddde1da8b624bf7d6e1873ec4a257d5f6dfc058a8d9b02528e699abb70000000000000000000000000000000015b41567f8c780f83342449f27094bc20a839602ae482de14b92e40017e7acac8857db48a2d27f1f1a625883b6e5255e000000000000000000000000000000000cbe79ac0718555fd8fdc38b68eec8be83b32499d2654be44888e45a2d610b0e81ae12fd56550524ad85b5a632db32ce00000000000000000000000000000000069f46b5baf4357d8010869685b3828c0dbf6e2338598c9b42dfecf0b22d803f95fca716115f74c77778d414cbcbd881fbb9f2400ed1dec7ea63d2b26bb3e9c2acf70117e3026626f6f88a07876177880000000000000000000000000000000017ada4038189c544902167be958e43ee133730e5cd329e572dae2d853b694f5ff8032bd9ab41cddd11c51e8284970f810000000000000000000000000000000013eef75e6d28deec945ddff33128c199fa52565288d63677c824b8d56a6c29eb98d34c5834e84865be35d40c1c59a40c000000000000000000000000000000000e2fb4f9c7ba6bdac1d4ff5055be609abef7fecd7923a753a704da537c0ff41951552420bd78d14cf972dc84fa3f5dd9000000000000000000000000000000000805376b814b8a59435310d49a43081dd7ea36dc7dcb40d38068ae9085b3ea9a3b2249234234cacc76724d8ef84a2eaca0170d7b7604b8951a95d49b6697e2d0cd2a41c3671d8f96e936cca911dd516d0000000000000000000000000000000002288860f2d671c84c5239313b7f6b82e31c3976e6d310e15d3bfe1c566e2ab5d86ae6ed0df02530f9f7893ba419f1870000000000000000000000000000000017365bc096e260f8dd7b189fabe10eb66923783b41fff70a149251576b3b465c13230dd0af13cde562751dacd8298335000000000000000000000000000000000fa8eb9c818df27181b45a74b333ab481dc7212e417c4e12634816f9e177064f9e1101deff26156d26bc6574db9617080000000000000000000000000000000009379598bf02222e1ec37a721b9ea31a3adc33524c6a41bc58da06caa3da3bd730659f0a80f793a0fcb9c07b43ca929c2c2afc06f19e627e9ec0edf1083823d30ac569346040965e1c92e0c15011c90b00000000000000000000000000000000136870e08ff5fabf36410629ce5c23470eafbe73a7dceb633df5c1492e39445b86ce15c22bf4c421cfd0adc6518e78c30000000000000000000000000000000010aefa3cdf1225da09b796430d096807a83eb2fd5a58db3a4bfc5e500dcfcd472fea3077f0c059620f4ff708f37c95a90000000000000000000000000000000019ee2c62ff860338af623c535979ed31c42c0d0b2f82cd56c153e80e6d92bec9ce39bc8e8f285d1efd1c1e969521dbb50000000000000000000000000000000008ed69eb0a16c8a35d507bc3a50bfc97e18143fef611263715aacf5400cb1aa285b6d2ebf2ec219d2fec477360875a03141d0ff346e46a20c2498a74f910e9bb2d5d8530afc7ba47c3525861c9e8c5920000000000000000000000000000000014abc4eec64f2611197d0c1322c3248eadb725049379e64682f2b3d7f83f7bcea11358d88f52711b3020924b6ddd84790000000000000000000000000000000009fd78c5d1d2043d83be30a88f046f5b633c6dbb11bab25fa3037bd250b6b9d9394327aae25d1939f777fea9f3df46960000000000000000000000000000000010f413640aaa16a95afba98660f9e1b03a8f3e0a7a3d7f2b971f71b5e3d09016ac2b410f97d20471f48621d5a363e9e6000000000000000000000000000000000154b5df93298a5a14a6157819e38db33ae7f2d11dfd13f7f2a92b2fd9b053fbd25f10a8c45db3026f6f583bd56eee0f1d688a1aca2a837e0a353039294a9988a7111ac134a6a8a68e4f881e7486025c000000000000000000000000000000000f1893df99adeff5e4042c4c5e8557e53f7c34efcb2a7953d5347f81d2f4a75ca0273a3845f54e795ac1c1f8ae7240dc0000000000000000000000000000000004856b05d58898be6aba07fcffe487dd895144c7ac8fa8bb1a37c61e73bcd062ff541d510e24c5bf005c8351d3ddf61c00000000000000000000000000000000178b22c2c698dbc4929b119474a741ef44d6275fff5ba058d9debe9475e71398e464aa14a6712c5deeb5010d1c7758ba0000000000000000000000000000000005ad09389c35c45f349e6dcaf1cdb3b63648b3df427ea0c2a371f45634635f9253957ba6987df4aca6cba4cd472308a31b59c33ff02791031e7a9424c781ff17a209d132af06f5b825df363fbd902cd4", - "Expected": "000000000000000000000000000000001090d83d501373cf07c75effb1c85852019b39eb0d77226823aa3c1054d4e408e82fbf0f4420a30144c611fbb856748c00000000000000000000000000000000120a1e3795f6d5c4ed5b886256c611bdd209677f8324b7091cdd7cab11788b1c0f780e8b4c38b84d7c2ea528123d4783000000000000000000000000000000000d250df34d906ed421eec2a78c2ff4ed4eedb717358d7ca879d58ff5b4d2d72521082dba6ac5d10859125e32c2c8b490000000000000000000000000000000000476adaed9d80cb1545be505496222dba1f0ea85d38d5bece0663461e0e9d47abbefe95303c926db008d08b8aa162e27", - "Name": "matter_g2_multiexp_16", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e1a9066289392b0b0b8f0986366c2975463c9cbe7a74f2eafcb3b8b6d4ee3226ea5886aaae374341bc76b53b165e22a000000000000000000000000000000001557cd01b61b5f2361f6b558a87c67f2778e11c21734b7ed25f72a88cc62cbed396d583de4c2190ae6bbfd096c33bf73000000000000000000000000000000000eab68305118d7e7076043719ac1e13ecda4497df2cf392d6aae4b7753f114d30aae3e8535742947636901feac4b620a0000000000000000000000000000000002cfe5014446556b82d60adf874cef25e58eabd035deb4717c93bf0361f37a4a67aab70b95627326bd97f111efeed57f58fef5bc887b7caf72f2a533fe1455ae523841bd49b4adf16cfe87edc6f573eb000000000000000000000000000000000c8fa30f6055357f6b697f2115203428b8005ad03286d2b3c805bf3d4dbb461c30e6ee8b0973ef41f884b91e857c53500000000000000000000000000000000005e1c785feb4c4fb7e960233d431d51a4fe471f10321251d018a950374d2a686d52ee8cdd855a29e770bdc1bc565f471000000000000000000000000000000001158d31faab483832d39f5431a5d8aeb952d6a63b82ec019f235b5b2e5580df8cd91b46cd53d4a90b9db354b38c5a1710000000000000000000000000000000004a389b09be6fb7ffd14d7f3359b17991e93d92a1c0b9a89faceaf71f5ce77a1875aaeb7a0ec3b2dfb363c47dfc9875273b243b83d44158a66eb6d31e7c4ae1f4b3ddbba81b2cf9a654ca7c4ea2147ad0000000000000000000000000000000010587118c5f90b545ee707466ea2c5f378e6795c260235cdf9876aed8bd753aac592ee05e23882ee77f4a13bff97f5940000000000000000000000000000000000a0344aed244b90c4fb9ac337edb01429e09f951062b06025a5212300f5471a95f28e09bbc715417a6d98423b518c3a00000000000000000000000000000000128457cf374e5b8864b8241f476da093f48553d609a5f30c0f0f235ecf7127231237b6c8802f2904a8304c7c237842620000000000000000000000000000000004d55ff04eb09b33ebfe90f2a0966a1b59cc224215c0359a4ff0c09e60f9fe7ad8342868184d8cfcaa1d8c28328864241ea87af09f6e62111c48993c408efd3db9ebe218ac68f61a461ad9ec1306873d0000000000000000000000000000000019e6992c3da47715bf379a668a15668508e7ad27bac647490be8e82759b9b79c996735aa1bfdc3cef217750e4ed36fce000000000000000000000000000000000828f782c5bd4f2de3570a4930db2c020f75f93adc98aa0e48449d29c7a3b0d5c349963d956bab7f985ba6ffe59c90ec00000000000000000000000000000000062c7a730d286e895c57b75907713ebf1d20650b5e621f270f1d22a2ca480d022346def4102a62eebe867210e4b6122e000000000000000000000000000000000d6c29462ad449ee6cd122e3dc00d56dd5caf17a2510e5305aecfe85626cf73adb401ec2192eb693158650893fa67412a691b9635e38a46e2469811405ef6325ae7ef88a67c1d1c5b05806da329f27e000000000000000000000000000000000098de9ab41c289a05ba5a774eafe27d91aa8272fe9f81fadefba9a0cc0e31de20f808ff454a8647c44f5aa632742af9e000000000000000000000000000000000c96019bd5cdd62df1642656f0832ac8ff6aab86f671e18c1c7023dc16b8ff54a8e3e446b19682a23b73ccb90da2fdf0000000000000000000000000000000000178e3b4366b2517d4c19fb40551be6979d46319d7040682241b046f10ab88d269dfc097ae02952d46e69cb1cf159da50000000000000000000000000000000008341bfe1e2fb999f0c3f4e79523c720edd332401f9dfdb8dddba8d1342c2c1fb20ae2fd9dda92c7bde5a0c95ad971f80d9a35f474325d0f065442805cab3beae4a186b252ebae54a567dec6695588f1000000000000000000000000000000001004d60af8c21f7c62fcba1c5c41b94fc77f64b89abcd23a218f0da8f47d2ae6879ddcde52f3e6feeae2dc7b2720577d000000000000000000000000000000000b8e8a7da87aa62ca852e2984b0f12b85052fdd03883f01f4496df0835d1cafa48818b5ff1e3cb0e9ecd66054540a0d40000000000000000000000000000000009c16854580ad8191e3e80a0afa8da759a8b2bfa7e0d556418b5c96d97e88a12fb75a91cd68c2f4336c3ed7ac99199fe00000000000000000000000000000000195ce9c562c460c7e715908991ea8b017b81561b45133427f63cdfbe8f65202bdc8e8958ab0977b3a244cfa32fb35f37c20e998acda67d406a238f16bc2b3066a6d69d2436577b8900a180e6a71b0a01000000000000000000000000000000000107292f77666064b7d80d73ea8f3b623170ef79ccc7c228b8366675a422a0cb8491586a2e4ab1a067c31396cd670a8900000000000000000000000000000000126f8136dd61d61b2a9c0f4af3ed44a3cec3ccdedc74821f341d200601a7bf0a17079c824de6cfe28467e843d0c74d2a000000000000000000000000000000000bcec8afcc7ee56b36d6d08b51f61454c8fb15ec5baee1117ed55af8fc85f68674250334f79b0fce632e75623dd173210000000000000000000000000000000016624d64660b63b70ed197f6a675911b02b0bc6f880348faa6ce4727af74127c509ce8535d8dc8db5ae2d71aa497e0756fb773cde356e2edac3afd2bf703b59161162dc1e915873ecf606dfc0e6efec5000000000000000000000000000000000f57747c20e1b3923c7e1d8bd7d877736cccc0e0829837a086d62d48cb54f323d90b57ca3339fe4b256df529bff11363000000000000000000000000000000001940327a1b319dc4212e7a553d3f49904660722c89636f6a38604d96771fa0fc71f57674b7aa710db4275822c2b89903000000000000000000000000000000001956b81bcf961d16e50c053ca07ae67cb8597138f34a9dad4d82e0e8d23a7e08b751682d588f229311bc63f9598ef448000000000000000000000000000000000208981064443e8c72987945e399b45b74e529a0bb75e99b7d6744728e5c182a6b0a10e449147bcb0b0cbe70edcdd845bffc1a58dd06752a2a77abab835d089599b4781ae51ab998ff3c5b68329068bf0000000000000000000000000000000018c35ca3a63053fec853e8fda5920b560f1be28431f2f4b08789c7a202336c8905a5ffffbf69ae4427f267b1e13288d60000000000000000000000000000000019de96be76bd93886cc486c2671b5b0d731b568638b1b830a52dd4c481b9a1fbe2b3cef14b46e25f1188ddb3c158da6e000000000000000000000000000000001813ab16a11c79eb3d3d47ae7d9a7c05401ee91eb1183266d23077ec4c0c8f3ac7188eece06876025dc3fe271d65d4ba0000000000000000000000000000000004d2a416dc874e956fd6d29a3fb96195019f4136561b4c127541ac171b5a6b229746af6d6e535a8017e64ce06709e52e57f35cfd74f62fa39f919400f4d692855a4b4e9f91920e4306ebb2e772a484f4000000000000000000000000000000000623b7a8a1c24dcc603f01589e6679c74c4ed3452894e536a4cea69e99047092acc877dd0bb395b0cb693cb1702a64a00000000000000000000000000000000013de9dc75e42f12e905d729a52f25bb1a4125f5edb435734649281bdfd41083716d0797b0a80d842c2503d09cc61162a0000000000000000000000000000000006453c06f56dbaabd4530160bcd5312b8a148dbe19fdf9f1e44b7b047a73ee9ef9d981116d00269942ef73537885eb7a00000000000000000000000000000000075376135ff3acaecc0eeea32f8dc15add57e8f0297d053ffaa0fb0a8fc4418c5b142f96b6b9ce9eee2f949c960aed682d1f3709700634653374fba5a94d69163ef616a72a63d462afd9f01c9ddba84000000000000000000000000000000000120d088fc12210c1f5f6cc3d1091563f9a37d4d0e0d2c305b479f4d7e893c4d5c8170eb164e34e4843a21c9eb193d11d00000000000000000000000000000000159de80db3b1f0ffc5fa8c93e1bd54cf8ae19cbc9018a5dfed86179cdbc976c1c312212080ab221806bbe142d496e7a7000000000000000000000000000000001103abb75a78220218cde4bc4c59ddb5fb647ff808754dda200bdf586ee9c47a09e03762bb726b085928ddcc998af3ee000000000000000000000000000000000bff4bea17eae0f2ff3e7f99bfa91e6ae8aea28f6f3fb6080eb644861defdefc26befbb7874f612edac0cecf70dfb275614ed9a08dfd406df00719d5eeacfb0a96413b608974fd0aa1d4c6176b968dc00000000000000000000000000000000012dde607a2d4452c6c060054c8adb6307743edea3ccb6ac34c275717f177f0e454d9e33d4391208198cae39d7eb6f6c00000000000000000000000000000000014cb4d8bc98060ee68a8ddbc44b83db5cb6d09f09b0d608357629251c35e44383e97058d0d68fe2df3bc47424a5dda03000000000000000000000000000000000c14fbb6c844fbf896fbd3cb3464a83aa4c6e9a7f0450ad96a07527df6f1eeeaf587f60a990bd6abe7aeaf5eb46f362d0000000000000000000000000000000001d9468774318ea711b79f16303ce86288cee312af296f1c9f607ef5f97c7d1cb48a7218775c8aef00c227ccb586286e7c1dd2e5e5f630fb1d07e8934dd3ab029917e7775e401c0bcf7e1fd83aef728400000000000000000000000000000000181e7f8d0ec7a4a7858bc96b61484c24dbb9dfeb3746fd3a231a8e442369e3e83516ee6043b1c06e7e2043dc86f6c75e00000000000000000000000000000000184c1d667c0ece59f18fd2eeafc66f1ed530b7d5f4560a6c886429caa13255c63dea01c3e357e3408af58a39420a8b28000000000000000000000000000000000a8475ea694cf607246a1c50064cf90cbe50ad5cf8006934a1fdf1621ba38d20e70860a2b5aecc05acc60943224cadb60000000000000000000000000000000008afa03c2df8e83fb64523c57d0daa7cfbb7af6a4bf2960ebc64515a61a659b2c37ee661050cd538fa00cb34746a371b64e9d16cb61f2bcdef30cf544d97e078fccb999b96a1da0eeaa0bf232f01995f0000000000000000000000000000000008b33a297c8f86f1e9d7166f9e905283c8e1581e582b879caf48585d0bca3608fe46d8d9f6e7c90855aee9d92283d7a40000000000000000000000000000000016962410d6b4b6f91437617e84bfaaba49de0369b8748d2e2dacb63b421e0d7de4514e7fd3e0dcbcfba8baa4915610d0000000000000000000000000000000000efdab72953b870d0e113efa7c183d99aefc100ce59791aabc72423aff70a5b74c577c06ca94bfd6a7722199b4bc22660000000000000000000000000000000013b18e31700987dfa4344384f9b41e72afe92c39bc961333cad3e7d0a5efd3842a5e849cff5655c4673f720fd0127dca35bca9082d66c06761f702dd439faa4957caa70ce0343268787f41a2f4bc0cbf0000000000000000000000000000000008b86f70c8d8b03b0e9a8975776d7fb0d08f95eded0a0124551d363c2df57124e0e89bd45ddd1cc75c258a4ae2f87916000000000000000000000000000000001120eef9eaff7c308b629deafb060d2c12b20b57562007fa810a2191d99fabe9c7d3c364caec1724665ef556de66b57e0000000000000000000000000000000007698bbef6dcea67a2c643342ab2a0f830c329fb6244d4a98512daa8a3c9d808cd2acc0cebbe3da920053ad73eb7cdc7000000000000000000000000000000001155b6beb28fd88d252c6b407bb9f55d22103257287ce77353bea580c90173b5c3d49080b319ea28817d67c52bead96f7980eac6c8db86ef83748d10b210835e53baf8cc9f607915df272b6e28ac6b2800000000000000000000000000000000142b28509d72f9e3be9ee916827fc1a8dfc4ef7ae2b72eebad5db605fdb2dfa4492b50cc3e472df1b52baa6e2b0eff5500000000000000000000000000000000134d6821088ce4a8b42383d5a43a32bb0cdc96c85f304a2601292670633d5e231b9dc479d199829a9ba9f39c162318d5000000000000000000000000000000000636da344fcb0fe50ff3e22f8591418f64cfc722b2860b4a5047f973f42e4cefb93c2f8eb8a14b4d150758ecbf3cf712000000000000000000000000000000000e6fd06d5dca702cc9f199f7583add86c82f7b530d4dfb9faec36dbb669cf7c1cd1260c7e4f3026824eeb5b979e9fdaea256ebae4b204b3888d7bd244bbff26431ab5890098870f13800bb3be3e842ca", - "Expected": "000000000000000000000000000000001684f447f8929ec0187811f66e985f0014eba46eaa87de2d4ac2347d10c0550e4044ec7792d9f315c50081dc2097ebdb000000000000000000000000000000000ee0c46efe930bc98f39dee8cc6a792744e84de4fadec035d25ee8ba82e1c53264d0885a1fb05b2b8dc9c6a1846c28320000000000000000000000000000000003a5ef98843099235a2ad9522c9cfce1908bef77b45794e7df9eb38a4854460031829e947a118e8160365fbec3725b85000000000000000000000000000000000dd205e195abef6a4cfa7da66f022a418235e1a1b2fefa6bd3ddf8a3851d8ca8c27652bf87ac644cd189ae55e3cc7808", - "Name": "matter_g2_multiexp_17", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000064698182f90c20ed6f6da7248cea32a291f901876a900d344ce4dc1b07822b480519cb8d891b5ee4f33b4efd90742cb000000000000000000000000000000000e7e9d2e79ec4b07015baf69a283f6a4abc8d7c1699f3356fdad6ea9b1c70e41e73bc14e500634d73749f9900eeb65f5000000000000000000000000000000000002ddbf40619ea5123c100e2d6553213e37883fb34f0f0f2124795dd971892d5c9051cd4aa78b9d20f196301ca9bb4d0000000000000000000000000000000017a07b32fbffdbf7a80f0437eac1ec5fff5a68f3b053482f034064992158b604bc34489dfd41a24ffba806ccb871fff15805f2e8013007c4f6d8abf441728eda8d742ea2f1df545f85d092f50ca8275c0000000000000000000000000000000018b4de9c04fde8b708408efb3aa7f24b5f7bcec14e7d06fd5a5b36bab528e5adc0bbb1e378a5ff6fcbc95aea530ffc6a0000000000000000000000000000000010da98267770a47e5ed14ffb3dbcf537dd14ae5eb79522c772a7a2833be214690db0b4e86621de1842d88018fc0f348400000000000000000000000000000000135548e2eec9ae7c3d23618d8286db13a5a628fee04fb6ec9da980f3a46838899cf965c1cc6f562e71d5b5c7428cabc8000000000000000000000000000000001669fcee7804df9b7bef32e2ffeaf285e8501842efe87c9e827fce872dffbf92255d3c3a2fb5c382ab7aec0bba1ae0e5502d777b25f3112ba2264022e2f28dfb6e5d5239ba097e9d815928be44b6a62a0000000000000000000000000000000010ed20c069bb300a27571adabd239e70b767af90b91c4d0e93d88278a6da47b7c12fcfaf62ac0a7b9966968cc9f3770b0000000000000000000000000000000017273eddc25cf41f2d7734a3866711e83d4f2823ee6a036942799f837d5ceff10dd6022ea25e3c1e28c7b14ed8f4e7c5000000000000000000000000000000000f201f314f66f6b2c6e1365c0fac7b187d31bc45b5edaef5243b5488e26581dee24de4a5fe493bee44165cc31d8d72ef0000000000000000000000000000000009dfbdd86633edfacad6b78d292141a1e653a1bfd8c48a96b2f6bf8271ed6033c0511628caf2ef258eb64cc8b63d8e5be7d64b471cca34ab0c91f61ff26719c7186dfcdef13895d37ead407873736a740000000000000000000000000000000005c4a4a5ffcb4a39c8809821ff275360ff937070cb97a791cc9ec45f429256a6d2d6127248b6ab0b6c71c30c4fe84ff20000000000000000000000000000000019fa60f481c5be953c9c7dc86903a89af0ca2b4205be3a00d793d6de7103852e147ebc7d983c6d6e8cd99e681241ad440000000000000000000000000000000015b3b2eeb0f81ff8a2624e2ff2396bc69feffeef62b1b6a1e73ca4b9e60506c2950fdd23a37cf56387b8794449d3237f0000000000000000000000000000000017021a69ceba3446dad9fcfd8cbe5b89b61372f57d43a8d2e2c8f4534bef6b91408409dfda9438f24526f7e6bf1f4240e5723630020fdb48e44adda735943c91ad7d1e12f3c32d823833eacfcc8b02ba0000000000000000000000000000000007c8f07f22a3412fb4638cb704751959cda4e42e4612edaf5b1f22c8f9ea314508353445114bab6c07ccbb4b0d0bfa6b00000000000000000000000000000000062d087155c8722d0102c8e5084f95f5f58ed626d48197297d21d2108ee05f70f16d595ef73e8e1207a3c0b013fe16710000000000000000000000000000000003b6652934f3acd4c91c6c521c2476bcd2594a939ff2e7ebcbb0f451fcf0a656a518dbd4f36f165f9b2f58054e9f778f000000000000000000000000000000000bbf21158227e0ad5461de9ad8bd580f9e65327dd4e23f1ad55618f6b0aec45aa6076fa88557953ad15d385a074bc7d96e9e37bd811b76133c12268d325ebbd6656e7ed718cd777458867dc98b1b3bc50000000000000000000000000000000019e336d4d342f110eeeba9773b8e351f26bb56361c77fbf12fd9fc218fd075ae38b95f4a8a5ef830fc2cd92558b1711e000000000000000000000000000000000a112725046ca3b6cc43207e6b36f38d96ff98dfe3444d67ee3f4b0208f3b8543768dc9989f936637d7819e7dc5740fd000000000000000000000000000000000527682076572d8cca15e47a2faf62b129baad29afed22d32ea47983a8d0b138653c1353bfc6fbf9fdbec2efe36700f90000000000000000000000000000000007e3c5aff373b5154ae66f978fcd66d09cbebc7e0c96b4a4cf23c4fa5f2fa655410c7f1ce597a3f5f155017720f7c50f7d46516db284a3938e672ad3c6bd40313d77c5d643ffcc59e3f55ad983cdc0ed000000000000000000000000000000001865c265ed4606ed16056c0b28f953119751d7272bb33b9865eed312ba23b32d01733ad5446cea5873c2bbe37fdfce7e0000000000000000000000000000000007018aca1e7ac211921cab1cc6bb18874d2f39f00d916b8f3d46a088a378f3c9b49ab8a296d0aa21608f11b144a0c687000000000000000000000000000000000210561c0bbe5a9f4b2237e5bdf88bcd73326d395277deb2a883526978df90792993e6ee520c9d5ec0a6f7ef5c6b3542000000000000000000000000000000000cdd344124b7b5da556f64ac5d651a6f9b74427fd712007310d720f3236724e2284aab812d739a87f3a1bfe8737dcee7586cf63c5e52b44aaa79cdda6dd6fa92c6fce11d867b2ff5a04c9e44e0b3930000000000000000000000000000000000024494aab30849df790185a4f939954b724c387c9a366fbe833b628577654174f705d05e7d7dbcd29b8873aecd55df0b000000000000000000000000000000000863054fe3e4838d2caec7103e3d0453e86a17fff0dfdb84dd819f31756032e9e97b7be89b636e5e0b642718f6da217b0000000000000000000000000000000015c8bb4fcb6d9cf941b722136d8d76d847fd6d5c643f4c0049c9746e76e49726fd463ce7899f4df66d04e5d48e523e6a000000000000000000000000000000000f101bea4e1bf610d2782ede91da95eb2b0be9ce60485465b9e94cbb9530b416c4394862f0ba7ee8067bb48e94c07c53efaac96bc5f686d6b952e7082236622b737fda0dd3900bec71654bdebc8ba2e40000000000000000000000000000000002dd11f4dacf3d9c46579182df1c1c45a364a8dc1eb7aa7d54d0141306f1c23bed85235783a22b8e6dc4adc35f9193ab0000000000000000000000000000000010d1c642fce533039e98712bdfcda86eaa62d2d69b861ec4fd835488732fcea414cfb6f3f8414152f9d5398c73a74fd2000000000000000000000000000000000c6759b75b1e3fe86c00fa124d09c5b7438ad61fd1bb71695743ed7793f39b7a0fc99b055201ac1e3aa07ccec61b24a80000000000000000000000000000000017580c9341789484fb31386eccc9c344539a09f1c4421dd124b1a0ce61f2d0528942f7fe8df67c6b2bbf782996def47b39d6045573dafd09ab2a0d8ab6e97b0ade43bd79d820749ecf19cf7d99792ca8000000000000000000000000000000000d9c48a111c8c74bce8cd78d127999531e46a411b2f0be3507226766bc8abd088638a237674ac62e0fb7dd4a86d09b79000000000000000000000000000000000073675bb81e2bfe6adb5cd929e0b7280f5d60b3dee7f797d65ffbefc2c2944a9c7207648bb096f13292ff4440c3f03f00000000000000000000000000000000024d2e0d5ba1a804520c72331fa23a2a326d461177fa527473240dda130f4ef893870e893e1dbf7c5dbb0178dcd29b3b0000000000000000000000000000000002a4c9487485ec33f8fb347d246ab0d41b883bec30d2a5e88cccafa676569f25ffd8341cdf6c09f68afae442a574f3334c4a2ff4ce4b633ec8fe0bfea42ccc329b7d3fbce96c26989b3c7a391c9e806a000000000000000000000000000000000c1965a745e42853b4d54739b2dc507d68d80b330360a4020e4412ba5422daaae313fb9597c98575c66ccf351e62a527000000000000000000000000000000000844439e6f08a411e61d37b5b2b07921049432e1833e839b00d6cc11227dfc8770ad9ca06037043668fe7ce3bf3ce84200000000000000000000000000000000152ad6fabde2e0310c978404a5244209a9363cab1f3ac9f71339cdad6d40c84f8e5a8a196283b581d0209ce90e1e3c6c0000000000000000000000000000000010eb6af62c7dba122b0e24e8326dc906370bcb4ba791c47630f05f657a228c20e010c065b93537ec84fa14a756b199789af09ef1f27cb83189e4e13f3801c08d3a2adc8b5f88717954ee84499defc0c40000000000000000000000000000000001febb2cf2d664e4a277cbf08fc1fbacd05db415a12329f7be551ed56d67f0b5dcc917d1b02951657bff3a26bd8c178d000000000000000000000000000000000018af160555292b2f7ce27112c1d60038b564f5427d62604387de97dcf48e4473107f91936b5e8008065a1537f7ca340000000000000000000000000000000016bbad2a7f5451098294a7cab2fe10d206741a99b128dde5eade581d02ca849bab3662fc3400fbe055dd93a418aecf0b000000000000000000000000000000000b1e9586cc1b357da6e58621ce09288e62a79517144f6c6b867359251baad6d40217578d49c1501f23206b125282bdf4c72c1dc1efefb775a1bda754ff17389a6b6b6bb25e22697847d24a117eb8974b000000000000000000000000000000000b88892250c848e7bc7bb7e42cfe1048a1f61dc546929211846f49501ad8c7c8817f5b5b99ed092d5a2236d59d9c8eaf0000000000000000000000000000000011680c6549f6b7d9d187a6409d40cc26554df654083f1e8a47dde826149d68da756adfb1b65bbd219f79a10d8454e881000000000000000000000000000000000f9596121dad98bf7acb3fd65fe7e0bdc8924e2390341c11d9cc9cbb0517f988ff79a5e1d60bd89449b5f042f0d0b0c30000000000000000000000000000000008982832ef53bafc23ea817be378532b95b5872217093e7c7c2f4512d03a9c9a6dbb7950563a520781c7ae213fc82897b4a0c7c2e611a24c722975ae882dcb4b45e6f6b41cfc87e8c766beefd5b10bfd000000000000000000000000000000000ea5bc2f8bc2b4088d1fed7090ba389577b11a3ee0775cb3f0657ab5b07a6709d3a18fa5fc33554dea235c60baae4bb100000000000000000000000000000000196b6259b06a4c91a0bb0adecea134c8609cf983c2c87158a69c9de3b6768510fc56543a84d1266dda78d90c3b0516ac000000000000000000000000000000000d0222d8ef278cd0d85dc8765fa7c4256394a5ef61f91301af6c7422b4cb17889224c75ccecd2df3ddc9bac98b493863000000000000000000000000000000000548809ce26cd498816ef1222d062b1ebb7313a07e99e3aad1431f984e9b8ecfd43357ea57da7e0c6c011c5d5400f7ba986d48aa5b00fc16c36dcad061d10937b55ec4deee63cc2841b7ebab84f910d2000000000000000000000000000000000b95455351fbce6f73de0345a195f91bf96abee361908cea6c4dcde72048a13a9a23991a75b9c988ba0afd9491d15696000000000000000000000000000000000305f29b05fed06ffab484cb065d4852eb323fda8c9b7c0a78843bd7143effa95cbe5e50c1a0c3a9675bb5381709b6550000000000000000000000000000000016ebcb25f1b8e8d7a8f7131455ed2be084bdcce40034e7ef24a47fc29e447f912c20c7c9910e025aab975cd2c8cf1a96000000000000000000000000000000000d84a5de7a5fd8592f6cc2bc7c3d93c06e26185787856c922d95eeee345ddfb7cbbb60b6d992c5ea4dfb33101f2ef1dc979d4df836daac0960fbbb8919d2f90c3457cc987153def711d6e8a12fb14363000000000000000000000000000000001377d654f80e933c4598aba1f637d1e37d66a96680c3a89a762f412e187817ec08f0ae897b08206a73f1a423b742261900000000000000000000000000000000014b71954b9bc22ac22cb2d7d7f373c3238c923205b223cce6c219175df2bb6d7258ae46d6cdb019311bd386275499fb000000000000000000000000000000000a08ef83b67bc972a67b9174d0e5b1536af882d505d03464c9a97f68061aa319d612de9db84e1e7b12fc3015fc2973b20000000000000000000000000000000005f716d0ffc30005e4a744092704a9e29f58fb06bf7d8d6fdbb95a4c0eeb5c39452cf662721ea3e0bcc67f25931a109425ae495ba75cdd0bfe200ee24d813e1aa93c100ce861c9ed7fa5537e11778990", - "Expected": "000000000000000000000000000000000c53f0ca8901f4751be4a478088b30dce70b9ecc382455049df9ce108eb0a8d2696bb325fe9ebfd7d967ab5b9b2c2bd800000000000000000000000000000000033460babd2984a5d8b7002409349972f518364e92648927e223d7a3b648e952482c06cc713bdc29ab83f2646e9398510000000000000000000000000000000007cb9dfe603dc070151cc477ec5bb5a2a949062e8442399597c5eff8f1decff538cd0aef1384256dec73746e63a6c66c0000000000000000000000000000000016b56ee9b21c533b9c464178d14ba5c92a90e6a54c3ed319f487c2082b1ce1d0ff81131a5fb3dd7d13e0fc1d9ad9e4a1", - "Name": "matter_g2_multiexp_18", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000104e0b91821c59290be48b97936458af89078b176b5585ca9a79070c7050309b01df4b0bcd84f137f58304d90599212f0000000000000000000000000000000013b00ece925fd17a8effc43e21d982553ab2764b13defaae5e5419cb9a23ca7436cfc44088c2aded63785e4f07b6e186000000000000000000000000000000000267cdd42febf0706675b60af8c0953582ced84dd5ae870815654cffa46eb14b747fb8fbb3b014e59c929da49c6908050000000000000000000000000000000011c5384d7c3e0f4fd66ba4b4c2ab60f6f78f9930e1fed233263dad25294814d9e2aaba6388ee9f924e2a323693b6e43bbb2a329761a3d6a2e4d9d63d7bbf7fc6fd321ec0344cc4d7d1b6565c475ee9670000000000000000000000000000000018158ad70994584e6f2443b8b96c1e4772a00fa0bf74865c76000eae470eb02cff627579126cc465046d4e088782557b000000000000000000000000000000000d72979d455733756a0849baa8afd79e18960f3f6dc9676c33d1663961617831f3266015cb998fff28b78300c87c2a73000000000000000000000000000000000056192c20cbcbde6099256a8f40c78a32d3fd212fe9c511951c7523a3559f60662e070f5b5e5f87b1686be0bf6cc890000000000000000000000000000000000c7b7e8ab7486012d95af5b2474ce15db612bfe1508852b8d99f4402d0e4f075ba056c19df3caa3a93bb4db89443096143cbc3dd7ec63ac63618a9e5da1f9c3fb952c6fc6972dfec6caf1a415a0aa79e00000000000000000000000000000000005a2741902dab47e8d38992180a9670faf56d1849dbeaa75b2b4ded93ee5494184c8658232e9131a8b08ac9b5460bd400000000000000000000000000000000189077d5130b3a4d7d4c3074633fb12739f95b8b6ccb082dfa61d845a389e6ca7aff835fa0f194dc349e1584b3141507000000000000000000000000000000000f226324f242cbc5f616c4a897f82bc5503ab1963ca38f30070c7c9916ef6bef5caa7e2e26b3f9fe68a1d59f19a9831d000000000000000000000000000000000a999bdfa10e4838ca69694272b0187f7d0198d6db0fd85eae688424fb09baa165c623dc6da567fe034d7cf9f9a0087e733a3a84eddaf3af8c5009646a899f6ae8cf233f535e360e29e2952088ebd7b6000000000000000000000000000000000fe85d976befdae8fd0ad33a4404415304afad1c5698b91bdc15abb4f268807c906410a6ca827320f5271c8fd4c8d6fe000000000000000000000000000000000cbff7963daa20c1d20717bcd47b872b3ecd5f38de1a467ef50936f13d6aebd978116a736cb6c5d676c6a9525bb0b7fc000000000000000000000000000000000c3d20ba17a21bbfe873d88e9221571f1bae7f02f35b8e677c9c42907673d765150c737f0011fdbaf4faa883b0dbf0280000000000000000000000000000000013482c68a5e1084faf12e8aec92cd9f0692b173556ac8ac3c7519beb4bd75f847f41ab9432421c631b14c885c001dce25112b5912aa3cba657d8de3dc8138fec92b391d5f988b82e19f16fe52fafea71000000000000000000000000000000000f9091a0df2c989e12a844c447287b704803d1532a3ecbcc890e6f6a885a54b969c53323c105b3d14d12f2cf766b8ac8000000000000000000000000000000000e54f3a9def8b3a9f972726e606195849584b7197ab70a28cf5644cde15e70bb6e3044042b649825adaf5e37c2d5e614000000000000000000000000000000000cae412d8a3ee3c5af38d7a65bdf2440d9cc2d6348dce0791f4a7e71ac483d7487b6c789be0a401777de3f57ec65de820000000000000000000000000000000014df09fd2ff406707004f6afa366d06bcf8bf18f5fc4b444b07c98b3f358247c6056a6337f5b53c35db45904797fb4455683e0b33b5463bc71283f0625269b2b33ead69c1eb7b23a996c31c514d06937000000000000000000000000000000000a8aa422e1d58fccc84615f9ca4a4743cf5efe3a1066c9819f05042100bb8784fcceffc8b3a739f549b42f34d62629e7000000000000000000000000000000000c737cf78b10e82fc0cc9823891f1a5f1e9229d61e8f369c589512d01e5180246db46e4f09e811464c6e1ad930226d390000000000000000000000000000000016017354434899e2285da6ff4b27fbaab633d962197d2ff4fa5f688c4a85e1817434cbef13a6b018df4e359d7b9ab7cf0000000000000000000000000000000001433c364428ac69ce4f5678aadfed4e6d076241519310686de01572da5cf78af4a98b3502519beb0dcf04b748d08cac5bcc597c5ed7f79173942a0250e618c93cd0917b37b5f354d63a2c02a576080c0000000000000000000000000000000001f8b803f3f76aee9825a9a960cd2f9e8aa931568b32be6169036683b4e6d8c4abba6bb73b137c7c6d6b6ea92f2023ab000000000000000000000000000000000fe9edeab60bb55990ad2c85c8fc9341e81de54324652c08c615a745813f08153bab3849dbeffcf4073f087f7c0cf0f6000000000000000000000000000000001955289b1210fa31542bd89f95188d60751b32e8d54f1d4d280975850e57db7b151b872bd431c528c22fb89c9b8784af00000000000000000000000000000000079c8a56c72adb9fc9baa503db394635abb10264dd43c60f2c82d041d43240321ac1028688d92c4696395d8840d52f15f2613a8e50fbc6683ecdd7c7fd38b4caa8e5dc9778909fc8680a58b16ebf40da0000000000000000000000000000000000b0fd79e62c6129fa115d821b8f2a58a4564f5ccbb14088f59d5e6a17a64e803f32bf8e5a415aac4d6491612d95ee8f00000000000000000000000000000000008d837b6c70468e1e10f6b979b7c0694d65942aac48b5baa829c191579186314ea35fe440e6d843fded02b95f9816890000000000000000000000000000000015a05bbc4607b113b37dc0b4b8add23736e0f1bb1e48aabc15500fa6941b17153918d256b6442687a432dd9ca9a198c70000000000000000000000000000000003546953d97306266bdd359d4daa939e05c0466691de59d2dbe3584e2ebfd9a9e1516cdc9cb643c5d31731835dfb07c657a747bc919991ef9b7b10388bf3f301fd910f807ccd31e322be46580a71b7c60000000000000000000000000000000009a4366299290c3c6651b22865fb22cc972a05ca5981f5682574851e41096d531e375e981c4e1b1cbfebbc70a41bb6ad00000000000000000000000000000000001e6fe2097fca2afb8385a3100dbd5ee1b7ae972e06ef9f5e34eb9fbdc65455e1c822299e06a9dd5a3f71a0c1efd44a0000000000000000000000000000000005ad2ffa8861848c46722a7924ece68580fe44e03157c982b7133361e974b59dab7b75358fe498fcde9f68b5b99f23e0000000000000000000000000000000000adac33e0b7e6740c980a4f297917fc4fc13f53a71909f2eecd0067656c6f82c3b371cc638509151bf937f8257aa415d86ba09829f4bbb383e2e131d554c42edf1065022975655c07df2b3445a3e6cbb000000000000000000000000000000001462d509503d2c33829c3fb5380199b79b970c2ae7f944e54a6d0f0deab3571976916cfc311ea6ce6128c467665fbbd10000000000000000000000000000000017f6fe356cb0dd5bddd489c26669f0f365260bb48a5f862e9bfb778a7ff5392938b905759718d050f7d93f107236cc75000000000000000000000000000000000d9b3ca93c5133cabf3d3daa565bc6b51e63b7e37f68f3bcc43b9b3ee7db15f8bb33052eb7e332ae3e9ffafb17cb77d60000000000000000000000000000000017d6b898d9799385990c9dcc3f72ed93333486b98349ef106a230a71d768b75cf56cd946f5952075bc41f26dca9c83c003fd5e91f590fbe171aa3f006617b20ad645626c970c2351e048b2ac3773213600000000000000000000000000000000158e5e008796c10f6050826c29523864d06e68977cdc95d281a8606924aeed0b475ab152bec5bfca8e0ec53691b307f50000000000000000000000000000000006fe8e75328c067546eaba93f4be2b15513bae4a3458112c3ffa457d15c23636816fb469f071889380f31870d713e949000000000000000000000000000000000b9b21cd58f8742ed094e9b770182f6f3f855204d869e53c02d0c242a133e957c53c9fabc827d6379b39541170be313000000000000000000000000000000000014eaae1f0789f0b1e8ad3b452b4ed3ff87bed49ffedd13c8c35c35668c33537b63050c06a5bf3d88d516cddac13b4c935ee16785c004dd2a01920c52d3244e2160fec2d17a519974d4331527cc627910000000000000000000000000000000019f976b3584ffc188424614fd287eb79f060c55e9b3dd2f3eb99760a7cb5b70e2b62a0895b05e7cce2e390853fed61b3000000000000000000000000000000001117181241fead3865eba4804ec2c14f571aef5351d5bce29399113d007cd4e9c262af1c77daf9183346153e562864b2000000000000000000000000000000000f823f71035a4870be2ef20bc94e97d74d18c0a1be9895fb27c54df1f663df6f9e6e45ea5fe4502143a84c05e517b02b00000000000000000000000000000000141250f392fabd4566e0cd3a472a4b2971a432a3a5e1d9c924866c7a9516322bfa691e9dccdd5ef14c561bca6dd70ba204a6d6e29336015d99e107cd312e300bd54f815c785f6008c47c99fa008452700000000000000000000000000000000014d6827b9bc782863491bc7c544263f58dc04c18e08a87ca2fbb5799c4aa70bc039416a85dbba67dd83bcc27b70748670000000000000000000000000000000016c2816e93ea9d4bd6e42a9720cb89d637d88e00074da3300c6409be98a03403e9ac15f83167cdeb13800ad174ac47f10000000000000000000000000000000002aebc0116a62f93a6e86c7fce86745618e08f4aa9cebca7b520e9176bcdf1521cb2bf7eca7f7af9487fdc82dce76bb50000000000000000000000000000000010684e3254207c4ccdd49e4775198df981afcf7d9f89b894e204c5dd84ef42b89fe3e2f6b9278470e6cde4d3f4abb3b003f9cd3873dc6243748e16e4806f8eaa339edcfdbf4408a8e41a3df80c9816210000000000000000000000000000000010ab1d5494509060c9784b4744a0572a9466d6c374524a6d338ea12ac5ad89519217c462c3487e398325439311bea86400000000000000000000000000000000197568cb53ce03f00aeb04278f355da862be757366dad14ca6d30b3a537df9855a1196010773768a91cb4bb664a34f0f0000000000000000000000000000000001fee249315794d30eaf929f44b99e07927194c6015ff34a4530698d7d68239240c9cc48530d52ea06218a826a655cce000000000000000000000000000000000645b5d701bf3422228576467120935f014c754dd68bb3555b50aff5ca04001a26298982c97a64469aeac3432784efca34135a2e7853c74725bdaee1ceadead7b4c7d729650df6544bd525c05c94234200000000000000000000000000000000113e17730f8dd7258157085c30cd9d1950a26c848b55e3a8a55865eb567edecfb09f32ba27fb3e2096ea00c30f31ced8000000000000000000000000000000000076db9ccf8df9530b64cd43ef7b496d1f432885062406028901bbfc5882fd12533f84eb12aa2ce8b7adf9dd980db0870000000000000000000000000000000015e487de49f1e494ce9907cf0ed31fb0a159c5290538ad969b2c8a504986dc9cccf7c74a61f622154e928aa2dd689c0800000000000000000000000000000000195e887083a98fe3f50a9ff4b342e004398cdfee55c4b02a4db0f65a77d3c0b142a45201674726c96d5f79f8604d61860033fdcb731830951dc3c4b33f06310eca51762cb7279039b3d7d9ace93c5f2a000000000000000000000000000000000d80c7e50973205585b20a068c64957cf4572eea40e32ffa8b759c38c6ad6f4468421f2fd6a6f5da1b0d008f625b3e6600000000000000000000000000000000009242dc1de055aea82b3b917f88b6232c550c3aff41241a7e54caab4c234d29b5d8138968846f7c754d73ab3b4e7913000000000000000000000000000000001188c31a9d8359d737576f4ce7a7900314aca0eb3b51baeccfdc9245bffec49143a11b3331f9126b01de0c307aa4e44400000000000000000000000000000000104ef4835124fa6b30dd551653aca25db5a544af6782cd0b1e7d26178253e0e33cda77428fc1dbcfe6114a758cab5c814c8112ebfe12bf44e84796e8b0cd03a93d2164d6edf1f06a5c520330a177da87", - "Expected": "000000000000000000000000000000000e79d18633c18ac818786bba87d09c9bb1571e179d8769f8fb82e2e2b7a6a8695c1f4f06deebcb84524e8facdcb49d0500000000000000000000000000000000149d0231fb030a1bec170decd307c10e72cf1cca55c8a1b67aa94ce61e4c7d2ddfd0b8e71598e1abb054355dbcac1528000000000000000000000000000000000090f5be784dbafb0a8aab1516c773720341de6176017e0fb43a275d60de54c1189144956d4876d989232b362b90851c0000000000000000000000000000000019dba28eaa6706361f285b3abebef68f764204c74ee93ea011db01c19591ddc6f98799fb3026c3c223effe4489a7c676", - "Name": "matter_g2_multiexp_19", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018a6a982acce5693e632901f3136eded40071e8c7caa7887f302c32621c5bcf9478991ca519978b52f8f69415c0d070b0000000000000000000000000000000013420ab920c8ecad5b2f9aaf9b0074c2386b0b08c81923558770d4c4a6b206a865af8322e9755706cd5e595bf0ffe564000000000000000000000000000000000c0e5bf5465d564e3ce86d6b742ca687448e6952439b1ff44b86ee6461464e07f8039e8ae7a301c6caee7eb99e38fab10000000000000000000000000000000015eb8751b750af62f57971e88b436658758bd5712f98861fa07328d2b11e8725fb55a2a00252e0be06b0c73aac0f7b8cdbb32a4fd8b9dc58a382a7e436e23f49a134915372553eee8c605436221acc80000000000000000000000000000000001328927910ab502e573188271108706152f562b1d5f6ec074f8f9ec5eaecc6cd5e8284a060b65d26463d22c8290ea4ca0000000000000000000000000000000005a1fcc348122350981dd5090c865a2aeb851ba8b6e0443c32f48b157ba673ae5652a70390888b3458afe6fe975321700000000000000000000000000000000019edc749a9799c8d3df75d4024791943a8fa02ba0cac90b6819f0bc42687b044457bc7cc6073506e8fc19af37f224624000000000000000000000000000000000fff20fb2b554b63758963c1583b996ad450cfbd5ca9952e38f38a8994809096086ed86311f7d73a0a5898ac261ce09e57df9664d3e17d9d46a886efde4e37e38859893113558843bc019699eeed8ec00000000000000000000000000000000002a7005dd32bddf1031f27c2ab999604c048a37c39734db48a30baa86c61ef626cf82084651ae9ba8a265333060a408d000000000000000000000000000000000421bf913a25108b8f520b2becc6f8064029dc046d0d5effbef31f0af59eee71cfce83fec8dda7983d50c6d5cbc8329a0000000000000000000000000000000016c75708f1dbfbeae3b06e5e9a7fb676c27100b99deece14d979b32a9c3cde6e9e96c8560a00aafbe6e7decc84e7e2780000000000000000000000000000000000ce23c27b5128bcffa424fd1d181d21b06b77bd6549ca5eba9a28cf18bb9a979270f6a5807c640dde57a0cd4f3af8cbe2b433b7a95c26e598002cc00b7904816d59baaba79bae7c6a7c26dcc48a487e000000000000000000000000000000000690c7ab321c0c93b5ae4ed77843ff4030e4ffb504c685d28573e98836e8e56dc19d662ae9f496a346bf2a8be5396741000000000000000000000000000000000fbbe3861a8d202b10801cdd606b50db0ad6ec7b923b90ae81ff5443676c3399e249e9efeb47b72d2b0a54cb0594686500000000000000000000000000000000148a27016968f0258e5eafe0a8182c22091873a5a58b27aa2160674584e06d5b2f46fc57a00617af18d0688df75294cb000000000000000000000000000000000148449d00b3d1b5b43b08a0c6e909a2d9c66920b60224a2c6a2521f0bad35b99e3bff8be0effb2f7f34438662d7a4882897583b53567bcfdbc63ae3e864a9cda24bb732694a6b27415c5212c7f45a9400000000000000000000000000000000026b55509b81befaf6baa682a3e92a0ab423fdaa84d2897613fd31acd9e1590f81581ba0ba87d68af76b01c36093e183000000000000000000000000000000000c675e190570bc5173b8f508d5bd2768c83e7f56a08cddbc636792dd75386939942827617c4aff8628a74b74195adea20000000000000000000000000000000014f59f38ae9e77f3a76478ecd47f32200567bad11f191d303cf15d7801ae7b5a3286095fc8726acc9818914b27a776bb000000000000000000000000000000000da89fe9493b2d9d46596d80162f5831d4fd8cbb83b46e84e95d5d684eb927022ee62ebc3519442007fdc543701f97bd2f7ff17e54d759eb9c51e16cf6f12d645bf2d091427416b4edbe1dd21947b4d900000000000000000000000000000000170e52a240a7ccf2d57ae92ea8dabe62ca4b458a5da42319ae89cad22ebf13541b0daccafa1b1d3cfcffe81b500c4cf400000000000000000000000000000000174879425f3bfd40fb74a88e3dc578e45b0e0eaad94da009e4076dc42d234d78248ec3a035666dd6de235f87e1a47bcb0000000000000000000000000000000005aee47acc3260d11fe0ca16050a29f92763b3cf8ac78da52b3b2b3e26d8ce7b6ccc187fcd81695aa456e9b94a84269b0000000000000000000000000000000005eb297abf35b51d57474b4989dd8f793005bf8e82e49859c41b786ae39217b2321299829198bda4aaa261a2723d43d6ce0a097efee666c22d1dd0ae8c8e11283aae781e1deadceb3ebbcbc5e5280a61000000000000000000000000000000000e49e94cfa35d8ade2b76865cc8be04737d00b48b195078c8085cbe782232a544cdb548373bd8ad0282674ba5c96fe0700000000000000000000000000000000047d59661f095c41bcc27da5f260f13a3fce334bba216b45df548894bdebc691fe779ccd63d99a9872973ab165a90c01000000000000000000000000000000000772e9a9c22bc7352fdf74915bc464de99ecd96420ef1af6e8bd5a05d73fff89c78e28eb340d4967e906f28afe1320490000000000000000000000000000000018bccff27bf9d7cb2159b9f2d1faabbf8591b53ca8e67e661d9f44f6dba6296e3e46ac32c50128bb5fb076cb8f214e277b2baa349884b54b542e3993210ef002f70c6467c7d512801f0003da789c00580000000000000000000000000000000002d947e728a3b376de520bf78e56452930de42544241180906719a24d72df65f8250402ccaf14d69935b1ecbb0b4d34c000000000000000000000000000000000d5614ec77a9f31915dddb3e4bb533db001702891a45f0bbac49e73d9c19a235a00442b52d452d77018f883706a616f1000000000000000000000000000000000dfc6a73a8e36b7b2d0614b1c6f7bf1ae284ed740c768f08416c0c09a601fadf3e4d7b17a93601b1803d19a04ccd570b0000000000000000000000000000000010d6a8e4eca2e818d6dff13faf0fae44a7fb90be436a9ef3aab05515a35cebfbd53e9af866cde1745f0e2c3b045486dd2b94d087c3ea101649ed57ff308dd3ae0d25a1ad8884763cea1b0b7c56a3834e000000000000000000000000000000000d6c5a6fe9b4d4580f8e1d89f0510bf5dd04e113d6ae5db04af2553bc0eb3a32fb881300f638fb33f7c4bfaa10b063660000000000000000000000000000000013e001b08191707ad98e21b3e0830286c6f3bf587b971dd4ce39e55f06db427676626a5c31c4a67a996a5725ec8f402c0000000000000000000000000000000012f86ed85113ed1abe9dd3826423911e63df0dfb51ad3d1e0e0318ae95991a6a11150176cec77f9c83268a322cb7e934000000000000000000000000000000000dda719cd2cf1aa769f94c21af20ab076b8f024e0a4903e38ddaca21b6bcd6f00baf7e1ed23259f135eb8bcf9c3f97c44f8c35b920a35b71dcf8d15a8a826e5a7c2a2c4f1ac2c2e3a6d100363e7f541800000000000000000000000000000000195ccfb9038bf9e637b88c83c552ffbd562357792513b15f703bffbd373ebaed715a6772fa7e6e5678c2e6422811dae1000000000000000000000000000000000c5a110f31d71b12cc42974003ba39d99dfd91769c2e93393449083a9b84d31473e3a7dff7ca40164e6e7215b03f44ef0000000000000000000000000000000006233b2dcfed96559b565928a494f2a50c2c375b3d7c60ee6b286c538f4fd5ca6f8b2a61654fd04d679bb3e05b9bcb03000000000000000000000000000000000d42233b7b5ad809c735c89c455ba1e8fbd623e1602bc729c01d362368666e4f90e7b076e32468041f3f5665c6fddb0d0ae6101fac82c10267770e74a0ee16b5be6eae2d455d742303a3c624d52aa726000000000000000000000000000000000f6d53de4f8b20de19b2fcbe8a6b8b8ec4bb801bce7363f89b133532ca7ce4925312e23c618a0182d158037c0d0bf07e0000000000000000000000000000000006ce094e24eb14b9bb1b4a1838d8b6da5f53b5c5799ab8dc8934b488cbabf698b99abeb016259a4e1b0f626d27f2c950000000000000000000000000000000000874aec7c8ac360e3980a6e2cbf3f7468f1df7a8d9158f8bdbb0f387d19f3b05326a081129576251ec41a926f670e58f000000000000000000000000000000001711c9b2ed7e2f789b29073f180e46d0c373d6e75c587ece67b8aaca1e9d9b43a96d04dfdcd42f943eca48e240b72ba8002fb31d0372e7730499b26d617b53ea04821c6eae922326d755a0df31b559ae000000000000000000000000000000000e8ddf88269aebf190bf9bd7a8276de92ff6039e479e42a490fe4ef00f646b049eb8ec4b8e073caa000bfcd86ee8724a000000000000000000000000000000000a9623655c0121ea0575de714e53c9e304fa3309f00828ba0e786112781a38bd458cd67864ab17929448171b5937c1d900000000000000000000000000000000198fccc4a333322599697e904e9096240b9c54f89ee6db97475beead62ebf730da1a179409133698ef13abe1310689270000000000000000000000000000000017b059ac08a3fcebde5888bec4d7cc2c70b147b3b1483fd001330637ff1c036faebf292801204bf2ba49350795708dedaa846e68337f4e9c99dde506a3af792732342e3b836376d4816557fc1fc9b916000000000000000000000000000000000a36274f33b4dc09e03a5ad648af0913e5ee95af83df8b4f2a158456aedf0a0528f9b4832b11162dd67e4d22b26e9f940000000000000000000000000000000008ce96d8bc0aaf2dea732dea188870d398b1f3c266b9bf019e1046cca05002416c910e02e998a1604a17c333c65c99a0000000000000000000000000000000000c1a0e4a80bb0331a94ed14570053f941a0438794e6f19d976cc62b3806a565697720ea03c2531004f13453991bd99bf00000000000000000000000000000000184bdae93abbe4d931a6a51ec85bc330d6181da2d34f2cc530e56b6803515ba87f5719fd6fce6a1a8bf1ee5a968bbfbedf9035283f1afc294ee68b2668870aa45e483d208483d9e967b11990cb55d8600000000000000000000000000000000016c3782daa55312a7cfa02c3be73ed75f4b726df5592351fffae19121b5cba73f427d35d5a2df7c63e2a5c68bf57f3800000000000000000000000000000000018b608343616eff759d512c97257f2103cb0909afb4c24a1cc9d8204274b7c9ed51bc762a6280e223a6116a9b23d1f1e000000000000000000000000000000000c687c11a879ec285180cbae3d2e4219df4614e238d4cbdff148ce5a8d21647c489ade3bf6f738052f149fdbc76c8bf6000000000000000000000000000000000936b34fea3a2633b9aa32244329891e332745876d05f95e4efdef859b23ceab4869db562555e5c8edce87a6fd075ae54005df80aa522e889e7720a9f2e44e6e7e19c3160ea282ec87a4b446d7b1c45f0000000000000000000000000000000000d4636a5e13bb59878319af6bb7c98e5d247c2c9cc970b9cec98027de2d4a8ad12d50906fe302c3d055c499a3742ee30000000000000000000000000000000002b0214bb1ee887a7ff10d458fe35208573456f685ee2fb93bb470762c9e27595cb00f2eae7574c8467e417c63c2a960000000000000000000000000000000001710d130f91861230562cd7ab87984ef45916af8e1168fb17b9765183d9d3f9b2c81c649687842de495a757471e28067000000000000000000000000000000000dd15fe505b1364f134ee77e5e3c1a497a20849b6ec7e201813677a1569a9f5a9edbe3df4c36bdcf9ada139b20e048ec893c9daec43032946a9e892dce960e07d29b304000378145148b9a24afd151570000000000000000000000000000000009a48d7c55d24ba49f890791d0f6a8a5ae08a19177575dc0d734fa37b52c3adc45b31b5e485a5d4a5533470c3549f5f900000000000000000000000000000000090f680c6fc1f0588add04ee03bf821868b1ce588e3ebe384dae657ba7885ef74da0bdc98d9d9594a9b979d5b50b93df000000000000000000000000000000000314f6aae1e99dbe3ea9ef85db7e1693a30869f48e05cdb073bf8e14865a671e75abb875d1b41f13d4eb74fc802299c70000000000000000000000000000000013c698b76dd68d1b9ab41672c2b07cb9a63168497d1144b51509b602c5acd71ca6cd049616d949214d95ab7a906a8f8bf685e6bb7713f8fe202c05dfd18003eff261456026a5185ee9e68aa821fe7c5b", - "Expected": "000000000000000000000000000000001747f6d3154e0717435fa023754f115ce2a2b3241b62525cb2833473d84a8ccf4c95e3ea030f2b8b0ccc61124095ac86000000000000000000000000000000001827ed7d84a61c21268857036e91c732b304f609f285cdc4736c951fd8954b10267a8505f25d8be666792358632058b400000000000000000000000000000000121ac61f59051e6e89a7c1e2fb4df4b3a5b7773f46495a99e55348454e1d9d42254e5e11b841a1654ff9c80b157389c70000000000000000000000000000000001bc60cd06879980bc6ef2ca109d31f12cac28ebe4d2a934076d720b12f430e1bc4d4260f40045cc7a862726521a69dc", - "Name": "matter_g2_multiexp_20", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000012a6984f0f8967c5ae6b13569a62095b5fe61ec607daff1845961bdd827c00fd56ef864802673dd21d90560fef6cbea00000000000000000000000000000000085ececa080d0f4c996d46c80a1fbad2ac9cff8b3e324aabb67182d79f941927050f025b633fd5119f30bb29b8e4b6f2000000000000000000000000000000000987518a5edfd5ae2616fc60000e117a4f1dd1db68195c3fb68d8cc639e4200945b2864d41ad86fb3e11c504fc1f9766000000000000000000000000000000000310939c7e11b93e5773cfd36fa70020c85396e525840742f994110e20019769abcd339db6881291639c193b987b68ae94b3c88e51af5822177b85978526036a426c9ca1077d594618ebb8fac4cdfc89000000000000000000000000000000000ec6922dfc74009c3750ce2540558c7c1e05cb45a5d651b96427c615d8fc563219215a0ee431c0a4827e40b26c4f8d3900000000000000000000000000000000040a4189d002a0e1ec600e71303575e82414e6400f06b9abf57151a28835d454f56421a6dc4049902bfb94dc0e9967ee000000000000000000000000000000000dfefc7c163c34cc004e9d97d812b2717d4736d0d1c722b6bf1a29676a32c8b46878d05a2d137cb7fff5fed8c0f02474000000000000000000000000000000000e3f0c9cbc778693c8ba88af8306d45477493ed6be1bdd9c81c65341239eb510fc948142cc30b73f570819b38f13e20f6e456b39f4efe6581657f5c701c696fde8acb59e856943f15cdd639c1fa68ed70000000000000000000000000000000013705ca4ecca16559713df65b376c7c5825b4f63d001ebbfce9cd1b592af5f2ddb38ac7c5ce3c5f7af4f39f909887e8b00000000000000000000000000000000179efff38ea1044e91ccad467cd2b49438079ccb4d0fc692e79e0bc374abe064fb9979c4a1f4b92c15cd1b042b501d5f000000000000000000000000000000000b6fda2dbf6339af225515681184843f1a9bcd72f7b1389f186f8d0e048ac16e20967c28e087cf09d7bcac597a85398d000000000000000000000000000000001946fca8c816e1e11187aabc40dd2436533d537ce4639eb2d08630ed2ce402c1806b6c2b3e04a960408fd4d2049849bae5d306f46a31c14de7b2940104d0a4424ebaff805a81f1c4a910566057c81604000000000000000000000000000000001802064095d029d3897725eeb93ed6e3b090390769026120aab6977d0de264a262aa312c5777ba322c9eac29e5396fc6000000000000000000000000000000001410f17820941e6a67b1b4993496cdcf0d4fa2d4fda3d43ee985f2606b1408aa9c9ce412c80c90a0c876cb5ecb76878c000000000000000000000000000000001514e9b2c65ca86713447f2d5bb8395fe8552e059829afc68bc43ba9267ef41ec6d69d06e7407a731bcca77ed5d9716f00000000000000000000000000000000025b5bb18cad46179fab15b2ccef17858f9259a90ea4548852b8c6fca69f0ecdf0b175669bacff1625a7143e762514194ff6d13bb0967945ff3b6fbbc104296805e4fedc3c25bb55b75cc997834de6b700000000000000000000000000000000146eaf5da57b6ac788f8caeb4b2ebf7c8999e03dd839977046ca834fffa7e57cd949e3fd44999a007b5dcf3c8621ba2f000000000000000000000000000000000d859632d3424ffe4227ae14856e05c4e750545cf276c97aa9ec03ebde334144eea670dc68e92b61fc775e477a2154040000000000000000000000000000000010b44279c0c80886e52fde5e71726422da2f9457ff86b21426d80356fad95d5ff3a7491002364d9de5ca99c2500f344d000000000000000000000000000000000851b769a691f0ebb53ee3693833881fed8dc6d9e5f1dfeaf4ab1aa7ad54e2fcac246b70d81110451ed78044a98d1547de4fb2dea292b76d8130e6aa8aff5edf0097de935b252d42a777d4d9b8615ef100000000000000000000000000000000131c9a76109929fc977a0a6eda0a7c71cfc744f5f3654e2221ce84c70787598e24c5d8049f92a7c4d78fdb869cbdd1ed00000000000000000000000000000000049872d2c7d472e090d2975daa64fd96f33e7f934e739633b1d7fcd5e771673ed8820752a0d5c8b0c6933318293a4f27000000000000000000000000000000000dd68fbb592a3957ef893180dd758f75978042add36c91b7bf87c4493b0baa875e1854fbc09e6856688cc241b76ab5a20000000000000000000000000000000006143699816cad8ab7583a72b6064fadb6caeb51c8625ddbf7b2911426cf438534da1bdd13e22cd545495c486c9733f7bac5c50a3a8a37111114c22839c88ce4072940c06f0d8b6d53fed155d0399ed70000000000000000000000000000000006c14301984607d569ad1bd774135e7c9e328be1fe54c3b543276bd06bc0bfff11f299a5eb43b5218c3605011d0ea6d80000000000000000000000000000000012f0a848022f95f4884380a5b8e3637a41e3c399a8d2765aada85dcf4b7c2b559122f792850430681a58ca153be2768a0000000000000000000000000000000016b4cb233e1bd59b7b362c64620eaaa5029c173a05e2278774ad6ed746c70a2f6e76c237182f5d9d790966ae69da5d44000000000000000000000000000000000c277d54a7a72c8528188f6cf29d934cc66471607e5e30d493cd11be6b203bdf734aaf37b686cd7101e8599b69446991c3f37387bad1af3a896a7e66a80dfce2df1709fa252b6fbe4334d02bdced432900000000000000000000000000000000169a3928266375dd5793b7504727f939ef0ed52d69e569b1b75a0e094698b37bc70472578beaeebfd0c3df4bce6177810000000000000000000000000000000008936d470dbb86db1567bb2fe7c09971c6d12b07208d9b1b403c20fbdc05ef8984dd576457fc6989470e40ebfe4ceed30000000000000000000000000000000009cdec9d80f2bf3ebfa9a3316e4250741d0d089245df2fd3c9bba4bac1c2dadfe212682166a0962f78c4bf25b618da900000000000000000000000000000000016521411286cabf3fa2c8f72ca62ca311738fbe63717fd12916a4c9e6af9b05d1f5d65cf60e84d9fc5f7b7645fe9bad570fbf5da3959a49fab7e97b3df3f2a38d16d714dd798a1f04ec2cbf84fce76910000000000000000000000000000000006a827f6149a320a74d9d8c1ae8861c1cb963b3eff899710eda642dae6ed4dbc247a22131758d9f843c62710ce083208000000000000000000000000000000000c83a9fd96bcfd4adcfc6d5a47e84108bd763366e91bf06a7431c6c3a107cbe5647da99ee6c1e57c376d366b21a923df000000000000000000000000000000001604d5c0364afb5503b0e1d52226988d7f7f043ce95e7c0a09d7f96e24a58f089156f0e6d19022138170c1b4b7dd33560000000000000000000000000000000019a11c86f78ce462f46e0462052cc3d342596b329fb62a282a59bbd64c345bd266922b1540e40aac147681754643c2e3e538bcefab5d8d0be5fc143e632e86fc065af3f2f621f293b914980abfd6a0c70000000000000000000000000000000015635de295c16841bf44c73639f047f735175e8906301746837838d124bf0d2a1ebaee142393ce9a0d58107c7cb036e90000000000000000000000000000000004fbbd4252fb901d0737d1bf4da62010c06d690a9584c7631ef5d36f1d8c37486a83f2a1e2db21f05c993fd117c662e8000000000000000000000000000000000f4cfcec1545a08e0e0298753ebcef5f61bfdb7c1b9af71cb4c2f783e4fa3948945d357e8302d99aca96df0cb0fc01a3000000000000000000000000000000000f543dad6d4b797f6fe0b00215a5f70f6340ac6bf7cb0bdfc5bc7698dbf0647e4098413dd19ca7af01685edaaa190c6e30b921d8cd2ca46aa6f3e0dc6ff08d77972fb0a248bd39e90a1e9f32be9e892a000000000000000000000000000000000ed552e94021d0912a0e7563462570cb572b189569eb847bd12ebf976d22343b9ad04d400ae98fa184b10ff36720f12700000000000000000000000000000000178727c3e6ff33be9894ef26347b104023ea0bcf79c1a33afc26ac0ee9879344964fada757118829214cfcdbbc0c5a30000000000000000000000000000000000b0a6a575afe5b0c1e287815612fdd3838ab39e8ee7795855837588614715f6687910c42217ad52c1b8721a9e1c908dd0000000000000000000000000000000018cdbf244c78cae1993400ae164b42c09dab4d8e3707a69e25ffa8d0b96b8270c022c0375f933f16f45c9274132a0a633a5ccd9436b15d4d04a8ee9894c116190062c4e7cfabb047b585f3aa1eeb460500000000000000000000000000000000070636611f903f55cc9499481bc3415a6de62d5e6bf8bfa82a8ce665f85bcf01690118441961ff46ff701e361db208500000000000000000000000000000000013d22dff8f6f86f659ad17ef91d90a70c180538f03e10de20c445d22e637015d51a311a3daaed90712d04c9a3d992d12000000000000000000000000000000000db3535057db95fc262f8adfd7f08f3237fde5f0e2aab589d4ddcd9c23aadc437e13644dd3b3534dcb17936a7c610cf200000000000000000000000000000000044c177d4484c07fb04d1dd477b188a2c157973cf26075001d14d2b07ebb9dbf8e495dc23b32a2419621e1c129b08c5ac7a5bf2cfedd7048be7ac7d2ff19d4f8bf0a94295ebdc5e792393e0e4bc27d56000000000000000000000000000000000e10fd069f2f5fddaa0112e70ae89d1ecf034defb24e2923731a7c0068780177c186fde92a3c254a1cbdd255111a4b7c0000000000000000000000000000000018363e01e86e2e922ba435651ad892bf9288be14b54dda821c397ae6167f9478c8132e92b1c2cb0c4037a4e020f08291000000000000000000000000000000000301b5ad2d5c35ebdcc7e7cd1ebf0405cf204d6f5e30ae6f46d20534eb6d7013682c5ae1bba76d2811124ebded0d2a590000000000000000000000000000000015fb3a8afad778031d04e094cbde5f02dcc89ad7b7d452c6c8f41be336a4c8b26e75cfc685b8776cbe5a487f09c304083563651d5f5729a0ffca6b383d884823aa3b0215fa057bffd8142199a16e4ffe000000000000000000000000000000000a7880b00f6a3e959ff1bd207fa503eff6e7279e701e37b40735e2bc8bf49e355e92edcaf23aa3654bb26fbfb07b5fb100000000000000000000000000000000113d9b792f4e3dcd958664a8778dc4b177c430d8db9da7805595e40293ef2c0a40f7a843bfa70ec134ed89a453f9da50000000000000000000000000000000000d7f92148dca4a9c96c47a0eb284f1834cf3d141be7c0d9a7a060af6e28e45620d8255e465e9a0d8f78b2ffe17d6b04e0000000000000000000000000000000004e7917a8f3070c656d324c9a816236842fbd6147d326652667e7bca0666d214233ed136dd9464c4ac619d46c28e2393833323c3a668541ceba18375531c3781dd98525b49dafce4c4b3188c90f3f4b500000000000000000000000000000000160cb05390b54151f6b154b396bb400a91fa83d77fabdf31fba349d1bf3b5dfb6476ad4d714af2a2963e41b077bffcb90000000000000000000000000000000012885f7ec8e780cbaa90a465b5706cf07d45bda7755ae3477c79adbd7956b926e0ef5303fc13f0b97349ff8b754dab500000000000000000000000000000000009ad7509e9e7f5018ae3d1280e881ec12129cbf825cb6606459211ed7b358a97cbe430e94dd9f5e4f6b74fb7287f862e0000000000000000000000000000000014d5d2ac2dbc3d5a061f4e52dbfa68e1eb1d3c818ba26686a3171e310c63cfeb188030b83407070019dc5c42dd079413d422e21fbffa7d55270eca9c96bbefa29dd915aca266071673e970daa0ca9c050000000000000000000000000000000008ee93fc610712411634079be0bd96c3969b48955fe5478b7a31c3ba7639c18291034167eb62e6b15c16b0dd5145edf500000000000000000000000000000000158cb1731b71905d7b958c5407f090a2c8a9319017719da143a3f4f3fb3982abb83b8dfe14facb014321b4f5edb5e41d000000000000000000000000000000000a9f98f775f06055ac1f137cbc1f95f4afa0d1c4935f536ba2e0569d874d9d76b7b86f71afcea07e2e785c7a6ee1c84400000000000000000000000000000000072f8988dd1ab0fa8037d3620068b34848c65e20dfc90612d123b6f9dbcf9d9d699d5ea73739d31ad54c22116365ab983ba7ea9ffda87131452b24a9efcdc91d1262d0d7550e5a6b787eace3577159b0", - "Expected": "00000000000000000000000000000000161203d8db1381722644f87b04f47e4be2ea2bb105ea0e67678bc8d29f8a8a3247f8c05e057af8f98032faa93d896aaa000000000000000000000000000000000d3af4842627a095a2dca99b52d802b2ef8c8f3d09873ffe39d224333fceae84bf74780956904df6c1dcf5ba31be218d0000000000000000000000000000000001c79fae014e55e5d0239645d618593bfd5aef665b3e636dac5d191a8b88949d207cf0ae9822ce8e1997de302b386b8800000000000000000000000000000000136314cc68b372b06e7771d82b7ce7bfd0e9fd306787e07629f831c7aee853bed80172121949a940bc59c4a0b76f0819", - "Name": "matter_g2_multiexp_21", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000099434adf799099f2e6e2fda4c905e1543893462133ba216aace25836db37b3dd5bd80af1a8c31c7fee56b5ecf9a0acb0000000000000000000000000000000008a6890e5bcacc13e116e3fe2d772ff49839803e4f81d6b088ecb7835b1ed44f2bfa04de1d46dd352346cdee71774e37000000000000000000000000000000000e94fe40225e863b7bdfab4cdc0c1c8d1399554ebbfa3f2c95ddeda74b3dff03d5cc78e295accdc9f02f3f89b4953de3000000000000000000000000000000000b23f2912fdc7a5fd1de69c1f479228f8ffc9f97c40845808cf17a6fd8131ea60285640d32bcd64c9be71d419aae82fb16aa2cadacb129598aa459bb2e6b7fb26d1bcb7a49617b6ef8e57018c3db1f510000000000000000000000000000000004c6f5aaac90132b2d0c6a4e70354ed2e724df7c3e6298eb9ae4ea92e3c7981944c89140c52e893ef2edb2773ab36bcc00000000000000000000000000000000021e813378be9ec30395b917ded5a0424fc7eab0abfdcd2328f725bbd6a1dace0a5aadebe40e10470df0c09b3f4b68440000000000000000000000000000000014e3fee16a833f8c543860ca438d763f764f488463601741a2331fa90efce9f6d54ee0fb7978460a1ab838039d398918000000000000000000000000000000000dec8bb882fe6028a4155e6e2bf48ffd314b5519dc4560f8f7410209214c4a8e37b2b36facc53f4db11ee63ff11f9f228c02014d5392d30863a12102d1c9315839b5611dccfdb489207f9186625138500000000000000000000000000000000002d107029bea087a2d53b6b371aae06c695fa85631450f4ad92c8948b09ed568b28948f80f1455cd22e2ad44697290b00000000000000000000000000000000002fab10cdd8bf17a633c8b3ee8ed2ce783f64bf978c384fb7dbd7e4f0da50b65eb9530365d982bcc17ab91a29eabc065000000000000000000000000000000001369237fb3241ac291a868e6f4610a5103d93aa915e954f18bcf348ece1560a12451723b96ad5fe162a6107dabe1c986000000000000000000000000000000000cb70b7064a2f94efc86060431ba4dea38bc64822efa73c76f3a4500ad23c452c8f2e72713b066a45bfa49559d14a719d960ff678e1b46ada4f866adf354ba8c1514df10ebe7d88d2c8de117ef5ea2490000000000000000000000000000000005ebb9c8202cba234851cf5e060a4114c6fee0632f37e0c52aeb852637f362ce64403347d336c32617cc59f23cc7c93e000000000000000000000000000000001126827b6a0a8adb698854c0089276861e3cccfee420512f0966df78ea0d9c55e85a0536f14ad40e649b8fe4384c836c000000000000000000000000000000000998549680649b294d506c529ade746aeb087f75d62a246b7abfb69397ed67f0f2ccb4811219b35aa894b2f87e3fcddb000000000000000000000000000000001027b604f877ade32df8de6162251acf2751a9bd770c21f22dc819a4f5515bb276a246ad667fe7881965f0b083d1f76304753af76295f72295645243ffc87ffc2110c9d8dfd20b464760ad965d7a97940000000000000000000000000000000005d1484bad44069b16d1ef4e9ca1db70ec6cd82eca645c2fbd4029ab4ca33d79780ebc144d8774d82518c1fefaab38530000000000000000000000000000000019abc7063361ed64a5750b70bd59283e6a61d55d49d8c2ea2f1be8ea425f040d3865c399a66c253bf38355360f06cdd40000000000000000000000000000000010a97b13b3b579ab5f7fd9801d9e4fc40f3b2b2acb9f21bfcdc6b6a3168720fd0abc2f77ccad01be6a6e268fddf3759c0000000000000000000000000000000004126b5454050d761047e5da23c0b2f9370996589c04f255a1ce8ef37a3a7c8078788a0125e4aa86aafce8df33f322d3d1b8760cc40d093912fb073c5012f910ae90f0a979cfe6d81c603adbb98289030000000000000000000000000000000017aa7a3f1ebbdec6abe12abea12ef50a3daabbf96a5f2ebfb517885f0b7aba1e927c682b15521529cb9e1f87c59be99e0000000000000000000000000000000016e23f7effbb9dd34ec1f6974115e7f0d23cc4553d86e6d61a0c98f47d09510e06b3f987c5bcf4bc30e20ae9684da74e000000000000000000000000000000000f3905dd4f99cfcfa6152db53106b4d1f6e24518a822da9388d8ca1dd654a4b8315697328571691f105d1abe9aad3dae0000000000000000000000000000000006bfd10d33df9326a55b35aa6d2bc3e831d4c3b5959aaa35613156e5e19343b74e34ed2670c43ba1a45cd3d91f055c9aab79d640b042664b23667d6c60ef9a5d59de72aee57a78d75752b350ce56d8da0000000000000000000000000000000016ca071d741363e7c3297355e49cfbdcf03d419813ed7b329cb2b2a26fc6a46cc52149ca3e9ca3ccd7284cfed97b985d0000000000000000000000000000000018da360fdee88e806ea1a61c01e86687f8e5359730c36c876ad2acb0297bbc1ae13d790d1edaafdaed65db9dac02a74d0000000000000000000000000000000005a46e4572f667b46aee36b8d377c249de25e797b31b822474aa647ee68cc7d40b083fd0a1d938e2b8d85508004c73f40000000000000000000000000000000011701bf88d4287c98996ea561c1ab2f29a5da9138338c7c7539a5fc8355efab6f58e240df4b0e0cb7f01df74bc8010501d1a2965e995bd4380d4ec52fe8e65e7fd99b1ca9f4f0c656adf7051c4b9a99a000000000000000000000000000000000576e79e507d250eb4040197064b8898b0142b3a2551875935f91f22705bfec6da156c7858fbf77028d4a00957553bea0000000000000000000000000000000015d39a325181d6d1a809b1236f4a1ba66a9bfa6c448470425aa5c8ef9fd00b5481c51e8752088dad62e928b3180408df000000000000000000000000000000000aafabc2f68a4933c7d734660e422ba154e37dd90114272e948f79db4ca51d5ca75d504cf74f2dd0479871d69a08386f000000000000000000000000000000000b017c731f63bbaa8fd0b0d9c17140060429f515d2e85a938d10f6529deeae4818c29b9a628802d0ffbbff720339b7bf2cfbf2abd851d2c1f55c56d4f8b11b196c020c2584cb03764580d410d66784d400000000000000000000000000000000028c4dacba5f33ba66368c19491f4baa6aea4f309afafcc8f464f2886b1d05b6397142d02f0295fd50825819621673a1000000000000000000000000000000000849e1b630e8db8ef039f280f8d401957f807ca90479745b68c3db1b5ce3a02fe2c099ddf9c387d7ed76ba75d6a9be9700000000000000000000000000000000013b43fabc3d4df82058db215a69776ed5dfd4c773d7a013dba3b4ef5cf65e25f79d7f76a06ca99132d6fd1fdadb59d400000000000000000000000000000000072cde8eb3d3e1a7f7e4a9eedb8e56f5e103db6de6ccf833f818f02a0706b2043d4ba0d5473bbb6472e8aeb28364e1d8214edaf16742762baa58a3d22d5bb2305cb03a1326adc68adcd268428f82a1e00000000000000000000000000000000007a33b95f42cb1d1ddeff3a199ccfd9a5d47c9fcb89dc09b5b3f59dde2b47d24ff29931920b76ecf6deacd70e83576970000000000000000000000000000000014c0a63e0152f06cfc32e6034b7829f9d9d09aca0a6ef821dc61ae8d99b77d76c1b2fafb2a14938a82ec72c4041ebd9f000000000000000000000000000000001433135cd913b05b3f58b2e9c1a3bbb951d2cf6c92fddb21bd5e1d9c44e464d5fe98f0791044d56e50b81a83ef6cb271000000000000000000000000000000000be12ce3bc47bf69a13762343b5e39c2a2f285896e5d1b73c55203cae2f32cccbb4f7b8230b2026a0c8b2f63db5e5bedc1f38916d6bdd5d379967dcd058ebce5887ef2bccd5fb7c2bcd758e374a195e2000000000000000000000000000000001494984d478784b2ab3ba27464109f99172033fcd5780a48fbd5a2144354157f6fca2d70b15b0081dfd306ab4239cecc00000000000000000000000000000000078aebc22025af53c6542abe56cf72ce5eb11d3f19212a0f7442d0a0df907c8aabe0ec01d1245ca237a691e685011bb8000000000000000000000000000000000415a1804a46f4595014ef29b12d99b89600aab1d98352437ab8342abf479bb2215bc687532e75f140918b3d030ad4520000000000000000000000000000000015e7b0dae7e3e80eee3c7a9ed4c739288ac2192f7d80b2c8cf9934cea5719081803b207623c771051d7694e705744dbf1cb8c8303157f23987f8a2d206f3add697b9d0a303393008429e93cd35711f74000000000000000000000000000000001470f82372e197a21aaf46cb2bd3c0b77c3428bf2ba073311e75eb65471a8164753ff1d989560f1ce477952bb6555200000000000000000000000000000000001645b5e5b4bcb5f6d34ac841e3a80f09a86a5edcb7f2a7e7bf549b022c0073e01be82e4c9e5c8e8de76ba367595639af000000000000000000000000000000000b43f6572553154e2530fb448d5bf20c3a182cc190149d3b1d75b60e45baa048f44884500fd02c434f9f7eac01dbe4170000000000000000000000000000000014adef5a52d76a267f87d9a8b5e9f570e7775ca4f6a55a5afbf80baea311b1866fa0689271799a654eddcfe36a6bb64c61ca9ab9c3df673b7ff8be098cdadd8354c17becdf82e7e99ce264174653007a000000000000000000000000000000000345a2ffa21eb06fa1d76fd81b1239147688093c6a44a40cae37f2af26add812884bed3e8b4643675b1a45320c64f7a8000000000000000000000000000000000c58eeb5ffdf886d6319ead9e6e190300ceb91d58abfb79c0a322de3987eee73ab82092eea8e1249e83ab67e33b303e1000000000000000000000000000000000763a3fba513b6731fb501aab39a4697f3e4de89125c6884f9782bfb73e6e062f17d34555a04a8e2959ee4e1a2ee284100000000000000000000000000000000024180dde2d23cd88cd29c8142d32435d0db57b8ce8e309701fdb963533c1cdc2595e3bfc01d8c0d08d594e096afb34a681a0861df30946911d789a5da1f5b89c38fa1a8c0407b608122a18be05955da00000000000000000000000000000000022d2e7502c4d9587df7ecdbafcbb813b1812d76655cb7f9f57418d5ac83d4f60b84a0ab5b53a5eee3c3954aa9fc70cb00000000000000000000000000000000083212aa1316561a079cb8d027bc8f89161fc828d050c8837a24fca6f7f94b6dbf10d6032fed895a427f07827deaf3cb00000000000000000000000000000000021552b99dc02a051ea3af1b1bbd0a7ef64088c3aef4a58b18a29ca05e1f442f8ea2c8fdb3642ee94c5df501ff6898f40000000000000000000000000000000001015a7987d329cd1eb5f991c270643a05b8e1bc35467130e9f53c5d96fc3c8336a00c060dfa2d3165358b51b6a521e56f0798b448ea0d10c84e2a8896f153b1ac3b84c5fed6a4ba6c932260bf01d34e000000000000000000000000000000000c19c3b9d7c7f520968d8531966cccbe6f0c3fa0938480ca3591b7489febdabd56a70ae55cc309e04d7acb3de6f41a3d0000000000000000000000000000000002ddc64023f0de2730d3affb695927eaba50ecb91cdf1f369a511a8cc8dae8913ada2d8f27a65e75deb9b8b648e4e2e00000000000000000000000000000000000311ef260debf2310fc31fb8ecc802200e11400909eba24b14d9500ff47c1c36ec540eb970c9262dac947b0c2053d6200000000000000000000000000000000199c19645375dea7602b74301adcfd9af259e1c7c20f377fd10d56b719f7a6e0e57d780c976124e0675c2a54aae3e0f5a8b7de8f34053facf1338b54cfbe38dad73121a0429663f484277af9a230abe600000000000000000000000000000000123fce6b793de0ce2d31f2c7c4218fb20f9db68946a7d57914174ea773d6e6fe1fbb1de141c742e0a8154fa1d81a91f70000000000000000000000000000000019f75536e004a61c6d7f466bfa06ad0c9375a1028eb7746406e7c71e551dba249b5c6284f635fe26989aeea69075b3fa0000000000000000000000000000000013088eab16ec77c7ce7e84236337e395690169a4ed7e44e23d233d36d5d25e6afde794cca2bee88fe749851a71aabe24000000000000000000000000000000000e627130da43a6ede3bd6f2fcdf008c8f5c7b7b1fa56cd3b367d3096317948bda115d732346e73b731d1921a1da6aaa18823cdb73dd076ad95679a9d7b11145c12a81b825477f799300d1fd761417c2b", - "Expected": "000000000000000000000000000000000e3b85a3d6628e097a3d962f3c9aa37e3c5be43faf2a12cd9830ab33c4a904eda23027735bba563d38ae5ae8b302864b000000000000000000000000000000000c92be62cb091056d981ab8872292017cc22ae4eeb0cee03a60cb5d57d37b264fbed2d752ae9dfd76c0bdde1f1dd10500000000000000000000000000000000019e172b23249a17924b890cda6a65287039d0c32b2c0833409816cb21ceb73ac95928234ccf566287400a2ed7d9de771000000000000000000000000000000001276e206235392fdf65e4ea6210d22eb7afd7783caa0777ff0af719cc1822579d5b82fb4c30f07dffe7d68c649b9e2fd", - "Name": "matter_g2_multiexp_22", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000a3d974770eda8c742e5d380482d36fabe18901b0217485141c3841003aeac4459ee28b280550e4643d0f50862bf2e2000000000000000000000000000000000369c2bf3beae4e8761f6c06d9bf5261bbedb177e609c81c9bd81ed0a17573b6e10e7f0512e06109cacc3d483918ed9400000000000000000000000000000000030253d0a050986f49c77ee20ea8e3e07de3ba72c39ffda877bcfe569eeb29598588f5a7cedd9e2e34491a059ac4e707000000000000000000000000000000000ce201f07353bf82ec894ec66c7012d17f3c7968b28b45e88f091510e1646380f902c1c5b036084f9497e9a91476dc2c9f2e54f21b7f2116c30d6e444ca82fe800435cbbd72a98a6d22bac92039c54070000000000000000000000000000000018f493dadbcd93df2c614af310e5aec4fac9e502843b8ca8c3de739315d9e9a380f826e2470c96bffa8789133f458d0a000000000000000000000000000000001768f8c3da107b9ac30a12b99f2f3a0f21483c0be334377733cee6024d85af91b03c7ea1c548b42e7a7869141816917a00000000000000000000000000000000076cfc99c16c270d2f6e34aff84832f9ee6493ab757b6361cc921823fe9c30f1c9b1664b650548dba767616bec0fd5d80000000000000000000000000000000006c5f580c9556ed31847b1a3527ac0b5b5f15b9c9197d3cff061c1cf72dc5c96cb5fe98535a4dca8c4e20c8c02158466c8cecea241dd6a924c9b9cc3d390fbf40ab897208ce9d3e4a148b2c30c25e7eb0000000000000000000000000000000010e2d7eb4e874a9c72a98e4c36701a9fa11051b683ac8ab9ac20d14929d72ff7b92a9048a11bde92dc2696467fcb48e6000000000000000000000000000000000eb29e621e9d0af8f661eb1ba90b307eb542dd84a486568f85e19055bf7b8f0a76d34acf276897a01349eff2c36e4b43000000000000000000000000000000000b5f890f22658b207dea2d721d90a8f5991ea2c5ca06b8d1b293f60959ed424dbd7052e010e594a5ee0feda1e93bcef4000000000000000000000000000000000082cdd4d8452078e8b853f196dd76505ece5e98df3e6a8bbb21f422755af23c5ab261accea48d8e4193d6c884773cf6e428fab2c596f23bc3c9e9855b74295f52caf73cb7371c93c65370583f7fef4c00000000000000000000000000000000077501a457d5f0946d25a4c5eede1b7fd80d90d502bca47d8cc40ab2f9a6d827d7323e7d4035f3d32b02401141f0a89d000000000000000000000000000000000985410246c1db01b42728ea46758906883586cba5618b66c21a3cf58cb98e7c6e0dfbabc5505d1d11ca9d047fb6d25f000000000000000000000000000000001775f4008f688882d02355b6eaa1ab108f239890f71238b36c76228cf2f575cd15f15293a62a72f6ad0ff17d7e8ae79f0000000000000000000000000000000004b6967a5ee180d8b92e95c5ef26baa56d8509e1acc710237083d19269c1c5a1f2d1680e85f0bf040747be1d301300b0f7d3d755410f77a0e4b2fad0f184fa9312b559785fb04c6020432465799ebe22000000000000000000000000000000000fee170589e8a3d3fdd93b536347af5002e59e8ef2ac8327a7e9f382560ee9bc36b3f636a3f99fba8be7b5ea3dfbcfc600000000000000000000000000000000032380cb6c043e3f9ef7169da12df1c6529d776b049c7061df660df841840933e514eb7ea3152ddac38daa2c52d66191000000000000000000000000000000000620ebccfd931eb70ec688110975ea24b7ee0f9937841aa1b7bf4f45af88b732b76a26299f0fe48259fdf08abefb4314000000000000000000000000000000000dee6bb8c198363fa4107996331aac07216b82208242c73736be31e14e4e04d97a56a1c22479dd94997acb0d32abd3b0557b05efdd02ac9d8e1453c82a321d798f3106bd18764140faede610ae01fa80000000000000000000000000000000000eb60e98d6cb4e4b3e58271d47261d05be892eebb9a37f6831ff19d0bf2fc235e655f0eb9b01494868bc082c58ed82d40000000000000000000000000000000007254a64a0d94340bcc2b0142faab2d73e8189dbaf52ad0c3a9206e802193168b8eb03cb18b0e4f1cc95b98b943910db0000000000000000000000000000000001e0051fafaf454072051d2aa9512ba2367778aa1617cecf6a7f989d69c7627c9070c349d363f56711f172d43f5730cf000000000000000000000000000000000f4141c8a45448fecce09908ddb42f7b5f6b5bb53b9e1ede0417bee327644af5c98470e8b5364642fc7435f84be1ab443313884abc4d430c06ae843d263f2efc1bba35f6cc270de05551e1f86096bb7500000000000000000000000000000000049c28e0bc677ccf54f4cb46e953a057ffad624752332fb9ee5295438fd5bd61abd2199a0bb729bb7678cf3077e32ec10000000000000000000000000000000007138a996356ca3f5d63bb5a36dfe901254459ed515e18ec8d91fa747a691b40a19878d9a6f1dc74e4f18374a399d38f000000000000000000000000000000000a621b36a3cf04e6a5cb699fe4ff7fb8b3361207186848e81972fdaecf667ceb35f413bd68772f7c1f77c1d3f43a3d610000000000000000000000000000000010becda5a06f3f077218d4387158e4a1ca5e0ef24d4ed304723ed5dd96da7cc9325f7e4ae16d9d6c348577697aa6017b8faea236e782a8fbe27ab15f051ed007a61e25247f1f259b9300974f521f30c800000000000000000000000000000000163ee307e0d0c3b61ade05a022ce2bf315d820ee8ece60f93d63a150e02be843a2eb2240a4882c29be2c7403932c348e0000000000000000000000000000000001fc8e9ca23e8dc8457df8f255db3b434f52cddaf05819dba7df1c5bfed438f756c8b57442197af18bf83fe9ee2b765200000000000000000000000000000000109cbe5279ccb592bd0b33b1a482df53459c48cd0913549739b784ba7ad32872377c2e3924c4d45064b0cc4764220513000000000000000000000000000000000d789795d556a37a375d83120a022f57e26da6e6f9aa3e40e1f32ed04b50fafc4d40d0b9b20a26e4d230dd789e20823013994f5645c6ce83741e48ae472674921bb2d9b8abb7d04ddbbb85a3f2f7f090000000000000000000000000000000000960654bd6e6a6b2f7d87c3c4d6e3fe6c684a50b62f7acf82a67075139a614c056a41cd49769960e229cf07468fc2dcb000000000000000000000000000000001727f2dbcc8d889127060de0079207eed1e094259b59a20fa42ab2783bfd176da00e61a65709dcd60402398fadf30710000000000000000000000000000000000c17805a01e64c320601e0ef521b6573e9c2eb354157cf0412e5c2b13f826759310907c4b77164f5899958cd30f78c030000000000000000000000000000000010fb286ce797c0429ad3385c709259b55cc962ae02c814e537e5261e897b7ee1b7c660273ec908110f997b166c14f5c181eda24db328588e8c670ab70431ddeebb0749b431bc1bfbd992c91f35d59b180000000000000000000000000000000015d96a0f988f4951206aeda63af85910db49ab817c83e218ec74cbbf5f34f81279d8a3f2fd1f3000f73b8c5550af3fd600000000000000000000000000000000186d2eca1cac226227d8981324859126864b84e8dac563b4d92357591c2416c93989cfd9e1ab6ad257dfeb168d829a09000000000000000000000000000000000a8a7247a3b09583cd2d4949721160573f1f88221e6eae833128914555a594f21a3fb2bfe3b1f01f3dee90f7772dc97d00000000000000000000000000000000132361ac1950756549c957c174cab9ef586eb2057a4eb22f49252cae032975f56eb0cb7ea70810afaf5716afde5b88015bf25b5070829e3d5a66ad24ba9930f3ad64767c51e432b51bdbe2fab470688d000000000000000000000000000000001328e22bb83331adb09dbed0a8c58040a3564fcae0ec85794f26c077de69cc0a7555f011e028879cb3aafac4dbecab33000000000000000000000000000000000a93db348adb3886802bab1e993f5d7275360a5b0466845055d5274e44716f3e1d03a6e1796ed4de4c157dc8a2d92c39000000000000000000000000000000000dc0879a8e9556b7d9b6d5dffce5e648f835f10acad3afca7a73b0fdd5d5babaa74a1ca80aa4f6880d9b015501e218a20000000000000000000000000000000003f7ae8207de4a179ae48cffc8c6e926455e46ef9e109c08be3ae7401bd36e0876642ae9ac4fd75a74c67ffb7790e265a9535c082e11b366cda0000d8ed0f92ee30fd2c4364c163a718518321c5e85d2000000000000000000000000000000001078f43093602a2dacf9b5dd7ec41d47bff02e0dd27a996b58c73febca06e3d977c2fbd73f63508243696ab5d8b97b980000000000000000000000000000000001841869086e850ad97b3122fa51c437113d2bca14deaef5715c354d3845f6829f6aebe668844352d5af3509c0d8da7800000000000000000000000000000000047c42e83194143b9e977fa1babf80d455fc86cf6cb491ef8306a1c32bbf8c868e11bb3308dd5f65fc2942b3e49ff5c50000000000000000000000000000000000872ce87ecd22b39b14c9036e971a562d51c5122bb10939cdfd1945dd1445ac9f5de06b70931aa5c86cd0fda51b89952c4cb49adce0292e259e92b229bf7965864a945de86eda3ce0bc9f1a6dc8b7b200000000000000000000000000000000157820de2a134081eb47b1800ec72630348583d77d512b4c6a8c8e581810471a2f57a8eb6b0af87a91960424009ff124000000000000000000000000000000000378cf11b0a2848b06412aa754ddbee5660730001db073724caf902d4b4894959f035a8838e28554b0efc2388f2b4f27000000000000000000000000000000001301d15f290dd11c3f8e53407195e02dbf8f13e4fe25fe38e84740753b5a0032f8dd07df3ce46ba424f6772b3aa66f4f000000000000000000000000000000000d166040d457187232f8f38f2beb1e0e0864105595764022c282867346166e46eb789786a7ec7c00b0446207e9ac1ec05e927f57aa85b2df54b4bddaa041d43766c8929c8b9146d723806ee0cf042275000000000000000000000000000000000793797c5bce4b1cc3bcd751c5ae1d293477af96a0e7c6bd392ab4410f806a53088cafeed51754ee7e60e61dc200ccb00000000000000000000000000000000019d595730af1f3039e37494b86a638a528d8bd24c429e3f8bc97076c7463e7f2618e23bd3f300bc7e7a4674f14f8295d0000000000000000000000000000000008e245c7590888fd8dd58f93332b81f48b6e3acd3cfcf5f3b28df654eae1172f52ef5a121707aa9cb111b0b402d1bfa6000000000000000000000000000000000a7c6403659e1a0c2dc7cc2e9b57a452bf553e96388676f4bf4a6e26b3ca2d3cb82006850d8340dacd65aaa0d20e6fba606ee8a5fdd9890b8017f6c432a45517d65328f13f3a2bb42d7115c02929db7a00000000000000000000000000000000054c37e8acadcec8a795619647d4cf1081a0592de02bef916f847936a1736e74cc3b7ee018717495def8b4ef1d098fc9000000000000000000000000000000000291d89d152b414fb5e7139d6d0bdc7b5b9de1fc44b49f895ae08718b631f7652bb4a895fa11149b9a9db30c344108ed00000000000000000000000000000000107b30992ced35e4ba874e436bed5d88aadf0a0c944ca3eb8319539017bdd652feb7483ab6c705aa17e845723b2cb46a000000000000000000000000000000000895dd8e04114fde4a4cf19925004a72f617f2ff146dd650a2cdbeb12977dd2b34ea7d655dee16ad9560b144b81212f5c1a77ccb4b32a762d60b37827ad6c3448c33af6af861c131adb5920ba3c2b85100000000000000000000000000000000005cea2e036a8ce057e4dbe2d9d786eb759c2a75934580480f78d2e228c3150a0a1d8c95ac5013aae3ab6e35f524d37b0000000000000000000000000000000000e18c18884209f9e4fb17431248a5f8d29c616a58af16e949f4317c2e117b80d531a39800dc70f6b161b98ba040a8af0000000000000000000000000000000007c42ce885d1bae906128589b72f2e6c18e4eeacb78c853e923e6eb785c073b6490b2f6b3dff2276916d96770ad5019800000000000000000000000000000000132d809c37c341eb0304ec933a6b11bf9ac0d2a13ead818ab6ee03ccc94160b405066381dcdb13b6ee3f5dca48ee10ef47cde609c38eabf457cdbd1e0c5366bf523dd5801d66a0282bc187d80417f455", - "Expected": "0000000000000000000000000000000009406918e2dd6f06f4782ed110e29516a911f47133ad8adc58f5780de916a8973ad60e05ba931d66de7545a92f388c20000000000000000000000000000000000041cbd52cad2a5f4c8353c7153b5711ec23fa8bfa2f34f5e1a16d8a14cfd47c237766880debb992a05ba9ed0353beea0000000000000000000000000000000017d4211c827379b310956371129011a92d62d11f0ee5b0cbad9eea2d3f2a95d364717713fd0c544747338725adf27248000000000000000000000000000000000a61903fb81064614c9c6894c7f3954aace7611cedf6bab8e751f0c203bcab827d296016947c071d7b6ccc742e28ee9f", - "Name": "matter_g2_multiexp_23", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007f90813f8c3eabcef04dc1bc9bbafe1dafe220e2db24e4b714aab2b164d7ec9df3e6a3f903e8b7b96df2ad8297381d2000000000000000000000000000000000e34371e51c4c952a0f38c4aaa5fc2324971ade310af2f36ed511fc5fd7a602a551ef77775fcd0f1fccc718710239561000000000000000000000000000000000787edf7a6ed6b50afcd7c0d3876d8919273428bc49833e3503f650e48e788b15cd82eab2672f612025d796bb62d72bb0000000000000000000000000000000006b49e631ace4f72c959919df5d64c537537ccaa3d1890ea9a1d70f9eacbaaa2ec361edf2d4880c9810976c6073028bc3c79fe6374bf8f91bf7851ff935a124b54fdb5db498d2d37939fcd43bb93d29a000000000000000000000000000000000cb63d7eef2d6614d1f629756b3a619a221033207d1621e4ce4791db4248500649b91ff07cd2f1f06eae3a9be5b6af080000000000000000000000000000000019aafbe56da1569959019033e8cc785c9b98bba6b069603969e7ff1150f023706b461913ea7949306a44c3b7d199e86e0000000000000000000000000000000005cdc3a7004f7a7f79ffbf4c4ba7c5dc30ecc62f270a5c231406fa63d82fc64f45e94779cac851ff8443040fd3b2ea6200000000000000000000000000000000040f30dc98e8668194c9278b189e0c0f7b76a4c686ce26a4a96b93190938f07c5b813670e206eb6b5da29624a1b6314ba59fcd2baa47621ebd90c5cd12b89f2a533ae86d537fbb61a14b1a80982c9257000000000000000000000000000000000a5a1bc231f803ae272e497f812ebb663c2ce8b43a366717fc6349264823ca93e29e30762c1a366d8680f81838907f59000000000000000000000000000000000a88fd59ee380449d632d7e1b926210d984d5298fa807570a63a63828cfa55c6e2f01b7745848281795dae36e562181b00000000000000000000000000000000025ad34537909e07beaaff09f22e91e76d93c668d1b45cf6845ab8ba0129e417b758e85a7100a31a9037e307f454bd370000000000000000000000000000000013590106126231b1c616a5dd7aa7ed6946aacdacec963b507907950d6ea11cf1f5b59f819a43eeebaf51a1faa7daa8e719ef9fdfc5f0c4ac41255eb172d485317c124211498a8b9a74c0bfda15b986c5000000000000000000000000000000000938d43b9747c926c3e2dfaca2d6f1e6d61d5a621ae08c66a5baf33d9241771509689f9ea7d75af607d76b66faa8fbc2000000000000000000000000000000001889a48a74966b9748f4a6128dc3d75a69499db1ba1bc9aa3a9428f0efa898b5f78a9e2dae942d3794ab3d1157a1d305000000000000000000000000000000001129c9bf343f476541980b85229c5c25289ca62173e29b75de431b572c8f01f64ec1aa4625dff9e7df535194c7f4e6e7000000000000000000000000000000000fe95c71f703dcc71cf409b332f66fd69c330758d41832236a510ec4bd9a28c4732434d4c3f97445e6301e3070153dbbb8ba028831f429d027319a92fc0f30def8b97a43da456ddc79443d9f8df72cc10000000000000000000000000000000007649efeb3e0bee49b9adb13f8e5d7db1c06d7fde08a3f3082194153bf4b3615aff1450e47fae88ac93f55a389a319da0000000000000000000000000000000008334731582fb1b6125d7ee1da0124fe88f0c70a0a3f6188636976c31ba6a72beed927fe598386f328e4ae534729a57c0000000000000000000000000000000010b57d80fce5cdc90bc93b3bc7a1affadd19fb00aeec2ca9a6287bf4e40fb74616986a44f2f7d945f58501a965f37f3000000000000000000000000000000000180dcae46ee41bccd422b3cc2b34cad26f6816dd08ba51b2f12835e7439ae2d46933de28ac04bbcad68a188e7e90ee8dedf8a6d86471f58c69c1a5e7518c69c34165e72ce84fbe0b7f69d9c2717e5d4d000000000000000000000000000000000b419b675ccee2509daf66e5da4031b08792e1181140b30489ae21f7925305d8cdd8a104580ae5938586d6b8e74f750f0000000000000000000000000000000012e070ab7118991a20b27f1a87fba1f5815665d76269f0d3d460a6b701e57ffdb4fed2c53fa63a3121c74f67e770f31100000000000000000000000000000000124218ca85f235eac3471e0acdabf73f79afdd4bbc159c1e34c641b97f03735e4c3430264f2d94f640486488dd1067380000000000000000000000000000000011c24f4fa1862779f22a628edf9d3cebe0f7593964b642f889201ae85e8fa01e00e48355053f5a7c6d920dcf6a7ee1d60dbaac3f5e25ca3d1d50ebb31258ec4450feca1e02c84672ef15c49b4de2cebd000000000000000000000000000000000266bf0d9d5a4fc713dc0fcc6ea6edae0b326e22cd97bc49c48a7ba398fc87d7a0c7141ba24d80df454de66c2b5a55fb000000000000000000000000000000000aa8f95c7cd61733b0a260149d6608a73d6c1f989afa8cb2aa4098e1fb5a66b4ad5a5c1c4d901aa79812385fd507f02e000000000000000000000000000000000a6b4929df13e1fe7f0a0cf699a7fbfaa97d7527cc3ea1f728ba59def2e75fcf3490199bd42e93b7d47985a307add07c000000000000000000000000000000001719321981d2085ba31c9fb131d6b79c7df5d10d6ad0b5015454329697860121e781093fdde1f19e897dd6f2c272f87a109ccbb8fcd4d4651b84f4708799d84ad0a717aedaf5a76d2970a7b93bd23d37000000000000000000000000000000000431002c9926aa7d2b06412f544a868a7d48fb5f077dfd098febeeafc28b876c434daec809e5cbf50ff2395ae7e456560000000000000000000000000000000005a15f713b6eafb09495cfb1c89e9421515a07a99ca0f208883f11c430ffe6f2592dbc41bcee5db36385a26f67cd26bb0000000000000000000000000000000008dd30fdd7767486844967c5da0803b52282178287b8ef28e14f07b487132fea3a82d86d414b4d0a25b3dc538be11b500000000000000000000000000000000002dcee67e2d17b3106dcb9f4117456a037ae1996e8f7a09b179baab1ee8345c6d01eae554d3f40da86bd79a04702fbf76326fded2b8a3fbf7637bc25bd201d20e3d4d724806cfa678ee039a39c24e86a000000000000000000000000000000001629fcc374e99fa8303a715fb5077f266b13367bbc0098b5463d3298c0892f83127d6b7f751446575b88858bc742586c000000000000000000000000000000001100783c10618752d25c235e1e76dc64db94adce05651fb8df0a5ee7c299d35b1319f7009b857892ddf9e90c91f7d23b0000000000000000000000000000000000ab6996e4935131becd5df288dacfad1e69b41e200ca7dc841ecc180a81b9d2ca14fc8a76a4e7bd6f924bb9f473de62000000000000000000000000000000000ae9b22f8dff29e5e0a2ec5b5641f53fb5e1ca03130b49d0c26696ca4b439a9d998d9a364ac9cc5ec52df699318cffeae005efa8ee75dec8a013029292976e107a507ec09e3c34fb4baf2979fb759f1d0000000000000000000000000000000019c557ae1c12ff8a7c00b7c9e4bc3d65c92753549c193311a38a84bccfc090052a2219461a9691affe2d67ea4357cdeb000000000000000000000000000000000cd35c5dd126bd4b90dd671f29953c5a49a14b6b3fe946991416edf235c3eb3d574613d27b05cd879518fa7dda3ed39a000000000000000000000000000000000224392063b0825fd332bbede23588c1912e7670a013a99da5507f650dc4284431698a5b4e8c180269af8bb30e4fc8450000000000000000000000000000000002ab8d3250d4bb8ceecc8ca2003f91420d0ef8a7dbc2361e5e7fbfcb59471a4c525856bf796a2c2608d219d215cf83fe3917f8baf17f71222166cb9b6c4beb2e57d0d054cba3f7fd3a28cd3dc4b409490000000000000000000000000000000000911417908c2bfe4f63a388f699b31b47df1ea0ec289ee3f96ffd0c71f3deade00d1841aa56b4bebc2adcd3068adf920000000000000000000000000000000005467c7e58e82089fa285c28ea22c759c7806d86fbdcdcc8e09e847d6330922a61bc331ae3b5acce777b7809ca98213f0000000000000000000000000000000010f376fb47933b1f701dd81cebaebb2d8d8f5510a26fb3e9e156ac5ecf2b943c5fa2812d52da542e6c335abad8ecce3c000000000000000000000000000000000dcbf467432acfa4eb9ba11a7cdf02f9110f44ac371128ff8f1f98fc70e4554f057a4608180bfa54d99fd2da010594f6f0f73e1b62561f5b0fbc409e6534ad9e37d1c0724b35cdd3f94bf6489e500fbf00000000000000000000000000000000179aaa7119f6fb986714c03b6db16f25eca7172d24cbdd318bebb633bf08920f9e2a8136c94e3ec7c19e57ab51531b3f0000000000000000000000000000000005937c484213ab5b2ca8ed1c5c90e8d2a2f1bac044b88c04b301ff2fdbe67dc4ea42779d919ad510cabfa2ccd178cd9f00000000000000000000000000000000183cc23fd64514ead63f55d375a07af7cf2a56aca64a887dcc542f8a396468a6abc776170a5d4b4bbcd4dbac285e7ffe000000000000000000000000000000000ce12228dec2f84219904d9ac7923f122a99803a9b34749ca68ba385c178811685c19a492aca2e1123ee82a8a9cb90fc3ea24fb6447f2493c78a267daa158eabb70c1b60af8175d0d4594c99122cb4420000000000000000000000000000000009612bf9130e17110f8b15aa6f3317071daf3433bf6d008c383bd5c2fdc7ca03f25ff4cdb483de3c84c0ef9e579f38c6000000000000000000000000000000000c40172540a7e20eeedfe02c37aabac07165cbf04830f20fa76fe8b05c826e7762c9f7567a0fb972212bf736e627948a000000000000000000000000000000000f49e5b1929ad3ed5c07670c471710baa24e8478a50f72a5b7bbc23a66cff91d30a3d68961fbc2e6e8003d08196f325c0000000000000000000000000000000004ba098f915ba9e934384682648ed8d4e1cbaae60d596655fcd9c05f4b049ba0d278730dba5ce3fd4892531a3153bb955ed307c01d9e29a0571de07c62d5fcfc80749f02b8dbaaee9f69dc9263e99188000000000000000000000000000000000449b15ecec6d6fe5cd32437b54218f62527157aa6344c635fcec8f8305c8b6e44c93105984e0832536237606f07792e0000000000000000000000000000000011e40e8aaf75f5ff8e4040f725ac27693d7b24805a2539ff54b3a6e90c048875ea9609fb8fb3d8de63ca1118876c172400000000000000000000000000000000006ef2a24445f728b53cbf01e5b076acfa7761a84d8261cf1a1b99cc32f330f32fa5ded83d5cd51cc284207adb2451ee000000000000000000000000000000000977966380e772670447b15ad9917035273eb71a21c37607a761aaec808909fcfed50679769aee1573d73cd241de6624877f31ddcb55d961bf9bc09903bd927451390922d647d589302855141cf5cef500000000000000000000000000000000074e475c0ff1a51a24be3c964c45c41f767f890dec82712d92a965be504fee43fcc6c0684b2b17c5b294a3eb7ceff1cb000000000000000000000000000000000597b7dd287f3fb27e35a9e4e1718b6b1a4addf9e95e93aeaa25aa34023669368b794a08fdb178d9bcda2738534d1962000000000000000000000000000000000a492d648393bfa317165ccb552e045fefce5b3444d5ff770f43a08a68efefe7fce1216114ed1495cd00f832538198180000000000000000000000000000000003d85cea8063828ff025ba599bdf1efe0412ed5ce06ad5faa841c6400e4eeb6aea1470d48f4e66fc768d7e7bfebedb37145c1442ab82241f56c27dec2cd4dbfa9fc3cf1ab72bc521ab32a82346f8f6070000000000000000000000000000000008ecc3dd40da2a7a348b4817d9c84242f2f07c5d0ef810dc08311e9d4090d6d96d68b6c725ee6c24de076c71754bc4b50000000000000000000000000000000018fb3a1dc4e0dd9227fba310236a6db7953f0b716fa995b928a2a8de38edb97eca09fe2ab385037dfdcda2ee577e677900000000000000000000000000000000062fce7fe7810273a80760d9f4b3be9e7c821f38ed3e075210d3aac6aa7a763e3cda56465f88b34540b408ac850742080000000000000000000000000000000006fa94466cc47990a80ae6a310ea765590a0e646b5988925f03cc7e30f04fc0a8044b403212290b2fc46c77e84a9028dde4d1470f6cbce027465b4dc2a3deaca14e34218910aa76cb45d47139b31df88", - "Expected": "000000000000000000000000000000000f41bad0a932e28096e51482c646dbdf294aa7b91e0ec258670e7674864765c76989a936fb440bfbf4268a49f450d3230000000000000000000000000000000018282b76521db98f589b1c14e603b6f5d27af357553bca761189a38a944a11c66480f7ddd89d17e4aeddc8d78a2b3a0d00000000000000000000000000000000007efc4a90dd97f1312047ac78a3163dc014c42a44c7054daeefd5b72cd0488832cb6396e02ccff09e4171d790954fcd000000000000000000000000000000000e790fe8323fffc96705a42ca071532d5359641ff7cf8714789c9c578717a054c811cdb581df8b6a43729c6c3e3255ab", - "Name": "matter_g2_multiexp_24", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001304e0ce6a4baa6e0545fdb314523fc91f73eee157249b94f284ba7390b12b23b1c849c45a563ac82b62a2c48aec24e1000000000000000000000000000000000a2d0e9e222db70d49d1e85f587d35bdf5e8328aad14343d296f95b152a79c83a4858cafc350a5df1ad0194c49bb929400000000000000000000000000000000199efb09b34d0699eb4bc1c57fef9cc5d98453bf522c504fe7897e22bd0596a3a6c310eb351e15e3f6609b074b240f7d0000000000000000000000000000000016b69f12ce30ad1a65150094e29d4cd82fbce5dc343517ba9e5d89245ec083c44af9a3dad2169f713d3b01fdf70d20642576b42e0728db912a78eec2b7b4c96575e341e86a7592a07a660c11e0044839000000000000000000000000000000000b3ce4ac12861052c602e71906a7c9f3e2186bd2b6eaaf222d8e80b48baee537065ce78372ed936e6728b9642ba1fdb9000000000000000000000000000000000e8186561d23515bc58c77769c93db76dc9c62bb715b283cbfb71462451120a6ded736cd8a292a6799fbad7617d9aa84000000000000000000000000000000000368a6dbc7daaab0a786257c813b1a25c97468732c27cc759fb921cbc3c9a37a46d7dd0298771c447d36ef0a10579ff5000000000000000000000000000000001348d5e34cbe54e3a6b357c4e651acb82d2dc40ef9ed8bb89f0cdf0882ec6a737998f4e4dd61e296d101cbaabccdc3e779f9205ef0e3a85199c60ad9267349fdc7b6fba4cb765ab21750eb3dcfc48d8b0000000000000000000000000000000004ebb53c462239a78bf13f29856ddc4d78645c457a656f3cccec9d3c032ec19c26488f39e0f5bf0d38424f9e3a9bcc870000000000000000000000000000000002fe1949365831f7c38b1cd6cf2e22345c4ce40cd73def77889c214d1077d70e39578e8be4fe5998f59d47cca7917280000000000000000000000000000000001152f2df1512013a42ac056b75802bc35c1883efb345cefda8276c594b061a0b0f4a49d8bafa6fe251658ee76b2493cc00000000000000000000000000000000094f90cb386f7933b2ffcdba5e46e09cbd7d537c12bc223e76d3a88ce9063a7b3574d3306365d65dd4c6505f1dceea53300679b7be7c71224247e8034f5d30a63f8707d92d843a703f0fa93160f6571500000000000000000000000000000000169d9469c53e55768c9312680ee82ee581727e28cdb1d6fcdca25d0c03f3da2ad6572039f12c90b09cdb843bc506e07200000000000000000000000000000000174528257f6d3542f754ecbe97eeeea7d196ee4dd01852f6cbad87fbeb4dd7d3799588f17aad129a15549bb787468772000000000000000000000000000000000c9ab635bdaca1c488538c0830453ec6ab3b2b62447c03ff6ffd2712bf62e02a63c76c79d41644ea412e733128685c45000000000000000000000000000000000172ef0fda359bab149c8c04f583f4ace4d1b148426e993996d278f79ed2c6d3933d6cc5fb62ec4869aadc773d3084ca0454b01910548432a0f706818a98151e38ff9e854f1faa95ad41a7239b5cc4910000000000000000000000000000000017060fa73b58957d12b3996d67b7baa8b7f0943ad52e80e5c4f8830d33dc74c0a39e08594b647945b402299ca861f7b10000000000000000000000000000000001efdc7f783f9977392e2797a3e0bed222d5b661d056aa0c7e04a493bb9b18048bf72aded134941ece78d63df0a0868d0000000000000000000000000000000011355198320af05f2121939e6489f31e9e13b3cbb2cb30c9e675854cb8ec038f80aa2f4b6f995774b36f5f1b6a84298f00000000000000000000000000000000172e18c490d0cd5ba2449362c0ab296212dbe69ac25515d0f91941d300051320f067f946dcaf999554f55f1f616adc0f3685617371b27ba8898ce7f30776d817ff09ef68a9d6721d4a923ed244ae82060000000000000000000000000000000005854f4dba62d1dbbf3ae16f70792f1bb39f111309b454a6400d2916e619d4f70764ecfda7eae5c28cf1d178ad53fe6d000000000000000000000000000000000ed0bad1f5d69a0e621d137746a9ecc764931ab89f24ca827e0340ddc03571ed697f63e79cc58b946e8462099ce4b1d70000000000000000000000000000000011de76edd1cc2f9ba06b98593a24a7a011f2701b451ea3ccd04361ddb678e06d91a676e3f11b62c68cfc05242cb8a859000000000000000000000000000000000599726b5f5b93d414f9310383ed9414e4675d644f83ebaa63dceb2bddc7dcfcbc17c7aaaccd0ee32b0875952554b4e660cb5aa2a0cd1e8c3fdc06a3a1f6f9b6d52a8cc2e98c85b8e258f72d03efc25400000000000000000000000000000000031110347cbea2756b5fdd549d6c0b8f4036f5718d41dcd6c854a91c9df29bd464774be479d0efcb8a3f82cc7441a6c8000000000000000000000000000000000e24a52dccfdda3689c87395e45dbd46156676d9eb2cc09dab22ef7ff0acf5ea243ff117c82b147994d65aee8605b2fb000000000000000000000000000000000e0cd6ea0bffc591c13c48bca0782fecf8e128b0b842aecb06f803a223d32cc350db869b7a77f8e31b05f36bddd587ea00000000000000000000000000000000042ff4ab4596d610638ad23eea904a82701cdf61f9e2dc5832a70e11e717711a2d0e72f32f74706d385a9567426b4713addb1fe778c84242953db87d2307b40eeb776f17767c3a4311b5d2ffd738f151000000000000000000000000000000001517efd853800946aa37868b525e58fb488bb69755ccec806afca2d21bd3a30ba46c39cdf694ad0ca92841760437c3c1000000000000000000000000000000000e5591c339e88544660380d6362f4119c5596f910d4ceb96ccd4c4d9672efc50805b6fedffa0a48d126aae69b241d3640000000000000000000000000000000010ea5babb0de734641f63eed2eba6124377b5c55e429987917c0bd109d7904766a10b0d2dd123413816d0fbabe25050b0000000000000000000000000000000000efc89ee2ffa56193129062ca55a3350bf50e8fc7d586fae3636a70e3577987fb0f8674d383def4b41225e490d3d81528416b4b4e965a5f024723fbad6ef2f65a1381e70201e26ccb40188dc3d0fae8000000000000000000000000000000000dae4277d62e3f3dfffb80818a5ba5c371a48d73b92d69a168ebab897ae8be206fdf776e9f955136d7f7f7b2903040270000000000000000000000000000000010ca635ee2e49cd6c951d75ffddd11557432726d26564239c611b139329a28812afe21f094c0585675f4f233233743050000000000000000000000000000000012378b2ec31119e508fd9ae0ccc4c2603b6820283284a278fe16864e5a18cf7992d850c1d6ebd1253103c219bd95ca4c0000000000000000000000000000000018cac4f0660240045214034cfd8a7e40bf0aa12f97a23c4e27db0e05bb25f4d755276a91a4e882a0be63437a522943ab78077a51f88236dba6d16d7fd681c631510106b0eb7448df456eb9ce758e74cb0000000000000000000000000000000002fd5571c818322d207d58fe0a898a045a26c95c2490765dc9ac663a0de78ef5fbd05b20ea96dc5388d5b2ccf13a5e320000000000000000000000000000000006ff29ccb768da45061ba4e01c90459ededa5e79513917401e7e37151095ccd4656aeb9cb7c083cf27b69377295934cc000000000000000000000000000000000414d34eac47430495be735eb5c4b1a68372abeb43658f27613a9c8b78f17d9074174a8deeeebb1f9cda5d6198bdf89d0000000000000000000000000000000010b11bf63b8c39c1370e8fdbfdcd149fea88eaf1c0a94a51bdd061e4c41abc626a448030bf9ba880032e9f1642caabae871716e790e1a0120fd26d169b8ffe3fcc0d03683dcdba7d2f953f05444076ce00000000000000000000000000000000023eaa08a44eebae674434b013ae9992c75690a3d0de53e4b05d1c0dff249feb24a12432bcb5defe25ee4e44a56b27eb000000000000000000000000000000000f146ac27e685cca04afe8fc58fe853825f5b0009e8831eb0d0121decec23b25bf8521da2fab1508a3ad8254865fbee70000000000000000000000000000000004af1a525d3c33e0b1629cbdb90c56a88d70a28037c87db81c59bcbc811c8f0b98aa9dd574436c9f600c0e8e2d194c0400000000000000000000000000000000170efb5e0e69e46a21ec3b972265bc04b9d5ee926254f61c0e18fed013922e00f1897cf69889576bb5d54810486e7f2776ed0a27553db6ac6d3959ff4c9bc5807fb7d4f0a56095ed2bbe31dbfa41827700000000000000000000000000000000111c832a96329d6db203fc8b6bb5b7db01521529c91c74d9cd71dc78d067b36cb7eabf1af80129a7a3f44b719235927400000000000000000000000000000000097339c17816795238629d4ca6c243a14e9e227e9bfc30370dbb9e1475f6d03020dc35559675121792436bacdf9eac4a000000000000000000000000000000000805870a1efd1fc34c9b576b77418ee8c0d36aa9caf9994a051e1d55b49275f34cdb55edc74ffc267c5776c8d0e113ed0000000000000000000000000000000001513afdfc2f000e3b725fcd0428fe72ab2413ff2aa91b44458a5249c9a160ee27bca01d2fc2e230f4a80454769961af95ce72b30d989889c8779c4056e441bbcd93629efc2877d36d27f670711e21c4000000000000000000000000000000000485b3b1f812b4a28ac87d16f86d8d634e85d49d6dc460646e1224de662e906002c44a1a269c3bc011fd22afeb2d58df0000000000000000000000000000000013ba0752444a794cd00c99eceae51e61c382d0abb26e5e0e595d59321447400e8a8f7d97390bd217fb50bc22cef34b2300000000000000000000000000000000184515a36024d0bf71d9fa4cc5165363ff94ee9f8579bca653ebc0620a9d3146fba70a2f4a9f6bd3777101de0d32e327000000000000000000000000000000000e041422088c0343f7704e726d65ccc4216c4a1bde3668108983643663cf0249e992f9acde2dd8ff478dd26cd8d9434d06d220f64de05bdd6e1140c1e409fdc13f43bd31cd94e633be38ecf22ebd77db0000000000000000000000000000000005bbb0c55fdbc59992c83fc0ff03f677e58b6de6f8649141d88963ebfead9383d692015a7b765b727eacb6de250351ad00000000000000000000000000000000183057eca610b8e07fffb60d21bf2eb87981e6e881bba04ceff420ca38228fce2f94d40a993e2aef09e209f3990dd14a000000000000000000000000000000001231bc55242bea6b589cedd1d82621fb71c606ca9306b268379dbf83ddb1420dea228ffc05cd8b67c38206f3f006ef18000000000000000000000000000000000f2c943e7a8b0ee00fc4e4ba912b94f68f504d2783babb90a3781b666b31bd161af2f97a77813eab9ebba76040b04155257da8ac7d23c5ed965d8bfc76a642a36ea6ec4c45baf6882021372e8643f09800000000000000000000000000000000054bd97b9cc979006f734ec433e215a4e8afe468e69173384bc895e10ead3749d991ff8ff203abff30bf5cc0d2fc8c6c00000000000000000000000000000000066b73a98d5f5ae140a5784c5594892c849aa7f2db3b5798643f755743d401ca745d810fad5f4a33e5b3cf0fd7d96f7b00000000000000000000000000000000007caea93ff5cc6ffc033717220a215ac4ed7283945ae77e62320a0bde13f2153dc8dd401297cd124b4c67a4f3839dfc00000000000000000000000000000000094568035ffff439e3d3201466f3a1d43414e3f6455627c5479c8b7c55130ccaa5007ace7ef6a2b3e2e5a4c9543dad9163d017ba8c7ed138b1bc70141abc5cdc3afbccd8b1db5a6b5f775efa62b8dbc30000000000000000000000000000000015eeef8bcbfac04112931e186f6fd48b7a8ea891ab364ce8266c5fd15f072f08fb3655e324795df182a5ed1c917a5db000000000000000000000000000000000028916fcb3b30a7f95321a0998e544f9f4f578be7a9f866cf72d6b8baccd93f8935f105ed26aceebb3f9c96073a8be180000000000000000000000000000000012b11f356a7e32f3d9281a8999363aca0ae5c1a058724cefb51583e5f217257d47ca76d21e54ab62260796b95f9d3ad0000000000000000000000000000000000d83c75c36cc8dea4aab47823edd26b4492da39b93a15fa454aed4175f28a025ad2c576ef2d76a66e666bedae95cef1a7a16e23e37ecffd514d47199cff249415a6d366fdfaa82450f0744520258955c", - "Expected": "00000000000000000000000000000000059443f363ef0c65973d36469ac651eec6e52485a07a6d28112f4d0711802d182b7e6fc56d4f1aae51fe1c549247d885000000000000000000000000000000000d22118a6f1cd06ee14c63f0e005076bfb061bb85ed184b5444c08ed9dc35f77217b6daafeac89a973f2c73f00e0d3c800000000000000000000000000000000180430caa9917cbb40e3ada2de8d685b4daa99639669a643b8f5cf9a4a55d6162e9fd7f5d4989a1a6588feb0273669b90000000000000000000000000000000015d01fba1192f0f1acf8fb32fe790f0448c6563cf8ef5505d9378fa2fdd38bd99ba938077f71bb8eaa91a99e787e840b", - "Name": "matter_g2_multiexp_25", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012d948b5268524659e29cd407dbbe8f529e608193ab9452f936b2f6fc0b81d3a63a0e929329e2d89b5475dc2d73ebd8a000000000000000000000000000000001219e20a081837f4d4e33bdffda08a946bb9cd876e42e2f561ebfd18ec439e0104b43de61f47b8b7a0c346c33e632be60000000000000000000000000000000000a135c72c45f254cc1c260af803e14cd0f89c2ac3029629a86b05acd3440465aafa4cf84e69551ae772bb55802a90ef00000000000000000000000000000000052750c3a99974f9044531dee9129110b99572cf283b61e6606f1137a87de7344bf01d2ac2f8a1db8d815b6d9e7511fa26a9bd0a71fd58edf81459152782733536e960d27e35f9f84d00da256bdc118c00000000000000000000000000000000136b2f21aba94bbc8e5235951b1b186fd4ad221e6ecbea5c7279cc8ee8b01edecedddf48cca47624ee9b155a4c167f140000000000000000000000000000000019852d2bc9c8abc92503f3e7eec9fb20df108c23643ba8a2fe16c2cf085bb4ac079d3f065a1241067daaf401b662288b00000000000000000000000000000000018bf1a4e74ac9507b97a990f3a41cbae3f32e263e9937a8a62679bee93296ee5cd25110833eb5d136425bae0e9dcb8100000000000000000000000000000000096ae4bfaaf4f18d3e987d9f287fdd3dc9b497cc84867e757da52bd5f58688403e1c9cb432a2eb87e239879d52990ab5f1e168ab93674bd7f2bf73318a48ef17ef4464fbefd39f77c17ebfdb24d679b60000000000000000000000000000000016ebc2ee18515354b7af5d924c895ffd5556ad088560f89c59a4ceec229279d4075f732b884a6ef2bb2eddc11d27572500000000000000000000000000000000110282084ab6f3e76eeb9e5e8c56749992913c2404b003df9c2d01d72751f879538d23f612c8faabbccff45185f4c6a40000000000000000000000000000000017476677ebf052d13f60ac0ec5e572c398f1a478d60ce92a3de88a74a28688d786d30b1ea8008409e45697db0adc628c000000000000000000000000000000000a5e4239d938bfc7c05f3b3a850ebd5f7784eee7aca48c861eb4bdb1ce6321fc9c6bba997e143aba13a42f69ea14937397fb0d947d71a1b032070a12588b85065c19affd0db53e466f194f04f58dba2e000000000000000000000000000000000b6e16f2a6cb821abc43c447da207cc3013f2f750c844f42f0fdf47160a38501bf502073bbeb565122bb3de61b3a5ab800000000000000000000000000000000040f5f3aab5d416e9a084fa298814f894ba599315fe10af20f836e624680582413b4a54623cda8ae2663ee094e4db775000000000000000000000000000000000d32ac715a094813c7b46ce2e932365bfd62ec5e584e047b0c56ed6eca3c58268ae01be31b833be7ba5c2588ebb9859d000000000000000000000000000000000850b9044f129e51658a02cfa49d40a2b09239823cba4d8fe423fa1b4815750811daf745e7e02b317a7318aad0734ddc640f850bad2f22049f2f8aaf3ee57564fb38a847e428e252f003eaac465f7d670000000000000000000000000000000010c703e31f2d488812a387596c797d8d414e406bd82f238cea50a459d842502e11220ad82fce5dd36635792ff5770bc50000000000000000000000000000000010c11caa640708850e1dddd48bae22961a45029971d823b53030979b7d8ef2eaf2ed055436105697c5b0b31b1a9d0a7a0000000000000000000000000000000006b98568b2b7f0aada97310f7e14084a14bffe580ec65bc8fe5d19c6213c45dc1b8e1da5c6c1b8555729f6c781575278000000000000000000000000000000000f2c506f3e41c28a748656d1dfd87e812b3ba21815637e497a30eca4fc5de18257846f12b67919dd2d739477cf5ed0ae8bf91051da5bce0a51bcba6f4e1b3c9063743646f4e75e3e5a8cbc84e8112af400000000000000000000000000000000102b6d561172adc9316b3ec11f05e66e7affb1bdc70a364faffa57aa5938c2ac08863be8fe79ce3f627558fcb2ab1230000000000000000000000000000000000c5e72c271a1ee186d443a96d53f0ba0ce226c76aff2a7c3215c2110f96cb3301bd586f509edc45cd20e662756897b78000000000000000000000000000000000d546fbf485bb283a04fa05aa962ae8d77ec4d26f749d83b208f77247778e32a9a2f1483bd84488806e27b13eabf41d30000000000000000000000000000000005a42c6ce8d43d122bbf984e9777f5d1c15057f27e70fef44b97c2c6e7e2e303fcbad643027b7ff3167916f21a723ea98da771e0e827a52a2f7e79e0e5d93ebae04c1ed78cab87d4353f24ffc52099b3000000000000000000000000000000001788323aafb95f8761f87f771fa05a8e49be71e397849daef5877a7f486af13fa651be7a93bdd9465df7be4ff65825fd0000000000000000000000000000000014b7a56f3f7c12e39be76b3872c1ee648f62f9cb6a1842d869e00a5dc2ac8cb4ecd96ec2483d5eade5b0f9113133bb050000000000000000000000000000000009a30623632b757ae8d03ced0c1fdd1877718f8d84f34ebb42426284f73bb7e8abc31a5e5ded57a02d08adaa90abfb2600000000000000000000000000000000020b47acafefce7f617081e22b2bfc566acec6d2cad5063a79cf33e02cc8931bb698b72184a11fab73e0bb0aaec76c61d6cff707bff10fd53ffeff8e9400966d8ffba6d4ad6a8e7e456df10f8f5ebed2000000000000000000000000000000000d1190466f0e8f03d2cac4a5e63a13d7c6d0cac9f2065295e2de818773199d731f8cb7b2be5f6ef0a246401b345a2d560000000000000000000000000000000007d9c5d187494df79c25b6292527b0d6d8c50b6467bf76a1a1316556e48159a3b5dbdbd9fb0bb901d857f61f423d15db0000000000000000000000000000000013e4401fe76e3f1ef73bd244189cdc81fcc152f71449c11aab24c4fa1d123c5aa8c68a2d10fe88c1c6631778dc0bcd420000000000000000000000000000000004ccffb4296883b8690b2f3fe17e4e9ab24390084ac917ed28fa1e04b9758373abd348290d24c915dfcaf0649ddf5a87e00831cce307cb44e8dbd5edf24f1535b837277160d2cf6daa4e862e57fe73b10000000000000000000000000000000000f4baa5e531ae462b95362292d5366daa89f2fb2707c58568c094c58578e84a8d253fe1de26b917b84635c0aac3a63300000000000000000000000000000000109057e5c5451eb9f85b95aa5ed2615d2faccd0539b1e4481923e04cbdbd2ea9290969022cfa508d3fd050549c74940d0000000000000000000000000000000001c3e147ad9c31927207f2344fedd541316f4010e3de194f924c4a1450a221285b76ff1894f8b1670731007f44965100000000000000000000000000000000000909cdf5c56dc177daa1f3fd7cc31d79a4f6dfcd462c07812cdf629426b75bdaa297b9d7e67aefdbb58175a21e29edada8168d56385722f339a5b27fc25a88034d348e3d533ff4dc99d28536c1c09a770000000000000000000000000000000009b4c6bd1c460d2e93febfe523c1d54d6bf6af50838e7a10b732c1be8748a0752a517e7103d0ffa4507b086626fbfa8a0000000000000000000000000000000015bf2c13891dfa8dba35b5da1235563d4ee1dac33e89006f5c9fcf06f2fef7b31ca845bcaa8ac608046e8b01c8a61fd2000000000000000000000000000000001898dfd6a0618df821474b90542f261c1febbf2e566978b0fafca44f6dadc57202f88366b19d2c955e4291ac21beab520000000000000000000000000000000019287e1ac6b3eaf412e58511b40d87558e7cbf90dc8af2f5d33825b40fd2f2425d0be3a05d0a49076f4114350dcc601eb929ae82ded73a4876c041d2e52fa811882fb8e22690a27cb4ad3ca05169bbf0000000000000000000000000000000000c0993401c024d32cecc0d86d4cc52c200e59acb34fee2ae052837f467905e736a1118260ee12a963ca2df6e1a6c9d0a000000000000000000000000000000000103f78f0e7c9a5628a66efa91f150a87e67623ded2560aef278a8caab017fdcf181981952b450c67e3b4d3f362822a80000000000000000000000000000000000df01ff335f23652f1c34480d23c62d705572321c0e7fe92556e033dd3cf5b78a3d554585403a7f3c71744c20d17579000000000000000000000000000000000a0e2c9e2e34e5cb36e96b29231f702abb127a011c7ea3e21d59e5c55f745a02039a68d59ce8e29afac0752d1939106936999c516d4acdfbcd488d39e3073db9db6cdd0c0fd1d29d58294ace6d2d199f000000000000000000000000000000000eabff0e6ed9dc358881796441c48e722ea171f26011ab898c5a06758f61a629ae21d5a2595a22dc9855fd2e516b30fe0000000000000000000000000000000002732155a7a2791078dedfedfd3381281554c389bf9b5baa47593153a2acfd22a08557d7a1d49be298e416051b9137dd00000000000000000000000000000000116faa2e2a261e6a3e4de6ad80d75ee05aebae47872e2eed9cd91aafb94a706de673a05f1b86c0b0131cf148a90b2b7900000000000000000000000000000000009a04c09c2a4fce22d237bbe930392dfbbe5c82d480abefbb3be876015e2f5889a0922df6d00d4e94be0e9fb8d2f4a1fd0bc405e3970dc2bbd7dfe0c54b7c64543fc241000adeef4f7aa2f1dd2506770000000000000000000000000000000002a6402848507062e5c5d63b1207a1a41d3b941d21792391f2feff95035f1b4625541770fa5e0f87585cfca670976533000000000000000000000000000000000904095ce640605c957715e378ed733ddf1f94d3beb63543a50c8922ab9f8092755fcc65e2a1ed9232c8cddcb5816371000000000000000000000000000000000ec62b911b08d3e8618880c3784685b2c6cbb07a4aa4e348ab72e4f918152622ddd7748bfcd79f35675cb956d11fcd650000000000000000000000000000000013f651e9104d48a081cef2ae0648816b2b4b5f644a791514e94a8e3dd3001099c27d1f9860337ced1b177b4ad7cd5866c36afa3c8581df069292d53b8ce3e35ca136a0b3f95a894958105fde9c77e39d0000000000000000000000000000000016334abef2a21b9c1926b2086075471bc2d2d2f66b963a41623af91fd2fd50f254c008fa3bad6b53658c2486edcc94aa000000000000000000000000000000001063002a5d17aab2bbb5da49e8bde63a1f3c4dcbc8800f9487f47c6d707109c86d3cf7f9171643418b195e50d7483af4000000000000000000000000000000001213004f31fdd0b0df5d8e3677c4f48624691e2534c02881c6cc6875b9abaee56ed5739c2acd66cb1b10553ba066ef1a000000000000000000000000000000000fb7659081cfcf8beaed9c1daf9e92702977c37a54376597d897082a25f9882f1ae14e7724c0aeb9e002dee708c6b4eb0f0a2bd678c5858be2a49ca54de8716fdeec84e1935b8f44545c740417efa7e400000000000000000000000000000000078f06bdfcbc7c0cc491fdc8069314c8a395983f9a2e5c2d1bec360f36e365da377885f897d8d711e33270e3ef9dc4d80000000000000000000000000000000007d43394d5175e020b3a5d768b60ec763d60cb1bb37c0343930fa82e92fb1becde0a178c4565df320824bdadd54ecabb0000000000000000000000000000000012f9fc96355721c35a6f5439065d89cfca5345622b3f38041b41c036b9bc6bcc980498ddc7bcf807e1b97831c099505300000000000000000000000000000000105307b482467b881a59eda1434e31dffdea531603fd3c460aa8d4f58d32668228bfa585bbba2dae7346141af59190e2c8e420db340ef2c1b5c6a71645e303eee95cd93228770b639287b14b6a5c59ba000000000000000000000000000000001576521fb3be8c3178549969e54bb17b0a3546ac4aacb470e935359e36bea4f43dacc06c151a527f441ab9616e07f7b90000000000000000000000000000000018dff940a21768ee9b9450fee7259663bb29af645bda2acb4d43f4e9d631e0127073f2db04293266e6fd6fd3d005e3f0000000000000000000000000000000000ca6a977016c1ebf52827a5ad52e5efcf7517ccc3ff40df8141f6335fb6c77c3fb8f6b0dcdba2596ded7c3838577e28000000000000000000000000000000000150cc33b55586fac30d316cad6580cee0a070900fe7d540167560b79f4cf9690a5e02cfce9946cf67a95dedc9a7d9aa35398541eb5a03271e2ab5ec2aeb2da80e634f63a050c25de98ad13e9d63d09bc", - "Expected": "000000000000000000000000000000000adf84ea7681c442731be8db9508a050d4689c42af8f7472491655356a86fd9a0afd91435bdbaee98db3b1d8f26203fe00000000000000000000000000000000090a7dadc0a14df481e44e2005c9ddc6e026ce2afaba7badd18492bd3a338dffc349b4a339f56221eb795314252d53640000000000000000000000000000000007390fbc06077cd167f53a16f347eaf50ce8c9d111afeabf3a672687441b80e66a66ba3fdb28e2ca8282f3ae3dc81be80000000000000000000000000000000001998f98e85285a428a2860c22a00d0b317854da4190dcb4dcd182ac249e13c51f5d5df5db6a0fd61d01232cbcacd5a1", - "Name": "matter_g2_multiexp_26", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c868a2cce65692f83eedbfeef6f9823ae9382fa5ed23395ff2444807e72403d4f6ac861ecd3a51db841889fe22a033700000000000000000000000000000000111c9aa53da85a63ce1870b963415f0d5f812e061aa6bff57425038d1b65fff57a78bdb963bf2450001525a93011a28e0000000000000000000000000000000011770810c16367d075c695981dfa69b072b82b034f8ac371f26bb157f9f9d667aa555a5c6baca69d08f421cd569faec2000000000000000000000000000000000df6146b29bc8226dccfc95a325d791b30cba8ff2495434d75622b170a634ec7995c5b4c689c73582ca861dd21d8e1e49f99387baca30b9cf63ad10c445daa142fcae1ab3c0a366a068bb5efc9abb3a9000000000000000000000000000000000fb30aac6502ecdd3544f1879bf1b3f4c19fb897de6c3a7cbf08f36244aa8e9dea8aaf781f7509d3ece16ca144a601e40000000000000000000000000000000012304be931a1d7440d67740f50b1a281468b412e8b6c54c62b993ec609012c7056fc7e62405c7530e8f5136cacb5926f00000000000000000000000000000000182320f5d9211c08f3ba5d40ccca45cb0060a6d362b4422084617b9d8212e94a9b878294ac176b8f0e959bc124a753310000000000000000000000000000000010be6678910072ed9f932ab01a2d72f7374a2cc82bbd86a6006a495272aa89fd655e6719ab8b3a0643d002021f7b7ebb4283a1773995bbc97a6df107082fed4ba40e2d30c5472a25a7643ca9e78b8b8b000000000000000000000000000000000f1ffed9514ee81e9b3fef4162c8f4980fe0429e57bbc224a9c9976cef7d26ab61ea7b0cd42eda30da97e3f8f5ab5f0600000000000000000000000000000000035b9b349b531d85361a4618a172b510dbc924df671b3fa707b474d0d8b17d30dc8ed208d66be91dcb7632d2f05ce31d00000000000000000000000000000000010030dcf6695d44ad3236032e47f7aa25b9f55869f5207e7ac8641db8c01f5b59627dd3442a1834b8b1fc595e47cdcb000000000000000000000000000000000f91ad5c923572a75d32962567e7b1b0eb84a91d485c968b5aebf8b3a772c2f94e47bc1d5b333fe43574308a78e768ac7f4202d670fc3b48eaa92e925f48821d2ae057d90c5f184edcce9ea900ab51a6000000000000000000000000000000000ae11c60537bbcfa46a08cbc219122ed66fd0d42f90e68243c32010eb99942554c349c021f0e3635bb50f7ca3d106a3f0000000000000000000000000000000019a61254aaa5b51b4d354f444706ebb0bc3edb87ec2d83e830ffe0282bcaa3278e947d053d6678549a098129bace43da000000000000000000000000000000001100f48a07456f01e16bcc833ae0a2835c964e9b0aa850574dfd8b4a7f06d03059e9b4df8931740ce0621ec7eb31218400000000000000000000000000000000003072392a824c386859735e2d203c9d52c19796ccf8538bda3b1436b2f6815bc86d05287f29fd0bb0569a81a57f0c22a76cd8d292a7053c449cb98f13cf768c6e37da9d702af28c16dceacfaf9cdef5000000000000000000000000000000000392760f98883f9cf6c0f0a324b9a645cbae12b780896f6a3eee918c44a815daed156248d6afb25901521b323f6baa240000000000000000000000000000000006375c6629f30b7a36785269d691772afe1b95d6e1bfaaba9459c31086c2697e4ce77d148fe2ea166cc330373583f4730000000000000000000000000000000000aa8e338df7eac5a7b070a69d3ed1553a0c52fcd894c2bc8d1b8cf6ed38983c6c392a9a045ffe8ff40b39d18e7c87c9000000000000000000000000000000000cbc73b589cba1bd47161282642fe6f51f2b3edcdcad6020bdaef369d3f2c11ea9cafb9a7fdccfb89bbbe13560d42d1d97b7bf8acdfbb148814afee1df79aea17261dad6f78772111a6dcb021d8c79d0000000000000000000000000000000000e71692cc2342d1e93e0ce72be69013023d012dd2294249dfd69e1d610e2236ee2cdef22446f1996bd3309825989930700000000000000000000000000000000013a1bbd3237dcbe44e05234f7e41982f4fd951d3741a3e90345418af1c922d35edf776a27bfbeaf7a15658db67164bc000000000000000000000000000000001197a2ee5c2541e19b5368c97abf51fde3dd0b922c3d701d7d84552c9f47b38ca09a8aef8240abfdcb03292ade1ff04c0000000000000000000000000000000010ca3c22ff8a47b1c683a58086ed9d831a5c25b6ce5a1971989974b4760cc9e83a1bc8d819825989751405b242eba379efdbd5953bc33bfba09fe7b3ee22c46c3a86f557e4b5f272853e67fd95a0f9b0000000000000000000000000000000001306f8047ba1a3417e7993bba0dfee9077eabfc275af91d0b882a53199874e0777d8dfd29767186d922d49087fff38b20000000000000000000000000000000005371b760380a6d287e129b329e735413447969eb9048def44f5c5987a64323d2a5c81484c40b20206832b86a4af9c4d000000000000000000000000000000001552eeae620c42d0bc4593d7c8e2c8fb4d6dbfcdde68d57158a7dfe837a1870a73b45a97b02abdea174a475a7061331400000000000000000000000000000000033a6dec61540a5cd5773b76847dc5016b309c5a027639598f51ae5b1067b3f7a02f5ea11b0e1be77a3ac236cba15c929a331bb218b99fd38451483a10e8add23c9641b975af3897670884efef90d4520000000000000000000000000000000012ad5ff49459fd3a7940a69e2a78919876e9b3a4f0c142499e7b5dbcadb5c2b5d79c5dea972f0f0acdfd10ac53bcdd92000000000000000000000000000000000ec1be9cb379bf1e24bd5429a4a91857bc3ad45095d15bc5537c2ba39407e9f2edc5fbf711ef4287a73ea466d4f53c3800000000000000000000000000000000173605df66aaf51810793db1cf2021de6a7645ae84a5d439ee035b917d037d9f9ff072b5dfe8b9ac69feab60fe2d70bb000000000000000000000000000000000d0bd336825381ae1e18ca37bf6160ae32b653ec9f9dad159006e92c24b661f22b5629ba323e9e06ccc5887a962ec23fe9301dc826bfe2988cf93c29ca9f01421b75ba63c5ed2cee1599122012ada36e000000000000000000000000000000000f5e593c6588add92cac2c9467247fc6d900f20b4d3216c258f88f3334eecaccbf3eacda227e2da46cf520e5102a9cdd000000000000000000000000000000000458177ad6c190222e53e054546413c13216286d414e3509b7dc794dc0704afd26bae93ff630c6157d05d46d805a04470000000000000000000000000000000015df8a7720d389e6112707e37694afac2f97282676a89964deabefddbb3a0f1cbc885d4c875b945b8303c1ed2c0f46b8000000000000000000000000000000000e3c7f1af7cf5923dccfc1d25bd86088706a3a44f5fa7f97171228e8f2a2b18e9631b2a63bd5a75ee0bb83fcc91a45c30a1cb530e8b828542fa4114de6aa936bd2be5ef3a9b7a0e20e475022381d62d40000000000000000000000000000000017823fc8a56e6e5cb9924037ad6ad1b43237894a877572dfe3d3cdc1120fe83e01de112b55f7f334dcb5c6247c210613000000000000000000000000000000000daa01f90cd14d82d4fc40b60b463089fc6c0e567fa46bae69184d0e3cc5acdb1d759e3291e2781fe0b65c734ddde28700000000000000000000000000000000164e742b123c19e52e2d7a6727689181f323990a3f3238072f7cfd7fc0f55b7be4274c0df194d85060a81f3744d3978b0000000000000000000000000000000007c03a1678b6e91c1bfc66ce8fd419cea13c7cda3213856ad21823b06db94538153a15d43a9d4270edf77b9a5ed490e6cf2f0c33bd044e8c4468b4b7e137ae294c178e7b6c9f19878331fb93220db2cb000000000000000000000000000000001865bc91e645e2e24c3efa3afab8b0e278dcf16b29831f75b3eef0b342479e997b9c5f8ccf67c789c830609b3cc425400000000000000000000000000000000018dda7857f919a6a49f6bb465c27342c8fab6afe6350c43b98e91a3105276f3ac27268454e9a9c6dafeb2218ddc7d3cc000000000000000000000000000000000b098258ff8b185a5c59b46150954d52db5a5f68bc7975234491406131e4f1286ce79156dd1290aafe688f936ad34e31000000000000000000000000000000000b294e9ce904fb9e243d0790147b6070b10ff611a06e3f639aacb744154d02016ac08f6769732d4f6944ce9257680d49e5f460dacc592bb947ff6f1c15b8464824aa5c957a645a763138ac1581ac5768000000000000000000000000000000000e541a22a7a36adc06e445f42497596e1017a1d99de85bb945a195cb3cf0c14d39eb7a2aa994cf234eed77f6307cf6410000000000000000000000000000000002de753e41a16565e5ab1b61debdad54950e9930e04badc6e356f10711d7688befc6827040356c0f0a8ce4f8d7121b3a000000000000000000000000000000000f2202e34ca164f1a6c0afbe179b714b303d87ef14534fe3f4230180f709dc63af17f04487264b3dee6b24ec4d0a423f00000000000000000000000000000000004044d9e3b3a77d6a309780c870a65e05e1ac531c5420f6ed0056f5e728e2b83a968ca90d579db50c2dd395f7e40beaf26a9736f728e16d7b8ce0cc59e2ccc848c181459fff4321982c08e9cac5794600000000000000000000000000000000166d7692fd30dcd06b9f01ba2101870ed347840509b3242f7cecf91fbed91abc24b08b08cc39c508e6499a2f8bc3637700000000000000000000000000000000076ce6dcbc77812b4d5b44a50edba5a082cc36dc24a5cc348283a4ce1518198b56134c9807ef850edc9e36e9a282b9ff000000000000000000000000000000001261d9412245abd7ba3fc1597f34179e54766c49306725d42588545e14f4e450ee1c7af913ad7225275c57680c23aa6300000000000000000000000000000000096602b4eee053998555ce522c060d5e04c7961eeaab0145d38c9b13362624f54fcc8d0b77f2bbaf8c312a3279f06e4eccf0a9be4775d65bbfc894f8ca66fa6f69d4249ea7f6b076fe193f2805e64f940000000000000000000000000000000012be34c18145aac51a1494f4052edbeff14c2812ff494cb78198cd7d9db9e951aea80490c55c4ed926f6a96a2c337c880000000000000000000000000000000000536e46a63ec5ac0f2f4eaaad6df98322c6a981cf2fc8ef253269cef20a76ba1ad089c24cba4ad4680dc4192d66595d0000000000000000000000000000000005363b9acb66ee95713b63dad076529805c0dd8921c738e205e7b1d0410a3ecca0870aeb2e64cf45270d49b473371ddd0000000000000000000000000000000016749b2b09d889b883b6fdaf518345d4cf097a728b833e92c4d21b5c41c8d5cfc0758e895b60ad101a74bbb6be6ca0c5fc6bfb37cbfb10a1ffdfcb91d9a52883cb9a606f4ffa8849a6e07386dc9bb34000000000000000000000000000000000067a684b55fdeea39a29252b355700a4810f083909cf2c07a80b362ac1b4d58f5900c68d266f7ad81ea278c0931bc1ec0000000000000000000000000000000001b1f78d194d77cfb4a2116ce9e29438dbf38c52733b0295198159d7cadb2584d86a75c24aedeb36234a0becf9d38a870000000000000000000000000000000011fced2244cd959872a25c0c7bb4af6151d99e1aac079c606db4987b9ba111261d4a16e7d82362b865324824445a946f0000000000000000000000000000000002659e7016ad615ed80ea1ae020903431b470bc0341f8e0918de9b8d2e933dd9f2d9123e9e9d20bfb05d49f71c3c454cd94959e16f6d780628694075ba5aa1a476d89d8fffcf4b4ab7e6343c011fee920000000000000000000000000000000008f3c5de8c94a98dc5ad7846c53980384f997d1657f7349ad9b51376d41f4b21861d212fb6428bcf2347d8774f44156d00000000000000000000000000000000110b245b1e788da41dcbf60a3ac4987c1925696dfca85d450107f654fa1230adb9436d60c9e742dfb4e453ec4944c56c0000000000000000000000000000000011043b975e01df36a36307ba9234a18b97aadb9da509513b13e4f3c80432b0cc5e69a3bbb3cbab8df41bbcc92cdbf60200000000000000000000000000000000120aebda10c52a67d23842e2bd9a897cf38c58fcd11e4e8c5614db5e409a7c03111feebfe2f1212ae753497dc59d6ae9122f3a5e940ee7e5038421619daffb8a6f433605f37e78d863f814b51b2ec4e2", - "Expected": "00000000000000000000000000000000021067690e6e001e3d0d01449a7257348c4ef68e66dd47b9014d7687d44749be1f33e6be95df6a204169ab7103dc2d3c00000000000000000000000000000000062efa0c36462ab0734128dab5da8635705bd1e1b540817c5805ed9417f176723eea92425db539e8763b1c79b9923e9700000000000000000000000000000000176c9af1970f026bcfa87e6f85a20ed498c28c6982e21bc050cdc29c0f0af832ed4424082e4862d985b78519cfa75b820000000000000000000000000000000018718b0d0fbdf4783cd0b01524ab153b891fbf08cad60241a3f3163d2c3496c36afdc6de62ab3c9a037f88ee408ce5f6", - "Name": "matter_g2_multiexp_27", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018adf92d8da050c76118a3a3b2ee43955ae8b14ddc8ed64f5672f40de475f7e0ba6ff60c4b6ca3e863d7914e6de2cc330000000000000000000000000000000013d1e19011a1ea90389480d14fa608985d895e05edd9c28fb34646f70fd7bdb7857fa785b1e3c8a2997da6c3b5337ccf0000000000000000000000000000000015764827d9838c2b011660230ef9805af388fd997cc229c939bc5f4213d517dd837328c45b0b8ee1d6508cb70629b7bb000000000000000000000000000000000d58fa30a2d095ee8d946e50a027ac4cfdd557b3fd9c82dbf1536ddc0f42491a176ecbdb026306e6ebf1bb182a4e8199b3908c739d505a1d6fa85a6dfb7a155202710b45861f1a8a7ac7bb3274a180cb000000000000000000000000000000000cacfc8d0bc6f9db737c8a316043a6b52fd5946937467afc09ddd14e509a89f2445065ac8a8c56454d529d67793edb0400000000000000000000000000000000148b1b941f159d93170fed949d5f53bdd2603d78a49443ac0e2353130ff914376e018c3db3d12b807d105f2d50eded8c000000000000000000000000000000001382a3e98cfd072807214479900a8602bd666cac7f19be0443ba1354bfc05666f40384e9ccac314b5d0a2bec1c90ef0c000000000000000000000000000000000c12c2222f67a5adba78f2c0be5be95ed743e835857f4204cf47b67fa2eac45cd5985fd82c7a3904944e7b84737374b17e0e27a8a416eb38c989a66b84f037a5a24ef3358e20cd553f037a0a2461d31000000000000000000000000000000000197ff997d6c5efa3d7de8e16f26082bf13a2401d6df5f5c33c6614c36105f347e40216c907bdad9c1df6ebbd44f41c3f000000000000000000000000000000000f27a0bf92329730d776a83583177993b2b354a212a9c004f9f8892a750c477b8d1e68c13127f03b1629bc8392d06f5b0000000000000000000000000000000011b239cc6914a321385d907527b85713a0d842f5be80752f4c5758586dc1de944b6e4578bbe324f16838115e9c866bca0000000000000000000000000000000000cf93c5b48cd9de51ccaa45124217cabf466d07d6fdf4a7bb810443339ec4af5b74931bd07eb9fd31c284c05f3f539e0a3cbab01c34856b892aacdabe63d0a0c241ebc137a88c83ad22cf38997b211b00000000000000000000000000000000137b12f731ec925dc51e20a9c90323d14e1497e16b3a4b5651135054ef0e58e9b18167da15220b9a4f7d81e9a7648fc20000000000000000000000000000000000b2d3ac534e1e5b2c9ff4092c2d8dc5efd99121de7df953e5426eb33934ef07e41b196eca50f5a04a936881a05f2b2a0000000000000000000000000000000004feae2377d950717695606844a4873ed7b5f6703d7a63dc8b960b99b68efbba710c2db0f1371acbee314875b97ca054000000000000000000000000000000000f49ce3061e7254dc1bc8af3636a05e098cb96d81fb31e25da97c6266adf3c41a74d46ff32f4fbdb4cb7e4a3f69e827bb386bebe0e49b7f07b0ac61b15306c2515a1ad6fd76a1825dd29a60e845c0e4a00000000000000000000000000000000064ae3fd67250f2c6332e1e149ec09946147e12e0d871403e559b49aab68190a1454b3ae924727b6dcf6e1ab327c9d7c000000000000000000000000000000001131f91c7a0e1854bba3958b36083c27904cfbdb8b8cb3fe68cf578bd1cb6f7c6eff91d98e4b99086926c5d4272cc1f200000000000000000000000000000000071c6a92a8d460ff72d172c204c8a69d6b6752b8c1f731ec63f7f394c0c3a2a1bc15e865172f693f523c11cd4ab1f88e000000000000000000000000000000001193876df7f4a1cc9b337a41c9faebac2f209b9070bd75294c2a88d3091a1e55b51fad482fd2aee8f90458eeb7e981fb8902a82d33993a10c56b2fa3333cabf1c5d47a9c78354d58f70ce4807cf2062800000000000000000000000000000000025c20ed5572dd1c9a098f241d2965d8739878ddc57c017632afcf6e54964894adbd6d30f62f316c9c3ec7a08268afc70000000000000000000000000000000013bc3e930f4fd5766db8f04e1ebfaab2b67f620119c39d687c68619b3564f3e8b74666c9f8bed6c1f080a9e23e9c0f22000000000000000000000000000000000973a3cf19312f90843f1f013b05484064032557807ca67b2ded4a27fdac12d6cd0e1416c8998cc8635ce10046adfbb900000000000000000000000000000000108903617c78fc608eaf007aa13861c970557f2693b24e8a278920897be9694570ae6e6c7749c3eab84d5fa3af5164b1426a4e2317fee033a226a91a52a5830f9ac2cf5f329feb6bdb382438b8a39f2a0000000000000000000000000000000005695975c140fa14998e5916268bde2135cda80a45414fa85193fd6e13c6b5a6486898f590d76175d8ec2629c923e33600000000000000000000000000000000033f58b1cf67e51e9ad817b31919530cfdb5db5ca4a537d9b006b63399da49b2a5077bf5c3b3b4fb10b2478f466542540000000000000000000000000000000015c532e40ec04d9143e308895b2e7e3d3daee093a5840e1e76ab528fcfa5be57d9796ffd58ad5ab7df6f88aaf34706f2000000000000000000000000000000000b55747d1e8b66e2b2fea67229f2b7b17d58ef547ca841bea8db5b53fafaa18390f11b8170c41a5dd29331917fa2e348de0390c05fb0dc9b4a3f76b51cf952a11b909ce13f9abc9fed6a349b8efa98ad00000000000000000000000000000000001ee5ebf73bb40a5c0822350853bb5aeead3262380dc274faba6b04e58e7fb9d5a4ace109ffa5011e73e3d89ee6fd77000000000000000000000000000000001427659e5ab1f8b47edddd27c613b578890d4c66c835c0cf8e8daf19d0ae842f0bba5bc83ed7248adcd75cea5d222a270000000000000000000000000000000001d4560185690ac05e56c2d629d599bceee3ed2919c29e3d1ac54e80ae99b5eb2f93bab865e8c1eef7206f96b2bf4eb20000000000000000000000000000000016ecd3589e3703e5b0ef53790130d5074d2bc0fd5839d9c6ff905746a77e393f73edf53b98b99d9c87a1fee1086aa8657431db9e576643f93505b5b25836218759e736c0d650a5221a652338b0073eb600000000000000000000000000000000163850016261f34de2b831a0a8dd3f224adaa3cc279cdb40e0ae976bbf736dec26c55a6c79cb1c623870b62ea216274b000000000000000000000000000000000a79af5c054cd08608d4be1705058ef7b4ec38a8727560d960f0325d0ef915c049a89e76956d0296bcb6c96333c3470c000000000000000000000000000000000ca89379e558c7308edd25bf06dc05db857204e9351299ab66bf050c8f051341a6c15a02864c679f07373038de3fe87c000000000000000000000000000000001929f42ee5d9dbfd1f6656f61e6243ebf0eb491762b7f3608db3f3e9abf565ab1524f770cd2ade334885d7479342c92c6745a32591e359efa41e9ea93a016d2eedf1da112cddbf31818e8d687b36af2e00000000000000000000000000000000193b6cf7300e47ecd21a05a71b13a8de45418d3f67931789ce6111b8633b9f44063ca13ba8c8a598ee0725caaa3f277a0000000000000000000000000000000016884d982e2ec0fa7e59fb34ae8708d0bf4abfc260837ef4432e8e04474e504b85450db8af8e6809413c90268801fb3b000000000000000000000000000000000fb48a8331f278845979beb8cd21060355566af215ba44029455a03d0c016daf0f6b7c5773d1a99e893e76b4411a53c70000000000000000000000000000000007056e30143058eaea89a3065e1de768d49860b170d4c364a28d38475f90711fba62c1787adda90dd2d347da72680f4eed37a5f4bfca6b77ff9e4f7e03bfed52ecf02a8f84ed3da6da2787a4ee81ad9b000000000000000000000000000000000501fa9af88e28d4f0c0590a2624239bf1724ac7174b0f1d5fd7527cff1de9971d6aaf28ba4005e88e181daffee6b20f0000000000000000000000000000000007af5e30b5aa9ad206645ace12cb2b36cc1c6068e604184ca8bfaac5a4ca327f7c43a74d43417918da7df84e3bffd282000000000000000000000000000000000bfc0538d52f277d54749ed0b69697b4c60ef0c5483d21dda76533e15efedc9e2b2ef07618457d64bae8ef922c0b41f600000000000000000000000000000000048935cd352e999bffa613e3be0a9f9a063d5b5eb46cb5056e41ba214e87f871f216ff41ee297aaaf2994a7b6433f58d81633dd6e729bc17ddc596cb1f17dc6f0e50c052a0b8c5a4c83900d918a9eb560000000000000000000000000000000016ab1e8b6f41891e0b65f14397c0887b27ff27e7463333e0938a7a1a181dec603056afbefdb23b41bbfb2c05807289b8000000000000000000000000000000000980d0ea9ad5c87bbe1aefb708061f85faae1e1e3b01c55bd577631e5bea2b5ffaf5e2478f5a8df89447fb8a73559729000000000000000000000000000000000784d0c5fa243bf0125cb2c83a4040715197e99d507d71a3bd9ca396074cfda652c1ad0dd95c3cfae369e68d3431ee7c000000000000000000000000000000000e533bb33e6d269dfdeedf7d17c3e0c19f694d151e8eef801c326cbcbc463a42558f58cbc330bdff0d8d91e2974eb4cfc6b019d29219b57404baa955f66cf1b2ee6571ad5b80d471ff6db569e32a1a5000000000000000000000000000000000050f005b00f371a7308b5d7d7f67f7c00bf15acc518942607f32686feab5eb503391f964eb7ca711aa6c7b4e494d7eba000000000000000000000000000000000e2ee5092170ea3da0b1397023b2386c65ec8b090484353f2e5d64694aaeb8d5410ae22c92662fcfa21566d70173ef36000000000000000000000000000000001549723160fc7b8f5ef9a84bd1803f18b76698aa7a663d9c107c9ff6c6d02894edc80fd00d436f3a942c05593c5464ad000000000000000000000000000000001032f49e3527cc1f1355c65edb21220c6afc88919ff67ba99c65645cd3b8ca6662dd0146f6a90d92558b3f54815a361d6a76411ce02b4dfc84ddf62ed26508a2dfa5edb5a98a6a20dd69e8b8e7ad2f5900000000000000000000000000000000170b317e49f1304570a3a3e6bef78fcf8537a451ebcfef5afe3eac4aa1aa87dbf95d0f870fd3372d37efc9e663621cf7000000000000000000000000000000000269ae0677d71b2537078e96d2593482e4d41b6d1d2cbec755f307735faaf79c01fa27f1103cdfae1a9bdcb665f592c9000000000000000000000000000000000b115d5a9fb9fd9361d0573a8d68c5193f02edc1cf3fecf004c6603f118f28ff394220f6a9e1051a5d9d4b417290b7f800000000000000000000000000000000107b45614b18c2513f8c42a0032cf0f3f300157b39d2969ef7b126f17a9b5e8e9ecc5a61a2ed4db92134b0797f6a0ea35906098e4ad7e4eb2e996075c7cd660fbc399bc942f9080404b9d0758c4ae14c0000000000000000000000000000000003de39b056f8f0248b138437db1536b7bfee29af00c37fcd14c25c88f0f051eaa07c763d94c8ce497696311736c0b7140000000000000000000000000000000002b52981e828f8dc1cd371e6821d001e1f96d57a865a3c0a255298c43d52741b18fc60903d1a5ef6227061dcb243096c0000000000000000000000000000000016b5335f0f9516f52f2ed45fe723ded427206ba96af0879958f1f22795485b2867e953de3d9b3a9eed2c37f26838e1540000000000000000000000000000000004c860058c7ea2e6e4eb2a65c1dfc20b3070f89ff58ab99bb51a4eb9e7f0642f7b32d1d9f27c668a36a9e053a8d585f394ef8c281a9be3766fe784ae017d93f608dc2cb97cbb7dd3e3814b5ade845d370000000000000000000000000000000019cbbc125ca1b89330c21ef5b42fe0dc1e795271ce4a9ecabff04eec9029f756f180520f0e7b84be2e9fa4af395536ab000000000000000000000000000000001630cf0c4f3282689a3e01b5c8f9be3803f60238bbe9fecbb0d9e8e49f4ec9f6123c44840acb8cf55f8f6bd15579e6830000000000000000000000000000000012afb848bc0ade8f0c25c6c342bb651a7481be065a48944bbedbc14c095af8a4a048fd1e776126e2128f904afbcb17ff000000000000000000000000000000000dbc984f9ff907ce5553bb11a458deaaee0efea49d6816ed7abf1dee7b70cb18cc669d4808e75678bb898359c7ebedbe6feced33019b3b66d335f2118cd22b2952cdf9757fb3a0cff55b7c4f245fb438", - "Expected": "000000000000000000000000000000000be6dee62b8c85e36a216d16c5477a7c58f03b992277af83d9b53b3b2169414b72bcb4a97e3667482e888738ff17c94900000000000000000000000000000000067337c69c37ef6f0ae59fddb84c46a2afe7fe047ddb57b3b80437609f1a21fa5a73420fa5b44704ca1cac6c7a99d9320000000000000000000000000000000017fe6f37d2410159e533374ff3812714dcd07610d75a53a5d502cf2f51e750c48858db1e109f6aaf724292c1402382f1000000000000000000000000000000000b8ecfe1f5f5d95777b0fe5d94fe81b82656e6e5a62b7591788baccd251d93e4bbc6857cc87cfe6b4ed470c33631ae22", - "Name": "matter_g2_multiexp_28", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000126d4a9ae3550e31185aac9011e3f086517cf79a279326c264f51bee6615dbcc730d78055489b5602e91b08f96d23882000000000000000000000000000000000aeff5fc04fd06c26af8b048fb2d0d493525ba5c2bde30664e7371812d529ec7dbd584c056b05fe02179b7eefbbc45fe0000000000000000000000000000000017c6538d2801947cbb646d4ec8b70b1e24453f7a984db7ba73e3a5dcf595bdbad9703f2d846ab02491e5e3a5bcee0762000000000000000000000000000000000badf551dbedcefbe7c303a5c8a52151b5460caa22004028893af4d8a3fac30cb1da1e986f9124acd5db7a634657dbd0cb5e7df372d346fd13faa90b0d6961372ce2f32ec379e5e50e7ed8a13942cd9d000000000000000000000000000000000bed71c7d878e7ecccd8233e3e604e564cba0b1ce75f726f846f3a6e2f3b4f5b12a28b8638be647f5c33226edc2bc7fe000000000000000000000000000000001914c20aabaf1f6f82063223053809622ad82a3a54668bd600db1aafba22aeee5c8a07584e263c91cb0fc5fb809da63d00000000000000000000000000000000056d9cd8f79a90d16b36bde77e546f8b3064ba7dd0fde78d6bc538bd6ce12a4f32860205d5d396bab3d70deaaaccf9450000000000000000000000000000000012f7e420708b66132157a80753678de292998cb6c4f00244d3c47a6077b3401132b73c7f52369aa2a6a90892f7be4ed913a5fa1674c20c97d08608d200f3f7611010e6a25a790853ed4ba0c5aacf111b000000000000000000000000000000000339aa1471eddee8cc0a4e4db5a29c3e4e92cfbabe023995a79624614aca522cd459dfacc0cab346b1cedac347e1df100000000000000000000000000000000016cc4ee8cb72fe09e65616fbe9bea1a0077114ca841ae335f1f9eb5a0b129a4bdc77cc6dae8727d74fe21f0d870a43f2000000000000000000000000000000000098a21da6e983228ebbed0ec3704c9d2521e935506c0567e3bbf9b9c379ce6d33c3d0dd8f5e013b431f740964db634b000000000000000000000000000000000a7a38abe8e282544ec6c8740dce8559fd264393d0a5c9af9813b2430bdb92b3150eacb6732b9cc278d0d0e622b263ecace10870acf190b373c19ce615e20e5cb96d3c6be3ec155f2b29825f8476b7740000000000000000000000000000000019ed305bfe8d8bfcc20794832b3c117715b6a658c0bfeb629e5989f265cbb456e857e53d168932589e4ed2806db7c4b4000000000000000000000000000000000e2ffda25fc316a38f556b35a7a3acb1a2bfbc1f9469a1b6427ed1f216e113a379932b0547f5370be1017a1fa0266cfa000000000000000000000000000000000ebc493c9a79b8ba58f48b90b9d287c74f505dcb484eabda79ada987d63a4df04d671d4c4ae4b32f8ad5db6a1b80f37f0000000000000000000000000000000019fc715d26c0c7a0c291ad8319e2e8f2920c63b4d4ed3f0e2f376aeddd4f7bd9269175ac8d0f421b001e2e48634f3f238d9e38d9383f09cf0f8a8077f1d1dba091ff0abdf7e77c3b65c2df48d6c6f536000000000000000000000000000000001285ff533da833a3daae7d815b1b86feb6f20b7592af8b0eb76240f390ea48b69a75547b040e7282b71779f450d3510c000000000000000000000000000000000813d38fa21c1f3c87b9c97ac03e6aeb8fa23e0340a0dff4e3892c774595648743d0b8980a7bd21648ce9b16a245ac3400000000000000000000000000000000020a69dbfb736c64e4cbc800aa415729b24ec05e901f2c7ba38e49a21c3851dc03bd4f7ec829d4326fe6c13867069a07000000000000000000000000000000000d518f3944053c8f74c0aea1d054d89106312880de4479b3dfb45b00945ff8bb58b12f9a489fa9fcd87194a71475d0a1abeffecf9b404c6bb2e2d0c78fbb8609a38e3d3187587c3848e8f9781b7e9f440000000000000000000000000000000018c82052cd483eee7aaa421c2b998ab0b4b32326dadba03c1d923726697d3940b40d5109ba34de09439e833ebc19daca000000000000000000000000000000000e4feddc3eeb3fd1eff8316d5b0cba554714713e8a605a55909889970ea2c8c58bb6c568024709def73b29a5a76563c100000000000000000000000000000000098da4cd0281a16e2e3e542ebb92269c8208a3d373394b0af92dc8a2676f9f0b6e85fda9161e32558e0569cfc7b1f3df000000000000000000000000000000000b7b54b51821fc037f02167d2e640f8dbfd1472407278b4bdf47b958da39f28c64569c3199846c293bf60e86aa45f205adfe53846c0038203d8b8df0cb636aec7d4ed7f78b0b0c1734be448bace08f340000000000000000000000000000000003058abd4e3d49c86ffac9c95b1f07b66a22c42654dc4a2e3b07b87c22024a8bb0ee084a558ac22cc9fa286861fd77ff000000000000000000000000000000000fc9a89ee26c323df22add487a6bb278ca3f4c9a91eba4e067d5abc9dd3afededb4f98263e10083cc7ea224f28d3bbe100000000000000000000000000000000058eb015f1e14da860215d59165e12feb8d1317f652eeb76b3f08b38ed943c94e632dbf8145233dc93755e44e027553e0000000000000000000000000000000010897d5c2b481f9937d830b333e7649931e801a6bbffb7d9a3ee28ab1e27889691a9f0b9616a8437c3cda942bf07282206e9d4e41b628be51690b86aa8938db066c052f3adff774d35eee1e332312d3f0000000000000000000000000000000013b88963296d8c8197cafe160846ee11365b7a991b35cf5613dc57714aa48307f4dd9c6ff9704b29905c18a41a48010e0000000000000000000000000000000016a97fff65fca5ff282a818deb8100104308b8d9dfacddcae32fc2b6082331b44fa70580018930fe1ab9d9c1b13a59a20000000000000000000000000000000019cd2038acd84c2db1f0fa1b7eccc5f7ae3da803cb72c4a1e8390d49e0adff1d88a85696d9daaebce9c6b8a2f861fb36000000000000000000000000000000001271338587f06847770c72dfb3d9a657d05f8c7a012bec77a7d40a98cb1637ae99281c82668486119608b01feb25e6dab3d349b1546a8c235d60c41408c969a0fd42425f8b5ddc1fa5102d2821bde2c600000000000000000000000000000000173ed7c70f4683102cc6a276d192a8f3b189197d5ea5dc813c7d0162a1649e906f76a1c9a1cb1ace6e4d937934b72338000000000000000000000000000000000936d260b789b1a2a9d04388caab364049395be61d320aef66ce50f052eb462faaa2017731518675bb0e4a2f050e4f7900000000000000000000000000000000070bd1254cf4b209ecb40afe248f2e53c390636625460439952ca2977be021d93fbec264c31ced2a810e8a5e54d750230000000000000000000000000000000016ddc3312f8ed359792bd213d086a0ff1540e3e5a2dedf6c450fb96a9b6d1edff9bde31fbc04de382cf44694a631178229b83950e79750e9827ed92856e4d1e1b5f0b47c6bbf3611a1fef8f2fc47659c000000000000000000000000000000000aa4bc6e1a3e6c3c45a29db74b27af27b61856e2cf385ce0e5094ad53db4d31c4af45b5b234c66a21bf15018c13ece8000000000000000000000000000000000188affc993bf6c99103029c1e406bb1a693e4f1dc650907809ba3de1471d41095dc1866578962c72538ca85d09fcd22d000000000000000000000000000000000e487a7151916694b980e62b64ba49ffc54aaccfa0b0fbc5c14fa4a50d1bfda55698df5cd8570c07030f145c49a4ba9000000000000000000000000000000000084a05dced107d29a0fd4cf817ab67017ca33018d5c7302167d08c64c45c5c455fb5c907f21c39b8a86d037a126df4e76b5ac07fb4a184dfed685b93d2265cebd02a3296a3b0416cc6a115242079752e000000000000000000000000000000000ea7060a07dacd84287007a05b494bf19a03e5a759b0ba67624c54cac3562c0ca3fa6e444206614d00d6d6684b86bcb5000000000000000000000000000000000eb2f332f4481276f931d2192c1a9f6d7585e85f248a8ac95aed398cb61bda05230bf8b9c041c6f78be3b34668a9c1a0000000000000000000000000000000000faa038219f844e379d8cce55cb8f0fe2b55548a0a0e1e37e25ba4f432e6b1a6451b8f081c171490bf055f81cbfe5f8600000000000000000000000000000000037c70d4e8befff257c4bc98a4726a961f3e2e68e7e02f9f2c94aa8f5fc67a1da44d41394dfe376a6c04240e4cd5825f3a7a25ad9f02bf51fd73550ccde12374d9b151f2f6fe535bfaa43efc391f789700000000000000000000000000000000100a24d21c0ddb20d76b6d9fe642da5ac1de28afd642ab5c08574206b8b64d1fd822d295476bbdf2ca7e9267138034dd0000000000000000000000000000000000aa7e4f2f77acfe8b4c8f3fabd56b17415ee9bb182bca1db15c399479ec60382f980067b9d4c4ef7556d621259ae9110000000000000000000000000000000012f7a7f91a988fa661c661013736f0ec92b40f571ac15a47067bb847b09ba128d1dcaf8049b941a51cacece5db4e1eb40000000000000000000000000000000007528b0ea66b6ab8d5d318f5e4d1c0e9a4f504057dbb0397b614a1adb160032127f2ac35a1a98da70f023cd343a35ffd47944c8c814f143f746175ba0b2d75e2ae73730a265d869763f0e986c088bfcd0000000000000000000000000000000015d72b8d4e71cc092c2875de80f3d12e003804d980a4b1dd13cff34e9336397c4533b6ae3a03beb2f09312a605947a270000000000000000000000000000000005976027a98f7b0caf4cc7d0d71440d3e4fffb1ff65fbf32dc890b275b646f2a32600a6215d6b2f999eaec8e58cb6d5c00000000000000000000000000000000111583b7734be53a7d4d090486070cd3d9622156c52871ec79c83ca024880684eada56a36b58cfc3490e65de41e10579000000000000000000000000000000000fb670b553c2ed4c81962b149efd4b0c77edf6ee70eba88300cf264dda98190e550540fb9fb95748599bca3abadd752030f33b187df3516866f259ff959d57fa9c53323d5c851fdabb96e5ea470518ac0000000000000000000000000000000003900e7cc0a8e891dc4dfc45f08d97e73ccbe2021a560a92c493aacd9c0614ad100294b5d7ebd634ffe4e5ea301a26170000000000000000000000000000000011ccc136127189728a7036e85d233fd150d5483963c48074f9d8ff83a0791c950da380e717f2bd0bff8fc115e9e886290000000000000000000000000000000007d3e76bd1f22679d228b4ee50a60cf1bd1fdaa171372cfa34bf4136a091abf7e5ef3c6b3446fd41d5de68b563fc7ff3000000000000000000000000000000001107f636d9187155357bea75c943dafcfba2394a9300054026b46d6f9db31eacc06d1f64c2b139af297dc4783026d98f4da8401050f30459e026a207ca631f0684a10813c64ee86dbdf06b7b29cd9786000000000000000000000000000000000e3a4101f6af3cf0d5d5aa5a0ebc26852dc69f91c06e96c5f1c7f8e4528c3dd92cb6f629620136ec356f0657fd9ebc6a0000000000000000000000000000000008d34dc3e1fa8bc22258e23b504d442a11938370325c101f1cfa52f313724e0894be722646195fd078c1a49720cde8c900000000000000000000000000000000163730996c79787e7ab89030de2c26e26188187762fa128ba4378a398ebd906dc56d99cf228591f394396248665c196600000000000000000000000000000000008f0a8b3d003b6727834228798950fb7a3cb6b931bced4540693445a007b474f7459ede17f87158e932e4c9c094ab904d940555d48649f30026f70450b2caf2b8f7148b28bfd4349458ae89c323512e000000000000000000000000000000000cc2d30f7d3869abfc34719f40b0ddaf00f52bcee7ec09a16de51785d55531fa7fe3ca1544d7103b9caf7105d60d9e930000000000000000000000000000000002ebd8af0bd3f82dc9dca585feaa83071534b2bc2b3d2aadbe0d01d759ade77ecec3b3f7b72f82087365a14dc205add80000000000000000000000000000000011aa3734a4b9168d3c46944cd726bcb203b94b25a97437a6aaace9c84da708bb073ee10585f28bc41e0601567863c193000000000000000000000000000000000ceb4ae5a8b506d31e77e2a43f3af8ba9459b887a927ca5287edbc2ba7c7cbba85a6e4d35c099b7ec7bf7eb2814cc38ae140e30424d2cccc91be1fd3a62d9ee49c9d64fa062d9350b3fa567ec21bb06b", - "Expected": "00000000000000000000000000000000192eb406b52075513584ae3c6093fb534270d716c79961d0a3c4bbc44096a2e8d28228363e2c8da54857945f1b983569000000000000000000000000000000000ee0d95748b13b531821ddd71a15fc529a2ce2c99a66f14e28f97478c3c2d524cb7c4cd7e71a1027030765554b8f50f7000000000000000000000000000000000610ab3e064532ce261aa2ba4f78721ac4f78661cc13fa09ccc279267e6f703f1bda17265a5eccb0061ce24d31e000ec000000000000000000000000000000001966a334b16e64e4dbd66119af97bd2b8d6afec0eb1b8207f437c00ab134ff369b3b3c1bf51b871a7fe8ad1ce93dca4e", - "Name": "matter_g2_multiexp_29", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004c22bd94b82ed3b106532a58a0253daf51f579b9d746c624bbc6b58603942eb139c1b576241ca8fab5bf1c457112bd80000000000000000000000000000000010c6f7551d758d1128add57b110227296e060074e4cb934132368f079a794770ff406fc7717867df0f461f5c9fe56960000000000000000000000000000000000048f88afaf6eee5039b76c0c5b4b49671f6fd04f38bdee1b1c8f347a9dd4e6aef387b742c8f9a8aa387ab4d01fe4267000000000000000000000000000000000e7be987d0411dd7138e47ac00f9f07c4737d93aac501edd16362ea5a633c9071a6bf542d4db540d75edecdedc3a8f0ca57b2c351a7946a20cbae1fd789ecc5f77376b09e911749831e9b5680185b15300000000000000000000000000000000056a29b523b0cf85ab04b0a496e078dba5529cb9699e567ca42f9ee3e3f07b61ae29b0ce17cad23131375f624a366157000000000000000000000000000000000acb91d1f057c7aec1f7561614a95f8db2252cc879bbc2595a5f607d8b0ecd6e6e3ec19849eacfca62d870b049ce84910000000000000000000000000000000010d9459e07178af8e125c2f66de699cfafb5f87a63454e24d0ed88b6c804a9ff204f146ecf4d6db62234ace0a944acb20000000000000000000000000000000007256a68e23b43a3b6475b3cf209ec108bac13631ca448cc860672c65c1760a8299fe941ed5bcbbbcf63a683e86806ae8fbff9f8ac4ad10718d46a857ba28f182263bf2d13c8b6a00902af737dea56160000000000000000000000000000000003e33b840426a6bbe15b23fceba829bda9a5ab89d37e60133874f61bf1b10e05d460bb5d228cb178cfae2a5f41035d32000000000000000000000000000000000a9c5460c6443364d9f9440d101d92a0037343789ca0aab6dffcc2bf81e1aed312299a21556d16e55b1398334d9061f00000000000000000000000000000000015db251708253f7de13a5eeae5aa76fec415ecee1ffd88d882580da5da8d9f96c6ff90d920b329096a103dd71e7cfa580000000000000000000000000000000014c3a004cb6ab8465e05d965dc720b37084d98de424b160062f225dd0b67a8e62ae11a3c7bacaa129a568f3a243357ebb061de16f4f609c6947733b58c6444fa9549721fd9a2459652e8e4b8c69b5d61000000000000000000000000000000000c8fecac8bee21d916cc47b96a66b7a522ef4fea76fcc86ec490ff44b46fc01ac0446e3885e36ae7ab62a409ccffcca60000000000000000000000000000000011676ccef54bb27ab7db0b5ec025a9d1f29217030f3686e71564fa011d9fb598f44a8bed3da8fa7fcd10d01e3f66d86500000000000000000000000000000000093aecb91956215980854c6f19120777983a160e16026560c8076bdc4372f53065f9fee0f5830ea192aa5637590a745100000000000000000000000000000000035d773ef15d8d99b600a6a575eefd661aacb49d6540639223a454594570d0f00ba37340b63a2c8a0d4e53ee7dc2dd91355ed5b57b28451ad98fbacd5ae87551b7304e4ef5cf7b7dc443a66432406f9a0000000000000000000000000000000007b2891e9cea2a464742c7f962deb1566c9d4f9e4e7cbee1912a72c5b064211c39801bf42bd888bc239e6b4ba71d700300000000000000000000000000000000169cf5e706dff2945145d5ac14bd5fc8f7e7c3e5f7ce733c865e1882d236926c71853efbea26e13efe4eb0d0e7ed5db6000000000000000000000000000000000de9ee19c4bc2fac36debd4c91317e54f57e761866b134ba9a0e84a8d268b11674110ee8f91aa8a6b80eabee2e5e75ae0000000000000000000000000000000016d91408a670e4ee43ab8e21cc341596709113950d22bdf5073cd90f520667699e94f64f76290f1bebfecfd80a9e051430b6eeb01874ff4b0fb07dc9f23d8e45455c1480eba7fb3033942214e85a7720000000000000000000000000000000001982744a15e8163a6f2ee681bf27a68996682216037d67d91993fbbe040e16ea21a9cb600fc6a40e7289185393544c3f000000000000000000000000000000001131d7dd5a5b96ac1f4c4aa210afe7af8d371cc16d32289aad38c93afcc1d3be53716f82e9d14ce6b1c833f7f5871ad00000000000000000000000000000000009adedaf19fb8823ec55b803c9509ad98217730bfc6424c8b69a071e99d026492e7c8c4a06509491a3bbe5893988c357000000000000000000000000000000000cc60733a783c7df76541daddef2245e6d2b694b94649b13c21aaffdce124c1cec3fd8ed5a5d4d4eff3115ac933e5df989a697a0e8d2cf512edd2a3c3df354eb30a3eaf697779dd9270234b367c2b5ff000000000000000000000000000000000b366a80247a8e3797f1c711aebd60c99ec7caffda34514a3716154e900f2387c46f87f81af036a383e3f9234bd1b50e0000000000000000000000000000000004608b7cea13d08724a2cac691e61255ea7472537f7ff59894d511af7fd99ad72f0a7406271576300a7d1d56aea17bdb00000000000000000000000000000000141abedc914d3d1ed587162acbfddde60f7dbc1ee5e07fdb5f3515b87d1a29024c9e19f24e4c0e3979bd938aa4e798270000000000000000000000000000000010e72c6c0510495dd2c4ecaf13c1c6404654e1be369d1ca485c76d8c2304d60d69b90c2e171f18bf55668232e747825820b72463d54ac1d8f1b3f56f0f98861768b05d5174cf1883dd8eb0410420d56200000000000000000000000000000000081d5a229481fd297363e8e217bf1f94a00f54eb6e8a3f95f4de30081bb2b9edd82d53cf287e37b459afabcb73fea1d1000000000000000000000000000000000ab55f52ff7dc578ae8267fe3fa09bdb8174dc30bb835cab9851dbee7a1aeba82e83e07d5e79aafb34643d9fc9a0d1c100000000000000000000000000000000195245c7a762776bc1e81d7111e3b814088f1e0e7d686c3ee3e500cd0a7ad4015851563a1b8b592e491e00078187c66e000000000000000000000000000000001850c1e8edb0d6dab973a9975833cffee8b5243654bc4ebe64972e423799283707f9ad343bfa86548cd2acbe04ede5da3de7997113708f9d092836c2b0b59abf710d8401baea6de73ee0689436f035fe00000000000000000000000000000000000007e9191fa9057cd7df8fb83d497ad774735c242bce9bd34cfd21d3f8f2a8e37d1f38b592a61ac8a8d22a4287fc5b0000000000000000000000000000000010e36db1460fa65ea229402f558397c6fc57e9c8a4b0b9e85d9ba938196bfeffc951587353cb7c7d84479f60c087e3660000000000000000000000000000000004d86938bebb850fea82acd336c3900b241757dd937f831dd909ce548325955f103dd57611c0b75bf71412a6ac3d6ed30000000000000000000000000000000013990c82583007b693c1d6271c1e5820d7274c4a729da21a76eccbf7abab1f2bdd6c5d26e78d51476ecf154e4fecd1b87fc3d0560432dbb721f8a0610f0db31dfdfea8cd5ebe8da3fe3b8ac5358dd4400000000000000000000000000000000009104610d5887fb7cf6a866584cae30cfeb00e1241083b017ccb82ddc9d72fdc0d2b1d227c22ff6d8497495f44828efc0000000000000000000000000000000002235f959b071f21fd63282fdbb46b1dec27cc193f3e9988def691c73dddd789b6a1adb977a68e2661fb41d62280f229000000000000000000000000000000000ccd46984208f183f0b70c9152c01fdb8ac078ad1d85f41e3a24819da321d9dd9321a8d70103282abe6d8b981447f202000000000000000000000000000000001711057042a54ca76b0c3e7f36f2fd49e339b76cbd2e053d93ec2838848d359865fdbbeb9e75e408b4b316d60ce2741ef0b271f02031a126f8632e30d8b17cc5b57de7b8b873e0971ff392d4246a40f400000000000000000000000000000000001481684941fea0f66c78faa40aeb4b5254bf78c44df7e37b191c095ff12fc94248acf01d2aac5637e9536e73a82c9f0000000000000000000000000000000016b72eff2830f49b24b1e1317c95143cda8bc11b9dc4a91ff22a24e0bc1a244c7215ab1040fcfbc292ab236ac73cbd3d0000000000000000000000000000000013535421771fdad616171f7348cdf32bea7486bf4d836b8b95c69b71ea9915c099e256287aa119af53cf6320ad86664f0000000000000000000000000000000019ba0f36dc556fcf09f0a4a6cee53de485d03d846af7afb792d16220551fb5a42a4261f936b008babc096e6f8f68b63af8b5c136aa5e2d670edcfb5bee9ff6095d85a332ad55763fe1e5e8babd145c070000000000000000000000000000000014b2da0add872d6e61253d6022559f668bf192b4aafe0acfbbf341ada55b404d42b2b31182c1ad50c73673494ea5b7d40000000000000000000000000000000018b76b74e9e6cda8466a354ff66baeb935b5645cf9eca81f4b7342f7914c9bf35c57be402458c09781e66a89cba6e67e0000000000000000000000000000000019bc8c1f32ce934b7ccae6d8ca39a263939585d8f94414c3880fc7bb5a0a27d728708e7ebc42c5a935f769adcfc083f6000000000000000000000000000000001636b62bbbe34bec06253887b78ad5b3ccda1bc5d8baafe450f2d1a8e07334ca79a40c5c4a50b58aaed96408749e6f68285193e7c10646a4601787edfad3d76e19d5b013a0a954873d92bd5293d325820000000000000000000000000000000013c0fd7a8441b6eb2dabfe8c152aa480015f81139c46440741f3da1c50d18c17526c47e8b8c2fbcfaefabbad5f8a0b000000000000000000000000000000000009da839802e7c6759a87eeae5a05146e1d226dd828d4ef6d908b4a0431008f352539f3abcd3e4c532a3d8204e350a8510000000000000000000000000000000014709634973e4554d2379e439d099e9be8bc7ef031b6ea36a7a85d2ff5090b0e0de7cc1c6b6a004465edcf868ef5fd5b00000000000000000000000000000000146779393d82bde1eaa6205e69907a0536c782fa7fc6e11e5e62ad5468f4422b3688f2ff4da2af396741ca5e0f97de3835bb2175fff61894ccbb69d90375df627e925f1ac430a349e75580dd39546e44000000000000000000000000000000000ddb7d0380370830803a7eda2e9b694af71381990f182b5d1223992abb5afe9531bbef8b9dba239f411fc422210fdc930000000000000000000000000000000018b685009d012d72193043d09f8968f9a41ce2fed598a20536fe54cb26db1733214add38f73148e754e632f6d78f524d000000000000000000000000000000000b967a7b4ed1bcd9f3da16584b08e0c28d967cebe7a07069abfb3bbce94d26b6d95d8a807879b24fb1f5ea00091d6dc300000000000000000000000000000000039349785fdb7d38707d8136e9a8f650c4491c50d7425388b75fe30da56147992c3d662f22131ba7173b2550e613477fa25856e5fb9547c48d41783bf2cd13493a1fd71e56b9c7e62af84a1f6cdae1c8000000000000000000000000000000000455d7799cc1c2af1e219b23e8683113fec126bad1dd7a441c5d113b064b552ccb1e7314dfed1b11f42a18acace706e50000000000000000000000000000000014d2400aa3e2270714b656bd755c4bba55866d6e313f619e10f94de6d82b5343ae9a9483dc10c1a72a5a21e619a20a8b000000000000000000000000000000000a6caa6cf8609d23b7873c908e5321d064a9c107b5492d296d04f92c308ee705229dfecb1f908bca0024ca56bc125126000000000000000000000000000000000b31c384423c84316f65e03ba9e01a8f626236f76e4df4b8ce2fa053c1c1e6a9b8f0afbc253db8c9c5e2ce9f9dcf05c71155c0b9c4185025310e8020eb52abb6f2f1780da15e4ba81f3c9a88ed1b4a6400000000000000000000000000000000097938bb53db8d0aeca3f2bc180039a5dc5269748e9cf065cd88e59b30733d527e54cdfa224e9690581e8c7f0881241b0000000000000000000000000000000002d52d97d4dd415fb18348f4de78c65e2933fc45d5e5e1d8f0f0ca1cd52885704ab12609b91d6d2d1ce13eecc7fa0c2d0000000000000000000000000000000018b926a37a8e0ad836846d06c03a9b84db795fdfe5f15d1fd3e0f8fef1b2825b29ee3a503ffb2f75765cca49c2b3d4cd00000000000000000000000000000000073bac093e958a3a09543e060c81b35b6598521a8685629f77200cdc73b372588e66c247097e7c03492c0943bfac4d6bc5610b2707ce84ce67e82d5c0e5f5cd2c90925aefc1e39468ca86475012df045", - "Expected": "000000000000000000000000000000000f79110c74f0e983f3d3618869af1d9b96dadba61f1d596294ef8a9412f946fa26cf63483528a57299dae48f85ada81e000000000000000000000000000000000e1a9cea3af1debcf7d6ef6f7b8566b5bb52d5548d4caf85925109228d7c9b50d65a1b24f089631e75a694f8e8dcaf040000000000000000000000000000000010efc1081f079e841eaa5a65cd7c945d4f37acc92c4ace9ae6c69a9a95d8cf569d604376b1c7e63558d022da90d269fd0000000000000000000000000000000010b7f55ffac8d57c89b664c36c20b2988a493de32f5a956c91b16ff67cb806298a59adcde12ead42d598b6ca3e1b94da", - "Name": "matter_g2_multiexp_30", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b139e5dddd53433362c49403838b3e2ecdd850a8df12d4dfacc0bb98f79d40966d62dfd0da1e721e7c0f298457d590000000000000000000000000000000000fa35e9c2e37bee1020ed99516174408ba2cf443fed115fe3a964ed86b5e5369e40291dbfbab477e339003ac85eb7405000000000000000000000000000000000e8fb87794860237066ed1b7ae7c2a783c48c52c2267f3e7295d1f17598b96232954e1eb6d6e80e716628f1db8afe48600000000000000000000000000000000083521e3a6d6e3f99570b747498520db5c89092b0077519c8421f9f41772c7a6e177c9cdca52f89a26c6036cadfafa8b32fac970e52778cc90396a5ba92ab98e26499eb1ff17d4bc4c1f78b64887d3f1000000000000000000000000000000000b1415e1dc2d4c1f5619b40e616d258867493d8624857e41d007f82ba8dc53f7ebb36d06f8348b94eedb794899e97df80000000000000000000000000000000001c01656fa47d62b4372361b80ea61501cfda47da5534e3e2aaa27b1e3c4de0bee0aa322e60c476fd4345340e5c00e130000000000000000000000000000000010caa407d9d265721d55f01dcfca52bde851ebd918e8fc4c752a41875940709c64599f36fae5e3ac7f211e1f67890d1c000000000000000000000000000000000b54a86474dd5f410290e4b4ac738fbba5e88c6debec17e38a52090b17ef371dc8feb0573e76c4b61d7688547a89f6a36583bac9672a77f2fe62bea4364aacf62d5e10eb3a757fa0595a81f76543e8630000000000000000000000000000000001649c78147fefa91100738e50034424244d22d8e1bb6a2bf471e4c9b29694a5c9476f4b129912bb09fece53aa87deeb00000000000000000000000000000000117a3e040c1f54b96c2435891a45fb9dd95774b5a55cfb306c22517e4ea72172332d893047f7eaa665fcc58dd21781f400000000000000000000000000000000105e8d80d46e6bab2bb9ce0525cbfc82e8b3320ee4a8b9c0086e21cf2b5895cb35abffedd1b5a9eef21f62a0a1dc48e8000000000000000000000000000000001437ee33abadc8ef6bfeca16c3edcf05480c3dd97db06e396e10d5180472f50074f43f9a031a04dcd11d803462fefadc5a8e1d77c9e42a187054c938a8a5b4bafa834021b727036ed3941b1c1deb9d030000000000000000000000000000000003b51b10efb54dbc2973e001f0bb634e36f689264484eb128de2882d6600a43ad548bc7d1def4541f0ed88a1fb37f3270000000000000000000000000000000009dd80dbfe6663ab04656856f192002593df9ef7f792dfa81f6a51c658c4c9ce5586a5edaffefd507f51ccb7e8c8101500000000000000000000000000000000144160d5ca6b2ad626e6a3424ff5139adadd3319940afa9bff7dc409ac1fc3775d5413ef4612b27fd22c02c1fe57bb86000000000000000000000000000000000e375ff490a626dd1d933a5c751c88cbd61803986fa8dc089ccbdeaa0a922758afbcdc30d29268fe0a34b7b79d0f76c139c02150e4e89b25563985c7802c0c43d00c721d521b54e767c1f509f584bf2b000000000000000000000000000000000997ade20fe9c0d3eb79e61a66a5c272d02af668b0f3c8201a1ea071737f3d2ee3b0764f859480e95be75ab8845b407f0000000000000000000000000000000003215194b6a363d31ece09b18700479e6093fa3472a23ef0133e3dce60a3d56b6fa984b900162c4ad56a6899aacf35c3000000000000000000000000000000001647647bbc399f40124c43510469cf613732d0919e22b478b2603d7553927584cd4b3a407e3ec6387c4a93e9e5373178000000000000000000000000000000000bacc8afdd70e927e21521b3f62264ad4f22adbc872439ff851d3d169a1c79a0d02bca2aabaa0b9941ab1c71d092fac12196ec0e9d2f572856217521fcc5e2869f16d5ec5fe76f7d350698f55ff0c565000000000000000000000000000000000b0c5981bf6ef5b85bbc504fb0196ba442fe87302346688165aa7df8cf2642548760e11daf5b3fe2e37b43379afbfd4a000000000000000000000000000000001086828b9560aaee5e28bcb50db8153c40e632b18c61ed4105bb7f472b6a69ddd8a2836f6605102931ee66b2f07e441f000000000000000000000000000000000f4d7aa3d1a281af6f8afb3d886774f4e4a64490232f63dbe16e3b8c4f626e9d07f7c668d09cadab3c92d6fe852427af000000000000000000000000000000000d92ea3318779b532cd81c9be44b1abb179a8411319a6f8fbd7e3f158bc970917d3e0b25f3f3f6c8e0764011f9bab0398df5017c9c35604f061a7095d976d08bb3570ef8fb518cb606cd39a3060157ab0000000000000000000000000000000000dbd83910f304d0fb2b6d8619c3a308c719f6454a357d9ced03b2882a50692c06cda7f4331f54eb293ed5aa079121fb00000000000000000000000000000000019c33ec829367dfd2610ccef9842ffaa5e4f35809657c22134fb09b024e07949d8370ba8ba1e9149060e9bd3babc19c000000000000000000000000000000000ac468b42925d2daacb8574d40064d393caa643f08767d20e72ac0fad1447a64d8743523312f3a91a118d3e51e1f52d7000000000000000000000000000000000202d1971fef2938cfd10bef5900b91cc4811939f66f1f5578a8ae0eacb2538d2a51c1e025449e1637b5173ab7fa3b6f7b82e7e565f8a521d1a9d0ecafc029f76b70042e1ec36c20e3789b49c7e50ef00000000000000000000000000000000008b6709123b9bd501360fa463dd08076c59177dc0e8035c49fa2f541eef3831e4c584c5a9410c68999dddda6c86fd9d5000000000000000000000000000000000fb94eb34355c636dca909cfa71f52471217b9bc241cd3e98907d4a5c7eb67d5bc9cdb0c73c1369d7950a014fe6069fc0000000000000000000000000000000002e2ee515a5dc96a664bb1f862f21a8d3b7f903fb87f6dac41c3541f3d83633f351ba8dc4661607d24b912dd1ab097da0000000000000000000000000000000008bee545e00e3fc283185a85511e09fd0253e191f52d5c0b440b10228041800c013db3c9322a835e4927c0ae0b21bc1e8260c1b7a249ba215f0dc127a41876f858b20f4422140bb7695c8f98e4c474d00000000000000000000000000000000006ba635e74538748c29aa7c5690a0530f2b1970554598a432d4ea6d2713a4d26786b6e80f67b2f39e218b19323654ea200000000000000000000000000000000133ca9e5e0d4a8200d3522d8e87dec3c72edc1cf16b7305af4abd466aa7a0e30159388d34c36ea030450ef45b7940ec20000000000000000000000000000000004724239afc773688ea92296bae8845f20793c05807a18d6f35f03bef295da06f8ac9dff438b720dbea7ea93f3ea9c4500000000000000000000000000000000149c12922fd69e1960274a8b91384e929fb354936c020911495e6e3c49faf16899ec0c6e87713ee2f0149bf808ac8abfcd68d2b074d038ee0d9887168dc16805ed55df26329a4c0e062c2124a6e5066700000000000000000000000000000000148a4fe6ca67b6c785d5d8a784d5e68fcd2bd08294ca37f296b6426433b805507b554eb9f0fadfa9d293e8cdb8547d4c0000000000000000000000000000000003700600c2b7bfea54801ac95ff7a2c069bace31ceadab2947a0641462089fb43f0b9697acc005a23007a923ffe97360000000000000000000000000000000001705a769ce3c9a7a91283e4068c602d85808980d6fb457345a5f9b2499ff8fb3ec8383049b9b7cae96bd2ac6106a07fd00000000000000000000000000000000052b1f4e8a48a5eb2b2580614c656393819b4f0ffea874be899e4964c7e32d54757f2d48ca7b50e47e8bf6d6ab8ee7572a40c2e796148ed1c539b0584b90cb386844fdcde5d3766cbfb1d1b58626fcd10000000000000000000000000000000012ff8ba50d587765e68f95d276e364c8c40c00b55abc929f9ec240985269eb096dd3cef5826cf6269ecf54bc67773510000000000000000000000000000000000959492d74cb34c8c9ca4a21ddee97df99c8a6e627db3ef72200f39e0402d56f0a9709596189c80aa3aa50793e0f1a68000000000000000000000000000000000f7e5dbe884597054d6dc5e80bf4d0d333025bddebc1fdb1d61482cf15bcb4c8a95ea29cdd0925b5b816cc0bb307387200000000000000000000000000000000194e940c041d71f43ffaa51fbb31eb63c23559069b42dbf8777f35eddf14edbc3f7762c7b354174a584507ad714948234a1e176fb26983e549aefff9aeb220f50e071222073422dc2c44abd85528ee2800000000000000000000000000000000101a8e54d1fc2357df60b0ef8872b729295218f29ff63f7a7b6a70b3ecdbfc6809eaa8dc1f62a664b9987e8e86154c6c0000000000000000000000000000000015b5ddd012b42e1a600d738e05b551d91e7fcf3cb36018ceda9b689b92022224990c11a6fa0b421d5610b7e59b7463c30000000000000000000000000000000016130be17fceab55387d43179cd943c85ce1ff1881c07c937b2cc0645ec9ebaf0e10718ec7fe0d720f49bed2b8caf15b0000000000000000000000000000000017d73650680856bc11619e6acc139e137f0a06476f5f8979b5ba7fb8123d85916915da60d1f2e8c84197eef518b350c2a62e07bb97ca3805ba2d30f39f44e70a7b2917889c26b84bac8f9739bdf764090000000000000000000000000000000007d26bf37a97d532ec93a3eac00d9d39b064ecd172ebd5e18228b1601eb7a2c272aff9d88d63781b4a587c2c8582eec4000000000000000000000000000000000108000e850bfbfb02d7acef97592e15ca721334eb51197511b0eb2bd3bb647fc8f07713487b0a0bedbafb106992de4b000000000000000000000000000000001868c0b2ba732731f7536851f8005e8bae7b16545b39190251eb2bf93dedbf0803a42ec24cebd151998b690c38c0346c0000000000000000000000000000000016faafe909a1f926333b12f5463231a71058aec31d73893687d3169c4c3588436f6178447eed307b642490199c507d63a14278fe7a08174660c08323de272b2110047a1d1d8bd0e3c7d76dde030e00a6000000000000000000000000000000000331338cbaeb8e304fbb9257bb80aff5d3e043d07dbc476dec2795347e4c25248caad06ad14f56183d2b6276c49ff98700000000000000000000000000000000167e9578304a1162de73914b02791468e14faa2e0f161aa57818b8a169b5933dfcab787ec0f4b23737011163dcaa02750000000000000000000000000000000010aadfd5cc781e73c31f2fb64e7981b2e28614aa18dc7b2d96d2bb4ed8c2ee9089d6ebe0cf85479b272cb049e934739900000000000000000000000000000000128d7ea54f338064cd2f041f42a1a1e77d8b9be4ee55f568786a36f87f965d8142207e518798061eb3e32fe3b0f1541d1f516ab5b36a59e6300a54d17363ffebba35fa0c64cadb21e541af5078545b400000000000000000000000000000000004539f22654b3182d4fda5ab8d4bce6f1268d4e402b6c29a4cdff3b5abe0618d33db55ccd1ff12b27b2cb0196ac53e0600000000000000000000000000000000177e80ab6aa8512cc9e4d65b06b2bd76e33bef9038cdc1ab97fbb9d896ae2ad884ea16407490653dbe972b14e9c30c0b000000000000000000000000000000000c280a4431e41df6515979a694ce292f220278178f7f36e23c8a4cb2b8a7ebc520901ebe34c72a26b2c8a60aa1a155100000000000000000000000000000000006a0b80538a6c8093f3655905af1c59c235567d22192758c28dad1b715045189a412e4c1edc26e1d8ac95a584277709b3bcdb23f9568e409271b5f907fd64b0cd81939a52a6db38fd8d95de76213f7b5000000000000000000000000000000000eb091007672a212dc4937b314576963d7561657cf1103820ce9bc34e4d46c24f4891a4a4ada648f8cdd2c30f670b86200000000000000000000000000000000166389a37e6e3c02317d68d54f29cc98d1d1df5853940555161d71df791cd92c483eaad87dc0e765b12408d6ac344f31000000000000000000000000000000000affd0d5734cbc27b192c0c0e464db48d3d76799d2c6a493b172127ef2df6ea18a33898828effeeaceb7a203e35ca41800000000000000000000000000000000155708b9756752c9b44048c91d71970fd2cf2a4cae6b0baec00629c81387c8261150e78f856093d81e816be6403f1ee91b716b02b3e94600867e019be166f4532d264e0aa65d723dc0e117aded59245d", - "Expected": "0000000000000000000000000000000007ceeb14945414d96088a7900c1120ff182b2a93b09943c2fd1dc2b0b223f684b0d4c0b1b5803502582f2daf16d81d2d0000000000000000000000000000000008df450fb25534fdc456a8f41cc143a84729ccb082aaa2243c8f37e34a6670f5195750f8547444c49f7a898aa8567d980000000000000000000000000000000008c12d360078d5645b0e095c90d4fd37eb20f0ebbc6fa93fa5beda7e7c78eecc06e0d839268e2c303422ab1769402e0b0000000000000000000000000000000002bd594a21153d7c458b9f804050d05caf2d90bbf9d18def79eb8148b7f89e3a3ac21f84b87fd13c39df5b91cf73460d", - "Name": "matter_g2_multiexp_31", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003e06e2dcfbd695e9bda0baee1276ceab637fd1fbe2d2d6458c923c35b00edc7edf4f9e797aea59ff8cfceada0615a02000000000000000000000000000000000a04a2ed5e42fac7f064b43d64151a6c517ecf22dbc7563a3e9f35f555a9992fe45cf6a728ba94607df7c96f7e0a334b00000000000000000000000000000000090fac97f9f524168bc930d26ea1627ceaf187398d6bfc5a019c8467d75cd31a41c7eb9fda35fc85bd92b4cfca92dbff000000000000000000000000000000000f37b91dc935c28668c27d38328a511148c1739b65f2816dc53e42a8f059c9b2be7417a6f97c9a2597b1a0f06b7afc65bcfdf0495e49dbb8a8f9a0dc517351f39a6d823dcd42715f329dc78400bd74fc00000000000000000000000000000000090b834a587521729426d5b134c6058bf7999f4d4bcc0812e8d8b3ebb050961321b5e93356e87171a6f12160749394ee000000000000000000000000000000000cd5148c7eeac4aaea4288b38a02b5a901a6e2805e2b1695ed98ed86cfa0d259d87b65bf3cc9d00b8548100a60a371d200000000000000000000000000000000026db1079b85411dea0b9fca383956af50b938a465f35347605c01f3b72b297630ee2fb5252da20ee0d8ba5071974ed70000000000000000000000000000000012ae26c193e02d7ae4a7a01181551085dec9fbcac811c45d5cef19abf736ca2514e1259811970af5913891abe22a75ecf095238bcee61ec1317c0f98ad4f8f9b39c5940cf37a8a3a676787d9dda99438000000000000000000000000000000000ed5d8a609aa4f3c65a89b8dbc9334bd3cec6c7763bff298acd6c260e4d3bec0088e15c5d82618571d13b74a2031eff1000000000000000000000000000000000c28f92f018e6f822912b6eccfab37432ab0ab9acab751f848401791bd2f16e32ac6d97948bd8a0bed2ddc1917f0db3b0000000000000000000000000000000014083be2539d914883172cdc70950512dfe7be8893b1ecf085d837c2e9ba7f03656c5a0e15373e04d300869620eb66d00000000000000000000000000000000002561b77cc2658c54d29f8d1988dd7448f59c80c02ee9256404d8ef5536ee50104cbc11b6ee1ab9ccbf0ca55e53c52aae45a6d64cac817cd479a501c77b6720c6777c6026dbee471b490fee9f242a6700000000000000000000000000000000000fff05aea33a9d1e8f7b227c80ae87c9e7589ba2804904b7d8386b24b0e5324e718f29531251969a972870a30c310630000000000000000000000000000000016ecb8f27a369df13e122c981e7ae37882b36d5492fccbc86d606aa1198f3e4ee7bb7ad0555e11949e6c1783d8f4cda100000000000000000000000000000000187f425b675cb12719a01ee3b78ea73d88f70805f72d6cabef6372ccb9d99008bdd7da54f155454c4c59f041deec86f800000000000000000000000000000000151c272d5cb67b3f801e103ee901deb4b3d3bef76ee4e1b2ce1b5e663ed292845ba012c732d38f9209f82e77f1f73cf354868215022673de608cb43a3cb74ef2073ffff34c54fbb43f19b22a02bcc2ad000000000000000000000000000000001791bd59815309f2aeb7b07df8afd89a288eb6f19c7e613f394353ac5398267e1388c97b17d83104446e57f94581a79c00000000000000000000000000000000154cc72ada5a9c99dea06ebec143a14271cf332b57c631725ab30e2d308d6b688ca08a79efb6fce632cb1216ac3d077e0000000000000000000000000000000012b4c6fe8c17274ef57539563a736c2f83c4cb473e9d075a976e18e193255057340f45de373c7d6e3fe5e08ad0dd97d20000000000000000000000000000000005aef16e11bd4e7787bd5ab4427276ecdf9c6c134b9fdb2ec39e87ae4a5b3b674b5ceee29bcdf804ebd7e83960d8d7ef7068c3ba82e52fce0223a9f28c1d42681c7863c94797d1786c1adbc3e6d10dbb0000000000000000000000000000000008e57f905fa202c7640500746b590791cf9d0f160a77e5eaa5a30280e513e8e801c4b6b04cc3f80d9403388571d180ba000000000000000000000000000000000da3c128ae234bc27824062832ac10aa9cd4978f37855a8b4cde3822f5b485fddb9a475a9805e795519d7f138a8199cf0000000000000000000000000000000000ec11b7e07710161fc557a56e04337f71aaa1a0f070cd84525965e53a1fe445c91ac07c618ec349997890ae893c165d000000000000000000000000000000000406b0eafbb8782d11f5dae2f6214282252af9ae9ebc5c17a81d4ddded40f05d0b534d14019bcb6cf4e49c4c182b90f00042b8005283c7b91ef4b3ff7e20a91349c8c3d1301c9b54b901e8348a7d186e000000000000000000000000000000000b1d456e66671dfa72ef3a56523eb939146226111fdbbeb697983928aebd5f50b0518db841a3d48912a7a780785c1f180000000000000000000000000000000007a15b2253496b78d270dd55b80bff90583a95283a89d40f6df71fadce56d103f0d365fe79256fa4f93b2d2bf4c06a2e0000000000000000000000000000000010829223166d38fd2c3041dd5643c9784da366a2ea8cbb3abdffb5fe43e975318c86de0ac9ec77c0126ee75bd209f7300000000000000000000000000000000004b124018e83e1e5e77bad42eb831798d450f8ff4a79c9b14f67f080047c491fbba45db79b2cf6015188f9fa6329e8be0a3eb64ce8fe140d94956b0685f91a5462dba1a90093e803dc617559a66d20da0000000000000000000000000000000011119be42b90c7857079a51695dd5be08e59374b0d1c7e12d0ffe870202e1f0c62bff84c9691679a82e610e788b7b5e1000000000000000000000000000000000c7a64524c5dd1bf10d16da7f15b39d05c9ee1620d4dcae79c60316a1f522b238e7934d1be897a441d0c8e621b67d44c0000000000000000000000000000000013045613a090d05d07310865d977c8e0bb1caa713b2249d6676e7cfd6f4e3ba8e667deabf9fdf7fd527685f7d251b178000000000000000000000000000000000dfee7f8259701b5726b6439a7ce77b92245499906502c7dfb384e29cafea61f3b1f21fcd7888231569ebf29d3035a61ec88ed0eac8d0f2f618530e91cdb9ea36b8d56c1001a6792a09e11ff65fc02aa0000000000000000000000000000000006d77669207bb2d064824cb56fc786c631936d30db630be3c08e18d7e95b1c26e2d4e7b2eddc2f946fba6e99acb2198a00000000000000000000000000000000168bd8f291f8bcdf8b5e9fa915f7f24856a62803bbbeb9bc38384149008d4e3129338035061631f1fbaceeccfaeef4a700000000000000000000000000000000146bf2dedc262557dec2b4545c94a37434e20e4900b1693e8fa9bda9a94dbd07e0a3bee5f3bedfa42148791f4951db7500000000000000000000000000000000138467700fd5088c76af2f77fea4b746f98701fc0578571997b0ac2fc343354ddc8b2dc57d5298dd4daf767573d8bd3d5f03e53ff983fe4886a3dfc03a353fb77927d7a0d1998a1c55ca7421a4bdac6f000000000000000000000000000000001536da0df7c91687339fc93608eb404c5f46adf4b9122b99b1e5cee0012e27ddf30934d8f669bd39091f8673aa3b3c490000000000000000000000000000000002deaa8f9349e7c551e39751b1454a00f8f7896d63110e8e42607e8023ae3070c4abc9885ed54ee37a82f6e5c68451e900000000000000000000000000000000079a62eb17f7b07d4117956d3dab5d16a7f90e98948d5c3caa124fcf755c73f060a90d002cf880f5246a87342717b4dd0000000000000000000000000000000001246f0f3ec2af7c0250ae14cc67b5a1d42309f06c6f47b89178ff7534c47e8413a26a43f27454c0f946c66634563d41cc1b04dc356bd348211ccc4c50d12cb382660a4f9526539c2a0c52b021ed216500000000000000000000000000000000046e4a08785de985c66c7417f9262d363b9acee07e250999a4a7124f101ec4d82e3e4b2b0d9736471329fd61d0cff13b0000000000000000000000000000000017bf1e20ac181780ced62a18c78b378fc0dad157cf30d6026680560b681f5755183bd30b4e454764c08edb93297590b5000000000000000000000000000000000a57cbe93254bb0796eafc0a57330e38bfca37f8b94c4d21ba656e5616239e1e18ba6d632c0129d30291736fe37a4ac90000000000000000000000000000000007f31df7dbe9abe15f4024d8f6bed93c92ff5bfbd7835e08e870eb1bc4a6f62b3809b922c6d5a7350e2e5a978c80a67397b584ee05c27d45390aba36772ed49d571837567e95f1fd3ba3fc1ba5916727000000000000000000000000000000001577abdf6e915c9c3b3fa50a4601709cd629397f2f91784528e4cdbb140065fc2a6ee3830983dcfd49a928e78cf530aa000000000000000000000000000000000d6f98df9e41009837cbb05bc3e3340d38e56a448fe396bd48acf03f061e7489d1402b36a84b3c56eb859437e9c406f1000000000000000000000000000000001912afae5361c3d8c6141755deeef26d1fadf6b0036b9d05b2e0c4d50f42328741f0423ac772fc66dbc922bd4a837ac40000000000000000000000000000000000616661f049b5c784ba05334b2931509e1e033bd203fe17f04cfe12e80e73eb7075beac9d379fc1c457bea1b6adf365752542cd551cafc5d50852526ba0a23d274317e1e4a6e75c0d19319e5853b8b6000000000000000000000000000000000f98fed7e4d67a513c746d2fb188597a605165d5d299072aad6d621e077845f93804d575a5796bfa726f529dbd90e014000000000000000000000000000000000adb2d0b6c02e4e8fcab11c7c8819e87f73aab673ff9dbc5c50fee751bc7a6a8d386c8f9fa830b5545f94a73ce6e1f1f000000000000000000000000000000000f08e05ac40655cf59ee3ea9f10fc900315c6f06ffd3b80853560559f580ecdd65aba5ba660c729e0bb9576eee3703710000000000000000000000000000000009da46469f4b8fcd8d2b016e96f6e6582fb01c75407c36c7f87b4a1cd8f08ad06e962a0ec2138ed6fabaa1cb0115f97e2f76a0fa585828f79553fbf3baac6a2776b782de66dedd6b734f9342e734ee3000000000000000000000000000000000047b45ad2ad4f7b5b72194f98b98b2150b5d73a9df2aeb2377beed9a1275a882fa2d849037ddb56af632489f892a48a7000000000000000000000000000000000e1b0d9b52c0c5324067857ba4701f5f20eec165be418871fc0f0adbc3a0bbdce5a33277a33b79013109b81e006c621400000000000000000000000000000000179c471e01e340d8e6fc0f737ec09f0180bd2dd2a86d0817f753d1e9a9f8cb18178e9de68c596dc6a824e6c3c151d8b80000000000000000000000000000000019405c1e571a9b200ff2949aa74647dae59d92a8669d4876ba23f1b4a12a1f9412412503c68acbd619cae3ff056bd346f638e6a70917c89811851109296a7225f9c7c5b3d7fe6d6ba6c7d1ee77db4458000000000000000000000000000000000ca8566b9bd088c471fd33fb7b1bf760ee12cc8b0cfa9ad92b45012cafef5c0772d9bd3bd9b266d6c3e3890c8f00057300000000000000000000000000000000055789839e786ecee7fb7d10f3876359fcc1bd6f2c5cf25c8337aff7fdeec9b43ffbe932cc4936bb708571a59e4339990000000000000000000000000000000013cf827bd57d8179d105f34c147665a072714ccbc114aa4e878d04ce66ca78bdabdc4867b3968c75dead147257197c6a0000000000000000000000000000000014a8dc5ac1858442ca627eaa194e1ba64091b5f9ace551338d770c92fb49ee12449dc200c8c35d70f9e0652b4d9b90da1c4ac944341dc68fee586d221db2a8167e833f18f012afa7c3844def6dfb26bc000000000000000000000000000000001124ea2b97a6d73c81387a51e814b9bdc951a773db2a32d50691be60f1d397cd4aadd9b06e4f49c32b12254e9f824fe80000000000000000000000000000000014cb365e9780feeeff3548f34a56548302ae0dc73402c40317fc819969ee9c4ea2a181381b94f82dd97a236671b456a000000000000000000000000000000000064b769c4b785d45472038aeeebd3ba9b28b3132d72023640ab2d7512cc6e31296c5330be5653ad6902e4e15e57e2c3e0000000000000000000000000000000014c7bfb1f142d69c17f73e23011aee0063a97a99d982d25ff72791a65c7a68941a80fc216cea8a49f3df2d0748b1f95db0eedaee9347b10ab7b346fbc16c10cc9db486f561f88b756c269ebbba23a7f4", - "Expected": "000000000000000000000000000000000fb1227806c750e0eec0b865daaaf51afb74a88589d1c035c60dc1913f05c8ab18de24903ea876fda27b97a5eaa2fd7c0000000000000000000000000000000019903e1341f0285658164f9273b5c958060bf836264502b9dc298f75d4104d7a43b8d5dc0bb934a506ce1273ba839d830000000000000000000000000000000006e791347b54057195189e8b9f10fd42d170f37d455c0af5e92cc6a12e2c23990253be6855f4be6c84a708852c19a6f90000000000000000000000000000000005b72c361dca430fb2414b9d5a326cef8b77cfe5310153d6994dc1f8b9e74e8fbb43079e21956f428ed8aa48d6897e32", - "Name": "matter_g2_multiexp_32", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000052acff88605f33a0cf1201e8101c95ca0befd443c087265821a7d954917a026d41ab24d29bdfd972bb52ff4ad6de14c000000000000000000000000000000000e134b2aac3f6270e43afd994302426796b1e362031638fe0263c0ec212b828a30d8321af34ef7bf260652150cf2293b000000000000000000000000000000000d6628f675008099e9a75e1294803e86417ab22670d36316798680289ae61a26821693f2f9efc8468721a1097c3bceb20000000000000000000000000000000006d66ffad1a2e0f39488fd3f6e0214c9407528c8bfb8d1ebe6d75596a3e3cc844d00fdf46ce7ff6cd6d67732874a24a484adc8cfd2e42abc2f0e0d7e9c4b378f73731905760bfeeef01c94f8d5c3cacd000000000000000000000000000000001160bf0f7f2915cfc64e12a5a91b7e2aac78d4c2ce362e7677dd0e9c0172b37fd1b52222a13c65819b87593ee32a9ba6000000000000000000000000000000000c8be2cbbd302b31b1ab6dcbeb57b4ad428447bca9159fdfd007f5375218d121673a010f2c7fdf83fb45883458fb068e000000000000000000000000000000000363d3d492e6e6901756bac13b5c32d55aabbedde878115aa41b57d27b49a0f017a61fc90b13a20e009989374b82f5dd0000000000000000000000000000000009302fc26e6d750ff9441d7471903cc296b320128de71f86c4eacc80ce0725e8eea6acd2af056abde2f61e0a349f9bb5bbd5d4a15998d733326ce23cced86ec5d5b410c29ee98a4de19f2662c3933dd1000000000000000000000000000000000b12aca17efc103cad500b3d773e43cb24df6be651963c0f30bca489f1dd7911ffc7204fcaa4511e161c6f75da4a5ff600000000000000000000000000000000179a36e9292d3f78a5fecbec1175f001bd4ac0ff3610f596aacdba29a12ea4844885a7c465e66d3883c7fc99d4a7e06a0000000000000000000000000000000016bfd0758b31f54f90eb8562bb693c45a92a297a3d302279c9e3cb8263efc0f31579a3af8e8f5a091d9a6a36776f445d00000000000000000000000000000000020f6c66fa554a5cb610ab05d194e7583e6798a113b8fff336c986f7358bb9fa6a7aab0b04be9b5c44a6fcfdd21999e83717aadf16301a9c8741d65c86ad7f849101e30b7b1a344643b100a8582a6ad10000000000000000000000000000000004bf40c1d2d3574ad7fe128ee376364591b6f647f939b0b556ac3fdb5a92873f17c007e926b8a39a97c814728f355bfa000000000000000000000000000000000b8669e10e0a538a421b717287455620b82574b96ed09f64db444ec73a67a3227503e1b4fd6869314214071399eeae0b0000000000000000000000000000000006ddea4adb703d7205b6d2af436b41b4bde3a8c5dbed9dd161c9b3b466ebf06beced64fca25c3bbb97f232315daa5565000000000000000000000000000000000d97248a25ddf0ebd0200c6abbcac9ecd9775cfc5ec8da91634e77488bb592e5ff277a9607fe721990f403dd73f746e622788b3597da7b9b106203dd0ea97527aa8f5149754bbb0c10bb6eca8a46d94000000000000000000000000000000000135bc4f28663a6d7d995f6b876ffb8e6ef1d2d0f232388aa5f390c57e8c48cb84d370ebc4bc267eae4466a019c9ed56e0000000000000000000000000000000008b6a9d13dd9d7014df6acb59f80b335a751fa2ba4dce63467aed18f68358f5cb743718112b3cb2d0b5add34bb6989000000000000000000000000000000000013a5389dba4da195f34fbe798b254403f0bc5632ed98bd6017ef24fff33640ae493c1bb7a77a0d3c97649230e455eb51000000000000000000000000000000000a69803a4cc237ddfebc51df2d90fa1ad03359f9635ac1646bc942546575d1558f5f2c3010f6e2207849ee697be41d093c21276fc1371060c226424eb9886de6897b15b075fc5a51aab4710e9dddd384000000000000000000000000000000001939c2431f8ac4ab19d2735f122c0424af2ef18c0028e155611237e86648bf1d74fcba3008f5c6aa30feb5d4a14a3f3f00000000000000000000000000000000174473eedb54aafc522973244ec2feb3f7e95e50a1e996d1100c8da4fa59428c280f76e9e7364906662c4d2802235aa5000000000000000000000000000000001021d15f8ae2f62dfd3862944bf3be88d86d8113f4be22544ae5e925d450044279c5bfa1bfca44cd5934b42a27096b510000000000000000000000000000000015e0f20efae92e1fe8dea2222ce808a7de9e9e861c333db139f8ac11d7c4fa9ae6e49f51095f6e16bc738dc6d094b4cfccbce4e92cf377f67244995badc72db0b80fe37c9b7d443595156fa41abea17a0000000000000000000000000000000012d70691721f5787ea2e2a652f9c65edaf763637f95c285a62d32dded18579b7257493e01eda19631d00ecdd4e27a9ff0000000000000000000000000000000014da9ef6076e646e7d5b52d1803d3a6d897664851c6de2a9b330e48695737e05f0369224c3eb357bf557625bb94e6ea2000000000000000000000000000000001554f68124a91be5b9f325394db23ed5db8f6c46eb46cb50e57947bae00819b151afbf4ab4949290ad41625499f42dc00000000000000000000000000000000009fc0d459e28cd1239d227e1d2f7d530b9d14ce5638cd308569300a791c997a51dd5a98aad703239a23cfe7cef7f47f6ff79345f31c107841ae388f6cf116d10bc696aec4933de56bb9affe7e20c649f000000000000000000000000000000000452580d6a37a07038ce3564a12c1c7391fdb002cf27a6df7e194b38f3c12a3026f2a8acfe5e634cf89140da256d0a420000000000000000000000000000000004b73c9a4f9d41b8b84e53de538e4b15198f50247e75c274c14f136d7d91dce4a62c5346bf11a105f035e29ccac3dbb70000000000000000000000000000000008a8a3b2705a82b551f8913853f682253e7f1f68c8e42f349337f4f1eaa5103f59430af0c4a124b6a739bf88298c5f6f0000000000000000000000000000000012f4220609899e8610809bb3a4da46e0688c285ba2e8750b4bf44a849cf15fbf5c016e8e8f9372239bb562e7f38916e921cf773387d5351aeab99971eaa3b207fa6a318ad60f1c3e16b7f68251f9c910000000000000000000000000000000001884558e709635c046bd6ea8872bda936ba4d5ebcf7a0208cd0a4ee08b69f36dd2e136ce655ddfd89a5b1cf8e48f5ef7000000000000000000000000000000001357e2dd9fb603e5190d7b7ee105668bca2ed23ec6a248aa71aa430c2b2755747b8dfa3b147eb51ea644bf0354a61ba000000000000000000000000000000000009b0b0a76c6980e62e4893157b85f59345e1ac81e1aad1e48acec44c4803e2a9080f0d193fb799e0277ae6f1058839e0000000000000000000000000000000014c984ae4ef5d9d319fc89895f34a7db02747f57b206b0b30e8c9757d4b47419e6c0c8378fdec5aba364936a3b1922ca2d69cfed6bb2d33fedcbd215dd4e9632a3cf86a4b2716406305f6a85e6090a050000000000000000000000000000000003e1bbb872db172a1fa615155f81aa75ee9760f8602e4135ef9f1640b7f9d54bda911a220d211dc4bb767bc2b5e6e23e0000000000000000000000000000000008464f23cf693b1d4545b6ce4aecdc8fd182cfb288c5ddb1f78ca578e9b16342c8178d886cbb6b8086c0fd1318c4ae09000000000000000000000000000000000af574c4d0fd86087e23daf6d9ce98765e1e445ef9152dbd68152fa4833ada0be440de4abfe7c07dbd4ee67f1a4aec9a000000000000000000000000000000000a8227b982f9286b03c4d49766687622206213d88cde007360df9b4ca5916c44ce44dbe6443577998b4b0d527d22593379cabae288f8a9a8cd54523c20825b8fb07886bbf0ba0c5c807956f268af4fa10000000000000000000000000000000012e31070a501a7df7be43dc23e23dafa32ebfbc10ffb4c53f5d36bab2af69db5a05ad64b9ed116560e40b71f9217189b0000000000000000000000000000000011cbcd38ec3c6a6d49df6a8d6e1029a0412b42bd3fe8b42ed625adeb5a2f631e97bfad302de82ae34f715962b5ba0289000000000000000000000000000000001019b1b619fde9fb885d3c5f03a4373358107af7509754ce1ab2deb67df536d05e07ca7d60d927c15b549502750054f90000000000000000000000000000000018f1768b7140484105cf3ad2daa7c565e18eaba834db3f6bdfc9ee37445f2d6f7dc2b4c986b7efd5373224d2c92aa5a81973977d8e8c592f9063c5a14a658990f9c3405643089eb58324cd3f05b5b5e4000000000000000000000000000000001847b14146cfa2e1700f368f414b6a66ccaa02ca2a90b40a8e2be2ee4eb66af77ba563d7507de63362fb18426b6149610000000000000000000000000000000005c028d2b344ccb6400b53134bd179028b8774000ace89369bc655bb9dcd1643aaeec830407ee941df5432ba27987e8f000000000000000000000000000000000c4a680e2157dbdb53ae761209d505b4cf6b18fef5aff1c5009ab41295e0ce2ca23bd7a4f983fb9d085e1d0dbc75ffe40000000000000000000000000000000013c0cc77a5d771f1df99d1530e65ba782604c1ecf67d08572609de9f18405b9b817c2643226cdc7c9ad35beebf87dab0a610bfd375a7b8d0b034c17c8fa27d4366b06c681131fa7daaeeeb08e25c2ca60000000000000000000000000000000009f32f2f83c21875963818872d243cc8c70b75234f53490eccffbf060cb3b9c53545c1c32025b271514f500b20b00ec10000000000000000000000000000000002491b571087a9e89dbdd039ccd2c37d5d8d25587495b2d7b0066e9dcca02d44b2c134b0128a9a1527396729f069df83000000000000000000000000000000000264e9c47f72b639597de8f26a42ca7d77324f8c0db705986fc3b40dfb46f47764b69c70037a68d76a5de49a278779a100000000000000000000000000000000090614b3bb302ed9fb78b8756524fb78d54a4390b27136087181342571f994b1a93faee28256d765a8ff4f448cc357c199ffe1dc2d7526338462860501d75380a5ed9d53e675125342afb6652a97437b0000000000000000000000000000000012c716ddf17fca0d974e8d6003d99aa90f06b201fd141c74d8fdf1167030d14dc732917d3c6f736c68fbde9df50c098a0000000000000000000000000000000000261ef2b47de8e1576aecc6e19ececf80ddc1f4e28b2ff27953a65199f65a6211db7326632cfe04d543895c727ef8b600000000000000000000000000000000044fd6b9b4a1bacb8b7d4c53c106b025ae78f17c3baebbccca4e18cfbdbcbf8b3ef88ed5bd9bb36d9aea9e24f4117e760000000000000000000000000000000007721612515fd075811ee804314acec9d389900c7ef883e866f71fba00c49d5c4dcc7a2b8e2366f5a93f4577926ed171fdd97465982b58e69993711a6a64134bc4e76b88ba1948af91ba3339e9b9d3e900000000000000000000000000000000122581659ab1712afc23c23c2986394de8e155bcf722e944ec05e7e42e05acc366d9a7abf2136b5dc68a8dcfd4a640bf000000000000000000000000000000000188842cf4ef54cf77c145acb685d3187cd9c842ba6705bfed846ace83dc4400c45120fc1d6a633ea879840d3d0c902f0000000000000000000000000000000005c8966862ed4458a753155ffe2c64655779860149641ee5511a46ec576798fdb5cd9521528df77bfebcdaae2f94b865000000000000000000000000000000000cc10d888d2b7a97666de99ac14a501b7e2171f074d30d947efd67d85226c312a7977cf923ddbc88c533f08a99f2045f786a2a3974c84752b32f29707805c71992d5d473f4b7bc1f0757d126607a1c07000000000000000000000000000000000e5af1420546c1a5a0e0c2bd9241bb7c7a26dd52f4f358fc868bea457a60bd4f6bc5b60b27069fb4f6760813a91ada740000000000000000000000000000000017426a65d239b1d9505bef2b476799c394fcc7bfdca36a1ee5a600351334dadc238b64cf8a667a25d4880a31b73c53a9000000000000000000000000000000000f151587944aad17429b51b1c16193c1e1c93cb412538d1475473666c997e012ce618eb841c4e9e064a08ab83d7fa60e0000000000000000000000000000000015c2e049c532db585807319c23ec077a51f288fcffb2cb6528d3697221e8542e3fc85d18b079ea1b217fae30858a36f285d33a7fbe6ac6eb42eb932dfbbca2f771ffad5e80fde686e5df9d34e9f83ad6", - "Expected": "000000000000000000000000000000000c9be91da9bd8774f18efa3ae9248e4b03d11c49b377c372613b7e745882b2b23c49d518672e58eabd4d9b510a25d8fa0000000000000000000000000000000019687b9eaf5d68b0e795cd57055a74e44efb3e997cb038b7f1cbf08ca70e80a1655cdb04402c542a92ae4e435c22d0b90000000000000000000000000000000010aa1514402ce348d1d61b8d38b53017cd3977a84dc14445db64799cfe822b56a0adbfc5332093ce7ea1f0f438bf15590000000000000000000000000000000019ade30ba0faffcaede95aa272be042aef090f89d9ca25cb825846c4bf9e4c1dc575f8968c88ada51fac71f26fb01517", - "Name": "matter_g2_multiexp_33", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a1346771f8ba25fc44323d5290068e46b3f756de6d97aa934d511979a1486bc32173575639a7e54aea8eeb60f32a8c3000000000000000000000000000000001958ae7fce87db47a65a03402313b99f659ae02e8b62db3525d48dc9075aacc5e5abb50156e704701f3ceb18747e0431000000000000000000000000000000000f98778311e28b4081aa76a3f9546b94c29d86fe8e66b905265d74ee21928dc3ac463049f70d355d8caee5b59d65e07300000000000000000000000000000000185cc233ce72770ae26406476c1779858523e7c940d69adf2750695cb12440440686b6b918f4adb3b14aee9aceb6422119582dfd9cb80d44c17c5f62360e62f6736d186194f0f8483e34d8d18d832d37000000000000000000000000000000000ae2f565a44c8e07f2a136368798a44926cffd3c3a6d4c2fbf91763c20d2bd959271343b80eccec4d59a84394c7a3ce70000000000000000000000000000000009481a5fb276c938801133adf10dde3e7da2087d0bcecd3c9435b7de544271eb3b07a69efe7e168869e727868f24b0d90000000000000000000000000000000011774e0197866b1c8b3428d353d2c9f6326a77ab30d5595e2402a0486f03ca6ebb1e8dd335a60a772dfdd9a3dbdd3eeb0000000000000000000000000000000011ed2480d79f73a67a2adaa6da3ae4f1e1c28feaf0e4cb9aafac658901960129e40f6415ec80a31d72004899326f714bac0bd9b8746fd02aa70d8b8a2b5d3be46baecf9449d8cd3d620cf9efb3c615d1000000000000000000000000000000000a73b0d8c31af2deed481faec54095875639233bb09f31b1c7c745cb54778d1c8bd0a230e963ddd2ec8d178d31fc14740000000000000000000000000000000015a889b16be93d0b6dced01f5e2278ffde1cef0576d0b04b49996cc5252854f879e04b1ffeb90e222f4b9d5fa350767c000000000000000000000000000000000b53dc4d72e90330ffad17012bc7dd2e497cf8aa6ec73bf25c10427e23fd28137631249eabe9d0308c956dc7a9e92047000000000000000000000000000000000930cdc5d04ed2d1eb62937d9f72fdd733c07a5a0e392fd5216100216b1a2e3cde7053bf766f046cc470d92bebaf6290069d889881d5bb87dd65a9a02a7fe239bdb55ee54a6310bc987e7c5772404d7d00000000000000000000000000000000131c4e590400b69b3657f7c67272b1e3491983997993ee87c94043001d78e605965abf3c1a8c8c39cc08d5a5ef05520000000000000000000000000000000000124f71c136dbb032504da910958e8a7949f1dc5c061f21d50e439e01e67919891633b3bb84fa8a54c69b632f78560ca70000000000000000000000000000000014a4b1a05f1060853f4294e669a20b91f939793a6eada6dbc84fda8ab11509b256d8b785b252a3795f1d2b99a51df05d000000000000000000000000000000000be2489f1f91d7adff356236859679c46b6bf8c1b375e8bc8bd1e97830b5ac223ffbbda60ecda168bacc2c0b90ed25d3be658348e299bbf2438a0c013f86eeeb69a013b8004a4996189472f3372b326c00000000000000000000000000000000111ebb796e8770d5a69e724a8d3ca62ef1f13778baf4ba12bf462211d35e325ff8e455c85237a73a3046e531f2e2255e0000000000000000000000000000000004308b76b06067e0a07bda143341220809b481b40b78edb2e24e83aa0f003d209198825b5fa9bfd92597e27a4054d3ee000000000000000000000000000000000de74485713f5c95653e98b96aeefb79b59911a610c2a848a807653c19d50394fdb52178947c779134d24b6d396ca36800000000000000000000000000000000069f47a71ad765591f6335b962e7c2d87b556801e1e6c25b449edc83432612fefd405c952397a704e9aa5a924769ad4e9b9d0ec92ae7df3f52a95747659f8fa3ca2cd01e8d7ef6de384111246886bafb000000000000000000000000000000000a3f89408ee43c0ba6a7c9c479327ebab426d430e3ff212c65da6364b16195619d27eee83d701a2ec50bd4b7acfaa06300000000000000000000000000000000092715831af983f740ca2c673e7c9c47727d64165c59fce19dc3fbbdd0b6a7be66288ea1f033ebb5ae2b38b3762edaee00000000000000000000000000000000071ca6fa9e546d4bce965b2bd0f0fb97e6833f05cedcf66d43ec88aba411dc4d6db9f1591de22f493f49a1dab1a2701e0000000000000000000000000000000018f89932ec032fc28775d34d588169a1435bf4ad7e2ee11c9d6934dae31324ddb96b3ef88f95d1bb2e52c3c8d9c01516d2ffdf1237b4e03c219806f2dea745c94bf08924e1b9f11deeedf0db19da6f3f0000000000000000000000000000000011b5cc382164fc21c9a72cd85acf61c2a78d00a16a2dff938f0b36bfb3bb7075845a1616001ab53271a9a257a38312cc00000000000000000000000000000000139ba2f27e545d45027a0b11253532e28fa691170e08608472ce3b3f9a3e9398c5ee76953b1a1d01a5e79f194c32d1f5000000000000000000000000000000000d875f44829555cec695f3f4a28078b0a6f168bb0985793d003443b75a141936f3c7c633518890e0f7238416d46573cf000000000000000000000000000000000675420ed817ecd24bc5172d3e7df60ac4281b24ba91e8b5ca8bd6a8321f5c7312a6ba043fbcdc467c8a5c957590a692cca0751c9534cee7f14d11b7c8ccbb2c537a799df59f850bb125c6362d72e9c400000000000000000000000000000000107bde844286cd3958cc7a1314127322251699b51d8af8e6b57495497f21a84e05612b1569b54fc5639a75e9f9deef750000000000000000000000000000000002355b1a60e24e4879448437d2c1b12e58f02d7eba88583e96e9634f7e2c8c6886132ef0488918f665ae3f7b6977c7c4000000000000000000000000000000000fed531e437b70bc4a19ad63c61ccaab49afc50fad1f156b1c8ecba0e1b703f8aea61882c6327d4d8fdd072df9c4e73500000000000000000000000000000000182177409579ad53786539514753c696c8757b8c4d9b8360392f24b591e43ec20e84c0abe468061a9e5e879c5c81314217f890a1120daca4a1bc1bc0fa7529f0a87b5fd6ec385f12b270bc0f1a5281b40000000000000000000000000000000001fb25395089228772d6000025cb0356eb510c964bf7d0c12d47a6608fc18cc448e44880eb5ba8475cbe6418fc9d8fee000000000000000000000000000000000f3b9de9980e5afaebc59c56e02fd75fdad13013842ac035f8d5569a46cc67f0cee461a939aa5a3d8fec2966294207930000000000000000000000000000000009a223ac0edb164845eb8397e0cae4363fb2c8c996c3c5d722cb50be56cc3789c732763cfd4b61470886dc991be39f57000000000000000000000000000000001909f17b229eb351dfe8317a8273d846edf14ad5ee0ebe8cc2b595ebfed19b73983035e19ebaee3d05b1dea35968586961ca18257d9d989ec13d4f158b18ec17d59344f4558b6dae6c0aa0c2f37affb500000000000000000000000000000000081fa9eb8ca7d9db52380e4c408e6d5d668471bafbafd62ba9023fa08f6d300a45295b583677824c29ddc3254439cadc000000000000000000000000000000000e2e613043b1566674f791dca9d860a49a75dfa24dce3fe18f544a9b24ec5266a64e77386b672c93fc4d079eb8e76a01000000000000000000000000000000000f471b86ac5783d720e7d73e8871474c8665e8a109aba27c1172ca24217eefb0f66c53232df1672dc0af6ddf9640e10d0000000000000000000000000000000010667cb22a6a818fa7c729e40a7e70e1f31b0ecd568b54a4d352d5c9df8cf1072ebf2ef1e612efd96bddcbeedd8566430fc004ed8a135ad97cdd1bc4d0c3ccd15e65031ad7e3cc13ef2c260958bc43be000000000000000000000000000000000a0ed87b01f27f26380c6285e82bf2f12ef3016c7e7f3a13041d465825664573db47be6cf099cea615e21f6a5d759b6a0000000000000000000000000000000007afb2a1bd50fa0fd3174d70f1c8d5c229627a496bc9bb89d4f52d47b1862e14d704dddd80045e58d00336e898a996eb000000000000000000000000000000001698f30f824ee5cb71b3f2451953c371987433d2eda570f2a13262ff9e5e529e316b06ef6aadffc152803b076f22db9f0000000000000000000000000000000009eb1d5f3da7cfe9b40a70e1b3c3dae36436e8d068a79dcaa283905614676645c99a5a165630ad46b70bd6be8b1f21a8d8cfaa1037e2c81c6973b221dc7badf25ebe3fb4b42bbdef1124265df2c7ccc40000000000000000000000000000000005c4390b8f37cc3fb9f248470b505a5d9502d44e4a4459d1f56452cd9aec89d114f1402fa45935930fa00888a4860a9900000000000000000000000000000000163b0ca84b5cca4f124bfb5a13a4a3efa677a84dc89b6a61e69d0aad34fade528614e549a7b2326d1f6016bd0d35465a000000000000000000000000000000000bf450dc8af483a9f993a29cb47d5362c9f5ef38afc2fba8040e14514eb834fec6520a413fce5868aa9a2c7c3ff6617a000000000000000000000000000000001063619f384102949fa1f8353f0aaa5031234d736c54103df6ef6fcd0df02a19c3aef471f0413a1e19febed6395459a0c25ecc5d37659ebb0c9e21ea2f8fddc518e3d8faa99627b21faf105445f69d7d000000000000000000000000000000000e35db3017963d3a9d62b7e7fbfa13ce4f5fb46a90c1285ddc0fa481d9379b95a77e8cdd4aab5c33059bfcdcd82473fb0000000000000000000000000000000004fa27c663c8d21f041d15cb199d31cfcb96a56cd673b730dd111bf03cd954cc33799456674ed4d58e8e0dfa826a6b26000000000000000000000000000000000e0df4e7f943db5b5c27bafc7e1ce099b2caa64642bcd6336ef926352682fbe81a1945b266cba7eab52b16f4aa63eb8500000000000000000000000000000000020167756b8c68f535c4691b1249ca1ccf0a539f7274623ada824d0ba789ef44ebb20ec1ba51d46c0a42da78653d287e26cbb32382902d9b1963779070d749cbc4df1e7605f840819f2c04aaf89c732f00000000000000000000000000000000178037c6b5fd1c6c396d8aaadb712863557feb744d2cb9165ae5c36376d2c066f7b1648e083f81c2c96da6562e0b3c20000000000000000000000000000000000b805b4e1cd5d45d8b6ed9d4f604ac0b40f336b8123f7281df43a6e803f8688bd8087fc4d5fbae695d06efb0fa35e18400000000000000000000000000000000000a947562dde45f613ee1d15614940a2edfc770d733a60374f8e9188675d4cf973a5c1081c11fe5a1d93bbe85e6f47800000000000000000000000000000000059473d80c82c6ca06b4aa71d072f4751b3b053b53ffcfb4a84906ddfc36ec5918668a62f07054af1b241bdd4485edba699aa549077a80ff8732b5fc9df148a90f405bccc14bf7305266836566b7a98b0000000000000000000000000000000008b9d0916a9f5689b8fdac84bec3a49d0224dbadca6329ecc156da633e1332bcc6735ca3ecb228c22032dcb7b2f372d3000000000000000000000000000000000cac0c264add10bdc1217384a7379f65b93cf822418f7e4e2b48eeac45f068a61f805cedfb1665dda06e04cb726d245c000000000000000000000000000000001578e98a40a64da59154b1c3d757d8f1f8cdc500482c7b7d65b9997576f745442fbac654c19331977bd210df440372970000000000000000000000000000000015ef69f82e85c81d28893d94927068f14c6516eb7d09898d5d055cbb7a9b55c6d7f686f067ab164160e6d6a8f91ea19d40e2de1a2901f1380a383a741d79fbb0a041da5d7bfb92edab74cd483edf95230000000000000000000000000000000000a6a27b498285085139b8dd0c37b700997134337e696c84b5e0cf70ea3991cfb40ca3a3098a3b3a2fa31e91aac78eb2000000000000000000000000000000000bbd7ebf4301c5eabd4f448b89f1b227415cede3247a1c8dc56a02247efaa99dc78cf370f644ffc06cd2158fa25197dc0000000000000000000000000000000004535a402540474d53c084d4fb6d9e12dba6716ee13286ed758aedc1ef911b55c572640180a54cbc084ff57ceae8a4b4000000000000000000000000000000000759de2a9e0f3c04b4f629a682dbcadb2140e5b935845cb55bd267e230e08c6e8cc5426057473aa03ea2196203bbf6dc062b323592118868d547e83b731d15ba2c7bdb1ee4fdf73600c2584f1db0b45d", - "Expected": "00000000000000000000000000000000134c29cc5c33c10f04b6c09b5db71b10304028d06ad6acd4f4b39b16823288085a84a0380a1549f04b3dc692cb8216d3000000000000000000000000000000000a0a9379d63527ab9b5f9c00be4acd54e5fd683a0a2f37c85ba570171c705eaadfb0f4e4be1a8836c9de86dff46138300000000000000000000000000000000006ce78f135dda5af34a0e069d7ef13fd589cec5a6128512bdae7f45f28b09c6e4b3cf638628c9f4783097cc00082aeea00000000000000000000000000000000141e710ce7a979dd1772150d0cb2d5b269d5cda50d1bf7bd0cd827b24f9cd8c1e2775f495cfec0428519627b7fede464", - "Name": "matter_g2_multiexp_34", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018aba8353cc470b287a163fdb9b8b4cc46071543ee8261f928a7b856287946637d9b36b728a54e1df5f185a47f1556060000000000000000000000000000000001129541b2e3b2e1a553995b603dc3eee44a5ea440e687739ee9e1339dd79bd96c67231ac753d483e0ca96b27054997b000000000000000000000000000000000e1cdf3591aadeb56dbd80890ff7d5639a64847cec771a19c769df7da732a6d3179d3a89ce0052bd7c982af0304408120000000000000000000000000000000000f5f5f0ebfd2b632e15381ccbabfa88eb774f2c61801381ca73e6970965ecd54f5f3a9af7c152186af8fb75ffb5bc25764ab6f4c43630d5e79e8c474d76d8973a7b7bd1c7f1a985333cf1a6be5ccff2000000000000000000000000000000000e527e40c311edc5dcdbb4d0b70497eaee14533aa8ec57dc7cbd7d839fe6c6ae62b1fd0be2346a038de687d5cf5394d60000000000000000000000000000000005f9fc63027dbee5e0d55cd6c57daf5df7af0d138393a2dcdc71ef9aeeb204ea347f7d574e71f2ffdd37d8f05dc7979f000000000000000000000000000000000f8788034c9f1c9c2018a52326c046cdba8997199732152963819b663c6e58e9d6a0065289e2e25a97ce5627505900f20000000000000000000000000000000002a747bb3bcccdc6ea0af1bf1d0ce55de3f41b93060361b30c76063346b606322a76ed7eb260219c83aea0806ac7d8583280f1b1e78d2339f64b5b2f2bd77aa24623b79fe2c9debab4212f4ff564983b0000000000000000000000000000000002148c043e065132e978e89f018a5b728d278c95c9cd1a6f276bd13f0cb708422a62fa22f7b377adf33055fcb09a6a8100000000000000000000000000000000024c4c721a0574e53118bdcc3fd41f73176bc8264d2ff39673210525166bb3513016b5c9af67a47a7032b74a62effcef000000000000000000000000000000000797dfa8cad94896916b7d55fbbb3eb0eeb74f70231205388d0dda69dd8abb436c22addd22c1e3689093739af957b65200000000000000000000000000000000010dd2ea2d45528de8bf1b5c5dc3267fe8951e48ff5987e67ec52d58635521cf1905f1688894e3e23a659764880b2301d4d27ff9d03ab9120ac2adfeb36b070015f0e90782255ddc9111704c5fb11177000000000000000000000000000000000eecc0a4edd3cc3f70d3e0e43ba56b04cfb3f1ac23c657048a94318e622217572b0f929c73f545d6f5f5613920c0580200000000000000000000000000000000137a098ea8d3aed32c197a2d244a2e18753045b55cfe16874f79c728c664b7f23b10476f20dfffb2f80417c26dff4f860000000000000000000000000000000004a7789b02d7d95a2ce0c7bac39d5b057509200393450a47fd9d087a353f866921aa11185550537b98f3073650d9a1370000000000000000000000000000000006ed63730bae06403baf705da0e30c6c00739799eea4a312d06b8d7dc35cb43a4f1e941a69e55ddd7ab8ce42d8629fdcc66d5291311c7cdd1f33e5365ec0689608b3569427a8f6a9cd0b94b671472e66000000000000000000000000000000000ee7ddbf43f17f722dae84d34d26add8c1d732918b8c75c6b295f2f584075cea0c655911410b32c06868c1acf36aeaaf0000000000000000000000000000000018775682555d9f5a576cf9462170910bcdd083671ae2e4c8c6fa99a702548f1ce9afe90e681b00d194322b1a2a3be7ef000000000000000000000000000000000f3935bbbf58b91fe8176f3e25ad3fdeffdd6b369ae70b704d4e54d4fe32fe5987e73aa5aa975e958497340274577cf3000000000000000000000000000000000c088bc439d638d86aba6bb1e6e9f7540ac2da3b96080aed455edd1fbabfc141e26f125cc3a9cf72070a24f298dcc3ef4b718a5129659250640e333f4567043ca749063e63d87efd86a9995adfd3b8450000000000000000000000000000000018d8a47d1a13b9b8fb5a1625f9616ba120d5c677bcc996f694b7e15d251fc4bc938b0a7cb5b70f22b8e9f5b416c513210000000000000000000000000000000003d0646458bbee7ccab27f858b8ab0af0cf583da12a40ca5a954d7eaf97c897d379129a63d8131036f29c30c6e644149000000000000000000000000000000000d5466b50975c5a2dad96e4e24339eafc8c85c2497a6f19e12d96603596498654cabea6995a92c91b8319ce06f18d56d00000000000000000000000000000000191a96d62139f8219b9e4369a783400d045d72ab2dd83fd229e08a4ca73de59a11a5add86c739cb3bab4adc5e9f79685708891f45d7bee38fe382820260061e212c6cb9a8572b4d1854f3ab09409b05a00000000000000000000000000000000032eb1f7846b563e98fca0cd44ede4909b6e16a893f5ef01eaccbd7d8aa11710606bbbd0ee6480f7cdbdc9ffe66c3a9c000000000000000000000000000000000c31bb6fb537cfcbffe815d86ebfae1f5053ceb756818ede8a58cd84cb34d0eacc70ab9095f9db1691e4fb4bb816d570000000000000000000000000000000000a8fa1dc2f28277a4bf8fd9665d4b5c3baf1352d89890d4af94a3657cdac7fd72558da1e65cbc5bfac142f0e817be74f0000000000000000000000000000000005ff65c22ff0abfb33518791823c5f2202ea5f7258c0a507ab84460335ffc2cc8d7c7f670752a7647d6a6487ca0c9adb85ac0f94f300b004c7f20aafcfd9129d6c2590749504a3f08c4cc708fa30100300000000000000000000000000000000190379b7629f74bfb88096dc9ffcdecebae0d653410f032a35a811a09022679c9be19f3790af95c3205a396819e068e1000000000000000000000000000000000b6f114fc277ae8f0b5374dd349985bf955dff7fcb0095e0e1e137fb539814be78c924074bbab54f29dfb42f3e7df24a0000000000000000000000000000000002d86b0507c147142d03d3461bfea4c3af7e57a6edbb372387de24a27cfe27c44ee4b9571325a1b3f5e83eef450f2fc6000000000000000000000000000000000ac3b226d5e13c36c3a8ef0c8896d9af55bcc0cb67ac1cee57a5c6519617ec77af9af60ed44e0a8284a2d59816ebf848fdbb634bc0f99c5795f3c4d6a0efcda7f71427f1eaa1c5411caa6cb05ee3147800000000000000000000000000000000079cd4511e953e4d1b3f4f3bbbc66a62772018e809779fa39aaeeffac737cda9a6116293848f967577f03017f33231d2000000000000000000000000000000000ce3cf48be423a2fc0188b94f2a22579872e9ba140798e560ad107f63ab2b8c601831f89d06a4bb8e7a758cf836ddfb3000000000000000000000000000000000a6a90f735f215a79216fc4e7daffbf74775f38824952af72ac38c38a77a277483e34bc95031679494d76f109c0aecc4000000000000000000000000000000000d55fbce780d885cf817cd2126e7acf115ae9c72843af23c376f3a5d4307d1eefaa0f4691e7c09b5da1707aeaa5b675af5e4695c01849259fb969183de385ef30c2403e081067c2d9b6b5522c73fcf200000000000000000000000000000000008924efbdb46b9324bfb79b922ba8b7d83f5e5e4b3b736105e5339805838171801bcf17208f3dfe5c7475d4e45b6ad970000000000000000000000000000000007bc0096fd23f0c93f0dde8a3974ea3105574e031202f6316d5940c85164c6d6bb5b86078a0c68dc822c0fd1b3dc8cc10000000000000000000000000000000017276b3208b347388a5657b10e3c8e4a187b376e42352f76ee3ee88873217b6b8185022c93097cc116abdecf3cc64467000000000000000000000000000000001915ff932acbdeb52f07b664bcc47c3a5b096c6cec32da4d7044326dfe84358e49539fe50782538a901b99428446b0f50ea6fd588db5efc5fb2248634cca683d39d610886b59eb3077fa9612c368d7690000000000000000000000000000000009e295d229b543a17db1cc85c846111b7097bd169d19b410de78f8da9684e664922eae77c64b0db430aeb422016cfe7d000000000000000000000000000000000e29aab30a1da56b8590e9df67171cc1b9c847696b51147cc57ed6c3b55819cfa0992c67e15e4ca6de2573c9e16231c10000000000000000000000000000000007cc9990c6722645e320dd16a4be8adaab41f958f769ba0d22e235549a7457778cb9b14aa6ea5caa9e0bd43f8d04cacc000000000000000000000000000000000b2dab5cf37ae8e76b71dd8748c86e8823142792445fa0b140de31957d35bb7267e3d94e0dc92f4342d9f8560c5d9d86dc2060a3421c5a8336c80983c9a160345901a496c3a74fc5248fca081d09953900000000000000000000000000000000128e2aa795f8479da3ea2a4efd12aa90a6fb019d4da89fd372e6848ff7ee17da689d766c9e49c88c962eb4f682c56fff0000000000000000000000000000000000fd68bb80d6b2200297aacae1174275f864669e962d85c9105032d7a352fea548e9fa0629a6749c789fa0827a40190700000000000000000000000000000000175bc3918dcc972fb728f1d8cc30ce9887efc6e0b254d8d22af87f95cd4182129d494c43d11b028c4b9849f5520a4fc00000000000000000000000000000000007c5363f507a01c0b6935fee0413345bceaf1336cdd20f69060bdba2e411521a61a549e6159b2e006ffa16e3bd77e998e27e4afc3e6d59d0f5871b35eb83b46cf15da6c326e88dd8edf84031f58e23f90000000000000000000000000000000000efcd782b89fee74ebc037160c6653ccc104260b5f8989545b40d51ead6ad6ce6252e1232281c813e3c883af86e68ca000000000000000000000000000000000b68ed21f76ce131c089dc454dc48ef948cc7c6d5fd87d647db954c9eeab2f7f76ccc51a1cff8612e89bceed16ca03ba000000000000000000000000000000000cd776670d5171610046fa294fecefb42f9bb4d71baed4af65a09018b09ad9341789abc23c9feb85adf96b4203b0c0a0000000000000000000000000000000000ec4ca0091a28b73c9adbe7120f2bf1a84a62ebba1e86b1948389b1a1966c1de4c632a5e245ba634b53cb932f5847f6ecc7efff04f143e2d038de153861da5e04016a7eb17fbe6365de13069d088b1a100000000000000000000000000000000022f319bb5167c2b945a69a438f712df8975a0e262438ea687e2b0d824e2d1d14bff1065f50fd6ae92494f6f3aa9472b00000000000000000000000000000000198ce9e4ddb6b423788dbea82d75513f43cb43ecf1b27c8788f041248f01808644f60fd823e5862cd7afb4f7e8b6b6a100000000000000000000000000000000119dc1be1bbb7e678319db73055ccb88ef7efcf6119f8a9c43c69247ff264879a627f653a10a950e0dbe69155ebca4f1000000000000000000000000000000000692a0ef5a75d42524e3fd52ae073b0f2ddf6378f18a5dcef05af4868a899b93c7f1d2691883e5c85f97052ef1f4177d09a2c3dbb4ee4f485dc60dfbd94a358a7c62204c021f2d7b140187ee9ffdc4ce00000000000000000000000000000000102c92272571b73a7df754728d7293fd8050d9dd2b8605c3f7722e6de541b7fc6a81b01c1cf15e5241ee4ee1f81ab39d000000000000000000000000000000000af1cd6f23bbd3e9ef75eed6d6d99a7cdd24574881b3609e45c4adbf82e08259d14701fcc5b6338ecf52166aecca003700000000000000000000000000000000026a1a4c3eb54de2ba4509dc806db9efc7e26247d501cb59c525b8dd15d03b91abafa9ba5816c22e1f8ca159cda34bd500000000000000000000000000000000170b510ec227fe8534a2cbb0f405756491c4f6832df552bd23980ab0946725371b3c24fa8b93a38bdcd47e1026e1d2a0d9b15c065497392e4b477a556ad620d44e671137cfd570d53590b7528f8ff680000000000000000000000000000000001423d1707e49d2215f639df75ee0e13bc724efc7d099259179260ba0f17157c4efc4276844bfdc46c61ac2185f64beca0000000000000000000000000000000019ad06d215d3c819311938f89609ea7cc63fadaa11bcc86cf5f26370a966eaed1aca312c18176674b5aaca3ed8ca876e0000000000000000000000000000000013bf3f13e87f3ce29f0524094e2ab8e39679566add32e779256006dc92ce09f60d5bb9cf0452b90ece71a5f6981d77f300000000000000000000000000000000112e4901efca14686c30a883ecdafdc389303f4cf46345e229885c76d900b0aa084a957076009ce22ee36d4e285d410c9e2a72eff2ec29a65b417767e7090b73c2fb530de6c8f4e4ba30543946423b12", - "Expected": "0000000000000000000000000000000016d1fce53fc4cf40acb0347c0983dda46383e4828c16985459ac89a2ce8d3c2a26cd9acfaa2ec899cc63b4c6bc351f560000000000000000000000000000000019c9626363b511a79f297dc79c5a3b7a2e5127fe49a2fac5bc43a4376f170404f044f9f84b82cd09a306012fc81e3bdb00000000000000000000000000000000062e324f3d7c5bd39808b762a5b009cb30bec14a9591477959339bf2de9ef27eb42a0eddb95aa5fdca9bb9d89b278cc20000000000000000000000000000000000f05225a4d3bf910b0ac0103594a90684ffc0c09e2c21744032e30470d5727be3c27621dc2377e9845ad78be67b856a", - "Name": "matter_g2_multiexp_35", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c64577b78ff306186dc44131cf8bd946a68e65502c4af9613154a7e3ffea4fe4e59cac4a500894b470a74e66db1834e000000000000000000000000000000000b4311c295bd30174f17b9ab3544f1496b9655302a4b6026a113b1aca31b555ce7b2d812bf8fafb6b075f67cdc59b77f0000000000000000000000000000000012d7dc3db10ae6b4e3e99c655aadb71124a0bdcfa6e30ec13c7c977d39f83aba4979a1f45881813a3a68e149a40120a90000000000000000000000000000000001b958c47cfecd619c05a2c54315585d15fe377beff889602ecba6ea3b29d51f6480f09a0a8490e4c754045f0bfdc3eb7b9aa7e0bfaf135ff24720773ccd1e0a46fab6d678d91a14de137061e145fb9d00000000000000000000000000000000010db66653f2ca73e55d85254f62e8b558584d546913e4b8f530968088d90cd5c4bc164fdb77325fe0bb2fb1a5683896000000000000000000000000000000000a1af9bf84f0b351c8e8c082a79c7ccae768bd2ed40eede38666aab1901a6eab0cff258f440c8c8eb4854a824b9aab4b000000000000000000000000000000000444fa654afb57f1b01d10be08a330f23667af58e3a40c630a2e01c1809125b3ff8f76e8a39418688a023293ff1a45e90000000000000000000000000000000002ebb117ea107a3598b888dcbd5918dd0ca307b21d65843c6c28b3efab89d0e276e5d92283bbb345b674d4a300595425c6733c9bb7bd195622b96c4181e8c8837d1912fbadf77d6029f7fc44d793b48000000000000000000000000000000000105818a11efaeab4801d4fa7558b09bd56294be7f58e3e54fab1f4f7c243ceaf08c99a14c3128ccfd866b6f93caf989800000000000000000000000000000000091ca092e5f83a04e872e621e71d54dd6886d088718f60ed5b62d3e4c165d3ff2cea1e50fcb94fff251df0f5ee453cfc000000000000000000000000000000000b42051a1ef52f87536b9bca459fa7070ca17bf825950b13b3bbe9db183ef722f62af6c05c174c65d59b722e1d2f5b0e0000000000000000000000000000000002fdb4a5480418e43aea28e5041af6ad55a6c226e1eea1a0449a99b5a937375285feecabea95c2652da5113dc17d8ef4410bb66334c677397d04f59eade9630463065cd7da3c9d50580c7d66bbaf487d000000000000000000000000000000000d8f93b589678d4e93bdf8da7834bc8edab648ead731b7f5f0cc299488f07262877ee9bb1174ccc106204dcd3f1f416800000000000000000000000000000000160f740ffca48d3a10c43e591cf46c129507f10e65d76a031fded2930d6c2dca4c79d7813f63e4ff71aee09d672173680000000000000000000000000000000013c768a4889315faa3976c8e43b4d466ea594bd94773f270a198f2571ba9662d10435d1e541a492055c333eece9bb29a0000000000000000000000000000000003dcbcc9e6a0cd5741d77da88fbbc269202e8f944a5df5dc4f9145758654934d5e1eedd596325080382458961ed3d21ed97a16fc5b2c70829b15f73615286eba334de1f520b5f0f6a83d2578399cc0b3000000000000000000000000000000001344fb37c1d7dcab01a4bf6fa50c6bb7606f7db22b85a3888ffcc2e9f229f196881cd7c82160730727e49b9e6fea04320000000000000000000000000000000010c7b15a6355d3152eaada7a606031f28809f278a1d0e04d264b563185ac7d9e351295191a6a90ffc9c6dd33995265db0000000000000000000000000000000014438086226a061a1bd557dac24d9333e14cdfa3a7bb00ded4a450e8889a3028b174bf38ae1347e6aad19ebc1cf5ff7800000000000000000000000000000000105165703c4592cc4f1f489d78426a56434dc77327c13221b582dc25306f4c5bfe596f3e47abcb741ab553fa14cad374bdbac08202bbe5df1229e99c76c1727f7789e0f8c2002f0a2c195bdfc00acb36000000000000000000000000000000000ad8b55a198a5e788bb54c32112761ccba9863cba16d95ec9e30181376e7eccaa2741660f2c5f708300be058e566ae27000000000000000000000000000000000b9bbca7db413964d2ec113cdee2d7a7bcdb712d285655f6b2897dcac61456ba4d08e25e8c28627231824829bd7d13800000000000000000000000000000000001ae49c10675256651e3e038a2150d85993fa6f2a97b9bc02c693ed97ad52af34015176258b3b2546b81010a4381d85c000000000000000000000000000000000c8f9668a0a497420acff5207a07cf780e0b2ba78083eb0ed8eef76beea996210541bae2e64d825000f307d54cbe3b2b43da827b812ec6ac23b00208cbad0f2e8b3a32434aa61dde029683c34c1ab1900000000000000000000000000000000012990a66c132a31d60d182f729b52d9b57d9d1eb1988b6f0b4d9fa2847f26983078ef9bbfd0e888e14bf7d1f92d09e54000000000000000000000000000000000585215ffc2673a197bf9cc6c6424547886abc6ef5c6edfeab2ef0c42034a4a458fc7155c35c84a8e9e9d89fbd4aa25c00000000000000000000000000000000118fb4fe0d3498dd2b55e62272e95a1203f9fd22314921d3e044f1b162376aaa7e8154a4e2184b66451aba98729330c0000000000000000000000000000000000364b9032ab9cd9f599979c8a93acbdb831707f1f84fdc92844b58bc7e4d72472ca5b09c51b1b04271ed9f0e391552463c7a8f7bf434ce5e63ac9365448da8663745f66689b4b04968f9b8b1b6805893000000000000000000000000000000000ddf9e4e302169e195f4f88fed06e0c93fd1b542abbfeea5da5d47c662ad9a16b8f4aed7874354fb9008d073920e1e7e000000000000000000000000000000000043fd1a4b781f25e8747ecb3eec45ce90760e0d5dd701e8193a7e726684ccb8ff21f0219ba15e9e777d339a3d87a1ee000000000000000000000000000000001117d2ca429048056084e4847c7169b4c8ddaefe1d48079949f9f14e4d74f0e0b38a95d0f17389f61da7b2a6d8cabd1c0000000000000000000000000000000007adfc7d87b1c533b4439f6b30d38c694b65b3b321f3eec13cd7d923f1d5f117005be6c3ea901a9479d79fc553e34e6c51f2e2bcfa6ebf84d3ad83c57257b9032e5d62a8663ed5d77afce00f33382bc600000000000000000000000000000000115a81aebee0329b174c01458f8714b13ea3fb2dbfb051b27b29b940652f27e01a84e522626d12be80da7e1039e2baf6000000000000000000000000000000000d9e37d2e5e7160db30acf5593d1c282541a0d4ac0482f0759fef8704b9ec3ab1e3ed248e37c6be285e890ef1a520d0b000000000000000000000000000000000c198a22c2f590df2902c8dc2bb1ee427b33e9687767666140f9d3b51d73fef18a259d43d86fb3559b1ab0abacf547a70000000000000000000000000000000017e705af54ab76145a79e747167a4fec6ec3a16f3ceef86b1ddd1be144e616ea7d686bbccbd1c5c258e4546405be023d6d8b15ec8908bfe008414757c0c7f79b3079f9db86d91ac3ec8f38ae2c94d48b0000000000000000000000000000000007c4c31287ae0b3bb90475f84abdda36610f887aae311d8e97bf97bbdbdfb11d38c7de331cc9dd022926678e5180c0770000000000000000000000000000000017f4afe28adc4b24d16b9cd97aacd171c2104b13b079c643d664a7c924151a401c352832c4967c0e5cecec5f1d1dae290000000000000000000000000000000005a8aa8a3a91461e0ba256e44af56875f8d07e24628e738ffc057249d8380417884f40c84e76dc6ce5816ffc05c0d686000000000000000000000000000000000f84bb7385a6936b519e881a708541570a31a9d7897ab8b348a350adb0d30522567fb917c9b6db661b6f53f98b5e68aaf4723e85076d48389c3fb5a5df16b6bc6f7a69ca701632b1159677bd8a6f7bb1000000000000000000000000000000000a8726ea352582ed52ab4e440102963891f059cf5a3f4901615733ad560a99930efd8692f3c30256d58e5cfc4f0803bf0000000000000000000000000000000016a623dfeae872639d99e3b8209748642f20af796325630596b6ab6146783bd4f2247c7ae38d53ba9a3fc0cdd6f29087000000000000000000000000000000000e40709656e569e4fe90eb85d8761c6ce44a4272793ccb7635ce75d67d97464e8dcd8c32bd4ac9a36fcce706006915b20000000000000000000000000000000019e64802756896206a9600f2d888f3d307ebf958492b1b5153c06a11231e2d7d2f1786368447f380093a29117cc25da9a632938a6df169fb64daa55d2f874ef7629d5be41dfa0d50827c082333f0fca00000000000000000000000000000000019c7409cda6084edc6e559da9b361c96cf207f1e2cd63cabc9b86c5bcb07a59b43e9c6ae3e90a61c872f168ab89cb2c9000000000000000000000000000000001101bb63a452b766a085fb788937f6b751417dd8d905ee50ab5bf96cdbb9d7b68c1735460a71eaf9e9bf662734f495c20000000000000000000000000000000014a103871fe523cd01053a992eb9884ce83c6023bd6a8c2cd9ca60b8780118c88502c6980904f2d2bf9ccc9fb597d535000000000000000000000000000000001929f25d52ee6b9a44333237c732a63ce2abc80c5510bd67faad1d7adac96eac5449823f3a52ed18bb90b93d9640d0d1283a4da7f71bde54d4b7e28b2b23e2eb05d8b025e77e15810625d71faca6d6e50000000000000000000000000000000015b0a46692f57ccd2b7f53040dd75f30af0196aa3c5499049eb172b4d927f96a59c42a129117d6162a1bb31d2e8734a4000000000000000000000000000000001366dde2d9070a2c057744fffe78effdc328b122e356a6aadb10c3fd2e8badc0ff70bc6d18293b3c52428e2ba78766600000000000000000000000000000000016fd48b067b949ed75bae3e4db29b5785bf672bd01032a925d653f8a605998e1eff6c77ec39dcfccd417f1e0a9defa820000000000000000000000000000000004cf22bd706dbb1cf8b97187ed97636380871402b3ba9de58f174bf50a7a0b528749762c3f55f5f835a276e43b46e669d402b71c1fc5c3f3a4ed9edc73457a27ea427f83a784796e01b7a1451b3305b0000000000000000000000000000000000ff424ae9372af46de34210bb0bd670eb173bd49076df5caca4bc4293e742121267a20506f931a4ae77cc36fcbc8df4d0000000000000000000000000000000015a6815b47966fb84aad5de62e6d4280f9135e129f33fd01e667f4d6e1bf7204317fa7741f3cff3682e251437927131c000000000000000000000000000000000639dca43483b79ba8043130e508e91fe3f43bc362fd1dbb135a2eb8f3b94d5cc4af70f1101c790545a0eaf2408706e1000000000000000000000000000000000045f0a04a642bb6e4db34fbffc8adb19a24648554f36ca371fb1a851384a4516a57f1850f7d6be59ff67029ec4002de310bc47acb3aba7eaa490ec104ed9b2985f65c7347f69fdc67b76f6f43846a99000000000000000000000000000000000e796fd500cb1a25b834baf7335641f34ccf04ccf60f82367f0e5c8c7fce8e3030e7b916752bac8e3adc01cbf4b319ac00000000000000000000000000000000142e8bbac9cae69ba3dca48aec045e0c4d7028f73c254433f921b7240761c661cf8e774a21da249f7758234cf7607fbe00000000000000000000000000000000045a3d80767d116e89bab0e9de812ffe7ffdbc41b61f5f17ad16be5bdc9968e34f46b937c5f94f8197e21b358f44b5240000000000000000000000000000000006978b93018bfdbaef0d40f1278e831a1fc50b44fff39b7c93820a284d90b699981b1f422f751a33094ae7b5cedbbb2691b88ce9888e5dcfef70d6f960a456dbabc792571f2a98746b7d833e7fab98500000000000000000000000000000000003c3561f5d255cf1f83cb5f4df8e3b8d5655d965826d56867ae66da631f8e7d489f733f5824c36652ab00586d9c593be0000000000000000000000000000000010b3adb0017e2cea1b71680ca33aee368429880759660dce2d3cdf57b6cd7339bd8853e5efafb9a5aec3f7e22da676c2000000000000000000000000000000000cdf976e4c65edb79ff15178f6ec5bf0a77a30d97b799e433f216a2fe3eedb10bc6ecbee2974167128773cff43f1922c000000000000000000000000000000001599b60ee70d927849764880830b2e7355daf95eefef39ef61569a2b83b2bcced4dfb28047a1e5350cc87ef3cd5cf1d93e82cc1261ac3864266379b4d518e25c05bc492a8946b38b8a64acf47aeec4b8", - "Expected": "00000000000000000000000000000000123af49ac2981e14a490a4a6792f21343497b562266a47487cf6c650769c810852e357445bc68f3460e7822e8cd1e3f000000000000000000000000000000000143e79853e4bf6d031e1116dac2c6eca4991b8a1f822fac1d352d2cf1b88df239d82df886f0b24b3e7f305286cc1257e000000000000000000000000000000000b621056a9de2d83c946b1e2c7a07f9beb8e053202407323e412c0d8f60123cfd5818067f57034fe1b1b5a3d1bb285a50000000000000000000000000000000001642fdff2c52d58d38201cf44c31e00df47ea1439e9896b5ac5e9372482f4ffcc698be46c2d375d57a72fc677a9fc8f", - "Name": "matter_g2_multiexp_36", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011f78204afa05c3717d3908dc7e4356ef96c426ef380b6abba3a5616d9ee01addeec3369967ed42e030c4b8ff9939c4e00000000000000000000000000000000175a19c86e7eff0f4e809a5105503ed223fe327ee4617f7f51257426fe408373899f39014821292a75e4cc4eb9f7f31e00000000000000000000000000000000052130dd3cd17840385db424802d869d7eac781365be25ba401b7b0e4025353c8dbf59e5997b5aac74c252192061299d000000000000000000000000000000000457f4fc7ac5d7d4fa07e8ed125df4c4e950e6ea926be9c04b6df3c3699a10e99af7ea8546b8ac70c3003468a75c821ca2a1148f1ba719b2da92c418fd137efe21a44dd4cce013ab36e57d97dfed92990000000000000000000000000000000005182a3af2b52102e09214d048a1a29d1e10b7ace6afbc4e6b1ebf16790be372dfb6d65cb8fe08c3dbbed8c5435a59a3000000000000000000000000000000000f2a1261463c09a88edac443ec3cea8aaa19659e8b7ec2e8a403dcffb1e50ebb3d07217a9ab057d8d097c075609c13900000000000000000000000000000000007d6525fea8fbb685fcf89bd772d48c406aff7377429fb199f27c3c3337f11f8e24c4d81c9026b469600d11e8cce51be0000000000000000000000000000000004b6d6102debaec16c34fecfeb444e7ba573b13b83ec375f14d2c541a0d1fa528ed6599a0eff4f8ca527c5baa579f762fec5d6167d7777169348cf81ad3eab5153f8f2f18fb5935c5ee5e3a759f9b5af000000000000000000000000000000000ba1f2b2c3f1c57afa0ab647d32af5d036ef18069a4abc9795dd9927ea274a718b67373230e337cb9374ef73b5e2303900000000000000000000000000000000016458ff2f5d600af9d2983f535c965a2a8aee48c0d95095bee642bb7bbab8bc87e3e7c3b52a787c53f0d1e00cb4ff32000000000000000000000000000000000d11324e812cd4fa65d20cf58f88a9bc9407657834d7a92f80bfd32c7085ffa2f9f78d7e18c1405a03de939bd0dbb06b00000000000000000000000000000000144a0f4d50bcb16942d22a12d28bf34d2b4c51512a3f11c130f1566aacbdb63ec3984df5569f41ef621f50d138883d0dda609e1c8fa42a993ff355a70d44dfeebc71a801daa36acd437daec5d7b645d10000000000000000000000000000000000d7b138fe445d7b7e130134db653022ebb389075ffb62ff9faa544cd0fdb9e78e313d0b1cb19bd812421d38d1e9996d00000000000000000000000000000000084411aa2719b729a1e299fe8a710f767009060f1b2becf2aaa92efdeea8c91239aa5d2504c6e7ad2e3f39d89ef00c1e00000000000000000000000000000000017e86dc0146c9bbfa5ea1e48f49918167dda13b31ba73311fd5cfdc12845b95b9e90972a9a4d36203be8c5920f8de5600000000000000000000000000000000150e4b6fa9cd9a609241d1de8a637c6ab25207bccf8e5eff4a97ed633b67826135172880b118037649407a3e1b1a0661bc5f7f5d096247ababa51852724ce9ddcc6acc7ab6180beaa1cda97dba94b4ea000000000000000000000000000000000ad7430b7778248d63a06e26119e5600ae97071fe8827b24440587e8bf6887b646f342741af69d20e243c9b45d7dcf24000000000000000000000000000000001230cba1a5a66197875240fe00c59b796ba1db5ea5653cc76bf43d6adce0db3a109168593beb39bb45688c1d124b9eb300000000000000000000000000000000144652474c58413cadf9b31715152052b7618e7093e931367a7ed0340e66d84c0471b6ec178e1730cf10e749e01815780000000000000000000000000000000009abdd0210f25d12146f2911a60035867f59cc341b35c73bbdf8f7a5a90d0bb6566c6ba0e868a3d62d3557436190f3f63222b41a59f9551e91572ae00582e1e41989ff5f8e2cd1ee1a78f55c2b28ecb40000000000000000000000000000000018ced3cd0c169693368fcf9c3dfc49fe248f0b9b5511e9407b8634d8ed7b54ae2dc4ac6ffde8b3dea70ca86ddc89449c0000000000000000000000000000000002f6b227e699dccf7ab1e0b1cba4cf9f05c4dcaf9fee6cd94bbb79f42bc9598fa23eb2c653a7654db73feb511b24829f0000000000000000000000000000000019785959766eb8b00ac2600d87240f2876e049725680f4504f59db6642ff8f82d4e1b856929643906c3be7807a2443180000000000000000000000000000000018285acdf25a475b37ee4da872debba4297fc8731eede6b22be3b0dff12117634de44b84a18042852ef419c3ae18a46b7431e5c1fe5f8d38c759bc48e8207695a3cdf07d4c1fd02f1009088539085da10000000000000000000000000000000019c7950b01e15669cc1f96fd94957535f32132ff6a5ae788f6f660024c332593942bd3e9603f862756edd4f3ab17b20b000000000000000000000000000000000bf3a6bbe10ad91d687a135f4863ba0332e9b04271d437a6a4770056e6b1ca34319dc895f9186482bbbc815aead03392000000000000000000000000000000000a3ef4d4f7a15da04a91ff079cc40040993a90e9ea21f53e31f7dede52dd513a97ece780374c5f3aa8c8b2e525ee31d10000000000000000000000000000000017749fc7761b06432632ac686d93484f08407504e58b04b3890cc2101f15d21f46ec0dc1e9028c8ef8df10f9ae929887d474e755f6ce9045baaed65c80f5a686547089e8cdf4ad2b7c2ce7c255cb5c730000000000000000000000000000000005a36af876edfdf26175c185c3ef005530e02474232ea659f5cf251c5de5721f1b44a25714967d283525632789331d2900000000000000000000000000000000130a6f5edf94736477143b1efc316f131b36d9658c484821be08e7f5b9c93f60cf34042858664db0ff0240addad8782f0000000000000000000000000000000004fedf49e6d49c074dcca96c01607da2105d8053861b4c677a69cff0f82e66a2a63f32f3d9fac8e6c844a1f77055bf31000000000000000000000000000000001528541de3a9d4a216c0e60c31d2b7c7cb91b839fc31307cc70f18e9b87b92bf5b9a9dc4eaacdec6e6bf7791e547d8a2976c8775b0eaa1e4aa384d222efc476305c7ea2d625cf5c67ea4368d7a9fccd10000000000000000000000000000000013faf7b2b8514f77021d8927a3b63bb7c57785e581f40ca82882341c13a9daf062a26b668844e58291366ea6ae2f179f0000000000000000000000000000000009060f9e1047f15f175fe95cb0914f4941bcaf071f24e856eae6f36263c812689a9217da277613c10c8e254a0933c80800000000000000000000000000000000154619e4ae3901789ed3ecdfc76069d8026a3e2cf142a144e8b58482233380690e378de6b81af0ed9b6536da1cc2a30b00000000000000000000000000000000040c1bce922503699e1fd5ac67725f11d7f9bb6903ff9204412f65355be69d73cd7330a3f7bfcacaa9b078ba6b9a9f839db274233c46caaa9c99690fd00fcbfa4eaaad7c41f8ae84313448c787165f6500000000000000000000000000000000103d91916d537379d6d8717b17ac5b7e9fedd98c24890b51c027cc086458259767d989b3ff9d6adad72bf977e4d378f400000000000000000000000000000000159c01ee371622378339518217dfc0570178aecc938b4a008dee1a6661ffa605c0f1472c107558ea791e0959d7dc1c70000000000000000000000000000000000ea3e10cbc3a55ef2dc7bde7a2e80666557e9e8fd9ce77e2e92c2c70777afe43c23072e263e1def56cae4b6d3772db96000000000000000000000000000000000cf1db638331c47f9080c04117ddab4ba79950563810d50e04af819f14ae0981f6e1e94a635fc90226c8d7beef0844354ac9f9ed46ae5aca33af9ba1c0fa5a2138d4ca02b962fd1d02b4636114ce19970000000000000000000000000000000000095c82c58182ae9a1ba14421c2966d687f7225ccd192b24097f997b471d13b46a048202712cb2d8b1be0ff40755dcc0000000000000000000000000000000017410aca05935a06942f673d1937a593423cbbd226f6707c5922306d28a60396baa08a941122dd4c583331c9481a734f0000000000000000000000000000000002c1d3a1262ce8aae42a6ed10d8020c31a468127e1a59d57d2d409ca9d14143d9fd21353b260edd8b387840580698846000000000000000000000000000000001512e29256b6b9f5a7ba4f79dde2c915b162e4881856258ac2050f02868842381518da4ed824243692b131710d7201f8ab300ee55e90ac046dbd772da788dacddf72c559d9378b39507987a9774301b0000000000000000000000000000000000ff83bf1d50fe35bb3d1bcb07b02d78a1b44d2e0c6bf82c600feec3897fae8b93c0ef05006c1322af0a732392dad86e8000000000000000000000000000000000d70c4957cb3615027cb950e4224d41849b9ff1b435ce936384fe17c4d7bc2883fdbba5123ca0c0c010651500557e1be0000000000000000000000000000000008b16fe9af45fa913aa7e5d01b5b58f946004eaaeeeb493759a5bc2b192d2dd71af24ecc5c6838b5e267ec2dfcf5c17d00000000000000000000000000000000038ca027c985af3cf60cda13e770fbe4919d3a5b413763c8ad155cb4903312822366eb986f2ec9e0804594ad4894e468275b22db781d5e8fd07f36788bc1219c4b4a13554c28d92a381adae111b265730000000000000000000000000000000003a313d6d41f1ebd6b98b2061a2d85943e52d89e4b8680611d41ea182385e154da24248faa1563e6ad79172f91a8763f00000000000000000000000000000000038d9388fe9169710e1a205ecfd03f674b47ba2275794469dbd5f193a55e00765c8eed026363b41afda417bdd8910ea60000000000000000000000000000000007a75f53d9b8e5eef19ef6f5fe8ce5d5308a1a7d02e0bf46f91a1e0cb22555752d82d8471c123269050fd8f35a272f600000000000000000000000000000000011f313127a036403652fb2f83c5122fd12c362ecba2251bd6c357a964dd758eb2a2c3053dc668b9a4bc071898d45cd46ec69b95dccdbf193d9ee4c51615c0b7be5ac6bed3f2559f0cb2755c634839ce7000000000000000000000000000000000a43335eb6ff3bf2daeeb1eaf44c2782eeb517e82e55203a247b7a396e26fdf85f93695753c52c68819b58c95f361820000000000000000000000000000000000c240b7896b3dd0c318dc9ffcaa001d20bff288def3ce42752d660fd705e1544e292a5a0aa3a9a80ae91cb47cb938989000000000000000000000000000000000e5195bcc4ee8b149a769322165b6a3157ee7d04546643390adc812b6296675dbd31168b268df869a6722a7c8f51c79d00000000000000000000000000000000004af7dc8a5c552f00d55b996d193a9571173ea829eba8fadfa7becc2f4149ee7c6c4d2c8c7b1970df33cc56e450657331e2bf1816a84c190eaa850ecfe1a9376123e0d0732d90ac3537668f8f18b9f70000000000000000000000000000000007860c3403607d4e13f738357e18bbcc4df10fad4aa25776f84d3c2758624a83aee0996146ba17a812384e1d67a7c54f0000000000000000000000000000000002169148d86b1f7a0ef75d9bd19b6d7cd66da4293fcf33fed9241544dc2564d980161a6bd959f3b43569312bff7a23cb0000000000000000000000000000000001897c121cbf5e82424cc50078ca7143a0c670f1217a9180cd2a4700e06aa895cf84c0af94b7c04bfce047a7d1f8443100000000000000000000000000000000040c1a0c4257f90bd83fece3c9372842a148132d2dffa956729e741ce996d229aacb04387d51a72630329230020b2235f4087feda4bd8205d96cd0bf6eee44c27a6669d7ae8e16c731849cfbb2324e1e00000000000000000000000000000000058c001ee1343c6cde55bbdc4c538f5d14b0e8c199fb822f080ad96ee764bd1908f92260ce60cd521919f223301ba1220000000000000000000000000000000000f8943c35e7fb8b58963719f1b9820153e0831cf81dd208176af7527781ceabcf6ed2e2276cbf374e0525952bace0c80000000000000000000000000000000003b43ea8c32a13c014b05326f7b4ad5b5fc1bb2367866a69373ba91402f4b45409c6d034898e8b0ec3b93c2878d59b72000000000000000000000000000000000101c371ab4d57ed2cf17dcb731117b1986bffc586529fc1edc630de1c6f4fdff1e10b0895907bb81d2ccd3eaa96c04a67b81583fcdc9afe5f35974dc9b6310ee8e1c92031a49c08b05555fc0d33517f", - "Expected": "0000000000000000000000000000000007152d538d0f750901466c1ea34a16e7b0e1296a2a3740568812587affa5c0c76ca2055804e24f3415a403f06a717c0e00000000000000000000000000000000119c0c282d22a01524d87eb850789c4816e7dafdb2782b57c32409b1016615beeee2067443835466283543773cc8b427000000000000000000000000000000000d68137c3df081a519747c044950c3231ef82295eea5b7040843668195d4549c8ece4a91447e0ec89530bc51277535fb0000000000000000000000000000000000d81a4fa2d32ada3e08a7bd4471d45a6afd2cfad5bbfa3d378b1df2e0749f9b05b465be61cc9d1a0f4abd56dce03dbc", - "Name": "matter_g2_multiexp_37", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004b153d6554c9879359052717457179d8318f8127eb73edc1d6ac2efb1ea9643c4357cc813d1df49730b77f995d6d449000000000000000000000000000000001533a450737b4bf8edada15446cf21ebf82aa7bec7943025dccc4784e1070fbce430699cf3a37a36a3ece692ce87639c0000000000000000000000000000000017b8afc300bd70a3221120f6fbc37a8e6158c48b476f00992c6f41808036765071bd0a76f7c641443b97ba523153947e0000000000000000000000000000000012f686b4759a3d5db2325508f148bfd6217e027fe261d3ed7b8fd0526036044dfb563e1c4399ec266e140ca372120e289f3c65c2c25c6c37aa45b1104745cb8ec511a165ffdb7e304f5478aa3add4d7e00000000000000000000000000000000061c8288b7bf2856c075a176d1086fc49f0359ca3e7c1aaf5f151e6462916a4e1b69b6decb18823759b620f7593079c0000000000000000000000000000000000877af18cfa0d029e7c9a5833b346c7fdec06e54d9641d3953d3cae0e8912bac7c990f8864c2adb6e576442c634865b6000000000000000000000000000000000331490f42993de3ce7cdd53afb4b310f25881710a23f601ed95961bad4e9cbf57d3077803908a91b65fc32d1a84130c0000000000000000000000000000000005aec079da804fc572bb8eb867acb93a24ffb6611eba920d2ce799c4c80cd8e73b3cefe989885167ab685365529b4f2a8fd50c46bade91a13d6dc5a06ee62e5e89e0ae7ee885e5516ca6c2dacc36f6f3000000000000000000000000000000000ecc7abf4f6f9692cf3a118cd01abaab4754c90d1a59468d402bd699992800c2994f47b2094878604bf7825f125133e4000000000000000000000000000000000662396427cc596458e880bb8a43dbe046deb85601e3c64556990de36e8637e8ea3b142a8195762910a83609ca311c3a00000000000000000000000000000000198b9c52be68d073910f5b26bdeada9e9b308e4541561a8ffb21fd8e69ec9d93b01ec966fba65be27ee53d4857a43e120000000000000000000000000000000005201975985cac810248e333ca714cbcac0ede46bb915d8c857837c80c805898d0f9ca0940819878a26d269faa02cb86128db1a106328916ca5d63c0b5722642febed26f00a89430d52ec3eae25a019b0000000000000000000000000000000004e61ad4818ea3c98ed3c0d247798a1a6ca6bcb35a1cb60bda9394272ec092c385661ab93a42af439f1b55ee8b9c0cd4000000000000000000000000000000000ee0b71ebf39e4009bdb310fe3b555cdc860abd47a67bf481ab36b5ed0c00bdca8082abfb75691d45e10c2f2d777be19000000000000000000000000000000000e9582e3b5bd580f3ca7ca1f58e39379918f2d04b82b418a91e133117a9703f7df4aad30d48a47e29aeaccf5b8e33559000000000000000000000000000000000113b4c068fd040cd3300a2d1ef658955b014e571e7c77594edd31968037c1fff241da88e7a88669a569462564e28cd7d45665afb6a864893e389511a0f7b2df74c9e45a86fb69f6bd79854e3a88c206000000000000000000000000000000000d8b0bf633072f19db61ea263a1dbeddb326738396caf1196e31e2cbe99a68e8c70f8db13cfdfa4fc4494e54c1ef28210000000000000000000000000000000009ceaf2a0c63604afb8a903195933fd1ada0e5314255be3d74a95679c7a7845785e22d2c0c206f3afd62110ac9810c2e0000000000000000000000000000000003a135b405f46ae3f5cbdd63f4964cdc5014c9f3405c2062ba17423dcd22b8f2011638d520ce0ec7bb0cb5b03e8ec01700000000000000000000000000000000066eafafe1cea67aa6de267c767f49d4a3fd44c28d45a920fe9b3cebdeded883d8960f5e9fa4cc179246918942b1428d28f5fd09c2c1819adf8e6d0e0f4e4681babff46757edeff3839e9691888c13220000000000000000000000000000000017e37a2f1c892fdc58ac3f72cc5a5e2b7c0c87333afb06de89f7a84b1267695bcd452925fb2f15f8b7b20aaa85a6b5650000000000000000000000000000000015b2919343962337a41b54076d6735a093190e1965faa33eee800f5eaa43c35f349aaf93f19977b6fcd19360b27edd6d00000000000000000000000000000000161afb1494482f953007038557c847e2cbf84c57c5f5b806e3b0178e71e3238305f733943bea7ad6f2bc290778638e6a000000000000000000000000000000000c27a2170fa584863697292e626e2539aa15f3c8eee65cbf1f1b7ced6297248d059fdaeb9c955437a51cb016d1ee97c3e6e61390ef88f20591570ec1fe71c3ed769ee8e234c7cc7303a4cdc065717736000000000000000000000000000000000313a30edffaf864d0f1c6bdafd7d1e563cef434d45e71489e9f9e4cc6700e44991a99220f53f0cf5e7de5f6e4098bf20000000000000000000000000000000010429081ebd2ed6fa07de6ab0b7bd559a26a43df99fca0a2252411b4554dc69821ccf3df1b05114da84a616ccee0a9c800000000000000000000000000000000131a31442f80da4621f7691664e9f8b467988fa039bd086a2d64f9810878b557614c27745b2e821016f648ec36ee797d000000000000000000000000000000001160cef9f5e4d022baeacdf10b3bf9d7ed5e50627a99e29df1be3667cb872b2af333f803bf426314369b490c2eca642aa83c5af2f9d10c06552ea7d1749cbfa7574b238433c1c0e4788efd0cafeffa57000000000000000000000000000000000b20ec53bc643bdfda1e3947b3773d748cce1992e2ae27c6b7460d90d48e08eb9240879a5a7d3dc3189f486706438dbe000000000000000000000000000000001024bae4a7f71d3d2fb8246e82d95664c4ee8bca4a380c293ea084f749911f984aa4c6f266ecfff69c4f57e20c0660ca000000000000000000000000000000000b58472d81a9f16d2fe7af87170ca0c8c51dada62a4b2a713cae053a0066fd268283a785ccf269e05d8873cd686d2f4a0000000000000000000000000000000016b68177bce92fedfbd90cdb752bc332f46fde6673911c016fb9cff4912d79d3267bf629c33097cf8979f2b913c0936d4bcc88d85a5a8a29dfad37ba97ab3a5defde4ec356146db8d10f33bfb36ddd37000000000000000000000000000000001030d5791bd2a27469d242c62403883ca167303d907839e608acd827b4118b752840a4eca0acbe5df0b447d6651e517800000000000000000000000000000000106d65f922581237f779ba3e66608729dfddb2c487bc927f34e5e39707f2c8a82e8c96af68e3257c7a9876a05a1b01d800000000000000000000000000000000115bec40b8fa914305b1d5a85b65f0811517d36839494ba69c929fc2422f7e8b85d78df4e1687ab0087287eff29c65430000000000000000000000000000000018d78a75ec057cfcf179fa2ffa7dba79cabf6525dabd69ab95b23dc8f293aa077e46e562caf447dd0913ac9dd60ec76b29d5d818e62c9791c320e01a3164e142d9804e9caa7f96b4c3b76baff38ee2e600000000000000000000000000000000023f7736d6de94b08d9e9efb6f32f8c17cafb1e1b9b1f3db6e58df72a451c3225d11f4304eb0d702b07a7966f95a11fb0000000000000000000000000000000007b3204f258c873a6fcb48d0b36c98ed5f99b424cf4f92a028174e0e93db2af549648ea95fa8c7bbb42b2a10eeceaf8500000000000000000000000000000000165d6e769b7df91374dfb44e18d43e03ae12ee10d8a618a20f67332cf96492ff514eb7de06ea53096e823770c686c32700000000000000000000000000000000012e69ca1e106411165c06ca15988362de583c4a05425e2f4aba4c14cef6d8d04c52c87b4fb26b1557801f55b02ee8ba971c8aad41e401ab6c49dccba28ef26acf4961978e94e633b72c581ac03621e4000000000000000000000000000000000e8e6bf1c8837c31446959242285e9b85978a5349e1f0b3447e380a7bcd6bce758bc6192cb880f9c09d6ad4a0ee36eea00000000000000000000000000000000199b361ad0b435d7a66b46a43d06e5898376a6c260b68c965f7b186fc75d2f321bf883646e7551eaba03181907d3aad1000000000000000000000000000000000a76e3f399f31cddc4dd4bc22187a68fba31fe2371291ab515d22730d320ae4240911c755750f687c7d26aed09da4210000000000000000000000000000000000cbc8dbc004b9253ba91b2238c92bbf7883360c7ce39f6e15592a8668654950a3fc5a94cfa97f5ddc60add40c32a3630659ff910eea5280dc5c24c542516053637a5dbea576a94a22acefc902e56568e0000000000000000000000000000000005448b623604262a9cf1a9a292c36738960e132bcf0ec8e61a510008c2ae0b51b31da25f2bcf0d7c0d4ce15b1d7179fc000000000000000000000000000000000b61df56ef891bac07a873571f68fe43f79438a31038cf8ff97393ba44cc47408e5a6d64e9ebddf0195bf914f141e668000000000000000000000000000000000d196ced22ddf11132bbebf6c85bb3006a194cebca975d74992ecfcbac546f0f25a39ed5d6100768c1f1a791f3604d12000000000000000000000000000000000f727cb947849d2d7b046218f084283e5513e8582229085f9f98fca522879543429cb8ab435aa3dbf01b68ed258d82c112ff32d44eb442a711250875d86a401d0dccc95e5ee39bec71738fd812d487c6000000000000000000000000000000001044bcb16b3384a1f350cbd62bae568c96932a364c16b34d91ab9b1035ddee93a02920ab4dbde2c6f254031909dc3a450000000000000000000000000000000004a29aae48210289e5f588aede0756ddf60724b8ac54de5d9159ea834d5da98b7a9d09a6f37bcaeaabc559dbdde58b6800000000000000000000000000000000112ca953b5ba652c715fd20e3b85c5bdfeaa7d577aa49aa4656d142c9c2afa3d8aee151338f59a199f3c0c3f6a430d6a0000000000000000000000000000000001ebc7a17da7809f9e744cf7f13fc437de34d3472f022493f58bb979e2282368f989ca0982098a7c377498f1d8d32583666b820fae2459b98f9bff20275a3c96ddcaf98a78f3f5fa4a2c0a26cea79352000000000000000000000000000000000e7c3d6bef4b1723479ab6724cf7858c221993357b194e5055db96b8168f8d78f72aaa4a2046be17ae9a7eb00695ec510000000000000000000000000000000015e85e85cec08133b86738e1f7a738de455930ffd5073997a1f1692c28044ac00b634b90eb24938cab56e286ca0dfaa400000000000000000000000000000000164646a4767ed69f9280f96be9a7f988d17c187162554239797436a0bf4c4ffa7e4f8387c3d2406a7528c021f56081df00000000000000000000000000000000197b1080bf3ac3ef7bd6123a55f20f1002f366d4efea9e14ed92fd2ef147e2b5d9251a302a85172235438bb2d35943a740a9181633a146d7f307ca7606cd45b8e721c46b955a6989d421baafd8e40139000000000000000000000000000000000db7cfdfd58a6ce9dbbcd5d65cbf22b5e1a81acc70f1c85651ba962d61fbd7ad83e5524fb9aa019c6bd75dade96f7d4e0000000000000000000000000000000011e269a390fd15ab1d52d38de78ec97eb6202604fab02c4598ecebc7635ac91ee564e751275a485fb43b933678f11fd8000000000000000000000000000000000b8597a00d2401664405dd1fc7d69786353c86cd4699af981fe869f266f9087b00df22a46ac34883173bead870798f650000000000000000000000000000000009117a49b3f2a8a850a0179b558319bdd19a5f1f4a45af0ccad0890e63b222d028536e9bb612093cb3f1068d262af90d662ac80797c633d8b9c8907acc2960ebdcb5bdad82d9fceb4411d5173b7411fd0000000000000000000000000000000002e1311abb9df5e4d76959276b6f725f13728844f8c7dfe5e25469cb95c6937a822282b3baa38817e24a6219601132bb0000000000000000000000000000000012820e6ddc50e19a8f98c15013ecc38901a4ef8ec2b79b85c7f7913da24404afa1c79045f1318cdf271028126f9420a5000000000000000000000000000000001794e653c5673e51a3ace631c1a1265dba07fb74235506b2149d42b90eb16afc26ec0ddc54d03f7ba2dd6a2503971fee00000000000000000000000000000000112479bdabb9dd057b325563c666910c01ef66adf47aa32f5a41bc9cb8234750985c266fcc329ea3704e2b8d9b15bfeb59401af15d9b83e2ad68cc8e2ad1508391516ba0b26fcc5ec6eda8b318a374b6", - "Expected": "00000000000000000000000000000000168c90045dcccef35cfe8eb642924ec2629db886366fd9ebc082019690d103627865f0dc39ffdd2167111f68d8d03c89000000000000000000000000000000000b6f0928a32672983664ad15252b3f145afaa04f11d5f43a6169a2fbdc0b0a04902a183b25e38987c45579ac6d11011f00000000000000000000000000000000195c4d796989630f85df4594eb8353d44bcee76d82b73ff7a57069466337b49b875b3c1418d22d79716ffded7e704a6c00000000000000000000000000000000032db644ff8ca6a3b1ac7bc51ff783ce0cdb7bee8b2c21dcfd3adb56a3e210390756211f22feb3dd4f706e13e5cc163a", - "Name": "matter_g2_multiexp_38", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c675cb5e90e45300619be91c752a5831ec47b4143c28330422cb57139882e776c1c5f000d6032cd87c16ab3b1c08ee0000000000000000000000000000000000aeb4e78724d46a55e5f101564bc05e0a1be1d80a781ce8a19607322e82c7ee59db9f53ec34c70bef0766a5b965f54b1000000000000000000000000000000000933e8d7c2420cc553afb1c88b5f64c7a39f78272b34b5611972dd5ced3f639ae2ed2aaba470abe829be6ca6d666ddaf000000000000000000000000000000000ac0a9b46323ccabf4b2024e3a5b4717cd8de9ed7de8a78e33a38037f802651a4b43380a746890d93289d547d94b61bb9c351c585d1920b8cfb89a5bcd72fe041b17f7bd091ba505b287778b0be4e87c000000000000000000000000000000000196597114fbaefb8108c185a85d0fff0f6bffecf056902b22d61cc70b49a747bb35638f5b663830a8d2ee15df9fd5a1000000000000000000000000000000000616ed44a5fe69da994e2ada03a1e09065964223333229f5f30ba7a452830848f599ee21810a95e3659cca495897bb710000000000000000000000000000000012d0631e524ee9d3c776c79137499f8c9fb752ca93e92497d89973033d60971da23f672f140c1a753b4d00d08a00babc00000000000000000000000000000000111159e95d131c8cbe8df75853fe9b3f24013daa083e57c5b716e77f6fd3872dcfe0156382c9d2778fe886621be19973ec42da11e95cebbeed0ebaecd31be24801fdec8b81f4046fea52f553c4e7910b000000000000000000000000000000000a7d253487591fbed97381b3a430404b87aac04073e5931ee0bfd9ea6e0d38a41090c6dc7f6a591336fc58a97a3bea8d000000000000000000000000000000000647c67f1816ae6fec39033c3169eb1ea89e5e20e755cfdea33572d6397e7e87635c7439eda4912361a32de313893206000000000000000000000000000000000e0cbd54634d070aa3c7a503df1171a5cc435d050def17395707bdf7a61cfd539348ee5a4c29c7845cbf0e5df0531f530000000000000000000000000000000007d006601dc1e092a616eb470be35b5d32742dc6a2a4d71cda8865f071dbba9d8a3a8cb10b486253b1633e4590e716dddfdd8996780460757702e34ad98f5f64a8c1e0bc8851d6c97f02749b8f77cd03000000000000000000000000000000000c502a19770a892b2fa1ba59900a36c0ed054a8bfa0c4e32bf471b90d0da9edca6c06b133c8f12e233b104262a81dbe00000000000000000000000000000000011801f159086d07833a691182595a42645513d316c084b2841445c4a63c6bbb402664a9a9a100e8d6436337ecbf398bb000000000000000000000000000000000f2b9bfd8ef6286bc41e9f47ffdd3efe437aad553c9da02b3c22ca04b5578d634c0543a07bea966bedf345562218c2190000000000000000000000000000000010be5ffe0cc9f580c74e027aad09c213189fa4b7aa92160ce813b8d398b2e2803294e1a730cf5c891cf1546c6bc91414f256ff23b38b3b986a62074c5a3e05e86ead9431fcdeb67512f6d502fcefe3c300000000000000000000000000000000132cd5220c125759a18c31313592eda774247f97b5134111b01ef28dad5c3ba4d3f13d1af9076d663f7e217258a6fdaf000000000000000000000000000000000f06a5b03daaf8f92f9a302f06413044ca0dcf2be81d9cf016120312fbd41b273650fbb542d419595fd2815a809c4b960000000000000000000000000000000001b11acf12cf46e40554a1d6a833566cec1b2750f3f72ef77496477831d5933f477d59463ba19c03dfbbbd02fcbb680b000000000000000000000000000000000b2aaf91827ba923c8a1c2fa1d6fb92384c9f48f8f77273056b94245114d1f3cf66fdcab330673ceb2e9dad6c1aed0d4c01b3c8bb0acb17198bde9adce3b0f7ed4cd8615f837aee928524b0984c99d0e00000000000000000000000000000000051858339be99d1271152bb390e9a2ec0c0760b7686804ba072c46db3cfc4472404a9f87d868a28f2aef16c9e989d6e90000000000000000000000000000000019a33f21d0bb8303f540bf26816f145360bd1e9a8229dbbe7981f1cb5b099e814f2691fadbeeed8e4c4b772bbd27e60600000000000000000000000000000000073eeb49aa7e601732dc0888ae6b0f5e8dde3d97b818155221f5ab8c599eda75b25c86f15ceecafdfb9ee4abe3419e10000000000000000000000000000000001507073b97d494de26e70f18bd1723d931cd2a88903ab6da2aac3b80fea78ce75caaa9b99375780d759fc4a1683950bd458f882b63c99ada33d8215111a6df21c8f7424eb2fe9f429256201d099413c10000000000000000000000000000000013b5422deb0e80bec71309d03fdba007eed33c3ce0fc6d4f9a0d063136b3b85a6fce90ee59956a9b91e1caa519f813e8000000000000000000000000000000000829a11eb50f3bb1a47b72cfeec9d1f63e02b9f7b2592174c481ea7b72a121645ecb36b3d1964b082bc6c7efb4483a180000000000000000000000000000000003d3aab53814f55fa97285af2dc6d32cfcf5a08032d2c15ac83ea036603e08a53e0d2b8d93a25dd969937c113e78064a000000000000000000000000000000000c938a68688138149cda64f168ac1466c401196eaaa44a464d9e345c422948767ad1e25d1ce4cc5996ac5d5dab61516b804d7a35e5731b111a6904e0998d90ce86cf612914152fe3d2fca0201a41166a0000000000000000000000000000000001ab96f0b60213855fe221fdbe2fb22da6bd6cad8bab8ecb747c9528d3511976236ffefb34afc462abfde13a99503cb900000000000000000000000000000000182fb121778cb002be3f90e2d6837a406edbb609bfae8fe59837aea6f5f6131a10791f92188958b57059b7b9a9d3a24500000000000000000000000000000000159cac269098d223ee6d145a4489f05875b6a546767c023dbea62b3cfba9f8518c9f4d2594d00ceac325f3d8ef551369000000000000000000000000000000000c0d2e4e7aaedec7e53bfebe8f7fe5115720e58768469b6673cee3473b08fb8cd1ebd0514689ef65d78d008889e3ed296f1629a801db6bb4066588ed79f75223120728c3a57f7129d88f7f877149223300000000000000000000000000000000079c40bd7fd2ce0f48806dd2e88850ba988e5adb0cc5120977da8110b07da264318fa034c0c213590a2616f0ebe40f21000000000000000000000000000000000905f41389be39361fbfe7641394d30870a079f230dacef89149fdcf81a4d1e0e10b9fa1c0c3ecadced9aaa19fa9dcc800000000000000000000000000000000192f50e08e497f902403df40a504a1b4b82f1957572a9ab7ef97f5ab93c6fb876d8b08f318244cba95ad5200fc2a6e34000000000000000000000000000000000be7ef45a14871dbb344a69c4036af4f994a22ef14540377d1144a92978a23c2d678cca47cbc18e8c036714112d11f7cfe80ddbcaeb784e24975b9a42801c89bdfb842cbde5fbc0c3d70c0632cfcdab80000000000000000000000000000000018d7410f0105ff03cc4ddd87a6e0b65ede4abd4609db5ae53720851c90255757e63c6482de4651eb1d3669b1e1a2f8d9000000000000000000000000000000000d4223be106693a672da890b64d2653135119983639f7052eb32051c34113022080ce2355a93a2f64a75d8e0578b2f95000000000000000000000000000000000764780391249d0c987270bd181a44f6260ef82eb00c06585db7ef09e8b069e46c4e0e659a081ab0fda491534b71b0ba000000000000000000000000000000000a8546031e6466ae43643462b7617703a63841d6d4cb0c09ce63b2fbe2c2ba7cc35367191d0313717b1daa665bcb54551aeff13de7bcc4bc2ac1b37e28ce466805757dda29c9c743eaea9da33f47f4fd000000000000000000000000000000001922491dee4e0f29a1dc090c9b48fe8e6d70c3441e532021985932005b22cedaeea7d9ce1796808d756b740ec63f8ca80000000000000000000000000000000005b34dae0e630be6a59ccae17b44eab4e7f10be2ee700bea15f9771a724f0979798617e129540901a8aa023630a446f800000000000000000000000000000000095bdf612289258b31cc79188566ceeef6fd66858b4dc060864d378cbbb69f951e9c6bfb3d1384014507ff29f9446f410000000000000000000000000000000019f06f11a833c06c1c9227255e3a1d74172e73b06675c547844065dbb909ad66bbc150ba396fa1ba22b7183c0fe80e96c4984739882bd2f882e12660815b96d2af7812d7ae87f5be034b88e9e04fa2890000000000000000000000000000000003de8082f828ec51e23c864a16147546ff60b5fa71897ff4c120556af5c6616bde96b6e53fa673cd1f8af503070bfacd00000000000000000000000000000000093013f75b6a19b5433b3b5ff044384ddfa258420c80fe81e0424e3102cbf9e550a946e56ba9746423ef745e33da51e7000000000000000000000000000000001227cfc3e9a8d6a71738c514c05766ed4f1f4605198f5a3ad8309c0a49499e4ecd34ba1ba7677d6d90203e54d7611807000000000000000000000000000000000a635221d514e58170ef299eb7f5b679050ee24c589cc7e348b2905a3cd1b7bcf2010cfe168f5aa60f4bfe15e59b4436e7f33141d383a1a927b7645656ff7a5795901a997e27003c5672ae4fbab4aecf0000000000000000000000000000000012ff0494d308d3e7321ad4c4000e9dcd19552d5e4bce8504760f066e2fb2509279b01f1568e3c3f6216bd5328cbf72db000000000000000000000000000000000038c6e8f0fab30b5c8e4323c1fd29527845c29e1a26c70b8e5284f7ca55fb55ad4ad5389b5280927b98907132f26b76000000000000000000000000000000000aef946b9b9e9fcabb36507c1cf441df2f5ccd71ef9281dafa5e25bf07d69556e4143ab402dfb38aa756bb6ee009a6890000000000000000000000000000000015f69bc7b0a6f2cb64fd0897b421e339fcc8637efced8bf33f5aed809a38b49a2e6376d18b1bff0ef70df1b7187ad048fba4674313a9727aa4b733832a0e06666d3e38184836edf786317de9dd055cbf0000000000000000000000000000000009e8450887137cf45b04184b3c6fedac6676cad416a7646e9980dc99a6d6b62164dbdfae7cc20edaacb84432627e6e550000000000000000000000000000000002acbd87ddca9dc775da01ae026f1c60f1cb5974ce40caef80cb0d2eb7839777c1f61eae0472c7568ec9d0ebb2ec7dd20000000000000000000000000000000017c295c458a9dd995d848e3ba585f8dcdec4185a953e4b8e3ca760eb3e815e39a8ff60416e1e6f974cf7e7b086ee4baf0000000000000000000000000000000003cd8725e1cadfbd80585bf5a19e086abd631d6787403edb4bbc785d1a81f6108f451ff642f4df17dfcf94dd6107352bdc0c4d0e34d8a16b3bfb51ffc9b3c353817e8e357c608b5075c173204963606e000000000000000000000000000000000b3cc99db523b3647937b694fc23281a74010079351b2c7d1ae4cc9167917f06c06e627c4ec44af6b09f2886ddf309b800000000000000000000000000000000001e2681dd123994627adc92e6ddd3ffb006521d8bb03040fe1989e4f709e4797d143cd0bb749de33c8109933c709e970000000000000000000000000000000017df13f532bc9894be932e72c609c0386d32390dee95dda45821bedbc1067043d46007b39b6ade871bd36d39a17dd04d00000000000000000000000000000000162db4d1e956fa5b5f9ef244dbc0c6d27718eca7dcc512d1d7b97bbfd2bd00cce7941d1b9a170da6341891773a729e9ae4e31f5b6629463311b9d3c8333c33c5b2e79761ffff9863acd9d636e1a9586a000000000000000000000000000000000f0e4b606ba0a175bf57d4478aa286640ce4b5507f9f9e354fd96c45443333f6889a93012d663d78956bbfa7c645bb9d000000000000000000000000000000000d85dc4d733f0498fcb10e1e814eb61245203d6c1a46181e5a388fda2680640a1271a68d645f8fb179c0dc3107fb788500000000000000000000000000000000185b02140f6314cb62bd7977042ffaaec41ba8788d356047488004d609ae680c2f0cdc94e59a3cf90b6651298b6a81d000000000000000000000000000000000038ce717d08d367a9f882f2241ae4cc0e8a31418498bf68d05805db2e162d053a10dcff85403dc473598089a78dec27e03f256e58f60307ac1888a1b0b14b56c7435213e271eecc79b4a6f88d102be4c", - "Expected": "0000000000000000000000000000000004cb919a72e67c31b3409c28dca1d57833a5066c240d2889f5bbdd5540ab2a49484c2462b25da197ec8d93dc8f26ea83000000000000000000000000000000000e1ac1dfcfe22ed7ac52c701a7221b542ce72bf59d62cc49f95f8ba64c05060671098d40c83947dd1952494833a19b55000000000000000000000000000000001331f6ed8ea5ec9b9e1a14997c2c9bc9af2ca305b313e2bc5c5bd35308b7b451a362f8ad61d636dbf77d1b2388702d8f00000000000000000000000000000000186b85e656e45cb5ac9a2a2009353e45749b53dcdcdad4f378431a0e4a317652301f834617e14dfac9836c3c11512aca", - "Name": "matter_g2_multiexp_39", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e6292b4d3031fcdeabe62921f0c562606b1ec6139b9c43938971d7851da4945cf69f39652425396ed1b2e70e65b9f55000000000000000000000000000000000e94bc63f3b8944ea6bd7bab811c013fd61303aa7713619faab85a271308bb220e2a94b26f5c7e4136a3d2761dffea610000000000000000000000000000000012313ef65ba41f8e0a57e9b810c13d23241e8430c6ab967a1a9bf5bd6308e89c135e00e789a5610694d146840fbd877300000000000000000000000000000000165ce83af7edc9e701eb57b332597305fedf4b939f3a13a95a0bb3d119c2a9204a4991388f7fb344ec8f15d32cab0eb5eb850f01feb55bb99e4accee0aea8fe6ed0bd29b2ca942ffe09456733aff10ea0000000000000000000000000000000005a88477765bbc8290b7eb137e6de78e62bbd929ca511cf0aa701f926440f21d33bcc6ac8f2ca5de57ee8116c685ba38000000000000000000000000000000000738074a9365c707190f882780b27dbe96179224103392b86c628b601e33b092a03e24a89bb6d1d1024862a9df6fce8d00000000000000000000000000000000188c713945046771bf852155ba412b4222173b6dec8320ffd1c59e9b36943c2c18b0dd3bd551b7b1367dde3e8031201a0000000000000000000000000000000017222294bacd664ec37e9b214407e5325eebe9753b430589de2eea13360783be52a479e2b0e9c5dc4907dd5f06a7fa822b373fd7e5806d227ca1f49ab0a7f8be2b5950906c8974de9f2cb4e13ed20a9a000000000000000000000000000000000c97299d7e18f41e538b91b75e962c3ce4e068202271b40469c58cfc477d7820e90a0e91d647e8ef5fc0cb822daefd29000000000000000000000000000000000bd1e11a3646c499a240bad708f97a49acaeb653aa5bafdcaba41c1c9d32d32c516c94a3db8816e0a43d1b1eceac7243000000000000000000000000000000001223ecf82c4622653ce84460c39afe8a967cbd87a2d75cbee1609161837c15b522480c4731c9e6de9c5c392ef1db18e10000000000000000000000000000000016c5e98d3d17c723548427868e3e6d7ef4bca339e41acef19e0710459bd4732de4a556b22cbb49b823c4ee656fa354f1babde7f3fdf9fba868b5eac61337be0d73517ac3f06c39b4eaceeb27ab6311db000000000000000000000000000000001125735092842142cb5387f1ef8fb69a3535e1f0ccce59661183d3104ec1ef79dd87a7fb36159bc67bd73ad403b46c1500000000000000000000000000000000162caf579539574199d56f4e756f1532c66278a55b4f67f4f4090368260f46023543a8a18d49e8c5783cb65f93d750480000000000000000000000000000000003accbc87996a220a625e36d5cdf05d8c16fb353068ad819f94ba8223cdf6436f8d822719153bdba620a07c5dd955fe5000000000000000000000000000000000b53c8a4b62466c998327e0c5ad65818ea383650bf0977d98a8a94fa9653fba276f7781af9f5a4e99052ee3ae65c283d5ba1635cf82b25b2d7e466717f5716c33f5f3e826bdedf19dbc1d95ff0c8052e000000000000000000000000000000001264608a59c0ee9a26568cdcea8801cc8cf6616773bcb0971234b2d987563270c7b2291fa035c8f2069ac99e16c68fc0000000000000000000000000000000000e839d8d982d6663ca4552527f4fcab6ad5e0a444e7b5921055c774871601d342a151133ae15bc76c023b7ea643182ba0000000000000000000000000000000012ffd0696b7e29b305412fb840c596b66b77ac2eed936fdbe0562541e4de6b3166a9991dbdfa0f79b78b4b86f11291de000000000000000000000000000000001777ece357f82d7303aa816237a0dbd3a1398574f4061dd2fbf6b32af38a65abf5ec9bc53bb8ede932db9cfa0842d53a1a0a832e5bbdf897553c1aed35fab43aa3f4510c1782115e14e5d56229de2dff0000000000000000000000000000000002b41743325db9550c3a84af80bc20c54b8b0b685d7f84d05d14dcabed2f450b91675aa8c5c650eb81151bcfbf1603b4000000000000000000000000000000000f3d3e69d475fe1d4259f18f193cd84a90b91589a6502588106f0a577d1c1dc4b2feeec20a4fc30b3e403d6ca9e03894000000000000000000000000000000000c10e2bd1335363fe958eb50981b99bfbadfd1c414830857b5257bc8fa6e26b50989d9adb5b3a2fa610b3151f8754309000000000000000000000000000000000008c825371319f4ebd684f76b567c4e9a389dce96068c101568dc8cafcc10896e3c20202b591a344d9a1c1be02310be9b75e0582e9ad7aa4a02ed5ffa22e55570c9f20e6a24e2186e8a2a2f838fa45300000000000000000000000000000000101d3f92fe64af93468229608007f50e3406719572acf265fb8b2a7051525a9cb67cf2e46fc8e098cf081e73f3b20c770000000000000000000000000000000017b1422f8208c2521e3896820b22a65bb2a9b47d7fdcd2ce57196123c1ce43c1db6d00f236d7582795d00ef33ad6d585000000000000000000000000000000000e261500a9c64f5ae107d6ccb57fa9151f5321ef4e80f0e271515f1eaaa5e3714c59bf97b39acca41b15d90c0505ba9a000000000000000000000000000000000c08c955b6df18444ce3726711d29c2088721fa0aa6e317c52a05f73ec7171ef8bd61047174c74afa1dea804c68a28e33b7252f8f3cc6341d490c5c4464bb36e012f1b05057f405aa907ebb2c983f646000000000000000000000000000000000985cdfb3934e0484805a1965984028d6c459654a3eea6ef66e867dfc737e1bbcd92e31020d5a4ddb7f8091cae2371f8000000000000000000000000000000001998c5682209153a261bf981e16bf1f7a6f8e5e566c1b0f975253ea62439e5b36c5e5060751f21941edf0d348bafd18a000000000000000000000000000000000c8822c1d6412bc45fea05faef33c65d5a6dd13aacf1279b9cfda2a2ee34df3146d45e3434ce8e5f242e9cf7d3ac27180000000000000000000000000000000019191b51d6664a3047aeb5590df2939b2cbb115ded70fafc2de4c2e8c2a955a957375314081a8838bf89d5a140b7b915f10427f6e461e7b63b781e116a4d5136ddc79ff86b71fa754f00c797c035412b00000000000000000000000000000000156fcfffbf01ff3c8a97e7bd99e59327d38c6f7f1083d068ae158d1901808b3c9ac96f95c2bcbdf5f74b36dd8ce58d7d0000000000000000000000000000000014c64256d1cce124c01fa727482caf8ccf007e4ae00e5277d984f31a11ce584e7633565c61d47bc8accdf7c28bb266b200000000000000000000000000000000052dc9f7fce4859c852d3d9e1e77bb7887ffd35d4d550726632acab3d4303ecf8b3ec7f4114dbd590ac20d748570899f0000000000000000000000000000000017abd1e5dad7ee06116a8131c05c9b48defaa92efc636ee34a2970d701c02b6be0345a58cd8749e582ebd105c02f10a06440c89f8b10ce15806938b7ad65ece194d2fa3cc8d7d5591bc1d52d010896af0000000000000000000000000000000018ce0fb077dfefd57f7943d432e12dc9bf92dfaa30f8341397ff8906b1abdf0c02b599edf85ba1e5bb6287aadc72d7a50000000000000000000000000000000019e5e9e3b0632ec10a26b7c1ec40248a9a8b230806c38aa24e47489a8aee5abb5450f6e5679e3f13c6ec7a79560689050000000000000000000000000000000006e257a74f45142817ea8044f403e98c99db8355d626c59e1d11c6859eb0dd1dc8af389f07562259c1f85411be6cbfe2000000000000000000000000000000000f463e345b004b1364894c6e8ab5d35bfbdf6b7544a576ed6b5c5398ca2074f67e2d80af1ff5b721fc126d3afadff1ef43f1bb26469b778edd10127e634fed4d749e25b41d8eba86eff2c068c33e714f00000000000000000000000000000000174231581338fc8c461c981d4949d18f5b753d27184ffb41568f11e178a271bfc69f8c73f2daed0fdbe5bdc7fdf8ef56000000000000000000000000000000001532474399d6a73501801e5f3fbfc6f13bdaff7a3ea7634568fe82745752ee15af23b16809be18788d295e044e29c05a000000000000000000000000000000000912eaef94ab1f3b3257b26c5e8bbe3f99eaceb8c7ae8da577ef98e24f3308abe6e6005ff674a2af01b4242f8ff87108000000000000000000000000000000001925cd635d0ce770f4925a3117721e96c316dd96708b096901ee04ce02e7b357428e4364cd488eeedf76352a26cc1d10a40251ec7a7e9f7cc29948b122010d9745752df3f4a9c67427a8b58122ad4e7e0000000000000000000000000000000005c4a7f26ef0416f34750badcbbb3bce075606435ee7f69b3589e21e37491f0b4a7a98c825ec222848f5e29618828258000000000000000000000000000000000381c5f6511c9f06ea1a76ca84adab4a26a3cde13e0825b3d81899d6ad3191628894d0f57787f854aeb9e4c57fd15d32000000000000000000000000000000000bd706a5b5ef0d4ee1b679a0af90c217ddf9242b7c39523c39657962952dc14e5e07d02154e05693bad08bfb24a2b19a0000000000000000000000000000000009f28a84aa5bd39eeb09f13fc8770fa7e2e053b6f5d7e6021da77f48b9c3807ad917ac671de88b28dd343c2847c5e8eee03e5eb477506c397bc1a5204b30872085a36b65b7a8df3e0e187f3022736329000000000000000000000000000000000a8ff1b15ddcc3684b4d4ecfb53473497feb8a04660350ab84e5719fdb0618d61acbb555174b0900b32341154eb7bec9000000000000000000000000000000001464d21df798c0242ac6aaaf3c579eb66eb8cd53eb1e5ab2727298ca61ea8ca4c7cf815bf5c9f94c2b76bf659a4e2da50000000000000000000000000000000003a25752a4360c84e9353b7f1ce74d5106cbd637ec5ecb03dd0752660fe5c7622fe2d0475a4db98f785307c6961f14b000000000000000000000000000000000163601a86f02900d214ff8fbd041934189503438c557138b6ebaca8ce3c109af50ac28074223fc81d6476a3a99559ac565cb04110bbfcdf00616c2826e253f61cf955756e94dffcbb6001f59ae4a93c100000000000000000000000000000000189597e6d618a20ecf9a87cc70b3e0eee69ffa4dba75056ebae93cfc3c2ebb368532b17d9f6c06f09e44d9f101397b2d00000000000000000000000000000000086ba610e490588e9385c8b6944c2bad1eb03058e927fb2f9740dbefb779bdf669a51af88b45985e8345b8cb168c13ec000000000000000000000000000000000db8b9cdd4a9bcfc9f7de144da0b33981e4dd53744cd260c4bf045d643a4ef5f25aa19edab7be0c7f8f5ab74a4b7f1820000000000000000000000000000000010198384a646807b16e2ed9186aed99ca3197b05964dd0348086f446d3ebb847907624f4e02f71a1e866d17a125e07e93ce1bb7cf7d7a55f0624bf5c4c35327b178923d88be748a9b079720c27b500e6000000000000000000000000000000000a293f07dc3f0da0da4bee671951175a4480a719d44cad3d627878ad2f17596f0dfbd6f43acc7a1f9857c5d1f453e5d5000000000000000000000000000000000be6382cc7a00d590f2aada3b4b75f01f8538caad2ade90227ec71e5661ae353e68789807a13f28b23b17dc0dafc19b70000000000000000000000000000000015a9ad5a6f1a511ffe1891ce260ce442996fe4d8515ca593e3e869cab9b18af57956b1daa43aec98a0281143b0c319fb000000000000000000000000000000001807a4ddb73a9aee58b54bab2b878bea8429cdc91384c8fa533a8c9d15c966350e892bdfce16d37a4048a763cbf25d71e2b4c64b363efef0c5525b0337bf407879755f060af451075f4345dea7e681a30000000000000000000000000000000015aa6b865796f88ffe770bf25612ad27942213131c566a446dc149fcc70a018230f1cc8b20461ba2c55300fd27930bb0000000000000000000000000000000000c39c4f229b23c0f65ed720d655121eab50f695864959a2aa49771b848730494d14597eb85ba35743f64eda897f95917000000000000000000000000000000000ad44cafa754f06e45dfab801998c40e5a9f56e4add5c8add1d7ed9e05d12459f2efe3f3367cbcd161f524c714f7782b000000000000000000000000000000001437b1f1a1399ce2a860f7c6517b14a2db264b2602c1c57b8eb04e165205842b483497e98e6b6f8a62e25ab8b0e722f04c85e47ebe2c26e0aa25661d3353b5d88c632182aaecb35303d8d47f01308a0d", - "Expected": "00000000000000000000000000000000077b81fa5997de07738e1b34d8e17ef4a9bde516577a4290253cc759ceaae745e10a457204b9ed0069942e0b487d106e0000000000000000000000000000000015e79be67a752a46dd0605e9d07d738c5732b2b605457ce056deaa1f7093b0bdc91b4c81c4c5462a51bc713a7fbb86c3000000000000000000000000000000000cfd2e6043263bda2b97798e1a7dcb24c63aa7197f2749f92524329e97f93dcb56429d82c1d63c067d7ceb38e6c65b5a00000000000000000000000000000000026f352d2f93e6407c59d58742dbd91ced464a3746dc1ad9059e6bb9c146dc1e74235bd54b1d90bb3399865cd3102f3a", - "Name": "matter_g2_multiexp_40", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001387fb972f997ed0cb97a5ccdaa759dcc3c2c7f4f15e5cc4fe74685e42cba75e778772d795847b45f274d32cd4960de600000000000000000000000000000000150b1ad31a3d434c1cbef877fde2e105d4a047dc34e3889d21544c2143e7b41b8e0024443a774bd1e09438293860a43f00000000000000000000000000000000065033cee91f5c4d429a074be3d2a8b001892455a11dc708ea73c0082bedb1cb8e8b567a6ea68a1296ad2b80e4b5b08f0000000000000000000000000000000001991ff6fb57e8cbf9d228f1a99697f785261ebce9d3c1f592389fc860b8d7a069896dd48debb8cbe0c43175cd2ecfff5bc589e7d89994400c511789cbcaea19b077e0b02d625e549bc6f2673ce40128000000000000000000000000000000000a0fa2d39d868737b9a0526296335256ab4894cc58ffd80bc6334e80d1314bdf017c8226b41ea135f6adefd07650ca1c0000000000000000000000000000000004334f7985211061dedc794ee8931ded12acd39d7e6a6ef44a749118d19ce8204d07935fe62fb2a8ea4f68f99d7c5f5d0000000000000000000000000000000018850a3fc8c851a06781511faaded1ce0752e7ef66da82c2464eccdf78c32fae306da3cfedaf76dad371cfbe012f2bee000000000000000000000000000000001296ca0b0e368429b122537b096fac77d6367988956a7f6cf70c7193b7033ce42fa0cccb8b84b9c78b16a68fd5f4c14c2c3d2a0cba111642a6354c117d494be805cad5b5c486bc47906a2d37a9cd9f850000000000000000000000000000000019deb7de7fa5254fdf5ef34fa616651ec70548187fb0bfae9f512e0bfe1f662783f06a9a99e434ced84229deddab9d240000000000000000000000000000000009c199ef916e6f6fe0677ab07beeff221a5687fa8da3ed3ad99a950b7f27159f857d1b561006bfffab551d240b764fb300000000000000000000000000000000148a211fb58b38072cf7c417c70d3ef92e9cbe22b31b2b626198add01dbe1ccfec32d333abf42140b9316312ac48aaa2000000000000000000000000000000000b551b57045365d842133e46814d5d0084248904960f8d2fb28e9623660bcee658582928703f86261cd70e95cd20cf3a530ff74626657262fb49460b2c6981155871f2eb5562581a74f968233c3cbe3d00000000000000000000000000000000185959a297a8f434cb9529a1f7bf9009fc1af3d09efb0a9dce1b9e7d30699da64e4b1d32cdb05b068621db092c1eb59c00000000000000000000000000000000106ef21e9031d108364e93ae4b5d21b0d6d78c2e86e0f8a7af27ed3d38dba0192954e8c716665333e5dcf21387d3f2b1000000000000000000000000000000000185d21efd7d613c409b6ddaa66eed70c235440974b2a9154f3711e3969061461f8824b4547c65e9db09ce875512ca2b0000000000000000000000000000000001aa46b22451afb12962bec5c6309feeb4acefdf3c98c1ea14275409b7111aacf7c92a8e024d01d4dcbfb1c91fc445a1d182ac912b005e90ab81d4f2a906da8309a69576a8afaa160fad2540ec049913000000000000000000000000000000000557370d81bc3da4c50980106b8e65ca2edc757a475194cef201c9edc0f50363cbebcf2750acab0b67e1020daf5660e7000000000000000000000000000000000462f1c1379be9bfed97a1a83a00428de63eadb6360393ba162af3762a99d7eae8549d0cee218e469e4997ada7b35cc00000000000000000000000000000000008aa5ead309fc703f6de980dd43c294530cc2b38b94d5281e9cd9b0d09f82f747a7107b700f1437f3abe36c01bcfed1b0000000000000000000000000000000014110a19d574f26e11e2163a981c3388c04854c5693e9033a474f1020d5f980666d84c60370950734c46663e194bf0ec42a002a460b51429e25f85ec4abaa580ac1a14315b1627bd52349b7b81a641d60000000000000000000000000000000015beff8cb3c79098bc73dc1ea4b240a4e0d094b3dbbd51592df6adc9c9847beb436ec83df6c55666e296fa843298446a000000000000000000000000000000000943aca2a6e57e9897ec764ee2911d9ff0a59d9e903c70a8494340cef2143895e79d3e6c03af2d6461ca199dfbd0ca0d000000000000000000000000000000000b812ba87c4989af07af44f3dfa87de119fea28ad598cb8e52247cf41bb8bd384c0d8913fc82e4cc2878065e797cc581000000000000000000000000000000000410ed148d1e354653f9d9d17c50026957fb03fec64964f2bee5eeea966b430e77f7b3538d9f4700a673fa07d0daac6b7a650dd3765032ac139d1b54ec7a5457c9e3caefa6af45d198433e5949d149ad000000000000000000000000000000000de0a9bbd63c59767938b555c7f9284d0885ca23019818c213a7d4f1594b028965da871cc5818240d155c05c69e4e25400000000000000000000000000000000079dee5649cc67700e9338799a9810d352a5c68098d0676e42e00bac31f37513944dcf47408288cb7f1cba121506a10500000000000000000000000000000000101a650e84352aaf3817b400da0aff40907aae3d2fcf16739f8ee8d5bfc62c2a0dd518201701932728a41134ea3f6278000000000000000000000000000000000f1f9dcc0b55d0ed327f667cebc052c4b6116fde5e3076dd6e447c3214d4c8847885be9547f95f341c42e7c7fa7e2c71bbedc44d54349cff199befba9531dd4120a51e2b830a3e356e68cff31bbe365b00000000000000000000000000000000148f706b4c93e739324e5db40d42025535cd33a32bb3f211add618c0e2022068384a5612da67150746896a2813a664e80000000000000000000000000000000007204ebcef495ca8232078fbf1539a4b46e89506a09dc008da457dee2792acafb6baac4f6cef2de15cbeb48bfd12bfd6000000000000000000000000000000000bf8900e48a4a56b653b1e02c3b9a7d81c2045dbf6297f1ac2acd69d1bf9e06480ea917e3a616243c3a30235abbc426f0000000000000000000000000000000005ebe0ddf4cd1aee76d0b3d03eab754664c8b36fb20ab1060900909e0e0a4abdb45bf74a0b1d40fece9bf73360f580bcbef3956ac71bfe97029b8e3f85923c2fdf9cf1ea6582b68d5a4eabc6b044c80d0000000000000000000000000000000007824d1c48bb2cc0f406e356f6e52b66392f6203f49dca7ce03ae6302ce3e8055d071cd812f97481acc654b318d6cae2000000000000000000000000000000000ae89f9eb1abe452efb7ca48f8f939d835f9a79e05211ed9f4abee06b93e34b17d920ddbca3d8bf18b96c3705c1a064500000000000000000000000000000000119ac787a7f3e9b7ee34070aac1a769430eaa8cc838f1752b573ac7f3c02a9f490de9600c856a55448598b149f5392e300000000000000000000000000000000193a3655a80e6e0b1278730600fd4f645d54947d193484131176b890ac197702333ea847317568230ad8af1280864096392f5b4291fbb18a93248e830b08fadbaad6434040c02b45cade73b77f22c2bc0000000000000000000000000000000012f66629836f0f57bdfd9bdeb2c9b7d6d5dc55c586e15d76aaa04aef06722bc8ca156fd1295b3063d738a85b3e8746d900000000000000000000000000000000097825c5db7289b1b9e640d19ecaaa81ee59e5b9884713f6d312604d8ac367634a264c316d73a9cf63358c8fb15f8c5700000000000000000000000000000000181133d027b97d8e2bef308a93b7ea2a35824dc7d01a3ed2f404fbe12ba3b3e51d94ec86cadf3da7dc9ecbaa23b411cc000000000000000000000000000000000a28a609d0bb015e375e74c087ce426dd3c20fbd8b374d3817c626faa81469cfd11a2a4e418a44f4d7ca621d0564bc4920a96f963375d7a294b584f2da699a6a00eb5781f46830987346cf4fe922a2f6000000000000000000000000000000000feca6f7e3cb286090fa3df9c5ebd10c06192fe14af58d46b827acf48fbd462f3f76d9d20670803946028437410ea52800000000000000000000000000000000183dc7085483bd05c27691c25588e33296fb610bddaac253af5b2262db38091650c1c3185d71a69d1a63770f95f381d7000000000000000000000000000000000189f9b9ea528bc2377ca3354fccf440fee059f5732dfdac320fb58541e74e444dbdcdc008c7b47681c05502f0b302f5000000000000000000000000000000000906162085e0e299a07e41b9d62668d4810b97d4be317bf376da537de7adb06de011f5f40af834593761b774771a80e4115cb4646c8996239f4fdda8c27a335361f0a19550d6eb0225c008408c47258800000000000000000000000000000000030cc52d7901d0360d10f344cecc8325412788cc30a912d5de3fa9bdab18db44efea235c5d34bab526f3b8ecee2cbb8d000000000000000000000000000000000cda35f561c19ebd85a445ce8bb1618b446c7013c07606ce58e0b5627a5c9e7cb200e2b8ee12a0564730279e75b469b500000000000000000000000000000000055ad0655a96f6dab5a432e7d2fef57a6a11113070444089df23b4b911e0994b90aaaaa2c62d06756f4704fa218f7c350000000000000000000000000000000011d22438d7c162d34802a664c254abaae07659902e1f1bfc2bdffa6c17eb11bff5276474cc3cec9507e28685f1c21bb0c8a8d98c93c392aefb64ce0c7ea455ba14c48bfbad0e3dc38d43abbc3276caab0000000000000000000000000000000001d04065373ce5d1ce47e00476f07708bb028040edb9ae7e8e00e2c6c460e1ab8b730ff510a25a3c8114c1753b7bf1ca00000000000000000000000000000000001c87217f150694a84a4e5aba8d188ebf7224e76b078dcaba4a91de6b4ab317966ce1a9267a5a27ce556c3386b086620000000000000000000000000000000003c8422590826e0999e7ae3ecba84edaed20fd7f1eba02b9daf1c46c2aec74d5fe63319047d37f5115f243ae0ddd4ffb00000000000000000000000000000000136ae093c3bd55ddaffc2494f3ba8176947cdf2f1ae408e7e786b23b6a65ba8c4131c83cd890386ba531b8637b3b042c8221622734dc6ccf6c7b84b387a3dfecafe187dab70ba373b4416ce3c505bef2000000000000000000000000000000000d09b92a559b8efe5224184fb4f43779d0b8c8f23587f4f74e2fc6fb1f94e8d2e0d591eb0702cf51a9eb402e79b46a0a0000000000000000000000000000000014ec2e4702f1ee1074cd1ad29791cf4903357e62570d16ac80c5e8ff73b255ee03a5ba070091cb2f984b2139de06a97d000000000000000000000000000000000d22fceaa48193756ce7331952a2d9a8057b67bede729e07cf8422bfc79f9ed2aeb99a9227af256deee9f8a6f227faba0000000000000000000000000000000015d9322c3a5a7ca404259c4cc7cb93dc3d46dd8dd9475756d2ce6fea527642f9230c7e94a804ecb0b4adec7963fa9cdcd3d1f427a25f5df025fa71244cb92dda9391d65b04756c41de0f67ea072c375d000000000000000000000000000000000e16fee11affc6714c7fc8fc5e7cce44d8afe645861dd2f0b8e58aa93d4f0de9b7e73020a1537bfbb0e2c8327c4aae03000000000000000000000000000000000b7745a4aaa8ab4593daa61e375d55f9043fbc7385ff229889fca514562168a4e769c5eeef4d564b41cff28b4efdb7bf0000000000000000000000000000000017f6c5b1fb00746b50ee4c7c743ae57fae2742617e5565241d012a0ef6067d9ce59be749a99886ce9836b648525d2e92000000000000000000000000000000000a3be81720e80f6aa0570c89613c78efe95d87ccb374e7f77065800590bc71d23ae097516ae1e97b498cd233221cf717b55c943fd9b11f2fb8a89f6c08a6eabe9434062354d845f1ac740e6043443f8b0000000000000000000000000000000008080a7d91caaf2470f9632575b43990a9523219d75994f1944979ed5b650be1e3c93eceeafb0875f66a40651f4c6dfc0000000000000000000000000000000007a19c4a6340e39230a33b12fe63e47bb0d1378420ec9e439f216699e512e4d70571a1670eaa6b60a5c899ac63360a250000000000000000000000000000000016898d22b2c123003480e3a01965a72de94cdfa39b20898c49e451dcf6a4727a1ebd629172aa1a1aa6897916cea192b4000000000000000000000000000000001217a373c78de9d3005690023b9e56bbed3073f13ca2408a27a3480578d8013fb9d3ee5cda95c3cdd091a5cc68d928da7b0c1d54e51b8572256aeb72bb032a5011a3e8ec5ad7e8b6e0397b9f6fc64c9f", - "Expected": "0000000000000000000000000000000005829c932c80baa420602bf841ad9bb24fa25c61f33f5d88693207b81271c94eef54bb524aa830fdad8caf8c082bd4990000000000000000000000000000000000b8d184316c2471ec6875641ea83de4f9b7227041922415b38b07a0704d01f2585ec2701bb4ae0bf6a0c0522efc0c630000000000000000000000000000000001dd81e075620914254b38ca5a7287eb56f2f31f6f8fe02fa51488d45c7f4609bcf49972d0ae5ded76eed5a4c096939d0000000000000000000000000000000008067feba36999b58342ac54e48b0fe28245f8ac2498b60093082822d19854df5c3168dcd55ccb6b2cb397b77e712333", - "Name": "matter_g2_multiexp_41", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016ed84856b9f41be9bc6c025a9b79e2968e2ee6bbc27608093256c541096e2c9eda1159e6dcdaefe783aa59d52f28ee90000000000000000000000000000000014aabafdfe8c7369f93d5472a9c6c4d426e4b02c943488be993d04ed24aef5477f6d455f82b4af78381b8bd16f42b56f000000000000000000000000000000000af34789c6c923103633e5b1b9fb447b671ab05265c16488ca7224e49db21973487a5d3de4de40b9d8a97ac9b1966619000000000000000000000000000000001123a6601c5351a586f27f8264d4227f5e1df868a03e0c3df5c148cb523cdd178f96fbe52464fdab210564dfc22b29536f082a5ffb8baa38ffd684a4a70114343a1e723bfcbfeb57d0a85ad5e592d7410000000000000000000000000000000011b82d78cd9b53b8e7e5c14a7371f34f08546896bd59d1e7d8be15d21742180aacdd01b0d08da2cb24873ce75e166bd500000000000000000000000000000000161ae0d724085a6e801edf73443cca87995c2d6b37e962db5719f4c480cb830e379fa778fd2f29e75173e1c31daccaee000000000000000000000000000000000a2c2b89d00b7d19f2b0530889905c30cecbd4ed0b56ca82208d666e7576c32a6e90cf867ad87f19e4fd367a10c449a2000000000000000000000000000000000b65c0226743b573dad7ff25bf1885e3dec686cfd5da2862ab300fde4fc8fa9b587d0f2d11ebe1f6a6770bcaf2588f8f5160286a6d23c30595809dab6ee6523d7d235114d1b295087e024b4f6ffc80e50000000000000000000000000000000012d4f299998aa897db9e3194244fdd1dfb95225e3271383b5cc296bbc51c4e1af52e849d8244f82421cd198158918d8900000000000000000000000000000000110638a2f7cdb7104de8fffe29be32610063bc656e13168921501e1614f282bdc9fccff4eb3c479a42b240a2c8014864000000000000000000000000000000000b0adbcbaedbedd376efd20a417bcce562b87b7449cac1e90d44eb05930e6f558b35ef755457305da012a231b5675bc2000000000000000000000000000000000db6fa926c7e02f633730569732fd9239bbacf2042599e79a4bee76619872901c6f4ec4d4fbf3f84143a0d17b167130ebbca29b94b6583d46753473143d13a7aadb0b18d6d35d7423b8a004991fa1ce500000000000000000000000000000000166578f3087772545c0f47fe0b3efe32874d26463e4f262be65a3bb6b0fad7d0f779808f69362f3fe63c72f24ed03d70000000000000000000000000000000000a8e61e8193228fa1825cf14e94f68a5eecece9afb48b44871c5ad62510ee1fc4e9c60d5f2529b8685e6aa13ec91979b0000000000000000000000000000000008d25d81bc4bc92508c8cade33c305c11d71a06bd46f184b05dc406f0939f0e0967b02f15b4f7f6984c9fba0644ca8e800000000000000000000000000000000113660a7d2152346500a1578641aad4dac2919ce63d01d8ffa6dad72f524c888fc2e9d2876859859e47d8e884f170f86607c80069dab2a16e39370de32df20534aca46565cf573159a93c64f1f0c4a1a00000000000000000000000000000000160529ff217934c85cbaa8b347151539e252dbb502c015e8e45c128df2b8a737866737d5cf0eca6f76e4a16790cd02a200000000000000000000000000000000127f7b0e4f9351836db9c204386a199293955471dbcd7b4ee9186f0434b46dcacd1edc02fb46b4c377c4e62cec10cd6700000000000000000000000000000000094abac17b11600d7447f7ad0f21d98c14e439c4a4a6572b00c90e14d9fc54e85045d0576f74b054d384179afc0a70c80000000000000000000000000000000017165c32410a498add8e1dd55ae43f94be234ba3859fc6b4816d7436746add313f42b1fb49e0cb6c4b7341f0acd09db841c1f256e866d218b3ec20c132446945177d518573ae3f0e739ebcc8821bfbc700000000000000000000000000000000060e503ee1c5d3eae4bc0eb30fd86303a5c48c10cc7b4736d17b8774c78a8c97ee05b40d366b2cc9bc7781b1e4a192f200000000000000000000000000000000034e7012414edfc6a8f7b2c6049236b6fb77eb94b05d55b218851fc1e553514e6ad388fac08a24c33bea63ddabdfd8720000000000000000000000000000000004c832477a90683d417a00a698b69c643d6dbf82f5afbb83eb3946f8098d80de6f2d457c0a06d0051315f06e93b5e13b00000000000000000000000000000000048c3339996948974f2bac14d8a6b8430897644ec8e9cff9eb369557003aa2827a4f3fc3444c4df73663ebc9325ff317c72a47e2267010c532d676ee3c3ebfb2be2b7569f6f7a22f76733d7773ed383c00000000000000000000000000000000082466944ee7c62788b6fa77816094ea623d03c7aa2af249cfbfbf78eed26a76cff8c23c2295aac7ee1ef8dc84630003000000000000000000000000000000000a8f88adecc3f50d8eb329492f2c031e722f36627cb3b21415781156ef44954c5b8529ceed5978a37ae1248909d38b5d000000000000000000000000000000000e08f628aa014152b50a85bb6eb947d53c596d82c0d03594ed3b64c486b8630c880adf43fb1575b02e4eb8174a04034c000000000000000000000000000000000776844f28958d3e12a5c163dbd039e50df44b1c6215429381790175a609a339621475a5b9a06c3276c9177d2dd2b576c52f48e84a68d99124e678dabaf376c956dbe9603974283a9efc7c27e830e9590000000000000000000000000000000004477f153c0510d8e50bfdc2db69182c05d5ae9b94bb1880de239733e380e03d50001378432312b24b5bf0952c38396c0000000000000000000000000000000016663990dbe529a5658f2b3044bbd390ad430adaeffbd5306f758d86bd5422391bfa1d21e88c63300faad55e6a2d1d3200000000000000000000000000000000188f701658558033ce2c41101a611f74ad6d3cd075c195476bd2cd59a1a9dcfe937020737250fe418b4de435f8b3a0380000000000000000000000000000000013f8d3625309767841603329f56686a99e196d697802cfcf31f8b48f9c76f77a321276a0158a22b94e91d6907f6ff451e4fe662495bffd8ace4c1ddb39e612b361bf90a0f1bdf6c7fde2bcf63df1bbd2000000000000000000000000000000000f184d22f3c0431b031ee0ee7ae9598ffb511a2a56f5c9f15c9a4b0c53af2a10d22a311805786e303e234239326dd74b000000000000000000000000000000001062725b8c576e79e314f6a56ef9c41f05a65d7d0d57d8414e2ae9cb1a520b16ede7e418d3a9413c9c1660dd7508d5860000000000000000000000000000000012ef02fbe96f9a191804b6c4a0b65b6024e3e2b1f8cff986f5a950cde9a32ad50d4f7a72804b2d18b93250a63a7ae97800000000000000000000000000000000000b3b0333d61fc46653a7172f5a813d13ff5a48056f9689c78c4b18b8aa3afaeb7cec305d98dd600786351338a2185a651e67e96f64b80f4978fdc1cac90be538774e34c2f619f8b8e60cd2aa20f2690000000000000000000000000000000010c91e1dda48dc528f618f01abbe01db1a7b6dcb0d47b83c7b7db3331f7156f7b2d0f081458241467b0078935a7b4a4c0000000000000000000000000000000006f87f782979d2adc02e65b56a4906e50430cb4e0913636e9aa0364535c9d7ecd3b9433358e00caa8e90e84b7705bdfe0000000000000000000000000000000004635089c7706cfdb5a22ef643d1a9a5021847646ef01ea559d1b655299b65cd76a73b04149adbac612e7aa756cf30060000000000000000000000000000000002d83d82bc9fd66c558e00547a8c25633899584c9b855195c00eb3c8742d22c601982f244a03f8e0c5c21caee24405481a6ecd3db89a7f07344b5728efffd35a11f7380c740669f746fdf565905a1ca0000000000000000000000000000000000848f10eeba8ef9c7fd0e679767f6b6a2392922092916da8f13573661f84ec97c65717e55c65526cedd59dc1e096f0840000000000000000000000000000000013781974518487de12661bedfca5fe72205c51cab461b5757ff14f319d081e7845cf8e099892ea85470039713e8e48cd0000000000000000000000000000000004cc1a27d1aa88484fed40ceef72e6bd201e5ee276b5ec27624286dee112ece767b37c6f1f7846d71cc0f4042f04dc170000000000000000000000000000000004f7335d6a1463976d9fd86e2baa45d08ec65059b14449ebe4aae99971c5666cdc6e40cf0510ae99dbce97ae8b4598067db5ef4c1c174c2e5ffe5555f54f4e845c463bb5105381fb39eddc01103b1bf70000000000000000000000000000000003c1b1e0848bbe37e62f1ebacef1a574400d5048f1e09d935af2052da29140dc4074175e4d6ceb7c2c071331b2f3d1d3000000000000000000000000000000000e1c84d6b20553ddc5ab09049ec488ea2839c5818e31455a7b231cd0455e2945aefcbdc6c1979821a80bb4f77d46e91e00000000000000000000000000000000199ebb31e8800395a9c2e103c9340444c97004186929b52de33cb8d9396e7ab8d5af3fe6035d4463701ea41e341f577300000000000000000000000000000000081b3882bfdf83e67d2dc42b211069a4e93c0f173263f9f20579128391e7f2de70335df949b9c0e9b834b6e574f2f8cc14018f14c50d40d3324952ec22ed247c13c4cf10eacd32c3671757bd12b041e60000000000000000000000000000000018aa45c6b3898a5fa618f87f9a08a7234c1b94fbe38e2297a1f9c7a2e9de0ed83023deebd56560b1928c012c14dd7a860000000000000000000000000000000009ab80da6c519aee8aa1fa68c35bd0fac78b55f88d861e8fcd445f629054325d63cc4241f61e5596dad0d54c94511e4c00000000000000000000000000000000105f8253f37f5538a2c25587fd33ea61fdc744a7cdf4ff23a55e2c66a39040d4de5eeacb7e11c0d2a483d59e7c3186aa000000000000000000000000000000000f6b10cd6522a1e34c87c702f58a07858cb753d67da9625155bd433020775351a9ec4ff879f91a43f63be1c969afe675ed4a28dc3acaf2220ba56d026b292a7d017bcbe358dedc57556cf638517bbb14000000000000000000000000000000001618dd5de43a6bcde91a6a03fcd88fe59d1c8c51d3d85cd44a1920dabd2608a0b17a987b76eb8f5b20c7f1dc0abb383e00000000000000000000000000000000198034b7ab8fb8ff267a52a9423da95bc587eef8684f18639df5db44e50bae7fdea5c5e5ef37ff14937f86cc948a34e500000000000000000000000000000000106d1f017da463176bdf55e3ada78ce70da4486be42dd0095e3a8a0f6e59ed503324565b717b45ee38d90dd3ad13c10600000000000000000000000000000000112d425765fa2fc28486b95e49db63346188fc5a6bd0b7dffa4430dc82703eb44d98d726edfa4a275aa5db5028d01ef530fb17a38b7d0888eb02394eed26406bce9e92779251bdbcb432153a550c0850000000000000000000000000000000001326581ac1a1a960db1ff2e8b89b1debaae46d1e2d0aa6ffc6c7398f207abb699ac59186ae7222b5cae3abe64cb61c93000000000000000000000000000000000218753594c63ebe5fe503aab4dbe1e944b24138948542c7c43d92ccfeba5854b7bf1bbcf8078d85fb0b8701b8b092fa000000000000000000000000000000000c3ce8c17f75e78a8c9980e9fe125290d377a32ac46411876ef011e169e86e1458ac5e71cb4a446f6c640cceb8d5617300000000000000000000000000000000176966eac1e20586ad2a03b4a1598b4db1d7c66be70b1b22833e4afe0e0b3783572f791ddcd4eb70a88f4acc28b6fc7a980b5873a5d0f78c3b8582581349498fa997fe3c6b1abe0edaed594253359d8700000000000000000000000000000000099ac8430fa411e74082cf3282f9a456d3826a7df4f91ecf621e645a1abc057e1bcfaf9ee73f149bc447cf4230f2f6c90000000000000000000000000000000004e93d7fedc9e2d7423c9e111b4674a2bd83de28dcbbcc54ce4b324c96318a11603fc9ea385f1c02364ab1f6b5458481000000000000000000000000000000000bbb29d70fba5b12fadb02a24bfe3f6a5362c71fe5f964dcd0e01442781d0462a873501029192858027d612a8572e9d30000000000000000000000000000000010daa9960005562ca2d18eaf4b4bf081f194fa824cc77515c81b2c836627f21b732448f367e2cc1830ad0fa4ceb928e1619f5719c320320a3c45dcd6207575e0d8527c458c56d3decf1d12ead8a985a1", - "Expected": "0000000000000000000000000000000002a61fead6801f41f2f27603cf34cfb4b917f2f85cba1f9c684995227653c9dde559e1e8497234fba9b2e4c119cbd9ec000000000000000000000000000000000085f73b8e835a10bcb9312931eb08d916d2b93a1da843fa2f4530cdb26e93b5dc95a555dbe8e50ca465b162661ce1d3000000000000000000000000000000001442fff9019b5476c217ff725ad95c92c17b42471ed7bcc121e8a0506755ec279d4e56d770a322d56f56bc6a6b0a41160000000000000000000000000000000017e7710c4639d51c4a79c5a2791101b52742df202b1827192872f168bd21020bd068160a587fc501782c1301c231a0d3", - "Name": "matter_g2_multiexp_42", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001213b5d5704c454845824994769c8b300676e75bafdeb95202001161aede276ab7967ea7362d38e97ca1484cf9c342fd0000000000000000000000000000000008c7c1fa04bebe5a1fb8678370563db63e7a10b30747c2ddeb4aabd4fc0ec93220d578b8110c6bfe8a3a6ea2820f0db8000000000000000000000000000000000c4061a295120a00de52300ee625ac46566464e6702489467316e8c182ca2168052c50b5962ff47285866c17d213fc8400000000000000000000000000000000086c153169a9ed1aba10a6cbebff4911b37907d6398c441ad47da17988d512d822ee36f5217355b93c9d6dd8dcbc8e0b119d33d32affaadbf6c2b6243bb7b344a971270b488cf887334fcb15de2818cc0000000000000000000000000000000017929edde8f9940826ed739bc9f59099ce76e85950698ab0140784647023f96afa064aa4a49b9728f496515a0a807e5900000000000000000000000000000000198d98f430384c1e7fa9e2403d9c3d2f81873fb7b204378cec95b97e674e10a1a43af97db0488209904469989ce80a0a000000000000000000000000000000000afc9b5138999bcef35613e38bff4f81cf532e00346f5205405470b2424622826c746ddf0369c7bdf77467dcea5cff290000000000000000000000000000000019ccc05724b3e9966bf918f01312c80e8422b697be89365b6ca00eb31b0bd08fae942e90a75bf9da1b3d264e416060f1f1d832b355d7e0ac3653431528ad0a8f6819daaa19292a00c910ff0ff39f46d5000000000000000000000000000000001568e52c2760d895874527d1ac8597730578176bdcfc67aaf69ccda253f6616230811dac59bc27cc1e57b94b5743cb3f000000000000000000000000000000000a4ddeb8b56f105ed5f47a538052f3d38a23c0ceaa2dea241554e6508f82f47d32415ffeeafe5ae5664c936b78e07648000000000000000000000000000000000b3b335a390aa0090bfd6467d6cd02eea1ced347cdce3c9ed85dd46e38e9f2ae9642392c2875a27618ba8f2c555d5b190000000000000000000000000000000012baa4b29d116eec749353b7658af70d4d216189133db707e56068c8483af43ba86583862e6b39df13b88058536861b9e6dcfa50f6129544835b5a4568954264ea68d9e2e5d4370ee31026997a3fbfe90000000000000000000000000000000001888b83ca28c244a6178377b4ee6844dc916e28c3f56312ecc0e29d08e6254dcda39a36ccdc317d1908303db3c028dd000000000000000000000000000000000f4b73d9316fee42d60f8de402a7d07765508b84d8f2c1be1f3f9e802ed7b0c6c5fece3db95d5287225026e73de98ea4000000000000000000000000000000000f1b48122191e1bc421881de831293a80566b9a7f2c9836f7718afb69592d59d2a714cfddf88945b94fac7a50b743eee000000000000000000000000000000000f1c6b052dbd03795433d7ad122473f109484d50245021c8727d252145e7db7dadc015265d1547f9c748409d74f5aa33f7822767391d3b2331e8e1b81c659c6e0262f7355063decedabac9797a84f0f400000000000000000000000000000000011e8613c3a771a177b4b85f0c6f97a53fd7900cc23566aecbf115058d2863189c21be36dd5dd736f6d0ffbe88182b400000000000000000000000000000000017b2c4e8d8aad0a12fd7130789188bb63a08f2b243c8f7700599dd33d7e176f70f2b1818e56540ab3fa507878d96a46e000000000000000000000000000000000e2b5ad5ed3578dfdffa414a4a2142846b1232cd2de468725283e3f92b536d8ede74bacc236993f6f68a16fc6a7828d3000000000000000000000000000000000fdbf06ae4cfedc462f5913bba9bba2b5c86ecd0e298bf27a21317fe74af6ab15014c62cbfb617356548cf808599caf4b1ba1cd6a4a6c433624dec63547119c0d492e3f38afb04e5153d82e400631aef000000000000000000000000000000000b48aebc6525620b99cd83979658a35afa233d17849bd0dcabffcf3b550f875a386b6c0b4ddacf18a23843629072c0150000000000000000000000000000000010432e5abf862d3be10ac5677b9f296ccdcedf1480e45de631b6bfec42f20edf62034f7205f659f11fe5a6aa9d882c7a00000000000000000000000000000000011702a3590e7aedd6948bb94bcc874e0b8d77a18126ed4ba3753dc98953ff941495486c14c6d801c71fca3564ded9910000000000000000000000000000000009faa427c0a7da26c92b451c61f5b5e8804fe032a4cfa014397e430882cbfcff81bb22f9c15a8747ef455773c1ef65b0a41e184bcaa0721caa4114d6393ae2251fed84aef57c7927a170145308bb136700000000000000000000000000000000061a1ee841251bad461f89c52196bebb1cb4463298e88abd62cccd21bbd325ddb33d1306ffedb2734be76c18d80c8dfe000000000000000000000000000000000d05a5ce6372ce34b0bf4b19d8e05aab74abc1cedcc35a2d1d4db38813d1e5c1375d63ca0e8bbf29c510a4319d2aec27000000000000000000000000000000000dfc57aa8de28745b8d28db3769ab5ea26b5115d3e59e51ff19af8ba37efacdccf763ce682cfdc77685705781c3924870000000000000000000000000000000018c17d87411c4f8e0ca51b3eb4c3765d3846e0d1b75574f8e511b2f3e8c5ff53bf7618959ce18dfd9e4c6285e88f094f63cb451d8eb3565274793925a1869ca5a25fb19639449c71a761809f785568de000000000000000000000000000000000a0642094b89dc9c6c7c11c1e57ed542982bd246112884969d424a3e091ec4fd73dd40a5ac116f6c68216fd1e733cdc7000000000000000000000000000000000788c7a63eecd1cbc26ee6b14b09d0a3b7a17a848fc0551d50cb7497bc98287da2d9b898260eb678a8a0f446eef5c6670000000000000000000000000000000017a1298f90022ddff3fbbcca180e3f4da8760218dba595a067287a2473a6e10b93dcd54154cb64b6c078b083b42cd09000000000000000000000000000000000116e999b808dcaea0566c0fbef1807e160612dce91756b2cbcf4883b04a90320a0759bba21b41e6f4d8449b52e52f9a96a2f94d55f784ebfc6b6260327372217d6a5b9637ea5f9afc1a65f99c221c29f00000000000000000000000000000000064c95bc9c0e2be48849a349f16713791c37310f71b5d0613cf0706febeea3a56a0f0f1ac6b504524eba801e8b759f2900000000000000000000000000000000007088d2f41fc7e1147b92a2ee7062b9bec194d3a47eb9985ac1ceeef57e1a006571e7247a13dc95afcf9905be57e2a7000000000000000000000000000000000e6a0770f4315acd9e410fe58395ab8b20a08240a6948b762dfbbad3414bfca0ced4ec9da982bc9b8798b60dde78a96c000000000000000000000000000000000a70b53a6d71c83971167afe329ffacdd417bd7b228766851c3b43701a439f253a8659312db7e83a398142fe19332b527d889a3362f551b88e63463b7f0cc334fab3fdd302b630e419e362ec1eaaeec000000000000000000000000000000000002486eaf9b743d3aa6a1f3e1174c5f213bbf3e3cc0558d63ce40e3c03e1c2f6e8508248bb649aae1bc92f3eb8118a2000000000000000000000000000000000042b03959b40eb0641d39117f7af50dc7ff048697a57b80723aaca164e2dbc647ffe78fea0a6a4c07671f7db6d5b2dfa000000000000000000000000000000000e141eab29f52b9bd0ee44861f154ec1bd30abd715935a7958a19007e789a41cdb0f4b9cf7b3fac0b0d4d77637b510d00000000000000000000000000000000002cc2eaf89cb7a04d425d878a30b5e2e9858ae0b2a2ab28fb28a6db0c7283ad861bb6a92067e969e5721b43466e857db8bdd400ad873cd6ec546bff698171942d536b94e69dfef4bbf316a471d4b45cd000000000000000000000000000000000e0f7595e4c136b4d8bbd1eeb021df7dd2bcf1d9f98e4fa293f7edab635e019af87c138275fefacd806213177af40eca0000000000000000000000000000000005dc209d6c86f1871637998c10490a70371f9e00a68d1363dfaeb62046473dfb4bbd3b18b943439f75c45a1ee7f264a90000000000000000000000000000000003d215567d1e8f504a72658d48fa51374ac77234552c17db4033af780133d8516bb0769678ecb50b8b9eb950c2dd73e80000000000000000000000000000000004d780849b731012e1e5732d5f6d32c659a95c3e1c8f5ef4841fe82afc6f0aa309b1e02dc2554a4a4ee781be2be2149f63b496a64cfd15410192aee9912f869deea5a08eebd6b160667e12fdf23c44510000000000000000000000000000000007ecfb753be501d9f9b7ae7ceaabaa4fcb7b690ee04fa1a711a15dcf67e4422adef64a0f8118f93e67f24a2d1a2bcb36000000000000000000000000000000000a459e403d85972f7132641c05bb842416a7135009ff46b617bf0918e65cbbf33f76b98c10d901936e589bdf5de31ea4000000000000000000000000000000000bc6ec31a3ff92b4fae07cb73ad7bfa8423044048337b0ab9add09bf10fdf190a5f7996d157483d29fb29a681ed585520000000000000000000000000000000004c622e2bc606fefc8bd83c4a32f7353123205a6d3716b581c2c71360e5200ab069f60c256dfcb04b466c53cd61fc94470de38cb4627f53509eadb0918e562c6fa68a4cbdfa9f7578a8aaa8182f5315000000000000000000000000000000000125688e44f593c5f585765f30e9fee5e4f15247cf33ac78ed1744453385f49ac61128e23b1569ea33d74b207a5e72e930000000000000000000000000000000009d77360ea37298fe971569230159967012c4991255fb5337ca6d58cecc3cd44a024a9a044ac98a894cc97dea161844e00000000000000000000000000000000056b2dd9569f0698c732367cfb217af90a3d6dc15e2555ce0aa845616e4067a7fefb304f6525b539555a0a685f0ec5f20000000000000000000000000000000009acb138abacac351e03f7589d4bf29cbd331e93bf538578ca9466b759ea070931c786d35f74fad42261e2df431fd00316732c583e8049a5de38642cebab774d90d5f87601e3599ffc9af692ba532e620000000000000000000000000000000013515b0022ea946a8e679b9c0eac6cd67dbc4efc820f0b3d8984f12b7d154c0632a8d7207747284d49c498c79b6bb5c60000000000000000000000000000000004d6765ec6aa8744225c1e652ccddccc91fff7fa8182931c8648b3d8bd33b2177a9af03b2906da02bf117bea59aed3040000000000000000000000000000000006f1d858c4b223552f0aee466cff35d14b3ac6da35b8f482417e8f597514b065be315aec6662ea5c7784d3a9e2184090000000000000000000000000000000000345eaf0d72b9c11fe72261a2fddea318a8dab92a67ccb9438c11e61fd298a333cc42084d4ca127e09792e346cfe0f004a037e7562adfbad6b1ac48b8e4b6f277a788ea2f4416ed2900ed2791f09bc2400000000000000000000000000000000029ad10ed6d6d5bb591771cbd597a3a0b841c2347c89027126bfd1efee2ac403933beb99d08721232ab9b7354fcf9aa800000000000000000000000000000000198400d4e026c2463a07ba5a3974c869ed8ceb1f029bfc7f41b23dd7076cf4a83b17c27ad6506c852cd2cf7c4987f93100000000000000000000000000000000152bbf74cefb77fae8e825443e4ce09b4e223242187f563a236695294d0a5f540f0b29d6f93a54cf0a77900e936e61e000000000000000000000000000000000079f4759eaf044a80417345a1b4029f8d4cfc7e00fc625e815cb7daba2243a97d21e42b42ec968dc8647158fbe467088fa878f6a2e18b88d6badc5b42775e92c17974f3a18817b7769d44ceecac46b89000000000000000000000000000000000cf3148d0c30774104a097562cc83456d5d18643d5f7ad58aedd9327bf8e9450feee50ee893442b1cde87acb02b62045000000000000000000000000000000000011d4037dcc15d0c50337d71816a2b77428b8ddd530bc3b3c8550606229f88286ae94ba03578cbb5bbaf118916dddc90000000000000000000000000000000016160c8ec4e2fb780748aac279bc248b2e2f1092262f86d368d2f06a78ebcd27e929930c8f2be124e9d92dff5c6c6f42000000000000000000000000000000001980375281735390f48ddac9d00d4c6ee7312ed0797333a26a1684e09c9575e57bcecfc4a31b8d9597a8ecc703835e22c4f1a7d2b66e6202c957a649384cb277dbba769afd60708b457613f0f3372515", - "Expected": "0000000000000000000000000000000019ff32d2901b7732df1a924eb3c099a9d36bf36cb32ab322f46a72d99d81c7942d0f2193a4aeb55cf079a2cc1707c7aa000000000000000000000000000000000193561d0433e1031fc51829504ca70e92e19bead2e0bad655aaffb6b41f5f75d18f04a162db7714f3f23da891ea91af000000000000000000000000000000000d010c36acbfb38d9dc2df6e6e21bd75deba5708fb1012eab23d06d78b1244d4daae38aa4f803d12441d91adfbaece7a000000000000000000000000000000001459ebfe65c3b2c9b2684042bd71201869db1a0248c740a54fbdafcf18fcdbcc7b677af43abe803362b462369237690c", - "Name": "matter_g2_multiexp_43", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005b9860b565fc64146020647d1902e2a2d2fb2002b54bf5e21b6601124edf14d6e8836f938843fbd8c02ed8530953dac00000000000000000000000000000000104938181f16f16318d223febec3be3877bc57067fc23729d1f5552099125558cb21ee0eddc32ae0b0cc3555219eedba000000000000000000000000000000000211f809b624c4992a43e78a978ea32accf9e61fccef6bcd05155e52adbf4853340dfacebec9fa87e5417c045da25f9a0000000000000000000000000000000019bfe94a18da9ab4ea744389c17870ac96218d02178bf2ad502f166a3a1da8c14e3fc52038021503cd24042cde8f306d0241da9d8505208b4d3ba2521a42f28df7d06fc212e9e84931cbd30ae3ba2e150000000000000000000000000000000004fbb396eac2a1de9953febed9fb6e158a3b5a366f783d2105b562e8143031d7a1ef039e3fdcdb675b3d3aa4f4dcbe4f00000000000000000000000000000000155e23b5b70f1ce34fc229ad5c8bdfde7fb5dc0eca19596c658c1f8c38716a0a7b5ff59ff19a7a67e12760fa90eeafcd0000000000000000000000000000000002cc82cf87e7ac05be236104c1e668b5573674d9bd741f2d91d05c8a11af1f72aaa1dc20c73953fea38e6e069d2a43de000000000000000000000000000000000a7d1dcab00db0e7c0a239511d630526fb120defcd9453fbb57ee328f974a98721274144e48d22558edf25595b8ff4cc6fecab1334668102e47f1e7139059c1d715a1851a026a1580f93c2daa3f08a270000000000000000000000000000000010c9293b3c58d646a95c620a0e0a7a0a55cf43b4abaa0de1d5570fabca8d97c91afd67bd45aa234273715457da5a2894000000000000000000000000000000001454f8682f3736847cdb3f784a098f7c9e488629efc3820d49b36a2e928bbf736dcb3e1b30187c2c0090fff290dbf97f000000000000000000000000000000000a0fe3c635a81f20258db4f1031589afc8c7fd07f2fe1e5cfc8f3c40d08a958a3dbec537c51be2de99b849e006870b6c000000000000000000000000000000000728876e3fdc42273e8d71953de61dd5c03e7c31ab6ec56fc03cdf55c8f0aa4b4e5c8ed88c23c28568be0d864df026af4e2023c64a3b51cc3d82e262f83260ed4a5e9e3238b85077852fd501b52aceed000000000000000000000000000000000c9ba542189ec1828c397ace9639cf2ebbd1613356d8fb26d3c40dd00af1f43f5bbb25032561aeebba7b874bf39cb0d500000000000000000000000000000000175aa6e94a9e42cf809f48f51c48d60e74d61388dd217b55f3f63612c4565357581e5c39751a65afc3b7488caf5151720000000000000000000000000000000014c880d35d1d31793145803182584a8da003b0ee3c29c978b64bbfe4e1da82910a4539587ba350d393e1bf3169c5e4c70000000000000000000000000000000002a063b3fcd77180de632deca1ba89ec4ceeefefe9883ed9e7e06301a268bdf377c3a6e30859e5a39419e449dd27ebf5dc0a88f0aeb2b082dea6b50d591018330c2276830ed554840c10772403561ed700000000000000000000000000000000069edfb8a83760e09726f6d1c117d4bb3e499084b65e1e830ab30daf1625c37f851ac122f9f5c795912b5b6f7907ffe1000000000000000000000000000000000eb6e9b55869f65ecdf3ac46d0ee596d07c573f88724bcd802b4429392b9a56730a217a03286deb5103f70aba7a9bc46000000000000000000000000000000000e2803e1a646bd70c51806b676591b328cb20359aadc8e79d59e7c31e1ce2f1473b0b19f7a34f23aae09678b11b37432000000000000000000000000000000000b3c9fb5a39a6c40343259e12ff4fe5058f25619d145922e1d80c3f5d105a7495dd9a4da329a2e78afc31a87b2c5d5e2f68c9e76d9d8914f14007c968a31089041e67312c6a3e5d30e65efa55894ba740000000000000000000000000000000019da372143e30307a71c7b96ae0703301ed723814a35e270ef6a6b0c57144f494df1d3fa0ac369f59f3daf534070c9120000000000000000000000000000000006521d89d810c7542108de26bbc888482a3bcec8cb9b542db42d5d4af30d6c339a5b4e959da4f98dd6ef8075554f4017000000000000000000000000000000001387d9c684a0fbf615e7023c0f3ff47f4d2c5a9f748f0261656a09b23066c745420df0eb180c9716d6d0743aae7689a10000000000000000000000000000000014271b9d0b21cc69072333a6c03493321b9d9028149d24964a3773bcbe5045875c457aee11ab0682c2bdd44f098f363d80eb90c6cc25b3a48d93b94b698eff513da37210ba79d22d76a270aa97fd51070000000000000000000000000000000001dd881f3d2063adcc5638b4b3813a30e75fd308de3c9f42e5382fdbf097d5796ee9e03cb44752515b2459f131f58bb90000000000000000000000000000000010f491f4594dab938115343edb47b0087d1cd1bc12ef908e150ecbdb3a54d8dd51ab24a0e10c585f235ed99fbd3172270000000000000000000000000000000019d1665d452ce7fb6bb6da9782a55dcf12a1d9abdfd50435b8f2a1bc5b323c004fad35ff7e9aedfd414a9b68fb1eb1860000000000000000000000000000000013828087beeeb85e43e8540fbdf97af189878f5ddc1eb35c95aa06a26923330f3b8a2b43f835186865d6f5f6afdb2b9b067bfd893b12c79e13659ee9b5f22de71d806a85410c9a23dc43363915a606b100000000000000000000000000000000014964f3576b97c00a8c5f4372e2501944a1e4374a3c30e11376ea62e09d52d40d428887833bc2f06279b859c00c98a60000000000000000000000000000000019ed533a3bf469ce5b3e4e9035af177efe9e4f8b0a0e5dc9721dde49a7fc66fa31c8b1c8d5bcda1bf75a532bd2be356d00000000000000000000000000000000064ec4ed48d63ab62373adb7898bc904d246bf2b3790c3cd850524e50ec38e7fb4a364344a6a1dbd26f2ad2d0fccaa1600000000000000000000000000000000134aa3c6b72d39bedd8f9c619d206a295cbc05c611147d38aa7304e995089ce34ab1fa13c2d6c6807a88797dea20214b34abb11f7ed6d73fb81ce2777acd6bbe8839112c527ef4ad88b094cabdb4742a000000000000000000000000000000000a2a4c8b457d0d2554a2d439fd3b74b18843386aaa00d1b89a1c2d8ff7192cdd1d3a888994376bb7ddda4d16bfcaae3200000000000000000000000000000000155a7dc763caf6f0fe1ba9537c0f75d3e455c2d1c749dbb4aa7242b40a9740fe9e8e88af6017e8f743a9e4c5dc6ebc23000000000000000000000000000000000a693da3aee178e2f0489af77f671c734423032f30c0b7b48debd3b71e65dab7db12ab1e0e72d3ef686d6c1922aebbf700000000000000000000000000000000109c3476016884386d6206c94073c628375a02c8fcd3041e06b8b413508188a1d26ec5ddf84a77d059e9a039dc5470d08d6693acb1eb73f6ed1bb4f74f1062f720a7f2c0ecf2b5a944ff89feb2688e19000000000000000000000000000000000a07f457f5dee69e9ee746dd67f982914a2182b5cb2609d273d4122d57a32c195270c956361d78eb65449cf5e13907ba0000000000000000000000000000000011f149ce84c2a11ff818be3ff0f86c1b38a9555e169a8cf791c79828207b7aa89c84e8012a0c5d8cce4e89d758b90e22000000000000000000000000000000000d636e5b027e41809d7ec8bbbfd4bf641a56599a63a7678569404ec8d45c3b88c1d2969e6101528d4edf1ee9d8e793320000000000000000000000000000000011878eefa5ee49be83ea1f7a9cdcd4997ccc59a9669778b3f006429e1a22d3b2a051924f371a228856523e3a09bab59b29ca1b157e6a2b5b88d7467e851282491ed30382ba217b82ea5cc9ca0c6986930000000000000000000000000000000019e9a1950f663b258474b24c334bd256d3aedcd26dc971a745857bf1fe007da0aa00777db5c3e5d21294e99862bf8ea1000000000000000000000000000000000329a12fa0add36f259e401442bbe6e5f9139e4a46d5d091a2110d2561b5629211a1c1996f20d19327d1782340e7ce4200000000000000000000000000000000032782c94c6e45a88425438324f3a24ebf37f0be213424b1be52c878985633950a022f57f8d64af1470486aa3744f3f7000000000000000000000000000000000631556d52fdcee3529023cf20d46ea09ab3c642a7f4eca2878e4af88801d21b80b829c9aec9e73317252639c148676c40bb53575662fa0b726469da01c39df389efde3936d2eee18d7035704130ad6d0000000000000000000000000000000009eb122c61ec44afb56b64929040058a804311e0e97d3fa513a162748091304233480bbc883f6fb66080b563b308a24a0000000000000000000000000000000007d1d810fb8788b9f0cd04235771d7adbbdf8c6e67e8538b2c6f0f278755cc5e57ad720515ca558412ae1fe2cd40b74d000000000000000000000000000000000955496bdcbca8716245a130fe6eef44d13280b2d56f15bfc772f8ca66a52ca0a742e6bc273c28cfc858a3269f59beab0000000000000000000000000000000000b27aaa0d94633912c96f00ecc021773e5cf5e164e20c7a7222a58b0465e7baec4e67fb56ffe564c7a2904f36c265e61574a30a575138c44881c1c126be214c6b68335d7338875b8a398196f27510d70000000000000000000000000000000012e0572f5c84f6082dd05705a3fae738920ffff840c21e444f0ed002df16394afdc21c249b6f1837389c48719539f4c5000000000000000000000000000000000c26bb3ab52e3bddc219dc223daf472247547544e3a9ccc31123b82000b17ef325148935621edd36ced4e702ade1ee3e000000000000000000000000000000000c13a8f02dc3f209e9abf3d316fa843be9c4dd98ce1ca2edecf757bf2bb498750f6d96c28abd45d9c6cf5b8b6334b63600000000000000000000000000000000157a50d9034024dfc7b0f0db4ea0f45323d76c81bc844844ff9bdd0c13f2059066ec3060210aaba61bc074afd7ccaa286dd51553c4119255b31cb0aaad7391694f7dd29420420b513699747bee819a99000000000000000000000000000000001054edb092a7053eebc542f690e03139f2e25a0098c665741e8711c8a6b9582af47e467f74fff9aeea098b7732be72d400000000000000000000000000000000084f919e219de15e7f9ee122383c772415741e5b86be6ee7d2193a4f6be5c9cc9b2fe5e8beba26cd768bf2ea1b6ebffb0000000000000000000000000000000001822b4e8fae5bddbb36f5c226216471862af238be770d33c4fc1ec2777350db2f42e33a7ba468c317a128e8446ceff300000000000000000000000000000000130f704596ddb28ec6e335d9527707a75c97298407ff3fe17d3cba0cde4c21bfcfd1ae46272018c1db768c036f215182d88f049ab3ee2b01af449abce08ca14ea3b065f06a8665ae3510b4c04f42308200000000000000000000000000000000194dde06f8c54de9ab0ad72ba0de2241fef32fba30fd6f5e83fb7750bc120d51c461d75e495cee0d1e85f0f39aa9d3620000000000000000000000000000000010646496be02c658c82dc68eab86a4f784cf64494bd8441f884e8ff384cbb6ff3a4bf5126bbacaa556aafd652397a8a800000000000000000000000000000000109807bd4b6613acb3eb7d386e84166219e52e841c41185a269cc7cfc5f34e9ef5cd1fea29877749e0cef93a3b44eb1600000000000000000000000000000000020a388c668c9339e7aab15d03108317dea97720dd27a94cd3bb59b372b268d1a7d7d7409780bc4912c3f95acd42a57619d6e227185c538b122858ad5ae594720fa7f743f5805552152a213ebea64aeb00000000000000000000000000000000161506c4a2d57c852fe8c3dce63ec6673f05f99c1e032c8e591239616ef4469c4240482ce5985fdfd4a80f54dfa7024f000000000000000000000000000000000486c5b106393e544852c143c5ac4a882c79870363858b2c910ef4041d8803876cc55ef59cd6a41869bf5247f0db2c0a0000000000000000000000000000000000fe765ebf3c4edd3035c7bedd4aec918426898339d7aa004fd74bbf0e3236deeb7d2bbba56c31fd447816e301100a66000000000000000000000000000000001917c9cf16032e22cdd3f87f098a532a33c9fec560a88f9d4232f96cbe0fe945fbae6bcfdd2095cafe6e0b21071d6ec53f53123f01c4d0d4c18dd72ea87ebb5fcb559df255773fa0165f1432c229deb6", - "Expected": "0000000000000000000000000000000015a88bcfa39f444cd66d0d7e15c4040561154c59b832c5ca895f8f8077659487581681cc8f13be136a35b4a573551ad00000000000000000000000000000000009fb6b87eba1edb3d1d23e566977eac68e8f1a28386fdca9d484c7e341c1b210390787418e2f2dff7a228e1cf10962d6000000000000000000000000000000000978de870dcd8d094072897707313b9f1a18d525e60a7cba2b2a395ffcc9d0f97f84e0784df36247d6c98824aaf3ec82000000000000000000000000000000000fbc6832c324d40f104bf82c8cda941212105131c26f630af1d3f7040ef43c6eb4486766b75a81433e46966f79953647", - "Name": "matter_g2_multiexp_44", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007517a941bec38d0e84d21508d8bdd6778a853d9fb4c5e953bcfe3c8fba3732ca0b7f6cb5c363f33d7718b1b1a68f8e800000000000000000000000000000000150c0d975481422ddec2a58a55b3d917b6b7c0510e75442c81ee856e267d7efa09641c6b79fb9e699c6b473cccde7f4d0000000000000000000000000000000009d37bf938ac30fae1cb3ffaa971ff3746ee4090d4bf8b11dff7710b3f2e4cc686813890e03643fd56fc99e847ae5e940000000000000000000000000000000010fabc4048e0fadad73d0481e290c81884f4578cfb66e0a83324739652ccf273b62204f126696a2fc6469ede39e00a9fcdf2bbbad52a3f5c0b3959d46a8c42f6f5250a93c3dcc636712a4a2baed289c900000000000000000000000000000000089b167ce7fa997ca0ad3f8bbbb358824cb41f525bf60352d5df99402af62cc6d768113d2c1ebc7fe8190c5f732fbfff0000000000000000000000000000000013dcd35865e27bf98f1f6508b32c7e9a989d528df0626228087bda0d8b456af3ea2f4be6732edf1bd8cfd0ab9576197a000000000000000000000000000000000333b0612d7068986d21e1cb67a1c7af423e98cb14aace2ce02f84d32a38f97bcdac465f2b22e5fafa6aaf0d40380e4a0000000000000000000000000000000010de7ba4f50b6654fdecc4fc6c41289bec50cff1be18be9d5c9d1f906ae843189bb43f144aad4d2a2cdebbc2697c974918adf5d8fbdf81f8e4bf2f622e2d481fb2dea06a1aaa289ce4f6e783eb9a98dd000000000000000000000000000000000fdddfceb29fd79c31b138ae8e41507f324abd5e3750da14f4f86176126a06380d53dd5f7efd00e7f94bc1370ac9816a000000000000000000000000000000000d8371c602e393a4be250583c299d069270a344953f7f07a5fe27f8617cbd3ebc91f423dc176b272339bb3bd8a9a348200000000000000000000000000000000193a260a417c9c46da0aaf139e3bbfbaa9f248943048396d95716b3be0b8a148a3f0ebcf7d6f9a318b16d2d850ec2f5c000000000000000000000000000000000be4d0f2bf6d746b930034eea8a19d73377617645c29153b6ae6d3ca6fb35a704b6a0bb658282cf93555c998f6fd054a650e995b73b63d068fd54f596cd9669fc3061f0c1da77ae7d0f5bec012f9ba69000000000000000000000000000000000731c0a5d076d6addb15c1e5d3143d41371f4835d77756418bee452d2f03b1e603230c59f87905fb67d5eccce65a45d20000000000000000000000000000000013bd198c023009190c65686468523eccb57c5fe7b159a1c5ba30c662a275fb24d69338ec9c023ee6a10a8ec9dc7968210000000000000000000000000000000018fb369923ee655839c7d996e264133c49f102978f18261faf2f8eef376eb0bdcb5af375ada2bc783e50df16737f78dc0000000000000000000000000000000009ab8e16e1d0b406adbb37e950bc3820ec13c882ec4483528ebac836726ba202bcf796e84abb3c16dbf6d1131b3854cc3350d4f13e25052b1162dad3ace76e5cda71680fdc89460d8fa88c0d157df426000000000000000000000000000000001401029d7cf8e7d2690a27c01b32008e273b5a33842dcf52d84f77dfa4b2a1fb290f56eb4ccddbb420b27e06a7a3a3b4000000000000000000000000000000000c464c6fdba702f2fbf4232b34d615e66dbb5bdf80233f695e9103272111a06a79f8972d1034176859d0e29400f5a9c10000000000000000000000000000000006cc97a29f4e694f0cdbb099278fa94140b40147f4f911de96a762f2bd28233598a892899a6329cc3cb854b56076787a000000000000000000000000000000000625811cad7c740758388f330c4a56ef30429ea4cdb9a00e2cd1b7f310184a2e6ba36ebdca57c87cebd5232f52c34d92283f0256766690c88df6cf7c968b9a96121d26d19672ce9adc84b699476a32db000000000000000000000000000000000d0a16b5d48eb062c71b91d74a0d25eca0d4bd7082de25199f33a9d3d598d137fbee2ac36e8f877c157be7438ebabd74000000000000000000000000000000000bf93533bf677050d9a77a5dbdbf7cf084b5d934d55318256712ec361693738d48ef27536476fdc93dd8e81f13d67a8e000000000000000000000000000000000696fbd8841e60300602aa5528391aa8b196d8c186d6124c842a0124a8d8dcbba637502f330c980b2f5a900be8e04d020000000000000000000000000000000017b0c51e699d2252f35619520af71775f9dd8c57c2ef146adeb72640bec2ca02a59680153e5c9f66bd513bd8559b9d66145cdeae7fd3f7455dfd2ea9a064c135f0a0a36990ea34929e292e4cdfa0f472000000000000000000000000000000000eee94b5148ccbb3642e582cf0a517b72e6ea019676a13b1484982de7f4be0346b7ed22979ba7303f6367294a3eb2716000000000000000000000000000000001502bb3964f6b3e862279e15fb105073e876c4e48c55c42f3737dc9efed82b10fe8e39438ccd39c933f5ac3c6768497e0000000000000000000000000000000016cd8c4b3be55474aef7081cb969b75ef5e7cca9bd0f9627928fe9931c6f869a9a49d0ae2cfb8346116eb3ced25d4a8e0000000000000000000000000000000012456eceaf32cbb6514e6211136475a750889caea18ff4f9d5ed7b378e6d1d265721a646715aee6b9f2098e954a88289d9cdaa979ab08b454dcb961e3cc4bb18f706bed93a72a9c1e105cd69c0b691af0000000000000000000000000000000007b5633f4a7dfe62f11065d44581f5060210f8e572d960eb85ffd0a903d8b989ce10449fc90b7e5646784a9f6df28699000000000000000000000000000000001710f252cb35d88f6bd151ed596f2d6455f050c5e25add394dbaf60fc036016ae07a5a8ed494b95875c02df3c523186a000000000000000000000000000000000bee19779dc6430ebee993f82a054fbd42e5b7265090017e5b2d2f1469bc96a5a188adf471d576a416f6a841081043df00000000000000000000000000000000038f9fb4159e4e6f596a17ddf45a00a9e4aede63b062af5eda045efacd3977e8dfd61c307834c08bb4c284638696e92ef262f9f7a26353193939bfbbdc50ee35614a3c099776f08b21e0c4c97521eb8e00000000000000000000000000000000197687895f22c4a639bcf2f494dd9e5a034610b0297528235f1d806cf032f5a86c5248a83ed6b12f0de27f5c6e6f49420000000000000000000000000000000011ccd5dd6d6ce553ade9b31503a9e6a6119ae329178706f051581e3cf0ee9d6fb527b340bab8c79fad1cd451c7edb4330000000000000000000000000000000011e9f051aacd69c8bfd2f0ecb566e6d38eabc43f276ba7a1b8e8ab093917dd1c672c61d6dac4651026823b9938d3601f000000000000000000000000000000001362c3b2e6fd9b3618df26ed28f96530c1915f0a4ecb647658d1ae4ccf4c000f3bd1797696c9ac5c5000dbe58dba8de44f0d2915e82c9a69f9e9af64a2c5cacf61ead492bf69912a35ad6a316f9914a8000000000000000000000000000000001819d13cf4522a9362bbeb0bbbb0a498c3f34da1c9e3b2c54d08f7c8acd9ee756983fe80405579effb79d673407390ef000000000000000000000000000000000f870e5978f4a6e3b655fb2a05541ac0673e7b10136adaf28be4dfc9022d4cc8a60e17d125dfe53fbe10c644ff37e02a0000000000000000000000000000000010207ef774cddd10db2bca0a051ceb12900c407ee265dea4615553c193d7475b5ba3198b7e0160740e4fd015dca33e1d0000000000000000000000000000000017937be546e06fd2eab4c969a029534c02fb770646d43edeb5e6c8bc0c2b5f35576c375bf860fd1087ce099d4377d24e25ed3f13198b69604c08b414562f67a67aa8dd4a7bd3c066874182d21ed9004d000000000000000000000000000000000db02fcda340fb27a3fd7da468c5cbed9c8dce8471843a8ddadae43dbec9957a0479aa52855d7a6dca99e7922432365c00000000000000000000000000000000163503d24f9af34058cb5afd8e9d5aaf29e141c8521eaac282f138466e834f0daa9ce14e0590b501680d5b47f866aa8c000000000000000000000000000000000fc9175e6d20afd9d194907f2eb311bf8134aeb96da72f6423610612f2ed20a074c113fe8bb632d9ad74b2f6e7e2417d000000000000000000000000000000000b4621f5e4465629648b62b7f2b77afe6470f9706f9bee5b3ccfa66c596842cbae26badc689f7f623360cb7fc1d416b84ae188cc115e9d492be64abefa4bd4c93b61dd42a7d213e1100b8108611a61630000000000000000000000000000000003c77c7efdab9a9e71283b034ef581a31faee417febfa99be3c18e8ab724c140be684ce719bc5a9ac5d3855ddbf3651a0000000000000000000000000000000011889b02b4a1150fc2b7191a95c5ee767f3c9b82a3a53591018242fa8685ee3b3542526dfdc00695a6cf046033b8eb760000000000000000000000000000000016d7463159c4e3cb635f24bfb944bc518369e894218bc49d7b7f0ea99240259f7ee2b4c26c6083dbc4559ffcfbd392bd0000000000000000000000000000000010a85df6294fd6406ca651f15494153e9802f0068bfa149e87fe4b1cc3071ba74940a21dfd55a8a77e7e2a193468a3d2eede725a693277356ce71ffd7814a77fcc30eeb3a2b8863fb91ca03da1cbe37a0000000000000000000000000000000016beec57d3049c382fc039ac96b890412c5e8075afcab599fb877f8639747a587e82241d9a8059a0bb45ad49959777d0000000000000000000000000000000000a70fba1b061dcf587f133035a3aaafcdace3b1e771d71887ae914919e5f52a99d9933307ec15b5f0a1623b9592824500000000000000000000000000000000005064161136c04f9f50e42a5cee5dce3fa0ce1dc0655b3785a852cb9741927f6c9b357ac1010d7212533d1593c83dba70000000000000000000000000000000000d50b992bc0eee37a15cfd32eda2c591fc4c4203ef84232d1a1e7a9888005bc00755d76b9d0345bb01ffa7525f2aa1e9d0618f898594b23ee3754fe390d6bdfa7d47fe749d6819e306935c1eab6b0460000000000000000000000000000000007617e60d8f67344ce6d2fb65cfd5b423a1fd091626da837dc8a51d6ffdeda9712864e8f30e45ae8df917e0e4625e59a00000000000000000000000000000000077c4aad14f870ba24703397ff0b33af2e50b026f3e0f13f3ec1aebc9ea3af98cc65ab56cce4045538ae6e5f410196f10000000000000000000000000000000004a31d0eff18afa87f9a53098cfd5d21e913c7519cb171f83d0b73abbf3e893a3ccd5aebb9f2bbdd3b0eb0326d37fd1b000000000000000000000000000000000393052e6dff65e01e79254af757f12eb1931e0b386f8cf0fa0782269f962ebc5d9bde46f5a4ad3806e88330aca59ff01e1c9420cfa91026286d7f986b538c13e8c97893995485308c69f053927f962200000000000000000000000000000000033aa108d252e9107f29cc7da79585d4525ff2a35d31479a099c7c011a9c4414d7bc5f8498f8a204134b2d14c5fcde5100000000000000000000000000000000121214465992bdefb970d420face6db75d531e67314a021d2877643ddf738fbe57625d286bde7f40efc1d329a2e85b6e0000000000000000000000000000000017e14f6cdd916b1fc949be8ba3ef9ae6cc16d64da4dd498b5458ea0c14eb7aab8f970f030aab26397110331da11a232d000000000000000000000000000000000c56ccda2a5cca61025253407e72967c767f0e7f2aa0b97d4e4a09420dcb882ff35039ae504a9c62b3f9e7bb0c2e7bbbe5095ed9a9181aee392888e3194ebf9c4a6d87b503f4668bb6cc0d290880a44f0000000000000000000000000000000010fb3396b0674b9285cc5d5a4e7a41ac002f2b43332c20a56f428d1e19e1d1bb6f886d3bf03f7b0fc509e52d75965e15000000000000000000000000000000001196b7c253c50da10815bdfd7930a69608187fc3ac5fbcfeb35b95754d3017a094afcdaea867c2f08346717dfce7bce8000000000000000000000000000000001021f178c53b7d7d2041a6419203d12ee162f27999dd8f79baa15c37a7401e7a6df6aa4192a310cc1a23bdb0b427d63c000000000000000000000000000000000953c75910165f11112583476574f3987495d33e5b1a5c650a2b30692592a442d9de36da49255b0c01a7bacaecc9b81adcece8ee33d3bf3188574e94a889794077035ee92473b7266d92a3c018771b4c", - "Expected": "0000000000000000000000000000000014da1d424c936453600a4acbd3666c6188493d4da8b34d6bc508aab07e59e3680a9e3488e69d42a724c9486d70ed4fd000000000000000000000000000000000048c637348fb9a4c631a82ded1fa08d693cfa2cdd6cdffb8bffee63d1bb2ee8676512a1a8d375e7ab942b6d6bdda45c80000000000000000000000000000000000443264e7dfca91f17251c33cf72c56b045902b4db2eb10d1fd856f79b4130afa6f29f3283af7d3b8b2a9d8dd63718a000000000000000000000000000000000fb386f875190ac7a49d4742edb387f72c1ae0366ca5c71d5b7e385c11442941ce0fb9fe2014fc624fe93ab86ebc7aff", - "Name": "matter_g2_multiexp_45", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016a539a21320574fc25ffbc0ff10c821d6ad20674413eaeda6f4a31f9a028e21cbb3b224c225a2e3bc3dc221cec084cf00000000000000000000000000000000104e44989e2fba9ddce8e309f5d3fa3129f679d6456ed11137149b50adf8b22c1a148d47154450853e6797aba2b006850000000000000000000000000000000008b33b8cfc992efdf7d733803a6d08a4102e27fc4960ebe6ebdb7949c4ff5af76e55002d93a4f7204eff5f2dc4e37ef10000000000000000000000000000000017c35411c571c302c746a9b79cae892e988d50b4660564660de960ee09b3937b6f5b61fe37d09f1c02528f554210744aaddc845ad867f1e2664ef0e78bced8ff6904c5836e7c63ea3a9c858fd7b710b60000000000000000000000000000000009cd32594094d4744f59690cf8d7fd260b5ffb2a22945d938c035151861507ecaac9ea553e7b44fc4b3beb03b33783540000000000000000000000000000000006f4de33731b9b13b9cb395798769e54a0679d272c2d5175455e10c790debabae4ee02b6df08975efe806da9c4a208b20000000000000000000000000000000011859798a8383b7f994a1535bc0a96a114b90644d19921f0eec774ed58dbaa899dd3736cd1f4a4ff9bfacbc7370091d7000000000000000000000000000000000376c25b0f70427d4974c4fd1539d40996b6847fbb67822fa01cfd541cd3a3f8a9f3fe9f7ddcc3ce920a6ecb27dafca0c78cfc6a30cea34d3d3505f4f897631f67ba77913734f6c2895d871fd6d5581c0000000000000000000000000000000003a178f91a135d59dbd65eacebab293a3817d30e734c247f56a08812aa540a5c80e3f9908d86ad787bab27fbddd21517000000000000000000000000000000000672b3544dd2b91a626f37dbb389aff073777164e3e20dc572b18a2e5223bd323094e41bdbe2dec9bada227efb37dd22000000000000000000000000000000000f40f2d279c66f22bf0fedd129e02c96d8906f9f1ec19f5a5c1cbd5beb10942a066dd391b69920a0a697138f627a1b180000000000000000000000000000000016ef3caad858d323b752e5c437ee2043c8f691ca0f1862e80857f7cc478a689df97bde5b1d1350892c1adb03c5d2373ba1e40df9e1f7c84633cb3dc2223296887de7281ea66c5e1f2d5816334f7b280a000000000000000000000000000000001276e133fc5e708a3265646ef0a0122048ef95d7fb46f78b8dca57dabae0164ca986bdc74e581604ff31165f9f28dca50000000000000000000000000000000008a77611be0502d2ea7fbcf73774fbaec68eba36038e2f34f79caf07f2e4b7444efc49a4e85f88af585fd28a041f26c800000000000000000000000000000000181ab176e391190b1cae2e9b4105ca14cc82d15890b0ec127d8cdb46f30b704a089ac69e76f5b50575ed66176950e1120000000000000000000000000000000004031ce77fe9ee319b8db8f220ef4480c81568b3f6e4043c8710b559d25ad69dd38dda48b2e11d5aead18db0d1cc09b98810b9ce0020904dc1903338089c30e616ed0be03741572ce46946883874f4ea000000000000000000000000000000000f26e6d71e206c88dc81b8b8a5c05ee84a9f185e7b7f155253aa39104b5de5be7bb6cb6662df4f8e63b37fd1682721f20000000000000000000000000000000010058d13637c8da2e91c8cda7dc2cf1734a2f14b12b798e5c563ef9ef3624255a6e1c7550c37b547c35c55dc736a17ce0000000000000000000000000000000019ed470bd514f8bda8fdcd9c64f7626efdde0102907bd31551b1d1972aa14e1d361e1d58b17948909a669fa4d99cf3200000000000000000000000000000000013277afe1891807e269c22c9aa1598c12081809d888e0eb2513ca3f81308700893f74f176858ceed9c7955dcc0d8fc6893e7702da2ff9f3f14586a9ae80c8713743d61b915a7c379c1faa1b151406a9a00000000000000000000000000000000083664daa965c4173d6028e047794703a16e52ae459d3db0534d13c72d749d603edd668b9ce500677715e45216367c63000000000000000000000000000000000f4e87a65f4720cbfde7868eaadb34ec1916925ffd84e5407defbda0c39e1c7afcbc90855b275d528e7b63fd3707bd4a0000000000000000000000000000000004c9f689abe0d2dd3d927bad4b39ab44f6704014ef9a1dcd1966777129e1c72515b43c1b92ee60e9611245454683588b000000000000000000000000000000000ecc57b08b45037e62498135643cf077f01d216b5106551daab391446ce7bb37d40f41378c830081bb6a326f0105c2c4eca54e365faa35d2c9be259b53a1157b180a373813382f47c9154af18a2d83270000000000000000000000000000000012b84341bbad1eaf7fc8ebe56f67598821017365b6f3b4cc1f2355f868e8d55f9c0bed2943ada202a7d85cc884d8e6a20000000000000000000000000000000017693721988f73d77f7a41db108e428b0ba781ea88eab463693ec352cc13d394101b9a2792e0f30c77bebaa395a4776700000000000000000000000000000000093245e2919523cd57a0abd2e8a9c5cbe774bee957f26d3cb502b9c8c06483b850b031461dc2cb033d399651724f4fe4000000000000000000000000000000001530f7dbf6a0fbdc8b4f7a4d298b7824c15035428cb8df834907e25c64b8985186bb13f397b7b99ea7014ae65c428b12abe2079ecb3618de3accdf291d9479bec32bca1f9fe87b00b64a12d735f5b9a5000000000000000000000000000000000f323f01f2a63bc6eb1b565594ded14043c4ea5d1f0fbf20f39299052617c334e6126afd4273738aeb153c3561348b8a000000000000000000000000000000001525d1e1fa65f1b674feef74f6c81c82c3eeb709e597aedabbfc2b3262271b31d93818613ecdeb49c5d3a6a64f17a5d90000000000000000000000000000000010458c15bf46947a237dd1c61882b1561121f64890681bae5db6fbd24ef6c34b7fcb826eeee1fa328d9ef4d859faf238000000000000000000000000000000000e1f29275fe1805d02e069082d5e9a7acf69be17013e6c4c351277408d49383fe06f00137e777ba4aa49c29c25c6c0ddc541a44756ebda14aea95f1a1d05e7366dc0285305116b907fc89e777ce45f79000000000000000000000000000000000efb7373e11694b966d0182a9b01d1e52ec1e89cb18275921294e2d36333460b1e49fd420f1ab781b000d1491ccb0b11000000000000000000000000000000000cafcdc2c58fb3fad713ce1a38deadba8636c384243f9971e3930b961efaf303cac4eef1e8e4662636ff91eff1bf52a80000000000000000000000000000000007ea7441e1b2b0f1e42bd511c060b646c2d00bb3e6507beb5d17ab93ff68515b02f82c2dd43ce035ff660ddb0c104a77000000000000000000000000000000000bd04b88caf9dbd0ef5f89d12e72aa47d64212332b0ed871b7eb96b16295cf4810f6f20cc85fd4d1ce72119f80697c1b37d521d31de52681f1d9bbf64a12f9bc8fe0ac61aaef14d7e8d048ff09e6578b000000000000000000000000000000000c3d2d978e23a690e8422fd54f36fbee1f642611b6c3b2c2413844066159bdcd3703d1a392b030446af04b654f8f73b7000000000000000000000000000000000ae652fcdbd8e467ee9b447e61fcb811f8b6aa48840476c92daec3285785a06a81c1705fc2896c0843ab48eb92555b9300000000000000000000000000000000007088e6441cb85aeffcb4a9a0c81ebfc54a61f35c542be3870c2bb94d7081353322d4745747b0dfc3e5db07f9e48c560000000000000000000000000000000006c11f3e0941ea3bde0dd3a562dbbdad433f0b1e99ba34879e86f7951ddfb29b9e04ca62d54d7552a74e8cf1c3da3e704904a876d4ac1341e88fc4808508c89c19dd74aa8fb1dd7673cbc2d28e7d920e000000000000000000000000000000000c665f4417d0163820ac96c83cc2f09b1b3c000023d827e2690aad7357ff59e278832b992703f5f0016051ce0a4510cb0000000000000000000000000000000012f4b6688300b253fe868b3790f6d2f4fc16d81a49ff7a2edf821de16dc992d79482d66e443e0abb5da43df69f8d648d0000000000000000000000000000000009e033750a118d998b136cd671d0e760e3a617f1d6a994db8f6dfc391619f408720cc57fe550785306184b0c824705620000000000000000000000000000000018cbacd471e528535e22f714a841f110fb0484826e30f97842d65072b2790dadf0bd7b28df96bec531fbed1f3f93486b68911b04d8155f90c7c5c0cb519ee6ff14c0ae27ece0374f30fa148235e8cb49000000000000000000000000000000000c42b6fd52cc52034b04078a6565af2b43948695851393596e05f37f297dfaaea931a33f5b4c25980c093f8a742c0020000000000000000000000000000000000fdc7aa20e63743dd6ab32c82d2d6992b29779ec06eebd452c17d844159e90a7f3221f3e0e6b5805dc0f42dc3836d90f0000000000000000000000000000000003a2342a1bd528d701c2a6c72708a16df632f4e4b6cdb3ccc224b58b57af30b44556cc968ba3c0396a5e3f11568a73710000000000000000000000000000000019ccf76462668905c5687b7612a0bdfd4aac70f291d8b772e84fd5d4bcb591556317426471242fb5f44fd695c7d49279481e894ecd52a252cc76547513e2cf0a5cc6b20c3dc9c64c7f34f29a488258ef000000000000000000000000000000000c8fd4a171c5fbf584f567a1c10b20628e7e0d5d796eac4a9dd2376f8d488da25b9219c7c70709999b5553f8bba915ae0000000000000000000000000000000005d791c907984f2aaebf903a0ace52147745295f0c5e85964999a8fc74b64c8871dce358f26ed1b4af6c6f7f18e8f4c500000000000000000000000000000000110a453bbba72ac171876e0f6b4acd5b178816301e02586a143c2bcbfffcdbf593655408b9aaa4141b2a210599f452ed000000000000000000000000000000001025d5065f9801fcc1c1ebebdf67923b967ce985b5ca27ab5db8af7057fda23561a46b84fac5e793dd9af692c4d56cde72780ab3c48c8a102469799ba2f70d2fd9d324cf558a8c8b49e2ecdb71ae1c9b00000000000000000000000000000000023e5ea1909032676cdb79111a33da7ed788d2affbf4029b932eed843268f355dc92905db283d6617fbb530da3d704dd000000000000000000000000000000000b46f07de520aa17d597586cb0a6894a356757941ff9bdc2976f620e1bf1eec1dd9801d6baa2d7efbb3cc7073412ce8e0000000000000000000000000000000010022940611f418de9f9210b1be919d7506aca468fe5853675fe159d3e58685bcff6cbc2c1cb9e7d45a7bf305fca0eaf000000000000000000000000000000001888b5b0dd1648d9a27345f570a1278238957de1bd30c195d554750ea4b119e98b3989b912c4fad531de416c1533467f84ae1de8aaf498bd2d91bd828bc64e56482b225322b86529da703f47289c65670000000000000000000000000000000011dcc334a5037719256e514b2c3b0f36396d8cedcd77f33545842c686fa0f35558c397562a7e245f8cc412c776a2b3930000000000000000000000000000000006efd32c6afc56a07c813fe19e71f0248666c87e1df7e79b7afbd70178929e5660e85cea35d1c6f42b4c627a94ae0d150000000000000000000000000000000005a5fc2010798c793c1b407a577da0bf0e04b0478f19b7d0cfeff8e4e4fe2d581461831db165cfd17146c49a732c41460000000000000000000000000000000011dfe3b62eb87b039113152af74ae74137cba1762d4ae62d3cb0746272d1c42d3cb4a8fccd845a519fd0650a23a897a13256548db55ee9de70ebf6fa347d81bc50494b937ab1c3079977234a34cbfcfd00000000000000000000000000000000110e73e44734b7ab63f021727b75e735702f1acfa6669e0dc27111794ebee371734764bb165132af3a7e02f3605456480000000000000000000000000000000005fbcac7c7334cd0e6468feedebe077b80390833eaa4c28af80d29e75d692a10cf13058526fa5e5ab0fb635335ac8f220000000000000000000000000000000013f537ecc28685aba2cd60d0e3e787bc8104a3373177cb93107b63d39919c583ad3ad7a42e322249d7605ef035fe1af40000000000000000000000000000000014791f94aff42bfca13ab328a3e47b06f7da52e13436ad477cf55e53b54108d3aa531f0a5d73ae5ed7108d5cca1ecf7a575ae146524544307ee51e58a654d7324983a87e1b37d46cea1a4ec34114b44b", - "Expected": "000000000000000000000000000000000bab02defb32b7938372d656feaebfb5431de1484361542c02519d20c6a500f0b0b112c331fe6f4eac3ec7f6ae4167e50000000000000000000000000000000000796b38c67df1361115bbf3a4afad2651664ef55b1ed02d3172f024f90a003fc3631753d7142aafffc64c6f6f57bf7800000000000000000000000000000000080d91637a93a9025e8691a400254af37cfde67eff7d3037d428596a808a01d9bda8025b7246fb00785cd1068b2752d400000000000000000000000000000000182a97624249f0c6d24672f04e2c93eff63fbe76cc11ace0f7193facd0655cc1e1ccb2d89d9547bc352a395efeb95afb", - "Name": "matter_g2_multiexp_46", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000115b14c4eb9cc78eafedd2072be4555a3db9e61b5fe0139bf3e40a92cc37b4936c68576fee5692a80e4a9aef05a9b7a80000000000000000000000000000000019c828ea555a3c8d28cf0981e98609361b5bafa8b62e860d121c0f6d0f0dcef544784e8a5fa6a9f1d1a68b30e8e8a6f8000000000000000000000000000000000a2ef5146d2658609fd4eb98fcb5d42f6c6aac4fe53597128bbba3ba3539042ee5824f381c41dc76e2c6e4dbe0665657000000000000000000000000000000001807a12ae5f289ecde8ca0a913647d44209b13fae9dd6aa8fb4365a3beeb81652ec17cf92f6784c9ca5a077824ff6dc31129275f3ab3125db33d43b36c7de0ad60a6e9cb4457aa03275caea9635f0b0700000000000000000000000000000000186bfd109ea2369818ae2f466953eddfa763960caeee9d6f1ecbf6a3f854163342c26b56d3844bfedd8f227070f75546000000000000000000000000000000001877077daa2ea074b2868e86faf14efc6ed35a64161a77aec54624d9cb916c45de81b40acc3797c6e3338fcd7a42bb0d00000000000000000000000000000000054be1650d9bb6cae6a1ed08879668e4aa4cd139c8b07ce21d40fb1cf37f11de730ff13814a02d2d6d6df5eec4afe8470000000000000000000000000000000001612b5b7c613cb66d4134aa867d985682f6a544147e7865732887d4fbb191a9f5bdc27bfbefd397f38cb101a2d68b192dbcfd8680258eee451db60f3f42f02f388f87440d00badb0a725964042515c90000000000000000000000000000000015e2b23aa42f1e6a07b0a31dd4acc27e35ce1fb3333c3f330f2d88f112375cf24e6dd5afc4d245531e4e84f1f82230ea00000000000000000000000000000000193649f3b7efb346e0c1f7bc05b0910311270cd44b5803fa16e06655d6239f609363344bb7c16c2105e20709fb5ff0400000000000000000000000000000000002a6ee30841f471dd2ef13888ba03c9cb93c85cfd0f1d0a3927205e3f57fe291bba7eccbd2352f25cc4047097fbb63860000000000000000000000000000000005482d4a47d6e381f755c4756a761f0310d0d981523afcf288e47a1a643d6be62ac6410521e0f25828f469af6150f41e5a6f194abeb6b7c1c561aa820bba658f0277870e2a32f972f9d18ca361929b01000000000000000000000000000000000178ca460993d503e496633fe5230d895bfcdd0696d817a23ae94e529bb145a0861e4448d3bd48c55907be762192a8c4000000000000000000000000000000000015d2db77105a8ed6eadc05d3d1f26a54b3d1b812a58ab49a889f5b7fcf5ec08c2eea6ad09484fda29cc007037a1f6c000000000000000000000000000000000fd5628d61cd0835fe49fcbd2f17058f23d0ffaca4474923a2c0706d9333d9881125efa2fda56234a82158da3eddb5b70000000000000000000000000000000010ce4a0bcada5f92cc8898dbf5c108c0897322eb6a467662be569d9ed0f6e2c808e214b83969ebb86c84d38f67d20754579450b7aa155a3ab61e47e337ddbcd17b197de2dbb76008cfaa09d3fc806be4000000000000000000000000000000000fc4ed0ca43d5cb172deef02704579187a480cc977737070b8ed2dce48d3f3141619f37e985c220a2840ac01dc5667f900000000000000000000000000000000047a15e96760affa4e537a45aefaaab1e0e18052f63514a9f6544136c87b7cb4a5c8dfc0d9544518adc7932ce9cff5f1000000000000000000000000000000000c9be55c06f81e87de58a5c1df8d16174cf4115f81091937d98dad6c4780a9b8dae1081f8961fadc4f994ef62927664700000000000000000000000000000000165f9b1a8f23831a91be8077b18563c7648e54caf30895983cc26580241ca7c86b9b30408a9b27776286ed9f07bd8ecd4be94f96ec4a3d4e028644c63b2577a9ef849b403acc55e42432c3063a918d160000000000000000000000000000000006edc0d62ec31b14e87b2ccff3a21a7c8d38c3ba0ec48bbb8df27fb1acf58e1a87c4458dc2b770172460adfb9a9bd50b000000000000000000000000000000000ae80063df8d41d45fc43f3aa0881364ab5fcb9ac526ee22d3870f2edb0aa379e9d81780b0ab08a4cf308d819338deee000000000000000000000000000000000e0898453feebb51d9a1cd2bda36a307ff2eebf44dc8f4c694831218c42b51f723ffe521b356ad4e5f0dbbca9af9ab47000000000000000000000000000000000fd186dbc046dd02217cec3c7894972f71e5f00e00a40fb1521659a33e079b7a1f60b026d9055a50ae18aae5757ab8490983e6618e9e4208cfbaf647592e42b2d30de9e74e4943fb2bb49109a66302aa0000000000000000000000000000000012134b433877e0a7858e6c3b95b2a1dcfb0548b290b68c209642dadf550db1c636598ac43d101b13c2d8d5ed9602a73800000000000000000000000000000000102b5de123c449a078f6f06935c9537efc791ed8e5475ffc2d9e1d098c814abe56d4b7fc6501c315edf7e64a431c5183000000000000000000000000000000000bce703ba78f45a1c59c69429d3dda18243ba2413c5eab46d469f504da975c434eda451c85357738d6c7054755d5cec1000000000000000000000000000000000387724937bfd817a65c0e0411678cdc78df26ebd4a814d92b023710558701163349b56b80e6bb68a4401f2662a0525506615e300a924ab962e0b7fd0b044cae9516d96de603ee80695718c27d7fba0c0000000000000000000000000000000005abed9305bb79a0ef1cc70e7fc2eae35a8580cd3d1ffad73d3bdae541ad546b8f74b4ca76f8f374e31dbdaf1bd14be9000000000000000000000000000000000199b29da8d161ab3061a18debc8b7400415caf029ced47131e27d81a0f7f79b6ae5e570f34a4c74fb85fea1411bd6ea000000000000000000000000000000000b8a7c42f5289d20b1a55a42d53d49510d3871b6efbe560bb4d87029b85b930f787c3a42e225006ad62c68d5f96c2f8a000000000000000000000000000000000e74aad2b29a210cc316181863e71a1dce8866a088a072ad5972af57b813a2e968a5b16b294273acd6e81e9a5be2961dd77d3e9e64e00b9356cceb62209ad48fc89e69e2214aad2edeba1812272736390000000000000000000000000000000001587e32753adc85c98cf1322115772b0e282ef4e6a75944fc86091e81aad076508e3d727f4df0e30924fff6b67c312e000000000000000000000000000000000ae96d3a1b79985e56f80df8ac4d9792229ca580b156dbbe71a9db470447fa4dfa19fc8a8a2e2f0fae28a24b7d6153d100000000000000000000000000000000114101ad0d29ddfd2fc436d2a270711c444c8c257785f4b4c549e9c795f6dd9834d3744995d2188c0c968752a7f68892000000000000000000000000000000000d30d9cc1e2273af745dd47a596a2202ca4fb655f9f9beeb0a87631e2461f29206163fd921761fde69654cb02e23505c41f75c89ec973f65b11786e186f4d42ee2e85c40f29745d9f428af08a39d5681000000000000000000000000000000001611787ba658b64467b4a28e55ea24a3b230836af6c2a7072231045ee4ee38e02302a62688d6f988f76cb5e50eba40080000000000000000000000000000000008badcd59d6d30f26ca674753ae9257a853dbcf49a5641999634a9a35a97096b6096b7b058360bec2f9476a51eb0d781000000000000000000000000000000000d30154440d8bb5fa6538953a96ba404658817be8047fa7a3a86493f02399543220758e649948b804f2daf84fb86f7580000000000000000000000000000000014fbdd62f761fa675e4cbcb61083a910bcfbd1f8e37f1fb1915f60929b047c970b87be0730ddc20f9716ed8c9bea7f19c70cfb76a04d1a9e0d937292e5553ef371e20d5d3dd33611edc0da178e2e4a1600000000000000000000000000000000143d1f811644e3a51c735b708cb2f8a2a90311f9971c90b9ec8e45bdd6488638b6851dbc882205263887b4dd5dfb4e120000000000000000000000000000000015692a6b06e3bd3100e149c6be3cbf1566fb24531eb29036fc48f85d5da83316a38af4e714a17552024c1ca4a5e39d9d00000000000000000000000000000000172b9c88ed9a1fc2d5a7f147d034fa243d420b129343ff92b79bc4d836e380e5a7e388069e9af9026485e9d3f41a7aa300000000000000000000000000000000012e8453dc64f72653c4e9b3f6f43fdd01b896c642d21604f992dc5591f2cadf71de4099e1075a4ca4b7539f84dd5a908db878b7f5fe817599add432ecf262f19d80ac834bb0a0f983728f6e2c189c880000000000000000000000000000000003e9b6d23809781f50c0033e53d245dfebbba9e0c4d9f676ae61b80fb6e774509f62fad854fd9ea841d9905d48d943a30000000000000000000000000000000016a1ba62bc684bb1848b0ccba59597b19973b56fd9b1d9d06352de44aa79c6bf65409dafb54f859d4a7c32e188bbe19d000000000000000000000000000000000e782741a4b16c5838a8f6e542135221ab3c6ad180c85c08742992ddf0239388e273735eae76c656e61614da386ce2640000000000000000000000000000000001cf6752e88990c221af94e18744790c30aa6a158b10a1f6a56c2ee3c3f0fdb2fa7213f16764ac9e9f4f65e99e715ca170751fe88ad289c91dfcd3c3c61ce1e33f4146f03fc0dc77cde9b32b51c75fc0000000000000000000000000000000000810b0175d781256053c3c9188cee4f55620a6624bfbd2f4d2e70ee68a105bc7b60bafdb76794a048e9f25da976390d4000000000000000000000000000000000716095f8fd72d9350ca62ca3ec34d2228cb563d4e89b19b152787d42fbb750435aa6233d0a97196a9324319837be14f00000000000000000000000000000000178e939d87c37d4a2f49e1e5596945879f2f0f64419e3dfe2afa06bd58098e1ba57a9b60c32cd6527481ab3b325ca827000000000000000000000000000000000aed480a1da482e40ae610a9522f0a18399b0130202f9ca79e3573987f5f7ae30724feddb52fdd05817a96f7937aaf7984bf139cc0b6ac94697b7dc278063a74e478d47528da3f84f55fb0adfd851d09000000000000000000000000000000000133adb236d9eec3544fc91852278abe37a1da0f32a84477c0d93927d64af613b7452a5f64ddec7447779f42873cb157000000000000000000000000000000000f6bd940b51b7ec5a0d92ac77a55c296215e970e9a499793864dd69c3a8d583403e95c08b719b5d8eb0c37a8476d3b960000000000000000000000000000000007d4444062ae06e65b45c6105af53c487f6b275ecdb36f87ec7b71d5861a1bdd6d735e9a1fc5dfb476ab8c13a98b570a000000000000000000000000000000000e043cdc87c67157b5ea3e5ab1b243aef479b23861f8cd823bced140ee03dd1f8bc6cebb4bde4683ac3340823f4d55b8d19d9496e7ebca44354d5c6e1f6b8211eb06ca23a6444c307f92f5bc6dcc2dbe0000000000000000000000000000000018c35112c27caa6bfe9cf8ae55f51755ed349ee7e7141c99069dea07c21a6d8634778a91f4dc3d17da04966a9eaccab5000000000000000000000000000000001800c8a9b146dba27050ce63e78895bee2016255c59acc34fd5e6cb926c16a8fcd2e8a579fa02559b3c571cb08011bea0000000000000000000000000000000014afab23fd4ea54b1ef576a12a2a62d42b493612ef466483ee8c4e62908486c038598e72dbd9256166960db73259def8000000000000000000000000000000000899a99ae8b10da4bbffb6590d79aa33bb2adb2444a11627f05622c732b70f90cbd2779362349aede5b591e84b53a8a06940e3509e1fb090fa787fdf633a74380cd5de722678826224641e46a6e920df000000000000000000000000000000000567d6458d1a3e012c63adc8b9dcf32254c98c0b7021ec6a8d579dad47d501715d2e42a0837def225515d663e663c4f000000000000000000000000000000000178daae121366ce025c1dc2d3e72068fd40ba9d54b2b3724f7a2071a59d4f17d4766a82364540bc31a46398c66d0e7da00000000000000000000000000000000147b2851311913ea53662082acfba785d21915cf00cd154b1b495246e109ac37c3fb6c63aabc4fe71a0d37c81a40148d0000000000000000000000000000000000122b7b1a81888aee37fdd6c23d31c38e79f28945cd1798cee3f4d674e923fc68311eda8ce45a561abf9c5f0bfeb4297b27d21c1d6e06d9fba7b61fb87d364a7a6252c70b8ace2d3679ed87ce0fcf7e", - "Expected": "000000000000000000000000000000000f5b941cda417cce69a30c1ba4a82cca71cb4b953d06d8e545c1b792ae22738dc006627da02b4344bb8be93a5a0dcf07000000000000000000000000000000000eebf4ac30fe0ffb905f81577466889666f801d4d6efe0fb8a663fbf1cbe76b2167243edfc6cde3f49d97d3040a9507400000000000000000000000000000000007ae6a99b86dc7ea95801776589472547ffc7a623009a592403a9710ca365510d85bbf20fa4519ca0e0ca208bf86a670000000000000000000000000000000004b5abf778c72bcc5b887855c582c042a4cfff489b0548785e4c1b735b19159be8a3f4cecf34c769a34cdefa722ba783", - "Name": "matter_g2_multiexp_47", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017b47384e6302b140118d0a9247aeae2091607ebb413ffa232223bb42d16753b2ae48e5ad0265e33616b25f0c4234be600000000000000000000000000000000167be566292b835a42ac7c099d80e8a0b5d4ff91d842d4ff6026876aa1570ef9641e9c0cbd44d8578f6a758717bad6f10000000000000000000000000000000014f692d195979abd9c55ac132d0def925d4e158fe946fa7b0a010c475d60171a0951d4b68ae3c463bf1136600a1ddaed000000000000000000000000000000000ddba1f4236c5200aa52f8cb7e15fac1f20cc66dc65ed180745a3eb8308f2c851ed6c1e27e1507d3f902ce672d6f8d24facfcdf87c6ca0506b070abff83ce7812181c31729cc534497aa8dabe243351300000000000000000000000000000000023d08e255b244cffe911e43b9b48408f9fb3562edc2c27f405bb657731c885a58392ebbde9fc80cccee2404cc8547ec00000000000000000000000000000000088ef289adaf206afd2b72c93049fca2cf9292bf6471133c64ac4f42015b97bb9a23f6c34653e0218fd0abdefa56bcc60000000000000000000000000000000015cb78c1440f74b17125c547fe7a37611f01b83b91a351664c696e0f647bd2db3ffead880b96a327780026d74c9abca30000000000000000000000000000000004d1a63607b9a5c9ec31168d85fbbee77cea0ae93e98c8c1dde14d0baa72f91042b2b7ca489958344916ce79bcf286456546fa692d9cd61895526282193c90148099e2afa54f7903a5431f932bd5fa06000000000000000000000000000000000ea6cb7ff6a7f4ec38ba11e9945eb406dbb8517585fef6cdd64edc970efba244b071fa162f7c8e184acbf71c5d1e12160000000000000000000000000000000001ab80c0dced33cac8a6a085efce71dcd7021f6255684bb631cf5c1716021bece57b900b819e6eb6f5b755b74c677b6c0000000000000000000000000000000005465fdd51352cbcd8b804cd509526c3b6232976b8278cec3b7db7da14b77f78898c6240c30943d1418462cb7a5abf8f0000000000000000000000000000000006b6caa6a0d5f2d671b10217c0ce5b3962b0c3edb4f2918497c316ebbdbe1a15c803d7fc3413907346f0e7d03920005aa9c1460c1cbb2a552e3452d5c5535868ee9c2952ec3fdb52dd826c16ae3d00bc00000000000000000000000000000000170db23154805a04013052a388e14b5da00e65b35b8ce2dd967213a74735dcbfd28782cef1ffe9d384be3ecadd101e9300000000000000000000000000000000082dea309092976408a379f1dbed9d8cf91f768e2921e49ece458859c80a1d9efd4d5e588470bd669c777d16f9d2e7de000000000000000000000000000000000adba8ef34e197689228e6c4e13be75b3d4732872c99b865ce7733b7a42034d6d4d7520ef7ab712f60f1ff87bc4d9d8d0000000000000000000000000000000005df0788ec39430fcd0625f8e030d917d8e7c251ee6e3b0e79fc6fa5f6fac2ad736c818bd833e58ec61cfdff52c9c6ee2c36204b6a005a64819b06804eb94c311d78977b557e7acfa82e147b4d6ec62f0000000000000000000000000000000000922d8b5db6e415aa3acbd0d6065db1b492c92313260019ef1bda0fa091c4bf091de95846af1edb34516b1abf7d278e0000000000000000000000000000000019af4ecc4f278315ed90d67cf4d22ed6fc9af5c0d0ca654f6a74a3c4bc98588bf5347b4536f36ca8b4750c18464f9b7b00000000000000000000000000000000021eaceb11638bda8b4293991983f11cc60c1daa2287f4b4a6066374bac82d117ac3ea4ec73afc4372d254bfc433b8c3000000000000000000000000000000001037fe26a10305cc5dc11a65edc705be5a0082656cad53e63038ee57a79e16075df54331233229a129483c34d6dd92ec9160c5a553479a10996704c3eda8e57be88eaaf5d1efc8371e7e10d7d106e4810000000000000000000000000000000011e63dc251a5a1e2ec83741682d90588b6b185365b33dba45458b1f56324a4900b04d61af155a0edb0bdc2971b7aaa210000000000000000000000000000000002dc1bd5448a2ebb9a02509af8777616ba9657bd3be65519233f0187df77c49fc931bbd3ec0ad5856b2ec0dfde476a870000000000000000000000000000000019f0cf8baf100451313711bbb0a0fa318c14224933897e74fb727b585cc8620b7d741c9ca2f0d3cbe14a8749aa48ef3e0000000000000000000000000000000018448fa9e05f87d4991ae1c248413edc9a8c3ee789c9c005e691bfc9003191ff469e26db9e42e5758fac79309a62942c5e5a50e5dbabb7a56897935683f80a5b16dbef3c23461e241fbdfceea38e3ee200000000000000000000000000000000109b71c19cd36ef3078bbae25ce6d0e8f7b58e129407fe68ab09aa747bfb3e90c04ab804fa6b7a223c172146fdb14683000000000000000000000000000000000d297750ba112da88beb84b8bbf74ed134b59fc9496da3045aa6dbcd97c68425fd68b75508de113733602a5565f4c8a600000000000000000000000000000000149b8ba6e05b66d07b353f46ace4e583bb61ed18fdbcea0e941b8d9805d3168040186d1c961add494f98e4e7fe68824d0000000000000000000000000000000013a6877bd46557d23b9aaf371ee5a101227d7938c64503b04b39cc6cb4e8ddedcf5cb6865439c9f8b1bfebb807ce52e24a95b293daa2761cc456b9667517f499c4d9eb9eb1d82237e7a7819b5d44f7a200000000000000000000000000000000073f440c2704fae6c86aca3cee34591ec03c362c2c5153a5e82c7bcdece2af0c58a3484b448c8bf4da851800ead959df00000000000000000000000000000000075a2c26372b482a2420bd3c9952fdbf9e5fea906dc8a4deb9691f8745372805bacd68a4838a3fefc381a2ce946ed1780000000000000000000000000000000017575b016435782cd09901afd2ea6773b11f5a983bdd19d14668d75362f95d055b76e5bf6966b1bd7bfdfbe9a939e4b60000000000000000000000000000000001569d74258298fac89d0d91a9945780f4c08d7af7b942d06255ae590db6e8509c908c16bd2c2bb634279debb72f489b5e22ef32d111261dfcb5a2e8d23c8d920f013bd9602bbef45e6d4e0909abdef20000000000000000000000000000000017180e36b925e2ce23c46813d96b919ca181481efb5d1666c4a4e9c8031abdd9521eb8228c4e3f16de0b33da4c73588e00000000000000000000000000000000138965bff7c573546d80ef7efb3d45e87ed20f59adb0cd7ae148d09a97da7feaf1b0ef2455ca19381762768a7d82f486000000000000000000000000000000000360bd29c3f07c5b560e2ac226112a628839da9db18b052991eb2d9c54541c1b5ade9b3c2d7f446ad50050531228120f0000000000000000000000000000000007105978bcf13bbe2bf5c8f7d165998c3ad99b6a2794c90f5b61fb7bf2472d307df8fc9f4afe7ae1e40e7f0eee8ef9466e687c0ac8fab70de2416642afa1553bb38183d2914050602874491057f78786000000000000000000000000000000000f4434c5180ad10cd45dca62b8da790cdb912c255c0f33950f7039e3885b38fa9e9297c7b0a875380545839d8c4d4ada000000000000000000000000000000000d0dd1429e512884ac209f788b5832d31649a78a8966d3348a93f841be23c8e4e42d6ff0d6c27e8f43daf495c9582935000000000000000000000000000000001307377f55dfed30ac1a406671af1895218a01d063b025d25bdbc53f5f9d535e4cd8053c09b2cebb25d3a08365ab8ccb0000000000000000000000000000000004f5c06f505ed15aa7661249b7edd71855bbf47237e049aa951e1ea3ff88f98591518bac975ac628e417892f8e9e5523428f1a27ea15135f044643dc36a3f9c2b4446a3136bb11f696b0a430a7454b3f00000000000000000000000000000000083336fa0b79691b4875ed27b2bbd2d2586992940356f6ae5ddd2021c5ddd87f07f0a5c1e8d8a2654b99182cc2233e84000000000000000000000000000000001880f3824f7cef95ae5743de2e17191848d8d30f0469f455461c6559ebc75a7afbc86dfa3ee17f5470f74018ec335edd0000000000000000000000000000000007c2b26353e86223e5dbd4ed6d59f1170b9cc9dc600fdfbc6c73b96f2c667a82128b1ae5af0542b11a7d1efae87c75610000000000000000000000000000000002427b7eeb497a20cf15c10513cadc9ea612f3ae94e2ae833d281734e7b5d1d50e240659ac01da7864a95b4cdcf88744ae21ad8a6c9d75b51133e81ec34d66ca70a52529c5c3a2307b0e8d6f1c5e7d97000000000000000000000000000000000e72845430ebfb84f8e3cd3dd418f6dc528bf521aca4f9dbd798ed903ef0ea3cf21dd1409aa3759351be32b21d8e8cbd000000000000000000000000000000001457ad87f0957006192dff7d99815c35adb3635815e5d157542b9f52f1e9f8c0143a21a3be4dc1aea3a895689f4a316f0000000000000000000000000000000007e8544b1037ece2e5a9ea387e0f43b72e895e9c2ca4d205f12bf6df0b35ae62a4d62756221d6fff65b928b7358f48b00000000000000000000000000000000012c5c3167f6ef118c4044c0aafc85a337d305437d694a7bd6fb406dabb7364d9e90d74a8b327aba971421a5b3dd5d06988a23b118179ee2c34ad030993a2d2d70375311b95254c44254a32508abcb612000000000000000000000000000000001995d7cb79da7b6c5a0c8ccc5ba075d8d6d8ed3cfca85e8ecdd2b589986fa58c4cd4f045983e9184d79173678d618f310000000000000000000000000000000000f9f7f6bcff0f6fd621f3f8fcfebac132b3f0d52a34af33bb9830bd714d2982f3cc6674ad6ca668131a5062e5589df90000000000000000000000000000000017699b298a46829020e0299ab89ab6411af0a602dffb0e149053ff40ccaec71a908da02c8e611723cd06c16a8e5c0f2d000000000000000000000000000000000523b287383c1e47a6f31d397359941fe0bb8167aa11604ff8569969eb5ccddf4c4f432d2b6fe6f39204020e850d4f2b30eac099ededf0087275d1af828bbf79ef7fb0e77179a068f2ebfe4c749a98c90000000000000000000000000000000004760120239593cae5bdec813735ccc99a88129c707686cf43efbd48fb08d8da3086879a6042bf118879fcccce0736bc00000000000000000000000000000000105b8191431f701b365c66680cb4eb267681ee4da17ba55d47cf26d21ba1c0c3eeeabcafcc79dd87b6457bcc91e9fec600000000000000000000000000000000126ab502f66e732aabe02fdb2f7a665a9a43f6b4ff21c22fa976e7e434b08b606e9cf0f02459fd85f5a80a332fb3a62e000000000000000000000000000000000b2ef01adea6c00250f2f14c98ec6d6083c45019f3d166419e3a137667324f80c34b6b72e991daf72e2eaf9985d0f9287e8dcbf708682225fe3f71b7a687da23de5ed188e40585be0553358012132577000000000000000000000000000000000ff22a0db4f1b1679bde5853a7c2932501f191f4a9f25eed968a796219cef028e26070851a9036a05a04abd73bd6bd4e00000000000000000000000000000000097e9310749f52a4b645190069f4d52315f0eb2ff9cbbcd31f1781a68b2664bbbf27166e6e74fc2be2e5b1eb3f3d77a00000000000000000000000000000000015ca218d7d128095bd4f4b4f7bcf7666e92b905e551dd22745bc743ad0783b6ac44b841f87d3deac44617a7c9a341c55000000000000000000000000000000000a1cb723a4c378e5db2775f4dde9a6887ee3313401a64130a78b90d65dda3a5d9c8bcbc1a0d78c310c869a7fc4889954532cd42a9b698a2c2d22b1a620a7ec60daa9d1eb8ac36894603be7bb9b5e37be0000000000000000000000000000000018b30cc461a4e1fbefe209a709a21ae201bc6094b2d15f0d6dee5a55dd84ef56b62ab1b6bd513b27c84c638291f4205a0000000000000000000000000000000008a6f2082d6d510b280a270c09044ad31fb18b851ad2b38859138c9c2e4870fba6b607f682a798bf21a13bff116014d200000000000000000000000000000000150ef352d494a97d0a7ffe44903aba1611c8d81fa2788c0f42a6db48a71101e12f07318da5ceb1f0af3aa10cd4c26341000000000000000000000000000000000ffdf3b133cc926684e4624531569bfa09b1658e29ad9c3efbd5e9d18353ffbbfbf23a2ad80ccee88f8fa597416d47173ccd5e19892765e549a63238e664c732af781fddea558a117cb927bc4a1aceb5", - "Expected": "00000000000000000000000000000000134f45e5409998e657923ca76ce92b7d2acc932308e0694bb22f121f8324d16bfce86f96c67111c8080289eada4b4fb40000000000000000000000000000000008d9063b7845ffc8400c0b7585e819043884f92e28f7e3ffa47a39e808cdbb034ef4230b6e19bebf083e939b6b686b0b000000000000000000000000000000000e95f8fcd6b5bcc9e00a580a99627d92fa7486ff5ea587df5dded24d1b0bb76d339f6765a5a2058a8e227f633ce36e91000000000000000000000000000000000393041eb33f2c63df3f40d8ea1e1a9eaa9eb0a46151294845e542054d503ef69b40b0b676b0e4f3e08f4d26c36a5d4b", - "Name": "matter_g2_multiexp_48", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000042a220276f12fb4e81c40ecef3a0d86634b4d1c0acfdc463df4e7501289f0be385e03808d44be053e6ac98f403a8a930000000000000000000000000000000004e3dc92e155aeebdfccaaa1d24f49efc8b02e4d9ba8500a5b953a96e0fdd58519bbf1c279750eb8b98616e6bb9a3f6d00000000000000000000000000000000086bc212a83b09c7361540349767896058d5567d4342c607ae9c07fe5f123d9aaac95ded6cdff0825edb5acbce3e2b6d00000000000000000000000000000000062598cd6d5680a155b6349cd51d636c1350746d17fe0fff5195f164ba2fa51cf52f8662f43d555f7be6bb8bcacca39448da17551b2369b723bf932173a9167663f8389d2461b763d6a061df78d7ff1c00000000000000000000000000000000193e2c749e5bbe87dd5c306d822740969cd69ad6e156c323d217c08b18bb3f97c85aad63aed1e3a455ffa1b6d2a670340000000000000000000000000000000012a3dce63a88ae32a746e3812833569959021e1dd9518621793308f8f11d04829b2c3d0e0ec39fc48dfb8285b6852746000000000000000000000000000000001235488d01c380e91872fc57cbf618c3531a6bbf6cba9dddb9f07168cd459c9e866e44e9e5336369cffd8cc3a36cddc00000000000000000000000000000000010d85f85d6242b63f8421e92f1c37f64d33fed67e0cd3dc4b2b2cb4a7fc7637f9e049fc959720eae6d1f452159d48b78def52379c8b9e7c24d971c3456b85b51a63ab03761ec66c8dfac1018833e05940000000000000000000000000000000010889825c752d0ae8445a1d0f3510135b9672c30a781788698f637c2f535e35788d76492edce8ea091223d016b5cc141000000000000000000000000000000000577175035c86c022e634ccc9a5beb96a36aa068cdc36e5a4fc2028d5dd099c5296d30a916d3b720f2e051e7d72e4d490000000000000000000000000000000017b46e49ba08a0abb9394479d693d8097a140094d0ef1d1ba7761fb601a686b0b2b4d49abc2e393a99c5cb760299992b000000000000000000000000000000000820f8e52c1b09986a70bff04909b044f671c3933de43a6bdfcbe3712310274ed880d7adc4947490c7de095ea651e578b2225be6985b9c8fa59a2890da56427612a4334937761e24a33d37f0f951a794000000000000000000000000000000001776b92f683069fdc006904fef8e91f716d9f6bc46306b042228088545f0e11a41b40b60722d4f0483250391febc0ed90000000000000000000000000000000010d5052ef2504115e9d9d4ca81c7080c0868cbed605dc7673f7f94f5959c793c96aa5334175e58499102ff76f974ced80000000000000000000000000000000011d1e719bb69d842df4fc23e8dc4393067d00f6fa8ee42d89b462a546414b91f68dda5378fa093b3ffa764b5fc63b1aa00000000000000000000000000000000099d0784a200e5d2d38773912cf1a49e813c871ede8c50da03abff58ec1943d2adefe66bd2feed1c57f5a80253e091d0a64ce8ad619276bc7a00cb49faf6cc84b917ae6b37654363f5719a727a220291000000000000000000000000000000000d7287adbe0bc3cbb35ab8bfe69064faa83e3e64d73a0c64d960949e10070081a99c35d1dacea5a3b9bf312745acd6e600000000000000000000000000000000034f1995eb8631e080378b22a51ace902ebc9da4589c89ab557b6aaf685fcc74ec1fcf95f6b9a31b7a45cfc5a1610c640000000000000000000000000000000009f56712a46c0fbc199c12d5eb7abd60e660e2c6d437007c34954c6234a0496ad0adf68cf759f8ea30980c9a78175e1a00000000000000000000000000000000073fae1cb78c776188190a4d7223f7cdce9a36488193dc06898919ef4d5136099c3185d352028760c753e9eebb52ac240b891d638d7e76e0dcb230b1f9a7c3b35b35193c43a6c86f345f5a5bc9c708f500000000000000000000000000000000019944fc459fb601bddf10a3a7eb55f34713d396c3208a10089b8f21f4bf0a5e87e95ccf73e0bd90474d3e043f37a72300000000000000000000000000000000158445bd2b6d396a390a0bd5e26256587f980eae84d7a592b2b4d788c452d312b854427185a770084e1b4c7898962e50000000000000000000000000000000000ba44a1b912645354da7d8d9c694b1d5a9ff2d642fad31975171deef3adb0f8d92b2d3a8bef6ecbe0b8e90470b3938d00000000000000000000000000000000012a040a72ab035684bfdf57bf473ff59cd1ee01ec949dcc6066e5c8afad775ed55123859cdd74c7016a092bade7f991b571175eb91888222085fc2dfe0f4401ed6a1fc5df86c0c6b8e44fba6454305bf000000000000000000000000000000000317ca8fdec8c7c56fa3812157f9ca8e9bbf91013dfc7052c0795a04a1b4649b2147d9cb1a61f2c114a705e5133729920000000000000000000000000000000012b893d50fe5ea2eb528d1a04bc8596b10d4714a0dc38bdd5f0a275c07c846970106c3f7b5686685f5c809e93c57e2ff0000000000000000000000000000000014f018a0d13c4c494f4a6b7e836f0f2f46c4b7975d91adb93616a0555910f53574add03b905000f8492465c9b5488c1300000000000000000000000000000000146eb4ef1103b525dfb5c31bcb98e550245732fa252a814824258093a2397d1489df8ca0228d4f5df0a00d473d1566c454c9e7f7ca14c66b8431e25e6eddb4f20507d03bf124eb607957ca2f43a0c17b0000000000000000000000000000000010e9962dc19aae8e92abf32fb9c8eac44d77f587159af4e3b3a080748322715a958d953d3c057999839a47dcc840076a000000000000000000000000000000000ccafa9761e654ba54a46afff51384f1c6331264082e23f94fffd6c31a1b1b568a391eac79417657f40ce2fc9a154a670000000000000000000000000000000007276b111c94130b2608827156021815faf2be29ae42c454f3e2f95de98d2f5b98cea3eb18335a8fa00e5464f8089cf300000000000000000000000000000000053550896e867e237086098f4493caa2520e8c97a05e14d0ab7012d37b7fbbd42a90accbf0fe2ac99e78ccf0be5c9c58000579e1ad83015c8f02a9db5c38d0220368a80b309ee45bb952cac824817b6b0000000000000000000000000000000016b5bca8537059362147911da9e69ad3ecd3b4a7c43ee7d6d809f46c74c16bc7d69bfb5d7c727b4d5d8a356a0458b59e0000000000000000000000000000000010f3a7eefeb3033a733af7d20c3c5caff4c409305de8d71e08cb9cefbdfacda41bb975c92c5e5f2952c3c1e2bc6ca8cc00000000000000000000000000000000148f5b2bd65b71184ba6974678f709c5f9e3f1a020e3d4bedfa5f5f66478adac47f06ca2626c4a759b5eae09756cfe49000000000000000000000000000000001301306d1259059b5567154ef6e4779fedf98c29ea967ce34b78147c5730f202e1c12d5b5094219bf85fa62834329b45909a45c8b78350e3ca21697e9f56d5fc8fc2a01817b78a7f5daeda487768ed1e000000000000000000000000000000001741f739459f5d462fc9ab55c68101a5a3f2741c05b4c3eec6959b2aa5e12493a19d1b33a9aa89337add642458089eb6000000000000000000000000000000000300d8b7988522706c0690da52d0a67ae41344e43cfa05d22feb91eb8635bdb970810e993e0ebf8fd63ab8fe3e048d660000000000000000000000000000000007c003cfba125692b88feba85e7288bf61bb25e04b1462f7a39b4198737010224ce4b73a320c81b1f70119af34d381d1000000000000000000000000000000000a4870c9de67517f4353de23af21fcfadcfce55365ced33a61a19e5de52f98721b17c6eb382970e7c4acd81b80a7bd2f6d4e2277da617f0ad530b6209df6264e1288122b1b4d92da04fe334be17bd8320000000000000000000000000000000002eef52fc72d5aa0456c13808ba548cb765e11cd0bfd0599544793f57c8a27ee90880e6577af1b76b3fe32c4e71f4104000000000000000000000000000000000ea99a4f6772f8114cfb3ae9dc20f11a34880a86088511e5b7fe521d50470148b43f866eb5bf4f67c523266bb55117050000000000000000000000000000000004bd802b889e6d18df7dbd65f39a908cf5889e14be51b5ebd423ccb63e4e5b35e429eb0d4f384b811b47975143ea2ef60000000000000000000000000000000018dded357c546d709beffff2da0c08e8059c720023234c7b53d0ae85750b3e166cde7faf340697b546b8dd7c13b1ce7bdcba6bed6b8c42240c01df5fa0ea81dd96168c6d98ee9d5d4653edfa5172eb28000000000000000000000000000000001405ef521bcc60c55f8551fb2e2aa7b10117b2f96c03e8535e5bff48ae197b7e5fe69a40eecd25a67f430ca02edcc9d2000000000000000000000000000000000477d85a7dfffcc5a2a1048205362ec42b268e5fbd27ee7c8d4ca77b5c9db84dba482bc4b164f92db2c15cc518b3d32800000000000000000000000000000000060988548ede00aad3682fe827d1e993ed1cf118bec7cbe6f69bc160f030bf87c299d40047a4fb5ee27dc2814649a4580000000000000000000000000000000006b9e0579f82fcb8bc149e40b1199f5897ea48ae5eb58abd2002c923efd0f5275d24a579bd904e49b7447c4a03e3fbe423d168e01657e5c2da89a27e513bcbc6620b8c6082bd39880619bfe2b3a7317d0000000000000000000000000000000003cde2bfc5a865cac624d9018c37c1b5746b5394597d79c171b25f84d5fdbc76bb90ba5cf9db14b3b8e62ff91cfd79520000000000000000000000000000000017596885262075e45db62ca68ee5b99d12223bd476e36ed4ddbf5cd56a0c6e9db5d79e7f95b96b1bc323d7c9fc5447d800000000000000000000000000000000018333858871dd41cddb7ad2f179f1f341b2ef20bfc7a1d3cb235e3a1a181e0da7251911886f0788e0f868e16520c5a200000000000000000000000000000000098ce44092980cb14e89faa7efc2906051c9a51cf7b2757dbffa49fafa3a9ba145f809f1212c27aa620bf062e839f83c2a76fafc5e8e33852bbeb7ab8229305be84f5474427e0c6d2ed35c7bfe99faa1000000000000000000000000000000001180d554fd523a51e0decb92e0134c6064a17dd3aa7b11d590b9b6022f76763b1e20562da21e836e65374efafd78b77e000000000000000000000000000000000488686f793dde899a3f4936f07f9eda7918450966ca85b4715d6fee978d9d091bae1b5d2d04943365c076a849b3359c0000000000000000000000000000000014661fb2d305ec9e63d63e9951d0f081aeba99972b094c922d2797a1100759cfe150812821411205f563e22f01ef29c50000000000000000000000000000000013dd681200608466853cd3bfd20f146a6383151931079654962684d6c6fc3bd6900bb049483c1ca6d2819da456f67e3be3c7e4e95167faed1391e269785918a207490c6d186bf2537c02e52e414d564e0000000000000000000000000000000016c8c7a2a1a76ec05770f2d6c8df35003104c034c76323fedd49663daa759caf2f4fefbe8d44b3abf1dadfec2a06cb45000000000000000000000000000000000837305004aba2e322ae29e8f0109f1c756a44b21c72733019e63ff9886a639464090770d12d35553f0002ad028332370000000000000000000000000000000005c8f82ca2d4f6785e2d76ca3a3d1ac67aedf78e9ac833c52cfda6289e6f5d7a83befbeaf753abce12376889caec312f0000000000000000000000000000000013595cdc9181ca70845c613663367ff774f073774688dc58edfd0c58de5ae12df5acd04a673b645371940d7f7e1601045d335e3d96a9b25be7f3916e92fffd75abeef5b91a1ec577ced52a96f6a9b10c0000000000000000000000000000000010f1b8b39ea8ffcb6a96bacd1c00b413c93d3f8da64dcf9257a7cf0264831be23ca63ab8d3d1cea21ed8d83ecaa3a0c70000000000000000000000000000000017a9030fbee573cb71330007900723f85e9e82530283f713f72e68c1d9a5ff9552d0da469a4f38b66e30df1514f922a40000000000000000000000000000000018b9020986a49213d4f3b4b052cf2fb65f82b9bc2051f20b399f2784b984ccfa2752ca576d352c7d65ab218bb8d5df870000000000000000000000000000000015a375a3711f5e9f85ad7266b2d307cac09ace9ea36e149dde5e0d5acdbac3f62e1cecba8be51d88f2143c3070eddaf0fa563a70780837ffcf9a84456f0b4f6eda0d60cce6a8538ba10960eaf17362fc", - "Expected": "000000000000000000000000000000000b668f602b9f56182b74be413d36b03d2266d7165386a7f1f0d25d336d06d2bc5659e80e54dc71f153883292df1cd8940000000000000000000000000000000013151d305bba39734538fe9a2717392bcd134ef1f8c1879740c8cce981a2d70c94b23f1a71a0596e7ead55a55eb186c80000000000000000000000000000000000e5e7c268f93d8a9d3ce45db2a95be906483aefa3831ed2ab2aa357eca0ca231927c0e5031daa200784cba33b96e51d0000000000000000000000000000000011d57d9a9123123f9fb56e990626346e5c76bbd1a4b3349c3f7bc44f05a899f9c4dddd67ce5a788f85b4fb172385faef", - "Name": "matter_g2_multiexp_49", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006a7946b50749147573991c91f13cdef4e9558be37736e3d990c5750d31ba9711721b88eec529ea4b1dec1c935fafa9a00000000000000000000000000000000078d8a565b7f58b915c220882a73b6aaf100f2d54cce2524cc3a80d9b526c3058903668d17427a617ea045c3322ec502000000000000000000000000000000000733c6562cdcb28d740c64f50ee9d204af4ecc8de2c1719fb73c20f2580fcf01e1e494faf4386764e03920a4162049fb000000000000000000000000000000000421365fa828affe963d145d318065933d4d865f2a3d24469ab0db66dd09a574945f8a8b622d079a7ce1c6fb6c795a8f6e2ee781da12b984e7a08730a60f50c41cdd7c7c8b3f1f30f721923ddc34fb79000000000000000000000000000000000a4fdc68bda287bd819ebb0a296212ddd19cc76b042e134f1637c894ad64bcd8431392c9791f2eaaf94f6c8d189846760000000000000000000000000000000009d974fcb46fe81d81d62b24b805ab5108c9450e162454c3260ecd0d5356b7c263be5f78f6214cc7254e461166910d23000000000000000000000000000000001081fe3579cb4d8a7e7d43ca8cdda28e1f9ea8df83c6069f4162a2a0e68e0d5876b283193649018e754c5c8fef101f53000000000000000000000000000000000ca4faaddc4d14a6648e3515a8b9028190c17f771c7de086fe4624a3008d7e6e374c967f303d9511b9da1a95409e3cb3d51e0b65be993ddd2892ab8f47eab78352b177be4b3fb68f47c65f5c59fa866000000000000000000000000000000000117318e376f2c130e5bca89b3d700fe76e9603adb22a5ef353bb3b5a8f641c85deb4640fbaccf94e025a59fbf2a41370000000000000000000000000000000000433428497ed89a43ba07d816df224809a827194ca899924c3844650a3800952cda8db82f2f8e513994ed9893fac747400000000000000000000000000000000064889f1cb7d6ab216fcceef7c4abf89be14ef93be2d39bbba2b74d06999dec5ae1941b507709d093b28e030700cf866000000000000000000000000000000000957fcb8658497802e78b8250373f77acc4ec47fa2c87e78adbb2daef70240da640a7945895940f76bbb80bd36b4ba24fed4dd284df98923bfc3c41496d6e64a10815a8c474275e0cdbc9ed26e92b0ae0000000000000000000000000000000013f9771c105462fb6b975b0b2fd20d0accdd2d95d879c8019b08db394cd785ed9f151d0eb1adeaa63bbc2686d1172b0f0000000000000000000000000000000002062a5f2db0a01114a1c6e8c739f80f598f4e905952101a244853078298eb443be6839b59d4f0c7745b739cc89ad8220000000000000000000000000000000015b5485439f1b94fbb3a8f5ac6197f0dc0577863f39c44b34d4c5437b6a82a704dec17529654b3037a9ee1ebf14c8d8300000000000000000000000000000000154d750e2a660205812d428cfe79aef4e1059f4e231024a665889d112af37e6e17e04cd7c926b6240bf2f616a1f572dd7c36ec97c1eafc8a20a772fb7887d75568047ea32458b9ce74ad9ca058129949000000000000000000000000000000000231223930956bd2d36a89a0a0a47aa46b4763919455ad3a3581439d25a82c176569698fd5ca2b9429793ebb16c98e50000000000000000000000000000000000b5dd675af51c18d2dc76e3103da4409f6e8c1cc719a622d4a33aaae3f23e529c78b63c55b67fa999bdcc7095a4ece300000000000000000000000000000000010c971be55cd02e4c97031d3b25acfbf722e47e5179beb26eafaa72d4bd5f47cf280a99e0c3c4cdac05bf1572d01fcfc0000000000000000000000000000000002c1370919e6445994df1e25ff4a79c8cd8805f12e5d8c781e58f04dff68a97424b35d162d875ca2b3f805b4cd6d1fa641b2c0354d2f7d92b05043f193b718d78b457ae76e19069c8e1c2b77d7999d6500000000000000000000000000000000169938b4d3c859f97a0627bd1a83fde725eafb7ab77b22cae06d2a776569236d834702081e78d61386999c938c0259b900000000000000000000000000000000091e922f00828488e324f9fea652ce1edff83d9f479e843ed4bffee27805a5025e7a150719b354b5e61f381ebd24d4ea000000000000000000000000000000000334ba8044d7d47795b59eb089502808a7ab8f18e3d5e1cc49acdb5020b3973fd21d6d82557afd748dad88e45a7623730000000000000000000000000000000002299bf949ef249b5057c103ecd149444635b4f636a2fd0d073484404c1ff4ef71820260ea6529bee6f5b07f2ba94de35615370a76bb0a5f64d61b97bdb045b9669f6a0b7644b101d21a50483d8b04dc00000000000000000000000000000000076ab7838db87727fd653a3b561a2a5594518f296284bc24a7d215b1fbc0a6492d425078fd98f92a414dfcb3c92cc1d000000000000000000000000000000000022b71fb467dbd6d9b130763350bd06f52d20ff2cbd46cdea5e8b1525fd73bfd08f5ff171f9fa28050e9a3b296d3e9e00000000000000000000000000000000007e917cef0195fc589317d4a71c14022867dbc0db26c653052e2e382d0dbebe67a0f582bc0a27dd1dfb4703c545d0da30000000000000000000000000000000005b1d8651b86a403ad993c5cea4b6b82a0f8a9f8a59d4b94f10e68e9538a559efdde2007736aa9d04f585851a89af88fbcc38cfd3c6bdd32ed1d583f2bd14e175d61448c627f195559b751aab1ecf7cb000000000000000000000000000000000653c5f5b2d97239821d173036929dc716e78d835a80af55868dcc3e218bcebdc2a052d31f6a573572d13f3bbb14f241000000000000000000000000000000000cdbdc3cf52239a6d4bdadc273b00924de8730c03ea82bd20ec1f04375daa4497fff3a1726269a736706355e72be83870000000000000000000000000000000008e0285b177fcd768d3519062177fa1314c4370f872eaf10f3e0dc94e716dc6a67894d887f40104552336cbb5ed614f20000000000000000000000000000000000638db8269ea4c2fecd5b45955609ef6a1c2c6faf6ee5a8d777e0b38f16d1acab2da7fe7b6f6ebb315ccb345835a21d94c41471a2e4edf0f688c2f032036d41ef5f8a966871dd099dcdbced8b37e1c40000000000000000000000000000000005b4f74cd099eafa6ae59e7105873d4a46e8e5985faf2d26ca564125dca93b1c48187ed7afa02cde8b52df878e1aa618000000000000000000000000000000000cda7f9eeadda16ef757ee8a98be147d374d3a1d40790d20a1ae42c9ed38e4fe22be76ec4f807cf93fff5c6efdb50d1c00000000000000000000000000000000121219b0b0d236a89a857c02249cc04c22299d041d95296dd235b3639416337f5be4a2ebe92a50d192fb748d5d4dca0300000000000000000000000000000000112545a4677ca7d60645cb8bd98689c4aa85a68bb62dc68c0affca5a17ecf0a08fb9b91589d08712b5af4aadf31caad2dd297b192f1c907914ef949fd27a5ea5659aab659b83239c4433f7a4e24529f2000000000000000000000000000000001342460712b73ca0ef07d953c32d280a3441e108abdc2d133265160608986481df3563c5dca20f209ce078b13b49707e0000000000000000000000000000000003580a5b4a7f6d6e066ad9073f7105f6cc1ff35ef5e79a0aba7f48ff2b732c7aec72cc9c5f9233fc9c267d8aa37ac17c000000000000000000000000000000000bb7f32db8a4e341cd9f8dd3b5677dc650cef675f0923bf2e5c8b84c33d447daacbf68631c2388eac5698495e1ad5a3a0000000000000000000000000000000015bf9cd1aa585eda2910128f2b452569abc1c94bc8bd308ee92b6c7315a56fc92d6cba03334bc36c137c14eb1f198b07d30fdb174a3f5c06b78cbaee5b6e7a4c90551083d78c5164de6bb45ee5de23c100000000000000000000000000000000091bca266255d692cdfd10929802d79b474706d160033495decd11cb0758136ec3ae7fd4bb99081e44dd7f25224e009c0000000000000000000000000000000001fbba1ba796416ac22c92f3741e3b268d89fbf0307edf0f25c7c12b5cd230c41582ba69465686ffead9f8363dc0c297000000000000000000000000000000001139590315fc4d81e3e747a53e63ad856635050367ffc143c1422e324d5fe9e4fb90631ff8bba764a87b8077b571aa0a000000000000000000000000000000000dcbba28afd445a57db762d08338a26980b4efbd11668e4050d18234ce35a909d6b563a5d3e8e72892514431fabf0147aafc42f7fe6854866cb954367fa65c8072bd1b60173a2d45077421d6e25f2bb3000000000000000000000000000000001322b1f1388a9dd2853829bda1a5120250ed08f07c84fa398e59fa2577454f38f0a76a1e8db897bf15b4b50ff52a847c0000000000000000000000000000000017020d7de1dd424de53992c168d924c42f26231d184ea3cd9cfe64ad9c82ad067540b2d9ab18b0fd28477ac792a80c4a0000000000000000000000000000000000fabc0769b95e6feedc2165bd6d324b7d16247b79eebc1f09d849792255136538e628bd6ad9b86af7bcdfdd991fc31000000000000000000000000000000000144f39f792bf5585f4b49dcd3fcdbb61cc7ef471e08af4c15cfebb855f0ac8d5fd057c9486e53e8e1ee4f66bd5e943ad106da5f98d5e7cd9f4a1c8d6e50ea2236c2abdf1e08a0eca54555a59bcadbc6a000000000000000000000000000000000c27ac29db98fe3038fe5f537d5ca6faa240602abe11c6f530d9b18d763d6dda3fb25f9538d316e6527c114405ae54f00000000000000000000000000000000017ecc872183413d8065a99a2d1a73b70150e2c1fca2c13a731a39b52aebc6db79772e91f115a63f7b23e5fa231df697a0000000000000000000000000000000016b9715ce820b619274202b52d7e7bee9a17aaeb06c2ecab8bc77c670bd4c714789e4478178d94d2aad57e7bb0b7a4040000000000000000000000000000000002d0723a3386248d8597d2b63289300de6a16011a38985170a1652ff81ea70a78459b3ef252cc5ed26ff1ef1ecaf6a42c971deeba2f757970bcd4f5548a2767bd6c43e63f4c5fc4b157ef060a1f45aae000000000000000000000000000000000eb1ddb7306d8d2858fb57dac71f67473b813f37f02d73b17f375be86028176cc1dd84347f183cb7d427b861be34c3d70000000000000000000000000000000009a8811ec77eb21f2b33a591f2fe6d7b74b40c5045ceeee275912aeec664838f332bb49bedcd958ede0af0d0232e76ed00000000000000000000000000000000156e28ee3c40c6f18c6059e06ac8f7b39fa23e5962f640ef3afce13c169346a4c8e5c2bcdac8fa15921a4740cc5a0f2300000000000000000000000000000000084371522a6ebb1925c8fad3f20277c34e657aa71abf8ed7d323a10c14cbbb1a9e0e54bace32eb845e6709c1c58afc34a5262a021977dd79ab96606eb24a7c5ed650300dd68bc79f4b8378f58c6eed49000000000000000000000000000000000be2ef9ef38a5dcb42ad31b1415c8eceae625850db4306a26a0598d4a567936d75b701c81793fa7b42d158df2dcb0d5d000000000000000000000000000000000851b82b59fc15b89e33fb618c56d11a07116ea35850583a07066ed97b8a864f3766c0cf921d007a6cb43931ad4fcf8e000000000000000000000000000000000ea8bdfa3c5f000d7cb1b5cd69537e4104daa15ffcec06f40a91b972d8011e5fccfa911c55a07383cce6760c145c39e4000000000000000000000000000000000652a4165602978004ef702103ef18e8fe7decab1522a76486c742d29103e3bdf6dda2d3cd64ff1b5d5a76f4823bd363083b3720c20044fa41712039b6e9e776197391ef393c0935a0e9990fbc1b7a4600000000000000000000000000000000015ce5b43e1fd950b77e2baccae8c99b82f38bce09989fdc5d402420e7931a38b7fdac5a254b0cb9bd8fbb488d02493b00000000000000000000000000000000018c5b3ff46a04ed114bbf56399738e5d594ef8dd1d5e2e8dc23a0097893be3da4fa4662686a6dac04418fd2d344e36c000000000000000000000000000000000efa3e970a5cd0c7bdef6a2df3be9be18cce63c10c331a18d628bbeef30488ef73d866f3c8804acb3bd375542e99eae6000000000000000000000000000000000e966d9e2f2d47df5d661a89fafb6d4518fa1544ab7a56716df511cbcca99098f944a981c9da569cf95debb455842006d6f846581848f5dbb9e8d220b881d0327c4f3f5d4b79fb2c4dcbdb9bcf44b02d", - "Expected": "000000000000000000000000000000000ef06b515addb951b24e5d61f6e6eededf5f93f9f17455e1b563f187f73394457b3b7c1b90ed454218f8782d2bc848be00000000000000000000000000000000167398608a87490fd17506166bf54636aa4dd6d3e8c4d42995bcb0262268eaf2a6d828b295434f45e3e53703aa67cdcf000000000000000000000000000000001602ec6519e4987a052f97eb222f505e241d99602c08ea9c41bc95796675ebf6a819aa0bf87319f29dfe47f45f3c8c7a0000000000000000000000000000000002ad4291ece7ea0fcc9f4440e88eef693b8dd53060ec847bd27d74cf71218eb6210a71895ff1f1f4537a901090f14de5", - "Name": "matter_g2_multiexp_50", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000129cc9cf82aa30671e969148f058a0b8d275bcbb1c8da66e52998d9555dfaa075e2fcf39fc18f305940fbc972cc5c0c0000000000000000000000000000000001252482c1419ad72229a00d90f1c09d464e896f47db91e9680efe36822e99e1ca7a2b5ba8b17b5929fdbeff8993bb18e000000000000000000000000000000001287d5054bf5db038ec2f7b7a3b79848fcc8ca42f9e19d5e21d36d2256f97e0edc2608d19c17d3714024e1e9e86ae264000000000000000000000000000000000f6262669e30a5db67550cdce8a4611b9501d02cd4e950aeedd1c87c4f0f63c74f35c802dafcf91c988a154dd690103c67c44f7c8513472b51f96d526422bac628aad4c40c521cd7cf9e86eaf92838fd0000000000000000000000000000000019cccd010df3e668b1c3ec053e76c46e45d01a4fe02eb074e296df2a48e0e4eb647b06c40cf64a0048a8fcc2b0cfa6100000000000000000000000000000000018e07bc50657f3bbf736c38518933e91af29e3bafd776243296cca3a1d975116e8b428b050045a61069adb23baa22d3800000000000000000000000000000000154f51badda1b828346986264b01fb1be4c7e9b570ab63a5eb15cabe9412a2f9bbc6d5111c638ff5118a4f6d08ed055200000000000000000000000000000000064d4e607a8994c0bb65770a14a14ed1b68c766ac2aed45a44c0f7c7cd4c3ecdfa077206812cf9b24e35021060a3668d2d6f95d4b6216e4226f78e4fa5011c9becf98fe45a17dfd740fdd0ef36d8ba94000000000000000000000000000000000b9bae5f720d9bd3271a71d751e4c35c39ad30fa8a67846107ff769c455e42465b2a39dfa32861634d5e323878f56f4f000000000000000000000000000000000a1077046cf5c7a66452cec2193ee21c1ace50dfd79f707c9297737f13806dc05e9e1cc5d1fb4c87b250ebea5a4ca6c40000000000000000000000000000000013e1fbe1a9b5f2ccff51120590ac0cb00cab502726b43a6fc12459e27bad4aa41537d6f3cc94a81a170998768f6a0fc6000000000000000000000000000000000a02c551ecec1c7a415256caaec1b5485a42f9ca8d897cf26546ace1f2bc8c2d10a353b8b84495b8dab5e3c60881185a58c25d36216b811ee42d0ba629ab7a0f9ce7edd7234620c28e37bb3df3f042e700000000000000000000000000000000021b9ab3ad614816d7006efe688e1ae8cd99b0c4437d4363e557642a7cfda2000db6503b32db36b6d1ffe40d967c5efd000000000000000000000000000000000b7fb0ddd9eb2be9cdffaf8f8c593a9296c4c7deeb1c714c11863d71dab1e6fd309b75c41e25de3cb6089726b43427f0000000000000000000000000000000001277065ea9d208777d0fb7a6726e11c8330f0b3ed3c6716acd559aab19b2fdafceca8126c9facc43b9d80534c07035a20000000000000000000000000000000015e8c12065d601dd5ede75bcfceb7300bf6f9fbcdf68d2f093b7654d80d3e565135d64137dc401d691a45fe052f58a6850a5c6bb6b87fbe5ebfb0d182d425ee173973c6f2085c556b0fe60219b9f3c32000000000000000000000000000000000484c4f9652427d0649c33e93d666dcb15bc56669c00980c53357ecee874bcdbaa016236df65a4339dfbd44e4eb0823c0000000000000000000000000000000013836a7275c29c989891c94e756cee9d6c54a8f634fa570655ee44b7c1e34137edc33323dc0d1f3a0218039fd6f7013d0000000000000000000000000000000002e88c7d5fd87e97a0de1be95021821942a8004115fb4fdd9ad26b7e0fd171f9c7e6f962eb179bdb95ef960cf9396372000000000000000000000000000000001636e351a0ed1a260ffe0d1355e6da288792fc97a7310b040cb9fcd5c550d85d90572154d58a9847dd5a8a06456bb2e43b4bdeaf6643ed159f4a3e23c33ac486b33e1edbc5a097a47a6c2c753e5299d20000000000000000000000000000000007579785c14fa012cb5d6c116d34dcc15dfc908a29e90de3bbfb8c9b44e0b4258644440d7c78d751a007c10f98053bd10000000000000000000000000000000009f023538822ceba0883a0e3454121dafe8e5e61d4754b54e6417c989efa998334641d458591b3076b615937de065cfd00000000000000000000000000000000130fe7f2d5e0ffefa67ad3378690c53a6e68de5504f3691de0df3a24c309619bd3a345bc2bec4dcfb4b77255cbfe09980000000000000000000000000000000015bf85ed997eef4d97a81f1d75825bb4409cf86b8c8e5f4368cf1e4c803f9e1e23a2a96f7b0a08e5cff55a78761ebce21d18596bc392dd0b71e1216bbb20a0e5e2559a46789c36a146cb78c5aa8e3921000000000000000000000000000000000a95597e4402bbd17c20dda088f0134d42f14443bd519b3511b28fd8d395a0e50758386498388ea6ad0e7634587336c1000000000000000000000000000000000079f348d3de505875c5192f795cd77e2f7385ed447b06f2dbee18e85c832386b201cb3eeb21aac3f258d2c4b0434d48000000000000000000000000000000001895b1891a08ea42eb1f68698abc20394ffd66bf0c32979668950bfec5cfc8425314eec2ac17ba25f29133a8becc9f5e00000000000000000000000000000000146160336d881b24c6258a3a86c08d346900680324632b6d5d4582ee0865a7e5f2d01677e5e49c5a4179f8382e49d1566fb3669c0789ba6a5b00f14c14fe2edd15d37a742c9e36cae9ac010e632d75a40000000000000000000000000000000013cadc6c394efb2f93e00f3976dde34efe75adff34bfb6f5e1a150b79bb5baf6bf29fa149581fda48faa68653cb61e300000000000000000000000000000000005fd25362d87f9581a202b186d2786d2859faa9966a1ceae747dd7a48749abd424eb9813e44caada0e456ee8bd12e99c0000000000000000000000000000000018e6b279e2b545acf1da29dc0504caa5982522546f83d4d3389e1fd6cb5328d4a167926a00ccaca402b3a3cdc67d757400000000000000000000000000000000089a9992a36b476fee21abd50977dfee01d7c91b24b3e26d7c15b2301352069dad920f0ea93a3e477a48029eef35605f06c2988dd6b8e9aa116eea4e1f63dacf100019844d37d163c047567e8e1188620000000000000000000000000000000005200b78dba7e423bc23e87c5937b464e97405f6461d05bd9d1d0fbf8f3c8e64a39081f9e43b4ec416198dc44db897e7000000000000000000000000000000000bdba1ed07c4a570359863a1098a73830818b3fa5b222316a3e0692a4ec65e59ca6b4bf5f72f8c1384e73e807d272d6e00000000000000000000000000000000073fa3eef473707b6aff37fb6f829f0fdb7ae808e85ebba4d4924a185c3656eb2856896307b671080347cebc32e958bf00000000000000000000000000000000076b56330f07cfc0ab34e98e2fa0ce4702b296a00f6ffee07c3ab523fadc048a047ccea7a9003c090951e4ef698d14e5fbf8322f706b1972f73fe4e22a3dad29c4ede09163561b2810cfc3eb2ffbc7ab0000000000000000000000000000000007252747c8275f87b21bbac4071c1826d166d14e6205095e5299315d6b6a85aed995f9ba59a2163ce2c51a8e60eaaeeb000000000000000000000000000000000460a000fe29cca24dec469ba5fb729edf3e443bb032d488cc99102a614a5251915267db003dbf395132d815ba78f262000000000000000000000000000000000161c01cb4d0942faf2303c108604babbd4cabf5d3d30c13d7db9428a445c7f72d96a7405e22e4e451058a94e20068720000000000000000000000000000000010ccf8a8ec4e6515b20e07057fb8cbecc5defb87480f3e32a1bcd0cfe239e00daf6a390c4815ef6b85be1f07a4c4bfbc4a46618381ba6b991b2edfdeafa67aef1cfea066fbffdba24db25385963326bf000000000000000000000000000000000e6cf781162502d2a758d0f96946bab887591b7c9ec9f67a1b0b962e74ee514e84c14bf67ae3c0a9ea2a3e472b7ef59c0000000000000000000000000000000001542b4e97f1e8a64ffd51ca43137b0660f897f6b3d5c6fee598fc4dd03932c3658ea55e1e9e73376e51df278ddd3a3f0000000000000000000000000000000016dae882ba240343e752eac68122424320d1acb1fbc4bd26c3983dd91325f25e1b1f06213e0e06c142997a13fbeca597000000000000000000000000000000001138b71c95d4de320f02e68dae9bb0de3e5b317cb596532c5cc18ca588cc8566c21551d7d55d685591126b9d9e466455cd05fce871e4ff11e7a4e834061c65a0aab7bfa8a0128d460a493337c6e63ebf000000000000000000000000000000000904f6a09f3a5f5baac902c702b059835737c06f62c2ffe9101bac32f854e4d72f74031f5410a5941612b1aaacbb50920000000000000000000000000000000012f39e7022150b2be12cdd621ae23525581405021b21cb9e55972724a22b1aeb2e15b135ceade132d3310e050e607f65000000000000000000000000000000000a92b1daaf23524904d74c3f149fcd2c98e3a4c257113533e7cc59c4656b785aacbf0ba6b9df0dc17cf7c25f1ca698c5000000000000000000000000000000000a20a5d7c0aeb16ff498f46bf05e512784d120b9c3c8b2877411852d7da3abde9e83a6d00213bf69ed88bcbb051a486daba9e37ae0dbb733af820743d8e307fc02a3ce9b40032b16d0e9466903de9caa00000000000000000000000000000000153918807d7da07ec7014154f00a558ebe0d5fb48fba4c16488d61a826a1eec28e3828d6744300c04207e8ff1cb61211000000000000000000000000000000000a755480457896c5a3fde35658e73fae821151c43fb92e9ffedcb05fabad37cb68aa24e029fc33a2518398d723c4859100000000000000000000000000000000148798bdc5b14b90aefc38946db93be1754f15d78762f38971b1e64a53fda92b96b0a70ca2548baec882887ae7f636910000000000000000000000000000000012299fc413dbaa77cf8867e331bc0602c4fb32fe44a150217de9e6391374a9ed83781034e5775c4933e13cdfffd25a9e6ef151662cba4952416eaadebfe5e0fa0ca1d31380e1540c2d5e0181af9e317c000000000000000000000000000000000fdfcbcce1603198fa344487d2d4838b3ff23fc0a73a76222707d9f8623f0b87dfc816be8717b0b12667bee460ef40f70000000000000000000000000000000015036dff68139419db619912e2d19b7d2a2d637fbb8bffcd941aefe2eb4d24c1f7dc32f4f53d4cfce67785e7c328d6c4000000000000000000000000000000000fd575be9bf54128a9a1cbd366339c993ced315a840d60f8b77e035352bf705c01a9def713e8cae3001dc1062cc0723b0000000000000000000000000000000004015ed456125cf0f46fe0093b81ff9315d955d470ad756a9303f548819f339e137305c58e6f4d8db3c8bbfab90718d4f0a3851bd52ca52919dfd21efa6efc56f6dd5060ad969360b1a731e8f38f0f5d0000000000000000000000000000000016d31e68cfdc5823970c8c2ebc53c3d4517792c44e90c10f920a819e72e4a6966c59a691b905c8b0b612065c56d86ca40000000000000000000000000000000005096d516e416fdc0df552c2688c74f1c067a3e5e7fd782479bfa468096e6ee3e601bc23d2e38ae7500325765483250600000000000000000000000000000000092c994e9dae287bb6450607a4263bcf6267f0f66ba3e63436292af7f6bc8e4ba794a12792b6af49ef59b5fe50ff6d3400000000000000000000000000000000175a645988f33612e969e1d91b2c30e47ec655ad655d89cd8dac151c3bd194cd5a8c28b498b1cc2f2966b7fc37cfc8c532b41960417047a2258b6e9e228f3cc1130b296cafbb75f58731a81fcfe8c83a0000000000000000000000000000000008d09ee15c80facf7e32b15418fefbf7e80400acf37f2a1bc6ced88b1591bcb8f86b45b544646c5fafa71b5b103b927400000000000000000000000000000000060865ba68ed8fb3d0a05779c278352b22d4244edb7add23d985a2836d2772dbffc3c82c3134916e9b0900c9db6ead8f000000000000000000000000000000000dce53bf8aca1ed44bee47096dd988689c1e32e1e65a5f8dbabab7c4edba866132ee2c036aba5648d0dafa9a26405fe30000000000000000000000000000000003319995785be720860bbf48692d1507185d898187993865648ded74d3aaca45df939c6dd986db42a51bd13579a55b8f71a6f7f091a6a21dbfffcec2eecaa22d05252b60bf91b56811a833dde3fcfde6", - "Expected": "0000000000000000000000000000000010643af30c3cdefc30144c5d7cab17c9c54adccb3294ae79fe5c69376011c159be1e43940640bf5d9012ccdbc997e2090000000000000000000000000000000002a22b08904ea9ca99103a01caad745dc2afb7b6d23e666770e81a97031de921f9d4d1c04fa941c433b8cd9cafced3a10000000000000000000000000000000010808e5518eb6cd61eec8820b9f279dba2423b1a3677e21fe3a0ca2ad49fbab2995de1c5adc9ac867de79e3b40ffddf30000000000000000000000000000000003ce1270644d71e0055345c7463d72dc119495bfa04a818dd398d944ca46deb0aee8c7936557754fa18225522fb79564", - "Name": "matter_g2_multiexp_51", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000059234bb6d1b66985b79e6a2c6cd158d37fc50ccd6e50ad2fe3b6a02ae2ad35b8b2be92139265957ea698441e780532100000000000000000000000000000000066adc7083a7f3dd75a8e431a36632dfcecc2527f261e961335bbe8fc8329d992880736bb41fffe41484f68c38fda61a0000000000000000000000000000000006aa0794c27d3f60debbee292c28b430c159cb2874b9467312cb857a8777058580f8a2d3b9bf4b8b732edb185cca6ac10000000000000000000000000000000000d81f222ed6acdf29437adf26d2b785535cd6d61b329df98be04114c3ae68bc6854e275792fd48de3eedf6ba7f3849a2e56b63fc6ba87cf021c2f92baec248756ddae0a4f070df840db281283a4c9b20000000000000000000000000000000013dab8066757b8bcce2c9965e600c31b792463623cd5561f7f6d55c5a52c22efcbe48b8684fc2dca87e2945765bf565600000000000000000000000000000000198a0594b5e606b18201fe2706bddffe7bee6c583147513333230715d18295714055b984cd3ff8d1127f9420863e3a67000000000000000000000000000000000ef77ae1e991daea1fe8338cf236ba959b22df4b24f00c6c01483b6956c609b805ab89712f80892bc0160fa3775907890000000000000000000000000000000004d30f5a866a100dfe469d4d0c47872245c4cdcfb18d3ffa0de422691044b52d2b9335682dcbf67aafa9275712ae3f5512a50af55f47fdaf176d4885e4910c54428c8ef433ea0cb1d009ea77783559470000000000000000000000000000000008010bd5fb5e222618bf4f919c203dadf9a7b7597bf90e16772020614481a0963a8e8b1bd244661bd33e0d147be7663c0000000000000000000000000000000007e21f548efb869a28d6fe39b999ab7fedae9cd6cfa531fe608476ef30c8703951839476811838608dac1aaf9cd87eed0000000000000000000000000000000006cc674c464f80cacb2156fc1eb680938cb38cc166a99f72daa50f9d2c40f10ff07e447d7bd5e59b6b22f0dc407dd8df0000000000000000000000000000000010b160c58ea82bc3904302b1b4fe83d1883efe3c8f52c4e05a3d8681e604eabb1b7f533e61c51e9a172987383506e7b189a012158b3c18e19471fca6d5aba5fd004a337d49ddef5db177da187c8cf1c8000000000000000000000000000000000d4f8372d1138489913654a7567735be1eacf8c7fd497c2216bf77a94f483bd4a7daa2c8232581d6815af9898a7569b80000000000000000000000000000000013676a1f72cc2ed80fa24f70fe1c52aad9ac13ad6cad1f519649fda6ea3787d86ea164d9ac86de96436e9db4fb4aa44f0000000000000000000000000000000003f7644f7ddc9276ac36aea5c36451f3d5d6e4c508932b16d5677977108f04deace5e8cf0b3b3dee88c328b6030f3567000000000000000000000000000000001953cf03effb7de9e62937572850e9fdeecb74fb4aa655de1abdc6e065920e6d2e51ff28880f33341443b5e6652eff4827dd109f6df1d9851dae28bcb9e552c6b1e1b2dfb331aa955d3d0b6c4862253d000000000000000000000000000000000c76a5bcbd2a61172fdd53b351d143bd30d460e398c9d4b7094a604ab2c0d46d6112bd8a5483c9935f0bf6d84df04b9500000000000000000000000000000000116b15825b780c49fb24617dca620e939e2528e10c49f34971736c82cd35fd3965088595deb86eaca3d3239c6c78a84f000000000000000000000000000000000a0cdaa541dd96fefd46b303b88f1dd4d24257b910a596817f1d946873cfd60ae58a88aa687ba573832331e8fc158db50000000000000000000000000000000016259f7285de159a2c6d6d8687ed348ab97e8cf329ea5de49b6d708b6da5b806bd012ca3641c50f479d85921e20fbaefca96785c1ab66cc5c8e434f59cc1ddf76bd78b6fe660f7cf74cfb79d7f2c7f84000000000000000000000000000000000797e815a98d362e1d7e2ac1fdcb477ccdec8ecdf340d7bded36856ce30e92b661669b38ecbcfb0896b2fd75df9b734a0000000000000000000000000000000017916c559db6b4b28b798c2027e2c70ba1b940212df8a1649b9f6087120660d698bea81258e2007edd4aa7d0d535bccb00000000000000000000000000000000167170a76db0783a8c3228f8246502b15d342b019fb44a46b514f4ba2de3ac66e435941adc3d91874371561870ba87150000000000000000000000000000000010097a585eb9264ea96904d8534820be185d8d9e4b1616439a926c0ff8ceb6f2bc082e5712454690c9c05b8018a996235aabd1fba36142bd768339e091b15b7f5b4ea609b57947a7187c498bd9833c2900000000000000000000000000000000025eff57e1f37903056835d1b4133ce064c86947f35859817b2cccf1a5c3923ccca766b3e0affd20a4a6df62a45c31000000000000000000000000000000000011158fce4ade070629162b2b6cf1924696f1f7776f3d623cfa3d54c66fc17fa0299c6650b709a1472262fc0abe8d9557000000000000000000000000000000001828a65fb90dcebe25413566deacf0677a3993b39d68854b264fe7807097fbd3106ac618545d3a6a42e197c65f0d2a7100000000000000000000000000000000045eb8164b6ec874467286dc3626fad3c01be61f6a8a88e5f88797978463db648a9b8a1e1a2589364ef2879cb5f75423fbe608fefa5472c7d1611abfa402d2eddb1e54542f45d4012db8ac6d1e5016100000000000000000000000000000000011847bdf2f67b40aac3426716391da488a8f0462b68bd35a8c1c762591e2f426f48f979a646a094bce16bc99cef7fcfc00000000000000000000000000000000092d61e408120b1549fc8d2174572eb7ed3f679327cb89754f326fa72fbff79e98cf5ad9c94c14dd86135e9aacc98b98000000000000000000000000000000001440e2f4ee2ba254a780a31b02babca093a38e5a1ac09ff388080b6c60918ae5b26e1c0888ea0976527ba103b257d02d0000000000000000000000000000000019797e49808b756128866fae0d6aa7e755a1d6f07f7e6a877bee150fe9adf0cfe612350c5a0e31d68cbeed226fa56f2a28d57066cce439d8d0385f647ed5e9b29e8fd0528c1ed8455f37dcd81f4b62240000000000000000000000000000000016d723a64ee06a7a631509c6e64b1c8bbe199952da532dd92194147bce9942cb4a76f2358e6c7d263916fa36e2c0c09d0000000000000000000000000000000003d04ce655cad1d63748f6eaa9912d6474a34820986835f60c812aee9980d3ebc18d6fd856a6de9546be024b2e95126a000000000000000000000000000000000ea840bd7f76f8e944f95146cdc9692d97e6a2d7d16d4a7f054f81888472da4d60ae5faccb72d3a05781b399536ccb1e00000000000000000000000000000000155a1c43c39e9dfc6d96e01c981662900fadf1a46aa1c2fdb70bb34e94dcbe86c4f255e259c771ea8ede50b388ceb2f61208d8d328014a6b2c8b2b9edc70589cdd63d38f4e70abb41cff1b7693bf9a290000000000000000000000000000000008f189d97f7d82aad87fb71d090a5c99d94079c0b74beb3dc860d440c0f46727fc49104d671bdcbe5b9551552e18afc60000000000000000000000000000000010c4edfb64b8932a617c316820cd27d3f6ffa89b471949362762af8e10d25265b84ca2aafd3b14f33c39a4b533da60d60000000000000000000000000000000017ef3bb919b087fb6745bbf115e2929394fbc9c89f65e7d591f15da93ab785aa6828ebb6ced99d3506810647d28ed814000000000000000000000000000000001591d8213ab349017cc93f1fbe6aca6765dd33ac1f468621e2c79e30aa73bd7606a0e5ba1d97ff03e0029dbc8ab1c5f4d3a2044ed4f938c17684413625bdd281f685abea2e375bece77c03d697c82cc20000000000000000000000000000000019b3a2df3a9571b066eb451e34d8a38c0d90b6e365862bcd92ae76195956c21c59441f0cd03cc69abdf4ba069759b87f00000000000000000000000000000000082537ef7f4bba5f32db4443abc8eabceef643b0878ef83860d75ba508369a3b459cad96f1cfd872df99548f656b0f9b000000000000000000000000000000000b2fda5ba0c405c9481edd598181ed8a59a8a18462508af8c5d66988a7a58a5c9635d93b5e0ee310bd35e0091fcd4986000000000000000000000000000000000af7e15e0052576f82e36e7e2b614dd835a290e05f2ed9dad7f508b4c04e8d437e7e937a7f4c88b5e66b06e0beffc4df7fd81e27a577b5e79929614c069d6d52146a6183822d25cf1ef84d8afcc1f6b40000000000000000000000000000000017a1d5add5601010d138263b4793149a02e8f4f7cfaafb69fde7b843a51cf5f0634e26b6e5e3315420d44b0fd205230d0000000000000000000000000000000013ea863ebe1b1cfcf4164d78dbe8fc809d2b82ef3e5a2589ca1357e48dddf2696e910a90301ed910fae77a1e462a5b1000000000000000000000000000000000012b40d9f25dc5a61454ddf1fa9c38e87eee60e55938b411bff9cf2161ebd7d3fc930131a198e7e97dc90cc245164e7000000000000000000000000000000000054f19ed8e2682caeda10c252f11706e7f3b65c81e7ae0a617469babc5f3268fe5c0ce2e85d44fb6731e8ac132b97c3ac5d47ce35d4ede84a83c9860322f582ec00c872b4b035d5d340981fc29884f13000000000000000000000000000000000ef0378945ae4683666099be36de3e60b5bae9c3137b702e5e4e35afd5c1e81d033c3d6b1debf5bf36bdfc4e3af37759000000000000000000000000000000000c37074af84ff596ff2c7ff963d96968464d6c8d88b69af64ae883457d02ee9ec80720661f39019230a6531a0f2952bb000000000000000000000000000000000454e8aaa2830f07d86eac7aca1d7589fb06aed646146a1b90f4959b5caed73131ab231313b50c15213f89566ed87a3600000000000000000000000000000000143516cd7a1b8da41226cb828887a0b3314cf4f87c207d1d84e9c49f0f7e548ab99e635bd126d49fd2e4dcea98f3adf784ae256d47de2d49b1e755cb0e972f3b614f3e7ba779c65ce175ca3811021a7f0000000000000000000000000000000019384e15a8754c6d85bd298ed550a26b51b714745bf2980b4920d6e73f59e657d85d3e86baa9bcf7e971233daff99d02000000000000000000000000000000000229d233d605a1a9f060605ae366a263594d8fa2b7797358ffe4c62431b9718d155d24d80bf5af1c806f447b92fcfbab000000000000000000000000000000000bbfb66cc0c7bcf251141c540f712fe9a359d1ed36d228379a1f3791991cccb7dfe1a10d40667ca062cccd55c9e6b08d00000000000000000000000000000000150a4d7a003cb81423604c13d0c5175183ab5f459b96842939f5c4cfbb9196db4667bb4382d2d5c92b70800adf384569a09d0136d4dbb3abfabcac55db48b1ce302067f413283fc1a21744f1c16ef7b50000000000000000000000000000000016352fb8e2751f126fd0f889f2a62a85b95c50d6bda7704112e4487dc94417218b0daa1dd6b998662af2582c44b011c90000000000000000000000000000000016bf4c60eeaca103c90643fe0969c2c261e9697ddbc02279f0d5afb5c905a984ab2396db93555cc2dd5682a1525446d00000000000000000000000000000000014be742feb1215cbdcde21e974c74e23c7bbc2cbfaaace28cf1d4f2b5a77dde2f3910aea74bc200277e6fe0475208057000000000000000000000000000000000bf98dd3e3a8b13e487d8b1a35615b0c6b0f514f9b8da7d6402586f113974c8dc9561db797a96f4f8040c1765518d175650a6fba1a5eace6b455ee780ff266c324f49801832640856a80098f0eed0b7b000000000000000000000000000000000362935e552dd01b5fc5a15a76faae937d7ad086b0a67e9cd3558287274106623deb85b6410bb4e64c424d44335f3b1e00000000000000000000000000000000096f23a54cf57aa3306df0a0a4f45aecb9b09bfe83878d551a59c53e18efc5a9f177cb7fdaec1648f66cdfaebb15c61d00000000000000000000000000000000135271fbe0cc0987e82f3430eefa8e3cdcc1be4a441393bb3fac0b8e8f78dc47ba2b833d9dca4277bd60befdf33275cf000000000000000000000000000000000dc1b7512fa5f9d4ea3f4229d947f43d7dc46b7770aadbd7351b6d48d525d0144183f2c84293c63c68d5262851401ae0282cb1f8f6d6dd81e7c49176503a76837a96d7f2b084d29d11dd9c6548cf0a57", - "Expected": "0000000000000000000000000000000001c11610b63eeaf9e00552a230bfee290ea49bf9c93cfea1b6f684c9b5a07f341b718a0070534e0da9e6ab1239d800830000000000000000000000000000000017e8107113714ebb1743c34d83be3acde096bfb6cf140e943ecd0831ecfcd097f58d25a45005db61551a01d9da46de10000000000000000000000000000000000c2eff6c7c25885c514aadecb8f0465a0fb4385eadffa082e8d4f497b10df2395be5e7760a87bc26772dd78701146b730000000000000000000000000000000011ad4e20f5c1518c72f75d67a897f30100dbb83365ef7729c3501c6f266d6002edcab8c8bc1f449c30ec3624cda13809", - "Name": "matter_g2_multiexp_52", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010a26eda028649789d9e01232884e4e5a6b8e0b17169b9d64393e2568b09ac4d3e61a5996108655c24e76abe9e3fb7380000000000000000000000000000000015e4e36bcad524f8aac7f909fbb884e879caa735f80fe9890d7874be919ee727beb2a074984c047dac1d02b8712afa3a0000000000000000000000000000000012458946f1e853a7a45861a92d4ce707e5aebbf69edfe69190c0bb130141a10869e2a73e06785b568248d5b1f647e63e0000000000000000000000000000000004d8061f25edb5a510a2db9e1df850518156138c78ace50f4c9ce47734a0b14352f5283083a232602a070c3ce94c7bd93d7f8fbaa4225f3008649eebf42315785ccda2b9ce922170e606876881825cb90000000000000000000000000000000000baa40ea518227b007b9714ae6eb5a4e92883dc75e6328caa780bb2ffee7573dcd7e9ac47821ac449187569986bd2980000000000000000000000000000000009d43d61f070ae308c5c285915600dd9c17b7de63cfeee6fe33c9ba857b3c72e057bcb4d4ac2b492797e7d785997c18800000000000000000000000000000000185215a7fefb96b3ff9229cc3239c3ce5202a97e275ea9b1541d7bc0a2931d7e3b01942febb45c6e96e66e3605744afa00000000000000000000000000000000103ae58b8066dd62c46c14c593c768fda91b90e4840b5560c974ce69b86bd6d2c13f689b72cf9619e57c9dc8e3d3fb15e71e6cb3d4e19f4a70a4465df6eec6326f558ee1cb99aa540ad2a73c363a133900000000000000000000000000000000075585f862c0e0e031efe12f31e159f2a8b89825ce80fdf65906474f0155f397fdc666292f6a7384cab790f071335c49000000000000000000000000000000000eba3d37a5cae738ab99ed9475c2c7fbb88ff54edb8490017162dbb16c8225102158a266fd4ba7570ee6d5ff6cf3f5d400000000000000000000000000000000135a0b0a38c036919f8389eb7bdc505a375fd75d513eecf0cac134645d60fb6030a437ac6a0fbbd167b7a77a927b3b0e000000000000000000000000000000001688fabd4ad751598ca036ec5ef6d7b314980dce7d8652163e89fad01b233af64defbcf352743ec478af42587f58177dbdb2b3c3b8e91540dc2724537526fd8c0d4b85d2cc20323d71fa5a4f61b3f12a00000000000000000000000000000000062a74a9ba0e2e8d95fca478be8d18fc716243b1faf7365a55387fd7188021f53bbe780e973e7d16c9db236faff176cc000000000000000000000000000000000f949be3fcf9b38995624570fcc9e7df9964d038eca189336ec39d9e0bd05148ff7df0b48436a2cf6e249e52248ee8a40000000000000000000000000000000007472e7c366419a0cab844522c46356acdf6a12cffae941fae3d3b78e7a83f0446c945bdf7b247abccaeeaafec49026c0000000000000000000000000000000006a564e6860b97feff368fc9a349282112e591a7a6987fd10a2d4de8ae4384ce229b9db9a93445f727eeec55a6fe5a9def0c8574167a3bd3b794f057ed01865ea69c38023dbddb0afdc55dd9523ebab7000000000000000000000000000000000c073d2885eb125d3e7db48127178bea2c5bb0f09eec7081f15bc6fe6cba156914fe1b1fea6cf14a21a328d831523ec300000000000000000000000000000000010d93564b2facde13d29dac198c5f5fa314a0398f30c6fb7fc9575bc83d4e97edcc1c1d34f78728729442777718f54600000000000000000000000000000000136a4ffaacf0b4a607c677ed343c1ad41a1eca49c7c48fe73ab2f74084a07cff18f07f54a7f8ea1bfb7fa3667863bdc8000000000000000000000000000000000fb0c007a907ecdff7bfe2242097caf0c5001124d112689a74544fe4fd85be9771632e7267a1cc7e9f66d7e4bb4c954c3ccc75501428d3be8bb469ed0f2df7dec10e1d205e11a907cc30c4a76eee3cc000000000000000000000000000000000032bb9f20fdb19f578fac3008396f5dd0a70860f77f8ae7771fc6253569d47b72751cd56bd373dbc5eadf55b99578861000000000000000000000000000000000c4a4bfb5ca6f9c1bd69d7377c6da405afc3128338dfddd9aea19aec5e1e0f547e3febd28445af5e27469c87c4ac15280000000000000000000000000000000003b551547af253d07625028db4b9a8da2a857bc925620c5d561bbcd3e063eb460d9407cd4d4813800551e5d0d23a2ea40000000000000000000000000000000006d5c69a251e9a042c66bd4ee92d4f3cd4e79704b1b215c15b319e09cae0d798eb201be24f407340dbcefcf2cb87da5ae5e403f555fbc800f1342275f18a73dbb679bd31873ee87617090912a52d6a55000000000000000000000000000000000a5802e388f7605bbacd0bb65ba96689e223379214fd7a92de9a313f55d66cc71ffc9ab3f9979b75edf55647ad3b6c94000000000000000000000000000000000f86f968b5c20a81f18074803e1ec55ebd73bc87451c48d5bb61604ebae46538dcc9d21cce062abc07b4b9e89c85bf60000000000000000000000000000000000f9fceddfa8fb5bd76fb7c8986372c32ab9fae3c26e9fedae892bb55178fa2f3432e6eab5043496dcebef46b20bf5824000000000000000000000000000000000dcf7a118881aea4e6a0e4e305910d4e4a5f3d0a8800f52659ac26f122bd63c8aa2c5583f1121275adc9af1800a007fc97ea57a38598204c15bf65e7270a175460510848540ca4004286f3ca09eb59260000000000000000000000000000000003ee0ba2b1de438abe66769124b97a951ce18aedc8d9ed005628aeebd90efd316e7a3c60cb5a103d6f72e7a40ed8f44000000000000000000000000000000000119597c99a7a16d8d35937ea15539089741363153ef898d6bb177d9a9b6c5bb4b79728155eacc5d82571f398ac6c32a200000000000000000000000000000000116184ac845a28c4f96641ec19a07e1f8326bd45e2106148f40277ae6fcf200d64e326915cf5c927222def8deccd4ff8000000000000000000000000000000000f890258e70b973c0d69492b2e7d10ccb3997798503c0943af4255c13b3856ca4007b18cb9d638d5d9cca71c368cdfccc54dd8cbe68d5151e4428d35ec2d5b5cc7f5e455207c0788a695c2d7fff6735200000000000000000000000000000000171035755bd519af04efdd477d407267c5a8108bd32dd6d3f1b9555f15f37ce7598c096fb5301873809f0c000457a4a2000000000000000000000000000000000bd35595246a8337a426c50c02299f297036f710b0979c7f981c6909e835c0d9556cf64e2676baf952a787e10d604f210000000000000000000000000000000006600ff240aaa026941290f49ae8968e72293ae7c2af0df1b4ebb9373199b95fc91feedd2782ce819440286aeb2388c50000000000000000000000000000000015b2bbffac097c27944143cfb22e38ff8e50e79f2336e64c8496b0b25892834efb18a765e26f1408df1d64f4b9b78fb947ee5651c127d7c8ef65ec68fcd97d1dc228bffb5bf1278aed3eef8115a5ae72000000000000000000000000000000001064bd04edf96a3c76d2ace669ff72ee5edd87d32592213cb5a6a4a482154c1723bc19c7c530d164c31626dbf758d43f00000000000000000000000000000000176ac06390e3629bdfa282bf825c0bca9bc4e0b8fd90fcf2d4ee456d5bcb3ac2882d8406d2fd59faf10c8327b1962124000000000000000000000000000000000b58fbe4e14ee0af03d9aac4131abfaaba43c7cd92d530802516cb67343b382a6d2af9399d93b43d6e05f7ec827d5ae20000000000000000000000000000000000bfd241e3180cd5ce9de831b24ca50db23685bea7e008be0c6ead11abee338618728968c25a8e5a916cef8aa516667214ab6a1d0d3f87e7c9df0c14b6fd2f9d0cd755d5fce5f40bdc8174790901549b00000000000000000000000000000000183ccf0ddeb8573923694decc02b8f02162037156a8f6523ed178c13113d094521c3d9257febcfbd8f15acfe3d5d5c27000000000000000000000000000000000cf716097aabb07979ee435cf57ae36a3034283eeec0771bea24c9a1a15ea106201af8606d3fc28ad8ffbea2cf274458000000000000000000000000000000000b962565763c4cc155b2d9ea104e754e5fb4745303240688fee7e2256fbda82dfb515a51096be5ba0b111637b1a25438000000000000000000000000000000000df04aea745b9df2df0e34153269958d3640c1596fdff3fba696801c96371420a3619c5ace9210af7e0de4f408b09a7729b12cff5a72f27e15032844fae50e3cabbe31a69568bc4b5cfa884f62e7e204000000000000000000000000000000000e6be3275371e533a676f8d075bb2ab8b0216642ecde13425bce4ffa8ac51cb1b4c5c789d82387f5355c27f18da556400000000000000000000000000000000009fa3a3df5195203f967322cee54a15d1e0096922b6b881bb3bce54587fdb82931c0b87de7a9dd1a21b4389a34d161ba0000000000000000000000000000000014dd5455deaa5ea4f9b5a6241c2e8b2230fabff9e1ac08b359f029f4c7838201cb88a92a5b696ed47819e4866512fff300000000000000000000000000000000181085d630d1e24ebf79bfafa134c08c0e75626dd400ce500392adf4462028bc714ca07b28b8b8f15c9cf2934a299c3092c1b10d980826351c3d193a0f54a7dd78a3995efb02fe5b4525fca8791b1c4f0000000000000000000000000000000013b60e3be9d7d43eb42f7cc2c0a7efc81c175b696e82b034c87d1238db2798d9ad6534b86992653d86755b4f00cf989d0000000000000000000000000000000009dbb325624e698c76b9d697e4f7f03e502ae1cd43b49a0957fc067858e20e8c7ede3577f336eeccee58cad53eb727560000000000000000000000000000000007f2f50be2c6fbc500ea347cd14ca195af08b835814ca515d14dd2f6078eb6def2b9475c2ce370780acf394065032d0400000000000000000000000000000000109803d612b9e27be5725f162d061b9428f363493c17eb39c097032039387d96d0939a06466470ab62ff507ff762fba78f715f35fc967837facb515ebff3df502223c29e7089fe6d2e9120bd3ecfcd120000000000000000000000000000000008a9fcb462412c1065dc7c3623ba5a980e6f86cc813b5d8eca6b1b8a302ee4176cebc233411f2c9ff171332c66a0d46e00000000000000000000000000000000058d2e7ee02bbd4896b5bcaac0f2b09c16d1664209710945c1f7f1a53e24496d7eace99488debb32afe10d7fea442cb800000000000000000000000000000000084d7600bcb68d5e375457078672fa07ba2c87c8ec5f9eb7b61a0232988b197aff052e7125b33c6657729ce8a1c668e2000000000000000000000000000000000a07c42468c7c65fcc984bbfc2f05bf452daf17d57e669ee5992ce67517e1c93b5f7f4c9434d40f3b9bbdb3446ddb982a9e49fcb12c0b1e9bcdbda52e9852ee0e98fa0d43f7476b3d65ef5370c9460a3000000000000000000000000000000000ec380d15e0efd71958978b1f9298ced4cc3322e472d03830ebbaf2a4601c8371e6bc1cad047b0e1e429ecf6fc628208000000000000000000000000000000000b278fcc53b7527545ae1340c24158ff662683919717c220e7d2838a853fcc84ce3915f105a932872ca7f64b7cf096ba000000000000000000000000000000001520798dcd146c0b39ee727e8276fd998de0157a68587c2fde56cd82a9779b6ffbf745ec151210d1e9143856f24f01d600000000000000000000000000000000175d53b992d750b34f9daa39aec918a0ebb2f539db8057eff1409492c90f79a00f14a4c53445c028bef5d6372c9f80c680b0d6316c5d62d41fb0399256c5c46ebe2a12eaad835d2c7177bb7325e21d3b000000000000000000000000000000000fb3863bc7b468f1a0ab0e4701ea392bd820ec5cc2d7d86b58949002f24c972f51f0f82400fadebef13b750884b35f9e0000000000000000000000000000000008fca1b30d4e01991811679f261d11723086753e816239c8c7ebb60ce9ac0ea207011a69cdc29e3336e8f589b71bdfde0000000000000000000000000000000010696ff9d78b48743abdc6c1f4b44b4c960aa516623a24da515206d95e65286e453a8f275d98aaa09fefea29e71b5643000000000000000000000000000000000fb4b5eb18b6f6f8ee7dc734e8bdb625a403dcac6d0cae363e5a7f3a834c8eed5f01fbc4dc752e228c41f3f9d992bbe01b96434f34fa3e00ee0cfe548a2d2ca29a848cf1c52f940685caa9a227e32a61", - "Expected": "00000000000000000000000000000000165baa8b143e3734169986e68a848739ca05330786012de260148cfd0810ffd5659210855f19ca92566ea0d6c48086ec000000000000000000000000000000001225672112e0476418288f381165292a9aabd009b0d9e44d9f8f00469b2c56698f5f985ab6292c9dbcf73bcf610080a20000000000000000000000000000000005418cba24a43fc7edaf2fe77422a0b2e8b38a45415e13654c6176c8f7cf6bb2b80401534154cd3b23e977af589eda9e00000000000000000000000000000000067126ad59105621cb0931ab8f386570b54977563ffd69c2231c56e7961f6df2c5d7b114e0b1ea176cbfc1d657127286", - "Name": "matter_g2_multiexp_53", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000139cfd67c3365c5b4422063d7901108c9f33e233bf6413ba2e5b2ad62d188cb50dbd3dac0f298aef7c1d621249d4b0c50000000000000000000000000000000012fcc0d5d09cb3d86895f76ac3d3e9fa9b2495110b0276e7a039d7d2fc2e48fee646fe331c1d8e6f019898ddb43dd09b00000000000000000000000000000000159356eb3ed0d4f146dc929aa6c77057be5ffbb064432d3fc35d346f19f6c1f8552c7079e27f3188bcf29941375e62c9000000000000000000000000000000000fbd4e9a57aaaec40ef9bce8b76b529bd2261d373f05fd69af58d1f23c089497473e44e937b2617a92942af1a99d031f10e0acc22c43080ab9cea11a60866feedd57664bbe6c3f0366beff177f66318500000000000000000000000000000000022ce2d2bee57f7567e9b52ae8e913c79e3b2dad381802ccad317b525be0b503bdfa92722eb0c21fdaa31fce2421ae300000000000000000000000000000000001177074350288dff9dd85dbee758fee1400cebc173793198a96c0be3bb810d352720e94b9bdcc6f5a8951b3a86b2a0e000000000000000000000000000000000179e21de58ff76427f5ed7c8ca3058d0e5e81e436280aecc75a3d989d1cf11d41734de22bda74cf0dff175ac789532b0000000000000000000000000000000016abe94a49f071fcd5e24b5f3a837fe3fe7c7dc53416f59d0469d71f144f71ade4569bac3aaa202a8479c794bd251645cab0c230c354cbf1a3c13c23a36ae5f2d5d084d7aaeb427c580cb6b9bfd9df600000000000000000000000000000000018dee638031a3c9b1198cd4a4f267cdd66849e2b80e3d670897d9e058bbe772936d827eaa4e78283d42ecd25eb4b22e200000000000000000000000000000000009c04ef31cfda7c086a31341434a1698c1132fb5916d359a523b98d05d57bb38a1e2e2bb779d4762f9d4ec24fbf2564000000000000000000000000000000000a788450652e0bfae66889c66b0dab8d1972a626facb690f8e4ebfefc7e1a7b2b58f6eed02c1f10a74b140a49b6c5de50000000000000000000000000000000009e48b52f2b0548dab1c0d260144ad2e66a22e0f1781f94071b5a3a08311d11dcad6963b4339fa63bd82b4ff0dabe685290608899cce4b3d25f57519cc881eb748e9ee7e27f7b21d69f5d8ab3650c3e8000000000000000000000000000000001319607058637d4b796020cca79d62af5862b1c186f32d99c0ff53a830888f297ac4389582f9fd010534d824522e6fe3000000000000000000000000000000000608ca0b4806f17b59a805a3f9f75e7a33ac0791e05050d4eb19f2d4c845fa4e4c738c3309e24a4524b6bfe716949ab5000000000000000000000000000000000a6a6201ec077e113995acb81d4d07d0c4a085d367ed740d26c4a0c04ddf28697c1cf5e648b25148888617ba77ced5e50000000000000000000000000000000003eaff54800dfc8eb3ce647ec4ae8c1aab6a87d4853a1ea061a5e6367d8ebc94243837d4752a1933f7eee0ec1ffe68c8b71debbd9f3be5d6e65e837bd78605d5653fe63025c320cf49c035ae66d8ff5700000000000000000000000000000000122822c91bfc4f761b65f4066a94c0eb1f53133a1355c019f04003e84edc5095523b2ce87ff24bb42425ce979743ce31000000000000000000000000000000001928bc315800ae9936e5b763bf29b19a9aeb71268cb47706494598e0ea057f9dbdda6733d9ea165acade87bd89b3ec12000000000000000000000000000000000a87c1ee17bcd7d348ed1a5022bbc7438bfad06172584dd8e3b51db4b3b09645290382ba991df37db0ce562c950c0e6600000000000000000000000000000000127c80da591c3ff8d300bbdbe27e0aa21b5edc1c1fd8a5da27f58a4dec3971b3c4f9631bde244a7072d9c19f1c0a46be250f62ee2c2972e751b36d95a578efd2fa5e0a2c1e29475a3cee48a28080cb0b0000000000000000000000000000000004bcd0a0321c3c7e6161cd53254353905c27d965f57c9783c3fa7cd5c55a5820116415ce45491d5d1ccef6017ea4608c0000000000000000000000000000000013a30e19c43a1f466c0c3ebb5cf1b57c44434892b18a7fde18a2a29b09a5b4d13d26cef871d689d9855a73a43d22119a00000000000000000000000000000000066d6b3c9a949049413300ec0398d605277911d7be327b1d816cf25543d1b2d7c31d912f426021e612b56ca288b462450000000000000000000000000000000008549f4dfdf018073cc4e32ac930397659ae7a59ef42ca4f864b26e4635c2b7669186a107e9e91c35f04674d2be46051ad08c3d2c36085212542427c1760c72f22838be5286402ef87403f816f4fec950000000000000000000000000000000015900fb486bd2c066cea98e51d30424681fc3347a1cfaeeab65989d1adba104a362837bee51b8b953ebb520feb49aa6c00000000000000000000000000000000198ccab1f94fa910f755936e357a92d358e00cf406894b46adcfc301918c4fd7cf7200a1ea515343d577d920680c83640000000000000000000000000000000018d9380a8568adb92f8f9f67c315f2a837d542b32aa82d9bbf5db6dfea27260738bd0a03683a9988c6c3370563e7bb8f000000000000000000000000000000000528ad42f23c4e21a687f2303f495e962b0a90713d6ef3abbdce38ed166ffea9c132e50c5b002b2ddbbd4933e9a1aedf6ffa16b6fc4cc9509a2b8d8434fa0f4f38b4cb4eb1bf7f545f9f43b9190cad890000000000000000000000000000000017eb2587aef34b03943a170d91d99aa16ceb2a36df3068663382ff4c135083c998743f9145a2fd5dd4ce3bb8b64cf3fe000000000000000000000000000000001256fb29c7482e5469d64183e3e848e5bf32f9c495cc495c3f8cd8e46f71c3f9880f875cfe429677615a6803f849952500000000000000000000000000000000146e2f329f86ddf5b0b17c37aa2905122f457c2c812782bdc15e132468af48c49b715e3080da504d59414ceb367596f100000000000000000000000000000000022a8e385972592430e76bd952a700df8d35b32deaf06c60173d0048d6ea22dad95cc62300bc1a60c6452c41b32b504a1271d29abc5f972809461a1afa5eb186dff5e28f20311a1d8416f8d54fc4b2d90000000000000000000000000000000009c80b3191783d235814fc86653bf2f9a32cb7938111408087b6ab5bafc480583e7a2a32c6bee0ee4aa867ad5dbbf77a000000000000000000000000000000000a09af60eed6c47a6c2615cbfe62025530b35727b42fd812032671ca1eece6694aaae259b05906faf7fbb54362ea890900000000000000000000000000000000055c5f0818f41e5d73e8cd5f70fa77cf477cad8dca2a88b8970a3a25c8f38382268e439642518f1974c5b470cbf29699000000000000000000000000000000000834e44669043aed8ad47cccaaa7476ad830e38fc1def66aa7e8207e889ac0fa1a931eb1e90aa6e1cd694bb95056c3e63ce55b3b32ad29dca1a0c99771fc8f7179851995d5eac804458edede9b8dbcd000000000000000000000000000000000190f8da34caaf472ea9b0f41851f808bba402b9be4baa5d02d1bcb2f66acc3172abe78a49a653cd24dea402dfb972f670000000000000000000000000000000019931343d0e59f0f0a060bcbbeea92fc4670db510c017fd94e0650ace68c2925c627f373d8e755813c199b79c70369f20000000000000000000000000000000013ee811cbc036d2786d8ec0339627d6134b10517c8858f6c6db19a9319636459ebaa217649825ffba32a224175267de90000000000000000000000000000000011039d587f3323ea9d3c50027c427fbcbbf7e097533d8a5f7a61520f3eb548c399e401df0f51884395ad6a338c0a3500c6fa7aeb016b3e3f599846af83f426b9ab85b6857f901c49554d03d27a390f5c0000000000000000000000000000000011d5791e9bc632eb63bff86aa433e6df463a84570b779c913f67e77fcfefb6af48f3df2174096a511ac35eff64e0e5f3000000000000000000000000000000000282716505907931bc93748ba1729777b959d65aec5a78c9f829ae6f2a94a022116715a8c2a653a832a62625473a0cd1000000000000000000000000000000000f694a16ce7a69f0261a0ae19478003dcb61bf93a2ff39f940fc4718a38b9f4b6ab13527c5b438d22499ba29c0b5461700000000000000000000000000000000031eab53440757e4065804896e9e811d459665598546796d67472054fa60e5da8685d8e847eae342e44730056757c6287275a8d16c02389795d54ebdcb70a39fa885320d00cd4e5aa15967916e46c61500000000000000000000000000000000138862ee422bc0f38ce3e27ed3c1b71f71a03d61cc474d989b0cc824efc512ef173ef17bbfb2090997eb9435f4d23e0d000000000000000000000000000000000fabf1fac2ffa25d9c8cbd49b3db5dfdbee52adb947ebc1a3423c9fa2f9d3d29329b60ce0c1c739c7fc6d5a5d3b9e96400000000000000000000000000000000090d92e8763d4df49b8121a50affcecfcd632923b5fede480a3ee79128781f3f49b592d8f65d30adfc75d8a1922c41b0000000000000000000000000000000000074456b341565b13ee3862bd87b72f9d01754c7715751738c5b33ee85e3d8a6f731d7292bb485b5fb59bbf3ddf9b0d0dbec9767ed2dbde21fd8f315ed6292b5b0b1bb6daf2b62665c34daed00a679cb0000000000000000000000000000000007b85110889fed72b3654a8632625835cc041ff0a827f3e1b86c090d816d98cb3b4be66b6e573b3dc05b1998f2772f0e00000000000000000000000000000000160524507679ee021f4307e5a9fdaf01459cbb9a3fb9dc8be5599431e2a8bef38bf8a05d601580085da503dfcf57aab7000000000000000000000000000000000f98e2e7ae9cef2b1d954b7f26fa1755258112c496605c3c77408786d4b210e51c76f10870f558296993e0ddcec3d76e00000000000000000000000000000000068841825f5f5d8f622c1d43bfe090d11c6996688589c3d644ff5da47b94c0638128878d51dcf6d43637781f0ab21a68ff634fd89223733f407c242e52f034691036c7ca69f30e6cd444c561de9ebdaf0000000000000000000000000000000013ec97016dc3d6a3cf41edcc18f88f58b1b88cb2616bc2a8f96af3e7774ec1aaefe86a86135a20ab7592c874a33a8e1b000000000000000000000000000000000021dc7e4be6462d64ba6c09c2d326ca0164305dbf5ca1981f265a1e50f1a646748ce66ae07297230325937faf60709e00000000000000000000000000000000121bda2855503ef11b043301cf331a0fda6e5914e5ca657890ffba2542d908f8fb02c2c93cb4ac4fe5bb92eea757ca7b000000000000000000000000000000000386fdda56c778a7552dce451a6ade55cd24bf9eaeb837ebef898e2e868d05eb5edfe97bfa8eff8ab7cbfaca3c918910461d349e9711fa701b92b62dd3e3569d1203b6a35ac8600367a4df9a9484bdb0000000000000000000000000000000000763746ba87e8bb547180b0bf18699ff74f11154a06cd77a76cc9c264db7c48286fc52e3ef2d30ca914cdcc5c4ed46ad0000000000000000000000000000000018037afcabd273413eb4a712f5d1888249dc987a6fdb8befb92c02660604bd11deb33f283b37f88880cf1be2b2e71f1c0000000000000000000000000000000008ecca3d1652be4764720ef13a6ed6164a3ae89d160cc8c2c8c37bcbaa52db0fc0de84fbe2a19b93b8100556fce0fc80000000000000000000000000000000000c5727babfbc5c36c1d57b9f69c5b41823882e0196e9e0a89d5f4380c4257818d90b1fa6d782e774f2424209bf2e6b5fcc110fd7a6ae46ef78c0e26183e707eb5e0a2944e3afc09e435d56e91584b93d00000000000000000000000000000000142d41630fb9db2f9630e4d5f9c13069242fbcaf1dd02f93224174567c3f944fa02b9791a409d9236d89df6ad785e8ed0000000000000000000000000000000002fb5fa0b3a7cef16e5638f217bb946085fba870836c618a7db9b4394da9144850572daccbff8208f14c8082aaf1ef6f000000000000000000000000000000000a6be9b4a6a9b96d2096eb3a95780f11be1e13bcb6e625517191822403935c52cd40481bce2e782c42b11321cff2cb7f0000000000000000000000000000000019e2d94e35d608a50b5c8b371044f6410dd6c1988ec7a677016d4b52cc3f21b82fbaa7db897f7107d81a177c31f8e52467de5b9bee26b26b28f81d96e880a3f07dd04eb56c15314f1a789436e01adcda", - "Expected": "000000000000000000000000000000000a6f3fcd812e3878cccc6967d49b104599fdaa80cb5dee7298c3fdc80477d277f2c68f1c941f6e03441eb176c222a448000000000000000000000000000000000a4007cc5586d677e7945dc8a5872b4839d5b256999166e7fe8efe4d56895f93be4659f43aaf68c6070babb6d3328168000000000000000000000000000000000cef5304a1077c8f31d72e6f1f91ef5a021d8ba64719b4527225b34e615af388d9b1391f65511eac209ff5e86244039f000000000000000000000000000000000c856e7847ea0b4a8334d124417b45a8689d5d9f113b99ebbe3af3f9aae1cefb236d751c40488a861a8f0e0326b42c4c", - "Name": "matter_g2_multiexp_54", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001805009a7fc3d1705936696191c163a07ea992cbb4bec66884a2d58ac3fc0e16b6e0d2292caccb3541f39b7fd6098100000000000000000000000000000000000f3bcfcb0c400d3d06184563204bdee465de167c7d17bea2e2150fe12eb9bc3285f5693b222fcd224181f8d193b7d95f00000000000000000000000000000000028d60b7fc3790aac7f6b3ec32c4be626a2c64c6348fb8a1f39e58ee56b81469e04886ed9be1388958550c02ca9a75b9000000000000000000000000000000000b60ed8052e43e99d3c10a4b97ac3197ee3cc04ad857c5cf4d8ea1df2671084d02fb683f28f5d499910351354d5e6288624ab43047c02e30ba2ec671511d06f869bf736a9866192c5f2eea6c065acea40000000000000000000000000000000002ddb1a9a88e3a0697540cb008bceb075e87e2331f6e9b68f8ffec48752d93cfda5fee121155ad2a142c0ec42808fbc200000000000000000000000000000000144b694018840835fa9c50fdf62c2e32261a8350d2ef074dcf7d016af982316a0c6f9e5d15d29d3a54d8d25aac5534940000000000000000000000000000000010a3765089ada75e9eb61328756ab9ca7b8362cf86cc82af3cf43f390a0745954f28da72a6ea4eb904a040596795639100000000000000000000000000000000056b51dbefab453012b35fb6e06af06ee92e4e84e92a9967b379af760fdca4a3f10f938684a646fd70a2188721c92e98edfdf850c0d3e3903404fe3e0f523cd230cabc45946c4fcb6d0e5e05e388c23500000000000000000000000000000000169effb324d60b71dc7ba975e3d5f18700b34cb9017f482f64be37c4df01fb66ee9eb5870e43649225c9a88a0d499b890000000000000000000000000000000016c7ad9c5f7b65a9423f642d87621a5192d7548e1099d774a99a34dd4ec9623aa1168b9adab092b3cf450f369bcb627600000000000000000000000000000000123b35bbcd791ce0d00148cdb3d35ba39054a7126ca5ad3351fef1437461379ef639896b271276a9561b46e270f7501400000000000000000000000000000000161fca2deb729fc55f1102fb75ff466319f18510fc66d6cf95a8256118fca618682f00318b0a5297be873a2f7af1915afeb34852ce0f3b5730962023418ad6cb860716dcb526dc53e8ab6a74a6a3910b00000000000000000000000000000000073ad8c2f713288313185c3b2455ade93d58e70d5df6b8dfaac8eccd990fca6843778fe42cc8aa6f34ee44aefb49397100000000000000000000000000000000012eb9cf288a366adc58d40c9ea5f2cb5dcc5b04108e3822266ff20eed71f56bd74f1a2727f20d55917adf20b6c4d6a1000000000000000000000000000000001463db177fe5c0dcb899797f89da963731dd4e9e8b2eb77b465b98415dc95f6d5569df51bd2b08a13838f4cca4b62fcc0000000000000000000000000000000009c0bbadad98361209f36eb23a9eeff98f6eafc7d5327fddb6bf43898a2be704520a005b84c5b45c6a68bb7c98d65d6dcf25e64093bd92a8fb394511215a3fa674db86d7329ac5ea70ec77d24d4ac58e0000000000000000000000000000000013c63973ce6549ca3dfe8ea8e3bcd6b0bd88f7c73730834d9ffe2076cd4345090d0364d161ae8998af1048d102f22e5d00000000000000000000000000000000060cd24eea4177c9a5c37038d4cb62aeb709218fa8e64b9084e002f53a0c4c411825812c20df282345bc4a6aabfff6a100000000000000000000000000000000106ea864dd52933be02c1a79cbaf6dc81ae9a2d619bb368c4abc36226104f3b74fadfab906e36d4852a6412315223bdd00000000000000000000000000000000192e45153e4942c88bcce76098fa51782a81b53abddb4c07bd79a2391be68858e2d278969b9fe75bc652d02fe4db1a130b40db4f9e5c27a3208899f4f536880b97f4c69e7d889c0726d87c3fa27e097500000000000000000000000000000000101ca1625e9d4a51e08f5eb81387b361f6445eb307d9bc92acd29d62735d4e5078b1a9b36b94e4ea0a314703a85ac4cd000000000000000000000000000000000f134c460c6d931396a0aa397558975ee973e642f1c4a32a3d397051fe250daf4215ff5ac4b2863d570c87f0e32c8cb800000000000000000000000000000000008eeb127a38104351298ad77481c32bf51bc5d3910b03da0cc34062dd2a8766adba6891cb9fc579672276666e1242730000000000000000000000000000000010c896ecd4bdc1ce010da81a51dac96409079853635e57e5c3a5733956a5f5a9c3ea6838849e286ce0405dd54d7e32d6730bc7f68d8d371d0bc51d95f8a5899249b8db5cba0d21fd88ba6f86d8691659000000000000000000000000000000000be489a1c71246adaa1c1dd6d2ddfae9523fd1d58d00d4f189f56d08632dccc694e63b371db6922a7f3faa05afbf487500000000000000000000000000000000174212b6840a797f0fe9e209b41f55aa5dbf169a2e2ecf05de48c44e608f6cd6d98ff5269e5412defb431caadc8a09c3000000000000000000000000000000000f4501715c0c511703f6236caa82479b3368de430f2c2d95b39193537be0b990fec1ed8e4d94634ee6233cfa359b043d000000000000000000000000000000000f3b4712f95005004d99fd739affc532d2c4c45970316c1a43f76fa9b57f6676c709e8791c276237b92750f5bdc94492ef06360717cfcab15be966cba2836b97deeedd20a52f88c73e2a583b64c8e5f00000000000000000000000000000000003abd36736fec3e8b89863670666365b169d8510090a89007c7ff3a82fc62ed371544013a1444fedc4358e92ceec62470000000000000000000000000000000008229855468fc63f4024938cd6f41c6e6a5653319cb83f38ab7efb9e9d281166261e7c854bfc08f55a0a9ca47e54dd42000000000000000000000000000000000463ccacb341fc5874f6ba2d44efb5cd24e9409b2ce7f43e9d39466288dc833a45988261f45d34332f416a68c5d10ce80000000000000000000000000000000002baa086177394203a04ce1b46415983399e60986531967b690b1a13cf8ae039b56f0a00bf9aff357d51ac57f8fac8b282b7d8b8b9345bf13d0e113b662141f5ebfc5888a5ef8ea06f7d5d137324ebef000000000000000000000000000000000b25a203268100df0510e4155c594a144dbdefbb0ac95e02bb4b3799aee4e738ef4c52f03c6937cdfa7275c28f130778000000000000000000000000000000000c432347a2534e86e90ca346a7b8b40f45075727847fa3ae2f2e297baa14aca88ac6e08342f0d248a92e2c272841fddf00000000000000000000000000000000057ec8099e1e30329762ccf0641b45e1a226f7b66b80644fd551d6fb1f2136afb8e8ab5c6905ffc7c24e67d7f21863e4000000000000000000000000000000000a9e472aa993bea05961affd6782efe8f50d746928efb8fbd328fb50a254db861c90db8df7faa7da8266ceb47fa1a13a2396fe15751bca2c4a651445cef236a865269849908df53551802dd378b892cc00000000000000000000000000000000025484652f18e2b32e2bbe79916c8bad42902db5528fc45993e04daeca008f3c2ff38fe4b48c292f70a7dc57654233400000000000000000000000000000000008e403f472b60a6046fd190544a1d6b249dc97cbd8641c62613f4de0e0fa9f5456d843ece4ac2b9f4ffa2c0278e61829000000000000000000000000000000000824e0b9b03198597fa54252b3df9690df678e9c6d82301848939dc55ab25a7751bcc2b99786cd31960ee7030bf68ac80000000000000000000000000000000018d1d8c7f2b20f0ba66db616322e48ac8f1d6f4205f228ee8ee6cd13d1f64be9af338c11f511859baabea3e15d165fc09a5897c9596223ca4d6628ca1f793a000aa21a739a37faa28637692b754148f80000000000000000000000000000000002845c4255819ec6e97abddf4c9db7d91658dd1d55328ab0565144b377e20ca0743d93fddf68acc985ceb7f7431e30b0000000000000000000000000000000001577a5691f2425e65ffd59071c2bb167ad05a8fe23c11c7f7464764442ebb2f7a75a8d02594d4426c1ff022f7a6e19360000000000000000000000000000000012c6ffefcd3964362f1373348404d04d1849e98ffbef7b5ed5704d74b9550869e30a4df26e74b5304b85c7503f7487f1000000000000000000000000000000000faf3dc42113f27ac27aae36725221d04fb1ab46b59e16277be0758b8fad706fa237c0c7627771d8e8d3ad610f63619bf20a2973faf886556e5329363bd9b9c96424fcf2e953df90bfd011ec07bc66eb00000000000000000000000000000000044de166200ec06bcb88720e57b84cd8f9534d1fe303a26aca08cc35104ffd7e81a6473c08b28037118dd8a61d090e910000000000000000000000000000000000f4325ebaafc67945de2418c81f5da92da4e67866ab5965eff0f392cc527fc34ba4e7e16b91c26aa370b27eb6a07f6b000000000000000000000000000000000e1d77ccc1c196cf1cdf0dabbee4829d56e937372e9f5613e261ca07e19b3fcf10f7a45c490b98b5a64b955eab5c4f2a0000000000000000000000000000000004ba2e81f901b0da1ead004c76d43278d372456c0c0a8c6752597823d44994177734ed3f355aaa22f325ea36b7c9eba1f4ddb773155a27badba330ae5d26096f350e9ca2811feb227c4eee09d2baf32f000000000000000000000000000000000c115e270ffd6f2cb9bbb2a62e04c3bf7be9d7db783d292bed272c297773b39e9e51c75e5c79a6606ff7d0bb9ddd040a000000000000000000000000000000000a57b637126b16b23bdaa6a7cf2346f33778cebdc0c9943eb2985ba5c4114674cd596ecdb6959791139c36c22148ab8300000000000000000000000000000000177c7ed16c29d99d3d98c6facca9cb5ffe72e6aa63959dbb51d9382f0fa49b02a1652a398eb223e093516ebf134448c4000000000000000000000000000000000d6bd518678828f582fbb3b1bef725e66f442c4d3e6325fa571e13db492300d03c0188399a2ef9d5687a76e647873c0f52e4030b5a4bfa767ae20cdea7f464dd2dba51c9c698556d24b8f3d4d1afc82e00000000000000000000000000000000085d4f90336987f99d250067c2331e7de8f09a80d71fef0570ecfd99e409c1f405058bd3461c9f8ac5ccda406db89bca0000000000000000000000000000000015f310660ca6a0c06b458d0b840a5c1c476d5175d9ff6dce6334466d363d319939572a2b00662247be1ed0f4e6676f8b0000000000000000000000000000000011e9352c0f81bd3857806db678bceb2150848f2224ddfc43fb0c733f0689ab4fffde50d5ce04d54055d27d7702e5d2d40000000000000000000000000000000005d835d04dcf4199130d6a16e86cb97f4ccff58c496594b83524dcd88f5570212f06b744379288f2a737c7a82e897cedd32e0429e7934faa526475c5c7fb977c3030ed74e145eba21af2d2cc8461580f000000000000000000000000000000000f7c4e621c37bd3068a972b9d4211abf9026e438ac7f8cb341516f7e6aa4d8bfb3536389e9155029ce9e8d5d376eec1c0000000000000000000000000000000012a46cab2624797513f2acaefa26fb22c4bf29188881690c350593fd1949cbc243c9d1d7d27d9d76aaccd347359a45660000000000000000000000000000000002dc383d4f9b75907f74bace1769bb5bb1b27a597c9548310f2b5f90098596fcce6b5fe0c72bc8be9037fbf31050d74e000000000000000000000000000000001900deff7ddc62ac302c941e1d2a28a4bd2351edd7700042ea4c4a48145ef91688666d8d7de503913ea259f0b58809f21f700d651c67ca5b8d95fad1a8e412befdf691b074956bb8092938bda2ad26940000000000000000000000000000000018ac8048d58f7b1a9407d3101824e3640eb20633f8ffdcc97d43d1b25329a2a1e91added42801c03635ec904e627eb690000000000000000000000000000000000b499fbdbe2ed41dfd6c454796e1ba57021f355a4de8f60964c78dc685e2ffe9c90f5a1f6c9677514ae4a9c95c8d6450000000000000000000000000000000009d10e5e2bb69ea6fd820778f75a2a60627802a49128c3f999d8c1cc2ba56ed18acef354a2e06fbbdfa7e7a4ade7529a00000000000000000000000000000000082839d66a18763656c2ef7196a1d83bd162e1f109b54c5a6095cc7c436e8a4888c4001696958270f54f61b81b00b32d83052a3bd7a13bb1ccc22b9519c7ab12d2dec67924fd9f15f96069de22e7b692", - "Expected": "000000000000000000000000000000001463ac5e269d286961036db48ae33fb868a28b0dd828c3a66592ff9dc115303bdf3ab78a8e1f5df68ed1f3b4c6c3f2440000000000000000000000000000000012c64ca0ac10ab616fc733f75fe6181814e9c204f9e4eb79487ba49e3a9746b9b7916a1d768f2ec573a4c4e226365f48000000000000000000000000000000000a06b5b745dd92adbe1f4cf30c79ce0c48428b3e3b05af1585c4ca12eb2e763ffff46b55a060913e1f77fc9b0b085c9f0000000000000000000000000000000006271931ce9c8b9cabdc932297f3c87128a5af25a9f77e71ea4e588f1e88686638e89a8e212c92f6472692be2e05fa5e", - "Name": "matter_g2_multiexp_55", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000001bf5b74c1ac89d4bab4663943e19128619731e315d2d7b39675f7c43493b338020190a72cc7a6edf0b8838886a7fe6000000000000000000000000000000000713f413bab7919cd57c2de3349394121d6bace3c10df0e41a0ab895433d225b05cdb1587deb93ae6e56ec26a29c39f4000000000000000000000000000000000dfb11c9c0bab7e4d1ee39941d5f6b932ab473567be2329c94bb0b146c46fc1c2cda25dbef8ff9b0066bd4ca3b6da67a0000000000000000000000000000000014e399169243bd619be7f2120b2cae5d19b2f04185aebc7d948007c4d3345a9f45249273b6290c2e86448648868ac552c40774f67a651ad70f17393b386e9ea9e81682ffd78db7fbc17cc5084f3c7052000000000000000000000000000000000a67bca1f8a0b386b2a67158e80262f025b225535a294394584118f9a701e31e91b2c7eb8fc7e28538966b967c139dc400000000000000000000000000000000185e8aaeec9b9abb9f0d6f34e2480e9abc30208eb1c6e023d4986d544b356a387c323c9edb5c52f5a2f0bd59cca7df98000000000000000000000000000000001877ce1ca6e8b30df86de688d950755f2708fd6f933c07ae45fad1b3e43337f1a8454ca5d2a80940e8fee98fffe953a700000000000000000000000000000000117a0ac9d27292f967ff5bff2ebed5d2ddd9f453d6aeadd9106eb52b53447974561b621fdc1d973c055f1cdf824c367bccf1e36e063a5fdd4b735dc18bf07703b80c6b72f987c05641612d7ce73562c00000000000000000000000000000000009fc4e9e816ff495dbfd4f745106fc90c023d95bc64b809801d02dc7cead905177ede5016f537243660e4b7f54a02ea200000000000000000000000000000000180aceb6e9851a11a1e34502897299e7db3e09f4970337612634fd9848d1de2bb3de8ede690ca051a75add5810ff777600000000000000000000000000000000199f3c43d429fe8f73e20f81ea00c4e78294eaaa29fd67563664381db3cee2186b387b880089cf96fb99c2e22c95449d00000000000000000000000000000000040b20ec4e685f104be188d0f15a79f27cf34dd01f813275f6019a9ffac56e234b6c967c80745294d9fa46e0083cdd907ea75dd2f54fa6413ba77f10a11e12abea3a4b947116e1e7c9334a0a37c3963100000000000000000000000000000000189fba635109ca215bf3a09c3e44ad65f7eaf653e0929aed39042e3b9c8b1132c5fe7cfafddfdd0646514aa1f9e7e1c0000000000000000000000000000000000c28f598c80ac262ec7a0e0d1c867e01ef26f182c5df9ea7f88fdf8bcf3a5d2f06128526b1ce72cead8ab4286a0b8d030000000000000000000000000000000008051be3328df43b79dc9040ef0a0263d474acc0edc023f300cdf7c13088d1bb21b5f37ed81b38dcf8718bf6441605f8000000000000000000000000000000000d2d474723c6c246dc59e683be147b1a6bd6e7d3cf12aff7b636802a99954e7a13c9ea429b19833a985ca5649b1a998f6855c61bb7d72b022c16290c6d3ca9c1255cede8e0b827b43e40fbf01840397800000000000000000000000000000000058bf424fd68aac77c42a046f78a55729e6b5b3fcaf436d0d98354b426a95904b55cdffdd9a8892c9f56f170ca8811a600000000000000000000000000000000142c1ded08928fd155b89bcfaf9c8194f4569b4cdeb3bc7286f4dd79e822f5db497768220533b71be8c71d121e557020000000000000000000000000000000000a9c753686534bfcc295eba0a617f86d7f9e78d3fe6d52f26cede97a5b1f107210a757a2d89361645856b7b20e89185a000000000000000000000000000000000f745541841cc4b5352f659c2b7cfa8d51b07f91b0cb8c787b4492bb4b94ea27117695416e2806e57c38d7e565b9eac67fa8503101f392a6c6c27300b6992af3fcc48d47f73db67615a44de883770d4f0000000000000000000000000000000004445d4464b51d6b12f164a49ee3b610f11738d60cfa6e02f8c33b168d9d5db90e6cc558cd12c56069571567d91183a30000000000000000000000000000000009e4b96c2b533a16803a36f8d1f179313b7adbe6c4b90716855474ffb2fbe087df3fc0b4ef14cda7d958efc5c92574ac00000000000000000000000000000000104dff7c859eec61a0ff8e0d831bf9667226d5bdbe298400b4f9e3159a64b1bbc7cb9f4ff9604e3ced40bb0de0455ce300000000000000000000000000000000134bc2461459ed6f0d96aca02b62e3110c2009e1ba7d3258656e9cf97c2a1685faf1f61733ce6ac3af7ef4d73d0b43b1dd947617bcb7ca1c8fda0d49e6d950a84d60230bc2411d42ac32e3651f48524b00000000000000000000000000000000104e5709f8edd71f50eac1770ff1c2b21f5ee8cf5a310fd1201109d1b73cab69913bcfa2d27a8ba16d974e9841586ebd0000000000000000000000000000000003a4bedc6277c61825f6ea1f438c058a1afd494c384689a8479195646888eecc7953b8b8aec849fb5f19a20071261336000000000000000000000000000000000856ee8eafb9b3d25fde7e38da4acec624d1444337b87b0b1a660bf497ff37929b1ef9aed8e1fb0ffc6cacd8f0d1a1a00000000000000000000000000000000011b52192c88264df56de3d7b14372443e25183bb816ea1c0346f15a1f324527ef8531e27aac3112e2a497a0eff0d5485b4cbbc6d537ed2b69c2c32c84f3cea3d2db180b64861859368e98aca32bceea6000000000000000000000000000000000a696c83010719161b6624aa7756e6e84980518416554ac045a93b63c2561a68ca2ff2fd5b6d2d667822ae4e3b3a2ba2000000000000000000000000000000000fb8fdab4f177b0dee52bb5ba615b1d548130deb87b14d05d427984ec148a7a94efc4674804b3660d0f7aae2b49f7b1e0000000000000000000000000000000004914c0359c8e23a7e431e517cb83e5735cb2876e8b53ad45abf1e9eda06e736378ce03ff75002374d47f1bd45b08e8900000000000000000000000000000000139abe340c2d773cc45cfc75c47ff31b2dcdce27ada3e6d6c0823f37e4e693ca30342fe41eb96dde464d14668eb72c5e457bcb8c44a2d9d1facb39ba7ec8ede5d5962b3256d9fc2e68a1ee5a733ccbd100000000000000000000000000000000180345fc01e3fa349c45b1a7fdccde5f9ee70d7d65510e8b4bce654f2541fae7641ad86f9bbc1f02e93e94422433f8b40000000000000000000000000000000006cfe7026cd423be189c5ade8de197aecbc9aefd4cdbbd2aeacda816247ad59ae06a5c49b0e29bf1140f400d46845191000000000000000000000000000000000cc4f240a317ae9ce75b44fae87c92fe9b6de10e1191cdebdcc37ac200957683849d8a957216676db1af51fa0a2a1136000000000000000000000000000000000ba84d595661e5d9bdf9d268a3cc575fbb6b0d469b58b3e43f80694c78f4e9e501c4a4f9c42ee4518ed7189a1c36ca0c19f254dbf75f1c42046343b0060e71302bf6c94ca2fb8aec74fe7a47a3c9c3ff000000000000000000000000000000000fdf7e2372b01b5d926a18ddd06b4573248c02d7debf944312dc06f76ba08a7be460c451d296b71e9e81cf0956b974b80000000000000000000000000000000018326d0e1bfb4a62ab6f772b47ed7188035a62141e6b2eccf53a299028902a172771e8e46c0b1ac4833ab12045922b3600000000000000000000000000000000072107574145c6afdfc7d618f2dba2b8bb01d92007dafd476e4ca62e6053e5e9f2e34243ec2dd16ffdbe3488b925a0f000000000000000000000000000000000070e8491a835ae96087013b0f8da267a7ca5b0a600d71b8c76fee35f41d8b5c1ad82c5170b0e8d1cacfc7b7b13938e96f08cf27a47d89ae6e2ffb27870d613b9ae586857e4ea00670944a2883ba325af0000000000000000000000000000000018f4da37ff63f66d68c875def8c758d9a5adcdc408f0c12b3a60ee4a285e6702b1d5b9326c61f443dc71ae83c7bd21e80000000000000000000000000000000013a665e430141cff62c25577798473a645d20321490bae7689de6ea223a434c7d3b16ad004b24a82e2c62879b2408cf90000000000000000000000000000000011b0108562f53bd47d9f8ada54166854bf758ef3769ca1c3b7b006fec8707107fef0b6c7e59feb727646b74c27ec699600000000000000000000000000000000028799b52107d8965066e2f629b30c0edb490a0f4d0b6cdfff89a9f7763afbe6217bd42c2059042397b6c0443465fdc050aa333bb6b44086fe6211e89cb70b8467eccc228c09aaa1d589cfc24771a11b000000000000000000000000000000000c42cb42e389f32926ef09584516249ae332641b573ed29bc0884feda08d35c1bdc6c3d4a69fa15105de95010c6cc24600000000000000000000000000000000006c57fbf93c7959c562e0f3ef59966c1640c706fd18a6b539dfd711b0ad79643642038954bc866d42d1c04be375b95a00000000000000000000000000000000039ca3ad23b71693e02af36a4abe6ccd0dd4f4aa709f74d900b9fd015a2eaed55bdc2bc0749c995783a7615971e8a1f50000000000000000000000000000000009a08596b29da34466c8a7f46b805f1b6f2e48bbba614d728562981d3d4884de9a3c1980d398eadcf69e90c851d48526d9f7f74a5ccbd01afd985d3259739023cd012cd67fba3a4ab5597e94d8fad43400000000000000000000000000000000123dde5bb9b7ca11da9e08a9489cf07d147492be8041a5ad0b70715147e21d6017a58af23c47d77885a7830cfbbe5e0d0000000000000000000000000000000001527cec3c393d03e74ee8a7b1d6a8b6398945cd284b59a93fade9839863f0af591c287e89b3b45e6048f2f9b518208e0000000000000000000000000000000017ac3a2d9458bbd5f38d584b0fe4b35f3a452e22161564a7582465d2068b3ba4dc5e1e24a996596b1fb553d641996a4e000000000000000000000000000000000ee5ed5610a78dee181750e35a8ab91c001446f04124930c2ed85de74c6167009af45a6cbc3c59c4915334d7853ee12f85c00be7e66e318bed8e66cc41e7fd0593004bbca20f0dbc28efe4441acfc9ae0000000000000000000000000000000014d60c1d436e4486f35ec85bf2655ba6b752a36c86fd9088c0ce46363e75abd636052f876986fa0f4a59152998c0e4a800000000000000000000000000000000083328e38373f1de1049deaba78f568db818b1dc38d981ae92b968134d369ccc399bc3bd55c841755beb484cbbd60f4b000000000000000000000000000000001788850a5508d81df9af1f087356bf8e63b3c8a4e209403c4de7b3adda07684a08f9de6f1f8fd8dd4b2bb9b75be329cf000000000000000000000000000000001506a37d222173f0098f56b7c443e04ffe08b376e1563344e7bf22b1c9df0a1292f70ba51cbe554843fb93a7f535a4aabacef63d90ad11bbdf0c5fa2db2838c238ad3049a3f47b7f67361825efbc6526000000000000000000000000000000000d5f153952defdea9309269bc996a7714deab12e7644f8f8344140fe53034de538aae6c3af7b06687684edcd2c5dd19e0000000000000000000000000000000002da67345153c87ca65012b8703acbe777900953abaedca4770fd893275948d150ca3d6694d58bbbc9e62904448a8d2c0000000000000000000000000000000006e8c95d22f01fd9d56178d754f0892f46166282a27e6b02826478cd39119636e811c03fd835c714a59bd2f7da5ce5e1000000000000000000000000000000000b5ab6233d8dff50648d89cd65793640c06ea784d00aff329e882ae04fb466506cce3fb6c381b4eacef8b5305953f7b6473fa3d16e6431da14b8639d4fe316692db087a167a2c4f07307e770bb9e35ae000000000000000000000000000000000595edc440a5c94506a79f3b3fee818256d7c4185be40c1953b46765b2f925ed16a476b07a267570c727592dfc4a0d8d00000000000000000000000000000000079ad05473fca57f26fd068ed659e4aa4919847dd96e683e7d4b3a731cc9ae0562a693abeea4fd550e644b43b553118500000000000000000000000000000000176a9751dbfe727a442797551254cf904862c4d590892e019a54b72f6a5a124d268777b82e19d557690ccfb81cbe949d00000000000000000000000000000000164ab74c150cd151b70fdd7d63d0404214fc9cdafba3bc642aa798b1c301c287ff6d05ee7b3a3ce997072b8189d54aa62774741f87af1d6942dc4ed79b70b2d706f3db6b6d083eef0475334ef1e2410a", - "Expected": "0000000000000000000000000000000017d73e29f1d555a10272043ac0900e80883c185ff7d087ee7f5a3b762213e658a42d1b4fdd435d1acb9d5587fa7e8243000000000000000000000000000000000ddc440795d0e4308577fe8439d43418641538711972c9744dfc8a4c206c193aa17958404bc387c7c2fa30bc678937f7000000000000000000000000000000000d7e43c0f99adcb02db99974e7615b4ca0de72117792ea515bb04c4bc8680a3fdb0afcf6a3bdfe16bf54c1d7336aa185000000000000000000000000000000000bcec1d7fc9f2210be80e90631810987801fdf60890ce197db041b6a62682fd7e181c6110956c5f5e9c196049e39100f", - "Name": "matter_g2_multiexp_56", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015425cbb7075a97dfa9409d7b014127396056dee6d4bb63ea285309fd91280fb691f9cb9572b544b332324f6cb3b1276000000000000000000000000000000000c5b9634e6748d5819396051322d9b7e0377554613a7fd8dc0c71cfb7886dc0ac29add7265af84087a9df5ae3799ae30000000000000000000000000000000000534226ad7324ed5600b5438b659c7b1e96f27ee1d77163f2d3073418f7ded5c613ca4b1a686764ecc43ce3388e0c32600000000000000000000000000000000198267e2bd474dc0415f47f5c87a11fe0945a91cc0bfc37d504ac53f9b9b0d087cd5dbc9b03972be03d4b3f9d2123945d10ffdd3797ad13e65a1115cab6529d0f87b91eb41d6265e694eed8f02667214000000000000000000000000000000000389a084d95445af6e0afaef21d3676794e45986b9520035111ccdbac4ddc1b23974a686a900616f878f3a06eec90db500000000000000000000000000000000064c75d1129753b5f399c1a5166a0f6a8f427d65ec2fd84d0c7339218e0a396681797bab68b33653ffb9820a6005fa7500000000000000000000000000000000147e199e8c08b9af38cb457b623d0fff32242b11e695f2adc0f136c5596db313b03c2466fb58e37c94704152e5c8f9dd000000000000000000000000000000000e8fe5436baf3470a19891b85d15486d1269e1b13098d837b0a510e71b0e6260700ea85f0bc6476217cc73615370cf003e5da5568a9427e0cbd7973a34c147ac2f3577d06f68280caecf8588ebf1591a000000000000000000000000000000000a39a2032858a57ccbfb940741f4ae21b318a56d5567cc0088ed52dddf1e0d5de60bd2da9b675212a9a28ec17fca7c0600000000000000000000000000000000039e2a4bb1b417f8a94b02cad60a3e1c4c4bc5a86a23def7cfaecbfd97d89a5104e0cd13870c9fbd010dfec3ad9b1df9000000000000000000000000000000000bc29c5623f9f18ec2af5bc651a65d89554705a349923ee15a9bfb82c114246b404a1dc1c24d65c8749e7c9cf62d963a0000000000000000000000000000000001496d76f7b8583a64c1627151589af876a2f5e7677611ea15f14606538f6052c56e9fc3ed145c313acea69a51547fb6145b5f1f156f3c823cc129568e7602694107608c1f9545edaa897df58d27b18f0000000000000000000000000000000015f83b2f998691e504aa740b4db38f5b0236ece3bc1ca933b79999d55b737bfec51e590c2127d57625a9b7c2960c06280000000000000000000000000000000001b7b117f5d722e320b7e90307ac1423aec5e30c29602d314bac9e5272ad3990d31999bf3f516ac78b2be0e16c0375d8000000000000000000000000000000000fa7992cd7fb679eb5f9f9a9febe9c3cf41a717c8f6fffbab5748572098407174f09457e13468165f1c7275d52f6c84b000000000000000000000000000000000737e95f62aacd12f8aebc288c5cfe052f34c4d16e7b44df4497d9a713b77485fb0efc09aef11c7b86eec4d0cfd9b03ecf6760be82cefac2843265be5fc0fd6d308c1ed06fc684c4693de25372f09ed000000000000000000000000000000000004d48d72ad4e77954ec6a5a62299f0472bc52b556cf3857019f8efdd694758f13029f9d6832ed672cc210f32033da8d0000000000000000000000000000000009b2394755d0319741d131b012ba0ece7e2044def20ae73fe73bcc276af9d807ad75be79202963f9a5c512a6ca53197800000000000000000000000000000000128f856fc4790d9fa68cd2a3c152d675453dd81dd64f0ab084c6dabce456f78c2bab0e7f315439b34f86e8fa61a33ffd00000000000000000000000000000000173dbb908ed617ffffb6aeb212cfe6c03f7ee51c84134fde67de2ad9561a897e28a0efa66257ae0c21ebcee3fe4fa68cd9fca4d166149ac9e6159ce95a06f790a96243662373637f0c6a59764b77b45e000000000000000000000000000000000bb7b84476d4b17f4ada0b6f50d34dfaecd611356862895c8d2fee6707c4aedbf565560d4207e43c179c5cd33cbb739000000000000000000000000000000000112d8b10c775218d318090dfcef55a903953f7466c50417125ec0b2c20a24fb50bd172331c0377d4f47aec99bd87a3fc000000000000000000000000000000000cf4e4b3c600053f45f350c8860e47621f50f3849872a91ab115f71a2b04657991217e2f0844b296d3a6bc33ee66e6a80000000000000000000000000000000008f625da164bc9d96be3e78df63bd1633a2951dbea0b98e359c6317abe6ac5799c4bb00bbc2c5d02048539e753019a6241733039312347a0c9d760c1bb9a1209a34a02b359a9c52a57eddced1575867000000000000000000000000000000000028db057ab9421eefd1fd481c91153b5c1ceb0f2dacb0097298cac986f036572c6ab0c8709325b3bc25bd494bb46c55400000000000000000000000000000000024be09301c9be4f726fbf7796e8336c50897e8534614c25f65c37bcfc6e724d530c2782bf483668fd08e91ad09484af00000000000000000000000000000000037bfdaa11660111ce0a9c3e18b5da74c004cb44882b1aea4173e18d3a17f04fefa3b319afaf4af9dbf3d4b9ddb2c3a00000000000000000000000000000000008f2138bf621237a286229fe762968a224358b030f6c20db58043c13727b516097b42d47781bd0f0df2b155197ca3946b21b18d883ef62084ce4bd353d7434d7e220e9cf6bd0e8d0bed1ad0a4ad94c7e000000000000000000000000000000000b4e2b058d6e77cf95be093375233e5c9c8ee0cb2a3aa93172c08faea111df81b9721a506180b7b45bdde4b58b0b7368000000000000000000000000000000000f7025cc33424a7c11eef47baef888535d938d50c0f40eb83ae86791834770e5dd95b30aebdd2c13eda3447d5730ce3b00000000000000000000000000000000088270ef05480ef8aac5c284358d8e06c3482c26279734b8513000019924cefeb396ae79f5d9bd863bdd9b22e3ac3c54000000000000000000000000000000000df75afafb138fb06bfd905c87035bc5d18c45a29267c3965131083d7e0112e10556d7693d424172a53e8d3120f0cf2aeafb6aa11296facbc13936bd2ba09a2cf9bbd9dab6ec8cc5f73d78c90b471a3000000000000000000000000000000000122fdd3c83c01c7cbe71f54d783181860e7dcf8406e3966e910f4d0ccddae3a245d6b1f94b1182d1917fd63960cd75d400000000000000000000000000000000043592e5797cc1409d6d42dacad628448799b24320acbda83f6ea9d232968efd021058f540e3bd73a7f95761efbb5fc400000000000000000000000000000000025b5a8577ec1064b5c557415a50e84c2302df97eb65860f979e5b1e261f47c0f305461681beb07e521cf03f0e21fd030000000000000000000000000000000017e86f3ffe72bcb71d46661a1537918d52e886e362d78ed756140a6b5083a4eebb5280b9eeb8a25251dec43a5cf509b13d39a61323c07f9f4656a6c5e6ba139da8175ebfb8a641de50cfa2290884662900000000000000000000000000000000122f26b4561d1f79a70bd0e401f25d50891c0fa0320579ef21aeed7c191fe1c75403a09260c3872cf74b798eb1587ebe00000000000000000000000000000000039a261d9f48b9eab6e89046f333ac328cea287993166057e9b99fa8a7d7eb3e7c34ecbb353b7427b235084f47f45d1100000000000000000000000000000000015d5e297317684bd0169c795d9dcd209452d024ef9a450c41beb0f6c7e6dc5fa0f3ae24c7cf2d7eef97bdc51788188d000000000000000000000000000000001487564f0e9d3e0d2d30ec9930a00f10093e29f2f195344f567960be323ca21231efd8528108dbee4d5ae4de3930ddedf6374d0849a4471eca96c5e715b10505c4c49664f341d04705fc688c8479cda4000000000000000000000000000000001965ac3a520c1ac39b86832ecbe226ae0474b76659076ccbb550a0daf41c40d424ceda084dd991f22cc53779085828430000000000000000000000000000000002e970a4248823049bb4339d21583fdce9540ec103d6e9530b89e39ea875b1c333f7f5f859be39baad34b374055baa770000000000000000000000000000000003460eafb3e54ec03fd5cc1d460e1359b97f5543e6231d61614c1225ab7545fae079ac8e65668b83d022031a7a54746b000000000000000000000000000000000321394863e7c70df3934d874613b7c9d6c331e59a599be593c82edb7a26eff9bee8e4befbf122240d2deb2d527bd38c0b7cb52b99abe10d1367f8d3def38221c18657a1114ceaa1c0673ab13a6e10870000000000000000000000000000000001a5eebe200ec041476457f8585cb4ccdda936cca4977d7701c44e0d4fc5d9c206682a23348013a055117028c16914400000000000000000000000000000000003519bd1dea70245e521988336eb41870599a877380c0a9eb19301f9b2caf963eb559070e23eaeefa4de0173bb1fbd8a00000000000000000000000000000000125707f5a8e26b28968dab97ef4654c315b0a118c20935e38a5a526d9ac0a0e18355d8c9f3f58c082de98691957e2d5e0000000000000000000000000000000010b58dd683f73a16d8bd5557b35b7003a761bdf7d90ef576de8acd420bc74f5219fe7f9d35667feeb3ddf1d568b56bf1f49b1fa80a321d4d100069b2c4b94cbda255d8e9f1a7f14ddf4762b76e4a386f00000000000000000000000000000000018267d8b83ca59d4efce7ee3d73f7b984f09556ea4fa5cff5997a1eeeaeb8bdc9185176d77ad0f4d86f2e429f4015350000000000000000000000000000000014114344d6b7c976cdaf2418d7f72c120c2fddcc65c3ead067482e7073e2a3a239af19f862ad247e3181b13f5236d1040000000000000000000000000000000015db961a093b248e83deea0ceeebfc3dd57c7cf8b48cd627c5c566a4f9bea30ff0ef9cab9287a0f520a72b02d9092a0c0000000000000000000000000000000015159439fbfb91d1e24af611563aee3eb498fde666a1014a9f645037995d72dca0ed5569da7ecd084208b7c228e8a2b2ad3625b0839cc1ab8c9798b2e9706ba6d7aa623f3c0ce0985bccb2ee5c05a313000000000000000000000000000000000e1780b32a7b17464cf514efc4bdb02283af396ffcf6d1ae023e07fae02becdcc3c467f89f8edc9173a71aad27b200da000000000000000000000000000000000c3e7fd95dd823338bdf3d82fd46c265a3f794d4065d83873b1aca66da5f80c5962c9dcf537fc315d024d8cab7bed89d000000000000000000000000000000000e4eb722080e24f54fac7eed4b94e7b1eedb081c3edd7aaf5433d00829929d8bdef940aedbdd7dfb0376b3ad5544d9cf00000000000000000000000000000000158c1ff057f7ffe6492097e339cc4ce56bbefd39658ad55e08d5407619d1cbea7c83b977a1583ee48897a5e9c0d9ce3e150e53fb45ba8ce5ca917010f26451220be51141fe21cfc1cc06a5557e8e7afc00000000000000000000000000000000138e8bc8cfaecba9fd1322a3c1682c9fc1286d78e5b6718da00acc69f811fe9f94c9f0dc9d80e9002c0022c6dfcf156a00000000000000000000000000000000021da679a068b2f5f473ceed588f07adc7f485003f7d2286a18c07b09b835881f4ab94c7d4ec742c33a7cf01801116fe0000000000000000000000000000000018a62c2f4a02b73f5a91f503b53332304afc9cd8769f236259789277599a203b8b304b38993835a87d7cc970ad514d2400000000000000000000000000000000179396865f859386df7c1b8fa84c4ee71c14daf695fc0841c293618e6f8c87fb56b924f3f91a273b969e8635d7f90985d69ec73df67feb970f1c7a3880ee84d948eab4d8672a6c1481d61efc6cd710020000000000000000000000000000000004a8cb437297722c0c1a9471ff083ce60ec40c908af4ebb570c87133df705e725e3209152bcff26a0d6e4602030610d3000000000000000000000000000000001832e55a9e703d727156e4677ef4f82b86c6764123c3ed1dd94ae3b46d7eed459114993968eaf8e21cf24c59d042f41d000000000000000000000000000000000f606d5ee57b188636334ad60057cec4008ace88f14ea06324edaecb26da627670b44b6ac57b9fa2717d03096010785300000000000000000000000000000000145bf70f90a9d98f56ed38b3506556a48a1340ca6161806d055d7a1382eed54e294564de7fdbf525b0012de3d25ab5c838f8acba4782dfbc02a14d4b1d7b2b0a582f9bd75642169707a475b1a7d2d7e0", - "Expected": "0000000000000000000000000000000018ca453b9d832f029ac8c7c70df846be97b530e6e42de3ba6943a7d0dc00296942f88eba6a9cc3352900ff124efaf7d90000000000000000000000000000000002e4514102aa3f772f2659ae9f1e2a91c7fb749ea590a3cea2c1a2e0f7236f71e182374cf7ebd2fa086dd921c29013910000000000000000000000000000000007c025696cdbf403494c5fc7f9a10ad0c549f84d1e06c5c4bb22f7a039486909c540776224bcdaaeb3880ae9d745dbe5000000000000000000000000000000000b5b5b70fae8b3953ee6661a0f4a1be25596839482d78710e584d3bcd93dff2b0bf4c8b20974744667e25fd8353cec0a", - "Name": "matter_g2_multiexp_57", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001265e90c564693db716f17d1a8815a8449e43b5a2d5446ca65160d864718cdfd413d5aa024e7581421c7222c29eb452b00000000000000000000000000000000133a6558baa53a2b8d239198e1dcd81af1ee46d55137177be467a99edf282edcd47b7861a3c822f9bd0df2e86aeb5dc2000000000000000000000000000000000d8287564bcedb1e57c3d74b0d484a9b475ce3f5b0322bda0e980de8891e2e8663abda99744b58032b8d7d3adddbac9500000000000000000000000000000000013cc35410d7fe07eac96abd2b35ff656e17b6b1eba2bd1d75ce5c87c5e76755ef9c2cce70f05cdec15d1bc44bf902d4cacfb05e5d10c41b06a487e9f8afa38759eeb55f0a5bc8640164bbb081c1fd2a00000000000000000000000000000000193f0cd6b4051cfd89f358cf6643528f0f042ae30ba3627d297b4fa2c2936426a9c1b65145b8192f65dfaad1f2fbc358000000000000000000000000000000000a92ca8943e64a391aa39126f093f2b530f556c1e3ea1b55bef1c264909dc93d260eec6420fb7a4e4a45f932d57951500000000000000000000000000000000005c7dc5832f744089d5fe034bc93e0bcca042ddd1b221cdd5958be86214831906ddbf82508dd91dccee467fd1625dd740000000000000000000000000000000011b11b3d24f44bcafbcb9baf62cef3f18b56ded696b73577375dae8108dcfb663d437e4cd9e44b7e6bf49741e058f8cb9a0b88d946231cc484550a87a548719f0a543c0698411f230a966cf602dc4de300000000000000000000000000000000073872ce0d74ea368df132897617aa8f941b67cf3fb395ca6c2f5bb2c551f17d68b0c6ef11e742206d6559796f06426c00000000000000000000000000000000156cc28eece7bed943c8410a44af112edd8576807e25701093eac0c9726f93da68a19c1d7b294f3ae6c84e32e7c2d5ba00000000000000000000000000000000050fe5987d5fa678be3d34c50fa6c5296f883e65ac3201c333b97ec0de00dee6187d2790c357a3f8822a174a534539a900000000000000000000000000000000177fee6e2d3909c0536acdbbdfc716f6ca19b6bfee7920a78ac9725c85114c69cd13152467e72270e35006b3c6caee8c74e3b5ff944bbbbf808f1f469a3380ee7dc37ebecdd8fcdbbd2f2561e0dcd68e000000000000000000000000000000000dd147bec9e0d1727c9d7597dea4a5b6b15c0a603dd1b586835580468148a502289fcc38194b2fccdcd8fdf0d8ec1904000000000000000000000000000000000186501fa4f3a20e80bf297e8ef1885b7d157617701839a3b524d61f35b2eb843ff0af13e253bbdef653a83e07a5871e000000000000000000000000000000000023eda2ed9d34aa253c8bf2f3b66b3c0c2551cc0e74f43dde2e429d9dea113a62572d245b44708bed79d662d9cba487000000000000000000000000000000001041cdaeb244803556e9b20db95f2a66830cbe47a68aea262865da50ab15ba658116657625318fe46fef393eeb6f3e2ec23064970a4ae4ae648a79edb193d98208418d3489e9b5b8517ebe99cc32b4d7000000000000000000000000000000000c27b1feeeb38068ee52b0fa440af2e3bcfd16601c8af983d259f2d15316b513ac3e89069bc141f02b934f2e474253ba00000000000000000000000000000000183f966cdb28f344ccae4cfda63ba6a6f29d00ab942ae7db7572cc09305e4f80c11305527b8ba38c40aae5f23165cf9400000000000000000000000000000000049cf59bbd6c26ab3e25b3cb94878271c73c0b4436573d612311feceed0f1668f4d79aad92360c1c97d60b540239ae630000000000000000000000000000000015f35eb8e4c40cb1297f7128d99b109ca75944c1943abe9158813432145a4a2a5663b55dbabfa48bfd9dd01907e1e8d3972fb60ccab83b6ce042c09ead82fea3d2cb891e21ddc5af7b5d8e334d5a3264000000000000000000000000000000000e5d9a671862733804f517dc9cae2190ef0005f26394e3161fbe771b9a486368871f4b1f10f405e45048362f437238260000000000000000000000000000000008100c6f96ae7af5fc86d9d91fbbefcc1bf5873dacaba9c3adf1b2833dd529d87f303a55e5d4098153377effd0f8114500000000000000000000000000000000010e4863a9b037d4ae6dff827a34be04c7f1627670b40e5cafb1fbca2fbf56af9ea6b24548db58e3119db64553d18cf200000000000000000000000000000000036a298ad5e8b32041a18e3f6c5847eaef20a5b63ddece41bd7dc4c4a54deb9c6d7002e6621aa01d78d64ec9991f68fbdb68c389b94c82f006fdc637696d8085b24897177d2992f504d4bcf5ff04d173000000000000000000000000000000000f62c0bad83c41887bf1ebd2644cef0577d793c2f3d67cbe43974f460a4afaf2e412fbf9ec97404e5e882ca0b23bd1a400000000000000000000000000000000191562ec9ace63ad2aae1f7fa977b9e0606e1da9775a978b2caafada4f6b3d9104562f2055fe037cd06df6093123a08e00000000000000000000000000000000156702c3feef1baf5ba202a25b9dfd5c1fc620e837501b0c5bcb85ec8b6e3e92bad1fc842bd1a0dac363e4bdf0fac87c0000000000000000000000000000000013a4b7e869ed9bdbf9671a5d8ca9145a2e97b6885d2a93b33f378e649e0e576be65bfe849119381057337315363bab2f4510c100005f2306f4b474d3843b4a79d04f0171afc5c66df70f631b0481dd330000000000000000000000000000000000a4b273438168494f0db235f535bf31893bb70f4119dc4741aa3c5e63e93b9a8bc001faaca10e37f36e130ef53853900000000000000000000000000000000010936551b148e16249dd934fcc83dee55279495c2a70d46dfc45945a69549657c3dd7cce00d8136e28d64b0c800344cd00000000000000000000000000000000115c053ac0b68573c3abd5f047b8fcd897e3d514945c5fe6efebf1921563d0079eadf32f7428ecb703d9163bc7811ebf00000000000000000000000000000000162e86af01daf552589b62be849e6176d74fa5da9b214a5cf2285802dbc44f346eaee5cc3d93a085740f74cf7e1b17e1dc682a2be4d67852d119795988c52230d8273648cc176ddc012a4b4da5a8636b000000000000000000000000000000000d77cb5045f7d4578621c76bf5b3db076661c72174508279280de3e92f0aa57057ab50180f0f908561a87d412636d964000000000000000000000000000000001853f9cdccf5e6e4b87231b153ea5257f52ff10dcb24cbaaaa95426d0231dbb355f9c47475d125ec1079b9bf26b23b560000000000000000000000000000000000fab825e06c2329a19de853a05c4bc65f16fa047eadba8e79607bb31b84ed6541b00f7f14b15687d67cb4cae0ef9c600000000000000000000000000000000005deaebb5f31a62fc0bc1af13da63d0af3c716df8c9bf00f1e831af5882b88974c49e8d35db2545747c85ac35156bb668af6b200fc8e6a57a954226d9a0254c8bcbbc55fd6c3db5cf8532323d4c50b4b0000000000000000000000000000000016faa5e91048badedcb33e83684d2670051c82b7a1d0ead0e28f4dddccb141a8ed1fa7606e4b6a3a893c55344263eb4400000000000000000000000000000000019b2c8758abe5d339afade4ad0c1d44d651f185f8a0030b81b136d5972510b353d43cef616ce04827d56255419831a400000000000000000000000000000000124b1e87f343a890fd690e384cd156da57f4f0fc5b1ca99c73bb0571332ec4c12d3ebe955e3ae792efadc1d5c0c67a410000000000000000000000000000000014cef10e4a9a41bf117aacd2fca5f1364a46b0c4aa0723a369fc6ede09dc76dcd8cb67fdf87ac49bd4bd9981a2e589647e2036f73e8cd5e42ad86914e192dd969465aed0c3b752986b84a0c2444c90b80000000000000000000000000000000002862fd5f38154dd452f65de0d3c1d54403cdd2a397ef416fb92e570913c543d3368a95fa114fcf48c3bb4b68895ba33000000000000000000000000000000000e7185443e5dbb656fcb9ed100949f8f7052ee2cdcba4f5c687a65a1b45bf66ede5c60b0c04845b9a870e004f8af8450000000000000000000000000000000001817be6d13cf2a67225b2eaf073e9f1614f3bd32cf5572766ace4a91f6b6be56f498b989f1c3dd3dbc9a819c029431dc0000000000000000000000000000000001cf41fe428b088a17b8ea93a653677705d5c024db530b8300752c6b100f2abe4c46dfc24afdaa2b3d53cd8ce0df1b6a70cd5c1545e76027c389645da1089fa88f675b5b6ef9217b584d7202b797f8520000000000000000000000000000000002eed272430ca3176988272e6157a18df7151bbfed5b90979752a02619ef467af8083208dcc9c7d926490b1283baa21f000000000000000000000000000000000a644f6137bde232c3a909b742d30bba096ef88b711ef100144276d0944487f9ebe8331483978a47c07d3a42c441310900000000000000000000000000000000042c67cdc10efa8301ae95d6d4f21cf152f04b235bad2dc5a61724cba64083f690b3158676ee6ef10f52dcc7061f7c7d0000000000000000000000000000000007018d0aed5abb744cb998f84140331fb2cef8d9e09c76176def48a85370c6247c2ac6fc726eea891b2041ad5edca7f0244041bcfc21ede8023ad80b6d4af4b2777c0204ca5f61854e6da34ff5e1145f00000000000000000000000000000000141c0edc966b7c845d4e68272c6a71f8ffb7fd8d56b7cabcd556a98422f830d7a81d123d701ce1479e84047328ac1f3100000000000000000000000000000000105c1164d721b6dfb05b6b69955b2f25db0e9fdb58600a3229dd516076087aaec05b837ade68bd2a19917eee7b9a22bb000000000000000000000000000000000da3dd97e693948fd6955ae52d493b3a2d2896dd4ad00a0b549d4d392e81593472e4f9435a8b7977f3d58e324c5b9af800000000000000000000000000000000068c531ddb26a2299cc584b5bbfb0235fd774a2447134c06e7de8b94993804958bbf1ee80728cc6db647e8a244462372ad7572da641373708bef008057aa5af1cc76ccb882bacc50a77b37d7047b1bf3000000000000000000000000000000001881432f4742dbe41bf774930413c98d49a781a48d6c64ee1a18f3076bc6c0e1214f92d5bc84ac65ee1c586c437d697300000000000000000000000000000000067e0a95f3eb826f3efeedc1882ecfa30b8b96c92f626aa324f4044ee74531fbfd50a221b1b0e0182d759d149d51427d00000000000000000000000000000000173f5be7098b756ea84f030e374973feb4f8811118ea6673db1db75ec6909303e571ec5a1d55a6bddf32fc80480cf103000000000000000000000000000000000f28540976a6ddb277df5951fe58e7310861af837cf31fe31c24f7b979f72ef1549372e7ea1ced15b655d24293dade7854b51c78093cafcb57c4c1f172d08257c379a9caeb5b5478cacb4887119a08c600000000000000000000000000000000188f296e218719bb9cabefd4f33d5728a1d280bc59c3d826a0f3b5338f92e6544a4cf36f1a493458e0adb246c01a415a0000000000000000000000000000000007dc8e4222c7ba78190a8e72ec7e6980e2581f51a8d6c41669b6fc9e16d50a2bf4d422af73398e76b2f39705eaf8a6da000000000000000000000000000000000b25a44523323301cc01b50d58726768c2cf61e691203dd34a0ce8d58fe4f72c1c33abfb2a56e0425fa9b7e2fe48e870000000000000000000000000000000000c6f11ea269d9061d2f462ac37401def1b2b28c47b84344d04d1f026add3237d99a586e3fcbae347a4ecb5646c8c569fae3bbf55186a89740af4da6c073d8c0e331542a2c972a49dd3bf65261dda6e49000000000000000000000000000000000c41a02e937f8cacc0be5d9f2d9fff0d6d4302fd252f32145974206463854b3a7d09b3b147cdf2d7536e970dc13613ab0000000000000000000000000000000005f9367f4e31f7e4d6e21664ac13d55f501f5368c1ca77fc439db60e1846861e6c4c3c44909469f88e02cd973499992300000000000000000000000000000000131fe6df7fff97f132bfcba1d2599a862c1feb514a05b4b7b0bccf49e00aaad043edae9346bf726e2eee498dbadf2067000000000000000000000000000000000e59044f0950a741da3881282697f4a1a522b026e493f6009227da4c0a963de622d5e421c30e0023f4118c9a036274f859b43915b15c509ab8930979312dea2ec9cfa9f679b004ee526aa5dbb25759a4", - "Expected": "00000000000000000000000000000000144433ad3afca0a9581e7e87220a4944e26ef2eef6b887ce77d2a2559ced058e7349b36efa66c492cc75b014b3448ef9000000000000000000000000000000000267b90e45d7001edae01fb198d16dd37c43cadcd2ca87bd7cd1f0f65a95148144f5ddfe75d344eb4573c1376aa2728600000000000000000000000000000000050ade28b09b0394b08d128c089808021e4c65dac49d9fb45efb93792a4faf210230b650fc3ce810fb8d11947e9af5060000000000000000000000000000000003b1d7dd7c6d944d16724fd1bbfe0f53b6b50a70e133dc5998c82b51f817f489bfe1e0c361be36fa41f5af7c1577f2ea", - "Name": "matter_g2_multiexp_58", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a081f037738b0d812da43a907e7c624e331108ffb72104d82725b9c14dec8449f5ba0e8c1a3f1379cad2c3e7aa99f70000000000000000000000000000000000937fb5d8b3c258b7b28555fb59620f114816f0fad46818a5f100bf7dc3332a03d285eda18e31e4047cb2606bc53b20c000000000000000000000000000000001574e355b7570043bf36ecd52f9c4d9ff556146d81a1e9d088444805db9b3b678fb55774865ad34d21022afea2c154590000000000000000000000000000000009f70a5cc658cdab280ed65e13aaa319049b9534a222217a08168047ee2491f25a9d2620c7343a6426bc54a0700bdb4fa53d5989b63ee5f157cc44c684ccc7cb4c74338b12fbfb534ea33db341fa6b460000000000000000000000000000000015a76e89c8938b8a27e4857aaae8c942371b6979605adf774827e9438ef739428fc53b65d32e4e152cbc6a4de42b8bf30000000000000000000000000000000019494030ae0507eeff20b69b4913596c1b9ea6927157945c8295e273707013ef1f2cd08c058f6b469a6c99ad73acc28700000000000000000000000000000000122ea7ac21a27ca7c4b00207538bf561f688429999332c45de7545046acbd6d9e96d31f5f6a00595eeb212918a28d2920000000000000000000000000000000018b023e7da67cb8d9159746bf700f9e151fa60ba8f5a28b3739de005822929cd28c49b9dbb4ca8a10729dd24771730ff4d840680013af06920dd06bacc0ce95cf0cf79e8ccc0b10027f2d28c1d0049980000000000000000000000000000000007811c759634904765029e955c3deca648fba6a9da6433b50a6d2086a59e65811d52d41ed8ff2e9bd63a4c0828bc702c00000000000000000000000000000000182c86cddf5e20697462c829f41c7b49e7976880311b01ed4d12d7174340799f19db0f295263a2617182bfd1b49e0d1b0000000000000000000000000000000011824bc20bd1b27876b4f48aa8fe3063f826b6b2c3dd777fb8999a25d9139f218f6f288955274884ce96ef2dc6d34d120000000000000000000000000000000000dd310d5e141e4eb13380db828caf74f62878959b6b2df998bebf9306965f723fcd4dae7c25bf2f79ece3e8e9b92de61b67d661ebc9008669bb4e5cffef81a32baabd71667a72f1d202ced823f09c740000000000000000000000000000000005667d8c4f8dc3f4aa0021d1026a1d0dd0bc3576c49339262e84d20198fffe33a389d28ab1d782e9d19af761a2f097b40000000000000000000000000000000002803d5ad6393d7072e149f1f2ebf70cd8961ba3bbefd648916a8ac5a5eb893b71bb6015e201dc241537ad5890024239000000000000000000000000000000000122e1d0e0859b04143f23c4d2d2ffec09ca2ce5eaa9429dd0c047032d180bcdb10c106071d9f9701c006e5eb8ef88130000000000000000000000000000000008347a7bdb3b4f381b58ed3a128134c09563b345380ec948943e738347de5b5737540b57c28d00b9d060c60942446617ee495199ebdebda02179432d42d5d9c76eead4d4993cd09a93d46cac997716a5000000000000000000000000000000000b26aaa46a279c482fb395ddb84d5b4c9c70102c336cd565ca9eecf62cb96f59f634adf46af748826590fe65beea752b0000000000000000000000000000000012cc63256a9f73f450e86ee38c54ea78baa5bf87d3bc01320f7fbd85bf11e19f75d787b9b12b8f2c7634368a9023de880000000000000000000000000000000006392fe611835f6fd50229725d71d435f704f78cabd1b5569e1c5a89d4b11f911f0e34ec034369f972a80eb407938b97000000000000000000000000000000000f4ff2d6a991fde9093000d7bd9cecb289383d259346d83bc9bf5389d4c39c82a0e1d7deb84b90ef370e0a19fce28d2b3e038e473d6f965751ebc5f69eea6f37be88cf001de0c4e4b700823d8326f17500000000000000000000000000000000193752c40fa0f466f7c8bd26658f133d0283d2ac3b02eadd27b3e9681329307f91a1512fbc53e537f9e1025a3d68a7ca000000000000000000000000000000001106d751c9e1637f00e51e0be856405e6b69421d81bb30b9b8718cbc9cfdc36c80d2848bab0d5246da84f10b478fe48e000000000000000000000000000000000827a83f28678c4e39c4963e95c2404a70691885788e5457e149c0c45d4e8c74eef55223ed15cd75fad9f7209a6ecaee00000000000000000000000000000000072667f02b781c8e0a75d0ed8f3d55e668ddcc8c61937c80653e240c3a744c961055c782ca41b15211c0f1e1ba800bf5ab2af2590309c9b9177e4f6f0fa06339fa720cf1c9fc7c001785d7145a3c9030000000000000000000000000000000001419629aaf0baf779feca264d0d9846b987506125b0049ebc8b307c4e3ffe00da1284a94a012bfd60456a4a937b2e0e000000000000000000000000000000000119a801bd0a5a1c1b25cebbbcccc7d2bed9baa4995483f4ae94121a8c6cd0c3f90a26234f51590d66cc38b8bef9020d3000000000000000000000000000000001125bd15fd9814ddd15be0997a6961b6f1c05ce7944514371f10c8e5bde271c4b936d6537d91ebed740fbefe6b281a0d000000000000000000000000000000000982a2904a524b1fafc50d540506b8fb07c3b4978310bf3cf53ce570b1b05e746981bcfc06d59a78d170573b09347f3fc9551f12084ad7d4ce346f841fef785d644821b5c2d3c8db3145fc26e65666bc000000000000000000000000000000000b1da333e508ec6b0329747fef35cb926d922091d4a45eab7cb5358f20496c66e17e46874ed9600cf4252432c29aeb07000000000000000000000000000000000c757daad8f3ed7dfd64782548eedfe904f7ef3bcc11eefc4781fb37159d07825a4c9f3fdf9cb3d8f3944277bf25f88c0000000000000000000000000000000011160e21503d6fd61a2ca0212a7d48317186f259a987a17cc3eb04a6d9251736e4a66b739a8f3095684b7d91ce6f79730000000000000000000000000000000007440ec0f9197352a3148f9bb3d3dba9b1d5add903e48b50ef3f6879859b22ea0e31b46ea4ce566930d8853520abdd14ef5823541696ecb88d0c71e00a15282c40d4826220a202be09c47fd6891b93ba00000000000000000000000000000000070ffa4d522df8b9f62aaf36132bb1b857e177280a7b6d3af6bfc79b73ad3848241df18ca7f8993ae3d67005ead9264d000000000000000000000000000000000e32b65bf035bcb11f86c60a334622d2367797d0226761b58a7db8c7324fc4bb498a558eec509c2326fbd0e7bb8d3d19000000000000000000000000000000000dd291a760393c6e962818986727e5ca5d46544dc47eb49dd828c6f74caf0599e88c4293881714c425b0697944faa861000000000000000000000000000000000f7ead0be081467f3371ab92c249cea73dedfefcb6aa16a162c06e30605e104844c3dd194b4a89ad5230f596bef64f19e32d695dd02323d40ac1eb9452cc53376ef941237563b1ee380c9824a565008d000000000000000000000000000000000ca545b53836899e507880329799e4c1a1acc17275f5d71d87b9e41ccd7a090da854f9936254448c988ec772a813bb6e0000000000000000000000000000000016c9b03fd01394560497d6a03add63c034f96744d96a13a4ec92d28719018d1eba1465e4332e53f37f2aec4d93d4ab7f0000000000000000000000000000000007019f5201dce326d5a6a1ebecf3fe50e22335593bc9d3e62256351c591f0a1a577d916055d79c0b4abe191b6b8011fe0000000000000000000000000000000017acbe72fe30c386e463f3e9b35a474b902f6712b30af88ef340e6fc6ec0fe2e606c7e26432c2a4de33a12e35ce41868f5e23ff8acf88d18e53bb31476f10fef288e20e818431f9f0d2ffe1265e8ea8200000000000000000000000000000000057f856ae648279f2b6dd17584e1388e4dfdc9e870db48ee6ef5f58389ccd4ba17e074b79ae12b728c59e2f91bac5709000000000000000000000000000000000e0f39f4beddbf05fd700458448067b52c11e963b22603f10d697d6b6286b1449b1663e032bf7bea48f2051d8ded923f000000000000000000000000000000000022cfadc1dc399ef5f12afe1349d9274cd595a9ab6ef7ffdd68f8bd2d170a4a783ce0a7303878d809a16bb8073d79860000000000000000000000000000000007e301565124eb66d59a70897f2ac356e7b0c1bfd4e3b57e508ba0cb5c9c881f9de86b91fd5133aa2977c8e81138d66971927817449ba5f053d0ed1e567b53b1179c6b62a554c8be6764d7ce203f74e4000000000000000000000000000000000edf3fdbfb03bc07871079aa4aade538a97e1619b54d0692a7f5f73d7fbc8abbf680ea3a99325e03c0501ef174deedd1000000000000000000000000000000000b8c1b5d3c926d7da6e0583f67d981af5286a04429e857b0aa4b1120604f9c8c93f04e763da169137416dc9ec4839a910000000000000000000000000000000006ca2aa4c7109f043da9cd90bc801404685db802eb8bc925d9d098e7af3d9f95ca490790b2b1c77995c050aaebb935db0000000000000000000000000000000001f40a2090b63f94f93e8b61b5ba1ac62a37548342ad81a9bd99ce8339435a7d7477c3b9cee9b531a1ecdc85a72041555ce5d6f0e44a20d0a0e2f1cc523455b001dbeef772d84b2599daec66b285027f00000000000000000000000000000000021464dded318cfa86db1e4329f302bbeca7095d910c4260799cd2a60ebb20e60152868e67a48b86f44000f267d11c33000000000000000000000000000000000ae45fa46fc8e043c3df99bc0d87ffc5867208fde0eaeda782230341a8624b101346f35fa24e1dd67ab200f5d6fbc8a7000000000000000000000000000000000795b9afedbb128a46c1eb25c52a71375903adf7d3520535372d9af5023dadb1dfefdcc0cb546e9d218890123252946d000000000000000000000000000000001852511855bb368cec51c54d95b430259f05dba6bae53b5c42d69f31371c30cb611037fbd81393a896cbdb6240114549d37f7bca1a59f65982294755ddf8af7f1c953b6e482fee854e0d89e9b269e0e900000000000000000000000000000000113b883c6bc41b0673145bfeccda414af45efe5710f436977712e7227f38911cbae851dbe03928f38e310033458eed72000000000000000000000000000000000853e32773ef1f95a3936aacbca50cdd5eed3d08dc467d7ee834487e445fbdaeddb0df394bd0c91fdb06d2883c4dadd60000000000000000000000000000000013a7f9cdebb2ec37fad172d31a717f4b538a8ee74432c5a5e6410460eaaa3b5f24d223b76bde4277097e93087b7136330000000000000000000000000000000003d6f141b56e1e2e400fe821524017cd972678a7d64f660c313e6a8910b72b5ac04328d45945077aa2946931c8dbd11706d0535e3728b9e358d9ea82df4f1137db7a02f79c0cd0dd672e24092bf7f6b40000000000000000000000000000000016adbeb3530f6b451d870b2d8292a01143986cd9890c79a64764383575771b8608ea61beb2de87bc034d3b8a085958be000000000000000000000000000000001125d7cf83239e4341c286fe0c8739e7013b234814b26a079ffbffa329ee4705da81fd12f34f49d821690a11b8f83c5e0000000000000000000000000000000005873dc5c0baf0f3297d884ac7b652c749abd0405b96ba60fe396efa179a79fa55be76924b0690c9a528c605ad4f9e120000000000000000000000000000000000fceec23f479c72e0fea0d10d3394d7121bf1673250cf1ebe72eca60af82f232fbee342e2c8705434394d4e519fbb40f56d6810620e8da932c202628c2fa9f0a9f3fda3aa07c262924aa51685d2c9af0000000000000000000000000000000005ec966cfa28e105f3496f977a2f046fb206a190fce1a6062df0fa1946f274cde9f6fa8a71089af8cc2fbc2b60746cf40000000000000000000000000000000013c77ab66fa92a2411391d366a331a40accd120db1c6a656bdd92858826fcbded296293c13ee189ea3f34635de56732c00000000000000000000000000000000162795b6feaf6a63e6ea2d34f2bff2a4985ad26463b8fac69f8525eb0a005bd377fe7ff4aae820d361592d2d88f98f5c00000000000000000000000000000000044c9d5d3bc0d99693f5a0605ed467cca8b5dc7c7093294d14015b59bfd8ac6bd479b73ed52fd30d8bd891ed971912c571e7f672ad398f5c02c989b475d12ce86e6e242d36784308e56178f2a6a1517c", - "Expected": "000000000000000000000000000000000c3bed2f51a60f9afa6655853ec2f0e9d46bdc1277bfedffc468d9f36cfc7ad9e70365fecc84a5a40d863dcaadabf22a0000000000000000000000000000000008c5894a4f93b02fa1deda8b556798fb7d71f53046ccc305588bfc00b68bdfc34b3f0bf154ce7cb50c9536ad45e65f300000000000000000000000000000000003699501ebb9698e98dc998fcdac54dff895457d2e4e0a0e2d65d275b5798dc016e921bf1f65fec0f284a563aee66ca70000000000000000000000000000000010389c73de7f6d860c972c1f09dd24137c898e92935c45c10565ef3da3406cf521647ef80688f6e799eef4879ca9a6e8", - "Name": "matter_g2_multiexp_59", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000114b9c33bd09899c684e81a5a4e620eefa4e620c01c391a4df5caa75be462ec7ab027a9ae2c31d6643c48e3d75b6ced6000000000000000000000000000000001925084d2a1f537329e23c77b8a820c385ec5e12e4a145888882ec611e99b05b789d79bcab48326db4424309c24d1688000000000000000000000000000000000a1dc78c25cd16211a38bd0c70d24c84da1b83adb219e1b9c06fe6a6669d6e0281a155b4cec32d32751fff653aeef1990000000000000000000000000000000001daa74f19cce1086a87232464ba903938465da5e3e1f9ddc05a4b4dc13f1026e1b07af7254d515d2ad6960ea62dca1f77f9a79850b2fd5a281b22f52de085f12bd34e56808496e1c1388804f534d2da0000000000000000000000000000000018810adf0cc793c21726e9a27b7c558aa16b81af73f22629c478d293208a107fbfed4511d9cbcc25fbc2826bf004e7dc000000000000000000000000000000000356b25cbc7cf65107438125c930dff24b7786cbd7eb744d7f27967619d5cc02799451ac8814782eaf9aa331e6f8dbe7000000000000000000000000000000001164ab32ddbeb11c2c8baf7f311ffb01bcc367395bc7ecbe5642d344a8e879c74a554b3f9e4b6ed7db4ea0f872cf96740000000000000000000000000000000017704b1dfb111807d1f5d90c370a5b2968008a5ee9fd72262b6543c93fa168285c04931198f5195f1abca648722ebdc5630c1fdad9338fa5236f817bada168a737dd3685b327fb59d8a37329920af4cb0000000000000000000000000000000000a336a04a8fd8e18dd9a582da897016983d9beb0fdbcea6c88b7c0640620be52bff32afbe700599e3c08669c457b760000000000000000000000000000000001765fe4faeeb13fc2c007682c031ea7ff2899090e16a9a11959c5c3ae7881a1dd2c6d2b7f5f708a92349a2b0de4b92d5000000000000000000000000000000000e7c57db660133ebeadc2cb2054ab4ed16355466932685d4d11038e1e1f47b0349b68bc4e918dd48ef8e1c5d7cc53f7800000000000000000000000000000000169b629ddd7add588b91d9866a750570dec58662e43409031a5e25f1b2913c5c5a7a7cf666953c99835431f091ab1b140969599bed4899c3c47e1d4081027203c73233536cc6e45aaa78a4f1150a51620000000000000000000000000000000017d03e9855f3bbee719a15208ae24324ebf1879972ac134b027c9e03444a5736863bc55604158e81b38c7fd78ba4bee7000000000000000000000000000000000468f7c5478cc0faab7098dbcc455bf18525b56272c2d02cc1febc1825579a613edc6b455764ffc71c903a0704224a4c00000000000000000000000000000000067104ba5366e7e11bd4d516565d9cdd93d4390f2af3c1ef2ea3b1e84ee8e5c0e0fd8ac11ec9d2553e4cc13b277d473e0000000000000000000000000000000012e10495ba15b29c669cb9683b2fc7a45fe7ddba743b4a39677fbf85aa738480eb9da967eee69b02ef14137e102e240eddd438de35651328de7183dd38820ea2983488ba31d401094e59cacfcd1d031900000000000000000000000000000000078f8c17427847ddaa1665d206866231a5f36d3a7b4e8fa13910161566163006b5aa5d9696f423d0c44195de65326f21000000000000000000000000000000001613c465b65940f43c61b5e3c93313ae49d92728518d9cdfc57b49d6924479b70e281e724e04fa5f165b5999f1c1ed3100000000000000000000000000000000031741b6830c16d730619457d42767a51037fb4118e00bfd6cfcd8baea35ae76a5159bf1f4639fc2951f0b57446110e70000000000000000000000000000000011a618ffbafe4bad0a435d04084233495e5f7fbeaeb66d0d49a8177f562329b52a5ed4fdc680b791f273a7b0d3d4b349191f2b2cc76d848e456d07c84c0826a8861981dc84bdc671bc9b5882d387a41a00000000000000000000000000000000043c09eea638e524661c60ae3704fd1c18c46443ae134a0ab7b9a98cd398377febd9026c28b3e1e50de98766aaf0083600000000000000000000000000000000105918aa1476cf52f91b9ddb7c23ac18af3bd5269dbafc369713687010720affed6b12af9414cecd521cf0c7f5416c350000000000000000000000000000000019ab4a3eca904a15782f560bbbc8819dc09275f1f6d7c3b8e98aa0a96ec33dcb528284636b0f42ad0d503489d17161ff000000000000000000000000000000000a2abada18e79c548d5829991a65491ebcfe0e1a2c89a1e05f06a0ecd197797c5ffea0ae90b61f54c6b3fc844e0eb3ddaa76094782d0c06f2080d699b81aa04a60891046e0053d2fa757c7029df8f848000000000000000000000000000000000d457cb2c77acc8ba4b19ade0c724a2b6b0966ecfbbec8cbea745439b9bb7f3dde2febf9fcd6c5e6139fd7175e57b1720000000000000000000000000000000003154466283addb0d0b5d86a9633f8300960cbe8bf6a1405a3a040472542e9da63fd4f79a43d641a47c2b69a31298d3c0000000000000000000000000000000006599794823797f8ccea9daf0459b9d26e0d207f5fb95383c6b61eba38516b272e8ae6ddff2a9fa791e69c0eb25f3e470000000000000000000000000000000018be316bbe0416ad7deced1486d4e31490f5dc7e379c17542b7d3e9dc77bbae9c992e657c884db320cd51c2141a4abd2049a751a406657dacceb3721461417571a0104e11c1e00805becf71ee77eadf10000000000000000000000000000000007ba1ec5293d169b88ca4d2d92eacd51f0b8cffdb403632ea8ffdebc37f3997baf736771231335d12717cb45b51be31a0000000000000000000000000000000013505cc24222fb2ba9e25f5f3497653462f5b10bdd0dc88f9b16d5643a99ddd4a7749dfa6b566f41cd2da7c2b1ae93d2000000000000000000000000000000001465fdced698ca76d5faaa7e4faf1260cd5c4fd2939b16d3593e3588c92de3d003540ec989be9632fdba4ecae889ef180000000000000000000000000000000013a20cecd5e8f161ac70e40b8e9ca4c23e2b267690a3abea941c293b03acbbe4fc68a1e7b6d35b79ac46f65edde73a3e0502d56084d1be7179fb735e233978a5a3c2756d780cc0ea6a8aa92b1d1f7c4f000000000000000000000000000000001936436783f02f3a5307bfc0bd8c0a00ed8013508a440d040ed4f45b37a4e89986102964a328e93fabde6d9dc7ca424900000000000000000000000000000000000f16408b869303181b4b4877b554353b26a7b4750b711f3c41cc4b6682b2113cc772cf9bfcd0cf60e59ef29a5d0814000000000000000000000000000000000d5880e2ef94663ead736687ee725f7ce98fdc594230c1ac9e8345d39754bd616e261076aa5362776a6026129bff105c0000000000000000000000000000000006865ce3cdb5081e86535beb990d95ec3d75f67c7e881306607e4876c42714d627f8d548849aece4382d1c8f2b693bdc9787a6720b8db1b4f0e1d535833ed20b519a0e4d2e9fef75022aafef523713750000000000000000000000000000000016d941b6a0dc023fa2699c836b74e16c31b4cd51538f73fbb271d163519d4de1cb0f6ec2f8efde22c74ffb532c576b16000000000000000000000000000000000d10a7bfe9541a7b22d455f1b68cfe2422a83a070d93476aa0844670f02aecb36e9f41b9d66e8e9d0d67c0ba85c99f44000000000000000000000000000000000d7873f96d45fa8c9ba9cb4913a7b01c8e38876b6bb2a05506d23df0491bcffb42983ef663db85bc3cf755f476291a79000000000000000000000000000000000c22fdb83f9991c85b3577d1ed5a171f28460d79dbc6167b0c30b200235c512f999066eb1fa449115aab55128f8f2dde10b47b662e8cc8dd005bdc81dc6d98d0eb98f86b46c0c8f24481af9120e84a820000000000000000000000000000000010faf9cb9d0fcb487c9e86a2d2123105baa8691d82ebae8f5bb7d5ae7b7d8154837120eea86dfcd35ea5482a7ebf7f8a0000000000000000000000000000000014e40640eb6e8e38651a2eac05165f6cf5e0178b3711f34828766ff9db951e1348f0cdc652a78840dc24ada8b1c835c600000000000000000000000000000000129db7482ec62873591018a8399a8c5e4bf00e8bd9dd78dfa3d0b4cd1d93ce5ec7531e56d58b7a1cb3e58f062f6895ee000000000000000000000000000000000d8db3b54b6e71497faed107b31f5e44f328780cf01c62cb5ca00f99f10385ebb22a367cc89505640d1106a9ceec98c4072460e3c5349c8fec9944dc99762625262e84c70f10d0a92077a351335127470000000000000000000000000000000011ae9bc3ce04df2add17e57f260a72f88f19a1e44b0b074cccb7fd547035038d19e5f2228db46843343a69823decda370000000000000000000000000000000015ea64b6147ef76212bb5223d6d5ab9ca866799365683720866d8ce1117f60bd552a8e9981c095894258ca3c1bb5150500000000000000000000000000000000173bd5cb455b80b78951b15180fa7f8fb4725c1a12e5c53df1b9b31b45a29083e66c7116741d9aa93448c81b5e6014610000000000000000000000000000000007eba059855ab058c2066c643ef5268c864d09ec9962537d65a1686322c374eb5ab8eba4c4260ad0919dc18b4289a694f3177c4d865caebf1ef6565bc85e0b0bd51365a6f321e26b97cce887bc3f44d6000000000000000000000000000000001598471460ae082c2e2568602c99923193c913b9e803cbb7a4503ceff369e8c4bb3a19ad245c08192e12a2e9b3e75c4e0000000000000000000000000000000013b289bec9d97c529382388f7037749c10a64f915746d23d8f37e15db9dcb173b3a6d00bf45e67b8c70959472148321d00000000000000000000000000000000094a99f9b031a51b7d54f7b8865621b204c85d23fd66fe8ce007f0b852f8b5b895010745b2fc469abb670e38fbc41e50000000000000000000000000000000000e36daddab2134f65696ede36c50f90f9a1c56165e09243cd56fd3d9902d3c78cd85e7028f6dd466f6a8655da62ecefd393654ef7ad8687c8878c55a8240ae9df04805d3e2f194e960d5e498ae3ca17700000000000000000000000000000000050a818ce247367e8b57673d205d6bff8c650bcab7bf794dd32494669eff865fd4e05d7b4d35eb579eb475a3a0320ff80000000000000000000000000000000017ae5d612bdd46e1351dd1367c08c16ceb002a29832eba75e48d4c82e364f17c58525ee653a0940955b874da6a5bcfcf000000000000000000000000000000000eb2075367b42a0b3dfa30799ce1ab327eb583316d15b8cae21b716e6c7fd8cab96c67bc39e353f5e842e74995356c070000000000000000000000000000000018ca4b533da1baab37f05afc3ae0afe976e4f4530401d2f97176f5c73de3eaa75b8a34e8c6c0543ca0a08aeed28e478bdb9f942124a381b150f00a59e4579d0a2b7b728f62715633288fd03d01dd12dd000000000000000000000000000000000b3f4bfec920018663bb39c5520491da5c538f82138f03390c768e088bbb2880287196af937f1f70e215edd49d1872ea000000000000000000000000000000000037e7607a60cf235d8e4ecbe69d378dc02f0a8e40b7f23745e15a73fdcfc971cc8707d55a8c5b91d9a5f42c2f49c455000000000000000000000000000000000467df75c2703ccff1a01fa5bdebde210b61b5f3fa33e76e55be5dc953f4758c3a2c499cbd42b256ff5a2005949d9bbf00000000000000000000000000000000010d574c69050ce9e909dc23a76e9a2106870e8d8ce2a0e30d42cbfeea56ce3167535a9af1d453d4d8e6a450eff870638e6eb65778a328cf899f66581ac7a4a89e0e824c15573bc68c02cdaad89cdf24000000000000000000000000000000000907fb825f247c85d93fca36dcede9c22a409fa82fcf540593e8247c17875a1385fe009f0ff43853c404f6c96e2809ce0000000000000000000000000000000012bff10bd4162207870f6363342f2541804adc6a4e3f7b8be51d361be34def7a85fb39357c85a4e8df670fe39233bed00000000000000000000000000000000014f7e61ccd52bbf6d050c9d506751e03c8771b320872179a9f0161ac5736edc13bc133bda6239abba1ae09bd6c16f0c3000000000000000000000000000000000ca78624563584f8929d72668da70218a2da12b42c4b894108e6b103201372554fdd6b3bbbf2d94a9d0cf4053eb07d460940e3620c59504062e4e98b5d4c8cbccdb017c47a094d06253743c29465731c", - "Expected": "000000000000000000000000000000000de8e87899b294575392d523ff6e153a7c2038302ac74574bfae7fb222558f2b4c9556be1bc2757b83ebc180ae710187000000000000000000000000000000001881c7688debe3ff795788c90397c3fe3d6d9f56da9221778d7b12f5a54d8c0a00e1a8d4bb9c0b1d578dff862516b5dc0000000000000000000000000000000014cdfdffbb956a20d8521ccdb214adab14975d22ffbac107b2c15f42e97bb823c6a3945a5b299d3226e2044e64f8d1ed000000000000000000000000000000000eb769b301cb7c0c976623badda4db8ccb18dc7322472b5fdb969393d5d82b3ce94bfa59dae06ece424bfcb88e24207a", - "Name": "matter_g2_multiexp_60", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000164227fbb787b2d47ceea93faf1cf7890f48107ffae3628192235aa57658d9a2861db13fec0e58c347571c2ab0cd11ea0000000000000000000000000000000015478417b6758826b1d6fe0c562d43451e289dd50de31ef365ec70faf961ebb65b510c4788b6c7da2dda9cf56d3c8a74000000000000000000000000000000000f9e50d802ca8cbf80caec6489fbb24a2761db1245d9f7e820e6747bdd0855902ff211c427c00157ed9b1bffdf39eea900000000000000000000000000000000128f69ef5dbea5f80dbb9558a25f133b9ad77492250e0654f8fa5b55266f2fd26826a5c373afcd74990ebf768d6d8fd20f2f697ef6783390724e04b81d0e18dde6533eea9f72c1e10bc72c7b954659660000000000000000000000000000000005f7cfb31492dacae51caf4036d99d917fa13b0d2353bbce4e6547ea744b3a49b162deac2f107149ebc2f79e74828f720000000000000000000000000000000015ed4627efa9b318cbb52f518b734327f5d1cfbb097adc6184c5034620504181a298ac7e52759586dae2e107f121a9b600000000000000000000000000000000023e832638849599d9d7854d3ae18648e67e8938ebf606a7c86c3a7ea21cab8d4dd5d9cda5c482e05d351ea3ccd854710000000000000000000000000000000001849665396bc36d0301f4c9adbce81fd2f2d0c7f89925487d91a25c6bd0730ce31678694a319666cf42162608ef15a834680b934e67bd7518f0d6a3a809dc7faf845eb71d0247291d61053d5cbe0ba20000000000000000000000000000000012c9b607e29e35f260f3c4617b4217d5dbc6953eaeffaaa903710195e080d593972e7794897eb176aae3539401a483b10000000000000000000000000000000019cdae8d1d9035d1fc4b4db09e7da3c20d3b8777523155d407cc6565a71a6c951eca609d328ddbb165c2b5a3e6b081da0000000000000000000000000000000009c4629b67c1c50e5fcf316136bc645e9e62ffadac8495c084f97e32b0a3990b3b1019261f78de576ff7ffc89e36e2af00000000000000000000000000000000070a49e8892c5b523f5914e2341dde63127b694eef556de6dcff603da109a53b342363d9a854dda3d2833e25afd5b57eefc024dbceb522c02b88810ada9a814bfd085fb63d570663a64bc0658e5ad0220000000000000000000000000000000018d3c9259f70312c803dd6bac6488541f92482f7eb61ead71fa42bd5e2cca9338218d62835051bd308799beeed3b422b0000000000000000000000000000000005e0da6859601b6ada82b1826a455a846f8b4e54d9f22c3c639835a8a89e17ea2d76e2f49fb151f519de3e9adb78f0590000000000000000000000000000000010113d2fdc1e8ce0027b651cee6f9f6832b531d843db3ef7bf209aa00018715c1c42c68a82c53247a267929ea3c9363f000000000000000000000000000000000e7d1152af6448aca78aa7983013395f0dfc298848d86def6f017780e9cb144bbb21540a14a4d47b61d7a9b8c62376fc2c136f00c97a515076f6a0b63faf7e378f2cf04f8a90ac942fd70e25e683cbe70000000000000000000000000000000014125c81d4d7a8ea18004d798311f0d80c41c8e3a08366f686145e867192bbb13244f9f77217559cae72a150faba12a6000000000000000000000000000000000fdcaaf79c0607ebe9c8ca309d29d32284f3567a18dbbd23da9d96bad7269395ec2445d153711df4c883e8e7f7b02ab2000000000000000000000000000000000d34dd6636ef18b14f011fbeb62d33ec4358166f96f38a54c36b8797b51c1bedafa43d9f51fa4afcc2acc0cdd991997f00000000000000000000000000000000017337fab49d545caba55b763c23ce9bb3d3cc475f5ca37a15322e94c37825fc800cc7ee67bdcac66f9b5c22b03bf6558b033f2270ad2416d03dedd4bafb78ddc598810768fafd349a42438923ddfc930000000000000000000000000000000013434d32deb96edafc9a0e855281970b7c748c92b3472b34cc758dc3c17c4e6fdcf3190c910fa54a0259ef8bec75a3b300000000000000000000000000000000137df92ec14dd2fc02c0ec15a4e63547492154b4d4809e25f3ebbf24fe84255babfd6949770ba61637cc67e8ff299a2b0000000000000000000000000000000012fb20ef106e8cf3c79173e15dcdddb216c25a4de6797e411fd11d5632aef1304b36f8135c915c8c38caa2d778788f060000000000000000000000000000000014ef5cbe5711a815b9ff845e9201745f4117149b54ea3c6d1606060a192d513aa8ffe73425e37a42537773796b6fac8f202d0d506bbcd56c92bfc6fbab36bc96716de1af02aa166e7db2e2a0a4c19cd7000000000000000000000000000000000b1581a5def94e95e565bfd402cb84f2f21c181639c047d8f91044da84bb7854f5cb4eb3a6cdeb66569d99410ca3ec6c000000000000000000000000000000000d8029828f4ca245cafa7f396c25592ef08f6768e1a5b806450be6ca5b548cfb212d8c4787c3f15fe922f466dbe518c0000000000000000000000000000000000f51e01a044b6da437e3850349476437e4ff8b94fa190387099b17e6462040918cb2eba3b10d6044ff2123242005bd6f000000000000000000000000000000000991201229a856f88348381e1f2e282f0487e7daf1e5a4ac3854e66fa3d1303e3c20eb9eca605859e7d46dcfdd7615cc8329762dde1c4c91043a740a8b9639e83e809f749fc8c4853966cb2ea520620a00000000000000000000000000000000011f1bff5df413ade311b0bc3b46c4ecb11e386b886b71226987f14bc1a3a4b986412c2bfe8a4618ad5d70afacf4a3b4000000000000000000000000000000001972f49fa8b36d11d9c9d4ed6197261506b892ce6dfa932b87e686cb197560dfb8718aa413c38ee1bb771a5618c17224000000000000000000000000000000000e563bd240f5e18b518a792750c00aa5dfbea1f79b80a71369238ef15df9885d341d6901fb9168a2e74249f036e9a688000000000000000000000000000000000670e59ebf6e30b458ea505075840ed5348563efd536c31003d8d0bafdacfec7ba1ed401c616a3bab431a0fa71bb6188ea46572fdb37fe282203172c147715bf0a16e02a62bc79f33cbfe36703c95a7300000000000000000000000000000000071319574a93739586eda876ffd3be5d982e6fa04f5667873dfabfab83ddf603513394e0dbb9f418e725b02d2dc7b876000000000000000000000000000000000c6a8e0261da2ab499bf9a639a6e261e8c479f3f2b2d12992b41a3267e034c25373d4da4645626e6343e867466bf3626000000000000000000000000000000000045a0312dd5fccdd19edb65e24d5ba50e44689a9748ed9ec208320bd9eddf8d606b9340cd34ebf983e69a65c242fed900000000000000000000000000000000090b3dbebc7dd49e9f764e99c43b5915b67bdebd00d22c80e36e08873e5c5186bcd082dbce94f4f230b237d60cab7107b9e49472b9b74cefe5a951febe595b0020c43fd54150445fcdc4292c5ffe65f60000000000000000000000000000000007b04063dc315025b8545cef11be6b601fb4ae02597d75979b4946f3872764ffdbfd309f5ab3b36fe47b810f8320c1b40000000000000000000000000000000009361927d02192433a8d3c3d7871d76c6d88361774913067d16b68625aaa60f5a4ca19b6fd4140a5a11f92dec57d783e0000000000000000000000000000000012501f19b73fc6ddb4d194895e5cc2b89ca84defb7ae94f3170f25417965102fc195f38dfb7a2d88aa4b24e4a2fcaa4300000000000000000000000000000000141d0a0be60c32247f6cb0e0114251ac68c90fd43651d58c3108c728601ad6efc27c27a331a2f086d55aed54b3585fd1b6bfa1ec877010aeab030b96e80d2e27b45a93c6a99e2aeb3ccef22527c6e47200000000000000000000000000000000043f74a82ebfbbcf4abf3fd02eaa4483108a3446c9cf041bc67f5078d1774308ddcb3f918d7999d1e2c0876177cab6790000000000000000000000000000000000da7d4fa72dabb314ad8f68b61fcfa38627d1d7719bc07767f596671c58cca16e005d36e42413d03da3c643eb46b1eb0000000000000000000000000000000019f3f8f1a4008f9db1b604373d3566ae7c14a9147f80597a31839b83f0f8dcdfd829f7fa933fef3499b671867c3121fc0000000000000000000000000000000018bba4bfcf7629fcfa47935e36462cef4fa3751c7affa2ee2cb2fe3e3532d46ca1d247393ea190fb3f48077270d6a8b22810705458845232e851b33fdbcaab01966b8ed53b455873a966c1d6b89363890000000000000000000000000000000005a1e0e3a023f67aa7ab0109814f130a05c8c739036b98c70c8a8ddc1828d2cc4e2fcd16de4ef038a7373d15c78e81f10000000000000000000000000000000019e2bb467409b3dfae0b06244b4140de7f75cb105ab897d1ffb999c6b53bf3b60a3d11354815621c5d9f07962a237ffe0000000000000000000000000000000012e745499d5ed626b4762b57923bbfae7f1209408e7ecb8813a545c4ece0ec7c48a4015e0e264b47fa08fa82c39d3a110000000000000000000000000000000008acfd3c2a2e17be41a70ebbd1ca2cff2eda8a359e0969a389ab0a6fa51db5601b386dd035b26232be08d704a02033a7175fa4954e56dabfd1808f93d2686e0b4fd285bcb78b80d15e10e63ea8c7b646000000000000000000000000000000000fb464af51161f9c2758acc09d16754d4d8ac52a37baf2fb6ccd3bca3058bd3cd204de6c8a0bfcce8822f16ecfcd0601000000000000000000000000000000001819075eaa6d9e3f0568ecc2e507370f938a65169cea1ecc40c9cb4d02c83d7964254602e3d041ba0f93c24369fdf3940000000000000000000000000000000016c179832739a8129d2ef184f4d1231d24bc8d4093670a63d73771983152ec322b6a8c954565d61c2af76c4f6ef5e8a2000000000000000000000000000000000f6623578a4fa45614f4b74768adf65a753a35dacc84af005fa4d7328d733a09f12f709a7bb7f89060f60d4fac85780ae7dda7e5373d0e0afc3da1507416f47ea8b467a5b6c2fbde484aec8777ab7559000000000000000000000000000000000189724a2a0723e7727d224ced126e4288f4743f6855b035722f2aa36cf2f0a6fc23f6835c25222b670c15248884451b0000000000000000000000000000000009a57d85140f31ca58e38b4a99c4ef103f0a4af0d5546d416134fa8adce6ecca6588c3c56ba06b2f59015acc1a081099000000000000000000000000000000000dfc67b7644851c3e928ea33aaa0f745a18983edb7488b148736e81ec0c62345c11e3f0dfce729d893dce27ea249860e000000000000000000000000000000001712009a81e06a85a225a46fac056b139c8da05e6b72074ee4079316e490a06f51c62241e380909b86239d867d631be16aa731f9393d2bb32adf04f19884dd1a5e7aa36e46408b847222a153da95aea5000000000000000000000000000000000976746ae4d9325d5e8300b57ce99650f28055b5e020700ee5f124fa76ef3bdb9923101c3a1f46b6985b8203b4e8c60600000000000000000000000000000000057310c3b6cff6c849938f533b401b0cbe10b6ff3736c79a968009b2c0b90708b6b9a98b8e594cce09c579a64ead846d000000000000000000000000000000000d39511e47f33e310332178b8a0210e76e4d4c7408ff5c2374f5e7bde8335525e03897cb3e2bdfe59bb76b21cc6411df0000000000000000000000000000000010c46a621b7fb2e7ceab8943b3371475d3d6f132fb658b8c6bf299888711f1b344ebd4a5793ffe6a7a7eec8c66c80303985f367919b0f3c667b1c1cacedeb0be1f9cb175c899992ef55f14e9b7aa6ad10000000000000000000000000000000011ffff38891ee56cb1fc062d02f6c9993100f991a556445b5ee1b1b0d56d8e64bc6eea4d7f69a6b6dc55ce7d8b4ba300000000000000000000000000000000000d6cdd95d1ab2a11ab424d7aa596cc7e5de025c57217da0da143887d7dccd6fda0addae7c2fd9e0996bdd0d23128e807000000000000000000000000000000000499b3e69214fdb4db7dbecd619ef9c6b5c8343c808e4953f593cc89adba02b5cbc56a5e7a3046c6023c5cf305e54e85000000000000000000000000000000000d267e21606c16479065e47da8e3c058cb59f55a1316a87117a73dbb067ec26f406eba6a40b30ecb00f506bfd3c32f4da3041cc52c6f1bf62dee4c61b1c5e35b72ebff7e8e89b05353388b551eb10010", - "Expected": "000000000000000000000000000000000650fe9f3cb3620e0bf1654a7f1dee503b79fe2218739bad608dba9f1e5330f325b4fb7c340f118eb10dd0776fbfe63c000000000000000000000000000000000bcbf1c6a684dea5ad6c1a540b3525cbc64c7c431f37213bc8b08c8d8915a331c07bc899d3a2ea72a9a4bb2c539cf56b0000000000000000000000000000000008fca1c364333f558c7284afa1be486e84bb035b049a2108b0df99395149de83549de153a784e4df2b0134317c85292b0000000000000000000000000000000002784cc1d11667bbd0759bca35a16a1baf49a21765c6c2c3bcdd4fc9697ef20f1274be5caa0f820d37e843bc38c68957", - "Name": "matter_g2_multiexp_61", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000051646993c3aba532988d7baa07eaabeb8366853436b8b19c0fe3e14ed45fdc65448d749adf745291ab5ee62d4e824880000000000000000000000000000000002cec01290d8e51ccf751183dcad20bac20b8231804a2b6f87f886aacb61d31b14f2335629e97af0ae0546a17a4cca49000000000000000000000000000000000762afa7b94ed580fd07d5141a8e1299c6ec439bbfc6c1a4d695d9aba4ab5d6dec93dc4de47096d72e5ad87d879eea190000000000000000000000000000000014769208ce8a9682c8e0340f68a0290a7782c2b04e3c13027f0b23966eada2ffb2156f6e20539738535fa0ef097f78d6709a2e80dd96eb12edc481e3d58893bd0d789a499d5289072d58c2ea80b036cb000000000000000000000000000000000acc4e3ccc3574285c19d2545839d1da9db6770b078aa399262b7c91a7c41fb4c83fe7dd0aad19f4e3eb2b56273f664f0000000000000000000000000000000017851c99881677b89956fcdf1b8c5ca5dd0997d810f3fb89f7378dbf7964926cfde315f8722531d6d715b4932179eeb40000000000000000000000000000000005e374a4c7118a76e59cdaadebb1c4e635b4dd18665010249f3bc78d559455d27d547856573e264c98ba39f6f3abea69000000000000000000000000000000000a532979cfd5263c774f629027f7624799dd0f9d6a77f675d790a85fccccad6e93c00ff2e5536b8e9a92443af14611e69ff35bc510c86a9e72c3e9c6b49d2abca546f7a62330156ec09c6fe6847a400e00000000000000000000000000000000056f109801b7a4a36fcadbee7219c06ac74e4a3f7b81616076c33ba2a71d7ca0776b596fb25d29992fa26d416272a4b4000000000000000000000000000000000c02d7e6ec50b778a7ff36fbe5751ba32beb1c2024b17bd99b46239e6dd5a708d2fc689e8e8924902e0d80287cdbd6e90000000000000000000000000000000016f18df97f48aba4d1b64e71eb894904d02ee7f6ba425e58f38a08542319e2498cb0dada8dbbb81bb398c9c924ae44270000000000000000000000000000000017dce98b335f536909ce01647aaabb918942ba2468d9a07c5516cfd347e1baa02029d39de1b2602932630e4819f2f00f391dd27628d0808d4a0773509737597230d7849418540e1fe4498fd70d39d16c00000000000000000000000000000000005b23d6f76b8bd4f334e91771383856794d1dc65b365fbc0c94f21fff049761d7379f0d512c42ce13f878e0661712d100000000000000000000000000000000009dcf70c16f524ff540f132b35074cec6ed7dcc1f319432a0dd09b3ded0778ec9ad0f05d67ecf3ebb7947951fc4b25d000000000000000000000000000000001075fb15240d532a9543dc59cb0098cbd03da77c3bf85a0ef8be1560958f8ab57d3777fab5836ba98d67c721a4a8cd460000000000000000000000000000000003511525fcf6fe224eb87b13999d2548b6b8bb8069fd354f298a025b04a33f48be72d8e82a99b9aa34ce5ccdc1f1a59c94f11b10e4c45f15d811e3db4b947ee6414e262965d7b5c23a731b019e63d5130000000000000000000000000000000019039c69d52a66330d2d8572a1308bd88159f0383c041ee7605d0aa86f1d0fe3e884d0a2ad9c72405149b5fd204ec3db000000000000000000000000000000000942163eca08672af3827dbd876b9c1adeefcd5ae74a2768fb55f1e8b342aefbf76bc6546853a2b33e26fa866e60a4e9000000000000000000000000000000000c60c6bd103ba5bb5323b5107373cd8d706038bf5ec2b367a43bab72411523bea35985b974c756184c346626ab2622d30000000000000000000000000000000016c4a2fc8a9b3c54f65cd150c80a3bf70ae8dbacdcd37128514b4a881239023e427f0b0c8984ce219207c458bb380da970f7a0ee05cfc3f63d46a3151c20da53604628bac70d7b521b3be65d7b2abedf0000000000000000000000000000000003e3df9a8ce220be05f15904a3321a6805ab68bbd539479be56b2a870c3d61234e9cda8190bdc89f48e7f0dd9374e1d800000000000000000000000000000000040446db3ec43e3e67dce62efd741a4157e8ea2597a143f7d6273b66c7045daf31f72397b4b9d374328520893157c1f1000000000000000000000000000000000c3a7dde5b02df5f7c1e750a9ee5314a580cc6ed53d326a9157b507ebd6c2da314c37a7f1837f7fcff7e8754ab603b7b0000000000000000000000000000000005e617ca4eced853f8f2e9fdefef810c97eb27d5c8bd06c5b4ea50c03761c01e8adddfe27d2d72eed8cb25ea7514a4aabd991eb5e8ac8ad7cbf8fe64a5889b715a2409305f2366b278adcd2144d7be8c00000000000000000000000000000000104ccaee210aa8196010a6478702a54cb7ba49c80a98ecbf5c0920408ff8b4a7568212bfbf3561b6a7790520bb73bd42000000000000000000000000000000000870ddd51dcc76c8a97ac4b4f23819df48dc8a8798df0450d7a45d273f830c908541dcaab7b066bcd668b289c846ea000000000000000000000000000000000012fdae32b020a346ad5edc3bab360fb5ba55004ef3dfe5f437e841b5dd7284ddb3880051956c8068e49a3fd165143ac50000000000000000000000000000000019081bf768dae314fbecec408d687df5b6ecb32ec24b41f9febd583c05693f80345e6b9d81322ddc72616c1cc39a86811a9caeccc2a2058c2f5a271c09036d73320f9bcb31b7296a796ef94ca4599757000000000000000000000000000000001316b5ce5bcc168d76d2c862230ce604d02cd3d242c51c250bc6b6fe5c380c9e83fe7041049f2272481ab38f44648f4700000000000000000000000000000000079acfc2b9629da9c9f3394874e64aa00527de21e726f02db180f86cc0b9a97138c2c567832e287635721ca40469e00c000000000000000000000000000000000e11807dcd4ac69fdcea71e3e6a93dafc27afedf12c2998dbbb2e4f33e37ea736df73af791eae69bff84f3bb212bab47000000000000000000000000000000000e834a34fb63d9df68d683a26d79ecf8ff67066586e5f760d4468ad196c66d4ebf8605ebfbb7bde201f47b35cfde3a5d8ed4eec02c2af286ae19ad5f05642587cb9ad93196756d269c783a11f23393bd000000000000000000000000000000000990f115519d2125d47b925b613edc3303110e9040fa705211e0d772edb2e0f7f88ce521d1738a5f65c9d158e9d360c2000000000000000000000000000000000bb951a16decf9be8381d0c88726b53d90bb32cd8aeff962d48e43863e4eab1839bd80d7434c7eb808bbc0e32e92a4290000000000000000000000000000000013dbd5bdb7caaecc42ffd81f14be0ff3d8fa228ff121ed4f2f3ad5961fbce617d7cbc8133fd49e03caa62f7d1567541b00000000000000000000000000000000195fd9b85e19d0e3e1c93bab0380cad6f6f3bdbdcbf5c6ec32b7de7972421d0065cf0b265f6250c02eada67e95284bce26f20eee9bd019f9e0f5c794e22e770128737198b5f5dbaf5b7d18040443a0bc0000000000000000000000000000000009ca977266277bdeb985750df47353a6b81c5f0c473eb3369d25a01df67610bebf66a6de5727a465131404025e90441a00000000000000000000000000000000054410a13287ecf4aa18f543916fcd65b15cd5d54617433217b0a2b91a79fea764b511b3b270de3e8985e8f6a2fd8c380000000000000000000000000000000009a9802a03a7c9fb63c1eb13972cd42ea2df614a0972b914c4015c2e8630af319d12fc8108b4c88db9508a9a77d9e57d00000000000000000000000000000000094d83483bca296b20b7bee124f538ae9c659a84541f5c9d9fd22e98251d2b48051ac55ebe07bcc9d2e9109f526d60a6c470a66cd3428a44a7d095ef410126257175597a333cd36ce6c9822d1ee9bb380000000000000000000000000000000003f2d93ddb6d5983fd5521c1d1726addf662af0945aee54788855037f47a013d2fe595231792a05e1259c5e5a8c553a900000000000000000000000000000000004f4f4e7df5dee975fb440b5a217c27d9d1eb83a5ae280a2b147896f6bb864abe04459c17ef56d784d3c4a0b7ad3f3900000000000000000000000000000000069da36057aaa89cda458af4ee27fd9ec969c8f7612cbb153da0e010d67bfdddadb2941cfbdba8c43019a9f1aaf9c296000000000000000000000000000000001545b8325a80176ea148a3d9301debd7046f33a1b419b4ed01916a3d0a072037fd617d96e0bad32b208983ac3be7dda4e53fa8fb708204e619c221b8ecee14fdbcb1f94731ac2c858787ab33906c9269000000000000000000000000000000001536a81b203df2640bbe7e695b5fde186021d21685f24c25966cf11dde554d49bcefca64f16697509a9ca86e58b75eff0000000000000000000000000000000014348a2bd4907cf081f2f7bc944a98d3fac671abde029995377df190f7f60319b8de1698b99be39c821328e32a449c760000000000000000000000000000000000e18d4da3823addb2a6cef8336c83f99f390e23d7129365d57035d4363aac7e9c4da9f8000f086f7d2206666f990dac000000000000000000000000000000000d6ba54e2af9afa57ff4536a35e9b61c8d8fb3d431b653a0c66a2a4b8f11d9b5c45389f894d64485233d4183895921f3abf8de43c54ed59b936e1d55032eab5c9d9e04e83e4696d969c24167b4239f62000000000000000000000000000000000d88d5719e07e2332c54ba41f330c7763d2b2b7c4140d19b8b0972fae6ef902415de5f2abcc2342fce24d3ed8ffe156300000000000000000000000000000000163aa2c768eca58194fb76822deffc37cefe04ceb70aba38a51f507be7cd64c0755abdc2e49e7db234cd5d68575c2d7a000000000000000000000000000000000e443d9953468b8cea4eca4f5968e214888e2b95bc20ece39483ac551d4e180c0b0a41c4668c8ddaf761a0ac03fbcad3000000000000000000000000000000000691930530ce86a1354d73cb21ee32d968e6d89b12e5a09a7991c7d27dec302348af7f49c3e0de91e1a1838aa11651e795f59041329b6c3e6aef01d3410836852f79cc436fcf23199e0985c56f65c4f0000000000000000000000000000000000d7c6f9d4aa794f34596bb9af4d62363462d9804898ebd7c7db7544be1f46b4bde488ec59004adaa0cbe40aef525ce3f000000000000000000000000000000001094629b1428c4c284b7a64d0623e10ca0c4d395bccbfaad89d1a737a3887c10b714541f2681c33e674c3b99a36b7a450000000000000000000000000000000000d6812fad9c5ea365a64ebd3150238349d88b76d041ccaa7e637fdfa6c715d9d6dc3d3315cb95fd6919fe419d028783000000000000000000000000000000000eee5cb772ce02fe2a4883008f17570aebb902ad7c40b4024a5b24ff75b3aaa2b54ace6fb4601b1c62837a20204194dd740e4a207ab5dd4a0621fd65697f5d30b8ee1440a5f5c5e74a0dbc6b6391c1b0000000000000000000000000000000001026d21e075fb8921dd849c98252a565d39ca9f5a62a825e7e3e77ab5be6620e76e45047e51350c48d9a4cf98a1222a9000000000000000000000000000000000f6459a8287bb2da77404a515dd7a35f46a4aa49ef72cd2cdefbc5e5242872df5f7b7aeae6848d59afa1dd142ae7caca0000000000000000000000000000000011e3545151d4e0b034b950cd2f1a3fc2d29e9d53250ade2482b7ea6075dacf7e8e777afa1e8e612b45028205235265970000000000000000000000000000000017a869d75144ece603c04d39cb56a487895cc882fec613f40f6a66601bdbbbb7748ec755553257d654d1558b1104a981f49a3f82d25c6e0d69207e6dff010d56f0d99b28fd986c5711878dcb6665b1f50000000000000000000000000000000011602a23c9b5cc091a700114e5d3557bd4857c4fc44cb8628ef327ddeeb728927347438f123e2011f9cfda9b6dfc42e4000000000000000000000000000000000c4fad264ca95827e9cbb9783e36cb0b683fcc33038d47bc7ab6b65998770325588e5b910e811cf7d61fce13c3378d6700000000000000000000000000000000009b4711aa67e84434cabc289a78fae48ea86641a162d48b79bbcbfd56237705dd2d1e9ba3a18d737eec29eb8e940e58000000000000000000000000000000001160fc9e2a488ad9385140bb62ab48ee613c2284208cf2f92912e1b973ff81a5d3de338d9aa6881cbe437907890258fc8390fa1b452f887ef3afc7129ad8ceb9a8397f7625c2b249d7442566814ae0a9", - "Expected": "000000000000000000000000000000000cd0d8c746ecc8d92fcf2232793282d7e0e17e0ec27ee851487eb7788f590db3487296061075f36c24f67cd4c4bbf36f0000000000000000000000000000000010c5e1d05070c27f19c228813051c6a830254542eb71469664c842695b219670dba8ddff858e2d147019847866f01084000000000000000000000000000000001799ca7d8f2637da761622b793a3ed3317d50b902a1cabefdfc776b0d0ef88b707b8a5c36786d5ede3d8a381de4e069d00000000000000000000000000000000129881a3b56e0014bf1dac4775f509f309c33406f2cf22df9a0ccd15c87ea48a868d4437303923127bf580b8d6ed0a8f", - "Name": "matter_g2_multiexp_62", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000d087c1b98f8c67c1bbc4389f21d9dab02faf46ee4223c609e7b9eb399132ae168bc12847c580f58edbb9255dca3b000000000000000000000000000000000065ded24bda39d2b830639fa511bce8dc770eb95e349d6874ce63b3355d23c1da3ee9771ad44e57c6c661b7453076fe7000000000000000000000000000000000fa3b2ef40a7c3d41f0c3a5f86afec252c6ce89bd1bf1f2192026e22fa256365360589c788753033658b1ba151797feb00000000000000000000000000000000105040ff4dc2bc435c2a82e1174e2ee0b94043d69074f01e8ed013da8c431f33c94a438a93b06774411780cdb72abbc8414ca9894bc15e6bca798544138689b2471f8171a5dc48eccfa36c83af142b7d00000000000000000000000000000000129c8c1db08ccd0dadd59b04df67a91fb6547d97ce23e59aa57cd3d38458e6baaa67285800809856e7e264d812e584390000000000000000000000000000000004a0be934248b4e142fc51745233b6d0ab2c46f53a8f9d4c84981e5eacff146ee6227de289c713e4ce24a4341572c9d70000000000000000000000000000000005916d14a8592af57a40418b10376e8e20f70929d2ba568c1fb70e343a1dfcf3e63c791cb639bec49c50aebd2f816fdf0000000000000000000000000000000018682c66a461a69b11d7c32f7aca07749e05a23fc46547bac121752aef64e9bb98a274d15a14faa93af8f284790acb9b99eac8ce85a1bc70c725a2f04aea3749d75d22c0df7c0755a5e76ab4d82ef9420000000000000000000000000000000001552053742eb89ae3d0b95be919c84e53919c898ada92d3eaf05605a19ac910091fc08a65e9764f3108877c837d478c00000000000000000000000000000000118e5d22f6df0e6bc7447177ce06659f94315478385372046b649fa6d39fefeeb492e6623e0160bc47233f4d3143e326000000000000000000000000000000000dd02c30cfdea5abd3550a9f28b546d82d5b3043f012de622d892062945847748ba820555fb811fb3382791ec43ce1f700000000000000000000000000000000050373898b396d9a641e2f2ed832c7619515fd9070852b891b4ce0b5bb5ea8b5e24248297d53e9db7cb946e76c4433fa49b25140d7967b0438e49f59a6b04b75bc8745b84d7350605be548c6b4b3aeee0000000000000000000000000000000006b465f4b9d60a3a14e119c54a7c35172bd648c86a7cf331e80ba849fc87b9dcd48410e3c9a07b634e83fc7dd71e5b9f000000000000000000000000000000000283ad9c77f549042f79c47b8a69e72164f0ee77aee50c20519d2b89029c63ea86dde2744cd21eb5d37e896c3abbdf56000000000000000000000000000000001668b08a87787928afe92d941240e503da07b646a34cf82ed09d4c2f4d479aa24358c8475eebd9bcfaa6bae17c430cfd00000000000000000000000000000000150e5b28bd901f7a2a9af44bfd6b78cc84900dc05e334de306f9a45f1e67708adddf4dcede8150a39670054f97a643436e30a51d55a1ac94089d0f3217c3a2182da6b02ce70ce7dd8e2d4e938bfefa9d00000000000000000000000000000000060d75764a92e30e80e7c1a6df1482585f4de901bbc36dd9d8978a76c12c739f85a9ba16741d0b19ed480fe2dc331e5b000000000000000000000000000000000024fd15c9e5b8872d2e9dae9ae96102bfb0e31d15e92a24316818862dd8ca7a6fef271d499fed5e0db6dfebc4c72e0200000000000000000000000000000000058cda551e1fcd701c6a3880b276a2f7536a26aa366a6425a1c42cf31eec678551f489a27f23ed5dbc76f19b0fbfae43000000000000000000000000000000001152e2cfdb584295563af8120c523a9f4c01cf72da64fcbe0a90a284d693a3089f299bc760166be062cf9f8efb6a951ad3da3db6492ff36102747d9d663bc6e9cf8f75b1cf77044989c7af3f11d66ae700000000000000000000000000000000116fc24e980b2e7ad6bf17bcd7c4f06e654bbf766ea0238a66d738bf3c2d41c8c63bd52f81553cca5fea91f5f9b74a2c0000000000000000000000000000000001078f19ecf785a5e0d3e764b7d6ea47b2d077b5eb222f4e6a9451f134ff0d77a0b9a3b53caf599705d131e3b17b6ca9000000000000000000000000000000000e44c07f00a1f198583a8ffca43da45d8e54e1f2a85bee7afff6c1c733b5d0b5712961c4b6d344869a8e4de3b34218e000000000000000000000000000000000083c78b3568cdf808b75d9ee2b03b98cd516bb16ca8cc35757f53f12119747bf6b5b0605bdffb2f079cbc69e99ee0bad6de8753f3df8be42b6d6ab578096426f852de4ff545d2e4ac12c3943b044b43800000000000000000000000000000000087ded6945bd6fae7a0aebb1ea68d3cd34588035531a6cb00fcf1b83e06f7ec21cd3486580165c1364027b43e238e34d00000000000000000000000000000000005a2fe8a9871273bb60cc7ebef44a361300a1033f3f0230a731f5723fca124ec9d305cfde45802482a45942154398cd00000000000000000000000000000000121eb94a41f9e133adf082ef651272c178d780a1c31ba8797f60a208ad36b4c703c9b6c08be845f8844dd14d6406734d000000000000000000000000000000000e5e3da7c91ab4cca1c9286020aab9795e64e667d55a5a700241f9589aa3519639f168d040a0027ac057f334a9f740aba28f7ef4b12c5097a15fa6394a4dcc3ceed6cf3c6240ec2ac949bc21a9f6447f00000000000000000000000000000000041f9117b426938acb40c905bbcba443c043bb55cf9b876edfa2ca051b6354124f0fa54d6a88ea172c3f5c10c6d921b3000000000000000000000000000000001828dc0b9533274db6afc802b2fadaacf57f28126094b6b9038ed5f6bbae0112c873fe5eed15bc49b970461abc2f5c3200000000000000000000000000000000107df6da02f106ae47718959aeba7b4fb4a8f0e2651560e2f2266a62566e13a5af86430b8800543f5eb6b1e96be79c69000000000000000000000000000000001628fd4a598813133de75cd7c96ff3711b6bc826806b96d07e5a89cd549592f0f51c84aa9ee0642cffae5630ca1ebae1a3d0eff3368b10d00566f35391bf43c9d204a4444b7eb91017f1b2d8a762d90c000000000000000000000000000000000e8fff44163cd9c2a4e148eef3cbbee19ab8f648da1a8d438be27d2b0bcab393fb7d49e096d9a7abed3d8f82c11c4e03000000000000000000000000000000001274335d8bde3d14924f8d7ba18fea82bbc85427892f18fb741c8ecc5f2d6d7bee74c68058164c55db3cb8da8597bfe40000000000000000000000000000000010c7fc728c094e47569f0e75446c399d20a1239b511e34d8d6193dd32df607dfaa4377a1825b3892a9f74ff4efa0d9df00000000000000000000000000000000067d904122a6581b5d5a60acfe8156dcb6c10ed083840e506487b5dd9117927663e0ad883fb91b4914778ae082de0a7eb90d76e660389e570bef756e9785e39b9748aecd7a34556bac8399aa5564d12d000000000000000000000000000000000a909706e3ce45c86f2c30de5e820c8c9eefef207e530fd504511827f5e6422714d3f4224afa6bbba22ffca533d647390000000000000000000000000000000013ff61472ddc0d70207692648087c283763ede668ae380b0b9d6ae6593498b0adc9d4e4fcc73b5cce250e7563f7577de000000000000000000000000000000000a81db69eca785373c4dcbafd8635b23a9f41265e91152f309fb2945622937e65b5c17656abf8aff042a1fd1e5e50341000000000000000000000000000000000c66269c3ccd9e91766d1a640789bde6de752d08ffe3b2955df8dad3d2a0b6cea9013af235cbfbccee8271a7242e310614f18dae096e4de75de3da284a5755efe51e912e180020a20adf1f5de43cb51800000000000000000000000000000000181f3f4a16696980bd0eb9bd10ff1084ffe90bcb65f12f505b25f0a26dc1d4e16987d486b2c0b117fd6f2e356b83a5250000000000000000000000000000000010d7be6788da3ec56c87acee68ea8a03e7d467f816060207bb163dfcf8a4e7721651bf2bb23d5bc390d50fb1ee6625a900000000000000000000000000000000196c1ac817493f51d9ca891b55fa65ad5192df83cdb63eb1a634ad54e2d627f7feaa68780418f5354e6cc09cdf2f6c5800000000000000000000000000000000190f36690b8d36f2e295b9625f23afef9d9babe87c1ba0303f60c6d44ec952ba6bf8356469cff9d952f8e26bdb86ca06e32d4645ce0172000fd74f30937261de89753caa716dd03a8b3269747f2349a1000000000000000000000000000000000f77df606f0611856c449c58393f4ee7a6225a5bee667382a48f59dfc747736a895d598f90ab26002dd0ed3a5a8f5a200000000000000000000000000000000012aa50d0ec440884fc6c2f7a0e8db8a5e79160f0c482209ae1a1aca2b9dfedfec6d6ea09252a373ea57905130220a4820000000000000000000000000000000004773f46165cdb19cae49cc42663316df39586c62be5b827535f138e1fca8dcf62ba42ab60ac6dcec85e8496f32b9eda0000000000000000000000000000000010c91923c2c7b3eb2cd9aaf0455c0eb035e38e5352d218b07ea23f50040ea58fd548b373c1bee9113d3d44fcb25f6ba08c8722e3e929ba21f1ed6c51fe5ad4940fb13d63e0293893135d0da5e6e0389300000000000000000000000000000000044b95fd5f0e049abfdc2adc699646afa5b0f64464779efacce85a5279477697090615933069992bf30036c6ac70dfe50000000000000000000000000000000002778e7dacc5566354c24ea1144613a5ce8a38eb56d53d230ca145ce83d5ed88596afe243df22cba10f423e64a7c103a0000000000000000000000000000000017e87cd2752d8674c373c557ab2b922e02620a070aacf6f5b3d3d07ca35d89ed2666da7246b800717c0e4763dc35f5f6000000000000000000000000000000000a3ed312e5f309eafaed486629d953970cb73f839bf30f506c2f393df4c283f299d6c643ae6c229430d919e8aeae8bd839bef6ccc893f6eed62e68f5f2a07812f2d3066b89653431e7e39e8596bc3652000000000000000000000000000000001082a0edac6267151c8ef11fac7614b74cf58b39b72fb71e4d66467ed4fb3264b177c691e569230f2a13a64b4a48c6fc000000000000000000000000000000000073a8d5f96ee580741bee1f82cacb6139d962fec34c44c648c8fcd0322796429bbaef083a11b4c8fa376d4c00cd79c00000000000000000000000000000000008d41e51dc2822e0f14b992511de799fe4db3783a05ddc1026a53faa89af000075ba5aa830ceb7551e51f0fff144c1360000000000000000000000000000000006bc4bf0bdf350af417160d06e8aebf2dde02c9b50be39b0c4dcb3a045f9e04f1f041f6de10328e287df6121247dd4e9c395ba8f2553e3eced8a42b221a710a5cd2a5ffe5834d3084dc260ae0f51698e000000000000000000000000000000000802e7b71127a15a279a629e89f194b51d19c4f329efd8ecf9fe69d340dd06068c8467da6ab39be25c194077d3ce2428000000000000000000000000000000000250172c787afe866b428748be8359d8e0bad161832abc108c850362c5839237483fb38678d77c94696260508907726a000000000000000000000000000000000d46223c1666f314f9a1e32a94f83d8150755d71252e19af91a3b460ab0ade2db2364d8c6217cb422095f0d9a1ed648a0000000000000000000000000000000002fc2849014717d1c07935efe601325e1842ed333897222f6de322dac8b50bf4d9859eed8880a34676af0d0e3277639053ef5568a766b6c39854ba059f3130b75d7fd870bfac2b00b626e2d71c4968e10000000000000000000000000000000004151d78d65b0c9eb26822e20d90ace8fac209a1f08f62ce722ae3effd7fcc476f4c0179e71b09fc181db96fb2ea4eec0000000000000000000000000000000013d17ef429483be98411947ca0771ce671fc38e27bd0aa4abcfd5ddf1af9e138404d86f4c2ed74702f80a573638d92f500000000000000000000000000000000178f2a7eb43b9f88acfa892b5868d7f7c5787a399c1c566de39ecedbfe88357fd5256ec57e1ba12e9784382c14331756000000000000000000000000000000000253a391373974beef746c4397654a30a68992fe9163f9518ff0ed9b7be37b858ac60c95259ab894bb6acfd123333b7fbadefc3880ca8dcff10b8b763f7d15f88965c2261b72ba879e3540a90c59effa", - "Expected": "000000000000000000000000000000000710bfc39e92b0b9d15ee9bdb4959daa3a78f66aeae29eaeb50a0aa0460f3ff703c86eec8903011b4b61a0dea725ab08000000000000000000000000000000000856fe7a074d37786237cc14ff1bc53c735ee8133b231dd3fc63dfa0dbd1979304bcc7b55cd1bb66fd7529e15d15db5800000000000000000000000000000000014757f1fbfd4fa7935ebfe65e150519d6eb4f4831890df4b236dda98804b79862fb6699b587c3e568fd6de1e582409900000000000000000000000000000000000f7b54e4961dab9e94b1c4b897177dfa74be9937694a38207ddc9d6290dae1d5e122cfe4c8c31d853db3783999a7f0", - "Name": "matter_g2_multiexp_63", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003bfd2535c6d8ffb44670bd02b5aa6f050f5cfae7266fc3225865bc3f34320820eaeaa952f80da51671f6d97b3df9d4f00000000000000000000000000000000026c1adc0ffc3fef9ccf018ff9a647ef5c69c5133fb4a6566cdcbd3180d9ee784f34d667edb1dd54ae292253b45576b4000000000000000000000000000000000ee90fb541becf96b4728f1859aee5ae74e30ba9193b90569b66b0e1d087eb81f30c21774298cb06e7dbee8f8aafb1930000000000000000000000000000000000a4361867bca952446f64c273735764e141eef43d156d6cbb6e68dbf3bc940e935f7bf3a77b57fca4bbc74bda2f26532c1a5abbddc02f453519563d6b6e05959d8de5feb493f7c58ea5e548cfec2df60000000000000000000000000000000004bdef85b0da28e0531734016e5953256c75c3620937736cf65de5f05b8beff294677668047a3b74f0f135b846a95bd6000000000000000000000000000000000b754df2aef855b4a0eb6f6aa03115ee8f38a31fc852381deef2b59bf23e2c885ae166030ccadd5673bacc35482f81e9000000000000000000000000000000000f1d760ac6dfb65b39c999211d4e4c3623c3fb8ea59cdcf926249a07285a8e4da1890327fed20ff07f12359f6d9035980000000000000000000000000000000009f2698239c8b452748126ffd83abec768edffb83dfa3dc7943fd499c8980e2d9aad76dc38b336a4a63eccf5c4150ce0b406eb0c097237556228f3a48b7e770c1707fd583b91b4b6b70f398b7dbb0d3c000000000000000000000000000000000cd724c51fd56528dfa688df46f71bbfc9144ff98958b559fca8fd05eda01c38c28630ee19579012b9913a393264cd90000000000000000000000000000000000aa1e55f2b6d9385ec6a9cbafcdbad157f7ebc06b2e30e2380ac54e71db5259cb919e17042d6ba6e045f1358aef276ea0000000000000000000000000000000010181ce9ffe235b6b271d570b3c2d6e1be60c53b4a98ef5e8d7d00b463e5bbc9d8d96dda881e58746090983d6f8edd35000000000000000000000000000000000333deb8b14f499319ad675f482fecd80f9a69ba369425decd441cd2ff5c3c77f11075f61bb1d90d0be850ff657d6b7cccc30cf1db4c6be6dbc5830ee37b5782c6dad215334163a9d9e4deb962186f80000000000000000000000000000000001581a5440fe892ee6eece5fc2227fe072dfbc440e0620a1e5fb505ff0b16d9e6033d83c83576b4b6ff87a807dc81b88400000000000000000000000000000000099b070a0d7497f33c1c478ac424d5564fa645d836a3d572d98782f08713d8e425b571433fee928475688db2b3a9a04c0000000000000000000000000000000011e1cbaa09a6361aff9e199e21bc52e98dfacc49ed83e732d4b4f2503b3bfdf85d029dead4412b6f3d7ea447e20d669b0000000000000000000000000000000005503e151d620e9a5a142e4f7940ed88375e7efc1109214141c191e9f38a32a40d3a92d6094584e763e0cf13cbb54bcc99461c0f12019b344a7f322900b64fe81e0d8a052c0ff5e977f58753b1b6edc60000000000000000000000000000000007c780f119bbccfd658f3f1b69ce9c56b1f5269bded713b6827d97d32b2a6deadcc02c410138d984d977527f3609cc2c00000000000000000000000000000000095aebacfa33928a916ca7b0ceac699c71620781b35cb2f3b254bdbd1544b728a2ec1fb35416ed7a8a3a630bc07ff8720000000000000000000000000000000012194abf7e411f4961b6f8a1e2ad052c27624ded863d7a9132d9c7ecd3b4074ef0060cd86adb73056323f4227ba5fa9e0000000000000000000000000000000002fde2be9ac1e8265f258a09eec85a70112ef1eadc3a91429c9206555933e2b89aaf7493fb833e33e5d61be28a12a1c2338ef9fa825e47b46483ed8fd2df64bc7b56da8aecbae704b7eff2e7d426f27d000000000000000000000000000000001586c65405e810e1d5b59304bb4555ca43c04a593671ec64d5ed2d2e626b1f8a89f48a4b21d38fb49909b8c614209a460000000000000000000000000000000014528cdf994e774b8fd54090cb45b68098c1ad9a351bc1f36a9393f3b4364f5beaf58fff6e5f8b21a85b67bc427c0e920000000000000000000000000000000000b48d8713aee51d80c79109fb8b4e0c6e32e25a7ca24dd3e7700f8f3195730375208b241b2c722af3c2295a1704cbb3000000000000000000000000000000001913cf6328429cf2966a48117dc74db0d45be7800f93cfbebf597fb48a8bdcae4fae2df7835f9536481f67261755da2a1dd6656a34f3b12e5568b9c348fbf4ecf50d65a89e63ec0936591f01e6cc7a4a0000000000000000000000000000000017e45a481449f167fd579accc896ac65aff6f1f7392df47d006b404de3cb7ebf6cb59d0913438f3a51e55a0ae3d446c9000000000000000000000000000000000cf4b7db343bea29af6e244a71880538b41b826bfd1d06a21512d00ce58f5d7500ab1ed77b446b1e3782df736bf3dbb6000000000000000000000000000000000525d08e134779ca7614784818876514e14b65e799b7832f61a63601fc491c8b9cb25430547f961cc1c22100170a2065000000000000000000000000000000000450cc2156c4716d0343f32aca82fd2d0712389b1aa984b31d51edc2aa0545c88ff52e470b15eb6b2c22e30f79864dc85202f32528e795e0fbe6deb4ef6e45efc70019520b01fa1d71d5505e42faa69a0000000000000000000000000000000004147c105ee8b4db68482b9d7f6a716ea1474b6c62efc41b9444ed1ef9e92e2b7010a1c1ecc59038ac37b385074a6bce0000000000000000000000000000000018a600a85c5c38be835d2e91a35cce4b59e5f5ac3b735fc007bf5498062beca9befc9c8ead58f9f21f6e08266b149d800000000000000000000000000000000012a476fcb81ab66e3101de2364cb609b17e06eabdff5246bf736eb9d5c87fddd404e8867578262f07a05731b04069164000000000000000000000000000000000c54a888678c28766ad17a18507e4bf5dc57dd394eb6e9b69abaf15e645cf4779bf6ccf4314d2756584647cf27af089ba2b39f2b893be03ab4da77ed518ef35b2e24278d707a20b67ab4d1e5972f9722000000000000000000000000000000000e809152c44cebdd8b40f0d22d57c3b31f29700e0cbc3e69f660bf7270e59093d84bf7ac358be7e45e799a75cf9c13df000000000000000000000000000000000c6c61f98bd4e3b7095fc7f1196baa98139087df00fae2a795e76544ca47e453f75929cab07c11cd3595de6ecbbbaff000000000000000000000000000000000171c70446c19fec3c152741925c8db28ab0d140720cb6a6c45e9bc66c012a421d12271889ea43fe1524944ff572fe6850000000000000000000000000000000006e4baa09b4660c69cace151e60320b771e56e7460b01442bfcf26823c17779034ac241b9365dbbfade770d2056eeecd892eb7c361f05e114a645caffce9437b7b43fa01dd66c1e75b30f3abd0209bcf000000000000000000000000000000001917a23350e94963e3a7488ac1dafefe9ab11856d405eff39d655e31ba808f02954b63e822613d3c6e5f358be04be4a4000000000000000000000000000000001620211b06288c16aa02f4404192e9f57a048e900f0ec5db9b478475f13b142f924c6de720031b3fc12cf869b422af470000000000000000000000000000000011e8ded9ad57e46713e7ac0044ee4edec12689cdfb98838a74adf1a35244e3d9a4a34c81323b089c10422abf26b044e70000000000000000000000000000000006f85c7478cec590fe3355a8d6e9557c5be084c161e090c72f1281be4ee56f36aa1e3c9c844eb45d9e295c15c4cd903efdafc3f57d6116163f1da9e70ea645243c5911cc4ad4a969a57c46c6b5c73acf000000000000000000000000000000000d555d9f23de97318dafb257cf444952bdd3e844e9ed5ce193c10b76f5179f0c6851f93af1553b128f34d3a7e75339f3000000000000000000000000000000000132704571a12a58f629dab48f1a3956392b40f801c2b3757c15f7be46ef1d9115d89920c460c0e2bb062b3cc1aaed7400000000000000000000000000000000152829eaef900fd2f19d6fdbb8f7eb3b02df35d218b494d075219b69016256e572eb7f555f6fbdbe17c59a666d190055000000000000000000000000000000000fe5c67c949b7c89a867301528f0ab24b04d31d6f18f575c475ab5a6098f7187eef20a9ed6e810684da9afd8de96ded6660a77b2be50eb72fd108644d913b9253209972fdec2d107213ba47357c96e9e00000000000000000000000000000000128bf3cbb5208d84dff719ced229921a889c9a4d02f5a508187662f03852531fb8be1f4c2aa9ef01de7720c352dbd19d00000000000000000000000000000000158d89a44b8fcf9ca8c96a8e516e130ae8af19ed71c2b8487ae300c3cdb546e248728bc58fd9cfef21107e0dabf44fc20000000000000000000000000000000012b70b42c8af4551267a94a795fe18e8d054291225438adaa33fe2edafa87742fc3709abcc7bada5d26e3a14649cb47f0000000000000000000000000000000015a853160b7666ea7d64aacd931314497ac7068a4b8bfe3a7deed85df2bb8dba277716a9d1ee50c56b2970016ada509d1ca575cca348dee9adfe68f8a78d39bb998205da2a5285c12141a77ee7af840900000000000000000000000000000000087c7bf08e085e19f0cb301d2e36478357e835620b1cde6e132c237ff6fc63e6fc16a8753550d50fb93a0a1741302cf9000000000000000000000000000000000615299ccefe4da879e5f4b01d6b6ef8358bb59ed8a2b365ec72003c16486d3266243db81f48855d81b6a25440bb861a0000000000000000000000000000000001498fd20640f39dbc03a474f4514e5e283256ac19468077af1c9ddaa40759dcf93afe256de1e49be6469fa106394193000000000000000000000000000000000cba50fc4919a29be2f4e74c261487dbf855db1856e8d5d008cc3f4ee5eb3babfdfaff878adae49b96db99d424bc4dab2e1e4537f855eb478274992cba4e3f50fd9e944f6246cd52dd1517b55bd7f71f000000000000000000000000000000001369dd82ed013474581ca1ab2d2133341d7c1d52065060d72b8317e899e79e9077bcefe6c76c3c7f67e54f76dd3c246c000000000000000000000000000000000405aa84d3ceb02bf8eae989a9cd65afa15451443af6f3cf5e70f5cd7bb8d413c57ac3893a7e8b888ae93a92dcfa2b20000000000000000000000000000000000378d003988f3c6c16d3b12ef47a4a49e2d3d2c7c67e384bcd510939581770aed92e06291ed3b7c742769f0d1ef740c100000000000000000000000000000000048bfa6550711a17d52f48377821baae6f3de6ad99ccfeb8302466047dfddee8005240cdc65b3ab11ed85b11f128624957f9a729aa01c8bf0271052202a077913a9e0c87201a367845f9b271c130e95d0000000000000000000000000000000013370ab697da0ff0a0efa8ebc7589b465374c983c13daee7b5451e8b299933eb5a4d255ffe4aa46782ae0916fd3990230000000000000000000000000000000002ee77be6e0b6fd260ad660a96100bf3259329faf2ff9796102928e70cd52c2bda8d0d1da1d484d7b023d3d59725d12b0000000000000000000000000000000014482fee88e02e61b847c08e61d7ae6fca2d993bbb69bf1653138150d5d7fed09cd5cd4097cb4b6368ea8023383477cf0000000000000000000000000000000009d0380d0d6fa39c9e242b9a67336d86445551658bc29fbd594239a76d7741ba388450caa244fb186afc36d35c8740e93017593cf311989ed8fedff72bb1f14f72cfe5bb7446ace5274d8ded54c1372f000000000000000000000000000000001537d4a47247af8f60f77d309666056c412ce089f3f011457e894f74fa4ad5168baafd36ed3294f5f61cc9cd8f87554500000000000000000000000000000000119e43382a846c8945e58dc7723a0f24b24d9cd487d436a156156a6da97795cf3f4ce382d21435695949b5137a2bf1d3000000000000000000000000000000000be5fd015998bd6043f124048c82e4d848e1b8c87442d0021390cba41c294de17648a47dacc06268606ba73cc95ae6e70000000000000000000000000000000000e05a3dbbf3da8320c40d51ac44c6380d56ecb460b0e7094819aa6af4d7c70d1541d4bc1fc5afd453b165f3d48d09a708bbe9e7a307e380c238ec1f8e2010a95fff8b03923ecd9b012f99e56c77a5cd", - "Expected": "000000000000000000000000000000000b00b5c14685ddd17ee99c74598e6bfae5bb1c103f8ebfaec3a620ba57312f3093f9ad5eac820d81096dfece90e72ef8000000000000000000000000000000000dd81552160d449cd787ac27c76685ea0dc993a9fcf8ab182f1ff5d8a484a47c14c1c1a785285b44336c7f6fc0732a0c0000000000000000000000000000000003008b6d97a12868554d294faa26e2ebe2920add650f841adfbf0ee89af72fc4da5dc23b45b7ff191a58c17971b50ae50000000000000000000000000000000013f438d927f35b04bee8fc55693d5c97229c8548ff9de39fae6e26c26f89623d3b0c810b9be8dcf0445910e8eac5c58b", - "Name": "matter_g2_multiexp_64", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e1f825b71cd9edcb231c178e160e37bea70108b369afb248edc7c6a59114c22e843fb5541e0f26c77a2b589ea88fb3d000000000000000000000000000000000d65d777e91920b17400955a4afecf82f67cd13f3e7c5d9c2076c4a4d8f7f26383d22d9977dfd0987f219a625c8a621200000000000000000000000000000000045716092850318c343f0dc5337df1a72f8c74dd729831d12103b46127c9180fb50cece34986a94fee6119e72d16a55e00000000000000000000000000000000083fac698ce800786719d1f6063c87d9f728da03cea2545b4ad8831f6c24bfff73e80f2c2fff1532f6d1fea60e7d438ccc5e9d01f6ea67dc3f943d57d9d8b5791d823592f7fae6719804c1ca097e651d00000000000000000000000000000000171d60b76698d4d3f14b4eacbdce9fa66b8c3cc7ecfb989439330fbf0d051d95f3007c389113346e614f5ec8cd170a2100000000000000000000000000000000151a96beb250bdeca3cdad1b07322040bf1cf2105dfa854bb24fa76c8abc25ef4fb924ff995da641244f9daccff2ff970000000000000000000000000000000007e5818778a8331cdcd1432b46abf1efcdf7e4aa8907fd42d5e7d14b57dbfc48125246b57587755ee1571be8b52d2c57000000000000000000000000000000000693eb562e22fa8ca4a655b76e43b50fe487ca1d65cc3867eaf793e50496f0b4658bd92199104c2ab92e4ac53c44db6f57b8fcb85e4dbc1969805d814e75b2b80f5cd1e5562bfc1e28becf731aadfc58000000000000000000000000000000001059d23ec6e472937d80829256db506d2d2deb37d4b750a980568cd5b0db085358a4d610d59009b64db1a9225f9f6f5300000000000000000000000000000000053d9ffc47672f1058856aa08e51aebd469111dcd129ed542454d6401e7893323f8a9c63641f499cd8617c7389518f8e0000000000000000000000000000000002b9b30a5e37b18af4bb02ae8cdd56f6a87820716ea1522a174a0d99c3716295ad0ff2daf663697cb56bc6053c9dba610000000000000000000000000000000019d3230c0bdc228fa0cfd5e0d8bb88be959e70e59d931d9f9e3683d5e65d8ba0d121fcea329b23c5905b80dac34de33b03edc53ced9ec5d7f302216fd30a81c3554a3fd04994f62b5e3da74c8b71bb870000000000000000000000000000000015a619addc75f425596f9a51c6cf2259087cf32afe9b1f07e346a2f4e1f8caa001dc10098d1287b89837f426d073982d000000000000000000000000000000001660598fcd3ab6a55423138ee72a4ca7b57277f6ce140f9f992dd9934bcda78513516df0d309a0e8ea151b2742dceddd0000000000000000000000000000000004cce7d84e0763fbbb54376833ddd7408afe3f741bc2b7e42fef3789a005134cc5540981a15a9f256e0e541ac58ff3b10000000000000000000000000000000019c20a0064f89d37548e06d63d8ff4fbf3584d5bcc2fc2757339b7c89db6d5da76d43b31da7364259187ed602e79bf4f976568ab779e335b8dc67a64f15b947e69cd3896ff393f51fbd3c3e3a157543f000000000000000000000000000000000d7ec5a27ac44daeebab7658011624c441e45924cce97d5bda354f1daf9362f5bce2ddf57151fa07f78740a7db170e8300000000000000000000000000000000121ee325f4252ae5cdd3e3495f36492d68d9dbe13249039d1185760e6e48a789744b2a9946a3d6478a64b378f76b0de300000000000000000000000000000000014c6c5b98c1e214f78b82f1b3be4c32c5013934b1231fec942b5591d3f0440bf63b1505cfbb7a8fa78a85ba58fd4aa90000000000000000000000000000000016aaea3bd0ae91b9d18ff89a40ae27b68d74f3a227383138ed737d59c19ac578da03df83f04c8d962cb9d6f84a15302f3aa5eeded490a17b1cfa66d409811741643b7beacf312b9d6c8e7e7e63579c8300000000000000000000000000000000188e5aed425a768f89f5ce09b2cc909b28c6a0165787c8e3750fca8e8162128ecf62ef0ff853d206d23bc076335008e70000000000000000000000000000000001cfd330da0d1b5b92b6533cf5a8b6b70bd93daec4373f28d669f5e970a947fd813ab1d1272b61afbd2748922b87c8c300000000000000000000000000000000002aec750fd085c99c3b9c3af62b6deddd85e49eba0293e6e8160b26a3945af546a760b8f8f85120d6a51d22313cd33800000000000000000000000000000000162a109abce2edef753ca6351aaa9cecdeac20919681c672dbb183b5b26649e885ff081b9d3687f802dbe20fda43462af9f1f9313bf966ea3b8f09bbe9dcb66a7f9e3e94e2024c49a72ccbbe03fe4662000000000000000000000000000000000f7ad6a1dd9f8cf52bef02ae1e82b0d20dcacfaa5c169a485bf8becec8b51373fae851ca29e64385f0b7024eb0bcf9270000000000000000000000000000000010412a7a710f842fe836414e2729d0ff2e145709d8f7b5e3964af3e0ae267ac53dac3db1e6d2b7f7671ec34b18c844a10000000000000000000000000000000002d3b96fab0e3b8fe44e316fcc5e35f06dab83f2c531a777e162f7521cdd5767ad0b6f877f876f73d2ff663d9b71f462000000000000000000000000000000000c09a98bf623e82a4d2d4b63fb867fab5d3bb1f85a0669c4c11cebaeb357c0717a0f246a9ce4064b7351dcf1e77cdbd393be64fc3763d06111961bb208a2b858aa1ff181781dda630ca41f0d45ef2a9000000000000000000000000000000000114270d35ebff55c0341776086d893513595aca3b200ab98c8b586029b19a360a04f2e77e90d382174296443ab8531d10000000000000000000000000000000008b88849c3cda9a23d37ec9f4700904edb24be95fbbe6d9e20ced0d52208b597d44bb9269830a1ac5cda35d0c0a03c9e000000000000000000000000000000001144466b13427c10ad7679567067dc47c671107064fbb9bad287924c9bdee653c395dc2654caa5b3013ade932fddd5e50000000000000000000000000000000008e14e3cff3bb57f0d87680a0c09d745c7272bd3c216ff9fde7c03df2caffc27e0bfd9f99912855c156a787200752c125d2a2b6008a3b4a4cb3a8c28864214c7fbe154fedab1f9ff8c96eab6a5f28fd30000000000000000000000000000000015cda76d42de9fa86f900a5180ff016155f31b9276c617ef664202848d2efd2876d412402516c0c3d26d49f71d894acf000000000000000000000000000000001307fa2b963fc19583b7e4ef2e9dddbe93e2505e8f4f00ec52db26ab411002136c1f646b1cda71e19480c767906a6d03000000000000000000000000000000000ba87b08173c841a2bfbe424584d4685c39bdd0f83f278f9fbafa8111102aa3acfad5aabbe032c7123631fb8b454255b0000000000000000000000000000000016c525c1dc247fdf34344168b7cc245579585fdbdd6fd783cbe60b727cd11ee97b87a86647f78dda207c98e65c2ee7e6854e742ef7c76ad438cbf30c30103741f57ebbcdca4d6c4f14e554dd1ed81b24000000000000000000000000000000000403887fd4429f44f8da7f17ca072f867e88ac046922ebe3e1e6c4f9d8e174399e7648aca924a557dbf7b29c540db33f000000000000000000000000000000000522324700fb6b2c43eb5b39e0da94cb60e234369543f530ea47f4aa510ec0fd79cdf4dd3ae046e21d78b9c0e35107900000000000000000000000000000000015e946b90984257ffe3814dcc3ef065fed1504f0790f3564c8bfad4e97cffdb61c0d73bb0b1dbe78c4266c773abd56b500000000000000000000000000000000078f604630074ebedbd836c463f3879cd5d4a2c947da0e47740ec369112f4fedd787ae59bea69aab61b91f05d92061036f4f00b2494a32844e01d0827ca78b06f5eb40b6769f36a04f20eea229c305f9000000000000000000000000000000000f722bfebd55f75f3bbd0a55492499c3a3f637ead0e54270042fcc88853df5bc5f11a3677efa26d31c28368e00c8713700000000000000000000000000000000182618bc8a4b3f6556d79848f90efd6883df90806a8358cb6852bde465a27a70644ac5d5040d4f64ec355763f1a384990000000000000000000000000000000015f717739a1cbb2eab30e7b1bd9b25f57ad56f36016b59128ea1f2089f2d1dd0128b455b1b0e9e3b320f68a38a1bdfac000000000000000000000000000000000b855788d6b6a7748aa923dea3163fe525a7b43f4619c1eff3f9219ec3d98ceaf34b97bfd19aa6f91f7fcff728728978191e47a0b0c72bd17319063abde7df51498cf0c980c46946bf80ae4c9864e2e200000000000000000000000000000000120048ace47bc1ab3fdc07713b91a9223fe0fffdcbeaabc8a61351d756f936e18177f672c5a4db7b9dc29bad16bb7c4c00000000000000000000000000000000101275492a6e843306f2927b6ab540d7a5ee925bdab40103b4ddd885e444e6a6ec2d6e99c061284a1967797d8a2e9e700000000000000000000000000000000002c12f17a5dd2c56aed0d308367f37510f83c94a4482e5f632161dd0517dc2d4f46a90bbc13034c63dbd04fe4c616e320000000000000000000000000000000000e4b9089155ce2178f26b058f4bfef57b73aafb83b0b78138a01890a167709f79100a1e4d797c5849473eb3486cffa4b7baf8816db56c0a602cfb4caa9089136ebde05722ad4838671e45ada5c716f20000000000000000000000000000000018180eee7e72b6a4bc2e60555236da335fe05fcbe2b3cca4937e73a550aeae6274122ba84ace78eff84d323b4196f58400000000000000000000000000000000147659347e0fac7a16c92950ea5fd115416072f339d7de3cc0f00ef369f5122ff050d8515effacc825c807f7e19650e10000000000000000000000000000000017bdbcae7f63052af9a7d8bd71dc98b6eca7ecf5eee7632959fe56ed51278099690c534ec33be4ace4612b0f516794aa000000000000000000000000000000000d6fa233be4d6d783bf973cca3740cbaf0f719827d7f9310f38d1dd9d1c1f125cdfca6d12fbf6a8e8104f79bf30b00647d9ac1699117bb9b8b90e2fb709eff4ea0f7882bdf6acc6885c9458703cbfb3500000000000000000000000000000000082f3beaafa575e86be53b4fe7b93835b00759f921933402282e5bb0e643a812e0e4b676ad51ff2c6f5332d777641cc3000000000000000000000000000000001760b87bc4d2c13122fd7acc6d629c9f9db9bc9a2c49634aaf33e258ceb3106bc2755b227c6660a1df1d92c60067cf5a0000000000000000000000000000000016a819d7109c9a12199eb98537a730908a693767cdb35a69b4c7329761939afea766f0b91ae405e273227330761a53dc0000000000000000000000000000000009d14d7138440349e83f5ded46d18b886ef3cd63e0e5bfa0a8b50985142b21a4733813ec347e40cabe28e6ec1e068c24a22b6c1a24eff71f0fc64b6aee8d3d2dd0827756f5c959f68f1216c2dea58503000000000000000000000000000000001676d7f489219b56c198f8494e156fc0672ae28dab20021b7a6018436c7c0f107efd2493ddc2a1cfb3ad490ef146348300000000000000000000000000000000001106e89fc098ce7bd8bead5d7f6432bc54501370ae6544f34cfd996b3b610f9cfc7ad366751ae1211b848aad7d93d30000000000000000000000000000000011f8f0bd037365b5427e76d57b018c1c644034b28d06c8f68c59bff45eb4a2c4d761d066d96c13f7e73dfd80c81704a0000000000000000000000000000000000fc826b5957613f35bfa36d3ce088dfbbd06c8f2e88056a22a9f35db561e06fa0378ccff29ba8b81cc12c7a504f8c704c0431e6877166686239f014008959332d9d009a801be6a1e68c2de52ee264bfc0000000000000000000000000000000014f0f64acb0d9638a68278099abf5b5da3aa087792bef15192cfe3689b69b7ec1aefbfa14e659358b5410d98d2eedac50000000000000000000000000000000015ca79c92e98cf8314a2f6319520e1eb7d4656ca6e51278710cefd9c768a25691fc58e983aaf858d3c8d0ed73e2beec300000000000000000000000000000000007a5192f1dc906693568291f163e9632c53e1f418a87cd25656064adffbf31863680468f3ea451fbd22ac990dc870b3000000000000000000000000000000000131d2e3f6956da8941e8340259b8a15aee9fc6f23573f9a348ee9a51bbca1308dc54e7b4675357e3a9c5971be3a5c16af833a784d22b99537236fb07ab7b59918783e35b89fc9692d7f76a03e024c94", - "Expected": "00000000000000000000000000000000163da4bf7e159e05eec90318a8ddad4a59fb02d7ae2fe18795d38c3ccaf797188fa16577e6a421ccfb12ba1ed573c4e6000000000000000000000000000000001256654eef3352b09e0027277aec042519d99eb2567fce2cfa50a0c251c12d3593604739128171bfc13b3bfd1ce8f9e8000000000000000000000000000000000b8a46123bc863bed525f97166bcb77504eeeb66d2db207eb8342a3d18f7f5a99910fae3e6423c6e84e437a2c4b24363000000000000000000000000000000000b73cf08023c8572f48c132add67dda7a15def638a01b198361b9d21a4634ba76ceed9819b37c12e24f148d255483856", - "Name": "matter_g2_multiexp_65", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003113ba8b216d933fe0c81f23f75942c0065d21d8f009d73b1f698281408874e33dd2750fd4298367b81827cf6fdad34000000000000000000000000000000000b8a921e840fc665a786d826f83ca5a9c8f00e7c802bce5473a7d1ebf63e8bb6cf5c4b426153508d874064d1f1dade09000000000000000000000000000000001492ab584088d23d3b0d1283904f9a8f29f9efe47950c6e9ffb9db2123f3f9820b906d672fc7f97f0bd38b8fc0ef44520000000000000000000000000000000010d321c2538f92aad4631af44ae39e63dc06becd2460f0cee0e526328d167fd6cfbcf4edfaafe32d13b5fe66c009533bb16c1bc60e1a9be9a82c93b7e0311e7516a57d687d8907599918df77b3b6caf3000000000000000000000000000000000ae75d01481a51294003041afc4802326ab878a3a75eafcda43cf873cc65e300d28aa986fb82a2d1d649e5be00f956820000000000000000000000000000000017640eeef8982250f88a4d187dcabfcc9adc3ee9194dbc3c04c741690fce5bc7cb07cd0b7c3497191d9ed8558fd0d24c0000000000000000000000000000000007527fd8dacb81b8d1abc746688db6a47211fa71556155d38361921c4bdb2a9e9921a3a540bcf55c6dd751b84c04a1040000000000000000000000000000000008de9109ba354d7426a5313d66cd747a54df347f0f86a3c0f99e9e4b68fc79641fcf98ab39fa23ef6f1a781c48f53f76cf301dfca76a83c70552c9cbc9c80cb20f0d82a70a9d887b04b150fa0764ce2e0000000000000000000000000000000017331b8367f07756e789f7edce4d22f6886656fed78ddacef6987a2751dd3d5d49011a050e7b2a3e11fc8d90266c9d710000000000000000000000000000000016959c303e11f23392f95c1402d1d1ad7f38343c711e96f18d03f832f76e3e81de789a6eaff797ae51079b13571334d40000000000000000000000000000000004266fd13db1ca80196a91263c79d1583b717fb61fd9ce5113e4cd94c59e605152b244e10e364b468c5a561c6fa9715800000000000000000000000000000000026f67cb263be83f3163856f091e9346651c29d4634e242da53b22eb6e66018d235b0f30f8833310dff9f3020e5bd3811cfb94c4e029a2126a9cf5561c677687f52059e4b7f8b7e7e73e5b1dd7f42129000000000000000000000000000000000114d8babd11c81ca2b8a7e193afbe0a8fce426b83996bae6f77201870e51c9355c319dd86b985272f73e0804c0f53700000000000000000000000000000000016f5ea7610891d0e72975816c08e6e25a75c7c42500655f26efdfb384241bbc825358a21caff347d00c8b2391501d15400000000000000000000000000000000199c8c74a79ee90c3606906bbb8cc163c214259e4d0127cee3283bcd9c1ebe4090ca7d7b180201910d3f6f51566d3bdc00000000000000000000000000000000032c785165ad4c1a2846e15318bd7cf5b42ce8b675cb18fcc4232e28701f225f1ea384b276e7a38b2c9e2e8b112f1911d8386fe6f4303959e58165b422e98c4813b1bad7808594473e4e66df09698cf0000000000000000000000000000000000842c65006caed9b53add048a2eea89e1b4584e1deb4365e3dcf8b9ecb02f337bccbe5d6929ef8c20461847f171fd4d600000000000000000000000000000000100dc23e6c1c6f6756419a9bad3133bba052f408a424c5239b8528ad4429a2bce64b72f1463625f7599ce43865581e9600000000000000000000000000000000125b4d71333274a16e52829ad5eaaecdda5c206063473dedec5a8ff4424def70e6f650926948dd2158b403f985a3421b0000000000000000000000000000000006a031e3c002702837e4ad28250b85cd94d42cf7b0d765b980fab95edded7636d13bdef1be63e66682c4e297d0cb2b0302e1c432f3b55ae87ab815647f196be3e138b2f6e9fe7acb9459650246187eb90000000000000000000000000000000003f7091a25da7d5afe6fa6b254604a1abe7a0c6ea11cc1a4167f5f648aa973d888383bc7e987b620d23e688868d318360000000000000000000000000000000016637f888efc3e057227cbefecb3037aebf8e330c3a794e51d691e3bc064237b98351beb746868aef977a83d1fe163ac00000000000000000000000000000000126d2884487984f851d1bd7d61bdb803321f263918e88e0677831563bacc9f5207358d1e9c76a5a25a66f0294f459e3900000000000000000000000000000000125c61b387a4462fa3bb2f06a4cfbd7df082d20cb23ee974aece2ec9a3b0c084d13a7ea83725a05d9f31b8033d2888ef9b0cc0ac499dffd627f5d19b87817dcd67e87561d5244a4b5698265f8c5b767e0000000000000000000000000000000006cf2bc7c691c4f8a64d0aa1ca3760d715b3188a2dd299ab09c723315acba8b0b4bbee819ba06cc564f0c875a63a415b000000000000000000000000000000000bded3d695e471f30f9d723f55826eda112eb0e3fbfb9a377cfa07d6233ed84108b92a79bb491a2971e9afdf83db8e9a0000000000000000000000000000000009b0e9928cb267508d4f9444c6ac3dc6f64f49a70c82c0bcaf4022e97854e5d9ec2612a2cd4d67642dc0451583bcb24d00000000000000000000000000000000009347dcfebe93a2f7674ad02ac48794e7cbffb04dd85b0c8c192fc85cfb9cef40fd11def6f63ae9a923960424eac6a02f3875f81fd39c9b3ec74eb269903dba4173d8eb0e41a196d3131252207ffa040000000000000000000000000000000013e8215c7bbdca445555c9fa0ae44e1905703334bade3294fc047ec262b9e4903880d52851967339eeadd666200b25ae0000000000000000000000000000000003b0bf4498103ac03601a8594b154b59a2a93d663f98ff8dbd2c85a1902e572a9456c629a12651aa87a1262102e1c770000000000000000000000000000000000e8bfd7d3fa0f773e6bcfd0d43a5c436862d1cb6a4ed715093c6782cd94699090c4bde597f65768e963fd0f8644e09b300000000000000000000000000000000064dab4d0d0c6b94c58b067337f2fac7d0d922cc822562b6bc941a794d96aac5ddb83d1d5844440d21d0a72a69303b8b2d8d4341822dba68c6fd58cfebd07b134c1d0c4e32ff63f7d59addff4df1ec3200000000000000000000000000000000098dd9a20f84fc26e78993a9de4d519aa2f8d343fbee501af945e5943e88425d29beb7ae54481b04175a07bf69b260a30000000000000000000000000000000007ef43e7a56e4e7d532420e152ce566d9055eadb4ef13d5698c49da905a4977fa8a7d3f51c8f5275582e1647984be61e0000000000000000000000000000000003755ee4432ea90f2197c7cc2e191dbbf7950c52a2c1b723f26d2aaf7a38c1b97efa29a312fed599f1199cf186400adc00000000000000000000000000000000150edc463f0a55fc70c2ffdd1f73a3abbdae459eb16adf79e96d18849ca638e6f41c6805b73755968be5cb110d81faa4efa3dab1d7cdf949bd938ca6ac371f953b3bbef1aec7ae76bda37db4c940b3d8000000000000000000000000000000000f7149602cbb3e5f2c5f8edfe59fc0fb8e1f03f89ea192bfe3990d87ccd28d4a80d7cd3003a8cfd669e1b6ff7e3cc5890000000000000000000000000000000006ffbc965bd06de07d8c0a9db8db5ab82d5f11afa1ad8eb92ed4453489f5899cc8c46ff02743956bed81229f64cf6efc00000000000000000000000000000000164cd3271ace4809eadeb1c0f769094272f3b66968690339bdb5da92e920cdc80c9d577ae4fa5b6426a5a6f46fba80bd00000000000000000000000000000000098f0a14a511ff424847d2b4d1b80a049b1f05ecd40af96b7a81def54486e4969011c122ca7dca3444029daeae2ecfc79848d3c53632dc461619c8c522013b83550ef3dc7fda197ba37c9cfe4340f5a50000000000000000000000000000000018409c0d0f37f4932cca87e24eb4d55e75dc98f938420ce036d43689fbdbbd839dc608b21d12a8af1d0a780aeac6617400000000000000000000000000000000109f2294669422a4946f926b1f106c2887893a042e3bf900559429c7fa484da4909216c8dcf826871534981021256741000000000000000000000000000000000a1ded19846e603b958d0bdcc9b554beca784b017d2a35ba117890fd0dbf729428bcd9823c7a378706220377c82a215c0000000000000000000000000000000000eafc89e30e4fc0544497e27674ec5b37ec0849fb382e608e09d0c1c94cb78bcb96ef4ea48e374aad1038881706fbcfcbfd192e917f2e0c4d6253c4e4755f30812149d1ce1ee4ae5540faf1dbfbc13a000000000000000000000000000000000e02cb3e099792ae7508321ce7afa323fd499de90c4006621ef5ce1054d0c934ae058a97ff8aeae0c88709c4d8ed0adf000000000000000000000000000000000e19318f5890320f17d5243adb4683a97e3e9763102c4fc93e3c3e3d24f4f61e0500be916c249dab00094b4ab048fe99000000000000000000000000000000000989faafcf6156472368b282313e076613cfe7ff135eb131b49e58932cbfafecf6585009d1f17ff8941d7f871be23e9e000000000000000000000000000000001167419d097ae8b96993b2e67da79b658adde1e12e43c71f27835845c7077f385612158d3e59fe2cb32b9418463e672679eaf11b3a30c7771ce63cec214416d798de20432670280d997b2f0631007d63000000000000000000000000000000001579b7d03d3d2c8a280e8ca113bcc98afa6a2705a5d228d92807a85cd5a1ee97510f632293a478c3fe0bd383f4b69cdd00000000000000000000000000000000107cc2e6bd02251bfd565b4b848adaa84babe9d4f083e827ceae6bacd9c9c221f0dbbef53278175bf27ebfe5949fcf8c00000000000000000000000000000000018d187c566690e4edd8d8abe5e0a448e352f622c96680378051228b6d081a4914aa51383326aedf45e351612ad6c5d000000000000000000000000000000000197427117a52f82aa6e931ecb0c5ffeec7f73ee8f44c5816935d26c06cc8285200ff9240d98cc244708e00669460f98b43077447b67f65e16a8aeb3564b2d13822e478dfb4a82a15a1c8fb7cc8170cc90000000000000000000000000000000019bd947df5a437a7f1ca2340bec628f2783cc1760dbc4a97ae10093aedd9f64e25ba79d9f4ce678f4fec91a3b1eef2d7000000000000000000000000000000000770e0c39988c9d8eca076464a3e10e274b06b1d2f6230e6dbd8dd59dd9c062f8958c6870c44ff196341bb9f65b8db38000000000000000000000000000000000a1833ef19e2b8e31577e5cd26e0a7fa46a5d25355d8b3dc0605f53714a60423556f3bcf17649745695f68f26570de0b000000000000000000000000000000000f449aed4120f3bef05506f2463f4546c7ea67b9e9110d3942dc256400d063dcc571305b1d4cd2bc3f18cf25319286e8eb64479b496c17d0587f6f26c62752881b6a9228643e8c43f21c441eeb643107000000000000000000000000000000000c1f9688ea64165f894e85b21761a9b2bfce891070103119ae71ff7acd164a57b0e054319631180c22f19eab8607f5b40000000000000000000000000000000005ba18dafcd3552af464acd469b133896e90c9ccd7e3bfc6e05db883f3c6aa1cc4610ec47f6354f6a7cff4385c56d2b3000000000000000000000000000000000fefbd9d78f48683b378d2d6311bf7ffaccaf7aa73a0bb4ce019a0c1d2e1673e52c724bf3a782729ec23d258043efff5000000000000000000000000000000000ea47ebbe3e858c5fcbf5b0cc9017d6ea23bda36e235d2aecbec827fdd2e4b042d1108d5f645b6dcdd786304e6bbf81b52b42f75aebdad1bf433917c025800c4f4e985cc077db3ba36f7484f95764e89000000000000000000000000000000000a313e1bf72d9a176bbad609631192c779e94c293463507edcd1c38bee8f33cfe6104d7169457ad5ffd9f045fce1cadf000000000000000000000000000000000af8db18938c51742b351fffddd74bf1137092ecb50a7e749391bacc9c1a19c7b9cf235b52ed577e7855d4ec1fadd940000000000000000000000000000000000febaa128de79274ef11d3e6378809d5b319796c653604723693c335eda175014b645604271429e3d449e756c85bcf6f0000000000000000000000000000000006adb29cc4ba053fea56d07225d2f7735651c0046f5cbe4a350dcc20431ed9457651d46a5d23d946959cadfc5500b7eae83106e9ea63791eb192e7a035bee27bd049b3a37f080076146eeeea6a769384", - "Expected": "0000000000000000000000000000000019a5b588aff8853adcfa959afc5135807d00196a75acb3536ad4fc9a9df3803d919a2de7cbe9ff762913225577ebdbf6000000000000000000000000000000000ac8bde939ba2f164795804d96dfa8d3a1c4d9e4eafb000cfccd956c24f4d594b30bbf961917f625c86270cbe164cc5b0000000000000000000000000000000002de09fdf52aec0b91bbe99fe2eb9043b19975c6fd503815264ce030dd5e5444f0f4275ac9a07a49de775335d52ea3c40000000000000000000000000000000012457bb55876c482e5b907c765b476dfe6ebfe8e588cb7f630e58f78942bfca57e6c0d5d7b0ce80e48960e297863d212", - "Name": "matter_g2_multiexp_66", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008f3f1f04fb80a23d348e3e25dac1d732265fd4a71ab8dad3718d268e49c79578e8e1ad1720e70357439e57df0791d64000000000000000000000000000000000fa4c15c76e395fa706a55d1909ede2163274a68b3e7afb8d2e0bb176f60c06f5a921c9ace35bd311bd79ae86340ba5000000000000000000000000000000000173633369e00c8c5528bd5ccf95c6af8b012e5a31941c134ad4541099c7c33c5ffd29a5a31e18be720f7ae85132cd6cf000000000000000000000000000000000800f5eaf7c8b1dd2787305ecc637a0bba8eac807a7b449410e48aed3dae2b4645b8459fcdd477fd92fa5ac6291b800ea4d710d2f632e3ed0ef69fa0219e16ba30d3efee99386f1a5c921f4548ebf64b000000000000000000000000000000000ea8057b2d609ac2130b21e0b4a41f0aca20ee7751f55d816ea42cfa4612b67c3c556b01b0bb1c5912a74c50a420407f0000000000000000000000000000000007fbccf8ce8d1a92756fe80b15c7d9342af4e166d3c1c7e35ea2fac34851cfd983633270c877224749365720fbcea54a0000000000000000000000000000000000885e173b73118721d28fd26f3a9c562bfbb878ce71091d7ae4b37c1f2625777d67955a2b7458af71077db7557171f2000000000000000000000000000000001754edbfc3f2af94c92e6754d6bb096bbc4b39bb1128dc6bba8b4d4d9fac6649598be90b06b9d5db44c4e77c0cd1537cbd9ae4597aaf582857b40096360ced0f044ea172551c6f9fe3a15e0ce290b56b0000000000000000000000000000000008a1a751b5f9a08e2bf5b2a58f62f0af6b8773f88e50f658ed220c0134e83c7031a288eb50a8a35016d2362b431d809d000000000000000000000000000000000d7f04d4a6c36cb3d105dc3915cd5d57f56692132681b3abca4b00e078c700931848e34ea1b7ec663f3886ff766fef41000000000000000000000000000000000a06c3ac81d6d0466e1ef21115150d04c8bd6dc3e4078e46eab213203c3226bb0c6500ae4fda591d6b8a791de598edb90000000000000000000000000000000014d849ddba2fa79b6a7107efeb46e9b6231d65384c69ed183acfb922d55b790d4fc7546afadc190b76f7da00103ef565efbcb4bad99b419820eec388f6f62ac8d87866d7beae6d431dfa48d4243b4a4b0000000000000000000000000000000014dfcb5fdb38cf09c1ecb284dd4f2de0c3d70f90d7c167a442d84e9a29bf43be62cd319b2dafdb6ead2c6596443a00090000000000000000000000000000000006220fc05c53f48e7e4104422b0660ab67fd88a695a201366de570f0ac0ad30421d5e37a1575e6b5ba35f45b441b297200000000000000000000000000000000077cb8ec1cb83c4974f6452ce0de630afc82e283eeb55d3b7e9969bb44bcf0404deae617393f82ac228b836c3cb6f95a000000000000000000000000000000000e2bdf539eb45a125112836008effd104e881aca397457004fbda4a40d152817801bd259434481f0509ab1838cdd1fd060d89acf5b49fd1f70fc54756c4bc1972cd8818e36efc37b422ba6a9318fa134000000000000000000000000000000000a09843630131cc6feeeee8aa8214408235655e4733badd6fe20c5cf1e45f6a61a5216e0cde937799437962706d3bfe2000000000000000000000000000000000ff518501614ed4a199ca9e9aad4e8efb8e9cffa9b4fa683093a49cef4669198a7893db998d5777f2cc8f4bb130c84360000000000000000000000000000000010ea66fb5224f4508ec100cdb611be133c4895a8de1b4c475b097494ff0f1ecdc1bf8fe467c630233cac2ddc07935fcf0000000000000000000000000000000009d22c0a45c82b0a19beb94eda0b93cbbe1f2e5f2d61279e1e1c93ba073cb766f5637195e6964a4814e588e44bb03f03386af376b9b393dde994da419d1f7aab60023546647f7b069ede939386bd6ee80000000000000000000000000000000015ca795fc7f0d169ba8abdafb1dee80b67e7dc616e824959f84c61284d6b2e0e8b9f99b414f5bd96d0e59b66ee706fd800000000000000000000000000000000042f473d1fa228961aad526efd003461935954abaae347dd6c9bc7fcd68b5f5138e57ab2a160cb19d1983089b58b51ab00000000000000000000000000000000188eb160cb968b4b048ce14bb72be27c228df1a6c014fa7dbec09a30aed8c71e8da59d3d5f8073b6a7d70d94c0e59dda000000000000000000000000000000000d467e6b05f033f3923667a82d5b489a5c90c99c5f68078aec700fc67a83d9bb4c09f3f00b9fc2cfd62bb098f885fe295ffca78eea65c00e1128f8dcfc96b39af1c4472b461ba5262307003bc972023d0000000000000000000000000000000003bec45d94f3073b2ca54d6332d36fdb8f5c801d9f70ccf6e3666b66ee06c0fdfd741f74cde1997aa205fb0318c9c4760000000000000000000000000000000014009b777b660264eedb35ec2e13ea586aa9438c47b3fbfd095ea3d8688a89c85bb4052bbd3edd450c19acea6372d0070000000000000000000000000000000017f26d3cfcb40fd6b4f3f1acb6d47a9b54c232aee484c7a8992a3d1accea794dc384fccefb0418d43e1fa7b399bdacaa00000000000000000000000000000000153c6cafbff3c53114c96d8caeee2880dc063d7db5edf5f14157117387f368c76b739553542bf6a9bc4ace3694de885a92837b4314e63ef5a153ea2ec4bd373cc3cecfa3e892c3a12aaac8ddcaf5905c0000000000000000000000000000000005d2481438c03493efc9f1e8e9ae6ab05b7430f7fb82e108aada0e886b14d769969d54b17b31e5bbb63d40836748f541000000000000000000000000000000000971deac599b2161a4baf1178feb81fd4798ad5cb063b1a0cbee7cc33b8fcec6c3f43d1d46d9ed45555187db636af99e000000000000000000000000000000000222acaf8df647744859e04104a5fcd546949feff6244e192a9031fc838f368aa465a3799779c637ef0087183f30731d000000000000000000000000000000000b8e8f1889816f89401b070db687aae47f7264c9be192a8d6e485ee71a5a688070d57ad8928d09d9a4925f1050e2c69e127ef2309c699a3602b0d86a070baef0eef90f539aac3cb6ff42cb19f284bd99000000000000000000000000000000000b8a5b0dd422469a8d6d7603e9f3179f443ef3fab0016afd94e93e2ea9e84b332da4b59f23a5257b99460efdf7d2aca7000000000000000000000000000000000c28e7068769c3a79bb8d92c3b89eca5d6eb42e3e18c2a7154f43a671f8670f878c4b110990c2e2b163ba4d1155319fe0000000000000000000000000000000001804302246fd07d86f4bb23f610af38deba8e324cdedbe5e61cf0941281cda8fb5dc211fbc0ce6fddf30aefa9563a0500000000000000000000000000000000015813fe0d6bbcfdc8e7e40b6141db21e1b490d846ffe82eeb3edcd9a024315193259612155b0179a4971e205738af74ba0f9a93c2fe35877ddccee5da39ce5ae60a6a19e72481319e3b3fa2eac614890000000000000000000000000000000011ac1ea4dad0f650fe0844ac3ab9434ebac6eb70a5f77c8f9c892cb4cb06639a15c63a9b820ef8f7a720040ae5b9e49500000000000000000000000000000000117da7999552e7886a25a939ada0944cdb15b5c468e9d1c3bf5b6af920e470bd648d24f3cb7f91e670f57a52cd65f7b3000000000000000000000000000000000a24147ef5f2b8ad888899c1db8df0a601eca9d76f1b934b1627e7eef3efe542f51205b96b5c00916688579ece81336900000000000000000000000000000000151863d964b12287ae4278c905341124985410f1ad6a72bd5c62230b7d8b0cddbea0c62cb2a7147afb5bfb03348be53363da2f227d636f10e814e360c2156e686e26ce3401dfd15f47c4ed277d05353f0000000000000000000000000000000001d32ea5faa6303c530790146df7cd5cdee93c0933b4cbc1c2b8030bf0a8d2600dba1907df1756152625cfccf8cc7fa90000000000000000000000000000000017b05f549751d090f42ce8a3ac5d959cf988ecdc485f51734d52c40a3e22a097917345978209fa74a0a05be0a66e5c6d000000000000000000000000000000001481fab7750380626b174602d9fcbc97555c516f4410193d2849443cf25ec22840e4fd00b225f98d81b38619e8844ce90000000000000000000000000000000001d56434066551c5bfbaf8c9007874abe57a6f78de9355a297bc117f2bc5e6e3f44b248037f400f7caf83fece0c00ba0ef79e3b6ce752d140c3dfb2007a08221d989038c921efff3bc4e150a6155a33e000000000000000000000000000000001667f1400973598ad3f56c2e49dcb5b556cc38ee3e5801ac4943f3c4554205d8fa69831e582a084aae1ef584feb0a1880000000000000000000000000000000003f0bb26ea548e498f05a5bbda8b8e536613f10e7165607ab77565b193f794664c8ab0a5ae2368d7483b77bc1173d14500000000000000000000000000000000176d8d294b4d975629c6a89bd6d45f9c3924a621259ab43d33a3d5aa1f423b68e3cef96dc103494bbb9036436c170f5600000000000000000000000000000000002f8ed87c584e69de59cdde02b6de9816c31a6efbebafb6ad9cecaf266f5bb9c8880f062dbc9235c91c668bae5051f4bc08091af8b8c6ea5c26f1a7d795132521350d774042d3a8c0523e86fdd23a3f00000000000000000000000000000000085fee95b859c52e44fcb2900a9aa590b1a5c2f981a388d6ad7b81ffbfe033f648c4a84e2119cb0484e178ebd3e220d100000000000000000000000000000000171e6ca074aa97981d2c2ab000a8bd12cbd5f5d574cb83158a6ed734e8f9b7aa4b74aaa43b7aae31b3f4fd3d82fd30ea00000000000000000000000000000000004fe6099a52fb491a0624a8d787d95617f6c64d16d20d1b3769f60d4721f7af66d7e3e905b3e08b2946ef7bff4806ed0000000000000000000000000000000004d3d1a56af91377ae6b00e192ad64fce6dd43a37592fa8706c9344b3d96b1f930e03be85a5ead3007f9016255d2df7570363101b87d685aa7314f6569fca0775bc6aaffabe136e6c336e8fa43dedb8a00000000000000000000000000000000155830eff04ec2f4dfca4f73403e408a68830bc031555433fd38ab3ce1035b5f882bcd6032aba69ecc43625546b4a3a8000000000000000000000000000000000ed5b698b1ae23769cf5b6dc2e39f8500fd8a881eb43452d67c6b84ef9f0b3c7d81db1909b646e92412acc7365923a940000000000000000000000000000000009f28ec2f949cddee9bbe2fac12c2c029f4e472afa1ea56d0edfeacdeb9f43a4a43b79ccdfbe8957b4cc16bbcac1857d000000000000000000000000000000001474b435131301db9e232ddf54569ba99bc476200ceefc15e4aaaf1a574c1de8bd2d63c8280e23127a7a036acae223b1997ff3852cd97c3a65bce9083ff66197fd5c70894641195514d556102f091e8800000000000000000000000000000000168475854829d47356d9a8dc13a94e8d169771ea0070d9ef45e666d5378dd676d603c2eb57a3cda072c11e0926b02d650000000000000000000000000000000008b493a9f4c19831341782fe6285db2f7e8250d72952351ddcfcae6f22a2ec0935e29d396ba32f72dfa4067d0e7ce7cb000000000000000000000000000000000d9e72e22f2a1522babc5f2e8dc7857ee690f60f7843ffe15a080d56bf63db86f124cac039cbfa16fc8ace4d6268a1180000000000000000000000000000000008f3db1f6c0e5e7b3bb27abd34bd877cc3c373c681a3abc88eaa91636924ee477ba5032801dda091dbc51936a90c84685ff95dfa306f91196849d752569b35812e1db7946708cd06df9db9ee75447bc30000000000000000000000000000000004e34bff7e9e3ede02df950aa0e8c5f4c5f85cd3be89d211e957a7de95b8e321cc11400c3dd5b2ba0d1a3008462cebe7000000000000000000000000000000000fc1047097f01fd2079e6357ed379ba39107ec41ed6c6dc17fa6248d52be2b1cc2593c9735a6cb48e6d6e0434028f755000000000000000000000000000000001896fc5e990aeb416cf21ccc73f02c41d019d0a2679bd533d0811b7c16ad3ad3a6988170fb2db030b5fa7c3e4df5acf4000000000000000000000000000000000b70e14ce1b54d7913b9f3782b2b8ff249967a6b871dfac7f54f959954febb2783cf20e20d1710e5526ef8aeafecb3d603c4308f0467520343825a91c0421f9c9c9d06957fa2fc051970f14085339e26", - "Expected": "0000000000000000000000000000000008056d4dfcb593c10a877cc8a4accbf58f360256b76876ed2b33a07be3110f8e295ef459dd6fb10d12bd02a8276351f50000000000000000000000000000000005686da1a0da89074c6b13fe9913f5cd49e0ecfea46e06493510625f1393ba4cc2e13f023fbc7ec2e130bf9a4f7483ef0000000000000000000000000000000010cd660001f65876db5b2cb1a56d85171d4cbf037f3bfb0e01bf4430c479237cde5b6cce5839a4fb22b406846e757868000000000000000000000000000000000809d7711211d37df76cd1cf71001cbf02c76df67c83e4eccea3e05b11d196b5d52ad7c3d0a00d9f0ef5b018717fc3eb", - "Name": "matter_g2_multiexp_67", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005d6cf50e3add0e5ac3016b394ec363d6145ed66ef56b07bcd33c90600e83b4277558695222062e02d1e2b0693858e73000000000000000000000000000000000de8caaa810d4ac39258e3d1656bf7f2fb7853a5963ecb989346abe90d5d35d3662f6e283cec7bc386a6a8638ac395ed000000000000000000000000000000001849ef86eec16b0612f214c5ed52c0d50a90bd65b623402879f2654fc578ab680d49af9afdeff546702304597a20f1fc00000000000000000000000000000000168707730c4e74eaa4e85e48e7239b9ba3e8cb74c24b7126a685da0fcc963b9f9180e252adf7d8c521deb1a2ce0099582849fab097a4f71bdfcfaf435994a0c6ac3671a4a9ed0402010be83ff95228fd0000000000000000000000000000000007d4fed2fbd9e9dd19e0af5c52637b2cd337e0bfbcef0384f182a56189a7e7304b9d2144266ffa79044be90cb7ede1b6000000000000000000000000000000000baabe8c23a10cfe85494c693d1b09fc8e43ef5f233052d5b6294dae14b4ff9e5ec240a1c00a16a9ddc27cf7b53bcc7c0000000000000000000000000000000001c595f193229da9acff04ef67ca444b0cec75db5b2c1921502e37eebdd2bb43ef47290fc6f1980abc75ef4c50034df00000000000000000000000000000000010fe7f3110ed3a240366ad7ba31d56ab993468dae2dc1b667a46c7759baa37b865d02834e14280a2ccc062af5bb2b7d6e6558521e301eabf09e80a509b46cf8ec118ee8586f4e46a7313a96dc37ba69900000000000000000000000000000000150350d8a771c79268606d6a5e1c147dc9d92e63fdc60b20be688bd52eac697aa5d90fe1b7b91321b2af87c47ac0d5060000000000000000000000000000000000fba8f4da448b8f2bbd99014bee2f9c581f2a974bb0b54f41a84a7fb359e9dbf88ba59a705504140284d486241e94e80000000000000000000000000000000003bb92d6a603bd93f8e987071a7385de68d10cfbde389eaf01ba6480caf1ad8aea03c84d1889b7d5b5c5f72e62a2d75a00000000000000000000000000000000193342a9f15109367030724946342e564507b26971caf75190e0b209e429a948d8b21ca16041a01010b68222db66a16b8f2f7c525fc0f353700fa823a5d32a93189699206c5ba5ed271a158ebb47674b000000000000000000000000000000000bc4a46eea57231cc64758560e3032a8ad8f1907b3cebd7a8faeb98c4216cb8a0c8fee09929ecefc4bee7955f4e799ba0000000000000000000000000000000009f9486257ae3f94a2ca48eb203e2ef44ecf866ddec7824e1a4bb3b89b320c38b3c46de8202480628c53c415433383a3000000000000000000000000000000000d8e2b5d0825b11344d16dbb2cc614c6b84eb1cb43f70d70e272123867b731775b429aacde611318b2700aa567a84c7a0000000000000000000000000000000007f720929287a70873e9f2f2031b66693eaa6e604668219aa5aff3f50e720b34c5fa3f5c66eced5c3e86e8b34a81b984c7e8adc0f0a042a32c733b5c3356cf4a7d648be51c1d78534ca65dd43a0c13e4000000000000000000000000000000001537ed68e203e56f31498efa314322694ebd74cd1dcc3145d534299fbdadd4256f20b9f74b895931a60753bde6ff9030000000000000000000000000000000000935c6ae847aa7f47bf427988665e5e18a32aa869e196cf9d5bac1349c650219a8d20e01bd8d49bc7e4bb8d464aee84300000000000000000000000000000000013e0661d7254428861cc3ed47c3fc9daae8b86db35d1c64f8ced3bc18a89202825f13163ff94ac0ebf046a0a99727e200000000000000000000000000000000039a6b0b2cb91e460d50eaf9600c29fd4f82a81c283ba4fbd9a7d103efdaeb1e82947f5cc1a7a1112ae6344c51119201650081a6720845a20164ef7c06ce1e73286a32dd64efbe57fe46765008dc9dd500000000000000000000000000000000071a6b0267806f2b9e0ba493960fe0e43f135c739a54c8daf5ef9ee348a281f19876f80c0dcea59dfe9457b49809c12a0000000000000000000000000000000009ac83690c30a4afd78f94b2493674668da4efc84007d2a08fc78bba271ed1f43e2a9e5909149bf0811c44dbe07c52f9000000000000000000000000000000000f5d523612fdb2e7dcf5da56720057dff6b0b80707cf5924d146c0c072edc0635c73fb04256e06c7c9355cfe77a7af0700000000000000000000000000000000168431fc569869ebba9b4a72371e3df232545b5fb95778baf3d9105930d9a89b4cb7eba430e9162a5589c7465e54ca3ac067d18b95591f7f14261f95513e1990f5a4f6908f94a015a93fe379726d5120000000000000000000000000000000000ce836522b983fe3ef6a502a0de4c599fad8a36a60d914218d5d2cc4d56d69eed8d27b2d50899639d1a0ea9dc7597f900000000000000000000000000000000014110ac048ac4c20e53f2214df8c06d77f0b3150077d027691cacd3715d4630a387d5819ef58eb1bce2e8669be330a3100000000000000000000000000000000178e5cb42f56df2f1b255a028a00df96c02eab0a79aa0ff3e9772fbe3eb62174728259b3a15e356e6d9666eb65fd6b7e00000000000000000000000000000000045197f136649b61d6e0e7b9a56674e769e2d26716ee7a63fd2b83b767a9ae96694e9cf81375d0377a1b27ea6dffaebbb448bb01a1963bf74e0fbf99329005af8e932074358d855ff43c213e02bf26bd0000000000000000000000000000000016a6a58301c243b0c59d6934bd926d6440b87b49f004f411ab0fdd924480175052f63f594c18007359055dc776e7f2d300000000000000000000000000000000176db4845cad46a13d9dd0f4077cd22b3458f64084c7325e9885f8ca341ce3ccd4f634f41efd6a70f16e1f0c9ae103a900000000000000000000000000000000068ba68f652c4f072a64d56618f93a1e148274b1b835433be878c06e11f65ff45b7cba0f67fbe80327abace68396da7e00000000000000000000000000000000047a699487964c98453207c98cc91c980c1ed37dc26e17748e6ee88e5f4c0ce424d87c82ca6db2264dc8aa9e437a5f25441fc4cb1ea8f86af8839aa40c35c0706f3a159b4bc902347009f744b73cee35000000000000000000000000000000000bf7e4a9751d4e3baa7ce9906f4378764e5384136944f6d3f3074dce66ed017759783c64fc381f0dd7512d6f6e55b4aa00000000000000000000000000000000006ae2a4fda156818cb5ea6120edf7ea39370eeecc3f306890f47a6dcfaffccbb69fd21f33fe491b7065838b277ad2b2000000000000000000000000000000000d3ce00c2f5febfeb232dbbb74fb0405bab86474d1d9c545c93b65c7892bdd58aa56225641074ec9b428efd9063085d00000000000000000000000000000000002552a8c1848fbefd6b039d6c4bd47c34dc34ab307163c4f6d337946f1d1b41aff2f7e37f5fd94012f0ebd21f97d18a83020a1ab853ef2018976e43cce2724105a2526b28d23b0226c49ff3d4a03d40c00000000000000000000000000000000105320cccd67b6ea78e96e66425a10a6911d2d348fac3231af583146273609fcd7fd27a19d4614fbdf05bcca0f92b927000000000000000000000000000000001204229ee1f66fb5a5dcc4ee978327e35d703ea310901be9c100af824e39d24a028ef8fce42370e5d734df02a26c145e000000000000000000000000000000000dd21f31f116681c1810bc36141cc18096cc113faee7db2c189abb7a746e398e272fa0cc61286aea0a5ec4008c8d03b60000000000000000000000000000000007911297718e98588844b9022c825bc4b37f2af30e1fc2d9cfb58b4500dffc8e9949afddd051e971fe78d4e1e7ad1b4a82702398b8c95c3a8cd163a8a3cb2a7a04030ef99404c325115e9a9312e8c1bf000000000000000000000000000000000760787190048e6ec8bc3bfc368f010e2f8aadd53164693a62b0d7207575bb2597bcec4bb382c57fe9053e90fe2f7159000000000000000000000000000000000ec525abbf13da64a8093c5d3fb800440f4c1fe798bcc71eb97bf2e0aa9e8be4b08afd2313f9143260058132d2607141000000000000000000000000000000000aa12c902084eb843daf7b351989bbab7a86acb62eb54eff0c7599bacaf44653c9fbf53f47f6ca72d22ea1671842eca800000000000000000000000000000000082f330d9a693f2bb9386fe5274aa79ac73a17688821f3c705120fb2aa76903627786a8614053f21a93e0aeb555de64e338468a325384a9367c90bd0450816a22849b845aadaf187c27b3f09800e791b0000000000000000000000000000000002ce7f08b8d5052d8bd07090744ca067700eaa1db61dad3e5086661850337bcab485c15fdd36c309a9e5169fd2a2b55e00000000000000000000000000000000073fa834cb4dc4ae120e738059749bfbd86b9e64fd71b1d372dcec8474f3341137ce8cb97a38955e9081f9bd5e07ab830000000000000000000000000000000001568df6806d8c3cfc9231802ebe5edc5d505198747a0adc24d0ac59f28d32b7b379d1f2c6b8352389057c7465692ded0000000000000000000000000000000004fb4b08a4fbfe197e924be3f7213a769a2bcd24109ae69a32a197b6212c5f50dbe8f46f5ab6044a4c779cd3e09d13bdd29136cbc4764346e7ae1af92fe64560f453821f96f32a42a2006b6edee75021000000000000000000000000000000000c07ff656904a47b0c7bf77540abc47cc6eee3e76b6ff0983151de9468ce3a860c427f3d5d489d096264159ab0567cd20000000000000000000000000000000008cce094ae1d9fff246a0e76cd67dbf9808c94554372fc4aed4879487ef240e45047dc201dd8bbccb613feb9c4623a0b0000000000000000000000000000000008a25297940a1bca1267fdce450b0cf43105eb4a21ab14562116039bc8379b1a3f58a7c117e9ba735bdec40f772465300000000000000000000000000000000000ae17a9b1fc3b0b7803ef48cb26643e8e78ef133f94bff5f87739182e662e2641e72383efab1f3ec58fa20fc816d56c675a59418f1462247d3bddda5937553e96d854b5df64a68145a193b2b1a7eb250000000000000000000000000000000002357e5a04b0dbd7f9a1709bce9b7afa12b10c7274b440b4dc3bf51a801d483804b1b4b9a096c3205a0e2aa7c0100c6e0000000000000000000000000000000002ff20af67f126c80293e44bb3c9ac74a94586a2de4146588c7ee8503530398eabc30f7e89322727739618087fa55de50000000000000000000000000000000013c6d06ce509fd557946479f2768f62474e6db04b2c92c5cfa86c023f79d05a387bd4c9aa618888476d4ecc93ba0995e00000000000000000000000000000000000fa477870c952f7506b879b17fb0a1c31771ee832ce0ab21a513fdd91b7a2a78a03d297c55558b834e255462b15520544a345719b40f973398a6fdaa2044037cacd7f6c361921c62053cd51f2e5ff700000000000000000000000000000000181336b8fdc03c02e23cd06ac975855caa2bbc1fe78a2fc7a9d0963c90a1f1f9330d50b88bf2526db6132d336ea5b8e6000000000000000000000000000000000f2d94d3fde2c0f67dae5a6ac12f713ccce2621303762e01961843eb9924d1d3c732b4c977d8cd0e5668adcd7dbf7dcc0000000000000000000000000000000005ac9ecab11c3368c75b0d396889dc34bd43ccf550d817c1dcdc7143c15d5c0e241add37328a7bd8556fde87d75d67fb000000000000000000000000000000000184704eeebead43f85b32d7f3efb9b9469f3ae10b73a2f034bd33e6e66da0bc36597d8e29ef5585443a655e24ffb68fbb38b4cd72eb18c3ac87860aa58b4b439712562f742f112b5d769415e9c19d0a00000000000000000000000000000000046751743f8f747e378738c265c1df3a368cd9570a2bd7636991045974c34039161fb0eddc6b813003e0908915b402170000000000000000000000000000000003341bea6cb81fc5e7baefd386a518d17a6f752c0e1ace5a9580a1b1649f5501c7b4639ba0cdbc33808d78b025a31f190000000000000000000000000000000016e3b9e8e189df73574a00a721440379589a7a6df09eca9a790e04c729400323b2110f63d547d83664c35227bd15b5760000000000000000000000000000000005ebd94e4640344e99e7e0f1619c6288665c985b90d99921ee61bbfce921265c4881a7e1034bcd840a665bae44467f5a94a849f6fb5a53bd5957e53ade1baee05702185b4d0fbb7c1cc0f46cb75614fc", - "Expected": "000000000000000000000000000000000d993522760839abc960e99d62dca1021b52ddc8147929c4a064ec72570ffb3793205598cefab8490446453fb6da231600000000000000000000000000000000105db1e83fdff735d06d34574f962e70d84e2c1ceef4d8a8f14c2673633d7dbc7b97ba6dce9013f06fcfb134ffa2ef98000000000000000000000000000000000363be663cb0d36b8eb076df283b075ab9e568e460be804f197c51cf7ef611d8783ced304407d4c2540f1a4a04c18467000000000000000000000000000000000ab2c00473a2267682ecb356422aeafc893fab96a3bd27ae58d9b0786624c8fde446cf68bf8a003d9449702e345b1ace", - "Name": "matter_g2_multiexp_68", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000a575d896b06c5ebd7459a70b9321cd0de082dce7dc0ce7e39581751d01b7db810bca80f39f521df0bf70ef642bd66a000000000000000000000000000000000ab497a9590deef40f6fdc0d4db2ae7b6ad9ab59f112a5a0671b48581f1f2b6a71602c73784ca6c0effce66a0a9c6500000000000000000000000000000000000af3812439e44981c91633f73d1a92298ca1ed426c98cfbdb50643cee36affd5fd02886349aa608f4b8a27452a51a96500000000000000000000000000000000013126db8b642d33dd988b745b07084ef86a228767f7e8bd45aac830dbce4136ca5febca5fda9644d3292203e27439d9f5b9d270fe31c772e9a0bb409d9f08a07887f045f906f30e2653d293b6c2c277000000000000000000000000000000000cc12f75fe5e6d6f082f9977dcce64c7858f3b6378112e7e083caf0c4b33b5811d62a1130c595937983905fbde8db1fe000000000000000000000000000000000308b803bcaf4f63affaea0206aa9f4770c21b4d191890602bb4151b80fdb42af0cd9f8dd2b1a3adfe28d0e49712d2290000000000000000000000000000000019f83af5cbee858fcbc9bca0f499222849b9e80dde7ac79b7c46785a484fecf274e0d4326469eca647cb223068a183d8000000000000000000000000000000000d0a8334171571bc63054c032299824523bd2476b1150a67eb17b84bba01d8a65295624202c3874e0302159951734702dcbf4fe86140c50618598be9185830bc1da11429162afe0528f00eb6698ec088000000000000000000000000000000000141cc01094391887f46391bd49fdedbaaf524cfc94d741cc7c8cf081dd7c425d81ea3e407be48127550012e39d2b0580000000000000000000000000000000014db31972eb242d6c2912b418ddf416fd7911f13aede9194559b05d1c9e12056deaa1e56c155cdbc231b39f4f9aa91ea0000000000000000000000000000000007b361beb6c156b5c8b92b489e6d6c05e32a4376d20ac3e1a54c94e678c88480779bb789c3e1ff7a021aa6d872c98551000000000000000000000000000000000215d270f2d3c5c5b9fa99a873fdc337f4edad6889f7a55556d8ccb5ee86b592453b74a720ef6a907bc342710cfd9cf91d7fb7121ef0baa85046567014620e1adfb9e8b3bc95adccbf2e0b0ea8f37c670000000000000000000000000000000017f5d31987655f8eaf046d6ea4025444924befa51c319b2bcb02dcdfde4d80a1c48049514e0b580e4bb59dd2fe40bb22000000000000000000000000000000000141ab771c08ad7c592725630aca0b2564de1ed8759eb3afb10a4bf451eb21d25e8d917f49bd5f7a06894baafdebbe790000000000000000000000000000000012dd82703c939cc5e7dd5bc3b924d744f0ef1a95fd0b9e57617e822e3fdda05b2e5a9959ec48cba0da40079da2253cc7000000000000000000000000000000000c53ff34d875fec4c7095af324d15921cd775873a3ba67740b2c123d6d482263b1cf93585dc810d19c68965cdbd9e102310d3b0535e78d803b477e5dc26c71bb18acfe66bd5ba5892d924d265afd6a16000000000000000000000000000000000a6514331035d42f58abf98b805f159921d8c4c935f88bb5493c580a6ce14a65e243424b41b3a9188e26a7f0c912a378000000000000000000000000000000001351e48b2d3f619887f4e83823dcd9dc15afb2800169ab78a2cd5ebdf25dcb6310f1051894bd2b549e509c55f5286f600000000000000000000000000000000007900972b84b6a76b2e686fa5757e98b8395bfc99da86eca122ce209afb39e8f3b07603cad92623774ed54d637e350d30000000000000000000000000000000002c68c42b3924b89a67764990478e48fc17aad4b5543bd38bcfee34fa1cae7535671f3b885852aecac53a30f28b0d4aa2fc9417e65cb76aa0093a7deb3d38c111c68f461a4aac57d8f09189f94407ee8000000000000000000000000000000000152d2c0e798d85e4dbf35dab808dd29d724e9b6c7ca7f53ffddfe1aef5976f2d3079eb1d3099e91b37d9fad7f1af5750000000000000000000000000000000015059423ee4e7201aa65e39116a2a49ba715b15e4b9547d18a0efd355de6f5a0159bc9047508bd3649407758d62887f0000000000000000000000000000000000e5a823fdc69f3928b22c542388f982f8131a978b08dde80d44e51d9eaed2ac4a1d5fa7392be6c7edfa33e833da4832c00000000000000000000000000000000044285f4e4ce526f96f9f512c5be754e0b0953744dcc04807ec6f041ba5c6fb9d5d395e93317064d50e61aae26810df0aa0b2d714aff175a0be2ba9e675a2be8936c42f15e304a146622a95dd6b3e3ef0000000000000000000000000000000019c457e369dbfaa130ee79bd33ca70d00a3797b6cf62126baec0c5d7c3fdcf5ba7f41195276dc412b6862b71560aeb77000000000000000000000000000000001206f67dee6521ede85573bbd5784d675fea42da16010544857d4e2d81b720b6f85f646fa23540880b44a6cde9a39f5d00000000000000000000000000000000142018ecd7c7acd4f4ae288e1c6a66594f1c7f31bdb9bade2b4dc4c6455cdc685b716382c54d67373831a19100185e850000000000000000000000000000000013b0b57463a3e4cbe063c0d4f4e998cbeb132a41c2877106ee60e83d4ef7d339a5432d30a3c149a42dfb1da9d61f34030227c3510ed6e4c7f84b11ddd2d6caa55e0e79ed59e1cc0cb325d55b5d145aa80000000000000000000000000000000008a463003900194e45fc2610fb461fde538b17c4fd516919000d423f5a1b582342ab9ec20d8eb6fda8fffc6a898e46420000000000000000000000000000000010eef0f7bf73e35dd75fb924bd9759c09aded9cce46b05e5d3c5eb3e93e5d5032ecc459e2220aa529d2f773c4b8b8c180000000000000000000000000000000002a0247f82a25468ee74da555218cdbb6405871f7097c24e89db3f3eab59b91ce48ac06e8eab2c049346436c846226a3000000000000000000000000000000001895b58a50c025e46a2cd0c59d5437f6eee75fac949adb7ee12d455c96206a33ec9ac17d5088fb773618fec131981ab6ad930000a9f82e082d408999b396aca2b0e435a66faba1d95e10fa0abc0625cc000000000000000000000000000000000cb0f13b0680c2f7de522a59f4e46fe1d4af3a64cd3ab97a2523ad3c3dc42f5e6760e06cf48e4db22ee64c5ed8273dd90000000000000000000000000000000016517038ecd2799d787c5b6ee93079c93f78de4a96449bc82699ddd6eebcedaa1d02981ab47c529652cc21663f1a665100000000000000000000000000000000067ae1dc093d4aa2ddd8b7127dc60745ce9c462a066106b099a7a07525597c72e4920bf64c2ea8a3fef3de51c703de8b0000000000000000000000000000000016374f51023e2448eee7c64115d85794996fadf4f76fd4266c45093c266f35be09e861d07ff194f3d15e310385705f0e1a6799cab8964c7b79b80e76be237ef49c2bdef5c99a38ea873af6e9d49790ec0000000000000000000000000000000017479396aeac06bd624a47e75b066d6daf5a37dbe515650cdf3e16be21e7d3a1f52a695c1c06382589eb7fc869c7d9250000000000000000000000000000000015c31ff36ed4eaec4d3927e62c111d062236e19fe6514236e6e3f7ff05ee96e3e4c084fcafcd21049a81faa1f84b7e7c000000000000000000000000000000000341b440e6c6273515fa7940d2f77018169bf6362b70a7b0cd6d66cd332ccc30e3ac48f7581edf47ebd137253a9c1369000000000000000000000000000000000cf424de046252efea9320b32b79bdab58e0e04f2916b4e8ef475da7b8ab85d8d5fc793a45ec6e6c035b6331a895d3efb206dbfd70e4b24bcc09ad35ce7b3aa62d17f18347f2bc5f15730202909c93770000000000000000000000000000000007c9111a85a6acb851e9cbdadf182096b720913ba3fb357dc2cbf2b8e796e9a8044b6df3ccadb740c73a16c3780c640b00000000000000000000000000000000059543a955c84a197d23cac22e15d82363c881026e41c57ee924da2a8c044f3021b29918d1db7926ddc2fc7a662ee7ab000000000000000000000000000000001355d8bcbea65a50c9b6ab59881e48e8e5f5592cee6aa69d5d01b033a84057cb6e74d911769bd2ab5f9722328aa204640000000000000000000000000000000011232571c95d0cbadf8e70454c851974efa4b326370249238db159a1224cc6d34eaad690e1840ad887a875b667ac1f193a607a7301bb7dc5b9c82d956ebb0bc54568d0654d725d4d5f13ceb6231e862e00000000000000000000000000000000088b7cbecf91721e01e5e4a08ea3b261febb58cdae3056d9316c3840b3e5720a289739568bec7b899f4b1f4f5372013b00000000000000000000000000000000001f8835d4b0e3b957e46b718b6bcd81acdb50ab85f10bb70c6343a23970efbe72bef89dbcb24d66e6a6be3eb55665a200000000000000000000000000000000046500afd292a31bb5a4a9bd7b5bd0fe608bb1265351edea69162e61f1623cf58e34e8e1a8ec58ca166e8203c86f84c00000000000000000000000000000000005d6cc367ff9c88fc8b6c35383f147b4f9e3eb21268a5a7405794441d449b3e1b44c8f66e30783e5f6c3567adf0d80171231e0fbbc2d98bfd1039a889acac471110d568b0a24ddf5eb3501adcbaac6fa0000000000000000000000000000000015bab57412cc5c7ee0147b0d2511b7836a14a82df06b4eb2b1baab102840ed04cad81da6e920ee000751e0727091c1460000000000000000000000000000000002f725e61e82980e6164cae7a2e30a36dd7245402f4933697607640d53fab2d5db57698be33a0c9b5dda14aa846db7c90000000000000000000000000000000007fdc589448887f6986efd817c63954d350511401333cb0df89214317dec0a82b06259ae9263f260fc7f21f98ad2630f000000000000000000000000000000001324e3bb46a1c69fc550fa8f2ae2d0ea74bc2d7159bed03c13a9d232233449e271ad1c3922dac5d84aae52606f77dcc0393c5c10d4bc4cd1567bca6960051f818e5c53704ce44dc4582767fef1092a870000000000000000000000000000000010adc26d73007e3b1cc58684fbdd7d197550658b4c66c702e9cd0f4e481f23a26c94c6798cdd9763110eefdca3d802050000000000000000000000000000000009138258ad1bdf6f9cdfb943fa32b42c4f1d834be536ed365d00126227c78b0df2776610fe5cf66a937cca3e0b088861000000000000000000000000000000001991db3a35bd2cd72377cd459502a84315422bed92890af906fefcc0acc4515fe7cacee1e4f360ba24efb23292482b8f000000000000000000000000000000000d10dfb682ae7a78b23b37b081efba32ff2011fcdae7b0f8a794a6ec33d71f5d6055f93e3b68a37086ab190d7d9bd7aed412195e347b680430c4528987859a1552ba8383cdc075c437ef19db6eff6e1a00000000000000000000000000000000182795b905320ee69281de833f37e040a3295e23be05ea7ae4563bd49d8b1fb02e95782c5c19645244633951cc29c5c900000000000000000000000000000000053368ee1412723b5c6465ee5ebddcfc00812e0e12e940f8485f44bce475c8897b324eaf7e66c0351ce9a6c92758c337000000000000000000000000000000000279f26c1e76e5f5d0fe1240c0956cd6025f6520ec303feb383b69525ebb6b2f199808a578a91368c3881a4044f37be50000000000000000000000000000000000ba4012c24dfe1038ec4b4565e1b321bbfc174cb197f0b0914bf1c126bdac9f423845f6742129670b7f3dfeaaa62df45b6701bc11c1ef3c9389710e4dd090e3db481c5400ecb91655c20694207a71f10000000000000000000000000000000016c27a3a950fc4857fc775441947f7ac02af9b3df6422874507b11f7b005c61d7d6a4a115d3759fcbd64633a8ad95611000000000000000000000000000000000e92954034df4f15450c32be31d4e146c4b0014a2b81e2afe755df79aa962afb05ca4d03577f15980fc6d8a34f2cc50200000000000000000000000000000000032db3e3c3617c16ceb1c8fae83e806744ca40cffb56bf9b79997cf48c55e5fea89db43b368cd922cd7ce30dd3984d82000000000000000000000000000000000d153fadc3854be49b2376ffcf4e5a46b9dfb4f54e580986767db13127e2d4d10e465f1ca932d79ca90f1971ddc0993dab45b07c059738ead9709bf36ab20b09fd3368f7aa12c6d9f3acf3f145c83fa5", - "Expected": "000000000000000000000000000000000e1968e131e25d3f911284c369eb63aaf264ee82f4d9bd978b7d02470feab68ae82aed8509ffba875798a292f012c9180000000000000000000000000000000011488365570d9bff018ce6aa15e3d7e078368f09873ed5e0b827d1c25ef369d6571899c8df38a3df3135d0db814c87a700000000000000000000000000000000161973f4949bd72b9f010f017398778e0d7f0c8f77e12a87db1851af516b4540e3f4df314381f295c4d167fd9ac091a6000000000000000000000000000000000ae16f0a4a597159195aa47862585839485615095e538b745c1081ca73f202115a438d279dfa45bd3aef8d4043ec67c6", - "Name": "matter_g2_multiexp_69", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000046eea8e5af344dc8600ba7e506e923f6c356f7ecb3b78bb3805c4561e808c1f570e122c4fc5a1fbe433b48ce0c15d510000000000000000000000000000000006f1ab405a46c825e104bc963d2b2f573f0d345bd2b08a952d8793c0297dce267a754b802ded4db478399cfa88e7e255000000000000000000000000000000000a5fc4a09019ac9649c07b623d2cbcd9f0cbb89d28c01b170b62544d8da8ba3f236ca3172ac754175a3db85d9b846cfd000000000000000000000000000000000f7580110db2549742f69bbc2850e4ab35a6e415bcd1b06220b9b009c1f4c99152289eedbcba2aa653f38f6b8460386b3ca13f8540eaf45ffdab5182883d32a1d35e7cd956092221cc40232efde6cd1e00000000000000000000000000000000026907ccf4d501265cfe67bc1c0b06840e9dd94a614c873d676b5416457d98a1dd744322887f1f1f86176b11a27d2830000000000000000000000000000000000cb08e541a5b32fdf51acb28ec64d3ea542c7bd75179fa3f74e9588156815bda9d027dcf5597d714aa001b2dd8a9553c00000000000000000000000000000000103ac1c03c16706d5936f216a6445577c96acd3a00a3d8a9c2c66e6ce568dd84a4c4db187a5fbde24e6ce60e037f53a90000000000000000000000000000000001da5cedccc02d0f8d1dd7e4d81c3ec47d432e81e941ea1452b112eaf40748a6634957c90f32fb0385dc5d642bf65acdb3c8b045ef559b76005875bce09a66b36f295070a73ec8dc66c86bca51fa5d4d000000000000000000000000000000000a0b8dd68918b58ca6b113e938f8a00b2595351777aaf32dfbf703ef3884f02c798f1b5bb78cfac32f196c1fe88aecaa00000000000000000000000000000000121a4104e374566f8d582f75a3c9b70f09628f116b7ab22679ee13a1691b0b0bdb0d737833fb606c746fafee5859f1ee0000000000000000000000000000000000b8bc89d718572ebdd6e3100769f2571cabdd79ef5ca9a4b9bbaa432b1a4dd752f9af9d2a9b1f1f32d76d4ec2d1636500000000000000000000000000000000129f1d760a12eb1a75fec1d2ca438189c933e87095b9fbf9a0371d64eb205d8f0932fde9ee2ab9f36f8b6e5d4b5dd31021953ea264f74bf64378a339461bff41c5193e17913c67be7e2a249c9737b825000000000000000000000000000000001499e5481ceeefcd2ff672df24e8987fb60872ed106c496178d71c68e9078409a80016e1f9727ed0d5922c93e821dcc80000000000000000000000000000000007bfb606c005c7da6b4ce2d974f9fdb2e3710c8f51f18257ced7663cc341ff81fe2e46308a2b62b13408965949a6f08800000000000000000000000000000000003fbd951e860e3a4724b667427fd9916ca4ba511a0dcac7b1125b14d8a4f4da82ddc0b0edab8ea50e911b0fcb5c200a000000000000000000000000000000000b43195a5f0263307e85408ae4eb046e06ddb1295a490ac4e0e654324de53d0dd023b8cc159d86b861dfcfdf7ebeee4a505655d72f1128ac0204539f0d823f076cb3a57a7e74e896b5019c9161d6486a000000000000000000000000000000000743bed2c17bea1ebddf750da504fe120f457cd3b1754c9413757cc48f7aef07eb4fa0572cb853cb72d68427e875456000000000000000000000000000000000102ddfe3dee27186a9484f74b3cb3aa366a79f0d2e36063af6e484f6a459e9168d7a4a6969bb720ec694a52db7ab34b40000000000000000000000000000000009bdf5b86aba4845adf9187ccf9c74b1fcabaa05764e41fcce4b38356b4a0ace8e7b16abfc7f7b96b785ad47fbf8e90f000000000000000000000000000000001934fa903b71d234c4341b2f49f8177334142e7c401553dad38e66a2c157fcdf7637165058955b7798a59051846dfb8cc4c861cde3f445e3a78d1498d98b2b947056cf578652e19be88da4a786af196f000000000000000000000000000000000ddde953f59b8591a83b0cdfce780ec23d052037c26d60cef36522d0f984f907315d7b41c8be9a9632f2b88e0ce950ce000000000000000000000000000000000b8d7bdd94a994901a434e6ea5d03ea45dcdb859e560833d8ea0bd9d20c7db9c16b2427eac27d8f1eb640b7d28a530fe0000000000000000000000000000000017b5b3a3097a74d9c1f1b23783723235b6148023b6b060234dd9e2f6fd05e38668167136c999d91249963e224f9bbcbd00000000000000000000000000000000133da0c217c31ca052800315aa8a3b934fc1f179e6247801904bcea1e28dec0b65632ab2690bcca3606bb1461aeb147b99762c5189cf154e24238e4b157caa1d8759002f69b289cfbf3f24f5dabf20bb0000000000000000000000000000000012778a6fe79b1f2b768432df036543cade95504bb7735ff547969faaa8db84e3588046a074838c9a551a4fb48f4a66140000000000000000000000000000000013288a3413d7e7edebd118463d5eea9f9ae2e10f51965480f9b5c244b05775d04079a1dc75ba0885aaa9e2e4bae1ac750000000000000000000000000000000005b766ad112b8d69f1a28079688942ea146f8f31616611909f539a57c58ec5e857da9fce415d683c1c6dcb5e74da9d17000000000000000000000000000000000907e5c3c83d3f12a68d6bf812e310f5a04f1417094301fab7d4f41007b9d01fc1bfbf739dceddef756417367ed5b1d0298b5f6b43074b8f0807086b03f5028709209310474c35c7ee232eec8579147c00000000000000000000000000000000090be6ce5ed09e45a6fd9ea3a9223fe43a835141c1c29d6b386e085846869f9c5798b80c3bddec8bc15171906dd417dc0000000000000000000000000000000019bdf67eb16f2708ca55fd20af8deca66e2ae270b2f2f9736fcf49dbdf7cee034cc956f6fb799f0e87c12f283a11448e00000000000000000000000000000000124a69c723cbd366d52919a72dfceb7e4cd9ca5b5cef1784bfad3f125b11d810328ea1c849602536af500261aa684f5b000000000000000000000000000000000bbf05318ffd81495efa4f4c271c8b1c669041a6446501788f49b8739a934f09de9d976fe7300b0ae861be567d35c992177bfb0218ecd8cdbc6dd9484e74e41be6971ec2911bacc8b53b9b4b8c70e5730000000000000000000000000000000010833a3e7329ad40c1a8cef296b015f6ac6542c612038ce00f13a99f673783cb7eeb14796485c168d21cc169065d051c000000000000000000000000000000000d3b1416b23453b893c92a6c7850cdc0e4a395459140391b1dce11055da10fb68f318c5561e1c12d991a28f3f544a5230000000000000000000000000000000014721dc58eada80f2d0574fb4e2c1c94c45fbd90c2d2fd666fd618a96f4736a5ecf34cab34fcbdcb19b6cf7b44098922000000000000000000000000000000001905d34029bf84617a956d1edae090853dc1b622f560c5289251447ab6bcea5700bdd80d6ffb2dc12fdf3b0267e74543cac52219796226385aebf9e85f5f179362d4149c33582a97b7d2aeb05a8e6a99000000000000000000000000000000000b4d380f4f4eb976e6121b933be8418c536f85994491b0b93695d50473615e41547ead326bab795d4d59524a61d607cb00000000000000000000000000000000104b7f4058c9b355d38908d715c311a53169b42d2434de0876f1c4ffce1c39603c4876b33fe3076528be15fe42849d3e0000000000000000000000000000000017e2fd647e7739366ebb606e8a326daa5c03cd2b726cc4cec7747cb3468419f1907126d7cba98bbbc659478ce3afee7700000000000000000000000000000000183be0a976dbb3b5385b544c194e111729c7a8d5aa98eba3fe1c0a5b69b5fe6e5d0164e96398cbc61eba5b86d91b3c94e03afb2efea85fcd035cb4ba09977b2e1c84a0d98edf88e9f8d2c4f116d0f50300000000000000000000000000000000023bc7eab817fcb9982cdac242cb6cc0ee1779bcefaecf144dbe57d5ae2b2ebfe9088f39f416a56de4b4dc04d4bbce7a000000000000000000000000000000001318e728c271746905788dd8f5ab22a3a10edce3fa063438e54ebadba22c29e461b2ed78a95a8f26a65b47022291b8df0000000000000000000000000000000010aab000b9c5de56623f18861b343ffa80da5ed4ae0d7767b7ed791bf3dd507fe7286447b6a07ea0fa12c19f2e4d8e8d000000000000000000000000000000000770e2909b5795a08d98dc66389655b1718e70b93c5bc6d805c3945cb5fc0092a5b390e6497b550988c28c58b6e016a3804dec43760dab29c161b8f4bddc52379a17f3168f684267cfbbc3505e32d5f1000000000000000000000000000000001259a4e36f5bce7d5f97184948d57fccd458cf7f2ae0c9e174f537bece01d744fef544447959cb73a678fe2c378ce3c900000000000000000000000000000000131aa575b2b94232e06879fa1f6f145a0bf5dd12456b698f731a72bc587e6def5054b3b2afb6dbbfc34fa5249dc673860000000000000000000000000000000011d64b923596c316b097a0752043efad8b61fbe068c58bec7a6766d9bc90ed965b3419dde3b96679426f72184adb8931000000000000000000000000000000001653af784cbad5a804e3f72716bb51e0c733014d587952c47395f953828566cbd7da811a3da1d48681998d569db00a7bed2d3daf616df3f0061f58c925e9dfbbf6e9cbfd4b0b3896a596919fb3d243db00000000000000000000000000000000077a9ab830f7683b7fb46676df09f72d773b65286c5f5ea86623306e5de51e63851c18d192c4c3b20af582bb7f017ff70000000000000000000000000000000016dc185f4158e249939541d35ae8230fd749988b9174c40c40b8c932aec625a7e94beaef9a07f492445d4675a01b7453000000000000000000000000000000000c107a895bfb45d33136db6251c76dc0461a235fa5d1ba7a5d216bfebe15691261b46c9816315c146becc328acb6b8c7000000000000000000000000000000001151cba240678efe61e3a36e169e314b3610e9d4df6650507f53ccf635d8f1277a80d86baa85a2d4c7e2af73934a7299e16797ed90581fd8c3cef1f30abaed10997f13461374ea649b29101959fd506400000000000000000000000000000000090a1ee6c611980e0421b72a122cb39257dc38d1e74ee41b809ad76e440fe307cf45e79afddd8d40b94382d48cdd4c450000000000000000000000000000000010f2e6e610eec7b7c2b95c1510af1af342ac19fd3b01dddf81b8961ead2cc57a8eca36c2f5747238eded5914e484c52e000000000000000000000000000000000acce0789cfff975b09d687ef79535c536f3b799157d3ff731915ea5b323ddd9f6f4750dc8e00a879d4e516bce8cb3e40000000000000000000000000000000008d8203dd13aee7363f6b10a9e1ae9b713bbc8b8fb2c56f05fa71e8d69ea571384d150e8fd01e855b1b0054fe7967a052f9f29432638c033ca84422b12ca80ac4ae85fa30ff56c913c5737aeb2c84d04000000000000000000000000000000000b332430c518d7dcd120b346440e5b6b48900b5c3656d84840823a96e5bf002816d583a989898cad9e09ba978ebc58a40000000000000000000000000000000004197b43877b833de7f69cc1a43ad8d6d3544cd10d42336d4b19a187f31337a37b10cbf48e72b77e4d8e1a1da68e5e4c0000000000000000000000000000000008887d5dd08f45034584f40a2a68254baf2104f9d6a4c2637ef79c5ff2503c246f7adc36559758a0c07533b66c3637d40000000000000000000000000000000009343819dec1d4569683de4596621c19785d5ed14ba13e57d94b1b1a108aa62cc8c55c58dfa18c06883ce50cc1364b95e6f1e5df7ff90c4a4fb9a071c0caf3a3997569538ab9837ed41d9d0a8d7305370000000000000000000000000000000003fc7f9a0804e7f1664f8cd3ca67b70ba128529a611c24214fd09674072a6b8d652ccd37bf5d4611424688213a41cb3100000000000000000000000000000000137a869cd7bde696035bd9353662e0d37d2aa0731ae55357df3bc43536b9210f360324cbb3670362cf9ef607b1919bca00000000000000000000000000000000045d9d39c04e257fcd912c54e57c86d2d4304e6a7cb95a83d2bff07964d0a5dd8b4e42bdb91a8b245e512395e6749f1f00000000000000000000000000000000120e5e4b04b8a744757812fc331e7c98b35624faa1cbabfc1470e4c0804248bfb0c53a484107a677a7d3f0d2b533e7530cf3283195707c30880e50ff5ef605b561c3c3c354fbe8108f93b36f212f9ef5", - "Expected": "0000000000000000000000000000000002bed414afe9c7a630441e7b163280be10e502cf877e94b6521d14baca0087c5dcdfa39ff4a51c8376d99855e1e6f36a000000000000000000000000000000000dcd54727a7729408e682c6e213005687ed51fa7935c522312793fc58cdb273eec9c61cd8b056a26619fc8dc006b066800000000000000000000000000000000137286f4086763e6ccd5ee82d3bda712b26814a17c6a71006a3e6dbdd919e469bd0e744bcdb2074679e78a1e7d56ee7d0000000000000000000000000000000012d75de1310199c0e556d61d6c0395b406afba0f13bfb37486c05d66b446809e8b1a024e8fd2c55f1b82cf2aed99a5e1", - "Name": "matter_g2_multiexp_70", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008b83142b22f6d6496cad0dea23c71355e7c5d98659580b5ee6e97eaccb9fbe523f7e3b925abbca3a38f67426f3fb35f00000000000000000000000000000000035f655a1b2d22ea21cf0081e78d7140bad08c4e66dd45230a113ff3b7a77e39f0f1a72991f85e2b00ff58b27d5cb54900000000000000000000000000000000105d04e38243ef1ad2f734a3c97e91506c5a7c5d95e9b8771b7fded8908f1be933a81a5769044b633d501c0df7b5d7fd000000000000000000000000000000000e670ae4af94d0df34a7f2d7cfbfcefa6eebcf2a6b2dc5b82068b023fe02ce8a279e1bb96d905ad4f2ffbd8214e47d702063b046a71c2674e35466657a85d8e02253b42517b033619e31a536659172120000000000000000000000000000000009051f1e636309016c5433cc7eb019c7dbb75b3a4a5b27f6927de08fdd9577e8eb9e12919157ed35bfd6607be7fc4de5000000000000000000000000000000001953b7a33695ede6d0792eba85567aa5052b8a58c1bdc94ee82b5001893c6b996d3e8f7af8b8effd6cf50656d8b85554000000000000000000000000000000000a2f769f00679b610bbe212c2f8045e7579a96dc6bff80899eb7715aabb1afe79421ad5000f2c7b85d4e0904e335ddfa000000000000000000000000000000000ec962a3d00fac14d05774adc49bbabaf46ae78325083c0020587fb85eb234387aaf6506f503fa988df8e9ecafb4a59992fa325cd07502c6576dfb93ee952fedb304022656597bf3bb03a2bbc471b32a0000000000000000000000000000000006823056a4da801cae430fb9e3a8663fc8f46bb6c180b743b7f9c7c7e3287f3feb1aad4be0e98409c74ff58004f8732e0000000000000000000000000000000015f7a3f692d55252fa5af5ec952f581b796d54089f13971fce2ef9062173664816dd9f37174294ed78681d8c8c5a9cd800000000000000000000000000000000154743c76f7de590a31cb96d46a0ec0fa88008b7d6684bd8f6fdaec70722afff7b6e88c1f0fb048714fb1072d30780e60000000000000000000000000000000006f3191946d0e7c1307a1a0d1ea9a26db195ec98ad88f9b8f08a03a3d48bbff1fa53ffc920f7db5ebd4c65911392bb834484e688799c3f0a3bbe00cec7322fba6245570685cd7df0d744473b72f03df8000000000000000000000000000000000355018079cd02dfcca15fbd2934a8e47c5ee89e679663488499ddd4abdaba7679fb1c9d2102317cf2798c47aff1ceec000000000000000000000000000000000c417d489a224fbba9999300eb65a23749194bf5302fdfaa33ff7daeb8d896e387e56600233038d5c5eb59f644a99b6a000000000000000000000000000000000f5a62e9d711293d4373bec1bc2637802938eb789c828939e6c42f10062ec171ac6110261165bd179206d649713f6fe3000000000000000000000000000000000b11f9fd0ef8dcac2e21ef09846ffe9f5a624ec246e31393b39082a47354fc9523dbd247f0059b6cc740d7a387b137f0fae2ef61a024e4d8c4ae277f6b1d834193df655ffb315da67afa4ee4ddcb7fbd000000000000000000000000000000000fbb5521cdb9c3a69d58e5c9cd7e4a50bf5469bda2603f5119f3209669eb3e374d700f851b0c7ac5ee3cc9de79e6a7ec00000000000000000000000000000000131ccc37581e64f6f9fdf675b9b63ceb67d9d5844bf512166f39b5bb09d8e031437c06b0ca01caae7ad6d8c9bbb9fd67000000000000000000000000000000000531cb0557fa18ef054dbff2e7e994f1af08aaea7557602a26fd6ff539ab3c0a73f1fe841177012dabed4a1223ffb5a7000000000000000000000000000000000a180e7a345d2b635be92888934608e8b6c17384c48c560f4cb9809ff995f8e70d83cd4cf0e96c458fc414e1275d2a993168a1007abd42bc398e317484149f2fa61174243fd1748deec6cc75e7c720a200000000000000000000000000000000125c83184f63dee35ffd2c0c7dad9010cd6a9735675099f24b465554ab3db727ee76b5b7ea603ead78795d33e37689a400000000000000000000000000000000141bdf7e270dcd356993327cdb5dabe38a5c5a9b53470d9a4aafc041c46fe8bc841089e337469bddab5d4f7fd3d6ccbd000000000000000000000000000000000f9613f6d05f38e3073f14d0c2557101a4864a7d6d0b5a2b931d0613f020adb99a1ab2037a39fea6e99fcfb47929827a00000000000000000000000000000000192d812e05a17d22c60b78c53fabcc55a0eef3656f8e84132faf16686ee18ab4d35767db9a384d42f392c40c7b0fe1c0f1525bba87baee35023d0976b4a2d87524ba74158f000e5501c6d06aed04adda000000000000000000000000000000000b6e1960e82586de19ffcf29a8c5f16cf2fcf5286bf42febef832767919abddc655a0d1bfa240cac8fdfaed5a1e8f389000000000000000000000000000000000fc1598454caf04414f1930f711d762f0d72f5cdc7a4053c92b916c742b00dd0f107aee111976c1b1218c4577deeb006000000000000000000000000000000000455d6e9e9bb848e0868c9d725edca1f50b279d0acef8c597927eda72763e3702f46b216919ac36b080b4865249fd961000000000000000000000000000000000174463cc7804796b4a6d8ff28d2e8cfd8361b2e38f368de30166cf3c20c474ea0a1e8d94749fc3e6468924a7d1369e62d3d7c014416f33724acaa46412348d350f93d334588d39c77dc0b8ffcb4cb1d00000000000000000000000000000000144e4b615ddb871bae85484c308423adceb5de387d0c7ffffdd2211b4ea28788eba9bfae96ffc46781e6d6343e2f501b000000000000000000000000000000000046e39cf43fd707ddc4b7ce9a8a22a2aa1e55aa63cae1eb23082f7b4b5dce49f32d2ff887b5108b40f98062c02d5613000000000000000000000000000000000b75b5460db2baca86528569b47209b5ac24930e2545cc6aa08c401a87ef2c4e233de537e5a857e533d0ba0981b24d7c000000000000000000000000000000000018f53b83072fe7daab226c831a89da63a0930ea86e301c97e639d0ee1609e298e2789d1a347bdb4afcd355fffd16d053bfbb1670b7045b6df689871d5d012dc93e8be65faa4a98a51db8501a4b7677000000000000000000000000000000000185b296e9c7209a9abcc3194b46be9a545666527ec9b0634a3e3be579447cb52330174c19e40e1667124552392a7a0c00000000000000000000000000000000158a053c788e5b914fcdcf1aebb4e21cc8bbfbcc20c4d692256b2ae48149f6644e1578f98d58b3e73d9768d0e7df643b000000000000000000000000000000001318ff4150bebd8fa612f4e84f89151d5c56c272969bc1f31a3c1fcbd8ded0e298914e98e1ca48248e9023cd12db0fd300000000000000000000000000000000076555254f382707fdb7419772a4978808a7409f59d1dbb8c9e648372e19c44573f5ce1888a2b570a83afc20e698ee44f944ee8d294d189226a6cff17456e2201d17d4dfcb78f58f8501870377a6e431000000000000000000000000000000000f4395e3f2e301ee3e18df3c23cdd142716c7fcfc23caed924f0561795948b0bfbed948a6f7c415ca615ee0ba4d5145c00000000000000000000000000000000176ad308c7fe8c3a1aa350fa82b8f8ec638f77bc703afe1042a6da22e5385cd8473ad789247f205214c9980532b12c7100000000000000000000000000000000092b0ec86c511992c66f320ad46c9d6d7c82df118a9ab2ce1f2c5611ff4e5cdc9193a39c3fc95f18ddf96e139688b00f000000000000000000000000000000000b4f671e334b7f22bd8d89d8c4eb8a52b04bbd4dd1259cc9caa1872093736680618930f3a469b3af4a00cb6e44b573f27de53613b7a31583ccb214726482b770029c0ed42f9528fa74da7d2d1dd915e100000000000000000000000000000000123b64561ebfe085238220eb1428b3a203acb01846d1e4428f3759db6cff4ed3c1b9d436706f28b77e3b92e2e39ecb41000000000000000000000000000000000ccdf1973693e4b43b6133563986f6c96e2b924895c813f8acdd0f39585e4ee95ef26c0d9d51d6ef88bb62305e51594d000000000000000000000000000000000f51693bd44b12188131ca84801bfee0ca853640c0a8d5b20123c97b369c98299ac04beeb27d75946cc6f45f8a07b5fd000000000000000000000000000000000804c6597810d2c75de94484873a67eae258fcc9577bafa778e13d4814ce099a5684b1cc94e0df5a59acc7b19328fb8bb0a9750cdfe0910c544668bc9b11ecdedf1b757ff69b61fcc838c502c2911bbc0000000000000000000000000000000009b02eea05c78a24adfb0187defb6810116e21894d8782605c1d590f8bdc10723bf71a1e5e5004b181504ac2deb142cb0000000000000000000000000000000015882389195128e20e50ec4f8d278e8b8791e362341be93c475064d640e1f8bb1c92a6c777d666f8644d471409bb9aa90000000000000000000000000000000000d89295f845f989e0fbc6e86e97400b08e39b2968fe6c9a141d1e92ec9c838a3d8e1ada5e44bb08189a5d514ebfc2f5000000000000000000000000000000000dea05d8e6ab50b8f8dd9632337948a60568724d5a03c7914e4a03e2af572dd8153effef1a7d5c2cb27765ef2c17bc5b4aadecb1111ff43894123648eea9e57685dcb7a25553233a374479c24f2f8899000000000000000000000000000000000bacd14447ede6af0e92e19b54c4f5b6ebfb94207efec3e9f385a4c84a7d670514ecbc28ab686b383e239ae7f9bd673d000000000000000000000000000000001698bc92d146049174b843dac8c5dadcee12d1d503b2d0e46ee68139dd43d3aa797fd5bd06e2b214cc9ae3647c98394a0000000000000000000000000000000018d20cf6c84446cadfa1a26192a04e16d2b2a053705a89abc51bfbfa35c2b03cd58021ad95a35364ae1e2da5d233208300000000000000000000000000000000113268e360006294fa0203ce58cbfd05d05fb625e1f9474c96c89c0ec1ea80fe834030592c2f1c182ef8a3d5c32caf71adde66cf749daf69a30f41ca00d251f7f1e93b0e7f916a1ba6b994d946b12ca0000000000000000000000000000000001727b6bfa9c601fe84a65c54f556887c4538cb5383a288156fec87420ae7f15da395886e1ac0e10b8fbbae8bf040f4ba0000000000000000000000000000000012127cdf02ada71f28ed036a417971b87fe443b8c65b7739795dc7067082cbc9f06f7bf10c709969281cd072490c06fb00000000000000000000000000000000134f1fa1d277d01e2811c118cf10e2de6324e2ba14efcf717a03c1a10dca0862ebde0f6328839da63d7d85f573e8501f000000000000000000000000000000000d20a036b715d18ac9e2dbe009dd0063a4b13b3ec6fd060a64c4ad2b98e05e069060179530410d154caa575d504c63b7b2f9b44c73a1a6dfba6462e1202166b63727f45dc3b8b3b73b5d06459a1beec20000000000000000000000000000000000bd5375e7f98d3972b93420a39fd6c31da86d0d9349ac3774bbef15c2240437cc0761b2f1245e805d2538cbca6f778600000000000000000000000000000000100232139641c8cd5bdaa75b77e1e1c8e33b3f9554e2ae00ec6315b82cc00a6a70d576d744e68938a299ee2b451558250000000000000000000000000000000004224691faacb007bde3e37db6c7486aa5d3b4259a24c8b7653238e7522604ef4ffc1eb3cecf719a1b7f52ff00c34399000000000000000000000000000000001156ceaccfe0396374c6dec5adb39f14b6f08a32b88ef7499756f5cc324a9f1553bf5dc106a97469f2c49be5d563e1100cdc89e668f7cbd53a2ef6597a48b93d7d9a78950d4f821f3935edf72649e0000000000000000000000000000000000010a549108e77f0ddeacdc795517ccdcb357f909264457cab22fac2b982d10064756d66d0e48af02a59f58eeb1e8ba14b000000000000000000000000000000000c68703ef1c1e93c78faebc5f7ccc69e39046fe8af92e12469e9fd6baee62a2e8cc06fbbb3def81ae5cc57f488fd9c9100000000000000000000000000000000064ffb6aeeed432629242c3843f8cbea5bf7fe78585763926c5c45dc3cb4d1c79b3715506d7cda18c531ef890b22a1f7000000000000000000000000000000000e0eeb69f28a552cc6563f5fdc9919423c4358a2b70ccd56b048c22111454f67107513cda2a5aa0efd2af25dc74a1c47e23b377ed80bc90a4645df09e825509eebf57f59d7a2aa1b9121ace80926ccf7", - "Expected": "000000000000000000000000000000000b1913c672760f98fc6d4e96ad1ef200f99add6f233b17291036e187ac6692ab0a29a4083dcf86a532dd06efb3d9b8c6000000000000000000000000000000000323b703abed59a9824f34d97851546a5e78441accea4e3a933b9270f92a9dd1aa056858ebd1739659018a0ca13b96e0000000000000000000000000000000001603cb3ed75c09ae5da6b94eea6017dac0c40b17d9aa8b65b78f2ba17de051bf3f21109d9afb214d260a09391f5526c10000000000000000000000000000000019f3bcdb8f16d9a2bd11e3f9491266780aa9110f447e19f12f7a2d62dc4f2c7b5fa18e13792007f5f361e20656c8ffdb", - "Name": "matter_g2_multiexp_71", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b7d06c16c77a57b5ed74d829ad6acd665e73d20f1d9285ebba67b60c0d1571e1b02cabe5dea44499ce6d40a83288aac0000000000000000000000000000000007e6ae768ee3d149c7130022f9883ed51e4fcf68c91327ac1fe85aec8083aa61a37e9afc25d3352e144aaf888f264ab20000000000000000000000000000000016f2423478e0388e8495a898c23d63a0929a2ee7cf848034e4c1adad3460c7070caf47631eb930678d3c85aaba044dae000000000000000000000000000000001587e63cdf50d6e0b6b3d7652ad0a0a2497e70259d73432831781641d3a76db4ac7cff1bef165fd8ba29200d7320e43475888762fd1de395fa80b6d8a751f280eca568de2947e953feac343fd6bd592d000000000000000000000000000000001181bebe3256dd6ed754b8a1d77ac07e9a341789b3f4a4988599c7c60a36f1e95d3e3cec52c54c0f0abe312ac358c28700000000000000000000000000000000189d224b2904bd45cd1e8fa72570a1e35c94680d03d30292892462664f9d7aca3cc45ecc0773e66a10248df28ba9a9a1000000000000000000000000000000000f654f4c8b02a891e14fccbd5a96228afaaf79ed8306c7c1267715bc934e5f2568ea06de2bcdc2a55ef708689d90108c000000000000000000000000000000000c0a413f16e1aab8b91a87e7027f067ffe7de65097da37d67f604a184c7e7a7af6fe59ced8c03fa32ab036862868b35018ce7941da132adec1eee8d81facdb5012a15ddfe0cd6751ebbf66ce6c495043000000000000000000000000000000000dc972d55b7e68f97191d988ae7be5f5301bce5c654b323d4c17bf6e070f7227c0789ee38af3ccc07b04f0793090c6130000000000000000000000000000000016288c405bb42b4e71d12fd0a798cfccc7d33aba0500f939f5fedbd0e071166169d3072befcc5549cc6963b6dacbef4100000000000000000000000000000000171ea4f6607d6efc875cd9cff203bc62eb83bdc05c07f702143c23ab2770f50f42738f748e6bb3bb5d6f51f40fea1d910000000000000000000000000000000000fb729cc9716bf2e9e30a598ee7c4281163b287422ab66b414da85b0b960102991c24cd023791e4241bda5b0f6ddd3424a0497c642dce3937d883ee25b0ea577c729366c7d67e2e5ff1ccde3b19a5dc0000000000000000000000000000000005720bcbc598c4eda697406dbb390c2aaf4bc22c794b4b664e9b85b7c2079b90f7678e69496a4a5cd3b46580b90a7a30000000000000000000000000000000001159788c3edf619cc5e6f77c4aeb4860764d46afac4cdce54cade63155040c631eed65c2fa11b9cdff14847950cddc2e000000000000000000000000000000000d61bf02587e2c61544ae8a98b4c742c26a3d6ca49c6ae1b19a9d69c7f8eca43cefd555c973145566f8332902217cec3000000000000000000000000000000000cc0da96623432a2c170f07a3aad2844c1c2aab9d1bb5d2183928c818e681c66cb3767be372be4ae65fa40bf5483258ce4e0ad0d478ccf5381470a3fc9b882639dde4a0147c7c82e50bb93431b07a1350000000000000000000000000000000016efffb5d4ecbd01567c1e6099c0f06644d4312c599579b4cb780fccc8a425f3d1263a5f0c957dda4508202a354162f600000000000000000000000000000000115686a37624ffa8272ec7dedb7a632ac568245918ed91be6c9116e0fde290c26b5291e5f57ba6a779750685b0f126ba000000000000000000000000000000001852662b92fb49b2f0359255db8a7a2d20bd37705b7994cef1eb8e318aed70fc37bb7af9fc0c32ab3efa8c0afad640570000000000000000000000000000000017a691c08724ccf0e668f2f4eeda692e9ac21385fea243dc62c37ca73421eaf51c3a60771da3fb3e3cb578de37d2d45d38573db9346a3c8de41af54048cc51a0edcb86f36372859d0d794f7560c8525b0000000000000000000000000000000006fe4276e8f2e23127853eb929ee4e0c6ec4a190d46ac222dceb995c2e1d8fc9f822806a877e6cf87cf579cb2862c25c00000000000000000000000000000000044dc671bcd516cf03ad98ccc55266688856a4e4e5a59d6a6bb93e9ca77c596b5ecd2db6f3cc6377a0086c53ceed5487000000000000000000000000000000000c3ca83688d20519423b2b5547afcccbfaaa088a90523272c7cdc9a9b0397340350f2a5ced2a8153d69c81cd79732bce00000000000000000000000000000000069916c468f22bad174522d7fb94b4b7d2a664743b4689daa5423f470014152387a29425642b50f9e50fb679ddafdafa02257ed12262d00e78bde574a9ebd2664484a446c03fe8cbb855bf92e56bc1630000000000000000000000000000000001fd452b8685b0806545e09783947551bc5f6446c9d15d079a8968a448a6fd6f8b7e91974b71a4b2c50954be299c4885000000000000000000000000000000000f28bdab0b0fd3e05d08ee2c51f1bc0d30380e3a7aa18d6e04b47018d6a8d2b35a8f06df3866ccb95ffbd9c5333ca94c00000000000000000000000000000000035f3aa1cff72df0bb10f1a6f8414aa2ad0289cd15f56d84061a7cc70562f1f12304c402c388e48dd3f34082aaf79eef00000000000000000000000000000000034730e3ad7a3373b97279a00dc7a053aadd088557e0da61b9aa132c5b402fd9aef73cc45dc1cb7f2076cb2ff27ae2fc76b9d21a3da0359a377c11a6d0a18bce7ea81d4128dc1e7618e6c35b9149d5c80000000000000000000000000000000009c91d800cb1d52501520b3625dd4c20173684bad8742c7ac4b35c0ce028556b6529de5cb7541e3c146b13f58ccae57800000000000000000000000000000000124259d345bf2f8c16215be4b6b7922f4e2d6b32f91c4b1c4f1d4974918fa9e6fcf10e46f0c0b55e2a7210d1a5336eed00000000000000000000000000000000072e6231244ed14aa0f5de06e2f953371995a567684b00e459113380c1434a8faaab8b28a0280336ae35bf1f90f1d4d10000000000000000000000000000000010289a63e0e5f1f35b7af22137e117a85df27874ba15df39b7c26801c169667a3afe9a14663d7ac0c2956f4eb70cf11fc9cd895d5d1ae0ae704e240c10d8ed4a01b319598d7885f7c3fffcd9b491f5fd000000000000000000000000000000000d0f22a9bcda47ffcd034618c15daebad8160f9ab6b3148f1cacb32e713df2ef19f706f14131f8ab1181b7ef7598e3e4000000000000000000000000000000001680314cd79fec583c8bc0842e1750b1318f94aa7700c6662aabd4c592ca61ad51a6876b686ac3fe3f508cb40192c31c000000000000000000000000000000000a172bd8e49637fd9eb611b590c68bda707931e403db35cde1c10bb74c389ed725aab54dcd7048285352c56c8bc5fd920000000000000000000000000000000012589683ff3f85ecb006c5c435ca7bfd9d5a6fd06eb625bcbcb18577cdef610d912e783f3986c965710269b1ff79ba972467604875028997efdf5139180a8d530a1e9f18c62ddac7753cc370bf25254b0000000000000000000000000000000009720c2b3a0658a4aba8e76e196a558bd155ff550b3e41bb5b43e7c5946bad803b1de64e342956a11627e7f24f69fef7000000000000000000000000000000000decf2262e8369d6a2b1ce07fdd257abe1c7610084ae2f347640c0cdb98c7cfa732dc609c18b7b6a51b47ebe4b07a586000000000000000000000000000000000e8a0158702ff6d6c3a7ed9fbc774bc329681130840d86ca3f26cf6642cb49e5f14ad95fff1c94151457b1d5a142bb5900000000000000000000000000000000035ae66137629e95539e09ee99b001d5b9a6ede79727d7deedcbeb5acf081cd05ad469ab06c265a5224fd5236db160b62f47637b64d28fb4facc31d5bed34b22e7b270431f54a689cd0fabd205e001ae000000000000000000000000000000000413d82d0b02ca706f0266051445c04f3ac594ad82e2f1fb4e8e0cf23a6c1087c29383238ad3677f170e99259e2fe93e00000000000000000000000000000000070af21f84895c0193f0b8174cb20b11f45c845a8d782b1f58182b149362e1368ba076ba702185fc54b5da94c3172f5500000000000000000000000000000000182e124ca29d66f9f6c370f6065f60928b6a8f445a74800d59209219add6cab0d1b79702c31d60e61cf56874a4eb6717000000000000000000000000000000000b94b733f76067a102cce9659292f31f3df2cf2770e3a83c1524536e29d0a84ea5c4883cb4e849830384dc7e157d8715474c3ac61d4fbece967fbd0599c9a92c3fe0e53899861f044308b0ea8df137880000000000000000000000000000000004b2feedd5badbbdff6fd0f33a4bee17b38cc8967fc72206246c349e1017ed0407fe08e0cd9208fa9e4e21eca4cfbc2a000000000000000000000000000000000df0d74d5cc17ea94457c0ee26ef24071700a0fd6bfc762e3ec69b8f1c096887f679e312f07cce8340686eb2716c9a96000000000000000000000000000000001878edbfff2efc5af64aa9a23589a52d63749b7ab2970f256874fe0cc15091c4511050b0a243d421dc6536f19b5977cb0000000000000000000000000000000015951da3b20494a266e4d014d0ec70fef4586c8656baf536a0ea9a48dfa041624e8154989a2fb106189217ca979ddbe8eaf9da65e0e1752a982601e9a070a7cc77d5007eb641fffbb78d2a1b02dcffec000000000000000000000000000000000657fdf40c829719db134acd6c2a9ff904681b1869f28512cbe2a64d93e5b62114a73bdc5260ad9a1f24a3ff191b7a3e0000000000000000000000000000000004e77bf63eb9c4741028dffd0591b4f525d533b455d35e51cd86c7884d63419a162b145752bde188d2a622251c087f870000000000000000000000000000000016cf02af01fa6750b4d862f0cdd5a87a79da7c3fbedb0fa356ef2e7419e25b3a2bc8cbfa97463d463d0ab349efaa3f2b000000000000000000000000000000000ea4468fe6a85d36ae990d0ba959ae050756805c4c769c829de475a2990ef1c46de20d5b466543978faae0f6045023e85158bfe535fbc342e31f32ab4723c0d9fe95a2c64cc4e59bd41d13a08ac811780000000000000000000000000000000018d42a2df8ca475be6bdc468a82c313599239b974ec3d27e8b8c534aa4d6b85d4ee9aceb15c38b3bade2bb1706a2c2cc000000000000000000000000000000000124d5dc60527faf48f5e9574308f8a328b410de1cb49f2cc6f76b8a1f2707f2d1a94bcbca0a97bc38f24545a8013b250000000000000000000000000000000018b690b3d1e3b22946a91ace004e1d8f92eb5beb284eb05b52ac5ba003d7bc387540d33d088a02711522e3aef7f74f4300000000000000000000000000000000103080d8bb379d961da06bc4c148cb5b056ae115b3a0e33f0a8c99a7fb7b7ceda35d3902e0733156d354dd0240e4bcabd66f5a8f37a7c6a32088897abfaf5a98bd4722c411bf4b52f0f5b5648e89df29000000000000000000000000000000000f4d068354cb5b51e5a86163978386533f8f9b6e388c5e75f7d9ff5e1ab6d1637717d251f2b723b7d683e26a274d610c00000000000000000000000000000000001ec5a0d408c55f247d62ffef172ef26e45c41029f1d04e36f0dbb4fe8af414b0f7fe7ec0cfda66a2855b58592486fc0000000000000000000000000000000000cb1b68045076f457746621cd415d743701bf3ecae8d52dd5582c3e0bfb38e6cf2651a5ebdf521afb1ec5b8066444210000000000000000000000000000000010f5672f813470378fa806abdff90edeb0239b00d85ff23a3fc6798779f46d6b43071d66f7742897a4e53ebf6c7dae719acdd24190589ae7823a42e8b59598eca12bf13b97aa9a0eec17f5f79a01e8df000000000000000000000000000000001422fbaf1bc2908be5900968af61ffa7b3af46e7250e4663ff321f42e2db057bcfb2106c433a9eef8fe20f7138b71d280000000000000000000000000000000002176e68cdb0ada2d7baea437bec8754ea293d14afb85a811f7a5d740d645a53e511b5605445b110174ceb5e6720e736000000000000000000000000000000000a69e992b6f4f7eaad2682cf9ac2e58faee9b3341e852543c2aafbff390ae067a641b2b5693319618fde413fdc64d6c10000000000000000000000000000000009440317af8f5c753b5de4648b06212256a39b7fb03678f1913b0a3d402a50e74e2da5d29c211cdf0b292c132759c36d0291be87a213b0a24c92df5ce42381ca378dc4b9aeb4cb9b6918263bea827bf8", - "Expected": "000000000000000000000000000000000fa31d16d9625200c13a415fd61b7552646c62fb8db307e92c1ac3d2acc92336765a1db42407ab0f774ccf01291b9ee800000000000000000000000000000000156a77678873dcbe4832b9fc7f516eabc1a10f4a6576cfb15765cdf999a771a6a6d41021897dd783e9beb2db722a6fa2000000000000000000000000000000000ee4599a6ca9642cb4cf38f5f2af23271cc8c5bc6e2cf6bad572b618bff9f8677837104b93ca8942843fd5db5c30dcdf00000000000000000000000000000000138986714a4053618e66a85835d105f4aa2ef38ad18e34b2ee7ae30a4282f7e543c80c94bd12c244506e7fcba25f4c1b", - "Name": "matter_g2_multiexp_72", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000083c515ef8509b12ab85ad7d0a816d986bcdefc14778efcb3bf7c2ab61991849f279ae6a9f5342880837c0d0f4a4eba700000000000000000000000000000000020cf5196b5d567fc429cb9ced7b55e4925e18c914caae216a736886a8d886c4bdf6d704bbd0ceebdc1975ef530c665a000000000000000000000000000000000f3d0a217c224434604d63cef559eed3864d2da62ac00d49fab8c2c6e22c688496adc30c8d591e21bc0be404b62083c20000000000000000000000000000000003d0bf7f25bab0bf2c768b44e10a6022650f7d5b7d568d502b9d0b28209ee69b1d952ed848572d3e966e8771c20becc4b14c6a38cc998df3583228080ea10f215a6e6a4b02ddb6d43e8f459d494a1ec1000000000000000000000000000000000cc4c4b7eb7e358d4133b65e635fc13b8a92229706a6dc5867171a60a99a8e343045a794c368f1133ae6cd2788c3a7db0000000000000000000000000000000019508aa39fda9c3efced287d2571db97045f8b7b0c7a9c9d51796aa8017fc0e5abb8fc994700dd5c9f755edb518e096600000000000000000000000000000000049f68b0ac142715cfb385161ee70e453f0e24e2e93f3f96c3d69447f3a28b180fe76989427b2e392c7ff939011e04ab0000000000000000000000000000000004903c0f8e0757dfd3f5edb4f54a0e292df15ff70757df7b0b04c99f590a3dd13c6ce7bbabf3e14daf9f3ec60e2379aafee8614394c8109338432ec72f2d9babba06f1e7b826b0f2558c3247c923b23500000000000000000000000000000000041128064ac768664f076116247e0f8a00adaaa824cd6fff33bf524d0c76e61203408ac13b294aa41f5c462cd42d3cec0000000000000000000000000000000005e150c27979ff1cbe307511816be900648957624caed1f08d88347061cd783179c615258fcf3619bc4bfa53d2513c610000000000000000000000000000000009d2b3d97d29386b93d7af014ea8f1cfe2c1db5a9aa0c17e8430b0fcde974a4e7b8b42ef041e9a7b1a8aecb97cefb52e000000000000000000000000000000000d86096ebd88b2cdaf5cda1e9ca6b7f12ed5def629354b0570eb084bc7139cf20bb8ebe4438f87937b8b554e2201344c28728d06cd90050e44a827b44f14ea35e83c9b58ce4c3a7a45aed6f31c94fb960000000000000000000000000000000018d677cd67e96b10b671d2ed9234d7708042ddfe6fb804d2e9371a80ad167004f9d6b92d26b3d3af34ab7caa0e03964e000000000000000000000000000000000e34a6c85187d328eb33c2d5b2ca96b5210d47a779ab810dcc380dcb7e6b3c334ac8fccd7354aa9108136e4f6dd4ea0a0000000000000000000000000000000000ab8f7274ee3fce1511c58661625c766ffb0ac68bdb835a948b09b7510bb573d49000000e3d3cea772bd71d79681e1800000000000000000000000000000000135ca42f2103905748a1c416d82170f7d24b49ff3f859d6cb7493cf89bbae0217529a9edc835be1f9890ce105877af630fda665c40d1da93b1f132070e0b7c8c2c0ea0e66993b5a3d7419a33d118d25f0000000000000000000000000000000007884edaacca499491580c8c7194c0d60ac6eba95f7a81f63742451c8ed21a223ca545d5cc1e648b9d2dd05016b4fea20000000000000000000000000000000014c78d5d1a93760096bf6da73bb41631e94d6a1b251ed0be7bda93e4c50568420bd4d49e4a46e5be4bb204cdb6b0ad5000000000000000000000000000000000128a860c23a183c5bdd18b4a1853cb53475f1a893420bdf3271cc4a65a827eba6b92e1f9e8ac0d10c73edec5160c640b000000000000000000000000000000000ac14b2170042ee6561c34f77fca40e1bd2d40d01798417dd954905135ed9b7772e5689e6d4e543d44a4563da8c3ca40c14f014117a74f21e0b698a257ae8e3d6091ba76bff7912abb6bd94d41886d0500000000000000000000000000000000144df2e76821c19167f60630f50c939b66867a82c2a5f807e943676c876aeaa2aef2126bef7fc431f0c7b39e648542fe0000000000000000000000000000000005e463627bb2d22c25520c27c05cdc75e1f2ee3b91e8088399ee42ad13ca217284596e5404b4370995f71fdbf1c1c7860000000000000000000000000000000012323010d6aba1bc6b1d6e7f7e8c7bbc0838564b279d5ae6279f7f7d3cb5d96273e27e7096e9a8540463ad16deb3780e0000000000000000000000000000000019102ac6bb33bd1c5a158a584ce32308b6ee5679dd6d2acdcfa4b9c54674fecad7489d1e39c05b1ded88e4ea93620724d81a1239ad2c945f1c560fd1674ac7e87d49aa41a1f4a5bfffeab1147c0ef7c6000000000000000000000000000000000faf210330693663c8a1d1fef78e211ed2542f7ffeddca3e19be3ba77ef211da1b8bb5abcfc96b692d74f8c7df40b0ce00000000000000000000000000000000134153a252fd8ec5d9aec08ba09a94c4416f95ff6f4ccce59bd400474c836af5bfd941f03384ca4bd5c56fbe81d96ea2000000000000000000000000000000000b4532ff1ceab2a3a177cb83a75c16a833a2ff28df447def351134ec4fcd608b2b75b1f8035ba7d40a737087f3e8c1c100000000000000000000000000000000127e3ed13384b69819b34ef8705fe9a66dd01b275f1f74c2c724420546b39c70cb7a8295a6c1ec4075ead4e3312b8b603a02689cfd2c353fc1b4d3913f5a43745fffe6a87a7c223ec3b25b321584a75c000000000000000000000000000000001351d0d5d531a63a5f56aaf1d7906b7ad2bfb4e9d823e2659bed4e05e7edc9179a7bbf13405ab5cf410b25c7d476c342000000000000000000000000000000000f0ec96128e058e8bfb6e0df1331887245dee87c4f9721fc7f1d20c20a2feea7a7078a4946803ac093477707598d59b70000000000000000000000000000000009399034e4aed13cbf197d8c4753285effa72fc53493ca316db11b39d5527b009aec6350d579f9dee22cd6d4cabd88ad000000000000000000000000000000000002f41ed0dcfa2437cad7b12a94501266d670ed6956196c438241aeb90474d17214eec5d5217090d28892d95f4e40055af95ab3fd062088ffbef6ed887fd39aa1d527fe7633b876187ae12e736fcf2f000000000000000000000000000000000ae208978a751f8921c6067ebab4190ac8d3608dbdf50222eec59460095b8ab2abadd97616c240edd0a9c53dd006e38c000000000000000000000000000000000905224b317a1e64d8af075b6db9de46ca4481458ad6bceaf726ba0f63e81e2a0322e79e70a5a82034abf00d47fccc300000000000000000000000000000000007173c3359f0c2e315d11d646a76e6f500c0922401e4bf9f4ccf2f0801a567fa653f287fdbfb878ba0d9ee12e25396ef000000000000000000000000000000000161d4cc71621e5df13d121c77105af195c2adff5fc6b656b0fc1dd6eb2518f474444d8bc526ae16387f23a4ab3f342f6541c6cf8217c2a95792900e8fc39581b177a57ca00162c57131ea4fb80a4c60000000000000000000000000000000000266af9991c393d3b55f9e0f22b0967d47dbc5b0c97947125e220c4bf9f4bc58d32ebc7bfb02b2e329c933ce41d0d8c00000000000000000000000000000000004cf5748aae8dbc1e4778dc85da575de2b6d9d346f5dc5ccbfd82513166384111f5e5f2f1c2f7ae367a22146d1fac027000000000000000000000000000000000095dbe68521b2cf51283a8cfea1f20eb7ae37e6e945c5f879ba4834d20918b74981f9e0eff4543a79ff4eb36d84a9c60000000000000000000000000000000007953cad14379ffd4309cef1ed6a2dbb73a93db0bd3a256753402e525bb62b10aaf22b662bb2c704865690af995e7d284b7c3f3c4ed10bced85f36fd6dac2646c65d3c810e6d2d116c38aa5e10b29c2d0000000000000000000000000000000010e99f318111baeb1b4611847fdaea7cbd5e3ae532af667ad2498fb2e97b1eee0297e2811c7ae854b882f616da7733fd000000000000000000000000000000000e56cea75b4c4e4c669a492a6723fd60e351a66dc5c34c46469dc36cb04d2c23cfd4aeaa23d0e9e83d5b78a1b77696ed0000000000000000000000000000000018f838d6a582a52a508cbd6bbbb9cf515e091deb7a640e141dea4018af6593c001dc43a8fe4819a7877d9ecf53d5752000000000000000000000000000000000119aaa2ebcdb6379f7ae972cb709990a3e8254f1025cef308281bf7057295e3099d1f3127f76bd2f9ce0a03ae0de8e8d7e33f394e96d17efa30d34f57eecc45d7b4ca150a31b8d0484578151d6e65c2b0000000000000000000000000000000008f837c478e874b857f1c939a26a02e13061d50728c10939ffcf5e862cb177993e204590699a28cabc7593056617d433000000000000000000000000000000000432d9e66dc78bb58ab98771e7e8b5fe51835f286b488e2df6c1991fd36c3c537f2ce30abf24f9d4fb13941189972e39000000000000000000000000000000000b202de3708984f44f7d05ccd9e574a2a93a285d5ca262017346580be273c58f13165437dc90d1d4103d3b9eaac536ce000000000000000000000000000000001873e1251d9ae9448de8e7ccb7ca59a21bcc0d07a2819d140c06ec33cbba559ba90647494a7ecdec8b609b58cf7995cbfde92a31e571ec03e509ac8a70ed5788869854eef0bf578efe6c5e6468315553000000000000000000000000000000000084e07b6576c73aaf43c0ef9c5666dc988ed93d1a106b71e4882fc0cfb5e710b91e5d5eff57327f5678f662f4a451d50000000000000000000000000000000008a29751f1653236a48adb5fbc59059c7137d36139574c6af97314bfbcc22f77a4c5162092762a26b5da7887b94f2da6000000000000000000000000000000000a4fd84c4d58cb9e18aeee180fb05f07c3e1d7ed8d09940182e9b4738744fa6faf600b6f720441e0ad6391a4d502ac040000000000000000000000000000000018b356be2aebca82c54988ab2a2ec58751ce7a815f3dd58a2218a638753d4734d38b74ca0e00bbc8681768f5d1a02b646f7de01ad0f7b4dcaee1123bb80a71d3bc1e63ca577a12b14ae2a11d8c0fde46000000000000000000000000000000000de0f22cf05620a5d4bdcf50ae179f23a9c089fd6eaeb14eca937d9e2480f1782a1c67df76e06191a9b87514daa8bbce000000000000000000000000000000001981cd1f260e7d96e55533b8e29867f37af507b4a58abd69e0ad6af2a55228ab1c82fc2de52deb7b7b7deae2fe621e10000000000000000000000000000000000d22a7a567ec8826391ee711768e612c403e3c16e20947ca5861185c24728b6c7e7756debb333e7acb53d86032d5748900000000000000000000000000000000016fad52e1e86b9e092955cefdf93a10f30db896fb519fd2ca12571d8dc8aa352cf4f8092e0e973d0b0c66df78433251e2c69d21d40813ee40a718f0ead36b51f3a50e9e4e4b2de8acd33add62bfc1d20000000000000000000000000000000000484bb2452158bca93dfeeedb40745bc5d9a9ad49afa20e6c29fc9ed1a8fde33ce508cc252ddd05fc486f8ef78738ac0000000000000000000000000000000003c2d6ff6f292b0f0e505fdfdd2940e72bf8c2837da4ec9c74fb593fe3318a9b9a8592524bb5d40f6c38ad871ab7b6150000000000000000000000000000000015f888ae2722713e1b5b02803a5b48d53116c1a4bb1191c9da77ded8c6ab49f1620b0f7c7867957d84503cfd3dca1be7000000000000000000000000000000000fd96baa382cceadc252eaf000d47d8c1e2085e9f274dd9dbb571bf85bba612836e1da2453fd914135842e2750796b54762d89025196aec4f87da2fcc5a9188b4dc7b1c014dd1d705223bf9fe1e7a7d1000000000000000000000000000000001820de289f62058920ac3d4bc60da023ac29c431ee429a10066f305d2b1a333ffaa906404af977cfd3212b53e66726b500000000000000000000000000000000094e448db84421e25cd03be3867125cedc7f77f286f404524757f3c1a9cfa28ab6771293da490a4d75852f515dfe1a6700000000000000000000000000000000097dec124970bc63d8f62f9133157d412f5ad3fd5eebb444568cf0fe2825d6ef6577ad302842f35570c9977638c6a827000000000000000000000000000000000490bdaabf4db27dce906cfacf3160c0fe25959df4af89301cbe6eeb29f72e4c55bb467841ba7d0750a59a32fc8b03d0ffb9f3e1d43aece3af1f59319a8228cd81e668b1e250d03350958dcac9e23843", - "Expected": "00000000000000000000000000000000193358b283147ed5848559d4d1533734822b0248dd17b2effa80920a853b70e7fb683b08aad6ad4dbb91f964ad1b3bb6000000000000000000000000000000000649be60ba72734db4cc307a2fd8be57857f60660d0c496c0dad73794296552e17cb2eabb3537ce677edaac1c6997341000000000000000000000000000000000f91ce27345e86003c99d133eca50710c0722cb35af2ce442ebd74b46d659e0118be9bebf32111c258e4cb4ab795a2cf000000000000000000000000000000000d76ad65233522b1e079fcfef4dfa80f163682d7984d5062680a5dd4cbccd5044de4705013c6bce2140f7950032f90ec", - "Name": "matter_g2_multiexp_73", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013fe4afb94d08ae311b7442de7291a11e733d8e555f2da6f72bf99da780a8f8d357cbf3d8959f6aeaca7bf3f5b5bd10500000000000000000000000000000000025af713b18cbdb5a960371c2dd0317f4bfd0182f4bfd6b88d588b56fadc1a0398412e7e0a786c326aca8779ae384243000000000000000000000000000000000581c277053c15df8eec05c34267f62e63faeefa2d124c2b4b84d2a739ce5484641ce955fbecb901d1e8ca816690189b0000000000000000000000000000000005355dd304b9b60498a3fb1f08e1ba0c98db327365ca9a0365a7f1e5cb56aec43b7fd2b4aa104eac7b1c30b6f53cd422be285a119dc8cb32b1a0c5380af736114a32e9d1ca870abdf278dfa84444f70e0000000000000000000000000000000016b5b3a6fdeffe5b9a0244a333ada4444a2e03771f94433832a4617be696e467b4e88ed80b174809dde4242bbb51248b0000000000000000000000000000000003dee846c5b84f89734016e547c63c02e4be07dbbecc86f811e2d8d3245f91205bfc055882565371db532240da1a845900000000000000000000000000000000194d53bbfa962def4da2a9bc7129fb6242a3922fe26cc4e603528ff31393a31d03dfc3463704250ea2ffa973ad175153000000000000000000000000000000000333768faee332d7468119b9e0469bbc7bc98a482562ff2fd9aeb6d9c67daac9c3da1db41c9e12224a2eff2feee51778bc0535bd504d7b9658e459c2e79b86bf4e718baa82b8d6e624fba0eb141c7260000000000000000000000000000000001910ded86d79f9b043bb79cc4049e0652c13d0fb8db2f070d695124d7a42cc3a2238282fc8a424fcd8d9ecdab4bb6fad000000000000000000000000000000000dc8d6caf97416928d2d58466219f054c6f28f49b2bc04d8a80cd46a308bc95aaca3a8df1914ab0c7da341862fdf47400000000000000000000000000000000004380ca7b1f7ef96295589f78a1683a51bce4b2afe50bd6076ccf5d07d35e6cb2ec7f74fa35097b2c0b9fff3f4797c1100000000000000000000000000000000054f492d7442b1c0d1293277d95efe822faa7d8881b9afde20db58d6267e049b90d0c8828a6c12540f4ba1e7c9ace6d84f3fa09243c01748954d84f4deeb460f3ef78f9c34296c6a092952bc463d7284000000000000000000000000000000000bba4761eda87a304a80180c2447a1d5a52f743015ea7c728e70d6a5defe3139c80696f842da3f06586be8d506ca4bc90000000000000000000000000000000019ea930d5733f4a1ace9fa0139d412d65b2886b659770e388894592de0694d38876fcd86d14580f9b92518d5496fd44c0000000000000000000000000000000002bf5d9a36d641d1259c1b30397aeb071b88844c4cf17e3de0984129d7b4d67865157ee2f682e7cf9d968fc07ce43618000000000000000000000000000000000f9a4f29868654abafc7ba935aa22d3d010023ef5112683a037a6c69b9e89374b256b8e1329eb5ad306d9f2063c22c335d84733ccc41f71a11d61852fa336df566109c5538c2c5f5cf2af961e93797fd00000000000000000000000000000000004f194f21373f09f8cb4984169890ad3855e814a4768c84e9fc97dfc181c60114aae534a27d3eb225b2125131c754ee000000000000000000000000000000000e6f88880e9645e35806d193f5d16799d63e2f9edd8ae28df54d19875c61857b0a34819a70ba3e9c31f00b5826b0cdc200000000000000000000000000000000193293c6cfae9ae4b24519fb23469e2f8dc4eda8524ee0b00c7141587b07c8a26a29841d41cafbd24bfbea2034a9c18e0000000000000000000000000000000017433efadfe9873dea9a68177af3d5dec4a13dcf4a710422d52020d4d145e2523ec0b48acc533a1ac7068c08ae6aa28bfeeb95c32362014caedf2a9e066a775e2db0d1322edc86759faa99bd70c05b580000000000000000000000000000000011dc003f7542f6822cb872117fa658638dee2a15429aaa9dd576a7e895bc0a2160bc120558a32aab9e646354233a1afd000000000000000000000000000000000fe9ed8ba572ef7d1176176a31fa92a5ff3dc38b0183ea1e22618e3b3214ee78c53074d4c60b5056901c6f046f8210070000000000000000000000000000000006ef1c20c3bd88bd6787598dcfca52da4e5e0e7c7643af983c709b916e71fd15475da30d763ddba0899b182cbc070ca20000000000000000000000000000000001a38a2e54a44ade572ecde076038f5244f266cd99532024a377829a64c20fb2cfe1633367c74b5990febb08e776bc34edee2ea28b93b2daf4ff927991769a9c69ba16490b5676074e64f5e91fa994a60000000000000000000000000000000011ce7b2cba037e5f3ff19b36371d34e287eec807178dad4118c6d43aba68623e182aedbf911a2ae5cf3d0e690ec3ba790000000000000000000000000000000017a617453f391e6e2437d56ee831ba895084f60d1a5f342e19a242b9661c703219d90a157e1b55f005f5059c15c179dd000000000000000000000000000000000746ab134c7f4bc19583a4ea4991c7cec3f651a60582b40c17b2d18cf6e252d93d2f3c2a1a3399be70512ec9eab251de000000000000000000000000000000000698daf214f2de44ebfaa36379862bd9ffb40987dfc8e632f14738c93c8e5c3fc7be9fa9100fb5f7440311cab34fe1897a07e50c1fbf1b388e9264c762798c31fe76761508d070f06adc63130df07641000000000000000000000000000000000e4ac65ce62180ac602ad68098ee31cb747886e95a183e4f819d54af99850d70496e6952076084dc7bc2d3f7a273383100000000000000000000000000000000182c718fc9e5cc961426258e82594a5cafc36270af0eb50646d161fcc192c30d40d06647e14a282421638b31f378de940000000000000000000000000000000002bf448ebd27cb6270e1b87087796ca6534ff51ba0962f3290ee1d06dc18ed39fb736ec95632b483f44d3a9d0e45d1d50000000000000000000000000000000018b956acc1300e60b22bb936b2b52e2ae82e256f15f1415263157965179855137715c321d3765c5227dacb63ba2d6225f0056903b4508cffb6334bb5f645cb553a8cc61ea6765283f933686f172f8360000000000000000000000000000000000f5372651ffb40bf853f6f8396a7c7483c401b89b67e098ea888fde8d19e7552a006a127af1f3311203434126ffad85800000000000000000000000000000000050d7e89b21c7484cc5831885422fe7aa8e898df85cf7a3a275370623eb9660611610cdb829d3935f0d0955e0ac97506000000000000000000000000000000000f83a3f79f1dd110bdb8521e18a64490d567210801d77fa3c0c6e5cbc7285840da325cab7ab08494c8d516511eb189dd000000000000000000000000000000000f72904131be66380c5a18af4857ada7c15e88572197e100de1cfcc9fdb4306e446f2f330fefcccb41b676f24e3e0bf88031f363c8b0062b34d48f4c2e5bdba884005e52f77ac04c2f29dc7ef10fac0c0000000000000000000000000000000009ba6bbf102d390638ceb9259205a1856def2b3a4b5209eb3e4e54074347f71b6c06b70764fe85c8dfc9074067b8d00d000000000000000000000000000000000339c30631229eabc1230240942bdbcfa6e18f23bfbf88b7b8a8fa92f18e35d2f7336f0b819e875ac643b43e6d931e68000000000000000000000000000000000600cfeda6033ff51c3bf9182d22abbfbeb6db46c0fbe15ba82e72fee483744ba5a57ab2eab6f35927b4ba6d2b150063000000000000000000000000000000001530bba4db8a60bb6b7a05f72dbcd23044011d75221d114b839aaa9535400874472f94c849597174322291b5cfec4974cb146e27a9d36dc698e1982afc945af9500fc5aeba719d06d0c4e4eb245034c6000000000000000000000000000000000c636ac98557e22897fd101dc6c54d87060f460b4cf2c5a88ea14641e2a8a9395492fc5a946eebbba36dbe38f6f5c0c60000000000000000000000000000000007fe3a557aa93f2e9aef4ffc55d39a9172475e6595fd57409df3a7fe3d11558c4d3dea3396ee62f61190add83b85813d0000000000000000000000000000000015b04e0daf4a10541623e7523ac5fbe57dfff9ac17afaf4293c493c1982f3395980ec63046cb1d424c6dec91899202c10000000000000000000000000000000019617b191e9e493751b0a02511a18757330bde56722a72a29a399ace983db7114f84795e2b70bc9d670cc0095220454ed983f98fe5112a55c23591bf4e259d072f893944741d9941a00f907749e3c9990000000000000000000000000000000017472b8c1cb3ec528400649fe7c39e3908b16ed69b42d967e4d225b694544e8bc7ce5bec87019db5539f1de39dc6807a0000000000000000000000000000000012b1c4884c37037a94f84c15061df5ca6c05c5a35ad9b37e3ab8e8297c9000e715fd2bdc3f2b485e86c415bf656392a10000000000000000000000000000000002c21af2933029f04b344be76e18ce499def4a0671a97dd9b6a108d0fb23852fcdc56f882be0319978952ef04a207a6a0000000000000000000000000000000015eb31e80fb162d5fa392fada8d43648ef54d4f9ebcb0e9652dd501f55a8875a16a148d42e283ea8bb2c5a38bfcc8843a62f99ac46f986f2f29f0ad3da0310f061e691955c711850a2816ad7464614a70000000000000000000000000000000015e68e011ed063a9fd9cc8a806d8e3561e4f449526ccb6e5ce983ebc4fc49d61d26dad7db64f56ad5ab0b54fbdb76e61000000000000000000000000000000001617d7387fedcdd772a34b267a44315212d21b798c0fe1e7a9ed3caafb678910d9c9c3bd1fff4a3c8e339d0c90a865b8000000000000000000000000000000000e2b3c9b9cc10f41c4c0129d34c62d526aea47c77ded91a5ca3afa0da1801bba81def3ca66a978ebb2d1f3227ea82a9700000000000000000000000000000000096b6caf7b6f29e91bea370f91c2576c188b08b95f9df6c7df995fc9879c11cdbe2af86809468d472fcac8a89716d1d87ee01b0c9c6a6ca1fdac35d89c803bee3595f03d9d200affc5292d8a7c6720b80000000000000000000000000000000016daa86ec04f57c72395d96b6ea5d6ba7cf2d9d4a50eb90f7121545f17c1ee16216f4086481d91e59fc5ed8542baeb7e0000000000000000000000000000000017a783d60be67206241e0bcad20e371d86d47d88ba1293b73f32999b0a1646967e5d031a5b28517f035168d7c7d7927800000000000000000000000000000000058f24fbe4e9befd8abe364c961f0ca4d9083260234a939bf6103a3e8f10a8381a9e3d74af7c13f159e5c7dcf456df00000000000000000000000000000000000485c9448fe3a069eb024ec43aaf563a98da09c02c294da2a94a98a95430e25b062e8ff886fb5fca240fba1abf7cee60297fc700698c56877be6764f48a836d210bb33e99b5735da9837882269af9b45000000000000000000000000000000001230577527a0fde2e8e66b8c4d17594bdab8be1339866819c8890c600b35889d1e3a749fe15fd8182001e30e6420ca6d000000000000000000000000000000000ce03cccfa87229fa8d560884d8c7963276d79ae9873a23d550b4555cc4bda35a242dd2e70cc730b70cdf898609b3d8400000000000000000000000000000000174aab1f142fbb7a45bcdffd64c2d38b99c8919baf9651aa430bcd39613d7565196c18f0f4ee6fe05f5c40ddbcd4a67a0000000000000000000000000000000011dd23f59ca2a033ee5dfa50afb0c7ddeaec6d4f50e1866cca3f061fa03594216f005bc65b2c97ed1109c305e16222671b7ac02db15cebb8af459290c35eb5a86cf98b86d8336764c6bdda6698b49b640000000000000000000000000000000014e1cdf4f10b11f47c15d0b6b7dfccb6081d05d116c8149989cce4f1c53dfcd2d0b7443677b03d037710eba813f6f597000000000000000000000000000000000c8415c7d5508010e0db1878ca663d359525b290b2f02c61436e945145a7a4e1b3ff4e27ea1b2c8d3adbe737d8291b14000000000000000000000000000000000e424ece68003cbfaf65a54dba51e7b0942cc53b2fa9794b4deb6aef1dc1ba1719cba285f9a1a59e71a881eebffe2eb9000000000000000000000000000000001404f9a3146b7201b09c5fd678fdbf2111c48130e82cc95012e5aec1df7e64a3b3c727afee4f603e620925686e126c0f5d1a3f78a2c2ab7b85cee68ee670f50a176e988a341303afb7722917f442fab6", - "Expected": "000000000000000000000000000000000e9f6bedba1f6e2a3ff33e0e4b18fbf8e77558bf42e89023df6338b03a648c591486c63c2ecc8ecbbce23b3ff9a7ae6e0000000000000000000000000000000013d2526d83b4495b5af645d5a1af7bd40bd0ebff125e0fa14f10d1c08511dc29643dcfbd25ca0bee5705a56b26c558730000000000000000000000000000000003fa442ab532094d47f1a9111c87deacb15d80ca6e76bfb5f9b9a209bfe196643351d778b0c6d6b274b4799f733abacf000000000000000000000000000000001278d51523d5d9aefc0d3783e745da54f74a88620f2161090a398defdebf82d13d5b5a21a5cd466352ab8685b034fa89", - "Name": "matter_g2_multiexp_74", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a497e74635fde8caaa5c9dfe666b1b40732e58b93a72d39c8a60c1f4b262e1f18f62229a30fb8257bf895352ac4d249000000000000000000000000000000000c1b2fcbd7f78d85c73ae55f67110b575750bec353e55761de0ff09a9f8a2d916c336655d8f6a78dfbae13fded5a9c36000000000000000000000000000000000173893333d998dd32cc3e82fd7ad8ce77003192ad2bfa1b1d2b43f9466898313276b922f9fbd8e83e86b67acfd9ad780000000000000000000000000000000004ed01b702bbafc73dc1e6846bc944be297ff08d1dfef397603294c7fe11668cd0670d386a8fa0f0f02c52d47f54a11b34aaf86eb77ce03f1d8eacab84d5ff98a565fd33a9a2c40f2a19d7c041a7e2a6000000000000000000000000000000000b5ec74a2150dcf5ebe09f39234c4dfec623318889d92b0bc1f197a69650bc48d28a1112306be763176b691c6915dc7c00000000000000000000000000000000028db19af73ffdd0111dabf9c7d6879cc7389320a249f108b41be8b1d4c259d5889dbcbb48b30a288e26cd9926682d1900000000000000000000000000000000172fe526c62f9cae49e6d3284170e6339d5af256441590cae9507c61f987eb495d340500cb761896163cb8ec631434690000000000000000000000000000000013bbfcf9cd3167b47b48af5f5ed7e6d45a5fa38192756c9e140eb89a85c75602814f767c57108cfa2f726e71f31548f808ab2065f1d2278caece0939cbbab4bcbe3eacdc80cfae6e4500a5195883de0000000000000000000000000000000000052d7a0f93142b36489cfa21d76c0eb96904a3ddd946a53b8a6730036d88d30336fd8aae3ab29ebf62a48c6e849ca66200000000000000000000000000000000198350abe8cc91bd675f26516d771422c128d5dc0af844c6c1af07bf04a1d3ad9654cbddf2de5b7828d1446c45e7828b00000000000000000000000000000000198f35692d5face8dda4b464ff48d650145242852fe189748783b1a2e48806294368ae0a99481bfe739fb4962f3b86a4000000000000000000000000000000000e3cf2e018a7e0acfee25bc3a82cb282cb377bbd72ce3044dd20e109d948f68720c27aea3d4663ee45b2de6f178a00ac58c69b55bac97a633f3ed7816e77e2a26cccc029f7e7429c86145ca4645eb41500000000000000000000000000000000150e6b03a3052d043da6514bf4ee09baf1a35b2a909473db33ea0bd4c6af7d7aee9a8366c1d08d2adc5998635eb0dfb0000000000000000000000000000000001370c2976b0d36fcb955e797087e6ccffc851d2450cd63833d6cbf52e1fccbbbbf9dc695ee45c7df01c2828051bcd79700000000000000000000000000000000048b5fad2fe0af7ccdf675328d8ff5e63b564d8436d04c55b23b6ab7d2aedbd25d614d1780963fcd03d569bed2085bae00000000000000000000000000000000141f94b4e7ba542707d0c3cb69f8dd79e499602952be2374cead840dc669c5ac57089c5fd60c44291703b872098fa2daae7faf23e841bd53683521cb3cf215577fa51f0f751714b6aafe5c740f66208c000000000000000000000000000000000eec51e0ddb8cf9914304e7766a7418e2854ca71367c1d2b3875c12b7dc5c7cc2fbc136037bb7ff72458027104ed3f270000000000000000000000000000000009fe5e8d1918f9b5865a8b97c2c2cfc8bd750a0ccbe2942070827a09d8e41ca795a86b2262b10462795f833c73e788ec000000000000000000000000000000000b95c9146f3f560ad880ca905b5f297e48905680b4613e91f393f72ddb042f6a6201628fb5f75fc23f2298cde66a6df5000000000000000000000000000000000a29a8fba7644ac96d77ee73a93dae23b03d81a57f6cd8cb4594b23571cc1f658f163081ae50d72e09c6513d1cd2c8bf72022cdd6d942158bad47a53a9b0c3be910a41036874975724a5cdd22c012871000000000000000000000000000000001807dd8d2bb40a642fef693739b1df12fc787db0f031306f31970d0f59f0c97c0894afc34b9a9913726a20dcb7d5191200000000000000000000000000000000096fe8bb5e911c1ed9985ac08d864c7020367f4259a0d074973a26cc421a44e8034a7007f6d1639285cf8acb8b2d64a60000000000000000000000000000000014026d43eceb26b9ab5bdd4139d4f94349b273e43f27737f9ad26d23454cdb1d35ea793d21f057359d28328a82d5290b0000000000000000000000000000000003dda2a84bd1f92524a8ede9f5e81f0f64b41b24510f4e0b8146496a776d5b509968f188c12c2d66cf755e5000cddb3b800ae0b956e38bc34cce55bb7e88f1370a30fc8ed0e3f1126c68c30792a2cabc00000000000000000000000000000000011246ad07713d1916c662679ab757c053e33def437d7a976533f0ce80ff6ffc259489c26524ea96898c3747c4127539000000000000000000000000000000000acf66265811a57e47a4c98b40b12a37c6f439550b18215fcf856c167b7218397d7d559f852fb45077945a5074f460be0000000000000000000000000000000009badf2799f1c43a2e3859123aca91e894f86d6298a06a9127249100ba270f2bdc79cf511691bf2d7faa45ffa17490eb00000000000000000000000000000000069438b1d53efcc4277ea7b41cbd28a19f80b5380136f62121e766bd2845e13d5cb40b2f15d508414876ddde491a3830a57c3322133d6ffac661c888995e7cb067ca1309f3e9178a266f1a410a79c01300000000000000000000000000000000112c4cc34da9e83207b5ea8a9251ac5f004546596f2294b3fd51b77ad8d8e98239d53ec4f527c7280801233175500b1b0000000000000000000000000000000011dd8627748c9a2b08524f88e560cd3944bfd1fa17e1d6e2e9cd025b04f2e3ed35125197136afa2848d24fb5fd19508900000000000000000000000000000000093219f9ffbfdaa60c5965b45a5d5bd923eb5d3971542ac147de3f591a5fbe31b30704a0061a524e2ddd05a45dfcb6a10000000000000000000000000000000006407dffb5580790e250a72dfe68a488431f61f45ec9df279217b8800f0ac1ab585d84e486487d5688735fe5aae75bacebe67f3d067b0d011abb31588d1b2fa9fdf8a56bc46b1a0196e926d4ec73040500000000000000000000000000000000107ede23f8e4f273ac2647fc251008905966dde32339c023f1da3c4d35d483a55b54f4157a303e68e1dd7fa3f3b14c8d000000000000000000000000000000001739327f282812fbcbeccb12e40df049284562d8986b8d4559787e1d5247eb6c83d6b838d099f36d8d0e32da2a7999a10000000000000000000000000000000005e5b6b2baede3ceae776da5adf075c1d774e83d6129ccfe7e835862686bb4064b187cc0be0cbfed37e5cc039f3a3fb6000000000000000000000000000000000249554dcfa53f73ef8f08daabf20c55301f75c8ce095cd794061c55e195221602a54ba54260980bcdb35685e41d0f4ffa1d6d0d1876a67337d66c596fbcd7eb22ee308e4a5f66cedff584f1441be6a700000000000000000000000000000000048b7fc5a71787231f1c7ed2134be528fc8d8f77102bda806ccbadf4f9bed79ee94b43c0fd3e5b1d776fe73d786872d1000000000000000000000000000000000152a1f005a64e16949d7249c3b391d5c1e0ded4893d0ce926cc666f0f88b64e8dd6ec4f92ddda18127ec24cad7e40b40000000000000000000000000000000013a2e1e7958a53307adf3beb32a88b7c493df0e37e074c9105da3c09bbaa01fed092fce2b1800790c6e8af3d30ec5a81000000000000000000000000000000000e2d405806764c75122c1b5e410673b28759f26af7489cfa6f35c6c0dd16c508af045009853f3329cda4a67948232bcef0c4ac919efdf3d0e649126da7f8ca3daa30b6ca6f3be6854c0f447a63cf2110000000000000000000000000000000000a71d61dbb3ae37230a2dceb54061d5f8c1ce645e20ec39785c229cf79aefe238959b2745e3b50e4b3c20c7a8e2ae27f0000000000000000000000000000000010e82b8dd5faed6bbd5755c4e5a88edbb3511d3f4442d1e44b82cf72a6414bf6558d29e8907b07f71c00f537637605bb000000000000000000000000000000000d8c93f1984b742b5a02777b706970215c7d8eeeb7377cc26c3af9005648c2eaea7f7a3177b6e049b132ef6bb4b188da0000000000000000000000000000000000ff082a252082499d70eaeba6d5514fc8d641404b48b2ecb256eeb40d9c6b68ad5af58556c9dcfc5667621c549b8ee760d8bf380bc2223efc779a747c0a36f8c2b18c3e821e96163bae14b18f3739f9000000000000000000000000000000000f4cf354b8de6dd2231448bb235af3c84daac2db49abed345da6ded50eae93982a4f2c27b07ce725a062b07fdd9058fe00000000000000000000000000000000076cf19408f0f0379c7e65a6675b9856782990986f5c6d7002e9c9c74b95ab875924bd7ad5e4812844f6d1f530e58deb0000000000000000000000000000000007acffe32f96f5e56557965e3db8dce87eb7140d93608cc003bf4a43fb261bb7360c576da0b7c4dccdbdd9cc53b5c5f8000000000000000000000000000000000eba1c668fd9323d42d6a82d9f075cec2d278cc57122e25ccd72cf8b5a569552cc6b0e9f88d23b9b7af18f3bfa0cc820006c3a7b5ae971e4b0ec34a1007a02cf8c55f067115ba00c5967f70a7dcef9d60000000000000000000000000000000006157cb6e2dfa2733d4c489ec0334f0303ff1ad410f329cb59f99a5fa3ed2cf84eb7d2f231078ba5db0954badb58425f0000000000000000000000000000000003dfee394f4c140e2cad61e8675b26f91244880d9a0b6798d6111090dc9d080563db5c89b7293dcaadc74ea5849a08aa0000000000000000000000000000000001aa1e0683014d5b6f99f469a0b7beefaf05a7ac0298bd1a3e2da409f6cf856f70bc067610fd705a851cd70054df9562000000000000000000000000000000001571b129f69f3a6717272ff75351fa053f46294f68ba3f859208d6c91ba5eb9a0f2133a5e139d04e38c7f7aa303451768f29e330b48230de23e0393bf1614cd26685cafb899db5a164497955d3e98be4000000000000000000000000000000000c4e84b7c8e46daea67c8090b27dc28b7867b89b92f56232bfd8ecd9968b865a057957292e79c6dc08162f9e91e6a4b2000000000000000000000000000000000b8d1eadcf3f1de6ee608a4a0ebb7defeeaf4e251bf07717a6a8e50c07223ca32a2ef290f26d0de14b1942e02acba39a000000000000000000000000000000000e901b546a4d3c68e4432f376c97f42ecf0724777956c4ffb1e6ca4fda562e57be788ecfa45ba3afadb439c2ea546ff30000000000000000000000000000000007ffe01da4fbda9fe5d47c3bedb4b92fdd71ad73fa272b071a7a7d1cdce7743a535da7dfe05a43d03368eb97fff54b2d861ffae8f62572938925593f7271a56e0f559b56bf97c454c38547a2185e2ce70000000000000000000000000000000008da0fe413e31ca68f84032f23bdd5399e01eb3b5ae47033c6834a39645d7b5cc2ec937067b91ac6d83035a86fa841f9000000000000000000000000000000000b950b982323f747782d9065dddca5332940058a604829e31560a6bf9b03ec72b09cfb87a1cd244ec694c7cf192c37ac000000000000000000000000000000000f4afddd25eac15d2248c71d76c9aa27323f75141820efeef1ab4f5003141053f138d9a7d1a901961d0f2c210ade27ed000000000000000000000000000000000217b1800c53d53459b00b8e463df1882b2cbafe85043f08093a5414e58ea7fd4dd933c601acfd7c154d0e4ce187468a2dd907071c2d39fe710215d174452459cc31d36007a1b5570a27ca2e42c8be55000000000000000000000000000000000046aed1acd19201553bb6a88fd6a6c0525ed44822d2a4ed3bca48a0a2b75e76cfcdced8f342b81ce03ffa72e667b3bf0000000000000000000000000000000009a5adbac43cca3402db016a2138342fae89285ab1fa16d7acaa9c3ee2b4e3df2641f7392355996bef7b1578ce1ef119000000000000000000000000000000000c8ebbcbdf2ac3fbb553a2e589f4b7c259a1621b83b14fd1927f92d9f6cb27e82507d7943ff5930f0c14b9fc38c9857900000000000000000000000000000000105b729f678db31d04ceae0aa37f9cb0b0319c4da9a1a4702a11bfe3a5f2f1f2af09b9cbd5ded5a930e2e65f4279a31699893c06db2dab559f2c374df4298707dc1815e55034dce920ae7b1df2ec8d23", - "Expected": "000000000000000000000000000000000708e9b926f2536731b02b6b75305c549da58e312d9c53701a993624697af2f3469af34dd4634467f8c98a0f721cd9c00000000000000000000000000000000019185b84fc0511a048e3c39bc10334c91dc1052d323a31c8bf325479a2fa3e4228f8260c0e725c2b89d5a0319e6fbed70000000000000000000000000000000013c7c441d5cca81b48d43e908d6a3bf8b5057cf19e4884227cefa9b235103b46edbe01bada06bb9b620ebbd016d537630000000000000000000000000000000000431182c8a1eed66073956fe5798a894be396403c072e766cdc262b719d1779f960f4aebf61c1bcd4d005d3c7413e52", - "Name": "matter_g2_multiexp_75", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000199f555aa5c651183f52470e36cde438422f41c9b2d1947510665254b74ba0bb9cdc6e6a1283b0c8f58d8f009eec46900000000000000000000000000000000018f1d8f22f43b4649300aa23ac92a2e8f17e7e3853b912bbc8e90588125c371084cb224c2d54dcecb4946ff6db53cd02000000000000000000000000000000000efed0bcc83a52f0faf9e260815da8d4e5286396081268485aab052a96af8eea0112be6cce1486b10b60551ad6c810780000000000000000000000000000000013a3b1ca3b9b7d50083c10d36997f5f521d4426af8d2905aa5d074ff37e218a0c96c74387485c2dae24c0842b7a74cf0d8555388bcc6791802ddb6c0f4cde44f45ac0b5d7ecd918bc34fb9fdedb65b94000000000000000000000000000000000efc5a5c506e94ad2754e235e2da866d9c46342f14d518f12510c93f13a619f6bfefec50c146d6d6170f190497eff229000000000000000000000000000000000fb91f34356005f38c9804250549554cfe67ce195d5e218e4e1b1a4fb904257bdb68d6dfb013e8e85fb5a4cbdbf0f21a000000000000000000000000000000000f09903db4c41fe3f11c6f0cdb7c31a131033e30f52cb66ba10c2e7da1ed8a225ef280d313630121701f9a490e8a0f5c0000000000000000000000000000000003484f7e8f7d67ce40b4cccef110bc255d91f61a4e1968a9ad37e25058eeaf39e9f1ff89c9b2e515388a7c1b49a84a2c33e5999498978d14c9de06f7beb2fd870f6f16dc42125fa496606e65c7466c0f000000000000000000000000000000000444215c3d4a7d62201ea1b69890e2ab90b5f5c6ff56fdc9908634c7489e785521b8dcd7ed409cf09c585cae8414a3250000000000000000000000000000000002d70674251a0c9ba76b8bf3b70547da77cde5592da9204954abd6d8aec82799cc0fa4fcd42139357043fc867b3d0e0d0000000000000000000000000000000018c57fafbad2351a3da695f8b523443e8c763dd7ab875caaa6a494a498cc40b1c0d44488e2dc80d1f0bce00a2c90c67000000000000000000000000000000000125d5a87ee3f558b5e1e7664b0cb95c195bcebd5e43b930fb47d15eee4fd50b3fdd0a401c9bb011c326acc77645440137894a51dcfe5a8fa4da1745a696c870b353fb03a31238b8744840a78084bde480000000000000000000000000000000018790123ce8b3b72d626493a16936c47770a9b06ca45b17c6fa5c7759f088cf98de8ce7b3b5d6082e9e42b39acf76f79000000000000000000000000000000000fea86cad8b40f315d8378550f6d3d831149339a8e8dafa77295859ddd2417e8f5c0ae2baad25fcfe00de14f45a537170000000000000000000000000000000014ad78bb2bce966d52b1fe1a273bc07f2f24b354465edef6dbb1e0123c7c3d7550983b3793ff1c7db846e88eddbf33c4000000000000000000000000000000000c0daa6fba40ec59f6b34d413130df5d9137297d1b7b71b83114a6570fef8e7f83d6f5689527164782f92da4b1ea12e8fb6a294589c816e18859cec34262df6490a2af6acc7daa3de861198c5bcf4b13000000000000000000000000000000001186b7c78952e5c32a9393eab07ad4532471595bc2c5d8137c61dd7fe6b6ca3aaba82dc205a559bdc15421a001b7270d0000000000000000000000000000000012d56b6fcec3d6511d2d723601cb8c9faabdcdd12efdd0e2bfd7c9292f2c3bd7f39c6e9aa53e6955727f88ad69c5b4f10000000000000000000000000000000006a5e56e4a42b04c03619c78232104f1f1f39e755058a19354eb230f2f09bf486b2586817aa6b88f27b884957ea0226600000000000000000000000000000000118c8521dd4866df907ecb252d9ce7a489f17d0f240d054a5dbff6c35895ef20b205236aa6e5be6f0825f9df87878ab783c4a3460caa35fc0e7342dd2da5c7b6aae818eeaf5a2cbf4794387180b95dfa00000000000000000000000000000000092809d18926c20456857826491f55cec17803e9e7d43f22faf4da18ede3bda15e3319539017ab20ed1de2bff490a33f0000000000000000000000000000000018d736b967eca64234f4e0018e5d6c902608e265037d9b8ba42dcc923b84ac62599e153e1c7d00e552ecc5aac57d1a5d000000000000000000000000000000001804aee99219354d4a5c46328f0658a417c85c6bc89af6db29a4911c4b0cad5638fac5ca61cc997fef3450cfb4a6c666000000000000000000000000000000000bf99dc4a400adda5bc89762e9011dae8ada23b284e52e2d49f75f1c75247f6282c95a36f7a72f896ea308131215404bd2b65c1580bb46e3a4cd9d9c4eb7dc998168c66982448abf3a4e08cd12f612b1000000000000000000000000000000000604f8bde85c0b26894e0de155cf896c911bca47533362a0b59ccdad0dd64108d33af8262d3ca2ca399306723f2482a8000000000000000000000000000000000ec10d3777aa54cd0cfd84b4062092ca3ac840a24e8e8aaad5f4c275e4d45091f838ae522efb1b2a0fa42229157297d300000000000000000000000000000000132cc70638d02186116773b31ec0e571a55c1cd78ec055fc647ab09cf4d3c543e0552d559b3daa4e99cef031e583e61500000000000000000000000000000000194a6a32a269692906b64feef9e4e8cd204e560b98db8c66380758d2123babae871273b4c571a1570a317c13a51d0fe9120892aded230949b83bfb2dbac054b83a9dbb852bd0ad85dd1d7f715852306f0000000000000000000000000000000016d05912dfff44912bf34f242ac85eb55bbb8a21625d45496c76d057f518352528c6632d6e8adbbccdd5983d13c26953000000000000000000000000000000000b10aa1402c15fd601ce605ade8f25531ea8f95cf592bf4ed86c4a3aa847dc8aa2369655ce5348da30a897fa8d71ffd800000000000000000000000000000000183f5a2f40da0a0f4598c6b9ea7b99f8cda1d85cec0e6da5365d7eaad1e9a3167bd647e5e654985f395ea72257f61e5d0000000000000000000000000000000014e615e2d5072c1b536ffa607f3a826ce297800b0da329fff397b6327800ecdc879e91f1e3ebc26c18e188e1ca66bfd66af9777a58539e5aa8b1fce0994e0e1cdb5877d93ed4db715c5aaf74d6a8bb1a000000000000000000000000000000000f3cd275d72a637bcce855e2e20727c6e5a1f15bc8d799231d3a7f61311d4cd2f58cf38448675aee9910c1a3d0b576210000000000000000000000000000000019efca445312f568727948c803d06b8d4e2c5289015740f2626fedbc0047d344aead06ef521ff7e139312fa41d1c107200000000000000000000000000000000141384e1c9f79e38bbb0bc1025c079741b93f56e150df58cf9a61ec27c2877c4188866fa197242965e3feb47a78c68380000000000000000000000000000000010638286faa6c45cf028e8e3d200edcb348560e2e35902927391401b3155240b62a40784db88e02b874e128e3a2132b5f37e2ed8e96921a0f9bff8b43d432b382d7b59938e269c381351ea49b8c1ba2b000000000000000000000000000000000c7fc4216767ed298206bc142862c138d78726e2d39afa18fe5732616c73a965d95cd2032d4b2f5a4d562be48ba6885a000000000000000000000000000000000928bbbd76b87f58ecc850e1aa4a2be11b15a81786aa7ca8cf0f6cc342db87b66c435f009f88ad97b747400fbcc651e10000000000000000000000000000000019f5ae9f06f2bc27a39bafacc7f3745fcdf8c78c9ae8a3c066ffd704aa4117eba773691ae43387b93e86d2e2de3688700000000000000000000000000000000014360a7ed73c05ef5fe651321f7e839c920bbc1896636143b88357cbf76e15da839bc7e1f1e629768d447c9d313cec8e23f4a77a2c34a370a9b59ab1cfad77212e433464d0195f0d2fd20c69141389f50000000000000000000000000000000000b9d955f9d28f9485d0bc4a961f0acbf09ee5fef38ccd81a2c73cf87a461ff1bf28d4dd1e0db3ea522299af67bff93b000000000000000000000000000000000889061e71866001b0760f68e20c7c0c033d782e6e6752f11502a0e8b6b70277a985dd13dd83424d1e5cdb9eb96a01c0000000000000000000000000000000000e05a26686667f44de2bef53c36c82f1fdda13dd3f7f8fe1fb026273dc4dfad18241d732ccb757e2b46ed8317dc69fad00000000000000000000000000000000038b55685b02231905dd9a62a709c0f015cf5650b3fa469462b3e9d06e3af8092d998c8e08ee61db1fd5583b0809a38996c59b0bc6dbf66f42cfee34413cc4cbdae7a61e232757c75474818591764d6f0000000000000000000000000000000006649a8eabb25fb7793344a0b29325a88294343f6c69612ee9d9002154a49791f6cd7b37b2bec69fa8ce11722e9f8a03000000000000000000000000000000000e10f2f3de16fce9b9817085f0130e1839d9aae949170ec16834732a9b12f589a2b00f17d2fd3416ddd020b7421ca20500000000000000000000000000000000016b51112b3c7c42a8c2a0fa7f286ec05cd07b6cea5675bf1132de99cf42b450b3c2a8f02ec821529a14a2a0fac3a751000000000000000000000000000000000f471ec8b65bde22e003500d1d422dd0d163abb424dd261fac588333755cc5124acde328085d8df852c61e024155564781c180924f1d982bf4b6a2bb1cac590cdfe84198fdecd87364e163dd988f9b1c000000000000000000000000000000000ec162d22b6516c309efb6a4577c5631a5807bebddc5fd1be5446e4a64785d49eed80eba2e89cfefe484ecb8d50440a600000000000000000000000000000000070c252caf6c56018af6b281b829a4fb8dbab850ba0446d233dcd4d87bebac00e3e5070bd41898dd561526498b153199000000000000000000000000000000000a0d76d1205c1f520d82c85bac4473ea7cf5f68022d95b1f04d06062197973001234d86921e70a94e478eea85264f14a0000000000000000000000000000000014c6a07f0d568f2103ccf8f61278e916458820bcb61fd91479b0dee874fe36c063a34bcb14ee434b68681d297637b5bfe44748b9eb1f44b5fb143cc8deaad23047bc5ecb8059705e7905c37625d5e2d3000000000000000000000000000000000aabac129385d145243c3a1f357ccc963ff14867ad039827488128ac639dc62fba82ace66f889b47d8eac39802bc1af900000000000000000000000000000000062bbbe8c72cd6f8626484bac159b7e28c6c8c3261edc6a05a30c308cc9e56db17eb58f62ab755f04a5c87e58c04c7550000000000000000000000000000000011a4a439d18501142350229778f67bbe0c9b948229dcecf70a8b09d1df6c54801a111c603301da2377d4198d09dd51e70000000000000000000000000000000017de3d9bc6fc5f415d04ecec013a635fa200699c496f4d0bdb5cea7d446274dddd0a7f6b06058fde43fc4f1457361558ae04d7723b7c9cb0574ba744bfed8f8a347ab740bdab99136aa71a6d635d0d98000000000000000000000000000000000c86590a02fb5c9568af4e69611f09980cb5a7e040c94ecdbe64e40005783fd3305a5657a5c6bebca7d20ee123a872b4000000000000000000000000000000000bc873a9bc694171d2606f4efa409897e03198a61b1bb16ae90f0d12345d2650d93c46e0c22b717e2f0504b8983515990000000000000000000000000000000001df9160ac3bc54c0121a9c69e9065f4266202f755c961bcb8641d13720b82ebd73eb3804ba44769fb2d75144442f1c400000000000000000000000000000000045e9c8ed2fe1e5c9a2a5bda75dd60f6bb5dcd0a805f68c1f662a5960b025ff29c8e21857d2a61bcd65c747d2a2da8ef6a794685a342ff25dd706e4df725e3466889d8f08a27ed2f32523b117f01a84e000000000000000000000000000000000f94df8d267339bb4f51b21014ca6d685f7657d0f0bca189e53cf19e0e5e05bfad773c0553daafd80c86f302b1907ba5000000000000000000000000000000000d92905addc028a1dfdad50e909c77662e10e4689e7c8a4a0174a3e1c746b361665b65e17fce02b6c067a5b8d7a6a6f500000000000000000000000000000000183444f0665790c48bd3c07545115a11f82463a092774234e7b33aac1094761f213235895e5e61ac1b0a15603bffe2140000000000000000000000000000000003cc2cbbf181fb023a5f6088d8a9793b17984b3dddc8c3ef1a9f82f8f436002610df60b2d35be212da9945bc8108c0bced3f23c51953e46d400802dde46c374178ef379d5c1b04d25449891f0d5623e5", - "Expected": "0000000000000000000000000000000011f85691799cb76213068ef4f997af66c349bf707295b969d85fe637d4eabf54f3f29e739152aba5027c1b55317a27210000000000000000000000000000000019627f9570f07f44f326b5b3ee19bc477e92d813be2865e00da93135645e02e6fe5507ac4d50085b02149667794609fd0000000000000000000000000000000018fdc97bf0f88b2348b436d70ac4e28b5ee5ba21e21e94808b8b9e401c0c7d688974fe203ebda0b23abe38018876f4930000000000000000000000000000000019e28c9c936ea5a0b3b41871c3afaaabd53a93902e44a96dcb7651bce7e6143d81cb695fea8b94aa32c09ec030dd9ac4", - "Name": "matter_g2_multiexp_76", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000703481cf48efe78fe8dad34184edd1765a1d01846de74a45b43d4721bf1af116c229f969868b0e6e851f22bdfb0451300000000000000000000000000000000063d316d495b1e82380c5b73bd61ce7f2159e7714c50e374e8a91dd56731dbe03a3378bf8afeccaba5fda73b4c2dd166000000000000000000000000000000001012cb2f6578065c93aeb673f447ce95fb42927ef9d12e07968ec04b6a604d785944620043dee5de4de33d59e67d64f20000000000000000000000000000000018cc7cfc360801ecc420d77ee171fb3eac3be0cf26b3f36a6cfb7c6adae7bb74c18071daed8fc56b8fa639ea138267928c8e071da1ae8f615631759cf33fdb876ab289a6bcfa6fba2693a58f8601dfd10000000000000000000000000000000011e0dfc437a65c6fe37bb9e554b5138f68a3c52816807bdf7d98f13cfaf86b37e9669f4e0db1b7865d910a309f16cc200000000000000000000000000000000006f2323e01591a7db1d3c7fa1a2ce4540cbe0396cc55baa3a3e13650a6f6b926a7cde0eebb45d359edd52137152fe360000000000000000000000000000000000066bfec8df4ab5f5f5eb369b34e8e22fe32abfc00ac58b68f2d3841248fe5843d6d29ad012249fb9ee851e40b940dc2000000000000000000000000000000000f4ea977d9249bc05dafb682a863ed17f7fba0a06c4a13cdf5a836748664183272eed96bc4109bc5beff61c5469e221f8371fff9230243d2e6cb6bdc4cd97260a8cf0362d18b9ba8df512d2a6f5563dc000000000000000000000000000000000fa3e3e77112774fd6d6b560ff88cc92ef8d009675d0ed65705398ce727cfe786684da50bcdfaffae97d19bdaddd81c00000000000000000000000000000000019e98284b8b9f53faf3b73902cc322dd80fc330dcaff2a7fceb55db6a4b0f7f667297f5e4650c797ee337985dc6b54310000000000000000000000000000000004e30acf2ba66d842575c8679caec607fd090f0aa2350464f3b6eef22e2b9a1d9d5fabb0f3909f1c19f6b8f27c53b040000000000000000000000000000000000ad76b86e32f84ad74bac68909da0c271571606e071b13bd92e387a8a16a1c4002c5a5e94ecaa1e8d2d6e051e19a45c763016c9a9cfbf336ebda090d3f2a1a1b265787e1917f0148f82a9c0b66b21dc100000000000000000000000000000000019bd07479b234bba974ca2f39b317d5f4be33afef66c1d69e53c44cb5e44c679775ba141f82486424110d186561777f00000000000000000000000000000000130002de0d453abe9052a5f70a9d55de74939d1c8e6ad5871a669a867861b1359322eb98539f4a21597d806aeca62d18000000000000000000000000000000000b2f0c649fdb37216c10762f510c3bb4c789dbd29c4f9a8ff39f74ed1a96609c60473a50f5ce3f6535e4af0f2f0a150c000000000000000000000000000000000893b9af710787361a32fbd19c380161c9a214a1bcf3761563424b8546f6068ba650d9caff3e42be63ebf4b6afa2de516c9f679167d5fbb29250834c9f65d3025606e2af20aedec309718f95ba01e90c00000000000000000000000000000000019805c0de5e232632228e2772dc79712e3d863bd6fe56932b29ee99870d2ce5eaf90c73632d1dcddc093e9b6b5b0f1d000000000000000000000000000000000405d77f4b3c44f99a956ef375879e62df033aa408127e0fee013b74675a8c7d999c6abd30f459693086bfdb326d67af00000000000000000000000000000000110f2c231998aca3d76e40055a05feb37eba76cdd10106719f2300f57906424d7eb6d9f85115b78b7371ee60e26d02b5000000000000000000000000000000000593a4721a67caa7cbbe1566611a1d48532c68adcdbb67f362c9ec21e08aaddf6b5e09a9a96df9a89bc25f11665f3a36aaa3300f5a2fafab132f5f4662c1d288210e7502ca2472d060aeea6f2eab2d7100000000000000000000000000000000151758f1921743d116f1c4adfc09cb68b3ff911329e2f6d6bcd04beb9c109568c796f328e1f04381a995fe89aebbc49c000000000000000000000000000000001388c73b1db46bdbe70540c99db46b730e157a23afea97648d73f9d5f7e8b073ed665eed9e9e2500152c87715f1c4d4c000000000000000000000000000000000284ad228867ed14ade5a327ed951ca50c87f0a669e59b7a75d17feb54bc5d685245448a912590179db1e84f1eed1e5b0000000000000000000000000000000017d3da7c167733dd88f1c39315e47cc80c3310cc431989d4cc50ddb22e9fa481c5dc02d94dbf806c4c8da16ba5b24905f6608f7c036c8fdc335601ac55e869215eb4e626f52bae813d45b827df2afd490000000000000000000000000000000016064871cb68f748939a839800afbb018fd5836914a2b76c51818e764628a76817c7ea329e6b2f9de653c8162a2a2e0c00000000000000000000000000000000082fa03cda4c617a780caaecd7c859c5251b56b61f70fb3ea8c05b4c11c030adb8a96d715c1325ef3dce9b20e8065b6700000000000000000000000000000000174a245baedb7e1bf1368212620b850151be41ebb00c977d85da499223c207ab6f1a1d94a51aa9e90d07764ec3615b3a000000000000000000000000000000000df5b81cf4b008480775ff3d7644f546a60382e92a98b03deaa4a20f831e69e14a893ffa731c4ae9ee237d747149a9080cd68c59b1371c7063dee5732182961be90b95247511a5b564d7eee8d2c7c64700000000000000000000000000000000019d36b8dae5e1083e687743f7494b7f9dd0923024df81e2f83c78743e227ffce588a16630201b9909daa6c9207b5f430000000000000000000000000000000015659059cfee7850e1cf0e49abeef2fe5837cd128742e62de20dc734f1bba343aee1c9f1a59d920a0519995561891fdc00000000000000000000000000000000102b7221257c40d9adabd0db3ec9f6348487187ea1110773fcb2ac5ce210dfed167a4d15e605e9d9e666fd092147a1c7000000000000000000000000000000001402ff9770d27d2d82efa6abe4a181e3c1d944e97a06f670d9e46b24f9900fb4a838b32e17482f25be9b6f3240870c02ea52329555d9b79eb1fd6d186df80b25245ba9225553f402cfa6037592f0b10f0000000000000000000000000000000001745ea52686f87a39fa42ddb5b0f69368db3757394fa7a1a93eb20c398c26415c8a7edeec7334df5b15345d6174126b0000000000000000000000000000000012b580e6fd228f087c7584cd95826e56d1c074cf16c35286c45d2067a362529d241c1e24fd22cc9727d423551de1a1f700000000000000000000000000000000104b46c42a706c61610f8c0434894c7cb9ef878cd0234f8aec0825cbb8297bed3de349e7f6037dd19a159103ca7753390000000000000000000000000000000010b781b3cbe6f415af15e37be7c60dc6703e6e79618cb3d8d9a5ea3b17c00822aef1eddacad66a646c009dac887bb070caf39f2a517d432d1653c37fd9a6c4a8a811107dae428f4b2af3b12e4b6acea30000000000000000000000000000000004b172c360fca555e65860c7a294960f506b562e012ddebad5803bc3f4b93159c16cedb73f339def9cd1beaa0912c93c000000000000000000000000000000000242e37775a042ccf59e99da667c67fc49e80e54a1b438a74fe306d668059ab4dc7d9e457adb45e1f91b3e6bef0a130f00000000000000000000000000000000186eb83ce3abe66b8760dcc0d375eb783d175b0b2f36cc08793d8a86cf76b7618b826f50c6b02ed586394abe4efec2f1000000000000000000000000000000000bf780324df1cc5de325a796f1fde367eb52dac76c0632915dfcaf01f5acd6ae890dbfc2e505bafeba7fed8fd63018c2ff0bad6dae80d5f47dd8c208fef0f3046cf1040112d18c596eeb934762977cdc000000000000000000000000000000001231b52c8a081add6e5c250caeb9467335933c2ed66826e4ab44561eda9259acf926f22ad0df8e8756aa51279d12bc9600000000000000000000000000000000051c46bb04d3e035d324de681c772e4561cecc6a5bc4ef0a0cea56618e09b3f39f5085e208229e50164bcdcd4abdefd2000000000000000000000000000000000ad7ee610398935a02c3a7139185409d7fd4681ebb74a239e15d1c092ea913016d3f585d8224cb1d109ac111660a94aa000000000000000000000000000000000903bb16efb052b99e9c46f3478b4acf800a173b35b0079d7728fc25c9415c8b05ad520f31e6a3c867245f64355cbc080d0c40e5d422685c5c83716380eed82392ae1dc6074a7edb5759fa34a61db2d0000000000000000000000000000000001788efb21597aaac29b7bcb9ad6cecb89267c757cfcd8893c32fb13c0f3e1af7fcccb9573dcffe8d9220292b7861cac90000000000000000000000000000000015f85d3686148ad62d7fecb71920981117cb8759ab249d0ceb45f9e4687914536a1eb16ccd0e185d1352a8d2b4a8ee7a0000000000000000000000000000000015d8ed94c0415ee0f7c9854841bac5821253bb2ed4d86a61f494cbfbd61614983e4279fb17802ca68aba4a0302ec1d8a000000000000000000000000000000000f950a4c8aa18f4605e1252c367dba1e170ad00376a8560c2fccfa7d5487b0d1d5885cec16a0a17d81b5a584d473853f7e93a16a443d5f981a02f0b6866536dadd276abc0998bedd76b168ebc8e31b82000000000000000000000000000000000da25ed9154121205ab6843f603a38a6892887d2725f16ff87a5218586c6139188f46da5a42b5e05982468e8115713ce0000000000000000000000000000000013c13ffbed4a60bcb8659013b022012ef3a4400f506d65aff7ffb1bd5a9a5e030a298e417cc1ec8ee7ebc06455dbe61b00000000000000000000000000000000132d83bd141c434326d4772de7f8772c30a6456de7adee7de66a04bece4c0d20bae5526c8eca5af5ef2eebd72c90d54d00000000000000000000000000000000131355c5e359081dc86e0b15c8aedb4f2016b41e8428051f5132258eaf4392fdb63a91452dc56aca20b7ad3263ebc8c92a1d13a64c03585715908744481c79f340b5bdcdd88d685ab8b91722ee7ab7190000000000000000000000000000000012dbe1327162e4176b4988cec23df0c1b0075d0dc51ea8afbbf98f00891511d9023cf7538c5705d59b6d6ddcc90b101d00000000000000000000000000000000036c12c7f7627b6d6fcba9a303248c38d784a3d1d0ff02e550565efbab68c5116e9a88faaaf09bc72bcc3358e9dad0ee000000000000000000000000000000001578ffb68cf12dc9a5ae6fb5d822324cec9e3f576ce08d45e24fec9203d36a6461c5b8ea6ac50233e8893b07ea6e71e00000000000000000000000000000000015cdb43c82b20b8ab270b942b9e625ada9283962a7ce95eae156aa4355e1123ff87ddb1cc85b2a94bf36102ccbec33fb2bc6979fa2e386abec058683c6d74de31af3cac21283cd5e4244d7edd94da9600000000000000000000000000000000017041e16975850e6445c7b4896955eb5eab383ad3c3031aef04e8fdfb65a6d52c9e647330bfbb0f0eab630c9f9ef7a12000000000000000000000000000000000b62757ccfb913ac4264692053f766e142697f598a3fe26e998119b63a3abc7fee03db32a8af36aa21181fe9ea89d12c0000000000000000000000000000000006bbb842a889d7ff3c1eb5e0b16e3a921a11d28a251c488a8a17a29edd93672fd15974a7e972a34c47283c583cf2d29b000000000000000000000000000000000e94e685fb1751f8720b8af79aec7b245ae8daa195f11f485f2c0c5dd68cf39eef848a402ce2342a6b3398cc7879c6010f1937936cc3766184e47f39acfe5af4497e8edf77ab34083135a9ced61d25ed00000000000000000000000000000000100d3fee47ae6c8c7981c8cc615870924fbcb34c2ed817d6862e2e6d0b4612222a4c8332c7d51b58ec59df6832139e1d0000000000000000000000000000000017270fa71c34ec84043ef64c5dfd61614b5b3bd99204f9f70994d71498219818a5f16843c67c668b06aa5ad3a6ba8a0a00000000000000000000000000000000057948c0ebd14664bf33fb282e200fa0e641764a353e8347586465dab0c79ca2caffbdc2c6d60b2d7c8cb6b088bd16fc0000000000000000000000000000000012747eb070f2de18f517648395109bc08b4af3f04d98e23eb6b516199b4eefc5df7d57baec736987139c7b03b573941f639a8b60a1849c71688a11e612b315439161717f525b5deabbce75808470166e", - "Expected": "00000000000000000000000000000000128c6c0283ea35c10330502d6aa849a909df6b8dd927a24f08072135b8e21e40c495c42e742160363772569189d73ef40000000000000000000000000000000016d78dba1e0feeab46f8cd38681a9c2f6490ecc3a6e79b31caead256611d133090a4eaed9691a87b66dd1c2ee50d5f470000000000000000000000000000000016de93e176c950975abcbc692384996315a98065db6d6a6214472e5a338e291b36abbcdea1b8be6162fe578acd669abf000000000000000000000000000000000d7155e239e9b15ab64a538b0a0bd53936df4ebdc3ec9b0b1d494e4df780bd014425759e9743c9b262cf48cda01e945a", - "Name": "matter_g2_multiexp_77", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a653e0c24eee1cdf8e3652809de0cd159f2c541981a4f43936e7d41c0f97ffe2f1e1e0d1032f0970023f1d27241a16a0000000000000000000000000000000012d1d8d2f96db0e5f97be096c961e3b90ef3d88492fb756894979d2e8104791a5b9a43888043ce9e543691f15d2fdb650000000000000000000000000000000006ffb94dc3c2d07830498260ebe4641b2cb64df61cebfffaf2d4ab5b6ba92cd75de209e8d7915ee744c4db5352ff239d0000000000000000000000000000000011f25722cf9db77ef8adb9caa250175e12412e6350b494395a86c31e1f5dee6c89cc6603f1dfd08a70344cdc44aa0c2df3efcda934ec9d2ab05f25d618e5a483e830d0452a88e980589fcd7cfc39e5d80000000000000000000000000000000006177a74e3551770e7d906222590108bae7b97a5dd3bdd2344fc12e7005f2c1a188ab9dffe68f5ffb0cc36294106f15800000000000000000000000000000000041b140c46868767119a6ebb58562570732198854c92bcc070f2a8d9be91282a70c5ab99e75cc9e5064ed628aa5c59de000000000000000000000000000000000f318ee33fccf455e46add44922bb6e99afd4354bbc79d7550f8d12d3de4f75e5ddf4e62624b116f91aaa80a148adaf9000000000000000000000000000000000fe012bf88e152eb62c0c906dccba469abe591687573a59d3debe747b7d895e4b0755f16e67fa9193a2fd338c04d243a4507a696cc57c0bc49fb4d1686752c71c9c816d7d09bd66910b23810d475aa02000000000000000000000000000000000b26c6e0106d4efbacf2dd0d15df17209b1306f388f493c096429c031bc4a6a535b64cb02b400433f948fd6004df2fa200000000000000000000000000000000061853cf1a32fdf4c370cd413754ea584d3722a08d58575075a7371e57a7bdef95386ed72f91c4893377f6b551dd6b1d000000000000000000000000000000000ebf17e60718c8563a1029ba035dbbba75e7191b4339d5d33f64bb35f34866081f26f4815e01b02e8330e7b7e9c428cd0000000000000000000000000000000008ce40f92efb5c5be48c814018fbbe45f1be45f5b607a6600cecd50d8f791de7d91939ab61204c2a1337c3f21b2c9d26518c1259f23de4cecd5e3a40abef5662b497ebaf16240f40ecd651d2ba50af0700000000000000000000000000000000123ef52cc44f36326b33234ab3348893bc722bac3674e43385b201f372fe4ea3569d69d4d561e26f8ea903e017d7376a0000000000000000000000000000000005b1707ef61ff9acb9e8b4dd6922daaaa2d8a7558cb55b1b9b96eb6d57c23f50a7955763c9b5ef04f52b09be8d55f4b50000000000000000000000000000000015b6e35d14da61e7a7fcbcb0dddaf0071d8d2d89f7179f44851947a2b9b0535d6fa86b5cae9713a73bbed909a4c6deaa0000000000000000000000000000000013463e135b1fd460cf042dcd0226e229d60cc2beccd8a1832df241e65a644159722a14297c0033eb499e5890f0caff1e5561616c195ccc1345421d8a6efec48f0a4dc8e89ee89599839efaf95c386551000000000000000000000000000000000fbdf4a533d355e232723fbc97352fc5d7d3d199934883a61a9ea116830bdf9e40d423256225d9a3458134332ef6e817000000000000000000000000000000001195f0ad227941c5e383c48f546be34762d158e6cee585650b6ee987f7b98e802f678abac6646832b30b6e12e90948cb000000000000000000000000000000001820d5fbb5a62140c6e8cd105a70fc2f1ed84e254c839deadae5eadbb75e1c33a07ad12ee92900f55478e91958a3147a0000000000000000000000000000000013849bdcae33fad27f16e91c6d46b9678a00491e3d70a8db905db4b1d2c6f02a29392b5b77c1472052d6f4d49f14a16737c77734125181c72454bb2d37c3725cf1f9b6d6f42b721bca469fec154b3e2600000000000000000000000000000000188fe1e394b567d71099fa13b5c8a5891636d83b6b8a08f410b080658a0663deaae4dca1afe8b9023b5e8e573c752c92000000000000000000000000000000000f66c65dab8e1b2912fd5285a4c87821888532f5107075cdfedacc4d7f75c6a74b4828d0b4c3a2c0ed94576654a7047d0000000000000000000000000000000016af44a6df79c8c9b6f1d8aeca24e024c454d7b94c9ed386858dd35c4158cddcad1207f9fc3ac9e3b748c2314f875dac000000000000000000000000000000000315e5e4f78e9fcb93aac78025e95b8bf82ce4c840cf565e0a868b0aac22950d62f7becbf8039a16ca3ea66a7498327d981483aa66e04351f4340fd2b461165b9a9983e91c148da78d3c8e0c69e77de4000000000000000000000000000000000f9a61dd1b3034b8cd7408b0a44c8d02f4fe0e87778d5d34f5e884ccc9e2d51eca6b6060b46b66843e8247b3c794e19d0000000000000000000000000000000005c47fa7799a0fffcafbbe4694dfe8d0f47b60f712d6319e9a56ac459a636460e700e2af80f9c688208978aec7c413af000000000000000000000000000000000ab1c55fe2207865ecf12e372a341c776d24c08dba10702fce1cd2c01eda314852d81d0ccf1c3423c2a12e8960677f060000000000000000000000000000000014f8a1964aa3240d788ea40bb51abc50fae2736a34120ca9585fb2d5bba4e5cfa201c83be1e00ecd1c46fcb2ebb4eb809913da6f756005ca8ab900ab686484483af07df768209a16d807f8b88b9334d30000000000000000000000000000000006441fcaf5e68b10e7e511a95e56b9613453ec6468bb126c5eb12f204c9681c69b5c296320f92a6fbb0b848f8ab5fcd1000000000000000000000000000000000141de16aeca0a2f991e9fca4b6ce8fbab3d66ee3ee4dffb0124384a7d4ba51864a53e005fd34516c92ecab33165944a0000000000000000000000000000000008543656b5495bdb726109cd98fa18e405648fa88cbe2e5fea5380b7d0ecb207f0343dc7888b9945e55156977336226b000000000000000000000000000000000b53d4e392f304225b1ef363a3528daca1d3a6ad64ee99d58491863ea432a29cde5edd4f390de45a567cf32112ca5929188fb33fb359f21bc5bdfc85d39676c2ca0a1e619bf8a8e8de62da8818bd6cfe0000000000000000000000000000000002e0c55a43078df575efb2c99b27c5632dd1c08bf28b6c0558081a78de58e4258d1b57d94ec6fa157add04aee06e7b6e0000000000000000000000000000000006d3f4f0791431a56fb386f4bb8e6744cd19b10bd0f2e65e927371ab488d3735e3b83400ddb25ef9d740a8620821b0ab0000000000000000000000000000000011e9cdfec8a8f8eba0de6809485911711149ca0ebd0cecc033e2e5ddfc195fa7de671a686edd2f56e5f7da7328dfbec000000000000000000000000000000000171f188afd5d9568cc5648aefb65cd715c0293344b9aceac1031f10b4a1e4b9fa2ab11114bd58f28aaa58c10ee0eeac65525ab4c4468a2ec0beecdb7fb072f28260ebb3d9da1a4c274b2c11a087e814a000000000000000000000000000000001651d9bddf61e5e54f86609c2479513ae84b000ad7defd840d9619a8361922dde81c999d0e95d8a3044c46fe0360c2030000000000000000000000000000000014a68c248808e826a3bb50f3c1c1438483cbb9da8dd67a0c9633a47f733e6aa7deb4a13aaebcd50de6e8e8f00000424a0000000000000000000000000000000010c8a94b9e0ec9965f6c8bd0c4279102ab682a14fc3c22e9640d68f240ccecfead9a2c6e69f7c8ed369cce7e2da50d5000000000000000000000000000000000181493e8137fcfae203e1b45189fb828dc9eb56887c89aaf9aad0380fffada423f0ab48ed068ba4e67a2b01a16abbfe55ab5a55a5cfc49cf6c36b5718e108f8d006bf7fa1ec3dc7a7f9c02a2d1e3fc57000000000000000000000000000000000e3e33fa4d85a35e8707419ca6d4fb6a61ee6b07ce152adfbaf6b5f1d7ccc253b59f91e4545848b3570bfaa804ad9767000000000000000000000000000000000c923a4de074dce3ccc94698bf6445af5847c0e6f22f225c589f744ec83ed0810913af2a6d04bd55200ffc738b31b01200000000000000000000000000000000186961ed1c6039476eb6f13bf1b5f6627b3b017ece57a4a5f33db8ef12347fd507398a421932d3d2a1d009f65d06e42c0000000000000000000000000000000011e10ae0139f95a2f1144810894fb98f6e5e86ce67877b949a2a7134c446dfe53c23dfbfd12919b24975f26eafa249216ce7aa7dcd01c1b7059ad3cc0ebf5d19ceaae633160a968c33aac5dc6adb942800000000000000000000000000000000029265ecf3c81aab289c98d9cdb917749ceef56e2e4d59de2d6c83907f394ddd1cce9d093a20206c2c1c215493c41c49000000000000000000000000000000000986ad139381e4dbabd6beba179600e1c782f436f84a7bd58cdd96a22269f1d937f88f25059214fe2a781ac519aa621d0000000000000000000000000000000019e296d5b17f78b3ffbdaa2ef5228fa9dd65abdf6b2c5b0f99a708c4721797b3b156b8df98a5a879f17f095548555da7000000000000000000000000000000000349677d4719445d5525cd65e2338463d232eb75721ca51c48fe52d0fbd299ddbd6cbc12546f056bf212d5700c3c4100854bce63dcdc0cf408b43690abbbbdacda5f3ebd9d9e462f89f9f50a9f7bd44b0000000000000000000000000000000016f5d5eb3fc3ff178843a7d21d3dd628bda120321ae44206d88f07ac001651428e0da95d3f0676e1bbb969a300406ce000000000000000000000000000000000029121c539ef1d7b9888497a362fda2f8402adf10a1bee11b53cf3dfcc6f99d5026bc386f86a2eecd0c276494878104f000000000000000000000000000000001320a402922f2a0bb287464854be6782046dd9dae4c0cd94efcb8ad8e0f37b7889bc97a3c8b4d3b3670a6924c8ee23ec00000000000000000000000000000000101fa8bb2c90b755bfba9cd7a98790b7bea2ede4c806fbd9f2006d10cf87c44172d4ba46ea40fb75afbbaa2abc3b6e9d7603824b834a83c1c408243b51cd2c2d31e2ee763d69e2ad6d369bb6aa2396fd0000000000000000000000000000000003285cb099b04b6acd333c7ac76c839b6c09388792d5fa1f2af0821e49dfbf40a06803c4cca92512bb76d073129a48a00000000000000000000000000000000005b2fdbb25381b3b67814bf6cc0a4cc17271416d16ee369b723b1711d968c355b755183f0bce519709723250515ba32a0000000000000000000000000000000002c7062ba4f642b95e028a364b0698b801f48af3c336fa09d13d83ec6cff10d210b55b23cad1d999889c83df7d1ab7e10000000000000000000000000000000012cdfdc10bf46097083294259754453e084010f7ee928cf540d44c80aa4f601247223a318700bc24114e7603922d15ae923c86e91c48582f19409b962be361da5936db02b6862eefc288f9a32d5f54760000000000000000000000000000000000669d760352e34a407aef8e141fcaa9468257b12ec08ec218f49f0769f3acd5068c6dc9d251a1b2af02a2d091f8ad0000000000000000000000000000000000064a7b4026ee3115cb730e56c4b9bf3e1527dd0f0ac6015f43d30a2f3d8d8c2659cf50247e70ca3c93d7e0a404d9faaa000000000000000000000000000000000979ca2e81663ed61486c1f841c19d83549388d798da72feda82283406d4964bc9991f876a6032382c35b605441ee7da0000000000000000000000000000000008d92cf77b44c516c243f3e6a8a8d3f9d3d7405820ab972338f700de1dd9a66d33b4a70540a30f630aa81fe1cb5bf057e1b3071b561a80aaaadb5cc24b348a2b6012340d3aebcca7e2f56983a8a13bf900000000000000000000000000000000198831a40fec54a210a63f5e00b132bb1eca6408335b85a75e28be6a111beea3b99d9f2fe5091ab0eba0f082c201c14d000000000000000000000000000000000fe457f8d215f390000efbb7fe7193ba02a2ef78e9bff6539995f01604fdca9fa3c010276afb90215890f5a5df3ae21500000000000000000000000000000000076771823180422495d89c301443a9d1fa141716e5e27205b8cb6b461a3ded7e6f196c3976cd6ad56b2e6ebb6b3a70860000000000000000000000000000000007f666efc677f6f767828e1291bde0ba0ca445ddb2d69d5d2fa090ca49e697ce4e00f55d2b706454be6d68f012d76efbb6863b755d3dee61328a60f585531c436663bbeab9afaffac49b6f0b57614eaa", - "Expected": "000000000000000000000000000000000e1268a5e2f654c4038647a910e6cb4bab1d6ca3562ad4a9ac18444c8b8a3fdfbd35acf37f9203041fd587a5175ce86d0000000000000000000000000000000005e701a8ddd15ecb0231b7625f7868c81467c140b2617e60440a9b348a192e5248b1b3c087545cfb6d173fafe48d32f600000000000000000000000000000000071327f52b1325bb664d32c513fb12afb96dd8da23dd91bc4c3e8ae5f97d6bf673a5d03bb8bdeb6da3144dedac200dbd000000000000000000000000000000001852b86d3ef45aaeb691f454a345ed61104cecf0f444e4d841f2bc0402ea1291ef056eddb3fc3929ef4623f31016c3b5", - "Name": "matter_g2_multiexp_78", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fcd3f253d018ef09a7c6e8f36662ab4190867a197e0c42a0b425dfb5fe61d57596ada28dde0b093676ce15d03406d20000000000000000000000000000000000df00598337060d603607f3b8dd16f277ce1882a2e9ced48e1944662323efc29b33c807653f31583a5d2198426019ba70000000000000000000000000000000009876c81a76986435d34c6d44d51cf1016c19ceed2432ef1e68decd64da2e31e42372c1a41a514b0eac0ac103ab6f43800000000000000000000000000000000121cf298ff8f610c64ca4a887c52cbe940333506ef2afecffe266b5b585ff737395e2c64adc23b5bd232250e67c7a62613ca0cfc742607bee58988df361d7cd5d809ba4fddb209c898cd555369fff566000000000000000000000000000000001885d5cdc3e0e0c8cffa7519e6914e5d85962d07633970c4174ae4587853f13970a1f5d7ccba97458b9b5046847ad29800000000000000000000000000000000105b7c0ba96d5ce32d7447351ded3e3f491a0e741e921447b91f22a23b64c2d749055a0593e5b47f0ff7815e1a4c9943000000000000000000000000000000000cb88fc10c94642ae7e1d7275bbfd51a2d40e9b29f3d51a1ceda577beeb131eae4b17418f9f358d47b4b9c9ca4960a3b00000000000000000000000000000000131a3e080b1d4e936d97d255b07b09a6210b5fe6900da87b5cc595a72de2b6ddb01809e2dc63ad460a2926dd8d3b3b2ebcca8ab454fbc576a2b910f140b23c23b14301c19e1f47989d78eeecf279862a00000000000000000000000000000000066b31c0bc4b3b9fe420dc095d551903a2859556d86e210c96480f1d31d449d85ea292e2432babdb71c151c7b215cd6b0000000000000000000000000000000019d79a60793957745077f9233aee7a4f096515eefa7c49473f09bbc73fa0ee13a2a30a08bd7f3bc1d5c412d671fc37ff00000000000000000000000000000000006882160e4fa8ae2c2d48ae389d8f023e2775adb7a815edeba13728b8f6b343c45788c8e9116445e9989e01eb43e1500000000000000000000000000000000000ce53ab2d81ebaf4a85b3e12a6175ad7fb6cfbae207a69a0fe2195ab916fcb582b097f09d9fc565b837925f68855c4b59f82ceeb6160d3256228d7a41fb3caa6f305b23142ab979e728356a13309e27000000000000000000000000000000000a30d335c035afe459dc262fb1bd24dc0bafbc08fae0bed47e4e204280eb96595fada9c4332df1218748921bfb1274c7000000000000000000000000000000000e37eb189560211d6fe56faa3b6e710878a21907fdc1a9f8becabca290c24b8831e28ebb48d06bd822300fd09b4d103100000000000000000000000000000000104842b88b9df6a7b8243494eb11eb62c89d1ccbde9f55fe221c2366d6bc9149178f177628c6fe7c7661318640295e570000000000000000000000000000000011df8599d72b85ade11261076e02c036be5dfa3b6fab4ff72ed7413a879c0a0742be6c36a32d0829a4e3171b0341c6a3995f7d2038ad02deddca34399e5b5653fa471d998c52bd52241840cdb9202b2c0000000000000000000000000000000019f6634435be45b099cc739fe5c2dfa01f61fd2d466d5ea464053e2d5acf2e0e9448b1bb7770b5ad426f8a872c5764400000000000000000000000000000000002bbd52efecb10b3bb6f8bd04a5751042d8598cc34e2837184cea2b5953ec125dee871d1f2f57ebc84849e3a7ee5abe2000000000000000000000000000000001962b716342df9c13c21d89ab5b8c4c0ca191440fa709627e0f240a7ba518f4c95adfc5973b6ed0af591bb54bd00937f00000000000000000000000000000000089eec676276c52bfbb2593ef0362c12a5f3c1a0566d5aa862f5f5ba1580f4dadb36c15fdcf0c3910ee14487ff146c8997b67e68bfe2d7fc256e6aa610dd91dc1b02c64186d24702ad8fa9f715b582a5000000000000000000000000000000001556d081a489eba4fbb0c20e22b8cab432a9f6ff459ab9b0e7ceacbbd46c8e24a2ee70151b019a1b4bfe47d934afede30000000000000000000000000000000008fdd7391113e8d9865ef48b60acf921b17c50744e6ad62fa24abaae54836b3d59a7441371bdfdcdb251d252a43aed7b000000000000000000000000000000000cc66cdb1fe32beb91b05922f3920060e7a95467381d62f2f036e6268af4128c9516780ea53e873993744ce932b901f100000000000000000000000000000000151f94dec958859ecaeb810c4b1cc7a707d0e1671cd4a1e3c811910bc8b95c6c944167dd280c7fed22f92ce7650beef998115b9f84e3ed6947bd6f0e3c65361cf360a65bc059515da852a72ec5cd178100000000000000000000000000000000004f88568c7ede48d7476175f1d2e7ded4312c24934f0d47794705621f8aa8a5072b86cc41e187f4aeeb49bff17a4c9d000000000000000000000000000000000ca6c579e86a68b4041150fbbc36da744d359028993681c34e66c537eb8a0a0d55aeb9b8da7fecb844104dabeb507805000000000000000000000000000000000fec63c57d3d3ca98cd1735b2f59217e163ca53b07b4fabc4415b98377d87e75f0fcc9b51c99a57ff61ca8d0016a206d000000000000000000000000000000000940e9f93f3ccbe74c7be93236a2c440b213a014ed51cb57fa053495c3d6f6c8edc08ba8e10be26e5faa898162d67fe327370e1037b709015e0bf178a41ac55774a813368e11ef7a764eb48abe75dbf500000000000000000000000000000000055e4dd9da22201b5eb64e3b9eff2eab614c48450424491a85c18e05f50659b88e862490edd11ff980b06696b60c35b00000000000000000000000000000000018fab38f58d3d541666bc29b9e94cb3940f1794b2aa851d079b9aaa1cf742b07cd6dc7c985c7e4d7d3fe683bb15d618e000000000000000000000000000000000534de5e1c1181e951b437fd17993e995fd4aa2f6b28fc3612cd4db615de742e12d66c03b9ced538c1c7cde27752c190000000000000000000000000000000000aa8580f1da71f2ae9ec26f3b6466813a40ba5bd3f89ed0d42695d420032540194617fcc2f13e36219fc0cc3886a69c36bf5fb297948e0ddc60ba26e49ef2892ca008e64a22ff2bb21ff70c56112f710000000000000000000000000000000001804ed7677fa3842bdc3eba708bf4fb7f7d4eaf2f1a46193c861595f64196398622df4358b9526f33663138b24fef1310000000000000000000000000000000011fdd7e1d0c5adfbbbaa69ce63c7c54525091289e4dfdfb3de772a8d5a958581cc23933deadcb8856540e2d0dc564dbc0000000000000000000000000000000013fcf17235506fb194e3adaab881c7aba4b87e5aef739e0547b858410e3cdbff0dab1980b1b30a7d03d617179ae545c900000000000000000000000000000000004eed0ca479cc458231ff969ebdd4e33732953e9f5610d78d4753b99c5f8cf73c742387b8e71b9be074fcc67acd71cf6b488b6b63cb8bf34efeedd9f95dff4d3d8c067c0d807bd1e20bd267748275d0000000000000000000000000000000001082b7796d35e387df689bcdda6e0316d343dc907822d1a873adea050374962b164ed27cea0e1b834997f8274e4c5438000000000000000000000000000000000b1905979a90c7a61f4ee2cf3a9f4d6ed4c724c9e216981b8ec34fb9b528018d237771ad620020efc2c3cb104df667cd000000000000000000000000000000000752663e72390108288ef4de3c3ea409c74e7051505b12083c41a2e8937eaadbd8cd61f96f7991722226fdd02dd8d252000000000000000000000000000000000f8e4eb7a3c78b8040a115c42b5d2fc69405f8334e948b8553f444dfef29bf3920892da431cd8394cf61f24e356e95694f661845e91de1c09f581c7612a25bfa0889f77c2add31b493b37d20bcce11070000000000000000000000000000000010884516bb9916084709351ed8768c6105fa451e08d5acb233511254ddbf4e72baf9c43b56b4d7dd129a38f5b34ee5f0000000000000000000000000000000000228fc5fffef746419cc69abb17cdc63ded44892b8c5d02f0c72bc8506a61d15a74ec4ea0e1d78f555ddec07f418539500000000000000000000000000000000048a4192c204b7441e871076d91d4f610c347c2d71cf495ffcb2e2ab808a8c1a549eae96e657d756d9a3b94db2892a2f0000000000000000000000000000000017a94d2472df89104ed96e24d166f922bb852b5ad80f80188fce65b08d39cc3ecf94991c6bec5dc12f9337e7c087db2f8b3bf8d5e529912b1b6e445f592a6d151c6f5d01d3b021a31a2669df4ce02aa3000000000000000000000000000000000f6293fb0e19ec85f43a1a02df9f59ad4fb0e49b16a216ce097b8ec59e781fdf176360d8492e8b77674ae2c0ddb1da70000000000000000000000000000000000e354d09aad68fce6cde40c787ba1e4488999d5b9f3fec25c9994b56bcccaaa746c958bd16ba271485f461b0d4e983200000000000000000000000000000000014fca0851b0bfdf2c69fb346f23b46135d2b7914bb49e297a0c1304d8c2851ff6bd0a0bb364938dd44680fe86cfe12e300000000000000000000000000000000164e23a53103dfa332e5ae09c7c898b95773c20f019d8b794a6b49594040e2e090db6a8047c943885dca95188e89a63b30e1c8f222019b877e66df0b6201b5bfc5b6c10aae340c55e74410a536ffb9b200000000000000000000000000000000146d37241ce4f71017e4423dd0bf907a12c1364ae9fc6dfe535c25e5e99e03ce157cbba2675829b396a69f92668107280000000000000000000000000000000000d5a992f5357615f436d95fa516212812f6811dd1f1921ba4129e84e3d487b6c97520995d8a65f6771dbba9d150c7ab0000000000000000000000000000000007b01f86574a9cb7eb3b9a19b6040055a5c11b13e7071078d16b9ad71f714ed28ad25db9511964b156ee34db22385cdf00000000000000000000000000000000154c29c6e2b21a75b14159b183e625c98a04be1850b22d314225e94b313619f641ead73130c1d6feb85abd8c9e172f6323a258d66f2296fa1c71065cf23c994eb8c6c35d35120d16790fec791ad215fe00000000000000000000000000000000075be2703b8416fa07a7cb6ae8841dcab1e36b0ea24231dba617a2fed3bebf8d952d31f68c149dd17eed136fe37b01880000000000000000000000000000000001156563f1401b731cc23c4be59e69b0e6a0827df4889cd9ef9e11310f679c1603a0d9c9679c29b8dab75ae51f49bfe3000000000000000000000000000000000663faacfaa92fbc095a5dd6b1f2dd141e248f84eff1716ee71bdffd4d28ef1f4c88828e3457e8ebf0daba1416d2d6070000000000000000000000000000000018f2871f5897aad9ff6ac45a9c0e78be8f312f07af5f1dab2bc4705558070abf367f1782af896288a7754da82bf1a5141ef4055b85f37b548dac2b64608d99ca293548bebe1e24355393520c34eda60a0000000000000000000000000000000001618a284286899f501f46c4761c93b68bc8ab3157144e4013e242e1678cba20a2d978ab53b4b43145dd6062748df541000000000000000000000000000000000c25da737368775e41ddcd9c64cf99a824afacb1d404f1ef46ec7fe4ffd89673648c5207551914e6e0d12c57e7d7682c00000000000000000000000000000000097ff49c4872e2da1f6c24fd6dd4667f0bef4eb30fc197d13e8b66adc425e39841dea011d79e4d775106a19ea1978f4c00000000000000000000000000000000147426b7d9b0bdc2be051d8f6cc4249014e1bbc2369bc32eca94684483f50ced2c07be6a320effddcc1ed5cae455fc92212529248c51c95b5b26961f27e6d44ef1c2b9233bb2ed32c3eee79ca6c6eb750000000000000000000000000000000000cf68f7ab056c4689af95b361ee3e3b1c1c48f18b5aa655cce1a2be217010814b3f07dedf6f9a7b835cb13e2afd7136000000000000000000000000000000000dd6d0fb94048dab34410dba4e682f020ed54a655099fbb6f6e94a31511960f0447d7e94143eea88195291b225d11246000000000000000000000000000000001864c6ad3f2f794239a179647d68734e23b3520b79952bda20acf2f5afe1b76bc18e35b852d35a5cf3b02a3ce86f640700000000000000000000000000000000015ea24562d7bc59d813b77b2a4943f9e98842b5a41c0c7026077a02ddfd3d5fecf352d4399f507fb12ada4ac495ddece9888dd839d9b8c236394c44d358f452a4588ae65d24ffe2bd345fc745de9d37", - "Expected": "00000000000000000000000000000000080f0e50f90e001a442965ba7900997fcc89246742590b99add6d90428d3b61516664654bc8fb423f701e85a342a668100000000000000000000000000000000003fa9e84ddd754047649b7cfcf5bd78852abb298b3bbe6575c4c7dbc2e7595499a9f42f379a2463aa74f29e5c73a9040000000000000000000000000000000009e72d3c418726f6400b8cd8b9b649005f3b25ade40cd6f77a0c3cbdbef461e917d4453c9e07ded45301d21df4ec44db0000000000000000000000000000000015a06cac223217602ccfba4f4586cb184994bf08b324bf977dbb3884c394aed0622da7dcf5712970554d73b18e2733c5", - "Name": "matter_g2_multiexp_79", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007340f432a5cd5aff1a1d98c6ea1c94be24de2d15a4e112925586c30979e23a5db93643308d3299e370b1f26bdd09eac00000000000000000000000000000000155027caae88381a60af71b2fa770e58efccfbb7642f5ef6b1591bf77e415eb117ab564aff8d9ebcd576f813b793ad2c000000000000000000000000000000000f604238d1b28f010ce8e45f2fe61d3ea20b902a4debbabcd54ce0ecd44a9540fe2bfe847178656fef0a5fd7e6d012b3000000000000000000000000000000000d7f503ede395dfa5682aadedc98bfe28d3fbfb52f42ecabc9eebc0e0a6616d3671604709f28255f50b62bee641d2711f812322dc2a7d5faa9e4877638faf8492d84e0f4c4c65ca3aadcb7eafed2106400000000000000000000000000000000176e1f9eac4dab0d253c0ff41b7600437b53a5ac5278d544a9620648e0bc4dc56aff0bda973fd1338f77fa174d8b13b90000000000000000000000000000000012919a18343cc166e2dfb92ff07bbf838779ef0479985bb85b3b82f9d0632b3f7a19d387f725a21729a77c58dd4d1d1d0000000000000000000000000000000017eb269ed75fe0403021ce70505bb60a711c91c551931605bb2a0773fafa07aeb47cdda382c0aa64f40f5e6e0e6bc77d000000000000000000000000000000000bed8ca999a4691646124a140fcc17dec02b74bd28b599c807abcaaff13bff65aff3892897652cd33b4ba5e4cc0198a9c1f6d538c5b4ae15c84581f8fd4c61160ed395816557fde197e1a013ba41ba0f000000000000000000000000000000001344d6902f5fdbb59a4c975847db0191beac284eb17cd92360e59f42cd7796cf2aa282bbd4cb074c4ee10b489ee3f2f60000000000000000000000000000000002158eb3429d0532792532fcceecc404e95a879be68b3685ae94016ca3762438b3320553ab6d5fbda3a0b615a04d996f00000000000000000000000000000000118f6fd8f60edf7088a0b4b49338bfcfc9c38be230460d7516f317b27c07600f504c8cc87acb0c95515c3acdc1b125ce0000000000000000000000000000000014eb422d44ec6931ac9860a6a017a907e8ed76de91bb7557e818dbacb19fb51457a1f45cca91f1d1d75a3567a3375b5cf2f6a4713eb692f7667fba2a3dc35363c3ba163519d95757daddefae11a95853000000000000000000000000000000000f2c72c53fdb1b0cd13a1f20407c64c46e4a0e461778b0e2d48c4f20be7c655c639b38f758fa9199b8395f706df10e7a0000000000000000000000000000000016e6c75cdfbc20c5dbc2dbd1caa66be92911264d407ce3c689ef3ae1dca44dffacb4c0d8a78ac959e47ac5c454f607bc0000000000000000000000000000000011c5d80d52e864b0a46fb48488f497fb85f51ac040c77b1d01336860b972858c0a6e59914112f6cd6c1612c604d26f56000000000000000000000000000000001136aa7eb63d6f85d665d0539975a9a51a9a3f5bd8731910c32130b1ec8b07c39eb42e4f61e7d22bed933d9fce1810581022e50c3fe7b2a65aab79de6d9e47c457d197e145592dd0611b1dc39941513b000000000000000000000000000000001306612f5119d33f177b8804443d14d04c8e059e28f63aa10ac6a1b25975327f378d5d24f0236e05849f07e99af93ae20000000000000000000000000000000017340f8887292264d498f84fce4af83573aa6cf1d57d99d364f2b84e1734fa4f9a1e07ddc81a2135ad5f5e0ed2989585000000000000000000000000000000000f65073250019ea69339379aacbeae7520c1ae10c8912ff827b702bdab2e15404cfc939389587364d811054b7d9f2b350000000000000000000000000000000019742f83ba0c9d36aa1d595fcedc3cdfa6c6f08579e66b8956fb32ac03530114ed4266738c57175e7a10313c8dd42deab80011c7a4aa905d4db6d4f6ae46eac9eb8bb18613d4ac5e5567990d7e8fdd96000000000000000000000000000000000b2513f906db531d052e8e6f1cb8d7d3c41c7ec3158b370268d1de204ed8fe7618b64ae35029d1718153b5bdb8439dd90000000000000000000000000000000001664c367a2d4170f463c90351cb321608e2a49fca6f3258bf10d32c39747084cf9d2c38d5241888aaad97985cb09a450000000000000000000000000000000014de15b86461cda9f1be69f43a9ceadfe7b7d1548a206f3237d93c7c01ee554c4245fb73827ed0ab72b99a62215faeae000000000000000000000000000000000b25e458522be9fbdde4554b1a0d9af157aeb7d3ec1f89185b193c0429125dafa554d7a531ef9502d443a26112b940b8f397789685a736375ead2312874174795586e12b230669a90d072fa636128c7d0000000000000000000000000000000006862c0b0e3d7bc4507bea1df82080745aff21b7549b372085776be2f88aedd4cff00ab8258aa21e63340963bd0d937b0000000000000000000000000000000017199c5ec3a2dbc1f1e8d74648cf8da247e35cb07df22629b3845274d29e473819a31bc344f2a2bd6c790530cfcc0126000000000000000000000000000000000e7fd1ff41d86a02014229c5085c886988dfaddcb60f5c7c81063e8289aba846337d61bdde57e276fe6c65bdfb48751f0000000000000000000000000000000010efa6aaf7650edb0c74d30125e36cb67cffd1c7f57932d92ab4aaf36f8d9245d7c75dc2b3bc8f3f328589b16e26230e28e325fea39d61269c576626984f85ea43cd683b08c3ce111aac0005adda39c5000000000000000000000000000000000935de4b16f5f9c0accee77b5820cf36c24aad9953d40a2409b7e6040f09f85da7d2252843f9f8005316146caae539800000000000000000000000000000000008a8c542111951b32bb0b50f7631f8938d22e298193edffefa3e0f5c861ac8205ea9b865f9420ad74cd22b37c5cb56200000000000000000000000000000000012ddd660879a1f52ae6284e14f2ae6ea381ff3f321458cb76bfa566b04ae19f3793468d0aab652a82671be74332a3b7a0000000000000000000000000000000005eb148c35732f7ababc73861b71fe4ea5e25bcdd675e975fadd0a9e0fc54e175b2e39dcf0323f4a9802a68baecd25df3cfd9bc41303803a0b4edd121b818a126bece309dfee4133aa5314cb8a91d08d000000000000000000000000000000000bc351eebfd3f3c332268055af1655c8729cea44eaae803607198cf747280adc0d3dedba137828834af3e7179ccff4c3000000000000000000000000000000000d8a6cca17e1c6ceace7c0ab1333ba76ed6c3b114bf99ff80127c6a17eb0585bf6fcce871deb7385e9a8896a21c065ba0000000000000000000000000000000013222db97e31e28946adecda10c9ccc9aa9fce33e0aca51d6483d2f0c5bc3f33994ad516215f8333e22167164ef5459500000000000000000000000000000000144d3707b1898d35c65ae2c89b1570971a9494e8bd23df835f565059554eb7b5cb66a6eec890058316aef43d6c6ff55c8e08fed30e422868f37c422d1efdcc93912d55b0a731479af863dca4705e0c5000000000000000000000000000000000138da93a9a4948d41a6fc6d057a217faf5efad863b45ae8eab311360c033362213edb0ff90bad6c95f60b8e1131336e6000000000000000000000000000000000f41766d9b57b3210d315a2b8f90aabe591c1de6037ec79c0d72a283f0ac3094436bb97b82b7ad12ff4f471a41227bb50000000000000000000000000000000009aa4f5b674782b7adce6bf75ad676480f96a58d68dd7ef8d1fa488cfab794f06e7754e9315430189eed265913db8b300000000000000000000000000000000004e2a4a48f02079c0ed50c1daa91b1216af481a982c7aa64d8ba90449ed886cdeddd0cc08f1f8764f7f8c5988fe677f5674ecdf795b48d62f0db0f9cce057fe570d15c78f2eb7a77b66e4895a45804880000000000000000000000000000000019c927bbffd96aeb9342666e1974d30f9dc215e8eca41c24244c63c106331ddad20d64c79faf8c5baa45cd30b561e167000000000000000000000000000000000523f063de96c9b77bfe5c5045a007e155b45dbe68c5f1162884f1d942bb385bd34c2a37e5e67e6dae4a23d600d75d1f000000000000000000000000000000000c221006f5bfc8baf43826258d0588d7c0fc345d68de1add1693bb897959c2cfdbb9c165e82c0c787529cd7be85afbc50000000000000000000000000000000004218e3d52b42a4504611929f94024326f38e78bba2aba105db3ffb4a51f8906b060ce2302e22ded60714d652a234c1f288fc80d07393f629ef2732879332a253b49d26ca7b2bef7cc49ee40530b2b3400000000000000000000000000000000189e5063a36b0edd736bcd9f997f4b08c62d33b27560e2e2b7b40039e7c63b75757f23746e70a330110d975ca683941300000000000000000000000000000000013393485ae494b1f1467cac9a8840c695d619aa1a78c40674038c053f264c1e20481f2005abc7f0545346f5a982d05e0000000000000000000000000000000003f2be501504f4d37e12acdc54b3280671ca0762a063fd3bc04473ed5a051cae3767044c002b7ed1abe88b2143af08750000000000000000000000000000000009d5952af88514996336e1ff19409e3e4eb3079f6dea22f9738f4a331ce842b151e0b842b68cddc10a711afa6d3242b256e69f4ce8fbd8f86f546fd6d129f9760edce7c5e178dffaf987bf565e9bb7e9000000000000000000000000000000000a79444c673e630f46bbc5a9e06e8c023978a78e3c58d72910a04c3733ad873c0d0de61448076b2fd3764cc17d86d94f00000000000000000000000000000000110cfd215d67d4a091578203855fa0e85feb4dfd0076fbfad20bd092fb91b528a4117850955f5fb6568fc5844e17bbfc0000000000000000000000000000000012ece0577512182c50dbb4a485256e705410108d9ba9c8d57780d49e2e25a0f89ed1fe917797b902aafcb8f7d98fe931000000000000000000000000000000000217cf1dffac7ae162181d43ef12e3e88da4840f1573d7ffa271f64d8d54861099be37b644e96e650dc613975d8a00a4ab40e86212189e6f5925df810141c132eab20c123166cd8d3c6f40f5dcf1b1cd0000000000000000000000000000000010bec428b2865aa7c077c168dc28dc549481c6f8367a5b84cbbad661b0225cf0fda3e840d96c4e4efc36c20d48f23d5d000000000000000000000000000000000ded3a1e9e2eded0a11211a217f9355070361f0a5887a7e19c74edc8768000311cb9dd8513977ecfb45416cda0908cca000000000000000000000000000000000b99ffddc79e825f0b73f2d0229d66e51624d854d00bdee5aa7a884dcafa1888963e2a2149db0f6e40ce3c67941a391000000000000000000000000000000000147618970c71965684bdf0d6cbe1de189bd23bddb2b861c9636efdcb7a96dff27bb1ac70485b562e78485a1e8e56531cb96a5b6129c58113bca713e6905c026c0bfdb6d679c203cbe2b256b0a49ecece0000000000000000000000000000000001a402aba8fb28dd37f1be11fca037baa99a6b57188ccab66208a50bb6967dcacd1943cca73e34f6b2e2f72407103a73000000000000000000000000000000000c0bd64d043fa4e3ea566cb84f9139091891231ff500b67e5fd451805f79003f6303352a4f0c236063d60d9088fae88c0000000000000000000000000000000002861fa7d0222711ffcadac86e7b9e7b494f5561c22544bd0876fb6e1b2e680d0f7074c2800312cb233de2412ccbbc8600000000000000000000000000000000015945f0c83e738a17cb1283d08d63ecf12a7272bc62812006ed78254bfc45ca7c42306cb79bb16ed17bea600a4d62b5d9d8147c4453cdeed971242d316e350abead3dd08e93ee54738a4a5aed23affb0000000000000000000000000000000002268793f6872f7715d802c0d96f3b3d850249d8e70aaa97f19793d2c92e7cef384aaac603eb51525c7ceccdd0211fc40000000000000000000000000000000002507d680a2db16746810e966d1ba5547ac98d08c8402aed0859203e6dae0cbd87a9ddcc05119c1ca08fca2fd733882200000000000000000000000000000000192426b6438b2abc7386599afbe09081ed4908fbeb807a65bcb7c6676aa76e5e0c2c87612cd109cb124c73b9c8e0591a0000000000000000000000000000000017f125a2ef5246e7a19e1b2741b31b9224511ffefe63ccfffaef1b7949e88af573e267d6c7617ea97bbaee6d50eef67e1ba8e52986d3bb0421eb53b18ca8c21b9f7e631f16b99ec56748baeb541b32e5", - "Expected": "0000000000000000000000000000000018c2f533f464f9768308a56209711cf9b6653e8d38591d782ae2374905f99f75c0d42c63af4b534056c28599a9da874400000000000000000000000000000000071d4d708f00875545f381e164f77183e14faab599e472b2857c15091254ddaf5c2e9df809875336f92ebcf5b7628da500000000000000000000000000000000099b207cf6ed022289c27393c32d0b83aed6c7b57323e746374c1a8e2ade071a5293168e72f7aab82f6c2e39b97b03830000000000000000000000000000000005dada01b4dfb6a52d998210a67ccedc11d6aca2405e0836280e2f7c8fd7c8dd271c815a2e9ea1dba6f1ab0d6e89d756", - "Name": "matter_g2_multiexp_80", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000195d3f440857011bf9b764ff270b8ba1d9d13daf48933e49c12ea20d335b58bcbef1353d9698a7e795b4370ee385f12b000000000000000000000000000000000716c151efc6e611b5b15c749eaf02816a86e267428750741b167404a21116f2025d0d07c447b9c7bee8edcc2c7b76d30000000000000000000000000000000012ba0bf62b35327111d09b402db2b75b2e835cbe581638af2fdd6d06034774533e6501be3de84e7075e4184e11fd81a8000000000000000000000000000000000329b14859d004c146047b03870371f53936e078ddc69294ff1fd6f42cf2a354a921e5f2e5c125c454e20af97dcf769e7d39b55aadd47afa3cd35cb85a89e729ca236ada965b99f64ab302a84952babd00000000000000000000000000000000042286dd205ac86fdec3fee779059e2ad59adb62505f7b78606c128244b031c53dc40ebc2f5afdba348892d5ef4c10e7000000000000000000000000000000000f960010d4818846b3a0291c6fe1aa53bf0eafbc0e0968e3ee82324452a7c1a8041c06b4db9cd36a07c119c9fd2f9038000000000000000000000000000000001876da0dca72869708b8ff9ea0b74ad6be25ba82ccc76660246413a04344f2b72e5a7f6fddb58e9dc0bfaa6b33a5fadf000000000000000000000000000000001538ad1673f117493d998941d9356fb9907f70c279bde8ae8813b9c7b371344456f8e67cf02bf3401ee06d55604cadf9c41ece17a6d8b4a22994227b37a9d73e17a88859683afd5d226e113246e70cb1000000000000000000000000000000000d91319b4a5e047ffc8a68e10c34b2b90e7f3f08f9e3ec53ed12bba5f66c168c20c6583ba2016f0137caed834845f7470000000000000000000000000000000018d5542919674d2fc32430175405d806ae4abe3e1236df2188bf4c9ddf66c0974036e28414890212ff8dad244d11e3c700000000000000000000000000000000160b128f1ffeb97edf0e62dff85e3f90fa48567ab777a7937a2c0e4659df180fae4565107c2236a5f2808e42a03a4ab40000000000000000000000000000000003ee74d214ec491331fb9db8243e75570daba9feb587671496cea4b480d80ee162c6294c082203534bee450c384f645e69700dfa3b6e5fba735d1fec3b3adc90719ec301c406ac40673f4e5677da3227000000000000000000000000000000001951afa33800a366944c43bb42b8c5c8beb9ea2e1cead8b84e0f94af51e4a156d9454c0f08d1b13c692c41cc480fdefb00000000000000000000000000000000077f4543fadad6f2f8ae8d5d98f64965bf9626971e7efef5221cb4d95d51b8764324cf4a11d0ff5330d58df70cb79d92000000000000000000000000000000000417251cd0c1b32505377e51bb30ac8a8a3c059644b9ddb5a058b3c6e1110e1c71ee19f549b15090144dcf4668d0d50100000000000000000000000000000000052133be345adc562238c4ecbaf76ca4159fc11ff563ab393317b03065ab668e7df401831baf7027f0577f5791b1ca3019e8eed297661c06c92075629e163e80a08835254f7af8c0f179400be114ba7b00000000000000000000000000000000067bd52b7a3193d31a4f1ffb76432c8d4108442616f17056d310fbfee2ffaade9437e2bdb8425cf83233f0c632efc1170000000000000000000000000000000011b045d6eebe1bc8218b696b5e81e78db78eadf1b5d987060c1bdd73aa65666f77e1d6bb6f3d939d64cb3e6bda08994c0000000000000000000000000000000016eb5ea5067413b72632f5300efbe0d01a284b2a59b68d0333c269da9302bf0f0cdc923acb27e51bbbbc1d4086e6b06a000000000000000000000000000000000ff37b8812963d9efaa1e6deb5cfd34eec70620fdb65808739295a819e03ebcc8f501b8194d0b3c72717fc922b785194199ca6fb7f6df8a2e72971c5738ad75d84935e922587acf3a6b6debf3c37bb5e00000000000000000000000000000000149b5e0df255281c1b518427094cc0903fe89eac9a6dcdc379b8ca30f3696d89824c201601fc4b0795a3c859a82893170000000000000000000000000000000016ee9e7d957f439d078f3c5da98d114a1b5bc4da9c17e117e1f540dcbf83a349bba94def4b87b63247f190e3b5813cb00000000000000000000000000000000005d4f56bea105be4bf1fcaf4f25df30f85968d59e60b1c438c28ea0f480851f5ab9c05a7ca6677e6f12c7dd3ed67c2e0000000000000000000000000000000000dc0e87ca5a8b339b485ff3da2b9854a07e9663c43344dfb5ecf3ea055eadf67405c43013e15367fbaa55f1bd8e222f98159c6b98bce6ed31c30957280d8f7820e9376093d1ec9ac68ce0777d02b084b000000000000000000000000000000000b0575fe2adc9ad66209cb2191efc2946672e4e81b96d50493d2125d9c83165f0c4d3f714539eecef9de0706cc20da9b000000000000000000000000000000001511649f0cb6b86111d2830812231ad37df5500d7ce1086241591dc3cf40b30f1c53dda3133b2f7fff253c94d5eb98720000000000000000000000000000000005b15e4e32f4f4e46c1560792a9973f6ad63f5176694734f379375f16a08c162a4a820385d3ea6c191bd87fea4f5c8cb00000000000000000000000000000000089218403fef08dcc6e679b49a74557dafed3278d41ff36a9801db091b91de0d46d779a40574fa4a3f2baaa1a14be098ef1bc580e0b52b10b049f07d5115a60ba96d14a39e48ddee3c219f11c3b2a82a0000000000000000000000000000000001c35a3fdea92b28c9ab4bd9ea592b998853a73be844b9dcb500ed6704bbf3ca4ed4216dc24b50254b6ca75c4ca3e7fc000000000000000000000000000000001815292d2a365dd7f41ecf3f9a89e040bab717241cefb3155a097eb9885d64fa55f5de7023f2ecfd33f483ff304666520000000000000000000000000000000013df522c72805b890aef97864ec6769f569504fca2d6a6beae97f80dc92643f8014daf3dafc0040dd7b985c0d9b2c462000000000000000000000000000000001155ad4373a8304fa6301cf48b4ace135d6a0c08cb06d624f42f88073e43612ced3cc37235422171b43af2b4ebbd5662d06f6ed682c56611fd060ed2b3b1dc48974769ed6dc504ca3e0b9f68b77e63c5000000000000000000000000000000000bb9afedf7417ca31beb96486b024af13c06007585d785efd1e78444daa9bc3c03e1d64b560e8d6a18ccf77a8c3c8d05000000000000000000000000000000001652d3adcf1612e487a9ca198801afb9ec30267148502684c2b91c05ebf6c48e2ce33f9c0a986daab81d5359ec1b503c000000000000000000000000000000000baf3d34bf4a78e3b9dfa637c6392c7f4d7ad0ec315d10748784b5b60221bd9da0f4b75c57c139ac2db329e270d559de0000000000000000000000000000000000c30e553fa2324d552bdbc7d2dc86531340c4894495ee9a38b64f5bb6f92314021a2a00c4bcd8837e55a0ae2676a9b761d7b314ae9d9e78f628ec5a207d12e2dcb690688d256fe46e0affdfcc9775ae00000000000000000000000000000000159a1e4e87c35aaaeacdf21efbf8ed99fd6a2ddd7e990c12407b1417edaf185b8f1df9bafbddfaf3d581b5d97d7718300000000000000000000000000000000012239ef7b1e1009c81098aa4aaad8ee9e003530db5afd49867aec47f46d5e29d44b5e62d80d9e832937a299633e863c80000000000000000000000000000000016af6f74392461a9294d9f848508651ca5c0cb50494ee7c6a334bd770580b924a17beb7824b489e7e101ccd50aa0d5cf000000000000000000000000000000001912a0f54ba4fbecaa55c150ae93455e1db6b238c032fa7992bc8456f183c09b6005dd6398a77ab91cf547919ce7485b03a0c47621401fc20d2c78f7e30814de9a6f838d4328a5b5be628b833c31a6fd000000000000000000000000000000000cf1cf7a09a12f51d10059425042ef8e140718ff11d2f17897a0156034f73ed29496d93b8695cdf609280d319c9bb742000000000000000000000000000000000b2c4d26fa1eb72eed1a24f27229d2675e0c6f91e3a4eba7d34b0fc1bf5a9b4eb49c3492d9586669abaf25a656e1f95d0000000000000000000000000000000012c5c83a03087b2449b71e9037591fa265d710ff6d869bfa18ac37cbdcc93024f673128db3dbad9e3517501af12f2540000000000000000000000000000000000ffe5824245e43953e3d0adcd5fdc1a97ffc87f8c5473fdb0fed57000fd126a9925ba7415c698248c51c1f3e12b270d5e4ac6a5e740e073c5ef8af389e70c2cb8ee8c4c04c2ab4c48c579e83e181005b00000000000000000000000000000000036aa888e40882b2d6ac71d66c88543e32b4a0a7c959eec560e3d26114d8aeca63fd87dcbb3171622c989a6c7a204ac60000000000000000000000000000000006a5e552e6d2dc95ab8636a8be16bc79572b47860bb88934bf04c195ec01fd71eb91e45f24c58bc2812ed5fa10c8dd7d0000000000000000000000000000000015fa3ffcbd4e562a4bc29975cf8c1eedf442e37374fc87128e6f68bcdf6e996f6f054e0b8c608e651753de96655b2c100000000000000000000000000000000019bba7c0b170dfc1f8fdbf7a2e09ca0c4027a6aa6930d15dc2772a0f20e5e56f0d11644094dc866595f801ba5552e6c4c1e20d8003fec60f68c03942185fed934ebc197c2863174442d1a1c8d1424d31000000000000000000000000000000000341f46ec06a8def4f044328bcdaa308798469c767d10e5db34b0ffb6f550421c67c6fab7b63cbc7504e55847cee419e0000000000000000000000000000000006952e5f791c37dfebcfe69cdef196dff66563b29e94927e3ab34365773b93e72251a63af4ff294af88d45fe0899a2c3000000000000000000000000000000000874dfe75b31450e99dea063c090e32d24fbff9b681b64a9dca5f967f82003005b003d17eb869bd3b37d4a412bcb28fb0000000000000000000000000000000014203b69e8af4e25232777f503d5e82d6121256fafdff1b037f65d5aaad0f09ce882151d6bb4705328400f00089dcc7a7713ea72a2ee99442232472ab3dea9307a02fa1279129d994af5588af4fe7af4000000000000000000000000000000001403fa3f418107e0bf7f3f4bfcf621812d32b1b744ab5a4c37b5cf946a5e5dabd675c2b70bd355590a9883436c5e32dd00000000000000000000000000000000069e006f168bed4439fb46db9ba4f279f72ed608c12a05eed172608693f42cb1f04aaa54191f4b0b35f967bf03d0e63b0000000000000000000000000000000003f9ce029f6fe605802de64701ccdf52bf4aa299400a6e1c36f5a1f9173bc11a38e7628f123fdcae01d2b260f77c577c0000000000000000000000000000000009c9732809f60635115cb479c80457c6cd8dad092111d663c0cda0da1fa71c9bd6795ad013d2efaa4599c8ac5c88e5f26f128420cf6ab4616a05b287191105f25c7212f2c39c3230fa56bc27cd06ebfd00000000000000000000000000000000115e08d8e4dff7adcfe46a416625be0ac26ea2d7900f5fed497809a6d46e7faa5b47c52ab3bbeb9fb16d82b549707ed6000000000000000000000000000000000dd1b31446e44f64ea5046dca5174ae854f6bb5d95886fb95aa136d432f1a8c03ef1a5f9320f89c82f764049a7f678a40000000000000000000000000000000014879783c07e6986cd393fa1e0ca8a7e23b2c9efa595229fc0b6a11b9c232ba33e92962a1087fe2ba0532d7b541827900000000000000000000000000000000013dc6e2bdb2801333e7f914b99f30b40125fa1ebd49b141d88a8c090b15ec3250a13812a19c3c0751a4e5ed100a6f0ba12bacb3419c34369dbfd1c968334f76bc50885028758a975cc812a04e6feabd6000000000000000000000000000000000a2cceef36ec78dc702b6731dbaf8cea1dc2b41fee1b235673c6941729bc5631e69ff37900479391a4d10b300fbf3eb40000000000000000000000000000000002f4881fd626f4ac434bc1e59716e5e5ee14dcb9adca4d639ebc9d86e323d274ad8ec0a4b1e6ff92e1fe7928d48924b000000000000000000000000000000000174cac80e7bc63989f58759e123513b611e9849b44d43a362f2eb84421ad008f3ae9e9f0f233e49fc8e10c1824ba948200000000000000000000000000000000143641099c8a6c8153dc8ce74debe795dd6c4487e8234f164f9f8dcdea6a53619c04a8fac215421f985557b5b956c20a5b00f26af6f59620c7130a6d12cf2091b5f52a6b638484fc1f242dc1773be256", - "Expected": "0000000000000000000000000000000009807ffe8fa881b235b1181d2d3f147dbe21042524fb0c0b4c90fb122d160c7b895034ab32e20324dfca564ca6e3183c0000000000000000000000000000000010f6da88525da3e86ee56cd5514a436e3ce4128e437a876be130a70c42444a05ac269326c84dca532ca2e546860027c00000000000000000000000000000000011396a7317918841ba171ea46bbddc9bb5a08db7c82b90008c6982b4b79a4dafc151081bbdb7b9fb79784e603e15eb9e00000000000000000000000000000000070b8580f303b83c643a484dd031b780ff4ca2ec805d8c538a0b0c791cc7f8163654f5e5a41776a8681500a6690e24a4", - "Name": "matter_g2_multiexp_81", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f38906bd058e4d32403fc3d39fa57bf49c0da65ef42fb129332b91c184185de4f9f0bfe8908a44833ff4ac4d65b88180000000000000000000000000000000014ea6fffa6dc462463c15feace841697698bc521f608ed0d16be5097bf42aefcd1f73182f37b6279f989e9668a8076d1000000000000000000000000000000000f56d296323177ce53c6977fb60e445278e59ed1cf92e3f68c570eb7a9e5f8afbec5e2ef64674bbb54d7016c829f72750000000000000000000000000000000001b29012ff3460cbe4a07bdc65885718f217cf177866823a7cbeae18bda67f65913ea20bb69e0ffb31bd82f19862113dacc5a8ec806f2f273120457865582b08697904a2c6510bfe9ea21eaf682fa4fd000000000000000000000000000000000a4126bff91ada057ceb9a75d577120c7ac8c9ba62151602414364cf88a3e12dfac90b5590db3e40c16163177ad4e7520000000000000000000000000000000004a3768d326c4ebcd5ffed89341e8d04f89e674f3f2aded3205a7193e11c20115b3c4d595b959d6e39a03d76f6b5925b0000000000000000000000000000000006e0ae4a9c45bb69c3a1c65e26e4869f2eb18fefe584e4598ba99c0044e8d911145a5db3f57194ceb6201e7eab9a81b20000000000000000000000000000000005be2ba6b147f3f2052c4877c90ca364427c6721ab64dd35e89f14f3179564d8812b9013e3e3db22f69afd739229682b98c15a259b4dbb8c300a39f0af558a9827112f6b4c5eae3d43bbfe057eb113cf0000000000000000000000000000000004c36cf955fc81bdba4ea8d2ecf934adaa57fa4073199f77bd0428d3ef80a7d7102179d4a44ef0de887bcb3ae915408900000000000000000000000000000000138bd3ec7a1b6fb65d1df6bc1d2ada35aa52b06729c10b5d45b9bb7cbbdf41677942b99eb9c2d32e3e73da7d5f9cfed40000000000000000000000000000000000b0291ca10245e2f7a963fa07ec62b15f6bf9e7a5a7839840ebcbe538dfecaf2114c7864a16564a5b3c85c15d97fb7a000000000000000000000000000000000b436e912b8a71cf8050d10d59017eca6e494e5440f02d2816924ac9cc2034bedb1cce6eff5c42f3dc57a74cf1b51cc0a0e68bdc97fd642581f7e62ecf134df2c05570713c96fa733d3db96ace88f0f0000000000000000000000000000000000c105ac7475ed9517a0b07f25a030a5616952d817f3893181e352907c7cf4ec9f5f3006e37b1da97e9cae4a1213584e20000000000000000000000000000000002c112c18268934823d5946d2322d0faec497d8e18736da91d2af744d90f74136c49370a4b43952152c62820d25e52ee000000000000000000000000000000000fe2818a397d70543e752e7022f12bab10f1b1289cee61a0230d545296ec872e34d8df6edf7ce9980f3c153e6e51d96d000000000000000000000000000000000f479e6a52bfaab3a31aa9a461adbec8a390daa8eb6273f9e425eeed764a6dbad44d12778bb888aa5808df272edde401e5512cac411cd103fcd7497fdf47d1221999bcecdba30467f06ec356483484fe00000000000000000000000000000000016106cb42ffc41d5b23bc5b06001473bdfe556d375fac6a0cb0a12494e9c02ca2dd6133356846e1759a2c485faf5e890000000000000000000000000000000003cec25b0f5d1db0ead5319d6dd15517657d1fec442facda4335ae0bbeff606fa9caa6a4c00445001180aaeef895d7fd0000000000000000000000000000000016ce3573fbe27a8d23b3ebd22aec989d61fbd0e41a519c5e2f1d650f2ad73adcfc8c840fb12bce83b722a0cc69164e21000000000000000000000000000000001434d13d44fd8dcf776c2a045734dff7c09ded31c9e3a4b5e765cf26fbfea4cbb4ac15c06599012a7f2cd572bfafd78ba32f6861298bcfd4668653544b4551d7357d64f733365a5f08ebf297a09fd4ca0000000000000000000000000000000019923ffba0d08ebf1bd43393142d61022430356081c18e37804172082c7ace987ece2594f4852e84604a77235c7795e000000000000000000000000000000000123acf9e1a86846ae27d5fc0358afa34fe9d6b68232c9ebf2d47cc169779c4bd24f225ad30886fdf68166adfd9898abf000000000000000000000000000000000a6061d4cef29d1e3535d54a2e36373e2c16f91543f53e1aca94c4abdabc663049673f2327ea8bb574244d7f5c99e981000000000000000000000000000000000b1f3e1d43575a74584ec7a3280f8b7196f9b99b5e911ed33ba6bde1188c82d906f0f8e6fc2b285fefa0ce59116e449524301fc5c3ab842d7f6a278fcd32249f1daf86a31dd254ab9a21941fffca98a1000000000000000000000000000000000373d36dd0fac76a0fc46ba5da279ca3be5a1f8d799570004e429256787110d4fb746f65a8527d0ba681a81b9980bd5c00000000000000000000000000000000057933c2b3e482ae026159211c4742264f7e890efbaeb6e14f3bf66c80923289af095dc97b751a117e181ef917d049b000000000000000000000000000000000068816ad2369bb57b3430c657284858d3736c327284e7410b61ed444786bcb34a66db9c16aca583aa9722aa8d7975b440000000000000000000000000000000007fcd7dbc062d28f6ef906f6a455337e517e1d6e6c02c7c0b2b2685b79f56ca3436c1bfa0ab96e4a5eb0c2e2c321c0dc17a920aef58100de67c482ae1fabf7ec87cf3447bde1e19d9aaff825695706740000000000000000000000000000000007bb0ab060cc12002e043724c0fd0c8bad30e08b65ba9f2fe5d09d18cac4bb2d50e29ee14590ca7bfc505f3ee3d4f93d000000000000000000000000000000000e680653d29eb5d90f21802f543eac3102a1de6d2a5bc943a53dd9b80bdcaa6951ced2eae5e2a25448b40468f1923ebc000000000000000000000000000000000b7494b494019e3ef36d5c620ac56483fc6b1c8fe5c6f67537b19f56ef01db327812095fdf805d3dfe678a3ed8bb6226000000000000000000000000000000000291e5b98ecaf7aef0374647d28fb9f8785a64d9165de407d062403047da14d4ecd19fad8575070b278608e16b71d387d76d5eebc3d099448ce4a8ea6dec047b0f062c6361ddb9e95ec898442423a31800000000000000000000000000000000186536e3ae3edd9cc6bc24fda6589ed26e72e06121e97e1ead65b200fa0578c6e53d1154dc7b14e7eccc3a53237685060000000000000000000000000000000012fefaf6c76ae7197b99571e41a19b14846fc4499e8e964ff750e7c3ffef6ab3dc19eeb42c5f6ba44a573bca7a15166b000000000000000000000000000000000a135db813a44a21174cea3a0b34fb49f273877203ccb66bce44b2b58794818d8bc1df27544ecbf780823467e2e4ee6b0000000000000000000000000000000009b08f70cdf4e349e1a73935de9fb2ad9f4feb8cf5f835be78383fda2af94d81af253ebce08cef825764151d5713ae60cd4cc1453dec7ae335db989886fc0964ee73e12bab69ce1f1458d1416471176a0000000000000000000000000000000007976df2d47c14374e554401c4d3330bbf6f1e6b8fafcea1e1974af61e8ebf493dc0473d34b30b0b1cbee082550d85c200000000000000000000000000000000177cd64db8334dccb17fb207e467e5b09e891b05df7658d9b439e3cb72bf3e0a70e84f96fb5e448f33c003c279cb38d800000000000000000000000000000000094d739a02b8ea6ff8113019597f41df4728b270770edc5e68b1f5c32775f0c706e3f31c0a82059c1ee150b89097376a0000000000000000000000000000000006ed888aa4bdbee94ec67500e30d654071774fe22464dd5b900fdc17b445754293504b10d044aac8fa0c289f0b2d9dce6d207c08e51d64a9a47f5353faac77fbb184e1123d38e39bbada85534cbcd3150000000000000000000000000000000014a16b856b04ac4b687c79f2b4e1dd6d45db25b382e0ba6687afac648c9b6384cdcfa89812f1a726bb4d1c22ebaa6668000000000000000000000000000000000764088e337df6db30ce8aa23aefd91d9e35be911c9e89ac62a1e06c3d06e28efac256490400fac4490f595cd03c127e000000000000000000000000000000000894856fa1c8488fce182a9c7749f7953e6a73879b6e743fdb8c780275447122f512806fa83d5ad528f8f61598ed01d20000000000000000000000000000000002b33bfd09e0ff452c3336bde08df0102162488bc83c27052447a1e5d16c9c68bc529f96ee3787a26d2009f22a1246342e1910b704d39b6a64cc7a44e44ba3e8b7e64ddfa90dfa6b5ef571f9ff7d7f0b00000000000000000000000000000000133e2d092352d3ecef5b67a09c2be268fcd4fe1f7360a8ce3ef5f33bf689242961a140d9c8afcc1e2fab3ad4e3dba49d00000000000000000000000000000000101eb285f0c462a22406846d82ca6a278520b65132d2008b124f6647a642c221b0c3bbd4a0abe8af7417e7aefb81b5b20000000000000000000000000000000010958cbc317f1186aab69ac24be87647b8013b678b0eabc6270167bdc9c0cefbaf4d9a34dc41524b709f1b881e6bfa34000000000000000000000000000000000d92c47257fd0c4d6baa4c81efe65852840479b9bfda5cc06b253f167069ca7367924c0c67d6497a1e9abcce7d0ce9502eda0eb154d5f9b0e25a828c6f77541701004cd0293c61ae4d36aa3038d0f1840000000000000000000000000000000014ad0f935ba129b47ecaad63b9dda44e7ef7933f182a0f5226141c8f0ede026ca2f11db7f4924b5c582461688dad6359000000000000000000000000000000001453716381f13bf6ebf8fff2ed7bcb90f7beb44269008af5880a355dd03de5c84c14f5aaf69fda043b422aab0c694784000000000000000000000000000000000e983c9e9b799eccfdb56444d31948067d46adf275d7f39a70aaa8bfd0fe1b83632c23d87f4e993c8191901e9a607217000000000000000000000000000000000267c8b8c5e09b59277736caad12ec6986f206d1c1f48023356d8bc877a594c8bbd98981cec6382bf9bdb9a5fa38275ecaf6dcd51a851eb200c7f5fc3e106ac5ffc432f756b942b1b9a5dde31cb2a3760000000000000000000000000000000002e28c245e71a7f6206427ee512f3250612785ce29b369682fbf767d06ac08f91de8ac9f82951574cce46cee1aa757720000000000000000000000000000000019b0dc35eacd961e0ca7d54a0e37c4ace37eb0200d5489316f3371412717c57c8f17c1379721f4dd67b3fde24f50d4cd0000000000000000000000000000000013b9741f7a32e5e5b1ae5400e32dd6fcc1fd43b68df54ade57c934720b1289a51deae77b1726e1955b6430f37928e2bf000000000000000000000000000000000693980b347ed7ee6cd93f565c87efb36fb304d7e9ae24e2b9f902bfc962b6c7fbab93287147f5ac892db2a709c9ab42106d4a893a68b7fcb8be96faedef65181c239dc2cd752c85ae7800ca84fc2dfd000000000000000000000000000000000ad6b7cfc6cefa5783093b7d700360b354d0698d27ecefb7d5928ac5bd6c299e4001474d205cf3b85a32c600ddaf1a360000000000000000000000000000000017172c3d5acf59b70b340fc703e9b7801aeb4857ffbe7a9d5daa0f32ad80d1c0ef2f0b3b7d1fd83a757c076872425fc7000000000000000000000000000000001291f55fa7d14b14c578d57178cc707cabcdc4bfb444cecabda271cbfba2ab361947d045ed46d9edbd215fa4c8164e56000000000000000000000000000000000f64ed6c989eec5222239d888d08dfd638a0e35eff2266410dab0498941fcd1683654064107fb7e53b8c02fbe98a25622b9e1cfbf140f4a3b1d06be656ad6ee5169a9cfa7cbe6efbf8173843d406acd30000000000000000000000000000000001d25b5bfcedc6d7ff7e9fcf729f858759936235d23ad45b14dfd0229bf3e50fc68799d19ef019b36728285bf7ecd0b4000000000000000000000000000000000326e300ba07935e0233a03ac891f18dc7b5a9ad9a28264136228e9e23e8f2aa31b7f5e5f3cb3354984f57a868a5d00c000000000000000000000000000000000dc92060e3403df3a92b15ba3e437ef0c403fcfc9c3545e544a78874e5d9b5e63b9ba6060c29022fe2594c2e6fbb6a840000000000000000000000000000000006a01e85f59dc45b1501309a350137d71147c30fb70da6b7637a9b1dd884aeb7e554215474784ecd3bef18d15d2c0524dbc68f77d40330ad5b8cfcda42edf57899454571c6c6465c4107e662a269aeb5", - "Expected": "000000000000000000000000000000000b7fc0b44723ff0d1cb7c43e470d4d432fc4bbc7f9d98ddb3d91434a5574956fdf15f898e579236426ea44677998665d00000000000000000000000000000000176586b6f157e408138391e3767d0c1c8457857f4cfae571267ed64ac86ff8a4b61a28b406e1caecffaae6a399f4ec9c000000000000000000000000000000000a420992f850db20d4f7d2ddff33e4dc79bc0c39caee533920c5d03d1c2619d8ced769ac09f664c0921829bd7edb446b0000000000000000000000000000000017e4000f4d03a6707174c3adb74966896bcc0eaabf4ff83cce92a666fbd13b59efa2c767442062b6c8b1a3abd604f0ac", - "Name": "matter_g2_multiexp_82", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016ac5146ffc26d1f0c33645931bddfb84756e1c7b03f4838467d1b6701ee9478ae03c910b6b4f5c14135487bd2c14bf8000000000000000000000000000000000e1d082f16e4d5c5f0b6fbe5178aef6f781a6fb165f775cf0cd4dd55f2b498a79edf373007113dcdf6b977a87e1fded2000000000000000000000000000000000bb94be280df1aed761651c0292f88037d172b675bae1933ec12323b947023b437d080aac9e196fe5e06e5c4137284d200000000000000000000000000000000064190f9725bfd5d56c31aef7fd1590c975e2ce549fa6d5c71b254851149e0a0dab0b9de3acfc2d64231c79bc0ebaa37ebb3c942d3a1a15cee806fdb0fc3635483743a5b0ee9c40a48700bad5da53ae70000000000000000000000000000000012199d02d3f1bd8c4005878c3302e6a731ea69d69accdd690b4667e847b079563d32e18eb7a440b8005ca936da5e73cf00000000000000000000000000000000125b0dbdb0058639513b007a84d3a3e6302f5d846f22f99a55181f097e200981d9013c00d688a11eb976120f1a5da64200000000000000000000000000000000081e723506635433528fe4a40fe4ecb8a9c3d8cd701c043c0418d149951651e21632cd85f03db33b89efadd69e009ebe000000000000000000000000000000000956af2e67f8ae676abc783c4ec9f85c50ea130410cee8216fe036cd0521b8ea38966288afe7d35c28b30f7ca5c6edc0c193d751c4f24f4808621979f07f03b2eabba75f08bb49682b9df2da7a85a7730000000000000000000000000000000003e11a4e9dfe82cb495e9e698b16c257ea3f4ecb24749751e7334e0f31fbd6677545e4bf9ff78a82853560f7e7ba2ae2000000000000000000000000000000000caea2c527cb3aeae427e92fc364365b1f55e7128a544009be2ff7a5236d1cf8ffd5a5cefc87820bff5bdf1c6bfa165d00000000000000000000000000000000064a3186774da8bb5d013debf46ccb0d894592c414f32de6f77da47f4d42b0c8a13a2ba4f14b9883d564fd8ff6a4c90200000000000000000000000000000000072f6c48b6a05039e3a4dfc6b73501d6d4ca7e840b119da9c074bd4cd2adf4f2c6e9e6325ebf6f97c3f0b00e6b9bfac6dee4eef524f133183b4af95e4445f3ee5084b96c32e284ebebc5b87f3d76150b0000000000000000000000000000000019ddf708ab31f6f6f725f0e4f65d11248d3a79af30927a6f2673901fef9819b189502cb952bd4742d2b8e84acebb5196000000000000000000000000000000000d928535c47eafa5da4ce4f91467fc31aff8b86b850e4582a597b334491b14da71763f9aedb15ed32856382069c094ce0000000000000000000000000000000004d6b3545d067aa0768cda9dc3cca0f58eb546345b96f7d6b9355d47770e00286d962a6b3a64ca2ce22fdb4834a4bb6e000000000000000000000000000000000f4ef9366d342b309076299816c1ed9b424b68886a5c69e21e785f97cb0f99ae3a99ff6b5244dab817094449048a7552da514f21c8eab0edb2405e673297bb595edc21027890ad680f1663fd960ce478000000000000000000000000000000000236c5b4c57ee4facec5d4ff37a478c505217af66e029c3382613442c58875c75cb423789f6703ff3c1c0d80991c9e3a0000000000000000000000000000000016c052de3336002f362d9b0cb386b800860527e0fe81a1a6df0ccde31f3265e6246191b3febd1ea48e9391c44593ab0700000000000000000000000000000000078dcb04ca93c676a9a924e59f924d9d3af872849bc30ca633d4025aecd981ba12e626337635ea77886a45f4da84104f00000000000000000000000000000000027df6394b195222bb8357bd684088e3e2a398f0fb0cb812ca5dcdcd1fa1279cfd03db62e0f8b2800d4b8b48238931656aeac9a669c962817c01069cffbd948d9d8ce764e92859f31fdaf85f5aefab77000000000000000000000000000000000485ce58b387083172102145fdb3e26c6ffca8b35af0e1d84ce9cbd89055be083bddd3da56443924049a056fdb2ef092000000000000000000000000000000000d998b234a69d584c78ed054b1322ceb33f73cafb5b23c1703a9fd609edcabd44f1a642802b9c0b6fde6a6828b50c1200000000000000000000000000000000019235ff13567bd007d77e4dfab139cd57dbb309a3cf6a6198a548c4e6915778094ddf2b05a91f5478169757bf5a56cb300000000000000000000000000000000110f6ea19a7f62bc3e78f4c5c1c6d3efdf1a7f563576e758218b2c363fff8ad8fab0e72431619e4ebc93d2d739fc786c40273bda92c9b1b677edd905d76d75875e5b77841befb2bcaf1fca7674dffd5a0000000000000000000000000000000001d45da76e3016c00fe65bb50f7067e4f06364ad8348184831c4932ea0e0f3a170ab5147e4670ee1b16924105b6fdb6f000000000000000000000000000000000b3468206db0613369b2b0750c98da65b660fc07c30cab4e459c311dab683b6b313b99ec0fbe92ba07f8aab43a12a2c9000000000000000000000000000000000f58a57c449a41105837d5e2419a34201cc921ec77408d6c0c7a2eb227be98ec1f6f6eb9fc088daa0d4c78928a1eacda000000000000000000000000000000000ba53b872dcb9fcabf35e673b467523ea77accfc1b38a5f92d7b9d269c28aa00d00b08d70eae6ed4d2e82bdb06008f9ab77e16276f9464fa2063230d6c1a4152553536c610062f18565c030e80b5cb540000000000000000000000000000000002b82e2b582b247271543117b939fd17ba8bdd617a223873296f7bd75de4790f0d5d8fe523792bc7fb4764d3739669d80000000000000000000000000000000006eb554347efc5f2ee79949bafc012e6d9964ce19459b3867865709d903fe3d11bc617f30f6279a9e62ea104565953600000000000000000000000000000000006a543fe5cfbae629fd3256575e3eb4e0b65864aad6c7f359e169038bf090ed9bd92fef32fe1ac20b2a8c90fbb6081690000000000000000000000000000000013ee42b0693b2f3b9b977fbae5c856e9e4c5e70120b5c29e0a9f898f6d04b7fe351e17b02716a44febcf0a00a9cdd9220be15b654ce22ae4e32987babc4863ffe2bd8a459d0f01f68fe84a75326889900000000000000000000000000000000001ae7368f84e354e5758554aa9c72ab4b00a644cfb9a4ecba38dc72227d297749bbc98c8f5d6149143b31442359d8013000000000000000000000000000000000abf087f77c79cb8c69e4289fae87b2ed483442daec3851a5ba32c43e342be29433b2deac6dbfa7a787547a7361ed0a00000000000000000000000000000000000fa01cff7aea64b649951a8d85fef0bd475f31e47c706b96ee2753df9987508b5e5456cc49e88ec3aad720a2535f6940000000000000000000000000000000018874d020e2eec0e286dce324b91f15b2a4f293d32956b27524f478983f0e0c5b43df802b60f4f001753f12d449cd821c8f1fe94bce21966427380b6d357a3599e9db03a7694159335ffba26fe29e4650000000000000000000000000000000018f7d19362e2cba91023455e115cd90f02aeafcb026349393ca4105e270ab1cf589621b40965fdc9795f66ea0f6a053100000000000000000000000000000000170ce0eb304e0e1047617b709c834b67a8989212e5bf1cbd5a33242be94bb141d5366e636c01a229943bead9a7baf43900000000000000000000000000000000077a17356b3b31faf90f709042938b9e901817f7379b7bd486d18e47d22b0430ba70fb3006e9afa67d7dac71ffaf152400000000000000000000000000000000064aca92c41561e195fa8239800c97d5242ff0f8ce76b0d119063e2ffa09c26e01d23d5728765a59bb9587e885450ad1c6d34471ed00035a484f97f4e8123d40ca23b017b94df65540a5551b905e57b3000000000000000000000000000000000876a57dc24ad58416f910ee3ce220630a1297e6bc691c908e6cc16f975b146872d71661bbb869361623c61670627eb0000000000000000000000000000000000760fc65097d215ab9aeb3d5a5153977e1e399e2cc0b0cb9befb0266d98ac13512a0eadaba4e051bf56794621c551ec60000000000000000000000000000000003c8e205e53075a96c14ec26345c75881a0d67c7ce0d62d73c83dc353cd7b555cde52ffc5659ab0db2179a899f0fd694000000000000000000000000000000000d7e8a7fe6b751f7f478698f4f0d30cd0a435a2295a958cabedf4668769819b4cbd4e8b7721eeb5ced3f913156abcaaff3abd467168bf5e57f71017b5779bdd400dbf416f34f105fe747ea2f8cf4a21000000000000000000000000000000000180546f697349adb2918129f4d0a979bb114d1b58e5baa6cc221a09d7083469bfaa61f80f1e3a6ccde0da54b24d59db70000000000000000000000000000000004074338380e3d7c0facbbc71d83e78b53191af9ba13ba0cba6015bf4f28e4b0b52ffb34c7867a335848f57b5ce5ef5200000000000000000000000000000000148a800ec38cfc2386497d9aacb4327d5953a6612cd4067ac13fb977046688e80032125d4b0e7cb49913e489796a50ea00000000000000000000000000000000132438d18d942e6dd3f69d117abf83c2fa18418e5145cc43b3cb8d18c873935e41279a9e13596f2863be7aeae9b73d172809801eb18d38a61ef8a80f13086d6b1f85ba751cdb8d17fbb9ad5f8d0f835c0000000000000000000000000000000018b3102ce91af86cd10162d3a43e488a0d7b7807dfb9624c3cae76f342e86f8ef1200444a57e2ed7f819828357a6dfe80000000000000000000000000000000017137b470f3c8d1a03e7252e18f4466c9ff809408cbb2043d6b226ae2746d890b267ce3255114b2e073eb66e93c55eb200000000000000000000000000000000054dc1c981c9166d0bd3a54064c33f15ab856b240770ed44adaf9f32d4429babcd0baf2c5b8a1ff80728e9c63e806cd3000000000000000000000000000000001897595f836342ab54bc2e1b72f433bfe3b5bc989727de48575abe89386aaad9b1549af3ca55f39feec14355b29dc9e33521c9cf035b094d754db994fce3161842a9509ec8288699680c0ac7761eac68000000000000000000000000000000000467f1a3093c72aba4c2d9e8171057cf88146eb32f38db0761a5ab2027f2213c89e12c67a338b4b342a73384109988d2000000000000000000000000000000000ab26c871d140c9c4e0512afe9fb576409ffdcb95417f8c6cdc0d964011dfb1e745045766bbbc08ff7dbd6935934bba300000000000000000000000000000000183488902b886200e63465098be87a905810b2e8ebe0364316da798e423dbb267743a0d2e3d93303623fb17df0e74ce30000000000000000000000000000000012c7e79f9ba36cc47762139d191e6625c850a03d5b6e0648032d1669575704c91e48a9ae432bb3553ec66e86e082de689c8c2998d141b9cd3a82507b6dd97e8d32e9e759169c575eb484e9a1559427da0000000000000000000000000000000012ef4988956e026a79e5e904ad3d7ca56793321d62cad46de3cbde8570be5f0ac86d386216152b37053741fe342de7c60000000000000000000000000000000014ff7804312754d23b251a42aea65207695d4df65cac4f87fc96cb920843c022f24cd27731224db751cfb621886249540000000000000000000000000000000006ea693105a1b2afc79dbf75504c256c519f927ea0d79ddd1997a49638a67151dc81b84473208e8078cf71d456f2de0c00000000000000000000000000000000122d367c147c91517679432d3c7b56f2d529d70040109f803b89a04fd8540a6c565354ae420e1bd4ad4ff61427332629dc83c1ea9e4f4fc12a7190e6c71c4f35d1a676d39e30fe688a05820dd989664000000000000000000000000000000000156e7f8f1412cec315eb76f10c92143157313b8eda0677a6c0236de5fd27e5660ec3eb7369f1604082c59e1aa5f94dd900000000000000000000000000000000018ca9f505a88ed2bf595fa9b55d2356748770af16b35bd5db448990b7d41c3aac53aa490791f7ac09d2f5a087f938f70000000000000000000000000000000017c76ca9ddfcc26b028928364ee35829c6e57fda40773a6bc0c259a1b3cdea715c664d7bd0340192aaf7dec7ad20a2ed00000000000000000000000000000000082a255966c4f9d0ad6bd3d88b136cb2cfca09ed6ae378c914c28ff3338a2cd466cafd839f3fff4a30b33ee56e684f4e00be1b9098f1873ce155a66899877c7b48ddda363ae1d2353cb3816f1ab15ef0", - "Expected": "00000000000000000000000000000000075c71e21ce327a97024c8ab5fcbef4fff76260a4f8c8489167166c4a85d25096c617cceef73097a4bb956be3eae8b780000000000000000000000000000000016270f3ac86c0ec43b9472499c4d845eab488a34ad9e2148c72cbb1db13623c5dbbc8327c47ce596521bd1f54f119a660000000000000000000000000000000007ad4914ceda9fbc161121c818bd05953836a581dcdc78bebcd82ef548671c899581681c908a337618a445f77c6b7cf400000000000000000000000000000000173f401cb78024e844adcc88fcf0e52d32de134f6300216ea0da7747752ae3ddf4d181b8d266b53d1b699921f9871425", - "Name": "matter_g2_multiexp_83", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f40eea638a3d4fec417701c936d61c5b233c9d6b3e94ba9addd0fa0b20adf9f8e07c6b629977445c7750acfd18001c0000000000000000000000000000000005f1ca1ca9cf67c33e3ff174a65adfde2db62e74edf30b5b0156d6b9dc86dd619ad8863c055096685d611ac015ba884f0000000000000000000000000000000001683dc67710880b8af76b464291c17fb0ee4eff3f648ac0772f4a777025c8cda0342d8f5aae3123da7fac57b965685900000000000000000000000000000000143d919ce2cf00838b10fc65374e770bec3db8ecb17d2db08b6a10ac38657bb109f54c1b3040b661c3914ded6f7eb80fa9cbdaa0ddbf854861eac6621255b2102e5343666c735d0384049d5680d105d4000000000000000000000000000000000616299341f2921adf083d1190c212a7941bc0d9fee50b05b265f2e8c339fc3dd9f94607631f485e394f5a7d71ae73d00000000000000000000000000000000006b2f12e22369e8aff45b6c05a2bb72a706dc46a5d1393aaa9e5a7931ccff33a5df2967189114c3fc5dbf69d080e39dc000000000000000000000000000000000981e1b119d04343e075a80dfc189000b4cfb4e321575817aece6009e6b3a6233d1409e8e584f0ac9caaed1f43e40d7d0000000000000000000000000000000001ce4693e8c14032c35497e0f9a586a4541d8a1a68ad014b0850753a04215be2bb60cd7c2fa9be4f4f09a562d7b29f3892073d958260a55b70b580f3ee27c42553b5b858b66f6928fe74b4de91c34bda0000000000000000000000000000000012d634764207dd7a0201703f855365f7750291c810ff292b3e8dee682d7d8eebd6d6f3b3dc8b0c9e25bd2860e031311b0000000000000000000000000000000000eb0859d79fcdef546026fcd380f5c936e64a5665d73f56d92c03dfb50c534a00c857c86ec43275ce69cccc0b53137f000000000000000000000000000000000131bf000fd117ef722b33a1cebd28899fb012e1113f767d0ed46fdad82a32e4327b883fbe29abba1bb7ba3ecc1cbab2000000000000000000000000000000000e24ef1e44029366ae1daf06524d8beacb2b99f60f419cc2ec1a49013b79fb7a4781dbd37785f32ec67c0a28d61a3cea2117f11d78dfead915a94f11fa7e904a96204ddf1835d3501639b83cd5f716f500000000000000000000000000000000067b6eda41cb8da47a424a02a142e2b98b9c69e7023cf616040993f41507798882194229cb6572806e82e9e5eb837b37000000000000000000000000000000000e38693cddf130d3645fd60ade780db84fa700e5bfb74ebea49cc95ab001bde442f363b4e4c61f683b3e67f1ec8c2af80000000000000000000000000000000006d593005cbccc55c5e336e19aded70da65a7fe42b6a85070e491a4ae54e18ac213556a91d5d62786b6d4d1305525a76000000000000000000000000000000000ff86216f5388114dc06deffa7b52a273b22fe0bc8d50804b491fac83e13915c2dd1b8c2779a46b5c313c4e1c05eb2979087caa1e89e48f05bad1d720477199410941a6105f911d589e1f94a851e0715000000000000000000000000000000000262cf4727703fb227bd7fce6cd3f25c1897011ab892e79fa47446711d6867ca82b9b95f129f7ca24dcb60ac75173d4700000000000000000000000000000000136b5a304807e029d0a77b2ed505ee5c920248242f0f95aa07e9bc2e13d35f6f67451d028dc19d26095b55cdc2fae4fc000000000000000000000000000000000b511b2e19da7bfeb183f0aec91bc7db3e7c913f1c282e12d5d2f422a49e7fa78a5f35656dc9c980324717a5ad386dc30000000000000000000000000000000012eae443aae59fdf907bcfe3ee4366e252bb57e268fd569d742456f348429f009f67bf92f9dadd401104ccd2549cecc8255603b470c056b3dfb3acae0dd45bcb3d014765a5181760336deeabff3f00be0000000000000000000000000000000016a827938d8b98e3446445ce23f48a7ba0d634de826dd1ee3c71467eb57bd4c24e0d1b4190f47bd841183baceaa2593e0000000000000000000000000000000011d360e0c18b45ace82eaee902475127d8f18aa4a2ec2081a453f1c85ffe3c59c0f7016f966574a7c51bc14f1935568400000000000000000000000000000000186b5d452c6dcc1ddb4f47b07e01b6d64644f6d01cba8498c3059cc494a68bd25eef35cae05885b9f2689683e65161410000000000000000000000000000000000ff826e5a62affbfd6d2062bd329fcb561f287046870b8be461767759cb0d5f1ac904ecd1f136c5ccd784bc11088233e0eab0e2486316956291feb44de6389b20f8bafe9cc890d86d27a598bab0f3c4000000000000000000000000000000001010e75c52ed0acebe30fc588961c849b7b6298bb8d859f9a9401737c467921c5e3cda101cd4e38e4318233d12b6c7b9000000000000000000000000000000001884db518fbe4d621403ce00521878c0d419d8cf476a1dfda59b7d3c7af2bd91058bbbf54ac0c5cf9a217beb78e3f98e0000000000000000000000000000000001272cf0ad917738bba052e88baf88347d60f63f5b875d604cf0531c1ba7d43e868bc70a682b7274067106f611f08ae60000000000000000000000000000000006e3236f6a66bd37af4be230d4edda6eaaed661f206ca4852d3004b5f358f184d80be6af81c62e5bc8c88e7a1072fe21fb9436456262e5149d02b33a1078e198bbb681699b3f485625784df444bfff670000000000000000000000000000000004fd1e2fd0d28db08224fa7e880abb8c48dfd0e488df4d2ae5f6649f448193acbe943baf22af4b12fd763e3e4ddaa08d0000000000000000000000000000000008df68f276f356ade28500eeae3b755c9af9b5acac5f5f60827b5b2044b2405129b00e5271baf9a80847d3b720026b3a0000000000000000000000000000000005e683d1556f513e6d093704405f312687c3b9e2de3b2840fff32e88186c89b18d1ac558d960b1196594730a9bc107480000000000000000000000000000000018161f8d23c394d10ba576fb0ceee530ebb95a670f2589d84c0646f693086ecb7ed80e556f3ed9434d7fa488430ccf430e2724d3501e3d79b85266fd83a2a6156eeb48e749a61676a1c92ab9bdd6b8990000000000000000000000000000000017860708943449c2227c0f50cf1274652dd32e999d5f9b1a8d672feedde15e9f1af484a7b9462a62dd745bb6d3c7295a00000000000000000000000000000000064f8cb707494f82ffb6374641817a466af65f5c7d83cc2964e6cb8efd021e0c40934a3ffbb0d91bf8a7a616dbe8d220000000000000000000000000000000000eb37cc9d56fa0dbf050b557aaeec76f9f6d0a6c448ea298af78004e41ecd8a1df8fe8640e77cb76b593ee17658326ff00000000000000000000000000000000092ab597967544fda640b145edcb3ae6c3f027c2111dbc282ebdd48eb93287ae4729cb30e45c1c8999b3a45b099dbf0ca49344fe6ea9274a103f323f3d9381e91ae48233dd579944e12afdeaf854000f00000000000000000000000000000000124fa4d48ffc5732fb21d465b559e995891fef98370a1eb73c9264988f75caa93fc134fde7f93c794582ba5cbf6bc685000000000000000000000000000000000b71d012abc1558e49831f053757518643ae04f79234fa92023db9c5483bbd872d24eb87a78960f12930094c4f8fb70e000000000000000000000000000000000651cf0016efea086d98e5bda8e1959e20e4947e302eeb021d196897cffde3e2c28f783521b2a28b8de1ad1a131f5e67000000000000000000000000000000000555ff8a930cc11d320afc3e0635a6f93da1487a5764d56636be4e5803d740a73d84666f6141ed5ee6b778a463823fbeb44aeaf3ba8b03e7ef7201415de7365365b828f2c1a38d09153e51432d35b9a7000000000000000000000000000000000974e769869719f0ee30895df837cff50d47382461c557abc4b8806b04776f401b76a5e630a6ccbd3484980d03ff58d300000000000000000000000000000000098157f0190e6bacbf34c20310f6471166750ea1b235e46a5fae313f90dddc799f21548088322910bb0fd7e41beb23450000000000000000000000000000000007f00d7d18719db9d91e2c32f51083b42c4fcb43c38087f86879ad6bc99600d4c395586187d26d041ff49dbbe517fca2000000000000000000000000000000000510cea4a7463bc5882d0cc25fa967a0b02072627bd57f9a5863fe5255953732846d4907fa301789bf02af9c1b25211c53961d33104649cbfccecc7eaf33b7a2a486c77dca363ffc9fbc9ce4e8c1adff000000000000000000000000000000000bf264c0b7bf68c595b89453ebbd7fe2e64f4ae2c7268ad51f4578c35d48040277f3dac9021997af02e492039348efaa00000000000000000000000000000000083a4fea41cb1e02e5002259f5f7b335c81e15cca93cbc884dc1b08ee981c55f2dd3c0db1a35ac9907435edd7f0ba625000000000000000000000000000000001468e508a02ed7b61f752ac38313345338d2b2d018f719f391c0f3fa1dd1602d9476f3d8829720d17021a459a2732e96000000000000000000000000000000000629edb2530c38ead8717b289c08036c12630cd8c9ae875111749ed893b8cbce40bcaeaf13df4044147bb665ecc2319ea04e97c20b42dc265271740f27f1a833bc5b324bcb843a8f9f8a68231c663d57000000000000000000000000000000001635830ebf227be126e13c634a84f3649d498e0999ad2dc73b9c7360db120dc2216addfe18c00676ed185efa1e789d8c000000000000000000000000000000000471e3cfca449bde0ba2b1e2a5b63d53badcb34da3251313190a35daf694d70ba385976d1f875242386fc74ae0173d18000000000000000000000000000000000986cf3f1eef587bcc70f66f25c60f353e6b15bd105fde9254487e9b522159658d0fc6b6a8a3ea38c27865f1ea4d76490000000000000000000000000000000015a2eccb9c10bc273cb712ee04bef01a11e486bc6a4d220a0f653582af6ba1bac0b5108250626ddf126f16f4015c9d2cb688426bbe9ae054acb6c1fdd4195f8a113727f5617642a5b3c0c65566e22527000000000000000000000000000000001213cbd035615f09189171b3e22630d72df2df93fa8c14427bb00c34f5b55bc8d1b1a59404bed6549b582537a397eaab00000000000000000000000000000000161072d8ebec2841f0f34cb38a3e1b2094a597640a34178ee951e5c993646ecfc3a4c0dd753e7e76f3a6da5a091f9f7100000000000000000000000000000000077e9c95b6c6f726902392c3a16b5cc71cd9d4cec58c00eadca6091e45bc095e53006ce8ac8827565e867531013821950000000000000000000000000000000018cdf909bd9f38e57ee24c0f51a5f9f703eb3d190dfbf75be00969e9e8f8fee331cf32d93c3a956d12f374f8752c2c79cf365a86a8d08db5cd95f239a2f3d22279556975ecc3baae0b774b0323dbb1b6000000000000000000000000000000000cbc27995eaeef2bef14919d48a008a0b0467856f8a6659d6e68e47a2d9d41d217c5913aa1d67911325dbd4fc38e36eb0000000000000000000000000000000010639740654bad5c4ec93f2496f4dc54a7642bc92ed03372ad4edc5fedcdfcf37158d3f02279d4e15078e9d5a7f8b5df000000000000000000000000000000000155ff4d6dfa031b0cc2f57df41c1e1b1c81bf5a5cc1e3aa93920e93c2e2e7a71b56ac410a87855400025badf6dae8e60000000000000000000000000000000018e637da048e7e84b9d1654113978fb148a54d86e1d011d7f5a86cd4f1e5bc15abc5b67d00129f53c0c021cf933f399c528715199c9f47fd6337b6b0e807e230b1397885fded024431c70e453f55f3650000000000000000000000000000000015d8f6e47b8f07b3e07ae0952a7c8f79519ce2828e3e26b284b8f2fae7432b337de17089b5c32f0081ec6c6916f2f53f0000000000000000000000000000000010ecfcdb02cff772db667266cb3f99f1dc28004ffcadca7a9c64b3b5853c09b7793ca0aadb155257bd64fa7bccb390450000000000000000000000000000000011096a52f3272955947304ba037e8b3fce6b2f07f2352c08d5932f4d2306ca511a74dc044d0f0e1e260ff40b0fac5e0e00000000000000000000000000000000130facbe0c1c6d077e9dcab647a44b049a1aba3df500bf27d1c268f71a59635e702c9ee1bdd68fbfcff7ae5b3e6bd83bc32e8643f38f8177b788b8c2bdc25b668308d914fce35c6f9023a769334a51d1", - "Expected": "000000000000000000000000000000000b47d58802579e662f34908a4060becd40434e4934ff58790df2a69a759223ca29f42e658ab475cb92bd9c46566811c7000000000000000000000000000000000091d3a4c58a669d3bf0377abfe28d1817168b2a86375928d95df3459c83334669a59aba95ab2b9957d5ded0bd8925910000000000000000000000000000000005aa9c3fe0067338675099ee32f93bc8a5e9ead94b120dfa391651da40cf1ef5ff79d193b0b14b5926f10660aca6c11500000000000000000000000000000000058200992b111461f4d737533301734a5c3731c9f2e7b55e18887ebff4d5b74dbbfd23773606f54cd6a930b85b89aabd", - "Name": "matter_g2_multiexp_84", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bc3eba5594666cec699a47fa13ee74722a80b4e5a1b28553de37c3163f2fdb8b801e35a19f6d99cd207d1642c0d4ad400000000000000000000000000000000104b334afeab36961824611f0fb58bcac55c9d36604ba73e9c8809085c019bd967cae7147c766df6565ddfcc0cd5fc9700000000000000000000000000000000026c3a6a4ace8638bf8ba7434b59c3aebd4bb274cbdcb898ec6a547b215f32d10395f3bb85a9eaecff5ef6d5ef2b50e000000000000000000000000000000000065bc419f9496b5e81ce72a13fc1bdce4738c2e3faacd80676be31db65ba3e7941ea75e370b6d6c0e7b2cdcce80a2fa14f8bfa3d47ed33a05fe3da738797f18ca5d5b8658055de5a9f85bafe6078f7fe000000000000000000000000000000000e7f1f5ead0f212439b4c47599581982712d2e6ba056f36cb04033ff5eebd81b5b41b874a78aeaa98562899418ab04c900000000000000000000000000000000095e45da9a4b2578cedd13af71e289d0067ecca1f09c014a294e0b250d1e8243ff98a9761030ac855a9d897cfe9fafdd00000000000000000000000000000000030b44b150d1337a3ed6a77f7b6332d7c8103da1aef0d445ff7467b4863e4c830fb782a81d01a6bf97e8d52bf333e78d0000000000000000000000000000000013bb76800375a45b847a96ef6edff3fc3c30e3d45bb4afe04230107f6a1802794e1dc23431797bc5e79e0d5ac6357eee4b0d302be94d437b8055586aa77ec1fe616e30552b4d7d3471ea219c148be069000000000000000000000000000000000602e0bd3d34415ddd517a73acaed5750dcfd68b633d51003edf79a169ad7a3ca2541d7a131c317c957a9597a753b5080000000000000000000000000000000007a964539081fff51e0ec24bb71257f6a1c513fb0047aad84b80180b22133246a1f62958ead75e4b2a68f973d17f1230000000000000000000000000000000000f48fe0f5b5a95e48bde4d8be1b2f352d748c1201b064bc88309a709b285f81260d4535d3e1dc7f1d6ee23ead35abd9f00000000000000000000000000000000135b480fc8a72248f7a4898fffc6c18b7f2f5b1af5cc3846610c299c8da252fb71190d9f761e037c6b47595bab6a03e56765d7f1079b142e513e604d577e7caf82cacae59fb98c6f8990522372dc906f0000000000000000000000000000000004773cd2884e52c2551c1ea0abb78fa17caacfffe13f18b75588484b8bfe781e623075bdf827fc82c6ed7e1d4d62081d0000000000000000000000000000000007e6023fc0e409bfc7d0b7ca65fa0e8d88bf1b4c202a8d1f0e1c3479b0963a646d16795fc5a128a54e624357050fed4000000000000000000000000000000000039f6eaaf99bcc9f4d8fb994a040af0d29c37960e9015d4e48466a9e554da30975c5534e76a1f08a55ed8ce7375b70100000000000000000000000000000000003d2b097d4afdde83a01cf2b4f9d12f77c8e92a8cadc225d40f974ccf385ae65bed1972a365d55e24231d58abed4395a2eeee02d9309af8c74c78e21836f4e6a7a6df5406617e2b4e9d300e37d8a2bfa00000000000000000000000000000000047b8c550310ae246e43b513d39e507f1dace7bcb543a49ae0854a397f62c408ae3632c94d172669ef3e013781796ecf000000000000000000000000000000001592914e260afaca80c0a240426c2828239ad5e256a707530f49cd65e9da2e4bb14a7d6d5978f52c04130a0d434cf4ca0000000000000000000000000000000006c0b8448ad87350db130373778d414deb738d3be97fba25c816826f59e3e926f44956c2e2056b7d769278cf56cf6fe0000000000000000000000000000000000a42d716fd83071bfa014a9b7af6c164d494f0347aed953bd2c1c97ade087a8bbea9f53c507fc0b22d520f28cc5d480cf8449caedd55f0a08825cc1a9e985201c8a7a54d1c4dd96f0ac54214743941810000000000000000000000000000000018026c9f6c86219d0be88955ce0afc3cb637b1c3a531aa2722c56816d368688181ef2fedf1525daec6d9b1651b71f27c000000000000000000000000000000000b40b15bb0621209bf9e33ebc27a7502d90fd3af62a1bb8f54a874a14c105df34ae34a43fc3805c1e4817ba30c048ac7000000000000000000000000000000000465262367e30ccc24632d39bf3af9cb160e97049d855176f665a185c138d5c529d11e53e56c65506e3e30be7b48c6730000000000000000000000000000000009485991319a311052d883b45911be12cf7648b5ca104ffe77594472f7047c803b8e9fb753b98645e630b9913bbc947e28ec5f9dc48931da70ba0cfa7251953e24c4c95cd019e00ac6fda095c1302a01000000000000000000000000000000000fcc0aca0d873cb8733ff7e2ea02b3736b737821af2db06ee6508e161f6159f9d944372c513a03cc4c9e30a707dca0930000000000000000000000000000000015c3774f4e0b30c9532beaa2f7f9b777f8d46bfd3888d6835f4a5a046153a98062efb17f78807fa17b3a995ce720c0b900000000000000000000000000000000083d48e01d2fb58244861a74a1261063f7d20b412c8a44f9945fbe373cb4b9a7ffd4c4ba4054ece0abddb6c14c013ceb00000000000000000000000000000000133c4976454b7be427c4c2ed437bc2e882854d2ddce42d2f97cd3fab1fcf60c3272aaa123a0cbecce1a774946bb7a8a0dc6046b43e6982f11f39412cbdef14f8e330d37fbe6dfa9ddf3656b86f4f60e7000000000000000000000000000000000f6ae7de1dba3b3030b208f61d182013231c4666f134b007b52d36bceb6f3cd77577be7b11abc097cf9618d351d61e270000000000000000000000000000000005803904e3e640e51900805f930638ddd8b86cc1bd50cbd32a142e10d85044cc52ff769bf1b40dcfb7269c913d00b01e000000000000000000000000000000000e6997b1f8bb649c56de5c4bf9968d19712abd22fb7dabee19e0aebd1b13adcd3e8b202975b4edc917d93adf087fb539000000000000000000000000000000000a32384fe03280962c5f575b47192e5ef3111fbbb0a01bda2db1e9733471f11eac0a37df8ae1a891de311770c482c06b0adf4625ec80149b7810767c985c2aa0187987b3649cab8c59a892404ff2aeb2000000000000000000000000000000000531fad86551ac6dee15fbd62cb13f38d8d5c89d23a031b9977f110efcf16501534757bc5b93f0250ff02d6cfdf2009a000000000000000000000000000000000e6d78343049a68514271fc785de053ed7f50a7774b87f264c42e03e6f8f86285477f8cc57ae066ef0fde237c8d1ddb30000000000000000000000000000000013e313484da4d6b85634c5306444bdbe45d7db823616d72821eb64a2bb5f352a4f7e4273fb6557039fa563ce1b091bea0000000000000000000000000000000009a40a984be66c3442fc8946cc42eca722187dd819be9ab34a9c3b4b0de7de3d5f126c175fe84c51a6f09e18623214f9345fd17367ecb06b29d764b22dc1e262ba1a339b6f0e0c77384245e3d41cda970000000000000000000000000000000008a76db551280cd43d4608e9fc629a021675bfdf9bc5a021546b92f3734acff1e97928850716b94d15b7dbcc4a1e0aee0000000000000000000000000000000000b2262872c268782e8f27ee8fefe0827d45131555e755c0a65a7c8b4185269bd621412b653348d7c1111d681f38d946000000000000000000000000000000000dabcf0f847045e01ef70ceaa32455f4c962e4657b840f97a1cff7cf5073cbf4ca8ea75a4887076f155e27e8d7406c95000000000000000000000000000000000a9c0ed94170eddfc485d9f1a770a8b493d4a59bd7156d6cd4b95b55bffa1b597ae9d6fbe529dc0833634d75906a4aba5ce5e62dd15958e6298cdf4a4e899e53644a48494d04fa6d1f73f2dbd645817c00000000000000000000000000000000170ac69c2bf9b48715f445524cab902b18ce6dea7b258481cc59986ae61c8fcb6708b1457be299a6e2f6f34dfd936fdb00000000000000000000000000000000107e855593b6f3bd2982a65167ecead47039065c9ae6e1bf963f81d441f0ebb411eec4b3ed1cff73044f68a4c114806a00000000000000000000000000000000063b470d158ebb4828e875c3dd0ca29a4fd2cd2af356233885a871cb5b77402090f29709c6d6a78f612c8ca4df2f4119000000000000000000000000000000000db75a60fa0b425b8cd2c955e21846ce3c407cb3f96c472cb412498143cc60212de0dfd0bf4de53ae3b345232180b4ad853396021d32530351deec5c266a65519471dce2087485781f33a1423755ef38000000000000000000000000000000000389e79154f627463a7966252deab10b5e809b0c2a9e90989c56d4076b834e2081ddae1c02a9e01b71d96b772766fc680000000000000000000000000000000009109473c7aa614334fde410951a69ac45967f7550890e01b05279b6dff394775dac51d583ae0aa82edda18ecc5e66240000000000000000000000000000000019dd51ec6783c1618a7f12298e38cc75d4fa32fc31438f67eb15419a2f0e9d4b5f70ea59b69e531c868475cada519569000000000000000000000000000000001121c7a6cbbb54d5e30a11a73c158237dedac46385aa15d93592a30fb64fcd94a674cc77afd21a611f704734337905596dfc62eb59bb84b3b6599bf3ce7af229096a8fd5925d4743a5ea386a26c9a6d000000000000000000000000000000000178670fb06f5eb8a4f182913f46f66147deb3f9f634d620ed55da2ccc88895e75f76f55b979e1ba3c3db29710050c7bd0000000000000000000000000000000011adec68ef139716ee081db7122e911ec5a6e1fd7f681a96a713dddc2b742b6e7cf7485b8f45e7ebdec8b1174c02eaf100000000000000000000000000000000089dac9a47cbdfead8536d6cfe8b94d316123bd92ddf30091e16711ff4651c4e2d8dcaf6c72bc159d7de9fd832c6f5be000000000000000000000000000000000c40b871930f0c6826a943a229112f8bf9a3b7d7e07139e1a7d99f97601b6ca8cf3638e0265743dd732cee17fadf996721d35ee6d29ee4816b91d1664b5957767b4b8066775b37c3b3d08729c949d6e5000000000000000000000000000000001040c4cd3c28a752295b115fd80c8ef0e538e1a3906e0d326e46585d633140bd6b8231f50d50c8e7a9018a625c4bdc530000000000000000000000000000000008b966d9433bfc3bede4ddb005cd0c256a168437c31b8ecc83e6fefa6f4b1f2bfd057c78f82bb76279b74a2f7de493b5000000000000000000000000000000000c0f75db7a17e4b712666b16c31b10bb935e7127eb9a0e59e35ec54814a9de9012210ff1862aef5f765d4f7f673c4962000000000000000000000000000000001015e63589a8b56aa643a79c5a433dcd8f4933a10edc9921bcaa7098af435f7879a40868e25d1ca6f7852800df29c2eb3d283067bac390f556891a531dfacfc4795358229bc9a651c0aa71d601bdd56d000000000000000000000000000000000fab22ab380043b01d312004057488ffc958168f8fe4d9c86af622030121e14a46c4308d711d5fa9a414b9ef75d51ba300000000000000000000000000000000047c738fe5272e695f421ed463ce0d6308e05c23b6bd0973df9b55ca96d89c0771a45d53b4d17f30d8cf08edbf94490c0000000000000000000000000000000017bcb3ed735e5a302f76002ae82f4ac74889fa0e966f0fb611fa6a6a09440bc923f447eb6aebe47eef917753b7427efe000000000000000000000000000000000b189d5b64578eb53ad850c826082265e506ab620a9ab9684cc2a53718f26befc35e9431af012306a6190f144a9632bf873724ba35e4e8b731db36f5067aeafd33f2e966977bd0962fd57cd5ccbfe87b00000000000000000000000000000000049fff545ac239696c995eacc560580a0328af07376f5ec819902e30d5e7e40d5fe07295c4ccf54d5c06134370373c1b000000000000000000000000000000000bff448d5ab544a8cae0cacd216a6b6d48f0abe1b4bc946d95c1a8c4ae44bf049c3b572675a5e20c1b4188fa27a867a70000000000000000000000000000000011dbc52baa00712f66def2fa8fc77bcb07431d3285774e2517dcca65e611f07aac265856cdef0c1637def44c382230fe00000000000000000000000000000000090af0898dd578123c65d1f818c3f33866e4acea19aeafbb31bd8da029ed1daa2d7ab3b22147eb32a09021f7a78fdf2acc5934c02b63797010cc8474e90fa5dc88d73dbe5f9be605bf335057fba47ea3", - "Expected": "000000000000000000000000000000000d52fcbe9f1776477a9d2149ca55e0651fe9d098a67209ce2e7d772d4901ff2c70be432b53dc94886651865a81ba8c620000000000000000000000000000000006b54871379e2be969f86c72cda9acab9bc99f73de987f17ab8b25c63c55ffa2cff61b87e8c30d9f712afb62a2b9cfcb0000000000000000000000000000000005652612b19c38650d1babd4772722ae2c560e2914f2e246725cea86dbe1275a981a592eb55077ee4b7c6090e84d2ed3000000000000000000000000000000000ee37a6d42ce69aa67cdcacb19efc230c6c34969a2e081ac77e8f9d45128a6e8fff923c7647a0f168fee18342bc6d845", - "Name": "matter_g2_multiexp_85", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f114e56d10dba7945d125fe1ab7871d9510771548d8388a2aec8a481de92572645b73631f9a60285c3eebcacb3bc0f5000000000000000000000000000000000667d3f31955df11e4e7896a1856fbd4e573f1cfc906b3953b5806a5d01dcdb96009d9f148156a3828e822435f722c5e000000000000000000000000000000000d7740ae776eb4766999f5671315c8965ccc84ff71757e361fbbb55babeefb96265c97df8892acdd6a9166641f656e62000000000000000000000000000000000166529d1a76ad784557384cb971728dba298baacc2f2a39ee36516bc7a761e9a7c29e385cf5784efb9f6e60e998b01e864a1ee754f6b0a86923e5501d54e6f47d7ab9e1483294ce98be13b7db52937100000000000000000000000000000000133e0b08430d9318d98bcf58b3d8f51c7b717fab56fe25f434bf521f830c7d4247d87d3df910490be2ad38adaa8eec26000000000000000000000000000000000e15afaee4f1ce6290ddfbc13cb887e540efc3fd8150dfbf3a5e7c759ccb8f334ba26953c7bbc43b5234b857159f6722000000000000000000000000000000000e4cc685524d42ea5e435afec7b3d7d025e93ea06407a28c246a39dee8ae77514a0bb2d5031f7367d658027299762bea0000000000000000000000000000000001b231237f7b0538d51adfa4ff92bf313507996cf5255f191875970ed4d946cffa8620b44045f4bcfd8f89baadd331fd93064d187f7d21b8b0a7092943de13b96c2e1ac9b578637a6e64331e2d40f53900000000000000000000000000000000084128f1848b2b244e4812eccba01287b9d07e85450459c8c42b01180bdd843058d9926f39e2fb5f610651a00233e31f000000000000000000000000000000000055ee70765f2cccac966dc08abd4bba0d004b379a2c6bf188f300f5d413f84e77ca1d462219bfb820d7f585b914a52f0000000000000000000000000000000002dd8f1d1cd85a5e6ac793f7e1e3cff887204aa4a5fed92f2088c06eae95842ab2c04d30d56f4b0fcfe61379e8e7c6940000000000000000000000000000000013e318f8b6f4165a8096c76ada440154901de42d69c38e66d9df4ffe5476666ecf7068e7163f29f04972682c43f3b0fd5e676b40c09f80be5d9398a9ec20cb811cf6819a130445203d792a4d34fc3e950000000000000000000000000000000003415c8bab713aa18d3f0d54e0101ba36793e6e9dd3471f8eed9a15e00d8312732a9ce88b5f0c30207aed92eb173ac680000000000000000000000000000000008a7e145e9576be8ba2fd980fb1735a2b73d1bf5f3e108878b721b6ed8378b5e0f03ecac179a6d148541096ba483b40200000000000000000000000000000000029e5554752db8bb87d58275268f24ccfcf3e0923744d57473d54a72e2cccb847eaa8f3bf638833a934c43930fbf30990000000000000000000000000000000000e0f2ead2697110a132c4ce1643b97fc652dd0660deadaa4e0c45e7ebfa64cb6a6fbbaac7c4e2b725beeadf6881ae5893f63a87972dd11f5239c35ce269e4b9239e3ae906ab117f1f045d3acfd16ca00000000000000000000000000000000014325fcc087aa108f152b42759cbc02cfa24e7e7cb995c78ccaa9a283ec2029c08cd747d599e0685d365ee99eeafca880000000000000000000000000000000011da603d3a1128329af19e596ebeaa4bad034c59581e9fa2e42a0260032f84654bf5ce22ee32c34eed7515d7fb0fade0000000000000000000000000000000000189cdb5b934cc1ec7ea0cf4b8158a1416712bb59c1650e6d244de33bebfffd3691b499b3ff8255b1b513deba709f7d3000000000000000000000000000000000e7ab2b279d0d5933df25d8fc4faeb8ca907e7bb8588e618b92737fcb6959380abc205118d2e3fc128b89a2ead5ca906145e3456d5ca6aa5910430e5a19567c327b757377aef98c4f46fe9a1f52cdc5e000000000000000000000000000000000895b6777e677732c74cfa82d5348c4c8ddd63ce10347836f5140b9a64dfe631804ea3be8e20bd4438f5e7fa14a121d80000000000000000000000000000000002422cc4781f007f732239ff9eedc126777d6ca0f0365dd90bab6b68c9e3d02ce726726a6d30d7d51a1f0b45aec1854100000000000000000000000000000000048af8a79663aefaff77a934f0af3a09ba02077c13a794ddb88e5c679ce348b3ab0fa217954ce1422f4e212d1383ebdc000000000000000000000000000000001190fec6c510b0b16e1505f737b25dc2401e9fc2c95bca92aa5d6e93b284b766bfed93a80b137e5fcb339983a86acd41ce27de5d3a5ef941d058a458f3ad2a386f1d66945789e51fa330fd65da4cd5080000000000000000000000000000000014fbf4d005f43563fb7408d1f20f672c8983120c66462ba9156b64a287e66960fecb41ca129b6b14466a5a0de91b81c50000000000000000000000000000000004fb283724950174d60f64af7bc8a7d059431332c8f17769df33f6607d72633aae3a8d595cb8d5af3f8909297844b3a0000000000000000000000000000000000e187476a19280ad9f33a55c50f37f765e343f92938e247ec9fe099c7f3df65e24af14885539bfcf3efe3bde9f2700ce000000000000000000000000000000000f086e6b9e845fe3b0c5100f82bc8aeaed166bed9fa4d34bc03ed86342a997101c508a4c096c4f67cb5791cc1a1fdb8187bf5c4624e86aaead712987f313e5db8f2fe6787fc33481ed6e5c4d3e96d5be0000000000000000000000000000000018dbe48c54347635d4b6bc17ff5ba390a73925f1b180d2c516eafc0936aa9bddaf7317cc0c211fb2a7f7bb096369a45d0000000000000000000000000000000015544c177a4b8018ed60c2639b43236957c2d995fb0f32523654584b0bf052e0930366a93406e1ec5c6d2edb955e811d000000000000000000000000000000000802d2cdbc5e15b25c77ded4bdba087f1d5760e6ebf9549a37f3314b1e88d3d6f58da9d8c6e9ef85028a271b83dd6242000000000000000000000000000000001577bfeaf213ca8b0983cb178e9634dd18f74baf02f6ca31b2e3b287d80a32d4cf11afc71df09ca5bb0bc8e60fc7ffa968cfa3fd0692c9ce56538bf70e77e2a47534d9472ac702c53f2dbe68217d53df0000000000000000000000000000000007c059044ce0c15bc527b19ce85cade8b1d5a9cc6dd304ce9a3c461e631e17c4feec52a0ab5cfab6a2270c75f73df86e00000000000000000000000000000000076344286cedc8c180e3bd762f12ac08f0ecc51293b9f9b8e7c0056ceba1bbb6fab4ee39cf559fdbd601db6c3d201199000000000000000000000000000000000bf6e708d0a4fd85c7566804e19f21f7a00bcc3bd7135f6639ad30aafef2ed1e72c84c8995b0e59738c2bf1e4040621b0000000000000000000000000000000018ff3d0ade15b690b6e306adaa5c10796b78ed7f8a984f637271cccfd39fd17c1e8288a11b051ca94de2a9bd04fa96d7a36b13ef742bfe88882a4e635b5fdbd9b079e1adf3423dd4962835c68c9617c500000000000000000000000000000000025cb808922f6deb0bed979b80a675d9324cf25c53de373534d771afd919a182af9aa1dc26a2d0284887121bf4d6b6470000000000000000000000000000000018970aa4f456c1b203817322df2e222516bce67ff9ace069599061c6229596e506c0286171f3551302e45b7d3b69a39f000000000000000000000000000000000a57d0da60f03fd4a5664546f9809c771ab6188aca5102c31f26b09950cadc26b0275417ddd9c4f4cf29794b739733cf0000000000000000000000000000000004ebf2bd93d7921d8bd97ee71cadf91145e064a33651da2604ed6fc8e08b1b8305005f12fd4e6b68b7b6a3b5cf123b1324c54daa7de8446e5a26cdbd6741cc90bfd26c544fdf221d47d509c978723c3b000000000000000000000000000000000c8ff29d0333e3f38fd8af91ecdca49e54ea5dced71b60d693b1bbade99ae668e4f994f7a5417a08a8ddafa410d437f300000000000000000000000000000000078ac1d0898a9e6cae29fe6b50e435e5f543d0ee233346728c46d659c4338295f27b42fc4b2851ad5035feab2bea8871000000000000000000000000000000000b3a566d2ef4467f21c27e4a3dec99a26c304b32ba1fcce8276a8518383a7de44de5b4011ba738dbb8761e67e36115560000000000000000000000000000000015a0aab8c3d51fc3fc8aa35dcd07f8a08188976883f9d3ccc87ee148525f2115ca46726a2e3c550167c169977b216d6217ff7a416011549f144a3a65238d62395f4f76afc09496902c064b27739c6d0a00000000000000000000000000000000115589e8e1440edcfe72c008f6e9cdf13fb7baaf70aee16166e7f32f4651db784f4c5cac15d91ee13001169fa777f0d00000000000000000000000000000000000f86710678b01c8f648bab2289e8f90648d9470cb13d5145ade526696d22508a4a59164290586c2c000dfc55b4a20350000000000000000000000000000000019b300961b40b0d9fe6e292e9357d04f0483ab3a8cc6f8f522153c51d22de8e96a812adf720d13ff7d05d1e68264638a000000000000000000000000000000000a80b61ab051ce413ec838167fce393f88c8a25f403bdf07cb60391fb15306a5271a7042d36f7c46b5978106a7b5293c4615de9bd7aebf1acedd9d40fddda34e4a85bc253c5e92c20d984f6c4cec533c000000000000000000000000000000000567c33d22805319418cb1ea7eca6205a6c44f1f881c03e37bf3c66a1baa5153473cc73b8c25d497b0b0057ceb0395960000000000000000000000000000000014d7a2bfeea6a746e709f6108eb32581ba38a617e4450b3567c77a992988d91f4da31b209286f8e9fd0d7b8628aa6c4e000000000000000000000000000000000ae6c9fbf0e06f2e38e91699cd21596ba90f92f6022a4f3c7c8a6557b7e1331283bd4d7a7d31d77d9d7cf70a2945ea1600000000000000000000000000000000066b8132c73e1da8ae7fec9169770a188b686f223fd0306441356040bc9070f34a47fe1bb8c94de9fd7606c18b1d2b1dd38f1a0417a5a366dd2d8f5ce229afb6f34c1b663ad6eb1d9ff12f38412f00f7000000000000000000000000000000001460040d0a19c37fb0736ebdac0324d8a38c94a73fc5f602b7ea5b7255be9d4b6ffc22fea5043d948420e9ae3476f56a000000000000000000000000000000000b37c0078ab8babcefa8874c6cd1c5184d713b976852d087ed84337073fab3054899859d0fac2f4351bb75ee0e534fa70000000000000000000000000000000004150f3b98e6166d9d6b0388342042dd8eff9b8e1239f479330b64c5b316f98fc7bb401b737efb87e1f6663ca4efa26700000000000000000000000000000000043e6131c1ff621fd6f8caf0939487a927550343e24425ada33cf622de757e6e75c9affff9f04373a954557181641617364da9c6b07aada98107447afbb189626180c5eef31f7f2cf26d5d76ab0c74590000000000000000000000000000000009fa1754bbc957d2a8317a2eed859457073571379cc7c6d65bc6a0b5829f8142db77654eb98a2bb0cfa5223a27d756cd000000000000000000000000000000000cfe8b8fbbff7507d3d74f4f550b4c85e19b8929d3728a462e12b4008c79014103153c69ed8dc6b743e1b6fb4720bad00000000000000000000000000000000017ca0c08c320c12502a1dbc841425694bde68b7806eddbb40702e58ed26c7e112f9a821a6c67afed174f51896ec2287300000000000000000000000000000000014d08df9cf825b07a387642ac9959e8cd15ea8e752231a3047fa30816acb1ecb79f1755484af9a98b993f50128c2bf5031aa8d860e3b598ad0c4e9f93f26d153f8a8d8d0dd614ba868ed055c517532f000000000000000000000000000000000273b64e867a9111e257c9b32484655e4d7e676ec50f174d9ebc9fc4262c037b176ada941dd8c1abf645e275dde04f4a0000000000000000000000000000000008a63b9604e96a5034d92e3790411f3112c2c7cdaa056f9f1bdfc0b164c37fc9f58dbb566337132cd1626f9ca2618f800000000000000000000000000000000006a661167c9fb6c26bfe0a3902f309fa683fd22729bfcb433756182e7e1a406bf44ae1d13ef0228534881daa339394e400000000000000000000000000000000193c6c5ec200d225c43c6e37cfd15e16e49b7d87e5515bb7b4c918903966f4f6ae0d42af6b98f6efdedc9b0301fa1c0f290c467c4827c9252b82ff523633ba116c52d15df9cd4e3121ff0e9f754ced5f", - "Expected": "000000000000000000000000000000001403c7e3059135ebcf5e752011fdfaf66e348135314f3f4239b066e1c6192ffcaf89bad4228fcc2be19a64f4f5386f5e000000000000000000000000000000000aadbd8d0e53d5b409f7fa508089337bcf36212a3f613b37a95757793dd6b0ca99d1b3578ad8020d46e29c9c4197ea070000000000000000000000000000000019e43bb32f92ed187fc32d9dbe24a486e38316a3cec0fd7f7c19b313af43a10fd63738b78e609e04a083de6761d53a90000000000000000000000000000000001490da7d36ff16304b27f6e57412975497e9f3a6d35cb162464bcf69fe141d34ae27a33afc75a2802eb120e90d4897bb", - "Name": "matter_g2_multiexp_86", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000038ee0c2c409d8832437ea450ed705589c82791b8319fd0ba6fb4d302d3c5b73ea0521a0253716e5810f03fca2e9dc720000000000000000000000000000000018c9d748aa685bf6e11e6e4b6ad2290ceff59c8837a088b41a08983fb2c5ef077adb0730b298c5df9aa02a820a19a4bd00000000000000000000000000000000015d248426e362ad2489c0c6a567d80b22d54d6a79e198198a771fae4c4e97eb317da9feba8eaafc9460ef45b1a5e5690000000000000000000000000000000005a2342412801cb37911a04d7ee3b1e5d3dce2a06e0658d59f2ddcaa9ba32804a1ddbe8f4d00f4436aad1346ed1ea5344aaa57782608de34c6334ce5039c67767f6da7b315dcfc772f03aaf3dd1e67b90000000000000000000000000000000019d49748f05458cb9b316e433b0d341e23bb5aaa724b824bd147596761c11efe8f4940eae09e302e563e14e96b814f4a0000000000000000000000000000000018011e7ee4988da168adbcf81cd14a9232edacc06bbfef0fc78dc0f96b5ac86ea67be8661442b5ef60e3889f3137182200000000000000000000000000000000175a2ae3bdade6551b23656c16884ba0fd4247df4ba7471cf81022d7e224b23490db153c8289f95467ddf9671f8b6cf90000000000000000000000000000000013c58c0f55c46bced98faf3865e3b6a836252f252e97b6d2a799b574dc569f09ce33082880a4d0c3b8a2c7c0d4c30eae22c1cde67b0e8ec7217c6ec72f36d8a1e73794297819de9ef6f1e52acbd3ec4a000000000000000000000000000000000ee45d5689a8ea6132d5ace000699a157c1cea3c0c98b38d504153d64fcaf1702ac7a1cb0889539d6b15489fef415aef000000000000000000000000000000000b320e0cdedbdc1fc5733488e6d2aece6386a030adc36b0a69dc3809827319947049f3861c2edc859797d30a3689322b00000000000000000000000000000000194096079b3a1d6ab1080dc71bf6d5734bc7b5e7f30bbb0f9b95c9495a6bc4adf76e198fc66accbbbaac215a8932d8c5000000000000000000000000000000000ec07be0cfa9b3d3a64c016471d9e6d25228b46dcaca6e197be00b9ca5087162c35f1d6326a3cf83f568cb06da8c5220895341f4363b688c4e9660fb0cd17f6c111a5c92e732205fab0d0da0175f6832000000000000000000000000000000000a7f3a3fcf2e7b0ada6d4fce179bdf229454002f1271a39d5e99daae72da549c6ccfc7c574f35bb9784100675c30b1120000000000000000000000000000000000fad14ab095fa09bea919ada313727e7aa5aa06a1cc7746d006e3eaf70f79c5e4001a8a8de03540b45e0598b22710e00000000000000000000000000000000015345ade62c5691690c181da09d8f39c1ead42046987b8c7c975d40690a286a816f8cca519731d0ca23349c54b30d8570000000000000000000000000000000019f0a32361bb6ecd8b1d87c2e15d31c0e0cf995eac9facd5eca123c0799c465f156b0142d98e0f315e9b3595974a7b824c5718fed7503c5e2a97fd6ab0294d6c42b1d35067e9d5ec1077176a4bd3126f0000000000000000000000000000000017af46e78904915e348734d2450fc6e1938bcf002989f855082e3b4ff3366d81ee8d28293609c3c3b11568668b1305f80000000000000000000000000000000018b0b3859763c2654fc00792a5193b7317fa5051bcfd15ea42be2fda0f43adf322219f34e54b2446ef73a4562151f9a70000000000000000000000000000000015c23509a1b324c649ff878d004ab5f253d041670ef172ec4dabec7a525d5ddb8f9f62f383e3f71b0e9c98532e247d560000000000000000000000000000000003a38564a55fdbe05b047281fa153f736edbf48c901749005473255333590f967171a6fc88751eaf57a5335bbfb6ebe86d055ad484f5054e8bd0d073cd556deba05418ef1235d08ecbf8717b550933fa00000000000000000000000000000000100322c4a92c136437714a6586c82a6842027ee218bf1fdfffaf95ce47c9c8b6c8f61115b092dff81ff2e645d0a7a4340000000000000000000000000000000013a91ed8629acb5e770683015c3c248255d673d4b2e6c96334d1c80326d1a8b4b655c81175e4a914a45fb37c1f178bd10000000000000000000000000000000019075c2eea3f64f42be82fdb8f83f2c68c08e858702a0225d869143c0b017b76a7a40d809116ffbdff6700b288f5ca3b000000000000000000000000000000000598ee9ba9d56400b59c7f5977aef1e179855a37179fbfe97b95f19137b6034568e5c7f616943b4aca804272955d42334cccbb062c27a67ae2783ab65a47ce166330cfced1f11b85f87483e0250b138400000000000000000000000000000000025a526b137aaab5ac1b5f8179a18b06feb7c905b4a843cd55e31b7464c2b6d432b569e9bfc3222511c18255102aba5b00000000000000000000000000000000090c20c9f78a242e52daa339d5cc1c3f35aff7ab802a3e4366597db8b6ca43d30fa0fe8d9484e49fa4fd0bf5509f19e6000000000000000000000000000000000e928b2173e32e5fc9c373a2a6f126e1a3a472c01a5e87677be0d29907022b9a7dbec3340cfc89e67377ce472c2d5d4c00000000000000000000000000000000147b4eaa2dcee39b918b7cdf24483b29466120677e5d42b51353a9b2fa207bd911d9b391142a13a212d0ab38adcbe10796111cb1181f048f51349aa2953bba2af50f7b7b5d2328d435bd63a7df5cfe5c00000000000000000000000000000000007790cde9ff8af2d7597d33909f00963eafa228817de1ebf4233ef0831202700b99641318186aec80ac913a1b1143eb0000000000000000000000000000000009d42ea1386d8b019dcd26068ab156f399c35b7d492722a20da0c915f7abe44ba688d9486f4bbb44268542c5a49168930000000000000000000000000000000010611f233bc1c4af0a14e1d1b945c91c077ec3dda592e2f852e2de41e09331664e1a92f9a0b7416c50327bc943a17b9e00000000000000000000000000000000048614243262dd070a754f40652b96a03326fc51273dddabed85df0654890ff38e0da7abb8190e4ebefdd6f78a5fec509d7f0c0c7e927bed3fb930fe2d0109f58678969ac8e14fabdf4ccdd0823f706d0000000000000000000000000000000008451d24fdc873c61db44e57372d43c35a2a8098255f9aad3a6b244913b86bff6444042e391685b1244f009c5ccde935000000000000000000000000000000001177c2da9972a2b96afaf866f97dc149482fbaaa93e194803c09c8334c2c7025e08cad4f7898959a57b07a545ecf76ad0000000000000000000000000000000016f40426cbd1f0f4ca5ae1dfa4c3960a6fbd51a1b5b24ff5d03fb9911e908406a0ecf4f20a78a280d24dc9bdd1c0799b00000000000000000000000000000000194a8c55f549da1842cc3173f3eb7bfd70df26b43a3059a3590992e34fb19b2caac4149f64d442965e166225b9013e2b11ce517fad2609f2ab8d44ae6263623a7903b2cbec683570949a96fad78fc6d3000000000000000000000000000000000a97664c1d7624cae0e969c728a84130fe260581305435ff8ec701cdc51a73977f58c891ecee637eb6b7c972069ebbb80000000000000000000000000000000003f4ed6a9e9f4229f0fb35394bbc10da9adbf4985d4453da64eb312ec88cb15bdc189a3b5df1af3107a36fc001ec92ad000000000000000000000000000000000ac552c5f6170a70563fcdca8e0c6a7c6135af2f9d5ae6f60a2c459d1be4cf76ebcdf9bcd891db8a1e2fc905a23a97b4000000000000000000000000000000001734a46c99e776d1ed4b807f5b313562e0989ad5c67dbcb961c134f8b7b7601c23308839569dc224bdf7c370c4498303b17d28cbcb9efde6d9cdc4c9cda385ce598ac8468d4fc94cc8e98ca3bfadf440000000000000000000000000000000000a523182c886671435ccc75cbc78293274802c6142465acb31a1809e43b1d656ed9c808068de167b1ab126ed0f73a4490000000000000000000000000000000007c4616080b5a002fea3589d54c7510884a3ece705d27dee315851746b1ee748e8a08d3516d8c6afe1c0482b960a9c62000000000000000000000000000000000dd1bd9b4b9c140aeb97887a0266bfb5696813fea034b78bb7d0cf1cca15b5bb0ed92a97841c8d8cc614f7721b8b7e040000000000000000000000000000000012a41a8941b6f0e4c87f8188718f9bc75305d41d6f4441eb9682473340fce0bbb463e1b922d3af8daea32b8a8ac9c3b4a9516e93416bc7b0f3c5ef5da6112abb73fc285a14093ed19d8eddf241169119000000000000000000000000000000001763ab2b361681955735ae00b69f26e06469391af993c8dc6f2e1dffb52ca01e49d58d6e2249e7433ccfb5ddaf8fead40000000000000000000000000000000003858f3bb01b2393aa4d4d7889bdeb0bb9bcde0dcb9b39c4ffe0fcd0b865baaff75b676c715be275929ff4303c416e0800000000000000000000000000000000086d64bd1302b0b3a620b87ac29cac3d9e606513ec8b47898cd852bf552c1364291aaa842616b92c8936e076e59451bd000000000000000000000000000000000967c9f59c15ed02c9b2da6e76fb0bf3d445ba849010afb7f9c994b1ef6a05ad577570d4adad043796eb90e51537ce5187fed462636eb57506f870ed1c8f66e211758327f4c19bf909a6419312c58945000000000000000000000000000000000e6b0da7b406bcac2dbb90fbf430fda6442cc2860ce633ab84404dfbb426949d55ecd72992da1a2e8e1ce229b599232c000000000000000000000000000000000fbe3a345ffc8fb85cedc4b8dedf9d952c41b4ff6f1c7ff4cf91b2276621969d905aa9aae5fc89bc516f96b9bd1bb3c10000000000000000000000000000000018c2a7fcc35099c41bb851ff66abb047e2af9cf4fa9fc45f030124ea2c7efd26e594abbfc7a7f258c8081a3a80d15105000000000000000000000000000000000a27cd33c2121c9c542e27b52a13275ef7e81dc0c6ece883b65e71d2bc3e7246f95aef7c6b41eace382a1400568cf298c373d64034c78482d6673c6906553151887c8aa28ab2930659671b8cb98a595700000000000000000000000000000000158bd8e6198d22b52efb7f3b945668666e1190a4a8e70307ba5c1b737316a8f8568092f219f683c0f53f56f25745d4e600000000000000000000000000000000097e64e4553371c81a9bf553ddd9719f59b329284eca0d76f023d603c29a034d123ab777cf173c5f2bbc66412d69d4ce000000000000000000000000000000001298cd5501e136a06ad4fcf87a75c0c7b96c73e844863b74bf6aa581a0ea98c2b1f608c668743a3e37ad5ca2074af9340000000000000000000000000000000017ff9f1336d7f2152f17daddde9d3e1679cab8120ed2c0288b0908d4e2099a08c9bc6f79425f004ea3ac4d684abff6dcf29c901f9769a42610958a8cd53eaacd9e5c4656106fab536052518b4989911700000000000000000000000000000000115baaab8f0331894da531ab557bb454e2003010ba1dc1d96e3d983d49b1312585c6d4c43d85dc074b23b2fb28c8a1d6000000000000000000000000000000000db1621b721c8a54ece26a355b190af5f3e1dc1b43e0827a1912ace651cbad4b980e77a4c3566aa809157229b234c808000000000000000000000000000000000c594e0ed3f7ee55886e251deef9732aea3de11f094ec53907a843b755add8fa5d00779a66621e615ba7772ee821c4030000000000000000000000000000000004e80aeff6c4b85188903b4d2dcac4f94f7cb4285a38f94b0becb556d83dce8735d1db5810b409d45a8dd1b9a6dde29c125c12599e84b7e648aab52cd68fcca7f1a5f56c854f3c36e0445ab7e2df2b740000000000000000000000000000000000371a74468ce2ad90e19b7fe3f57159dffb1b0422b32ad693b2fe6c45c5d371b97a90054095da887019d25c1ee8197800000000000000000000000000000000010575e1ec9a3e609ca086ef8bca679c4548482d9e0da2e51878158ac8e5b29d824c31ad7ff642041e748efc50c2514e000000000000000000000000000000000ef36130380f1e84b2f462b5f970abb8535431b79813015261015c6d7e74f038b47504de01794840d93fbbb4b386e17500000000000000000000000000000000018419e85fc2d75f007d1e0e02c1975332e03d42c3b41c50c3538c3625e702161cdcf8913babd2995aea7566ff15abf2bb9a1d051e33a617c25e17b7ca8ae6b02f16c759cae0df7fbd403372eb2407f6", - "Expected": "00000000000000000000000000000000125406a942ae0119575453beb4c093d2696d3bea7bc031d7a586439197f848e1d5a82b925b4e96138a3460eecf198ffa000000000000000000000000000000000befcee6bd1412c54674a3d519dd2813b87b18f2ab3375a731197e9f539f8f8fff634f15647e7fea3c65b93594343c2000000000000000000000000000000000011e4d432ee6babd502a9cbbb5cf4839dc6da6176b6bb0ba51d99a3587465f5f3f83f4d4cf2c7e6187de93b859ca61d800000000000000000000000000000000168509010b867aa198fc294a5879ce14a51503c1d0e8fbc02ec08cf62afbd357ceac24b633bd0fa99f83dda92e10724b", - "Name": "matter_g2_multiexp_87", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000070a0d060c6e9bad0d1bb15417578daaa8b7a5c984c4947dba10fd874d93fd1e3994337c87799d78a674087678d9168f00000000000000000000000000000000128985b69d5d6ea0ad0b19eba7c2b430f5242a7e89626c66fb83b58ca7cb65a479de4b2fca6886cf55b8cfb52394102a000000000000000000000000000000000bb0bced708571662af042d18956b5b7d797b61aba70823618682287deebe69bf1f9a94ca4059e0570e25a39e60b9a8b00000000000000000000000000000000193f0793324dc78c40f356dde030b632feeb1609a1bd75ce88f0d313a0864dbf1f5e92826870866ab9b3c98cd1c12aa508c35887835bf4497d673936f40ed44145c5d5009fae16eb0f3ee9168831abf7000000000000000000000000000000000a61a310f90a5ffde617b78f784b2e699cd77e7c3e7c483a2ccb768f94d68e59a2a4521410c22ef6f21ba589ec3abdcc000000000000000000000000000000000e6568c83e0f7e459b27a28e5bf954983c5dee478a009c244da16041e710ddc67479cdb3da6f47e7203fedb8f765b2490000000000000000000000000000000001c5cf6b948b85a1c426fe932cd87605f1fbf6c932756eb1bfb43beaf012bec4612d8dd0840efd4cba3f5394beb65112000000000000000000000000000000000e02d5bc20c40d7cc2165a21ab37c6e4eb71322c01a43f2085f93b5b02bcabcd668dab90323db0f9288737d757997631a0154f7f8d52319c9e5cd59052e91b84640efe83ac814d95370e46aff4334cf400000000000000000000000000000000165287d72eca1ecda5fe16a555245b0a34a04beaf9177466bfd88bbc675442d206e70f7a2063b6ed0e15e9406232f5ea0000000000000000000000000000000004c0608bd7e01e65a15716b0c505111a3abb0abac3efb846e05e8db59c063950dcee052f04d1c4e9e492bc6740fafe6d000000000000000000000000000000000de897f7ebaf9089f7e198ee41e1efd7d84fbec7327799b9293a489965cd36159442eb0dc1f79f6b1f122f592b013bb30000000000000000000000000000000009774586dc359e5d20486f00dcea6ff93948c5a8b74058645d1048fe46ae3330dd56d85204d328f43f15e674020f353ec252ac28ea29b5459cd2ae5bce4bf08a102280c093b9962cafb481016a212709000000000000000000000000000000000438ee51a560aa419ad6ae45e1014c38b7c43f1f6a512bccc2d4f10a35838369b71799fab4b6a754fd938c1a1b874fc0000000000000000000000000000000000c1491c85965c0b74d08f5866ca727fd30bf641a6ada0ab8363ff01916c37d10b1b7eccff79b396c587d9beca2c826c0000000000000000000000000000000001452f254ceae9626443265ba31a1a750a425f2a7789e69cde16b70eb319c744a6221e74a9e2881c6bafea161d29638df0000000000000000000000000000000011bd6a1bbded174e9cb95d74492f7b07a755339a6c40f2a1a76debccc0f3a32c7017ca4e6679fb2c038c751f19986f526d3bb5ee3410dfad575b0fbe71ac5df2048f74b52e777fe0955d6e244d434f3b00000000000000000000000000000000139157c34aaf70cbfaa82be655281b085e37d6406df4cf8e291b221394e91d9e3cf04d431f15436064d0bfc8cbe13701000000000000000000000000000000000353fcf6e587e71e59d8f05d4085961d37b1f62694dd5c7f40efb5875b90459dd66c4d2d6c01a40834307ae9e82c2e08000000000000000000000000000000000a4975c9872fd167d0ff4cc80a6ce179b1e6e1eb21c8de80321451b1deffe68d8a13db26218f14935b64af25d63644c10000000000000000000000000000000001e8a2824f21cda745a24844ac0336994fb18e30608ac61201a932c0a5a58f1acd56cbd9353bfab4944efcf2859ad5915c30684c596976bf46384e6afb2bad6f821c4a62338d7a6eb204ed75070b1973000000000000000000000000000000000537d7a9d7d9dc451cba4d50630caed32e182cbbd95212577b8c2855c327530e447a4f3d73c7d63fa3ad5111254c9ed90000000000000000000000000000000006984b32955fac4ad3c0d181c81b98534ebaddc316d51a40baa1028bacd6a93a20d4bd6cad6a0f8cf7ade96bcd4d68dd000000000000000000000000000000000720c392a663884ad4d8daeb7279ac41717ea602108c76519da13a45a77d2acafee842828f5ccfcd786bf7ea88afd01600000000000000000000000000000000081f1d3e37ebaacc11671bfe1670ed65ece2aee0e3b5d746a8d618b44bd4b7dea905eb8e958bc026a092b2bd5a7b87cb11009058bb8e23b0a4294b5cae63aff10265e729d3601d85dd7f1e8063ce260a00000000000000000000000000000000005af33731879a574f39dca99c5c1b9517eda13121221be77a0c1bac82fbf29b37889c15a9d32531a3f6bf9137ce82dc000000000000000000000000000000000c62939f00d70a07a85804cd97fd34b9764565bdba225cdd7549729ceb9735bf4d09a80ec3055c483e1e24b66c41e403000000000000000000000000000000000e415677988c9d4656e59f77c608926c83028f91bf4c0634120b5f774ba07180b98141ffdf727cf9d0fc7a4cb52f4393000000000000000000000000000000000c9c37eaca857151a0c4a49b079f2f061e6a8ebb77e11eb32b29227529562f8dc8e2646e25469491eec5a07b11943f203e5489447bb9a5b661bcff2d9a4153a5aad975abdec380301b6d4ce019bf2cdf00000000000000000000000000000000015113f8f9100cd18427ff48038e1070fd835fce6c0812b7bafa679ac733c80bef56492ec3ca08c1117bd0edf19cb26f000000000000000000000000000000000789cd90c0be1de5d0b359c030d4b9d8aef93951e26870e37c375b9e7879cf277971a05babd319a3a6ac53f00f3254e40000000000000000000000000000000019b1cb91c9a1b1ee49c3837339778806bf0c093f171c92c9931ad43e35fc61cc08dafaf55b7b9e0f49dac28a12bcf92d00000000000000000000000000000000066c7864631333226f191e313436453e59f48f91d42e68874fa4da45eeda1f6f7f6342204e64e124d5ecd861f02ef4f00444d520ee01d87407747a4ac37abb7bd4e4c4f1735ca7458cc2e4dcb1d6297c00000000000000000000000000000000129d887d694be0ef2f84c343a9aebd0a2aaf19a4e78586470351ffaf0b1309593363bd9c6e7fe39a6e59445d935414ef000000000000000000000000000000000596d7061c2399b6a9be7d4d495e58c0377b18db1e45cf3eb431d10cb8b15ae42548a86a26086d57b1a71cb5857d7917000000000000000000000000000000000cce7181fc87dfe1bb493043279a5d93cb2d980eed38dab2ace8c9fb335c2890447434d80df6e7c95729933ada7b9d8f000000000000000000000000000000000f0e1274ff70bc6d3f1d0d5b251ae528ed94aa3a1b9bbdb260892bfaa6213892071b8a6407abe26105b2f81df90569492035cab8f8120ea8e91389707a290db4ee69875d7429c6857e74e8bd40dc7360000000000000000000000000000000001192050735b114c19eb2bb9aa01f04d1fd9bed4df877113a14f7fbc9c31acc10db3ed0e0d15d8433e7408bc237c985b9000000000000000000000000000000000a8a66cda780790311b56836fe69479c7b94dbc6c82ed5886887dbb539a40390ebb2683c04078ed105e639a2ed8732a1000000000000000000000000000000001678ddff677b99011c73e0c9875b5b2ba063170f4d565d261b4c6d3263ccce0334b5bbb7ee08692568037fa96782e48b000000000000000000000000000000000ae15f79ad7f790f8ceaf7709f4b5da71642da0c1f7c442eeaeb165c7dacd8a4892fdfc8447a03a7c56e12513499e43c4bec711286827f0941ffbb451a8eba871239341a60e3aaef23487175c9d2e8260000000000000000000000000000000007fcb5ea5358074d06b64c5f46454e682dd9ac2127374c83f3ac5ad46bc5fd2fff7c5a80ffc669a1c159ee8c9a01bd37000000000000000000000000000000001010ada1bd493d6282ac2d3582480f50074a02fdf412c63e93c5857974626ff464150c20bdf23a87692bfe69a075eeb300000000000000000000000000000000086bb5664a8738f02af5517aec4c6db47653a6d76bd4b5e37ba4d8b27a7819e82e6a4c7ba4f8377e06a5878e7c0bffbc000000000000000000000000000000000be1463ab76e468e47e1711c158dc9bb10d1278f5cc676cff937f60ba457061bacdad7b8d3286f40219963b147cce4bd369d91a4d575d4c142b98a53115a792ec50a290608ad316465487762e83f3a86000000000000000000000000000000000c3329d1e1c76b0bcc7ca3766b2cc5ec8169690f45e0ea3e37b7173bfd6c884921c7523ff25391a85b47d5de395ca63b00000000000000000000000000000000081ff066c008d5a4c893a636d24e9752c6a06666dcbf80082167610e73a32d70aae3e58c88ffaa27f05260b86b11f72a000000000000000000000000000000001178e88c652d257888cda1c0b65ee2c0636184194fef9e6ae3791a85417c43a31fe75893773ff3e7b4d4cda9eafa8de40000000000000000000000000000000019657ec4604ab5e8812237a28e5ff320a0d728c60c541142ffd87fec2c703665638e5eebc33e308d5582cd043d08d788ee472561535a7710db521976cef0c92a4ed89861ecb397cbcfafa477756e8e120000000000000000000000000000000010789200f69d8acc70f108145804b62b521a30a04176c449f52bedff5975ad7b273aaf4a32f8461ced8e92b2229e2cef000000000000000000000000000000001178c36174cdb783b5b09d419ae4a154512bf9ce07368521d1576b2f1bf39f98be29bf533bad16ba9d96aae621612aa70000000000000000000000000000000002580f2115d1814667b6178b6bffca6a4d992eb66e9601c0d21e32a5f3b69e3f85e1205c877b2dc2696a0e872c5bbc6c0000000000000000000000000000000002c94d7ff016d57bd5f589971344c6499577bc2234e18e6c8dfd7d27a205442a4236ac54fe279d1bbca76467530140b42cfdcb8240f183abec526344e8ceca6a007c35b757928803f854225d3a6ca36100000000000000000000000000000000108b6fef7396ef71b46339d421726f83b08320599d66da18234011720d2b524d24075a255d2771f1ae904958c50a9046000000000000000000000000000000000723d5045b65c0887da1bb01d874714ac86d21441119a93a1d5758957215f399f5ef1cbc00558db01b295bf0cc988cab000000000000000000000000000000000994914a3df9d3094dab0c0c41a45315dce5968a99e6171fc609ac9e50bee5ccac771efaa04067467e95709bd924973f000000000000000000000000000000000ac746602f804f52e9a485c30412adf92eb9af3f6daa8f23b974339a0ffa6f5aa1b70a80a9f19cde2a69a4b7251ecf5d60659743dc1977a698371cc302b7579b6d7d13632a31b47df369365fb02aff790000000000000000000000000000000000a2ffeaff148dc5f70fcf53e7e8d7b6100cd6e7df5b3fa4aa33bced243f15b4f77f48d25f74366a693404b6ed7d3075000000000000000000000000000000000f3e1b34ac8fde4caedf3d8c3e24db02de3f91487db300f09c779e7e4e96ae55229288abd946abcc3a8adaf18a0c89e000000000000000000000000000000000166a68c5191dd7f9d44eade2ef1a9b522dc062bba9c55e2ff03aef400e5d2765a12816b4ba51e10bc21e06113c8ddc5100000000000000000000000000000000109c00de20f7e827375c1841348e684fdb248fad116e9643dbda8be2bd06b71db264e9f2c40dec2092e7d518540a6d82652a5d4fdf6d6703c857fc7b10a741b95fbce91fe823d827cc7203be3b3bce0a0000000000000000000000000000000014ddb61173359514226c150a3343576b04fb1b06fabd8fe2f921fb3b90baf5513447c107f6d2f96c8b03274bfe451dca0000000000000000000000000000000001d1064860f6c4d62a282147308e80ceb0c5dd62f39b3232a231b1b287e497df31cbc5a3905a7687eb2f24447e50a395000000000000000000000000000000000859611bb3962955f92bff861e03d07bab7fe1f69e90c6bc7928be8d1758c9194ff7a52b16472d04564607b742543eaf0000000000000000000000000000000008a3e8396901a205a071aad06ba9812207171f33775eb358de4232826a5f0ff50ec3e137b1344b583849e8a5b424b46676a30abda185e7d280804952fc0c074ad907fea2aa54da4c3190895270169b20", - "Expected": "0000000000000000000000000000000008c9db83241e7f3ae6c2eac8fdcff5f2d35318e24c3b4130e9bb7048a3b84a52fa3f222a8190121d2a5b8835bf911bb200000000000000000000000000000000002db79cbcbabf41bd8c715e024f4687bc0d058d76b8dbe58ffdb80918212ab6e9b35256fde583c0fe903c34a4c41ba70000000000000000000000000000000019f37d05f5c9e65c6f004e1aef03ff0e1899f0739c9cc4e9038e18f9d45678388454d144495b2cd993eb3691bf3e96f5000000000000000000000000000000000d8e0d7715ed71291729bf480f5fee7ae04264015732677488472bedc0dbacf8b35eef7adcce196e3bba9cac0991be81", - "Name": "matter_g2_multiexp_88", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000064a134260b753af73df3764ab662e3b1bd624c8f3248e9bcf7676d8fb0825ab85ea33387d4641c81fb8ba3757e0870a000000000000000000000000000000000d67eff1936a395cd3f808ed7fc89f8b6a227c4849a6941d4bf762af6e41ae41c8114aeccc2565ba01fd902df530df1e000000000000000000000000000000000110ca2339832e7a9468844b94b3ced0c9216654bef1c8a5cf66385a99d5d452f978bbb7fe15fb477f56753488fc909b00000000000000000000000000000000173210b548d1b98b926539049996713f53108cd2911105235c1d5258360d5620d330951db67219ffaa304a67fd6219f39f4db766964c7855daea58d1205fe8da572aef06e0ca64912cec7c87bcb2f51f000000000000000000000000000000000f7c3795ac3d511f93a3d85e65261e4c09cd316787f74ced6e472a3993b7b5b0ce5a7c91d99559a8e0791f712cb4e1700000000000000000000000000000000018eacb2c5fa9221881c6311256a69c7616748deb3235c61cc11412860450151a25e3d6a220bb23e0b3e3325044fba68300000000000000000000000000000000121827286873ad31f58cb3889fd01cb7d0f91ff1c241295f6ef2dd0e8aa8638b63a7e6061efc2e7ca1d3579b4868f0460000000000000000000000000000000003a57315175d70880b2b53c67d61831ab066b08d7ac68637364ab1c1f3efad96d42a3cf5189c45012c1f73a1b97bdb4c1deebc727d98bdec47b5a1fc48916dca1e42345ff5474a5fd6cab0ae99e9f10800000000000000000000000000000000180648e5d0bf727101417f515cb9578bdde3e9f6c4176d516454ea7c32c1712610cc8bbed303bd1afd48f580ec11b77c000000000000000000000000000000000d6ffa9b85d69b67abb77f5c8bd776eae82d1cb055d2dcdea31ac66b1825014ec7f7a2aea320ef9f6897c9aac8c0706900000000000000000000000000000000073214fedbade28cc60ecfa4e1fe2fbc05f3d71528aca315312d50214f680956bb9e0fc12783843b00b3f4f0f52efe2700000000000000000000000000000000128f87e7da7b53f28944aeb26ef0f6c99d84038af51a1d242501ec84b5a6a8593ef1a0f6b523478d9fa12e36c2fdbe694b964d74259c216c1eccd7f2b52ffa5fcf151d47bd69bd2768e6466b32eb4fe50000000000000000000000000000000001443980d7450af1e19949fb328776cb7238a9b26240cddc565aa9d52c5592083b1533e8103dc07eac80e4bd830f209f000000000000000000000000000000000afdbea7f1cec534c03d3269d50017372f7ccbcba9f096fdb2754af4d6b4956decbab2b0afb69f97a03beeb20b4ccc31000000000000000000000000000000000a83dfa3197dc65097601457a97d0df7710e001e90657b150e289515609f13997b454167a7589ef218893309460139f300000000000000000000000000000000029c362244510c342358130f877de947acad5a379295f3149d5c713274316e06a169501f889e4b9cbf86f10b9521c1bb124ceb1dbc8004a4b1f8b422d394b0480bca7c0f38aafd8f06ba090a98a1d3c60000000000000000000000000000000010a83f13a185c70ca3f724dd84efcfa3ec463d7c05360056f8b5304864b20025b0a82c9d542ba08b645e2334f176472d000000000000000000000000000000000848a6a18bcf64d083e118190805d68f7ffea8b5a66e0807b9cd3733d31ffa5cc25dbfa6ada604646dcd8dfa622e08a30000000000000000000000000000000009962205c0ba43e5101fc3d5353f429a57a97bcb84baa0942a7e7facdfb0d032b9307aed8bd2ac9094a2e5b1460db7140000000000000000000000000000000019b1012661a10d31a4a73d0cb31f7eec0e7be729a42baf560c1e90a9124fe8d5fe31ecbb6d4954dba7d943a7af773eaa5a2bf15b2ed08b33056a0733c920741f86730dcda9c06aa0e3c135a844cef916000000000000000000000000000000000e7f02c1d2ceae60f314f51374b338c329f2eaa82553c3fc1643c7f1910ca24e277f3d658f552a47f780d4d9e0ac5e030000000000000000000000000000000014b6b56afc4afed5199191ec13dbeedd797f14ed493c25658a9658f031ac8d43de12e6a8c4b1671c9e5ef78da1a55e2600000000000000000000000000000000194d8a50618ff55ba3fa5602d41cbbeadc01a348ad1484c5e9aee5fb7241fcd9018f436e3c6c6dc64beaa241513a6c8300000000000000000000000000000000052681eac4bd59e160b67ebb27582a6d3ad5286d652787a0e160026607acfbfc5b9f38b9b171375079d052cb242b87fe8c3c919f31d72ab414f91938089430bbbeaa53ad7a73224fd3f204b80fa1ab87000000000000000000000000000000000d96ce83d917204e674ad9f5e5728651f5f23df25236b0fe769be48adf482ed8c36ad9c9abb6efa3719bd35324bd700800000000000000000000000000000000107f55ab0e5b60dbcc0632c345a9e93818014d7657b264031709275744e1c6722ec63aa209e655878a57704ca6cb3bc10000000000000000000000000000000018d97fba324431fa28b8845d94f62fc9eacc0253134b923908f06889d375405b51610ac21a75bdfb27e3533dd4debc22000000000000000000000000000000001667856804a5471238ffd64bf3bf266ce3a2351ebc68265674bc86ce6faa8dd50a3dfa00c647fb4265951b3a9607ab99f749063165c6db0eb038cb9f1a573de25bf377e1fee94f31df5987f7b2450aff000000000000000000000000000000000fde2fd0349e7a47a9b6858014d551aea569ef9802629bd9520e303ef0487c9d2d399682ac16ce6fa03adb6f4b478fa5000000000000000000000000000000001858ae58920dd0abd8ad94d2f9f946c53e050fe89c61f62fccad37e17f8723a4fbecb6b1be1e3cb853f045d0dca8e53e00000000000000000000000000000000093615a7f9d12e92c90706a47abe9620c4db41e95e42e478949745d6b73e021422e40b969e9e34263778c8a4d4907445000000000000000000000000000000001006ae7963b1e1c4d8c2c85175aca958758fb380019825b09ca3f728b5356254ae4fc670aa29812320b921b48a069df622d292cbcb836843acdd5a3fb404024174cd5c1cef632d1b9b6a73f2c5f705a3000000000000000000000000000000000ac407b75ea77789748e7607b5d6edb1d891875aeef2802715ddc393818fc8cbe82cde9f96377e3ac60107ddcda7e6610000000000000000000000000000000006e63e49356c38b816736d1d7c360ceaaba875c53c98ec68cb825962531855dc6410a125b914b0ad99f6f4327f5450890000000000000000000000000000000018ffb4ac95b8ffde112c8bdbf07a1c97b1d30a42dd4a97c82617698617ceb169e8702437ff6082a2ae387b462cd86256000000000000000000000000000000000497c4b3788c4d6c9b4cd8b3d3569ac4b4332b2f76c5f03f112e089bb79d33152b2469f7ad3eadb8b954775aab73f47de816dd1bfe025685f2eff0856f9c162d73a58fdeae0dfbeb5ce076e9f9ec1a700000000000000000000000000000000003e16f2f5a2fe15fa02b6217aed7dc688dd2670c09c02791cafeccfceb7d99ce826bccf213f6a7c6064687519f9283de00000000000000000000000000000000095e6638ac74815dc451b3ec85a6a8cc18643b541e8be99052ff6dad39c971f2e8bee976ab2ed5e1cdacf92816249ded000000000000000000000000000000000f2703c08b1d707fb6de215de80b53ffbf2ac48f3dd059d2a952b1031189248fad27beec5c8591ac93625a08e3420f0200000000000000000000000000000000024ae36412ba6f2fdeb0777b892f1ed7bab0527879d93f7b71b62f437f5c1ad1f04a5a7380ae5990a455f11870c7208304f117d41a011d36f55d0cb53d4f98de3b1a6cb55dc8a76b29d393bc21826ea0000000000000000000000000000000000f7ab1908c6d4b152835f950b604b55fdda7eb55c6b90c05e98626ba7cd014683bd3e219fd0d5983e9dcfaaa5d389e560000000000000000000000000000000010b285c2884dbdd540d6dfeca704e00839337f12d2267f6a3fc731fa0f724cde19e268782b4b9c2e11ec3aef9a72a6ed0000000000000000000000000000000014a40cc55570e8f45369bd9dc622e05f03989bce6a98a0d87f4fa7add67eee3e2ad9a297615dde05e64203e86153ec230000000000000000000000000000000007f2b6a092adc595e4857e821579801301396321d4a20bccb3296a031d74a62bd79ea4ea094d2e545943138d2fc930fb6b6f5ee0549b28a1bb317cb020ae0e031dbc381075772ff582718fa49db486d200000000000000000000000000000000108834a685455dc0be10aaf54607a06100673140b012ef23a16d3df204a81dd8505d62ca3e0278a2581abc59e0fbc421000000000000000000000000000000000bca7130de9896e8d6858022f24308af7ca66fb4c91f38b30f717c5491996ef4cdb01f4d38a730f9ba9ca5af5ad1de7700000000000000000000000000000000007d60ded107a06114afaf741dc8826f9e14bac6014eba26089c4e31a73b0f30c4b6e22533ac0db7e73621cecf753590000000000000000000000000000000000b538213a703f7a0bbcffb4aa8ce25ba2a538bf599d3c0251f5e8acddfd596c9912d4cf9a1bd8d3ec070713328ca992205edf9812adf95c9844b2da06f75d96e742c0620d1cb0d47dfd9b68d0bb76128000000000000000000000000000000000cdf0b9bc829cd8537918d665e5bf344d309678d01ee80c71a6d6efb45ee8a7beca35bb5ee046e0a3fac76e1771520ff00000000000000000000000000000000014e5be9dca2f8ee4da18e5ec9c4caa891dd78acc47f553af584308c72988435b85ad21b14abf8421bdb9e25164d568f000000000000000000000000000000000accdde22a1c479e47a17b8da6f1d2b7f780ac278c68a68090e5402977d897bd734f5af8164118d613f480c1f65e5d8e00000000000000000000000000000000029614458afdf6b572bea02a0af987d178c43650ca1c80a297b1d31e259aabd3e2a2c8e4b2c044466924dd6e5e3483e6f64a71e4e7652860038df67c99d97b1e5a063370e65217531253419bf2e6365b0000000000000000000000000000000004e45cc43d4d10ed878e18df156062c799a687b8e6beedad9fa6f66ad855cd053af6918e234ff9a43561da7e67f3dee10000000000000000000000000000000009c9ae47a76c199c93c38e7213c8d6c030cfca709714c703839b9ae9b65207e83486f9c8c16373e2b37756f3fd4355fd0000000000000000000000000000000001594ce9c2e229491b22317452938115747515ce62a0d49f4dd12667f5b3e7b541b3775c9b1363cc185a539b9f7596330000000000000000000000000000000016bf68e05e32168c69ad67331d7bc88a6d130fe8aed3e42eddfeb1d92add266eb69487b246a3ca961ea6ac0a35f8da78059bebd962501b8381b67c22055ba01667d916932713d7ca427cd80d8f76b41900000000000000000000000000000000080d165c57354f87008eb97610d4a596f180e48ed3190779591a0f7e07278f8d2fa6cd21d1b10e6347f11bd9731fdfed0000000000000000000000000000000008d5a1e66ec76743ca366be80fd1cbd5efc9112dbcfa84ce6c44e8df03140ca5f07d4bafc6c6ce5f2f190ede55fe8718000000000000000000000000000000000d0e1d2e5ef384a4fb314fdce54ab7895f895b3bc669acffd48e92c6320024d4f371f42071fceea550c8cf68615b00960000000000000000000000000000000010beae4ffbb68cf6e5d0683dc0629411ee14563f84788d50b1c8755b0b06092cc0f0ef7b55a39d51945b5178e374f8e047b3448b9b404e184f7ff20466aef3dbd4e08375673ca31fdb303c88243fface00000000000000000000000000000000161486d422462460923bd98834f0cc270982087697747fe40eb9153a7923d48eda191e4e7a75964f18f1df9365901a360000000000000000000000000000000017ab168a4ec81c8db4a74d529670fe6332b3870004f696f3a143cd1a62abd747d94afac9485e5dc19b0f4262dd379c990000000000000000000000000000000001e9cc85f03039ea53253f0fa2420012171fe39ed8696ddfbed57b80b73476171e59631388d75fe43aafde52aa14a64100000000000000000000000000000000109a5d5449002f4bdca44c0bd141175d5ca1cee449302f0314fcb5f282f022a7a3cef77f4e9fb515107e797726ff51d767d9d30b38b252a0661c12dc69127ac380f3f756144801633e99bc2ffa2f463c", - "Expected": "000000000000000000000000000000000aaa5de171664fcb45439b17a024806ff7e07d02294e0592ca74752a5b66f3365d1b49d6893b3bac3b8b0d10d026e48d000000000000000000000000000000000418354ce1820ecf848321a07ce22117303e5a15169a9cbfd141fb4797de8871d84d577e86270a9cbfe31c088ceed0250000000000000000000000000000000016884caa03ea641e0660a790975d77c5bb03568f873800d0559b69e3e0afcc10ddf031bb5c25c46f136f0791bbd3cc8f0000000000000000000000000000000002bdf659df76cbaaec030448e8f4bbd6b424037a8dfd7c4b8ccaa2224b0852c168f49c6f45c04f23abc85b8df21953ce", - "Name": "matter_g2_multiexp_89", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000062bad6816308f1c8c6941980caf71929a4006083dd29827902ffc92ebd9b14f1ef662f3a0125b1e74dabd039f9106400000000000000000000000000000000118e4ae76e2c321a5b89eb19b58f58f44e80dcbc7bd6d619579da40e1156aab32fe81df8eeb1bd047f96d65aed8b3b6a000000000000000000000000000000000c8c93e1beeb4efe52a96e5d5612338721e3e487c13c18b02475f9ccd8fafc2c95101aed291951f2031bee5216dba26f0000000000000000000000000000000016fba44e9aa39a12ae27e3c36de1f14e3f37ffb0ceaf5fed2a0d9815eab02c5aae91b254812a8f3a2e3654cec01a341caaea75e63204e177d404898aa51555767f813c3f3ed283405ed1ee829b04c85c0000000000000000000000000000000013716488daf8586719c52fcec80d35f17d4c595b66c7f2138244f3c8cea69b819778bfb50e49ca1d092e57c51674fca00000000000000000000000000000000019cee25c4731bf48602ceab23b5fc4f764993443e3622107b4c33b29c23d1b5916380431b7ecd94a0ce99811fe6dadba000000000000000000000000000000000562b28b245b7c1ee531a320fa0f4e12d7c171c7e3932ffda6cfebb123fa7f5993e5ed5e7b7d295405e5031b339994bf00000000000000000000000000000000180c4a8158a26d34123c870bc694382352a8e4de712b650d3e45e6baa16d6950ec15d3a4e032c1d1ae8fea18faa6f3d8db48a90ddcd791e6a9debfabcb1c71c88e7ad98f9e739ee752b381b28d7656f20000000000000000000000000000000008472d40e0505d6b8b92500e8e9711112048611fcdcca2377481ae86a7f6da1571f179183301e2194a42dac3873a3ba5000000000000000000000000000000000e2c5b61c050a8a12298f76b5f15383e72b90b001fa26889b67a24bb374b63c1e00979b05450e44ed63e72042af6d46e000000000000000000000000000000000e8723eace9c7a72b3e6097afc9bcadde61462e2ee03fcd5ad1b1c0dcf39f437f80530c2a1c5e6ecdaac14e8715f02e30000000000000000000000000000000002e21e0f451d035a5257fb09e9ed17b27f0994e6d85ddaf8d33153628adb194c97db17656351c029be4d3125bd29dc22ad1795823d3834496b0a1c2c07431f9d76071db77834005fa1228393ad4ce3f40000000000000000000000000000000000dce49634595869d7858e95a301bcff8112eb73dca8a22042137456d6d4887998a541489ff09f8e006176e6beee4e300000000000000000000000000000000010835f7336dc49e62706da4ef21d8e3173629b16742c317c1b397d4f17ced40a56520ea63557d7ac7f251568f4eb3a220000000000000000000000000000000017446ebe659a4510a362ee3b406b636bea8f381503e51ac21031c7cc92acd23046d62c2f32cda01b680c0f107142ae7d0000000000000000000000000000000006ef82deabd8983ebe4255d8e06f4a1b3585c057b2a1ca3c3e1cf04b582b65792e9980e3a1735a8ad58b053b16ca03d036d56e38fe63e573b02203be04ef9e1a044e1754eb2db50c6f9804abc4a40f46000000000000000000000000000000000cd8e7422ee179a0499178c3848cc4fbc87fc25c8c882f036a03cd9d3f273f7f2bf71bd3c9cf5e30c42b1ee6e90b36fb0000000000000000000000000000000005005a471d77a35e922b6d6a45b13a90947c2b31d8e7a2e4b6388265b039ce23ed958495dbf904186bef60fd547b941c0000000000000000000000000000000006c337380065eb8a5f63cb20fc61a9eec4ccf0e23c4e0f231a5bc4d765271b9c5697bbde692b4828ae22ea12423ad932000000000000000000000000000000000f7a0080cbe72a6e6473f66ed729f58683a80815a1748e52f7b67a6bf2846b7df8e7dd8599f87fe63706e9823bfe00d21a6b36f4674ab19202037d59fd8e14369e5d3d71acc3c76985b813d81ca6e24a000000000000000000000000000000000c94834474ac91547546d7d179b2091e33c8812c1b582ff186e69b63011177283a74b549aa342a7f3882ee82ad8ecc03000000000000000000000000000000000d72c4308e9ae695acedb9413445bf6a40d59ca78bd4f74ddbc1bcd8508cfb521bfcca99c98dad8022d3d1ccdd98bca9000000000000000000000000000000001487d006830d00d84a567c5d031019035443fae4791a05253f91249b32a4b3e7b3ce7eae885b8caeaea411a90b3445e0000000000000000000000000000000000d94f17aa100503f605732a48e4f55c394a8df1421a3d7c78bc85f4cb7a53744eadcf76e1620fc54204b123d6071cd3bad85286877fa7e5a9a61dba9df5ce35083beca7c2f5ecad13d226fa32b9720e900000000000000000000000000000000101cfa8d9c7522277f2bb4bae6c09e8b93a876c749c91c61784feeb105be61c2479375abdaa81deafc2fe754ed6cd9da00000000000000000000000000000000089ebbdd489ff670a70218f5aaca78d4e7ade483c7f20de4a84d39217be8f560fbf7bbe36f3f8b8361ba16d17ce609d200000000000000000000000000000000094f094372b2315fabc219099200e7b9e2f3a2f6fef2ede6f83c82f44792da03aaad06b8cd06dc3f140746bee2a45706000000000000000000000000000000000cde6cf9a3a7018b2b1c0c26b5850820080c7e4b56e615d577a78565431c93de78348d2851d5ad9f120ddaa9ff3da31b8fa5387c5712832b52c9c72e10c6f69e9c1c5b278aa379140e75e404c4f50a2c00000000000000000000000000000000059bb8e5dc5f0cd31cf674ea78b80b67b8a8a753e51284a2ab37d3f29459250d904e70ed00481b73556970a7f5424e5900000000000000000000000000000000043c6a53c413bfa2f4bb14ef296afd97ce801a37fe63d11a842f8d66160794c1a651d70f4c836af2c73cb1bc58c706460000000000000000000000000000000003e7b67da1513656f7b08fc5a77682477349ac57e53687c82b6d98772b5f929a2b06b0c7e14481d522aa94fa3a6e1cde00000000000000000000000000000000109e07928216eaea36fbb20a38711e73fdc26e18a6967b54f308b10116a5c8af0c8411406ef6ab1050b61c23bb746b0a3023298162ebe7f4ae6aee45a8a6ba602c3942a8bd6b35636fc6b85596a582e000000000000000000000000000000000166f26d3d26cd48e498578900a8c830ce9b80f162c4b430749651b945d9f60ae6a26306ad7711a1f9d3428946074912d00000000000000000000000000000000165f1bc59c9c36d12754097ea83e9a63fb4ae5d1b93a1b9239a6f338cddf4a9b30415d58076852288c6a467ce9b6b9eb00000000000000000000000000000000198e73619cb93fa6a2bc700cd400519d11a7d3d6d945ffac9754a6faf37da8596b49b7a3a4f2cd899ec9c84f1e79b7ed000000000000000000000000000000000a4740820d60034d37bb85e3e622783852779d36d6e61f81a7eabcd094993dd7d81900277550bb4299d550d2805466aa8ff2430d2f82c6d5e7424836ecea15af0ba2d0bd6498e65c65b6cd281a7b8f28000000000000000000000000000000001714857b0ee07b94ea928ff57aae9fe003c0c85d8564456955d14fc8d4ae14a7c9bc303983af3e2999c6db2d000ea51d0000000000000000000000000000000016512cb60aa372cf5098ad514291d8168ed31bd755861dbd9ef020252c01379d343a9c058839cdec8d14f2fb9da0db80000000000000000000000000000000000af74d8ac711b6590e7041e80ca40dd4db659e42b950bdd68c56d676de654c1a47867bfe6483dfe1971eb7c1d1a70bd10000000000000000000000000000000019e56ca1ef3fffa9e131fc5bc93100577b062cf9b2acd234c79e5e54aa799a389f30002b4bd683edec5fb100f1800d66415eea22058493dbf6ac248fd2ad8b4734ebe33761f2177089a3feda396001c00000000000000000000000000000000019d1d1e1e2dd4ab86df81a8246c902a573d1fd1598050663342e411a1d1b3c8849473c689afcc8e0ce5e51a9dc9c3b6200000000000000000000000000000000190d7c923bdd6336fe3e0509563b2eb6067354d8807f66e6052e97d5997464b9f07f29f3022f78779a5c4ac155a703ce00000000000000000000000000000000128591bb699c18a7b9e6e4e894654853f6a68233dfe8c744b42e057711b8d0efb3a98bab6aaa40ae7675d9200a8427d600000000000000000000000000000000045e0560e0936b16d1e055d3d3f4e0fb42d129546abddebeb78e871d1442f4796d939929d354b0326b95e50fd5208fa9ff79e3ef5d32a751b713180be37d44ae55c59c5a8121c132c5098ff972d8a97400000000000000000000000000000000092373dfd7d4375d6bcffa415e5b36a31499e881a80be32400105a6d56b34d64f4fed09f12640a43289a710f034b71e6000000000000000000000000000000000fa75d6510b3b58a32635a7a6cb4b9255aa7af46905cafc893f29b7866e12565765bcde498dbe87df3d1dd53ab5628320000000000000000000000000000000010dfd3456cb6a8bc853b390380a13f045ab43abd289fd05e7f98839477dea1fb1fbe38ca4f5bdd6691446ac0219e453000000000000000000000000000000000112567397f3fda84db6042817a99aeccd0c46a11fd3ba44e2600deafaaab7014dba98cdcadf81b97272fb7f275ee8a4e039bc7274a3ab172285d853d368da0950203a48ef61b3c7564644762279c1ff30000000000000000000000000000000007b397f093e69874d2bd3592489d93c80d0191b157e71d08a6ebe73063f77e7c5e084a24b34da2aa6354b1815a694185000000000000000000000000000000000fcede3a39dd5f905d072dafdb6f56d85726f6f362f91f079fcd47a8c1d3bdcf199d64edf17e3db1dfc96a3e59f69bfe0000000000000000000000000000000010cfa13c84e750d8af8bbb88bd6d16adf3bc7b532447c2e6accb359a5576be08c1b25f336047fb8e01a4d7f9080d0392000000000000000000000000000000000ca0e88b5c2035bcd3a65e8bf1aa219cf428b6f80617040ae02a0ed41559804844df373ac61a85899bec83e5a6243ed42c47d0b1fd24c1c66a3cb0deb7d51ea19f0fc492f637ed5d4d03e102cbdd055500000000000000000000000000000000021f3b793680e0e3127fa53034e9fcf286f5279cd167ac1e8ba051c440aa265ec6d28fcc2f6d3bad126180efd4503fe900000000000000000000000000000000182b429f27996ee070ed27e7015bd70191b814bd02ca6558a9be81d6898161aa525197c1672ae75da92729f2fae9fa3c000000000000000000000000000000000a20b3922e07da4ef6696de85754eabf1f58f7f5d37accb6cde4f62066e789bc64bc8ad6ac827b8c955acc858b03d053000000000000000000000000000000000814faebd3b60fa1a8fb86b3cb57d36b9c85d4b28e97a2251e6bc1fed1ccb18f17664321f38f3723cf8b09a2161c6aeaab4aca860ae4bc20d33808533c9a70108b153bc4b2256003ad4bbc11dc92898500000000000000000000000000000000159f9d329f929a65e41c7a0d4c05e11db61ca7d6d82f8b92a780bac66568694656f4c845a730861fde9a313fa49bdf0e000000000000000000000000000000000d556bdc8dc959b00f74209dff27023c5521d387a40bf20ae2a98f3f55318eddd347bf1e9d856f43a4b5fcd26c3567ad0000000000000000000000000000000009b4b0cedf477ef1e0f99627bdd7a7afeb9e29afbac553a516fab479913b23a9be5e0b38994215a9e23849bb664201ee0000000000000000000000000000000010899f4dc55ac5d1f56a7b8d55ce7f6a5e0a8647bf1ef6e9050f00c5fcac9f679f138018b9aa611be73d3bdc0af2056e297500a2747f9a68b2d8d9ca5b0390369d919897c53d422cb76c5a283c38669e000000000000000000000000000000000226c8a6b27437972ce29c2ed7e5cca4b6691e3a5dbbe713b5d309ff2f4cbb95e8f1571314444d65ff5fbc3281f9354f000000000000000000000000000000000282a49d0c560d873676967700c1062013a2d4beee96a09af7e14436fda4e3d2a32ab8ee4e591decec39a811ddff130400000000000000000000000000000000167bfe499f1f4609e67134e12ad91aadc37bdabd0055ecf7f96162c39a02a86e62a7b3d39f514f63edd82d04beb1958a00000000000000000000000000000000191673ea5470e4704e361f5ead1c56371d6aee3035d92d9e1b96fd119c4f877cde6451411e441fb45aa9fcb90fe4c66ba87ca4cf226c212c80f3db5e4e781ad7391fb73b1124d01cf893169d1c50ca99", - "Expected": "000000000000000000000000000000001488532d83fddf0bfd69b32f965790b3fe4cd9f64e8d17e78189c346518c91e69db2f0b742cdd5804b3db3777dd931230000000000000000000000000000000016205c470c6371d73b012a14d519bf214ff10de458605097da1b798977bd938727c5be19a10f4f492f301d2ab6c38ed000000000000000000000000000000000142cc08f61d3c9bd4c7bfd0b7a0b8693af6120898fcaff49a7fb5abdaf1d15bf70eb033d6ff09a75995547e6856c595f00000000000000000000000000000000164b2807e19135ca3b66bac9aceb371165c930ae063f3cb5a06efb8985a1e0c39023d8f01df517713796083e8c2cceb7", - "Name": "matter_g2_multiexp_90", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000023bec14deefcc20a90e439bc16912e90191dc7142234b1870e4e8d70c56f695d5cd30a68930ff9b007bdcae8ca90d870000000000000000000000000000000000053a6e226f3bd82150e08ec3690f36616d5ab745b36a9990baac7ad3429a41bc60c7f7000ceda4cc9298b10043639e000000000000000000000000000000000b81b331589ac332093928faa60d6819d3b5559d32d37d2cc13c78aafa1cc34e32d317695c1c4b4979baa1865ced90150000000000000000000000000000000010dbac5e52f9a046ab88aa36b3c5f6952720e174bf8f1732e886e66e5803aab63642185aa24ea08c991edaf8375bcadd9abfe7e05e8a210604355a77f64386a01323407d9f25397769cc6dd141bc6643000000000000000000000000000000001875ef3f90df03d49ce6cede2c791b4d8503b75acff2dcb1c7c88026394dfe11481da72de4ff58ee9a98e75577b6398c000000000000000000000000000000000c8ee603d1404e64ea3ff08c70b3dbffd318736ae95f9a96ca07ddaa449818e6c5a17b2970f572f53c90be893e5c323b000000000000000000000000000000000f31af63c68481f527092b261d29d5c2daa95873b68899c28ac7753d95a64f455ebabedfe6e72246e494cc5fa2a9bd040000000000000000000000000000000009fd06bc51d4dc51de9fad6d1eb763809cdb5ccdba8e0427859d878904bdf295983b318f311856728078e7cbbecb0c5b64be08e7c2fd15ac0116ca941b85615c6deb38fe85e2c0fd22997e394b8a67690000000000000000000000000000000003ce75ecf6b605ce73f4e215b1aad4799f91e624daf0deae3a273968490bdbdbd0250686ee91a1c24c2e2f2b6024fa49000000000000000000000000000000000e4d9b65d71b7593310fb5145677d170663c0ca29636f7b7c50ec1988bd2d2f1c41d542d4cd8fa23fad94bd6a84aef5b000000000000000000000000000000000fa4accea53a6362651f6c6ad2a68d20b5f549f8eb961718e0c14cd05249a121e442a6a588eafc83d6a43d8baa66882400000000000000000000000000000000121e325406767852620ddc45677495fe3e0851fd3c70922896a3e92033347d2fe8d07f4db8f26b8127ec39d619d596030c391dff1c0c303c77b2a1fff24f50250dc793338f7d7f8f1d54bf7d87ab37da0000000000000000000000000000000003a0ac3ac37932b71672b9c48bdbd368d64c11f57ccb952f633bcd10ec19134c65fb2cbad655d773a90cbec2d9232b3b0000000000000000000000000000000007553c470bd8f38a48490dadea29df81ad901ecaaf1eab35b1f497bb58acce77b883e03e78702930dda72e2277139a2b00000000000000000000000000000000044973913824b3326b72e62ccbabd8c9f1b5dc81b423d0dca37b6f33972d993a681c326730717036bc6f0286da9177430000000000000000000000000000000017b0407d2864cfb39dbb0a5fa8deb4ed4a690a4042153e829f51c56bd0f2953a440d8305a318e6d6f67970d473753021a2d728e013e5fc3e1ca24c105a0c268cbb4f152a97e318f3aae33186ea6bc93a000000000000000000000000000000000b7478dda7053590ed013b7c23431a21626e748c3843e2332bde0bd3890ecea95b6104bac420a8be5f3dd9b075203616000000000000000000000000000000000e6dea641181cf796f62b196652f952ee2a26ba998cce1cfe9d65ae49198d10badffa561e2bd818eb2a7f350c122fa820000000000000000000000000000000003c79917ad5a9c7f046b34e5491ed015695aecb00760f3009dde4cfbf88ad1c03e44117fcb6cdbd5ecaa8df8760a3da100000000000000000000000000000000034e22ddbdeb9dea46c71ca2144ffcc8356c1a525c5ada69a6d5e5c1786aaaf0cf532e31a2f78371e04a72e8222ed4c7e8da0c8da19dc441f53c54551579fec5d820ce2e3599824b24b7c5bf1847c5890000000000000000000000000000000017964112272360a38d3bddf89da922ab50be076bf71a094fc8afde109d3817cc2db633e6408f5716b76d70e30ae00c0d0000000000000000000000000000000009bed28bbf43846ab97b92aab9ce094b077bbc59db648dbb469f21842058ef20318a1a8c18045b3de555bd8c76132ff0000000000000000000000000000000001297110789c7aecb0fec577f6f4a4de14608d9aa26a8de68289adea7f6b53b766b840d315152ea346f8c10b2d2729e730000000000000000000000000000000002b551c6a7846b96c6895e55ec435397af70eb435dc1c562ac71a44c36936c2c6d3e6a1e3545513516513391aedaf9ca76e90965adfc2fe52e4341895e6b6154fd7a097e052b59e4935c8267a6f0e63800000000000000000000000000000000003d463ee4d177d78849fdecba52b7e83ca90d54177ed39e82b4e80c17994a6a2bfd9c46edc0ddb256f8955428f30eca0000000000000000000000000000000011dd976dfeb8ecb7d7f5cd10c235131709fb16d8a827e83d7084266c2504cd1f5276ae3333bc7fbb4ebab48c0d97a9930000000000000000000000000000000005fd19477fffc246f5991603b48085d95256b273631bcfc16f19c6980a3ba01ac098061faa149b475bfce37d586464b800000000000000000000000000000000103ac3dd682aee109dd7fbf60b50c28cf7e37642f05b424773a06f6cfaf7e9fb01d5074ade97ef6cb0ace2e1fe07d54c7f3f352c7b7a9e2eb6c87edfc99e2df3148966760168f6abb13ee482f223a01d0000000000000000000000000000000003208ce7f51a96dee053cbaa66fbdb921c2c3b42ead78b39b4f1df7ab49f05cb88d0f4ac18de5839749416eba5535d4b0000000000000000000000000000000001ff7f9db52aaa0fddc8e96a67b99353b92d7032f59d200bf69da3b446d08435d2ddaeb93584d3b68a1934566187922b0000000000000000000000000000000005f05ccfa5704652cecfb42979c538823fb9d11a00222a963d00f1a4b9a040a0222dcf45baad40c6574d85e5617dbbea0000000000000000000000000000000018637b8c3ef111f6ad4538464c250d780e7f081802bdf720f4c925154f4667c5d50cdbc4dbb7d0b2747b97d2ba2280bfd35c4286f19a9fe8117e37132ce4ce76e28afee25ecca2f66de3cd5e1c83235f000000000000000000000000000000000eb400becfa5521b824a4288885fe46642c31576238e94f95e9b4bcbf62845ee9d9ee122f87d36fbe668f0e605fa2ce00000000000000000000000000000000003c8cbdeea0d09590e1719ddffa0a116723f0fe85585583f3f271ead66fbc2107873181915cc41eed3ec6e2c5669e9d3000000000000000000000000000000000e61c0768561517405952c6462f1c5df95be272251d8a7060624b62f9be310cef64436eb2c4c04e8352d7b75fea1756200000000000000000000000000000000036cd74a8efa8a1fce7587f07d5c2a6c4b7ef161b0faae037c9bbe63bd0c92b83e514c8c1bae4a5d9866c0889b1b914f3c2b40b7968a39fe8e4f24acc25b6c727887c3c44cc89cf62eb14a78ae47e8680000000000000000000000000000000013019d0fc8b93da2c79e473d713d94af33eaffda65a7a49d0cbae9f5259b8323e6f29b83da9608ba7d6ec004fb0710eb000000000000000000000000000000001505d30bf8f7c51994d896d91e8e2259782e2b49bda834015477f18c29e64da4d31f8b96edd080267b77a9539afca06a000000000000000000000000000000000eba929531615d9c0f59c4b33c1fc34b81e9c77cd8c6887099d850b3e39326d7caee1feeb101222f22bea1e9853d06ea0000000000000000000000000000000019d88f62cae047ddf2cefe497495f890d9ab8499e56f72488af65095e992427bf821f63555a67b0afb00d6fb441080a010325465403dbd4898beb740884cc325923ec3e1d7483540377d8bbd02c11382000000000000000000000000000000000b7c8f3d0c56b3b7d96c0a24fea3394551a186f87acbbbbce41d1313b23762945bae2e911725da4211614b456b508c0500000000000000000000000000000000125316f64bdd0c5bcd26a0e5bcfc3139045b3a44c8a8dd1cebbfaeb83b963c5a5abd4a5961465cff261c0e49189278d800000000000000000000000000000000095a327f488b901fe7dcc9f9ce6f4f25876bb09b053b64e9f4de9506a0fb95fc0cd443473c2cc5436750581d39b8e51f0000000000000000000000000000000015d406b31c791ae2d25ce462304c0bcf341686d7967c9dbb6734bc28b02123b1730d0a673fa8071dd90950d9411a2b3909545b90dbe35b0d5764bc72d45717e0c3aca6aa77c73178fa8a3ee9fec9cdb3000000000000000000000000000000000c7029af9422246d0a30784431d6bf9eca09481589438fe9a6d2fe1d5e526ec3d176a3d550204aadb85353d99bfe3ce50000000000000000000000000000000014a0dcb26c40693ad19a1edccda05055a27ca24544e933d01dfb964571071f94c94233f81e1ead0925d24e6d3df2c21500000000000000000000000000000000147a55ebd83c746128ba9c7ac57be125ca5c95f80f891e2c5893caa779484bdc1f9c3b3ccc4223b2343ba939251f7fdc00000000000000000000000000000000125622a040d8b157432ad81b8a83a9b1f0920b92680bbb65050b4862b89017b3bfaf81a3402ccb383265ba7200ce677feef0f8014102664a300ea9a30fdc7afeae3cc338fd45cd421a1bfea98e304c810000000000000000000000000000000013b394fd7a0f3d94e5fe4cf5cce3627d425ec848912395565b3e61ffe89e56be799c4779d3b9a0222ecc6538ca3346e40000000000000000000000000000000014ac1a87b333caed0f557fa5692d1138a8c1e92d1f9acdc9f357e2a46f27513dea42f367b046d389dc831610be4fbcf40000000000000000000000000000000011fa243a0aa8b0c01c7636387d60021afe6efc223b7deb69d030651c369643188b9dd5e08d6d031d71dd11eca1e825ac0000000000000000000000000000000015bf8fd7fe438407db7f1b0b586b2c285777c5b6dbef9e45b46cc0a50dc831f32a70e7d4316d4869bc769ff6de58ac30c8f1e08cdd72ed200253211e3b9947cb2a5fa24079b6920b4a4d3f1fd78146e80000000000000000000000000000000005ea57c269c9d43d3f17a83df04c95ea7e7bd85aad1dc2dd285ccdbd52bfe707a1d2476417e848ab119e62fea30520af000000000000000000000000000000000b99768ffbe95e315b244bf996cf34f8ac356664adda5aa7f4ff8d513b2eb5934b8ffe0fd9af94bc9b934e0a8bbd51ba0000000000000000000000000000000003b02c259df189370dd2700c5cccfc8b212a4b332a083adf9771503f5bd0c9ef040590320fe4a86c555a4ea87531268100000000000000000000000000000000003ebb1e610bd055d037a410cce3ae06aa654950aee0210ed0ee79f7a332be7342e308347d7b17a146a8b4c623029e08a7e25b1a60b6c6080ccf1bfdc37aabbc2bf92079d9356844f7f12867b3e2b2800000000000000000000000000000000015c4da691b5e6242af870e06b29bcde467b4644f01080eca60a28c7f941590192be30e6a4270a36dc8959b80235600aa00000000000000000000000000000000080f3d3d5c35ee24179f51ad854a37ac4ff867a2736a0e3e8f3312ac98c7016beea6ffe2bad1dd4842d6ec77995ff97600000000000000000000000000000000130c29dc633aaefc831b0bccb13fde1212fdce8cdd17beaaf1d06e74ef5b1b69bcc219c8d63f054690af1b6dc7c0d647000000000000000000000000000000000767290aaa1ed4c1dfa5603d976df0715b417599445ca577ded7d99e685118bbec71443fe1d9a65e0f23436353df152cdcb456eaad2b7c71ca32277206c1a1dbfa7e0e84950cbf14aadd455fb58e398a00000000000000000000000000000000133e997857f47f8d6278b8ad86f4692ba0dec9da336f2726704db593af368dda7aefc0b218ce1674f415e0d9e2dee5c60000000000000000000000000000000018db87da1272bd386f7d8b5245dc2de30e82739723b680dedd36f4ac4cf5042bcbada1e1bb307ba444431d73a4248f9c0000000000000000000000000000000006580be3e67c7a615408aaf9c95c0956678af0e2b1f536f1e69588193387f8a05b03d5e1060ca60c4fec9eaf3e72d39900000000000000000000000000000000050bd9879ef9eea147678f552cedacaee84562e6561b3b7338fa8f9d514099291c3f2a3723fdb22c88f1c9243d411ccba6e7b19245341fdfc5927cdae57f59de5f3fc8c37f8653e5aaca87db682034ce", - "Expected": "000000000000000000000000000000000d8f69d90c871c08ae09e7b3e62e36514fd056c41fb596fec2fc9ce8509ab4f6675d7e85aa6b4b3197f5ab781f6f2e490000000000000000000000000000000011c4bd3cd156c34065e408efcaa5e13ad23d114458b71c2a6345f4aaf82af76cd4362db7ba9ee7e1e92ce72e242f570a000000000000000000000000000000000712dbbf20e9b24d20511d01717a3783608386408a258c2261fcdad5fbcab36c6bd21473c3d93ef8518975256c65a945000000000000000000000000000000000d13747be82153aea8076fd7813ecd7f60a214c31e88e25b14dee5cdb9336599e40b136d9ae6deb85606d35406b2675d", - "Name": "matter_g2_multiexp_91", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017da08f2faa32570d95b9efd2d2fe358faec1ffe304750dca1dc3a273be3427c70904d58864f76afa19b0fe33ab1535f0000000000000000000000000000000017de677b713202f23baecef2b0618da140af624e56b876f2d7a20cd437c3868ea00ff6cd9c8908c1ef323ad294edd9670000000000000000000000000000000011d50aad957c54868aed6d848b2e67094b129282cc2df56c41d6ffe976d02ee83a592c33370d3715588a074db503b3e8000000000000000000000000000000000b8aeb019d120959b21627c1dcfdfb67ade22a948fe433172994d4a34084ac9e1c11333a9c663c87acf50962e21c728e92898d9cbad829a5346c0925c15b585de18869adfe796e46cbd56828540571b70000000000000000000000000000000001312ebeee36fff8152324a3ed24c37eee50b3099619a33c7a6316470ae722548b4b9e0f0640453caf53f374dba504830000000000000000000000000000000005ea81d2e5d9edeb3ed6c200b75beb731c31ad666e6e37db72ffd0265378bffc2724047c7c0c6e3f1598345fd390e9270000000000000000000000000000000017617a836beb12e637c5bbadd4fbf1ca2f5cc3280814ff5cbb5890b31cf2d2faee9e3ea8134af97ad4feace50aa194140000000000000000000000000000000002606deb5d57dce5b3d2e5f7ccec3ad036992beae238673641ad6042479ec3cf83bcc0fd03b7dacb9b4bb6c181ea9cc8c193fe87634fb0bdaa1700466881b557c470a62464e8521be311a95dff65eca6000000000000000000000000000000001203ef36896bfad2a2841689a964328fe4ce3d83798671630d0c8876e67ceda03d99555aac46d984f1d3bc38ffc134c50000000000000000000000000000000013e7461c256c8ff9144b17f8cc2e270aa94b64be62588280baca2ae6b6efc4d32b3800eb84da62561e0e96d5f0387a3f0000000000000000000000000000000009454b6a810647350cf0b364eb1c2b719670af45bdba9d7d1a534e23d4e810c3ef4d9318532e46fd104a83bb10159a30000000000000000000000000000000001034546c4288f642daeccf5b56beed2ca2d946bb4391d056df9c6fd6771048903fa330ec16d59d05540cd715333c4bc73dd9c99a5aea019436e3c91030d03ebefbf6ea6ac69222f1870fadae32f55ae6000000000000000000000000000000000d7782404dc6721f52648fc6969db33a9aa209f8baf5faa9678437c76c9e1635fa6d22d94aedefc90112223bb81ce33f0000000000000000000000000000000001e442e548d3045d1589817d0b57dfcd66fc64ff978186f784bd576faf57607170d49364a72189328c9837c9a2d8b0a0000000000000000000000000000000000da2b207bb7720aeca2e6ea02b65076770b960d4b7a96ed941a7f409757b952031a472384298acc3948bdc485088501c00000000000000000000000000000000048f85bc05ed78c692138f27c3541ced11b6b0ec158b43d133c3450a905416682fbb8c83dea06a06d294c48289ddb829e74ab390c3f73c62eb1435226e9b4f9b921ea1918a61a614b9bdbe9eebd1cd790000000000000000000000000000000017134f787c920bc15cf2228a186dfa1d10194087f28b6dd8f03e1c86226928f0eb1c27020a5cc74d94b50c4b4e36b8020000000000000000000000000000000012fa1fdcbaa81c4cc1e37447cae51beb29e55bb19b91e2b575afa3754589ee0151cd9e83573edaaefd341f381d34f4f8000000000000000000000000000000000ecafd00cc87a773a13909512466ed11288c842716e1ca5c37a4d9a4cd7585136c86f32140fdf02e2997a6e19e3d76a200000000000000000000000000000000104cf007ea863dbd473d7dbab6f55e74062b18986e9bc09bcfdc9c23e4bff8683f73aa998a5cce59ded10499d18a0ecc4dee3e2bfae3820f611c30df232c1d9c6bf58d40b3530858c79f840720d78d72000000000000000000000000000000000ffffc98e55f4ba9a642c40678d625690464bea39d085dbc9c99b4c36ea8bff5154eae3c315e1dec29aa669840accf290000000000000000000000000000000000a3df9595167048c52b8170596d4127968194aef7fbaea4594a27c6af05c54bb772928a7749d74311038d1c115e91b2000000000000000000000000000000000b317a3abd808e94a7197e0d3b2515a147774f78d0cd7d36e1156da28a26e33bfa76d75c6e3ae346f9ace050c9911cc6000000000000000000000000000000000fb5fbcc2f74fc30ae7e32143f219db7dfe5db6ecb09cedad8f087b6df56bf9693c8b7d78aace064e7c31785f6869541795fc8e20dd30622876a94afce1c1a76e3b689d6848903c21103cfce6a8a95680000000000000000000000000000000011e4b907a72f34af899a6c4de211af5fbe0265e5bf24d406798de53ecea273d5df4f4953d13fd7c9dc3bb0f0c143e3e4000000000000000000000000000000001623de5e87b6e1ee920e1b7d979fb9c431c12abb47b93876f9ddfaf28a7b673c18be634f96b813f7e0574c55b628a8790000000000000000000000000000000018ba994b02dad759ee79301b42ea20d7545844c0ea4bff2f95dc9420194cc4196fff12cc09bc0cef03cb7ba868c273700000000000000000000000000000000004b3527c8d148bd9e6006bd298ff8d7fe320748dd3f6d23449e874fc0c2f58d933c1e038a74f60fb6032cce41a3dbf5725b49f325e76733eb3c1a2cee5467157b2ee80987abae43d2c4b93e5157f083800000000000000000000000000000000129641af11fa92056236ef135843b2189d46d870381261d5781a5fd6f2c5cc1861ebb2e801f19f3adf2216609a9e196f0000000000000000000000000000000007b4007c55e47f6bf3aa420ad75fd191ffe0fe824fd30c3f1961a8168922476fdb3869822704999b044feead470e3b8f00000000000000000000000000000000174209113e2d8c363b04f49487176dc6d9eb4ecc0b22daa7ecaa5548d038b3b7c23ebda4f1b6845425cee13493385302000000000000000000000000000000000a58c80a02b7f93db01d2f8e0005839625e6c4f121f3d69115f435526a7f7cb53177caab4db86273bc2d2f0474235f31df49b30dd6aff459f64906eb1a9c9b2067d4f1b75057874b2fee17923bcb906e000000000000000000000000000000001738a03b46a8ca3f3d1f4f4447497c59f114005400f06813b24ff462ebc6f27c1c3c788b5f83f65958cadb34fddd08f40000000000000000000000000000000004dcfff2bc9ca0282016f38df484655cce7b872b1ff047351ae6b903e05f457d7fefae93104f9dfb549980394dfad2760000000000000000000000000000000017cd89434225dba07be137a73892faf0258b3fb19e6c8cec412fcda912c0613f2a925ad50ae485187020a371ff2dbc59000000000000000000000000000000000f1f9f87d3401e7b3b59331a89d9535adc973f869b81bfd8892a37117d8597ebab2800c966e623469792f4ae2a8eb232959e0a33b1fa12e0ba960761b09921b81746b8df23e808a8de09e7f5cbe2bf41000000000000000000000000000000000bdcb1d2a782541ff7884dde4167ba060fbd4b117944ae69aa2ff685b9bd7d475f45adce0c9f92695b4f4ecdd48cb9b50000000000000000000000000000000012a55432678043888bb9e7e47efb17700b3e702e389d0f58dd454224a02da3f190b2fef4c9d3e2074c7bef813fb56fb0000000000000000000000000000000000efa51ba64f1e7a1a269dc083179a222afac916778a967098582f55a41394bff3747f8d024261959f6d399f44a40d0fe000000000000000000000000000000000845dd0974c5789a85c3cb09ea441f2c433f0606928ee1b177eb851530d6e6b620b4fdcaffb8f75623435dff99b3ad9526ca68383528f6a871c237ae5214b49c18c4f3e2f3ef5dfba39e69eb181143d700000000000000000000000000000000180beba92bdb95c7803fca0407e29929ee64e03d61cad96ea0e6c469c5a888cc5ca5eb20983b3418a8da6596a5f1b2ba000000000000000000000000000000001322f7356eb3069fe20063f4be22c44426162dc8fc117e4e382bc4e33bdf3d971ef662fffc1d58ce187c33a43a4c853e000000000000000000000000000000001601a0aadaba846f11ba5c9f48e13bda1007ffdc1b8bbc9e85e83e569e9ee17a1e9e780a50ce617e6c780b8155675f2100000000000000000000000000000000105b2c213aa43ead42d9cfdf1d6c0559c25b4b86af43d4493bd75b76986d0d4f1d9b3bf9e3922b5c08a37a1629cab7d8f1f95a9d1d4e8e7d0f17a954177253709d988c3a77c77d35b8bf70294bb358c20000000000000000000000000000000017bc70346765b7160a0a5e556805c7944304acbecde06cadba474c51f05f22445c3d943674cc8215f973cdf11b9ea2e9000000000000000000000000000000000bfdbe202619a1d95359941c249b25462d3ecf09fabb878943a8a37cb9eb94abd7e6399f8d82f90ffcf904f4466cc5b1000000000000000000000000000000000f048db8530a288fef10a5ef9bb3cdd9f3d3b0ef4824609efad96bdf52d7c3b10ef628fa04f8b6513485e55f653f4b990000000000000000000000000000000004ec35f59287eadb1738bb50b0e2ad9d280bedfdb0a201e72594bfc4322ade0b7ffd6b532ebc7796cfc71f88a194bef4b481f986998d863c98e55a7661136a8f19d7d4c57f6036cd642ae16c82cdcfb30000000000000000000000000000000014424c77af7ace8ebf66f556cf219919712d96d24438466ad620221ce1ae9b2cd75b9c526e25df7fbf3c9250583757f500000000000000000000000000000000198aa00723781714152b3494b76ea3ee043b363b3fa81806cdf7e440b4cea907f226a3c038fb95c932710dc9aad4c9dd000000000000000000000000000000001360e4c775f6fa5e987231dce25ec67f61429ca9fd8160c3074383c30a8c0d7ff068b1d1215b2c0cc87129d9c9aecbc9000000000000000000000000000000001280ee6160800c4b0f82d5c2775238b4b223d8a0ac9a8f8013f138d554ba31c9fedb30e0eb5c330da17f5785b2717422ad872848d72367467094675a819f9aa6107183aa0c8685d5d84c27b3aaab33c1000000000000000000000000000000000f1f84251204d9f9328f79a45d15b311984df0715579633a82b5a9f680f6645cbe748b0fa64b9ce1e696e20a5645d6d300000000000000000000000000000000156901506e502a09917f76d825614824dfbc34d019ed53c2ec5395b51512da512b27541bc53331444eac2f618ffd5357000000000000000000000000000000000ea8736a97a33112bea9d07b729e973e3a942422f1d2b24c30e96637b535ccfc10cb5930bb59ed90bef604453df8772100000000000000000000000000000000187378477f60e3eaa225e89d8532bd95babd4a5c51729cca800d364b61575704992639dc5035138664e8e074ed0820033c2c60541fe17fa8e71d58184a055fa8b1dd0bfd16ac2baa912b4472c6056122000000000000000000000000000000000e5281c1c9210269a7f5ccd02cd5a7d3648b56d9ca6a4ee50beadf151c2601e0291fe7f1b89b694500e6c636d4e445c4000000000000000000000000000000000d5d5399f49697e46013558dfff544383b25f3b60681ba5fa2c5e6edfd3924267d0992abe65cbd5109ba8a1c6eadc7e30000000000000000000000000000000012a2104aa92871dd8e41ae1ae6dc18ceb7d0f361a5a4fc67936454b8866b8aec1602dd596459cccf6d9e1319ec3299d4000000000000000000000000000000000268795f6f9892f5b476c3a534673538647300203a51a8ff60b530094608b5fdf16297f02ab7ba41d6fe556885f064a4ff07c19ad4f10ab47e73b6698f9febf3f28087614759e082e6e717588c1caff7000000000000000000000000000000000a5585961328c52e0fefff16e66e3367e34339dac1a20cbc5e89b78804b8bc265e6e3fec1da6a62cd8a46be2f08a6d960000000000000000000000000000000016fbbd698784beec5a636332c0b20fdcb68fd3015cc6d18b541346a5e6af76613e6fcb14c888a2b8133c0f4132fc079300000000000000000000000000000000041805e0adf2a32153b89d1131226cf0ebd77cde3116a168e792ae8b88ba2edcb1fe7275658a384251b805d282ee039c00000000000000000000000000000000024213e4a8504cbae4875617b9b78473e7842ff72415ceacfaaf2e8b415f9f7e411989bada8101be72f9295dfbddfa3f240c881fdbfc414d3e85ead1cdf166ed6929d0b2ccbc35f0811473757b6b41af", - "Expected": "0000000000000000000000000000000003c4f051d528166f256d9356aa9cb885db5680c51990d9474a948848888fb82a9b86daa7a2273725ac8ec564ebbf15db00000000000000000000000000000000010a6c4c7067f511ca8f1b66bf9ffcbb275c7575540909262f7c4332c3d75b2f6d2f3ad2848c0d455410afb1cd60c835000000000000000000000000000000000ee5e582554b3930c5670d4e3542bf32e8b871849d7859eafc077bb2b533e936d462f614057f9fc09c4010afab501c1f0000000000000000000000000000000017fdbcaa065d301adb94a60dd20dbae71512d369fc82c556ea0dff66843be768be942e060752591c6eb0718985d8e313", - "Name": "matter_g2_multiexp_92", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001353960aff58d45691c5378a0676a8e837260f5819cbbac9cd75c8cc4c6f1e17b9dc9843eabc0b1dfb27ff7631e4e52d000000000000000000000000000000000d6279a43d3526c035e88b0b640b04d42ea573ed07323aaac1d9d5570a8be64782682892415ba2be5cbb13f56e3a44db000000000000000000000000000000001250fd14fd003f88eb6e0e80e9f2ebe204475fc6c06cd10fa45608a17b7039afe0326474ff80c357f86c2825cdf7a16d00000000000000000000000000000000186cd91cfc8ae625e302946f2b393ea67e1107c0bfe938f5f36d28879fa0c0780c847aac77d0310d43211152c1d5f5d314d5455ff1717bdd545f4daa37e145121e7bd9636d7a2b65633e5ca5a63f2d98000000000000000000000000000000000e55a98e8b1e59600e86cabb5e8db8ee622009b1618ff0df3e93fb55b80985bf2a8ed060aeaba53773274d4186934f75000000000000000000000000000000000bb7215fc43f465f51fc8265477fc8c79493966f040e02f0eacc4ebcb3414b84fd94ded822bd24dd5ad5720f12bb8313000000000000000000000000000000000b23328e15cda8a576ea352b5dd7ce382ec781deca6c23f646e42f0cf63e28669539579ea51e3c0afebbb58e1e8e3243000000000000000000000000000000001716019236169bdb4af7bf7d7ce0aeee7900b74023acbb16f6965c2abcf28917bf88d0f9d5bc26a81710496f7821fd4682cd8da62bd901355a60b37ca14ce65d427bcf9551203cae7c346a49b4fa8626000000000000000000000000000000001718a4d6f5e78524d8df23d2c589abf04e3567d2176539a30b9f73c6251de573caa60c2881f3da99c48d48e9aacd7402000000000000000000000000000000000ce0e35721379077e6eb3b572f7f7718bbf775b116521c14acbd3ff19549c75d50bf70ce84326cbc3f9e5e53605d8ecd0000000000000000000000000000000007cb3305ef0d2cd7de4dceaf25d2eff44d4f437e065f6b244bf1b0611c891626eafc4b759d55b45d76e94b85852df1de0000000000000000000000000000000011cb56d2ed32a46bd951836f8e0f92d3824a4cddf011eecf1e2d92d81bff407a04abdfcffd60ccecda6e9443b328d51eea2c7fc2050e9c1ebd05d15f197b4b1be61c6820c8d27ade57d85109d7f982490000000000000000000000000000000011ba705da23100f853882dd166d81ee1d7621550d156b14f7c2123e2681887ec3724626061db68b2c63987325b27d6230000000000000000000000000000000014271414fe078a80587269398afd127ce34c8dc2a4851f76613b81dc99d766d75c703949c1093b04d66a301a79d89bc30000000000000000000000000000000011b7935ff284b0f812b5da5b28ed338dc4c21ebbc7fee04db834732b11fd76092db0e8d80368255b0f1205129081e9af00000000000000000000000000000000104ff0ad2e3db08d3b4890b2e54f29e456e627cefc3a4f07c1109b764dae4142480e3e5312ada43fec9ba96ce587e8a4e3bf7e661d54796c71437354d7d3182770f10ab450827512a423d3dc82d5b43d000000000000000000000000000000000c60749ef36d63960022f3127d0ab4e12acf05ba1e1a136dec89be388b9d7144c1d78c04df658727763dbaa9725bd8b90000000000000000000000000000000019932b1c205a765bc9de0cc136999deb153222a9dd9e9ec3660fb6daef56242d08791d440888e69ca0da2bbe0fcb7d79000000000000000000000000000000001764790d12f5ff79ee4f2c9fadd5dfb1cf47db70b9e86018bbdbffd1be18df193c7dfa71533afa381053a77e02719c6400000000000000000000000000000000044b2b0211cbb407281ab2abc4725c2cd791b313bab8779954a2461ce445cdae60d4a9efad9f90f80e66b1438514e0f0d3a364e7b217dfd649d1e08f76393372d8768bb0fc85c79ef4652417ef1637fc00000000000000000000000000000000175cf9e7eead650e7ae4fd657bc288b6b6392773bf1bbea48e17172a5019637fbb2bc0a3d0d1e3b8054564935c908db200000000000000000000000000000000136da2a625cf72403d0861b9cd947cdad12b1f1e6cdefc4aab6756536425285a7953a1b892df40ec12ac3430fec889cd000000000000000000000000000000000c2d10c6d71cff4e1deba1984bfd17166571e64659ac91b64c343cdf587c29d52a2266c00a57c01feddb1df6439d21d1000000000000000000000000000000000384a782fb31278f49c840bb8f0552ac2734ef36bb3d115be7df20333aa747c92db990f7e879399235d122fdba0eed76eef7b05d5c725ed31269ae9c56dc7ae35048af39ab114319680d4af69be7e7c3000000000000000000000000000000000a9a821cc63e7c9857b0f39f7444a1e00a422f7cd5d0575c26bc5c6b98313abfde51e3f6d5f4c817193bdf391344e5ba0000000000000000000000000000000010daa8c7194a75cea757b6ae4eee85006eda459ff2cf155b1b5f19c3ad341972f72e28b781c4878e8919c7e5abe9a1d5000000000000000000000000000000001154d5d5764aa2b8818a9dc5dce30ba2197a86d0bdc7dee3e600462e295cc3a69dfbf8db34acf138e7a1f16b62a45717000000000000000000000000000000000b4243a09b05a958d78ba8ae25fd3fa85d520b95e56f1dff44e556b221a075f8dd3370313886d9dbfc56a75697454d72acecaee3dd4dc11e341b3dd0073842d90f641d4dd467a6596f337a6147bd30a9000000000000000000000000000000001820f953fd22b71ce00bbe9e9b78fcf5fb28bcb925f6b5dbf5711e00470ed7fd2f38d7291d40514ab4258807f29150270000000000000000000000000000000007b737b56a2ba33f76bcf66c0b26fb44d5f79879273f6ab21ecbfe6a5744da289464ca2b46c55edaadfe3210b907f3f7000000000000000000000000000000001735d1b39c5369bbf886c5063a96dd12b85e56fd9d8ff9d84520918e1dfeccb62bbbe1c2ab440ccecd0fe66f6ec55853000000000000000000000000000000000e591b7709bf00bb2a87e9edb95720de19adc41a42378cf9ebb930c6d3f5993a1d7b6320040d5c69908685d978be8f980cba585b847bec40515a257cb839c7e5d677d17b7313c258e83d630e65cfb5d2000000000000000000000000000000001732ac410b2a7d10110bbf7709dc6fdc91ce742f8cb9b2c3ba37ba5f0934f8622c675753a26d04a176e24a630d090d81000000000000000000000000000000001111a52da6aca10cf40127fa8ab7683505305e0d474eed28a5e1735ee6877aa00c1bd598420876f2154b814660f3fe7600000000000000000000000000000000098c6d19c2ff42c2c57a4924693325de1a91135e3474ec699b70439d034469e72e844a5511e23dff3948a66cc2a2165300000000000000000000000000000000175fb79e5e54963cdbb133f38dccea2d1abc3cdf005c17e8f2de6dba9b9dbdeff7719983aa9ddb602f0cf966fdd430e0b8cd305c650d2e1cfa91ef0aca9dd0d785d7570d6fb67e61fb9b6817116a05440000000000000000000000000000000004e88468d35d72dba6b3e4b9ca216b75b5d20c447064a48bee6a6ddf994b1e22fd6ee8abd60c627622daffcda219645a0000000000000000000000000000000015eb2ae16e3310b4c4ff557f0615519c13f29109d9863418fdfbe6309b5bac4463456df8ebb0b6d9022e294cc16265ea000000000000000000000000000000001288ffe0ffdb96708558d914bc412758770d048c4d50523e2b134f8468d11a57da97e42bea303ab7137e2d26c0b3b8f30000000000000000000000000000000003ce563b63c50b09a80b71a1a82995238a9de31aaf189c6d29307924b6f0990854507b7dc1644f689c5abcf931dd5a3c825e5f9d81273f306a065fd064ae24bc2c5ce8dbff6b22128753663a218da8a30000000000000000000000000000000009e39ce653485caf699ae1d1d9cf2b8c5ea85b80ea042279e57f0beb81056159e49f73d67e7b1f9ece9f9ece7dcd2cf50000000000000000000000000000000008d6492cc335660c54e4a34b29b337b5800f1ef992d124524c799c04c852ccd3cfc01bf39515cb8b96151753147e8c49000000000000000000000000000000000ca779d87aaa3a6552f9f1a10b0d2e635be90022326db04e6072f326b919ee55d4124b9268f55751dc0f18172bd327ae00000000000000000000000000000000112eea543d6609d0acfaeb7be98be609f03304f50c3814ee8a010283146e6b5dbf170c7314598cac06efb9ced1ac2930307ff9660ad0c24cbb139486638a2556687f88fb93a290a1d174bf87d780b3fd0000000000000000000000000000000006624dd7f6eb043da41a36a15752f370eeb3cb2e6bd88b337b370fe0660c5ba8fe64f62e112f91d2524e9324f3a049fb000000000000000000000000000000000415b964484c9246385cf95461ab955ed0390e20209ed405d84fa8c8af9fa7ab39ce89049691a63c61b12bbf6aa2a4e80000000000000000000000000000000014411d7b2db7c9ee78ea14c6a315df3d90827b511db2e2423d660176384d8f8afd284879b22f5aeed73afb2eca4be52200000000000000000000000000000000105bfb471340e76f28901edbdbfe2ba246a8824b501ae2d4a73cffd2690181347c1e6530804614e88e2bb13a8edef8f4bfa8ee3b44c70ba2512c00a1aaecede2180b08ac3ac8c550d70407f0c12e027d0000000000000000000000000000000002b17f4b0b0231be229d87f075998435560ce9046a8b0e8f15e3a9f07cd52f3316f6d8c00d6a872362e7066715cf990e0000000000000000000000000000000003110eb232154f8a06834e2ddd33c0207ea552f439a6127b652bc261158209a00654e50341d333cd1b206a915fe0691d0000000000000000000000000000000007940e209c8934c185e4392f12fc0afe3d234dd1ef3f92df18d76be8fc42bdcdd6d1ea8d5bb6f07b3f3caecbeb5ef27f00000000000000000000000000000000012ec903a8442f68c03300ab02ddd08ec935d97bec9050d26a5e276584592df3ab87d596f90768d2c0918099b28963be58aa85b50e5f4ffe375599cbb912f41d35acbb85a324880148f9b9003c4265bd0000000000000000000000000000000010fdc16bff0fea02b325c672fe06297e0669094e2710d0baf3838f3e234c3f776bb3fd41b967c9ebbc72a6bc6eca70850000000000000000000000000000000009d64ce322e39d5b2d0872760a61a831877c450b1cfac6cacec52d4070b0f179dce90afbdefdaa8466f6a6e2e83ee8da000000000000000000000000000000000cddca46f3b24e05b76e61b4584bc716ca7036afdd914731a61347e453a26d07549e9808e553ee056bd47e53c75eac8f000000000000000000000000000000000451cccaebe1a188d3eaadd40090ca594f071c8b6d0e0d82f5b2d43fa784f8437e4226104c4cfdb24ece1ed75375aa616810c6cd59b14ef4f6a4c2702cc53c65b3dc84988372c1195980417c583fd7ff0000000000000000000000000000000005832ad778dca8dfcfbe741dcf311024d76341d5920b6830cb75893a112c9d86719583d1dfa7287281fb73fe21650c3500000000000000000000000000000000044feb86b4816e45ffb98e9a670fcb039fd9d8844a2c7ff9b7752f20e619195fe6ab1148f30afa393936d3605fa4c8da0000000000000000000000000000000018db9365370a8c703364ba6d9c48b3512da46cc603a43c3fb91c0a8ee59777d7cf9ac646c3e4274bd950d7de92ebce840000000000000000000000000000000017bd82310e251701cafbf8c4dc5b9e6c88085b0df287b6dde7887e1f64f2d9487a25b31abe07aec7d99a75baa5983195c5ebc09190ba3df49d8ea55cfd18370b9d443f9d9084cf84f2236ef4723d2d470000000000000000000000000000000002c1df194f01dcb503dcc8a283f059b82d141274c8f37cdb6441aa33f84f16dd288d566752a93ca23d26ef5834c0658c000000000000000000000000000000001700fa4459dd4e609453284f4f7dab479342675a87c1cb42b601908296557f39256f1597ed3b9ec38ad0a40a2c728f0d00000000000000000000000000000000135ed4f475eb99397cf204f971215a0303316a3ed8b62b303b4bf756ff753410b7fe263c4e97fd4c4b399c319ff3ad98000000000000000000000000000000000a487e179bf1b73627af9d7d2b43bc0e43127a8fbfeaea7ce958ddd53ecb27741eda187745e3917f1cbb60adf0286f5413a56b176fc835b7e825c817d432b9ec6d51b0a66483dfbf12166ee979b664cc", - "Expected": "000000000000000000000000000000001327c57e16f03fbf652bbacd16cf574113860eb87b8f2f6e498dc5dcc4f2fa63859d922d88ccd6683d503d0962db5336000000000000000000000000000000000cb06948c539cbf686f6936b6a1ebef2e148d98c531da36272e0334afca5c2b16a52da542a0fdbc3bf764eb877f5778a0000000000000000000000000000000003acddfb5bc4fd5579d3f592977365840be4d3cff96434e5ff4f01ea798e4401930a1f5d91f8de3ff98504dce398c2ef000000000000000000000000000000000a5a332805f704613eb085d6639f99667d0d9247cae34eabcfa399eed551f24c5d5cb05d6458530ae270b1be682e71f4", - "Name": "matter_g2_multiexp_93", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b1b06a76e5bdcb6c1c2f1952b49e1820a9d8557229fbff8740269a0b819b91cfd0de20db0afd76a2cb0fbc5fac12ec5000000000000000000000000000000000347654df2084082efd32cba2b270f66b0ed30fa8713b27949fc9d270ee8eaa9b9a7896d7a52dfd8faa3e0cd112a24e0000000000000000000000000000000000bf5b7a2c0c8bc223ab334bd1df5d9fd4bc0c635379ed2b32da13f6178e07217bb88a4bc2eae0b975f2e566f657d23aa0000000000000000000000000000000017042f8585a07304995853270b1b03bb08484104f7498a12bc865f2a0e37e662fc4b0331b94ee5690efe74056567000bdedf65658ec3cca48fd48e844337159af090c5d1f5e9d713ac6d0fe1e1f193d2000000000000000000000000000000000fcbc73d0628537eae417f8efc67af0a4c9c375d82406086bdff669911fe1307576333c389f189f49677cbbfe2ee98730000000000000000000000000000000019d552b85b1445660ca49518d202afdc67b0eb5be02c8d3482dc1b12e5d40a4ff95a49ce47809e4d6644d04aeb67b3c2000000000000000000000000000000000ed536c0f19f592180291bbce59a72ce5e516199dcbd4fbba736cae2edbe3cfb860ead0325dcc8f8d9be1ac126dc6cda000000000000000000000000000000000f5d4f0c0ae3e76b1c41edbbebcf1ff17c7cefd41e7ef8f75dfc10170834d05820149d5f721a8c6460cd0181571fca97db65ad6bcd6f485eefebda0badfc64e9e7dfe7e911f3ccf4f4fb9528dfebdae6000000000000000000000000000000000d6207f6684f8d2f083c963551bbf0a674ba40e691a34ebe6164ff80ba9bab2cc23024a896d7b906fb74c95016a9adfb00000000000000000000000000000000145855e7d610b50cde39db8995b127145d68fc9bea3f075f65b7793acbb14bbb313a1a39bd96fbea6641baae02612b000000000000000000000000000000000005b533ee83cf72f0e4d9c9ddcc6b91f4364e50a106becf766987c490d559d0f733839ecc706bbc9c2c75b243814068a3000000000000000000000000000000000cd8fba13b9ba7557c7577da183bf50810fb14eec7380e3b3d4f2fed62bb36f2b5ff288736bed0578fb6f47fb6d22ac86e0fa09884a7ff4c801ea0722cf6bfa58a46fc3d36058e8c395ea8fe56d9fca4000000000000000000000000000000000fd6a466f2eb12f6337ae9f9b847ac1481820013142af1a474229c5f5f5e1c0bb2d9678c19c7a3a1aa22cfc7b5052e0e0000000000000000000000000000000002a0340f5a0caf5c66719f7d546972bb4b89147989280542787d281901ff036b7c69d41418c21c43127c0158593aa5cb000000000000000000000000000000000deeee37ef96f26a4907e1a8a8f3f030dc09102799bd0c6dbeb1d208a0c86a423d0da6313e0be03c026da5614a6a576b0000000000000000000000000000000007220475449add59b3cc6570701528dcbdedacb9a3d39674ad4aef4d94114f24d2bff32f40b25af97ba883905ea6838a27a3377d7b9ff3aee2ce1194a22d7115b09a9fd53fcfa5e7f76bd9fdd35559610000000000000000000000000000000009d7023ebb73df81455f74cb2708c14ccecacd49521a0cf67ecb6edc8756e286ede59eed54d89eee5f77f178ea8fdee900000000000000000000000000000000002ad48fc3192634e7b01604678473e286afb0efe67a4377bb885d38b59ea00202241fb28c93232ce7c9a3dabb136a53000000000000000000000000000000001934664f2bfffb254f0415d6769f4e2ac710ee88cd822bf5da5df3a2541f887e4155dbb7e8056efb2a0370d6f9173e3b0000000000000000000000000000000019df518e1ebafe95adf683279729a3298fc8d7eb39c9a3dfe4b6665153f970e243e50dfb16fb87b3be54192f69766659446a62ef5760c995cb3cd0984d607c232c1eb0df5516a501ce448a189a3134d8000000000000000000000000000000001870048d360f397877321904563d35bfd0817ce464e0078e9605a4744e2723f49f9cb21dd3d6f37f1f9aff5a6a99bc530000000000000000000000000000000000e29dd0da13ac451d013d4a38408827cb0e739772e1f250d31e4192ddc13d651ab576ed6b8f4ee44e928fa663244999000000000000000000000000000000001646183099579322e0115ab0b3bd6c814e216ae6b2b80206354925565b7bcd97bc12668b7f3530a95409456ac99bf01200000000000000000000000000000000092f6f594ad0d92c9c64f78c819c44320e6bb5dc1dc8fbe58acc7ce3c101e49a74ae6d50b1a668a3b7436dc445e3da345f0c1a7c2dd281f7d2f006497f99f65d6a1e22f1d9aacb08724b3576aa19e19f0000000000000000000000000000000000428ff447de18dcc11b2c5c679bc2efd125464f589013c6964ea6cab33d9b7cbcce3a5d6177bf43114ee256f23fefa10000000000000000000000000000000000d1ded695e88dae6dfa702375959831f4bda688fc0faa289dcfb90a07f3a7963f2c9070958561909a2051a852cc15e1000000000000000000000000000000000c39bf1d11fc5693167890246c81133faee93a8639f459429757965e0b62e372153ce53c61f2c539247dbe7747b27d1c000000000000000000000000000000000e84ecb6dd9cbd4133c22350f07a976ae13dcbe4c6ae09ccb023f2118fa2dec68c20ba2266f9b571bbe30dde97480e0a94c1476ae0a62c502aa096a371e30ca885dc13fc417e3dc9bc00bcdf516764100000000000000000000000000000000015e040fc8753f06ed1112cc06e2cb7142a4fc984834f01faae718c17cde782d5953547857ca9aeee1c4a7d91df060d330000000000000000000000000000000006789ac15d719a7159b650b757f7d3cf58fca02d3b8f3685478ad5e5b1dca0508dea7a8203ece97c7c6d32b2f194458d000000000000000000000000000000001824d75634043cac3fd17ff0bb141daf7010f70b5941d8f75f1ae076713afaa7e0a0a25fc71038baf1b1255d64c914c6000000000000000000000000000000000a2f71bf85af6392a8a070596e30225bec9e3dc12c70e8df7c545bd6bbcee56799db2c9a8d2504c4f90ecf6a5e18abc9b677bc9f1f7572f808e969aa50efc519192ab8653c71090e5cf8cdeb1a3544dd0000000000000000000000000000000008bd859ff1f22d682f86e1a0e3bdf3a332ae78d64814720687a3de44c9bdd7506d2696b4daf81a94d33f64983967fdc2000000000000000000000000000000000d7b4b958e0087f8edf18a4370ff98700764c126808d5c52afd3e71ee326c766c1e5712dfa351cf5b3c518e52133ce780000000000000000000000000000000013a145331bdd9c93e63edbabb9f6c541a7c4dccb1705f07eb353a0407074a76022a8e5f5f2535b41ecf6474649e257bf000000000000000000000000000000000a12e461b7439bff0dddb560dba21ec53ce88f71fd3dc10723f3d8742ed63a1ab725f7e9619ca1ccb729564dfbdb1be7f5ca580a25a5c87015f57f7c23cc51a0beb5926c84d44659e45512da51aa0cf4000000000000000000000000000000001430a8184c5055008a06ea22ca9c997d1a24ddce7e374937c32ed1e487c80537b238a589b5e50b86fa194666bd3410e80000000000000000000000000000000005c78c94f457bdda242deab79524bd2beac82bb1cb427dcb2872b56d1f46d11fc9d69ba132004958fabc5da7d6d103fc000000000000000000000000000000000e985e8ca038b5dadc9fcaf22699e75cad9d2effa47fe7d4c579ee056b1e34ccc540372111a665041062fc6c39e05d170000000000000000000000000000000018c865243534fbde740de0ffbdeab0d38ee878c20f5d84c0226d1f2b14ed3359f5b5b909808b6b3789bfcab3be75c4cdfa1cc45c35e266a82899d8ea0c9c1f96f96140eace41a8758a87975b088f0231000000000000000000000000000000000c5b10541ec34dc0a8b8e42d9d6fd6f4f71e1fe56b5afa323f4ade35c0170b5e224a66771326d9edbddf2bd38c6c68ce0000000000000000000000000000000019cf33c19936f7489a1bbc095d0f5c6ddc1f43bccf7e8d1b30fb8e8cd1ef747b483b9a8e9faf21cba7cb17fbee887ad70000000000000000000000000000000010e83916faa7bc9de9feb8a7f34ac6f2aced06a771b662cbce846107245edb9c07632782300e838957788a8d88c8253c00000000000000000000000000000000066127bed5ac9f2871500fdd68a03ade57c35449d4b4186b9fac7c89e91b4ebf2f2a02e94d0b578aaf60b32017f147a493d2908aa9266844eb265c2b1c17f8357a5ff039836ba83c837909f6a9d0bc03000000000000000000000000000000000cb5a734a28b44f04d39ffae049fe8b63b138411661ca6dba00c72cadd47b50ad4b71e858e817561682d6ca378ebbe870000000000000000000000000000000000baf4d689baa09aaf763ae7e142b801223c8ff58f2b541ee4c44ab2460fb8f6dfc1e9f61a8d73aeb92d7d08c281cf410000000000000000000000000000000008a0c736f19bd0005c9d25f88565b1355e53fa3403021577de536712ec986567184f4dd626127ee80dd03cdf9044b2ba00000000000000000000000000000000063ffb7a3b4e057a9ffe233296c11fb462136fc4b187be6f9e36f9e6d335a3d673ef8b9ae6f60c146a075a1789f389cf3b94325aad8a2c80971a781bf6f6bebad63ee37405ab7e903fb7094beef14d06000000000000000000000000000000000c33d89595d039722222b9b9ee7ff1a0dae896a8de97f202d3aca00bd81d0169f14676efc4b051bbd339dce862d8b60b000000000000000000000000000000001109a24dc6f70bea47e040b24df395bf561cf5f1ee79e90c9b0480fff0795677483a85e6f2e9ded4f36ca849ff39d6f60000000000000000000000000000000009c7878f3a4e4e3149b72149a7da91bf527c4d7c94b15ba80b02e0e50b02a2c482ecae9f458a881c87e669986514f6d70000000000000000000000000000000004284448e42187c128578b801f76d421fc508cfee9360a7203a91d6f9cc7ccb6ed3211fc5df9e15f14aea98bc298b2f95143a8e734824840346078aec03d6760564870c5ee2b2dc13f8a39ac452be9f5000000000000000000000000000000000271ec1a3f8e3364ba8e101b49c0bb17e2b7c7f27a4aa4d4db5c07203195050f30c1a05d33c524a84b1a2f0ce31a587200000000000000000000000000000000082ce9d1da5d7f192c537b2bd617b36b65f88b308fe1ff85e47c64b62dc62324458493d1cd1da9f5fe308d27545fb6510000000000000000000000000000000000b30356b59eb04258096d0c3f357fb04471583cfe6a060de5279bf2cff4413678c1716ba87d0b6de6b6e79a96ec26030000000000000000000000000000000003c02470a14211fef14d754f6f71efb33a06a76e099093a5b9512f907ff819e1e0e15f14995febe48852007bb5c380bd0dbee37fea759c2a58cf360c654f85298e8ff44b3f900e8229c3f838345d053b00000000000000000000000000000000172df3290c3c5044d590eea59980d02e02d4fc6fe7948168492362de8f0a85df0c3d09d8cd8b206cc4d1608311ef4c130000000000000000000000000000000010e4d14065315a0d9e48204e47955ee9652b08318251a7836f32e6fc015d4856444172de44b3b88efa1b54dad346e9b1000000000000000000000000000000001549b9c85cb2fc2c7495d7ef6aa1452e58937baf58717037069e6bc6d72ced3a163f800991cd26510e71aa64c44f66170000000000000000000000000000000007814c2f1734fcc8cbf9fcba06b936c86d0452a2370f8c9480b97105e42f9babfe0869cecda7e15500e9d8d868290201b92f9db82d0976f4c379622c4028002ede2ab17f647bca3bbfb159045cdb342b0000000000000000000000000000000014f849e9749a5ff6b7b10daac7f5934be5f783d49c8593367c4243664e01b1d3552e878802d7dfee823e0122e9fd46f90000000000000000000000000000000000d0b32d7904dbf08269ca3c6ae3fe582501f55e32337ae361fe4a58dada560db54205e56a399aed33bce8758a05ebcb000000000000000000000000000000000cb21440baba44c3cc6943c8cfa2fe544a652f06423d3de06c2ff734ebbb544da07ba8982b3009b6c4857b73ceca570100000000000000000000000000000000174ef591975fdaa0e3cb05bbb4140abcb38f685ce4de77c95e2cec1911985557b77d9229940b8c9157ccf9fb553e8e0d98df4ba50cd5cb5a02d5f50b3ba23e5f5b0172a46cc315a0a94fed05551a68af", - "Expected": "0000000000000000000000000000000006da1222c7ae02843ff289931fcfcb315f621972f45e4fb4160b8bf48cd8102d50fb53d2c699afd36892d91f5e608784000000000000000000000000000000000523048c5de2d0139965c976d8c3328666e99c249104712719e992334442245e955cd6b14a1e3d666220617d78edcc630000000000000000000000000000000009f669d4e7d89fa8d999d8d5a6323da9445583344276bd6a29494a91174aeeb29132926a893d5a0eeee9c3048ebc0dd200000000000000000000000000000000099ee1c33d6f09a8d063393d2a8debeaba93027e31f7b23c5170b6747f56bd6e6494de966dc280dd67a38d39ae35a336", - "Name": "matter_g2_multiexp_94", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b46cd281a09b85d977e88cb2251cc61cf13181522cf1c344b114783c4fa22d08f2d008faea3dfee8ea7c56aa35ee39a0000000000000000000000000000000012b530bd34f5b31161355436c7dc444d41d634b0ac3292c0096558618005fe82d189e4b208a48240dfdb4d50ad44dc620000000000000000000000000000000014d334e7835d4bcee2698ca4f643f9692f28d8090ebb8ed8f67c60639c64eb116067e5e8a6d04a0c88c765c608d57ef1000000000000000000000000000000000578cb4e243b4b20c99afefcdc0e0a9e308ab4bec6d655a8c4981a711515c807067472a6fca30060d776213b8ed98d74e49662df81f6bd455ee554704ff0c7d5a589d91e017d7ab4c500d36378c17c8900000000000000000000000000000000046ad1212696acdbb686543d284d7cf2e1e8e8c10af76c6ba51d55f060c006dbab25d3a789c71c428f5bdde9aafbf6d5000000000000000000000000000000000a6a880d52fed6a45bdc61d9ee78d8fe472e76ccbe155bddd0e2a967f4d116bb9f2dd4c62cc6f7224b835c8060213ecd000000000000000000000000000000000786544589eda15edc433edcbaa46d4953da72473f04169ea64dc114b99f0a58181d41dce1fcaf7f3109f66aef02e53900000000000000000000000000000000030759c3bdeafc94fc8fc0b03ddcd96869459bf54ace74582aa06c179323ef076aef89c09ce8e7bf9109ab2e8c8fb0be79eb26c79d78ab84c4d7e48e56889a601fda17901037a74fd79355e7536f3953000000000000000000000000000000000e6addfe0db96a7377fcab1fb92183fd7d7f13ec003fdfe0740bcc8cf03d8cc602d5d808b4bc874f34944a65b249997a0000000000000000000000000000000014a4337107e716113d8ba0fc7f75e85edd1c132e2b3dadb3f9cdec1440f261513646525314b5c0de6fd372472aafe877000000000000000000000000000000000d472ee0484ed831f8ddf7ad86faef5443df8b943c6fd4c3f94c8d52d9eed6fbb53107170a60f25be52219ca4816788f00000000000000000000000000000000035d06ffc452c65a31f80c3f8a0c1e2d15e32d993ec06c50499bc0fb8f669acd3d2182ba23d942489ea922baf61dd49cd2918ddc2bfb7f7cb3d7e74b43b9a972c5b51ac20ea83f41d5b51034b5714c0b000000000000000000000000000000000ef1f5f6b3041939557368d613279043d1aceaf5fee3ed90b3b756ad409d700fb41e62b3758c8c2d325db7a37f339c610000000000000000000000000000000004d66040a8e055399bacb6a1e762b698afbfabf789caeb957fb7a3dccb01d7dff5414e90f5a14961c4e980b298f834ec0000000000000000000000000000000006efe9e66078000c26d375e87ffaca643aae9cd3f8337f5718e0e268b74f4b7838f7661dc0ce60f557e162a21ff467160000000000000000000000000000000014ab782a3b2c06af7e9c2f28f1604cbfa8a676a874853bf38195780751d306936cefd1cc38c2192cb756e28793d2abb3e9a8159fd7915c15db69355514d9dd26c66fbd14af969ee576401b1b782fc6d300000000000000000000000000000000057270788a199a894b37a526a26bc4d293780d365a6b66247e7417884d543dd752ef7c89f2f4b38f4b51e6f9d86b45ad0000000000000000000000000000000000b59fedd6798487ec09d226a7406b27f04f7983075b4659ca6a78c6bb8aa83828fafdc6488518e2cba6fa4193de938c000000000000000000000000000000001105c18d92b4192833302814ee9b176831e57fb64b703ab3c2d3f440ab302c8fdf7ddc81933d3b1adaad16038dd6dc1f00000000000000000000000000000000020509b08e6ed980df29da649051c7095edcd4eed4ce95cd797da430cd09062a110bae21b6f73daff2053fc0289041fac818ce6e33e581595e83cf8d33a62edc26ed38c22f20c6949a94e2652bb954cc0000000000000000000000000000000007be348ccf6a76827d3b9b33e7a89378c133c9b226e47dcb205ee061423ee6e1b838bc262a7befae7c15aa385ced00bf000000000000000000000000000000000689787c19192ad55b9c6c260a5ec3aa203ef71f0b746eebf10f82526c4fadaa8570936d7049c1a46e7f3cdc455a63a6000000000000000000000000000000000306965b09678d481aa4c754d56a0bb4565f16f7523cd0b404fbd39dfc3b6ed483f5239fa30f13aa3e87918ca039d5ee0000000000000000000000000000000000a2586143f9610a96eb0ef86593988770db5ed49663eab72f8c368b9388bdfbcd02fc6bee09f4fe055813d140ca0fa89ab338e94b31d22947dbeb20fce3150127249d2db6107d95bdd032eb24c49645000000000000000000000000000000000018f46dfdde786a88e582ff6addbecb4f58e12c2625e3d6440f2e5b5781beaa95cad6f63b7d132e84700e7bd344fe3200000000000000000000000000000000185a4fc339a95a50551d53c18bb0dc3b74e9c164729c2b0d919392f7aad2be3ebae3b8f676ab81ea05233b3039918ab50000000000000000000000000000000015395b020a9d0bb336066c1347dd91c557b6ae7b8817cd8a2cba9e5bb149ca3401d661227c26d52a9be234faea894c8a00000000000000000000000000000000103d9d7e33a0767554e13b57dc756981488a3c7dfcc026ea84b35b0af21193e301226cb5a4760962707d19a95841be9296acb797236dbd0316fdd355f07b9b45c9bc626f73105e87c376af4d7dc075d30000000000000000000000000000000018359aad8af59cdda484232b885d1b14956ec04b5584684b13a64d97b8310c283e5d66637dd75de405f5f4bc65a6879a000000000000000000000000000000000849fd55e4f3d4dfc643dfede6356826eef21290b84f7e8e226deabbc84273d95f7be5479e9656dc907ec367a7ebf8f60000000000000000000000000000000006ee01b54eb7834b4de53f821ad46f467cadffce6df09751b728d0952bfe615253d7ad173892a52c6181810a815bd90600000000000000000000000000000000161472d45b56dd9fd276fc607f2eef84c5c843ea05799e732d7eb6dce96c632335949e1b3a06815e410e919f4cdc3fb360bc12a8b34e717b2c410d026660c14182250d7c66f8f88dd4cc94e550421caf00000000000000000000000000000000107ef91cf3a3068c4e5644676f7bc7c5f9ecc361524bf3fe2ebfc606f22f8f83b38c0d4bae89f3cdff6119cc27fedf820000000000000000000000000000000006a7f7cad2fa9db8824e4e30da7158f7737d2536554b904ed835c37add0341c07c5220db0f9801da2587a456300c7b75000000000000000000000000000000000f6dc3adda42dbccb1d1e3fea8918f5572e8b26ba3011429e754edd28559b731853761d33777f4e767094f80e63d417700000000000000000000000000000000107d93537a79173ba9367732fa3a28113ec37e053cdf31ce6970dedfa8a9b4cd55238289be9a6f40319e3dfedd132f95537f0f732fee8b882d254a81704d2310c05dde186232f3cffc05401fa98302150000000000000000000000000000000019dc19a1663bb05ebfc0b7cc23ea9e07376de413f77e15a685a3f11fc19bf0ddf38d5671e2a5e6e31624cbcd47a19cf60000000000000000000000000000000019e78aae57f327fbe8ce794afc22bddde08ff9bc9ad3527601cb1fd5dc0b8ed8fdf3b210f86760954b48bf61d74162220000000000000000000000000000000013954a533bf871e99f4a7d81a8b9931c480ce7fc47260c3708c590ade42e6b7bb887d4d24aa18642d010a8170cf85d34000000000000000000000000000000000a561d3f64ba31a6d45ffcf1bcac95f8f665133a1e962e31351ec78e369042bd3afb0c43d12b3087168c1142107241f31a22bc0bec2501a505cc8e00a24792bb380ed451ab6f56fde07ace8b6c9348a20000000000000000000000000000000007149094366e29537b0ad7239ce04bf49f253e4b746b9fe440dbf9b425bfff21064fce66e286e08c87dd83e22a3b499b00000000000000000000000000000000045ead132e0d03c842656cfc82a45c8b4a3b0cee7a5d071c5f235791ff7b5ead071b2c529b446a15aa8837aafc11222d00000000000000000000000000000000013159458f2123698ad4e7d41da47ad7d5083b928839e346a32f2307ee69f643ca11335d50e47d328b0079f1873cc7e800000000000000000000000000000000167edcf807ee723ba70e352367705448047c6b5223fe703381af6bb103cbb24da739ed005b14fab5699fbae6574505a7c7b10c801fb9d929432cbbe994b404d3baa5633628f396d20d047fe2c2ac2914000000000000000000000000000000000feb6f6f85903b3c8e4d6ec2ff234775f12727fdf7c35eade09c9773b004270f659b00248338f0b749d6715778f1f4d90000000000000000000000000000000003300794df19b9e472e8b869a2762c07a9251cdb96b508dfecdbd62fc3c3843b37118d216a64519bc3bdb71e40f9bd700000000000000000000000000000000005fa144135a5d6cf1c73055750ab6582b4c6d368566172b75902b1fc7a6f5de2a251ca7efc7ac6cc6c0bded14df02b700000000000000000000000000000000004239a7bfdefbe78116a588810328024b1bcebaf8f28f09387dcab66dcf2b02c94002df09d12db369fef9dd960783c0b84f2f3f31d9869799ed8bfc2cb129dbbeeb096d771730ae2863c4ddece66158d00000000000000000000000000000000007c8a24005575a3098c12ffa65095bfe227ee59e5e978a7ccab7a9a72391fea61690648c102ce24af723945bbcafece0000000000000000000000000000000000323d57bec7dfbb4614c8c3b286860fbadbf71901fa006149053ea614dafd56b1f3d6a86fa55bf1cbdfe8af4ff08dec000000000000000000000000000000001180b2b0b9c4c12f6d06eec07bbf6f5a220722015fe5365d1c4ca9e58ac9c8f67964d8230152d7a2220575c756bdf8b0000000000000000000000000000000001969a364c447f07d0820586bade587ccc816e50696aa0c5ea4f1daf6cd577769a890b44caa013d93e7f21f5ea269aa85c62206fadb762c23bf77f69f69bd492674bb92edb39248ad2a432f819304e6ea0000000000000000000000000000000008a51c01c3bbed13d42a4da626a8b89e2811db1d83d7de3332b36881ad14a5c8668ece4f5ed2b71204810457aa3d75cb000000000000000000000000000000000658a56aaf627e3f776d3f03caa2c00425bf197c6fa20c92f563f48260109a8f935d0d1638f5039486ce0c0100834fcd00000000000000000000000000000000126d1964f2d964c290cd7364e175ca4a855149e5c4ba488829a436b09ee5e21f6c964e439739f15317873088726bd51f000000000000000000000000000000001803186f88833393bd853970ca4fe414a43b7a619ded1f9c830444b4d43a94e9146146e2284d690436b395bf1e3fad15a6f950de53d07fda75ab43f73982c2684edb06317568df15b8712dff2ef782830000000000000000000000000000000002dc3756c7f4bb47559cd720a3acf4159290d7413e0498877d1fe321cbcb7cdda90b6c8b4ef8e27b2642b82ab9b3174d000000000000000000000000000000000c7490f1ccfdd91aa37a3044d265cb0612bfd9c065c370adb813b2d96f02d44041e79921d1b8935dcdb8c83ea4460ef30000000000000000000000000000000007beb34bfb9ba9b6fb590c7e830400888095d1958b252d187c184de91f165e12599d66345341292fdcb662deadcded030000000000000000000000000000000001ce203d58bebe1eb5b7cbc6038f75b2f7534bce9f50e7e4c91d6cc5ac1bb68d9fd8ce99206c5ec92bcabb71672c6ac195a373fab5176d124f783a36eb2346dddd5c4eba9e24e4c0cdc4f925e2e24cc9000000000000000000000000000000000765acace3e238e51bdaa08c0f6d737c9de55b5ce9ac3523335f0d35bfab6f4e7e2944b8aa4ee031ae9d39d4db96e9ac000000000000000000000000000000000b0fd488a6f9e92c4bdb5e82b52a0035f9a0aed7f69ec65303632017669f34d11552f849326e4dd204d58f50f3ad124800000000000000000000000000000000033991f66588b5e39eb78c7cbf62a74bbde2fa1b7c96164cb58040f0887c485b372e0ef4def9d38da9c6f5c4df2d59a700000000000000000000000000000000187d41fa7905739078d2c2f8775394f830d20352a9d91e97568c6929412f356009239bc9e1da3a8c766e89d09893b5b5319d855218eee020f9cf8e4c0b6004902f0b16eedba8a1c911476af34f65dd40", - "Expected": "000000000000000000000000000000000dedf92894c567ee656051a7f02384edc7206152af6d3c5f662ca02559a3cc349c6b034c6fadceeccf652a396dbec6c900000000000000000000000000000000089deb173bda620678247a7218408594efff7ab0cebbf627b93ed37e553cf944e09232b92afe2f5f31d29bb9ae442c26000000000000000000000000000000000178bc39b2ca8b032d3cde53d2da3f8797026d78c76c51381b377c79992f027cf55ba4e182773c99c99ea6293a948e5c00000000000000000000000000000000195d9cb91537e77e7a4be4370b982b6d36190342ef6ebc2250a9cc8ef6ef45211736ce1f41da899178c1adcc4927a9ba", - "Name": "matter_g2_multiexp_95", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004638ececd7f626a069b1bc3ad9d0f7cc71e5f0c1b11711fbfee1f81466b574f7a11de8161e55eb574ab367f56b9d6480000000000000000000000000000000013ef4f403f139771afe7e97815d3b3777818a3054d02125d3a25138e504c8c2c6696061572322aa19ace9ffd8e3ff308000000000000000000000000000000001910f776582f5acbaea626d2378e9da133b63afa087f25c2cfbcd1e7b34f6a237f2e9adccc303f9d5efe22496ee2ab75000000000000000000000000000000001963bd62098614c4ca2fc2a9e2d679c2b74bf9d322d34377cc63c3b8e7f8a4eb7d6d440d081e044606402fb3f51b0cee2a397c2f19a8c4e66df0e062f179be2f45a0c5e104588222a1a78447512f299b000000000000000000000000000000001935ecdf4f21cc6b510321b4ed2663e339954cd7399b9d67f1d9e2ea7fb9bfff8531f83ab59d3f0546393dc289ab2dd7000000000000000000000000000000000f390b86fb4cd4c1a072a83e1d1198a57a650fa6e94b69d983b693c592bc0c8fcd9a46c6883adacc4c7e2546dcd079fe00000000000000000000000000000000136beae11ea54ae26a8d69015ea7793675625b2013dbeb081a5ed877832849d67ac709b81fcc4fb322b262ec3776c0c00000000000000000000000000000000011f1df574f63f679b6464df463b58948fd337a4b3f159229ba0313cc040303345e75a3a2b0ed0dedfbefa89d8331d074f193d5a575c80a3e7599923bf5a8ba8a48e8f98322d1d8eb1da42e446d518c1b0000000000000000000000000000000001510378fdcde4027999edc99d49bfb46423ceb0d740829e310f8a381a7632fd0d6b6aa3533c2702a5ca76d386ac0145000000000000000000000000000000000bae237bfcc061552ca07eb14300cf557c974611885aa6894f7933f7dc7a0a1cc3b5587bbe1ea5fa604e3cee1db5f7c9000000000000000000000000000000001743207a1814990c798dc3de272a02b1b194a485bf09faea382dedd957861dc15cbf981f9906cda50cce2899785b9a6300000000000000000000000000000000106f902004c66c80437392e92cad73bed6b73010bdc7b6a75de4c01f0b6fbe5b8d1f47378279bfa42b3af05120854ced07f2013742ddf2d35448feb80b6b7aaf2925d3975ce28ed2b1ac789886ae26e400000000000000000000000000000000123362e41268f7821fcd2294b032c6a51c6d80506eb052ab6132267fa248a1a60c3e4eb2e75a1674bee1c9d46d82b9180000000000000000000000000000000006296670461ca67081cd76528446867e1a4905f88742d0ed8d1f7baf86e0a5e5ee86c8b0eeef07c14dd821dee0143bea00000000000000000000000000000000058bff9544e4e02c063158a52a68c93c7544e8157d37159dbb99b51b09e3d8f5b307bfe63a10fa409e20a35219ac244a000000000000000000000000000000000b135edfbf53187004d0977db94eeabf426ad7bea84ad76c6ac771fa186a073d430af76d717070e3c4057a7a2da095984e637a80a4eb1b2caba68b6828aa18f956c62baa7c5e9e591a15156c5abb605000000000000000000000000000000000133d3a223112dc5665e78fba8fc8d040d133858d984e66d2382d5e629f9369dd127e93c7a4da77fad98a0520ebedfeba000000000000000000000000000000000e88515db391bcdeeed2a9f64d27387af0391bf832164fba79100b560d8150debbd703c140dae3ba9b1ec35c1f45670600000000000000000000000000000000042583722c69a19f413392c6a2b75c8ca969be85eb951056d7e1d94e046dba49c346d5774009b8463a40b0576ccc1a6e000000000000000000000000000000000ee61a9eb6ad497c57405a44d798868e22b4fd5b8c480e9938cfdd3f1817eaaf331a9988368680158c59c2801add0a7a27671631f9afd9d2e86f263f5c17c3c11c7f6e43efb6d75cb2cb8250094f228900000000000000000000000000000000020352de9b4e8ea1acc8589bb22e23dfd0ae3a80de9e21bdb3f6391dd05a012e635de9e1f5f450bf4aab05728c054f8a000000000000000000000000000000001733593b94ec800bb59ed97dacbefda5ad882a8023346bdff8f471c5613c67247e27d72cb4ed8cdaa0f236018dd2128a0000000000000000000000000000000011f272a3b25bc519fc3e229211b846042031e22fbed22ecd0d1a4ef1d05feacf105772d71157e3d7293575aca257cd5f00000000000000000000000000000000153b4b4d7d65f7bd13d20fee4812f04706c96cd1a0d27b7e139c47299805e0ac86e8941aa38d90331c78a61c2dd56aa3c2decb1f482f3eb48e7f52b89f6452b659812ef79bb42fb25f03aa9969faf9bc00000000000000000000000000000000143e1f6dd9397f0e89a46c6ec995bf6c87ec8a72b309f050dc5b3134e00e2a16327767cb0573ca5ea9776215a5815df500000000000000000000000000000000186cb3af2cdb4562bf2d0c180079547cfb345cc3943fd7f9203fabbdc1547079cb9ed854f9b1a47f513e318cd409df83000000000000000000000000000000000c8c9197fa5a1e66b371a653c5d18c01fed8d17a8aa92d89b2cbd954b9fd2931fa61abb6676e4851dc9481732c6195610000000000000000000000000000000009026b259e840cb5264f6aad6ebbb09661f5b6d980389817309aef99e4e0cb228d3a7a06e6c25bdb1aeafe5acdc44441911eb1de54fa8ccb746336b681504fd08f995c864a8dae2aa866862f81f0e7850000000000000000000000000000000007bceb74ba86c07d0fca20e4febd3b12b1fe9f786c9a5da0531550244f40261d7ce728498fbfcfe16cc235db6ed42e11000000000000000000000000000000000883104ffcc0d040d70bda04dcf67c1197c39e200d4d9daf5f3c185638a13dffe3dcac94fce4175187dad867e8d2b78c000000000000000000000000000000001404e48e86f199486db7d40076cc8dc4e2aa2c1b6d4bed8f027512e2c71817905b26ff4f0551f9c08a2a7a27b2075b6c000000000000000000000000000000000b789a6addb98ea43c0f9e85831a75b8ee1977936c17929fb45d4c06b4f1ec33b9b41e32b52cde542c9e4b64d27c686cfd0a61dbcb0c657e824cbcf4670a31a95ecbd47a9b93812cd5124f3ac9450c1b000000000000000000000000000000000654e7f3985bf90dd1e3169382690fdc0f804eb6384ce407a060f539804fe6e0451094abaa0dad611c15d3ee52f31a92000000000000000000000000000000000deeec957d58a2246ff8f7b7448f5198647576c16c1717369ad155ae36d5a6bdb42c8d6a1f0a095891fb0890b6203f950000000000000000000000000000000013a01a6ca4c296f59cfa4a5f5399d28af76ffcb8b218c861d5e6dc603e140f730f632028c8da46c823d87bff5ca703280000000000000000000000000000000003698f659e86b96613ca74a480c81e749bce4b74324976c1d241a0911d078926fb2adfcc3f901a7a015a02f525ddbb808118e9c70cc5def8e7d258e05273937c514131f39e0cc9fd2a3620dbffc7ce3c0000000000000000000000000000000016ce72e1798ffd84b52ac664a184c6cf5ce1ca2aa263c9d056355cf610517e9c7bf7f057c342f6e3ae801b84c2082c0f0000000000000000000000000000000010992af1438eec10881b5e2e3fa3b1e91b6b5313ea58dcc0cd2159f8ba6ce5912d81b38956929620e04b3596f6835a6f0000000000000000000000000000000014315dbebd532d0c835e8e85a02c0814574cf040a20c18d06573718223c8ea15b7ea69f0cf342dd09037258398ba4bef00000000000000000000000000000000136d13a83e72525b2d4af54d14d5e21d8bd9bed18543836b02ae0a7e51d433c93aa1943e85f978a8a9ff4454d8c5d120c445931b79e2b826aca02d1bfbb00c2dfb6d30ac2ef97a4ded18243b1afce7730000000000000000000000000000000002c1bf7dc75006c2941b89a2de52fdcdd1b4fbda5b14fe3fc165915b90fd9d93cdb8105898ef59d5b374707f0afaccd600000000000000000000000000000000049a16efcf81de84e443666bf990f6aad2145f9c9c2c61a752e256e8f447dfb27b462e4553544971807f909a666af12f0000000000000000000000000000000000aa4702fb69d791ef958826753d3f74f61c7a591ab94bb6c1bd5d82d94c5877121ecfc1e769d0d16ebe491b775ad96e0000000000000000000000000000000008cd7f2562eca6c53a37382fcdb04be53998f45c2241bfebac3d1fb08d8e1d4df3182f2bd63861d0de72d58072356ccc982ae6de98df906922e660d461009ba6c04cc6497f3645a66385c775b21b210b000000000000000000000000000000000a6b30c4ddb692ae33c903693cdba00ba48efa48e90b9cec9dc747004e57a8d5a05b5522634fc0de306d38c28390dbf4000000000000000000000000000000000601341b3c4057767a910bf30dd16324ad7abcb55b7e98e73584f26d7f87d8a8d24ff2113c12ceb3077bf65e0912b2360000000000000000000000000000000019dc9c50f613470abdb5c763c0272e88e34ed38e617d6757f4e70d05b8ec9f67a023b4ec1363e7e60e38cff64e18f0510000000000000000000000000000000013fb1858f7efeec5fd03d9f7f4513e3e9103c340eee7bfe48ed3cd3dd073b96add9450a17f12e161f1d44669b1b2f813000674ac5d09c6c599173bbe9a43726c120c3a60a96d43954727a2f33ac4320d000000000000000000000000000000000d6c135bfe0fc7af93571a69b7c37ba691f051d69582cf159cbeb0bd59b48342172a82a3eec2e3d440805934e1574f2a0000000000000000000000000000000001b04e56cb3bb221caedd3582943f89a33b955f624f9e473941f1dd987f2898339142a654d11d87bf8bd2fd0fe0d4c1a000000000000000000000000000000000f185fd420b761a1e38d542558b0beffba916f369b37296fdd8878a7c3d2ac9d3ab1d8e45ad799f0d81bb439b5e5058100000000000000000000000000000000002d10ce460c414fa1094ef2b7de8f1ce024b6d086d10067be0fed4e45dc25c8e50bef361d39a2743be1e1ea4fb7e2ef773f8e9637886d795b75e7ecaee512005c1780e7ab17b9f20ae9232595478bb2000000000000000000000000000000001972ea36bae504d7047639ce6e0e6c3b16afe89fa3d6c6b33c910c8d4b70782d8165912e5bfbe8bd84f78f9f23f7f956000000000000000000000000000000000ae55c4fc1c01f1bbdb060191e8551a7ba5ebd3dbadd138202090d7dc6765fd1ef5fe8204ae76a8bcfa03ee5985a35280000000000000000000000000000000018ebed295805e0fc14f1c7b0e6ee12ca48cb7177c1d367a613e0d6cfaaac5128fefce0e8f38d4e2f11ae0d327be466a400000000000000000000000000000000157068d89fe48e77e0f62e3b5b0293423f35c5f4ffb9e0577f5aa49e91cea6bd312a0e65ec08af9c1f53de6499409c8d759d0bab12ac790cc3a16e88f1a108e670681f117d4fc7d01f8c5a2d6ca7fe8e00000000000000000000000000000000120e4a8935c08032dbfc19a43e2a770b12b05cf1dc229e12f683f0d7f604bc13666bf318fcc38038b618ef83c9448b870000000000000000000000000000000004e3f851be46bd85f37c8b1d84507f4ed63ea76bc305cc26a6f4cfa2135d5affcd3b319d9f57619e21c964c6246fc3f600000000000000000000000000000000138733f352029373b19e1c40d5958a04257e2b344770e1bbb8f377bcfb1c7225ae7a8b0b0e57795ec06a08e13c90d7de00000000000000000000000000000000093e85783c556a017829e28bc42b607b1035890fb9743bf0e279df4dd8a695c1dd07a76a213087c3a8a7e614b29b7a1ecce865074a8a41f8a3f40228046c5be68bdb50ced10bb73ac8472f0525302938000000000000000000000000000000000be1ae00f9ba0a2e57f94728508e0029b1bafd52c91ce718ba41790a3541117d1a9f846d68440978cdef016c3b9ae422000000000000000000000000000000001947683154204c9fc93e3aeac17b417453a24d01804e8acbf6f67947f5962dce875f49d05e6ae65384602828784f852c000000000000000000000000000000000859dc1c00b49cd1292cdc65c6aa4b11e27637b949c7db508930c557ee3ce00f98f9cd3dd0f6d73a646d176a91d75c070000000000000000000000000000000015a7a6984b5f42aadebba1e1f4682aaf1a2d01c9ce2afab7fed2269373467787bb1361b493dcdd862180e9159ec2ad5785e2f9597c9b687150864e90ab042f4f012a54d92cf9d2ece09e4a081ec9773f", - "Expected": "00000000000000000000000000000000047cc33d9decfd059724bbb014fb9cd95de187e2dd29cf4a9bf9ad06d415e2cacb5a4e49266c13e0c38f2563d1a21d6a0000000000000000000000000000000011c79d93fa870d541e79ad4037c20b85d3cec053587f9df60dc11e7dc2727d79059f75bef76474c09fe61ed10b317cad0000000000000000000000000000000003df3f0db20c5ffea4dc9f4d9333d76141447bba50da18e521e89aae1e63750c71b392570d79e597967dfc9952e903c60000000000000000000000000000000014e83ea645b1019ac2dfafe370f616af0c5baeabe217ac1f9ecf78877717475b25911b339557422526a8163434439923", - "Name": "matter_g2_multiexp_96", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cd1d25f285c2073175ecad5bba4987cc52012eadc7b19dbaa20fa82d7a6cfb8a52f33469b6308d921eb4b3b23f7022d000000000000000000000000000000001707b67a23d9212d30c06f26f0040c38389b185057e80236d2c828a8d9ade4f72eee1d6eccd78e4f4d71e2c28ee9539e0000000000000000000000000000000008e5c04effd14d915b9afc2083afa2b6d4008cfa0e47144a41982d8b5a8e77922a2609384e2c5d18c871ae24a7d505b7000000000000000000000000000000000f414acb056fff2cd6d9b408adb6eb7f34c8f66a66ee93945a3381d46c2d181613047ca6d4067614c190da444223cab685431a1df7678e49ee049b75ea968ca255ef456dd58cce57b64edffac1ac223c0000000000000000000000000000000008ea841aced2d0b8dd688947648a8ff18d0f6f03f63ee1c331f126dd4fc0da3d386535156b80902bdc1f65add7769cd70000000000000000000000000000000017a32ad2763d99c38c954f62466e78c0332e48875e15afbbe9c78376f1bab12346c73a573738353e2162d3928091dede0000000000000000000000000000000010ea738884dbfe5bc35d031bde9aa4109b1fca529502e236aebb5ad0bf71dd2f3db250d924415b0bfca56519f8ca5d290000000000000000000000000000000013699e29cc1871f51a469898be8b3c732b5cf7860286e655e65bd8176832804d17b48d0ff85eb023360db78162581297b6ccbc0b600f11f1b89061d94c6fbdc9b1d389244fb29a5d140dab8842d44eaa00000000000000000000000000000000004d504e62b2825651381ae862fd33407309851d5291591cd0f541fd092800d709ede00a9134e65ee752eaceb0a344b50000000000000000000000000000000016481efba290c37aa4ecbf940c76ee5df199b0c1f90fddebd2db28120bb5a14dd9f4a067b6d4889aeb683cca0f6ab337000000000000000000000000000000001400c89942cc63417ca4cb05c9d81dda3251e5611c27fc7727c3e803170672f103bff26f7216a0b646533aac3171488d0000000000000000000000000000000019889641be9db08880543ff476b9d4c72167092548ba49a3f3ace4518d3874f4f7993ae7b8cec90f092f144ec9d66c1a54dfe31190469897c30ac3736ab166220dd3702df5bc897835347713d03a8d04000000000000000000000000000000001927fe80adc6dbb581349c603103ad8831e645d9275af8669939b83829182cc6e2a30df2fdeda6d3aa2e2a6126e00ba3000000000000000000000000000000000b6d7934d5ca1098a85a0c60acca075220105e221b802b1be97c2967820bffc2937fc3278ed0f26905c60d44d5fd8dc000000000000000000000000000000000057acc1379f23c0d1d37427d400eb1b0a89f3736c83d3ffd797ae279e01e2acddd84082f13f3c8b8f1bf7c275702a9c700000000000000000000000000000000038dbcd7e08d34c553850a52336991a7d48968e98057e930790d78b5c6368eb2fe01571b60c4aefb653ec04122953d56eff1ceff9e5184dd9fea44da4f07529823dc9b100f776cef6f6881120f7de11a00000000000000000000000000000000014052031b88af979b7edb06c99c2e46bd9df2c862c7e1b71321754841fad67fc3242b51141e49ad86b61344aec913f40000000000000000000000000000000014806a86d078ee9bdde99257b67f50dc2ddf9bbf01dde931742ee6f739aa986cfdca06cd32d23d86f2c14c3b09033d29000000000000000000000000000000000e0561e795d35ceb8bd9e3b276406ec1f697a38ada25d1dbe08715a28bdd3d6ce6e0aac01f7dfc7c2b403850ab213b4700000000000000000000000000000000146a65209b09487e00e356e3b29952280ebc6a06343c4ce14efa0c6281bc2482698bd02295bc35125275ff5f5bb867dfb273e4c6266c1f5cf022902fe1310d2191af91c47995486342bc61cd361eab8500000000000000000000000000000000021592cd7f4cf9cab3be53561c889c9ee865961aad51339f6393dd6a0b7dcc8a7c48b753c947b15cd3add01abd3d76d8000000000000000000000000000000000f9e1a80bad58055a8577700c177889c4d702de04343c1202eaed9485a76493158547b20bcb552b66c42a0c86df809ed0000000000000000000000000000000013908dcff1945cf06f038e3caac9a7fbb3a6466ca18627e93468a875759a2b5599a96834ff21fcd6bfbba82b79536b9a0000000000000000000000000000000001b6354665109c5a64613c3bd7d805b3a34098708f3d41c7b77db031ac6fa0b2d4e2f2f70c84ac78687b0c0f9bf334771342b5cd4ad3179f406941ef6ea15d0aecdf9f6d96dc334c39b7dca89d256d4f0000000000000000000000000000000019394063202186e141dcebce7b8f0f267ba6057a0f993bb1cbe22a5bc528323823bfd1597a87017d478186a18f09a47800000000000000000000000000000000148437bcc43d432d70b47dadac8e738616c97d38d0f84dc132599626612f7bba74988bb23ae47ac15e6f70c059d607ed00000000000000000000000000000000180851594710f4bb5be7ae0104a383081c50f59e4e048614660ab5a4e2661e171510f5b112d8cf97a6af27d56d137c860000000000000000000000000000000000599f3f82f29b493ffe9ee3a8363b9a599a5ef3c9c5c680d4e003f4ac5a7de0562cba8e2a4c6da7d07cbe86c3f7bfb85b36620f65ed84fc0bb344b4b73f4eba4b1680a47b28b47f6d10f9ee82398125000000000000000000000000000000000cfdce7997601afbe484901893a1b5fc0b83e8d238d41d2f889a58fd4d884df1c667a000b53b587df2c42ad46aa2c3e0000000000000000000000000000000000c50bf3e06400cb10494cd09bd89f3c96ff49c9f74dd5325f9489ed6be13b59bd7b0b2351411ac854d430405b8a2a3de0000000000000000000000000000000001db313a34ca4073e4fa2287e234ac32bc579742de22e5218f7873b922f5804894826e6054925a394f125fce850f33ef000000000000000000000000000000000e0627a66d286e8d4d3654b32fc5f552a7ca12f0bd47eb6dee0dde22ee48165247c067a0f4c3d422bf3562d38a3c0cf1249ca9bcf879a770b0a054422a6ea97ae795118ae45532c1523c842696de6d170000000000000000000000000000000005285ba39f5bd981fce2fdf853706d70992acab2dc6d4c4198144fab397392a60d631056b580d0d98f3f350414ce554e0000000000000000000000000000000013bddbc1180f155872376fcdfaff2fb12d3d9645b81bd1475a5323ea855cea820ed7eb693791caa9bd3fa5c66036439700000000000000000000000000000000125644d32df397def58dff875d7e3f14166e765ed49a3991f45b38d74db3985fc7f5052058d85594c8b97afcf850e11b000000000000000000000000000000000fca4662eb1b39f576ee820385fba88ddd2fc01fcfb9d9f874453ad725cd5defb357be028fae97ce71bc5ac26d11c1bac014a0aa616e809b674390b4553bf2d9bf325e73d3a935eba94488dddee4e8950000000000000000000000000000000015b97d7c74c8ec102083b41d7ce5490466e1c0e261b5ea5c756d3f9ae79dd2d8ec6eb5075cfb76dfcf7bfdd80442f7d10000000000000000000000000000000016812f845faf96b8b69ac7a6af3c8947aa25877199e3c12552527706a17b768bbea259ea61ea82c4624a96cbcdf4040d00000000000000000000000000000000123ad55e5cb5ac5bdd3ca0a5afa7c3f8e4b98ad91a205f073fb546fe799ffc57b3c1c3a6209547ffc6ef05fd24be6f5d00000000000000000000000000000000017719f31946aedabe0e9d88ef3f90eb6ceda884f5e3d2ece368373785b2d8bf0f9677731803b25accfcb6cb716e0aa4ab722a1c20f068b6955a44073914c418a082345796912ca634e79983a24ec4bb0000000000000000000000000000000000497e3480d58027c780f47cc35a121ee0cd76c4e84d9a2f9002c04a1c286be990167a0138049ad70467132818f48ec9000000000000000000000000000000000ec0ddf938553105400f70989140ca322d996f48ffb1b35641ca36a6ba9ac1daac1603c100822f80cf62ec3bfb442158000000000000000000000000000000000a0b6ebee28a792df46d2f727af812c15fc91a471e0d8e34b25b26048f3b9606d8375b5b268c40fb04ef8f098e1d03340000000000000000000000000000000017843dd19bfabbd0cfa41fb58e70a8900397d17ccea783087ece90962560f5cf090e8d9eaa873a6a6ebac45219ea97a68b314f83cc3ad501caa44b4c3ca8cf68c70ff6920f445d3a7ada212b6a19ba3e000000000000000000000000000000000b27c82d71f7e4aab9a68596669596df3f62071e921e131ba4d9e59d8d81d370e077e93a4a6a43e059661227f40b38c800000000000000000000000000000000093004917ceb2fb4a1b33960ff74943d520f86e83aa02b9a6c85e4b9a489e9331863cd30cb6ad6f099d03289b4ada5520000000000000000000000000000000016f04e35186c7deaf730708e1678089bf3e73c1164bca24bf8f70c4f6cccd5bbb34bbb5dc313ee428aec4ac9c638a01a00000000000000000000000000000000011052348cec9dc3e85e01abcca5a652461f08a9f5d72b3fc27140a6a571137f0065ed7ccf9ec8cebe314ad9a214d5ed94ffab83099c69845cc87727d459ae300a5725ec53176424ab0ec8bd3f80eaff0000000000000000000000000000000007083dfb0738d58ba8933a1f60283e5da8bf90af5aae4053ca573ee7223d3b80e4bdc30b4a831ce6af9f52f393e9742600000000000000000000000000000000130c627b7d3a527c94cfeba9f514e75eac047e1b6088c082229a8c95d0765a0898ce1e45694ca2c7935bb8e41e44e8b10000000000000000000000000000000009610645b074e652a08f2b89dbe594afa3009d795ef211f7c036a56274b1e1bd69a035c4f356b6b21f69b9cec2bf7c32000000000000000000000000000000001020f3cdef468af700269aa1e9d928e71b8c521f23586c9b0155314f0073da7de04ca41ececd5edcc052af72c05f0e4bb1d80be637e2abd98d0433150e14b629d98fc0918c7dfc179204669ab465e90300000000000000000000000000000000123540047f0768b0af841aa4aeceaf3dac31ea832daed86c8cbd1d33ed0282c6f697d5881f9022af032e90ff82efb6bc000000000000000000000000000000000113daffbe413075f5f4f6fb42f37b6e9d5e5822aa24d6f865792f63e6078584246bcf8b17117385db1d6233974f6ed9000000000000000000000000000000001067b46fd221b6995d25d4bf0adb088e0554d858d4e5d9d6b59e1ae2a7d57188d559b0208918a8944aedd62b1ebd4f4700000000000000000000000000000000087dae77e483d5c0baa37b9b96dad5ca92b5869fa253bffad24dd8747446f7ce60858b52438e58233210d86f470f765fe670a57ce4dcfa680e60ef33ba99c437e4fdb160ea1012de36f4b59613a6af8500000000000000000000000000000000039d09a094d655c139cb9714aa258d9548473162548048b0f07c9317a41a7e5dbaa5aca156992c8a509d4071d9ae4394000000000000000000000000000000000f0273a38b1b9d006efa43c15a53f026587a676912d0275968608519e97994ea9c6a147e377f68b1738ebeaa178f9c1000000000000000000000000000000000132cd92417578d2e46884f1c1a1080b1916c8c8404d2533a4de02bf8575c80ce7e8097c2ddd1f95737355521c0ec21ce0000000000000000000000000000000019adbf09a268a3ed8eff936d25fbe8af2874e44d2580c7941dc14fb89c5da963b468a7088c4a763eac89f4d15deaaf5e54a999fdf391d3944318c54680e69b58ce3778683b6f2c607d64450ed32c6d89000000000000000000000000000000000756dced467ea32c3c425590b7690a45e250e464ac6927ad3f5d2d8d2826961b8dd7572db609375c8d06cc3b9bc3a157000000000000000000000000000000000b79b4eecbaf1d0f8a89f9ef8fc144b3aff38148ae260da7c20e9dd3866d946585df7ed12c8b7005e7b0e1387c9db41d000000000000000000000000000000000afc403b008b70e19f17b1ef37c9c396577a585b6c34b23d09621b891efc00ef9460c3f4b5f3e851ef63620dc06c824300000000000000000000000000000000024e06f3f3b18c026a166c41f75d7bcf699480f5b6811463c27606c9ec1232fd249a46235b7f5b5a2ed3b53231b333150563ae7b444cca7ebaba36b8d59aaa5c0e6c1454a4a2907866247e752e640a7d", - "Expected": "0000000000000000000000000000000004f2480d0b7e84a996965b76055f6879aab5bab26656e4e5ca7220adc17f14b5946047484327bbc5952d9f2ffa5f92af0000000000000000000000000000000002f7260c55c500b54df4391a55eb4adefa7d19bcbec82a107fc0d222c898b97360a679a02ab3023ce2ebdcffd125ddf30000000000000000000000000000000002cddfa94c8f6b3f29c2fe018b1f8679d0e98c8c2656f86f327b9cbcba574cc52643ab423b458994a03347460deef6570000000000000000000000000000000014eb4c84f71ef5935e707a11a92ba34780677ac7eb198e160585ad92aa5c1ea21e3a77be940fe344e7e170680e2a8d53", - "Name": "matter_g2_multiexp_97", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c2c4c039047d297049afd0e8f0375bd4294d628d3a22078d93b684b737e8c4b6ad3ee544ecbeaad6b3c75d8d217f3a20000000000000000000000000000000004c77a2c0943c6f997ce2e785461f8ec253c47273ded4e1af43ae882766ef8c168e66d831abc2b3b3a0849bbc210cbd40000000000000000000000000000000004456a6c267a5cc6b7d9a9f573270855186a1b621cfdc465fe71ddb4d614565d9d36b13985b31396587919226843c6230000000000000000000000000000000009487cdd8a0cf7f40e9087fd3121cb480730f4302339d25fa12128033239662ed65579a59b837bf1bc5fa87db15b15335b59d128b5ac47106b4114cf225dceb621d177141ef5783943f40a54ad94e990000000000000000000000000000000000ba43205e8392168824f77bac344d60c1a9a0b14ab55538c3bfea4a64984cf381a2f61c64f1ba1bcfd8a7973e43f6e80000000000000000000000000000000000e95e5ac415c3e3e7c9feb6e7a2af3e8189afca06ae1fe54bbeb31783810860921ab3c76a475fb227b3c8299e3f1caf00000000000000000000000000000000001e3cb2106a23e77a126013087751c4d2a419a51beedc3a33faa6c933bedb3d34ee9c6450c583642426edb352e04da98000000000000000000000000000000000ab5af4c98aca1fc3fa55355351d12f3bc639662bf8b5b772152988d676b00ef39f767237a2fa3be936e83d1dd77da86a057c0405e24b7373f67197b2109b633a02589711b6a92ff49ca024f893d7ecc0000000000000000000000000000000012f3d927316ba638bd6294f7dd2f3f166d20285ee1662ae4dc145835704a17127078343d26042a5c397bfef31754186200000000000000000000000000000000162893d6252361c340057bcac31986458b8b55a8a4283f5a06ce1730098f9838dad1bca264374e7261bb9d08c177c1820000000000000000000000000000000017264aead0ec41a079827296f3d32c12adfca7cb6c674070d54087438d57b6ccca4822b2337263e60075d469b4ce0ccc000000000000000000000000000000000480cae035bd3bf1b4a4a766bcd5f188833e9587e1aff0e1f10e36ebbf2f3ae76bc0946e7c336efc3ee00bf42e7efbb9677b05905180182427efeb848b2ba2eafbabc7519ab33db14de0746afb607191000000000000000000000000000000000d13375356b1518e37a13b43b7d192eb74bd69636f91c570c41a741a8763c03caf8d13c7364f57c867a4a3983e88060f000000000000000000000000000000000f6f78dffb404faab88ac7373e0c765209c0af80514d438e18393bfcfeb60d9a5e13158d399f43162033571ee4a75dbc0000000000000000000000000000000010c379860638ccf3b6cb8479aa38881b0004197e3e367a1d5ef7c7fcf075689d283b87022e2825b5c789ac6a448467320000000000000000000000000000000002dc392872cf2fcd8e196f10c1ded175300070e4e38aa58c89c81e1aa5faa08d770a5ad90a8295a890551f9329a13cee53e7f69582f4c106ee5bfccba1d5f557736c1b75b6e3777cfde47d552e6bdcac0000000000000000000000000000000010383a21acda7c8f3f3be980bff2d57fa0a5b2dc424164dd2ce53c0b20ca399d6227913b7b550462180b01c231e4813200000000000000000000000000000000078aec90354721f0a31e1377b3652bcb1f388ab36f1866c955f3ea8dfe6ac2c25bc4cea14f54aee71595c2c1bd2dc4910000000000000000000000000000000007dfeec77213d952c183452b98ad936e8854608d950c0c1451262cdc7d6de5aed0db07a8d74b3e8f674967cb4839c4d00000000000000000000000000000000015c09e4ed2ea76d10d196f7a733ccc272b94dc436d6bb5fafad2fae4a96372c2c6f1325d1554746814ae292d8e6b1e3634c87bfb629b817e7ab97def7400b0a83e47af8d628787ff814733fdf34ba8d500000000000000000000000000000000138656fa091cc6613b1fcff04a3efb4f9c393985b2c78fa838eecbbbb8b6dafd88d9c72441f9bc735649480b5187acac000000000000000000000000000000000a35cec4819ca3321917cea5aa589db8cf61882fd1135031dc41a8207a8e71d326312799291b160a646148c382ed086b0000000000000000000000000000000005b6e4c02c9c54630c96271073513cac3a42d47a7272f62a21c7ad4c85c19b60b70d04719626cf4273f6c5691719931700000000000000000000000000000000166a20da734a47d7e28cce8f0c2d679fa6c738a7a1ca9089dc67ba2b1c92a83b024b8991f131e7e8802a617153de4554bebb60069acf431e1671e3d00e4da0d70fa11ed4099b21d45a2b811f99dd9cca000000000000000000000000000000000a4432a544deda931b1f62759320ada2963062e722bc1b748c9bd0d026ffae10f228be36ea0ab076358924f4c06b6feb0000000000000000000000000000000000e955b1b1b28d2044b6be371c58bc85097c77145b239e913bb0729757518c465d9e69338066f7496aa6a2038ea604f900000000000000000000000000000000017ca2a7d52c3a82ab8abf9fc1bc187389b6e4904e161541008e5b3ba0981870e01060d1272a6d59bfcfb294c942403f000000000000000000000000000000001870649a50e0978185551f213eefd9305d33e92b3f8c39752b6ebe18ae86ad97f92acef05971dceee3b3729becea18168b1ee2765e762f1b8c2451270cd5a755758fd733d7922a537aa9f1fd7d0c95960000000000000000000000000000000013713effa20d5039ced751ebafe1516f062f11ee05ffad37281cfee9d7a49ab14c065709832f6674bfbf2c9f379bc9c9000000000000000000000000000000000295f7ef148430209b48c292b024474f05036edfdee082c56aea05a62f1fba3ee7a540955423f78614c8385da8ef60040000000000000000000000000000000007408c97321b6d7c27e5e442a9e35b054e743c34d845874aeb1ccf4e903ca7803ed7fb1288327865f9e0ff0a388e92b400000000000000000000000000000000081808d03722a2d48846a693059c2662dee614f181dc406825544d30a6adc0f9d84a712eff80bddd4a27a036e4bf7359d5009fd559714d5692de5500ec8cae9c04ae1ab1c7c6e08c8738ef22da19ceca000000000000000000000000000000000880b646a674723c15b240ff56d2031e5db724251b1402a68df8b26261ffc9fb60a81abf165c6832137dc7a7293142d200000000000000000000000000000000172354b62bfb8d388b5a984411414738302725a508e8abeacdcb46454371d5e9cf762028fb65921d5c3dd8c67d42a981000000000000000000000000000000000a1af459bc3122dcef78359e468f4094d609ae3da09ca5aa6efb71a7494dafa2373a3906bac1f324d98b3eaa982a27d500000000000000000000000000000000092ac3b47253c7f090df076914cdc08a715faf153e8e365392b4859fca1db14d3f7fb998c97de9ad99b7d0b357252f086330c755ef708d8eb129475785f24be9e7836385ac918c60ad36e80e2f3281b80000000000000000000000000000000003b23eff722c078a781771d8b75d519e7a062ca3e4252ecca877845920158fb20d79a9ce449d9087426b113da0091826000000000000000000000000000000000c9026e8d3fee6282492393db504a2c41db19d8fbb83260624b05ba4107d6cb2c90d645a3c16862b27cc3fcce9bf89840000000000000000000000000000000018b8648d0a42285d474f809519696df9e1ad5c35d8e848ad74fbee37425aee8844a8be8cb4d3331670ee294ddb9a290200000000000000000000000000000000068cad37ee8578f4b502ac2ef4371a10e5432e57fe20d0cb074dc427831872113d3514a0b199d813b796b8357fa2a3dbc2431888d05cae840dde4c26911db1893659fdc345d5433556d9bf75e51fe3740000000000000000000000000000000013200f0aea4c60937be47213b6149b0ae76767f3559e0519f774af4a5d9431e2dd7ea74b42cc3ceb28ccf0d2f01116f30000000000000000000000000000000001c5bff08fd16ecb68f21289a3e7b9a2ec5da1357d604710a18e78ab780f8ef0343d5d9ee7f7988a009329b17e498beb00000000000000000000000000000000125453772eb9d1335ce4dbcc8f2ab8426fe89a0e49fec51d4e96718a38570aa82dbef452368141be2df260fb131c50b2000000000000000000000000000000000432cdd445519775b9914a986a0941cc829b4a15cd361df9ae7129547b24f7a6a15cd8fe9393fa1551db2d761a208b8ec9a72369cda74e5c86c6559cbc4f4db1b3ab24c5150c7decea862ede3c02c505000000000000000000000000000000000396cb6d7b44f92b716ed02985d351b4e8cd1bbb95f239e4f29d7379428470be395e2faeb8e3a910007aaa490d3c336d0000000000000000000000000000000000ad0c0623fdf50c2b504777554dbab3cde1b9705e976561873d7c22b81f49c7654a7c76e558fad1518ed73a0d3c3570000000000000000000000000000000001241d5bed68e02a2ddeb3ccbe109a161abe81edd7affb72182c5163851211c4763e6aecf766053b61ce575de893985f800000000000000000000000000000000183696d2a48feef6088f4e9f75a5055e8c54b3813658b593958490ddd4245ac495a8ff966861b20f26047f07fa8609a0c2f50989b04fc29c4c4a0090fb11e860c15f89a66f3bb8281e4678ba63ff3f9a000000000000000000000000000000000fe0ce41aa9e7cb2bcb4e01721b7b1d99fca4e9b7c4df09bec00bd346fc57c25118ba70d5333b7f3eef2659c64520a470000000000000000000000000000000005c932e09c62b7ddaf3f5c420c60740befa7cdff5bb812e0f089c45098d71b57004b7a207f0cdd34daaa3282cf6e9f7e000000000000000000000000000000001874200ead9776c1ecd6a54a57e5d0f9577910a4b3afb9b051622f658fe3ef6cc5070af60e7ef910562720e9716158d6000000000000000000000000000000000c2c657e58e400a67e59deee8c28234ff4688e781a2f6f2f0d0b186a5e4012695a522dfa0770cfd543f55939a05e20b09fc9abf1c76ff11ab538f46ce768ba597eb5f2f63073ec67e8de10aa1d666720000000000000000000000000000000000f0b561e5860321249b9ff434c604d26c3275824fc4ab9c1ce5c5858605ddaafae83ae27e523bf6006932f6c7f33d0a7000000000000000000000000000000000b47aab85bbd909599aa85c5eda363b67790ac6729fd8b1f4f53f66dd796cf2fa3496407b1bfaea4dc8eae53519054e70000000000000000000000000000000000cab1ebd23bc05c53bc9e8481c469eac3ee1b140af545bebed10a8fe50698d2ed883219881929207c0addf2f687198d0000000000000000000000000000000007742de55b799950e6f786f4eef45d0fb67e0475272ad68a183135b70047abab6c2ed51ede16c39be7b986df334e9e75d4167723682bc0e7476797b3be5e14b8de3e4e23b4ca33c50a2096cda8766dd7000000000000000000000000000000000923861332988bc843a65ec5dd4637f9dca8a15e71b82c780fe60d768213d118d8948ab554e30bb9253e900a9b7d87f200000000000000000000000000000000132b1faef49e7966a05783ba526e71134bfb577b13116548352da37e91e617d7c72ed2645e672ebbc517e079247dfb0e00000000000000000000000000000000000a46a8893a194ebfe077afd05fb25d4680f1e4991a3ec29475fa5651d086d20b38136155a65a4c70af31de5a78af59000000000000000000000000000000001344eb957594028b4228cbdb8efb03cc7cf49ec43b2ca5481eae1df6f2df3d5be9a7c4e4e78f8c39be546e29a83c92f49644c3727f78dd12811092190d5d10adcd5b9fc581dd783c97d4e7b5130f309a0000000000000000000000000000000012d7111303563a6358e5ce9155d7a153b5781062c2f6b919efc67ddfb4c61ef03be8828ca6339397b84763a5f8a7e8330000000000000000000000000000000010a2a0ea9973728d3fb1b5906ee84b2635c687c11398ebf605cad30216df3b7b4e3ee1653d4b323a690e6ba614ebec30000000000000000000000000000000000b93d5de37b892d4de9407a820c73ecfd6cd9fa565db82e7e8c14c8406823f705ff0adf6bd6add5ddc5f72c91e52e840000000000000000000000000000000000dcb320ceba5436df8f099c5a77f34376c96d830f5e8ab80667d156d89f6bf8998c148ef9a53847ed395871ab86f6d280df9846c84354ab7f947caca7800e12e38d8e6651527e6831f4d8b1bd66c4f3d", - "Expected": "000000000000000000000000000000000ff3e299e6b9fc488d6db991cf9d226d330846e87c4a5cd3e5d4ac955bc2c3c2d1ee5ff230098b48f594d256495f489800000000000000000000000000000000097fdb8fc95d64c7070d8c71e0fd2a933d1e1ad3fefa230f079bc5743828317cd1b0c6d4253ba9c3c6ec6b12d53afa700000000000000000000000000000000002448bbb179d82eaa453cd5452752b9a083b52694cc65c5d9b47f72eff118d7aa06b0fba18eafe93d2937d7399c001af0000000000000000000000000000000009dec4c0aff2a46b07855c87e08832811633709ddfbbc30dbb7e78b3de43bd95e383baa6ff4c58188f0c7643e0ea5a40", - "Name": "matter_g2_multiexp_98", - "Gas": 293920, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008afabec8a9985cbbc6246825785654c1d2eb7da5a01f76c4af4d0096b9baed3c33dbe492d14a6f9e762f06eb3d198f800000000000000000000000000000000027c592315dee4bcc892acc6f41a6eff5219c308253f7cd715d0e4a32c03c6d0d0e8568e146e9e799ac3025486c77fc30000000000000000000000000000000015b4ee27a3aa518a1ec1b447bb8f9128301c85b7176296d68dad3339b1dee78715b2f031a7fb6ba376145c97ceafeef60000000000000000000000000000000004b7e30ec7cc024ced863ce511cef3cabe954a4e5843dd636d776645a44225a36ed7e153ab5bf5d18f23c6444751875c8a71abe11a893fce872f6b8a020b6d84241df03eb934b50cbf3571df4800a83300000000000000000000000000000000119949d36d8d8e2bc1c26ded5f5fb01225a980a28b934ed3862480dc9297a3758e0f08ccaab3a09b5e5c0e4215e3246c0000000000000000000000000000000004a82dc22316ee6af39d937b662d1f1f2dc855c2ca8f33ec3274d833e87d594633fc7fab247911e0f46564397910d6ce00000000000000000000000000000000196900a09d8504ed960d41f4a8a2cde2e5dac61b008d3f6eb47e86d7b2ce6fcdc0f85157e3ab1571094d9fdaa75d0d500000000000000000000000000000000010c52ef9407eb4ec57844aebbcc3ea5000b1940d035dcc2a873327affaaabdd79e3560cbd29c63ce04f6279056d6eed1bbf28e5bca314391550d3a0fce50b1220965860e72c8c3865a2d4c599d31d3f1000000000000000000000000000000000e43655ae05dc6cfa93113dc26cea895d1c5bc73f20454c7b441dbc5ac80035b290514b13b31b41931ea5336d8d9a6a7000000000000000000000000000000001199a873958c63147e6b82625dfea15ce90dd41ceb4e315f67221eb874ef32c6a2953412e7e981659c72239a7a72bfe6000000000000000000000000000000001845af5936b4d7487ffe59137ba2f86daea3770cf37fd560969ee48243389941a1072205e049ddaa06c0ac56b7edc8930000000000000000000000000000000003cc831177f24614f93a118b896434105f05a277051a852fb9973a775fc54f779c2a1f3d64c457e5231dc22d6aef606b58b208a6845aeb2bf31999042c59b7b130a7ce5297e88023953b1aef63616fe400000000000000000000000000000000005e63584bc85ba58615985f6a466afe05268e545e0062cd7214e0b6fc8b87537c745b754cd9a1144948bc88b3c43acd000000000000000000000000000000000635b6a49090ccede3ed2ef203f0ed164783e3df4d9a7d93319515cb9230bd841b61a097f39e30175793b3e934d8e426000000000000000000000000000000001861e65f47a9da1584c45bc79a66045d86bc1709c2d1cf6cd2930a9fcc8c4efaa6536b5015be8d54789e8f574f93f9f70000000000000000000000000000000009290ce63d55eb436794acf11be9d896f03e7608a1bc8528f61ec9473f054bc9fbbda1072440e58e2f6ba080a01180173b53b6cf9e0ce1661c4960283be790abf956c2d6433529b8f3a32b92b227aebe0000000000000000000000000000000018feed9500bff884d2bb58554da2180c68267b6d3a45c2c7cee4c3f8524252d3faaa5eff971bf40123587e669fe66bbb000000000000000000000000000000001441bd3b58b4a4a87c2459f873c0692f5977b775af984bab46dd76cb9f775d2faebcb77b2854c9f1faa33f6c5de61c6a00000000000000000000000000000000123a890c3362c77e5b5cf9846d9c9e43fb3242d5a831e640ad080993fa0547854c8d11cc22f7f7b426528bf1154d2300000000000000000000000000000000000ff4a59ea98d13cfd353ae61e18d3c7018688f755561e6a1da5f09acc4277e8d49645087115acc64f992ea778a11f39bb049228435ade4c4c565e65f39f13a84c747c312afcdaff352560b9fb3cfebcc0000000000000000000000000000000006b019d005141e82393a2ca04469d1f6fd7b9456001ffef4c34eff6b2e91df58e99fd07944f52b108bd41ab6c4d6bbf200000000000000000000000000000000109ae87042029856befff0c916db5437e1e058a96f2970d8816b3becc93a1a50d6d336d5451303715f3e272147a36caa0000000000000000000000000000000000fc381b8dc9dc02d34db13e34732a10d0dfcf676c224a05a3bffd888b0af7c415b38af0b6afe6b464ffca42947c6ee5000000000000000000000000000000000087040d09c39ccd06c9ecc360fa02147a32e8036ad6e4b6bdf5b3883722a4e5a887dd022d53706d2585fe558696be6656197f5ad17062d2ecbdc8887bcdd32e5ed4c48cefd9e14d622a0b800d970330000000000000000000000000000000000e35c27b29df0fa9298bb9ab6a38b3450782223e2115d79152f9baa924d762d583b3ebe88e42f33028814ec78e5b319d00000000000000000000000000000000190c65667627a16f0af0ac7f23af0803bca810f3986b906b7b4f126d98473d52badf45e90e2e45bb390242fa8c40135100000000000000000000000000000000103f0283a5673c16bcc0f74f259c2eb077061947da04e467dfebf62aa005491e32b85cb73418b624a30dbaa01672921e000000000000000000000000000000000465466955c908607191faf15f0768dce42488c488eb4a065977f21ac7484766bc0abf23961ea2ba46dcc04956abf6c7721d9d7fe10104cafcad71307e785321ab87b2b69593535caecbf0e166cfda5b00000000000000000000000000000000082346e352e845a54cd4267f93b85b2c8623d4650e00c1c56082b73ee31f63588d2c117d3cdecc0378fbbf8956b082040000000000000000000000000000000001a7f43c2bb19cb32345c43c950536f8e85815b86364f278f6ec8169eca80917c2b8fc08d59b20cf55f25dc468e7bd7f00000000000000000000000000000000085a5cb020df10f9b4c7afc01b1d11700579dec1e85e766507def2e6cf5b714174f7be9cce3b18533a5ebfeec2b4e481000000000000000000000000000000001836d7506d1cc984fb777b8ee935d6f5b110644f59e96ff44d8329336d59a3e1d2b53a05d35e97f634baa4fdc11a6cd8461531ecb61365908019c1e8074a4c322df2b356eea3f3eea9aa1e0e1fc5525e000000000000000000000000000000000c1c59828ec6257a02679cff0bee0d665d449d2a158bc6d877e84cc0fe2161c297dde09b778d5e1249c515833e483004000000000000000000000000000000000f5e82589bfb7781e4110f1486752b00cbdf96cdf4191d75053c6d6d646e1c989add011361031a11559e156d64139fbf0000000000000000000000000000000015053afa7fb2b4e4b70f3c8a570fef8288fdc22dd951b6ba8a40b6087b9ab04ede21f0ddfa84d6d18914041bcf244c110000000000000000000000000000000003f399800cba51ab35624d866831ab6506392cb3acf549787153ffaf08cc451acea46c7a612821dd96c45f8b75133d88569c1c1ae2d18bbe36ed50db1bf30957802b09a982fbed49d4968815552e010d000000000000000000000000000000000e26242c8f73116079369ef4265f624abd4377e4e3485c28197663de9de9f5618c3b6ee602ff6bebd1c242aef7295b2200000000000000000000000000000000066ceb3ea6067220bd28fa1164237782859d27c1d3087a42b4d09bcc343611e4ed2be014a27f5b394c67643dc00f57cf00000000000000000000000000000000157f9d30de52110ea7a2a35ddfe67d9fad7223c5e3307e797dd0df3621520a421958a2835205e3c4777923f47d47e5310000000000000000000000000000000016ebb41beb85b9489a6d5482f8a3330a5c5c5e5718e8efb8b67362f9d8e9c313e9e563275ba38c207c5bf3d89c406ea62061d33b2f7e786effbd2e93101a56ba1bb62c1a773a08b72ca82f5183bea35b0000000000000000000000000000000005d1c9109b5b7409f94ae3f7dd9e8ae4908a9b378fea4ea284cbd33d1e59b605577b63892aaa8ec14d415f34e22fec520000000000000000000000000000000005afed05e62599f20f7eca019f41d770c630cf6359cb5601464be821691fba5205c16e7b580e6881047214f938e5104b00000000000000000000000000000000105637a2aa4725d8e080dec3b731a111ea4c94b79f898dfd51f645501ef0c8d68ea8e80fde28ff96e927e44306ebbb1d00000000000000000000000000000000080cfeea754474ceb37973234d5dc3269f8ca99bd862d4d2d1a602321fc709945a3209e5ff2cc962cfa6d03017c9a1354129b150752d2d5551a622231ab067931678454aaeb23f76168219406f0d50ee00000000000000000000000000000000137762ea5c80033aaf17570451b15a062feedde810f11ebdbe9a79a3275dc12613e0505835c122bd5f9afea7dba84203000000000000000000000000000000000d89c04e45e60769a63fcd73df2a138c457bb549195f2c4eebb3be1ea46149f286756795be8328b5b886f497d8167b34000000000000000000000000000000000be43d515083c8c10f467618685a43d4d5f6457204bacd278445943a9f44f7189b561a0e1bc59d2757fcfab2e3f93a4a0000000000000000000000000000000011a52583227c6dcdc1784d3633fd584612a9f3bbc1922477396dcd5af84413e5e9382a34a71b3a72491ea09fab2fc6bf366c32d5d3c132f32a6ac3cfe1dabb649c59ae224338f747ad98b193e8346729000000000000000000000000000000000073acefe33525dd2d5204cce72371ed82c7e4b58d1b4e7f4b4994f9c58b02d9d6206fefb3552446b6b355e860ace43c0000000000000000000000000000000007344eaeaae71e17930e769e02bcb4f44ddf3d040ffa0b081f25901cc125a37a58a6a5d13e7b0ba493802ccdaa054e29000000000000000000000000000000000a65fec6ad29ec3eee9ddc7ded2297f49d03ff18a255f1e6d29d2a67c20713f319d79d513af0c58ae3cddfd1f6240ff50000000000000000000000000000000019d5f00d9e2b271f4e9ac779a096386f08ae124f77fb8183405d48ea7f16e685805442dc67a392aefc643ea95b4f1fcfd997516cac28a3968ac6946b5bffaace0856a52e38fdcca11ddfa16cf5a568f50000000000000000000000000000000018230bf1a873aa04855af1426da30f1b3ef4b64eec613b9f660222e3827b325c318baea031b463c7e9f775165d22ec8f00000000000000000000000000000000017faafa1294fac53e1de8cae9601acc62d76a5f01a39ce49d65f3f5d2cd5cca33eb90bb4116b3ea36f912ae2b81b6cf000000000000000000000000000000000fc3ef5ea59849a87fcd45500989f1744cb5570ee88e34a952cec32cea2eb5900b64d8d0d04ef5c51e8fdcccd46412490000000000000000000000000000000001c53aa8aaae8422fa4fddc86cacdefa89c37592c8e67e472a23627514623a90901a619af79e93561a0dc65215837274e881ec65fdc2f58e46d3ee45a06d0c5ac844ee5b62872c7ba21f6b48621a3371000000000000000000000000000000000e3db6885c2db9244548e11b8c49b73f85e4104b413f54308497262fdff1957495859830114528a22c45d39a554ba82700000000000000000000000000000000181b1bfe2d9a1c563e73356d73f4ed3e7061a79c610bc97c911ab1a0213d123c9f83ed6706e862087a796ce14c5cf53d0000000000000000000000000000000013f5fdceddce771588869b945bd6025e5ce485fe78a362356720b474b83998f27e535cfd8d33ee51cfc68e5d514f915c0000000000000000000000000000000007e8fd7ba457a3cefd50c641847425cf2262deb1d6945a0bd740eadf38dcaa616edc48c3912508d663349f089b8b56fadcd9b95e49473277a665ca0f9a8309df9ed6ee4f25d803aa967fb8f688273e650000000000000000000000000000000004b20b0408da7b704694b47607928a655077015f2174fe01bac9a0b3a61dae087b0b593f58d2947d8d84f75bbfb327c900000000000000000000000000000000106d623b2007c5d7128e03e540325ba763e992a651e2e5c78936f82ee2ff72d89a1a914345486cd0a04440c75beb190b000000000000000000000000000000001847348e5ef429cfdf1ba4d265d8c5ebcbec3d5dd4611ba36e2754fbd3d327273bf2eb7b7ba4b3888d059dc87f034739000000000000000000000000000000000bcb0a9dfe5189bc965e9721407b4cb3ed4171510aa4d4e5d5f0823a1c2827643e1278f9c0ee960c54ef8f6c208eee7b334582482a9038ab906880e43a4a9d39e73b6c63604eba0c8f6399eb5c288638", - "Expected": "000000000000000000000000000000001205b70b29ee04212589f8a70a71e004f517d3354e714c1b4fe42cf93faf1a8ed40dbc1b5089ddb53bb052c9cb74c0e8000000000000000000000000000000000f619082734dd9de653b61cf2fb927199f228637db70797bd2a21fdd48b6ecd4c4f712097037534024880a436fdd63680000000000000000000000000000000000592eca560be6ae256abe1796f7ec394a8085c127437f6590c8d41501a482c61456392cb320b9e801044dcba7802df9000000000000000000000000000000000a6d20b8009708ca01a274aed6dece732c5eed5aae5e4c2f3793b5fa1f8cb8c95037ce387bda2e7476e9c493507c7fbc", - "Name": "matter_g2_multiexp_99", - "Gas": 293920, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsMapG1.json b/builder/core/vm/testdata/precompiles/blsMapG1.json deleted file mode 100644 index 07903a312..000000000 --- a/builder/core/vm/testdata/precompiles/blsMapG1.json +++ /dev/null @@ -1,702 +0,0 @@ -[ - { - "Input": "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350", - "Expected": "000000000000000000000000000000000d7721bcdb7ce1047557776eb2659a444166dc6dd55c7ca6e240e21ae9aa18f529f04ac31d861b54faf3307692545db700000000000000000000000000000000108286acbdf4384f67659a8abe89e712a504cb3ce1cba07a716869025d60d499a00d1da8cdc92958918c222ea93d87f0", - "Name": "matter_fp_to_g1_0", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641", - "Expected": "00000000000000000000000000000000191ba6e4c4dafa22c03d41b050fe8782629337641be21e0397dc2553eb8588318a21d30647182782dee7f62a22fd020c000000000000000000000000000000000a721510a67277eabed3f153bd91df0074e1cbd37ef65b85226b1ce4fb5346d943cf21c388f0c5edbc753888254c760a", - "Name": "matter_fp_to_g1_1", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ba1b6d79150bdc368a14157ebfe8b5f691cf657a6bbe30e79b6654691136577d2ef1b36bfb232e3336e7e4c9352a8ed", - "Expected": "000000000000000000000000000000001658c31c0db44b5f029dba56786776358f184341458577b94d3a53c877af84ffbb1a13cc47d228a76abb4b67912991850000000000000000000000000000000018cf1f27eab0a1a66f28a227bd624b7d1286af8f85562c3f03950879dd3b8b4b72e74b034223c6fd93de7cd1ade367cb", - "Name": "matter_fp_to_g1_2", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f12847f7787f439575031bcdb1f03cfb79f942f3a9709306e4bd5afc73d3f78fd1c1fef913f503c8cbab58453fb7df2", - "Expected": "000000000000000000000000000000001672a8831d3e8bf9441972969e56b338594c5c0ede7bdba5b4113ac31ccb848dc2a2c4e23c0b9ec88bfe7165f472b427000000000000000000000000000000000a86e65037cccb5281389512673068d6f91606923629905e895f630059cf87fb37e716494db288958316c6a50de65ca1", - "Name": "matter_fp_to_g1_3", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001632336631a3c666159b6e5e1fb62ffa21488e571cffb7bc3d75d55a837f242e789a75f0f583ce2b3a969c64c2b46de2", - "Expected": "0000000000000000000000000000000019adfbc918cb74abc6fa0664dfe60697b233f0663665d2cc133478db4d6c9a41309ff09f9af9240037a7332bc42ffe3a000000000000000000000000000000000d31ffd63837cdf1cf2a7b3fe23a9d86c08f3a7c44ac4fa52d21b8c235f0d45f85c036d80bab332034635845deb31467", - "Name": "matter_fp_to_g1_4", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000184f1db9ac0fdd6b5ac0307e203d0b4237a50554eb7af37bb1894d9769609c96c8437e9d6d3679ebd5f979eb04035799", - "Expected": "00000000000000000000000000000000192a005eb944f391251402ac3d31c30f0b2d77987ed9928d244f492f96c1a0a06a7cd0be4bb3dfe3c484ab8ac5279a09000000000000000000000000000000000b99b9e7f0b51a2e0d12272fd0d9ae65294dfd34d45f30fe446a25b225316ef467b02acc3b6a578e054e612434096d7c", - "Name": "matter_fp_to_g1_5", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000732f171d8f6e283dd40a0324dae42ef0209c4caa0bd8ce2b12b206b6a9704f2c6015c918c79f0625fa791051b05c55c", - "Expected": "0000000000000000000000000000000019dbf865a67157efe65fa7171279049864bf6c280d3c3462e93425bbf25f9cbad6c27885d7927b5cdca642df48ceccd2000000000000000000000000000000001606be1ef7aaf56349e5179b01b89e172e463bb3446792d5210452905fcde42522f9719b9e7ddeb8cc3f227eacd55947", - "Name": "matter_fp_to_g1_6", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001139e8d932fc0ab10d6d4f6874c757c545b15be27cdb88056ed7c690aa6d924226d83e66b3e2484b2fc3dcd14418ee60", - "Expected": "0000000000000000000000000000000017d476fdf0be6b09206dc83cce64c603a6b911f051e9191a2473a1bc6b1dd2c6e9bc4d262edc936f62911460f0b648a70000000000000000000000000000000016f824bb325ff7f485a8e9d116f4a56ea71ecd2c11b2a4d119c208cf323bc62bf1e9fc609230c571e7830a956e140e47", - "Name": "matter_fp_to_g1_7", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019a9630cce5181fd0ad80677ed5ad8cd8bce3f284cd529175902b78ad4915f0df56f0d8b37c87c9ddb23d0342005f157", - "Expected": "00000000000000000000000000000000145726f8479d7390e7a21cd31dfee0e6203115e72d04c5a735feb2cb688ff74944bff2b1af1b6368b4d095143662a1300000000000000000000000000000000002fd68d51753faa242bee10148c0e473f4110fc7b67848dfbab7d7105090648534854ba75890e099cb738d1dce604ea4", - "Name": "matter_fp_to_g1_8", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002cdd00b7662569c9f74553a7d0585312a776c8638e54ad016f8d9d25df98651789470b12ce2626fb3ad1373744387ac", - "Expected": "000000000000000000000000000000000671b0f33b0f1ea3386e6876452989416c7171e283c4b0c375e840ea05e7fda22aa03899b50e59e9ca5a87039b2e732800000000000000000000000000000000031bf8caad5ce6a0d94f14693da0d551dd4bfd2c2163c8e8d5a448956153f63ce2ab72f03b97b560d67933887e83be1b", - "Name": "matter_fp_to_g1_9", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e63c4d12a38837354bbcdf4f844e5dfe727ebe292016748007d162e74c1f849787767f7e77fc57a42783fe0b06c24c8", - "Expected": "0000000000000000000000000000000007d67999ac2fe6ab93591646905f23aead0d37ca43573ab02dc16c2b199086f788a8a1de6b10aef4f4d772b2e12e72ad0000000000000000000000000000000003700b150ebf60cacbb2b7bcf969b70edb57b34b5c772cdf68d42dc9f1513631799b9b9041c5e94595ea848e195aa730", - "Name": "matter_fp_to_g1_10", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d879e4891a891f2e7d27eb95aef70d5b785b796620ec43dfbb6ae550b4effb9f24210dc20f401d54420445e21cfdd3", - "Expected": "0000000000000000000000000000000006cf4af50766ec08696c9bc0d9617c1f0fcb0ea1bcb576179cd4537d9d31b373bf8e3c5f5fde2c21e44917cf1f51ff0a00000000000000000000000000000000050a9f7d8490ba2b6e49762cf2bfce557e39edb51ef03128b64267fd3c6b996e95d73b26cf1965d427e3445b1ee4d133", - "Name": "matter_fp_to_g1_11", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000028d6de947a3958af5b53578b0ceacc7ef89d36526d8f3b6fbe787af69fed2c85cad3001643b81c575a741c4566e617e", - "Expected": "0000000000000000000000000000000009fbbc6ba7ec2315dc18aadda7b2e53180b904c5f1cbdca1b2f42ed9c6675da7beb4007ab6639520c4736bbf2ee3f04500000000000000000000000000000000113f0bc737b2f3a141121ef236cbaff2f34502aa13e121b857baf327f7be66be97867fc6f752555835fdd01610e30c77", - "Name": "matter_fp_to_g1_12", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000182b56202f0494bd8baf5c03969288a1288b8ed8e6c7f49ec9f7493ee3369eeb42fa8f5fb7b243fb2bcee6be244f02be", - "Expected": "00000000000000000000000000000000047dd479fe99840150e73e4a8fa6be74a9b7d743e21cf33e9d7a9fd8700feeccd5111fb037eb3b15b79d5737ec4c7f0c00000000000000000000000000000000000ba7f57ce062eb9c67d84eee64d64d250a18454bd63dc5a136f5341214079eb9269eea7c4e0d836dd8be63a8a45c04", - "Name": "matter_fp_to_g1_13", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016adb5935f32bafcccb81cf4d177dd8826013d85e11a4aad66e3aa596e1183aeb9d68eb8cf5b716a8a9445ea81b40d7a", - "Expected": "000000000000000000000000000000000e8cf94e68b03d1f6a3d4eac7898f143324d08f7544aa9f952947e9008d2c14e46236667173266d82f5e41887c6f614200000000000000000000000000000000089a1ada37f30b1f6e3a6613705992e9708d0437611f1de72a9f696ea5efea6793f285bd5badbdc20af64df8ba95c79e", - "Name": "matter_fp_to_g1_14", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018bee24b0c97af8aec210f15bbb6acbb76168dabe16e669d5558d8d32f00fdf5146471922fa98a28f238974d327996a3", - "Expected": "0000000000000000000000000000000011e4919deb9eefd13dd0ba5184003ce34ff6c2bd8920dc49b936917a7b6aaf1c7541780b5d0e380e6c808f093a877eaa000000000000000000000000000000000152dbb758aa5f60b8d0703eb30680857abee717114b8cc5f6466e70856f19c76a88ec6c536e7a679c177986bf636e6a", - "Name": "matter_fp_to_g1_15", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000114285411713eafd395ee43bf1728f52d17ac512b9d0cddd38c904a9a3a1b30283a3918cd2cc3da6a7d6b4ff923cbb6e", - "Expected": "000000000000000000000000000000000750f69c43c56df2c8524b4ead9f6cb3ec16d3a6ec913254e585b0d8518e53c18e0e93dd4594adb926c51820de6001c10000000000000000000000000000000011f5c985ed12f72b6ec7e222dc8d93da520ac65476c716e231e7142cd3aca49b25dbd716a8f587006e4a2af31c37956e", - "Name": "matter_fp_to_g1_16", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018a067f91f94b2904c5bb6900f427ec4e93374b5079c84707feabeabde20b5e49801f1f3c7504dd27da94d5e754df4ad", - "Expected": "0000000000000000000000000000000012652effba341826ee7bc3108404f5fcac84776c6f5fef5d440454b59f04afc2cc87f243265248445c7c2bfc14493ece000000000000000000000000000000000c0fd215b7c012da4532c882d7d7f83ebf133d58acaf8b5123c1211aae5929c6726410631c7f9347456448df643c9ed8", - "Name": "matter_fp_to_g1_17", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000dafa9fa843879038fd1566c319c24119989090c5fd34f6514e57f633d3709f0aa9954dfb289843a6990588e337b63e6", - "Expected": "000000000000000000000000000000000c444b07e9ee5dc366c63ba30f1b17087bc4c548963caafacf223f4bf5b5bad1f9b51433bd1942978f3f5e5696d5056f000000000000000000000000000000000453941626954845d89821df34efc6f81660684b08f03fc42da54119d10f1f95357ba75a0962961f1487df45b0c534ac", - "Name": "matter_fp_to_g1_18", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001742a98dd7d3671c2c64aa71023a0040e936fd726c062d520626113bed471e53ff3e85737e5abf9ee8821bae53135f20", - "Expected": "0000000000000000000000000000000013d5fcd7e4a0b1d7d8c7b242b46968519521ff8bc4b990a56ece26053d4bf884afd24a00670911f943522e06fe4f87d1000000000000000000000000000000000aab46534de37b5c6d206959a1023ad4f20ed5966bc3fd1750c1758ed806f077444ac70e9943b4e8debaecf208817a5d", - "Name": "matter_fp_to_g1_19", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019cda532e5d94f3b193b3f286a038637a736c2b87b804efd4779359db5bd95320e06d6d28da3c229ae48ffc02303fab1", - "Expected": "000000000000000000000000000000001440f44e3964de59be03a6c69affbb3b44ffcf4ec4976361ac49c31a23f9f154f91750533ff2425d5e8fcde0974a91d50000000000000000000000000000000002031eb89620736dea022880e5188145f080537b1aec183db70bf307029be21a167fb6456bd1a47a75626280f78442a2", - "Name": "matter_fp_to_g1_20", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018df89e4a545bfb825bcce2f4c25f2416a72e32633b3dead5205c8b7d69c78f119d0e940e5bde9ae1cf91574e5d6c175", - "Expected": "000000000000000000000000000000000a2d7297376216582c3938c2aab0a26494da7d9df45e1af7b4f826f064467a939ad99134be4c9b804b5bf273e082c4c2000000000000000000000000000000000b0a4da7cc585be1be6c091006fe831edb6f6eadbe3ef611041efa3d14f442c9768feb2958efa161e0adf5c321d7d522", - "Name": "matter_fp_to_g1_21", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008ad60829ff001404da40923806e496640a90c5c258a41ef5912f8a1a20eab84ce43b2b5aa4aa7dc4d8b281591d23502", - "Expected": "000000000000000000000000000000001314d7faac7b4d5003baa10cc432108d6bb7f80bb13991f6ac45fd7a772f31cd43345ea100b05f2ad73e3bf583e7e7b2000000000000000000000000000000000eefa97eaf2143a991343a8823d8b362f77d8370421bd13a9a6cc4988544feb0cafd3a797a28d27f4f8d361cb7f49ed4", - "Name": "matter_fp_to_g1_22", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000f13dfef4b3b83aa7f9525eae9913e10502e77c03c55a7aa2de083dc5102c098b6f8e36cb5247b827e30fbcded9e2d3", - "Expected": "0000000000000000000000000000000003ee4f3d29cd9f29a2e559a86d8204a1d65598e7788d585b145022de2c19022b122c1f10423d3bec769545d656726f5e000000000000000000000000000000001803f26af468740849a2737a42e53098b48c0709415247023aedb111c96043e3b13de300213e5196cc3b678f8be0696f", - "Name": "matter_fp_to_g1_23", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010468e5421a72ec85b63f7f3070a949223105763868111424fd151c8365eb0307dbc9cbc92e5dfb296d06ddfb58d9900", - "Expected": "000000000000000000000000000000001800b9766f3e621ad7a8d1870ce16c8cd054c87d7fb100120a38c3368cf1879859645874b23297957fef6cd8f9112bf800000000000000000000000000000000091a8b69a1f4eb883a25af2a3a0d1e384ef7a9ba4e8ff8811ad356781c79f631ea20fcd0590e94b9c1841e6add2b848b", - "Name": "matter_fp_to_g1_24", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008149ce856d489050ea834452bc66f7f3478c2056969354dca8652f3d0a349e40fae0c4c57ff0f5e022aa93c61f8c844", - "Expected": "0000000000000000000000000000000005fe170feabac3805c3eaace41fdaab2c9ae7fe609ba609f4ebce2d24c0d704d847efd510acd8abe5aeff2eb24e781b80000000000000000000000000000000003262879ff5c9831ebdd0de9df478923fee72a8829378f40cfec310a41110ad22faa759276e3b9e015c86c94c3594e0a", - "Name": "matter_fp_to_g1_25", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006295de7bfec61f06a56fe09afbb74be968329e88ba2e87afffe9ea9bf646ff5b4a03d6088e87644958ced95eceeea08", - "Expected": "000000000000000000000000000000000e4110b2efc984c4d7affcbcf5cbbf919c55f948ac7412dc120d30774924d6020a2292f27b8e716c2b5045a561f2b14300000000000000000000000000000000194649f6906daa0394fbc1d45355e17d62f6c22a9e772bd7fa5149e29ab2ac6060d83dc5d70fad75bf3f2c7917b641e1", - "Name": "matter_fp_to_g1_26", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001443e61dbf14b6c6ed99e1917ecfbe5a4a23ab9bdd3bb089fbba76d795d715d9d2e3c7d8db0b7a9434ad691b68bad3b2", - "Expected": "0000000000000000000000000000000013af2a5f26d1f51da0d80fe7c62369ebbec235faf4565e62ba475e6f58418183efc8b9906196ffda72539506243e0482000000000000000000000000000000000774f3096c99bb826792cfd9243d8cbb1bab54fccc3a6347daea74ff1c8aebafdd971b7bfbea5b9a0bce243372caad6a", - "Name": "matter_fp_to_g1_27", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b14b12ecaa94f9656be54772be9b22a2495d4ff873b0bb971c27ab1d8b940c84cabcf921f6f75e93942c38cddeb8750", - "Expected": "00000000000000000000000000000000107c66e91d518789be416606058cfa8e9df478fa097241fc109d065005ae927d83563b72410e5b207d1556c2ee4dd67b00000000000000000000000000000000148c208e55e834c4e4fe20c02f517c21030f60c74b1a3bcf70bb2311cfb9b7548837b9187910bb7e8d1faa40ca8d6d92", - "Name": "matter_fp_to_g1_28", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019eca0daafbfdcd3b56be863dceb21e624b22c0d376fb92ba606456ce3825981713b88e40b7fd801e915f97d5c29ba75", - "Expected": "000000000000000000000000000000000fa72de55fc2229c0176120fac3e0a64c4498bcc7b67ca40b92d47a76a9db87ba498b72f06345c61d59a3d37c51153a300000000000000000000000000000000001f0e176d0987b8ceb7ca0e5ebb491bab0be17282cace8e03d52c986483026180082f86196fe512ac6bac58ec4cd024", - "Name": "matter_fp_to_g1_29", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000104a452343a4098e9bf07380a8e52050259da95f5fc88f31511a08090bda85f0a08d49cef95bd26c7181aa3eb0be1222", - "Expected": "000000000000000000000000000000001655eedb905670d10d2f979962e864d68e9491aea41d073a6119e5bc0ae74216383501a48343d7099b93601f8b67c00c000000000000000000000000000000000842846147959f0f81efc6e8f515a9c59456637740bc15b2d335e0de45890cdd814ca7057c5d3e49e48e5a250c5dad25", - "Name": "matter_fp_to_g1_30", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000012400aaec3d2f4a1a8cf3f28fd396133c3999c074a565c110354472ae29479b9b62ab67128521c2c6ec4869811ba760", - "Expected": "000000000000000000000000000000001098de70e8748daba7bbad52ce344619d3b5374821c1f932a18666ea0a591b24ece05004546cd519ba4d78c9747c57cb0000000000000000000000000000000005f537b6a394458ad51c2e677b2d52974a714bcf6a7474e748ad7f1b28738b6b874b6f49bdf19479bce4ff6c6a47de1a", - "Name": "matter_fp_to_g1_31", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000093e04bfcbd77bc6bafeb77f02d0f794a20b155435ee3af1d667c025e7645d9387abe0ef281386339f461352da93fbe2", - "Expected": "000000000000000000000000000000000a27f7fde0c79210f4b6cf59c97ac773c9766fdab289225c97f6cf42179385cf18f47f14b7e481df7c19418c79dfaaba000000000000000000000000000000000874f21294205152df3a4fab2ced482d325274886d8105b61668074dc8fc90240a715c62b2a2864901ca7a30f12e76a3", - "Name": "matter_fp_to_g1_32", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000481ffec570d4e155ec10e0cc58effe7a5651795d604cfda6cdbf011676772fdce2c25227e7d5a1a26748d15b1668091", - "Expected": "000000000000000000000000000000000a6fd7355965c9514dc7237efd262fb9dfd8025ca2c56165e22675e615095887760ecfed4a2080cd5a2b8041ff26578e0000000000000000000000000000000019b1e02c9258fe62160d92eba8640ffd79b3bffb8ca4d602ca6c059239047c5563049758911d0e6034a25ec5094b1f33", - "Name": "matter_fp_to_g1_33", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013a3c5dd40f7d7fbba7563331917fe19a093d5d25ae7993200c39460e0c46d839e3958b672b4ed195300f398137faa18", - "Expected": "00000000000000000000000000000000013e4cd06b8ba7b5efb70feaa03550bfa45c7c2c79033c92b819257b2ddce28d501cc836a5ec81bf210bed671bfa66f100000000000000000000000000000000165d806d235d41f21e961795ec3da4f1b0334ba6e71ce384445bfda9e5d89e448d00253ec9f8d49825a230b25ffb2848", - "Name": "matter_fp_to_g1_34", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000255bc4d313fbd61a270dce8c851f1fa09e6ac5dff9b9e8dfc8a236a1d44548cb079023ee9b8f0f5756b39e44489c3f1", - "Expected": "00000000000000000000000000000000067c19b7c3dcf8b43d6e83dbda7406f5f88b06cfa0d7d145201164a1f06cb5549545ab28fd1ea8c1d5a662cced00822a00000000000000000000000000000000013aab7ac4ebce4686ad8a05e4eb2f60ebdf03c4f4ca0111bb1cd3dd5fa7558f1cf0dec394d0b616cf557f3811bc2104", - "Name": "matter_fp_to_g1_35", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab7b4dec955de92224b234c2d8bb2e3881806c2d36a9a21036e9412f0a8d3946027cbb65b5dd9c975e01b3f235b883f", - "Expected": "000000000000000000000000000000001673e66a7e558d533be5b855df7c3bdc58f1fb0a3b268b84b4fc25a3a8a211c4c9c8d884fc62f00eccbadbc96dadd7230000000000000000000000000000000016265b691fd43045567ab4fc7e7efa63c8430c8130761b128f0ba7bf381a7cb81bf05aea2526b50ff6e48a87c8ee9cf6", - "Name": "matter_fp_to_g1_36", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ffbb55002d9e926b3d8e7d963ece82c14afaca8b4d8415df8f964a39db606ac99f9e442ff69f7ddbbc4ae563b836192", - "Expected": "000000000000000000000000000000000b36ad42aeacfa47d77f045de527d5bd4fa5fcf25ca3caca99e3e7980e283278e013611d1bc7694bb0b1b86d8589730700000000000000000000000000000000136290ed913b8669f522e16103ff42733a57c1026f966facf4a2d385b0bd52668925d748760975ca5a132d00deddf675", - "Name": "matter_fp_to_g1_37", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000103469c08562f6f72152db58b48811b0098b68af8de00e652bd5a67246459664cc8c54e15705d702d51e3f1d8ff76a77", - "Expected": "00000000000000000000000000000000076fef7b61f4c687246991d6f735d6f89c953476ffc193bacc1f3cf9573ed47bfbf6dcfbb3da1ec1bb764a9cc9b1c26b0000000000000000000000000000000012b6bb88e8acd6cd0ef1929a79bf4d8b10ec3fd575fe460686921fe94aa3a472cbc7aea543ee6284c368f5ef2c33ebc0", - "Name": "matter_fp_to_g1_38", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000059b326dd567fb2f8a6ae87f41fb22b3edc25122138a5f6732edb48ed7fa1949eda6144297f54faf406d873a016a1510", - "Expected": "000000000000000000000000000000000bbc25f7788b0031f1487ef154e877c5ae277a80d56b3a24a39c3ee94eb7df81a47bbff233c1baaf700829919e5254690000000000000000000000000000000019fd9d1237b508d06d7b2ff807c15c3ab36e6eab7e5b9f145bb2c0f2ce8ec96ca3a24932076abfb74eca85744eee4044", - "Name": "matter_fp_to_g1_39", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bd594d2f5e1472f85bfd550df3eb948085781459eb3037fab34186ad9a0204a0767c8fba571af858a054dc231931b80", - "Expected": "0000000000000000000000000000000015eca2e3d36d619601b0f40b01add7a708bbe59d04d5dfbf12d6e473e252505cec0cf7ea1c420000d49221d5e1ba6b91000000000000000000000000000000000cc6045184317aaf2bb8a904755bf48df9e6754e3a864037ebe0218eb3cd1c0a54e50b95f9e6d318799a72fac8d4e262", - "Name": "matter_fp_to_g1_40", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000087b8398406c1e707fe87a16118e2448d6a5f4fd1d6c9d7174c4d8a4314fc7b2c21f04178533480976dd20e28b278ad5", - "Expected": "000000000000000000000000000000000ef0a6307d4a3e92570cad673ca5212780902de416e81d15638ba654951f442e852b53255d7bc4d4e71098924d69f5a600000000000000000000000000000000156abf6f096326c75710300578f0cd946536e16bbf80034c6dbfe454565a501c268135118745989e5274ca2431ca5155", - "Name": "matter_fp_to_g1_41", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000673dface7041c3d7503ce4a50af946d344ad48327b515740b45276403d91bf1ef9deba79c8ffa0126be990b62bf3072", - "Expected": "000000000000000000000000000000000dc94ea6018ffc5838cb7cb00df9625c0c09701bbf19edddb735a3659b385bdd09e9a7d6e869720b727ec59ff3956d9b0000000000000000000000000000000000a20ea6360179bb6608bcbe4879df186916ee71b3ff7a1dd0fd137a0e9dfb135bfda2c66d1cf8d358d69934012a1a1e", - "Name": "matter_fp_to_g1_42", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000adb42b7eb0f6759a04da7b933bbc2b6aedde47da8571d6fa32268c606dbafcbc810844017eb6377493a12d76ca56c03", - "Expected": "000000000000000000000000000000000b4e11f70679333c064d06180df6b54dd1df20ea216415ecb9b704bf4b206141fd841770ab77de4ab2400a076cf9dd04000000000000000000000000000000000ad8c02345e141396401221bb36a2ca21096e89aa76fca4121066da74f2f54b3e2c4049483d9855b7f3159ef448c120c", - "Name": "matter_fp_to_g1_43", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f554e52c4a6c5a94fd09c617f57e8f87af57e73ceaee8997fc62c8ddcb2f875ee805e6594a0fb72738abd3cd4748ddb", - "Expected": "00000000000000000000000000000000136cd8012cebf1639a396f331f73f0da6c114927559cc595f01bad1a18046ae8364858fa262ae04ae3f3b7d13db55a86000000000000000000000000000000000393a915629ccaa9ea06be749f3053dfd07061cfa24bc0aead12622c7d14c085e2994178bfec98b3f8867ac5b4b7a05e", - "Name": "matter_fp_to_g1_44", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001876dd03316ff007a2efb4c5f452d8418edacc2881b20e8340895f6fc768d14fd89bd9db3dcfb53fa98a1e96055fa83e", - "Expected": "0000000000000000000000000000000019008e485a0a9c2f73a79bfe31782a17952edebca308bbc9f90e2ae15525bd501268a1c38c669de0b4e4fcaf1194591b0000000000000000000000000000000009c35254702eb7e3213fcbab62946ba79b7375cc320ee1733d8bf5729d378d1a98fb27d870e27c13626c35cb00a6bcbc", - "Name": "matter_fp_to_g1_45", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e8b2369fc2c584d78d52037b109aecc87dea0eefc2da46948b5535ad19c9abdb31aee66739f4852a2d3c51f2e7f74e9", - "Expected": "000000000000000000000000000000000059a3315f8b6e75c45e32843b4ff2401c41e1f6716a5909894cfdc71a49253d2cb04ec416d204bf0bdda051ace606260000000000000000000000000000000019cee852aa9fe28e1da49dfbfa7901220616f464ba447480c2421fd6d3a5a818c778510a04cb6557d27f7ef9a78f2fb8", - "Name": "matter_fp_to_g1_46", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000168b2d3e4b67390cb8ba5e48a7a823db08edee7d8eff41b88cd653cec1fc0df7a55303d3c91e92a2dc8ebdb327b225fe", - "Expected": "0000000000000000000000000000000001d157c963811725ad533539f17acd16ac3aa22917ecb2198d83a3ba396955f2c9654c02fd42e3d4ee6156cd148e9c270000000000000000000000000000000008fd299ddabfe525075f548a31ffc990a3626aba0369bd0accd0e1968204c8e1085c6b287b370808609178ec8ace2d0a", - "Name": "matter_fp_to_g1_47", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016cf7b1a9ebafbd20c078948fc974bcca9b8069edc1ca5e8f364f8ca2a52e56e1a424ea6bcc4240f46dc7f262760bf48", - "Expected": "000000000000000000000000000000000ee6b51c5eb4dd9c27a61bc2f3480d799cc4fb88414630adb3961508c7067bb186682194af406f811296228c068e6415000000000000000000000000000000000b878c207bc4b61e827ee09a7825fb216a63ddbc4ef0522b8a944bcb673ca368996c31e6513504c5deb5325ef4df0459", - "Name": "matter_fp_to_g1_48", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011a6a67d4501a8d9b3ab985be59ffc41e79c453bb5548299abff3b83ba9ff951025a68fe6a8ad3eef3c02d39fca8f909", - "Expected": "000000000000000000000000000000000658d61bbb2273e8969269dc16e16be93ef82be0668c3a164097a1c0816bb4aa94e5f70ed8d96bd15d9acb602d70f8ee0000000000000000000000000000000008f696d49a5c6f3dc971699a5837f7b3a20e222d9559d899eade367ce684b60153dfb75a9a8b81d7359a93069e2d7d7d", - "Name": "matter_fp_to_g1_49", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010e53fe9fa94ca622cfa370129c1619b2426bd9d50f4b5eb8a3f681479128dbe92adde15477ad8a4463b08f1a02a62d5", - "Expected": "000000000000000000000000000000001313f4cc65865c367cb5c1c96cf30c7e993207e9ef4b2fce9db01181b1192520f01a0428668bb9d33eb857d9435939df0000000000000000000000000000000006b5e883fc24585de3b0a0b83cc1742050e578cb57e89b385e245da0dd2832852c3fa5f31ccf55e6744e9cae6c2f705f", - "Name": "matter_fp_to_g1_50", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014d10a90709789b25369f0376f39b16860aee1ddc3a4340542abff0077a4af8da946cc29fb6afd9930b872ea98749be5", - "Expected": "000000000000000000000000000000000f3fdb57966f9ffd0e20b9ad3bfb4fcade56468aa598cacfe388cd3b647d5966350586daa4493de23703a1debc82e48900000000000000000000000000000000044ff5ce3b9bed637709f9105bec0d86b4f0ea2dd86c9c3b1324637cd4c0fe5a4a965021c51279fc03592414e7968d23", - "Name": "matter_fp_to_g1_51", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000194612afb777e39d0308a290bf823fe706487c3473412d1410dcb2c0016a70706e70e3a009c0bd61e755b1e4c65bcad0", - "Expected": "000000000000000000000000000000001288807e8f49323b39c5d592b97f19cf76f2f642dc4fa704004789d28452ce7a02a45f3f83a8d9875480d380e76df09400000000000000000000000000000000123b15dc7f166cb7c2c106cfd2f7c321a9bea9e3bdd118058c4745b6666a0df2a7c7fea16887a4c85faf860fe48a3787", - "Name": "matter_fp_to_g1_52", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ade016d06179faa8d44a9ee2542058bb81724d6af2954c0c09a897703d364ec25e62a3a917c5cecce5c96a7cfba924a", - "Expected": "000000000000000000000000000000000adadcf2f074679ef3523c10674260b0e40106cca8d94b05f83e2b27d8da8c00dea4215a30275ea5e1a8fd0beb45dfb30000000000000000000000000000000003c2d436e545163abbb18ff7c8e6db1e55c733c75f9594c695c66656690e88995f9f266c2620e99075d3b78805e3ad41", - "Name": "matter_fp_to_g1_53", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005aaeba19cb0baff9a8e46b901f15735a0c1f45116fe1f41c22fbe1aba22c0a7678bd4799db5cd9141f3112877e2c5f8", - "Expected": "0000000000000000000000000000000016cf855c1ea449c47236065ffe53a4c6afdadc08f1eaa26a8f79ea92a7a119b26dea1dfdab4db9b02b3dcad2c077338600000000000000000000000000000000071924c7d4e6aa5234dc921d288dcad3e49b44d2f455d207f3641f4b5b5c809b84c04945df08e785b3d99eda1807611c", - "Name": "matter_fp_to_g1_54", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f54664746a5bc6f64021e2f18d8c175d96b1c8ce895809c0e6fcfbe896b3e8c1ac7f7556b9ef953371bb143bfbdafa", - "Expected": "0000000000000000000000000000000016d80d4689e959233f05a3266628e233b747705bf6d6236771d5e697da03a0daa2dfa88aa5a3a5b97bc4517c467e94510000000000000000000000000000000003bc451286fec0e7a01d29ffae4986a2a3371d4aab875547cac05f759f5a52b8cbf84798b5b3d664a8692b212d4e974d", - "Name": "matter_fp_to_g1_55", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010ca243fcabbdb219c5b30092d9d4595a4b8ad1cbed267229eb79a99aef9c5df03d8f24b71db77a5a76917c2fd960ffe", - "Expected": "0000000000000000000000000000000017297cdec2f6a54cb11c1fdac799f252c72dad52ead6c29de61d64e56ea0e0a1d3a60284029323e35d38a4a25f82fcd60000000000000000000000000000000009beaeaf3ce2c9bfbfe5e04ceaee87460d760c4c16caa7b37767e16b8e97cf08bdb6d30472b3027f66803dec1ce40eee", - "Name": "matter_fp_to_g1_56", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000135d8d92f075c219f8012ce6aebc8e48443b2f33382479a4ca8db0a4f92041d5b6b1e5818b7a3de77a5d30be0e461d13", - "Expected": "0000000000000000000000000000000015a163067e8039be1c365804887dfbb78a7a699f0308c8e26519bf1c86fbe6acffaa26f0e5a2a380d1c704fe84d3bba60000000000000000000000000000000013f94e107625aca9c4346102dd5f09d51e445fd44ea67f171048e8f9965ce3496e759610c078404d41add90a358af482", - "Name": "matter_fp_to_g1_57", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013e042ccfe0cbb7fa3b045a1fa1a86f199ae91721aaed488b96cc4f6de1899402f81842da2ab55c5bfa63f5b19ddce73", - "Expected": "000000000000000000000000000000000b0667e2b7c0fa318c5c0e66425f8cbb8217bec845bfe56997cdb9d0d915131b81e82419a4533eb573ffe103077f35c90000000000000000000000000000000018074b6e0cf144fff9da02a4b5785d21762952d4ed23b1430d6165974f49521b73eaf98973f7967ffb35cee92a2b5269", - "Name": "matter_fp_to_g1_58", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000063cee89d1981f27a4f4d4f23c4d1229fd3333fc8f371ebd85c588e751307ccc75d71d151f7481ecba1ef0cffbfdea5b", - "Expected": "000000000000000000000000000000000b5e953227f4f5e2070482cde7fded231bb0d4649a626d356cab2bfcba6c1588ef38c62cb2c550719091206727715dec00000000000000000000000000000000095f29eab98321d334f22b4db0c30a0604c5c385fd222a71399763f5c815e04226d9d06b460b9e3b44d1ec127d20315d", - "Name": "matter_fp_to_g1_59", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e07265d2762e8e398c83efe1c43452d91b90b7a4271c09ff693c83745a6c01b73561ffe3da9300c8e7e1602dbaab0bc", - "Expected": "0000000000000000000000000000000017946ce626cd11556f85d15b85044fdab0456e24b5e331886be860bf55411a03886738aed9b19d52e91a94ea5cc5f040000000000000000000000000000000000cbe613ecf3c8ca8a5f0617c64647a609ce6e8fd40ae42f69a928f4ba78f7038254689bac2dcde7a464a03d5e26e34ce", - "Name": "matter_fp_to_g1_60", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000375579c16a167fd9f9f61d5177705f157aa0df3451971029a9444432db119fb33b8c07de33fc822eab46ed4ae47cf82", - "Expected": "0000000000000000000000000000000003b425300fc1885f2e932a469a8137bbf9df9560279a5ba87a13e7d4a461489bd8005054f14fad881e06aa46e4333d920000000000000000000000000000000011dcec636ef785d348fcbf9c59a82080b8f2c02d7ab954bc17af1c163a5383a36dd3948ac9110c6afb363ccfde2b6682", - "Name": "matter_fp_to_g1_61", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aaa37576af2101d090139f562edc2a6e7169b0150af831d053a3a87a3a5518889a51871e02deb3ec154ccbe9dda46df", - "Expected": "000000000000000000000000000000000e545a87fb19f7943e18c75f7a173d18ef8129b200222bf6a2ba5a93a92c47ba7accecc4f089c42d6c6bb2425bd1786e0000000000000000000000000000000008c005ef6e5b25e84a8251add6112db49637c2b955af8cd65d029f8e17abfc660794b474689a00b5d2784163a9a0c241", - "Name": "matter_fp_to_g1_62", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000158edaeb58b99d9442d608bc8e6024365e9a81e0aa23bbbd466c9ccc8d29415352a153e1f852666505ef097122592ecb", - "Expected": "0000000000000000000000000000000004cedd2deb72d9168ab5704e21d9a5d85b65ae1510a628515753e85425286d9825dac99922be4a19870700956a65ece9000000000000000000000000000000000f5b0efbb2b327e294246fe862ac01dcedc7e728b938edb9c4a6128740b7d192cf8ad877b869207fb6d1453d85db895a", - "Name": "matter_fp_to_g1_63", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012bfaf34a8111a01d213f9a9fc90846335cda978b3df23de99cb7b764cf5db1a816f66adad1319aa7e25c0ab89e7de74", - "Expected": "00000000000000000000000000000000031841f58b82f7e44aa03f474f18360128aa5699e748e4e2fda1c29d3cf165dc3542b90f09e415e92d73a162af38ad52000000000000000000000000000000000028cbb3ff58cf28f6dc876c2c1cb147bd6af85f3baabe253e9a1dd69687b3a46d4604d2d92d08310ecd7c90723bc7c2", - "Name": "matter_fp_to_g1_64", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000fed118654a128735fd39ffd3b381ad2d71479054b6bccc04dd58fbeed9b255ce2b925e2141a96a12edc3a19188d1f5", - "Expected": "000000000000000000000000000000000e378bf9d1d65cf3a39dc2b3cd2dca8954270006abe048cc29183c5e7c1cf464b21a548679fdf5af8a31e198b69ded53000000000000000000000000000000000865c90b45eba1979e433f71c93c7b3b8e90d3d12a3c2153ab7c420f507bbf91edb593d3beb3899e76d41674b5ca33d6", - "Name": "matter_fp_to_g1_65", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b693fe53cbcd6f8d8c98900be1f9c85966cc644f0a900c70826c6573ee801ce7863a0b170ce0ef168fb1f0ea484b276", - "Expected": "000000000000000000000000000000000844679db6a74e2a1f7c342771616c446c5e240e40e1f994fcba49f8ab22a7fe06b6909f50ea3c49a8fbebaf2b22b0a000000000000000000000000000000000090afa19255f7b71630c466d6b180b2100f8ea6b7ee2085973e409af8027859b61e0c46b639120ef6f3ee1555aed2f94", - "Name": "matter_fp_to_g1_66", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c6bd688fb883f3097f8b6fd6fd0bc5acef9341f21d62a0706fb3625a70459c45a5200ee36a3802d4bb4912030bfcfc7", - "Expected": "0000000000000000000000000000000009ffb2b0054536d714944c6c96f8c1ea902e7109d4917a54ec551d811ab15042f843e158a9e4decab9761cb10e7c3e24000000000000000000000000000000000a6c7a862b951aa9f8c2d1e8ba30af8b7909e9721a06479d186e46ffae3ba09f5f52561c7c4c34d121be1304650cfc6a", - "Name": "matter_fp_to_g1_67", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ba7f82549ebfdc7f4959dc67cebde4720d76d5d4742af730d45d614133f0a7b0ae7b61ba5b914a997d9dde83b77b031", - "Expected": "0000000000000000000000000000000001f9035574fac4ddc3f114a79938105d95ad4947588028b60e2926a8e0fd78710434edb2ab6b761fec43e458e19f0e200000000000000000000000000000000001e86d391172978aadc652b1c5d28dbb26a5357d1deb522bc280a270cc63cc18284e5b05033cd7ce1a6eb962a5b7e268", - "Name": "matter_fp_to_g1_68", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b4acd8c203ebd8e3ce12b10cc791b9a4183440309f24bbd60cb2991712c792ecac64d3f878cbe407fa8ca0d09548acb", - "Expected": "0000000000000000000000000000000002583631492e3e0bf080a5f67334f7a2907c707a678bf63d53badb3ed90305a6eae895f7842a5d44a2110585d412ed860000000000000000000000000000000018719d22fc604567689870d5a5b043ee7234927b1e878dce88be212a8b0981e64f3cf9e03dea94439f504c846c6e42f9", - "Name": "matter_fp_to_g1_69", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000145f6f774d943a1bb753d5d4876b1a88a4021cb6a6607c0efb07eef2f90ba2a90a6e9dc94586de35f6047332553ce7b5", - "Expected": "000000000000000000000000000000000fc1acd8490dee632c51e67356601295291b107087efc2483c1e1a41fedcff244114608c49f6911a4249a59a891264140000000000000000000000000000000019c402eaa9ddd6ff3c72a7d3bbc736cc867b437dbf56c9941ffdb2e0cd60bdb7ccbecef3d62aad22e97c1d96a328e8db", - "Name": "matter_fp_to_g1_70", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b892f1c8d001c8aeddf845c3845c51f2e06c3c77e543e9721d797951b6211a869da97325b569e0de35cf3beda853ac2", - "Expected": "000000000000000000000000000000001785abb82ace5d8024c97b3480fa69a65f5ed48fd3f5416f068690f8f79295d13929d01922c562277f65293abf5d739a000000000000000000000000000000001076dbc521375a1431b24f7d03902491b80b1856cbfd3e759b520927fc559e705801460afaba6991b032d59739c25059", - "Name": "matter_fp_to_g1_71", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001878e791993186ab76f785b2c6b0fe08588b048007c66fc00c695b55bd17b37bdba71f34ddf75ac441a0c2687711b299", - "Expected": "000000000000000000000000000000000bf99b7aa1dd96f57974fd79d5823d1f379bc0e32ce416e6f89a499b82727081aa78529dcc76257d1d699b9979ee23f900000000000000000000000000000000067044e8b0cf455974850859bf76bca780f1908beb06a64a7ee8db2ed54703431c354cc3d7576fde0b45611a2f49f862", - "Name": "matter_fp_to_g1_72", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016598f630f72a0e1f39678e1d0ec6530c4795d7565c5d026fea2389ec0ceb51b434b532466fbb1c92c1c958041283baf", - "Expected": "000000000000000000000000000000000d102c354adf7380053c8b0c11a5c15b046516a87b3e98d1f909bdaff06eebfd9b0c457ec3741833da262f77d411cc500000000000000000000000000000000012cfcd6910ac046ab8c0b448edca5847d0f8cc2a4633fe42edd223ea1b73ec451de8d75cc3d37dfb741ee35259b34449", - "Name": "matter_fp_to_g1_73", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000134725b4d43cb87d2e4d3c43ca98b8df257acfa612ccd61dc0aa1ca749f20bd42c38d933d39f8c3c1a14dd8fec433292", - "Expected": "0000000000000000000000000000000013c11f82052df6294da64b16551e689c439d2d27922bef2a067bc49eb4718a392693570f3b3e58158dc0f5bc3a5b8f73000000000000000000000000000000001517ee24f199913c184181561823d7c3506caa09d93d506c7773f9f615169df444c9f09b518e840735c259ec02488670", - "Name": "matter_fp_to_g1_74", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000070ad61a7f5ff9f0b4e7483f5d56b0f315b5f6545b194565ebcf8f0b8d78519ec113af6d70550888be4d661a8403a036", - "Expected": "000000000000000000000000000000000a546a1f4d65a37d7d60468c18f72152473feeed100119b4518f4c778a7a37a23e8c60ee04cc0b39d5a1eb8c908856870000000000000000000000000000000009c5766d9c88dca87768c0aff4160ff0fdc3aa67dde3eafcca030eb295a6736e95e415f3f5a443f2545c7fbd01f97964", - "Name": "matter_fp_to_g1_75", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000179bc843fecfe713f6e3ccdc8ca0f48759459b675c8b96f5403e1f6da92c2d60449638f564ce179373bce473669965d7", - "Expected": "000000000000000000000000000000000a197b81c0950b1b802128a01e3b620fb2134115a0d1aa2946a82fd22e91f172785d19017fca385863ee1643bcd332b80000000000000000000000000000000011fba5b82b0b2726bbe7a6157ec9103d0b5a480066ce5ab7120294930b81c04cf6d0fb8b979d17c3e262bd1268bdf1aa", - "Name": "matter_fp_to_g1_76", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000082bd89b49aa62c94ecd4244b3077421569c71efccc62aed3d4bd492bdfe57c0d2cced568df5992a196a7b71bcbe5e3e", - "Expected": "000000000000000000000000000000001644dd543ee92960effec90347ffe5f06d6b087f13c6bd73dca93c9e16818d25ffafe3610260cd43ce9909e2ac2e2884000000000000000000000000000000001893436c9dc44500be831076b375d0feccfad2a126110fbcfb77acfb95d6dd6c6615b4b795c007ece6ea0c31915b8e32", - "Name": "matter_fp_to_g1_77", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fb118c86e974734fc434c3bcb783e4a7f9251d9fcfb9f4419529354c8a7a3d9f2215de2d1b9f0927b185c5b4db838b6", - "Expected": "0000000000000000000000000000000001aded655b8ba2739b820b894eefd7e60d11889d7321fdae5ddff5dce11551af24acea3f501044562237fe5df53305df0000000000000000000000000000000010f4f3f415891ba4dfb21307798329aac5baea98cdb44354d4263e1ee6436f613a3accf06802ce2c2782e8a15738bc63", - "Name": "matter_fp_to_g1_78", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004da0ce78f3068bebd0a59bc2e41e7ade737375f07d6c9ce962be022856c569a33e8bd6ae60c4bb1b53b3ffc2dcc2aee", - "Expected": "000000000000000000000000000000000be0b580d0f12faa809d589ba59c5810c18f74b025e6dd4dc49c83b6a39423c5cf82b0dbb1d750e1801e37a5291692fa0000000000000000000000000000000010891c5bfece55dabcd223518167c5b0663f65c001ed051735635b417cbcf2484a057522e1c3417e43c82095b0cbb855", - "Name": "matter_fp_to_g1_79", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001f43b86ec24ad40552dc4874a632b4ff4663eeefe1a8c613a19a798a0ebe321a3d543e2df28277944a941b4586ac770", - "Expected": "00000000000000000000000000000000152454ae7fed9c971cfd72ed054f44124d71542f9ada5a90f1601114289c93fb490a1c5d99b3e8c70fc44fd10322173f0000000000000000000000000000000017bf9499bdc15ae5091daf41812c74535ca31b56520e420edf9e5aa90795ce5db5fa42a06dfcbc7438e954db83f09b75", - "Name": "matter_fp_to_g1_80", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000baaca6bc34feac790807b5eb5fd173c86c12803b76b50be59b2707df765bd10eb467effe34f8dc3e1e79df8a54fde38", - "Expected": "000000000000000000000000000000001633516081b91621b786a09389e89b274c2d9ec616db5028b009ed5c0a1ab47695a0b95c53a45112144613a4af08e6ea0000000000000000000000000000000014b09586f75c939fd62c3d667ab6263367f8961ad4597f1b92d792e8ef79a469137dfba5ec0a6354d5bfe3a84130bc65", - "Name": "matter_fp_to_g1_81", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005e4751707f3ea7bc7a74d80eff27a0d65cea0c3d2e793425e79cdb0c41e6ad0cfcdbb4de604637c41dbaf30a1e816e6", - "Expected": "0000000000000000000000000000000000f0474d596ed86a0d664885f9c981228fdc352755d52dd7e979a85fdb1b6dad106d8bc0a1eac04b510829b7da496686000000000000000000000000000000000a72f532897f912eeea707bfd6d183a73786c7b2e2c80a01f3abe7b959467d6ea63093c16d6465382a7808d5f0edd92f", - "Name": "matter_fp_to_g1_82", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008f69021794d93826f8207b96d49214b46dfb1778603634a9f5194e92481465702a8be1bc49a7bb57527fe6f963ae04d", - "Expected": "00000000000000000000000000000000139ae959f9b0cc2d900e748220c4bfa7dbe22926d8ecb9a10e7d713fa0a6e147fa3463e06b791a5e604c66110b77f7530000000000000000000000000000000013f8d09915f77f4a18854dc2451cf39d7ff502a8184d3b4c59ad3317d62940e903d68836751172ec0b4a796db003b373", - "Name": "matter_fp_to_g1_83", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000116988a869cf552b2440e16569d8b6e30c6b15430855c4d6bbf80683c5497291bac7999c1f8f08f494fcb4a989451c3b", - "Expected": "0000000000000000000000000000000015d065191ab63df2175f821cf62a4b948a6b2389512c7e94e1fa3c99506af624810ee17de2c183ebd69b4dc485ae264b000000000000000000000000000000000fa8cfd94bbfa6d504497866c1e0d9e84717fbf0468a164e3b8ca46348789e2b7f08ac5e8aa2e7205062f3d5083dc5fa", - "Name": "matter_fp_to_g1_84", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e26058d72875fd3d852aa4139f71d35e1edb58242a4939da7986645117d027d20baf85770fc909d537524244da59ce7", - "Expected": "0000000000000000000000000000000012978a0da7162aa1e8b32cb6ec0eebf2c2e62350cab4534358c6bf80299dda9281e16ee40313e7c52c804b2f4de7f1870000000000000000000000000000000009dfbafc8e40d71a789a52d5f8b80e7c8510c58bc0774cfa84211a9c1417d75d5c7b06d7aa9fe052ad9c1f30c922705e", - "Name": "matter_fp_to_g1_85", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000078c6cf89561533810b583a88149586b29da5228ced10a75257b2587904217f63499d8b9ad2d536617247e12f8d1657d", - "Expected": "000000000000000000000000000000000de98869442b759a382d0f6ca45eb60424eb9aee2efdac83086cb6dd374120941343eb314756113e084f943cb60d91470000000000000000000000000000000019dacc8180e6dd09ac4bb97114d2ecadb04bd2aef6e5f0993742c5270267e42d052d436c99ba61f6c0fd1fd2cd51d172", - "Name": "matter_fp_to_g1_86", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005b016ede9d892fbd7aea4e8ed0f1eab70713557311481735a91308fabf76fe71e44a06dc23ea66ac5d831e982f401b1", - "Expected": "00000000000000000000000000000000123313e3cc006c4b95938f5eca903604ac9272c7a0c79cd932407b70635d7ca5de9297496c27406f180d5edebbb54c7e0000000000000000000000000000000002164460e59cc8788c96e235a6faa7fadb7e6ee9f6b0b95292992973ff54a92147dc7ae8e8f217515b6185875bd0bd7d", - "Name": "matter_fp_to_g1_87", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007160f36f0e5c4ccbcc7900c6504cd86fd6fd700bfa79af69841e4a6127eaad467ccc93c66baf7d767c3fdb1f31c527a", - "Expected": "000000000000000000000000000000000393a1b2395447b2e2838c2f49493c185424c4848f888616f16a95552671ff28b5ef223bf34299005f22a8df6efd68290000000000000000000000000000000012b1fe46279922e92d356355752ae0c2f28fc55de39ebfbd317a6c1c507d973f88c6282468571a1efc20c10314ac72f3", - "Name": "matter_fp_to_g1_88", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000043fe62b0b9be76a375f3be0d6ec891d5bf5f2982cb2390125ff8d5db57b6b18c5616c526102e4f615963d601d13f122", - "Expected": "000000000000000000000000000000000739f563b42648cde5befaf44317468982eb9d2fceee7d2efff1755be973cfc2beda829268246d09cd29fc3aa91f0b8a0000000000000000000000000000000014fe0b03ac5e0e03acd7811270d65742a3345bed7a4790d5f40097dd34050d0043104b65fd4691c251f03e67525d41b5", - "Name": "matter_fp_to_g1_89", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b9590b1d0d292d9967d759060a551f4e8e4c1c0066a9a3c0be515085847fa26b77462e3bae9e2621f28e01f897df0be", - "Expected": "00000000000000000000000000000000128e92c9c10fb9b065fe2c2dcfe365e98aa54eaeb3fae987306c7f0a227171ae0b3464d01a54a8d6b144ff60c45088a00000000000000000000000000000000001beaace4e23c9a31e1e9eb8596b3b05b9d72553f44c61627654757080171b05c900fe1b638193a69058e8d66cff1aa6", - "Name": "matter_fp_to_g1_90", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006ee7c459bb4da96e87eb1d39bd7368de5f60104f85b7b4bcdd7761ce08d48babe1bf5e765282779803bfa972d0e668f", - "Expected": "000000000000000000000000000000000a6099ebb3a1101206bbd21149cf22af2371106bd34671c1cbd4f2e19311fd100bcb56a6d9d77bd834f972e55e0fb75e0000000000000000000000000000000001db77a2045e54b0ac4b3d61190684b4eec9c4ea415e5c820992b70d6ee2e086c02892228c4465c8494f939cc0b7b5ee", - "Name": "matter_fp_to_g1_91", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000044612b42a2baa9d3e1d187b2a4e048773b4851bbd7d4025e0f7f61abee703b5a563397da4515c7379397dcde698228a", - "Expected": "000000000000000000000000000000001101cd37b61247a9859bb09ccf9eb416643f86b7109bb45d6827fbf424956c9a16b2a19c5e198551c43aa1934ad8ed0e000000000000000000000000000000000da562fcb2e3cba853de6d245a1ea0cfc3ac120b316a5f4f7072cc35a6634027409ad08c5d591a6688b24cdc4562cddb", - "Name": "matter_fp_to_g1_92", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000014cbff1000bc0f9b394b18e81124dc81f80e291e841dae6e96e0c86a6f618b9f6aa6103e0e7582e5136319a4dac92fb", - "Expected": "000000000000000000000000000000000323c3aa4b20691af32696c449668fb6da6a0c2e8eb176fb8fcd8aeebc9b5a3bffc57b28dd35e374811d420419fb0fd30000000000000000000000000000000019516a092385d8c917b46a742f086c51e2648c7e9a709ebeb5a0f8bc29c9aabf99972aa3a218582f37d91f9758a5ddb2", - "Name": "matter_fp_to_g1_93", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013da827dd718d3736cfcec53f034d34bce253bc91f7cfd6cd2666819bdebbfc43a9363f82bf4b580a7739b5dda9c9436", - "Expected": "000000000000000000000000000000000d0351d8557d21c2dd3b1be77bb01df804ebb9e2d7e80910264ff94861cdc0a4deedc1231c61b7503c5d653e31fe10850000000000000000000000000000000005858ee487860d1ba04cfdcedebda235616c2d271ed50f89d6cf2852ea7e10ac825dacd8b00071684858a12459d1705c", - "Name": "matter_fp_to_g1_94", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010e94039f37d218ad393e88a226dd324a37e8d5352dedf6d84fa2ed2cab2f874ccc5ce94599950f91b8dd6d6c8b84aba", - "Expected": "00000000000000000000000000000000176c50c2fcf1bcbe03a1a1ed2eb120f94ad4fcea34a59607ea595bc2b37cb92f87641191b65d4b5d57f5491ce6576a670000000000000000000000000000000000e177361e09975c98849faf8e24086f75a48df0f257ea47b659cc2a142a57ad1f64416f6dee5cbc4e57f780dadd1cf2", - "Name": "matter_fp_to_g1_95", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000010416da7cfbed2768c77b80957053030d49d535b21a8a3297ab257dee0463c91b87a9e571b86bd874522149d9af0c29", - "Expected": "000000000000000000000000000000000dcce000aae744f8b3b6754af57a36786d887d7f9857654f93edbcb6c4416ccfea5e859acc82860b5f706087e87cdc07000000000000000000000000000000001847c32c839668a38669fdbabb512df15cde2b28ca336b0e158d1fd57f74638d86ba40ff68f0a50cead7021e86c5271d", - "Name": "matter_fp_to_g1_96", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000197ef97f6d02a51b80e6f5629e88a3c60399bcc4a358ab103dac3a55a5877482558abed922585a1ce3228ffb507679b4", - "Expected": "00000000000000000000000000000000062a58846d39dd1fdbd34a7117797f2200d814b2a8eac9479885762565a979e93b5313575bff5ada3211eeed0a3f4ddc000000000000000000000000000000000548a24e7af2b38c4d16d8dfc8fb2d7e7669051e2643c44aee113f20d31f4853cef84e2dec20095c273680cca278331c", - "Name": "matter_fp_to_g1_97", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000025f1ac90f5b0748d57d8f7a928be875c5712801f70af0d057546228c1bf83d3a207884c0d66d0b5dbcaa736bfe0aa1", - "Expected": "00000000000000000000000000000000107f01e4fb6430e34128e3335872cf40df2b498a63e048d46158190cb627e37833d2238dd72681037ce376384736b43e0000000000000000000000000000000000e1812299403efe0f8d111d97a4b7e7b8aa1f4ec58f9935b1367d81a847fb42cf756154448f9172118123679a41a280", - "Name": "matter_fp_to_g1_98", - "Gas": 5500, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f66b472b36717ee0902d685c808bb5f190bbcb2c51d067f1cbec64669f10199a5868d7181dcec0498fcc71f5acaf79", - "Expected": "00000000000000000000000000000000188dc9e5ddf48977f33aeb6e505518269bf67fb624fa86b79741d842e75a6fa1be0911c2caa9e55571b6e55a3c0c0b9e00000000000000000000000000000000193e8b7c7e78daf104a59d7b39401a65355fa874bd34e91688580941e99a863367efc68fe871e38e07423090e93919c9", - "Name": "matter_fp_to_g1_99", - "Gas": 5500, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsMapG2.json b/builder/core/vm/testdata/precompiles/blsMapG2.json deleted file mode 100644 index f30eef656..000000000 --- a/builder/core/vm/testdata/precompiles/blsMapG2.json +++ /dev/null @@ -1,702 +0,0 @@ -[ - { - "Input": "0000000000000000000000000000000014406e5bfb9209256a3820879a29ac2f62d6aca82324bf3ae2aa7d3c54792043bd8c791fccdb080c1a52dc68b8b69350000000000000000000000000000000000e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641", - "Expected": "000000000000000000000000000000000d029393d3a13ff5b26fe52bd8953768946c5510f9441f1136f1e938957882db6adbd7504177ee49281ecccba596f2bf000000000000000000000000000000001993f668fb1ae603aefbb1323000033fcb3b65d8ed3bf09c84c61e27704b745f540299a1872cd697ae45a5afd780f1d600000000000000000000000000000000079cb41060ef7a128d286c9ef8638689a49ca19da8672ea5c47b6ba6dbde193ee835d3b87a76a689966037c07159c10d0000000000000000000000000000000017c688ae9a8b59a7069c27f2d58dd2196cb414f4fb89da8510518a1142ab19d158badd1c3bad03408fafb1669903cd6c", - "Name": "matter_fp2_to_g2_0", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ba1b6d79150bdc368a14157ebfe8b5f691cf657a6bbe30e79b6654691136577d2ef1b36bfb232e3336e7e4c9352a8ed000000000000000000000000000000000f12847f7787f439575031bcdb1f03cfb79f942f3a9709306e4bd5afc73d3f78fd1c1fef913f503c8cbab58453fb7df2", - "Expected": "000000000000000000000000000000000a2bca68ca23f3f03c678140d87465b5b336dbd50926d1219fcc0def162280765fe1093c117d52483d3d8cdc7ab76529000000000000000000000000000000000fe83e3a958d6038569da6132bfa19f0e3dae3bee0d8a60e7cc33e4d7084a9e8c32fe31ec6e617277e2e450699eba1f80000000000000000000000000000000005602683f0ef231cc0b7c8c695765d7933f4efa7503ed9f2aa3c774284eabcdd32fd287b6a3539c9749f2e15b58f5cd50000000000000000000000000000000000b4f17de0db6e9d081723b613b23864c1eeae91b7cbda40ecd24823022aee7fc4068adc41947b97e17009fad9d0d4de", - "Name": "matter_fp2_to_g2_1", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001632336631a3c666159b6e5e1fb62ffa21488e571cffb7bc3d75d55a837f242e789a75f0f583ce2b3a969c64c2b46de200000000000000000000000000000000184f1db9ac0fdd6b5ac0307e203d0b4237a50554eb7af37bb1894d9769609c96c8437e9d6d3679ebd5f979eb04035799", - "Expected": "00000000000000000000000000000000184af3f8a359dd35dddd3dfcc6f5b55ed327907ed573378289209569244e3c9c02bdf278eb567186f8b64de380c115360000000000000000000000000000000012f5ba8e520c4730ac1fb75dabbfdc0181855e5ba2968a8c0ba36a47ab86ac45d19aa3d55f15a601e120be1f75eefe240000000000000000000000000000000004e313db704b103c2c1e3a58f8e95a470e7199081eb086e9524583131714c4a3db551fd51a3f2314a19a658e7b1765380000000000000000000000000000000004040eab7416a1703b0d103120506f1de2b26b0f48c7a0ea63dca4d9ad1c478ae03b5d7bfd51f4cd6f8cea26212c4edf", - "Name": "matter_fp2_to_g2_2", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000732f171d8f6e283dd40a0324dae42ef0209c4caa0bd8ce2b12b206b6a9704f2c6015c918c79f0625fa791051b05c55c000000000000000000000000000000001139e8d932fc0ab10d6d4f6874c757c545b15be27cdb88056ed7c690aa6d924226d83e66b3e2484b2fc3dcd14418ee60", - "Expected": "0000000000000000000000000000000017fc341e495bf4ef5da4c159a28320aca97ca28fe3a0441242cf506b0f89bb52f5b5d8c6e038d229ffe67d00151912f00000000000000000000000000000000007666300b7be3d904ae3d19019f7be5cf5ba6161b969c1a78aff639a24387d8fdcc4d0e3cd81ba6f063ebf2d859370f20000000000000000000000000000000007cc705dbfb5c0418beb1cfbd864fa0631bd60eccfdb16b5d55b6ef3558e2ec87dac3b45294dcf04a064d6d1eba5a6eb00000000000000000000000000000000052cb9c982e6b05c1d2ab4eed1d8082f96426b55615ebc6a53bdc320ccad0aad044395ed641b3176b554f19e62d46b73", - "Name": "matter_fp2_to_g2_3", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019a9630cce5181fd0ad80677ed5ad8cd8bce3f284cd529175902b78ad4915f0df56f0d8b37c87c9ddb23d0342005f1570000000000000000000000000000000002cdd00b7662569c9f74553a7d0585312a776c8638e54ad016f8d9d25df98651789470b12ce2626fb3ad1373744387ac", - "Expected": "0000000000000000000000000000000015ad9155037e03898cb3b706f7105e39d413ff3a5abb65812b8d21d003cab8fbb607d3938ccd6a774bc8debfa30f42760000000000000000000000000000000019d6382bb2d78180a8998a0536d67412d00ec0ef65f4cbce01340b8d6e781c0ff790296f8cada28966b147c69e02f366000000000000000000000000000000001290c2c205b748069d0875a89ca74a3b05ad8218ed46a1570696932302983c090d96e17e0b828a666fdfc3b72cd348bc000000000000000000000000000000000114f2f7ffaa9f90b547e86c863a5d3585819a78b095848dfa39576a10874a905488687b73e613f3d426510f5d1d1ce1", - "Name": "matter_fp2_to_g2_4", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e63c4d12a38837354bbcdf4f844e5dfe727ebe292016748007d162e74c1f849787767f7e77fc57a42783fe0b06c24c80000000000000000000000000000000008d879e4891a891f2e7d27eb95aef70d5b785b796620ec43dfbb6ae550b4effb9f24210dc20f401d54420445e21cfdd3", - "Expected": "0000000000000000000000000000000012084a53cde353a46af17cd2fb02c477e47b874d8ff58025b5015837759032ff98013dc5bf01253bb964f035183c9071000000000000000000000000000000001659272ab7e3a070a5c7b25a5d3402f7371ed67e58cac8438df41c39c1acd95ac5886b030384bf537d7c4bb8ddb2c538000000000000000000000000000000000852ddcc37a09a0a8f62dfbd1ba5064c1f6afacc9a279a4d998bed643eec5a0d96d6bad95701a04f52c83e8f87f48d5d00000000000000000000000000000000097a399370875398028d42bde8cf4e9641730af7a2971e2f59c95938120603a239c65030ded4323c955f7fd24bebf31b", - "Name": "matter_fp2_to_g2_5", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000028d6de947a3958af5b53578b0ceacc7ef89d36526d8f3b6fbe787af69fed2c85cad3001643b81c575a741c4566e617e00000000000000000000000000000000182b56202f0494bd8baf5c03969288a1288b8ed8e6c7f49ec9f7493ee3369eeb42fa8f5fb7b243fb2bcee6be244f02be", - "Expected": "0000000000000000000000000000000006f8191123f1e8f6a05e4e663fa763c8a0ade5de3c7cd38ec1c82e1c85f123ab51fffcebd677afec8e9adecd8d11263d0000000000000000000000000000000004fcd825bc55d044eb70e0bdd5ea2ac58ec1487e903b431c57a640c756265a382581b8450fb15dc649cf22a8539088220000000000000000000000000000000015259f83d76490bb868bb88c2a2c3e07a326bd3e97fc2f552adf85722a360a443d720c328076e35224328e09494746e0000000000000000000000000000000000f76b0b960a1343b4267f5aff44901fd6796a778b1a87666b95b773edd0e7ffb6656d4f0cc3b9b38bc6c0ed20cfce153", - "Name": "matter_fp2_to_g2_6", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016adb5935f32bafcccb81cf4d177dd8826013d85e11a4aad66e3aa596e1183aeb9d68eb8cf5b716a8a9445ea81b40d7a0000000000000000000000000000000018bee24b0c97af8aec210f15bbb6acbb76168dabe16e669d5558d8d32f00fdf5146471922fa98a28f238974d327996a3", - "Expected": "0000000000000000000000000000000018bf5f93dbc2c37479b819f8edccd687c4d3c4dd04f8c73762fd89d0c003674e3b2ed749d23e775f925279b3112689f80000000000000000000000000000000008a033b197aa8ea2213dbd7ed478d98c25dc6e9f91b9924f3c14124da26a67bb196926e02da89b746f2a67b14ad226070000000000000000000000000000000006f7824bdc9c53212609512858278f79d9b094165ff178e3da8776e24311bebbd9deb29f366d4c7693a15c34df118403000000000000000000000000000000000edde25fc24b9ec58b3c317aa3ae48dd5fecdf6397ed9636ea042722d264db0b1a89a15a1e16e892755730ef52796527", - "Name": "matter_fp2_to_g2_7", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000114285411713eafd395ee43bf1728f52d17ac512b9d0cddd38c904a9a3a1b30283a3918cd2cc3da6a7d6b4ff923cbb6e0000000000000000000000000000000018a067f91f94b2904c5bb6900f427ec4e93374b5079c84707feabeabde20b5e49801f1f3c7504dd27da94d5e754df4ad", - "Expected": "0000000000000000000000000000000002d28025f4b798083aec3ca9a91a051ce27a374b115c944932026b4fe0dcf68b335d5e47212f800c241c2d42fd219635000000000000000000000000000000001742fb6ef8e9a5a7572b0d3fa4ae8ae56c9c6f4daa20d0b88212c40511c6f6b5ee98314a2d1cbe4bbbec907495a1ade8000000000000000000000000000000000d700a511a58c1b8f11153669cb21d88512dfdacbabe38e402431b4f7ba374b5f9a88614da2d56799d39324e9d19e27a000000000000000000000000000000000c6068bc7a43d614b8f1132b13e04f66d2fb5ac0c5bc8501b754a0bcf4f382db92b0994c4999e104c9d1111ef91d5edc", - "Name": "matter_fp2_to_g2_8", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000dafa9fa843879038fd1566c319c24119989090c5fd34f6514e57f633d3709f0aa9954dfb289843a6990588e337b63e6000000000000000000000000000000001742a98dd7d3671c2c64aa71023a0040e936fd726c062d520626113bed471e53ff3e85737e5abf9ee8821bae53135f20", - "Expected": "000000000000000000000000000000001350c68434a9b02392e60540a3985bae8daf9a170b30336ac73afae6f892c7ae8f5f1cadfb2780d6e5961ebf91cd69ee0000000000000000000000000000000000c20bd286fc1886b9b28dfa40d1a27395cf76a8b73946849ea0a7b5e12530de13c16acef8fe2a2c247ea65ca023eed70000000000000000000000000000000002d8ffd0235fb60fa573662034d46260e0c96396537b2a9d486dd03bdd13c5a1efd2d3cb9849ed11c4376b665f378226000000000000000000000000000000000d90ca1b73a6a9566832f9f19d8530a3b12f22bef853fc44088559b923ca108cebf4291e0d7de8f25c7429d455f5ae46", - "Name": "matter_fp2_to_g2_9", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019cda532e5d94f3b193b3f286a038637a736c2b87b804efd4779359db5bd95320e06d6d28da3c229ae48ffc02303fab10000000000000000000000000000000018df89e4a545bfb825bcce2f4c25f2416a72e32633b3dead5205c8b7d69c78f119d0e940e5bde9ae1cf91574e5d6c175", - "Expected": "0000000000000000000000000000000013f223602e8d12c3bb51cd393f6f59beb5c55fe80c3fc8fb0bc90eca533d9b7981563a30ebd727ab6cf0111fa2d3099d000000000000000000000000000000000962b0585c681894cb701f17ec06c0c240899db574c02d82d85ed4dabd4b8654c29b84c71d2921986fc2abc542a3ed9f0000000000000000000000000000000000f0e79245e645a6e3fb88b9103ede3e6ecdd7e45d61b5755d7a8d100d80719746af58bb23d3068cee7389b2acf17f8b0000000000000000000000000000000017fa0aac84c58283f34b9bf713cde98c175b38e92503c08205350822d778f3dd5bed8051e185c495831a628aa89335c7", - "Name": "matter_fp2_to_g2_10", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008ad60829ff001404da40923806e496640a90c5c258a41ef5912f8a1a20eab84ce43b2b5aa4aa7dc4d8b281591d235020000000000000000000000000000000000f13dfef4b3b83aa7f9525eae9913e10502e77c03c55a7aa2de083dc5102c098b6f8e36cb5247b827e30fbcded9e2d3", - "Expected": "000000000000000000000000000000001062c97c214b86518660c5e1c33a4e48923ae89ab7d8bc5c798e631de16fc1f104aa957d3e7915aee8551e24aaafc8e6000000000000000000000000000000000e42b785f17f25b87a0dc558a8d57b19d8f41767c3b4fd70c147e95443aff2d9a743003da41d578a2b56d7dc748cf59500000000000000000000000000000000111fd38cd2f5f681bb37f6239a5eea820ce3f01023c685f8e7e244fe9aa9dcbd18f0e50705faa5d8d66b28af9f371c630000000000000000000000000000000004726d3e452f6fcb180ce1d50bbee3a23f7949b635a058f12de1cf5abda19c042168feea53211dbed0bfca489a020930", - "Name": "matter_fp2_to_g2_11", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010468e5421a72ec85b63f7f3070a949223105763868111424fd151c8365eb0307dbc9cbc92e5dfb296d06ddfb58d99000000000000000000000000000000000008149ce856d489050ea834452bc66f7f3478c2056969354dca8652f3d0a349e40fae0c4c57ff0f5e022aa93c61f8c844", - "Expected": "000000000000000000000000000000001211bb8d3bf65b60efc7237ffecddb4e7e2f0dd36e2a704dfc9f4972897addff1a57182f8e0a0ac08c9af2c98eaa4c560000000000000000000000000000000007e9877280aad45a3b1453b6771ab509e4f53937cc6da73d3add50aff94869b27f49218fb479fe19a6176b9aadd36e35000000000000000000000000000000000ff915801695a281f6642751be77155a813847ae0237d77d2edf836aebac02b659b98d49842d4d10e82d9d146e63a3da000000000000000000000000000000000fae1c8c01a2dd94f17c660353d158ff6f3eed4e6375f1e414ade9d6fd040a48e3ff0d558c882e92e74bd6ef4ab06168", - "Name": "matter_fp2_to_g2_12", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006295de7bfec61f06a56fe09afbb74be968329e88ba2e87afffe9ea9bf646ff5b4a03d6088e87644958ced95eceeea08000000000000000000000000000000001443e61dbf14b6c6ed99e1917ecfbe5a4a23ab9bdd3bb089fbba76d795d715d9d2e3c7d8db0b7a9434ad691b68bad3b2", - "Expected": "000000000000000000000000000000000dd00d9f31cb5148048125668286c1790cb7294e740df978ac0bdaa6e1c4ba139a04f5770b194c9bcfb123d9b40b6acb00000000000000000000000000000000085d5f4cb831720fa13cef25464a1ba7af33abcc4079d2c5736a219ad9649ebb5dbb8687a2d3952390866587d7088f72000000000000000000000000000000000de377d773e40e1c76e218b969297d15f7819c525ce39aee5114e8405bd7361116682cf9d673574d415a7016b23b567d0000000000000000000000000000000018db26c2097f72b8788ef5aad2d7aa400627e224924afea1ac7c7a6b5cff4a55255e218572614519a536eaaf0f65533c", - "Name": "matter_fp2_to_g2_13", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b14b12ecaa94f9656be54772be9b22a2495d4ff873b0bb971c27ab1d8b940c84cabcf921f6f75e93942c38cddeb87500000000000000000000000000000000019eca0daafbfdcd3b56be863dceb21e624b22c0d376fb92ba606456ce3825981713b88e40b7fd801e915f97d5c29ba75", - "Expected": "000000000000000000000000000000001853b4c4e6fcdbed29c5d3aa4a9f6d447adc512f66a32fdef06c6ad316c42eb3ca47ffe6f21318ad610d0a68673d7bc300000000000000000000000000000000123d15c37fa8b1a95229e28500c9a767e6286b780138dcff2714bf1f8242f39bebb7d86e2811551914719ca90fb5615f000000000000000000000000000000000537498c2ec64b2ba58aa0a858b69990cac544d5cac29abdf6a42ae9c04061f83580b79c2a6104ebc55939d9a2bc5ae2000000000000000000000000000000000b348c19aad3b67c690512f372d995555ee38bffcdaf33bb827160d6929d2ce598523880f6136f11e1d6482a654cb016", - "Name": "matter_fp2_to_g2_14", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000104a452343a4098e9bf07380a8e52050259da95f5fc88f31511a08090bda85f0a08d49cef95bd26c7181aa3eb0be122200000000000000000000000000000000012400aaec3d2f4a1a8cf3f28fd396133c3999c074a565c110354472ae29479b9b62ab67128521c2c6ec4869811ba760", - "Expected": "000000000000000000000000000000000994e7b6ccafc996f672c42ab491105ffe1482e65aeb456de2213b531889773ad4d5e6ea1687d6a1f13e74878766f11e000000000000000000000000000000000b89030486a1d622c97970ee7da6189ac341b9cafbb4081463f579ab8b4b049c6e6c8b63157455770a79108424a14f24000000000000000000000000000000000ded43800a991f8c37282d803a39941d3bfbfbdc56dbf7500ef3d16750b27dcb1ad93f89714395fd3dffe318c1771375000000000000000000000000000000001994144b032e1f8c4d688754eef82cdba0018ac47030fcb77e8fd920e0b0336255d2cc8376c03e1074f91269cd2519d1", - "Name": "matter_fp2_to_g2_15", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000093e04bfcbd77bc6bafeb77f02d0f794a20b155435ee3af1d667c025e7645d9387abe0ef281386339f461352da93fbe2000000000000000000000000000000000481ffec570d4e155ec10e0cc58effe7a5651795d604cfda6cdbf011676772fdce2c25227e7d5a1a26748d15b1668091", - "Expected": "00000000000000000000000000000000195d99406baadc7d8740962cbbf4bc1f22b08eafb52f3cb3c588b6cb3cd89d16cb7b8d388563289f5b5ea466128525c80000000000000000000000000000000004809f70463633595dd763d658354df4f9b409911e1a0328fdaf486d76ffb410d7c6cfcc2d48fd6757d5c2a4834f81fd000000000000000000000000000000000654f8475562098a2cb27ce224674a383283cde35173e1c16b141998b641ac9ee663d766f045451a7f6d600973f0ec520000000000000000000000000000000013bac451a44982c7b1aaac7522dab598cb79b9a3dab77f4d5a4c1c97c154451499979af1f86ced8ce2099bccd400420d", - "Name": "matter_fp2_to_g2_16", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013a3c5dd40f7d7fbba7563331917fe19a093d5d25ae7993200c39460e0c46d839e3958b672b4ed195300f398137faa18000000000000000000000000000000000255bc4d313fbd61a270dce8c851f1fa09e6ac5dff9b9e8dfc8a236a1d44548cb079023ee9b8f0f5756b39e44489c3f1", - "Expected": "0000000000000000000000000000000016ea88d0bce32981f489438df1bc14e7ade7a45d449ee1ac1a041c1204460cf53ae5c0e111914d8af9e6b3b7fa394484000000000000000000000000000000000db571ca6a55bc8285421553a373048f7877ecb9683d52acf07d48e1026795993e4e7177490921bc6fe1e63d69c2de3c0000000000000000000000000000000011602919de1df6cc0dd36a59c84ebb8e209056534e336f5074c9ae5323f8a03b123dc6354cf85301d838b16518ab64390000000000000000000000000000000004407d30fbd632fd493055bd4d8cbed337767a2ac534411a3eabec570ba41d2ad28ef37512a7da3611ad60b6536b3f07", - "Name": "matter_fp2_to_g2_17", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab7b4dec955de92224b234c2d8bb2e3881806c2d36a9a21036e9412f0a8d3946027cbb65b5dd9c975e01b3f235b883f000000000000000000000000000000000ffbb55002d9e926b3d8e7d963ece82c14afaca8b4d8415df8f964a39db606ac99f9e442ff69f7ddbbc4ae563b836192", - "Expected": "000000000000000000000000000000000c1e7b188697aa9a053f14e2d907f2c61a59e0b0c72f9cce30faf81dc714a50113500ca9bc3af6657a5d214f52c90616000000000000000000000000000000001544c35d712eaf79d8dd5a22fbab72f8a6843728898412a7f305b205f8a50e03c6c462b87b3ac165e9e6428e0a44a74a00000000000000000000000000000000029ebafd90a1a887669fd0ace762a66bca2bf0a216333b0ac97dedb6bff3dda2bca1e3d0ed5fa9081c2887fe6a8e24cf000000000000000000000000000000000e1a01ca93ed268e0291a937483f7f8e252c91f9bd8bde55271b0c97fcbbb9219009514217dd8bd7e0267f44e9927a93", - "Name": "matter_fp2_to_g2_18", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000103469c08562f6f72152db58b48811b0098b68af8de00e652bd5a67246459664cc8c54e15705d702d51e3f1d8ff76a7700000000000000000000000000000000059b326dd567fb2f8a6ae87f41fb22b3edc25122138a5f6732edb48ed7fa1949eda6144297f54faf406d873a016a1510", - "Expected": "0000000000000000000000000000000004e8ad9838e7e269cddf0ae5c8f0f57e7467e0b6f2b9e37e7c4bcae965e9582dc46c9c50aa01f5dc761bf2f1ad311eec0000000000000000000000000000000011b1438ccc668900914578c3ec6e1334d0823861c892608817498fe2e538deec73e0034a6e8ba9790f63fdd95af3714a0000000000000000000000000000000005b4c88196425d3ecd22bfc0cb1a95488493f85bb74f50315f0ffcdd57ad2de23c137cd6d2f6f6dca8af2e3f7bb0539c0000000000000000000000000000000017066344a0f345ecf6a2ba66c37ccbce26a3f551524f74636d4c4812bf5adfabffb0645b898b10c332e94e5f2ae2d1c2", - "Name": "matter_fp2_to_g2_19", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bd594d2f5e1472f85bfd550df3eb948085781459eb3037fab34186ad9a0204a0767c8fba571af858a054dc231931b8000000000000000000000000000000000087b8398406c1e707fe87a16118e2448d6a5f4fd1d6c9d7174c4d8a4314fc7b2c21f04178533480976dd20e28b278ad5", - "Expected": "0000000000000000000000000000000010d393bf893d589c578df58f4d0098ad3cd10d3a1d0f112f51b132a369e68c0284a6b70a5673383ae24a27a9043b16cf0000000000000000000000000000000003402afb77b187b45906d9cce348976ed88c758d75b9962a53352a6c3ee37751a9928097c0d68c6f8a315def4ca875200000000000000000000000000000000019b98631e53a3ffda3fb9165ef7236dad5c0c8d57c3315617cbd3ce77430bd89b9e1d88a019042cae0075594514a5e67000000000000000000000000000000001783bf1c9b0ec44c9191dab01ef5bda0cb2f533dbcd3aeac2b7c6720dbc8e3f770a215ec8ea2035129711ce4b448ba87", - "Name": "matter_fp2_to_g2_20", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000673dface7041c3d7503ce4a50af946d344ad48327b515740b45276403d91bf1ef9deba79c8ffa0126be990b62bf3072000000000000000000000000000000000adb42b7eb0f6759a04da7b933bbc2b6aedde47da8571d6fa32268c606dbafcbc810844017eb6377493a12d76ca56c03", - "Expected": "00000000000000000000000000000000086ac901098212acd091d9c4d42a1318c3b343480f1130d6e52128d61df9e19fb61ef1ff35de0ef60062cd99202910ff0000000000000000000000000000000019109b7292f1a420f09a56dce9694cb4944808a2ce9f1964cbb6ffd14a710c35abe81300090ffcd9e95f33e0de9f879a0000000000000000000000000000000012660c4e114a215390c6f6eabc4bd6e3d062ee28d0c87e24351c7d43195253cb7b5bcfed2b4abb2fdeb3ac04ee228997000000000000000000000000000000000e56d35a7e40a86ffd2088c81488265ecc4468d6cf02d563c91611cdf8b4333cf66ef50b993fe651b1792d2b242cff94", - "Name": "matter_fp2_to_g2_21", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f554e52c4a6c5a94fd09c617f57e8f87af57e73ceaee8997fc62c8ddcb2f875ee805e6594a0fb72738abd3cd4748ddb000000000000000000000000000000001876dd03316ff007a2efb4c5f452d8418edacc2881b20e8340895f6fc768d14fd89bd9db3dcfb53fa98a1e96055fa83e", - "Expected": "00000000000000000000000000000000071d3e796fb15d63c2d5cf68f59f11792b0b580b85c8839a02fad96664f14735ede2edfd5ba5b64045b366904f54ab600000000000000000000000000000000013fd1ea38d32772458622731b9e2d9d749f2b747443f7e47ef5e041531b56f86d1775d42a548b2bb201228f49ec9f46800000000000000000000000000000000099c2bd996c8c5ee37de971e8b75a0bdd4f69299778ee3d216973c9dbba97c7a93e40b209d390024bc4b5e82560a1a83000000000000000000000000000000000c4922ed9af845467440b78efa3a53ba904f29adf66e8ac437c8bb6624b5e5ba0772a5639b45fe167b1fb9283747c50f", - "Name": "matter_fp2_to_g2_22", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e8b2369fc2c584d78d52037b109aecc87dea0eefc2da46948b5535ad19c9abdb31aee66739f4852a2d3c51f2e7f74e900000000000000000000000000000000168b2d3e4b67390cb8ba5e48a7a823db08edee7d8eff41b88cd653cec1fc0df7a55303d3c91e92a2dc8ebdb327b225fe", - "Expected": "000000000000000000000000000000000e413d72fdc3db6fc79ef26ae8b37fe5c4356a80b3598513b5173b3406ffb54708b8794dae158060a1accbe956a39ff30000000000000000000000000000000019ba9dfa74fd241a55a3b47c9f37c6ebd1e8b51f46197881abb64b7f57c0e2d8f18edee35bb9da03702c0dc5cc8749f700000000000000000000000000000000183525156fbc80cc67d6cd15fd2ddf7fb0528656ec1d31b4c275ef101dbb635424abbff1154a3ee04346ac53148fb1f70000000000000000000000000000000011da0dcd666d01180902d8a7fd7d2fbb39f9c7587540451045956108a8579d7c116385a81627dad9d4cb8cfe68927b6d", - "Name": "matter_fp2_to_g2_23", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000016cf7b1a9ebafbd20c078948fc974bcca9b8069edc1ca5e8f364f8ca2a52e56e1a424ea6bcc4240f46dc7f262760bf480000000000000000000000000000000011a6a67d4501a8d9b3ab985be59ffc41e79c453bb5548299abff3b83ba9ff951025a68fe6a8ad3eef3c02d39fca8f909", - "Expected": "000000000000000000000000000000001932acb1fd0708edf13c293007a035991bdfbfe0089b61c261258e8c5c10d82a5318b2af221b372f0f3f43c391421582000000000000000000000000000000000973650743f0ec8e2acca33f2ef230ee7a05635d14099cdce913ad8678458ec0dde5c5a941097af2ee0c8ffb937d09fd000000000000000000000000000000000bdaf319044101ee9aa27b3accd36a5ecaf8b80deda4548377ddeb97283537be3f7199ad3c190ed23cdb44abb8786a080000000000000000000000000000000006c448827e3fe4f274bfa55a66bc76c5b01e29ac6a8dbebd801855ba4e93bcbd03292ccf804f07f21481260c135b827b", - "Name": "matter_fp2_to_g2_24", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010e53fe9fa94ca622cfa370129c1619b2426bd9d50f4b5eb8a3f681479128dbe92adde15477ad8a4463b08f1a02a62d50000000000000000000000000000000014d10a90709789b25369f0376f39b16860aee1ddc3a4340542abff0077a4af8da946cc29fb6afd9930b872ea98749be5", - "Expected": "0000000000000000000000000000000004aee050b0ea07118d76f835218b77b39854f5ababc4e2a29d7c8cc7c18a69c30bb22437049a051d049c8a84f7868ad40000000000000000000000000000000003b1b809d5046054924c3814d26fd5fbdc59e03e5505813bab73bc212b0f5bc0d3fc34478311c5e1ac70fd16a01c52800000000000000000000000000000000002249a026af0b49f4659eca2c23dc790fb36a7b2996188828a17d5852003f1420f11699062932835cfe6543d454521e30000000000000000000000000000000008217aea2221f8748cd81cd37777605a95a63aba36a6ddad72c1e1ac57b24d79ff9d9c4ed71a6e3ac8a378129d5475ad", - "Name": "matter_fp2_to_g2_25", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000194612afb777e39d0308a290bf823fe706487c3473412d1410dcb2c0016a70706e70e3a009c0bd61e755b1e4c65bcad0000000000000000000000000000000000ade016d06179faa8d44a9ee2542058bb81724d6af2954c0c09a897703d364ec25e62a3a917c5cecce5c96a7cfba924a", - "Expected": "000000000000000000000000000000001274f676bcc05e54fa4b0cce234870ba97a0b1626543d6a9f09afebd5a752769000df404e4d434ebfd561f8335f36d0d0000000000000000000000000000000002877c9438fa319dd1a00f381834e8f3d3cdebf4e1f7690cb82559a2e978bedfd2455be020d0353aa56d435c0174b5b10000000000000000000000000000000009487cc9c7a09be901673cb1bd9a51f45e5d2ed30c90cbdd3e2b294c8f866f68da55533b78152e9ef6de30c345fde5b7000000000000000000000000000000000a3a8d4aabdb260203898655745cb695e6dc90c6e7bf0248784f8aa2340390fd5d8f1c6a98eb1990eb97c2a7f103e3fe", - "Name": "matter_fp2_to_g2_26", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005aaeba19cb0baff9a8e46b901f15735a0c1f45116fe1f41c22fbe1aba22c0a7678bd4799db5cd9141f3112877e2c5f80000000000000000000000000000000003f54664746a5bc6f64021e2f18d8c175d96b1c8ce895809c0e6fcfbe896b3e8c1ac7f7556b9ef953371bb143bfbdafa", - "Expected": "000000000000000000000000000000000ef415dfc1e47f39e9632ed21c9c2bfcc1959299710dcd7935a757e3756a42c8f6c627c720fd62f9c486a8e88a64c76d00000000000000000000000000000000088079108fe7d9ac93590c045be0d41396f3204d83793c4e862c5360ddb3268a63f704a9d14323943fc85874cdadaff1000000000000000000000000000000000cce908e8dbb7ec35820f2db5ae1174e0f675b21ae416fc89a7f242df3ee98764022744842999f65132229156d2627370000000000000000000000000000000011e0e2f8513d0a71b48599139a9a29c8eca090c5b02292baba58e07b1d3898fe158cdeb3bbe8edb4a805e695e896984a", - "Name": "matter_fp2_to_g2_27", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010ca243fcabbdb219c5b30092d9d4595a4b8ad1cbed267229eb79a99aef9c5df03d8f24b71db77a5a76917c2fd960ffe00000000000000000000000000000000135d8d92f075c219f8012ce6aebc8e48443b2f33382479a4ca8db0a4f92041d5b6b1e5818b7a3de77a5d30be0e461d13", - "Expected": "0000000000000000000000000000000007c6f133647745c312695439f1d8c251e941bad6e988cfe324ec7c959a9e0fb50618984429ff1841d4286922a26873170000000000000000000000000000000008edb220f77ed17fa1f4757a42ec66ad808c1acc25c4b9311be4c09703d547f648d9dd7c8109ffa89d01a35c69ec2685000000000000000000000000000000001595cc05b04f557ed569b19d64c09f4d82e6617437571fddd72a672d07ad94bfbaaed906b3a7e3db519159ec8d0a8c4400000000000000000000000000000000041157d4f40bfcef680af0143ccdd0c4bdd25e598a470dae844d887c398bc498edad715fd7383421fc78758cc9b00326", - "Name": "matter_fp2_to_g2_28", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013e042ccfe0cbb7fa3b045a1fa1a86f199ae91721aaed488b96cc4f6de1899402f81842da2ab55c5bfa63f5b19ddce7300000000000000000000000000000000063cee89d1981f27a4f4d4f23c4d1229fd3333fc8f371ebd85c588e751307ccc75d71d151f7481ecba1ef0cffbfdea5b", - "Expected": "000000000000000000000000000000000f983607a6d8a5c3b8a577cbd5d81ad2ae936e714199e3f4095cf280b8fd6d3699acf4d2ef251a571dd1ef4ba6d838bc00000000000000000000000000000000048c12f8b95f9537e56479b1bc43a121e4edfb6477fcb090a5ea60c5f4d01071776dd0264b0250902448f62800f4d2ea000000000000000000000000000000001644ba272d7003d0077991ccb4569638de0dcc48fd2e8e9a41cee1d2200aee1a849f2d620f60beeb06b08c31cd4eeacc0000000000000000000000000000000018892d773f7e48247215484ca0c8d996833c43a5291b0380c97607c86f4ab2784e692673a1da012ac4fec2713d156a49", - "Name": "matter_fp2_to_g2_29", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e07265d2762e8e398c83efe1c43452d91b90b7a4271c09ff693c83745a6c01b73561ffe3da9300c8e7e1602dbaab0bc000000000000000000000000000000000375579c16a167fd9f9f61d5177705f157aa0df3451971029a9444432db119fb33b8c07de33fc822eab46ed4ae47cf82", - "Expected": "000000000000000000000000000000000a06ea8e644d2d762520ad956d41ac2086a588450bc34f6d070b86fdfd73cd0734341a751d823935a009b7517770f86e00000000000000000000000000000000140ef0d6a0482537da7db8d775ac3c4a93b16c15fbe4602b5b1843ce757aada5f7776a74151d0bcf760f7284d4ffe56c000000000000000000000000000000000873c90f56a2b99da2f0a1528b8e376a5912f9cd81a159379ad70b7c10e6ebb7fea0a90d65543d968a34ebd539372e89000000000000000000000000000000000b05ff57079386e4e18e73cbff5f7b0efa329ef7355f083e8be258922203240dbb8926f7d11c22ab4c16d1df4bcbb600", - "Name": "matter_fp2_to_g2_30", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aaa37576af2101d090139f562edc2a6e7169b0150af831d053a3a87a3a5518889a51871e02deb3ec154ccbe9dda46df00000000000000000000000000000000158edaeb58b99d9442d608bc8e6024365e9a81e0aa23bbbd466c9ccc8d29415352a153e1f852666505ef097122592ecb", - "Expected": "000000000000000000000000000000000e9d6f9e83a2584f2cdacc4711085bd251e060f8c87ff7538ce474d663c6f23361c88971c9da589586e754ed69699c820000000000000000000000000000000003fa90cc1dd81b815704e15c0448bd0e8e8d0cd7ad51237a25d4b8a0f78f532b18ec30a108930b7407b7486aad9824de0000000000000000000000000000000000cb97bce1f75b1df5a4b52745014eb632d2d2230e52a9767e3dfd76754e98252ca81ce274b92a2947f6a65fedbaa3e400000000000000000000000000000000090edabb37f411fae1764792083c8c7412fb470833a9f7399fb312c58687d4afbdc622ecf9d74cdfa3ea87382adcdd5f", - "Name": "matter_fp2_to_g2_31", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012bfaf34a8111a01d213f9a9fc90846335cda978b3df23de99cb7b764cf5db1a816f66adad1319aa7e25c0ab89e7de740000000000000000000000000000000000fed118654a128735fd39ffd3b381ad2d71479054b6bccc04dd58fbeed9b255ce2b925e2141a96a12edc3a19188d1f5", - "Expected": "000000000000000000000000000000000cd234fcc729a4206233e46875a557027cb52c96322386b56d6e50d95dd9d23b6f8936ddc6f8475b1076a855c1ae23510000000000000000000000000000000010a774120f607bf9ad2d7bc498536cc9d35cefe384f88a2439a75f1a4f6a9e4b4253daff0d2c91b5915ee0e9a99b4582000000000000000000000000000000001496e7181495114abc0314f580c16038a04a8dab43b5564d518dba5f5e48112ce9daca4b16b6ad51c3af54ec9ce915d20000000000000000000000000000000002c61691a96a2120663c726d7fba3ed37524b58c92a024c15fccc659d1d2cdce077ba233a0d4419a6f237ee4e09abf52", - "Name": "matter_fp2_to_g2_32", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b693fe53cbcd6f8d8c98900be1f9c85966cc644f0a900c70826c6573ee801ce7863a0b170ce0ef168fb1f0ea484b276000000000000000000000000000000000c6bd688fb883f3097f8b6fd6fd0bc5acef9341f21d62a0706fb3625a70459c45a5200ee36a3802d4bb4912030bfcfc7", - "Expected": "00000000000000000000000000000000011cd454f16209b0b7040c744291f2df465ebc786946ce3cde77fe4d4bcc4b60a51573c45b8bb2d209da69107613764b0000000000000000000000000000000018a026f29fc2f81e82015ef8610b4396f2e3514ab1a213356953804d585c5cd6a3c5cffbf70d63d9dfca50129021f0e60000000000000000000000000000000015bdcc8c139e636b05ba7376c1ced4a183eb465df53b1996f4ddc8cbf42cdff4ae2bbc2d24831a8ec8b1134cff4444ee0000000000000000000000000000000017671fc3995babcd2c0a1d2a71c417fea84e29df67fa1096fe6d3ec77c45b64fb8da6ed08a57726ab314fb860899961d", - "Name": "matter_fp2_to_g2_33", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ba7f82549ebfdc7f4959dc67cebde4720d76d5d4742af730d45d614133f0a7b0ae7b61ba5b914a997d9dde83b77b031000000000000000000000000000000000b4acd8c203ebd8e3ce12b10cc791b9a4183440309f24bbd60cb2991712c792ecac64d3f878cbe407fa8ca0d09548acb", - "Expected": "00000000000000000000000000000000156d8823c37c81d8f03c0b2e61a2342aab6e6c9db36cadc9eb741e085de711e9fda08ca78f21753c4fdd8cec059b6c2800000000000000000000000000000000064d4fc2584c78f1e92f808d4457070b0470eb8de9d558885bba8b03efd8d8e195e4923d8e3382481a0ecee905371ae10000000000000000000000000000000008f1dc4d2ba12e7e3e1b0ef3855df4dbf29468bc99d5cb29fa3058a535af2ba038396bccaa238bba6d538498565c2809000000000000000000000000000000000fc9839b6ee876f7846b5086d487360b8faf133b6f5bd2dbc92a7fe2261b91b15aef8d90c227cd5f8ec05e32d807e022", - "Name": "matter_fp2_to_g2_34", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000145f6f774d943a1bb753d5d4876b1a88a4021cb6a6607c0efb07eef2f90ba2a90a6e9dc94586de35f6047332553ce7b5000000000000000000000000000000000b892f1c8d001c8aeddf845c3845c51f2e06c3c77e543e9721d797951b6211a869da97325b569e0de35cf3beda853ac2", - "Expected": "000000000000000000000000000000000d40f1c25dd57e36ed305276d4505cb250d2d9da0d5b954fe5e396b2c17a5399613243216586cedb19340e80f898873800000000000000000000000000000000063367c4a622fc925319fc6d119d8592f40f126ae05eed86ee5e4f6707b1d234c747e698c40f292dcb82ac5fe74ea80c00000000000000000000000000000000199ddbb5d4b6cd0fb9225a72c53f4596cf2597de63da56f4a9a18be8321a982de17367b0f3d794fa799657dd8ca10c5f000000000000000000000000000000000f1ed84e4fd958547d40cd2dbf16e2da4cb6d0d02763441067221890ae27ea1f689c26c900b695464ededf083667146d", - "Name": "matter_fp2_to_g2_35", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001878e791993186ab76f785b2c6b0fe08588b048007c66fc00c695b55bd17b37bdba71f34ddf75ac441a0c2687711b2990000000000000000000000000000000016598f630f72a0e1f39678e1d0ec6530c4795d7565c5d026fea2389ec0ceb51b434b532466fbb1c92c1c958041283baf", - "Expected": "000000000000000000000000000000000ee446310185ce76e31c13e4ca6c43166d971d9b9c539c7d0e8dd8ebbbdd9249922cb674bf6ad6840c203a5e208911fc00000000000000000000000000000000037344752896cff03bc39a9d09757a83c15fbd90f8bc1d8d58dca9b23bc00fa2b0f3f0bd7c9ed857d285825d40afde450000000000000000000000000000000003ef77f0220d1caa7538ecaef1ae2924ac1a180f11004034fc118aeac464fe1ce684b5fc90dae3370e3f79619889f3d7000000000000000000000000000000000fdfa434e7bedec071a1a333088d06299f55735f085a1e907a1c71c312bbb8d27ffa7de7ac69d421ebd675c4afd37594", - "Name": "matter_fp2_to_g2_36", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000134725b4d43cb87d2e4d3c43ca98b8df257acfa612ccd61dc0aa1ca749f20bd42c38d933d39f8c3c1a14dd8fec43329200000000000000000000000000000000070ad61a7f5ff9f0b4e7483f5d56b0f315b5f6545b194565ebcf8f0b8d78519ec113af6d70550888be4d661a8403a036", - "Expected": "0000000000000000000000000000000000ac465de3832452edcead434729be73be90785158617b5ec3ad53b12653e43721eda7de6742dc51d4d4bb58a291999f00000000000000000000000000000000147c39a5c162afa1f8eef400cfa1bdbe5436bc59d93973f50384022962f828ac934a4f88ab7c3d505b0bc3bb002f5efe00000000000000000000000000000000141bcdad53845a7eb2ec08189a55445059dad24ae5d39fedce869791aa28459f05a6cdf9575676cc6f3dd7d6faf077240000000000000000000000000000000010e9f539a9ced860661472f53147d0347927f065ec09bc32e00c5bc157b07f8b41b05aa4e0eedd1f73c7a287b2d0e5ab", - "Name": "matter_fp2_to_g2_37", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000179bc843fecfe713f6e3ccdc8ca0f48759459b675c8b96f5403e1f6da92c2d60449638f564ce179373bce473669965d700000000000000000000000000000000082bd89b49aa62c94ecd4244b3077421569c71efccc62aed3d4bd492bdfe57c0d2cced568df5992a196a7b71bcbe5e3e", - "Expected": "0000000000000000000000000000000016479eca30f48bfdaba4c8afca63ddbf59fe3367b2d3c17d15a5869dd2956fc67ebde964530926598cdcb62cfc993d32000000000000000000000000000000000650b4fd24ffbb953ccdb1b112799149d29e2377ee233b9ac97f4db432da63c98b8aad751f6060d04fe1f9262b75fca50000000000000000000000000000000004568dc0b9b430596f2fa59291ea6f923d552683ab9ab93000788145cd7c468c5576efd981c9ecee2ee0c16eca1ecdbe00000000000000000000000000000000154af1490463930d6b8261aa1d066eeda6d65b742cb53c65348e5cd766d86982a1489ad191d1b126233f193d24823b9c", - "Name": "matter_fp2_to_g2_38", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fb118c86e974734fc434c3bcb783e4a7f9251d9fcfb9f4419529354c8a7a3d9f2215de2d1b9f0927b185c5b4db838b60000000000000000000000000000000004da0ce78f3068bebd0a59bc2e41e7ade737375f07d6c9ce962be022856c569a33e8bd6ae60c4bb1b53b3ffc2dcc2aee", - "Expected": "0000000000000000000000000000000000df692ca763a74877352af3609c8cdbc184eb71bd35fd86334cb88543637b40b3adbb5802dcd7b88f4d722b566aba7700000000000000000000000000000000181495e709d1617f2d912f43487ad3920ac5f8e47395ec4b58bcf0b2d986c674a0c7838830a039bfb5bb59cd2fee2f5c000000000000000000000000000000000d20b482dd8aad583bd5d08ba9c61b3e954f022d48f9f4f62ddc9f5015ac71dab7d206b1d8b885d5e605519bd33d93a20000000000000000000000000000000010d3deccb9364ee386eb35c7117bab373a76d024627b8a031f96465d5f75b029fa992e29ad4a170c4473cd1df585429b", - "Name": "matter_fp2_to_g2_39", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001f43b86ec24ad40552dc4874a632b4ff4663eeefe1a8c613a19a798a0ebe321a3d543e2df28277944a941b4586ac770000000000000000000000000000000000baaca6bc34feac790807b5eb5fd173c86c12803b76b50be59b2707df765bd10eb467effe34f8dc3e1e79df8a54fde38", - "Expected": "000000000000000000000000000000000a007c914ed40c7f2719fc70def0d4752cbaa775cedae9365c5afb61a5e1a2854f9e1ce19af9fc85bfbfd2c33f5bf095000000000000000000000000000000000d85b0d173c25c2915fee429d2468a9eae01ba43c0f1a661f2ef83c1acd726865c00c40ccbc3aae306f93074e5e7858e000000000000000000000000000000000b3df302ec532c8100c121c9a3455392c713ec60de1f9572b040b0966f8ffb888e8cd768dcf6d63d4835a52d13a730c0000000000000000000000000000000001123c43dda8717d03fbc02fa53c4b1c9a931db6b274162cfb02ef5eec602bd8161dedc37c7f6217c8e82236f06e49e2e", - "Name": "matter_fp2_to_g2_40", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005e4751707f3ea7bc7a74d80eff27a0d65cea0c3d2e793425e79cdb0c41e6ad0cfcdbb4de604637c41dbaf30a1e816e60000000000000000000000000000000008f69021794d93826f8207b96d49214b46dfb1778603634a9f5194e92481465702a8be1bc49a7bb57527fe6f963ae04d", - "Expected": "0000000000000000000000000000000016d8d9b1b59a22fd830f88b9850576488f75672a87ccb766e52da77f187a8e66071130c7e71f86675f8379b2a8802c4b000000000000000000000000000000000aa4ca84aa23f01ec536ffa25c4b7a6c822f588bc75a4a72ed9237c0588ab892c8474a0f23afc7ff0dbc3b08f8e35b60000000000000000000000000000000001425e759e2537d9e5f0f356ff1d38128eff3a771fa661a839f7a8d0f548347438574ef7d592cd4273ef9b7269c9c5d7f0000000000000000000000000000000012cf1c67d1ce244ae22eec0bf4a400a0f356b9dd075d87a6e61941933872d7c0e42c1d238b2c1704d2cdb2df75169f39", - "Name": "matter_fp2_to_g2_41", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000116988a869cf552b2440e16569d8b6e30c6b15430855c4d6bbf80683c5497291bac7999c1f8f08f494fcb4a989451c3b000000000000000000000000000000000e26058d72875fd3d852aa4139f71d35e1edb58242a4939da7986645117d027d20baf85770fc909d537524244da59ce7", - "Expected": "0000000000000000000000000000000017f6e2743cb30fb93816d0dc802c24509315363c3652b0244e1395cb9200efb4d7b9fa7642e8d165d28a00740f1a83be000000000000000000000000000000001483644fffd3989ac98cea71843e87b8e446a3d497630419afe99b3f1729a831fa6a49bf763b0c410cfc5390ac4ac1db0000000000000000000000000000000018ad20ae5012266d771b2c86f891f498c2e90a7df19561be240319edc1fbfb316948fb3f8a6b0e3720676b076eb372e10000000000000000000000000000000012f404211899d8fc1221ab5b82db9042ad37e63348871e5ac6cdbddacda0a564888f89d22712069b6096b58c5935edd2", - "Name": "matter_fp2_to_g2_42", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000078c6cf89561533810b583a88149586b29da5228ced10a75257b2587904217f63499d8b9ad2d536617247e12f8d1657d0000000000000000000000000000000005b016ede9d892fbd7aea4e8ed0f1eab70713557311481735a91308fabf76fe71e44a06dc23ea66ac5d831e982f401b1", - "Expected": "000000000000000000000000000000000d4d78f992f12aefb0e3a6b18fbe2411108327a9befe4a822618fecca4def3169972b4f1fb254cc4656a676529d554ad00000000000000000000000000000000145ef33250240a5c9434d4b2cf2404d9e7cc51b55e482ebc6a8aed85caa21ed00623b3cb2d76ce2d96b2f346d395dfc40000000000000000000000000000000011af2ee2514c58078da335c0273cd18b98d1ac6f0e67890677403f71b0e06863fc72611c0cfba39ac894ae500edbdbae00000000000000000000000000000000186863e7c24cbeb45f7a66b5dddc9b57c7e22c5139aa6bdb82e77cd8182bb8d2fb7bddd7d3516b5422f92e08d02606b5", - "Name": "matter_fp2_to_g2_43", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007160f36f0e5c4ccbcc7900c6504cd86fd6fd700bfa79af69841e4a6127eaad467ccc93c66baf7d767c3fdb1f31c527a00000000000000000000000000000000043fe62b0b9be76a375f3be0d6ec891d5bf5f2982cb2390125ff8d5db57b6b18c5616c526102e4f615963d601d13f122", - "Expected": "0000000000000000000000000000000002af4a301e90c71eb375110e7fe23f8f05e2ede86b1a9b240e8d1d4d70e96f1dc3640fca7ebbcde9918deb91f3592de600000000000000000000000000000000058b5f36cfb6b0adb14b397dee4c3769c7446426eb5719aef4965cde2dcb70e6f2fa60101a5f03517c0040093453d092000000000000000000000000000000000f77b560469cd42c5cf3458ae13020c6678af3cddf9bc559372d12bc5d6b930795e1eb09f27cfdb8215f39fb2a11b30c0000000000000000000000000000000003308985946c742af7bd7d29abc2517ff1d225607b5f11fc66695cefabd8f25e294ebdb7339949d6bc4d98db19533966", - "Name": "matter_fp2_to_g2_44", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b9590b1d0d292d9967d759060a551f4e8e4c1c0066a9a3c0be515085847fa26b77462e3bae9e2621f28e01f897df0be0000000000000000000000000000000006ee7c459bb4da96e87eb1d39bd7368de5f60104f85b7b4bcdd7761ce08d48babe1bf5e765282779803bfa972d0e668f", - "Expected": "00000000000000000000000000000000093c936d57135b25900bd5dd55cd579aa8b85b9c1b5e8dac6196c4450b624734d9bfc3fda499cedf2e877d79f2da650b000000000000000000000000000000001832306d3ac1c1c61bdaa73c9b6e9c2ccb484c3baa1de6a217a2884c72b72618e864f75fcc2dfaca358181ecbd3347980000000000000000000000000000000002b2e5ff1ee02657fa88c7d6f23cd4c0465152a9daad8479b4b68c97930acb22e4e2eb0011ec4062b8ec46991a7cc630000000000000000000000000000000000712543547e9d24cc78d1c2e3fbe0b51222185f4c6e513256d1ee066ba50beee20321bfd60462e2587c375a0e9395715", - "Name": "matter_fp2_to_g2_45", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000044612b42a2baa9d3e1d187b2a4e048773b4851bbd7d4025e0f7f61abee703b5a563397da4515c7379397dcde698228a00000000000000000000000000000000014cbff1000bc0f9b394b18e81124dc81f80e291e841dae6e96e0c86a6f618b9f6aa6103e0e7582e5136319a4dac92fb", - "Expected": "000000000000000000000000000000000f52e2f8dff9a93b2985d5c2b8b980e4869af53ce55aa48bc1c9295e557e3b5ff78896e5e6342c2d535d18b11950bf390000000000000000000000000000000013d36cf2805d350c5b748e639d20e592deb4c5bcde99a94fb539dc56d48a862151b925314f21dce4c9130b32e44f54060000000000000000000000000000000017728f485d881b861f626c9de8b3df7d807b266de6cf8dfcba262f40a6248fb5e6506d11e88f460f0b5f1a1907ae5f3e000000000000000000000000000000000c0ab998f63f861c82106dc3ed5ea11a16e98139e8686f8442047a1cf9ac48c3d34b5129263767830144e9a13d4a1f44", - "Name": "matter_fp2_to_g2_46", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013da827dd718d3736cfcec53f034d34bce253bc91f7cfd6cd2666819bdebbfc43a9363f82bf4b580a7739b5dda9c94360000000000000000000000000000000010e94039f37d218ad393e88a226dd324a37e8d5352dedf6d84fa2ed2cab2f874ccc5ce94599950f91b8dd6d6c8b84aba", - "Expected": "0000000000000000000000000000000003463d887c4d0aaa21acaa308d77f2c7e13d10157efa9ec3fb1586a8db5ff1a9e807c91c86afc4df34c9fcf06e8561d700000000000000000000000000000000128a81efb9f30ed811ea3163c71b6a46ba2cbdbd3a9f93cb8d0f518747cc860431c6e93bdcdf36d00f83838965da4b50000000000000000000000000000000001777802b7c41111b38da3fd8092c280b4925827b2c1592f779a4ddca71f8268858855c413fd5c0057a652155261d75ba000000000000000000000000000000000c88b522d6dc2000cfbb7052e141ddfe15c6cd7fddc970edc4afc36fc59e7f8e31415706a8121e8e84348be0b50d0d88", - "Name": "matter_fp2_to_g2_47", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000010416da7cfbed2768c77b80957053030d49d535b21a8a3297ab257dee0463c91b87a9e571b86bd874522149d9af0c2900000000000000000000000000000000197ef97f6d02a51b80e6f5629e88a3c60399bcc4a358ab103dac3a55a5877482558abed922585a1ce3228ffb507679b4", - "Expected": "0000000000000000000000000000000014be96cfc0dbe09155ac8d8233b71ed584153e279b2b2be88471eb653aa4913fd2c33947547c61f7fd8bedbb552a8b1b00000000000000000000000000000000146b9a0011260e2646920894cf405bdebb101db12da7849b30868655fb5f972113cdf2fc322cc246d3dbd9f20b98fe2f00000000000000000000000000000000104bc20e104da5173dcff3e195f80960819a0d64e922bb484c2739c4b7c22535f7faeb1c85188aa853277740b389eac90000000000000000000000000000000019f5aec599f9ec286aefe48eedca3f929ac6c758c231182b92dc965d6ac1f3db53d93f57d733ca8425a5dde070b0dfa8", - "Name": "matter_fp2_to_g2_48", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000025f1ac90f5b0748d57d8f7a928be875c5712801f70af0d057546228c1bf83d3a207884c0d66d0b5dbcaa736bfe0aa10000000000000000000000000000000017f66b472b36717ee0902d685c808bb5f190bbcb2c51d067f1cbec64669f10199a5868d7181dcec0498fcc71f5acaf79", - "Expected": "0000000000000000000000000000000004ca0149527817b4df0f08acabd4e8c6329c0d1bd9f2e8211cbea25d69b84009ef158c770f948fd67e4609ccadc938680000000000000000000000000000000004101b351e2a9d34042291f38a289d8575872104bcf76f60bf888c60cca5101c34c247da30f7a8db4f0cf2f32abd302c00000000000000000000000000000000167e668de3207ddc60b8a5d5d246bf2f63ceae3bcbc4309e73eebf4d4234c2785bb13e4d5d8fff9c5f205e4fb942a2f6000000000000000000000000000000000491b965ed005065abdac53e3065781f2fd23f6159debc64f01c9f62073c651da33c05ed84617efcb5ffe08ce05e3b2c", - "Name": "matter_fp2_to_g2_49", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f2dd27e3f0ab503a8752c0802ee14c655271e8cfbc734905b4331fb4e70cdfe291ff71053fbaf91680b1dd108f458f000000000000000000000000000000000c62014b7694a3e81370761e0adcc32430547a1bbe33746637e7762dc24f8d04b4bb955f17ca901659482c622d777642", - "Expected": "000000000000000000000000000000001541320fb6f8a8c3c67278a7ad05ae7927d3555ad562bc8addb54c6693c51fb1c7355d2e74ff10f6bc3eb182d8f5b88b00000000000000000000000000000000172b65b110935b116ee683c8680ef0a660afdee43b9b8fce08ef3a70b352f8710c06b820348c338fb903a165cc5376da000000000000000000000000000000000df529b0e274e2e8993dd89ffef487aff23d31f502a19dd7d383de08fc77f1308a59ac5bf7cc899e81d377b2422187850000000000000000000000000000000010b40c9063d174b358637ab710d15c80d9230a1b3a056cfac4d583ad8c5b79c3d9bf22a1b0a4e0f629cd09ff7586f886", - "Name": "matter_fp2_to_g2_50", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014d1491a45b4b0914a6cb2e4dc7de9d0962f5c175cd571057cae1e17d2c943954d119690ea14f5815f858d277a9ad828000000000000000000000000000000001650771e0f7b33d235f229b7d49a7a5a0f00f78e5f4abaa70f39ec452370198a8532b5873e41f17c449f9c565e6adea5", - "Expected": "000000000000000000000000000000000978ff68d94d33703488298658cf2c1b6034d3d8d21c175d71a0545bc2f99eaaf131f061f3e4f55622668e686e691f53000000000000000000000000000000001124804b252f8187178435761897d00c43cf67b588ca69f97c20b0ffad3ed94acc2c0f85f900713dd6ee9f38e5ca94490000000000000000000000000000000010ca2a8ce71b9a096c132c4a060a17365475b6556d4fc6284266ae787e217b3ceaa3a32bdf751375eaf6ab49800132fd000000000000000000000000000000000a43b435b116d9480497f6b2e1bb377550cb1a7ad59e4214bffacd517afc6b7bf91112fe57b17a02a86876ea07361bca", - "Name": "matter_fp2_to_g2_51", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aeb244909654b3e1df7cbeccf297223be57c2f514474edf0740dff48dcd5898b6e49eb65c787aa56ef79778249f4e07000000000000000000000000000000001007c89a66dab07f54313db8682f9e829baea229b030b4514d9c93686747207939c50a198e83ac2cf50315e02642a24f", - "Expected": "000000000000000000000000000000000c3d87b1b78fab65cfc853304c682b39b6ec2b4ed005e9108f69daee5aecbd586c9818c37cdee865ba53eab9302320ce00000000000000000000000000000000062a7203cd2fd04a957cac8b6b6bb51e635ed7165c547ace10f93a32b7f37747a2e63d5767d966684409a6c748d4ee6c000000000000000000000000000000000526b44af8157dd68725aa8743684e020c1e385af7413c9dcebb320568663d18b6f29edea26f2628358852b794ffcc8e00000000000000000000000000000000098126f486ff55c21f64421e85b09a1b54f42d3499dc0e198db6f3bf7dd8476cad97c02b5b366e5ea20d8f83cc223f7c", - "Name": "matter_fp2_to_g2_52", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000398d86b5206bae4ceef0bcc6335b1f6bf5d17863ef3a5e8463aaa69d9f73f8227263964659d4b770d6d9813f9399b9d00000000000000000000000000000000096bd18be1176e16a0d80e60f7d7ec9d3b6162f683440e3cde70082a73605da3783c8a058bf76d7e25056f5cd95c31ed", - "Expected": "000000000000000000000000000000000f3e76e7d1cadfaad08d16457b02d89c40c157225eec7916d306faca8dbda008f41792888c647dff1acb4d4ba3b43c4900000000000000000000000000000000132bf730456e2afe745a58cdee689e37223292bf682d5b7dafa7df99e40d385559d0b3161bdda0bf5173c43ee46412dd00000000000000000000000000000000141b36ff6890e35db0054358bc0731b3aa0efac1a247a51daeff3515746456216975f44769174a4be41c109d35e4be33000000000000000000000000000000000ca401ee1addff8fe87b600e057ae34ba297886f92c5be8a8c00b360ada71831e31bc4ea1c309c7da31cb28d1011ecad", - "Name": "matter_fp2_to_g2_53", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004ca5cb60c32edfa385baa911ccb7fd1f383824c22b945944b0f3f7011db8c123efd8fa70e4fe699d40c6716021f0151000000000000000000000000000000001339adb0dd8d83574c2008f0a7ed001b0808d2fb639b5e57e1d293884247d5c66c948ecc60caeea7bf440a3a44ed296d", - "Expected": "0000000000000000000000000000000009d0af77517b654ad97de3ee1dbf69ec1eee901facd0f8c39b4af393d0e63957292a7529b461f7fa58909acad32ba3a2000000000000000000000000000000000fda17cd878ec0f8c294daec1bd1d56c63e875b002a81c9c41146dbb564bab6e4eae2717c9fd718af1ba816a1526e8fa0000000000000000000000000000000017563b7ff22b50b6d9e24b1e0d89ca5c72e68d4d3cc24cce36856191111d087c3dfb392070462dc7850ef5a1422931c600000000000000000000000000000000020001fcff638504055ba35230b360e6d3cb5777b959c194d6f9b038b58d3ead0b82b28bb215378abd85d357b85ea260", - "Name": "matter_fp2_to_g2_54", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000089211892a61202b1ad3a85aab9f08f8d028f3e3deb16c1de4d62c1a403fa63c6dbbdf8cec37f0a9d6f346b1c7ee179d0000000000000000000000000000000012a9fc2070b326f4d7e64804b3a2e977f4bb36b6a4afcf27252af757d8535e8172a99dc909fad5a3ff8df23d6d6c5948", - "Expected": "0000000000000000000000000000000000d51c77c2443f00d965c0d7ec9b5a8a8003c2a77b0ffce3e47bcb55420e8690a9c2ba9235b62a4b351d79d216a3aad40000000000000000000000000000000013cd46e3ee6cbb3bfb771ee30b5f5faf0a64a9efa1f8fc57024c83ad07a9b25e513f211ea604cfdf319dc42bf4c067d300000000000000000000000000000000009fbe1fffc67220067c948e0c80de23795e045fbe8031c9010eaa69356ffd8e5741cfe12731ec13aa236630f1b1dab4000000000000000000000000000000000e5ecdf808d10d47f041e4b078e79b32520ce9623b50059a3bd8b59daebf9103c31425659ecbaebfb2384d1c2f1b400d", - "Name": "matter_fp2_to_g2_55", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b37365748fdb21fcb46f94edf86c586f17d0e042c4683e68c6cb83e7c0ed2c30ed260c15af2c9dce77bb705debfa7590000000000000000000000000000000010d7c02c6c1ba3cf6ac09a05dfe043905e1a7eb32b67f2e8a5dfe82eaca66ef46cce43aaadeff58ca85345dd0d3bf3cb", - "Expected": "000000000000000000000000000000000f3e4d2559261829c0f4816f8b571170de1f74d75d74997cba56fdad42932db73504691f9e001f5b4604705a8c1a38e40000000000000000000000000000000018c72136bc7d3050ee693270668e706ebf70f990e447ecc6153a10625cccc9deaf5ae82d2a656b1376bf33b1c1fdc2c9000000000000000000000000000000001754f2725bfa76e92a74ad5b520ec2aa82a1f86e8623a054ebba489adfc9e71d1f14d4692ff9fdd8acc3d768b67e1b7000000000000000000000000000000000096f1373434a8822569cba0679dbd2abf619bd9a8c73e54e078688d4e2615d45431ac8cf3da5e15a83fe77d14b339e49", - "Name": "matter_fp2_to_g2_56", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000aeee59421c8ee65f8070b9d036e6bacb39dd2537d02960a3a57da4f0985cc7b27784d60fc1613f5a83c34d2250395c1000000000000000000000000000000001715ddcbaed0a05b38b1c820724405a713cc0215a4c497892f00746c0f9af28b440a3686178d9bfcd41944a224311306", - "Expected": "0000000000000000000000000000000018d515b8c99f541c7dd448c3564c1909b84517b662d6a2d1176d3bf5e70abc0a2995c73ae3f1614bfed2f64229e173e80000000000000000000000000000000012126ab671420933cc4fa9206311200cc5241ca3eec54f5d97a426a72642bdde32a65c79735446779cd1744d112d544100000000000000000000000000000000190d836312ffb0d6bf493f4c942263922659abec46ac4de639efc311753148b445509f808c2fd813729b1bd96e0e663f0000000000000000000000000000000006494f9a451460ac658ec17710bef79d59b6e0fca049804c0954c5fc472bbef520f75d34408ccc62cf2da3deeb79acc2", - "Name": "matter_fp2_to_g2_57", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ca4b3e1a8351057ba4a2ffaf0cdf1c3c0717ccfe26433f6c40e2cc29e32ed884f63d25979580fb555a5a86c9147bcb00000000000000000000000000000000010c1db593af38aa14ca9dd588f54b219ff1fc9edd25b3d16c595662ffa7939879244326b14d978e0dfdd25e37776964c", - "Expected": "00000000000000000000000000000000173fa567aa952bfaa9a60b8232a185475cbb36761ebef49ea5fce900a06043d0e2c1b6024e40eadc9f4bf04b077201450000000000000000000000000000000010fdc32ff84f79fe39351cee1ed6b67dbcf2956020e2518d5bb5b367b61f86f1bce36f75516d9551d74cc3a567e6c2be0000000000000000000000000000000007abdff8a8967eccc4de6b4ce142173841c0e8399f5a67dcf0f7b5e5b4133391b44bf4d41d3ae3426839b19aa4c5d40c000000000000000000000000000000000c99f160062566418c09f10eb80f005f2c8c12825435f354f1d65bec0322e9b8ee968c009a84ba792a7ee7334b32bb3d", - "Name": "matter_fp2_to_g2_58", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017cd94e7e672f0dba9a3c1db742d87cb18b9401e8311c4badc24f811a8f40c27942da6485807701c1a12da58076c756b0000000000000000000000000000000012f6de4ac9883e78f9d658cede4c70b44bac6b4c9734cbf24298ddf0df0cf54164aca245d8e313be4aca66ba3cab5d70", - "Expected": "0000000000000000000000000000000019dc92f1da66d0855ebc8e7a2ddec623a2f843a97c7385364a631671be7ee3387a0f98940b5a51c8d9e23eb27e3133b00000000000000000000000000000000008493903c5c68b2847869b8c3b0fa9b8ba15bf1f11a40a29e6e82942e2910901044254cc8e8c3c3bf56e1f1b6dab7e86000000000000000000000000000000000bd3c1e302a191094059a6493e59a11ab05a49faf333f36f7680ec9b1043e59dfd7f0fabe9f334b97cd638dbb8bb664b00000000000000000000000000000000141c9b07ff33b6ab55b320dda6be54320082f0057c446236cf3d3a51e674c26a5241f2c702d9989adbae9045942eeab6", - "Name": "matter_fp2_to_g2_59", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001b2843d9852feae3145b242cd0999877c07785bc72cc2626f388dca32edfb112bb90f9aefd6953eb15a0babe748573d000000000000000000000000000000000a69bfe809a67ee853cb96b5a7a72798748cda56936e5664d509001544539730f57a7541ecd2396c9225818b9dbfa3c6", - "Expected": "000000000000000000000000000000000d0922466c358cfd756727e134b5e64d211244587e4eea036f0959e78570dce3ee264c703cc356cde20637c7560369340000000000000000000000000000000011a66d618f79fb662ac2b2d3b50750a5567e36d7092dfcc72d8f340c04df75ecc0ce4a01b410ea775dc548b8dc66c3d8000000000000000000000000000000000cc49cf4be5e2df6b43054092afa2d6acd66f5a43ef0667f6a2d660beb7fec70558ce02d7acbcd090df91fe833326718000000000000000000000000000000001270b0519db083f903a3dbe0b1b1bd5ce0b0059ea2c2c50335dd80b4bf154fc23a3de1ea753b0e279145254d8e5bd045", - "Name": "matter_fp2_to_g2_60", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002479a989dbf27141bd9f467447218dfa6ef60781a7231f089d5f1f1d8dca2ce9606a75c09f63f37f9cc1ee61dceb32500000000000000000000000000000000037c2f1b96170f6847138232bac663e4940bca602717c877f58ff7f5259778246085d499ec6bbeaade18f738df333cc7", - "Expected": "0000000000000000000000000000000007826398b4ec35ab58ba9fda5c15ada2a41d3854677172ef6a4a54087b64d0f73fc875ad62236eb7fdcbd94f14c8895b0000000000000000000000000000000016b14fa92de5f6e43988829ea2f851746efd6680b0ea1283264f803c8ffbe85a343bdd42225caefd1b94b8b311d2f4950000000000000000000000000000000018797093ff82bc10e6db60b1da50b9a60da01d67673e9bee8c7af2bfa2d57f409f7b06f53944938e5c73b049c2d3c6500000000000000000000000000000000000c66dcc3d30f35c21b8a9369c8f6de28af404e8b30d3c9a7f09c461b0272ba6d5a29e716012536dbeac1d9672af8427", - "Name": "matter_fp2_to_g2_61", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e6fcc48312831b910e52aebbf19869b3b32f05db8310b68905bb244ab784df5732db2e72183de5d231d803d92aacff9000000000000000000000000000000000f61f9e52fe3afc2a6bf12e420cebf83bc55a449d6a167779e5b6ba3281c51d790a045643aa75f2516eaf6ae2a816ac4", - "Expected": "00000000000000000000000000000000191aacce60a1a83f2c453fe196bbe5839a3a1178b147580435f7de8a2b0b4f65b3e280ac7a67570aba0fdbce6c11ad9700000000000000000000000000000000075ddd6b256f53a6ae6758a5158508540aa99b78ca069378f0ae3f5621ec24b9acff1f9b61d378334a63682a33fb0561000000000000000000000000000000000b06e11c9f858446fcc90c69d05cc26c33bafed0feda19adbd838c9c24bbf567b673110a1b248d0ee97fc682e561298e0000000000000000000000000000000018c75dc203493e12e1523af50f85ed648130ce5d3e9757f713850c867cc95c7acbb66c9733dc4f53d6a0e64bfaad5832", - "Name": "matter_fp2_to_g2_62", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018efc6d366d79a09b7d56c81c17c2eec2ef7395fdb5991f41273329cdcf4537d342bddd83c3994a40d5c18f6afa054c600000000000000000000000000000000127021ce28627a9d6a492720f728acef3b38c12b951f70a932c7fc0ce3f5b6c80783351cec55d7d1bc4ab964bb4913b2", - "Expected": "0000000000000000000000000000000012931f51430bea6e96f8ec456ce6b3c9e058b0bd3bbfbfe8b6e84fd6110c3bbbe0001018064e8981797f9c93713a0e4400000000000000000000000000000000196b6093dd2276098853ef2bfac84f0cad06b67a12484e98915dcc756310b818d8136954de1b602eb825ab29a143cf4b0000000000000000000000000000000008284beaa877b25374571dccb218c401cd905b351dd96700853f01920e409d11c4e440e90dc175cdf0fa807cb9d1e93a00000000000000000000000000000000063c6c238485c291fbb60bd2824154a9e23dea374292966d271ae94875391b7ceeee813e3fb9504223bb86f0ea3b6cb4", - "Name": "matter_fp2_to_g2_63", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a0277228ab4e880c12f957a6fcdfe49e2155083f3f93d3f00c68622415cd1f5bae183b7df9e08328a8139392772cdc6000000000000000000000000000000000de0ab426e56029790a5ff72f34da97e11c028dc5d31e448c49ede004102804d2bcc36d509640247a4c8bfdf5104a781", - "Expected": "0000000000000000000000000000000000f7bd0705cc4ea96ca38314cb85963044164b83a506ffeaea6e5eb8f7c4967cab1f1658f33b5435191427aaf9605bbb0000000000000000000000000000000007a93e2a5c118aff6ceaf2370ddad52a82854946ae595d384ee0b2b4935a574ba758736d84b0ae792f998ec6a707dfbe00000000000000000000000000000000090936add00fe5c7556610b28ecb4466ffc37b95b5cab43e072a585920b3cbe70faad01ef75d1dcb4f7d00d900bd99600000000000000000000000000000000006ae82539c68b7af3143e23229fe320924472c2b3e15a2e27e94cba674d30f083dce94706da094435c53285a43f89e56", - "Name": "matter_fp2_to_g2_64", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000170b243c5aa49a0134bf3d6494cc1e55a1c6ebefc6117eca3b343a48ef0a2b077c443ec5b9201b198df015a38e66b7910000000000000000000000000000000019a8ac8a3be1d45318801bb0a654963b312540d24aafec46bb7661cebeec27b0b345275fd53c041d02b1ebfa27fc3854", - "Expected": "00000000000000000000000000000000024c1b869fc13191b71d7159a07e869f1b13c11c73231b82e9bd0a7b4c32d7b376fb73d54f7231dd4974713179f235140000000000000000000000000000000012b9f95af661e8452aa5026302a7c28695307f75e9e4e32365caf378ed394fcecc831a3c47b443172188f4d18338fa75000000000000000000000000000000000f52675fb4d112d1d39ff953a253b22dfa0b73d972e756ea7fb673bf87aa992883c5baf32be6f50f880b03dcb740f06c0000000000000000000000000000000008b57726e17c873e12834dc291cff6bd95307f50e7b1d0caebd8c1eeb6eff4acc0520b135bc8e35a257133b7dc640db2", - "Name": "matter_fp2_to_g2_65", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000fbbd5a10eeb2f358f2b167f1985d4084c4b12accb1520d780ef1c52f6fa80e97aaf190e7a7b241ef96fe8289fc0a9600000000000000000000000000000000155687114e7aa786ba27aeada830fc705aed069c4e3a07e88d7f33923319f416ff3caf6533cbb36e5bbb1b93a191bfd0", - "Expected": "00000000000000000000000000000000061938df3365bf910884ccbd74d3cea7c30416bddc1a9b65e7723c15d89aa657da36a45fe10ed50bfa0c2769bb98aa2b0000000000000000000000000000000007b3981054255715826cf8f247210521ac681305aad3928b69804117fc143c5101383eab7017127c8452a79003a857d60000000000000000000000000000000004c745113480fd87212ed3ff30ba43c8716b32e62c1f0091bde53bd4a8fa8fe6bbcf0904144f4791ed1bf12dffa1f17a000000000000000000000000000000001237ba297c7f69e5e240846a12d86c8276a9a6ceb4af977edadc7ebfba3ad3f4ecc0b875da0ea578c83fc3b91f9f31a5", - "Name": "matter_fp2_to_g2_66", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000115edef357ccc3432226d9bad796a42b1a278d9c8adfdddc5a0f8a36d32ea1787183877f8b7dfab71424cdd10b63441a0000000000000000000000000000000014b369ce61abe60d942346e049644b95a0fda96316446b2fe7ee427641af52fdd2a654bf125ff6c8c7f3dec98f6cbfb9", - "Expected": "000000000000000000000000000000000a0cc3e328b4cfd01afe53dbf971ad78fc74d951050d76210e4c84438109622f0531747e762e185e3d7ecb9faa7c3255000000000000000000000000000000000622ad6092caa727d069b8921f4124d5996f3019705a908ef95d23092c5bb148873a22c227aa25ebee361d4184cc38a10000000000000000000000000000000002938d2ff50cffaab8c056c2844c50013f5bcdbb4f91b3f823836edabb39ba17ed1b8b5862301efad04bd2f5d5bf599b00000000000000000000000000000000072e96136afebbf8c06a37cf9b20c85ef8cb3f7f99d5c71b05a187c193711e5b76f52863c7ef080a1b64b2120ab2ed84", - "Name": "matter_fp2_to_g2_67", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d22b7b36ac66b10adb4570f8e7521ed76de2df2a7b94b2d0b9ee4514cdff6fa7c74854d16e7e70f054a91df93c7ebaf0000000000000000000000000000000016867c9cba66dd9f1d0332d31c4e46f8e393eeeeb19af7e6e01effb29ad999b3086b599ee4b371de557d4fafd5da3794", - "Expected": "00000000000000000000000000000000142ceeefa9fceb903b25d4dc68f6755833d7529752db0f125f7f65f2b7aeea8c90e599ac409576e82f7b9d6f83c43aa0000000000000000000000000000000001664acd89b482aed04ef40bd4d1ff9f39c80d7738771e2b3ca731af01aa230d865869cb05d83992e94ad99549fd0b8550000000000000000000000000000000013d6ace9b492c014d9a7504b5abe442e3bba13b1ada454aa53177990ec44f616e091f1382d36db87b7e794c11570a9bf00000000000000000000000000000000081b7a8a2906435f8a9242f573225ea62c5429e903bebda9fe9973a18ed2682185d72aaa6584b9848d1cc45ac907dd27", - "Name": "matter_fp2_to_g2_68", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000db9258e1257e659e60bf8569ea90c8247a53a1d1eb958481623447a38d0f1f1686c3e40c8f15bd06cf5be9c02485452000000000000000000000000000000000517c87f3df032ff08d960f524939e66f7fa69b4168b0f2507baf7d7231a70dc5690a02d317b26f219365ac3255bee78", - "Expected": "000000000000000000000000000000001182e4230f0c360c07913349f89f8436c01841c9615348a0d7057336c7483342024b0369ae52f39d4582f9885f552b5d000000000000000000000000000000000d15433ed130163a85f8ba87468c906aba88ef8610fcc1a8d6b3308cda29907acca351fd7fb19799184f1ad91c751b5e00000000000000000000000000000000111089005c4c5370863b0ea6b629197a865f978f71becb741f50f9b4e49b13162ca63c29aa26287faa9c923f57f4ad4c000000000000000000000000000000000dce405ed2a79ad433123105ad01a26ee85d1ba4e5f3b4e0339fea787058c06e9a6b10f5ec8f6eeb85b211e18b6ea076", - "Name": "matter_fp2_to_g2_69", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000b6573c743989fc8613d4ea09c2e500ce965b50cf0c8975ff703116464082efff4b42828c8337809f6938d7cdd3f66e000000000000000000000000000000000896d316629c80ce6e5f240535863b9e064728665c0815f39b21675c236f6995e7dfff1e4aec9ad05861e2122469ea56", - "Expected": "000000000000000000000000000000001694cb615d2994a903a13645ad44a63395320f286503902b6009e7c795dc8f024260e0c45bedd864edc9fcb9d1ca6bc1000000000000000000000000000000000f20538af015bd6d213f90fb1a1ebde4d9e2ab2defaf80d791a1f70af2ca7ea1598d43e9eef1cc982f468cf15d223c9d00000000000000000000000000000000046c62bec4c6876a67f5fe68107d677db8fa4d59ac0cb7afe6e706864c6e94744bedac6b34a68e8ebf89c231307b86d3000000000000000000000000000000001839f3b8a6dd8fe8028247670fe5b491bb43ea8fda53116dca87f97da96573a5e701a703fb5fa7bca457ef88a827e061", - "Name": "matter_fp2_to_g2_70", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011fd2ccf6883b78fe19cfe7beded503cdbe1cd5dc9ee452aa6b329d2237c2529df6774334b132cfeaa616f20335f88680000000000000000000000000000000009eacceef036ec500e7676f54af703016fac93d69ed19c8943b64ffed2db498b19cd255a0a3437b568eade0f497c7b17", - "Expected": "0000000000000000000000000000000009d8725eb8757828a94969ebf40545a62835686897d4504a66484a3078b2f15e39fe918d8dc01bc7560dcb005a7a0dbb000000000000000000000000000000000954a6cc9b2dedca1cf280f72fd0625184b8f83b78ee1ffcaf0f9178ce97900d759e4a74b914c3ddc32f84c3f4c3a8d60000000000000000000000000000000014121b83d2a06390ce7359e570e1593d5ff097cb0e44c38bc74171fbd8a8da0dfffcc2bcb95fb2d80a55933f696a86cb0000000000000000000000000000000016f71d24256de70618a02b0f016c6f31a21d2cc42855886ba30176584a028c2e12367be19b834bf41356cdab21223314", - "Name": "matter_fp2_to_g2_71", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004a851380536054f6b69ef7581b57dfd753d1e6201069bd1218ae5766aada087b4b08f65d43b3ce0215640e8d34633310000000000000000000000000000000013579671b64f2d9a2c3ac2737cf95c2148acce3dcecb3db6d019730010c50d1c0504ba4ed42d93771ba296b0b07487d7", - "Expected": "000000000000000000000000000000000cd47f0982904ccaf4f3cdaa37091a08e67a5f04af09033b864631300bb6c2aacbad105eca6ddf68a643976fb555d3d80000000000000000000000000000000012332ddb0e91f0ef9e085f21634c6d69576e60d3d24732a0c91a560906791f60f79d09ac0ebf448bd39f047b1dd428450000000000000000000000000000000000a756a869b3cbc5624f0e08019170beda35fd2642a79108b284a503942f8267b75868636302e5a12b4f1505331b15f9000000000000000000000000000000000f60724f6c8200edff41f3299ca003e9ea03b97b01a3e8c63763bdf67b9f7677331a7144915312458c40d041be97b3c8", - "Name": "matter_fp2_to_g2_72", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000021dc1dedded9b0dd90afa9ab7fa8f9c33930fe4ae68185ea4cce9ed97ce4cc9ff93f96377b11f8d42b02e759a10b06200000000000000000000000000000000034c963fda3bb80043d6d7887661ad59b3c31c88c958b451a8e11684770c132205db6655ad7cbd604ecc3225b0c128b0", - "Expected": "00000000000000000000000000000000095cd509e53f10b1ee18b2120e2d18f0905a202a992a9c62480beb6588275fc8b5b151e6abf17a12b6d9cd03a8b37a59000000000000000000000000000000001723bf1a3d79935eb4b39f7feaa1e05cd8f3e7a32e2c406625053d8d8fde33eefec231ee00adb00b0acac16a83dc77fb0000000000000000000000000000000004af528e886dad3f9fa7232605936bc22a6a22622828367791920ec9d31cdb2f290e37f5fc79efaeaf96c86b3f6e39220000000000000000000000000000000015bada14a84fdb09b77397cd2e27836f9f88854924af0cafc6f9125d32be848c8325a3eee1a26de8be8eb80b601f1ad5", - "Name": "matter_fp2_to_g2_73", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003e8d1be04f8dbe5c7e1c7553cde8355ae16d26c819dea92fb543cbd9fe9e726359e1e4be0483a7720343f34c6a3fb9200000000000000000000000000000000062bc5fdae812802bdea09e4130c3d9bf80c7518138b116a4b6a302c155b97226a6ccc8a3ace18744e7adece08781f72", - "Expected": "000000000000000000000000000000000d8f14042f36bb377655b63dbc37c50e0eb5775d4e4399972a6758cdfa9751cb4b733745ed1a47fe5f2cc434efc5af81000000000000000000000000000000001384016829d028f823e6d062898c042a461bca13ae4627c983d9b5c9e8b4ffff7eb25daa1c52b39e309b9c1e7e4f2e920000000000000000000000000000000004f7904d491a0c2018b1361a9cfec4fc829e607402859fd9b9ded60adcee51e9b522d302f9064130a4eed1327f49bb4f000000000000000000000000000000000ef4fe949fca569b31fc57ae7d0166ea53318c5712311076e052c2967144116f5490fdf56f26adf64aa01beb4f6cd214", - "Name": "matter_fp2_to_g2_74", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000014b922157b19ed9debd9ae95cd9435f7980b8d4ea33fd29f99d5e7fb1a96f6d99ae13f7f86239c4bc286c3927d3522a000000000000000000000000000000000f6d4badf78d9115d93783a59ec9576fcfd87a2c29e1c506b6f7e313e71723811a36d64b37650fb6f7b460105a7e13f1", - "Expected": "000000000000000000000000000000000f20b3a6505784681331208b573d3a241706692db71b5daf4e9c80adb1fa9bb87023d7ba7f9c65158653c735dee9dfdd000000000000000000000000000000000f7f357407ca6cc5c5fae4b84509d71b2f4de9af226cb4038b4820c0541d4999b7396608efd2f322a00a768129f9800400000000000000000000000000000000138dcc1b9d978adb5eee6356980cec5d18cfbfbf18cf6fd14f4119a563f473f5027af06342e84ea858223ed63d1a16af00000000000000000000000000000000012b63f0d2e8ea361d55aa617a99e066b5feef3af1930b83d2a48b527e0ef304ceadf7cba1415db80c54fdcbbcf66d14", - "Name": "matter_fp2_to_g2_75", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000005a54ee5e3dc05c38ade7a42c71baf5a1467938f97c0cdf0742441cd339f22542b1ca6cd215d385b3fd6ba74ec996a4d00000000000000000000000000000000051c6f0ce621e8e27e5017628690fb68f0fea27d67726a0a77b0caf9f524936e123ff096168ff2079b9990c07fa80354", - "Expected": "0000000000000000000000000000000015ff2aa94f802d8f9c60ddcb43aee598239cf3ab7f90f8289a487b673f6065f8d9bc92bd4cd28df4a7b0d3bb78fad243000000000000000000000000000000000884b5d4ca3c8abea737cfca05878528890b6cee9bbac0bf027df5d4e0add431829caddf4c1e001818581ce08686eeed0000000000000000000000000000000019b91a7738fde9760240b335457955e963030848e85717858f22dc33ba5a4721156cfdd7341aa86d10d268e2fc9a1d26000000000000000000000000000000000af85e60161795906f3cf705f5e8cb8c15083a90836eac78445c6bc27ffbfc8c2df3009b436989b46b271dd8d1dbc282", - "Name": "matter_fp2_to_g2_76", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000094e958d9b7dac39fa4f0143a333b2ccee09046cd23e6a1c0712470a3c2e61d2f8b85aeca37350f71d7ec75aea2b3b6b00000000000000000000000000000000080743cdb5e359e8b8ad3485d53ea286669ad66d841945296edf80dde77b20a158e2c1529dfc33a1fbecf177d75a0c69", - "Expected": "0000000000000000000000000000000001bd1fe6a6c373cfdc2bfd488b0c942492b77d55b2560824edef3a91c711ee336bc1366690be40949d04edd39ad48a7500000000000000000000000000000000161476946a5687113c74a34284f49b0658e323fae57aba88b039eae584d6ef28adca669fb083a2fe8f0ef664eb5b957d0000000000000000000000000000000007aead870ae09a04cf9c9fa49d0888f7010782cdc5a0ade4c1340ff15d99cb39b7412d66d4147b95601fcf5a39c39bca00000000000000000000000000000000095cce83dbfec12973e27627bfb2d93fa9a027a2c2af4259a0879d6bda055d74559fc93fb3b4f6b0088f702af29a7643", - "Name": "matter_fp2_to_g2_77", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000dec04526dbf7666d2c29db5de1ef0b3da85380a171d871a57ae3df364d2754fceabf9d4d2a3da1ecd94e377abc78430000000000000000000000000000000000d19875fe988ffbd0cf1e9bfefc7019579962ffa3a585ee232615e4a5fce0a07bce0537b203ea00010a90ec05d5b8de7", - "Expected": "00000000000000000000000000000000133cdf684c3ff1cdaf07ff787b57a66c215eef06acc2aec4d726a086480e7b2a5dead2cb357d99e298df32d4c6f5029b0000000000000000000000000000000019cd65b830fb17880f40e104ed63a7d49b0fbad8eead7502f18f1b9f85f3f6ba6c275b8a242effc61a7a5d770a4fdaa700000000000000000000000000000000039aeacd163862e476b17a22c76042d7896a04f158489ae71afdd35d27106a3ec276baf5c08e3eed4b3f0a79c3c458d200000000000000000000000000000000125a9bd770c1fea2155a581211bd71d55eb1966645cc892a05d32cf1e4e5b23278ea2fb1336bba7f2c887debe4a93b52", - "Name": "matter_fp2_to_g2_78", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000016dd03f0df71b183e42cc29c665f18d57637b65f05df85aed9a0f7b8aa37f7913f6606c10f24a7a8c570f485905583a00000000000000000000000000000000161e62d8be678a114fd4a99a6caeb9481f5eaef145571152fe8a6ed77a34c06a1b6ff66044102d19a94abcaaeb254e73", - "Expected": "0000000000000000000000000000000007843268081f61ad2b3f6653336a99086381bb4da4c23b7d59b9c7827f2d4c196d136508c8a1f3d2f939e8c9799b95e10000000000000000000000000000000000e2c57ad95f762115d8230320810a4ea9978e26ca17decd6af4c112789608967a92fafe3fb3e79539d75d1c0bae97740000000000000000000000000000000010951c9839db9dd6ca5ef95bd1b1b9cf60bfd97cf88129fca23b24f19c9d5c71486dffb762e92f23d2a9e9d462556f620000000000000000000000000000000013d35c17b3763fc5db46ac8c44aef996f3f876c49f5278b7c97e844f23ac49f2d50b3af080322d30ead873af7b4257e1", - "Name": "matter_fp2_to_g2_79", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000036efffcb0c6f42109bf9b8b7421e32fa3f855373345341e6000eccaca135ef3b2e1c0151bddbd46ae92185acb847d74000000000000000000000000000000000edbd7a40f3e688eaff5e29800159b8d799df07e81f65d59011e84329b4689a28a15ce11537fb560df705be26bf14b1e", - "Expected": "0000000000000000000000000000000001aa1919a50b5bad62b839d672d5a11ad345fcc61f75eccc42990e113deb8a486423d1b27e7c81536d8a5799986b9408000000000000000000000000000000001879295d2f7bb3923ec61c063ee4f96d7d7cf7786259e2f4cbc3ccffe7e114af264b3527a5e06dcfad50ec1e2a9c1ae0000000000000000000000000000000001042632662e406c95f3fd44a6d956e526907147e7e6d4219c1c4b28a31e479974d00d4ad6e683f6a834d3d4a20830f4b000000000000000000000000000000000a29ea98ec25e7827bcb349ccdb2a57926809f3cce44d5ff6cd636460278c8103b0db78fa580e9edd4ecd0bdb21018ff", - "Name": "matter_fp2_to_g2_80", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000974c7d17cbf91947ad435b30ad2b639671a43d67da6a4edc7f8bdc11fe817d4d42f687dd642a2be89c81bc36e8df592000000000000000000000000000000000efeeb85860877abdabae35672a77ca9d2cf0ed18ed209fb905b591a841c900ed06d2c32c56bed5f7efd469d369b05b8", - "Expected": "000000000000000000000000000000000c67498c6751cc27d871b8711c4739398c501a5bfb688d7e1a73dc7db5c47c3e28b633078cb83745bf5b0d5d2dde3ce2000000000000000000000000000000000c205c03305422bd44082715b90e0a0ec178003d6f5e14a0d13bb0f2c38f2270816b884b4870b75db44ab080f88a35e2000000000000000000000000000000000257f378935772d326710ec6efeb22f8c9b6b549c8a4c0205b75740047d750d73da4e71aaa8ff33b9bd8ab7621b08e62000000000000000000000000000000000c386a15f09c849be9f449a59e1332a1e7f16a9394c8de198c01399a05b0f963921c4c57d49916407ae0d202af8da32a", - "Name": "matter_fp2_to_g2_81", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015333364f4d0d173ef35e447fc189b9d65ef71b9fc4ecba25fb6c8c1bfe8467f26bb9c55ef10bb34125d714b94aa1df1000000000000000000000000000000000cbba9d8ac191032f03c0746f13108962130c9e2c01d47f01174a4c4d3daa7631268f7dcc08dfda317bd249fb6e73e8a", - "Expected": "000000000000000000000000000000000864da537fd94a9ff1bdae733f01e145dc97a894733d0811cd67c2648ba61d0b187241f9ec69d8c011f514894a05a608000000000000000000000000000000000a53ea4ff9c0ff71541ee21127a33daff2b39e74301946a86e51dc7834717e7d8784cf92fa5845bc0613b6b869003f58000000000000000000000000000000000582f5a1fcef3067dfcdfabc6af33871114538abcb02fcad761cb496020c7b423fc52f0075916f160fbe03574df97ea4000000000000000000000000000000001244ede8ba0dc09aacdc5d9f886e59bf963a25885dbbe2c3d1f611bfae82debc556ec4c94f0606492c7b8c7bf976ec34", - "Name": "matter_fp2_to_g2_82", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000781e980c167c982c2fc8d0baa3907bc5499eafca675ae20a10b25063c9088fd06f6769df505e5900bcaf99e266c052c00000000000000000000000000000000183c12798438ea92db75d5bf76cf29d320fab3653e4131989205f2817aebcb1b13f161864c084fd13a11459d7d5ccd92", - "Expected": "0000000000000000000000000000000016c334aec0e19934665596f0ae37eb398f1d6f0d0c9f08189f1ccc219230395124a9da03858bdba13ec5366da54228af000000000000000000000000000000000b156ea34ae7b5c252dd90997f1c693773a463c26935a69bcc0599b95bde9e6aa31649c48b6ee4ec1f0a56b19273a5170000000000000000000000000000000014b2d69e02418844effcbc0d564b2721deae2872cd1f27f61d544fc0ebd5cadc77c6777ec944ef0500db181a5443618e0000000000000000000000000000000004f0d48a25c1eb81233f385af17ab6abf554e1285b669eeb5e884c64d5815fd5fa1350bb361997cf2e317f7c5e9cd19a", - "Name": "matter_fp2_to_g2_83", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000879133a3c0e50c90abf1a6ac75bbeca1121c865ef39e9224ddb160eb725e0850a34aaf9014e42174966773e40e4c99a0000000000000000000000000000000004c66f8f5bd462cb27e9f5e1d93e322bd97582b9e81d07b2877103420262e4cfe6d0e3bc07f9f160701fd754793eae33", - "Expected": "0000000000000000000000000000000003c0d6b721cee4e5fdc6a02095674a58075f81b1d28163f81d5b258c82634297009e6bfc8193969e23e196cf7a99ad6c0000000000000000000000000000000013229818411c8e55e50a63df6983150c1d5ead828711131d9c81841850ed76e4712954d3225eb6d7fffd3cb9924f7497000000000000000000000000000000000f42d6e4d5a28dbfda87c806cb0b1bbabb745e63e655c3c6be50411da4dcdc745ae50f71d56e88db8454d40375e325810000000000000000000000000000000000f663ab791b48f76d358e66e8cd8fa40848dff2bbec758ce1d7b3fe02d1f6b3f123cef644d4fd86d6a77b8155feae58", - "Name": "matter_fp2_to_g2_84", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a7e855324ef471b8fefb31967cec84d57953407ba555b672fa59364b303030cb02b6c77933cc63fcd1b8c107b263554000000000000000000000000000000000b50c3f7cebdcf538820113acdb017fcd5d41a4fd679af8dfde7b0c330e3576ca79d09eedc724a93a3f5c90d141e7524", - "Expected": "00000000000000000000000000000000197865f685e78a8842fa79ddc728d507e9f31b31666d1952a46f6422c97c83fba3087be70e3bb588260556014523f74000000000000000000000000000000000131f5d85ad3beaabd129d5a5675d90ea911ebd02cddb5ddc7a8be28c33061430d684d123d5c516785d21ebf756c99195000000000000000000000000000000000c7a14948f3aa29f845e5ca9877db9f0477af376eaeb45324c21e6f99e738aeec96b89af4df942bffbabbf50172d8e5b000000000000000000000000000000000ed4aea3cb585b0d36972f9ad6943172ca7375b44d1d6e80e0bf97a0b25d74deca4d35ce865c8747f1c7a2771a37c667", - "Name": "matter_fp2_to_g2_85", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001706830efca18d3e75ea0f1ca8af23a816017ceeb045694cdbad6d3d9aa5a9ddb123f5097a226a217166de3a82038393000000000000000000000000000000000402132ac383a2fcb17fe73398273ef0c2f2d0d6edabc78f31080d3ecbf7c249ffeef28bb8b37a6ef2a7d726c070dc41", - "Expected": "000000000000000000000000000000000a795c2affaaecab6cd2cfd6c8fab6e35cdd646e9cfa7b5e02400ef4abf839a69924ea80152eca7810a5041d1bf58ee800000000000000000000000000000000121426bb945d6f6b385c98a5247b7dadaebd3375dd8b2bff7aa77fddfbe603de89e77baf0e8f36a924c707c53d29a1450000000000000000000000000000000007a6fcb486634186f001c8b99874f0a07a37f1ff4b30599d2f570f1bb4ff290b816547f6ce8b3c1ed33e57630a1d57ab000000000000000000000000000000000fa65924a8f17414eb7dcc54f2a4134568484e91533dd21fd33cbcc37a920f2804516a64f1986e9d887ca189179d07c8", - "Name": "matter_fp2_to_g2_86", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024beda2b950efcee233435f0c748e33aa928f54ff29d3db217d7e32b1aac5f4ed11705da4fb8fd38481382486e4aef7000000000000000000000000000000000c85283ad6e35a72d07b74775df1a4660113d50b51426451f454a575adf9cbf9d7be3f521649f6c367c4f4c74b67ff6b", - "Expected": "00000000000000000000000000000000049d9ac43e31faa3d02f8255d207b82e4b27e8a9a61ba45fc4f9ad8048e5f89b58d25d98253aabe29334e0dc09d1cd6b000000000000000000000000000000001544f90a0baea38b48d89bcb337cf5a80faaa79334733b7e6126f55358a7e498aeb61419065b9434cab9d10fe8e7fd9f00000000000000000000000000000000139bdd668462a1b5d3ef1299d47aa91ed141ccbeba5b08a8ee31b023aa78c16514a97ba08abf5c8bb1abbd85b3fe87350000000000000000000000000000000005c7dbb8a22403a96aee634cfc67ee6f1069cd61a1e1831e8faa9d7e1aa5e4f7623f51f2e5b739f7fcf3b4ba77c82ff1", - "Name": "matter_fp2_to_g2_87", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000cb18f477abe58af92116101c3f52ad4f6074ed92a08c3adcc6660b555df9cff09dd8b34e032ed81e868a62bda50378d0000000000000000000000000000000013c4ab1558dc250c3b5d0f0fae3db62b8df969bb41e9ecc24c10e1e51cb399f1368bed7375a9b9ad9c7653c868eecfe3", - "Expected": "000000000000000000000000000000000b8b8bf2b25c2386e5f3be4bdb387d8005cf055e68ab9a5606f17dbedc4fbd7a11314fd646d08bbd6e394485d4f56f5f00000000000000000000000000000000173a45d766682f82ec2d69aed1d80ede2477c276ddaa8fb97f5f4d0515b2c2e370c615cd81c1e361f95db855c9b1b6e200000000000000000000000000000000115868a9187a0465a9309054e865ef224ec3c88a5eafbcc25f9a912ee3b19084757a90b72a4038ba71b10f59fe2f93100000000000000000000000000000000006c5476eb8aa1a471d289af52c7d1df55f6bb1ad53d7eaba6bdc2a97fcb24ec480f9d8e12079d366f2213194c861f016", - "Name": "matter_fp2_to_g2_88", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000188f650fdc51b970d16c0637ad5e97aade93c7f1398751439484ec6cc56613814908e51cfa7f68da9d980bb9dac47a400000000000000000000000000000000081834f86f1310135a2cb03265f37d9b7c9459bb149bc54b5a61319a7cde36c6a2a0fb49f8f1fb9d80f07b84f799119f", - "Expected": "0000000000000000000000000000000016e8fea4d09831146fc35bcad28e441f2c02e4d17838e04dc7cf909b2133297a13f07ee927722f3d78e36721d6848e3400000000000000000000000000000000114dee8b3a47269e9ada05ee015a874d1cbdfff4acdf5310642f829efd08f78dd6110e1c7a514e7d76aff52046f4ed140000000000000000000000000000000017b9d23f7a865a3ca61197d841fd9195805a9e883d79dc7d36e82f504e6689ade0e84c70a5c5c516fac3e3c643942e160000000000000000000000000000000001ab82b2a0986dec3211507b8adca351829b0a13f25e281f98f54d9e0e32280ea4c638dcb74280eb747a0d9af43b6b74", - "Name": "matter_fp2_to_g2_89", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006f66eb49f95f51ec90df86254580f0ae57862bdd8b5f2759ace63c5f14f8c5a762207f744bb82a8962f8c4fa410dfdb0000000000000000000000000000000004e02a80628c30ce336eab890fa37a227f77357a60be72cb87cc2b7442d2163d395fdc59350624ca1322bfe8619a2efd", - "Expected": "0000000000000000000000000000000006bc2ae646a603a1f4524b445cdeb99914e4ed19cd0676d511764b828bfe126e81cad2cb566655f04de1a302c14d70bc00000000000000000000000000000000023bd509aabfa41385e90cd4b1cbbfa45d066c4defab56993aaa386dc5b7707b1a3a7d444b8bd295a30d0b8f4bdc572e0000000000000000000000000000000006f82e60e18cc958375cce6f465db461ff46ed9d15cfcc01a3aff455d54c77ebba5a654c2ec788b6ed8ac53c39defdd3000000000000000000000000000000000896fbe6492c4c297f8b6d60295a7f2565734d69eea67b2675211a203fec043f0d181b1348bea425a068b7bc12676ed0", - "Name": "matter_fp2_to_g2_90", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001451bcd19495cea3a19393b77760f688fbf17b107dc131c88cbb503eee2a804e2978d6e8a4720d144083d28be73371d70000000000000000000000000000000017db715e8680a0e82e18b513f2c9c7ea136cefe8add71aac6baba146e3e33a498d025c7e0808ced306c915eb02900c61", - "Expected": "0000000000000000000000000000000008604a06a198c3e11458de920176842221667d024f9c155892485a37ff56252be1dc629a6fd580fa41f5e598a23f3651000000000000000000000000000000000e008eed25eafeaa67f27e89e1f81b469724a4b00f08dc4ae672aa1587b19dc615330e3fce0fbd98d7526bc2c4afe69e0000000000000000000000000000000015bc1e4ea5ae2a7fde6d5e5c3e58f6ff5df5bcb125ab402f10edd09087bde39fa27dfcdce7d04fd18ce399729e155fae0000000000000000000000000000000006684e9be8bf9fa4badda842a1d8840f0820d9a797e482c64f4004a18cd63986f19abfc93f6bf068d38eb1e491cabbe6", - "Name": "matter_fp2_to_g2_91", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013a6e129d4dd4aa93cff5489ee879763e2a2231939e609d2d72f07e630b37d09f3057a36fd5cdfc9c81675c996f8ba0f000000000000000000000000000000000e8d7ad082e8f9a718fc2ea712853ed9ab4e8b1a8ca9988f77c70fc759f1fe2d4bd73696e539f130be13b2862efbdf77", - "Expected": "000000000000000000000000000000000f15c3d0b40735babb2e38a2471773faa16b2fa307c3a573ef4cfa5a5559574b2d26cf88b19dee204b77f6e11a1b927c000000000000000000000000000000000d224445f3d31d381bb29c4fdc8130174f5bcb957f451c92f4a652cc3d2b5df985017133a944849b5228a88f99bec771000000000000000000000000000000001338b48bc1fa229f251bcd4828654baec9d149f090b19596ad3b444eacc7bc583f97d9cfc40d5611fdcf89cc9a88e33b000000000000000000000000000000000c30dd2aa51f6577d57175edb3ccc1b324717bc195eb0073c1dff4e5b0d77cf5e41ec233527b3936994e86303f91b172", - "Name": "matter_fp2_to_g2_92", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003379bc10acda5ed1014e2bba1e30cf83b72fe69259eb35476a031b8a898e0183bc32ee853a85fb3d738424208fc880900000000000000000000000000000000175a2e5a44ed62744fbbab9581ea7283470bff12436dfc414ad80b4070f895de3786022cbaed55bdbbc4f68db7460548", - "Expected": "000000000000000000000000000000001735e1f2fe905839fd6534c95b95322f8cc86a4c482f1ad7691b9b9bb8f55015b4faaa1f243786aa33b5874817cd09c80000000000000000000000000000000013f1a27931ac513145f2601e009cf637ba4bdb18a7604f89534fa3ec8488f5b6eab9963c5d753fdd34cbe7d2f8eb8a5900000000000000000000000000000000092d8f800e7a4bf6f9a25ddd7f64fc403db53b1695ae59c15f229458f347a8e7c2ebc415af2d3849282b670c5cf6f8600000000000000000000000000000000019d22d694e559c55db63521e7b60a1a2342c3cce868d70951e5ed32ec0f5efaeab0e78b21359110f6e769776b745938a", - "Name": "matter_fp2_to_g2_93", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b384a9db472c38a5d246da56059b7630f002b5f4663abce7c5f6e896222a1ca1ac02883a1ec95a4ef09bcfab7d0652a000000000000000000000000000000000de09ef45aafa56936e446e18ef9ff97ca8b81c295d35cf7b72416ebd80586d0fc479d86c23295ac54a23489af045ebc", - "Expected": "000000000000000000000000000000000d7dc499e5213120b3ccc173c83d3c15dde9e13ef57238cad84889243b35c8e69eea2ac7ef7560051dcd7402b46b733e00000000000000000000000000000000063ad31c17eb17d39cb4b33e45a0b0e951becc11b685b10cb45cff268b6dca40b780f7e1532be91903372c413a11b5be00000000000000000000000000000000140da959456cbd34e041409350d6106ff65ce6dd2ac3149f04959b16eb83dd0456ca11e5990daf4a1e5c23d3f30a6c4b00000000000000000000000000000000195d07ab127d49baf89fcf5eea1f5e4cffea1a577a5c864c0e637fbdfa10182adc1d5d4ebb871949300193e45ae0fbdd", - "Name": "matter_fp2_to_g2_94", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014df33e7d3ef2c339b958fee667097ccf146556261f7db4b0b0a3c29897b73a0ca249866cff1461488012bc16df43b0d00000000000000000000000000000000099dda253a43b8cfac580306267d9dfeb2c129ac1818fee43c6df5e582f5fa726ba73e1a2ef6a9e011a387c393529678", - "Expected": "0000000000000000000000000000000013ec1ef25b303fe2f10a0bbe9bd77a4b2a055e176c2870c99e63b4baf2b313a835459263351dfbc25c22ea32946d8956000000000000000000000000000000000cb1c3292a2e0c9b1c1ff43cbf7595f39c00fd413b54782681fe75a6f5f231d13912f8d598dd8aaae8159de083dccd8e0000000000000000000000000000000005385f2d4bb6d94d67b2a3bacd3aae31da282707672252c0ab1a12fc85d8e9b9eb75454eb145937542099b860f9d6dce000000000000000000000000000000000e59506f7733a38a7e1da4ea5958de4755b52a9307ba2e5813131b33b86f0e401f97594d9674ff1667068a1ec3c9b145", - "Name": "matter_fp2_to_g2_95", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000011c89c8d7e83155a308b2e517a23f05a4a55353332292b44b0a891b6f730fd126bd0b97eb87f0fbdb6c82779791d022f000000000000000000000000000000000da6f02450955bf26e236ec63aaf80a018ac34fd8784bb24a22a1fc5e8bd686244a923009a10cb38b1422534d0997afd", - "Expected": "000000000000000000000000000000000f4392a41fb3e58dea97b97fd22e2fe6436c3f9bbcd944585a76a5f1a8f98ea4ee21639208d765b6c3a7d08f8cd3f3f00000000000000000000000000000000002c3d62794996dbb881b665eece98926f41a42c21539125fda6070d9f69e29e0557c886b42e4bcd97b14134d6e9d1d710000000000000000000000000000000004b93f315822aa1be8250c2e736727d390ae3a862c4c7dda452817f70f01c73e6f344df1b0f05f03bd574edecc70902e000000000000000000000000000000000731403981fd6243d00c23d0a42a759016f7907548847743f18421f51b1e72cea92f0c5580328babd4ae3e15bc9c56de", - "Name": "matter_fp2_to_g2_96", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015bb227b5c9ccfb8390edcd158b04a69a88a3b99a10ae90e548182751a16448df25493061afde2c9790a0e75e6f409a20000000000000000000000000000000001d7b609155bf3939192eee9642032e6fb10f57d53916674c60211a37b4a7662759899a9569e2dc730febd23f747a7a3", - "Expected": "000000000000000000000000000000000b35c6294b70336217eb9334ff1f1bde9d892d109e947de7f4f5681b3830ed00ad1b89ccd7cbad88ce1586449140697d00000000000000000000000000000000032691e5f4597c06496e9e37907041ddcadd18ca8ce64a8b400b1e2e8d63acce5533231edb66b69807fa2dc026c1d2be000000000000000000000000000000000773ccd132cb215cd98aa17d7fc432e0577b08d8faaa35199000d46fdeeb954e8652566384fa0cc5bcd1724942f7075b00000000000000000000000000000000112e951db3694944fc82fb980547cd8b7f2e5ec6fd2051b6aff2573797bd6a28437848ea0627054af1960ad1de0981e5", - "Name": "matter_fp2_to_g2_97", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000017599d71686e817cf58b78dd7586d5b359999b32b0dec2d67e33fb6388411418ecfaa2670a2cc9dce3dadaed0fb3364000000000000000000000000000000001773995b540be9ffbfd276a92c0494e4eae296d094f9f7eca975cf4f73ae05e92bd64ea71ac47bba534044f4072a6591", - "Expected": "0000000000000000000000000000000018f2eace212eacabd44ff01d886543410ef72b4d27f8d25cb080dbe4b1d4b2b4e57e4dd40723d15789d9b5104b088d9b00000000000000000000000000000000098e9e9b302876ce85ba486609fd028f357314149ce8b530778e6de586ab057fe59648d8c8ae80fe619c4c605b90784a0000000000000000000000000000000016d20a8ca43d37518c8a0f47566ba61a7aade9ea2cdd4a0907ff0ed862c6b7c64815d50397eebec262a05c6010cfaa790000000000000000000000000000000005a70c2fce25acdc4a95fc2bdedb007d71f24b0b5714fa14910ef590215d25442e91a66b6bfea5f7777f0c6d202eff32", - "Name": "matter_fp2_to_g2_98", - "Gas": 110000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f470603a402bc134db1b389fd187460f9eb2dd001a2e99f730af386508c62f0e911d831a2562da84bce11d39f2ff13f000000000000000000000000000000000d8c45f4ab20642d0cba9764126e0818b7d731a6ba29ed234d9d6309a5e8ddfbd85193f1fa8b7cfeed3d31b23b904ee9", - "Expected": "0000000000000000000000000000000012e74d5a0c005a86ca148e9eff8e34a00bfa8b6e6aadf633d65cd09bb29917e0ceb0d5c9d9650c162d7fe4aa274526850000000000000000000000000000000005f09101a2088712619f9c096403b66855a12f9016c55aef6047372fba933f02d9d59db1a86df7be57978021e245782100000000000000000000000000000000136975b37fe400d1d217a2b496c1552b39be4e9e71dd7ad482f5f0836d271d02959fdb698dda3d0530587fb86e0db1dd0000000000000000000000000000000000bad0aabd9309e92e2dd752f4dd73be07c0de2c5ddd57916b9ffa065d7440d03d44e7c042075cda694414a9fb639bb7", - "Name": "matter_fp2_to_g2_99", - "Gas": 110000, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/blsPairing.json b/builder/core/vm/testdata/precompiles/blsPairing.json deleted file mode 100644 index 138b13944..000000000 --- a/builder/core/vm/testdata/precompiles/blsPairing.json +++ /dev/null @@ -1,702 +0,0 @@ -[ - { - "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e8490000000000000000000000000000000006e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb9090000000000000000000000000000000017d81038f7d60bee9110d9c0d6d1102fe2d998c957f28e31ec284cc04134df8e47e8f82ff3af2e60a6d9688a4563477c00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "bls_pairing_e(2*G1,3*G2)=e(6*G1,G2)", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d2800000000000000000000000000000000122915c824a0857e2ee414a3dccb23ae691ae54329781315a0c75df1c04d6d7a50a030fc866f09d516020ef82324afae0000000000000000000000000000000009380275bbc8e5dcea7dc4dd7e0550ff2ac480905396eda55062650f8d251c96eb480673937cc6d9d6a44aaa56ca66dc000000000000000000000000000000000b21da7955969e61010c7a1abc1a6f0136961d1e3b20b1a7326ac738fef5c721479dfd948b52fdf2455e44813ecfd8920000000000000000000000000000000008f239ba329b3967fe48d718a36cfe5f62a7e42e0bf1c1ed714150a166bfbd6bcf6b3b58b975b9edea56d53f23a0e8490000000000000000000000000000000010e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc0000000000000000000000000000000016ba437edcc6551e30c10512367494bfb6b01cc6681e8a4c3cd2501832ab5c4abc40b4578b85cbaffbf0bcd70d67c6e200000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_pairing_e(2*G1,3*G2)=e(5*G1,G2)", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a9000000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf100000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab160000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb541170000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a70000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb3000000000000000000000000000000000029ea93c2f1eb48b195815571ea0148198ff1b19462618cab08d037646b592ecab5a66b4bc660ffd02d1b996ca377da000000000000000000000000000000000bb319a4550c981ee89e3c7e6dcc434283454847792807940f72fd2dbf3625b092e0a0c03e581fd9bd9cf74f95ccef15000000000000000000000000000000000abb072b8d9011e81c9f5b23ba86fdb6399c878aa4eadee45fb2486afe594dffc53be643598a23e5428894a36f5ac3ce0000000000000000000000000000000005d04aa0b644faae17d4c76a14aa680c69fdfc6b59fee3ef45641f566165fced60cbbda4ca096e132bb6f58ab4516686000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436000000000000000000000000000000001065f2a2d29a997343765f239c99a018490eced40ac42fc93217dfe20d8b43ee2215f65166aff483b3dc042c5a43b196000000000000000000000000000000000766e4c66f4a442ff1f61a7a4d197d2b47dd226d0e7822a9b065108cfc643cd3f3d5ae59ed2ce4cde13fd9260bb5b7cc0000000000000000000000000000000012251cc6abbabeb7bbe1fdd63eaee10832a748fff24f7e3fdccaea87facb6e99f2e0407a38f27f90450a471b873104620000000000000000000000000000000011181e08c8fba91271adfee9d31681f8412ab7a3f754f7ba4709024c0ad2287e32dd455d71a296b4838072a8ab9d96f2000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f53580000000000000000000000000000000005a7445f55add1ed5c143424ceef3d594280e316c9441a8e68c3ad97377141d015bf878bdfcf0df9fbcd0529f4e8100800000000000000000000000000000000192b52ba08ed509fc84d5775a7182498fd1ff80941d673c53470c9c9f1192f9c0057d68a1dfee0c68fe5df3625cc43bf000000000000000000000000000000000d3fcaf2f727e0eb32c65da9b910dc681b948dda874d0db6f6ed3f063430fbf073385a9a14c2dd78568726124e2b3ea8000000000000000000000000000000001943ce22cdb2387bd5796950dc95d1ace4012ab9bb4afb46223760230c1709e075f1ae76d6b3f2e947ba6b16d458ccd1000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000a29e38da2d42fd4712052800c7c8dd6e94fd9f506e946068aaac799d60b94c2d7515769ffdd32ea95d3910330ec47de000000000000000000000000000000000c60dae92451206390e30b5daa7151d63624dee496753c87dd54eadc92dc9602081fae02a1a53bac97e984a571923a5d00000000000000000000000000000000085f4fda4c72328895f20c683cb49603a37ff2c43d62f66602506dad5b8d1daebfbac7a7db3f50ccf4dfff277deb105c0000000000000000000000000000000005674d005457e0fe1f0fd978d63996c5f3d29f9149ee4eb04c464742dd329ccaef5e5f6b896d986ddfc9f1b2a3aec13100000000000000000000000000000000071bc66d6e2d244afc4a5ce4da1dce3d0c22c303ba61310fdf57843bbd97763ef496833dfa99d14be084bb1a039bb2da0000000000000000000000000000000012c22e047b0af8e2f4bf3bd3633ef0f8264004ca8ea5677a468857a1762f815235a479e53f4ad4741ffda3fb855021c900000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "bls_pairing_10paircheckstrue", - "Gas": 345000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a550000000000000000000000000000000004523f5a3915fc57ee889cdb057e3e76109112d125217546ccfe26810c99b130d1b27820595ad61c7527dc5bbb132a9000000000000000000000000000000000186a1da343cacf1815b9c8b6c807f536249dbfdb59d77bf4920ad2198a0d83ada21f7c39de6f06a5599f22571cab288d000000000000000000000000000000000ba1ec44f95121bd622932b84bbb4b3d279f69c494ee44db68e3165c86b627ba5e397ee197313fb5b775972798997332000000000000000000000000000000000783e7493e9fb106fa0d085e7c03eb816468d12c65d9b77643ed07c02583d491f4db5db44e565d50d8ccaa9ad8f7f8e80000000000000000000000000000000010a6a5fd90cd5f4fb6545814f5df065b001074bb3f29f649dd2612815df3a19a320f7754dd3d458e48e7fb1b4953978f000000000000000000000000000000000345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c00000000000000000000000000000000083d3baf25e42f2845d8fa594dda2e0f40a4d670dda40f30da0aff0d81c87ac3d687fe84eca72f34c7c755a045668cf100000000000000000000000000000000129c4945fe62538d2806fff056adac24f3bba8e17e42d82122affe6ad2123d68784348a79755f194fde3b3d448924032000000000000000000000000000000000528590e82f409ea8ce953f0c59d15080185dc6e3219b69fcaa3a2c8fc9d0b9e0bc1e75ec6c52638e6eaa4584005b5380000000000000000000000000000000018dc3e893f74729d27dd44f45a5a4f433dcd09a3b485e9d1c2bd0eb5e0e4c9024d928ddc426fdecae931e89885ee4db4000000000000000000000000000000000d6ee02e1fc7e52a8e1ef17e753065882c6fcc14da61da7ffe955fe84a9d2af9ba57562c69db3088652931bf124b0d5300000000000000000000000000000000051f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e000000000000000000000000000000000b6a63ac48b7d7666ccfcf1e7de0097c5e6e1aacd03507d23fb975d8daec42857b3a471bf3fc471425b63864e045f4df00000000000000000000000000000000131747485cce9a5c32837a964b8c0689ff70cb4702c6520f2220ab95192d73ae9508c5b998ffb0be40520926846ce3f100000000000000000000000000000000101e147f8bd7682b47b3a6cc0c552c26ce90b9ce0daef21f7f634b3360483afa14a11e6745e7de01a35c65b396a1a12700000000000000000000000000000000090ca61ed16c4c1e80acfef736eea2db0d7425d9110cb53e6c4a2aa3f8a59ee6c60bdce8df5825011066d44bef84d29600000000000000000000000000000000028207394adcbf30250ac21a8f1db6283580bc5e39159930552e5edb25e6215c66b6450296edc80dbc3a2acd125dab160000000000000000000000000000000019bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3000000000000000000000000000000000adb3250ba142db6a748a85e4e401fa0490dd10f27068d161bd47cb562cc189b3194ab53a998e48a48c65e071bb541170000000000000000000000000000000016cfabbe60d1e55723a0ff72cf802f2d1cf13ed131e17729adc88522a657f320a336078a9399c8e61a3bbde3d52fd3640000000000000000000000000000000009aa9a3c2a6d49d286aa593c6ff644f1786fa9ae471bdb3fe70b150a9ed7584eaa886ac057c30005c3642f65ad5581cc0000000000000000000000000000000001d417894c0cce924955a795b188b27951f8438a5485404b921a42fa79dea03c10e29d0390df2f34d7be13f360a7fada00000000000000000000000000000000189b0b3a04e6c613899d51231dbf0cba6a8a8f507ebed99d24fba7ebac6c97a8859ffde88e6d95c1a9d6b4f0a8f3c417000000000000000000000000000000000d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a414950835820000000000000000000000000000000009d0d1f706f1a85a98f3efaf5c35a41c9182afc129285cf2db3212f6ea0da586ca539bc66181f2ccb228485dd8aff0a70000000000000000000000000000000016cad7807d761f2c0c6ff11e786a9ed296442de8acc50f72a87139b9f1eb7c168e1c2f0b2a1ad7f9579e1e922d0eb309000000000000000000000000000000000d3577c713fcbc0648ca8fbdda0a0bf83c726a6205ee04d2d34cacff92b58725ca3c9766206e22d0791cb232fa8a9bc3000000000000000000000000000000000f5ea1957be1b9ca8956ba5f6b1c37ea72e2529f80d7a1c61df01afcc2df6f99ced81ac0052bd0e1e83f09d76ad8d33b000000000000000000000000000000000aabced4e2b9e4a473e72bf2b1cc0ce7ab13de533107df2205ed9e2bb50fa0217e6a13abcd12fce1bda1ccf84dac237a00000000000000000000000000000000073eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086000000000000000000000000000000001825bacd18f695351f843521ebeada20352c3c3965626f98bc4c68e6ff7c4eed38b48f328204bbb9cd461511d24ebfb3000000000000000000000000000000000029ea93c2f1eb48b195815571ea0148198ff1b19462618cab08d037646b592ecab5a66b4bc660ffd02d1b996ca377da000000000000000000000000000000000bb319a4550c981ee89e3c7e6dcc434283454847792807940f72fd2dbf3625b092e0a0c03e581fd9bd9cf74f95ccef15000000000000000000000000000000000abb072b8d9011e81c9f5b23ba86fdb6399c878aa4eadee45fb2486afe594dffc53be643598a23e5428894a36f5ac3ce0000000000000000000000000000000005d04aa0b644faae17d4c76a14aa680c69fdfc6b59fee3ef45641f566165fced60cbbda4ca096e132bb6f58ab4516686000000000000000000000000000000001098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a000000000000000000000000000000000ea923110b733b531006075f796cc9368f2477fe26020f465468efbb380ce1f8eebaf5c770f31d320f9bd378dc758436000000000000000000000000000000001065f2a2d29a997343765f239c99a018490eced40ac42fc93217dfe20d8b43ee2215f65166aff483b3dc042c5a43b196000000000000000000000000000000000766e4c66f4a442ff1f61a7a4d197d2b47dd226d0e7822a9b065108cfc643cd3f3d5ae59ed2ce4cde13fd9260bb5b7cc0000000000000000000000000000000012251cc6abbabeb7bbe1fdd63eaee10832a748fff24f7e3fdccaea87facb6e99f2e0407a38f27f90450a471b873104620000000000000000000000000000000011181e08c8fba91271adfee9d31681f8412ab7a3f754f7ba4709024c0ad2287e32dd455d71a296b4838072a8ab9d96f2000000000000000000000000000000001252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada0000000000000000000000000000000002a1bc189e36902d1a49b9965eca3cb818ab5c26dffca63ca9af032870f7bbc615ac65f21bed27bd77dd65f2e90f53580000000000000000000000000000000005a7445f55add1ed5c143424ceef3d594280e316c9441a8e68c3ad97377141d015bf878bdfcf0df9fbcd0529f4e8100800000000000000000000000000000000192b52ba08ed509fc84d5775a7182498fd1ff80941d673c53470c9c9f1192f9c0057d68a1dfee0c68fe5df3625cc43bf000000000000000000000000000000000d3fcaf2f727e0eb32c65da9b910dc681b948dda874d0db6f6ed3f063430fbf073385a9a14c2dd78568726124e2b3ea8000000000000000000000000000000001943ce22cdb2387bd5796950dc95d1ace4012ab9bb4afb46223760230c1709e075f1ae76d6b3f2e947ba6b16d458ccd1000000000000000000000000000000001271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4000000000000000000000000000000001407ffc2c1a2fe3b00d1f91e1f4febcda31004f7c301075c9031c55dd3dfa8104b156a6a3b7017fccd27f81c2af222ef000000000000000000000000000000000a29e38da2d42fd4712052800c7c8dd6e94fd9f506e946068aaac799d60b94c2d7515769ffdd32ea95d3910330ec47de000000000000000000000000000000000c60dae92451206390e30b5daa7151d63624dee496753c87dd54eadc92dc9602081fae02a1a53bac97e984a571923a5d00000000000000000000000000000000085f4fda4c72328895f20c683cb49603a37ff2c43d62f66602506dad5b8d1daebfbac7a7db3f50ccf4dfff277deb105c0000000000000000000000000000000005674d005457e0fe1f0fd978d63996c5f3d29f9149ee4eb04c464742dd329ccaef5e5f6b896d986ddfc9f1b2a3aec13100000000000000000000000000000000071bc66d6e2d244afc4a5ce4da1dce3d0c22c303ba61310fdf57843bbd97763ef496833dfa99d14be084bb1a039bb2da0000000000000000000000000000000012c22e047b0af8e2f4bf3bd3633ef0f8264004ca8ea5677a468857a1762f815235a479e53f4ad4741ffda3fb855021c900000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "bls_pairing_10pairchecksfalse", - "Gas": 345000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee0000000000000000000000000000000017c9fcf0504e62d3553b2f089b64574150aa5117bd3d2e89a8c1ed59bb7f70fb83215975ef31976e757abf60a75a1d9f0000000000000000000000000000000008f5a53d704298fe0cfc955e020442874fe87d5c729c7126abbdcbed355eef6c8f07277bee6d49d56c4ebaf334848624000000000000000000000000000000001302dcc50c6ce4c28086f8e1b43f9f65543cf598be440123816765ab6bc93f62bceda80045fbcad8598d4f32d03ee8fa000000000000000000000000000000000bbb4eb37628d60b035a3e0c45c0ea8c4abef5a6ddc5625e0560097ef9caab208221062e81cd77ef72162923a1906a40", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_0", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000117dbe419018f67844f6a5e1b78a1e597283ad7b8ee7ac5e58846f5a5fd68d0da99ce235a91db3ec1cf340fe6b7afcdb0000000000000000000000000000000013316f23de032d25e912ae8dc9b54c8dba1be7cecdbb9d2228d7e8f652011d46be79089dd0a6080a73c82256ce5e4ed200000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_1", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008ab7b556c672db7883ec47efa6d98bb08cec7902ebb421aac1c31506b177ac444ffa2d9b400a6f1cbdc6240c607ee110000000000000000000000000000000016b7fa9adf4addc2192271ce7ad3c8d8f902d061c43b7d2e8e26922009b777855bffabe7ed1a09155819eabfa87f276f000000000000000000000000000000000a69d6d9f79e19b38e6bf5a245dc820bddbdfe038d50932f76d0e4629d759f8ca6d573fcfc39256305daedf452f9fdf40000000000000000000000000000000015f5949369e58487afcecf8018775d1b0a73e913bf77e13d2e5a843bbbeba7d1978ca27ae8bfc87d30f567dd396b980e00000000000000000000000000000000182198bb38a0353b8db25389e56ab0d8679a1bda008a65dad77e4c95bc6804f6311eb16c761e1a5e2a5f87cfada49fa4000000000000000000000000000000000eb5483959e98c30e71db52615f63521378b156f142d46f3bb285b94aef39d80feacec335b797c5a68dc17ba89d43e0f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_2", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015ff9a232d9b5a8020a85d5fe08a1dcfb73ece434258fe0e2fddf10ddef0906c42dcb5f5d62fc97f934ba900f17beb330000000000000000000000000000000009cfe4ee2241d9413c616462d7bac035a6766aeaab69c81e094d75b840df45d7e0dfac0265608b93efefb9a8728b98e4000000000000000000000000000000000286f09f931c07507ba4aafb7d43befe0b1d25b27ecc9199b19a9dc20bc7ec0329479ef224e00dece67ec0d61f1ca5ae0000000000000000000000000000000014e6ed154b5552be5c463b730b2134f83e0071dcdadfaa68e6c7c7f6e17dabb7daf06e409177bc4b38cfdb8248157618000000000000000000000000000000000f145e998dc6eb0c2b2be87db62949c7bfa63e8b01c8634248010fd623cfaec5d6c6c193331440957d333bf0c988b7b10000000000000000000000000000000002a1ab3eea343cfdea5779f64b3bddbf0769aded60e54a7507338f044310ba239430663394f110e560594d6042a99f1c", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_3", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017a17b82e3bfadf3250210d8ef572c02c3610d65ab4d7366e0b748768a28ee6a1b51f77ed686a64f087f36f641e7dca900000000000000000000000000000000077ea73d233ccea51dc4d5acecf6d9332bf17ae51598f4b394a5f62fb387e9c9aa1d6823b64a074f5873422ca57545d3000000000000000000000000000000000d1007ca90451229d3780d66d3aed7c9d8fc82e9d45549e8586600e38eb6763f3c466e2f6ba6ba1dafd8f00cc452dda20000000000000000000000000000000001d017d920a262b6d6597bab532f83270f41526409510e80278d1c3595ceabb9ceba8ae32b1817297ff78ea7a0d252e8000000000000000000000000000000000935b7a59d2e51bbb2f9b54ccb06ebee9d189fa82f0e97d10c8020badb3de7fe15731b5895faed8cad92ae76e2e1b649000000000000000000000000000000000792dadd48a20040ad43facedc109747411895180813349d41d0e5b389176bfb15895d41665be8d1afa80835ef818eca", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_4", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c1243478f4fbdc21ea9b241655947a28accd058d0cdb4f9f0576d32f09dddaf0850464550ff07cab5927b3e4c863ce90000000000000000000000000000000015fb54db10ffac0b6cd374eb7168a8cb3df0a7d5f872d8e98c1f623deb66df5dd08ff4c3658f2905ec8bd02598bd4f9000000000000000000000000000000000095353ad699b89ac82ca7ef631775b2b3a6e3ed8dd320440cdb929baa428e63cb902a83857cc0e2621470544c69e84aa000000000000000000000000000000000892559ade1060b0eef2cbc1c74de62a7ff076a3621e5f0f159672a549f1201f2ffb3ac12c8b12cb86ae3e386c33e219000000000000000000000000000000000750df4632a7126ddb08658a4001f949b9764d9cc43a9393cc55d8fdbb15d4a1186dd87a6433d111888a7804540ad9fc0000000000000000000000000000000017554bd444665df044b91b0b2614017bbfcd7acc7f8c5a16cea2861235578ce2b27dcced9fba234999fa478cd3f6e42d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_5", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000328f09584b6d6c98a709fc22e184123994613aca95a28ac53df8523b92273eb6f4e2d9b2a7dcebb474604d54a210719000000000000000000000000000000001220ebde579911fe2e707446aaad8d3789fae96ae2e23670a4fd856ed82daaab704779eb4224027c1ed9460f39951a1b00000000000000000000000000000000175dadb6ee656ec6aebf8d0e5edaee3f119c74e0ea64e374be9e8ab9fd3d085fceeedf4ed8de676ebe9065d83b0542ad0000000000000000000000000000000005cd6a875329c23e4918976cf997e93e403957acfc999f8159a630d21ab6f1762925c063784237262bedc82402ad81bb0000000000000000000000000000000003274bcb8db35e50164d136c2a98b5a6d2fb5f9767d0ee11c1358bf7ca5ed96d9122f8c1051ba3c658cc89777d03dfa5000000000000000000000000000000000380a240443dff85b6542f75db28b87c39e278cdb8d9627efbbc63b229e6ce783f6fb0114c8e91c2fd6ea71c95bb99a4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_6", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002ebfa98aa92c32a29ebe17fcb1819ba82e686abd9371fcee8ea793b4c72b6464085044f818f1f5902396df0122830cb00000000000000000000000000000000001184715b8432ed190b459113977289a890f68f6085ea111466af15103c9c02467da33e01d6bff87fd57db6ccba442a000000000000000000000000000000000834cf1b4149d100c41b1bca0495e455002eb6596bddcb94ae48d0c65957e8b313372f8e0d6e57504664b266f38293150000000000000000000000000000000000de2875fbd14760bac4c2cc7d3f239177efe9f7f61f767be420d44f24c9fb863efd60dcd732986db8c5b72470617ea60000000000000000000000000000000000bc9535ebf11c2dcc8c7d3bcd09d7d14035635fccb5fddb7df29ce8855e79f99809781d6ffbbcb33d1227314609abee00000000000000000000000000000000039bbfb4d969d702255e3be7f255a97529a19687ce38cb70637c37894d4102591feef428b0afe8c9ef50310ae3b83091", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_7", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009d6424e002439998e91cd509f85751ad25e574830c564e7568347d19e3f38add0cab067c0b4b0801785a78bcbeaf246000000000000000000000000000000000ef6d7db03ee654503b46ff0dbc3297536a422e963bda9871a8da8f4eeb98dedebd6071c4880b4636198f4c2375dc795000000000000000000000000000000000fc09c241899fa6e8cc3b31830e9c9f2777d2bc6758260c9f6af5fce56c9dc1a8daedb5bcb7d7669005ccf6bfacf71050000000000000000000000000000000018e95921a76bc37308e2f10afb36a812b622afe19c8db84465ab8b3293c7d371948ee0578dbb025eed7ed60686109aa0000000000000000000000000000000001558cdfbac6ea2c4c1f4b9a2e809b19e9f4ba47b78d2b18185ed8c97c2f9c2990beadc78b85c123b4c3c08d5c5b3bbef000000000000000000000000000000000ea4dfdd12b9a4b9a3172671a6eafed7508af296813ec5700b697d9239ae484bcf7ab630e5b6830d6d95675be5174bb2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_8", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002d1cdb93191d1f9f0308c2c55d0208a071f5520faca7c52ab0311dbc9ba563bd33b5dd6baa77bf45ac2c3269e945f4800000000000000000000000000000000072a52106e6d7b92c594c4dacd20ef5fab7141e45c231457cd7e71463b2254ee6e72689e516fa6a8f29f2a173ce0a1900000000000000000000000000000000000b36d8fb9bd156f618ab8049d41dfe0698218764c0abb10e12fae43c8810b8e2a5201364e2778f6f433b199bb8f9a6800000000000000000000000000000000000707eb15411b63722b4308c0ed4288320078d2463ae659ad4fb3f9ef8124f379df92d64e077403e50727388adb59ac00000000000000000000000000000000158e1249d5b91614924acb23899c6bae408697dec0982c10d0459746499f4e6739afb9d5129568106ed1a1caefeaa9640000000000000000000000000000000019e841562e4aa75321143f8ce1e5ec6158fa5cb8b98c839a486188260c18ee8a7600930f23aa39eac2eb520d6a0fba90", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_9", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000641642f6801d39a09a536f506056f72a619c50d043673d6d39aa4af11d8e3ded38b9c3bbc970dbc1bd55d68f94b50d0000000000000000000000000000000009ab050de356a24aea90007c6b319614ba2f2ed67223b972767117769e3c8e31ee4056494628fb2892d3d37afb6ac94300000000000000000000000000000000186a9661d6fb539e8687ac214301b2d7623caedd76f4055089befba6ef2c96263d810921ad7783d229f82783c9def424000000000000000000000000000000000447f3e20caa1f99fbaccab7bde2bd37fe77cea691ebf2b9499f95bbbb77afe72b7039eb0c05970b61360fcf8ade73730000000000000000000000000000000005e11f828eda86c10a1d7929def547ac06885da278afae59c5d95453caf0a2d8ed186fa7c6d0a7ab6e9142cfa4b338190000000000000000000000000000000003d954e61b6ab71042b19e804efccd4956b56662f27f70a9255cec0c464b86c0e83721ad3785dec62dd4a9dd3d6d5d53", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_10", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000fd4893addbd58fb1bf30b8e62bef068da386edbab9541d198e8719b2de5beb9223d87387af82e8b55bd521ff3e47e2d000000000000000000000000000000000f3a923b76473d5b5a53501790cb02597bb778bdacb3805a9002b152d22241ad131d0f0d6a260739cbab2c2fe602870e0000000000000000000000000000000002b94534aa0ba923bda34cbe92b3cd7a3e263741b120240ff5bdb8b718f094d3867e3fcabeab4a7be39c8f8c4fdd10d900000000000000000000000000000000048711cf6a82534d64d072355cb8fe647808e7e8b2d9ac9ed52eb7fe121647a721dd1234c71ecd163d91701eb7331cac00000000000000000000000000000000141ef2e23a1ecc7ef2ed3ea915492e79cfffe60b5e0de8441e878bd0653843d79c724e3c5ebe2321361df99f8932ddc200000000000000000000000000000000085513b4009f29b3e00a91c2c4be418368560802ba4194cbd2f4fa3d72a55fcae547014434514a8b2a8fe3e0b28d2773", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_11", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002cb4b24c8aa799fd7cb1e4ab1aab1372113200343d8526ea7bc64dfaf926baf5d90756a40e35617854a2079cd07fba40000000000000000000000000000000003327ca22bd64ebd673cc6d5b02b2a8804d5353c9d251637c4273ad08d581cc0d58da9bea27c37a0b3f4961dbafd276b0000000000000000000000000000000009143507a24313ee33401955fc46562c9b20c9917df3b40ccbd7ed43b1349d4551cfd98a4976d6fec5fc289460c8d89900000000000000000000000000000000060566b79df5cc975e669da8ca3a7fa91bf3f5c9fb871c3d62f4a3e79dbc341b89d38b588e5414bc385d5e3cbf3ab9310000000000000000000000000000000016bf40b8cc4c01a87aafae0c4439b623a51ba9a383756a550b69d627d6f45209f0d87e4f9be9edff35c986f7b9c49e3f000000000000000000000000000000001842d9172bce51a164fbdbdb108d0faae07e4642f21c80e40ac31e737657472ae3dfe552b65349629c210a068c4afc0e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_12", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ad70f2b2105ca37112858e84c6f5e3ffd4a8b064522faae1ecba38fabd52a6274cb46b00075deb87472f11f2e67d90000000000000000000000000000000010a502c8b2a68aa30d2cb719273550b9a3c283c35b2e18a01b0b765344ffaaa5cb30a1e3e6ecd3a53ab67658a5787681000000000000000000000000000000000ab19bbddd661e9db8fe4cb307ecebdc5e03efbb95c5b44716c7075bd60efcfc67de0bfd7c46ad989a613946c90a4c1000000000000000000000000000000000120800e7f344cda816299fa37f603ade06beb3b10907f5af896d6b4e42f7f865b756f14164db84411c56cb2ea81f60be000000000000000000000000000000000f688ddd257e66362af1437b6922d3397a7c3dd6dea6bca8ebd6375e75bf2de40bc287cbf3434388191e56b92949c83b0000000000000000000000000000000005252465784aff8c1c707da58b5808c69583bf852d68f96912bc53f8dae4536b09ccbbd25a49d9e744118992b92b6792", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_13", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000704cc57c8e0944326ddc7c747d9e7347a7f6918977132eea269f161461eb64066f773352f293a3ac458dc3ccd5026a000000000000000000000000000000001099d3c2bb2d082f2fdcbed013f7ac69e8624f4fcf6dfab3ee9dcf7fbbdb8c49ee79de40e887c0b6828d2496e3a6f768000000000000000000000000000000000e3165efe00f69aee84ac56d2161f07c017abfaadeaad34f8c96799d68bae0e6f9b557bbf9137e7826f49f29c58d1ef9000000000000000000000000000000000de0dce7ea371ad60f21f2cb61cb582b5072408a7efc91edf05b36a1a3b58fd9e6cf808d75157eedccc8f1c93a8ae07d0000000000000000000000000000000016d911943d80427385ebac1d1b293914a9e4dd9db06c1d6a758192d63c8fc9368e02eae7fb0e3a7859408f215cfa76ca0000000000000000000000000000000007bfdc6afb8acec625e50ecbc08a5cdb7862b795866323679885ba5cba3fd51f181078e03fe35e96e6383c077eed1bf5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_14", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000130535a29392c77f045ac90e47f2e7b3cffff94494fe605aad345b41043f6663ada8e2e7ecd3d06f3b8854ef92212f42000000000000000000000000000000001699a3cc1f10cd2ed0dc68eb916b4402e4f12bf4746893bf70e26e209e605ea89e3d53e7ac52bd07713d3c8fc671931d000000000000000000000000000000000a68dccbe3452731f075580fe6102b8ee5265007ee19c56d95bcb096a3a6ac444f4145b980f41afcb0a865853b279bc600000000000000000000000000000000164767ea55a9038ac2dd254d8c8a4970dba93dacdf5416aecaa407914719cab165e7a32784b2c41652a86358737d831f000000000000000000000000000000000da9441fbc6578c85fdeca49082c9ebbf183de894d67c65158380ee56132d3cdb44b100d72b6d3b82688defb75d2aa390000000000000000000000000000000017d570e4f6e46550679d5d12c347414da207060f594620e2f8db66df8e0b06c912290b207a268e782d4b45db19a199db", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_15", - "Gas": 138000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd80000000000000000000000000000000000874389c02d4cf1c61bc54c4c24def11dfbe7880bc998a95e70063009451ee8226fec4b278aade3a7cea55659459f1d500000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e000000000000000000000000000000001830f52d9bff64a623c6f5259e2cd2c2a08ea17a8797aaf83174ea1e8c3bd3955c2af1d39bfa474815bfe60714b7cd8000000000000000000000000000000000118cd94e36ab177de95f52f180fdbdc584b8d30436eb882980306fa0625f07a1f7ad3b4c38a921c53d14aa9a6ba5b8d600000000000000000000000000000000197737f831d4dc7e708475f4ca7ca15284db2f3751fcaac0c17f517f1ddab35e1a37907d7b99b39d6c8d9001cd50e79e000000000000000000000000000000000af1a3f6396f0c983e7c2d42d489a3ae5a3ff0a553d93154f73ac770cd0af7467aa0cef79f10bbd34621b3ec9583a834000000000000000000000000000000001918cb6e448ed69fb906145de3f11455ee0359d030e90d673ce050a360d796de33ccd6a941c49a1414aca1c26f9e699e0000000000000000000000000000000019a915154a13249d784093facc44520e7f3a18410ab2a3093e0b12657788e9419eec25729944f7945e732104939e7a9e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_16", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a67000000000000000000000000000000000013a80ede40df002b72f6b33b1f0e3862d505efbe0721dce495d18920d542c98cdd2daf5164dbd1a2fee917ba943debe0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f900000000000000000000000000000000043c4ff154778330b4d5457b7811b551dbbf9701b402230411c527282fb5d2ba12cb445709718d5999e79fdd74c0a6700000000000000000000000000000000018c690fc5571f69793ec3c82915ac9513726ec891312f4f11dd3ba0ee95cc98b50d925099b0642e58a106e8456bbcbed0000000000000000000000000000000001c2d8d353d5983f22a5313ddd58fdc0d9c994b2915dbc87a9b65b7b98ff00b62e140a27dc322d42b3ad190c1b3728dd0000000000000000000000000000000010412f3625947b38bb380a6ed059f1677b7a7afcb91517837c563dadd0e285b95740a200ddff6570d4d92bb636b625bb0000000000000000000000000000000015f4f9a480a57bd1b2388532ab045a1ba93d2f6589a3022c585fe06a1d611165c99d70be06251812405c9c37d6e9f7730000000000000000000000000000000001a78e6c5062a6634a56e9853ff5afacb2e7cf31fd0ea5f0d8c8ac6174c88133cf2f63450ec4590544c9a0e37daac1f9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_17", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e880000000000000000000000000000000008d7489c2d78f17b2b9b1d535f21588d8761b8fb323b08fa9af8a60f39b26e98af76aa883522f21e083c8a14c2e7edb6000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae70000000000000000000000000000000009f9a78a70b9973c43182ba54bb6e363c6984d5f7920c1d347c5ff82e6093e73f4fb5e3cd985c9ddf9af936b16200e88000000000000000000000000000000001129c94e0c06f51f1f808a62e42a5449dd159289c14a09c4cc382c91bcfe878b6f3555767c310de1b1c275eb3d17bcf5000000000000000000000000000000000818e567aea83eaf3142984bb736b443743659626c407987b604a30c79756081fa6ae6beeb2e6c652dbfe9cf62d44e3900000000000000000000000000000000193f0317305fde1046acda2c9491e376aa67244f68ef6495845d049e1293082af91f880be935d9d8ad0e25ad918caae200000000000000000000000000000000109224b8178be58ea4e4a194ca66bef9d14f6fc2c625d25feaa4f32e0f4d72d91024d96839bc96e6a624c5ad6221bd94000000000000000000000000000000000e42decf8a987efaeb4ede37236b637e61249bf6245679be7fd4d633e2d814ed4748b73890ad3c4fcbcfb4960cb67ae7", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_18", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000aba6a0b58b49f7c6c2802afd2a5ed1320bf062c7b93135f3c0ed7a1d7b1ee27b2b986cde732a60fa585ca6ab7cc154b000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a79157800000000000000000000000000000000010fcfe8af8403a52400bf79e1bd0058f66b9cab583afe554aa1d82a3e794fffad5f0e19d385263b2dd9ef69d1154f10a000000000000000000000000000000000f46a7dee0cb471ddef3a50670a5bfc443b8455877f1ff602b21faff1eff07fc6bf27930ca2159f01479359548339560000000000000000000000000000000000ca0d865f8c8ce0a476f7a6edb3ce4bd5e6c3a8d905d8fb5a10e66542f4325a9963c2f8d96f804f4d295f8993b5204df0000000000000000000000000000000005a966f6254f0ef4f93f082a97abe07db56f00c2ade047d2f0027edef6f00a0dfecaa24d50faa778fa29087302211f7e00000000000000000000000000000000121c51da366557c09af1bbd927521da88dfab3e2e9a95b6effb0a968795486f281f0c887e37f51837557b9e3808987130000000000000000000000000000000001a5524975400b1e88f3fff8dd34dadf5d75564cfc0026df31ee9c2c1d48b0f69a48e1e4a48cc4b7db61f023a7915780", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_19", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b0900000000000000000000000000000000082543b58a13354d0cce5dc3fb1d91d1de6d5927290b2ff51e4e48f40cdf2d490730843b53a92865140153888d73d4af0000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e0000000000000000000000000000000013c5ebfb853f0c8741f12057b6b845c4cdbf72aecbeafc8f5b5978f186eead8685f2f3f125e536c465ade1a00f212b090000000000000000000000000000000011dbce34af6cb14d3e4d49f2482e1b058609f25dca79e2ca48e289ace9d1c8db177b7bc35daad79aa5fdac77728bd5fc0000000000000000000000000000000002b51851ef3b44481d13f42e5111fa4fec04be0bf6acc7e59dec3a8c8113e5bb7b604c6dbdc5e8eddc2a1ffb81bc2baf0000000000000000000000000000000018ddb483ae75402852b7f285277ff7308ff78a3364cca8b0e0e1fa9182de275fd55c1e8ec3dbde180379c4280787ba8000000000000000000000000000000000170539890c89a4f91acd59efd413b5d1059f0c8fd8718e8f722e865dd106a4eb02e6fb0cd71b34ebc4b94375b52e4dd60000000000000000000000000000000001c2e9392f5d4b75efc5ff10fe97f37e2671cad7e4710765866e92aec99b0130e6ff1314502d069fb7b5f86bfce4300e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_20", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000097ec91c728ae2d290489909bbee1a30048a7fa90bcfd96fe1d9297545867cbfee0939f20f1791329460a4fe1ac719290000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd6700000000000000000000000000000000053a12f6a1cb64272c34e042b7922fabe879275b837ba3b116adfe1eb2a6dc1c1fa6df40c779a7cdb8ed8689b8bc5ba800000000000000000000000000000000108248cdc6f503c7bad30eac875d92a75feccbdbe7b5394f8557a92bb12a796430a2c60ca23c6ecd259e5b01e53891820000000000000000000000000000000011bbc566a10eadf16009c1d2655cfae6adfb0f56f5e55b31dc000414be1b4cee9a0b9f7d9eab4c6829037c327914d5640000000000000000000000000000000009b28329096d8644dfcba6e92477eafff29f7477da4581ce76d1493f03034d7f5d3acaadbe42c76a83ca51db79d456d10000000000000000000000000000000019f75a303fdede5d97f3e521b03ef6b9d7c008d770b59ce3ac38900b340895e008342701ad1b41830b9c010936f4ff1700000000000000000000000000000000161aa1853edbb56fa3bd685c9c6b88e466dfa3c4f194f6774b4d9b1f30b016993bd0d65e8e9d6dea6caa196ff735bd67", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_21", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed302500000000000000000000000000000000130f139ca118869de846d1d938521647b7d27a95b127bbc53578c7b66d88d541adb525e7028a147bf332607bd760deac000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4000000000000000000000000000000001354dd8a230fde7c983dcf06fa9ac075b3ab8f56cdd9f15bf870afce2ae6e7c65ba91a1df6255b6f640bb51d7fed30250000000000000000000000000000000006f1fe4d98675ffc62d4d5dd0af9968faca4d0ef425d56fa31b80aea892820e270f6da17aec9eb83c6cc9f84289ecbff000000000000000000000000000000000ae7289aa9bf20c4a9c807f2b3ac32f0db24e9a0a360c92e5ce4f8253f0e3e7853f771597c8141d705062bef12d4fea80000000000000000000000000000000001d2f610d79110f93145faad2e34f3408316b1dc3a72852e811b324577d9037035e24af25002ddd100cd9283b70ddcad0000000000000000000000000000000012947315d5c0ec670619125eed0de3dd259a008baee4379b82accf2391e70a2bdad264cda04c3bc1b5394a62559fa0ef000000000000000000000000000000001239e687c4d3417c3c9b655035f8d8a649c255f9a8e6f03b785eed0d416a1cd6ef7c8b45563acb4616af24f64dbccac4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_22", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e70580000000000000000000000000000000010e4280374c532ed0df44ac0bac82572f839afcfb8b696eea617d5bd1261288dfa90a7190200687d470992fb4827ff32000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa0000000000000000000000000000000003f76a6dc6da31a399b93f4431bfabb3e48d86745eaa4b24d6337305006e3c7fc7bfcc85c85e2f3514cd389fec4e705800000000000000000000000000000000091ce9e6c4bab3ad3d275cf5888387646c3d9bb53ace7bd0c118fce3e44fcd96241b58e5af53978272f56d04b7d7ab79000000000000000000000000000000001179ee329771b5913d07818e70f6ce5a58d74ea0b573eaa1bd3d97e45d3eeb27fcc7d37dba127af7a38354cb6ff48f7c000000000000000000000000000000000c898abe6eb76ef99f5143cfb8d840a918bcc9096ce25caa45d0bf5d20814cb01b024f1fd2cbecb6bef65d9456070dd90000000000000000000000000000000008e2a4fd746e86f90484f9b9b7b47b6afe5833762e515ccb276c554f00df88dd9aa0fb792c5f419dda0465cfed838e7c0000000000000000000000000000000012b5e6f7070c0045ade96f548ed6428c5030fa20c6f6f37a42fde9dbb5cd01def0fd8585bf8aeef913e7d42b9ef22efa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_23", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000ebdef273e2288c784c061bef6a45cd49b0306ac1e9faab263c6ff73dea4627189c8f10a823253d86a8752769cc4f8f2000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e0000000000000000000000000000000009439f061c7d5fada6e5431c77fd093222285c98449951f6a6c4c8f225b316144875bc764be5ca51c7895773a9f1a640000000000000000000000000000000000b4322c2fb5d5dd2c65b45f74ca75002c97444d8d4e5680d0369d32d180c93b294e30ef42f21ac274f77ad89633ab1b9000000000000000000000000000000000fe2e61bc8e9085d2b472a6791d4851762d6401fd3e7d3f3ba61620dc70b773f2102df1c9d6f1462144662fb2f15359700000000000000000000000000000000031f160cde626ca11f67613884a977fb5d3248d78ddbf23e50e52c3ba4090268c1f6cd8156fa41d848a482a0ca39eb04000000000000000000000000000000000eb61ba51124be7f3ee9be1488aa83cbd2333aa7e09ae67fef63c890534cb37ca7de3d16046b984e72db21e1f5c57a8a0000000000000000000000000000000006bf6f5d65aa7d19613141018ac8bf5d1e6fe494a9f30da215a2313a0241779006bce33a776aeedae5de5ea6ee5a9b9e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_24", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b10000000000000000000000000000000011efaeec0b1a4057b1e0053263afe40158790229c5bfb08062c90a252f59eca36085ab35e4cbc70483d29880c5c2f8c200000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f000000000000000000000000000000001478ee0ffebf22708a6ab88855081daba5ee2f279b5a2ee5f5f8aec8f97649c8d5634fec3f8b28ad60981e6f29a091b100000000000000000000000000000000081162fe2e65a642993ba283df9bc8d60bfe495b2dc5623f0467c87bc7570980be2654c8cc8838fb362c677f3a3cb1e900000000000000000000000000000000196044a5cdbc5300ee837dca745a44379070e9297697f5db28df4a37307cc740abed45cc778a3f4e3b8c9890ab6c3c70000000000000000000000000000000001176f5de6a3577ad67863bd3d9152ab9e8184964c6ac276e95946788f5a76394047580077c0971d874a40d510eb0443e00000000000000000000000000000000147dd55dff69213c5760e8d22b700dd7a9c7c33c434a3be95bd5281b97b464fb934a3dff7c23f3e59c5d8d26faa426bf0000000000000000000000000000000019efcf03ddb0934b0f0dba3569809d5b48b863d50d3be4973b504244414e1e1db56adff51d33265ce102b320c552781f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_25", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e2728390000000000000000000000000000000006dc2ccb10213d3f6c3f10856888cb2bf6f1c7fcb2a17d6e63596c29281682cafd4c72696ecd6af3cce31c440144ebd10000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f00000000000000000000000000000000150d43c64cb1dbb7b981f455e90b740918e2d63453ca17d8eeecb68e662d2581f8aa1aea5b095cd8fc2a941d6e272839000000000000000000000000000000001324e51f295ea95adedc9730dac2e1ab6d85838840e3955103d76677ce9a7359215f8d954286950bed1be3bbfebabeda0000000000000000000000000000000005d8edbabf37a47a539d84393bb2747d0a35a52b80a7c99616c910479306e204e5db1f0fa3fe69f35af3164c7e5726b50000000000000000000000000000000005015082d6975649fbc172035da04f8aeb6d0dd88fdfac3fbd68ec925dc199413ed670488dc6588f9bd34c4ff527f149000000000000000000000000000000001312d53088ca58dfc325772b8dc0e1b20cebf7b2d5b6b4c560759987b44060bf4a59a68d1a5623bbb3cc5b0bc3986b810000000000000000000000000000000012110cd462c6fabf04f67d652639d19640c46f51aadd6c4f9a6dd7806cffb6192d95c198f4c8284151feaa2e2a0dbc1f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_26", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b0000000000000000000000000000000006d38cc6cc1a950a18e92e16287f201af4c014aba1a17929dd407d0440924ce5f08fad8fe0c50f7f733b285bf282acfc00000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352000000000000000000000000000000000f46bb86e827aa9c0c570d93f4d7d6986668c0099e4853927571199e1ce9e756d9db951f5b0325acafb2bf6e8fec2a1b00000000000000000000000000000000132d85236d655190323279a01acc8cbc6fb736d951e3999589f0559cb61ea93e2e1c526ed08ef08046c3d7a40d7cfdaf00000000000000000000000000000000117fd5016ddb779a6979d2bffe18032d9a5cdc5a6c7feeaa412381983d49ab894cb067f671163ccbe6225c3d85219db6000000000000000000000000000000000dcf01077dcce35c283bea662f4e4d16f871717eb78e630d9f95a200cc104fe67b0d69d95f6704d9812b46c92b1bc9de00000000000000000000000000000000121f212cd7251697ef6a7e3aa93eb0d7d0157cf1247d4411430c36c7277bf8acfccc4ed8590b5e8d0f760e0e4ed7e95a0000000000000000000000000000000007d22d78b486f575e01e21e1239cbedc4628ba7e01ecf4a3459bd78a9716e2969f26ea3f2449685f60397e1ab2aa7352", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_27", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000fb24d3d4063fd054cd5b7288498f107114ff323226aca58d3336444fc79c010db15094ceda6eb99770c168d459f0da0000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a60000000000000000000000000000000010cde0dbf4e18009c94ba648477624bbfb3732481d21663dd13cea914d6c54ec060557010ebe333d5e4b266e1563c631000000000000000000000000000000000a4ec4acf91be994fe45f08dbeb2bbd053275861d11a486693fd6e5bfa3736134396f6b1c3ad146642f2e972ba609d0b000000000000000000000000000000000224cbea61c5136987d8dbc8deafa78ae002255c031bb54335bcf99e56a57768aa127506fca1761e8b835e67e88bb4dd0000000000000000000000000000000018cbf072b544df760c051d394ff68ad2dd5a8c731377fa2a5f61e61481ad5b42645704a2d083c7d45ed4774e5448141e000000000000000000000000000000000740b8b7d7bce78a51809713656c94cf98de72887676050f65f74c57cbe574278dd3634c44e057ea95babcc3d230e3c40000000000000000000000000000000006696058a191c7012a4ee7c973c2005ac51af02a85cbb60e3164809a583b4431dda2b59e1c9ceeb652b3ac7021d116a6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_28", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe976000000000000000000000000000000000824e1631f054b666893784b1e7edb44b9a53596f718a6e5ba606dc1020cb6e269e9edf828de1768df0dd8ab8440e053000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b592947030000000000000000000000000000000008c0a4c543b7506e9718658902982b4ab7926cd90d4986eceb17b149d8f5122334903300ad419b90c2cb56dc6d2fe9760000000000000000000000000000000011dc30871a7a9b33e2882f6b24ccd192aad215edfc6c6bd9acd064dff4a43f41b4c212068875e896daf127547bbeca58000000000000000000000000000000001522e0a4ccd607f117fc6fc8f9abcd704e9850d96adb95d9bfaab210b76bfb2c5dc75163b922bd7a886541250bc1d8630000000000000000000000000000000018a6e4327d633108a292a51abed43e95230e951e4476dc385ceea9c72ed528bf3e06c42d10cefbd4aa75b134936e4747000000000000000000000000000000001198587188e793ad2ec2fa0fa1d0da9b61ed48444fe6722e523aeac270f17f73f56b1e726ab811bb54a6e42e506d70a20000000000000000000000000000000004bedd94182e0f16c71223ac3d68ab327d28ee0ccdcd2c2db07faf69e1babe3fbf3ba09c28b146eca7ab047b59294703", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_29", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000c2ffe6be05eccd9170b6c181966bb8c1c3ed10e763613112238cabb41370e2a5bb5fef967f4f8f2af944dbef09d265e00000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb00000000000000000000000000000000159d94fb0cf6f4e3e26bdeb536d1ee9c511a29d32944da43420e86c3b5818e0f482a7a8af72880d4825a50fee6bc8cd8000000000000000000000000000000000dd1137e592119c134103b9e29e4f14b48387a767d4effae44f807e5b579e7f9c2f60105495f070d0a6ab2410f62844d00000000000000000000000000000000148b7dfc21521d79ff817c7a0305f1048851e283be13c07d5c04d28b571d48172838399ba539529e8d037ffd1f7295580000000000000000000000000000000003015abea326c15098f5205a8b2d3cd74d72dac59d60671ca6ef8c9c714ea61ffdacd46d1024b5b4f7e6b3b569fabaf20000000000000000000000000000000011f0c512fe7dc2dd8abdc1d22c2ecd2e7d1b84f8950ab90fc93bf54badf7bb9a9bad8c355d52a5efb110dca891e4cc3d0000000000000000000000000000000019774010814d1d94caf3ecda3ef4f5c5986e966eaf187c32a8a5a4a59452af0849690cf71338193f2d8435819160bcfb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_30", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad6242000000000000000000000000000000000353d6521a17474856ad69582ce225f27d60f5a8319bea8cefded2c3f6b862d76fe633c77ed8ccdf99d2b10430253fc8000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c0533455013242330000000000000000000000000000000019c822a4d44ac22f6fbaef356c37ceff93c1d6933e8c8f3b55784cfe62e5705930be48607c3f7a4a2ca146945cad62420000000000000000000000000000000016ad3b981f689f51f46e3e5e166986e4e71655dcc1e928327751ffdcfff8934caec5cc37327b3320202c4efbcfda6ae3000000000000000000000000000000000805892f21889cab3cfe62226eaff6a8d3586d4396692b379efc7e90b0eaad4c9afbdf0f56b30f0c07ae0bc4013343b30000000000000000000000000000000007853f0e75c8dee034c2444299da58c98f22de367a90550dbc635fb52c9a8f61ccc100f70f10208944e48d09507fdce100000000000000000000000000000000064afd6b3ef7ff7ec34f1fa330877b42958a46a7698c6d21adf73bfdfcab7793b312e21e5988652e655f2d42edb8a673000000000000000000000000000000000ea8a2217c3dbcc0f6e562de9cb2f334c896577d0b3a7108d96b1aba2d705dbf531e870d4023cec2c053345501324233", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_31", - "Gas": 161000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff170000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000cbcd06a1c576af16d0d77ff8bcc3669a486d044cc7b85db03661a92f4c5c44a28d028521dfcfc292d8ecd05aed6ab940000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f0000000000000000000000000000000004c56d3ee9931f7582d7eebeb598d1be208e3b333ab976dc7bb271969fa1d6caf8f467eb7cbee4af5d30e5c66d00a4e2000000000000000000000000000000000de29857dae126c0acbe966da6f50342837ef5dd9994ad929d75814f6f33f77e5b33690945bf6e980031ddd90ebc76ce00000000000000000000000000000000189bf269a72de2872706983835afcbd09f6f4dfcabe0241b4e9fe1965a250d230d6f793ab17ce7cac456af7be4376be6000000000000000000000000000000000d4441801d287ba8de0e2fb6b77f766dbff07b4027098ce463cab80e01eb31d9f5dbd7ac935703d68c7032fa5128ff170000000000000000000000000000000011798ea9c137acf6ef9483b489c0273d4f69296959922a352b079857953263372b8d339115f0576cfabedc185abf2086000000000000000000000000000000001498b1412f52b07a0e4f91cbf5e1852ea38fc111613523f1e61b97ebf1fd7fd2cdf36d7f73f1e33719c0b63d7bf66b8f00000000000000000000000000000000153ba4ab4fecc724c843b8f78db2db1943e91051b8cb9be2eb7e610a570f1f5925b7981334951b505cce1a3992ff05c9000000000000000000000000000000000c1e79925e9ebfd99e5d11489c56a994e0f855a759f0652cc9bb5151877cfea5c37896f56b949167b9cd2226f14333dd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_32", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac50000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c81292925400000000000000000000000000000000065d3d4be1589a6f00c85c208c44916a35349a096b09219704b4c31861ef58e6b4ea5be57a175b429e482b1038718d6c000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000e751ccbd475fe7eda1c62df626c1d37e8ae6853cc9b2109beef3e8c6f26d41a5e4e0a91bbc3371c7ab6ba780b5db41600000000000000000000000000000000184097644c9b44d543ebc0934825610590cc9f8b17ed08e9c06592bf85591d2702b18cf48a70b378926057e541eb8ac50000000000000000000000000000000003299542a0c40efbb55d169a92ad11b4d6d7a6ed949cb0d6477803fbedcf74e4bd74de854c4c8b7f200c85c8129292540000000000000000000000000000000013a3d49e58274c2b4a534b95b7071b6d2f42b17b887bf128627c0f8894c19d3d69c1a419373ca4bd1bb6d4efc78e1d3f000000000000000000000000000000001755d8a095e087ca66f8a118e0d2c7d5e4d8427dda8fe3049080f4aff12a8746f8c2679c310f4be0d94c5bef0414a7a600000000000000000000000000000000069c84c6419ed5c0441975ee8410065a56c65f07a4b545ff596b657dc4620c7405fd4d092b281e272773d2281a6359a8000000000000000000000000000000000b8bf51e6509e81b70ff44d6e0df8f9f7bc8e33126e9f1b5a8419414878a2209c05df56cf590c8e33f484587f4a1f6950000000000000000000000000000000001c07a85ece4a1c5072fe722fb264bd1d3aaabf9db9809d5a6cb3fe17157d8fd1bfa730a26e34c87279ea81abe141fe6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_33", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c9973900000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda00000000000000000000000000000000055caff20f9f3f2ea27c64caeb6bb1880f326c64eb6ed6ee7d15da7bfeb16518f76a75f061cd347f7322e0cec634f0fc000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000001869606dde1688e5ae9f1c466c5897fce7794f3735234b5af1ad3617f0688529499bbdc9f0b911840a3d99fd9c49150d00000000000000000000000000000000001bfd33df4a6059608ada794e03d7456e78317145eb4d5677c00d482ac4cf470053d33583cf602feb67b6f972c9973900000000000000000000000000000000121b540a0465b39f2f093112c20a9822fc82497105778937c9d5cdcfe039d62998d47d4f41c76482c31f39a79352beda0000000000000000000000000000000014a461f829e0a76ba89f42eb57dffb4f5544df2008163bd0ea1af824f7ff910b27418a0e4f86cb8046dc1f3139cab9af000000000000000000000000000000000213e5d2d46523203ae07f36fdeb6c304fb86f552fb9adb566711c31262629efb0b1561585f85d2ac7be174682229bd8000000000000000000000000000000000b3336b5a4f7c0d16db9615e77bcdd55b7cb5b5c1591d835f34f5c1f1468e3cef954608667fb97a32e4595f43b845612000000000000000000000000000000000197b17c5b695db49c7c8b6fd6f314da7cfdfc4dbe61c76475839c89064870fad5104234c09aee7bafc1660263b6959e0000000000000000000000000000000019e514b65a358640ea90cd3cf547d591f5ff1a13ad99c568ef70c558cbec26dd1e582cc92d849fcfce9749068d361372", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_34", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c30000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000003c0c619be1382199bee84862a0ac6bf4c891d22f722b6af5bfef0edd1ed8c7e9af5efb5d3fc546801f3e019329ae4e80000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa520000000000000000000000000000000002c536dd2f05f4a7eaa33fd884262b22a2ab2a88e7b63cb08ebb67fc0f143da7d6b18dd394c424161f7cf703acdc82f50000000000000000000000000000000002d1d9ff74e20ea9b03c478784f57e7a58a21ca2b1e552319f33305f367f5ae4daf8138505f953db4f86c0ec1d96d5f0000000000000000000000000000000001383bc4d6c748d5c76ab4ba04f8fcd4c0fed9a49ea080c548893440819833ad72a8249f77391d5fbff78329eb319d3830000000000000000000000000000000016404bd07b6c6480af2d23301940e61817ee2e61fc625c100b31e1b324c369a583b61048dd57ab97b80b1fe6cd64c5c30000000000000000000000000000000004ac6e6077d4eddd0e23f30cfd64b7aa1525c85424224e70c15d7535e02aea7a312ef24ba2dcf70b926acb851da2530c0000000000000000000000000000000006ad07d3e8f45cedfb4279913bf0a29e37604810463d6020b4fa8c8c4977d69cffaa33e1149706f04eb237194dcafa5200000000000000000000000000000000173bdb0d0a79f1f2607867ddbf2581b4c1cc20fc0bced60ed8756aa4e79cb87c47fa722b1c8fdbe99a8208fc532327b600000000000000000000000000000000172f37eac49dd7f09adf602ebe562e5d0bd52ee2419fc08dc7fda241c0319b3f43b3ec79ab5aac246a783f13e268d4bb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_35", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a030000000000000000000000000000000014c22dcacf2e21ff447c94d81067c626b1217e58b7dc98aacab2ea3fc00b1c5e66f660d19f1c69b16571e49d13c8e1d0000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec350000000000000000000000000000000018db123e05404eea8707f9356f417c3966312b9e41765a6fd8449879ddc4c9850c38434481b235a5bc35db1b8ee86d43000000000000000000000000000000000b4162715717e9065a3849a9294cfe39b351e57ab5a6790f3e725ad9fbf0e4b9d6a3554e872af9c37df33bb896dada5c0000000000000000000000000000000006bc68c6510c15a5d7bc6eebce04f7c5fce3bb02f9f89ea14ab0dfb43645b6346af7e25a8e044e842b7a3d06fe9b1a0300000000000000000000000000000000053ee41f6a51c49b069f12de32e3e6b0b355cd2c3ba87a149c7de86136a5d9c5b7b59f2d1237964e548d1b62ec36c8db000000000000000000000000000000001913ce14bcd1d7bbb47f8efd92d7ffd155ed1990a1dbf1ee7d5e6d592a92bcbec6e865199362950afd6c8fc49b3e10a400000000000000000000000000000000020df729079e76cf06f84e3355e683e093dafad38c2ba92cf7a9faa0515f2f44d814f971046ea20116cc4b0014d7ec35000000000000000000000000000000000125ffac343f97afc413ae80d40a309dfe461fe6b20eb84f8eec3a2718ec2c9f1273bcba2fa1ca59fdc924e471173d68000000000000000000000000000000000ebfaf78e267fd93f0e35e0d19feae9db125660a3dde99b028be77c6fac0116a4808aab02a29063c3c0bc4476924d04f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_36", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218080000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d0571200000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000010338047b7c67c122ffb13466935623ef2338b32bbf5452f78f7abe9a13a16824c11f5520c9dac256b9d257da88d92a30000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000f6adad0a3bab3610165be2fadb1b020f25488a0af3d418b7d7cf1165812e17aefcbc23308ebcd31d22ba4ca5773dd87000000000000000000000000000000001657ff792e3d89d5d35767bd0cc788411b0420665a5e0704f4d2399b9d9a5ad3c027ee030fdf495e5a6e2a4c69d0571200000000000000000000000000000000024ca57c2dc2a7deec3082f2f2110b6788c57a8cdc43515044d275fe7d6f20540055bde823b7b091134fb811d23468ce0000000000000000000000000000000009cd91a281b96a881b20946fda164a987243c052378fcd8fee3926b75576dfa1d29a0aaca4b653da4e61da82577218080000000000000000000000000000000008be924b49e05c45419e328340f1cbcdd3350bacf832a372417d8331c942df200493a3f7f2e46ad2cdaf3544cfd8cd8600000000000000000000000000000000028cd100457f4e930fc0f55996a6b588c5361816bb853d1f522806e5ec1c455eb200343476feeb07ca77e961fc2adc1f000000000000000000000000000000000a96371995c5333949b5e9869599fcb67222c2e44447d133e9b3e18a9e9e14a92ee03dcba86832cde7d35b35a88bcd240000000000000000000000000000000003a912710b425cc477c43ff93684249649732b1e99270bba725e990559169b505e8411fba174b6a15f90d5b3962f5399", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_37", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000008418a39124b40643dddcd6afe1dbdf930303bca65226c2fee1b95de6e080e25451f8b4f2b2b7c4633e1de6a5a7d47cb000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c0000000000000000000000000000000004cb55008ccb5b2b8ece69fac7283f5a9ef9e622e2a0e42bed5bdd77faa550882643afc1759b1a327c4f2277e13a3d4f000000000000000000000000000000001690dee40c6c824dc2588fc47dbf93f68ac250b9357e1112db72ded905ed7b101b5f877bdc42d56afb5b6202403a91c4000000000000000000000000000000001305e1b9706c7fc132aea63f0926146557d4dd081b7a2913dae02bab75b0409a515d0f25ffa3eda81cf4764de15741f60000000000000000000000000000000011bf87b12734a6360d3dda4b452deede34470fba8e62a68f79153cc288a8e7fed98c74af862883b9861d2195a58262e0000000000000000000000000000000000a5048d860b997a9fb352e58284ebbc026622d9be73de79b2807a0c9b431f41f379c255a2db0dd67413c18217cb21b7200000000000000000000000000000000045a701a3f46ca801c02a5419c836b2ab3d74ebd6f4fd1e7dddb1965b49c9a278f6e89950e7c35ebc6724569d34e364c000000000000000000000000000000001535bce9acb48b6ebc4d3dbb7c236d7cc57d656210e42e9379d4f528fc0ba59bf868503d3bb8e5cd3dafdd881ec56d5c00000000000000000000000000000000037033062d13644c88c317f1c58c18e0d9b4facbbe0701ac8bbdf3c7f0c37b14034c7882d5112a94bea39dfdbfc518e7", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_38", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb00000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000ada13f88a645bc6082c6321e0cf2b7ac45c633fe2f0cb36aeb187fe2e50e7510df2a86b98979e8551636e94488c8ce000000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000017078538092ace26cc88b94360871fc9a6bb9992172158ef3a16467919955083accf8d55d48c7ec462a743dbbca7b448000000000000000000000000000000000289b703157a02fc1d687a5aa595495be8bbb3eb0d70554728255a44b7820e0ee82d984d5493c800f1d9d8ca0c9381dc0000000000000000000000000000000012662b26f03fc8179f090f29894e86155cff4ec2def43393e054f417bbf375edd79f5032a5333ab4eba4418306ed0153000000000000000000000000000000000f26fdf1af1b8ad442ef4494627c815ca01ae84510944788b87f4aa2c8600ed310b9579318bc617a689b916bb7731dcb00000000000000000000000000000000153cec9690a6420a10e5a5a8ca46fd9d9f90e2a139886a07b375eeecce9083a5f5418e6baf64ef0f34176e432bc5343a000000000000000000000000000000000d87c1f37f83ae78a51af9c420e2584a64337d2d2dd8dc3b64f252c521901924e5eec1d9899594db5e64c93c7a01ef020000000000000000000000000000000002f98cb2305518737e92ee72e2c48d0dbdbbb1f2dc63b9d02d1a8c27dd1ba5a071dc72a8dcc7813b5757bc244357f6630000000000000000000000000000000017775ae72405e39e2db32d5b9db6637b7bbb9799e614bd783f0b785c3f2ee815367e67b15cc037fec8252735f36c28cf", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_39", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a3700000000000000000000000000000000162e49ebd1b50c7837336509e48ace0e7856f00ec45a76b96d1dd88eea300a8118357cafabf32ee2d06b601def523e4800000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b600000000000000000000000000000000048b3e4ba3e2d1e0dbf5955101cf038dc22e87b0855a57b631ef119d1bd19d56c38a1d72376284c8598e866b6dba37530000000000000000000000000000000007c0b98cda33be53cf4ef29d0500ff5e7a3c2df6f83dfc1c36211d7f9c696b77dfa6571169cf7935d2fb5a6463cceac6000000000000000000000000000000001837f0f18bed66841b4ff0b0411da3d5929e59b957a0872bce1c898a4ef0e13350bf4c7c8bcff4e61f24feca1acd5a370000000000000000000000000000000003d2c7fe67cada2213e842ac5ec0dec8ec205b762f2a9c05fa12fa120c80eba30676834f0560d11ce9939fe210ad6c6300000000000000000000000000000000057f975064a29ba6ad20d6e6d97a15bd314d6cd419948d974a16923d52b38b9203f95937a0a0493a693099e4fa17ea540000000000000000000000000000000014396ce4abfc32945a6b2b0eb4896a6b19a041d4eae320ba18507ec3828964e56719fffaa47e57ea4a2e3bd1a149b6b6000000000000000000000000000000001575d39e959d14b96f261265417ca949a248c3d46e2abb093541c103dadf58cd5b21e28c79f17b376070799492457358000000000000000000000000000000001240585d5f4c28467bccb5193e4aad78ea3b1d8dfb4716a3310fb5215a478aac3f05a8ed478486c9e703a59b9c32bfe5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_40", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d0300000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000efe47bf2b11dd10608a309c8aaefdbcbc2bb5e6adceef375371cface8f79668e2b7c2ce9990063a3b53e419e80e2a79000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba000000000000000000000000000000001172684b21c4dfe02a55e13b57bbf105c954daec849d4c6df5276b02872c004fdf09d24f4eef366bc82eb72fe91bf70d000000000000000000000000000000001151aeb9441c5a8fabe80867b5c791420645241eae1400bbcc064d75bedd39de2ef585138fe9f65725efa1b1e5888d0300000000000000000000000000000000181dc6fd3668d036a37d60b214d68f1a6ffe1949ec6b22f923e69fb373b9c70e8bcc5cdace068024c631c27f28d994e5000000000000000000000000000000000b02ca2b0e6e0989ea917719b89caf1aa84b959e45b6238813bf02f40db95fbb3bf43d3017c3f9c57eab1be617f18032000000000000000000000000000000000b6069a2c375471d34029d2a776e56b86b0210c35d3eb530bf116205b70995e4929fc90349a7db057168dbe6c39857970000000000000000000000000000000014251a0a154731f73513b99d830f70b6fc4bcf05d11f52d2cbe9795ee8ffc5a5f717ad25770b8ecad6d0e9f8066e0cba00000000000000000000000000000000088ea99f17bb06ba20c5c67aeb8fbbd19b2270986ee7c6517209679e6f84f5d43fa22daf6264c993f1d048d016e3b39e0000000000000000000000000000000008af6330f5638c0a9f339f4e8d841b955e322766457112039b2a852b37d3bc45efb67aeb216a09a8940f5e4e1a771da8", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_41", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f000000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c1872290000000000000000000000000000000001099fe889d8f5ddcad09328997c7c3098ef4b4d74ab1d9f6fcbc33a03cafb59c7b28931da67950d1389fbcedca3fb5bb00000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e000000000000000000000000000000001995b9d697bded656236430e78726f0f6ef963db9a5a24d455c12db38aeab0f8629e5dc2d04920156f2a057d69613096000000000000000000000000000000001119b13caf82c18fadcb65c9c166914bfd822534bb9def3feae6c9e572c97c84e97fab3b345cf59358436a404075493d000000000000000000000000000000001329a75975b714c861064d743092866d61c4467e0c0316b78142e6db7e74538a376a09487cb09ee89583d547c187229000000000000000000000000000000000096713619bf088bd9e12752cab83e9cdd58296ada8d338c86a749f00ba014087a3836ce10adaaf2e815f431235bff4f000000000000000000000000000000000161b70d0f384e589d8117938602f3d696f941c24e3c1ca5a9be090b670456c9df315d6fde52daed55c9d8335928a7a3c00000000000000000000000000000000186bb9e6f5ba70dd2c66a641d3b711844977939904c59946d4e9f49ac2d8c00890a43ccb20d4a62bfff63ce4a0a44e8e00000000000000000000000000000000006b5813a1c1f934e8e564a7cad93dc7f57de7a9592aedeb116fa4ed6bc6452bbc0da23be10adfea4ad4fa82969e7a150000000000000000000000000000000008e760ad89fd250a9d5041ec81e51b8b66f5265037e7237f7c4a08bb83e7799f352c54c37cf70a6c61bb95bfbf8a616e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_42", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a9000000000000000000000000000000001750d2e78525453f113b76f18abf2334de9755c03786fbc9233cda2364d57ed493f4fe6c2b565f4d82ff8113e9b63c4d0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000001bca57e985906695e14882f2aaeef75de5009e8717eb59962e978aa11e9d0a4d9a9e203df774cb1e993b1c6ecd6048c000000000000000000000000000000000695b11cc32740c91546eb7d554ca8b1f3afc942ad977345031be8b94b78b57a87ab049ca2d3676e039efccbf24d0c47000000000000000000000000000000001195502bc48c44b37e3f8f4e6f40295c1156f58dbc00b04b3018d237b574a20512599d18af01c50192db37cb8eb2c8a90000000000000000000000000000000002b03f02b45aa15b39e030c4b88c89a285dff5c4bbfe16f643f3f87d91db774f8ab7019285fda0b236ff7eec16496e5e0000000000000000000000000000000017d1ffcad218efd8b09c68eba34dbbc30b0a62ae250368ee37e5f6fd40479b8580563416afdbd92c0622c341331e20a30000000000000000000000000000000009f0eb3805ed78aa3952a0a437966258ed38cb72912756253a7a2f9113f0dd9a4e187062b0423e0587d93e904d88f50d0000000000000000000000000000000018446c6ba126e030ed071f87189cbd618627419c82065d26044759f6e4c7257f45021dfad1dcb34dd06b4e391329a61f00000000000000000000000000000000136b60cd7658a5d135d4bc38edff042570c7824245ed9f7a6414e9e7ab3840a99700fb620e809891b66003340db29e64", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_43", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb0000000000000000000000000000000001a28b7856a22db6e79ac4165e60addbb7dfe1f19d815032bc68fea905bd0d7709c2dafc65fe51493c964de678a30d32000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb8776600000000000000000000000000000000135b3db43511dbd8b3bd5a91880d6da1a2bd1383000e0d6f0a521bf88a5836a3b5f7cb9c0c02aa861a1c2d339f3c11f20000000000000000000000000000000000e1337271bd3302a1cab762161ccfbf2a18b7800e6efe58cf897d4adbfe4cb3bf14f4b59307fffc548179bda70c18bf000000000000000000000000000000000d7e1651f3e172dcca8774a7a0d58ab47178d3e759933289e1d3eb0da414160ff9e890a608bf8ccdf2820c4aea6e11cb00000000000000000000000000000000185e8671e2ddb8e36380e39fe4eafefbac9769935603c28caac7d3f7f0f3e8ad14e925024b55aeb67d68b219875c9d79000000000000000000000000000000000546a0cb9d9f1ef9ec4a1e576fa0047557a56c0217baed8691c4085b88c84a0e12d44043aab8671393d02c4a764407ee00000000000000000000000000000000131884c1386980a181353548da9602db70ab495a661e76235c4b0a32b54acb0dfd8846e17bebd731e8041c4aebb877660000000000000000000000000000000006a5d436046e0ac1975e4d24bb3e3f35c1ba3801f37705505cdeb6a86c58bf8068b43462a55155799fe2d2cc60c398b900000000000000000000000000000000191fde77c7c2b397a950f0542d2edd183a5e9404e516146697a755561ab2a9705f970b491e4c0003657d864258f391ec", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_44", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e82000000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e270000000000000000000000000000000007c17aaf82c2aa6bf01695157bcd0c2b34734dfbd572b0abe79c8dd3eef7ce6eb9c5e7de55b36ddf87f05e55ba9ac28b00000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df70000000000000000000000000000000012c5b00376a1dd31378ec44f2dc8e321e17185d903cfc5c15345a01c33f2f151b21b938d31816550594a7a1e7216c5b00000000000000000000000000000000013d79f825c44775c68e90932d0496a5cae53f04a1edb19f8abeb5948a3dd325dfec4a8b6f58c7fbca9cf3c09b909d8b2000000000000000000000000000000001454d4a82163a155446467164904cefd7e1e3c67ae99bf65c581a75c72716fb011e2fd030eaf3d36977fbb0ff5156e2700000000000000000000000000000000123f973ab6bd3c2e5b0512a0c77ea0ac3003fd891e1262137f9444cd07b927b564e618205ba09220320ea1aa4564e82000000000000000000000000000000000113dc3354146ca79eb103b31b61fe8bc6f33dcb9c59a7c39d989bd9411c1afce4239034f84e6b00a084be061c73e69c0000000000000000000000000000000000ae33bf68f24978c7ea9fc58d8d76047ec45d01fdbc880e6a5ba02a22a49a3a8253afe0678ecfa6013f4849da3401df700000000000000000000000000000000073b61e6c2de0969138ce3671582c9b58305c5abefb54cfe13eb3284c2be04d26c906c717fd29aaf60b485e18de8e4fb0000000000000000000000000000000006297267dd3b6f3de2329e837302427ab6235b3ad4a9f8c6bb45795852d3c3c61fe75747bbc78043102fc3f646f5d1f9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_45", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000017147eda83f35d0b6c8894317da5b2e991818479674d7dd1aef6bfaebacbb61ad4b2a17ce7e799939f8c2004af4799530000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c743900000000000000000000000000000000101e143b838c8a3f5f80fb1412081091b875230f1e2f9cf374d4bcd595392f6daa9552dbb6d5834e27b1b3dafe061ed300000000000000000000000000000000072463400b3e875395a1cdd31d73d51396e34347cd86d9f6f43f42253b3cdb24b89ed7434b1522af95ba1ee2d29ed1bb000000000000000000000000000000000178e6828261ee6855b38234ed15c27551bb1648ac6ec9a9e70744643cd1f134b2309dd0c34b1e59ddfe3f831ab814c90000000000000000000000000000000002ec930fb58c898ede931384c5a5f9edd2f5c70b8c3794edb83a12f23be5400949f95e81c96c666c1a72dffb50b811580000000000000000000000000000000006ccaf6c08f831be9c99a97714f5257a985cc2a29b5f5c81bc8d794dd0d8d1a41eb5413bed654c0140dbacfd0dda9e1800000000000000000000000000000000144e9cf91580800dfaa47c98ff7d002a576be76d9e44ae1f8335a3f733e1162af0636372e143174d872c7ea89f4c74390000000000000000000000000000000009e2fdaeb5f35c5aeb9aaca231439c45ac022875d55575cbf25c15cb6177c6b67416ad22fa7e7cb1924d4c2501f98bd80000000000000000000000000000000012dcaeaa2e415f46b579d9e325d7d7c3cd94083d25fe38c872f1907bbb741aff660d28bb663edd502444e11d2d60d8f0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_46", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f10000000000000000000000000000000016c1c9ca735535f801c58a9e35a80ce122d20abb327b44db4dea31b899982c4e136a2430c51cf3a31adc5611621f9dde000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000eb731bc99cdadf7f2280385c7e17d72d34bcbdbdc725d5bc94e841036115e8cb95df08084221696f9be479821fbdd7400000000000000000000000000000000143ba7d3f66445249d9a81a6949f24ff40e7c4d270fa044a8b80200a4369b07806c5497a0ef9e9dbb87b9e63694623ee0000000000000000000000000000000001ea88d0f329135df49893406b4f9aee0abfd74b62e7eb5576d3ddb329fc4b1649b7c228ec39c6577a069c0811c952f100000000000000000000000000000000033f481fc62ab0a249561d180da39ff641a540c9c109cde41946a0e85d18c9d60b41dbcdec370c5c9f22a9ee9de00ccd000000000000000000000000000000001354146aa546754e10ada6e0fe98f04f5f3a3f8a8350d0295e02b8e9c80735b04c3061412e08ddb13c80ac36e5638e540000000000000000000000000000000012ab26513534b4dc1b71eec46b73199c4157ba9369e66fbe4d2d8f62237fc7c6fad31854ebd878f989b8c5cf35c7cfe0000000000000000000000000000000000b49e02d9fb238a258f3a4307b6a2f64912b7fa91712b5639de24e90c09f9797654e0f7e2d31e968c040b867de03cd370000000000000000000000000000000005c56a16431ba175ad81260faeac87d8238f86b2828b0e74dbb0b296b34745ac17e6b684a25a16240183619c96b986bd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_47", - "Gas": 184000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe90000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb90000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be100000000000000000000000000000000084486ebc81878331aab7d6f53ca3c773fda7b181b56a93e5ee0bfa189afbb7fd7a05c5bea35ec1054c0e1ddc2e2dac20000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000068edef3169c58920509ed4e7069229bd8038a45d2ce5773451cc18b396d2838c9539ecb52298a27eebd714afacb907c0000000000000000000000000000000004c5346765a62f2d2e700aadccf747acb3322c250435ce2cf358c08f1e286427cabace052327c4b30135c8482c5c0eb90000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be10000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe90000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000137232f722e38e084611ba67d2e28a3b8c73c13f20b6bb4c22141115bd43cdeb555861335f2a75d7cb418eb505341a2f00000000000000000000000000000000153bdd82d3d9b76d1cab9d087654652ab1451f5fef4f449273d81211d88891fc53f131f98e2c3b4cb8c937b7d3a39bf20000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be100000000000000000000000000000000084486ebc81878331aab7d6f53ca3c773fda7b181b56a93e5ee0bfa189afbb7fd7a05c5bea35ec1054c0e1ddc2e2dac20000000000000000000000000000000013a3de1d25380c44ca06321151e89ca22210926c1cd4e3c1a9c3aa6c709ab5fdd00f8df19243ce058bc753ccf03424ed000000000000000000000000000000001657dbebf712cbda6f15d1d387c87b3fb9b386d5d754135049728a2a856ba2944c741024131a93c78655fdb7bfe3c80300000000000000000000000000000000137232f722e38e084611ba67d2e28a3b8c73c13f20b6bb4c22141115bd43cdeb555861335f2a75d7cb418eb505341a2f00000000000000000000000000000000153bdd82d3d9b76d1cab9d087654652ab1451f5fef4f449273d81211d88891fc53f131f98e2c3b4cb8c937b7d3a39bf2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_48", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c600000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000a5b95d6031e92578f6b5de5b8873e87486fd818214be93814753dcf6665229758248a6529892265fcc2b2ba45f89171000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000f6fdc4e5dceb555c9eb4c912fedbfb3cb1b842345f73ded02cfaf8d397c4378809721094aa4a4113a368e0787effeb500000000000000000000000000000000143ac06258c579c11c05569669a2a10babc63ecc86f85c91791d8ea48af700a2067c5f13d2700b8d5cf59bcca8fbf7c600000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000fa57c1436615442bbb049d08ac46e501c07736cd239298752bb94d1904bd38cc687759987cadd99bd3c4d45ba07193a000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000a91359bdbb1314481305b25135ded23995bc761ad8dd4d264612313bd34b2ab9e14def566af5bee7fc871f8780fabf60000000000000000000000000000000005c65187e0ba6cd92f16511fd9a90bcbb8b10cb86c8cb62dee1343fc6bb9f582182fa0eadee3f4725d0964335703b2e500000000000000000000000000000000120ddc1cd9e3a7b298673b1036d162c31dbb35d6e83b39b2564b3be16e446a836c96907e8a6af1e677e906bf5ed73159000000000000000000000000000000000a5b95d6031e92578f6b5de5b8873e87486fd818214be93814753dcf6665229758248a6529892265fcc2b2ba45f89171000000000000000000000000000000000dd75b4aebed3bd6bd020c3af671aaed67bf1582aceb6c8b5a476968c0c500753e4d0f3276341b79d87af38850893d92000000000000000000000000000000000e9b3be06afd6157eb6df52be4f2db2bcccd650f720661f8d6fcff3f71d69e152e17100ce60b7b90a7f798c4cdd02209000000000000000000000000000000000a91359bdbb1314481305b25135ded23995bc761ad8dd4d264612313bd34b2ab9e14def566af5bee7fc871f8780fabf60000000000000000000000000000000005c65187e0ba6cd92f16511fd9a90bcbb8b10cb86c8cb62dee1343fc6bb9f582182fa0eadee3f4725d0964335703b2e5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_49", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b60000000000000000000000000000000002a534a7e1432aa317f782a581f974d23ec75420611165d0486ecd377660fa7c2e8235f829c64501d1b9bf3131e87289000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc500000000000000000000000000000000192f3e8ae2588f9223de77f5e872115f1edec96d6a0f403a47879410c2562e79853c9a706e423b83fbf3154234edb6f80000000000000000000000000000000015084258d58fd1a07bbdb2e90df5a56ae15a787037eff4fe55f660e45f04820c6fc8982303b5e82074cf0cdcbde61307000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b600000000000000000000000000000000175bdd42583cbbf733242510c152380525aff7649273acef1ec20569804ffba7f029ca06878dbafde84540cece173822000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc50000000000000000000000000000000000d1d35f57275708273d2fc05ad99b78459882178975d2851fa93e90345ac7aa996f658e4311c47bbe0beabdcb11f3b30000000000000000000000000000000004f8cf9163f014f9cf5df4cd3556076c831cd314bb951dc1113a71bc97ac7417aee367dbad9e17df452ff323421997a4000000000000000000000000000000000e3ccaa4fa358a5a885094cbb0b8baa106fbcca66edbe31511ac2f6f3d14edbd8701979d6e4690853555c625091392b60000000000000000000000000000000002a534a7e1432aa317f782a581f974d23ec75420611165d0486ecd377660fa7c2e8235f829c64501d1b9bf3131e87289000000000000000000000000000000000057bbf62cdf3c56e146f60f8ce6b6bdebe7aae7d9410c6902c7a505b589ae26ce3ab67d9b8da047185f9d37ab27595e000000000000000000000000000000000843e55c07bba3573592d3f649938654a5c51f9ced0f92bcb3e4f431141fe91a1de3695324b21e31dd2ae0a328055cc50000000000000000000000000000000000d1d35f57275708273d2fc05ad99b78459882178975d2851fa93e90345ac7aa996f658e4311c47bbe0beabdcb11f3b30000000000000000000000000000000004f8cf9163f014f9cf5df4cd3556076c831cd314bb951dc1113a71bc97ac7417aee367dbad9e17df452ff323421997a4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_50", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc260000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000d4197b85280f1a5e4cfdd6a7acce516b34a5e12cf55081a858a2ad517d12733aa294a2ca1adf81bc9bf22922fbfd99f000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f000000000000000000000000000000000477b55bd7fff14e0d1807bfc21edb9481be01c12abb1460d78b1aafe42953730167e32e694c2ddfb0d442e8cea57d460000000000000000000000000000000004b884c6ea36f189dbc3c0e9cf88f08baf5d868579998f63b752e61fcce3cf2c901bb9b51959d3597c4ef53cff41fc260000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000cbf7a31e6fef4f4664bca4bc87ec7c0b12ced7224300aa4e1a6a7cbdedfcef07482b5d20fa607e3f03fdd6dd03fd10c000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f0000000000000000000000000000000015895c8e617ff54c3e039ff6812cd142e2b949c3c8c9fe5e8fa5b7f11287a2b11d441cd04807d220092abd17315a2d650000000000000000000000000000000015488d234f48f5106f57e6cc73c2bc4bb519c4ff79eb835bafddec8129cd26f78e90464997fa2ca63db00ac300bdae850000000000000000000000000000000001bc359baeac07a93aca770174ea6444aac9f04affdaa77c8a47b30c60ee2b527c061a4344139264e541d4134f42bfd0000000000000000000000000000000000d4197b85280f1a5e4cfdd6a7acce516b34a5e12cf55081a858a2ad517d12733aa294a2ca1adf81bc9bf22922fbfd99f000000000000000000000000000000000bcec23e092111b38a2f7dc957cf455312ffd33528d084204314492440d29248cb5719346a4f7a490d17ba149e30de5200000000000000000000000000000000194605e5680cc80bd2685949efa3cce90d345b9151ba72f3adf226dd299c23464c4344a42b8834131a51a4156038585f0000000000000000000000000000000015895c8e617ff54c3e039ff6812cd142e2b949c3c8c9fe5e8fa5b7f11287a2b11d441cd04807d220092abd17315a2d650000000000000000000000000000000015488d234f48f5106f57e6cc73c2bc4bb519c4ff79eb835bafddec8129cd26f78e90464997fa2ca63db00ac300bdae85", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_51", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb341500000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa00000000000000000000000000000000145688bf2f7a76a4341564a725a16dd5009b4a5174d766e6bf337a8bcbb11c797b82173d92aa796da6b168e734be90ec00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac800000000000000000000000000000000183b7b917aaaa94f0ea9959273ed4701102346be2a9d72531bd18fef908ecb0579a6ac10ed42a91f1147fc3a05b2e81900000000000000000000000000000000070983b1582a97d9797782e4f960a298aaa8ec509720495acdbf176d8ecb9ec9e041c2b5ed6b7dfb46fdeaae3fb341500000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa0000000000000000000000000000000005aa892b0a056ff61706430f1daa3f0263dc01337eadabd8a7fd58152affd9aaa329e8c11ea98692134d9718cb4119bf00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac80000000000000000000000000000000001c59658bed53d4b3c721223cf5e65d6545404c6c8e7a06c4b5f42b166222b1ea50553edc41156e0a8b703c5fa4cc2920000000000000000000000000000000012f78e38e1554ec0d1a424d149eb0a3eb9ce5f345c64c9649971bb3367e5575a3e6a3d48c3e8820473011551c04c695b0000000000000000000000000000000006b06ae8cb0981bf5167ad51e19d132db77548c4376697f855c8397b835743c42771096ed7b0a4b18af9494e42ee89aa00000000000000000000000000000000145688bf2f7a76a4341564a725a16dd5009b4a5174d766e6bf337a8bcbb11c797b82173d92aa796da6b168e734be90ec00000000000000000000000000000000073341309b6fbabb18f3cf0842817905e9248db98b582dc0efb2b741a80cdbb13d0df4bce920f257996b95029891a36f0000000000000000000000000000000012d19e09dc254bd1e84afce75aa215c96dd38bcac3f6d4cf08d9e2e8d20345b7c534a0b14ffcdfd4fa3600730e2eeac80000000000000000000000000000000001c59658bed53d4b3c721223cf5e65d6545404c6c8e7a06c4b5f42b166222b1ea50553edc41156e0a8b703c5fa4cc2920000000000000000000000000000000012f78e38e1554ec0d1a424d149eb0a3eb9ce5f345c64c9649971bb3367e5575a3e6a3d48c3e8820473011551c04c695b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_52", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b10000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a030000000000000000000000000000000003942eae34fd3104cead334a2cbb2131eaa10b59d07949479331a8f4cc66761cd5d23eb8a861ae618f3a2e01b25080f9000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b0000000000000000000000000000000010f7bf9f6711ba723bb71a004a90109ee22be6643d56d410da18103ef44a1b3d50f10c4b94222c7f05fd3c28acbdc8ee00000000000000000000000000000000007af41f09e6d0adcb1935d6a93ea1f6156fa0157a63f265a3a7ceffe82f6635b8511e7e8f21e8f3be7a73513ff597b10000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a0300000000000000000000000000000000166ce33c0482b5957c6e746c16908ba579d6402b230bc977d3ff29ac2a4a800748d9c14608f2519e2ac4d1fe4daf29b2000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b000000000000000000000000000000000909524ad26e2c280f648db5f8bb9c38824b6520b62e3eae8d18c2620266dae6cdbaf3b31d31d380b401c3d75341e1bd0000000000000000000000000000000019861dcb2f9915ec800271df9a0d0ae14f07ab6f79212059c38903a10e818fee665ae1802232170bfb848caec00a12fa0000000000000000000000000000000015dc9f87213e4781863ad43f6bbccd547967d9bcf6a35d95d530cbfbf0d7307981aee5bc4ccd41254841651717393a030000000000000000000000000000000003942eae34fd3104cead334a2cbb2131eaa10b59d07949479331a8f4cc66761cd5d23eb8a861ae618f3a2e01b25080f9000000000000000000000000000000000dca3b392f75583b5266a8def02bd66bf44f26b8a0a27aced57299756cffaf9e1af3538beb08b2a5939b745c8f016fee000000000000000000000000000000000d7feafc9ec0935d5b7be7cd5e2a3c57b667aba9fcc87fd5b8a585010be6958c4e7538a6d2a1f46c9641ff7b8598d74b000000000000000000000000000000000909524ad26e2c280f648db5f8bb9c38824b6520b62e3eae8d18c2620266dae6cdbaf3b31d31d380b401c3d75341e1bd0000000000000000000000000000000019861dcb2f9915ec800271df9a0d0ae14f07ab6f79212059c38903a10e818fee665ae1802232170bfb848caec00a12fa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_53", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f60463000000000000000000000000000000000575bd953fc6600f5b48faea1032cf2b6615bf34cc9c526fdcc5042a292812d35fef2884bf51e017eb24c174b2bc20a00000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a0000000000000000000000000000000003a6cc74cc398f38d535b4341faa37c968daf2009c3f05ace1f938b33bbe4002d81d18d30c2c856b21afe7a22b83c37a000000000000000000000000000000000452d1b2da6392f9df1bfd35e4575c565333703b2f83f56e0a88a0c8195968c5321296b07f6750584e23597304a5472e00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f6046300000000000000000000000000000000148b5454f9b9868aefd2accc3318ddabfe618c5026e8c04f8a6bce76cd88e350bebcd779f2021fe7ceda3e8b4d438a0b0000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a00000000000000000000000000000000165a45756d46576175e5f38223a1750dfb9c598457460d12853799edbaf2b621468ee72ba5277a94984f185dd47be7310000000000000000000000000000000015ae40375f1c53a06bffaa805ef450811143db49c4011d515ca831d8dd578d5eec99694e31ecafa76bdba68cfb5a637d00000000000000000000000000000000171fbc9cec717964c4324aa0d7dcf56a59b947c24a9092157f4f8c78ae43b8e4222fd1e8acdbf5989d0d17ea10f60463000000000000000000000000000000000575bd953fc6600f5b48faea1032cf2b6615bf34cc9c526fdcc5042a292812d35fef2884bf51e017eb24c174b2bc20a00000000000000000000000000000000019e05ccf064f7cdad9748d328170b3e4bcfa6787dbfa93011d16f6d031648faa10dbfb7cc4d7c884d75480c4c864bb75000000000000000000000000000000001999d5f54ee66b3c0dedf9f46450e0ed463fa9c6cd9e0db317a35ec6ce78efae9bea9b64e3b2aaf7f70fbcace71b075a00000000000000000000000000000000165a45756d46576175e5f38223a1750dfb9c598457460d12853799edbaf2b621468ee72ba5277a94984f185dd47be7310000000000000000000000000000000015ae40375f1c53a06bffaa805ef450811143db49c4011d515ca831d8dd578d5eec99694e31ecafa76bdba68cfb5a637d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_54", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e60000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a000000000000000000000000000000000032e4fbb8dab462ff0352c2d3925b0e97ca662189129928ccc1714364e4f01d8b026887d808342091ad442b6e11635910000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf780000000000000000000000000000000007a9cf48dbe005c5c59b2c731cf4117e5fadc9cb2cd8f486f1ed58b2909092ee8f36d88b8f719db94715641b418ab4240000000000000000000000000000000004ba40d4766b91bf8da1cc2526f62791a1b5f6fc24ffc54b522dd30cde2d29a6a6f81e8429d518710843d43705f3b4e60000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a00000000000000000000000000000000016d2c22eabd4a06a5ae67b890a25fbede7d0e96c625b80329b19be6aa861f44b6e85778130d0bdf69f2abd491ee9751a0000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf7800000000000000000000000000000000125742a15d9fe0d485807b4326579b5904c981b9c6ac1e38754379ee662063358f75277321e2624672e99be4be74f687000000000000000000000000000000001546d115c31454dabd79db911c558545c2c15488ce854d741502ff941883cc7d77b3e17a877ee78eb1bb2bc8fa0bf5c50000000000000000000000000000000018724e2b9a2f383329207ee85577805f35d5c5bb9f6903e3c962e57ab7eb9d1639d1e9adbde53499863b299f576325a000000000000000000000000000000000032e4fbb8dab462ff0352c2d3925b0e97ca662189129928ccc1714364e4f01d8b026887d808342091ad442b6e11635910000000000000000000000000000000004506802747afd8777904c46ad9bf0b06859a1b395ca3474a93ca4151ca158d2fd41b3a21e0ce0bc950b3241256e10d800000000000000000000000000000000115f41d2c173c3c2c7ecdff1a4aaa3c2e67c803db7a588d6143fe913961eef743d8b1f9d32e3ef1fc0475f41572faf7800000000000000000000000000000000125742a15d9fe0d485807b4326579b5904c981b9c6ac1e38754379ee662063358f75277321e2624672e99be4be74f687000000000000000000000000000000001546d115c31454dabd79db911c558545c2c15488ce854d741502ff941883cc7d77b3e17a877ee78eb1bb2bc8fa0bf5c5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_55", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df910000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c320000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000ae6134f1fec83a52e5358db260eb9dc6b918f7a803aae5715854ebee2b9bbecea9ab0d955f2e13e2c47a96b234ecb1a0000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c7952820000000000000000000000000000000008ceb842a17953578013ceee519a28ef1b37f73e13564def5ffe08a64dc53aa680784e26138176c89269477ee003d16700000000000000000000000000000000159791b6f2c26ed611ca40bfbd2059c15cfec9d073a84254ad9b509ef786d62d17fdc67ab13092cf0b7b3482866f4c320000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000f1afe9b199362f51cc84edb1d3cf2faf8e5bc0a734a646851ab83e213f73a3734114f255b611ec18db75694dcb0df910000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c79528200000000000000000000000000000000113259a798069342cb07d8c7f1b183e8493f5446e02ec4d00732c9faa8ebbb7d9e33b1d89dd289372795b8811ffbd944000000000000000000000000000000000469803346bd77c4395166f6862b5316077881b47fdcd06ab9958201ff2a1ff706ae398400236d30ae83cb7d79905e790000000000000000000000000000000010fcf5e5e478ac6442b218ce261878d8f61b405c0b9549512e23ead1f26a2240771993f8c039fbce4008a1707aeaaf25000000000000000000000000000000000ae6134f1fec83a52e5358db260eb9dc6b918f7a803aae5715854ebee2b9bbecea9ab0d955f2e13e2c47a96b234ecb1a0000000000000000000000000000000019cc0ec24da141f27b38a53aef0b3d93c4c2b981c1b248014be277002d39d7bde66f6957a659a89adcd3477dfe4f897a000000000000000000000000000000000e4c01d7425e35be84e3cf806aa76a079cf4557732980f7e8f8ce9a879483e28f223694ed8dd45706e12272f4c79528200000000000000000000000000000000113259a798069342cb07d8c7f1b183e8493f5446e02ec4d00732c9faa8ebbb7d9e33b1d89dd289372795b8811ffbd944000000000000000000000000000000000469803346bd77c4395166f6862b5316077881b47fdcd06ab9958201ff2a1ff706ae398400236d30ae83cb7d79905e79", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_56", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000000d9bd58946a4d26e3f97e5fe96e574d6f93562c0fb0c187c0c586208fe9a4d9383d3ca22b272ff3eb7e624ad7fb9ea7000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf000000000000000000000000000000001272c63693873e1dabe2c2739310f627d3d9b5bcaa615402c3849ffd8dfe72b40fea4a068064655f2c8f46f074e6518d0000000000000000000000000000000000161a8e5e1de10938e5bce241ae73d76173022127822d744b23e656095c28f2f8d142ceb48b72a1dbc36b6143f8af95000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000019275491a51599736722295659dd5589f4e3f558e3d45137a66b4c8066c7514ae66ec35c862cd00bce809db528040c04000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf00000000000000000000000000000000078e4bb3a5f8a87c9f38e542b03ab6af909d95c84923bebca3ac32a368b283700ec1b5f830ef9aa08d6fb90f8b19591e0000000000000000000000000000000019eaf75bdb6205911235ead4019d390003044963cc02e54b1c0cec4aed54cd3125dabd2ffcc88d5dde3b949ebc06fb16000000000000000000000000000000000f75bc9feb74110697c9f353686910c6246e587dd71d744aab99917f1aea7165b41deb333e6bd14843f28b2232f799830000000000000000000000000000000000d9bd58946a4d26e3f97e5fe96e574d6f93562c0fb0c187c0c586208fe9a4d9383d3ca22b272ff3eb7e624ad7fb9ea7000000000000000000000000000000000040d03956c821010969a67c91a6546800c5aa7ac392b16a9895136c941f4ca9f378c55446161562feace3b5b65f3c4f000000000000000000000000000000000e4b299f9fb25caec655d21c390bdad3c1256ca29faa33466a13aaa6d86310106d95fc8d8a0409fbd228fd3be7965cdf00000000000000000000000000000000078e4bb3a5f8a87c9f38e542b03ab6af909d95c84923bebca3ac32a368b283700ec1b5f830ef9aa08d6fb90f8b19591e0000000000000000000000000000000019eaf75bdb6205911235ead4019d390003044963cc02e54b1c0cec4aed54cd3125dabd2ffcc88d5dde3b949ebc06fb16", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_57", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e2946000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000f77a58fb4b4165bf86d30b6349b84780d72b24e8eddce16c73a1f5a06de0638045a64978eb9c477d806f1955e818165000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a220000000000000000000000000000000018a236ea02b1971d6e193a6eb92e1298956679d86864042fb6a0c36dd91c0e385944d779dedd0149fa8a1b3d6a07949d00000000000000000000000000000000048eac7d116b5a7906bce070e2b51ee7c4c493f1415abdb6fd2d35676036d3b741d14b7135419645a6906018e9d3f150000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000a896c5a84cbd03e52ae77000eb0285f5704993664a744a89ff6b346efd2efec1a519b67229a3b87e1f80e6aa17e2946000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a2200000000000000000000000000000000015edb0036ce4f7cdd026d478a1d9a3ecf10d1ac8b210e8fb0900f331d94e7ebc5672884d276feb5bf74e4c295f8160e000000000000000000000000000000001572656d28148c21445ec74560968def9fb2b793b22a55086a039d39967a226cdcdab48d7c1269ba136e9fe7162bb95b000000000000000000000000000000000a87d0ccfb9c01148703d48993de04059d22a4cc48c5dabd2571ad4f7e60d6abfbcc5fb3bf363fd311fec675486c2a20000000000000000000000000000000000f77a58fb4b4165bf86d30b6349b84780d72b24e8eddce16c73a1f5a06de0638045a64978eb9c477d806f1955e818165000000000000000000000000000000000b50dc0957eccf5ad941b148a3824e82464bb7345a05125a0aa64f6ba34e34e767d4f679e9916faaacf82b3c79c9bddc00000000000000000000000000000000087152b3cb0db88776a7144fbafc1b210d150b637ca7148e3df600989231bce613fcf8e310fcc53aa2dc934bcbf86a2200000000000000000000000000000000015edb0036ce4f7cdd026d478a1d9a3ecf10d1ac8b210e8fb0900f331d94e7ebc5672884d276feb5bf74e4c295f8160e000000000000000000000000000000001572656d28148c21445ec74560968def9fb2b793b22a55086a039d39967a226cdcdab48d7c1269ba136e9fe7162bb95b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_58", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000018bc060c3f6be35b724dee72bcda5cc376dc1f35561f7e70c9fe11eda256edd30aca8c19018433483186beb5b9b2792700000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c95384000000000000000000000000000000000003c96c6f20d7ac31ee7ca77d11e8d25ea78cdf13e5f4d317752320e059e19196f14c15b5a18ca712f3a7cc6f09be6d4000000000000000000000000000000000ebd71f61fcddf1652675f577bbaeec26b892dd954965b057ffb431d6e37cc5425a2a42a0059482c2bd75adb2a120b0b000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000001450bddfa14033ed8cdb94386715013ed9b2c4f9d65944e9d32c0b3545a085113e173e5afcfccb78878414a464d318400000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c9538400000000000000000000000000000000019c47b2347726bd72c33dd3e722d1fb179fe7d93b525c58defdea092f112dd0aaf973ea3573b358e8ac483390f63c3d7000000000000000000000000000000000b439ff419b20783f8b4485ec790be14f8ee1dab9eeeb7b9e7358f83887929cff9095bd4b0fab7d38e27a524d5ed9fa0000000000000000000000000000000000d35ffa284655a94c3050213f4f14e927c162818bbfd0480bad2e07000dd3081274056715c96408f243589d83365c9f20000000000000000000000000000000018bc060c3f6be35b724dee72bcda5cc376dc1f35561f7e70c9fe11eda256edd30aca8c19018433483186beb5b9b2792700000000000000000000000000000000094fdcc2119b4f674b5639653dfabcac59c2adb1ee2ec06c55c3f148c9361351ff0acb2519e4638cb2cde98efaec8f4400000000000000000000000000000000051d5edcbd6eadac808222f0423bada165fcb98f98a89f335c981262b0ca7ea1c536d41aa41b49b25f0c43f53c9538400000000000000000000000000000000019c47b2347726bd72c33dd3e722d1fb179fe7d93b525c58defdea092f112dd0aaf973ea3573b358e8ac483390f63c3d7000000000000000000000000000000000b439ff419b20783f8b4485ec790be14f8ee1dab9eeeb7b9e7358f83887929cff9095bd4b0fab7d38e27a524d5ed9fa0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_59", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f3555650000000000000000000000000000000007f7dc55c90fa181c55c9b83b7736ee84b3f19d960318e75661dd22c0546d62f4c9e07b915f9295a3c9fe6a62c84fc190000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e4000000000000000000000000000000000174ffb89d7715866562d9882acb81ce40758644ca3e0decd546c8f5c349b24fce88214956e7540fac36bcfc105cf34a0000000000000000000000000000000003e06c5f607ccf1e2991828034fcdf91106295e7174b4dca21926169451ee58e737d535af45073e2378206e03c81c421000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f35556500000000000000000000000000000000120935947070451885bf0c328bd83def193831ab9353844a01130074f16a1ff4d20df8459b5ad6a57d5f1959d37aae920000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e400000000000000000000000000000000188c12319c08d113e5b8ce2e18802b092401c540294704d291ea09ab336743d45023deb55a6cabf00dc84303efa2b761000000000000000000000000000000001620a58ad903177c218a25360e4ecd465414b59ddc39c4f5459e7137b1921095ab2eaca3bd038c1d827cf91fc37de68a000000000000000000000000000000000344cafaca754db423544657de1b77025164ccc702f8d45697fb73602302a3cb4511c38f0a76a37415d683398f3555650000000000000000000000000000000007f7dc55c90fa181c55c9b83b7736ee84b3f19d960318e75661dd22c0546d62f4c9e07b915f9295a3c9fe6a62c84fc190000000000000000000000000000000014b0862ac988a169342a4abacfebc5e7e7e8f8ff1166c6ca8fa53613c5fc28fd8b02d9c8d5e7a264b2fa59cd33a0f33c000000000000000000000000000000000f0f79631e7790192c18187144388373d52653cf11dd076688877fa9b5cf58e65fe4332874c301563089b9b3fa2322e400000000000000000000000000000000188c12319c08d113e5b8ce2e18802b092401c540294704d291ea09ab336743d45023deb55a6cabf00dc84303efa2b761000000000000000000000000000000001620a58ad903177c218a25360e4ecd465414b59ddc39c4f5459e7137b1921095ab2eaca3bd038c1d827cf91fc37de68a", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_60", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d4006290000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce0000000000000000000000000000000005b1ce5cb2ae0e9175f2bd557d7869233d65008e0f47c52914fa44c4a6234b70eed236bc5499bb0412d0cbb61c98f93b0000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000b15d92f2301075ab0e3215aa72cf9b130bc8e1bcd9fa36375c4b9d7da430ae3e2b24f417336d8729f44542ee7f561d300000000000000000000000000000000197d90090501e8cdea28eb7963231f1a7b5f716cc3a086acb6e7626600d6544132cac943e8d5cefb5daf0a2f8d4006290000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce00000000000000000000000000000000144f438d86d1d808d528ea60c5d343b427124af6e43d4d9652368ddc508daab32fd9c9425cba44fba72e3449e366b1700000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000eeb38bb167edf3f9a38865b9c1eb32633babd6925e56f5bf16c18c91c6deb403bf9b0bd3e1d278d1abaabd1180a48d800000000000000000000000000000000008381e1347dfdcc60f2bc3ce0288dbce917da182fe48c12b049703af5daa1e2ebe136bac87e31045c4ff5d072bfa4820000000000000000000000000000000008797f704442e133d3b77a5f0020aa304d36ce326ea75ca47e041e4d8a721754e0579ce82b96a69142cb7185998d18ce0000000000000000000000000000000005b1ce5cb2ae0e9175f2bd557d7869233d65008e0f47c52914fa44c4a6234b70eed236bc5499bb0412d0cbb61c98f93b0000000000000000000000000000000006a3a773638c0b4a13e7ea399ac319f5ea55ed533aca32a933d69d8198ae997a66d1e32a02683e7fc5c1ec597106848f00000000000000000000000000000000155ef036f60a5b11697581265293cc4c6eebd3fdf500540529b6997c27a3be31212aee5cdfea6cd95d6d5bf83a8ce5aa000000000000000000000000000000000eeb38bb167edf3f9a38865b9c1eb32633babd6925e56f5bf16c18c91c6deb403bf9b0bd3e1d278d1abaabd1180a48d800000000000000000000000000000000008381e1347dfdcc60f2bc3ce0288dbce917da182fe48c12b049703af5daa1e2ebe136bac87e31045c4ff5d072bfa482", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_61", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d0000000000000000000000000000000007efcb9da7b7ff0f4a1d92489ad76c59158bcc42c5c7a93067772a6d9ef1d3b6df9360d0fc1214e7dec02aaaf7b118bf0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf2300000000000000000000000000000000005c35f3372f1ec9845bd04ea722fbed2be1388abf59e622dd3dafb4b3af49bc5fba9e20235e7e58973fedf4b8b720691000000000000000000000000000000001111d18d621070509805d306a31c109701288fd55d4c0644349deb080c6591b6e852b4f7e009b80019513de7f2fce17d00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d000000000000000000000000000000001211464c91c7e78b00fe156da874407e4eeb7f422dbd698effb9a83357bf226d3f189f2db541eb17db3ed555084e91ec0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf23000000000000000000000000000000000143db2b6c68dfa02055ea2cbd11bee04a663c2d8fde6b0919355d755bbbc5a5e23021dfc7b6c1a76460020b4748da41a0000000000000000000000000000000008ef405cd76f7649b315d4afa02f9c40634ebbaf96390c7b3292e798ea4b646d36594b06d14a47ffa0adc2180d02c92e00000000000000000000000000000000000707c711f77bb425cddc71ecf96a18b6eb0bed7f012c4f6cc9431003f2e1ac17f7c1f68c4965a4fcc273a3db93451d0000000000000000000000000000000007efcb9da7b7ff0f4a1d92489ad76c59158bcc42c5c7a93067772a6d9ef1d3b6df9360d0fc1214e7dec02aaaf7b118bf0000000000000000000000000000000006a90568fa25b401756e3f86b5300c4d3b626dc6274f4685e8a9f56ec5ca2afce36a1fdc6d3414edc8780c4e650f10dc0000000000000000000000000000000012e41e8e0dd10b3ee31fa866753aa5d9db7669153b141114cdb2ef7fa6df5db27aef0cc70e76a741eae504b038ecf23000000000000000000000000000000000143db2b6c68dfa02055ea2cbd11bee04a663c2d8fde6b0919355d755bbbc5a5e23021dfc7b6c1a76460020b4748da41a0000000000000000000000000000000008ef405cd76f7649b315d4afa02f9c40634ebbaf96390c7b3292e798ea4b646d36594b06d14a47ffa0adc2180d02c92e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_62", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000eb29e948adc9e1816c67a7865517fbc91610b2eb30da1d8a1e15c5f62e71a1fd1f40d4d59b23bea7edeba79829010e6000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000000e7e532ee4b892af39f8a3db7a05cc77a6eb0b3d977c17076bac4a52d5ba003a0ac1f902a4257791a45370eb88426a70000000000000000000000000000000016a556050e4905fa74b5061e3874f05cc7a6c5b049bd3bb7c34adef5a77c393239a600542a4401c3e61978ee6515a30e0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000b4e7355aea3488234552d3dddfa2d1ad3164056407770e6c54f764193c9dc044cb7f2b157a1c4153b2045867d6f99c5000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000019192cb74b345d6f577c1d788bab500fea089ad11a0d514ef0760dfbc95556207dffe06e8711a8869fb9c8f1477b840400000000000000000000000000000000035bbbe52b36e09fd666a1980ad6bc7a9cd085d4a9c7d707a3e5f3ab4f34bcf1e505ffaa870ffe3bd3e587119aea079d0000000000000000000000000000000004b3c0e8b240b79c55f02833c2c20fa158e35c941e9e8e48247b96cb1d4923641b97e766637a3ced9fbef275ca9bd1ea000000000000000000000000000000000eb29e948adc9e1816c67a7865517fbc91610b2eb30da1d8a1e15c5f62e71a1fd1f40d4d59b23bea7edeba79829010e6000000000000000000000000000000001310a8cebed1491bb6399abe3a08fb25ad6ca00feb5db62069bc5bd45a57c167aaf06a628a3f18aa990bb389173855b100000000000000000000000000000000134655489380a9ae9cfbc3f4c6a1aa5b6dbe0a994e681915602c1d197c54bf3da6fb2df54eec3634ea87bf3fa92a69740000000000000000000000000000000019192cb74b345d6f577c1d788bab500fea089ad11a0d514ef0760dfbc95556207dffe06e8711a8869fb9c8f1477b840400000000000000000000000000000000035bbbe52b36e09fd666a1980ad6bc7a9cd085d4a9c7d707a3e5f3ab4f34bcf1e505ffaa870ffe3bd3e587119aea079d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_63", - "Gas": 207000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d0000000000000000000000000000000002f2e4467cdc15f1e57d75d6f5c172637df589590863bb437cc5166314e6362b7cd0d7499176b94529979849624cb432000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d29000000000000000000000000000000000264dd2fa407109abaf47d89c3d64542fd6d470579dfe0a98cc73f2fa3f6252bb9356ba39f3c92c1a6343c72d9cc4e5a000000000000000000000000000000000c34a091319b052226395b96f20fa37deb11b766b4b46811fa24799e5b5bfb20813a956524b7be7ea941b63a1c9a5a2c000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d0000000000000000000000000000000002f2e4467cdc15f1e57d75d6f5c172637df589590863bb437cc5166314e6362b7cd0d7499176b94529979849624cb432000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d29000000000000000000000000000000000264dd2fa407109abaf47d89c3d64542fd6d470579dfe0a98cc73f2fa3f6252bb9356ba39f3c92c1a6343c72d9cc4e5a000000000000000000000000000000000c34a091319b052226395b96f20fa37deb11b766b4b46811fa24799e5b5bfb20813a956524b7be7ea941b63a1c9a5a2c000000000000000000000000000000001465358836eb5c6e173e425f675aa231f9c62e9b122584078f2ab9af7440a4ce4ac2cd21ce35a0017b01e4913b40f73d00000000000000000000000000000000170e2da3bca3d0a8659e31df4d8a3a73e681c22beb21577bea6bbc3de1cabff8a1db28b51fdd46ba906767b69db2f679000000000000000000000000000000001360612f80227a2fc50a2dbdb3a49db16bd9f0ae401e2fb69408d990284cec05a1c29696f98b16d83a3dab6eac8678310000000000000000000000000000000001223232338ce1ac91e28b4c00ef4e3561f21f34fc405e479599cced3a86b7c36f541370bfd0176f785326f741699d2900000000000000000000000000000000179c34ba9578d5ff90272a2c7f756794670a047f79a53215da69937152bad0f86576945b12176d3e13cac38d26335c51000000000000000000000000000000000dcc715907e4e17824e24c1f513c09597965941e3ed0aaad6d0c59029b54fb039d716a998c9c418110bd49c5e365507f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_64", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000cab5ed8dc53e9c891df449bd199776adbfc193fc8d6bebf9716610fd4db6def608df059bf29fe43dbf1bf0aa52c1b7f0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c8530000000000000000000000000000000003bdbb702a5d2d8a5b2d10ed605627c1413eff588ac82966ca516dd7c2dc617b46a612308182759201efb7e6c6e1d8b2000000000000000000000000000000000bb2d13f201626fb4a2d6c1dfa03fe41a4fbb60b35d623d640cd430b8fb84afd3ff0b371714aaca303bcd4d3d548827e000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000cab5ed8dc53e9c891df449bd199776adbfc193fc8d6bebf9716610fd4db6def608df059bf29fe43dbf1bf0aa52c1b7f0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c8530000000000000000000000000000000003bdbb702a5d2d8a5b2d10ed605627c1413eff588ac82966ca516dd7c2dc617b46a612308182759201efb7e6c6e1d8b2000000000000000000000000000000000bb2d13f201626fb4a2d6c1dfa03fe41a4fbb60b35d623d640cd430b8fb84afd3ff0b371714aaca303bcd4d3d548827e000000000000000000000000000000000ab6e2a649ed97be4574603b3b4a210f0748d8cddf132079e0543ec776ceb63902e48598b7698cf79fd5130cebaf0250000000000000000000000000000000000d55b3115d2bfcd1b93c631a71b2356c887b32452aae53ffd01a719121d58834be1e0fa4f22a01bbde0d40f55ad38f2c0000000000000000000000000000000002fec3b2e25d9300b9757cbe77857d7220d91a53fc29f3b7a0da5c4e0815882d1cc51a40a60fa8e1ae01296c209eda0a00000000000000000000000000000000041ff1a77aca41f7aaeec13fb5238c24d038e2e566b611203c430d7ac6251d545ed4a60e9e0087d6baa36272c7b1c853000000000000000000000000000000001643567a0f22b90fefee96c8e2f5851623384c2c68bce9589cdf64c933d494a8d805edce2fd18a6db80f4819391dd1f9000000000000000000000000000000000e4e40ab1969bf9f00ee3b984947ae95bf7b9579bdaeeee926638f9566f8ab26debb4c8d4009535cb6422b2c2ab7282d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_65", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf1000000000000000000000000000000001528dcaae381eb764333992e28ed557034ba5413c5b64df40ef3150d2771e5d1cd8c211ca22075c7436e2582960ab3b400000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000fd913e00fb884cc217475cb69e1fafc298d5c38ee3bd5fbf68fa9c777b79f5ec111aff51fa0184023fec7c9cc881bf0000000000000000000000000000000000c45786b44e8dc531f1eb777adb0e146a963e46ab65d49a8ce9978607e5aa5c58b2880b8018a9ac97add3ca5c2e65beb000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf1000000000000000000000000000000001528dcaae381eb764333992e28ed557034ba5413c5b64df40ef3150d2771e5d1cd8c211ca22075c7436e2582960ab3b400000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000fd913e00fb884cc217475cb69e1fafc298d5c38ee3bd5fbf68fa9c777b79f5ec111aff51fa0184023fec7c9cc881bf0000000000000000000000000000000000c45786b44e8dc531f1eb777adb0e146a963e46ab65d49a8ce9978607e5aa5c58b2880b8018a9ac97add3ca5c2e65beb000000000000000000000000000000001654e99ebd103ed5709ae412a6df1751add90d4d56025667a4640c1d51435e7cad5464ff2c8b08cca56e34517b05acf10000000000000000000000000000000004d8353f55fdfb2407e80e881a5e57672fbcf7712dcec4cb583dbd93cf3f1052511fdee20f338a387690da7d69f4f6f700000000000000000000000000000000123a19e1427bac55eabdaec2aeeefadfca6e2b7581a5726c393bede2efd78af04e6cb986aa8d8d5c845bbbc28d62e7a00000000000000000000000000000000018026687f43591dac03a16fce0c4b8020469ec309bdbf9f0f270cf75e262abf4ae55d46f0b4ff130b7bbe2430bd0c9f4000000000000000000000000000000000a27fe0a29c761ce29a731ead969b1db3ae9ef4c05493cc370a128d97ef956c55d9a500991b3e7bf9600383633778ebb000000000000000000000000000000000dbb997ef4970a472bfcf03e959acb90bb13671a3d27c91698975a407856505e93837f46afc965363f21c35a3d194ec0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_66", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec275080000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c5100000000000000000000000000000000010ee94e9470765ac32b5648f1cd7d745a793dbd46dc95fa32db86929eec385e50cb35755120480be0956a2a342a46d900000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec275080000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000b4d1c17ec6597484ae95466d3ca0656f8226c5127b4068f46fcaef6a77d9418d75f25cc92c1b7fd03c825514cbbaa640000000000000000000000000000000003110cf859c0d28c6ad8c2c0d0481a4d0d09bb2000aab784939e9f819a6dc3a7a18190293cfd2a106149b5c1a13d35a30000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c5100000000000000000000000000000000010ee94e9470765ac32b5648f1cd7d745a793dbd46dc95fa32db86929eec385e50cb35755120480be0956a2a342a46d900000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000b4d1c17ec6597484ae95466d3ca0656f8226c5127b4068f46fcaef6a77d9418d75f25cc92c1b7fd03c825514cbbaa640000000000000000000000000000000003110cf859c0d28c6ad8c2c0d0481a4d0d09bb2000aab784939e9f819a6dc3a7a18190293cfd2a106149b5c1a13d35a30000000000000000000000000000000001bb1e11a1ccc0b70ce46114caca7ac1aba2a607fea8c6a0e01785e17559b271a0e8b5afbfa8705ecb77420473e81c510000000000000000000000000000000018f2289ba50f703f87f0516d517e2f6309fe0dc7aca87cc534554c0e57c4bdc5cde0ca896033b7f3d96995d5cbd563d200000000000000000000000000000000000353798691ffba215b6458a47823d149e4e2e48c9e5f65df61d6b995889f3b0e2b34824e4ffa73296d03148c607c26000000000000000000000000000000001190ba585a928413dc3cef3d77b2cff99b053cadcb13b2529c74171a094d479a259678dd43a3ef2a2e597223eb7fd35c000000000000000000000000000000000eb3f5d24d1a4f520032534f6f81a6806c54df33cbd10c30203423aa4f33620b474cda321e924802b636daaeb34400470000000000000000000000000000000016f004f1dfbf140de042e4f57303928a576d9064f2da5b3ad392331f5c43327c7d2a6fd57456d5ef58b54a3e5ec27508", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_67", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab0000000000000000000000000000000004acd0ba7577ffe37bdeeaf5810b5a8a4a6b51c3c02bec4e0c6f0cfb4f12283120d283c12ecb7e4be7063fefb37a578c0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d00000000000000000000000000000000175da48b3c4c64d6eb26b45475ca7240a0923333b1bf7a6ef37c758ddceb0291da8085580f004814972d4afad7ececab000000000000000000000000000000000a8cb418c0192fdb509c33a79feb88c60226ee228a62a2c1be2b8c1ab9a0f711d11c15eae9f030491dcf70ed47e2678c0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab0000000000000000000000000000000004acd0ba7577ffe37bdeeaf5810b5a8a4a6b51c3c02bec4e0c6f0cfb4f12283120d283c12ecb7e4be7063fefb37a578c0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d00000000000000000000000000000000175da48b3c4c64d6eb26b45475ca7240a0923333b1bf7a6ef37c758ddceb0291da8085580f004814972d4afad7ececab000000000000000000000000000000000a8cb418c0192fdb509c33a79feb88c60226ee228a62a2c1be2b8c1ab9a0f711d11c15eae9f030491dcf70ed47e2678c0000000000000000000000000000000012ecb4c2f259efb4416025e236108eff7862e54f796605cc7eb12f3e5275c80ef42aadd2acfbf84d5206f6884d8e3eab000000000000000000000000000000001554412fc407e6b6cf3cbcc0c240524d1a0bf9c1335926715ac1c5a5a79ecdf2fdd97c3d828881b3d2f8c0104c85531f0000000000000000000000000000000018b0cd0360c5d5bf8254725c19976345cd84d32d0d770286444fe29dfdbc495dd58407ee8d48ec1004971f249453b8460000000000000000000000000000000009a6ea13f5a5a279ec3bb86cc028a1685d84135ed5fe99cd6b6fb380a42c3af5497e3ba5ea558618487cf953172a376d0000000000000000000000000000000002a36d5efd3381c35ff4f361cd813a96c3e5185141c5985073b45d1319c5f392442b7aa6a253b7eb22d1b5052812be00000000000000000000000000000000000f745dd17966b6befa7f740ea360241162505d6269226ffda90546863d0fff124d8fea13c763cfb69c2f8f12b81d431f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_68", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e20000000000000000000000000000000012ee6884c9d68bdabe8f4aa92aa613129993aad6a7aafffef1922c910cbd3f8b4ae8a810c59a0b9de0a79d4e5db13232000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b00000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000001669360d7591ed2362569fc05c4912fcd7ffe60dd26f533087b3099eb6603336863793d2b976bbff0edf4765066dc66c0000000000000000000000000000000006653bf1218a486d94578b5d40ff9a09b4e22325ba3d5abcff3d64652440d68ed5f69e3a215003a1db10c01843704f5000000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e20000000000000000000000000000000012ee6884c9d68bdabe8f4aa92aa613129993aad6a7aafffef1922c910cbd3f8b4ae8a810c59a0b9de0a79d4e5db13232000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000001669360d7591ed2362569fc05c4912fcd7ffe60dd26f533087b3099eb6603336863793d2b976bbff0edf4765066dc66c0000000000000000000000000000000006653bf1218a486d94578b5d40ff9a09b4e22325ba3d5abcff3d64652440d68ed5f69e3a215003a1db10c01843704f5000000000000000000000000000000000010dac3e5885cc55f3e53b3fdd5d28b2d78ceeea2b669757a187de0ce3f28b586e451b119cdb7dc8b97d603f2bb700e2000000000000000000000000000000000712a9656fa95abf8c8c5d0d18a599c4cae3a0ae4bda12c0759ea60fe9f3b698d3c357edebb9f461d95762b1a24e7879000000000000000000000000000000001431c5161fc51024c5708496a1f9545c3d4c05ef9e2c91154e22ebfe251017fc61ba54c679ba2ad6b8314bfd8d6272c900000000000000000000000000000000098f2e8b6d3fcf9fb27e912af57b45d3d35a7c5471b9ea2c85262c0efb44c435cd949f23d7d40f14b6b6d4d92cb8412e000000000000000000000000000000000397dbdcc3edf976e8c507f5e70299da8c7765772115bf8edf7dc9024050c2ed98746c2bf7dd4400ab1fb89af991e43f00000000000000000000000000000000139bd5f917f59e2cb6c41c59024c12cdaf95285f3947b80267f36e3bd2701f9548b561c49003fc5ddeee3fe7bc8f5b5b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_69", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e5590000000000000000000000000000000006abf7ef1d5e3484992225b5a59791a68cc7e1e0f8aaf2415a9f759f2dff53f62aecf23e0443fdf37bb3775be9f5c981000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b000000000000000000000000000000000082385363502637bd8d030855032ee447fdfd7f0bc1eb14c5f00be2f5a7f30867483a066590a5fa22229e16c2dc00ec0000000000000000000000000000000009aa4ff672d1afdc24d89aa21616fbef5d0eef0b60307c7e193085e89db01dca0666b4201544d9aec8614ca14c22641e000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e5590000000000000000000000000000000006abf7ef1d5e3484992225b5a59791a68cc7e1e0f8aaf2415a9f759f2dff53f62aecf23e0443fdf37bb3775be9f5c981000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b000000000000000000000000000000000082385363502637bd8d030855032ee447fdfd7f0bc1eb14c5f00be2f5a7f30867483a066590a5fa22229e16c2dc00ec0000000000000000000000000000000009aa4ff672d1afdc24d89aa21616fbef5d0eef0b60307c7e193085e89db01dca0666b4201544d9aec8614ca14c22641e000000000000000000000000000000001889ef0e20d5ddbeeb4380b97ed7d4be97ef0def051d232598b2459a72845d97fa5c1264802ab18d76b15d8fbd25e55900000000000000000000000000000000135519fb1c21b215b1f982009db41b30d7af69a3fada207e0c915d01c8b1a22df3bf0dc0ad10020c3e4b88a41609e12a000000000000000000000000000000000caecf650a12bb629ebd3b978ef9c2d4486f8ce21d515451ecdf01d27740f41b719d5a952e737c83641953a8c8b3a1bb000000000000000000000000000000001641ca29ff6016af335499dfc7167b3d961a25b7f61008c27b3cb13d3cb28fb5096413b1c7f1ca18e5d3b5017d6fed1b00000000000000000000000000000000197ed996d62fc0628d8ea4adee487df31c794e05e7c327aaa140c6be0109031bb763c5f84bc35a0597dc61e93d23a9bf000000000000000000000000000000001056c1f3c6ae36be26430d142d34b0e807685c79935496414e004cb85900d85a18454bde9c0f2650f19db35eb3dd468d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_70", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf9250000000000000000000000000000000001b7a86c4142843a854dd0937bdbfd833a34fb15303d753e3f41eaf19f4fd9a6af785804d5ae2c3b99044cc13e6ca4b60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f00000000000000000000000000000000118871ec2ef96fd3a5b465133902c6f108eea08781ff754f1776dc029889a958b56943ad041d3a98a5f8fad5530e0cb2000000000000000000000000000000000d8b09f53d16443f4c1b0272d95999130c034720b02c3874a80a014f170c65c87538e22f0025d5c08da9e3532f0ac62c0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf9250000000000000000000000000000000001b7a86c4142843a854dd0937bdbfd833a34fb15303d753e3f41eaf19f4fd9a6af785804d5ae2c3b99044cc13e6ca4b60000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f00000000000000000000000000000000118871ec2ef96fd3a5b465133902c6f108eea08781ff754f1776dc029889a958b56943ad041d3a98a5f8fad5530e0cb2000000000000000000000000000000000d8b09f53d16443f4c1b0272d95999130c034720b02c3874a80a014f170c65c87538e22f0025d5c08da9e3532f0ac62c0000000000000000000000000000000008726a32d489a5ea1c1b314dc4d400d995d0eb8b49d47e65a6ac8fd0e6ec0cda1c637ee314c0c5d1ad72cd3588ebf925000000000000000000000000000000001849697df83d625fc5cdd722c76faf542a42506fc3479d8127eee7af57611c7d6f33a7f9dba5d3c420fab33ec19305f50000000000000000000000000000000009c7164f8d40c7e9ca571c46f8edf1c4a961779e55f6b10ffc44d76da78adadb83195d757949be39631c6a53d2d67fae0000000000000000000000000000000012cd5149125e7cc21bb5349be7fe03d5854ee73ba515021b6dc87e81ce1e1fa3e386fcb0de80977b9329e72ad54f929f0000000000000000000000000000000008789ffe0a8676c6a56742a30a48e5e65b88aafd71859d704fb9f69e5e274ccb6942bc51ad36c5671406052aacf19df9000000000000000000000000000000000c7607f4fc69a25aff00a54369f213c4587404644358da4abf26d151dfa4905ba9731dcfb12e2a3f2c551cacd0f4e47f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_71", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000008151a15a13daeee49a82737118d488005fa7ed1869bc458f8af88e7341e0a48b5d8f129f6eb071fb07c11887f4d543800000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000efb08850063e94f4ce935ef65928deaabafa580a1c0a8e92b7f59efc09adf240f5363caedf8a212170e8d39120cbf74000000000000000000000000000000000838486201e313e21e62bbde270d9804a45b41a70e1c072804f4ca2a2f5ba6d151f15cc19958f0f2c6cd337a8b6c69de000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000008151a15a13daeee49a82737118d488005fa7ed1869bc458f8af88e7341e0a48b5d8f129f6eb071fb07c11887f4d543800000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000efb08850063e94f4ce935ef65928deaabafa580a1c0a8e92b7f59efc09adf240f5363caedf8a212170e8d39120cbf74000000000000000000000000000000000838486201e313e21e62bbde270d9804a45b41a70e1c072804f4ca2a2f5ba6d151f15cc19958f0f2c6cd337a8b6c69de000000000000000000000000000000001688c63e325569855bc2e51d668cef112b2479efa33519fe7f45eab89e275e2c4652cf8c2814f179935ccf1d24d8bd0f0000000000000000000000000000000011ebf7d4984237ac0173807f31be64575e7cccb36ce94e666e8149b9c292ebdb68d30ed4ba68f8e00982ee7780b2567300000000000000000000000000000000093c423917d10edc429acd927def56ab4f07254b3892762aa7056f24224528aa0f528fe8538ca996ca63506c84af73270000000000000000000000000000000003fd3ba68878485e25ccaa2539eed0a97743ae9f5b848e9d83c8ea60f7ad0f1cc6d94a59498f79dcab2bfcc2fdbacfed000000000000000000000000000000000b060965391bfd4afe3271c6ddb91eecb8c7a60451c469d63bb178b1361617000f589c33c35b5deda2f072c6edf2eb370000000000000000000000000000000011c8c988379cd2b82cb8ebd81c3e14d2c01c09dde5690b97623c0876c7554f52ccbaa33d17fb0f0cf331cc85749340cd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_72", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a07060000000000000000000000000000000000876cf6553b21053e0d7a4449cd137fd946f2de0f7032f535f54914a8ae7da5afbe765bdfa3a0cdea0a50e1ed43bce800000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000afb70d8856591b980a2e4144357f4cb75fb367f5319786fb7fa2b656f9ed8facbdfb0b26346349986342ed4f34fae4900000000000000000000000000000000012670f096c4b225332cc181df91d6317c27071668f04226f807b0e17506fed0001c11613598926e38fce506ba02c6c8000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a07060000000000000000000000000000000000876cf6553b21053e0d7a4449cd137fd946f2de0f7032f535f54914a8ae7da5afbe765bdfa3a0cdea0a50e1ed43bce800000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000afb70d8856591b980a2e4144357f4cb75fb367f5319786fb7fa2b656f9ed8facbdfb0b26346349986342ed4f34fae4900000000000000000000000000000000012670f096c4b225332cc181df91d6317c27071668f04226f807b0e17506fed0001c11613598926e38fce506ba02c6c8000000000000000000000000000000000bb6f731b345bb1319b9acab09c186449a51dad8b6526251bc58e958cfd933137067e6f778b019f131cc7b23e08a0706000000000000000000000000000000001979a4f3e444c5950d0e2d71f97e99578b3058a6e414dfca313b898c4e02787e6eed89a2d1b05f31cff4af1e12bbedc300000000000000000000000000000000039d8e90425810a0b2fb5c915905863eb2da363ad4188e42cedce678bdd0f51eca0a96b78ab9e082d59dcd10e3c3c97a000000000000000000000000000000001973250dc31d16f658323d021dddc5439ef4396b6ed735f108cd7b27feb1b508daf863ab6431a77ec0b10cf7e001244f000000000000000000000000000000000f05a111b41a54e0ca78c3a1fff3b80bee7c1505a06b9a4faf36a73b87121d2952cc4f4c4e0dcb6633cad12b0caffc620000000000000000000000000000000018daa0f9a2bb347517eee63463b9d6a5e850446e8a94d0986f2921bf81a9f7541e8fee9d7bbb6d9181021af945fce3e3", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_73", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c2000000000000000000000000000000001093356407cff41779ce8f3d53dfe7a04edc8ce7192ddfeeb4329c38152cf1875d0df9ffeced95f1c7fae7d124649f21000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a903505000000000000000000000000000000000227280838fae5023ab2dcb23f6470b056dd6c87acf848e339d5164981a6abcbfb3c7084235f0749b2f5a4957f17cc62000000000000000000000000000000000b43329a7230c0dc0ee61c43a13e90ce24df40a52a415a2740cb3faa64cfe21058aaae5ea8f69364cd72d2cd6543fe9e00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c2000000000000000000000000000000001093356407cff41779ce8f3d53dfe7a04edc8ce7192ddfeeb4329c38152cf1875d0df9ffeced95f1c7fae7d124649f21000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a903505000000000000000000000000000000000227280838fae5023ab2dcb23f6470b056dd6c87acf848e339d5164981a6abcbfb3c7084235f0749b2f5a4957f17cc62000000000000000000000000000000000b43329a7230c0dc0ee61c43a13e90ce24df40a52a415a2740cb3faa64cfe21058aaae5ea8f69364cd72d2cd6543fe9e00000000000000000000000000000000078cca0bfd6957f9aff9731b45fdbdbeca6691f6fe6bf0b7847859c77478037e14864b202b235953ac7da231367324c200000000000000000000000000000000096ddc8631aff282d14d1878ef6bc537159abe9dda5732d0b2fe3668e184049cc19e05fec4666a0df204182edb9b0b8a000000000000000000000000000000000eff44a5e3b9fc8ffe31771fbcabea6efbd68384c5931216a2b7465aaa2566ee116b7daeea632677f35379107f7334f0000000000000000000000000000000000c3c942373f69c2c9631cef1c6bbb1a4567d5b95500409d4f2c6bf4a66ee263e6f167e22790badea0eac4a541a9035050000000000000000000000000000000017d9e9e2008501981068cb0403e73c270d99defd468cc9dc2d5bbc57750a4a58236f8f7a8df4f8b607095b6a80e7de49000000000000000000000000000000000ebddf4fc74f25be3c358b72a20d1c093f980adfc943b898266592f691e11413c60151a0085d6c9aec8c2d329abbac0d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_74", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e0000000000000000000000000000000007007c89288b69f16870dc857a02cd071db8178e578fd2b78fcd5edb5050dcded107a1c1c0071d45e4c4af364bc9400800000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000018034dc4ccb64f0700b5e12b89d531cd9ccc7a399c1f36d08bbe277ccd8dd970eb00606d6e12bca68291897a817637d200000000000000000000000000000000069e1dd2b22d8ce5ce1e0969e35e07abcfd97f8f3b6d8fa724a0feb9ea78b603391caea3172f50aa222f5fc82bdb18e5000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e0000000000000000000000000000000007007c89288b69f16870dc857a02cd071db8178e578fd2b78fcd5edb5050dcded107a1c1c0071d45e4c4af364bc9400800000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000018034dc4ccb64f0700b5e12b89d531cd9ccc7a399c1f36d08bbe277ccd8dd970eb00606d6e12bca68291897a817637d200000000000000000000000000000000069e1dd2b22d8ce5ce1e0969e35e07abcfd97f8f3b6d8fa724a0feb9ea78b603391caea3172f50aa222f5fc82bdb18e5000000000000000000000000000000000b3a1dfe2d1b62538ed49648cb2a8a1d66bdc4f7a492eee59942ab810a306876a7d49e5ac4c6bb1613866c158ded993e000000000000000000000000000000001300956110f47ca8e2aacb30c948dfd046bf33f69bf54007d76373c5a66019454da45e3cf14ce2b9d53a50c9b4366aa300000000000000000000000000000000081da74d812a6718e351c062e93f9edb24eff830be5c44c3f21cca606f5b1287de8ba65a60d42cbf9740c9522fcdc9eb000000000000000000000000000000000eb1d38fd394b7e78dfaeb3b3b97d3d928c16472ee74ae0be1ec3efa510b9bb64cec369793219ceab55a0ed0ece23de80000000000000000000000000000000001fdc4256cc997934a65c68ab9767b09c7aad14b5765dbeedb72ab2429231cb333ab9f9143414359376d76857e8972d9000000000000000000000000000000001362f417875259b47cfd9e4c5feda52b949dcbf5b8178318428fd3e70c384020e58f515b9a24af5597cfa037d42491c6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_75", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000a76ccda2ca736ce935b4b88e08bbf183f69e2b3f5a471662a5de571976e7d4264021db88b919c896bbbb8128732c3e3000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000009060f4c03cbefb8f46332a22d5a2be92b167e493cca773121c9bcb485ff3c100df3404737bb08bae60a9dacc4a5c83f00000000000000000000000000000000058eac9c9eddd5f62da6c450254602ebf94e246b3f1a6c5fd27a26cbe1f1f02da4d1176190537db9e264c7e4f28058ed0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000a76ccda2ca736ce935b4b88e08bbf183f69e2b3f5a471662a5de571976e7d4264021db88b919c896bbbb8128732c3e3000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000009060f4c03cbefb8f46332a22d5a2be92b167e493cca773121c9bcb485ff3c100df3404737bb08bae60a9dacc4a5c83f00000000000000000000000000000000058eac9c9eddd5f62da6c450254602ebf94e246b3f1a6c5fd27a26cbe1f1f02da4d1176190537db9e264c7e4f28058ed0000000000000000000000000000000007c00b3e7e50a860e99cdc92235f45a555c343304a067a71b6aaade016ef99bc50e3b2c5e3335d4bdacb816d3c765630000000000000000000000000000000000f8a45100cd8afcbb7c05c2d62bfedbf250d68d0fde0a1593cd2ed2f5f4278e1baa9e24625c263764e4347ed78cce6c8000000000000000000000000000000000b8e764aa5afa4a6e8227d1bc720eeffd72d963458a4963a3bbe697d3da11186a30d90f7a4eda5630f6967095816913300000000000000000000000000000000085d05b570cd58def6ac2f7e80dc18658dc5d0e6a1f5a5cf4d18745e03494654eb1a6d5399ec2c5288890ade446317d00000000000000000000000000000000010fb029e35b3f6e156b8751415f180ee3960cd3bb6ba9b8e456715ec70b1ba1410b8bfb77998f744d3f462533b59e26c000000000000000000000000000000001472654d9aa210a41d74e3661e05a9eb6b292719b46aa65f94b6abd514bf05f679dae89d21008245d79a381b0d7f51be", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_76", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c00000000000000000000000000000000124a601a06d5094945ec8528c5457ea3f8ca710137b6ad48ee7ad93db53c056059dbc8b02d9edf5e2786c575a0bff89a00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d70000000000000000000000000000000014e04221744944c56495e2cb7789acc9f3cb7456d78c44872d593343fcaa575103fc4ea96e61c4729f0887454fa57d6a000000000000000000000000000000000231121026adca019380e499e795165f297bce1b30c633afb6c00329e21b5872d5545b887bef49a43b2ceb284b72710f000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c00000000000000000000000000000000124a601a06d5094945ec8528c5457ea3f8ca710137b6ad48ee7ad93db53c056059dbc8b02d9edf5e2786c575a0bff89a00000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d70000000000000000000000000000000014e04221744944c56495e2cb7789acc9f3cb7456d78c44872d593343fcaa575103fc4ea96e61c4729f0887454fa57d6a000000000000000000000000000000000231121026adca019380e499e795165f297bce1b30c633afb6c00329e21b5872d5545b887bef49a43b2ceb284b72710f000000000000000000000000000000001517dd04b165c50d2b1ef2f470c821c080f604fe1a23f2fa5481f3a63e0f56e05c89c7403d4067a5f6e59d4a338d0b5c0000000000000000000000000000000007b6b1d032aadd51052f228d7e062e336bacda83bbce657678b5f9634174f0c3c4d0374e83b520a192783a8a5f3fb21100000000000000000000000000000000042280b112fdbbd94f647e5b1f4b51d864f85063a5b66e1f1fe5b1a8d280f9bf1db81ad3588f93f8801ff1a3f66b96330000000000000000000000000000000001e0887904228790d03d8b6d17bebdd8659deafa2ebd9b07069ce89fe228824a39966953d14dda1bd6ccce5faf16e4d7000000000000000000000000000000000520cfc8c536a1d4e685c4eacbc2000d70abd72e1bf8ce3839d79f5cfa069ed31aafb15542f23b8d1af678bab05a2d410000000000000000000000000000000017cfffda12d21c98b79ac31c5bb696783afb7d69c2bedf0fb070cf7714959db14957a4763564b65b7ed214d7b48d399c", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_77", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c04200000000000000000000000000000000001b8c085fd1f34fb273da7d651602b326fef7c357c2fb7845f4c17ce95152042af9e51e7d7699b50f3605bacab563a100000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000012098b001cb819309d0b45df8a37854967f88cfa823a69f262fe9a40c564bad8e8a6be94d3f7939ed38305c6fd2d93b6000000000000000000000000000000000099b6e094a1b1eb0ead2e7117f3f9bbf72db98409ef1234c8b3b60fea1048f9e97e3c61fd568ccca1da89f6a484bbe8000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c04200000000000000000000000000000000001b8c085fd1f34fb273da7d651602b326fef7c357c2fb7845f4c17ce95152042af9e51e7d7699b50f3605bacab563a100000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000012098b001cb819309d0b45df8a37854967f88cfa823a69f262fe9a40c564bad8e8a6be94d3f7939ed38305c6fd2d93b6000000000000000000000000000000000099b6e094a1b1eb0ead2e7117f3f9bbf72db98409ef1234c8b3b60fea1048f9e97e3c61fd568ccca1da89f6a484bbe8000000000000000000000000000000000475e66c9e4e434c4872b8537e0ab930165b39f41e04b208d74d3033e1d69dfb4b134ae3a9dc46347d30a6805508c0420000000000000000000000000000000019e585e1d9adf34a98a7cd38de35aa243d7853c19bc21747213c11240d5fa41ff3b21ae033dd664aaac8fa45354a470a00000000000000000000000000000000137e91115129cbaa1ae2bbb79abe5505436bb51ddceeb011d56dc5c3c396b6b00067d6e6108bafca40fc717737487b27000000000000000000000000000000001592fec7d33bffa7f3eebf038e3194513736cc41a143471fb8c55a44c7521c07e4d8368e5c6ee21ed0478f949f3e224e0000000000000000000000000000000007f786ea1cc7cd69ae1061d6b914278dfc7ebe8a714aa8cd04323860314c3b4b36054169dd5c6c60e67bfa3902d216f50000000000000000000000000000000019675b09a4de34af3c6e79452b57b31b6d499200e996008a9e7d1c910ca0ad2a352dc39cb3fd7333182476095b7aeec3", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_78", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a880000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000c8bd020743550a6d27f0052d0037547db204e3fd752abf6758d899a3793fd3cd50c3073df6258c20a2f8e4797cbab700000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a880000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000a42cfd1e09bd5fdf93d4ffec5a6b312a27dfb7b5e5238dc590158156b613c2d15de1e5a1a4ef2f6751e766874ea788d00000000000000000000000000000000000c87de488d68a3ef74410fe4c892cf62d25fb7d9ef6cbf3cb093184803e12066e86020225e3b9899decf8dbe6a20230000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000c8bd020743550a6d27f0052d0037547db204e3fd752abf6758d899a3793fd3cd50c3073df6258c20a2f8e4797cbab700000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000a42cfd1e09bd5fdf93d4ffec5a6b312a27dfb7b5e5238dc590158156b613c2d15de1e5a1a4ef2f6751e766874ea788d00000000000000000000000000000000000c87de488d68a3ef74410fe4c892cf62d25fb7d9ef6cbf3cb093184803e12066e86020225e3b9899decf8dbe6a20230000000000000000000000000000000002291ff240598e2c129ea12292e4a2fc86e03da9bd9fbbb8bddd6f25797003a4688ba2ed3bafd8dfcf0ddd44c3288c1e000000000000000000000000000000000d7541c9c54a95f3789ca7637348378f8956fd451c3266c8f1a34906bf1cf8e7499fcf8ad1f1a73dafcf71b86833ff3b0000000000000000000000000000000016aed55f56416b8f450283c4afea4c606100eed9bf7b8fea9ab4d04797a7bfe3bf0f10cf229f8ce3156869d75beabe6b0000000000000000000000000000000007e5c03e51a513c6f77179bcb5f7d147dcee32426b4365b1c95f434be7f83a5883d1ee5b0e01a636b3e5377542314b75000000000000000000000000000000000fbe421858e4109c51de57b77da4f9c4c1f950099532d9e30e2f7a8b8b4fb9f708cde1a497050d0944e089978b15321e0000000000000000000000000000000019f48a0bf0f27df65ba766a65e831a0801a4ebcd1995a6002a803f88aead1503b7c39fde8ef5c4672020307241958a88", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "matter_pairing_79", - "Gas": 230000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa000000000000000000000000000000001233421a38d77c59bbe1b83992a7a6c964ede5ef83c5a72bd1ba2c0a81b4205ce9a6925718cabcaf4a72ca3d216fbffc0000000000000000000000000000000016b8c22b35af7d925b5c68b6b7b63442e051fdc45542f233f2d97106c4b960eeb47f204c659d16a3a0d3b65ee38ff1480000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb0000000000000000000000000000000010b6db11d4fc3a2b449b8fd189d2e4ed4591bf4258d7b92b3eb152048cb3a3eecb87782691e9b954377fd1f34b38cb0d0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb9630000000000000000000000000000000018d31bd5a7e94ceb18d803969a2001c6eb3bfbcf82c27e88ca60d4c46807d12f116ca71c67d27270c2332205a4ea11bb00000000000000000000000000000000094a36d86483ac6f068017e4b978c7ea1ee58c429aad5994287f809c69fd5235532487d81f6a46ab827f2e0cb4c6df9e0000000000000000000000000000000016114be17b400ba35875d9009b4d8974023a57d32508c9f658a0d82a8efc6b379ce4a3dbf5ca7130c5581f5008806934000000000000000000000000000000000c68cd7b9d3c3d6c559fa3d52da48ebe68e40a44863c332bb90dd151d1281dd3faa34e6c7b07c277affbdbc1b0a43cfa0000000000000000000000000000000007cdcfd000a86a408f39ef7cb0a4060dff8965956fbf6b939576a69674fcd5c735056da7988943506f8c35c2de8feaaf0000000000000000000000000000000003484fbf03d06907efbf3eff8b95789484254dc09e42208b7457619a31f795356a2cdfb24bb6e95c192b49a11c6fb963", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_80", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b560000000000000000000000000000000016c917abe637da21e60378ea7c2682306aded4ff17ccfea742e9ba63590be1b0fd5432ff0d3b72cdcb15943763cbb6bb00000000000000000000000000000000153bdddfe73f21c3593b128d3885f621935585ba1715e1d989e87cf7271897eea3917b81f0f342790f0f7a330ca0c68f00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000c47feeb1a1d2891d986b1660810859c1bba427d43a69b4e5ddeaf77116418138bfc2b7b4aa4c0cc6df10bd116721d5000000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c00000000000000000000000000000000190f4dc14439eccc46d46c5c9b15eeba0bbf2dbca11af4183408afdb15c7bfa26f107cf5fda0c1e0236aab95728eac2e000000000000000000000000000000000db912ff1f62be087194f6503b3b273b48bd0907afde777109522329e54cde1092afd48366af3f334c0df42ee98d8d5b00000000000000000000000000000000135b96feb4f1e712661ce0d13842de1198c589f335141ab1fd7ffc6b9d58de82c300e9fe6dacdefe8e68b6db9298da5100000000000000000000000000000000046a3563d167d8b0a9f74e0c6514fdabd795110cf48caa014947ca90a9eeda3d07dd7dce58d3f2b7b86fab1143946b56000000000000000000000000000000000337fa3e53480c7865182ecbc7252aa6f9987685dbb814182447183d9da514732157ccffa4188d31eee96bc89c33f3f00000000000000000000000000000000004c5340a5240c4d6f1e095290ac5b6b5d121c5cadc6f30e5dd4855a9cf985e357b1a847cc060bd86aaef85ccf35ee41c", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_81", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000a9e191c9775f57810a511c8bd3dca14b3328e20f0983ca72e42e561b5dd1693209b42a11f2faeecd6307dd34cc01d60000000000000000000000000000000000146061b13546754c74a705776656100a9577f1ff939a82ba990d6b885b27c450f824555829bbb19f9b1f636991799cf00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d8000000000000000000000000000000000062783335b87300c97b38e03e5b1318d15a499b29a473c187f930bf34bc1214b4d822725678cbde978c7b5ae6d4bad5100000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc00000000000000000000000000000000021203675e0ae188ec782160e21492a6ee39fa97d922c1ef9bbfd79b82b3fad54fab11ba633fb8f02cf92249d85d9d800000000000000000000000000000000013d98eb6ddf8b68db36819b25d9a7b4a4ed2b1d2593dd6a6e79dc6adaaefd4d8d129d8d949c7421641374a5192b3fd5a00000000000000000000000000000000117821e6c87bb0e04882e95d36dce18ca33a2c8bd0efd5532b33d597804c08ff1799b2d64a95cc84bd31ba45c3b1e822000000000000000000000000000000000887c07c8a9ebe3154950746a4506ff192bb4a05dccb0f4a1a8ac2b8ca0da07190129ba44d9bc8e6c2666027c67d2ddc000000000000000000000000000000000f62f8cda209f1223a7695ed860de2c2b144bd6402ecd61838eded3f40d3df90fe10bd5d92245112e3ce822cb33f8d4b0000000000000000000000000000000018bb0bcf262b7f4583d1375ecce64bd6bb1fcc64fa4b6a93bd9ffbe870fe79df0f29baa92eb844e5c04d09c966e810dc", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_82", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000e96f685e6f87677cda23177f9fe7fd15726ab31e4d85a5725e93d558bdf61437dbc2c9ebcfc6a94705fa70de88a81bd00000000000000000000000000000000157ce060a46912c992587fde3db4c64a705ab7115717031778176f6ea311cb352f3a76f4839be4658470e4b0b9854f77000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a80000000000000000000000000000000013b5317e3ff7540048b19ceebd47c15538d7eb3bf402823b9c348c464afb1000ce0f7ea4c1cb668af5c8cbf77e6a92510000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34000000000000000000000000000000000e4979375cd880e26d00461de629bac880c12e24ede4a7c702f151c34a728a69a021e37b6a1af520a5f47d3a33f8c8a800000000000000000000000000000000064be06bf988929a026a0ac78603eb822b9f6048ff829083cafc465aabb5e623509c8159ef889974c43634088195185a0000000000000000000000000000000011f9a369401d2c376c77b4b414e345e6108b11594b26521b51afe6318648af232bf9f1455a99dc2f9b0207cc78339510000000000000000000000000000000000863492499f4791e71bd8d58dd2444a34e66dd3e3ca1cb3669f4182fafc9ef080a1d8111b3dd754f2405032350732b32000000000000000000000000000000000b6a1b64528770227d79763e494d2d060d50a0530eacb8684147954b6ad194e0a0efd35ff457956b499f58f2177528ee00000000000000000000000000000000048431899516d3d0b8c327d80596e68cf41c94739c6e0fa7ef196332539f2aeeef71890a2db81b9a358e1b4f467a5b34", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_83", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e0000000000000000000000000000000016002a054bdf3cd916b5f8aca47d97feb170e8864da2eff8bbbf19a5b25ac857dbe6daab97dfe15a4e82455d154652e2000000000000000000000000000000000efc6f6c595368288f5687e710e2faebf12bd63a0ca34a527c05f1d925fcedd23c5e2b6708194069a36f858fa510ee410000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000ae10eb4f791aa31e5bd7b6c4d68b04c6744262d8f5e9469b3987b101ff5a3066794e05694a9167b7050c3944b6d84f60000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a0000000000000000000000000000000017f16cffb737dadd52b3c5be258733dc47301474b7351c8dcb8ddb4c519018be08b64efea3336f2b6cfa78e0669dccf9000000000000000000000000000000000f20033541ee3c68655e2c49f5e2fc8afd33255764267e55b3985790d6bb531db7171fa81caae98449ae3c6bb49225b50000000000000000000000000000000000a8382a5f73a7d15c3ee35e5fcaf7142e6d91d71ef30ce7da9c8db2f80c95441dc93674bed244096b71aea40d43c318000000000000000000000000000000000733e9a022695ed6908caf6ec7e67211c6d5ac16ba3fb8e244227f5da787e69e7311fac1e8d102a2d84e6ba98903ff6e000000000000000000000000000000000400e7e4eda0a9c13465af099ece14d8b30662fea5e222c6ab71b8fb44562dcc42c5255319741ea56b7cbaa2eab957c9000000000000000000000000000000000b04a27de02c7e71bbc51fcf3268b1eb734b754ae6e1c86ceb2ae0c7d0b40851e24dd497a93abf96168f7a705aeebc6a", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_84", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a1000000000000000000000000000000001408beb1c3951d79fa43477c5af6894ee3c2ea9605f8ae64a78b51ee7e16ae9641134a9a75735972dbd7b53dd4c9f3bf000000000000000000000000000000000e6c6c9405ff001faa8d8c06bcbd75ee91140f477ef8283d3c5eb3039f16543ca9e7e4162177a7499edb6f3fdb01643f00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a61685420000000000000000000000000000000016aead8bd8c4d5ddc444e15bc83e8f14d377d5e8d756a0255f1387506b9a9add69592241dbd9cab95474d55ac473886200000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c00000000000000000000000000000000062168f0bfd29c44074430158708a1e3b6808bae633ce9506b32eb9124db1a0668d83f2076adffb568ccf289a6168542000000000000000000000000000000000352645e60bb10bc86d6c65a7b0d1dc290ff759c1c2e729a081d4b508b165b46b552ddbcd57a3546658a2aa53b8c224900000000000000000000000000000000050b449c2425926d961af37c4c88e671eac676a1f828def54b76dc04960d0222fb5832ed44c45d5fbb59549d9d24c236000000000000000000000000000000000c6e811987b30ed77c804e647f867186d425411e514e9bf31099cc0f695195729ae970766b2738a928e776511a44f8a10000000000000000000000000000000005f8533875eac92050d86039e855238880b460eeed8c645abfa580b2789a478ddd98b5643be0a68cde274ac22b35b6ec000000000000000000000000000000000b94a5563380e67aa08e1baf868e36e8d3633c3d748cea822ad21f9d579aa1e774c41be88fdc58b61b2390c024fe466c", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_85", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000018a8b48aabc6c003a58593a40b55e54b122994f9ab58cc229d1a0e6a3670244cfe73854f07117dc77dd5c2c81314a17e00000000000000000000000000000000062f6a0a8b9dd56001f0f57f82bb7468d709fb8f33e6729369b015685995ef27abebff9dda55c38b0d9e88a1e0b9fc6c000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000019049c394e547b9b714b5969adcf068b381def6af2b27d1d361d06e9576273a8febb5bf94b5061ccec7afdb5642c0ae8000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f000000000000000000000000000000000c60b948942652a8214d8776b77a6c559ca77eb3a537b0a9abadc3058eac8c1d7840f091acd6c0056d5a71468a2b1ceb0000000000000000000000000000000000fc75b0eb2b6afed9d04e4c957ca64c2c595c1a00d295a23113cbb79f4e827b1ff0a40566039e32cd84024a9bd39fc3000000000000000000000000000000000a8679f08643ff1c4db54e58de15a4828fc80e3f9d80a932b26b49d5c13831b1dc5dc29af2e080eb08e71938e5010fc400000000000000000000000000000000110957f7e9f8e0806bb3d2a811b91c926feab046ef983495f3f768a6cc6e4a6d95bb92facb77d989e53ce5489aa64b3c0000000000000000000000000000000001585d5f8db92696a596141237f5c78c524db68b482c469cca16c436c040d1d720387aafaa4282383c293d37eceb092d0000000000000000000000000000000013d1a7dfade2113a492ab236c090386e8d6d4ff5bf9ea02bfd80bd389d1b06fc72c00060d6fe3c74ac60775e1f45ae3f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_86", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000d81a0809479694fde24e5a3ee7d32deacc25e77f241024666bc3372e80379a722863ea8105f345f1d09e462fc5a8c6c0000000000000000000000000000000001a5be923f1ca5ee876d660fbca5896f1634ef6a83ff8c64dca4ed76d1db2ba4875099fa5a39a09f839731278b307fb10000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000009f7d7b21882455e9f1f24ea120f3eb69f739c1320c37eb2b17e0a271cb03ac6e2b0c55d3518548a005f28b5748b7f59000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa0000000000000000000000000000000013fe38343072af8ef1d8247c3d46b4fd190086ceddfeb767787031368da6a6a6ae849cfc26a24ead499338e37fa337e30000000000000000000000000000000010093a3820fda13babfc82cc313c6e20c503af71d2c1940cb5b2c879da00bb5d3bfb3aa17c3bab75b99fd74a8b742b52000000000000000000000000000000000ba48cbd776dd03a5b69aed3a31b7d151a8d98cd9adc3b9987cf2ac94644a364ebf3d30cf31742e2152aeba0eebc9ceb0000000000000000000000000000000008793a44c730949a9e50e9439d579ff0991dfc49a67a29b1701989ab065e6e937b14ac1bbca5a3dbf79a61837ad18394000000000000000000000000000000000c7f7169a5067d4a6cf6c21254ce79f8b7b4ed0d0144107900749f2e0ead7c7cfc25c156a0f4cba09cf51b9d03a51e3f00000000000000000000000000000000185b5357fa6340abc3ae41a686a623684e425c1a6f85865a8a8be52a24d5ca7f975b6604571a5f603667ced874cf2afa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_87", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b2720000000000000000000000000000000000b76cdde0e1205c918e6e6d324ac3f35d42ebe9bb101f1cd8955acdfa8836f22f1497bced2c93495022b0c335bcaaae0000000000000000000000000000000018340c2a8b079b88595aa50e93251d12e3a5aead2d2add3b72ce82e03a26525aa45fe9b379504392edb0a2a26d7e99dc0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000146696840e8e988d0eab90ea935dd8b5f1272bbb81eb524e523c57d34ad7c5f0f3b721566f51dac4774826b84cc1c82f0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf0000000000000000000000000000000018c6df81d810deaac0b143edf79956c92af7941f7b279db345f838bd583177912fc2eb367616ae165e261014a4d7b1b900000000000000000000000000000000059a7b662af14e0d3c7016cbafedd42173501fc97199c07114f47acdabd930332af4dea84202253b42b6d947b33de27c0000000000000000000000000000000008691df5b245399f24118badfbef3e01a4acd53dc9ab149e407c733df6122fa91f5cbe2f9d247cdbac18b266d3d8f18300000000000000000000000000000000053e6eef4ffdbe239c8bbade8cfc90461d54f281ee6180c271412bf2d64e005d3f0291d3401c324e41067f4dfcc4b272000000000000000000000000000000001949a50c589ec63db98d39491100e8e407345f9b3874f3a28e9b77d2fc28bf31ef976841c4276cb669dc4f3cca42fffd0000000000000000000000000000000001cd05bfae784b11f1c102a7b0268fc480d19cd7c65a3583f4624fc0bc8aa3c97a4c164b3803bc6ccc4e5d5d928110cf", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_88", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c6640000000000000000000000000000000011d7aff6c4512f68031aeb94ce3733ac43659f9fc58fc94c05d99ae80a7656f66b3e3e86843387d1c10f51b4284755150000000000000000000000000000000012a9e7f3804c6b5b25410a82758cd5b6ea1eb150c696b0d67d92cf9eb1f8e17752184d94a4ad2645b1520d6aee1094ed000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d0000000000000000000000000000000009d569f05e69a38231d0f636e1ef040af059a00db4ff09bd2ad82b7e04cc041a33603c2eb9b148e3b1412bdef9740ab400000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be000000000000000000000000000000000c6b634d90c2664b9fa4ccbca35913d23696825350e21f0a6dd5e9abb17497a0a499e1b7b928a57ba8c730158f63b75d00000000000000000000000000000000102ba7f9db164318194ab17f615ca8cc741dab773e8609023c58a722f1e4f209eb4bc3cff7a2b71c08bdd421068b9ff700000000000000000000000000000000042120affcefe4735ae25e192d1cf34e40afdc6d2ebdacde2e23d30709fecfb71960bc9131e3702b27b6fcd5c7a98d170000000000000000000000000000000001998caf5163b0dccec7c8423c4c56a7d0f0b26d9034f707ed07f636f42dac590a2674c1667d70be385c4e626815c66400000000000000000000000000000000082961f3752eb7324800bc217514792b2111abe52df54973615737b8ec3a9f2db36dc1782d20782df8efae4bd7b8559600000000000000000000000000000000075729f6b9337b3f25da9d33cdbed7207a589a342cee61e8e99e030244b814accc93b26a0ca6d9ba08acf29511ef15be", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_89", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca0000000000000000000000000000000018bc90cd83e1271bf0e39b0c80989f0ddcffc960ae466c64ad340cc32607dbdc73eac5b9145e1339fa02a0c3fafcc1df00000000000000000000000000000000124c4bf66a5e015f142e9e4b26421414a60e54ed76c6d4acc0f20b24a25ddf5ec7ef1f561fac9d470a94bcfb2f2698c50000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000e8b0f968ccb230517ef8980be559f410a2c4035a1101e6796d4f7a5ee5c93a19c111d38930bd5bca69405fc35fea7c20000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e60000000000000000000000000000000018129b2f00be24717c906d215beaaa136758aa1730bd0bbe9c0de9b3cbb3c0ea47911817fa322b907cc6fc720cabde05000000000000000000000000000000000b760253acb4c395332c1e3584f60d965a4b0b4f5274f457d05bdafb08546282829ae2c61e482a43136afa03ca0102e90000000000000000000000000000000001462f8080d9b51235a8aa652445f509e3e13e3073769e9a047e8b2bfa5b227f4354bef017d18bf06f7ec98c169abf1e000000000000000000000000000000000070fdbc18112b49bd83f4347922797f2bbd68bf2592ad59041c97948ba7a091bdb3622c804803ad605604ba364dbdca000000000000000000000000000000000144811cb59ebf7e5a380ca9c2b30dc987778224453ea65ab9fcc5ddd0a91a47aac13a459cf5ecc5bffc5f3c0502e8cc0000000000000000000000000000000007b4c5f3cf21e53b36ed096b1d0998c2be68f6977cbe3e12a63ec77c545316c556bce0a891a762b8af6a4304d0d911e6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_90", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca20000000000000000000000000000000017f93d49ec5c34cdc31931cbe2d5b3ad7a6dcd3ea864862aa7b41d5b2f4618c9c92da01e246ff8f34240bcf1de4c1c450000000000000000000000000000000002180a95dbe57c43171e2607593dd3b54344bdbf409dcd0c5706a9a72ad0e26ed60b9e4cb17ea4e7b460adc5a6f6d2de000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a4700000000000000000000000000000000193118d1f237c68a8a0961fb220c0fd6a08853908a039dd57f8ed334063e5316bf83e8c3c3f44420734abbd7ddda31a600000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd000000000000000000000000000000001667fdc9b89d12fb0704fdec910cab1b51ac04219ef6e50f996688b2ceb26dca0e9e8594c5b81fca2e8fc2c8d8fa9a470000000000000000000000000000000000cff9184748200fc11245bb213f9d00c3eef7f4698174e9e7a1ff6cf072a30d5f28173aed5fbbdf46b444282225790500000000000000000000000000000000156901359e5b399168e90ccad27a054d147aa9c4a731294180e395e8e2d458f5537fdac591cdc82fd8bffa4c9fa126ed00000000000000000000000000000000143872757c0a25d85e95a86c5e09175fdbeaf59bae3d1e8a367902d59c662cc3a293ae252443b3201671ad1dbaed8ca2000000000000000000000000000000000207d4a04d23b1cc880275ea6075f929ea097e464b208c94bf7cb545c76add5a557e5fe08ce4070c77be430e21b38e660000000000000000000000000000000017e907545d9a6a5733fd81aeea0dd92221328dc5b2e745b3102a28f9cbe013b548a061b1ffd55b18059e523a5908d7cd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_91", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c01300000000000000000000000000000000034f7418d96bdbe4f1ed5996fc9e9e99233a5cb3aad717b3717e91ff94fecaa67250ba5b27dcf59c6e36aae08d22983a00000000000000000000000000000000100cd7ea3c342aa2c15e9c6121a1cfecf611235add08290cf9cb8ea54e8ff523e17a0b5dc41e6d07992e5927e3ff6157000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000007025f1c4a5f85a9c1587d4d4a2e620d83d60568343940ffd85e6b1e4fb0f0f53bb08c4f48bf6f45a7dbc3722ecc951e00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954000000000000000000000000000000000217a4c563d730ef545e452038813301933ccc6638321ee5e217dad0be2e3ddc855a14054d0d72b6bcc692a5fb1ac7300000000000000000000000000000000012feb2cdef2060f089c32a68f91d4ac9e0a1461cbf4bd1bf8ed26782a700052ee2fb73af689490ba12233c8dd133158d00000000000000000000000000000000162ea8f985c83d59361ee6beb49cf2a797d8c909e2eccfc61fdc5359d5ac9b10fbaeef2eebea1667b5b9bf8f5d603d6e0000000000000000000000000000000018344ca9d4913e817264ed8119fe4d136f2041b0a99d4b5fe7f2b7f268256eec9fceb27fa61c4225f47babd17759c0130000000000000000000000000000000016b19dd160140ab5592e4e1f46ad0e3e413ceed148adfb0bf5b240a161b22b7dac5b45a389770a634bc8551f72dd12710000000000000000000000000000000009f439fffd4bbbf789bd0b5521a9dcea6e66282a167ce9b26d6543fba82101003d31f4a0ed3592f820d0a6d81c004954", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_92", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000013574b997ee8988aa81db0e2ddb98be2e7005603076fac5cb246f65c869aa7bb3f148c8dde970e34e5e5efce023e633c000000000000000000000000000000000998bc9d41c5d527360fc4e68ba067d3778cf5cf00e5959b5ec52c1595aabe6e2e92d40cb34faa84513d150568c8cfc00000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000dd8d1bd66f4accbc9d0c7dabef7af72f51c67a0d61384647533ad92bba44a312f0be0fa52163176f1aff4e64c00aefb0000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb0000000000000000000000000000000009ec00ea2da59d937d3154d86dbed2957667253401bce9de80e0ffe6df32f36b06404b9e3af08e912a0b4ef091f93efb000000000000000000000000000000000c28402cd28b39ce814adfdb8453fd646f5ae3e41d718e5af1fd250e3b0cabf2efa01f045f3dce88c84f0b19b3fefbb00000000000000000000000000000000001cdfae9234096578b9413f926ef8c6831f2c0f700e25d7553a746aef44238e493f8032e09f67f2fed9676c9611f60e70000000000000000000000000000000019c8bae08d3926997146f7827f00cde863684dd4050ea5da64f6798e7a930d3c1f34046bea0f44232594f5469db566280000000000000000000000000000000006a9c650ba974e0fa2fdf6d3659220f47d76f581ec156662b4e9dc4470164e68df977370d2bcf1cad4191031fdc1476f000000000000000000000000000000001068554cf7ba1173150be2cfb7ab4503ecea55b5f29f7d24086ba68b610637b5f0192bf1fe04557b68c1eafa9736daeb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_93", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000008c7a67b89960da4309888bc6ce31e7efe74867165a8aceda7c7290f8a92687100ccbcd39d4d5a67f21f4b63ecc638320000000000000000000000000000000001cd7978ce28629ed1a9c5433c555b1ebb584f80909599282467e7b2471f591bea1d73e7b0a247aed7de4f1fecc012040000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec0000000000000000000000000000000001648030be79658c134e016a211d311841988065957b35e9bc1580fb6e05e291e747b7a960a50e26a2a3c0cd1634c3585000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a70000000000000000000000000000000014153e01c9e495c5c01c82b3cad9eaf20cf78369ccbabf57fb160ded309cbd1caea3d3df38a7ea5490c67f168e9acec00000000000000000000000000000000003b90ede51e98dd9163b911431789b534aef452b9bd1b423a5d8c2ea1652cd05aa308568a7031d958fc2f32e9cb37526000000000000000000000000000000000c78d84157dc0b102c3843e4c8e88f244cc1b2a27043e07b2fab694a58f93d47e4cf9ca1158a8e30e3d43f94a20d33b50000000000000000000000000000000004842fe0df312f735a9d8af0c2ff7c561ed9cf4add5e3e9402bcff1190f3f36ca91de8edc9472b3ebd27ee2d9afdf8770000000000000000000000000000000011396b6eafe9d8f61a831ef9d6688e586602c5138ddc65d1bf69a9916c1e8db31ddf432b1406a597c7dfb49c1339727900000000000000000000000000000000183398716b5783fb7971e27306f651b8a91efc0462ef799742c8eaeeaf919d08348e8c1700b1b850e220b0e0133f98a7", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_94", - "Gas": 299000, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd0000000000000000000000000000000001652a688dbfd63a1c89452335bdaf248c97c9c6e5a3ad5a126577a6b9ab57075b22987ea8697b459611a5ab164f328400000000000000000000000000000000058a37347c5637808632ae6e8f264e8bde14ebb0ae69828f962f51b728321fea57c5a97ab694f7db175efe7a17d36cb6000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d579500000000000000000000000000000000144401f7eb69f6321eae8dad39dbe2cf4ae58e455474701dd9f1b62c85c7536813e84eb4f9def511eb62e5194288728b000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5000000000000000000000000000000001555535228eb9a24f460df9894d59aa06fc848a8bf8d6c3b51653b1d85734b3c5a2bece161309bd478d356fa198d57950000000000000000000000000000000005bd0ff24e15f0682c6d1a09096fca081991bd3f9f10a2a18d3f1c7470e9a2bc0ac3b149b7750aedce9c1ae6bd773820000000000000000000000000000000000e619d79792ac685030311a31a21203e5172d2e5d20ecf69a1e64158e7fe903b3695fd15432d3ca35562b5a8bd9cbdc20000000000000000000000000000000012394a621a503d1d92df3306649a6c6979816cabeb8f8d27450ec883c4e75f6f7411f3bfd068dc8dee58cdb8ebbd91bd00000000000000000000000000000000189be781abc010602e9262930d8dfdb2d7df81be0de1656554cb5afa3d059f1cc389678008ea84ba23ed5a54e9b07827000000000000000000000000000000001476dab5bd29af19c4e8f947b4255e4b86625fd4451b902fd10180e9ce7ed639c6e65683fabf0824a2a00185e82c3df5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "matter_pairing_95", - "Gas": 299000, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/bn256Add.json b/builder/core/vm/testdata/precompiles/bn256Add.json deleted file mode 100644 index b6fcd550e..000000000 --- a/builder/core/vm/testdata/precompiles/bn256Add.json +++ /dev/null @@ -1,114 +0,0 @@ -[ - { - "Input": "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", - "Expected": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915", - "Name": "chfast1", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266", - "Expected": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204", - "Name": "chfast2", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio1", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio2", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio3", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio4", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio5", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Name": "cdetrio6", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Name": "cdetrio7", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Name": "cdetrio8", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Gas": 150, - "Name": "cdetrio9", - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Gas": 150, - "Name": "cdetrio10", - "NoBenchmark": false - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", - "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4", - "Name": "cdetrio11", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4", - "Name": "cdetrio12", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", - "Expected": "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f", - "Name": "cdetrio13", - "Gas": 150, - "NoBenchmark": false - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "cdetrio14", - "Gas": 150, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/bn256Pairing.json b/builder/core/vm/testdata/precompiles/bn256Pairing.json deleted file mode 100644 index 3fbed6b87..000000000 --- a/builder/core/vm/testdata/precompiles/bn256Pairing.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "jeff1", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "jeff2", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "jeff3", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "jeff4", - "Gas": 147000, - "NoBenchmark": false - }, - { - "Input": "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "jeff5", - "Gas": 147000, - "NoBenchmark": false - }, - { - "Input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "jeff6", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "empty_data", - "Gas": 45000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "one_point", - "Gas": 79000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "two_point_match_2", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "two_point_match_3", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "two_point_match_4", - "Gas": 113000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "ten_point_match_1", - "Gas": 385000, - "NoBenchmark": false - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "ten_point_match_2", - "Gas": 385000, - "NoBenchmark": false - }, - { - "Input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "ten_point_match_3", - "Gas": 113000, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/bn256ScalarMul.json b/builder/core/vm/testdata/precompiles/bn256ScalarMul.json deleted file mode 100644 index b0427fcc0..000000000 --- a/builder/core/vm/testdata/precompiles/bn256ScalarMul.json +++ /dev/null @@ -1,135 +0,0 @@ -[ - { - "Input": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2", - "Expected": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc", - "Name": "chfast1", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", - "Expected": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e", - "Name": "chfast2", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3", - "Expected": "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27", - "Name": "chfast3", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "Expected": "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11", - "Name": "cdetrio1", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", - "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451", - "Name": "cdetrio2", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000", - "Expected": "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b", - "Name": "cdetrio3", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009", - "Expected": "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575", - "Name": "cdetrio4", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001", - "Expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6", - "Name": "cdetrio5", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "Expected": "29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1", - "Name": "cdetrio6", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", - "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb", - "Name": "cdetrio7", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000100000000000000000000000000000000", - "Expected": "221a3577763877920d0d14a91cd59b9479f83b87a653bb41f82a3f6f120cea7c2752c7f64cdd7f0e494bff7b60419f242210f2026ed2ec70f89f78a4c56a1f15", - "Name": "cdetrio8", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000009", - "Expected": "228e687a379ba154554040f8821f4e41ee2be287c201aa9c3bc02c9dd12f1e691e0fd6ee672d04cfd924ed8fdc7ba5f2d06c53c1edc30f65f2af5a5b97f0a76a", - "Name": "cdetrio9", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000001", - "Expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c", - "Name": "cdetrio10", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "Expected": "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024", - "Name": "cdetrio11", - "Gas": 6000, - "NoBenchmark": false - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", - "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b8692929ee761a352600f54921df9bf472e66217e7bb0cee9032e00acc86b3c8bfaf", - "Name": "cdetrio12", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000100000000000000000000000000000000", - "Expected": "1071b63011e8c222c5a771dfa03c2e11aac9666dd097f2c620852c3951a4376a2f46fe2f73e1cf310a168d56baa5575a8319389d7bfa6b29ee2d908305791434", - "Name": "cdetrio13", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000009", - "Expected": "19f75b9dd68c080a688774a6213f131e3052bd353a304a189d7a2ee367e3c2582612f545fb9fc89fde80fd81c68fc7dcb27fea5fc124eeda69433cf5c46d2d7f", - "Name": "cdetrio14", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000001", - "Expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", - "Name": "cdetrio15", - "Gas": 6000, - "NoBenchmark": true - }, - { - "Input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000000", - "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Name": "zeroScalar", - "Gas": 6000, - "NoBenchmark": true - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/ecRecover.json b/builder/core/vm/testdata/precompiles/ecRecover.json deleted file mode 100644 index 4911d6157..000000000 --- a/builder/core/vm/testdata/precompiles/ecRecover.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "Input": "a8b53bdf3306a35a7103ab5504a0c9b492295564b6202b1942a84ef300107281000000000000000000000000000000000000000000000000000000000000001b307835653165303366353363653138623737326363623030393366663731663366353366356337356237346463623331613835616138623838393262346538621122334455667788991011121314151617181920212223242526272829303132", - "Expected": "", - "Gas": 3000, - "Name": "CallEcrecoverUnrecoverableKey", - "NoBenchmark": false - }, - { - "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - "Expected": "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "Gas": 3000, - "Name": "ValidKey", - "NoBenchmark": false - }, - { - "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c100000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - "Expected": "", - "Gas": 3000, - "Name": "InvalidHighV-bits-1", - "NoBenchmark": false - }, - { - "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - "Expected": "", - "Gas": 3000, - "Name": "InvalidHighV-bits-2", - "NoBenchmark": false - }, - { - "Input": "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000011c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - "Expected": "", - "Gas": 3000, - "Name": "InvalidHighV-bits-3", - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blake2f.json b/builder/core/vm/testdata/precompiles/fail-blake2f.json deleted file mode 100644 index 70835aa5b..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blake2f.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "vector 0: empty input" - }, - { - "Input": "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "ExpectedError": "invalid input length", - "Name": "vector 1: less than 213 bytes input" - }, - { - "Input": "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", - "ExpectedError": "invalid input length", - "Name": "vector 2: more than 213 bytes input" - }, - { - "Input": "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002", - "ExpectedError": "invalid final flag", - "Name": "vector 3: malformed final block indicator flag" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG1Add.json b/builder/core/vm/testdata/precompiles/fail-blsG1Add.json deleted file mode 100644 index e58ec0e90..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG1Add.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g1add_empty_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "ExpectedError": "invalid input length", - "Name": "bls_g1add_short_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "ExpectedError": "invalid input length", - "Name": "bls_g1add_large_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g1add_violate_top_bytes" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "ExpectedError": "must be less than modulus", - "Name": "bls_g1add_invalid_field_element" - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - "ExpectedError": "point is not on curve", - "Name": "bls_g1add_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG1Mul.json b/builder/core/vm/testdata/precompiles/fail-blsG1Mul.json deleted file mode 100644 index acb8228aa..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG1Mul.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g1mul_empty_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g1mul_short_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g1mul_large_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g1mul_violate_top_bytes" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "must be less than modulus", - "Name": "bls_g1mul_invalid_field_element" - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", - "ExpectedError": "point is not on curve", - "Name": "bls_g1mul_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG1MultiExp.json b/builder/core/vm/testdata/precompiles/fail-blsG1MultiExp.json deleted file mode 100644 index 2cd28bd3b..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG1MultiExp.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g1multiexp_empty_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g1multiexp_short_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g1multiexp_large_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "must be less than modulus", - "Name": "bls_g1multiexp_invalid_field_element" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000108b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g1multiexp_violate_top_bytes" - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", - "ExpectedError": "point is not on curve", - "Name": "bls_g1multiexp_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG2Add.json b/builder/core/vm/testdata/precompiles/fail-blsG2Add.json deleted file mode 100644 index b1fe9d5b8..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG2Add.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g2add_empty_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "invalid input length", - "Name": "bls_g2add_short_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "invalid input length", - "Name": "bls_g2add_large_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g2add_violate_top_bytes" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "must be less than modulus", - "Name": "bls_g2add_invalid_field_element" - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "point is not on curve", - "Name": "bls_g2add_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG2Mul.json b/builder/core/vm/testdata/precompiles/fail-blsG2Mul.json deleted file mode 100644 index c2f0b89c8..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG2Mul.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g2mul_empty_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g2mul_short_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g2mul_large_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g2mul_violate_top_bytes" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "must be less than modulus", - "Name": "bls_g2mul_invalid_field_element" - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", - "ExpectedError": "point is not on curve", - "Name": "bls_g2mul_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsG2MultiExp.json b/builder/core/vm/testdata/precompiles/fail-blsG2MultiExp.json deleted file mode 100644 index 437f8dfca..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsG2MultiExp.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_g2multiexp_empty_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828010000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g2multiexp_short_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid input length", - "Name": "bls_g2multiexp_large_input" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_g2multiexp_violate_top_bytes" - }, - { - "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac0000000000000000000000000000000000000000000000000000000000000007", - "ExpectedError": "must be less than modulus", - "Name": "bls_g2multiexp_invalid_field_element" - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", - "ExpectedError": "point is not on curve", - "Name": "bls_g2multiexp_point_not_on_curve" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsMapG1.json b/builder/core/vm/testdata/precompiles/fail-blsMapG1.json deleted file mode 100644 index 8550269f1..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsMapG1.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_mapg1_empty_input" - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "ExpectedError": "invalid input length", - "Name": "bls_mapg1_short_input" - }, - { - "Input": "00000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_mapg1_top_bytes" - }, - { - "Input": "000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac", - "ExpectedError": "must be less than modulus", - "Name": "bls_mapg1_invalid_fq_element" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsMapG2.json b/builder/core/vm/testdata/precompiles/fail-blsMapG2.json deleted file mode 100644 index 397a608b0..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsMapG2.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_mapg2_empty_input" - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "ExpectedError": "invalid input length", - "Name": "bls_mapg2_short_input" - }, - { - "Input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_mapg2_top_bytes" - }, - { - "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac", - "ExpectedError": "must be less than modulus", - "Name": "bls_mapg2_invalid_fq_element" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/fail-blsPairing.json b/builder/core/vm/testdata/precompiles/fail-blsPairing.json deleted file mode 100644 index 084e55635..000000000 --- a/builder/core/vm/testdata/precompiles/fail-blsPairing.json +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "Input": "", - "ExpectedError": "invalid input length", - "Name": "bls_pairing_empty_input" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280100000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "invalid input length", - "Name": "bls_pairing_extra_data" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac", - "ExpectedError": "must be less than modulus", - "Name": "bls_pairing_invalid_field_element" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000010606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "invalid field element top bytes", - "Name": "bls_pairing_top_bytes" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "point is not on curve", - "Name": "bls_pairing_g1_not_on_curve" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "ExpectedError": "point is not on curve", - "Name": "bls_pairing_g2_not_on_curve" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000a989badd40d6212b33cffc3f3763e9bc760f988c9926b26da9dd85e928483446346b8ed00e1de5d5ea93e354abe706c00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", - "ExpectedError": "g1 point is not on correct subgroup", - "Name": "bls_pairing_g1_not_in_correct_subgroup" - }, - { - "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013a59858b6809fca4d9a3b6539246a70051a3c88899964a42bc9a69cf9acdd9dd387cfa9086b894185b9a46a402be730000000000000000000000000000000002d27e0ec3356299a346a09ad7dc4ef68a483c3aed53f9139d2f929a3eecebf72082e5e58c6da24ee32e03040c406d4f", - "ExpectedError": "g2 point is not on correct subgroup", - "Name": "bls_pairing_g2_not_in_correct_subgroup" - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/modexp.json b/builder/core/vm/testdata/precompiles/modexp.json deleted file mode 100644 index 4550eb913..000000000 --- a/builder/core/vm/testdata/precompiles/modexp.json +++ /dev/null @@ -1,121 +0,0 @@ -[ - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "eip_example1", - "Gas": 13056, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "eip_example2", - "Gas": 13056, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc", - "Name": "nagydani-1-square", - "Gas": 204, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec", - "Name": "nagydani-1-qube", - "Gas": 204, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2", - "Name": "nagydani-1-pow0x10001", - "Gas": 3276, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70", - "Name": "nagydani-2-square", - "Gas": 665, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f", - "Name": "nagydani-2-qube", - "Gas": 665, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2", - "Name": "nagydani-2-pow0x10001", - "Gas": 10649, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8", - "Name": "nagydani-3-square", - "Gas": 1894, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e", - "Name": "nagydani-3-qube", - "Gas": 1894, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76", - "Name": "nagydani-3-pow0x10001", - "Gas": 30310, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10", - "Name": "nagydani-4-square", - "Gas": 5580, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc", - "Name": "nagydani-4-qube", - "Gas": 5580, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963", - "Name": "nagydani-4-pow0x10001", - "Gas": 89292, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb", - "Name": "nagydani-5-square", - "Gas": 17868, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f", - "Name": "nagydani-5-qube", - "Gas": 17868, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500", - "Name": "nagydani-5-pow0x10001", - "Gas": 285900, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/modexp_eip2565.json b/builder/core/vm/testdata/precompiles/modexp_eip2565.json deleted file mode 100644 index c55441439..000000000 --- a/builder/core/vm/testdata/precompiles/modexp_eip2565.json +++ /dev/null @@ -1,121 +0,0 @@ -[ - { - "Input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Name": "eip_example1", - "Gas": 1360, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000000", - "Name": "eip_example2", - "Gas": 1360, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc", - "Name": "nagydani-1-square", - "Gas": 200, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec", - "Name": "nagydani-1-qube", - "Gas": 200, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", - "Expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2", - "Name": "nagydani-1-pow0x10001", - "Gas": 341, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70", - "Name": "nagydani-2-square", - "Gas": 200, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f", - "Name": "nagydani-2-qube", - "Gas": 200, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", - "Expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2", - "Name": "nagydani-2-pow0x10001", - "Gas": 1365, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8", - "Name": "nagydani-3-square", - "Gas": 341, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e", - "Name": "nagydani-3-qube", - "Gas": 341, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", - "Expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76", - "Name": "nagydani-3-pow0x10001", - "Gas": 5461, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10", - "Name": "nagydani-4-square", - "Gas": 1365, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc", - "Name": "nagydani-4-qube", - "Gas": 1365, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", - "Expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963", - "Name": "nagydani-4-pow0x10001", - "Gas": 21845, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb", - "Name": "nagydani-5-square", - "Gas": 5461, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f", - "Name": "nagydani-5-qube", - "Gas": 5461, - "NoBenchmark": false - }, - { - "Input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", - "Expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500", - "Name": "nagydani-5-pow0x10001", - "Gas": 87381, - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/builder/core/vm/testdata/precompiles/pointEvaluation.json b/builder/core/vm/testdata/precompiles/pointEvaluation.json deleted file mode 100644 index dfb2cad2e..000000000 --- a/builder/core/vm/testdata/precompiles/pointEvaluation.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "Input": "01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a", - "Expected": "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", - "Name": "pointEvaluation1", - "Gas": 50000, - "NoBenchmark": false - } -] diff --git a/builder/core/vm/testdata/testcases_add.json b/builder/core/vm/testdata/testcases_add.json deleted file mode 100644 index c03ae96ad..000000000 --- a/builder/core/vm/testdata/testcases_add.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_and.json b/builder/core/vm/testdata/testcases_and.json deleted file mode 100644 index aba5f2463..000000000 --- a/builder/core/vm/testdata/testcases_and.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_byte.json b/builder/core/vm/testdata/testcases_byte.json deleted file mode 100644 index 88d7c7d80..000000000 --- a/builder/core/vm/testdata/testcases_byte.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"000000000000000000000000000000000000000000000000000000000000007f"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"000000000000000000000000000000000000000000000000000000000000007f"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000080"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000080"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000ff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_div.json b/builder/core/vm/testdata/testcases_div.json deleted file mode 100644 index b1f9c7fba..000000000 --- a/builder/core/vm/testdata/testcases_div.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333332"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_eq.json b/builder/core/vm/testdata/testcases_eq.json deleted file mode 100644 index 937eadb02..000000000 --- a/builder/core/vm/testdata/testcases_eq.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_exp.json b/builder/core/vm/testdata/testcases_exp.json deleted file mode 100644 index 61818357f..000000000 --- a/builder/core/vm/testdata/testcases_exp.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000c35"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3cb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c29"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c28f5c29"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccd"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"58cd20afa2f05a708ede54b48d3ae685db76b3bb83cf2cf95d4e8fb00bcbe61d"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"a732df505d0fa58f7121ab4b72c5197a24894c447c30d306a2b1704ff43419e3"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccd"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"3333333333333333333333333333333333333333333333333333333333333333"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_gt.json b/builder/core/vm/testdata/testcases_gt.json deleted file mode 100644 index 637bd3f6e..000000000 --- a/builder/core/vm/testdata/testcases_gt.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_lt.json b/builder/core/vm/testdata/testcases_lt.json deleted file mode 100644 index 55252a4de..000000000 --- a/builder/core/vm/testdata/testcases_lt.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_mod.json b/builder/core/vm/testdata/testcases_mod.json deleted file mode 100644 index 192503f26..000000000 --- a/builder/core/vm/testdata/testcases_mod.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_mul.json b/builder/core/vm/testdata/testcases_mul.json deleted file mode 100644 index dc44c253f..000000000 --- a/builder/core/vm/testdata/testcases_mul.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000019"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"800000000000000000000000000000000000000000000000000000000000000a"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"800000000000000000000000000000000000000000000000000000000000000a"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000019"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_or.json b/builder/core/vm/testdata/testcases_or.json deleted file mode 100644 index bfa561b58..000000000 --- a/builder/core/vm/testdata/testcases_or.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_sar.json b/builder/core/vm/testdata/testcases_sar.json deleted file mode 100644 index c93abbd65..000000000 --- a/builder/core/vm/testdata/testcases_sar.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"c000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fc00000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"c000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fc00000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_sdiv.json b/builder/core/vm/testdata/testcases_sdiv.json deleted file mode 100644 index 18cb666ab..000000000 --- a/builder/core/vm/testdata/testcases_sdiv.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"e666666666666666666666666666666666666666666666666666666666666667"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"1999999999999999999999999999999999999999999999999999999999999999"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_sgt.json b/builder/core/vm/testdata/testcases_sgt.json deleted file mode 100644 index aa581a654..000000000 --- a/builder/core/vm/testdata/testcases_sgt.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_shl.json b/builder/core/vm/testdata/testcases_shl.json deleted file mode 100644 index 65e9c07b7..000000000 --- a/builder/core/vm/testdata/testcases_shl.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000020"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"00000000000000000000000000000000000000000000000000000000000000a0"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000020"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_shr.json b/builder/core/vm/testdata/testcases_shr.json deleted file mode 100644 index a38491350..000000000 --- a/builder/core/vm/testdata/testcases_shr.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"4000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0400000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"4000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0400000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_signext.json b/builder/core/vm/testdata/testcases_signext.json deleted file mode 100644 index bdadd400e..000000000 --- a/builder/core/vm/testdata/testcases_signext.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_slt.json b/builder/core/vm/testdata/testcases_slt.json deleted file mode 100644 index 4369b96fd..000000000 --- a/builder/core/vm/testdata/testcases_slt.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_smod.json b/builder/core/vm/testdata/testcases_smod.json deleted file mode 100644 index 980e0341a..000000000 --- a/builder/core/vm/testdata/testcases_smod.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_sub.json b/builder/core/vm/testdata/testcases_sub.json deleted file mode 100644 index b3881a5ab..000000000 --- a/builder/core/vm/testdata/testcases_sub.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000007"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000003"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"000000000000000000000000000000000000000000000000000000000000000a"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000003"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000006"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000006"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000002"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/core/vm/testdata/testcases_xor.json b/builder/core/vm/testdata/testcases_xor.json deleted file mode 100644 index 4cc2dddd7..000000000 --- a/builder/core/vm/testdata/testcases_xor.json +++ /dev/null @@ -1 +0,0 @@ -[{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"0000000000000000000000000000000000000000000000000000000000000005","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"8000000000000000000000000000000000000000000000000000000000000000","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"0000000000000000000000000000000000000000000000000000000000000001"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"8000000000000000000000000000000000000000000000000000000000000001","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000005"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000004"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000000"},{"X":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000000","Expected":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000001","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"0000000000000000000000000000000000000000000000000000000000000005","Expected":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe","Expected":"8000000000000000000000000000000000000000000000000000000000000001"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"8000000000000000000000000000000000000000000000000000000000000000"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000000","Expected":"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"8000000000000000000000000000000000000000000000000000000000000001","Expected":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb","Expected":"0000000000000000000000000000000000000000000000000000000000000004"},{"X":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Y":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","Expected":"0000000000000000000000000000000000000000000000000000000000000000"}] \ No newline at end of file diff --git a/builder/crypto/blake2b/blake2b.go b/builder/crypto/blake2b/blake2b.go deleted file mode 100644 index 7ecaab813..000000000 --- a/builder/crypto/blake2b/blake2b.go +++ /dev/null @@ -1,321 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 -// and the extendable output function (XOF) BLAKE2Xb. -// -// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf -// and for BLAKE2Xb see https://blake2.net/blake2x.pdf -// -// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). -// If you need a secret-key MAC (message authentication code), use the New512 -// function with a non-nil key. -// -// BLAKE2X is a construction to compute hash values larger than 64 bytes. It -// can produce hash values between 0 and 4 GiB. -package blake2b - -import ( - "encoding/binary" - "errors" - "hash" -) - -const ( - // The blocksize of BLAKE2b in bytes. - BlockSize = 128 - // The hash size of BLAKE2b-512 in bytes. - Size = 64 - // The hash size of BLAKE2b-384 in bytes. - Size384 = 48 - // The hash size of BLAKE2b-256 in bytes. - Size256 = 32 -) - -var ( - useAVX2 bool - useAVX bool - useSSE4 bool -) - -var ( - errKeySize = errors.New("blake2b: invalid key size") - errHashSize = errors.New("blake2b: invalid hash size") -) - -var iv = [8]uint64{ - 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, -} - -// Sum512 returns the BLAKE2b-512 checksum of the data. -func Sum512(data []byte) [Size]byte { - var sum [Size]byte - checkSum(&sum, Size, data) - return sum -} - -// Sum384 returns the BLAKE2b-384 checksum of the data. -func Sum384(data []byte) [Size384]byte { - var sum [Size]byte - var sum384 [Size384]byte - checkSum(&sum, Size384, data) - copy(sum384[:], sum[:Size384]) - return sum384 -} - -// Sum256 returns the BLAKE2b-256 checksum of the data. -func Sum256(data []byte) [Size256]byte { - var sum [Size]byte - var sum256 [Size256]byte - checkSum(&sum, Size256, data) - copy(sum256[:], sum[:Size256]) - return sum256 -} - -// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil -// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } - -// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil -// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } - -// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil -// key turns the hash into a MAC. The key must be between zero and 64 bytes long. -func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } - -// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. -// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long. -// The hash size can be a value between 1 and 64 but it is highly recommended to use -// values equal or greater than: -// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). -// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). -// When the key is nil, the returned hash.Hash implements BinaryMarshaler -// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash. -func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } - -// F is a compression function for BLAKE2b. It takes as an argument the state -// vector `h`, message block vector `m`, offset counter `t`, final block indicator -// flag `f`, and number of rounds `rounds`. The state vector provided as the first -// parameter is modified by the function. -func F(h *[8]uint64, m [16]uint64, c [2]uint64, final bool, rounds uint32) { - var flag uint64 - if final { - flag = 0xFFFFFFFFFFFFFFFF - } - f(h, &m, c[0], c[1], flag, uint64(rounds)) -} - -func newDigest(hashSize int, key []byte) (*digest, error) { - if hashSize < 1 || hashSize > Size { - return nil, errHashSize - } - if len(key) > Size { - return nil, errKeySize - } - d := &digest{ - size: hashSize, - keyLen: len(key), - } - copy(d.key[:], key) - d.Reset() - return d, nil -} - -func checkSum(sum *[Size]byte, hashSize int, data []byte) { - h := iv - h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) - var c [2]uint64 - - if length := len(data); length > BlockSize { - n := length &^ (BlockSize - 1) - if length == n { - n -= BlockSize - } - hashBlocks(&h, &c, 0, data[:n]) - data = data[n:] - } - - var block [BlockSize]byte - offset := copy(block[:], data) - remaining := uint64(BlockSize - offset) - if c[0] < remaining { - c[1]-- - } - c[0] -= remaining - - hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) - - for i, v := range h[:(hashSize+7)/8] { - binary.LittleEndian.PutUint64(sum[8*i:], v) - } -} - -func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - var m [16]uint64 - c0, c1 := c[0], c[1] - - for i := 0; i < len(blocks); { - c0 += BlockSize - if c0 < BlockSize { - c1++ - } - for j := range m { - m[j] = binary.LittleEndian.Uint64(blocks[i:]) - i += 8 - } - f(h, &m, c0, c1, flag, 12) - } - c[0], c[1] = c0, c1 -} - -type digest struct { - h [8]uint64 - c [2]uint64 - size int - block [BlockSize]byte - offset int - - key [BlockSize]byte - keyLen int -} - -const ( - magic = "b2b" - marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1 -) - -func (d *digest) MarshalBinary() ([]byte, error) { - if d.keyLen != 0 { - return nil, errors.New("crypto/blake2b: cannot marshal MACs") - } - b := make([]byte, 0, marshaledSize) - b = append(b, magic...) - for i := 0; i < 8; i++ { - b = appendUint64(b, d.h[i]) - } - b = appendUint64(b, d.c[0]) - b = appendUint64(b, d.c[1]) - // Maximum value for size is 64 - b = append(b, byte(d.size)) - b = append(b, d.block[:]...) - b = append(b, byte(d.offset)) - return b, nil -} - -func (d *digest) UnmarshalBinary(b []byte) error { - if len(b) < len(magic) || string(b[:len(magic)]) != magic { - return errors.New("crypto/blake2b: invalid hash state identifier") - } - if len(b) != marshaledSize { - return errors.New("crypto/blake2b: invalid hash state size") - } - b = b[len(magic):] - for i := 0; i < 8; i++ { - b, d.h[i] = consumeUint64(b) - } - b, d.c[0] = consumeUint64(b) - b, d.c[1] = consumeUint64(b) - d.size = int(b[0]) - b = b[1:] - copy(d.block[:], b[:BlockSize]) - b = b[BlockSize:] - d.offset = int(b[0]) - return nil -} - -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Size() int { return d.size } - -func (d *digest) Reset() { - d.h = iv - d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) - d.offset, d.c[0], d.c[1] = 0, 0, 0 - if d.keyLen > 0 { - d.block = d.key - d.offset = BlockSize - } -} - -func (d *digest) Write(p []byte) (n int, err error) { - n = len(p) - - if d.offset > 0 { - remaining := BlockSize - d.offset - if n <= remaining { - d.offset += copy(d.block[d.offset:], p) - return - } - copy(d.block[d.offset:], p[:remaining]) - hashBlocks(&d.h, &d.c, 0, d.block[:]) - d.offset = 0 - p = p[remaining:] - } - - if length := len(p); length > BlockSize { - nn := length &^ (BlockSize - 1) - if length == nn { - nn -= BlockSize - } - hashBlocks(&d.h, &d.c, 0, p[:nn]) - p = p[nn:] - } - - if len(p) > 0 { - d.offset += copy(d.block[:], p) - } - - return -} - -func (d *digest) Sum(sum []byte) []byte { - var hash [Size]byte - d.finalize(&hash) - return append(sum, hash[:d.size]...) -} - -func (d *digest) finalize(hash *[Size]byte) { - var block [BlockSize]byte - copy(block[:], d.block[:d.offset]) - remaining := uint64(BlockSize - d.offset) - - c := d.c - if c[0] < remaining { - c[1]-- - } - c[0] -= remaining - - h := d.h - hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) - - for i, v := range h { - binary.LittleEndian.PutUint64(hash[8*i:], v) - } -} - -func appendUint64(b []byte, x uint64) []byte { - var a [8]byte - binary.BigEndian.PutUint64(a[:], x) - return append(b, a[:]...) -} - -//nolint:unused,deadcode -func appendUint32(b []byte, x uint32) []byte { - var a [4]byte - binary.BigEndian.PutUint32(a[:], x) - return append(b, a[:]...) -} - -func consumeUint64(b []byte) ([]byte, uint64) { - x := binary.BigEndian.Uint64(b) - return b[8:], x -} - -//nolint:unused,deadcode -func consumeUint32(b []byte) ([]byte, uint32) { - x := binary.BigEndian.Uint32(b) - return b[4:], x -} diff --git a/builder/crypto/blake2b/blake2bAVX2_amd64.go b/builder/crypto/blake2b/blake2bAVX2_amd64.go deleted file mode 100644 index 3a85d0e73..000000000 --- a/builder/crypto/blake2b/blake2bAVX2_amd64.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.7 && amd64 && !gccgo && !appengine -// +build go1.7,amd64,!gccgo,!appengine - -package blake2b - -import "golang.org/x/sys/cpu" - -func init() { - useAVX2 = cpu.X86.HasAVX2 - useAVX = cpu.X86.HasAVX - useSSE4 = cpu.X86.HasSSE41 -} - -//go:noescape -func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) - -//go:noescape -func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) - -//go:noescape -func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) - -func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { - switch { - case useAVX2: - fAVX2(h, m, c0, c1, flag, rounds) - case useAVX: - fAVX(h, m, c0, c1, flag, rounds) - case useSSE4: - fSSE4(h, m, c0, c1, flag, rounds) - default: - fGeneric(h, m, c0, c1, flag, rounds) - } -} diff --git a/builder/crypto/blake2b/blake2bAVX2_amd64.s b/builder/crypto/blake2b/blake2bAVX2_amd64.s deleted file mode 100644 index 4998af37d..000000000 --- a/builder/crypto/blake2b/blake2bAVX2_amd64.s +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.7,amd64,!gccgo,!appengine - -#include "textflag.h" - -DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b -DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b -DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 -GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 -DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 -DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 - -DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 - -DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 - -#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 -#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 -#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e -#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 -#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 - -#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ - VPADDQ m0, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFD $-79, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPSHUFB c40, Y1, Y1; \ - VPADDQ m1, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFB c48, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPADDQ Y1, Y1, t; \ - VPSRLQ $63, Y1, Y1; \ - VPXOR t, Y1, Y1; \ - VPERMQ_0x39_Y1_Y1; \ - VPERMQ_0x4E_Y2_Y2; \ - VPERMQ_0x93_Y3_Y3; \ - VPADDQ m2, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFD $-79, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPSHUFB c40, Y1, Y1; \ - VPADDQ m3, Y0, Y0; \ - VPADDQ Y1, Y0, Y0; \ - VPXOR Y0, Y3, Y3; \ - VPSHUFB c48, Y3, Y3; \ - VPADDQ Y3, Y2, Y2; \ - VPXOR Y2, Y1, Y1; \ - VPADDQ Y1, Y1, t; \ - VPSRLQ $63, Y1, Y1; \ - VPXOR t, Y1, Y1; \ - VPERMQ_0x39_Y3_Y3; \ - VPERMQ_0x4E_Y2_Y2; \ - VPERMQ_0x93_Y1_Y1 - -#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E -#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 -#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E -#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 -#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E - -#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n -#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n -#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n -#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n -#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n - -#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 -#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 -#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 -#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 -#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 - -#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 -#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 - -#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 -#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 - -// load msg: Y12 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ - VMOVQ_SI_X12(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X12(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y12, Y12 - -// load msg: Y13 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ - VMOVQ_SI_X13(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X13(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y13, Y13 - -// load msg: Y14 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ - VMOVQ_SI_X14(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X14(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y14, Y14 - -// load msg: Y15 = (i0, i1, i2, i3) -// i0, i1, i2, i3 must not be 0 -#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ - VMOVQ_SI_X15(i0*8); \ - VMOVQ_SI_X11(i2*8); \ - VPINSRQ_1_SI_X15(i1*8); \ - VPINSRQ_1_SI_X11(i3*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ - VMOVQ_SI_X12_0; \ - VMOVQ_SI_X11(4*8); \ - VPINSRQ_1_SI_X12(2*8); \ - VPINSRQ_1_SI_X11(6*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ - LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ - LOAD_MSG_AVX2_Y15(9, 11, 13, 15) - -#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ - LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ - LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ - VMOVQ_SI_X11(11*8); \ - VPSHUFD $0x4E, 0*8(SI), X14; \ - VPINSRQ_1_SI_X11(5*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - LOAD_MSG_AVX2_Y15(12, 2, 7, 3) - -#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ - VMOVQ_SI_X11(5*8); \ - VMOVDQU 11*8(SI), X12; \ - VPINSRQ_1_SI_X11(15*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - VMOVQ_SI_X13(8*8); \ - VMOVQ_SI_X11(2*8); \ - VPINSRQ_1_SI_X13_0; \ - VPINSRQ_1_SI_X11(13*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ - LOAD_MSG_AVX2_Y15(14, 6, 1, 4) - -#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ - LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ - LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ - LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ - VMOVQ_SI_X15(6*8); \ - VMOVQ_SI_X11_0; \ - VPINSRQ_1_SI_X15(10*8); \ - VPINSRQ_1_SI_X11(8*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ - LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ - VMOVQ_SI_X13_0; \ - VMOVQ_SI_X11(4*8); \ - VPINSRQ_1_SI_X13(7*8); \ - VPINSRQ_1_SI_X11(15*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ - LOAD_MSG_AVX2_Y15(1, 12, 8, 13) - -#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X11_0; \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X11(8*8); \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ - LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ - LOAD_MSG_AVX2_Y15(13, 5, 14, 9) - -#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ - LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ - LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ - VMOVQ_SI_X14_0; \ - VPSHUFD $0x4E, 8*8(SI), X11; \ - VPINSRQ_1_SI_X14(6*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - LOAD_MSG_AVX2_Y15(7, 3, 2, 11) - -#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ - LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ - LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ - LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ - VMOVQ_SI_X15_0; \ - VMOVQ_SI_X11(6*8); \ - VPINSRQ_1_SI_X15(4*8); \ - VPINSRQ_1_SI_X11(10*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ - VMOVQ_SI_X12(6*8); \ - VMOVQ_SI_X11(11*8); \ - VPINSRQ_1_SI_X12(14*8); \ - VPINSRQ_1_SI_X11_0; \ - VINSERTI128 $1, X11, Y12, Y12; \ - LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ - VMOVQ_SI_X11(1*8); \ - VMOVDQU 12*8(SI), X14; \ - VPINSRQ_1_SI_X11(10*8); \ - VINSERTI128 $1, X11, Y14, Y14; \ - VMOVQ_SI_X15(2*8); \ - VMOVDQU 4*8(SI), X11; \ - VPINSRQ_1_SI_X15(7*8); \ - VINSERTI128 $1, X11, Y15, Y15 - -#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ - LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ - VMOVQ_SI_X13(2*8); \ - VPSHUFD $0x4E, 5*8(SI), X11; \ - VPINSRQ_1_SI_X13(4*8); \ - VINSERTI128 $1, X11, Y13, Y13; \ - LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ - VMOVQ_SI_X15(11*8); \ - VMOVQ_SI_X11(12*8); \ - VPINSRQ_1_SI_X15(14*8); \ - VPINSRQ_1_SI_X11_0; \ - VINSERTI128 $1, X11, Y15, Y15 - -// func fAVX2(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) -TEXT ·fAVX2(SB), 4, $64-48 // frame size = 32 + 32 byte alignment - MOVQ h+0(FP), AX - MOVQ m+8(FP), SI - MOVQ c0+16(FP), R8 - MOVQ c1+24(FP), R9 - MOVQ flag+32(FP), CX - MOVQ rounds+40(FP), BX - - MOVQ SP, DX - MOVQ SP, R10 - ADDQ $31, R10 - ANDQ $~31, R10 - MOVQ R10, SP - - MOVQ CX, 16(SP) - XORQ CX, CX - MOVQ CX, 24(SP) - - VMOVDQU ·AVX2_c40<>(SB), Y4 - VMOVDQU ·AVX2_c48<>(SB), Y5 - - VMOVDQU 0(AX), Y8 - VMOVDQU 32(AX), Y9 - VMOVDQU ·AVX2_iv0<>(SB), Y6 - VMOVDQU ·AVX2_iv1<>(SB), Y7 - - MOVQ R8, 0(SP) - MOVQ R9, 8(SP) - - VMOVDQA Y8, Y0 - VMOVDQA Y9, Y1 - VMOVDQA Y6, Y2 - VPXOR 0(SP), Y7, Y3 - -loop: - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() - ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) - - JMP loop - -done: - VPXOR Y0, Y8, Y8 - VPXOR Y1, Y9, Y9 - VPXOR Y2, Y8, Y8 - VPXOR Y3, Y9, Y9 - - VMOVDQU Y8, 0(AX) - VMOVDQU Y9, 32(AX) - VZEROUPPER - - MOVQ DX, SP - RET - -#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA -#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB -#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF -#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD -#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE - -#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 -#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF -#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 -#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF -#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 -#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 -#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF -#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF - -#define SHUFFLE_AVX() \ - VMOVDQA X6, X13; \ - VMOVDQA X2, X14; \ - VMOVDQA X4, X6; \ - VPUNPCKLQDQ_X13_X13_X15; \ - VMOVDQA X5, X4; \ - VMOVDQA X6, X5; \ - VPUNPCKHQDQ_X15_X7_X6; \ - VPUNPCKLQDQ_X7_X7_X15; \ - VPUNPCKHQDQ_X15_X13_X7; \ - VPUNPCKLQDQ_X3_X3_X15; \ - VPUNPCKHQDQ_X15_X2_X2; \ - VPUNPCKLQDQ_X14_X14_X15; \ - VPUNPCKHQDQ_X15_X3_X3; \ - -#define SHUFFLE_AVX_INV() \ - VMOVDQA X2, X13; \ - VMOVDQA X4, X14; \ - VPUNPCKLQDQ_X2_X2_X15; \ - VMOVDQA X5, X4; \ - VPUNPCKHQDQ_X15_X3_X2; \ - VMOVDQA X14, X5; \ - VPUNPCKLQDQ_X3_X3_X15; \ - VMOVDQA X6, X14; \ - VPUNPCKHQDQ_X15_X13_X3; \ - VPUNPCKLQDQ_X7_X7_X15; \ - VPUNPCKHQDQ_X15_X6_X6; \ - VPUNPCKLQDQ_X14_X14_X15; \ - VPUNPCKHQDQ_X15_X7_X7; \ - -#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ - VPADDQ m0, v0, v0; \ - VPADDQ v2, v0, v0; \ - VPADDQ m1, v1, v1; \ - VPADDQ v3, v1, v1; \ - VPXOR v0, v6, v6; \ - VPXOR v1, v7, v7; \ - VPSHUFD $-79, v6, v6; \ - VPSHUFD $-79, v7, v7; \ - VPADDQ v6, v4, v4; \ - VPADDQ v7, v5, v5; \ - VPXOR v4, v2, v2; \ - VPXOR v5, v3, v3; \ - VPSHUFB c40, v2, v2; \ - VPSHUFB c40, v3, v3; \ - VPADDQ m2, v0, v0; \ - VPADDQ v2, v0, v0; \ - VPADDQ m3, v1, v1; \ - VPADDQ v3, v1, v1; \ - VPXOR v0, v6, v6; \ - VPXOR v1, v7, v7; \ - VPSHUFB c48, v6, v6; \ - VPSHUFB c48, v7, v7; \ - VPADDQ v6, v4, v4; \ - VPADDQ v7, v5, v5; \ - VPXOR v4, v2, v2; \ - VPXOR v5, v3, v3; \ - VPADDQ v2, v2, t0; \ - VPSRLQ $63, v2, v2; \ - VPXOR t0, v2, v2; \ - VPADDQ v3, v3, t0; \ - VPSRLQ $63, v3, v3; \ - VPXOR t0, v3, v3 - -// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) -// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 -#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ - VMOVQ_SI_X12(i0*8); \ - VMOVQ_SI_X13(i2*8); \ - VMOVQ_SI_X14(i4*8); \ - VMOVQ_SI_X15(i6*8); \ - VPINSRQ_1_SI_X12(i1*8); \ - VPINSRQ_1_SI_X13(i3*8); \ - VPINSRQ_1_SI_X14(i5*8); \ - VPINSRQ_1_SI_X15(i7*8) - -// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) -#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ - VMOVQ_SI_X12_0; \ - VMOVQ_SI_X13(4*8); \ - VMOVQ_SI_X14(1*8); \ - VMOVQ_SI_X15(5*8); \ - VPINSRQ_1_SI_X12(2*8); \ - VPINSRQ_1_SI_X13(6*8); \ - VPINSRQ_1_SI_X14(3*8); \ - VPINSRQ_1_SI_X15(7*8) - -// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) -#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ - VPSHUFD $0x4E, 0*8(SI), X12; \ - VMOVQ_SI_X13(11*8); \ - VMOVQ_SI_X14(12*8); \ - VMOVQ_SI_X15(7*8); \ - VPINSRQ_1_SI_X13(5*8); \ - VPINSRQ_1_SI_X14(2*8); \ - VPINSRQ_1_SI_X15(3*8) - -// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) -#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ - VMOVDQU 11*8(SI), X12; \ - VMOVQ_SI_X13(5*8); \ - VMOVQ_SI_X14(8*8); \ - VMOVQ_SI_X15(2*8); \ - VPINSRQ_1_SI_X13(15*8); \ - VPINSRQ_1_SI_X14_0; \ - VPINSRQ_1_SI_X15(13*8) - -// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) -#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X13(4*8); \ - VMOVQ_SI_X14(6*8); \ - VMOVQ_SI_X15_0; \ - VPINSRQ_1_SI_X12(5*8); \ - VPINSRQ_1_SI_X13(15*8); \ - VPINSRQ_1_SI_X14(10*8); \ - VPINSRQ_1_SI_X15(8*8) - -// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) -#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ - VMOVQ_SI_X12(9*8); \ - VMOVQ_SI_X13(2*8); \ - VMOVQ_SI_X14_0; \ - VMOVQ_SI_X15(4*8); \ - VPINSRQ_1_SI_X12(5*8); \ - VPINSRQ_1_SI_X13(10*8); \ - VPINSRQ_1_SI_X14(7*8); \ - VPINSRQ_1_SI_X15(15*8) - -// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) -#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ - VMOVQ_SI_X12(2*8); \ - VMOVQ_SI_X13_0; \ - VMOVQ_SI_X14(12*8); \ - VMOVQ_SI_X15(11*8); \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X13(8*8); \ - VPINSRQ_1_SI_X14(10*8); \ - VPINSRQ_1_SI_X15(3*8) - -// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) -#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ - MOVQ 0*8(SI), X12; \ - VPSHUFD $0x4E, 8*8(SI), X13; \ - MOVQ 7*8(SI), X14; \ - MOVQ 2*8(SI), X15; \ - VPINSRQ_1_SI_X12(6*8); \ - VPINSRQ_1_SI_X14(3*8); \ - VPINSRQ_1_SI_X15(11*8) - -// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) -#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ - MOVQ 6*8(SI), X12; \ - MOVQ 11*8(SI), X13; \ - MOVQ 15*8(SI), X14; \ - MOVQ 3*8(SI), X15; \ - VPINSRQ_1_SI_X12(14*8); \ - VPINSRQ_1_SI_X13_0; \ - VPINSRQ_1_SI_X14(9*8); \ - VPINSRQ_1_SI_X15(8*8) - -// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) -#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ - MOVQ 5*8(SI), X12; \ - MOVQ 8*8(SI), X13; \ - MOVQ 0*8(SI), X14; \ - MOVQ 6*8(SI), X15; \ - VPINSRQ_1_SI_X12(15*8); \ - VPINSRQ_1_SI_X13(2*8); \ - VPINSRQ_1_SI_X14(4*8); \ - VPINSRQ_1_SI_X15(10*8) - -// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) -#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ - VMOVDQU 12*8(SI), X12; \ - MOVQ 1*8(SI), X13; \ - MOVQ 2*8(SI), X14; \ - VPINSRQ_1_SI_X13(10*8); \ - VPINSRQ_1_SI_X14(7*8); \ - VMOVDQU 4*8(SI), X15 - -// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) -#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ - MOVQ 15*8(SI), X12; \ - MOVQ 3*8(SI), X13; \ - MOVQ 11*8(SI), X14; \ - MOVQ 12*8(SI), X15; \ - VPINSRQ_1_SI_X12(9*8); \ - VPINSRQ_1_SI_X13(13*8); \ - VPINSRQ_1_SI_X14(14*8); \ - VPINSRQ_1_SI_X15_0 - -// func fAVX(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) -TEXT ·fAVX(SB), 4, $24-48 // frame size = 8 + 16 byte alignment - MOVQ h+0(FP), AX - MOVQ m+8(FP), SI - MOVQ c0+16(FP), R8 - MOVQ c1+24(FP), R9 - MOVQ flag+32(FP), CX - MOVQ rounds+40(FP), BX - - MOVQ SP, BP - MOVQ SP, R10 - ADDQ $15, R10 - ANDQ $~15, R10 - MOVQ R10, SP - - VMOVDQU ·AVX_c40<>(SB), X0 - VMOVDQU ·AVX_c48<>(SB), X1 - VMOVDQA X0, X8 - VMOVDQA X1, X9 - - VMOVDQU ·AVX_iv3<>(SB), X0 - VMOVDQA X0, 0(SP) - XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) - - VMOVDQU 0(AX), X10 - VMOVDQU 16(AX), X11 - VMOVDQU 32(AX), X2 - VMOVDQU 48(AX), X3 - - VMOVQ_R8_X15 - VPINSRQ_1_R9_X15 - - VMOVDQA X10, X0 - VMOVDQA X11, X1 - VMOVDQU ·AVX_iv0<>(SB), X4 - VMOVDQU ·AVX_iv1<>(SB), X5 - VMOVDQU ·AVX_iv2<>(SB), X6 - - VPXOR X15, X6, X6 - VMOVDQA 0(SP), X7 - -loop: - SUBQ $1, BX; JCS done - LOAD_MSG_AVX_0_2_4_6_1_3_5_7() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_1_0_11_5_12_2_7_3() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX_11_12_5_15_8_0_2_13() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_2_5_4_15_6_10_0_8() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX_9_5_2_10_0_7_4_15() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX_2_6_0_8_12_10_11_3() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_0_6_9_8_7_3_2_11() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_5_15_8_2_0_4_6_10() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX_6_14_11_0_15_9_3_8() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_12_13_1_10_2_7_4_5() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - SUBQ $1, BX; JCS done - LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX() - LOAD_MSG_AVX_15_9_3_13_11_14_12_0() - HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) - SHUFFLE_AVX_INV() - - JMP loop - -done: - VMOVDQU 32(AX), X14 - VMOVDQU 48(AX), X15 - VPXOR X0, X10, X10 - VPXOR X1, X11, X11 - VPXOR X2, X14, X14 - VPXOR X3, X15, X15 - VPXOR X4, X10, X10 - VPXOR X5, X11, X11 - VPXOR X6, X14, X2 - VPXOR X7, X15, X3 - VMOVDQU X2, 32(AX) - VMOVDQU X3, 48(AX) - - VMOVDQU X10, 0(AX) - VMOVDQU X11, 16(AX) - VZEROUPPER - - MOVQ BP, SP - RET diff --git a/builder/crypto/blake2b/blake2b_amd64.go b/builder/crypto/blake2b/blake2b_amd64.go deleted file mode 100644 index a318b2b61..000000000 --- a/builder/crypto/blake2b/blake2b_amd64.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.7 && amd64 && !gccgo && !appengine -// +build !go1.7,amd64,!gccgo,!appengine - -package blake2b - -import "golang.org/x/sys/cpu" - -func init() { - useSSE4 = cpu.X86.HasSSE41 -} - -//go:noescape -func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) - -func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { - if useSSE4 { - fSSE4(h, m, c0, c1, flag, rounds) - } else { - fGeneric(h, m, c0, c1, flag, rounds) - } -} diff --git a/builder/crypto/blake2b/blake2b_amd64.s b/builder/crypto/blake2b/blake2b_amd64.s deleted file mode 100644 index ce4b56d10..000000000 --- a/builder/crypto/blake2b/blake2b_amd64.s +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!gccgo,!appengine - -#include "textflag.h" - -DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 -DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b -GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b -DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 -GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 -DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f -GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 - -DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b -DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 -GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 - -DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 -DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b -GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 - -DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 -DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a -GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 - -#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v6, t1; \ - PUNPCKLQDQ v6, t2; \ - PUNPCKHQDQ v7, v6; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ v7, t2; \ - MOVO t1, v7; \ - MOVO v2, t1; \ - PUNPCKHQDQ t2, v7; \ - PUNPCKLQDQ v3, t2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v3 - -#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ - MOVO v4, t1; \ - MOVO v5, v4; \ - MOVO t1, v5; \ - MOVO v2, t1; \ - PUNPCKLQDQ v2, t2; \ - PUNPCKHQDQ v3, v2; \ - PUNPCKHQDQ t2, v2; \ - PUNPCKLQDQ v3, t2; \ - MOVO t1, v3; \ - MOVO v6, t1; \ - PUNPCKHQDQ t2, v3; \ - PUNPCKLQDQ v7, t2; \ - PUNPCKHQDQ t2, v6; \ - PUNPCKLQDQ t1, t2; \ - PUNPCKHQDQ t2, v7 - -#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ - PADDQ m0, v0; \ - PADDQ m1, v1; \ - PADDQ v2, v0; \ - PADDQ v3, v1; \ - PXOR v0, v6; \ - PXOR v1, v7; \ - PSHUFD $0xB1, v6, v6; \ - PSHUFD $0xB1, v7, v7; \ - PADDQ v6, v4; \ - PADDQ v7, v5; \ - PXOR v4, v2; \ - PXOR v5, v3; \ - PSHUFB c40, v2; \ - PSHUFB c40, v3; \ - PADDQ m2, v0; \ - PADDQ m3, v1; \ - PADDQ v2, v0; \ - PADDQ v3, v1; \ - PXOR v0, v6; \ - PXOR v1, v7; \ - PSHUFB c48, v6; \ - PSHUFB c48, v7; \ - PADDQ v6, v4; \ - PADDQ v7, v5; \ - PXOR v4, v2; \ - PXOR v5, v3; \ - MOVOU v2, t0; \ - PADDQ v2, t0; \ - PSRLQ $63, v2; \ - PXOR t0, v2; \ - MOVOU v3, t0; \ - PADDQ v3, t0; \ - PSRLQ $63, v3; \ - PXOR t0, v3 - -#define LOAD_MSG(m0, m1, m2, m3, i0, i1, i2, i3, i4, i5, i6, i7) \ - MOVQ i0*8(SI), m0; \ - PINSRQ $1, i1*8(SI), m0; \ - MOVQ i2*8(SI), m1; \ - PINSRQ $1, i3*8(SI), m1; \ - MOVQ i4*8(SI), m2; \ - PINSRQ $1, i5*8(SI), m2; \ - MOVQ i6*8(SI), m3; \ - PINSRQ $1, i7*8(SI), m3 - -// func fSSE4(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) -TEXT ·fSSE4(SB), 4, $24-48 // frame size = 8 + 16 byte alignment - MOVQ h+0(FP), AX - MOVQ m+8(FP), SI - MOVQ c0+16(FP), R8 - MOVQ c1+24(FP), R9 - MOVQ flag+32(FP), CX - MOVQ rounds+40(FP), BX - - MOVQ SP, BP - MOVQ SP, R10 - ADDQ $15, R10 - ANDQ $~15, R10 - MOVQ R10, SP - - MOVOU ·iv3<>(SB), X0 - MOVO X0, 0(SP) - XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) - - MOVOU ·c40<>(SB), X13 - MOVOU ·c48<>(SB), X14 - - MOVOU 0(AX), X12 - MOVOU 16(AX), X15 - - MOVQ R8, X8 - PINSRQ $1, R9, X8 - - MOVO X12, X0 - MOVO X15, X1 - MOVOU 32(AX), X2 - MOVOU 48(AX), X3 - MOVOU ·iv0<>(SB), X4 - MOVOU ·iv1<>(SB), X5 - MOVOU ·iv2<>(SB), X6 - - PXOR X8, X6 - MOVO 0(SP), X7 - -loop: - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 0, 2, 4, 6, 1, 3, 5, 7) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 8, 10, 12, 14, 9, 11, 13, 15) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 14, 4, 9, 13, 10, 8, 15, 6) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 1, 0, 11, 5, 12, 2, 7, 3) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 11, 12, 5, 15, 8, 0, 2, 13) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 10, 3, 7, 9, 14, 6, 1, 4) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 7, 3, 13, 11, 9, 1, 12, 14) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 2, 5, 4, 15, 6, 10, 0, 8) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 9, 5, 2, 10, 0, 7, 4, 15) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 14, 11, 6, 3, 1, 12, 8, 13) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 2, 6, 0, 8, 12, 10, 11, 3) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 4, 7, 15, 1, 13, 5, 14, 9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 12, 1, 14, 4, 5, 15, 13, 10) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 0, 6, 9, 8, 7, 3, 2, 11) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 13, 7, 12, 3, 11, 14, 1, 9) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 5, 15, 8, 2, 0, 4, 6, 10) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 6, 14, 11, 0, 15, 9, 3, 8) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 12, 13, 1, 10, 2, 7, 4, 5) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - SUBQ $1, BX; JCS done - LOAD_MSG(X8, X9, X10, X11, 10, 8, 7, 1, 2, 4, 6, 5) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) - LOAD_MSG(X8, X9, X10, X11, 15, 9, 3, 13, 11, 14, 12, 0) - HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) - SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) - - JMP loop - -done: - MOVOU 32(AX), X10 - MOVOU 48(AX), X11 - PXOR X0, X12 - PXOR X1, X15 - PXOR X2, X10 - PXOR X3, X11 - PXOR X4, X12 - PXOR X5, X15 - PXOR X6, X10 - PXOR X7, X11 - MOVOU X10, 32(AX) - MOVOU X11, 48(AX) - - MOVOU X12, 0(AX) - MOVOU X15, 16(AX) - - MOVQ BP, SP - RET diff --git a/builder/crypto/blake2b/blake2b_f_fuzz_test.go b/builder/crypto/blake2b/blake2b_f_fuzz_test.go deleted file mode 100644 index 1de9a62de..000000000 --- a/builder/crypto/blake2b/blake2b_f_fuzz_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Only enable fuzzer on platforms with AVX enabled -//go:build go1.7 && amd64 && !gccgo && !appengine -// +build go1.7,amd64,!gccgo,!appengine - -package blake2b - -import ( - "encoding/binary" - "testing" -) - -func Fuzz(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - fuzz(data) - }) -} - -func fuzz(data []byte) { - // Make sure the data confirms to the input model - if len(data) != 211 { - return - } - // Parse everything and call all the implementations - var ( - rounds = binary.BigEndian.Uint16(data[0:2]) - - h [8]uint64 - m [16]uint64 - t [2]uint64 - f uint64 - ) - - for i := 0; i < 8; i++ { - offset := 2 + i*8 - h[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) - } - for i := 0; i < 16; i++ { - offset := 66 + i*8 - m[i] = binary.LittleEndian.Uint64(data[offset : offset+8]) - } - t[0] = binary.LittleEndian.Uint64(data[194:202]) - t[1] = binary.LittleEndian.Uint64(data[202:210]) - - if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1 - f = 0xFFFFFFFFFFFFFFFF - } - - // Run the blake2b compression on all instruction sets and cross reference - want := h - fGeneric(&want, &m, t[0], t[1], f, uint64(rounds)) - - have := h - if useSSE4 { - fSSE4(&have, &m, t[0], t[1], f, uint64(rounds)) - if have != want { - panic("SSE4 mismatches generic algo") - } - } - - if useAVX { - have = h - fAVX(&have, &m, t[0], t[1], f, uint64(rounds)) - if have != want { - panic("AVX mismatches generic algo") - } - } - - if useAVX2 { - have = h - fAVX2(&have, &m, t[0], t[1], f, uint64(rounds)) - if have != want { - panic("AVX2 mismatches generic algo") - } - } -} diff --git a/builder/crypto/blake2b/blake2b_f_test.go b/builder/crypto/blake2b/blake2b_f_test.go deleted file mode 100644 index 4e07d131c..000000000 --- a/builder/crypto/blake2b/blake2b_f_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package blake2b - -import ( - "fmt" - "reflect" - "testing" -) - -func TestF(t *testing.T) { - for i, test := range testVectorsF { - t.Run(fmt.Sprintf("test vector %v", i), func(t *testing.T) { - //toEthereumTestCase(test) - - h := test.hIn - F(&h, test.m, test.c, test.f, test.rounds) - - if !reflect.DeepEqual(test.hOut, h) { - t.Errorf("Unexpected result\nExpected: [%#x]\nActual: [%#x]\n", test.hOut, h) - } - }) - } -} - -type testVector struct { - hIn [8]uint64 - m [16]uint64 - c [2]uint64 - f bool - rounds uint32 - hOut [8]uint64 -} - -// https://tools.ietf.org/html/rfc7693#appendix-A -var testVectorsF = []testVector{ - { - hIn: [8]uint64{ - 0x6a09e667f2bdc948, 0xbb67ae8584caa73b, - 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, - 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, - }, - m: [16]uint64{ - 0x0000000000636261, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, - }, - c: [2]uint64{3, 0}, - f: true, - rounds: 12, - hOut: [8]uint64{ - 0x0D4D1C983FA580BA, 0xE9F6129FB697276A, 0xB7C45A68142F214C, - 0xD1A2FFDB6FBB124B, 0x2D79AB2A39C5877D, 0x95CC3345DED552C2, - 0x5A92F1DBA88AD318, 0x239900D4ED8623B9, - }, - }, -} diff --git a/builder/crypto/blake2b/blake2b_generic.go b/builder/crypto/blake2b/blake2b_generic.go deleted file mode 100644 index 61e678fdf..000000000 --- a/builder/crypto/blake2b/blake2b_generic.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blake2b - -import ( - "encoding/binary" - "math/bits" -) - -// the precomputed values for BLAKE2b -// there are 10 16-byte arrays - one for each round -// the entries are calculated from the sigma constants. -var precomputed = [10][16]byte{ - {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, - {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, - {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, - {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, - {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, - {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, - {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, - {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, - {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, - {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, -} - -// nolint:unused,deadcode -func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { - var m [16]uint64 - c0, c1 := c[0], c[1] - - for i := 0; i < len(blocks); { - c0 += BlockSize - if c0 < BlockSize { - c1++ - } - for j := range m { - m[j] = binary.LittleEndian.Uint64(blocks[i:]) - i += 8 - } - fGeneric(h, &m, c0, c1, flag, 12) - } - c[0], c[1] = c0, c1 -} - -func fGeneric(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { - v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] - v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] - v12 ^= c0 - v13 ^= c1 - v14 ^= flag - - for i := 0; i < int(rounds); i++ { - s := &(precomputed[i%10]) - - v0 += m[s[0]] - v0 += v4 - v12 ^= v0 - v12 = bits.RotateLeft64(v12, -32) - v8 += v12 - v4 ^= v8 - v4 = bits.RotateLeft64(v4, -24) - v1 += m[s[1]] - v1 += v5 - v13 ^= v1 - v13 = bits.RotateLeft64(v13, -32) - v9 += v13 - v5 ^= v9 - v5 = bits.RotateLeft64(v5, -24) - v2 += m[s[2]] - v2 += v6 - v14 ^= v2 - v14 = bits.RotateLeft64(v14, -32) - v10 += v14 - v6 ^= v10 - v6 = bits.RotateLeft64(v6, -24) - v3 += m[s[3]] - v3 += v7 - v15 ^= v3 - v15 = bits.RotateLeft64(v15, -32) - v11 += v15 - v7 ^= v11 - v7 = bits.RotateLeft64(v7, -24) - - v0 += m[s[4]] - v0 += v4 - v12 ^= v0 - v12 = bits.RotateLeft64(v12, -16) - v8 += v12 - v4 ^= v8 - v4 = bits.RotateLeft64(v4, -63) - v1 += m[s[5]] - v1 += v5 - v13 ^= v1 - v13 = bits.RotateLeft64(v13, -16) - v9 += v13 - v5 ^= v9 - v5 = bits.RotateLeft64(v5, -63) - v2 += m[s[6]] - v2 += v6 - v14 ^= v2 - v14 = bits.RotateLeft64(v14, -16) - v10 += v14 - v6 ^= v10 - v6 = bits.RotateLeft64(v6, -63) - v3 += m[s[7]] - v3 += v7 - v15 ^= v3 - v15 = bits.RotateLeft64(v15, -16) - v11 += v15 - v7 ^= v11 - v7 = bits.RotateLeft64(v7, -63) - - v0 += m[s[8]] - v0 += v5 - v15 ^= v0 - v15 = bits.RotateLeft64(v15, -32) - v10 += v15 - v5 ^= v10 - v5 = bits.RotateLeft64(v5, -24) - v1 += m[s[9]] - v1 += v6 - v12 ^= v1 - v12 = bits.RotateLeft64(v12, -32) - v11 += v12 - v6 ^= v11 - v6 = bits.RotateLeft64(v6, -24) - v2 += m[s[10]] - v2 += v7 - v13 ^= v2 - v13 = bits.RotateLeft64(v13, -32) - v8 += v13 - v7 ^= v8 - v7 = bits.RotateLeft64(v7, -24) - v3 += m[s[11]] - v3 += v4 - v14 ^= v3 - v14 = bits.RotateLeft64(v14, -32) - v9 += v14 - v4 ^= v9 - v4 = bits.RotateLeft64(v4, -24) - - v0 += m[s[12]] - v0 += v5 - v15 ^= v0 - v15 = bits.RotateLeft64(v15, -16) - v10 += v15 - v5 ^= v10 - v5 = bits.RotateLeft64(v5, -63) - v1 += m[s[13]] - v1 += v6 - v12 ^= v1 - v12 = bits.RotateLeft64(v12, -16) - v11 += v12 - v6 ^= v11 - v6 = bits.RotateLeft64(v6, -63) - v2 += m[s[14]] - v2 += v7 - v13 ^= v2 - v13 = bits.RotateLeft64(v13, -16) - v8 += v13 - v7 ^= v8 - v7 = bits.RotateLeft64(v7, -63) - v3 += m[s[15]] - v3 += v4 - v14 ^= v3 - v14 = bits.RotateLeft64(v14, -16) - v9 += v14 - v4 ^= v9 - v4 = bits.RotateLeft64(v4, -63) - } - h[0] ^= v0 ^ v8 - h[1] ^= v1 ^ v9 - h[2] ^= v2 ^ v10 - h[3] ^= v3 ^ v11 - h[4] ^= v4 ^ v12 - h[5] ^= v5 ^ v13 - h[6] ^= v6 ^ v14 - h[7] ^= v7 ^ v15 -} diff --git a/builder/crypto/blake2b/blake2b_ref.go b/builder/crypto/blake2b/blake2b_ref.go deleted file mode 100644 index 095c71a64..000000000 --- a/builder/crypto/blake2b/blake2b_ref.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !amd64 || appengine || gccgo -// +build !amd64 appengine gccgo - -package blake2b - -func f(h *[8]uint64, m *[16]uint64, c0, c1 uint64, flag uint64, rounds uint64) { - fGeneric(h, m, c0, c1, flag, rounds) -} diff --git a/builder/crypto/blake2b/blake2b_test.go b/builder/crypto/blake2b/blake2b_test.go deleted file mode 100644 index 9d24444a2..000000000 --- a/builder/crypto/blake2b/blake2b_test.go +++ /dev/null @@ -1,863 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blake2b - -import ( - "bytes" - "encoding" - "encoding/hex" - "fmt" - "hash" - "io" - "testing" -) - -func TestHashes(t *testing.T) { - defer func(sse4, avx, avx2 bool) { - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - }(useSSE4, useAVX, useAVX2) - - if useAVX2 { - t.Log("AVX2 version") - testHashes(t) - useAVX2 = false - } - if useAVX { - t.Log("AVX version") - testHashes(t) - useAVX = false - } - if useSSE4 { - t.Log("SSE4 version") - testHashes(t) - useSSE4 = false - } - t.Log("generic version") - testHashes(t) -} - -func TestHashes2X(t *testing.T) { - defer func(sse4, avx, avx2 bool) { - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - }(useSSE4, useAVX, useAVX2) - - if useAVX2 { - t.Log("AVX2 version") - testHashes2X(t) - useAVX2 = false - } - if useAVX { - t.Log("AVX version") - testHashes2X(t) - useAVX = false - } - if useSSE4 { - t.Log("SSE4 version") - testHashes2X(t) - useSSE4 = false - } - t.Log("generic version") - testHashes2X(t) -} - -func TestMarshal(t *testing.T) { - input := make([]byte, 255) - for i := range input { - input[i] = byte(i) - } - for _, size := range []int{Size, Size256, Size384, 12, 25, 63} { - for i := 0; i < 256; i++ { - h, err := New(size, nil) - if err != nil { - t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) - } - h2, err := New(size, nil) - if err != nil { - t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) - } - - h.Write(input[:i/2]) - halfstate, err := h.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { - t.Fatalf("size=%d, len(input)=%d: could not marshal: %v", size, i, err) - } - err = h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(halfstate) - if err != nil { - t.Fatalf("size=%d, len(input)=%d: could not unmarshal: %v", size, i, err) - } - - h.Write(input[i/2 : i]) - sum := h.Sum(nil) - h2.Write(input[i/2 : i]) - sum2 := h2.Sum(nil) - - if !bytes.Equal(sum, sum2) { - t.Fatalf("size=%d, len(input)=%d: results do not match; sum = %v, sum2 = %v", size, i, sum, sum2) - } - - h3, err := New(size, nil) - if err != nil { - t.Fatalf("size=%d, len(input)=%d: error from New(%v, nil): %v", size, i, size, err) - } - h3.Write(input[:i]) - sum3 := h3.Sum(nil) - if !bytes.Equal(sum, sum3) { - t.Fatalf("size=%d, len(input)=%d: sum = %v, want %v", size, i, sum, sum3) - } - } - } -} - -func testHashes(t *testing.T) { - key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") - - input := make([]byte, 255) - for i := range input { - input[i] = byte(i) - } - - for i, expectedHex := range hashes { - h, err := New512(key) - if err != nil { - t.Fatalf("#%d: error from New512: %v", i, err) - } - - h.Write(input[:i]) - sum := h.Sum(nil) - - if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { - t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) - } - - h.Reset() - for j := 0; j < i; j++ { - h.Write(input[j : j+1]) - } - - sum = h.Sum(sum[:0]) - if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { - t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) - } - } -} - -func testHashes2X(t *testing.T) { - key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") - - input := make([]byte, 256) - for i := range input { - input[i] = byte(i) - } - - for i, expectedHex := range hashes2X { - length := uint32(len(expectedHex) / 2) - sum := make([]byte, int(length)) - - h, err := NewXOF(length, key) - if err != nil { - t.Fatalf("#%d: error from NewXOF: %v", i, err) - } - - if _, err := h.Write(input); err != nil { - t.Fatalf("#%d (single write): error from Write: %v", i, err) - } - if _, err := h.Read(sum); err != nil { - t.Fatalf("#%d (single write): error from Read: %v", i, err) - } - if n, err := h.Read(sum); n != 0 || err != io.EOF { - t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err) - } - if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { - t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) - } - - h.Reset() - for j := 0; j < len(input); j++ { - h.Write(input[j : j+1]) - } - for j := 0; j < len(sum); j++ { - h = h.Clone() - if _, err := h.Read(sum[j : j+1]); err != nil { - t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) - } - } - if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { - t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) - } - } - - h, err := NewXOF(OutputLengthUnknown, key) - if err != nil { - t.Fatalf("#unknown length: error from NewXOF: %v", err) - } - if _, err := h.Write(input); err != nil { - t.Fatalf("#unknown length: error from Write: %v", err) - } - - var result [64]byte - if n, err := h.Read(result[:]); err != nil { - t.Fatalf("#unknown length: error from Read: %v", err) - } else if n != len(result) { - t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) - } - - const expected = "3dbba8516da76bf7330055c66ea36cf1005e92714262b24d9710f51d9e126406e1bcd6497059f9331f1091c3634b695428d475ed432f987040575520a1c29f5e" - if fmt.Sprintf("%x", result) != expected { - t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) - } -} - -func generateSequence(out []byte, seed uint32) { - a := 0xDEAD4BAD * seed // prime - b := uint32(1) - - for i := range out { // fill the buf - a, b = b, a+b - out[i] = byte(b >> 24) - } -} - -func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) { - var h hash.Hash - switch hashSize { - case Size: - h, _ = New512(key) - case Size384: - h, _ = New384(key) - case Size256: - h, _ = New256(key) - case 20: - h, _ = newDigest(20, key) - default: - panic("unexpected hashSize") - } - - h.Write(msg) - return h.Sum(sum) -} - -func computeHash(msg []byte, hashSize int) (sum []byte) { - switch hashSize { - case Size: - hash := Sum512(msg) - return hash[:] - case Size384: - hash := Sum384(msg) - return hash[:] - case Size256: - hash := Sum256(msg) - return hash[:] - case 20: - var hash [64]byte - checkSum(&hash, 20, msg) - return hash[:20] - default: - panic("unexpected hashSize") - } -} - -// Test function from RFC 7693. -func TestSelfTest(t *testing.T) { - hashLens := [4]int{20, 32, 48, 64} - msgLens := [6]int{0, 3, 128, 129, 255, 1024} - - msg := make([]byte, 1024) - key := make([]byte, 64) - - h, _ := New256(nil) - for _, hashSize := range hashLens { - for _, msgLength := range msgLens { - generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash - - md := computeHash(msg[:msgLength], hashSize) - h.Write(md) - - generateSequence(key[:], uint32(hashSize)) // keyed hash - md = computeMAC(msg[:msgLength], hashSize, key[:hashSize]) - h.Write(md) - } - } - - sum := h.Sum(nil) - expected := [32]byte{ - 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd, - 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56, - 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73, - 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75, - } - if !bytes.Equal(sum, expected[:]) { - t.Fatalf("got %x, wanted %x", sum, expected) - } -} - -// Benchmarks - -func benchmarkSum(b *testing.B, size int, sse4, avx, avx2 bool) { - // Enable the correct set of instructions - defer func(sse4, avx, avx2 bool) { - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - }(useSSE4, useAVX, useAVX2) - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - - data := make([]byte, size) - b.SetBytes(int64(size)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Sum512(data) - } -} - -func benchmarkWrite(b *testing.B, size int, sse4, avx, avx2 bool) { - // Enable the correct set of instructions - defer func(sse4, avx, avx2 bool) { - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - }(useSSE4, useAVX, useAVX2) - useSSE4, useAVX, useAVX2 = sse4, avx, avx2 - - data := make([]byte, size) - h, _ := New512(nil) - b.SetBytes(int64(size)) - b.ResetTimer() - for i := 0; i < b.N; i++ { - h.Write(data) - } -} - -func BenchmarkWrite128Generic(b *testing.B) { benchmarkWrite(b, 128, false, false, false) } -func BenchmarkWrite1KGeneric(b *testing.B) { benchmarkWrite(b, 1024, false, false, false) } -func BenchmarkWrite128SSE4(b *testing.B) { benchmarkWrite(b, 128, true, false, false) } -func BenchmarkWrite1KSSE4(b *testing.B) { benchmarkWrite(b, 1024, true, false, false) } -func BenchmarkWrite128AVX(b *testing.B) { benchmarkWrite(b, 128, false, true, false) } -func BenchmarkWrite1KAVX(b *testing.B) { benchmarkWrite(b, 1024, false, true, false) } -func BenchmarkWrite128AVX2(b *testing.B) { benchmarkWrite(b, 128, false, false, true) } -func BenchmarkWrite1KAVX2(b *testing.B) { benchmarkWrite(b, 1024, false, false, true) } - -func BenchmarkSum128Generic(b *testing.B) { benchmarkSum(b, 128, false, false, false) } -func BenchmarkSum1KGeneric(b *testing.B) { benchmarkSum(b, 1024, false, false, false) } -func BenchmarkSum128SSE4(b *testing.B) { benchmarkSum(b, 128, true, false, false) } -func BenchmarkSum1KSSE4(b *testing.B) { benchmarkSum(b, 1024, true, false, false) } -func BenchmarkSum128AVX(b *testing.B) { benchmarkSum(b, 128, false, true, false) } -func BenchmarkSum1KAVX(b *testing.B) { benchmarkSum(b, 1024, false, true, false) } -func BenchmarkSum128AVX2(b *testing.B) { benchmarkSum(b, 128, false, false, true) } -func BenchmarkSum1KAVX2(b *testing.B) { benchmarkSum(b, 1024, false, false, true) } - -// These values were taken from https://blake2.net/blake2b-test.txt. -var hashes = []string{ - "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568", - "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd", - "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965", - "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1", - "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac", - "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb", - "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f", - "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52", - "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9", - "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637", - "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd", - "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b", - "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563", - "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355", - "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6", - "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e", - "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93", - "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1", - "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670", - "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9", - "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c", - "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd", - "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152", - "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9", - "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f", - "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b", - "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764", - "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d", - "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55", - "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b", - "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e", - "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7", - "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991", - "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347", - "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82", - "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42", - "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327", - "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760", - "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252", - "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55", - "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1", - "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee", - "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa", - "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7", - "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071", - "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4", - "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf", - "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d", - "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8", - "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487", - "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c", - "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2", - "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa", - "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33", - "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d", - "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e", - "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2", - "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4", - "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2", - "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a", - "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564", - "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f", - "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9", - "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa", - "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022", - "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c", - "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc", - "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f", - "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b", - "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866", - "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d", - "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8", - "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4", - "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3", - "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e", - "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745", - "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545", - "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063", - "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd", - "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a", - "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed", - "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd", - "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275", - "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897", - "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430", - "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab", - "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f", - "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46", - "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29", - "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab", - "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8", - "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a", - "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec", - "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79", - "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24", - "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b", - "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5", - "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463", - "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4", - "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3", - "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9", - "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d", - "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4", - "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a", - "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6", - "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73", - "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6", - "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6", - "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3", - "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa", - "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3", - "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b", - "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f", - "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc", - "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200", - "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6", - "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8", - "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f", - "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a", - "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e", - "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935", - "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74", - "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0", - "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c", - "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145", - "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f", - "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0", - "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb", - "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4", - "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91", - "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89", - "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444", - "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a", - "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414", - "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49", - "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b", - "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0", - "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469", - "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3", - "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd", - "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8", - "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21", - "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989", - "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1", - "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399", - "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0", - "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723", - "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff", - "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc", - "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38", - "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a", - "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051", - "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca", - "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4", - "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677", - "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1", - "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce", - "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347", - "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91", - "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209", - "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659", - "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381", - "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56", - "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7", - "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f", - "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972", - "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe", - "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e", - "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be", - "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8", - "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc", - "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8", - "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0", - "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc", - "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979", - "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29", - "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d", - "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108", - "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45", - "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4", - "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267", - "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d", - "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb", - "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813", - "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc", - "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29", - "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc", - "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16", - "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1", - "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c", - "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7", - "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a", - "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa", - "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e", - "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc", - "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5", - "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a", - "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3", - "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc", - "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d", - "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff", - "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb", - "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4", - "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc", - "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902", - "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e", - "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08", - "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816", - "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406", - "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4", - "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d", - "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d", - "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900", - "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06", - "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01", - "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0", - "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94", - "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02", - "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492", - "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2", - "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c", - "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb", - "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077", - "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727", - "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd", - "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c", - "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0", - "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403", - "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391", - "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8", - "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605", - "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9", - "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d", - "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe", - "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe", - "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1", - "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3", - "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb", - "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b", - "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef", - "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253", - "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec", - "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a", - "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473", - "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837", - "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a", - "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1", - "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d", - "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9", - "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537", - "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7", - "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2", - "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338", - "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15", - "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9", - "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", -} - -var hashes2X = []string{ - "64", - "f457", - "e8c045", - "a74c6d0d", - "eb02ae482a", - "be65b981275e", - "8540ccd083a455", - "074a02fa58d7c7c0", - "da6da05e10db3022b6", - "542a5aae2f28f2c3b68c", - "ca3af2afc4afe891da78b1", - "e0f66b8dcebf4edc85f12c85", - "744224d383733b3fa2c53bfcf5", - "b09b653e85b72ef5cdf8fcfa95f3", - "dd51877f31f1cf7b9f68bbb09064a3", - "f5ebf68e7ebed6ad445ffc0c47e82650", - "ebdcfe03bcb7e21a9091202c5938c0a1bb", - "860fa5a72ff92efafc48a89df1632a4e2809", - "0d6d49daa26ae2818041108df3ce0a4db48c8d", - "e5d7e1bc5715f5ae991e4043e39533af5d53e47f", - "5232028a43b9d4dfa7f37439b49495926481ab8a29", - "c118803c922f9ae2397fb676a2ab7603dd9c29c21fe4", - "2af924f48b9bd7076bfd68794bba6402e2a7ae048de3ea", - "61255ac38231087c79ea1a0fa14538c26be1c851b6f318c0", - "f9712b8e42f0532162822f142cb946c40369f2f0e77b6b186e", - "76da0b89558df66f9b1e66a61d1e795b178ce77a359087793ff2", - "9036fd1eb32061bdecebc4a32aa524b343b8098a16768ee774d93c", - "f4ce5a05934e125d159678bea521f585574bcf9572629f155f63efcc", - "5e1c0d9fae56393445d3024d6b82692d1339f7b5936f68b062c691d3bf", - "538e35f3e11111d7c4bab69f83b30ade4f67addf1f45cdd2ac74bf299509", - "17572c4dcbb17faf8785f3bba9f6903895394352eae79b01ebd758377694cc", - "29f6bb55de7f8868e053176c878c9fe6c2055c4c5413b51ab0386c277fdbac75", - "bad026c8b2bd3d294907f2280a7145253ec2117d76e3800357be6d431b16366e41", - "386b7cb6e0fd4b27783125cbe80065af8eb9981fafc3ed18d8120863d972fa7427d9", - "06e8e6e26e756fff0b83b226dce974c21f970e44fb5b3e5bbada6e4b12f81cca666f48", - "2f9bd300244f5bc093ba6dcdb4a89fa29da22b1de9d2c9762af919b5fedf6998fbda305b", - "cf6bdcc46d788074511f9e8f0a4b86704365b2d3f98340b8db53920c385b959a38c8869ae7", - "1171e603e5cdeb4cda8fd7890222dd8390ede87b6f3284cac0f0d832d8250c9200715af7913d", - "bda7b2ad5d02bd35ffb009bdd72b7d7bc9c28b3a32f32b0ba31d6cbd3ee87c60b7b98c03404621", - "2001455324e748503aa08eff2fb2e52ae0170e81a6e9368ada054a36ca340fb779393fb045ac72b3", - "45f0761aefafbf87a68f9f1f801148d9bba52616ad5ee8e8ac9207e9846a782f487d5cca8b20355a18", - "3a7e05708be62f087f17b41ac9f20e4ef8115c5ab6d08e84d46af8c273fb46d3ce1aabebae5eea14e018", - "ea318da9d042ca337ccdfb2bee3e96ecb8f907876c8d143e8e44569178353c2e593e4a82c265931ba1dd79", - "e0f7c08f5bd712f87094b04528fadb283d83c9ceb82a3e39ec31c19a42a1a1c3bee5613b5640abe069b0d690", - "d35e63fb1f3f52ab8f7c6cd7c8247e9799042e53922fbaea808ab979fa0c096588cfea3009181d2f93002dfc11", - "b8b0ab69e3ae55a8699eb481dd665b6a2424c89bc6b7cca02d15fdf1b9854139cab49d34de498b50b2c7e8b910cf", - "fb65e3222a2950eae1701d4cdd4736266f65bf2c0d2e77968996eadb60ef74fb786f6234973a2524bdfe32d100aa0e", - "f28b4bb3a2e2c4d5c01a23ff134558559a2d3d704b75402983ee4e0f71d273ae056842c4153b18ee5c47e2bfa54313d4", - "7bb78794e58a53c3e4b1aeb161e756af051583d14e0a5a3205e094b7c9a8cf62d098fa9ea1db12f330a51ab9852c17f983", - "a879a8ebae4d0987789bcc58ec3448e35ba1fa1ee58c668d8295aba4eaeaf2762b053a677e25404f635a53037996974d418a", - "695865b353ec701ecc1cb38f3154489eed0d39829fc192bb68db286d20fa0a64235cde5639137819f7e99f86bd89afcef84a0f", - "a6ec25f369f71176952fb9b33305dc768589a6070463ee4c35996e1ced4964a865a5c3dc8f0d809eab71366450de702318e4834d", - "604749f7bfadb069a036409ffac5ba291fa05be8cba2f141554132f56d9bcb88d1ce12f2004cd3ade1aa66a26e6ef64e327514096d", - "daf9fa7dc2464a899533594e7916fc9bc585bd29dd60c930f3bfa78bc47f6c8439448043a45119fc9228c15bce5fd24f46baf9de736b", - "943ea5647a8666763084da6a6f15dcf0e8dc24f27fd0d9194805d25180fe3a6d98f4b2b5e0d6a04e9b41869817030f16ae975dd41fc35c", - "af4f73cbfc093760dfeb52d57ef45207bbd1a515f5523404e5d95a73c237d97ae65bd195b472de6d514c2c448b12fafc282166da132258e9", - "605f4ed72ed7f5046a342fe4cf6808100d4632e610d59f7ebb016e367d0ff0a95cf45b02c727ba71f147e95212f52046804d376c918cadd260", - "3750d8ab0a6b13f78e51d321dfd1aa801680e958de45b7b977d05732ee39f856b27cb2bcce8fbf3db6666d35e21244c2881fdcc27fbfea6b1672", - "8f1b929e80ab752b58abe9731b7b34eb61369536995abef1c0980d93903c1880da3637d367456895f0cb4769d6de3a979e38ed6f5f6ac4d48e9b32", - "d8469b7aa538b36cdc711a591d60dafecca22bd421973a70e2deef72f69d8014a6f0064eabfbebf5383cbb90f452c6e113d2110e4b1092c54a38b857", - "7d1f1ad2029f4880e1898af8289c23bc933a40863cc4ab697fead79c58b6b8e25b68cf5324579b0fe879fe7a12e6d03907f0140dfe7b29d33d6109ecf1", - "87a77aca6d551642288a0dff66078225ae39d288801607429d6725ca949eed7a6f199dd8a65523b4ee7cfa4187400e96597bfffc3e38ade0ae0ab88536a9", - "e101f43179d8e8546e5ce6a96d7556b7e6b9d4a7d00e7aade5579d085d527ce34a9329551ebcaf6ba946949bbe38e30a62ae344c1950b4bde55306b3bac432", - "4324561d76c370ef35ac36a4adf8f3773a50d86504bd284f71f7ce9e2bc4c1f1d34a7fb2d67561d101955d448b67577eb30dfee96a95c7f921ef53e20be8bc44", - "78f0ed6e220b3da3cc9381563b2f72c8dc830cb0f39a48c6ae479a6a78dcfa94002631dec467e9e9b47cc8f0887eb680e340aec3ec009d4a33d241533c76c8ca8c", - "9f6589c31a472e0a736f4eb22b6c70a9d332cc15304ccb66a6b97cd051b6ed82f8990e1d9bee2e4bb1c3c45e550ae0e7b96e93ae23f2fb8f63b309131e72b36cba6a", - "c138077ee4ed3d7ffa85ba851dfdf6e9843fc1dc00889d117237bfaad9aa757192f73556b959f98e6d24886ce48869f2a01a48c371785f12b6484eb2078f08c22066e1", - "f83e7c9e0954a500576ea1fc90a3db2cbd7994eaef647dab5b34e88ab9dc0b47addbc807b21c8e6dd3d0bd357f008471d4f3e0abb18450e1d4919e03a34545b9643f870e", - "3277a11f2628544fc66f50428f1ad56bcba6ee36ba2ca6ecdf7e255effc0c30235c039d13e01f04cf1efe95b5c2033ab72adda30994b62f2851d17c9920eadca9a251752dc", - "c2a834281a06fe7b730d3a03f90761daf02714c066e33fc07e1f59ac801ec2f4433486b5a2da8faa51a0cf3c34e29b2960cd0013378938dbd47c3a3d12d70db01d7d06c3e91e", - "47680182924a51cabe142a6175c9253e8ba7ea579ece8d9bcb78b1e9ca00db844fa08abcf41702bd758ee2c608d9612fed50e85854469cb4ef3038acf1e35b6ba4390561d8ae82", - "cec45830cd71869e83b109a99a3cd7d935f83a95de7c582f3adbd34e4938fa2f3f922f52f14f169c38cc6618d3f306a8a4d607b345b8a9c48017136fbf825aecf7b620e85f837fae", - "46fb53c70ab105079d5d78dc60eaa30d938f26e4d0b9df122e21ec85deda94744c1daf8038b8a6652d1ff3e7e15376f5abd30e564784a999f665078340d66b0e939e0c2ef03f9c08bb", - "7b0dcb52791a170cc52f2e8b95d8956f325c3751d3ef3b2b83b41d82d4496b46228a750d02b71a96012e56b0720949ca77dc68be9b1ef1ad6d6a5ceb86bf565cb972279039e209dddcdc", - "7153fd43e6b05f5e1a4401e0fef954a737ed142ec2f60bc4daeef9ce73ea1b40a0fcaf1a1e03a3513f930dd5335723632f59f7297fe3a98b68e125eadf478eb045ed9fc4ee566d13f537f5", - "c7f569c79c801dab50e9d9ca6542f25774b3841e49c83efe0b89109f569509ce7887bc0d2b57b50320eb81fab9017f16c4c870e59edb6c26620d93748500231d70a36f48a7c60747ca2d5986", - "0a81e0c547648595adca65623ce783411aac7f7d30c3ad269efafab288e7186f6895261972f5137877669c550f34f5128850ebb50e1884814ea1055ee29a866afd04b2087abed02d9592573428", - "6a7b6769e1f1c95314b0c7fe77013567891bd23416374f23e4f43e27bc4c55cfada13b53b1581948e07fb96a50676baa2756db0988077b0f27d36ac088e0ff0fe72eda1e8eb4b8facff3218d9af0", - "a399474595cb1ccab6107f18e80f03b1707745c7bf769fc9f260094dc9f8bc6fe09271cb0b131ebb2acd073de4a6521c8368e664278be86be216d1622393f23435fae4fbc6a2e7c961282a777c2d75", - "4f0fc590b2755a515ae6b46e9628092369d9c8e589e3239320639aa8f7aa44f8111c7c4b3fdbe6e55e036fbf5ebc9c0aa87a4e66851c11e86f6cbf0bd9eb1c98a378c7a7d3af900f55ee108b59bc9e5c", - "ed96a046f08dd675107331d267379c6fce3c352a9f8d7b243008a74cb4e9410836afaabe871dab6038ca94ce5f6d41fa922ce08aba58169f94cfc86d9f688f396abd24c11a6a9b0830572105a477c33e92", - "379955f539abf0eb2972ee99ed9546c4bbee363403991833005dc27904c271ef22a799bc32cb39f08d2e4ba6717d55153feb692d7c5efae70890bf29d96df02333c7b05ccc314e4835b018fec9141a82c745", - "e16cc8d41b96547ede0d0cf4d908c5fa393399daa4a9696e76a4c1f6a2a9fef70f17fb53551a8145ed88f18db8fe780a079d94732437023f7c1d1849ef69ad536a76204239e8ba5d97e507c36c7d042f87fe0e", - "a81de50750ece3f84536728f227208bf01ec5b7721579d007de72c88ee20663318332efe5bc7c09ad1fa8342be51f0609046ccf760a7957a7d8dc88941adb93666a4521ebe76618e5ddc2dd3261493d400b50073", - "b72c5fb7c7f60d243928fa41a2d711157b96aef290185c64b4de3dcfa3d644da67a8f37c2ac55caad79ec695a473e8b481f658c497edb8a191526592b11a412282d2a4010c90ef4647bd6ce745ebc9244a71d4876b", - "9550703877079c90e200e830f277b605624954c549e729c359ee01ee2b07741ecc4255cb37f96682dafcdbaade1063e2c5ccbd1918fb669926a67744101fb6de3ac016be4c74165a1e5a696b704ba2ebf4a953d44b95", - "a17eb44d4de502dc04a80d5a5e9507d17f27c96467f24c79b06bc98a4c410741d4ac2db98ec02c2a976d788531f1a4451b6c6204cef6dae1b6ebbcd0bde23e6fffb02754043c8fd3c783d90a670b16879ce68b5554fe1c", - "41d3ea1eaba5be4a206732dbb5b70b79b66a6e5908795ad4fb7cf9e67efb13f06fef8f90acb080ce082aadec6a1b543af759ab63fa6f1d3941186482b0c2b312f1151ea8386253a13ed3708093279b8eb04185636488b226", - "5e7cdd8373dc42a243c96013cd29df9283b5f28bb50453a903c85e2ce57f35861bf93f03029072b70dac0804e7d51fd0c578c8d9fa619f1e9ce3d8044f65d55634dba611280c1d5cfb59c836a595c803124f696b07ddfac718", - "26a14c4aa168907cb5de0d12a82e1373a128fb21f2ed11feba108b1bebce934ad63ed89f4ed7ea5e0bc8846e4fc10142f82de0bebd39d68f7874f615c3a9c896bab34190e85df05aaa316e14820b5e478d838fa89dfc94a7fc1e", - "0211dfc3c35881adc170e4ba6daab1b702dff88933db9a6829a76b8f4a7c2a6d658117132a974f0a0b3a38ceea1efc2488da21905345909e1d859921dc2b5054f09bce8eeb91fa2fc6d048ce00b9cd655e6aafbdaa3a2f19270a16", - "ddf015b01b68c4f5f72c3145d54049867d99ee6bef24282abf0eecdb506e295bacf8f23ffa65a4cd891f76a046b9dd82cae43a8d01e18a8dff3b50aeb92672be69d7c087ec1fa2d3b2a39196ea5b49b7baede37a586fea71aded587f", - "6ee721f71ca4dd5c9ce7873c5c04c6ce76a2c824b984251c15535afc96adc9a4d48ca314bfeb6b8ee65092f14cf2a7ca9614e1dcf24c2a7f0f0c11207d3d8aed4af92873b56e8b9ba2fbd659c3f4ca90fa24f113f74a37181bf0fdf758", - "689bd150e65ac123612524f720f54def78c095eaab8a87b8bcc72b443408e3227f5c8e2bd5af9bcac684d497bc3e41b7a022c28fb5458b95e8dfa2e8caccde0492936ff1902476bb7b4ef2125b19aca2cd3384d922d9f36dddbcd96ae0d6", - "3a3c0ef066fa4390ec76ad6be1dc9c31ddf45fef43fbfa1f49b439caa2eb9f3042253a9853e96a9cf86b4f873785a5d2c5d3b05f6501bc876e09031188e05f48937bf3c9b667d14800db62437590b84ce96aa70bb5141ee2ea41b55a6fd944", - "741ce384e5e0edaebb136701ce38b3d33215415197758ae81235307a4115777d4dab23891db530c6d28f63a957428391421f742789a0e04c99c828373d9903b64dd57f26b3a38b67df829ae243feef731ead0abfca049924667fdec49d40f665", - "a513f450d66cd5a48a115aee862c65b26e836f35a5eb6894a80519e2cd96cc4cad8ed7eb922b4fc9bbc55c973089d627b1da9c3a95f6c019ef1d47143cc545b15e4244424be28199c51a5efc7234dcd94e72d229897c392af85f523c2633427825", - "71f1554d2d49bb7bd9e62e71fa049fb54a2c097032f61ebda669b3e1d4593962e47fc62a0ab5d85706aebd6a2f9a192c88aa1ee2f6a46710cf4af6d3c25b7e68ad5c3db23ac009c8f13625ff85dc8e50a9a1b2682d3329330b973ec8cbb7bb73b2bd", - "167cc1067bc08a8d2c1a0c10041ebe1fc327b37043f6bd8f1c63569e9d36ded58519e66b162f34b6d8f1107ef1e3de199d97b36b44141a1fc4f49b883f40507ff11f909a017869dc8a2357fc7336ae68703d25f75710b0ff5f9765321c0fa53a51675c", - "cb859b35dc70e264efaad2a809fea1e71cd4a3f924be3b5a13f8687a1166b538c40b2ad51d5c3e47b0de482497382673140f547068ff0b3b0fb7501209e1bf36082509ae85f60bb98fd02ac50d883a1a8daa704952d83c1f6da60c9624bc7c99912930bf", - "afb1f0c6b7125b04fa2578dd40f60cb411b35ebc7026c702e25b3f0ae3d4695d44cfdf37cb755691dd9c365edadf21ee44245620e6a24d4c2497135b37cd7ac67e3bd0aaee9f63f107746f9b88859ea902bc7d6895406aa2161f480cad56327d0a5bba2836", - "13e9c0522587460d90c7cb354604de8f1bf850e75b4b176bda92862d35ec810861f7d5e7ff6ba9302f2c2c8642ff8b7776a2f53665790f570fcef3cac069a90d50db42227331c4affb33d6c040d75b9aeafc9086eb83ced38bb02c759e95ba08c92b17031288", - "0549812d62d3ed497307673a4806a21060987a4dbbf43d352b9b170a29240954cf04bc3e1e250476e6800b79e843a8bd8253b7d743de01ab336e978d4bea384eaff700ce020691647411b10a60acacb6f8837fb08ad666b8dcc9eaa87ccb42aef6914a3f3bc30a", - "3a263efbe1f2d463f20526e1d0fd735035fd3f808925f058b32c4d8788aeeab9b8ce233b3c34894731cd73361f465bd350395aebcabd2fb63010298ca025d849c1fa3cd573309b74d7f824bbfe383f09db24bcc565f636b877333206a6ad70815c3bef5574c5fc1c", - "3c6a7d8a84ef7e3eaa812fc1eb8e85105467230d2c9e4562edbfd808f4d1ac15d16b786cc6a02959c2bc17149c2ce74c6f85ee5ef22a8a96b9be1f197cffd214c1ab02a06a9227f37cd432579f8c28ff2b5ac91cca8ffe6240932739d56788c354e92c591e1dd76499", - "b571859294b02af17541a0b5e899a5f67d6f5e36d38255bc417486e69240db56b09cf2607fbf4f95d085a779358a8a8b41f36503438c1860c8f361ce0f2783a08b21bd7232b50ca6d35428335272a5c05b436b2631d8d5c84d60e8040083768ce56a250727fb0579dd5c", - "98ee1b7269d2a0dd490ca38d447279870ea55326571a1b430adbb2cf65c492131136f504145df3ab113a13abfb72c33663266b8bc9c458db4bf5d7ef03e1d3b8a99d5de0c024be8fabc8dc4f5dac82a0342d8ed65c329e7018d6997e69e29a01350516c86beaf153da65ac", - "41c5c95f088df320d35269e5bf86d10248f17aec6776f0fe653f1c356aae409788c938befeb67c86d1c8870e8099ca0ce61a80fbb5a6654c44529368f70fc9b9c2f912f5092047d0ffc339577d24142300e34948e086f62e23ecaca410d24f8a36b5c8c5a80e0926bc8aa16a", - "9f93c41f533b2a82a4df893c78faaaa793c1506974ba2a604cd33101713ca4adfd30819ffd8403402b8d40aff78106f3357f3e2c24312c0d3603a17184d7b999fc9908d14d50192aebabd90d05073da7af4be37dd3d81c90acc80e8333df546f17ab6874f1ec204392d1c0571e", - "3da5207245ac270a915fc91cdb314e5a2577c4f8e269c4e701f0d7493ba716de79935918b917a2bd5db98050dbd1eb3894b65fac5abf13e075abebc011e651c03cafb6127147771a5c8418223e1548137a89206635c26ca9c235ccc108dc25cf846e4732444bd0c2782b197b262b", - "96011af3965bb941dc8f749932ea484eccb9ba94e34b39f24c1e80410f96ce1d4f6e0aa5be606def4f54301e930493d4b55d484d93ab9dd4dc2c9cfb79345363af31ad42f4bd1aa6c77b8afc9f0d551bef7570b13b927afe3e7ac4de7603a0876d5edb1ad9be05e9ee8b53941e8f59", - "51dbbf2a7ca224e524e3454fe82ddc901fafd2120fa8603bc343f129484e9600f688586e040566de0351d1693829045232d04ff31aa6b80125c763faab2a9b233313d931903dcfaba490538b06e4688a35886dc24cdd32a13875e6acf45454a8eb8a315ab95e608ad8b6a49aef0e299a", - "5a6a422529e22104681e8b18d64bc0463a45df19ae2633751c7aae412c250f8fb2cd5e1270d3d0cf009c8aa69688ccd4e2b6536f5747a5bc479b20c135bf4e89d33a26118705a614c6be7ecfe766932471ad4ba01c4f045b1abb5070f90ec78439a27a1788db9327d1c32f939e5fb1d5ba", - "5d26c983642093cb12ff0afabd87b7c56e211d01844ad6da3f623b9f20a0c968034299f2a65e6673530c5980a532beb831c7d0697d12760445986681076dfb6fae5f3a4d8f17a0db5008ce8619f566d2cfe4cf2a6d6f9c3664e3a48564a351c0b3c945c5ee24587521e4112c57e318be1b6a", - "52641dbc6e36be4d905d8d60311e303e8e859cc47901ce30d6f67f152343e3c4030e3a33463793c19effd81fb7c4d631a9479a7505a983a052b1e948ce093b30efa595fab3a00f4cef9a2f664ceeb07ec61719212d58966bca9f00a7d7a8cb4024cf6476bab7fbccee5fd4e7c3f5e2b2975aa2", - "a34ce135b37bf3db1c4aaa4878b4499bd2ee17b85578fcaf605d41e1826b45fdaa1b083d8235dc642787f11469a5493e36806504fe2a2063905e821475e2d5ee217057950370492f5024995e77b82aa51b4f5bd8ea24dc71e0a8a640b0592c0d80c24a726169cf0a10b40944747113d03b52708c", - "46b3cdf4946e15a5334fc3244d6680f5fc132afa67bf43bfade23d0c9e0ec64e7dab76faaeca1870c05f96b7d019411d8b0873d9fed04fa5057c039d5949a4d592827f619471359d6171691cfa8a5d7cb07ef2804f6ccad4821c56d4988bea7765f660f09ef87405f0a80bcf8559efa111f2a0b419", - "8b9fc21691477f11252fca050b121c5334eb4280aa11659e267297de1fec2b2294c7ccee9b59a149b9930b08bd320d3943130930a7d931b71d2f10234f4480c67f1de883d9894ada5ed5071660e221d78ae402f1f05af47761e13fec979f2671e3c63fb0ae7aa1327cf9b8313adab90794a52686bbc4", - "cd6598924ce847de7ff45b20ac940aa6292a8a99b56a74eddc24f2cfb45797188614a21d4e8867e23ff75afd7cd324248d58fcf1ddc73fbd115dfa8c09e62022fab540a59f87c989c12a86ded05130939f00cd2f3b512963dfe0289f0e54acad881c1027d2a0292138fdee902d67d9669c0ca1034a9456", - "594e1cd7337248704e691854af0fdb021067ddf7832b049ba7b684438c32b029eded2df2c89a6ff5f2f2c311522ae2dc6db5a815afc60637b15ec24ef9541f1550409db2a006da3affffe548a1eaee7bd114e9b805d0756c8e90c4dc33cb05226bc2b393b18d953f8730d4c7ae693159cdba758ad28964e2", - "1f0d292453f04406ada8be4c161b82e3cdd69099a8637659e0ee40b8f6da46005cfc6085db9804852decfbe9f7b4dda019a7112612895a144ed430a960c8b2f5458d3d56b7f427cee6358915aee7146278aed2a0296cdd929e4d21ef95a3adf8b7a6beba673cdccdbdcfb2474711732d972ad054b2dc64f38d", - "b65a72d4e1f9f9f75911cc46ad0806b9b18c87d105332a3fe183f45f063a746c892dc6c4b9181b1485b3e3a2cc3b453eba2d4c39d6905a774ed3fb755468beb190925ecd8e57ecb0d985125741650c6b6a1b2a3a50e93e3892c21d47ed5884eed83aa94e1602288f2f49fe286624de9d01fcb54433a0dc4ad70b", - "705ce0ffa469250782aff725248fc88fe98eb76659e8407edc1c4842c9867d61fe64fb86f74e980598b92bc213d06f337bd5654fc28643c7ba769a4c31563427543c00808b627a19c90d86c322f33566ce020121cc322229c3337943d46f68ef939d613dcef0077269f88151d6398b6b009abb763410b154ad76a3", - "7fa881ce87498440ab6af13854f0d851a7e0404de33896999a9b3292a5d2f5b3ad033530c558168fe5d2fdb9b89a2354c46cf32a0e612afc6c6485d789511bfef26800c74bf1a4cfbe30bda310d5f6029c3dccdedb6149e4971274e276dccfabd63bc4b9955e8303feb57f8a688db55ecb4b33d1f9fe1b3a8ba7ac32", - "23a98f71c01c0408ae16843dc03be7db0aeaf055f951709d4e0dfdf64fffbffaf900ee592ee10929648e56f6c1e9f5be5793f7df66453eb56502c7c56c0f0c88da77abc8fa371e434104627ef7c663c49f40998dbad63fa6c7aa4fac17ae138d8bbe081f9bd168cd33c1fbc92fa35ed687679f48a64b87db1fe5bae675", - "7b8970b6a33237e5a7bcb39272703edb92285c55842b30b9a48834b1b507cc02a6764739f2f7ee6ae02a7b715a1c455e59e8c77a1ae98abb10161853f1234d20da99016588cd8602d6b7ec7e177d4011edfa61e6b3766a3c6f8d6e9eac893c568903eb6e6aba9c4725774f6b4343b7acaa6c031593a36eef6c72806ff309", - "f7f4d328ba108b7b1de4443e889a985ed52f485f3ca4e0c246aa5526590cbed344e9f4fe53e4eea0e761c82324649206ca8c2b45152157d4115e68c818644b03b65bb47ad79f94d37cb03c1d953b74c2b8adfa0e1c418bda9c518ddcd7050e0f149044740a2b16479413b63fc13c36144f80c73687513dca761ba8642a8ae0", - "2d7dc80c19a1d12d5fe3963569547a5d1d3e821e6f06c5d5e2c09401f946c9f7e13cd019f2f9a878b62dd850453b6294b99ccaa068e542993524b0f63832d48e865be31e8ec1ee103c718340c904b32efb69170b67f038d50a3252794b1b4076c0620621ab3d91215d55ffea99f23d54e161a90d8d4902fda5931d9f6a27146a", - "77dff4c7ad30c954338c4b23639dae4b275086cbe654d401a2343528065e4c9f1f2eca22aa025d49ca823e76fdbb35df78b1e5075ff2c82b680bca385c6d57f7ea7d1030bb392527b25dd73e9eeff97bea397cf3b9dda0c817a9c870ed12c006cc054968c64000e0da874e9b7d7d621b0679866912243ea096c7b38a1344e98f74", - "83bed0d556798f2b419f7056e6d3ffada06e939b95a688d0ec8c6ac5ea45ab73a4cf01043e0a170766e21395f27ab4b78c435f5f0dfe6e93ab80df38610e41158429ddf20296f53a06a017723359fe22dc08b5da33f0800a4fe50118e8d7eab2f83a85cd764bf8a166903bd0e9dcfeeceba44ff4ca4439846458d31ea2bb564645d1", - "ea12cf5a113543e39504123036f15a5bafa9c555562469f99cd29996a4dfaaab2a34b00557ccf15f37fc0cc1b3be427e725f2cd952e50af7970dda9200cd5ce252b1f29c40067fea3027ed686190803b59d834179d1b8f5b55abe55ad174b2a1188f7753ec0ae2fc01316e7d498b68ee3598a0e9baaaa664a60f7fb4f90edbed494ad7", - "55266358332d8d9e68bd13432088beadf95833aab67a0eb3b10650414255f299e2670c3e1a5b2976159a46c72a7ce57d59b7be14c15798e09ed50fa312a431b0264d7a1396aa6168bde897e208ece53d2cfc83786113b1e6eac5e9bb98984abb6c8d64eebb991903254abc650c999bb9958a5d7937434b869bc940e21b9dc1cc8982f2ba", - "4d6104ded730aefe02873f4c741232c8234a6d66d85393aff57fbf56ba6347666988dfc4d58f3cc895a0da598822edeee4533d24ec0ee292fd5e1ad04898ffbc1ff4bef14dec220babcb0f28fffe32a6e2c28aaaac16442bf4feb02917d18bb3a415d84fa9358d5a9852688d846c92271911f934181c30f82434d915f93f155a1ffbf0b125", - "eb5f579a4c476af554aac11e5719d378549497e613b35a929d6f36bb8831d7a466aa76de9be24ebb55543f1c13924f64cfd648a5b3fa90387315c16174dbf1e9a183c196d9bb8f84af65f1f8212429aadc11ef2426d07d4716062b85c8d5d2dff8e21b9e62b7fa7dbd57d72633054b464fb28583a56ca13ccc5ddc74dae942492f31731e7046", - "ebddec3dcaf18063e45a76ebeac39af85a1adc2818881ccce48c106288f5988365cca2b4b1d7f037322da46840f42bebdcbc7193838d426e101087d8cea03aaff743d573eb4f4e9a71a2c884390769a6503874125d194bee8d46a3a0d5e4fcf28ff8465887d8e9df771d70157e75df3642b331d2778ceb32ceba868640171ab7a5d22eede1ee44", - "26d87ec70b57691e3bb359633d3ddba17f029d62cdfe977f5fd42274d79b444a32494d1c01e9f72d03cce78c806df96e93ea78da3a054209924ed765edc4d570f66168dc25ee3114e4017e387440349c8f0a94804761c3055f88e4fda2a49b860b1486a9609095f6250f268b6a4d1aecc03a505632ebf0b9dc22d0755a736faf7ad7000858b5864b", - "3880f5cc2d08fa70ef44b1f263fcf534d062a298c1bd5ee2eee8c3265806c4ce50b004f3a1fc1fa5b024aaac7f528c023c8181f67c6e1c357425dc4d573bd46b93a542afa3a19bdb140a2ce666e1a01f5c4d2dcd681fa9f5839b797813c394738d5ee4971386c12c7c117d17c7bec324b760aa30cda9ab2aa850284ba6fa97946f710f02449d1883c6", - "3317d2f452105dd3f4a96f9257af8285a80be58066b50f6f54bd633749b49f6ab9d57d45652d2ae852a2f6940cd5ec3159dd7f333358b12f502325df38843508faf7e246352d201280babd90b14fbf7722641c3601d0e458474439973c611bb5502fd0eb3078f87124ca7e1a016fcb6cfeff65f6a565985aca7122cfa8c5a11da0cb47797c5132333179", - "f2c5c955d0224e784a46b9125f8fef8a5e1271e145eb08bbbd07ca8e1cfc848cef14fa3b36221ac62006403dbb7f7d77958ccc54a8566c837858b809f3e310ace8ca682515bc655d2a397cab238a663b464d511f02dc5d033dad4cb5e0e519e94a54b62a3896e460ec70e5716b5921bf8396aa86a60123e6287e34570bb01bdc602e113670bf498af2ff10", - "180e275205691a83630cf4b0c7b80e6df8fad6ef1c23ba8013d2f09aef7abade1827f23af230de90676240b4b3b0673f8afdea0327330055041741f65560d90348de696d34ca80dfe8afae582fe4879d4594b80e9408fb53e800e01ca58552b905c365e7f1416e51c080f517d6bbd30e64ae1535d59decdc76c6624d737868f49f2f719da39ba1344d59eab9", - "c517a84e4631a7f65ace170d1e5c2fdb259841535d88da323e68c0883e6af7b041cfe05908815a5a9d1b14fa712c2c16fadcf1ca54d3aa954d411240df331b2aebdfb65aced84d0b8aace56ec0aa7c13ec7d75ca883b6bcf6db74c9e98463c484a8262684f29910373430651f90ecffe18b072170e61ee58de20e2a6ff67b3ab00fccbb80af943f20b56b98107", - "d1a56a5ee990e02b84b5862fde62f69ec07567be2d7ccb769a461c4989d11fdda6c945d942fb8b2da795ed97e43a5b7dbdde7f8fd2ff7154544336d5c50fb7380341e660d4898c7fbc39b2b782f28defac6873523c7c1de8e52c65e4395c686ba483c35a220b0416d46357a063fa4c33fa9c52d5c207a1304ae141c791e62ba6a7374ed922b8dd94079b72b69302", - "4720b88d6bfb1ab43958e26827730d852d9ec30173ebd0fe0d273edcece2e788558984cd9306fe5978086a5cb6d37975755d2a3daeb16f99a8a11544b8247a8b7ed5587afc5bea1daf85dcea5703c5905cf56ae7cc76408ccabb8fcc25cacc5ff456db3f62fa559c45b9c71505eb5073df1f10fc4c9060843f0cd68bbb4e8edfb48d0fd81d9c21e53b28a2aae4f7ba", - "f4639b511db9e092823d47d2947efacbaae0e5b912dec3b284d2350b9262f3a51796a0cd9f8bc5a65879d6578ec24a060e293100c2e12ad82d5b2a0e9d22965858030e7cdf2ab3562bfa8ac084c6e8237aa22f54b94c4e92d69f22169ced6c85a293f5e16bfc326153bf629cdd6393675c6627cd949cd367eef02e0f54779f4d5210197698e4754a5fe490a3a7521c1c", - "3d9e7a860a718565e3670c29079ce80e381969fea91017cfd5952e0d8a4a79bb08e2cd1e26161f30ee03a24891d1bfa8c212861b51618d07429fb48000ff87ef09c6fca526567777e9c076d58a642d5c521b1caa5fb0fb3a4b8982dc14a444732b72b239b8f01fc8ba8ee86b3013b5d3e98a92b2aeaecd4879fca5d5e9e0bd880dbfffa6f96f94f3998812aac6a714f331", - "4d9bf551d7fd531e7482e2ec875c0651b0bcc6caa738f7497befd11e67ae0e036c9d7ae4301cc3c7906f0d0e1ed4738753f414f9b3cd9b8a71176e325c4c74ce020680ecbfb146889597f5b40487e93f974cd866817fb9fb24c7c7c16177e6e120bfe349e83aa82ba40e59e917565788658a2b254f25cf99bc65070b3794cea2259eb10e42bb54852cba3110baa773dcd70c", - "b91f65ab5bc059bfa5b43b6ebae243b1c46826f3da061338b5af02b2da76bb5ebad2b426de3c3134a633499c7c36a120369727cb48a0c6cbab0acecdda137057159aa117a5d687c4286868f561a272e0c18966b2fec3e55d75abea818ce2d339e26adc005c2658493fe06271ad0cc33fcb25065e6a2a286af45a518aee5e2532f81ec9256f93ff2d0d41c9b9a2efdb1a2af899", - "736f6e387acb9acbee026a6080f8a9eb8dbb5d7c54ac7053ce75dd184b2cb7b942e22a3497419ddb3a04cf9e4eb9340a1a6f9474c06ee1dcfc8513979fee1fc4768087617fd424f4d65f54782c787a1d2de6efc81534343e855f20b3f3589027a5436201eee747d45b9b8375e4294d72ab6a52e04dfbb2914db92ee58f134b026527ed52d4f794459e02a43a17b0d51ea69bd7f3", - "9242d3eb31d26d923b99d66954cfade94f25a18912e6356810b63b971ae74bb53bc58b3c01424208ea1e0b1499936daea27e63d904f9ed65fdf69de40780a3027b2e89d94bdf214f585472613ce328f628f4f0d56217dfb53db5f7a07f54c8d71db16e27de7cdb8d23988837b49b65c12f1771d979e8b192c9f4a16b8d9fba917bcf74ce5a82aac2075608ba6c2d485fa59864b9de", - "5da68704f4b592d41f08aca08f62d85e2e2466e5f3be010315d11d113db674c4b98764a509a2f5aacc7ae72c9deff2bcc42810b47f64d429b35745b9efff0b18c58653461e968aaa3c2c7fc455bc5771a8f10cd184be831040df767201ab8d32cb9a58c89afbebecb524502c9b940c1b838f8361bbcde90d272715017f67609ea39b20fac985332d82daaa023999e3f8bfa5f3758bb8", - "71ea2af9c8ac2e5ae44a176662882e01027ca3cdb41ec2c6785606a07d7231cd4a2bded7155c2feef3d44d8fd42afa73265cef826f6e03aa761c5c51d5b1f129ddc27503ff50d9c2d748322df4b13dd5cdc7d46381528ab22b79b0049011e4d2e57fe2735e0d58d8d56e92c75dbeac8c76c4239d7f3f24fb56697593b3e4afa6671d5bbc96c079a1c154fe20212ade67b05d49ceaa7a84", - "1d133170582fa4bff59a21953ebbc01bc202d43cd79c083d1f5c02fa15a43a0f519e36acb710bdabac880f04bc003800641c2487930de9c03c0e0deb347fa815efca0a38c6c5de694db698743bc955581f6a945deec4ae988ef7cdf40498b77796ddea3fae0ea844891ab751c7ee20917c5a4af53cd4ebd82170078f41ada2795e6eea17593fa90cbf5290a1095e299fc7f507f360f187cd", - "5ec4ac45d48fc15c72471d795066bdf8e99a483d5fdd599511b9cdc408de7c0616491b73924d0266da34a495331a935c4b8884f57d7ad8cce4cbe586875aa52482215ed39d7626cce55d50349c7767981c8bd6890f132a196184247343566fc972b86fe3c5369d6a6519e9f07942f0522b77ad01c751dcf7defe31e471a0ec00963765dd8518144a3b8c3c978ad108056516a25dbe3092e73c", - "0d5e74b78290c689f2b3cfea45fc9b6a84c822639cd438a7f05c07c374adced42cdc12d2a9233a4ffe80307efc1ac13cb04300e165f8d90dd01c0ea955e7657332c6e86ad6b43e78ba4c13c675aed83192d8427866fb6484e6a3071b2369a46fba9005f31232da7ffec7952f831aaaddf63e225263531c2cf387f8cc14fa856c8795137142c3a52ffa69b8e30ebc88ce3bbc227597bcc8dddd89", - "a0fe36f983259921dc2fa7d89002b3066241d63bfc2448caf7e10522a35562be0bfedc3dce49cfce2e614a04d4c64cfc0ab898873a7fc26928dc1927c009d12f6f9b7a278205d3d0057604f4ac746f8b9287c3bc6b929832bf253b6586192ac43fdd29ba585dbd9059aab9c6ff6000a7867c67fec1457b733f6b620881166b8fed92bc8d84f0426002e7be7fcd6ee0abf3755e2babfe5636ca0b37", - "1d29b6d8eca793bb801becf90b7d7de215b17618ec32340da4bac707cdbb58b951d5036ec02e105d83b5960e2a72002d19b7fa8e1128cc7c5049ed1f76b82a59eac6ed09e56eb73d9ade38a6739f0e07155afa6ec0d9f5cf13c4b30f5f9a465b162a9c3ba04b5a0b3363c2a63f13f2a3b57c590ec6aa7f64f4dcf7f1582d0ca157eb3b3e53b20e306b1f24e9bda87397d413f01b453ceffeca1fb1e7", - "6a2860c110cd0fc5a19bcaafcd30762ee10242d34739638e716bd89fd537ea4dc630e6f85d1bd88a25ad3892ca554c232c9830bd56980c9f08d378d28f7fa6fa7df4fcbf6ad98b1adfff3ec1f63310e50f920c99a5200b8e64c2c2ca249399a149942261f737d5d72da949e914c024d57c4b639cb89990fed2b38a37e5bcd24d17ca12dfcd36ce04691fd03c32f6ed5de2a2191ed7c826375ba81f78d0", - "7132aa291ddc9210c60dbe7eb3c19f9053f2dd74742cf57fdc5df98312adbf4710a73245de4a0c3b24e21ab8b466a77ae29d15500d5142555ef3088cbccbe685ed9119a10755148f0b9f0dbcf02b2b9bcadc8517c88346ea4e78285e9cbab122f824cc18faf53b742a87c008bb6aa47eed8e1c8709b8c2b9adb4cc4f07fb423e5830a8e503ab4f7945a2a02ab0a019b65d4fd71dc364d07bdc6e637990e3", - "3e664da330f2c6007bff0d5101d88288aaacd3c07913c09e871cce16e55a39fde1ce4db6b8379977c46cce08983ca686778afe0a77a41baf447854b9aa286c398c2b83c95a127b053101b6799c1638e5efd67273b2618df6ec0b96d8d040e8c1ee01a99b9b5c8fe63fea2f749e6c90d31f6fae4e1469ac09884c4fe1a8539acb313f42c941224a0e79c059e18affc2bcb6724975c436f7bf949ebdd8aef51c", - "7a6ea63a271eb49470f5ce77519ed61ae9b2f1be07a96855726bc3df1d0723af3a703fdfc2e739c9d31d25814daf661a23558b50982e66ee37ad880f5c8f11c8130fac8a5d0250583700d5a324894fae6d61993f6bf9327214f8674649f355b23fd634940b2c467973a839e659169c773119919f5b81ee171edb2e5f6940d7551f9e5a70625d9ea88711ad0ed8ab2da720ad358bef954456cb2d5636425717c2", - "c5106bbda114168c449172e49590c7eeb827fa4e1a2a7a87a3c1f721a9047d0c0a50fbf244731be1b7eb1a2ef30f5ae846a9f38f0df44f32af61b68dbdcd0226e741dfb6ef81a2503691af5e4b3171f48c59ba4ef91eba344b5b697f261df7bbbb734ca6e6daebaa4a179feb17002823281b8534d55a6531c59305f6e3fd3fa63b747bcf0deb654c392a02fe687a269effb1238f38bcaea6b208b221c45fe7fbe7", - "597716a5ebeebc4bf524c15518816f0b5dcda39cc833c3d66b6368ce39f3fd02ceba8d12072bfe6137c68d3acd50c849873150928b320b4fbc31c1456679ea1d0acaeeabf666d1f1bad3e6b9312c5cbdecf9b799d3e30b0316bed5f41245107b693366accc8b2bcef2a6be54209ffabc0bb6f93377abdcd57d1b25a89e046f16d8fd00f99d1c0cd247aafa72234386ae484510c084ee609f08aad32a005a0a5710cb", - "0771ffe789f4135704b6970b617bae41666bc9a6939d47bd04282e140d5a861c44cf05e0aa57190f5b02e298f1431265a365d29e3127d6fccd86ec0df600e26bcdda2d8f487d2e4b38fbb20f1667591f9b5730930788f2691b9ee1564829d1ada15fffc53e785e0c5e5dd11705a5a71e390ca66f4a592785be188fefe89b4bd085b2024b22a210cb7f4a71c2ad215f082ec63746c7367c22aedb5601f513d9f1ffc1f3", - "be6556c94313739c115895a7bad2b620c0708e24f0390daa55521c31d2c6782acf41156271238885c367a57c72b4fe999c160e804ad58d8e565edbce14a2dd90e443eb80626b3eab9d7ab75d6f8a062d7ca89b7af8eb292c98eaf87ad1dfd0db103d1bb6188bd7e7a63502153cf3ce23d43b60c5782602bac8ad92fb2324f5a79453898c5de18415639ecc5c7974d3077f76fc1df5b956723bb19a624d7ea3ec13ba3d86", - "4bc33729f14cd2f1dc2ff459abee8f6860dda1062845e4adab78b53c835d106bdfa35dd9e77219eaef403d4e80488ca6bd1c93dd76ef9d543fbb7c8904dccc5f71509a6214f73d0f4e467c3e038ea639b29e7fc442ee29f57117740576188ada15a739827c647a46b0271817ab235c023c30c90f2115e5c90cd8501e7b286962fc66ffc3fe7e8978746168314908a41998bd83a1eeffda9d714b864f4d490fdeb9c7a6edfa", - "ab12faea205b3d3a803cf6cb32b9698c32301a1e7f7c6c23a20174c95e98b7c3cfe93fffb3c970face8f5751312a261741141b948d777b8a2ea286fe69fc8ac84d34116a4674bb09a1a0b6af90a748e511749de4697908f4acb22be08e96ebc58ab1690acf73914286c198a2b57f1dd70ea8a52325d3045b8bdfe9a09792521526b7564a2a5fcd01e291f1f8894017ce7d3e8a5dba15332fb410fcfc8d62195a48a9e7c86fc4", - "7d421e59a567af70594757a49809a9c22e07fe14061090b9a041875bb77933deae36c823a9b47044fa0599187c75426b6b5ed94982ab1af7882d9e952eca399ee80a8903c4bc8ebe7a0fb035b6b26a2a013536e57fa9c94b16f8c2753c9dd79fb568f638966b06da81ce87cd77ac0793b7a36c45b8687c995bf4414d28289dbee977e77bf05d931b4feaa359a397ca41be529910077c8d498e0e8fb06e8e660cc6ebf07b77a02f", - "0c18ab727725d62fd3a2714b7185c09faca130438eff1675b38beca7f93a6962d7b98cb300ea33067a2035cdd694348784aa2eda2f16c731eca119a050d3b3ce7d5c0fd6c234354a1da98c0642451922f670984d035f8c6f35031d6188bbeb31a95e99e21b26f6eb5e2af3c7f8eea426357b3b5f83e0029f4c4732bca366c9aa625748297f039327c276cd8d9c9bf692a47af098aa50ca97b99961bef8bc2a7a802e0b8cfdb84319", - "92d5909d18a8b2b9971cd1627b461e98a74ba377186a6a9df5bd133635250b300abccb2254cacb775df6d99f7c7d0952653c28e6909b9f9a45adce691f7adc1afffcd9b06e49f775364cc2c62825b9c1a86089080e26b57e732aac98d80d009bfe50df01b95205aa07ed8ec5c873da3b92d00d53af825aa64b3c634c5ece40bff152c331222d3453fd92e0ca17cef19ecb96a6eed4961b627aca48b12fecd091754f770d52ba861546", - "802f22e4a388e874927fef24c797408254e03910bab5bf372320207f8067f2b1ea543917d4a27df89f5bf936ba12e04302bde23119533d0976beca9e20cc16b4dbf17a2ddc44b66aba76c61ad59d5e90de02a88327ead0a8b75463a1a68e307a6e2e53ecc1986274b9ee80bc9f3140671d5285bc5fb57b281042a8978a1175900c6073fd7bd740122956602c1aa773dd2896674d0a6beab24454b107f7c847acb31a0d332b4dfc5e3f2f", - "3844fe65db11c92fb90bf15e2e0cd216b5b5be91604baf3b84a0ca480e41ecfaca3709b32f8c6e8761406a635b88eec91e075c48799a16ca08f295d9766d74475c47f3f2a274eae8a6ee1d191a7f37ee413a4bf42cad52acd5564a651715ae42ac2cddd52f819c692ecdef52ecb763270322cdca7bd5aef71428fa73e844568b96b43c89bf1ed42a0abf209ffad0eeec286c6f141e8af073ba4adfbbdeda253752ae36c9957dfc905b4c49", - "329377f7bf3c8d74991a7d61b0cf39baff5d485d79751b0d5ad017d23bec570fb19810105bab79ab5acb102ab972165224d4ec888ec7de5148077fa9c1bb6820e0d91ae4e2591a21fec2f820606ce4bafc1e377f8dc3a5bd1a9e2772a57abccd0b757164d768872c91d02789545ab5b203f688d71dd08522a3fd2f5bcd7df507aebf1ca27ddff0a82afb7aa9c180008f49d1325adf97d047e77238fc75f56356de4e87d8c961575c9f6362c9", - "f7f269929b0d71ea8eef7120e55ccba691c582dd534692abef35c0fe9dec7dae973cd9702e5ad420d278fe0e653fdcb22fdcb63148109ec7e94f2d0750b28157dd1764376ae10fdb0a4aef3b304bd82793e0595f941226a2d72abbc929f53134dc495b0d65ced409914f94c2523f3dfbbdeeac84ae247ab5d1b9ea33dce1a808885a55be1f3683b46f4be73d9b62eec2585f690056858dfc427aabf591cd276724885bcd4c00b93bb51fb7484d", - "ac022309aa2c4d7fb628255b8b7fb4c3e3ae64b1cb65e0de711a6def1653d95d8088871cb8905fe8ae76423604988a8f77589f3f776dc1e4b30dbe9dd262b2187db02518a132d219bd1a06ebac13132b5164b6c420b37dd2ccee7d69b3b7fa12e54f0a53b853d490a68379ea1fa2d79762830ffb71bf86aab506b51f85c4b6a41b69325c7d0c7aa85b93b7144489d213e8f33dbb879fce22849865337b620b155cb2d2d36a68832889e30194d36d", - "d009c2b78a8f02e5e5dbb586ef71fc324b375092e15913ca1a5bfd22d516baadb96867bee3562e77c4a4852344a1a76c30728be5e22400b4cc41711f66754c246a520498d8c24f0205b9c873748dbeb67fe1ad099ad04cf89f4b517f0aa481136d9f6de2d727df01c6aa4099da59d4382b51e25fd47c33d9842c32b62331e50794bfe8b61b3ba9de1b8b704779c6d65edff3af00f121ab4a7ea384edabe47c6d0098a48991f387ca4444135ec59d46", - "c00bab36cce69899817d1425016d222d7303197ed3e3fdcac744705e7f178a1ac745968900f69299163e19b3161f3e0a4cc55aa2e4e71e0ee6ac427d1f4d14e063f68d303ddfbb18118335cfa7a6a90d99c38319ee76f7a884846a9e0b68030bf28e78bfbd56359b9368842814da42b04cb0e307d5d846dc22f049147bae31b9a956d17676a8cc348dafa3cabc2007a30e730e3894dddf9999fb8819086311f0703e141613ed6dcd7af8510e2dc435b0", - "c9789152a9fc29698d49ed95f09bd11b75f18a8c5615a73dbe54ae5e550027fd0ae6a8b60667040c1b12de3d1ee3f6bf061c78c951a3210effc912e19f482dd4de152063c588c44903bc11761706fd935afa040df085b08144d83d0dde32b46ab52f4fae98ac116c7ff11d7f553450c2e37b9c5f0b1dd9e0b8640a24cba6f2a5246c41f197f46e3dc8a29131c79bef3351c6e277a0a34442274d546ccd058891277473d668420f121750d19cd684267405", - "06a15a0731ce52557e368bcbaa11ef3399299e36fb9f2eda6e5726907c1d29c5c6fc581405ba48c7e2e522206a8f128d7c1c939d1132a00bd7d6366aa82724e968964eb2e373563f607dfa649590dcf5589114df69da5547fef8d1604cc4c6de1ed5783c8746918a4dd31168d6bc8784cd0c769206bd803d6ca8557b66748770402b075ef44b38157d4c0da7c6281725a2065d087b1f7b23455fa673bdeeba45b983311c44eabe9ef4b7bde3420ae9881863", - "d08aacef2d7a41aec09473bd8a44f628e15addb7b9e5b77a1e09c8ab4942f379a0bfcb324d580b774666f18ae78dd36710824ff12393f059068fe4b559c53662c2b0e6c69e23785c8f32554e837ec1714bee902e60737b639dd933af4f68cb9d7de77e1f3b28e5b122891afce62b79acd5b1ab4ba411662cc77d806449e69c5a45a143b742d98ac84a0826d68433b9b700ace6cd472ba2d58a90847f42ce9c43f38ffc017db4bf40450b2eee1f4594dc740c0f", - "6a6058b0a498b7ea76a93c646eb9b8629f0cba4a0c726420c5f67ba9b0412cade356abdf0a4fb94384bad32ce0d5dd9e23dcaae1d6f28ff8683616b30f1392890c67b3a2c04b360893b801f127e527e4da82e239f4c878da13f4a4f1c76db07190e77ec123995168102fb274434a2d1e12913b9b5cbab4aacaad2bd89d88b3ca2b8e60dacf7c22c9379097ff60880f552e320ca3b571994f52534470feee2b39e0dadb5cd88257a3e459a4cc6f12f17b8d54e1bb", - "adeced01fc5671531cbb45679f5ddd42b3a95151677b6125aaf6f5e8f82fbabaa5ecf7c3552c2458587224f0042870f178f5fca5465250e75d71352e652eeed23cdb7f915f5ebb44099b6db116ca1be45530ac8ed32b7f161d60ed4397ad3d7d649ae6bf75ca5bec891d8e595605be9764f3a03965e1fe0eaffbf212e3df4f0fa35e08ff9d0091e6d4ac4748edfe43b611085a6ffec163014655fdd839fd9e81b63b1fa8cae4ec335ec343289758e389a79ceedfae", - "d014592f3a83ba40af366f137c674724916c3cdd3f6cf9d4c5c7c8d6d51ebf26e315e2c12b3546be56fb52382904046ecbd2f5b883aa4ff473de6f0c26ab862c3fa34bf3d880cc1911ce39a4088c6617c179dc5faf68a2c488bbde12d67b50f73abcfab0e3b062e68c95363e11f5f1de8ec36ed01ea21442518089045df67d346135283ad5b3fff80cf57f20876849f6db9fa139728358415a90610f69ec720fc92d8234e3e122551e9df2c644c4a2c4e3734d07de8e", - "c0d0c37838873ba8757d6e41b409605043bc1635edcd731219587676d94217e9f0ab44b71de25000661ce7303b7015f45e6eaa7b7ebef92b8f4a34c902c908d2172185505fa33aca5a41be83079316cdfdd430fc2c45f505f85d867e6d516f7e1bf19c001d9f43018968aab65ec031b3801399231c83ec9e622dab5629922a6b424cab938c135ff7310501c2c02971bfd2f577e25904d1a618baf0859f77f4e8b1d0cde9544e95ec52ff710c0672fdb3d891feeea2b017", - "7022e7f00902219ba97baa0e940e8ac7727f58955aa068c29680fac4a16bcd812c03eeb5adbcfe867a7f7c6b5d89f4641adb9173b76a1a8438866f9b4f640ce2aedf5f1080c890bcf515b4be4e3e512352f1e5323c62ec46cb73f3d71be8235fee55a154763f7c3f9aeb61ffd28f4cd93d3310f608e2133586bf1ab3f102de96f64c68a4668de8acb2a76a7ce0cddddc8fa3df5e9d230823da16ed9ebb402d36e38e6e018795e5a71517ecab5f9ca472b9ced8ff69d2d195", - "acaf4baf3681ab865ab9abfae41697141ead9d5e98523c2e0e1eeb6373dd15405242a3393611e19b693cabaa4e45ac866cc66663a6e898dc73095a4132d43fb78ff7166724f06562fc6c546c78f2d5087467fcfb780478ec871ac38d9516c2f62bdb66c00218747e959b24f1f1795fafe39ee4109a1f84e3f82e96436a3f8e2c74ef1a665b0daaa459c7a80757b52c905e2fb4e30c4a3f882e87bce35d70e2925a1671205c28c89886a49e045e31434abaab4a7aed077ff22c", - "84cb6ec8a2da4f6c3b15edf77f9af9e44e13d67acc17b24bd4c7a33980f37050c0301ba3aa15ad92efe842cd3ebd3636cf945bb1f199fe0682037b9dacf86f162dadabfa625239c37f8b8db9901df0e618ff56fa62a57499f7ba83baebc085eaf3dda850835520344a67e09419368d81012168e5de5ea45158397af9a5c6a1657b26f319b66f816cd2c28996547d697e8df2bb163ccb9dda4d6691dffd102a13667ab9cde60ffbfb872187d9c425a7f67c1d9fffff9276ed0aeb", - "6a52c9bbbba454c14540b2be58230d78ecbeb391646a0c6fcce2f789086a78364b81ae85d5396d7cfa8b46bda41e3083ec5cf7b4c47dc601c8a697df52f557defca248506dbebab25657f5a561d09625b7f4b2f0119a12beeac087efc9d350a735c35d2431c1da7dda99befb17f41a3dc4da0f00bb95366be128538ce27763d81f832fe3c1d4efc07b5b08ad8dc9e65fb5e48546664e18cb2d3bb3fe1f56fa7aae718c5e3bbdeaf70e15023f6a25b72a2d177fcfd04211d40664fe", - "c3c4d3b31f1f5f9538923df3478c84fffaef411520a542da9a220ee4132eabb9d718b5076fb2f985485e8ba058330aed27ddfd3afa3db34aa60301088caec3d0053828c0c2bc87e2e61db5ea5a29f62fdad9c8b5fc5063ec4ee865e5b2e35fac0c7a835d5f57a1b1079833c25fc38fcb14311c54f8a3bd251bca19342d69e5785f9c2e43cf189d421c76c8e8db925d70fa0fae5ee3a28c4047c23a2b8a167ce53f35ced33bec822b88b06f41558c47d4fed1bfa3e21eb060df4d8ba1", - "8d55e92136992ba23856c1aea109766fc44772477efc932b3194af2265e433ed77d63b44d2a1cff2e8680eff120a430fe012f0f09c6201d546e13ad46fc4ce910eab27bb1569879abed2d9c37fae9f1267c2216ec5debcb20d4de58461a621e6ce8946899de81c0add44d35e27b7982a97f2a5e6314901caebe41dbba35f48bc9244ca6dca2bdde7306435892f287036df088633a070c2e385815ab3e2bfc1a47c05a5b9fe0e80dd6e38e4713a70c8f82bd32475eea8400c7bc67f59cf", - "5016284e20362610fa05ca9d789cad25f6d43263787e7e085476764ce4a8908ce99b262b375e9d106170b1bec1f473d5e777e0c1896533040e39c8c1465e07907ef5860e14e4d8310013e35f12090e0bfc687474b1f15f3dd2033a0edac5246102da4deec7e188c3517d84d9c2a0a4497a4c5f82a30f1ba009e45ee6eb3ab4368c720ea6feee428ffd2c4cc52debb8d634a64176572c72368f94a66689f23f8a01218f532117af5a8060d140e7ca435a92882fcb5630ebe14a4805f1dc83", - "05456ec59b8d41bbd736727976b96b38c43827f9e16169be673ff37870c2ecd5f0d1ea1a136be4cc7b047a02a4421d484fd2a12ece418e42ee391a13a0b1df5a0162b29ab70d3fe3e04ba6ab26b37d62b7cf05a5e2f033611bf970b8e1f30e198e483e740fa9618c1e8677e07b61296b94a9787a68fba622d7653b5568f4a8628025939b0f74389ea8fced6098c065bf2a869fd8e07d705eadb53006be2abb716a3114ceb0236d7e916f037cb954cf977720855d12be76d900ca124a2a66bb", - "eb6f60b83fcee77060ff346aaf6ec34d82a8af469947d3b5074cde8eb26566eb1fa039bcc707738df1e95869bd827c246e88436f0614d9834ead5392ef376105c4a9f370071cdeaaff6ca0f18b74c3a48d19a717253c49bd9009ccbfdd5728a08b7d112a2ed8dbafbbb46d7a75dc9a05e09bfde1a0a92d74a51887f9d123d7896e9f9d0057b660ed7d55454c069d3c5260411db4cdc67e7b74f680d7ac4b9dcc2f8baf72e15e6b3cafebcdf449a6436ed2c398b675f79c644747c57553bf7ea2", - "187a88e88514f6c4157c1ba40b442baae1ae563a6c989277443b12a219aa484cb9fa8adbb9a29d429f50155321b15664926317477079c7060dfdaa84c1d74bba78892c34e6f21ad35208d2ae622012401696bff5cd57b6485944b3db7b9071fa5f57fbfb1085d91bb9cff5808d662cdc6c8157249478262c44b7fbc397ed42a4977b202e817717bfccc9f0467294062313f7705251ed09573f16d23429361fada259dfb300369c4198f07341b38e84d02cdb74af5de6aab1fc2026208ea7c418c0", - "be31bc96606d0fab007e5caeded2f1c9f747c759777e9b6eef962bed49e45a1d4fc993e279d024915e600865ecb087b960584be18c41114d3c43f92169b9e0e1f85a0ebcd4e196376ccdc920e66103cd3b1c58407d0aafd0e003c4e341a1daddb9f4faba974362a32f35db83384b05ae8e3322d728893861afd8b1c940de5a17f691e763ce4969b6d94f67fb4a0235d100225bd8602f291388f0ca4a568748ad0d6040f1262eac2aede6cd27419bb78a394c1ffad72c262be8c3f9d9619d633e51d0", - "4d83d85ca838b4518588f2a90228a4dd18f14dd5b4c012d26298a97d848abbd825d221d02cceb6e8c701b4ad00e1dee4889b5c533e4bb60f1f41a4a61ee5478be2c1b1016c30345afd7a5253668260515e70751f22c8b4022d7fe4877d7bbce90b46531507dd3e89549e7fd58ea28f4cb23d33662bd003c1345ba94cc4b06867f778957901a8c441bee0f3b12e16463a51f7e50690356971dd73a686a49fda1eae46c9d54fba262811d698025d0ee053f1c58591c3bb3cbde69de0b31549ef5b69cf10", - "cdeb07d36dc5f9a1cd717a9e9cca37a2ce93caa298eee63571f7d6c5fde2a11c666cf53cf2dcb41ca2ea2319e7230ca68e38c647905928713a13982bf47fe33d7095ebd50b2df976208920a43eb2e29b942f32467403c45cea18bf44e0f6aeb155b48a8e5c471fec972a9d62f7ae093d2758f0aaec7ca50cb4725bfa219f1a3a46ad6bde7361f445f86b94d66b8ece080e56c510250693a5d0ea0ae87b4421860b853bcf0381eae4f1bf7c5c0472a93ad18407bc88475ab8560d344a921d3e86a02da397", - "a598fad52852c5d51ae3b10528fc1f722e21d44fbd42ae5acdf20e85a28532e646a223d27fd907bfd38eb8bb75175636892f8242877aab89e8c0824d368f3339ce7a82aa4e5af6db1f3b588a4d667a00f67bee37cfd2724dde06d2909fb9e58d892f4cfd2c4ca85acdf8256f5458b030a6bda151154ff2e6d7a8da90b54a2884c8a99fab5a4ac211ff23dc0975f4f592fd1b6b9dc7783bdcd2d4ca4e68d2902f2013e122cb62e2bff6b0a98ec55ba25837e21f1cfe67739b568d43e6413dab2bd1dc471e5a", - "17b68c74c9fe4926e8102070916a4e381b9fe25f5973c9bd4b04ce25749fc18931f37a65a356d3f5e5a1ef125d546f4f0ea797c15fb2efea6fbfcc5739c564693d47adeb12dcb3d98a2830719b13247792cb2491dca159a28138c6cff925aca42f4fdb02e73fbd508ec49b25c60703a7595a3e8f44b155b371d525e48e7e5dc84ac7b17c52bf5e526a67e7187234a2f19f57c548c70fc0b27183df73ffa53fa58b658034c896fa791ae9a7fd2620f5e46ce84c842a6e60e9324ae4db224ffc87d9617cb85ca2", - "b9e4267ea39e1de1fed0579f93bb351007c9f8fcdd811053fae33f09e2753d7428f04e1a9efcd45ea701a5d87a35b3afb2e6b65365dee6ead0bbb611b7797b212ac688653f542e604a39df277f12514ddfee3b4e27b98395c2cd97a203f1f1153c50327965770802ec2c9783edc428271762b275471e7ac65ac36523df28b0d7e6e6ccc7674268a132a63411fc82c0738dbb68af003b769a0bf9e6587b36476cb465350fee13f88ea355d47ffac7b0f964f4139db11b7642cb8d75fe1bc74d859b6d9e884f75ac", - "8ca704fe7208fe5f9c23110c0b3b4eee0ef632cae82bda68d8db2436ad409aa05cf159223586e1e6d8bdae9f316ea786809fbe7fe81ec61c61552d3a83cd6beaf652d1263862664df6aae321d0323440430f400f291c3efbe5d5c690b0cc6b0bf871b3933befb40bc870e2ee1ebb68025a2dcc11b68daadef6be29b5f21e440374301bde1e80dcfade4c9d681480e65ec494a6af48df232c3d51447b9d06be714949249c44c43cf73ed13ef0d533e770284e51369d94ae241a5fb2f163893071b2b4c118aeaf9eae", - "4fd8dd01012bb4df82bf42e0683f998e6f52dd9c5617bae33f867d6c0b69798cead8179346d70acc941abbbdd26e3229d5651361d2252c72ff22db2938d06ff6fc29a42fdf800ae967d06479bc7bbb8e71f40b1190a4b7189ffc9a7096cdb76d40aec424e1388e1eb7ef4ac3b34f3f089da8fda7d1927f5d775c0b2801d22dd1265c973158f640cec93edfed06dc80b20ef8c496b98289d54d46ccd205951cbb0f4e7daeb866b60bacb483411e4382b6f04d472843186bd0e31fbaa93e5c901ec028efafeb45fc551a", - "e9ee1b22b04b321a5fdd8301627011f583887d77560fb0f35552e207561f81e38ac58a0d0aeaf832d1ee72d913720d01f75574e9a321864fe95f4d0d8f0b8db97649a53e71e940aede5c40b4b9105daa42a6fb2811b61209247534cbaf830b07abe338d75d2f5f4eb1c3cf151e9edabe2c8d5f6fff08fac1495ef48160b100d30dcb0676700bcceb28723a29980ab0766a93abb8cb3d1963007db8458ed99b689d2a7c28c788743c80e8c1239b20982c81dadd0eed6740c65fbc4ef15c7b5569cb9fc997c6550a34b3b2", - "ec01e3a60964360f7f23ab0b22e021815765ad706f242265ebc19a2bb9e4eac94393952dcf61aae47682671a10f9165f0b20adf83a6706bfbdcf04c6faba6114653a35584267267873291c6fe7ff5f7695243143421509502c8875aafa9e9afe5be5ef2c851c7f35d69be5d3896000ccdbbfab5c238bb34d607cfe2d55d748880545b4aa7ca61137992925189025c62654b1f20d49c3ccd75aa73ce99cd7258dabedd6480a9f5185531fc0118beb68cc0a9cd182f6973287cf9252e12be5b619f15c25b65c71b7a316ebfd", - "db51a2f84704b78414093aa93708ec5e78573595c6e3a16c9e15744fa0f98ec78a1b3ed1e16f9717c01f6cab1bff0d56367ffc516c2e33261074935e0735ccf0d018744b4d28450f9a4db0dcf7ff504d3183aa967f76a507357948da9018fc38f150db53e2df6cea14466f03792f8bc11bdb5266dd6d508cde9e12ff04305c0295de29de19d491ad86e766774bb517e7e65befb1c5e2c267f013e235d8483e177214f89978b4cdc81aa7eff8b39f2825ad3a1b6ac1424e30edd49b067d770f16e74dd7a9c3af2ad74289a676", - "00e40f30ae3746edad0f5dd03d0e640933cf3d1694804c1e1ed6399ac36611d405196ee48f129344a8512feda16a354517871322bd5d9c6a1b592933eab531923efb393ffb23d9109cbe1075cebfa5fb917b40df028a621460ff6783c798792cb1d9635b5a6f84ec13918fa302924649b5c7fcb1f7007f0d2f06e9cfd7c27491e565a96c68a0c3644f92cd8f38857258c33801c5d537a83dfe583cba59d7eec7e394199c0a2660a62fabe3ed2099d57f315a6cd8de1a4ade29d977f15d65759cff433e5ac0c182aef3761163e1", - "3c5ea24d0d9b618294a263f062b2414a722be4eb10dfc346a6ec3b821d7396eba61cd6ef33618b04cd087a811f299d4606820227f16000d7c839062b96d3e3f59cd1a082448d13fc8f56b3fa7fb5f66d0350aa3b72dd7c165d590282f7da2e12cfe9e60e1796122bb8c2d40fdc2997af634b9c6b127a893dfb3467909378300db3da911be1d7b616bb8e0572433e65527e15d936500a2c60e9f9909dcf22ab5e4b6700f0238c205b4a813626fac3d945bab2637fb08203044a73d20c9a3fcf7c3fc4eb7807c3276dd5f73ce89597", - "9271aeeebfac46f4de85df78f1bfd36136aa8905e15835c9e1941176f71e3aa5b1b131843d40479735e23e182a2bd71f66f6149dccb7ed8c16469079dc8590bbf165374951785f4531f7e7361de62f936cfb23a2b5bdf186632e7042a0dd451fdc9b7208f923f3a5f250ae590ec348c63a16c3aacaf7379f53b5dd4152dcd40d23e683e2156e64c592ffc07e2cd6bbeebef4dd590b2f6b2bcbf08fcd111c079f5c4033adb6c17574f8756ecd87be27eff1d7c8e8d0324438d59ae171d5a17128fbcb5533d921bd044a2038a5046b33", - "4e3e533d5bcb15793d1b9d0468aaee801f32fdb486b11027183553a09ddbee8213924296f2815dc61577297459e834bf1c7a53f87d43782209e589b8295219ba7073a8fff18ad647fdb474fa39e1faa69911bf83438d5f64fe52f38ce6a991f25812c8f548de7bf2fdea7e9b4782beb4011d3567184c817521a2ba0ebad75b892f7f8e35d68b099827a1b08a84ec5e8125651d6f260295684d0ab1011a9209d2bdeb75128bf5364774d7df91e0746b7b08bda9185035f4f226e7d0a1946fcaa9c607a66b185d8546aac2800e85b74e67", - "b5d89fa2d94531093365d1259cc6fe8827fea48e6374c8b9a8c4d2209c280fa5c44958a1847222a692a59e6aa2696e6cdc8a543dd89b0ce03bc293b4e78d6ef48e1839694ccd5c65661143095c705b07e3ced84a0f5959114dd89deb956ab3fac8130eb4a878278205b801ae41a29e34146192308c4e759b374757b0c3b00319bce92a1b95a4d2ee179fd6714ff96155d26f693a5bc973f84ac8b3b91e3926276297532d98b46992a3f104c08100bf1671c43134bac280c617da711e90a0100137525375ebb12802a428885ae7fce6514a", - "40e3d8048fc10650cb8a7fc2e7113e26dec34f9ca2d5129cd10a8e8e44d113d61ee48c7d003e19fd307fc6debd70feb30243f298c510ccc4418355ce143066f067ad7c6de7288c3080e7ad46a23c8d34deb55a43e652fe90444ad3c57d3ec1e1c489d63ef915a24bc74a7925a0a7b1e1523f21ca8fee78df24e3d0a68d0013423db97c280799a0618229c0f2c167289a891e5c8d6661ab21285951c31710e3b5fe55f6347fe16d9b40507948a59252efeb616df83e5c098b07d0a7247cd371daff0e50491c582503fd89f79ba94d6af9ed76", - "1fa444de01dd3901e2b4684e3d7a799ffa02d85afd35fb30fe4c9d672837bee6dd8a3b8608b4bb5e589220ad5a854f46b46e41c6d57ad124a46beab4169ff69fee7e3838a6165e19dad8eb5d7bf53d4edd3cd2769daf219510a02fdd2afe0c0e1da3cd30fcd1aa88b68965586f07a25a1720fbd90a096ea30fc8e945e3637d7857c8a9c0ab4154ffb2000e57b5f9adfa4e4eaf8065bc3c2b2e75f495963325588785a6ce417dcddffd299873b15dcccca128d63cd4eeeadb64cda28099a9ad7c80d34844901f26b88b00b9aafeb2f90286d29d", - "fde0a0d9d813983bd1f55cf778a003a2023b34a555322ab280584537bc6bdd844d22a7d6066c18da83ec09f3d8d5a1aab4be0d5ce19b436052f6e259a4b49017a1f47f1fe2bf115d5bc8599fb216351c60dd6b1bedb2e6f4dcadf424b833501b6f099cbfad9e2290680fb69c25032b42a6274f7cb9b5c5950401354838a45f7cb77b95bf54718e2f3d3d9fb91eb2311903980277396398d9736d8e92fd838594ac8a537c6c529db5a8a4f89290e6ba6f20ac0e5ed6fef40901d0e0e8e3e502990811f9acaae555dd54eb1bcd96b513e2fe751bec", - "9f8e0caec87858599f5ab29bff86da78a841a918a023a111098687ecdf2747612d3f3809d9ca400b878bd4f92c43a1004f1c17c7f19a3cd1ce449bd2b23aff551623c37dd8c0be56bf3fd857b500c2b9f9ccea62481944090a3cf3b6ee81d9af8eeb60f65ef150f9fa4d3ed6ce4762d3d4f174ee8ccd460c25cafac0ea5ec8a6a4b2f9e8c0520cb7061155e532cb65f188b01e4b9086db951f504b060c296b326b3fc1c590498ecce594f828f4a10ea416675720ae505295d38a791bd0e93f428448a8f4c1fc0af53604a9e8255384d29ae5c334e2", - "33d1e683a4c97ee6bbaa5f9df1a88cb53b7f3c157b6045d70a56fda0ccbd3a1fa1f049cd564da072b53f415bf5fb843771c1d2551fd075d33377362b2f7c0645f9723123d11975991db8a2b518f02e2c7c30342a044754290bae2c77496d755e5981f12e6b0a0174280b958bf11ed628a9062775993ced04bf752ea8d165e3ac2177d7cd1b9371c44efa98f0b3e68602a839d384eec007979f46429dafb138cbc231ad928a9f65f7d66fac77416395e8f1debaaf76ec2e4e03e8674102cd26f614739f3ec9f949033df1fb97e87c2326d65aef94ed5f", - "180048f09d0b480887af7fd548a85abf605440c1ddde6afe4c30c30670233f7bf928f43b4681f59279ebbda5e8f8f2a1abefdee129e18ac60f9224e90b38b0aabd01308e0a27f41b6fb2ee07ee176ec9048c5fe33c3f7c791469c81f30e28170585b9f3e7e3c8c2e9d74370cb4518f13bf2dee048cbd98ffa32d85e43bcc64a626b40efb51ce712925fdd6fee006dc68b88004a81549d2121986dd1966084cd654a7c6686b3bae32afbd9625e09344e85cf9611ea08dfce835a2e5b3726e69ae8a76a97db60fcc539944ba4b1e8449e4d9802ae99fae86", - "13c0bc2f5eb887cd90eae426143764cf82b3545998c386007cca871890912217aa143ac4ed4ddb5a7495b704aa4de18419b8664b15bc26cfc6596a4d2ae408f98b47a566476d5802d594ba84c2f538def9d016661f6404bb2337a3932a24f6e30073a6c9c274b940c62c727242e24466084a3ea336365d71ea8fa6499c0ea8d59eea505f1126b99c795023c4963aa0d99323d0391e8701110edf551b2d3799e1063ca443f1add162156e445502ca1a052fe70c289838593b58839fc63de128a03e2bbf389e22ae0cf957fd03315ee407b096cc1cfd92dee6", - "6f1eb607d679efef065df08987a1174aab41bdac8aece7726dfa65805d6fff5b3d17a672d96b770dc32165f144f0f7324822a5c87563b7cd9e37a742ae83ef245d09006d91576f435a03476f509ea2936636232f66aa7f6cdf1ac187bbd1fcb8e20f8791866e60ed96c73374c12ac16795e999b891c64507d2dbd97e5fc29fac750ad27f2937cbcd29fdafccf27ab22453834d475f6186eaf975a36fad5c8bd61c21da554e1ded46c4c39765dcf5c8f5ccfb49b6a4dc562c919d0c7d8940ec536ab2448ec3c9a9c8b0e8fd4870cad9de2577c7b0c38563f355", - "dcdd993c94d3acbc555f464871a32c5da6f13b3d5bbc3e34429705e8ad2e76393fdd96a69a94acb652f5dc3c120d41187e9aa919669f727c4868013b0cb6acc165c1b7706c52248e15c3bf81eb6c147619467945c7c48fa14a73e7c3d5bec91706c567145342a026c9d97eff97ec672c5debb9df1a998083b0b0081d65c517b3e5634c95e347e781aa30ca1c8af815e2e494d844e847fdcb41622894a518dc36571123a40bfdbe8c4f4cff44d83c61dd9dcd24c464c53b395edb31efee9f3aa080e87cdc3d22d613ae84a53c9249c32c96f9a3bc4629bb126a70", - "49971f9823e63c3a72574d977953329e813b22a8387cd13f56d8ea77a5d1a8a20012632d1d8732bbcb9f756b9675aab5db927beacab7ca263e5718b8dfa7b2eed9a91bf5ed163b16139d45f7b8cc7e3f7bdda6202106f67dfb23b7c315ee3e17a09d466b1e6b13e7c7428184a979f5358667b4fa8bd40bcc8ea46058db44587a85377ac46bf155136c09ac58cb6c27f28e17028c91e7e8f74d5b500e56293b316974f02b9d9ea205d9b6ac4cfb74eb8eb0c944577fd2f41316368307beab3e327bf7dbaa0a4428836ec4e895dea635234abeaf113ceeadac33c7a3", - "c57a9cc958cee983599b04fe694f15fb470fcbc53e4bfcc00a27351b12d5d2434444253ad4184e87b81b738922ffd7ff1dc1e54f39c5518b49fb8fe50d63e3935f99e4bd125e8dc0ba8a17fd62de709339a43fabe15cf86d96a54010112170c340cfac4132182eed7301402bc7c8276089dec38488af145cb6222525894658f03501204b7a66aba0be1b557b28a2f652d66f7313ed825ecc4d8596c1be7420d4425b86a1a90a5b7f30d0f24e0d1aae0eb619ca457a71699e44be612a4011c597ee80b94d5507e429d7fc6af22579cd6ad642723b05ef169fade526fb", - "0568a672cd1ecbaa947045b712e2ac27995392fbef8f9488f79803cbee561c212287f080eca95adb5ba42739d78e3ba667f06045d87850d3a0499358649caa257ad29f1a9c511e7054db20554d15cbb55ff854afa45cae475c729cea72ede953522031865bc02b95589ed4d9841c552a8cc94904a93ed09ed77222f6c178195056be59bc4e96a815adf534e6b466fb47e262ff79c803c157a21b6e2269c2e0abeb494113cd868d8466e82d4b2f6a28b73645853d96bc9242515d803e33294848d3fe42fdff68da53c03491636beede47ff1399dd3d54a5e914d55d7adf", - "3f19f61a4cd085796731ac9f85a75a8bce77031932c31762d87d8b8d07b8bd19ff78d6b7d1bd1e87f3a4f41aad03b6c4d17a6cbc86be55f7c8b88ada047bb04f8d49f1c34bcf81cc0f3389ad01a758fc7eeb0072aa9ad1481992bfdde82e438e75590a4423832dfbe3756e2229ea873bc3606e6d72174cb2163bf40b5d49c81009dab85ecc03e311351bbf96e32c030a2b276a7698cb25bc2c967acb3213161a1fdde7d912cd6a804490f8056c47da1333f6e35c41e749c2c23919cb9af5eec5652e6e072b034fb1682e9aaa194a9c0bd456ea0b008d14dbce37967a7a8e", - "705f98f632d99d3651793825c38dc4deda56c59eac539da6a0159c83131cf8ab6f2ee0c3b74111fde351f7aa1a8c500a0cecab17c212d2c58ca09eae608c8eefc922b9902ef8d6832f799ba48c3c28aa702b3242107edeba01daafe424406a3822965056cfe8783455a671e93b1e2eae2321364f1871471c82124df33bc09e1b52882bd7e1c4c7d0b2f3dd4a28c2a002a43246768af0700f9659de99d62167be93177aabf19d678e79e9c726ac510d94e74873eda99620a3961930cd91937c88a06d8153d64fd60da7ca38cf26d1d4f04a0df273f52127c53fdc593f0f8df9", - "ea6f8e977c954657b45f25480ff42c36c7a10c77caa26eb1c907062e24fbca5aebc65cacca0de10abea8c78322f08672e13d8ac16996eca1aa17402eaea4c1cc6c800b22dc18cb8d620192d74bac02c07b5cfa61e513c7f28b7e29b9700e0e442720bf4c669d4995da19d19f841d9eb68cc74153592591e3bf059ef616b95305aa453b32fe99a91afb35bd482cf2b7aa42702837a53be3c38883d2963020e347556f841254ec6b85854485fe8c520b05f2ea67a9bf3981555c20991e2bacd4db5b418228b6002d8d41c025cb472bf5443aaa885974a408ea7f2e3f932c600deb", - "408190134ed06556811b1af808ab2d986aff152a28de2c41a2207c0ccc18125ac20f48384de89ea7c80cda1da14e60cc1599943646b4c0082bbcda2d9fa55a13e9df2934edf15eb4fd41f25fa3dd706ab6de522ed351b106321e494e7a27d5f7caf44ec6fadf1122d227eefc0f57aefc140d2c63d07dcbfd65790b1099745ed042cfd1548242076b98e616b76ff0d53db5179df8dd62c06a36a8b9e95a671e2a9b9dd3fb187a31ae5828d218ec5851913e0b52e2532bd4bf9e7b349f32de2b6d5d3cdf9f372d49617b6220c93c05962327e99a0480488443349f0fd54c1860f7c8", - "5f9e5c6f38573a85010a9d84d33f29c057003b2645e3ea6f72cbc7af95d197ce6a06b13fea81722853e6991791b8b15091cd066f5ed913592ed3d3af5370d39ba22beeb2a582a414b16824b77e194a094c2afdcc09aa73ce36f4943cca5ae32c5017dc398801dd92a47382d9327c9f6cffd38ca4167cd836f7855fc5ff048d8efba378cdde224905a0425e6b1de061fc951c5e624a5153b008ad41160a710b3ff2081748d5e02deb9f841f4fc6cf4a15153dd4fe874fd447482696283e79ee0e6bc8c1c0409baa5ab02c5209c319e3169b2476149c0c6e541c6197ca46e004eef533", - "218c6b3508aec69574f2b5039b30b942b72a8349d05f48ff945bbbe5c8957d5a6199492a6bf54bab821c9377e2edfa4c908384664d2c80112d5e805d66e0a551b941021be17dd20bd825bea9a3b6afb1b8c605805b3bda58750f03ea5c953a698494b425d8980c69f34d1c3f6b5866e8717031152a127215c256e08873c21b0f5cc85875d0f7c94601659150c04cd5fe5d381ba29983a2d94fcd3a65a94c53c7279cd000dddd4253d8cff8d7f6ace10247fe3bc30d63ba4bb54f557b3d22a3924369430d71ab37b701e9500bda70b5a643704858beed4726a889b6c9c91584194c68f1", - "dac26aa7273fc25d6e044c79fc2bfa46e59892a42bbca59a86826c91e76ab03e4bd9f7c0b5f08d1931d88b36ea77d94f7ba67cd4f1d3086e529427201119096ae066ae6f170940830ed7900de7bb9d66e09788287403a4ecc93c6da975d2fb08e918840a236c15f5d3a8f7375c2eeebbf6f01a6e7f29ca2b8d42df158414c320777433663c59fdcd1f39ca68e3473db721be7ce8c6dba5fddc024f94fedb286b0477581d451313ca8c737484daf60d67f9b2d56d4bcc271f7e9ae958c7f258efbc74d25753e0516f28282461941bf2dcc7dd8c7df6173b89760cefcac07190243ff863fb", - "c46e6512e6797cc7a54254a1b26b2de29aa83d6c4b1ea5a2786fbcec388270625b12635eae39e1fba013f8a65219421bca8b52a8ddfd431cda60299bdf160734d5a7450ec79620058522702174ae451b9bfa7c4a455fbbee3e1d048c7d4bac5131018228f137c8e130440c7059b4f15eaa34ce872a851a16ce86f982df78a00be4d564da2003a450ddee9ab43ea876b8b4b65c84f0b39265fd5456417afb5bc54997c986e66fc222f2123ba5e719c4d6b9a177b188277df384f1125821cf19d5248cef0be183ccdc84ac194506f740ed2188b2689ea4c9236a9e9e3a2fff85b6af4e9b49a3", - "1ccd4d278d67b65cf2564ecd4de1b55fe07adc80e1f735fe2f08ea53fd3977323689122c29c798957abaff6aba09bdcbf661d77f4dc8913ab1fe2bef38846166e3834785e7105d746484eff8c656af5d8c7854abc1c62b7fadb65521dc6f793d978bda9838eb3800417d32e8a24d8c8cb1d18a5de6ca79d9e1b0ff9aa25e6218fe944cf18666fecc1e31334b390260dbe0997539e1b02f6366b2aea4f4a21efe04f4b97568fcb39e59919d5ebac6543d5d0f48fc66b923c34aac377dc95c20329b837b6ed5e8d9a3d2089cd0d8f025658006ff41cbdaccca618822ca590ab155253f8bc1c7f5", - "9875209588395ee3c9fdd793fd48717cc84c8c3ea622b2ccc4a1be4448e6034b7810569855255031f10be5ffd714b05f9ce01972d712d40abf03d4d0ce175813a7a668f761324996093fc2aa5912f7fc2abdadd8775d2b4d9ad492216293381460ed8f6db3d641d1525f4242c348bbfe504c704f215dc461de51b5c75c1aae967936963848f16c673eca5e78dfd47eb19001d52d1bcf96c98956dad5ddf594a5da757e7ca35f2f69803b784e66ac5a58b75c228b8266ec592505e5d1ca87d81225738855f15bc0914677e81593fd409e77d159f8a908f67788de9eb06c5561547aada96c47c535", - "40c90e375e366f3756d89091eb3eed9fe0fbfc5638700af4617d358812bac53124a2205dd6756456787d49cd6a35e302479a0992288f47532e4ea7ab62fc5ad5adc690a5d9a446f7e035ad4641bd8dae83946aee3338ec984ccb5cc633e1409f2531eeffe05532a8b0062ba99454c9aeabf8ecb94db195af7032bfebc22912f49d39330add47ff8fa5720612d697f0b602738930e060a1bb214efc5e292224cf34e29deaea6b1b1ff847e94ecc997325ac38df61db45d82bf0e74a664d2fe085c20b04c39e90d6a170b68d2f1d373f00c731c524456ada73d659aaac9df3191a7a3865083343fc13", - "e8800d82e072210ca6d7fa2472028974780b76aad4bcb9ad362422dd05ae3232668251d164daa375a43b26a38cce28dbeb3dee1a4a579f70d0fe7febb29b5ece8aa836e050fb3d188c63aa9c3c0da6c717d86458a6096b5effceb964efdec7035960c09ccd10dea3c5f1c7f9f478d5887ebbe2e15c5ff85dbacbc444bb951c4eec7abecb89ed80187e409e2972ffe1a5f01562af109f2cf09471cf72cf83a3bb8f4e2ef38ed0e326b698296394e5b2718a5000c01425708e8ad0461e62462d8819c2377f13ab1be2c7c9f33dc06fe23cad27b87569f2ce2e56e4b2c60c7b1b3d370841d89ebdc1f192", - "796d6d1447d5b7e8c55cd8b2f8b7010db39f27565f907e3fc0e464ea2d4bb52b37f10e7c6dcfc59231b9cdee12c32aeb4adbc42b86e86eb6defb5b69e6ca75e1f4d0dae3e124e5a1b8b6697f7e10b0403f1f0a5ff848eef3752837a9ba17780f16a9a709188a8d5b89a2fa74adb2e651163b1c2b3d261e225c9158dcd9eb7ac3d6704cee290cdff6bcb3cb90cee030aa0d19d4693655c3c30ac6fc06d2ae37787c47126d57ed9a6bef5f8a6c56859aefc08755739a95aac57a4dd916a92ba9f3afbf969df8085949615033365c751a9a3e1a18cee98a69d22e64009bebf8307169b6c61de0617ecfafdf", - "4f9057183566153cf337b07c3f5556006de54c56b2a1e5326c07aaeabd1886ec6f1641358925db232b2f0dbf75229c796a7395b2f934c1f99090bec1123f3c841b1cb3c5b1ec42ed5408f2940f0c48a9470b852c46d6557853d459cecd2c32bbcd8ee21fa11e385eef0857cba4d8545a61b52a484cdd779db4739fbc7aa9860dcabe0488b98fa0b60c3f7d6153db279000a52ffb573dab37d2ab1896a90e5deb7ac6bbe56239085c325d83a917dc6e8a448425b718c2356b9f3066163555ec444f372e184e02c8c4c69b1c1c2ae2b51e45b98f73d933d18750968945ca85d6bbb22014b4c4015262e3c40d", - "79dcca7d8b81a61359e4aece21f3df7b99518ce70bd2f57a18bab5e7114af2add0a0cea7f319d69f231f060e0a539d9a23fb3e95451ce8c6340cfb09edf931df84203a39226dd9eb278f11b691ef612585b973daab373e65d11325898badf6732100371fd759960fa8fec373268421d28bffdb9b12a430b92fe4b07566ca0c89e616e49f8fc75ccd9cdc66db820d7c02e109aa5ed86b89770262918a518f90a2292f6b68d68ae03992e4259a17a23c84ec2a417f082b5abf3a26e44d2278ecb8ba9456965303a75f25394d1aaf5544590e74b14d8a4cc4050be2b0ebcfe4d2db6b12a02c68a3bcdda70301f3", - "848755dc31e25e9a42f9ec12d847d19f292c14c162c9aba49e972cb123b58b8e57bb263a923929833373858594ff52dbc298dbbc078599194e4c07b0e5fc1e10808bbacdb6e93c72b333685cf961f28eb0d5a395c63266b01f130d25db384b356e5da6d01042fc2359581b89c63b3bb2d1ce897fbc9e83fe85d9666cb60e6a8c657f70caad5387b8a045bf91095606802c8424ea8ac52ef29386dc46183378a5fcb2cb927428b8c070f1c42aafd3bc70ca25437807696a46873cfeb7b80ba2ebc3c4272443d445e46343a1465253a9eebd532a0d1d2c18264b91ff45159f245404ae9335f2af55c802772426b4", - "ecaa6e999ef355a0768730edb835db411829a3764f79d764bb5682af6d00f51b313e017b83fffe2e332cd4a3de0a81d6a52084d5748346a1f81eb9b183ff6d93d05edc00e938d001c90872dfe234e8dd085f639af168af4a07e18f1c56ca6c7c1addffc4a70eb4660666dda0321636c3f83479ad3b64e23d749620413a2ecdcc52ad4e6e63f2b817ce99c15b5d2da3792721d7158297cce65e0c04fe810d7e2434b969e4c7892b3840623e153576356e9a696fd9e7a801c25de621a7849da3f99158d3d09bf039f43c510c8ffb00fa3e9a3c12d2c8062dd25b8dabe53d8581e30427e81c3dfc2d455352487e1255", - "23a3fe80e3636313fdf922a1359514d9f31775e1adf24285e8001c04dbce866df055edf25b506e18953492a173ba5aa0c1ec758123406a97025ba9b6b7a97eb14734424d1a7841ec0eaeba0051d6e9734263bea1af9895a3b8c83d8c854da2ae7832bdd7c285b73f8113c3821cced38b3656b4e6369a9f8327cd368f04128f1d78b6b4260f55995277feffa15e34532cd0306c1f47354667c17018ee012a791af2dbbc7afc92c388008c601740cccbbe66f1eb06ea657e9d478066c2bd2093ab62cd94abadc002722f50968e8acf361658fc64f50685a5b1b004888b3b4f64a4ddb67bec7e4ac64c9ee8deeda896b9", - "758f3567cd992228386a1c01930f7c52a9dcce28fdc1aaa54b0fed97d9a54f1df805f31bac12d559e90a2063cd7df8311a148f6904f78c5440f75e49877c0c0855d59c7f7ee52837e6ef3e54a568a7b38a0d5b896e298c8e46a56d24d8cabda8aeff85a622a3e7c87483ba921f34156defd185f608e2241224286e38121a162c2ba7604f68484717196f6628861a948180e8f06c6cc1ec66d032cf8d16da039cd74277cde31e535bc1692a44046e16881c954af3cd91dc49b443a3680e4bc42a954a46ebd1368b1398edd7580f935514b15c7fbfa9b40048a35122283af731f5e460aa85b66e65f49a9d158699bd2870", - "fe511e86971cea2b6af91b2afa898d9b067fa71780790bb409189f5debe719f405e16acf7c4306a6e6ac5cd535290efe088943b9e6c5d25bfc508023c1b105d20d57252fee8cdbddb4d34a6ec2f72e8d55be55afcafd2e922ab8c31888bec4e816d04f0b2cd23df6e04720969c5152b3563c6da37e4608554cc7b8715bc10aba6a2e3b6fbcd35408df0dd73a9076bfad32b741fcdb0edfb563b3f753508b9b26f0a91673255f9bcda2b9a120f6bfa0632b6551ca517d846a747b66ebda1b2170891ece94c19ce8bf682cc94afdf0053fba4e4f0530935c07cdd6f879c999a8c4328ef6d3e0a37974a230ada83910604337", - "a6024f5b959698c0de45f4f29e1803f99dc8112989c536e5a1337e281bc856ff721e986de183d7b0ea9eb61166830ae5d6d6bc857dc833ff189b52889b8e2bd3f35b4937624d9b36dc5f19db44f0772508029784c7dac9568d28609058bc437e2f79f95b12307d8a8fb042d7fd6ee910a9e8df609ede3283f958ba918a9925a0b1d0f9f9f232062315f28a52cbd60e71c09d83e0f6600f508f0ae8ad7642c080ffc618fcd2314e26f67f1529342569f6df37017f7e3b2dac32ad88d56d175ab22205ee7e3ee94720d76933a21132e110fefbb0689a3adbaa4c685f43652136d09b3a359b5c671e38f11915cb5612db2ae294", - "af6de0e227bd78494acb559ddf34d8a7d55a03912384831be21c38376f39cda8a864aff7a48aed758f6bdf777779a669068a75ce82a06f6b3325c855ed83daf5513a078a61f7dc6c1622a633367e5f3a33e765c8ec5d8d54f48494006fdbf8922063e5340013e312871b7f8f8e5ea439c0d4cb78e2f19dd11f010729b692c65dd0d347f0ce53de9d849224666ea2f6487f1c6f953e8f9dbfd3d6de291c3e9d045e633cfd83c89d2f2327d0b2f31f72ac1604a3db1febc5f22cad08153278047210cc2894582c251a014c652e3951593e70e52a5d7451be8924b64f85c8247dab6268d24710b39fc1c07b4ac829fbda34ed79b5", - "d7314e8b1ff82100b8f5870da62b61c31ab37ace9e6a7b6f7d294571523783c1fdedcbc00dd487dd6f848c34aab493507d07071b5eb59d1a2346068c7f356755fbde3d2cab67514f8c3a12d6ff9f96a977a9ac9263491bd33122a904da5386b943d35a6ba383932df07f259b6b45f69e9b27b4ca124fb3ae143d709853eed86690bc2754d5f8865c355a44b5279d8eb31cdc00f7407fb5f5b34edc57fc7ace943565da2222dc80632ccf42f2f125ceb19714ea964c2e50603c9f8960c3f27c2ed0e18a559931c4352bd7422109a28c5e145003f55c9b7c664fdc985168868950396eaf6fefc7b73d815c1aca721d7c67da632925", - "2928b55c0e4d0f5cb4b60af59e9a702e3d616a8cf427c8bb03981fb8c29026d8f7d89161f36c11654f9a5e8ccb703595a58d671ecdc22c6a784abe363158682be4643002a7da5c9d268a30ea9a8d4cc24f562ab59f55c2b43af7dbcecc7e5ebe7494e82d74145a1e7d442125eb0431c5ea0939b27afa47f8ca97849f341f707660c7fbe49b7a0712fbcb6f7562ae2961425f27c7779c7534ecdeb8047ff3cb89a25159f3e1cefe42f9ef16426241f2c4d62c11d7ac43c4500dfcd184436bb4ef33260366f875230f26d81613c334dbda4736ba9d1d2966502914ec01bbe72d885606ec11da7a2cb01b29d35eebedbb0ecc73ed6c35", - "fd993f50e8a68c7b2c7f87511ce65b93c0aa94dcbdf2c9cca93816f0f3b2ab34c62c586fc507b4900a34cf9d0517e0fe10a89d154c5419c1f5e38de00e8834fe3dc1032abdeb10729a81655a69a12856a78ca6e12110580de879b086fd6608726541cfa9616326bdd36064bc0d1e5f9c93b41278bff6a13b2494b81e238c0c45aea1b07d855e8f3fe1478e373bd9d3957cf8a5e5b9003386793d994c7c575cff2322e2428cbbaa4f47560316ae3354a7478842ff7cc5dcbacb6e871e72b36f06d63a9aaeb9044cfb7974afdc238a5816f537dcf33ee40b4e1a5eb3cff2402b46d548264e133008d284f11b7e4e450bc3c5ff9f79b9c4", - "8df21892f5fc303b0de4adef1970186db6fe71bb3ea3094922e13afcfabf1d0be009f36d6f6310c5f9fda51f1a946507a055b645c296370440e5e83d8e906a2fb51f2b42de8856a81a4f28a73a8825c68ea08e5e366730bce8047011cb7d6d9be8c6f4211308fad21856284d5bc47d199988e0abf5badf8693ceeed0a2d98e8ae94b7775a42925edb1f697ffbd8e806af23145054a85e071819cca4cd48875290ca65e5ee72a9a54ff9f19c10ef4adaf8d04c9a9afcc73853fc128bbebc61f78702787c966ca6e1b1a0e4dab646acdfcd3c6bf3e5cfbec5ebe3e06c8abaa1de56e48421d87c46b5c78030afcafd91f27e7d7c85eb4872b", - "48ec6ec520f8e593d7b3f653eb15553de246723b81a6d0c3221aaa42a37420fba98a23796338dff5f845dce6d5a449be5ecc1887356619270461087e08d05fb60433a83d7bd00c002b09ea210b428965124b9b27d9105a71c826c1a2491cfd60e4cfa86c2da0c7100a8dc1c3f2f94b280d54e01e043acf0e966200d9fa8a41daf3b9382820786c75cadbb8841a1b2be5b6cbeb64878e4a231ae063a99b4e2308960ef0c8e2a16bb3545cc43bdf171493fb89a84f47e7973dc60cf75aeeca71e0a7ebe17d161d4fb9fe009941cc438f16a5bae6c99fcad08cac486eb2a48060b023d8730bf1d82fe60a2f036e6f52a5bff95f43bbe088933f", - "f4d84ed3e564c102600a795eaa9b1eaf4ad12f1a4deca1d042a0a2750ddf6201db03073d8bf553cb9dde48a1b0083827a609f7242b86584cc180964ae794b12ce55661e00e36a6ba4dbc389e6a5a85f1b45df9af7ead1b0a54db56e68639b9d438a91504e82c35d40c7bc7e048a53ac0b04accd0dadf4ac9884b0ca0e3cb5ba4336e3581be4c4760a553823ffa283a1120d4e145af56a59f2533903650f0b9e9ad9fe2e8a3c3c3dd03a1fcb709032c8835324839c735b0c051d0cbd8b5d867617c11023432e4bd275d3d0eb98a0b6cf58071a5b712922f2bc751ac7c2588c447444cde2f37a8ea5ec126425bf517e0d17c9e2999f52fee14b3", - "2ccea21bac9c2b70d3923309cbf2d7cb7abd1fcc8b8b002688870a80029c62397350c3c898194e5deea360bb963d26d485cb7963f8167586976ec0556950b2e86135f4a2800991ce8473bfd44a3c5e937a48b5e355ba5141bccf2131a83988d9d2a9e8e7635a956105b3512c05ef708139ced51d7a4e204c12d8a49a21e8dc6de2629a2fd092326885d9f218745fe09f6d91fb6afce250a30a63689534b6be1f26899ffa3767d835cf586aa47776700f94241bc999b1e3deefe188f37ff734f5f16ee6a00914323dc7b8a143c9137cdcc5cd08ae9566f04bb2941532674c97dff6ffa5ce3405ef8e5d27ec403114253dd6394c0167d72a0044c5", - "2b681c6398aee63bf862770341648bbcd31d7de7903c5903fe3d9469311320bb24d914f2af0cdca199c97214c7c679dc32a2800ba484a03c010ea6be3bb9f2c87e30a98b606050b8a3f297f12b8f92caaeceb3e844652115934874e0a1ab093a73d759b53f6a6c3096940dd22c2bb96ce6820a7b9c6d71a208de9892aa6a7209b0fff56a0cafea52b952cdd6f5752cff3309d448800b4e4c878aa595595b56b12b83fcd6ca89520c7da664e449d7b4438fc455888aad5de0fad9a06eed14afd3513b5ebbffe01775549b701181bd26370764f56eba52fdb24286ad1ac0f5418a7c429f7dfc7f3168437fa8eed7a2ed7c723a485e4c3ed14dea2e07", - "aadfd505a89f4aade2c3018258a7e039401b1fc6a7f3d87910dddbb880d372ec8a13c70d92245de5b8e5f9a285c33b99dc82fa2b22decee72b93a72211656ad7a52696c8e570f78be28c0e427a371dafde856e8d5ed24f83b0660b51e7fac05d93a8666dfde6def59af863f80f3e5f6801182c87422203df390dcb736b8f830052a8832eeeb0b4e27e732aaf793d166b5a3ec7745aeef3766937c2b75a276bddd145f6010c29d035e343e267cb2d828436876ec3a7ebe3b6347d4172f7a99d6821ce152e039e53deb33340b324c7f068ffb94b3cde35a8eaa12d15c3806a7ad0acec3e8c7078c1d32a28fd3eec9f32cb86e4c22166ff69e83785e851", - "1605b8cce529a9d6262fd4390d9e4ae5e14e0adc0ec89b028ef68dd0f373ea259aaa96f2967091dd0874c0105385e9e6da9ca68297c31afa44ef834535fb302ce5b4e49edacbbdf359fe1228a8172495b3e57014c27edd58b685110980056c50c398a64f4923f2d720b4df16d75cb36b4233660694182099c35028a972519c24764fc94e18e582b24deb3491535fc06b83837c7958522800e822201d694af0bd0aa3834e17d4b1ba36f470905ae5f8bbeeb6c4c8604d8af02baa347b07086d6989867ddd5e8e8ed7740c3469bfa2810519c55c6add1332c4c54ee9097961d6741cb12a09713a0d07645f784f42f5ad94b48b836b34263130b0483f15e3", - "ff9c6125b2f60bfd6c2427b279df070e430075096647599bdc68c531152c58e13858b82385d78c856092d6c74106e87ccf51ac7e673936332d9b223444eaa0e762ee258d8a733d3a515ec68ed73285e5ca183ae3278b4820b0ab2797feb1e7d8cc864df585dfb5ebe02a993325a9ad5e2d7d49d3132cf66013898351d044e0fe908ccdfeeebf651983601e3673a1f92d36510c0cc19b2e75856db8e4a41f92a51efa66d6cc22e414944c2c34a5a89ccde0be76f51410824e330d8e7c613194338c93732e8aea651fca18bcf1ac1824340c5553aff1e58d4ab8d7c8842b4712021e517cd6c140f6743c69c7bee05b10a8f24050a8caa4f96d1664909c5a06", - "6e85c2f8e1fdc3aaeb969da1258cb504bbf0070cd03d23b3fb5ee08feea5ee2e0ee1c71a5d0f4f701b351f4e4b4d74cb1e2ae6184814f77b62d2f08134b7236ebf6b67d8a6c9f01b4248b30667c555f5d8646dbfe291151b23c9c9857e33a4d5c847be29a5ee7b402e03bac02d1a4319acc0dd8f25e9c7a266f5e5c896cc11b5b238df96a0963ae806cb277abc515c298a3e61a3036b177acf87a56ca4478c4c6d0d468913de602ec891318bbaf52c97a77c35c5b7d164816cf24e4c4b0b5f45853882f716d61eb947a45ce2efa78f1c70a918512af1ad536cbe6148083385b34e207f5f690d7a954021e4b5f4258a385fd8a87809a481f34202af4caccb82", - "1e9b2c454e9de3a2d723d850331037dbf54133dbe27488ff757dd255833a27d8eb8a128ad12d0978b6884e25737086a704fb289aaaccf930d5b582ab4df1f55f0c429b6875edec3fe45464fa74164be056a55e243c4222c586bec5b18f39036aa903d98180f24f83d09a454dfa1e03a60e6a3ba4613e99c35f874d790174ee48a557f4f021ade4d1b278d7997ef094569b37b3db0505951e9ee8400adaea275c6db51b325ee730c69df97745b556ae41cd98741e28aa3a49544541eeb3da1b1e8fa4e8e9100d66dd0c7f5e2c271b1ecc077de79c462b9fe4c273543ecd82a5bea63c5acc01eca5fb780c7d7c8c9fe208ae8bd50cad1769693d92c6c8649d20d8", -} diff --git a/builder/crypto/blake2b/blake2x.go b/builder/crypto/blake2b/blake2x.go deleted file mode 100644 index 52c414db0..000000000 --- a/builder/crypto/blake2b/blake2x.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blake2b - -import ( - "encoding/binary" - "errors" - "io" -) - -// XOF defines the interface to hash functions that -// support arbitrary-length output. -type XOF interface { - // Write absorbs more data into the hash's state. It panics if called - // after Read. - io.Writer - - // Read reads more output from the hash. It returns io.EOF if the limit - // has been reached. - io.Reader - - // Clone returns a copy of the XOF in its current state. - Clone() XOF - - // Reset resets the XOF to its initial state. - Reset() -} - -// OutputLengthUnknown can be used as the size argument to NewXOF to indicate -// the length of the output is not known in advance. -const OutputLengthUnknown = 0 - -// magicUnknownOutputLength is a magic value for the output size that indicates -// an unknown number of output bytes. -const magicUnknownOutputLength = (1 << 32) - 1 - -// maxOutputLength is the absolute maximum number of bytes to produce when the -// number of output bytes is unknown. -const maxOutputLength = (1 << 32) * 64 - -// NewXOF creates a new variable-output-length hash. The hash either produce a -// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes -// (size == OutputLengthUnknown). In the latter case, an absolute limit of -// 256GiB applies. -// -// A non-nil key turns the hash into a MAC. The key must between -// zero and 32 bytes long. -func NewXOF(size uint32, key []byte) (XOF, error) { - if len(key) > Size { - return nil, errKeySize - } - if size == magicUnknownOutputLength { - // 2^32-1 indicates an unknown number of bytes and thus isn't a - // valid length. - return nil, errors.New("blake2b: XOF length too large") - } - if size == OutputLengthUnknown { - size = magicUnknownOutputLength - } - x := &xof{ - d: digest{ - size: Size, - keyLen: len(key), - }, - length: size, - } - copy(x.d.key[:], key) - x.Reset() - return x, nil -} - -type xof struct { - d digest - length uint32 - remaining uint64 - cfg, root, block [Size]byte - offset int - nodeOffset uint32 - readMode bool -} - -func (x *xof) Write(p []byte) (n int, err error) { - if x.readMode { - panic("blake2b: write to XOF after read") - } - return x.d.Write(p) -} - -func (x *xof) Clone() XOF { - clone := *x - return &clone -} - -func (x *xof) Reset() { - x.cfg[0] = byte(Size) - binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length - binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length - x.cfg[17] = byte(Size) // inner hash size - - x.d.Reset() - x.d.h[1] ^= uint64(x.length) << 32 - - x.remaining = uint64(x.length) - if x.remaining == magicUnknownOutputLength { - x.remaining = maxOutputLength - } - x.offset, x.nodeOffset = 0, 0 - x.readMode = false -} - -func (x *xof) Read(p []byte) (n int, err error) { - if !x.readMode { - x.d.finalize(&x.root) - x.readMode = true - } - - if x.remaining == 0 { - return 0, io.EOF - } - - n = len(p) - if uint64(n) > x.remaining { - n = int(x.remaining) - p = p[:n] - } - - if x.offset > 0 { - blockRemaining := Size - x.offset - if n < blockRemaining { - x.offset += copy(p, x.block[x.offset:]) - x.remaining -= uint64(n) - return - } - copy(p, x.block[x.offset:]) - p = p[blockRemaining:] - x.offset = 0 - x.remaining -= uint64(blockRemaining) - } - - for len(p) >= Size { - binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) - x.nodeOffset++ - - x.d.initConfig(&x.cfg) - x.d.Write(x.root[:]) - x.d.finalize(&x.block) - - copy(p, x.block[:]) - p = p[Size:] - x.remaining -= uint64(Size) - } - - if todo := len(p); todo > 0 { - if x.remaining < uint64(Size) { - x.cfg[0] = byte(x.remaining) - } - binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) - x.nodeOffset++ - - x.d.initConfig(&x.cfg) - x.d.Write(x.root[:]) - x.d.finalize(&x.block) - - x.offset = copy(p, x.block[:todo]) - x.remaining -= uint64(todo) - } - return -} - -func (d *digest) initConfig(cfg *[Size]byte) { - d.offset, d.c[0], d.c[1] = 0, 0, 0 - for i := range d.h { - d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) - } -} diff --git a/builder/crypto/blake2b/register.go b/builder/crypto/blake2b/register.go deleted file mode 100644 index 9d8633963..000000000 --- a/builder/crypto/blake2b/register.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.9 -// +build go1.9 - -package blake2b - -import ( - "crypto" - "hash" -) - -func init() { - newHash256 := func() hash.Hash { - h, _ := New256(nil) - return h - } - newHash384 := func() hash.Hash { - h, _ := New384(nil) - return h - } - - newHash512 := func() hash.Hash { - h, _ := New512(nil) - return h - } - - crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) - crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) - crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) -} diff --git a/builder/crypto/bls12381/arithmetic_decl.go b/builder/crypto/bls12381/arithmetic_decl.go deleted file mode 100644 index f6d232d65..000000000 --- a/builder/crypto/bls12381/arithmetic_decl.go +++ /dev/null @@ -1,84 +0,0 @@ -// 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 . - -//go:build (amd64 && blsasm) || (amd64 && blsadx) -// +build amd64,blsasm amd64,blsadx - -package bls12381 - -import ( - "golang.org/x/sys/cpu" -) - -func init() { - if !enableADX || !cpu.X86.HasADX || !cpu.X86.HasBMI2 { - mul = mulNoADX - } -} - -// Use ADX backend for default -var mul func(c, a, b *fe) = mulADX - -func square(c, a *fe) { - mul(c, a, a) -} - -func neg(c, a *fe) { - if a.isZero() { - c.set(a) - } else { - _neg(c, a) - } -} - -//go:noescape -func add(c, a, b *fe) - -//go:noescape -func addAssign(a, b *fe) - -//go:noescape -func ladd(c, a, b *fe) - -//go:noescape -func laddAssign(a, b *fe) - -//go:noescape -func double(c, a *fe) - -//go:noescape -func doubleAssign(a *fe) - -//go:noescape -func ldouble(c, a *fe) - -//go:noescape -func sub(c, a, b *fe) - -//go:noescape -func subAssign(a, b *fe) - -//go:noescape -func lsubAssign(a, b *fe) - -//go:noescape -func _neg(c, a *fe) - -//go:noescape -func mulNoADX(c, a, b *fe) - -//go:noescape -func mulADX(c, a, b *fe) diff --git a/builder/crypto/bls12381/arithmetic_fallback.go b/builder/crypto/bls12381/arithmetic_fallback.go deleted file mode 100644 index c09ae0d91..000000000 --- a/builder/crypto/bls12381/arithmetic_fallback.go +++ /dev/null @@ -1,567 +0,0 @@ -// Native go field arithmetic code is generated with 'goff' -// https://github.com/ConsenSys/goff -// Many function signature of field operations are renamed. - -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// field modulus q = -// -// 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 -// Code generated by goff DO NOT EDIT -// goff version: v0.1.0 - build: 790f1f56eac432441e043abff8819eacddd1d668 -// fe are assumed to be in Montgomery form in all methods - -// /!\ WARNING /!\ -// this code has not been audited and is provided as-is. In particular, -// there is no security guarantees such as constant time implementation -// or side-channel attack resistance -// /!\ WARNING /!\ - -// Package bls (generated by goff) contains field arithmetics operations - -//go:build !amd64 || (!blsasm && !blsadx) -// +build !amd64 !blsasm,!blsadx - -package bls12381 - -import ( - "math/bits" -) - -func add(z, x, y *fe) { - var carry uint64 - - z[0], carry = bits.Add64(x[0], y[0], 0) - z[1], carry = bits.Add64(x[1], y[1], carry) - z[2], carry = bits.Add64(x[2], y[2], carry) - z[3], carry = bits.Add64(x[3], y[3], carry) - z[4], carry = bits.Add64(x[4], y[4], carry) - z[5], _ = bits.Add64(x[5], y[5], carry) - - // if z > q --> z -= q - // note: this is NOT constant time - if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) { - var b uint64 - z[0], b = bits.Sub64(z[0], 13402431016077863595, 0) - z[1], b = bits.Sub64(z[1], 2210141511517208575, b) - z[2], b = bits.Sub64(z[2], 7435674573564081700, b) - z[3], b = bits.Sub64(z[3], 7239337960414712511, b) - z[4], b = bits.Sub64(z[4], 5412103778470702295, b) - z[5], _ = bits.Sub64(z[5], 1873798617647539866, b) - } -} - -func addAssign(x, y *fe) { - var carry uint64 - - x[0], carry = bits.Add64(x[0], y[0], 0) - x[1], carry = bits.Add64(x[1], y[1], carry) - x[2], carry = bits.Add64(x[2], y[2], carry) - x[3], carry = bits.Add64(x[3], y[3], carry) - x[4], carry = bits.Add64(x[4], y[4], carry) - x[5], _ = bits.Add64(x[5], y[5], carry) - - // if z > q --> z -= q - // note: this is NOT constant time - if !(x[5] < 1873798617647539866 || (x[5] == 1873798617647539866 && (x[4] < 5412103778470702295 || (x[4] == 5412103778470702295 && (x[3] < 7239337960414712511 || (x[3] == 7239337960414712511 && (x[2] < 7435674573564081700 || (x[2] == 7435674573564081700 && (x[1] < 2210141511517208575 || (x[1] == 2210141511517208575 && (x[0] < 13402431016077863595))))))))))) { - var b uint64 - x[0], b = bits.Sub64(x[0], 13402431016077863595, 0) - x[1], b = bits.Sub64(x[1], 2210141511517208575, b) - x[2], b = bits.Sub64(x[2], 7435674573564081700, b) - x[3], b = bits.Sub64(x[3], 7239337960414712511, b) - x[4], b = bits.Sub64(x[4], 5412103778470702295, b) - x[5], _ = bits.Sub64(x[5], 1873798617647539866, b) - } -} - -func ladd(z, x, y *fe) { - var carry uint64 - z[0], carry = bits.Add64(x[0], y[0], 0) - z[1], carry = bits.Add64(x[1], y[1], carry) - z[2], carry = bits.Add64(x[2], y[2], carry) - z[3], carry = bits.Add64(x[3], y[3], carry) - z[4], carry = bits.Add64(x[4], y[4], carry) - z[5], _ = bits.Add64(x[5], y[5], carry) -} - -func laddAssign(x, y *fe) { - var carry uint64 - x[0], carry = bits.Add64(x[0], y[0], 0) - x[1], carry = bits.Add64(x[1], y[1], carry) - x[2], carry = bits.Add64(x[2], y[2], carry) - x[3], carry = bits.Add64(x[3], y[3], carry) - x[4], carry = bits.Add64(x[4], y[4], carry) - x[5], _ = bits.Add64(x[5], y[5], carry) -} - -func double(z, x *fe) { - var carry uint64 - - z[0], carry = bits.Add64(x[0], x[0], 0) - z[1], carry = bits.Add64(x[1], x[1], carry) - z[2], carry = bits.Add64(x[2], x[2], carry) - z[3], carry = bits.Add64(x[3], x[3], carry) - z[4], carry = bits.Add64(x[4], x[4], carry) - z[5], _ = bits.Add64(x[5], x[5], carry) - - // if z > q --> z -= q - // note: this is NOT constant time - if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) { - var b uint64 - z[0], b = bits.Sub64(z[0], 13402431016077863595, 0) - z[1], b = bits.Sub64(z[1], 2210141511517208575, b) - z[2], b = bits.Sub64(z[2], 7435674573564081700, b) - z[3], b = bits.Sub64(z[3], 7239337960414712511, b) - z[4], b = bits.Sub64(z[4], 5412103778470702295, b) - z[5], _ = bits.Sub64(z[5], 1873798617647539866, b) - } -} - -func doubleAssign(z *fe) { - var carry uint64 - - z[0], carry = bits.Add64(z[0], z[0], 0) - z[1], carry = bits.Add64(z[1], z[1], carry) - z[2], carry = bits.Add64(z[2], z[2], carry) - z[3], carry = bits.Add64(z[3], z[3], carry) - z[4], carry = bits.Add64(z[4], z[4], carry) - z[5], _ = bits.Add64(z[5], z[5], carry) - - // if z > q --> z -= q - // note: this is NOT constant time - if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) { - var b uint64 - z[0], b = bits.Sub64(z[0], 13402431016077863595, 0) - z[1], b = bits.Sub64(z[1], 2210141511517208575, b) - z[2], b = bits.Sub64(z[2], 7435674573564081700, b) - z[3], b = bits.Sub64(z[3], 7239337960414712511, b) - z[4], b = bits.Sub64(z[4], 5412103778470702295, b) - z[5], _ = bits.Sub64(z[5], 1873798617647539866, b) - } -} - -func ldouble(z, x *fe) { - var carry uint64 - - z[0], carry = bits.Add64(x[0], x[0], 0) - z[1], carry = bits.Add64(x[1], x[1], carry) - z[2], carry = bits.Add64(x[2], x[2], carry) - z[3], carry = bits.Add64(x[3], x[3], carry) - z[4], carry = bits.Add64(x[4], x[4], carry) - z[5], _ = bits.Add64(x[5], x[5], carry) -} - -func sub(z, x, y *fe) { - var b uint64 - z[0], b = bits.Sub64(x[0], y[0], 0) - z[1], b = bits.Sub64(x[1], y[1], b) - z[2], b = bits.Sub64(x[2], y[2], b) - z[3], b = bits.Sub64(x[3], y[3], b) - z[4], b = bits.Sub64(x[4], y[4], b) - z[5], b = bits.Sub64(x[5], y[5], b) - if b != 0 { - var c uint64 - z[0], c = bits.Add64(z[0], 13402431016077863595, 0) - z[1], c = bits.Add64(z[1], 2210141511517208575, c) - z[2], c = bits.Add64(z[2], 7435674573564081700, c) - z[3], c = bits.Add64(z[3], 7239337960414712511, c) - z[4], c = bits.Add64(z[4], 5412103778470702295, c) - z[5], _ = bits.Add64(z[5], 1873798617647539866, c) - } -} - -func subAssign(z, x *fe) { - var b uint64 - z[0], b = bits.Sub64(z[0], x[0], 0) - z[1], b = bits.Sub64(z[1], x[1], b) - z[2], b = bits.Sub64(z[2], x[2], b) - z[3], b = bits.Sub64(z[3], x[3], b) - z[4], b = bits.Sub64(z[4], x[4], b) - z[5], b = bits.Sub64(z[5], x[5], b) - if b != 0 { - var c uint64 - z[0], c = bits.Add64(z[0], 13402431016077863595, 0) - z[1], c = bits.Add64(z[1], 2210141511517208575, c) - z[2], c = bits.Add64(z[2], 7435674573564081700, c) - z[3], c = bits.Add64(z[3], 7239337960414712511, c) - z[4], c = bits.Add64(z[4], 5412103778470702295, c) - z[5], _ = bits.Add64(z[5], 1873798617647539866, c) - } -} - -func lsubAssign(z, x *fe) { - var b uint64 - z[0], b = bits.Sub64(z[0], x[0], 0) - z[1], b = bits.Sub64(z[1], x[1], b) - z[2], b = bits.Sub64(z[2], x[2], b) - z[3], b = bits.Sub64(z[3], x[3], b) - z[4], b = bits.Sub64(z[4], x[4], b) - z[5], _ = bits.Sub64(z[5], x[5], b) -} - -func neg(z *fe, x *fe) { - if x.isZero() { - z.zero() - return - } - var borrow uint64 - z[0], borrow = bits.Sub64(13402431016077863595, x[0], 0) - z[1], borrow = bits.Sub64(2210141511517208575, x[1], borrow) - z[2], borrow = bits.Sub64(7435674573564081700, x[2], borrow) - z[3], borrow = bits.Sub64(7239337960414712511, x[3], borrow) - z[4], borrow = bits.Sub64(5412103778470702295, x[4], borrow) - z[5], _ = bits.Sub64(1873798617647539866, x[5], borrow) -} - -func mul(z, x, y *fe) { - var t [6]uint64 - var c [3]uint64 - { - // round 0 - v := x[0] - c[1], c[0] = bits.Mul64(v, y[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd1(v, y[1], c[1]) - c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd1(v, y[2], c[1]) - c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd1(v, y[3], c[1]) - c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd1(v, y[4], c[1]) - c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd1(v, y[5], c[1]) - t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - { - // round 1 - v := x[1] - c[1], c[0] = madd1(v, y[0], t[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd2(v, y[1], c[1], t[1]) - c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd2(v, y[2], c[1], t[2]) - c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd2(v, y[3], c[1], t[3]) - c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd2(v, y[4], c[1], t[4]) - c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd2(v, y[5], c[1], t[5]) - t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - { - // round 2 - v := x[2] - c[1], c[0] = madd1(v, y[0], t[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd2(v, y[1], c[1], t[1]) - c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd2(v, y[2], c[1], t[2]) - c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd2(v, y[3], c[1], t[3]) - c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd2(v, y[4], c[1], t[4]) - c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd2(v, y[5], c[1], t[5]) - t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - { - // round 3 - v := x[3] - c[1], c[0] = madd1(v, y[0], t[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd2(v, y[1], c[1], t[1]) - c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd2(v, y[2], c[1], t[2]) - c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd2(v, y[3], c[1], t[3]) - c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd2(v, y[4], c[1], t[4]) - c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd2(v, y[5], c[1], t[5]) - t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - { - // round 4 - v := x[4] - c[1], c[0] = madd1(v, y[0], t[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd2(v, y[1], c[1], t[1]) - c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd2(v, y[2], c[1], t[2]) - c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd2(v, y[3], c[1], t[3]) - c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd2(v, y[4], c[1], t[4]) - c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd2(v, y[5], c[1], t[5]) - t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - { - // round 5 - v := x[5] - c[1], c[0] = madd1(v, y[0], t[0]) - m := c[0] * 9940570264628428797 - c[2] = madd0(m, 13402431016077863595, c[0]) - c[1], c[0] = madd2(v, y[1], c[1], t[1]) - c[2], z[0] = madd2(m, 2210141511517208575, c[2], c[0]) - c[1], c[0] = madd2(v, y[2], c[1], t[2]) - c[2], z[1] = madd2(m, 7435674573564081700, c[2], c[0]) - c[1], c[0] = madd2(v, y[3], c[1], t[3]) - c[2], z[2] = madd2(m, 7239337960414712511, c[2], c[0]) - c[1], c[0] = madd2(v, y[4], c[1], t[4]) - c[2], z[3] = madd2(m, 5412103778470702295, c[2], c[0]) - c[1], c[0] = madd2(v, y[5], c[1], t[5]) - z[5], z[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1]) - } - - // if z > q --> z -= q - // note: this is NOT constant time - if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) { - var b uint64 - z[0], b = bits.Sub64(z[0], 13402431016077863595, 0) - z[1], b = bits.Sub64(z[1], 2210141511517208575, b) - z[2], b = bits.Sub64(z[2], 7435674573564081700, b) - z[3], b = bits.Sub64(z[3], 7239337960414712511, b) - z[4], b = bits.Sub64(z[4], 5412103778470702295, b) - z[5], _ = bits.Sub64(z[5], 1873798617647539866, b) - } -} - -func square(z, x *fe) { - - var p [6]uint64 - - var u, v uint64 - { - // round 0 - u, p[0] = bits.Mul64(x[0], x[0]) - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - var t uint64 - t, u, v = madd1sb(x[0], x[1], u) - C, p[0] = madd2(m, 2210141511517208575, v, C) - t, u, v = madd1s(x[0], x[2], t, u) - C, p[1] = madd2(m, 7435674573564081700, v, C) - t, u, v = madd1s(x[0], x[3], t, u) - C, p[2] = madd2(m, 7239337960414712511, v, C) - t, u, v = madd1s(x[0], x[4], t, u) - C, p[3] = madd2(m, 5412103778470702295, v, C) - _, u, v = madd1s(x[0], x[5], t, u) - p[5], p[4] = madd3(m, 1873798617647539866, v, C, u) - } - { - // round 1 - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - u, v = madd1(x[1], x[1], p[1]) - C, p[0] = madd2(m, 2210141511517208575, v, C) - var t uint64 - t, u, v = madd2sb(x[1], x[2], p[2], u) - C, p[1] = madd2(m, 7435674573564081700, v, C) - t, u, v = madd2s(x[1], x[3], p[3], t, u) - C, p[2] = madd2(m, 7239337960414712511, v, C) - t, u, v = madd2s(x[1], x[4], p[4], t, u) - C, p[3] = madd2(m, 5412103778470702295, v, C) - _, u, v = madd2s(x[1], x[5], p[5], t, u) - p[5], p[4] = madd3(m, 1873798617647539866, v, C, u) - } - { - // round 2 - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - C, p[0] = madd2(m, 2210141511517208575, p[1], C) - u, v = madd1(x[2], x[2], p[2]) - C, p[1] = madd2(m, 7435674573564081700, v, C) - var t uint64 - t, u, v = madd2sb(x[2], x[3], p[3], u) - C, p[2] = madd2(m, 7239337960414712511, v, C) - t, u, v = madd2s(x[2], x[4], p[4], t, u) - C, p[3] = madd2(m, 5412103778470702295, v, C) - _, u, v = madd2s(x[2], x[5], p[5], t, u) - p[5], p[4] = madd3(m, 1873798617647539866, v, C, u) - } - { - // round 3 - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - C, p[0] = madd2(m, 2210141511517208575, p[1], C) - C, p[1] = madd2(m, 7435674573564081700, p[2], C) - u, v = madd1(x[3], x[3], p[3]) - C, p[2] = madd2(m, 7239337960414712511, v, C) - var t uint64 - t, u, v = madd2sb(x[3], x[4], p[4], u) - C, p[3] = madd2(m, 5412103778470702295, v, C) - _, u, v = madd2s(x[3], x[5], p[5], t, u) - p[5], p[4] = madd3(m, 1873798617647539866, v, C, u) - } - { - // round 4 - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - C, p[0] = madd2(m, 2210141511517208575, p[1], C) - C, p[1] = madd2(m, 7435674573564081700, p[2], C) - C, p[2] = madd2(m, 7239337960414712511, p[3], C) - u, v = madd1(x[4], x[4], p[4]) - C, p[3] = madd2(m, 5412103778470702295, v, C) - _, u, v = madd2sb(x[4], x[5], p[5], u) - p[5], p[4] = madd3(m, 1873798617647539866, v, C, u) - } - { - // round 5 - m := p[0] * 9940570264628428797 - C := madd0(m, 13402431016077863595, p[0]) - C, z[0] = madd2(m, 2210141511517208575, p[1], C) - C, z[1] = madd2(m, 7435674573564081700, p[2], C) - C, z[2] = madd2(m, 7239337960414712511, p[3], C) - C, z[3] = madd2(m, 5412103778470702295, p[4], C) - u, v = madd1(x[5], x[5], p[5]) - z[5], z[4] = madd3(m, 1873798617647539866, v, C, u) - } - - // if z > q --> z -= q - // note: this is NOT constant time - if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) { - var b uint64 - z[0], b = bits.Sub64(z[0], 13402431016077863595, 0) - z[1], b = bits.Sub64(z[1], 2210141511517208575, b) - z[2], b = bits.Sub64(z[2], 7435674573564081700, b) - z[3], b = bits.Sub64(z[3], 7239337960414712511, b) - z[4], b = bits.Sub64(z[4], 5412103778470702295, b) - z[5], _ = bits.Sub64(z[5], 1873798617647539866, b) - } -} - -// arith.go -// Copyright 2020 ConsenSys AG -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by goff DO NOT EDIT - -func madd(a, b, t, u, v uint64) (uint64, uint64, uint64) { - var carry uint64 - hi, lo := bits.Mul64(a, b) - v, carry = bits.Add64(lo, v, 0) - u, carry = bits.Add64(hi, u, carry) - t, _ = bits.Add64(t, 0, carry) - return t, u, v -} - -// madd0 hi = a*b + c (discards lo bits) -func madd0(a, b, c uint64) (hi uint64) { - var carry, lo uint64 - hi, lo = bits.Mul64(a, b) - _, carry = bits.Add64(lo, c, 0) - hi, _ = bits.Add64(hi, 0, carry) - return -} - -// madd1 hi, lo = a*b + c -func madd1(a, b, c uint64) (hi uint64, lo uint64) { - var carry uint64 - hi, lo = bits.Mul64(a, b) - lo, carry = bits.Add64(lo, c, 0) - hi, _ = bits.Add64(hi, 0, carry) - return -} - -// madd2 hi, lo = a*b + c + d -func madd2(a, b, c, d uint64) (hi uint64, lo uint64) { - var carry uint64 - hi, lo = bits.Mul64(a, b) - c, carry = bits.Add64(c, d, 0) - hi, _ = bits.Add64(hi, 0, carry) - lo, carry = bits.Add64(lo, c, 0) - hi, _ = bits.Add64(hi, 0, carry) - return -} - -// madd2s superhi, hi, lo = 2*a*b + c + d + e -func madd2s(a, b, c, d, e uint64) (superhi, hi, lo uint64) { - var carry, sum uint64 - - hi, lo = bits.Mul64(a, b) - lo, carry = bits.Add64(lo, lo, 0) - hi, superhi = bits.Add64(hi, hi, carry) - - sum, carry = bits.Add64(c, e, 0) - hi, _ = bits.Add64(hi, 0, carry) - lo, carry = bits.Add64(lo, sum, 0) - hi, _ = bits.Add64(hi, 0, carry) - hi, _ = bits.Add64(hi, 0, d) - return -} - -func madd1s(a, b, d, e uint64) (superhi, hi, lo uint64) { - var carry uint64 - - hi, lo = bits.Mul64(a, b) - lo, carry = bits.Add64(lo, lo, 0) - hi, superhi = bits.Add64(hi, hi, carry) - lo, carry = bits.Add64(lo, e, 0) - hi, _ = bits.Add64(hi, 0, carry) - hi, _ = bits.Add64(hi, 0, d) - return -} - -func madd2sb(a, b, c, e uint64) (superhi, hi, lo uint64) { - var carry, sum uint64 - - hi, lo = bits.Mul64(a, b) - lo, carry = bits.Add64(lo, lo, 0) - hi, superhi = bits.Add64(hi, hi, carry) - - sum, carry = bits.Add64(c, e, 0) - hi, _ = bits.Add64(hi, 0, carry) - lo, carry = bits.Add64(lo, sum, 0) - hi, _ = bits.Add64(hi, 0, carry) - return -} - -func madd1sb(a, b, e uint64) (superhi, hi, lo uint64) { - var carry uint64 - - hi, lo = bits.Mul64(a, b) - lo, carry = bits.Add64(lo, lo, 0) - hi, superhi = bits.Add64(hi, hi, carry) - lo, carry = bits.Add64(lo, e, 0) - hi, _ = bits.Add64(hi, 0, carry) - return -} - -func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) { - var carry uint64 - hi, lo = bits.Mul64(a, b) - c, carry = bits.Add64(c, d, 0) - hi, _ = bits.Add64(hi, 0, carry) - lo, carry = bits.Add64(lo, c, 0) - hi, _ = bits.Add64(hi, e, carry) - return -} diff --git a/builder/crypto/bls12381/arithmetic_x86.s b/builder/crypto/bls12381/arithmetic_x86.s deleted file mode 100644 index 2cebbc46f..000000000 --- a/builder/crypto/bls12381/arithmetic_x86.s +++ /dev/null @@ -1,2150 +0,0 @@ -// +build amd64,blsasm amd64,blsadx - -#include "textflag.h" - -// addition w/ modular reduction -// a = (a + b) % p -TEXT ·addAssign(SB), NOSPLIT, $0-16 - // | - MOVQ a+0(FP), DI - MOVQ b+8(FP), SI - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - - // | - ADDQ (SI), R8 - ADCQ 8(SI), R9 - ADCQ 16(SI), R10 - ADCQ 24(SI), R11 - ADCQ 32(SI), R12 - ADCQ 40(SI), R13 - - // | - MOVQ R8, R14 - MOVQ R9, R15 - MOVQ R10, CX - MOVQ R11, DX - MOVQ R12, SI - MOVQ R13, BX - MOVQ $0xb9feffffffffaaab, AX - SUBQ AX, R14 - MOVQ $0x1eabfffeb153ffff, AX - SBBQ AX, R15 - MOVQ $0x6730d2a0f6b0f624, AX - SBBQ AX, CX - MOVQ $0x64774b84f38512bf, AX - SBBQ AX, DX - MOVQ $0x4b1ba7b6434bacd7, AX - SBBQ AX, SI - MOVQ $0x1a0111ea397fe69a, AX - SBBQ AX, BX - CMOVQCC R14, R8 - CMOVQCC R15, R9 - CMOVQCC CX, R10 - CMOVQCC DX, R11 - CMOVQCC SI, R12 - CMOVQCC BX, R13 - - // | - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET - -/* | end */ - - -// addition w/ modular reduction -// c = (a + b) % p -TEXT ·add(SB), NOSPLIT, $0-24 - // | - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - - // | - ADDQ (SI), R8 - ADCQ 8(SI), R9 - ADCQ 16(SI), R10 - ADCQ 24(SI), R11 - ADCQ 32(SI), R12 - ADCQ 40(SI), R13 - - // | - MOVQ R8, R14 - MOVQ R9, R15 - MOVQ R10, CX - MOVQ R11, DX - MOVQ R12, SI - MOVQ R13, BX - MOVQ $0xb9feffffffffaaab, DI - SUBQ DI, R14 - MOVQ $0x1eabfffeb153ffff, DI - SBBQ DI, R15 - MOVQ $0x6730d2a0f6b0f624, DI - SBBQ DI, CX - MOVQ $0x64774b84f38512bf, DI - SBBQ DI, DX - MOVQ $0x4b1ba7b6434bacd7, DI - SBBQ DI, SI - MOVQ $0x1a0111ea397fe69a, DI - SBBQ DI, BX - CMOVQCC R14, R8 - CMOVQCC R15, R9 - CMOVQCC CX, R10 - CMOVQCC DX, R11 - CMOVQCC SI, R12 - CMOVQCC BX, R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// addition w/o reduction check -// c = (a + b) -TEXT ·ladd(SB), NOSPLIT, $0-24 - // | - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - - // | - ADDQ (SI), R8 - ADCQ 8(SI), R9 - ADCQ 16(SI), R10 - ADCQ 24(SI), R11 - ADCQ 32(SI), R12 - ADCQ 40(SI), R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// addition w/o reduction check -// a = a + b -TEXT ·laddAssign(SB), NOSPLIT, $0-16 - // | - MOVQ a+0(FP), DI - MOVQ b+8(FP), SI - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - - // | - ADDQ (SI), R8 - ADCQ 8(SI), R9 - ADCQ 16(SI), R10 - ADCQ 24(SI), R11 - ADCQ 32(SI), R12 - ADCQ 40(SI), R13 - - // | - MOVQ a+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// subtraction w/ modular reduction -// c = (a - b) % p -TEXT ·sub(SB), NOSPLIT, $0-24 - // | - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - XORQ AX, AX - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - SUBQ (SI), R8 - SBBQ 8(SI), R9 - SBBQ 16(SI), R10 - SBBQ 24(SI), R11 - SBBQ 32(SI), R12 - SBBQ 40(SI), R13 - - // | - MOVQ $0xb9feffffffffaaab, R14 - MOVQ $0x1eabfffeb153ffff, R15 - MOVQ $0x6730d2a0f6b0f624, CX - MOVQ $0x64774b84f38512bf, DX - MOVQ $0x4b1ba7b6434bacd7, SI - MOVQ $0x1a0111ea397fe69a, BX - CMOVQCC AX, R14 - CMOVQCC AX, R15 - CMOVQCC AX, CX - CMOVQCC AX, DX - CMOVQCC AX, SI - CMOVQCC AX, BX - ADDQ R14, R8 - ADCQ R15, R9 - ADCQ CX, R10 - ADCQ DX, R11 - ADCQ SI, R12 - ADCQ BX, R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// subtraction w/ modular reduction -// a = (a - b) % p -TEXT ·subAssign(SB), NOSPLIT, $0-16 - // | - MOVQ a+0(FP), DI - MOVQ b+8(FP), SI - XORQ AX, AX - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - SUBQ (SI), R8 - SBBQ 8(SI), R9 - SBBQ 16(SI), R10 - SBBQ 24(SI), R11 - SBBQ 32(SI), R12 - SBBQ 40(SI), R13 - - // | - MOVQ $0xb9feffffffffaaab, R14 - MOVQ $0x1eabfffeb153ffff, R15 - MOVQ $0x6730d2a0f6b0f624, CX - MOVQ $0x64774b84f38512bf, DX - MOVQ $0x4b1ba7b6434bacd7, SI - MOVQ $0x1a0111ea397fe69a, BX - CMOVQCC AX, R14 - CMOVQCC AX, R15 - CMOVQCC AX, CX - CMOVQCC AX, DX - CMOVQCC AX, SI - CMOVQCC AX, BX - ADDQ R14, R8 - ADCQ R15, R9 - ADCQ CX, R10 - ADCQ DX, R11 - ADCQ SI, R12 - ADCQ BX, R13 - - // | - MOVQ a+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// subtraction w/o reduction check -// a = (a - b) -TEXT ·lsubAssign(SB), NOSPLIT, $0-16 - // | - MOVQ a+0(FP), DI - MOVQ b+8(FP), SI - - // | - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - SUBQ (SI), R8 - SBBQ 8(SI), R9 - SBBQ 16(SI), R10 - SBBQ 24(SI), R11 - SBBQ 32(SI), R12 - SBBQ 40(SI), R13 - - // | - MOVQ a+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - -// doubling w/ reduction -// c = (2 * a) % p -TEXT ·double(SB), NOSPLIT, $0-16 - // | - MOVQ a+8(FP), DI - - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - ADDQ R8, R8 - ADCQ R9, R9 - ADCQ R10, R10 - ADCQ R11, R11 - ADCQ R12, R12 - ADCQ R13, R13 - - // | - MOVQ R8, R14 - MOVQ R9, R15 - MOVQ R10, CX - MOVQ R11, DX - MOVQ R12, SI - MOVQ R13, BX - MOVQ $0xb9feffffffffaaab, DI - SUBQ DI, R14 - MOVQ $0x1eabfffeb153ffff, DI - SBBQ DI, R15 - MOVQ $0x6730d2a0f6b0f624, DI - SBBQ DI, CX - MOVQ $0x64774b84f38512bf, DI - SBBQ DI, DX - MOVQ $0x4b1ba7b6434bacd7, DI - SBBQ DI, SI - MOVQ $0x1a0111ea397fe69a, DI - SBBQ DI, BX - CMOVQCC R14, R8 - CMOVQCC R15, R9 - CMOVQCC CX, R10 - CMOVQCC DX, R11 - CMOVQCC SI, R12 - CMOVQCC BX, R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// doubling w/ reduction -// a = (2 * a) % p -TEXT ·doubleAssign(SB), NOSPLIT, $0-8 - // | - MOVQ a+0(FP), DI - - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - ADDQ R8, R8 - ADCQ R9, R9 - ADCQ R10, R10 - ADCQ R11, R11 - ADCQ R12, R12 - ADCQ R13, R13 - - // | - MOVQ R8, R14 - MOVQ R9, R15 - MOVQ R10, CX - MOVQ R11, DX - MOVQ R12, SI - MOVQ R13, BX - MOVQ $0xb9feffffffffaaab, AX - SUBQ AX, R14 - MOVQ $0x1eabfffeb153ffff, AX - SBBQ AX, R15 - MOVQ $0x6730d2a0f6b0f624, AX - SBBQ AX, CX - MOVQ $0x64774b84f38512bf, AX - SBBQ AX, DX - MOVQ $0x4b1ba7b6434bacd7, AX - SBBQ AX, SI - MOVQ $0x1a0111ea397fe69a, AX - SBBQ AX, BX - CMOVQCC R14, R8 - CMOVQCC R15, R9 - CMOVQCC CX, R10 - CMOVQCC DX, R11 - CMOVQCC SI, R12 - CMOVQCC BX, R13 - - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// doubling w/o reduction -// c = 2 * a -TEXT ·ldouble(SB), NOSPLIT, $0-16 - // | - MOVQ a+8(FP), DI - - MOVQ (DI), R8 - MOVQ 8(DI), R9 - MOVQ 16(DI), R10 - MOVQ 24(DI), R11 - MOVQ 32(DI), R12 - MOVQ 40(DI), R13 - - // | - ADDQ R8, R8 - ADCQ R9, R9 - ADCQ R10, R10 - ADCQ R11, R11 - ADCQ R12, R12 - ADCQ R13, R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - - RET -/* | end */ - - -TEXT ·_neg(SB), NOSPLIT, $0-16 - // | - MOVQ a+8(FP), DI - - // | - MOVQ $0xb9feffffffffaaab, R8 - MOVQ $0x1eabfffeb153ffff, R9 - MOVQ $0x6730d2a0f6b0f624, R10 - MOVQ $0x64774b84f38512bf, R11 - MOVQ $0x4b1ba7b6434bacd7, R12 - MOVQ $0x1a0111ea397fe69a, R13 - SUBQ (DI), R8 - SBBQ 8(DI), R9 - SBBQ 16(DI), R10 - SBBQ 24(DI), R11 - SBBQ 32(DI), R12 - SBBQ 40(DI), R13 - - // | - MOVQ c+0(FP), DI - MOVQ R8, (DI) - MOVQ R9, 8(DI) - MOVQ R10, 16(DI) - MOVQ R11, 24(DI) - MOVQ R12, 32(DI) - MOVQ R13, 40(DI) - RET -/* | end */ - - -// multiplication without using MULX/ADX -// c = a * b % p -TEXT ·mulNoADX(SB), NOSPLIT, $24-24 - // | - -/* inputs */ - - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - MOVQ $0x00, R9 - MOVQ $0x00, R10 - MOVQ $0x00, R11 - MOVQ $0x00, R12 - MOVQ $0x00, R13 - MOVQ $0x00, R14 - MOVQ $0x00, R15 - - // | - -/* i0 */ - - // | a0 @ CX - MOVQ (DI), CX - - // | a0 * b0 - MOVQ (SI), AX - MULQ CX - MOVQ AX, (SP) - MOVQ DX, R8 - - // | a0 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R8 - ADCQ DX, R9 - - // | a0 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R9 - ADCQ DX, R10 - - // | a0 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R10 - ADCQ DX, R11 - - // | a0 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R11 - ADCQ DX, R12 - - // | a0 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - - // | - -/* i1 */ - - // | a1 @ CX - MOVQ 8(DI), CX - MOVQ $0x00, BX - - // | a1 * b0 - MOVQ (SI), AX - MULQ CX - ADDQ AX, R8 - ADCQ DX, R9 - ADCQ $0x00, R10 - ADCQ $0x00, BX - MOVQ R8, 8(SP) - MOVQ $0x00, R8 - - // | a1 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R9 - ADCQ DX, R10 - ADCQ BX, R11 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a1 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R10 - ADCQ DX, R11 - ADCQ BX, R12 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a1 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R11 - ADCQ DX, R12 - ADCQ BX, R13 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a1 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - ADCQ BX, R14 - - // | a1 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R13 - ADCQ DX, R14 - - // | - -/* i2 */ - - // | a2 @ CX - MOVQ 16(DI), CX - MOVQ $0x00, BX - - // | a2 * b0 - MOVQ (SI), AX - MULQ CX - ADDQ AX, R9 - ADCQ DX, R10 - ADCQ $0x00, R11 - ADCQ $0x00, BX - MOVQ R9, 16(SP) - MOVQ $0x00, R9 - - // | a2 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R10 - ADCQ DX, R11 - ADCQ BX, R12 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a2 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R11 - ADCQ DX, R12 - ADCQ BX, R13 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a2 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - ADCQ BX, R14 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a2 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R13 - ADCQ DX, R14 - ADCQ BX, R15 - - // | a2 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R14 - ADCQ DX, R15 - - // | - -/* i3 */ - - // | a3 @ CX - MOVQ 24(DI), CX - MOVQ $0x00, BX - - // | a3 * b0 - MOVQ (SI), AX - MULQ CX - ADDQ AX, R10 - ADCQ DX, R11 - ADCQ $0x00, R12 - ADCQ $0x00, BX - - // | a3 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R11 - ADCQ DX, R12 - ADCQ BX, R13 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a3 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - ADCQ BX, R14 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a3 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R13 - ADCQ DX, R14 - ADCQ BX, R15 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a3 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R14 - ADCQ DX, R15 - ADCQ BX, R8 - - // | a3 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R15 - ADCQ DX, R8 - - // | - -/* i4 */ - - // | a4 @ CX - MOVQ 32(DI), CX - MOVQ $0x00, BX - - // | a4 * b0 - MOVQ (SI), AX - MULQ CX - ADDQ AX, R11 - ADCQ DX, R12 - ADCQ $0x00, R13 - ADCQ $0x00, BX - - // | a4 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - ADCQ BX, R14 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a4 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R13 - ADCQ DX, R14 - ADCQ BX, R15 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a4 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R14 - ADCQ DX, R15 - ADCQ BX, R8 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a4 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R15 - ADCQ DX, R8 - ADCQ BX, R9 - - // | a4 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R8 - ADCQ DX, R9 - - // | - -/* i5 */ - - // | a5 @ CX - MOVQ 40(DI), CX - MOVQ $0x00, BX - - // | a5 * b0 - MOVQ (SI), AX - MULQ CX - ADDQ AX, R12 - ADCQ DX, R13 - ADCQ $0x00, R14 - ADCQ $0x00, BX - - // | a5 * b1 - MOVQ 8(SI), AX - MULQ CX - ADDQ AX, R13 - ADCQ DX, R14 - ADCQ BX, R15 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a5 * b2 - MOVQ 16(SI), AX - MULQ CX - ADDQ AX, R14 - ADCQ DX, R15 - ADCQ BX, R8 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a5 * b3 - MOVQ 24(SI), AX - MULQ CX - ADDQ AX, R15 - ADCQ DX, R8 - ADCQ BX, R9 - MOVQ $0x00, BX - ADCQ $0x00, BX - - // | a5 * b4 - MOVQ 32(SI), AX - MULQ CX - ADDQ AX, R8 - ADCQ DX, R9 - ADCQ $0x00, BX - - // | a5 * b5 - MOVQ 40(SI), AX - MULQ CX - ADDQ AX, R9 - ADCQ DX, BX - - // | - -/* */ - - // | - // | W - // | 0 (SP) | 1 8(SP) | 2 16(SP) | 3 R10 | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 R9 | 11 BX - - - MOVQ (SP), CX - MOVQ 8(SP), DI - MOVQ 16(SP), SI - MOVQ BX, (SP) - MOVQ R9, 8(SP) - - // | - -/* montgomery reduction */ - - // | - -/* i0 */ - - // | - // | W - // | 0 CX | 1 DI | 2 SI | 3 R10 | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP) - - - // | | u0 = w0 * inp - MOVQ CX, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w0 @ CX - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, CX - ADCQ DX, BX - - // | j1 - - // | w1 @ DI - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, DI - ADCQ $0x00, DX - ADDQ BX, DI - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w2 @ SI - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, SI - ADCQ $0x00, DX - ADDQ BX, SI - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w3 @ R10 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R10 - ADCQ $0x00, DX - ADDQ BX, R10 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w4 @ R11 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R11 - ADCQ $0x00, DX - ADDQ BX, R11 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w5 @ R12 - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ $0x00, DX - ADDQ BX, R12 - - // | w6 @ R13 - ADCQ DX, R13 - ADCQ $0x00, CX - - // | - -/* i1 */ - - // | - // | W - // | 0 - | 1 DI | 2 SI | 3 R10 | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP) - - - // | | u1 = w1 * inp - MOVQ DI, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w1 @ DI - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, DI - ADCQ DX, BX - - // | j1 - - // | w2 @ SI - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, SI - ADCQ $0x00, DX - ADDQ BX, SI - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w3 @ R10 - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, R10 - ADCQ $0x00, DX - ADDQ BX, R10 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w4 @ R11 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R11 - ADCQ $0x00, DX - ADDQ BX, R11 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w5 @ R12 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ $0x00, DX - ADDQ BX, R12 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w6 @ R13 - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, R13 - ADCQ DX, CX - ADDQ BX, R13 - - // | w7 @ R14 - ADCQ CX, R14 - MOVQ $0x00, CX - ADCQ $0x00, CX - - // | - -/* i2 */ - - // | - // | W - // | 0 - | 1 - | 2 SI | 3 R10 | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP) - - - // | | u2 = w2 * inp - MOVQ SI, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w2 @ SI - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, SI - ADCQ DX, BX - - // | j1 - - // | w3 @ R10 - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, R10 - ADCQ $0x00, DX - ADDQ BX, R10 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w4 @ R11 - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, R11 - ADCQ $0x00, DX - ADDQ BX, R11 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w5 @ R12 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ $0x00, DX - ADDQ BX, R12 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w6 @ R13 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R13 - ADCQ $0x00, DX - ADDQ BX, R13 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w7 @ R14 - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, R14 - ADCQ DX, CX - ADDQ BX, R14 - - // | w8 @ R15 - ADCQ CX, R15 - MOVQ $0x00, CX - ADCQ $0x00, CX - - // | - -/* i3 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 R10 | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP) - - - // | | u3 = w3 * inp - MOVQ R10, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w3 @ R10 - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, R10 - ADCQ DX, BX - - // | j1 - - // | w4 @ R11 - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, R11 - ADCQ $0x00, DX - ADDQ BX, R11 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w5 @ R12 - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ $0x00, DX - ADDQ BX, R12 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w6 @ R13 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R13 - ADCQ $0x00, DX - ADDQ BX, R13 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w7 @ R14 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R14 - ADCQ $0x00, DX - ADDQ BX, R14 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w8 @ R15 - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, R15 - ADCQ DX, CX - ADDQ BX, R15 - - // | w9 @ R8 - ADCQ CX, R8 - MOVQ $0x00, CX - ADCQ $0x00, CX - - // | - -/* i4 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 - | 4 R11 | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP) - - - // | | u4 = w4 * inp - MOVQ R11, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w4 @ R11 - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, R11 - ADCQ DX, BX - - // | j1 - - // | w5 @ R12 - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ $0x00, DX - ADDQ BX, R12 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w6 @ R13 - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, R13 - ADCQ $0x00, DX - ADDQ BX, R13 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w7 @ R14 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R14 - ADCQ $0x00, DX - ADDQ BX, R14 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w8 @ R15 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R15 - ADCQ $0x00, DX - ADDQ BX, R15 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w9 @ R8 - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, R8 - ADCQ DX, CX - ADDQ BX, R8 - - // | move to idle register - MOVQ 8(SP), DI - - // | w10 @ DI - ADCQ CX, DI - MOVQ $0x00, CX - ADCQ $0x00, CX - - // | - -/* i5 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 R12 - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 DI | 11 (SP) - - - // | | u5 = w5 * inp - MOVQ R12, AX - MULQ ·inp+0(SB) - MOVQ AX, R9 - MOVQ $0x00, BX - - // | - -/* */ - - // | j0 - - // | w5 @ R12 - MOVQ ·modulus+0(SB), AX - MULQ R9 - ADDQ AX, R12 - ADCQ DX, BX - - // | j1 - - // | w6 @ R13 - MOVQ ·modulus+8(SB), AX - MULQ R9 - ADDQ AX, R13 - ADCQ $0x00, DX - ADDQ BX, R13 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j2 - - // | w7 @ R14 - MOVQ ·modulus+16(SB), AX - MULQ R9 - ADDQ AX, R14 - ADCQ $0x00, DX - ADDQ BX, R14 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j3 - - // | w8 @ R15 - MOVQ ·modulus+24(SB), AX - MULQ R9 - ADDQ AX, R15 - ADCQ $0x00, DX - ADDQ BX, R15 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j4 - - // | w9 @ R8 - MOVQ ·modulus+32(SB), AX - MULQ R9 - ADDQ AX, R8 - ADCQ $0x00, DX - ADDQ BX, R8 - MOVQ $0x00, BX - ADCQ DX, BX - - // | j5 - - // | w10 @ DI - MOVQ ·modulus+40(SB), AX - MULQ R9 - ADDQ AX, DI - ADCQ DX, CX - ADDQ BX, DI - - // | w11 @ CX - ADCQ (SP), CX - - // | - // | W montgomerry reduction ends - // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 - - // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 DI | 11 CX - - - // | - - -/* modular reduction */ - - MOVQ R13, R10 - SUBQ ·modulus+0(SB), R10 - MOVQ R14, R11 - SBBQ ·modulus+8(SB), R11 - MOVQ R15, R12 - SBBQ ·modulus+16(SB), R12 - MOVQ R8, AX - SBBQ ·modulus+24(SB), AX - MOVQ DI, BX - SBBQ ·modulus+32(SB), BX - MOVQ CX, R9 - SBBQ ·modulus+40(SB), R9 - // | - -/* out */ - - MOVQ c+0(FP), SI - CMOVQCC R10, R13 - MOVQ R13, (SI) - CMOVQCC R11, R14 - MOVQ R14, 8(SI) - CMOVQCC R12, R15 - MOVQ R15, 16(SI) - CMOVQCC AX, R8 - MOVQ R8, 24(SI) - CMOVQCC BX, DI - MOVQ DI, 32(SI) - CMOVQCC R9, CX - MOVQ CX, 40(SI) - RET - - // | - -/* end */ - - -// multiplication -// c = a * b % p -TEXT ·mulADX(SB), NOSPLIT, $16-24 - // | - -/* inputs */ - - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - XORQ AX, AX - - // | - -/* i0 */ - - // | a0 @ DX - MOVQ (DI), DX - - // | a0 * b0 - MULXQ (SI), AX, CX - MOVQ AX, (SP) - - // | a0 * b1 - MULXQ 8(SI), AX, R8 - ADCXQ AX, CX - - // | a0 * b2 - MULXQ 16(SI), AX, R9 - ADCXQ AX, R8 - - // | a0 * b3 - MULXQ 24(SI), AX, R10 - ADCXQ AX, R9 - - // | a0 * b4 - MULXQ 32(SI), AX, R11 - ADCXQ AX, R10 - - // | a0 * b5 - MULXQ 40(SI), AX, R12 - ADCXQ AX, R11 - ADCQ $0x00, R12 - - // | - -/* i1 */ - - // | a1 @ DX - MOVQ 8(DI), DX - XORQ R13, R13 - - // | a1 * b0 - MULXQ (SI), AX, BX - ADOXQ AX, CX - ADCXQ BX, R8 - MOVQ CX, 8(SP) - - // | a1 * b1 - MULXQ 8(SI), AX, BX - ADOXQ AX, R8 - ADCXQ BX, R9 - - // | a1 * b2 - MULXQ 16(SI), AX, BX - ADOXQ AX, R9 - ADCXQ BX, R10 - - // | a1 * b3 - MULXQ 24(SI), AX, BX - ADOXQ AX, R10 - ADCXQ BX, R11 - - // | a1 * b4 - MULXQ 32(SI), AX, BX - ADOXQ AX, R11 - ADCXQ BX, R12 - - // | a1 * b5 - MULXQ 40(SI), AX, BX - ADOXQ AX, R12 - ADOXQ R13, R13 - ADCXQ BX, R13 - - // | - -/* i2 */ - - // | a2 @ DX - MOVQ 16(DI), DX - XORQ R14, R14 - - // | a2 * b0 - MULXQ (SI), AX, BX - ADOXQ AX, R8 - ADCXQ BX, R9 - - // | a2 * b1 - MULXQ 8(SI), AX, BX - ADOXQ AX, R9 - ADCXQ BX, R10 - - // | a2 * b2 - MULXQ 16(SI), AX, BX - ADOXQ AX, R10 - ADCXQ BX, R11 - - // | a2 * b3 - MULXQ 24(SI), AX, BX - ADOXQ AX, R11 - ADCXQ BX, R12 - - // | a2 * b4 - MULXQ 32(SI), AX, BX - ADOXQ AX, R12 - ADCXQ BX, R13 - - // | a2 * b5 - MULXQ 40(SI), AX, BX - ADOXQ AX, R13 - ADOXQ R14, R14 - ADCXQ BX, R14 - - // | - -/* i3 */ - - // | a3 @ DX - MOVQ 24(DI), DX - XORQ R15, R15 - - // | a3 * b0 - MULXQ (SI), AX, BX - ADOXQ AX, R9 - ADCXQ BX, R10 - - // | a3 * b1 - MULXQ 8(SI), AX, BX - ADOXQ AX, R10 - ADCXQ BX, R11 - - // | a3 * b2 - MULXQ 16(SI), AX, BX - ADOXQ AX, R11 - ADCXQ BX, R12 - - // | a3 * b3 - MULXQ 24(SI), AX, BX - ADOXQ AX, R12 - ADCXQ BX, R13 - - // | a3 * b4 - MULXQ 32(SI), AX, BX - ADOXQ AX, R13 - ADCXQ BX, R14 - - // | a3 * b5 - MULXQ 40(SI), AX, BX - ADOXQ AX, R14 - ADOXQ R15, R15 - ADCXQ BX, R15 - - // | - -/* i4 */ - - // | a4 @ DX - MOVQ 32(DI), DX - XORQ CX, CX - - // | a4 * b0 - MULXQ (SI), AX, BX - ADOXQ AX, R10 - ADCXQ BX, R11 - - // | a4 * b1 - MULXQ 8(SI), AX, BX - ADOXQ AX, R11 - ADCXQ BX, R12 - - // | a4 * b2 - MULXQ 16(SI), AX, BX - ADOXQ AX, R12 - ADCXQ BX, R13 - - // | a4 * b3 - MULXQ 24(SI), AX, BX - ADOXQ AX, R13 - ADCXQ BX, R14 - - // | a4 * b4 - MULXQ 32(SI), AX, BX - ADOXQ AX, R14 - ADCXQ BX, R15 - - // | a4 * b5 - MULXQ 40(SI), AX, BX - ADOXQ AX, R15 - ADOXQ CX, CX - ADCXQ BX, CX - - // | - -/* i5 */ - - // | a5 @ DX - MOVQ 40(DI), DX - XORQ DI, DI - - // | a5 * b0 - MULXQ (SI), AX, BX - ADOXQ AX, R11 - ADCXQ BX, R12 - - // | a5 * b1 - MULXQ 8(SI), AX, BX - ADOXQ AX, R12 - ADCXQ BX, R13 - - // | a5 * b2 - MULXQ 16(SI), AX, BX - ADOXQ AX, R13 - ADCXQ BX, R14 - - // | a5 * b3 - MULXQ 24(SI), AX, BX - ADOXQ AX, R14 - ADCXQ BX, R15 - - // | a5 * b4 - MULXQ 32(SI), AX, BX - ADOXQ AX, R15 - ADCXQ BX, CX - - // | a5 * b5 - MULXQ 40(SI), AX, BX - ADOXQ AX, CX - ADOXQ BX, DI - ADCQ $0x00, DI - - // | - -/* */ - - // | - // | W - // | 0 (SP) | 1 8(SP) | 2 R8 | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 DI - - - MOVQ (SP), BX - MOVQ 8(SP), SI - MOVQ DI, (SP) - - // | - // | W ready to mont - // | 0 BX | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | - -/* montgomery reduction */ - - // | clear flags - XORQ AX, AX - - // | - -/* i0 */ - - // | - // | W - // | 0 BX | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u0 = w0 * inp - MOVQ BX, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w0 @ BX - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, BX - ADCXQ DI, SI - - // | j1 - - // | w1 @ SI - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, SI - ADCXQ DI, R8 - - // | j2 - - // | w2 @ R8 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R8 - ADCXQ DI, R9 - - // | j3 - - // | w3 @ R9 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R9 - ADCXQ DI, R10 - - // | j4 - - // | w4 @ R10 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R10 - ADCXQ DI, R11 - - // | j5 - - // | w5 @ R11 - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - ADOXQ BX, R12 - ADCXQ BX, BX - MOVQ $0x00, AX - ADOXQ AX, BX - - // | clear flags - XORQ AX, AX - - // | - -/* i1 */ - - // | - // | W - // | 0 - | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u1 = w1 * inp - MOVQ SI, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w1 @ SI - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, SI - ADCXQ DI, R8 - - // | j1 - - // | w2 @ R8 - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, R8 - ADCXQ DI, R9 - - // | j2 - - // | w3 @ R9 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R9 - ADCXQ DI, R10 - - // | j3 - - // | w4 @ R10 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R10 - ADCXQ DI, R11 - - // | j4 - - // | w5 @ R11 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - - // | j5 - - // | w6 @ R12 - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, R12 - ADCXQ DI, R13 - ADOXQ BX, R13 - ADCXQ SI, SI - MOVQ $0x00, AX - ADOXQ AX, SI - - // | clear flags - XORQ AX, AX - - // | - -/* i2 */ - - // | - // | W - // | 0 - | 1 - | 2 R8 | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u2 = w2 * inp - MOVQ R8, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w2 @ R8 - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, R8 - ADCXQ DI, R9 - - // | j1 - - // | w3 @ R9 - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, R9 - ADCXQ DI, R10 - - // | j2 - - // | w4 @ R10 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R10 - ADCXQ DI, R11 - - // | j3 - - // | w5 @ R11 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - - // | j4 - - // | w6 @ R12 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R12 - ADCXQ DI, R13 - - // | j5 - - // | w7 @ R13 - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, R13 - ADCXQ DI, R14 - ADOXQ SI, R14 - ADCXQ R8, R8 - MOVQ $0x00, AX - ADOXQ AX, R8 - - // | clear flags - XORQ AX, AX - - // | - -/* i3 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 R9 | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u3 = w3 * inp - MOVQ R9, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w3 @ R9 - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, R9 - ADCXQ DI, R10 - - // | j1 - - // | w4 @ R10 - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, R10 - ADCXQ DI, R11 - - // | j2 - - // | w5 @ R11 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - - // | j3 - - // | w6 @ R12 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R12 - ADCXQ DI, R13 - - // | j4 - - // | w7 @ R13 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R13 - ADCXQ DI, R14 - - // | j5 - - // | w8 @ R14 - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, R14 - ADCXQ DI, R15 - ADOXQ R8, R15 - ADCXQ R9, R9 - MOVQ $0x00, AX - ADOXQ AX, R9 - - // | clear flags - XORQ AX, AX - - // | - -/* i4 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 - | 4 R10 | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u4 = w4 * inp - MOVQ R10, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w4 @ R10 - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, R10 - ADCXQ DI, R11 - - // | j1 - - // | w5 @ R11 - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - - // | j2 - - // | w6 @ R12 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R12 - ADCXQ DI, R13 - - // | j3 - - // | w7 @ R13 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R13 - ADCXQ DI, R14 - - // | j4 - - // | w8 @ R14 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R14 - ADCXQ DI, R15 - - // | j5 - - // | w9 @ R15 - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, R15 - ADCXQ DI, CX - ADOXQ R9, CX - ADCXQ R10, R10 - MOVQ $0x00, AX - ADOXQ AX, R10 - - // | clear flags - XORQ AX, AX - - // | - -/* i5 */ - - // | - // | W - // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 R11 - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP) - - - // | | u5 = w5 * inp - MOVQ R11, DX - MULXQ ·inp+0(SB), DX, DI - - // | - -/* */ - - // | j0 - - // | w5 @ R11 - MULXQ ·modulus+0(SB), AX, DI - ADOXQ AX, R11 - ADCXQ DI, R12 - - // | j1 - - // | w6 @ R12 - MULXQ ·modulus+8(SB), AX, DI - ADOXQ AX, R12 - ADCXQ DI, R13 - - // | j2 - - // | w7 @ R13 - MULXQ ·modulus+16(SB), AX, DI - ADOXQ AX, R13 - ADCXQ DI, R14 - - // | j3 - - // | w8 @ R14 - MULXQ ·modulus+24(SB), AX, DI - ADOXQ AX, R14 - ADCXQ DI, R15 - - // | j4 - - // | w9 @ R15 - MULXQ ·modulus+32(SB), AX, DI - ADOXQ AX, R15 - ADCXQ DI, CX - - // | j5 - - // | w10 @ CX - MULXQ ·modulus+40(SB), AX, DI - ADOXQ AX, CX - - // | w11 @ (SP) - // | move to an idle register - MOVQ (SP), BX - ADCXQ DI, BX - ADOXQ R10, BX - - // | - // | W montgomery reduction ends - // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 - - // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 BX - - - // | - -/* modular reduction */ - - MOVQ R12, AX - SUBQ ·modulus+0(SB), AX - MOVQ R13, DI - SBBQ ·modulus+8(SB), DI - MOVQ R14, SI - SBBQ ·modulus+16(SB), SI - MOVQ R15, R8 - SBBQ ·modulus+24(SB), R8 - MOVQ CX, R9 - SBBQ ·modulus+32(SB), R9 - MOVQ BX, R10 - SBBQ ·modulus+40(SB), R10 - - // | - -/* out */ - - MOVQ c+0(FP), R11 - CMOVQCC AX, R12 - MOVQ R12, (R11) - CMOVQCC DI, R13 - MOVQ R13, 8(R11) - CMOVQCC SI, R14 - MOVQ R14, 16(R11) - CMOVQCC R8, R15 - MOVQ R15, 24(R11) - CMOVQCC R9, CX - MOVQ CX, 32(R11) - CMOVQCC R10, BX - MOVQ BX, 40(R11) - RET - - // | - -/* end */ diff --git a/builder/crypto/bls12381/arithmetic_x86_adx.go b/builder/crypto/bls12381/arithmetic_x86_adx.go deleted file mode 100644 index a40c7384e..000000000 --- a/builder/crypto/bls12381/arithmetic_x86_adx.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 . - -//go:build amd64 && blsadx -// +build amd64,blsadx - -package bls12381 - -// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS -// implementation. The system may still fall back to plain ASM if the necessary -// instructions are unavailable on the CPU. -const enableADX = true diff --git a/builder/crypto/bls12381/arithmetic_x86_noadx.go b/builder/crypto/bls12381/arithmetic_x86_noadx.go deleted file mode 100644 index 679b30ec8..000000000 --- a/builder/crypto/bls12381/arithmetic_x86_noadx.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 . - -//go:build amd64 && blsasm -// +build amd64,blsasm - -package bls12381 - -// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS -// implementation. The system may still fall back to plain ASM if the necessary -// instructions are unavailable on the CPU. -const enableADX = false diff --git a/builder/crypto/bls12381/bls12_381.go b/builder/crypto/bls12381/bls12_381.go deleted file mode 100644 index 1c1c97765..000000000 --- a/builder/crypto/bls12381/bls12_381.go +++ /dev/null @@ -1,230 +0,0 @@ -// 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 bls12381 - -/* - Field Constants -*/ - -// Base field modulus -// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab - -// Size of six words -// r = 2 ^ 384 - -// modulus = p -var modulus = fe{0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a} - -var ( - // -p^(-1) mod 2^64 - inp uint64 = 0x89f3fffcfffcfffd - // This value is used in assembly code - _ = inp -) - -// r mod p -var r1 = &fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493} - -// r^2 mod p -var r2 = &fe{ - 0xf4df1f341c341746, 0x0a76e6a609d104f1, 0x8de5476c4c95b6d5, 0x67eb88a9939d83c0, 0x9a793e85b519952d, 0x11988fe592cae3aa, -} - -// -1 + 0 * u -var negativeOne2 = &fe2{ - fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, -} - -// 2 ^ (-1) -var twoInv = &fe{0x1804000000015554, 0x855000053ab00001, 0x633cb57c253c276f, 0x6e22d1ec31ebb502, 0xd3916126f2d14ca2, 0x17fbb8571a006596} - -// (p - 3) / 4 -var pMinus3Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa") - -// (p + 1) / 4 -var pPlus1Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaab") - -// (p - 1) / 2 -var pMinus1Over2 = bigFromHex("0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd555") - -// -1 -var nonResidue1 = &fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206} - -// (1 + 1 * u) -var nonResidue2 = &fe2{ - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, -} - -/* - Curve Constants -*/ - -// b coefficient for G1 -var b = &fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e} - -// b coefficient for G2 -var b2 = &fe2{ - fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e}, - fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e}, -} - -// Curve order -var q = bigFromHex("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001") - -// Efficient cofactor of G1 -var cofactorEFFG1 = bigFromHex("0xd201000000010001") - -// Efficient cofactor of G2 -var cofactorEFFG2 = bigFromHex("0x0bc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551") - -var g1One = PointG1{ - fe{0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75}, - fe{0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0x0e1c8c3fad0059c0, 0x0bbc3efc5008a26a}, - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, -} - -var g2One = PointG2{ - fe2{ - fe{0xf5f28fa202940a10, 0xb3f5fb2687b4961a, 0xa1a893b53e2ae580, 0x9894999d1a3caee9, 0x6f67b7631863366b, 0x058191924350bcd7}, - fe{0xa5a9c0759e23f606, 0xaaa0c59dbccd60c3, 0x3bb17e18e2867806, 0x1b1ab6cc8541b367, 0xc2b6ed0ef2158547, 0x11922a097360edf3}, - }, - fe2{ - fe{0x4c730af860494c4a, 0x597cfa1f5e369c5a, 0xe7e6856caa0a635a, 0xbbefb5e96e0d495f, 0x07d3a975f0ef25a2, 0x083fd8e7e80dae5}, - fe{0xadc0fc92df64b05d, 0x18aa270a2b1461dc, 0x86adac6a3be4eba0, 0x79495c4ec93da33a, 0xe7175850a43ccaed, 0xb2bc2a163de1bf2}, - }, - fe2{ - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, -} - -/* - Frobenious Coeffs -*/ - -var frobeniusCoeffs61 = [6]fe2{ - { - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741}, - }, - { - fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - }, - { - fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160}, - }, -} - -var frobeniusCoeffs62 = [6]fe2{ - { - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, -} - -var frobeniusCoeffs12 = [12]fe2{ - { - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb}, - fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf}, - }, - { - fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8}, - fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2}, - }, - { - fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd}, - fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd}, - }, - { - fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf}, - fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb}, - }, - { - fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2}, - fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8}, - }, - { - fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a}, - fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, - }, - { - fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd}, - fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd}, - }, -} - -/* - x -*/ - -var x = bigFromHex("0xd201000000010000") diff --git a/builder/crypto/bls12381/bls12_381_test.go b/builder/crypto/bls12381/bls12_381_test.go deleted file mode 100644 index 6bf583410..000000000 --- a/builder/crypto/bls12381/bls12_381_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package bls12381 - -import ( - "crypto/rand" - "math/big" -) - -var fuz = 10 - -func randScalar(max *big.Int) *big.Int { - a, _ := rand.Int(rand.Reader, max) - return a -} diff --git a/builder/crypto/bls12381/field_element.go b/builder/crypto/bls12381/field_element.go deleted file mode 100644 index 9fdddc618..000000000 --- a/builder/crypto/bls12381/field_element.go +++ /dev/null @@ -1,340 +0,0 @@ -// 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 bls12381 - -import ( - "crypto/rand" - "encoding/hex" - "fmt" - "io" - "math/big" -) - -// fe is base field element representation -type fe [6]uint64 - -// fe2 is element representation of 'fp2' which is quadratic extension of base field 'fp' -// Representation follows c[0] + c[1] * u encoding order. -type fe2 [2]fe - -// fe6 is element representation of 'fp6' field which is cubic extension of 'fp2' -// Representation follows c[0] + c[1] * v + c[2] * v^2 encoding order. -type fe6 [3]fe2 - -// fe12 is element representation of 'fp12' field which is quadratic extension of 'fp6' -// Representation follows c[0] + c[1] * w encoding order. -type fe12 [2]fe6 - -func (fe *fe) setBytes(in []byte) *fe { - size := 48 - l := len(in) - if l >= size { - l = size - } - padded := make([]byte, size) - copy(padded[size-l:], in[:]) - var a int - for i := 0; i < 6; i++ { - a = size - i*8 - fe[i] = uint64(padded[a-1]) | uint64(padded[a-2])<<8 | - uint64(padded[a-3])<<16 | uint64(padded[a-4])<<24 | - uint64(padded[a-5])<<32 | uint64(padded[a-6])<<40 | - uint64(padded[a-7])<<48 | uint64(padded[a-8])<<56 - } - return fe -} - -func (fe *fe) setBig(a *big.Int) *fe { - return fe.setBytes(a.Bytes()) -} - -func (fe *fe) setString(s string) (*fe, error) { - if s[:2] == "0x" { - s = s[2:] - } - bytes, err := hex.DecodeString(s) - if err != nil { - return nil, err - } - return fe.setBytes(bytes), nil -} - -func (fe *fe) set(fe2 *fe) *fe { - fe[0] = fe2[0] - fe[1] = fe2[1] - fe[2] = fe2[2] - fe[3] = fe2[3] - fe[4] = fe2[4] - fe[5] = fe2[5] - return fe -} - -func (fe *fe) bytes() []byte { - out := make([]byte, 48) - var a int - for i := 0; i < 6; i++ { - a = 48 - i*8 - out[a-1] = byte(fe[i]) - out[a-2] = byte(fe[i] >> 8) - out[a-3] = byte(fe[i] >> 16) - out[a-4] = byte(fe[i] >> 24) - out[a-5] = byte(fe[i] >> 32) - out[a-6] = byte(fe[i] >> 40) - out[a-7] = byte(fe[i] >> 48) - out[a-8] = byte(fe[i] >> 56) - } - return out -} - -func (fe *fe) big() *big.Int { - return new(big.Int).SetBytes(fe.bytes()) -} - -func (fe *fe) string() (s string) { - for i := 5; i >= 0; i-- { - s = fmt.Sprintf("%s%16.16x", s, fe[i]) - } - return "0x" + s -} - -func (fe *fe) zero() *fe { - fe[0] = 0 - fe[1] = 0 - fe[2] = 0 - fe[3] = 0 - fe[4] = 0 - fe[5] = 0 - return fe -} - -func (fe *fe) one() *fe { - return fe.set(r1) -} - -func (fe *fe) rand(r io.Reader) (*fe, error) { - bi, err := rand.Int(r, modulus.big()) - if err != nil { - return nil, err - } - return fe.setBig(bi), nil -} - -func (fe *fe) isValid() bool { - return fe.cmp(&modulus) < 0 -} - -func (fe *fe) isOdd() bool { - var mask uint64 = 1 - return fe[0]&mask != 0 -} - -func (fe *fe) isEven() bool { - var mask uint64 = 1 - return fe[0]&mask == 0 -} - -func (fe *fe) isZero() bool { - return (fe[5] | fe[4] | fe[3] | fe[2] | fe[1] | fe[0]) == 0 -} - -func (fe *fe) isOne() bool { - return fe.equal(r1) -} - -func (fe *fe) cmp(fe2 *fe) int { - for i := 5; i >= 0; i-- { - if fe[i] > fe2[i] { - return 1 - } else if fe[i] < fe2[i] { - return -1 - } - } - return 0 -} - -func (fe *fe) equal(fe2 *fe) bool { - return fe2[0] == fe[0] && fe2[1] == fe[1] && fe2[2] == fe[2] && fe2[3] == fe[3] && fe2[4] == fe[4] && fe2[5] == fe[5] -} - -func (e *fe) sign() bool { - r := new(fe) - fromMont(r, e) - return r[0]&1 == 0 -} - -func (fe *fe) div2(e uint64) { - fe[0] = fe[0]>>1 | fe[1]<<63 - fe[1] = fe[1]>>1 | fe[2]<<63 - fe[2] = fe[2]>>1 | fe[3]<<63 - fe[3] = fe[3]>>1 | fe[4]<<63 - fe[4] = fe[4]>>1 | fe[5]<<63 - fe[5] = fe[5]>>1 | e<<63 -} - -func (fe *fe) mul2() uint64 { - e := fe[5] >> 63 - fe[5] = fe[5]<<1 | fe[4]>>63 - fe[4] = fe[4]<<1 | fe[3]>>63 - fe[3] = fe[3]<<1 | fe[2]>>63 - fe[2] = fe[2]<<1 | fe[1]>>63 - fe[1] = fe[1]<<1 | fe[0]>>63 - fe[0] = fe[0] << 1 - return e -} - -func (e *fe2) zero() *fe2 { - e[0].zero() - e[1].zero() - return e -} - -func (e *fe2) one() *fe2 { - e[0].one() - e[1].zero() - return e -} - -func (e *fe2) set(e2 *fe2) *fe2 { - e[0].set(&e2[0]) - e[1].set(&e2[1]) - return e -} - -func (e *fe2) rand(r io.Reader) (*fe2, error) { - a0, err := new(fe).rand(r) - if err != nil { - return nil, err - } - a1, err := new(fe).rand(r) - if err != nil { - return nil, err - } - return &fe2{*a0, *a1}, nil -} - -func (e *fe2) isOne() bool { - return e[0].isOne() && e[1].isZero() -} - -func (e *fe2) isZero() bool { - return e[0].isZero() && e[1].isZero() -} - -func (e *fe2) equal(e2 *fe2) bool { - return e[0].equal(&e2[0]) && e[1].equal(&e2[1]) -} - -func (e *fe2) sign() bool { - r := new(fe) - if !e[0].isZero() { - fromMont(r, &e[0]) - return r[0]&1 == 0 - } - fromMont(r, &e[1]) - return r[0]&1 == 0 -} - -func (e *fe6) zero() *fe6 { - e[0].zero() - e[1].zero() - e[2].zero() - return e -} - -func (e *fe6) one() *fe6 { - e[0].one() - e[1].zero() - e[2].zero() - return e -} - -func (e *fe6) set(e2 *fe6) *fe6 { - e[0].set(&e2[0]) - e[1].set(&e2[1]) - e[2].set(&e2[2]) - return e -} - -func (e *fe6) rand(r io.Reader) (*fe6, error) { - a0, err := new(fe2).rand(r) - if err != nil { - return nil, err - } - a1, err := new(fe2).rand(r) - if err != nil { - return nil, err - } - a2, err := new(fe2).rand(r) - if err != nil { - return nil, err - } - return &fe6{*a0, *a1, *a2}, nil -} - -func (e *fe6) isOne() bool { - return e[0].isOne() && e[1].isZero() && e[2].isZero() -} - -func (e *fe6) isZero() bool { - return e[0].isZero() && e[1].isZero() && e[2].isZero() -} - -func (e *fe6) equal(e2 *fe6) bool { - return e[0].equal(&e2[0]) && e[1].equal(&e2[1]) && e[2].equal(&e2[2]) -} - -func (e *fe12) zero() *fe12 { - e[0].zero() - e[1].zero() - return e -} - -func (e *fe12) one() *fe12 { - e[0].one() - e[1].zero() - return e -} - -func (e *fe12) set(e2 *fe12) *fe12 { - e[0].set(&e2[0]) - e[1].set(&e2[1]) - return e -} - -func (e *fe12) rand(r io.Reader) (*fe12, error) { - a0, err := new(fe6).rand(r) - if err != nil { - return nil, err - } - a1, err := new(fe6).rand(r) - if err != nil { - return nil, err - } - return &fe12{*a0, *a1}, nil -} - -func (e *fe12) isOne() bool { - return e[0].isOne() && e[1].isZero() -} - -func (e *fe12) isZero() bool { - return e[0].isZero() && e[1].isZero() -} - -func (e *fe12) equal(e2 *fe12) bool { - return e[0].equal(&e2[0]) && e[1].equal(&e2[1]) -} diff --git a/builder/crypto/bls12381/field_element_test.go b/builder/crypto/bls12381/field_element_test.go deleted file mode 100644 index 70bbe5cfe..000000000 --- a/builder/crypto/bls12381/field_element_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package bls12381 - -import ( - "bytes" - "crypto/rand" - "math/big" - "testing" -) - -func TestFieldElementValidation(t *testing.T) { - zero := new(fe).zero() - if !zero.isValid() { - t.Fatal("zero must be valid") - } - one := new(fe).one() - if !one.isValid() { - t.Fatal("one must be valid") - } - if modulus.isValid() { - t.Fatal("modulus must be invalid") - } - n := modulus.big() - n.Add(n, big.NewInt(1)) - if new(fe).setBig(n).isValid() { - t.Fatal("number greater than modulus must be invalid") - } -} - -func TestFieldElementEquality(t *testing.T) { - // fe - zero := new(fe).zero() - if !zero.equal(zero) { - t.Fatal("0 == 0") - } - one := new(fe).one() - if !one.equal(one) { - t.Fatal("1 == 1") - } - a, _ := new(fe).rand(rand.Reader) - if !a.equal(a) { - t.Fatal("a == a") - } - b := new(fe) - add(b, a, one) - if a.equal(b) { - t.Fatal("a != a + 1") - } - // fe2 - zero2 := new(fe2).zero() - if !zero2.equal(zero2) { - t.Fatal("0 == 0") - } - one2 := new(fe2).one() - if !one2.equal(one2) { - t.Fatal("1 == 1") - } - a2, _ := new(fe2).rand(rand.Reader) - if !a2.equal(a2) { - t.Fatal("a == a") - } - b2 := new(fe2) - fp2 := newFp2() - fp2.add(b2, a2, one2) - if a2.equal(b2) { - t.Fatal("a != a + 1") - } - // fe6 - zero6 := new(fe6).zero() - if !zero6.equal(zero6) { - t.Fatal("0 == 0") - } - one6 := new(fe6).one() - if !one6.equal(one6) { - t.Fatal("1 == 1") - } - a6, _ := new(fe6).rand(rand.Reader) - if !a6.equal(a6) { - t.Fatal("a == a") - } - b6 := new(fe6) - fp6 := newFp6(fp2) - fp6.add(b6, a6, one6) - if a6.equal(b6) { - t.Fatal("a != a + 1") - } - // fe12 - zero12 := new(fe12).zero() - if !zero12.equal(zero12) { - t.Fatal("0 == 0") - } - one12 := new(fe12).one() - if !one12.equal(one12) { - t.Fatal("1 == 1") - } - a12, _ := new(fe12).rand(rand.Reader) - if !a12.equal(a12) { - t.Fatal("a == a") - } - b12 := new(fe12) - fp12 := newFp12(fp6) - fp12.add(b12, a12, one12) - if a12.equal(b12) { - t.Fatal("a != a + 1") - } -} - -func TestFieldElementHelpers(t *testing.T) { - // fe - zero := new(fe).zero() - if !zero.isZero() { - t.Fatal("'zero' is not zero") - } - one := new(fe).one() - if !one.isOne() { - t.Fatal("'one' is not one") - } - odd := new(fe).setBig(big.NewInt(1)) - if !odd.isOdd() { - t.Fatal("1 must be odd") - } - if odd.isEven() { - t.Fatal("1 must not be even") - } - even := new(fe).setBig(big.NewInt(2)) - if !even.isEven() { - t.Fatal("2 must be even") - } - if even.isOdd() { - t.Fatal("2 must not be odd") - } - // fe2 - zero2 := new(fe2).zero() - if !zero2.isZero() { - t.Fatal("'zero' is not zero, 2") - } - one2 := new(fe2).one() - if !one2.isOne() { - t.Fatal("'one' is not one, 2") - } - // fe6 - zero6 := new(fe6).zero() - if !zero6.isZero() { - t.Fatal("'zero' is not zero, 6") - } - one6 := new(fe6).one() - if !one6.isOne() { - t.Fatal("'one' is not one, 6") - } - // fe12 - zero12 := new(fe12).zero() - if !zero12.isZero() { - t.Fatal("'zero' is not zero, 12") - } - one12 := new(fe12).one() - if !one12.isOne() { - t.Fatal("'one' is not one, 12") - } -} - -func TestFieldElementSerialization(t *testing.T) { - t.Run("zero", func(t *testing.T) { - in := make([]byte, 48) - fe := new(fe).setBytes(in) - if !fe.isZero() { - t.Fatal("bad serialization") - } - if !bytes.Equal(in, fe.bytes()) { - t.Fatal("bad serialization") - } - }) - t.Run("bytes", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b := new(fe).setBytes(a.bytes()) - if !a.equal(b) { - t.Fatal("bad serialization") - } - } - }) - t.Run("big", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b := new(fe).setBig(a.big()) - if !a.equal(b) { - t.Fatal("bad encoding or decoding") - } - } - }) - t.Run("string", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, err := new(fe).setString(a.string()) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad encoding or decoding") - } - } - }) -} - -func TestFieldElementByteInputs(t *testing.T) { - zero := new(fe).zero() - in := make([]byte, 0) - a := new(fe).setBytes(in) - if !a.equal(zero) { - t.Fatal("bad serialization") - } - in = make([]byte, 48) - a = new(fe).setBytes(in) - if !a.equal(zero) { - t.Fatal("bad serialization") - } - in = make([]byte, 64) - a = new(fe).setBytes(in) - if !a.equal(zero) { - t.Fatal("bad serialization") - } - in = make([]byte, 49) - in[47] = 1 - normalOne := &fe{1, 0, 0, 0, 0, 0} - a = new(fe).setBytes(in) - if !a.equal(normalOne) { - t.Fatal("bad serialization") - } -} - -func TestFieldElementCopy(t *testing.T) { - a, _ := new(fe).rand(rand.Reader) - b := new(fe).set(a) - if !a.equal(b) { - t.Fatal("bad copy, 1") - } - a2, _ := new(fe2).rand(rand.Reader) - b2 := new(fe2).set(a2) - if !a2.equal(b2) { - t.Fatal("bad copy, 2") - } - a6, _ := new(fe6).rand(rand.Reader) - b6 := new(fe6).set(a6) - if !a6.equal(b6) { - t.Fatal("bad copy, 6") - } - a12, _ := new(fe12).rand(rand.Reader) - b12 := new(fe12).set(a12) - if !a12.equal(b12) { - t.Fatal("bad copy, 12") - } -} diff --git a/builder/crypto/bls12381/fp.go b/builder/crypto/bls12381/fp.go deleted file mode 100644 index 09f6f49bc..000000000 --- a/builder/crypto/bls12381/fp.go +++ /dev/null @@ -1,167 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" -) - -func fromBytes(in []byte) (*fe, error) { - fe := &fe{} - if len(in) != 48 { - return nil, errors.New("input string should be equal 48 bytes") - } - fe.setBytes(in) - if !fe.isValid() { - return nil, errors.New("must be less than modulus") - } - toMont(fe, fe) - return fe, nil -} - -func fromBig(in *big.Int) (*fe, error) { - fe := new(fe).setBig(in) - if !fe.isValid() { - return nil, errors.New("invalid input string") - } - toMont(fe, fe) - return fe, nil -} - -func fromString(in string) (*fe, error) { - fe, err := new(fe).setString(in) - if err != nil { - return nil, err - } - if !fe.isValid() { - return nil, errors.New("invalid input string") - } - toMont(fe, fe) - return fe, nil -} - -func toBytes(e *fe) []byte { - e2 := new(fe) - fromMont(e2, e) - return e2.bytes() -} - -func toBig(e *fe) *big.Int { - e2 := new(fe) - fromMont(e2, e) - return e2.big() -} - -func toString(e *fe) (s string) { - e2 := new(fe) - fromMont(e2, e) - return e2.string() -} - -func toMont(c, a *fe) { - mul(c, a, r2) -} - -func fromMont(c, a *fe) { - mul(c, a, &fe{1}) -} - -func exp(c, a *fe, e *big.Int) { - z := new(fe).set(r1) - for i := e.BitLen(); i >= 0; i-- { - mul(z, z, z) - if e.Bit(i) == 1 { - mul(z, z, a) - } - } - c.set(z) -} - -func inverse(inv, e *fe) { - if e.isZero() { - inv.zero() - return - } - u := new(fe).set(&modulus) - v := new(fe).set(e) - s := &fe{1} - r := &fe{0} - var k int - var z uint64 - var found = false - // Phase 1 - for i := 0; i < 768; i++ { - if v.isZero() { - found = true - break - } - if u.isEven() { - u.div2(0) - s.mul2() - } else if v.isEven() { - v.div2(0) - z += r.mul2() - } else if u.cmp(v) == 1 { - lsubAssign(u, v) - u.div2(0) - laddAssign(r, s) - s.mul2() - } else { - lsubAssign(v, u) - v.div2(0) - laddAssign(s, r) - z += r.mul2() - } - k += 1 - } - - if !found { - inv.zero() - return - } - - if k < 381 || k > 381+384 { - inv.zero() - return - } - - if r.cmp(&modulus) != -1 || z > 0 { - lsubAssign(r, &modulus) - } - u.set(&modulus) - lsubAssign(u, r) - - // Phase 2 - for i := k; i < 384*2; i++ { - double(u, u) - } - inv.set(u) -} - -func sqrt(c, a *fe) bool { - u, v := new(fe).set(a), new(fe) - exp(c, a, pPlus1Over4) - square(v, c) - return u.equal(v) -} - -func isQuadraticNonResidue(elem *fe) bool { - result := new(fe) - exp(result, elem, pMinus1Over2) - return !result.isOne() -} diff --git a/builder/crypto/bls12381/fp12.go b/builder/crypto/bls12381/fp12.go deleted file mode 100644 index 51e949fe5..000000000 --- a/builder/crypto/bls12381/fp12.go +++ /dev/null @@ -1,277 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" -) - -type fp12 struct { - fp12temp - fp6 *fp6 -} - -type fp12temp struct { - t2 [9]*fe2 - t6 [5]*fe6 - t12 *fe12 -} - -func newFp12Temp() fp12temp { - t2 := [9]*fe2{} - t6 := [5]*fe6{} - for i := 0; i < len(t2); i++ { - t2[i] = &fe2{} - } - for i := 0; i < len(t6); i++ { - t6[i] = &fe6{} - } - return fp12temp{t2, t6, &fe12{}} -} - -func newFp12(fp6 *fp6) *fp12 { - t := newFp12Temp() - if fp6 == nil { - return &fp12{t, newFp6(nil)} - } - return &fp12{t, fp6} -} - -func (e *fp12) fp2() *fp2 { - return e.fp6.fp2 -} - -func (e *fp12) fromBytes(in []byte) (*fe12, error) { - if len(in) != 576 { - return nil, errors.New("input string should be larger than 96 bytes") - } - fp6 := e.fp6 - c1, err := fp6.fromBytes(in[:288]) - if err != nil { - return nil, err - } - c0, err := fp6.fromBytes(in[288:]) - if err != nil { - return nil, err - } - return &fe12{*c0, *c1}, nil -} - -func (e *fp12) toBytes(a *fe12) []byte { - fp6 := e.fp6 - out := make([]byte, 576) - copy(out[:288], fp6.toBytes(&a[1])) - copy(out[288:], fp6.toBytes(&a[0])) - return out -} - -func (e *fp12) new() *fe12 { - return new(fe12) -} - -func (e *fp12) zero() *fe12 { - return new(fe12) -} - -func (e *fp12) one() *fe12 { - return new(fe12).one() -} - -func (e *fp12) add(c, a, b *fe12) { - fp6 := e.fp6 - fp6.add(&c[0], &a[0], &b[0]) - fp6.add(&c[1], &a[1], &b[1]) -} - -func (e *fp12) double(c, a *fe12) { - fp6 := e.fp6 - fp6.double(&c[0], &a[0]) - fp6.double(&c[1], &a[1]) -} - -func (e *fp12) sub(c, a, b *fe12) { - fp6 := e.fp6 - fp6.sub(&c[0], &a[0], &b[0]) - fp6.sub(&c[1], &a[1], &b[1]) -} - -func (e *fp12) neg(c, a *fe12) { - fp6 := e.fp6 - fp6.neg(&c[0], &a[0]) - fp6.neg(&c[1], &a[1]) -} - -func (e *fp12) conjugate(c, a *fe12) { - fp6 := e.fp6 - c[0].set(&a[0]) - fp6.neg(&c[1], &a[1]) -} - -func (e *fp12) square(c, a *fe12) { - fp6, t := e.fp6, e.t6 - fp6.add(t[0], &a[0], &a[1]) - fp6.mul(t[2], &a[0], &a[1]) - fp6.mulByNonResidue(t[1], &a[1]) - fp6.addAssign(t[1], &a[0]) - fp6.mulByNonResidue(t[3], t[2]) - fp6.mulAssign(t[0], t[1]) - fp6.subAssign(t[0], t[2]) - fp6.sub(&c[0], t[0], t[3]) - fp6.double(&c[1], t[2]) -} - -func (e *fp12) cyclotomicSquare(c, a *fe12) { - t, fp2 := e.t2, e.fp2() - e.fp4Square(t[3], t[4], &a[0][0], &a[1][1]) - fp2.sub(t[2], t[3], &a[0][0]) - fp2.doubleAssign(t[2]) - fp2.add(&c[0][0], t[2], t[3]) - fp2.add(t[2], t[4], &a[1][1]) - fp2.doubleAssign(t[2]) - fp2.add(&c[1][1], t[2], t[4]) - e.fp4Square(t[3], t[4], &a[1][0], &a[0][2]) - e.fp4Square(t[5], t[6], &a[0][1], &a[1][2]) - fp2.sub(t[2], t[3], &a[0][1]) - fp2.doubleAssign(t[2]) - fp2.add(&c[0][1], t[2], t[3]) - fp2.add(t[2], t[4], &a[1][2]) - fp2.doubleAssign(t[2]) - fp2.add(&c[1][2], t[2], t[4]) - fp2.mulByNonResidue(t[3], t[6]) - fp2.add(t[2], t[3], &a[1][0]) - fp2.doubleAssign(t[2]) - fp2.add(&c[1][0], t[2], t[3]) - fp2.sub(t[2], t[5], &a[0][2]) - fp2.doubleAssign(t[2]) - fp2.add(&c[0][2], t[2], t[5]) -} - -func (e *fp12) mul(c, a, b *fe12) { - t, fp6 := e.t6, e.fp6 - fp6.mul(t[1], &a[0], &b[0]) - fp6.mul(t[2], &a[1], &b[1]) - fp6.add(t[0], t[1], t[2]) - fp6.mulByNonResidue(t[2], t[2]) - fp6.add(t[3], t[1], t[2]) - fp6.add(t[1], &a[0], &a[1]) - fp6.add(t[2], &b[0], &b[1]) - fp6.mulAssign(t[1], t[2]) - c[0].set(t[3]) - fp6.sub(&c[1], t[1], t[0]) -} - -func (e *fp12) mulAssign(a, b *fe12) { - t, fp6 := e.t6, e.fp6 - fp6.mul(t[1], &a[0], &b[0]) - fp6.mul(t[2], &a[1], &b[1]) - fp6.add(t[0], t[1], t[2]) - fp6.mulByNonResidue(t[2], t[2]) - fp6.add(t[3], t[1], t[2]) - fp6.add(t[1], &a[0], &a[1]) - fp6.add(t[2], &b[0], &b[1]) - fp6.mulAssign(t[1], t[2]) - a[0].set(t[3]) - fp6.sub(&a[1], t[1], t[0]) -} - -func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) { - t, fp2 := e.t2, e.fp2() - fp2.square(t[0], a0) - fp2.square(t[1], a1) - fp2.mulByNonResidue(t[2], t[1]) - fp2.add(c0, t[2], t[0]) - fp2.add(t[2], a0, a1) - fp2.squareAssign(t[2]) - fp2.subAssign(t[2], t[0]) - fp2.sub(c1, t[2], t[1]) -} - -func (e *fp12) inverse(c, a *fe12) { - fp6, t := e.fp6, e.t6 - fp6.square(t[0], &a[0]) - fp6.square(t[1], &a[1]) - fp6.mulByNonResidue(t[1], t[1]) - fp6.sub(t[1], t[0], t[1]) - fp6.inverse(t[0], t[1]) - fp6.mul(&c[0], &a[0], t[0]) - fp6.mulAssign(t[0], &a[1]) - fp6.neg(&c[1], t[0]) -} - -func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) { - fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0] - fp6.mulBy01(t[0], &a[0], c0, c1) - fp6.mulBy1(t[1], &a[1], c4) - fp2.add(t2, c1, c4) - fp6.add(t[2], &a[1], &a[0]) - fp6.mulBy01Assign(t[2], c0, t2) - fp6.subAssign(t[2], t[0]) - fp6.sub(&a[1], t[2], t[1]) - fp6.mulByNonResidue(t[1], t[1]) - fp6.add(&a[0], t[1], t[0]) -} - -func (e *fp12) exp(c, a *fe12, s *big.Int) { - z := e.one() - for i := s.BitLen() - 1; i >= 0; i-- { - e.square(z, z) - if s.Bit(i) == 1 { - e.mul(z, z, a) - } - } - c.set(z) -} - -func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) { - z := e.one() - for i := s.BitLen() - 1; i >= 0; i-- { - e.cyclotomicSquare(z, z) - if s.Bit(i) == 1 { - e.mul(z, z, a) - } - } - c.set(z) -} - -func (e *fp12) frobeniusMap(c, a *fe12, power uint) { - fp6 := e.fp6 - fp6.frobeniusMap(&c[0], &a[0], power) - fp6.frobeniusMap(&c[1], &a[1], power) - switch power { - case 0: - return - case 6: - fp6.neg(&c[1], &c[1]) - default: - fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power]) - } -} - -func (e *fp12) frobeniusMapAssign(a *fe12, power uint) { - fp6 := e.fp6 - fp6.frobeniusMapAssign(&a[0], power) - fp6.frobeniusMapAssign(&a[1], power) - switch power { - case 0: - return - case 6: - fp6.neg(&a[1], &a[1]) - default: - fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power]) - } -} diff --git a/builder/crypto/bls12381/fp2.go b/builder/crypto/bls12381/fp2.go deleted file mode 100644 index 0f1c5a23a..000000000 --- a/builder/crypto/bls12381/fp2.go +++ /dev/null @@ -1,252 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" -) - -type fp2Temp struct { - t [4]*fe -} - -type fp2 struct { - fp2Temp -} - -func newFp2Temp() fp2Temp { - t := [4]*fe{} - for i := 0; i < len(t); i++ { - t[i] = &fe{} - } - return fp2Temp{t} -} - -func newFp2() *fp2 { - t := newFp2Temp() - return &fp2{t} -} - -func (e *fp2) fromBytes(in []byte) (*fe2, error) { - if len(in) != 96 { - return nil, errors.New("length of input string should be 96 bytes") - } - c1, err := fromBytes(in[:48]) - if err != nil { - return nil, err - } - c0, err := fromBytes(in[48:]) - if err != nil { - return nil, err - } - return &fe2{*c0, *c1}, nil -} - -func (e *fp2) toBytes(a *fe2) []byte { - out := make([]byte, 96) - copy(out[:48], toBytes(&a[1])) - copy(out[48:], toBytes(&a[0])) - return out -} - -func (e *fp2) new() *fe2 { - return new(fe2).zero() -} - -func (e *fp2) zero() *fe2 { - return new(fe2).zero() -} - -func (e *fp2) one() *fe2 { - return new(fe2).one() -} - -func (e *fp2) add(c, a, b *fe2) { - add(&c[0], &a[0], &b[0]) - add(&c[1], &a[1], &b[1]) -} - -func (e *fp2) addAssign(a, b *fe2) { - addAssign(&a[0], &b[0]) - addAssign(&a[1], &b[1]) -} - -func (e *fp2) ladd(c, a, b *fe2) { - ladd(&c[0], &a[0], &b[0]) - ladd(&c[1], &a[1], &b[1]) -} - -func (e *fp2) double(c, a *fe2) { - double(&c[0], &a[0]) - double(&c[1], &a[1]) -} - -func (e *fp2) doubleAssign(a *fe2) { - doubleAssign(&a[0]) - doubleAssign(&a[1]) -} - -func (e *fp2) ldouble(c, a *fe2) { - ldouble(&c[0], &a[0]) - ldouble(&c[1], &a[1]) -} - -func (e *fp2) sub(c, a, b *fe2) { - sub(&c[0], &a[0], &b[0]) - sub(&c[1], &a[1], &b[1]) -} - -func (e *fp2) subAssign(c, a *fe2) { - subAssign(&c[0], &a[0]) - subAssign(&c[1], &a[1]) -} - -func (e *fp2) neg(c, a *fe2) { - neg(&c[0], &a[0]) - neg(&c[1], &a[1]) -} - -func (e *fp2) mul(c, a, b *fe2) { - t := e.t - mul(t[1], &a[0], &b[0]) - mul(t[2], &a[1], &b[1]) - add(t[0], &a[0], &a[1]) - add(t[3], &b[0], &b[1]) - sub(&c[0], t[1], t[2]) - addAssign(t[1], t[2]) - mul(t[0], t[0], t[3]) - sub(&c[1], t[0], t[1]) -} - -func (e *fp2) mulAssign(a, b *fe2) { - t := e.t - mul(t[1], &a[0], &b[0]) - mul(t[2], &a[1], &b[1]) - add(t[0], &a[0], &a[1]) - add(t[3], &b[0], &b[1]) - sub(&a[0], t[1], t[2]) - addAssign(t[1], t[2]) - mul(t[0], t[0], t[3]) - sub(&a[1], t[0], t[1]) -} - -func (e *fp2) square(c, a *fe2) { - t := e.t - ladd(t[0], &a[0], &a[1]) - sub(t[1], &a[0], &a[1]) - ldouble(t[2], &a[0]) - mul(&c[0], t[0], t[1]) - mul(&c[1], t[2], &a[1]) -} - -func (e *fp2) squareAssign(a *fe2) { - t := e.t - ladd(t[0], &a[0], &a[1]) - sub(t[1], &a[0], &a[1]) - ldouble(t[2], &a[0]) - mul(&a[0], t[0], t[1]) - mul(&a[1], t[2], &a[1]) -} - -func (e *fp2) mulByNonResidue(c, a *fe2) { - t := e.t - sub(t[0], &a[0], &a[1]) - add(&c[1], &a[0], &a[1]) - c[0].set(t[0]) -} - -func (e *fp2) mulByB(c, a *fe2) { - t := e.t - double(t[0], &a[0]) - double(t[1], &a[1]) - doubleAssign(t[0]) - doubleAssign(t[1]) - sub(&c[0], t[0], t[1]) - add(&c[1], t[0], t[1]) -} - -func (e *fp2) inverse(c, a *fe2) { - t := e.t - square(t[0], &a[0]) - square(t[1], &a[1]) - addAssign(t[0], t[1]) - inverse(t[0], t[0]) - mul(&c[0], &a[0], t[0]) - mul(t[0], t[0], &a[1]) - neg(&c[1], t[0]) -} - -func (e *fp2) mulByFq(c, a *fe2, b *fe) { - mul(&c[0], &a[0], b) - mul(&c[1], &a[1], b) -} - -func (e *fp2) exp(c, a *fe2, s *big.Int) { - z := e.one() - for i := s.BitLen() - 1; i >= 0; i-- { - e.square(z, z) - if s.Bit(i) == 1 { - e.mul(z, z, a) - } - } - c.set(z) -} - -func (e *fp2) frobeniusMap(c, a *fe2, power uint) { - c[0].set(&a[0]) - if power%2 == 1 { - neg(&c[1], &a[1]) - return - } - c[1].set(&a[1]) -} - -func (e *fp2) frobeniusMapAssign(a *fe2, power uint) { - if power%2 == 1 { - neg(&a[1], &a[1]) - return - } -} - -func (e *fp2) sqrt(c, a *fe2) bool { - u, x0, a1, alpha := &fe2{}, &fe2{}, &fe2{}, &fe2{} - u.set(a) - e.exp(a1, a, pMinus3Over4) - e.square(alpha, a1) - e.mul(alpha, alpha, a) - e.mul(x0, a1, a) - if alpha.equal(negativeOne2) { - neg(&c[0], &x0[1]) - c[1].set(&x0[0]) - return true - } - e.add(alpha, alpha, e.one()) - e.exp(alpha, alpha, pMinus1Over2) - e.mul(c, alpha, x0) - e.square(alpha, c) - return alpha.equal(u) -} - -func (e *fp2) isQuadraticNonResidue(a *fe2) bool { - // https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields - c0, c1 := new(fe), new(fe) - square(c0, &a[0]) - square(c1, &a[1]) - add(c1, c1, c0) - return isQuadraticNonResidue(c1) -} diff --git a/builder/crypto/bls12381/fp6.go b/builder/crypto/bls12381/fp6.go deleted file mode 100644 index 304173baa..000000000 --- a/builder/crypto/bls12381/fp6.go +++ /dev/null @@ -1,351 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" -) - -type fp6Temp struct { - t [6]*fe2 -} - -type fp6 struct { - fp2 *fp2 - fp6Temp -} - -func newFp6Temp() fp6Temp { - t := [6]*fe2{} - for i := 0; i < len(t); i++ { - t[i] = &fe2{} - } - return fp6Temp{t} -} - -func newFp6(f *fp2) *fp6 { - t := newFp6Temp() - if f == nil { - return &fp6{newFp2(), t} - } - return &fp6{f, t} -} - -func (e *fp6) fromBytes(b []byte) (*fe6, error) { - if len(b) < 288 { - return nil, errors.New("input string should be larger than 288 bytes") - } - fp2 := e.fp2 - u2, err := fp2.fromBytes(b[:96]) - if err != nil { - return nil, err - } - u1, err := fp2.fromBytes(b[96:192]) - if err != nil { - return nil, err - } - u0, err := fp2.fromBytes(b[192:]) - if err != nil { - return nil, err - } - return &fe6{*u0, *u1, *u2}, nil -} - -func (e *fp6) toBytes(a *fe6) []byte { - fp2 := e.fp2 - out := make([]byte, 288) - copy(out[:96], fp2.toBytes(&a[2])) - copy(out[96:192], fp2.toBytes(&a[1])) - copy(out[192:], fp2.toBytes(&a[0])) - return out -} - -func (e *fp6) new() *fe6 { - return new(fe6) -} - -func (e *fp6) zero() *fe6 { - return new(fe6) -} - -func (e *fp6) one() *fe6 { - return new(fe6).one() -} - -func (e *fp6) add(c, a, b *fe6) { - fp2 := e.fp2 - fp2.add(&c[0], &a[0], &b[0]) - fp2.add(&c[1], &a[1], &b[1]) - fp2.add(&c[2], &a[2], &b[2]) -} - -func (e *fp6) addAssign(a, b *fe6) { - fp2 := e.fp2 - fp2.addAssign(&a[0], &b[0]) - fp2.addAssign(&a[1], &b[1]) - fp2.addAssign(&a[2], &b[2]) -} - -func (e *fp6) double(c, a *fe6) { - fp2 := e.fp2 - fp2.double(&c[0], &a[0]) - fp2.double(&c[1], &a[1]) - fp2.double(&c[2], &a[2]) -} - -func (e *fp6) doubleAssign(a *fe6) { - fp2 := e.fp2 - fp2.doubleAssign(&a[0]) - fp2.doubleAssign(&a[1]) - fp2.doubleAssign(&a[2]) -} - -func (e *fp6) sub(c, a, b *fe6) { - fp2 := e.fp2 - fp2.sub(&c[0], &a[0], &b[0]) - fp2.sub(&c[1], &a[1], &b[1]) - fp2.sub(&c[2], &a[2], &b[2]) -} - -func (e *fp6) subAssign(a, b *fe6) { - fp2 := e.fp2 - fp2.subAssign(&a[0], &b[0]) - fp2.subAssign(&a[1], &b[1]) - fp2.subAssign(&a[2], &b[2]) -} - -func (e *fp6) neg(c, a *fe6) { - fp2 := e.fp2 - fp2.neg(&c[0], &a[0]) - fp2.neg(&c[1], &a[1]) - fp2.neg(&c[2], &a[2]) -} - -func (e *fp6) mul(c, a, b *fe6) { - fp2, t := e.fp2, e.t - fp2.mul(t[0], &a[0], &b[0]) - fp2.mul(t[1], &a[1], &b[1]) - fp2.mul(t[2], &a[2], &b[2]) - fp2.add(t[3], &a[1], &a[2]) - fp2.add(t[4], &b[1], &b[2]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[1], t[2]) - fp2.subAssign(t[3], t[4]) - fp2.mulByNonResidue(t[3], t[3]) - fp2.add(t[5], t[0], t[3]) - fp2.add(t[3], &a[0], &a[1]) - fp2.add(t[4], &b[0], &b[1]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[0], t[1]) - fp2.subAssign(t[3], t[4]) - fp2.mulByNonResidue(t[4], t[2]) - fp2.add(&c[1], t[3], t[4]) - fp2.add(t[3], &a[0], &a[2]) - fp2.add(t[4], &b[0], &b[2]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[0], t[2]) - fp2.subAssign(t[3], t[4]) - fp2.add(&c[2], t[1], t[3]) - c[0].set(t[5]) -} - -func (e *fp6) mulAssign(a, b *fe6) { - fp2, t := e.fp2, e.t - fp2.mul(t[0], &a[0], &b[0]) - fp2.mul(t[1], &a[1], &b[1]) - fp2.mul(t[2], &a[2], &b[2]) - fp2.add(t[3], &a[1], &a[2]) - fp2.add(t[4], &b[1], &b[2]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[1], t[2]) - fp2.subAssign(t[3], t[4]) - fp2.mulByNonResidue(t[3], t[3]) - fp2.add(t[5], t[0], t[3]) - fp2.add(t[3], &a[0], &a[1]) - fp2.add(t[4], &b[0], &b[1]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[0], t[1]) - fp2.subAssign(t[3], t[4]) - fp2.mulByNonResidue(t[4], t[2]) - fp2.add(&a[1], t[3], t[4]) - fp2.add(t[3], &a[0], &a[2]) - fp2.add(t[4], &b[0], &b[2]) - fp2.mulAssign(t[3], t[4]) - fp2.add(t[4], t[0], t[2]) - fp2.subAssign(t[3], t[4]) - fp2.add(&a[2], t[1], t[3]) - a[0].set(t[5]) -} - -func (e *fp6) square(c, a *fe6) { - fp2, t := e.fp2, e.t - fp2.square(t[0], &a[0]) - fp2.mul(t[1], &a[0], &a[1]) - fp2.doubleAssign(t[1]) - fp2.sub(t[2], &a[0], &a[1]) - fp2.addAssign(t[2], &a[2]) - fp2.squareAssign(t[2]) - fp2.mul(t[3], &a[1], &a[2]) - fp2.doubleAssign(t[3]) - fp2.square(t[4], &a[2]) - fp2.mulByNonResidue(t[5], t[3]) - fp2.add(&c[0], t[0], t[5]) - fp2.mulByNonResidue(t[5], t[4]) - fp2.add(&c[1], t[1], t[5]) - fp2.addAssign(t[1], t[2]) - fp2.addAssign(t[1], t[3]) - fp2.addAssign(t[0], t[4]) - fp2.sub(&c[2], t[1], t[0]) -} - -func (e *fp6) mulBy01Assign(a *fe6, b0, b1 *fe2) { - fp2, t := e.fp2, e.t - fp2.mul(t[0], &a[0], b0) - fp2.mul(t[1], &a[1], b1) - fp2.add(t[5], &a[1], &a[2]) - fp2.mul(t[2], b1, t[5]) - fp2.subAssign(t[2], t[1]) - fp2.mulByNonResidue(t[2], t[2]) - fp2.add(t[5], &a[0], &a[2]) - fp2.mul(t[3], b0, t[5]) - fp2.subAssign(t[3], t[0]) - fp2.add(&a[2], t[3], t[1]) - fp2.add(t[4], b0, b1) - fp2.add(t[5], &a[0], &a[1]) - fp2.mulAssign(t[4], t[5]) - fp2.subAssign(t[4], t[0]) - fp2.sub(&a[1], t[4], t[1]) - fp2.add(&a[0], t[2], t[0]) -} - -func (e *fp6) mulBy01(c, a *fe6, b0, b1 *fe2) { - fp2, t := e.fp2, e.t - fp2.mul(t[0], &a[0], b0) - fp2.mul(t[1], &a[1], b1) - fp2.add(t[2], &a[1], &a[2]) - fp2.mulAssign(t[2], b1) - fp2.subAssign(t[2], t[1]) - fp2.mulByNonResidue(t[2], t[2]) - fp2.add(t[3], &a[0], &a[2]) - fp2.mulAssign(t[3], b0) - fp2.subAssign(t[3], t[0]) - fp2.add(&c[2], t[3], t[1]) - fp2.add(t[4], b0, b1) - fp2.add(t[3], &a[0], &a[1]) - fp2.mulAssign(t[4], t[3]) - fp2.subAssign(t[4], t[0]) - fp2.sub(&c[1], t[4], t[1]) - fp2.add(&c[0], t[2], t[0]) -} - -func (e *fp6) mulBy1(c, a *fe6, b1 *fe2) { - fp2, t := e.fp2, e.t - fp2.mul(t[0], &a[2], b1) - fp2.mul(&c[2], &a[1], b1) - fp2.mul(&c[1], &a[0], b1) - fp2.mulByNonResidue(&c[0], t[0]) -} - -func (e *fp6) mulByNonResidue(c, a *fe6) { - fp2, t := e.fp2, e.t - t[0].set(&a[0]) - fp2.mulByNonResidue(&c[0], &a[2]) - c[2].set(&a[1]) - c[1].set(t[0]) -} - -func (e *fp6) mulByBaseField(c, a *fe6, b *fe2) { - fp2 := e.fp2 - fp2.mul(&c[0], &a[0], b) - fp2.mul(&c[1], &a[1], b) - fp2.mul(&c[2], &a[2], b) -} - -func (e *fp6) exp(c, a *fe6, s *big.Int) { - z := e.one() - for i := s.BitLen() - 1; i >= 0; i-- { - e.square(z, z) - if s.Bit(i) == 1 { - e.mul(z, z, a) - } - } - c.set(z) -} - -func (e *fp6) inverse(c, a *fe6) { - fp2, t := e.fp2, e.t - fp2.square(t[0], &a[0]) - fp2.mul(t[1], &a[1], &a[2]) - fp2.mulByNonResidue(t[1], t[1]) - fp2.subAssign(t[0], t[1]) - fp2.square(t[1], &a[1]) - fp2.mul(t[2], &a[0], &a[2]) - fp2.subAssign(t[1], t[2]) - fp2.square(t[2], &a[2]) - fp2.mulByNonResidue(t[2], t[2]) - fp2.mul(t[3], &a[0], &a[1]) - fp2.subAssign(t[2], t[3]) - fp2.mul(t[3], &a[2], t[2]) - fp2.mul(t[4], &a[1], t[1]) - fp2.addAssign(t[3], t[4]) - fp2.mulByNonResidue(t[3], t[3]) - fp2.mul(t[4], &a[0], t[0]) - fp2.addAssign(t[3], t[4]) - fp2.inverse(t[3], t[3]) - fp2.mul(&c[0], t[0], t[3]) - fp2.mul(&c[1], t[2], t[3]) - fp2.mul(&c[2], t[1], t[3]) -} - -func (e *fp6) frobeniusMap(c, a *fe6, power uint) { - fp2 := e.fp2 - fp2.frobeniusMap(&c[0], &a[0], power) - fp2.frobeniusMap(&c[1], &a[1], power) - fp2.frobeniusMap(&c[2], &a[2], power) - switch power % 6 { - case 0: - return - case 3: - neg(&c[0][0], &a[1][1]) - c[1][1].set(&a[1][0]) - fp2.neg(&a[2], &a[2]) - default: - fp2.mul(&c[1], &c[1], &frobeniusCoeffs61[power%6]) - fp2.mul(&c[2], &c[2], &frobeniusCoeffs62[power%6]) - } -} - -func (e *fp6) frobeniusMapAssign(a *fe6, power uint) { - fp2 := e.fp2 - fp2.frobeniusMapAssign(&a[0], power) - fp2.frobeniusMapAssign(&a[1], power) - fp2.frobeniusMapAssign(&a[2], power) - t := e.t - switch power % 6 { - case 0: - return - case 3: - neg(&t[0][0], &a[1][1]) - a[1][1].set(&a[1][0]) - a[1][0].set(&t[0][0]) - fp2.neg(&a[2], &a[2]) - default: - fp2.mulAssign(&a[1], &frobeniusCoeffs61[power%6]) - fp2.mulAssign(&a[2], &frobeniusCoeffs62[power%6]) - } -} diff --git a/builder/crypto/bls12381/fp_test.go b/builder/crypto/bls12381/fp_test.go deleted file mode 100644 index 0bad35de1..000000000 --- a/builder/crypto/bls12381/fp_test.go +++ /dev/null @@ -1,1411 +0,0 @@ -package bls12381 - -import ( - "bytes" - "crypto/rand" - "math/big" - "testing" -) - -func TestFpSerialization(t *testing.T) { - t.Run("zero", func(t *testing.T) { - in := make([]byte, 48) - fe, err := fromBytes(in) - if err != nil { - t.Fatal(err) - } - if !fe.isZero() { - t.Fatal("bad serialization") - } - if !bytes.Equal(in, toBytes(fe)) { - t.Fatal("bad serialization") - } - }) - t.Run("bytes", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, err := fromBytes(toBytes(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad serialization") - } - } - }) - t.Run("string", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, err := fromString(toString(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad encoding or decoding") - } - } - }) - t.Run("big", func(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, err := fromBig(toBig(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad encoding or decoding") - } - } - }) -} - -func TestFpAdditionCrossAgainstBigInt(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - c := new(fe) - big_a := toBig(a) - big_b := toBig(b) - big_c := new(big.Int) - add(c, a, b) - out_1 := toBytes(c) - out_2 := padBytes(big_c.Add(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied A") - } - double(c, a) - out_1 = toBytes(c) - out_2 = padBytes(big_c.Add(big_a, big_a).Mod(big_c, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied B") - } - sub(c, a, b) - out_1 = toBytes(c) - out_2 = padBytes(big_c.Sub(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied C") - } - neg(c, a) - out_1 = toBytes(c) - out_2 = padBytes(big_c.Neg(big_a).Mod(big_c, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied D") - } - } -} - -func TestFpAdditionCrossAgainstBigIntAssigned(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - big_a, big_b := toBig(a), toBig(b) - addAssign(a, b) - out_1 := toBytes(a) - out_2 := padBytes(big_a.Add(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied A") - } - a, _ = new(fe).rand(rand.Reader) - big_a = toBig(a) - doubleAssign(a) - out_1 = toBytes(a) - out_2 = padBytes(big_a.Add(big_a, big_a).Mod(big_a, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied B") - } - a, _ = new(fe).rand(rand.Reader) - b, _ = new(fe).rand(rand.Reader) - big_a, big_b = toBig(a), toBig(b) - subAssign(a, b) - out_1 = toBytes(a) - out_2 = padBytes(big_a.Sub(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied A") - } - } -} - -func TestFpAdditionProperties(t *testing.T) { - for i := 0; i < fuz; i++ { - zero := new(fe).zero() - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - c_1, c_2 := new(fe), new(fe) - add(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a + 0 == a") - } - sub(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a - 0 == a") - } - double(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("2 * 0 == 0") - } - neg(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("-0 == 0") - } - sub(c_1, zero, a) - neg(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("0-a == -a") - } - double(c_1, a) - add(c_2, a, a) - if !c_1.equal(c_2) { - t.Fatal("2 * a == a + a") - } - add(c_1, a, b) - add(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - sub(c_1, a, b) - sub(c_2, b, a) - neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - c_x, _ := new(fe).rand(rand.Reader) - add(c_1, a, b) - add(c_1, c_1, c_x) - add(c_2, a, c_x) - add(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - sub(c_1, a, b) - sub(c_1, c_1, c_x) - sub(c_2, a, c_x) - sub(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a - b) - c == (a - c ) -b") - } - } -} - -func TestFpAdditionPropertiesAssigned(t *testing.T) { - for i := 0; i < fuz; i++ { - zero := new(fe).zero() - a, b := new(fe), new(fe) - _, _ = a.rand(rand.Reader) - b.set(a) - addAssign(a, zero) - if !a.equal(b) { - t.Fatal("a + 0 == a") - } - subAssign(a, zero) - if !a.equal(b) { - t.Fatal("a - 0 == a") - } - a.set(zero) - doubleAssign(a) - if !a.equal(zero) { - t.Fatal("2 * 0 == 0") - } - a.set(zero) - subAssign(a, b) - neg(b, b) - if !a.equal(b) { - t.Fatal("0-a == -a") - } - _, _ = a.rand(rand.Reader) - b.set(a) - doubleAssign(a) - addAssign(b, b) - if !a.equal(b) { - t.Fatal("2 * a == a + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1, c_2 := new(fe).set(a), new(fe).set(b) - addAssign(c_1, b) - addAssign(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1.set(a) - c_2.set(b) - subAssign(c_1, b) - subAssign(c_2, a) - neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c, _ := new(fe).rand(rand.Reader) - a0 := new(fe).set(a) - addAssign(a, b) - addAssign(a, c) - addAssign(b, c) - addAssign(b, a0) - if !a.equal(b) { - t.Fatal("(a + b) + c == (b + c) + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - _, _ = c.rand(rand.Reader) - a0.set(a) - subAssign(a, b) - subAssign(a, c) - subAssign(a0, c) - subAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a - b) - c == (a - c) -b") - } - } -} - -func TestFpLazyOperations(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - c, _ := new(fe).rand(rand.Reader) - c0 := new(fe) - c1 := new(fe) - ladd(c0, a, b) - add(c1, a, b) - mul(c0, c0, c) - mul(c1, c1, c) - if !c0.equal(c1) { - // l+ operator stands for lazy addition - t.Fatal("(a + b) * c == (a l+ b) * c") - } - _, _ = a.rand(rand.Reader) - b.set(a) - ldouble(a, a) - ladd(b, b, b) - if !a.equal(b) { - t.Fatal("2 l* a = a l+ a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - _, _ = c.rand(rand.Reader) - a0 := new(fe).set(a) - lsubAssign(a, b) - laddAssign(a, &modulus) - mul(a, a, c) - subAssign(a0, b) - mul(a0, a0, c) - if !a.equal(a0) { - t.Fatal("((a l- b) + p) * c = (a-b) * c") - } - } -} - -func TestFpMultiplicationCrossAgainstBigInt(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - c := new(fe) - big_a := toBig(a) - big_b := toBig(b) - big_c := new(big.Int) - mul(c, a, b) - out_1 := toBytes(c) - out_2 := padBytes(big_c.Mul(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48) - if !bytes.Equal(out_1, out_2) { - t.Fatal("cross test against big.Int is not satisfied") - } - } -} - -func TestFpMultiplicationProperties(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - zero, one := new(fe).zero(), new(fe).one() - c_1, c_2 := new(fe), new(fe) - mul(c_1, a, zero) - if !c_1.equal(zero) { - t.Fatal("a * 0 == 0") - } - mul(c_1, a, one) - if !c_1.equal(a) { - t.Fatal("a * 1 == a") - } - mul(c_1, a, b) - mul(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a * b == b * a") - } - c_x, _ := new(fe).rand(rand.Reader) - mul(c_1, a, b) - mul(c_1, c_1, c_x) - mul(c_2, c_x, b) - mul(c_2, c_2, a) - if !c_1.equal(c_2) { - t.Fatal("(a * b) * c == (a * c) * b") - } - square(a, zero) - if !a.equal(zero) { - t.Fatal("0^2 == 0") - } - square(a, one) - if !a.equal(one) { - t.Fatal("1^2 == 1") - } - _, _ = a.rand(rand.Reader) - square(c_1, a) - mul(c_2, a, a) - if !c_1.equal(c_1) { - t.Fatal("a^2 == a*a") - } - } -} - -func TestFpExponentiation(t *testing.T) { - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - u := new(fe) - exp(u, a, big.NewInt(0)) - if !u.isOne() { - t.Fatal("a^0 == 1") - } - exp(u, a, big.NewInt(1)) - if !u.equal(a) { - t.Fatal("a^1 == a") - } - v := new(fe) - mul(u, a, a) - mul(u, u, u) - mul(u, u, u) - exp(v, a, big.NewInt(8)) - if !u.equal(v) { - t.Fatal("((a^2)^2)^2 == a^8") - } - p := modulus.big() - exp(u, a, p) - if !u.equal(a) { - t.Fatal("a^p == a") - } - exp(u, a, p.Sub(p, big.NewInt(1))) - if !u.isOne() { - t.Fatal("a^(p-1) == 1") - } - } -} - -func TestFpInversion(t *testing.T) { - for i := 0; i < fuz; i++ { - u := new(fe) - zero, one := new(fe).zero(), new(fe).one() - inverse(u, zero) - if !u.equal(zero) { - t.Fatal("(0^-1) == 0)") - } - inverse(u, one) - if !u.equal(one) { - t.Fatal("(1^-1) == 1)") - } - a, _ := new(fe).rand(rand.Reader) - inverse(u, a) - mul(u, u, a) - if !u.equal(one) { - t.Fatal("(r*a) * r*(a^-1) == r)") - } - v := new(fe) - p := modulus.big() - exp(u, a, p.Sub(p, big.NewInt(2))) - inverse(v, a) - if !v.equal(u) { - t.Fatal("a^(p-2) == a^-1") - } - } -} - -func TestFpSquareRoot(t *testing.T) { - r := new(fe) - if sqrt(r, nonResidue1) { - t.Fatal("non residue cannot have a sqrt") - } - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - aa, rr, r := &fe{}, &fe{}, &fe{} - square(aa, a) - if !sqrt(r, aa) { - t.Fatal("bad sqrt 1") - } - square(rr, r) - if !rr.equal(aa) { - t.Fatal("bad sqrt 2") - } - } -} - -func TestFpNonResidue(t *testing.T) { - if !isQuadraticNonResidue(nonResidue1) { - t.Fatal("element is quadratic non residue, 1") - } - if isQuadraticNonResidue(new(fe).one()) { - t.Fatal("one is not quadratic non residue") - } - if !isQuadraticNonResidue(new(fe).zero()) { - t.Fatal("should accept zero as quadratic non residue") - } - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - square(a, a) - if isQuadraticNonResidue(new(fe).one()) { - t.Fatal("element is not quadratic non residue") - } - } - for i := 0; i < fuz; i++ { - a, _ := new(fe).rand(rand.Reader) - if !sqrt(new(fe), a) { - if !isQuadraticNonResidue(a) { - t.Fatal("element is quadratic non residue, 2", i) - } - } else { - i -= 1 - } - } -} - -func TestFp2Serialization(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - b, err := field.fromBytes(field.toBytes(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad serialization") - } - } -} - -func TestFp2AdditionProperties(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - zero := field.zero() - a, _ := new(fe2).rand(rand.Reader) - b, _ := new(fe2).rand(rand.Reader) - c_1 := field.new() - c_2 := field.new() - field.add(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a + 0 == a") - } - field.sub(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a - 0 == a") - } - field.double(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("2 * 0 == 0") - } - field.neg(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("-0 == 0") - } - field.sub(c_1, zero, a) - field.neg(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("0-a == -a") - } - field.double(c_1, a) - field.add(c_2, a, a) - if !c_1.equal(c_2) { - t.Fatal("2 * a == a + a") - } - field.add(c_1, a, b) - field.add(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - field.sub(c_1, a, b) - field.sub(c_2, b, a) - field.neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - c_x, _ := new(fe2).rand(rand.Reader) - field.add(c_1, a, b) - field.add(c_1, c_1, c_x) - field.add(c_2, a, c_x) - field.add(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - field.sub(c_1, a, b) - field.sub(c_1, c_1, c_x) - field.sub(c_2, a, c_x) - field.sub(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a - b) - c == (a - c ) -b") - } - } -} - -func TestFp2AdditionPropertiesAssigned(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - zero := new(fe2).zero() - a, b := new(fe2), new(fe2) - _, _ = a.rand(rand.Reader) - b.set(a) - field.addAssign(a, zero) - if !a.equal(b) { - t.Fatal("a + 0 == a") - } - field.subAssign(a, zero) - if !a.equal(b) { - t.Fatal("a - 0 == a") - } - a.set(zero) - field.doubleAssign(a) - if !a.equal(zero) { - t.Fatal("2 * 0 == 0") - } - a.set(zero) - field.subAssign(a, b) - field.neg(b, b) - if !a.equal(b) { - t.Fatal("0-a == -a") - } - _, _ = a.rand(rand.Reader) - b.set(a) - field.doubleAssign(a) - field.addAssign(b, b) - if !a.equal(b) { - t.Fatal("2 * a == a + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1, c_2 := new(fe2).set(a), new(fe2).set(b) - field.addAssign(c_1, b) - field.addAssign(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1.set(a) - c_2.set(b) - field.subAssign(c_1, b) - field.subAssign(c_2, a) - field.neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c, _ := new(fe2).rand(rand.Reader) - a0 := new(fe2).set(a) - field.addAssign(a, b) - field.addAssign(a, c) - field.addAssign(b, c) - field.addAssign(b, a0) - if !a.equal(b) { - t.Fatal("(a + b) + c == (b + c) + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - _, _ = c.rand(rand.Reader) - a0.set(a) - field.subAssign(a, b) - field.subAssign(a, c) - field.subAssign(a0, c) - field.subAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a - b) - c == (a - c) -b") - } - } -} - -func TestFp2LazyOperations(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - b, _ := new(fe2).rand(rand.Reader) - c, _ := new(fe2).rand(rand.Reader) - c0 := new(fe2) - c1 := new(fe2) - field.ladd(c0, a, b) - field.add(c1, a, b) - field.mulAssign(c0, c) - field.mulAssign(c1, c) - if !c0.equal(c1) { - // l+ operator stands for lazy addition - t.Fatal("(a + b) * c == (a l+ b) * c") - } - _, _ = a.rand(rand.Reader) - b.set(a) - field.ldouble(a, a) - field.ladd(b, b, b) - if !a.equal(b) { - t.Fatal("2 l* a = a l+ a") - } - } -} - -func TestFp2MultiplicationProperties(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - b, _ := new(fe2).rand(rand.Reader) - zero := field.zero() - one := field.one() - c_1, c_2 := field.new(), field.new() - field.mul(c_1, a, zero) - if !c_1.equal(zero) { - t.Fatal("a * 0 == 0") - } - field.mul(c_1, a, one) - if !c_1.equal(a) { - t.Fatal("a * 1 == a") - } - field.mul(c_1, a, b) - field.mul(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a * b == b * a") - } - c_x, _ := new(fe2).rand(rand.Reader) - field.mul(c_1, a, b) - field.mul(c_1, c_1, c_x) - field.mul(c_2, c_x, b) - field.mul(c_2, c_2, a) - if !c_1.equal(c_2) { - t.Fatal("(a * b) * c == (a * c) * b") - } - field.square(a, zero) - if !a.equal(zero) { - t.Fatal("0^2 == 0") - } - field.square(a, one) - if !a.equal(one) { - t.Fatal("1^2 == 1") - } - _, _ = a.rand(rand.Reader) - field.square(c_1, a) - field.mul(c_2, a, a) - if !c_2.equal(c_1) { - t.Fatal("a^2 == a*a") - } - } -} - -func TestFp2MultiplicationPropertiesAssigned(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - zero, one := new(fe2).zero(), new(fe2).one() - field.mulAssign(a, zero) - if !a.equal(zero) { - t.Fatal("a * 0 == 0") - } - _, _ = a.rand(rand.Reader) - a0 := new(fe2).set(a) - field.mulAssign(a, one) - if !a.equal(a0) { - t.Fatal("a * 1 == a") - } - _, _ = a.rand(rand.Reader) - b, _ := new(fe2).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(b, a0) - if !a.equal(b) { - t.Fatal("a * b == b * a") - } - c, _ := new(fe2).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(a, c) - field.mulAssign(a0, c) - field.mulAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a * b) * c == (a * c) * b") - } - a0.set(a) - field.squareAssign(a) - field.mulAssign(a0, a0) - if !a.equal(a0) { - t.Fatal("a^2 == a*a") - } - } -} - -func TestFp2Exponentiation(t *testing.T) { - field := newFp2() - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - u := field.new() - field.exp(u, a, big.NewInt(0)) - if !u.equal(field.one()) { - t.Fatal("a^0 == 1") - } - field.exp(u, a, big.NewInt(1)) - if !u.equal(a) { - t.Fatal("a^1 == a") - } - v := field.new() - field.mul(u, a, a) - field.mul(u, u, u) - field.mul(u, u, u) - field.exp(v, a, big.NewInt(8)) - if !u.equal(v) { - t.Fatal("((a^2)^2)^2 == a^8") - } - } -} - -func TestFp2Inversion(t *testing.T) { - field := newFp2() - u := field.new() - zero := field.zero() - one := field.one() - field.inverse(u, zero) - if !u.equal(zero) { - t.Fatal("(0 ^ -1) == 0)") - } - field.inverse(u, one) - if !u.equal(one) { - t.Fatal("(1 ^ -1) == 1)") - } - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - field.inverse(u, a) - field.mul(u, u, a) - if !u.equal(one) { - t.Fatal("(r * a) * r * (a ^ -1) == r)") - } - } -} - -func TestFp2SquareRoot(t *testing.T) { - field := newFp2() - for z := 0; z < 1000; z++ { - zi := new(fe) - sub(zi, &modulus, &fe{uint64(z * z)}) - // r = (-z*z, 0) - r := &fe2{*zi, fe{0}} - toMont(&r[0], &r[0]) - toMont(&r[1], &r[1]) - c := field.new() - // sqrt((-z*z, 0)) = (0, z) - if !field.sqrt(c, r) { - t.Fatal("z*z does have a square root") - } - e := &fe2{fe{uint64(0)}, fe{uint64(z)}} - toMont(&e[0], &e[0]) - toMont(&e[1], &e[1]) - field.square(e, e) - field.square(c, c) - if !e.equal(c) { - t.Fatal("square root failed") - } - } - if field.sqrt(field.new(), nonResidue2) { - t.Fatal("non residue cannot have a sqrt") - } - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - aa, rr, r := field.new(), field.new(), field.new() - field.square(aa, a) - if !field.sqrt(r, aa) { - t.Fatal("bad sqrt 1") - } - field.square(rr, r) - if !rr.equal(aa) { - t.Fatal("bad sqrt 2") - } - } -} - -func TestFp2NonResidue(t *testing.T) { - field := newFp2() - if !field.isQuadraticNonResidue(nonResidue2) { - t.Fatal("element is quadratic non residue, 1") - } - if field.isQuadraticNonResidue(new(fe2).one()) { - t.Fatal("one is not quadratic non residue") - } - if !field.isQuadraticNonResidue(new(fe2).zero()) { - t.Fatal("should accept zero as quadratic non residue") - } - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - field.squareAssign(a) - if field.isQuadraticNonResidue(new(fe2).one()) { - t.Fatal("element is not quadratic non residue") - } - } - for i := 0; i < fuz; i++ { - a, _ := new(fe2).rand(rand.Reader) - if !field.sqrt(new(fe2), a) { - if !field.isQuadraticNonResidue(a) { - t.Fatal("element is quadratic non residue, 2", i) - } - } else { - i -= 1 - } - } -} - -func TestFp6Serialization(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe6).rand(rand.Reader) - b, err := field.fromBytes(field.toBytes(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad serialization") - } - } -} - -func TestFp6AdditionProperties(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - zero := field.zero() - a, _ := new(fe6).rand(rand.Reader) - b, _ := new(fe6).rand(rand.Reader) - c_1 := field.new() - c_2 := field.new() - field.add(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a + 0 == a") - } - field.sub(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a - 0 == a") - } - field.double(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("2 * 0 == 0") - } - field.neg(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("-0 == 0") - } - field.sub(c_1, zero, a) - field.neg(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("0-a == -a") - } - field.double(c_1, a) - field.add(c_2, a, a) - if !c_1.equal(c_2) { - t.Fatal("2 * a == a + a") - } - field.add(c_1, a, b) - field.add(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - field.sub(c_1, a, b) - field.sub(c_2, b, a) - field.neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - c_x, _ := new(fe6).rand(rand.Reader) - field.add(c_1, a, b) - field.add(c_1, c_1, c_x) - field.add(c_2, a, c_x) - field.add(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - field.sub(c_1, a, b) - field.sub(c_1, c_1, c_x) - field.sub(c_2, a, c_x) - field.sub(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a - b) - c == (a - c ) -b") - } - } -} - -func TestFp6AdditionPropertiesAssigned(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - zero := new(fe6).zero() - a, b := new(fe6), new(fe6) - _, _ = a.rand(rand.Reader) - b.set(a) - field.addAssign(a, zero) - if !a.equal(b) { - t.Fatal("a + 0 == a") - } - field.subAssign(a, zero) - if !a.equal(b) { - t.Fatal("a - 0 == a") - } - a.set(zero) - field.doubleAssign(a) - if !a.equal(zero) { - t.Fatal("2 * 0 == 0") - } - a.set(zero) - field.subAssign(a, b) - field.neg(b, b) - if !a.equal(b) { - t.Fatal("0-a == -a") - } - _, _ = a.rand(rand.Reader) - b.set(a) - field.doubleAssign(a) - field.addAssign(b, b) - if !a.equal(b) { - t.Fatal("2 * a == a + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1, c_2 := new(fe6).set(a), new(fe6).set(b) - field.addAssign(c_1, b) - field.addAssign(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c_1.set(a) - c_2.set(b) - field.subAssign(c_1, b) - field.subAssign(c_2, a) - field.neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - c, _ := new(fe6).rand(rand.Reader) - a0 := new(fe6).set(a) - field.addAssign(a, b) - field.addAssign(a, c) - field.addAssign(b, c) - field.addAssign(b, a0) - if !a.equal(b) { - t.Fatal("(a + b) + c == (b + c) + a") - } - _, _ = a.rand(rand.Reader) - _, _ = b.rand(rand.Reader) - _, _ = c.rand(rand.Reader) - a0.set(a) - field.subAssign(a, b) - field.subAssign(a, c) - field.subAssign(a0, c) - field.subAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a - b) - c == (a - c) -b") - } - } -} - -func TestFp6SparseMultiplication(t *testing.T) { - fp6 := newFp6(nil) - var a, b, u *fe6 - for j := 0; j < fuz; j++ { - a, _ = new(fe6).rand(rand.Reader) - b, _ = new(fe6).rand(rand.Reader) - u, _ = new(fe6).rand(rand.Reader) - b[2].zero() - fp6.mul(u, a, b) - fp6.mulBy01(a, a, &b[0], &b[1]) - if !a.equal(u) { - t.Fatal("bad mul by 01") - } - } - for j := 0; j < fuz; j++ { - a, _ = new(fe6).rand(rand.Reader) - b, _ = new(fe6).rand(rand.Reader) - u, _ = new(fe6).rand(rand.Reader) - b[2].zero() - b[0].zero() - fp6.mul(u, a, b) - fp6.mulBy1(a, a, &b[1]) - if !a.equal(u) { - t.Fatal("bad mul by 1") - } - } -} - -func TestFp6MultiplicationProperties(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe6).rand(rand.Reader) - b, _ := new(fe6).rand(rand.Reader) - zero := field.zero() - one := field.one() - c_1, c_2 := field.new(), field.new() - field.mul(c_1, a, zero) - if !c_1.equal(zero) { - t.Fatal("a * 0 == 0") - } - field.mul(c_1, a, one) - if !c_1.equal(a) { - t.Fatal("a * 1 == a") - } - field.mul(c_1, a, b) - field.mul(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a * b == b * a") - } - c_x, _ := new(fe6).rand(rand.Reader) - field.mul(c_1, a, b) - field.mul(c_1, c_1, c_x) - field.mul(c_2, c_x, b) - field.mul(c_2, c_2, a) - if !c_1.equal(c_2) { - t.Fatal("(a * b) * c == (a * c) * b") - } - field.square(a, zero) - if !a.equal(zero) { - t.Fatal("0^2 == 0") - } - field.square(a, one) - if !a.equal(one) { - t.Fatal("1^2 == 1") - } - _, _ = a.rand(rand.Reader) - field.square(c_1, a) - field.mul(c_2, a, a) - if !c_2.equal(c_1) { - t.Fatal("a^2 == a*a") - } - } -} - -func TestFp6MultiplicationPropertiesAssigned(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe6).rand(rand.Reader) - zero, one := new(fe6).zero(), new(fe6).one() - field.mulAssign(a, zero) - if !a.equal(zero) { - t.Fatal("a * 0 == 0") - } - _, _ = a.rand(rand.Reader) - a0 := new(fe6).set(a) - field.mulAssign(a, one) - if !a.equal(a0) { - t.Fatal("a * 1 == a") - } - _, _ = a.rand(rand.Reader) - b, _ := new(fe6).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(b, a0) - if !a.equal(b) { - t.Fatal("a * b == b * a") - } - c, _ := new(fe6).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(a, c) - field.mulAssign(a0, c) - field.mulAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a * b) * c == (a * c) * b") - } - } -} - -func TestFp6Exponentiation(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe6).rand(rand.Reader) - u := field.new() - field.exp(u, a, big.NewInt(0)) - if !u.equal(field.one()) { - t.Fatal("a^0 == 1") - } - field.exp(u, a, big.NewInt(1)) - if !u.equal(a) { - t.Fatal("a^1 == a") - } - v := field.new() - field.mul(u, a, a) - field.mul(u, u, u) - field.mul(u, u, u) - field.exp(v, a, big.NewInt(8)) - if !u.equal(v) { - t.Fatal("((a^2)^2)^2 == a^8") - } - } -} - -func TestFp6Inversion(t *testing.T) { - field := newFp6(nil) - for i := 0; i < fuz; i++ { - u := field.new() - zero := field.zero() - one := field.one() - field.inverse(u, zero) - if !u.equal(zero) { - t.Fatal("(0^-1) == 0)") - } - field.inverse(u, one) - if !u.equal(one) { - t.Fatal("(1^-1) == 1)") - } - a, _ := new(fe6).rand(rand.Reader) - field.inverse(u, a) - field.mul(u, u, a) - if !u.equal(one) { - t.Fatal("(r*a) * r*(a^-1) == r)") - } - } -} - -func TestFp12Serialization(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe12).rand(rand.Reader) - b, err := field.fromBytes(field.toBytes(a)) - if err != nil { - t.Fatal(err) - } - if !a.equal(b) { - t.Fatal("bad serialization") - } - } -} - -func TestFp12AdditionProperties(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - zero := field.zero() - a, _ := new(fe12).rand(rand.Reader) - b, _ := new(fe12).rand(rand.Reader) - c_1 := field.new() - c_2 := field.new() - field.add(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a + 0 == a") - } - field.sub(c_1, a, zero) - if !c_1.equal(a) { - t.Fatal("a - 0 == a") - } - field.double(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("2 * 0 == 0") - } - field.neg(c_1, zero) - if !c_1.equal(zero) { - t.Fatal("-0 == 0") - } - field.sub(c_1, zero, a) - field.neg(c_2, a) - if !c_1.equal(c_2) { - t.Fatal("0-a == -a") - } - field.double(c_1, a) - field.add(c_2, a, a) - if !c_1.equal(c_2) { - t.Fatal("2 * a == a + a") - } - field.add(c_1, a, b) - field.add(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a + b = b + a") - } - field.sub(c_1, a, b) - field.sub(c_2, b, a) - field.neg(c_2, c_2) - if !c_1.equal(c_2) { - t.Fatal("a - b = - ( b - a )") - } - c_x, _ := new(fe12).rand(rand.Reader) - field.add(c_1, a, b) - field.add(c_1, c_1, c_x) - field.add(c_2, a, c_x) - field.add(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - field.sub(c_1, a, b) - field.sub(c_1, c_1, c_x) - field.sub(c_2, a, c_x) - field.sub(c_2, c_2, b) - if !c_1.equal(c_2) { - t.Fatal("(a - b) - c == (a - c ) -b") - } - } -} - -func TestFp12MultiplicationProperties(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe12).rand(rand.Reader) - b, _ := new(fe12).rand(rand.Reader) - zero := field.zero() - one := field.one() - c_1, c_2 := field.new(), field.new() - field.mul(c_1, a, zero) - if !c_1.equal(zero) { - t.Fatal("a * 0 == 0") - } - field.mul(c_1, a, one) - if !c_1.equal(a) { - t.Fatal("a * 1 == a") - } - field.mul(c_1, a, b) - field.mul(c_2, b, a) - if !c_1.equal(c_2) { - t.Fatal("a * b == b * a") - } - c_x, _ := new(fe12).rand(rand.Reader) - field.mul(c_1, a, b) - field.mul(c_1, c_1, c_x) - field.mul(c_2, c_x, b) - field.mul(c_2, c_2, a) - if !c_1.equal(c_2) { - t.Fatal("(a * b) * c == (a * c) * b") - } - field.square(a, zero) - if !a.equal(zero) { - t.Fatal("0^2 == 0") - } - field.square(a, one) - if !a.equal(one) { - t.Fatal("1^2 == 1") - } - _, _ = a.rand(rand.Reader) - field.square(c_1, a) - field.mul(c_2, a, a) - if !c_2.equal(c_1) { - t.Fatal("a^2 == a*a") - } - } -} - -func TestFp12MultiplicationPropertiesAssigned(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe12).rand(rand.Reader) - zero, one := new(fe12).zero(), new(fe12).one() - field.mulAssign(a, zero) - if !a.equal(zero) { - t.Fatal("a * 0 == 0") - } - _, _ = a.rand(rand.Reader) - a0 := new(fe12).set(a) - field.mulAssign(a, one) - if !a.equal(a0) { - t.Fatal("a * 1 == a") - } - _, _ = a.rand(rand.Reader) - b, _ := new(fe12).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(b, a0) - if !a.equal(b) { - t.Fatal("a * b == b * a") - } - c, _ := new(fe12).rand(rand.Reader) - a0.set(a) - field.mulAssign(a, b) - field.mulAssign(a, c) - field.mulAssign(a0, c) - field.mulAssign(a0, b) - if !a.equal(a0) { - t.Fatal("(a * b) * c == (a * c) * b") - } - } -} - -func TestFp12SparseMultiplication(t *testing.T) { - fp12 := newFp12(nil) - var a, b, u *fe12 - for j := 0; j < fuz; j++ { - a, _ = new(fe12).rand(rand.Reader) - b, _ = new(fe12).rand(rand.Reader) - u, _ = new(fe12).rand(rand.Reader) - b[0][2].zero() - b[1][0].zero() - b[1][2].zero() - fp12.mul(u, a, b) - fp12.mulBy014Assign(a, &b[0][0], &b[0][1], &b[1][1]) - if !a.equal(u) { - t.Fatal("bad mul by 01") - } - } -} - -func TestFp12Exponentiation(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - a, _ := new(fe12).rand(rand.Reader) - u := field.new() - field.exp(u, a, big.NewInt(0)) - if !u.equal(field.one()) { - t.Fatal("a^0 == 1") - } - field.exp(u, a, big.NewInt(1)) - if !u.equal(a) { - t.Fatal("a^1 == a") - } - v := field.new() - field.mul(u, a, a) - field.mul(u, u, u) - field.mul(u, u, u) - field.exp(v, a, big.NewInt(8)) - if !u.equal(v) { - t.Fatal("((a^2)^2)^2 == a^8") - } - } -} - -func TestFp12Inversion(t *testing.T) { - field := newFp12(nil) - for i := 0; i < fuz; i++ { - u := field.new() - zero := field.zero() - one := field.one() - field.inverse(u, zero) - if !u.equal(zero) { - t.Fatal("(0^-1) == 0)") - } - field.inverse(u, one) - if !u.equal(one) { - t.Fatal("(1^-1) == 1)") - } - a, _ := new(fe12).rand(rand.Reader) - field.inverse(u, a) - field.mul(u, u, a) - if !u.equal(one) { - t.Fatal("(r*a) * r*(a^-1) == r)") - } - } -} - -func BenchmarkMultiplication(t *testing.B) { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - c, _ := new(fe).rand(rand.Reader) - t.ResetTimer() - for i := 0; i < t.N; i++ { - mul(c, a, b) - } -} - -func BenchmarkInverse(t *testing.B) { - a, _ := new(fe).rand(rand.Reader) - b, _ := new(fe).rand(rand.Reader) - t.ResetTimer() - for i := 0; i < t.N; i++ { - inverse(a, b) - } -} - -func padBytes(in []byte, size int) []byte { - out := make([]byte, size) - if len(in) > size { - panic("bad input for padding") - } - copy(out[size-len(in):], in) - return out -} diff --git a/builder/crypto/bls12381/g1.go b/builder/crypto/bls12381/g1.go deleted file mode 100644 index bcb898027..000000000 --- a/builder/crypto/bls12381/g1.go +++ /dev/null @@ -1,434 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math" - "math/big" -) - -// PointG1 is type for point in G1. -// PointG1 is both used for Affine and Jacobian point representation. -// If z is equal to one the point is considered as in affine form. -type PointG1 [3]fe - -func (p *PointG1) Set(p2 *PointG1) *PointG1 { - p[0].set(&p2[0]) - p[1].set(&p2[1]) - p[2].set(&p2[2]) - return p -} - -// Zero returns G1 point in point at infinity representation -func (p *PointG1) Zero() *PointG1 { - p[0].zero() - p[1].one() - p[2].zero() - return p -} - -type tempG1 struct { - t [9]*fe -} - -// G1 is struct for G1 group. -type G1 struct { - tempG1 -} - -// NewG1 constructs a new G1 instance. -func NewG1() *G1 { - t := newTempG1() - return &G1{t} -} - -func newTempG1() tempG1 { - t := [9]*fe{} - for i := 0; i < 9; i++ { - t[i] = &fe{} - } - return tempG1{t} -} - -// Q returns group order in big.Int. -func (g *G1) Q() *big.Int { - return new(big.Int).Set(q) -} - -func (g *G1) fromBytesUnchecked(in []byte) (*PointG1, error) { - p0, err := fromBytes(in[:48]) - if err != nil { - return nil, err - } - p1, err := fromBytes(in[48:]) - if err != nil { - return nil, err - } - p2 := new(fe).one() - return &PointG1{*p0, *p1, *p2}, nil -} - -// FromBytes constructs a new point given uncompressed byte input. -// FromBytes does not take zcash flags into account. -// Byte input expected to be larger than 96 bytes. -// First 96 bytes should be concatenation of x and y values. -// Point (0, 0) is considered as infinity. -func (g *G1) FromBytes(in []byte) (*PointG1, error) { - if len(in) != 96 { - return nil, errors.New("input string should be equal or larger than 96") - } - p0, err := fromBytes(in[:48]) - if err != nil { - return nil, err - } - p1, err := fromBytes(in[48:]) - if err != nil { - return nil, err - } - // check if given input points to infinity - if p0.isZero() && p1.isZero() { - return g.Zero(), nil - } - p2 := new(fe).one() - p := &PointG1{*p0, *p1, *p2} - if !g.IsOnCurve(p) { - return nil, errors.New("point is not on curve") - } - return p, nil -} - -// DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point. -func (g *G1) DecodePoint(in []byte) (*PointG1, error) { - if len(in) != 128 { - return nil, errors.New("invalid g1 point length") - } - pointBytes := make([]byte, 96) - // decode x - xBytes, err := decodeFieldElement(in[:64]) - if err != nil { - return nil, err - } - // decode y - yBytes, err := decodeFieldElement(in[64:]) - if err != nil { - return nil, err - } - copy(pointBytes[:48], xBytes) - copy(pointBytes[48:], yBytes) - return g.FromBytes(pointBytes) -} - -// ToBytes serializes a point into bytes in uncompressed form. -// ToBytes does not take zcash flags into account. -// ToBytes returns (0, 0) if point is infinity. -func (g *G1) ToBytes(p *PointG1) []byte { - out := make([]byte, 96) - if g.IsZero(p) { - return out - } - g.Affine(p) - copy(out[:48], toBytes(&p[0])) - copy(out[48:], toBytes(&p[1])) - return out -} - -// EncodePoint encodes a point into 128 bytes. -func (g *G1) EncodePoint(p *PointG1) []byte { - outRaw := g.ToBytes(p) - out := make([]byte, 128) - // encode x - copy(out[16:], outRaw[:48]) - // encode y - copy(out[64+16:], outRaw[48:]) - return out -} - -// New creates a new G1 Point which is equal to zero in other words point at infinity. -func (g *G1) New() *PointG1 { - return g.Zero() -} - -// Zero returns a new G1 Point which is equal to point at infinity. -func (g *G1) Zero() *PointG1 { - return new(PointG1).Zero() -} - -// One returns a new G1 Point which is equal to generator point. -func (g *G1) One() *PointG1 { - p := &PointG1{} - return p.Set(&g1One) -} - -// IsZero returns true if given point is equal to zero. -func (g *G1) IsZero(p *PointG1) bool { - return p[2].isZero() -} - -// Equal checks if given two G1 point is equal in their affine form. -func (g *G1) Equal(p1, p2 *PointG1) bool { - if g.IsZero(p1) { - return g.IsZero(p2) - } - if g.IsZero(p2) { - return g.IsZero(p1) - } - t := g.t - square(t[0], &p1[2]) - square(t[1], &p2[2]) - mul(t[2], t[0], &p2[0]) - mul(t[3], t[1], &p1[0]) - mul(t[0], t[0], &p1[2]) - mul(t[1], t[1], &p2[2]) - mul(t[1], t[1], &p1[1]) - mul(t[0], t[0], &p2[1]) - return t[0].equal(t[1]) && t[2].equal(t[3]) -} - -// InCorrectSubgroup checks whether given point is in correct subgroup. -func (g *G1) InCorrectSubgroup(p *PointG1) bool { - tmp := &PointG1{} - g.MulScalar(tmp, p, q) - return g.IsZero(tmp) -} - -// IsOnCurve checks a G1 point is on curve. -func (g *G1) IsOnCurve(p *PointG1) bool { - if g.IsZero(p) { - return true - } - t := g.t - square(t[0], &p[1]) - square(t[1], &p[0]) - mul(t[1], t[1], &p[0]) - square(t[2], &p[2]) - square(t[3], t[2]) - mul(t[2], t[2], t[3]) - mul(t[2], b, t[2]) - add(t[1], t[1], t[2]) - return t[0].equal(t[1]) -} - -// IsAffine checks a G1 point whether it is in affine form. -func (g *G1) IsAffine(p *PointG1) bool { - return p[2].isOne() -} - -// Affine calculates affine form of given G1 point. -func (g *G1) Affine(p *PointG1) *PointG1 { - if g.IsZero(p) { - return p - } - if !g.IsAffine(p) { - t := g.t - inverse(t[0], &p[2]) - square(t[1], t[0]) - mul(&p[0], &p[0], t[1]) - mul(t[0], t[0], t[1]) - mul(&p[1], &p[1], t[0]) - p[2].one() - } - return p -} - -// Add adds two G1 points p1, p2 and assigns the result to point at first argument. -func (g *G1) Add(r, p1, p2 *PointG1) *PointG1 { - // www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - if g.IsZero(p1) { - return r.Set(p2) - } - if g.IsZero(p2) { - return r.Set(p1) - } - t := g.t - square(t[7], &p1[2]) - mul(t[1], &p2[0], t[7]) - mul(t[2], &p1[2], t[7]) - mul(t[0], &p2[1], t[2]) - square(t[8], &p2[2]) - mul(t[3], &p1[0], t[8]) - mul(t[4], &p2[2], t[8]) - mul(t[2], &p1[1], t[4]) - if t[1].equal(t[3]) { - if t[0].equal(t[2]) { - return g.Double(r, p1) - } - return r.Zero() - } - sub(t[1], t[1], t[3]) - double(t[4], t[1]) - square(t[4], t[4]) - mul(t[5], t[1], t[4]) - sub(t[0], t[0], t[2]) - double(t[0], t[0]) - square(t[6], t[0]) - sub(t[6], t[6], t[5]) - mul(t[3], t[3], t[4]) - double(t[4], t[3]) - sub(&r[0], t[6], t[4]) - sub(t[4], t[3], &r[0]) - mul(t[6], t[2], t[5]) - double(t[6], t[6]) - mul(t[0], t[0], t[4]) - sub(&r[1], t[0], t[6]) - add(t[0], &p1[2], &p2[2]) - square(t[0], t[0]) - sub(t[0], t[0], t[7]) - sub(t[0], t[0], t[8]) - mul(&r[2], t[0], t[1]) - return r -} - -// Double doubles a G1 point p and assigns the result to the point at first argument. -func (g *G1) Double(r, p *PointG1) *PointG1 { - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - if g.IsZero(p) { - return r.Set(p) - } - t := g.t - square(t[0], &p[0]) - square(t[1], &p[1]) - square(t[2], t[1]) - add(t[1], &p[0], t[1]) - square(t[1], t[1]) - sub(t[1], t[1], t[0]) - sub(t[1], t[1], t[2]) - double(t[1], t[1]) - double(t[3], t[0]) - add(t[0], t[3], t[0]) - square(t[4], t[0]) - double(t[3], t[1]) - sub(&r[0], t[4], t[3]) - sub(t[1], t[1], &r[0]) - double(t[2], t[2]) - double(t[2], t[2]) - double(t[2], t[2]) - mul(t[0], t[0], t[1]) - sub(t[1], t[0], t[2]) - mul(t[0], &p[1], &p[2]) - r[1].set(t[1]) - double(&r[2], t[0]) - return r -} - -// Neg negates a G1 point p and assigns the result to the point at first argument. -func (g *G1) Neg(r, p *PointG1) *PointG1 { - r[0].set(&p[0]) - r[2].set(&p[2]) - neg(&r[1], &p[1]) - return r -} - -// Sub subtracts two G1 points p1, p2 and assigns the result to point at first argument. -func (g *G1) Sub(c, a, b *PointG1) *PointG1 { - d := &PointG1{} - g.Neg(d, b) - g.Add(c, a, d) - return c -} - -// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument. -func (g *G1) MulScalar(c, p *PointG1, e *big.Int) *PointG1 { - q, n := &PointG1{}, &PointG1{} - n.Set(p) - l := e.BitLen() - for i := 0; i < l; i++ { - if e.Bit(i) == 1 { - g.Add(q, q, n) - } - g.Double(n, n) - } - return c.Set(q) -} - -// ClearCofactor maps given a G1 point to correct subgroup -func (g *G1) ClearCofactor(p *PointG1) { - g.MulScalar(p, p, cofactorEFFG1) -} - -// MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values -// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n -// Length of points and scalars are expected to be equal, otherwise an error is returned. -// Result is assigned to point at first argument. -func (g *G1) MultiExp(r *PointG1, points []*PointG1, powers []*big.Int) (*PointG1, error) { - if len(points) != len(powers) { - return nil, errors.New("point and scalar vectors should be in same length") - } - var c uint32 = 3 - if len(powers) >= 32 { - c = uint32(math.Ceil(math.Log10(float64(len(powers))))) - } - bucketSize, numBits := (1<= 0; i-- { - g.Add(sum, sum, bucket[i]) - g.Add(acc, acc, sum) - } - windows[j] = g.New() - windows[j].Set(acc) - j++ - cur += c - } - acc.Zero() - for i := len(windows) - 1; i >= 0; i-- { - for j := uint32(0); j < c; j++ { - g.Double(acc, acc) - } - g.Add(acc, acc, windows[i]) - } - return r.Set(acc), nil -} - -// MapToCurve given a byte slice returns a valid G1 point. -// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method. -// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06 -// Input byte slice should be a valid field element, otherwise an error is returned. -func (g *G1) MapToCurve(in []byte) (*PointG1, error) { - u, err := fromBytes(in) - if err != nil { - return nil, err - } - x, y := swuMapG1(u) - isogenyMapG1(x, y) - one := new(fe).one() - p := &PointG1{*x, *y, *one} - g.ClearCofactor(p) - return g.Affine(p), nil -} diff --git a/builder/crypto/bls12381/g1_test.go b/builder/crypto/bls12381/g1_test.go deleted file mode 100644 index 87140459f..000000000 --- a/builder/crypto/bls12381/g1_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package bls12381 - -import ( - "bytes" - "crypto/rand" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func (g *G1) one() *PointG1 { - one, _ := g.fromBytesUnchecked( - common.FromHex("" + - "17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb" + - "08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", - ), - ) - return one -} - -func (g *G1) rand() *PointG1 { - k, err := rand.Int(rand.Reader, q) - if err != nil { - panic(err) - } - return g.MulScalar(&PointG1{}, g.one(), k) -} - -func TestG1Serialization(t *testing.T) { - g1 := NewG1() - for i := 0; i < fuz; i++ { - a := g1.rand() - buf := g1.ToBytes(a) - b, err := g1.FromBytes(buf) - if err != nil { - t.Fatal(err) - } - if !g1.Equal(a, b) { - t.Fatal("bad serialization from/to") - } - } - for i := 0; i < fuz; i++ { - a := g1.rand() - encoded := g1.EncodePoint(a) - b, err := g1.DecodePoint(encoded) - if err != nil { - t.Fatal(err) - } - if !g1.Equal(a, b) { - t.Fatal("bad serialization encode/decode") - } - } -} - -func TestG1IsOnCurve(t *testing.T) { - g := NewG1() - zero := g.Zero() - if !g.IsOnCurve(zero) { - t.Fatal("zero must be on curve") - } - one := new(fe).one() - p := &PointG1{*one, *one, *one} - if g.IsOnCurve(p) { - t.Fatal("(1, 1) is not on curve") - } -} - -func TestG1AdditiveProperties(t *testing.T) { - g := NewG1() - t0, t1 := g.New(), g.New() - zero := g.Zero() - for i := 0; i < fuz; i++ { - a, b := g.rand(), g.rand() - g.Add(t0, a, zero) - if !g.Equal(t0, a) { - t.Fatal("a + 0 == a") - } - g.Add(t0, zero, zero) - if !g.Equal(t0, zero) { - t.Fatal("0 + 0 == 0") - } - g.Sub(t0, a, zero) - if !g.Equal(t0, a) { - t.Fatal("a - 0 == a") - } - g.Sub(t0, zero, zero) - if !g.Equal(t0, zero) { - t.Fatal("0 - 0 == 0") - } - g.Neg(t0, zero) - if !g.Equal(t0, zero) { - t.Fatal("- 0 == 0") - } - g.Sub(t0, zero, a) - g.Neg(t0, t0) - if !g.Equal(t0, a) { - t.Fatal(" - (0 - a) == a") - } - g.Double(t0, zero) - if !g.Equal(t0, zero) { - t.Fatal("2 * 0 == 0") - } - g.Double(t0, a) - g.Sub(t0, t0, a) - if !g.Equal(t0, a) || !g.IsOnCurve(t0) { - t.Fatal(" (2 * a) - a == a") - } - g.Add(t0, a, b) - g.Add(t1, b, a) - if !g.Equal(t0, t1) { - t.Fatal("a + b == b + a") - } - g.Sub(t0, a, b) - g.Sub(t1, b, a) - g.Neg(t1, t1) - if !g.Equal(t0, t1) { - t.Fatal("a - b == - ( b - a )") - } - c := g.rand() - g.Add(t0, a, b) - g.Add(t0, t0, c) - g.Add(t1, a, c) - g.Add(t1, t1, b) - if !g.Equal(t0, t1) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - g.Sub(t0, a, b) - g.Sub(t0, t0, c) - g.Sub(t1, a, c) - g.Sub(t1, t1, b) - if !g.Equal(t0, t1) { - t.Fatal("(a - b) - c == (a - c) -b") - } - } -} - -func TestG1MultiplicativeProperties(t *testing.T) { - g := NewG1() - t0, t1 := g.New(), g.New() - zero := g.Zero() - for i := 0; i < fuz; i++ { - a := g.rand() - s1, s2, s3 := randScalar(q), randScalar(q), randScalar(q) - sone := big.NewInt(1) - g.MulScalar(t0, zero, s1) - if !g.Equal(t0, zero) { - t.Fatal(" 0 ^ s == 0") - } - g.MulScalar(t0, a, sone) - if !g.Equal(t0, a) { - t.Fatal(" a ^ 1 == a") - } - g.MulScalar(t0, zero, s1) - if !g.Equal(t0, zero) { - t.Fatal(" 0 ^ s == a") - } - g.MulScalar(t0, a, s1) - g.MulScalar(t0, t0, s2) - s3.Mul(s1, s2) - g.MulScalar(t1, a, s3) - if !g.Equal(t0, t1) { - t.Errorf(" (a ^ s1) ^ s2 == a ^ (s1 * s2)") - } - g.MulScalar(t0, a, s1) - g.MulScalar(t1, a, s2) - g.Add(t0, t0, t1) - s3.Add(s1, s2) - g.MulScalar(t1, a, s3) - if !g.Equal(t0, t1) { - t.Errorf(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)") - } - } -} - -func TestG1MultiExpExpected(t *testing.T) { - g := NewG1() - one := g.one() - var scalars [2]*big.Int - var bases [2]*PointG1 - scalars[0] = big.NewInt(2) - scalars[1] = big.NewInt(3) - bases[0], bases[1] = new(PointG1).Set(one), new(PointG1).Set(one) - expected, result := g.New(), g.New() - g.MulScalar(expected, one, big.NewInt(5)) - _, _ = g.MultiExp(result, bases[:], scalars[:]) - if !g.Equal(expected, result) { - t.Fatal("bad multi-exponentiation") - } -} - -func TestG1MultiExpBatch(t *testing.T) { - g := NewG1() - one := g.one() - n := 1000 - bases := make([]*PointG1, n) - scalars := make([]*big.Int, n) - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] - for i, j := 0, n-1; i < n; i, j = i+1, j-1 { - scalars[j], _ = rand.Int(rand.Reader, big.NewInt(100000)) - bases[i] = g.New() - g.MulScalar(bases[i], one, scalars[j]) - } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) - expected, tmp := g.New(), g.New() - for i := 0; i < n; i++ { - g.MulScalar(tmp, bases[i], scalars[i]) - g.Add(expected, expected, tmp) - } - result := g.New() - _, _ = g.MultiExp(result, bases, scalars) - if !g.Equal(expected, result) { - t.Fatal("bad multi-exponentiation") - } -} - -func TestG1MapToCurve(t *testing.T) { - for i, v := range []struct { - u []byte - expected []byte - }{ - { - u: make([]byte, 48), - expected: common.FromHex("11a9a0372b8f332d5c30de9ad14e50372a73fa4c45d5f2fa5097f2d6fb93bcac592f2e1711ac43db0519870c7d0ea415" + "092c0f994164a0719f51c24ba3788de240ff926b55f58c445116e8bc6a47cd63392fd4e8e22bdf9feaa96ee773222133"), - }, - { - u: common.FromHex("07fdf49ea58e96015d61f6b5c9d1c8f277146a533ae7fbca2a8ef4c41055cd961fbc6e26979b5554e4b4f22330c0e16d"), - expected: common.FromHex("1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c" + "0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5"), - }, - { - u: common.FromHex("1275ab3adbf824a169ed4b1fd669b49cf406d822f7fe90d6b2f8c601b5348436f89761bb1ad89a6fb1137cd91810e5d2"), - expected: common.FromHex("179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6" + "0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4"), - }, - { - u: common.FromHex("0e93d11d30de6d84b8578827856f5c05feef36083eef0b7b263e35ecb9b56e86299614a042e57d467fa20948e8564909"), - expected: common.FromHex("15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af" + "0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788"), - }, - { - u: common.FromHex("015a41481155d17074d20be6d8ec4d46632a51521cd9c916e265bd9b47343b3689979b50708c8546cbc2916b86cb1a3a"), - expected: common.FromHex("06328ce5106e837935e8da84bd9af473422e62492930aa5f460369baad9545defa468d9399854c23a75495d2a80487ee" + "094bfdfe3e552447433b5a00967498a3f1314b86ce7a7164c8a8f4131f99333b30a574607e301d5f774172c627fd0bca"), - }, - } { - g := NewG1() - p0, err := g.MapToCurve(v.u) - if err != nil { - t.Fatal("map to curve fails", i, err) - } - if !bytes.Equal(g.ToBytes(p0), v.expected) { - t.Fatal("map to curve fails", i) - } - } -} - -func BenchmarkG1Add(t *testing.B) { - g1 := NewG1() - a, b, c := g1.rand(), g1.rand(), PointG1{} - t.ResetTimer() - for i := 0; i < t.N; i++ { - g1.Add(&c, a, b) - } -} - -func BenchmarkG1Mul(t *testing.B) { - worstCaseScalar, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16) - g1 := NewG1() - a, e, c := g1.rand(), worstCaseScalar, PointG1{} - t.ResetTimer() - for i := 0; i < t.N; i++ { - g1.MulScalar(&c, a, e) - } -} - -func BenchmarkG1MapToCurve(t *testing.B) { - a := make([]byte, 48) - g1 := NewG1() - t.ResetTimer() - for i := 0; i < t.N; i++ { - _, err := g1.MapToCurve(a) - if err != nil { - t.Fatal(err) - } - } -} diff --git a/builder/crypto/bls12381/g2.go b/builder/crypto/bls12381/g2.go deleted file mode 100644 index b942bf94f..000000000 --- a/builder/crypto/bls12381/g2.go +++ /dev/null @@ -1,455 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math" - "math/big" -) - -// PointG2 is type for point in G2. -// PointG2 is both used for Affine and Jacobian point representation. -// If z is equal to one the point is considered as in affine form. -type PointG2 [3]fe2 - -// Set copies values of one point to another. -func (p *PointG2) Set(p2 *PointG2) *PointG2 { - p[0].set(&p2[0]) - p[1].set(&p2[1]) - p[2].set(&p2[2]) - return p -} - -// Zero returns G2 point in point at infinity representation -func (p *PointG2) Zero() *PointG2 { - p[0].zero() - p[1].one() - p[2].zero() - return p -} - -type tempG2 struct { - t [9]*fe2 -} - -// G2 is struct for G2 group. -type G2 struct { - f *fp2 - tempG2 -} - -// NewG2 constructs a new G2 instance. -func NewG2() *G2 { - return newG2(nil) -} - -func newG2(f *fp2) *G2 { - if f == nil { - f = newFp2() - } - t := newTempG2() - return &G2{f, t} -} - -func newTempG2() tempG2 { - t := [9]*fe2{} - for i := 0; i < 9; i++ { - t[i] = &fe2{} - } - return tempG2{t} -} - -// Q returns group order in big.Int. -func (g *G2) Q() *big.Int { - return new(big.Int).Set(q) -} - -func (g *G2) fromBytesUnchecked(in []byte) (*PointG2, error) { - p0, err := g.f.fromBytes(in[:96]) - if err != nil { - return nil, err - } - p1, err := g.f.fromBytes(in[96:]) - if err != nil { - return nil, err - } - p2 := new(fe2).one() - return &PointG2{*p0, *p1, *p2}, nil -} - -// FromBytes constructs a new point given uncompressed byte input. -// FromBytes does not take zcash flags into account. -// Byte input expected to be larger than 96 bytes. -// First 192 bytes should be concatenation of x and y values -// Point (0, 0) is considered as infinity. -func (g *G2) FromBytes(in []byte) (*PointG2, error) { - if len(in) != 192 { - return nil, errors.New("input string should be equal or larger than 192") - } - p0, err := g.f.fromBytes(in[:96]) - if err != nil { - return nil, err - } - p1, err := g.f.fromBytes(in[96:]) - if err != nil { - return nil, err - } - // check if given input points to infinity - if p0.isZero() && p1.isZero() { - return g.Zero(), nil - } - p2 := new(fe2).one() - p := &PointG2{*p0, *p1, *p2} - if !g.IsOnCurve(p) { - return nil, errors.New("point is not on curve") - } - return p, nil -} - -// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G2 Point. -func (g *G2) DecodePoint(in []byte) (*PointG2, error) { - if len(in) != 256 { - return nil, errors.New("invalid g2 point length") - } - pointBytes := make([]byte, 192) - x0Bytes, err := decodeFieldElement(in[:64]) - if err != nil { - return nil, err - } - x1Bytes, err := decodeFieldElement(in[64:128]) - if err != nil { - return nil, err - } - y0Bytes, err := decodeFieldElement(in[128:192]) - if err != nil { - return nil, err - } - y1Bytes, err := decodeFieldElement(in[192:]) - if err != nil { - return nil, err - } - copy(pointBytes[:48], x1Bytes) - copy(pointBytes[48:96], x0Bytes) - copy(pointBytes[96:144], y1Bytes) - copy(pointBytes[144:192], y0Bytes) - return g.FromBytes(pointBytes) -} - -// ToBytes serializes a point into bytes in uncompressed form, -// does not take zcash flags into account, -// returns (0, 0) if point is infinity. -func (g *G2) ToBytes(p *PointG2) []byte { - out := make([]byte, 192) - if g.IsZero(p) { - return out - } - g.Affine(p) - copy(out[:96], g.f.toBytes(&p[0])) - copy(out[96:], g.f.toBytes(&p[1])) - return out -} - -// EncodePoint encodes a point into 256 bytes. -func (g *G2) EncodePoint(p *PointG2) []byte { - // outRaw is 96 bytes - outRaw := g.ToBytes(p) - out := make([]byte, 256) - // encode x - copy(out[16:16+48], outRaw[48:96]) - copy(out[80:80+48], outRaw[:48]) - // encode y - copy(out[144:144+48], outRaw[144:]) - copy(out[208:208+48], outRaw[96:144]) - return out -} - -// New creates a new G2 Point which is equal to zero in other words point at infinity. -func (g *G2) New() *PointG2 { - return new(PointG2).Zero() -} - -// Zero returns a new G2 Point which is equal to point at infinity. -func (g *G2) Zero() *PointG2 { - return new(PointG2).Zero() -} - -// One returns a new G2 Point which is equal to generator point. -func (g *G2) One() *PointG2 { - p := &PointG2{} - return p.Set(&g2One) -} - -// IsZero returns true if given point is equal to zero. -func (g *G2) IsZero(p *PointG2) bool { - return p[2].isZero() -} - -// Equal checks if given two G2 point is equal in their affine form. -func (g *G2) Equal(p1, p2 *PointG2) bool { - if g.IsZero(p1) { - return g.IsZero(p2) - } - if g.IsZero(p2) { - return g.IsZero(p1) - } - t := g.t - g.f.square(t[0], &p1[2]) - g.f.square(t[1], &p2[2]) - g.f.mul(t[2], t[0], &p2[0]) - g.f.mul(t[3], t[1], &p1[0]) - g.f.mul(t[0], t[0], &p1[2]) - g.f.mul(t[1], t[1], &p2[2]) - g.f.mul(t[1], t[1], &p1[1]) - g.f.mul(t[0], t[0], &p2[1]) - return t[0].equal(t[1]) && t[2].equal(t[3]) -} - -// InCorrectSubgroup checks whether given point is in correct subgroup. -func (g *G2) InCorrectSubgroup(p *PointG2) bool { - tmp := &PointG2{} - g.MulScalar(tmp, p, q) - return g.IsZero(tmp) -} - -// IsOnCurve checks a G2 point is on curve. -func (g *G2) IsOnCurve(p *PointG2) bool { - if g.IsZero(p) { - return true - } - t := g.t - g.f.square(t[0], &p[1]) - g.f.square(t[1], &p[0]) - g.f.mul(t[1], t[1], &p[0]) - g.f.square(t[2], &p[2]) - g.f.square(t[3], t[2]) - g.f.mul(t[2], t[2], t[3]) - g.f.mul(t[2], b2, t[2]) - g.f.add(t[1], t[1], t[2]) - return t[0].equal(t[1]) -} - -// IsAffine checks a G2 point whether it is in affine form. -func (g *G2) IsAffine(p *PointG2) bool { - return p[2].isOne() -} - -// Affine calculates affine form of given G2 point. -func (g *G2) Affine(p *PointG2) *PointG2 { - if g.IsZero(p) { - return p - } - if !g.IsAffine(p) { - t := g.t - g.f.inverse(t[0], &p[2]) - g.f.square(t[1], t[0]) - g.f.mul(&p[0], &p[0], t[1]) - g.f.mul(t[0], t[0], t[1]) - g.f.mul(&p[1], &p[1], t[0]) - p[2].one() - } - return p -} - -// Add adds two G2 points p1, p2 and assigns the result to point at first argument. -func (g *G2) Add(r, p1, p2 *PointG2) *PointG2 { - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - if g.IsZero(p1) { - return r.Set(p2) - } - if g.IsZero(p2) { - return r.Set(p1) - } - t := g.t - g.f.square(t[7], &p1[2]) - g.f.mul(t[1], &p2[0], t[7]) - g.f.mul(t[2], &p1[2], t[7]) - g.f.mul(t[0], &p2[1], t[2]) - g.f.square(t[8], &p2[2]) - g.f.mul(t[3], &p1[0], t[8]) - g.f.mul(t[4], &p2[2], t[8]) - g.f.mul(t[2], &p1[1], t[4]) - if t[1].equal(t[3]) { - if t[0].equal(t[2]) { - return g.Double(r, p1) - } - return r.Zero() - } - g.f.sub(t[1], t[1], t[3]) - g.f.double(t[4], t[1]) - g.f.square(t[4], t[4]) - g.f.mul(t[5], t[1], t[4]) - g.f.sub(t[0], t[0], t[2]) - g.f.double(t[0], t[0]) - g.f.square(t[6], t[0]) - g.f.sub(t[6], t[6], t[5]) - g.f.mul(t[3], t[3], t[4]) - g.f.double(t[4], t[3]) - g.f.sub(&r[0], t[6], t[4]) - g.f.sub(t[4], t[3], &r[0]) - g.f.mul(t[6], t[2], t[5]) - g.f.double(t[6], t[6]) - g.f.mul(t[0], t[0], t[4]) - g.f.sub(&r[1], t[0], t[6]) - g.f.add(t[0], &p1[2], &p2[2]) - g.f.square(t[0], t[0]) - g.f.sub(t[0], t[0], t[7]) - g.f.sub(t[0], t[0], t[8]) - g.f.mul(&r[2], t[0], t[1]) - return r -} - -// Double doubles a G2 point p and assigns the result to the point at first argument. -func (g *G2) Double(r, p *PointG2) *PointG2 { - // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - if g.IsZero(p) { - return r.Set(p) - } - t := g.t - g.f.square(t[0], &p[0]) - g.f.square(t[1], &p[1]) - g.f.square(t[2], t[1]) - g.f.add(t[1], &p[0], t[1]) - g.f.square(t[1], t[1]) - g.f.sub(t[1], t[1], t[0]) - g.f.sub(t[1], t[1], t[2]) - g.f.double(t[1], t[1]) - g.f.double(t[3], t[0]) - g.f.add(t[0], t[3], t[0]) - g.f.square(t[4], t[0]) - g.f.double(t[3], t[1]) - g.f.sub(&r[0], t[4], t[3]) - g.f.sub(t[1], t[1], &r[0]) - g.f.double(t[2], t[2]) - g.f.double(t[2], t[2]) - g.f.double(t[2], t[2]) - g.f.mul(t[0], t[0], t[1]) - g.f.sub(t[1], t[0], t[2]) - g.f.mul(t[0], &p[1], &p[2]) - r[1].set(t[1]) - g.f.double(&r[2], t[0]) - return r -} - -// Neg negates a G2 point p and assigns the result to the point at first argument. -func (g *G2) Neg(r, p *PointG2) *PointG2 { - r[0].set(&p[0]) - g.f.neg(&r[1], &p[1]) - r[2].set(&p[2]) - return r -} - -// Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument. -func (g *G2) Sub(c, a, b *PointG2) *PointG2 { - d := &PointG2{} - g.Neg(d, b) - g.Add(c, a, d) - return c -} - -// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument. -func (g *G2) MulScalar(c, p *PointG2, e *big.Int) *PointG2 { - q, n := &PointG2{}, &PointG2{} - n.Set(p) - l := e.BitLen() - for i := 0; i < l; i++ { - if e.Bit(i) == 1 { - g.Add(q, q, n) - } - g.Double(n, n) - } - return c.Set(q) -} - -// ClearCofactor maps given a G2 point to correct subgroup -func (g *G2) ClearCofactor(p *PointG2) { - g.MulScalar(p, p, cofactorEFFG2) -} - -// MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values -// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n -// Length of points and scalars are expected to be equal, otherwise an error is returned. -// Result is assigned to point at first argument. -func (g *G2) MultiExp(r *PointG2, points []*PointG2, powers []*big.Int) (*PointG2, error) { - if len(points) != len(powers) { - return nil, errors.New("point and scalar vectors should be in same length") - } - var c uint32 = 3 - if len(powers) >= 32 { - c = uint32(math.Ceil(math.Log10(float64(len(powers))))) - } - bucketSize, numBits := (1<= 0; i-- { - g.Add(sum, sum, bucket[i]) - g.Add(acc, acc, sum) - } - windows[j] = g.New() - windows[j].Set(acc) - j++ - cur += c - } - acc.Zero() - for i := len(windows) - 1; i >= 0; i-- { - for j := uint32(0); j < c; j++ { - g.Double(acc, acc) - } - g.Add(acc, acc, windows[i]) - } - return r.Set(acc), nil -} - -// MapToCurve given a byte slice returns a valid G2 point. -// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method. -// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2 -// Input byte slice should be a valid field element, otherwise an error is returned. -func (g *G2) MapToCurve(in []byte) (*PointG2, error) { - fp2 := g.f - u, err := fp2.fromBytes(in) - if err != nil { - return nil, err - } - x, y := swuMapG2(fp2, u) - isogenyMapG2(fp2, x, y) - z := new(fe2).one() - q := &PointG2{*x, *y, *z} - g.ClearCofactor(q) - return g.Affine(q), nil -} diff --git a/builder/crypto/bls12381/g2_test.go b/builder/crypto/bls12381/g2_test.go deleted file mode 100644 index 4d1f3a19a..000000000 --- a/builder/crypto/bls12381/g2_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package bls12381 - -import ( - "bytes" - "crypto/rand" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func (g *G2) one() *PointG2 { - one, _ := g.fromBytesUnchecked( - common.FromHex("" + - "13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e" + - "024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8" + - "0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be" + - "0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801", - ), - ) - return one -} - -func (g *G2) rand() *PointG2 { - k, err := rand.Int(rand.Reader, q) - if err != nil { - panic(err) - } - return g.MulScalar(&PointG2{}, g.one(), k) -} - -func TestG2Serialization(t *testing.T) { - g2 := NewG2() - for i := 0; i < fuz; i++ { - a := g2.rand() - buf := g2.ToBytes(a) - b, err := g2.FromBytes(buf) - if err != nil { - t.Fatal(err) - } - if !g2.Equal(a, b) { - t.Fatal("bad serialization from/to") - } - } - for i := 0; i < fuz; i++ { - a := g2.rand() - encoded := g2.EncodePoint(a) - b, err := g2.DecodePoint(encoded) - if err != nil { - t.Fatal(err) - } - if !g2.Equal(a, b) { - t.Fatal("bad serialization encode/decode") - } - } -} - -func TestG2IsOnCurve(t *testing.T) { - g := NewG2() - zero := g.Zero() - if !g.IsOnCurve(zero) { - t.Fatal("zero must be on curve") - } - one := new(fe2).one() - p := &PointG2{*one, *one, *one} - if g.IsOnCurve(p) { - t.Fatal("(1, 1) is not on curve") - } -} - -func TestG2AdditiveProperties(t *testing.T) { - g := NewG2() - t0, t1 := g.New(), g.New() - zero := g.Zero() - for i := 0; i < fuz; i++ { - a, b := g.rand(), g.rand() - _, _, _ = b, t1, zero - g.Add(t0, a, zero) - if !g.Equal(t0, a) { - t.Fatal("a + 0 == a") - } - g.Add(t0, zero, zero) - if !g.Equal(t0, zero) { - t.Fatal("0 + 0 == 0") - } - g.Sub(t0, a, zero) - if !g.Equal(t0, a) { - t.Fatal("a - 0 == a") - } - g.Sub(t0, zero, zero) - if !g.Equal(t0, zero) { - t.Fatal("0 - 0 == 0") - } - g.Neg(t0, zero) - if !g.Equal(t0, zero) { - t.Fatal("- 0 == 0") - } - g.Sub(t0, zero, a) - g.Neg(t0, t0) - if !g.Equal(t0, a) { - t.Fatal(" - (0 - a) == a") - } - g.Double(t0, zero) - if !g.Equal(t0, zero) { - t.Fatal("2 * 0 == 0") - } - g.Double(t0, a) - g.Sub(t0, t0, a) - if !g.Equal(t0, a) || !g.IsOnCurve(t0) { - t.Fatal(" (2 * a) - a == a") - } - g.Add(t0, a, b) - g.Add(t1, b, a) - if !g.Equal(t0, t1) { - t.Fatal("a + b == b + a") - } - g.Sub(t0, a, b) - g.Sub(t1, b, a) - g.Neg(t1, t1) - if !g.Equal(t0, t1) { - t.Fatal("a - b == - ( b - a )") - } - c := g.rand() - g.Add(t0, a, b) - g.Add(t0, t0, c) - g.Add(t1, a, c) - g.Add(t1, t1, b) - if !g.Equal(t0, t1) { - t.Fatal("(a + b) + c == (a + c ) + b") - } - g.Sub(t0, a, b) - g.Sub(t0, t0, c) - g.Sub(t1, a, c) - g.Sub(t1, t1, b) - if !g.Equal(t0, t1) { - t.Fatal("(a - b) - c == (a - c) -b") - } - } -} - -func TestG2MultiplicativeProperties(t *testing.T) { - g := NewG2() - t0, t1 := g.New(), g.New() - zero := g.Zero() - for i := 0; i < fuz; i++ { - a := g.rand() - s1, s2, s3 := randScalar(q), randScalar(q), randScalar(q) - sone := big.NewInt(1) - g.MulScalar(t0, zero, s1) - if !g.Equal(t0, zero) { - t.Fatal(" 0 ^ s == 0") - } - g.MulScalar(t0, a, sone) - if !g.Equal(t0, a) { - t.Fatal(" a ^ 1 == a") - } - g.MulScalar(t0, zero, s1) - if !g.Equal(t0, zero) { - t.Fatal(" 0 ^ s == a") - } - g.MulScalar(t0, a, s1) - g.MulScalar(t0, t0, s2) - s3.Mul(s1, s2) - g.MulScalar(t1, a, s3) - if !g.Equal(t0, t1) { - t.Errorf(" (a ^ s1) ^ s2 == a ^ (s1 * s2)") - } - g.MulScalar(t0, a, s1) - g.MulScalar(t1, a, s2) - g.Add(t0, t0, t1) - s3.Add(s1, s2) - g.MulScalar(t1, a, s3) - if !g.Equal(t0, t1) { - t.Errorf(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)") - } - } -} - -func TestG2MultiExpExpected(t *testing.T) { - g := NewG2() - one := g.one() - var scalars [2]*big.Int - var bases [2]*PointG2 - scalars[0] = big.NewInt(2) - scalars[1] = big.NewInt(3) - bases[0], bases[1] = new(PointG2).Set(one), new(PointG2).Set(one) - expected, result := g.New(), g.New() - g.MulScalar(expected, one, big.NewInt(5)) - _, _ = g.MultiExp(result, bases[:], scalars[:]) - if !g.Equal(expected, result) { - t.Fatal("bad multi-exponentiation") - } -} - -func TestG2MultiExpBatch(t *testing.T) { - g := NewG2() - one := g.one() - n := 1000 - bases := make([]*PointG2, n) - scalars := make([]*big.Int, n) - // scalars: [s0,s1 ... s(n-1)] - // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G] - for i, j := 0, n-1; i < n; i, j = i+1, j-1 { - scalars[j], _ = rand.Int(rand.Reader, big.NewInt(100000)) - bases[i] = g.New() - g.MulScalar(bases[i], one, scalars[j]) - } - // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1) - expected, tmp := g.New(), g.New() - for i := 0; i < n; i++ { - g.MulScalar(tmp, bases[i], scalars[i]) - g.Add(expected, expected, tmp) - } - result := g.New() - _, _ = g.MultiExp(result, bases, scalars) - if !g.Equal(expected, result) { - t.Fatal("bad multi-exponentiation") - } -} - -func TestG2MapToCurve(t *testing.T) { - for i, v := range []struct { - u []byte - expected []byte - }{ - { - u: make([]byte, 96), - expected: common.FromHex("0a67d12118b5a35bb02d2e86b3ebfa7e23410db93de39fb06d7025fa95e96ffa428a7a27c3ae4dd4b40bd251ac658892" + "018320896ec9eef9d5e619848dc29ce266f413d02dd31d9b9d44ec0c79cd61f18b075ddba6d7bd20b7ff27a4b324bfce" + "04c69777a43f0bda07679d5805e63f18cf4e0e7c6112ac7f70266d199b4f76ae27c6269a3ceebdae30806e9a76aadf5c" + "0260e03644d1a2c321256b3246bad2b895cad13890cbe6f85df55106a0d334604fb143c7a042d878006271865bc35941"), - }, - { - u: common.FromHex("025fbc07711ba267b7e70c82caa70a16fbb1d470ae24ceef307f5e2000751677820b7013ad4e25492dcf30052d3e5eca" + "0e775d7827adf385b83e20e4445bd3fab21d7b4498426daf3c1d608b9d41e9edb5eda0df022e753b8bb4bc3bb7db4914"), - expected: common.FromHex("0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8" + "027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d" + "0cc76dc777ea0d447e02a41004f37a0a7b1fafb6746884e8d9fc276716ccf47e4e0899548a2ec71c2bdf1a2a50e876db" + "053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7"), - }, - { - u: common.FromHex("1870a7dbfd2a1deb74015a3546b20f598041bf5d5202997956a94a368d30d3f70f18cdaa1d33ce970a4e16af961cbdcb" + "045ab31ce4b5a8ba7c4b2851b64f063a66cd1223d3c85005b78e1beee65e33c90ceef0244e45fc45a5e1d6eab6644fdb"), - expected: common.FromHex("18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778" + "09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b" + "10a2ba341bc689ab947b7941ce6ef39be17acaab067bd32bd652b471ab0792c53a2bd03bdac47f96aaafe96e441f63c0" + "02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811"), - }, - { - u: common.FromHex("088fe329b054db8a6474f21a7fbfdf17b4c18044db299d9007af582c3d5f17d00e56d99921d4b5640fce44b05219b5de" + "0b6e6135a4cd31ba980ddbd115ac48abef7ec60e226f264d7befe002c165f3a496f36f76dd524efd75d17422558d10b4"), - expected: common.FromHex("19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163" + "149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7" + "04783e391c30c83f805ca271e353582fdf19d159f6a4c39b73acbb637a9b8ac820cfbe2738d683368a7c07ad020e3e33" + "04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551"), - }, - { - u: common.FromHex("03df16a66a05e4c1188c234788f43896e0565bfb64ac49b9639e6b284cc47dad73c47bb4ea7e677db8d496beb907fbb6" + "0f45b50647d67485295aa9eb2d91a877b44813677c67c8d35b2173ff3ba95f7bd0806f9ca8a1436b8b9d14ee81da4d7e"), - expected: common.FromHex("0b8e0094c886487870372eb6264613a6a087c7eb9804fab789be4e47a57b29eb19b1983a51165a1b5eb025865e9fc63a" + "0804152cbf8474669ad7d1796ab92d7ca21f32d8bed70898a748ed4e4e0ec557069003732fc86866d938538a2ae95552" + "14c80f068ece15a3936bb00c3c883966f75b4e8d9ddde809c11f781ab92d23a2d1d103ad48f6f3bb158bf3e3a4063449" + "09e5c8242dd7281ad32c03fe4af3f19167770016255fb25ad9b67ec51d62fade31a1af101e8f6172ec2ee8857662be3a"), - }, - } { - g := NewG2() - p0, err := g.MapToCurve(v.u) - if err != nil { - t.Fatal("map to curve fails", i, err) - } - if !bytes.Equal(g.ToBytes(p0), v.expected) { - t.Fatal("map to curve fails", i) - } - } -} - -func BenchmarkG2Add(t *testing.B) { - g2 := NewG2() - a, b, c := g2.rand(), g2.rand(), PointG2{} - t.ResetTimer() - for i := 0; i < t.N; i++ { - g2.Add(&c, a, b) - } -} - -func BenchmarkG2Mul(t *testing.B) { - worstCaseScalar, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16) - g2 := NewG2() - a, e, c := g2.rand(), worstCaseScalar, PointG2{} - t.ResetTimer() - for i := 0; i < t.N; i++ { - g2.MulScalar(&c, a, e) - } -} - -func BenchmarkG2SWUMap(t *testing.B) { - a := make([]byte, 96) - g2 := NewG2() - t.ResetTimer() - for i := 0; i < t.N; i++ { - _, err := g2.MapToCurve(a) - if err != nil { - t.Fatal(err) - } - } -} diff --git a/builder/crypto/bls12381/gt.go b/builder/crypto/bls12381/gt.go deleted file mode 100644 index 2ac265e95..000000000 --- a/builder/crypto/bls12381/gt.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" -) - -// E is type for target group element -type E = fe12 - -// GT is type for target multiplicative group GT. -type GT struct { - fp12 *fp12 -} - -func (e *E) Set(e2 *E) *E { - return e.set(e2) -} - -// One sets a new target group element to one -func (e *E) One() *E { - e = new(fe12).one() - return e -} - -// IsOne returns true if given element equals to one -func (e *E) IsOne() bool { - return e.isOne() -} - -// Equal returns true if given two element is equal, otherwise returns false -func (g *E) Equal(g2 *E) bool { - return g.equal(g2) -} - -// NewGT constructs new target group instance. -func NewGT() *GT { - fp12 := newFp12(nil) - return >{fp12} -} - -// Q returns group order in big.Int. -func (g *GT) Q() *big.Int { - return new(big.Int).Set(q) -} - -// FromBytes expects 576 byte input and returns target group element -// FromBytes returns error if given element is not on correct subgroup. -func (g *GT) FromBytes(in []byte) (*E, error) { - e, err := g.fp12.fromBytes(in) - if err != nil { - return nil, err - } - if !g.IsValid(e) { - return e, errors.New("invalid element") - } - return e, nil -} - -// ToBytes serializes target group element. -func (g *GT) ToBytes(e *E) []byte { - return g.fp12.toBytes(e) -} - -// IsValid checks whether given target group element is in correct subgroup. -func (g *GT) IsValid(e *E) bool { - r := g.New() - g.fp12.exp(r, e, q) - return r.isOne() -} - -// New initializes a new target group element which is equal to one -func (g *GT) New() *E { - return new(E).One() -} - -// Add adds two field element `a` and `b` and assigns the result to the element in first argument. -func (g *GT) Add(c, a, b *E) { - g.fp12.add(c, a, b) -} - -// Sub subtracts two field element `a` and `b`, and assigns the result to the element in first argument. -func (g *GT) Sub(c, a, b *E) { - g.fp12.sub(c, a, b) -} - -// Mul multiplies two field element `a` and `b` and assigns the result to the element in first argument. -func (g *GT) Mul(c, a, b *E) { - g.fp12.mul(c, a, b) -} - -// Square squares an element `a` and assigns the result to the element in first argument. -func (g *GT) Square(c, a *E) { - g.fp12.cyclotomicSquare(c, a) -} - -// Exp exponents an element `a` by a scalar `s` and assigns the result to the element in first argument. -func (g *GT) Exp(c, a *E, s *big.Int) { - g.fp12.cyclotomicExp(c, a, s) -} - -// Inverse inverses an element `a` and assigns the result to the element in first argument. -func (g *GT) Inverse(c, a *E) { - g.fp12.inverse(c, a) -} diff --git a/builder/crypto/bls12381/isogeny.go b/builder/crypto/bls12381/isogeny.go deleted file mode 100644 index a63f585dd..000000000 --- a/builder/crypto/bls12381/isogeny.go +++ /dev/null @@ -1,227 +0,0 @@ -// 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 bls12381 - -// isogenyMapG1 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06. -func isogenyMapG1(x, y *fe) { - // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2 - params := isogenyConstantsG1 - degree := 15 - xNum, xDen, yNum, yDen := new(fe), new(fe), new(fe), new(fe) - xNum.set(params[0][degree]) - xDen.set(params[1][degree]) - yNum.set(params[2][degree]) - yDen.set(params[3][degree]) - for i := degree - 1; i >= 0; i-- { - mul(xNum, xNum, x) - mul(xDen, xDen, x) - mul(yNum, yNum, x) - mul(yDen, yDen, x) - add(xNum, xNum, params[0][i]) - add(xDen, xDen, params[1][i]) - add(yNum, yNum, params[2][i]) - add(yDen, yDen, params[3][i]) - } - inverse(xDen, xDen) - inverse(yDen, yDen) - mul(xNum, xNum, xDen) - mul(yNum, yNum, yDen) - mul(yNum, yNum, y) - x.set(xNum) - y.set(yNum) -} - -// isogenyMapG2 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06. -func isogenyMapG2(e *fp2, x, y *fe2) { - if e == nil { - e = newFp2() - } - // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2 - params := isogenyConstantsG2 - degree := 3 - xNum := new(fe2).set(params[0][degree]) - xDen := new(fe2).set(params[1][degree]) - yNum := new(fe2).set(params[2][degree]) - yDen := new(fe2).set(params[3][degree]) - for i := degree - 1; i >= 0; i-- { - e.mul(xNum, xNum, x) - e.mul(xDen, xDen, x) - e.mul(yNum, yNum, x) - e.mul(yDen, yDen, x) - e.add(xNum, xNum, params[0][i]) - e.add(xDen, xDen, params[1][i]) - e.add(yNum, yNum, params[2][i]) - e.add(yDen, yDen, params[3][i]) - } - e.inverse(xDen, xDen) - e.inverse(yDen, yDen) - e.mul(xNum, xNum, xDen) - e.mul(yNum, yNum, yDen) - e.mul(yNum, yNum, y) - x.set(xNum) - y.set(yNum) -} - -var isogenyConstantsG1 = [4][16]*fe{ - { - {0x4d18b6f3af00131c, 0x19fa219793fee28c, 0x3f2885f1467f19ae, 0x23dcea34f2ffb304, 0xd15b58d2ffc00054, 0x0913be200a20bef4}, - {0x898985385cdbbd8b, 0x3c79e43cc7d966aa, 0x1597e193f4cd233a, 0x8637ef1e4d6623ad, 0x11b22deed20d827b, 0x07097bc5998784ad}, - {0xa542583a480b664b, 0xfc7169c026e568c6, 0x5ba2ef314ed8b5a6, 0x5b5491c05102f0e7, 0xdf6e99707d2a0079, 0x0784151ed7605524}, - {0x494e212870f72741, 0xab9be52fbda43021, 0x26f5577994e34c3d, 0x049dfee82aefbd60, 0x65dadd7828505289, 0x0e93d431ea011aeb}, - {0x90ee774bd6a74d45, 0x7ada1c8a41bfb185, 0x0f1a8953b325f464, 0x104c24211be4805c, 0x169139d319ea7a8f, 0x09f20ead8e532bf6}, - {0x6ddd93e2f43626b7, 0xa5482c9aa1ccd7bd, 0x143245631883f4bd, 0x2e0a94ccf77ec0db, 0xb0282d480e56489f, 0x18f4bfcbb4368929}, - {0x23c5f0c953402dfd, 0x7a43ff6958ce4fe9, 0x2c390d3d2da5df63, 0xd0df5c98e1f9d70f, 0xffd89869a572b297, 0x1277ffc72f25e8fe}, - {0x79f4f0490f06a8a6, 0x85f894a88030fd81, 0x12da3054b18b6410, 0xe2a57f6505880d65, 0xbba074f260e400f1, 0x08b76279f621d028}, - {0xe67245ba78d5b00b, 0x8456ba9a1f186475, 0x7888bff6e6b33bb4, 0xe21585b9a30f86cb, 0x05a69cdcef55feee, 0x09e699dd9adfa5ac}, - {0x0de5c357bff57107, 0x0a0db4ae6b1a10b2, 0xe256bb67b3b3cd8d, 0x8ad456574e9db24f, 0x0443915f50fd4179, 0x098c4bf7de8b6375}, - {0xe6b0617e7dd929c7, 0xfe6e37d442537375, 0x1dafdeda137a489e, 0xe4efd1ad3f767ceb, 0x4a51d8667f0fe1cf, 0x054fdf4bbf1d821c}, - {0x72db2a50658d767b, 0x8abf91faa257b3d5, 0xe969d6833764ab47, 0x464170142a1009eb, 0xb14f01aadb30be2f, 0x18ae6a856f40715d}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - }, - { - {0xb962a077fdb0f945, 0xa6a9740fefda13a0, 0xc14d568c3ed6c544, 0xb43fc37b908b133e, 0x9c0b3ac929599016, 0x0165aa6c93ad115f}, - {0x23279a3ba506c1d9, 0x92cfca0a9465176a, 0x3b294ab13755f0ff, 0x116dda1c5070ae93, 0xed4530924cec2045, 0x083383d6ed81f1ce}, - {0x9885c2a6449fecfc, 0x4a2b54ccd37733f0, 0x17da9ffd8738c142, 0xa0fba72732b3fafd, 0xff364f36e54b6812, 0x0f29c13c660523e2}, - {0xe349cc118278f041, 0xd487228f2f3204fb, 0xc9d325849ade5150, 0x43a92bd69c15c2df, 0x1c2c7844bc417be4, 0x12025184f407440c}, - {0x587f65ae6acb057b, 0x1444ef325140201f, 0xfbf995e71270da49, 0xccda066072436a42, 0x7408904f0f186bb2, 0x13b93c63edf6c015}, - {0xfb918622cd141920, 0x4a4c64423ecaddb4, 0x0beb232927f7fb26, 0x30f94df6f83a3dc2, 0xaeedd424d780f388, 0x06cc402dd594bbeb}, - {0xd41f761151b23f8f, 0x32a92465435719b3, 0x64f436e888c62cb9, 0xdf70a9a1f757c6e4, 0x6933a38d5b594c81, 0x0c6f7f7237b46606}, - {0x693c08747876c8f7, 0x22c9850bf9cf80f0, 0x8e9071dab950c124, 0x89bc62d61c7baf23, 0xbc6be2d8dad57c23, 0x17916987aa14a122}, - {0x1be3ff439c1316fd, 0x9965243a7571dfa7, 0xc7f7f62962f5cd81, 0x32c6aa9af394361c, 0xbbc2ee18e1c227f4, 0x0c102cbac531bb34}, - {0x997614c97bacbf07, 0x61f86372b99192c0, 0x5b8c95fc14353fc3, 0xca2b066c2a87492f, 0x16178f5bbf698711, 0x12a6dcd7f0f4e0e8}, - {0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - {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}, - }, - { - {0x2b567ff3e2837267, 0x1d4d9e57b958a767, 0xce028fea04bd7373, 0xcc31a30a0b6cd3df, 0x7d7b18a682692693, 0x0d300744d42a0310}, - {0x99c2555fa542493f, 0xfe7f53cc4874f878, 0x5df0608b8f97608a, 0x14e03832052b49c8, 0x706326a6957dd5a4, 0x0a8dadd9c2414555}, - {0x13d942922a5cf63a, 0x357e33e36e261e7d, 0xcf05a27c8456088d, 0x0000bd1de7ba50f0, 0x83d0c7532f8c1fde, 0x13f70bf38bbf2905}, - {0x5c57fd95bfafbdbb, 0x28a359a65e541707, 0x3983ceb4f6360b6d, 0xafe19ff6f97e6d53, 0xb3468f4550192bf7, 0x0bb6cde49d8ba257}, - {0x590b62c7ff8a513f, 0x314b4ce372cacefd, 0x6bef32ce94b8a800, 0x6ddf84a095713d5f, 0x64eace4cb0982191, 0x0386213c651b888d}, - {0xa5310a31111bbcdd, 0xa14ac0f5da148982, 0xf9ad9cc95423d2e9, 0xaa6ec095283ee4a7, 0xcf5b1f022e1c9107, 0x01fddf5aed881793}, - {0x65a572b0d7a7d950, 0xe25c2d8183473a19, 0xc2fcebe7cb877dbd, 0x05b2d36c769a89b0, 0xba12961be86e9efb, 0x07eb1b29c1dfde1f}, - {0x93e09572f7c4cd24, 0x364e929076795091, 0x8569467e68af51b5, 0xa47da89439f5340f, 0xf4fa918082e44d64, 0x0ad52ba3e6695a79}, - {0x911429844e0d5f54, 0xd03f51a3516bb233, 0x3d587e5640536e66, 0xfa86d2a3a9a73482, 0xa90ed5adf1ed5537, 0x149c9c326a5e7393}, - {0x462bbeb03c12921a, 0xdc9af5fa0a274a17, 0x9a558ebde836ebed, 0x649ef8f11a4fae46, 0x8100e1652b3cdc62, 0x1862bd62c291dacb}, - {0x05c9b8ca89f12c26, 0x0194160fa9b9ac4f, 0x6a643d5a6879fa2c, 0x14665bdd8846e19d, 0xbb1d0d53af3ff6bf, 0x12c7e1c3b28962e5}, - {0xb55ebf900b8a3e17, 0xfedc77ec1a9201c4, 0x1f07db10ea1a4df4, 0x0dfbd15dc41a594d, 0x389547f2334a5391, 0x02419f98165871a4}, - {0xb416af000745fc20, 0x8e563e9d1ea6d0f5, 0x7c763e17763a0652, 0x01458ef0159ebbef, 0x8346fe421f96bb13, 0x0d2d7b829ce324d2}, - {0x93096bb538d64615, 0x6f2a2619951d823a, 0x8f66b3ea59514fa4, 0xf563e63704f7092f, 0x724b136c4cf2d9fa, 0x046959cfcfd0bf49}, - {0xea748d4b6e405346, 0x91e9079c2c02d58f, 0x41064965946d9b59, 0xa06731f1d2bbe1ee, 0x07f897e267a33f1b, 0x1017290919210e5f}, - {0x872aa6c17d985097, 0xeecc53161264562a, 0x07afe37afff55002, 0x54759078e5be6838, 0xc4b92d15db8acca8, 0x106d87d1b51d13b9}, - }, - { - {0xeb6c359d47e52b1c, 0x18ef5f8a10634d60, 0xddfa71a0889d5b7e, 0x723e71dcc5fc1323, 0x52f45700b70d5c69, 0x0a8b981ee47691f1}, - {0x616a3c4f5535b9fb, 0x6f5f037395dbd911, 0xf25f4cc5e35c65da, 0x3e50dffea3c62658, 0x6a33dca523560776, 0x0fadeff77b6bfe3e}, - {0x2be9b66df470059c, 0x24a2c159a3d36742, 0x115dbe7ad10c2a37, 0xb6634a652ee5884d, 0x04fe8bb2b8d81af4, 0x01c2a7a256fe9c41}, - {0xf27bf8ef3b75a386, 0x898b367476c9073f, 0x24482e6b8c2f4e5f, 0xc8e0bbd6fe110806, 0x59b0c17f7631448a, 0x11037cd58b3dbfbd}, - {0x31c7912ea267eec6, 0x1dbf6f1c5fcdb700, 0xd30d4fe3ba86fdb1, 0x3cae528fbee9a2a4, 0xb1cce69b6aa9ad9a, 0x044393bb632d94fb}, - {0xc66ef6efeeb5c7e8, 0x9824c289dd72bb55, 0x71b1a4d2f119981d, 0x104fc1aafb0919cc, 0x0e49df01d942a628, 0x096c3a09773272d4}, - {0x9abc11eb5fadeff4, 0x32dca50a885728f0, 0xfb1fa3721569734c, 0xc4b76271ea6506b3, 0xd466a75599ce728e, 0x0c81d4645f4cb6ed}, - {0x4199f10e5b8be45b, 0xda64e495b1e87930, 0xcb353efe9b33e4ff, 0x9e9efb24aa6424c6, 0xf08d33680a237465, 0x0d3378023e4c7406}, - {0x7eb4ae92ec74d3a5, 0xc341b4aa9fac3497, 0x5be603899e907687, 0x03bfd9cca75cbdeb, 0x564c2935a96bfa93, 0x0ef3c33371e2fdb5}, - {0x7ee91fd449f6ac2e, 0xe5d5bd5cb9357a30, 0x773a8ca5196b1380, 0xd0fda172174ed023, 0x6cb95e0fa776aead, 0x0d22d5a40cec7cff}, - {0xf727e09285fd8519, 0xdc9d55a83017897b, 0x7549d8bd057894ae, 0x178419613d90d8f8, 0xfce95ebdeb5b490a, 0x0467ffaef23fc49e}, - {0xc1769e6a7c385f1b, 0x79bc930deac01c03, 0x5461c75a23ede3b5, 0x6e20829e5c230c45, 0x828e0f1e772a53cd, 0x116aefa749127bff}, - {0x101c10bf2744c10a, 0xbbf18d053a6a3154, 0xa0ecf39ef026f602, 0xfc009d4996dc5153, 0xb9000209d5bd08d3, 0x189e5fe4470cd73c}, - {0x7ebd546ca1575ed2, 0xe47d5a981d081b55, 0x57b2b625b6d4ca21, 0xb0a1ba04228520cc, 0x98738983c2107ff3, 0x13dddbc4799d81d6}, - {0x09319f2e39834935, 0x039e952cbdb05c21, 0x55ba77a9a2f76493, 0xfd04e3dfc6086467, 0xfb95832e7d78742e, 0x0ef9c24eccaf5e0e}, - {0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - }, -} - -var isogenyConstantsG2 = [4][4]*fe2{ - { - { - fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41}, - fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41}, - }, - { - fe{0, 0, 0, 0, 0, 0}, - fe{0x5fe55555554c71d0, 0x873fffdd236aaaa3, 0x6a6b4619b26ef918, 0x21c2888408874945, 0x2836cda7028cabc5, 0x0ac73310a7fd5abd}, - }, - { - fe{0x0a0c5555555971c3, 0xdb0c00101f9eaaae, 0xb1fb2f941d797997, 0xd3960742ef416e1c, 0xb70040e2c20556f4, 0x149d7861e581393b}, - fe{0xaff2aaaaaaa638e8, 0x439fffee91b55551, 0xb535a30cd9377c8c, 0x90e144420443a4a2, 0x941b66d3814655e2, 0x0563998853fead5e}, - }, - { - fe{0x40aac71c71c725ed, 0x190955557a84e38e, 0xd817050a8f41abc3, 0xd86485d4c87f6fb1, 0x696eb479f885d059, 0x198e1a74328002d2}, - fe{0, 0, 0, 0, 0, 0}, - }, - }, - { - { - fe{0, 0, 0, 0, 0, 0}, - fe{0x1f3affffff13ab97, 0xf25bfc611da3ff3e, 0xca3757cb3819b208, 0x3e6427366f8cec18, 0x03977bc86095b089, 0x04f69db13f39a952}, - }, - { - fe{0x447600000027552e, 0xdcb8009a43480020, 0x6f7ee9ce4a6e8b59, 0xb10330b7c0a95bc6, 0x6140b1fcfb1e54b7, 0x0381be097f0bb4e1}, - fe{0x7588ffffffd8557d, 0x41f3ff646e0bffdf, 0xf7b1e8d2ac426aca, 0xb3741acd32dbb6f8, 0xe9daf5b9482d581f, 0x167f53e0ba7431b8}, - }, - { - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0, 0, 0, 0, 0, 0}, - }, - { - fe{0, 0, 0, 0, 0, 0}, - fe{0, 0, 0, 0, 0, 0}, - }, - }, - { - { - fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3}, - fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3}, - }, - { - fe{0, 0, 0, 0, 0, 0}, - fe{0xbf0a71c71c91b406, 0x4d6d55d28b7638fd, 0x9d82f98e5f205aee, 0xa27aa27b1d1a18d5, 0x02c3b2b2d2938e86, 0x0c7d13420b09807f}, - }, - { - fe{0xd7f9555555531c74, 0x21cffff748daaaa8, 0x5a9ad1866c9bbe46, 0x4870a2210221d251, 0x4a0db369c0a32af1, 0x02b1ccc429ff56af}, - fe{0xe205aaaaaaac8e37, 0xfcdc000768795556, 0x0c96011a8a1537dd, 0x1c06a963f163406e, 0x010df44c82a881e6, 0x174f45260f808feb}, - }, - { - fe{0xa470bda12f67f35c, 0xc0fe38e23327b425, 0xc9d3d0f2c6f0678d, 0x1c55c9935b5a982e, 0x27f6c0e2f0746764, 0x117c5e6e28aa9054}, - fe{0, 0, 0, 0, 0, 0}, - }, - }, - { - { - fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151}, - fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151}, - }, - { - fe{0, 0, 0, 0, 0, 0}, - fe{0x5db0fffffd3b02c5, 0xd713f52358ebfdba, 0x5ea60761a84d161a, 0xbb2c75a34ea6c44a, 0x0ac6735921c1119b, 0x0ee3d913bdacfbf6}, - }, - { - fe{0x66b10000003affc5, 0xcb1400e764ec0030, 0xa73e5eb56fa5d106, 0x8984c913a0fe09a9, 0x11e10afb78ad7f13, 0x05429d0e3e918f52}, - fe{0x534dffffffc4aae6, 0x5397ff174c67ffcf, 0xbff273eb870b251d, 0xdaf2827152870915, 0x393a9cbaca9e2dc3, 0x14be74dbfaee5748}, - }, - { - fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, - fe{0, 0, 0, 0, 0, 0}, - }, - }, -} diff --git a/builder/crypto/bls12381/pairing.go b/builder/crypto/bls12381/pairing.go deleted file mode 100644 index d292d7c3a..000000000 --- a/builder/crypto/bls12381/pairing.go +++ /dev/null @@ -1,282 +0,0 @@ -// 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 bls12381 - -type pair struct { - g1 *PointG1 - g2 *PointG2 -} - -func newPair(g1 *PointG1, g2 *PointG2) pair { - return pair{g1, g2} -} - -// Engine is BLS12-381 elliptic curve pairing engine -type Engine struct { - G1 *G1 - G2 *G2 - fp12 *fp12 - fp2 *fp2 - pairingEngineTemp - pairs []pair -} - -// NewPairingEngine creates new pairing engine instance. -func NewPairingEngine() *Engine { - fp2 := newFp2() - fp6 := newFp6(fp2) - fp12 := newFp12(fp6) - g1 := NewG1() - g2 := newG2(fp2) - return &Engine{ - fp2: fp2, - fp12: fp12, - G1: g1, - G2: g2, - pairingEngineTemp: newEngineTemp(), - } -} - -type pairingEngineTemp struct { - t2 [10]*fe2 - t12 [9]fe12 -} - -func newEngineTemp() pairingEngineTemp { - t2 := [10]*fe2{} - for i := 0; i < 10; i++ { - t2[i] = &fe2{} - } - t12 := [9]fe12{} - return pairingEngineTemp{t2, t12} -} - -// AddPair adds a g1, g2 point pair to pairing engine -func (e *Engine) AddPair(g1 *PointG1, g2 *PointG2) *Engine { - p := newPair(g1, g2) - if !e.isZero(p) { - e.affine(p) - e.pairs = append(e.pairs, p) - } - return e -} - -// AddPairInv adds a G1, G2 point pair to pairing engine. G1 point is negated. -func (e *Engine) AddPairInv(g1 *PointG1, g2 *PointG2) *Engine { - e.G1.Neg(g1, g1) - e.AddPair(g1, g2) - return e -} - -// Reset deletes added pairs. -func (e *Engine) Reset() *Engine { - e.pairs = []pair{} - return e -} - -func (e *Engine) isZero(p pair) bool { - return e.G1.IsZero(p.g1) || e.G2.IsZero(p.g2) -} - -func (e *Engine) affine(p pair) { - e.G1.Affine(p.g1) - e.G2.Affine(p.g2) -} - -func (e *Engine) doublingStep(coeff *[3]fe2, r *PointG2) { - // Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf - fp2 := e.fp2 - t := e.t2 - fp2.mul(t[0], &r[0], &r[1]) - fp2.mulByFq(t[0], t[0], twoInv) - fp2.square(t[1], &r[1]) - fp2.square(t[2], &r[2]) - fp2.double(t[7], t[2]) - fp2.add(t[7], t[7], t[2]) - fp2.mulByB(t[3], t[7]) - fp2.double(t[4], t[3]) - fp2.add(t[4], t[4], t[3]) - fp2.add(t[5], t[1], t[4]) - fp2.mulByFq(t[5], t[5], twoInv) - fp2.add(t[6], &r[1], &r[2]) - fp2.square(t[6], t[6]) - fp2.add(t[7], t[2], t[1]) - fp2.sub(t[6], t[6], t[7]) - fp2.sub(&coeff[0], t[3], t[1]) - fp2.square(t[7], &r[0]) - fp2.sub(t[4], t[1], t[4]) - fp2.mul(&r[0], t[4], t[0]) - fp2.square(t[2], t[3]) - fp2.double(t[3], t[2]) - fp2.add(t[3], t[3], t[2]) - fp2.square(t[5], t[5]) - fp2.sub(&r[1], t[5], t[3]) - fp2.mul(&r[2], t[1], t[6]) - fp2.double(t[0], t[7]) - fp2.add(&coeff[1], t[0], t[7]) - fp2.neg(&coeff[2], t[6]) -} - -func (e *Engine) additionStep(coeff *[3]fe2, r, q *PointG2) { - // Algorithm 12 in https://eprint.iacr.org/2010/526.pdf - fp2 := e.fp2 - t := e.t2 - fp2.mul(t[0], &q[1], &r[2]) - fp2.neg(t[0], t[0]) - fp2.add(t[0], t[0], &r[1]) - fp2.mul(t[1], &q[0], &r[2]) - fp2.neg(t[1], t[1]) - fp2.add(t[1], t[1], &r[0]) - fp2.square(t[2], t[0]) - fp2.square(t[3], t[1]) - fp2.mul(t[4], t[1], t[3]) - fp2.mul(t[2], &r[2], t[2]) - fp2.mul(t[3], &r[0], t[3]) - fp2.double(t[5], t[3]) - fp2.sub(t[5], t[4], t[5]) - fp2.add(t[5], t[5], t[2]) - fp2.mul(&r[0], t[1], t[5]) - fp2.sub(t[2], t[3], t[5]) - fp2.mul(t[2], t[2], t[0]) - fp2.mul(t[3], &r[1], t[4]) - fp2.sub(&r[1], t[2], t[3]) - fp2.mul(&r[2], &r[2], t[4]) - fp2.mul(t[2], t[1], &q[1]) - fp2.mul(t[3], t[0], &q[0]) - fp2.sub(&coeff[0], t[3], t[2]) - fp2.neg(&coeff[1], t[0]) - coeff[2].set(t[1]) -} - -func (e *Engine) preCompute(ellCoeffs *[68][3]fe2, twistPoint *PointG2) { - // Algorithm 5 in https://eprint.iacr.org/2019/077.pdf - if e.G2.IsZero(twistPoint) { - return - } - r := new(PointG2).Set(twistPoint) - j := 0 - for i := x.BitLen() - 2; i >= 0; i-- { - e.doublingStep(&ellCoeffs[j], r) - if x.Bit(i) != 0 { - j++ - ellCoeffs[j] = fe6{} - e.additionStep(&ellCoeffs[j], r, twistPoint) - } - j++ - } -} - -func (e *Engine) millerLoop(f *fe12) { - pairs := e.pairs - ellCoeffs := make([][68][3]fe2, len(pairs)) - for i := 0; i < len(pairs); i++ { - e.preCompute(&ellCoeffs[i], pairs[i].g2) - } - fp12, fp2 := e.fp12, e.fp2 - t := e.t2 - f.one() - j := 0 - for i := 62; /* x.BitLen() - 2 */ i >= 0; i-- { - if i != 62 { - fp12.square(f, f) - } - for i := 0; i <= len(pairs)-1; i++ { - fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1]) - fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0]) - fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0]) - } - if x.Bit(i) != 0 { - j++ - for i := 0; i <= len(pairs)-1; i++ { - fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1]) - fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0]) - fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0]) - } - } - j++ - } - fp12.conjugate(f, f) -} - -func (e *Engine) exp(c, a *fe12) { - fp12 := e.fp12 - fp12.cyclotomicExp(c, a, x) - fp12.conjugate(c, c) -} - -func (e *Engine) finalExp(f *fe12) { - fp12 := e.fp12 - t := e.t12 - // easy part - fp12.frobeniusMap(&t[0], f, 6) - fp12.inverse(&t[1], f) - fp12.mul(&t[2], &t[0], &t[1]) - t[1].set(&t[2]) - fp12.frobeniusMapAssign(&t[2], 2) - fp12.mulAssign(&t[2], &t[1]) - fp12.cyclotomicSquare(&t[1], &t[2]) - fp12.conjugate(&t[1], &t[1]) - // hard part - e.exp(&t[3], &t[2]) - fp12.cyclotomicSquare(&t[4], &t[3]) - fp12.mul(&t[5], &t[1], &t[3]) - e.exp(&t[1], &t[5]) - e.exp(&t[0], &t[1]) - e.exp(&t[6], &t[0]) - fp12.mulAssign(&t[6], &t[4]) - e.exp(&t[4], &t[6]) - fp12.conjugate(&t[5], &t[5]) - fp12.mulAssign(&t[4], &t[5]) - fp12.mulAssign(&t[4], &t[2]) - fp12.conjugate(&t[5], &t[2]) - fp12.mulAssign(&t[1], &t[2]) - fp12.frobeniusMapAssign(&t[1], 3) - fp12.mulAssign(&t[6], &t[5]) - fp12.frobeniusMapAssign(&t[6], 1) - fp12.mulAssign(&t[3], &t[0]) - fp12.frobeniusMapAssign(&t[3], 2) - fp12.mulAssign(&t[3], &t[1]) - fp12.mulAssign(&t[3], &t[6]) - fp12.mul(f, &t[3], &t[4]) -} - -func (e *Engine) calculate() *fe12 { - f := e.fp12.one() - if len(e.pairs) == 0 { - return f - } - e.millerLoop(f) - e.finalExp(f) - return f -} - -// Check computes pairing and checks if result is equal to one -func (e *Engine) Check() bool { - return e.calculate().isOne() -} - -// Result computes pairing and returns target group element as result. -func (e *Engine) Result() *E { - r := e.calculate() - e.Reset() - return r -} - -// GT returns target group instance. -func (e *Engine) GT() *GT { - return NewGT() -} diff --git a/builder/crypto/bls12381/pairing_test.go b/builder/crypto/bls12381/pairing_test.go deleted file mode 100644 index 77676fe9b..000000000 --- a/builder/crypto/bls12381/pairing_test.go +++ /dev/null @@ -1,230 +0,0 @@ -package bls12381 - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func TestPairingExpected(t *testing.T) { - bls := NewPairingEngine() - G1, G2 := bls.G1, bls.G2 - GT := bls.GT() - expected, err := GT.FromBytes( - common.FromHex("" + - "0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631" + - "04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef" + - "03350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a2" + - "11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba57" + - "06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a" + - "19f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d" + - "018107154f25a764bd3c79937a45b84546da634b8f6be14a8061e55cceba478b23f7dacaa35c8ca78beae9624045b4b6" + - "01b2f522473d171391125ba84dc4007cfbf2f8da752f7c74185203fcca589ac719c34dffbbaad8431dad1c1fb597aaa5" + - "193502b86edb8857c273fa075a50512937e0794e1e65a7617c90d8bd66065b1fffe51d7a579973b1315021ec3c19934f" + - "1368bb445c7c2d209703f239689ce34c0378a68e72a6b3b216da0e22a5031b54ddff57309396b38c881c4c849ec23e87" + - "089a1c5b46e5110b86750ec6a532348868a84045483c92b7af5af689452eafabf1a8943e50439f1d59882a98eaa0170f" + - "1250ebd871fc0a92a7b2d83168d0d727272d441befa15c503dd8e90ce98db3e7b6d194f60839c508a84305aaca1789b6", - ), - ) - if err != nil { - t.Fatal(err) - } - r := bls.AddPair(G1.One(), G2.One()).Result() - if !r.Equal(expected) { - t.Fatal("bad pairing") - } - if !GT.IsValid(r) { - t.Fatal("element is not in correct subgroup") - } -} - -func TestPairingNonDegeneracy(t *testing.T) { - bls := NewPairingEngine() - G1, G2 := bls.G1, bls.G2 - g1Zero, g2Zero, g1One, g2One := G1.Zero(), G2.Zero(), G1.One(), G2.One() - GT := bls.GT() - // e(g1^a, g2^b) != 1 - bls.Reset() - { - bls.AddPair(g1One, g2One) - e := bls.Result() - if e.IsOne() { - t.Fatal("pairing result is not expected to be one") - } - if !GT.IsValid(e) { - t.Fatal("pairing result is not valid") - } - } - // e(g1^a, 0) == 1 - bls.Reset() - { - bls.AddPair(g1One, g2Zero) - e := bls.Result() - if !e.IsOne() { - t.Fatal("pairing result is expected to be one") - } - } - // e(0, g2^b) == 1 - bls.Reset() - { - bls.AddPair(g1Zero, g2One) - e := bls.Result() - if !e.IsOne() { - t.Fatal("pairing result is expected to be one") - } - } - // - bls.Reset() - { - bls.AddPair(g1Zero, g2One) - bls.AddPair(g1One, g2Zero) - bls.AddPair(g1Zero, g2Zero) - e := bls.Result() - if !e.IsOne() { - t.Fatal("pairing result is expected to be one") - } - } - // - bls.Reset() - { - expected, err := GT.FromBytes( - common.FromHex("" + - "0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631" + - "04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef" + - "03350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a2" + - "11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba57" + - "06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a" + - "19f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d" + - "018107154f25a764bd3c79937a45b84546da634b8f6be14a8061e55cceba478b23f7dacaa35c8ca78beae9624045b4b6" + - "01b2f522473d171391125ba84dc4007cfbf2f8da752f7c74185203fcca589ac719c34dffbbaad8431dad1c1fb597aaa5" + - "193502b86edb8857c273fa075a50512937e0794e1e65a7617c90d8bd66065b1fffe51d7a579973b1315021ec3c19934f" + - "1368bb445c7c2d209703f239689ce34c0378a68e72a6b3b216da0e22a5031b54ddff57309396b38c881c4c849ec23e87" + - "089a1c5b46e5110b86750ec6a532348868a84045483c92b7af5af689452eafabf1a8943e50439f1d59882a98eaa0170f" + - "1250ebd871fc0a92a7b2d83168d0d727272d441befa15c503dd8e90ce98db3e7b6d194f60839c508a84305aaca1789b6", - ), - ) - if err != nil { - t.Fatal(err) - } - bls.AddPair(g1Zero, g2One) - bls.AddPair(g1One, g2Zero) - bls.AddPair(g1Zero, g2Zero) - bls.AddPair(g1One, g2One) - e := bls.Result() - if !e.Equal(expected) { - t.Fatal("bad pairing") - } - } -} - -func TestPairingBilinearity(t *testing.T) { - bls := NewPairingEngine() - g1, g2 := bls.G1, bls.G2 - gt := bls.GT() - // e(a*G1, b*G2) = e(G1, G2)^c - { - a, b := big.NewInt(17), big.NewInt(117) - c := new(big.Int).Mul(a, b) - G1, G2 := g1.One(), g2.One() - e0 := bls.AddPair(G1, G2).Result() - P1, P2 := g1.New(), g2.New() - g1.MulScalar(P1, G1, a) - g2.MulScalar(P2, G2, b) - e1 := bls.AddPair(P1, P2).Result() - gt.Exp(e0, e0, c) - if !e0.Equal(e1) { - t.Fatal("bad pairing, 1") - } - } - // e(a * G1, b * G2) = e((a + b) * G1, G2) - { - // scalars - a, b := big.NewInt(17), big.NewInt(117) - c := new(big.Int).Mul(a, b) - // LHS - G1, G2 := g1.One(), g2.One() - g1.MulScalar(G1, G1, c) - bls.AddPair(G1, G2) - // RHS - P1, P2 := g1.One(), g2.One() - g1.MulScalar(P1, P1, a) - g2.MulScalar(P2, P2, b) - bls.AddPairInv(P1, P2) - // should be one - if !bls.Check() { - t.Fatal("bad pairing, 2") - } - } - // e(a * G1, b * G2) = e((a + b) * G1, G2) - { - // scalars - a, b := big.NewInt(17), big.NewInt(117) - c := new(big.Int).Mul(a, b) - // LHS - G1, G2 := g1.One(), g2.One() - g2.MulScalar(G2, G2, c) - bls.AddPair(G1, G2) - // RHS - H1, H2 := g1.One(), g2.One() - g1.MulScalar(H1, H1, a) - g2.MulScalar(H2, H2, b) - bls.AddPairInv(H1, H2) - // should be one - if !bls.Check() { - t.Fatal("bad pairing, 3") - } - } -} - -func TestPairingMulti(t *testing.T) { - // e(G1, G2) ^ t == e(a01 * G1, a02 * G2) * e(a11 * G1, a12 * G2) * ... * e(an1 * G1, an2 * G2) - // where t = sum(ai1 * ai2) - bls := NewPairingEngine() - g1, g2 := bls.G1, bls.G2 - numOfPair := 100 - targetExp := new(big.Int) - // RHS - for i := 0; i < numOfPair; i++ { - // (ai1 * G1, ai2 * G2) - a1, a2 := randScalar(q), randScalar(q) - P1, P2 := g1.One(), g2.One() - g1.MulScalar(P1, P1, a1) - g2.MulScalar(P2, P2, a2) - bls.AddPair(P1, P2) - // accumulate targetExp - // t += (ai1 * ai2) - a1.Mul(a1, a2) - targetExp.Add(targetExp, a1) - } - // LHS - // e(t * G1, G2) - T1, T2 := g1.One(), g2.One() - g1.MulScalar(T1, T1, targetExp) - bls.AddPairInv(T1, T2) - if !bls.Check() { - t.Fatal("fail multi pairing") - } -} - -func TestPairingEmpty(t *testing.T) { - bls := NewPairingEngine() - if !bls.Check() { - t.Fatal("empty check should be accepted") - } - if !bls.Result().IsOne() { - t.Fatal("empty pairing result should be one") - } -} - -func BenchmarkPairing(t *testing.B) { - bls := NewPairingEngine() - g1, g2, gt := bls.G1, bls.G2, bls.GT() - bls.AddPair(g1.One(), g2.One()) - e := gt.New() - t.ResetTimer() - for i := 0; i < t.N; i++ { - e = bls.calculate() - } - _ = e -} diff --git a/builder/crypto/bls12381/swu.go b/builder/crypto/bls12381/swu.go deleted file mode 100644 index e78753b24..000000000 --- a/builder/crypto/bls12381/swu.go +++ /dev/null @@ -1,158 +0,0 @@ -// 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 bls12381 - -// swuMapG1 is implementation of Simplified Shallue-van de Woestijne-Ulas Method -// follows the implementation at draft-irtf-cfrg-hash-to-curve-06. -func swuMapG1(u *fe) (*fe, *fe) { - var params = swuParamsForG1 - var tv [4]*fe - for i := 0; i < 4; i++ { - tv[i] = new(fe) - } - square(tv[0], u) - mul(tv[0], tv[0], params.z) - square(tv[1], tv[0]) - x1 := new(fe) - add(x1, tv[0], tv[1]) - inverse(x1, x1) - e1 := x1.isZero() - one := new(fe).one() - add(x1, x1, one) - if e1 { - x1.set(params.zInv) - } - mul(x1, x1, params.minusBOverA) - gx1 := new(fe) - square(gx1, x1) - add(gx1, gx1, params.a) - mul(gx1, gx1, x1) - add(gx1, gx1, params.b) - x2 := new(fe) - mul(x2, tv[0], x1) - mul(tv[1], tv[0], tv[1]) - gx2 := new(fe) - mul(gx2, gx1, tv[1]) - e2 := !isQuadraticNonResidue(gx1) - x, y2 := new(fe), new(fe) - if e2 { - x.set(x1) - y2.set(gx1) - } else { - x.set(x2) - y2.set(gx2) - } - y := new(fe) - sqrt(y, y2) - if y.sign() != u.sign() { - neg(y, y) - } - return x, y -} - -// swuMapG2 is implementation of Simplified Shallue-van de Woestijne-Ulas Method -// defined at draft-irtf-cfrg-hash-to-curve-06. -func swuMapG2(e *fp2, u *fe2) (*fe2, *fe2) { - if e == nil { - e = newFp2() - } - params := swuParamsForG2 - var tv [4]*fe2 - for i := 0; i < 4; i++ { - tv[i] = e.new() - } - e.square(tv[0], u) - e.mul(tv[0], tv[0], params.z) - e.square(tv[1], tv[0]) - x1 := e.new() - e.add(x1, tv[0], tv[1]) - e.inverse(x1, x1) - e1 := x1.isZero() - e.add(x1, x1, e.one()) - if e1 { - x1.set(params.zInv) - } - e.mul(x1, x1, params.minusBOverA) - gx1 := e.new() - e.square(gx1, x1) - e.add(gx1, gx1, params.a) - e.mul(gx1, gx1, x1) - e.add(gx1, gx1, params.b) - x2 := e.new() - e.mul(x2, tv[0], x1) - e.mul(tv[1], tv[0], tv[1]) - gx2 := e.new() - e.mul(gx2, gx1, tv[1]) - e2 := !e.isQuadraticNonResidue(gx1) - x, y2 := e.new(), e.new() - if e2 { - x.set(x1) - y2.set(gx1) - } else { - x.set(x2) - y2.set(gx2) - } - y := e.new() - e.sqrt(y, y2) - if y.sign() != u.sign() { - e.neg(y, y) - } - return x, y -} - -var swuParamsForG1 = struct { - z *fe - zInv *fe - a *fe - b *fe - minusBOverA *fe -}{ - a: &fe{0x2f65aa0e9af5aa51, 0x86464c2d1e8416c3, 0xb85ce591b7bd31e2, 0x27e11c91b5f24e7c, 0x28376eda6bfc1835, 0x155455c3e5071d85}, - b: &fe{0xfb996971fe22a1e0, 0x9aa93eb35b742d6f, 0x8c476013de99c5c4, 0x873e27c3a221e571, 0xca72b5e45a52d888, 0x06824061418a386b}, - z: &fe{0x886c00000023ffdc, 0x0f70008d3090001d, 0x77672417ed5828c3, 0x9dac23e943dc1740, 0x50553f1b9c131521, 0x078c712fbe0ab6e8}, - zInv: &fe{0x0e8a2e8ba2e83e10, 0x5b28ba2ca4d745d1, 0x678cd5473847377a, 0x4c506dd8a8076116, 0x9bcb227d79284139, 0x0e8d3154b0ba099a}, - minusBOverA: &fe{0x052583c93555a7fe, 0x3b40d72430f93c82, 0x1b75faa0105ec983, 0x2527e7dc63851767, 0x99fffd1f34fc181d, 0x097cab54770ca0d3}, -} - -var swuParamsForG2 = struct { - z *fe2 - zInv *fe2 - a *fe2 - b *fe2 - minusBOverA *fe2 -}{ - a: &fe2{ - fe{0, 0, 0, 0, 0, 0}, - fe{0xe53a000003135242, 0x01080c0fdef80285, 0xe7889edbe340f6bd, 0x0b51375126310601, 0x02d6985717c744ab, 0x1220b4e979ea5467}, - }, - b: &fe2{ - fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1}, - fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1}, - }, - z: &fe2{ - fe{0x87ebfffffff9555c, 0x656fffe5da8ffffa, 0x0fd0749345d33ad2, 0xd951e663066576f4, 0xde291a3d41e980d3, 0x0815664c7dfe040d}, - fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}, - }, - zInv: &fe2{ - fe{0xacd0000000011110, 0x9dd9999dc88ccccd, 0xb5ca2ac9b76352bf, 0xf1b574bcf4bc90ce, 0x42dab41f28a77081, 0x132fc6ac14cd1e12}, - fe{0xe396ffffffff2223, 0x4fbf332fcd0d9998, 0x0c4bbd3c1aff4cc4, 0x6b9c91267926ca58, 0x29ae4da6aef7f496, 0x10692e942f195791}, - }, - minusBOverA: &fe2{ - fe{0x903c555555474fb3, 0x5f98cc95ce451105, 0x9f8e582eefe0fade, 0xc68946b6aebbd062, 0x467a4ad10ee6de53, 0x0e7146f483e23a05}, - fe{0x29c2aaaaaab85af8, 0xbf133368e30eeefa, 0xc7a27a7206cffb45, 0x9dee04ce44c9425c, 0x04a15ce53464ce83, 0x0b8fcaf5b59dac95}, - }, -} diff --git a/builder/crypto/bls12381/utils.go b/builder/crypto/bls12381/utils.go deleted file mode 100644 index de8bf495f..000000000 --- a/builder/crypto/bls12381/utils.go +++ /dev/null @@ -1,45 +0,0 @@ -// 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 bls12381 - -import ( - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -func bigFromHex(hex string) *big.Int { - return new(big.Int).SetBytes(common.FromHex(hex)) -} - -// decodeFieldElement expects 64 byte input with zero top 16 bytes, -// returns lower 48 bytes. -func decodeFieldElement(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, errors.New("invalid field element top bytes") - } - } - out := make([]byte, 48) - copy(out[:], in[16:]) - return out, nil -} diff --git a/builder/crypto/bn256/LICENSE b/builder/crypto/bn256/LICENSE deleted file mode 100644 index 634e0cb2c..000000000 --- a/builder/crypto/bn256/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2018 Péter Szilágyi. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/builder/crypto/bn256/bn256_fast.go b/builder/crypto/bn256/bn256_fast.go deleted file mode 100644 index e3c9b6051..000000000 --- a/builder/crypto/bn256/bn256_fast.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 Péter Szilágyi. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -//go:build amd64 || arm64 -// +build amd64 arm64 - -// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. -package bn256 - -import ( - bn256cf "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" -) - -// G1 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G1 = bn256cf.G1 - -// G2 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G2 = bn256cf.G2 - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - return bn256cf.PairingCheck(a, b) -} diff --git a/builder/crypto/bn256/bn256_slow.go b/builder/crypto/bn256/bn256_slow.go deleted file mode 100644 index 4c0c351e2..000000000 --- a/builder/crypto/bn256/bn256_slow.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 Péter Szilágyi. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -//go:build !amd64 && !arm64 -// +build !amd64,!arm64 - -// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. -package bn256 - -import bn256 "github.com/ethereum/go-ethereum/crypto/bn256/google" - -// G1 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G1 = bn256.G1 - -// G2 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G2 = bn256.G2 - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - return bn256.PairingCheck(a, b) -} diff --git a/builder/crypto/bn256/cloudflare/LICENSE b/builder/crypto/bn256/cloudflare/LICENSE deleted file mode 100644 index 6a66aea5e..000000000 --- a/builder/crypto/bn256/cloudflare/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/builder/crypto/bn256/cloudflare/bn256.go b/builder/crypto/bn256/cloudflare/bn256.go deleted file mode 100644 index 4f607af2a..000000000 --- a/builder/crypto/bn256/cloudflare/bn256.go +++ /dev/null @@ -1,495 +0,0 @@ -// Package bn256 implements a particular bilinear group at the 128-bit security -// level. -// -// Bilinear groups are the basis of many of the new cryptographic protocols that -// have been proposed over the past decade. They consist of a triplet of groups -// (Gâ‚, Gâ‚‚ and GT) such that there exists a function e(gâ‚Ë£,g₂ʸ)=gTˣʸ (where gâ‚“ -// is a generator of the respective group). That function is called a pairing -// function. -// -// This package specifically implements the Optimal Ate pairing over a 256-bit -// Barreto-Naehrig curve as described in -// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is not -// compatible with the implementation described in that paper, as different -// parameters are chosen. -// -// (This package previously claimed to operate at a 128-bit security level. -// However, recent improvements in attacks mean that is no longer true. See -// https://moderncrypto.org/mail-archive/curves/2016/000740.html.) -package bn256 - -import ( - "crypto/rand" - "errors" - "io" - "math/big" -) - -func randomK(r io.Reader) (k *big.Int, err error) { - for { - k, err = rand.Int(r, Order) - if err != nil || k.Sign() > 0 { - return - } - } -} - -// G1 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G1 struct { - p *curvePoint -} - -// RandomG1 returns x and gâ‚Ë£ where x is a random, non-zero number read from r. -func RandomG1(r io.Reader) (*big.Int, *G1, error) { - k, err := randomK(r) - if err != nil { - return nil, nil, err - } - - return k, new(G1).ScalarBaseMult(k), nil -} - -func (g *G1) String() string { - return "bn256.G1" + g.p.String() -} - -// ScalarBaseMult sets e to g*k where g is the generator of the group and then -// returns e. -func (e *G1) ScalarBaseMult(k *big.Int) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Mul(curveGen, k) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Mul(a.p, k) - return e -} - -// Add sets e to a+b and then returns e. -func (e *G1) Add(a, b *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Add(a.p, b.p) - return e -} - -// Neg sets e to -a and then returns e. -func (e *G1) Neg(a *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Neg(a.p) - return e -} - -// Set sets e to a and then returns e. -func (e *G1) Set(a *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Set(a.p) - return e -} - -// Marshal converts e to a byte slice. -func (e *G1) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if e.p == nil { - e.p = &curvePoint{} - } - - e.p.MakeAffine() - ret := make([]byte, numBytes*2) - if e.p.IsInfinity() { - return ret - } - temp := &gfP{} - - montDecode(temp, &e.p.x) - temp.Marshal(ret) - montDecode(temp, &e.p.y) - temp.Marshal(ret[numBytes:]) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *G1) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - if len(m) < 2*numBytes { - return nil, errors.New("bn256: not enough data") - } - // Unmarshal the points and check their caps - if e.p == nil { - e.p = &curvePoint{} - } else { - e.p.x, e.p.y = gfP{0}, gfP{0} - } - var err error - if err = e.p.x.Unmarshal(m); err != nil { - return nil, err - } - if err = e.p.y.Unmarshal(m[numBytes:]); err != nil { - return nil, err - } - // Encode into Montgomery form and ensure it's on the curve - montEncode(&e.p.x, &e.p.x) - montEncode(&e.p.y, &e.p.y) - - zero := gfP{0} - if e.p.x == zero && e.p.y == zero { - // This is the point at infinity. - e.p.y = *newGFp(1) - e.p.z = gfP{0} - e.p.t = gfP{0} - } else { - e.p.z = *newGFp(1) - e.p.t = *newGFp(1) - - if !e.p.IsOnCurve() { - return nil, errors.New("bn256: malformed point") - } - } - return m[2*numBytes:], nil -} - -// G2 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G2 struct { - p *twistPoint -} - -// RandomG2 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r. -func RandomG2(r io.Reader) (*big.Int, *G2, error) { - k, err := randomK(r) - if err != nil { - return nil, nil, err - } - - return k, new(G2).ScalarBaseMult(k), nil -} - -func (e *G2) String() string { - return "bn256.G2" + e.p.String() -} - -// ScalarBaseMult sets e to g*k where g is the generator of the group and then -// returns out. -func (e *G2) ScalarBaseMult(k *big.Int) *G2 { - if e.p == nil { - e.p = &twistPoint{} - } - e.p.Mul(twistGen, k) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { - if e.p == nil { - e.p = &twistPoint{} - } - e.p.Mul(a.p, k) - return e -} - -// Add sets e to a+b and then returns e. -func (e *G2) Add(a, b *G2) *G2 { - if e.p == nil { - e.p = &twistPoint{} - } - e.p.Add(a.p, b.p) - return e -} - -// Neg sets e to -a and then returns e. -func (e *G2) Neg(a *G2) *G2 { - if e.p == nil { - e.p = &twistPoint{} - } - e.p.Neg(a.p) - return e -} - -// Set sets e to a and then returns e. -func (e *G2) Set(a *G2) *G2 { - if e.p == nil { - e.p = &twistPoint{} - } - e.p.Set(a.p) - return e -} - -// Marshal converts e into a byte slice. -func (e *G2) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if e.p == nil { - e.p = &twistPoint{} - } - - e.p.MakeAffine() - ret := make([]byte, numBytes*4) - if e.p.IsInfinity() { - return ret - } - temp := &gfP{} - - montDecode(temp, &e.p.x.x) - temp.Marshal(ret) - montDecode(temp, &e.p.x.y) - temp.Marshal(ret[numBytes:]) - montDecode(temp, &e.p.y.x) - temp.Marshal(ret[2*numBytes:]) - montDecode(temp, &e.p.y.y) - temp.Marshal(ret[3*numBytes:]) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *G2) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - if len(m) < 4*numBytes { - return nil, errors.New("bn256: not enough data") - } - // Unmarshal the points and check their caps - if e.p == nil { - e.p = &twistPoint{} - } - var err error - if err = e.p.x.x.Unmarshal(m); err != nil { - return nil, err - } - if err = e.p.x.y.Unmarshal(m[numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.x.Unmarshal(m[2*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.y.Unmarshal(m[3*numBytes:]); err != nil { - return nil, err - } - // Encode into Montgomery form and ensure it's on the curve - montEncode(&e.p.x.x, &e.p.x.x) - montEncode(&e.p.x.y, &e.p.x.y) - montEncode(&e.p.y.x, &e.p.y.x) - montEncode(&e.p.y.y, &e.p.y.y) - - if e.p.x.IsZero() && e.p.y.IsZero() { - // This is the point at infinity. - e.p.y.SetOne() - e.p.z.SetZero() - e.p.t.SetZero() - } else { - e.p.z.SetOne() - e.p.t.SetOne() - - if !e.p.IsOnCurve() { - return nil, errors.New("bn256: malformed point") - } - } - return m[4*numBytes:], nil -} - -// GT is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type GT struct { - p *gfP12 -} - -// Pair calculates an Optimal Ate pairing. -func Pair(g1 *G1, g2 *G2) *GT { - return >{optimalAte(g2.p, g1.p)} -} - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - acc := new(gfP12) - acc.SetOne() - - for i := 0; i < len(a); i++ { - if a[i].p.IsInfinity() || b[i].p.IsInfinity() { - continue - } - acc.Mul(acc, miller(b[i].p, a[i].p)) - } - return finalExponentiation(acc).IsOne() -} - -// Miller applies Miller's algorithm, which is a bilinear function from the -// source groups to F_p^12. Miller(g1, g2).Finalize() is equivalent to Pair(g1, -// g2). -func Miller(g1 *G1, g2 *G2) *GT { - return >{miller(g2.p, g1.p)} -} - -func (g *GT) String() string { - return "bn256.GT" + g.p.String() -} - -// ScalarMult sets e to a*k and then returns e. -func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Exp(a.p, k) - return e -} - -// Add sets e to a+b and then returns e. -func (e *GT) Add(a, b *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Mul(a.p, b.p) - return e -} - -// Neg sets e to -a and then returns e. -func (e *GT) Neg(a *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Conjugate(a.p) - return e -} - -// Set sets e to a and then returns e. -func (e *GT) Set(a *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Set(a.p) - return e -} - -// Finalize is a linear function from F_p^12 to GT. -func (e *GT) Finalize() *GT { - ret := finalExponentiation(e.p) - e.p.Set(ret) - return e -} - -// Marshal converts e into a byte slice. -func (e *GT) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if e.p == nil { - e.p = &gfP12{} - e.p.SetOne() - } - - ret := make([]byte, numBytes*12) - temp := &gfP{} - - montDecode(temp, &e.p.x.x.x) - temp.Marshal(ret) - montDecode(temp, &e.p.x.x.y) - temp.Marshal(ret[numBytes:]) - montDecode(temp, &e.p.x.y.x) - temp.Marshal(ret[2*numBytes:]) - montDecode(temp, &e.p.x.y.y) - temp.Marshal(ret[3*numBytes:]) - montDecode(temp, &e.p.x.z.x) - temp.Marshal(ret[4*numBytes:]) - montDecode(temp, &e.p.x.z.y) - temp.Marshal(ret[5*numBytes:]) - montDecode(temp, &e.p.y.x.x) - temp.Marshal(ret[6*numBytes:]) - montDecode(temp, &e.p.y.x.y) - temp.Marshal(ret[7*numBytes:]) - montDecode(temp, &e.p.y.y.x) - temp.Marshal(ret[8*numBytes:]) - montDecode(temp, &e.p.y.y.y) - temp.Marshal(ret[9*numBytes:]) - montDecode(temp, &e.p.y.z.x) - temp.Marshal(ret[10*numBytes:]) - montDecode(temp, &e.p.y.z.y) - temp.Marshal(ret[11*numBytes:]) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *GT) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if len(m) < 12*numBytes { - return nil, errors.New("bn256: not enough data") - } - - if e.p == nil { - e.p = &gfP12{} - } - - var err error - if err = e.p.x.x.x.Unmarshal(m); err != nil { - return nil, err - } - if err = e.p.x.x.y.Unmarshal(m[numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.y.x.Unmarshal(m[2*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.y.y.Unmarshal(m[3*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.z.x.Unmarshal(m[4*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.z.y.Unmarshal(m[5*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.x.x.Unmarshal(m[6*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.x.y.Unmarshal(m[7*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.y.x.Unmarshal(m[8*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.y.y.Unmarshal(m[9*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.z.x.Unmarshal(m[10*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.z.y.Unmarshal(m[11*numBytes:]); err != nil { - return nil, err - } - montEncode(&e.p.x.x.x, &e.p.x.x.x) - montEncode(&e.p.x.x.y, &e.p.x.x.y) - montEncode(&e.p.x.y.x, &e.p.x.y.x) - montEncode(&e.p.x.y.y, &e.p.x.y.y) - montEncode(&e.p.x.z.x, &e.p.x.z.x) - montEncode(&e.p.x.z.y, &e.p.x.z.y) - montEncode(&e.p.y.x.x, &e.p.y.x.x) - montEncode(&e.p.y.x.y, &e.p.y.x.y) - montEncode(&e.p.y.y.x, &e.p.y.y.x) - montEncode(&e.p.y.y.y, &e.p.y.y.y) - montEncode(&e.p.y.z.x, &e.p.y.z.x) - montEncode(&e.p.y.z.y, &e.p.y.z.y) - - return m[12*numBytes:], nil -} diff --git a/builder/crypto/bn256/cloudflare/bn256_test.go b/builder/crypto/bn256/cloudflare/bn256_test.go deleted file mode 100644 index 481e2f78c..000000000 --- a/builder/crypto/bn256/cloudflare/bn256_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package bn256 - -import ( - "bytes" - "crypto/rand" - "testing" -) - -func TestG1Marshal(t *testing.T) { - _, Ga, err := RandomG1(rand.Reader) - if err != nil { - t.Fatal(err) - } - ma := Ga.Marshal() - - Gb := new(G1) - _, err = Gb.Unmarshal(ma) - if err != nil { - t.Fatal(err) - } - mb := Gb.Marshal() - - if !bytes.Equal(ma, mb) { - t.Fatal("bytes are different") - } -} - -func TestG2Marshal(t *testing.T) { - _, Ga, err := RandomG2(rand.Reader) - if err != nil { - t.Fatal(err) - } - ma := Ga.Marshal() - - Gb := new(G2) - _, err = Gb.Unmarshal(ma) - if err != nil { - t.Fatal(err) - } - mb := Gb.Marshal() - - if !bytes.Equal(ma, mb) { - t.Fatal("bytes are different") - } -} - -func TestBilinearity(t *testing.T) { - for i := 0; i < 2; i++ { - a, p1, _ := RandomG1(rand.Reader) - b, p2, _ := RandomG2(rand.Reader) - e1 := Pair(p1, p2) - - e2 := Pair(&G1{curveGen}, &G2{twistGen}) - e2.ScalarMult(e2, a) - e2.ScalarMult(e2, b) - - if *e1.p != *e2.p { - t.Fatalf("bad pairing result: %s", e1) - } - } -} - -func TestTripartiteDiffieHellman(t *testing.T) { - a, _ := rand.Int(rand.Reader, Order) - b, _ := rand.Int(rand.Reader, Order) - c, _ := rand.Int(rand.Reader, Order) - - pa, pb, pc := new(G1), new(G1), new(G1) - qa, qb, qc := new(G2), new(G2), new(G2) - - pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) - qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) - pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) - qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) - pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) - qc.Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) - - k1 := Pair(pb, qc) - k1.ScalarMult(k1, a) - k1Bytes := k1.Marshal() - - k2 := Pair(pc, qa) - k2.ScalarMult(k2, b) - k2Bytes := k2.Marshal() - - k3 := Pair(pa, qb) - k3.ScalarMult(k3, c) - k3Bytes := k3.Marshal() - - if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { - t.Errorf("keys didn't agree") - } -} - -func TestG2SelfAddition(t *testing.T) { - s, _ := rand.Int(rand.Reader, Order) - p := new(G2).ScalarBaseMult(s) - - if !p.p.IsOnCurve() { - t.Fatal("p isn't on curve") - } - m := p.Add(p, p).Marshal() - if _, err := p.Unmarshal(m); err != nil { - t.Fatalf("p.Add(p, p) ∉ Gâ‚‚: %v", err) - } -} - -func BenchmarkG1(b *testing.B) { - x, _ := rand.Int(rand.Reader, Order) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - new(G1).ScalarBaseMult(x) - } -} - -func BenchmarkG2(b *testing.B) { - x, _ := rand.Int(rand.Reader, Order) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - new(G2).ScalarBaseMult(x) - } -} -func BenchmarkPairing(b *testing.B) { - for i := 0; i < b.N; i++ { - Pair(&G1{curveGen}, &G2{twistGen}) - } -} diff --git a/builder/crypto/bn256/cloudflare/constants.go b/builder/crypto/bn256/cloudflare/constants.go deleted file mode 100644 index f7d2c7c00..000000000 --- a/builder/crypto/bn256/cloudflare/constants.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "math/big" -) - -func bigFromBase10(s string) *big.Int { - n, _ := new(big.Int).SetString(s, 10) - return n -} - -// u is the BN parameter. -var u = bigFromBase10("4965661367192848881") - -// Order is the number of elements in both Gâ‚ and Gâ‚‚: 36uâ´+36u³+18u²+6u+1. -// Needs to be highly 2-adic for efficient SNARK key and proof generation. -// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081. -// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters. -var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") - -// P is a prime over which we form a basic field: 36uâ´+36u³+24u²+6u+1. -var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") - -// p2 is p, represented as little-endian 64-bit words. -var p2 = [4]uint64{0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} - -// np is the negative inverse of p, mod 2^256. -var np = [4]uint64{0x87d20782e4866389, 0x9ede7d651eca6ac9, 0xd8afcbd01833da80, 0xf57a22b791888c6b} - -// rN1 is R^-1 where R = 2^256 mod p. -var rN1 = &gfP{0xed84884a014afa37, 0xeb2022850278edf8, 0xcf63e9cfb74492d9, 0x2e67157159e5c639} - -// r2 is R^2 where R = 2^256 mod p. -var r2 = &gfP{0xf32cfc5b538afa89, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f} - -// r3 is R^3 where R = 2^256 mod p. -var r3 = &gfP{0xb1cd6dafda1530df, 0x62f210e6a7283db6, 0xef7f0b0c0ada0afb, 0x20fd6e902d592544} - -// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9. -var xiToPMinus1Over6 = &gfP2{gfP{0xa222ae234c492d72, 0xd00f02a4565de15b, 0xdc2ff3a253dfc926, 0x10a75716b3899551}, gfP{0xaf9ba69633144907, 0xca6b1d7387afb78a, 0x11bded5ef08a2087, 0x02f34d751a1f3a7c}} - -// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9. -var xiToPMinus1Over3 = &gfP2{gfP{0x6e849f1ea0aa4757, 0xaa1c7b6d89f89141, 0xb6e713cdfae0ca3a, 0x26694fbb4e82ebc3}, gfP{0xb5773b104563ab30, 0x347f91c8a9aa6454, 0x7a007127242e0991, 0x1956bcd8118214ec}} - -// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9. -var xiToPMinus1Over2 = &gfP2{gfP{0xa1d77ce45ffe77c7, 0x07affd117826d1db, 0x6d16bd27bb7edc6b, 0x2c87200285defecc}, gfP{0xe4bbdd0c2936b629, 0xbb30f162e133bacb, 0x31a9d1b6f9645366, 0x253570bea500f8dd}} - -// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9. -var xiToPSquaredMinus1Over3 = &gfP{0x3350c88e13e80b9c, 0x7dce557cdb5e56b9, 0x6001b4b8b615564a, 0x2682e617020217e0} - -// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p). -var xiTo2PSquaredMinus2Over3 = &gfP{0x71930c11d782e155, 0xa6bb947cffbe3323, 0xaa303344d4741444, 0x2c3b3f0d26594943} - -// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p). -var xiToPSquaredMinus1Over6 = &gfP{0xca8d800500fa1bf2, 0xf0c5d61468b39769, 0x0e201271ad0d4418, 0x04290f65bad856e6} - -// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9. -var xiTo2PMinus2Over3 = &gfP2{gfP{0x5dddfd154bd8c949, 0x62cb29a5a4445b60, 0x37bc870a0c7dd2b9, 0x24830a9d3171f0fd}, gfP{0x7361d77f843abe92, 0xa5bb2bd3273411fb, 0x9c941f314b3e2399, 0x15df9cddbb9fd3ec}} diff --git a/builder/crypto/bn256/cloudflare/curve.go b/builder/crypto/bn256/cloudflare/curve.go deleted file mode 100644 index 16f0489e3..000000000 --- a/builder/crypto/bn256/cloudflare/curve.go +++ /dev/null @@ -1,238 +0,0 @@ -package bn256 - -import ( - "math/big" -) - -// curvePoint implements the elliptic curve y²=x³+3. Points are kept in Jacobian -// form and t=z² when valid. Gâ‚ is the set of points of this curve on GF(p). -type curvePoint struct { - x, y, z, t gfP -} - -var curveB = newGFp(3) - -// curveGen is the generator of Gâ‚. -var curveGen = &curvePoint{ - x: *newGFp(1), - y: *newGFp(2), - z: *newGFp(1), - t: *newGFp(1), -} - -func (c *curvePoint) String() string { - c.MakeAffine() - x, y := &gfP{}, &gfP{} - montDecode(x, &c.x) - montDecode(y, &c.y) - return "(" + x.String() + ", " + y.String() + ")" -} - -func (c *curvePoint) Set(a *curvePoint) { - c.x.Set(&a.x) - c.y.Set(&a.y) - c.z.Set(&a.z) - c.t.Set(&a.t) -} - -// IsOnCurve returns true iff c is on the curve. -func (c *curvePoint) IsOnCurve() bool { - c.MakeAffine() - if c.IsInfinity() { - return true - } - - y2, x3 := &gfP{}, &gfP{} - gfpMul(y2, &c.y, &c.y) - gfpMul(x3, &c.x, &c.x) - gfpMul(x3, x3, &c.x) - gfpAdd(x3, x3, curveB) - - return *y2 == *x3 -} - -func (c *curvePoint) SetInfinity() { - c.x = gfP{0} - c.y = *newGFp(1) - c.z = gfP{0} - c.t = gfP{0} -} - -func (c *curvePoint) IsInfinity() bool { - return c.z == gfP{0} -} - -func (c *curvePoint) Add(a, b *curvePoint) { - if a.IsInfinity() { - c.Set(b) - return - } - if b.IsInfinity() { - c.Set(a) - return - } - - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 - - // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] - // by [u1:s1:z1·z2] and [u2:s2:z1·z2] - // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ - z12, z22 := &gfP{}, &gfP{} - gfpMul(z12, &a.z, &a.z) - gfpMul(z22, &b.z, &b.z) - - u1, u2 := &gfP{}, &gfP{} - gfpMul(u1, &a.x, z22) - gfpMul(u2, &b.x, z12) - - t, s1 := &gfP{}, &gfP{} - gfpMul(t, &b.z, z22) - gfpMul(s1, &a.y, t) - - s2 := &gfP{} - gfpMul(t, &a.z, z12) - gfpMul(s2, &b.y, t) - - // Compute x = (2h)²(s²-u1-u2) - // where s = (s2-s1)/(u2-u1) is the slope of the line through - // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. - // This is also: - // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) - // = r² - j - 2v - // with the notations below. - h := &gfP{} - gfpSub(h, u2, u1) - xEqual := *h == gfP{0} - - gfpAdd(t, h, h) - // i = 4h² - i := &gfP{} - gfpMul(i, t, t) - // j = 4h³ - j := &gfP{} - gfpMul(j, h, i) - - gfpSub(t, s2, s1) - yEqual := *t == gfP{0} - if xEqual && yEqual { - c.Double(a) - return - } - r := &gfP{} - gfpAdd(r, t, t) - - v := &gfP{} - gfpMul(v, u1, i) - - // t4 = 4(s2-s1)² - t4, t6 := &gfP{}, &gfP{} - gfpMul(t4, r, r) - gfpAdd(t, v, v) - gfpSub(t6, t4, j) - - gfpSub(&c.x, t6, t) - - // Set y = -(2h)³(s1 + s*(x/4h²-u1)) - // This is also - // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j - gfpSub(t, v, &c.x) // t7 - gfpMul(t4, s1, j) // t8 - gfpAdd(t6, t4, t4) // t9 - gfpMul(t4, r, t) // t10 - gfpSub(&c.y, t4, t6) - - // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 - gfpAdd(t, &a.z, &b.z) // t11 - gfpMul(t4, t, t) // t12 - gfpSub(t, t4, z12) // t13 - gfpSub(t4, t, z22) // t14 - gfpMul(&c.z, t4, h) -} - -func (c *curvePoint) Double(a *curvePoint) { - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 - A, B, C := &gfP{}, &gfP{}, &gfP{} - gfpMul(A, &a.x, &a.x) - gfpMul(B, &a.y, &a.y) - gfpMul(C, B, B) - - t, t2 := &gfP{}, &gfP{} - gfpAdd(t, &a.x, B) - gfpMul(t2, t, t) - gfpSub(t, t2, A) - gfpSub(t2, t, C) - - d, e, f := &gfP{}, &gfP{}, &gfP{} - gfpAdd(d, t2, t2) - gfpAdd(t, A, A) - gfpAdd(e, t, A) - gfpMul(f, e, e) - - gfpAdd(t, d, d) - gfpSub(&c.x, f, t) - - gfpMul(&c.z, &a.y, &a.z) - gfpAdd(&c.z, &c.z, &c.z) - - gfpAdd(t, C, C) - gfpAdd(t2, t, t) - gfpAdd(t, t2, t2) - gfpSub(&c.y, d, &c.x) - gfpMul(t2, e, &c.y) - gfpSub(&c.y, t2, t) -} - -func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) { - precomp := [1 << 2]*curvePoint{nil, {}, {}, {}} - precomp[1].Set(a) - precomp[2].Set(a) - gfpMul(&precomp[2].x, &precomp[2].x, xiTo2PSquaredMinus2Over3) - precomp[3].Add(precomp[1], precomp[2]) - - multiScalar := curveLattice.Multi(scalar) - - sum := &curvePoint{} - sum.SetInfinity() - t := &curvePoint{} - - for i := len(multiScalar) - 1; i >= 0; i-- { - t.Double(sum) - if multiScalar[i] == 0 { - sum.Set(t) - } else { - sum.Add(t, precomp[multiScalar[i]]) - } - } - c.Set(sum) -} - -func (c *curvePoint) MakeAffine() { - if c.z == *newGFp(1) { - return - } else if c.z == *newGFp(0) { - c.x = gfP{0} - c.y = *newGFp(1) - c.t = gfP{0} - return - } - - zInv := &gfP{} - zInv.Invert(&c.z) - - t, zInv2 := &gfP{}, &gfP{} - gfpMul(t, &c.y, zInv) - gfpMul(zInv2, zInv, zInv) - - gfpMul(&c.x, &c.x, zInv2) - gfpMul(&c.y, t, zInv2) - - c.z = *newGFp(1) - c.t = *newGFp(1) -} - -func (c *curvePoint) Neg(a *curvePoint) { - c.x.Set(&a.x) - gfpNeg(&c.y, &a.y) - c.z.Set(&a.z) - c.t = gfP{0} -} diff --git a/builder/crypto/bn256/cloudflare/example_test.go b/builder/crypto/bn256/cloudflare/example_test.go deleted file mode 100644 index 6c285995c..000000000 --- a/builder/crypto/bn256/cloudflare/example_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "crypto/rand" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestExamplePair(t *testing.T) { - // This implements the tripartite Diffie-Hellman algorithm from "A One - // Round Protocol for Tripartite Diffie-Hellman", A. Joux. - // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf - - // Each of three parties, a, b and c, generate a private value. - a, _ := rand.Int(rand.Reader, Order) - b, _ := rand.Int(rand.Reader, Order) - c, _ := rand.Int(rand.Reader, Order) - - // Then each party calculates gâ‚ and gâ‚‚ times their private value. - pa := new(G1).ScalarBaseMult(a) - qa := new(G2).ScalarBaseMult(a) - - pb := new(G1).ScalarBaseMult(b) - qb := new(G2).ScalarBaseMult(b) - - pc := new(G1).ScalarBaseMult(c) - qc := new(G2).ScalarBaseMult(c) - - // Now each party exchanges its public values with the other two and - // all parties can calculate the shared key. - k1 := Pair(pb, qc) - k1.ScalarMult(k1, a) - - k2 := Pair(pc, qa) - k2.ScalarMult(k2, b) - - k3 := Pair(pa, qb) - k3.ScalarMult(k3, c) - - // k1, k2 and k3 will all be equal. - - require.Equal(t, k1, k2) - require.Equal(t, k1, k3) - - require.Equal(t, len(np), 4) //Avoid gometalinter varcheck err on np -} diff --git a/builder/crypto/bn256/cloudflare/gfp.go b/builder/crypto/bn256/cloudflare/gfp.go deleted file mode 100644 index b15e1697e..000000000 --- a/builder/crypto/bn256/cloudflare/gfp.go +++ /dev/null @@ -1,82 +0,0 @@ -package bn256 - -import ( - "errors" - "fmt" -) - -type gfP [4]uint64 - -func newGFp(x int64) (out *gfP) { - if x >= 0 { - out = &gfP{uint64(x)} - } else { - out = &gfP{uint64(-x)} - gfpNeg(out, out) - } - - montEncode(out, out) - return out -} - -func (e *gfP) String() string { - return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0]) -} - -func (e *gfP) Set(f *gfP) { - e[0] = f[0] - e[1] = f[1] - e[2] = f[2] - e[3] = f[3] -} - -func (e *gfP) Invert(f *gfP) { - bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} - - sum, power := &gfP{}, &gfP{} - sum.Set(rN1) - power.Set(f) - - for word := 0; word < 4; word++ { - for bit := uint(0); bit < 64; bit++ { - if (bits[word]>>bit)&1 == 1 { - gfpMul(sum, sum, power) - } - gfpMul(power, power, power) - } - } - - gfpMul(sum, sum, r3) - e.Set(sum) -} - -func (e *gfP) Marshal(out []byte) { - for w := uint(0); w < 4; w++ { - for b := uint(0); b < 8; b++ { - out[8*w+b] = byte(e[3-w] >> (56 - 8*b)) - } - } -} - -func (e *gfP) Unmarshal(in []byte) error { - // Unmarshal the bytes into little endian form - for w := uint(0); w < 4; w++ { - e[3-w] = 0 - for b := uint(0); b < 8; b++ { - e[3-w] += uint64(in[8*w+b]) << (56 - 8*b) - } - } - // Ensure the point respects the curve modulus - for i := 3; i >= 0; i-- { - if e[i] < p2[i] { - return nil - } - if e[i] > p2[i] { - return errors.New("bn256: coordinate exceeds modulus") - } - } - return errors.New("bn256: coordinate equals modulus") -} - -func montEncode(c, a *gfP) { gfpMul(c, a, r2) } -func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) } diff --git a/builder/crypto/bn256/cloudflare/gfp12.go b/builder/crypto/bn256/cloudflare/gfp12.go deleted file mode 100644 index 93fb368a7..000000000 --- a/builder/crypto/bn256/cloudflare/gfp12.go +++ /dev/null @@ -1,160 +0,0 @@ -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -import ( - "math/big" -) - -// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 -// where ω²=Ï„. -type gfP12 struct { - x, y gfP6 // value is xω + y -} - -func (e *gfP12) String() string { - return "(" + e.x.String() + "," + e.y.String() + ")" -} - -func (e *gfP12) Set(a *gfP12) *gfP12 { - e.x.Set(&a.x) - e.y.Set(&a.y) - return e -} - -func (e *gfP12) SetZero() *gfP12 { - e.x.SetZero() - e.y.SetZero() - return e -} - -func (e *gfP12) SetOne() *gfP12 { - e.x.SetZero() - e.y.SetOne() - return e -} - -func (e *gfP12) IsZero() bool { - return e.x.IsZero() && e.y.IsZero() -} - -func (e *gfP12) IsOne() bool { - return e.x.IsZero() && e.y.IsOne() -} - -func (e *gfP12) Conjugate(a *gfP12) *gfP12 { - e.x.Neg(&a.x) - e.y.Set(&a.y) - return e -} - -func (e *gfP12) Neg(a *gfP12) *gfP12 { - e.x.Neg(&a.x) - e.y.Neg(&a.y) - return e -} - -// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p -func (e *gfP12) Frobenius(a *gfP12) *gfP12 { - e.x.Frobenius(&a.x) - e.y.Frobenius(&a.y) - e.x.MulScalar(&e.x, xiToPMinus1Over6) - return e -} - -// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² -func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { - e.x.FrobeniusP2(&a.x) - e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6) - e.y.FrobeniusP2(&a.y) - return e -} - -func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 { - e.x.FrobeniusP4(&a.x) - e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3) - e.y.FrobeniusP4(&a.y) - return e -} - -func (e *gfP12) Add(a, b *gfP12) *gfP12 { - e.x.Add(&a.x, &b.x) - e.y.Add(&a.y, &b.y) - return e -} - -func (e *gfP12) Sub(a, b *gfP12) *gfP12 { - e.x.Sub(&a.x, &b.x) - e.y.Sub(&a.y, &b.y) - return e -} - -func (e *gfP12) Mul(a, b *gfP12) *gfP12 { - tx := (&gfP6{}).Mul(&a.x, &b.y) - t := (&gfP6{}).Mul(&b.x, &a.y) - tx.Add(tx, t) - - ty := (&gfP6{}).Mul(&a.y, &b.y) - t.Mul(&a.x, &b.x).MulTau(t) - - e.x.Set(tx) - e.y.Add(ty, t) - return e -} - -func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 { - e.x.Mul(&e.x, b) - e.y.Mul(&e.y, b) - return e -} - -func (c *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 { - sum := (&gfP12{}).SetOne() - t := &gfP12{} - - for i := power.BitLen() - 1; i >= 0; i-- { - t.Square(sum) - if power.Bit(i) != 0 { - sum.Mul(t, a) - } else { - sum.Set(t) - } - } - - c.Set(sum) - return c -} - -func (e *gfP12) Square(a *gfP12) *gfP12 { - // Complex squaring algorithm - v0 := (&gfP6{}).Mul(&a.x, &a.y) - - t := (&gfP6{}).MulTau(&a.x) - t.Add(&a.y, t) - ty := (&gfP6{}).Add(&a.x, &a.y) - ty.Mul(ty, t).Sub(ty, v0) - t.MulTau(v0) - ty.Sub(ty, t) - - e.x.Add(v0, v0) - e.y.Set(ty) - return e -} - -func (e *gfP12) Invert(a *gfP12) *gfP12 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - t1, t2 := &gfP6{}, &gfP6{} - - t1.Square(&a.x) - t2.Square(&a.y) - t1.MulTau(t1).Sub(t2, t1) - t2.Invert(t1) - - e.x.Neg(&a.x) - e.y.Set(&a.y) - e.MulScalar(e, t2) - return e -} diff --git a/builder/crypto/bn256/cloudflare/gfp2.go b/builder/crypto/bn256/cloudflare/gfp2.go deleted file mode 100644 index 90a89e8b4..000000000 --- a/builder/crypto/bn256/cloudflare/gfp2.go +++ /dev/null @@ -1,156 +0,0 @@ -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -// gfP2 implements a field of size p² as a quadratic extension of the base field -// where i²=-1. -type gfP2 struct { - x, y gfP // value is xi+y. -} - -func gfP2Decode(in *gfP2) *gfP2 { - out := &gfP2{} - montDecode(&out.x, &in.x) - montDecode(&out.y, &in.y) - return out -} - -func (e *gfP2) String() string { - return "(" + e.x.String() + ", " + e.y.String() + ")" -} - -func (e *gfP2) Set(a *gfP2) *gfP2 { - e.x.Set(&a.x) - e.y.Set(&a.y) - return e -} - -func (e *gfP2) SetZero() *gfP2 { - e.x = gfP{0} - e.y = gfP{0} - return e -} - -func (e *gfP2) SetOne() *gfP2 { - e.x = gfP{0} - e.y = *newGFp(1) - return e -} - -func (e *gfP2) IsZero() bool { - zero := gfP{0} - return e.x == zero && e.y == zero -} - -func (e *gfP2) IsOne() bool { - zero, one := gfP{0}, *newGFp(1) - return e.x == zero && e.y == one -} - -func (e *gfP2) Conjugate(a *gfP2) *gfP2 { - e.y.Set(&a.y) - gfpNeg(&e.x, &a.x) - return e -} - -func (e *gfP2) Neg(a *gfP2) *gfP2 { - gfpNeg(&e.x, &a.x) - gfpNeg(&e.y, &a.y) - return e -} - -func (e *gfP2) Add(a, b *gfP2) *gfP2 { - gfpAdd(&e.x, &a.x, &b.x) - gfpAdd(&e.y, &a.y, &b.y) - return e -} - -func (e *gfP2) Sub(a, b *gfP2) *gfP2 { - gfpSub(&e.x, &a.x, &b.x) - gfpSub(&e.y, &a.y, &b.y) - return e -} - -// See "Multiplication and Squaring in Pairing-Friendly Fields", -// http://eprint.iacr.org/2006/471.pdf -func (e *gfP2) Mul(a, b *gfP2) *gfP2 { - tx, t := &gfP{}, &gfP{} - gfpMul(tx, &a.x, &b.y) - gfpMul(t, &b.x, &a.y) - gfpAdd(tx, tx, t) - - ty := &gfP{} - gfpMul(ty, &a.y, &b.y) - gfpMul(t, &a.x, &b.x) - gfpSub(ty, ty, t) - - e.x.Set(tx) - e.y.Set(ty) - return e -} - -func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 { - gfpMul(&e.x, &a.x, b) - gfpMul(&e.y, &a.y, b) - return e -} - -// MulXi sets e=ξa where ξ=i+9 and then returns e. -func (e *gfP2) MulXi(a *gfP2) *gfP2 { - // (xi+y)(i+9) = (9x+y)i+(9y-x) - tx := &gfP{} - gfpAdd(tx, &a.x, &a.x) - gfpAdd(tx, tx, tx) - gfpAdd(tx, tx, tx) - gfpAdd(tx, tx, &a.x) - - gfpAdd(tx, tx, &a.y) - - ty := &gfP{} - gfpAdd(ty, &a.y, &a.y) - gfpAdd(ty, ty, ty) - gfpAdd(ty, ty, ty) - gfpAdd(ty, ty, &a.y) - - gfpSub(ty, ty, &a.x) - - e.x.Set(tx) - e.y.Set(ty) - return e -} - -func (e *gfP2) Square(a *gfP2) *gfP2 { - // Complex squaring algorithm: - // (xi+y)² = (x+y)(y-x) + 2*i*x*y - tx, ty := &gfP{}, &gfP{} - gfpSub(tx, &a.y, &a.x) - gfpAdd(ty, &a.x, &a.y) - gfpMul(ty, tx, ty) - - gfpMul(tx, &a.x, &a.y) - gfpAdd(tx, tx, tx) - - e.x.Set(tx) - e.y.Set(ty) - return e -} - -func (e *gfP2) Invert(a *gfP2) *gfP2 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - t1, t2 := &gfP{}, &gfP{} - gfpMul(t1, &a.x, &a.x) - gfpMul(t2, &a.y, &a.y) - gfpAdd(t1, t1, t2) - - inv := &gfP{} - inv.Invert(t1) - - gfpNeg(t1, &a.x) - - gfpMul(&e.x, t1, inv) - gfpMul(&e.y, &a.y, inv) - return e -} diff --git a/builder/crypto/bn256/cloudflare/gfp6.go b/builder/crypto/bn256/cloudflare/gfp6.go deleted file mode 100644 index a42734911..000000000 --- a/builder/crypto/bn256/cloudflare/gfp6.go +++ /dev/null @@ -1,213 +0,0 @@ -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -// gfP6 implements the field of size pⶠas a cubic extension of gfP2 where τ³=ξ -// and ξ=i+9. -type gfP6 struct { - x, y, z gfP2 // value is xτ² + yÏ„ + z -} - -func (e *gfP6) String() string { - return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" -} - -func (e *gfP6) Set(a *gfP6) *gfP6 { - e.x.Set(&a.x) - e.y.Set(&a.y) - e.z.Set(&a.z) - return e -} - -func (e *gfP6) SetZero() *gfP6 { - e.x.SetZero() - e.y.SetZero() - e.z.SetZero() - return e -} - -func (e *gfP6) SetOne() *gfP6 { - e.x.SetZero() - e.y.SetZero() - e.z.SetOne() - return e -} - -func (e *gfP6) IsZero() bool { - return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() -} - -func (e *gfP6) IsOne() bool { - return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() -} - -func (e *gfP6) Neg(a *gfP6) *gfP6 { - e.x.Neg(&a.x) - e.y.Neg(&a.y) - e.z.Neg(&a.z) - return e -} - -func (e *gfP6) Frobenius(a *gfP6) *gfP6 { - e.x.Conjugate(&a.x) - e.y.Conjugate(&a.y) - e.z.Conjugate(&a.z) - - e.x.Mul(&e.x, xiTo2PMinus2Over3) - e.y.Mul(&e.y, xiToPMinus1Over3) - return e -} - -// FrobeniusP2 computes (xτ²+yÏ„+z)^(p²) = xÏ„^(2p²) + yÏ„^(p²) + z -func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { - // Ï„^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) - e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3) - // Ï„^(p²) = Ï„Ï„^(p²-1) = τξ^((p²-1)/3) - e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3) - e.z.Set(&a.z) - return e -} - -func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { - e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) - e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3) - e.z.Set(&a.z) - return e -} - -func (e *gfP6) Add(a, b *gfP6) *gfP6 { - e.x.Add(&a.x, &b.x) - e.y.Add(&a.y, &b.y) - e.z.Add(&a.z, &b.z) - return e -} - -func (e *gfP6) Sub(a, b *gfP6) *gfP6 { - e.x.Sub(&a.x, &b.x) - e.y.Sub(&a.y, &b.y) - e.z.Sub(&a.z, &b.z) - return e -} - -func (e *gfP6) Mul(a, b *gfP6) *gfP6 { - // "Multiplication and Squaring on Pairing-Friendly Fields" - // Section 4, Karatsuba method. - // http://eprint.iacr.org/2006/471.pdf - v0 := (&gfP2{}).Mul(&a.z, &b.z) - v1 := (&gfP2{}).Mul(&a.y, &b.y) - v2 := (&gfP2{}).Mul(&a.x, &b.x) - - t0 := (&gfP2{}).Add(&a.x, &a.y) - t1 := (&gfP2{}).Add(&b.x, &b.y) - tz := (&gfP2{}).Mul(t0, t1) - tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0) - - t0.Add(&a.y, &a.z) - t1.Add(&b.y, &b.z) - ty := (&gfP2{}).Mul(t0, t1) - t0.MulXi(v2) - ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0) - - t0.Add(&a.x, &a.z) - t1.Add(&b.x, &b.z) - tx := (&gfP2{}).Mul(t0, t1) - tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2) - - e.x.Set(tx) - e.y.Set(ty) - e.z.Set(tz) - return e -} - -func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { - e.x.Mul(&a.x, b) - e.y.Mul(&a.y, b) - e.z.Mul(&a.z, b) - return e -} - -func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 { - e.x.MulScalar(&a.x, b) - e.y.MulScalar(&a.y, b) - e.z.MulScalar(&a.z, b) - return e -} - -// MulTau computes τ·(aτ²+bÏ„+c) = bτ²+cÏ„+aξ -func (e *gfP6) MulTau(a *gfP6) *gfP6 { - tz := (&gfP2{}).MulXi(&a.x) - ty := (&gfP2{}).Set(&a.y) - - e.y.Set(&a.z) - e.x.Set(ty) - e.z.Set(tz) - return e -} - -func (e *gfP6) Square(a *gfP6) *gfP6 { - v0 := (&gfP2{}).Square(&a.z) - v1 := (&gfP2{}).Square(&a.y) - v2 := (&gfP2{}).Square(&a.x) - - c0 := (&gfP2{}).Add(&a.x, &a.y) - c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0) - - c1 := (&gfP2{}).Add(&a.y, &a.z) - c1.Square(c1).Sub(c1, v0).Sub(c1, v1) - xiV2 := (&gfP2{}).MulXi(v2) - c1.Add(c1, xiV2) - - c2 := (&gfP2{}).Add(&a.x, &a.z) - c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2) - - e.x.Set(c2) - e.y.Set(c1) - e.z.Set(c0) - return e -} - -func (e *gfP6) Invert(a *gfP6) *gfP6 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - - // Here we can give a short explanation of how it works: let j be a cubic root of - // unity in GF(p²) so that 1+j+j²=0. - // Then (xτ² + yÏ„ + z)(xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) - // = (xτ² + yÏ„ + z)(Cτ²+BÏ„+A) - // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). - // - // On the other hand (xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) - // = τ²(y²-ξxz) + Ï„(ξx²-yz) + (z²-ξxy) - // - // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) - t1 := (&gfP2{}).Mul(&a.x, &a.y) - t1.MulXi(t1) - - A := (&gfP2{}).Square(&a.z) - A.Sub(A, t1) - - B := (&gfP2{}).Square(&a.x) - B.MulXi(B) - t1.Mul(&a.y, &a.z) - B.Sub(B, t1) - - C := (&gfP2{}).Square(&a.y) - t1.Mul(&a.x, &a.z) - C.Sub(C, t1) - - F := (&gfP2{}).Mul(C, &a.y) - F.MulXi(F) - t1.Mul(A, &a.z) - F.Add(F, t1) - t1.Mul(B, &a.x).MulXi(t1) - F.Add(F, t1) - - F.Invert(F) - - e.x.Mul(C, F) - e.y.Mul(B, F) - e.z.Mul(A, F) - return e -} diff --git a/builder/crypto/bn256/cloudflare/gfp_amd64.s b/builder/crypto/bn256/cloudflare/gfp_amd64.s deleted file mode 100644 index 64c97eaed..000000000 --- a/builder/crypto/bn256/cloudflare/gfp_amd64.s +++ /dev/null @@ -1,129 +0,0 @@ -// +build amd64,!generic - -#define storeBlock(a0,a1,a2,a3, r) \ - MOVQ a0, 0+r \ - MOVQ a1, 8+r \ - MOVQ a2, 16+r \ - MOVQ a3, 24+r - -#define loadBlock(r, a0,a1,a2,a3) \ - MOVQ 0+r, a0 \ - MOVQ 8+r, a1 \ - MOVQ 16+r, a2 \ - MOVQ 24+r, a3 - -#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \ - \ // b = a-p - MOVQ a0, b0 \ - MOVQ a1, b1 \ - MOVQ a2, b2 \ - MOVQ a3, b3 \ - MOVQ a4, b4 \ - \ - SUBQ ·p2+0(SB), b0 \ - SBBQ ·p2+8(SB), b1 \ - SBBQ ·p2+16(SB), b2 \ - SBBQ ·p2+24(SB), b3 \ - SBBQ $0, b4 \ - \ - \ // if b is negative then return a - \ // else return b - CMOVQCC b0, a0 \ - CMOVQCC b1, a1 \ - CMOVQCC b2, a2 \ - CMOVQCC b3, a3 - -#include "mul_amd64.h" -#include "mul_bmi2_amd64.h" - -TEXT ·gfpNeg(SB),0,$0-16 - MOVQ ·p2+0(SB), R8 - MOVQ ·p2+8(SB), R9 - MOVQ ·p2+16(SB), R10 - MOVQ ·p2+24(SB), R11 - - MOVQ a+8(FP), DI - SUBQ 0(DI), R8 - SBBQ 8(DI), R9 - SBBQ 16(DI), R10 - SBBQ 24(DI), R11 - - MOVQ $0, AX - gfpCarry(R8,R9,R10,R11,AX, R12,R13,R14,CX,BX) - - MOVQ c+0(FP), DI - storeBlock(R8,R9,R10,R11, 0(DI)) - RET - -TEXT ·gfpAdd(SB),0,$0-24 - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - - loadBlock(0(DI), R8,R9,R10,R11) - MOVQ $0, R12 - - ADDQ 0(SI), R8 - ADCQ 8(SI), R9 - ADCQ 16(SI), R10 - ADCQ 24(SI), R11 - ADCQ $0, R12 - - gfpCarry(R8,R9,R10,R11,R12, R13,R14,CX,AX,BX) - - MOVQ c+0(FP), DI - storeBlock(R8,R9,R10,R11, 0(DI)) - RET - -TEXT ·gfpSub(SB),0,$0-24 - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - - loadBlock(0(DI), R8,R9,R10,R11) - - MOVQ ·p2+0(SB), R12 - MOVQ ·p2+8(SB), R13 - MOVQ ·p2+16(SB), R14 - MOVQ ·p2+24(SB), CX - MOVQ $0, AX - - SUBQ 0(SI), R8 - SBBQ 8(SI), R9 - SBBQ 16(SI), R10 - SBBQ 24(SI), R11 - - CMOVQCC AX, R12 - CMOVQCC AX, R13 - CMOVQCC AX, R14 - CMOVQCC AX, CX - - ADDQ R12, R8 - ADCQ R13, R9 - ADCQ R14, R10 - ADCQ CX, R11 - - MOVQ c+0(FP), DI - storeBlock(R8,R9,R10,R11, 0(DI)) - RET - -TEXT ·gfpMul(SB),0,$160-24 - MOVQ a+8(FP), DI - MOVQ b+16(FP), SI - - // Jump to a slightly different implementation if MULX isn't supported. - CMPB ·hasBMI2(SB), $0 - JE nobmi2Mul - - mulBMI2(0(DI),8(DI),16(DI),24(DI), 0(SI)) - storeBlock( R8, R9,R10,R11, 0(SP)) - storeBlock(R12,R13,R14,CX, 32(SP)) - gfpReduceBMI2() - JMP end - -nobmi2Mul: - mul(0(DI),8(DI),16(DI),24(DI), 0(SI), 0(SP)) - gfpReduce(0(SP)) - -end: - MOVQ c+0(FP), DI - storeBlock(R12,R13,R14,CX, 0(DI)) - RET diff --git a/builder/crypto/bn256/cloudflare/gfp_arm64.s b/builder/crypto/bn256/cloudflare/gfp_arm64.s deleted file mode 100644 index c65e80168..000000000 --- a/builder/crypto/bn256/cloudflare/gfp_arm64.s +++ /dev/null @@ -1,113 +0,0 @@ -// +build arm64,!generic - -#define storeBlock(a0,a1,a2,a3, r) \ - MOVD a0, 0+r \ - MOVD a1, 8+r \ - MOVD a2, 16+r \ - MOVD a3, 24+r - -#define loadBlock(r, a0,a1,a2,a3) \ - MOVD 0+r, a0 \ - MOVD 8+r, a1 \ - MOVD 16+r, a2 \ - MOVD 24+r, a3 - -#define loadModulus(p0,p1,p2,p3) \ - MOVD ·p2+0(SB), p0 \ - MOVD ·p2+8(SB), p1 \ - MOVD ·p2+16(SB), p2 \ - MOVD ·p2+24(SB), p3 - -#include "mul_arm64.h" - -TEXT ·gfpNeg(SB),0,$0-16 - MOVD a+8(FP), R0 - loadBlock(0(R0), R1,R2,R3,R4) - loadModulus(R5,R6,R7,R8) - - SUBS R1, R5, R1 - SBCS R2, R6, R2 - SBCS R3, R7, R3 - SBCS R4, R8, R4 - - SUBS R5, R1, R5 - SBCS R6, R2, R6 - SBCS R7, R3, R7 - SBCS R8, R4, R8 - - CSEL CS, R5, R1, R1 - CSEL CS, R6, R2, R2 - CSEL CS, R7, R3, R3 - CSEL CS, R8, R4, R4 - - MOVD c+0(FP), R0 - storeBlock(R1,R2,R3,R4, 0(R0)) - RET - -TEXT ·gfpAdd(SB),0,$0-24 - MOVD a+8(FP), R0 - loadBlock(0(R0), R1,R2,R3,R4) - MOVD b+16(FP), R0 - loadBlock(0(R0), R5,R6,R7,R8) - loadModulus(R9,R10,R11,R12) - MOVD ZR, R0 - - ADDS R5, R1 - ADCS R6, R2 - ADCS R7, R3 - ADCS R8, R4 - ADCS ZR, R0 - - SUBS R9, R1, R5 - SBCS R10, R2, R6 - SBCS R11, R3, R7 - SBCS R12, R4, R8 - SBCS ZR, R0, R0 - - CSEL CS, R5, R1, R1 - CSEL CS, R6, R2, R2 - CSEL CS, R7, R3, R3 - CSEL CS, R8, R4, R4 - - MOVD c+0(FP), R0 - storeBlock(R1,R2,R3,R4, 0(R0)) - RET - -TEXT ·gfpSub(SB),0,$0-24 - MOVD a+8(FP), R0 - loadBlock(0(R0), R1,R2,R3,R4) - MOVD b+16(FP), R0 - loadBlock(0(R0), R5,R6,R7,R8) - loadModulus(R9,R10,R11,R12) - - SUBS R5, R1 - SBCS R6, R2 - SBCS R7, R3 - SBCS R8, R4 - - CSEL CS, ZR, R9, R9 - CSEL CS, ZR, R10, R10 - CSEL CS, ZR, R11, R11 - CSEL CS, ZR, R12, R12 - - ADDS R9, R1 - ADCS R10, R2 - ADCS R11, R3 - ADCS R12, R4 - - MOVD c+0(FP), R0 - storeBlock(R1,R2,R3,R4, 0(R0)) - RET - -TEXT ·gfpMul(SB),0,$0-24 - MOVD a+8(FP), R0 - loadBlock(0(R0), R1,R2,R3,R4) - MOVD b+16(FP), R0 - loadBlock(0(R0), R5,R6,R7,R8) - - mul(R9,R10,R11,R12,R13,R14,R15,R16) - gfpReduce() - - MOVD c+0(FP), R0 - storeBlock(R1,R2,R3,R4, 0(R0)) - RET diff --git a/builder/crypto/bn256/cloudflare/gfp_decl.go b/builder/crypto/bn256/cloudflare/gfp_decl.go deleted file mode 100644 index cf7f56542..000000000 --- a/builder/crypto/bn256/cloudflare/gfp_decl.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build (amd64 && !generic) || (arm64 && !generic) -// +build amd64,!generic arm64,!generic - -package bn256 - -// This file contains forward declarations for the architecture-specific -// assembly implementations of these functions, provided that they exist. - -import ( - "golang.org/x/sys/cpu" -) - -//nolint:varcheck,unused,deadcode -var hasBMI2 = cpu.X86.HasBMI2 - -// go:noescape -func gfpNeg(c, a *gfP) - -//go:noescape -func gfpAdd(c, a, b *gfP) - -//go:noescape -func gfpSub(c, a, b *gfP) - -//go:noescape -func gfpMul(c, a, b *gfP) diff --git a/builder/crypto/bn256/cloudflare/gfp_generic.go b/builder/crypto/bn256/cloudflare/gfp_generic.go deleted file mode 100644 index 7742dda4c..000000000 --- a/builder/crypto/bn256/cloudflare/gfp_generic.go +++ /dev/null @@ -1,174 +0,0 @@ -//go:build (!amd64 && !arm64) || generic -// +build !amd64,!arm64 generic - -package bn256 - -func gfpCarry(a *gfP, head uint64) { - b := &gfP{} - - var carry uint64 - for i, pi := range p2 { - ai := a[i] - bi := ai - pi - carry - b[i] = bi - carry = (pi&^ai | (pi|^ai)&bi) >> 63 - } - carry = carry &^ head - - // If b is negative, then return a. - // Else return b. - carry = -carry - ncarry := ^carry - for i := 0; i < 4; i++ { - a[i] = (a[i] & carry) | (b[i] & ncarry) - } -} - -func gfpNeg(c, a *gfP) { - var carry uint64 - for i, pi := range p2 { - ai := a[i] - ci := pi - ai - carry - c[i] = ci - carry = (ai&^pi | (ai|^pi)&ci) >> 63 - } - gfpCarry(c, 0) -} - -func gfpAdd(c, a, b *gfP) { - var carry uint64 - for i, ai := range a { - bi := b[i] - ci := ai + bi + carry - c[i] = ci - carry = (ai&bi | (ai|bi)&^ci) >> 63 - } - gfpCarry(c, carry) -} - -func gfpSub(c, a, b *gfP) { - t := &gfP{} - - var carry uint64 - for i, pi := range p2 { - bi := b[i] - ti := pi - bi - carry - t[i] = ti - carry = (bi&^pi | (bi|^pi)&ti) >> 63 - } - - carry = 0 - for i, ai := range a { - ti := t[i] - ci := ai + ti + carry - c[i] = ci - carry = (ai&ti | (ai|ti)&^ci) >> 63 - } - gfpCarry(c, carry) -} - -func mul(a, b [4]uint64) [8]uint64 { - const ( - mask16 uint64 = 0x0000ffff - mask32 uint64 = 0xffffffff - ) - - var buff [32]uint64 - for i, ai := range a { - a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 - - for j, bj := range b { - b0, b2 := bj&mask32, bj>>32 - - off := 4 * (i + j) - buff[off+0] += a0 * b0 - buff[off+1] += a1 * b0 - buff[off+2] += a2*b0 + a0*b2 - buff[off+3] += a3*b0 + a1*b2 - buff[off+4] += a2 * b2 - buff[off+5] += a3 * b2 - } - } - - for i := uint(1); i < 4; i++ { - shift := 16 * i - - var head, carry uint64 - for j := uint(0); j < 8; j++ { - block := 4 * j - - xi := buff[block] - yi := (buff[block+i] << shift) + head - zi := xi + yi + carry - buff[block] = zi - carry = (xi&yi | (xi|yi)&^zi) >> 63 - - head = buff[block+i] >> (64 - shift) - } - } - - return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]} -} - -func halfMul(a, b [4]uint64) [4]uint64 { - const ( - mask16 uint64 = 0x0000ffff - mask32 uint64 = 0xffffffff - ) - - var buff [18]uint64 - for i, ai := range a { - a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 - - for j, bj := range b { - if i+j > 3 { - break - } - b0, b2 := bj&mask32, bj>>32 - - off := 4 * (i + j) - buff[off+0] += a0 * b0 - buff[off+1] += a1 * b0 - buff[off+2] += a2*b0 + a0*b2 - buff[off+3] += a3*b0 + a1*b2 - buff[off+4] += a2 * b2 - buff[off+5] += a3 * b2 - } - } - - for i := uint(1); i < 4; i++ { - shift := 16 * i - - var head, carry uint64 - for j := uint(0); j < 4; j++ { - block := 4 * j - - xi := buff[block] - yi := (buff[block+i] << shift) + head - zi := xi + yi + carry - buff[block] = zi - carry = (xi&yi | (xi|yi)&^zi) >> 63 - - head = buff[block+i] >> (64 - shift) - } - } - - return [4]uint64{buff[0], buff[4], buff[8], buff[12]} -} - -func gfpMul(c, a, b *gfP) { - T := mul(*a, *b) - m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) - t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) - - var carry uint64 - for i, Ti := range T { - ti := t[i] - zi := Ti + ti + carry - T[i] = zi - carry = (Ti&ti | (Ti|ti)&^zi) >> 63 - } - - *c = gfP{T[4], T[5], T[6], T[7]} - gfpCarry(c, carry) -} diff --git a/builder/crypto/bn256/cloudflare/gfp_test.go b/builder/crypto/bn256/cloudflare/gfp_test.go deleted file mode 100644 index 16ab2a841..000000000 --- a/builder/crypto/bn256/cloudflare/gfp_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package bn256 - -import ( - "testing" -) - -// Tests that negation works the same way on both assembly-optimized and pure Go -// implementation. -func TestGFpNeg(t *testing.T) { - n := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} - w := &gfP{0xfedcba9876543211, 0x0123456789abcdef, 0x2152411021524110, 0x0114251201142512} - h := &gfP{} - - gfpNeg(h, n) - if *h != *w { - t.Errorf("negation mismatch: have %#x, want %#x", *h, *w) - } -} - -// Tests that addition works the same way on both assembly-optimized and pure Go -// implementation. -func TestGFpAdd(t *testing.T) { - a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} - b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} - w := &gfP{0xc3df73e9278302b8, 0x687e956e978e3572, 0x254954275c18417f, 0xad354b6afc67f9b4} - h := &gfP{} - - gfpAdd(h, a, b) - if *h != *w { - t.Errorf("addition mismatch: have %#x, want %#x", *h, *w) - } -} - -// Tests that subtraction works the same way on both assembly-optimized and pure Go -// implementation. -func TestGFpSub(t *testing.T) { - a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} - b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} - w := &gfP{0x02468acf13579bdf, 0xfdb97530eca86420, 0xdfc1e401dfc1e402, 0x203e1bfe203e1bfd} - h := &gfP{} - - gfpSub(h, a, b) - if *h != *w { - t.Errorf("subtraction mismatch: have %#x, want %#x", *h, *w) - } -} - -// Tests that multiplication works the same way on both assembly-optimized and pure Go -// implementation. -func TestGFpMul(t *testing.T) { - a := &gfP{0x0123456789abcdef, 0xfedcba9876543210, 0xdeadbeefdeadbeef, 0xfeebdaedfeebdaed} - b := &gfP{0xfedcba9876543210, 0x0123456789abcdef, 0xfeebdaedfeebdaed, 0xdeadbeefdeadbeef} - w := &gfP{0xcbcbd377f7ad22d3, 0x3b89ba5d849379bf, 0x87b61627bd38b6d2, 0xc44052a2a0e654b2} - h := &gfP{} - - gfpMul(h, a, b) - if *h != *w { - t.Errorf("multiplication mismatch: have %#x, want %#x", *h, *w) - } -} diff --git a/builder/crypto/bn256/cloudflare/lattice.go b/builder/crypto/bn256/cloudflare/lattice.go deleted file mode 100644 index f9ace4d9f..000000000 --- a/builder/crypto/bn256/cloudflare/lattice.go +++ /dev/null @@ -1,115 +0,0 @@ -package bn256 - -import ( - "math/big" -) - -var half = new(big.Int).Rsh(Order, 1) - -var curveLattice = &lattice{ - vectors: [][]*big.Int{ - {bigFromBase10("147946756881789319000765030803803410728"), bigFromBase10("147946756881789319010696353538189108491")}, - {bigFromBase10("147946756881789319020627676272574806254"), bigFromBase10("-147946756881789318990833708069417712965")}, - }, - inverse: []*big.Int{ - bigFromBase10("147946756881789318990833708069417712965"), - bigFromBase10("147946756881789319010696353538189108491"), - }, - det: bigFromBase10("43776485743678550444492811490514550177096728800832068687396408373151616991234"), -} - -var targetLattice = &lattice{ - vectors: [][]*big.Int{ - {bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697763"), bigFromBase10("9931322734385697764")}, - {bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848882"), bigFromBase10("-9931322734385697762")}, - {bigFromBase10("-9931322734385697762"), bigFromBase10("-4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("-4965661367192848882")}, - {bigFromBase10("9931322734385697763"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881")}, - }, - inverse: []*big.Int{ - bigFromBase10("734653495049373973658254490726798021314063399421879442165"), - bigFromBase10("147946756881789319000765030803803410728"), - bigFromBase10("-147946756881789319005730692170996259609"), - bigFromBase10("1469306990098747947464455738335385361643788813749140841702"), - }, - det: new(big.Int).Set(Order), -} - -type lattice struct { - vectors [][]*big.Int - inverse []*big.Int - det *big.Int -} - -// decompose takes a scalar mod Order as input and finds a short, positive decomposition of it wrt to the lattice basis. -func (l *lattice) decompose(k *big.Int) []*big.Int { - n := len(l.inverse) - - // Calculate closest vector in lattice to with Babai's rounding. - c := make([]*big.Int, n) - for i := 0; i < n; i++ { - c[i] = new(big.Int).Mul(k, l.inverse[i]) - round(c[i], l.det) - } - - // Transform vectors according to c and subtract . - out := make([]*big.Int, n) - temp := new(big.Int) - - for i := 0; i < n; i++ { - out[i] = new(big.Int) - - for j := 0; j < n; j++ { - temp.Mul(c[j], l.vectors[j][i]) - out[i].Add(out[i], temp) - } - - out[i].Neg(out[i]) - out[i].Add(out[i], l.vectors[0][i]).Add(out[i], l.vectors[0][i]) - } - out[0].Add(out[0], k) - - return out -} - -func (l *lattice) Precompute(add func(i, j uint)) { - n := uint(len(l.vectors)) - total := uint(1) << n - - for i := uint(0); i < n; i++ { - for j := uint(0); j < total; j++ { - if (j>>i)&1 == 1 { - add(i, j) - } - } - } -} - -func (l *lattice) Multi(scalar *big.Int) []uint8 { - decomp := l.decompose(scalar) - - maxLen := 0 - for _, x := range decomp { - if x.BitLen() > maxLen { - maxLen = x.BitLen() - } - } - - out := make([]uint8, maxLen) - for j, x := range decomp { - for i := 0; i < maxLen; i++ { - out[i] += uint8(x.Bit(i)) << uint(j) - } - } - - return out -} - -// round sets num to num/denom rounded to the nearest integer. -func round(num, denom *big.Int) { - r := new(big.Int) - num.DivMod(num, denom, r) - - if r.Cmp(half) == 1 { - num.Add(num, big.NewInt(1)) - } -} diff --git a/builder/crypto/bn256/cloudflare/lattice_test.go b/builder/crypto/bn256/cloudflare/lattice_test.go deleted file mode 100644 index 4d52ad9b2..000000000 --- a/builder/crypto/bn256/cloudflare/lattice_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package bn256 - -import ( - "crypto/rand" - - "testing" -) - -func TestLatticeReduceCurve(t *testing.T) { - k, _ := rand.Int(rand.Reader, Order) - ks := curveLattice.decompose(k) - - if ks[0].BitLen() > 130 || ks[1].BitLen() > 130 { - t.Fatal("reduction too large") - } else if ks[0].Sign() < 0 || ks[1].Sign() < 0 { - t.Fatal("reduction must be positive") - } -} - -func TestLatticeReduceTarget(t *testing.T) { - k, _ := rand.Int(rand.Reader, Order) - ks := targetLattice.decompose(k) - - if ks[0].BitLen() > 66 || ks[1].BitLen() > 66 || ks[2].BitLen() > 66 || ks[3].BitLen() > 66 { - t.Fatal("reduction too large") - } else if ks[0].Sign() < 0 || ks[1].Sign() < 0 || ks[2].Sign() < 0 || ks[3].Sign() < 0 { - t.Fatal("reduction must be positive") - } -} diff --git a/builder/crypto/bn256/cloudflare/main_test.go b/builder/crypto/bn256/cloudflare/main_test.go deleted file mode 100644 index c0c85457b..000000000 --- a/builder/crypto/bn256/cloudflare/main_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package bn256 - -import ( - "testing" - - "crypto/rand" -) - -func TestRandomG2Marshal(t *testing.T) { - for i := 0; i < 10; i++ { - n, g2, err := RandomG2(rand.Reader) - if err != nil { - t.Error(err) - continue - } - t.Logf("%v: %x\n", n, g2.Marshal()) - } -} - -func TestPairings(t *testing.T) { - a1 := new(G1).ScalarBaseMult(bigFromBase10("1")) - a2 := new(G1).ScalarBaseMult(bigFromBase10("2")) - a37 := new(G1).ScalarBaseMult(bigFromBase10("37")) - an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) - - b0 := new(G2).ScalarBaseMult(bigFromBase10("0")) - b1 := new(G2).ScalarBaseMult(bigFromBase10("1")) - b2 := new(G2).ScalarBaseMult(bigFromBase10("2")) - b27 := new(G2).ScalarBaseMult(bigFromBase10("27")) - b999 := new(G2).ScalarBaseMult(bigFromBase10("999")) - bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) - - p1 := Pair(a1, b1) - pn1 := Pair(a1, bn1) - np1 := Pair(an1, b1) - if pn1.String() != np1.String() { - t.Error("Pairing mismatch: e(a, -b) != e(-a, b)") - } - if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) { - t.Error("MultiAte check gave false negative!") - } - p0 := new(GT).Add(p1, pn1) - p0_2 := Pair(a1, b0) - if p0.String() != p0_2.String() { - t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1") - } - p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")) - if p0.String() != p0_3.String() { - t.Error("Pairing mismatch: e(a, b) has wrong order") - } - p2 := Pair(a2, b1) - p2_2 := Pair(a1, b2) - p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2")) - if p2.String() != p2_2.String() { - t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)") - } - if p2.String() != p2_3.String() { - t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2") - } - if p2.String() == p1.String() { - t.Error("Pairing is degenerate!") - } - if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) { - t.Error("MultiAte check gave false positive!") - } - p999 := Pair(a37, b27) - p999_2 := Pair(a1, b999) - if p999.String() != p999_2.String() { - t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)") - } -} diff --git a/builder/crypto/bn256/cloudflare/mul_amd64.h b/builder/crypto/bn256/cloudflare/mul_amd64.h deleted file mode 100644 index 9d8e4b37d..000000000 --- a/builder/crypto/bn256/cloudflare/mul_amd64.h +++ /dev/null @@ -1,181 +0,0 @@ -#define mul(a0,a1,a2,a3, rb, stack) \ - MOVQ a0, AX \ - MULQ 0+rb \ - MOVQ AX, R8 \ - MOVQ DX, R9 \ - MOVQ a0, AX \ - MULQ 8+rb \ - ADDQ AX, R9 \ - ADCQ $0, DX \ - MOVQ DX, R10 \ - MOVQ a0, AX \ - MULQ 16+rb \ - ADDQ AX, R10 \ - ADCQ $0, DX \ - MOVQ DX, R11 \ - MOVQ a0, AX \ - MULQ 24+rb \ - ADDQ AX, R11 \ - ADCQ $0, DX \ - MOVQ DX, R12 \ - \ - storeBlock(R8,R9,R10,R11, 0+stack) \ - MOVQ R12, 32+stack \ - \ - MOVQ a1, AX \ - MULQ 0+rb \ - MOVQ AX, R8 \ - MOVQ DX, R9 \ - MOVQ a1, AX \ - MULQ 8+rb \ - ADDQ AX, R9 \ - ADCQ $0, DX \ - MOVQ DX, R10 \ - MOVQ a1, AX \ - MULQ 16+rb \ - ADDQ AX, R10 \ - ADCQ $0, DX \ - MOVQ DX, R11 \ - MOVQ a1, AX \ - MULQ 24+rb \ - ADDQ AX, R11 \ - ADCQ $0, DX \ - MOVQ DX, R12 \ - \ - ADDQ 8+stack, R8 \ - ADCQ 16+stack, R9 \ - ADCQ 24+stack, R10 \ - ADCQ 32+stack, R11 \ - ADCQ $0, R12 \ - storeBlock(R8,R9,R10,R11, 8+stack) \ - MOVQ R12, 40+stack \ - \ - MOVQ a2, AX \ - MULQ 0+rb \ - MOVQ AX, R8 \ - MOVQ DX, R9 \ - MOVQ a2, AX \ - MULQ 8+rb \ - ADDQ AX, R9 \ - ADCQ $0, DX \ - MOVQ DX, R10 \ - MOVQ a2, AX \ - MULQ 16+rb \ - ADDQ AX, R10 \ - ADCQ $0, DX \ - MOVQ DX, R11 \ - MOVQ a2, AX \ - MULQ 24+rb \ - ADDQ AX, R11 \ - ADCQ $0, DX \ - MOVQ DX, R12 \ - \ - ADDQ 16+stack, R8 \ - ADCQ 24+stack, R9 \ - ADCQ 32+stack, R10 \ - ADCQ 40+stack, R11 \ - ADCQ $0, R12 \ - storeBlock(R8,R9,R10,R11, 16+stack) \ - MOVQ R12, 48+stack \ - \ - MOVQ a3, AX \ - MULQ 0+rb \ - MOVQ AX, R8 \ - MOVQ DX, R9 \ - MOVQ a3, AX \ - MULQ 8+rb \ - ADDQ AX, R9 \ - ADCQ $0, DX \ - MOVQ DX, R10 \ - MOVQ a3, AX \ - MULQ 16+rb \ - ADDQ AX, R10 \ - ADCQ $0, DX \ - MOVQ DX, R11 \ - MOVQ a3, AX \ - MULQ 24+rb \ - ADDQ AX, R11 \ - ADCQ $0, DX \ - MOVQ DX, R12 \ - \ - ADDQ 24+stack, R8 \ - ADCQ 32+stack, R9 \ - ADCQ 40+stack, R10 \ - ADCQ 48+stack, R11 \ - ADCQ $0, R12 \ - storeBlock(R8,R9,R10,R11, 24+stack) \ - MOVQ R12, 56+stack - -#define gfpReduce(stack) \ - \ // m = (T * N') mod R, store m in R8:R9:R10:R11 - MOVQ ·np+0(SB), AX \ - MULQ 0+stack \ - MOVQ AX, R8 \ - MOVQ DX, R9 \ - MOVQ ·np+0(SB), AX \ - MULQ 8+stack \ - ADDQ AX, R9 \ - ADCQ $0, DX \ - MOVQ DX, R10 \ - MOVQ ·np+0(SB), AX \ - MULQ 16+stack \ - ADDQ AX, R10 \ - ADCQ $0, DX \ - MOVQ DX, R11 \ - MOVQ ·np+0(SB), AX \ - MULQ 24+stack \ - ADDQ AX, R11 \ - \ - MOVQ ·np+8(SB), AX \ - MULQ 0+stack \ - MOVQ AX, R12 \ - MOVQ DX, R13 \ - MOVQ ·np+8(SB), AX \ - MULQ 8+stack \ - ADDQ AX, R13 \ - ADCQ $0, DX \ - MOVQ DX, R14 \ - MOVQ ·np+8(SB), AX \ - MULQ 16+stack \ - ADDQ AX, R14 \ - \ - ADDQ R12, R9 \ - ADCQ R13, R10 \ - ADCQ R14, R11 \ - \ - MOVQ ·np+16(SB), AX \ - MULQ 0+stack \ - MOVQ AX, R12 \ - MOVQ DX, R13 \ - MOVQ ·np+16(SB), AX \ - MULQ 8+stack \ - ADDQ AX, R13 \ - \ - ADDQ R12, R10 \ - ADCQ R13, R11 \ - \ - MOVQ ·np+24(SB), AX \ - MULQ 0+stack \ - ADDQ AX, R11 \ - \ - storeBlock(R8,R9,R10,R11, 64+stack) \ - \ - \ // m * N - mul(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64+stack, 96+stack) \ - \ - \ // Add the 512-bit intermediate to m*N - loadBlock(96+stack, R8,R9,R10,R11) \ - loadBlock(128+stack, R12,R13,R14,CX) \ - \ - MOVQ $0, AX \ - ADDQ 0+stack, R8 \ - ADCQ 8+stack, R9 \ - ADCQ 16+stack, R10 \ - ADCQ 24+stack, R11 \ - ADCQ 32+stack, R12 \ - ADCQ 40+stack, R13 \ - ADCQ 48+stack, R14 \ - ADCQ 56+stack, CX \ - ADCQ $0, AX \ - \ - gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX) diff --git a/builder/crypto/bn256/cloudflare/mul_arm64.h b/builder/crypto/bn256/cloudflare/mul_arm64.h deleted file mode 100644 index d405eb8f7..000000000 --- a/builder/crypto/bn256/cloudflare/mul_arm64.h +++ /dev/null @@ -1,133 +0,0 @@ -#define mul(c0,c1,c2,c3,c4,c5,c6,c7) \ - MUL R1, R5, c0 \ - UMULH R1, R5, c1 \ - MUL R1, R6, R0 \ - ADDS R0, c1 \ - UMULH R1, R6, c2 \ - MUL R1, R7, R0 \ - ADCS R0, c2 \ - UMULH R1, R7, c3 \ - MUL R1, R8, R0 \ - ADCS R0, c3 \ - UMULH R1, R8, c4 \ - ADCS ZR, c4 \ - \ - MUL R2, R5, R1 \ - UMULH R2, R5, R26 \ - MUL R2, R6, R0 \ - ADDS R0, R26 \ - UMULH R2, R6, R27 \ - MUL R2, R7, R0 \ - ADCS R0, R27 \ - UMULH R2, R7, R29 \ - MUL R2, R8, R0 \ - ADCS R0, R29 \ - UMULH R2, R8, c5 \ - ADCS ZR, c5 \ - ADDS R1, c1 \ - ADCS R26, c2 \ - ADCS R27, c3 \ - ADCS R29, c4 \ - ADCS ZR, c5 \ - \ - MUL R3, R5, R1 \ - UMULH R3, R5, R26 \ - MUL R3, R6, R0 \ - ADDS R0, R26 \ - UMULH R3, R6, R27 \ - MUL R3, R7, R0 \ - ADCS R0, R27 \ - UMULH R3, R7, R29 \ - MUL R3, R8, R0 \ - ADCS R0, R29 \ - UMULH R3, R8, c6 \ - ADCS ZR, c6 \ - ADDS R1, c2 \ - ADCS R26, c3 \ - ADCS R27, c4 \ - ADCS R29, c5 \ - ADCS ZR, c6 \ - \ - MUL R4, R5, R1 \ - UMULH R4, R5, R26 \ - MUL R4, R6, R0 \ - ADDS R0, R26 \ - UMULH R4, R6, R27 \ - MUL R4, R7, R0 \ - ADCS R0, R27 \ - UMULH R4, R7, R29 \ - MUL R4, R8, R0 \ - ADCS R0, R29 \ - UMULH R4, R8, c7 \ - ADCS ZR, c7 \ - ADDS R1, c3 \ - ADCS R26, c4 \ - ADCS R27, c5 \ - ADCS R29, c6 \ - ADCS ZR, c7 - -#define gfpReduce() \ - \ // m = (T * N') mod R, store m in R1:R2:R3:R4 - MOVD ·np+0(SB), R17 \ - MOVD ·np+8(SB), R25 \ - MOVD ·np+16(SB), R19 \ - MOVD ·np+24(SB), R20 \ - \ - MUL R9, R17, R1 \ - UMULH R9, R17, R2 \ - MUL R9, R25, R0 \ - ADDS R0, R2 \ - UMULH R9, R25, R3 \ - MUL R9, R19, R0 \ - ADCS R0, R3 \ - UMULH R9, R19, R4 \ - MUL R9, R20, R0 \ - ADCS R0, R4 \ - \ - MUL R10, R17, R21 \ - UMULH R10, R17, R22 \ - MUL R10, R25, R0 \ - ADDS R0, R22 \ - UMULH R10, R25, R23 \ - MUL R10, R19, R0 \ - ADCS R0, R23 \ - ADDS R21, R2 \ - ADCS R22, R3 \ - ADCS R23, R4 \ - \ - MUL R11, R17, R21 \ - UMULH R11, R17, R22 \ - MUL R11, R25, R0 \ - ADDS R0, R22 \ - ADDS R21, R3 \ - ADCS R22, R4 \ - \ - MUL R12, R17, R21 \ - ADDS R21, R4 \ - \ - \ // m * N - loadModulus(R5,R6,R7,R8) \ - mul(R17,R25,R19,R20,R21,R22,R23,R24) \ - \ - \ // Add the 512-bit intermediate to m*N - MOVD ZR, R0 \ - ADDS R9, R17 \ - ADCS R10, R25 \ - ADCS R11, R19 \ - ADCS R12, R20 \ - ADCS R13, R21 \ - ADCS R14, R22 \ - ADCS R15, R23 \ - ADCS R16, R24 \ - ADCS ZR, R0 \ - \ - \ // Our output is R21:R22:R23:R24. Reduce mod p if necessary. - SUBS R5, R21, R10 \ - SBCS R6, R22, R11 \ - SBCS R7, R23, R12 \ - SBCS R8, R24, R13 \ - \ - CSEL CS, R10, R21, R1 \ - CSEL CS, R11, R22, R2 \ - CSEL CS, R12, R23, R3 \ - CSEL CS, R13, R24, R4 diff --git a/builder/crypto/bn256/cloudflare/mul_bmi2_amd64.h b/builder/crypto/bn256/cloudflare/mul_bmi2_amd64.h deleted file mode 100644 index 403566c6f..000000000 --- a/builder/crypto/bn256/cloudflare/mul_bmi2_amd64.h +++ /dev/null @@ -1,112 +0,0 @@ -#define mulBMI2(a0,a1,a2,a3, rb) \ - MOVQ a0, DX \ - MOVQ $0, R13 \ - MULXQ 0+rb, R8, R9 \ - MULXQ 8+rb, AX, R10 \ - ADDQ AX, R9 \ - MULXQ 16+rb, AX, R11 \ - ADCQ AX, R10 \ - MULXQ 24+rb, AX, R12 \ - ADCQ AX, R11 \ - ADCQ $0, R12 \ - ADCQ $0, R13 \ - \ - MOVQ a1, DX \ - MOVQ $0, R14 \ - MULXQ 0+rb, AX, BX \ - ADDQ AX, R9 \ - ADCQ BX, R10 \ - MULXQ 16+rb, AX, BX \ - ADCQ AX, R11 \ - ADCQ BX, R12 \ - ADCQ $0, R13 \ - MULXQ 8+rb, AX, BX \ - ADDQ AX, R10 \ - ADCQ BX, R11 \ - MULXQ 24+rb, AX, BX \ - ADCQ AX, R12 \ - ADCQ BX, R13 \ - ADCQ $0, R14 \ - \ - MOVQ a2, DX \ - MOVQ $0, CX \ - MULXQ 0+rb, AX, BX \ - ADDQ AX, R10 \ - ADCQ BX, R11 \ - MULXQ 16+rb, AX, BX \ - ADCQ AX, R12 \ - ADCQ BX, R13 \ - ADCQ $0, R14 \ - MULXQ 8+rb, AX, BX \ - ADDQ AX, R11 \ - ADCQ BX, R12 \ - MULXQ 24+rb, AX, BX \ - ADCQ AX, R13 \ - ADCQ BX, R14 \ - ADCQ $0, CX \ - \ - MOVQ a3, DX \ - MULXQ 0+rb, AX, BX \ - ADDQ AX, R11 \ - ADCQ BX, R12 \ - MULXQ 16+rb, AX, BX \ - ADCQ AX, R13 \ - ADCQ BX, R14 \ - ADCQ $0, CX \ - MULXQ 8+rb, AX, BX \ - ADDQ AX, R12 \ - ADCQ BX, R13 \ - MULXQ 24+rb, AX, BX \ - ADCQ AX, R14 \ - ADCQ BX, CX - -#define gfpReduceBMI2() \ - \ // m = (T * N') mod R, store m in R8:R9:R10:R11 - MOVQ ·np+0(SB), DX \ - MULXQ 0(SP), R8, R9 \ - MULXQ 8(SP), AX, R10 \ - ADDQ AX, R9 \ - MULXQ 16(SP), AX, R11 \ - ADCQ AX, R10 \ - MULXQ 24(SP), AX, BX \ - ADCQ AX, R11 \ - \ - MOVQ ·np+8(SB), DX \ - MULXQ 0(SP), AX, BX \ - ADDQ AX, R9 \ - ADCQ BX, R10 \ - MULXQ 16(SP), AX, BX \ - ADCQ AX, R11 \ - MULXQ 8(SP), AX, BX \ - ADDQ AX, R10 \ - ADCQ BX, R11 \ - \ - MOVQ ·np+16(SB), DX \ - MULXQ 0(SP), AX, BX \ - ADDQ AX, R10 \ - ADCQ BX, R11 \ - MULXQ 8(SP), AX, BX \ - ADDQ AX, R11 \ - \ - MOVQ ·np+24(SB), DX \ - MULXQ 0(SP), AX, BX \ - ADDQ AX, R11 \ - \ - storeBlock(R8,R9,R10,R11, 64(SP)) \ - \ - \ // m * N - mulBMI2(·p2+0(SB),·p2+8(SB),·p2+16(SB),·p2+24(SB), 64(SP)) \ - \ - \ // Add the 512-bit intermediate to m*N - MOVQ $0, AX \ - ADDQ 0(SP), R8 \ - ADCQ 8(SP), R9 \ - ADCQ 16(SP), R10 \ - ADCQ 24(SP), R11 \ - ADCQ 32(SP), R12 \ - ADCQ 40(SP), R13 \ - ADCQ 48(SP), R14 \ - ADCQ 56(SP), CX \ - ADCQ $0, AX \ - \ - gfpCarry(R12,R13,R14,CX,AX, R8,R9,R10,R11,BX) diff --git a/builder/crypto/bn256/cloudflare/optate.go b/builder/crypto/bn256/cloudflare/optate.go deleted file mode 100644 index e8caa7a08..000000000 --- a/builder/crypto/bn256/cloudflare/optate.go +++ /dev/null @@ -1,270 +0,0 @@ -package bn256 - -func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2) (a, b, c *gfP2, rOut *twistPoint) { - // See the mixed addition algorithm from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - B := (&gfP2{}).Mul(&p.x, &r.t) - - D := (&gfP2{}).Add(&p.y, &r.z) - D.Square(D).Sub(D, r2).Sub(D, &r.t).Mul(D, &r.t) - - H := (&gfP2{}).Sub(B, &r.x) - I := (&gfP2{}).Square(H) - - E := (&gfP2{}).Add(I, I) - E.Add(E, E) - - J := (&gfP2{}).Mul(H, E) - - L1 := (&gfP2{}).Sub(D, &r.y) - L1.Sub(L1, &r.y) - - V := (&gfP2{}).Mul(&r.x, E) - - rOut = &twistPoint{} - rOut.x.Square(L1).Sub(&rOut.x, J).Sub(&rOut.x, V).Sub(&rOut.x, V) - - rOut.z.Add(&r.z, H).Square(&rOut.z).Sub(&rOut.z, &r.t).Sub(&rOut.z, I) - - t := (&gfP2{}).Sub(V, &rOut.x) - t.Mul(t, L1) - t2 := (&gfP2{}).Mul(&r.y, J) - t2.Add(t2, t2) - rOut.y.Sub(t, t2) - - rOut.t.Square(&rOut.z) - - t.Add(&p.y, &rOut.z).Square(t).Sub(t, r2).Sub(t, &rOut.t) - - t2.Mul(L1, &p.x) - t2.Add(t2, t2) - a = (&gfP2{}).Sub(t2, t) - - c = (&gfP2{}).MulScalar(&rOut.z, &q.y) - c.Add(c, c) - - b = (&gfP2{}).Neg(L1) - b.MulScalar(b, &q.x).Add(b, b) - - return -} - -func lineFunctionDouble(r *twistPoint, q *curvePoint) (a, b, c *gfP2, rOut *twistPoint) { - // See the doubling algorithm for a=0 from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - A := (&gfP2{}).Square(&r.x) - B := (&gfP2{}).Square(&r.y) - C := (&gfP2{}).Square(B) - - D := (&gfP2{}).Add(&r.x, B) - D.Square(D).Sub(D, A).Sub(D, C).Add(D, D) - - E := (&gfP2{}).Add(A, A) - E.Add(E, A) - - G := (&gfP2{}).Square(E) - - rOut = &twistPoint{} - rOut.x.Sub(G, D).Sub(&rOut.x, D) - - rOut.z.Add(&r.y, &r.z).Square(&rOut.z).Sub(&rOut.z, B).Sub(&rOut.z, &r.t) - - rOut.y.Sub(D, &rOut.x).Mul(&rOut.y, E) - t := (&gfP2{}).Add(C, C) - t.Add(t, t).Add(t, t) - rOut.y.Sub(&rOut.y, t) - - rOut.t.Square(&rOut.z) - - t.Mul(E, &r.t).Add(t, t) - b = (&gfP2{}).Neg(t) - b.MulScalar(b, &q.x) - - a = (&gfP2{}).Add(&r.x, E) - a.Square(a).Sub(a, A).Sub(a, G) - t.Add(B, B).Add(t, t) - a.Sub(a, t) - - c = (&gfP2{}).Mul(&rOut.z, &r.t) - c.Add(c, c).MulScalar(c, &q.y) - - return -} - -func mulLine(ret *gfP12, a, b, c *gfP2) { - a2 := &gfP6{} - a2.y.Set(a) - a2.z.Set(b) - a2.Mul(a2, &ret.x) - t3 := (&gfP6{}).MulScalar(&ret.y, c) - - t := (&gfP2{}).Add(b, c) - t2 := &gfP6{} - t2.y.Set(a) - t2.z.Set(t) - ret.x.Add(&ret.x, &ret.y) - - ret.y.Set(t3) - - ret.x.Mul(&ret.x, t2).Sub(&ret.x, a2).Sub(&ret.x, &ret.y) - a2.MulTau(a2) - ret.y.Add(&ret.y, a2) -} - -// sixuPlus2NAF is 6u+2 in non-adjacent form. -var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, - 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, - 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, - 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} - -// miller implements the Miller loop for calculating the Optimal Ate pairing. -// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf -func miller(q *twistPoint, p *curvePoint) *gfP12 { - ret := (&gfP12{}).SetOne() - - aAffine := &twistPoint{} - aAffine.Set(q) - aAffine.MakeAffine() - - bAffine := &curvePoint{} - bAffine.Set(p) - bAffine.MakeAffine() - - minusA := &twistPoint{} - minusA.Neg(aAffine) - - r := &twistPoint{} - r.Set(aAffine) - - r2 := (&gfP2{}).Square(&aAffine.y) - - for i := len(sixuPlus2NAF) - 1; i > 0; i-- { - a, b, c, newR := lineFunctionDouble(r, bAffine) - if i != len(sixuPlus2NAF)-1 { - ret.Square(ret) - } - - mulLine(ret, a, b, c) - r = newR - - switch sixuPlus2NAF[i-1] { - case 1: - a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2) - case -1: - a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2) - default: - continue - } - - mulLine(ret, a, b, c) - r = newR - } - - // In order to calculate Q1 we have to convert q from the sextic twist - // to the full GF(p^12) group, apply the Frobenius there, and convert - // back. - // - // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just - // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) - // where xÌ„ is the conjugate of x. If we are going to apply the inverse - // isomorphism we need a value with a single coefficient of ω² so we - // rewrite this as x̄ω^(2p-2)ω². ξⶠ= ω and, due to the construction of - // p, 2p-2 is a multiple of six. Therefore we can rewrite as - // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the - // ω². - // - // A similar argument can be made for the y value. - - q1 := &twistPoint{} - q1.x.Conjugate(&aAffine.x).Mul(&q1.x, xiToPMinus1Over3) - q1.y.Conjugate(&aAffine.y).Mul(&q1.y, xiToPMinus1Over2) - q1.z.SetOne() - q1.t.SetOne() - - // For Q2 we are applying the p² Frobenius. The two conjugations cancel - // out and we are left only with the factors from the isomorphism. In - // the case of x, we end up with a pure number which is why - // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We - // ignore this to end up with -Q2. - - minusQ2 := &twistPoint{} - minusQ2.x.MulScalar(&aAffine.x, xiToPSquaredMinus1Over3) - minusQ2.y.Set(&aAffine.y) - minusQ2.z.SetOne() - minusQ2.t.SetOne() - - r2.Square(&q1.y) - a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2) - mulLine(ret, a, b, c) - r = newR - - r2.Square(&minusQ2.y) - a, b, c, _ = lineFunctionAdd(r, minusQ2, bAffine, r2) - mulLine(ret, a, b, c) - - return ret -} - -// finalExponentiation computes the (p¹²-1)/Order-th power of an element of -// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from -// http://cryptojedi.org/papers/dclxvi-20100714.pdf) -func finalExponentiation(in *gfP12) *gfP12 { - t1 := &gfP12{} - - // This is the p^6-Frobenius - t1.x.Neg(&in.x) - t1.y.Set(&in.y) - - inv := &gfP12{} - inv.Invert(in) - t1.Mul(t1, inv) - - t2 := (&gfP12{}).FrobeniusP2(t1) - t1.Mul(t1, t2) - - fp := (&gfP12{}).Frobenius(t1) - fp2 := (&gfP12{}).FrobeniusP2(t1) - fp3 := (&gfP12{}).Frobenius(fp2) - - fu := (&gfP12{}).Exp(t1, u) - fu2 := (&gfP12{}).Exp(fu, u) - fu3 := (&gfP12{}).Exp(fu2, u) - - y3 := (&gfP12{}).Frobenius(fu) - fu2p := (&gfP12{}).Frobenius(fu2) - fu3p := (&gfP12{}).Frobenius(fu3) - y2 := (&gfP12{}).FrobeniusP2(fu2) - - y0 := &gfP12{} - y0.Mul(fp, fp2).Mul(y0, fp3) - - y1 := (&gfP12{}).Conjugate(t1) - y5 := (&gfP12{}).Conjugate(fu2) - y3.Conjugate(y3) - y4 := (&gfP12{}).Mul(fu, fu2p) - y4.Conjugate(y4) - - y6 := (&gfP12{}).Mul(fu3, fu3p) - y6.Conjugate(y6) - - t0 := (&gfP12{}).Square(y6) - t0.Mul(t0, y4).Mul(t0, y5) - t1.Mul(y3, y5).Mul(t1, t0) - t0.Mul(t0, y2) - t1.Square(t1).Mul(t1, t0).Square(t1) - t0.Mul(t1, y1) - t1.Mul(t1, y0) - t0.Square(t0).Mul(t0, t1) - - return t0 -} - -func optimalAte(a *twistPoint, b *curvePoint) *gfP12 { - e := miller(a, b) - ret := finalExponentiation(e) - - if a.IsInfinity() || b.IsInfinity() { - ret.SetOne() - } - return ret -} diff --git a/builder/crypto/bn256/cloudflare/twist.go b/builder/crypto/bn256/cloudflare/twist.go deleted file mode 100644 index 2c7a69a4d..000000000 --- a/builder/crypto/bn256/cloudflare/twist.go +++ /dev/null @@ -1,204 +0,0 @@ -package bn256 - -import ( - "math/big" -) - -// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are -// kept in Jacobian form and t=z² when valid. The group Gâ‚‚ is the set of -// n-torsion points of this curve over GF(p²) (where n = Order) -type twistPoint struct { - x, y, z, t gfP2 -} - -var twistB = &gfP2{ - gfP{0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d}, - gfP{0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d}, -} - -// twistGen is the generator of group Gâ‚‚. -var twistGen = &twistPoint{ - gfP2{ - gfP{0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b}, - gfP{0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b}, - }, - gfP2{ - gfP{0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482}, - gfP{0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206}, - }, - gfP2{*newGFp(0), *newGFp(1)}, - gfP2{*newGFp(0), *newGFp(1)}, -} - -func (c *twistPoint) String() string { - c.MakeAffine() - x, y := gfP2Decode(&c.x), gfP2Decode(&c.y) - return "(" + x.String() + ", " + y.String() + ")" -} - -func (c *twistPoint) Set(a *twistPoint) { - c.x.Set(&a.x) - c.y.Set(&a.y) - c.z.Set(&a.z) - c.t.Set(&a.t) -} - -// IsOnCurve returns true iff c is on the curve. -func (c *twistPoint) IsOnCurve() bool { - c.MakeAffine() - if c.IsInfinity() { - return true - } - - y2, x3 := &gfP2{}, &gfP2{} - y2.Square(&c.y) - x3.Square(&c.x).Mul(x3, &c.x).Add(x3, twistB) - - if *y2 != *x3 { - return false - } - cneg := &twistPoint{} - cneg.Mul(c, Order) - return cneg.z.IsZero() -} - -func (c *twistPoint) SetInfinity() { - c.x.SetZero() - c.y.SetOne() - c.z.SetZero() - c.t.SetZero() -} - -func (c *twistPoint) IsInfinity() bool { - return c.z.IsZero() -} - -func (c *twistPoint) Add(a, b *twistPoint) { - // For additional comments, see the same function in curve.go. - - if a.IsInfinity() { - c.Set(b) - return - } - if b.IsInfinity() { - c.Set(a) - return - } - - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 - z12 := (&gfP2{}).Square(&a.z) - z22 := (&gfP2{}).Square(&b.z) - u1 := (&gfP2{}).Mul(&a.x, z22) - u2 := (&gfP2{}).Mul(&b.x, z12) - - t := (&gfP2{}).Mul(&b.z, z22) - s1 := (&gfP2{}).Mul(&a.y, t) - - t.Mul(&a.z, z12) - s2 := (&gfP2{}).Mul(&b.y, t) - - h := (&gfP2{}).Sub(u2, u1) - xEqual := h.IsZero() - - t.Add(h, h) - i := (&gfP2{}).Square(t) - j := (&gfP2{}).Mul(h, i) - - t.Sub(s2, s1) - yEqual := t.IsZero() - if xEqual && yEqual { - c.Double(a) - return - } - r := (&gfP2{}).Add(t, t) - - v := (&gfP2{}).Mul(u1, i) - - t4 := (&gfP2{}).Square(r) - t.Add(v, v) - t6 := (&gfP2{}).Sub(t4, j) - c.x.Sub(t6, t) - - t.Sub(v, &c.x) // t7 - t4.Mul(s1, j) // t8 - t6.Add(t4, t4) // t9 - t4.Mul(r, t) // t10 - c.y.Sub(t4, t6) - - t.Add(&a.z, &b.z) // t11 - t4.Square(t) // t12 - t.Sub(t4, z12) // t13 - t4.Sub(t, z22) // t14 - c.z.Mul(t4, h) -} - -func (c *twistPoint) Double(a *twistPoint) { - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 - A := (&gfP2{}).Square(&a.x) - B := (&gfP2{}).Square(&a.y) - C := (&gfP2{}).Square(B) - - t := (&gfP2{}).Add(&a.x, B) - t2 := (&gfP2{}).Square(t) - t.Sub(t2, A) - t2.Sub(t, C) - d := (&gfP2{}).Add(t2, t2) - t.Add(A, A) - e := (&gfP2{}).Add(t, A) - f := (&gfP2{}).Square(e) - - t.Add(d, d) - c.x.Sub(f, t) - - c.z.Mul(&a.y, &a.z) - c.z.Add(&c.z, &c.z) - - t.Add(C, C) - t2.Add(t, t) - t.Add(t2, t2) - c.y.Sub(d, &c.x) - t2.Mul(e, &c.y) - c.y.Sub(t2, t) -} - -func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int) { - sum, t := &twistPoint{}, &twistPoint{} - - for i := scalar.BitLen(); i >= 0; i-- { - t.Double(sum) - if scalar.Bit(i) != 0 { - sum.Add(t, a) - } else { - sum.Set(t) - } - } - - c.Set(sum) -} - -func (c *twistPoint) MakeAffine() { - if c.z.IsOne() { - return - } else if c.z.IsZero() { - c.x.SetZero() - c.y.SetOne() - c.t.SetZero() - return - } - - zInv := (&gfP2{}).Invert(&c.z) - t := (&gfP2{}).Mul(&c.y, zInv) - zInv2 := (&gfP2{}).Square(zInv) - c.y.Mul(t, zInv2) - t.Mul(&c.x, zInv2) - c.x.Set(t) - c.z.SetOne() - c.t.SetOne() -} - -func (c *twistPoint) Neg(a *twistPoint) { - c.x.Set(&a.x) - c.y.Neg(&a.y) - c.z.Set(&a.z) - c.t.SetZero() -} diff --git a/builder/crypto/bn256/google/bn256.go b/builder/crypto/bn256/google/bn256.go deleted file mode 100644 index 93953e23a..000000000 --- a/builder/crypto/bn256/google/bn256.go +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bn256 implements a particular bilinear group. -// -// Bilinear groups are the basis of many of the new cryptographic protocols -// that have been proposed over the past decade. They consist of a triplet of -// groups (Gâ‚, Gâ‚‚ and GT) such that there exists a function e(gâ‚Ë£,g₂ʸ)=gTˣʸ -// (where gâ‚“ is a generator of the respective group). That function is called -// a pairing function. -// -// This package specifically implements the Optimal Ate pairing over a 256-bit -// Barreto-Naehrig curve as described in -// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is not -// compatible with the implementation described in that paper, as different -// parameters are chosen. -// -// (This package previously claimed to operate at a 128-bit security level. -// However, recent improvements in attacks mean that is no longer true. See -// https://moderncrypto.org/mail-archive/curves/2016/000740.html.) -package bn256 - -import ( - "crypto/rand" - "errors" - "io" - "math/big" -) - -// BUG(agl): this implementation is not constant time. -// TODO(agl): keep GF(p²) elements in Mongomery form. - -// G1 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G1 struct { - p *curvePoint -} - -// RandomG1 returns x and gâ‚Ë£ where x is a random, non-zero number read from r. -func RandomG1(r io.Reader) (*big.Int, *G1, error) { - var k *big.Int - var err error - - for { - k, err = rand.Int(r, Order) - if err != nil { - return nil, nil, err - } - if k.Sign() > 0 { - break - } - } - - return k, new(G1).ScalarBaseMult(k), nil -} - -func (e *G1) String() string { - return "bn256.G1" + e.p.String() -} - -// CurvePoints returns p's curve points in big integer -func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) { - return e.p.x, e.p.y, e.p.z, e.p.t -} - -// ScalarBaseMult sets e to g*k where g is the generator of the group and -// then returns e. -func (e *G1) ScalarBaseMult(k *big.Int) *G1 { - if e.p == nil { - e.p = newCurvePoint(nil) - } - e.p.Mul(curveGen, k, new(bnPool)) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { - if e.p == nil { - e.p = newCurvePoint(nil) - } - e.p.Mul(a.p, k, new(bnPool)) - return e -} - -// Add sets e to a+b and then returns e. -// BUG(agl): this function is not complete: a==b fails. -func (e *G1) Add(a, b *G1) *G1 { - if e.p == nil { - e.p = newCurvePoint(nil) - } - e.p.Add(a.p, b.p, new(bnPool)) - return e -} - -// Neg sets e to -a and then returns e. -func (e *G1) Neg(a *G1) *G1 { - if e.p == nil { - e.p = newCurvePoint(nil) - } - e.p.Negative(a.p) - return e -} - -// Marshal converts n to a byte slice. -func (e *G1) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if e.p.IsInfinity() { - return make([]byte, numBytes*2) - } - - e.p.MakeAffine(nil) - - xBytes := new(big.Int).Mod(e.p.x, P).Bytes() - yBytes := new(big.Int).Mod(e.p.y, P).Bytes() - - ret := make([]byte, numBytes*2) - copy(ret[1*numBytes-len(xBytes):], xBytes) - copy(ret[2*numBytes-len(yBytes):], yBytes) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *G1) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - if len(m) != 2*numBytes { - return nil, errors.New("bn256: not enough data") - } - // Unmarshal the points and check their caps - if e.p == nil { - e.p = newCurvePoint(nil) - } - e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) - if e.p.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) - if e.p.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - // Ensure the point is on the curve - if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { - // This is the point at infinity. - e.p.y.SetInt64(1) - e.p.z.SetInt64(0) - e.p.t.SetInt64(0) - } else { - e.p.z.SetInt64(1) - e.p.t.SetInt64(1) - - if !e.p.IsOnCurve() { - return nil, errors.New("bn256: malformed point") - } - } - return m[2*numBytes:], nil -} - -// G2 is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type G2 struct { - p *twistPoint -} - -// RandomG2 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r. -func RandomG2(r io.Reader) (*big.Int, *G2, error) { - var k *big.Int - var err error - - for { - k, err = rand.Int(r, Order) - if err != nil { - return nil, nil, err - } - if k.Sign() > 0 { - break - } - } - - return k, new(G2).ScalarBaseMult(k), nil -} - -func (e *G2) String() string { - return "bn256.G2" + e.p.String() -} - -// CurvePoints returns the curve points of p which includes the real -// and imaginary parts of the curve point. -func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) { - return e.p.x, e.p.y, e.p.z, e.p.t -} - -// ScalarBaseMult sets e to g*k where g is the generator of the group and -// then returns out. -func (e *G2) ScalarBaseMult(k *big.Int) *G2 { - if e.p == nil { - e.p = newTwistPoint(nil) - } - e.p.Mul(twistGen, k, new(bnPool)) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { - if e.p == nil { - e.p = newTwistPoint(nil) - } - e.p.Mul(a.p, k, new(bnPool)) - return e -} - -// Add sets e to a+b and then returns e. -// BUG(agl): this function is not complete: a==b fails. -func (e *G2) Add(a, b *G2) *G2 { - if e.p == nil { - e.p = newTwistPoint(nil) - } - e.p.Add(a.p, b.p, new(bnPool)) - return e -} - -// Marshal converts n into a byte slice. -func (n *G2) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if n.p.IsInfinity() { - return make([]byte, numBytes*4) - } - - n.p.MakeAffine(nil) - - xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes() - xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes() - yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes() - yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes() - - ret := make([]byte, numBytes*4) - copy(ret[1*numBytes-len(xxBytes):], xxBytes) - copy(ret[2*numBytes-len(xyBytes):], xyBytes) - copy(ret[3*numBytes-len(yxBytes):], yxBytes) - copy(ret[4*numBytes-len(yyBytes):], yyBytes) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *G2) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - if len(m) != 4*numBytes { - return nil, errors.New("bn256: not enough data") - } - // Unmarshal the points and check their caps - if e.p == nil { - e.p = newTwistPoint(nil) - } - e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) - if e.p.x.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) - if e.p.x.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) - if e.p.y.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) - if e.p.y.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - // Ensure the point is on the curve - if e.p.x.x.Sign() == 0 && - e.p.x.y.Sign() == 0 && - e.p.y.x.Sign() == 0 && - e.p.y.y.Sign() == 0 { - // This is the point at infinity. - e.p.y.SetOne() - e.p.z.SetZero() - e.p.t.SetZero() - } else { - e.p.z.SetOne() - e.p.t.SetOne() - - if !e.p.IsOnCurve() { - return nil, errors.New("bn256: malformed point") - } - } - return m[4*numBytes:], nil -} - -// GT is an abstract cyclic group. The zero value is suitable for use as the -// output of an operation, but cannot be used as an input. -type GT struct { - p *gfP12 -} - -func (g *GT) String() string { - return "bn256.GT" + g.p.String() -} - -// ScalarMult sets e to a*k and then returns e. -func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { - if e.p == nil { - e.p = newGFp12(nil) - } - e.p.Exp(a.p, k, new(bnPool)) - return e -} - -// Add sets e to a+b and then returns e. -func (e *GT) Add(a, b *GT) *GT { - if e.p == nil { - e.p = newGFp12(nil) - } - e.p.Mul(a.p, b.p, new(bnPool)) - return e -} - -// Neg sets e to -a and then returns e. -func (e *GT) Neg(a *GT) *GT { - if e.p == nil { - e.p = newGFp12(nil) - } - e.p.Invert(a.p, new(bnPool)) - return e -} - -// Marshal converts n into a byte slice. -func (n *GT) Marshal() []byte { - n.p.Minimal() - - xxxBytes := n.p.x.x.x.Bytes() - xxyBytes := n.p.x.x.y.Bytes() - xyxBytes := n.p.x.y.x.Bytes() - xyyBytes := n.p.x.y.y.Bytes() - xzxBytes := n.p.x.z.x.Bytes() - xzyBytes := n.p.x.z.y.Bytes() - yxxBytes := n.p.y.x.x.Bytes() - yxyBytes := n.p.y.x.y.Bytes() - yyxBytes := n.p.y.y.x.Bytes() - yyyBytes := n.p.y.y.y.Bytes() - yzxBytes := n.p.y.z.x.Bytes() - yzyBytes := n.p.y.z.y.Bytes() - - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - ret := make([]byte, numBytes*12) - copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) - copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) - copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) - copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) - copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) - copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) - copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) - copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) - copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) - copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) - copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) - copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *GT) Unmarshal(m []byte) (*GT, bool) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if len(m) != 12*numBytes { - return nil, false - } - - if e.p == nil { - e.p = newGFp12(nil) - } - - e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) - e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) - e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) - e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) - e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) - e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) - e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) - e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) - e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) - e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) - e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) - e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) - - return e, true -} - -// Pair calculates an Optimal Ate pairing. -func Pair(g1 *G1, g2 *G2) *GT { - return >{optimalAte(g2.p, g1.p, new(bnPool))} -} - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - pool := new(bnPool) - - acc := newGFp12(pool) - acc.SetOne() - - for i := 0; i < len(a); i++ { - if a[i].p.IsInfinity() || b[i].p.IsInfinity() { - continue - } - acc.Mul(acc, miller(b[i].p, a[i].p, pool), pool) - } - ret := finalExponentiation(acc, pool) - acc.Put(pool) - - return ret.IsOne() -} - -// bnPool implements a tiny cache of *big.Int objects that's used to reduce the -// number of allocations made during processing. -type bnPool struct { - bns []*big.Int - count int -} - -func (pool *bnPool) Get() *big.Int { - if pool == nil { - return new(big.Int) - } - - pool.count++ - l := len(pool.bns) - if l == 0 { - return new(big.Int) - } - - bn := pool.bns[l-1] - pool.bns = pool.bns[:l-1] - return bn -} - -func (pool *bnPool) Put(bn *big.Int) { - if pool == nil { - return - } - pool.bns = append(pool.bns, bn) - pool.count-- -} - -func (pool *bnPool) Count() int { - return pool.count -} diff --git a/builder/crypto/bn256/google/bn256_test.go b/builder/crypto/bn256/google/bn256_test.go deleted file mode 100644 index a4497ada9..000000000 --- a/builder/crypto/bn256/google/bn256_test.go +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "bytes" - "crypto/rand" - "math/big" - "testing" -) - -func TestGFp2Invert(t *testing.T) { - pool := new(bnPool) - - a := newGFp2(pool) - a.x.SetString("23423492374", 10) - a.y.SetString("12934872398472394827398470", 10) - - inv := newGFp2(pool) - inv.Invert(a, pool) - - b := newGFp2(pool).Mul(inv, a, pool) - if b.x.Int64() != 0 || b.y.Int64() != 1 { - t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) - } - - a.Put(pool) - b.Put(pool) - inv.Put(pool) - - if c := pool.Count(); c > 0 { - t.Errorf("Pool count non-zero: %d\n", c) - } -} - -func isZero(n *big.Int) bool { - return new(big.Int).Mod(n, P).Int64() == 0 -} - -func isOne(n *big.Int) bool { - return new(big.Int).Mod(n, P).Int64() == 1 -} - -func TestGFp6Invert(t *testing.T) { - pool := new(bnPool) - - a := newGFp6(pool) - a.x.x.SetString("239487238491", 10) - a.x.y.SetString("2356249827341", 10) - a.y.x.SetString("082659782", 10) - a.y.y.SetString("182703523765", 10) - a.z.x.SetString("978236549263", 10) - a.z.y.SetString("64893242", 10) - - inv := newGFp6(pool) - inv.Invert(a, pool) - - b := newGFp6(pool).Mul(inv, a, pool) - if !isZero(b.x.x) || - !isZero(b.x.y) || - !isZero(b.y.x) || - !isZero(b.y.y) || - !isZero(b.z.x) || - !isOne(b.z.y) { - t.Fatalf("bad result for a^-1*a: %s", b) - } - - a.Put(pool) - b.Put(pool) - inv.Put(pool) - - if c := pool.Count(); c > 0 { - t.Errorf("Pool count non-zero: %d\n", c) - } -} - -func TestGFp12Invert(t *testing.T) { - pool := new(bnPool) - - a := newGFp12(pool) - a.x.x.x.SetString("239846234862342323958623", 10) - a.x.x.y.SetString("2359862352529835623", 10) - a.x.y.x.SetString("928836523", 10) - a.x.y.y.SetString("9856234", 10) - a.x.z.x.SetString("235635286", 10) - a.x.z.y.SetString("5628392833", 10) - a.y.x.x.SetString("252936598265329856238956532167968", 10) - a.y.x.y.SetString("23596239865236954178968", 10) - a.y.y.x.SetString("95421692834", 10) - a.y.y.y.SetString("236548", 10) - a.y.z.x.SetString("924523", 10) - a.y.z.y.SetString("12954623", 10) - - inv := newGFp12(pool) - inv.Invert(a, pool) - - b := newGFp12(pool).Mul(inv, a, pool) - if !isZero(b.x.x.x) || - !isZero(b.x.x.y) || - !isZero(b.x.y.x) || - !isZero(b.x.y.y) || - !isZero(b.x.z.x) || - !isZero(b.x.z.y) || - !isZero(b.y.x.x) || - !isZero(b.y.x.y) || - !isZero(b.y.y.x) || - !isZero(b.y.y.y) || - !isZero(b.y.z.x) || - !isOne(b.y.z.y) { - t.Fatalf("bad result for a^-1*a: %s", b) - } - - a.Put(pool) - b.Put(pool) - inv.Put(pool) - - if c := pool.Count(); c > 0 { - t.Errorf("Pool count non-zero: %d\n", c) - } -} - -func TestCurveImpl(t *testing.T) { - pool := new(bnPool) - - g := &curvePoint{ - pool.Get().SetInt64(1), - pool.Get().SetInt64(-2), - pool.Get().SetInt64(1), - pool.Get().SetInt64(0), - } - - x := pool.Get().SetInt64(32498273234) - X := newCurvePoint(pool).Mul(g, x, pool) - - y := pool.Get().SetInt64(98732423523) - Y := newCurvePoint(pool).Mul(g, y, pool) - - s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) - s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) - - if s1.x.Cmp(s2.x) != 0 || - s2.x.Cmp(s1.x) != 0 { - t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) - } - - pool.Put(x) - X.Put(pool) - pool.Put(y) - Y.Put(pool) - s1.Put(pool) - s2.Put(pool) - g.Put(pool) - - if c := pool.Count(); c > 0 { - t.Errorf("Pool count non-zero: %d\n", c) - } -} - -func TestOrderG1(t *testing.T) { - g := new(G1).ScalarBaseMult(Order) - if !g.p.IsInfinity() { - t.Error("G1 has incorrect order") - } - - one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) - g.Add(g, one) - g.p.MakeAffine(nil) - if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { - t.Errorf("1+0 != 1 in G1") - } -} - -func TestOrderG2(t *testing.T) { - g := new(G2).ScalarBaseMult(Order) - if !g.p.IsInfinity() { - t.Error("G2 has incorrect order") - } - - one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) - g.Add(g, one) - g.p.MakeAffine(nil) - if g.p.x.x.Cmp(one.p.x.x) != 0 || - g.p.x.y.Cmp(one.p.x.y) != 0 || - g.p.y.x.Cmp(one.p.y.x) != 0 || - g.p.y.y.Cmp(one.p.y.y) != 0 { - t.Errorf("1+0 != 1 in G2") - } -} - -func TestOrderGT(t *testing.T) { - gt := Pair(&G1{curveGen}, &G2{twistGen}) - g := new(GT).ScalarMult(gt, Order) - if !g.p.IsOne() { - t.Error("GT has incorrect order") - } -} - -func TestBilinearity(t *testing.T) { - for i := 0; i < 2; i++ { - a, p1, _ := RandomG1(rand.Reader) - b, p2, _ := RandomG2(rand.Reader) - e1 := Pair(p1, p2) - - e2 := Pair(&G1{curveGen}, &G2{twistGen}) - e2.ScalarMult(e2, a) - e2.ScalarMult(e2, b) - - minusE2 := new(GT).Neg(e2) - e1.Add(e1, minusE2) - - if !e1.p.IsOne() { - t.Fatalf("bad pairing result: %s", e1) - } - } -} - -func TestG1Marshal(t *testing.T) { - g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) - form := g.Marshal() - _, err := new(G1).Unmarshal(form) - if err != nil { - t.Fatalf("failed to unmarshal") - } - - g.ScalarBaseMult(Order) - form = g.Marshal() - - g2 := new(G1) - if _, err = g2.Unmarshal(form); err != nil { - t.Fatalf("failed to unmarshal ∞") - } - if !g2.p.IsInfinity() { - t.Fatalf("∞ unmarshaled incorrectly") - } -} - -func TestG2Marshal(t *testing.T) { - g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) - form := g.Marshal() - _, err := new(G2).Unmarshal(form) - if err != nil { - t.Fatalf("failed to unmarshal") - } - - g.ScalarBaseMult(Order) - form = g.Marshal() - g2 := new(G2) - if _, err = g2.Unmarshal(form); err != nil { - t.Fatalf("failed to unmarshal ∞") - } - if !g2.p.IsInfinity() { - t.Fatalf("∞ unmarshaled incorrectly") - } -} - -func TestG1Identity(t *testing.T) { - g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) - if !g.p.IsInfinity() { - t.Error("failure") - } -} - -func TestG2Identity(t *testing.T) { - g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) - if !g.p.IsInfinity() { - t.Error("failure") - } -} - -func TestTripartiteDiffieHellman(t *testing.T) { - a, _ := rand.Int(rand.Reader, Order) - b, _ := rand.Int(rand.Reader, Order) - c, _ := rand.Int(rand.Reader, Order) - - pa := new(G1) - pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) - qa := new(G2) - qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) - pb := new(G1) - pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) - qb := new(G2) - qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) - pc := new(G1) - pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) - qc := new(G2) - qc.Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) - - k1 := Pair(pb, qc) - k1.ScalarMult(k1, a) - k1Bytes := k1.Marshal() - - k2 := Pair(pc, qa) - k2.ScalarMult(k2, b) - k2Bytes := k2.Marshal() - - k3 := Pair(pa, qb) - k3.ScalarMult(k3, c) - k3Bytes := k3.Marshal() - - if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { - t.Errorf("keys didn't agree") - } -} - -func BenchmarkPairing(b *testing.B) { - for i := 0; i < b.N; i++ { - Pair(&G1{curveGen}, &G2{twistGen}) - } -} diff --git a/builder/crypto/bn256/google/constants.go b/builder/crypto/bn256/google/constants.go deleted file mode 100644 index 2990bd951..000000000 --- a/builder/crypto/bn256/google/constants.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "math/big" -) - -func bigFromBase10(s string) *big.Int { - n, _ := new(big.Int).SetString(s, 10) - return n -} - -// u is the BN parameter that determines the prime. -var u = bigFromBase10("4965661367192848881") - -// P is a prime over which we form a basic field: 36uâ´+36u³+24u²+6u+1. -var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") - -// Order is the number of elements in both Gâ‚ and Gâ‚‚: 36uâ´+36u³+18u²+6u+1. -// Needs to be highly 2-adic for efficient SNARK key and proof generation. -// Order - 1 = 2^28 * 3^2 * 13 * 29 * 983 * 11003 * 237073 * 405928799 * 1670836401704629 * 13818364434197438864469338081. -// Refer to https://eprint.iacr.org/2013/879.pdf and https://eprint.iacr.org/2013/507.pdf for more information on these parameters. -var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") - -// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9. -var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")} - -// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9. -var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")} - -// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9. -var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")} - -// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9. -var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616") - -// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p). -var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966") - -// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p). -var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617") - -// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9. -var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")} diff --git a/builder/crypto/bn256/google/curve.go b/builder/crypto/bn256/google/curve.go deleted file mode 100644 index 819cb81da..000000000 --- a/builder/crypto/bn256/google/curve.go +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "math/big" -) - -// curvePoint implements the elliptic curve y²=x³+3. Points are kept in -// Jacobian form and t=z² when valid. Gâ‚ is the set of points of this curve on -// GF(p). -type curvePoint struct { - x, y, z, t *big.Int -} - -var curveB = new(big.Int).SetInt64(3) - -// curveGen is the generator of Gâ‚. -var curveGen = &curvePoint{ - new(big.Int).SetInt64(1), - new(big.Int).SetInt64(2), - new(big.Int).SetInt64(1), - new(big.Int).SetInt64(1), -} - -func newCurvePoint(pool *bnPool) *curvePoint { - return &curvePoint{ - pool.Get(), - pool.Get(), - pool.Get(), - pool.Get(), - } -} - -func (c *curvePoint) String() string { - c.MakeAffine(new(bnPool)) - return "(" + c.x.String() + ", " + c.y.String() + ")" -} - -func (c *curvePoint) Put(pool *bnPool) { - pool.Put(c.x) - pool.Put(c.y) - pool.Put(c.z) - pool.Put(c.t) -} - -func (c *curvePoint) Set(a *curvePoint) { - c.x.Set(a.x) - c.y.Set(a.y) - c.z.Set(a.z) - c.t.Set(a.t) -} - -// IsOnCurve returns true iff c is on the curve where c must be in affine form. -func (c *curvePoint) IsOnCurve() bool { - yy := new(big.Int).Mul(c.y, c.y) - xxx := new(big.Int).Mul(c.x, c.x) - xxx.Mul(xxx, c.x) - yy.Sub(yy, xxx) - yy.Sub(yy, curveB) - if yy.Sign() < 0 || yy.Cmp(P) >= 0 { - yy.Mod(yy, P) - } - return yy.Sign() == 0 -} - -func (c *curvePoint) SetInfinity() { - c.z.SetInt64(0) -} - -func (c *curvePoint) IsInfinity() bool { - return c.z.Sign() == 0 -} - -func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { - if a.IsInfinity() { - c.Set(b) - return - } - if b.IsInfinity() { - c.Set(a) - return - } - - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 - - // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] - // by [u1:s1:z1·z2] and [u2:s2:z1·z2] - // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ - z1z1 := pool.Get().Mul(a.z, a.z) - z1z1.Mod(z1z1, P) - z2z2 := pool.Get().Mul(b.z, b.z) - z2z2.Mod(z2z2, P) - u1 := pool.Get().Mul(a.x, z2z2) - u1.Mod(u1, P) - u2 := pool.Get().Mul(b.x, z1z1) - u2.Mod(u2, P) - - t := pool.Get().Mul(b.z, z2z2) - t.Mod(t, P) - s1 := pool.Get().Mul(a.y, t) - s1.Mod(s1, P) - - t.Mul(a.z, z1z1) - t.Mod(t, P) - s2 := pool.Get().Mul(b.y, t) - s2.Mod(s2, P) - - // Compute x = (2h)²(s²-u1-u2) - // where s = (s2-s1)/(u2-u1) is the slope of the line through - // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. - // This is also: - // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) - // = r² - j - 2v - // with the notations below. - h := pool.Get().Sub(u2, u1) - xEqual := h.Sign() == 0 - - t.Add(h, h) - // i = 4h² - i := pool.Get().Mul(t, t) - i.Mod(i, P) - // j = 4h³ - j := pool.Get().Mul(h, i) - j.Mod(j, P) - - t.Sub(s2, s1) - yEqual := t.Sign() == 0 - if xEqual && yEqual { - c.Double(a, pool) - return - } - r := pool.Get().Add(t, t) - - v := pool.Get().Mul(u1, i) - v.Mod(v, P) - - // t4 = 4(s2-s1)² - t4 := pool.Get().Mul(r, r) - t4.Mod(t4, P) - t.Add(v, v) - t6 := pool.Get().Sub(t4, j) - c.x.Sub(t6, t) - - // Set y = -(2h)³(s1 + s*(x/4h²-u1)) - // This is also - // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j - t.Sub(v, c.x) // t7 - t4.Mul(s1, j) // t8 - t4.Mod(t4, P) - t6.Add(t4, t4) // t9 - t4.Mul(r, t) // t10 - t4.Mod(t4, P) - c.y.Sub(t4, t6) - - // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 - t.Add(a.z, b.z) // t11 - t4.Mul(t, t) // t12 - t4.Mod(t4, P) - t.Sub(t4, z1z1) // t13 - t4.Sub(t, z2z2) // t14 - c.z.Mul(t4, h) - c.z.Mod(c.z, P) - - pool.Put(z1z1) - pool.Put(z2z2) - pool.Put(u1) - pool.Put(u2) - pool.Put(t) - pool.Put(s1) - pool.Put(s2) - pool.Put(h) - pool.Put(i) - pool.Put(j) - pool.Put(r) - pool.Put(v) - pool.Put(t4) - pool.Put(t6) -} - -func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 - A := pool.Get().Mul(a.x, a.x) - A.Mod(A, P) - B := pool.Get().Mul(a.y, a.y) - B.Mod(B, P) - C_ := pool.Get().Mul(B, B) - C_.Mod(C_, P) - - t := pool.Get().Add(a.x, B) - t2 := pool.Get().Mul(t, t) - t2.Mod(t2, P) - t.Sub(t2, A) - t2.Sub(t, C_) - d := pool.Get().Add(t2, t2) - t.Add(A, A) - e := pool.Get().Add(t, A) - f := pool.Get().Mul(e, e) - f.Mod(f, P) - - t.Add(d, d) - c.x.Sub(f, t) - - t.Add(C_, C_) - t2.Add(t, t) - t.Add(t2, t2) - c.y.Sub(d, c.x) - t2.Mul(e, c.y) - t2.Mod(t2, P) - c.y.Sub(t2, t) - - t.Mul(a.y, a.z) - t.Mod(t, P) - c.z.Add(t, t) - - pool.Put(A) - pool.Put(B) - pool.Put(C_) - pool.Put(t) - pool.Put(t2) - pool.Put(d) - pool.Put(e) - pool.Put(f) -} - -func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { - sum := newCurvePoint(pool) - sum.SetInfinity() - t := newCurvePoint(pool) - - for i := scalar.BitLen(); i >= 0; i-- { - t.Double(sum, pool) - if scalar.Bit(i) != 0 { - sum.Add(t, a, pool) - } else { - sum.Set(t) - } - } - - c.Set(sum) - sum.Put(pool) - t.Put(pool) - return c -} - -// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -// c to 0 : 1 : 0. -func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { - if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { - return c - } - if c.IsInfinity() { - c.x.SetInt64(0) - c.y.SetInt64(1) - c.z.SetInt64(0) - c.t.SetInt64(0) - return c - } - zInv := pool.Get().ModInverse(c.z, P) - t := pool.Get().Mul(c.y, zInv) - t.Mod(t, P) - zInv2 := pool.Get().Mul(zInv, zInv) - zInv2.Mod(zInv2, P) - c.y.Mul(t, zInv2) - c.y.Mod(c.y, P) - t.Mul(c.x, zInv2) - t.Mod(t, P) - c.x.Set(t) - c.z.SetInt64(1) - c.t.SetInt64(1) - - pool.Put(zInv) - pool.Put(t) - pool.Put(zInv2) - - return c -} - -func (c *curvePoint) Negative(a *curvePoint) { - c.x.Set(a.x) - c.y.Neg(a.y) - c.z.Set(a.z) - c.t.SetInt64(0) -} diff --git a/builder/crypto/bn256/google/example_test.go b/builder/crypto/bn256/google/example_test.go deleted file mode 100644 index b2d19807a..000000000 --- a/builder/crypto/bn256/google/example_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "crypto/rand" -) - -func ExamplePair() { - // This implements the tripartite Diffie-Hellman algorithm from "A One - // Round Protocol for Tripartite Diffie-Hellman", A. Joux. - // http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf - - // Each of three parties, a, b and c, generate a private value. - a, _ := rand.Int(rand.Reader, Order) - b, _ := rand.Int(rand.Reader, Order) - c, _ := rand.Int(rand.Reader, Order) - - // Then each party calculates gâ‚ and gâ‚‚ times their private value. - pa := new(G1).ScalarBaseMult(a) - qa := new(G2).ScalarBaseMult(a) - - pb := new(G1).ScalarBaseMult(b) - qb := new(G2).ScalarBaseMult(b) - - pc := new(G1).ScalarBaseMult(c) - qc := new(G2).ScalarBaseMult(c) - - // Now each party exchanges its public values with the other two and - // all parties can calculate the shared key. - k1 := Pair(pb, qc) - k1.ScalarMult(k1, a) - - k2 := Pair(pc, qa) - k2.ScalarMult(k2, b) - - k3 := Pair(pa, qb) - k3.ScalarMult(k3, c) - - // k1, k2 and k3 will all be equal. -} diff --git a/builder/crypto/bn256/google/gfp12.go b/builder/crypto/bn256/google/gfp12.go deleted file mode 100644 index f084eddf2..000000000 --- a/builder/crypto/bn256/google/gfp12.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -import ( - "math/big" -) - -// gfP12 implements the field of size p¹² as a quadratic extension of gfP6 -// where ω²=Ï„. -type gfP12 struct { - x, y *gfP6 // value is xω + y -} - -func newGFp12(pool *bnPool) *gfP12 { - return &gfP12{newGFp6(pool), newGFp6(pool)} -} - -func (e *gfP12) String() string { - return "(" + e.x.String() + "," + e.y.String() + ")" -} - -func (e *gfP12) Put(pool *bnPool) { - e.x.Put(pool) - e.y.Put(pool) -} - -func (e *gfP12) Set(a *gfP12) *gfP12 { - e.x.Set(a.x) - e.y.Set(a.y) - return e -} - -func (e *gfP12) SetZero() *gfP12 { - e.x.SetZero() - e.y.SetZero() - return e -} - -func (e *gfP12) SetOne() *gfP12 { - e.x.SetZero() - e.y.SetOne() - return e -} - -func (e *gfP12) Minimal() { - e.x.Minimal() - e.y.Minimal() -} - -func (e *gfP12) IsZero() bool { - e.Minimal() - return e.x.IsZero() && e.y.IsZero() -} - -func (e *gfP12) IsOne() bool { - e.Minimal() - return e.x.IsZero() && e.y.IsOne() -} - -func (e *gfP12) Conjugate(a *gfP12) *gfP12 { - e.x.Negative(a.x) - e.y.Set(a.y) - return a -} - -func (e *gfP12) Negative(a *gfP12) *gfP12 { - e.x.Negative(a.x) - e.y.Negative(a.y) - return e -} - -// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p -func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { - e.x.Frobenius(a.x, pool) - e.y.Frobenius(a.y, pool) - e.x.MulScalar(e.x, xiToPMinus1Over6, pool) - return e -} - -// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² -func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { - e.x.FrobeniusP2(a.x) - e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) - e.y.FrobeniusP2(a.y) - return e -} - -func (e *gfP12) Add(a, b *gfP12) *gfP12 { - e.x.Add(a.x, b.x) - e.y.Add(a.y, b.y) - return e -} - -func (e *gfP12) Sub(a, b *gfP12) *gfP12 { - e.x.Sub(a.x, b.x) - e.y.Sub(a.y, b.y) - return e -} - -func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { - tx := newGFp6(pool) - tx.Mul(a.x, b.y, pool) - t := newGFp6(pool) - t.Mul(b.x, a.y, pool) - tx.Add(tx, t) - - ty := newGFp6(pool) - ty.Mul(a.y, b.y, pool) - t.Mul(a.x, b.x, pool) - t.MulTau(t, pool) - e.y.Add(ty, t) - e.x.Set(tx) - - tx.Put(pool) - ty.Put(pool) - t.Put(pool) - return e -} - -func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { - e.x.Mul(e.x, b, pool) - e.y.Mul(e.y, b, pool) - return e -} - -func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { - sum := newGFp12(pool) - sum.SetOne() - t := newGFp12(pool) - - for i := power.BitLen() - 1; i >= 0; i-- { - t.Square(sum, pool) - if power.Bit(i) != 0 { - sum.Mul(t, a, pool) - } else { - sum.Set(t) - } - } - - c.Set(sum) - - sum.Put(pool) - t.Put(pool) - - return c -} - -func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { - // Complex squaring algorithm - v0 := newGFp6(pool) - v0.Mul(a.x, a.y, pool) - - t := newGFp6(pool) - t.MulTau(a.x, pool) - t.Add(a.y, t) - ty := newGFp6(pool) - ty.Add(a.x, a.y) - ty.Mul(ty, t, pool) - ty.Sub(ty, v0) - t.MulTau(v0, pool) - ty.Sub(ty, t) - - e.y.Set(ty) - e.x.Double(v0) - - v0.Put(pool) - t.Put(pool) - ty.Put(pool) - - return e -} - -func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - t1 := newGFp6(pool) - t2 := newGFp6(pool) - - t1.Square(a.x, pool) - t2.Square(a.y, pool) - t1.MulTau(t1, pool) - t1.Sub(t2, t1) - t2.Invert(t1, pool) - - e.x.Negative(a.x) - e.y.Set(a.y) - e.MulScalar(e, t2, pool) - - t1.Put(pool) - t2.Put(pool) - - return e -} diff --git a/builder/crypto/bn256/google/gfp2.go b/builder/crypto/bn256/google/gfp2.go deleted file mode 100644 index 3981f6cb4..000000000 --- a/builder/crypto/bn256/google/gfp2.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -import ( - "math/big" -) - -// gfP2 implements a field of size p² as a quadratic extension of the base -// field where i²=-1. -type gfP2 struct { - x, y *big.Int // value is xi+y. -} - -func newGFp2(pool *bnPool) *gfP2 { - return &gfP2{pool.Get(), pool.Get()} -} - -func (e *gfP2) String() string { - x := new(big.Int).Mod(e.x, P) - y := new(big.Int).Mod(e.y, P) - return "(" + x.String() + "," + y.String() + ")" -} - -func (e *gfP2) Put(pool *bnPool) { - pool.Put(e.x) - pool.Put(e.y) -} - -func (e *gfP2) Set(a *gfP2) *gfP2 { - e.x.Set(a.x) - e.y.Set(a.y) - return e -} - -func (e *gfP2) SetZero() *gfP2 { - e.x.SetInt64(0) - e.y.SetInt64(0) - return e -} - -func (e *gfP2) SetOne() *gfP2 { - e.x.SetInt64(0) - e.y.SetInt64(1) - return e -} - -func (e *gfP2) Minimal() { - if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 { - e.x.Mod(e.x, P) - } - if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 { - e.y.Mod(e.y, P) - } -} - -func (e *gfP2) IsZero() bool { - return e.x.Sign() == 0 && e.y.Sign() == 0 -} - -func (e *gfP2) IsOne() bool { - if e.x.Sign() != 0 { - return false - } - words := e.y.Bits() - return len(words) == 1 && words[0] == 1 -} - -func (e *gfP2) Conjugate(a *gfP2) *gfP2 { - e.y.Set(a.y) - e.x.Neg(a.x) - return e -} - -func (e *gfP2) Negative(a *gfP2) *gfP2 { - e.x.Neg(a.x) - e.y.Neg(a.y) - return e -} - -func (e *gfP2) Add(a, b *gfP2) *gfP2 { - e.x.Add(a.x, b.x) - e.y.Add(a.y, b.y) - return e -} - -func (e *gfP2) Sub(a, b *gfP2) *gfP2 { - e.x.Sub(a.x, b.x) - e.y.Sub(a.y, b.y) - return e -} - -func (e *gfP2) Double(a *gfP2) *gfP2 { - e.x.Lsh(a.x, 1) - e.y.Lsh(a.y, 1) - return e -} - -func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { - sum := newGFp2(pool) - sum.SetOne() - t := newGFp2(pool) - - for i := power.BitLen() - 1; i >= 0; i-- { - t.Square(sum, pool) - if power.Bit(i) != 0 { - sum.Mul(t, a, pool) - } else { - sum.Set(t) - } - } - - c.Set(sum) - - sum.Put(pool) - t.Put(pool) - - return c -} - -// See "Multiplication and Squaring in Pairing-Friendly Fields", -// http://eprint.iacr.org/2006/471.pdf -func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { - tx := pool.Get().Mul(a.x, b.y) - t := pool.Get().Mul(b.x, a.y) - tx.Add(tx, t) - tx.Mod(tx, P) - - ty := pool.Get().Mul(a.y, b.y) - t.Mul(a.x, b.x) - ty.Sub(ty, t) - e.y.Mod(ty, P) - e.x.Set(tx) - - pool.Put(tx) - pool.Put(ty) - pool.Put(t) - - return e -} - -func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { - e.x.Mul(a.x, b) - e.y.Mul(a.y, b) - return e -} - -// MulXi sets e=ξa where ξ=i+9 and then returns e. -func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { - // (xi+y)(i+3) = (9x+y)i+(9y-x) - tx := pool.Get().Lsh(a.x, 3) - tx.Add(tx, a.x) - tx.Add(tx, a.y) - - ty := pool.Get().Lsh(a.y, 3) - ty.Add(ty, a.y) - ty.Sub(ty, a.x) - - e.x.Set(tx) - e.y.Set(ty) - - pool.Put(tx) - pool.Put(ty) - - return e -} - -func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { - // Complex squaring algorithm: - // (xi+b)² = (x+y)(y-x) + 2*i*x*y - t1 := pool.Get().Sub(a.y, a.x) - t2 := pool.Get().Add(a.x, a.y) - ty := pool.Get().Mul(t1, t2) - ty.Mod(ty, P) - - t1.Mul(a.x, a.y) - t1.Lsh(t1, 1) - - e.x.Mod(t1, P) - e.y.Set(ty) - - pool.Put(t1) - pool.Put(t2) - pool.Put(ty) - - return e -} - -func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - t := pool.Get() - t.Mul(a.y, a.y) - t2 := pool.Get() - t2.Mul(a.x, a.x) - t.Add(t, t2) - - inv := pool.Get() - inv.ModInverse(t, P) - - e.x.Neg(a.x) - e.x.Mul(e.x, inv) - e.x.Mod(e.x, P) - - e.y.Mul(a.y, inv) - e.y.Mod(e.y, P) - - pool.Put(t) - pool.Put(t2) - pool.Put(inv) - - return e -} - -func (e *gfP2) Real() *big.Int { - return e.x -} - -func (e *gfP2) Imag() *big.Int { - return e.y -} diff --git a/builder/crypto/bn256/google/gfp6.go b/builder/crypto/bn256/google/gfp6.go deleted file mode 100644 index 218856617..000000000 --- a/builder/crypto/bn256/google/gfp6.go +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -// For details of the algorithms used, see "Multiplication and Squaring on -// Pairing-Friendly Fields, Devegili et al. -// http://eprint.iacr.org/2006/471.pdf. - -import ( - "math/big" -) - -// gfP6 implements the field of size pⶠas a cubic extension of gfP2 where τ³=ξ -// and ξ=i+9. -type gfP6 struct { - x, y, z *gfP2 // value is xτ² + yÏ„ + z -} - -func newGFp6(pool *bnPool) *gfP6 { - return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} -} - -func (e *gfP6) String() string { - return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" -} - -func (e *gfP6) Put(pool *bnPool) { - e.x.Put(pool) - e.y.Put(pool) - e.z.Put(pool) -} - -func (e *gfP6) Set(a *gfP6) *gfP6 { - e.x.Set(a.x) - e.y.Set(a.y) - e.z.Set(a.z) - return e -} - -func (e *gfP6) SetZero() *gfP6 { - e.x.SetZero() - e.y.SetZero() - e.z.SetZero() - return e -} - -func (e *gfP6) SetOne() *gfP6 { - e.x.SetZero() - e.y.SetZero() - e.z.SetOne() - return e -} - -func (e *gfP6) Minimal() { - e.x.Minimal() - e.y.Minimal() - e.z.Minimal() -} - -func (e *gfP6) IsZero() bool { - return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() -} - -func (e *gfP6) IsOne() bool { - return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() -} - -func (e *gfP6) Negative(a *gfP6) *gfP6 { - e.x.Negative(a.x) - e.y.Negative(a.y) - e.z.Negative(a.z) - return e -} - -func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { - e.x.Conjugate(a.x) - e.y.Conjugate(a.y) - e.z.Conjugate(a.z) - - e.x.Mul(e.x, xiTo2PMinus2Over3, pool) - e.y.Mul(e.y, xiToPMinus1Over3, pool) - return e -} - -// FrobeniusP2 computes (xτ²+yÏ„+z)^(p²) = xÏ„^(2p²) + yÏ„^(p²) + z -func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { - // Ï„^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) - e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) - // Ï„^(p²) = Ï„Ï„^(p²-1) = τξ^((p²-1)/3) - e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) - e.z.Set(a.z) - return e -} - -func (e *gfP6) Add(a, b *gfP6) *gfP6 { - e.x.Add(a.x, b.x) - e.y.Add(a.y, b.y) - e.z.Add(a.z, b.z) - return e -} - -func (e *gfP6) Sub(a, b *gfP6) *gfP6 { - e.x.Sub(a.x, b.x) - e.y.Sub(a.y, b.y) - e.z.Sub(a.z, b.z) - return e -} - -func (e *gfP6) Double(a *gfP6) *gfP6 { - e.x.Double(a.x) - e.y.Double(a.y) - e.z.Double(a.z) - return e -} - -func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { - // "Multiplication and Squaring on Pairing-Friendly Fields" - // Section 4, Karatsuba method. - // http://eprint.iacr.org/2006/471.pdf - - v0 := newGFp2(pool) - v0.Mul(a.z, b.z, pool) - v1 := newGFp2(pool) - v1.Mul(a.y, b.y, pool) - v2 := newGFp2(pool) - v2.Mul(a.x, b.x, pool) - - t0 := newGFp2(pool) - t0.Add(a.x, a.y) - t1 := newGFp2(pool) - t1.Add(b.x, b.y) - tz := newGFp2(pool) - tz.Mul(t0, t1, pool) - - tz.Sub(tz, v1) - tz.Sub(tz, v2) - tz.MulXi(tz, pool) - tz.Add(tz, v0) - - t0.Add(a.y, a.z) - t1.Add(b.y, b.z) - ty := newGFp2(pool) - ty.Mul(t0, t1, pool) - ty.Sub(ty, v0) - ty.Sub(ty, v1) - t0.MulXi(v2, pool) - ty.Add(ty, t0) - - t0.Add(a.x, a.z) - t1.Add(b.x, b.z) - tx := newGFp2(pool) - tx.Mul(t0, t1, pool) - tx.Sub(tx, v0) - tx.Add(tx, v1) - tx.Sub(tx, v2) - - e.x.Set(tx) - e.y.Set(ty) - e.z.Set(tz) - - t0.Put(pool) - t1.Put(pool) - tx.Put(pool) - ty.Put(pool) - tz.Put(pool) - v0.Put(pool) - v1.Put(pool) - v2.Put(pool) - return e -} - -func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { - e.x.Mul(a.x, b, pool) - e.y.Mul(a.y, b, pool) - e.z.Mul(a.z, b, pool) - return e -} - -func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { - e.x.MulScalar(a.x, b) - e.y.MulScalar(a.y, b) - e.z.MulScalar(a.z, b) - return e -} - -// MulTau computes τ·(aτ²+bÏ„+c) = bτ²+cÏ„+aξ -func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { - tz := newGFp2(pool) - tz.MulXi(a.x, pool) - ty := newGFp2(pool) - ty.Set(a.y) - e.y.Set(a.z) - e.x.Set(ty) - e.z.Set(tz) - tz.Put(pool) - ty.Put(pool) -} - -func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { - v0 := newGFp2(pool).Square(a.z, pool) - v1 := newGFp2(pool).Square(a.y, pool) - v2 := newGFp2(pool).Square(a.x, pool) - - c0 := newGFp2(pool).Add(a.x, a.y) - c0.Square(c0, pool) - c0.Sub(c0, v1) - c0.Sub(c0, v2) - c0.MulXi(c0, pool) - c0.Add(c0, v0) - - c1 := newGFp2(pool).Add(a.y, a.z) - c1.Square(c1, pool) - c1.Sub(c1, v0) - c1.Sub(c1, v1) - xiV2 := newGFp2(pool).MulXi(v2, pool) - c1.Add(c1, xiV2) - - c2 := newGFp2(pool).Add(a.x, a.z) - c2.Square(c2, pool) - c2.Sub(c2, v0) - c2.Add(c2, v1) - c2.Sub(c2, v2) - - e.x.Set(c2) - e.y.Set(c1) - e.z.Set(c0) - - v0.Put(pool) - v1.Put(pool) - v2.Put(pool) - c0.Put(pool) - c1.Put(pool) - c2.Put(pool) - xiV2.Put(pool) - - return e -} - -func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { - // See "Implementing cryptographic pairings", M. Scott, section 3.2. - // ftp://136.206.11.249/pub/crypto/pairings.pdf - - // Here we can give a short explanation of how it works: let j be a cubic root of - // unity in GF(p²) so that 1+j+j²=0. - // Then (xτ² + yÏ„ + z)(xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) - // = (xτ² + yÏ„ + z)(Cτ²+BÏ„+A) - // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). - // - // On the other hand (xj²τ² + yjÏ„ + z)(xjτ² + yj²τ + z) - // = τ²(y²-ξxz) + Ï„(ξx²-yz) + (z²-ξxy) - // - // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) - t1 := newGFp2(pool) - - A := newGFp2(pool) - A.Square(a.z, pool) - t1.Mul(a.x, a.y, pool) - t1.MulXi(t1, pool) - A.Sub(A, t1) - - B := newGFp2(pool) - B.Square(a.x, pool) - B.MulXi(B, pool) - t1.Mul(a.y, a.z, pool) - B.Sub(B, t1) - - C_ := newGFp2(pool) - C_.Square(a.y, pool) - t1.Mul(a.x, a.z, pool) - C_.Sub(C_, t1) - - F := newGFp2(pool) - F.Mul(C_, a.y, pool) - F.MulXi(F, pool) - t1.Mul(A, a.z, pool) - F.Add(F, t1) - t1.Mul(B, a.x, pool) - t1.MulXi(t1, pool) - F.Add(F, t1) - - F.Invert(F, pool) - - e.x.Mul(C_, F, pool) - e.y.Mul(B, F, pool) - e.z.Mul(A, F, pool) - - t1.Put(pool) - A.Put(pool) - B.Put(pool) - C_.Put(pool) - F.Put(pool) - - return e -} diff --git a/builder/crypto/bn256/google/main_test.go b/builder/crypto/bn256/google/main_test.go deleted file mode 100644 index c0c85457b..000000000 --- a/builder/crypto/bn256/google/main_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package bn256 - -import ( - "testing" - - "crypto/rand" -) - -func TestRandomG2Marshal(t *testing.T) { - for i := 0; i < 10; i++ { - n, g2, err := RandomG2(rand.Reader) - if err != nil { - t.Error(err) - continue - } - t.Logf("%v: %x\n", n, g2.Marshal()) - } -} - -func TestPairings(t *testing.T) { - a1 := new(G1).ScalarBaseMult(bigFromBase10("1")) - a2 := new(G1).ScalarBaseMult(bigFromBase10("2")) - a37 := new(G1).ScalarBaseMult(bigFromBase10("37")) - an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) - - b0 := new(G2).ScalarBaseMult(bigFromBase10("0")) - b1 := new(G2).ScalarBaseMult(bigFromBase10("1")) - b2 := new(G2).ScalarBaseMult(bigFromBase10("2")) - b27 := new(G2).ScalarBaseMult(bigFromBase10("27")) - b999 := new(G2).ScalarBaseMult(bigFromBase10("999")) - bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) - - p1 := Pair(a1, b1) - pn1 := Pair(a1, bn1) - np1 := Pair(an1, b1) - if pn1.String() != np1.String() { - t.Error("Pairing mismatch: e(a, -b) != e(-a, b)") - } - if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) { - t.Error("MultiAte check gave false negative!") - } - p0 := new(GT).Add(p1, pn1) - p0_2 := Pair(a1, b0) - if p0.String() != p0_2.String() { - t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1") - } - p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")) - if p0.String() != p0_3.String() { - t.Error("Pairing mismatch: e(a, b) has wrong order") - } - p2 := Pair(a2, b1) - p2_2 := Pair(a1, b2) - p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2")) - if p2.String() != p2_2.String() { - t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)") - } - if p2.String() != p2_3.String() { - t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2") - } - if p2.String() == p1.String() { - t.Error("Pairing is degenerate!") - } - if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) { - t.Error("MultiAte check gave false positive!") - } - p999 := Pair(a37, b27) - p999_2 := Pair(a1, b999) - if p999.String() != p999_2.String() { - t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)") - } -} diff --git a/builder/crypto/bn256/google/optate.go b/builder/crypto/bn256/google/optate.go deleted file mode 100644 index 9d6957062..000000000 --- a/builder/crypto/bn256/google/optate.go +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { - // See the mixed addition algorithm from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - - B := newGFp2(pool).Mul(p.x, r.t, pool) - - D := newGFp2(pool).Add(p.y, r.z) - D.Square(D, pool) - D.Sub(D, r2) - D.Sub(D, r.t) - D.Mul(D, r.t, pool) - - H := newGFp2(pool).Sub(B, r.x) - I := newGFp2(pool).Square(H, pool) - - E := newGFp2(pool).Add(I, I) - E.Add(E, E) - - J := newGFp2(pool).Mul(H, E, pool) - - L1 := newGFp2(pool).Sub(D, r.y) - L1.Sub(L1, r.y) - - V := newGFp2(pool).Mul(r.x, E, pool) - - rOut = newTwistPoint(pool) - rOut.x.Square(L1, pool) - rOut.x.Sub(rOut.x, J) - rOut.x.Sub(rOut.x, V) - rOut.x.Sub(rOut.x, V) - - rOut.z.Add(r.z, H) - rOut.z.Square(rOut.z, pool) - rOut.z.Sub(rOut.z, r.t) - rOut.z.Sub(rOut.z, I) - - t := newGFp2(pool).Sub(V, rOut.x) - t.Mul(t, L1, pool) - t2 := newGFp2(pool).Mul(r.y, J, pool) - t2.Add(t2, t2) - rOut.y.Sub(t, t2) - - rOut.t.Square(rOut.z, pool) - - t.Add(p.y, rOut.z) - t.Square(t, pool) - t.Sub(t, r2) - t.Sub(t, rOut.t) - - t2.Mul(L1, p.x, pool) - t2.Add(t2, t2) - a = newGFp2(pool) - a.Sub(t2, t) - - c = newGFp2(pool) - c.MulScalar(rOut.z, q.y) - c.Add(c, c) - - b = newGFp2(pool) - b.SetZero() - b.Sub(b, L1) - b.MulScalar(b, q.x) - b.Add(b, b) - - B.Put(pool) - D.Put(pool) - H.Put(pool) - I.Put(pool) - E.Put(pool) - J.Put(pool) - L1.Put(pool) - V.Put(pool) - t.Put(pool) - t2.Put(pool) - - return -} - -func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { - // See the doubling algorithm for a=0 from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - - A := newGFp2(pool).Square(r.x, pool) - B := newGFp2(pool).Square(r.y, pool) - C_ := newGFp2(pool).Square(B, pool) - - D := newGFp2(pool).Add(r.x, B) - D.Square(D, pool) - D.Sub(D, A) - D.Sub(D, C_) - D.Add(D, D) - - E := newGFp2(pool).Add(A, A) - E.Add(E, A) - - G := newGFp2(pool).Square(E, pool) - - rOut = newTwistPoint(pool) - rOut.x.Sub(G, D) - rOut.x.Sub(rOut.x, D) - - rOut.z.Add(r.y, r.z) - rOut.z.Square(rOut.z, pool) - rOut.z.Sub(rOut.z, B) - rOut.z.Sub(rOut.z, r.t) - - rOut.y.Sub(D, rOut.x) - rOut.y.Mul(rOut.y, E, pool) - t := newGFp2(pool).Add(C_, C_) - t.Add(t, t) - t.Add(t, t) - rOut.y.Sub(rOut.y, t) - - rOut.t.Square(rOut.z, pool) - - t.Mul(E, r.t, pool) - t.Add(t, t) - b = newGFp2(pool) - b.SetZero() - b.Sub(b, t) - b.MulScalar(b, q.x) - - a = newGFp2(pool) - a.Add(r.x, E) - a.Square(a, pool) - a.Sub(a, A) - a.Sub(a, G) - t.Add(B, B) - t.Add(t, t) - a.Sub(a, t) - - c = newGFp2(pool) - c.Mul(rOut.z, r.t, pool) - c.Add(c, c) - c.MulScalar(c, q.y) - - A.Put(pool) - B.Put(pool) - C_.Put(pool) - D.Put(pool) - E.Put(pool) - G.Put(pool) - t.Put(pool) - - return -} - -func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { - a2 := newGFp6(pool) - a2.x.SetZero() - a2.y.Set(a) - a2.z.Set(b) - a2.Mul(a2, ret.x, pool) - t3 := newGFp6(pool).MulScalar(ret.y, c, pool) - - t := newGFp2(pool) - t.Add(b, c) - t2 := newGFp6(pool) - t2.x.SetZero() - t2.y.Set(a) - t2.z.Set(t) - ret.x.Add(ret.x, ret.y) - - ret.y.Set(t3) - - ret.x.Mul(ret.x, t2, pool) - ret.x.Sub(ret.x, a2) - ret.x.Sub(ret.x, ret.y) - a2.MulTau(a2, pool) - ret.y.Add(ret.y, a2) - - a2.Put(pool) - t3.Put(pool) - t2.Put(pool) - t.Put(pool) -} - -// sixuPlus2NAF is 6u+2 in non-adjacent form. -var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, - 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, - 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, - 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} - -// miller implements the Miller loop for calculating the Optimal Ate pairing. -// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf -func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { - ret := newGFp12(pool) - ret.SetOne() - - aAffine := newTwistPoint(pool) - aAffine.Set(q) - aAffine.MakeAffine(pool) - - bAffine := newCurvePoint(pool) - bAffine.Set(p) - bAffine.MakeAffine(pool) - - minusA := newTwistPoint(pool) - minusA.Negative(aAffine, pool) - - r := newTwistPoint(pool) - r.Set(aAffine) - - r2 := newGFp2(pool) - r2.Square(aAffine.y, pool) - - for i := len(sixuPlus2NAF) - 1; i > 0; i-- { - a, b, c, newR := lineFunctionDouble(r, bAffine, pool) - if i != len(sixuPlus2NAF)-1 { - ret.Square(ret, pool) - } - - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - switch sixuPlus2NAF[i-1] { - case 1: - a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) - case -1: - a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) - default: - continue - } - - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - } - - // In order to calculate Q1 we have to convert q from the sextic twist - // to the full GF(p^12) group, apply the Frobenius there, and convert - // back. - // - // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just - // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) - // where xÌ„ is the conjugate of x. If we are going to apply the inverse - // isomorphism we need a value with a single coefficient of ω² so we - // rewrite this as x̄ω^(2p-2)ω². ξⶠ= ω and, due to the construction of - // p, 2p-2 is a multiple of six. Therefore we can rewrite as - // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the - // ω². - // - // A similar argument can be made for the y value. - - q1 := newTwistPoint(pool) - q1.x.Conjugate(aAffine.x) - q1.x.Mul(q1.x, xiToPMinus1Over3, pool) - q1.y.Conjugate(aAffine.y) - q1.y.Mul(q1.y, xiToPMinus1Over2, pool) - q1.z.SetOne() - q1.t.SetOne() - - // For Q2 we are applying the p² Frobenius. The two conjugations cancel - // out and we are left only with the factors from the isomorphism. In - // the case of x, we end up with a pure number which is why - // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We - // ignore this to end up with -Q2. - - minusQ2 := newTwistPoint(pool) - minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) - minusQ2.y.Set(aAffine.y) - minusQ2.z.SetOne() - minusQ2.t.SetOne() - - r2.Square(q1.y, pool) - a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - r2.Square(minusQ2.y, pool) - a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - aAffine.Put(pool) - bAffine.Put(pool) - minusA.Put(pool) - r.Put(pool) - r2.Put(pool) - - return ret -} - -// finalExponentiation computes the (p¹²-1)/Order-th power of an element of -// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from -// http://cryptojedi.org/papers/dclxvi-20100714.pdf) -func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { - t1 := newGFp12(pool) - - // This is the p^6-Frobenius - t1.x.Negative(in.x) - t1.y.Set(in.y) - - inv := newGFp12(pool) - inv.Invert(in, pool) - t1.Mul(t1, inv, pool) - - t2 := newGFp12(pool).FrobeniusP2(t1, pool) - t1.Mul(t1, t2, pool) - - fp := newGFp12(pool).Frobenius(t1, pool) - fp2 := newGFp12(pool).FrobeniusP2(t1, pool) - fp3 := newGFp12(pool).Frobenius(fp2, pool) - - fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) - fu.Exp(t1, u, pool) - fu2.Exp(fu, u, pool) - fu3.Exp(fu2, u, pool) - - y3 := newGFp12(pool).Frobenius(fu, pool) - fu2p := newGFp12(pool).Frobenius(fu2, pool) - fu3p := newGFp12(pool).Frobenius(fu3, pool) - y2 := newGFp12(pool).FrobeniusP2(fu2, pool) - - y0 := newGFp12(pool) - y0.Mul(fp, fp2, pool) - y0.Mul(y0, fp3, pool) - - y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) - y1.Conjugate(t1) - y5.Conjugate(fu2) - y3.Conjugate(y3) - y4.Mul(fu, fu2p, pool) - y4.Conjugate(y4) - - y6 := newGFp12(pool) - y6.Mul(fu3, fu3p, pool) - y6.Conjugate(y6) - - t0 := newGFp12(pool) - t0.Square(y6, pool) - t0.Mul(t0, y4, pool) - t0.Mul(t0, y5, pool) - t1.Mul(y3, y5, pool) - t1.Mul(t1, t0, pool) - t0.Mul(t0, y2, pool) - t1.Square(t1, pool) - t1.Mul(t1, t0, pool) - t1.Square(t1, pool) - t0.Mul(t1, y1, pool) - t1.Mul(t1, y0, pool) - t0.Square(t0, pool) - t0.Mul(t0, t1, pool) - - inv.Put(pool) - t1.Put(pool) - t2.Put(pool) - fp.Put(pool) - fp2.Put(pool) - fp3.Put(pool) - fu.Put(pool) - fu2.Put(pool) - fu3.Put(pool) - fu2p.Put(pool) - fu3p.Put(pool) - y0.Put(pool) - y1.Put(pool) - y2.Put(pool) - y3.Put(pool) - y4.Put(pool) - y5.Put(pool) - y6.Put(pool) - - return t0 -} - -func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { - e := miller(a, b, pool) - ret := finalExponentiation(e, pool) - e.Put(pool) - - if a.IsInfinity() || b.IsInfinity() { - ret.SetOne() - } - return ret -} diff --git a/builder/crypto/bn256/google/twist.go b/builder/crypto/bn256/google/twist.go deleted file mode 100644 index 43364ff5b..000000000 --- a/builder/crypto/bn256/google/twist.go +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bn256 - -import ( - "math/big" -) - -// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are -// kept in Jacobian form and t=z² when valid. The group Gâ‚‚ is the set of -// n-torsion points of this curve over GF(p²) (where n = Order) -type twistPoint struct { - x, y, z, t *gfP2 -} - -var twistB = &gfP2{ - bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"), - bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"), -} - -// twistGen is the generator of group Gâ‚‚. -var twistGen = &twistPoint{ - &gfP2{ - bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"), - bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"), - }, - &gfP2{ - bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"), - bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"), - }, - &gfP2{ - bigFromBase10("0"), - bigFromBase10("1"), - }, - &gfP2{ - bigFromBase10("0"), - bigFromBase10("1"), - }, -} - -func newTwistPoint(pool *bnPool) *twistPoint { - return &twistPoint{ - newGFp2(pool), - newGFp2(pool), - newGFp2(pool), - newGFp2(pool), - } -} - -func (c *twistPoint) String() string { - return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" -} - -func (c *twistPoint) Put(pool *bnPool) { - c.x.Put(pool) - c.y.Put(pool) - c.z.Put(pool) - c.t.Put(pool) -} - -func (c *twistPoint) Set(a *twistPoint) { - c.x.Set(a.x) - c.y.Set(a.y) - c.z.Set(a.z) - c.t.Set(a.t) -} - -// IsOnCurve returns true iff c is on the curve where c must be in affine form. -func (c *twistPoint) IsOnCurve() bool { - pool := new(bnPool) - yy := newGFp2(pool).Square(c.y, pool) - xxx := newGFp2(pool).Square(c.x, pool) - xxx.Mul(xxx, c.x, pool) - yy.Sub(yy, xxx) - yy.Sub(yy, twistB) - yy.Minimal() - - if yy.x.Sign() != 0 || yy.y.Sign() != 0 { - return false - } - cneg := newTwistPoint(pool) - cneg.Mul(c, Order, pool) - return cneg.z.IsZero() -} - -func (c *twistPoint) SetInfinity() { - c.z.SetZero() -} - -func (c *twistPoint) IsInfinity() bool { - return c.z.IsZero() -} - -func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { - // For additional comments, see the same function in curve.go. - - if a.IsInfinity() { - c.Set(b) - return - } - if b.IsInfinity() { - c.Set(a) - return - } - - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 - z1z1 := newGFp2(pool).Square(a.z, pool) - z2z2 := newGFp2(pool).Square(b.z, pool) - u1 := newGFp2(pool).Mul(a.x, z2z2, pool) - u2 := newGFp2(pool).Mul(b.x, z1z1, pool) - - t := newGFp2(pool).Mul(b.z, z2z2, pool) - s1 := newGFp2(pool).Mul(a.y, t, pool) - - t.Mul(a.z, z1z1, pool) - s2 := newGFp2(pool).Mul(b.y, t, pool) - - h := newGFp2(pool).Sub(u2, u1) - xEqual := h.IsZero() - - t.Add(h, h) - i := newGFp2(pool).Square(t, pool) - j := newGFp2(pool).Mul(h, i, pool) - - t.Sub(s2, s1) - yEqual := t.IsZero() - if xEqual && yEqual { - c.Double(a, pool) - return - } - r := newGFp2(pool).Add(t, t) - - v := newGFp2(pool).Mul(u1, i, pool) - - t4 := newGFp2(pool).Square(r, pool) - t.Add(v, v) - t6 := newGFp2(pool).Sub(t4, j) - c.x.Sub(t6, t) - - t.Sub(v, c.x) // t7 - t4.Mul(s1, j, pool) // t8 - t6.Add(t4, t4) // t9 - t4.Mul(r, t, pool) // t10 - c.y.Sub(t4, t6) - - t.Add(a.z, b.z) // t11 - t4.Square(t, pool) // t12 - t.Sub(t4, z1z1) // t13 - t4.Sub(t, z2z2) // t14 - c.z.Mul(t4, h, pool) - - z1z1.Put(pool) - z2z2.Put(pool) - u1.Put(pool) - u2.Put(pool) - t.Put(pool) - s1.Put(pool) - s2.Put(pool) - h.Put(pool) - i.Put(pool) - j.Put(pool) - r.Put(pool) - v.Put(pool) - t4.Put(pool) - t6.Put(pool) -} - -func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { - // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 - A := newGFp2(pool).Square(a.x, pool) - B := newGFp2(pool).Square(a.y, pool) - C_ := newGFp2(pool).Square(B, pool) - - t := newGFp2(pool).Add(a.x, B) - t2 := newGFp2(pool).Square(t, pool) - t.Sub(t2, A) - t2.Sub(t, C_) - d := newGFp2(pool).Add(t2, t2) - t.Add(A, A) - e := newGFp2(pool).Add(t, A) - f := newGFp2(pool).Square(e, pool) - - t.Add(d, d) - c.x.Sub(f, t) - - t.Add(C_, C_) - t2.Add(t, t) - t.Add(t2, t2) - c.y.Sub(d, c.x) - t2.Mul(e, c.y, pool) - c.y.Sub(t2, t) - - t.Mul(a.y, a.z, pool) - c.z.Add(t, t) - - A.Put(pool) - B.Put(pool) - C_.Put(pool) - t.Put(pool) - t2.Put(pool) - d.Put(pool) - e.Put(pool) - f.Put(pool) -} - -func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { - sum := newTwistPoint(pool) - sum.SetInfinity() - t := newTwistPoint(pool) - - for i := scalar.BitLen(); i >= 0; i-- { - t.Double(sum, pool) - if scalar.Bit(i) != 0 { - sum.Add(t, a, pool) - } else { - sum.Set(t) - } - } - - c.Set(sum) - sum.Put(pool) - t.Put(pool) - return c -} - -// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets -// c to 0 : 1 : 0. -func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { - if c.z.IsOne() { - return c - } - if c.IsInfinity() { - c.x.SetZero() - c.y.SetOne() - c.z.SetZero() - c.t.SetZero() - return c - } - zInv := newGFp2(pool).Invert(c.z, pool) - t := newGFp2(pool).Mul(c.y, zInv, pool) - zInv2 := newGFp2(pool).Square(zInv, pool) - c.y.Mul(t, zInv2, pool) - t.Mul(c.x, zInv2, pool) - c.x.Set(t) - c.z.SetOne() - c.t.SetOne() - - zInv.Put(pool) - t.Put(pool) - zInv2.Put(pool) - - return c -} - -func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { - c.x.Set(a.x) - c.y.SetZero() - c.y.Sub(c.y, a.y) - c.z.Set(a.z) - c.t.SetZero() -} diff --git a/builder/crypto/crypto.go b/builder/crypto/crypto.go deleted file mode 100644 index 2492165d3..000000000 --- a/builder/crypto/crypto.go +++ /dev/null @@ -1,284 +0,0 @@ -// 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 crypto - -import ( - "bufio" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "encoding/hex" - "errors" - "fmt" - "hash" - "io" - "math/big" - "os" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" -) - -// SignatureLength indicates the byte length required to carry a signature with recovery id. -const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id - -// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id. -const RecoveryIDOffset = 64 - -// DigestLength sets the signature digest exact length -const DigestLength = 32 - -var ( - secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) - secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2)) -) - -var errInvalidPubkey = errors.New("invalid secp256k1 public key") - -// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports -// Read to get a variable amount of data from the hash state. Read is faster than Sum -// because it doesn't copy the internal state, but also modifies the internal state. -type KeccakState interface { - hash.Hash - Read([]byte) (int, error) -} - -// NewKeccakState creates a new KeccakState -func NewKeccakState() KeccakState { - return sha3.NewLegacyKeccak256().(KeccakState) -} - -// HashData hashes the provided data using the KeccakState and returns a 32 byte hash -func HashData(kh KeccakState, data []byte) (h common.Hash) { - kh.Reset() - kh.Write(data) - kh.Read(h[:]) - return h -} - -// Keccak256 calculates and returns the Keccak256 hash of the input data. -func Keccak256(data ...[]byte) []byte { - b := make([]byte, 32) - d := NewKeccakState() - for _, b := range data { - d.Write(b) - } - d.Read(b) - return b -} - -// Keccak256Hash calculates and returns the Keccak256 hash of the input data, -// converting it to an internal Hash data structure. -func Keccak256Hash(data ...[]byte) (h common.Hash) { - d := NewKeccakState() - for _, b := range data { - d.Write(b) - } - d.Read(h[:]) - return h -} - -// Keccak512 calculates and returns the Keccak512 hash of the input data. -func Keccak512(data ...[]byte) []byte { - d := sha3.NewLegacyKeccak512() - for _, b := range data { - d.Write(b) - } - return d.Sum(nil) -} - -// CreateAddress creates an ethereum address given the bytes and the nonce -func CreateAddress(b common.Address, nonce uint64) common.Address { - data, _ := rlp.EncodeToBytes([]interface{}{b, nonce}) - return common.BytesToAddress(Keccak256(data)[12:]) -} - -// CreateAddress2 creates an ethereum address given the address bytes, initial -// contract code hash and a salt. -func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address { - return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:]) -} - -// ToECDSA creates a private key with the given D value. -func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) { - return toECDSA(d, true) -} - -// ToECDSAUnsafe blindly converts a binary blob to a private key. It should almost -// never be used unless you are sure the input is valid and want to avoid hitting -// errors due to bad origin encoding (0 prefixes cut off). -func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey { - priv, _ := toECDSA(d, false) - return priv -} - -// toECDSA creates a private key with the given D value. The strict parameter -// controls whether the key's length should be enforced at the curve size or -// it can also accept legacy encodings (0 prefixes). -func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) { - priv := new(ecdsa.PrivateKey) - priv.PublicKey.Curve = S256() - if strict && 8*len(d) != priv.Params().BitSize { - return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize) - } - priv.D = new(big.Int).SetBytes(d) - - // The priv.D must < N - if priv.D.Cmp(secp256k1N) >= 0 { - return nil, errors.New("invalid private key, >=N") - } - // The priv.D must not be zero or negative. - if priv.D.Sign() <= 0 { - return nil, errors.New("invalid private key, zero or negative") - } - - priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d) - if priv.PublicKey.X == nil { - return nil, errors.New("invalid private key") - } - return priv, nil -} - -// FromECDSA exports a private key into a binary dump. -func FromECDSA(priv *ecdsa.PrivateKey) []byte { - if priv == nil { - return nil - } - return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8) -} - -// UnmarshalPubkey converts bytes to a secp256k1 public key. -func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) { - x, y := elliptic.Unmarshal(S256(), pub) - if x == nil { - return nil, errInvalidPubkey - } - return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil -} - -func FromECDSAPub(pub *ecdsa.PublicKey) []byte { - if pub == nil || pub.X == nil || pub.Y == nil { - return nil - } - return elliptic.Marshal(S256(), pub.X, pub.Y) -} - -// HexToECDSA parses a secp256k1 private key. -func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) { - b, err := hex.DecodeString(hexkey) - if byteErr, ok := err.(hex.InvalidByteError); ok { - return nil, fmt.Errorf("invalid hex character %q in private key", byte(byteErr)) - } else if err != nil { - return nil, errors.New("invalid hex data for private key") - } - return ToECDSA(b) -} - -// LoadECDSA loads a secp256k1 private key from the given file. -func LoadECDSA(file string) (*ecdsa.PrivateKey, error) { - fd, err := os.Open(file) - if err != nil { - return nil, err - } - defer fd.Close() - - r := bufio.NewReader(fd) - buf := make([]byte, 64) - n, err := readASCII(buf, r) - if err != nil { - return nil, err - } else if n != len(buf) { - return nil, errors.New("key file too short, want 64 hex characters") - } - if err := checkKeyFileEnd(r); err != nil { - return nil, err - } - - return HexToECDSA(string(buf)) -} - -// readASCII reads into 'buf', stopping when the buffer is full or -// when a non-printable control character is encountered. -func readASCII(buf []byte, r *bufio.Reader) (n int, err error) { - for ; n < len(buf); n++ { - buf[n], err = r.ReadByte() - switch { - case err == io.EOF || buf[n] < '!': - return n, nil - case err != nil: - return n, err - } - } - return n, nil -} - -// checkKeyFileEnd skips over additional newlines at the end of a key file. -func checkKeyFileEnd(r *bufio.Reader) error { - for i := 0; ; i++ { - b, err := r.ReadByte() - switch { - case err == io.EOF: - return nil - case err != nil: - return err - case b != '\n' && b != '\r': - return fmt.Errorf("invalid character %q at end of key file", b) - case i >= 2: - return errors.New("key file too long, want 64 hex characters") - } - } -} - -// SaveECDSA saves a secp256k1 private key to the given file with -// restrictive permissions. The key data is saved hex-encoded. -func SaveECDSA(file string, key *ecdsa.PrivateKey) error { - k := hex.EncodeToString(FromECDSA(key)) - return os.WriteFile(file, []byte(k), 0600) -} - -// GenerateKey generates a new private key. -func GenerateKey() (*ecdsa.PrivateKey, error) { - return ecdsa.GenerateKey(S256(), rand.Reader) -} - -// ValidateSignatureValues verifies whether the signature values are valid with -// the given chain rules. The v value is assumed to be either 0 or 1. -func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool { - if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 { - return false - } - // reject upper range of s values (ECDSA malleability) - // see discussion in secp256k1/libsecp256k1/include/secp256k1.h - if homestead && s.Cmp(secp256k1halfN) > 0 { - return false - } - // Frontier: allow s to be in full N range - return r.Cmp(secp256k1N) < 0 && s.Cmp(secp256k1N) < 0 && (v == 0 || v == 1) -} - -func PubkeyToAddress(p ecdsa.PublicKey) common.Address { - pubBytes := FromECDSAPub(&p) - return common.BytesToAddress(Keccak256(pubBytes[1:])[12:]) -} - -func zeroBytes(bytes []byte) { - for i := range bytes { - bytes[i] = 0 - } -} diff --git a/builder/crypto/crypto_test.go b/builder/crypto/crypto_test.go deleted file mode 100644 index da123cf98..000000000 --- a/builder/crypto/crypto_test.go +++ /dev/null @@ -1,299 +0,0 @@ -// 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 crypto - -import ( - "bytes" - "crypto/ecdsa" - "encoding/hex" - "math/big" - "os" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791" -var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" - -// These tests are sanity checks. -// They should ensure that we don't e.g. use Sha3-224 instead of Sha3-256 -// and that the sha3 library uses keccak-f permutation. -func TestKeccak256Hash(t *testing.T) { - msg := []byte("abc") - exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") - checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp) -} - -func TestKeccak256Hasher(t *testing.T) { - msg := []byte("abc") - exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") - hasher := NewKeccakState() - checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := HashData(hasher, in); return h[:] }, msg, exp) -} - -func TestToECDSAErrors(t *testing.T) { - if _, err := HexToECDSA("0000000000000000000000000000000000000000000000000000000000000000"); err == nil { - t.Fatal("HexToECDSA should've returned error") - } - if _, err := HexToECDSA("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); err == nil { - t.Fatal("HexToECDSA should've returned error") - } -} - -func BenchmarkSha3(b *testing.B) { - a := []byte("hello world") - for i := 0; i < b.N; i++ { - Keccak256(a) - } -} - -func TestUnmarshalPubkey(t *testing.T) { - key, err := UnmarshalPubkey(nil) - if err != errInvalidPubkey || key != nil { - t.Fatalf("expected error, got %v, %v", err, key) - } - key, err = UnmarshalPubkey([]byte{1, 2, 3}) - if err != errInvalidPubkey || key != nil { - t.Fatalf("expected error, got %v, %v", err, key) - } - - var ( - enc, _ = hex.DecodeString("04760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1b01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d") - dec = &ecdsa.PublicKey{ - Curve: S256(), - X: hexutil.MustDecodeBig("0x760c4460e5336ac9bbd87952a3c7ec4363fc0a97bd31c86430806e287b437fd1"), - Y: hexutil.MustDecodeBig("0xb01abc6e1db640cf3106b520344af1d58b00b57823db3e1407cbc433e1b6d04d"), - } - ) - key, err = UnmarshalPubkey(enc) - if err != nil { - t.Fatalf("expected no error, got %v", err) - } - if !reflect.DeepEqual(key, dec) { - t.Fatal("wrong result") - } -} - -func TestSign(t *testing.T) { - key, _ := HexToECDSA(testPrivHex) - addr := common.HexToAddress(testAddrHex) - - msg := Keccak256([]byte("foo")) - sig, err := Sign(msg, key) - if err != nil { - t.Errorf("Sign error: %s", err) - } - recoveredPub, err := Ecrecover(msg, sig) - if err != nil { - t.Errorf("ECRecover error: %s", err) - } - pubKey, _ := UnmarshalPubkey(recoveredPub) - recoveredAddr := PubkeyToAddress(*pubKey) - if addr != recoveredAddr { - t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr) - } - - // should be equal to SigToPub - recoveredPub2, err := SigToPub(msg, sig) - if err != nil { - t.Errorf("ECRecover error: %s", err) - } - recoveredAddr2 := PubkeyToAddress(*recoveredPub2) - if addr != recoveredAddr2 { - t.Errorf("Address mismatch: want: %x have: %x", addr, recoveredAddr2) - } -} - -func TestInvalidSign(t *testing.T) { - if _, err := Sign(make([]byte, 1), nil); err == nil { - t.Errorf("expected sign with hash 1 byte to error") - } - if _, err := Sign(make([]byte, 33), nil); err == nil { - t.Errorf("expected sign with hash 33 byte to error") - } -} - -func TestNewContractAddress(t *testing.T) { - key, _ := HexToECDSA(testPrivHex) - addr := common.HexToAddress(testAddrHex) - genAddr := PubkeyToAddress(key.PublicKey) - // sanity check before using addr to create contract address - checkAddr(t, genAddr, addr) - - caddr0 := CreateAddress(addr, 0) - caddr1 := CreateAddress(addr, 1) - caddr2 := CreateAddress(addr, 2) - checkAddr(t, common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d"), caddr0) - checkAddr(t, common.HexToAddress("8bda78331c916a08481428e4b07c96d3e916d165"), caddr1) - checkAddr(t, common.HexToAddress("c9ddedf451bc62ce88bf9292afb13df35b670699"), caddr2) -} - -func TestLoadECDSA(t *testing.T) { - tests := []struct { - input string - err string - }{ - // good - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n"}, - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"}, - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\r\n"}, - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n"}, - {input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\r"}, - // bad - { - input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde", - err: "key file too short, want 64 hex characters", - }, - { - input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde\n", - err: "key file too short, want 64 hex characters", - }, - { - input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdeX", - err: "invalid hex character 'X' in private key", - }, - { - input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefX", - err: "invalid character 'X' at end of key file", - }, - { - input: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n\n\n", - err: "key file too long, want 64 hex characters", - }, - } - - for _, test := range tests { - f, err := os.CreateTemp("", "loadecdsa_test.*.txt") - if err != nil { - t.Fatal(err) - } - filename := f.Name() - f.WriteString(test.input) - f.Close() - - _, err = LoadECDSA(filename) - switch { - case err != nil && test.err == "": - t.Fatalf("unexpected error for input %q:\n %v", test.input, err) - case err != nil && err.Error() != test.err: - t.Fatalf("wrong error for input %q:\n %v", test.input, err) - case err == nil && test.err != "": - t.Fatalf("LoadECDSA did not return error for input %q", test.input) - } - } -} - -func TestSaveECDSA(t *testing.T) { - f, err := os.CreateTemp("", "saveecdsa_test.*.txt") - if err != nil { - t.Fatal(err) - } - file := f.Name() - f.Close() - defer os.Remove(file) - - key, _ := HexToECDSA(testPrivHex) - if err := SaveECDSA(file, key); err != nil { - t.Fatal(err) - } - loaded, err := LoadECDSA(file) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(key, loaded) { - t.Fatal("loaded key not equal to saved key") - } -} - -func TestValidateSignatureValues(t *testing.T) { - check := func(expected bool, v byte, r, s *big.Int) { - if ValidateSignatureValues(v, r, s, false) != expected { - t.Errorf("mismatch for v: %d r: %d s: %d want: %v", v, r, s, expected) - } - } - minusOne := big.NewInt(-1) - one := common.Big1 - zero := common.Big0 - secp256k1nMinus1 := new(big.Int).Sub(secp256k1N, common.Big1) - - // correct v,r,s - check(true, 0, one, one) - check(true, 1, one, one) - // incorrect v, correct r,s, - check(false, 2, one, one) - check(false, 3, one, one) - - // incorrect v, combinations of incorrect/correct r,s at lower limit - check(false, 2, zero, zero) - check(false, 2, zero, one) - check(false, 2, one, zero) - check(false, 2, one, one) - - // correct v for any combination of incorrect r,s - check(false, 0, zero, zero) - check(false, 0, zero, one) - check(false, 0, one, zero) - - check(false, 1, zero, zero) - check(false, 1, zero, one) - check(false, 1, one, zero) - - // correct sig with max r,s - check(true, 0, secp256k1nMinus1, secp256k1nMinus1) - // correct v, combinations of incorrect r,s at upper limit - check(false, 0, secp256k1N, secp256k1nMinus1) - check(false, 0, secp256k1nMinus1, secp256k1N) - check(false, 0, secp256k1N, secp256k1N) - - // current callers ensures r,s cannot be negative, but let's test for that too - // as crypto package could be used stand-alone - check(false, 0, minusOne, one) - check(false, 0, one, minusOne) -} - -func checkhash(t *testing.T, name string, f func([]byte) []byte, msg, exp []byte) { - sum := f(msg) - if !bytes.Equal(exp, sum) { - t.Fatalf("hash %s mismatch: want: %x have: %x", name, exp, sum) - } -} - -func checkAddr(t *testing.T, addr0, addr1 common.Address) { - if addr0 != addr1 { - t.Fatalf("address mismatch: want: %x have: %x", addr0, addr1) - } -} - -// test to help Python team with integration of libsecp256k1 -// skip but keep it after they are done -func TestPythonIntegration(t *testing.T) { - kh := "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032" - k0, _ := HexToECDSA(kh) - - msg0 := Keccak256([]byte("foo")) - sig0, _ := Sign(msg0, k0) - - msg1 := common.FromHex("00000000000000000000000000000000") - sig1, _ := Sign(msg0, k0) - - t.Logf("msg: %x, privkey: %s sig: %x\n", msg0, kh, sig0) - t.Logf("msg: %x, privkey: %s sig: %x\n", msg1, kh, sig1) -} diff --git a/builder/crypto/ecies/.gitignore b/builder/crypto/ecies/.gitignore deleted file mode 100644 index 802b6744a..000000000 --- a/builder/crypto/ecies/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -*~ diff --git a/builder/crypto/ecies/LICENSE b/builder/crypto/ecies/LICENSE deleted file mode 100644 index e1ed19a27..000000000 --- a/builder/crypto/ecies/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2013 Kyle Isom -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/builder/crypto/ecies/README b/builder/crypto/ecies/README deleted file mode 100644 index 2650c7b9f..000000000 --- a/builder/crypto/ecies/README +++ /dev/null @@ -1,94 +0,0 @@ -# NOTE - -This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications. -Please be aware this code **has not yet been reviewed**. - -ecies implements the Elliptic Curve Integrated Encryption Scheme. - -The package is designed to be compliant with the appropriate NIST -standards, and therefore doesn't support the full SEC 1 algorithm set. - - -STATUS: - -ecies should be ready for use. The ASN.1 support is only complete so -far as to supported the listed algorithms before. - - -CAVEATS - -1. CMAC support is currently not present. - - -SUPPORTED ALGORITHMS - - SYMMETRIC CIPHERS HASH FUNCTIONS - AES128 SHA-1 - AES192 SHA-224 - AES256 SHA-256 - SHA-384 - ELLIPTIC CURVE SHA-512 - P256 - P384 KEY DERIVATION FUNCTION - P521 NIST SP 800-65a Concatenation KDF - -Curve P224 isn't supported because it does not provide a minimum security -level of AES128 with HMAC-SHA1. According to NIST SP 800-57, the security -level of P224 is 112 bits of security. Symmetric ciphers use CTR-mode; -message tags are computed using HMAC- function. - - -CURVE SELECTION - -According to NIST SP 800-57, the following curves should be selected: - - +----------------+-------+ - | SYMMETRIC SIZE | CURVE | - +----------------+-------+ - | 128-bit | P256 | - +----------------+-------+ - | 192-bit | P384 | - +----------------+-------+ - | 256-bit | P521 | - +----------------+-------+ - - -TODO - -1. Look at serialising the parameters with the SEC 1 ASN.1 module. -2. Validate ASN.1 formats with SEC 1. - - -TEST VECTORS - -The only test vectors I've found so far date from 1993, predating AES -and including only 163-bit curves. Therefore, there are no published -test vectors to compare to. - - -LICENSE - -ecies is released under the same license as the Go source code. See the -LICENSE file for details. - - -REFERENCES - -* SEC (Standard for Efficient Cryptography) 1, version 2.0: Elliptic - Curve Cryptography; Certicom, May 2009. - http://www.secg.org/sec1-v2.pdf -* GEC (Guidelines for Efficient Cryptography) 2, version 0.3: Test - Vectors for SEC 1; Certicom, September 1999. - http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf -* NIST SP 800-56a: Recommendation for Pair-Wise Key Establishment Schemes - Using Discrete Logarithm Cryptography. National Institute of Standards - and Technology, May 2007. - http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf -* Suite B Implementer’s Guide to NIST SP 800-56A. National Security - Agency, July 28, 2009. - http://www.nsa.gov/ia/_files/SuiteB_Implementer_G-113808.pdf -* NIST SP 800-57: Recommendation for Key Management – Part 1: General - (Revision 3). National Institute of Standards and Technology, July - 2012. - http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf - diff --git a/builder/crypto/ecies/ecies.go b/builder/crypto/ecies/ecies.go deleted file mode 100644 index 738bb8f58..000000000 --- a/builder/crypto/ecies/ecies.go +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2013 Kyle Isom -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ecies - -import ( - "crypto/cipher" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/hmac" - "crypto/subtle" - "encoding/binary" - "errors" - "hash" - "io" - "math/big" -) - -var ( - ErrImport = errors.New("ecies: failed to import key") - ErrInvalidCurve = errors.New("ecies: invalid elliptic curve") - ErrInvalidPublicKey = errors.New("ecies: invalid public key") - ErrSharedKeyIsPointAtInfinity = errors.New("ecies: shared key is point at infinity") - ErrSharedKeyTooBig = errors.New("ecies: shared key params are too big") -) - -// PublicKey is a representation of an elliptic curve public key. -type PublicKey struct { - X *big.Int - Y *big.Int - elliptic.Curve - Params *ECIESParams -} - -// Export an ECIES public key as an ECDSA public key. -func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { - return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} -} - -// Import an ECDSA public key as an ECIES public key. -func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { - return &PublicKey{ - X: pub.X, - Y: pub.Y, - Curve: pub.Curve, - Params: ParamsFromCurve(pub.Curve), - } -} - -// PrivateKey is a representation of an elliptic curve private key. -type PrivateKey struct { - PublicKey - D *big.Int -} - -// Export an ECIES private key as an ECDSA private key. -func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { - pub := &prv.PublicKey - pubECDSA := pub.ExportECDSA() - return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} -} - -// Import an ECDSA private key as an ECIES private key. -func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { - pub := ImportECDSAPublic(&prv.PublicKey) - return &PrivateKey{*pub, prv.D} -} - -// Generate an elliptic curve public / private keypair. If params is nil, -// the recommended default parameters for the key will be chosen. -func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { - pb, x, y, err := elliptic.GenerateKey(curve, rand) - if err != nil { - return - } - prv = new(PrivateKey) - prv.PublicKey.X = x - prv.PublicKey.Y = y - prv.PublicKey.Curve = curve - prv.D = new(big.Int).SetBytes(pb) - if params == nil { - params = ParamsFromCurve(curve) - } - prv.PublicKey.Params = params - return -} - -// MaxSharedKeyLength returns the maximum length of the shared key the -// public key can produce. -func MaxSharedKeyLength(pub *PublicKey) int { - return (pub.Curve.Params().BitSize + 7) / 8 -} - -// ECDH key agreement method used to establish secret keys for encryption. -func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { - if prv.PublicKey.Curve != pub.Curve { - return nil, ErrInvalidCurve - } - if skLen+macLen > MaxSharedKeyLength(pub) { - return nil, ErrSharedKeyTooBig - } - - x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes()) - if x == nil { - return nil, ErrSharedKeyIsPointAtInfinity - } - - sk = make([]byte, skLen+macLen) - skBytes := x.Bytes() - copy(sk[len(sk)-len(skBytes):], skBytes) - return sk, nil -} - -var ( - ErrSharedTooLong = errors.New("ecies: shared secret is too long") - ErrInvalidMessage = errors.New("ecies: invalid message") -) - -// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). -func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) []byte { - counterBytes := make([]byte, 4) - k := make([]byte, 0, roundup(kdLen, hash.Size())) - for counter := uint32(1); len(k) < kdLen; counter++ { - binary.BigEndian.PutUint32(counterBytes, counter) - hash.Reset() - hash.Write(counterBytes) - hash.Write(z) - hash.Write(s1) - k = hash.Sum(k) - } - return k[:kdLen] -} - -// roundup rounds size up to the next multiple of blocksize. -func roundup(size, blocksize int) int { - return size + blocksize - (size % blocksize) -} - -// deriveKeys creates the encryption and MAC keys using concatKDF. -func deriveKeys(hash hash.Hash, z, s1 []byte, keyLen int) (Ke, Km []byte) { - K := concatKDF(hash, z, s1, 2*keyLen) - Ke = K[:keyLen] - Km = K[keyLen:] - hash.Reset() - hash.Write(Km) - Km = hash.Sum(Km[:0]) - return Ke, Km -} - -// messageTag computes the MAC of a message (called the tag) as per -// SEC 1, 3.5. -func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { - mac := hmac.New(hash, km) - mac.Write(msg) - mac.Write(shared) - tag := mac.Sum(nil) - return tag -} - -// Generate an initialisation vector for CTR mode. -func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { - iv = make([]byte, params.BlockSize) - _, err = io.ReadFull(rand, iv) - return -} - -// symEncrypt carries out CTR encryption using the block cipher specified in the -func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { - c, err := params.Cipher(key) - if err != nil { - return - } - - iv, err := generateIV(params, rand) - if err != nil { - return - } - ctr := cipher.NewCTR(c, iv) - - ct = make([]byte, len(m)+params.BlockSize) - copy(ct, iv) - ctr.XORKeyStream(ct[params.BlockSize:], m) - return -} - -// symDecrypt carries out CTR decryption using the block cipher specified in -// the parameters -func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { - c, err := params.Cipher(key) - if err != nil { - return - } - - ctr := cipher.NewCTR(c, ct[:params.BlockSize]) - - m = make([]byte, len(ct)-params.BlockSize) - ctr.XORKeyStream(m, ct[params.BlockSize:]) - return -} - -// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. -// -// s1 and s2 contain shared information that is not part of the resulting -// ciphertext. s1 is fed into key derivation, s2 is fed into the MAC. If the -// shared information parameters aren't being used, they should be nil. -func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { - params, err := pubkeyParams(pub) - if err != nil { - return nil, err - } - - R, err := GenerateKey(rand, pub.Curve, params) - if err != nil { - return nil, err - } - - z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) - if err != nil { - return nil, err - } - - hash := params.Hash() - Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) - - em, err := symEncrypt(rand, params, Ke, m) - if err != nil || len(em) <= params.BlockSize { - return nil, err - } - - d := messageTag(params.Hash, Km, em, s2) - - Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) - ct = make([]byte, len(Rb)+len(em)+len(d)) - copy(ct, Rb) - copy(ct[len(Rb):], em) - copy(ct[len(Rb)+len(em):], d) - return ct, nil -} - -// Decrypt decrypts an ECIES ciphertext. -func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { - if len(c) == 0 { - return nil, ErrInvalidMessage - } - params, err := pubkeyParams(&prv.PublicKey) - if err != nil { - return nil, err - } - - hash := params.Hash() - - var ( - rLen int - hLen int = hash.Size() - mStart int - mEnd int - ) - - switch c[0] { - case 2, 3, 4: - rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4 - if len(c) < (rLen + hLen + 1) { - return nil, ErrInvalidMessage - } - default: - return nil, ErrInvalidPublicKey - } - - mStart = rLen - mEnd = len(c) - hLen - - R := new(PublicKey) - R.Curve = prv.PublicKey.Curve - R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) - if R.X == nil { - return nil, ErrInvalidPublicKey - } - - z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) - if err != nil { - return nil, err - } - Ke, Km := deriveKeys(hash, z, s1, params.KeyLen) - - d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) - if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { - return nil, ErrInvalidMessage - } - - return symDecrypt(params, Ke, c[mStart:mEnd]) -} diff --git a/builder/crypto/ecies/ecies_test.go b/builder/crypto/ecies/ecies_test.go deleted file mode 100644 index e3da71010..000000000 --- a/builder/crypto/ecies/ecies_test.go +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) 2013 Kyle Isom -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ecies - -import ( - "bytes" - "crypto/elliptic" - "crypto/rand" - "crypto/sha256" - "encoding/hex" - "errors" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/crypto" -) - -func TestKDF(t *testing.T) { - tests := []struct { - length int - output []byte - }{ - {6, decode("858b192fa2ed")}, - {32, decode("858b192fa2ed4395e2bf88dd8d5770d67dc284ee539f12da8bceaa45d06ebae0")}, - {48, decode("858b192fa2ed4395e2bf88dd8d5770d67dc284ee539f12da8bceaa45d06ebae0700f1ab918a5f0413b8140f9940d6955")}, - {64, decode("858b192fa2ed4395e2bf88dd8d5770d67dc284ee539f12da8bceaa45d06ebae0700f1ab918a5f0413b8140f9940d6955f3467fd6672cce1024c5b1effccc0f61")}, - } - - for _, test := range tests { - h := sha256.New() - k := concatKDF(h, []byte("input"), nil, test.length) - if !bytes.Equal(k, test.output) { - t.Fatalf("KDF: generated key %x does not match expected output %x", k, test.output) - } - } -} - -var ErrBadSharedKeys = errors.New("ecies: shared keys don't match") - -// cmpParams compares a set of ECIES parameters. We assume, as per the -// docs, that AES is the only supported symmetric encryption algorithm. -func cmpParams(p1, p2 *ECIESParams) bool { - return p1.hashAlgo == p2.hashAlgo && - p1.KeyLen == p2.KeyLen && - p1.BlockSize == p2.BlockSize -} - -// Validate the ECDH component. -func TestSharedKey(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) - if err != nil { - t.Fatal(err) - } - - sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(sk1, sk2) { - t.Fatal(ErrBadSharedKeys) - } -} - -func TestSharedKeyPadding(t *testing.T) { - // sanity checks - prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9") - prv1 := hexKey("0097a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a") - x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16) - x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16) - y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16) - y1, _ := new(big.Int).SetString("8ad915f2b503a8be6facab6588731fefeb584fd2dfa9a77a5e0bba1ec439e4fa", 16) - - if prv0.PublicKey.X.Cmp(x0) != 0 { - t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0.PublicKey.X.Bytes(), x0.Bytes()) - } - if prv0.PublicKey.Y.Cmp(y0) != 0 { - t.Errorf("mismatched prv0.Y:\nhave: %x\nwant: %x\n", prv0.PublicKey.Y.Bytes(), y0.Bytes()) - } - if prv1.PublicKey.X.Cmp(x1) != 0 { - t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1.PublicKey.X.Bytes(), x1.Bytes()) - } - if prv1.PublicKey.Y.Cmp(y1) != 0 { - t.Errorf("mismatched prv1.Y:\nhave: %x\nwant: %x\n", prv1.PublicKey.Y.Bytes(), y1.Bytes()) - } - - // test shared secret generation - sk1, err := prv0.GenerateShared(&prv1.PublicKey, 16, 16) - if err != nil { - t.Log(err.Error()) - } - - sk2, err := prv1.GenerateShared(&prv0.PublicKey, 16, 16) - if err != nil { - t.Fatal(err.Error()) - } - - if !bytes.Equal(sk1, sk2) { - t.Fatal(ErrBadSharedKeys.Error()) - } -} - -// Verify that the key generation code fails when too much key data is -// requested. -func TestTooBigSharedKey(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - _, err = prv1.GenerateShared(&prv2.PublicKey, 32, 32) - if err != ErrSharedKeyTooBig { - t.Fatal("ecdh: shared key should be too large for curve") - } - - _, err = prv2.GenerateShared(&prv1.PublicKey, 32, 32) - if err != ErrSharedKeyTooBig { - t.Fatal("ecdh: shared key should be too large for curve") - } -} - -// Benchmark the generation of P256 keys. -func BenchmarkGenerateKeyP256(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := GenerateKey(rand.Reader, elliptic.P256(), nil); err != nil { - b.Fatal(err) - } - } -} - -// Benchmark the generation of P256 shared keys. -func BenchmarkGenSharedKeyP256(b *testing.B) { - prv, err := GenerateKey(rand.Reader, elliptic.P256(), nil) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) - if err != nil { - b.Fatal(err) - } - } -} - -// Benchmark the generation of S256 shared keys. -func BenchmarkGenSharedKeyS256(b *testing.B) { - prv, err := GenerateKey(rand.Reader, crypto.S256(), nil) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := prv.GenerateShared(&prv.PublicKey, 16, 16) - if err != nil { - b.Fatal(err) - } - } -} - -// Verify that an encrypted message can be successfully decrypted. -func TestEncryptDecrypt(t *testing.T) { - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) - if err != nil { - t.Fatal(err) - } - - pt, err := prv2.Decrypt(ct, nil, nil) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(pt, message) { - t.Fatal("ecies: plaintext doesn't match message") - } - - _, err = prv1.Decrypt(ct, nil, nil) - if err == nil { - t.Fatal("ecies: encryption should not have succeeded") - } -} - -func TestDecryptShared2(t *testing.T) { - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - message := []byte("Hello, world.") - shared2 := []byte("shared data 2") - ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, shared2) - if err != nil { - t.Fatal(err) - } - - // Check that decrypting with correct shared data works. - pt, err := prv.Decrypt(ct, nil, shared2) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(pt, message) { - t.Fatal("ecies: plaintext doesn't match message") - } - - // Decrypting without shared data or incorrect shared data fails. - if _, err = prv.Decrypt(ct, nil, nil); err == nil { - t.Fatal("ecies: decrypting without shared data didn't fail") - } - if _, err = prv.Decrypt(ct, nil, []byte("garbage")); err == nil { - t.Fatal("ecies: decrypting with incorrect shared data didn't fail") - } -} - -type testCase struct { - Curve elliptic.Curve - Name string - Expected *ECIESParams -} - -var testCases = []testCase{ - { - Curve: elliptic.P256(), - Name: "P256", - Expected: ECIES_AES128_SHA256, - }, - { - Curve: elliptic.P384(), - Name: "P384", - Expected: ECIES_AES192_SHA384, - }, - { - Curve: elliptic.P521(), - Name: "P521", - Expected: ECIES_AES256_SHA512, - }, -} - -// Test parameter selection for each curve, and that P224 fails automatic -// parameter selection (see README for a discussion of P224). Ensures that -// selecting a set of parameters automatically for the given curve works. -func TestParamSelection(t *testing.T) { - for _, c := range testCases { - testParamSelection(t, c) - } -} - -func testParamSelection(t *testing.T, c testCase) { - params := ParamsFromCurve(c.Curve) - if params == nil { - t.Fatal("ParamsFromCurve returned nil") - } else if params != nil && !cmpParams(params, c.Expected) { - t.Fatalf("ecies: parameters should be invalid (%s)\n", c.Name) - } - - prv1, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatalf("%s (%s)\n", err.Error(), c.Name) - } - - prv2, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatalf("%s (%s)\n", err.Error(), c.Name) - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv2.PublicKey, message, nil, nil) - if err != nil { - t.Fatalf("%s (%s)\n", err.Error(), c.Name) - } - - pt, err := prv2.Decrypt(ct, nil, nil) - if err != nil { - t.Fatalf("%s (%s)\n", err.Error(), c.Name) - } - - if !bytes.Equal(pt, message) { - t.Fatalf("ecies: plaintext doesn't match message (%s)\n", c.Name) - } - - _, err = prv1.Decrypt(ct, nil, nil) - if err == nil { - t.Fatalf("ecies: encryption should not have succeeded (%s)\n", c.Name) - } -} - -// Ensure that the basic public key validation in the decryption operation -// works. -func TestBasicKeyValidation(t *testing.T) { - badBytes := []byte{0, 1, 5, 6, 7, 8, 9} - - prv, err := GenerateKey(rand.Reader, DefaultCurve, nil) - if err != nil { - t.Fatal(err) - } - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, &prv.PublicKey, message, nil, nil) - if err != nil { - t.Fatal(err) - } - - for _, b := range badBytes { - ct[0] = b - _, err := prv.Decrypt(ct, nil, nil) - if err != ErrInvalidPublicKey { - t.Fatal("ecies: validated an invalid key") - } - } -} - -func TestBox(t *testing.T) { - prv1 := hexKey("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f") - prv2 := hexKey("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a") - pub2 := &prv2.PublicKey - - message := []byte("Hello, world.") - ct, err := Encrypt(rand.Reader, pub2, message, nil, nil) - if err != nil { - t.Fatal(err) - } - - pt, err := prv2.Decrypt(ct, nil, nil) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(pt, message) { - t.Fatal("ecies: plaintext doesn't match message") - } - if _, err = prv1.Decrypt(ct, nil, nil); err == nil { - t.Fatal("ecies: encryption should not have succeeded") - } -} - -// Verify GenerateShared against static values - useful when -// debugging changes in underlying libs -func TestSharedKeyStatic(t *testing.T) { - prv1 := hexKey("7ebbc6a8358bc76dd73ebc557056702c8cfc34e5cfcd90eb83af0347575fd2ad") - prv2 := hexKey("6a3d6396903245bba5837752b9e0348874e72db0c4e11e9c485a81b4ea4353b9") - - skLen := MaxSharedKeyLength(&prv1.PublicKey) / 2 - - sk1, err := prv1.GenerateShared(&prv2.PublicKey, skLen, skLen) - if err != nil { - t.Fatal(err) - } - - sk2, err := prv2.GenerateShared(&prv1.PublicKey, skLen, skLen) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(sk1, sk2) { - t.Fatal(ErrBadSharedKeys) - } - - sk := decode("167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62") - if !bytes.Equal(sk1, sk) { - t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1) - } -} - -func hexKey(prv string) *PrivateKey { - key, err := crypto.HexToECDSA(prv) - if err != nil { - panic(err) - } - return ImportECDSA(key) -} - -func decode(s string) []byte { - bytes, err := hex.DecodeString(s) - if err != nil { - panic(err) - } - return bytes -} diff --git a/builder/crypto/ecies/params.go b/builder/crypto/ecies/params.go deleted file mode 100644 index df7698ea0..000000000 --- a/builder/crypto/ecies/params.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2013 Kyle Isom -// Copyright (c) 2012 The Go Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ecies - -// This file contains parameters for ECIES encryption, specifying the -// symmetric encryption and HMAC parameters. - -import ( - "crypto" - "crypto/aes" - "crypto/cipher" - "crypto/elliptic" - "crypto/sha256" - "crypto/sha512" - "errors" - "fmt" - "hash" - - ethcrypto "github.com/ethereum/go-ethereum/crypto" -) - -var ( - DefaultCurve = ethcrypto.S256() - ErrUnsupportedECDHAlgorithm = errors.New("ecies: unsupported ECDH algorithm") - ErrUnsupportedECIESParameters = errors.New("ecies: unsupported ECIES parameters") - ErrInvalidKeyLen = fmt.Errorf("ecies: invalid key size (> %d) in ECIESParams", maxKeyLen) -) - -// KeyLen is limited to prevent overflow of the counter -// in concatKDF. While the theoretical limit is much higher, -// no known cipher uses keys larger than 512 bytes. -const maxKeyLen = 512 - -type ECIESParams struct { - Hash func() hash.Hash // hash function - hashAlgo crypto.Hash - Cipher func([]byte) (cipher.Block, error) // symmetric cipher - BlockSize int // block size of symmetric cipher - KeyLen int // length of symmetric key -} - -// Standard ECIES parameters: -// * ECIES using AES128 and HMAC-SHA-256-16 -// * ECIES using AES256 and HMAC-SHA-256-32 -// * ECIES using AES256 and HMAC-SHA-384-48 -// * ECIES using AES256 and HMAC-SHA-512-64 - -var ( - ECIES_AES128_SHA256 = &ECIESParams{ - Hash: sha256.New, - hashAlgo: crypto.SHA256, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 16, - } - - ECIES_AES192_SHA384 = &ECIESParams{ - Hash: sha512.New384, - hashAlgo: crypto.SHA384, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 24, - } - - ECIES_AES256_SHA256 = &ECIESParams{ - Hash: sha256.New, - hashAlgo: crypto.SHA256, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } - - ECIES_AES256_SHA384 = &ECIESParams{ - Hash: sha512.New384, - hashAlgo: crypto.SHA384, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } - - ECIES_AES256_SHA512 = &ECIESParams{ - Hash: sha512.New, - hashAlgo: crypto.SHA512, - Cipher: aes.NewCipher, - BlockSize: aes.BlockSize, - KeyLen: 32, - } -) - -var paramsFromCurve = map[elliptic.Curve]*ECIESParams{ - ethcrypto.S256(): ECIES_AES128_SHA256, - elliptic.P256(): ECIES_AES128_SHA256, - elliptic.P384(): ECIES_AES192_SHA384, - elliptic.P521(): ECIES_AES256_SHA512, -} - -func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) { - paramsFromCurve[curve] = params -} - -// ParamsFromCurve selects parameters optimal for the selected elliptic curve. -// Only the curves P256, P384, and P512 are supported. -func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) { - return paramsFromCurve[curve] -} - -func pubkeyParams(key *PublicKey) (*ECIESParams, error) { - params := key.Params - if params == nil { - if params = ParamsFromCurve(key.Curve); params == nil { - return nil, ErrUnsupportedECIESParameters - } - } - if params.KeyLen > maxKeyLen { - return nil, ErrInvalidKeyLen - } - return params, nil -} diff --git a/builder/crypto/kzg4844/kzg4844.go b/builder/crypto/kzg4844/kzg4844.go deleted file mode 100644 index 52124df67..000000000 --- a/builder/crypto/kzg4844/kzg4844.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2023 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 kzg4844 implements the KZG crypto for EIP-4844. -package kzg4844 - -import ( - "embed" - "errors" - "hash" - "reflect" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -//go:embed trusted_setup.json -var content embed.FS - -var ( - blobT = reflect.TypeOf(Blob{}) - commitmentT = reflect.TypeOf(Commitment{}) - proofT = reflect.TypeOf(Proof{}) -) - -// Blob represents a 4844 data blob. -type Blob [131072]byte - -// UnmarshalJSON parses a blob in hex syntax. -func (b *Blob) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(blobT, input, b[:]) -} - -// MarshalText returns the hex representation of b. -func (b Blob) MarshalText() ([]byte, error) { - return hexutil.Bytes(b[:]).MarshalText() -} - -// Commitment is a serialized commitment to a polynomial. -type Commitment [48]byte - -// UnmarshalJSON parses a commitment in hex syntax. -func (c *Commitment) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(commitmentT, input, c[:]) -} - -// MarshalText returns the hex representation of c. -func (c Commitment) MarshalText() ([]byte, error) { - return hexutil.Bytes(c[:]).MarshalText() -} - -// Proof is a serialized commitment to the quotient polynomial. -type Proof [48]byte - -// UnmarshalJSON parses a proof in hex syntax. -func (p *Proof) UnmarshalJSON(input []byte) error { - return hexutil.UnmarshalFixedJSON(proofT, input, p[:]) -} - -// MarshalText returns the hex representation of p. -func (p Proof) MarshalText() ([]byte, error) { - return hexutil.Bytes(p[:]).MarshalText() -} - -// Point is a BLS field element. -type Point [32]byte - -// Claim is a claimed evaluation value in a specific point. -type Claim [32]byte - -// useCKZG controls whether the cryptography should use the Go or C backend. -var useCKZG atomic.Bool - -// UseCKZG can be called to switch the default Go implementation of KZG to the C -// library if fo some reason the user wishes to do so (e.g. consensus bug in one -// or the other). -func UseCKZG(use bool) error { - if use && !ckzgAvailable { - return errors.New("CKZG unavailable on your platform") - } - useCKZG.Store(use) - - // Initializing the library can take 2-4 seconds - and can potentially crash - // on CKZG and non-ADX CPUs - so might as well do it now and don't wait until - // a crypto operation is actually needed live. - if use { - ckzgIniter.Do(ckzgInit) - } else { - gokzgIniter.Do(gokzgInit) - } - return nil -} - -// BlobToCommitment creates a small commitment out of a data blob. -func BlobToCommitment(blob Blob) (Commitment, error) { - if useCKZG.Load() { - return ckzgBlobToCommitment(blob) - } - return gokzgBlobToCommitment(blob) -} - -// ComputeProof computes the KZG proof at the given point for the polynomial -// represented by the blob. -func ComputeProof(blob Blob, point Point) (Proof, Claim, error) { - if useCKZG.Load() { - return ckzgComputeProof(blob, point) - } - return gokzgComputeProof(blob, point) -} - -// VerifyProof verifies the KZG proof that the polynomial represented by the blob -// evaluated at the given point is the claimed value. -func VerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error { - if useCKZG.Load() { - return ckzgVerifyProof(commitment, point, claim, proof) - } - return gokzgVerifyProof(commitment, point, claim, proof) -} - -// ComputeBlobProof returns the KZG proof that is used to verify the blob against -// the commitment. -// -// This method does not verify that the commitment is correct with respect to blob. -func ComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) { - if useCKZG.Load() { - return ckzgComputeBlobProof(blob, commitment) - } - return gokzgComputeBlobProof(blob, commitment) -} - -// VerifyBlobProof verifies that the blob data corresponds to the provided commitment. -func VerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error { - if useCKZG.Load() { - return ckzgVerifyBlobProof(blob, commitment, proof) - } - return gokzgVerifyBlobProof(blob, commitment, proof) -} - -// CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment. -// The given hasher must be a sha256 hash instance, otherwise the result will be invalid! -func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) { - if hasher.Size() != 32 { - panic("wrong hash size") - } - hasher.Reset() - hasher.Write(commit[:]) - hasher.Sum(vh[:0]) - vh[0] = 0x01 // version - return vh -} - -// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash. -func IsValidVersionedHash(h []byte) bool { - return len(h) == 32 && h[0] == 0x01 -} diff --git a/builder/crypto/kzg4844/kzg4844_ckzg_cgo.go b/builder/crypto/kzg4844/kzg4844_ckzg_cgo.go deleted file mode 100644 index 540028569..000000000 --- a/builder/crypto/kzg4844/kzg4844_ckzg_cgo.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2023 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 . - -//go:build ckzg && !nacl && !js && cgo && !gofuzz - -package kzg4844 - -import ( - "encoding/json" - "errors" - "sync" - - gokzg4844 "github.com/crate-crypto/go-kzg-4844" - ckzg4844 "github.com/ethereum/c-kzg-4844/bindings/go" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// ckzgAvailable signals whether the library was compiled into Geth. -const ckzgAvailable = true - -// ckzgIniter ensures that we initialize the KZG library once before using it. -var ckzgIniter sync.Once - -// ckzgInit initializes the KZG library with the provided trusted setup. -func ckzgInit() { - config, err := content.ReadFile("trusted_setup.json") - if err != nil { - panic(err) - } - params := new(gokzg4844.JSONTrustedSetup) - if err = json.Unmarshal(config, params); err != nil { - panic(err) - } - if err = gokzg4844.CheckTrustedSetupIsWellFormed(params); err != nil { - panic(err) - } - g1s := make([]byte, len(params.SetupG1Lagrange)*(len(params.SetupG1Lagrange[0])-2)/2) - for i, g1 := range params.SetupG1Lagrange { - copy(g1s[i*(len(g1)-2)/2:], hexutil.MustDecode(g1)) - } - g2s := make([]byte, len(params.SetupG2)*(len(params.SetupG2[0])-2)/2) - for i, g2 := range params.SetupG2 { - copy(g2s[i*(len(g2)-2)/2:], hexutil.MustDecode(g2)) - } - if err = ckzg4844.LoadTrustedSetup(g1s, g2s); err != nil { - panic(err) - } -} - -// ckzgBlobToCommitment creates a small commitment out of a data blob. -func ckzgBlobToCommitment(blob Blob) (Commitment, error) { - ckzgIniter.Do(ckzgInit) - - commitment, err := ckzg4844.BlobToKZGCommitment((ckzg4844.Blob)(blob)) - if err != nil { - return Commitment{}, err - } - return (Commitment)(commitment), nil -} - -// ckzgComputeProof computes the KZG proof at the given point for the polynomial -// represented by the blob. -func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) { - ckzgIniter.Do(ckzgInit) - - proof, claim, err := ckzg4844.ComputeKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes32)(point)) - if err != nil { - return Proof{}, Claim{}, err - } - return (Proof)(proof), (Claim)(claim), nil -} - -// ckzgVerifyProof verifies the KZG proof that the polynomial represented by the blob -// evaluated at the given point is the claimed value. -func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error { - ckzgIniter.Do(ckzgInit) - - valid, err := ckzg4844.VerifyKZGProof((ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes32)(point), (ckzg4844.Bytes32)(claim), (ckzg4844.Bytes48)(proof)) - if err != nil { - return err - } - if !valid { - return errors.New("invalid proof") - } - return nil -} - -// ckzgComputeBlobProof returns the KZG proof that is used to verify the blob against -// the commitment. -// -// This method does not verify that the commitment is correct with respect to blob. -func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) { - ckzgIniter.Do(ckzgInit) - - proof, err := ckzg4844.ComputeBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment)) - if err != nil { - return Proof{}, err - } - return (Proof)(proof), nil -} - -// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment. -func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error { - ckzgIniter.Do(ckzgInit) - - valid, err := ckzg4844.VerifyBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes48)(proof)) - if err != nil { - return err - } - if !valid { - return errors.New("invalid proof") - } - return nil -} diff --git a/builder/crypto/kzg4844/kzg4844_ckzg_nocgo.go b/builder/crypto/kzg4844/kzg4844_ckzg_nocgo.go deleted file mode 100644 index ed840c75b..000000000 --- a/builder/crypto/kzg4844/kzg4844_ckzg_nocgo.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2023 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 . - -//go:build !ckzg || nacl || js || !cgo || gofuzz - -package kzg4844 - -import "sync" - -// ckzgAvailable signals whether the library was compiled into Geth. -const ckzgAvailable = false - -// ckzgIniter ensures that we initialize the KZG library once before using it. -var ckzgIniter sync.Once - -// ckzgInit initializes the KZG library with the provided trusted setup. -func ckzgInit() { - panic("unsupported platform") -} - -// ckzgBlobToCommitment creates a small commitment out of a data blob. -func ckzgBlobToCommitment(blob Blob) (Commitment, error) { - panic("unsupported platform") -} - -// ckzgComputeProof computes the KZG proof at the given point for the polynomial -// represented by the blob. -func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) { - panic("unsupported platform") -} - -// ckzgVerifyProof verifies the KZG proof that the polynomial represented by the blob -// evaluated at the given point is the claimed value. -func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error { - panic("unsupported platform") -} - -// ckzgComputeBlobProof returns the KZG proof that is used to verify the blob against -// the commitment. -// -// This method does not verify that the commitment is correct with respect to blob. -func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) { - panic("unsupported platform") -} - -// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment. -func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error { - panic("unsupported platform") -} diff --git a/builder/crypto/kzg4844/kzg4844_gokzg.go b/builder/crypto/kzg4844/kzg4844_gokzg.go deleted file mode 100644 index 3f03bb527..000000000 --- a/builder/crypto/kzg4844/kzg4844_gokzg.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2023 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 kzg4844 - -import ( - "encoding/json" - "sync" - - gokzg4844 "github.com/crate-crypto/go-kzg-4844" -) - -// context is the crypto primitive pre-seeded with the trusted setup parameters. -var context *gokzg4844.Context - -// gokzgIniter ensures that we initialize the KZG library once before using it. -var gokzgIniter sync.Once - -// gokzgInit initializes the KZG library with the provided trusted setup. -func gokzgInit() { - config, err := content.ReadFile("trusted_setup.json") - if err != nil { - panic(err) - } - params := new(gokzg4844.JSONTrustedSetup) - if err = json.Unmarshal(config, params); err != nil { - panic(err) - } - context, err = gokzg4844.NewContext4096(params) - if err != nil { - panic(err) - } -} - -// gokzgBlobToCommitment creates a small commitment out of a data blob. -func gokzgBlobToCommitment(blob Blob) (Commitment, error) { - gokzgIniter.Do(gokzgInit) - - commitment, err := context.BlobToKZGCommitment((gokzg4844.Blob)(blob), 0) - if err != nil { - return Commitment{}, err - } - return (Commitment)(commitment), nil -} - -// gokzgComputeProof computes the KZG proof at the given point for the polynomial -// represented by the blob. -func gokzgComputeProof(blob Blob, point Point) (Proof, Claim, error) { - gokzgIniter.Do(gokzgInit) - - proof, claim, err := context.ComputeKZGProof((gokzg4844.Blob)(blob), (gokzg4844.Scalar)(point), 0) - if err != nil { - return Proof{}, Claim{}, err - } - return (Proof)(proof), (Claim)(claim), nil -} - -// gokzgVerifyProof verifies the KZG proof that the polynomial represented by the blob -// evaluated at the given point is the claimed value. -func gokzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error { - gokzgIniter.Do(gokzgInit) - - return context.VerifyKZGProof((gokzg4844.KZGCommitment)(commitment), (gokzg4844.Scalar)(point), (gokzg4844.Scalar)(claim), (gokzg4844.KZGProof)(proof)) -} - -// gokzgComputeBlobProof returns the KZG proof that is used to verify the blob against -// the commitment. -// -// This method does not verify that the commitment is correct with respect to blob. -func gokzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) { - gokzgIniter.Do(gokzgInit) - - proof, err := context.ComputeBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), 0) - if err != nil { - return Proof{}, err - } - return (Proof)(proof), nil -} - -// gokzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment. -func gokzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error { - gokzgIniter.Do(gokzgInit) - - return context.VerifyBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), (gokzg4844.KZGProof)(proof)) -} diff --git a/builder/crypto/kzg4844/kzg4844_test.go b/builder/crypto/kzg4844/kzg4844_test.go deleted file mode 100644 index fae8a7a76..000000000 --- a/builder/crypto/kzg4844/kzg4844_test.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2023 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 kzg4844 - -import ( - "crypto/rand" - "testing" - - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - gokzg4844 "github.com/crate-crypto/go-kzg-4844" -) - -func randFieldElement() [32]byte { - bytes := make([]byte, 32) - _, err := rand.Read(bytes) - if err != nil { - panic("failed to get random field element") - } - var r fr.Element - r.SetBytes(bytes) - - return gokzg4844.SerializeScalar(r) -} - -func randBlob() Blob { - var blob Blob - for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize { - fieldElementBytes := randFieldElement() - copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:]) - } - return blob -} - -func TestCKZGWithPoint(t *testing.T) { testKZGWithPoint(t, true) } -func TestGoKZGWithPoint(t *testing.T) { testKZGWithPoint(t, false) } -func testKZGWithPoint(t *testing.T, ckzg bool) { - if ckzg && !ckzgAvailable { - t.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - blob := randBlob() - - commitment, err := BlobToCommitment(blob) - if err != nil { - t.Fatalf("failed to create KZG commitment from blob: %v", err) - } - point := randFieldElement() - proof, claim, err := ComputeProof(blob, point) - if err != nil { - t.Fatalf("failed to create KZG proof at point: %v", err) - } - if err := VerifyProof(commitment, point, claim, proof); err != nil { - t.Fatalf("failed to verify KZG proof at point: %v", err) - } -} - -func TestCKZGWithBlob(t *testing.T) { testKZGWithBlob(t, true) } -func TestGoKZGWithBlob(t *testing.T) { testKZGWithBlob(t, false) } -func testKZGWithBlob(t *testing.T, ckzg bool) { - if ckzg && !ckzgAvailable { - t.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - blob := randBlob() - - commitment, err := BlobToCommitment(blob) - if err != nil { - t.Fatalf("failed to create KZG commitment from blob: %v", err) - } - proof, err := ComputeBlobProof(blob, commitment) - if err != nil { - t.Fatalf("failed to create KZG proof for blob: %v", err) - } - if err := VerifyBlobProof(blob, commitment, proof); err != nil { - t.Fatalf("failed to verify KZG proof for blob: %v", err) - } -} - -func BenchmarkCKZGBlobToCommitment(b *testing.B) { benchmarkBlobToCommitment(b, true) } -func BenchmarkGoKZGBlobToCommitment(b *testing.B) { benchmarkBlobToCommitment(b, false) } -func benchmarkBlobToCommitment(b *testing.B, ckzg bool) { - if ckzg && !ckzgAvailable { - b.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - blob := randBlob() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - BlobToCommitment(blob) - } -} - -func BenchmarkCKZGComputeProof(b *testing.B) { benchmarkComputeProof(b, true) } -func BenchmarkGoKZGComputeProof(b *testing.B) { benchmarkComputeProof(b, false) } -func benchmarkComputeProof(b *testing.B, ckzg bool) { - if ckzg && !ckzgAvailable { - b.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - var ( - blob = randBlob() - point = randFieldElement() - ) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - ComputeProof(blob, point) - } -} - -func BenchmarkCKZGVerifyProof(b *testing.B) { benchmarkVerifyProof(b, true) } -func BenchmarkGoKZGVerifyProof(b *testing.B) { benchmarkVerifyProof(b, false) } -func benchmarkVerifyProof(b *testing.B, ckzg bool) { - if ckzg && !ckzgAvailable { - b.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - var ( - blob = randBlob() - point = randFieldElement() - commitment, _ = BlobToCommitment(blob) - proof, claim, _ = ComputeProof(blob, point) - ) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - VerifyProof(commitment, point, claim, proof) - } -} - -func BenchmarkCKZGComputeBlobProof(b *testing.B) { benchmarkComputeBlobProof(b, true) } -func BenchmarkGoKZGComputeBlobProof(b *testing.B) { benchmarkComputeBlobProof(b, false) } -func benchmarkComputeBlobProof(b *testing.B, ckzg bool) { - if ckzg && !ckzgAvailable { - b.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - var ( - blob = randBlob() - commitment, _ = BlobToCommitment(blob) - ) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - ComputeBlobProof(blob, commitment) - } -} - -func BenchmarkCKZGVerifyBlobProof(b *testing.B) { benchmarkVerifyBlobProof(b, true) } -func BenchmarkGoKZGVerifyBlobProof(b *testing.B) { benchmarkVerifyBlobProof(b, false) } -func benchmarkVerifyBlobProof(b *testing.B, ckzg bool) { - if ckzg && !ckzgAvailable { - b.Skip("CKZG unavailable in this test build") - } - defer func(old bool) { useCKZG.Store(old) }(useCKZG.Load()) - useCKZG.Store(ckzg) - - var ( - blob = randBlob() - commitment, _ = BlobToCommitment(blob) - proof, _ = ComputeBlobProof(blob, commitment) - ) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - VerifyBlobProof(blob, commitment, proof) - } -} diff --git a/builder/crypto/kzg4844/trusted_setup.json b/builder/crypto/kzg4844/trusted_setup.json deleted file mode 100644 index 08a2c413c..000000000 --- a/builder/crypto/kzg4844/trusted_setup.json +++ /dev/null @@ -1,4167 +0,0 @@ -{ - "g1_lagrange": [ - "0xa0413c0dcafec6dbc9f47d66785cf1e8c981044f7d13cfe3e4fcbb71b5408dfde6312493cb3c1d30516cb3ca88c03654", - "0x8b997fb25730d661918371bb41f2a6e899cac23f04fc5365800b75433c0a953250e15e7a98fb5ca5cc56a8cd34c20c57", - "0x83302852db89424d5699f3f157e79e91dc1380f8d5895c5a772bb4ea3a5928e7c26c07db6775203ce33e62a114adaa99", - "0xa759c48b7e4a685e735c01e5aa6ef9c248705001f470f9ad856cd87806983e917a8742a3bd5ee27db8d76080269b7c83", - "0x967f8dc45ebc3be14c8705f43249a30ff48e96205fb02ae28daeab47b72eb3f45df0625928582aa1eb4368381c33e127", - "0xa418eb1e9fb84cb32b370610f56f3cb470706a40ac5a47c411c464299c45c91f25b63ae3fcd623172aa0f273c0526c13", - "0x8f44e3f0387293bc7931e978165abbaed08f53acd72a0a23ac85f6da0091196b886233bcee5b4a194db02f3d5a9b3f78", - "0x97173434b336be73c89412a6d70d416e170ea355bf1956c32d464090b107c090ef2d4e1a467a5632fbc332eeb679bf2d", - "0xa24052ad8d55ad04bc5d951f78e14213435681594110fd18173482609d5019105b8045182d53ffce4fc29fc8810516c1", - "0xb950768136b260277590b5bec3f56bbc2f7a8bc383d44ce8600e85bf8cf19f479898bcc999d96dfbd2001ede01d94949", - "0x92ab8077871037bd3b57b95cbb9fb10eb11efde9191690dcac655356986fd02841d8fdb25396faa0feadfe3f50baf56d", - "0xa79b096dff98038ac30f91112dd14b78f8ad428268af36d20c292e2b3b6d9ed4fb28480bb04e465071cc67d05786b6d1", - "0xb9ff71461328f370ce68bf591aa7fb13027044f42a575517f3319e2be4aa4843fa281e756d0aa5645428d6dfa857cef2", - "0x8d765808c00b3543ff182e2d159c38ae174b12d1314da88ea08e13bd9d1c37184cb515e6bf6420531b5d41767987d7ce", - "0xb8c9a837d20c3b53e6f578e4a257bb7ef8fc43178614ec2a154915b267ad2be135981d01ed2ee1b5fbd9d9bb27f0800a", - "0xa9773d92cf23f65f98ef68f6cf95c72b53d0683af2f9bf886bb9036e4a38184b1131b26fd24397910b494fbef856f3aa", - "0xb41ebe38962d112da4a01bf101cb248d808fbd50aaf749fc7c151cf332032eb3e3bdbd716db899724b734d392f26c412", - "0x90fbb030167fb47dcc13d604a726c0339418567c1d287d1d87423fa0cb92eec3455fbb46bcbe2e697144a2d3972142e4", - "0xb11d298bd167464b35fb923520d14832bd9ed50ed841bf6d7618424fd6f3699190af21759e351b89142d355952149da1", - "0x8bc36066f69dc89f7c4d1e58d67497675050c6aa002244cebd9fc957ec5e364c46bab4735ea3db02b73b3ca43c96e019", - "0xab7ab92c5d4d773068e485aa5831941ebd63db7118674ca38089635f3b4186833af2455a6fb9ed2b745df53b3ce96727", - "0xaf191ca3089892cb943cd97cf11a51f38e38bd9be50844a4e8da99f27e305e876f9ed4ab0628e8ae3939066b7d34a15f", - "0xa3204c1747feabc2c11339a542195e7cb6628fd3964f846e71e2e3f2d6bb379a5e51700682ea1844eba12756adb13216", - "0x903a29883846b7c50c15968b20e30c471aeac07b872c40a4d19eb1a42da18b649d5bbfde4b4cf6225d215a461b0deb6d", - "0x8e6e9c15ffbf1e16e5865a5fef7ed751dc81957a9757b535cb38b649e1098cda25d42381dc4f776778573cdf90c3e6e0", - "0xa8f6dd26100b512a8c96c52e00715c4b2cb9ac457f17aed8ffe1cf1ea524068fe5a1ddf218149845fc1417b789ecfc98", - "0xa5b0ffc819451ea639cfd1c18cbc9365cc79368d3b2e736c0ae54eba2f0801e6eb0ee14a5f373f4a70ca463bdb696c09", - "0x879f91ccd56a1b9736fbfd20d8747354da743fb121f0e308a0d298ff0d9344431890e41da66b5009af3f442c636b4f43", - "0x81bf3a2d9755e206b515a508ac4d1109bf933c282a46a4ae4a1b4cb4a94e1d23642fad6bd452428845afa155742ade7e", - "0x8de778d4742f945df40004964e165592f9c6b1946263adcdd5a88b00244bda46c7bb49098c8eb6b3d97a0dd46148a8ca", - "0xb7a57b21d13121907ee28c5c1f80ee2e3e83a3135a8101e933cf57171209a96173ff5037f5af606e9fd6d066de6ed693", - "0xb0877d1963fd9200414a38753dffd9f23a10eb3198912790d7eddbc9f6b477019d52ddd4ebdcb9f60818db076938a5a9", - "0x88da2d7a6611bc16adc55fc1c377480c828aba4496c645e3efe0e1a67f333c05a0307f7f1d2df8ac013602c655c6e209", - "0x95719eb02e8a9dede1a888c656a778b1c69b7716fbe3d1538fe8afd4a1bc972183c7d32aa7d6073376f7701df80116d8", - "0x8e8a1ca971f2444b35af3376e85dccda3abb8e8e11d095d0a4c37628dfe5d3e043a377c3de68289ef142e4308e9941a0", - "0xb720caaff02f6d798ac84c4f527203e823ff685869e3943c979e388e1c34c3f77f5c242c6daa7e3b30e511aab917b866", - "0x86040d55809afeec10e315d1ad950d269d37cfee8c144cd8dd4126459e3b15a53b3e68df5981df3c2346d23c7b4baaf4", - "0x82d8cabf13ab853db0377504f0aec00dba3a5cd3119787e8ad378ddf2c40b022ecfc67c642b7acc8c1e3dd03ab50993e", - "0xb8d873927936719d2484cd03a6687d65697e17dcf4f0d5aed6f5e4750f52ef2133d4645894e7ebfc4ef6ce6788d404c8", - "0xb1235594dbb15b674a419ff2b2deb644ad2a93791ca05af402823f87114483d6aa1689b7a9bea0f547ad12fe270e4344", - "0xa53fda86571b0651f5affb74312551a082fffc0385cfd24c1d779985b72a5b1cf7c78b42b4f7e51e77055f8e5e915b00", - "0xb579adcfd9c6ef916a5a999e77a0cb21d378c4ea67e13b7c58709d5da23a56c2e54218691fc4ac39a4a3d74f88cc31f7", - "0xab79e584011713e8a2f583e483a91a0c2a40771b77d91475825b5acbea82db4262132901cb3e4a108c46d7c9ee217a4e", - "0xa0fe58ea9eb982d7654c8aaf9366230578fc1362f6faae0594f8b9e659bcb405dff4aac0c7888bbe07f614ecf0d800a6", - "0x867e50e74281f28ecd4925560e2e7a6f8911b135557b688254623acce0dbc41e23ac3e706a184a45d54c586edc416eb0", - "0x89f81b61adda20ea9d0b387a36d0ab073dc7c7cbff518501962038be19867042f11fcc7ff78096e5d3b68c6d8dc04d9b", - "0xa58ee91bb556d43cf01f1398c5811f76dc0f11efdd569eed9ef178b3b0715e122060ec8f945b4dbf6eebfa2b90af6fa6", - "0xac460be540f4c840def2eef19fc754a9af34608d107cbadb53334cf194cc91138d53b9538fcd0ec970b5d4aa455b224a", - "0xb09b91f929de52c09d48ca0893be6eb44e2f5210a6c394689dc1f7729d4be4e11d0474b178e80cea8c2ac0d081f0e811", - "0x8d37a442a76b06a02a4e64c2504aea72c8b9b020ab7bcc94580fe2b9603c7c50d7b1e9d70d2a7daea19c68667e8f8c31", - "0xa9838d4c4e3f3a0075a952cf7dd623307ec633fcc81a7cf9e52e66c31780de33dbb3d74c320dc7f0a4b72f7a49949515", - "0xa44766b6251af458fe4f5f9ed1e02950f35703520b8656f09fc42d9a2d38a700c11a7c8a0436ac2e5e9f053d0bb8ff91", - "0xad78d9481c840f5202546bea0d13c776826feb8b1b7c72e83d99a947622f0bf38a4208551c4c41beb1270d7792075457", - "0xb619ffa8733b470039451e224b777845021e8dc1125f247a4ff2476cc774657d0ff9c5279da841fc1236047de9d81c60", - "0xaf760b0a30a1d6af3bc5cd6686f396bd41779aeeb6e0d70a09349bd5da17ca2e7965afc5c8ec22744198fbe3f02fb331", - "0xa0cc209abdb768b589fcb7b376b6e1cac07743288c95a1cf1a0354b47f0cf91fca78a75c1fcafa6f5926d6c379116608", - "0x864add673c89c41c754eeb3cd8dcff5cdde1d739fce65c30e474a082bb5d813cba6412e61154ce88fdb6c12c5d9be35b", - "0xb091443b0ce279327dc37cb484e9a5b69b257a714ce21895d67539172f95ffa326903747b64a3649e99aea7bb10d03f7", - "0xa8c452b8c4ca8e0a61942a8e08e28f17fb0ef4c5b018b4e6d1a64038280afa2bf1169202f05f14af24a06ca72f448ccd", - "0xa23c24721d18bc48d5dcf70effcbef89a7ae24e67158d70ae1d8169ee75d9a051d34b14e9cf06488bac324fe58549f26", - "0x92a730e30eb5f3231feb85f6720489dbb1afd42c43f05a1610c6b3c67bb949ec8fde507e924498f4ffc646f7b07d9123", - "0x8dbe5abf4031ec9ba6bb06d1a47dd1121fb9e03b652804069250967fd5e9577d0039e233441b7f837a7c9d67ba18c28e", - "0xaa456bcfef6a21bb88181482b279df260297b3778e84594ebddbdf337e85d9e3d46ca1d0b516622fb0b103df8ec519b7", - "0xa3b31ae621bd210a2b767e0e6f22eb28fe3c4943498a7e91753225426168b9a26da0e02f1dc5264da53a5ad240d9f51b", - "0xaa8d66857127e6e71874ce2202923385a7d2818b84cb73a6c42d71afe70972a70c6bdd2aad1a6e8c5e4ca728382a8ea8", - "0xac7e8e7a82f439127a5e40558d90d17990f8229852d21c13d753c2e97facf077cf59582b603984c3dd3faebd80aff4f5", - "0x93a8bcf4159f455d1baa73d2ef2450dcd4100420de84169bbe28b8b7a5d1746273f870091a87a057e834f754f34204b1", - "0x89d0ebb287c3613cdcae7f5acc43f17f09c0213fc40c074660120b755d664109ffb9902ed981ede79e018ddb0c845698", - "0xa87ccbfad431406aadbee878d9cf7d91b13649d5f7e19938b7dfd32645a43b114eef64ff3a13201398bd9b0337832e5a", - "0x833c51d0d0048f70c3eefb4e70e4ff66d0809c41838e8d2c21c288dd3ae9d9dfaf26d1742bf4976dab83a2b381677011", - "0x8bcd6b1c3b02fffead432e8b1680bad0a1ac5a712d4225e220690ee18df3e7406e2769e1f309e2e803b850bc96f0e768", - "0xb61e3dbd88aaf4ff1401521781e2eea9ef8b66d1fac5387c83b1da9e65c2aa2a56c262dea9eceeb4ad86c90211672db0", - "0x866d3090db944ecf190dd0651abf67659caafd31ae861bab9992c1e3915cb0952da7c561cc7e203560a610f48fae633b", - "0xa5e8971543c14274a8dc892b0be188c1b4fbc75c692ed29f166e0ea80874bc5520c2791342b7c1d2fb5dd454b03b8a5b", - "0x8f2f9fc50471bae9ea87487ebd1bc8576ef844cc42d606af5c4c0969670fdf2189afd643e4de3145864e7773d215f37f", - "0xb1bb0f2527db6d51f42b9224383c0f96048bbc03d469bf01fe1383173ef8b1cc9455d9dd8ba04d46057f46949bfc92b5", - "0xaa7c99d906b4d7922296cfe2520473fc50137c03d68b7865c5bfb8adbc316b1034310ec4b5670c47295f4a80fb8d61e9", - "0xa5d1da4d6aba555919df44cbaa8ff79378a1c9e2cfdfbf9d39c63a4a00f284c5a5724e28ecbc2d9dba27fe4ee5018bd5", - "0xa8db53224f70af4d991b9aae4ffe92d2aa5b618ad9137784b55843e9f16cefbfd25ada355d308e9bbf55f6d2f7976fb3", - "0xb6536c4232bb20e22af1a8bb12de76d5fec2ad9a3b48af1f38fa67e0f8504ef60f305a73d19385095bb6a9603fe29889", - "0x87f7e371a1817a63d6838a8cf4ab3a8473d19ce0d4f40fd013c03d5ddd5f4985df2956531cc9f187928ef54c68f4f9a9", - "0xae13530b1dbc5e4dced9d909ea61286ec09e25c12f37a1ed2f309b0eb99863d236c3b25ed3484acc8c076ad2fa8cd430", - "0x98928d850247c6f7606190e687d5c94a627550198dbdbea0161ef9515eacdb1a0f195cae3bb293112179082daccf8b35", - "0x918528bb8e6a055ad4db6230d3a405e9e55866da15c4721f5ddd1f1f37962d4904aad7a419218fe6d906fe191a991806", - "0xb71e31a06afe065773dd3f4a6e9ef81c3292e27a3b7fdfdd452d03e05af3b6dd654c355f7516b2a93553360c6681a73a", - "0x8870b83ab78a98820866f91ac643af9f3ff792a2b7fda34185a9456a63abdce42bfe8ad4dc67f08a6392f250d4062df4", - "0x91eea1b668e52f7a7a5087fabf1cab803b0316f78d9fff469fbfde2162f660c250e4336a9eea4cb0450bd30ac067bc8b", - "0x8b74990946de7b72a92147ceac1bd9d55999a8b576e8df68639e40ed5dc2062cfcd727903133de482b6dca19d0aaed82", - "0x8ebad537fece090ebbab662bdf2618e21ca30cf6329c50935e8346d1217dcbe3c1fe1ea28efca369c6003ce0a94703c1", - "0xa8640479556fb59ebd1c40c5f368fbd960932fdbb782665e4a0e24e2bdb598fc0164ce8c0726d7759cfc59e60a62e182", - "0xa9a52a6bf98ee4d749f6d38be2c60a6d54b64d5cbe4e67266633dc096cf28c97fe998596707d31968cbe2064b72256bf", - "0x847953c48a4ce6032780e9b39d0ed4384e0be202c2bbe2dfda3910f5d87aa5cd3c2ffbfcfae4dddce16d6ab657599b95", - "0xb6f6e1485d3ec2a06abaecd23028b200b2e4a0096c16144d07403e1720ff8f9ba9d919016b5eb8dc5103880a7a77a1d3", - "0x98dfc2065b1622f596dbe27131ea60bef7a193b12922cecb27f8c571404f483014f8014572e86ae2e341ab738e4887ef", - "0xacb0d205566bacc87bbe2e25d10793f63f7a1f27fd9e58f4f653ceae3ffeba511eaf658e068fad289eeb28f9edbeb35b", - "0xae4411ed5b263673cee894c11fe4abc72a4bf642d94022a5c0f3369380fcdfc1c21e277f2902972252503f91ada3029a", - "0xac4a7a27ba390a75d0a247d93d4a8ef1f0485f8d373a4af4e1139369ec274b91b3464d9738eeaceb19cd6f509e2f8262", - "0x87379c3bf231fdafcf6472a79e9e55a938d851d4dd662ab6e0d95fd47a478ed99e2ad1e6e39be3c0fc4f6d996a7dd833", - "0x81316904b035a8bcc2041199a789a2e6879486ba9fddcba0a82c745cc8dd8374a39e523b91792170cd30be7aa3005b85", - "0xb8206809c6cd027ed019f472581b45f7e12288f89047928ba32b4856b6560ad30395830d71e5e30c556f6f182b1fe690", - "0x88d76c028f534a62e019b4a52967bb8642ede6becfa3807be68fdd36d366fc84a4ac8dc176e80a68bc59eb62caf5dff9", - "0x8c3b8be685b0f8aad131ee7544d0e12f223f08a6f8edaf464b385ac644e0ddc9eff7cc7cb5c1b50ab5d71ea0f41d2213", - "0x8d91410e004f76c50fdc05784157b4d839cb5090022c629c7c97a5e0c3536eeafee17a527b54b1165c3cd81774bb54ce", - "0xb25c2863bc28ec5281ce800ddf91a7e1a53f4c6d5da1e6c86ef4616e93bcf55ed49e297216d01379f5c6e7b3c1e46728", - "0x865f7b09ac3ca03f20be90c48f6975dd2588838c2536c7a3532a6aa5187ed0b709cd03d91ff4048061c10d0aa72b69ce", - "0xb3f7477c90c11596eb4f8bbf34adbcb832638c4ff3cdd090d4d477ee50472ac9ddaf5be9ad7eca3f148960d362bbd098", - "0x8db35fd53fca04faecd1c76a8227160b3ab46ac1af070f2492445a19d8ff7c25bbaef6c9fa0c8c088444561e9f7e4eb2", - "0xa478b6e9d058a2e01d2fc053b739092e113c23a6a2770a16afbef044a3709a9e32f425ace9ba7981325f02667c3f9609", - "0x98caa6bd38916c08cf221722a675a4f7577f33452623de801d2b3429595f988090907a7e99960fff7c076d6d8e877b31", - "0xb79aaaacefc49c3038a14d2ac468cfec8c2161e88bdae91798d63552cdbe39e0e02f9225717436b9b8a40a022c633c6e", - "0x845a31006c680ee6a0cc41d3dc6c0c95d833fcf426f2e7c573fa15b2c4c641fbd6fe5ebb0e23720cc3467d6ee1d80dc4", - "0xa1bc287e272cf8b74dbf6405b3a5190883195806aa351f1dc8e525aa342283f0a35ff687e3b434324dedee74946dd185", - "0xa4fd2dc8db75d3783a020856e2b3aa266dc6926e84f5c491ef739a3bddd46dc8e9e0fc1177937839ef1b18d062ffbb9e", - "0xacbf0d3c697f57c202bb8c5dc4f3fc341b8fc509a455d44bd86acc67cad2a04495d5537bcd3e98680185e8aa286f2587", - "0xa5caf423a917352e1b8e844f5968a6da4fdeae467d10c6f4bbd82b5eea46a660b82d2f5440d3641c717b2c3c9ed0be52", - "0x8a39d763c08b926599ab1233219c49c825368fad14d9afc7c0c039224d37c00d8743293fd21645bf0b91eaf579a99867", - "0xb2b53a496def0ba06e80b28f36530fbe0fb5d70a601a2f10722e59abee529369c1ae8fd0f2db9184dd4a2519bb832d94", - "0xa73980fcef053f1b60ebbb5d78ba6332a475e0b96a0c724741a3abf3b59dd344772527f07203cf4c9cb5155ebed81fa0", - "0xa070d20acce42518ece322c9db096f16aed620303a39d8d5735a0df6e70fbeceb940e8d9f5cc38f3314b2240394ec47b", - "0xa50cf591f522f19ca337b73089557f75929d9f645f3e57d4f241e14cdd1ea3fb48d84bcf05e4f0377afbb789fbdb5d20", - "0x82a5ffce451096aca8eeb0cd2ae9d83db3ed76da3f531a80d9a70a346359bf05d74863ce6a7c848522b526156a5e20cd", - "0x88e0e84d358cbb93755a906f329db1537c3894845f32b9b0b691c29cbb455373d9452fadd1e77e20a623f6eaf624de6f", - "0xaa07ac7b84a6d6838826e0b9e350d8ec75e398a52e9824e6b0da6ae4010e5943fec4f00239e96433f291fef9d1d1e609", - "0xac8887bf39366034bc63f6cc5db0c26fd27307cbc3d6cce47894a8a019c22dd51322fb5096edc018227edfafc053a8f6", - "0xb7d26c26c5b33f77422191dca94977588ab1d4b9ce7d0e19c4a3b4cd1c25211b78c328dbf81e755e78cd7d1d622ad23e", - "0x99a676d5af49f0ba44047009298d8474cabf2d5bca1a76ba21eff7ee3c4691a102fdefea27bc948ccad8894a658abd02", - "0xb0d09a91909ab3620c183bdf1d53d43d39eb750dc7a722c661c3de3a1a5d383ad221f71bae374f8a71867505958a3f76", - "0x84681a883de8e4b93d68ac10e91899c2bbb815ce2de74bb48a11a6113b2a3f4df8aceabda1f5f67bc5aacac8c9da7221", - "0x9470259957780fa9b43521fab3644f555f5343281c72582b56d2efd11991d897b3b481cafa48681c5aeb80c9663b68f7", - "0xab1b29f7ece686e6fa968a4815da1d64f3579fed3bc92e1f3e51cd13a3c076b6cf695ed269d373300a62463dc98a4234", - "0x8ab415bfcd5f1061f7687597024c96dd9c7cb4942b5989379a7a3b5742f7d394337886317659cbeacaf030234a24f972", - "0xb9b524aad924f9acc63d002d617488f31b0016e0f0548f050cada285ce7491b74a125621638f19e9c96eabb091d945be", - "0x8c4c373e79415061837dd0def4f28a2d5d74d21cb13a76c9049ad678ca40228405ab0c3941df49249847ecdefc1a5b78", - "0xa8edf4710b5ab2929d3db6c1c0e3e242261bbaa8bcec56908ddadd7d2dad2dca9d6eb9de630b960b122ebeea41040421", - "0x8d66bb3b50b9df8f373163629f9221b3d4b6980a05ea81dc3741bfe9519cf3ebba7ab98e98390bae475e8ede5821bd5c", - "0x8d3c21bae7f0cfb97c56952bb22084b58e7bb718890935b73103f33adf5e4d99cd262f929c6eeab96209814f0dbae50a", - "0xa5c66cfab3d9ebf733c4af24bebc97070e7989fe3c73e79ac85fb0e4d40ae44fb571e0fad4ad72560e13ed453900d14f", - "0x9362e6b50b43dbefbc3254471372297b5dcce809cd3b60bf74a1268ab68bdb50e46e462cbd78f0d6c056330e982846af", - "0x854630d08e3f0243d570cc2e856234cb4c1a158d9c1883bf028a76525aaa34be897fe918d5f6da9764a3735fa9ebd24a", - "0x8c7d246985469ff252c3f4df6c7c9196fc79f05c1c66a609d84725c78001d0837c7a7049394ba5cf7e863e2d58af8417", - "0xae050271e01b528925302e71903f785b782f7bf4e4e7a7f537140219bc352dc7540c657ed03d3a297ad36798ecdb98cd", - "0x8d2ae9179fcf2b0c69850554580b52c1f4a5bd865af5f3028f222f4acad9c1ad69a8ef6c7dc7b03715ee5c506b74325e", - "0xb8ef8de6ce6369a8851cd36db0ccf00a85077e816c14c4e601f533330af9e3acf0743a95d28962ed8bfcfc2520ef3cfe", - "0xa6ecad6fdfb851b40356a8b1060f38235407a0f2706e7b8bb4a13465ca3f81d4f5b99466ac2565c60af15f022d26732e", - "0x819ff14cdea3ab89d98e133cd2d0379361e2e2c67ad94eeddcdb9232efd509f51d12f4f03ebd4dd953bd262a886281f7", - "0x8561cd0f7a6dbcddd83fcd7f472d7dbcba95b2d4fb98276f48fccf69f76d284e626d7e41314b633352df8e6333fd52a1", - "0xb42557ccce32d9a894d538c48712cb3e212d06ac05cd5e0527ccd2db1078ee6ae399bf6a601ffdab1f5913d35fc0b20c", - "0x89b4008d767aad3c6f93c349d3b956e28307311a5b1cec237e8d74bb0dee7e972c24f347fd56afd915a2342bd7bc32f0", - "0x877487384b207e53f5492f4e36c832c2227f92d1bb60542cfeb35e025a4a7afc2b885fae2528b33b40ab09510398f83e", - "0x8c411050b63c9053dd0cd81dacb48753c3d7f162028098e024d17cd6348482703a69df31ad6256e3d25a8bbf7783de39", - "0xa8506b54a88d17ac10fb1b0d1fe4aa40eae7553a064863d7f6b52ccc4236dd4b82d01dca6ba87da9a239e3069ba879fb", - "0xb1a24caef9df64750c1350789bb8d8a0db0f39474a1c74ea9ba064b1516db6923f00af8d57c632d58844fb8786c3d47a", - "0x959d6e255f212b0708c58a2f75cb1fe932248c9d93424612c1b8d1e640149656059737e4db2139afd5556bcdacf3eda2", - "0x84525af21a8d78748680b6535bbc9dc2f0cf9a1d1740d12f382f6ecb2e73811d6c1da2ad9956070b1a617c61fcff9fe5", - "0xb74417d84597a485d0a8e1be07bf78f17ebb2e7b3521b748f73935b9afbbd82f34b710fb7749e7d4ab55b0c7f9de127d", - "0xa4a9aecb19a6bab167af96d8b9d9aa5308eab19e6bfb78f5a580f9bf89bdf250a7b52a09b75f715d651cb73febd08e84", - "0x9777b30be2c5ffe7d29cc2803a562a32fb43b59d8c3f05a707ab60ec05b28293716230a7d264d7cd9dd358fc031cc13e", - "0x95dce7a3d4f23ac0050c510999f5fbf8042f771e8f8f94192e17bcbfa213470802ebdbe33a876cb621cf42e275cbfc8b", - "0xb0b963ebcbbee847ab8ae740478544350b3ac7e86887e4dfb2299ee5096247cd2b03c1de74c774d9bde94ae2ee2dcd59", - "0xa4ab20bafa316030264e13f7ef5891a2c3b29ab62e1668fcb5881f50a9acac6adbe3d706c07e62f2539715db768f6c43", - "0x901478a297669d608e406fe4989be75264b6c8be12169aa9e0ad5234f459ca377f78484ffd2099a2fe2db5e457826427", - "0x88c76e5c250810c057004a03408b85cd918e0c8903dc55a0dd8bb9b4fc2b25c87f9b8cf5943eb19fbbe99d36490050c5", - "0x91607322bbad4a4f03fc0012d0821eff5f8c516fda45d1ec1133bface6f858bf04b25547be24159cab931a7aa08344d4", - "0x843203e07fce3c6c81f84bc6dc5fb5e9d1c50c8811ace522dc66e8658433a0ef9784c947e6a62c11bf705307ef05212e", - "0x91dd8813a5d6dddcda7b0f87f672b83198cd0959d8311b2b26fb1fae745185c01f796fbd03aad9db9b58482483fdadd8", - "0x8d15911aacf76c8bcd7136e958febd6963104addcd751ce5c06b6c37213f9c4fb0ffd4e0d12c8e40c36d658999724bfd", - "0x8a36c5732d3f1b497ebe9250610605ee62a78eaa9e1a45f329d09aaa1061131cf1d9df00f3a7d0fe8ad614a1ff9caaae", - "0xa407d06affae03660881ce20dab5e2d2d6cddc23cd09b95502a9181c465e57597841144cb34d22889902aff23a76d049", - "0xb5fd856d0578620a7e25674d9503be7d97a2222900e1b4738c1d81ff6483b144e19e46802e91161e246271f90270e6cf", - "0x91b7708869cdb5a7317f88c0312d103f8ce90be14fb4f219c2e074045a2a83636fdc3e69e862049fc7c1ef000e832541", - "0xb64719cc5480709d1dae958f1d3082b32a43376da446c8f9f64cb02a301effc9c34d9102051733315a8179aed94d53cc", - "0x94347a9542ff9d18f7d9eaa2f4d9b832d0e535fe49d52aa2de08aa8192400eddabdb6444a2a78883e27c779eed7fdf5a", - "0x840ef44a733ff1376466698cd26f82cf56bb44811e196340467f932efa3ae1ef9958a0701b3b032f50fd9c1d2aed9ab5", - "0x90ab3f6f67688888a31ffc2a882bb37adab32d1a4b278951a21646f90d03385fc976715fc639a785d015751171016f10", - "0xb56f35d164c24b557dbcbc8a4bfa681ec916f8741ffcb27fb389c164f4e3ed2be325210ef5bdaeae7a172ca9599ab442", - "0xa7921a5a80d7cf6ae81ba9ee05e0579b18c20cd2852762c89d6496aa4c8ca9d1ca2434a67b2c16d333ea8e382cdab1e3", - "0xa506bcfbd7e7e5a92f68a1bd87d07ad5fe3b97aeee40af2bf2cae4efcd77fff03f872732c5b7883aa6584bee65d6f8cb", - "0xa8c46cff58931a1ce9cbe1501e1da90b174cddd6d50f3dfdfb759d1d4ad4673c0a8feed6c1f24c7af32865a7d6c984e5", - "0xb45686265a83bff69e312c5149db7bb70ac3ec790dc92e392b54d9c85a656e2bf58596ce269f014a906eafc97461aa5f", - "0x8d4009a75ccb2f29f54a5f16684b93202c570d7a56ec1a8b20173269c5f7115894f210c26b41e8d54d4072de2d1c75d0", - "0xaef8810af4fc676bf84a0d57b189760ddc3375c64e982539107422e3de2580b89bd27aa6da44e827b56db1b5555e4ee8", - "0x888f0e1e4a34f48eb9a18ef4de334c27564d72f2cf8073e3d46d881853ac1424d79e88d8ddb251914890588937c8f711", - "0xb64b0aa7b3a8f6e0d4b3499fe54e751b8c3e946377c0d5a6dbb677be23736b86a7e8a6be022411601dd75012012c3555", - "0x8d57776f519f0dd912ea14f79fbab53a30624e102f9575c0bad08d2dc754e6be54f39b11278c290977d9b9c7c0e1e0ad", - "0xa018fc00d532ceb2e4de908a15606db9b6e0665dd77190e2338da7c87a1713e6b9b61554e7c1462f0f6d4934b960b15c", - "0x8c932be83ace46f65c78e145b384f58e41546dc0395270c1397874d88626fdeda395c8a289d602b4c312fe98c1311856", - "0x89174838e21639d6bdd91a0621f04dc056907b88e305dd66e46a08f6d65f731dea72ae87ca5e3042d609e8de8de9aa26", - "0xb7b7f508bb74f7a827ac8189daa855598ff1d96fa3a02394891fd105d8f0816224cd50ac4bf2ed1cf469ace516c48184", - "0xb31877ad682583283baadd68dc1bebd83f5748b165aadd7fe9ef61a343773b88bcd3a022f36d6c92f339b7bfd72820a9", - "0xb79d77260b25daf9126dab7a193df2d7d30542786fa1733ffaf6261734770275d3ca8bae1d9915d1181a78510b3439db", - "0x91894fb94cd4c1dd2ceaf9c53a7020c5799ba1217cf2d251ea5bc91ed26e1159dd758e98282ebe35a0395ef9f1ed15a0", - "0xab59895cdafd33934ceedfc3f0d5d89880482cba6c99a6db93245f9e41987efd76e0640e80aef31782c9a8c7a83fccec", - "0xaa22ea63654315e033e09d4d4432331904a6fc5fb1732557987846e3c564668ca67c60a324b4af01663a23af11a9ce4b", - "0xb53ba3ef342601467e1f71aa280e100fbabbd38518fa0193e0099505036ee517c1ac78e96e9baeb549bb6879bb698fb0", - "0x943fd69fd656f37487cca3605dc7e5a215fddd811caf228595ec428751fc1de484a0cb84c667fe4d7c35599bfa0e5e34", - "0x9353128b5ebe0dddc555093cf3e5942754f938173541033e8788d7331fafc56f68d9f97b4131e37963ab7f1c8946f5f1", - "0xa76cd3c566691f65cfb86453b5b31dbaf3cab8f84fe1f795dd1e570784b9b01bdd5f0b3c1e233942b1b5838290e00598", - "0x983d84b2e53ffa4ae7f3ba29ef2345247ea2377686b74a10479a0ef105ecf90427bf53b74c96dfa346d0f842b6ffb25b", - "0x92e0fe9063306894a2c6970c001781cff416c87e87cb5fbac927a3192655c3da4063e6fa93539f6ff58efac6adcc5514", - "0xb00a81f03c2b8703acd4e2e4c21e06973aba696415d0ea1a648ace2b0ea19b242fede10e4f9d7dcd61c546ab878bc8f9", - "0xb0d08d880f3b456a10bf65cff983f754f545c840c413aea90ce7101a66eb0a0b9b1549d6c4d57725315828607963f15a", - "0x90cb64d03534f913b411375cce88a9e8b1329ce67a9f89ca5df8a22b8c1c97707fec727dbcbb9737f20c4cf751359277", - "0x8327c2d42590dfcdb78477fc18dcf71608686ad66c49bce64d7ee874668be7e1c17cc1042a754bbc77c9daf50b2dae07", - "0x8532171ea13aa7e37178e51a6c775da469d2e26ec854eb16e60f3307db4acec110d2155832c202e9ba525fc99174e3b0", - "0x83ca44b15393d021de2a511fa5511c5bd4e0ac7d67259dce5a5328f38a3cce9c3a269405959a2486016bc27bb140f9ff", - "0xb1d36e8ca812be545505c8214943b36cabee48112cf0de369957afa796d37f86bf7249d9f36e8e990f26f1076f292b13", - "0x9803abf45be5271e2f3164c328d449efc4b8fc92dfc1225d38e09630909fe92e90a5c77618daa5f592d23fc3ad667094", - "0xb268ad68c7bf432a01039cd889afae815c3e120f57930d463aece10af4fd330b5bd7d8869ef1bcf6b2e78e4229922edc", - "0xa4c91a0d6f16b1553264592b4cbbbf3ca5da32ab053ffbdd3dbb1aed1afb650fb6e0dc5274f71a51d7160856477228db", - "0xad89d043c2f0f17806277ffdf3ecf007448e93968663f8a0b674254f36170447b7527d5906035e5e56f4146b89b5af56", - "0x8b6964f757a72a22a642e4d69102951897e20c21449184e44717bd0681d75f7c5bfa5ee5397f6e53febf85a1810d6ed1", - "0xb08f5cdaabec910856920cd6e836c830b863eb578423edf0b32529488f71fe8257d90aed4a127448204df498b6815d79", - "0xaf26bb3358be9d280d39b21d831bb53145c4527a642446073fee5a86215c4c89ff49a3877a7a549486262f6f57a0f476", - "0xb4010b37ec4d7c2af20800e272539200a6b623ae4636ecbd0e619484f4ab9240d02bc5541ace3a3fb955dc0a3d774212", - "0x82752ab52bdcc3cc2fc405cb05a2e694d3df4a3a68f2179ec0652536d067b43660b96f85f573f26fbd664a9ef899f650", - "0x96d392dde067473a81faf2d1fea55b6429126b88b160e39b4210d31d0a82833ffd3a80e07d24d495aea2d96be7251547", - "0xa76d8236d6671204d440c33ac5b8deb71fa389f6563d80e73be8b043ec77d4c9b06f9a586117c7f957f4af0331cbc871", - "0xb6c90961f68b5e385d85c9830ec765d22a425f506904c4d506b87d8944c2b2c09615e740ed351df0f9321a7b93979cae", - "0xa6ec5ea80c7558403485b3b1869cdc63bde239bafdf936d9b62a37031628402a36a2cfa5cfbb8e26ac922cb0a209b3ba", - "0x8c3195bbdbf9bc0fc95fa7e3d7f739353c947f7767d1e3cb24d8c8602d8ea0a1790ac30b815be2a2ba26caa5227891e2", - "0xa7f8a63d809f1155722c57f375ea00412b00147776ae4444f342550279ef4415450d6f400000a326bf11fea6c77bf941", - "0x97fa404df48433a00c85793440e89bb1af44c7267588ae937a1f5d53e01e1c4d4fc8e4a6d517f3978bfdd6c2dfde012f", - "0xa984a0a3836de3d8d909c4629a2636aacb85393f6f214a2ef68860081e9db05ad608024762db0dc35e895dc00e2d4cdd", - "0x9526cf088ab90335add1db4d3a4ac631b58cbfbe88fa0845a877d33247d1cfeb85994522e1eb8f8874651bfb1df03e2a", - "0xac83443fd0afe99ad49de9bf8230158c118e2814c9c89db5ac951c240d6c2ce45e7677221279d9e97848ec466b99aafe", - "0xaeeefdbaba612e971697798ceaf63b247949dc823a0ad771ae5b988a5e882b338a98d3d0796230f49d533ec5ba411b39", - "0xae3f248b5a7b0f92b7820a6c5ae21e5bd8f4265d4f6e21a22512079b8ee9be06393fd3133ce8ebac0faf23f4f8517e36", - "0xa64a831b908eee784b8388b45447d2885ec0551b26b0c2b15e5f417d0a12c79e867fb7bd3d008d0af98b44336f8ec1ad", - "0xb242238cd8362b6e440ba21806905714dd55172db25ec7195f3fc4937b2aba146d5cbf3cf691a1384b4752dc3b54d627", - "0x819f97f337eea1ffb2a678cc25f556f1aab751c6b048993a1d430fe1a3ddd8bb411c152e12ca60ec6e057c190cd1db9a", - "0xb9d7d187407380df54ee9fef224c54eec1bfabf17dc8abf60765b7951f538f59aa26fffd5846cfe05546c35f59b573f4", - "0xaa6e3c14efa6a5962812e3f94f8ce673a433f4a82d07a67577285ea0eaa07f8be7115853122d12d6d4e1fdf64c504be1", - "0x82268bee9c1662d3ddb5fb785abfae6fb8b774190f30267f1d47091d2cd4b3874db4372625aa36c32f27b0eee986269b", - "0xb236459565b7b966166c4a35b2fa71030b40321821b8e96879d95f0e83a0baf33fa25721f30af4a631df209e25b96061", - "0x8708d752632d2435d2d5b1db4ad1fa2558d776a013655f88e9a3556d86b71976e7dfe5b8834fdec97682cd94560d0d0d", - "0xae1424a68ae2dbfb0f01211f11773732a50510b5585c1fb005cb892b2c6a58f4a55490b5c5b4483c6fce40e9d3236a52", - "0xb3f5f722af9dddb07293c871ce97abbccba0093ca98c8d74b1318fa21396fc1b45b69c15084f63d728f9908442024506", - "0x9606f3ce5e63886853ca476dc0949e7f1051889d529365c0cb0296fdc02abd088f0f0318ecd2cf36740a3634132d36f6", - "0xb11a833a49fa138db46b25ff8cdda665295226595bc212c0931b4931d0a55c99da972c12b4ef753f7e37c6332356e350", - "0xafede34e7dab0a9e074bc19a7daddb27df65735581ca24ad70c891c98b1349fcebbcf3ba6b32c2617fe06a5818dabc2d", - "0x97993d456e459e66322d01f8eb13918979761c3e8590910453944bdff90b24091bb018ac6499792515c9923be289f99f", - "0x977e3e967eff19290a192cd11df3667d511b398fb3ac9a5114a0f3707e25a0edcb56105648b1b85a8b7519fc529fc6f6", - "0xb873a7c88bf58731fe1bf61ff6828bf114cf5228f254083304a4570e854e83748fc98683ddba62d978fff7909f2c5c47", - "0xad4b2691f6f19da1d123aaa23cca3e876247ed9a4ab23c599afdbc0d3aa49776442a7ceaa996ac550d0313d9b9a36cee", - "0xb9210713c78e19685608c6475bfa974b57ac276808a443f8b280945c5d5f9c39da43effa294bfb1a6c6f7b6b9f85bf6c", - "0xa65152f376113e61a0e468759de38d742caa260291b4753391ee408dea55927af08a4d4a9918600a3bdf1df462dffe76", - "0x8bf8c27ad5140dde7f3d2280fd4cc6b29ab76537e8d7aa7011a9d2796ee3e56e9a60c27b5c2da6c5e14fc866301dc195", - "0x92fde8effc9f61393a2771155812b863cff2a0c5423d7d40aa04d621d396b44af94ddd376c28e7d2f53c930aea947484", - "0x97a01d1dd9ee30553ce676011aea97fa93d55038ada95f0057d2362ae9437f3ed13de8290e2ff21e3167dd7ba10b9c3f", - "0x89affffaa63cb2df3490f76f0d1e1d6ca35c221dd34057176ba739fa18d492355e6d2a5a5ad93a136d3b1fed0bb8aa19", - "0x928b8e255a77e1f0495c86d3c63b83677b4561a5fcbbe5d3210f1e0fc947496e426d6bf3b49394a5df796c9f25673fc4", - "0x842a0af91799c9b533e79ee081efe2a634cac6c584c2f054fb7d1db67dde90ae36de36cbf712ec9cd1a0c7ee79e151ea", - "0xa65b946cf637e090baf2107c9a42f354b390e7316beb8913638130dbc67c918926eb87bec3b1fe92ef72bc77a170fa3b", - "0xaafc0f19bfd71ab5ae4a8510c7861458b70ad062a44107b1b1dbacbfa44ba3217028c2824bd7058e2fa32455f624040b", - "0x95269dc787653814e0be899c95dba8cfa384f575a25e671c0806fd80816ad6797dc819d30ae06e1d0ed9cb01c3950d47", - "0xa1e760f7fa5775a1b2964b719ff961a92083c5c617f637fc46e0c9c20ab233f8686f7f38c3cb27d825c54dd95e93a59b", - "0xac3b8a7c2317ea967f229eddc3e23e279427f665c4705c7532ed33443f1243d33453c1088f57088d2ab1e3df690a9cc9", - "0xb787beeddfbfe36dd51ec4efd9cf83e59e84d354c3353cc9c447be53ae53d366ed1c59b686e52a92f002142c8652bfe0", - "0xb7a64198300cb6716aa7ac6b25621f8bdec46ad5c07a27e165b3f774cdf65bcfdbf31e9bae0c16b44de4b00ada7a4244", - "0xb8ae9f1452909e0c412c7a7fe075027691ea8df1347f65a5507bc8848f1d2c833d69748076db1129e5b4fb912f65c86c", - "0x9682e41872456b9fa67def89e71f06d362d6c8ca85c9c48536615bc401442711e1c9803f10ab7f8ab5feaec0f9df20a6", - "0x88889ff4e271dc1c7e21989cc39f73cde2f0475acd98078281591ff6c944fadeb9954e72334319050205d745d4df73df", - "0x8f79b5b8159e7fd0d93b0645f3c416464f39aec353b57d99ecf24f96272df8a068ad67a6c90c78d82c63b40bb73989bb", - "0x838c01a009a3d8558a3f0bdd5e22de21af71ca1aefc8423c91dc577d50920e9516880e87dce3e6d086e11cd45c9052d9", - "0xb97f1c6eee8a78f137c840667cc288256e39294268a3009419298a04a1d0087c9c9077b33c917c65caf76637702dda8a", - "0x972284ce72f96a61c899260203dfa06fc3268981732bef74060641c1a5068ead723e3399431c247ca034b0dae861e8df", - "0x945a8d52d6d3db6663dbd3110c6587f9e9c44132045eeffba15621576d178315cb52870fa5861669f84f0bee646183fe", - "0xa0a547b5f0967b1c3e5ec6c6a9a99f0578521489180dfdfbb5561f4d166baac43a2f06f950f645ce991664e167537eed", - "0xa0592cda5cdddf1340033a745fd13a6eff2021f2e26587116c61c60edead067e0f217bc2bef4172a3c9839b0b978ab35", - "0xb9c223b65a3281587fa44ec829e609154b32f801fd1de6950e01eafb07a8324243b960d5735288d0f89f0078b2c42b5b", - "0x99ebfc3b8f9f98249f4d37a0023149ed85edd7a5abe062c8fb30c8c84555258b998bdcdd1d400bc0fa2a4aaa8b224466", - "0x955b68526e6cb3937b26843270f4e60f9c6c8ece2fa9308fe3e23afa433309c068c66a4bc16ee2cf04220f095e9afce4", - "0xb766caeafcc00378135ae53397f8a67ed586f5e30795462c4a35853de6681b1f17401a1c40958de32b197c083b7279c1", - "0x921bf87cad947c2c33fa596d819423c10337a76fe5a63813c0a9dc78a728207ae7b339407a402fc4d0f7cba3af6da6fc", - "0xa74ba1f3bc3e6c025db411308f49b347ec91da1c916bda9da61e510ec8d71d25e0ac0f124811b7860e5204f93099af27", - "0xa29b4d144e0bf17a7e8353f2824cef0ce85621396babe8a0b873ca1e8a5f8d508b87866cf86da348470649fceefd735c", - "0xa8040e12ffc3480dd83a349d06741d1572ef91932c46f5cf03aee8454254156ee95786fd013d5654725e674c920cec32", - "0x8c4cf34ca60afd33923f219ffed054f90cd3f253ffeb2204a3b61b0183417e366c16c07fae860e362b0f2bfe3e1a1d35", - "0x8195eede4ddb1c950459df6c396b2e99d83059f282b420acc34220cadeed16ab65c856f2c52568d86d3c682818ed7b37", - "0x91fff19e54c15932260aa990c7fcb3c3c3da94845cc5aa8740ef56cf9f58d19b4c3c55596f8d6c877f9f4d22921d93aa", - "0xa3e0bf7e5d02a80b75cf75f2db7e66cb625250c45436e3c136d86297d652590ec97c2311bafe407ad357c79ab29d107b", - "0x81917ff87e5ed2ae4656b481a63ced9e6e5ff653b8aa6b7986911b8bc1ee5b8ef4f4d7882c3f250f2238e141b227e510", - "0x915fdbe5e7de09c66c0416ae14a8750db9412e11dc576cf6158755fdcaf67abdbf0fa79b554cac4fe91c4ec245be073f", - "0x8df27eafb5c3996ba4dc5773c1a45ca77e626b52e454dc1c4058aa94c2067c18332280630cc3d364821ee53bf2b8c130", - "0x934f8a17c5cbb827d7868f5c8ca00cb027728a841000a16a3428ab16aa28733f16b52f58c9c4fbf75ccc45df72d9c4df", - "0xb83f4da811f9183c25de8958bc73b504cf790e0f357cbe74ef696efa7aca97ad3b7ead1faf76e9f982c65b6a4d888fc2", - "0x87188213c8b5c268dc2b6da413f0501c95749e953791b727450af3e43714149c115b596b33b63a2f006a1a271b87efd0", - "0x83e9e888ab9c3e30761de635d9aabd31248cdd92f7675fc43e4b21fd96a03ec1dc4ad2ec94fec857ffb52683ac98e360", - "0xb4b9a1823fe2d983dc4ec4e3aaea297e581c3fc5ab4b4af5fa1370caa37af2d1cc7fc6bfc5e7da60ad8fdce27dfe4b24", - "0x856388bc78aef465dbcdd1f559252e028c9e9a2225c37d645c138e78f008f764124522705822a61326a6d1c79781e189", - "0xa6431b36db93c3b47353ba22e7c9592c9cdfb9cbdd052ecf2cc3793f5b60c1e89bc96e6bae117bfd047f2308da00dd2f", - "0xb619972d48e7e4291542dcde08f7a9cdc883c892986ded2f23ccb216e245cd8d9ad1d285347b0f9d7611d63bf4cee2bc", - "0x8845cca6ff8595955f37440232f8e61d5351500bd016dfadd182b9d39544db77a62f4e0102ff74dd4173ae2c181d24ef", - "0xb2f5f7fa26dcd3b6550879520172db2d64ee6aaa213cbef1a12befbce03f0973a22eb4e5d7b977f466ac2bf8323dcedd", - "0x858b7f7e2d44bdf5235841164aa8b4f3d33934e8cb122794d90e0c1cac726417b220529e4f896d7b77902ab0ccd35b3a", - "0x80b0408a092dae2b287a5e32ea1ad52b78b10e9c12f49282976cd738f5d834e03d1ad59b09c5ccaccc39818b87d06092", - "0xb996b0a9c6a2d14d984edcd6ab56bc941674102980d65b3ad9733455f49473d3f587c8cbf661228a7e125ddbe07e3198", - "0x90224fcebb36865293bd63af786e0c5ade6b67c4938d77eb0cbae730d514fdd0fe2d6632788e858afd29d46310cf86df", - "0xb71351fdfff7168b0a5ec48397ecc27ac36657a8033d9981e97002dcca0303e3715ce6dd3f39423bc8ef286fa2e9e669", - "0xae2a3f078b89fb753ce4ed87e0c1a58bb19b4f0cfb6586dedb9fcab99d097d659a489fb40e14651741e1375cfc4b6c5f", - "0x8ef476b118e0b868caed297c161f4231bbeb863cdfa5e2eaa0fc6b6669425ce7af50dc374abceac154c287de50c22307", - "0x92e46ab472c56cfc6458955270d3c72b7bde563bb32f7d4ab4d959db6f885764a3d864e1aa19802fefaa5e16b0cb0b54", - "0x96a3f68323d1c94e73d5938a18a377af31b782f56212de3f489d22bc289cf24793a95b37f1d6776edf88114b5c1fa695", - "0x962cc068cfce6faaa27213c4e43e44eeff0dfbb6d25b814e82c7da981fb81d7d91868fa2344f05fb552362f98cfd4a72", - "0x895d4e4c4ad670abf66d43d59675b1add7afad7438ada8f42a0360c704cee2060f9ac15b4d27e9b9d0996bb801276fe3", - "0xb3ad18d7ece71f89f2ef749b853c45dc56bf1c796250024b39a1e91ed11ca32713864049c9aaaea60cde309b47486bbf", - "0x8f05404e0c0258fdbae50e97ccb9b72ee17e0bd2400d9102c0dad981dac8c4c71585f03e9b5d50086d0a2d3334cb55d1", - "0x8bd877e9d4591d02c63c6f9fc9976c109de2d0d2df2bfa5f6a3232bab5b0b8b46e255679520480c2d7a318545efa1245", - "0x8d4c16b5d98957c9da13d3f36c46f176e64e5be879f22be3179a2c0e624fe4758a82bf8c8027410002f973a3b84cd55a", - "0x86e2a8dea86427b424fa8eada881bdff896907084a495546e66556cbdf070b78ba312bf441eb1be6a80006d25d5097a3", - "0x8608b0c117fd8652fdab0495b08fadbeba95d9c37068e570de6fddfef1ba4a1773b42ac2be212836141d1bdcdef11a17", - "0xa13d6febf5fb993ae76cae08423ca28da8b818d6ef0fde32976a4db57839cd45b085026b28ee5795f10a9a8e3098c683", - "0x8e261967fa6de96f00bc94a199d7f72896a6ad8a7bbb1d6187cca8fad824e522880e20f766620f4f7e191c53321d70f9", - "0x8b8e8972ac0218d7e3d922c734302803878ad508ca19f5f012bc047babd8a5c5a53deb5fe7c15a4c00fd6d1cb9b1dbd0", - "0xb5616b233fb3574a2717d125a434a2682ff68546dccf116dd8a3b750a096982f185614b9fb6c7678107ff40a451f56fa", - "0xaa6adf9b0c3334b0d0663f583a4914523b2ac2e7adffdb026ab9109295ff6af003ef8357026dbcf789896d2afded8d73", - "0xacb72df56a0b65496cd534448ed4f62950bb1e11e50873b6ed349c088ee364441821294ce0f7c61bd7d38105bea3b442", - "0xabae12df83e01ec947249fedd0115dc501d2b03ff7232092979eda531dbbca29ace1d46923427c7dde4c17bdf3fd7708", - "0x820b4fc2b63a9fda7964acf5caf19a2fc4965007cb6d6b511fcafcb1f71c3f673a1c0791d3f86e3a9a1eb6955b191cc0", - "0xaf277259d78c6b0f4f030a10c53577555df5e83319ddbad91afbd7c30bc58e7671c56d00d66ec3ab5ef56470cd910cee", - "0xad4a861c59f1f5ca1beedd488fb3d131dea924fffd8e038741a1a7371fad7370ca5cf80dc01f177fbb9576713bb9a5b3", - "0xb67a5162982ce6a55ccfb2f177b1ec26b110043cf18abd6a6c451cf140b5af2d634591eb4f28ad92177d8c7e5cd0a5e8", - "0x96176d0a83816330187798072d449cbfccff682561e668faf6b1220c9a6535b32a6e4f852e8abb00f79abb87493df16b", - "0xb0afe6e7cb672e18f0206e4423f51f8bd0017bf464c4b186d46332c5a5847647f89ff7fa4801a41c1b0b42f6135bcc92", - "0x8fc5e7a95ef20c1278c645892811f6fe3f15c431ebc998a32ec0da44e7213ea934ed2be65239f3f49b8ec471e9914160", - "0xb7793e41adda6c82ba1f2a31f656f6205f65bf8a3d50d836ee631bc7ce77c153345a2d0fc5c60edf8b37457c3729c4ec", - "0xa504dd7e4d6b2f4379f22cc867c65535079c75ccc575955f961677fa63ecb9f74026fa2f60c9fb6323c1699259e5e9c8", - "0xab899d00ae693649cc1afdf30fb80d728973d2177c006e428bf61c7be01e183866614e05410041bc82cb14a33330e69c", - "0x8a3bd8b0b1be570b65c4432a0f6dc42f48a2000e30ab089cf781d38f4090467b54f79c0d472fcbf18ef6a00df69cc6f3", - "0xb4d7028f7f76a96a3d7803fca7f507ae11a77c5346e9cdfccb120a833a59bda1f4264e425aa588e7a16f8e7638061d84", - "0xb9c7511a76ea5fb105de905d44b02edb17008335766ee357ed386b7b3cf19640a98b38785cb14603c1192bee5886c9b6", - "0x8563afb12e53aed71ac7103ab8602bfa8371ae095207cb0d59e8fd389b6ad1aff0641147e53cb6a7ca16c7f37c9c5e6b", - "0x8e108be614604e09974a9ed90960c28c4ea330a3d9a0cb4af6dd6f193f84ab282b243ecdf549b3131036bebc8905690c", - "0xb794d127fbedb9c5b58e31822361706ffac55ce023fbfe55716c3c48c2fd2f2c7660a67346864dfe588812d369cb50b6", - "0xb797a3442fc3b44f41baefd30346f9ac7f96e770d010d53c146ce74ce424c10fb62758b7e108b8abfdc5fafd89d745cb", - "0x993bb71e031e8096442e6205625e1bfddfe6dd6a83a81f3e2f84fafa9e5082ab4cad80a099f21eff2e81c83457c725c3", - "0x8711ab833fc03e37acf2e1e74cfd9133b101ff4144fe30260654398ae48912ab46549d552eb9d15d2ea57760d35ac62e", - "0xb21321fd2a12083863a1576c5930e1aecb330391ef83326d9d92e1f6f0d066d1394519284ddab55b2cb77417d4b0292f", - "0x877d98f731ffe3ee94b0b5b72d127630fa8a96f6ca4f913d2aa581f67732df6709493693053b3e22b0181632ac6c1e3b", - "0xae391c12e0eb8c145103c62ea64f41345973311c3bf7281fa6bf9b7faafac87bcf0998e5649b9ef81e288c369c827e07", - "0xb83a2842f36998890492ab1cd5a088d9423d192681b9a3a90ec518d4c541bce63e6c5f4df0f734f31fbfdd87785a2463", - "0xa21b6a790011396e1569ec5b2a423857b9bec16f543e63af28024e116c1ea24a3b96e8e4c75c6537c3e4611fd265e896", - "0xb4251a9c4aab3a495da7a42e684ba4860dbcf940ad1da4b6d5ec46050cbe8dab0ab9ae6b63b5879de97b905723a41576", - "0x8222f70aebfe6ac037f8543a08498f4cadb3edaac00336fc00437eb09f2cba758f6c38e887cc634b4d5b7112b6334836", - "0x86f05038e060594c46b5d94621a1d9620aa8ba59a6995baf448734e21f58e23c1ea2993d3002ad5250d6edd5ba59b34f", - "0xa7c0c749baef811ab31b973c39ceb1d94750e2bc559c90dc5eeb20d8bb6b78586a2b363c599ba2107d6be65cd435f24e", - "0x861d46a5d70b38d6c1cd72817a2813803d9f34c00320c8b62f8b9deb67f5b5687bc0b37c16d28fd017367b92e05da9ca", - "0xb3365d3dab639bffbe38e35383686a435c8c88b397b717cd4aeced2772ea1053ceb670f811f883f4e02975e5f1c4ac58", - "0xa5750285f61ab8f64cd771f6466e2c0395e01b692fd878f2ef2d5c78bdd8212a73a3b1dfa5e4c8d9e1afda7c84857d3b", - "0x835a10809ccf939bc46cf950a33b36d71be418774f51861f1cd98a016ade30f289114a88225a2c11e771b8b346cbe6ef", - "0xa4f59473a037077181a0a62f1856ec271028546ca9452b45cedfcb229d0f4d1aabfc13062b07e536cc8a0d4b113156a2", - "0x95cd14802180b224d44a73cc1ed599d6c4ca62ddcaa503513ccdc80aaa8be050cc98bd4b4f3b639549beb4587ac6caf9", - "0x973b731992a3e69996253d7f36dd7a0af1982b5ed21624b77a7965d69e9a377b010d6dabf88a8a97eec2a476259859cc", - "0xaf8a1655d6f9c78c8eb9a95051aa3baaf9c811adf0ae8c944a8d3fcba87b15f61021f3baf6996fa0aa51c81b3cb69de1", - "0x835aad5c56872d2a2d6c252507b85dd742bf9b8c211ccb6b25b52d15c07245b6d89b2a40f722aeb5083a47cca159c947", - "0xabf4e970b02bef8a102df983e22e97e2541dd3650b46e26be9ee394a3ea8b577019331857241d3d12b41d4eacd29a3ac", - "0xa13c32449dbedf158721c13db9539ae076a6ce5aeaf68491e90e6ad4e20e20d1cdcc4a89ed9fd49cb8c0dd50c17633c1", - "0x8c8f78f88b7e22dd7e9150ab1c000f10c28e696e21d85d6469a6fe315254740f32e73d81ab1f3c1cf8f544c86df506e8", - "0xb4b77f2acfe945abf81f2605f906c10b88fb4d28628487fb4feb3a09f17f28e9780445dfcee4878349d4c6387a9d17d4", - "0x8d255c235f3812c6ecc646f855fa3832be5cb4dbb9c9e544989fafdf3f69f05bfd370732eaf954012f0044aa013fc9c6", - "0xb982efd3f34b47df37c910148ac56a84e8116647bea24145a49e34e0a6c0176e3284d838dae6230cb40d0be91c078b85", - "0x983f365aa09bd85df2a6a2ad8e4318996b1e27d02090755391d4486144e40d80b1fbfe1c798d626db92f52e33aa634da", - "0x95fd1981271f3ea3a41d654cf497e6696730d9ff7369f26bc4d7d15c7adb4823dd0c42e4a005a810af12d234065e5390", - "0xa9f5219bd4b913c186ef30c02f995a08f0f6f1462614ea5f236964e02bdaa33db9d9b816c4aee5829947840a9a07ba60", - "0x9210e6ceb05c09b46fd09d036287ca33c45124ab86315e5d6911ff89054f1101faaa3e83d123b7805056d388bcec6664", - "0x8ed9cbf69c6ff3a5c62dd9fe0d7264578c0f826a29e614bc2fb4d621d90c8c9992438accdd7a614b1dca5d1bb73dc315", - "0x85cf2a8cca93e00da459e3cecd22c342d697eee13c74d5851634844fc215f60053cf84b0e03c327cb395f48d1c71a8a4", - "0x8818a18e9a2ec90a271b784400c1903089ffb0e0b40bc5abbbe12fbebe0f731f91959d98c5519ef1694543e31e2016d4", - "0x8dabc130f296fa7a82870bf9a8405aaf542b222ed9276bba9bd3c3555a0f473acb97d655ee7280baff766a827a8993f0", - "0xac7952b84b0dc60c4d858f034093b4d322c35959605a3dad2b806af9813a4680cb038c6d7f4485b4d6b2ff502aaeca25", - "0xad65cb6d57b48a2602568d2ec8010baed0eb440eec7638c5ec8f02687d764e9de5b5d42ad5582934e592b48471c22d26", - "0xa02ab8bd4c3d114ea23aebdd880952f9495912817da8c0c08eabc4e6755439899d635034413d51134c72a6320f807f1c", - "0x8319567764b8295402ec1ebef4c2930a138480b37e6d7d01c8b4c9cd1f2fc3f6e9a44ae6e380a0c469b25b06db23305f", - "0xafec53b2301dc0caa8034cd9daef78c48905e6068d692ca23d589b84a6fa9ddc2ed24a39480597e19cb3e83eec213b3f", - "0xac0b4ffdb5ae08e586a9cdb98f9fe56f4712af3a97065e89e274feacfb52b53c839565aee93c4cfaaccfe51432c4fab0", - "0x8972cbf07a738549205b1094c5987818124144bf187bc0a85287c94fdb22ce038c0f11df1aa16ec5992e91b44d1af793", - "0xb7267aa6f9e3de864179b7da30319f1d4cb2a3560f2ea980254775963f1523b44c680f917095879bebfa3dc2b603efcf", - "0x80f68f4bfc337952e29504ee5149f15093824ea7ab02507efd1317a670f6cbc3611201848560312e3e52e9d9af72eccf", - "0x8897fee93ce8fc1e1122e46b6d640bba309384dbd92e46e185e6364aa8210ebf5f9ee7e5e604b6ffba99aa80a10dd7d0", - "0xb58ea6c02f2360be60595223d692e82ee64874fda41a9f75930f7d28586f89be34b1083e03bbc1575bbfdda2d30db1ea", - "0x85a523a33d903280d70ac5938770453a58293480170c84926457ac2df45c10d5ff34322ab130ef4a38c916e70d81af53", - "0xa2cbf045e1bed38937492c1f2f93a5ba41875f1f262291914bc1fc40c60bd0740fb3fea428faf6da38b7c180fe8ac109", - "0x8c09328770ed8eb17afc6ac7ddd87bb476de18ed63cab80027234a605806895959990c47bd10d259d7f3e2ecb50074c9", - "0xb4b9e19edb4a33bde8b7289956568a5b6b6557404e0a34584b5721fe6f564821091013fbb158e2858c6d398293bb4b59", - "0x8a47377df61733a2aa5a0e945fce00267f8e950f37e109d4487d92d878fb8b573317bb382d902de515b544e9e233458d", - "0xb5804c9d97efeff5ca94f3689b8088c62422d92a1506fd1d8d3b1b30e8a866ad0d6dad4abfa051dfc4471250cac4c5d9", - "0x9084a6ee8ec22d4881e9dcc8a9eb3c2513523d8bc141942370fd191ad2601bf9537a0b1e84316f3209b3d8a54368051e", - "0x85447eea2fa26656a649f8519fa67279183044791d61cf8563d0783d46d747d96af31d0a93507bbb2242666aa87d3720", - "0x97566a84481027b60116c751aec552adfff2d9038e68d48c4db9811fb0cbfdb3f1d91fc176a0b0d988a765f8a020bce1", - "0xae87e5c1b9e86c49a23dceda4ecfd1dcf08567f1db8e5b6ec752ebd45433c11e7da4988573cdaebbb6f4135814fc059e", - "0xabee05cf9abdbc52897ac1ce9ed157f5466ed6c383d6497de28616238d60409e5e92619e528af8b62cc552bf09970dc2", - "0xae6d31cd7bf9599e5ee0828bab00ceb4856d829bba967278a73706b5f388465367aa8a6c7da24b5e5f1fdd3256ef8e63", - "0xac33e7b1ee47e1ee4af472e37ab9e9175260e506a4e5ce449788075da1b53c44cb035f3792d1eea2aa24b1f688cc6ed3", - "0x80f65b205666b0e089bb62152251c48c380a831e5f277f11f3ef4f0d52533f0851c1b612267042802f019ec900dc0e8f", - "0x858520ad7aa1c9fed738e3b583c84168f2927837ad0e1d326afe9935c26e9b473d7f8c382e82ef1fe37d2b39bb40a1ee", - "0xb842dd4af8befe00a97c2d0f0c33c93974761e2cb9e5ab8331b25170318ddd5e4bdbc02d8f90cbfdd5f348f4f371c1f7", - "0x8bf2cb79bc783cb57088aae7363320cbeaabd078ffdec9d41bc74ff49e0043d0dad0086a30e5112b689fd2f5a606365d", - "0x982eb03bbe563e8850847cd37e6a3306d298ab08c4d63ab6334e6b8c1fa13fce80cf2693b09714c7621d74261a0ff306", - "0xb143edb113dec9f1e5105d4a93fbe502b859e587640d3db2f628c09a17060e6aec9e900e2c8c411cda99bc301ff96625", - "0xaf472d9befa750dcebc5428fe1a024f18ec1c07bca0f95643ce6b5f4189892a910285afb03fd7ed7068fbe614e80d33c", - "0xa97e3bc57ede73ecd1bbf02de8f51b4e7c1a067da68a3cd719f4ba26a0156cbf1cef2169fd35a18c5a4cced50d475998", - "0xa862253c937cf3d75d7183e5f5be6a4385d526aeda5171c1c60a8381fea79f88f5f52a4fab244ecc70765d5765e6dfd5", - "0x90cb776f8e5a108f1719df4a355bebb04bf023349356382cae55991b31720f0fd03206b895fa10c56c98f52453be8778", - "0xa7614e8d0769dccd520ea4b46f7646e12489951efaef5176bc889e9eb65f6e31758df136b5bf1e9107e68472fa9b46ec", - "0xac3a9b80a3254c42e5ed3a090a0dd7aee2352f480de96ad187027a3bb6c791eddfc3074b6ffd74eea825188f107cda4d", - "0x82a01d0168238ef04180d4b6e0a0e39024c02c2d75b065017c2928039e154d093e1af4503f4d1f3d8a948917abb5d09f", - "0x8fab000a2b0eef851a483aec8d2dd85fe60504794411a2f73ed82e116960547ac58766cb73df71aea71079302630258d", - "0x872451a35c6db61c63e9b8bb9f16b217f985c20be4451c14282c814adb29d7fb13f201367c664435c7f1d4d9375d7a58", - "0x887d9ff54cc96b35d562df4a537ff972d7c4b3fd91ab06354969a4cfede0b9fc68bbffb61d0dbf1a58948dc701e54f5a", - "0x8cb5c2a6bd956875d88f41ae24574434f1308514d44057b55c9c70f13a3366ed054150eed0955a38fda3f757be73d55f", - "0x89ad0163cad93e24129d63f8e38422b7674632a8d0a9016ee8636184cab177659a676c4ee7efba3abe1a68807c656d60", - "0xb9ec01c7cab6d00359b5a0b4a1573467d09476e05ca51a9227cd16b589a9943d161eef62dcc73f0de2ec504d81f4d252", - "0x8031d17635d39dfe9705c485d2c94830b6fc9bc67b91300d9d2591b51e36a782e77ab5904662effa9382d9cca201f525", - "0x8be5a5f6bc8d680e5092d6f9a6585acbaaaa2ddc671da560dcf5cfa4472f4f184b9597b5b539438accd40dda885687cc", - "0xb1fc0f052fae038a2e3de3b3a96b0a1024b009de8457b8b3adb2d315ae68a89af905720108a30038e5ab8d0d97087785", - "0x8b8bdc77bd3a6bc7ca5492b6f8c614852c39a70d6c8a74916eaca0aeb4533b11898b8820a4c2620a97bf35e275480029", - "0xaf35f4dc538d4ad5cdf710caa38fd1eb496c3fa890a047b6a659619c5ad3054158371d1e88e0894428282eed9f47f76b", - "0x8166454a7089cc07758ad78724654f4e7a1a13e305bbf88ddb86f1a4b2904c4fc8ab872d7da364cdd6a6c0365239e2ad", - "0xab287c7d3addce74ce40491871c768abe01daaa0833481276ff2e56926b38a7c6d2681ffe837d2cc323045ad1a4414f9", - "0xb90317f4505793094d89365beb35537f55a6b5618904236258dd04ca61f21476837624a2f45fef8168acf732cab65579", - "0x98ae5ea27448e236b6657ab5ef7b1cccb5372f92ab25f5fa651fbac97d08353a1dae1b280b1cd42b17d2c6a70a63ab9d", - "0xadcf54e752d32cbaa6cb98fbca48d8cd087b1db1d131d465705a0d8042c8393c8f4d26b59006eb50129b21e6240f0c06", - "0xb591a3e4db18a7345fa935a8dd7994bbac5cc270b8ebd84c8304c44484c7a74afb45471fdbe4ab22156a30fae1149b40", - "0x806b53ac049a42f1dcc1d6335505371da0bf27c614f441b03bbf2e356be7b2fb4eed7117eabcce9e427a542eaa2bf7d8", - "0x800482e7a772d49210b81c4a907f5ce97f270b959e745621ee293cf8c71e8989363d61f66a98f2d16914439544ca84c7", - "0x99de9eafdad3617445312341644f2bb888680ff01ce95ca9276b1d2e5ef83fa02dab5e948ebf66c17df0752f1bd37b70", - "0x961ee30810aa4c93ae157fbe9009b8e443c082192bd36a73a6764ff9b2ad8b0948fe9a73344556e01399dd77badb4257", - "0xae0a361067c52efbe56c8adf982c00432cd478929459fc7f74052c8ee9531cd031fe1335418fde53f7c2ef34254eb7ac", - "0xa3503d16b6b27eb20c1b177bcf90d13706169220523a6271b85b2ce35a9a2b9c5bed088540031c0a4ebfdae3a4c6ab04", - "0x909420122c3e723289ca4e7b81c2df5aff312972a2203f4c45821b176e7c862bf9cac7f7df3adf1d59278f02694d06e7", - "0x989f42380ae904b982f85d0c6186c1aef5d6bcba29bcfbb658e811b587eb2749c65c6e4a8cc6409c229a107499a4f5d7", - "0x8037a6337195c8e26a27ea4ef218c6e7d79a9720aaab43932d343192abc2320fe72955f5e431c109093bda074103330a", - "0xb312e168663842099b88445e940249cc508f080ab0c94331f672e7760258dbd86be5267e4cf25ea25facb80bff82a7e9", - "0xaaa3ff8639496864fcdbfdda1ac97edc4f08e3c9288b768f6c8073038c9fbbf7e1c4bea169b4d45c31935cdf0680d45e", - "0x97dbd3df37f0b481a311dfc5f40e59227720f367912200d71908ef6650f32cc985cb05b981e3eea38958f7e48d10a15d", - "0xa89d49d1e267bb452d6cb621b9a90826fe55e9b489c0427b94442d02a16f390eed758e209991687f73f6b5a032321f42", - "0x9530dea4e0e19d6496f536f2e75cf7d814d65fde567055eb20db48fd8d20d501cd2a22fb506db566b94c9ee10f413d43", - "0x81a7009b9e67f1965fa7da6a57591c307de91bf0cd35ab4348dc4a98a4961e096d004d7e7ad318000011dc4342c1b809", - "0x83440a9402b766045d7aca61a58bba2aa29cac1cf718199e472ba086f5d48093d9dda4d135292ba51d049a23964eceae", - "0xa06c9ce5e802df14f6b064a3d1a0735d429b452f0e2e276042800b0a4f16df988fd94cf3945921d5dd3802ab2636f867", - "0xb1359e358b89936dee9e678a187aad3e9ab14ac40e96a0a68f70ee2583cdcf467ae03bef4215e92893f4e12f902adec8", - "0x835304f8619188b4d14674d803103d5a3fa594d48e96d9699e653115dd05fdc2dda6ba3641cf7ad53994d448da155f02", - "0x8327cba5a9ff0d3f5cd0ae55e77167448926d5fcf76550c0ad978092a14122723090c51c415e88e42a2b62eb07cc3981", - "0xb373dcdaea85f85ce9978b1426a7ef4945f65f2d3467a9f1cc551a99766aac95df4a09e2251d3f89ca8c9d1a7cfd7b0e", - "0xab1422dc41af2a227b973a6fd124dfcb2367e2a11a21faa1d381d404f51b7257e5bc82e9cf20cd7fe37d7ae761a2ab37", - "0xa93774a03519d2f20fdf2ef46547b0a5b77c137d6a3434b48d56a2cbef9e77120d1b85d0092cf8842909213826699477", - "0x8eb967a495a38130ea28711580b7e61bcd1d051cd9e4f2dbf62f1380bd86e0d60e978d72f6f31e909eb97b3b9a2b867c", - "0xae8213378da1287ba1fe4242e1acaec19b877b6fe872400013c6eac1084b8d03156792fa3020201725b08228a1e80f49", - "0xb143daf6893d674d607772b3b02d8ac48f294237e2f2c87963c0d4e26d9227d94a2a13512457c3d5883544bbc259f0ef", - "0xb343bd2aca8973888e42542218924e2dda2e938fd1150d06878af76f777546213912b7c7a34a0f94186817d80ffa185c", - "0xb188ebc6a8c3007001aa347ae72cc0b15d09bc6c19a80e386ee4b334734ec0cc2fe8b493c2422f38d1e6d133cc3db6fe", - "0xb795f6a8b9b826aaeee18ccd6baf6c5adeeec85f95eb5b6d19450085ec7217e95a2d9e221d77f583b297d0872073ba0e", - "0xb1c7dbd998ad32ae57bfa95deafa147024afd57389e98992c36b6e52df915d3d5a39db585141ec2423173e85d212fed8", - "0x812bcdeb9fe5f12d0e1df9964798056e1f1c3de3b17b6bd2919b6356c4b86d8e763c01933efbe0224c86a96d5198a4be", - "0xb19ebeda61c23d255cbf472ef0b8a441f4c55b70f0d8ed47078c248b1d3c7c62e076b43b95c00a958ec8b16d5a7cb0d7", - "0xb02adc9aaa20e0368a989c2af14ff48b67233d28ebee44ff3418bb0473592e6b681af1cc45450bd4b175df9051df63d9", - "0x8d87f0714acee522eb58cec00360e762adc411901dba46adc9227124fa70ee679f9a47e91a6306d6030dd4eb8de2f3c1", - "0x8be54cec21e74bcc71de29dc621444263737db15f16d0bb13670f64e42f818154e04b484593d19ef95f2ee17e4b3fe21", - "0xab8e20546c1db38d31493b5d5f535758afb17e459645c1b70813b1cf7d242fd5d1f4354a7c929e8f7259f6a25302e351", - "0x89f035a1ed8a1e302ac893349ba8ddf967580fcb6e73d44af09e3929cde445e97ff60c87dafe489e2c0ab9c9986cfa00", - "0x8b2b0851a795c19191a692af55f7e72ad2474efdc5401bc3733cfdd910e34c918aaebe69d5ea951bdddf3c01cabbfc67", - "0xa4edb52c2b51495ccd1ee6450fc14b7b3ede8b3d106808929d02fb31475bacb403e112ba9c818d2857651e508b3a7dd1", - "0x9569341fded45d19f00bcf3cbf3f20eb2b4d82ef92aba3c8abd95866398438a2387437e580d8b646f17cf6fde8c5af23", - "0xaa4b671c6d20f72f2f18a939a6ff21cc37e0084b44b4a717f1be859a80b39fb1be026b3205adec2a66a608ec2bcd578f", - "0x94902e980de23c4de394ad8aec91b46f888d18f045753541492bfbb92c59d3daa8de37ae755a6853744af8472ba7b72b", - "0xaf651ef1b2a0d30a7884557edfad95b6b5d445a7561caebdc46a485aedd25932c62c0798465c340a76f6feaa196dd712", - "0xb7b669b8e5a763452128846dd46b530dca4893ace5cc5881c7ddcd3d45969d7e73fbebdb0e78aa81686e5f7b22ec5759", - "0x82507fd4ebe9fa656a7f2e084d64a1fa6777a2b0bc106d686e2d9d2edafc58997e58cb6bfd0453b2bf415704aa82ae62", - "0xb40bce2b42b88678400ecd52955bbdadd15f8b9e1b3751a1a3375dc0efb5ca3ee258cf201e1140b3c09ad41217d1d49e", - "0xb0210d0cbb3fbf3b8cdb39e862f036b0ff941cd838e7aaf3a8354e24246e64778d22f3de34572e6b2a580614fb6425be", - "0x876693cba4301b251523c7d034108831df3ce133d8be5a514e7a2ca494c268ca0556fa2ad8310a1d92a16b55bcd99ea9", - "0x8660281406d22a4950f5ef050bf71dd3090edb16eff27fa29ef600cdea628315e2054211ed2cc6eaf8f2a1771ef689fd", - "0xa610e7e41e41ab66955b809ba4ade0330b8e9057d8efc9144753caed81995edeb1a42a53f93ce93540feca1fae708dac", - "0xa49e2c176a350251daef1218efaccc07a1e06203386ede59c136699d25ca5cb2ac1b800c25b28dd05678f14e78e51891", - "0x83e0915aa2b09359604566080d411874af8c993beba97d4547782fdbe1a68e59324b800ff1f07b8db30c71adcbd102a8", - "0xa19e84e3541fb6498e9bb8a099c495cbfcad113330e0262a7e4c6544495bb8a754b2208d0c2d895c93463558013a5a32", - "0x87f2bd49859a364912023aca7b19a592c60214b8d6239e2be887ae80b69ebdeb59742bdebcfa73a586ab23b2c945586c", - "0xb8e8fdddae934a14b57bc274b8dcd0d45ebb95ddbaabef4454e0f6ce7d3a5a61c86181929546b3d60c447a15134d08e1", - "0x87e0c31dcb736ea4604727e92dc1d9a3cf00adcff79df3546e02108355260f3dd171531c3c0f57be78d8b28058fcc8c0", - "0x9617d74e8f808a4165a8ac2e30878c349e1c3d40972006f0787b31ea62d248c2d9f3fc3da83181c6e57e95feedfd0e8c", - "0x8949e2cee582a2f8db86e89785a6e46bc1565c2d8627d5b6bf43ba71ffadfab7e3c5710f88dcb5fb2fc6edf6f4fae216", - "0xad3fa7b0edceb83118972a2935a09f409d09a8db3869f30be3a76f67aa9fb379cabb3a3aff805ba023a331cad7d7eb64", - "0x8c95718a4112512c4efbd496be38bf3ca6cdcaad8a0d128f32a3f9aae57f3a57bdf295a3b372a8c549fda8f4707cffed", - "0x88f3261d1e28a58b2dee3fcc799777ad1c0eb68b3560f9b4410d134672d9533532a91ea7be28a041784872632d3c9d80", - "0xb47472a41d72dd2e8b72f5c4f8ad626737dde3717f63d6bc776639ab299e564cbad0a2ad5452a07f02ff49a359c437e5", - "0x9896d21dc2e8aad87b76d6df1654f10cd7bceed4884159d50a818bea391f8e473e01e14684814c7780235f28e69dca6e", - "0x82d47c332bbd31bbe83b5eb44a23da76d4a7a06c45d7f80f395035822bc27f62f59281d5174e6f8e77cc9b5c3193d6f0", - "0x95c74cd46206e7f70c9766117c34c0ec45c2b0f927a15ea167901a160e1530d8522943c29b61e03568aa0f9c55926c53", - "0xa89d7757825ae73a6e81829ff788ea7b3d7409857b378ebccd7df73fdbe62c8d9073741cf038314971b39af6c29c9030", - "0x8c1cd212d0b010905d560688cfc036ae6535bc334fa8b812519d810b7e7dcf1bb7c5f43deaa40f097158358987324a7f", - "0xb86993c383c015ed8d847c6b795164114dd3e9efd25143f509da318bfba89389ea72a420699e339423afd68b6512fafb", - "0x8d06bd379c6d87c6ed841d8c6e9d2d0de21653a073725ff74be1934301cc3a79b81ef6dd0aad4e7a9dc6eac9b73019bc", - "0x81af4d2d87219985b9b1202d724fe39ef988f14fef07dfe3c3b11714e90ffba2a97250838e8535eb63f107abfe645e96", - "0x8c5e0af6330a8becb787e4b502f34f528ef5756e298a77dc0c7467433454347f3a2e0bd2641fbc2a45b95e231c6e1c02", - "0x8e2a8f0f04562820dc8e7da681d5cad9fe2e85dd11c785fb6fba6786c57a857e0b3bd838fb849b0376c34ce1665e4837", - "0xa39be8269449bfdfc61b1f62077033649f18dae9bef7c6163b9314ca8923691fb832f42776f0160b9e8abd4d143aa4e1", - "0x8c154e665706355e1cc98e0a4cabf294ab019545ba9c4c399d666e6ec5c869ca9e1faf8fb06cd9c0a5c2f51a7d51b70a", - "0xa046a7d4de879d3ebd4284f08f24398e9e3bf006cd4e25b5c67273ade248689c69affff92ae810c07941e4904296a563", - "0xafd94c1cb48758e5917804df03fb38a6da0e48cd9b6262413ea13b26973f9e266690a1b7d9d24bbaf7e82718e0e594b0", - "0x859e21080310c8d6a38e12e2ac9f90a156578cdeb4bb2e324700e97d9a5511cd6045dc39d1d0de3f94aeed043a24119d", - "0xa219fb0303c379d0ab50893264919f598e753aac9065e1f23ef2949abc992577ab43c636a1d2c089203ec9ddb941e27d", - "0xb0fdb639d449588a2ca730afcba59334e7c387342d56defdfb7ef79c493f7fd0e5277eff18e7203e756c7bdda5803047", - "0x87f9c3b7ed01f54368aca6dbcf2f6e06bff96e183c4b2c65f8baa23b377988863a0a125d5cdd41a072da8462ced4c070", - "0x99ef7a5d5ac2f1c567160e1f8c95f2f38d41881850f30c461a205f7b1b9fb181277311333839b13fb3ae203447e17727", - "0xaeaca9b1c2afd24e443326cc68de67b4d9cedb22ad7b501a799d30d39c85bb2ea910d4672673e39e154d699e12d9b3dc", - "0xa11675a1721a4ba24dd3d0e4c3c33a6edf4cd1b9f6b471070b4386c61f77452266eae6e3f566a40cfc885eada9a29f23", - "0xb228334445e37b9b49cb4f2cc56b454575e92173ddb01370a553bba665adadd52df353ad74470d512561c2c3473c7bb9", - "0xa18177087c996572d76f81178d18ed1ceebc8362a396348ce289f1d8bd708b9e99539be6fccd4acb1112381cfc5749b4", - "0x8e7b8bf460f0d3c99abb19803b9e43422e91507a1c0c22b29ee8b2c52d1a384da4b87c292e28eff040db5be7b1f8641f", - "0xb03d038d813e29688b6e6f444eb56fec3abba64c3d6f890a6bcf2e916507091cdb2b9d2c7484617be6b26552ed1c56cb", - "0xa1c88ccd30e934adfc5494b72655f8afe1865a84196abfb376968f22ddc07761210b6a9fb7638f1413d1b4073d430290", - "0x961b714faebf172ad2dbc11902461e286e4f24a99a939152a53406117767682a571057044decbeb3d3feef81f4488497", - "0xa03dc4059b46effdd786a0a03cc17cfee8585683faa35bb07936ded3fa3f3a097f518c0b8e2db92fd700149db1937789", - "0xadf60180c99ca574191cbcc23e8d025b2f931f98ca7dfcebfc380226239b6329347100fcb8b0fcb12db108c6ad101c07", - "0x805d4f5ef24d46911cbf942f62cb84b0346e5e712284f82b0db223db26d51aabf43204755eb19519b00e665c7719fcaa", - "0x8dea7243e9c139662a7fe3526c6c601eee72fd8847c54c8e1f2ad93ef7f9e1826b170afe58817dac212427164a88e87f", - "0xa2ba42356606d651b077983de1ad643650997bb2babb188c9a3b27245bb65d2036e46667c37d4ce02cb1be5ae8547abe", - "0xaf2ae50b392bdc013db2d12ce2544883472d72424fc767d3f5cb0ca2d973fc7d1f425880101e61970e1a988d0670c81b", - "0x98e6bec0568d3939b31d00eb1040e9b8b2a35db46ddf4369bdaee41bbb63cc84423d29ee510a170fb5b0e2df434ba589", - "0x822ff3cd12fbef4f508f3ca813c04a2e0b9b799c99848e5ad3563265979e753ee61a48f6adc2984a850f1b46c1a43d35", - "0x891e8b8b92a394f36653d55725ef514bd2e2a46840a0a2975c76c2a935577f85289026aaa74384da0afe26775cbddfb9", - "0xb2a3131a5d2fe7c8967047aa66e4524babae941d90552171cc109527f345f42aa0df06dcbb2fa01b33d0043917bbed69", - "0x80c869469900431f3eeefafdbe07b8afd8cee7739e659e6d0109b397cacff85a88247698f87dc4e2fe39a592f250ac64", - "0x9091594f488b38f9d2bb5df49fd8b4f8829d9c2f11a197dd1431ed5abbc5c954bbde3387088f9ee3a5a834beb7619bce", - "0xb472e241e6956146cca57b97a8a204668d050423b4e76f857bad5b47f43b203a04c8391ba9d9c3e95093c071f9d376a1", - "0xb7dd2de0284844392f7dfb56fe7ca3ede41e27519753ffc579a0a8d2d65ceb8108d06b6b0d4c3c1a2588951297bd1a1e", - "0x902116ce70d0a079ac190321c1f48701318c05f8e69ee09694754885d33a835a849cafe56f499a2f49f6cda413ddf9a7", - "0xb18105cc736787fafaf7c3c11c448bce9466e683159dff52723b7951dff429565e466e4841d982e3aaa9ee2066838666", - "0x97ab9911f3f659691762d568ae0b7faa1047b0aed1009c319fa79d15d0db8db9f808fc385dc9a68fa388c10224985379", - "0xb2a2cba65f5b927e64d2904ba412e2bac1cf18c9c3eda9c72fb70262497ecf505b640827e2afebecf10eebbcf48ccd3e", - "0xb36a3fd677baa0d3ef0dac4f1548ff50a1730286b8c99d276a0a45d576e17b39b3cbadd2fe55e003796d370d4be43ce3", - "0xa5dfec96ca3c272566e89dc453a458909247e3895d3e44831528130bc47cc9d0a0dac78dd3cad680a4351d399d241967", - "0x8029382113909af6340959c3e61db27392531d62d90f92370a432aec3eb1e4c36ae1d4ef2ba8ec6edb4d7320c7a453f6", - "0x971d85121ea108e6769d54f9c51299b0381ece8b51d46d49c89f65bedc123bab4d5a8bc14d6f67f4f680077529cbae4c", - "0x98ff6afc01d0bec80a278f25912e1b1ebff80117adae72e31d5b9fa4d9624db4ba2065b444df49b489b0607c45e26c4c", - "0x8fa29be10fb3ab30ce25920fec0187e6e91e458947009dabb869aade7136c8ba23602682b71e390c251f3743164cbdaa", - "0xb3345c89eb1653418fe3940cf3e56a9a9c66526389b98f45ca02dd62bfb37baa69a4baaa7132d7320695f8ea6ad1fd94", - "0xb72c7f5541c9ac6b60a7ec9f5415e7fb14da03f7164ea529952a29399f3a071576608dbbcc0d45994f21f92ddbeb1e19", - "0xaa3450bb155a5f9043d0ef95f546a2e6ade167280bfb75c9f09c6f9cdb1fffb7ce8181436161a538433afa3681c7a141", - "0x92a18fecaded7854b349f441e7102b638ababa75b1b0281dd0bded6541abe7aa37d96693595be0b01fe0a2e2133d50f9", - "0x980756ddf9d2253cfe6c94960b516c94889d09e612810935150892627d2ecee9a2517e04968eea295d0106850c04ca44", - "0xae68c6ccc454318cdd92f32b11d89116a3b8350207a36d22a0f626718cad671d960090e054c0c77ac3162ae180ecfd4b", - "0x99f31f66eaaa551749ad91d48a0d4e3ff4d82ef0e8b28f3184c54e852422ba1bdafd53b1e753f3a070f3b55f3c23b6a2", - "0xa44eaeaa6589206069e9c0a45ff9fc51c68da38d4edff1d15529b7932e6f403d12b9387019c44a1488a5d5f27782a51f", - "0xb80b5d54d4b344840e45b79e621bd77a3f83fb4ce6d8796b7d6915107b3f3c34d2e7d95bdafd120f285669e5acf2437a", - "0xb36c069ec085a612b5908314d6b84c00a83031780261d1c77a0384c406867c9847d5b0845deddfa512cc04a8df2046fb", - "0xb09dbe501583220f640d201acea7ee3e39bf9eda8b91aa07b5c50b7641d86d71acb619b38d27835ce97c3759787f08e9", - "0x87403d46a2bf63170fff0b857acacf42ee801afe9ccba8e5b4aea967b68eac73a499a65ca46906c2eb4c8f27bc739faa", - "0x82b93669f42a0a2aa5e250ffe6097269da06a9c02fcd1801abbad415a7729a64f830754bafc702e64600ba47671c2208", - "0x8e3a3029be7edb8dd3ab1f8216664c8dc50d395f603736061d802cef77627db7b859ef287ed850382c13b4d22d6a2d80", - "0x968e9ec7194ff424409d182ce0259acd950c384c163c04463bc8700a40b79beba6146d22b7fa7016875a249b7b31c602", - "0x8b42c984bbe4996e0c20862059167c6bdc5164b1ffcd928f29512664459212d263e89f0f0e30eed4e672ffa5ed0b01b5", - "0x96bac54062110dada905363211133f1f15dc7e4fd80a4c6e4a83bc9a0bcbbaba11cd2c7a13debcf0985e1a954c1da66b", - "0xa16dc8a653d67a7cd7ae90b2fffac0bf1ca587005430fe5ba9403edd70ca33e38ba5661d2ed6e9d2864400d997626a62", - "0xa68ab11a570a27853c8d67e491591dcba746bfbee08a2e75ae0790399130d027ed387f41ef1d7de8df38b472df309161", - "0x92532b74886874447c0300d07eda9bbe4b41ed25349a3da2e072a93fe32c89d280f740d8ff70d5816793d7f2b97373cc", - "0x88e35711b471e89218fd5f4d0eadea8a29405af1cd81974427bc4a5fb26ed60798daaf94f726c96e779b403a2cd82820", - "0xb5c72aa4147c19f8c4f3a0a62d32315b0f4606e0a7025edc5445571eaf4daff64f4b7a585464821574dd50dbe1b49d08", - "0x9305d9b4095258e79744338683fd93f9e657367b3ab32d78080e51d54eec331edbc224fad5093ebf8ee4bd4286757eb8", - "0xb2a17abb3f6a05bcb14dc7b98321fa8b46d299626c73d7c6eb12140bf4c3f8e1795250870947af817834f033c88a59d6", - "0xb3477004837dbd8ba594e4296f960fc91ab3f13551458445e6c232eb04b326da803c4d93e2e8dcd268b4413305ff84da", - "0x924b4b2ebaafdcfdfedb2829a8bf46cd32e1407d8d725a5bd28bdc821f1bafb3614f030ea4352c671076a63494275a3f", - "0x8b81b9ef6125c82a9bece6fdcb9888a767ac16e70527753428cc87c56a1236e437da8be4f7ecfe57b9296dc3ae7ba807", - "0x906e19ec8b8edd58bdf9ae05610a86e4ea2282b1bbc1e8b00b7021d093194e0837d74cf27ac9916bdb8ec308b00da3da", - "0xb41c5185869071760ac786078a57a2ab4e2af60a890037ac0c0c28d6826f15c2cf028fddd42a9b6de632c3d550bfbc14", - "0xa646e5dec1b713ae9dfdf7bdc6cd474d5731a320403c7dfcfd666ffc9ae0cff4b5a79530e8df3f4aa9cb80568cb138e9", - "0xb0efad22827e562bd3c3e925acbd0d9425d19057868608d78c2209a531cccd0f2c43dc5673acf9822247428ffa2bb821", - "0xa94c19468d14b6f99002fc52ac06bbe59e5c472e4a0cdb225144a62f8870b3f10593749df7a2de0bd3c9476ce682e148", - "0x803864a91162f0273d49271dafaab632d93d494d1af935aefa522768af058fce52165018512e8d6774976d52bd797e22", - "0xa08711c2f7d45c68fb340ac23597332e1bcaec9198f72967b9921204b9d48a7843561ff318f87908c05a44fc35e3cc9d", - "0x91c3cad94a11a3197ae4f9461faab91a669e0dddb0371d3cab3ed9aeb1267badc797d8375181130e461eadd05099b2a2", - "0x81bdaaf48aae4f7b480fc13f1e7f4dd3023a41439ba231760409ce9292c11128ab2b0bdbbf28b98af4f97b3551f363af", - "0x8d60f9df9fd303f625af90e8272c4ecb95bb94e6efc5da17b8ab663ee3b3f673e9f6420d890ccc94acf4d2cae7a860d8", - "0xa7b75901520c06e9495ab983f70b61483504c7ff2a0980c51115d11e0744683ce022d76e3e09f4e99e698cbd21432a0d", - "0x82956072df0586562fda7e7738226f694e1c73518dd86e0799d2e820d7f79233667192c9236dcb27637e4c65ef19d493", - "0xa586beb9b6ffd06ad200957490803a7cd8c9bf76e782734e0f55e04a3dc38949de75dc607822ec405736c576cf83bca3", - "0xa179a30d00def9b34a7e85607a447eea0401e32ab5abeee1a281f2acd1cf6ec81a178020666f641d9492b1bdf66f05a3", - "0x83e129705c538787ed8e0fdc1275e6466a3f4ee21a1e6abedd239393b1df72244723b92f9d9d9339a0cab6ebf28f5a16", - "0x811bd8d1e3722b64cd2f5b431167e7f91456e8bba2cc669d3fbbce7d553e29c3c19f629fcedd2498bc26d33a24891d17", - "0xa243c030c858f1f60cccd26b45b024698cc6d9d9e6198c1ed4964a235d9f8d0baf9cde10c8e63dfaa47f8e74e51a6e85", - "0xab839eb82e23ca52663281f863b55b0a3d6d4425c33ffb4eeb1d7979488ab068bf99e2a60e82cea4dc42c56c26cbfebe", - "0x8b896f9bb21d49343e67aec6ad175b58c0c81a3ca73d44d113ae4354a0065d98eb1a5cafedaf232a2bb9cdc62152f309", - "0xaf6230340cc0b66f5bf845540ed4fc3e7d6077f361d60762e488d57834c3e7eb7eacc1b0ed73a7d134f174a01410e50c", - "0x88975e1b1af678d1b5179f72300a30900736af580dd748fd9461ef7afccc91ccd9bed33f9da55c8711a7635b800e831f", - "0xa97486bb9047391661718a54b8dd5a5e363964e495eae6c692730264478c927cf3e66dd3602413189a3699fbeae26e15", - "0xa5973c161ab38732885d1d2785fd74bf156ba34881980cba27fe239caef06b24a533ffe6dbbbeca5e6566682cc00300a", - "0xa24776e9a840afda0003fa73b415d5bd6ecd9b5c2cc842b643ee51b8c6087f4eead4d0bfbd987eb174c489a7b952ff2a", - "0xa8a6ee06e3af053b705a12b59777267c546f33ba8a0f49493af8e6df4e15cf8dd2d4fb4daf7e84c6b5d3a7363118ff03", - "0xa28e59ce6ad02c2ce725067c0123117e12ac5a52c8f5af13eec75f4a9efc4f696777db18a374fa33bcae82e0734ebd16", - "0x86dfc3b78e841c708aff677baa8ee654c808e5d257158715097c1025d46ece94993efe12c9d188252ad98a1e0e331fec", - "0xa88d0275510f242eab11fdb0410ff6e1b9d7a3cbd3658333539815f1b450a84816e6613d15aa8a8eb15d87cdad4b27a2", - "0x8440acea2931118a5b481268ff9f180ee4ede85d14a52c026adc882410825b8275caa44aff0b50c2b88d39f21b1a0696", - "0xa7c3182eab25bd6785bacf12079d0afb0a9b165d6ed327814e2177148539f249eb9b5b2554538f54f3c882d37c0a8abe", - "0x85291fbe10538d7da38efdd55a7acebf03b1848428a2f664c3ce55367aece60039f4f320b1771c9c89a35941797f717c", - "0xa2c6414eeb1234728ab0de94aa98fc06433a58efa646ca3fcbd97dbfb8d98ae59f7ce6d528f669c8149e1e13266f69c9", - "0x840c8462785591ee93aee2538d9f1ec44ba2ca61a569ab51d335ac873f5d48099ae8d7a7efa0725d9ff8f9475bfa4f56", - "0xa7065a9d02fb3673acf7702a488fbc01aa69580964932f6f40b6c2d1c386b19e50b0e104fcac24ea26c4e723611d0238", - "0xb72db6d141267438279e032c95e6106c2ccb3164b842ba857a2018f3a35f4b040da92680881eb17cd61d0920d5b8f006", - "0xa8005d6c5960e090374747307ef0be2871a7a43fa4e76a16c35d2baab808e9777b496e9f57a4218b23390887c33a0b55", - "0x8e152cea1e00a451ca47c20a1e8875873419700af15a5f38ee2268d3fbc974d4bd5f4be38008fa6f404dbdedd6e6e710", - "0xa3391aed1fcd68761f06a7d1008ec62a09b1cb3d0203cd04e300a0c91adfed1812d8bc1e4a3fd7976dc0aae0e99f52f1", - "0x967eb57bf2aa503ee0c6e67438098149eac305089c155f1762cf5e84e31f0fbf27c34a9af05621e34645c1ec96afaec8", - "0x88af97ddc4937a95ec0dcd25e4173127260f91c8db2f6eac84afb789b363705fb3196235af631c70cafd09411d233589", - "0xa32df75b3f2c921b8767638fd289bcfc61e08597170186637a7128ffedd52c798c434485ac2c7de07014f9e895c2c3d8", - "0xb0a783832153650aa0d766a3a73ec208b6ce5caeb40b87177ffc035ab03c7705ecdd1090b6456a29f5fb7e90e2fa8930", - "0xb59c8e803b4c3486777d15fc2311b97f9ded1602fa570c7b0200bada36a49ee9ef4d4c1474265af8e1c38a93eb66b18b", - "0x982f2c85f83e852022998ff91bafbb6ff093ef22cf9d5063e083a48b29175ccbd51b9c6557151409e439096300981a6c", - "0x939e3b5989fefebb9d272a954659a4eb125b98c9da6953f5e628d26266bd0525ec38304b8d56f08d65abc4d6da4a8dbb", - "0x8898212fe05bc8de7d18503cb84a1c1337cc2c09d1eeef2b475aa79185b7322bf1f8e065f1bf871c0c927dd19faf1f6d", - "0x94b0393a41cd00f724aee2d4bc72103d626a5aecb4b5486dd1ef8ac27528398edf56df9db5c3d238d8579af368afeb09", - "0x96ac564450d998e7445dd2ea8e3fc7974d575508fa19e1c60c308d83b645864c029f2f6b7396d4ff4c1b24e92e3bac37", - "0x8adf6638e18aff3eb3b47617da696eb6c4bdfbecbbc3c45d3d0ab0b12cbad00e462fdfbe0c35780d21aa973fc150285e", - "0xb53f94612f818571b5565bbb295e74bada9b5f9794b3b91125915e44d6ddcc4da25510eab718e251a09c99534d6042d9", - "0x8b96462508d77ee083c376cd90807aebad8de96bca43983c84a4a6f196d5faf6619a2351f43bfeec101864c3bf255519", - "0xaeadf34657083fc71df33bd44af73bf5281c9ca6d906b9c745536e1819ea90b56107c55e2178ebad08f3ba75b3f81c86", - "0x9784ba29b2f0057b5af1d3ab2796d439b8753f1f749c73e791037461bdfc3f7097394283105b8ab01788ea5255a96710", - "0x8756241bda159d4a33bf74faba0d4594d963c370fb6a18431f279b4a865b070b0547a6d1613cf45b8cfb5f9236bbf831", - "0xb03ebfd6b71421dfd49a30460f9f57063eebfe31b9ceaa2a05c37c61522b35bdc09d7db3ad75c76c253c00ba282d3cd2", - "0xb34e7e6341fa9d854b2d3153bdda0c4ae2b2f442ab7af6f99a0975d45725aa48e36ae5f7011edd249862e91f499687d4", - "0xb462ee09dc3963a14354244313e3444de5cc37ea5ccfbf14cd9aca8027b59c4cb2a949bc30474497cab8123e768460e6", - "0xaea753290e51e2f6a21a9a0ee67d3a2713f95c2a5c17fe41116c87d3aa77b1683761264d704df1ac34f8b873bc88ef7b", - "0x98430592afd414394f98ddfff9f280fcb1c322dbe3510f45e1e9c4bb8ee306b3e0cf0282c0ee73ebb8ba087d4d9e0858", - "0xb95d3b5aaf54ffca11f4be8d57f76e14afdb20afc859dc7c7471e0b42031e8f3d461b726ecb979bdb2f353498dfe95ea", - "0x984d17f9b11a683132e0b5a9ee5945e3ff7054c2d5c716be73b29078db1d36f54c6e652fd2f52a19da313112e97ade07", - "0xab232f756b3fff3262be418a1af61a7e0c95ceebbc775389622a8e10610508cd6784ab7960441917a83cc191c58829ea", - "0xa28f41678d6e60de76b0e36ab10e4516e53e02e9c77d2b5af3cfeee3ce94cfa30c5797bd1daab20c98e1cad83ad0f633", - "0xb55395fca84dd3ccc05dd480cb9b430bf8631ff06e24cb51d54519703d667268c2f8afcde4ba4ed16bece8cc7bc8c6e0", - "0x8a8a5392a0e2ea3c7a8c51328fab11156004e84a9c63483b64e8f8ebf18a58b6ffa8fe8b9d95af0a2f655f601d096396", - "0xab480000fe194d23f08a7a9ec1c392334e9c687e06851f083845121ce502c06b54dda8c43092bcc1035df45cc752fe9b", - "0xb265644c29f628d1c7e8e25a5e845cabb21799371814730a41a363e1bda8a7be50fee7c3996a365b7fcba4642add10db", - "0xb8a915a3c685c2d4728f6931c4d29487cad764c5ce23c25e64b1a3259ac27235e41b23bfe7ae982921b4cb84463097df", - "0x8efa7338442a4b6318145a5440fc213b97869647eeae41b9aa3c0a27ee51285b73e3ae3b4a9423df255e6add58864aa9", - "0x9106d65444f74d217f4187dfc8fcf3810b916d1e4275f94f6a86d1c4f3565b131fd6cde1fa708bc05fe183c49f14941a", - "0x948252dac8026bbbdb0a06b3c9d66ec4cf9532163bab68076fda1bd2357b69e4b514729c15aaa83b5618b1977bbc60c4", - "0xae6596ccfdf5cbbc5782efe3bb0b101bb132dbe1d568854ca24cacc0b2e0e9fabcb2ca7ab42aecec412efd15cf8cb7a2", - "0x84a0b6c198ff64fd7958dfd1b40eac9638e8e0b2c4cd8cf5d8cdf80419baee76a05184bce6c5b635f6bf2d30055476a7", - "0x8893118be4a055c2b3da593dbca51b1ae2ea2469911acfb27ee42faf3e6c3ad0693d3914c508c0b05b36a88c8b312b76", - "0xb097479e967504deb6734785db7e60d1d8034d6ca5ba9552887e937f5e17bb413fccac2c1d1082154ed76609127860ad", - "0xa0294e6b9958f244d29943debf24b00b538b3da1116269b6e452bb12dc742226712fd1a15b9c88195afeb5d2415f505c", - "0xb3cc15f635080bc038f61b615f62b5b5c6f2870586191f59476e8368a73641d6ac2f7d0c1f54621982defdb318020230", - "0x99856f49b9fe1604d917c94d09cc0ed753d13d015d30587a94e6631ffd964b214e607deb8a69a8b5e349a7edf4309206", - "0xa8571e113ea22b4b4fce41a094da8c70de37830ae32e62c65c2fa5ad06a9bc29e884b945e73d448c72b176d6ecebfb58", - "0xa9e9c6e52beb0013273c29844956b3ce291023678107cdc785f7b44eff5003462841ad8780761b86aefc6b734adde7cf", - "0x80a784b0b27edb51ef2bad3aee80e51778dcaa0f3f5d3dcb5dc5d4f4b2cf7ae35b08de6680ea9dac53f8438b92eb09ef", - "0x827b543e609ea328e97e373f70ad72d4915a2d1daae0c60d44ac637231070e164c43a2a58db80a64df1c624a042b38f9", - "0xb449c65e8195202efdcb9bdb4e869a437313b118fef8b510cbbf8b79a4e99376adb749b37e9c20b51b31ed3310169e27", - "0x8ea3028f4548a79a94c717e1ed28ad4d8725b8d6ab18b021063ce46f665c79da3c49440c6577319dab2d036b7e08f387", - "0x897798431cfb17fe39f08f5f854005dc37b1c1ec1edba6c24bc8acb3b88838d0534a75475325a5ea98b326ad47dbad75", - "0x89cf232e6303b0751561960fd4dea5754a28c594daf930326b4541274ffb03c7dd75938e411eb9a375006a70ce38097f", - "0x9727c6ae7f0840f0b6c8bfb3a1a5582ceee705e0b5c59b97def7a7a2283edd4d3f47b7971e902a3a2079e40b53ff69b8", - "0xb76ed72b122c48679d221072efc0eeea063cb205cbf5f9ef0101fd10cb1075b8628166c83577cced654e1c001c7882f7", - "0xae908c42d208759da5ee9b405df85a6532ea35c6f0f6a1288d22870f59d98edc896841b8ac890a538e6c8d1e8b02d359", - "0x809d12fe4039a0ec80dc9be6a89acaab7797e5f7f9b163378f52f9a75a1d73b2e9ae6e3dd49e32ced439783c1cabbef5", - "0xa4149530b7f85d1098ba534d69548c6c612c416e8d35992fc1f64f4deeb41e09e49c6cf7aadbed7e846b91299358fe2d", - "0xa49342eacd1ec1148b8df1e253b1c015f603c39de11fa0a364ccb86ea32d69c34fd7aa6980a1fadcd8e785a57fa46f60", - "0x87d43eff5a006dc4dddcf76cc96c656a1f3a68f19f124181feab86c6cc9a52cb9189cdbb423414defdd9bb0ca8ff1ddc", - "0x861367e87a9aa2f0f68296ba50aa5dbc5713008d260cc2c7e62d407c2063064749324c4e8156dc21b749656cfebce26b", - "0xb5303c2f72e84e170e66ae1b0fbd51b8c7a6f27476eaf5694b64e8737d5c84b51fe90100b256465a4c4156dd873cddb0", - "0xb62849a4f891415d74f434cdc1d23c4a69074487659ca96e1762466b2b7a5d8525b056b891d0feea6fe6845cba8bc7fb", - "0x923dd9e0d6590a9307e8c4c23f13bae3306b580e297a937711a8b13e8de85e41a61462f25b7d352b682e8437bf2b4ab3", - "0x9147379860cd713cd46c94b8cdf75125d36c37517fbecf81ace9680b98ce6291cd1c3e472f84249cc3b2b445e314b1b6", - "0xa808a4f17ac21e3fb5cfef404e61fae3693ca3e688d375f99b6116779696059a146c27b06de3ac36da349b0649befd56", - "0x87787e9322e1b75e66c1f0d9ea0915722a232770930c2d2a95e9478c4b950d15ab767e30cea128f9ed65893bfc2d0743", - "0x9036a6ee2577223be105defe1081c48ea7319e112fff9110eb9f61110c319da25a6cea0464ce65e858635b079691ef1f", - "0xaf5548c7c24e1088c23b57ee14d26c12a83484c9fd9296edf1012d8dcf88243f20039b43c8c548c265ef9a1ffe9c1c88", - "0xa0fff520045e14065965fb8accd17e878d3fcaf9e0af2962c8954e50be6683d31fa0bf4816ab68f08630dbac6bfce52a", - "0xb4c1b249e079f6ae1781af1d97a60b15855f49864c50496c09c91fe1946266915b799f0406084d7783f5b1039116dd8b", - "0x8b0ffa5e7c498cb3879dddca34743b41eee8e2dea3d4317a6e961b58adb699ef0c92400c068d5228881a2b08121226bf", - "0x852ae8b19a1d80aa8ae5382e7ee5c8e7670ceb16640871c56b20b96b66b3b60e00015a3dde039446972e57b49a999ddd", - "0xa49942f04234a7d8492169da232cfff8051df86e8e1ba3db46aede02422c689c87dc1d99699c25f96cb763f5ca0983e5", - "0xb04b597b7760cf5dcf411ef896d1661e6d5b0db3257ac2cf64b20b60c6cc18fa10523bb958a48d010b55bac7b02ab3b1", - "0xa494591b51ea8285daecc194b5e5bd45ae35767d0246ac94fae204d674ee180c8e97ff15f71f28b7aeb175b8aea59710", - "0x97d2624919e78406e7460730680dea8e71c8571cf988e11441aeea54512b95bd820e78562c99372d535d96f7e200d20d", - "0xac693ddb00e48f76e667243b9b6a7008424043fb779e4f2252330285232c3fccac4da25cbd6d95fe9ad959ff305a91f6", - "0x8d20ca0a71a64a3f702a0825bb46bd810d03bebfb227683680d474a52f965716ff99e19a165ebaf6567987f4f9ee3c94", - "0xa5c516a438f916d1d68ca76996404792e0a66e97b7f18fc54c917bf10cf3211b62387932756e39e67e47b0bd6e88385a", - "0xb089614d830abc0afa435034cec7f851f2f095d479cacf1a3fb57272da826c499a52e7dcbc0eb85f4166fb94778e18e9", - "0xa8dacc943765d930848288192f4c69e2461c4b9bc6e79e30eeef9a543318cf9ae9569d6986c65c5668a89d49993f8e07", - "0xab5a9361fa339eec8c621bdad0a58078983abd8942d4282b22835d7a3a47e132d42414b7c359694986f7db39386c2e19", - "0x94230517fb57bd8eb26c6f64129b8b2abd0282323bf7b94b8bac7fab27b4ecc2c4290c294275e1a759de19f2216134f3", - "0xb8f158ea5006bc3b90b285246625faaa6ac9b5f5030dc69701b12f3b79a53ec7e92eeb5a63bbd1f9509a0a3469ff3ffc", - "0x8b6944fd8cb8540957a91a142fdcda827762aa777a31e8810ca6d026e50370ee1636fc351724767e817ca38804ebe005", - "0x82d1ee40fe1569c29644f79fa6c4033b7ed45cd2c3b343881f6eb0de2e79548fded4787fae19bed6ee76ed76ff9f2f11", - "0xa8924c7035e99eaed244ca165607e7e568b6c8085510dcdbaf6ebdbed405af2e6c14ee27d94ffef10d30aa52a60bf66d", - "0x956f82a6c2ae044635e85812581e4866c5fa2f427b01942047d81f6d79a14192f66fbbe77c9ffeaef4e6147097fdd2b5", - "0xb1100255a1bcf5e05b6aff1dfeb6e1d55b5d68d43a7457ba10cc76b61885f67f4d0d5179abda786e037ae95deb8eea45", - "0x99510799025e3e5e8fbf06dedb14c060c6548ba2bda824f687d3999dc395e794b1fb6514b9013f3892b6cf65cb0d65aa", - "0x8f9091cebf5e9c809aab415942172258f894e66e625d7388a05289183f01b8d994d52e05a8e69f784fba41db9ea357f0", - "0xa13d2eeb0776bdee9820ecb6693536720232848c51936bb4ef4fe65588d3f920d08a21907e1fdb881c1ad70b3725e726", - "0xa68b8f18922d550284c5e5dc2dda771f24c21965a6a4d5e7a71678178f46df4d8a421497aad8fcb4c7e241aba26378a0", - "0x8b7601f0a3c6ad27f03f2d23e785c81c1460d60100f91ea9d1cab978aa03b523150206c6d52ce7c7769c71d2c8228e9e", - "0xa8e02926430813caa851bb2b46de7f0420f0a64eb5f6b805401c11c9091d3b6d67d841b5674fa2b1dce0867714124cd8", - "0xb7968ecba568b8193b3058400af02c183f0a6df995a744450b3f7e0af7a772454677c3857f99c140bbdb2a09e832e8e0", - "0x8f20b1e9ba87d0a3f35309b985f3c18d2e8800f1ca7f0c52cadef773f1496b6070c936eea48c4a1cae83fd2524e9d233", - "0x88aef260042db0d641a51f40639dbeeefa9e9811df30bee695f3791f88a2f84d318f04e8926b7f47bf25956cb9e3754f", - "0x9725345893b647e9ba4e6a29e12f96751f1ae25fcaec2173e9a259921a1a7edb7a47159b3c8767e44d9e2689f5aa0f72", - "0x8c281e6f72752cb11e239e4df9341c45106eb7993c160e54423c2bffe10bc39d42624b45a1f673936ef2e1a02fc92f1a", - "0x90aba2f68bddb2fcce6c51430dacdfeec43ea8dc379660c99095df11017691ccf5faa27665cf4b9f0eea7728ae53c327", - "0xb7022695c16521c5704f49b7ddbdbec9b5f57ce0ceebe537bc0ebb0906d8196cc855a9afeb8950a1710f6a654464d93f", - "0x8fe1b9dd3c6a258116415d36e08374e094b22f0afb104385a5da48be17123e86fb8327baacc4f0d9ebae923d55d99bb5", - "0x817e85d8e3d19a4cbc1dec31597142c2daa4871bda89c2177fa719c00eda3344eb08b82eb92d4aa91a9eaacb3fc09783", - "0xb59053e1081d2603f1ca0ba553804d6fa696e1fd996631db8f62087b26a40dfef02098b0326bb75f99ec83b9267ca738", - "0x990a173d857d3ba81ff3789b931bfc9f5609cde0169b7f055fa3cb56451748d593d62d46ba33f80f9cafffe02b68dd14", - "0xb0c538dbba4954b809ab26f9f94a3cf1dcb77ce289eaec1d19f556c0ae4be1fa03af4a9b7057837541c3cc0a80538736", - "0xac3ba42f5f44f9e1fc453ce49c4ab79d0e1d5c42d3b30b1e098f3ab3f414c4c262fa12fb2be249f52d4aaf3c5224beb9", - "0xaf47467eb152e59870e21f0d4da2f43e093daf40180ab01438030684b114d025326928eaab12c41b81a066d94fce8436", - "0x98d1b58ba22e7289b1c45c79a24624f19b1d89e00f778eef327ec4856a9a897278e6f1a9a7e673844b31dde949153000", - "0x97ccb15dfadc7c59dca08cfe0d22df2e52c684cf97de1d94bc00d7ba24e020025130b0a39c0f4d46e4fc872771ee7875", - "0xb699e4ed9a000ff96ca296b2f09dce278832bc8ac96851ff3cff99ed3f6f752cfc0fea8571be28cd9b5a7ec36f1a08ee", - "0xb9f49f0edb7941cc296435ff0a912e3ad16848ee8765ab5f60a050b280d6ea585e5b34051b15f6b8934ef01ceb85f648", - "0xac3893df7b4ceab23c6b9054e48e8ba40d6e5beda8fbe90b814f992f52494186969b35d8c4cdc3c99890a222c9c09008", - "0xa41293ad22fae81dea94467bc1488c3707f3d4765059173980be93995fa4fcc3c9340796e3eed0beeb0ba0d9bb4fa3aa", - "0xa0543e77acd2aeecde13d18d258aeb2c7397b77f17c35a1992e8666ea7abcd8a38ec6c2741bd929abba2f766138618cc", - "0x92e79b22bc40e69f6527c969500ca543899105837b6b1075fa1796755c723462059b3d1b028e0b3df2559fa440e09175", - "0xa1fa1eac8f41a5197a6fb4aa1eae1a031c89f9c13ff9448338b222780cf9022e0b0925d930c37501a0ef7b2b00fdaf83", - "0xb3cb29ff73229f0637335f28a08ad8c5f166066f27c6c175164d0f26766a927f843b987ee9b309ed71cbf0a65d483831", - "0x84d4ab787f0ac00f104f4a734dc693d62d48c2aeb03913153da62c2ae2c27d11b1110dcef8980368dd84682ea2c1a308", - "0xab6a8e4bbc78d4a7b291ad3e9a8fe2d65f640524ba3181123b09d2d18a9e300e2509ccf7000fe47e75b65f3e992a2e7e", - "0xb7805ebe4f1a4df414003dc10bca805f2ab86ca75820012653e8f9b79c405196b0e2cab099f2ab953d67f0d60d31a0f9", - "0xb12c582454148338ea605d22bd00a754109063e22617f1f8ac8ddf5502c22a181c50c216c3617b9852aa5f26af56b323", - "0x86333ad9f898947e31ce747728dc8c887479e18d36ff3013f69ebef807d82c6981543b5c3788af93c4d912ba084d3cba", - "0xb514efa310dc4ad1258add138891e540d8c87142a881b5f46563cc58ecd1488e6d3a2fca54c0b72a929f3364ca8c333e", - "0xaa0a30f92843cf2f484066a783a1d75a7aa6f41f00b421d4baf20a6ac7886c468d0eea7ca8b17dd22f4f74631b62b640", - "0xb3b7dc63baec9a752e8433c0cdee4d0f9bc41f66f2b8d132faf925eef9cf89aae756fc132c45910f057122462605dc10", - "0xb9b8190dac5bfdeb59fd44f4da41a57e7f1e7d2c21faba9da91fa45cbeca06dcf299c9ae22f0c89ece11ac46352d619f", - "0x89f8cf36501ad8bdfeab863752a9090e3bfda57cf8fdeca2944864dc05925f501e252c048221bcc57136ab09a64b64b2", - "0xb0cbfaf317f05f97be47fc9d69eda2dd82500e00d42612f271a1fe24626408c28881f171e855bd5bd67409f9847502b4", - "0xa7c21a8fcede581bfd9847b6835eda62ba250bea81f1bb17372c800a19c732abe03064e64a2f865d974fb636cab4b859", - "0x95f9df524ba7a4667351696c4176b505d8ea3659f5ff2701173064acc624af69a0fad4970963736383b979830cb32260", - "0x856a74fe8b37a2e3afeac858c8632200485d438422a16ae3b29f359e470e8244995c63ad79c7e007ed063f178d0306fd", - "0xb37faa4d78fdc0bb9d403674dbea0176c2014a171c7be8527b54f7d1a32a76883d3422a3e7a5f5fcc5e9b31b57822eeb", - "0x8d37234d8594ec3fe75670b5c9cc1ec3537564d4739b2682a75b18b08401869a4264c0f264354219d8d896cded715db4", - "0xb5289ee5737f0e0bde485d32096d23387d68dab8f01f47821ab4f06cc79a967afe7355e72dc0c751d96b2747b26f6255", - "0x9085e1fdf9f813e9c3b8232d3c8863cd84ab30d45e8e0d3d6a0abd9ebc6fd70cdf749ff4d04390000e14c7d8c6655fc7", - "0x93a388c83630331eca4da37ea4a97b3b453238af474817cc0a0727fd3138dcb4a22de38c04783ec829c22cb459cb4e8e", - "0xa5377116027c5d061dbe24c240b891c08cdd8cd3f0899e848d682c873aff5b8132c1e7cfe76d2e5ed97ee0eb1d42cb68", - "0xa274c84b04338ed28d74683e2a7519c2591a3ce37c294d6f6e678f7d628be2db8eff253ede21823e2df7183e6552f622", - "0x8bc201147a842453a50bec3ac97671397bc086d6dfc9377fa38c2124cdc286abda69b7324f47d64da094ae011d98d9d9", - "0x9842d0c066c524592b76fbec5132bc628e5e1d21c424bec4555efca8619cc1fd8ea3161febcb8b9e8ab54702f4e815e2", - "0xa19191b713a07efe85c266f839d14e25660ee74452e6c691cd9997d85ae4f732052d802d3deb018bdd847caa298a894b", - "0xa24f71fc0db504da4e287dd118a4a74301cbcd16033937ba2abc8417956fcb4ae19b8e63b931795544a978137eff51cb", - "0xa90eec4a6a3a4b8f9a5b93d978b5026fcf812fe65585b008d7e08c4aaf21195a1d0699f12fc16f79b6a18a369af45771", - "0x8b551cf89737d7d06d9b3b9c4c1c73b41f2ea0af4540999c70b82dabff8580797cf0a3caf34c86c59a7069eb2e38f087", - "0xb8d312e6c635e7a216a1cda075ae77ba3e1d2fd501dc31e83496e6e81ed5d9c7799f8e578869c2e0e256fb29f5de10a7", - "0x8d144bdb8cae0b2cdb5b33d44bbc96984a5925202506a8cc65eb67ac904b466f5a7fe3e1cbf04aa785bbb7348c4bb73c", - "0xa101b3d58b7a98659244b88de0b478b3fb87dc5fc6031f6e689b99edf498abd43e151fd32bd4bbd240e0b3e59c440359", - "0x907453abca7d8e7151a05cc3d506c988007692fe7401395dc93177d0d07d114ab6cca0cc658eb94c0223fe8658295cad", - "0x825329ffbe2147ddb68f63a0a67f32d7f309657b8e5d9ab5bb34b3730bfa2c77a23eaaadb05def7d9f94a9e08fdc1e96", - "0x88ee923c95c1dac99ae7ed6067906d734d793c5dc5d26339c1bb3314abe201c5dccb33b9007351885eb2754e9a8ea06c", - "0x98bc9798543f5f1adc9f2cfcfa72331989420e9c3f6598c45269f0dc9b7c8607bbeaf03faa0aea2ddde2b8f17fdceff5", - "0x8ee87877702a79aef923ab970db6fa81561b3c07d5bf1a072af0a7bad765b4cbaec910afe1a91703feacc7822fa38a94", - "0x8060b9584aa294fe8adc2b22f67e988bc6da768eae91e429dcc43ddc53cfcc5d6753fdc1b420b268c7eb2fb50736a970", - "0xb344a5524d80a2f051870c7001f74fcf348a70fcf78dbd20c6ff9ca85d81567d2318c8b8089f2c4f195d6aec9fc15fa6", - "0x8f5a5d893e1936ed062149d20eb73d98b62b7f50ab5d93a6429c03656b36688d1c80cb5010e4977491e51fa0d7dd35d5", - "0x86fa32ebbf97328c5f5f15564e1238297e289ec3219b9a741724e9f3ae8d5c15277008f555863a478b247ba5dc601d44", - "0x9557e55377e279f4b6b5e0ffe01eca037cc13aac242d67dfcd0374a1e775c5ed5cb30c25fe21143fee54e3302d34a3ea", - "0x8cb6bcbc39372d23464a416ea7039f57ba8413cf3f00d9a7a5b356ab20dcb8ed11b3561f7bce372b8534d2870c7ee270", - "0xb5d59075cb5abde5391f64b6c3b8b50adc6e1f654e2a580b6d6d6eff3f4fbdd8fffc92e06809c393f5c8eab37f774c4b", - "0xafcfb6903ef13e493a1f7308675582f15af0403b6553e8c37afb8b2808ad21b88b347dc139464367dc260df075fea1ad", - "0x810fbbe808375735dd22d5bc7fc3828dc49fdd22cc2d7661604e7ac9c4535c1df578780affb3b895a0831640a945bcad", - "0x8056b0c678803b416f924e09a6299a33cf9ad7da6fe1ad7accefe95c179e0077da36815fde3716711c394e2c5ea7127f", - "0x8b67403702d06979be19f1d6dc3ec73cc2e81254d6b7d0cc49cd4fdda8cd51ab0835c1d2d26fc0ecab5df90585c2f351", - "0x87f97f9e6d4be07e8db250e5dd2bffdf1390665bc5709f2b631a6fa69a7fca958f19bd7cc617183da1f50ee63e9352b5", - "0xae151310985940471e6803fcf37600d7fa98830613e381e00dab943aec32c14162d51c4598e8847148148000d6e5af5c", - "0x81eb537b35b7602c45441cfc61b27fa9a30d3998fad35a064e05bc9479e9f10b62eba2b234b348219eea3cadcaac64bb", - "0x8a441434934180ab6f5bc541f86ebd06eadbee01f438836d797e930fa803a51510e005c9248cecc231a775b74d12b5e9", - "0x81f3c250a27ba14d8496a5092b145629eb2c2e6a5298438670375363f57e2798207832c8027c3e9238ad94ecdadfc4df", - "0xa6217c311f2f3db02ceaa5b6096849fe92b6f4b6f1491535ef8525f6ccee6130bed2809e625073ecbaddd4a3eb3df186", - "0x82d1c396f0388b942cf22b119d7ef1ad03d3dad49a74d9d01649ee284f377c8daddd095d596871669e16160299a210db", - "0xa40ddf7043c5d72a7246bd727b07f7fff1549f0e443d611de6f9976c37448b21664c5089c57f20105102d935ab82f27b", - "0xb6c03c1c97adf0c4bf4447ec71366c6c1bff401ba46236cd4a33d39291e7a1f0bb34bd078ba3a18d15c98993b153a279", - "0x8a94f5f632068399c359c4b3a3653cb6df2b207379b3d0cdace51afdf70d6d5cce6b89a2b0fee66744eba86c98fb21c2", - "0xb2f19e78ee85073f680c3bba1f07fd31b057c00b97040357d97855b54a0b5accb0d3b05b2a294568fcd6a4be6f266950", - "0xa74632d13bbe2d64b51d7a9c3ae0a5a971c19f51cf7596a807cea053e6a0f3719700976d4e394b356c0329a2dced9aa2", - "0xafef616d341a9bc94393b8dfba68ff0581436aa3a3adb7c26a1bbf2cf19fa877066191681f71f17f3cd6f9cf6bf70b5a", - "0x8ce96d93ae217408acf7eb0f9cbb9563363e5c7002e19bbe1e80760bc9d449daee2118f3878b955163ed664516b97294", - "0x8414f79b496176bc8b8e25f8e4cfee28f4f1c2ddab099d63d2aca1b6403d26a571152fc3edb97794767a7c4686ad557c", - "0xb6c61d01fd8ce087ef9f079bf25bf10090db483dd4f88c4a786d31c1bdf52065651c1f5523f20c21e75cea17df69ab73", - "0xa5790fd629be70545093631efadddc136661f63b65ec682609c38ef7d3d7fa4e56bdf94f06e263bc055b90cb1c6bcefe", - "0xb515a767e95704fb7597bca9e46f1753abacdc0e56e867ee3c6f4cd382643c2a28e65312c05ad040eaa3a8cbe7217a65", - "0x8135806a02ead6aa92e9adb6fefb91349837ab73105aaa7be488ef966aa8dfaafdfa64bbae30fcbfa55dd135a036a863", - "0x8f22435702716d76b1369750694540742d909d5e72b54d0878245fab7c269953b1c6f2b29c66f08d5e0263ca3a731771", - "0x8e0f8a8e8753e077dac95848212aeffd51c23d9b6d611df8b102f654089401954413ecbedc6367561ca599512ae5dda7", - "0x815a9084e3e2345f24c5fa559deec21ee1352fb60f4025c0779be65057f2d528a3d91593bd30d3a185f5ec53a9950676", - "0x967e6555ccba395b2cc1605f8484c5112c7b263f41ce8439a99fd1c71c5ed14ad02684d6f636364199ca48afbbde13be", - "0x8cd0ccf17682950b34c796a41e2ea7dd5367aba5e80a907e01f4cdc611e4a411918215e5aebf4292f8b24765d73314a6", - "0xa58bf1bbb377e4b3915df6f058a0f53b8fb8130fdec8c391f6bc82065694d0be59bb67ffb540e6c42cc8b380c6e36359", - "0x92af3151d9e6bfb3383d85433e953c0160859f759b0988431ec5893542ba40288f65db43c78a904325ef8d324988f09d", - "0x8011bbb05705167afb47d4425065630f54cb86cd462095e83b81dfebf348f846e4d8fbcf1c13208f5de1931f81da40b9", - "0x81c743c104fc3cb047885c9fa0fb9705c3a83ee24f690f539f4985509c3dafd507af3f6a2128276f45d5939ef70c167f", - "0xa2c9679b151c041aaf5efeac5a737a8f70d1631d931609fca16be1905682f35e291292874cb3b03f14994f98573c6f44", - "0xa4949b86c4e5b1d5c82a337e5ce6b2718b1f7c215148c8bfb7e7c44ec86c5c9476048fc5c01f57cb0920876478c41ad6", - "0x86c2495088bd1772152e527a1da0ef473f924ea9ab0e5b8077df859c28078f73c4e22e3a906b507fdf217c3c80808b5c", - "0x892e0a910dcf162bcea379763c3e2349349e4cda9402949255ac4a78dd5a47e0bf42f5bd0913951576b1d206dc1e536a", - "0xa7009b2c6b396138afe4754b7cc10dee557c51c7f1a357a11486b3253818531f781ea8107360c8d4c3b1cd96282353c0", - "0x911763ef439c086065cc7b4e57484ed6d693ea44acee4b18c9fd998116da55fbe7dcb8d2a0f0f9b32132fca82d73dff6", - "0xa722000b95a4a2d40bed81870793f15ba2af633f9892df507f2842e52452e02b5ea8dea6a043c2b2611d82376e33742a", - "0x9387ac49477bd719c2f92240d0bdfcf9767aad247ca93dc51e56106463206bc343a8ec855eb803471629a66fffb565d6", - "0x92819a1fa48ab4902939bb72a0a4e6143c058ea42b42f9bc6cea5df45f49724e2530daf3fc4f097cceefa2a8b9db0076", - "0x98eac7b04537653bc0f4941aae732e4b1f84bd276c992c64a219b8715eb1fb829b5cbd997d57feb15c7694c468f95f70", - "0xb275e7ba848ce21bf7996e12dbeb8dadb5d0e4f1cb5a0248a4f8f9c9fe6c74e3c93f4b61edbcb0a51af5a141e1c14bc7", - "0x97243189285aba4d49c53770c242f2faf5fd3914451da4931472e3290164f7663c726cf86020f8f181e568c72fd172d1", - "0x839b0b3c25dd412bee3dc24653b873cc65454f8f16186bb707bcd58259c0b6765fa4c195403209179192a4455c95f3b8", - "0x8689d1a870514568a074a38232e2ceb4d7df30fabeb76cff0aed5b42bf7f02baea12c5fadf69f4713464dbd52aafa55f", - "0x8958ae7b290f0b00d17c3e9fdb4dbf168432b457c7676829299dd428984aba892de1966fc106cfc58a772862ecce3976", - "0xa422bc6bd68b8870cfa5bc4ce71781fd7f4368b564d7f1e0917f6013c8bbb5b240a257f89ecfdbecb40fe0f3aa31d310", - "0xaa61f78130cebe09bc9a2c0a37f0dd57ed2d702962e37d38b1df7f17dc554b1d4b7a39a44182a452ce4c5eb31fa4cfcc", - "0xb7918bd114f37869bf1a459023386825821bfadce545201929d13ac3256d92a431e34f690a55d944f77d0b652cefeffc", - "0x819bba35fb6ace1510920d4dcff30aa682a3c9af9022e287751a6a6649b00c5402f14b6309f0aeef8fce312a0402915e", - "0x8b7c9ad446c6f63c11e1c24e24014bd570862b65d53684e107ba9ad381e81a2eaa96731b4b33536efd55e0f055071274", - "0x8fe79b53f06d33386c0ec7d6d521183c13199498594a46d44a8a716932c3ec480c60be398650bbfa044fa791c4e99b65", - "0x9558e10fb81250b9844c99648cf38fa05ec1e65d0ccbb18aa17f2d1f503144baf59d802c25be8cc0879fff82ed5034ad", - "0xb538a7b97fbd702ba84645ca0a63725be1e2891c784b1d599e54e3480e4670d0025526674ef5cf2f87dddf2290ba09f0", - "0x92eafe2e869a3dd8519bbbceb630585c6eb21712b2f31e1b63067c0acb5f9bdbbcbdb612db4ea7f9cc4e7be83d31973f", - "0xb40d21390bb813ab7b70a010dff64c57178418c62685761784e37d327ba3cb9ef62df87ecb84277c325a637fe3709732", - "0xb349e6fbf778c4af35fbed33130bd8a7216ed3ba0a79163ebb556e8eb8e1a7dad3456ddd700dad9d08d202491c51b939", - "0xa8fdaedecb251f892b66c669e34137f2650509ade5d38fbe8a05d9b9184bb3b2d416186a3640429bd1f3e4b903c159dd", - "0xac6167ebfee1dbab338eff7642f5e785fc21ef0b4ddd6660333fe398068cbd6c42585f62e81e4edbb72161ce852a1a4f", - "0x874b1fbf2ebe140c683bd7e4e0ab017afa5d4ad38055aaa83ee6bbef77dbc88a6ce8eb0dcc48f0155244af6f86f34c2d", - "0x903c58e57ddd9c446afab8256a6bb6c911121e6ccfb4f9b4ed3e2ed922a0e500a5cb7fa379d5285bc16e11dac90d1fda", - "0x8dae7a0cffa2fd166859cd1bf10ff82dd1932e488af377366b7efc0d5dec85f85fe5e8150ff86a79a39cefc29631733a", - "0xaa047857a47cc4dfc08585f28640420fcf105b881fd59a6cf7890a36516af0644d143b73f3515ab48faaa621168f8c31", - "0x864508f7077c266cc0cb3f7f001cb6e27125ebfe79ab57a123a8195f2e27d3799ff98413e8483c533b46a816a3557f1f", - "0x8bcd45ab1f9cbab36937a27e724af819838f66dfeb15923f8113654ff877bd8667c54f6307aaf0c35027ca11b6229bfd", - "0xb21aa34da9ab0a48fcfdd291df224697ce0c1ebc0e9b022fdee8750a1a4b5ba421c419541ed5c98b461eecf363047471", - "0xa9a18a2ab2fae14542dc336269fe612e9c1af6cf0c9ac933679a2f2cb77d3c304114f4d219ca66fe288adde30716775b", - "0xb5205989b92c58bdda71817f9a897e84100b5c4e708de1fced5c286f7a6f01ae96b1c8d845f3a320d77c8e2703c0e8b1", - "0xa364059412bbcc17b8907d43ac8e5df90bc87fd1724b5f99832d0d24559fae6fa76a74cff1d1eac8cbac6ec80b44af20", - "0xae709f2c339886b31450834cf29a38b26eb3b0779bd77c9ac269a8a925d1d78ea3837876c654b61a8fe834b3b6940808", - "0x8802581bba66e1952ac4dab36af371f66778958f4612901d95e5cac17f59165e6064371d02de8fb6fccf89c6dc8bd118", - "0xa313252df653e29c672cbcfd2d4f775089cb77be1077381cf4dc9533790e88af6cedc8a119158e7da5bf6806ad9b91a1", - "0x992a065b4152c7ef11515cd54ba9d191fda44032a01aed954acff3443377ee16680c7248d530b746b8c6dee2d634e68c", - "0xb627b683ee2b32c1ab4ccd27b9f6cce2fe097d96386fa0e5c182ad997c4c422ab8dfc03870cd830b8c774feb66537282", - "0xb823cf8a9aee03dadd013eb9efe40a201b4b57ef67efaae9f99683005f5d1bf55e950bf4af0774f50859d743642d3fea", - "0xb8a7449ffac0a3f206677097baf7ce00ca07a4d2bd9b5356fbcb83f3649b0fda07cfebad220c1066afba89e5a52abf4b", - "0xb2dd1a2f986395bb4e3e960fbbe823dbb154f823284ebc9068502c19a7609790ec0073d08bfa63f71e30c7161b6ef966", - "0x98e5236de4281245234f5d40a25b503505af140b503a035fc25a26159a9074ec81512b28f324c56ea2c9a5aa7ce90805", - "0x89070847dc8bbf5bc4ed073aa2e2a1f699cf0c2ca226f185a0671cecc54e7d3e14cd475c7752314a7a8e7476829da4bc", - "0xa9402dc9117fdb39c4734c0688254f23aed3dce94f5f53f5b7ef2b4bf1b71a67f85ab1a38ec224a59691f3bee050aeb3", - "0x957288f9866a4bf56a4204218ccc583f717d7ce45c01ea27142a7e245ad04a07f289cc044f8cf1f21d35e67e39299e9c", - "0xb2fb31ccb4e69113763d7247d0fc8edaae69b550c5c56aecacfd780c7217dc672f9fb7496edf4aba65dacf3361268e5b", - "0xb44a4526b2f1d6eb2aa8dba23bfa385ff7634572ab2afddd0546c3beb630fbfe85a32f42dd287a7fec069041411537f7", - "0x8db5a6660c3ac7fd7a093573940f068ee79a82bc17312af900b51c8c439336bc86ca646c6b7ab13aaaa008a24ca508ab", - "0x8f9899a6d7e8eb4367beb5c060a1f8e94d8a21099033ae582118477265155ba9e72176a67f7f25d7bad75a152b56e21a", - "0xa67de0e91ade8d69a0e00c9ff33ee2909b8a609357095fa12319e6158570c232e5b6f4647522efb7345ce0052aa9d489", - "0x82eb2414898e9c3023d57907a2b17de8e7eea5269029d05a94bfd7bf5685ac4a799110fbb375eb5e0e2bd16acf6458ae", - "0x94451fc7fea3c5a89ba701004a9693bab555cb622caf0896b678faba040409fdfd14a978979038b2a81e8f0abc4994d2", - "0xac879a5bb433998e289809a4a966bd02b4bf6a9c1cc276454e39c886efcf4fc68baebed575826bde577ab5aa71d735a9", - "0x880c0f8f49c875dfd62b4ddedde0f5c8b19f5687e693717f7e5c031bc580e58e13ab497d48b4874130a18743c59fdce3", - "0xb582af8d8ff0bf76f0a3934775e0b54c0e8fed893245d7d89cae65b03c8125b7237edc29dc45b4fe1a3fe6db45d280ee", - "0x89f337882ed3ae060aaee98efa20d79b6822bde9708c1c5fcee365d0ec9297f694cae37d38fd8e3d49717c1e86f078e7", - "0x826d2c1faea54061848b484e288a5f4de0d221258178cf87f72e14baaa4acc21322f8c9eab5dde612ef497f2d2e1d60b", - "0xa5333d4f227543e9cd741ccf3b81db79f2f03ca9e649e40d6a6e8ff9073e06da83683566d3b3c8d7b258c62970fb24d1", - "0xa28f08c473db06aaf4c043a2fae82b3c8cfaa160bce793a4c208e4e168fb1c65115ff8139dea06453c5963d95e922b94", - "0x8162546135cc5e124e9683bdfaa45833c18553ff06a0861c887dc84a5b12ae8cd4697f6794c7ef6230492c32faba7014", - "0xb23f0d05b74c08d6a7df1760792be83a761b36e3f8ae360f3c363fb196e2a9dd2de2e492e49d36561366e14daa77155c", - "0xb6f70d6c546722d3907c708d630dbe289771d2c8bf059c2e32b77f224696d750b4dda9b3a014debda38e7d02c9a77585", - "0x83bf4c4a9f3ca022c631017e7a30ea205ba97f7f5927cba8fc8489a4646eac6712cb821c5668c9ffe94d69d524374a27", - "0xb0371475425a8076d0dd5f733f55aabbe42d20a7c8ea7da352e736d4d35a327b2beb370dfcb05284e22cfd69c5f6c4cc", - "0xa0031ba7522c79211416c2cca3aa5450f96f8fee711552a30889910970ba13608646538781a2c08b834b140aadd7166f", - "0x99d273c80c7f2dc6045d4ed355d9fc6f74e93549d961f4a3b73cd38683f905934d359058cd1fc4da8083c7d75070487f", - "0xb0e4b0efa3237793e9dcce86d75aafe9879c5fa23f0d628649aef2130454dcf72578f9bf227b9d2b9e05617468e82588", - "0xa5ab076fa2e1c5c51f3ae101afdd596ad9d106bba7882b359c43d8548b64f528af19afa76cd6f40da1e6c5fca4def3fa", - "0x8ce2299e570331d60f6a6eff1b271097cd5f1c0e1113fc69b89c6a0f685dabea3e5bc2ac6bd789aa492ab189f89be494", - "0x91b829068874d911a310a5f9dee001021f97471307b5a3de9ec336870ec597413e1d92010ce320b619f38bed7c4f7910", - "0xb14fe91f4b07bf33b046e9285b66cb07927f3a8da0af548ac2569b4c4fb1309d3ced76d733051a20814e90dd5b75ffd1", - "0xabaab92ea6152d40f82940277c725aa768a631ee0b37f5961667f82fb990fc11e6d3a6a2752b0c6f94563ed9bb28265c", - "0xb7fe28543eca2a716859a76ab9092f135337e28109544f6bd2727728d0a7650428af5713171ea60bfc273d1c821d992c", - "0x8a4917b2ab749fc7343fc64bdf51b6c0698ff15d740cc7baf248c030475c097097d5a473bcc00d8c25817563fe0447b4", - "0xaa96156d1379553256350a0a3250166add75948fb9cde62aa555a0a9dc0a9cb7f2f7b8428aff66097bf6bfedaf14bbe2", - "0xae4ffeb9bdc76830d3eca2b705f30c1bdede6412fa064260a21562c8850c7fb611ec62bc68479fe48f692833e6f66d8d", - "0xb96543caaba9d051600a14997765d49e4ab10b07c7a92cccf0c90b309e6da334fdd6d18c96806cbb67a7801024fbd3c7", - "0x97b2b9ad76f19f500fcc94ca8e434176249f542ac66e5881a3dccd07354bdab6a2157018b19f8459437a68d8b86ba8e0", - "0xa8d206f6c5a14c80005849474fde44b1e7bcf0b2d52068f5f97504c3c035b09e65e56d1cf4b5322791ae2c2fdbd61859", - "0x936bad397ad577a70cf99bf9056584a61bd7f02d2d5a6cf219c05d770ae30a5cd902ba38366ce636067fc1dd10108d31", - "0xa77e30195ee402b84f3882e2286bf5380c0ed374a112dbd11e16cef6b6b61ab209d4635e6f35cdaaa72c1a1981d5dabe", - "0xa46ba4d3947188590a43c180757886a453a0503f79cc435322d92490446f37419c7b999fdf868a023601078070e03346", - "0x80d8d4c5542f223d48240b445d4d8cf6a75d120b060bc08c45e99a13028b809d910b534d2ac47fb7068930c54efd8da9", - "0x803be9c68c91b42b68e1f55e58917a477a9a6265e679ca44ee30d3eb92453f8c89c64eafc04c970d6831edd33d066902", - "0xb14b2b3d0dfe2bb57cee4cd72765b60ac33c1056580950be005790176543826c1d4fbd737f6cfeada6c735543244ab57", - "0xa9e480188bba1b8fb7105ff12215706665fd35bf1117bacfb6ab6985f4dbc181229873b82e5e18323c2b8f5de03258e0", - "0xa66a0f0779436a9a3999996d1e6d3000f22c2cac8e0b29cddef9636393c7f1457fb188a293b6c875b05d68d138a7cc4a", - "0x848397366300ab40c52d0dbbdafbafef6cd3dadf1503bb14b430f52bb9724188928ac26f6292a2412bc7d7aa620763c8", - "0x95466cc1a78c9f33a9aaa3829a4c8a690af074916b56f43ae46a67a12bb537a5ac6dbe61590344a25b44e8512355a4a7", - "0x8b5f7a959f818e3baf0887f140f4575cac093d0aece27e23b823cf421f34d6e4ff4bb8384426e33e8ec7b5eed51f6b5c", - "0x8d5e1368ec7e3c65640d216bcc5d076f3d9845924c734a34f3558ac0f16e40597c1a775a25bf38b187213fbdba17c93b", - "0xb4647c1b823516880f60d20c5cc38c7f80b363c19d191e8992226799718ee26b522a12ecb66556ed3d483aa4824f3326", - "0xac3abaea9cd283eb347efda4ed9086ea3acf495043e08d0d19945876329e8675224b685612a6badf8fd72fb6274902b1", - "0x8eae1ce292d317aaa71bcf6e77e654914edd5090e2e1ebab78b18bb41b9b1bc2e697439f54a44c0c8aa0d436ebe6e1a9", - "0x94dc7d1aec2c28eb43d93b111fa59aaa0d77d5a09501220bd411768c3e52208806abf973c6a452fd8292ff6490e0c9e2", - "0x8fd8967f8e506fef27d17b435d6b86b232ec71c1036351f12e6fb8a2e12daf01d0ee04451fb944d0f1bf7fd20e714d02", - "0x824e6865be55d43032f0fec65b3480ea89b0a2bf860872237a19a54bc186a85d2f8f9989cc837fbb325b7c72d9babe2c", - "0x8bd361f5adb27fd6f4e3f5de866e2befda6a8454efeb704aacc606f528c03f0faae888f60310e49440496abd84083ce2", - "0xb098a3c49f2aaa28b6b3e85bc40ce6a9cdd02134ee522ae73771e667ad7629c8d82c393fba9f27f5416986af4c261438", - "0xb385f5ca285ff2cfe64dcaa32dcde869c28996ed091542600a0b46f65f3f5a38428cca46029ede72b6cf43e12279e3d3", - "0x8196b03d011e5be5288196ef7d47137d6f9237a635ab913acdf9c595fa521d9e2df722090ec7eb0203544ee88178fc5f", - "0x8ed1270211ef928db18e502271b7edf24d0bbd11d97f2786aee772d70c2029e28095cf8f650b0328cc8a4c38d045316d", - "0xa52ab60e28d69b333d597a445884d44fd2a7e1923dd60f763951e1e45f83e27a4dac745f3b9eff75977b3280e132c15d", - "0x91e9fe78cdac578f4a4687f71b800b35da54b824b1886dafec073a3c977ce7a25038a2f3a5b1e35c2c8c9d1a7312417c", - "0xa42832173f9d9491c7bd93b21497fbfa4121687cd4d2ab572e80753d7edcbb42cfa49f460026fbde52f420786751a138", - "0x97b947126d84dcc70c97be3c04b3de3f239b1c4914342fa643b1a4bb8c4fe45c0fcb585700d13a7ed50784790c54bef9", - "0x860e407d353eac070e2418ef6cb80b96fc5f6661d6333e634f6f306779651588037be4c2419562c89c61f9aa2c4947f5", - "0xb2c9d93c3ba4e511b0560b55d3501bf28a510745fd666b3cb532db051e6a8617841ea2f071dda6c9f15619c7bfd2737f", - "0x8596f4d239aeeac78311207904d1bd863ef68e769629cc379db60e019aaf05a9d5cd31dc8e630b31e106a3a93e47cbc5", - "0x8b26e14e2e136b65c5e9e5c2022cee8c255834ea427552f780a6ca130a6446102f2a6f334c3f9a0308c53df09e3dba7e", - "0xb54724354eb515a3c8bed0d0677ff1db94ac0a07043459b4358cb90e3e1aa38ac23f2caa3072cf9647275d7cd61d0e80", - "0xb7ce9fe0e515e7a6b2d7ddcb92bc0196416ff04199326aea57996eef8c5b1548bd8569012210da317f7c0074691d01b7", - "0xa1a13549c82c877253ddefa36a29ea6a23695ee401fdd48e65f6f61e5ebd956d5e0edeff99484e9075cb35071fec41e2", - "0x838ba0c1e5bd1a6da05611ff1822b8622457ebd019cb065ece36a2d176bd2d889511328120b8a357e44569e7f640c1e6", - "0xb916eccff2a95519400bbf76b5f576cbe53cf200410370a19d77734dc04c05b585cfe382e8864e67142d548cd3c4c2f4", - "0xa610447cb7ca6eea53a6ff1f5fe562377dcb7f4aaa7300f755a4f5e8eba61e863c51dc2aa9a29b35525b550fbc32a0fe", - "0x9620e8f0f0ee9a4719aa9685eeb1049c5c77659ba6149ec4c158f999cfd09514794b23388879931fe26fea03fa471fd3", - "0xa9dcf8b679e276583cf5b9360702a185470d09aea463dc474ee9c8aee91ef089dacb073e334e47fbc78ec5417c90465c", - "0x8c9adee8410bdd99e5b285744cee61e2593b6300ff31a8a83b0ec28da59475a5c6fb9346fe43aadea2e6c3dad2a8e30a", - "0x97d5afe9b3897d7b8bb628b7220cf02d8ee4e9d0b78f5000d500aaf4c1df9251aaaabfd1601626519f9d66f00a821d4e", - "0x8a382418157b601ce4c3501d3b8409ca98136a4ef6abcbf62885e16e215b76b035c94d149cc41ff92e42ccd7c43b9b3d", - "0xb64b8d11fb3b01abb2646ac99fdb9c02b804ce15d98f9fe0fbf1c9df8440c71417487feb6cdf51e3e81d37104b19e012", - "0x849d7d044f9d8f0aab346a9374f0b3a5d14a9d1faa83dbacccbdc629ad1ef903a990940255564770537f8567521d17f0", - "0x829dbb0c76b996c2a91b4cbbe93ba455ca0d5729755e5f0c92aaee37dff7f36fcdc06f33aca41f1b609c784127b67d88", - "0x85a7c0069047b978422d264d831ab816435f63938015d2e977222b6b5746066c0071b7f89267027f8a975206ed25c1b0", - "0x84b9fbc1cfb302df1acdcf3dc5d66fd1edfe7839f7a3b2fb3a0d5548656249dd556104d7c32b73967bccf0f5bdcf9e3b", - "0x972220ac5b807f53eac37dccfc2ad355d8b21ea6a9c9b011c09fe440ddcdf7513e0b43d7692c09ded80d7040e26aa28f", - "0x855885ed0b21350baeca890811f344c553cf9c21024649c722453138ba29193c6b02c4b4994cd414035486f923472e28", - "0x841874783ae6d9d0e59daea03e96a01cbbe4ecaced91ae4f2c8386e0d87b3128e6d893c98d17c59e4de1098e1ad519dd", - "0x827e50fc9ce56f97a4c3f2f4cbaf0b22f1c3ce6f844ff0ef93a9c57a09b8bf91ebfbd2ba9c7f83c442920bffdaf288cc", - "0xa441f9136c7aa4c08d5b3534921b730e41ee91ab506313e1ba5f7c6f19fd2d2e1594e88c219834e92e6fb95356385aa7", - "0x97d75b144471bf580099dd6842b823ec0e6c1fb86dd0da0db195e65524129ea8b6fd4a7a9bbf37146269e938a6956596", - "0xa4b6fa87f09d5a29252efb2b3aaab6b3b6ea9fab343132a651630206254a25378e3e9d6c96c3d14c150d01817d375a8e", - "0xa31a671876d5d1e95fe2b8858dc69967231190880529d57d3cab7f9f4a2b9b458ac9ee5bdaa3289158141bf18f559efb", - "0x90bee6fff4338ba825974021b3b2a84e36d617e53857321f13d2b3d4a28954e6de3b3c0e629d61823d18a9763313b3bf", - "0x96b622a63153f393bb419bfcf88272ea8b3560dbd46b0aa07ada3a6223990d0abdd6c2adb356ef4be5641688c8d83941", - "0x84c202adeaff9293698022bc0381adba2cd959f9a35a4e8472288fd68f96f6de8be9da314c526d88e291c96b1f3d6db9", - "0x8ca01a143b8d13809e5a8024d03e6bc9492e22226073ef6e327edf1328ef4aff82d0bcccee92cb8e212831fa35fe1204", - "0xb2f970dbad15bfbefb38903c9bcc043d1367055c55dc1100a850f5eb816a4252c8c194b3132c929105511e14ea10a67d", - "0xa5e36556472a95ad57eb90c3b6623671b03eafd842238f01a081997ffc6e2401f76e781d049bb4aa94d899313577a9cf", - "0x8d1057071051772f7c8bedce53a862af6fd530dd56ae6321eaf2b9fc6a68beff5ed745e1c429ad09d5a118650bfd420a", - "0x8aadc4f70ace4fcb8d93a78610779748dcffc36182d45b932c226dc90e48238ea5daa91f137c65ed532352c4c4d57416", - "0xa2ea05ae37e673b4343232ae685ee14e6b88b867aef6dfac35db3589cbcd76f99540fed5c2641d5bb5a4a9f808e9bf0d", - "0x947f1abad982d65648ae4978e094332b4ecb90f482c9be5741d5d1cf5a28acf4680f1977bf6e49dd2174c37f11e01296", - "0xa27b144f1565e4047ba0e3f4840ef19b5095d1e281eaa463c5358f932114cbd018aa6dcf97546465cf2946d014d8e6d6", - "0x8574e1fc3acade47cd4539df578ce9205e745e161b91e59e4d088711a7ab5aa3b410d517d7304b92109924d9e2af8895", - "0xa48ee6b86b88015d6f0d282c1ae01d2a5b9e8c7aa3d0c18b35943dceb1af580d08a65f54dc6903cde82fd0d73ce94722", - "0x8875650cec543a7bf02ea4f2848a61d167a66c91ffaefe31a9e38dc8511c6a25bde431007eefe27a62af3655aca208dc", - "0x999b0a6e040372e61937bf0d68374e230346b654b5a0f591a59d33a4f95bdb2f3581db7c7ccb420cd7699ed709c50713", - "0x878c9e56c7100c5e47bbe77dc8da5c5fe706cec94d37fa729633bca63cace7c40102eee780fcdabb655f5fa47a99600e", - "0x865006fb5b475ada5e935f27b96f9425fc2d5449a3c106aa366e55ebed3b4ee42adc3c3f0ac19fd129b40bc7d6bc4f63", - "0xb7a7da847f1202e7bc1672553e68904715e84fd897d529243e3ecda59faa4e17ba99c649a802d53f6b8dfdd51f01fb74", - "0x8b2fb4432c05653303d8c8436473682933a5cb604da10c118ecfcd2c8a0e3132e125afef562bdbcc3df936164e5ce4f2", - "0x808d95762d33ddfa5d0ee3d7d9f327de21a994d681a5f372e2e3632963ea974da7f1f9e5bac8ccce24293509d1f54d27", - "0x932946532e3c397990a1df0e94c90e1e45133e347a39b6714c695be21aeb2d309504cb6b1dde7228ff6f6353f73e1ca2", - "0x9705e7c93f0cdfaa3fa96821f830fe53402ad0806036cd1b48adc2f022d8e781c1fbdab60215ce85c653203d98426da3", - "0xaa180819531c3ec1feb829d789cb2092964c069974ae4faad60e04a6afcce5c3a59aec9f11291e6d110a788d22532bc6", - "0x88f755097f7e25cb7dd3c449520c89b83ae9e119778efabb54fbd5c5714b6f37c5f9e0346c58c6ab09c1aef2483f895d", - "0x99fc03ab7810e94104c494f7e40b900f475fde65bdec853e60807ffd3f531d74de43335c3b2646b5b8c26804a7448898", - "0xaf2dea9683086bed1a179110efb227c9c00e76cd00a2015b089ccbcee46d1134aa18bda5d6cab6f82ae4c5cd2461ac21", - "0xa500f87ba9744787fdbb8e750702a3fd229de6b8817594348dec9a723b3c4240ddfa066262d002844b9e38240ce55658", - "0x924d0e45c780f5bc1c1f35d15dfc3da28036bdb59e4c5440606750ecc991b85be18bc9a240b6c983bc5430baa4c68287", - "0x865b11e0157b8bf4c5f336024b016a0162fc093069d44ac494723f56648bc4ded13dfb3896e924959ea11c96321afefc", - "0x93672d8607d4143a8f7894f1dcca83fb84906dc8d6dd7dd063bb0049cfc20c1efd933e06ca7bd03ea4cb5a5037990bfe", - "0x826891efbdff0360446825a61cd1fa04326dd90dae8c33dfb1ed97b045e165766dd070bd7105560994d0b2044bdea418", - "0x93c4a4a8bcbc8b190485cc3bc04175b7c0ed002c28c98a540919effd6ed908e540e6594f6db95cd65823017258fb3b1c", - "0xaeb2a0af2d2239fda9aa6b8234b019708e8f792834ff0dd9c487fa09d29800ddceddd6d7929faa9a3edcb9e1b3aa0d6b", - "0x87f11de7236d387863ec660d2b04db9ac08143a9a2c4dfff87727c95b4b1477e3bc473a91e5797313c58754905079643", - "0x80dc1db20067a844fe8baceca77f80db171a5ca967acb24e2d480eae9ceb91a3343c31ad1c95b721f390829084f0eae6", - "0x9825c31f1c18da0de3fa84399c8b40f8002c3cae211fb6a0623c76b097b4d39f5c50058f57a16362f7a575909d0a44a2", - "0xa99fc8de0c38dbf7b9e946de83943a6b46a762167bafe2a603fb9b86f094da30d6de7ed55d639aafc91936923ee414b3", - "0xad594678b407db5d6ea2e90528121f84f2b96a4113a252a30d359a721429857c204c1c1c4ff71d8bb5768c833f82e80e", - "0xb33d985e847b54510b9b007e31053732c8a495e43be158bd2ffcea25c6765bcbc7ca815f7c60b36ad088b955dd6e9350", - "0x815f8dfc6f90b3342ca3fbd968c67f324dae8f74245cbf8bc3bef10e9440c65d3a2151f951e8d18959ba01c1b50b0ec1", - "0x94c608a362dd732a1abc56e338637c900d59013db8668e49398b3c7a0cae3f7e2f1d1bf94c0299eeafe6af7f76c88618", - "0x8ebd8446b23e5adfcc393adc5c52fe172f030a73e63cd2d515245ca0dd02782ceed5bcdd9ccd9c1b4c5953dfac9c340c", - "0x820437f3f6f9ad0f5d7502815b221b83755eb8dc56cd92c29e9535eb0b48fb8d08c9e4fcc26945f9c8cca60d89c44710", - "0x8910e4e8a56bf4be9cc3bbf0bf6b1182a2f48837a2ed3c2aaec7099bfd7f0c83e14e608876b17893a98021ff4ab2f20d", - "0x9633918fde348573eec15ce0ad53ac7e1823aac86429710a376ad661002ae6d049ded879383faaa139435122f64047c6", - "0xa1f5e3fa558a9e89318ca87978492f0fb4f6e54a9735c1b8d2ecfb1d1c57194ded6e0dd82d077b2d54251f3bee1279e1", - "0xb208e22d04896abfd515a95c429ff318e87ff81a5d534c8ac2c33c052d6ffb73ef1dccd39c0bbe0734b596c384014766", - "0x986d5d7d2b5bde6d16336f378bd13d0e671ad23a8ec8a10b3fc09036faeeb069f60662138d7a6df3dfb8e0d36180f770", - "0xa2d4e6c5f5569e9cef1cddb569515d4b6ace38c8aed594f06da7434ba6b24477392cc67ba867c2b079545ca0c625c457", - "0xb5ac32b1d231957d91c8b7fc43115ce3c5c0d8c13ca633374402fa8000b6d9fb19499f9181844f0c10b47357f3f757ce", - "0x96b8bf2504b4d28fa34a4ec378e0e0b684890c5f44b7a6bb6e19d7b3db2ab27b1e2686389d1de9fbd981962833a313ea", - "0x953bfd7f6c3a0469ad432072b9679a25486f5f4828092401eff494cfb46656c958641a4e6d0d97d400bc59d92dba0030", - "0x876ab3cea7484bbfd0db621ec085b9ac885d94ab55c4bb671168d82b92e609754b86aaf472c55df3d81421d768fd108a", - "0x885ff4e67d9ece646d02dd425aa5a087e485c3f280c3471b77532b0db6145b69b0fbefb18aa2e3fa5b64928b43a94e57", - "0xb91931d93f806d0b0e6cc62a53c718c099526140f50f45d94b8bbb57d71e78647e06ee7b42aa5714aed9a5c05ac8533f", - "0xa0313eeadd39c720c9c27b3d671215331ab8d0a794e71e7e690f06bcd87722b531d6525060c358f35f5705dbb7109ccb", - "0x874c0944b7fedc6701e53344100612ddcb495351e29305c00ec40a7276ea5455465ffb7bded898886c1853139dfb1fc7", - "0x8dc31701a01ee8137059ca1874a015130d3024823c0576aa9243e6942ec99d377e7715ed1444cd9b750a64b85dcaa3e5", - "0x836d2a757405e922ec9a2dfdcf489a58bd48b5f9683dd46bf6047688f778c8dee9bc456de806f70464df0b25f3f3d238", - "0xb30b0a1e454a503ea3e2efdec7483eaf20b0a5c3cefc42069e891952b35d4b2c955cf615f3066285ed8fafd9fcfbb8f6", - "0x8e6d4044b55ab747e83ec8762ea86845f1785cc7be0279c075dadf08aca3ccc5a096c015bb3c3f738f647a4eadea3ba5", - "0xad7735d16ab03cbe09c029610aa625133a6daecfc990b297205b6da98eda8c136a7c50db90f426d35069708510d5ae9c", - "0x8d62d858bbb59ec3c8cc9acda002e08addab4d3ad143b3812098f3d9087a1b4a1bb255dcb1635da2402487d8d0249161", - "0x805beec33238b832e8530645a3254aeef957e8f7ea24bcfc1054f8b9c69421145ebb8f9d893237e8a001c857fedfc77e", - "0xb1005644be4b085e3f5775aa9bd3e09a283e87ddada3082c04e7a62d303dcef3b8cf8f92944c200c7ae6bb6bdf63f832", - "0xb4ba0e0790dc29063e577474ffe3b61f5ea2508169f5adc1e394934ebb473e356239413a17962bc3e5d3762d72cce8c2", - "0xa157ba9169c9e3e6748d9f1dd67fbe08b9114ade4c5d8fc475f87a764fb7e6f1d21f66d7905cd730f28a1c2d8378682a", - "0x913e52b5c93989b5d15e0d91aa0f19f78d592bc28bcfdfddc885a9980c732b1f4debb8166a7c4083c42aeda93a702898", - "0x90fbfc1567e7cd4e096a38433704d3f96a2de2f6ed3371515ccc30bc4dd0721a704487d25a97f3c3d7e4344472702d8d", - "0x89646043028ffee4b69d346907586fd12c2c0730f024acb1481abea478e61031966e72072ff1d5e65cb8c64a69ad4eb1", - "0xb125a45e86117ee11d2fb42f680ab4a7894edd67ff927ae2c808920c66c3e55f6a9d4588eee906f33a05d592e5ec3c04", - "0xaad47f5b41eae9be55fb4f67674ff1e4ae2482897676f964a4d2dcb6982252ee4ff56aac49578b23f72d1fced707525e", - "0xb9ddff8986145e33851b4de54d3e81faa3352e8385895f357734085a1616ef61c692d925fe62a5ed3be8ca49f5d66306", - "0xb3cb0963387ed28c0c0adf7fe645f02606e6e1780a24d6cecef5b7c642499109974c81a7c2a198b19862eedcea2c2d8c", - "0xac9c53c885457aaf5cb36c717a6f4077af701e0098eebd7aa600f5e4b14e6c1067255b3a0bc40e4a552025231be7de60", - "0x8e1a8d823c4603f6648ec21d064101094f2a762a4ed37dd2f0a2d9aa97b2d850ce1e76f4a4b8cae58819b058180f7031", - "0xb268b73bf7a179b6d22bd37e5e8cb514e9f5f8968c78e14e4f6d5700ca0d0ca5081d0344bb73b028970eebde3cb4124e", - "0xa7f57d71940f0edbd29ed8473d0149cae71d921dd15d1ff589774003e816b54b24de2620871108cec1ab9fa956ad6ce6", - "0x8053e6416c8b120e2b999cc2fc420a6a55094c61ac7f2a6c6f0a2c108a320890e389af96cbe378936132363c0d551277", - "0xb3823f4511125e5aa0f4269e991b435a0d6ceb523ebd91c04d7add5534e3df5fc951c504b4fd412a309fd3726b7f940b", - "0xae6eb04674d04e982ca9a6add30370ab90e303c71486f43ed3efbe431af1b0e43e9d06c11c3412651f304c473e7dbf39", - "0x96ab55e641ed2e677591f7379a3cd126449614181fce403e93e89b1645d82c4af524381ff986cae7f9cebe676878646d", - "0xb52423b4a8c37d3c3e2eca8f0ddbf7abe0938855f33a0af50f117fab26415fb0a3da5405908ec5fdc22a2c1f2ca64892", - "0x82a69ce1ee92a09cc709d0e3cd22116c9f69d28ea507fe5901f5676000b5179b9abe4c1875d052b0dd42d39925e186bb", - "0xa84c8cb84b9d5cfb69a5414f0a5283a5f2e90739e9362a1e8c784b96381b59ac6c18723a4aa45988ee8ef5c1f45cc97d", - "0xafd7efce6b36813082eb98257aae22a4c1ae97d51cac7ea9c852d4a66d05ef2732116137d8432e3f117119725a817d24", - "0xa0f5fe25af3ce021b706fcff05f3d825384a272284d04735574ce5fb256bf27100fad0b1f1ba0e54ae9dcbb9570ecad3", - "0x8751786cb80e2e1ff819fc7fa31c2833d25086534eb12b373d31f826382430acfd87023d2a688c65b5e983927e146336", - "0x8cf5c4b17fa4f3d35c78ce41e1dc86988fd1135cd5e6b2bb0c108ee13538d0d09ae7102609c6070f39f937b439b31e33", - "0xa9108967a2fedd7c322711eca8159c533dd561bedcb181b646de98bf5c3079449478eab579731bee8d215ae8852c7e21", - "0xb54c5171704f42a6f0f4e70767cdb3d96ffc4888c842eece343a01557da405961d53ffdc34d2f902ea25d3e1ed867cad", - "0xae8d4b764a7a25330ba205bf77e9f46182cd60f94a336bbd96773cf8064e3d39caf04c310680943dc89ed1fbad2c6e0d", - "0xaa5150e911a8e1346868e1b71c5a01e2a4bb8632c195861fb6c3038a0e9b85f0e09b3822e9283654a4d7bb17db2fc5f4", - "0x9685d3756ce9069bf8bb716cf7d5063ebfafe37e15b137fc8c3159633c4e006ff4887ddd0ae90360767a25c3f90cba7f", - "0x82155fd70f107ab3c8e414eadf226c797e07b65911508c76c554445422325e71af8c9a8e77fd52d94412a6fc29417cd3", - "0xabfae52f53a4b6e00760468d973a267f29321997c3dbb5aee36dc1f20619551229c0c45b9d9749f410e7f531b73378e8", - "0x81a76d921f8ef88e774fd985e786a4a330d779b93fad7def718c014685ca0247379e2e2a007ad63ee7f729cd9ed6ce1b", - "0x81947c84bc5e28e26e2e533af5ae8fe10407a7b77436dbf8f1d5b0bbe86fc659eae10f974659dc7c826c6dabd03e3a4b", - "0x92b8c07050d635b8dd4fd09df9054efe4edae6b86a63c292e73cc819a12a21dd7d104ce51fa56af6539dedf6dbe6f7b6", - "0xb44c579e3881f32b32d20c82c207307eca08e44995dd2aac3b2692d2c8eb2a325626c80ac81c26eeb38c4137ff95add5", - "0x97efab8941c90c30860926dea69a841f2dcd02980bf5413b9fd78d85904588bf0c1021798dbc16c8bbb32cce66c82621", - "0x913363012528b50698e904de0588bf55c8ec5cf6f0367cfd42095c4468fcc64954fbf784508073e542fee242d0743867", - "0x8ed203cf215148296454012bd10fddaf119203db1919a7b3d2cdc9f80e66729464fdfae42f1f2fc5af1ed53a42b40024", - "0xab84312db7b87d711e9a60824f4fe50e7a6190bf92e1628688dfcb38930fe87b2d53f9e14dd4de509b2216856d8d9188", - "0x880726def069c160278b12d2258eac8fa63f729cd351a710d28b7e601c6712903c3ac1e7bbd0d21e4a15f13ca49db5aa", - "0x980699cd51bac6283959765f5174e543ed1e5f5584b5127980cbc2ef18d984ecabba45042c6773b447b8e694db066028", - "0xaeb019cb80dc4cb4207430d0f2cd24c9888998b6f21d9bf286cc638449668d2eec0018a4cf3fe6448673cd6729335e2b", - "0xb29852f6aa6c60effdffe96ae88590c88abae732561d35cc19e82d3a51e26cb35ea00986193e07f90060756240f5346e", - "0xa0fa855adc5ba469f35800c48414b8921455950a5c0a49945d1ef6e8f2a1881f2e2dfae47de6417270a6bf49deeb091d", - "0xb6c7332e3b14813641e7272d4f69ecc7e09081df0037d6dab97ce13a9e58510f5c930d300633f208181d9205c5534001", - "0x85a6c050f42fce560b5a8d54a11c3bbb8407abbadd859647a7b0c21c4b579ec65671098b74f10a16245dc779dff7838e", - "0x8f3eb34bb68759d53c6677de4de78a6c24dd32c8962a7fb355ed362572ef8253733e6b52bc21c9f92ecd875020a9b8de", - "0xa17dd44181e5dab4dbc128e1af93ec22624b57a448ca65d2d9e246797e4af7d079e09c6e0dfb62db3a9957ce92f098d5", - "0xa56a1b854c3183082543a8685bb34cae1289f86cfa8123a579049dbd059e77982886bfeb61bf6e05b4b1fe4e620932e7", - "0xaedae3033cb2fb7628cb4803435bdd7757370a86f808ae4cecb9a268ad0e875f308c048c80cbcac523de16b609683887", - "0x9344905376aa3982b1179497fac5a1d74b14b7038fd15e3b002db4c11c8bfc7c39430db492cdaf58b9c47996c9901f28", - "0xa3bfafdae011a19f030c749c3b071f83580dee97dd6f949e790366f95618ca9f828f1daaeabad6dcd664fcef81b6556d", - "0x81c03d8429129e7e04434dee2c529194ddb01b414feda3adee2271eb680f6c85ec872a55c9fa9d2096f517e13ed5abcc", - "0x98205ef3a72dff54c5a9c82d293c3e45d908946fa74bb749c3aabe1ab994ea93c269bcce1a266d2fe67a8f02133c5985", - "0x85a70aeed09fda24412fadbafbbbf5ba1e00ac92885df329e147bfafa97b57629a3582115b780d8549d07d19b7867715", - "0xb0fbe81c719f89a57d9ea3397705f898175808c5f75f8eb81c2193a0b555869ba7bd2e6bc54ee8a60cea11735e21c68c", - "0xb03a0bd160495ee626ff3a5c7d95bc79d7da7e5a96f6d10116600c8fa20bedd1132f5170f25a22371a34a2d763f2d6d0", - "0xa90ab04091fbca9f433b885e6c1d60ab45f6f1daf4b35ec22b09909d493a6aab65ce41a6f30c98239cbca27022f61a8b", - "0xb66f92aa3bf2549f9b60b86f99a0bd19cbdd97036d4ae71ca4b83d669607f275260a497208f6476cde1931d9712c2402", - "0xb08e1fdf20e6a9b0b4942f14fa339551c3175c1ffc5d0ab5b226b6e6a322e9eb0ba96adc5c8d59ca4259e2bdd04a7eb0", - "0xa2812231e92c1ce74d4f5ac3ab6698520288db6a38398bb38a914ac9326519580af17ae3e27cde26607e698294022c81", - "0xabfcbbcf1d3b9e84c02499003e490a1d5d9a2841a9e50c7babbef0b2dd20d7483371d4dc629ba07faf46db659459d296", - "0xb0fe9f98c3da70927c23f2975a9dc4789194d81932d2ad0f3b00843dd9cbd7fb60747a1da8fe5a79f136a601becf279d", - "0xb130a6dba7645165348cb90f023713bed0eefbd90a976b313521c60a36d34f02032e69a2bdcf5361e343ed46911297ec", - "0x862f0cffe3020cea7a5fd4703353aa1eb1be335e3b712b29d079ff9f7090d1d8b12013011e1bdcbaa80c44641fd37c9f", - "0x8c6f11123b26633e1abb9ed857e0bce845b2b3df91cc7b013b2fc77b477eee445da0285fc6fc793e29d5912977f40916", - "0x91381846126ea819d40f84d3005e9fb233dc80071d1f9bb07f102bf015f813f61e5884ffffb4f5cd333c1b1e38a05a58", - "0x8add7d908de6e1775adbd39c29a391f06692b936518db1f8fde74eb4f533fc510673a59afb86e3a9b52ade96e3004c57", - "0x8780e086a244a092206edcde625cafb87c9ab1f89cc3e0d378bc9ee776313836160960a82ec397bc3800c0a0ec3da283", - "0xa6cb4cd9481e22870fdd757fae0785edf4635e7aacb18072fe8dc5876d0bab53fb99ce40964a7d3e8bcfff6f0ab1332f", - "0xaf30ff47ecc5b543efba1ba4706921066ca8bb625f40e530fb668aea0551c7647a9d126e8aba282fbcce168c3e7e0130", - "0x91b0bcf408ce3c11555dcb80c4410b5bc2386d3c05caec0b653352377efdcb6bab4827f2018671fc8e4a0e90d772acc1", - "0xa9430b975ef138b6b2944c7baded8fe102d31da4cfe3bd3d8778bda79189c99d38176a19c848a19e2d1ee0bddd9a13c1", - "0xaa5a4eef849d7c9d2f4b018bd01271c1dd83f771de860c4261f385d3bdcc130218495860a1de298f14b703ec32fa235f", - "0xb0ce79e7f9ae57abe4ff366146c3b9bfb38b0dee09c28c28f5981a5d234c6810ad4d582751948affb480d6ae1c8c31c4", - "0xb75122748560f73d15c01a8907d36d06dc068e82ce22b84b322ac1f727034493572f7907dec34ebc3ddcc976f2f89ed7", - "0xb0fc7836369a3e4411d34792d6bd5617c14f61d9bba023dda64e89dc5fb0f423244e9b48ee64869258931daa9753a56f", - "0x8956d7455ae9009d70c6e4a0bcd7610e55f37494cf9897a8f9e1b904cc8febc3fd2d642ebd09025cfff4609ad7e3bc52", - "0xad741efe9e472026aa49ae3d9914cb9c1a6f37a54f1a6fe6419bebd8c7d68dca105a751c7859f4389505ede40a0de786", - "0xb52f418797d719f0d0d0ffb0846788b5cba5d0454a69a2925de4b0b80fa4dd7e8c445e5eac40afd92897ed28ca650566", - "0xa0ab65fb9d42dd966cd93b1de01d7c822694669dd2b7a0c04d99cd0f3c3de795f387b9c92da11353412f33af5c950e9a", - "0xa0052f44a31e5741a331f7cac515a08b3325666d388880162d9a7b97598fde8b61f9ff35ff220df224eb5c4e40ef0567", - "0xa0101cfdc94e42b2b976c0d89612a720e55d145a5ef6ef6f1f78cf6de084a49973d9b5d45915349c34ce712512191e3c", - "0xa0dd99fcf3f5cead5aaf08e82212df3a8bb543c407a4d6fab88dc5130c1769df3f147e934a46f291d6c1a55d92b86917", - "0xa5939153f0d1931bbda5cf6bdf20562519ea55fbfa978d6dbc6828d298260c0da7a50c37c34f386e59431301a96c2232", - "0x9568269f3f5257200f9ca44afe1174a5d3cf92950a7f553e50e279c239e156a9faaa2a67f288e3d5100b4142efe64856", - "0xb746b0832866c23288e07f24991bbf687cad794e7b794d3d3b79367566ca617d38af586cdc8d6f4a85a34835be41d54f", - "0xa871ce28e39ab467706e32fec1669fda5a4abba2f8c209c6745df9f7a0fa36bbf1919cf14cb89ea26fa214c4c907ae03", - "0xa08dacdd758e523cb8484f6bd070642c0c20e184abdf8e2a601f61507e93952d5b8b0c723c34fcbdd70a8485eec29db2", - "0x85bdb78d501382bb95f1166b8d032941005661aefd17a5ac32df9a3a18e9df2fc5dc2c1f07075f9641af10353cecc0c9", - "0x98d730c28f6fa692a389e97e368b58f4d95382fad8f0baa58e71a3d7baaea1988ead47b13742ce587456f083636fa98e", - "0xa557198c6f3d5382be9fb363feb02e2e243b0c3c61337b3f1801c4a0943f18e38ce1a1c36b5c289c8fa2aa9d58742bab", - "0x89174f79201742220ac689c403fc7b243eed4f8e3f2f8aba0bf183e6f5d4907cb55ade3e238e3623d9885f03155c4d2b", - "0xb891d600132a86709e06f3381158db300975f73ea4c1f7c100358e14e98c5fbe792a9af666b85c4e402707c3f2db321e", - "0xb9e5b2529ef1043278c939373fc0dbafe446def52ddd0a8edecd3e4b736de87e63e187df853c54c28d865de18a358bb6", - "0x8589b2e9770340c64679062c5badb7bbef68f55476289b19511a158a9a721f197da03ece3309e059fc4468b15ac33aa3", - "0xaad8c6cd01d785a881b446f06f1e9cd71bca74ba98674c2dcddc8af01c40aa7a6d469037498b5602e76e9c91a58d3dbd", - "0xabaccb1bd918a8465f1bf8dbe2c9ad4775c620b055550b949a399f30cf0d9eb909f3851f5b55e38f9e461e762f88f499", - "0xae62339d26db46e85f157c0151bd29916d5cc619bd4b832814b3fd2f00af8f38e7f0f09932ffe5bba692005dab2d9a74", - "0x93a6ff30a5c0edf8058c89aba8c3259e0f1b1be1b80e67682de651e5346f7e1b4b4ac3d87cbaebf198cf779524aff6bf", - "0x8980a2b1d8f574af45b459193c952400b10a86122b71fca2acb75ee0dbd492e7e1ef5b959baf609a5172115e371f3177", - "0x8c2f49f3666faee6940c75e8c7f6f8edc3f704cca7a858bbb7ee5e96bba3b0cf0993996f781ba6be3b0821ef4cb75039", - "0xb14b9e348215b278696018330f63c38db100b0542cfc5be11dc33046e3bca6a13034c4ae40d9cef9ea8b34fef0910c4e", - "0xb59bc3d0a30d66c16e6a411cb641f348cb1135186d5f69fda8b0a0934a5a2e7f6199095ba319ec87d3fe8f1ec4a06368", - "0x8874aca2a3767aa198e4c3fec2d9c62d496bc41ff71ce242e9e082b7f38cdf356089295f80a301a3cf1182bde5308c97", - "0xb1820ebd61376d91232423fc20bf008b2ba37e761199f4ef0648ea2bd70282766799b4de814846d2f4d516d525c8daa7", - "0xa6b202e5dedc16a4073e04a11af3a8509b23dfe5a1952f899adeb240e75c3f5bde0c424f811a81ea48d343591faffe46", - "0xa69becee9c93734805523b92150a59a62eed4934f66056b645728740d42223f2925a1ad38359ba644da24d9414f4cdda", - "0xad72f0f1305e37c7e6b48c272323ee883320994cb2e0d850905d6655fafc9f361389bcb9c66b3ff8d2051dbb58c8aa96", - "0xb563600bd56fad7c8853af21c6a02a16ed9d8a8bbeea2c31731d63b976d83cb05b9779372d898233e8fd597a75424797", - "0xb0abb78ce465bf7051f563c62e8be9c57a2cc997f47c82819300f36e301fefd908894bb2053a9d27ce2d0f8c46d88b5b", - "0xa071a85fb8274bac2202e0cb8e0e2028a5e138a82d6e0374d39ca1884a549c7c401312f00071b91f455c3a2afcfe0cda", - "0xb931c271513a0f267b9f41444a5650b1918100b8f1a64959c552aff4e2193cc1b9927906c6fa7b8a8c68ef13d79aaa52", - "0xa6a1bb9c7d32cb0ca44d8b75af7e40479fbce67d216b48a2bb680d3f3a772003a49d3cd675fc64e9e0f8fabeb86d6d61", - "0xb98d609858671543e1c3b8564162ad828808bb50ded261a9f8690ded5b665ed8368c58f947365ed6e84e5a12e27b423d", - "0xb3dca58cd69ec855e2701a1d66cad86717ff103ef862c490399c771ad28f675680f9500cb97be48de34bcdc1e4503ffd", - "0xb34867c6735d3c49865e246ddf6c3b33baf8e6f164db3406a64ebce4768cb46b0309635e11be985fee09ab7a31d81402", - "0xacb966c554188c5b266624208f31fab250b3aa197adbdd14aee5ab27d7fb886eb4350985c553b20fdf66d5d332bfd3fe", - "0x943c36a18223d6c870d54c3b051ef08d802b85e9dd6de37a51c932f90191890656c06adfa883c87b906557ae32d09da0", - "0x81bca7954d0b9b6c3d4528aadf83e4bc2ef9ea143d6209bc45ae9e7ae9787dbcd8333c41f12c0b6deee8dcb6805e826a", - "0xaba176b92256efb68f574e543479e5cf0376889fb48e3db4ebfb7cba91e4d9bcf19dcfec444c6622d9398f06de29e2b9", - "0xb9f743691448053216f6ece7cd699871fff4217a1409ceb8ab7bdf3312d11696d62c74b0664ba0a631b1e0237a8a0361", - "0xa383c2b6276fa9af346b21609326b53fb14fdf6f61676683076e80f375b603645f2051985706d0401e6fbed7eb0666b6", - "0xa9ef2f63ec6d9beb8f3d04e36807d84bda87bdd6b351a3e4a9bf7edcb5618c46c1f58cfbf89e64b40f550915c6988447", - "0xa141b2d7a82f5005eaea7ae7d112c6788b9b95121e5b70b7168d971812f3381de8b0082ac1f0a82c7d365922ebd2d26a", - "0xb1b76ef8120e66e1535c17038b75255a07849935d3128e3e99e56567b842fb1e8d56ef932d508d2fb18b82f7868fe1a9", - "0x8e2e234684c81f21099f5c54f6bbe2dd01e3b172623836c77668a0c49ce1fe218786c3827e4d9ae2ea25c50a8924fb3c", - "0xa5caf5ff948bfd3c4ca3ffbdfcd91eec83214a6c6017235f309a0bbf7061d3b0b466307c00b44a1009cf575163898b43", - "0x986415a82ca16ebb107b4c50b0c023c28714281db0bcdab589f6cb13d80e473a3034b7081b3c358e725833f6d845cb14", - "0xb94836bf406ac2cbacb10e6df5bcdfcc9d9124ae1062767ca4e322d287fd5e353fdcebd0e52407cb3cd68571258a8900", - "0x83c6d70a640b33087454a4788dfd9ef3ed00272da084a8d36be817296f71c086b23b576f98178ab8ca6a74f04524b46b", - "0xad4115182ad784cfe11bcfc5ce21fd56229cc2ce77ac82746e91a2f0aa53ca6593a22efd2dc4ed8d00f84542643d9c58", - "0xab1434c5e5065da826d10c2a2dba0facccab0e52b506ce0ce42fbe47ced5a741797151d9ecc99dc7d6373cfa1779bbf6", - "0x8a8b591d82358d55e6938f67ea87a89097ab5f5496f7260adb9f649abb289da12b498c5b2539c2f9614fb4e21b1f66b0", - "0x964f355d603264bc1f44c64d6d64debca66f37dff39c971d9fc924f2bc68e6c187b48564a6dc82660a98b035f8addb5d", - "0xb66235eaaf47456bc1dc4bde454a028e2ce494ece6b713a94cd6bf27cf18c717fd0c57a5681caaa2ad73a473593cdd7a", - "0x9103e3bb74304186fa4e3e355a02da77da4aca9b7e702982fc2082af67127ebb23a455098313c88465bc9b7d26820dd5", - "0xb6a42ff407c9dd132670cdb83cbad4b20871716e44133b59a932cd1c3f97c7ac8ff7f61acfaf8628372508d8dc8cad7c", - "0x883a9c21c16a167a4171b0f084565c13b6f28ba7c4977a0de69f0a25911f64099e7bbb4da8858f2e93068f4155d04e18", - "0x8dbb3220abc6a43220adf0331e3903d3bfd1d5213aadfbd8dfcdf4b2864ce2e96a71f35ecfb7a07c3bbabf0372b50271", - "0xb4ad08aee48e176bda390b7d9acf2f8d5eb008f30d20994707b757dc6a3974b2902d29cd9b4d85e032810ad25ac49e97", - "0x865bb0f33f7636ec501bb634e5b65751c8a230ae1fa807a961a8289bbf9c7fe8c59e01fbc4c04f8d59b7f539cf79ddd5", - "0x86a54d4c12ad1e3605b9f93d4a37082fd26e888d2329847d89afa7802e815f33f38185c5b7292293d788ad7d7da1df97", - "0xb26c8615c5e47691c9ff3deca3021714662d236c4d8401c5d27b50152ce7e566266b9d512d14eb63e65bc1d38a16f914", - "0x827639d5ce7db43ba40152c8a0eaad443af21dc92636cc8cc2b35f10647da7d475a1e408901cd220552fddad79db74df", - "0xa2b79a582191a85dbe22dc384c9ca3de345e69f6aa370aa6d3ff1e1c3de513e30b72df9555b15a46586bd27ea2854d9d", - "0xae0d74644aba9a49521d3e9553813bcb9e18f0b43515e4c74366e503c52f47236be92dfbd99c7285b3248c267b1de5a0", - "0x80fb0c116e0fd6822a04b9c25f456bdca704e2be7bdc5d141dbf5d1c5eeb0a2c4f5d80db583b03ef3e47517e4f9a1b10", - "0xac3a1fa3b4a2f30ea7e0a114cdc479eb51773573804c2a158d603ad9902ae8e39ffe95df09c0d871725a5d7f9ba71a57", - "0xb56b2b0d601cba7f817fa76102c68c2e518c6f20ff693aad3ff2e07d6c4c76203753f7f91686b1801e8c4659e4d45c48", - "0x89d50c1fc56e656fb9d3915964ebce703cb723fe411ab3c9eaa88ccc5d2b155a9b2e515363d9c600d3c0cee782c43f41", - "0xb24207e61462f6230f3cd8ccf6828357d03e725769f7d1de35099ef9ee4dca57dbce699bb49ed994462bee17059d25ce", - "0xb886f17fcbcbfcd08ac07f04bb9543ef58510189decaccea4b4158c9174a067cb67d14b6be3c934e6e2a18c77efa9c9c", - "0xb9c050ad9cafd41c6e2e192b70d080076eed59ed38ea19a12bd92fa17b5d8947d58d5546aaf5e8e27e1d3b5481a6ce51", - "0xaaf7a34d3267e3b1ddbc54c641e3922e89303f7c86ebebc7347ebca4cffad5b76117dac0cbae1a133053492799cd936f", - "0xa9ee604ada50adef82e29e893070649d2d4b7136cc24fa20e281ce1a07bd736bf0de7c420369676bcbcecff26fb6e900", - "0x9855315a12a4b4cf80ab90b8bd13003223ba25206e52fd4fe6a409232fbed938f30120a3db23eab9c53f308bd8b9db81", - "0x8cd488dd7a24f548a3cf03c54dec7ff61d0685cb0f6e5c46c2d728e3500d8c7bd6bba0156f4bf600466fda53e5b20444", - "0x890ad4942ebac8f5b16c777701ab80c68f56fa542002b0786f8fea0fb073154369920ac3dbfc07ea598b82f4985b8ced", - "0x8de0cf9ddc84c9b92c59b9b044387597799246b30b9f4d7626fc12c51f6e423e08ee4cbfe9289984983c1f9521c3e19d", - "0xb474dfb5b5f4231d7775b3c3a8744956b3f0c7a871d835d7e4fd9cc895222c7b868d6c6ce250de568a65851151fac860", - "0x86433b6135d9ed9b5ee8cb7a6c40e5c9d30a68774cec04988117302b8a02a11a71a1e03fd8e0264ef6611d219f103007", - "0x80b9ed4adbe9538fb1ef69dd44ec0ec5b57cbfea820054d8d445b4261962624b4c70ac330480594bc5168184378379c3", - "0x8b2e83562ccd23b7ad2d17f55b1ab7ef5fbef64b3a284e6725b800f3222b8bdf49937f4a873917ada9c4ddfb090938c2", - "0xabe78cebc0f5a45d754140d1f685e387489acbfa46d297a8592aaa0d676a470654f417a4f7d666fc0b2508fab37d908e", - "0xa9c5f8ff1f8568e252b06d10e1558326db9901840e6b3c26bbd0cd5e850cb5fb3af3f117dbb0f282740276f6fd84126f", - "0x975f8dc4fb55032a5df3b42b96c8c0ffecb75456f01d4aef66f973cb7270d4eff32c71520ceefc1adcf38d77b6b80c67", - "0xb043306ed2c3d8a5b9a056565afd8b5e354c8c4569fda66b0d797a50a3ce2c08cffbae9bbe292da69f39e89d5dc7911e", - "0x8d2afc36b1e44386ba350c14a6c1bb31ff6ea77128a0c5287584ac3584282d18516901ce402b4644a53db1ed8e7fa581", - "0x8c294058bed53d7290325c363fe243f6ec4f4ea2343692f4bac8f0cb86f115c069ccb8334b53d2e42c067691ad110dba", - "0xb92157b926751aaf7ef82c1aa8c654907dccab6376187ee8b3e8c0c82811eae01242832de953faa13ebaff7da8698b3e", - "0xa780c4bdd9e4ba57254b09d745075cecab87feda78c88ffee489625c5a3cf96aa6b3c9503a374a37927d9b78de9bd22b", - "0x811f548ef3a2e6a654f7dcb28ac9378de9515ed61e5a428515d9594a83e80b35c60f96a5cf743e6fab0d3cb526149f49", - "0x85a4dccf6d90ee8e094731eec53bd00b3887aec6bd81a0740efddf812fd35e3e4fe4f983afb49a8588691c202dabf942", - "0xb152c2da6f2e01c8913079ae2b40a09b1f361a80f5408a0237a8131b429677c3157295e11b365b1b1841924b9efb922e", - "0x849b9efee8742502ffd981c4517c88ed33e4dd518a330802caff168abae3cd09956a5ee5eda15900243bc2e829016b74", - "0x955a933f3c18ec0f1c0e38fa931e4427a5372c46a3906ebe95082bcf878c35246523c23f0266644ace1fa590ffa6d119", - "0x911989e9f43e580c886656377c6f856cdd4ff1bd001b6db3bbd86e590a821d34a5c6688a29b8d90f28680e9fdf03ba69", - "0xb73b8b4f1fd6049fb68d47cd96a18fcba3f716e0a1061aa5a2596302795354e0c39dea04d91d232aec86b0bf2ba10522", - "0x90f87456d9156e6a1f029a833bf3c7dbed98ca2f2f147a8564922c25ae197a55f7ea9b2ee1f81bf7383197c4bad2e20c", - "0x903cba8b1e088574cb04a05ca1899ab00d8960580c884bd3c8a4c98d680c2ad11410f2b75739d6050f91d7208cac33a5", - "0x9329987d42529c261bd15ecedd360be0ea8966e7838f32896522c965adfc4febf187db392bd441fb43bbd10c38fdf68b", - "0x8178ee93acf5353baa349285067b20e9bb41aa32d77b5aeb7384fe5220c1fe64a2461bd7a83142694fe673e8bbf61b7c", - "0xa06a8e53abcff271b1394bcc647440f81fb1c1a5f29c27a226e08f961c3353f4891620f2d59b9d1902bf2f5cc07a4553", - "0xaaf5fe493b337810889e777980e6bbea6cac39ac66bc0875c680c4208807ac866e9fda9b5952aa1d04539b9f4a4bec57", - "0xaa058abb1953eceac14ccfa7c0cc482a146e1232905dcecc86dd27f75575285f06bbae16a8c9fe8e35d8713717f5f19f", - "0x8f15dd732799c879ca46d2763453b359ff483ca33adb1d0e0a57262352e0476c235987dc3a8a243c74bc768f93d3014c", - "0xa61cc8263e9bc03cce985f1663b8a72928a607121005a301b28a278e9654727fd1b22bc8a949af73929c56d9d3d4a273", - "0x98d6dc78502d19eb9f921225475a6ebcc7b44f01a2df6f55ccf6908d65b27af1891be2a37735f0315b6e0f1576c1f8d8", - "0x8bd258b883f3b3793ec5be9472ad1ff3dc4b51bc5a58e9f944acfb927349ead8231a523cc2175c1f98e7e1e2b9f363b8", - "0xaeacc2ecb6e807ad09bedd99654b097a6f39840e932873ace02eabd64ccfbb475abdcb62939a698abf17572d2034c51e", - "0xb8ccf78c08ccd8df59fd6eda2e01de328bc6d8a65824d6f1fc0537654e9bc6bf6f89c422dd3a295cce628749da85c864", - "0x8f91fd8cb253ba2e71cc6f13da5e05f62c2c3b485c24f5d68397d04665673167fce1fc1aec6085c69e87e66ec555d3fd", - "0xa254baa10cb26d04136886073bb4c159af8a8532e3fd36b1e9c3a2e41b5b2b6a86c4ebc14dbe624ee07b7ccdaf59f9ab", - "0x94e3286fe5cd68c4c7b9a7d33ae3d714a7f265cf77cd0e9bc19fc51015b1d1c34ad7e3a5221c459e89f5a043ee84e3a9", - "0xa279da8878af8d449a9539bec4b17cea94f0242911f66fab275b5143ab040825f78c89cb32a793930609415cfa3a1078", - "0xac846ceb89c9e5d43a2991c8443079dc32298cd63e370e64149cec98cf48a6351c09c856f2632fd2f2b3d685a18bbf8b", - "0xa847b27995c8a2e2454aaeb983879fb5d3a23105c33175839f7300b7e1e8ec3efd6450e9fa3f10323609dee7b98c6fd5", - "0xa2f432d147d904d185ff4b2de8c6b82fbea278a2956bc406855b44c18041854c4f0ecccd472d1d0dff1d8aa8e281cb1d", - "0x94a48ad40326f95bd63dff4755f863a1b79e1df771a1173b17937f9baba57b39e651e7695be9f66a472f098b339364fc", - "0xa12a0ccd8f96e96e1bc6494341f7ebce959899341b3a084aa1aa87d1c0d489ac908552b7770b887bb47e7b8cbc3d8e66", - "0x81a1f1681bda923bd274bfe0fbb9181d6d164fe738e54e25e8d4849193d311e2c4253614ed673c98af2c798f19a93468", - "0xabf71106a05d501e84cc54610d349d7d5eae21a70bd0250f1bebbf412a130414d1c8dbe673ffdb80208fd72f1defa4d4", - "0x96266dc2e0df18d8136d79f5b59e489978eee0e6b04926687fe389d4293c14f36f055c550657a8e27be4118b64254901", - "0x8df5dcbefbfb4810ae3a413ca6b4bf08619ca53cd50eb1dde2a1c035efffc7b7ac7dff18d403253fd80104bd83dc029e", - "0x9610b87ff02e391a43324a7122736876d5b3af2a137d749c52f75d07b17f19900b151b7f439d564f4529e77aa057ad12", - "0xa90a5572198b40fe2fcf47c422274ff36c9624df7db7a89c0eb47eb48a73a03c985f4ac5016161c76ca317f64339bce1", - "0x98e5e61a6ab6462ba692124dba7794b6c6bde4249ab4fcc98c9edd631592d5bc2fb5e38466691a0970a38e48d87c2e43", - "0x918cefb8f292f78d4db81462c633daf73b395e772f47b3a7d2cea598025b1d8c3ec0cbff46cdb23597e74929981cde40", - "0xa98918a5dc7cf610fe55f725e4fd24ce581d594cb957bb9b4e888672e9c0137003e1041f83e3f1d7b9caab06462c87d4", - "0xb92b74ac015262ca66c33f2d950221e19d940ba3bf4cf17845f961dc1729ae227aa9e1f2017829f2135b489064565c29", - "0xa053ee339f359665feb178b4e7ee30a85df37debd17cacc5a27d6b3369d170b0114e67ad1712ed26d828f1df641bcd99", - "0x8c3c8bad510b35da5ce5bd84b35c958797fbea024ad1c97091d2ff71d9b962e9222f65a9b776e5b3cc29c36e1063d2ee", - "0xaf99dc7330fe7c37e850283eb47cc3257888e7c197cb0d102edf94439e1e02267b6a56306d246c326c4c79f9dc8c6986", - "0xafecb2dc34d57a725efbd7eb93d61eb29dbe8409b668ab9ea040791f5b796d9be6d4fc10d7f627bf693452f330cf0435", - "0x93334fedf19a3727a81a6b6f2459db859186227b96fe7a391263f69f1a0884e4235de64d29edebc7b99c44d19e7c7d7a", - "0x89579c51ac405ad7e9df13c904061670ce4b38372492764170e4d3d667ed52e5d15c7cd5c5991bbfa3a5e4e3fa16363e", - "0x9778f3e8639030f7ef1c344014f124e375acb8045bd13d8e97a92c5265c52de9d1ffebaa5bc3e1ad2719da0083222991", - "0x88f77f34ee92b3d36791bdf3326532524a67d544297dcf1a47ff00b47c1b8219ff11e34034eab7d23b507caa2fd3c6b9", - "0xa699c1e654e7c484431d81d90657892efeb4adcf72c43618e71ca7bd7c7a7ebbb1db7e06e75b75dc4c74efd306b5df3f", - "0x81d13153baebb2ef672b5bdb069d3cd669ce0be96b742c94e04038f689ff92a61376341366b286eee6bf3ae85156f694", - "0x81efb17de94400fdacc1deec2550cbe3eecb27c7af99d8207e2f9be397e26be24a40446d2a09536bb5172c28959318d9", - "0x989b21ebe9ceab02488992673dc071d4d5edec24bff0e17a4306c8cb4b3c83df53a2063d1827edd8ed16d6e837f0d222", - "0x8d6005d6536825661b13c5fdce177cb37c04e8b109b7eb2b6d82ea1cb70efecf6a0022b64f84d753d165edc2bba784a3", - "0xa32607360a71d5e34af2271211652d73d7756d393161f4cf0da000c2d66a84c6826e09e759bd787d4fd0305e2439d342", - "0xaaad8d6f6e260db45d51b2da723be6fa832e76f5fbcb77a9a31e7f090dd38446d3b631b96230d78208cae408c288ac4e", - "0xabcfe425255fd3c5cffd3a818af7650190c957b6b07b632443f9e33e970a8a4c3bf79ac9b71f4d45f238a04d1c049857", - "0xaeabf026d4c783adc4414b5923dbd0be4b039cc7201219f7260d321f55e9a5b166d7b5875af6129c034d0108fdc5d666", - "0xaf49e740c752d7b6f17048014851f437ffd17413c59797e5078eaaa36f73f0017c3e7da020310cfe7d3c85f94a99f203", - "0x8854ca600d842566e3090040cd66bb0b3c46dae6962a13946f0024c4a8aca447e2ccf6f240045f1ceee799a88cb9210c", - "0xb6c03b93b1ab1b88ded8edfa1b487a1ed8bdce8535244dddb558ffb78f89b1c74058f80f4db2320ad060d0c2a9c351cc", - "0xb5bd7d17372faff4898a7517009b61a7c8f6f0e7ed4192c555db264618e3f6e57fb30a472d169fea01bf2bf0362a19a8", - "0x96eb1d38319dc74afe7e7eb076fcd230d19983f645abd14a71e6103545c01301b31c47ae931e025f3ecc01fb3d2f31fa", - "0xb55a8d30d4403067def9b65e16f867299f8f64c9b391d0846d4780bc196569622e7e5b64ce799b5aefac8f965b2a7a7b", - "0x8356d199a991e5cbbff608752b6291731b6b6771aed292f8948b1f41c6543e4ab1bedc82dd26d10206c907c03508df06", - "0x97f4137445c2d98b0d1d478049de952610ad698c91c9d0f0e7227d2aae690e9935e914ec4a2ea1fbf3fc1dddfeeacebb", - "0xaf5621707e0938320b15ddfc87584ab325fbdfd85c30efea36f8f9bd0707d7ec12c344eff3ec21761189518d192df035", - "0x8ac7817e71ea0825b292687928e349da7140285d035e1e1abff0c3704fa8453faaae343a441b7143a74ec56539687cc4", - "0x8a5e0a9e4758449489df10f3386029ada828d1762e4fb0a8ffe6b79e5b6d5d713cb64ed95960e126398b0cdb89002bc9", - "0x81324be4a71208bbb9bca74b77177f8f1abb9d3d5d9db195d1854651f2cf333cd618d35400da0f060f3e1b025124e4b2", - "0x849971d9d095ae067525b3cbc4a7dfae81f739537ade6d6cec1b42fb692d923176197a8770907c58069754b8882822d6", - "0x89f830825416802477cc81fdf11084885865ee6607aa15aa4eb28e351c569c49b8a1b9b5e95ddc04fa0ebafe20071313", - "0x9240aeeaff37a91af55f860b9badd466e8243af9e8c96a7aa8cf348cd270685ab6301bc135b246dca9eda696f8b0e350", - "0xacf74db78cc33138273127599eba35b0fb4e7b9a69fe02dae18fc6692d748ca332bd00b22afa8e654ed587aab11833f3", - "0xb091e6d37b157b50d76bd297ad752220cd5c9390fac16dc838f8557aed6d9833fc920b61519df21265406216315e883f", - "0xa6446c429ebf1c7793c622250e23594c836b2fbcaf6c5b3d0995e1595a37f50ea643f3e549b0be8bbdadd69044d72ab9", - "0x93e675353bd60e996bf1c914d5267eeaa8a52fc3077987ccc796710ef9becc6b7a00e3d82671a6bdfb8145ee3c80245a", - "0xa2f731e43251d04ed3364aa2f072d05355f299626f2d71a8a38b6f76cf08c544133f7d72dd0ab4162814b674b9fc7fa6", - "0x97a8b791a5a8f6e1d0de192d78615d73d0c38f1e557e4e15d15adc663d649e655bc8da3bcc499ef70112eafe7fb45c7a", - "0x98cd624cbbd6c53a94469be4643c13130916b91143425bcb7d7028adbbfede38eff7a21092af43b12d4fab703c116359", - "0x995783ce38fd5f6f9433027f122d4cf1e1ff3caf2d196ce591877f4a544ce9113ead60de2de1827eaff4dd31a20d79a8", - "0x8cf251d6f5229183b7f3fe2f607a90b4e4b6f020fb4ba2459d28eb8872426e7be8761a93d5413640a661d73e34a5b81f", - "0xb9232d99620652a3aa7880cad0876f153ff881c4ed4c0c2e7b4ea81d5d42b70daf1a56b869d752c3743c6d4c947e6641", - "0x849716f938f9d37250cccb1bf77f5f9fde53096cdfc6f2a25536a6187029a8f1331cdbed08909184b201f8d9f04b792f", - "0x80c7c4de098cbf9c6d17b14eba1805e433b5bc905f6096f8f63d34b94734f2e4ebf4bce8a177efd1186842a61204a062", - "0xb790f410cf06b9b8daadceeb4fd5ff40a2deda820c8df2537e0a7554613ae3948e149504e3e79aa84889df50c8678eeb", - "0x813aab8bd000299cd37485b73cd7cba06e205f8efb87f1efc0bae8b70f6db2bc7702eb39510ad734854fb65515fe9d0f", - "0x94f0ab7388ac71cdb67f6b85dfd5945748afb2e5abb622f0b5ad104be1d4d0062b651f134ba22385c9e32c2dfdcccce1", - "0xab6223dca8bd6a4f969e21ccd9f8106fc5251d321f9e90cc42cea2424b3a9c4e5060a47eeef6b23c7976109b548498e8", - "0x859c56b71343fce4d5c5b87814c47bf55d581c50fd1871a17e77b5e1742f5af639d0e94d19d909ec7dfe27919e954e0c", - "0xaae0d632b6191b8ad71b027791735f1578e1b89890b6c22e37de0e4a6074886126988fe8319ae228ac9ef3b3bcccb730", - "0x8ca9f32a27a024c3d595ecfaf96b0461de57befa3b331ab71dc110ec3be5824fed783d9516597537683e77a11d334338", - "0xa061df379fb3f4b24816c9f6cd8a94ecb89b4c6dc6cd81e4b8096fa9784b7f97ab3540259d1de9c02eb91d9945af4823", - "0x998603102ac63001d63eb7347a4bb2bf4cf33b28079bb48a169076a65c20d511ccd3ef696d159e54cc8e772fb5d65d50", - "0x94444d96d39450872ac69e44088c252c71f46be8333a608a475147752dbb99db0e36acfc5198f158509401959c12b709", - "0xac1b51b6c09fe055c1d7c9176eea9adc33f710818c83a1fbfa073c8dc3a7eb3513cbdd3f5960b7845e31e3e83181e6ba", - "0x803d530523fc9e1e0f11040d2412d02baef3f07eeb9b177fa9bfa396af42eea898a4276d56e1db998dc96ae47b644cb2", - "0x85a3c9fc7638f5bf2c3e15ba8c2fa1ae87eb1ceb44c6598c67a2948667a9dfa41e61f66d535b4e7fda62f013a5a8b885", - "0xa961cf5654c46a1a22c29baf7a4e77837a26b7f138f410e9d1883480ed5fa42411d522aba32040b577046c11f007388e", - "0xad1154142344f494e3061ef45a34fab1aaacf5fdf7d1b26adbb5fbc3d795655fa743444e39d9a4119b4a4f82a6f30441", - "0xb1d6c30771130c77806e7ab893b73d4deb590b2ff8f2f8b5e54c2040c1f3e060e2bd99afc668cf706a2df666a508bbf6", - "0xa00361fd440f9decabd98d96c575cd251dc94c60611025095d1201ef2dedde51cb4de7c2ece47732e5ed9b3526c2012c", - "0xa85c5ab4d17d328bda5e6d839a9a6adcc92ff844ec25f84981e4f44a0e8419247c081530f8d9aa629c7eb4ca21affba6", - "0xa4ddd3eab4527a2672cf9463db38bc29f61460e2a162f426b7852b7a7645fbd62084fd39a8e4d60e1958cce436dd8f57", - "0x811648140080fe55b8618f4cf17f3c5a250adb0cd53d885f2ddba835d2b4433188e41fc0661faac88e4ff910b16278c0", - "0xb85c7f1cfb0ed29addccf7546023a79249e8f15ac2d14a20accbfef4dd9dc11355d599815fa09d2b6b4e966e6ea8cff1", - "0xa10b5d8c260b159043b020d5dd62b3467df2671afea6d480ca9087b7e60ed170c82b121819d088315902842d66c8fb45", - "0x917e191df1bcf3f5715419c1e2191da6b8680543b1ba41fe84ed07ef570376e072c081beb67b375fca3565a2565bcabb", - "0x881fd967407390bfd7badc9ab494e8a287559a01eb07861f527207c127eadea626e9bcc5aa9cca2c5112fbac3b3f0e9c", - "0x959fd71149af82cc733619e0e5bf71760ca2650448c82984b3db74030d0e10f8ab1ce1609a6de6f470fe8b5bd90df5b3", - "0xa3370898a1c5f33d15adb4238df9a6c945f18b9ada4ce2624fc32a844f9ece4c916a64e9442225b6592afa06d2e015f2", - "0x817efb8a791435e4236f7d7b278181a5fa34587578c629dbc14fbf9a5c26772290611395eecd20222a4c58649fc256d8", - "0xa04c9876acf2cfdc8ef96de4879742709270fa1d03fe4c8511fbef2d59eb0aaf0336fa2c7dfe41a651157377fa217813", - "0x81e15875d7ea7f123e418edf14099f2e109d4f3a6ce0eb65f67fe9fb10d2f809a864a29f60ad3fc949f89e2596b21783", - "0xb49f529975c09e436e6bc202fdc16e3fdcbe056db45178016ad6fdece9faad4446343e83aed096209690b21a6910724f", - "0x879e8eda589e1a279f7f49f6dd0580788c040d973748ec4942dbe51ea8fbd05983cc919b78f0c6b92ef3292ae29db875", - "0x81a2b74b2118923f34139a102f3d95e7eee11c4c2929c2576dee200a5abfd364606158535a6c9e4178a6a83dbb65f3c4", - "0x8913f281d8927f2b45fc815d0f7104631cb7f5f7278a316f1327d670d15868daadd2a64e3eb98e1f53fe7e300338cc80", - "0xa6f815fba7ef9af7fbf45f93bc952e8b351f5de6568a27c7c47a00cb39a254c6b31753794f67940fc7d2e9cc581529f4", - "0xb3722a15c66a0014ce4d082de118def8d39190c15678a472b846225585f3a83756ae1b255b2e3f86a26168878e4773b2", - "0x817ae61ab3d0dd5b6e24846b5a5364b1a7dc2e77432d9fed587727520ae2f307264ea0948c91ad29f0aea3a11ff38624", - "0xb3db467464415fcad36dc1de2d6ba7686772a577cc2619242ac040d6734881a45d3b40ed4588db124e4289cfeec4bbf6", - "0xad66a14f5a54ac69603b16e5f1529851183da77d3cc60867f10aea41339dd5e06a5257982e9e90a352cdd32750f42ee4", - "0xadafa3681ef45d685555601a25a55cf23358319a17f61e2179e704f63df83a73bdd298d12cf6cef86db89bd17119e11d", - "0xa379dc44cb6dd3b9d378c07b2ec654fec7ca2f272de6ba895e3d00d20c9e4c5550498a843c8ac67e4221db2115bedc1c", - "0xb7bf81c267a78efc6b9e5a904574445a6487678d7ef70054e3e93ea6a23f966c2b68787f9164918e3b16d2175459ed92", - "0xb41d66a13a4afafd5760062b77f79de7e6ab8ccacde9c6c5116a6d886912fb491dc027af435b1b44aacc6af7b3c887f2", - "0x9904d23a7c1c1d2e4bab85d69f283eb0a8e26d46e8b7b30224438015c936729b2f0af7c7c54c03509bb0500acb42d8a4", - "0xae30d65e9e20c3bfd603994ae2b175ff691d51f3e24b2d058b3b8556d12ca4c75087809062dddd4aaac81c94d15d8a17", - "0x9245162fab42ac01527424f6013310c3eb462982518debef6c127f46ba8a06c705d7dc9f0a41e796ba8d35d60ae6cc64", - "0x87fab853638d7a29a20f3ba2b1a7919d023e9415bfa78ebb27973d8cbc7626f584dc5665d2e7ad71f1d760eba9700d88", - "0x85aac46ecd330608e5272430970e6081ff02a571e8ea444f1e11785ea798769634a22a142d0237f67b75369d3c484a8a", - "0x938c85ab14894cc5dfce3d80456f189a2e98eddbc8828f4ff6b1df1dcb7b42b17ca2ff40226a8a1390a95d63dca698dd", - "0xa18ce1f846e3e3c4d846822f60271eecf0f5d7d9f986385ac53c5ace9589dc7c0188910448c19b91341a1ef556652fa9", - "0x8611608a9d844f0e9d7584ad6ccf62a5087a64f764caf108db648a776b5390feb51e5120f0ef0e9e11301af3987dd7dc", - "0x8106333ba4b4de8d1ae43bc9735d3fea047392e88efd6a2fa6f7b924a18a7a265ca6123c3edc0f36307dd7fb7fe89257", - "0xa91426fa500951ff1b051a248c050b7139ca30dde8768690432d597d2b3c4357b11a577be6b455a1c5d145264dcf81fc", - "0xb7f9f90e0e450f37b081297f7f651bad0496a8b9afd2a4cf4120a2671aaaa8536dce1af301258bfbfdb122afa44c5048", - "0x84126da6435699b0c09fa4032dec73d1fca21d2d19f5214e8b0bea43267e9a8dd1fc44f8132d8315e734c8e2e04d7291", - "0xaff064708103884cb4f1a3c1718b3fc40a238d35cf0a7dc24bdf9823693b407c70da50df585bf5bc4e9c07d1c2d203e8", - "0xa8b40fc6533752983a5329c31d376c7a5c13ce6879cc7faee648200075d9cd273537001fb4c86e8576350eaac6ba60c2", - "0xa02db682bdc117a84dcb9312eb28fcbde12d49f4ce915cc92c610bb6965ec3cc38290f8c5b5ec70afe153956692cda95", - "0x86decd22b25d300508472c9ce75d3e465b737e7ce13bc0fcce32835e54646fe12322ba5bc457be18bfd926a1a6ca4a38", - "0xa18666ef65b8c2904fd598791f5627207165315a85ee01d5fb0e6b2e10bdd9b00babc447da5bd63445e3337de33b9b89", - "0x89bb0c06effadefdaf34ffe4b123e1678a90d4451ee856c863df1e752eef41fd984689ded8f0f878bf8916d5dd8e8024", - "0x97cfcba08ebec05d0073992a66b1d7d6fb9d95871f2cdc36db301f78bf8069294d1c259efef5c93d20dc937eedae3a1a", - "0xac2643b14ece79dcb2e289c96776a47e2bebd40dd6dc74fd035df5bb727b5596f40e3dd2d2202141e69b0993717ede09", - "0xa5e6fd88a2f9174d9bd4c6a55d9c30974be414992f22aa852f552c7648f722ed8077acf5aba030abd47939bb451b2c60", - "0x8ad40a612824a7994487731a40b311b7349038c841145865539c6ada75c56de6ac547a1c23df190e0caaafecddd80ccc", - "0x953a7cea1d857e09202c438c6108060961f195f88c32f0e012236d7a4b39d840c61b162ec86436e8c38567328bea0246", - "0x80d8b47a46dae1868a7b8ccfe7029445bbe1009dad4a6c31f9ef081be32e8e1ac1178c3c8fb68d3e536c84990cc035b1", - "0x81ecd99f22b3766ce0aca08a0a9191793f68c754fdec78b82a4c3bdc2db122bbb9ebfd02fc2dcc6e1567a7d42d0cc16a", - "0xb1dd0446bccc25846fb95d08c1c9cc52fb51c72c4c5d169ffde56ecfe800f108dc1106d65d5c5bd1087c656de3940b63", - "0xb87547f0931e164e96de5c550ca5aa81273648fe34f6e193cd9d69cf729cb432e17aa02e25b1c27a8a0d20a3b795e94e", - "0x820a94e69a927e077082aae66f6b292cfbe4589d932edf9e68e268c9bd3d71ef76cf7d169dd445b93967c25db11f58f1", - "0xb0d07ddf2595270c39adfa0c8cf2ab1322979b0546aa4d918f641be53cd97f36c879bb75d205e457c011aca3bbd9f731", - "0x8700b876b35b4b10a8a9372c5230acecd39539c1bb87515640293ad4464a9e02929d7d6a6a11112e8a29564815ac0de4", - "0xa61a601c5bb27dcb97e37c8e2b9ce479c6b192a5e04d9ed5e065833c5a1017ee5f237b77d1a17be5d48f8e7cc0bcacf6", - "0x92fb88fe774c1ba1d4a08cae3c0e05467ad610e7a3f1d2423fd47751759235fe0a3036db4095bd6404716aa03820f484", - "0xb274f140d77a3ce0796f5e09094b516537ccaf27ae1907099bff172e6368ba85e7c3ef8ea2a07457cac48ae334da95b3", - "0xb2292d9181f16581a9a9142490b2bdcdfb218ca6315d1effc8592100d792eb89d5356996c890441f04f2b4a95763503e", - "0x8897e73f576d86bc354baa3bd96e553107c48cf5889dcc23c5ba68ab8bcd4e81f27767be2233fdfa13d39f885087e668", - "0xa29eac6f0829791c728d71abc49569df95a4446ecbfc534b39f24f56c88fe70301838dfc1c19751e7f3c5c1b8c6af6a0", - "0x9346dc3720adc5df500a8df27fd9c75ef38dc5c8f4e8ed66983304750e66d502c3c59b8e955be781b670a0afc70a2167", - "0x9566d534e0e30a5c5f1428665590617e95fd05d45f573715f58157854ad596ece3a3cfec61356aee342308d623e029d5", - "0xa464fb8bffe6bd65f71938c1715c6e296cc6d0311a83858e4e7eb5873b7f2cf0c584d2101e3407b85b64ca78b2ac93ce", - "0xb54088f7217987c87e9498a747569ac5b2f8afd5348f9c45bf3fd9fbf713a20f495f49c8572d087efe778ac7313ad6d3", - "0x91fa9f5f8000fe050f5b224d90b59fcce13c77e903cbf98ded752e5b3db16adb2bc1f8c94be48b69f65f1f1ad81d6264", - "0x92d04a5b0ac5d8c8e313709b432c9434ecd3e73231f01e9b4e7952b87df60cbfa97b5dedd2200bd033b4b9ea8ba45cc1", - "0xa94b90ad3c3d6c4bbe169f8661a790c40645b40f0a9d1c7220f01cf7fc176e04d80bab0ced9323fcafb93643f12b2760", - "0x94d86149b9c8443b46196f7e5a3738206dd6f3be7762df488bcbb9f9ee285a64c997ed875b7b16b26604fa59020a8199", - "0x82efe4ae2c50a2d7645240c173a047f238536598c04a2c0b69c96e96bd18e075a99110f1206bc213f39edca42ba00cc1", - "0xab8667685f831bc14d4610f84a5da27b4ea5b133b4d991741a9e64dceb22cb64a3ce8f1b6e101d52af6296df7127c9ad", - "0x83ba433661c05dcc5d562f4a9a261c8110dac44b8d833ae1514b1fc60d8b4ee395b18804baea04cb10adb428faf713c3", - "0xb5748f6f660cc5277f1211d2b8649493ed8a11085b871cd33a5aea630abd960a740f08c08be5f9c21574600ac9bf5737", - "0xa5c8dd12af48fb710642ad65ebb97ca489e8206741807f7acfc334f8035d3c80593b1ff2090c9bb7bd138f0c48714ca8", - "0xa2b382fd5744e3babf454b1d806cc8783efeb4761bc42b6914ea48a46a2eae835efbe0a18262b6bc034379e03cf1262b", - "0xb3145ffaf603f69f15a64936d32e3219eea5ed49fdfd2f5bf40ea0dfd974b36fb6ff12164d4c2282d892db4cf3ff3ce1", - "0x87a316fb213f4c5e30c5e3face049db66be4f28821bd96034714ec23d3e97849d7b301930f90a4323c7ccf53de23050c", - "0xb9de09a919455070fed6220fc179c8b7a4c753062bcd27acf28f5b9947a659c0b364298daf7c85c4ca6fca7f945add1f", - "0x806fbd98d411b76979464c40ad88bc07a151628a27fcc1012ba1dfbaf5b5cc9d962fb9b3386008978a12515edce934bc", - "0xa15268877fae0d21610ae6a31061ed7c20814723385955fac09fdc9693a94c33dea11db98bb89fdfe68f933490f5c381", - "0x8d633fb0c4da86b2e0b37d8fad5972d62bff2ac663c5ec815d095cd4b7e1fe66ebef2a2590995b57eaf941983c7ad7a4", - "0x8139e5dd9cf405e8ef65f11164f0440827d98389ce1b418b0c9628be983a9ddd6cf4863036ccb1483b40b8a527acd9ed", - "0x88b15fa94a08eac291d2b94a2b30eb851ff24addf2cc30b678e72e32cfcb3424cf4b33aa395d741803f3e578ddf524de", - "0xb5eaf0c8506e101f1646bcf049ee38d99ea1c60169730da893fd6020fd00a289eb2f415947e44677af49e43454a7b1be", - "0x8489822ad0647a7e06aa2aa5595960811858ddd4542acca419dd2308a8c5477648f4dd969a6740bb78aa26db9bfcc555", - "0xb1e9a7b9f3423c220330d45f69e45fa03d7671897cf077f913c252e3e99c7b1b1cf6d30caad65e4228d5d7b80eb86e5e", - "0xb28fe9629592b9e6a55a1406903be76250b1c50c65296c10c5e48c64b539fb08fe11f68cf462a6edcbba71b0cee3feb2", - "0xa41acf96a02c96cd8744ff6577c244fc923810d17ade133587e4c223beb7b4d99fa56eae311a500d7151979267d0895c", - "0x880798938fe4ba70721be90e666dfb62fcab4f3556fdb7b0dc8ec5bc34f6b4513df965eae78527136eb391889fe2caf9", - "0x98d4d89d358e0fb7e212498c73447d94a83c1b66e98fc81427ab13acddb17a20f52308983f3a5a8e0aaacec432359604", - "0x81430b6d2998fc78ba937a1639c6020199c52da499f68109da227882dc26d005b73d54c5bdcac1a04e8356a8ca0f7017", - "0xa8d906a4786455eb74613aba4ce1c963c60095ffb8658d368df9266fdd01e30269ce10bf984e7465f34b4fd83beba26a", - "0xaf54167ac1f954d10131d44a8e0045df00d581dd9e93596a28d157543fbe5fb25d213806ed7fb3cba6b8f5b5423562db", - "0x8511e373a978a12d81266b9afbd55035d7bc736835cfa921903a92969eeba3624437d1346b55382e61415726ab84a448", - "0x8cf43eea93508ae586fa9a0f1354a1e16af659782479c2040874a46317f9e8d572a23238efa318fdfb87cc63932602b7", - "0xb0bdd3bacff077173d302e3a9678d1d37936188c7ecc34950185af6b462b7c679815176f3cce5db19aac8b282f2d60ad", - "0xa355e9b87f2f2672052f5d4d65b8c1c827d24d89b0d8594641fccfb69aef1b94009105f3242058bb31c8bf51caae5a41", - "0xb8baa9e4b950b72ff6b88a6509e8ed1304bc6fd955748b2e59a523a1e0c5e99f52aec3da7fa9ff407a7adf259652466c", - "0x840bc3dbb300ea6f27d1d6dd861f15680bd098be5174f45d6b75b094d0635aced539fa03ddbccb453879de77fb5d1fe9", - "0xb4bc7e7e30686303856472bae07e581a0c0bfc815657c479f9f5931cff208d5c12930d2fd1ff413ebd8424bcd7a9b571", - "0x89b5d514155d7999408334a50822508b9d689add55d44a240ff2bdde2eee419d117031f85e924e2a2c1ca77db9b91eea", - "0xa8604b6196f87a04e1350302e8aa745bba8dc162115d22657b37a1d1a98cb14876ddf7f65840b5dbd77e80cd22b4256c", - "0x83cb7acdb9e03247515bb2ce0227486ccf803426717a14510f0d59d45e998b245797d356f10abca94f7a14e1a2f0d552", - "0xaeb3266a9f16649210ab2df0e1908ac259f34ce1f01162c22b56cf1019096ee4ea5854c36e30bb2feb06c21a71e8a45c", - "0x89e72e86edf2aa032a0fc9acf4d876a40865fbb2c8f87cb7e4d88856295c4ac14583e874142fd0c314a49aba68c0aa3c", - "0x8c3576eba0583c2a7884976b4ed11fe1fda4f6c32f6385d96c47b0e776afa287503b397fa516a455b4b8c3afeedc76db", - "0xa31e5b633bda9ffa174654fee98b5d5930a691c3c42fcf55673d927dbc8d91c58c4e42e615353145431baa646e8bbb30", - "0x89f2f3f7a8da1544f24682f41c68114a8f78c86bd36b066e27da13acb70f18d9f548773a16bd8e24789420e17183f137", - "0xada27fa4e90a086240c9164544d2528621a415a5497badb79f8019dc3dce4d12eb6b599597e47ec6ac39c81efda43520", - "0x90dc1eb21bf21c0187f359566fc4bf5386abea52799306a0e5a1151c0817c5f5bc60c86e76b1929c092c0f3ff48cedd2", - "0xb702a53ebcc17ae35d2e735a347d2c700e9cbef8eadbece33cac83df483b2054c126593e1f462cfc00a3ce9d737e2af5", - "0x9891b06455ec925a6f8eafffba05af6a38cc5e193acaaf74ffbf199df912c5197106c5e06d72942bbb032ce277b6417f", - "0x8c0ee71eb01197b019275bcf96cae94e81d2cdc3115dbf2d8e3080074260318bc9303597e8f72b18f965ad601d31ec43", - "0x8aaf580aaf75c1b7a5f99ccf60503506e62058ef43b28b02f79b8536a96be3f019c9f71caf327b4e6730134730d1bef5", - "0xae6f9fc21dd7dfa672b25a87eb0a41644f7609fab5026d5cedb6e43a06dbbfd6d6e30322a2598c8dedde88c52eaed626", - "0x8159b953ffece5693edadb2e906ebf76ff080ee1ad22698950d2d3bfc36ac5ea78f58284b2ca180664452d55bd54716c", - "0xab7647c32ca5e9856ac283a2f86768d68de75ceeba9e58b74c5324f8298319e52183739aba4340be901699d66ac9eb3f", - "0xa4d85a5701d89bcfaf1572db83258d86a1a0717603d6f24ac2963ffcf80f1265e5ab376a4529ca504f4396498791253c", - "0x816080c0cdbfe61b4d726c305747a9eb58ac26d9a35f501dd32ba43c098082d20faf3ccd41aad24600aa73bfa453dfac", - "0x84f3afac024f576b0fd9acc6f2349c2fcefc3f77dbe5a2d4964d14b861b88e9b1810334b908cf3427d9b67a8aee74b18", - "0x94b390655557b1a09110018e9b5a14490681ade275bdc83510b6465a1218465260d9a7e2a6e4ec700f58c31dc3659962", - "0xa8c66826b1c04a2dd4c682543242e7a57acae37278bd09888a3d17747c5b5fec43548101e6f46d703638337e2fd3277b", - "0x86e6f4608a00007fa533c36a5b054c5768ccafe41ad52521d772dcae4c8a4bcaff8f7609be30d8fab62c5988cbbb6830", - "0x837da4cf09ae8aa0bceb16f8b3bfcc3b3367aecac9eed6b4b56d7b65f55981ef066490764fb4c108792623ecf8cad383", - "0x941ff3011462f9b5bf97d8cbdb0b6f5d37a1b1295b622f5485b7d69f2cb2bcabc83630dae427f0259d0d9539a77d8424", - "0xb99e5d6d82aa9cf7d5970e7f710f4039ac32c2077530e4c2779250c6b9b373bc380adb0a03b892b652f649720672fc8c", - "0xa791c78464b2d65a15440b699e1e30ebd08501d6f2720adbc8255d989a82fcded2f79819b5f8f201bed84a255211b141", - "0x84af7ad4a0e31fcbb3276ab1ad6171429cf39adcf78dc03750dc5deaa46536d15591e26d53e953dfb31e1622bc0743ab", - "0xa833e62fe97e1086fae1d4917fbaf09c345feb6bf1975b5cb863d8b66e8d621c7989ab3dbecda36bc9eaffc5eaa6fa66", - "0xb4ef79a46a2126f53e2ebe62770feb57fd94600be29459d70a77c5e9cc260fa892be06cd60f886bf48459e48eb50d063", - "0xb43b8f61919ea380bf151c294e54d3a3ff98e20d1ee5efbfe38aa2b66fafbc6a49739793bd5cb1c809f8b30466277c3a", - "0xab37735af2412d2550e62df9d8b3b5e6f467f20de3890bf56faf1abf2bf3bd1d98dc3fa0ad5e7ab3fce0fa20409eb392", - "0x82416b74b1551d484250d85bb151fabb67e29cce93d516125533df585bc80779ab057ea6992801a3d7d5c6dcff87a018", - "0x8145d0787f0e3b5325190ae10c1d6bee713e6765fb6a0e9214132c6f78f4582bb2771aaeae40d3dad4bafb56bf7e36d8", - "0xb6935886349ecbdd5774e12196f4275c97ec8279fdf28ccf940f6a022ebb6de8e97d6d2173c3fe402cbe9643bed3883b", - "0x87ef9b4d3dc71ac86369f8ed17e0dd3b91d16d14ae694bc21a35b5ae37211b043d0e36d8ff07dcc513fb9e6481a1f37f", - "0xae1d0ded32f7e6f1dc8fef495879c1d9e01826f449f903c1e5034aeeabc5479a9e323b162b688317d46d35a42d570d86", - "0xa40d16497004db4104c6794e2f4428d75bdf70352685944f3fbe17526df333e46a4ca6de55a4a48c02ecf0bde8ba03c0", - "0x8d45121efba8cc308a498e8ee39ea6fa5cae9fb2e4aab1c2ff9d448aa8494ccbec9a078f978a86fcd97b5d5e7be7522a", - "0xa8173865c64634ba4ac2fa432740f5c05056a9deaf6427cb9b4b8da94ca5ddbc8c0c5d3185a89b8b28878194de9cdfcd", - "0xb6ec06a74d690f6545f0f0efba236e63d1fdfba54639ca2617408e185177ece28901c457d02b849fd00f1a53ae319d0a", - "0xb69a12df293c014a40070e3e760169b6f3c627caf9e50b35a93f11ecf8df98b2bc481b410eecb7ab210bf213bbe944de", - "0x97e7dc121795a533d4224803e591eef3e9008bab16f12472210b73aaf77890cf6e3877e0139403a0d3003c12c8f45636", - "0xacdfa6fdd4a5acb7738cc8768f7cba84dbb95c639399b291ae8e4e63df37d2d4096900a84d2f0606bf534a9ccaa4993f", - "0x86ee253f3a9446a33e4d1169719b7d513c6b50730988415382faaf751988c10a421020609f7bcdef91be136704b906e2", - "0xaac9438382a856caf84c5a8a234282f71b5fc5f65219103b147e7e6cf565522285fbfd7417b513bdad8277a00f652ca1", - "0x83f3799d8e5772527930f5dc071a2e0a65471618993ec8990a96ccdeee65270e490bda9d26bb877612475268711ffd80", - "0x93f28a81ac8c0ec9450b9d762fae9c7f8feaace87a6ee6bd141ef1d2d0697ef1bbd159fe6e1de640dbdab2b0361fca8a", - "0xa0825c95ba69999b90eac3a31a3fd830ea4f4b2b7409bde5f202b61d741d6326852ce790f41de5cb0eccec7af4db30c1", - "0x83924b0e66233edd603c3b813d698daa05751fc34367120e3cf384ea7432e256ccee4d4daf13858950549d75a377107d", - "0x956fd9fa58345277e06ba2ec72f49ed230b8d3d4ff658555c52d6cddeb84dd4e36f1a614f5242d5ca0192e8daf0543c2", - "0x944869912476baae0b114cced4ff65c0e4c90136f73ece5656460626599051b78802df67d7201c55d52725a97f5f29fe", - "0x865cb25b64b4531fb6fe4814d7c8cd26b017a6c6b72232ff53defc18a80fe3b39511b23f9e4c6c7249d06e03b2282ed2", - "0x81e09ff55214960775e1e7f2758b9a6c4e4cd39edf7ec1adfaad51c52141182b79fe2176b23ddc7df9fd153e5f82d668", - "0xb31006896f02bc90641121083f43c3172b1039334501fbaf1672f7bf5d174ddd185f945adf1a9c6cf77be34c5501483d", - "0x88b92f6f42ae45e9f05b16e52852826e933efd0c68b0f2418ac90957fd018df661bc47c8d43c2a7d7bfcf669dab98c3c", - "0x92fc68f595853ee8683930751789b799f397135d002eda244fe63ecef2754e15849edde3ba2f0cc8b865c9777230b712", - "0x99ca06a49c5cd0bb097c447793fcdd809869b216a34c66c78c7e41e8c22f05d09168d46b8b1f3390db9452d91bc96dea", - "0xb48b9490a5d65296802431852d548d81047bbefc74fa7dc1d4e2a2878faacdfcb365ae59209cb0ade01901a283cbd15d", - "0xaff0fdbef7c188b120a02bc9085d7b808e88f73973773fef54707bf2cd772cd066740b1b6f4127b5c349f657bd97e738", - "0x966fd4463b4f43dd8ccba7ad50baa42292f9f8b2e70da23bb6780e14155d9346e275ef03ddaf79e47020dcf43f3738bd", - "0x9330c3e1fadd9e08ac85f4839121ae20bbeb0a5103d84fa5aadbd1213805bdcda67bf2fb75fc301349cbc851b5559d20", - "0x993bb99867bd9041a71a55ad5d397755cfa7ab6a4618fc526179bfc10b7dc8b26e4372fe9a9b4a15d64f2b63c1052dda", - "0xa29b59bcfab51f9b3c490a3b96f0bf1934265c315349b236012adbd64a56d7f6941b2c8cc272b412044bc7731f71e1dc", - "0xa65c9cefe1fc35d089fe8580c2e7671ebefdb43014ac291528ff4deefd4883fd4df274af83711dad610dad0d615f9d65", - "0x944c78c56fb227ae632805d448ca3884cd3d2a89181cead3d2b7835e63297e6d740aa79a112edb1d4727824991636df5", - "0xa73d782da1db7e4e65d7b26717a76e16dd9fab4df65063310b8e917dc0bc24e0d6755df5546c58504d04d9e68c3b474a", - "0xaf80f0b87811ae3124f68108b4ca1937009403f87928bbc53480e7c5408d072053ace5eeaf5a5aba814dab8a45502085", - "0x88aaf1acfc6e2e19b8387c97da707cb171c69812fefdd4650468e9b2c627bd5ccfb459f4d8e56bdfd84b09ddf87e128f", - "0x92c97276ff6f72bab6e9423d02ad6dc127962dbce15a0dd1e4a393b4510c555df6aa27be0f697c0d847033a9ca8b8dfd", - "0xa0e07d43d96e2d85b6276b3c60aadb48f0aedf2de8c415756dc597249ea64d2093731d8735231dadc961e5682ac59479", - "0xadc9e6718a8f9298957d1da3842a7751c5399bbdf56f8de6c1c4bc39428f4aee6f1ba6613d37bf46b9403345e9d6fc81", - "0x951da434da4b20d949b509ceeba02e24da7ed2da964c2fcdf426ec787779c696b385822c7dbea4df3e4a35921f1e912c", - "0xa04cbce0d2b2e87bbf038c798a12ec828423ca6aca08dc8d481cf6466e3c9c73d4d4a7fa47df9a7e2e15aae9e9f67208", - "0x8f855cca2e440d248121c0469de1f94c2a71b8ee2682bbad3a78243a9e03da31d1925e6760dbc48a1957e040fae9abe8", - "0xb642e5b17c1df4a4e101772d73851180b3a92e9e8b26c918050f51e6dd3592f102d20b0a1e96f0e25752c292f4c903ff", - "0xa92454c300781f8ae1766dbbb50a96192da7d48ef4cbdd72dd8cbb44c6eb5913c112cc38e9144615fdc03684deb99420", - "0x8b74f7e6c2304f8e780df4649ef8221795dfe85fdbdaa477a1542d135b75c8be45bf89adbbb6f3ddf54ca40f02e733e9", - "0x85cf66292cbb30cec5fd835ab10c9fcb3aea95e093aebf123e9a83c26f322d76ebc89c4e914524f6c5f6ee7d74fc917d", - "0xae0bfe0cdc97c09542a7431820015f2d16067b30dca56288013876025e81daa8c519e5e347268e19aa1a85fa1dc28793", - "0x921322fc6a47dc091afa0ad6df18ed14cde38e48c6e71550aa513918b056044983aee402de21051235eecf4ce8040fbe", - "0x96c030381e97050a45a318d307dcb3c8377b79b4dd5daf6337cded114de26eb725c14171b9b8e1b3c08fe1f5ea6b49e0", - "0x90c23b86b6111818c8baaf53a13eaee1c89203b50e7f9a994bf0edf851919b48edbac7ceef14ac9414cf70c486174a77", - "0x8bf6c301240d2d1c8d84c71d33a6dfc6d9e8f1cfae66d4d0f7a256d98ae12b0bcebfa94a667735ee89f810bcd7170cff", - "0xa41a4ffbbea0e36874d65c009ee4c3feffff322f6fc0e30d26ee4dbc1f46040d05e25d9d0ecb378cef0d24a7c2c4b850", - "0xa8d4cdd423986bb392a0a92c12a8bd4da3437eec6ef6af34cf5310944899287452a2eb92eb5386086d5063381189d10e", - "0xa81dd26ec057c4032a4ed7ad54d926165273ed51d09a1267b2e477535cf6966835a257c209e4e92d165d74fa75695fa3", - "0x8d7f708c3ee8449515d94fc26b547303b53d8dd55f177bc3b25d3da2768accd9bc8e9f09546090ebb7f15c66e6c9c723", - "0x839ba65cffcd24cfffa7ab3b21faabe3c66d4c06324f07b2729c92f15cad34e474b0f0ddb16cd652870b26a756b731d3", - "0x87f1a3968afec354d92d77e2726b702847c6afcabb8438634f9c6f7766de4c1504317dc4fa9a4a735acdbf985e119564", - "0x91a8a7fd6542f3e0673f07f510d850864b34ac087eb7eef8845a1d14b2b1b651cbdc27fa4049bdbf3fea54221c5c8549", - "0xaef3cf5f5e3a2385ead115728d7059e622146c3457d266c612e778324b6e06fbfb8f98e076624d2f3ce1035d65389a07", - "0x819915d6232e95ccd7693fdd78d00492299b1983bc8f96a08dcb50f9c0a813ed93ae53c0238345d5bea0beda2855a913", - "0x8e9ba68ded0e94935131b392b28218315a185f63bf5e3c1a9a9dd470944509ca0ba8f6122265f8da851b5cc2abce68f1", - "0xb28468e9b04ee9d69003399a3cf4457c9bf9d59f36ab6ceeb8e964672433d06b58beeea198fedc7edbaa1948577e9fa2", - "0xa633005e2c9f2fd94c8bce2dd5bb708fe946b25f1ec561ae65e54e15cdd88dc339f1a083e01f0d39610c8fe24151aaf0", - "0x841d0031e22723f9328dd993805abd13e0c99b0f59435d2426246996b08d00ce73ab906f66c4eab423473b409e972ce0", - "0x85758d1b084263992070ec8943f33073a2d9b86a8606672550c17545507a5b3c88d87382b41916a87ee96ff55a7aa535", - "0x8581b06b0fc41466ef94a76a1d9fb8ae0edca6d018063acf6a8ca5f4b02d76021902feba58972415691b4bdbc33ae3b4", - "0x83539597ff5e327357ee62bc6bf8c0bcaec2f227c55c7c385a4806f0d37fb461f1690bad5066b8a5370950af32fafbef", - "0xaee3557290d2dc10827e4791d00e0259006911f3f3fce4179ed3c514b779160613eca70f720bff7804752715a1266ffa", - "0xb48d2f0c4e90fc307d5995464e3f611a9b0ef5fe426a289071f4168ed5cc4f8770c9332960c2ca5c8c427f40e6bb389f", - "0x847af8973b4e300bb06be69b71b96183fd1a0b9d51b91701bef6fcfde465068f1eb2b1503b07afda380f18d69de5c9e1", - "0xa70a6a80ce407f07804c0051ac21dc24d794b387be94eb24e1db94b58a78e1bcfb48cd0006db8fc1f9bedaece7a44fbe", - "0xb40e942b8fa5336910ff0098347df716bff9d1fa236a1950c16eeb966b3bc1a50b8f7b0980469d42e75ae13ced53cead", - "0xb208fabaa742d7db3148515330eb7a3577487845abdb7bd9ed169d0e081db0a5816595c33d375e56aeac5b51e60e49d3", - "0xb7c8194b30d3d6ef5ab66ec88ad7ebbc732a3b8a41731b153e6f63759a93f3f4a537eab9ad369705bd730184bdbbdc34", - "0x9280096445fe7394d04aa1bc4620c8f9296e991cc4d6c131bd703cb1cc317510e6e5855ac763f4d958c5edfe7eebeed7", - "0xabc2aa4616a521400af1a12440dc544e3c821313d0ab936c86af28468ef8bbe534837e364598396a81cf8d06274ed5a6", - "0xb18ca8a3325adb0c8c18a666d4859535397a1c3fe08f95eebfac916a7a99bbd40b3c37b919e8a8ae91da38bc00fa56c0", - "0x8a40c33109ecea2a8b3558565877082f79121a432c45ec2c5a5e0ec4d1c203a6788e6b69cb37f1fd5b8c9a661bc5476d", - "0x88c47301dd30998e903c84e0b0f2c9af2e1ce6b9f187dab03528d44f834dc991e4c86d0c474a2c63468cf4020a1e24a0", - "0x920c832853e6ab4c851eecfa9c11d3acc7da37c823be7aa1ab15e14dfd8beb5d0b91d62a30cec94763bd8e4594b66600", - "0x98e1addbe2a6b8edc7f12ecb9be81c3250aeeca54a1c6a7225772ca66549827c15f3950d01b8eb44aecb56fe0fff901a", - "0x8cfb0fa1068be0ec088402f5950c4679a2eb9218c729da67050b0d1b2d7079f3ddf4bf0f57d95fe2a8db04bc6bcdb20c", - "0xb70f381aafe336b024120453813aeab70baac85b9c4c0f86918797b6aee206e6ed93244a49950f3d8ec9f81f4ac15808", - "0xa4c8edf4aa33b709a91e1062939512419711c1757084e46f8f4b7ed64f8e682f4e78b7135920c12f0eb0422fe9f87a6a", - "0xb4817e85fd0752d7ebb662d3a51a03367a84bac74ebddfba0e5af5e636a979500f72b148052d333b3dedf9edd2b4031b", - "0xa87430169c6195f5d3e314ff2d1c2f050e766fd5d2de88f5207d72dba4a7745bb86d0baca6e9ae156582d0d89e5838c7", - "0x991b00f8b104566b63a12af4826b61ce7aa40f4e5b8fff3085e7a99815bdb4471b6214da1e480214fac83f86a0b93cc5", - "0xb39966e3076482079de0678477df98578377a094054960ee518ef99504d6851f8bcd3203e8da5e1d4f6f96776e1fe6eb", - "0xa448846d9dc2ab7a0995fa44b8527e27f6b3b74c6e03e95edb64e6baa4f1b866103f0addb97c84bef1d72487b2e21796", - "0x894bec21a453ae84b592286e696c35bc30e820e9c2fd3e63dd4fbe629e07df16439c891056070faa490155f255bf7187", - "0xa9ec652a491b11f6a692064e955f3f3287e7d2764527e58938571469a1e29b5225b9415bd602a45074dfbfe9c131d6ca", - "0xb39d37822e6cbe28244b5f42ce467c65a23765bd16eb6447c5b3e942278069793763483dafd8c4dd864f8917aad357fe", - "0x88dba51133f2019cb266641c56101e3e5987d3b77647a2e608b5ff9113dfc5f85e2b7c365118723131fbc0c9ca833c9c", - "0xb566579d904b54ecf798018efcb824dccbebfc6753a0fd2128ac3b4bd3b038c2284a7c782b5ca6f310eb7ea4d26a3f0a", - "0xa97a55c0a492e53c047e7d6f9d5f3e86fb96f3dddc68389c0561515343b66b4bc02a9c0d5722dff1e3445308240b27f7", - "0xa044028ab4bcb9e1a2b9b4ca4efbf04c5da9e4bf2fff0e8bd57aa1fc12a71e897999c25d9117413faf2f45395dee0f13", - "0xa78dc461decbeaeed8ebd0909369b491a5e764d6a5645a7dac61d3140d7dc0062526f777b0eb866bff27608429ebbdde", - "0xb2c2a8991f94c39ca35fea59f01a92cb3393e0eccb2476dfbf57261d406a68bd34a6cff33ed80209991688c183609ef4", - "0x84189eefb521aff730a4fd3fd5b10ddfd29f0d365664caef63bb015d07e689989e54c33c2141dd64427805d37a7e546e", - "0x85ac80bd734a52235da288ff042dea9a62e085928954e8eacd2c751013f61904ed110e5b3afe1ab770a7e6485efb7b5e", - "0x9183a560393dcb22d0d5063e71182020d0fbabb39e32493eeffeb808df084aa243eb397027f150b55a247d1ed0c8513e", - "0x81c940944df7ecc58d3c43c34996852c3c7915ed185d7654627f7af62abae7e0048dd444a6c09961756455000bd96d09", - "0xaa8c34e164019743fd8284b84f06c3b449aae7996e892f419ee55d82ad548cb300fd651de329da0384243954c0ef6a60", - "0x89a7b7bdfc7e300d06a14d463e573d6296d8e66197491900cc9ae49504c4809ff6e61b758579e9091c61085ba1237b83", - "0x878d21809ba540f50bd11f4c4d9590fb6f3ab9de5692606e6e2ef4ed9d18520119e385be5e1f4b3f2e2b09c319f0e8fc", - "0x8eb248390193189cf0355365e630b782cd15751e672dc478b39d75dc681234dcd9309df0d11f4610dbb249c1e6be7ef9", - "0xa1d7fb3aecb896df3a52d6bd0943838b13f1bd039c936d76d03de2044c371d48865694b6f532393b27fd10a4cf642061", - "0xa34bca58a24979be442238cbb5ece5bee51ae8c0794dd3efb3983d4db713bc6f28a96e976ac3bd9a551d3ed9ba6b3e22", - "0x817c608fc8cacdd178665320b5a7587ca21df8bdd761833c3018b967575d25e3951cf3d498a63619a3cd2ad4406f5f28", - "0x86c95707db0495689afd0c2e39e97f445f7ca0edffad5c8b4cacd1421f2f3cc55049dfd504f728f91534e20383955582", - "0x99c3b0bb15942c301137765d4e19502f65806f3b126dc01a5b7820c87e8979bce6a37289a8f6a4c1e4637227ad5bf3bf", - "0x8aa1518a80ea8b074505a9b3f96829f5d4afa55a30efe7b4de4e5dbf666897fdd2cf31728ca45921e21a78a80f0e0f10", - "0x8d74f46361c79e15128ac399e958a91067ef4cec8983408775a87eca1eed5b7dcbf0ddf30e66f51780457413496c7f07", - "0xa41cde4a786b55387458a1db95171aca4fd146507b81c4da1e6d6e495527c3ec83fc42fad1dfe3d92744084a664fd431", - "0x8c352852c906fae99413a84ad11701f93f292fbf7bd14738814f4c4ceab32db02feb5eb70bc73898b0bc724a39d5d017", - "0xa5993046e8f23b71ba87b7caa7ace2d9023fb48ce4c51838813174880d918e9b4d2b0dc21a2b9c6f612338c31a289df8", - "0x83576d3324bf2d8afbfb6eaecdc5d767c8e22e7d25160414924f0645491df60541948a05e1f4202e612368e78675de8a", - "0xb43749b8df4b15bc9a3697e0f1c518e6b04114171739ef1a0c9c65185d8ec18e40e6954d125cbc14ebc652cf41ad3109", - "0xb4eebd5d80a7327a040cafb9ccdb12b2dfe1aa86e6bc6d3ac8a57fadfb95a5b1a7332c66318ff72ba459f525668af056", - "0x9198be7f1d413c5029b0e1c617bcbc082d21abe2c60ec8ce9b54ca1a85d3dba637b72fda39dae0c0ae40d047eab9f55a", - "0x8d96a0232832e24d45092653e781e7a9c9520766c3989e67bbe86b3a820c4bf621ea911e7cd5270a4bfea78b618411f6", - "0x8d7160d0ea98161a2d14d46ef01dff72d566c330cd4fabd27654d300e1bc7644c68dc8eabf2a20a59bfe7ba276545f9b", - "0xabb60fce29dec7ba37e3056e412e0ec3e05538a1fc0e2c68877378c867605966108bc5742585ab6a405ce0c962b285b6", - "0x8fabffa3ed792f05e414f5839386f6449fd9f7b41a47595c5d71074bd1bb3784cc7a1a7e1ad6b041b455035957e5b2dc", - "0x90ff017b4804c2d0533b72461436b10603ab13a55f86fd4ec11b06a70ef8166f958c110519ca1b4cc7beba440729fe2d", - "0xb340cfd120f6a4623e3a74cf8c32bfd7cd61a280b59dfd17b15ca8fae4d82f64a6f15fbde4c02f424debc72b7db5fe67", - "0x871311c9c7220c932e738d59f0ecc67a34356d1429fe570ca503d340c9996cb5ee2cd188fad0e3bd16e4c468ec1dbebd", - "0xa772470262186e7b94239ba921b29f2412c148d6f97c4412e96d21e55f3be73f992f1ad53c71008f0558ec3f84e2b5a7", - "0xb2a897dcb7ffd6257f3f2947ec966f2077d57d5191a88840b1d4f67effebe8c436641be85524d0a21be734c63ab5965d", - "0xa044f6eacc48a4a061fa149500d96b48cbf14853469aa4d045faf3dca973be1bd4b4ce01646d83e2f24f7c486d03205d", - "0x981af5dc2daa73f7fa9eae35a93d81eb6edba4a7f673b55d41f6ecd87a37685d31bb40ef4f1c469b3d72f2f18b925a17", - "0x912d2597a07864de9020ac77083eff2f15ceb07600f15755aba61251e8ce3c905a758453b417f04d9c38db040954eb65", - "0x9642b7f6f09394ba5e0805734ef6702c3eddf9eea187ba98c676d5bbaec0e360e3e51dc58433aaa1e2da6060c8659cb7", - "0x8ab3836e0a8ac492d5e707d056310c4c8e0489ca85eb771bff35ba1d658360084e836a6f51bb990f9e3d2d9aeb18fbb5", - "0x879e058e72b73bb1f4642c21ffdb90544b846868139c6511f299aafe59c2d0f0b944dffc7990491b7c4edcd6a9889250", - "0xb9e60b737023f61479a4a8fd253ed0d2a944ea6ba0439bbc0a0d3abf09b0ad1f18d75555e4a50405470ae4990626f390", - "0xb9c2535d362796dcd673640a9fa2ebdaec274e6f8b850b023153b0a7a30fffc87f96e0b72696f647ebe7ab63099a6963", - "0x94aeff145386a087b0e91e68a84a5ede01f978f9dd9fe7bebca78941938469495dc30a96bba9508c0d017873aeea9610", - "0x98b179f8a3d9f0d0a983c30682dd425a2ddc7803be59bd626c623c8951a5179117d1d2a68254c95c9952989877d0ee55", - "0x889ecf5f0ee56938273f74eb3e9ecfb5617f04fb58e83fe4c0e4aef51615cf345bc56f3f61b17f6eed3249d4afd54451", - "0xa0f2b2c39bcea4b50883e2587d16559e246248a66ecb4a4b7d9ab3b51fb39fe98d83765e087eee37a0f86b0ba4144c02", - "0xb2a61e247ed595e8a3830f7973b07079cbda510f28ad8c78c220b26cb6acde4fbb5ee90c14a665f329168ee951b08cf0", - "0x95bd0fcfb42f0d6d8a8e73d7458498a85bcddd2fb132fd7989265648d82ac2707d6d203fac045504977af4f0a2aca4b7", - "0x843e5a537c298666e6cf50fcc044f13506499ef83c802e719ff2c90e85003c132024e04711be7234c04d4b0125512d5d", - "0xa46d1797c5959dcd3a5cfc857488f4d96f74277c3d13b98b133620192f79944abcb3a361d939a100187f1b0856eae875", - "0xa1c7786736d6707a48515c38660615fcec67eb8a2598f46657855215f804fd72ab122d17f94fcffad8893f3be658dca7", - "0xb23dc9e610abc7d8bd21d147e22509a0fa49db5be6ea7057b51aae38e31654b3aa044df05b94b718153361371ba2f622", - "0xb00cc8f257d659c22d30e6d641f79166b1e752ea8606f558e4cad6fc01532e8319ea4ee12265ba4140ac45aa4613c004", - "0xac7019af65221b0cc736287b32d7f1a3561405715ba9a6a122342e04e51637ba911c41573de53e4781f2230fdcb2475f", - "0x81a630bc41b3da8b3eb4bf56cba10cd9f93153c3667f009dc332287baeb707d505fb537e6233c8e53d299ec0f013290c", - "0xa6b7aea5c545bb76df0f230548539db92bc26642572cb7dd3d5a30edca2b4c386f44fc8466f056b42de2a452b81aff5b", - "0x8271624ff736b7b238e43943c81de80a1612207d32036d820c11fc830c737972ccc9c60d3c2359922b06652311e3c994", - "0x8a684106458cb6f4db478170b9ad595d4b54c18bf63b9058f095a2fa1b928c15101472c70c648873d5887880059ed402", - "0xa5cc3c35228122f410184e4326cf61a37637206e589fcd245cb5d0cec91031f8f7586b80503070840fdfd8ce75d3c88b", - "0x9443fc631aed8866a7ed220890911057a1f56b0afe0ba15f0a0e295ab97f604b134b1ed9a4245e46ee5f9a93aa74f731", - "0x984b6f7d79835dffde9558c6bb912d992ca1180a2361757bdba4a7b69dc74b056e303adc69fe67414495dd9c2dd91e64", - "0xb15a5c8cba5de080224c274d31c68ed72d2a7126d347796569aef0c4e97ed084afe3da4d4b590b9dda1a07f0c2ff3dfb", - "0x991708fe9650a1f9a4e43938b91d45dc68c230e05ee999c95dbff3bf79b1c1b2bb0e7977de454237c355a73b8438b1d9", - "0xb4f7edc7468b176a4a7c0273700c444fa95c726af6697028bed4f77eee887e3400f9c42ee15b782c0ca861c4c3b8c98a", - "0x8c60dcc16c51087eb477c13e837031d6c6a3dc2b8bf8cb43c23f48006bc7173151807e866ead2234b460c2de93b31956", - "0x83ad63e9c910d1fc44bc114accfb0d4d333b7ebe032f73f62d25d3e172c029d5e34a1c9d547273bf6c0fead5c8801007", - "0x85de73213cc236f00777560756bdbf2b16841ba4b55902cf2cad9742ecaf5d28209b012ceb41f337456dfeca93010cd7", - "0xa7561f8827ccd75b6686ba5398bb8fc3083351c55a589b18984e186820af7e275af04bcd4c28e1dc11be1e8617a0610b", - "0x88c0a4febd4068850557f497ea888035c7fc9f404f6cc7794e7cc8722f048ad2f249e7dc62743e7a339eb7473ad3b0cd", - "0x932b22b1d3e6d5a6409c34980d176feb85ada1bf94332ef5c9fc4d42b907dabea608ceef9b5595ef3feee195151f18d8", - "0xa2867bb3f5ab88fbdae3a16c9143ab8a8f4f476a2643c505bb9f37e5b1fd34d216cab2204c9a017a5a67b7ad2dda10e8", - "0xb573d5f38e4e9e8a3a6fd82f0880dc049efa492a946d00283019bf1d5e5516464cf87039e80aef667cb86fdea5075904", - "0xb948f1b5ab755f3f5f36af27d94f503b070696d793b1240c1bdfd2e8e56890d69e6904688b5f8ff5a4bdf5a6abfe195f", - "0x917eae95ebc4109a2e99ddd8fec7881d2f7aaa0e25fda44dec7ce37458c2ee832f1829db7d2dcfa4ca0f06381c7fe91d", - "0x95751d17ed00a3030bce909333799bb7f4ab641acf585807f355b51d6976dceee410798026a1a004ef4dcdff7ec0f5b8", - "0xb9b7bd266f449a79bbfe075e429613e76c5a42ac61f01c8f0bbbd34669650682efe01ff9dbbc400a1e995616af6aa278", - "0xac1722d097ce9cd7617161f8ec8c23d68f1fb1c9ca533e2a8b4f78516c2fd8fb38f23f834e2b9a03bb06a9d655693ca9", - "0xa7ad9e96ffd98db2ecdb6340c5d592614f3c159abfd832fe27ee9293519d213a578e6246aae51672ee353e3296858873", - "0x989b8814d5de7937c4acafd000eec2b4cd58ba395d7b25f98cafd021e8efa37029b29ad8303a1f6867923f5852a220eb", - "0xa5bfe6282c771bc9e453e964042d44eff4098decacb89aecd3be662ea5b74506e1357ab26f3527110ba377711f3c9f41", - "0x8900a7470b656639721d2abbb7b06af0ac4222ab85a1976386e2a62eb4b88bfb5b72cf7921ddb3cf3a395d7eeb192a2e", - "0x95a71b55cd1f35a438cf5e75f8ff11c5ec6a2ebf2e4dba172f50bfad7d6d5dca5de1b1afc541662c81c858f7604c1163", - "0x82b5d62fea8db8d85c5bc3a76d68dedd25794cf14d4a7bc368938ffca9e09f7e598fdad2a5aac614e0e52f8112ae62b9", - "0x997173f07c729202afcde3028fa7f52cefc90fda2d0c8ac2b58154a5073140683e54c49ed1f254481070d119ce0ce02a", - "0xaeffb91ccc7a72bbd6ffe0f9b99c9e66e67d59cec2e02440465e9636a613ab3017278cfa72ea8bc4aba9a8dc728cb367", - "0x952743b06e8645894aeb6440fc7a5f62dd3acf96dab70a51e20176762c9751ea5f2ba0b9497ccf0114dc4892dc606031", - "0x874c63baeddc56fbbca2ff6031f8634b745f6e34ea6791d7c439201aee8f08ef5ee75f7778700a647f3b21068513fce6", - "0x85128fec9c750c1071edfb15586435cc2f317e3e9a175bb8a9697bcda1eb9375478cf25d01e7fed113483b28f625122d", - "0x85522c9576fd9763e32af8495ae3928ed7116fb70d4378448926bc9790e8a8d08f98cf47648d7da1b6e40d6a210c7924", - "0x97d0f37a13cfb723b848099ca1c14d83e9aaf2f7aeb71829180e664b7968632a08f6a85f557d74b55afe6242f2a36e7c", - "0xabaa472d6ad61a5fccd1a57c01aa1bc081253f95abbcba7f73923f1f11c4e79b904263890eeb66926de3e2652f5d1c70", - "0xb3c04945ba727a141e5e8aec2bf9aa3772b64d8fd0e2a2b07f3a91106a95cbcb249adcd074cbe498caf76fffac20d4ef", - "0x82c46781a3d730d9931bcabd7434a9171372dde57171b6180e5516d4e68db8b23495c8ac3ab96994c17ddb1cf249b9fb", - "0xa202d8b65613c42d01738ccd68ed8c2dbc021631f602d53f751966e04182743ebc8e0747d600b8a8676b1da9ae7f11ab", - "0xae73e7256e9459db04667a899e0d3ea5255211fb486d084e6550b6dd64ca44af6c6b2d59d7aa152de9f96ce9b58d940d", - "0xb67d87b176a9722945ec7593777ee461809861c6cfd1b945dde9ee4ff009ca4f19cf88f4bbb5c80c9cbab2fe25b23ac8", - "0x8f0b7a317a076758b0dac79959ee4a06c08b07d0f10538a4b53d3da2eda16e2af26922feb32c090330dc4d969cf69bd3", - "0x90b36bf56adbd8c4b6cb32febc3a8d5f714370c2ac3305c10fa6d168dffb2a026804517215f9a2d4ec8310cdb6bb459b", - "0xaa80c19b0682ead69934bf18cf476291a0beddd8ef4ed75975d0a472e2ab5c70f119722a8574ae4973aceb733d312e57", - "0xa3fc9abb12574e5c28dcb51750b4339b794b8e558675eef7d26126edf1de920c35e992333bcbffcbf6a5f5c0d383ce62", - "0xa1573ff23ab972acdcd08818853b111fc757fdd35aa070186d3e11e56b172fb49d840bf297ac0dd222e072fc09f26a81", - "0x98306f2be4caa92c2b4392212d0cbf430b409b19ff7d5b899986613bd0e762c909fc01999aa94be3bd529d67f0113d7f", - "0x8c1fc42482a0819074241746d17dc89c0304a2acdae8ed91b5009e9e3e70ff725ba063b4a3e68fdce05b74f5180c545e", - "0xa6c6113ebf72d8cf3163b2b8d7f3fa24303b13f55752522c660a98cd834d85d8c79214d900fa649499365e2e7641f77a", - "0xab95eea424f8a2cfd9fb1c78bb724e5b1d71a0d0d1e4217c5d0f98b0d8bbd3f8400a2002abc0a0e4576d1f93f46fefad", - "0x823c5a4fd8cf4a75fdc71d5f2dd511b6c0f189b82affeacd2b7cfcad8ad1a5551227dcc9bfdb2e34b2097eaa00efbb51", - "0xb97314dfff36d80c46b53d87a61b0e124dc94018a0bb680c32765b9a2d457f833a7c42bbc90b3b1520c33a182580398d", - "0xb17566ee3dcc6bb3b004afe4c0136dfe7dd27df9045ae896dca49fb36987501ae069eb745af81ba3fc19ff037e7b1406", - "0xb0bdc0f55cfd98d331e3a0c4fbb776a131936c3c47c6bffdc3aaf7d8c9fa6803fbc122c2fefbb532e634228687d52174", - "0xaa5d9e60cc9f0598559c28bb9bdd52aa46605ab4ffe3d192ba982398e72cec9a2a44c0d0d938ce69935693cabc0887ea", - "0x802b6459d2354fa1d56c592ac1346c428dadea6b6c0a87bf7d309bab55c94e1cf31dd98a7a86bd92a840dd51f218b91b", - "0xa526914efdc190381bf1a73dd33f392ecf01350b9d3f4ae96b1b1c3d1d064721c7d6eec5788162c933245a3943f5ee51", - "0xb3b8fcf637d8d6628620a1a99dbe619eabb3e5c7ce930d6efd2197e261bf394b74d4e5c26b96c4b8009c7e523ccfd082", - "0x8f7510c732502a93e095aba744535f3928f893f188adc5b16008385fb9e80f695d0435bfc5b91cdad4537e87e9d2551c", - "0x97b90beaa56aa936c3ca45698f79273a68dd3ccd0076eab48d2a4db01782665e63f33c25751c1f2e070f4d1a8525bf96", - "0xb9fb798324b1d1283fdc3e48288e3861a5449b2ab5e884b34ebb8f740225324af86e4711da6b5cc8361c1db15466602f", - "0xb6d52b53cea98f1d1d4c9a759c25bf9d8a50b604b144e4912acbdbdc32aab8b9dbb10d64a29aa33a4f502121a6fb481c", - "0x9174ffff0f2930fc228f0e539f5cfd82c9368d26b074467f39c07a774367ff6cccb5039ac63f107677d77706cd431680", - "0xa33b6250d4ac9e66ec51c063d1a6a31f253eb29bbaed12a0d67e2eccfffb0f3a52750fbf52a1c2aaba8c7692346426e7", - "0xa97025fd5cbcebe8ef865afc39cd3ea707b89d4e765ec817fd021d6438e02fa51e3544b1fd45470c58007a08efac6edd", - "0xb32a78480edd9ff6ba2f1eec4088db5d6ceb2d62d7e59e904ecaef7bb4a2e983a4588e51692b3be76e6ffbc0b5f911a5", - "0xb5ab590ef0bb77191f00495b33d11c53c65a819f7d0c1f9dc4a2caa147a69c77a4fff7366a602d743ee1f395ce934c1e", - "0xb3fb0842f9441fb1d0ee0293b6efbc70a8f58d12d6f769b12872db726b19e16f0f65efbc891cf27a28a248b0ef9c7e75", - "0x9372ad12856fefb928ccb0d34e198df99e2f8973b07e9d417a3134d5f69e12e79ff572c4e03ccd65415d70639bc7c73e", - "0xaa8d6e83d09ce216bfe2009a6b07d0110d98cf305364d5529c170a23e693aabb768b2016befb5ada8dabdd92b4d012bb", - "0xa954a75791eeb0ce41c85200c3763a508ed8214b5945a42c79bfdcfb1ec4f86ad1dd7b2862474a368d4ac31911a2b718", - "0x8e2081cfd1d062fe3ab4dab01f68062bac802795545fede9a188f6c9f802cb5f884e60dbe866710baadbf55dc77c11a4", - "0xa2f06003b9713e7dd5929501ed485436b49d43de80ea5b15170763fd6346badf8da6de8261828913ee0dacd8ff23c0e1", - "0x98eecc34b838e6ffd1931ca65eec27bcdb2fdcb61f33e7e5673a93028c5865e0d1bf6d3bec040c5e96f9bd08089a53a4", - "0x88cc16019741b341060b95498747db4377100d2a5bf0a5f516f7dec71b62bcb6e779de2c269c946d39040e03b3ae12b7", - "0xad1135ccbc3019d5b2faf59a688eef2500697642be8cfbdf211a1ab59abcc1f24483e50d653b55ff1834675ac7b4978f", - "0xa946f05ed9972f71dfde0020bbb086020fa35b482cce8a4cc36dd94355b2d10497d7f2580541bb3e81b71ac8bba3c49f", - "0xa83aeed488f9a19d8cfd743aa9aa1982ab3723560b1cd337fc2f91ad82f07afa412b3993afb845f68d47e91ba4869840", - "0x95eebe006bfc316810cb71da919e5d62c2cebb4ac99d8e8ef67be420302320465f8b69873470982de13a7c2e23516be9", - "0xa55f8961295a11e91d1e5deadc0c06c15dacbfc67f04ccba1d069cba89d72aa3b3d64045579c3ea8991b150ac29366ae", - "0xb321991d12f6ac07a5de3c492841d1a27b0d3446082fbce93e7e1f9e8d8fe3b45d41253556261c21b70f5e189e1a7a6f", - "0xa0b0822f15f652ce7962a4f130104b97bf9529797c13d6bd8e24701c213cc37f18157bd07f3d0f3eae6b7cd1cb40401f", - "0x96e2fa4da378aa782cc2d5e6e465fc9e49b5c805ed01d560e9b98abb5c0de8b74a2e7bec3aa5e2887d25cccb12c66f0c", - "0x97e4ab610d414f9210ed6f35300285eb3ccff5b0b6a95ed33425100d7725e159708ea78704497624ca0a2dcabce3a2f9", - "0x960a375b17bdb325761e01e88a3ea57026b2393e1d887b34b8fa5d2532928079ce88dc9fd06a728b26d2bb41b12b9032", - "0x8328a1647398e832aadc05bd717487a2b6fcdaa0d4850d2c4da230c6a2ed44c3e78ec4837b6094f3813f1ee99414713f", - "0xaa283834ebd18e6c99229ce4b401eda83f01d904f250fedd4e24f1006f8fa0712a6a89a7296a9bf2ce8de30e28d1408e", - "0xb29e097f2caadae3e0f0ae3473c072b0cd0206cf6d2e9b22c1a5ad3e07d433e32bd09ed1f4e4276a2da4268633357b7f", - "0x9539c5cbba14538b2fe077ecf67694ef240da5249950baaabea0340718b882a966f66d97f08556b08a4320ceb2cc2629", - "0xb4529f25e9b42ae8cf8338d2eface6ba5cd4b4d8da73af502d081388135c654c0b3afb3aa779ffc80b8c4c8f4425dd2b", - "0x95be0739c4330619fbe7ee2249c133c91d6c07eab846c18c5d6c85fc21ac5528c5d56dcb0145af68ed0c6a79f68f2ccd", - "0xac0c83ea802227bfc23814a24655c9ff13f729619bcffdb487ccbbf029b8eaee709f8bddb98232ef33cd70e30e45ca47", - "0xb503becb90acc93b1901e939059f93e671900ca52c6f64ae701d11ac891d3a050b505d89324ce267bc43ab8275da6ffe", - "0x98e3811b55b1bacb70aa409100abb1b870f67e6d059475d9f278c751b6e1e2e2d6f2e586c81a9fb6597fda06e7923274", - "0xb0b0f61a44053fa6c715dbb0731e35d48dba257d134f851ee1b81fd49a5c51a90ebf5459ec6e489fce25da4f184fbdb1", - "0xb1d2117fe811720bb997c7c93fe9e4260dc50fca8881b245b5e34f724aaf37ed970cdad4e8fcb68e05ac8cf55a274a53", - "0xa10f502051968f14b02895393271776dee7a06db9de14effa0b3471825ba94c3f805302bdddac4d397d08456f620999d", - "0xa3dbad2ef060ae0bb7b02eaa4a13594f3f900450faa1854fc09620b01ac94ab896321dfb1157cf2374c27e5718e8026a", - "0xb550fdec503195ecb9e079dcdf0cad559d64d3c30818ef369b4907e813e689da316a74ad2422e391b4a8c2a2bef25fc0", - "0xa25ba865e2ac8f28186cea497294c8649a201732ecb4620c4e77b8e887403119910423df061117e5f03fc5ba39042db1", - "0xb3f88174e03fdb443dd6addd01303cf88a4369352520187c739fc5ae6b22fa99629c63c985b4383219dab6acc5f6f532", - "0x97a7503248e31e81b10eb621ba8f5210c537ad11b539c96dfb7cf72b846c7fe81bd7532c5136095652a9618000b7f8d3", - "0xa8bcdc1ce5aa8bfa683a2fc65c1e79de8ff5446695dcb8620f7350c26d2972a23da22889f9e2b1cacb3f688c6a2953dc", - "0x8458c111df2a37f5dd91a9bee6c6f4b79f4f161c93fe78075b24a35f9817da8dde71763218d627917a9f1f0c4709c1ed", - "0xac5f061a0541152b876cbc10640f26f1cc923c9d4ae1b6621e4bb3bf2cec59bbf87363a4eb72fb0e5b6d4e1c269b52d5", - "0xa9a25ca87006e8a9203cbb78a93f50a36694aa4aad468b8d80d3feff9194455ca559fcc63838128a0ab75ad78c07c13a", - "0xa450b85f5dfffa8b34dfd8bc985f921318efacf8857cf7948f93884ba09fb831482ee90a44224b1a41e859e19b74962f", - "0x8ed91e7f92f5c6d7a71708b6132f157ac226ecaf8662af7d7468a4fa25627302efe31e4620ad28719318923e3a59bf82", - "0xab524165fd4c71b1fd395467a14272bd2b568592deafa039d8492e9ef36c6d3f96927c95c72d410a768dc0b6d1fbbc9b", - "0xb662144505aa8432c75ffb8d10318526b6d5777ac7af9ebfad87d9b0866c364f7905a6352743bd8fd79ffd9d5dd4f3e6", - "0xa48f1677550a5cd40663bb3ba8f84caaf8454f332d0ceb1d94dbea52d0412fe69c94997f7749929712fd3995298572f7", - "0x8391cd6e2f6b0c242de1117a612be99776c3dc95cb800b187685ea5bf7e2722275eddb79fd7dfc8be8e389c4524cdf70", - "0x875d3acb9af47833b72900bc0a2448999d638f153c5e97e8a14ec02d0c76f6264353a7e275e1f1a5855daced523d243b", - "0x91f1823657d30b59b2f627880a9a9cb530f5aca28a9fd217fe6f2f5133690dfe7ad5a897872e400512db2e788b3f7628", - "0xad3564332aa56cea84123fc7ca79ea70bb4fef2009fa131cb44e4b15e8613bd11ca1d83b9d9bf456e4b7fee9f2e8b017", - "0x8c530b84001936d5ab366c84c0b105241a26d1fb163669f17c8f2e94776895c2870edf3e1bc8ccd04d5e65531471f695", - "0x932d01fa174fdb0c366f1230cffde2571cc47485f37f23ba5a1825532190cc3b722aeb1f15aed62cf83ccae9403ba713", - "0x88b28c20585aca50d10752e84b901b5c2d58efef5131479fbbe53de7bce2029e1423a494c0298e1497669bd55be97a5d", - "0xb914148ca717721144ebb3d3bf3fcea2cd44c30c5f7051b89d8001502f3856fef30ec167174d5b76265b55d70f8716b5", - "0x81d0173821c6ddd2a068d70766d9103d1ee961c475156e0cbd67d54e668a796310474ef698c7ab55abe6f2cf76c14679", - "0x8f28e8d78e2fe7fa66340c53718e0db4b84823c8cfb159c76eac032a62fb53da0a5d7e24ca656cf9d2a890cb2a216542", - "0x8a26360335c73d1ab51cec3166c3cf23b9ea51e44a0ad631b0b0329ef55aaae555420348a544e18d5760969281759b61", - "0x94f326a32ed287545b0515be9e08149eb0a565025074796d72387cc3a237e87979776410d78339e23ef3172ca43b2544", - "0xa785d2961a2fa5e70bffa137858a92c48fe749fee91b02599a252b0cd50d311991a08efd7fa5e96b78d07e6e66ffe746", - "0x94af9030b5ac792dd1ce517eaadcec1482206848bea4e09e55cc7f40fd64d4c2b3e9197027c5636b70d6122c51d2235d", - "0x9722869f7d1a3992850fe7be405ec93aa17dc4d35e9e257d2e469f46d2c5a59dbd504056c85ab83d541ad8c13e8bcd54", - "0xb13c4088b61a06e2c03ac9813a75ff1f68ffdfee9df6a8f65095179a475e29cc49119cad2ce05862c3b1ac217f3aace9", - "0x8c64d51774753623666b10ca1b0fe63ae42f82ed6aa26b81dc1d48c86937c5772eb1402624c52a154b86031854e1fb9f", - "0xb47e4df18002b7dac3fee945bf9c0503159e1b8aafcce2138818e140753011b6d09ef1b20894e08ba3006b093559061b", - "0x93cb5970076522c5a0483693f6a35ffd4ea2aa7aaf3730c4eccd6af6d1bebfc1122fc4c67d53898ae13eb6db647be7e2", - "0xa68873ef80986795ea5ed1a597d1cd99ed978ec25e0abb57fdcc96e89ef0f50aeb779ff46e3dce21dc83ada3157a8498", - "0x8cab67f50949cc8eee6710e27358aea373aae3c92849f8f0b5531c080a6300cdf2c2094fe6fecfef6148de0d28446919", - "0x993e932bcb616dbaa7ad18a4439e0565211d31071ef1b85a0627db74a05d978c60d507695eaeea5c7bd9868a21d06923", - "0xacdadff26e3132d9478a818ef770e9fa0d2b56c6f5f48bd3bd674436ccce9bdfc34db884a73a30c04c5f5e9764cb2218", - "0xa0d3e64c9c71f84c0eef9d7a9cb4fa184224b969db5514d678e93e00f98b41595588ca802643ea225512a4a272f5f534", - "0x91c9140c9e1ba6e330cb08f6b2ce4809cd0d5a0f0516f70032bf30e912b0ed684d07b413b326ab531ee7e5b4668c799b", - "0x87bc2ee7a0c21ba8334cd098e35cb703f9af57f35e091b8151b9b63c3a5b0f89bd7701dbd44f644ea475901fa6d9ef08", - "0x9325ccbf64bf5d71b303e31ee85d486298f9802c5e55b2c3d75427097bf8f60fa2ab4fcaffa9b60bf922c3e24fbd4b19", - "0x95d0506e898318f3dc8d28d16dfd9f0038b54798838b3c9be2a2ae3c2bf204eb496166353fc042220b0bd4f6673b9285", - "0x811de529416331fe9c416726d45df9434c29dcd7e949045eb15740f47e97dde8f31489242200e19922cac2a8b7c6fd1f", - "0xade632d04a4c8bbab6ca7df370b2213cb9225023e7973f0e29f4f5e52e8aeaabc65171306bbdd12a67b195dfbb96d48f", - "0x88b7f029e079b6ae956042c0ea75d53088c5d0efd750dd018adaeacf46be21bf990897c58578c491f41afd3978d08073", - "0x91f477802de507ffd2be3f4319903119225b277ad24f74eb50f28b66c14d32fae53c7edb8c7590704741af7f7f3e3654", - "0x809838b32bb4f4d0237e98108320d4b079ee16ed80c567e7548bd37e4d7915b1192880f4812ac0e00476d246aec1dbc8", - "0x84183b5fc4a7997a8ae5afedb4d21dce69c480d5966b5cbdafd6dd10d29a9a6377f3b90ce44da0eb8b176ac3af0253bb", - "0x8508abbf6d3739a16b9165caf0f95afb3b3ac1b8c38d6d374cf0c91296e2c1809a99772492b539cda184510bce8a0271", - "0x8722054e59bab2062e6419a6e45fc803af77fde912ef2cd23055ad0484963de65a816a2debe1693d93c18218d2b8e81a", - "0x8e895f80e485a7c4f56827bf53d34b956281cdc74856c21eb3b51f6288c01cc3d08565a11cc6f3e2604775885490e8c5", - "0xafc92714771b7aa6e60f3aee12efd9c2595e9659797452f0c1e99519f67c8bc3ac567119c1ddfe82a3e961ee9defea9a", - "0x818ff0fd9cefd32db87b259e5fa32967201016fc02ef44116cdca3c63ce5e637756f60477a408709928444a8ad69c471", - "0x8251e29af4c61ae806fc5d032347fb332a94d472038149225298389495139ce5678fae739d02dfe53a231598a992e728", - "0xa0ea39574b26643f6f1f48f99f276a8a64b5481989cfb2936f9432a3f8ef5075abfe5c067dc5512143ce8bf933984097", - "0xaf67a73911b372bf04e57e21f289fc6c3dfac366c6a01409b6e76fea4769bdb07a6940e52e8d7d3078f235c6d2f632c6", - "0xb5291484ef336024dd2b9b4cf4d3a6b751133a40656d0a0825bcc6d41c21b1c79cb50b0e8f4693f90c29c8f4358641f9", - "0x8bc0d9754d70f2cb9c63f991902165a87c6535a763d5eece43143b5064ae0bcdce7c7a8f398f2c1c29167b2d5a3e6867", - "0x8d7faff53579ec8f6c92f661c399614cc35276971752ce0623270f88be937c414eddcb0997e14724a783905a026c8883", - "0x9310b5f6e675fdf60796f814dbaa5a6e7e9029a61c395761e330d9348a7efab992e4e115c8be3a43d08e90d21290c892", - "0xb5eb4f3eb646038ad2a020f0a42202532d4932e766da82b2c1002bf9c9c2e5336b54c8c0ffcc0e02d19dde2e6a35b6cc", - "0x91dabfd30a66710f1f37a891136c9be1e23af4abf8cb751f512a40c022a35f8e0a4fb05b17ec36d4208de02d56f0d53a", - "0xb3ded14e82d62ac7a5a036122a62f00ff8308498f3feae57d861babaff5a6628d43f0a0c5fc903f10936bcf4e2758ceb", - "0xa88e8348fed2b26acca6784d19ef27c75963450d99651d11a950ea81d4b93acd2c43e0ecce100eaf7e78508263d5baf3", - "0xb1f5bbf7c4756877b87bb42163ac570e08c6667c4528bf68b5976680e19beeff7c5effd17009b0718797077e2955457a", - "0xad2e7b516243f915d4d1415326e98b1a7390ae88897d0b03b66c2d9bd8c3fba283d7e8fe44ed3333296a736454cef6d8", - "0x8f82eae096d5b11f995de6724a9af895f5e1c58d593845ad16ce8fcae8507e0d8e2b2348a0f50a1f66a17fd6fac51a5c", - "0x890e4404d0657c6c1ee14e1aac132ecf7a568bb3e04137b85ac0f84f1d333bd94993e8750f88eee033a33fb00f85dcc7", - "0x82ac7d3385e035115f1d39a99fc73e5919de44f5e6424579776d118d711c8120b8e5916372c6f27bed4cc64cac170b6c", - "0x85ee16d8901c272cfbbe966e724b7a891c1bd5e68efd5d863043ad8520fc409080af61fd726adc680b3f1186fe0ac8b8", - "0x86dc564c9b545567483b43a38f24c41c6551a49cabeebb58ce86404662a12dbfafd0778d30d26e1c93ce222e547e3898", - "0xa29f5b4522db26d88f5f95f18d459f8feefab02e380c2edb65aa0617a82a3c1a89474727a951cef5f15050bcf7b380fb", - "0xa1ce039c8f6cac53352899edb0e3a72c76da143564ad1a44858bd7ee88552e2fe6858d1593bbd74aeee5a6f8034b9b9d", - "0x97f10d77983f088286bd7ef3e7fdd8fa275a56bec19919adf33cf939a90c8f2967d2b1b6fc51195cb45ad561202a3ed7", - "0xa25e2772e8c911aaf8712bdac1dd40ee061c84d3d224c466cfaae8e5c99604053f940cde259bd1c3b8b69595781dbfec", - "0xb31bb95a0388595149409c48781174c340960d59032ab2b47689911d03c68f77a2273576fbe0c2bf4553e330656058c7", - "0xb8b2e9287ad803fb185a13f0d7456b397d4e3c8ad5078f57f49e8beb2e85f661356a3392dbd7bcf6a900baa5582b86a1", - "0xa3d0893923455eb6e96cc414341cac33d2dbc88fba821ac672708cce131761d85a0e08286663a32828244febfcae6451", - "0x82310cb42f647d99a136014a9f881eb0b9791efd2e01fc1841907ad3fc8a9654d3d1dab6689c3607214b4dc2aca01cee", - "0x874022d99c16f60c22de1b094532a0bc6d4de700ad01a31798fac1d5088b9a42ad02bef8a7339af7ed9c0d4f16b186ee", - "0x94981369e120265aed40910eebc37eded481e90f4596b8d57c3bec790ab7f929784bd33ddd05b7870aad6c02e869603b", - "0xa4f1f50e1e2a73f07095e0dd31cb45154f24968dae967e38962341c1241bcd473102fff1ff668b20c6547e9732d11701", - "0xae2328f3b0ad79fcda807e69a1b5278145225083f150f67511dafc97e079f860c3392675f1752ae7e864c056e592205b", - "0x875d8c971e593ca79552c43d55c8c73b17cd20c81ff2c2fed1eb19b1b91e4a3a83d32df150dbfd5db1092d0aebde1e1f", - "0xadd2e80aa46aae95da73a11f130f4bda339db028e24c9b11e5316e75ba5e63bc991d2a1da172c7c8e8fee038baae3433", - "0xb46dbe1cb3424002aa7de51e82f600852248e251465c440695d52538d3f36828ff46c90ed77fc1d11534fe3c487df8ef", - "0xa5e5045d28b4e83d0055863c30c056628c58d4657e6176fd0536f5933f723d60e851bb726d5bf3c546b8ce4ac4a57ef8", - "0x91fec01e86dd1537e498fff7536ea3ca012058b145f29d9ada49370cd7b7193ac380e116989515df1b94b74a55c45df3", - "0xa7428176d6918cd916a310bdc75483c72de660df48cac4e6e7478eef03205f1827ea55afc0df5d5fa7567d14bbea7fc9", - "0x851d89bef45d9761fe5fdb62972209335193610015e16a675149519f9911373bac0919add226ef118d9f3669cfdf4734", - "0xb74acf5c149d0042021cb2422ea022be4c4f72a77855f42393e71ffd12ebb3eec16bdf16f812159b67b79a9706e7156d", - "0x99f35dce64ec99aa595e7894b55ce7b5a435851b396e79036ffb249c28206087db4c85379df666c4d95857db02e21ff9", - "0xb6b9a384f70db9e298415b8ab394ee625dafff04be2886476e59df8d052ca832d11ac68a9b93fba7ab055b7bc36948a4", - "0x898ee4aefa923ffec9e79f2219c7389663eb11eb5b49014e04ed4a336399f6ea1691051d86991f4c46ca65bcd4fdf359", - "0xb0f948217b0d65df7599a0ba4654a5e43c84db477936276e6f11c8981efc6eaf14c90d3650107ed4c09af4cc8ec11137", - "0xaa6286e27ac54f73e63dbf6f41865dd94d24bc0cf732262fcaff67319d162bb43af909f6f8ee27b1971939cfbba08141", - "0x8bca7cdf730cf56c7b2c8a2c4879d61361a6e1dba5a3681a1a16c17a56e168ace0e99cf0d15826a1f5e67e6b8a8a049a", - "0xa746d876e8b1ce225fcafca603b099b36504846961526589af977a88c60d31ba2cc56e66a3dec8a77b3f3531bf7524c9", - "0xa11e2e1927e6704cdb8874c75e4f1842cef84d7d43d7a38e339e61dc8ba90e61bbb20dd3c12e0b11d2471d58eed245be", - "0xa36395e22bc1d1ba8b0459a235203177737397da5643ce54ded3459d0869ff6d8d89f50c73cb62394bf66a959cde9b90", - "0x8b49f12ba2fdf9aca7e5f81d45c07d47f9302a2655610e7634d1e4bd16048381a45ef2c95a8dd5b0715e4b7cf42273af", - "0x91cffa2a17e64eb7f76bccbe4e87280ee1dd244e04a3c9eac12e15d2d04845d876eb24fe2ec6d6d266cce9efb281077f", - "0xa6b8afabf65f2dee01788114e33a2f3ce25376fb47a50b74da7c3c25ff1fdc8aa9f41307534abbf48acb6f7466068f69", - "0x8d13db896ccfea403bd6441191995c1a65365cab7d0b97fbe9526da3f45a877bd1f4ef2edef160e8a56838cd1586330e", - "0x98c717de9e01bef8842c162a5e757fe8552d53269c84862f4d451e7c656ae6f2ae473767b04290b134773f63be6fdb9d", - "0x8c2036ace1920bd13cf018e82848c49eb511fad65fd0ff51f4e4b50cf3bfc294afb63cba682c16f52fb595a98fa84970", - "0xa3520fdff05dbad9e12551b0896922e375f9e5589368bcb2cc303bde252743b74460cb5caf99629325d3620f13adc796", - "0x8d4f83a5bfec05caf5910e0ce538ee9816ee18d0bd44c1d0da2a87715a23cd2733ad4d47552c6dc0eb397687d611dd19", - "0xa7b39a0a6a02823452d376533f39d35029867b3c9a6ad6bca181f18c54132d675613a700f9db2440fb1b4fa13c8bf18a", - "0x80bcb114b2544b80f404a200fc36860ed5e1ad31fe551acd4661d09730c452831751baa9b19d7d311600d267086a70bc", - "0x90dcce03c6f88fc2b08f2b42771eedde90cc5330fe0336e46c1a7d1b5a6c1641e5fcc4e7b3d5db00bd8afca9ec66ed81", - "0xaec15f40805065c98e2965b1ae12a6c9020cfdb094c2d0549acfc7ea2401a5fb48d3ea7d41133cf37c4e096e7ff53eb9", - "0x80e129b735dba49fa627a615d6c273119acec8e219b2f2c4373a332b5f98d66cbbdd688dfbe72a8f8bfefaccc02c50c1", - "0xa9b596da3bdfe23e6799ece5f7975bf7a1979a75f4f546deeaf8b34dfe3e0d623217cb4cf4ccd504cfa3625b88cd53f1", - "0xabcbbb70b16f6e517c0ab4363ab76b46e4ff58576b5f8340e5c0e8cc0e02621b6e23d742d73b015822a238b17cfd7665", - "0xa046937cc6ea6a2e1adae543353a9fe929c1ae4ad655be1cc051378482cf88b041e28b1e9a577e6ccff2d3570f55e200", - "0x831279437282f315e65a60184ef158f0a3dddc15a648dc552bdc88b3e6fe8288d3cfe9f0031846d81350f5e7874b4b33", - "0x993d7916fa213c6d66e7c4cafafc1eaec9a2a86981f91c31eb8a69c5df076c789cbf498a24c84e0ee77af95b42145026", - "0x823907a3b6719f8d49b3a4b7c181bd9bb29fcf842d7c70660c4f351852a1e197ca46cf5e879b47fa55f616fa2b87ce5e", - "0x8d228244e26132b234930ee14c75d88df0943cdb9c276a8faf167d259b7efc1beec2a87c112a6c608ad1600a239e9aae", - "0xab6e55766e5bfb0cf0764ed909a8473ab5047d3388b4f46faeba2d1425c4754c55c6daf6ad4751e634c618b53e549529", - "0xab0cab6860e55a84c5ad2948a7e0989e2b4b1fd637605634b118361497332df32d9549cb854b2327ca54f2bcb85eed8f", - "0xb086b349ae03ef34f4b25a57bcaa5d1b29bd94f9ebf87e22be475adfe475c51a1230c1ebe13506cb72c4186192451658", - "0x8a0b49d8a254ca6d91500f449cbbfbb69bb516c6948ac06808c65595e46773e346f97a5ce0ef7e5a5e0de278af22709c", - "0xac49de11edaaf04302c73c578cc0824bdd165c0d6321be1c421c1950e68e4f3589aa3995448c9699e93c6ebae8803e27", - "0x884f02d841cb5d8f4c60d1402469216b114ab4e93550b5bc1431756e365c4f870a9853449285384a6fa49e12ce6dc654", - "0xb75f3a28fa2cc8d36b49130cb7448a23d73a7311d0185ba803ad55c8219741d451c110f48b786e96c728bc525903a54f", - "0x80ae04dbd41f4a35e33f9de413b6ad518af0919e5a30cb0fa1b061b260420780bb674f828d37fd3b52b5a31673cbd803", - "0xb9a8011eb5fcea766907029bf743b45262db3e49d24f84503687e838651ed11cb64c66281e20a0ae9f6aa51acc552263", - "0x90bfdd75e2dc9cf013e22a5d55d2d2b8a754c96103a17524488e01206e67f8b6d52b1be8c4e3d5307d4fe06d0e51f54c", - "0xb4af353a19b06203a815ec43e79a88578cc678c46f5a954b85bc5c53b84059dddba731f3d463c23bfd5273885c7c56a4", - "0xaa125e96d4553b64f7140e5453ff5d2330318b69d74d37d283e84c26ad672fa00e3f71e530eb7e28be1e94afb9c4612e", - "0xa18e060aee3d49cde2389b10888696436bb7949a79ca7d728be6456a356ea5541b55492b2138da90108bd1ce0e6f5524", - "0x93e55f92bdbccc2de655d14b1526836ea2e52dba65eb3f87823dd458a4cb5079bf22ce6ef625cb6d6bfdd0995ab9a874", - "0x89f5a683526b90c1c3ceebbb8dc824b21cff851ce3531b164f6626e326d98b27d3e1d50982e507d84a99b1e04e86a915", - "0x83d1c38800361633a3f742b1cb2bfc528129496e80232611682ddbe403e92c2ac5373aea0bca93ecb5128b0b2b7a719e", - "0x8ecba560ac94905e19ce8d9c7af217bf0a145d8c8bd38e2db82f5e94cc3f2f26f55819176376b51f154b4aab22056059", - "0xa7e2a4a002b60291924850642e703232994acb4cfb90f07c94d1e0ecd2257bb583443283c20fc6017c37e6bfe85b7366", - "0x93ed7316fa50b528f1636fc6507683a672f4f4403e55e94663f91221cc198199595bd02eef43d609f451acc9d9b36a24", - "0xa1220a8ebc5c50ceed76a74bc3b7e0aa77f6884c71b64b67c4310ac29ce5526cb8992d6abc13ef6c8413ce62486a6795", - "0xb2f6eac5c869ad7f4a25161d3347093e2f70e66cd925032747e901189355022fab3038bca4d610d2f68feb7e719c110b", - "0xb703fa11a4d511ca01c7462979a94acb40b5d933759199af42670eb48f83df202fa0c943f6ab3b4e1cc54673ea3aab1e", - "0xb5422912afbfcb901f84791b04f1ddb3c3fbdc76d961ee2a00c5c320e06d3cc5b5909c3bb805df66c5f10c47a292b13d", - "0xad0934368da823302e1ac08e3ede74b05dfdbfffca203e97ffb0282c226814b65c142e6e15ec1e754518f221f01b30f7", - "0xa1dd302a02e37df15bf2f1147efe0e3c06933a5a767d2d030e1132f5c3ce6b98e216b6145eb39e1e2f74e76a83165b8d", - "0xa346aab07564432f802ae44738049a36f7ca4056df2d8f110dbe7fef4a3e047684dea609b2d03dc6bf917c9c2a47608f", - "0xb96c5f682a5f5d02123568e50f5d0d186e4b2c4c9b956ec7aabac1b3e4a766d78d19bd111adb5176b898e916e49be2aa", - "0x8a96676d56876fc85538db2e806e1cba20fd01aeb9fa3cb43ca6ca94a2c102639f65660db330e5d74a029bb72d6a0b39", - "0xab0048336bd5c3def1a4064eadd49e66480c1f2abb4df46e03afbd8a3342c2c9d74ee35d79f08f4768c1646681440984", - "0x888427bdf76caec90814c57ee1c3210a97d107dd88f7256f14f883ad0f392334b82be11e36dd8bfec2b37935177c7831", - "0xb622b282becf0094a1916fa658429a5292ba30fb48a4c8066ce1ddcefb71037948262a01c95bab6929ed3a76ba5db9fe", - "0xb5b9e005c1f456b6a368a3097634fb455723abe95433a186e8278dceb79d4ca2fbe21f8002e80027b3c531e5bf494629", - "0xa3c6707117a1e48697ed41062897f55d8119403eea6c2ee88f60180f6526f45172664bfee96bf61d6ec0b7fbae6aa058", - "0xb02a9567386a4fbbdb772d8a27057b0be210447348efe6feb935ceec81f361ed2c0c211e54787dc617cdffed6b4a6652", - "0xa9b8364e40ef15c3b5902e5534998997b8493064fa2bea99600def58279bb0f64574c09ba11e9f6f669a8354dd79dc85", - "0x9998a2e553a9aa9a206518fae2bc8b90329ee59ab23005b10972712389f2ec0ee746033c733092ffe43d73d33abbb8ef", - "0x843a4b34d9039bf79df96d79f2d15e8d755affb4d83d61872daf540b68c0a3888cf8fc00d5b8b247b38524bcb3b5a856", - "0x84f7128920c1b0bb40eee95701d30e6fc3a83b7bb3709f16d97e72acbb6057004ee7ac8e8f575936ca9dcb7866ab45f7", - "0x918d3e2222e10e05edb34728162a899ad5ada0aaa491aeb7c81572a9c0d506e31d5390e1803a91ff3bd8e2bb15d47f31", - "0x9442d18e2489613a7d47bb1cb803c8d6f3259d088cd079460976d87f7905ee07dea8f371b2537f6e1d792d36d7e42723", - "0xb491976970fe091995b2ed86d629126523ccf3e9daf8145302faca71b5a71a5da92e0e05b62d7139d3efac5c4e367584", - "0xaa628006235dc77c14cef4c04a308d66b07ac92d377df3de1a2e6ecfe3144f2219ad6d7795e671e1cb37a3641910b940", - "0x99d386adaea5d4981d7306feecac9a555b74ffdc218c907c5aa7ac04abaead0ec2a8237300d42a3fbc464673e417ceed", - "0x8f78e8b1556f9d739648ea3cab9606f8328b52877fe72f9305545a73b74d49884044ba9c1f1c6db7d9b7c7b7c661caba", - "0x8fb357ae49932d0babdf74fc7aa7464a65d3b6a2b3acf4f550b99601d3c0215900cfd67f2b6651ef94cfc323bac79fae", - "0x9906f2fa25c0290775aa001fb6198113d53804262454ae8b83ef371b5271bde189c0460a645829cb6c59f9ee3a55ce4d", - "0x8f4379b3ebb50e052325b27655ca6a82e6f00b87bf0d2b680d205dd2c7afdc9ff32a9047ae71a1cdf0d0ce6b9474d878", - "0xa85534e88c2bd43c043792eaa75e50914b21741a566635e0e107ae857aed0412035f7576cf04488ade16fd3f35fdbb87", - "0xb4ce93199966d3c23251ca7f28ec5af7efea1763d376b0385352ffb2e0a462ef95c69940950278cf0e3dafd638b7bd36", - "0xb10cb3d0317dd570aa73129f4acf63c256816f007607c19b423fb42f65133ce21f2f517e0afb41a5378cccf893ae14d0", - "0xa9b231c9f739f7f914e5d943ed9bff7eba9e2c333fbd7c34eb1648a362ee01a01af6e2f7c35c9fe962b11152cddf35de", - "0x99ff6a899e156732937fb81c0cced80ae13d2d44c40ba99ac183aa246103b31ec084594b1b7feb96da58f4be2dd5c0ed", - "0x8748d15d18b75ff2596f50d6a9c4ce82f61ecbcee123a6ceae0e43cab3012a29b6f83cf67b48c22f6f9d757c6caf76b2", - "0xb88ab05e4248b7fb634cf640a4e6a945d13e331237410f7217d3d17e3e384ddd48897e7a91e4516f1b9cbd30f35f238b", - "0x8d826deaeeb84a3b2d2c04c2300ca592501f992810582d6ae993e0d52f6283a839dba66c6c72278cff5871802b71173b", - "0xb36fed027c2f05a5ef625ca00b0364b930901e9e4420975b111858d0941f60e205546474bb25d6bfa6928d37305ae95f", - "0xaf2fcfc6b87967567e8b8a13a4ed914478185705724e56ce68fb2df6d1576a0cf34a61e880997a0d35dc2c3276ff7501", - "0xac351b919cd1fbf106feb8af2c67692bfcddc84762d18cea681cfa7470a5644839caace27efee5f38c87d3df306f4211", - "0x8d6665fb1d4d8d1fa23bd9b8a86e043b8555663519caac214d1e3e3effbc6bee7f2bcf21e645f77de0ced279d69a8a8b", - "0xa9fc1c2061756b2a1a169c1b149f212ff7f0d2488acd1c5a0197eba793cffa593fc6d1d1b40718aa75ca3ec77eff10e1", - "0xaff64f0fa009c7a6cf0b8d7a22ddb2c8170c3cb3eec082e60d5aadb00b0040443be8936d728d99581e33c22178c41c87", - "0x82e0b181adc5e3b1c87ff8598447260e839d53debfae941ebea38265575546c3a74a14b4325a030833a62ff6c52d9365", - "0xb7ad43cbb22f6f892c2a1548a41dc120ab1f4e1b8dea0cb6272dd9cb02054c542ecabc582f7e16de709d48f5166cae86", - "0x985e0c61094281532c4afb788ecb2dfcba998e974b5d4257a22040a161883908cdd068fe80f8eb49b8953cfd11acf43a", - "0xae46895c6d67ea6d469b6c9c07b9e5d295d9ae73b22e30da4ba2c973ba83a130d7eef39717ec9d0f36e81d56bf742671", - "0x8600177ea1f7e7ef90514b38b219a37dedfc39cb83297e4c7a5b479817ef56479d48cf6314820960c751183f6edf8b0e", - "0xb9208ec1c1d7a1e99b59c62d3e4e61dfb706b0e940d09d3abfc3454c19749083260614d89cfd7e822596c3cdbcc6bb95", - "0xa1e94042c796c2b48bc724352d2e9f3a22291d9a34705993357ddb6adabd76da6fc25dac200a8cb0b5bbd99ecddb7af6", - "0xb29c3adedd0bcad8a930625bc4dfdc3552a9afd5ca6dd9c0d758f978068c7982b50b711aa0eb5b97f2b84ee784637835", - "0xaf0632a238bb1f413c7ea8e9b4c3d68f2827bd2e38cd56024391fba6446ac5d19a780d0cfd4a78fe497d537b766a591a", - "0xaaf6e7f7d54f8ef5e2e45dd59774ecbeecf8683aa70483b2a75be6a6071b5981bbaf1627512a65d212817acdfab2e428", - "0x8c751496065da2e927cf492aa5ca9013b24f861d5e6c24b30bbf52ec5aaf1905f40f9a28175faef283dd4ed4f2182a09", - "0x8952377d8e80a85cf67d6b45499f3bad5fd452ea7bcd99efc1b066c4720d8e5bff1214cea90fd1f972a7f0baac3d29be", - "0xa1946ee543d1a6e21f380453be4d446e4130950c5fc3d075794eb8260f6f52d0a795c1ff91d028a648dc1ce7d9ab6b47", - "0x89f3fefe37af31e0c17533d2ca1ce0884cc1dc97c15cbfab9c331b8debd94781c9396abef4bb2f163d09277a08d6adf0", - "0xa2753f1e6e1a154fb117100a5bd9052137add85961f8158830ac20541ab12227d83887d10acf7fd36dcaf7c2596d8d23", - "0x814955b4198933ee11c3883863b06ff98c7eceb21fc3e09df5f916107827ccf3323141983e74b025f46ae00284c9513b", - "0x8cc5c6bb429073bfef47cae7b3bfccb0ffa076514d91a1862c6bda4d581e0df87db53cc6c130bf8a7826304960f5a34e", - "0x909f22c1f1cdc87f7be7439c831a73484a49acbf8f23d47087d7cf867c64ef61da3bde85dc57d705682b4c3fc710d36e", - "0x8048fee7f276fcd504aed91284f28e73693615e0eb3858fa44bcf79d7285a9001c373b3ef71d9a3054817ba293ebe28c", - "0x94400e5cf5d2700ca608c5fe35ce14623f71cc24959f2bc27ca3684092850f76b67fb1f07ca9e5b2ca3062cf8ad17bd4", - "0x81c2ae7d4d1b17f8b6de6a0430acc0d58260993980fe48dc2129c4948269cdc74f9dbfbf9c26b19360823fd913083d48", - "0x8c41fe765128e63f6889d6a979f6a4342300327c8b245a8cfe3ecfbcac1e09c3da30e2a1045b24b78efc6d6d50c8c6ac", - "0xa5dd4ae51ae48c8be4b218c312ade226cffce671cf121cb77810f6c0990768d6dd767badecb5c69921d5574d5e8433d3", - "0xb7642e325f4ba97ae2a39c1c9d97b35aafd49d53dba36aed3f3cb0ca816480b3394079f46a48252d46596559c90f4d58", - "0xae87375b40f35519e7bd4b1b2f73cd0b329b0c2cb9d616629342a71c6c304338445eda069b78ea0fbe44087f3de91e09", - "0xb08918cb6f736855e11d3daca1ddfbdd61c9589b203b5493143227bf48e2c77c2e8c94b0d1aa2fab2226e0eae83f2681", - "0xac36b84a4ac2ebd4d6591923a449c564e3be8a664c46092c09e875c2998eba16b5d32bfd0882fd3851762868e669f0b1", - "0xa44800a3bb192066fa17a3f29029a23697240467053b5aa49b9839fb9b9b8b12bcdcbfc557f024b61f4f51a9aacdefcb", - "0x9064c688fec23441a274cdf2075e5a449caf5c7363cc5e8a5dc9747183d2e00a0c69f2e6b3f6a7057079c46014c93b3b", - "0xaa367b021469af9f5b764a79bb3afbe2d87fe1e51862221672d1a66f954b165778b7c27a705e0f93841fab4c8468344d", - "0xa1a8bfc593d4ab71f91640bc824de5c1380ab2591cfdafcbc78a14b32de3c0e15f9d1b461d85c504baa3d4232c16bb53", - "0x97df48da1799430f528184d30b6baa90c2a2f88f34cdfb342d715339c5ebd6d019aa693cea7c4993daafc9849063a3aa", - "0xabd923831fbb427e06e0dd335253178a9e5791395c84d0ab1433c07c53c1209161097e9582fb8736f8a60bde62d8693e", - "0x84cd1a43f1a438b43dc60ffc775f646937c4f6871438163905a3cebf1115f814ccd38a6ccb134130bff226306e412f32", - "0x91426065996b0743c5f689eb3ca68a9f7b9e4d01f6c5a2652b57fa9a03d8dc7cd4bdbdab0ca5a891fee1e97a7f00cf02", - "0xa4bee50249db3df7fd75162b28f04e57c678ba142ce4d3def2bc17bcb29e4670284a45f218dad3969af466c62a903757", - "0x83141ebcc94d4681404e8b67a12a46374fded6df92b506aff3490d875919631408b369823a08b271d006d5b93136f317", - "0xa0ea1c8883d58d5a784da3d8c8a880061adea796d7505c1f903d07c287c5467f71e4563fc0faafbc15b5a5538b0a7559", - "0x89d9d480574f201a87269d26fb114278ed2c446328df431dc3556e3500e80e4cd01fcac196a2459d8646361ebda840df", - "0x8bf302978973632dd464bec819bdb91304712a3ec859be071e662040620422c6e75eba6f864f764cffa2799272efec39", - "0x922f666bc0fd58b6d7d815c0ae4f66d193d32fc8382c631037f59eeaeae9a8ca6c72d08e72944cf9e800b8d639094e77", - "0x81ad8714f491cdff7fe4399f2eb20e32650cff2999dd45b9b3d996d54a4aba24cc6c451212e78c9e5550368a1a38fb3f", - "0xb58fcf4659d73edb73175bd9139d18254e94c3e32031b5d4b026f2ed37aa19dca17ec2eb54c14340231615277a9d347e", - "0xb365ac9c2bfe409b710928c646ea2fb15b28557e0f089d39878e365589b9d1c34baf5566d20bb28b33bb60fa133f6eff", - "0x8fcae1d75b53ab470be805f39630d204853ca1629a14158bac2f52632277d77458dec204ff84b7b2d77e641c2045be65", - "0xa03efa6bebe84f4f958a56e2d76b5ba4f95dd9ed7eb479edc7cc5e646c8d4792e5b0dfc66cc86aa4b4afe2f7a4850760", - "0xaf1c823930a3638975fb0cc5c59651771b2719119c3cd08404fbd4ce77a74d708cefbe3c56ea08c48f5f10e6907f338f", - "0x8260c8299b17898032c761c325ac9cabb4c5b7e735de81eacf244f647a45fb385012f4f8df743128888c29aefcaaad16", - "0xab2f37a573c82e96a8d46198691cd694dfa860615625f477e41f91b879bc58a745784fccd8ffa13065834ffd150d881d", - "0x986c746c9b4249352d8e5c629e8d7d05e716b3c7aab5e529ca969dd1e984a14b5be41528baef4c85d2369a42d7209216", - "0xb25e32da1a8adddf2a6080725818b75bc67240728ad1853d90738485d8924ea1e202df0a3034a60ffae6f965ec55cf63", - "0xa266e627afcebcefea6b6b44cbc50f5c508f7187e87d047b0450871c2a030042c9e376f3ede0afcf9d1952f089582f71", - "0x86c3bbca4c0300606071c0a80dbdec21ce1dd4d8d4309648151c420854032dff1241a1677d1cd5de4e4de4385efda986", - "0xb9a21a1fe2d1f3273a8e4a9185abf2ff86448cc98bfa435e3d68306a2b8b4a6a3ea33a155be3cb62a2170a86f77679a5", - "0xb117b1ea381adce87d8b342cba3a15d492ff2d644afa28f22424cb9cbc820d4f7693dfc1a4d1b3697046c300e1c9b4c8", - "0x9004c425a2e68870d6c69b658c344e3aa3a86a8914ee08d72b2f95c2e2d8a4c7bb0c6e7e271460c0e637cec11117bf8e", - "0x86a18aa4783b9ebd9131580c8b17994825f27f4ac427b0929a1e0236907732a1c8139e98112c605488ee95f48bbefbfc", - "0x84042243b955286482ab6f0b5df4c2d73571ada00716d2f737ca05a0d2e88c6349e8ee9e67934cfee4a1775dbf7f4800", - "0x92c2153a4733a62e4e1d5b60369f3c26777c7d01cd3c8679212660d572bd3bac9b8a8a64e1f10f7dbf5eaa7579c4e423", - "0x918454b6bb8e44a2afa144695ba8d48ae08d0cdfef4ad078f67709eddf3bb31191e8b006f04e82ea45a54715ef4d5817", - "0xacf0b54f6bf34cf6ed6c2b39cf43194a40d68de6bcf1e4b82c34c15a1343e9ac3737885e1a30b78d01fa3a5125463db8", - "0xa7d60dbe4b6a7b054f7afe9ee5cbbfeca0d05dc619e6041fa2296b549322529faddb8a11e949562309aecefb842ac380", - "0x91ffb53e6d7e5f11159eaf13e783d6dbdfdb1698ed1e6dbf3413c6ea23492bbb9e0932230a9e2caac8fe899a17682795", - "0xb6e8d7be5076ee3565d5765a710c5ecf17921dd3cf555c375d01e958a365ae087d4a88da492a5fb81838b7b92bf01143", - "0xa8c6b763de2d4b2ed42102ef64eccfef31e2fb2a8a2776241c82912fa50fc9f77f175b6d109a97ede331307c016a4b1a", - "0x99839f86cb700c297c58bc33e28d46b92931961548deac29ba8df91d3e11721b10ea956c8e16984f9e4acf1298a79b37", - "0x8c2e2c338f25ea5c25756b7131cde0d9a2b35abf5d90781180a00fe4b8e64e62590dc63fe10a57fba3a31c76d784eb01", - "0x9687d7df2f41319ca5469d91978fed0565a5f11f829ebadaa83db92b221755f76c6eacd7700735e75c91e257087512e3", - "0x8795fdfb7ff8439c58b9bf58ed53873d2780d3939b902b9ddaaa4c99447224ced9206c3039a23c2c44bcc461e2bb637f", - "0xa803697b744d2d087f4e2307218d48fa88620cf25529db9ce71e2e3bbcc65bac5e8bb9be04777ef7bfb5ed1a5b8e6170", - "0x80f3d3efbbb9346ddd413f0a8e36b269eb5d7ff6809d5525ff9a47c4bcab2c01b70018b117f6fe05253775612ff70c6b", - "0x9050e0e45bcc83930d4c505af35e5e4d7ca01cd8681cba92eb55821aececcebe32bb692ebe1a4daac4e7472975671067", - "0x8d206812aac42742dbaf233e0c080b3d1b30943b54b60283515da005de05ea5caa90f91fedcfcba72e922f64d7040189", - "0xa2d44faaeb2eff7915c83f32b13ca6f31a6847b1c1ce114ea240bac3595eded89f09b2313b7915ad882292e2b586d5b4", - "0x961776c8576030c39f214ea6e0a3e8b3d32f023d2600958c098c95c8a4e374deeb2b9dc522adfbd6bda5949bdc09e2a2", - "0x993fa7d8447407af0fbcd9e6d77f815fa5233ab00674efbcf74a1f51c37481445ae291cc7b76db7c178f9cb0e570e0fc", - "0xabd5b1c78e05f9d7c8cc99bdaef8b0b6a57f2daf0f02bf492bec48ea4a27a8f1e38b5854da96efff11973326ff980f92", - "0x8f15af4764bc275e6ccb892b3a4362cacb4e175b1526a9a99944e692fe6ccb1b4fc19abf312bb2a089cb1f344d91a779", - "0xa09b27ccd71855512aba1d0c30a79ffbe7f6707a55978f3ced50e674b511a79a446dbc6d7946add421ce111135a460af", - "0x94b2f98ce86a9271fbd4153e1fc37de48421fe3490fb3840c00f2d5a4d0ba8810c6a32880b002f6374b59e0a7952518b", - "0x8650ac644f93bbcb88a6a0f49fee2663297fd4bc6fd47b6a89b9d8038d32370438ab3a4775ec9b58cb10aea8a95ef7b6", - "0x95e5c2f2e84eed88c6980bbba5a1c0bb375d5a628bff006f7516d45bb7d723da676add4fdd45956f312e7bab0f052644", - "0xb3278a3fa377ac93af7cfc9453f8cb594aae04269bbc99d2e0e45472ff4b6a2f97a26c4c57bf675b9d86f5e77a5d55d1", - "0xb4bcbe6eb666a206e2ea2f877912c1d3b5bdbd08a989fc4490eb06013e1a69ad1ba08bcdac048bf29192312be399077b", - "0xa76d70b78c99fffcbf9bb9886eab40f1ea4f99a309710b660b64cbf86057cbcb644d243f6e341711bb7ef0fedf0435a7", - "0xb2093c1ee945dca7ac76ad5aed08eae23af31dd5a77c903fd7b6f051f4ab84425d33a03c3d45bf2907bc93c02d1f3ad8", - "0x904b1f7534e053a265b22d20be859912b9c9ccb303af9a8d6f1d8f6ccdc5c53eb4a45a1762b880d8444d9be0cd55e7f9", - "0x8f664a965d65bc730c9ef1ec7467be984d4b8eb46bd9b0d64e38e48f94e6e55dda19aeac82cbcf4e1473440e64c4ca18", - "0x8bcee65c4cc7a7799353d07b114c718a2aae0cd10a3f22b7eead5185d159dafd64852cb63924bf87627d176228878bce", - "0x8c78f2e3675096fef7ebaa898d2615cd50d39ca3d8f02b9bdfb07e67da648ae4be3da64838dffc5935fd72962c4b96c7", - "0x8c40afd3701629421fec1df1aac4e849384ef2e80472c0e28d36cb1327acdf2826f99b357f3d7afdbc58a6347fc40b3c", - "0xa197813b1c65a8ea5754ef782522a57d63433ef752215ecda1e7da76b0412ee619f58d904abd2e07e0c097048b6ae1dd", - "0xa670542629e4333884ad7410f9ea3bd6f988df4a8f8a424ca74b9add2312586900cf9ae8bd50411f9146e82626b4af56", - "0xa19875cc07ab84e569d98b8b67fb1dbbdfb59093c7b748fae008c8904a6fd931a63ca8d03ab5fea9bc8d263568125a9b", - "0xb57e7f68e4eb1bd04aafa917b1db1bdab759a02aa8a9cdb1cba34ba8852b5890f655645c9b4e15d5f19bf37e9f2ffe9f", - "0x8abe4e2a4f6462b6c64b3f10e45db2a53c2b0d3c5d5443d3f00a453e193df771eda635b098b6c8604ace3557514027af", - "0x8459e4fb378189b22b870a6ef20183deb816cefbf66eca1dc7e86d36a2e011537db893729f500dc154f14ce24633ba47", - "0x930851df4bc7913c0d8c0f7bd3b071a83668987ed7c397d3d042fdc0d9765945a39a3bae83da9c88cb6b686ed8aeeb26", - "0x8078c9e5cd05e1a8c932f8a1d835f61a248b6e7133fcbb3de406bf4ffc0e584f6f9f95062740ba6008d98348886cf76b", - "0xaddff62bb29430983fe578e3709b0949cdc0d47a13a29bc3f50371a2cb5c822ce53e2448cfaa01bcb6e0aa850d5a380e", - "0x9433add687b5a1e12066721789b1db2edf9b6558c3bdc0f452ba33b1da67426abe326e9a34d207bfb1c491c18811bde1", - "0x822beda3389963428cccc4a2918fa9a8a51cf0919640350293af70821967108cded5997adae86b33cb917780b097f1ca", - "0xa7a9f52bda45e4148ed56dd176df7bd672e9b5ed18888ccdb405f47920fdb0844355f8565cefb17010b38324edd8315f", - "0xb35c3a872e18e607b2555c51f9696a17fa18da1f924d503b163b4ec9fe22ed0c110925275cb6c93ce2d013e88f173d6a", - "0xadf34b002b2b26ab84fc1bf94e05bd8616a1d06664799ab149363c56a6e0c807fdc473327d25632416e952ea327fcd95", - "0xae4a6b9d22a4a3183fac29e2551e1124a8ce4a561a9a2afa9b23032b58d444e6155bb2b48f85c7b6d70393274e230db7", - "0xa2ea3be4fc17e9b7ce3110284038d46a09e88a247b6971167a7878d9dcf36925d613c382b400cfa4f37a3ebea3699897", - "0x8e5863786b641ce3140fbfe37124d7ad3925472e924f814ebfc45959aaf3f61dc554a597610b5defaecc85b59a99b50f", - "0xaefde3193d0f700d0f515ab2aaa43e2ef1d7831c4f7859f48e52693d57f97fa9e520090f3ed700e1c966f4b76048e57f", - "0x841a50f772956622798e5cd208dc7534d4e39eddee30d8ce133383d66e5f267e389254a0cdae01b770ecd0a9ca421929", - "0x8fbc2bfd28238c7d47d4c03b1b910946c0d94274a199575e5b23242619b1de3497784e646a92aa03e3e24123ae4fcaba", - "0x926999579c8eec1cc47d7330112586bdca20b4149c8b2d066f527c8b9f609e61ce27feb69db67eea382649c6905efcf9", - "0xb09f31f305efcc65589adf5d3690a76cf339efd67cd43a4e3ced7b839507466e4be72dd91f04e89e4bbef629d46e68c0", - "0xb917361f6b95f759642638e0b1d2b3a29c3bdef0b94faa30de562e6078c7e2d25976159df3edbacbf43614635c2640b4", - "0x8e7e8a1253bbda0e134d62bfe003a2669d471b47bd2b5cde0ff60d385d8e62279d54022f5ac12053b1e2d3aaa6910b4c", - "0xb69671a3c64e0a99d90b0ed108ce1912ff8ed983e4bddd75a370e9babde25ee1f5efb59ec707edddd46793207a8b1fe7", - "0x910b2f4ebd37b7ae94108922b233d0920b4aba0bd94202c70f1314418b548d11d8e9caa91f2cd95aff51b9432d122b7f", - "0x82f645c90dfb52d195c1020346287c43a80233d3538954548604d09fbab7421241cde8593dbc4acc4986e0ea39a27dd9", - "0x8fee895f0a140d88104ce442fed3966f58ff9d275e7373483f6b4249d64a25fb5374bbdc6bce6b5ab0270c2847066f83", - "0x84f5bd7aab27b2509397aeb86510dd5ac0a53f2c8f73799bf720f2f87a52277f8d6b0f77f17bc80739c6a7119b7eb062", - "0x9903ceced81099d7e146e661bcf01cbaccab5ba54366b85e2177f07e2d8621e19d9c9c3eee14b9266de6b3f9b6ea75ae", - "0xb9c16ea2a07afa32dd6c7c06df0dec39bca2067a9339e45475c98917f47e2320f6f235da353fd5e15b477de97ddc68dd", - "0x9820a9bbf8b826bec61ebf886de2c4f404c1ebdc8bab82ee1fea816d9de29127ce1852448ff717a3fe8bbfe9e92012e5", - "0x817224d9359f5da6f2158c2c7bf9165501424f063e67ba9859a07ab72ee2ee62eb00ca6da821cfa19065c3282ca72c74", - "0x94b95c465e6cb00da400558a3c60cfec4b79b27e602ca67cbc91aead08de4b6872d8ea096b0dc06dca4525c8992b8547", - "0xa2b539a5bccd43fa347ba9c15f249b417997c6a38c63517ca38394976baa08e20be384a360969ff54e7e721db536b3e5", - "0x96caf707e34f62811ee8d32ccf28d8d6ec579bc33e424d0473529af5315c456fd026aa910c1fed70c91982d51df7d3ca", - "0x8a77b73e890b644c6a142bdbac59b22d6a676f3b63ddafb52d914bb9d395b8bf5aedcbcc90429337df431ebd758a07a6", - "0x8857830a7351025617a08bc44caec28d2fae07ebf5ffc9f01d979ce2a53839a670e61ae2783e138313929129790a51a1", - "0xaa3e420321ed6f0aa326d28d1a10f13facec6f605b6218a6eb9cbc074801f3467bf013a456d1415a5536f12599efa3d3", - "0x824aed0951957b00ea2f3d423e30328a3527bf6714cf9abbae84cf27e58e5c35452ba89ccc011de7c68c75d6e021d8f1", - "0xa2e87cc06bf202e953fb1081933d8b4445527dde20e38ed1a4f440144fd8fa464a2b73e068b140562e9045e0f4bd3144", - "0xae3b8f06ad97d7ae3a5e5ca839efff3e4824dc238c0c03fc1a8d2fc8aa546cdfd165b784a31bb4dec7c77e9305b99a4b", - "0xb30c3e12395b1fb8b776f3ec9f87c70e35763a7b2ddc68f0f60a4982a84017f27c891a98561c830038deb033698ed7fc", - "0x874e507757cd1177d0dff0b0c62ce90130324442a33da3b2c8ee09dbca5d543e3ecfe707e9f1361e7c7db641c72794bb", - "0xb53012dd10b5e7460b57c092eaa06d6502720df9edbbe3e3f61a9998a272bf5baaac4a5a732ad4efe35d6fac6feca744", - "0x85e6509d711515534d394e6cacbed6c81da710074d16ef3f4950bf2f578d662a494d835674f79c4d6315bced4defc5f0", - "0xb6132b2a34b0905dcadc6119fd215419a7971fe545e52f48b768006944b4a9d7db1a74b149e2951ea48c083b752d0804", - "0x989867da6415036d19b4bacc926ce6f4df7a556f50a1ba5f3c48eea9cefbb1c09da81481c8009331ee83f0859185e164", - "0x960a6c36542876174d3fbc1505413e29f053ed87b8d38fef3af180491c7eff25200b45dd5fe5d4d8e63c7e8c9c00f4c8", - "0x9040b59bd739d9cc2e8f6e894683429e4e876a8106238689ff4c22770ae5fdae1f32d962b30301fa0634ee163b524f35", - "0xaf3fcd0a45fe9e8fe256dc7eab242ef7f582dd832d147444483c62787ac820fafc6ca55d639a73f76bfa5e7f5462ab8f", - "0xb934c799d0736953a73d91e761767fdb78454355c4b15c680ce08accb57ccf941b13a1236980001f9e6195801cffd692", - "0x8871e8e741157c2c326b22cf09551e78da3c1ec0fc0543136f581f1550f8bab03b0a7b80525c1e99812cdbf3a9698f96", - "0xa8a977f51473a91d178ee8cfa45ffef8d6fd93ab1d6e428f96a3c79816d9c6a93cd70f94d4deda0125fd6816e30f3bea", - "0xa7688b3b0a4fc1dd16e8ba6dc758d3cfe1b7cf401c31739484c7fa253cce0967df1b290769bcefc9d23d3e0cb19e6218", - "0x8ae84322662a57c6d729e6ff9d2737698cc2da2daeb1f39e506618750ed23442a6740955f299e4a15dda6db3e534d2c6", - "0xa04a961cdccfa4b7ef83ced17ab221d6a043b2c718a0d6cc8e6f798507a31f10bf70361f70a049bc8058303fa7f96864", - "0xb463e39732a7d9daec8a456fb58e54b30a6e160aa522a18b9a9e836488cce3342bcbb2e1deab0f5e6ec0a8796d77197d", - "0xb1434a11c6750f14018a2d3bcf94390e2948f4f187e93bb22070ca3e5393d339dc328cbfc3e48815f51929465ffe7d81", - "0x84ff81d73f3828340623d7e3345553610aa22a5432217ef0ebd193cbf4a24234b190c65ca0873c22d10ea7b63bd1fbed", - "0xb6fe2723f0c47757932c2ddde7a4f8434f665612f7b87b4009c2635d56b6e16b200859a8ade49276de0ef27a2b6c970a", - "0x9742884ed7cd52b4a4a068a43d3faa02551a424136c85a9313f7cb58ea54c04aa83b0728fd741d1fe39621e931e88f8f", - "0xb7d2d65ea4d1ad07a5dee39e40d6c03a61264a56b1585b4d76fc5b2a68d80a93a42a0181d432528582bf08d144c2d6a9", - "0x88c0f66bada89f8a43e5a6ead2915088173d106c76f724f4a97b0f6758aed6ae5c37c373c6b92cdd4aea8f6261f3a374", - "0x81f9c43582cb42db3900747eb49ec94edb2284999a499d1527f03315fd330e5a509afa3bff659853570e9886aab5b28b", - "0x821f9d27d6beb416abf9aa5c79afb65a50ed276dbda6060103bc808bcd34426b82da5f23e38e88a55e172f5c294b4d40", - "0x8ba307b9e7cb63a6c4f3851b321aebfdb6af34a5a4c3bd949ff7d96603e59b27ff4dc4970715d35f7758260ff942c9e9", - "0xb142eb6c5f846de33227d0bda61d445a7c33c98f0a8365fe6ab4c1fabdc130849be597ef734305894a424ea715372d08", - "0xa732730ae4512e86a741c8e4c87fee8a05ee840fec0e23b2e037d58dba8dde8d10a9bc5191d34d00598941becbbe467f", - "0xadce6f7c30fd221f6b10a0413cc76435c4bb36c2d60bca821e5c67409fe9dbb2f4c36ef85eb3d734695e4be4827e9fd3", - "0xa74f00e0f9b23aff7b2527ce69852f8906dab9d6abe62ecd497498ab21e57542e12af9918d4fd610bb09e10b0929c510", - "0xa593b6b0ef26448ce4eb3ab07e84238fc020b3cb10d542ff4b16d4e2be1bcde3797e45c9cf753b8dc3b0ffdb63984232", - "0xaed3913afccf1aa1ac0eb4980eb8426d0baccebd836d44651fd72af00d09fac488a870223c42aca3ceb39752070405ae", - "0xb2c44c66a5ea7fde626548ba4cef8c8710191343d3dadfd3bb653ce715c0e03056a5303a581d47dde66e70ea5a2d2779", - "0x8e5029b2ccf5128a12327b5103f7532db599846e422531869560ceaff392236434d87159f597937dbf4054f810c114f4", - "0x82beed1a2c4477e5eb39fc5b0e773b30cfec77ef2b1bf17eadaf60eb35b6d0dd9d8cf06315c48d3546badb3f21cd0cca", - "0x90077bd6cc0e4be5fff08e5d07a5a158d36cebd1d1363125bc4fae0866ffe825b26f933d4ee5427ba5cd0c33c19a7b06", - "0xa7ec0d8f079970e8e34f0ef3a53d3e0e45428ddcef9cc776ead5e542ef06f3c86981644f61c5a637e4faf001fb8c6b3e", - "0xae6d4add6d1a6f90b22792bc9d40723ee6850c27d0b97eefafd5b7fd98e424aa97868b5287cc41b4fbd7023bca6a322c", - "0x831aa917533d077da07c01417feaa1408846363ba2b8d22c6116bb858a95801547dd88b7d7fa1d2e3f0a02bdeb2e103d", - "0x96511b860b07c8a5ed773f36d4aa9d02fb5e7882753bf56303595bcb57e37ccc60288887eb83bef08c657ec261a021a2", - "0x921d2a3e7e9790f74068623de327443666b634c8443aba80120a45bba450df920b2374d96df1ce3fb1b06dd06f8cf6e3", - "0xaa74451d51fe82b4581ead8e506ec6cd881010f7e7dd51fc388eb9a557db5d3c6721f81c151d08ebd9c2591689fbc13e", - "0xa972bfbcf4033d5742d08716c927c442119bdae336bf5dff914523b285ccf31953da2733759aacaa246a9af9f698342c", - "0xad1fcd0cae0e76840194ce4150cb8a56ebed728ec9272035f52a799d480dfc85840a4d52d994a18b6edb31e79be6e8ad", - "0xa2c69fe1d36f235215432dad48d75887a44c99dfa0d78149acc74087da215a44bdb5f04e6eef88ff7eff80a5a7decc77", - "0xa94ab2af2b6ee1bc6e0d4e689ca45380d9fbd3c5a65b9bd249d266a4d4c07bf5d5f7ef2ae6000623aee64027892bf8fe", - "0x881ec1fc514e926cdc66480ac59e139148ff8a2a7895a49f0dff45910c90cdda97b66441a25f357d6dd2471cddd99bb3", - "0x884e6d3b894a914c8cef946a76d5a0c8351843b2bffa2d1e56c6b5b99c84104381dd1320c451d551c0b966f4086e60f9", - "0x817c6c10ce2677b9fc5223500322e2b880583254d0bb0d247d728f8716f5e05c9ff39f135854342a1afecd9fbdcf7c46", - "0xaaf4a9cb686a14619aa1fc1ac285dd3843ac3dd99f2b2331c711ec87b03491c02f49101046f3c5c538dc9f8dba2a0ac2", - "0x97ecea5ce53ca720b5d845227ae61d70269a2f53540089305c86af35f0898bfd57356e74a8a5e083fa6e1ea70080bd31", - "0xa22d811e1a20a75feac0157c418a4bfe745ccb5d29466ffa854dca03e395b6c3504a734341746b2846d76583a780b32e", - "0x940cbaa0d2b2db94ae96b6b9cf2deefbfd059e3e5745de9aec4a25f0991b9721e5cd37ef71c631575d1a0c280b01cd5b", - "0xae33cb4951191258a11044682de861bf8d92d90ce751b354932dd9f3913f542b6a0f8a4dc228b3cd9244ac32c4582832", - "0xa580df5e58c4274fe0f52ac2da1837e32f5c9db92be16c170187db4c358f43e5cfdda7c5911dcc79d77a5764e32325f5", - "0x81798178cb9d8affa424f8d3be67576ba94d108a28ccc01d330c51d5a63ca45bb8ca63a2f569b5c5fe1303cecd2d777f", - "0x89975b91b94c25c9c3660e4af4047a8bacf964783010820dbc91ff8281509379cb3b24c25080d5a01174dd9a049118d5", - "0xa7327fcb3710ed3273b048650bde40a32732ef40a7e58cf7f2f400979c177944c8bc54117ba6c80d5d4260801dddab79", - "0x92b475dc8cb5be4b90c482f122a51bcb3b6c70593817e7e2459c28ea54a7845c50272af38119406eaadb9bcb993368d0", - "0x9645173e9ecefc4f2eae8363504f7c0b81d85f8949a9f8a6c01f2d49e0a0764f4eacecf3e94016dd407fc14494fce9f9", - "0x9215fd8983d7de6ae94d35e6698226fc1454977ae58d42d294be9aad13ac821562ad37d5e7ee5cdfe6e87031d45cd197", - "0x810360a1c9b88a9e36f520ab5a1eb8bed93f52deefbe1312a69225c0a08edb10f87cc43b794aced9c74220cefcc57e7d", - "0xad7e810efd61ed4684aeda9ed8bb02fb9ae4b4b63fda8217d37012b94ff1b91c0087043bfa4e376f961fff030c729f3b", - "0x8b07c95c6a06db8738d10bb03ec11b89375c08e77f0cab7e672ce70b2685667ca19c7e1c8b092821d31108ea18dfd4c7", - "0x968825d025ded899ff7c57245250535c732836f7565eab1ae23ee7e513201d413c16e1ba3f5166e7ac6cf74de8ceef4f", - "0x908243370c5788200703ade8164943ad5f8c458219186432e74dbc9904a701ea307fd9b94976c866e6c58595fd891c4b", - "0x959969d16680bc535cdc6339e6186355d0d6c0d53d7bbfb411641b9bf4b770fd5f575beef5deec5c4fa4d192d455c350", - "0xad177f4f826a961adeac76da40e2d930748effff731756c797eddc4e5aa23c91f070fb69b19221748130b0961e68a6bb", - "0x82f8462bcc25448ef7e0739425378e9bb8a05e283ce54aae9dbebaf7a3469f57833c9171672ad43a79778366c72a5e37", - "0xa28fb275b1845706c2814d9638573e9bc32ff552ebaed761fe96fdbce70395891ca41c400ae438369264e31a2713b15f", - "0x8a9c613996b5e51dadb587a787253d6081ea446bf5c71096980bf6bd3c4b69905062a8e8a3792de2d2ece3b177a71089", - "0x8d5aefef9f60cb27c1db2c649221204dda48bb9bf8bf48f965741da051340e8e4cab88b9d15c69f3f84f4c854709f48a", - "0x93ebf2ca6ad85ab6deace6de1a458706285b31877b1b4d7dcb9d126b63047efaf8c06d580115ec9acee30c8a7212fa55", - "0xb3ee46ce189956ca298057fa8223b7fd1128cf52f39159a58bca03c71dd25161ac13f1472301f72aef3e1993fe1ab269", - "0xa24d7a8d066504fc3f5027ccb13120e2f22896860e02c45b5eba1dbd512d6a17c28f39155ea581619f9d33db43a96f92", - "0xae9ceacbfe12137db2c1a271e1b34b8f92e4816bad1b3b9b6feecc34df0f8b3b0f7ed0133acdf59c537d43d33fc8d429", - "0x83967e69bf2b361f86361bd705dce0e1ad26df06da6c52b48176fe8dfcbeb03c462c1a4c9e649eff8c654b18c876fdef", - "0x9148e6b814a7d779c19c31e33a068e97b597de1f8100513db3c581190513edc4d544801ce3dd2cf6b19e0cd6daedd28a", - "0x94ccdafc84920d320ed22de1e754adea072935d3c5f8c2d1378ebe53d140ea29853f056fb3fb1e375846061a038cc9bc", - "0xafb43348498c38b0fa5f971b8cdd3a62c844f0eb52bc33daf2f67850af0880fce84ecfb96201b308d9e6168a0d443ae3", - "0x86d5736520a83538d4cd058cc4b4e84213ed00ebd6e7af79ae787adc17a92ba5359e28ba6c91936d967b4b28d24c3070", - "0xb5210c1ff212c5b1e9ef9126e08fe120a41e386bb12c22266f7538c6d69c7fd8774f11c02b81fd4e88f9137b020801fe", - "0xb78cfd19f94d24e529d0f52e18ce6185cb238edc6bd43086270fd51dd99f664f43dd4c7d2fe506762fbd859028e13fcf", - "0xa6e7220598c554abdcc3fdc587b988617b32c7bb0f82c06205467dbedb58276cc07cae317a190f19d19078773f4c2bbb", - "0xb88862809487ee430368dccd85a5d72fa4d163ca4aad15c78800e19c1a95be2192719801e315d86cff7795e0544a77e4", - "0x87ecb13a03921296f8c42ceb252d04716f10e09c93962239fcaa0a7fef93f19ab3f2680bc406170108bc583e9ff2e721", - "0xa810cd473832b6581c36ec4cb403f2849357ba2d0b54df98ef3004b8a530c078032922a81d40158f5fb0043d56477f6e", - "0xa247b45dd85ca7fbb718b328f30a03f03c84aef2c583fbdc9fcc9eb8b52b34529e8c8f535505c10598b1b4dac3d7c647", - "0x96ee0b91313c68bac4aa9e065ce9e1d77e51ca4cff31d6a438718c58264dee87674bd97fc5c6b8008be709521e4fd008", - "0x837567ad073e42266951a9a54750919280a2ac835a73c158407c3a2b1904cf0d17b7195a393c71a18ad029cbd9cf79ee", - "0xa6a469c44b67ebf02196213e7a63ad0423aab9a6e54acc6fcbdbb915bc043586993454dc3cd9e4be8f27d67c1050879b", - "0x8712d380a843b08b7b294f1f06e2f11f4ad6bcc655fdde86a4d8bc739c23916f6fad2b902fe47d6212f03607907e9f0e", - "0x920adfb644b534789943cdae1bdd6e42828dda1696a440af2f54e6b97f4f97470a1c6ea9fa6a2705d8f04911d055acd1", - "0xa161c73adf584a0061e963b062f59d90faac65c9b3a936b837a10d817f02fcabfa748824607be45a183dd40f991fe83f", - "0x874f4ecd408c76e625ea50bc59c53c2d930ee25baf4b4eca2440bfbffb3b8bc294db579caa7c68629f4d9ec24187c1ba", - "0x8bff18087f112be7f4aa654e85c71fef70eee8ae480f61d0383ff6f5ab1a0508f966183bb3fc4d6f29cb7ca234aa50d3", - "0xb03b46a3ca3bc743a173cbc008f92ab1aedd7466b35a6d1ca11e894b9482ea9dc75f8d6db2ddd1add99bfbe7657518b7", - "0x8b4f3691403c3a8ad9e097f02d130769628feddfa8c2b3dfe8cff64e2bed7d6e5d192c1e2ba0ac348b8585e94acd5fa1", - "0xa0d9ca4a212301f97591bf65d5ef2b2664766b427c9dd342e23cb468426e6a56be66b1cb41fea1889ac5d11a8e3c50a5", - "0x8c93ed74188ca23b3df29e5396974b9cc135c91fdefdea6c0df694c8116410e93509559af55533a3776ac11b228d69b1", - "0x82dd331fb3f9e344ebdeeb557769b86a2cc8cc38f6c298d7572a33aea87c261afa9dbd898989139b9fc16bc1e880a099", - "0xa65faedf326bcfd8ef98a51410c78b021d39206704e8291cd1f09e096a66b9b0486be65ff185ca224c45918ac337ddeb", - "0xa188b37d363ac072a766fd5d6fa27df07363feff1342217b19e3c37385e42ffde55e4be8355aceaa2f267b6d66b4ac41", - "0x810fa3ba3e96d843e3bafd3f2995727f223d3567c8ba77d684c993ba1773c66551eb5009897c51b3fe9b37196984f5ec", - "0x87631537541852da323b4353af45a164f68b304d24c01183bf271782e11687f3fcf528394e1566c2a26cb527b3148e64", - "0xb721cb2b37b3c477a48e3cc0044167d51ff568a5fd2fb606e5aec7a267000f1ddc07d3db919926ae12761a8e017c767c", - "0x904dfad4ba2cc1f6e60d1b708438a70b1743b400164cd981f13c064b8328d5973987d4fb9cf894068f29d3deaf624dfb", - "0xa70491538893552c20939fae6be2f07bfa84d97e2534a6bbcc0f1729246b831103505e9f60e97a8fa7d2e6c1c2384579", - "0x8726cf1b26b41f443ff7485adcfddc39ace2e62f4d65dd0bb927d933e262b66f1a9b367ded5fbdd6f3b0932553ac1735", - "0xae8a11cfdf7aa54c08f80cb645e3339187ab3886babe9fae5239ba507bb3dd1c0d161ca474a2df081dcd3d63e8fe445e", - "0x92328719e97ce60e56110f30a00ac5d9c7a2baaf5f8d22355d53c1c77941e3a1fec7d1405e6fbf8959665fe2ba7a8cad", - "0x8d9d6255b65798d0018a8cccb0b6343efd41dc14ff2058d3eed9451ceaad681e4a0fa6af67b0a04318aa628024e5553d", - "0xb70209090055459296006742d946a513f0cba6d83a05249ee8e7a51052b29c0ca9722dc4af5f9816a1b7938a5dac7f79", - "0xaab7b766b9bf91786dfa801fcef6d575dc6f12b77ecc662eb4498f0312e54d0de9ea820e61508fc8aeee5ab5db529349", - "0xa8104b462337748b7f086a135d0c3f87f8e51b7165ca6611264b8fb639d9a2f519926cb311fa2055b5fadf03da70c678", - "0xb0d2460747d5d8b30fc6c6bd0a87cb343ddb05d90a51b465e8f67d499cfc5e3a9e365da05ae233bbee792cdf90ec67d5", - "0xaa55f5bf3815266b4a149f85ed18e451c93de9163575e3ec75dd610381cc0805bb0a4d7c4af5b1f94d10231255436d2c", - "0x8d4c6a1944ff94426151909eb5b99cfd92167b967dabe2bf3aa66bb3c26c449c13097de881b2cfc1bf052862c1ef7b03", - "0x8862296162451b9b6b77f03bf32e6df71325e8d7485cf3335d66fd48b74c2a8334c241db8263033724f26269ad95b395", - "0x901aa96deb26cda5d9321190ae6624d357a41729d72ef1abfd71bebf6139af6d690798daba53b7bc5923462115ff748a", - "0x96c195ec4992728a1eb38cdde42d89a7bce150db43adbc9e61e279ea839e538deec71326b618dd39c50d589f78fc0614", - "0xb6ff8b8aa0837b99a1a8b46fb37f20ad4aecc6a98381b1308697829a59b8442ffc748637a88cb30c9b1f0f28a926c4f6", - "0x8d807e3dca9e7bef277db1d2cfb372408dd587364e8048b304eff00eacde2c723bfc84be9b98553f83cba5c7b3cba248", - "0x8800c96adb0195c4fc5b24511450dee503c32bf47044f5e2e25bd6651f514d79a2dd9b01cd8c09f3c9d3859338490f57", - "0x89fe366096097e38ec28dd1148887112efa5306cc0c3da09562aafa56f4eb000bf46ff79bf0bdd270cbde6bf0e1c8957", - "0xaf409a90c2776e1e7e3760b2042507b8709e943424606e31e791d42f17873a2710797f5baaab4cc4a19998ef648556b0", - "0x8d761863c9b6edbd232d35ab853d944f5c950c2b643f84a1a1327ebb947290800710ff01dcfa26dc8e9828481240e8b1", - "0x90b95e9be1e55c463ed857c4e0617d6dc3674e99b6aa62ed33c8e79d6dfcf7d122f4f4cc2ee3e7c5a49170cb617d2e2e", - "0xb3ff381efefabc4db38cc4727432e0301949ae4f16f8d1dea9b4f4de611cf5a36d84290a0bef160dac4e1955e516b3b0", - "0xa8a84564b56a9003adcadb3565dc512239fc79572762cda7b5901a255bc82656bb9c01212ad33d6bef4fbbce18dacc87", - "0x90a081890364b222eef54bf0075417f85e340d2fec8b7375995f598aeb33f26b44143ebf56fca7d8b4ebb36b5747b0eb", - "0xade6ee49e1293224ddf2d8ab7f14bb5be6bc6284f60fd5b3a1e0cf147b73cff57cf19763b8a36c5083badc79c606b103", - "0xb2fa99806dd2fa3de09320b615a2570c416c9bcdb052e592b0aead748bbe407ec9475a3d932ae48b71c2627eb81986a6", - "0x91f3b7b73c8ccc9392542711c45fe6f236057e6efad587d661ad5cb4d6e88265f86b807bb1151736b1009ab74fd7acb4", - "0x8800e2a46af96696dfbdcbf2ca2918b3dcf28ad970170d2d1783b52b8d945a9167d052beeb55f56c126da7ffa7059baa", - "0x9862267a1311c385956b977c9aa08548c28d758d7ba82d43dbc3d0a0fd1b7a221d39e8399997fea9014ac509ff510ac4", - "0xb7d24f78886fd3e2d283e18d9ad5a25c1a904e7d9b9104bf47da469d74f34162e27e531380dbbe0a9d051e6ffd51d6e7", - "0xb0f445f9d143e28b9df36b0f2c052da87ee2ca374d9d0fbe2eff66ca6fe5fe0d2c1951b428d58f7314b7e74e45d445ea", - "0xb63fc4083eabb8437dafeb6a904120691dcb53ce2938b820bb553da0e1eecd476f72495aacb72600cf9cad18698fd3db", - "0xb9ffd8108eaebd582d665f8690fe8bb207fd85185e6dd9f0b355a09bac1bbff26e0fdb172bc0498df025414e88fe2eda", - "0x967ed453e1f1a4c5b7b6834cc9f75c13f6889edc0cc91dc445727e9f408487bbf05c337103f61397a10011dfbe25d61d", - "0x98ceb673aff36e1987d5521a3984a07079c3c6155974bb8b413e8ae1ce84095fe4f7862fba7aefa14753eb26f2a5805f", - "0x85f01d28603a8fdf6ce6a50cb5c44f8a36b95b91302e3f4cd95c108ce8f4d212e73aec1b8d936520d9226802a2bd9136", - "0x88118e9703200ca07910345fbb789e7a8f92bd80bbc79f0a9e040e8767d33df39f6eded403a9b636eabf9101e588482a", - "0x90833a51eef1b10ed74e8f9bbd6197e29c5292e469c854eed10b0da663e2bceb92539710b1858bbb21887bd538d28d89", - "0xb513b905ec19191167c6193067b5cfdf5a3d3828375360df1c7e2ced5815437dfd37f0c4c8f009d7fb29ff3c8793f560", - "0xb1b6d405d2d18f9554b8a358cc7e2d78a3b34269737d561992c8de83392ac9a2857be4bf15de5a6c74e0c9d0f31f393c", - "0xb828bd3e452b797323b798186607849f85d1fb20c616833c0619360dfd6b3e3aa000fd09dafe4b62d74abc41072ff1a9", - "0x8efde67d0cca56bb2c464731879c9ac46a52e75bac702a63200a5e192b4f81c641f855ca6747752b84fe469cb7113b6c", - "0xb2762ba1c89ac3c9a983c242e4d1c2610ff0528585ed5c0dfc8a2c0253551142af9b59f43158e8915a1da7cc26b9df67", - "0x8a3f1157fb820d1497ef6b25cd70b7e16bb8b961b0063ad340d82a79ee76eb2359ca9e15e6d42987ed7f154f5eeaa2da", - "0xa75e29f29d38f09c879f971c11beb5368affa084313474a5ecafa2896180b9e47ea1995c2733ec46f421e395a1d9cffe", - "0x8e8c3dd3e7196ef0b4996b531ec79e4a1f211db5d5635e48ceb80ff7568b2ff587e845f97ee703bb23a60945ad64314a", - "0x8e7f32f4a3e3c584af5e3d406924a0aa34024c42eca74ef6cc2a358fd3c9efaf25f1c03aa1e66bb94b023a2ee2a1cace", - "0xab7dce05d59c10a84feb524fcb62478906b3fa045135b23afbede3bb32e0c678d8ebe59feabccb5c8f3550ea76cae44b", - "0xb38bb4b44d827f6fd3bd34e31f9186c59e312dbfadd4a7a88e588da10146a78b1f8716c91ad8b806beb8da65cab80c4c", - "0x9490ce9442bbbd05438c7f5c4dea789f74a7e92b1886a730544b55ba377840740a3ae4f2f146ee73f47c9278b0e233bc", - "0x83c003fab22a7178eed1a668e0f65d4fe38ef3900044e9ec63070c23f2827d36a1e73e5c2b883ec6a2afe2450171b3b3", - "0x9982f02405978ddc4fca9063ebbdb152f524c84e79398955e66fe51bc7c1660ec1afc3a86ec49f58d7b7dde03505731c", - "0xab337bd83ccdd2322088ffa8d005f450ced6b35790f37ab4534313315ee84312adc25e99cce052863a8bedee991729ed", - "0x8312ce4bec94366d88f16127a17419ef64285cd5bf9e5eda010319b48085966ed1252ed2f5a9fd3e0259b91bb65f1827", - "0xa60d5a6327c4041b0c00a1aa2f0af056520f83c9ce9d9ccd03a0bd4d9e6a1511f26a422ea86bd858a1f77438adf07e6c", - "0xb84a0a0b030bdad83cf5202aa9afe58c9820e52483ab41f835f8c582c129ee3f34aa096d11c1cd922eda02ea1196a882", - "0x8077d105317f4a8a8f1aadeb05e0722bb55f11abcb490c36c0904401107eb3372875b0ac233144829e734f0c538d8c1d", - "0x9202503bd29a6ec198823a1e4e098f9cfe359ed51eb5174d1ca41368821bfeebcbd49debfd02952c41359d1c7c06d2b1", - "0xabc28c155e09365cb77ffead8dc8f602335ef93b2f44e4ef767ce8fc8ef9dd707400f3a722e92776c2e0b40192c06354", - "0xb0f6d1442533ca45c9399e0a63a11f85ff288d242cea6cb3b68c02e77bd7d158047cae2d25b3bcd9606f8f66d9b32855", - "0xb01c3d56a0db84dc94575f4b6ee2de4beca3230e86bed63e2066beb22768b0a8efb08ebaf8ac3dedb5fe46708b084807", - "0x8c8634b0432159f66feaabb165842d1c8ac378f79565b1b90c381aa8450eb4231c3dad11ec9317b9fc2b155c3a771e32", - "0x8e67f623d69ecd430c9ee0888520b6038f13a2b6140525b056dc0951f0cfed2822e62cf11d952a483107c5c5acac4826", - "0x9590bb1cba816dd6acd5ac5fba5142c0a19d53573e422c74005e0bcf34993a8138c83124cad35a3df65879dba6134edd", - "0x801cd96cde0749021a253027118d3ea135f3fcdbe895db08a6c145641f95ebd368dd6a1568d995e1d0084146aebe224a", - "0x848b5d196427f6fc1f762ee3d36e832b64a76ec1033cfedc8b985dea93932a7892b8ef1035c653fb9dcd9ab2d9a44ac8", - "0xa1017eb83d5c4e2477e7bd2241b2b98c4951a3b391081cae7d75965cadc1acaec755cf350f1f3d29741b0828e36fedea", - "0x8d6d2785e30f3c29aad17bd677914a752f831e96d46caf54446d967cb2432be2c849e26f0d193a60bee161ea5c6fe90a", - "0x935c0ba4290d4595428e034b5c8001cbd400040d89ab00861108e8f8f4af4258e41f34a7e6b93b04bc253d3b9ffc13bf", - "0xaac02257146246998477921cef2e9892228590d323b839f3e64ea893b991b463bc2f47e1e5092ddb47e70b2f5bce7622", - "0xb921fde9412970a5d4c9a908ae8ce65861d06c7679af577cf0ad0d5344c421166986bee471fd6a6cecb7d591f06ec985", - "0x8ef4c37487b139d6756003060600bb6ebac7ea810b9c4364fc978e842f13ac196d1264fbe5af60d76ff6d9203d8e7d3f", - "0x94b65e14022b5cf6a9b95f94be5ace2711957c96f4211c3f7bb36206bd39cfbd0ea82186cab5ad0577a23214a5c86e9e", - "0xa31c166d2a2ca1d5a75a5920fef7532681f62191a50d8555fdaa63ba4581c3391cc94a536fc09aac89f64eafceec3f90", - "0x919a8cc128de01e9e10f5d83b08b52293fdd41bde2b5ae070f3d95842d4a16e5331cf2f3d61c765570c8022403610fa4", - "0xb23d6f8331eef100152d60483cfa14232a85ee712c8538c9b6417a5a7c5b353c2ac401390c6c215cb101f5cee6b5f43e", - "0xab357160c08a18319510a571eafff154298ce1020de8e1dc6138a09fcb0fcbcdd8359f7e9386bda00b7b9cdea745ffdc", - "0xab55079aea34afa5c0bd1124b9cdfe01f325b402fdfa017301bf87812eaa811ea5798c3aaf818074d420d1c782b10ada", - "0xade616010dc5009e7fc4f8d8b00dc716686a5fa0a7816ad9e503e15839d3b909b69d9dd929b7575376434ffec0d2bea8", - "0x863997b97ed46898a8a014599508fa3079f414b1f4a0c4fdc6d74ae8b444afa350f327f8bfc2a85d27f9e2d049c50135", - "0x8d602ff596334efd4925549ed95f2aa762b0629189f0df6dbb162581657cf3ea6863cd2287b4d9c8ad52813d87fcd235", - "0xb70f68c596dcdeed92ad5c6c348578b26862a51eb5364237b1221e840c47a8702f0fbc56eb520a22c0eed99795d3903e", - "0x9628088f8e0853cefadee305a8bf47fa990c50fa96a82511bbe6e5dc81ef4b794e7918a109070f92fc8384d77ace226f", - "0x97e26a46e068b605ce96007197ecd943c9a23881862f4797a12a3e96ba2b8d07806ad9e2a0646796b1889c6b7d75188c", - "0xb1edf467c068cc163e2d6413cc22b16751e78b3312fe47b7ea82b08a1206d64415b2c8f2a677fa89171e82cc49797150", - "0xa44d15ef18745b251429703e3cab188420e2d974de07251501799b016617f9630643fcd06f895634d8ecdd579e1bf000", - "0xabd126df3917ba48c618ee4dbdf87df506193462f792874439043fa1b844466f6f4e0ff2e42516e63b5b23c0892b2695", - "0xa2a67f57c4aa3c2aa1eeddbfd5009a89c26c2ce8fa3c96a64626aba19514beb125f27df8559506f737de3eae0f1fc18f", - "0xa633e0132197e6038197304b296ab171f1d8e0d0f34dcf66fe9146ac385b0239232a8470b9205a4802ab432389f4836d", - "0xa914b3a28509a906c3821463b936455d58ff45dcbe158922f9efb2037f2eb0ce8e92532d29b5d5a3fcd0d23fa773f272", - "0xa0e1412ce4505daf1a2e59ce4f0fc0e0023e335b50d2b204422f57cd65744cc7a8ed35d5ef131a42c70b27111d3115b7", - "0xa2339e2f2b6072e88816224fdd612c04d64e7967a492b9f8829db15367f565745325d361fd0607b0def1be384d010d9e", - "0xa7309fc41203cb99382e8193a1dcf03ac190a7ce04835304eb7e341d78634e83ea47cb15b885601956736d04cdfcaa01", - "0x81f3ccd6c7f5b39e4e873365f8c37b214e8ab122d04a606fbb7339dc3298c427e922ec7418002561d4106505b5c399ee", - "0x92c121cf914ca549130e352eb297872a63200e99b148d88fbc9506ad882bec9d0203d65f280fb5b0ba92e336b7f932e8", - "0xa4b330cf3f064f5b131578626ad7043ce2a433b6f175feb0b52d36134a454ca219373fd30d5e5796410e005b69082e47", - "0x86fe5774112403ad83f9c55d58317eeb17ad8e1176d9f2f69c2afb7ed83bc718ed4e0245ceab4b377f5f062dcd4c00e7", - "0x809d152a7e2654c7fd175b57f7928365a521be92e1ed06c05188a95864ddb25f7cab4c71db7d61bbf4cae46f3a1d96ce", - "0xb82d663e55c2a5ada7e169e9b1a87bc1c0177baf1ec1c96559b4cb1c5214ce1ddf2ab8d345014cab6402f3774235cf5a", - "0x86580af86df1bd2c385adb8f9a079e925981b7184db66fc5fe5b14cddb82e7d836b06eaeef14924ac529487b23dae111", - "0xb5f5f4c5c94944ecc804df6ab8687d64e27d988cbfeae1ba7394e0f6adbf778c5881ead7cd8082dd7d68542b9bb4ecd5", - "0xa6016916146c2685c46e8fdd24186394e2d5496e77e08c0c6a709d4cd7dfa97f1efcef94922b89196819076a91ad37b5", - "0xb778e7367ded3b6eab53d5fc257f7a87e8faf74a593900f2f517220add2125be3f6142022660d8181df8d164ad9441ce", - "0x8581b2d36abe6f553add4d24be761bec1b8efaa2929519114346615380b3c55b59e6ad86990e312f7e234d0203bdf59b", - "0x9917e74fd45c3f71a829ff5498a7f6b5599b48c098dda2339bf04352bfc7f368ccf1a407f5835901240e76452ae807d7", - "0xafd196ce6f9335069138fd2e3d133134da253978b4ce373152c0f26affe77a336505787594022e610f8feb722f7cc1fb", - "0xa477491a1562e329764645e8f24d8e228e5ef28c9f74c6b5b3abc4b6a562c15ffb0f680d372aed04d9e1bf944dece7be", - "0x9767440d58c57d3077319d3a330e5322b9ba16981ec74a5a14d53462eab59ae7fd2b14025bfc63b268862094acb444e6", - "0x80986d921be3513ef69264423f351a61cb48390c1be8673aee0f089076086aaebea7ebe268fd0aa7182695606116f679", - "0xa9554c5c921c07b450ee04e34ec58e054ac1541b26ce2ce5a393367a97348ba0089f53db6660ad76b60278b66fd12e3e", - "0x95097e7d2999b3e84bf052c775581cf361325325f4a50192521d8f4693c830bed667d88f482dc1e3f833aa2bd22d2cbf", - "0x9014c91d0f85aefd28436b5228c12f6353c055a9326c7efbf5e071e089e2ee7c070fcbc84c5fafc336cbb8fa6fec1ca1", - "0x90f57ba36ee1066b55d37384942d8b57ae00f3cf9a3c1d6a3dfee1d1af42d4b5fa9baeb0cd7e46687d1d6d090ddb931d", - "0x8e4b1db12fd760a17214c9e47f1fce6e43c0dbb4589a827a13ac61aaae93759345697bb438a00edab92e0b7b62414683", - "0x8022a959a513cdc0e9c705e0fc04eafd05ff37c867ae0f31f6d01cddd5df86138a426cab2ff0ac8ff03a62e20f7e8f51", - "0x914e9a38829834c7360443b8ed86137e6f936389488eccf05b4b4db7c9425611705076ecb3f27105d24b85c852be7511", - "0x957fb10783e2bd0db1ba66b18e794df710bc3b2b05776be146fa5863c15b1ebdd39747b1a95d9564e1772cdfc4f37b8a", - "0xb6307028444daed8ed785ac9d0de76bc3fe23ff2cc7e48102553613bbfb5afe0ebe45e4212a27021c8eb870721e62a1f", - "0x8f76143597777d940b15a01b39c5e1b045464d146d9a30a6abe8b5d3907250e6c7f858ff2308f8591e8b0a7b3f3c568a", - "0x96163138ac0ce5fd00ae9a289648fd9300a0ca0f63a88481d703ecd281c06a52a3b5178e849e331f9c85ca4ba398f4cc", - "0xa63ef47c3e18245b0482596a09f488a716df3cbd0f9e5cfabed0d742843e65db8961c556f45f49762f3a6ac8b627b3ef", - "0x8cb595466552e7c4d42909f232d4063e0a663a8ef6f6c9b7ce3a0542b2459cde04e0e54c7623d404acb5b82775ac04f6", - "0xb47fe69960eb45f399368807cff16d941a5a4ebad1f5ec46e3dc8a2e4d598a7e6114d8f0ca791e9720fd786070524e2b", - "0x89eb5ff83eea9df490e5beca1a1fbbbbcf7184a37e2c8c91ede7a1e654c81e8cd41eceece4042ea7918a4f4646b67fd6", - "0xa84f5d155ed08b9054eecb15f689ba81e44589e6e7207a99790c598962837ca99ec12344105b16641ca91165672f7153", - "0xa6cc8f25c2d5b2d2f220ec359e6a37a52b95fa6af6e173c65e7cd55299eff4aa9e6d9e6f2769e6459313f1f2aecb0fab", - "0xafcde944411f017a9f7979755294981e941cc41f03df5e10522ef7c7505e5f1babdd67b3bf5258e8623150062eb41d9b", - "0x8fab39f39c0f40182fcd996ade2012643fe7731808afbc53f9b26900b4d4d1f0f5312d9d40b3df8baa4739970a49c732", - "0xae193af9726da0ebe7df1f9ee1c4846a5b2a7621403baf8e66c66b60f523e719c30c6b4f897bb14b27d3ff3da8392eeb", - "0x8ac5adb82d852eba255764029f42e6da92dcdd0e224d387d1ef94174038db9709ac558d90d7e7c57ad4ce7f89bbfc38c", - "0xa2066b3458fdf678ee487a55dd5bfb74fde03b54620cb0e25412a89ee28ad0d685e309a51e3e4694be2fa6f1593a344c", - "0x88d031745dd0ae07d61a15b594be5d4b2e2a29e715d081649ad63605e3404b0c3a5353f0fd9fad9c05c18e93ce674fa1", - "0x8283cfb0ef743a043f2b77ecaeba3005e2ca50435585b5dd24777ee6bce12332f85e21b446b536da38508807f0f07563", - "0xb376de22d5f6b0af0b59f7d9764561f4244cf8ffe22890ecd3dcf2ff1832130c9b821e068c9d8773136f4796721e5963", - "0xae3afc50c764f406353965363840bf28ee85e7064eb9d5f0bb3c31c64ab10f48c853e942ee2c9b51bae59651eaa08c2f", - "0x948b204d103917461a01a6c57a88f2d66b476eae5b00be20ec8c747650e864bc8a83aee0aff59cb7584b7a3387e0ee48", - "0x81ab098a082b07f896c5ffd1e4446cb7fb44804cbbf38d125208b233fc82f8ec9a6a8d8dd1c9a1162dc28ffeec0dde50", - "0xa149c6f1312821ced2969268789a3151bdda213451760b397139a028da609c4134ac083169feb0ee423a0acafd10eceb", - "0xb0ac9e27a5dadaf523010f730b28f0ebac01f460d3bbbe277dc9d44218abb5686f4fac89ae462682fef9edbba663520a", - "0x8d0e0073cca273daaaa61b6fc54bfe5a009bc3e20ae820f6c93ba77b19eca517d457e948a2de5e77678e4241807157cb", - "0xad61d3a2edf7c7533a04964b97499503fd8374ca64286dba80465e68fe932e96749b476f458c6fc57cb1a7ca85764d11", - "0x90eb5e121ae46bc01a30881eaa556f46bd8457a4e80787cf634aab355082de34ac57d7f497446468225f7721e68e2a47", - "0x8cdac557de7c42d1f3780e33dec1b81889f6352279be81c65566cdd4952d4c15d79e656cbd46035ab090b385e90245ef", - "0x82b67e61b88b84f4f4d4f65df37b3e3dcf8ec91ea1b5c008fdccd52da643adbe6468a1cfdb999e87d195afe2883a3b46", - "0x8503b467e8f5d6048a4a9b78496c58493a462852cab54a70594ae3fd064cfd0deb4b8f336a262155d9fedcaa67d2f6fd", - "0x8db56c5ac763a57b6ce6832930c57117058e3e5a81532b7d19346346205e2ec614eb1a2ee836ef621de50a7bc9b7f040", - "0xad344699198f3c6e8c0a3470f92aaffc805b76266734414c298e10b5b3797ca53578de7ccb2f458f5e0448203f55282b", - "0x80602032c43c9e2a09154cc88b83238343b7a139f566d64cb482d87436b288a98f1ea244fd3bff8da3c398686a900c14", - "0xa6385bd50ecd548cfb37174cdbb89e10025b5cadaf3cff164c95d7aef5a33e3d6a9bf0c681b9e11db9ef54ebeee2a0c1", - "0xabf2d95f4aa34b0581eb9257a0cc8462b2213941a5deb8ba014283293e8b36613951b61261cc67bbd09526a54cbbff76", - "0xa3d5de52f48df72c289ff713e445991f142390798cd42bd9d9dbefaee4af4f5faf09042d126b975cf6b98711c3072553", - "0x8e627302ff3d686cff8872a1b7c2a57b35f45bf2fc9aa42b049d8b4d6996a662b8e7cbac6597f0cb79b0cc4e29fbf133", - "0x8510702e101b39a1efbf4e504e6123540c34b5689645e70d0bac1ecc1baf47d86c05cef6c4317a4e99b4edaeb53f2d00", - "0xaa173f0ecbcc6088f878f8726d317748c81ebf501bba461f163b55d66099b191ec7c55f7702f351a9c8eb42cfa3280e2", - "0xb560a697eafab695bcef1416648a0a664a71e311ecbe5823ae903bd0ed2057b9d7574b9a86d3fe22aa3e6ddce38ea513", - "0x8df6304a3d9cf40100f3f687575419c998cd77e5cc27d579cf4f8e98642de3609af384a0337d145dd7c5635172d26a71", - "0x8105c7f3e4d30a29151849673853b457c1885c186c132d0a98e63096c3774bc9deb956cf957367e633d0913680bda307", - "0x95373fc22c0917c3c2044ac688c4f29a63ed858a45c0d6d2d0fe97afd6f532dcb648670594290c1c89010ecc69259bef", - "0x8c2fae9bcadab341f49b55230310df93cac46be42d4caa0d42e45104148a91e527af1b4209c0d972448162aed28fab64", - "0xb05a77baab70683f76209626eaefdda2d36a0b66c780a20142d23c55bd479ddd4ad95b24579384b6cf62c8eb4c92d021", - "0x8e6bc6a7ea2755b4aaa19c1c1dee93811fcde514f03485fdc3252f0ab7f032c315614f6336e57cea25dcfb8fb6084eeb", - "0xb656a27d06aade55eadae2ad2a1059198918ea6cc3fd22c0ed881294d34d5ac7b5e4700cc24350e27d76646263b223aa", - "0xa296469f24f6f56da92d713afcd4dd606e7da1f79dc4e434593c53695847eefc81c7c446486c4b3b8c8d00c90c166f14", - "0x87a326f57713ac2c9dffeb3af44b9f3c613a8f952676fc46343299122b47ee0f8d792abaa4b5db6451ced5dd153aabd0", - "0xb689e554ba9293b9c1f6344a3c8fcb6951d9f9eac4a2e2df13de021aade7c186be27500e81388e5b8bcab4c80f220a31", - "0x87ae0aa0aa48eac53d1ca5a7b93917de12db9e40ceabf8fdb40884ae771cfdf095411deef7c9f821af0b7070454a2608", - "0xa71ffa7eae8ace94e6c3581d4cb2ad25d48cbd27edc9ec45baa2c8eb932a4773c3272b2ffaf077b40f76942a1f3af7f2", - "0x94c218c91a9b73da6b7a495b3728f3028df8ad9133312fc0c03e8c5253b7ccb83ed14688fd4602e2fd41f29a0bc698bd", - "0xae1e77b90ca33728af07a4c03fb2ef71cd92e2618e7bf8ed4d785ce90097fc4866c29999eb84a6cf1819d75285a03af2", - "0xb7a5945b277dab9993cf761e838b0ac6eaa903d7111fca79f9fde3d4285af7a89bf6634a71909d095d7619d913972c9c", - "0x8c43b37be02f39b22029b20aca31bff661abce4471dca88aa3bddefd9c92304a088b2dfc8c4795acc301ca3160656af2", - "0xb32e5d0fba024554bd5fe8a793ebe8003335ddd7f585876df2048dcf759a01285fecb53daae4950ba57f3a282a4d8495", - "0x85ea7fd5e10c7b659df5289b2978b2c89e244f269e061b9a15fcab7983fc1962b63546e82d5731c97ec74b6804be63ef", - "0x96b89f39181141a7e32986ac02d7586088c5a9662cec39843f397f3178714d02f929af70630c12cbaba0268f8ba2d4fa", - "0x929ab1a2a009b1eb37a2817c89696a06426529ebe3f306c586ab717bd34c35a53eca2d7ddcdef36117872db660024af9", - "0xa696dccf439e9ca41511e16bf3042d7ec0e2f86c099e4fc8879d778a5ea79e33aa7ce96b23dc4332b7ba26859d8e674d", - "0xa8fe69a678f9a194b8670a41e941f0460f6e2dbc60470ab4d6ae2679cc9c6ce2c3a39df2303bee486dbfde6844e6b31a", - "0x95f58f5c82de2f2a927ca99bf63c9fc02e9030c7e46d0bf6b67fe83a448d0ae1c99541b59caf0e1ccab8326231af09a5", - "0xa57badb2c56ca2c45953bd569caf22968f76ed46b9bac389163d6fe22a715c83d5e94ae8759b0e6e8c2f27bff7748f3f", - "0x868726fd49963b24acb5333364dffea147e98f33aa19c7919dc9aca0fd26661cfaded74ede7418a5fadbe7f5ae67b67b", - "0xa8d8550dcc64d9f1dd7bcdab236c4122f2b65ea404bb483256d712c7518f08bb028ff8801f1da6aed6cbfc5c7062e33b", - "0x97e25a87dae23155809476232178538d4bc05d4ff0882916eb29ae515f2a62bfce73083466cc0010ca956aca200aeacc", - "0xb4ea26be3f4bd04aa82d7c4b0913b97bcdf5e88b76c57eb1a336cbd0a3eb29de751e1bc47c0e8258adec3f17426d0c71", - "0x99ee555a4d9b3cf2eb420b2af8e3bc99046880536116d0ce7193464ac40685ef14e0e3c442f604e32f8338cb0ef92558", - "0x8c64efa1da63cd08f319103c5c7a761221080e74227bbc58b8fb35d08aa42078810d7af3e60446cbaff160c319535648", - "0x8d9fd88040076c28420e3395cbdfea402e4077a3808a97b7939d49ecbcf1418fe50a0460e1c1b22ac3f6e7771d65169a", - "0xae3c19882d7a9875d439265a0c7003c8d410367627d21575a864b9cb4918de7dbdb58a364af40c5e045f3df40f95d337", - "0xb4f7bfacab7b2cafe393f1322d6dcc6f21ffe69cd31edc8db18c06f1a2b512c27bd0618091fd207ba8df1808e9d45914", - "0x94f134acd0007c623fb7934bcb65ef853313eb283a889a3ffa79a37a5c8f3665f3d5b4876bc66223610c21dc9b919d37", - "0xaa15f74051171daacdc1f1093d3f8e2d13da2833624b80a934afec86fc02208b8f55d24b7d66076444e7633f46375c6a", - "0xa32d6bb47ef9c836d9d2371807bafbbbbb1ae719530c19d6013f1d1f813c49a60e4fa51d83693586cba3a840b23c0404", - "0xb61b3599145ea8680011aa2366dc511a358b7d67672d5b0c5be6db03b0efb8ca5a8294cf220ea7409621f1664e00e631", - "0x859cafc3ee90b7ececa1ed8ef2b2fc17567126ff10ca712d5ffdd16aa411a5a7d8d32c9cab1fbf63e87dce1c6e2f5f53", - "0xa2fef1b0b2874387010e9ae425f3a9676d01a095d017493648bcdf3b31304b087ccddb5cf76abc4e1548b88919663b6b", - "0x939e18c73befc1ba2932a65ede34c70e4b91e74cc2129d57ace43ed2b3af2a9cc22a40fbf50d79a63681b6d98852866d", - "0xb3b4259d37b1b14aee5b676c9a0dd2d7f679ab95c120cb5f09f9fbf10b0a920cb613655ddb7b9e2ba5af4a221f31303c", - "0x997255fe51aaca6e5a9cb3359bcbf25b2bb9e30649bbd53a8a7c556df07e441c4e27328b38934f09c09d9500b5fabf66", - "0xabb91be2a2d860fd662ed4f1c6edeefd4da8dc10e79251cf87f06029906e7f0be9b486462718f0525d5e049472692cb7", - "0xb2398e593bf340a15f7801e1d1fbda69d93f2a32a889ec7c6ae5e8a37567ac3e5227213c1392ee86cfb3b56ec2787839", - "0x8ddf10ccdd72922bed36829a36073a460c2118fc7a56ff9c1ac72581c799b15c762cb56cb78e3d118bb9f6a7e56cb25e", - "0x93e6bc0a4708d16387cacd44cf59363b994dc67d7ada7b6d6dbd831c606d975247541b42b2a309f814c1bfe205681fc6", - "0xb93fc35c05998cffda2978e12e75812122831523041f10d52f810d34ff71944979054b04de0117e81ddf5b0b4b3e13c0", - "0x92221631c44d60d68c6bc7b287509f37ee44cbe5fdb6935cee36b58b17c7325098f98f7910d2c3ca5dc885ad1d6dabc7", - "0xa230124424a57fad3b1671f404a94d7c05f4c67b7a8fbacfccea28887b78d7c1ed40b92a58348e4d61328891cd2f6cee", - "0xa6a230edb8518a0f49d7231bc3e0bceb5c2ac427f045819f8584ba6f3ae3d63ed107a9a62aad543d7e1fcf1f20605706", - "0x845be1fe94223c7f1f97d74c49d682472585d8f772762baad8a9d341d9c3015534cc83d102113c51a9dea2ab10d8d27b", - "0xb44262515e34f2db597c8128c7614d33858740310a49cdbdf9c8677c5343884b42c1292759f55b8b4abc4c86e4728033", - "0x805592e4a3cd07c1844bc23783408310accfdb769cca882ad4d07d608e590a288b7370c2cb327f5336e72b7083a0e30f", - "0x95153e8b1140df34ee864f4ca601cb873cdd3efa634af0c4093fbaede36f51b55571ab271e6a133020cd34db8411241f", - "0x82878c1285cfa5ea1d32175c9401f3cc99f6bb224d622d3fd98cc7b0a27372f13f7ab463ce3a33ec96f9be38dbe2dfe3", - "0xb7588748f55783077c27fc47d33e20c5c0f5a53fc0ac10194c003aa09b9f055d08ec971effa4b7f760553997a56967b3", - "0xb36b4de6d1883b6951f59cfae381581f9c6352fcfcf1524fccdab1571a20f80441d9152dc6b48bcbbf00371337ca0bd5", - "0x89c5523f2574e1c340a955cbed9c2f7b5fbceb260cb1133160dabb7d41c2f613ec3f6e74bbfab3c4a0a6f0626dbe068f", - "0xa52f58cc39f968a9813b1a8ddc4e83f4219e4dd82c7aa1dd083bea7edf967151d635aa9597457f879771759b876774e4", - "0x8300a67c2e2e123f89704abfde095463045dbd97e20d4c1157bab35e9e1d3d18f1f4aaba9cbe6aa2d544e92578eaa1b6", - "0xac6a7f2918768eb6a43df9d3a8a04f8f72ee52f2e91c064c1c7d75cad1a3e83e5aba9fe55bb94f818099ac91ccf2e961", - "0x8d64a2b0991cf164e29835c8ddef6069993a71ec2a7de8157bbfa2e00f6367be646ed74cbaf524f0e9fe13fb09fa15fd", - "0x8b2ffe5a545f9f680b49d0a9797a4a11700a2e2e348c34a7a985fc278f0f12def6e06710f40f9d48e4b7fbb71e072229", - "0x8ab8f71cd337fa19178924e961958653abf7a598e3f022138b55c228440a2bac4176cea3aea393549c03cd38a13eb3fc", - "0x8419d28318c19ea4a179b7abb43669fe96347426ef3ac06b158d79c0acf777a09e8e770c2fb10e14b3a0421705990b23", - "0x8bacdac310e1e49660359d0a7a17fe3d334eb820e61ae25e84cb52f863a2f74cbe89c2e9fc3283745d93a99b79132354", - "0xb57ace3fa2b9f6b2db60c0d861ace7d7e657c5d35d992588aeed588c6ce3a80b6f0d49f8a26607f0b17167ab21b675e4", - "0x83e265cde477f2ecc164f49ddc7fb255bb05ff6adc347408353b7336dc3a14fdedc86d5a7fb23f36b8423248a7a67ed1", - "0xa60ada971f9f2d79d436de5d3d045f5ab05308cae3098acaf5521115134b2a40d664828bb89895840db7f7fb499edbc5", - "0xa63eea12efd89b62d3952bf0542a73890b104dd1d7ff360d4755ebfa148fd62de668edac9eeb20507967ea37fb220202", - "0xa0275767a270289adc991cc4571eff205b58ad6d3e93778ddbf95b75146d82517e8921bd0d0564e5b75fa0ccdab8e624", - "0xb9b03fd3bf07201ba3a039176a965d736b4ef7912dd9e9bf69fe1b57c330a6aa170e5521fe8be62505f3af81b41d7806", - "0xa95f640e26fb1106ced1729d6053e41a16e4896acac54992279ff873e5a969aad1dcfa10311e28b8f409ac1dab7f03bb", - "0xb144778921742418053cb3c70516c63162c187f00db2062193bb2c14031075dbe055d020cde761b26e8c58d0ea6df2c1", - "0x8432fbb799e0435ef428d4fefc309a05dd589bce74d7a87faf659823e8c9ed51d3e42603d878e80f439a38be4321c2fa", - "0xb08ddef14e42d4fd5d8bf39feb7485848f0060d43b51ed5bdda39c05fe154fb111d29719ee61a23c392141358c0cfcff", - "0x8ae3c5329a5e025b86b5370e06f5e61177df4bda075856fade20a17bfef79c92f54ed495f310130021ba94fb7c33632b", - "0x92b6d3c9444100b4d7391febfc1dddaa224651677c3695c47a289a40d7a96d200b83b64e6d9df51f534564f272a2c6c6", - "0xb432bc2a3f93d28b5e506d68527f1efeb2e2570f6be0794576e2a6ef9138926fdad8dd2eabfa979b79ab7266370e86bc", - "0x8bc315eacedbcfc462ece66a29662ca3dcd451f83de5c7626ef8712c196208fb3d8a0faf80b2e80384f0dd9772f61a23", - "0xa72375b797283f0f4266dec188678e2b2c060dfed5880fc6bb0c996b06e91a5343ea2b695adaab0a6fd183b040b46b56", - "0xa43445036fbaa414621918d6a897d3692fdae7b2961d87e2a03741360e45ebb19fcb1703d23f1e15bb1e2babcafc56ac", - "0xb9636b2ffe305e63a1a84bd44fb402442b1799bd5272638287aa87ca548649b23ce8ce7f67be077caed6aa2dbc454b78", - "0x99a30bf0921d854c282b83d438a79f615424f28c2f99d26a05201c93d10378ab2cd94a792b571ddae5d4e0c0013f4006", - "0x8648e3c2f93d70b392443be116b48a863e4b75991bab5db656a4ef3c1e7f645e8d536771dfe4e8d1ceda3be8d32978b0", - "0xab50dc9e6924c1d2e9d2e335b2d679fc7d1a7632e84964d3bac0c9fe57e85aa5906ec2e7b0399d98ddd022e9b19b5904", - "0xab729328d98d295f8f3272afaf5d8345ff54d58ff9884da14f17ecbdb7371857fdf2f3ef58080054e9874cc919b46224", - "0x83fa5da7592bd451cad3ad7702b4006332b3aae23beab4c4cb887fa6348317d234bf62a359e665b28818e5410c278a09", - "0x8bdbff566ae9d368f114858ef1f009439b3e9f4649f73efa946e678d6c781d52c69af195df0a68170f5f191b2eac286b", - "0x91245e59b4425fd4edb2a61d0d47c1ccc83d3ced8180de34887b9655b5dcda033d48cde0bdc3b7de846d246c053a02e8", - "0xa2cb00721e68f1cad8933947456f07144dc69653f96ceed845bd577d599521ba99cdc02421118971d56d7603ed118cbf", - "0xaf8cd66d303e808b22ec57860dd909ca64c27ec2c60e26ffecfdc1179d8762ffd2739d87b43959496e9fee4108df71df", - "0x9954136812dffcd5d3f167a500e7ab339c15cfc9b3398d83f64b0daa3dd5b9a851204f424a3493b4e326d3de81e50a62", - "0x93252254d12511955f1aa464883ad0da793f84d900fea83e1df8bca0f2f4cf5b5f9acbaec06a24160d33f908ab5fea38", - "0x997cb55c26996586ba436a95566bd535e9c22452ca5d2a0ded2bd175376557fa895f9f4def4519241ff386a063f2e526", - "0xa12c78ad451e0ac911260ade2927a768b50cb4125343025d43474e7f465cdc446e9f52a84609c5e7e87ae6c9b3f56cda", - "0xa789d4ca55cbba327086563831b34487d63d0980ba8cf55197c016702ed6da9b102b1f0709ce3da3c53ff925793a3d73", - "0xa5d76acbb76741ce85be0e655b99baa04f7f587347947c0a30d27f8a49ae78cce06e1cde770a8b618d3db402be1c0c4b", - "0x873c0366668c8faddb0eb7c86f485718d65f8c4734020f1a18efd5fa123d3ea8a990977fe13592cd01d17e60809cb5ff", - "0xb659b71fe70f37573ff7c5970cc095a1dc0da3973979778f80a71a347ef25ad5746b2b9608bad4ab9a4a53a4d7df42d7", - "0xa34cbe05888e5e5f024a2db14cb6dcdc401a9cbd13d73d3c37b348f68688f87c24ca790030b8f84fef9e74b4eab5e412", - "0x94ce8010f85875c045b0f014db93ef5ab9f1f6842e9a5743dce9e4cb872c94affd9e77c1f1d1ab8b8660b52345d9acb9", - "0xadefa9b27a62edc0c5b019ddd3ebf45e4de846165256cf6329331def2e088c5232456d3de470fdce3fa758bfdd387512", - "0xa6b83821ba7c1f83cc9e4529cf4903adb93b26108e3d1f20a753070db072ad5a3689643144bdd9c5ea06bb9a7a515cd0", - "0xa3a9ddedc2a1b183eb1d52de26718151744db6050f86f3580790c51d09226bf05f15111691926151ecdbef683baa992c", - "0xa64bac89e7686932cdc5670d07f0b50830e69bfb8c93791c87c7ffa4913f8da881a9d8a8ce8c1a9ce5b6079358c54136", - "0xa77b5a63452cb1320b61ab6c7c2ef9cfbcade5fd4727583751fb2bf3ea330b5ca67757ec1f517bf4d503ec924fe32fbd", - "0x8746fd8d8eb99639d8cd0ca34c0d9c3230ed5a312aab1d3d925953a17973ee5aeb66e68667e93caf9cb817c868ea8f3d", - "0x88a2462a26558fc1fbd6e31aa8abdc706190a17c27fdc4217ffd2297d1b1f3321016e5c4b2384c5454d5717dc732ed03", - "0xb78893a97e93d730c8201af2e0d3b31cb923d38dc594ffa98a714e627c473d42ea82e0c4d2eeb06862ee22a9b2c54588", - "0x920cc8b5f1297cf215a43f6fc843e379146b4229411c44c0231f6749793d40f07b9af7699fd5d21fd69400b97febe027", - "0xa0f0eafce1e098a6b58c7ad8945e297cd93aaf10bc55e32e2e32503f02e59fc1d5776936577d77c0b1162cb93b88518b", - "0x98480ba0064e97a2e7a6c4769b4d8c2a322cfc9a3b2ca2e67e9317e2ce04c6e1108169a20bd97692e1cb1f1423b14908", - "0x83dbbb2fda7e287288011764a00b8357753a6a44794cc8245a2275237f11affdc38977214e463ad67aec032f3dfa37e9", - "0x86442fff37598ce2b12015ff19b01bb8a780b40ad353d143a0f30a06f6d23afd5c2b0a1253716c855dbf445cc5dd6865", - "0xb8a4c60c5171189414887847b9ed9501bff4e4c107240f063e2d254820d2906b69ef70406c585918c4d24f1dd052142b", - "0x919f33a98e84015b2034b57b5ffe9340220926b2c6e45f86fd79ec879dbe06a148ae68b77b73bf7d01bd638a81165617", - "0x95c13e78d89474a47fbc0664f6f806744b75dede95a479bbf844db4a7f4c3ae410ec721cb6ffcd9fa9c323da5740d5ae", - "0xab7151acc41fffd8ec6e90387700bcd7e1cde291ea669567295bea1b9dd3f1df2e0f31f3588cd1a1c08af8120aca4921", - "0x80e74c5c47414bd6eeef24b6793fb1fa2d8fb397467045fcff887c52476741d5bc4ff8b6d3387cb53ad285485630537f", - "0xa296ad23995268276aa351a7764d36df3a5a3cffd7dbeddbcea6b1f77adc112629fdeffa0918b3242b3ccd5e7587e946", - "0x813d2506a28a2b01cb60f49d6bd5e63c9b056aa56946faf2f33bd4f28a8d947569cfead3ae53166fc65285740b210f86", - "0x924b265385e1646287d8c09f6c855b094daaee74b9e64a0dddcf9ad88c6979f8280ba30c8597b911ef58ddb6c67e9fe3", - "0x8d531513c70c2d3566039f7ca47cd2352fd2d55b25675a65250bdb8b06c3843db7b2d29c626eed6391c238fc651cf350", - "0x82b338181b62fdc81ceb558a6843df767b6a6e3ceedc5485664b4ea2f555904b1a45fbb35f6cf5d96f27da10df82a325", - "0x92e62faaedea83a37f314e1d3cb4faaa200178371d917938e59ac35090be1db4b4f4e0edb78b9c991de202efe4f313d8", - "0x99d645e1b642c2dc065bac9aaa0621bc648c9a8351efb6891559c3a41ba737bd155fb32d7731950514e3ecf4d75980e4", - "0xb34a13968b9e414172fb5d5ece9a39cf2eb656128c3f2f6cc7a9f0c69c6bae34f555ecc8f8837dc34b5e470e29055c78", - "0xa2a0bb7f3a0b23a2cbc6585d59f87cd7e56b2bbcb0ae48f828685edd9f7af0f5edb4c8e9718a0aaf6ef04553ba71f3b7", - "0x8e1a94bec053ed378e524b6685152d2b52d428266f2b6eadd4bcb7c4e162ed21ab3e1364879673442ee2162635b7a4d8", - "0x9944adaff14a85eab81c73f38f386701713b52513c4d4b838d58d4ffa1d17260a6d056b02334850ea9a31677c4b078bd", - "0xa450067c7eceb0854b3eca3db6cf38669d72cb7143c3a68787833cbca44f02c0be9bfbe082896f8a57debb13deb2afb1", - "0x8be4ad3ac9ef02f7df09254d569939757101ee2eda8586fefcd8c847adc1efe5bdcb963a0cafa17651befaafb376a531", - "0x90f6de91ea50255f148ac435e08cf2ac00c772a466e38155bd7e8acf9197af55662c7b5227f88589b71abe9dcf7ba343", - "0x86e5a24f0748b106dee2d4d54e14a3b0af45a96cbee69cac811a4196403ebbee17fd24946d7e7e1b962ac7f66dbaf610", - "0xafdd96fbcda7aa73bf9eeb2292e036c25753d249caee3b9c013009cc22e10d3ec29e2aa6ddbb21c4e949b0c0bccaa7f4", - "0xb5a4e7436d5473647c002120a2cb436b9b28e27ad4ebdd7c5f122b91597c507d256d0cbd889d65b3a908531936e53053", - "0xb632414c3da704d80ac2f3e5e0e9f18a3637cdc2ebeb613c29300745582427138819c4e7b0bec3099c1b8739dac1807b", - "0xa28df1464d3372ce9f37ef1db33cc010f752156afae6f76949d98cd799c0cf225c20228ae86a4da592d65f0cffe3951b", - "0x898b93d0a31f7d3f11f253cb7a102db54b669fd150da302d8354d8e02b1739a47cb9bd88015f3baf12b00b879442464e", - "0x96fb88d89a12049091070cb0048a381902965e67a8493e3991eaabe5d3b7ff7eecd5c94493a93b174df3d9b2c9511755", - "0xb899cb2176f59a5cfba3e3d346813da7a82b03417cad6342f19cc8f12f28985b03bf031e856a4743fd7ebe16324805b0", - "0xa60e2d31bc48e0c0579db15516718a03b73f5138f15037491f4dae336c904e312eda82d50862f4debd1622bb0e56d866", - "0x979fc8b987b5cef7d4f4b58b53a2c278bd25a5c0ea6f41c715142ea5ff224c707de38451b0ad3aa5e749aa219256650a", - "0xb2a75bff18e1a6b9cf2a4079572e41205741979f57e7631654a3c0fcec57c876c6df44733c9da3d863db8dff392b44a3", - "0xb7a0f0e811222c91e3df98ff7f286b750bc3b20d2083966d713a84a2281744199e664879401e77470d44e5a90f3e5181", - "0x82b74ba21c9d147fbc338730e8f1f8a6e7fc847c3110944eb17a48bea5e06eecded84595d485506d15a3e675fd0e5e62", - "0xa7f44eef817d5556f0d1abcf420301217d23c69dd2988f44d91ea1f1a16c322263cbacd0f190b9ba22b0f141b9267b4f", - "0xaadb68164ede84fc1cb3334b3194d84ba868d5a88e4c9a27519eef4923bc4abf81aab8114449496c073c2a6a0eb24114", - "0xb5378605fabe9a8c12a5dc55ef2b1de7f51aedb61960735c08767a565793cea1922a603a6983dc25f7cea738d0f7c40d", - "0xa97a4a5cd8d51302e5e670aee78fe6b5723f6cc892902bbb4f131e82ca1dfd5de820731e7e3367fb0c4c1922a02196e3", - "0x8bdfeb15c29244d4a28896f2b2cb211243cd6a1984a3f5e3b0ebe5341c419beeab3304b390a009ffb47588018034b0ea", - "0xa9af3022727f2aa2fca3b096968e97edad3f08edcbd0dbca107b892ae8f746a9c0485e0d6eb5f267999b23a845923ed0", - "0x8e7594034feef412f055590fbb15b6322dc4c6ab7a4baef4685bd13d71a83f7d682b5781bdfa0d1c659489ce9c2b8000", - "0x84977ca6c865ebee021c58106c1a4ad0c745949ecc5332948002fd09bd9b890524878d0c29da96fd11207621136421fe", - "0x8687551a79158e56b2375a271136756313122132a6670fa51f99a1b5c229ed8eea1655a734abae13228b3ebfd2a825dd", - "0xa0227d6708979d99edfc10f7d9d3719fd3fc68b0d815a7185b60307e4c9146ad2f9be2b8b4f242e320d4288ceeb9504c", - "0x89f75583a16735f9dd8b7782a130437805b34280ccea8dac6ecaee4b83fe96947e7b53598b06fecfffdf57ffc12cc445", - "0xa0056c3353227f6dd9cfc8e3399aa5a8f1d71edf25d3d64c982910f50786b1e395c508d3e3727ac360e3e040c64b5298", - "0xb070e61a6d813626144b312ded1788a6d0c7cec650a762b2f8df6e4743941dd82a2511cd956a3f141fc81e15f4e092da", - "0xb4e6db232e028a1f989bb5fc13416711f42d389f63564d60851f009dcffac01acfd54efa307aa6d4c0f932892d4e62b0", - "0x89b5991a67db90024ddd844e5e1a03ef9b943ad54194ae0a97df775dde1addf31561874f4e40fbc37a896630f3bbda58", - "0xad0e8442cb8c77d891df49cdb9efcf2b0d15ac93ec9be1ad5c3b3cca1f4647b675e79c075335c1f681d56f14dc250d76", - "0xb5d55a6ae65bb34dd8306806cb49b5ccb1c83a282ee47085cf26c4e648e19a52d9c422f65c1cd7e03ca63e926c5e92ea", - "0xb749501347e5ec07e13a79f0cb112f1b6534393458b3678a77f02ca89dca973fa7b30e55f0b25d8b92b97f6cb0120056", - "0x94144b4a3ffc5eec6ba35ce9c245c148b39372d19a928e236a60e27d7bc227d18a8cac9983851071935d8ffb64b3a34f", - "0x92bb4f9f85bc8c028a3391306603151c6896673135f8a7aefedd27acb322c04ef5dac982fc47b455d6740023e0dd3ea3", - "0xb9633a4a101461a782fc2aa092e9dbe4e2ad00987578f18cd7cf0021a909951d60fe79654eb7897806795f93c8ff4d1c", - "0x809f0196753024821b48a016eca5dbb449a7c55750f25981bb7a4b4c0e0846c09b8f6128137905055fc43a3f0deb4a74", - "0xa27dc9cdd1e78737a443570194a03d89285576d3d7f3a3cf15cc55b3013e42635d4723e2e8fe1d0b274428604b630db9", - "0x861f60f0462e04cd84924c36a28163def63e777318d00884ab8cb64c8df1df0bce5900342163edb60449296484a6c5bf", - "0xb7bc23fb4e14af4c4704a944253e760adefeca8caee0882b6bbd572c84434042236f39ae07a8f21a560f486b15d82819", - "0xb9a6eb492d6dd448654214bd01d6dc5ff12067a11537ab82023fc16167507ee25eed2c91693912f4155d1c07ed9650b3", - "0x97678af29c68f9a5e213bf0fb85c265303714482cfc4c2c00b4a1e8a76ed08834ee6af52357b143a1ca590fb0265ea5a", - "0x8a15b499e9eca5b6cac3070b5409e8296778222018ad8b53a5d1f6b70ad9bb10c68a015d105c941ed657bf3499299e33", - "0xb487fefede2e8091f2c7bfe85770db2edff1db83d4effe7f7d87bff5ab1ace35e9b823a71adfec6737fede8d67b3c467", - "0x8b51b916402aa2c437fce3bcad6dad3be8301a1a7eab9d163085b322ffb6c62abf28637636fe6114573950117fc92898", - "0xb06a2106d031a45a494adec0881cb2f82275dff9dcdd2bc16807e76f3bec28a6734edd3d54f0be8199799a78cd6228ad", - "0xaf0a185391bbe2315eb97feac98ad6dd2e5d931d012c621abd6e404a31cc188b286fef14871762190acf086482b2b5e2", - "0x8e78ee8206506dd06eb7729e32fceda3bebd8924a64e4d8621c72e36758fda3d0001af42443851d6c0aea58562870b43", - "0xa1ba52a569f0461aaf90b49b92be976c0e73ec4a2c884752ee52ffb62dd137770c985123d405dfb5de70692db454b54a", - "0x8d51b692fa1543c51f6b62b9acb8625ed94b746ef96c944ca02859a4133a5629da2e2ce84e111a7af8d9a5b836401c64", - "0xa7a20d45044cf6492e0531d0b8b26ffbae6232fa05a96ed7f06bdb64c2b0f5ca7ec59d5477038096a02579e633c7a3ff", - "0x84df867b98c53c1fcd4620fef133ee18849c78d3809d6aca0fb6f50ff993a053a455993f216c42ab6090fa5356b8d564", - "0xa7227c439f14c48e2577d5713c97a5205feb69acb0b449152842e278fa71e8046adfab468089c8b2288af1fc51fa945b", - "0x855189b3a105670779997690876dfaa512b4a25a24931a912c2f0f1936971d2882fb4d9f0b3d9daba77eaf660e9d05d5", - "0xb5696bd6706de51c502f40385f87f43040a5abf99df705d6aac74d88c913b8ecf7a99a63d7a37d9bdf3a941b9e432ff5", - "0xab997beb0d6df9c98d5b49864ef0b41a2a2f407e1687dfd6089959757ba30ed02228940b0e841afe6911990c74d536c4", - "0xb36b65f85546ebfdbe98823d5555144f96b4ab39279facd19c0de3b8919f105ba0315a0784dce4344b1bc62d8bb4a5a3", - "0xb8371f0e4450788720ac5e0f6cd3ecc5413d33895083b2c168d961ec2b5c3de411a4cc0712481cbe8df8c2fa1a7af006", - "0x98325d8026b810a8b7a114171ae59a57e8bbc9848e7c3df992efc523621729fd8c9f52114ce01d7730541a1ada6f1df1", - "0x8d0e76dbd37806259486cd9a31bc8b2306c2b95452dc395546a1042d1d17863ef7a74c636b782e214d3aa0e8d717f94a", - "0xa4e15ead76da0214d702c859fb4a8accdcdad75ed08b865842bd203391ec4cba2dcc916455e685f662923b96ee0c023f", - "0x8618190972086ebb0c4c1b4a6c94421a13f378bc961cc8267a301de7390c5e73c3333864b3b7696d81148f9d4843fd02", - "0x85369d6cc7342e1aa15b59141517d8db8baaaeb7ab9670f3ba3905353948d575923d283b7e5a05b13a30e7baf1208a86", - "0x87c51ef42233c24a6da901f28c9a075d9ba3c625687c387ad6757b72ca6b5a8885e6902a3082da7281611728b1e45f26", - "0xaa6348a4f71927a3106ad0ea8b02fc8d8c65531e4ab0bd0a17243e66f35afe252e40ab8eef9f13ae55a72566ffdaff5c", - "0x96a3bc976e9d03765cc3fee275fa05b4a84c94fed6b767e23ca689394501e96f56f7a97cffddc579a6abff632bf153be", - "0x97dbf96c6176379fdb2b888be4e757b2bca54e74124bd068d3fa1dbd82a011bbeb75079da38e0cd22a761fe208ecad9b", - "0xb70cf0a1d14089a4129ec4e295313863a59da8c7e26bf74cc0e704ed7f0ee4d7760090d0ddf7728180f1bf2c5ac64955", - "0x882d664714cc0ffe53cbc9bef21f23f3649824f423c4dbad1f893d22c4687ab29583688699efc4d5101aa08b0c3e267a", - "0x80ecb7cc963e677ccaddbe3320831dd6ee41209acf4ed41b16dc4817121a3d86a1aac9c4db3d8c08a55d28257088af32", - "0xa25ba667d832b145f9ce18c3f9b1bd00737aa36db020e1b99752c8ef7d27c6c448982bd8d352e1b6df266b8d8358a8d5", - "0x83734841c13dee12759d40bdd209b277e743b0d08cc0dd1e0b7afd2d65bfa640400eefcf6be4a52e463e5b3d885eeac6", - "0x848d16505b04804afc773aebabb51b36fd8aacfbb0e09b36c0d5d57df3c0a3b92f33e7d5ad0a7006ec46ebb91df42b8c", - "0x909a8d793f599e33bb9f1dc4792a507a97169c87cd5c087310bc05f30afcd247470b4b56dec59894c0fb1d48d39bb54e", - "0x8e558a8559df84a1ba8b244ece667f858095c50bb33a5381e60fcc6ba586b69693566d8819b4246a27287f16846c1dfa", - "0x84d6b69729f5aaa000cd710c2352087592cfbdf20d5e1166977e195818e593fa1a50d1e04566be23163a2523dc1612f1", - "0x9536d262b7a42125d89f4f32b407d737ba8d9242acfc99d965913ab3e043dcac9f7072a43708553562cac4cba841df30", - "0x9598548923ca119d6a15fd10861596601dd1dedbcccca97bb208cdc1153cf82991ea8cc17686fbaa867921065265970c", - "0xb87f2d4af6d026e4d2836bc3d390a4a18e98a6e386282ce96744603bab74974272e97ac2da281afa21885e2cbb3a8001", - "0x991ece62bf07d1a348dd22191868372904b9f8cf065ae7aa4e44fd24a53faf6d851842e35fb472895963aa1992894918", - "0xa8c53dea4c665b30e51d22ca6bc1bc78aaf172b0a48e64a1d4b93439b053877ec26cb5221c55efd64fa841bbf7d5aff4", - "0x93487ec939ed8e740f15335b58617c3f917f72d07b7a369befd479ae2554d04deb240d4a14394b26192efae4d2f4f35d", - "0xa44793ab4035443f8f2968a40e043b4555960193ffa3358d22112093aadfe2c136587e4139ffd46d91ed4107f61ea5e0", - "0xb13fe033da5f0d227c75927d3dacb06dbaf3e1322f9d5c7c009de75cdcba5e308232838785ab69a70f0bedea755e003f", - "0x970a29b075faccd0700fe60d1f726bdebf82d2cc8252f4a84543ebd3b16f91be42a75c9719a39c4096139f0f31393d58", - "0xa4c3eb1f7160f8216fc176fb244df53008ff32f2892363d85254002e66e2de21ccfe1f3b1047589abee50f29b9d507e3", - "0x8c552885eab04ba40922a8f0c3c38c96089c95ff1405258d3f1efe8d179e39e1295cbf67677894c607ae986e4e6b1fb0", - "0xb3671746fa7f848c4e2ae6946894defadd815230b906b419143523cc0597bc1d6c0a4c1e09d49b66b4a2c11cde3a4de3", - "0x937a249a95813a5e2ef428e355efd202e15a37d73e56cfb7e57ea9f943f2ce5ca8026f2f1fd25bf164ba89d07077d858", - "0x83646bdf6053a04aa9e2f112499769e5bd5d0d10f2e13db3ca89bd45c0b3b7a2d752b7d137fb3909f9c62b78166c9339", - "0xb4eac4b91e763666696811b7ed45e97fd78310377ebea1674b58a2250973f80492ac35110ed1240cd9bb2d17493d708c", - "0x82db43a99bc6573e9d92a3fd6635dbbb249ac66ba53099c3c0c8c8080b121dd8243cd5c6e36ba0a4d2525bae57f5c89c", - "0xa64d6a264a681b49d134c655d5fc7756127f1ee7c93d328820f32bca68869f53115c0d27fef35fe71f7bc4fdaed97348", - "0x8739b7a9e2b4bc1831e7f04517771bc7cde683a5e74e052542517f8375a2f64e53e0d5ac925ef722327e7bb195b4d1d9", - "0x8f337cdd29918a2493515ebb5cf702bbe8ecb23b53c6d18920cc22f519e276ca9b991d3313e2d38ae17ae8bdfa4f8b7e", - "0xb0edeab9850e193a61f138ef2739fc42ceec98f25e7e8403bfd5fa34a7bc956b9d0898250d18a69fa4625a9b3d6129da", - "0xa9920f26fe0a6d51044e623665d998745c9eca5bce12051198b88a77d728c8238f97d4196f26e43b24f8841500b998d0", - "0x86e655d61502b979eeeeb6f9a7e1d0074f936451d0a1b0d2fa4fb3225b439a3770767b649256fe481361f481a8dbc276", - "0x84d3b32fa62096831cc3bf013488a9f3f481dfe293ae209ed19585a03f7db8d961a7a9dd0db82bd7f62d612707575d9c", - "0x81c827826ec9346995ffccf62a241e3b2d32f7357acd1b1f8f7a7dbc97022d3eb51b8a1230e23ce0b401d2e535e8cd78", - "0x94a1e40c151191c5b055b21e86f32e69cbc751dcbdf759a48580951834b96a1eed75914c0d19a38aefd21fb6c8d43d0c", - "0xab890222b44bc21b71f7c75e15b6c6e16bb03371acce4f8d4353ff3b8fcd42a14026589c5ed19555a3e15e4d18bfc3a3", - "0xaccb0be851e93c6c8cc64724cdb86887eea284194b10e7a43c90528ed97e9ec71ca69c6fac13899530593756dd49eab2", - "0xb630220aa9e1829c233331413ee28c5efe94ea8ea08d0c6bfd781955078b43a4f92915257187d8526873e6c919c6a1de", - "0xadd389a4d358c585f1274b73f6c3c45b58ef8df11f9d11221f620e241bf3579fba07427b288c0c682885a700cc1fa28d", - "0xa9fe6ca8bf2961a3386e8b8dcecc29c0567b5c0b3bcf3b0f9169f88e372b80151af883871fc5229815f94f43a6f5b2b0", - "0xad839ae003b92b37ea431fa35998b46a0afc3f9c0dd54c3b3bf7a262467b13ff3c323ada1c1ae02ac7716528bdf39e3e", - "0x9356d3fd0edcbbb65713c0f2a214394f831b26f792124b08c5f26e7f734b8711a87b7c4623408da6a091c9aef1f6af3c", - "0x896b25b083c35ac67f0af3784a6a82435b0e27433d4d74cd6d1eafe11e6827827799490fb1c77c11de25f0d75f14e047", - "0x8bfa019391c9627e8e5f05c213db625f0f1e51ec68816455f876c7e55b8f17a4f13e5aae9e3fb9e1cf920b1402ee2b40", - "0x8ba3a6faa6a860a8f3ce1e884aa8769ceded86380a86520ab177ab83043d380a4f535fe13884346c5e51bee68da6ab41", - "0xa8292d0844084e4e3bb7af92b1989f841a46640288c5b220fecfad063ee94e86e13d3d08038ec2ac82f41c96a3bfe14d", - "0x8229bb030b2fc566e11fd33c7eab7a1bb7b49fed872ea1f815004f7398cb03b85ea14e310ec19e1f23e0bdaf60f8f76c", - "0x8cfbf869ade3ec551562ff7f63c2745cc3a1f4d4dc853a0cd42dd5f6fe54228f86195ea8fe217643b32e9f513f34a545", - "0xac52a3c8d3270ddfe1b5630159da9290a5ccf9ccbdef43b58fc0a191a6c03b8a5974cf6e2bbc7bd98d4a40a3581482d7", - "0xab13decb9e2669e33a7049b8eca3ca327c40dea15ad6e0e7fa63ed506db1d258bc36ac88b35f65cae0984e937eb6575d", - "0xb5e748eb1a7a1e274ff0cc56311c198f2c076fe4b7e73e5f80396fe85358549df906584e6bb2c8195b3e2be7736850a5", - "0xb5cb911325d8f963c41f691a60c37831c7d3bbd92736efa33d1f77a22b3fde7f283127256c2f47e197571e6fe0b46149", - "0x8a01dc6ed1b55f26427a014faa347130738b191a06b800e32042a46c13f60b49534520214359d68eb2e170c31e2b8672", - "0xa72fa874866e19b2efb8e069328362bf7921ec375e3bcd6b1619384c3f7ee980f6cf686f3544e9374ff54b4d17a1629c", - "0x8db21092f7c5f110fba63650b119e82f4b42a997095d65f08f8237b02dd66fdf959f788df2c35124db1dbd330a235671", - "0x8c65d50433d9954fe28a09fa7ba91a70a590fe7ba6b3060f5e4be0f6cef860b9897fa935fb4ebc42133524eb071dd169", - "0xb4614058e8fa21138fc5e4592623e78b8982ed72aa35ee4391b164f00c68d277fa9f9eba2eeefc890b4e86eba5124591", - "0xab2ad3a1bce2fbd55ca6b7c23786171fe1440a97d99d6df4d80d07dd56ac2d7203c294b32fc9e10a6c259381a73f24a1", - "0x812ae3315fdc18774a8da3713a4679e8ed10b9405edc548c00cacbe25a587d32040566676f135e4723c5dc25df5a22e9", - "0xa464b75f95d01e5655b54730334f443c8ff27c3cb79ec7af4b2f9da3c2039c609908cd128572e1fd0552eb597e8cef8d", - "0xa0db3172e93ca5138fe419e1c49a1925140999f6eff7c593e5681951ee0ec1c7e454c851782cbd2b8c9bc90d466e90e0", - "0x806db23ba7d00b87d544eed926b3443f5f9c60da6b41b1c489fba8f73593b6e3b46ebfcab671ee009396cd77d5e68aa1", - "0x8bfdf2c0044cc80260994e1c0374588b6653947b178e8b312be5c2a05e05767e98ea15077278506aee7df4fee1aaf89e", - "0x827f6558c16841b5592ff089c9c31e31eb03097623524394813a2e4093ad2d3f8f845504e2af92195aaa8a1679d8d692", - "0x925c4f8eab2531135cd71a4ec88e7035b5eea34ba9d799c5898856080256b4a15ed1a746e002552e2a86c9c157e22e83", - "0xa9f9a368f0e0b24d00a35b325964c85b69533013f9c2cfad9708be5fb87ff455210f8cb8d2ce3ba58ca3f27495552899", - "0x8ac0d3bebc1cae534024187e7c71f8927ba8fcc6a1926cb61c2b6c8f26bb7831019e635a376146c29872a506784a4aaa", - "0x97c577be2cbbfdb37ad754fae9df2ada5fc5889869efc7e18a13f8e502fbf3f4067a509efbd46fd990ab47ce9a70f5a8", - "0x935e7d82bca19f16614aa43b4a3474e4d20d064e4bfdf1cea2909e5c9ab72cfe3e54dc50030e41ee84f3588cebc524e9", - "0x941aafc08f7c0d94cebfbb1f0aad5202c02e6e37f2c12614f57e727efa275f3926348f567107ee6d8914dd71e6060271", - "0xaf0fbc1ba05b4b5b63399686df3619968be5d40073de0313cbf5f913d3d4b518d4c249cdd2176468ccaa36040a484f58", - "0xa0c414f23f46ca6d69ce74c6f8a00c036cb0edd098af0c1a7d39c802b52cfb2d5dbdf93fb0295453d4646e2af7954d45", - "0x909cf39e11b3875bb63b39687ae1b5d1f5a15445e39bf164a0b14691b4ddb39a8e4363f584ef42213616abc4785b5d66", - "0xa92bac085d1194fbd1c88299f07a061d0bdd3f980b663e81e6254dbb288bf11478c0ee880e28e01560f12c5ccb3c0103", - "0x841705cd5cd76b943e2b7c5e845b9dd3c8defe8ef67e93078d6d5e67ade33ad4b0fd413bc196f93b0a4073c855cd97d4", - "0x8e7eb8364f384a9161e81d3f1d52ceca9b65536ae49cc35b48c3e2236322ba4ae9973e0840802d9fa4f4d82ea833544f", - "0xaed3ab927548bc8bec31467ba80689c71a168e34f50dcb6892f19a33a099f5aa6b3f9cb79f5c0699e837b9a8c7f27efe", - "0xb8fbf7696210a36e20edabd77839f4dfdf50d6d015cdf81d587f90284a9bcef7d2a1ff520728d7cc69a4843d6c20dedd", - "0xa9d533769ce6830211c884ae50a82a7bf259b44ac71f9fb11f0296fdb3981e6b4c1753fe744647b247ebc433a5a61436", - "0x8b4bdf90d33360b7f428c71cde0a49fb733badba8c726876945f58c620ce7768ae0e98fc8c31fa59d8955a4823336bb1", - "0x808d42238e440e6571c59e52a35ae32547d502dc24fd1759d8ea70a7231a95859baf30b490a4ba55fa2f3aaa11204597", - "0x85594701f1d2fee6dc1956bc44c7b31db93bdeec2f3a7d622c1a08b26994760773e3d57521a44cfd7e407ac3fd430429", - "0xa66de045ce7173043a6825e9dc440ac957e2efb6df0a337f4f8003eb0c719d873a52e6eba3cb0d69d977ca37d9187674", - "0x87a1c6a1fdff993fa51efa5c3ba034c079c0928a7d599b906336af7c2dcab9721ceaf3108c646490af9dff9a754f54b3", - "0x926424223e462ceb75aed7c22ade8a7911a903b7e5dd4bc49746ddce8657f4616325cd12667d4393ac52cdd866396d0e", - "0xb5dc96106593b42b30f06f0b0a1e0c1aafc70432e31807252d3674f0b1ea5e58eac8424879d655c9488d85a879a3e572", - "0x997ca0987735cc716507cb0124b1d266d218b40c9d8e0ecbf26a1d65719c82a637ce7e8be4b4815d307df717bde7c72a", - "0x92994d3f57a569b7760324bb5ae4e8e14e1633d175dab06aa57b8e391540e05f662fdc08b8830f489a063f59b689a688", - "0xa8087fcc6aa4642cb998bea11facfe87eb33b90a9aa428ab86a4124ad032fc7d2e57795311a54ec9f55cc120ebe42df1", - "0xa9bd7d1de6c0706052ca0b362e2e70e8c8f70f1f026ea189b4f87a08ce810297ebfe781cc8004430776c54c1a05ae90c", - "0x856d33282e8a8e33a3d237fb0a0cbabaf77ba9edf2fa35a831fdafcadf620561846aa6cbb6bdc5e681118e1245834165", - "0x9524a7aa8e97a31a6958439c5f3339b19370f03e86b89b1d02d87e4887309dbbe9a3a8d2befd3b7ed5143c8da7e0a8ad", - "0x824fdf433e090f8acbd258ac7429b21f36f9f3b337c6d0b71d1416a5c88a767883e255b2888b7c906dd2e9560c4af24c", - "0x88c7fee662ca7844f42ed5527996b35723abffd0d22d4ca203b9452c639a5066031207a5ae763dbc0865b3299d19b1ec", - "0x919dca5c5595082c221d5ab3a5bc230f45da7f6dec4eb389371e142c1b9c6a2c919074842479c2844b72c0d806170c0c", - "0xb939be8175715e55a684578d8be3ceff3087f60fa875fff48e52a6e6e9979c955efef8ff67cfa2b79499ea23778e33b0", - "0x873b6db725e7397d11bc9bed9ac4468e36619135be686790a79bc6ed4249058f1387c9a802ea86499f692cf635851066", - "0xaeae06db3ec47e9e5647323fa02fac44e06e59b885ad8506bf71b184ab3895510c82f78b6b22a5d978e8218e7f761e9f", - "0xb99c0a8359c72ab88448bae45d4bf98797a26bca48b0d4460cd6cf65a4e8c3dd823970ac3eb774ae5d0cea4e7fadf33e", - "0x8f10c8ec41cdfb986a1647463076a533e6b0eec08520c1562401b36bb063ac972aa6b28a0b6ce717254e35940b900e3c", - "0xa106d9be199636d7add43b942290269351578500d8245d4aae4c083954e4f27f64740a3138a66230391f2d0e6043a8de", - "0xa469997908244578e8909ff57cffc070f1dbd86f0098df3cfeb46b7a085cfecc93dc69ee7cad90ff1dc5a34d50fe580c", - "0xa4ef087bea9c20eb0afc0ee4caba7a9d29dfa872137828c721391273e402fb6714afc80c40e98bbd8276d3836bffa080", - "0xb07a013f73cd5b98dae0d0f9c1c0f35bff8a9f019975c4e1499e9bee736ca6fcd504f9bc32df1655ff333062382cff04", - "0xb0a77188673e87cc83348c4cc5db1eecf6b5184e236220c8eeed7585e4b928db849944a76ec60ef7708ef6dac02d5592", - "0xb1284b37e59b529f0084c0dacf0af6c0b91fc0f387bf649a8c74819debf606f7b07fc3e572500016fb145ec2b24e9f17", - "0x97b20b5b4d6b9129da185adfbf0d3d0b0faeba5b9715f10299e48ea0521709a8296a9264ce77c275a59c012b50b6519a", - "0xb9d37e946fae5e4d65c1fbfacc8a62e445a1c9d0f882e60cca649125af303b3b23af53c81d7bac544fb7fcfc7a314665", - "0x8e5acaac379f4bb0127efbef26180f91ff60e4c525bc9b798fc50dfaf4fe8a5aa84f18f3d3cfb8baead7d1e0499af753", - "0xb0c0b8ab1235bf1cda43d4152e71efc1a06c548edb964eb4afceb201c8af24240bf8ab5cae30a08604e77432b0a5faf0", - "0x8cc28d75d5c8d062d649cbc218e31c4d327e067e6dbd737ec0a35c91db44fbbd0d40ec424f5ed79814add16947417572", - "0x95ae6219e9fd47efaa9cb088753df06bc101405ba50a179d7c9f7c85679e182d3033f35b00dbba71fdcd186cd775c52e", - "0xb5d28fa09f186ebc5aa37453c9b4d9474a7997b8ae92748ecb940c14868792292ac7d10ade01e2f8069242b308cf97e5", - "0x8c922a0faa14cc6b7221f302df3342f38fc8521ec6c653f2587890192732c6da289777a6cd310747ea7b7d104af95995", - "0xb9ad5f660b65230de54de535d4c0fcae5bc6b59db21dea5500fdc12eea4470fb8ea003690fdd16d052523418d5e01e8c", - "0xa39a9dd41a0ff78c82979483731f1cd68d3921c3e9965869662c22e02dde3877802e180ba93f06e7346f96d9fa9261d2", - "0x8b32875977ec372c583b24234c27ed73aef00cdff61eb3c3776e073afbdeade548de9497c32ec6d703ff8ad0a5cb7fe4", - "0x9644cbe755a5642fe9d26cfecf170d3164f1848c2c2e271d5b6574a01755f3980b3fc870b98cf8528fef6ecef4210c16", - "0x81ea9d1fdd9dd66d60f40ce0712764b99da9448ae0b300f8324e1c52f154e472a086dda840cb2e0b9813dc8ce8afd4b5", - "0x906aaa4a7a7cdf01909c5cfbc7ded2abc4b869213cbf7c922d4171a4f2e637e56f17020b852ad339d83b8ac92f111666", - "0x939b5f11acbdeff998f2a080393033c9b9d8d5c70912ea651c53815c572d36ee822a98d6dfffb2e339f29201264f2cf4", - "0xaba4898bf1ccea9b9e2df1ff19001e05891581659c1cbbde7ee76c349c7fc7857261d9785823c9463a8aea3f40e86b38", - "0x83ca1a56b8a0be4820bdb5a9346357c68f9772e43f0b887729a50d2eb2a326bbcede676c8bf2e51d7c89bbd8fdb778a6", - "0x94e86e9fe6addfe2c3ee3a547267ed921f4230d877a85bb4442c2d9350c2fa9a9c54e6fe662de82d1a2407e4ab1691c2", - "0xa0cc3bdef671a59d77c6984338b023fa2b431b32e9ed2abe80484d73edc6540979d6f10812ecc06d4d0c5d4eaca7183c", - "0xb5343413c1b5776b55ea3c7cdd1f3af1f6bd802ea95effe3f2b91a523817719d2ecc3f8d5f3cc2623ace7e35f99ca967", - "0x92085d1ed0ed28d8cabe3e7ff1905ed52c7ceb1eac5503760c52fb5ee3a726aba7c90b483c032acc3f166b083d7ec370", - "0x8ec679520455275cd957fca8122724d287db5df7d29f1702a322879b127bff215e5b71d9c191901465d19c86c8d8d404", - "0xb65eb2c63d8a30332eb24ee8a0c70156fc89325ebbb38bacac7cf3f8636ad8a472d81ccca80423772abc00192d886d8a", - "0xa9fe1c060b974bee4d590f2873b28635b61bfcf614e61ff88b1be3eee4320f4874e21e8d666d8ac8c9aba672efc6ecae", - "0xb3fe2a9a389c006a831dea7e777062df84b5c2803f9574d7fbe10b7e1c125817986af8b6454d6be9d931a5ac94cfe963", - "0x95418ad13b734b6f0d33822d9912c4c49b558f68d08c1b34a0127fcfa666bcae8e6fda8832d2c75bb9170794a20e4d7c", - "0xa9a7df761e7f18b79494bf429572140c8c6e9d456c4d4e336184f3f51525a65eb9582bea1e601bdb6ef8150b7ca736a5", - "0xa0de03b1e75edf7998c8c1ac69b4a1544a6fa675a1941950297917366682e5644a4bda9cdeedfaf9473d7fccd9080b0c", - "0xa61838af8d95c95edf32663a68f007d95167bf6e41b0c784a30b22d8300cfdd5703bd6d16e86396638f6db6ae7e42a85", - "0x8866d62084d905c145ff2d41025299d8b702ac1814a7dec4e277412c161bc9a62fed735536789cb43c88693c6b423882", - "0x91da22c378c81497fe363e7f695c0268443abee50f8a6625b8a41e865638a643f07b157ee566de09ba09846934b4e2d7", - "0x941d21dd57c9496aa68f0c0c05507405fdd413acb59bc668ce7e92e1936c68ec4b065c3c30123319884149e88228f0b2", - "0xa77af9b094bc26966ddf2bf9e1520c898194a5ccb694915950dadc204facbe3066d3d89f50972642d76b14884cfbaa21", - "0x8e76162932346869f4618bde744647f7ab52ab498ad654bdf2a4feeb986ac6e51370841e5acbb589e38b6e7142bb3049", - "0xb60979ace17d6937ece72e4f015da4657a443dd01cebc7143ef11c09e42d4aa8855999a65a79e2ea0067f31c9fc2ab0f", - "0xb3e2ffdd5ee6fd110b982fd4fad4b93d0fca65478f986d086eeccb0804960bfaa1919afa743c2239973ea65091fe57d2", - "0x8ce0ce05e7d7160d44574011da687454dbd3c8b8290aa671731b066e2c82f8cf2d63cb8e932d78c6122ec610e44660e6", - "0xab005dd8d297045c39e2f72fb1c48edb501ccf3575d3d04b9817b3afee3f0bb0f3f53f64bda37d1d9cde545aae999bae", - "0x95bd7edb4c4cd60e3cb8a72558845a3cce6bb7032ccdf33d5a49ebb6ddf203bc3c79e7b7e550735d2d75b04c8b2441e8", - "0x889953ee256206284094e4735dbbb17975bafc7c3cb94c9fbfee4c3e653857bfd49e818f64a47567f721b98411a3b454", - "0xb188423e707640ab0e75a061e0b62830cde8afab8e1ad3dae30db69ffae4e2fc005bababbdcbd7213b918ed4f70e0c14", - "0xa97e0fafe011abd70d4f99a0b36638b3d6e7354284588f17a88970ed48f348f88392779e9a038c6cbc9208d998485072", - "0x87db11014a91cb9b63e8dfaa82cdebca98272d89eb445ee1e3ff9dbaf2b3fad1a03b888cffc128e4fe208ed0dddece0f", - "0xaad2e40364edd905d66ea4ac9d51f9640d6fda9a54957d26ba233809851529b32c85660fa401dbee3679ec54fa6dd966", - "0x863e99336ca6edf03a5a259e59a2d0f308206e8a2fb320cfc0be06057366df8e0f94b33a28f574092736b3c5ada84270", - "0xb34bcc56a057589f34939a1adc51de4ff6a9f4fee9c7fa9aa131e28d0cf0759a0c871b640162acdfbf91f3f1b59a3703", - "0x935dd28f2896092995c5eff1618e5b6efe7a40178888d7826da9b0503c2d6e68a28e7fac1a334e166d0205f0695ef614", - "0xb842cd5f8f5de5ca6c68cb4a5c1d7b451984930eb4cc18fd0934d52fdc9c3d2d451b1c395594d73bc3451432bfba653f", - "0x9014537885ce2debad736bc1926b25fdab9f69b216bf024f589c49dc7e6478c71d595c3647c9f65ff980b14f4bb2283b", - "0x8e827ccca1dd4cd21707140d10703177d722be0bbe5cac578db26f1ef8ad2909103af3c601a53795435b27bf95d0c9ed", - "0x8a0b8ad4d466c09d4f1e9167410dbe2edc6e0e6229d4b3036d30f85eb6a333a18b1c968f6ca6d6889bb08fecde017ef4", - "0x9241ee66c0191b06266332dc9161dede384c4bb4e116dbd0890f3c3790ec5566da4568243665c4725b718ac0f6b5c179", - "0xaeb4d5fad81d2b505d47958a08262b6f1b1de9373c2c9ba6362594194dea3e002ab03b8cbb43f867be83065d3d370f19", - "0x8781bc83bb73f7760628629fe19e4714b494dbed444c4e4e4729b7f6a8d12ee347841a199888794c2234f51fa26fc2b9", - "0xb58864f0acd1c2afa29367e637cbde1968d18589245d9936c9a489c6c495f54f0113ecdcbe4680ac085dd3c397c4d0c3", - "0x94a24284afaeead61e70f3e30f87248d76e9726759445ca18cdb9360586c60cc9f0ec1c397f9675083e0b56459784e2e", - "0xaed358853f2b54dcbddf865e1816c2e89be12e940e1abfa661e2ee63ffc24a8c8096be2072fa83556482c0d89e975124", - "0xb95374e6b4fc0765708e370bc881e271abf2e35c08b056a03b847e089831ef4fe3124b9c5849d9c276eb2e35b3daf264", - "0xb834cdbcfb24c8f84bfa4c552e7fadc0028a140952fd69ed13a516e1314a4cd35d4b954a77d51a1b93e1f5d657d0315d", - "0x8fb6d09d23bfa90e7443753d45a918d91d75d8e12ec7d016c0dfe94e5c592ba6aaf483d2f16108d190822d955ad9cdc3", - "0xaa315cd3c60247a6ad4b04f26c5404c2713b95972843e4b87b5a36a89f201667d70f0adf20757ebe1de1b29ae27dda50", - "0xa116862dca409db8beff5b1ccd6301cdd0c92ca29a3d6d20eb8b87f25965f42699ca66974dd1a355200157476b998f3b", - "0xb4c2f5fe173c4dc8311b60d04a65ce1be87f070ac42e13cd19c6559a2931c6ee104859cc2520edebbc66a13dc7d30693", - "0x8d4a02bf99b2260c334e7d81775c5cf582b00b0c982ce7745e5a90624919028278f5e9b098573bad5515ce7fa92a80c8", - "0x8543493bf564ce6d97bd23be9bff1aba08bd5821ca834f311a26c9139c92a48f0c2d9dfe645afa95fec07d675d1fd53b", - "0x9344239d13fde08f98cb48f1f87d34cf6abe8faecd0b682955382a975e6eed64e863fa19043290c0736261622e00045c", - "0xaa49d0518f343005ca72b9e6c7dcaa97225ce6bb8b908ebbe7b1a22884ff8bfb090890364e325a0d414ad180b8f161d1", - "0x907d7fd3e009355ab326847c4a2431f688627faa698c13c03ffdd476ecf988678407f029b8543a475dcb3dafdf2e7a9c", - "0x845f1f10c6c5dad2adc7935f5cd2e2b32f169a99091d4f1b05babe7317b9b1cdce29b5e62f947dc621b9acbfe517a258", - "0x8f3be8e3b380ea6cdf9e9c237f5e88fd5a357e5ded80ea1fc2019810814de82501273b4da38916881125b6fa0cfd4459", - "0xb9c7f487c089bf1d20c822e579628db91ed9c82d6ca652983aa16d98b4270c4da19757f216a71b9c13ddee3e6e43705f", - "0x8ba2d8c88ad2b872db104ea8ddbb006ec2f3749fd0e19298a804bb3a5d94de19285cc7fb19fee58a66f7851d1a66c39f", - "0x9375ecd3ed16786fe161af5d5c908f56eeb467a144d3bbddfc767e90065b7c94fc53431adebecba2b6c9b5821184d36e", - "0xa49e069bfadb1e2e8bff6a4286872e2a9765d62f0eaa4fcb0e5af4bbbed8be3510fb19849125a40a8a81d1e33e81c3eb", - "0x9522cc66757b386aa6b88619525c8ce47a5c346d590bb3647d12f991e6c65c3ab3c0cfc28f0726b6756c892eae1672be", - "0xa9a0f1f51ff877406fa83a807aeb17b92a283879f447b8a2159653db577848cc451cbadd01f70441e351e9ed433c18bc", - "0x8ff7533dcff6be8714df573e33f82cf8e9f2bcaaa43e939c4759d52b754e502717950de4b4252fb904560fc31dce94a4", - "0x959724671e265a28d67c29d95210e97b894b360da55e4cf16e6682e7912491ed8ca14bfaa4dce9c25a25b16af580494f", - "0x92566730c3002f4046c737032487d0833c971e775de59fe02d9835c9858e2e3bc37f157424a69764596c625c482a2219", - "0xa84b47ceff13ed9c3e5e9cdf6739a66d3e7c2bd8a6ba318fefb1a9aecf653bb2981da6733ddb33c4b0a4523acc429d23", - "0xb4ddf571317e44f859386d6140828a42cf94994e2f1dcbcc9777f4eebbfc64fc1e160b49379acc27c4672b8e41835c5d", - "0x8ab95c94072b853d1603fdd0a43b30db617d13c1d1255b99075198e1947bfa5f59aed2b1147548a1b5e986cd9173d15c", - "0x89511f2eab33894fd4b3753d24249f410ff7263052c1fef6166fc63a79816656b0d24c529e45ccce6be28de6e375d916", - "0xa0866160ca63d4f2be1b4ea050dac6b59db554e2ebb4e5b592859d8df339b46fd7cb89aaed0951c3ee540aee982c238a", - "0x8fcc5cbba1b94970f5ff2eb1922322f5b0aa7d918d4b380c9e7abfd57afd8b247c346bff7b87af82efbce3052511cd1b", - "0x99aeb2a5e846b0a2874cca02c66ed40d5569eb65ab2495bc3f964a092e91e1517941f2688e79f8cca49cd3674c4e06dc", - "0xb7a096dc3bad5ca49bee94efd884aa3ff5615cf3825cf95fbe0ce132e35f46581d6482fa82666c7ef5f1643eaee8f1ca", - "0x94393b1da6eaac2ffd186b7725eca582f1ddc8cdd916004657f8a564a7c588175cb443fc6943b39029f5bbe0add3fad8", - "0x884b85fe012ccbcd849cb68c3ad832d83b3ef1c40c3954ffdc97f103b1ed582c801e1a41d9950f6bddc1d11f19d5ec76", - "0xb00061c00131eded8305a7ce76362163deb33596569afb46fe499a7c9d7a0734c084d336b38d168024c2bb42b58e7660", - "0xa439153ac8e6ca037381e3240e7ba08d056c83d7090f16ed538df25901835e09e27de2073646e7d7f3c65056af6e4ce7", - "0x830fc9ca099097d1f38b90e6843dc86f702be9d20bdacc3e52cae659dc41df5b8d2c970effa6f83a5229b0244a86fe22", - "0xb81ea2ffaaff2bb00dd59a9ab825ba5eed4db0d8ac9c8ed1a632ce8f086328a1cddd045fbe1ace289083c1325881b7e7", - "0xb51ea03c58daf2db32c99b9c4789b183365168cb5019c72c4cc91ac30b5fb7311d3db76e6fa41b7cd4a8c81e2f6cdc94", - "0xa4170b2c6d09ca5beb08318730419b6f19215ce6c631c854116f904be3bc30dd85a80c946a8ab054d3e307afaa3f8fbc", - "0x897cc42ff28971ff54d2a55dd6b35cfb8610ac902f3c06e3a5cea0e0a257e870c471236a8e84709211c742a09c5601a6", - "0xa18f2e98d389dace36641621488664ecbb422088ab03b74e67009b8b8acacaaa24fdcf42093935f355207d934adc52a8", - "0x92adcfb678cc2ba19c866f3f2b988fdcb4610567f3ab436cc0cb9acaf5a88414848d71133ebdbec1983e38e6190f1b5f", - "0xa86d43c2ce01b366330d3b36b3ca85f000c3548b8297e48478da1ee7d70d8576d4650cba7852ed125c0d7cb6109aa7f3", - "0x8ed31ceed9445437d7732dce78a762d72ff32a7636bfb3fd7974b7ae15db414d8184a1766915244355deb354fbc5803b", - "0x9268f70032584f416e92225d65af9ea18c466ebc7ae30952d56a4e36fd9ea811dde0a126da9220ba3c596ec54d8a335e", - "0x9433b99ee94f2d3fbdd63b163a2bdf440379334c52308bd24537f7defd807145a062ff255a50d119a7f29f4b85d250e3", - "0x90ce664f5e4628a02278f5cf5060d1a34f123854634b1870906e5723ac9afd044d48289be283b267d45fcbf3f4656aaf", - "0xaaf21c4d59378bb835d42ae5c5e5ab7a3c8c36a59e75997989313197752b79a472d866a23683b329ea69b048b87fa13e", - "0xb83c0589b304cec9ede549fde54f8a7c2a468c6657da8c02169a6351605261202610b2055c639b9ed2d5b8c401fb8f56", - "0x9370f326ea0f170c2c05fe2c5a49189f20aec93b6b18a5572a818cd4c2a6adb359e68975557b349fb54f065d572f4c92", - "0xac3232fa5ce6f03fca238bef1ce902432a90b8afce1c85457a6bee5571c033d4bceefafc863af04d4e85ac72a4d94d51", - "0x80d9ea168ff821b22c30e93e4c7960ce3ad3c1e6deeebedd342a36d01bd942419b187e2f382dbfd8caa34cca08d06a48", - "0xa387a3c61676fb3381eefa2a45d82625635a666e999aba30e3b037ec9e040f414f9e1ad9652abd3bcad63f95d85038db", - "0xa1b229fe32121e0b391b0f6e0180670b9dc89d79f7337de4c77ea7ad0073e9593846f06797c20e923092a08263204416", - "0x92164a9d841a2b828cedf2511213268b698520f8d1285852186644e9a0c97512cafa4bfbe29af892c929ebccd102e998", - "0x82ee2fa56308a67c7db4fd7ef539b5a9f26a1c2cc36da8c3206ba4b08258fbb3cec6fe5cdbd111433fb1ba2a1e275927", - "0x8c77bfe9e191f190a49d46f05600603fa42345592539b82923388d72392404e0b29a493a15e75e8b068dddcd444c2928", - "0x80b927f93ccf79dcf5c5b20bcf5a7d91d7a17bc0401bb7cc9b53a6797feac31026eb114257621f5a64a52876e4474cc1", - "0xb6b68b6501c37804d4833d5a063dd108a46310b1400549074e3cac84acc6d88f73948b7ad48d686de89c1ec043ae8c1a", - "0xab3da00f9bdc13e3f77624f58a3a18fc3728956f84b5b549d62f1033ae4b300538e53896e2d943f160618e05af265117", - "0xb6830e87233b8eace65327fdc764159645b75d2fd4024bf8f313b2dd5f45617d7ecfb4a0b53ccafb5429815a9a1adde6", - "0xb9251cfe32a6dc0440615aadcd98b6b1b46e3f4e44324e8f5142912b597ee3526bea2431e2b0282bb58f71be5b63f65e", - "0xaf8d70711e81cdddfb39e67a1b76643292652584c1ce7ce4feb1641431ad596e75c9120e85f1a341e7a4da920a9cdd94", - "0x98cd4e996594e89495c078bfd52a4586b932c50a449a7c8dfdd16043ca4cda94dafbaa8ad1b44249c99bbcc52152506e", - "0xb9fc6d1c24f48404a4a64fbe3e43342738797905db46e4132aee5f086aaa4c704918ad508aaefa455cfe1b36572e6242", - "0xa365e871d30ba9291cedaba1be7b04e968905d003e9e1af7e3b55c5eb048818ae5b913514fb08b24fb4fbdccbb35d0b8", - "0x93bf99510971ea9af9f1e364f1234c898380677c8e8de9b0dd24432760164e46c787bc9ec42a7ad450500706cf247b2d", - "0xb872f825a5b6e7b9c7a9ddfeded3516f0b1449acc9b4fd29fc6eba162051c17416a31e5be6d3563f424d28e65bab8b8f", - "0xb06b780e5a5e8eb4f4c9dc040f749cf9709c8a4c9ef15e925f442b696e41e5095db0778a6c73bcd329b265f2c6955c8b", - "0x848f1a981f5fc6cd9180cdddb8d032ad32cdfa614fc750d690dbae36cc0cd355cbf1574af9b3ffc8b878f1b2fafb9544", - "0xa03f48cbff3e9e8a3a655578051a5ae37567433093ac500ed0021c6250a51b767afac9bdb194ee1e3eac38a08c0eaf45", - "0xb5be78ce638ff8c4aa84352b536628231d3f7558c5be3bf010b28feac3022e64691fa672f358c8b663904aebe24a54ed", - "0xa9d4da70ff676fa55d1728ba6ab03b471fa38b08854d99e985d88c2d050102d8ccffbe1c90249a5607fa7520b15fe791", - "0x8fe9f7092ffb0b69862c8e972fb1ecf54308c96d41354ed0569638bb0364f1749838d6d32051fff1599112978c6e229c", - "0xae6083e95f37770ecae0df1e010456f165d96cfe9a7278c85c15cffd61034081ce5723e25e2bede719dc9341ec8ed481", - "0xa260891891103089a7afbd9081ea116cfd596fd1015f5b65e10b0961eb37fab7d09c69b7ce4be8bf35e4131848fb3fe4", - "0x8d729fa32f6eb9fd2f6a140bef34e8299a2f3111bffd0fe463aa8622c9d98bfd31a1df3f3e87cd5abc52a595f96b970e", - "0xa30ec6047ae4bc7da4daa7f4c28c93aedb1112cfe240e681d07e1a183782c9ff6783ac077c155af23c69643b712a533f", - "0xac830726544bfe7b5467339e5114c1a75f2a2a8d89453ce86115e6a789387e23551cd64620ead6283dfa4538eb313d86", - "0x8445c135b7a48068d8ed3e011c6d818cfe462b445095e2fbf940301e50ded23f272d799eea47683fc027430ce14613ef", - "0x95785411715c9ae9d8293ce16a693a2aa83e3cb1b4aa9f76333d0da2bf00c55f65e21e42e50e6c5772ce213dd7b4f7a0", - "0xb273b024fa18b7568c0d1c4d2f0c4e79ec509dafac8c5951f14192d63ddbcf2d8a7512c1c1b615cc38fa3e336618e0c5", - "0xa78b9d3ea4b6a90572eb27956f411f1d105fdb577ee2ffeec9f221da9b45db84bfe866af1f29597220c75e0c37a628d8", - "0xa4be2bf058c36699c41513c4d667681ce161a437c09d81383244fc55e1c44e8b1363439d0cce90a3e44581fb31d49493", - "0xb6eef13040f17dd4eba22aaf284d2f988a4a0c4605db44b8d2f4bf9567ac794550b543cc513c5f3e2820242dd704152e", - "0x87eb00489071fa95d008c5244b88e317a3454652dcb1c441213aa16b28cd3ecaa9b22fec0bdd483c1df71c37119100b1", - "0x92d388acdcb49793afca329cd06e645544d2269234e8b0b27d2818c809c21726bc9cf725651b951e358a63c83dedee24", - "0xae27e219277a73030da27ab5603c72c8bd81b6224b7e488d7193806a41343dff2456132274991a4722fdb0ef265d04cd", - "0x97583e08ecb82bbc27c0c8476d710389fa9ffbead5c43001bd36c1b018f29faa98de778644883e51870b69c5ffb558b5", - "0x90a799a8ce73387599babf6b7da12767c0591cadd36c20a7990e7c05ea1aa2b9645654ec65308ee008816623a2757a6a", - "0xa1b47841a0a2b06efd9ab8c111309cc5fc9e1d5896b3e42ed531f6057e5ade8977c29831ce08dbda40348386b1dcc06d", - "0xb92b8ef59bbddb50c9457691bc023d63dfcc54e0fd88bd5d27a09e0d98ac290fc90e6a8f6b88492043bf7c87fac8f3e4", - "0xa9d6240b07d62e22ec8ab9b1f6007c975a77b7320f02504fc7c468b4ee9cfcfd945456ff0128bc0ef2174d9e09333f8d", - "0x8e96534c94693226dc32bca79a595ca6de503af635f802e86442c67e77564829756961d9b701187fe91318da515bf0e6", - "0xb6ba290623cd8dd5c2f50931c0045d1cfb0c30877bc8fe58cbc3ff61ee8da100045a39153916efa1936f4aee0892b473", - "0xb43baa7717fac02d4294f5b3bb5e58a65b3557747e3188b482410388daac7a9c177f762d943fd5dcf871273921213da8", - "0xb9cf00f8fb5e2ef2b836659fece15e735060b2ea39b8e901d3dcbdcf612be8bf82d013833718c04cd46ffaa70b85f42e", - "0x8017d0c57419e414cbba504368723e751ef990cc6f05dad7b3c2de6360adc774ad95512875ab8337d110bf39a42026fa", - "0xae7401048b838c0dcd4b26bb6c56d79d51964a0daba780970b6c97daee4ea45854ea0ac0e4139b3fe60dac189f84df65", - "0x887b237b0cd0f816b749b21db0b40072f9145f7896c36916296973f9e6990ede110f14e5976c906d08987c9836cca57f", - "0xa88c3d5770148aee59930561ca1223aceb2c832fb5417e188dca935905301fc4c6c2c9270bc1dff7add490a125eb81c6", - "0xb6cf9b02c0cd91895ad209e38c54039523f137b5848b9d3ad33ae43af6c20c98434952db375fe378de7866f2d0e8b18a", - "0x84ef3d322ff580c8ad584b1fe4fe346c60866eb6a56e982ba2cf3b021ecb1fdb75ecc6c29747adda86d9264430b3f816", - "0xa0561c27224baf0927ad144cb71e31e54a064c598373fcf0d66aebf98ab7af1d8e2f343f77baefff69a6da750a219e11", - "0xaa5cc43f5b8162b016f5e1b61214c0c9d15b1078911c650b75e6cdfb49b85ee04c6739f5b1687d15908444f691f732de", - "0xad4ac099b935589c7b8fdfdf3db332b7b82bb948e13a5beb121ebd7db81a87d278024a1434bcf0115c54ca5109585c3d", - "0x8a00466abf3f109a1dcd19e643b603d3af23d42794ef8ca2514dd507ecea44a031ac6dbc18bd02f99701168b25c1791e", - "0xb00b5900dfad79645f8bee4e5adc7b84eb22e5b1e67df77ccb505b7fc044a6c08a8ea5faca662414eb945f874f884cea", - "0x950e204e5f17112250b22ea6bb8423baf522fc0af494366f18fe0f949f51d6e6812074a80875cf1ed9c8e7420058d541", - "0x91e5cbf8bb1a1d50c81608c9727b414d0dd2fb467ebc92f100882a3772e54f94979cfdf8e373fdef7c7fcdd60fec9e00", - "0xa093f6a857b8caaff80599c2e89c962b415ecbaa70d8fd973155fa976a284c6b29a855f5f7a3521134d00d2972755188", - "0xb4d55a3551b00da54cc010f80d99ddd2544bde9219a3173dfaadf3848edc7e4056ab532fb75ac26f5f7141e724267663", - "0xa03ea050fc9b011d1b04041b5765d6f6453a93a1819cd9bd6328637d0b428f08526466912895dcc2e3008ee58822e9a7", - "0x99b12b3665e473d01bc6985844f8994fb65cb15745024fb7af518398c4a37ff215da8f054e8fdf3286984ae36a73ca5e", - "0x9972c7e7a7fb12e15f78d55abcaf322c11249cd44a08f62c95288f34f66b51f146302bce750ff4d591707075d9123bd2", - "0xa64b4a6d72354e596d87cda213c4fc2814009461570ccb27d455bbe131f8d948421a71925425b546d8cf63d5458cd64b", - "0x91c215c73b195795ede2228b7ed1f6e37892e0c6b0f4a0b5a16c57aa1100c84df9239054a173b6110d6c2b7f4bf1ce52", - "0x88807198910ec1303480f76a3683870246a995e36adaeadc29c22f0bdba8152fe705bd070b75de657b04934f7d0ccf80", - "0xb37c0026c7b32eb02cacac5b55cb5fe784b8e48b2945c64d3037af83ece556a117f0ff053a5968c2f5fa230e291c1238", - "0x94c768384ce212bc2387e91ce8b45e4ff120987e42472888a317abc9dcdf3563b62e7a61c8e98d7cdcbe272167d91fc6", - "0xa10c2564936e967a390cb14ef6e8f8b04ea9ece5214a38837eda09e79e0c7970b1f83adf017c10efd6faa8b7ffa2c567", - "0xa5085eed3a95f9d4b1269182ea1e0d719b7809bf5009096557a0674bde4201b0ddc1f0f16a908fc468846b3721748ce3", - "0x87468eb620b79a0a455a259a6b4dfbc297d0d53336537b771254dd956b145dc816b195b7002647ea218552e345818a3f", - "0xace2b77ffb87366af0a9cb5d27d6fc4a14323dbbf1643f5f3c4559306330d86461bb008894054394cbfaefeaa0bc2745", - "0xb27f56e840a54fbd793f0b7a7631aa4cee64b5947e4382b2dfb5eb1790270288884c2a19afebe5dc0c6ef335d4531c1c", - "0x876e438633931f7f895062ee16c4b9d10428875f7bc79a8e156a64d379a77a2c45bf5430c5ab94330f03da352f1e9006", - "0xa2512a252587d200d2092b44c914df54e04ff8bcef36bf631f84bde0cf5a732e3dc7f00f662842cfd74b0b0f7f24180e", - "0x827f1bc8f54a35b7a4bd8154f79bcc055e45faed2e74adf7cf21cca95df44d96899e847bd70ead6bb27b9c0ed97bbd8b", - "0xa0c92cf5a9ed843714f3aea9fe7b880f622d0b4a3bf66de291d1b745279accf6ba35097849691370f41732ba64b5966b", - "0xa63f5c1e222775658421c487b1256b52626c6f79cb55a9b7deb2352622cedffb08502042d622eb3b02c97f9c09f9c957", - "0x8cc093d52651e65fb390e186db6cc4de559176af4624d1c44cb9b0e836832419dacac7b8db0627b96288977b738d785d", - "0xaa7b6a17dfcec146134562d32a12f7bd7fe9522e300859202a02939e69dbd345ed7ff164a184296268f9984f9312e8fc", - "0x8ac76721f0d2b679f023d06cbd28c85ae5f4b43c614867ccee88651d4101d4fd352dbdb65bf36bfc3ebc0109e4b0c6f9", - "0x8d350f7c05fc0dcd9a1170748846fb1f5d39453e4cb31e6d1457bed287d96fc393b2ecc53793ca729906a33e59c6834a", - "0xb9913510dfc5056d7ec5309f0b631d1ec53e3a776412ada9aefdaf033c90da9a49fdde6719e7c76340e86599b1f0eec2", - "0x94955626bf4ce87612c5cfffcf73bf1c46a4c11a736602b9ba066328dc52ad6d51e6d4f53453d4ed55a51e0aad810271", - "0xb0fcab384fd4016b2f1e53f1aafd160ae3b1a8865cd6c155d7073ecc1664e05b1d8bca1def39c158c7086c4e1103345e", - "0x827de3f03edfbde08570b72de6662c8bfa499b066a0a27ebad9b481c273097d17a5a0a67f01553da5392ec3f149b2a78", - "0xab7940384c25e9027c55c40df20bd2a0d479a165ced9b1046958353cd69015eeb1e44ed2fd64e407805ba42df10fc7bf", - "0x8ad456f6ff8cd58bd57567d931f923d0c99141978511b17e03cab7390a72b9f62498b2893e1b05c7c22dd274e9a31919", - "0xac75399e999effe564672db426faa17a839e57c5ef735985c70cd559a377adec23928382767b55ed5a52f7b11b54b756", - "0xb17f975a00b817299ac7af5f2024ea820351805df58b43724393bfb3920a8cd747a3bbd4b8286e795521489db3657168", - "0xa2bed800a6d95501674d9ee866e7314063407231491d794f8cf57d5be020452729c1c7cefd8c50dc1540181f5caab248", - "0x9743f5473171271ffdd3cc59a3ae50545901a7b45cd4bc3570db487865f3b73c0595bebabbfe79268809ee1862e86e4a", - "0xb7eab77c2d4687b60d9d7b04e842b3880c7940140012583898d39fcc22d9b9b0a9be2c2e3788b3e6f30319b39c338f09", - "0x8e2b8f797a436a1b661140e9569dcf3e1eea0a77c7ff2bc4ff0f3e49af04ed2de95e255df8765f1d0927fb456a9926b1", - "0x8aefea201d4a1f4ff98ffce94e540bb313f2d4dfe7e9db484a41f13fc316ed02b282e1acc9bc6f56cad2dc2e393a44c9", - "0xb950c17c0e5ca6607d182144aa7556bb0efe24c68f06d79d6413a973b493bfdf04fd147a4f1ab03033a32004cc3ea66f", - "0xb7b8dcbb179a07165f2dc6aa829fad09f582a71b05c3e3ea0396bf9e6fe73076f47035c031c2101e8e38e0d597eadd30", - "0xa9d77ed89c77ec1bf8335d08d41c3c94dcca9fd1c54f22837b4e54506b212aa38d7440126c80648ab7723ff18e65ed72", - "0xa819d6dfd4aef70e52b8402fe5d135f8082d40eb7d3bb5c4d7997395b621e2bb10682a1bad2c9caa33dd818550fc3ec6", - "0x8f6ee34128fac8bbf13ce2d68b2bb363eb4fd65b297075f88e1446ddeac242500eeb4ef0735e105882ff5ba8c44c139b", - "0xb4440e48255c1644bcecf3a1e9958f1ec4901cb5b1122ee5b56ffd02cad1c29c4266999dbb85aa2605c1b125490074d4", - "0xa43304a067bede5f347775d5811cf65a6380a8d552a652a0063580b5c5ef12a0867a39c7912fa219e184f4538eba1251", - "0xa891ad67a790089ffc9f6d53e6a3d63d3556f5f693e0cd8a7d0131db06fd4520e719cfcc3934f0a8f62a95f90840f1d4", - "0xaea6df8e9bb871081aa0fc5a9bafb00be7d54012c5baf653791907d5042a326aeee966fd9012a582cc16695f5baf7042", - "0x8ffa2660dc52ed1cd4eff67d6a84a8404f358a5f713d04328922269bee1e75e9d49afeec0c8ad751620f22352a438e25", - "0x87ec6108e2d63b06abed350f8b363b7489d642486f879a6c3aa90e5b0f335efc2ff2834eef9353951a42136f8e6a1b32", - "0x865619436076c2760d9e87ddc905023c6de0a8d56eef12c98a98c87837f2ca3f27fd26a2ad752252dbcbe2b9f1d5a032", - "0x980437dce55964293cb315c650c5586ffd97e7a944a83f6618af31c9d92c37b53ca7a21bb5bc557c151b9a9e217e7098", - "0x95d128fc369df4ad8316b72aea0ca363cbc7b0620d6d7bb18f7076a8717a6a46956ff140948b0cc4f6d2ce33b5c10054", - "0x8c7212d4a67b9ec70ebbca04358ad2d36494618d2859609163526d7b3acc2fc935ca98519380f55e6550f70a9bc76862", - "0x893a2968819401bf355e85eee0f0ed0406a6d4a7d7f172d0017420f71e00bb0ba984f6020999a3cdf874d3cd8ebcd371", - "0x9103c1af82dece25d87274e89ea0acd7e68c2921c4af3d8d7c82ab0ed9990a5811231b5b06113e7fa43a6bd492b4564f", - "0x99cfd87a94eab7d35466caa4ed7d7bb45e5c932b2ec094258fb14bf205659f83c209b83b2f2c9ccb175974b2a33e7746", - "0x874b6b93e4ee61be3f00c32dd84c897ccd6855c4b6251eb0953b4023634490ed17753cd3223472873cbc6095b2945075", - "0x84a32c0dc4ea60d33aac3e03e70d6d639cc9c4cc435c539eff915017be3b7bdaba33349562a87746291ebe9bc5671f24", - "0xa7057b24208928ad67914e653f5ac1792c417f413d9176ba635502c3f9c688f7e2ee81800d7e3dc0a340c464da2fd9c5", - "0xa03fb9ed8286aacfa69fbd5d953bec591c2ae4153400983d5dbb6cd9ea37fff46ca9e5cceb9d117f73e9992a6c055ad2", - "0x863b2de04e89936c9a4a2b40380f42f20aefbae18d03750fd816c658aee9c4a03df7b12121f795c85d01f415baaeaa59", - "0x8526eb9bd31790fe8292360d7a4c3eed23be23dd6b8b8f01d2309dbfdc0cfd33ad1568ddd7f8a610f3f85a9dfafc6a92", - "0xb46ab8c5091a493d6d4d60490c40aa27950574a338ea5bbc045be3a114af87bdcb160a8c80435a9b7ad815f3cb56a3f3", - "0xaeadc47b41a8d8b4176629557646202f868b1d728b2dda58a347d937e7ffc8303f20d26d6c00b34c851b8aeec547885d", - "0xaebb19fc424d72c1f1822aa7adc744cd0ef7e55727186f8df8771c784925058c248406ebeeaf3c1a9ee005a26e9a10c6", - "0x8ff96e81c1a4a2ab1b4476c21018fae0a67e92129ee36120cae8699f2d7e57e891f5c624902cb1b845b944926a605cc3", - "0x8251b8d2c43fadcaa049a9e7aff838dae4fb32884018d58d46403ac5f3beb5c518bfd45f03b8abb710369186075eb71c", - "0xa8b2a64f865f51a5e5e86a66455c093407933d9d255d6b61e1fd81ffafc9538d73caaf342338a66ba8ee166372a3d105", - "0xaad915f31c6ba7fdc04e2aaac62e84ef434b7ee76a325f07dc430d12c84081999720181067b87d792efd0117d7ee1eab", - "0xa13db3bb60389883fd41d565c54fb5180d9c47ce2fe7a169ae96e01d17495f7f4fa928d7e556e7c74319c4c25d653eb2", - "0xa4491b0198459b3f552855d680a59214eb74e6a4d6c5fa3b309887dc50ebea2ecf6d26c040550f7dc478b452481466fb", - "0x8f017f13d4b1e3f0c087843582b52d5f8d13240912254d826dd11f8703a99a2f3166dfbdfdffd9a3492979d77524276b", - "0x96c3d5dcd032660d50d7cd9db2914f117240a63439966162b10c8f1f3cf74bc83b0f15451a43b31dbd85e4a7ce0e4bb1", - "0xb479ec4bb79573d32e0ec93b92bdd7ec8c26ddb5a2d3865e7d4209d119fd3499eaac527615ffac78c440e60ef3867ae0", - "0xb2c49c4a33aa94b52b6410b599e81ff15490aafa7e43c8031c865a84e4676354a9c81eb4e7b8be6825fdcefd1e317d44", - "0x906dc51d6a90c089b6704b47592805578a6eed106608eeb276832f127e1b8e858b72e448edcbefb497d152447e0e68ff", - "0xb0e81c63b764d7dfbe3f3fddc9905aef50f3633e5d6a4af6b340495124abedcff5700dfd1577bbbed7b6bf97d02719cb", - "0x9304c64701e3b4ed6d146e48a881f7d83a17f58357cca0c073b2bb593afd2d94f6e2a7a1ec511d0a67ad6ff4c3be5937", - "0xb6fdbd12ba05aa598d80b83f70a15ef90e5cba7e6e75fa038540ee741b644cd1f408a6cecfd2a891ef8d902de586c6b5", - "0xb80557871a6521b1b3c74a1ba083ae055b575df607f1f7b04c867ba8c8c181ea68f8d90be6031f4d25002cca27c44da2", - "0xaa7285b8e9712e06b091f64163f1266926a36607f9d624af9996856ed2aaf03a580cb22ce407d1ade436c28b44ca173f", - "0x8148d72b975238b51e6ea389e5486940d22641b48637d7dfadfa603a605bfc6d74a016480023945d0b85935e396aea5d", - "0x8a014933a6aea2684b5762af43dcf4bdbb633cd0428d42d71167a2b6fc563ece5e618bff22f1db2ddb69b845b9a2db19", - "0x990d91740041db770d0e0eb9d9d97d826f09fd354b91c41e0716c29f8420e0e8aac0d575231efba12fe831091ec38d5a", - "0x9454d0d32e7e308ddec57cf2522fb1b67a2706e33fb3895e9e1f18284129ab4f4c0b7e51af25681d248d7832c05eb698", - "0xa5bd434e75bac105cb3e329665a35bce6a12f71dd90c15165777d64d4c13a82bceedb9b48e762bd24034e0fc9fbe45f4", - "0xb09e3b95e41800d4dc29c6ffdaab2cd611a0050347f6414f154a47ee20ee59bf8cf7181454169d479ebce1eb5c777c46", - "0xb193e341d6a047d15eea33766d656d807b89393665a783a316e9ba10518e5515c8e0ade3d6e15641d917a8a172a5a635", - "0xade435ec0671b3621dde69e07ead596014f6e1daa1152707a8c18877a8b067bde2895dd47444ffa69db2bbef1f1d8816", - "0xa7fd3d6d87522dfc56fb47aef9ce781a1597c56a8bbfd796baba907afdc872f753d732bfda1d3402aee6c4e0c189f52d", - "0xa298cb4f4218d0464b2fab393e512bbc477c3225aa449743299b2c3572f065bc3a42d07e29546167ed9e1b6b3b3a3af3", - "0xa9ee57540e1fd9c27f4f0430d194b91401d0c642456c18527127d1f95e2dba41c2c86d1990432eb38a692fda058fafde", - "0x81d6c1a5f93c04e6d8e5a7e0678c1fc89a1c47a5c920bcd36180125c49fcf7c114866b90e90a165823560b19898a7c16", - "0xa4b7a1ec9e93c899b9fd9aaf264c50e42c36c0788d68296a471f7a3447af4dbc81e4fa96070139941564083ec5b5b5a1", - "0xb3364e327d381f46940c0e11e29f9d994efc6978bf37a32586636c0070b03e4e23d00650c1440f448809e1018ef9f6d8", - "0x8056e0913a60155348300e3a62e28b5e30629a90f7dd4fe11289097076708110a1d70f7855601782a3cdc5bdb1ca9626", - "0xb4980fd3ea17bac0ba9ee1c470b17e575bb52e83ebdd7d40c93f4f87bebeaff1c8a679f9d3d09d635f068d37d5bd28bd", - "0x905a9299e7e1853648e398901dfcd437aa575c826551f83520df62984f5679cb5f0ea86aa45ed3e18b67ddc0dfafe809", - "0xab99553bf31a84f2e0264eb34a08e13d8d15e2484aa9352354becf9a15999c76cc568d68274b70a65e49703fc23540d0", - "0xa43681597bc574d2dae8964c9a8dc1a07613d7a1272bdcb818d98c85d44e16d744250c33f3b5e4d552d97396b55e601f", - "0xa54e5a31716fccb50245898c99865644405b8dc920ded7a11f3d19bdc255996054b268e16f2e40273f11480e7145f41e", - "0x8134f3ad5ef2ad4ba12a8a4e4d8508d91394d2bcdc38b7c8c8c0b0a820357ac9f79d286c65220f471eb1adca1d98fc68", - "0x94e2f755e60471578ab2c1adb9e9cea28d4eec9b0e92e0140770bca7002c365fcabfe1e5fb4fe6cfe79a0413712aa3ef", - "0xad48f8d0ce7eb3cc6e2a3086ad96f562e5bed98a360721492ae2e74dc158586e77ec8c35d5fd5927376301b7741bad2b", - "0x8614f0630bdd7fbad3a31f55afd9789f1c605dc85e7dc67e2edfd77f5105f878bb79beded6e9f0b109e38ea7da67e8d5", - "0x9804c284c4c5e77dabb73f655b12181534ca877c3e1e134aa3f47c23b7ec92277db34d2b0a5d38d2b69e5d1c3008a3e3", - "0xa51b99c3088e473afdaa9e0a9f7e75a373530d3b04e44e1148da0726b95e9f5f0c7e571b2da000310817c36f84b19f7f", - "0xac4ff909933b3b76c726b0a382157cdc74ab851a1ac6cef76953c6444441804cc43abb883363f416592e8f6cfbc4550b", - "0xae7d915eb9fc928b65a29d6edbc75682d08584d0014f7bcf17d59118421ae07d26a02137d1e4de6938bcd1ab8ef48fad", - "0x852f7e453b1af89b754df6d11a40d5d41ea057376e8ecacd705aacd2f917457f4a093d6b9a8801837fa0f62986ad7149", - "0x92c6bf5ada5d0c3d4dd8058483de36c215fa98edab9d75242f3eff9db07c734ad67337da6f0eefe23a487bf75a600dee", - "0xa2b42c09d0db615853763552a48d2e704542bbd786aae016eb58acbf6c0226c844f5fb31e428cb6450b9db855f8f2a6f", - "0x880cc07968266dbfdcfbc21815cd69e0eddfee239167ac693fb0413912d816f2578a74f7716eecd6deefa68c6eccd394", - "0xb885b3ace736cd373e8098bf75ba66fa1c6943ca1bc4408cd98ac7074775c4478594f91154b8a743d9c697e1b29f5840", - "0xa51ce78de512bd87bfa0835de819941dffbf18bec23221b61d8096fc9436af64e0693c335b54e7bfc763f287bdca2db6", - "0xa3c76166a3bdb9b06ef696e57603b58871bc72883ee9d45171a30fe6e1d50e30bc9c51b4a0f5a7270e19a77b89733850", - "0xacefc5c6f8a1e7c24d7b41e0fc7f6f3dc0ede6cf3115ffb9a6e54b1d954cbca9bda8ad7a084be9be245a1b8e9770d141", - "0xb420ed079941842510e31cfad117fa11fb6b4f97dfbc6298cb840f27ebaceba23eeaf3f513bcffbf5e4aae946310182d", - "0x95c3bb5ef26c5ed2f035aa5d389c6b3c15a6705b9818a3fefaed28922158b35642b2e8e5a1a620fdad07e75ad4b43af4", - "0x825149f9081ecf07a2a4e3e8b5d21bade86c1a882475d51c55ee909330b70c5a2ac63771c8600c6f38df716af61a3ea1", - "0x873b935aae16d9f08adbc25353cee18af2f1b8d5f26dec6538d6bbddc515f2217ed7d235dcfea59ae61b428798b28637", - "0x9294150843a2bedcedb3bb74c43eb28e759cf9499582c5430bccefb574a8ddd4f11f9929257ff4c153990f9970a2558f", - "0xb619563a811cc531da07f4f04e5c4c6423010ff9f8ed7e6ec9449162e3d501b269fb1c564c09c0429431879b0f45df02", - "0x91b509b87eb09f007d839627514658c7341bc76d468920fe8a740a8cb96a7e7e631e0ea584a7e3dc1172266f641d0f5c", - "0x8b8aceace9a7b9b4317f1f01308c3904d7663856946afbcea141a1c615e21ccad06b71217413e832166e9dd915fbe098", - "0x87b3b36e725833ea0b0f54753c3728c0dbc87c52d44d705ffc709f2d2394414c652d3283bab28dcce09799504996cee0", - "0xb2670aad5691cbf308e4a6a77a075c4422e6cbe86fdba24e9f84a313e90b0696afb6a067eebb42ba2d10340d6a2f6e51", - "0x876784a9aff3d54faa89b2bacd3ff5862f70195d0b2edc58e8d1068b3c9074c0da1cfa23671fe12f35e33b8a329c0ccd", - "0x8b48b9e758e8a8eae182f5cbec96f67d20cca6d3eee80a2d09208eb1d5d872e09ef23d0df8ebbb9b01c7449d0e3e3650", - "0xb79303453100654c04a487bdcadc9e3578bc80930c489a7069a52e8ca1dba36c492c8c899ce025f8364599899baa287d", - "0x961b35a6111da54ece6494f24dacd5ea46181f55775b5f03df0e370c34a5046ac2b4082925855325bb42bc2a2c98381d", - "0xa31feb1be3f5a0247a1f7d487987eb622e34fca817832904c6ee3ee60277e5847945a6f6ea1ac24542c72e47bdf647df", - "0xa12a2aa3e7327e457e1aae30e9612715dd2cfed32892c1cd6dcda4e9a18203af8a44afb46d03b2eed89f6b9c5a2c0c23", - "0xa08265a838e69a2ca2f80fead6ccf16f6366415b920c0b22ee359bcd8d4464ecf156f400a16a7918d52e6d733dd64211", - "0xb723d6344e938d801cca1a00032af200e541d4471fd6cbd38fb9130daa83f6a1dffbbe7e67fc20f9577f884acd7594b2", - "0xa6733d83ec78ba98e72ddd1e7ff79b7adb0e559e256760d0c590a986e742445e8cdf560d44b29439c26d87edd0b07c8c", - "0xa61c2c27d3f7b9ff4695a17afedf63818d4bfba390507e1f4d0d806ce8778d9418784430ce3d4199fd3bdbc2504d2af3", - "0x8332f3b63a6dc985376e8b1b25eeae68be6160fbe40053ba7bcf6f073204f682da72321786e422d3482fd60c9e5aa034", - "0xa280f44877583fbb6b860d500b1a3f572e3ee833ec8f06476b3d8002058e25964062feaa1e5bec1536d734a5cfa09145", - "0xa4026a52d277fcea512440d2204f53047718ebfcae7b48ac57ea7f6bfbc5de9d7304db9a9a6cbb273612281049ddaec5", - "0x95cdf69c831ab2fad6c2535ede9c07e663d2ddccc936b64e0843d2df2a7b1c31f1759c3c20f1e7a57b1c8f0dbb21b540", - "0x95c96cec88806469c277ab567863c5209027cecc06c7012358e5f555689c0d9a5ffb219a464f086b45817e8536b86d2f", - "0xafe38d4684132a0f03d806a4c8df556bf589b25271fbc6fe2e1ed16de7962b341c5003755da758d0959d2e6499b06c68", - "0xa9b77784fda64987f97c3a23c5e8f61b918be0f7c59ba285084116d60465c4a2aaafc8857eb16823282cc83143eb9126", - "0xa830f05881ad3ce532a55685877f529d32a5dbe56cea57ffad52c4128ee0fad0eeaf0da4362b55075e77eda7babe70e5", - "0x992b3ad190d6578033c13ed5abfee4ef49cbc492babb90061e3c51ee4b5790cdd4c8fc1abff1fa2c00183b6b64f0bbbe", - "0xb1015424d9364aeff75de191652dc66484fdbec3e98199a9eb9671ec57bec6a13ff4b38446e28e4d8aedb58dd619cd90", - "0xa745304604075d60c9db36cada4063ac7558e7ec2835d7da8485e58d8422e817457b8da069f56511b02601289fbb8981", - "0xa5ba4330bc5cb3dbe0486ddf995632a7260a46180a08f42ae51a2e47778142132463cc9f10021a9ad36986108fefa1a9", - "0xb419e9fd4babcaf8180d5479db188bb3da232ae77a1c4ed65687c306e6262f8083070a9ac32220cddb3af2ec73114092", - "0xa49e23dc5f3468f3bf3a0bb7e4a114a788b951ff6f23a3396ae9e12cbff0abd1240878a3d1892105413dbc38818e807c", - "0xb7ecc7b4831f650202987e85b86bc0053f40d983f252e9832ef503aea81c51221ce93279da4aa7466c026b2d2070e55d", - "0x96a8c35cb87f84fa84dcd6399cc2a0fd79cc9158ef4bdde4bae31a129616c8a9f2576cd19baa3f497ca34060979aed7d", - "0x8681b2c00aa62c2b519f664a95dcb8faef601a3b961bb4ce5d85a75030f40965e2983871d41ea394aee934e859581548", - "0x85c229a07efa54a713d0790963a392400f55fbb1a43995a535dc6c929f20d6a65cf4efb434e0ad1cb61f689b8011a3bc", - "0x90856f7f3444e5ad44651c28e24cc085a5db4d2ffe79aa53228c26718cf53a6e44615f3c5cda5aa752d5f762c4623c66", - "0x978999b7d8aa3f28a04076f74d11c41ef9c89fdfe514936c4238e0f13c38ec97e51a5c078ebc6409e517bfe7ccb42630", - "0xa099914dd7ed934d8e0d363a648e9038eb7c1ec03fa04dbcaa40f7721c618c3ef947afef7a16b4d7ac8c12aa46637f03", - "0xab2a104fed3c83d16f2cda06878fa5f30c8c9411de71bfb67fd2fc9aa454dcbcf3d299d72f8cc12e919466a50fcf7426", - "0xa4471d111db4418f56915689482f6144efc4664cfb0311727f36c864648d35734351becc48875df96f4abd3cfcf820f9", - "0x83be11727cd30ea94ccc8fa31b09b81c9d6a9a5d3a4686af9da99587332fe78c1f94282f9755854bafd6033549afec91", - "0x88020ff971dc1a01a9e993cd50a5d2131ffdcbb990c1a6aaa54b20d8f23f9546a70918ea57a21530dcc440c1509c24ad", - "0xae24547623465e87905eaffa1fa5d52bb7c453a8dbd89614fa8819a2abcedaf455c2345099b7324ae36eb0ad7c8ef977", - "0xb59b0c60997de1ee00b7c388bc7101d136c9803bf5437b1d589ba57c213f4f835a3e4125b54738e78abbc21b000f2016", - "0xa584c434dfe194546526691b68fa968c831c31da42303a1d735d960901c74011d522246f37f299555416b8cf25c5a548", - "0x80408ce3724f4837d4d52376d255e10f69eb8558399ae5ca6c11b78b98fe67d4b93157d2b9b639f1b5b64198bfe87713", - "0xabb941e8d406c2606e0ddc35c113604fdd9d249eacc51cb64e2991e551b8639ce44d288cc92afa7a1e7fc599cfc84b22", - "0xb223173f560cacb1c21dba0f1713839e348ad02cbfdef0626748604c86f89e0f4c919ed40b583343795bdd519ba952c8", - "0xaf1c70512ec3a19d98b8a1fc3ff7f7f5048a27d17d438d43f561974bbdd116fcd5d5c21040f3447af3f0266848d47a15", - "0x8a44809568ebe50405bede19b4d2607199159b26a1b33e03d180e6840c5cf59d991a4fb150d111443235d75ecad085b7", - "0xb06207cdca46b125a27b3221b5b50cf27af4c527dd7c80e2dbcebbb09778a96df3af67e50f07725239ce3583dad60660", - "0x993352d9278814ec89b26a11c4a7c4941bf8f0e6781ae79559d14749ee5def672259792db4587f85f0100c7bb812f933", - "0x9180b8a718b971fd27bc82c8582d19c4b4f012453e8c0ffeeeffe745581fc6c07875ab28be3af3fa3896d19f0c89ac5b", - "0x8b8e1263eb48d0fe304032dd5ea1f30e73f0121265f7458ba9054d3626894e8a5fef665340abd2ede9653045c2665938", - "0x99a2beee4a10b7941c24b2092192faf52b819afd033e4a2de050fd6c7f56d364d0cf5f99764c3357cf32399e60fc5d74", - "0x946a4aad7f8647ea60bee2c5fcdeb6f9a58fb2cfca70c4d10e458027a04846e13798c66506151be3df9454b1e417893f", - "0xa672a88847652d260b5472d6908d1d57e200f1e492d30dd1cecc441cdfc9b76e016d9bab560efd4d7f3c30801de884a9", - "0x9414e1959c156cde1eb24e628395744db75fc24b9df4595350aaad0bc38e0246c9b4148f6443ef68b8e253a4a6bcf11c", - "0x9316e9e4ec5fab4f80d6540df0e3a4774db52f1d759d2e5b5bcd3d7b53597bb007eb1887cb7dc61f62497d51ffc8d996", - "0x902d6d77bb49492c7a00bc4b70277bc28c8bf9888f4307bb017ac75a962decdedf3a4e2cf6c1ea9f9ba551f4610cbbd7", - "0xb07025a18b0e32dd5e12ec6a85781aa3554329ea12c4cd0d3b2c22e43d777ef6f89876dd90a9c8fb097ddf61cf18adc5", - "0xb355a849ad3227caa4476759137e813505ec523cbc2d4105bc7148a4630f9e81918d110479a2d5f5e4cd9ccec9d9d3e3", - "0xb49532cfdf02ee760109881ad030b89c48ee3bb7f219ccafc13c93aead754d29bdafe345be54c482e9d5672bd4505080", - "0x9477802410e263e4f938d57fa8f2a6cac7754c5d38505b73ee35ea3f057aad958cb9722ba6b7b3cfc4524e9ca93f9cdc", - "0x9148ea83b4436339580f3dbc9ba51509e9ab13c03063587a57e125432dd0915f5d2a8f456a68f8fff57d5f08c8f34d6e", - "0xb00b6b5392b1930b54352c02b1b3b4f6186d20bf21698689bbfc7d13e86538a4397b90e9d5c93fd2054640c4dbe52a4f", - "0x926a9702500441243cd446e7cbf15dde16400259726794694b1d9a40263a9fc9e12f7bcbf12a27cb9aaba9e2d5848ddc", - "0xa0c6155f42686cbe7684a1dc327100962e13bafcf3db97971fc116d9f5c0c8355377e3d70979cdbd58fd3ea52440901c", - "0xa277f899f99edb8791889d0817ea6a96c24a61acfda3ad8c3379e7c62b9d4facc4b965020b588651672fd261a77f1bfc", - "0x8f528cebb866b501f91afa50e995234bef5bf20bff13005de99cb51eaac7b4f0bf38580cfd0470de40f577ead5d9ba0f", - "0x963fc03a44e9d502cc1d23250efef44d299befd03b898d07ce63ca607bb474b5cf7c965a7b9b0f32198b04a8393821f7", - "0xab087438d0a51078c378bf4a93bd48ef933ff0f1fa68d02d4460820df564e6642a663b5e50a5fe509527d55cb510ae04", - "0xb0592e1f2c54746bb076be0fa480e1c4bebc4225e1236bcda3b299aa3853e3afb401233bdbcfc4a007b0523a720fbf62", - "0x851613517966de76c1c55a94dc4595f299398a9808f2d2f0a84330ba657ab1f357701d0895f658c18a44cb00547f6f57", - "0xa2fe9a1dd251e72b0fe4db27be508bb55208f8f1616b13d8be288363ec722826b1a1fd729fc561c3369bf13950bf1fd6", - "0xb896cb2bc2d0c77739853bc59b0f89b2e008ba1f701c9cbe3bef035f499e1baee8f0ff1e794854a48c320586a2dfc81a", - "0xa1b60f98e5e5106785a9b81a85423452ee9ef980fa7fa8464f4366e73f89c50435a0c37b2906052b8e58e212ebd366cf", - "0xa853b0ebd9609656636df2e6acd5d8839c0fda56f7bf9288a943b06f0b67901a32b95e016ca8bc99bd7b5eab31347e72", - "0xb290fa4c1346963bd5225235e6bdf7c542174dab4c908ab483d1745b9b3a6015525e398e1761c90e4b49968d05e30eea", - "0xb0f65a33ad18f154f1351f07879a183ad62e5144ad9f3241c2d06533dad09cbb2253949daff1bb02d24d16a3569f7ef0", - "0xa00db59b8d4218faf5aeafcd39231027324408f208ec1f54d55a1c41228b463b88304d909d16b718cfc784213917b71e", - "0xb8d695dd33dc2c3bc73d98248c535b2770ad7fa31aa726f0aa4b3299efb0295ba9b4a51c71d314a4a1bd5872307534d1", - "0xb848057cca2ca837ee49c42b88422303e58ea7d2fc76535260eb5bd609255e430514e927cc188324faa8e657396d63ec", - "0x92677836061364685c2aaf0313fa32322746074ed5666fd5f142a7e8f87135f45cd10e78a17557a4067a51dfde890371", - "0xa854b22c9056a3a24ab164a53e5c5cf388616c33e67d8ebb4590cb16b2e7d88b54b1393c93760d154208b5ca822dc68f", - "0x86fff174920388bfab841118fb076b2b0cdec3fdb6c3d9a476262f82689fb0ed3f1897f7be9dbf0932bb14d346815c63", - "0x99661cf4c94a74e182752bcc4b98a8c2218a8f2765642025048e12e88ba776f14f7be73a2d79bd21a61def757f47f904", - "0x8a8893144d771dca28760cba0f950a5d634195fd401ec8cf1145146286caffb0b1a6ba0c4c1828d0a5480ce49073c64c", - "0x938a59ae761359ee2688571e7b7d54692848eb5dde57ffc572b473001ea199786886f8c6346a226209484afb61d2e526", - "0x923f68a6aa6616714cf077cf548aeb845bfdd78f2f6851d8148cba9e33a374017f2f3da186c39b82d14785a093313222", - "0xac923a93d7da7013e73ce8b4a2b14b8fd0cc93dc29d5de941a70285bdd19be4740fedfe0c56b046689252a3696e9c5bc", - "0xb49b32c76d4ec1a2c68d4989285a920a805993bc6fcce6dacd3d2ddae73373050a5c44ba8422a3781050682fa0ef6ba2", - "0x8a367941c07c3bdca5712524a1411bad7945c7c48ffc7103b1d4dff2c25751b0624219d1ccde8c3f70c465f954be5445", - "0xb838f029df455efb6c530d0e370bbbf7d87d61a9aea3d2fe5474c5fe0a39cf235ceecf9693c5c6c5820b1ba8f820bd31", - "0xa8983b7c715eaac7f13a001d2abc462dfc1559dab4a6b554119c271aa8fe00ffcf6b6949a1121f324d6d26cb877bcbae", - "0xa2afb24ad95a6f14a6796315fbe0d8d7700d08f0cfaf7a2abe841f5f18d4fecf094406cbd54da7232a159f9c5b6e805e", - "0x87e8e95ad2d62f947b2766ff405a23f7a8afba14e7f718a691d95369c79955cdebe24c54662553c60a3f55e6322c0f6f", - "0x87c2cbcecb754e0cc96128e707e5c5005c9de07ffd899efa3437cadc23362f5a1d3fcdd30a1f5bdc72af3fb594398c2a", - "0x91afd6ee04f0496dc633db88b9370d41c428b04fd991002502da2e9a0ef051bcd7b760e860829a44fbe5539fa65f8525", - "0x8c50e5d1a24515a9dd624fe08b12223a75ca55196f769f24748686315329b337efadca1c63f88bee0ac292dd0a587440", - "0x8a07e8f912a38d94309f317c32068e87f68f51bdfa082d96026f5f5f8a2211621f8a3856dda8069386bf15fb2d28c18f", - "0x94ad1dbe341c44eeaf4dc133eed47d8dbfe752575e836c075745770a6679ff1f0e7883b6aa917462993a7f469d74cab5", - "0x8745f8bd86c2bb30efa7efb7725489f2654f3e1ac4ea95bd7ad0f3cfa223055d06c187a16192d9d7bdaea7b050c6a324", - "0x900d149c8d79418cda5955974c450a70845e02e5a4ecbcc584a3ca64d237df73987c303e3eeb79da1af83bf62d9e579f", - "0x8f652ab565f677fb1a7ba03b08004e3cda06b86c6f1b0b9ab932e0834acf1370abb2914c15b0d08327b5504e5990681c", - "0x9103097d088be1f75ab9d3da879106c2f597e2cc91ec31e73430647bdd5c33bcfd771530d5521e7e14df6acda44f38a6", - "0xb0fec7791cfb0f96e60601e1aeced9a92446b61fedab832539d1d1037558612d78419efa87ff5f6b7aab8fd697d4d9de", - "0xb9d2945bdb188b98958854ba287eb0480ef614199c4235ce5f15fc670b8c5ffe8eeb120c09c53ea8a543a022e6a321ac", - "0xa9461bb7d5490973ebaa51afc0bb4a5e42acdccb80e2f939e88b77ac28a98870e103e1042899750f8667a8cc9123bae9", - "0xa37fdf11d4bcb2aed74b9f460a30aa34afea93386fa4cdb690f0a71bc58f0b8df60bec56e7a24f225978b862626fa00e", - "0xa214420e183e03d531cf91661466ea2187d84b6e814b8b20b3730a9400a7d25cf23181bb85589ebc982cec414f5c2923", - "0xad09a45a698a6beb3e0915f540ef16e9af7087f53328972532d6b5dfe98ce4020555ece65c6cbad8bd6be8a4dfefe6fd", - "0xab6742800b02728c92d806976764cb027413d6f86edd08ad8bb5922a2969ee9836878cd39db70db0bd9a2646862acc4f", - "0x974ca9305bd5ea1dc1755dff3b63e8bfe9f744321046c1395659bcea2a987b528e64d5aa96ac7b015650b2253b37888d", - "0x84eee9d6bce039c52c2ebc4fccc0ad70e20c82f47c558098da4be2f386a493cbc76adc795b5488c8d11b6518c2c4fab8", - "0x875d7bda46efcb63944e1ccf760a20144df3b00d53282b781e95f12bfc8f8316dfe6492c2efbf796f1150e36e436e9df", - "0xb68a2208e0c587b5c31b5f6cb32d3e6058a9642e2d9855da4f85566e1412db528475892060bb932c55b3a80877ad7b4a", - "0xba006368ecab5febb6ab348644d9b63de202293085ed468df8bc24d992ae8ce468470aa37f36a73630c789fb9c819b30", - "0x90a196035150846cd2b482c7b17027471372a8ce7d914c4d82b6ea7fa705d8ed5817bd42d63886242585baf7d1397a1c", - "0xa223b4c85e0daa8434b015fd9170b5561fe676664b67064974a1e9325066ecf88fc81f97ab5011c59fad28cedd04b240", - "0x82e8ec43139cf15c6bbeed484b62e06cded8a39b5ce0389e4cbe9c9e9c02f2f0275d8d8d4e8dfec8f69a191bef220408", - "0x81a3fc07a7b68d92c6ee4b6d28f5653ee9ec85f7e2ee1c51c075c1b130a8c5097dc661cf10c5aff1c7114b1a6a19f11a", - "0x8ed2ef8331546d98819a5dd0e6c9f8cb2630d0847671314a28f277faf68da080b53891dd75c82cbcf7788b255490785d", - "0xacecabf84a6f9bbed6b2fc2e7e4b48f02ef2f15e597538a73aea8f98addc6badda15e4695a67ecdb505c1554e8f345ec", - "0xb8f51019b2aa575f8476e03dcadf86cc8391f007e5f922c2a36b2daa63f5a503646a468990cd5c65148d323942193051", - "0xaaa595a84b403ec65729bc1c8055a94f874bf9adddc6c507b3e1f24f79d3ad359595a672b93aab3394db4e2d4a7d8970", - "0x895144c55fcbd0f64d7dd69e6855cfb956e02b5658eadf0f026a70703f3643037268fdd673b0d21b288578a83c6338dd", - "0xa2e92ae6d0d237d1274259a8f99d4ea4912a299816350b876fba5ebc60b714490e198a916e1c38c6e020a792496fa23c", - "0xa45795fda3b5bb0ad1d3c628f6add5b2a4473a1414c1a232e80e70d1cfffd7f8a8d9861f8df2946999d7dbb56bf60113", - "0xb6659bf7f6f2fef61c39923e8c23b8c70e9c903028d8f62516d16755cd3fba2fe41c285aa9432dc75ab08f8a1d8a81fc", - "0xa735609a6bc5bfd85e58234fc439ff1f58f1ff1dd966c5921d8b649e21f006bf2b8642ad8a75063c159aaf6935789293", - "0xa3c622eb387c9d15e7bda2e3e84d007cb13a6d50d655c3f2f289758e49d3b37b9a35e4535d3cc53d8efd51f407281f19", - "0x8afe147b53ad99220f5ef9d763bfc91f9c20caecbcf823564236fb0e6ede49414c57d71eec4772c8715cc65a81af0047", - "0xb5f0203233cf71913951e9c9c4e10d9243e3e4a1f2cb235bf3f42009120ba96e04aa414c9938ea8873b63148478927e8", - "0x93c52493361b458d196172d7ba982a90a4f79f03aa8008edc322950de3ce6acf4c3977807a2ffa9e924047e02072b229", - "0xb9e72b805c8ac56503f4a86c82720afbd5c73654408a22a2ac0b2e5caccdfb0e20b59807433a6233bc97ae58cf14c70a", - "0xaf0475779b5cee278cca14c82da2a9f9c8ef222eb885e8c50cca2315fea420de6e04146590ed0dd5a29c0e0812964df5", - "0xb430ccab85690db02c2d0eb610f3197884ca12bc5f23c51e282bf3a6aa7e4a79222c3d8761454caf55d6c01a327595f9", - "0x830032937418b26ee6da9b5206f3e24dc76acd98589e37937e963a8333e5430abd6ce3dd93ef4b8997bd41440eed75d6", - "0x8820a6d73180f3fe255199f3f175c5eb770461ad5cfdde2fb11508041ed19b8c4ce66ad6ecebf7d7e836cc2318df47ca", - "0xaef1393e7d97278e77bbf52ef6e1c1d5db721ccf75fe753cf47a881fa034ca61eaa5098ee5a344c156d2b14ff9e284ad", - "0x8a4a26c07218948c1196c45d927ef4d2c42ade5e29fe7a91eaebe34a29900072ce5194cf28d51f746f4c4c649daf4396", - "0x84011dc150b7177abdcb715efbd8c201f9cb39c36e6069af5c50a096021768ba40cef45b659c70915af209f904ede3b6", - "0xb1bd90675411389bb66910b21a4bbb50edce5330850c5ab0b682393950124252766fc81f5ecfc72fb7184387238c402e", - "0x8dfdcd30583b696d2c7744655f79809f451a60c9ad5bf1226dc078b19f4585d7b3ef7fa9d54e1ac09520d95cbfd20928", - "0xb351b4dc6d98f75b8e5a48eb7c6f6e4b78451991c9ba630e5a1b9874c15ac450cd409c1a024713bf2cf82dc400e025ef", - "0xa462b8bc97ac668b97b28b3ae24b9f5de60e098d7b23ecb600d2194cd35827fb79f77c3e50d358f5bd72ee83fef18fa0", - "0xa183753265c5f7890270821880cce5f9b2965b115ba783c6dba9769536f57a04465d7da5049c7cf8b3fcf48146173c18", - "0xa8a771b81ed0d09e0da4d79f990e58eabcd2be3a2680419502dd592783fe52f657fe55125b385c41d0ba3b9b9cf54a83", - "0xa71ec577db46011689d073245e3b1c3222a9b1fe6aa5b83629adec5733dd48617ebea91346f0dd0e6cdaa86e4931b168", - "0xa334b8b244f0d598a02da6ae0f918a7857a54dce928376c4c85df15f3b0f2ba3ac321296b8b7c9dd47d770daf16c8f8c", - "0xa29037f8ef925c417c90c4df4f9fb27fb977d04e2b3dd5e8547d33e92ab72e7a00f5461de21e28835319eae5db145eb7", - "0xb91054108ae78b00e3298d667b913ebc44d8f26e531eae78a8fe26fdfb60271c97efb2dee5f47ef5a3c15c8228138927", - "0x926c13efbe90604f6244be9315a34f72a1f8d1aab7572df431998949c378cddbf2fe393502c930fff614ff06ae98a0ce", - "0x995c758fd5600e6537089b1baa4fbe0376ab274ff3e82a17768b40df6f91c2e443411de9cafa1e65ea88fb8b87d504f4", - "0x9245ba307a7a90847da75fca8d77ec03fdfc812c871e7a2529c56a0a79a6de16084258e7a9ac4ae8a3756f394336e21c", - "0x99e0cfa2bb57a7e624231317044c15e52196ecce020db567c8e8cb960354a0be9862ee0c128c60b44777e65ac315e59f", - "0xad4f6b3d27bbbb744126601053c3dc98c07ff0eb0b38a898bd80dce778372846d67e5ab8fb34fb3ad0ef3f235d77ba7f", - "0xa0f12cae3722bbbca2e539eb9cc7614632a2aefe51410430070a12b5bc5314ecec5857b7ff8f41e9980cac23064f7c56", - "0xb487f1bc59485848c98222fd3bc36c8c9bb3d2912e2911f4ceca32c840a7921477f9b1fe00877e05c96c75d3eecae061", - "0xa6033db53925654e18ecb3ce715715c36165d7035db9397087ac3a0585e587998a53973d011ac6d48af439493029cee6", - "0xa6b4d09cd01c70a3311fd131d3710ccf97bde3e7b80efd5a8c0eaeffeb48cca0f951ced905290267b115b06d46f2693b", - "0xa9dff1df0a8f4f218a98b6f818a693fb0d611fed0fc3143537cbd6578d479af13a653a8155e535548a2a0628ae24fa58", - "0xa58e469f65d366b519f9a394cacb7edaddac214463b7b6d62c2dbc1316e11c6c5184ce45c16de2d77f990dcdd8b55430", - "0x989e71734f8119103586dc9a3c5f5033ddc815a21018b34c1f876cdfc112efa868d5751bf6419323e4e59fa6a03ece1c", - "0xa2da00e05036c884369e04cf55f3de7d659cd5fa3f849092b2519dd263694efe0f051953d9d94b7e121f0aee8b6174d7", - "0x968f3c029f57ee31c4e1adea89a7f92e28483af9a74f30fbdb995dc2d40e8e657dff8f8d340d4a92bf65f54440f2859f", - "0x932778df6f60ac1639c1453ef0cbd2bf67592759dcccb3e96dcc743ff01679e4c7dd0ef2b0833dda548d32cb4eba49e2", - "0xa805a31139f8e0d6dae1ac87d454b23a3dc9fc653d4ca18d4f8ebab30fc189c16e73981c2cb7dd6f8c30454a5208109d", - "0xa9ba0991296caa2aaa4a1ceacfb205544c2a2ec97088eace1d84ee5e2767656a172f75d2f0c4e16a3640a0e0dec316e0", - "0xb1e49055c968dced47ec95ae934cf45023836d180702e20e2df57e0f62fb85d7ac60d657ba3ae13b8560b67210449459", - "0xa94e1da570a38809c71e37571066acabff7bf5632737c9ab6e4a32856924bf6211139ab3cedbf083850ff2d0e0c0fcfc", - "0x88ef1bb322000c5a5515b310c838c9af4c1cdbb32eab1c83ac3b2283191cd40e9573747d663763a28dad0d64adc13840", - "0xa987ce205f923100df0fbd5a85f22c9b99b9b9cbe6ddfa8dfda1b8fe95b4f71ff01d6c5b64ca02eb24edb2b255a14ef0", - "0x84fe8221a9e95d9178359918a108de4763ebfa7a6487facb9c963406882a08a9a93f492f8e77cf9e7ea41ae079c45993", - "0xaa1cf3dc7c5dcfa15bbbc811a4bb6dbac4fba4f97fb1ed344ab60264d7051f6eef19ea9773441d89929ee942ed089319", - "0x8f6a7d610d59d9f54689bbe6a41f92d9f6096cde919c1ab94c3c7fcecf0851423bc191e5612349e10f855121c0570f56", - "0xb5af1fa7894428a53ea520f260f3dc3726da245026b6d5d240625380bfb9c7c186df0204bb604efac5e613a70af5106e", - "0xa5bce6055ff812e72ce105f147147c7d48d7a2313884dd1f488b1240ee320f13e8a33f5441953a8e7a3209f65b673ce1", - "0xb9b55b4a1422677d95821e1d042ab81bbf0bf087496504021ec2e17e238c2ca6b44fb3b635a5c9eac0871a724b8d47c3", - "0x941c38e533ce4a673a3830845b56786585e5fe49c427f2e5c279fc6db08530c8f91db3e6c7822ec6bb4f956940052d18", - "0xa38e191d66c625f975313c7007bbe7431b5a06ed2da1290a7d5d0f2ec73770d476efd07b8e632de64597d47df175cbb0", - "0x94ba76b667abf055621db4c4145d18743a368d951565632ed4e743dd50dd3333507c0c34f286a5c5fdbf38191a2255cd", - "0xa5ca38c60be5602f2bfa6e00c687ac96ac36d517145018ddbee6f12eb0faa63dd57909b9eeed26085fe5ac44e55d10ab", - "0xb00fea3b825e60c1ed1c5deb4b551aa65a340e5af36b17d5262c9cd2c508711e4dc50dc2521a2c16c7c901902266e64a", - "0x971b86fc4033485e235ccb0997a236206ba25c6859075edbcdf3c943116a5030b7f75ebca9753d863a522ba21a215a90", - "0xb3b31f52370de246ee215400975b674f6da39b2f32514fe6bd54e747752eedca22bb840493b44a67df42a3639c5f901f", - "0xaffbbfac9c1ba7cbfa1839d2ae271dd6149869b75790bf103230637da41857fc326ef3552ff31c15bda0694080198143", - "0xa95d42aa7ef1962520845aa3688f2752d291926f7b0d73ea2ee24f0612c03b43f2b0fe3c9a9a99620ffc8d487b981bc2", - "0x914a266065caf64985e8c5b1cb2e3f4e3fe94d7d085a1881b1fefa435afef4e1b39a98551d096a62e4f5cc1a7f0fdc2e", - "0x81a0b4a96e2b75bc1bf2dbd165d58d55cfd259000a35504d1ffb18bc346a3e6f07602c683723864ffb980f840836fd8d", - "0x91c1556631cddd4c00b65b67962b39e4a33429029d311c8acf73a18600e362304fb68bccb56fde40f49e95b7829e0b87", - "0x8befbacc19e57f7c885d1b7a6028359eb3d80792fe13b92a8400df21ce48deb0bb60f2ddb50e3d74f39f85d7eab23adc", - "0x92f9458d674df6e990789690ec9ca73dacb67fc9255b58c417c555a8cc1208ace56e8e538f86ba0f3615573a0fbac00d", - "0xb4b1b3062512d6ae7417850c08c13f707d5838e43d48eb98dd4621baf62eee9e82348f80fe9b888a12874bfa538771f8", - "0xa13c4a3ac642ede37d9c883f5319e748d2b938f708c9d779714108a449b343f7b71a6e3ef4080fee125b416762920273", - "0xaf44983d5fc8cceee0551ef934e6e653f2d3efa385e5c8a27a272463a6f333e290378cc307c2b664eb923c78994e706e", - "0xa389fd6c59fe2b4031cc244e22d3991e541bd203dd5b5e73a6159e72df1ab41d49994961500dcde7989e945213184778", - "0x8d2141e4a17836c548de9598d7b298b03f0e6c73b7364979a411c464e0628e21cff6ac3d6decdba5d1c4909eff479761", - "0x980b22ef53b7bdf188a3f14bc51b0dbfdf9c758826daa3cbc1e3986022406a8aa9a6a79e400567120b88c67faa35ce5f", - "0xa28882f0a055f96df3711de5d0aa69473e71245f4f3e9aa944e9d1fb166e02caa50832e46da6d3a03b4801735fd01b29", - "0x8db106a37d7b88f5d995c126abb563934dd8de516af48e85695d02b1aea07f79217e3cdd03c6f5ca57421830186c772b", - "0xb5a7e50da0559a675c472f7dfaee456caab6695ab7870541b2be8c2b118c63752427184aad81f0e1afc61aef1f28c46f", - "0x9962118780e20fe291d10b64f28d09442a8e1b5cffd0f3dd68d980d0614050a626c616b44e9807fbee7accecae00686a", - "0xb38ddf33745e8d2ad6a991aefaf656a33c5f8cbe5d5b6b6fd03bd962153d8fd0e01b5f8f96d80ae53ab28d593ab1d4e7", - "0x857dc12c0544ff2c0c703761d901aba636415dee45618aba2e3454ff9cbc634a85c8b05565e88520ff9be2d097c8b2b1", - "0xa80d465c3f8cc63af6d74a6a5086b626c1cb4a8c0fee425964c3bd203d9d7094e299f81ce96d58afc20c8c9a029d9dae", - "0x89e1c8fbde8563763be483123a3ed702efac189c6d8ab4d16c85e74bbaf856048cc42d5d6e138633a38572ba5ec3f594", - "0x893a594cf495535f6d216508f8d03c317dcf03446668cba688da90f52d0111ac83d76ad09bf5ea47056846585ee5c791", - "0xaadbd8be0ae452f7f9450c7d2957598a20cbf10139a4023a78b4438172d62b18b0de39754dd2f8862dbd50a3a0815e53", - "0xae7d39670ecca3eb6db2095da2517a581b0e8853bdfef619b1fad9aacd443e7e6a40f18209fadd44038a55085c5fe8b2", - "0x866ef241520eacb6331593cfcb206f7409d2f33d04542e6e52cba5447934e02d44c471f6c9a45963f9307e9809ab91d9", - "0xb1a09911ad3864678f7be79a9c3c3eb5c84a0a45f8dcb52c67148f43439aeaaa9fd3ed3471276b7e588b49d6ebe3033a", - "0xadd07b7f0dbb34049cd8feeb3c18da5944bf706871cfd9f14ff72f6c59ad217ebb1f0258b13b167851929387e4e34cfe", - "0xae048892d5c328eefbdd4fba67d95901e3c14d974bfc0a1fc68155ca9f0d59e61d7ba17c6c9948b120cf35fd26e6fee9", - "0x9185b4f3b7da0ddb4e0d0f09b8a9e0d6943a4611e43f13c3e2a767ed8592d31e0ba3ebe1914026a3627680274291f6e5", - "0xa9c022d4e37b0802284ce3b7ee9258628ab4044f0db4de53d1c3efba9de19d15d65cc5e608dbe149c21c2af47d0b07b5", - "0xb24dbd5852f8f24921a4e27013b6c3fa8885b973266cb839b9c388efad95821d5d746348179dcc07542bd0d0aefad1ce", - "0xb5fb4f279300876a539a27a441348764908bc0051ebd66dc51739807305e73db3d2f6f0f294ffb91b508ab150eaf8527", - "0xace50841e718265b290c3483ed4b0fdd1175338c5f1f7530ae9a0e75d5f80216f4de37536adcbc8d8c95982e88808cd0", - "0xb19cadcde0f63bd1a9c24bd9c2806f53c14c0b9735bf351601498408ba503ddbd2037c891041cbba47f58b8c483f3b21", - "0xb6061e63558d312eb891b97b39aa552fa218568d79ee26fe6dd5b864aea9e3216d8f2e2f3b093503be274766dac41426", - "0x89730fdb2876ab6f0fe780d695f6e12090259027e789b819956d786e977518057e5d1d7f5ab24a3ae3d5d4c97773bd2b", - "0xb6fa841e81f9f2cad0163a02a63ae96dc341f7ae803b616efc6e1da2fbea551c1b96b11ad02c4afbdf6d0cc9f23da172", - "0x8fb66187182629c861ddb6896d7ed3caf2ad050c3dba8ab8eb0d7a2c924c3d44c48d1a148f9e33fb1f061b86972f8d21", - "0x86022ac339c1f84a7fa9e05358c1a5b316b4fc0b83dbe9c8c7225dc514f709d66490b539359b084ce776e301024345fa", - "0xb50b9c321468da950f01480bb62b6edafd42f83c0001d6e97f2bd523a1c49a0e8574fb66380ea28d23a7c4d54784f9f0", - "0xa31c05f7032f30d1dac06678be64d0250a071fd655e557400e4a7f4c152be4d5c7aa32529baf3e5be7c4bd49820054f6", - "0xb95ac0848cd322684772119f5b682d90a66bbf9dac411d9d86d2c34844bbd944dbaf8e47aa41380455abd51687931a78", - "0xae4a6a5ce9553b65a05f7935e61e496a4a0f6fd8203367a2c627394c9ce1e280750297b74cdc48fd1d9a31e93f97bef4", - "0xa22daf35f6e9b05e52e0b07f7bd1dbbebd2c263033fb0e1b2c804e2d964e2f11bc0ece6aca6af079dd3a9939c9c80674", - "0x902150e0cb1f16b9b59690db35281e28998ce275acb313900da8b2d8dfd29fa1795f8ca3ff820c31d0697de29df347c1", - "0xb17b5104a5dc665cdd7d47e476153d715eb78c6e5199303e4b5445c21a7fa7cf85fe7cfd08d7570f4e84e579b005428c", - "0xa03f49b81c15433f121680aa02d734bb9e363af2156654a62bcb5b2ba2218398ccb0ff61104ea5d7df5b16ea18623b1e", - "0x802101abd5d3c88876e75a27ffc2f9ddcce75e6b24f23dba03e5201281a7bd5cc7530b6a003be92d225093ca17d3c3bb", - "0xa4d183f63c1b4521a6b52226fc19106158fc8ea402461a5cccdaa35fee93669df6a8661f45c1750cd01308149b7bf08e", - "0x8d17c22e0c8403b69736364d460b3014775c591032604413d20a5096a94d4030d7c50b9fe3240e31d0311efcf9816a47", - "0x947225acfcce5992eab96276f668c3cbe5f298b90a59f2bb213be9997d8850919e8f496f182689b5cbd54084a7332482", - "0x8df6f4ed216fc8d1905e06163ba1c90d336ab991a18564b0169623eb39b84e627fa267397da15d3ed754d1f3423bff07", - "0x83480007a88f1a36dea464c32b849a3a999316044f12281e2e1c25f07d495f9b1710b4ba0d88e9560e72433addd50bc2", - "0xb3019d6e591cf5b33eb972e49e06c6d0a82a73a75d78d383dd6f6a4269838289e6e07c245f54fed67f5c9bb0fd5e1c5f", - "0x92e8ce05e94927a9fb02debadb99cf30a26172b2705003a2c0c47b3d8002bf1060edb0f6a5750aad827c98a656b19199", - "0xac2aff801448dbbfc13cca7d603fd9c69e82100d997faf11f465323b97255504f10c0c77401e4d1890339d8b224f5803", - "0xb0453d9903d08f508ee27e577445dc098baed6cde0ac984b42e0f0efed62760bd58d5816cf1e109d204607b7b175e30c", - "0xae68dc4ba5067e825d46d2c7c67f1009ceb49d68e8d3e4c57f4bcd299eb2de3575d42ea45e8722f8f28497a6e14a1cfe", - "0xb22486c2f5b51d72335ce819bbafb7fa25eb1c28a378a658f13f9fc79cd20083a7e573248d911231b45a5cf23b561ca7", - "0x89d1201d1dbd6921867341471488b4d2fd0fc773ae1d4d074c78ae2eb779a59b64c00452c2a0255826fca6b3d03be2b1", - "0xa2998977c91c7a53dc6104f5bc0a5b675e5350f835e2f0af69825db8af4aeb68435bdbcc795f3dd1f55e1dd50bc0507f", - "0xb0be4937a925b3c05056ed621910d535ccabf5ab99fd3b9335080b0e51d9607d0fd36cb5781ff340018f6acfca4a9736", - "0xaea145a0f6e0ba9df8e52e84bb9c9de2c2dc822f70d2724029b153eb68ee9c17de7d35063dcd6a39c37c59fdd12138f7", - "0x91cb4545d7165ee8ffbc74c874baceca11fdebbc7387908d1a25877ca3c57f2c5def424dab24148826832f1e880bede0", - "0xb3b579cb77573f19c571ad5eeeb21f65548d7dff9d298b8d7418c11f3e8cd3727c5b467f013cb87d6861cfaceee0d2e3", - "0xb98a1eeec2b19fecc8378c876d73645aa52fb99e4819903735b2c7a885b242787a30d1269a04bfb8573d72d9bbc5f0f0", - "0x940c1f01ed362bd588b950c27f8cc1d52276c71bb153d47f07ec85b038c11d9a8424b7904f424423e714454d5e80d1cd", - "0xaa343a8ecf09ce11599b8cf22f7279cf80f06dbf9f6d62cb05308dbbb39c46fd0a4a1240b032665fbb488a767379b91b", - "0x87c3ac72084aca5974599d3232e11d416348719e08443acaba2b328923af945031f86432e170dcdd103774ec92e988c9", - "0x91d6486eb5e61d2b9a9e742c20ec974a47627c6096b3da56209c2b4e4757f007e793ebb63b2b246857c9839b64dc0233", - "0xaebcd3257d295747dd6fc4ff910d839dd80c51c173ae59b8b2ec937747c2072fa85e3017f9060aa509af88dfc7529481", - "0xb3075ba6668ca04eff19efbfa3356b92f0ab12632dcda99cf8c655f35b7928c304218e0f9799d68ef9f809a1492ff7db", - "0x93ba7468bb325639ec2abd4d55179c69fd04eaaf39fc5340709227bbaa4ad0a54ea8b480a1a3c8d44684e3be0f8d1980", - "0xa6aef86c8c0d92839f38544d91b767c582568b391071228ff5a5a6b859c87bf4f81a7d926094a4ada1993ddbd677a920", - "0x91dcd6d14207aa569194aa224d1e5037b999b69ade52843315ca61ba26abe9a76412c9e88259bc5cf5d7b95b97d9c3bc", - "0xb3b483d31c88f78d49bd065893bc1e3d2aa637e27dedb46d9a7d60be7660ce7a10aaaa7deead362284a52e6d14021178", - "0x8e5730070acf8371461ef301cc4523e8e672aa0e3d945d438a0e0aa6bdf8cb9c685dcf38df429037b0c8aff3955c6f5b", - "0xb8c6d769890a8ee18dc4f9e917993315877c97549549b34785a92543cbeec96a08ae3a28d6e809c4aacd69de356c0012", - "0x95ca86cd384eaceaa7c077c5615736ca31f36824bd6451a16142a1edc129fa42b50724aeed7c738f08d7b157f78b569e", - "0x94df609c6d71e8eee7ab74226e371ccc77e01738fe0ef1a6424435b4570fe1e5d15797b66ed0f64eb88d4a3a37631f0e", - "0x89057b9783212add6a0690d6bb99097b182738deff2bd9e147d7fd7d6c8eacb4c219923633e6309ad993c24572289901", - "0x83a0f9f5f265c5a0e54defa87128240235e24498f20965009fef664f505a360b6fb4020f2742565dfc7746eb185bcec0", - "0x91170da5306128931349bc3ed50d7df0e48a68b8cc8420975170723ac79d8773e4fa13c5f14dc6e3fafcad78379050b1", - "0xb7178484d1b55f7e56a4cc250b6b2ec6040437d96bdfddfa7b35ed27435860f3855c2eb86c636f2911b012eb83b00db8", - "0xac0b00c4322d1e4208e09cd977b4e54d221133ff09551f75b32b0b55d0e2be80941dda26257b0e288c162e63c7e9cf68", - "0x9690ed9e7e53ed37ff362930e4096b878b12234c332fd19d5d064824084245952eda9f979e0098110d6963e468cf513e", - "0xb6fa547bb0bb83e5c5be0ed462a8783fba119041c136a250045c09d0d2af330c604331e7de960df976ff76d67f8000cd", - "0x814603907c21463bcf4e59cfb43066dfe1a50344ae04ef03c87c0f61b30836c3f4dea0851d6fa358c620045b7f9214c8", - "0x9495639e3939fad2a3df00a88603a5a180f3c3a0fe4d424c35060e2043e0921788003689887b1ed5be424d9a89bb18bb", - "0xaba4c02d8d57f2c92d5bc765885849e9ff8393d6554f5e5f3e907e5bfac041193a0d8716d7861104a4295d5a03c36b03", - "0x8ead0b56c1ca49723f94a998ba113b9058059321da72d9e395a667e6a63d5a9dac0f5717cec343f021695e8ced1f72af", - "0xb43037f7e3852c34ed918c5854cd74e9d5799eeddfe457d4f93bb494801a064735e326a76e1f5e50a339844a2f4a8ec9", - "0x99db8422bb7302199eb0ff3c3d08821f8c32f53a600c5b6fb43e41205d96adae72be5b460773d1280ad1acb806af9be8", - "0x8a9be08eae0086c0f020838925984df345c5512ff32e37120b644512b1d9d4fecf0fd30639ca90fc6cf334a86770d536", - "0x81b43614f1c28aa3713a309a88a782fb2bdfc4261dd52ddc204687791a40cf5fd6a263a8179388596582cccf0162efc2", - "0xa9f3a8b76912deb61d966c75daf5ddb868702ebec91bd4033471c8e533183df548742a81a2671de5be63a502d827437d", - "0x902e2415077f063e638207dc7e14109652e42ab47caccd6204e2870115791c9defac5425fd360b37ac0f7bd8fe7011f8", - "0xaa18e4fdc1381b59c18503ae6f6f2d6943445bd00dd7d4a2ad7e5adad7027f2263832690be30d456e6d772ad76f22350", - "0xa348b40ba3ba7d81c5d4631f038186ebd5e5f314f1ea737259151b07c3cc8cf0c6ed4201e71bcc1c22fefda81a20cde6", - "0xaa1306f7ac1acbfc47dc6f7a0cb6d03786cec8c8dc8060388ccda777bca24bdc634d03e53512c23dba79709ff64f8620", - "0x818ccfe46e700567b7f3eb400e5a35f6a5e39b3db3aa8bc07f58ace35d9ae5a242faf8dbccd08d9a9175bbce15612155", - "0xb7e3da2282b65dc8333592bb345a473f03bd6df69170055fec60222de9897184536bf22b9388b08160321144d0940279", - "0xa4d976be0f0568f4e57de1460a1729129252b44c552a69fceec44e5b97c96c711763360d11f9e5bf6d86b4976bf40d69", - "0x85d185f0397c24c2b875b09b6328a23b87982b84ee880f2677a22ff4c9a1ba9f0fea000bb3f7f66375a00d98ebafce17", - "0xb4ccbb8c3a2606bd9b87ce022704663af71d418351575f3b350d294f4efc68c26f9a2ce49ff81e6ff29c3b63d746294e", - "0x93ffd3265fddb63724dfde261d1f9e22f15ecf39df28e4d89e9fea03221e8e88b5dd9b77628bacaa783c6f91802d47cc", - "0xb1fd0f8d7a01378e693da98d03a2d2fda6b099d03454b6f2b1fa6472ff6bb092751ce6290059826b74ac0361eab00e1e", - "0xa89f440c71c561641589796994dd2769616b9088766e983c873fae0716b95c386c8483ab8a4f367b6a68b72b7456dd32", - "0xaf4fe92b01d42d03dd5d1e7fa55e96d4bbcb7bf7d4c8c197acd16b3e0f3455807199f683dcd263d74547ef9c244b35cc", - "0xa8227f6e0a344dfe76bfbe7a1861be32c4f4bed587ccce09f9ce2cf481b2dda8ae4f566154bc663d15f962f2d41761bd", - "0xa7b361663f7495939ed7f518ba45ea9ff576c4e628995b7aea026480c17a71d63fc2c922319f0502eb7ef8f14a406882", - "0x8ddcf382a9f39f75777160967c07012cfa89e67b19714a7191f0c68eaf263935e5504e1104aaabd0899348c972a8d3c6", - "0x98c95b9f6f5c91f805fb185eedd06c6fc4457d37dd248d0be45a6a168a70031715165ea20606245cbdf8815dc0ac697f", - "0x805b44f96e001e5909834f70c09be3efcd3b43632bcac5b6b66b6d227a03a758e4b1768ce2a723045681a1d34562aaeb", - "0xb0e81b07cdc45b3dca60882676d9badb99f25c461b7efe56e3043b80100bb62d29e1873ae25eb83087273160ece72a55", - "0xb0c53f0abe78ee86c7b78c82ae1f7c070bb0b9c45c563a8b3baa2c515d482d7507bb80771e60b38ac13f78b8af92b4a9", - "0xa7838ef6696a9e4d2e5dfd581f6c8d6a700467e8fd4e85adabb5f7a56f514785dd4ab64f6f1b48366f7d94728359441b", - "0x88c76f7700a1d23c30366a1d8612a796da57b2500f97f88fdf2d76b045a9d24e7426a8ffa2f4e86d3046937a841dad58", - "0xad8964baf98c1f02e088d1d9fcb3af6b1dfa44cdfe0ed2eae684e7187c33d3a3c28c38e8f4e015f9c04d451ed6f85ff6", - "0x90e9d00a098317ececaa9574da91fc149eda5b772dedb3e5a39636da6603aa007804fa86358550cfeff9be5a2cb7845e", - "0xa56ff4ddd73d9a6f5ab23bb77efa25977917df63571b269f6a999e1ad6681a88387fcc4ca3b26d57badf91b236503a29", - "0x97ad839a6302c410a47e245df84c01fb9c4dfef86751af3f9340e86ff8fc3cd52fa5ff0b9a0bd1d9f453e02ca80658a6", - "0xa4c8c44cbffa804129e123474854645107d1f0f463c45c30fd168848ebea94880f7c0c5a45183e9eb837f346270bdb35", - "0xa72e53d0a1586d736e86427a93569f52edd2f42b01e78aee7e1961c2b63522423877ae3ac1227a2cf1e69f8e1ff15bc3", - "0x8559f88a7ef13b4f09ac82ae458bbae6ab25671cfbf52dae7eac7280d6565dd3f0c3286aec1a56a8a16dc3b61d78ce47", - "0x8221503f4cdbed550876c5dc118a3f2f17800c04e8be000266633c83777b039a432d576f3a36c8a01e8fd18289ebc10b", - "0x99bfbe5f3e46d4d898a578ba86ed26de7ed23914bd3bcdf3c791c0bcd49398a52419077354a5ab75cea63b6c871c6e96", - "0xaa134416d8ff46f2acd866c1074af67566cfcf4e8be8d97329dfa0f603e1ff208488831ce5948ac8d75bfcba058ddcaa", - "0xb02609d65ebfe1fe8e52f21224a022ea4b5ea8c1bd6e7b9792eed8975fc387cdf9e3b419b8dd5bcce80703ab3a12a45f", - "0xa4f14798508698fa3852e5cac42a9db9797ecee7672a54988aa74037d334819aa7b2ac7b14efea6b81c509134a6b7ad2", - "0x884f01afecbcb987cb3e7c489c43155c416ed41340f61ecb651d8cba884fb9274f6d9e7e4a46dd220253ae561614e44c", - "0xa05523c9e71dce1fe5307cc71bd721feb3e1a0f57a7d17c7d1c9fb080d44527b7dbaa1f817b1af1c0b4322e37bc4bb1e", - "0x8560aec176a4242b39f39433dd5a02d554248c9e49d3179530815f5031fee78ba9c71a35ceeb2b9d1f04c3617c13d8f0", - "0x996aefd402748d8472477cae76d5a2b92e3f092fc834d5222ae50194dd884c9fb8b6ed8e5ccf8f6ed483ddbb4e80c747", - "0x8fd09900320000cbabc40e16893e2fcf08815d288ec19345ad7b6bb22f7d78a52b6575a3ca1ca2f8bc252d2eafc928ec", - "0x939e51f73022bc5dc6862a0adf8fb8a3246b7bfb9943cbb4b27c73743926cc20f615a036c7e5b90c80840e7f1bfee0e7", - "0xa0a6258700cadbb9e241f50766573bf9bdb7ad380b1079dc3afb4054363d838e177b869cad000314186936e40359b1f2", - "0x972699a4131c8ed27a2d0e2104d54a65a7ff1c450ad9da3a325c662ab26869c21b0a84d0700b98c8b5f6ce3b746873d7", - "0xa454c7fe870cb8aa6491eafbfb5f7872d6e696033f92e4991d057b59d70671f2acdabef533e229878b60c7fff8f748b1", - "0xa167969477214201f09c79027b10221e4707662e0c0fde81a0f628249f2f8a859ce3d30a7dcc03b8ecca8f7828ad85c7", - "0x8ff6b7265175beb8a63e1dbf18c9153fb2578c207c781282374f51b40d57a84fd2ef2ea2b9c6df4a54646788a62fd17f", - "0xa3d7ebeccde69d73d8b3e76af0da1a30884bb59729503ff0fb0c3bccf9221651b974a6e72ea33b7956fc3ae758226495", - "0xb71ef144c9a98ce5935620cb86c1590bd4f48e5a2815d25c0cdb008fde628cf628c31450d3d4f67abbfeb16178a74cfd", - "0xb5e0a16d115134f4e2503990e3f2035ed66b9ccf767063fe6747870d97d73b10bc76ed668550cb82eedc9a2ca6f75524", - "0xb30ffaaf94ee8cbc42aa2c413175b68afdb207dbf351fb20be3852cb7961b635c22838da97eaf43b103aff37e9e725cc", - "0x98aa7d52284f6c1f22e272fbddd8c8698cf8f5fbb702d5de96452141fafb559622815981e50b87a72c2b1190f59a7deb", - "0x81fbacda3905cfaf7780bb4850730c44166ed26a7c8d07197a5d4dcd969c09e94a0461638431476c16397dd7bdc449f9", - "0x95e47021c1726eac2e5853f570d6225332c6e48e04c9738690d53e07c6b979283ebae31e2af1fc9c9b3e59f87e5195b1", - "0xac024a661ba568426bb8fce21780406537f518075c066276197300841e811860696f7588188bc01d90bace7bc73d56e3", - "0xa4ebcaf668a888dd404988ab978594dee193dad2d0aec5cdc0ccaf4ec9a7a8228aa663db1da8ddc52ec8472178e40c32", - "0xa20421b8eaf2199d93b083f2aff37fb662670bd18689d046ae976d1db1fedd2c2ff897985ecc6277b396db7da68bcb27", - "0x8bc33d4b40197fd4d49d1de47489d10b90d9b346828f53a82256f3e9212b0cbc6930b895e879da9cec9fedf026aadb3e", - "0xaaafdd1bec8b757f55a0433eddc0a39f818591954fd4e982003437fcceb317423ad7ee74dbf17a2960380e7067a6b4e2", - "0xaad34277ebaed81a6ec154d16736866f95832803af28aa5625bf0461a71d02b1faba02d9d9e002be51c8356425a56867", - "0x976e9c8b150d08706079945bd0e84ab09a648ecc6f64ded9eb5329e57213149ae409ae93e8fbd8eda5b5c69f5212b883", - "0x8097fae1653247d2aed4111533bc378171d6b2c6d09cbc7baa9b52f188d150d645941f46d19f7f5e27b7f073c1ebd079", - "0x83905f93b250d3184eaba8ea7d727c4464b6bdb027e5cbe4f597d8b9dc741dcbea709630bd4fd59ce24023bec32fc0f3", - "0x8095030b7045cff28f34271386e4752f9a9a0312f8df75de4f424366d78534be2b8e1720a19cb1f9a2d21105d790a225", - "0xa7b7b73a6ae2ed1009c49960374b0790f93c74ee03b917642f33420498c188a169724945a975e5adec0a1e83e07fb1b2", - "0x856a41c54df393b6660b7f6354572a4e71c8bfca9cabaffb3d4ef2632c015e7ee2bc10056f3eccb3dbed1ad17d939178", - "0xa8f7a55cf04b38cd4e330394ee6589da3a07dc9673f74804fdf67b364e0b233f14aec42e783200a2e4666f7c5ff62490", - "0x82c529f4e543c6bca60016dc93232c115b359eaee2798a9cf669a654b800aafe6ab4ba58ea8b9cdda2b371c8d62fa845", - "0x8caab020c1baddce77a6794113ef1dfeafc5f5000f48e97f4351b588bf02f1f208101745463c480d37f588d5887e6d8c", - "0x8fa91b3cc400f48b77b6fd77f3b3fbfb3f10cdff408e1fd22d38f77e087b7683adad258804409ba099f1235b4b4d6fea", - "0x8aa02787663d6be9a35677d9d8188b725d5fcd770e61b11b64e3def8808ea5c71c0a9afd7f6630c48634546088fcd8e2", - "0xb5635b7b972e195cab878b97dea62237c7f77eb57298538582a330b1082f6207a359f2923864630136d8b1f27c41b9aa", - "0x8257bb14583551a65975946980c714ecd6e5b629672bb950b9caacd886fbd22704bc9e3ba7d30778adab65dc74f0203a", - "0xab5fe1cd12634bfa4e5c60d946e2005cbd38f1063ec9a5668994a2463c02449a0a185ef331bd86b68b6e23a8780cb3ba", - "0xa7d3487da56cda93570cc70215d438204f6a2709bfb5fda6c5df1e77e2efc80f4235c787e57fbf2c74aaff8cbb510a14", - "0xb61cff7b4c49d010e133319fb828eb900f8a7e55114fc86b39c261a339c74f630e1a7d7e1350244ada566a0ff3d46c4b", - "0x8d4d1d55d321d278db7a85522ccceca09510374ca81d4d73e3bb5249ace7674b73900c35a531ec4fa6448fabf7ad00dc", - "0x966492248aee24f0f56c8cfca3c8ec6ba3b19abb69ae642041d4c3be8523d22c65c4dafcab4c58989ccc4e0bd2f77919", - "0xb20c320a90cb220b86e1af651cdc1e21315cd215da69f6787e28157172f93fc8285dcd59b039c626ed8ca4633cba1a47", - "0xaae9e6b22f018ceb5c0950210bb8182cb8cb61014b7e14581a09d36ebd1bbfebdb2b82afb7fdb0cf75e58a293d9c456d", - "0x875547fb67951ad37b02466b79f0c9b985ccbc500cfb431b17823457dc79fb9597ec42cd9f198e15523fcd88652e63a4", - "0x92afce49773cb2e20fb21e4f86f18e0959ebb9c33361547ddb30454ee8e36b1e234019cbdca0e964cb292f7f77df6b90", - "0x8af85343dfe1821464c76ba11c216cbef697b5afc69c4d821342e55afdac047081ec2e3f7b09fc14b518d9a23b78c003", - "0xb7de4a1648fd63f3a918096ea669502af5357438e69dac77cb8102b6e6c15c76e033cfaa80dafc806e535ede5c1a20aa", - "0xac80e9b545e8bd762951d96c9ce87f629d01ffcde07efc2ef7879ca011f1d0d8a745abf26c9d452541008871304fac00", - "0xa4cf0f7ed724e481368016c38ea5816698a5f68eb21af4d3c422d2ba55f96a33e427c2aa40de1b56a7cfac7f7cf43ab0", - "0x899b0a678bb2db2cae1b44e75a661284844ebcdd87abf308fedeb2e4dbe5c5920c07db4db7284a7af806a2382e8b111a", - "0xaf0588a2a4afce2b1b13c1230816f59e8264177e774e4a341b289a101dcf6af813638fed14fb4d09cb45f35d5d032609", - "0xa4b8df79e2be76e9f5fc5845f06fe745a724cf37c82fcdb72719b77bdebea3c0e763f37909373e3a94480cc5e875cba0", - "0x83e42c46d88930c8f386b19fd999288f142d325e2ebc86a74907d6d77112cb0d449bc511c95422cc810574031a8cbba9", - "0xb5e39534070de1e5f6e27efbdd3dc917d966c2a9b8cf2d893f964256e95e954330f2442027dc148c776d63a95bcde955", - "0x958607569dc28c075e658cd4ae3927055c6bc456eef6212a6fea8205e48ed8777a8064f584cda38fe5639c371e2e7fba", - "0x812adf409fa63575113662966f5078a903212ffb65c9b0bbe62da0f13a133443a7062cb8fd70f5e5dd5559a32c26d2c8", - "0xa679f673e5ce6a3cce7fa31f22ee3785e96bcb55e5a776e2dd3467bef7440e3555d1a9b87cb215e86ee9ed13a090344b", - "0xafedbb34508b159eb25eb2248d7fe328f86ef8c7d84c62d5b5607d74aae27cc2cc45ee148eb22153b09898a835c58df4", - "0xb75505d4f6b67d31e665cfaf5e4acdb5838ae069166b7fbcd48937c0608a59e40a25302fcc1873d2e81c1782808c70f0", - "0xb62515d539ec21a155d94fc00ea3c6b7e5f6636937bce18ed5b618c12257fb82571886287fd5d1da495296c663ebc512", - "0xab8e1a9446bbdd588d1690243b1549d230e6149c28f59662b66a8391a138d37ab594df38e7720fae53217e5c3573b5be", - "0xb31e8abf4212e03c3287bb2c0a153065a7290a16764a0bac8f112a72e632185a654bb4e88fdd6053e6c7515d9719fadb", - "0xb55165477fe15b6abd2d0f4fddaa9c411710dcc4dd712daba3d30e303c9a3ee5415c256f9dc917ecf18c725b4dbab059", - "0xa0939d4f57cacaae549b78e87cc234de4ff6a35dc0d9cd5d7410abc30ebcd34c135e008651c756e5a9d2ca79c40ef42b", - "0x8cf10e50769f3443340844aad4d56ec790850fed5a41fcbd739abac4c3015f0a085a038fbe7fae9f5ad899cce5069f6b", - "0x924055e804d82a99ea4bb160041ea4dc14b568abf379010bc1922fde5d664718c31d103b8b807e3a1ae809390e708c73", - "0x8ec0f9d26f71b0f2e60a179e4fd1778452e2ffb129d50815e5d7c7cb9415fa69ae5890578086e8ef6bfde35ad2a74661", - "0x98c7f12b15ec4426b59f737f73bf5faea4572340f4550b7590dfb7f7ffedb2372e3e555977c63946d579544c53210ad0", - "0x8a935f7a955c78f69d66f18eee0092e5e833fa621781c9581058e219af4d7ceee48b84e472e159dda6199715fb2f9acf", - "0xb78d4219f95a2dbfaa7d0c8a610c57c358754f4f43c2af312ab0fe8f10a5f0177e475332fb8fd23604e474fc2abeb051", - "0x8d086a14803392b7318c28f1039a17e3cfdcece8abcaca3657ec3d0ac330842098a85c0212f889fabb296dfb133ce9aa", - "0xa53249f417aac82f2c2a50c244ce21d3e08a5e5a8bd33bec2a5ab0d6cd17793e34a17edfa3690899244ce201e2fb9986", - "0x8619b0264f9182867a1425be514dc4f1ababc1093138a728a28bd7e4ecc99b9faaff68c23792264bc6e4dce5f52a5c52", - "0x8c171edbbbde551ec19e31b2091eb6956107dd9b1f853e1df23bff3c10a3469ac77a58335eee2b79112502e8e163f3de", - "0xa9d19ec40f0ca07c238e9337c6d6a319190bdba2db76fb63902f3fb459aeeb50a1ac30db5b25ee1b4201f3ca7164a7f4", - "0xb9c6ec14b1581a03520b8d2c1fbbc31fb8ceaef2c0f1a0d0080b6b96e18442f1734bea7ef7b635d787c691de4765d469", - "0x8cb437beb4cfa013096f40ccc169a713dc17afee6daa229a398e45fd5c0645a9ad2795c3f0cd439531a7151945d7064d", - "0xa6e8740cc509126e146775157c2eb278003e5bb6c48465c160ed27888ca803fa12eee1f6a8dd7f444f571664ed87fdc1", - "0xb75c1fecc85b2732e96b3f23aefb491dbd0206a21d682aee0225838dc057d7ed3b576176353e8e90ae55663f79e986e4", - "0xad8d249b0aea9597b08358bce6c77c1fd552ef3fbc197d6a1cfe44e5e6f89b628b12a6fb04d5dcfcbacc51f46e4ae7bb", - "0xb998b2269932cbd58d04b8e898d373ac4bb1a62e8567484f4f83e224061bc0f212459f1daae95abdbc63816ae6486a55", - "0x827988ef6c1101cddc96b98f4a30365ff08eea2471dd949d2c0a9b35c3bbfa8c07054ad1f4c88c8fbf829b20bb5a9a4f", - "0x8692e638dd60babf7d9f2f2d2ce58e0ac689e1326d88311416357298c6a2bffbfebf55d5253563e7b3fbbf5072264146", - "0xa685d75b91aea04dbc14ab3c1b1588e6de96dae414c8e37b8388766029631b28dd860688079b12d09cd27f2c5af11adf", - "0xb57eced93eec3371c56679c259b34ac0992286be4f4ff9489d81cf9712403509932e47404ddd86f89d7c1c3b6391b28c", - "0xa1c8b4e42ebcbd8927669a97f1b72e236fb19249325659e72be7ddaaa1d9e81ca2abb643295d41a8c04a2c01f9c0efd7", - "0x877c33de20d4ed31674a671ba3e8f01a316581e32503136a70c9c15bf0b7cb7b1cba6cd4eb641fad165fb3c3c6c235fd", - "0xa2a469d84ec478da40838f775d11ad38f6596eb41caa139cc190d6a10b5108c09febae34ffdafac92271d2e73c143693", - "0x972f817caedb254055d52e963ed28c206848b6c4cfdb69dbc961c891f8458eaf582a6d4403ce1177d87bc2ea410ef60a", - "0xaccbd739e138007422f28536381decc54bb6bd71d93edf3890e54f9ef339f83d2821697d1a4ac1f5a98175f9a9ecb9b5", - "0x8940f8772e05389f823b62b3adc3ed541f91647f0318d7a0d3f293aeeb421013de0d0a3664ea53dd24e5fbe02d7efef6", - "0x8ecce20f3ef6212edef07ec4d6183fda8e0e8cad2c6ccd0b325e75c425ee1faba00b5c26b4d95204238931598d78f49d", - "0x97cc72c36335bd008afbed34a3b0c7225933faba87f7916d0a6d2161e6f82e0cdcda7959573a366f638ca75d30e9dab1", - "0x9105f5de8699b5bdb6bd3bb6cc1992d1eac23929c29837985f83b22efdda92af64d9c574aa9640475087201bbbe5fd73", - "0x8ffb33c4f6d05c413b9647eb6933526a350ed2e4278ca2ecc06b0e8026d8dbe829c476a40e45a6df63a633090a3f82ef", - "0x8bfc6421fdc9c2d2aaa68d2a69b1a2728c25b84944cc3e6a57ff0c94bfd210d1cbf4ff3f06702d2a8257024d8be7de63", - "0xa80e1dc1dddfb41a70220939b96dc6935e00b32fb8be5dff4eed1f1c650002ff95e4af481c43292e3827363b7ec4768a", - "0x96f714ebd54617198bd636ba7f7a7f8995a61db20962f2165078d9ed8ee764d5946ef3cbdc7ebf8435bb8d5dd4c1deac", - "0x8cdb0890e33144d66391d2ae73f5c71f5a861f72bc93bff6cc399fc25dd1f9e17d8772592b44593429718784802ac377", - "0x8ccf9a7f80800ee770b92add734ed45a73ecc31e2af0e04364eefc6056a8223834c7c0dc9dfc52495bdec6e74ce69994", - "0xaa0875f423bd68b5f10ba978ddb79d3b96ec093bfbac9ff366323193e339ed7c4578760fb60f60e93598bdf1e5cc4995", - "0xa9214f523957b59c7a4cb61a40251ad72aba0b57573163b0dc0f33e41d2df483fb9a1b85a5e7c080e9376c866790f8cb", - "0xb6224b605028c6673a536cc8ff9aeb94e7a22e686fda82cf16068d326469172f511219b68b2b3affb7933af0c1f80d07", - "0xb6d58968d8a017c6a34e24c2c09852f736515a2c50f37232ac6b43a38f8faa7572cc31dade543b594b61b5761c4781d0", - "0x8a97cefe5120020c38deeb861d394404e6c993c6cbd5989b6c9ebffe24f46ad11b4ba6348e2991cbf3949c28cfc3c99d", - "0x95bf046f8c3a9c0ce2634be4de3713024daec3fc4083e808903b25ce3ac971145af90686b451efcc72f6b22df0216667", - "0xa6a4e2f71b8fa28801f553231eff2794c0f10d12e7e414276995e21195abc9c2983a8997e41af41e78d19ff6fbb2680b", - "0x8e5e62a7ca9c2f58ebaab63db2ff1fb1ff0877ae94b7f5e2897f273f684ae639dff44cc65718f78a9c894787602ab26a", - "0x8542784383eec4f565fcb8b9fc2ad8d7a644267d8d7612a0f476fc8df3aff458897a38003d506d24142ad18f93554f2b", - "0xb7db68ba4616ea072b37925ec4fb39096358c2832cc6d35169e032326b2d6614479f765ae98913c267105b84afcb9bf2", - "0x8b31dbb9457d23d416c47542c786e07a489af35c4a87dadb8ee91bea5ac4a5315e65625d78dad2cf8f9561af31b45390", - "0xa8545a1d91ac17257732033d89e6b7111db8242e9c6ebb0213a88906d5ef407a2c6fdb444e29504b06368b6efb4f4839", - "0xb1bd85d29ebb28ccfb05779aad8674906b267c2bf8cdb1f9a0591dd621b53a4ee9f2942687ee3476740c0b4a7621a3ae", - "0xa2b54534e152e46c50d91fff03ae9cd019ff7cd9f4168b2fe7ac08ef8c3bbc134cadd3f9d6bd33d20ae476c2a8596c8a", - "0xb19b571ff4ae3e9f5d95acda133c455e72c9ea9973cae360732859836c0341c4c29ab039224dc5bc3deb824e031675d8", - "0x940b5f80478648bac025a30f3efeb47023ce20ee98be833948a248bca6979f206bb28fc0f17b90acf3bb4abd3d14d731", - "0x8f106b40588586ac11629b96d57808ad2808915d89539409c97414aded90b4ff23286a692608230a52bff696055ba5d6", - "0xae6bda03aa10da3d2abbc66d764ca6c8d0993e7304a1bdd413eb9622f3ca1913baa6da1e9f4f9e6cf847f14f44d6924d", - "0xa18e7796054a340ef826c4d6b5a117b80927afaf2ebd547794c400204ae2caf277692e2eabb55bc2f620763c9e9da66d", - "0x8d2d25180dc2c65a4844d3e66819ccfcf48858f0cc89e1c77553b463ec0f7feb9a4002ce26bc618d1142549b9850f232", - "0x863f413a394de42cc8166c1c75d513b91d545fff1de6b359037a742c70b008d34bf8e587afa2d62c844d0c6f0ea753e7", - "0x83cd0cf62d63475e7fcad18a2e74108499cdbf28af2113cfe005e3b5887794422da450b1944d0a986eb7e1f4c3b18f25", - "0xb4f8b350a6d88fea5ab2e44715a292efb12eb52df738c9b2393da3f1ddee68d0a75b476733ccf93642154bceb208f2b8", - "0xb3f52aaa4cd4221cb9fc45936cc67fd3864bf6d26bf3dd86aa85aa55ecfc05f5e392ecce5e7cf9406b4b1c4fce0398c8", - "0xb33137084422fb643123f40a6df2b498065e65230fc65dc31791c330e898c51c3a65ff738930f32c63d78f3c9315f85b", - "0x91452bfa75019363976bb7337fe3a73f1c10f01637428c135536b0cdc7da5ce558dae3dfc792aa55022292600814a8ef", - "0xad6ba94c787cd4361ca642c20793ea44f1f127d4de0bb4a77c7fbfebae0fcadbf28e2cb6f0c12c12a07324ec8c19761d", - "0x890aa6248b17f1501b0f869c556be7bf2b1d31a176f9978bb97ab7a6bd4138eed32467951c5ef1871944b7f620542f43", - "0x82111db2052194ee7dd22ff1eafffac0443cf969d3762cceae046c9a11561c0fdce9c0711f88ac01d1bed165f8a7cee3", - "0xb1527b71df2b42b55832f72e772a466e0fa05743aacc7814f4414e4bcc8d42a4010c9e0fd940e6f254cafedff3cd6543", - "0x922370fa49903679fc565f09c16a5917f8125e72acfeb060fcdbadbd1644eb9f4016229756019c93c6d609cda5d5d174", - "0xaa4c7d98a96cab138d2a53d4aee8ebff6ef903e3b629a92519608d88b3bbd94de5522291a1097e6acf830270e64c8ee1", - "0xb3dc21608a389a72d3a752883a382baaafc61ecc44083b832610a237f6a2363f24195acce529eb4aed4ef0e27a12b66e", - "0x94619f5de05e07b32291e1d7ab1d8b7337a2235e49d4fb5f3055f090a65e932e829efa95db886b32b153bdd05a53ec8c", - "0xade1e92722c2ffa85865d2426fb3d1654a16477d3abf580cfc45ea4b92d5668afc9d09275d3b79283e13e6b39e47424d", - "0xb7201589de7bed094911dd62fcd25c459a8e327ac447b69f541cdba30233063e5ddffad0b67e9c3e34adcffedfd0e13d", - "0x809d325310f862d6549e7cb40f7e5fc9b7544bd751dd28c4f363c724a0378c0e2adcb5e42ec8f912f5f49f18f3365c07", - "0xa79c20aa533de7a5d671c99eb9eb454803ba54dd4f2efa3c8fec1a38f8308e9905c71e9282955225f686146388506ff6", - "0xa85eeacb5e8fc9f3ed06a3fe2dc3108ab9f8c5877b148c73cf26e4e979bf5795edbe2e63a8d452565fd1176ed40402b2", - "0x97ef55662f8a1ec0842b22ee21391227540adf7708f491436044f3a2eb18c471525e78e1e14fa292507c99d74d7437c6", - "0x93110d64ed5886f3d16ce83b11425576a3a7a9bb831cd0de3f9a0b0f2270a730d68136b4ef7ff035ede004358f419b5c", - "0xac9ed0a071517f0ae4f61ce95916a90ba9a77a3f84b0ec50ef7298acdcd44d1b94525d191c39d6bd1bb68f4471428760", - "0x98abd6a02c7690f5a339adf292b8c9368dfc12e0f8069cf26a5e0ce54b4441638f5c66ea735142f3c28e00a0024267e6", - "0xb51efb73ba6d44146f047d69b19c0722227a7748b0e8f644d0fc9551324cf034c041a2378c56ce8b58d06038fb8a78de", - "0x8f115af274ef75c1662b588b0896b97d71f8d67986ae846792702c4742ab855952865ce236b27e2321967ce36ff93357", - "0xb3c4548f14d58b3ab03c222da09e4381a0afe47a72d18d50a94e0008797f78e39e99990e5b4757be62310d400746e35a", - "0xa9b1883bd5f31f909b8b1b6dcb48c1c60ed20aa7374b3ffa7f5b2ed036599b5bef33289d23c80a5e6420d191723b92f7", - "0x85d38dffd99487ae5bb41ab4a44d80a46157bbbe8ef9497e68f061721f74e4da513ccc3422936b059575975f6787c936", - "0xadf870fcb96e972c033ab7a35d28ae79ee795f82bc49c3bd69138f0e338103118d5529c53f2d72a9c0d947bf7d312af2", - "0xab4c7a44e2d9446c6ff303eb49aef0e367a58b22cc3bb27b4e69b55d1d9ee639c9234148d2ee95f9ca8079b1457d5a75", - "0xa386420b738aba2d7145eb4cba6d643d96bda3f2ca55bb11980b318d43b289d55a108f4bc23a9606fb0bccdeb3b3bb30", - "0x847020e0a440d9c4109773ecca5d8268b44d523389993b1f5e60e541187f7c597d79ebd6e318871815e26c96b4a4dbb1", - "0xa530aa7e5ca86fcd1bec4b072b55cc793781f38a666c2033b510a69e110eeabb54c7d8cbcb9c61fee531a6f635ffa972", - "0x87364a5ea1d270632a44269d686b2402da737948dac27f51b7a97af80b66728b0256547a5103d2227005541ca4b7ed04", - "0x8816fc6e16ea277de93a6d793d0eb5c15e9e93eb958c5ef30adaf8241805adeb4da8ce19c3c2167f971f61e0b361077d", - "0x8836a72d301c42510367181bb091e4be377777aed57b73c29ef2ce1d475feedd7e0f31676284d9a94f6db01cc4de81a2", - "0xb0d9d8b7116156d9dde138d28aa05a33e61f8a85839c1e9071ccd517b46a5b4b53acb32c2edd7150c15bc1b4bd8db9e3", - "0xae931b6eaeda790ba7f1cd674e53dc87f6306ff44951fa0df88d506316a5da240df9794ccbd7215a6470e6b31c5ea193", - "0x8c6d5bdf87bd7f645419d7c6444e244fe054d437ed1ba0c122fde7800603a5fadc061e5b836cb22a6cfb2b466f20f013", - "0x90d530c6d0cb654999fa771b8d11d723f54b8a8233d1052dc1e839ea6e314fbed3697084601f3e9bbb71d2b4eaa596df", - "0xb0d341a1422588c983f767b1ed36c18b141774f67ef6a43cff8e18b73a009da10fc12120938b8bba27f225bdfd3138f9", - "0xa131b56f9537f460d304e9a1dd75702ace8abd68cb45419695cb8dee76998139058336c87b7afd6239dc20d7f8f940cc", - "0xaa6c51fa28975f709329adee1bbd35d49c6b878041841a94465e8218338e4371f5cb6c17f44a63ac93644bf28f15d20f", - "0x88440fb584a99ebd7f9ea04aaf622f6e44e2b43bbb49fb5de548d24a238dc8f26c8da2ccf03dd43102bda9f16623f609", - "0x9777b8695b790e702159a4a750d5e7ff865425b95fa0a3c15495af385b91c90c00a6bd01d1b77bffe8c47d01baae846f", - "0x8b9d764ece7799079e63c7f01690c8eff00896a26a0d095773dea7a35967a8c40db7a6a74692f0118bf0460c26739af4", - "0x85808c65c485520609c9e61fa1bb67b28f4611d3608a9f7a5030ee61c3aa3c7e7dc17fff48af76b4aecee2cb0dbd22ac", - "0xad2783a76f5b3db008ef5f7e67391fda4e7e36abde6b3b089fc4835b5c339370287935af6bd53998bed4e399eda1136d", - "0x96f18ec03ae47c205cc4242ca58e2eff185c9dca86d5158817e2e5dc2207ab84aadda78725f8dc080a231efdc093b940", - "0x97de1ab6c6cc646ae60cf7b86df73b9cf56cc0cd1f31b966951ebf79fc153531af55ca643b20b773daa7cab784b832f7", - "0x870ba266a9bfa86ef644b1ef025a0f1b7609a60de170fe9508de8fd53170c0b48adb37f19397ee8019b041ce29a16576", - "0xad990e888d279ac4e8db90619d663d5ae027f994a3992c2fbc7d262b5990ae8a243e19157f3565671d1cb0de17fe6e55", - "0x8d9d5adcdd94c5ba3be4d9a7428133b42e485f040a28d16ee2384758e87d35528f7f9868de9bd23d1a42a594ce50a567", - "0x85a33ed75d514ece6ad78440e42f7fcdb59b6f4cff821188236d20edae9050b3a042ce9bc7d2054296e133d033e45022", - "0x92afd2f49a124aaba90de59be85ff269457f982b54c91b06650c1b8055f9b4b0640fd378df02a00e4fc91f7d226ab980", - "0x8c0ee09ec64bd831e544785e3d65418fe83ed9c920d9bb4d0bf6dd162c1264eb9d6652d2def0722e223915615931581c", - "0x8369bedfa17b24e9ad48ebd9c5afea4b66b3296d5770e09b00446c5b0a8a373d39d300780c01dcc1c6752792bccf5fd0", - "0x8b9e960782576a59b2eb2250d346030daa50bbbec114e95cdb9e4b1ba18c3d34525ae388f859708131984976ca439d94", - "0xb682bface862008fea2b5a07812ca6a28a58fd151a1d54c708fc2f8572916e0d678a9cb8dc1c10c0470025c8a605249e", - "0xa38d5e189bea540a824b36815fc41e3750760a52be0862c4cac68214febdc1a754fb194a7415a8fb7f96f6836196d82a", - "0xb9e7fbda650f18c7eb8b40e42cc42273a7298e65e8be524292369581861075c55299ce69309710e5b843cb884de171bd", - "0xb6657e5e31b3193874a1bace08f42faccbd3c502fb73ad87d15d18a1b6c2a146f1baa929e6f517db390a5a47b66c0acf", - "0xae15487312f84ed6265e4c28327d24a8a0f4d2d17d4a5b7c29b974139cf93223435aaebe3af918f5b4bb20911799715f", - "0x8bb4608beb06bc394e1a70739b872ce5a2a3ffc98c7547bf2698c893ca399d6c13686f6663f483894bccaabc3b9c56ad", - "0xb58ac36bc6847077584308d952c5f3663e3001af5ecf2e19cb162e1c58bd6c49510205d453cffc876ca1dc6b8e04a578", - "0x924f65ced61266a79a671ffb49b300f0ea44c50a0b4e3b02064faa99fcc3e4f6061ea8f38168ab118c5d47bd7804590e", - "0x8d67d43b8a06b0ff4fafd7f0483fa9ed1a9e3e658a03fb49d9d9b74e2e24858dc1bed065c12392037b467f255d4e5643", - "0xb4d4f87813125a6b355e4519a81657fa97c43a6115817b819a6caf4823f1d6a1169683fd68f8d025cdfa40ebf3069acb", - "0xa7fd4d2c8e7b59b8eed3d4332ae94b77a89a2616347402f880bc81bde072220131e6dbec8a605be3a1c760b775375879", - "0x8d4a7d8fa6f55a30df37bcf74952e2fa4fd6676a2e4606185cf154bdd84643fd01619f8fb8813a564f72e3f574f8ce30", - "0x8086fb88e6260e9a9c42e9560fde76315ff5e5680ec7140f2a18438f15bc2cc7d7d43bfb5880b180b738c20a834e6134", - "0x916c4c54721de03934fee6f43de50bb04c81f6f8dd4f6781e159e71c40c60408aa54251d457369d133d4ba3ed7c12cb4", - "0x902e5bf468f11ed9954e2a4a595c27e34abe512f1d6dc08bbca1c2441063f9af3dc5a8075ab910a10ff6c05c1c644a35", - "0xa1302953015e164bf4c15f7d4d35e3633425a78294406b861675667eec77765ff88472306531e5d3a4ec0a2ff0dd6a9e", - "0x87874461df3c9aa6c0fa91325576c0590f367075f2f0ecfeb34afe162c04c14f8ce9d608c37ac1adc8b9985bc036e366", - "0x84b50a8a61d3cc609bfb0417348133e698fe09a6d37357ce3358de189efcf35773d78c57635c2d26c3542b13cc371752", - "0xacaed2cff8633d12c1d12bb7270c54d65b0b0733ab084fd47f81d0a6e1e9b6f300e615e79538239e6160c566d8bb8d29", - "0x889e6a0e136372ca4bac90d1ab220d4e1cad425a710e8cdd48b400b73bb8137291ceb36a39440fa84305783b1d42c72f", - "0x90952e5becec45b2b73719c228429a2c364991cf1d5a9d6845ae5b38018c2626f4308daa322cab1c72e0f6c621bb2b35", - "0x8f5a97a801b6e9dcd66ccb80d337562c96f7914e7169e8ff0fda71534054c64bf2a9493bb830623d612cfe998789be65", - "0x84f3df8b9847dcf1d63ca470dc623154898f83c25a6983e9b78c6d2d90a97bf5e622445be835f32c1e55e6a0a562ea78", - "0x91d12095cd7a88e7f57f254f02fdb1a1ab18984871dead2f107404bcf8069fe68258c4e6f6ebd2477bddf738135400bb", - "0xb771a28bc04baef68604d4723791d3712f82b5e4fe316d7adc2fc01b935d8e644c06d59b83bcb542afc40ebafbee0683", - "0x872f6341476e387604a7e93ae6d6117e72d164e38ebc2b825bc6df4fcce815004d7516423c190c1575946b5de438c08d", - "0x90d6b4aa7d40a020cdcd04e8b016d041795961a8e532a0e1f4041252131089114a251791bf57794cadb7d636342f5d1c", - "0x899023ba6096a181448d927fed7a0fe858be4eac4082a42e30b3050ee065278d72fa9b9d5ce3bc1372d4cbd30a2f2976", - "0xa28f176571e1a9124f95973f414d5bdbf5794d41c3839d8b917100902ac4e2171eb940431236cec93928a60a77ede793", - "0x838dbe5bcd29c4e465d02350270fa0036cd46f8730b13d91e77afb7f5ed16525d0021d3b2ae173a76c378516a903e0cb", - "0x8e105d012dd3f5d20f0f1c4a7e7f09f0fdd74ce554c3032e48da8cce0a77260d7d47a454851387770f5c256fa29bcb88", - "0x8f4df0f9feeb7a487e1d138d13ea961459a6402fd8f8cabb226a92249a0d04ded5971f3242b9f90d08da5ff66da28af6", - "0xad1cfda4f2122a20935aa32fb17c536a3653a18617a65c6836700b5537122af5a8206befe9eaea781c1244c43778e7f1", - "0x832c6f01d6571964ea383292efc8c8fa11e61c0634a25fa180737cc7ab57bc77f25e614aac9a2a03d98f27b3c1c29de2", - "0x903f89cc13ec6685ac7728521898781fecb300e9094ef913d530bf875c18bcc3ceed7ed51e7b482d45619ab4b025c2e9", - "0xa03c474bb915aad94f171e8d96f46abb2a19c9470601f4c915512ec8b9e743c3938450a2a5b077b4618b9df8809e1dc1", - "0x83536c8456f306045a5f38ae4be2e350878fa7e164ea408d467f8c3bc4c2ee396bd5868008c089183868e4dfad7aa50b", - "0x88f26b4ea1b236cb326cd7ad7e2517ec8c4919598691474fe15d09cabcfc37a8d8b1b818f4d112432ee3a716b0f37871", - "0xa44324e3fe96e9c12b40ded4f0f3397c8c7ee8ff5e96441118d8a6bfad712d3ac990b2a6a23231a8f691491ac1fd480f", - "0xb0de4693b4b9f932191a21ee88629964878680152a82996c0019ffc39f8d9369bbe2fe5844b68d6d9589ace54af947e4", - "0x8e5d8ba948aea5fd26035351a960e87f0d23efddd8e13236cc8e4545a3dda2e9a85e6521efb8577e03772d3637d213d9", - "0x93efc82d2017e9c57834a1246463e64774e56183bb247c8fc9dd98c56817e878d97b05f5c8d900acf1fbbbca6f146556", - "0x8731176363ad7658a2862426ee47a5dce9434216cef60e6045fa57c40bb3ce1e78dac4510ae40f1f31db5967022ced32", - "0xb10c9a96745722c85bdb1a693100104d560433d45b9ac4add54c7646a7310d8e9b3ca9abd1039d473ae768a18e489845", - "0xa2ac374dfbb464bf850b4a2caf15b112634a6428e8395f9c9243baefd2452b4b4c61b0cb2836d8eae2d57d4900bf407e", - "0xb69fe3ded0c4f5d44a09a0e0f398221b6d1bf5dbb8bc4e338b93c64f1a3cac1e4b5f73c2b8117158030ec03787f4b452", - "0x8852cdbaf7d0447a8c6f211b4830711b3b5c105c0f316e3a6a18dcfbb9be08bd6f4e5c8ae0c3692da08a2dfa532f9d5c", - "0x93bbf6d7432a7d98ade3f94b57bf9f4da9bc221a180a370b113066dd42601bb9e09edd79e2e6e04e00423399339eebda", - "0xa80941c391f1eeafc1451c59e4775d6a383946ff22997aeaadf806542ba451d3b0f0c6864eeba954174a296efe2c1550", - "0xa045fe2bb011c2a2f71a0181a8f457a3078470fb74c628eab8b59aef69ffd0d649723bf74d6885af3f028bc5a104fb39", - "0xb9d8c35911009c4c8cad64692139bf3fc16b78f5a19980790cb6a7aea650a25df4231a4437ae0c351676a7e42c16134f", - "0x94c79501ded0cfcbab99e1841abe4a00a0252b3870e20774c3da16c982d74c501916ec28304e71194845be6e3113c7ab", - "0x900a66418b082a24c6348d8644ddb1817df5b25cb33044a519ef47cc8e1f7f1e38d2465b7b96d32ed472d2d17f8414c6", - "0xb26f45d393b8b2fcb29bdbb16323dc7f4b81c09618519ab3a39f8ee5bd148d0d9f3c0b5dfab55b5ce14a1cb9206d777b", - "0xaa1a87735fc493a80a96a9a57ca40a6d9c32702bfcaa9869ce1a116ae65d69cefe2f3e79a12454b4590353e96f8912b4", - "0xa922b188d3d0b69b4e4ea2a2aa076566962844637da12c0832105d7b31dea4a309eee15d12b7a336be3ea36fcbd3e3b7", - "0x8f3841fcf4105131d8c4d9885e6e11a46c448226401cf99356c291fadb864da9fa9d30f3a73c327f23f9fd99a11d633e", - "0x9791d1183fae270e226379af6c497e7da803ea854bb20afa74b253239b744c15f670ee808f708ede873e78d79a626c9a", - "0xa4cad52e3369491ada61bf28ada9e85de4516d21c882e5f1cd845bea9c06e0b2887b0c5527fcff6fc28acd3c04f0a796", - "0xb9ac86a900899603452bd11a7892a9bfed8054970bfcbeaa8c9d1930db891169e38d6977f5258c25734f96c8462eee3b", - "0xa3a154c28e5580656a859f4efc2f5ebfa7eaa84ca40e3f134fa7865e8581586db74992dbfa4036aa252fba103773ddde", - "0x95cc2a0c1885a029e094f5d737e3ecf4d26b99036453a8773c77e360101f9f98676ee246f6f732a377a996702d55691f", - "0x842651bbe99720438d8d4b0218feb60481280c05beb17750e9ca0d8c0599a60f873b7fbdcc7d8835ba9a6d57b16eec03", - "0x81ee54699da98f5620307893dcea8f64670609fa20e5622265d66283adeac122d458b3308c5898e6c57c298db2c8b24f", - "0xb97868b0b2bc98032d68352a535a1b341b9ff3c7af4e3a7f3ebc82d3419daa1b5859d6aedc39994939623c7cd878bd9b", - "0xb60325cd5d36461d07ef253d826f37f9ee6474a760f2fff80f9873d01fd2b57711543cdc8d7afa1c350aa753c2e33dea", - "0x8c205326c11d25a46717b780c639d89714c7736c974ae71287e3f4b02e6605ac2d9b4928967b1684f12be040b7bf2dd3", - "0x95a392d82db51e26ade6c2ccd3396d7e40aff68fa570b5951466580d6e56dda51775dce5cf3a74a7f28c3cb2eb551c4d", - "0x8f2cc8071eb56dffb70bda6dd433b556221dc8bba21c53353c865f00e7d4d86c9e39f119ea9a8a12ef583e9a55d9a6b6", - "0x9449a71af9672aaf8856896d7e3d788b22991a7103f75b08c0abbcc2bfe60fda4ed8ce502cea4511ff0ea52a93e81222", - "0x857090ab9fdb7d59632d068f3cc8cf27e61f0d8322d30e6b38e780a1f05227199b4cd746aac1311c36c659ef20931f28", - "0x98a891f4973e7d9aaf9ac70854608d4f7493dffc7e0987d7be9dd6029f6ea5636d24ef3a83205615ca1ff403750058e1", - "0xa486e1365bbc278dd66a2a25d258dc82f46b911103cb16aab3945b9c95ae87b386313a12b566df5b22322ede0afe25ad", - "0xa9a1eb399ed95d396dccd8d1ac718043446f8b979ec62bdce51c617c97a312f01376ab7fb87d27034e5f5570797b3c33", - "0xb7abc3858d7a74bb446218d2f5a037e0fae11871ed9caf44b29b69c500c1fa1dcfad64c9cdccc9d80d5e584f06213deb", - "0x8cfb09fe2e202faa4cebad932b1d35f5ca204e1c2a0c740a57812ac9a6792130d1312aabd9e9d4c58ca168bfebd4c177", - "0xa90a305c2cd0f184787c6be596fa67f436afd1f9b93f30e875f817ac2aae8bdd2e6e656f6be809467e6b3ad84adb86b1", - "0x80a9ef993c2b009ae172cc8f7ec036f5734cf4f4dfa06a7db4d54725e7fbfae5e3bc6f22687bdbb6961939d6f0c87537", - "0x848ade1901931e72b955d7db1893f07003e1708ff5d93174bac5930b9a732640f0578839203e9b77eb27965c700032d3", - "0x93fdf4697609c5ae9c33b9ca2f5f1af44abeb2b98dc4fdf732cf7388de086f410730dc384d9b7a7f447bb009653c8381", - "0x89ce3fb805aea618b5715c0d22a9f46da696b6fa86794f56fdf1d44155a33d42daf1920bcbe36cbacf3cf4c92df9cbc7", - "0x829ce2c342cf82aa469c65f724f308f7a750bd1494adc264609cd790c8718b8b25b5cab5858cf4ee2f8f651d569eea67", - "0xaf2f0cee7bf413204be8b9df59b9e4991bc9009e0d6dbe6815181df0ec2ca93ab8f4f3135b1c14d8f53d74bff0bd6f27", - "0xb87998cecf7b88cde93d1779f10a521edd5574a2fbd240102978639ec57433ba08cdb53849038a329cebbe74657268d2", - "0xa64542a1261a6ed3d720c2c3a802303aad8c4c110c95d0f12e05c1065e66f42da494792b6bfc5b9272363f3b1d457f58", - "0x86a6fd042e4f282fadf07a4bfee03fc96a3aea49f7a00f52bf249a20f1ec892326855410e61f37fbb27d9305eb2fc713", - "0x967ea5bc403b6db269682f7fd0df90659350d7e1aa66bc4fab4c9dfcd75ed0bba4b52f1cebc5f34dc8ba810793727629", - "0xa52990f9f3b8616ce3cdc2c74cd195029e6a969753dcf2d1630438700e7d6ebde36538532b3525ac516f5f2ce9dd27a3", - "0xa64f7ff870bab4a8bf0d4ef6f5c744e9bf1021ed08b4c80903c7ad318e80ba1817c3180cc45cb5a1cae1170f0241655f", - "0xb00f706fa4de1f663f021e8ad3d155e84ce6084a409374b6e6cd0f924a0a0b51bebaaaf1d228c77233a73b0a5a0df0e9", - "0x8b882cc3bff3e42babdb96df95fb780faded84887a0a9bab896bef371cdcf169d909f5658649e93006aa3c6e1146d62e", - "0x9332663ef1d1dcf805c3d0e4ce7a07d9863fb1731172e766b3cde030bf81682cc011e26b773fb9c68e0477b4ae2cfb79", - "0xa8aa8151348dbd4ef40aaeb699b71b4c4bfd3218560c120d85036d14f678f6736f0ec68e80ce1459d3d35feccc575164", - "0xa16cd8b729768f51881c213434aa28301fa78fcb554ddd5f9012ee1e4eae7b5cb3dd88d269d53146dea92d10790faf0b", - "0x86844f0ef9d37142faf3b1e196e44fbe280a3ba4189aa05c356778cb9e3b388a2bff95eed305ada8769935c9974e4c57", - "0xae2eec6b328fccf3b47bcdac32901ac2744a51beb410b04c81dea34dee4912b619466a4f5e2780d87ecefaebbe77b46d", - "0x915df4c38d301c8a4eb2dc5b1ba0ffaad67cbb177e0a80095614e9c711f4ef24a4cef133f9d982a63d2a943ba6c8669d", - "0xae6a2a4dedfc2d1811711a8946991fede972fdf2a389b282471280737536ffc0ac3a6d885b1f8bda0366eb0b229b9979", - "0xa9b628c63d08b8aba6b1317f6e91c34b2382a6c85376e8ef2410a463c6796740ae936fc4e9e0737cb9455d1daa287bd8", - "0x848e30bf7edf2546670b390d5cf9ab71f98fcb6add3c0b582cb34996c26a446dee5d1bde4fdcde4fc80c10936e117b29", - "0x907d6096c7c8c087d1808dd995d5d2b9169b3768c3f433475b50c2e2bd4b082f4d543afd8b0b0ddffa9c66222a72d51d", - "0xa59970a2493b07339124d763ac9d793c60a03354539ecbcf6035bc43d1ea6e35718202ae6d7060b7d388f483d971573c", - "0xb9cfef2af9681b2318f119d8611ff6d9485a68d8044581b1959ab1840cbca576dbb53eec17863d2149966e9feb21122f", - "0xad47271806161f61d3afa45cdfe2babceef5e90031a21779f83dc8562e6076680525b4970b2f11fe9b2b23c382768323", - "0x8e425a99b71677b04fe044625d338811fbb8ee32368a424f6ab2381c52e86ee7a6cecedf777dc97181519d41c351bc22", - "0x86b55b54d7adefc12954a9252ee23ae83efe8b5b4b9a7dc307904413e5d69868c7087a818b2833f9b004213d629be8ad", - "0xa14fda6b93923dd11e564ae4457a66f397741527166e0b16a8eb91c6701c244fd1c4b63f9dd3515193ec88fa6c266b35", - "0xa9b17c36ae6cd85a0ed7f6cabc5b47dc8f80ced605db327c47826476dc1fb8f8669aa7a7dc679fbd4ee3d8e8b4bd6a6f", - "0x82a0829469c1458d959c821148f15dacae9ea94bf56c59a6ab2d4dd8b3d16d73e313b5a3912a6c1f131d73a8f06730c4", - "0xb22d56d549a53eaef549595924bdb621ff807aa4513feedf3fdcbf7ba8b6b9cfa4481c2f67fc642db397a6b794a8b63a", - "0x974c59c24392e2cb9294006cbe3c52163e255f3bd0c2b457bdc68a6338e6d5b6f87f716854492f8d880a6b896ccf757c", - "0xb70d247ba7cad97c50b57f526c2ba915786e926a94e8f8c3eebc2e1be6f4255411b9670e382060049c8f4184302c40b2", - "0xad80201fe75ef21c3ddbd98cf23591e0d7a3ba1036dfe77785c32f44755a212c31f0ceb0a0b6f5ee9b6dc81f358d30c3", - "0x8c656e841f9bb90b9a42d425251f3fdbc022a604d75f5845f479ed4be23e02aaf9e6e56cde351dd7449c50574818a199", - "0x8b88dd3fa209d3063b7c5b058f7249ee9900fbc2287d16da61a0704a0a1d71e45d9c96e1cda7fdf9654534ec44558b22", - "0x961da00cc8750bd84d253c08f011970ae1b1158ad6778e8ed943d547bceaf52d6d5a212a7de3bf2706688c4389b827d2", - "0xa5dd379922549a956033e3d51a986a4b1508e575042b8eaa1df007aa77cf0b8c2ab23212f9c075702788fa9c53696133", - "0xac8fcfde3a349d1e93fc8cf450814e842005c545c4844c0401bc80e6b96cdb77f29285a14455e167c191d4f312e866cd", - "0xac63d79c799783a8466617030c59dd5a8f92ee6c5204676fd8d881ce5f7f8663bdbeb0379e480ea9b6340ab0dc88e574", - "0x805874fde19ce359041ae2bd52a39e2841acabfd31f965792f2737d7137f36d4e4722ede8340d8c95afa6af278af8acb", - "0x8d2f323a228aa8ba7b7dc1399138f9e6b41df1a16a7069003ab8104b8b68506a45141bc5fe66acf430e23e13a545190b", - "0xa1610c721a2d9af882bb6b39bea97cff1527a3aea041d25934de080214ae77c959e79957164440686d15ab301e897d4d", - "0xaba16d29a47fc36f12b654fde513896723e2c700c4190f11b26aa4011da57737ad717daa02794aa3246e4ae5f0b0cc3a", - "0xa406db2f15fdd135f346cc4846623c47edd195e80ba8c7cb447332095314d565e4040694ca924696bb5ee7f8996ea0ba", - "0x8b30e2cd9b47d75ba57b83630e40f832249af6c058d4f490416562af451993eec46f3e1f90bc4d389e4c06abd1b32a46", - "0xaacf9eb7036e248e209adbfc3dd7ce386569ea9b312caa4b240726549db3c68c4f1c8cbf8ed5ea9ea60c7e57c9df3b8e", - "0xb20fcac63bf6f5ee638a42d7f89be847f348c085ddcbec3fa318f4323592d136c230495f188ef2022aa355cc2b0da6f9", - "0x811eff750456a79ec1b1249d76d7c1547065b839d8d4aaad860f6d4528eb5b669473dcceeeea676cddbc3980b68461b7", - "0xb52d14ae33f4ab422f953392ae76a19c618cc31afc96290bd3fe2fb44c954b5c92c4789f3f16e8793f2c0c1691ade444", - "0xa7826dafeeba0db5b66c4dfcf2b17fd7b40507a5a53ac2e42942633a2cb30b95ba1739a6e9f3b7a0e0f1ec729bf274e2", - "0x8acfd83ddf7c60dd7c8b20c706a3b972c65d336b8f9b3d907bdd8926ced271430479448100050b1ef17578a49c8fa616", - "0xaf0c69f65184bb06868029ad46f8465d75c36814c621ac20a5c0b06a900d59305584f5a6709683d9c0e4b6cd08d650a6", - "0xb6cc8588191e00680ee6c3339bd0f0a17ad8fd7f4be57d5d7075bede0ea593a19e67f3d7c1a20114894ee5bfcab71063", - "0xa82fd4f58635129dbb6cc3eb9391cf2d28400018b105fc41500fbbd12bd890b918f97d3d359c29dd3b4c4e34391dfab0", - "0x92fc544ed65b4a3625cf03c41ddff7c039bc22d22c0d59dcc00efd5438401f2606adb125a1d5de294cca216ec8ac35a3", - "0x906f67e4a32582b71f15940523c0c7ce370336935e2646bdaea16a06995256d25e99df57297e39d6c39535e180456407", - "0x97510337ea5bbd5977287339197db55c60533b2ec35c94d0a460a416ae9f60e85cee39be82abeeacd5813cf54df05862", - "0x87e6894643815c0ea48cb96c607266c5ee4f1f82ba5fe352fb77f9b6ed14bfc2b8e09e80a99ac9047dfcf62b2ae26795", - "0xb6fd55dd156622ad7d5d51b7dde75e47bd052d4e542dd6449e72411f68275775c846dde301e84613312be8c7bce58b07", - "0xb98461ac71f554b2f03a94e429b255af89eec917e208a8e60edf5fc43b65f1d17a20de3f31d2ce9f0cb573c25f2f4d98", - "0x96f0dea40ca61cefbee41c4e1fe9a7d81fbe1f49bb153d083ab70f5d0488a1f717fd28cedcf6aa18d07cce2c62801898", - "0x8d7c3ab310184f7dc34b6ce4684e4d29a31e77b09940448ea4daac730b7eb308063125d4dd229046cf11bfd521b771e0", - "0x96f0564898fe96687918bbf0a6adead99cf72e3a35ea3347e124af9d006221f8e82e5a9d2fe80094d5e8d48e610f415e", - "0xad50fcb92c2675a398cf07d4c40a579e44bf8d35f27cc330b57e54d5ea59f7d898af0f75dccfe3726e5471133d70f92b", - "0x828beed62020361689ae7481dd8f116902b522fb0c6c122678e7f949fdef70ead011e0e6bffd25678e388744e17cdb69", - "0x8349decac1ca16599eee2efc95bcaabf67631107da1d34a2f917884bd70dfec9b4b08ab7bc4379d6c73b19c0b6e54fb8", - "0xb2a6a2e50230c05613ace9e58bb2e98d94127f196f02d9dddc53c43fc68c184549ca12d713cb1b025d8260a41e947155", - "0x94ff52181aadae832aed52fc3b7794536e2a31a21fc8be3ea312ca5c695750d37f08002f286b33f4023dba1e3253ecfa", - "0xa21d56153c7e5972ee9a319501be4faff199fdf09bb821ea9ce64aa815289676c00f105e6f00311b3a5b627091b0d0fc", - "0xa27a60d219f1f0c971db73a7f563b371b5c9fc3ed1f72883b2eac8a0df6698400c9954f4ca17d7e94e44bd4f95532afb", - "0xa2fc56fae99b1f18ba5e4fe838402164ce82f8a7f3193d0bbd360c2bac07c46f9330c4c7681ffb47074c6f81ee6e7ac6", - "0xb748e530cd3afb96d879b83e89c9f1a444f54e55372ab1dcd46a0872f95ce8f49cf2363fc61be82259e04f555937ed16", - "0x8bf8993e81080c7cbba1e14a798504af1e4950b2f186ab3335b771d6acaee4ffe92131ae9c53d74379d957cb6344d9cd", - "0x96774d0ef730d22d7ab6d9fb7f90b9ead44285219d076584a901960542756700a2a1603cdf72be4708b267200f6c36a9", - "0xb47703c2ab17be1e823cc7bf3460db1d6760c0e33862c90ca058845b2ff234b0f9834ddba2efb2ee1770eb261e7d8ffd", - "0x84319e67c37a9581f8b09b5e4d4ae88d0a7fb4cbb6908971ab5be28070c3830f040b1de83ee663c573e0f2f6198640e4", - "0x96811875fa83133e0b3c0e0290f9e0e28bca6178b77fdf5350eb19344d453dbd0d71e55a0ef749025a5a2ca0ad251e81", - "0x81a423423e9438343879f2bfd7ee9f1c74ebebe7ce3cfffc8a11da6f040cc4145c3b527bd3cf63f9137e714dbcb474ef", - "0xb8c3535701ddbeec2db08e17a4fa99ba6752d32ece5331a0b8743676f421fcb14798afc7c783815484f14693d2f70db8", - "0x81aee980c876949bf40782835eec8817d535f6f3f7e00bf402ddd61101fdcd60173961ae90a1cf7c5d060339a18c959d", - "0x87e67b928d97b62c49dac321ce6cb680233f3a394d4c9a899ac2e8db8ccd8e00418e66cdfd68691aa3cb8559723b580c", - "0x8eac204208d99a2b738648df96353bbb1b1065e33ee4f6bba174b540bbbd37d205855e1f1e69a6b7ff043ca377651126", - "0x848e6e7a54ad64d18009300b93ea6f459ce855971dddb419b101f5ac4c159215626fadc20cc3b9ab1701d8f6dfaddd8b", - "0x88aa123d9e0cf309d46dddb6acf634b1ade3b090a2826d6e5e78669fa1220d6df9a6697d7778cd9b627db17eea846126", - "0x9200c2a629b9144d88a61151b661b6c4256cc5dadfd1e59a8ce17a013c2d8f7e754aabe61663c3b30f1bc47784c1f8cf", - "0xb6e1a2827c3bdda91715b0e1b1f10dd363cef337e7c80cac1f34165fc0dea7c8b69747e310563db5818390146ce3e231", - "0x92c333e694f89f0d306d54105b2a5dcc912dbe7654d9e733edab12e8537350815be472b063e56cfde5286df8922fdecb", - "0xa6fac04b6d86091158ebb286586ccfec2a95c9786e14d91a9c743f5f05546073e5e3cc717635a0c602cad8334e922346", - "0xa581b4af77feebc1fb897d49b5b507c6ad513d8f09b273328efbb24ef0d91eb740d01b4d398f2738125dacfe550330cd", - "0x81c4860cccf76a34f8a2bc3f464b7bfd3e909e975cce0d28979f457738a56e60a4af8e68a3992cf273b5946e8d7f76e2", - "0x8d1eaa09a3180d8af1cbaee673db5223363cc7229a69565f592fa38ba0f9d582cedf91e15dabd06ebbf2862fc0feba54", - "0x9832f49b0147f4552402e54593cfa51f99540bffada12759b71fcb86734be8e500eea2d8b3d036710bdf04c901432de9", - "0x8bdb0e8ec93b11e5718e8c13cb4f5de545d24829fd76161216340108098dfe5148ed25e3b57a89a516f09fa79043734d", - "0xab96f06c4b9b0b2c0571740b24fca758e6976315053a7ecb20119150a9fa416db2d3a2e0f8168b390bb063f0c1caf785", - "0xab777f5c52acd62ecf4d1f168b9cc8e1a9b45d4ec6a8ff52c583e867c2239aba98d7d3af977289b367edce03d9c2dfb1", - "0xa09d3ce5e748da84802436951acc3d3ea5d8ec1d6933505ed724d6b4b0d69973ab0930daec9c6606960f6e541e4a3ce2", - "0x8ef94f7be4d85d5ad3d779a5cf4d7b2fc3e65c52fb8e1c3c112509a4af77a0b5be994f251e5e40fabeeb1f7d5615c22b", - "0xa7406a5bf5708d9e10922d3c5c45c03ef891b8d0d74ec9f28328a72be4cdc05b4f2703fa99366426659dfca25d007535", - "0xb7f52709669bf92a2e070bfe740f422f0b7127392c5589c7f0af71bb5a8428697c762d3c0d74532899da24ea7d8695c2", - "0xb9dfb0c8df84104dbf9239ccefa4672ef95ddabb8801b74997935d1b81a78a6a5669a3c553767ec19a1281f6e570f4ff", - "0xae4d5c872156061ce9195ac640190d8d71dd406055ee43ffa6f9893eb24b870075b74c94d65bc1d5a07a6573282b5520", - "0xafe6bd3eb72266d333f1807164900dcfa02a7eb5b1744bb3c86b34b3ee91e3f05e38fa52a50dc64eeb4bdb1dd62874b8", - "0x948043cf1bc2ef3c01105f6a78dc06487f57548a3e6ef30e6ebc51c94b71e4bf3ff6d0058c72b6f3ecc37efd7c7fa8c0", - "0xa22fd17c2f7ffe552bb0f23fa135584e8d2d8d75e3f742d94d04aded2a79e22a00dfe7acbb57d44e1cdb962fb22ae170", - "0x8cd0f4e9e4fb4a37c02c1bde0f69359c43ab012eb662d346487be0c3758293f1ca560122b059b091fddce626383c3a8f", - "0x90499e45f5b9c81426f3d735a52a564cafbed72711d9279fdd88de8038e953bc48c57b58cba85c3b2e4ce56f1ddb0e11", - "0x8c30e4c034c02958384564cac4f85022ef36ab5697a3d2feaf6bf105049675bbf23d01b4b6814711d3d9271abff04cac", - "0x81f7999e7eeea30f3e1075e6780bbf054f2fb6f27628a2afa4d41872a385b4216dd5f549da7ce6cf39049b2251f27fb7", - "0xb36a7191f82fc39c283ffe53fc1f5a9a00b4c64eee7792a8443475da9a4d226cf257f226ea9d66e329af15d8f04984ec", - "0xaad4da528fdbb4db504f3041c747455baff5fcd459a2efd78f15bdf3aea0bdb808343e49df88fe7a7c8620009b7964a3", - "0x99ebd8c6dd5dd299517fb6381cfc2a7f443e6e04a351440260dd7c2aee3f1d8ef06eb6c18820b394366ecdfd2a3ce264", - "0x8873725b81871db72e4ec3643084b1cdce3cbf80b40b834b092767728605825c19b6847ad3dcf328438607e8f88b4410", - "0xb008ee2f895daa6abd35bd39b6f7901ae4611a11a3271194e19da1cdcc7f1e1ea008fe5c5440e50d2c273784541ad9c5", - "0x9036feafb4218d1f576ef89d0e99124e45dacaa6d816988e34d80f454d10e96809791d5b78f7fd65f569e90d4d7238c5", - "0x92073c1d11b168e4fa50988b0288638b4868e48bbc668c5a6dddf5499875d53be23a285acb5e4bad60114f6cf6c556e9", - "0x88c87dfcb8ba6cbfe7e1be081ccfadbd589301db2cb7c99f9ee5d7db90aa297ed1538d5a867678a763f2deede5fd219a", - "0xb42a562805c661a50f5dea63108002c0f27c0da113da6a9864c9feb5552225417c0356c4209e8e012d9bcc9d182c7611", - "0x8e6317d00a504e3b79cd47feb4c60f9df186467fe9ca0f35b55c0364db30528f5ff071109dabb2fc80bb9cd4949f0c24", - "0xb7b1ea6a88694f8d2f539e52a47466695e39e43a5eb9c6f23bca15305fe52939d8755cc3ac9d6725e60f82f994a3772f", - "0xa3cd55161befe795af93a38d33290fb642b8d80da8b786c6e6fb02d393ea308fbe87f486994039cbd7c7b390414594b6", - "0xb416d2d45b44ead3b1424e92c73c2cf510801897b05d1724ff31cbd741920cd858282fb5d6040fe1f0aa97a65bc49424", - "0x950ee01291754feace97c2e933e4681e7ddfbc4fcd079eb6ff830b0e481d929c93d0c7fb479c9939c28ca1945c40da09", - "0x869bd916aee8d86efe362a49010382674825d49195b413b4b4018e88ce43fe091b475d0b863ff0ba2259400f280c2b23", - "0x9782f38cd9c9d3385ec286ebbc7cba5b718d2e65a5890b0a5906b10a89dc8ed80d417d71d7c213bf52f2af1a1f513ea7", - "0x91cd33bc2628d096269b23faf47ee15e14cb7fdc6a8e3a98b55e1031ea0b68d10ba30d97e660f7e967d24436d40fad73", - "0x8becc978129cc96737034c577ae7225372dd855da8811ae4e46328e020c803833b5bdbc4a20a93270e2b8bd1a2feae52", - "0xa36b1d8076783a9522476ce17f799d78008967728ce920531fdaf88303321bcaf97ecaa08e0c01f77bc32e53c5f09525", - "0xb4720e744943f70467983aa34499e76de6d59aa6fadf86f6b787fdce32a2f5b535b55db38fe2da95825c51002cfe142d", - "0x91ad21fc502eda3945f6de874d1b6bf9a9a7711f4d61354f9e5634fc73f9c06ada848de15ab0a75811d3250be862827d", - "0x84f78e2ebf5fc077d78635f981712daf17e2475e14c2a96d187913006ad69e234746184a51a06ef510c9455b38acb0d7", - "0x960aa7906e9a2f11db64a26b5892ac45f20d2ccb5480f4888d89973beb6fa0dfdc06d68d241ff5ffc7f1b82b1aac242d", - "0xa99365dcd1a00c66c9db6924b97c920f5c723380e823b250db85c07631b320ec4e92e586f7319e67a522a0578f7b6d6c", - "0xa25d92d7f70cf6a88ff317cfec071e13774516da664f5fac0d4ecaa65b8bf4eb87a64a4d5ef2bd97dfae98d388dbf5cc", - "0xa7af47cd0041295798f9779020a44653007444e8b4ef0712982b06d0dcdd434ec4e1f7c5f7a049326602cb605c9105b7", - "0xaefe172eac5568369a05980931cc476bebd9dea573ba276d59b9d8c4420784299df5a910033b7e324a6c2dfc62e3ef05", - "0xb69bc9d22ffa645baa55e3e02522e9892bb2daa7fff7c15846f13517d0799766883ee09ae0869df4139150c5b843ca8a", - "0x95a10856140e493354fdd12722c7fdded21b6a2ffbc78aa2697104af8ad0c8e2206f44b0bfee077ef3949d46bbf7c16b", - "0x891f2fcd2c47cbea36b7fa715968540c233313f05333f09d29aba23c193f462ed490dd4d00969656e89c53155fdfe710", - "0xa6c33e18115e64e385c843dde34e8a228222795c7ca90bc2cc085705d609025f3351d9be61822c69035a49fb3e48f2d5", - "0xb87fb12f12c0533b005adad0487f03393ff682e13575e3cb57280c3873b2c38ba96a63c49eef7a442753d26b7005230b", - "0xb905c02ba451bfd411c135036d92c27af3b0b1c9c2f1309d6948544a264b125f39dd41afeff4666b12146c545adc168a", - "0x8b29c513f43a78951cf742231cf5457a6d9d55edf45df5481a0f299a418d94effef561b15d2c1a01d1b8067e7153fda9", - "0xb9941cccd51dc645920d2781c81a317e5a33cb7cf76427b60396735912cb6d2ca9292bb4d36b6392467d390d2c58d9f3", - "0xa8546b627c76b6ef5c93c6a98538d8593dbe21cb7673fd383d5401b0c935eea0bdeeefeb1af6ad41bad8464fb87bbc48", - "0xaa286b27de2812de63108a1aec29d171775b69538dc6198640ac1e96767c2b83a50391f49259195957d457b493b667c9", - "0xa932fb229f641e9abbd8eb2bd874015d97b6658ab6d29769fc23b7db9e41dd4f850382d4c1f08af8f156c5937d524473", - "0xa1412840fcc86e2aeec175526f2fb36e8b3b8d21a78412b7266daf81e51b3f68584ed8bd42a66a43afdd8c297b320520", - "0x89c78be9efb624c97ebca4fe04c7704fa52311d183ffd87737f76b7dadc187c12c982bd8e9ed7cd8beb48cdaafd2fd01", - "0xa3f5ddec412a5bec0ce15e3bcb41c6214c2b05d4e9135a0d33c8e50a78eaba71e0a5a6ea8b45854dec5c2ed300971fc2", - "0x9721f9cec7a68b7758e3887548790de49fa6a442d0396739efa20c2f50352a7f91d300867556d11a703866def2d5f7b5", - "0xa23764e140a87e5991573521af039630dd28128bf56eed2edbed130fd4278e090b60cf5a1dca9de2910603d44b9f6d45", - "0xa1a6494a994215e48ab55c70efa8ffdddce6e92403c38ae7e8dd2f8288cad460c6c7db526bbdf578e96ca04d9fe12797", - "0xb1705ea4cb7e074efe0405fc7b8ee2ec789af0426142f3ec81241cacd4f7edcd88e39435e4e4d8e7b1df64f3880d6613", - "0x85595d061d677116089a6064418b93eb44ff79e68d12bd9625078d3bbc440a60d0b02944eff6054433ee34710ae6fbb4", - "0x9978d5e30bedb7526734f9a1febd973a70bfa20890490e7cc6f2f9328feab1e24f991285dbc3711d892514e2d7d005ad", - "0xaf30243c66ea43b9f87a061f947f7bce745f09194f6e95f379c7582b9fead920e5d6957eaf05c12ae1282ada4670652f", - "0xa1930efb473f88001e47aa0b2b2a7566848cccf295792e4544096ecd14ee5d7927c173a8576b405bfa2eec551cd67eb5", - "0xb0446d1c590ee5a45f7e22d269c044f3848c97aec1d226b44bfd0e94d9729c28a38bccddc3a1006cc5fe4e3c24f001f2", - "0xb8a8380172df3d84b06176df916cf557966d4f2f716d3e9437e415d75b646810f79f2b2b71d857181b7fc944018883a3", - "0xa563afec25b7817bfa26e19dc9908bc00aa8fc3d19be7d6de23648701659009d10e3e4486c28e9c6b13d48231ae29ac5", - "0xa5a8e80579de886fb7d6408f542791876885947b27ad6fa99a8a26e381f052598d7b4e647b0115d4b5c64297e00ce28e", - "0x8f87afcc7ad33c51ac719bade3cd92da671a37a82c14446b0a2073f4a0a23085e2c8d31913ed2d0be928f053297de8f6", - "0xa43c455ce377e0bc434386c53c752880687e017b2f5ae7f8a15c044895b242dffde4c92fb8f8bb50b18470b17351b156", - "0x8368f8b12a5bceb1dba25adb3a2e9c7dc9b1a77a1f328e5a693f5aec195cd1e06b0fe9476b554c1c25dac6c4a5b640a3", - "0x919878b27f3671fc78396f11531c032f3e2bd132d04cc234fa4858676b15fb1db3051c0b1db9b4fc49038216f11321ce", - "0xb48cd67fb7f1242696c1f877da4bdf188eac676cd0e561fbac1a537f7b8229aff5a043922441d603a26aae56a15faee4", - "0xa3e0fdfd4d29ea996517a16f0370b54787fefe543c2fe73bfc6f9e560c1fd30dad8409859e2d7fa2d44316f24746c712", - "0x8bb156ade8faf149df7bea02c140c7e392a4742ae6d0394d880a849127943e6f26312033336d3b9fdc0092d71b5efe87", - "0x8845e5d5cc555ca3e0523244300f2c8d7e4d02aaebcb5bd749d791208856c209a6f84dd99fd55968c9f0ab5f82916707", - "0xa3e90bb5c97b07789c2f32dff1aec61d0a2220928202f5ad5355ae71f8249237799d6c8a22602e32e572cb12eabe0c17", - "0xb150bcc391884c996149dc3779ce71f15dda63a759ee9cc05871f5a8379dcb62b047098922c0f26c7bd04deb394c33f9", - "0x95cd4ad88d51f0f2efcfd0c2df802fe252bb9704d1afbf9c26a248df22d55da87bdfaf41d7bc6e5df38bd848f0b13f42", - "0xa05a49a31e91dff6a52ac8b9c2cfdd646a43f0d488253f9e3cfbce52f26667166bbb9b608fc358763a65cbf066cd6d05", - "0xa59c3c1227fdd7c2e81f5e11ef5c406da44662987bac33caed72314081e2eed66055d38137e01b2268e58ec85dd986c0", - "0xb7020ec3bd73a99861f0f1d88cf5a19abab1cbe14b7de77c9868398c84bb8e18dbbe9831838a96b6d6ca06e82451c67b", - "0x98d1ff2525e9718ee59a21d8900621636fcd873d9a564b8dceb4be80a194a0148daf1232742730b3341514b2e5a5436c", - "0x886d97b635975fc638c1b6afc493e5998ca139edba131b75b65cfe5a8e814f11bb678e0eeee5e6e5cd913ad3f2fefdfc", - "0x8fb9fd928d38d5d813b671c924edd56601dd7163b686c13f158645c2f869d9250f3859aa5463a39258c90fef0f41190a", - "0xaac35e1cd655c94dec3580bb3800bd9c2946c4a9856f7d725af15fbea6a2d8ca51c8ad2772abed60ee0e3fb9cb24046b", - "0xb8d71fa0fa05ac9e443c9b4929df9e7f09a919be679692682e614d24227e04894bfc14a5c73a62fb927fedff4a0e4aa7", - "0xa45a19f11fbbb531a704badbb813ed8088ab827c884ee4e4ebf363fa1132ff7cfa9d28be9c85b143e4f7cdbc94e7cf1a", - "0x82b54703a4f295f5471b255ab59dce00f0fe90c9fb6e06b9ee48b15c91d43f4e2ef4a96c3118aeb03b08767be58181bb", - "0x8283264c8e6d2a36558f0d145c18576b6600ff45ff99cc93eca54b6c6422993cf392668633e5df396b9331e873d457e5", - "0x8c549c03131ead601bc30eb6b9537b5d3beb7472f5bb1bcbbfd1e9f3704477f7840ab3ab7f7dc13bbbbcdff886a462d4", - "0xafbb0c520ac1b5486513587700ad53e314cb74bfbc12e0b5fbdcfdaac36d342e8b59856196a0d84a25cff6e6e1d17e76", - "0x89e4c22ffb51f2829061b3c7c1983c5c750cad158e3a825d46f7cf875677da5d63f653d8a297022b5db5845c9271b32b", - "0xafb27a86c4c2373088c96b9adf4433f2ebfc78ac5c526e9f0510670b6e4e5e0057c0a4f75b185e1a30331b9e805c1c15", - "0xa18e16b57445f88730fc5d3567bf5a176861dc14c7a08ed2996fe80eed27a0e7628501bcb78a1727c5e9ac55f29c12c4", - "0x93d61bf88b192d6825cf4e1120af1c17aa0f994d158b405e25437eaeefae049f7b721a206e7cc8a04fdc29d3c42580a1", - "0xa99f2995a2e3ed2fd1228d64166112038de2f516410aa439f4c507044e2017ea388604e2d0f7121256fadf7fbe7023d1", - "0x914fd91cffc23c32f1c6d0e98bf660925090d873367d543034654389916f65f552e445b0300b71b61b721a72e9a5983c", - "0xb42a578a7787b71f924e7def425d849c1c777156b1d4170a8ee7709a4a914e816935131afd9a0412c4cb952957b20828", - "0x82fb30590e84b9e45db1ec475a39971cf554dc01bcc7050bc89265740725c02e2be5a972168c5170c86ae83e5b0ad2c0", - "0xb14f8d8e1e93a84976289e0cf0dfa6f3a1809e98da16ee5c4932d0e1ed6bf8a07697fdd4dd86a3df84fb0003353cdcc0", - "0x85d7a2f4bda31aa2cb208b771fe03291a4ebdaf6f1dc944c27775af5caec412584c1f45bc741fca2a6a85acb3f26ad7d", - "0xaf02e56ce886ff2253bc0a68faad76f25ead84b2144e5364f3fb9b648f03a50ee9dc0b2c33ebacf7c61e9e43201ef9ef", - "0x87e025558c8a0b0abd06dfc350016847ea5ced7af2d135a5c9eec9324a4858c4b21510fb0992ec52a73447f24945058e", - "0x80fff0bafcd058118f5e7a4d4f1ae0912efeb281d2cbe4d34ba8945cc3dbe5d8baf47fb077343b90b8d895c90b297aca", - "0xb6edcf3a40e7b1c3c0148f47a263cd819e585a51ef31c2e35a29ce6f04c53e413f743034c0d998d9c00a08ba00166f31", - "0xabb87ed86098c0c70a76e557262a494ff51a30fb193f1c1a32f8e35eafa34a43fcc07aa93a3b7a077d9e35afa07b1a3d", - "0xa280214cd3bb0fb7ecd2d8bcf518cbd9078417f2b91d2533ec2717563f090fb84f2a5fcfdbbeb2a2a1f8a71cc5aa5941", - "0xa63083ca7238ea2b57d15a475963cf1d4f550d8cd76db290014a0461b90351f1f26a67d674c837b0b773b330c7c3d534", - "0xa8fa39064cb585ece5263e2f42f430206476bf261bd50f18d2b694889bd79d04d56410664cecad62690e5c5a20b3f6ff", - "0x85ba52ce9d700a5dcf6c5b00559acbe599d671ce5512467ff4b6179d7fad550567ce2a9c126a50964e3096458ea87920", - "0xb913501e1008f076e5eac6d883105174f88b248e1c9801e568fefaffa1558e4909364fc6d9512aa4d125cbd7cc895f05", - "0x8eb33b5266c8f2ed4725a6ad147a322e44c9264cf261c933cbbe230a43d47fca0f29ec39756b20561dabafadd5796494", - "0x850ebc8b661a04318c9db5a0515066e6454fa73865aa4908767a837857ecd717387f614acb614a88e075d4edc53a2f5a", - "0xa08d6b92d866270f29f4ce23a3f5d99b36b1e241a01271ede02817c8ec3f552a5c562db400766c07b104a331835c0c64", - "0x8131804c89bb3e74e9718bfc4afa547c1005ff676bd4db9604335032b203390cfa54478d45c6c78d1fe31a436ed4be9f", - "0x9106d94f23cc1eacec8316f16d6f0a1cc160967c886f51981fdb9f3f12ee1182407d2bb24e5b873de58cb1a3ee915a6b", - "0xa13806bfc3eae7a7000c9d9f1bd25e10218d4e67f59ae798b145b098bca3edad2b1040e3fc1e6310e612fb8818f459ac", - "0x8c69fbca502046cb5f6db99900a47b34117aef3f4b241690cdb3b84ca2a2fc7833e149361995dc41fa78892525bce746", - "0x852c473150c91912d58ecb05769222fa18312800c3f56605ad29eec9e2d8667b0b81c379048d3d29100ed2773bb1f3c5", - "0xb1767f6074426a00e01095dbb1795beb4e4050c6411792cbad6537bc444c3165d1058bafd1487451f9c5ddd209e0ae7e", - "0x80c600a5fe99354ce59ff0f84c760923dc8ff66a30bf47dc0a086181785ceb01f9b951c4e66df800ea6d705e8bc47055", - "0xb5cf19002fbc88a0764865b82afcb4d64a50196ea361e5c71dff7de084f4dcbbc34ec94a45cc9e0247bd51da565981aa", - "0x93e67a254ea8ce25e112d93cc927fadaa814152a2c4ec7d9a56eaa1ed47aec99b7e9916b02e64452cc724a6641729bbb", - "0xace70b32491bda18eee4a4d041c3bc9effae9340fe7e6c2f5ad975ee0874c17f1a7da7c96bd85fccff9312c518fac6e9", - "0xab4cfa02065017dd7f1aadc66f2c92f78f0f11b8597c03a5d69d82cb2eaf95a4476a836ac102908f137662472c8d914b", - "0xa40b8cd8deb8ae503d20364d64cab7c2801b7728a9646ed19c65edea6a842756a2f636283494299584ad57f4bb12cd0b", - "0x8594e11d5fc2396bcd9dbf5509ce4816dbb2b7305168021c426171fb444d111da5a152d6835ad8034542277011c26c0e", - "0x8024de98c26b4c994a66628dc304bb737f4b6859c86ded552c5abb81fd4c6c2e19d5a30beed398a694b9b2fdea1dd06a", - "0x8843f5872f33f54df8d0e06166c1857d733995f67bc54abb8dfa94ad92407cf0179bc91b0a50bbb56cdc2b350d950329", - "0xb8bab44c7dd53ef9edf497dcb228e2a41282c90f00ba052fc52d57e87b5c8ab132d227af1fcdff9a12713d1f980bcaae", - "0x982b4d7b29aff22d527fd82d2a52601d95549bfb000429bb20789ed45e5abf1f4b7416c7b7c4b79431eb3574b29be658", - "0x8eb1f571b6a1878e11e8c1c757e0bc084bab5e82e897ca9be9b7f4b47b91679a8190bf0fc8f799d9b487da5442415857", - "0xa6e74b588e5af935c8b243e888582ef7718f8714569dd4992920740227518305eb35fab674d21a5551cca44b3e511ef2", - "0xa30fc2f3a4cb4f50566e82307de73cd7bd8fe2c1184e9293c136a9b9e926a018d57c6e4f308c95b9eb8299e94d90a2a1", - "0xa50c5869ca5d2b40722c056a32f918d47e0b65ca9d7863ca7d2fb4a7b64fe523fe9365cf0573733ceaadebf20b48fff8", - "0x83bbdd32c04d17581418cf360749c7a169b55d54f2427390defd9f751f100897b2d800ce6636c5bbc046c47508d60c8c", - "0xa82904bdf614de5d8deaff688c8a5e7ac5b3431687acbcda8fa53960b7c417a39c8b2e462d7af91ce6d79260f412db8e", - "0xa4362e31ff4b05d278b033cf5eebea20de01714ae16d4115d04c1da4754269873afc8171a6f56c5104bfd7b0db93c3e7", - "0xb5b8daa63a3735581e74a021b684a1038cea77168fdb7fdf83c670c2cfabcfc3ab2fc7359069b5f9048188351aef26b5", - "0xb48d723894b7782d96ac8433c48faca1bdfa5238019c451a7f47d958097cce3ae599b876cf274269236b9d6ff8b6d7ca", - "0x98ffff6a61a3a6205c7820a91ca2e7176fab5dba02bc194c4d14942ac421cb254183c705506ab279e4f8db066f941c6c", - "0xae7db24731da2eaa6efc4f7fcba2ecc26940ddd68038dce43acf2cee15b72dc4ef42a7bfdd32946d1ed78786dd7696b3", - "0xa656db14f1de9a7eb84f6301b4acb2fbf78bfe867f48a270e416c974ab92821eb4df1cb881b2d600cfed0034ac784641", - "0xaa315f8ecba85a5535e9a49e558b15f39520fce5d4bf43131bfbf2e2c9dfccc829074f9083e8d49f405fb221d0bc4c3c", - "0x90bffba5d9ff40a62f6c8e9fc402d5b95f6077ed58d030c93e321b8081b77d6b8dac3f63a92a7ddc01585cf2c127d66c", - "0xabdd733a36e0e0f05a570d0504e73801bf9b5a25ff2c78786f8b805704997acb2e6069af342538c581144d53149fa6d3", - "0xb4a723bb19e8c18a01bd449b1bb3440ddb2017f10bb153da27deb7a6a60e9bb37619d6d5435fbb1ba617687838e01dd0", - "0x870016b4678bab3375516db0187a2108b2e840bae4d264b9f4f27dbbc7cc9cac1d7dc582d7a04d6fd1ed588238e5e513", - "0x80d33d2e20e8fc170aa3cb4f69fffb72aeafb3b5bb4ea0bc79ab55da14142ca19b2d8b617a6b24d537366e3b49cb67c3", - "0xa7ee76aec273aaae03b3b87015789289551969fb175c11557da3ab77e39ab49d24634726f92affae9f4d24003050d974", - "0x8415ea4ab69d779ebd42d0fe0c6aef531d6a465a5739e429b1fcf433ec45aa8296c527e965a20f0ec9f340c9273ea3cf", - "0x8c7662520794e8b4405d0b33b5cac839784bc86a5868766c06cbc1fa306dbe334978177417b31baf90ce7b0052a29c56", - "0x902b2abecc053a3dbdea9897ee21e74821f3a1b98b2d560a514a35799f4680322550fd3a728d4f6d64e1de98033c32b8", - "0xa05e84ed9ecab8d508d670c39f2db61ad6e08d2795ec32a3c9d0d3737ef3801618f4fc2a95f90ec2f068606131e076c5", - "0x8b9208ff4d5af0c2e3f53c9375da666773ac57197dfabb0d25b1c8d0588ba7f3c15ee9661bb001297f322ea2fbf6928b", - "0xa3c827741b34a03254d4451b5ab74a96f2b9f7fb069e2f5adaf54fd97cc7a4d516d378db5ca07da87d8566d6eef13726", - "0x8509d8a3f4a0ed378e0a1e28ea02f6bf1d7f6c819c6c2f5297c7df54c895b848f841653e32ba2a2c22c2ff739571acb8", - "0xa0ce988b7d3c40b4e496aa83a09e4b5472a2d98679622f32bea23e6d607bc7de1a5374fb162bce0549a67dad948519be", - "0xaa8a3dd12bd60e3d2e05f9c683cdcb8eab17fc59134815f8d197681b1bcf65108cba63ac5c58ee632b1e5ed6bba5d474", - "0x8b955f1d894b3aefd883fb4b65f14cd37fc2b9db77db79273f1700bef9973bf3fd123897ea2b7989f50003733f8f7f21", - "0xac79c00ddac47f5daf8d9418d798d8af89fc6f1682e7e451f71ea3a405b0d36af35388dd2a332af790bc83ca7b819328", - "0xa0d44dd2a4438b809522b130d0938c3fe7c5c46379365dbd1810a170a9aa5818e1c783470dd5d0b6d4ac7edbb7330910", - "0xa30b69e39ad43dd540a43c521f05b51b5f1b9c4eed54b8162374ae11eac25da4f5756e7b70ce9f3c92c2eeceee7431ed", - "0xac43220b762c299c7951222ea19761ab938bf38e4972deef58ed84f4f9c68c230647cf7506d7cbfc08562fcca55f0485", - "0xb28233b46a8fb424cfa386a845a3b5399d8489ceb83c8f3e05c22c934798d639c93718b7b68ab3ce24c5358339e41cbb", - "0xac30d50ee8ce59a10d4b37a3a35e62cdb2273e5e52232e202ca7d7b8d09d28958ee667fae41a7bb6cdc6fe8f6e6c9c85", - "0xb199842d9141ad169f35cc7ff782b274cbaa645fdb727761e0a89edbf0d781a15f8218b4bf4eead326f2903dd88a9cc1", - "0x85e018c7ddcad34bb8285a737c578bf741ccd547e68c734bdb3808380e12c5d4ef60fc896b497a87d443ff9abd063b38", - "0x8c856e6ba4a815bdb891e1276f93545b7072f6cb1a9aa6aa5cf240976f29f4dee01878638500a6bf1daf677b96b54343", - "0xb8a47555fa8710534150e1a3f13eab33666017be6b41005397afa647ea49708565f2b86b77ad4964d140d9ced6b4d585", - "0x8cd1f1db1b2f4c85a3f46211599caf512d5439e2d8e184663d7d50166fd3008f0e9253272f898d81007988435f715881", - "0xb1f34b14612c973a3eceb716dc102b82ab18afef9de7630172c2780776679a7706a4874e1df3eaadf541fb009731807f", - "0xb25464af9cff883b55be2ff8daf610052c02df9a5e147a2cf4df6ce63edcdee6dc535c533590084cc177da85c5dc0baa", - "0x91c3c4b658b42d8d3448ae1415d4541d02379a40dc51e36a59bd6e7b9ba3ea51533f480c7c6e8405250ee9b96a466c29", - "0x86dc027b95deb74c36a58a1333a03e63cb5ae22d3b29d114cfd2271badb05268c9d0c819a977f5e0c6014b00c1512e3a", - "0xae0e6ff58eb5fa35da5107ebeacf222ab8f52a22bb1e13504247c1dfa65320f40d97b0e6b201cb6613476687cb2f0681", - "0x8f13415d960b9d7a1d93ef28afc2223e926639b63bdefce0f85e945dfc81670a55df288893a0d8b3abe13c5708f82f91", - "0x956f67ca49ad27c1e3a68c1faad5e7baf0160c459094bf6b7baf36b112de935fdfd79fa4a9ea87ea8de0ac07272969f4", - "0x835e45e4a67df9fb51b645d37840b3a15c171d571a10b03a406dd69d3c2f22df3aa9c5cbe1e73f8d767ce01c4914ea9a", - "0x919b938e56d4b32e2667469d0bdccb95d9dda3341aa907683ee70a14bbbe623035014511c261f4f59b318b610ac90aa3", - "0x96b48182121ccd9d689bf1dfdc228175564cd68dc904a99c808a7f0053a6f636c9d953e12198bdf2ea49ea92772f2e18", - "0xac5e5a941d567fa38fdbcfa8cf7f85bb304e3401c52d88752bcd516d1fa9bac4572534ea2205e38423c1df065990790f", - "0xac0bd594fb85a8d4fc26d6df0fa81f11919401f1ecf9168b891ec7f061a2d9368af99f7fd8d9b43b2ce361e7b8482159", - "0x83d92c69ca540d298fe80d8162a1c7af3fa9b49dfb69e85c1d136a3ec39fe419c9fa78e0bb6d96878771fbd37fe92e40", - "0xb35443ae8aa66c763c2db9273f908552fe458e96696b90e41dd509c17a5c04ee178e3490d9c6ba2dc0b8f793c433c134", - "0x923b2d25aa45b2e580ffd94cbb37dc8110f340f0f011217ee1bd81afb0714c0b1d5fb4db86006cdd2457563276f59c59", - "0x96c9125d38fca1a61ac21257b696f8ac3dae78def50285e44d90ea293d591d1c58f703540a7e4e99e070afe4646bbe15", - "0xb57946b2332077fbcdcb406b811779aefd54473b5559a163cd65cb8310679b7e2028aa55c12a1401fdcfcac0e6fae29a", - "0x845daedc5cf972883835d7e13c937b63753c2200324a3b8082a6c4abb4be06c5f7c629d4abe4bfaf1d80a1f073eb6ce6", - "0x91a55dfd0efefcd03dc6dacc64ec93b8d296cb83c0ee72400a36f27246e7f2a60e73b7b70ba65819e9cfb73edb7bd297", - "0x8874606b93266455fe8fdd25df9f8d2994e927460af06f2e97dd4d2d90db1e6b06d441b72c2e76504d753badca87fb37", - "0x8ee99e6d231274ff9252c0f4e84549da173041299ad1230929c3e3d32399731c4f20a502b4a307642cac9306ccd49d3c", - "0x8836497714a525118e20849d6933bb8535fb6f72b96337d49e3133d936999c90a398a740f42e772353b5f1c63581df6d", - "0xa6916945e10628f7497a6cdc5e2de113d25f7ade3e41e74d3de48ccd4fce9f2fa9ab69645275002e6f49399b798c40af", - "0x9597706983107eb23883e0812e1a2c58af7f3499d50c6e29b455946cb9812fde1aa323d9ed30d1c0ffd455abe32303cd", - "0xa24ee89f7f515cc33bdbdb822e7d5c1877d337f3b2162303cfc2dae028011c3a267c5cb4194afa63a4856a6e1c213448", - "0x8cd25315e4318801c2776824ae6e7d543cb85ed3bc2498ba5752df2e8142b37653cf9e60104d674be3aeb0a66912e97a", - "0xb5085ecbe793180b40dbeb879f4c976eaaccaca3a5246807dced5890e0ed24d35f3f86955e2460e14fb44ff5081c07ba", - "0x960188cc0b4f908633a6840963a6fa2205fc42c511c6c309685234911c5304ef4c304e3ae9c9c69daa2fb6a73560c256", - "0xa32d0a70bf15d569b4cda5aebe3e41e03c28bf99cdd34ffa6c5d58a097f322772acca904b3a47addb6c7492a7126ebac", - "0x977f72d06ad72d4aa4765e0f1f9f4a3231d9f030501f320fe7714cc5d329d08112789fa918c60dd7fdb5837d56bb7fc6", - "0x99fa038bb0470d45852bb871620d8d88520adb701712fcb1f278fed2882722b9e729e6cdce44c82caafad95e37d0e6f7", - "0xb855e8f4fc7634ada07e83b6c719a1e37acb06394bc8c7dcab7747a8c54e5df3943915f021364bd019fdea103864e55f", - "0x88bc2cd7458532e98c596ef59ea2cf640d7cc31b4c33cef9ed065c078d1d4eb49677a67de8e6229cc17ea48bace8ee5a", - "0xaaa78a3feaa836d944d987d813f9b9741afb076e6aca1ffa42682ab06d46d66e0c07b8f40b9dbd63e75e81efa1ef7b08", - "0xb7b080420cc4d808723b98b2a5b7b59c81e624ab568ecdfdeb8bf3aa151a581b6f56e983ef1b6f909661e25db40b0c69", - "0xabee85c462ac9a2c58e54f06c91b3e5cd8c5f9ab5b5deb602b53763c54826ed6deb0d6db315a8d7ad88733407e8d35e2", - "0x994d075c1527407547590df53e9d72dd31f037c763848d1662eebd4cefec93a24328c986802efa80e038cb760a5300f5", - "0xab8777640116dfb6678e8c7d5b36d01265dfb16321abbfc277da71556a34bb3be04bc4ae90124ed9c55386d2bfb3bda0", - "0x967e3a828bc59409144463bcf883a3a276b5f24bf3cbfdd7a42343348cba91e00b46ac285835a9b91eef171202974204", - "0x875a9f0c4ffe5bb1d8da5e3c8e41d0397aa6248422a628bd60bfae536a651417d4e8a7d2fb98e13f2dad3680f7bd86d3", - "0xacaa330c3e8f95d46b1880126572b238dbb6d04484d2cd4f257ab9642d8c9fc7b212188b9c7ac9e0fd135c520d46b1bf", - "0xaceb762edbb0f0c43dfcdb01ea7a1ac5918ca3882b1e7ebc4373521742f1ed5250d8966b498c00b2b0f4d13212e6dd0b", - "0x81d072b4ad258b3646f52f399bced97c613b22e7ad76373453d80b1650c0ca87edb291a041f8253b649b6e5429bb4cff", - "0x980a47d27416ac39c7c3a0ebe50c492f8c776ea1de44d5159ac7d889b6d554357f0a77f0e5d9d0ff41aae4369eba1fc2", - "0x8b4dfd5ef5573db1476d5e43aacfb5941e45d6297794508f29c454fe50ea622e6f068b28b3debe8635cf6036007de2e3", - "0xa60831559d6305839515b68f8c3bc7abbd8212cc4083502e19dd682d56ca37c9780fc3ce4ec2eae81ab23b221452dc57", - "0x951f6b2c1848ced9e8a2339c65918e00d3d22d3e59a0a660b1eca667d18f8430d737884e9805865ef3ed0fe1638a22d9", - "0xb02e38fe790b492aa5e89257c4986c9033a8b67010fa2add9787de857d53759170fdd67715ca658220b4e14b0ca48124", - "0xa51007e4346060746e6b0e4797fc08ef17f04a34fe24f307f6b6817edbb8ce2b176f40771d4ae8a60d6152cbebe62653", - "0xa510005b05c0b305075b27b243c9d64bcdce85146b6ed0e75a3178b5ff9608213f08c8c9246f2ca6035a0c3e31619860", - "0xaaff4ef27a7a23be3419d22197e13676d6e3810ceb06a9e920d38125745dc68a930f1741c9c2d9d5c875968e30f34ab5", - "0x864522a9af9857de9814e61383bebad1ba9a881696925a0ea6bfc6eff520d42c506bbe5685a9946ed710e889765be4a0", - "0xb63258c080d13f3b7d5b9f3ca9929f8982a6960bdb1b0f8676f4dca823971601672f15e653917bf5d3746bb220504913", - "0xb51ce0cb10869121ae310c7159ee1f3e3a9f8ad498827f72c3d56864808c1f21fa2881788f19ece884d3f705cd7bd0c5", - "0x95d9cecfc018c6ed510e441cf84c712d9909c778c16734706c93222257f64dcd2a9f1bd0b400ca271e22c9c487014274", - "0x8beff4d7d0140b86380ff4842a9bda94c2d2be638e20ac68a4912cb47dbe01a261857536375208040c0554929ced1ddc", - "0x891ff49258749e2b57c1e9b8e04b12c77d79c3308b1fb615a081f2aacdfb4b39e32d53e069ed136fdbd43c53b87418fa", - "0x9625cad224e163d387738825982d1e40eeff35fe816d10d7541d15fdc4d3eee48009090f3faef4024b249205b0b28f72", - "0x8f3947433d9bd01aa335895484b540a9025a19481a1c40b4f72dd676bfcf332713714fd4010bde936eaf9470fd239ed0", - "0xa00ec2d67789a7054b53f0e858a8a232706ccc29a9f3e389df7455f1a51a2e75801fd78469a13dbc25d28399ae4c6182", - "0xa3f65884506d4a62b8775a0ea0e3d78f5f46bc07910a93cd604022154eabdf1d73591e304d61edc869e91462951975e1", - "0xa14eef4fd5dfac311713f0faa9a60415e3d30b95a4590cbf95f2033dffb4d16c02e7ceff3dcd42148a4e3bc49cce2dd4", - "0x8afa11c0eef3c540e1e3460bc759bb2b6ea90743623f88e62950c94e370fe4fd01c22b6729beba4dcd4d581198d9358f", - "0xafb05548a69f0845ffcc5f5dc63e3cdb93cd270f5655173b9a950394b0583663f2b7164ba6df8d60c2e775c1d9f120af", - "0x97f179e01a947a906e1cbeafa083960bc9f1bade45742a3afee488dfb6011c1c6e2db09a355d77f5228a42ccaa7bdf8e", - "0x8447fca4d35f74b3efcbd96774f41874ca376bf85b79b6e66c92fa3f14bdd6e743a051f12a7fbfd87f319d1c6a5ce217", - "0xa57ca39c23617cd2cf32ff93b02161bd7baf52c4effb4679d9d5166406e103bc8f3c6b5209e17c37dbb02deb8bc72ddd", - "0x9667c7300ff80f0140be002b0e36caab07aaee7cce72679197c64d355e20d96196acaf54e06e1382167d081fe6f739c1", - "0x828126bb0559ce748809b622677267ca896fa2ee76360fd2c02990e6477e06a667241379ca7e65d61a5b64b96d7867de", - "0x8b8835dea6ba8cf61c91f01a4b3d2f8150b687a4ee09b45f2e5fc8f80f208ae5d142d8e3a18153f0722b90214e60c5a7", - "0xa98e8ff02049b4da386e3ee93db23bbb13dfeb72f1cfde72587c7e6d962780b7671c63e8ac3fbaeb1a6605e8d79e2f29", - "0x87a4892a0026d7e39ef3af632172b88337cb03669dea564bcdb70653b52d744730ebb5d642e20cb627acc9dbb547a26b", - "0x877352a22fc8052878a57effc159dac4d75fe08c84d3d5324c0bab6d564cdf868f33ceee515eee747e5856b62cfa0cc7", - "0x8b801ba8e2ff019ee62f64b8cb8a5f601fc35423eb0f9494b401050103e1307dc584e4e4b21249cd2c686e32475e96c3", - "0xa9e7338d6d4d9bfec91b2af28a8ed13b09415f57a3a00e5e777c93d768fdb3f8e4456ae48a2c6626b264226e911a0e28", - "0x99c05fedf40ac4726ed585d7c1544c6e79619a0d3fb6bda75a08c7f3c0008e8d5e19ed4da48de3216135f34a15eba17c", - "0xa61cce8a1a8b13a4a650fdbec0eeea8297c352a8238fb7cac95a0df18ed16ee02a3daa2de108fa122aca733bd8ad7855", - "0xb97f37da9005b440b4cb05870dd881bf8491fe735844f2d5c8281818583b38e02286e653d9f2e7fa5e74c3c3eb616540", - "0xa72164a8554da8e103f692ac5ebb4aece55d5194302b9f74b6f2a05335b6e39beede0bf7bf8c5bfd4d324a784c5fb08c", - "0xb87e8221c5341cd9cc8bb99c10fe730bc105550f25ed4b96c0d45e6142193a1b2e72f1b3857373a659b8c09be17b3d91", - "0xa41fb1f327ef91dcb7ac0787918376584890dd9a9675c297c45796e32d6e5985b12f9b80be47fc3a8596c245f419d395", - "0x90dafa3592bdbb3465c92e2a54c2531822ba0459d45d3e7a7092fa6b823f55af28357cb51896d4ec2d66029c82f08e26", - "0xa0a9adc872ebc396557f484f1dd21954d4f4a21c4aa5eec543f5fa386fe590839735c01f236574f7ff95407cd12de103", - "0xb8c5c940d58be7538acf8672852b5da3af34f82405ef2ce8e4c923f1362f97fc50921568d0fd2fe846edfb0823e62979", - "0x85aaf06a8b2d0dac89dafd00c28533f35dbd074978c2aaa5bef75db44a7b12aeb222e724f395513b9a535809a275e30b", - "0x81f3cbe82fbc7028c26a6c1808c604c63ba023a30c9f78a4c581340008dbda5ec07497ee849a2183fcd9124f7936af32", - "0xa11ac738de75fd60f15a34209d3825d5e23385796a4c7fc5931822f3f380af977dd0f7b59fbd58eed7777a071e21b680", - "0x85a279c493de03db6fa6c3e3c1b1b29adc9a8c4effc12400ae1128da8421954fa8b75ad19e5388fe4543b76fb0812813", - "0x83a217b395d59ab20db6c4adb1e9713fc9267f5f31a6c936042fe051ce8b541f579442f3dcf0fa16b9e6de9fd3518191", - "0x83a0b86e7d4ed8f9ccdc6dfc8ff1484509a6378fa6f09ed908e6ab9d1073f03011dc497e14304e4e3d181b57de06a5ab", - "0xa63ad69c9d25704ce1cc8e74f67818e5ed985f8f851afa8412248b2df5f833f83b95b27180e9e7273833ed0d07113d3b", - "0x99b1bc2021e63b561fe44ddd0af81fcc8627a91bfeecbbc989b642bc859abc0c8d636399701aad7bbaf6a385d5f27d61", - "0xb53434adb66f4a807a6ad917c6e856321753e559b1add70824e5c1e88191bf6993fccb9b8b911fc0f473fb11743acacd", - "0x97ed3b9e6fb99bf5f945d4a41f198161294866aa23f2327818cdd55cb5dc4c1a8eff29dd8b8d04902d6cd43a71835c82", - "0xb1e808260e368a18d9d10bdea5d60223ba1713b948c782285a27a99ae50cc5fc2c53d407de07155ecc16fb8a36d744a0", - "0xa3eb4665f18f71833fec43802730e56b3ee5a357ea30a888ad482725b169d6f1f6ade6e208ee081b2e2633079b82ba7d", - "0xab8beb2c8353fc9f571c18fdd02bdb977fc883313469e1277b0372fbbb33b80dcff354ca41de436d98d2ed710faa467e", - "0xaa9071cfa971e4a335a91ad634c98f2be51544cb21f040f2471d01bb97e1df2277ae1646e1ea8f55b7ba9f5c8c599b39", - "0x80b7dbfdcaf40f0678012acc634eba44ea51181475180d9deb2050dc4f2de395289edd0223018c81057ec79b04b04c49", - "0x89623d7f6cb17aa877af14de842c2d4ab7fd576d61ddd7518b5878620a01ded40b6010de0da3cdf31d837eecf30e9847", - "0xa773bb024ae74dd24761f266d4fb27d6fd366a8634febe8235376b1ae9065c2fe12c769f1d0407867dfbe9f5272c352f", - "0x8455a561c3aaa6ba64c881a5e13921c592b3a02e968f4fb24a2243c36202795d0366d9cc1a24e916f84d6e158b7aeac7", - "0x81d8bfc4b283cf702a40b87a2b96b275bdbf0def17e67d04842598610b67ea08c804d400c3e69fa09ea001eaf345b276", - "0xb8f8f82cb11fea1c99467013d7e167ff03deb0c65a677fab76ded58826d1ba29aa7cf9fcd7763615735ea3ad38e28719", - "0x89a6a04baf9cccc1db55179e1650b1a195dd91fb0aebc197a25143f0f393524d2589975e3fbfc2547126f0bced7fd6f2", - "0xb81b2162df045390f04df07cbd0962e6b6ca94275a63edded58001a2f28b2ae2af2c7a6cba4ecd753869684e77e7e799", - "0xa3757f722776e50de45c62d9c4a2ee0f5655a512344c4cbec542d8045332806568dd626a719ef21a4eb06792ca70f204", - "0x8c5590df96ec22179a4e8786de41beb44f987a1dcc508eb341eecbc0b39236fdfad47f108f852e87179ccf4e10091e59", - "0x87502f026ed4e10167419130b88c3737635c5b9074c364e1dd247cef5ef0fc064b4ae99b187e33301e438bbd2fe7d032", - "0xaf925a2165e980ced620ff12289129fe17670a90ae0f4db9d4b39bd887ccb1f5d2514ac9ecf910f6390a8fc66bd5be17", - "0x857fca899828cf5c65d26e3e8a6e658542782fc72762b3b9c73514919f83259e0f849a9d4838b40dc905fe43024d0d23", - "0x87ffebdbfb69a9e1007ebac4ffcb4090ff13705967b73937063719aa97908986effcb7262fdadc1ae0f95c3690e3245d", - "0xa9ff6c347ac6f4c6ab993b748802e96982eaf489dc69032269568412fc9a79e7c2850dfc991b28211b3522ee4454344b", - "0xa65b3159df4ec48bebb67cb3663cd744027ad98d970d620e05bf6c48f230fa45bf17527fe726fdf705419bb7a1bb913e", - "0x84b97b1e6408b6791831997b03cd91f027e7660fd492a93d95daafe61f02427371c0e237c75706412f442991dfdff989", - "0xab761c26527439b209af0ae6afccd9340bbed5fbe098734c3145b76c5d2cd7115d9227b2eb523882b7317fbb09180498", - "0xa0479a8da06d7a69c0b0fee60df4e691c19c551f5e7da286dab430bfbcabf31726508e20d26ea48c53365a7f00a3ad34", - "0xa732dfc9baa0f4f40b5756d2e8d8937742999623477458e0bc81431a7b633eefc6f53b3b7939fe0a020018549c954054", - "0x901502436a1169ba51dc479a5abe7c8d84e0943b16bc3c6a627b49b92cd46263c0005bc324c67509edd693f28e612af1", - "0xb627aee83474e7f84d1bab9b7f6b605e33b26297ac6bbf52d110d38ba10749032bd551641e73a383a303882367af429b", - "0x95108866745760baef4a46ef56f82da6de7e81c58b10126ebd2ba2cd13d339f91303bf2fb4dd104a6956aa3b13739503", - "0x899ed2ade37236cec90056f3569bc50f984f2247792defafcceb49ad0ca5f6f8a2f06573705300e07f0de0c759289ff5", - "0xa9f5eee196d608efe4bcef9bf71c646d27feb615e21252cf839a44a49fd89da8d26a758419e0085a05b1d59600e2dc42", - "0xb36c6f68fed6e6c85f1f4a162485f24817f2843ec5cbee45a1ebfa367d44892e464949c6669f7972dc7167af08d55d25", - "0xaaaede243a9a1b6162afbc8f571a52671a5a4519b4062e3f26777664e245ba873ed13b0492c5dbf0258c788c397a0e9e", - "0x972b4fb39c31cbe127bf9a32a5cc10d621ebdd9411df5e5da3d457f03b2ab2cd1f6372d8284a4a9400f0b06ecdbfd38e", - "0x8f6ca1e110e959a4b1d9a5ce5f212893cec21db40d64d5ac4d524f352d72198f923416a850bf845bc5a22a79c0ea2619", - "0xa0f3c93b22134f66f04b2553a53b738644d1665ceb196b8494b315a4c28236fb492017e4a0de4224827c78e42f9908b7", - "0x807fb5ee74f6c8735b0b5ca07e28506214fe4047dbeb00045d7c24f7849e98706aea79771241224939cb749cf1366c7d", - "0x915eb1ff034224c0b645442cdb7d669303fdc00ca464f91aaf0b6fde0b220a3a74ff0cb043c26c9f3a5667b3fdaa9420", - "0x8fda6cef56ed33fefffa9e6ac8e6f76b1af379f89761945c63dd448801f7bb8ca970504a7105fac2f74f652ccff32327", - "0x87380cffdcffb1d0820fa36b63cc081e72187f86d487315177d4d04da4533eb19a0e2ff6115ceab528887819c44a5164", - "0x8cd89e03411a18e7f16f968b89fb500c36d47d229f6487b99e62403a980058db5925ce249206743333538adfad168330", - "0x974451b1df33522ce7056de9f03e10c70bf302c44b0741a59df3d6877d53d61a7394dcee1dd46e013d7cb9d73419c092", - "0x98c35ddf645940260c490f384a49496a7352bb8e3f686feed815b1d38f59ded17b1ad6e84a209e773ed08f7b8ff1e4c2", - "0x963f386cf944bb9b2ddebb97171b64253ea0a2894ac40049bdd86cda392292315f3a3d490ca5d9628c890cfb669f0acb", - "0x8d507712152babd6d142ee682638da8495a6f3838136088df9424ef50d5ec28d815a198c9a4963610b22e49b4cdf95e9", - "0x83d4bc6b0be87c8a4f1e9c53f257719de0c73d85b490a41f7420e777311640937320557ff2f1d9bafd1daaa54f932356", - "0x82f5381c965b7a0718441131c4d13999f4cdce637698989a17ed97c8ea2e5bdb5d07719c5f7be8688edb081b23ede0f4", - "0xa6ebecab0b72a49dfd01d69fa37a7f74d34fb1d4fef0aa10e3d6fceb9eccd671225c230af89f6eb514250e41a5f91f52", - "0x846d185bdad6e11e604df7f753b7a08a28b643674221f0e750ebdb6b86ec584a29c869e131bca868972a507e61403f6a", - "0x85a98332292acb744bd1c0fd6fdcf1f889a78a2c9624d79413ffa194cc8dfa7821a4b60cde8081d4b5f71f51168dd67f", - "0x8f7d97c3b4597880d73200d074eb813d95432306e82dafc70b580b8e08cb8098b70f2d07b4b3ac6a4d77e92d57035031", - "0x8185439c8751e595825d7053518cbe121f191846a38d4dbcb558c3f9d7a3104f3153401adaaaf27843bbe2edb504bfe3", - "0xb3c00d8ece1518fca6b1215a139b0a0e26d9cba1b3a424f7ee59f30ce800a5db967279ed60958dd1f3ee69cf4dd1b204", - "0xa2e6cb6978e883f9719c3c0d44cfe8de0cc6f644b98f98858433bea8bbe7b612c8aca5952fccce4f195f9d54f9722dc2", - "0x99663087e3d5000abbec0fbda4e7342ec38846cc6a1505191fb3f1a337cb369455b7f8531a6eb8b0f7b2c4baf83cbe2b", - "0xab0836c6377a4dbc7ca6a4d6cf021d4cd60013877314dd05f351706b128d4af6337711ed3443cb6ca976f40d74070a9a", - "0x87abfd5126152fd3bac3c56230579b489436755ea89e0566aa349490b36a5d7b85028e9fb0710907042bcde6a6f5d7e3", - "0x974ba1033f75f60e0cf7c718a57ae1da3721cf9d0fb925714c46f027632bdd84cd9e6de4cf4d00bc55465b1c5ebb7384", - "0xa607b49d73689ac64f25cec71221d30d53e781e1100d19a2114a21da6507a60166166369d860bd314acb226596525670", - "0xa7c2b0b915d7beba94954f2aa7dd08ec075813661e2a3ecca5d28a0733e59583247fed9528eb28aba55b972cdbaf06eb", - "0xb8b3123e44128cc8efbe3270f2f94e50ca214a4294c71c3b851f8cbb70cb67fe9536cf07d04bf7fe380e5e3a29dd3c15", - "0xa59a07e343b62ad6445a0859a32b58c21a593f9ddbfe52049650f59628c93715aa1f4e1f45b109321756d0eeec8a5429", - "0x94f51f8a4ed18a6030d0aaa8899056744bd0e9dc9ac68f62b00355cddab11da5da16798db75f0bfbce0e5bdfe750c0b6", - "0x97460a97ca1e1fa5ce243b81425edc0ec19b7448e93f0b55bc9785eedeeafe194a3c8b33a61a5c72990edf375f122777", - "0x8fa859a089bc17d698a7ee381f37ce9beadf4e5b44fce5f6f29762bc04f96faff5d58c48c73631290325f05e9a1ecf49", - "0xabdf38f3b20fc95eff31de5aa9ef1031abfa48f1305ee57e4d507594570401503476d3bcc493838fc24d6967a3082c7f", - "0xb8914bfb82815abb86da35c64d39ab838581bc0bf08967192697d9663877825f2b9d6fbdcf9b410463482b3731361aef", - "0xa8187f9d22b193a5f578999954d6ec9aa9b32338ccadb8a3e1ce5bad5ea361d69016e1cdfac44e9d6c54e49dd88561b9", - "0xaac262cb7cba7fd62c14daa7b39677cabc1ef0947dd06dd89cac8570006a200f90d5f0353e84f5ff03179e3bebe14231", - "0xa630ef5ece9733b8c46c0a2df14a0f37647a85e69c63148e79ffdcc145707053f9f9d305c3f1cf3c7915cb46d33abd07", - "0xb102c237cb2e254588b6d53350dfda6901bd99493a3fbddb4121d45e0b475cf2663a40d7b9a75325eda83e4ba1e68cb3", - "0x86a930dd1ddcc16d1dfa00aa292cb6c2607d42c367e470aa920964b7c17ab6232a7108d1c2c11fc40fb7496547d0bbf8", - "0xa832fdc4500683e72a96cce61e62ac9ee812c37fe03527ad4cf893915ca1962cee80e72d4f82b20c8fc0b764376635a1", - "0x88ad985f448dabb04f8808efd90f273f11f5e6d0468b5489a1a6a3d77de342992a73eb842d419034968d733f101ff683", - "0x98a8538145f0d86f7fbf9a81c9140f6095c5bdd8960b1c6f3a1716428cd9cca1bf8322e6d0af24e6169abcf7df2b0ff6", - "0x9048c6eba5e062519011e177e955a200b2c00b3a0b8615bdecdebc217559d41058d3315f6d05617be531ef0f6aef0e51", - "0x833bf225ab6fc68cdcacf1ec1b50f9d05f5410e6cdcd8d56a3081dc2be8a8d07b81534d1ec93a25c2e270313dfb99e3b", - "0xa84bcd24c3da5e537e64a811b93c91bfc84d7729b9ead7f79078989a6eb76717d620c1fad17466a0519208651e92f5ff", - "0xb7cdd0a3fbd79aed93e1b5a44ca44a94e7af5ed911e4492f332e3a5ed146c7286bde01b52276a2fcc02780d2109874dd", - "0x8a19a09854e627cb95750d83c20c67442b66b35896a476358f993ba9ac114d32c59c1b3d0b8787ee3224cf3888b56c64", - "0xa9abd5afb8659ee52ada8fa5d57e7dd355f0a7350276f6160bec5fbf70d5f99234dd179eb221c913e22a49ec6d267846", - "0x8c13c4274c0d30d184e73eaf812200094bbbd57293780bdadbceb262e34dee5b453991e7f37c7333a654fc71c69d6445", - "0xa4320d73296ff8176ce0127ca1921c450e2a9c06eff936681ebaffb5a0b05b17fded24e548454de89aca2dcf6d7a9de4", - "0xb2b8b3e15c1f645f07783e5628aba614e60157889db41d8161d977606788842b67f83f361eae91815dc0abd84e09abd5", - "0xad26c3aa35ddfddc15719b8bb6c264aaec7065e88ac29ba820eb61f220fef451609a7bb037f3722d022e6c86e4f1dc88", - "0xb8615bf43e13ae5d7b8dd903ce37190800cd490f441c09b22aa29d7a29ed2c0417b7a08ead417868f1de2589deaadd80", - "0x8d3425e1482cd1e76750a76239d33c06b3554c3c3c87c15cb7ab58b1cee86a4c5c4178b44e23f36928365a1b484bde02", - "0x806893a62e38c941a7dd6f249c83af16596f69877cc737d8f73f6b8cd93cbc01177a7a276b2b8c6b0e5f2ad864db5994", - "0x86618f17fa4b0d65496b661bbb5ba3bc3a87129d30a4b7d4f515b904f4206ca5253a41f49fd52095861e5e065ec54f21", - "0x9551915da1304051e55717f4c31db761dcdcf3a1366c89a4af800a9e99aca93a357bf928307f098e62b44a02cb689a46", - "0x8f79c4ec0ec1146cb2a523b52fe33def90d7b5652a0cb9c2d1c8808a32293e00aec6969f5b1538e3a94cd1efa3937f86", - "0xa0c03e329a707300081780f1e310671315b4c6a4cedcb29697aedfabb07a9d5df83f27b20e9c44cf6b16e39d9ded5b98", - "0x86a7cfa7c8e7ce2c01dd0baec2139e97e8e090ad4e7b5f51518f83d564765003c65968f85481bbb97cb18f005ccc7d9f", - "0xa33811770c6dfda3f7f74e6ad0107a187fe622d61b444bbd84fd7ef6e03302e693b093df76f6ab39bb4e02afd84a575a", - "0x85480f5c10d4162a8e6702b5e04f801874d572a62a130be94b0c02b58c3c59bdcd48cd05f0a1c2839f88f06b6e3cd337", - "0x8e181011564b17f7d787fe0e7f3c87f6b62da9083c54c74fd6c357a1f464c123c1d3d8ade3cf72475000b464b14e2be3", - "0x8ee178937294b8c991337e0621ab37e9ffa4ca2bdb3284065c5e9c08aad6785d50cf156270ff9daf9a9127289710f55b", - "0x8bd1e8e2d37379d4b172f1aec96f2e41a6e1393158d7a3dbd9a95c8dd4f8e0b05336a42efc11a732e5f22b47fc5c271d", - "0x8f3da353cd487c13136a85677de8cedf306faae0edec733cf4f0046f82fa4639db4745b0095ff33a9766aba50de0cbcf", - "0x8d187c1e97638df0e4792b78e8c23967dac43d98ea268ca4aabea4e0fa06cb93183fd92d4c9df74118d7cc27bf54415e", - "0xa4c992f08c2f8bac0b74b3702fb0c75c9838d2ce90b28812019553d47613c14d8ce514d15443159d700b218c5a312c49", - "0xa6fd1874034a34c3ea962a316c018d9493d2b3719bb0ec4edbc7c56b240802b2228ab49bee6f04c8a3e9f6f24a48c1c2", - "0xb2efed8e799f8a15999020900dc2c58ece5a3641c90811b86a5198e593d7318b9d53b167818ccdfbe7df2414c9c34011", - "0x995ff7de6181ddf95e3ead746089c6148da3508e4e7a2323c81785718b754d356789b902e7e78e2edc6b0cbd4ff22c78", - "0x944073d24750a9068cbd020b834afc72d2dde87efac04482b3287b40678ad07588519a4176b10f2172a2c463d063a5cd", - "0x99db4b1bb76475a6fd75289986ef40367960279524378cc917525fb6ba02a145a218c1e9caeb99332332ab486a125ac0", - "0x89fce4ecd420f8e477af4353b16faabb39e063f3f3c98fde2858b1f2d1ef6eed46f0975a7c08f233b97899bf60ccd60a", - "0x8c09a4f07a02b80654798bc63aada39fd638d3e3c4236ccd8a5ca280350c31e4a89e5f4c9aafb34116e71da18c1226b8", - "0x85325cfa7ded346cc51a2894257eab56e7488dbff504f10f99f4cd2b630d913003761a50f175ed167e8073f1b6b63fb0", - "0xb678b4fbec09a8cc794dcbca185f133578f29e354e99c05f6d07ac323be20aecb11f781d12898168e86f2e0f09aca15e", - "0xa249cfcbca4d9ba0a13b5f6aac72bf9b899adf582f9746bb2ad043742b28915607467eb794fca3704278f9136f7642be", - "0x9438e036c836a990c5e17af3d78367a75b23c37f807228362b4d13e3ddcb9e431348a7b552d09d11a2e9680704a4514f", - "0x925ab70450af28c21a488bfb5d38ac994f784cf249d7fd9ad251bb7fd897a23e23d2528308c03415074d43330dc37ef4", - "0xa290563904d5a8c0058fc8330120365bdd2ba1fdbaef7a14bc65d4961bb4217acfaed11ab82669e359531f8bf589b8db", - "0xa7e07a7801b871fc9b981a71e195a3b4ba6b6313bc132b04796a125157e78fe5c11a3a46cf731a255ac2d78a4ae78cd0", - "0xb26cd2501ee72718b0eebab6fb24d955a71f363f36e0f6dff0ab1d2d7836dab88474c0cef43a2cc32701fca7e82f7df3", - "0xa1dc3b6c968f3de00f11275092290afab65b2200afbcfa8ddc70e751fa19dbbc300445d6d479a81bda3880729007e496", - "0xa9bc213e28b630889476a095947d323b9ac6461dea726f2dc9084473ae8e196d66fb792a21905ad4ec52a6d757863e7d", - "0xb25d178df8c2df8051e7c888e9fa677fde5922e602a95e966db9e4a3d6b23ce043d7dc48a5b375c6b7c78e966893e8c3", - "0xa1c8d88d72303692eaa7adf68ea41de4febec40cc14ae551bb4012afd786d7b6444a3196b5d9d5040655a3366d96b7cd", - "0xb22bd44f9235a47118a9bbe2ba5a2ba9ec62476061be2e8e57806c1a17a02f9a51403e849e2e589520b759abd0117683", - "0xb8add766050c0d69fe81d8d9ea73e1ed05f0135d093ff01debd7247e42dbb86ad950aceb3b50b9af6cdc14ab443b238f", - "0xaf2cf95f30ef478f018cf81d70d47d742120b09193d8bb77f0d41a5d2e1a80bfb467793d9e2471b4e0ad0cb2c3b42271", - "0x8af5ef2107ad284e246bb56e20fef2a255954f72de791cbdfd3be09f825298d8466064f3c98a50496c7277af32b5c0bc", - "0x85dc19558572844c2849e729395a0c125096476388bd1b14fa7f54a7c38008fc93e578da3aac6a52ff1504d6ca82db05", - "0xae8c9b43c49572e2e166d704caf5b4b621a3b47827bb2a3bcd71cdc599bba90396fd9a405261b13e831bb5d44c0827d7", - "0xa7ba7efede25f02e88f6f4cbf70643e76784a03d97e0fbd5d9437c2485283ad7ca3abb638a5f826cd9f6193e5dec0b6c", - "0x94a9d122f2f06ef709fd8016fd4b712d88052245a65a301f5f177ce22992f74ad05552b1f1af4e70d1eac62cef309752", - "0x82d999b3e7cf563833b8bc028ff63a6b26eb357dfdb3fd5f10e33a1f80a9b2cfa7814d871b32a7ebfbaa09e753e37c02", - "0xaec6edcde234df502a3268dd2c26f4a36a2e0db730afa83173f9c78fcb2b2f75510a02b80194327b792811caefda2725", - "0x94c0bfa66c9f91d462e9194144fdd12d96f9bbe745737e73bab8130607ee6ea9d740e2cfcbbd00a195746edb6369ee61", - "0xab7573dab8c9d46d339e3f491cb2826cabe8b49f85f1ede78d845fc3995537d1b4ab85140b7d0238d9c24daf0e5e2a7e", - "0x87e8b16832843251fe952dadfd01d41890ed4bb4b8fa0254550d92c8cced44368225eca83a6c3ad47a7f81ff8a80c984", - "0x9189d2d9a7c64791b19c0773ad4f0564ce6bea94aa275a917f78ad987f150fdb3e5e26e7fef9982ac184897ecc04683f", - "0xb3661bf19e2da41415396ae4dd051a9272e8a2580b06f1a1118f57b901fa237616a9f8075af1129af4eabfefedbe2f1c", - "0xaf43c86661fb15daf5d910a4e06837225e100fb5680bd3e4b10f79a2144c6ec48b1f8d6e6b98e067d36609a5d038889a", - "0x82ac0c7acaa83ddc86c5b4249aae12f28155989c7c6b91e5137a4ce05113c6cbc16f6c44948b0efd8665362d3162f16a", - "0x8f268d1195ab465beeeb112cd7ffd5d5548559a8bc01261106d3555533fc1971081b25558d884d552df0db1cddda89d8", - "0x8ef7caa5521f3e037586ce8ac872a4182ee20c7921c0065ed9986c047e3dda08294da1165f385d008b40d500f07d895f", - "0x8c2f98f6880550573fad46075d3eba26634b5b025ce25a0b4d6e0193352c8a1f0661064027a70fe8190b522405f9f4e3", - "0xb7653f353564feb164f0f89ec7949da475b8dad4a4d396d252fc2a884f6932d027b7eb2dc4d280702c74569319ed701a", - "0xa026904f4066333befd9b87a8fad791d014096af60cdd668ef919c24dbe295ff31f7a790e1e721ba40cf5105abca67f4", - "0x988f982004ada07a22dd345f2412a228d7a96b9cae2c487de42e392afe1e35c2655f829ce07a14629148ce7079a1f142", - "0x9616add009067ed135295fb74d5b223b006b312bf14663e547a0d306694ff3a8a7bb9cfc466986707192a26c0bce599f", - "0xad4c425de9855f6968a17ee9ae5b15e0a5b596411388cf976df62ecc6c847a6e2ddb2cea792a5f6e9113c2445dba3e5c", - "0xb698ac9d86afa3dc69ff8375061f88e3b0cff92ff6dfe747cebaf142e813c011851e7a2830c10993b715e7fd594604a9", - "0xa386fa189847bb3b798efca917461e38ead61a08b101948def0f82cd258b945ed4d45b53774b400af500670149e601b7", - "0x905c95abda2c68a6559d8a39b6db081c68cef1e1b4be63498004e1b2f408409be9350b5b5d86a30fd443e2b3e445640a", - "0x9116dade969e7ce8954afcdd43e5cab64dc15f6c1b8da9d2d69de3f02ba79e6c4f6c7f54d6bf586d30256ae405cd1e41", - "0xa3084d173eacd08c9b5084a196719b57e47a0179826fda73466758235d7ecdb87cbcf097bd6b510517d163a85a7c7edd", - "0x85bb00415ad3c9be99ff9ba83672cc59fdd24356b661ab93713a3c8eab34e125d8867f628a3c3891b8dc056e69cd0e83", - "0x8d58541f9f39ed2ee4478acce5d58d124031338ec11b0d55551f00a5a9a6351faa903a5d7c132dc5e4bb026e9cbd18e4", - "0xa622adf72dc250e54f672e14e128c700166168dbe0474cecb340da175346e89917c400677b1bc1c11fcc4cc26591d9db", - "0xb3f865014754b688ca8372e8448114fff87bf3ca99856ab9168894d0c4679782c1ced703f5b74e851b370630f5e6ee86", - "0xa7e490b2c40c2446fcd91861c020da9742c326a81180e38110558bb5d9f2341f1c1885e79b364e6419023d1cbdc47380", - "0xb3748d472b1062e54572badbb8e87ac36534407f74932e7fc5b8392d008e8e89758f1671d1e4d30ab0fa40551b13bb5e", - "0x89898a5c5ec4313aabc607b0049fd1ebad0e0c074920cf503c9275b564d91916c2c446d3096491c950b7af3ac5e4b0ed", - "0x8eb8c83fef2c9dd30ea44e286e9599ec5c20aba983f702e5438afe2e5b921884327ad8d1566c72395587efac79ca7d56", - "0xb92479599e806516ce21fb0bd422a1d1d925335ebe2b4a0a7e044dd275f30985a72b97292477053ac5f00e081430da80", - "0xa34ae450a324fe8a3c25a4d653a654f9580ed56bbea213b8096987bbad0f5701d809a17076435e18017fea4d69f414bc", - "0x81381afe6433d62faf62ea488f39675e0091835892ecc238e02acf1662669c6d3962a71a3db652f6fe3bc5f42a0e5dc5", - "0xa430d475bf8580c59111103316fe1aa79c523ea12f1d47a976bbfae76894717c20220e31cf259f08e84a693da6688d70", - "0xb842814c359754ece614deb7d184d679d05d16f18a14b288a401cef5dad2cf0d5ee90bad487b80923fc5573779d4e4e8", - "0x971d9a2627ff2a6d0dcf2af3d895dfbafca28b1c09610c466e4e2bff2746f8369de7f40d65b70aed135fe1d72564aa88", - "0x8f4ce1c59e22b1ce7a0664caaa7e53735b154cfba8d2c5cc4159f2385843de82ab58ed901be876c6f7fce69cb4130950", - "0x86cc9dc321b6264297987000d344fa297ef45bcc2a4df04e458fe2d907ad304c0ea2318e32c3179af639a9a56f3263cf", - "0x8229e0876dfe8f665c3fb19b250bd89d40f039bbf1b331468b403655be7be2e104c2fd07b9983580c742d5462ca39a43", - "0x99299d73066e8eb128f698e56a9f8506dfe4bd014931e86b6b487d6195d2198c6c5bf15cccb40ccf1f8ddb57e9da44a2", - "0xa3a3be37ac554c574b393b2f33d0a32a116c1a7cfeaf88c54299a4da2267149a5ecca71f94e6c0ef6e2f472b802f5189", - "0xa91700d1a00387502cdba98c90f75fbc4066fefe7cc221c8f0e660994c936badd7d2695893fde2260c8c11d5bdcdd951", - "0x8e03cae725b7f9562c5c5ab6361644b976a68bada3d7ca508abca8dfc80a469975689af1fba1abcf21bc2a190dab397d", - "0xb01461ad23b2a8fa8a6d241e1675855d23bc977dbf4714add8c4b4b7469ccf2375cec20e80cedfe49361d1a30414ac5b", - "0xa2673bf9bc621e3892c3d7dd4f1a9497f369add8cbaa3472409f4f86bd21ac67cfac357604828adfee6ada1835365029", - "0xa042dff4bf0dfc33c178ba1b335e798e6308915128de91b12e5dbbab7c4ac8d60a01f6aea028c3a6d87b9b01e4e74c01", - "0x86339e8a75293e4b3ae66b5630d375736b6e6b6b05c5cda5e73fbf7b2f2bd34c18a1d6cefede08625ce3046e77905cb8", - "0xaf2ebe1b7d073d03e3d98bc61af83bf26f7a8c130fd607aa92b75db22d14d016481b8aa231e2c9757695f55b7224a27f", - "0xa00ee882c9685e978041fd74a2c465f06e2a42ffd3db659053519925be5b454d6f401e3c12c746e49d910e4c5c9c5e8c", - "0x978a781c0e4e264e0dad57e438f1097d447d891a1e2aa0d5928f79a9d5c3faae6f258bc94fdc530b7b2fa6a9932bb193", - "0xaa4b7ce2e0c2c9e9655bf21e3e5651c8503bce27483017b0bf476be743ba06db10228b3a4c721219c0779747f11ca282", - "0xb003d1c459dacbcf1a715551311e45d7dbca83a185a65748ac74d1800bbeaba37765d9f5a1a221805c571910b34ebca8", - "0x95b6e531b38648049f0d19de09b881baa1f7ea3b2130816b006ad5703901a05da57467d1a3d9d2e7c73fb3f2e409363c", - "0xa6cf9c06593432d8eba23a4f131bb7f72b9bd51ab6b4b772a749fe03ed72b5ced835a349c6d9920dba2a39669cb7c684", - "0xaa3d59f6e2e96fbb66195bc58c8704e139fa76cd15e4d61035470bd6e305db9f98bcbf61ac1b95e95b69ba330454c1b3", - "0xb57f97959c208361de6d7e86dff2b873068adb0f158066e646f42ae90e650079798f165b5cd713141cd3a2a90a961d9a", - "0xa76ee8ed9052f6a7a8c69774bb2597be182942f08115baba03bf8faaeaee526feba86120039fe8ca7b9354c3b6e0a8e6", - "0x95689d78c867724823f564627d22d25010f278674c6d2d0cdb10329169a47580818995d1d727ce46c38a1e47943ebb89", - "0xab676d2256c6288a88e044b3d9ffd43eb9d5aaee00e8fc60ac921395fb835044c71a26ca948e557fed770f52d711e057", - "0x96351c72785c32e5d004b6f4a1259fb8153d631f0c93fed172f18e8ba438fbc5585c1618deeabd0d6d0b82173c2e6170", - "0x93dd8d3db576418e22536eba45ab7f56967c6c97c64260d6cddf38fb19c88f2ec5cd0e0156f50e70855eee8a2b879ffd", - "0xad6ff16f40f6de3d7a737f8e6cebd8416920c4ff89dbdcd75eabab414af9a6087f83ceb9aff7680aa86bff98bd09c8cc", - "0x84de53b11671abc9c38710e19540c5c403817562aeb22a88404cdaff792c1180f717dbdfe8f54940c062c4d032897429", - "0x872231b9efa1cdd447b312099a5c164c560440a9441d904e70f5abfc3b2a0d16be9a01aca5e0a2599a61e19407587e3d", - "0x88f44ac27094a2aa14e9dc40b099ee6d68f97385950f303969d889ee93d4635e34dff9239103bdf66a4b7cbba3e7eb7a", - "0xa59afebadf0260e832f6f44468443562f53fbaf7bcb5e46e1462d3f328ac437ce56edbca617659ac9883f9e13261fad7", - "0xb1990e42743a88de4deeacfd55fafeab3bc380cb95de43ed623d021a4f2353530bcab9594389c1844b1c5ea6634c4555", - "0x85051e841149a10e83f56764e042182208591396d0ce78c762c4a413e6836906df67f38c69793e158d64fef111407ba3", - "0x9778172bbd9b1f2ec6bbdd61829d7b39a7df494a818e31c654bf7f6a30139899c4822c1bf418dd4f923243067759ce63", - "0x9355005b4878c87804fc966e7d24f3e4b02bed35b4a77369d01f25a3dcbff7621b08306b1ac85b76fe7b4a3eb5f839b1", - "0x8f9dc6a54fac052e236f8f0e1f571ac4b5308a43acbe4cc8183bce26262ddaf7994e41cf3034a4cbeca2c505a151e3b1", - "0x8cc59c17307111723fe313046a09e0e32ea0cce62c13814ab7c6408c142d6a0311d801be4af53fc9240523f12045f9ef", - "0x8e6057975ed40a1932e47dd3ac778f72ee2a868d8540271301b1aa6858de1a5450f596466494a3e0488be4fbeb41c840", - "0x812145efbd6559ae13325d56a15940ca4253b17e72a9728986b563bb5acc13ec86453796506ac1a8f12bd6f9e4a288c3", - "0x911da0a6d6489eb3dab2ec4a16e36127e8a291ae68a6c2c9de33e97f3a9b1f00da57a94e270a0de79ecc5ecb45d19e83", - "0xb72ea85973f4b2a7e6e71962b0502024e979a73c18a9111130e158541fa47bbaaf53940c8f846913a517dc69982ba9e1", - "0xa7a56ad1dbdc55f177a7ad1d0af78447dc2673291e34e8ab74b26e2e2e7d8c5fe5dc89e7ef60f04a9508847b5b3a8188", - "0xb52503f6e5411db5d1e70f5fb72ccd6463fa0f197b3e51ca79c7b5a8ab2e894f0030476ada72534fa4eb4e06c3880f90", - "0xb51c7957a3d18c4e38f6358f2237b3904618d58b1de5dec53387d25a63772e675a5b714ad35a38185409931157d4b529", - "0xb86b4266e719d29c043d7ec091547aa6f65bbf2d8d831d1515957c5c06513b72aa82113e9645ad38a7bc3f5383504fa6", - "0xb95b547357e6601667b0f5f61f261800a44c2879cf94e879def6a105b1ad2bbf1795c3b98a90d588388e81789bd02681", - "0xa58fd4c5ae4673fa350da6777e13313d5d37ed1dafeeb8f4f171549765b84c895875d9d3ae6a9741f3d51006ef81d962", - "0x9398dc348d078a604aadc154e6eef2c0be1a93bb93ba7fe8976edc2840a3a318941338cc4d5f743310e539d9b46613d2", - "0x902c9f0095014c4a2f0dccaaab543debba6f4cc82c345a10aaf4e72511725dbed7a34cd393a5f4e48a3e5142b7be84ed", - "0xa7c0447849bb44d04a0393a680f6cd390093484a79a147dd238f5d878030d1c26646d88211108e59fe08b58ad20c6fbd", - "0x80db045535d6e67a422519f5c89699e37098449d249698a7cc173a26ccd06f60238ae6cc7242eb780a340705c906790c", - "0x8e52b451a299f30124505de2e74d5341e1b5597bdd13301cc39b05536c96e4380e7f1b5c7ef076f5b3005a868657f17c", - "0x824499e89701036037571761e977654d2760b8ce21f184f2879fda55d3cda1e7a95306b8abacf1caa79d3cc075b9d27f", - "0x9049b956b77f8453d2070607610b79db795588c0cec12943a0f5fe76f358dea81e4f57a4692112afda0e2c05c142b26f", - "0x81911647d818a4b5f4990bfd4bc13bf7be7b0059afcf1b6839333e8569cdb0172fd2945410d88879349f677abaed5eb3", - "0xad4048f19b8194ed45b6317d9492b71a89a66928353072659f5ce6c816d8f21e69b9d1817d793effe49ca1874daa1096", - "0x8d22f7b2ddb31458661abd34b65819a374a1f68c01fc6c9887edeba8b80c65bceadb8f57a3eb686374004b836261ef67", - "0x92637280c259bc6842884db3d6e32602a62252811ae9b019b3c1df664e8809ffe86db88cfdeb8af9f46435c9ee790267", - "0xa2f416379e52e3f5edc21641ea73dc76c99f7e29ea75b487e18bd233856f4c0183429f378d2bfc6cd736d29d6cadfa49", - "0x882cb6b76dbdc188615dcf1a8439eba05ffca637dd25197508156e03c930b17b9fed2938506fdd7b77567cb488f96222", - "0xb68b621bb198a763fb0634eddb93ed4b5156e59b96c88ca2246fd1aea3e6b77ed651e112ac41b30cd361fadc011d385e", - "0xa3cb22f6b675a29b2d1f827cacd30df14d463c93c3502ef965166f20d046af7f9ab7b2586a9c64f4eae4fad2d808a164", - "0x8302d9ce4403f48ca217079762ce42cee8bc30168686bb8d3a945fbd5acd53b39f028dce757b825eb63af2d5ae41169d", - "0xb2eef1fbd1a176f1f4cd10f2988c7329abe4eb16c7405099fb92baa724ab397bc98734ef7d4b24c0f53dd90f57520d04", - "0xa1bbef0bd684a3f0364a66bde9b29326bac7aa3dde4caed67f14fb84fed3de45c55e406702f1495a3e2864d4ee975030", - "0x976acdb0efb73e3a3b65633197692dedc2adaed674291ae3df76b827fc866d214e9cac9ca46baefc4405ff13f953d936", - "0xb9fbf71cc7b6690f601f0b1c74a19b7d14254183a2daaafec7dc3830cba5ae173d854bbfebeca985d1d908abe5ef0cda", - "0x90591d7b483598c94e38969c4dbb92710a1a894bcf147807f1bcbd8aa3ac210b9f2be65519aa829f8e1ccdc83ad9b8cf", - "0xa30568577c91866b9c40f0719d46b7b3b2e0b4a95e56196ac80898a2d89cc67880e1229933f2cd28ee3286f8d03414d7", - "0x97589a88c3850556b359ec5e891f0937f922a751ac7c95949d3bbc7058c172c387611c0f4cb06351ef02e5178b3dd9e4", - "0x98e7bbe27a1711f4545df742f17e3233fbcc63659d7419e1ca633f104cb02a32c84f2fac23ca2b84145c2672f68077ab", - "0xa7ddb91636e4506d8b7e92aa9f4720491bb71a72dadc47c7f4410e15f93e43d07d2b371951a0e6a18d1bd087aa96a5c4", - "0xa7c006692227a06db40bceac3d5b1daae60b5692dd9b54772bedb5fea0bcc91cbcdb530cac31900ffc70c5b3ffadc969", - "0x8d3ec6032778420dfa8be52066ba0e623467df33e4e1901dbadd586c5d750f4ccde499b5197e26b9ea43931214060f69", - "0x8d9a8410518ea64f89df319bfd1fc97a0971cdb9ad9b11d1f8fe834042ea7f8dce4db56eeaf179ff8dda93b6db93e5ce", - "0xa3c533e9b3aa04df20b9ff635cb1154ce303e045278fcf3f10f609064a5445552a1f93989c52ce852fd0bbd6e2b6c22e", - "0x81934f3a7f8c1ae60ec6e4f212986bcc316118c760a74155d06ce0a8c00a9b9669ec4e143ca214e1b995e41271774fd9", - "0xab8e2d01a71192093ef8fafa7485e795567cc9db95a93fb7cc4cf63a391ef89af5e2bfad4b827fffe02b89271300407f", - "0x83064a1eaa937a84e392226f1a60b7cfad4efaa802f66de5df7498962f7b2649924f63cd9962d47906380b97b9fe80e1", - "0xb4f5e64a15c6672e4b55417ee5dc292dcf93d7ea99965a888b1cc4f5474a11e5b6520eacbcf066840b343f4ceeb6bf33", - "0xa63d278b842456ef15c278b37a6ea0f27c7b3ffffefca77c7a66d2ea06c33c4631eb242bbb064d730e70a8262a7b848a", - "0x83a41a83dbcdf0d22dc049de082296204e848c453c5ab1ba75aa4067984e053acf6f8b6909a2e1f0009ed051a828a73b", - "0x819485b036b7958508f15f3c19436da069cbe635b0318ebe8c014cf1ef9ab2df038c81161b7027475bcfa6fff8dd9faf", - "0xaa40e38172806e1e045e167f3d1677ef12d5dcdc89b43639a170f68054bd196c4fae34c675c1644d198907a03f76ba57", - "0x969bae484883a9ed1fbed53b26b3d4ee4b0e39a6c93ece5b3a49daa01444a1c25727dabe62518546f36b047b311b177c", - "0x80a9e73a65da99664988b238096a090d313a0ee8e4235bc102fa79bb337b51bb08c4507814eb5baec22103ec512eaab0", - "0x86604379aec5bddda6cbe3ef99c0ac3a3c285b0b1a15b50451c7242cd42ae6b6c8acb717dcca7917838432df93a28502", - "0xa23407ee02a495bed06aa7e15f94cfb05c83e6d6fba64456a9bbabfa76b2b68c5c47de00ba169e710681f6a29bb41a22", - "0x98cff5ecc73b366c6a01b34ac9066cb34f7eeaf4f38a5429bad2d07e84a237047e2a065c7e8a0a6581017dadb4695deb", - "0x8de9f68a938f441f3b7ab84bb1f473c5f9e5c9e139e42b7ccee1d254bd57d0e99c2ccda0f3198f1fc5737f6023dd204e", - "0xb0ce48d815c2768fb472a315cad86aa033d0e9ca506f146656e2941829e0acb735590b4fbc713c2d18d3676db0a954ac", - "0x82f485cdefd5642a6af58ac6817991c49fac9c10ace60f90b27f1788cc026c2fe8afc83cf499b3444118f9f0103598a8", - "0x82c24550ed512a0d53fc56f64cc36b553823ae8766d75d772dacf038c460f16f108f87a39ceef7c66389790f799dbab3", - "0x859ffcf1fe9166388316149b9acc35694c0ea534d43f09dae9b86f4aa00a23b27144dda6a352e74b9516e8c8d6fc809c", - "0xb8f7f353eec45da77fb27742405e5ad08d95ec0f5b6842025be9def3d9892f85eb5dd0921b41e6eff373618dba215bca", - "0x8ccca4436f9017e426229290f5cd05eac3f16571a4713141a7461acfe8ae99cd5a95bf5b6df129148693c533966145da", - "0xa2c67ecc19c0178b2994846fea4c34c327a5d786ac4b09d1d13549d5be5996d8a89021d63d65cb814923388f47cc3a03", - "0xaa0ff87d676b418ec08f5cbf577ac7e744d1d0e9ebd14615b550eb86931eafd2a36d4732cc5d6fab1713fd7ab2f6f7c0", - "0x8aef4730bb65e44efd6bb9441c0ae897363a2f3054867590a2c2ecf4f0224e578c7a67f10b40f8453d9f492ac15a9b2d", - "0x86a187e13d8fba5addcfdd5b0410cedd352016c930f913addd769ee09faa6be5ca3e4b1bdb417a965c643a99bd92be42", - "0xa0a4e9632a7a094b14b29b78cd9c894218cdf6783e61671e0203865dc2a835350f465fbaf86168f28af7c478ca17bc89", - "0xa8c7b02d8deff2cd657d8447689a9c5e2cd74ef57c1314ac4d69084ac24a7471954d9ff43fe0907d875dcb65fd0d3ce5", - "0x97ded38760aa7be6b6960b5b50e83b618fe413cbf2bcc1da64c05140bcc32f5e0e709cd05bf8007949953fac5716bad9", - "0xb0d293835a24d64c2ae48ce26e550b71a8c94a0883103757fb6b07e30747f1a871707d23389ba2b2065fa6bafe220095", - "0x8f9e291bf849feaa575592e28e3c8d4b7283f733d41827262367ea1c40f298c7bcc16505255a906b62bf15d9f1ba85fb", - "0x998f4e2d12708b4fd85a61597ca2eddd750f73c9e0c9b3cf0825d8f8e01f1628fd19797dcaed3b16dc50331fc6b8b821", - "0xb30d1f8c115d0e63bf48f595dd10908416774c78b3bbb3194192995154d80ea042d2e94d858de5f8aa0261b093c401fd", - "0xb5d9c75bb41f964cbff3f00e96d9f1480c91df8913f139f0d385d27a19f57a820f838eb728e46823cbff00e21c660996", - "0xa6edec90b5d25350e2f5f0518777634f9e661ec9d30674cf5b156c4801746d62517751d90074830ac0f4b09911c262f1", - "0x82f98da1264b6b75b8fbeb6a4d96d6a05b25c24db0d57ba3a38efe3a82d0d4e331b9fc4237d6494ccfe4727206457519", - "0xb89511843453cf4ecd24669572d6371b1e529c8e284300c43e0d5bb6b3aaf35aeb634b3cb5c0a2868f0d5e959c1d0772", - "0xa82bf065676583e5c1d3b81987aaae5542f522ba39538263a944bb33ea5b514c649344a96c0205a3b197a3f930fcda6c", - "0xa37b47ea527b7e06c460776aa662d9a49ff4149d3993f1a974b0dd165f7171770d189b0e2ea54fd5fccb6a14b116e68a", - "0xa1017677f97dda818274d47556d09d0e4ccacb23a252f82a6cfe78c630ad46fb9806307445a59fb61262182de3a2b29c", - "0xb01e9fcac239ba270e6877b79273ddd768bf8a51d2ed8a051b1c11e18eff3de5920e2fcbfbd26f06d381eddd3b1f1e1b", - "0x82fcd53d803b1c8e4ed76adc339b7f3a5962d37042b9683aabac7513ac68775d4a566a9460183926a6a95dbe7d551a1f", - "0xa763e78995d55cd21cdb7ef75d9642d6e1c72453945e346ab6690c20a4e1eeec61bb848ef830ae4b56182535e3c71d8f", - "0xb769f4db602251d4b0a1186782799bdcef66de33c110999a5775c50b349666ffd83d4c89714c4e376f2efe021a5cfdb2", - "0xa59cbd1b785efcfa6e83fc3b1d8cf638820bc0c119726b5368f3fba9dce8e3414204fb1f1a88f6c1ff52e87961252f97", - "0x95c8c458fd01aa23ecf120481a9c6332ebec2e8bb70a308d0576926a858457021c277958cf79017ddd86a56cacc2d7db", - "0x82eb41390800287ae56e77f2e87709de5b871c8bdb67c10a80fc65f3acb9f7c29e8fa43047436e8933f27449ea61d94d", - "0xb3ec25e3545eb83aed2a1f3558d1a31c7edde4be145ecc13b33802654b77dc049b4f0065069dd9047b051e52ab11dcdd", - "0xb78a0c715738f56f0dc459ab99e252e3b579b208142836b3c416b704ca1de640ca082f29ebbcee648c8c127df06f6b1e", - "0xa4083149432eaaf9520188ebf4607d09cf664acd1f471d4fb654476e77a9eaae2251424ffda78d09b6cb880df35c1219", - "0x8c52857d68d6e9672df3db2df2dbf46b516a21a0e8a18eec09a6ae13c1ef8f369d03233320dd1c2c0bbe00abfc1ea18b", - "0x8c856089488803066bff3f8d8e09afb9baf20cecc33c8823c1c0836c3d45498c3de37e87c016b705207f60d2b00f8609", - "0x831a3df39be959047b2aead06b4dcd3012d7b29417f642b83c9e8ce8de24a3dbbd29c6fdf55e2db3f7ea04636c94e403", - "0xaed84d009f66544addabe404bf6d65af7779ce140dc561ff0c86a4078557b96b2053b7b8a43432ffb18cd814f143b9da", - "0x93282e4d72b0aa85212a77b336007d8ba071eea17492da19860f1ad16c1ea8867ccc27ef5c37c74b052465cc11ea4f52", - "0xa7b78b8c8d057194e8d68767f1488363f77c77bddd56c3da2bc70b6354c7aa76247c86d51f7371aa38a4aa7f7e3c0bb7", - "0xb1c77283d01dcd1bde649b5b044eac26befc98ff57cbee379fb5b8e420134a88f2fc7f0bf04d15e1fbd45d29e7590fe6", - "0xa4aa8de70330a73b2c6458f20a1067eed4b3474829b36970a8df125d53bbdda4f4a2c60063b7cccb0c80fc155527652f", - "0x948a6c79ba1b8ad7e0bed2fae2f0481c4e41b4d9bbdd9b58164e28e9065700e83f210c8d5351d0212e0b0b68b345b3a5", - "0x86a48c31dcbbf7b082c92d28e1f613a2378a910677d7db3a349dc089e4a1e24b12eee8e8206777a3a8c64748840b7387", - "0x976adb1af21e0fc34148917cf43d933d7bfd3fd12ed6c37039dcd5a4520e3c6cf5868539ba5bf082326430deb8a4458d", - "0xb93e1a4476f2c51864bb4037e7145f0635eb2827ab91732b98d49b6c07f6ac443111aa1f1da76d1888665cb897c3834e", - "0x8afd46fb23bf869999fa19784b18a432a1f252d09506b8dbb756af900518d3f5f244989b3d7c823d9029218c655d3dc6", - "0x83f1e59e3abeed18cdc632921672673f1cb6e330326e11c4e600e13e0d5bc11bdc970ae12952e15103a706fe720bf4d6", - "0x90ce4cc660714b0b673d48010641c09c00fc92a2c596208f65c46073d7f349dd8e6e077ba7dcef9403084971c3295b76", - "0x8b09b0f431a7c796561ecf1549b85048564de428dac0474522e9558b6065fede231886bc108539c104ce88ebd9b5d1b0", - "0x85d6e742e2fb16a7b0ba0df64bc2c0dbff9549be691f46a6669bca05e89c884af16822b85faefefb604ec48c8705a309", - "0xa87989ee231e468a712c66513746fcf03c14f103aadca0eac28e9732487deb56d7532e407953ab87a4bf8961588ef7b0", - "0xb00da10efe1c29ee03c9d37d5918e391ae30e48304e294696b81b434f65cf8c8b95b9d1758c64c25e534d045ba28696f", - "0x91c0e1fb49afe46c7056400baa06dbb5f6e479db78ee37e2d76c1f4e88994357e257b83b78624c4ef6091a6c0eb8254d", - "0x883fb797c498297ccbf9411a3e727c3614af4eccde41619b773dc7f3259950835ee79453debf178e11dec4d3ada687a0", - "0xa14703347e44eb5059070b2759297fcfcfc60e6893c0373eea069388eba3950aa06f1c57cd2c30984a2d6f9e9c92c79e", - "0xafebc7585b304ceba9a769634adff35940e89cd32682c78002822aab25eec3edc29342b7f5a42a56a1fec67821172ad5", - "0xaea3ff3822d09dba1425084ca95fd359718d856f6c133c5fabe2b2eed8303b6e0ba0d8698b48b93136a673baac174fd9", - "0xaf2456a09aa777d9e67aa6c7c49a1845ea5cdda2e39f4c935c34a5f8280d69d4eec570446998cbbe31ede69a91e90b06", - "0x82cada19fed16b891ef3442bafd49e1f07c00c2f57b2492dd4ee36af2bd6fd877d6cb41188a4d6ce9ec8d48e8133d697", - "0x82a21034c832287f616619a37c122cee265cc34ae75e881fcaea4ea7f689f3c2bc8150bbf7dbcfd123522bfb7f7b1d68", - "0x86877217105f5d0ec3eeff0289fc2a70d505c9fdf7862e8159553ef60908fb1a27bdaf899381356a4ef4649072a9796c", - "0x82b196e49c6e861089a427c0b4671d464e9d15555ffb90954cd0d630d7ae02eb3d98ceb529d00719c2526cd96481355a", - "0xa29b41d0d43d26ce76d4358e0db2b77df11f56e389f3b084d8af70a636218bd3ac86b36a9fe46ec9058c26a490f887f7", - "0xa4311c4c20c4d7dd943765099c50f2fd423e203ccfe98ff00087d205467a7873762510cac5fdce7a308913ed07991ed7", - "0xb1f040fc5cc51550cb2c25cf1fd418ecdd961635a11f365515f0cb4ffb31da71f48128c233e9cc7c0cf3978d757ec84e", - "0xa9ebae46f86d3bd543c5f207ed0d1aed94b8375dc991161d7a271f01592912072e083e2daf30c146430894e37325a1b9", - "0x826418c8e17ad902b5fe88736323a47e0ca7a44bce4cbe27846ec8fe81de1e8942455dda6d30e192cdcc73e11df31256", - "0x85199db563427c5edcbac21f3d39fec2357be91fb571982ddcdc4646b446ad5ced84410de008cb47b3477ee0d532daf8", - "0xb7eed9cd400b2ca12bf1d9ae008214b8561fb09c8ad9ff959e626ffde00fee5ff2f5b6612e231f2a1a9b1646fcc575e3", - "0x8b40bf12501dcbac78f5a314941326bfcddf7907c83d8d887d0bb149207f85d80cd4dfbd7935439ea7b14ea39a3fded7", - "0x83e3041af302485399ba6cd5120e17af61043977083887e8d26b15feec4a6b11171ac5c06e6ad0971d4b58a81ff12af3", - "0x8f5b9a0eecc589dbf8c35a65d5e996a659277ef6ea509739c0cb7b3e2da9895e8c8012de662e5b23c5fa85d4a8f48904", - "0x835d71ed5e919d89d8e6455f234f3ff215462c4e3720c371ac8c75e83b19dfe3ae15a81547e4dc1138e5f5997f413cc9", - "0x8b7d2e4614716b1db18e9370176ea483e6abe8acdcc3dcdf5fb1f4d22ca55d652feebdccc171c6de38398d9f7bfdec7a", - "0x93eace72036fe57d019676a02acf3d224cf376f166658c1bf705db4f24295881d477d6fdd7916efcfceff8c7a063deda", - "0xb1ac460b3d516879a84bc886c54f020a9d799e7c49af3e4d7de5bf0d2793c852254c5d8fe5616147e6659512e5ccb012", - "0xacd0947a35cb167a48bcd9667620464b54ac0e78f9316b4aa92dcaab5422d7a732087e52e1c827faa847c6b2fe6e7766", - "0x94ac33d21c3d12ff762d32557860e911cd94d666609ddcc42161b9c16f28d24a526e8b10bb03137257a92cec25ae637d", - "0x832e02058b6b994eadd8702921486241f9a19e68ed1406dad545e000a491ae510f525ccf9d10a4bba91c68f2c53a0f58", - "0x9471035d14f78ff8f463b9901dd476b587bb07225c351161915c2e9c6114c3c78a501379ab6fb4eb03194c457cbd22bf", - "0xab64593e034c6241d357fcbc32d8ea5593445a5e7c24cac81ad12bd2ef01843d477a36dc1ba21dbe63b440750d72096a", - "0x9850f3b30045e927ad3ec4123a32ed2eb4c911f572b6abb79121873f91016f0d80268de8b12e2093a4904f6e6cab7642", - "0x987212c36b4722fe2e54fa30c52b1e54474439f9f35ca6ad33c5130cd305b8b54b532dd80ffd2c274105f20ce6d79f6e", - "0x8b4d0c6abcb239b5ed47bef63bc17efe558a27462c8208fa652b056e9eae9665787cd1aee34fbb55beb045c8bfdb882b", - "0xa9f3483c6fee2fe41312d89dd4355d5b2193ac413258993805c5cbbf0a59221f879386d3e7a28e73014f10e65dd503d9", - "0xa2225da3119b9b7c83d514b9f3aeb9a6d9e32d9cbf9309cbb971fd53c4b2c001d10d880a8ad8a7c281b21d85ceca0b7c", - "0xa050be52e54e676c151f7a54453bbb707232f849beab4f3bf504b4d620f59ed214409d7c2bd3000f3ff13184ccda1c35", - "0xadbccf681e15b3edb6455a68d292b0a1d0f5a4cb135613f5e6db9943f02181341d5755875db6ee474e19ace1c0634a28", - "0x8b6eff675632a6fad0111ec72aacc61c7387380eb87933fd1d098856387d418bd38e77d897e65d6fe35951d0627c550b", - "0xaabe2328ddf90989b15e409b91ef055cb02757d34987849ae6d60bef2c902bf8251ed21ab30acf39e500d1d511e90845", - "0x92ba4eb1f796bc3d8b03515f65c045b66e2734c2da3fc507fdd9d6b5d1e19ab3893726816a32141db7a31099ca817d96", - "0x8a98b3cf353138a1810beb60e946183803ef1d39ac4ea92f5a1e03060d35a4774a6e52b14ead54f6794d5f4022b8685c", - "0x909f8a5c13ec4a59b649ed3bee9f5d13b21d7f3e2636fd2bb3413c0646573fdf9243d63083356f12f5147545339fcd55", - "0x9359d914d1267633141328ed0790d81c695fea3ddd2d406c0df3d81d0c64931cf316fe4d92f4353c99ff63e2aefc4e34", - "0xb88302031681b54415fe8fbfa161c032ea345c6af63d2fb8ad97615103fd4d4281c5a9cae5b0794c4657b97571a81d3b", - "0x992c80192a519038082446b1fb947323005b275e25f2c14c33cc7269e0ec038581cc43705894f94bad62ae33a8b7f965", - "0xa78253e3e3eece124bef84a0a8807ce76573509f6861d0b6f70d0aa35a30a123a9da5e01e84969708c40b0669eb70aa6", - "0x8d5724de45270ca91c94792e8584e676547d7ac1ac816a6bb9982ee854eb5df071d20545cdfd3771cd40f90e5ba04c8e", - "0x825a6f586726c68d45f00ad0f5a4436523317939a47713f78fd4fe81cd74236fdac1b04ecd97c2d0267d6f4981d7beb1" - ], - "g2_monomial": [ - "0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8", - "0xb5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2", - "0xb5337ba0ce5d37224290916e268e2060e5c14f3f9fc9e1ec3af5a958e7a0303122500ce18f1a4640bf66525bd10e763501fe986d86649d8d45143c08c3209db3411802c226e9fe9a55716ac4a0c14f9dcef9e70b2bb309553880dc5025eab3cc", - "0xb3c1dcdc1f62046c786f0b82242ef283e7ed8f5626f72542aa2c7a40f14d9094dd1ebdbd7457ffdcdac45fd7da7e16c51200b06d791e5e43e257e45efdf0bd5b06cd2333beca2a3a84354eb48662d83aef5ecf4e67658c851c10b13d8d87c874", - "0x954d91c7688983382609fca9e211e461f488a5971fd4e40d7e2892037268eacdfd495cfa0a7ed6eb0eb11ac3ae6f651716757e7526abe1e06c64649d80996fd3105c20c4c94bc2b22d97045356fe9d791f21ea6428ac48db6f9e68e30d875280", - "0x88a6b6bb26c51cf9812260795523973bb90ce80f6820b6c9048ab366f0fb96e48437a7f7cb62aedf64b11eb4dfefebb0147608793133d32003cb1f2dc47b13b5ff45f1bb1b2408ea45770a08dbfaec60961acb8119c47b139a13b8641e2c9487", - "0x85cd7be9728bd925d12f47fb04b32d9fad7cab88788b559f053e69ca18e463113ecc8bbb6dbfb024835f901b3a957d3108d6770fb26d4c8be0a9a619f6e3a4bf15cbfd48e61593490885f6cee30e4300c5f9cf5e1c08e60a2d5b023ee94fcad0", - "0x80477dba360f04399821a48ca388c0fa81102dd15687fea792ee8c1114e00d1bc4839ad37ac58900a118d863723acfbe08126ea883be87f50e4eabe3b5e72f5d9e041db8d9b186409fd4df4a7dde38c0e0a3b1ae29b098e5697e7f110b6b27e4", - "0xb7a6aec08715a9f8672a2b8c367e407be37e59514ac19dd4f0942a68007bba3923df22da48702c63c0d6b3efd3c2d04e0fe042d8b5a54d562f9f33afc4865dcbcc16e99029e25925580e87920c399e710d438ac1ce3a6dc9b0d76c064a01f6f7", - "0xac1b001edcea02c8258aeffbf9203114c1c874ad88dae1184fadd7d94cd09053649efd0ca413400e6e9b5fa4eac33261000af88b6bd0d2abf877a4f0355d2fb4d6007adb181695201c5432e50b850b51b3969f893bddf82126c5a71b042b7686", - "0x90043fda4de53fb364fab2c04be5296c215599105ecff0c12e4917c549257125775c29f2507124d15f56e30447f367db0596c33237242c02d83dfd058735f1e3c1ff99069af55773b6d51d32a68bf75763f59ec4ee7267932ae426522b8aaab6", - "0xa8660ce853e9dc08271bf882e29cd53397d63b739584dda5263da4c7cc1878d0cf6f3e403557885f557e184700575fee016ee8542dec22c97befe1d10f414d22e84560741cdb3e74c30dda9b42eeaaf53e27822de2ee06e24e912bf764a9a533", - "0x8fe3921a96d0d065e8aa8fce9aa42c8e1461ca0470688c137be89396dd05103606dab6cdd2a4591efd6addf72026c12e065da7be276dee27a7e30afa2bd81c18f1516e7f068f324d0bad9570b95f6bd02c727cd2343e26db0887c3e4e26dceda", - "0x8ae1ad97dcb9c192c9a3933541b40447d1dc4eebf380151440bbaae1e120cc5cdf1bcea55180b128d8e180e3af623815191d063cc0d7a47d55fb7687b9d87040bf7bc1a7546b07c61db5ccf1841372d7c2fe4a5431ffff829f3c2eb590b0b710", - "0x8c2fa96870a88150f7876c931e2d3cc2adeaaaf5c73ef5fa1cf9dfa0991ae4819f9321af7e916e5057d87338e630a2f21242c29d76963cf26035b548d2a63d8ad7bd6efefa01c1df502cbdfdfe0334fb21ceb9f686887440f713bf17a89b8081", - "0xb9aa98e2f02bb616e22ee5dd74c7d1049321ac9214d093a738159850a1dbcc7138cb8d26ce09d8296368fd5b291d74fa17ac7cc1b80840fdd4ee35e111501e3fa8485b508baecda7c1ab7bd703872b7d64a2a40b3210b6a70e8a6ffe0e5127e3", - "0x9292db67f8771cdc86854a3f614a73805bf3012b48f1541e704ea4015d2b6b9c9aaed36419769c87c49f9e3165f03edb159c23b3a49c4390951f78e1d9b0ad997129b17cdb57ea1a6638794c0cca7d239f229e589c5ae4f9fe6979f7f8cba1d7", - "0x91cd9e86550f230d128664f7312591fee6a84c34f5fc7aed557bcf986a409a6de722c4330453a305f06911d2728626e611acfdf81284f77f60a3a1595053a9479964fd713117e27c0222cc679674b03bc8001501aaf9b506196c56de29429b46", - "0xa9516b73f605cc31b89c68b7675dc451e6364595243d235339437f556cf22d745d4250c1376182273be2d99e02c10eee047410a43eff634d051aeb784e76cb3605d8e079b9eb6ad1957dfdf77e1cd32ce4a573c9dfcc207ca65af6eb187f6c3d", - "0xa9667271f7d191935cc8ad59ef3ec50229945faea85bfdfb0d582090f524436b348aaa0183b16a6231c00332fdac2826125b8c857a2ed9ec66821cfe02b3a2279be2412441bc2e369b255eb98614e4be8490799c4df22f18d47d24ec70bba5f7", - "0xa4371144d2aa44d70d3cb9789096d3aa411149a6f800cb46f506461ee8363c8724667974252f28aea61b6030c05930ac039c1ee64bb4bd56532a685cae182bf2ab935eee34718cffcb46cae214c77aaca11dbb1320faf23c47247db1da04d8dc", - "0x89a7eb441892260b7e81168c386899cd84ffc4a2c5cad2eae0d1ab9e8b5524662e6f660fe3f8bfe4c92f60b060811bc605b14c5631d16709266886d7885a5eb5930097127ec6fb2ebbaf2df65909cf48f253b3d5e22ae48d3e9a2fd2b01f447e", - "0x9648c42ca97665b5eccb49580d8532df05eb5a68db07f391a2340769b55119eaf4c52fe4f650c09250fa78a76c3a1e271799b8333cc2628e3d4b4a6a3e03da1f771ecf6516dd63236574a7864ff07e319a6f11f153406280d63af9e2b5713283", - "0x9663bf6dd446ea7a90658ee458578d4196dc0b175ef7fcfa75f44d41670850774c2e46c5a6be132a2c072a3c0180a24f0305d1acac49d2d79878e5cda80c57feda3d01a6af12e78b5874e2a4b3717f11c97503b41a4474e2e95b179113726199", - "0xb212aeb4814e0915b432711b317923ed2b09e076aaf558c3ae8ef83f9e15a83f9ea3f47805b2750ab9e8106cb4dc6ad003522c84b03dc02829978a097899c773f6fb31f7fe6b8f2d836d96580f216fec20158f1590c3e0d7850622e15194db05", - "0x925f005059bf07e9ceccbe66c711b048e236ade775720d0fe479aebe6e23e8af281225ad18e62458dc1b03b42ad4ca290d4aa176260604a7aad0d9791337006fbdebe23746f8060d42876f45e4c83c3643931392fde1cd13ff8bddf8111ef974", - "0x9553edb22b4330c568e156a59ef03b26f5c326424f830fe3e8c0b602f08c124730ffc40bc745bec1a22417adb22a1a960243a10565c2be3066bfdb841d1cd14c624cd06e0008f4beb83f972ce6182a303bee3fcbcabc6cfe48ec5ae4b7941bfc", - "0x935f5a404f0a78bdcce709899eda0631169b366a669e9b58eacbbd86d7b5016d044b8dfc59ce7ed8de743ae16c2343b50e2f925e88ba6319e33c3fc76b314043abad7813677b4615c8a97eb83cc79de4fedf6ccbcfa4d4cbf759a5a84e4d9742", - "0xa5b014ab936eb4be113204490e8b61cd38d71da0dec7215125bcd131bf3ab22d0a32ce645bca93e7b3637cf0c2db3d6601a0ddd330dc46f9fae82abe864ffc12d656c88eb50c20782e5bb6f75d18760666f43943abb644b881639083e122f557", - "0x935b7298ae52862fa22bf03bfc1795b34c70b181679ae27de08a9f5b4b884f824ef1b276b7600efa0d2f1d79e4a470d51692fd565c5cf8343dd80e5d3336968fc21c09ba9348590f6206d4424eb229e767547daefa98bc3aa9f421158dee3f2a", - "0x9830f92446e708a8f6b091cc3c38b653505414f8b6507504010a96ffda3bcf763d5331eb749301e2a1437f00e2415efb01b799ad4c03f4b02de077569626255ac1165f96ea408915d4cf7955047620da573e5c439671d1fa5c833fb11de7afe6", - "0x840dcc44f673fff3e387af2bb41e89640f2a70bcd2b92544876daa92143f67c7512faf5f90a04b7191de01f3e2b1bde00622a20dc62ca23bbbfaa6ad220613deff43908382642d4d6a86999f662efd64b1df448b68c847cfa87630a3ffd2ec76", - "0x92950c895ed54f7f876b2fda17ecc9c41b7accfbdd42c210cc5b475e0737a7279f558148531b5c916e310604a1de25a80940c94fe5389ae5d6a5e9c371be67bceea1877f5401725a6595bcf77ece60905151b6dfcb68b75ed2e708c73632f4fd", - "0x8010246bf8e94c25fd029b346b5fbadb404ef6f44a58fd9dd75acf62433d8cc6db66974f139a76e0c26dddc1f329a88214dbb63276516cf325c7869e855d07e0852d622c332ac55609ba1ec9258c45746a2aeb1af0800141ee011da80af175d4", - "0xb0f1bad257ebd187bdc3f37b23f33c6a5d6a8e1f2de586080d6ada19087b0e2bf23b79c1b6da1ee82271323f5bdf3e1b018586b54a5b92ab6a1a16bb3315190a3584a05e6c37d5ca1e05d702b9869e27f513472bcdd00f4d0502a107773097da", - "0x9636d24f1ede773ce919f309448dd7ce023f424afd6b4b69cb98c2a988d849a283646dc3e469879daa1b1edae91ae41f009887518e7eb5578f88469321117303cd3ac2d7aee4d9cb5f82ab9ae3458e796dfe7c24284b05815acfcaa270ff22e2", - "0xb373feb5d7012fd60578d7d00834c5c81df2a23d42794fed91aa9535a4771fde0341c4da882261785e0caca40bf83405143085e7f17e55b64f6c5c809680c20b050409bf3702c574769127c854d27388b144b05624a0e24a1cbcc4d08467005b", - "0xb15680648949ce69f82526e9b67d9b55ce5c537dc6ab7f3089091a9a19a6b90df7656794f6edc87fb387d21573ffc847062623685931c2790a508cbc8c6b231dd2c34f4d37d4706237b1407673605a604bcf6a50cc0b1a2db20485e22b02c17e", - "0x8817e46672d40c8f748081567b038a3165f87994788ec77ee8daea8587f5540df3422f9e120e94339be67f186f50952504cb44f61e30a5241f1827e501b2de53c4c64473bcc79ab887dd277f282fbfe47997a930dd140ac08b03efac88d81075", - "0xa6e4ef6c1d1098f95aae119905f87eb49b909d17f9c41bcfe51127aa25fee20782ea884a7fdf7d5e9c245b5a5b32230b07e0dbf7c6743bf52ee20e2acc0b269422bd6cf3c07115df4aa85b11b2c16630a07c974492d9cdd0ec325a3fabd95044", - "0x8634aa7c3d00e7f17150009698ce440d8e1b0f13042b624a722ace68ead870c3d2212fbee549a2c190e384d7d6ac37ce14ab962c299ea1218ef1b1489c98906c91323b94c587f1d205a6edd5e9d05b42d591c26494a6f6a029a2aadb5f8b6f67", - "0x821a58092900bdb73decf48e13e7a5012a3f88b06288a97b855ef51306406e7d867d613d9ec738ebacfa6db344b677d21509d93f3b55c2ebf3a2f2a6356f875150554c6fff52e62e3e46f7859be971bf7dd9d5b3e1d799749c8a97c2e04325df", - "0x8dba356577a3a388f782e90edb1a7f3619759f4de314ad5d95c7cc6e197211446819c4955f99c5fc67f79450d2934e3c09adefc91b724887e005c5190362245eec48ce117d0a94d6fa6db12eda4ba8dde608fbbd0051f54dcf3bb057adfb2493", - "0xa32a690dc95c23ed9fb46443d9b7d4c2e27053a7fcc216d2b0020a8cf279729c46114d2cda5772fd60a97016a07d6c5a0a7eb085a18307d34194596f5b541cdf01b2ceb31d62d6b55515acfd2b9eec92b27d082fbc4dc59fc63b551eccdb8468", - "0xa040f7f4be67eaf0a1d658a3175d65df21a7dbde99bfa893469b9b43b9d150fc2e333148b1cb88cfd0447d88fa1a501d126987e9fdccb2852ecf1ba907c2ca3d6f97b055e354a9789854a64ecc8c2e928382cf09dda9abde42bbdf92280cdd96", - "0x864baff97fa60164f91f334e0c9be00a152a416556b462f96d7c43b59fe1ebaff42f0471d0bf264976f8aa6431176eb905bd875024cf4f76c13a70bede51dc3e47e10b9d5652d30d2663b3af3f08d5d11b9709a0321aba371d2ef13174dcfcaf", - "0x95a46f32c994133ecc22db49bad2c36a281d6b574c83cfee6680b8c8100466ca034b815cfaedfbf54f4e75188e661df901abd089524e1e0eb0bf48d48caa9dd97482d2e8c1253e7e8ac250a32fd066d5b5cb08a8641bdd64ecfa48289dca83a3", - "0xa2cce2be4d12144138cb91066e0cd0542c80b478bf467867ebef9ddaf3bd64e918294043500bf5a9f45ee089a8d6ace917108d9ce9e4f41e7e860cbce19ac52e791db3b6dde1c4b0367377b581f999f340e1d6814d724edc94cb07f9c4730774", - "0xb145f203eee1ac0a1a1731113ffa7a8b0b694ef2312dabc4d431660f5e0645ef5838e3e624cfe1228cfa248d48b5760501f93e6ab13d3159fc241427116c4b90359599a4cb0a86d0bb9190aa7fabff482c812db966fd2ce0a1b48cb8ac8b3bca", - "0xadabe5d215c608696e03861cbd5f7401869c756b3a5aadc55f41745ad9478145d44393fec8bb6dfc4ad9236dc62b9ada0f7ca57fe2bae1b71565dbf9536d33a68b8e2090b233422313cc96afc7f1f7e0907dc7787806671541d6de8ce47c4cd0", - "0xae7845fa6b06db53201c1080e01e629781817f421f28956589c6df3091ec33754f8a4bd4647a6bb1c141ac22731e3c1014865d13f3ed538dcb0f7b7576435133d9d03be655f8fbb4c9f7d83e06d1210aedd45128c2b0c9bab45a9ddde1c862a5", - "0x9159eaa826a24adfa7adf6e8d2832120ebb6eccbeb3d0459ffdc338548813a2d239d22b26451fda98cc0c204d8e1ac69150b5498e0be3045300e789bcb4e210d5cd431da4bdd915a21f407ea296c20c96608ded0b70d07188e96e6c1a7b9b86b", - "0xa9fc6281e2d54b46458ef564ffaed6944bff71e389d0acc11fa35d3fcd8e10c1066e0dde5b9b6516f691bb478e81c6b20865281104dcb640e29dc116daae2e884f1fe6730d639dbe0e19a532be4fb337bf52ae8408446deb393d224eee7cfa50", - "0x84291a42f991bfb36358eedead3699d9176a38f6f63757742fdbb7f631f2c70178b1aedef4912fed7b6cf27e88ddc7eb0e2a6aa4b999f3eb4b662b93f386c8d78e9ac9929e21f4c5e63b12991fcde93aa64a735b75b535e730ff8dd2abb16e04", - "0xa1b7fcacae181495d91765dfddf26581e8e39421579c9cbd0dd27a40ea4c54af3444a36bf85a11dda2114246eaddbdd619397424bb1eb41b5a15004b902a590ede5742cd850cf312555be24d2df8becf48f5afba5a8cd087cb7be0a521728386", - "0x92feaaf540dbd84719a4889a87cdd125b7e995a6782911931fef26da9afcfbe6f86aaf5328fe1f77631491ce6239c5470f44c7791506c6ef1626803a5794e76d2be0af92f7052c29ac6264b7b9b51f267ad820afc6f881460521428496c6a5f1", - "0xa525c925bfae1b89320a5054acc1fa11820f73d0cf28d273092b305467b2831fab53b6daf75fb926f332782d50e2522a19edcd85be5eb72f1497193c952d8cd0bcc5d43b39363b206eae4cb1e61668bde28a3fb2fc1e0d3d113f6dfadb799717", - "0x98752bb6f5a44213f40eda6aa4ff124057c1b13b6529ab42fe575b9afa66e59b9c0ed563fb20dff62130c436c3e905ee17dd8433ba02c445b1d67182ab6504a90bbe12c26a754bbf734665c622f76c62fe2e11dd43ce04fd2b91a8463679058b", - "0xa9aa9a84729f7c44219ff9e00e651e50ddea3735ef2a73fdf8ed8cd271961d8ed7af5cd724b713a89a097a3fe65a3c0202f69458a8b4c157c62a85668b12fc0d3957774bc9b35f86c184dd03bfefd5c325da717d74192cc9751c2073fe9d170e", - "0xb221c1fd335a4362eff504cd95145f122bf93ea02ae162a3fb39c75583fc13a932d26050e164da97cff3e91f9a7f6ff80302c19dd1916f24acf6b93b62f36e9665a8785413b0c7d930c7f1668549910f849bca319b00e59dd01e5dec8d2edacc", - "0xa71e2b1e0b16d754b848f05eda90f67bedab37709550171551050c94efba0bfc282f72aeaaa1f0330041461f5e6aa4d11537237e955e1609a469d38ed17f5c2a35a1752f546db89bfeff9eab78ec944266f1cb94c1db3334ab48df716ce408ef", - "0xb990ae72768779ba0b2e66df4dd29b3dbd00f901c23b2b4a53419226ef9232acedeb498b0d0687c463e3f1eead58b20b09efcefa566fbfdfe1c6e48d32367936142d0a734143e5e63cdf86be7457723535b787a9cfcfa32fe1d61ad5a2617220", - "0x8d27e7fbff77d5b9b9bbc864d5231fecf817238a6433db668d5a62a2c1ee1e5694fdd90c3293c06cc0cb15f7cbeab44d0d42be632cb9ff41fc3f6628b4b62897797d7b56126d65b694dcf3e298e3561ac8813fbd7296593ced33850426df42db", - "0xa92039a08b5502d5b211a7744099c9f93fa8c90cedcb1d05e92f01886219dd464eb5fb0337496ad96ed09c987da4e5f019035c5b01cc09b2a18b8a8dd419bc5895388a07e26958f6bd26751929c25f89b8eb4a299d822e2d26fec9ef350e0d3c", - "0x92dcc5a1c8c3e1b28b1524e3dd6dbecd63017c9201da9dbe077f1b82adc08c50169f56fc7b5a3b28ec6b89254de3e2fd12838a761053437883c3e01ba616670cea843754548ef84bcc397de2369adcca2ab54cd73c55dc68d87aec3fc2fe4f10" - ] -} diff --git a/builder/crypto/secp256k1/.gitignore b/builder/crypto/secp256k1/.gitignore deleted file mode 100644 index 802b6744a..000000000 --- a/builder/crypto/secp256k1/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe - -*~ diff --git a/builder/crypto/secp256k1/LICENSE b/builder/crypto/secp256k1/LICENSE deleted file mode 100644 index f9090e142..000000000 --- a/builder/crypto/secp256k1/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Copyright (c) 2010 The Go Authors. All rights reserved. -Copyright (c) 2011 ThePiachu. All rights reserved. -Copyright (c) 2015 Jeffrey Wilcke. All rights reserved. -Copyright (c) 2015 Felix Lange. All rights reserved. -Copyright (c) 2015 Gustav Simonsson. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of the copyright holder. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/builder/crypto/secp256k1/curve.go b/builder/crypto/secp256k1/curve.go deleted file mode 100644 index 9b26ab292..000000000 --- a/builder/crypto/secp256k1/curve.go +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Copyright 2011 ThePiachu. All rights reserved. -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// * The name of ThePiachu may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package secp256k1 - -import ( - "crypto/elliptic" - "math/big" -) - -const ( - // number of bits in a big.Word - wordBits = 32 << (uint64(^big.Word(0)) >> 63) - // number of bytes in a big.Word - wordBytes = wordBits / 8 -) - -// readBits encodes the absolute value of bigint as big-endian bytes. Callers -// must ensure that buf has enough space. If buf is too short the result will -// be incomplete. -func readBits(bigint *big.Int, buf []byte) { - i := len(buf) - for _, d := range bigint.Bits() { - for j := 0; j < wordBytes && i > 0; j++ { - i-- - buf[i] = byte(d) - d >>= 8 - } - } -} - -// This code is from https://github.com/ThePiachu/GoBit and implements -// several Koblitz elliptic curves over prime fields. -// -// The curve methods, internally, on Jacobian coordinates. For a given -// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, -// z1) where x = x1/z1² and y = y1/z1³. The greatest speedups come -// when the whole calculation can be performed within the transform -// (as in ScalarMult and ScalarBaseMult). But even for Add and Double, -// it's faster to apply and reverse the transform than to operate in -// affine coordinates. - -// A BitCurve represents a Koblitz Curve with a=0. -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html -type BitCurve struct { - P *big.Int // the order of the underlying field - N *big.Int // the order of the base point - B *big.Int // the constant of the BitCurve equation - Gx, Gy *big.Int // (x,y) of the base point - BitSize int // the size of the underlying field -} - -func (BitCurve *BitCurve) Params() *elliptic.CurveParams { - return &elliptic.CurveParams{ - P: BitCurve.P, - N: BitCurve.N, - B: BitCurve.B, - Gx: BitCurve.Gx, - Gy: BitCurve.Gy, - BitSize: BitCurve.BitSize, - } -} - -// IsOnCurve returns true if the given (x,y) lies on the BitCurve. -func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool { - // y² = x³ + b - y2 := new(big.Int).Mul(y, y) //y² - y2.Mod(y2, BitCurve.P) //y²%P - - x3 := new(big.Int).Mul(x, x) //x² - x3.Mul(x3, x) //x³ - - x3.Add(x3, BitCurve.B) //x³+B - x3.Mod(x3, BitCurve.P) //(x³+B)%P - - return x3.Cmp(y2) == 0 -} - -// affineFromJacobian reverses the Jacobian transform. See the comment at the -// top of the file. -func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { - if z.Sign() == 0 { - return new(big.Int), new(big.Int) - } - - zinv := new(big.Int).ModInverse(z, BitCurve.P) - zinvsq := new(big.Int).Mul(zinv, zinv) - - xOut = new(big.Int).Mul(x, zinvsq) - xOut.Mod(xOut, BitCurve.P) - zinvsq.Mul(zinvsq, zinv) - yOut = new(big.Int).Mul(y, zinvsq) - yOut.Mod(yOut, BitCurve.P) - return -} - -// Add returns the sum of (x1,y1) and (x2,y2) -func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { - // If one point is at infinity, return the other point. - // Adding the point at infinity to any point will preserve the other point. - if x1.Sign() == 0 && y1.Sign() == 0 { - return x2, y2 - } - if x2.Sign() == 0 && y2.Sign() == 0 { - return x1, y1 - } - z := new(big.Int).SetInt64(1) - if x1.Cmp(x2) == 0 && y1.Cmp(y2) == 0 { - return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z)) - } - return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z)) -} - -// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and -// (x2, y2, z2) and returns their sum, also in Jacobian form. -func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - z1z1 := new(big.Int).Mul(z1, z1) - z1z1.Mod(z1z1, BitCurve.P) - z2z2 := new(big.Int).Mul(z2, z2) - z2z2.Mod(z2z2, BitCurve.P) - - u1 := new(big.Int).Mul(x1, z2z2) - u1.Mod(u1, BitCurve.P) - u2 := new(big.Int).Mul(x2, z1z1) - u2.Mod(u2, BitCurve.P) - h := new(big.Int).Sub(u2, u1) - if h.Sign() == -1 { - h.Add(h, BitCurve.P) - } - i := new(big.Int).Lsh(h, 1) - i.Mul(i, i) - j := new(big.Int).Mul(h, i) - - s1 := new(big.Int).Mul(y1, z2) - s1.Mul(s1, z2z2) - s1.Mod(s1, BitCurve.P) - s2 := new(big.Int).Mul(y2, z1) - s2.Mul(s2, z1z1) - s2.Mod(s2, BitCurve.P) - r := new(big.Int).Sub(s2, s1) - if r.Sign() == -1 { - r.Add(r, BitCurve.P) - } - r.Lsh(r, 1) - v := new(big.Int).Mul(u1, i) - - x3 := new(big.Int).Set(r) - x3.Mul(x3, x3) - x3.Sub(x3, j) - x3.Sub(x3, v) - x3.Sub(x3, v) - x3.Mod(x3, BitCurve.P) - - y3 := new(big.Int).Set(r) - v.Sub(v, x3) - y3.Mul(y3, v) - s1.Mul(s1, j) - s1.Lsh(s1, 1) - y3.Sub(y3, s1) - y3.Mod(y3, BitCurve.P) - - z3 := new(big.Int).Add(z1, z2) - z3.Mul(z3, z3) - z3.Sub(z3, z1z1) - if z3.Sign() == -1 { - z3.Add(z3, BitCurve.P) - } - z3.Sub(z3, z2z2) - if z3.Sign() == -1 { - z3.Add(z3, BitCurve.P) - } - z3.Mul(z3, h) - z3.Mod(z3, BitCurve.P) - - return x3, y3, z3 -} - -// Double returns 2*(x,y) -func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - z1 := new(big.Int).SetInt64(1) - return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1)) -} - -// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and -// returns its double, also in Jacobian form. -func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - - a := new(big.Int).Mul(x, x) //X1² - b := new(big.Int).Mul(y, y) //Y1² - c := new(big.Int).Mul(b, b) //B² - - d := new(big.Int).Add(x, b) //X1+B - d.Mul(d, d) //(X1+B)² - d.Sub(d, a) //(X1+B)²-A - d.Sub(d, c) //(X1+B)²-A-C - d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C) - - e := new(big.Int).Mul(big.NewInt(3), a) //3*A - f := new(big.Int).Mul(e, e) //E² - - x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D - x3.Sub(f, x3) //F-2*D - x3.Mod(x3, BitCurve.P) - - y3 := new(big.Int).Sub(d, x3) //D-X3 - y3.Mul(e, y3) //E*(D-X3) - y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C - y3.Mod(y3, BitCurve.P) - - z3 := new(big.Int).Mul(y, z) //Y1*Z1 - z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 - z3.Mod(z3, BitCurve.P) - - return x3, y3, z3 -} - -// ScalarBaseMult returns k*G, where G is the base point of the group and k is -// an integer in big-endian form. -func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { - return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k) -} - -// Marshal converts a point into the form specified in section 4.3.6 of ANSI -// X9.62. -func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte { - byteLen := (BitCurve.BitSize + 7) >> 3 - ret := make([]byte, 1+2*byteLen) - ret[0] = 4 // uncompressed point flag - readBits(x, ret[1:1+byteLen]) - readBits(y, ret[1+byteLen:]) - return ret -} - -// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On -// error, x = nil. -func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) { - byteLen := (BitCurve.BitSize + 7) >> 3 - if len(data) != 1+2*byteLen { - return - } - if data[0] != 4 { // uncompressed form - return - } - x = new(big.Int).SetBytes(data[1 : 1+byteLen]) - y = new(big.Int).SetBytes(data[1+byteLen:]) - return -} - -var theCurve = new(BitCurve) - -func init() { - // See SEC 2 section 2.7.1 - // curve parameters taken from: - // http://www.secg.org/sec2-v2.pdf - theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0) - theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0) - theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0) - theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0) - theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0) - theCurve.BitSize = 256 -} - -// S256 returns a BitCurve which implements secp256k1. -func S256() *BitCurve { - return theCurve -} diff --git a/builder/crypto/secp256k1/dummy.go b/builder/crypto/secp256k1/dummy.go deleted file mode 100644 index 65a75080f..000000000 --- a/builder/crypto/secp256k1/dummy.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build dummy -// +build dummy - -// This file is part of a workaround for `go mod vendor` which won't vendor -// C files if there's no Go file in the same directory. -// This would prevent the crypto/secp256k1/libsecp256k1/include/secp256k1.h file to be vendored. -// -// This Go file imports the c directory where there is another dummy.go file which -// is the second part of this workaround. -// -// These two files combined make it so `go mod vendor` behaves correctly. -// -// See this issue for reference: https://github.com/golang/go/issues/26366 - -package secp256k1 - -import ( - _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include" - _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src" - _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery" -) diff --git a/builder/crypto/secp256k1/ext.h b/builder/crypto/secp256k1/ext.h deleted file mode 100644 index e422fe4b4..000000000 --- a/builder/crypto/secp256k1/ext.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -// secp256k1_context_create_sign_verify creates a context for signing and signature verification. -static secp256k1_context* secp256k1_context_create_sign_verify() { - return secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); -} - -// secp256k1_ext_ecdsa_recover recovers the public key of an encoded compact signature. -// -// Returns: 1: recovery was successful -// 0: recovery was not successful -// Args: ctx: pointer to a context object (cannot be NULL) -// Out: pubkey_out: the serialized 65-byte public key of the signer (cannot be NULL) -// In: sigdata: pointer to a 65-byte signature with the recovery id at the end (cannot be NULL) -// msgdata: pointer to a 32-byte message (cannot be NULL) -static int secp256k1_ext_ecdsa_recover( - const secp256k1_context* ctx, - unsigned char *pubkey_out, - const unsigned char *sigdata, - const unsigned char *msgdata -) { - secp256k1_ecdsa_recoverable_signature sig; - secp256k1_pubkey pubkey; - - if (!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &sig, sigdata, (int)sigdata[64])) { - return 0; - } - if (!secp256k1_ecdsa_recover(ctx, &pubkey, &sig, msgdata)) { - return 0; - } - size_t outputlen = 65; - return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED); -} - -// secp256k1_ext_ecdsa_verify verifies an encoded compact signature. -// -// Returns: 1: signature is valid -// 0: signature is invalid -// Args: ctx: pointer to a context object (cannot be NULL) -// In: sigdata: pointer to a 64-byte signature (cannot be NULL) -// msgdata: pointer to a 32-byte message (cannot be NULL) -// pubkeydata: pointer to public key data (cannot be NULL) -// pubkeylen: length of pubkeydata -static int secp256k1_ext_ecdsa_verify( - const secp256k1_context* ctx, - const unsigned char *sigdata, - const unsigned char *msgdata, - const unsigned char *pubkeydata, - size_t pubkeylen -) { - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pubkey; - - if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata)) { - return 0; - } - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) { - return 0; - } - return secp256k1_ecdsa_verify(ctx, &sig, msgdata, &pubkey); -} - -// secp256k1_ext_reencode_pubkey decodes then encodes a public key. It can be used to -// convert between public key formats. The input/output formats are chosen depending on the -// length of the input/output buffers. -// -// Returns: 1: conversion successful -// 0: conversion unsuccessful -// Args: ctx: pointer to a context object (cannot be NULL) -// Out: out: output buffer that will contain the reencoded key (cannot be NULL) -// In: outlen: length of out (33 for compressed keys, 65 for uncompressed keys) -// pubkeydata: the input public key (cannot be NULL) -// pubkeylen: length of pubkeydata -static int secp256k1_ext_reencode_pubkey( - const secp256k1_context* ctx, - unsigned char *out, - size_t outlen, - const unsigned char *pubkeydata, - size_t pubkeylen -) { - secp256k1_pubkey pubkey; - - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) { - return 0; - } - unsigned int flag = (outlen == 33) ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED; - return secp256k1_ec_pubkey_serialize(ctx, out, &outlen, &pubkey, flag); -} - -// secp256k1_ext_scalar_mul multiplies a point by a scalar in constant time. -// -// Returns: 1: multiplication was successful -// 0: scalar was invalid (zero or overflow) -// Args: ctx: pointer to a context object (cannot be NULL) -// Out: point: the multiplied point (usually secret) -// In: point: pointer to a 64-byte public point, -// encoded as two 256bit big-endian numbers. -// scalar: a 32-byte scalar with which to multiply the point -int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, unsigned char *point, const unsigned char *scalar) { - int ret = 0; - int overflow = 0; - secp256k1_fe feX, feY; - secp256k1_gej res; - secp256k1_ge ge; - secp256k1_scalar s; - ARG_CHECK(point != NULL); - ARG_CHECK(scalar != NULL); - (void)ctx; - - secp256k1_fe_set_b32(&feX, point); - secp256k1_fe_set_b32(&feY, point+32); - secp256k1_ge_set_xy(&ge, &feX, &feY); - secp256k1_scalar_set_b32(&s, scalar, &overflow); - if (overflow || secp256k1_scalar_is_zero(&s)) { - ret = 0; - } else { - secp256k1_ecmult_const(&res, &ge, &s); - secp256k1_ge_set_gej(&ge, &res); - /* Note: can't use secp256k1_pubkey_save here because it is not constant time. */ - secp256k1_fe_normalize(&ge.x); - secp256k1_fe_normalize(&ge.y); - secp256k1_fe_get_b32(point, &ge.x); - secp256k1_fe_get_b32(point+32, &ge.y); - ret = 1; - } - secp256k1_scalar_clear(&s); - return ret; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/.gitignore b/builder/crypto/secp256k1/libsecp256k1/.gitignore deleted file mode 100644 index 87fea161b..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -bench_inv -bench_ecdh -bench_sign -bench_verify -bench_schnorr_verify -bench_recover -bench_internal -tests -exhaustive_tests -gen_context -*.exe -*.so -*.a -!.gitignore - -Makefile -configure -.libs/ -Makefile.in -aclocal.m4 -autom4te.cache/ -config.log -config.status -*.tar.gz -*.la -libtool -.deps/ -.dirstamp -*.lo -*.o -*~ -src/libsecp256k1-config.h -src/libsecp256k1-config.h.in -src/ecmult_static_context.h -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/ltmain.sh -build-aux/m4/libtool.m4 -build-aux/m4/lt~obsolete.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/missing -build-aux/compile -build-aux/test-driver -src/stamp-h1 -libsecp256k1.pc diff --git a/builder/crypto/secp256k1/libsecp256k1/.travis.yml b/builder/crypto/secp256k1/libsecp256k1/.travis.yml deleted file mode 100644 index 243952924..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/.travis.yml +++ /dev/null @@ -1,69 +0,0 @@ -language: c -sudo: false -addons: - apt: - packages: libgmp-dev -compiler: - - clang - - gcc -cache: - directories: - - src/java/guava/ -env: - global: - - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no - - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar - matrix: - - SCALAR=32bit RECOVERY=yes - - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes - - SCALAR=64bit - - FIELD=64bit RECOVERY=yes - - FIELD=64bit ENDOMORPHISM=yes - - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - - FIELD=64bit ASM=x86_64 - - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - - FIELD=32bit ENDOMORPHISM=yes - - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes - - BIGNUM=no STATICPRECOMPUTATION=no - - BUILD=distcheck - - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - - EXTRAFLAGS=CFLAGS=-O0 - - BUILD=check-java ECDH=yes EXPERIMENTAL=yes -matrix: - fast_finish: true - include: - - compiler: clang - env: HOST=i686-linux-gnu ENDOMORPHISM=yes - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 - - compiler: clang - env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - compiler: gcc - env: HOST=i686-linux-gnu ENDOMORPHISM=yes - addons: - apt: - packages: - - gcc-multilib - - compiler: gcc - env: HOST=i686-linux-gnu - addons: - apt: - packages: - - gcc-multilib - - libgmp-dev:i386 -before_install: mkdir -p `dirname $GUAVA_JAR` -install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi -before_script: ./autogen.sh -script: - - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD -os: linux diff --git a/builder/crypto/secp256k1/libsecp256k1/COPYING b/builder/crypto/secp256k1/libsecp256k1/COPYING deleted file mode 100644 index 4522a5990..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 Pieter Wuille - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/builder/crypto/secp256k1/libsecp256k1/Makefile.am b/builder/crypto/secp256k1/libsecp256k1/Makefile.am deleted file mode 100644 index c071fbe27..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/Makefile.am +++ /dev/null @@ -1,177 +0,0 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 - -lib_LTLIBRARIES = libsecp256k1.la -if USE_JNI -JNI_LIB = libsecp256k1_jni.la -noinst_LTLIBRARIES = $(JNI_LIB) -else -JNI_LIB = -endif -include_HEADERS = include/secp256k1.h -noinst_HEADERS = -noinst_HEADERS += src/scalar.h -noinst_HEADERS += src/scalar_4x64.h -noinst_HEADERS += src/scalar_8x32.h -noinst_HEADERS += src/scalar_low.h -noinst_HEADERS += src/scalar_impl.h -noinst_HEADERS += src/scalar_4x64_impl.h -noinst_HEADERS += src/scalar_8x32_impl.h -noinst_HEADERS += src/scalar_low_impl.h -noinst_HEADERS += src/group.h -noinst_HEADERS += src/group_impl.h -noinst_HEADERS += src/num_gmp.h -noinst_HEADERS += src/num_gmp_impl.h -noinst_HEADERS += src/ecdsa.h -noinst_HEADERS += src/ecdsa_impl.h -noinst_HEADERS += src/eckey.h -noinst_HEADERS += src/eckey_impl.h -noinst_HEADERS += src/ecmult.h -noinst_HEADERS += src/ecmult_impl.h -noinst_HEADERS += src/ecmult_const.h -noinst_HEADERS += src/ecmult_const_impl.h -noinst_HEADERS += src/ecmult_gen.h -noinst_HEADERS += src/ecmult_gen_impl.h -noinst_HEADERS += src/num.h -noinst_HEADERS += src/num_impl.h -noinst_HEADERS += src/field_10x26.h -noinst_HEADERS += src/field_10x26_impl.h -noinst_HEADERS += src/field_5x52.h -noinst_HEADERS += src/field_5x52_impl.h -noinst_HEADERS += src/field_5x52_int128_impl.h -noinst_HEADERS += src/field_5x52_asm_impl.h -noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h -noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h -noinst_HEADERS += src/util.h -noinst_HEADERS += src/testrand.h -noinst_HEADERS += src/testrand_impl.h -noinst_HEADERS += src/hash.h -noinst_HEADERS += src/hash_impl.h -noinst_HEADERS += src/field.h -noinst_HEADERS += src/field_impl.h -noinst_HEADERS += src/bench.h -noinst_HEADERS += contrib/lax_der_parsing.h -noinst_HEADERS += contrib/lax_der_parsing.c -noinst_HEADERS += contrib/lax_der_privatekey_parsing.h -noinst_HEADERS += contrib/lax_der_privatekey_parsing.c - -if USE_EXTERNAL_ASM -COMMON_LIB = libsecp256k1_common.la -noinst_LTLIBRARIES = $(COMMON_LIB) -else -COMMON_LIB = -endif - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsecp256k1.pc - -if USE_EXTERNAL_ASM -if USE_ASM_ARM -libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s -endif -endif - -libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) -libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) - -libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c -libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) - -noinst_PROGRAMS = -if USE_BENCHMARK -noinst_PROGRAMS += bench_verify bench_sign bench_internal -bench_verify_SOURCES = src/bench_verify.c -bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -bench_sign_SOURCES = src/bench_sign.c -bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) -bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) -endif - -TESTS = -if USE_TESTS -noinst_PROGRAMS += tests -tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -if !ENABLE_COVERAGE -tests_CPPFLAGS += -DVERIFY -endif -tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) -tests_LDFLAGS = -static -TESTS += tests -endif - -if USE_EXHAUSTIVE_TESTS -noinst_PROGRAMS += exhaustive_tests -exhaustive_tests_SOURCES = src/tests_exhaustive.c -exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) -if !ENABLE_COVERAGE -exhaustive_tests_CPPFLAGS += -DVERIFY -endif -exhaustive_tests_LDADD = $(SECP_LIBS) -exhaustive_tests_LDFLAGS = -static -TESTS += exhaustive_tests -endif - -JAVAROOT=src/java -JAVAORG=org/bitcoin -JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar -CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) -JAVA_FILES= \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ - $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ - $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java - -if USE_JNI - -$(JAVA_GUAVA): - @echo Guava is missing. Fetch it via: \ - wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) - @false - -.stamp-java: $(JAVA_FILES) - @echo Compiling $^ - $(AM_V_at)$(CLASSPATH_ENV) javac $^ - @touch $@ - -if USE_TESTS - -check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java - $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test - -endif -endif - -if USE_ECMULT_STATIC_PRECOMPUTATION -CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function - -gen_context_OBJECTS = gen_context.o -gen_context_BIN = gen_context$(BUILD_EXEEXT) -gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ - -$(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ - -$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h -$(tests_OBJECTS): src/ecmult_static_context.h -$(bench_internal_OBJECTS): src/ecmult_static_context.h - -src/ecmult_static_context.h: $(gen_context_BIN) - ./$(gen_context_BIN) - -CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java -endif - -EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) - -if ENABLE_MODULE_ECDH -include src/modules/ecdh/Makefile.am.include -endif - -if ENABLE_MODULE_RECOVERY -include src/modules/recovery/Makefile.am.include -endif diff --git a/builder/crypto/secp256k1/libsecp256k1/README.md b/builder/crypto/secp256k1/libsecp256k1/README.md deleted file mode 100644 index 8cd344ea8..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/README.md +++ /dev/null @@ -1,61 +0,0 @@ -libsecp256k1 -============ - -[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) - -Optimized C library for EC operations on curve secp256k1. - -This library is a work in progress and is being used to research best practices. Use at your own risk. - -Features: -* secp256k1 ECDSA signing/verification and key generation. -* Adding/multiplying private/public keys. -* Serialization/parsing of private keys, public keys, signatures. -* Constant time, constant memory access signing and pubkey generation. -* Derandomized DSA (via RFC6979 or with a caller provided function.) -* Very efficient implementation. - -Implementation details ----------------------- - -* General - * No runtime heap allocation. - * Extensive testing infrastructure. - * Structured to facilitate review and analysis. - * Intended to be portable to any system with a C89 compiler and uint64_t support. - * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") -* Field operations - * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). - * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). - * Using 10 26-bit limbs. - * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). -* Scalar operations - * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. - * Using 4 64-bit limbs (relying on __int128 support in the compiler). - * Using 8 32-bit limbs. -* Group operations - * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). - * Use addition between points in Jacobian and affine coordinates where possible. - * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. - * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. -* Point multiplication for verification (a*P + b*G). - * Use wNAF notation for point multiplicands. - * Use a much larger window for multiples of G, using precomputed multiples. - * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. - * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. -* Point multiplication for signing - * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. - * Access the table with branch-free conditional moves so memory access is uniform. - * No data-dependent branches - * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. - -Build steps ------------ - -libsecp256k1 is built using autotools: - - $ ./autogen.sh - $ ./configure - $ make - $ ./tests - $ sudo make install # optional diff --git a/builder/crypto/secp256k1/libsecp256k1/TODO b/builder/crypto/secp256k1/libsecp256k1/TODO deleted file mode 100644 index a300e1c5e..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* Unit tests for fieldelem/groupelem, including ones intended to - trigger fieldelem's boundary cases. -* Complete constant-time operations for signing/keygen diff --git a/builder/crypto/secp256k1/libsecp256k1/autogen.sh b/builder/crypto/secp256k1/libsecp256k1/autogen.sh deleted file mode 100755 index 65286b935..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/autogen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -set -e -autoreconf -if --warnings=all diff --git a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 b/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 deleted file mode 100644 index 1fc362761..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 +++ /dev/null @@ -1,140 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_JNI_INCLUDE_DIR -# -# DESCRIPTION -# -# AX_JNI_INCLUDE_DIR finds include directories needed for compiling -# programs using the JNI interface. -# -# JNI include directories are usually in the Java distribution. This is -# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in -# that order. When this macro completes, a list of directories is left in -# the variable JNI_INCLUDE_DIRS. -# -# Example usage follows: -# -# AX_JNI_INCLUDE_DIR -# -# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS -# do -# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" -# done -# -# If you want to force a specific compiler: -# -# - at the configure.in level, set JAVAC=yourcompiler before calling -# AX_JNI_INCLUDE_DIR -# -# - at the configure level, setenv JAVAC -# -# Note: This macro can work with the autoconf M4 macros for Java programs. -# This particular macro is not part of the original set of macros. -# -# LICENSE -# -# Copyright (c) 2008 Don Anderson -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 10 - -AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) -AC_DEFUN([AX_JNI_INCLUDE_DIR],[ - -JNI_INCLUDE_DIRS="" - -if test "x$JAVA_HOME" != x; then - _JTOPDIR="$JAVA_HOME" -else - if test "x$JAVAC" = x; then - JAVAC=javac - fi - AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) - if test "x$_ACJNI_JAVAC" = xno; then - AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) - fi - _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") - _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` -fi - -case "$host_os" in - darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - _JINC="$_JTOPDIR/Headers";; - *) _JINC="$_JTOPDIR/include";; -esac -_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) -_AS_ECHO_LOG([_JINC=$_JINC]) - -# On Mac OS X 10.6.4, jni.h is a symlink: -# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h -# -> ../../CurrentJDK/Headers/jni.h. - -AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, -[ -if test -f "$_JINC/jni.h"; then - ac_cv_jni_header_path="$_JINC" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" -else - _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - if test -f "$_JTOPDIR/include/jni.h"; then - ac_cv_jni_header_path="$_JTOPDIR/include" - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" - else - ac_cv_jni_header_path=none - fi -fi -]) - - - -# get the likely subdirectories for system specific java includes -case "$host_os" in -bsdi*) _JNI_INC_SUBDIRS="bsdos";; -darwin*) _JNI_INC_SUBDIRS="darwin";; -freebsd*) _JNI_INC_SUBDIRS="freebsd";; -linux*) _JNI_INC_SUBDIRS="linux genunix";; -osf*) _JNI_INC_SUBDIRS="alpha";; -solaris*) _JNI_INC_SUBDIRS="solaris";; -mingw*) _JNI_INC_SUBDIRS="win32";; -cygwin*) _JNI_INC_SUBDIRS="win32";; -*) _JNI_INC_SUBDIRS="genunix";; -esac - -if test "x$ac_cv_jni_header_path" != "xnone"; then - # add any subdirectories that are present - for JINCSUBDIR in $_JNI_INC_SUBDIRS - do - if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" - fi - done -fi -]) - -# _ACJNI_FOLLOW_SYMLINKS -# Follows symbolic links on , -# finally setting variable _ACJNI_FOLLOWED -# ---------------------------------------- -AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ -# find the include directory relative to the javac executable -_cur="$1" -while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do - AC_MSG_CHECKING([symlink for $_cur]) - _slink=`ls -ld "$_cur" | sed 's/.* -> //'` - case "$_slink" in - /*) _cur="$_slink";; - # 'X' avoids triggering unwanted echo options. - *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; - esac - AC_MSG_RESULT([$_cur]) -done -_ACJNI_FOLLOWED="$_cur" -])# _ACJNI diff --git a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 deleted file mode 100644 index 77fd346a7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 +++ /dev/null @@ -1,125 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_CC_FOR_BUILD -# -# DESCRIPTION -# -# This macro searches for a C compiler that generates native executables, -# that is a C compiler that surely is not a cross-compiler. This can be -# useful if you have to generate source code at compile-time like for -# example GCC does. -# -# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything -# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). -# The value of these variables can be overridden by the user by specifying -# a compiler with an environment variable (like you do for standard CC). -# -# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object -# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if -# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are -# substituted in the Makefile. -# -# LICENSE -# -# Copyright (c) 2008 Paolo Bonzini -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 8 - -AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) -AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_CPP])dnl -AC_REQUIRE([AC_EXEEXT])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl - -dnl Use the standard macros, but make them use other variable names -dnl -pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl -pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl -pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl -pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl -pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl -pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl -pushdef([ac_cv_objext], ac_cv_build_objext)dnl -pushdef([ac_exeext], ac_build_exeext)dnl -pushdef([ac_objext], ac_build_objext)dnl -pushdef([CC], CC_FOR_BUILD)dnl -pushdef([CPP], CPP_FOR_BUILD)dnl -pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl -pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl -pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl -pushdef([host], build)dnl -pushdef([host_alias], build_alias)dnl -pushdef([host_cpu], build_cpu)dnl -pushdef([host_vendor], build_vendor)dnl -pushdef([host_os], build_os)dnl -pushdef([ac_cv_host], ac_cv_build)dnl -pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl -pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl -pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl -pushdef([ac_cv_host_os], ac_cv_build_os)dnl -pushdef([ac_cpp], ac_build_cpp)dnl -pushdef([ac_compile], ac_build_compile)dnl -pushdef([ac_link], ac_build_link)dnl - -save_cross_compiling=$cross_compiling -save_ac_tool_prefix=$ac_tool_prefix -cross_compiling=no -ac_tool_prefix= - -AC_PROG_CC -AC_PROG_CPP -AC_EXEEXT - -ac_tool_prefix=$save_ac_tool_prefix -cross_compiling=$save_cross_compiling - -dnl Restore the old definitions -dnl -popdef([ac_link])dnl -popdef([ac_compile])dnl -popdef([ac_cpp])dnl -popdef([ac_cv_host_os])dnl -popdef([ac_cv_host_vendor])dnl -popdef([ac_cv_host_cpu])dnl -popdef([ac_cv_host_alias])dnl -popdef([ac_cv_host])dnl -popdef([host_os])dnl -popdef([host_vendor])dnl -popdef([host_cpu])dnl -popdef([host_alias])dnl -popdef([host])dnl -popdef([LDFLAGS])dnl -popdef([CPPFLAGS])dnl -popdef([CFLAGS])dnl -popdef([CPP])dnl -popdef([CC])dnl -popdef([ac_objext])dnl -popdef([ac_exeext])dnl -popdef([ac_cv_objext])dnl -popdef([ac_cv_exeext])dnl -popdef([ac_cv_prog_cc_g])dnl -popdef([ac_cv_prog_cc_cross])dnl -popdef([ac_cv_prog_cc_works])dnl -popdef([ac_cv_prog_gcc])dnl -popdef([ac_cv_prog_CPP])dnl - -dnl Finally, set Makefile variables -dnl -BUILD_EXEEXT=$ac_build_exeext -BUILD_OBJEXT=$ac_build_objext -AC_SUBST(BUILD_EXEEXT)dnl -AC_SUBST(BUILD_OBJEXT)dnl -AC_SUBST([CFLAGS_FOR_BUILD])dnl -AC_SUBST([CPPFLAGS_FOR_BUILD])dnl -AC_SUBST([LDFLAGS_FOR_BUILD])dnl -]) diff --git a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 b/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 deleted file mode 100644 index b74acb8c1..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 +++ /dev/null @@ -1,69 +0,0 @@ -dnl libsecp25k1 helper checks -AC_DEFUN([SECP_INT128_CHECK],[ -has_int128=$ac_cv_type___int128 -]) - -dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. -AC_DEFUN([SECP_64BIT_ASM_CHECK],[ -AC_MSG_CHECKING(for x86_64 assembly availability) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include ]],[[ - uint64_t a = 11, tmp; - __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); - ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) -AC_MSG_RESULT([$has_64bit_asm]) -]) - -dnl -AC_DEFUN([SECP_OPENSSL_CHECK],[ - has_libcrypto=no - m4_ifdef([PKG_CHECK_MODULES],[ - PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) - if test x"$has_libcrypto" = x"yes"; then - TEMP_LIBS="$LIBS" - LIBS="$LIBS $CRYPTO_LIBS" - AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) - LIBS="$TEMP_LIBS" - fi - ]) - if test x$has_libcrypto = xno; then - AC_CHECK_HEADER(openssl/crypto.h,[ - AC_CHECK_LIB(crypto, main,[ - has_libcrypto=yes - CRYPTO_LIBS=-lcrypto - AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed]) - ]) - ]) - LIBS= - fi -if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then - AC_MSG_CHECKING(for EC functions in libcrypto) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - #include - #include ]],[[ - EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); - ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); - ECDSA_verify(0, NULL, 0, NULL, 0, eckey); - EC_KEY_free(eckey); - ECDSA_SIG *sig_openssl; - sig_openssl = ECDSA_SIG_new(); - (void)sig_openssl->r; - ECDSA_SIG_free(sig_openssl); - ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) - AC_MSG_RESULT([$has_openssl_ec]) -fi -]) - -dnl -AC_DEFUN([SECP_GMP_CHECK],[ -if test x"$has_gmp" != x"yes"; then - CPPFLAGS_TEMP="$CPPFLAGS" - CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" - LIBS_TEMP="$LIBS" - LIBS="$GMP_LIBS $LIBS" - AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) - CPPFLAGS="$CPPFLAGS_TEMP" - LIBS="$LIBS_TEMP" -fi -]) diff --git a/builder/crypto/secp256k1/libsecp256k1/configure.ac b/builder/crypto/secp256k1/libsecp256k1/configure.ac deleted file mode 100644 index e5fcbcb4e..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/configure.ac +++ /dev/null @@ -1,493 +0,0 @@ -AC_PREREQ([2.60]) -AC_INIT([libsecp256k1],[0.1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) -AC_CANONICAL_HOST -AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) -AH_TOP([#define LIBSECP256K1_CONFIG_H]) -AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) -AM_INIT_AUTOMAKE([foreign subdir-objects]) -LT_INIT - -dnl make the compilation flags quiet unless V=1 is used -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -PKG_PROG_PKG_CONFIG - -AC_PATH_TOOL(AR, ar) -AC_PATH_TOOL(RANLIB, ranlib) -AC_PATH_TOOL(STRIP, strip) -AX_PROG_CC_FOR_BUILD - -if test "x$CFLAGS" = "x"; then - CFLAGS="-g" -fi - -AM_PROG_CC_C_O - -AC_PROG_CC_C89 -if test x"$ac_cv_prog_cc_c89" = x"no"; then - AC_MSG_ERROR([c89 compiler support required]) -fi -AM_PROG_AS - -case $host_os in - *darwin*) - if test x$cross_compiling != xyes; then - AC_PATH_PROG([BREW],brew,) - if test x$BREW != x; then - dnl These Homebrew packages may be keg-only, meaning that they won't be found - dnl in expected paths because they may conflict with system files. Ask - dnl Homebrew where each one is located, then adjust paths accordingly. - - openssl_prefix=`$BREW --prefix openssl 2>/dev/null` - gmp_prefix=`$BREW --prefix gmp 2>/dev/null` - if test x$openssl_prefix != x; then - PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH - fi - if test x$gmp_prefix != x; then - GMP_CPPFLAGS="-I$gmp_prefix/include" - GMP_LIBS="-L$gmp_prefix/lib" - fi - else - AC_PATH_PROG([PORT],port,) - dnl if homebrew isn't installed and macports is, add the macports default paths - dnl as a last resort. - if test x$PORT != x; then - CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" - fi - fi - fi - ;; -esac - -CFLAGS="$CFLAGS -W" - -warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings" -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $warn_CFLAGS" -AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fvisibility=hidden" -AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), - [use_benchmark=$enableval], - [use_benchmark=no]) - -AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), - [enable_coverage=$enableval], - [enable_coverage=no]) - -AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), - [use_tests=$enableval], - [use_tests=yes]) - -AC_ARG_ENABLE(openssl_tests, - AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), - [enable_openssl_tests=$enableval], - [enable_openssl_tests=auto]) - -AC_ARG_ENABLE(experimental, - AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), - [use_experimental=$enableval], - [use_experimental=no]) - -AC_ARG_ENABLE(exhaustive_tests, - AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), - [use_exhaustive_tests=$enableval], - [use_exhaustive_tests=yes]) - -AC_ARG_ENABLE(endomorphism, - AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), - [use_endomorphism=$enableval], - [use_endomorphism=no]) - -AC_ARG_ENABLE(ecmult_static_precomputation, - AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), - [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=auto]) - -AC_ARG_ENABLE(module_ecdh, - AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), - [enable_module_ecdh=$enableval], - [enable_module_ecdh=no]) - -AC_ARG_ENABLE(module_recovery, - AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), - [enable_module_recovery=$enableval], - [enable_module_recovery=no]) - -AC_ARG_ENABLE(jni, - AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), - [use_jni=$enableval], - [use_jni=auto]) - -AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], -[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) - -AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], -[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) - -AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], -[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) - -AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] -[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) - -AC_CHECK_TYPES([__int128]) - -AC_MSG_CHECKING([for __builtin_expect]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], - [ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ], - [ AC_MSG_RESULT([no]) - ]) - -if test x"$enable_coverage" = x"yes"; then - AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) - CFLAGS="$CFLAGS -O0 --coverage" - LDFLAGS="--coverage" -else - CFLAGS="$CFLAGS -O3" -fi - -if test x"$use_ecmult_static_precomputation" != x"no"; then - save_cross_compiling=$cross_compiling - cross_compiling=no - TEMP_CC="$CC" - CC="$CC_FOR_BUILD" - AC_MSG_CHECKING([native compiler: ${CC_FOR_BUILD}]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([], [return 0])], - [working_native_cc=yes], - [working_native_cc=no],[dnl]) - CC="$TEMP_CC" - cross_compiling=$save_cross_compiling - - if test x"$working_native_cc" = x"no"; then - set_precomp=no - if test x"$use_ecmult_static_precomputation" = x"yes"; then - AC_MSG_ERROR([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) - else - AC_MSG_RESULT([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) - fi - else - AC_MSG_RESULT([ok]) - set_precomp=yes - fi -else - set_precomp=no -fi - -if test x"$req_asm" = x"auto"; then - SECP_64BIT_ASM_CHECK - if test x"$has_64bit_asm" = x"yes"; then - set_asm=x86_64 - fi - if test x"$set_asm" = x; then - set_asm=no - fi -else - set_asm=$req_asm - case $set_asm in - x86_64) - SECP_64BIT_ASM_CHECK - if test x"$has_64bit_asm" != x"yes"; then - AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) - fi - ;; - arm) - ;; - no) - ;; - *) - AC_MSG_ERROR([invalid assembly optimization selection]) - ;; - esac -fi - -if test x"$req_field" = x"auto"; then - if test x"set_asm" = x"x86_64"; then - set_field=64bit - fi - if test x"$set_field" = x; then - SECP_INT128_CHECK - if test x"$has_int128" = x"yes"; then - set_field=64bit - fi - fi - if test x"$set_field" = x; then - set_field=32bit - fi -else - set_field=$req_field - case $set_field in - 64bit) - if test x"$set_asm" != x"x86_64"; then - SECP_INT128_CHECK - if test x"$has_int128" != x"yes"; then - AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available]) - fi - fi - ;; - 32bit) - ;; - *) - AC_MSG_ERROR([invalid field implementation selection]) - ;; - esac -fi - -if test x"$req_scalar" = x"auto"; then - SECP_INT128_CHECK - if test x"$has_int128" = x"yes"; then - set_scalar=64bit - fi - if test x"$set_scalar" = x; then - set_scalar=32bit - fi -else - set_scalar=$req_scalar - case $set_scalar in - 64bit) - SECP_INT128_CHECK - if test x"$has_int128" != x"yes"; then - AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available]) - fi - ;; - 32bit) - ;; - *) - AC_MSG_ERROR([invalid scalar implementation selected]) - ;; - esac -fi - -if test x"$req_bignum" = x"auto"; then - SECP_GMP_CHECK - if test x"$has_gmp" = x"yes"; then - set_bignum=gmp - fi - - if test x"$set_bignum" = x; then - set_bignum=no - fi -else - set_bignum=$req_bignum - case $set_bignum in - gmp) - SECP_GMP_CHECK - if test x"$has_gmp" != x"yes"; then - AC_MSG_ERROR([gmp bignum explicitly requested but libgmp not available]) - fi - ;; - no) - ;; - *) - AC_MSG_ERROR([invalid bignum implementation selection]) - ;; - esac -fi - -# select assembly optimization -use_external_asm=no - -case $set_asm in -x86_64) - AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) - ;; -arm) - use_external_asm=yes - ;; -no) - ;; -*) - AC_MSG_ERROR([invalid assembly optimizations]) - ;; -esac - -# select field implementation -case $set_field in -64bit) - AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) - ;; -32bit) - AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) - ;; -*) - AC_MSG_ERROR([invalid field implementation]) - ;; -esac - -# select bignum implementation -case $set_bignum in -gmp) - AC_DEFINE(HAVE_LIBGMP, 1, [Define this symbol if libgmp is installed]) - AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation for num]) - AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation]) - AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation]) - ;; -no) - AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation]) - AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation]) - AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation]) - ;; -*) - AC_MSG_ERROR([invalid bignum implementation]) - ;; -esac - -#select scalar implementation -case $set_scalar in -64bit) - AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) - ;; -32bit) - AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) - ;; -*) - AC_MSG_ERROR([invalid scalar implementation]) - ;; -esac - -if test x"$use_tests" = x"yes"; then - SECP_OPENSSL_CHECK - if test x"$has_openssl_ec" = x"yes"; then - if test x"$enable_openssl_tests" != x"no"; then - AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) - SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" - SECP_TEST_LIBS="$CRYPTO_LIBS" - - case $host in - *mingw*) - SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" - ;; - esac - fi - else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) - fi - fi -else - if test x"$enable_openssl_tests" = x"yes"; then - AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) - fi -fi - -if test x"$use_jni" != x"no"; then - AX_JNI_INCLUDE_DIR - have_jni_dependencies=yes - if test x"$enable_module_ecdh" = x"no"; then - have_jni_dependencies=no - fi - if test "x$JNI_INCLUDE_DIRS" = "x"; then - have_jni_dependencies=no - fi - if test "x$have_jni_dependencies" = "xno"; then - if test x"$use_jni" = x"yes"; then - AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) - fi - AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) - use_jni=no - else - use_jni=yes - for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do - JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" - done - fi -fi - -if test x"$set_bignum" = x"gmp"; then - SECP_LIBS="$SECP_LIBS $GMP_LIBS" - SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" -fi - -if test x"$use_endomorphism" = x"yes"; then - AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) -fi - -if test x"$set_precomp" = x"yes"; then - AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) -fi - -if test x"$enable_module_ecdh" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) -fi - -if test x"$enable_module_recovery" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) -fi - -AC_C_BIGENDIAN() - -if test x"$use_external_asm" = x"yes"; then - AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) -fi - -AC_MSG_NOTICE([Using static precomputation: $set_precomp]) -AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) -AC_MSG_NOTICE([Using field implementation: $set_field]) -AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) -AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) -AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) -AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) -AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) -AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) -AC_MSG_NOTICE([Using jni: $use_jni]) - -if test x"$enable_experimental" = x"yes"; then - AC_MSG_NOTICE([******]) - AC_MSG_NOTICE([WARNING: experimental build]) - AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) - AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) - AC_MSG_NOTICE([******]) -else - if test x"$enable_module_ecdh" = x"yes"; then - AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) - fi - if test x"$set_asm" = x"arm"; then - AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) - fi -fi - -AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) -AC_CONFIG_FILES([Makefile libsecp256k1.pc]) -AC_SUBST(JNI_INCLUDES) -AC_SUBST(SECP_INCLUDES) -AC_SUBST(SECP_LIBS) -AC_SUBST(SECP_TEST_LIBS) -AC_SUBST(SECP_TEST_INCLUDES) -AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) -AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) -AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) -AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) -AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) -AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) -AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) -AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) - -dnl make sure nothing new is exported so that we don't break the cache -PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" -unset PKG_CONFIG_PATH -PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" - -AC_OUTPUT diff --git a/builder/crypto/secp256k1/libsecp256k1/contrib/dummy.go b/builder/crypto/secp256k1/libsecp256k1/contrib/dummy.go deleted file mode 100644 index 2c946210c..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/contrib/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package contrib diff --git a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c b/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c deleted file mode 100644 index 5b141a994..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c +++ /dev/null @@ -1,150 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "lax_der_parsing.h" - -int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - size_t rpos, rlen, spos, slen; - size_t pos = 0; - size_t lenbyte; - unsigned char tmpsig[64] = {0}; - int overflow = 0; - - /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - - /* Sequence tag byte */ - if (pos == inputlen || input[pos] != 0x30) { - return 0; - } - pos++; - - /* Sequence length bytes */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - pos += lenbyte; - } - - /* Integer tag byte for R */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for R */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - rlen = 0; - while (lenbyte > 0) { - rlen = (rlen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - rlen = lenbyte; - } - if (rlen > inputlen - pos) { - return 0; - } - rpos = pos; - pos += rlen; - - /* Integer tag byte for S */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for S */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - slen = 0; - while (lenbyte > 0) { - slen = (slen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - slen = lenbyte; - } - if (slen > inputlen - pos) { - return 0; - } - spos = pos; - pos += slen; - - /* Ignore leading zeroes in R */ - while (rlen > 0 && input[rpos] == 0) { - rlen--; - rpos++; - } - /* Copy R value */ - if (rlen > 32) { - overflow = 1; - } else { - memcpy(tmpsig + 32 - rlen, input + rpos, rlen); - } - - /* Ignore leading zeroes in S */ - while (slen > 0 && input[spos] == 0) { - slen--; - spos++; - } - /* Copy S value */ - if (slen > 32) { - overflow = 1; - } else { - memcpy(tmpsig + 64 - slen, input + spos, slen); - } - - if (!overflow) { - overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - if (overflow) { - memset(tmpsig, 0, 64); - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - return 1; -} - diff --git a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h b/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h deleted file mode 100644 index 6d27871a7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h +++ /dev/null @@ -1,91 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file defines a function that parses DER with various errors and - * violations. This is not a part of the library itself, because the allowed - * violations are chosen arbitrarily and do not follow or establish any - * standard. - * - * In many places it matters that different implementations do not only accept - * the same set of valid signatures, but also reject the same set of signatures. - * The only means to accomplish that is by strictly obeying a standard, and not - * accepting anything else. - * - * Nonetheless, sometimes there is a need for compatibility with systems that - * use signatures which do not strictly obey DER. The snippet below shows how - * certain violations are easily supported. You may need to adapt it. - * - * Do not use this for new systems. Use well-defined DER or compact signatures - * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and - * secp256k1_ecdsa_signature_parse_compact). - * - * The supported violations are: - * - All numbers are parsed as nonnegative integers, even though X.609-0207 - * section 8.3.3 specifies that integers are always encoded as two's - * complement. - * - Integers can have length 0, even though section 8.3.1 says they can't. - * - Integers with overly long padding are accepted, violation section - * 8.3.2. - * - 127-byte long length descriptors are accepted, even though section - * 8.1.3.5.c says that they are not. - * - Trailing garbage data inside or after the signature is ignored. - * - The length descriptor of the sequence is ignored. - * - * Compared to for example OpenSSL, many violations are NOT supported: - * - Using overly long tag descriptors for the sequence or integers inside, - * violating section 8.1.2.2. - * - Encoding primitive integers as constructed values, violating section - * 8.3.1. - */ - -#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ -#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ - -#include - -# ifdef __cplusplus -extern "C" { -# endif - -/** Parse a signature in "lax DER" format - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. In addition, it will accept signatures - * which violate the DER spec in various ways. Its purpose is to allow - * validation of the Bitcoin blockchain, which includes non-DER signatures - * from before the network rules were updated to enforce DER. Note that - * the set of supported violations is a strict subset of what OpenSSL will - * accept. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is - * guaranteed to fail for every message and public key. - */ -int ecdsa_signature_parse_der_lax( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c b/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c deleted file mode 100644 index c2e63b4b8..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c +++ /dev/null @@ -1,113 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "lax_der_privatekey_parsing.h" - -int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { - const unsigned char *end = privkey + privkeylen; - int lenb = 0; - int len = 0; - memset(out32, 0, 32); - /* sequence header */ - if (end < privkey+1 || *privkey != 0x30) { - return 0; - } - privkey++; - /* sequence length constructor */ - if (end < privkey+1 || !(*privkey & 0x80)) { - return 0; - } - lenb = *privkey & ~0x80; privkey++; - if (lenb < 1 || lenb > 2) { - return 0; - } - if (end < privkey+lenb) { - return 0; - } - /* sequence length */ - len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); - privkey += lenb; - if (end < privkey+len) { - return 0; - } - /* sequence element 0: version number (=1) */ - if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { - return 0; - } - privkey += 3; - /* sequence element 1: octet string, up to 32 bytes */ - if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { - return 0; - } - memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); - if (!secp256k1_ec_seckey_verify(ctx, out32)) { - memset(out32, 0, 32); - return 0; - } - return 1; -} - -int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { - secp256k1_pubkey pubkey; - size_t pubkeylen = 0; - if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { - *privkeylen = 0; - return 0; - } - if (compressed) { - static const unsigned char begin[] = { - 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 33; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } else { - static const unsigned char begin[] = { - 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, - 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, - 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 65; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } - return 1; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h b/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h deleted file mode 100644 index 2fd088f8a..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h +++ /dev/null @@ -1,90 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file contains code snippets that parse DER private keys with - * various errors and violations. This is not a part of the library - * itself, because the allowed violations are chosen arbitrarily and - * do not follow or establish any standard. - * - * It also contains code to serialize private keys in a compatible - * manner. - * - * These functions are meant for compatibility with applications - * that require BER encoded keys. When working with secp256k1-specific - * code, the simple 32-byte private keys normally used by the - * library are sufficient. - */ - -#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ -#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ - -#include - -# ifdef __cplusplus -extern "C" { -# endif - -/** Export a private key in DER format. - * - * Returns: 1 if the private key was valid. - * Args: ctx: pointer to a context object, initialized for signing (cannot - * be NULL) - * Out: privkey: pointer to an array for storing the private key in BER. - * Should have space for 279 bytes, and cannot be NULL. - * privkeylen: Pointer to an int where the length of the private key in - * privkey will be stored. - * In: seckey: pointer to a 32-byte secret key to export. - * compressed: 1 if the key should be exported in - * compressed format, 0 otherwise - * - * This function is purely meant for compatibility with applications that - * require BER encoded keys. When working with secp256k1-specific code, the - * simple 32-byte private keys are sufficient. - * - * Note that this function does not guarantee correct DER output. It is - * guaranteed to be parsable by secp256k1_ec_privkey_import_der - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( - const secp256k1_context* ctx, - unsigned char *privkey, - size_t *privkeylen, - const unsigned char *seckey, - int compressed -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Import a private key in DER format. - * Returns: 1 if a private key was extracted. - * Args: ctx: pointer to a context object (cannot be NULL). - * Out: seckey: pointer to a 32-byte array for storing the private key. - * (cannot be NULL). - * In: privkey: pointer to a private key in DER format (cannot be NULL). - * privkeylen: length of the DER private key pointed to be privkey. - * - * This function will accept more than just strict DER, and even allow some BER - * violations. The public key stored inside the DER-encoded private key is not - * verified for correctness, nor are the curve parameters. Use this function - * only if you know in advance it is supposed to contain a secp256k1 private - * key. - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *privkey, - size_t privkeylen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/dummy.go b/builder/crypto/secp256k1/libsecp256k1/dummy.go deleted file mode 100644 index 04bbe3d76..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package libsecp256k1 diff --git a/builder/crypto/secp256k1/libsecp256k1/include/dummy.go b/builder/crypto/secp256k1/libsecp256k1/include/dummy.go deleted file mode 100644 index 64c71b845..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/include/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package include diff --git a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1.h b/builder/crypto/secp256k1/libsecp256k1/include/secp256k1.h deleted file mode 100644 index f268e309d..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1.h +++ /dev/null @@ -1,577 +0,0 @@ -#ifndef _SECP256K1_ -# define _SECP256K1_ - -# ifdef __cplusplus -extern "C" { -# endif - -#include - -/* These rules specify the order of arguments in API calls: - * - * 1. Context pointers go first, followed by output arguments, combined - * output/input arguments, and finally input-only arguments. - * 2. Array lengths always immediately the follow the argument whose length - * they describe, even if this violates rule 1. - * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated - * later go first. This means: signatures, public nonces, private nonces, - * messages, public keys, secret keys, tweaks. - * 4. Arguments that are not data pointers go last, from more complex to less - * complex: function pointers, algorithm names, messages, void pointers, - * counts, flags, booleans. - * 5. Opaque data pointers follow the function pointer they are to be passed to. - */ - -/** Opaque data structure that holds context information (precomputed tables etc.). - * - * The purpose of context structures is to cache large precomputed data tables - * that are expensive to construct, and also to maintain the randomization data - * for blinding. - * - * Do not create a new context object for each operation, as construction is - * far slower than all other API calls (~100 times slower than an ECDSA - * verification). - * - * A constructed context can safely be used from multiple threads - * simultaneously, but API call that take a non-const pointer to a context - * need exclusive access to it. In particular this is the case for - * secp256k1_context_destroy and secp256k1_context_randomize. - * - * Regarding randomization, either do it once at creation time (in which case - * you do not need any locking for the other calls), or use a read-write lock. - */ -typedef struct secp256k1_context_struct secp256k1_context; - -/** Opaque data structure that holds a parsed and valid public key. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. - */ -typedef struct { - unsigned char data[64]; -} secp256k1_pubkey; - -/** Opaque data structured that holds a parsed ECDSA signature. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_serialize_* functions. - */ -typedef struct { - unsigned char data[64]; -} secp256k1_ecdsa_signature; - -/** A pointer to a function to deterministically generate a nonce. - * - * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. - * Out: nonce32: pointer to a 32-byte array to be filled by the function. - * In: msg32: the 32-byte message hash being verified (will not be NULL) - * key32: pointer to a 32-byte secret key (will not be NULL) - * algo16: pointer to a 16-byte array describing the signature - * algorithm (will be NULL for ECDSA for compatibility). - * data: Arbitrary data pointer that is passed through. - * attempt: how many iterations we have tried to find a nonce. - * This will almost always be 0, but different attempt values - * are required to result in a different nonce. - * - * Except for test cases, this function should compute some cryptographic hash of - * the message, the algorithm, the key and the attempt. - */ -typedef int (*secp256k1_nonce_function)( - unsigned char *nonce32, - const unsigned char *msg32, - const unsigned char *key32, - const unsigned char *algo16, - void *data, - unsigned int attempt -); - -# if !defined(SECP256K1_GNUC_PREREQ) -# if defined(__GNUC__)&&defined(__GNUC_MINOR__) -# define SECP256K1_GNUC_PREREQ(_maj,_min) \ - ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) -# else -# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 -# endif -# endif - -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(2,7) -# define SECP256K1_INLINE __inline__ -# elif (defined(_MSC_VER)) -# define SECP256K1_INLINE __inline -# else -# define SECP256K1_INLINE -# endif -# else -# define SECP256K1_INLINE inline -# endif - -#ifndef SECP256K1_API -# if defined(_WIN32) -# ifdef SECP256K1_BUILD -# define SECP256K1_API __declspec(dllexport) -# else -# define SECP256K1_API -# endif -# elif defined(__GNUC__) && defined(SECP256K1_BUILD) -# define SECP256K1_API __attribute__ ((visibility ("default"))) -# else -# define SECP256K1_API -# endif -#endif - -/**Warning attributes - * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out - * some paranoid null checks. */ -# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) -# else -# define SECP256K1_WARN_UNUSED_RESULT -# endif -# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) -# else -# define SECP256K1_ARG_NONNULL(_x) -# endif - -/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ -#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) -#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) -#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) -/** The higher bits contain the actual data. Do not use directly. */ -#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) -#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) -#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) - -/** Flags to pass to secp256k1_context_create. */ -#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) -#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) -#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) - -/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ -#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) -#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) - -/** Create a secp256k1 context object. - * - * Returns: a newly created context object. - * In: flags: which parts of the context to initialize. - */ -SECP256K1_API secp256k1_context* secp256k1_context_create( - unsigned int flags -) SECP256K1_WARN_UNUSED_RESULT; - -/** Copies a secp256k1 context object. - * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (cannot be NULL) - */ -SECP256K1_API secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; - -/** Destroy a secp256k1 context object. - * - * The context pointer may not be used afterwards. - * Args: ctx: an existing context to destroy (cannot be NULL) - */ -SECP256K1_API void secp256k1_context_destroy( - secp256k1_context* ctx -); - -/** Set a callback function to be called when an illegal argument is passed to - * an API call. It will only trigger for violations that are mentioned - * explicitly in the header. - * - * The philosophy is that these shouldn't be dealt with through a - * specific return value, as calling code should not have branches to deal with - * the case that this code itself is broken. - * - * On the other hand, during debug stage, one would want to be informed about - * such mistakes, and the default (crashing) may be inadvisable. - * When this callback is triggered, the API function called is guaranteed not - * to cause a crash, though its return value and output arguments are - * undefined. - * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an illegal argument is - * passed to the API, taking a message and an opaque pointer - * (NULL restores a default handler that calls abort). - * data: the opaque pointer to pass to fun above. - */ -SECP256K1_API void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -) SECP256K1_ARG_NONNULL(1); - -/** Set a callback function to be called when an internal consistency check - * fails. The default is crashing. - * - * This can only trigger in case of a hardware failure, miscompilation, - * memory corruption, serious bug in the library, or other error would can - * otherwise result in undefined behaviour. It will not trigger due to mere - * incorrect usage of the API (see secp256k1_context_set_illegal_callback - * for that). After this callback returns, anything may happen, including - * crashing. - * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an internal error occurs, - * taking a message and an opaque pointer (NULL restores a default - * handler that calls abort). - * data: the opaque pointer to pass to fun above. - */ -SECP256K1_API void secp256k1_context_set_error_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -) SECP256K1_ARG_NONNULL(1); - -/** Parse a variable-length public key into the pubkey object. - * - * Returns: 1 if the public key was fully valid. - * 0 if the public key could not be parsed or is invalid. - * Args: ctx: a secp256k1 context object. - * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a - * parsed version of input. If not, its value is undefined. - * In: input: pointer to a serialized public key - * inputlen: length of the array pointed to by input - * - * This function supports parsing compressed (33 bytes, header byte 0x02 or - * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header - * byte 0x06 or 0x07) format public keys. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a pubkey object into a serialized byte sequence. - * - * Returns: 1 always. - * Args: ctx: a secp256k1 context object. - * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if - * compressed==1) byte array to place the serialized key - * in. - * In/Out: outputlen: a pointer to an integer which is initially set to the - * size of output, and is overwritten with the written - * size. - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key. - * flags: SECP256K1_EC_COMPRESSED if serialization should be in - * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. - */ -SECP256K1_API int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_pubkey* pubkey, - unsigned int flags -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Parse an ECDSA signature in compact (64 bytes) format. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to the 64-byte array to parse - * - * The signature must consist of a 32-byte big endian R value, followed by a - * 32-byte big endian S value. If R or S fall outside of [0..order-1], the - * encoding is invalid. R and S with value 0 are allowed in the encoding. - * - * After the call, sig will always be initialized. If parsing failed or R or - * S are zero, the resulting sig value is guaranteed to fail validation for any - * message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input64 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse a DER ECDSA signature. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is - * guaranteed to fail for every message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in DER format. - * - * Returns: 1 if enough space was available to serialize, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: output: a pointer to an array to store the DER serialization - * In/Out: outputlen: a pointer to a length integer. Initially, this integer - * should be set to the length of output. After the call - * it will be set to the length of the serialization (even - * if 0 was returned). - * In: sig: a pointer to an initialized signature object - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_ecdsa_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Serialize an ECDSA signature in compact (64 byte) format. - * - * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array to store the compact serialization - * In: sig: a pointer to an initialized signature object - * - * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, - unsigned char *output64, - const secp256k1_ecdsa_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Verify an ECDSA signature. - * - * Returns: 1: correct signature - * 0: incorrect or unparseable signature - * Args: ctx: a secp256k1 context object, initialized for verification. - * In: sig: the signature being verified (cannot be NULL) - * msg32: the 32-byte message hash being verified (cannot be NULL) - * pubkey: pointer to an initialized public key to verify with (cannot be NULL) - * - * To avoid accepting malleable signatures, only ECDSA signatures in lower-S - * form are accepted. - * - * If you need to accept ECDSA signatures from sources that do not obey this - * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to - * validation, but be aware that doing so results in malleable signatures. - * - * For details, see the comments for that function. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, - const secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, - const secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Convert a signature to a normalized lower-S form. - * - * Returns: 1 if sigin was not normalized, 0 if it already was. - * Args: ctx: a secp256k1 context object - * Out: sigout: a pointer to a signature to fill with the normalized form, - * or copy if the input was already normalized. (can be NULL if - * you're only interested in whether the input was already - * normalized). - * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, - * can be identical to sigout) - * - * With ECDSA a third-party can forge a second distinct signature of the same - * message, given a single initial signature, but without knowing the key. This - * is done by negating the S value modulo the order of the curve, 'flipping' - * the sign of the random point R which is not included in the signature. - * - * Forgery of the same message isn't universally problematic, but in systems - * where message malleability or uniqueness of signatures is important this can - * cause issues. This forgery can be blocked by all verifiers forcing signers - * to use a normalized form. - * - * The lower-S form reduces the size of signatures slightly on average when - * variable length encodings (such as DER) are used and is cheap to verify, - * making it a good choice. Security of always using lower-S is assured because - * anyone can trivially modify a signature after the fact to enforce this - * property anyway. - * - * The lower S value is always between 0x1 and - * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, - * inclusive. - * - * No other forms of ECDSA malleability are known and none seem likely, but - * there is no formal proof that ECDSA, even with this additional restriction, - * is free of other malleability. Commonly used serialization schemes will also - * accept various non-unique encodings, so care should be taken when this - * property is required for an application. - * - * The secp256k1_ecdsa_sign function will by default create signatures in the - * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case - * signatures come from a system that cannot enforce this property, - * secp256k1_ecdsa_signature_normalize must be called before verification. - */ -SECP256K1_API int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sigout, - const secp256k1_ecdsa_signature *sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); - -/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. - * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of - * extra entropy. - */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; - -/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; - -/** Create an ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) - * - * The created signature is always in lower-S form. See - * secp256k1_ecdsa_signature_normalize for more details. - */ -SECP256K1_API int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Verify an ECDSA secret key. - * - * Returns: 1: secret key is valid - * 0: secret key is invalid - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seckey: pointer to a 32-byte secret key (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Compute the public key for a secret key. - * - * Returns: 1: secret was valid, public key stores - * 0: secret was invalid, try again - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: pubkey: pointer to the created public key (cannot be NULL) - * In: seckey: pointer to a 32-byte private key (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a private key by adding tweak to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting private key - * would be invalid (only when the tweak is the complement of the - * private key). 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a public key by adding tweak times the generator to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting public key - * would be invalid (only when the tweak is the complement of the - * corresponding private key). 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key object. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a private key by multiplying it by a tweak. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a public key by multiplying it by a tweak value. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key obkect. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Updates the context randomization. - * Returns: 1: randomization successfully updated - * 0: error - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( - secp256k1_context* ctx, - const unsigned char *seed32 -) SECP256K1_ARG_NONNULL(1); - -/** Add a number of public keys together. - * Returns: 1: the sum of the public keys is valid. - * 0: the sum of the public keys is not valid. - * Args: ctx: pointer to a context object - * Out: out: pointer to a public key object for placing the resulting public key - * (cannot be NULL) - * In: ins: pointer to array of pointers to public keys (cannot be NULL) - * n: the number of public keys to add together (must be at least 1) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, - secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, - size_t n -) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h b/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h deleted file mode 100644 index 4b84d7a96..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _SECP256K1_ECDH_ -# define _SECP256K1_ECDH_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Compute an EC Diffie-Hellman secret in constant time - * Returns: 1: exponentiation was successful - * 0: scalar was invalid (zero or overflow) - * Args: ctx: pointer to a context object (cannot be NULL) - * Out: result: a 32-byte array which will be populated by an ECDH - * secret computed from the point and scalar - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key - * privkey: a 32-byte scalar with which to multiply the point - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( - const secp256k1_context* ctx, - unsigned char *result, - const secp256k1_pubkey *pubkey, - const unsigned char *privkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h b/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h deleted file mode 100644 index 055379725..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef _SECP256K1_RECOVERY_ -# define _SECP256K1_RECOVERY_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Opaque data structured that holds a parsed ECDSA signature, - * supporting pubkey recovery. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 65 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, use - * the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. - * - * Furthermore, it is guaranteed that identical signatures (including their - * recoverability) will have identical representation, so they can be - * memcmp'ed. - */ -typedef struct { - unsigned char data[65]; -} secp256k1_ecdsa_recoverable_signature; - -/** Parse a compact ECDSA signature (64 bytes + recovery id). - * - * Returns: 1 when the signature could be parsed, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to a 64-byte compact signature - * recid: the recovery id (0, 1, 2 or 3) - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, - const unsigned char *input64, - int recid -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Convert a recoverable signature into a normal signature. - * - * Returns: 1 - * Out: sig: a pointer to a normal signature (cannot be NULL). - * In: sigin: a pointer to a recoverable signature (cannot be NULL). - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). - * - * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) - * recid: a pointer to an integer to hold the recovery id (can be NULL). - * In: sig: a pointer to an initialized signature object (cannot be NULL) - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, - unsigned char *output64, - int *recid, - const secp256k1_ecdsa_recoverable_signature* sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Create a recoverable ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) - */ -SECP256K1_API int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Recover an ECDSA public key from a signature. - * - * Returns: 1: public key successfully recovered (which guarantees a correct signature). - * 0: otherwise. - * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) - * Out: pubkey: pointer to the recovered public key (cannot be NULL) - * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) - * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in b/builder/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in deleted file mode 100644 index a0d006f11..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libsecp256k1 -Description: Optimized C library for EC operations on curve secp256k1 -URL: https://github.com/bitcoin-core/secp256k1 -Version: @PACKAGE_VERSION@ -Cflags: -I${includedir} -Libs.private: @SECP_LIBS@ -Libs: -L${libdir} -lsecp256k1 - diff --git a/builder/crypto/secp256k1/libsecp256k1/obj/.gitignore b/builder/crypto/secp256k1/libsecp256k1/obj/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/builder/crypto/secp256k1/libsecp256k1/sage/group_prover.sage b/builder/crypto/secp256k1/libsecp256k1/sage/group_prover.sage deleted file mode 100644 index ab580c5b2..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/sage/group_prover.sage +++ /dev/null @@ -1,322 +0,0 @@ -# This code supports verifying group implementations which have branches -# or conditional statements (like cmovs), by allowing each execution path -# to independently set assumptions on input or intermediary variables. -# -# The general approach is: -# * A constraint is a tuple of two sets of of symbolic expressions: -# the first of which are required to evaluate to zero, the second of which -# are required to evaluate to nonzero. -# - A constraint is said to be conflicting if any of its nonzero expressions -# is in the ideal with basis the zero expressions (in other words: when the -# zero expressions imply that one of the nonzero expressions are zero). -# * There is a list of laws that describe the intended behaviour, including -# laws for addition and doubling. Each law is called with the symbolic point -# coordinates as arguments, and returns: -# - A constraint describing the assumptions under which it is applicable, -# called "assumeLaw" -# - A constraint describing the requirements of the law, called "require" -# * Implementations are transliterated into functions that operate as well on -# algebraic input points, and are called once per combination of branches -# exectured. Each execution returns: -# - A constraint describing the assumptions this implementation requires -# (such as Z1=1), called "assumeFormula" -# - A constraint describing the assumptions this specific branch requires, -# but which is by construction guaranteed to cover the entire space by -# merging the results from all branches, called "assumeBranch" -# - The result of the computation -# * All combinations of laws with implementation branches are tried, and: -# - If the combination of assumeLaw, assumeFormula, and assumeBranch results -# in a conflict, it means this law does not apply to this branch, and it is -# skipped. -# - For others, we try to prove the require constraints hold, assuming the -# information in assumeLaw + assumeFormula + assumeBranch, and if this does -# not succeed, we fail. -# + To prove an expression is zero, we check whether it belongs to the -# ideal with the assumed zero expressions as basis. This test is exact. -# + To prove an expression is nonzero, we check whether each of its -# factors is contained in the set of nonzero assumptions' factors. -# This test is not exact, so various combinations of original and -# reduced expressions' factors are tried. -# - If we succeed, we print out the assumptions from assumeFormula that -# weren't implied by assumeLaw already. Those from assumeBranch are skipped, -# as we assume that all constraints in it are complementary with each other. -# -# Based on the sage verification scripts used in the Explicit-Formulas Database -# by Tanja Lange and others, see http://hyperelliptic.org/EFD - -class fastfrac: - """Fractions over rings.""" - - def __init__(self,R,top,bot=1): - """Construct a fractional, given a ring, a numerator, and denominator.""" - self.R = R - if parent(top) == ZZ or parent(top) == R: - self.top = R(top) - self.bot = R(bot) - elif top.__class__ == fastfrac: - self.top = top.top - self.bot = top.bot * bot - else: - self.top = R(numerator(top)) - self.bot = R(denominator(top)) * bot - - def iszero(self,I): - """Return whether this fraction is zero given an ideal.""" - return self.top in I and self.bot not in I - - def reduce(self,assumeZero): - zero = self.R.ideal(map(numerator, assumeZero)) - return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) - - def __add__(self,other): - """Add two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top + self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __sub__(self,other): - """Subtract two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top - self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __neg__(self): - """Return the negation of a fraction.""" - return fastfrac(self.R,-self.top,self.bot) - - def __mul__(self,other): - """Multiply two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.top,self.bot * other.bot) - return NotImplemented - - def __rmul__(self,other): - """Multiply something else with a fraction.""" - return self.__mul__(other) - - def __div__(self,other): - """Divide two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top,self.bot * other) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot,self.bot * other.top) - return NotImplemented - - def __pow__(self,other): - """Compute a power of a fraction.""" - if parent(other) == ZZ: - if other < 0: - # Negative powers require flipping top and bottom - return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) - else: - return fastfrac(self.R,self.top ^ other,self.bot ^ other) - return NotImplemented - - def __str__(self): - return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" - def __repr__(self): - return "%s" % self - - def numerator(self): - return self.top - -class constraints: - """A set of constraints, consisting of zero and nonzero expressions. - - Constraints can either be used to express knowledge or a requirement. - - Both the fields zero and nonzero are maps from expressions to description - strings. The expressions that are the keys in zero are required to be zero, - and the expressions that are the keys in nonzero are required to be nonzero. - - Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in - nonzero could be multiplied into a single key. This is often much less - efficient to work with though, so we keep them separate inside the - constraints. This allows higher-level code to do fast checks on the individual - nonzero elements, or combine them if needed for stronger checks. - - We can't multiply the different zero elements, as it would suffice for one of - the factors to be zero, instead of all of them. Instead, the zero elements are - typically combined into an ideal first. - """ - - def __init__(self, **kwargs): - if 'zero' in kwargs: - self.zero = dict(kwargs['zero']) - else: - self.zero = dict() - if 'nonzero' in kwargs: - self.nonzero = dict(kwargs['nonzero']) - else: - self.nonzero = dict() - - def negate(self): - return constraints(zero=self.nonzero, nonzero=self.zero) - - def __add__(self, other): - zero = self.zero.copy() - zero.update(other.zero) - nonzero = self.nonzero.copy() - nonzero.update(other.nonzero) - return constraints(zero=zero, nonzero=nonzero) - - def __str__(self): - return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) - - def __repr__(self): - return "%s" % self - - -def conflicts(R, con): - """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" - zero = R.ideal(map(numerator, con.zero)) - if 1 in zero: - return True - # First a cheap check whether any of the individual nonzero terms conflict on - # their own. - for nonzero in con.nonzero: - if nonzero.iszero(zero): - return True - # It can be the case that entries in the nonzero set do not individually - # conflict with the zero set, but their combination does. For example, knowing - # that either x or y is zero is equivalent to having x*y in the zero set. - # Having x or y individually in the nonzero set is not a conflict, but both - # simultaneously is, so that is the right thing to check for. - if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): - return True - return False - - -def get_nonzero_set(R, assume): - """Calculate a simple set of nonzero expressions""" - zero = R.ideal(map(numerator, assume.zero)) - nonzero = set() - for nz in map(numerator, assume.nonzero): - for (f,n) in nz.factor(): - nonzero.add(f) - rnz = zero.reduce(nz) - for (f,n) in rnz.factor(): - nonzero.add(f) - return nonzero - - -def prove_nonzero(R, exprs, assume): - """Check whether an expression is provably nonzero, given assumptions""" - zero = R.ideal(map(numerator, assume.zero)) - nonzero = get_nonzero_set(R, assume) - expl = set() - ok = True - for expr in exprs: - if numerator(expr) in zero: - return (False, [exprs[expr]]) - allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) - for (f, n) in allexprs.factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for (f, n) in zero.reduce(numerator(allexprs)).factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in numerator(expr).factor(): - if f not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in zero.reduce(numerator(expr)).factor(): - if f not in nonzero: - expl.add(exprs[expr]) - if expl: - return (False, list(expl)) - else: - return (True, None) - - -def prove_zero(R, exprs, assume): - """Check whether all of the passed expressions are provably zero, given assumptions""" - r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) - if not r: - return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) - zero = R.ideal(map(numerator, assume.zero)) - nonzero = prod(x for x in assume.nonzero) - expl = [] - for expr in exprs: - if not expr.iszero(zero): - expl.append(exprs[expr]) - if not expl: - return (True, None) - return (False, expl) - - -def describe_extra(R, assume, assumeExtra): - """Describe what assumptions are added, given existing assumptions""" - zerox = assume.zero.copy() - zerox.update(assumeExtra.zero) - zero = R.ideal(map(numerator, assume.zero)) - zeroextra = R.ideal(map(numerator, zerox)) - nonzero = get_nonzero_set(R, assume) - ret = set() - # Iterate over the extra zero expressions - for base in assumeExtra.zero: - if base not in zero: - add = [] - for (f, n) in numerator(base).factor(): - if f not in nonzero: - add += ["%s" % f] - if add: - ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) - # Iterate over the extra nonzero expressions - for nz in assumeExtra.nonzero: - nzr = zeroextra.reduce(numerator(nz)) - if nzr not in zeroextra: - for (f,n) in nzr.factor(): - if zeroextra.reduce(f) not in nonzero: - ret.add("%s != 0" % zeroextra.reduce(f)) - return ", ".join(x for x in ret) - - -def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): - """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" - assume = assumeLaw + assumeAssert + assumeBranch - - if conflicts(R, assume): - # This formula does not apply - return None - - describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) - - ok, msg = prove_zero(R, require.zero, assume) - if not ok: - return "FAIL, %s fails (assuming %s)" % (str(msg), describe) - - res, expl = prove_nonzero(R, require.nonzero, assume) - if not res: - return "FAIL, %s fails (assuming %s)" % (str(expl), describe) - - if describe != "": - return "OK (assuming %s)" % describe - else: - return "OK" - - -def concrete_verify(c): - for k in c.zero: - if k != 0: - return (False, c.zero[k]) - for k in c.nonzero: - if k == 0: - return (False, c.nonzero[k]) - return (True, None) diff --git a/builder/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage b/builder/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage deleted file mode 100644 index a97e732f7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage +++ /dev/null @@ -1,306 +0,0 @@ -# Test libsecp256k1' group operation implementations using prover.sage - -import sys - -load("group_prover.sage") -load("weierstrass_prover.sage") - -def formula_secp256k1_gej_double_var(a): - """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" - rz = a.Z * a.Y - rz = rz * 2 - t1 = a.X^2 - t1 = t1 * 3 - t2 = t1^2 - t3 = a.Y^2 - t3 = t3 * 2 - t4 = t3^2 - t4 = t4 * 2 - t3 = t3 * a.X - rx = t3 - rx = rx * 4 - rx = -rx - rx = rx + t2 - t2 = -t2 - t3 = t3 * 6 - t3 = t3 + t2 - ry = t1 * t3 - t2 = -t4 - ry = ry + t2 - return jacobianpoint(rx, ry, rz) - -def formula_secp256k1_gej_add_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_var""" - if branch == 0: - return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z22 = b.Z^2 - z12 = a.Z^2 - u1 = a.X * z22 - u2 = b.X * z12 - s1 = a.Y * z22 - s1 = s1 * b.Z - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) - if branch == 3: - return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h2 * h - h = h * b.Z - rz = a.Z * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" - if branch == 0: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z12 = a.Z^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if (branch == 2): - r = formula_secp256k1_gej_double_var(a) - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if (branch == 3): - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h * h2 - rz = a.Z * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_zinv_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_zinv_var""" - bzinv = b.Z^(-1) - if branch == 0: - return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) - if branch == 1: - bzinv2 = bzinv^2 - bzinv3 = bzinv2 * bzinv - rx = b.X * bzinv2 - ry = b.Y * bzinv3 - rz = 1 - return (constraints(), constraints(zero={b.Infinity : 'b_finite'}, nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz)) - azz = a.Z * bzinv - z12 = azz^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * azz - h = -u1 - h = h + u2 - i = -s1 - i = i + s2 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if branch == 3: - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - i2 = i^2 - h2 = h^2 - h3 = h * h2 - rz = a.Z - rz = rz * h - t = u1 * h2 - rx = t - rx = rx * 2 - rx = rx + h3 - rx = -rx - rx = rx + i2 - ry = -rx - ry = ry + t - ry = ry * i - h3 = h3 * s1 - h3 = -h3 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge""" - zeroes = {} - nonzeroes = {} - a_infinity = False - if (branch & 4) != 0: - nonzeroes.update({a.Infinity : 'a_infinite'}) - a_infinity = True - else: - zeroes.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - rr = t^2 - m_alt = -u2 - tt = u1 * m_alt - rr = rr + tt - degenerate = (branch & 3) == 3 - if (branch & 1) != 0: - zeroes.update({m : 'm_zero'}) - else: - nonzeroes.update({m : 'm_nonzero'}) - if (branch & 2) != 0: - zeroes.update({rr : 'rr_zero'}) - else: - nonzeroes.update({rr : 'rr_nonzero'}) - rr_alt = s1 - rr_alt = rr_alt * 2 - m_alt = m_alt + u1 - if not degenerate: - rr_alt = rr - m_alt = m - n = m_alt^2 - q = n * t - n = n^2 - if degenerate: - n = m - t = rr_alt^2 - rz = a.Z * m_alt - infinity = False - if (branch & 8) != 0: - if not a_infinity: - infinity = True - zeroes.update({rz : 'r.z=0'}) - else: - nonzeroes.update({rz : 'r.z!=0'}) - rz = rz * 2 - q = -q - t = t + q - rx = t - t = t * 2 - t = t + q - t = t * rr_alt - t = t + n - ry = -t - rx = rx * 4 - ry = ry * 4 - if a_infinity: - rx = b.X - ry = b.Y - rz = 1 - if infinity: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_old(branch, a, b): - """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" - a_infinity = (branch & 1) != 0 - zero = {} - nonzero = {} - if a_infinity: - nonzero.update({a.Infinity : 'a_infinite'}) - else: - zero.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - z = a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - n = m^2 - q = n * t - n = n^2 - rr = t^2 - t = u1 * u2 - t = -t - rr = rr + t - t = rr^2 - rz = m * z - infinity = False - if (branch & 2) != 0: - if not a_infinity: - infinity = True - else: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) - zero.update({rz : 'r.z=0'}) - else: - nonzero.update({rz : 'r.z!=0'}) - rz = rz * (0 if a_infinity else 2) - rx = t - q = -q - rx = rx + q - q = q * 3 - t = t * 2 - t = t + q - t = t * rr - t = t + n - ry = -t - rx = rx * (0 if a_infinity else 4) - ry = ry * (0 if a_infinity else 4) - t = b.X - t = t * (1 if a_infinity else 0) - rx = rx + t - t = b.Y - t = t * (1 if a_infinity else 0) - ry = ry + t - t = (1 if a_infinity else 0) - rz = rz + t - if infinity: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) - -if __name__ == "__main__": - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) - - if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) diff --git a/builder/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage b/builder/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage deleted file mode 100644 index 03ef2ec90..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage +++ /dev/null @@ -1,264 +0,0 @@ -# Prover implementation for Weierstrass curves of the form -# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws -# operating on affine and Jacobian coordinates, including the point at infinity -# represented by a 4th variable in coordinates. - -load("group_prover.sage") - - -class affinepoint: - def __init__(self, x, y, infinity=0): - self.x = x - self.y = y - self.infinity = infinity - def __str__(self): - return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) - - -class jacobianpoint: - def __init__(self, x, y, z, infinity=0): - self.X = x - self.Y = y - self.Z = z - self.Infinity = infinity - def __str__(self): - return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) - - -def point_at_infinity(): - return jacobianpoint(1, 1, 1, 1) - - -def negate(p): - if p.__class__ == affinepoint: - return affinepoint(p.x, -p.y) - if p.__class__ == jacobianpoint: - return jacobianpoint(p.X, -p.Y, p.Z) - assert(False) - - -def on_weierstrass_curve(A, B, p): - """Return a set of zero-expressions for an affine point to be on the curve""" - return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) - - -def tangential_to_weierstrass_curve(A, B, p12, p3): - """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" - return constraints(zero={ - (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' - }) - - -def colinear(p1, p2, p3): - """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" - return constraints(zero={ - (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', - (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', - (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' - }) - - -def good_affine_point(p): - return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) - - -def good_jacobian_point(p): - return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) - - -def good_point(p): - return constraints(nonzero={p.Z^6 : 'nonzero_X'}) - - -def finite(p, *affine_fns): - con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) - if p.Z != 0: - return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) - else: - return con - -def infinite(p): - return constraints(nonzero={p.Infinity : 'infinite_point'}) - - -def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(nonzero={pa.x - pb.x : 'different_x'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - colinear(pa, pb, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) - require = infinite(pC) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pb) + - infinite(pA) + - finite(pB)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - infinite(pB) + - finite(pA)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - infinite(pA) + - infinite(pB)) - require = infinite(pC) - return (assumeLaw, require) - - -laws_jacobian_weierstrass = { - 'add': law_jacobian_weierstrass_add, - 'double': law_jacobian_weierstrass_double, - 'add_opposite': law_jacobian_weierstrass_add_opposites, - 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, - 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, - 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab -} - - -def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" - F = Integers(p) - print "Formula %s on Z%i:" % (name, p) - points = [] - for x in xrange(0, p): - for y in xrange(0, p): - point = affinepoint(F(x), F(y)) - r, e = concrete_verify(on_weierstrass_curve(A, B, point)) - if r: - points.append(point) - - for za in xrange(1, p): - for zb in xrange(1, p): - for pa in points: - for pb in points: - for ia in xrange(2): - for ib in xrange(2): - pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) - pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) - for branch in xrange(0, branches): - assumeAssert, assumeBranch, pC = formula(branch, pA, pB) - pC.X = F(pC.X) - pC.Y = F(pC.Y) - pC.Z = F(pC.Z) - pC.Infinity = F(pC.Infinity) - r, e = concrete_verify(assumeAssert + assumeBranch) - if r: - match = False - for key in laws_jacobian_weierstrass: - assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) - r, e = concrete_verify(assumeLaw) - if r: - if match: - print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) - else: - match = True - r, e = concrete_verify(require) - if not r: - print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) - print - - -def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): - assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) - return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) - -def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" - R. = PolynomialRing(QQ,8,order='invlex') - lift = lambda x: fastfrac(R,x) - ax = lift(ax) - ay = lift(ay) - Az = lift(Az) - bx = lift(bx) - by = lift(by) - Bz = lift(Bz) - Ai = lift(Ai) - Bi = lift(Bi) - - pa = affinepoint(ax, ay, Ai) - pb = affinepoint(bx, by, Bi) - pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) - pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) - - res = {} - - for key in laws_jacobian_weierstrass: - res[key] = [] - - print ("Formula " + name + ":") - count = 0 - for branch in xrange(branches): - assumeFormula, assumeBranch, pC = formula(branch, pA, pB) - pC.X = lift(pC.X) - pC.Y = lift(pC.Y) - pC.Z = lift(pC.Z) - pC.Infinity = lift(pC.Infinity) - - for key in laws_jacobian_weierstrass: - res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) - - for key in res: - print " %s:" % key - val = res[key] - for x in val: - if x[0] is not None: - print " branch %i: %s" % (x[1], x[0]) - - print diff --git a/builder/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s b/builder/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s deleted file mode 100644 index 5a9cc3ffc..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s +++ /dev/null @@ -1,919 +0,0 @@ -@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: -/********************************************************************** - * Copyright (c) 2014 Wladimir J. van der Laan * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ -/* -ARM implementation of field_10x26 inner loops. - -Note: - -- To avoid unnecessary loads and make use of available registers, two - 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the even passes - -*/ - - .syntax unified - .arch armv7-a - @ eabi attributes - see readelf -A - .eabi_attribute 8, 1 @ Tag_ARM_ISA_use = yes - .eabi_attribute 9, 0 @ Tag_Thumb_ISA_use = no - .eabi_attribute 10, 0 @ Tag_FP_arch = none - .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte - .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP - .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed - .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 - .text - - @ Field constants - .set field_R0, 0x3d10 - .set field_R1, 0x400 - .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff - - .align 2 - .global secp256k1_fe_mul_inner - .type secp256k1_fe_mul_inner, %function - @ Arguments: - @ r0 r Restrict: can overlap with a, not with b - @ r1 a - @ r2 b - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_mul_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r7,r8 scratch - r1 a (pointer) - r2 b (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - - /* A - interleaved with B */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #9*4] @ b[9] - ldr r0, [r1, #1*4] @ a[1] - umull r5, r6, r7, r8 @ d = a[0] * b[9] - ldr r14, [r2, #8*4] @ b[8] - umull r9, r10, r0, r8 @ d' = a[1] * b[9] - ldr r7, [r1, #2*4] @ a[2] - umlal r5, r6, r0, r14 @ d += a[1] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r14 @ d' += a[2] * b[8] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r8 @ d += a[2] * b[7] - ldr r14, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r8 @ d' += a[3] * b[7] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r14 @ d += a[3] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r14 @ d' += a[4] * b[6] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r8 @ d += a[4] * b[5] - ldr r14, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r8 @ d' += a[5] * b[5] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r14 @ d += a[5] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r14 @ d' += a[6] * b[4] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[3] - ldr r14, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r8 @ d' += a[7] * b[3] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[7] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r9, r10, r7, r14 @ d' += a[8] * b[2] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r8 @ d += a[8] * b[1] - ldr r14, [r2, #0*4] @ b[0] - umlal r9, r10, r0, r8 @ d' += a[9] * b[1] - ldr r7, [r1, #0*4] @ a[0] - umlal r5, r6, r0, r14 @ d += a[9] * b[0] - @ r7,r14 used in B - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 4*9] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - umull r3, r4, r7, r14 @ c = a[0] * b[0] - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C - interleaved with D */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #2*4] @ b[2] - ldr r14, [r2, #1*4] @ b[1] - umull r11, r12, r7, r8 @ c' = a[0] * b[2] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[1] * b[1] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[2] * b[0] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r14 @ d += a[2] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[3] * b[9] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r8 @ d += a[3] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[4] * b[8] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r14 @ d += a[4] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[5] * b[7] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r8 @ d += a[5] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r8 @ d' += a[6] * b[6] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r14 @ d' += a[7] * b[5] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r8 @ d' += a[8] * b[4] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r14 @ d' += a[9] * b[3] - umlal r5, r6, r0, r8 @ d += a[9] * b[2] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E - interleaved with F */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #4*4] @ b[4] - umull r11, r12, r7, r8 @ c' = a[0] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r3, r4, r7, r8 @ c += a[0] * b[3] - ldr r7, [r1, #1*4] @ a[1] - umlal r11, r12, r7, r8 @ c' += a[1] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r3, r4, r7, r8 @ c += a[1] * b[2] - ldr r7, [r1, #2*4] @ a[2] - umlal r11, r12, r7, r8 @ c' += a[2] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r3, r4, r7, r8 @ c += a[2] * b[1] - ldr r7, [r1, #3*4] @ a[3] - umlal r11, r12, r7, r8 @ c' += a[3] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r3, r4, r7, r8 @ c += a[3] * b[0] - ldr r7, [r1, #4*4] @ a[4] - umlal r11, r12, r7, r8 @ c' += a[4] * b[0] - ldr r8, [r2, #9*4] @ b[9] - umlal r5, r6, r7, r8 @ d += a[4] * b[9] - ldr r7, [r1, #5*4] @ a[5] - umull r9, r10, r7, r8 @ d' = a[5] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umlal r5, r6, r7, r8 @ d += a[5] * b[8] - ldr r7, [r1, #6*4] @ a[6] - umlal r9, r10, r7, r8 @ d' += a[6] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[7] - ldr r7, [r1, #7*4] @ a[7] - umlal r9, r10, r7, r8 @ d' += a[7] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r5, r6, r7, r8 @ d += a[7] * b[6] - ldr r7, [r1, #8*4] @ a[8] - umlal r9, r10, r7, r8 @ d' += a[8] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r5, r6, r7, r8 @ d += a[8] * b[5] - ldr r7, [r1, #9*4] @ a[9] - umlal r9, r10, r7, r8 @ d' += a[9] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r5, r6, r7, r8 @ d += a[9] * b[4] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G - interleaved with H */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #6*4] @ b[6] - ldr r14, [r2, #5*4] @ b[5] - umull r11, r12, r7, r8 @ c' = a[0] * b[6] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[1] * b[5] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[2] * b[4] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[3] * b[3] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[4] * b[2] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[5] * b[1] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[6] * b[0] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[7] * b[9] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[8] * b[8] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[9] * b[7] - umlal r5, r6, r0, r8 @ d += a[9] * b[6] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I - interleaved with J */ - ldr r8, [r2, #8*4] @ b[8] - ldr r7, [r1, #0*4] @ a[0] - ldr r14, [r2, #7*4] @ b[7] - umull r11, r12, r7, r8 @ c' = a[0] * b[8] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r11, r12, r0, r14 @ c' += a[1] * b[7] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r11, r12, r7, r8 @ c' += a[2] * b[6] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[3] * b[5] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[4] * b[4] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[5] * b[3] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[6] * b[2] - ldr r0, [r1, #7*4] @ a[7] - umlal r3, r4, r7, r14 @ c += a[6] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[7] * b[1] - ldr r7, [r1, #8*4] @ a[8] - umlal r3, r4, r0, r8 @ c += a[7] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[8] * b[0] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[9] * b[9] - umlal r5, r6, r0, r8 @ d += a[9] * b[8] - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner - - .align 2 - .global secp256k1_fe_sqr_inner - .type secp256k1_fe_sqr_inner, %function - @ Arguments: - @ r0 r Can overlap with a - @ r1 a - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_sqr_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r2,r7,r8 scratch - r1 a (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - /* A interleaved with B */ - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r7, [r1, #0*4] @ a[0] - mov r0, r0, asl #1 - ldr r14, [r1, #9*4] @ a[9] - umull r3, r4, r7, r7 @ c = a[0] * a[0] - ldr r8, [r1, #8*4] @ a[8] - mov r7, r7, asl #1 - umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] - ldr r7, [r1, #2*4] @ a[2]*2 - umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #3*4] @ a[3]*2 - umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] - ldr r14, [r1, #5*4] @ a[5] - mov r7, r7, asl #1 - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] - umlal r9, r10, r14, r14 @ d' += a[5] * a[5] - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 9*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C interleaved with D */ - ldr r0, [r1, #0*4] @ a[0]*2 - ldr r14, [r1, #1*4] @ a[1] - mov r0, r0, asl #1 - ldr r8, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] - mov r7, r8, asl #1 @ a[2]*2 - umull r11, r12, r14, r14 @ c' = a[1] * a[1] - ldr r14, [r1, #9*4] @ a[9] - umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] - ldr r0, [r1, #3*4] @ a[3]*2 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] - umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] - umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] - umlal r9, r10, r8, r8 @ d' += a[6] * a[6] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E interleaved with F */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r14, [r1, #2*4] @ a[2] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - ldr r2, [r1, #4*4] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] - mov r2, r2, asl #1 @ a[4]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] - ldr r8, [r1, #9*4] @ a[9] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r11, r12, r14, r14 @ c' += a[2] * a[2] - ldr r14, [r1, #8*4] @ a[8] - mov r0, r0, asl #1 - umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] - ldr r7, [r1, #6*4] @ a[6]*2 - umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] - umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] - umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] - umlal r9, r10, r8, r8 @ d' += a[7] * a[7] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G interleaved with H */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #5*4] @ a[5] - ldr r2, [r1, #6*4] @ a[6] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] - mov r0, r2, asl #1 @ a[6]*2 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] - ldr r14, [r1, #9*4] @ a[9] - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] - ldr r7, [r1, #7*4] @ a[7]*2 - umlal r11, r12, r8, r8 @ c' += a[3] * a[3] - mov r7, r7, asl #1 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] - umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] - umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] - umlal r9, r10, r8, r8 @ d' += a[8] * a[8] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I interleaved with J */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - ldr r2, [r1, #8*4] @ a[8] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] - ldr r14, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] - ldr r8, [r1, #5*4] @ a[5] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] - ldr r0, [r1, #3*4] @ a[3]*2 - mov r7, r7, asl #1 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] - mov r2, r2, asl #1 @ a[8]*2 - umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] - umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] - umlal r11, r12, r14, r14 @ c' += a[4] * a[4] - ldr r8, [r1, #9*4] @ a[9] - umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] - @ r8 will be used in J - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - umlal r5, r6, r8, r8 @ d += a[9] * a[9] - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner - diff --git a/builder/crypto/secp256k1/libsecp256k1/src/basic-config.h b/builder/crypto/secp256k1/libsecp256k1/src/basic-config.h deleted file mode 100644 index c4c16eb7c..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/basic-config.h +++ /dev/null @@ -1,32 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_BASIC_CONFIG_ -#define _SECP256K1_BASIC_CONFIG_ - -#ifdef USE_BASIC_CONFIG - -#undef USE_ASM_X86_64 -#undef USE_ENDOMORPHISM -#undef USE_FIELD_10X26 -#undef USE_FIELD_5X52 -#undef USE_FIELD_INV_BUILTIN -#undef USE_FIELD_INV_NUM -#undef USE_NUM_GMP -#undef USE_NUM_NONE -#undef USE_SCALAR_4X64 -#undef USE_SCALAR_8X32 -#undef USE_SCALAR_INV_BUILTIN -#undef USE_SCALAR_INV_NUM - -#define USE_NUM_NONE 1 -#define USE_FIELD_INV_BUILTIN 1 -#define USE_SCALAR_INV_BUILTIN 1 -#define USE_FIELD_10X26 1 -#define USE_SCALAR_8X32 1 - -#endif // USE_BASIC_CONFIG -#endif // _SECP256K1_BASIC_CONFIG_ diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench.h b/builder/crypto/secp256k1/libsecp256k1/src/bench.h deleted file mode 100644 index 3a71b4aaf..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench.h +++ /dev/null @@ -1,66 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_BENCH_H_ -#define _SECP256K1_BENCH_H_ - -#include -#include -#include "sys/time.h" - -static double gettimedouble(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_usec * 0.000001 + tv.tv_sec; -} - -void print_number(double x) { - double y = x; - int c = 0; - if (y < 0.0) { - y = -y; - } - while (y < 100.0) { - y *= 10.0; - c++; - } - printf("%.*f", c, x); -} - -void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { - int i; - double min = HUGE_VAL; - double sum = 0.0; - double max = 0.0; - for (i = 0; i < count; i++) { - double begin, total; - if (setup != NULL) { - setup(data); - } - begin = gettimedouble(); - benchmark(data); - total = gettimedouble() - begin; - if (teardown != NULL) { - teardown(data); - } - if (total < min) { - min = total; - } - if (total > max) { - max = total; - } - sum += total; - } - printf("%s: min ", name); - print_number(min * 1000000.0 / iter); - printf("us / avg "); - print_number((sum / count) * 1000000.0 / iter); - printf("us / max "); - print_number(max * 1000000.0 / iter); - printf("us\n"); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c deleted file mode 100644 index cde5e2dbb..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_ecdh.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context *ctx; - secp256k1_pubkey point; - unsigned char scalar[32]; -} bench_ecdh_t; - -static void bench_ecdh_setup(void* arg) { - int i; - bench_ecdh_t *data = (bench_ecdh_t*)arg; - const unsigned char point[] = { - 0x03, - 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, - 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, - 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, - 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f - }; - - /* create a context with no capabilities */ - data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); - for (i = 0; i < 32; i++) { - data->scalar[i] = i + 1; - } - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); -} - -static void bench_ecdh(void* arg) { - int i; - unsigned char res[32]; - bench_ecdh_t *data = (bench_ecdh_t*)arg; - - for (i = 0; i < 20000; i++) { - CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); - } -} - -int main(void) { - bench_ecdh_t data; - - run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_internal.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_internal.c deleted file mode 100644 index 0809f77bd..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_internal.c +++ /dev/null @@ -1,382 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ -#include - -#include "include/secp256k1.h" - -#include "util.h" -#include "hash_impl.h" -#include "num_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_impl.h" -#include "bench.h" -#include "secp256k1.c" - -typedef struct { - secp256k1_scalar scalar_x, scalar_y; - secp256k1_fe fe_x, fe_y; - secp256k1_ge ge_x, ge_y; - secp256k1_gej gej_x, gej_y; - unsigned char data[64]; - int wnaf[256]; -} bench_inv_t; - -void bench_setup(void* arg) { - bench_inv_t *data = (bench_inv_t*)arg; - - static const unsigned char init_x[32] = { - 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, - 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, - 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, - 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 - }; - - static const unsigned char init_y[32] = { - 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, - 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, - 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, - 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 - }; - - secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); - secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); - secp256k1_fe_set_b32(&data->fe_x, init_x); - secp256k1_fe_set_b32(&data->fe_y, init_y); - CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); - CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); - secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); - secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); - memcpy(data->data, init_x, 32); - memcpy(data->data + 32, init_y, 32); -} - -void bench_scalar_add(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_scalar_negate(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); - } -} - -void bench_scalar_sqr(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); - } -} - -void bench_scalar_mul(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -#ifdef USE_ENDOMORPHISM -void bench_scalar_split(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_scalar l, r; - secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} -#endif - -void bench_scalar_inverse(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_scalar_inverse_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_field_normalize(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize(&data->fe_x); - } -} - -void bench_field_normalize_weak(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize_weak(&data->fe_x); - } -} - -void bench_field_mul(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); - } -} - -void bench_field_sqr(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_fe_sqr(&data->fe_x, &data->fe_x); - } -} - -void bench_field_inverse(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_inv(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_field_inverse_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_field_sqrt(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); - } -} - -void bench_group_double_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); - } -} - -void bench_group_add_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); - } -} - -void bench_group_add_affine(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); - } -} - -void bench_group_add_affine_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); - } -} - -void bench_group_jacobi_var(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_gej_has_quad_y_var(&data->gej_x); - } -} - -void bench_ecmult_wnaf(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - -void bench_wnaf_const(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); - } -} - - -void bench_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_sha256_t sha; - - for (i = 0; i < 20000; i++) { - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data->data, 32); - secp256k1_sha256_finalize(&sha, data->data); - } -} - -void bench_hmac_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_hmac_sha256_t hmac; - - for (i = 0; i < 20000; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); - secp256k1_hmac_sha256_write(&hmac, data->data, 32); - secp256k1_hmac_sha256_finalize(&hmac, data->data); - } -} - -void bench_rfc6979_hmac_sha256(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_rfc6979_hmac_sha256_t rng; - - for (i = 0; i < 20000; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); - } -} - -void bench_context_verify(void* arg) { - int i; - (void)arg; - for (i = 0; i < 20; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); - } -} - -void bench_context_sign(void* arg) { - int i; - (void)arg; - for (i = 0; i < 200; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); - } -} - -#ifndef USE_NUM_NONE -void bench_num_jacobi(void* arg) { - int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_num nx, norder; - - secp256k1_scalar_get_num(&nx, &data->scalar_x); - secp256k1_scalar_order_get_num(&norder); - secp256k1_scalar_get_num(&norder, &data->scalar_y); - - for (i = 0; i < 200000; i++) { - secp256k1_num_jacobi(&nx, &norder); - } -} -#endif - -int have_flag(int argc, char** argv, char *flag) { - char** argm = argv + argc; - argv++; - if (argv == argm) { - return 1; - } - while (argv != NULL && argv != argm) { - if (strcmp(*argv, flag) == 0) { - return 1; - } - argv++; - } - return 0; -} - -int main(int argc, char **argv) { - bench_inv_t data; - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000); -#ifdef USE_ENDOMORPHISM - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000); -#endif - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); - if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); - - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); - if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000); - - if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); - if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); - -#ifndef USE_NUM_NONE - if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); -#endif - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_recover.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_recover.c deleted file mode 100644 index 6489378cc..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_recover.c +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" -#include "include/secp256k1_recovery.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char sig[64]; -} bench_recover_t; - -void bench_recover(void* arg) { - int i; - bench_recover_t *data = (bench_recover_t*)arg; - secp256k1_pubkey pubkey; - unsigned char pubkeyc[33]; - - for (i = 0; i < 20000; i++) { - int j; - size_t pubkeylen = 33; - secp256k1_ecdsa_recoverable_signature sig; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); - CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - for (j = 0; j < 32; j++) { - data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ - data->msg[j] = data->sig[j]; /* Move former R to message. */ - data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ - } - } -} - -void bench_recover_setup(void* arg) { - int i; - bench_recover_t *data = (bench_recover_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (i = 0; i < 64; i++) { - data->sig[i] = 65 + i; - } -} - -int main(void) { - bench_recover_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - - run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c deleted file mode 100644 index 5f137dda2..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c +++ /dev/null @@ -1,73 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_schnorr.h" -#include "util.h" -#include "bench.h" - -typedef struct { - unsigned char key[32]; - unsigned char sig[64]; - unsigned char pubkey[33]; - size_t pubkeylen; -} benchmark_schnorr_sig_t; - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - benchmark_schnorr_sig_t sigs[64]; - int numsigs; -} benchmark_schnorr_verify_t; - -static void benchmark_schnorr_init(void* arg) { - int i, k; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (k = 0; k < data->numsigs; k++) { - secp256k1_pubkey pubkey; - for (i = 0; i < 32; i++) { - data->sigs[k].key[i] = 33 + i + k; - } - secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); - data->sigs[k].pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - } -} - -static void benchmark_schnorr_verify(void* arg) { - int i; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 20000 / data->numsigs; i++) { - secp256k1_pubkey pubkey; - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); - CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - } -} - - - -int main(void) { - benchmark_schnorr_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - data.numsigs = 1; - run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_sign.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_sign.c deleted file mode 100644 index ed7224d75..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_sign.c +++ /dev/null @@ -1,56 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" -#include "util.h" -#include "bench.h" - -typedef struct { - secp256k1_context* ctx; - unsigned char msg[32]; - unsigned char key[32]; -} bench_sign_t; - -static void bench_sign_setup(void* arg) { - int i; - bench_sign_t *data = (bench_sign_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = i + 1; - } - for (i = 0; i < 32; i++) { - data->key[i] = i + 65; - } -} - -static void bench_sign(void* arg) { - int i; - bench_sign_t *data = (bench_sign_t*)arg; - - unsigned char sig[74]; - for (i = 0; i < 20000; i++) { - size_t siglen = 74; - int j; - secp256k1_ecdsa_signature signature; - CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); - for (j = 0; j < 32; j++) { - data->msg[j] = sig[j]; - data->key[j] = sig[j + 32]; - } - } -} - -int main(void) { - bench_sign_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - - run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/bench_verify.c b/builder/crypto/secp256k1/libsecp256k1/src/bench_verify.c deleted file mode 100644 index 418defa0a..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/bench_verify.c +++ /dev/null @@ -1,112 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "util.h" -#include "bench.h" - -#ifdef ENABLE_OPENSSL_TESTS -#include -#include -#include -#endif - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char key[32]; - unsigned char sig[72]; - size_t siglen; - unsigned char pubkey[33]; - size_t pubkeylen; -#ifdef ENABLE_OPENSSL_TESTS - EC_GROUP* ec_group; -#endif -} benchmark_verify_t; - -static void benchmark_verify(void* arg) { - int i; - benchmark_verify_t* data = (benchmark_verify_t*)arg; - - for (i = 0; i < 20000; i++) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); - CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - } -} - -#ifdef ENABLE_OPENSSL_TESTS -static void benchmark_verify_openssl(void* arg) { - int i; - benchmark_verify_t* data = (benchmark_verify_t*)arg; - - for (i = 0; i < 20000; i++) { - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - { - EC_KEY *pkey = EC_KEY_new(); - const unsigned char *pubkey = &data->pubkey[0]; - int result; - - CHECK(pkey != NULL); - result = EC_KEY_set_group(pkey, data->ec_group); - CHECK(result); - result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; - CHECK(result); - result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); - CHECK(result); - EC_KEY_free(pkey); - } - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - } -} -#endif - -int main(void) { - int i; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - benchmark_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - for (i = 0; i < 32; i++) { - data.msg[i] = 1 + i; - } - for (i = 0; i < 32; i++) { - data.key[i] = 33 + i; - } - data.siglen = 72; - CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); - CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); - data.pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - - run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); -#ifdef ENABLE_OPENSSL_TESTS - data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); - run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); - EC_GROUP_free(data.ec_group); -#endif - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/dummy.go b/builder/crypto/secp256k1/libsecp256k1/src/dummy.go deleted file mode 100644 index 2df270adc..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package src diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecdsa.h b/builder/crypto/secp256k1/libsecp256k1/src/ecdsa.h deleted file mode 100644 index 54ae101b9..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecdsa.h +++ /dev/null @@ -1,21 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECDSA_ -#define _SECP256K1_ECDSA_ - -#include - -#include "scalar.h" -#include "group.h" -#include "ecmult.h" - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h deleted file mode 100644 index 453bb1188..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h +++ /dev/null @@ -1,315 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - - -#ifndef _SECP256K1_ECDSA_IMPL_H_ -#define _SECP256K1_ECDSA_IMPL_H_ - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult.h" -#include "ecmult_gen.h" -#include "ecdsa.h" - -/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 - * sage: for t in xrange(1023, -1, -1): - * .. p = 2**256 - 2**32 - t - * .. if p.is_prime(): - * .. print '%x'%p - * .. break - * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' - * sage: a = 0 - * sage: b = 7 - * sage: F = FiniteField (p) - * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) - * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' - */ -static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL -); - -/** Difference between field and order, values 'p' and 'n' values defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - * sage: a = 0 - * sage: b = 7 - * sage: F = FiniteField (p) - * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) - * '14551231950b75fc4402da1722fc9baee' - */ -static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( - 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL -); - -static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { - int lenleft, b1; - size_t ret = 0; - if (*sigp >= sigend) { - return -1; - } - b1 = *((*sigp)++); - if (b1 == 0xFF) { - /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ - return -1; - } - if ((b1 & 0x80) == 0) { - /* X.690-0207 8.1.3.4 short form length octets */ - return b1; - } - if (b1 == 0x80) { - /* Indefinite length is not allowed in DER. */ - return -1; - } - /* X.690-207 8.1.3.5 long form length octets */ - lenleft = b1 & 0x7F; - if (lenleft > sigend - *sigp) { - return -1; - } - if (**sigp == 0) { - /* Not the shortest possible length encoding. */ - return -1; - } - if ((size_t)lenleft > sizeof(size_t)) { - /* The resulting length would exceed the range of a size_t, so - * certainly longer than the passed array size. - */ - return -1; - } - while (lenleft > 0) { - if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { - } - ret = (ret << 8) | **sigp; - if (ret + lenleft > (size_t)(sigend - *sigp)) { - /* Result exceeds the length of the passed array. */ - return -1; - } - (*sigp)++; - lenleft--; - } - if (ret < 128) { - /* Not the shortest possible length encoding. */ - return -1; - } - return ret; -} - -static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { - int overflow = 0; - unsigned char ra[32] = {0}; - int rlen; - - if (*sig == sigend || **sig != 0x02) { - /* Not a primitive integer (X.690-0207 8.3.1). */ - return 0; - } - (*sig)++; - rlen = secp256k1_der_read_len(sig, sigend); - if (rlen <= 0 || (*sig) + rlen > sigend) { - /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ - return 0; - } - if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { - /* Excessive 0x00 padding. */ - return 0; - } - if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { - /* Excessive 0xFF padding. */ - return 0; - } - if ((**sig & 0x80) == 0x80) { - /* Negative. */ - overflow = 1; - } - while (rlen > 0 && **sig == 0) { - /* Skip leading zero bytes */ - rlen--; - (*sig)++; - } - if (rlen > 32) { - overflow = 1; - } - if (!overflow) { - memcpy(ra + 32 - rlen, *sig, rlen); - secp256k1_scalar_set_b32(r, ra, &overflow); - } - if (overflow) { - secp256k1_scalar_set_int(r, 0); - } - (*sig) += rlen; - return 1; -} - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { - const unsigned char *sigend = sig + size; - int rlen; - if (sig == sigend || *(sig++) != 0x30) { - /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ - return 0; - } - rlen = secp256k1_der_read_len(&sig, sigend); - if (rlen < 0 || sig + rlen > sigend) { - /* Tuple exceeds bounds */ - return 0; - } - if (sig + rlen != sigend) { - /* Garbage after tuple. */ - return 0; - } - - if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { - return 0; - } - if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { - return 0; - } - - if (sig != sigend) { - /* Trailing garbage inside tuple. */ - return 0; - } - - return 1; -} - -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { - unsigned char r[33] = {0}, s[33] = {0}; - unsigned char *rp = r, *sp = s; - size_t lenR = 33, lenS = 33; - secp256k1_scalar_get_b32(&r[1], ar); - secp256k1_scalar_get_b32(&s[1], as); - while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } - while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } - if (*size < 6+lenS+lenR) { - *size = 6 + lenS + lenR; - return 0; - } - *size = 6 + lenS + lenR; - sig[0] = 0x30; - sig[1] = 4 + lenS + lenR; - sig[2] = 0x02; - sig[3] = lenR; - memcpy(sig+4, rp, lenR); - sig[4+lenR] = 0x02; - sig[5+lenR] = lenS; - memcpy(sig+lenR+6, sp, lenS); - return 1; -} - -static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { - unsigned char c[32]; - secp256k1_scalar sn, u1, u2; -#if !defined(EXHAUSTIVE_TEST_ORDER) - secp256k1_fe xr; -#endif - secp256k1_gej pubkeyj; - secp256k1_gej pr; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_inverse_var(&sn, sigs); - secp256k1_scalar_mul(&u1, &sn, message); - secp256k1_scalar_mul(&u2, &sn, sigr); - secp256k1_gej_set_ge(&pubkeyj, pubkey); - secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); - if (secp256k1_gej_is_infinity(&pr)) { - return 0; - } - -#if defined(EXHAUSTIVE_TEST_ORDER) -{ - secp256k1_scalar computed_r; - secp256k1_ge pr_ge; - secp256k1_ge_set_gej(&pr_ge, &pr); - secp256k1_fe_normalize(&pr_ge.x); - - secp256k1_fe_get_b32(c, &pr_ge.x); - secp256k1_scalar_set_b32(&computed_r, c, NULL); - return secp256k1_scalar_eq(sigr, &computed_r); -} -#else - secp256k1_scalar_get_b32(c, sigr); - secp256k1_fe_set_b32(&xr, c); - - /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) - * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), - * compute the remainder modulo n, and compare it to xr. However: - * - * xr == X(pr) mod n - * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) - * [Since 2 * n > p, h can only be 0 or 1] - * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) - * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] - * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) - * [Multiplying both sides of the equations by pr.z^2 mod p] - * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) - * - * Thus, we can avoid the inversion, but we have to check both cases separately. - * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. - */ - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - /* xr + n >= p, so we can skip testing the second case. */ - return 0; - } - secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - return 0; -#endif -} - -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { - unsigned char b[32]; - secp256k1_gej rp; - secp256k1_ge r; - secp256k1_scalar n; - int overflow = 0; - - secp256k1_ecmult_gen(ctx, &rp, nonce); - secp256k1_ge_set_gej(&r, &rp); - secp256k1_fe_normalize(&r.x); - secp256k1_fe_normalize(&r.y); - secp256k1_fe_get_b32(b, &r.x); - secp256k1_scalar_set_b32(sigr, b, &overflow); - /* These two conditions should be checked before calling */ - VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); - VERIFY_CHECK(overflow == 0); - - if (recid) { - /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log - * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. - */ - *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); - } - secp256k1_scalar_mul(&n, sigr, seckey); - secp256k1_scalar_add(&n, &n, message); - secp256k1_scalar_inverse(sigs, nonce); - secp256k1_scalar_mul(sigs, sigs, &n); - secp256k1_scalar_clear(&n); - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - if (secp256k1_scalar_is_zero(sigs)) { - return 0; - } - if (secp256k1_scalar_is_high(sigs)) { - secp256k1_scalar_negate(sigs, sigs); - if (recid) { - *recid ^= 1; - } - } - return 1; -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/eckey.h b/builder/crypto/secp256k1/libsecp256k1/src/eckey.h deleted file mode 100644 index 42739a3be..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/eckey.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECKEY_ -#define _SECP256K1_ECKEY_ - -#include - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/eckey_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/eckey_impl.h deleted file mode 100644 index ce38071ac..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/eckey_impl.h +++ /dev/null @@ -1,99 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECKEY_IMPL_H_ -#define _SECP256K1_ECKEY_IMPL_H_ - -#include "eckey.h" - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { - if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { - secp256k1_fe x; - return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); - } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { - secp256k1_fe x, y; - if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { - return 0; - } - secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { - return 0; - } - return secp256k1_ge_is_valid_var(elem); - } else { - return 0; - } -} - -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { - if (secp256k1_ge_is_infinity(elem)) { - return 0; - } - secp256k1_fe_normalize_var(&elem->x); - secp256k1_fe_normalize_var(&elem->y); - secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { - *size = 33; - pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); - } else { - *size = 65; - pub[0] = 0x04; - secp256k1_fe_get_b32(&pub[33], &elem->y); - } - return 1; -} - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - secp256k1_scalar_add(key, key, tweak); - if (secp256k1_scalar_is_zero(key)) { - return 0; - } - return 1; -} - -static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_gej pt; - secp256k1_scalar one; - secp256k1_gej_set_ge(&pt, key); - secp256k1_scalar_set_int(&one, 1); - secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); - - if (secp256k1_gej_is_infinity(&pt)) { - return 0; - } - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_scalar_mul(key, key, tweak); - return 1; -} - -static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_scalar zero; - secp256k1_gej pt; - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_scalar_set_int(&zero, 0); - secp256k1_gej_set_ge(&pt, key); - secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult.h deleted file mode 100644 index 20484134f..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_ -#define _SECP256K1_ECMULT_ - -#include "num.h" -#include "group.h" - -typedef struct { - /* For accelerating the computation of a*P + b*G: */ - secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ -#endif -} secp256k1_ecmult_context; - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); - -/** Double multiply: R = na*A + ng*G */ -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const.h deleted file mode 100644 index 2b0097655..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_CONST_ -#define _SECP256K1_ECMULT_CONST_ - -#include "scalar.h" -#include "group.h" - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h deleted file mode 100644 index 0db314c48..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h +++ /dev/null @@ -1,239 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_CONST_IMPL_ -#define _SECP256K1_ECMULT_CONST_IMPL_ - -#include "scalar.h" -#include "group.h" -#include "ecmult_const.h" -#include "ecmult_impl.h" - -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) - -/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ -#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ - int m; \ - int abs_n = (n) * (((n) > 0) * 2 - 1); \ - int idx_n = abs_n / 2; \ - secp256k1_fe neg_y; \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ - for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ - /* This loop is used to avoid secret data in array indices. See - * the comment in ecmult_gen_impl.h for rationale. */ \ - secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ - secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ - } \ - (r)->infinity = 0; \ - secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ - secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ -} while(0) - - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) - * with the following guarantees: - * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) - * - each wnaf[i] is nonzero - * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w - * - * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar - * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) - * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 - * - * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 - */ -static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { - int global_sign; - int skew = 0; - int word = 0; - - /* 1 2 3 */ - int u_last; - int u; - - int flip; - int bit; - secp256k1_scalar neg_s; - int not_neg_one; - /* Note that we cannot handle even numbers by negating them to be odd, as is - * done in other implementations, since if our scalars were specified to have - * width < 256 for performance reasons, their negations would have width 256 - * and we'd lose any performance benefit. Instead, we use a technique from - * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) - * or 2 (for odd) to the number we are encoding, returning a skew value indicating - * this, and having the caller compensate after doing the multiplication. */ - - /* Negative numbers will be negated to keep their bit representation below the maximum width */ - flip = secp256k1_scalar_is_high(&s); - /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ !secp256k1_scalar_is_even(&s); - /* We check for negative one, since adding 2 to it will cause an overflow */ - secp256k1_scalar_negate(&neg_s, &s); - not_neg_one = !secp256k1_scalar_is_one(&neg_s); - secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); - /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects - * that we added two to it and flipped it. In fact for -1 these operations are - * identical. We only flipped, but since skewing is required (in the sense that - * the skew must be 1 or 2, never zero) and flipping is not, we need to change - * our flags to claim that we only skewed. */ - global_sign = secp256k1_scalar_cond_negate(&s, flip); - global_sign *= not_neg_one * 2 - 1; - skew = 1 << bit; - - /* 4 */ - u_last = secp256k1_scalar_shr_int(&s, w); - while (word * w < WNAF_BITS) { - int sign; - int even; - - /* 4.1 4.4 */ - u = secp256k1_scalar_shr_int(&s, w); - /* 4.2 */ - even = ((u & 1) == 0); - sign = 2 * (u_last > 0) - 1; - u += sign * even; - u_last -= sign * even * (1 << w); - - /* 4.3, adapted for global sign change */ - wnaf[word++] = u_last * global_sign; - - u_last = u; - } - wnaf[word] = u * global_sign; - - VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); - VERIFY_CHECK(word == WNAF_SIZE(w)); - return skew; -} - - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; - - int skew_1; - int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; - int skew_lam; - secp256k1_scalar q_1, q_lam; -#endif - - int i; - secp256k1_scalar sc = *scalar; - - /* build wnaf representation for q. */ -#ifdef USE_ENDOMORPHISM - /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); - skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); - skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); -#else - skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - */ - secp256k1_gej_set_ge(r, a); - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_normalize_weak(&pre_a[i].y); - } -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } -#endif - - /* first loop iteration (separated out so we can directly set r, rather - * than having it start at infinity, get doubled several times, then have - * its new value added to it) */ - i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); - secp256k1_gej_set_ge(r, &tmpa); -#ifdef USE_ENDOMORPHISM - i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); -#endif - /* remaining loop iterations */ - for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { - int n; - int j; - for (j = 0; j < WINDOW_A - 1; ++j) { - secp256k1_gej_double_nonzero(r, r, NULL); - } - - n = wnaf_1[i]; - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - VERIFY_CHECK(n != 0); - secp256k1_gej_add_ge(r, r, &tmpa); -#ifdef USE_ENDOMORPHISM - n = wnaf_lam[i]; - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - VERIFY_CHECK(n != 0); - secp256k1_gej_add_ge(r, r, &tmpa); -#endif - } - - secp256k1_fe_mul(&r->z, &r->z, &Z); - - { - /* Correct for wNAF skew */ - secp256k1_ge correction = *a; - secp256k1_ge_storage correction_1_stor; -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage correction_lam_stor; -#endif - secp256k1_ge_storage a2_stor; - secp256k1_gej tmpj; - secp256k1_gej_set_ge(&tmpj, &correction); - secp256k1_gej_double_var(&tmpj, &tmpj, NULL); - secp256k1_ge_set_gej(&correction, &tmpj); - secp256k1_ge_to_storage(&correction_1_stor, a); -#ifdef USE_ENDOMORPHISM - secp256k1_ge_to_storage(&correction_lam_stor, a); -#endif - secp256k1_ge_to_storage(&a2_stor, &correction); - - /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ - secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); -#endif - - /* Apply the correction */ - secp256k1_ge_from_storage(&correction, &correction_1_stor); - secp256k1_ge_neg(&correction, &correction); - secp256k1_gej_add_ge(r, r, &correction); - -#ifdef USE_ENDOMORPHISM - secp256k1_ge_from_storage(&correction, &correction_lam_stor); - secp256k1_ge_neg(&correction, &correction); - secp256k1_ge_mul_lambda(&correction, &correction); - secp256k1_gej_add_ge(r, r, &correction); -#endif - } -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h deleted file mode 100644 index eb2cc9ead..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_ -#define _SECP256K1_ECMULT_GEN_ - -#include "scalar.h" -#include "group.h" - -typedef struct { - /* For accelerating the computation of a*G: - * To harden against timing attacks, use the following mechanism: - * * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. - * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: - * * U_i = U * 2^i (for i=0..62) - * * U_i = U * (1-2^63) (for i=63) - * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. - * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is - * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). - * None of the resulting prec group elements have a known scalar, and neither do any of - * the intermediate sums while computing a*G. - */ - secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ - secp256k1_scalar blind; - secp256k1_gej initial; -} secp256k1_ecmult_gen_context; - -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); -static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); -static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); - -/** Multiply with the generator: R = a*G */ -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); - -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h deleted file mode 100644 index 35f254607..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h +++ /dev/null @@ -1,210 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ -#define _SECP256K1_ECMULT_GEN_IMPL_H_ - -#include "scalar.h" -#include "group.h" -#include "ecmult_gen.h" -#include "hash_impl.h" -#ifdef USE_ECMULT_STATIC_PRECOMPUTATION -#include "ecmult_static_context.h" -#endif -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { - ctx->prec = NULL; -} - -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - secp256k1_ge prec[1024]; - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; -#endif - - if (ctx->prec != NULL) { - return; - } -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ - { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - secp256k1_fe nums_x; - secp256k1_ge nums_ge; - int r; - r = secp256k1_fe_set_b32(&nums_x, nums_b32); - (void)r; - VERIFY_CHECK(r); - r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); - (void)r; - VERIFY_CHECK(r); - secp256k1_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); - } - - /* compute prec. */ - { - secp256k1_gej precj[1024]; /* Jacobian versions of prec. */ - secp256k1_gej gbase; - secp256k1_gej numsbase; - gbase = gj; /* 16^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < 64; j++) { - /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ - precj[j*16] = numsbase; - for (i = 1; i < 16; i++) { - secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); - } - /* Multiply gbase by 16. */ - for (i = 0; i < 4; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == 62) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); - } - } - secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); - } - for (j = 0; j < 64; j++) { - for (i = 0; i < 16; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); - } - } -#else - (void)cb; - ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context; -#endif - secp256k1_ecmult_gen_blind(ctx, NULL); -} - -static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { - return ctx->prec != NULL; -} - -static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { - if (src->prec == NULL) { - dst->prec = NULL; - } else { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); - memcpy(dst->prec, src->prec, sizeof(*dst->prec)); -#else - (void)cb; - dst->prec = src->prec; -#endif - dst->initial = src->initial; - dst->blind = src->blind; - } -} - -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - free(ctx->prec); -#endif - secp256k1_scalar_clear(&ctx->blind); - secp256k1_gej_clear(&ctx->initial); - ctx->prec = NULL; -} - -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { - secp256k1_ge add; - secp256k1_ge_storage adds; - secp256k1_scalar gnb; - int bits; - int i, j; - memset(&adds, 0, sizeof(adds)); - *r = ctx->initial; - /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ - secp256k1_scalar_add(&gnb, gn, &ctx->blind); - add.infinity = 0; - for (j = 0; j < 64; j++) { - bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); - for (i = 0; i < 16; i++) { - /** This uses a conditional move to avoid any secret data in array indexes. - * _Any_ use of secret indexes has been demonstrated to result in timing - * sidechannels, even when the cache-line access patterns are uniform. - * See also: - * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe - * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and - * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, - * by Dag Arne Osvik, Adi Shamir, and Eran Tromer - * (http://www.tau.ac.il/~tromer/papers/cache.pdf) - */ - secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); - } - secp256k1_ge_from_storage(&add, &adds); - secp256k1_gej_add_ge(r, r, &add); - } - bits = 0; - secp256k1_ge_clear(&add); - secp256k1_scalar_clear(&gnb); -} - -/* Setup blinding values for secp256k1_ecmult_gen. */ -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { - secp256k1_scalar b; - secp256k1_gej gb; - secp256k1_fe s; - unsigned char nonce32[32]; - secp256k1_rfc6979_hmac_sha256_t rng; - int retry; - unsigned char keydata[64] = {0}; - if (seed32 == NULL) { - /* When seed is NULL, reset the initial point and blinding value. */ - secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); - secp256k1_gej_neg(&ctx->initial, &ctx->initial); - secp256k1_scalar_set_int(&ctx->blind, 1); - } - /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ - secp256k1_scalar_get_b32(nonce32, &ctx->blind); - /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, - * and guards against weak or adversarial seeds. This is a simpler and safer interface than - * asking the caller for blinding values directly and expecting them to retry on failure. - */ - memcpy(keydata, nonce32, 32); - if (seed32 != NULL) { - memcpy(keydata + 32, seed32, 32); - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); - memset(keydata, 0, sizeof(keydata)); - /* Retry for out of range results to achieve uniformity. */ - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - retry = !secp256k1_fe_set_b32(&s, nonce32); - retry |= secp256k1_fe_is_zero(&s); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ - /* Randomize the projection to defend against multiplier sidechannels. */ - secp256k1_gej_rescale(&ctx->initial, &s); - secp256k1_fe_clear(&s); - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_scalar_set_b32(&b, nonce32, &retry); - /* A blinding value of 0 works, but would undermine the projection hardening. */ - retry |= secp256k1_scalar_is_zero(&b); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - memset(nonce32, 0, 32); - secp256k1_ecmult_gen(ctx, &gb, &b); - secp256k1_scalar_negate(&b, &b); - ctx->blind = b; - ctx->initial = gb; - secp256k1_scalar_clear(&b); - secp256k1_gej_clear(&gb); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h deleted file mode 100644 index 4e40104ad..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h +++ /dev/null @@ -1,406 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_IMPL_H_ -#define _SECP256K1_ECMULT_IMPL_H_ - -#include - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need to lower these values for exhaustive tests because - * the tables cannot have infinities in them (this breaks the - * affine-isomorphism stuff which tracks z-ratios) */ -# if EXHAUSTIVE_TEST_ORDER > 128 -# define WINDOW_A 5 -# define WINDOW_G 8 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define WINDOW_A 4 -# define WINDOW_G 4 -# else -# define WINDOW_A 2 -# define WINDOW_G 2 -# endif -#else -/* optimal for 128-bit and 256-bit exponents. */ -#define WINDOW_A 5 -/** larger numbers may result in slightly better performance, at the cost of - exponentially larger precomputed tables. */ -#ifdef USE_ENDOMORPHISM -/** Two tables for window size 15: 1.375 MiB. */ -#define WINDOW_G 15 -#else -/** One table for window size 16: 1.375 MiB. */ -#define WINDOW_G 16 -#endif -#endif - -/** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) - -/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain - * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will - * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. - * Prej's Z values are undefined, except for the last value. - */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { - secp256k1_gej d; - secp256k1_ge a_ge, d_ge; - int i; - - VERIFY_CHECK(!a->infinity); - - secp256k1_gej_double_var(&d, a, NULL); - - /* - * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate - * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. - */ - d_ge.x = d.x; - d_ge.y = d.y; - d_ge.infinity = 0; - - secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); - prej[0].x = a_ge.x; - prej[0].y = a_ge.y; - prej[0].z = a->z; - prej[0].infinity = 0; - - zr[0] = d.z; - for (i = 1; i < n; i++) { - secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); - } - - /* - * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only - * the final point's z coordinate is actually used though, so just update that. - */ - secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); -} - -/** Fill a table 'pre' with precomputed odd multiples of a. - * - * There are two versions of this function: - * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its - * resulting point set to a single constant Z denominator, stores the X and Y - * coordinates as ge_storage points in pre, and stores the global Z in rz. - * It only operates on tables sized for WINDOW_A wnaf multiples. - * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its - * resulting point set to actually affine points, and stores those in pre. - * It operates on tables of any size, but uses heap-allocated temporaries. - * - * To compute a*P + b*G, we compute a table for P using the first function, - * and for G using the second (which requires an inverse, but it only needs to - * happen once). - */ -static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { - secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); - /* Bring them to the same Z denominator. */ - secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); -} - -static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { - secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); - secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); - secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); - int i; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); - /* Convert them in batch to affine coordinates. */ - secp256k1_ge_set_table_gej_var(prea, prej, zr, n); - /* Convert them to compact storage form. */ - for (i = 0; i < n; i++) { - secp256k1_ge_to_storage(&pre[i], &prea[i]); - } - - free(prea); - free(prej); - free(zr); -} - -/** The following two macro retrieves a particular odd multiple from a table - * of precomputed multiples. */ -#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - *(r) = (pre)[((n)-1)/2]; \ - } else { \ - secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ - } \ -} while(0) - -#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ - } else { \ - secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ - secp256k1_ge_neg((r), (r)); \ - } \ -} while(0) - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { - ctx->pre_g = NULL; -#ifdef USE_ENDOMORPHISM - ctx->pre_g_128 = NULL; -#endif -} - -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { - secp256k1_gej gj; - - if (ctx->pre_g != NULL) { - return; - } - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* precompute the tables with odd multiples */ - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); - -#ifdef USE_ENDOMORPHISM - { - secp256k1_gej g_128j; - int i; - - ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* calculate 2^128*generator */ - g_128j = gj; - for (i = 0; i < 128; i++) { - secp256k1_gej_double_var(&g_128j, &g_128j, NULL); - } - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); - } -#endif -} - -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { - if (src->pre_g == NULL) { - dst->pre_g = NULL; - } else { - size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g, src->pre_g, size); - } -#ifdef USE_ENDOMORPHISM - if (src->pre_g_128 == NULL) { - dst->pre_g_128 = NULL; - } else { - size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g_128, src->pre_g_128, size); - } -#endif -} - -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { - return ctx->pre_g != NULL; -} - -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { - free(ctx->pre_g); -#ifdef USE_ENDOMORPHISM - free(ctx->pre_g_128); -#endif - secp256k1_ecmult_context_init(ctx); -} - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), - * with the following guarantees: - * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) - * - two non-zero entries in wnaf are separated by at least w-1 zeroes. - * - the number of set values in wnaf is returned. This number is at most 256, and at most one more - * than the number of bits in the (absolute value) of the input. - */ -static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { - secp256k1_scalar s = *a; - int last_set_bit = -1; - int bit = 0; - int sign = 1; - int carry = 0; - - VERIFY_CHECK(wnaf != NULL); - VERIFY_CHECK(0 <= len && len <= 256); - VERIFY_CHECK(a != NULL); - VERIFY_CHECK(2 <= w && w <= 31); - - memset(wnaf, 0, len * sizeof(wnaf[0])); - - if (secp256k1_scalar_get_bits(&s, 255, 1)) { - secp256k1_scalar_negate(&s, &s); - sign = -1; - } - - while (bit < len) { - int now; - int word; - if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { - bit++; - continue; - } - - now = w; - if (now > len - bit) { - now = len - bit; - } - - word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; - - carry = (word >> (w-1)) & 1; - word -= carry << w; - - wnaf[bit] = sign * word; - last_set_bit = bit; - - bit += now; - } -#ifdef VERIFY - CHECK(carry == 0); - while (bit < 256) { - CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); - } -#endif - return last_set_bit + 1; -} - -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_scalar na_1, na_lam; - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; - int wnaf_na_1[130]; - int wnaf_na_lam[130]; - int bits_na_1; - int bits_na_lam; - int wnaf_ng_1[129]; - int bits_ng_1; - int wnaf_ng_128[129]; - int bits_ng_128; -#else - int wnaf_na[256]; - int bits_na; - int wnaf_ng[256]; - int bits_ng; -#endif - int i; - int bits; - -#ifdef USE_ENDOMORPHISM - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&na_1, &na_lam, na); - - /* build wnaf representation for na_1 and na_lam. */ - bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); - bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); - VERIFY_CHECK(bits_na_1 <= 130); - VERIFY_CHECK(bits_na_lam <= 130); - bits = bits_na_1; - if (bits_na_lam > bits) { - bits = bits_na_lam; - } -#else - /* build wnaf representation for na. */ - bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); - bits = bits_na; -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - * The exception is the precomputed G table points, which are actually - * affine. Compared to the base used for other points, they have a Z ratio - * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same - * isomorphism to efficiently add with a known Z inverse. - */ - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); - -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } - - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; - } -#else - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; - } -#endif - - secp256k1_gej_set_infinity(r); - - for (i = bits - 1; i >= 0; i--) { - int n; - secp256k1_gej_double_var(r, r, NULL); -#ifdef USE_ENDOMORPHISM - if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_na_lam && (n = wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } - if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#else - if (i < bits_na && (n = wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng && (n = wnaf_ng[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#endif - } - - if (!r->infinity) { - secp256k1_fe_mul(&r->z, &r->z, &Z); - } -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field.h b/builder/crypto/secp256k1/libsecp256k1/src/field.h deleted file mode 100644 index bbb1ee866..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field.h +++ /dev/null @@ -1,132 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_ -#define _SECP256K1_FIELD_ - -/** Field element module. - * - * Field elements can be represented in several ways, but code accessing - * it (and implementations) need to take certain properties into account: - * - Each field element can be normalized or not. - * - Each field element has a magnitude, which represents how far away - * its representation is away from normalization. Normalized elements - * always have a magnitude of 1, but a magnitude of 1 doesn't imply - * normality. - */ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_FIELD_10X26) -#include "field_10x26.h" -#elif defined(USE_FIELD_5X52) -#include "field_5x52.h" -#else -#error "Please select field implementation" -#endif - -#include "util.h" - -/** Normalize a field element. */ -static void secp256k1_fe_normalize(secp256k1_fe *r); - -/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */ -static void secp256k1_fe_normalize_weak(secp256k1_fe *r); - -/** Normalize a field element, without constant-time guarantee. */ -static void secp256k1_fe_normalize_var(secp256k1_fe *r); - -/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field - * implementation may optionally normalize the input, but this should not be relied upon. */ -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r); - -/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field - * implementation may optionally normalize the input, but this should not be relied upon. */ -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); - -/** Set a field element equal to a small integer. Resulting field element is normalized. */ -static void secp256k1_fe_set_int(secp256k1_fe *r, int a); - -/** Sets a field element equal to zero, initializing all fields. */ -static void secp256k1_fe_clear(secp256k1_fe *a); - -/** Verify whether a field element is zero. Requires the input to be normalized. */ -static int secp256k1_fe_is_zero(const secp256k1_fe *a); - -/** Check the "oddness" of a field element. Requires the input to be normalized. */ -static int secp256k1_fe_is_odd(const secp256k1_fe *a); - -/** Compare two field elements. Requires magnitude-1 inputs. */ -static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Same as secp256k1_fe_equal, but may be variable time. */ -static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Compare two field elements. Requires both inputs to be normalized */ -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */ -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); - -/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input - * as an argument. The magnitude of the output is one higher. */ -static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); - -/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that - * small integer. */ -static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); - -/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ -static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); - -/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. - * The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); - -/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. - * The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); - -/** If a has a square root, it is computed in r and 1 is returned. If a does not - * have a square root, the root of its negation is computed and 0 is returned. - * The input's magnitude can be at most 8. The output magnitude is 1 (but not - * guaranteed to be normalized). The result in r will always be a square - * itself. */ -static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); - -/** Checks whether a field element is a quadratic residue. */ -static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); - -/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be - * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ -static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); - -/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ -static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); - -/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be - * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and - * outputs must not overlap in memory. */ -static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len); - -/** Convert a field element to the storage type. */ -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); - -/** Convert a field element back from the storage type. */ -static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_10x26.h b/builder/crypto/secp256k1/libsecp256k1/src/field_10x26.h deleted file mode 100644 index 61ee1e096..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_10x26.h +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ - -#include - -typedef struct { - /* X = sum(i=0..9, elem[i]*2^26) mod n */ - uint32_t n[10]; -#ifdef VERIFY - int magnitude; - int normalized; -#endif -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) & 0x3FFFFFFUL, \ - (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ - (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ - (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ - (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ - (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ - (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ - (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ - (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ - (((uint32_t)d7) >> 10) \ -} - -#ifdef VERIFY -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} -#else -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} -#endif - -typedef struct { - uint32_t n[8]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} -#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h deleted file mode 100644 index 5fb092f1b..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h +++ /dev/null @@ -1,1140 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ - -#include "util.h" -#include "num.h" -#include "field.h" - -#ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { - const uint32_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; - r &= (d[0] <= 0x3FFFFFFUL * m); - r &= (d[1] <= 0x3FFFFFFUL * m); - r &= (d[2] <= 0x3FFFFFFUL * m); - r &= (d[3] <= 0x3FFFFFFUL * m); - r &= (d[4] <= 0x3FFFFFFUL * m); - r &= (d[5] <= 0x3FFFFFFUL * m); - r &= (d[6] <= 0x3FFFFFFUL * m); - r &= (d[7] <= 0x3FFFFFFUL * m); - r &= (d[8] <= 0x3FFFFFFUL * m); - r &= (d[9] <= 0x03FFFFFUL * m); - r &= (a->magnitude >= 0); - r &= (a->magnitude <= 32); - if (a->normalized) { - r &= (a->magnitude <= 1); - if (r && (d[9] == 0x03FFFFFUL)) { - uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; - if (mid == 0x3FFFFFFUL) { - r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); - } - } - } - VERIFY_CHECK(r == 1); -} -#endif - -static void secp256k1_fe_normalize(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - if (x) { - t0 += 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint32_t z0, z1; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t z0, z1; - uint32_t x; - - t0 = r->n[0]; - t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - x = t9 >> 22; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0x3FFFFFFUL; - z1 = z0 ^ 0x3D0UL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - t4 = r->n[4]; - t5 = r->n[5]; - t6 = r->n[6]; - t7 = r->n[7]; - t8 = r->n[8]; - - t9 &= 0x03FFFFFUL; - t1 += (x << 6); - - t1 += (t0 >> 26); - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { - const uint32_t *t = a->n; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return a->n[0] & 1; -} - -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - int i; -#ifdef VERIFY - a->magnitude = 0; - a->normalized = 1; -#endif - for (i=0; i<10; i++) { - a->n[i] = 0; - } -} - -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); -#endif - for (i = 9; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; - } - } - if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { - return 0; - } -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif - return 1; -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); - } - r[31-i] = c; - } -} - -SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); -#endif - r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; - r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; - r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; - r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; - r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; - r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; -#ifdef VERIFY - r->magnitude = m + 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; - r->n[5] *= a; - r->n[6] *= a; - r->n[7] *= a; - r->n[8] *= a; - r->n[9] *= a; -#ifdef VERIFY - r->magnitude *= a; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - secp256k1_fe_verify(a); -#endif - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; - r->n[5] += a->n[5]; - r->n[6] += a->n[6]; - r->n[7] += a->n[7]; - r->n[8] += a->n[8]; - r->n[9] += a->n[9]; -#ifdef VERIFY - r->magnitude += a->magnitude; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -#if defined(USE_EXTERNAL_ASM) - -/* External assembler implementation */ -void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); -void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); - -#else - -#ifdef VERIFY -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#else -#define VERIFY_BITS(x, n) do { } while(0) -#endif - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - VERIFY_BITS(b[0], 30); - VERIFY_BITS(b[1], 30); - VERIFY_BITS(b[2], 30); - VERIFY_BITS(b[3], 30); - VERIFY_BITS(b[4], 30); - VERIFY_BITS(b[5], 30); - VERIFY_BITS(b[6], 30); - VERIFY_BITS(b[7], 30); - VERIFY_BITS(b[8], 30); - VERIFY_BITS(b[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)a[0] * b[9] - + (uint64_t)a[1] * b[8] - + (uint64_t)a[2] * b[7] - + (uint64_t)a[3] * b[6] - + (uint64_t)a[4] * b[5] - + (uint64_t)a[5] * b[4] - + (uint64_t)a[6] * b[3] - + (uint64_t)a[7] * b[2] - + (uint64_t)a[8] * b[1] - + (uint64_t)a[9] * b[0]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * b[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)a[1] * b[9] - + (uint64_t)a[2] * b[8] - + (uint64_t)a[3] * b[7] - + (uint64_t)a[4] * b[6] - + (uint64_t)a[5] * b[5] - + (uint64_t)a[6] * b[4] - + (uint64_t)a[7] * b[3] - + (uint64_t)a[8] * b[2] - + (uint64_t)a[9] * b[1]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)a[0] * b[1] - + (uint64_t)a[1] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)a[2] * b[9] - + (uint64_t)a[3] * b[8] - + (uint64_t)a[4] * b[7] - + (uint64_t)a[5] * b[6] - + (uint64_t)a[6] * b[5] - + (uint64_t)a[7] * b[4] - + (uint64_t)a[8] * b[3] - + (uint64_t)a[9] * b[2]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)a[0] * b[2] - + (uint64_t)a[1] * b[1] - + (uint64_t)a[2] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)a[3] * b[9] - + (uint64_t)a[4] * b[8] - + (uint64_t)a[5] * b[7] - + (uint64_t)a[6] * b[6] - + (uint64_t)a[7] * b[5] - + (uint64_t)a[8] * b[4] - + (uint64_t)a[9] * b[3]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[3] - + (uint64_t)a[1] * b[2] - + (uint64_t)a[2] * b[1] - + (uint64_t)a[3] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)a[4] * b[9] - + (uint64_t)a[5] * b[8] - + (uint64_t)a[6] * b[7] - + (uint64_t)a[7] * b[6] - + (uint64_t)a[8] * b[5] - + (uint64_t)a[9] * b[4]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[4] - + (uint64_t)a[1] * b[3] - + (uint64_t)a[2] * b[2] - + (uint64_t)a[3] * b[1] - + (uint64_t)a[4] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[5] * b[9] - + (uint64_t)a[6] * b[8] - + (uint64_t)a[7] * b[7] - + (uint64_t)a[8] * b[6] - + (uint64_t)a[9] * b[5]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[5] - + (uint64_t)a[1] * b[4] - + (uint64_t)a[2] * b[3] - + (uint64_t)a[3] * b[2] - + (uint64_t)a[4] * b[1] - + (uint64_t)a[5] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[6] * b[9] - + (uint64_t)a[7] * b[8] - + (uint64_t)a[8] * b[7] - + (uint64_t)a[9] * b[6]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[6] - + (uint64_t)a[1] * b[5] - + (uint64_t)a[2] * b[4] - + (uint64_t)a[3] * b[3] - + (uint64_t)a[4] * b[2] - + (uint64_t)a[5] * b[1] - + (uint64_t)a[6] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[7] * b[9] - + (uint64_t)a[8] * b[8] - + (uint64_t)a[9] * b[7]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[7] - + (uint64_t)a[1] * b[6] - + (uint64_t)a[2] * b[5] - + (uint64_t)a[3] * b[4] - + (uint64_t)a[4] * b[3] - + (uint64_t)a[5] * b[2] - + (uint64_t)a[6] * b[1] - + (uint64_t)a[7] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[8] * b[9] - + (uint64_t)a[9] * b[8]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[8] - + (uint64_t)a[1] * b[7] - + (uint64_t)a[2] * b[6] - + (uint64_t)a[3] * b[5] - + (uint64_t)a[4] * b[4] - + (uint64_t)a[5] * b[3] - + (uint64_t)a[6] * b[2] - + (uint64_t)a[7] * b[1] - + (uint64_t)a[8] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * b[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)(a[0]*2) * a[9] - + (uint64_t)(a[1]*2) * a[8] - + (uint64_t)(a[2]*2) * a[7] - + (uint64_t)(a[3]*2) * a[6] - + (uint64_t)(a[4]*2) * a[5]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * a[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)(a[1]*2) * a[9] - + (uint64_t)(a[2]*2) * a[8] - + (uint64_t)(a[3]*2) * a[7] - + (uint64_t)(a[4]*2) * a[6] - + (uint64_t)a[5] * a[5]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)(a[0]*2) * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)(a[2]*2) * a[9] - + (uint64_t)(a[3]*2) * a[8] - + (uint64_t)(a[4]*2) * a[7] - + (uint64_t)(a[5]*2) * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[2] - + (uint64_t)a[1] * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)(a[3]*2) * a[9] - + (uint64_t)(a[4]*2) * a[8] - + (uint64_t)(a[5]*2) * a[7] - + (uint64_t)a[6] * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[3] - + (uint64_t)(a[1]*2) * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)(a[4]*2) * a[9] - + (uint64_t)(a[5]*2) * a[8] - + (uint64_t)(a[6]*2) * a[7]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[4] - + (uint64_t)(a[1]*2) * a[3] - + (uint64_t)a[2] * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[5]*2) * a[9] - + (uint64_t)(a[6]*2) * a[8] - + (uint64_t)a[7] * a[7]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[5] - + (uint64_t)(a[1]*2) * a[4] - + (uint64_t)(a[2]*2) * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[6]*2) * a[9] - + (uint64_t)(a[7]*2) * a[8]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[6] - + (uint64_t)(a[1]*2) * a[5] - + (uint64_t)(a[2]*2) * a[4] - + (uint64_t)a[3] * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[7]*2) * a[9] - + (uint64_t)a[8] * a[8]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[7] - + (uint64_t)(a[1]*2) * a[6] - + (uint64_t)(a[2]*2) * a[5] - + (uint64_t)(a[3]*2) * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[8]*2) * a[9]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[8] - + (uint64_t)(a[1]*2) * a[7] - + (uint64_t)(a[2]*2) * a[6] - + (uint64_t)(a[3]*2) * a[5] - + (uint64_t)a[4] * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * a[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} -#endif - -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); - VERIFY_CHECK(r != b); -#endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); -#endif - secp256k1_fe_sqr_inner(r->n, a->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint32_t mask0, mask1; - mask0 = flag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); - r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); - r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); -#ifdef VERIFY - if (a->magnitude > r->magnitude) { - r->magnitude = a->magnitude; - } - r->normalized &= a->normalized; -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint32_t mask0, mask1; - mask0 = flag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); -} - -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); -#endif - r->n[0] = a->n[0] | a->n[1] << 26; - r->n[1] = a->n[1] >> 6 | a->n[2] << 20; - r->n[2] = a->n[2] >> 12 | a->n[3] << 14; - r->n[3] = a->n[3] >> 18 | a->n[4] << 8; - r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; - r->n[5] = a->n[6] >> 4 | a->n[7] << 22; - r->n[6] = a->n[7] >> 10 | a->n[8] << 16; - r->n[7] = a->n[8] >> 16 | a->n[9] << 10; -} - -static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0x3FFFFFFUL; - r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); - r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); - r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); - r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); - r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; - r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); - r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); - r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); - r->n[9] = a->n[7] >> 10; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; -#endif -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52.h b/builder/crypto/secp256k1/libsecp256k1/src/field_5x52.h deleted file mode 100644 index 8e69a560d..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52.h +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ - -#include - -typedef struct { - /* X = sum(i=0..4, elem[i]*2^52) mod n */ - uint64_t n[5]; -#ifdef VERIFY - int magnitude; - int normalized; -#endif -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ - ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ - ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ - ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ - ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ -} - -#ifdef VERIFY -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} -#else -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} -#endif - -typedef struct { - uint64_t n[4]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ - (d0) | (((uint64_t)(d1)) << 32), \ - (d2) | (((uint64_t)(d3)) << 32), \ - (d4) | (((uint64_t)(d5)) << 32), \ - (d6) | (((uint64_t)(d7)) << 32) \ -}} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h deleted file mode 100644 index 98cc004bf..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h +++ /dev/null @@ -1,502 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -/** - * Changelog: - * - March 2013, Diederik Huys: original version - * - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm - * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly - */ - -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { -/** - * Registers: rdx:rax = multiplication accumulator - * r9:r8 = c - * r15:rcx = d - * r10-r14 = a0-a4 - * rbx = b - * rdi = r - * rsi = a / t? - */ - uint64_t tmp1, tmp2, tmp3; -__asm__ __volatile__( - "movq 0(%%rsi),%%r10\n" - "movq 8(%%rsi),%%r11\n" - "movq 16(%%rsi),%%r12\n" - "movq 24(%%rsi),%%r13\n" - "movq 32(%%rsi),%%r14\n" - - /* d += a3 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r13\n" - "movq %%rax,%%rcx\n" - "movq %%rdx,%%r15\n" - /* d += a2 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d = a0 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c = a4 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r14\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += (c & M) * R */ - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* t3 (tmp1) = d & M */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - "movq %%rsi,%q1\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* d += a4 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a0 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += c * R */ - "movq %%r8,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* t4 = d & M (%%rsi) */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* tx = t4 >> 48 (tmp3) */ - "movq %%rsi,%%rax\n" - "shrq $48,%%rax\n" - "movq %%rax,%q3\n" - /* t4 &= (M >> 4) (tmp2) */ - "movq $0xffffffffffff,%%rax\n" - "andq %%rax,%%rsi\n" - "movq %%rsi,%q2\n" - /* c = a0 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r10\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += a4 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a1 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* u0 = d & M (%%rsi) */ - "movq %%rcx,%%rsi\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* u0 = (u0 << 4) | tx (%%rsi) */ - "shlq $4,%%rsi\n" - "movq %q3,%%rax\n" - "orq %%rax,%%rsi\n" - /* c += u0 * (R >> 4) */ - "movq $0x1000003d1,%%rax\n" - "mulq %%rsi\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[0] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,0(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a1 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a0 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a4 * b2 */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a2 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c += (d & M) * R */ - "movq %%rcx,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 */ - "shrdq $52,%%r15,%%rcx\n" - "xorq %%r15,%%r15\n" - /* r[1] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,8(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a2 * b0 */ - "movq 0(%%rbx),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a1 * b1 */ - "movq 8(%%rbx),%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* c += a0 * b2 (last use of %%r10 = a0) */ - "movq 16(%%rbx),%%rax\n" - "mulq %%r10\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */ - "movq %q2,%%rsi\n" - "movq %q1,%%r10\n" - /* d += a4 * b3 */ - "movq 24(%%rbx),%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* d += a3 * b4 */ - "movq 32(%%rbx),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rcx\n" - "adcq %%rdx,%%r15\n" - /* c += (d & M) * R */ - "movq %%rcx,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 (%%rcx only) */ - "shrdq $52,%%r15,%%rcx\n" - /* r[2] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,16(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += t3 */ - "addq %%r10,%%r8\n" - /* c += d * R */ - "movq %%rcx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[3] = c & M */ - "movq %%r8,%%rax\n" - "movq $0xfffffffffffff,%%rdx\n" - "andq %%rdx,%%rax\n" - "movq %%rax,24(%%rdi)\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* c += t4 (%%r8 only) */ - "addq %%rsi,%%r8\n" - /* r[4] = c */ - "movq %%r8,32(%%rdi)\n" -: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) -: "b"(b), "D"(r) -: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" -); -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { -/** - * Registers: rdx:rax = multiplication accumulator - * r9:r8 = c - * rcx:rbx = d - * r10-r14 = a0-a4 - * r15 = M (0xfffffffffffff) - * rdi = r - * rsi = a / t? - */ - uint64_t tmp1, tmp2, tmp3; -__asm__ __volatile__( - "movq 0(%%rsi),%%r10\n" - "movq 8(%%rsi),%%r11\n" - "movq 16(%%rsi),%%r12\n" - "movq 24(%%rsi),%%r13\n" - "movq 32(%%rsi),%%r14\n" - "movq $0xfffffffffffff,%%r15\n" - - /* d = (a0*2) * a3 */ - "leaq (%%r10,%%r10,1),%%rax\n" - "mulq %%r13\n" - "movq %%rax,%%rbx\n" - "movq %%rdx,%%rcx\n" - /* d += (a1*2) * a2 */ - "leaq (%%r11,%%r11,1),%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c = a4 * a4 */ - "movq %%r14,%%rax\n" - "mulq %%r14\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += (c & M) * R */ - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* t3 (tmp1) = d & M */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - "movq %%rsi,%q1\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* a4 *= 2 */ - "addq %%r14,%%r14\n" - /* d += a0 * a4 */ - "movq %%r10,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d+= (a1*2) * a3 */ - "leaq (%%r11,%%r11,1),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += a2 * a2 */ - "movq %%r12,%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += c * R */ - "movq %%r8,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* t4 = d & M (%%rsi) */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* tx = t4 >> 48 (tmp3) */ - "movq %%rsi,%%rax\n" - "shrq $48,%%rax\n" - "movq %%rax,%q3\n" - /* t4 &= (M >> 4) (tmp2) */ - "movq $0xffffffffffff,%%rax\n" - "andq %%rax,%%rsi\n" - "movq %%rsi,%q2\n" - /* c = a0 * a0 */ - "movq %%r10,%%rax\n" - "mulq %%r10\n" - "movq %%rax,%%r8\n" - "movq %%rdx,%%r9\n" - /* d += a1 * a4 */ - "movq %%r11,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += (a2*2) * a3 */ - "leaq (%%r12,%%r12,1),%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* u0 = d & M (%%rsi) */ - "movq %%rbx,%%rsi\n" - "andq %%r15,%%rsi\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* u0 = (u0 << 4) | tx (%%rsi) */ - "shlq $4,%%rsi\n" - "movq %q3,%%rax\n" - "orq %%rax,%%rsi\n" - /* c += u0 * (R >> 4) */ - "movq $0x1000003d1,%%rax\n" - "mulq %%rsi\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[0] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,0(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* a0 *= 2 */ - "addq %%r10,%%r10\n" - /* c += a0 * a1 */ - "movq %%r10,%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a2 * a4 */ - "movq %%r12,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* d += a3 * a3 */ - "movq %%r13,%%rax\n" - "mulq %%r13\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c += (d & M) * R */ - "movq %%rbx,%%rax\n" - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 */ - "shrdq $52,%%rcx,%%rbx\n" - "xorq %%rcx,%%rcx\n" - /* r[1] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,8(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += a0 * a2 (last use of %%r10) */ - "movq %%r10,%%rax\n" - "mulq %%r12\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */ - "movq %q2,%%rsi\n" - "movq %q1,%%r10\n" - /* c += a1 * a1 */ - "movq %%r11,%%rax\n" - "mulq %%r11\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d += a3 * a4 */ - "movq %%r13,%%rax\n" - "mulq %%r14\n" - "addq %%rax,%%rbx\n" - "adcq %%rdx,%%rcx\n" - /* c += (d & M) * R */ - "movq %%rbx,%%rax\n" - "andq %%r15,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* d >>= 52 (%%rbx only) */ - "shrdq $52,%%rcx,%%rbx\n" - /* r[2] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,16(%%rdi)\n" - /* c >>= 52 */ - "shrdq $52,%%r9,%%r8\n" - "xorq %%r9,%%r9\n" - /* c += t3 */ - "addq %%r10,%%r8\n" - /* c += d * R */ - "movq %%rbx,%%rax\n" - "movq $0x1000003d10,%%rdx\n" - "mulq %%rdx\n" - "addq %%rax,%%r8\n" - "adcq %%rdx,%%r9\n" - /* r[3] = c & M */ - "movq %%r8,%%rax\n" - "andq %%r15,%%rax\n" - "movq %%rax,24(%%rdi)\n" - /* c >>= 52 (%%r8 only) */ - "shrdq $52,%%r9,%%r8\n" - /* c += t4 (%%r8 only) */ - "addq %%rsi,%%r8\n" - /* r[4] = c */ - "movq %%r8,32(%%rdi)\n" -: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) -: "D"(r) -: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" -); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h deleted file mode 100644 index dd88f38c7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h +++ /dev/null @@ -1,451 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "util.h" -#include "num.h" -#include "field.h" - -#if defined(USE_ASM_X86_64) -#include "field_5x52_asm_impl.h" -#else -#include "field_5x52_int128_impl.h" -#endif - -/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, - * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, - * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element - * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations - * accept any input with magnitude at most M, and have different rules for propagating magnitude to their - * output. - */ - -#ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { - const uint64_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; - /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); - r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); - r &= (a->magnitude >= 0); - r &= (a->magnitude <= 2048); - if (a->normalized) { - r &= (a->magnitude <= 1); - if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { - r &= (d[0] < 0xFFFFEFFFFFC2FULL); - } - } - VERIFY_CHECK(r == 1); -} -#endif - -static void secp256k1_fe_normalize(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - if (x) { - t0 += 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint64_t z0, z1; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { - uint64_t t0, t1, t2, t3, t4; - uint64_t z0, z1; - uint64_t x; - - t0 = r->n[0]; - t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - x = t4 >> 48; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0xFFFFFFFFFFFFFULL; - z1 = z0 ^ 0x1000003D0ULL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - - t4 &= 0x0FFFFFFFFFFFFULL; - - t1 += (t0 >> 52); - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { - const uint64_t *t = a->n; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - return a->n[0] & 1; -} - -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - int i; -#ifdef VERIFY - a->magnitude = 0; - a->normalized = 1; -#endif - for (i=0; i<5; i++) { - a->n[i] = 0; - } -} - -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); -#endif - for (i = 4; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; - } - } - if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { - return 0; - } -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; - secp256k1_fe_verify(r); -#endif - return 1; -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; -#ifdef VERIFY - VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); -#endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); - } - r[31-i] = c; - } -} - -SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); -#endif - r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; -#ifdef VERIFY - r->magnitude = m + 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; -#ifdef VERIFY - r->magnitude *= a; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - secp256k1_fe_verify(a); -#endif - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; -#ifdef VERIFY - r->magnitude += a->magnitude; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); - VERIFY_CHECK(r != b); -#endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); -#endif - secp256k1_fe_sqr_inner(r->n, a->n); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 0; - secp256k1_fe_verify(r); -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint64_t mask0, mask1; - mask0 = flag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); -#ifdef VERIFY - if (a->magnitude > r->magnitude) { - r->magnitude = a->magnitude; - } - r->normalized &= a->normalized; -#endif -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint64_t mask0, mask1; - mask0 = flag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); -} - -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { -#ifdef VERIFY - VERIFY_CHECK(a->normalized); -#endif - r->n[0] = a->n[0] | a->n[1] << 52; - r->n[1] = a->n[1] >> 12 | a->n[2] << 40; - r->n[2] = a->n[2] >> 24 | a->n[3] << 28; - r->n[3] = a->n[3] >> 36 | a->n[4] << 16; -} - -static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; - r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); - r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); - r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); - r->n[4] = a->n[3] >> 16; -#ifdef VERIFY - r->magnitude = 1; - r->normalized = 1; -#endif -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h deleted file mode 100644 index 0bf22bdd3..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h +++ /dev/null @@ -1,277 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ - -#include - -#ifdef VERIFY -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#else -#define VERIFY_BITS(x, n) do { } while(0) -#endif - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { - uint128_t c, d; - uint64_t t3, t4, tx, u0; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - VERIFY_BITS(b[0], 56); - VERIFY_BITS(b[1], 56); - VERIFY_BITS(b[2], 56); - VERIFY_BITS(b[3], 56); - VERIFY_BITS(b[4], 52); - VERIFY_CHECK(r != b); - - /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - d = (uint128_t)a0 * b[3] - + (uint128_t)a1 * b[2] - + (uint128_t)a2 * b[1] - + (uint128_t)a3 * b[0]; - VERIFY_BITS(d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - c = (uint128_t)a4 * b[4]; - VERIFY_BITS(c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - d += (c & M) * R; c >>= 52; - VERIFY_BITS(d, 115); - VERIFY_BITS(c, 60); - /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = d & M; d >>= 52; - VERIFY_BITS(t3, 52); - VERIFY_BITS(d, 63); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - d += (uint128_t)a0 * b[4] - + (uint128_t)a1 * b[3] - + (uint128_t)a2 * b[2] - + (uint128_t)a3 * b[1] - + (uint128_t)a4 * b[0]; - VERIFY_BITS(d, 115); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - d += c * R; - VERIFY_BITS(d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = d & M; d >>= 52; - VERIFY_BITS(t4, 52); - VERIFY_BITS(d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - c = (uint128_t)a0 * b[0]; - VERIFY_BITS(c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - d += (uint128_t)a1 * b[4] - + (uint128_t)a2 * b[3] - + (uint128_t)a3 * b[2] - + (uint128_t)a4 * b[1]; - VERIFY_BITS(d, 115); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = d & M; d >>= 52; - VERIFY_BITS(u0, 52); - VERIFY_BITS(d, 63); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - c += (uint128_t)u0 * (R >> 4); - VERIFY_BITS(c, 115); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = c & M; c >>= 52; - VERIFY_BITS(r[0], 52); - VERIFY_BITS(c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - c += (uint128_t)a0 * b[1] - + (uint128_t)a1 * b[0]; - VERIFY_BITS(c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - d += (uint128_t)a2 * b[4] - + (uint128_t)a3 * b[3] - + (uint128_t)a4 * b[2]; - VERIFY_BITS(d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = c & M; c >>= 52; - VERIFY_BITS(r[1], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - c += (uint128_t)a0 * b[2] - + (uint128_t)a1 * b[1] - + (uint128_t)a2 * b[0]; - VERIFY_BITS(c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint128_t)a3 * b[4] - + (uint128_t)a4 * b[3]; - VERIFY_BITS(d, 114); - /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = c & M; c >>= 52; - VERIFY_BITS(r[2], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R + t3; - VERIFY_BITS(c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = c & M; c >>= 52; - VERIFY_BITS(r[3], 52); - VERIFY_BITS(c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += t4; - VERIFY_BITS(c, 49); - /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = c; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { - uint128_t c, d; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - int64_t t3, t4, tx, u0; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - - /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - d = (uint128_t)(a0*2) * a3 - + (uint128_t)(a1*2) * a2; - VERIFY_BITS(d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - c = (uint128_t)a4 * a4; - VERIFY_BITS(c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - d += (c & M) * R; c >>= 52; - VERIFY_BITS(d, 115); - VERIFY_BITS(c, 60); - /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = d & M; d >>= 52; - VERIFY_BITS(t3, 52); - VERIFY_BITS(d, 63); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - a4 *= 2; - d += (uint128_t)a0 * a4 - + (uint128_t)(a1*2) * a3 - + (uint128_t)a2 * a2; - VERIFY_BITS(d, 115); - /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - d += c * R; - VERIFY_BITS(d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = d & M; d >>= 52; - VERIFY_BITS(t4, 52); - VERIFY_BITS(d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - c = (uint128_t)a0 * a0; - VERIFY_BITS(c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - d += (uint128_t)a1 * a4 - + (uint128_t)(a2*2) * a3; - VERIFY_BITS(d, 114); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = d & M; d >>= 52; - VERIFY_BITS(u0, 52); - VERIFY_BITS(d, 62); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - c += (uint128_t)u0 * (R >> 4); - VERIFY_BITS(c, 113); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = c & M; c >>= 52; - VERIFY_BITS(r[0], 52); - VERIFY_BITS(c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - a0 *= 2; - c += (uint128_t)a0 * a1; - VERIFY_BITS(c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - d += (uint128_t)a2 * a4 - + (uint128_t)a3 * a3; - VERIFY_BITS(d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = c & M; c >>= 52; - VERIFY_BITS(r[1], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - c += (uint128_t)a0 * a2 - + (uint128_t)a1 * a1; - VERIFY_BITS(c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint128_t)a3 * a4; - VERIFY_BITS(d, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += (d & M) * R; d >>= 52; - VERIFY_BITS(c, 115); - VERIFY_BITS(d, 62); - /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = c & M; c >>= 52; - VERIFY_BITS(r[2], 52); - VERIFY_BITS(c, 63); - /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += d * R + t3; - VERIFY_BITS(c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = c & M; c >>= 52; - VERIFY_BITS(r[3], 52); - VERIFY_BITS(c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += t4; - VERIFY_BITS(c, 49); - /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = c; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/field_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/field_impl.h deleted file mode 100644 index 5127b279b..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/field_impl.h +++ /dev/null @@ -1,315 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_IMPL_H_ -#define _SECP256K1_FIELD_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "util.h" - -#if defined(USE_FIELD_10X26) -#include "field_10x26_impl.h" -#elif defined(USE_FIELD_5X52) -#include "field_5x52_impl.h" -#else -#error "Please select field implementation" -#endif - -SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe na; - secp256k1_fe_negate(&na, a, 1); - secp256k1_fe_add(&na, b); - return secp256k1_fe_normalizes_to_zero(&na); -} - -SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe na; - secp256k1_fe_negate(&na, a, 1); - secp256k1_fe_add(&na, b); - return secp256k1_fe_normalizes_to_zero_var(&na); -} - -static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { - /** Given that p is congruent to 3 mod 4, we can compute the square root of - * a mod p as the (p+1)/4'th power of a. - * - * As (p+1)/4 is an even number, it will have the same result for a and for - * (-a). Only one of these two numbers actually has a square root however, - * so we test at the end by squaring and comparing to the input. - * Also because (p+1)/4 is an even number, the computed square root is - * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). - */ - secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; - int j; - - /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in - * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - */ - - secp256k1_fe_sqr(&x2, a); - secp256k1_fe_mul(&x2, &x2, a); - - secp256k1_fe_sqr(&x3, &x2); - secp256k1_fe_mul(&x3, &x3, a); - - x6 = x3; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x6, &x6); - } - secp256k1_fe_mul(&x6, &x6, &x3); - - x9 = x6; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x9, &x9); - } - secp256k1_fe_mul(&x9, &x9, &x3); - - x11 = x9; - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&x11, &x11); - } - secp256k1_fe_mul(&x11, &x11, &x2); - - x22 = x11; - for (j=0; j<11; j++) { - secp256k1_fe_sqr(&x22, &x22); - } - secp256k1_fe_mul(&x22, &x22, &x11); - - x44 = x22; - for (j=0; j<22; j++) { - secp256k1_fe_sqr(&x44, &x44); - } - secp256k1_fe_mul(&x44, &x44, &x22); - - x88 = x44; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x88, &x88); - } - secp256k1_fe_mul(&x88, &x88, &x44); - - x176 = x88; - for (j=0; j<88; j++) { - secp256k1_fe_sqr(&x176, &x176); - } - secp256k1_fe_mul(&x176, &x176, &x88); - - x220 = x176; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x220, &x220); - } - secp256k1_fe_mul(&x220, &x220, &x44); - - x223 = x220; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x223, &x223); - } - secp256k1_fe_mul(&x223, &x223, &x3); - - /* The final result is then assembled using a sliding window over the blocks. */ - - t1 = x223; - for (j=0; j<23; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x22); - for (j=0; j<6; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x2); - secp256k1_fe_sqr(&t1, &t1); - secp256k1_fe_sqr(r, &t1); - - /* Check that a square root was actually calculated */ - - secp256k1_fe_sqr(&t1, r); - return secp256k1_fe_equal(&t1, a); -} - -static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { - secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; - int j; - - /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in - * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - */ - - secp256k1_fe_sqr(&x2, a); - secp256k1_fe_mul(&x2, &x2, a); - - secp256k1_fe_sqr(&x3, &x2); - secp256k1_fe_mul(&x3, &x3, a); - - x6 = x3; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x6, &x6); - } - secp256k1_fe_mul(&x6, &x6, &x3); - - x9 = x6; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x9, &x9); - } - secp256k1_fe_mul(&x9, &x9, &x3); - - x11 = x9; - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&x11, &x11); - } - secp256k1_fe_mul(&x11, &x11, &x2); - - x22 = x11; - for (j=0; j<11; j++) { - secp256k1_fe_sqr(&x22, &x22); - } - secp256k1_fe_mul(&x22, &x22, &x11); - - x44 = x22; - for (j=0; j<22; j++) { - secp256k1_fe_sqr(&x44, &x44); - } - secp256k1_fe_mul(&x44, &x44, &x22); - - x88 = x44; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x88, &x88); - } - secp256k1_fe_mul(&x88, &x88, &x44); - - x176 = x88; - for (j=0; j<88; j++) { - secp256k1_fe_sqr(&x176, &x176); - } - secp256k1_fe_mul(&x176, &x176, &x88); - - x220 = x176; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x220, &x220); - } - secp256k1_fe_mul(&x220, &x220, &x44); - - x223 = x220; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x223, &x223); - } - secp256k1_fe_mul(&x223, &x223, &x3); - - /* The final result is then assembled using a sliding window over the blocks. */ - - t1 = x223; - for (j=0; j<23; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x22); - for (j=0; j<5; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, a); - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x2); - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(r, a, &t1); -} - -static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) { -#if defined(USE_FIELD_INV_BUILTIN) - secp256k1_fe_inv(r, a); -#elif defined(USE_FIELD_INV_NUM) - secp256k1_num n, m; - static const secp256k1_fe negone = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL - ); - /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - static const unsigned char prime[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F - }; - unsigned char b[32]; - int res; - secp256k1_fe c = *a; - secp256k1_fe_normalize_var(&c); - secp256k1_fe_get_b32(b, &c); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_num_set_bin(&m, prime, 32); - secp256k1_num_mod_inverse(&n, &n, &m); - secp256k1_num_get_bin(b, 32, &n); - res = secp256k1_fe_set_b32(r, b); - (void)res; - VERIFY_CHECK(res); - /* Verify the result is the (unique) valid inverse using non-GMP code. */ - secp256k1_fe_mul(&c, &c, r); - secp256k1_fe_add(&c, &negone); - CHECK(secp256k1_fe_normalizes_to_zero_var(&c)); -#else -#error "Please select field inverse implementation" -#endif -} - -static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) { - secp256k1_fe u; - size_t i; - if (len < 1) { - return; - } - - VERIFY_CHECK((r + len <= a) || (a + len <= r)); - - r[0] = a[0]; - - i = 0; - while (++i < len) { - secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); - } - - secp256k1_fe_inv_var(&u, &r[--i]); - - while (i > 0) { - size_t j = i--; - secp256k1_fe_mul(&r[j], &r[i], &u); - secp256k1_fe_mul(&u, &u, &a[j]); - } - - r[0] = u; -} - -static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { -#ifndef USE_NUM_NONE - unsigned char b[32]; - secp256k1_num n; - secp256k1_num m; - /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - static const unsigned char prime[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F - }; - - secp256k1_fe c = *a; - secp256k1_fe_normalize_var(&c); - secp256k1_fe_get_b32(b, &c); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_num_set_bin(&m, prime, 32); - return secp256k1_num_jacobi(&n, &m) >= 0; -#else - secp256k1_fe r; - return secp256k1_fe_sqrt(&r, a); -#endif -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/gen_context.c b/builder/crypto/secp256k1/libsecp256k1/src/gen_context.c deleted file mode 100644 index 1835fd491..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/gen_context.c +++ /dev/null @@ -1,74 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#define USE_BASIC_CONFIG 1 - -#include "basic-config.h" -#include "include/secp256k1.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_gen_impl.h" - -static void default_error_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} - -static const secp256k1_callback default_error_callback = { - default_error_callback_fn, - NULL -}; - -int main(int argc, char **argv) { - secp256k1_ecmult_gen_context ctx; - int inner; - int outer; - FILE* fp; - - (void)argc; - (void)argv; - - fp = fopen("src/ecmult_static_context.h","w"); - if (fp == NULL) { - fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); - return -1; - } - - fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#include \"group.h\"\n"); - fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); - fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); - - secp256k1_ecmult_gen_context_init(&ctx); - secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); - for(outer = 0; outer != 64; outer++) { - fprintf(fp,"{\n"); - for(inner = 0; inner != 16; inner++) { - fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); - if (inner != 15) { - fprintf(fp,",\n"); - } else { - fprintf(fp,"\n"); - } - } - if (outer != 63) { - fprintf(fp,"},\n"); - } else { - fprintf(fp,"}\n"); - } - } - fprintf(fp,"};\n"); - secp256k1_ecmult_gen_context_clear(&ctx); - - fprintf(fp, "#undef SC\n"); - fprintf(fp, "#endif\n"); - fclose(fp); - - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/group.h b/builder/crypto/secp256k1/libsecp256k1/src/group.h deleted file mode 100644 index 4957b248f..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/group.h +++ /dev/null @@ -1,144 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_GROUP_ -#define _SECP256K1_GROUP_ - -#include "num.h" -#include "field.h" - -/** A group element of the secp256k1 curve, in affine coordinates. */ -typedef struct { - secp256k1_fe x; - secp256k1_fe y; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_ge; - -#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} -#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -/** A group element of the secp256k1 curve, in jacobian coordinates. */ -typedef struct { - secp256k1_fe x; /* actual X: x/z^2 */ - secp256k1_fe y; /* actual Y: y/z^3 */ - secp256k1_fe z; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_gej; - -#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} -#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -typedef struct { - secp256k1_fe_storage x; - secp256k1_fe_storage y; -} secp256k1_ge_storage; - -#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} - -#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) - -/** Set a group element equal to the point with given X and Y coordinates */ -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); - -/** Set a group element (affine) equal to the point with the given X coordinate - * and a Y coordinate that is a quadratic residue modulo p. The return value - * is true iff a coordinate with the given X coordinate exists. - */ -static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); - -/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness - * for Y. Return value indicates whether the result is valid. */ -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_ge_is_infinity(const secp256k1_ge *a); - -/** Check whether a group element is valid (i.e., on the curve). */ -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); - -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); - -/** Set a group element equal to another which is given in jacobian coordinates */ -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); - -/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); - -/** Set a batch of group elements equal to the inputs given in jacobian - * coordinates (with known z-ratios). zr must contain the known z-ratios such - * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ -static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len); - -/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to - * the same global z "denominator". zr must contain the known z-ratios such - * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y - * coordinates of the result are stored in r, the common z coordinate is - * stored in globalz. */ -static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); - -/** Set a group element (jacobian) equal to the point at infinity. */ -static void secp256k1_gej_set_infinity(secp256k1_gej *r); - -/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); - -/** Compare the X coordinate of a group element (jacobian). */ -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); - -/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_gej_is_infinity(const secp256k1_gej *a); - -/** Check whether a group element's y coordinate is a quadratic residue. */ -static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); - -/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). - * a may not be zero. Constant time. */ -static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); - -/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); - -/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient - than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time - guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); - -#ifdef USE_ENDOMORPHISM -/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); -#endif - -/** Clear a secp256k1_gej to prevent leaking sensitive information. */ -static void secp256k1_gej_clear(secp256k1_gej *r); - -/** Clear a secp256k1_ge to prevent leaking sensitive information. */ -static void secp256k1_ge_clear(secp256k1_ge *r); - -/** Convert a group element to the storage type. */ -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); - -/** Convert a group element back from the storage type. */ -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); - -/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/group_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/group_impl.h deleted file mode 100644 index 7d723532f..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/group_impl.h +++ /dev/null @@ -1,700 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_GROUP_IMPL_H_ -#define _SECP256K1_GROUP_IMPL_H_ - -#include "num.h" -#include "field.h" -#include "group.h" - -/* These points can be generated in sage as follows: - * - * 0. Setup a worksheet with the following parameters. - * b = 4 # whatever CURVE_B will be set to - * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) - * C = EllipticCurve ([F (0), F (b)]) - * - * 1. Determine all the small orders available to you. (If there are - * no satisfactory ones, go back and change b.) - * print C.order().factor(limit=1000) - * - * 2. Choose an order as one of the prime factors listed in the above step. - * (You can also multiply some to get a composite order, though the - * tests will crash trying to invert scalars during signing.) We take a - * random point and scale it to drop its order to the desired value. - * There is some probability this won't work; just try again. - * order = 199 - * P = C.random_point() - * P = (int(P.order()) / int(order)) * P - * assert(P.order() == order) - * - * 3. Print the values. You'll need to use a vim macro or something to - * split the hex output into 4-byte chunks. - * print "%x %x" % P.xy() - */ -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 199 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, - 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, - 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, - 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED -); - -const int CURVE_B = 4; -# elif EXHAUSTIVE_TEST_ORDER == 13 -const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, - 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, - 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, - 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac -); -const int CURVE_B = 2; -# else -# error No known generator for the specified exhaustive test group order. -# endif -#else -/** Generator for secp256k1, value 'g' defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - */ -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( - 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, - 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, - 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, - 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL -); - -const int CURVE_B = 7; -#endif - -static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { - secp256k1_fe zi2; - secp256k1_fe zi3; - secp256k1_fe_sqr(&zi2, zi); - secp256k1_fe_mul(&zi3, &zi2, zi); - secp256k1_fe_mul(&r->x, &a->x, &zi2); - secp256k1_fe_mul(&r->y, &a->y, &zi3); - r->infinity = a->infinity; -} - -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { - r->infinity = 0; - r->x = *x; - r->y = *y; -} - -static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { - return a->infinity; -} - -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { - *r = *a; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); -} - -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - r->infinity = a->infinity; - secp256k1_fe_inv(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - r->x = a->x; - r->y = a->y; -} - -static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - r->infinity = a->infinity; - if (a->infinity) { - return; - } - secp256k1_fe_inv_var(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - r->x = a->x; - r->y = a->y; -} - -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { - secp256k1_fe *az; - secp256k1_fe *azi; - size_t i; - size_t count = 0; - az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); - for (i = 0; i < len; i++) { - if (!a[i].infinity) { - az[count++] = a[i].z; - } - } - - azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); - secp256k1_fe_inv_all_var(azi, az, count); - free(az); - - count = 0; - for (i = 0; i < len; i++) { - r[i].infinity = a[i].infinity; - if (!a[i].infinity) { - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); - } - } - free(azi); -} - -static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { - size_t i = len - 1; - secp256k1_fe zi; - - if (len > 0) { - /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ - secp256k1_fe_inv(&zi, &a[i].z); - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - - /* Work out way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - secp256k1_fe_mul(&zi, &zi, &zr[i]); - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - } - } -} - -static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { - size_t i = len - 1; - secp256k1_fe zs; - - if (len > 0) { - /* The z of the final point gives us the "global Z" for the table. */ - r[i].x = a[i].x; - r[i].y = a[i].y; - *globalz = a[i].z; - r[i].infinity = 0; - zs = zr[i]; - - /* Work our way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - if (i != len - 1) { - secp256k1_fe_mul(&zs, &zs, &zr[i]); - } - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); - } - } -} - -static void secp256k1_gej_set_infinity(secp256k1_gej *r) { - r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); -} - -static void secp256k1_gej_clear(secp256k1_gej *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); -} - -static void secp256k1_ge_clear(secp256k1_ge *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); -} - -static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { - secp256k1_fe x2, x3, c; - r->x = *x; - secp256k1_fe_sqr(&x2, x); - secp256k1_fe_mul(&x3, x, &x2); - r->infinity = 0; - secp256k1_fe_set_int(&c, CURVE_B); - secp256k1_fe_add(&c, &x3); - return secp256k1_fe_sqrt(&r->y, &c); -} - -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { - if (!secp256k1_ge_set_xquad(r, x)) { - return 0; - } - secp256k1_fe_normalize_var(&r->y); - if (secp256k1_fe_is_odd(&r->y) != odd) { - secp256k1_fe_negate(&r->y, &r->y, 1); - } - return 1; - -} - -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - secp256k1_fe_set_int(&r->z, 1); -} - -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { - secp256k1_fe r, r2; - VERIFY_CHECK(!a->infinity); - secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); - r2 = a->x; secp256k1_fe_normalize_weak(&r2); - return secp256k1_fe_equal_var(&r, &r2); -} - -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - r->z = a->z; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); -} - -static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { - return a->infinity; -} - -static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { - secp256k1_fe y2, x3, z2, z6; - if (a->infinity) { - return 0; - } - /** y^2 = x^3 + 7 - * (Y/Z^3)^2 = (X/Z^2)^3 + 7 - * Y^2 / Z^6 = X^3 / Z^6 + 7 - * Y^2 = X^3 + 7*Z^6 - */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); - secp256k1_fe_mul_int(&z6, CURVE_B); - secp256k1_fe_add(&x3, &z6); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { - secp256k1_fe y2, x3, c; - if (a->infinity) { - return 0; - } - /* y^2 = x^3 + 7 */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_set_int(&c, CURVE_B); - secp256k1_fe_add(&x3, &c); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. - * - * Note that there is an implementation described at - * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - * which trades a multiply for a square, but in practice this is actually slower, - * mainly because it requires more normalizations. - */ - secp256k1_fe t1,t2,t3,t4; - /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, - * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have - * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. - * - * Having said this, if this function receives a point on a sextic twist, e.g. by - * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, - * since -6 does have a cube root mod p. For this point, this function will not set - * the infinity flag even though the point doubles to infinity, and the result - * point will be gibberish (z = 0 but infinity = 0). - */ - r->infinity = a->infinity; - if (r->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - return; - } - - if (rzr != NULL) { - *rzr = a->y; - secp256k1_fe_normalize_weak(rzr); - secp256k1_fe_mul_int(rzr, 2); - } - - secp256k1_fe_mul(&r->z, &a->z, &a->y); - secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ - secp256k1_fe_sqr(&t1, &a->x); - secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ - secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ - secp256k1_fe_sqr(&t3, &a->y); - secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ - secp256k1_fe_sqr(&t4, &t3); - secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ - secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ - r->x = t3; - secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ - secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ - secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ - secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ - secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ - secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ - secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ - secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ - secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ -} - -static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); - secp256k1_gej_double_var(r, a, rzr); -} - -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { - /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ - secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - *r = *b; - return; - } - - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - - r->infinity = 0; - secp256k1_fe_sqr(&z22, &b->z); - secp256k1_fe_sqr(&z12, &a->z); - secp256k1_fe_mul(&u1, &a->x, &z22); - secp256k1_fe_mul(&u2, &b->x, &z12); - secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - secp256k1_fe_mul(&h, &h, &b->z); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { - /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - secp256k1_gej_set_ge(r, b); - return; - } - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - r->infinity = 0; - - secp256k1_fe_sqr(&z12, &a->z); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { - /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (b->infinity) { - *r = *a; - return; - } - if (a->infinity) { - secp256k1_fe bzinv2, bzinv3; - r->infinity = b->infinity; - secp256k1_fe_sqr(&bzinv2, bzinv); - secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); - secp256k1_fe_mul(&r->x, &b->x, &bzinv2); - secp256k1_fe_mul(&r->y, &b->y, &bzinv3); - secp256k1_fe_set_int(&r->z, 1); - return; - } - r->infinity = 0; - - /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to - * secp256k1's isomorphism we can multiply the Z coordinates on both sides - * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). - * This means that (rx,ry,rz) can be calculated as - * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. - * The variable az below holds the modified Z coordinate for a, which is used - * for the computation of rx and ry, but not for rz. - */ - secp256k1_fe_mul(&az, &a->z, bzinv); - - secp256k1_fe_sqr(&z12, &az); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, NULL); - } else { - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - - -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { - /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ - static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; - secp256k1_fe m_alt, rr_alt; - int infinity, degenerate; - VERIFY_CHECK(!b->infinity); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); - - /** In: - * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. - * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. - * we find as solution for a unified addition/doubling formula: - * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. - * x3 = lambda^2 - (x1 + x2) - * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). - * - * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: - * U1 = X1*Z2^2, U2 = X2*Z1^2 - * S1 = Y1*Z2^3, S2 = Y2*Z1^3 - * Z = Z1*Z2 - * T = U1+U2 - * M = S1+S2 - * Q = T*M^2 - * R = T^2-U1*U2 - * X3 = 4*(R^2-Q) - * Y3 = 4*(R*(3*Q-2*R^2)-M^4) - * Z3 = 2*M*Z - * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) - * - * This formula has the benefit of being the same for both addition - * of distinct points and doubling. However, it breaks down in the - * case that either point is infinity, or that y1 = -y2. We handle - * these cases in the following ways: - * - * - If b is infinity we simply bail by means of a VERIFY_CHECK. - * - * - If a is infinity, we detect this, and at the end of the - * computation replace the result (which will be meaningless, - * but we compute to be constant-time) with b.x : b.y : 1. - * - * - If a = -b, we have y1 = -y2, which is a degenerate case. - * But here the answer is infinity, so we simply set the - * infinity flag of the result, overriding the computed values - * without even needing to cmov. - * - * - If y1 = -y2 but x1 != x2, which does occur thanks to certain - * properties of our curve (specifically, 1 has nontrivial cube - * roots in our field, and the curve equation has no x coefficient) - * then the answer is not infinity but also not given by the above - * equation. In this case, we cmov in place an alternate expression - * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these - * expressions for lambda are defined, they are equal, and can be - * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) - * then substitution of x^3 + 7 for y^2 (using the curve equation). - * For all pairs of nonzero points (a, b) at least one is defined, - * so this covers everything. - */ - - secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ - u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ - secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ - s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ - secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ - secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ - m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ - secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ - secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ - secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ - /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" - * case that Z = z1z2 = 0, and this is special-cased later on). */ - degenerate = secp256k1_fe_normalizes_to_zero(&m) & - secp256k1_fe_normalizes_to_zero(&rr); - /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. - * This means either x1 == beta*x2 or beta*x1 == x2, where beta is - * a nontrivial cube root of one. In either case, an alternate - * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), - * so we set R/M equal to this. */ - rr_alt = s1; - secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ - secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ - - secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); - secp256k1_fe_cmov(&m_alt, &m, !degenerate); - /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. - * From here on out Ralt and Malt represent the numerator - * and denominator of lambda; R and M represent the explicit - * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ - secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ - /* These two lines use the observation that either M == Malt or M == 0, - * so M^3 * Malt is either Malt^4 (which is computed by squaring), or - * zero (which is "computed" by cmov). So the cost is one squaring - * versus two multiplications. */ - secp256k1_fe_sqr(&n, &n); - secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ - secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ - secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ - infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); - secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ - secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ - secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ - secp256k1_fe_normalize_weak(&t); - r->x = t; /* r->x = Ralt^2-Q (1) */ - secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ - secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ - secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ - secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ - secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ - secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ - - /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ - secp256k1_fe_cmov(&r->x, &b->x, a->infinity); - secp256k1_fe_cmov(&r->y, &b->y, a->infinity); - secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); - r->infinity = infinity; -} - -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { - /* Operations: 4 mul, 1 sqr */ - secp256k1_fe zz; - VERIFY_CHECK(!secp256k1_fe_is_zero(s)); - secp256k1_fe_sqr(&zz, s); - secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ - secp256k1_fe_mul(&r->y, &r->y, &zz); - secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ - secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ -} - -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { - secp256k1_fe x, y; - VERIFY_CHECK(!a->infinity); - x = a->x; - secp256k1_fe_normalize(&x); - y = a->y; - secp256k1_fe_normalize(&y); - secp256k1_fe_to_storage(&r->x, &x); - secp256k1_fe_to_storage(&r->y, &y); -} - -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { - secp256k1_fe_from_storage(&r->x, &a->x); - secp256k1_fe_from_storage(&r->y, &a->y); - r->infinity = 0; -} - -static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { - secp256k1_fe_storage_cmov(&r->x, &a->x, flag); - secp256k1_fe_storage_cmov(&r->y, &a->y, flag); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { - static const secp256k1_fe beta = SECP256K1_FE_CONST( - 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, - 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul - ); - *r = *a; - secp256k1_fe_mul(&r->x, &r->x, &beta); -} -#endif - -static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { - secp256k1_fe yz; - - if (a->infinity) { - return 0; - } - - /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as - * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z - is */ - secp256k1_fe_mul(&yz, &a->y, &a->z); - return secp256k1_fe_is_quad_var(&yz); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/hash.h b/builder/crypto/secp256k1/libsecp256k1/src/hash.h deleted file mode 100644 index fca98cab9..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_HASH_ -#define _SECP256K1_HASH_ - -#include -#include - -typedef struct { - uint32_t s[8]; - uint32_t buf[16]; /* In big endian */ - size_t bytes; -} secp256k1_sha256_t; - -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); - -typedef struct { - secp256k1_sha256_t inner, outer; -} secp256k1_hmac_sha256_t; - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); - -typedef struct { - unsigned char v[32]; - unsigned char k[32]; - int retry; -} secp256k1_rfc6979_hmac_sha256_t; - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/hash_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/hash_impl.h deleted file mode 100644 index b47e65f83..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/hash_impl.h +++ /dev/null @@ -1,281 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_HASH_IMPL_H_ -#define _SECP256K1_HASH_IMPL_H_ - -#include "hash.h" - -#include -#include -#include - -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) -#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) -#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) -#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) -#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) - -#define Round(a,b,c,d,e,f,g,h,k,w) do { \ - uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ - uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ - (d) += t1; \ - (h) = t1 + t2; \ -} while(0) - -#ifdef WORDS_BIGENDIAN -#define BE32(x) (x) -#else -#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) -#endif - -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { - hash->s[0] = 0x6a09e667ul; - hash->s[1] = 0xbb67ae85ul; - hash->s[2] = 0x3c6ef372ul; - hash->s[3] = 0xa54ff53aul; - hash->s[4] = 0x510e527ful; - hash->s[5] = 0x9b05688cul; - hash->s[6] = 0x1f83d9abul; - hash->s[7] = 0x5be0cd19ul; - hash->bytes = 0; -} - -/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; -} - -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { - size_t bufsize = hash->bytes & 0x3F; - hash->bytes += len; - while (bufsize + len >= 64) { - /* Fill the buffer, and process it. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); - data += 64 - bufsize; - len -= 64 - bufsize; - secp256k1_sha256_transform(hash->s, hash->buf); - bufsize = 0; - } - if (len) { - /* Fill the buffer with what remains. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, len); - } -} - -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { - static const unsigned char pad[64] = {0x80, 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, 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}; - uint32_t sizedesc[2]; - uint32_t out[8]; - int i = 0; - sizedesc[0] = BE32(hash->bytes >> 29); - sizedesc[1] = BE32(hash->bytes << 3); - secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); - secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); - for (i = 0; i < 8; i++) { - out[i] = BE32(hash->s[i]); - hash->s[i] = 0; - } - memcpy(out32, (const unsigned char*)out, 32); -} - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { - int n; - unsigned char rkey[64]; - if (keylen <= 64) { - memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, 64 - keylen); - } else { - secp256k1_sha256_t sha256; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, key, keylen); - secp256k1_sha256_finalize(&sha256, rkey); - memset(rkey + 32, 0, 32); - } - - secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < 64; n++) { - rkey[n] ^= 0x5c; - } - secp256k1_sha256_write(&hash->outer, rkey, 64); - - secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < 64; n++) { - rkey[n] ^= 0x5c ^ 0x36; - } - secp256k1_sha256_write(&hash->inner, rkey, 64); - memset(rkey, 0, 64); -} - -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { - secp256k1_sha256_write(&hash->inner, data, size); -} - -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { - unsigned char temp[32]; - secp256k1_sha256_finalize(&hash->inner, temp); - secp256k1_sha256_write(&hash->outer, temp, 32); - memset(temp, 0, 32); - secp256k1_sha256_finalize(&hash->outer, out32); -} - - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256_t hmac; - static const unsigned char zero[1] = {0x00}; - static const unsigned char one[1] = {0x01}; - - memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ - memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ - - /* RFC6979 3.2.d. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - - /* RFC6979 3.2.f. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, one, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - rng->retry = 0; -} - -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { - /* RFC6979 3.2.h. */ - static const unsigned char zero[1] = {0x00}; - if (rng->retry) { - secp256k1_hmac_sha256_t hmac; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - } - - while (outlen > 0) { - secp256k1_hmac_sha256_t hmac; - int now = outlen; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - if (now > 32) { - now = 32; - } - memcpy(out, rng->v, now); - out += now; - outlen -= now; - } - - rng->retry = 1; -} - -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { - memset(rng->k, 0, 32); - memset(rng->v, 0, 32); - rng->retry = 0; -} - -#undef BE32 -#undef Round -#undef sigma1 -#undef sigma0 -#undef Sigma1 -#undef Sigma0 -#undef Maj -#undef Ch - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java deleted file mode 100644 index 1c67802fb..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import java.math.BigInteger; -import com.google.common.base.Preconditions; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import static org.bitcoin.NativeSecp256k1Util.*; - -/** - *

This class holds native methods to handle ECDSA verification.

- * - *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

- * - *

To build secp256k1 for use with bitcoinj, run - * `./configure --enable-jni --enable-experimental --enable-module-ecdh` - * and `make` then copy `.libs/libsecp256k1.so` to your system library path - * or point the JVM to the folder containing it with -Djava.library.path - *

- */ -public class NativeSecp256k1 { - - private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); - private static final Lock r = rwl.readLock(); - private static final Lock w = rwl.writeLock(); - private static ThreadLocal nativeECDSABuffer = new ThreadLocal(); - /** - * Verifies the given secp256k1 signature in native code. - * Calling when enabled == false is undefined (probably library not loaded) - * - * @param data The data which was signed, must be exactly 32 bytes - * @param signature The signature - * @param pub The public key which did the signing - */ - public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ - Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 520) { - byteBuff = ByteBuffer.allocateDirect(520); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.put(signature); - byteBuff.put(pub); - - byte[][] retByteArray; - - r.lock(); - try { - return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; - } finally { - r.unlock(); - } - } - - /** - * libsecp256k1 Create an ECDSA signature. - * - * @param data Message hash, 32 bytes - * @param key Secret key, 32 bytes - * - * Return values - * @param sig byte array of signature - */ - public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ - Preconditions.checkArgument(data.length == 32 && sec.length <= 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 32 + 32) { - byteBuff = ByteBuffer.allocateDirect(32 + 32); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.put(sec); - - byte[][] retByteArray; - - r.lock(); - try { - retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] sigArr = retByteArray[0]; - int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(sigArr.length, sigLen, "Got bad signature length."); - - return retVal == 0 ? new byte[0] : sigArr; - } - - /** - * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid - * - * @param seckey ECDSA Secret key, 32 bytes - */ - public static boolean secKeyVerify(byte[] seckey) { - Preconditions.checkArgument(seckey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seckey.length) { - byteBuff = ByteBuffer.allocateDirect(seckey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - - r.lock(); - try { - return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; - } finally { - r.unlock(); - } - } - - - /** - * libsecp256k1 Compute Pubkey - computes public key from secret key - * - * @param seckey ECDSA Secret key, 32 bytes - * - * Return values - * @param pubkey ECDSA Public key, 33 or 65 bytes - */ - //TODO add a 'compressed' arg - public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ - Preconditions.checkArgument(seckey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seckey.length) { - byteBuff = ByteBuffer.allocateDirect(seckey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - - byte[][] retByteArray; - - r.lock(); - try { - retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - return retVal == 0 ? new byte[0]: pubArr; - } - - /** - * libsecp256k1 Cleanup - This destroys the secp256k1 context object - * This should be called at the end of the program for proper cleanup of the context. - */ - public static synchronized void cleanup() { - w.lock(); - try { - secp256k1_destroy_context(Secp256k1Context.getContext()); - } finally { - w.unlock(); - } - } - - public static long cloneContext() { - r.lock(); - try { - return secp256k1_ctx_clone(Secp256k1Context.getContext()); - } finally { r.unlock(); } - } - - /** - * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it - * - * @param tweak some bytes to tweak with - * @param seckey 32-byte seckey - */ - public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(privkey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(privkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] privArr = retByteArray[0]; - - int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(privArr.length, privLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return privArr; - } - - /** - * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it - * - * @param tweak some bytes to tweak with - * @param seckey 32-byte seckey - */ - public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(privkey.length == 32); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(privkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); - } finally { - r.unlock(); - } - - byte[] privArr = retByteArray[0]; - - int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(privArr.length, privLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return privArr; - } - - /** - * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it - * - * @param tweak some bytes to tweak with - * @param pubkey 32-byte seckey - */ - public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(pubkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - - int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return pubArr; - } - - /** - * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it - * - * @param tweak some bytes to tweak with - * @param pubkey 32-byte seckey - */ - public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ - Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { - byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(pubkey); - byteBuff.put(tweak); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] pubArr = retByteArray[0]; - - int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; - int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); - - assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); - - assertEquals(retVal, 1, "Failed return value check."); - - return pubArr; - } - - /** - * libsecp256k1 create ECDH secret - constant time ECDH calculation - * - * @param seckey byte array of secret key used in exponentiaion - * @param pubkey byte array of public key used in exponentiaion - */ - public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ - Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { - byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seckey); - byteBuff.put(pubkey); - - byte[][] retByteArray; - r.lock(); - try { - retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); - } finally { - r.unlock(); - } - - byte[] resArr = retByteArray[0]; - int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); - - assertEquals(resArr.length, 32, "Got bad result length."); - assertEquals(retVal, 1, "Failed return value check."); - - return resArr; - } - - /** - * libsecp256k1 randomize - updates the context randomization - * - * @param seed 32-byte random seed - */ - public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ - Preconditions.checkArgument(seed.length == 32 || seed == null); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null || byteBuff.capacity() < seed.length) { - byteBuff = ByteBuffer.allocateDirect(seed.length); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(seed); - - w.lock(); - try { - return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; - } finally { - w.unlock(); - } - } - - private static native long secp256k1_ctx_clone(long context); - - private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); - - private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); - - private static native void secp256k1_destroy_context(long context); - - private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); - - private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); - - private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); - - private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); - - private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); - -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java deleted file mode 100644 index c00d08899..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.bitcoin; - -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.math.BigInteger; -import javax.xml.bind.DatatypeConverter; -import static org.bitcoin.NativeSecp256k1Util.*; - -/** - * This class holds test cases defined for testing this library. - */ -public class NativeSecp256k1Test { - - //TODO improve comments/add more tests - /** - * This tests verify() for a valid signature - */ - public static void testVerifyPos() throws AssertFailException{ - boolean result = false; - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - result = NativeSecp256k1.verify( data, sig, pub); - assertEquals( result, true , "testVerifyPos"); - } - - /** - * This tests verify() for a non-valid signature - */ - public static void testVerifyNeg() throws AssertFailException{ - boolean result = false; - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" - byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - result = NativeSecp256k1.verify( data, sig, pub); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, false , "testVerifyNeg"); - } - - /** - * This tests secret key verify() for a valid secretkey - */ - public static void testSecKeyVerifyPos() throws AssertFailException{ - boolean result = false; - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - result = NativeSecp256k1.secKeyVerify( sec ); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, true , "testSecKeyVerifyPos"); - } - - /** - * This tests secret key verify() for a invalid secretkey - */ - public static void testSecKeyVerifyNeg() throws AssertFailException{ - boolean result = false; - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - result = NativeSecp256k1.secKeyVerify( sec ); - //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); - assertEquals( result, false , "testSecKeyVerifyNeg"); - } - - /** - * This tests public key create() for a valid secretkey - */ - public static void testPubKeyCreatePos() throws AssertFailException{ - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); - } - - /** - * This tests public key create() for a invalid secretkey - */ - public static void testPubKeyCreateNeg() throws AssertFailException{ - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); - } - - /** - * This tests sign() for a valid secretkey - */ - public static void testSignPos() throws AssertFailException{ - - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); - } - - /** - * This tests sign() for a invalid secretkey - */ - public static void testSignNeg() throws AssertFailException{ - byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" - byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString, "" , "testSignNeg"); - } - - /** - * This tests private key tweak-add - */ - public static void testPrivKeyTweakAdd_1() throws AssertFailException { - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); - } - - /** - * This tests private key tweak-mul - */ - public static void testPrivKeyTweakMul_1() throws AssertFailException { - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); - } - - /** - * This tests private key tweak-add uncompressed - */ - public static void testPrivKeyTweakAdd_2() throws AssertFailException { - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); - } - - /** - * This tests private key tweak-mul uncompressed - */ - public static void testPrivKeyTweakMul_2() throws AssertFailException { - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" - - byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); - } - - /** - * This tests seed randomization - */ - public static void testRandomize() throws AssertFailException { - byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" - boolean result = NativeSecp256k1.randomize(seed); - assertEquals( result, true, "testRandomize"); - } - - public static void testCreateECDHSecret() throws AssertFailException{ - - byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); - byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); - - byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); - String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); - } - - public static void main(String[] args) throws AssertFailException{ - - - System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); - - assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); - - //Test verify() success/fail - testVerifyPos(); - testVerifyNeg(); - - //Test secKeyVerify() success/fail - testSecKeyVerifyPos(); - testSecKeyVerifyNeg(); - - //Test computePubkey() success/fail - testPubKeyCreatePos(); - testPubKeyCreateNeg(); - - //Test sign() success/fail - testSignPos(); - testSignNeg(); - - //Test privKeyTweakAdd() 1 - testPrivKeyTweakAdd_1(); - - //Test privKeyTweakMul() 2 - testPrivKeyTweakMul_1(); - - //Test privKeyTweakAdd() 3 - testPrivKeyTweakAdd_2(); - - //Test privKeyTweakMul() 4 - testPrivKeyTweakMul_2(); - - //Test randomize() - testRandomize(); - - //Test ECDH - testCreateECDHSecret(); - - NativeSecp256k1.cleanup(); - - System.out.println(" All tests passed." ); - - } -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java deleted file mode 100644 index 04732ba04..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -public class NativeSecp256k1Util{ - - public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ - if( val != val2 ) - throw new AssertFailException("FAIL: " + message); - } - - public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ - if( val != val2 ) - throw new AssertFailException("FAIL: " + message); - else - System.out.println("PASS: " + message); - } - - public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ - if( !val.equals(val2) ) - throw new AssertFailException("FAIL: " + message); - else - System.out.println("PASS: " + message); - } - - public static class AssertFailException extends Exception { - public AssertFailException(String message) { - super( message ); - } - } -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java b/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java deleted file mode 100644 index 216c986a8..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -/** - * This class holds the context reference used in native methods - * to handle ECDSA operations. - */ -public class Secp256k1Context { - private static final boolean enabled; //true if the library is loaded - private static final long context; //ref to pointer to context obj - - static { //static initializer - boolean isEnabled = true; - long contextRef = -1; - try { - System.loadLibrary("secp256k1"); - contextRef = secp256k1_init_context(); - } catch (UnsatisfiedLinkError e) { - System.out.println("UnsatisfiedLinkError: " + e.toString()); - isEnabled = false; - } - enabled = isEnabled; - context = contextRef; - } - - public static boolean isEnabled() { - return enabled; - } - - public static long getContext() { - if(!enabled) return -1; //sanity check - return context; - } - - private static native long secp256k1_init_context(); -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c deleted file mode 100644 index bcef7b32c..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ /dev/null @@ -1,377 +0,0 @@ -#include -#include -#include -#include "org_bitcoin_NativeSecp256k1.h" -#include "include/secp256k1.h" -#include "include/secp256k1_ecdh.h" -#include "include/secp256k1_recovery.h" - - -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone - (JNIEnv* env, jclass classObject, jlong ctx_l) -{ - const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx); - - (void)classObject;(void)env; - - return ctx_clone_l; - -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - (void)classObject; - - return secp256k1_context_randomize(ctx, seed); - -} - -SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context - (JNIEnv* env, jclass classObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - secp256k1_context_destroy(ctx); - - (void)classObject;(void)env; -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* sigdata = { (unsigned char*) (data + 32) }; - const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; - - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pubkey; - - int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); - - if( ret ) { - ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); - - if( ret ) { - ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); - } - } - - (void)classObject; - - return ret; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - unsigned char* secKey = (unsigned char*) (data + 32); - - jobjectArray retArray; - jbyteArray sigArray, intsByteArray; - unsigned char intsarray[2]; - - secp256k1_ecdsa_signature sig[72]; - - int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); - - unsigned char outputSer[72]; - size_t outputLen = 72; - - if( ret ) { - int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - sigArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - (void)classObject; - - return secp256k1_ec_seckey_verify(ctx, secKey); -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - - secp256k1_pubkey pubkey; - - jobjectArray retArray; - jbyteArray pubkeyArray, intsByteArray; - unsigned char intsarray[2]; - - int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); - - unsigned char outputSer[65]; - size_t outputLen = 65; - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubkeyArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; - -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (privkey + 32); - - jobjectArray retArray; - jbyteArray privArray, intsByteArray; - unsigned char intsarray[2]; - - int privkeylen = 32; - - int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); - - intsarray[0] = privkeylen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - privArray = (*env)->NewByteArray(env, privkeylen); - (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); - (*env)->SetObjectArrayElement(env, retArray, 0, privArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (privkey + 32); - - jobjectArray retArray; - jbyteArray privArray, intsByteArray; - unsigned char intsarray[2]; - - int privkeylen = 32; - - int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); - - intsarray[0] = privkeylen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - privArray = (*env)->NewByteArray(env, privkeylen); - (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); - (*env)->SetObjectArrayElement(env, retArray, 0, privArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; -/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ - unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (pkey + publen); - - jobjectArray retArray; - jbyteArray pubArray, intsByteArray; - unsigned char intsarray[2]; - unsigned char outputSer[65]; - size_t outputLen = 65; - - secp256k1_pubkey pubkey; - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); - - if( ret ) { - ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); - } - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* tweak = (unsigned char*) (pkey + publen); - - jobjectArray retArray; - jbyteArray pubArray, intsByteArray; - unsigned char intsarray[2]; - unsigned char outputSer[65]; - size_t outputLen = 65; - - secp256k1_pubkey pubkey; - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); - - if ( ret ) { - ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); - } - - if( ret ) { - int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; - } - - intsarray[0] = outputLen; - intsarray[1] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - pubArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); - (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); - - intsByteArray = (*env)->NewByteArray(env, 2); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} - -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine - (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) -{ - (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; - - return 0; -} - -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) -{ - secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; - const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); - const unsigned char* pubdata = (const unsigned char*) (secdata + 32); - - jobjectArray retArray; - jbyteArray outArray, intsByteArray; - unsigned char intsarray[1]; - secp256k1_pubkey pubkey; - unsigned char nonce_res[32]; - size_t outputLen = 32; - - int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); - - if (ret) { - ret = secp256k1_ecdh( - ctx, - nonce_res, - &pubkey, - secdata - ); - } - - intsarray[0] = ret; - - retArray = (*env)->NewObjectArray(env, 2, - (*env)->FindClass(env, "[B"), - (*env)->NewByteArray(env, 1)); - - outArray = (*env)->NewByteArray(env, outputLen); - (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); - (*env)->SetObjectArrayElement(env, retArray, 0, outArray); - - intsByteArray = (*env)->NewByteArray(env, 1); - (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); - (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); - - (void)classObject; - - return retArray; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h deleted file mode 100644 index fe613c9e9..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ /dev/null @@ -1,119 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_NativeSecp256k1 */ - -#ifndef _Included_org_bitcoin_NativeSecp256k1 -#define _Included_org_bitcoin_NativeSecp256k1 -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ctx_clone - * Signature: (J)J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_context_randomize - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_destroy_context - * Signature: (J)V - */ -SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_verify - * Signature: (Ljava/nio/ByteBuffer;JII)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv *, jclass, jobject, jlong, jint, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_sign - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_seckey_verify - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_create - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_parse - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdh - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c b/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c deleted file mode 100644 index a52939e7e..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include "org_bitcoin_Secp256k1Context.h" -#include "include/secp256k1.h" - -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context - (JNIEnv* env, jclass classObject) -{ - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - (void)classObject;(void)env; - - return (uintptr_t)ctx; -} - diff --git a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h b/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h deleted file mode 100644 index 0d2bc84b7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h +++ /dev/null @@ -1,22 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_Secp256k1Context */ - -#ifndef _Included_org_bitcoin_Secp256k1Context -#define _Included_org_bitcoin_Secp256k1Context -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_Secp256k1Context - * Method: secp256k1_init_context - * Signature: ()J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/dummy.go b/builder/crypto/secp256k1/libsecp256k1/src/modules/dummy.go deleted file mode 100644 index 99c538db5..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package module diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include b/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include deleted file mode 100644 index e3088b469..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_ecdh.h -noinst_HEADERS += src/modules/ecdh/main_impl.h -noinst_HEADERS += src/modules/ecdh/tests_impl.h -if USE_BENCHMARK -noinst_PROGRAMS += bench_ecdh -bench_ecdh_SOURCES = src/bench_ecdh.c -bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) -endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go b/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go deleted file mode 100644 index 48c2e0aa5..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package ecdh diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h deleted file mode 100644 index 9e30fb73d..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_MAIN_ -#define _SECP256K1_MODULE_ECDH_MAIN_ - -#include "include/secp256k1_ecdh.h" -#include "ecmult_const_impl.h" - -int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { - int ret = 0; - int overflow = 0; - secp256k1_gej res; - secp256k1_ge pt; - secp256k1_scalar s; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(result != NULL); - ARG_CHECK(point != NULL); - ARG_CHECK(scalar != NULL); - - secp256k1_pubkey_load(ctx, &pt, point); - secp256k1_scalar_set_b32(&s, scalar, &overflow); - if (overflow || secp256k1_scalar_is_zero(&s)) { - ret = 0; - } else { - unsigned char x[32]; - unsigned char y[1]; - secp256k1_sha256_t sha; - - secp256k1_ecmult_const(&res, &pt, &s); - secp256k1_ge_set_gej(&pt, &res); - /* Compute a hash of the point in compressed form - * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not - * expect its output to be secret and has a timing sidechannel. */ - secp256k1_fe_normalize(&pt.x); - secp256k1_fe_normalize(&pt.y); - secp256k1_fe_get_b32(x, &pt.x); - y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, y, sizeof(y)); - secp256k1_sha256_write(&sha, x, sizeof(x)); - secp256k1_sha256_finalize(&sha, result); - ret = 1; - } - - secp256k1_scalar_clear(&s); - return ret; -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h deleted file mode 100644 index 85a5d0a9a..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h +++ /dev/null @@ -1,105 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_TESTS_ -#define _SECP256K1_MODULE_ECDH_TESTS_ - -void test_ecdh_api(void) { - /* Setup context that just counts errors */ - secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_pubkey point; - unsigned char res[32]; - unsigned char s_one[32] = { 0 }; - int32_t ecount = 0; - s_one[31] = 1; - - secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); - CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); - - /* Check all NULLs are detected */ - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); - CHECK(ecount == 3); - - /* Cleanup */ - secp256k1_context_destroy(tctx); -} - -void test_ecdh_generator_basepoint(void) { - unsigned char s_one[32] = { 0 }; - secp256k1_pubkey point[2]; - int i; - - s_one[31] = 1; - /* Check against pubkey creation when the basepoint is the generator */ - for (i = 0; i < 100; ++i) { - secp256k1_sha256_t sha; - unsigned char s_b32[32]; - unsigned char output_ecdh[32]; - unsigned char output_ser[32]; - unsigned char point_ser[33]; - size_t point_ser_len = sizeof(point_ser); - secp256k1_scalar s; - - random_scalar_order(&s); - secp256k1_scalar_get_b32(s_b32, &s); - - /* compute using ECDH function */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); - CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); - /* compute "explicitly" */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - CHECK(point_ser_len == sizeof(point_ser)); - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, point_ser, point_ser_len); - secp256k1_sha256_finalize(&sha, output_ser); - /* compare */ - CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); - } -} - -void test_bad_scalar(void) { - unsigned char s_zero[32] = { 0 }; - unsigned char s_overflow[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - unsigned char s_rand[32] = { 0 }; - unsigned char output[32]; - secp256k1_scalar rand; - secp256k1_pubkey point; - - /* Create random point */ - random_scalar_order(&rand); - secp256k1_scalar_get_b32(s_rand, &rand); - CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); - - /* Try to multiply it by bad values */ - CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); - /* ...and a good one */ - s_overflow[31] -= 1; - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); -} - -void run_ecdh_tests(void) { - test_ecdh_api(); - test_ecdh_generator_basepoint(); - test_bad_scalar(); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include b/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include deleted file mode 100644 index bf23c26e7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_recovery.h -noinst_HEADERS += src/modules/recovery/main_impl.h -noinst_HEADERS += src/modules/recovery/tests_impl.h -if USE_BENCHMARK -noinst_PROGRAMS += bench_recover -bench_recover_SOURCES = src/bench_recover.c -bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) -endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go b/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go deleted file mode 100644 index 8efbd7abe..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build dummy -// +build dummy - -// Package c contains only a C file. -// -// This Go file is part of a workaround for `go mod vendor`. -// Please see the file crypto/secp256k1/dummy.go for more information. -package recovery diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h deleted file mode 100755 index c6fbe2398..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h +++ /dev/null @@ -1,193 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ -#define _SECP256K1_MODULE_RECOVERY_MAIN_ - -#include "include/secp256k1_recovery.h" - -static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } - *recid = sig->data[64]; -} - -static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } - sig->data[64] = recid; -} - -int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - (void)ctx; - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - ARG_CHECK(recid >= 0 && recid <= 3); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { - secp256k1_scalar r, s; - - (void)ctx; - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(recid != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { - secp256k1_scalar r, s; - int recid; - - (void)ctx; - ARG_CHECK(sig != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; -} - -static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { - unsigned char brx[32]; - secp256k1_fe fx; - secp256k1_ge x; - secp256k1_gej xj; - secp256k1_scalar rn, u1, u2; - secp256k1_gej qj; - int r; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_get_b32(brx, sigr); - r = secp256k1_fe_set_b32(&fx, brx); - (void)r; - VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ - if (recid & 2) { - if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - return 0; - } - secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); - } - if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { - return 0; - } - secp256k1_gej_set_ge(&xj, &x); - secp256k1_scalar_inverse_var(&rn, sigr); - secp256k1_scalar_mul(&u1, &rn, message); - secp256k1_scalar_negate(&u1, &u1); - secp256k1_scalar_mul(&u2, &rn, sigs); - secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); - secp256k1_ge_set_gej_var(pubkey, &qj); - return !secp256k1_gej_is_infinity(&qj); -} - -int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int recid; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned char nonce32[32]; - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { - break; - } - } - count++; - } - memset(nonce32, 0, 32); - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - int recid; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ - secp256k1_scalar_set_b32(&m, msg32, NULL); - if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { - secp256k1_pubkey_save(pubkey, &q); - return 1; - } else { - memset(pubkey, 0, sizeof(*pubkey)); - return 0; - } -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h deleted file mode 100644 index 765c7dd81..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h +++ /dev/null @@ -1,393 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ -#define _SECP256K1_MODULE_RECOVERY_TESTS_ - -static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void) msg32; - (void) key32; - (void) algo16; - (void) data; - - /* On the first run, return 0 to force a second run */ - if (counter == 0) { - memset(nonce32, 0, 32); - return 1; - } - /* On the second run, return an overflow to force a third run */ - if (counter == 1) { - memset(nonce32, 0xff, 32); - return 1; - } - /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ - memset(nonce32, 1, 32); - return secp256k1_rand_bits(1); -} - -void test_ecdsa_recovery_api(void) { - /* Setup contexts that just count errors */ - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - secp256k1_ecdsa_signature normal_sig; - secp256k1_ecdsa_recoverable_signature recsig; - unsigned char privkey[32] = { 1 }; - unsigned char message[32] = { 2 }; - int32_t ecount = 0; - int recid = 0; - unsigned char sig[74]; - unsigned char zero_privkey[32] = { 0 }; - unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Check bad contexts and NULLs for signing */ - ecount = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); - CHECK(ecount == 5); - /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ - secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); - CHECK(ecount == 5); - /* These will all fail, but not in ARG_CHECK way */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); - /* This one will succeed. */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - CHECK(ecount == 5); - - /* Check signing with a goofy nonce function */ - - /* Check bad contexts and NULLs for recovery */ - ecount = 0; - CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); - CHECK(ecount == 5); - - /* Check NULLs for conversion */ - CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); - - /* Check NULLs for de/serialization */ - CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); - ecount = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); - CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); - CHECK(ecount == 7); - /* overflow in signature will fail but not affect ecount */ - memcpy(sig, over_privkey, 32); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); - CHECK(ecount == 7); - - /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); -} - -void test_ecdsa_recovery_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - secp256k1_ecdsa_signature signature[5]; - secp256k1_ecdsa_recoverable_signature rsignature[5]; - unsigned char sig[74]; - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - int recid = 0; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Serialize/parse compact and verify/recover. */ - extra[0] = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(memcmp(&signature[4], &signature[0], 64) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); - memset(&rsignature[4], 0, sizeof(rsignature[4])); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); - /* Parse compact (with recovery id) and recover. */ - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); - CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); - /* Serialize/destroy/parse signature and verify again. */ - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); - sig[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); - /* Recover again */ - CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || - memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); -} - -/* Tests several edge cases. */ -void test_ecdsa_recovery_edge_cases(void) { - const unsigned char msg32[32] = { - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', - 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', - 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', - 's', 's', 'a', 'g', 'e', '.', '.', '.' - }; - const unsigned char sig64[64] = { - /* Generated by signing the above message with nonce 'This is the nonce we will use...' - * and secret key 0 (which is not valid), resulting in recid 0. */ - 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, - 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, - 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, - 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, - 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, - 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, - 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, - 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 - }; - secp256k1_pubkey pubkey; - /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ - const unsigned char sigb64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - secp256k1_pubkey pubkeyb; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - int recid; - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); - CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); - - for (recid = 0; recid < 4; recid++) { - int i; - int recid2; - /* (4,4) encoded in DER. */ - unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; - unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; - unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; - unsigned char sigbderalt1[39] = { - 0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt2[39] = { - 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - unsigned char sigbderalt3[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt4[40] = { - 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - /* (order + r,4) encoded in DER. */ - unsigned char sigbderlong[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, - 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, - 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 - }; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); - for (recid2 = 0; recid2 < 4; recid2++) { - secp256k1_pubkey pubkey2b; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); - /* Verifying with (order + r,4) should always fail. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - } - /* DER parsing tests. */ - /* Zero length r/s. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); - /* Leading zeros. */ - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); - sigbderalt3[4] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - sigbderalt4[7] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - /* Damage signature. */ - sigbder[7]++; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - sigbder[7]--; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); - for(i = 0; i < 8; i++) { - int c; - unsigned char orig = sigbder[i]; - /*Try every single-byte change.*/ - for (c = 0; c < 256; c++) { - if (c == orig ) { - continue; - } - sigbder[i] = c; - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); - } - sigbder[i] = orig; - } - } - - /* Test r/s equal to zero */ - { - /* (1,1) encoded in DER. */ - unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; - unsigned char sigc64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - secp256k1_pubkey pubkeyc; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); - sigcder[4] = 0; - sigc64[31] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); - sigcder[4] = 1; - sigcder[7] = 0; - sigc64[31] = 1; - sigc64[63] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); - } -} - -void run_recovery_tests(void) { - int i; - for (i = 0; i < count; i++) { - test_ecdsa_recovery_api(); - } - for (i = 0; i < 64*count; i++) { - test_ecdsa_recovery_end_to_end(); - } - test_ecdsa_recovery_edge_cases(); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/num.h b/builder/crypto/secp256k1/libsecp256k1/src/num.h deleted file mode 100644 index eff842200..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/num.h +++ /dev/null @@ -1,74 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_ -#define _SECP256K1_NUM_ - -#ifndef USE_NUM_NONE - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_NUM_GMP) -#include "num_gmp.h" -#else -#error "Please select num implementation" -#endif - -/** Copy a number. */ -static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a); - -/** Convert a number's absolute value to a binary big-endian string. - * There must be enough place. */ -static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a); - -/** Set a number to the value of a binary big-endian string. */ -static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen); - -/** Compute a modular inverse. The input must be less than the modulus. */ -static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); - -/** Compute the jacobi symbol (a|b). b must be positive and odd. */ -static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); - -/** Compare the absolute value of two numbers. */ -static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); - -/** Test whether two number are equal (including sign). */ -static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b); - -/** Add two (signed) numbers. */ -static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Subtract two (signed) numbers. */ -static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Multiply two (signed) numbers. */ -static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); - -/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, - even if r was negative. */ -static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m); - -/** Right-shift the passed number by bits. */ -static void secp256k1_num_shift(secp256k1_num *r, int bits); - -/** Check whether a number is zero. */ -static int secp256k1_num_is_zero(const secp256k1_num *a); - -/** Check whether a number is one. */ -static int secp256k1_num_is_one(const secp256k1_num *a); - -/** Check whether a number is strictly negative. */ -static int secp256k1_num_is_neg(const secp256k1_num *a); - -/** Change a number's sign. */ -static void secp256k1_num_negate(secp256k1_num *r); - -#endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/num_gmp.h b/builder/crypto/secp256k1/libsecp256k1/src/num_gmp.h deleted file mode 100644 index 7dd813088..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/num_gmp.h +++ /dev/null @@ -1,20 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_REPR_ -#define _SECP256K1_NUM_REPR_ - -#include - -#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) - -typedef struct { - mp_limb_t data[2*NUM_LIMBS]; - int neg; - int limbs; -} secp256k1_num; - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h deleted file mode 100644 index 3a46495ee..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h +++ /dev/null @@ -1,288 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_REPR_IMPL_H_ -#define _SECP256K1_NUM_REPR_IMPL_H_ - -#include -#include -#include - -#include "util.h" -#include "num.h" - -#ifdef VERIFY -static void secp256k1_num_sanity(const secp256k1_num *a) { - VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); -} -#else -#define secp256k1_num_sanity(a) do { } while(0) -#endif - -static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { - *r = *a; -} - -static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { - unsigned char tmp[65]; - int len = 0; - int shift = 0; - if (a->limbs>1 || a->data[0] != 0) { - len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); - } - while (shift < len && tmp[shift] == 0) shift++; - VERIFY_CHECK(len-shift <= (int)rlen); - memset(r, 0, rlen - len + shift); - if (len > shift) { - memcpy(r + rlen - len + shift, tmp + shift, len - shift); - } - memset(tmp, 0, sizeof(tmp)); -} - -static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { - int len; - VERIFY_CHECK(alen > 0); - VERIFY_CHECK(alen <= 64); - len = mpn_set_str(r->data, a, alen, 256); - if (len == 0) { - r->data[0] = 0; - len = 1; - } - VERIFY_CHECK(len <= NUM_LIMBS*2); - r->limbs = len; - r->neg = 0; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); - r->limbs = a->limbs; - if (c != 0) { - VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); - r->data[r->limbs++] = c; - } -} - -static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); - (void)c; - VERIFY_CHECK(c == 0); - r->limbs = a->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { - secp256k1_num_sanity(r); - secp256k1_num_sanity(m); - - if (r->limbs >= m->limbs) { - mp_limb_t t[2*NUM_LIMBS]; - mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); - memset(t, 0, sizeof(t)); - r->limbs = m->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } - } - - if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { - secp256k1_num_sub_abs(r, m, r); - r->neg = 0; - } -} - -static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) { - int i; - mp_limb_t g[NUM_LIMBS+1]; - mp_limb_t u[NUM_LIMBS+1]; - mp_limb_t v[NUM_LIMBS+1]; - mp_size_t sn; - mp_size_t gn; - secp256k1_num_sanity(a); - secp256k1_num_sanity(m); - - /** mpn_gcdext computes: (G,S) = gcdext(U,V), where - * * G = gcd(U,V) - * * G = U*S + V*T - * * U has equal or more limbs than V, and V has no padding - * If we set U to be (a padded version of) a, and V = m: - * G = a*S + m*T - * G = a*S mod m - * Assuming G=1: - * S = 1/a mod m - */ - VERIFY_CHECK(m->limbs <= NUM_LIMBS); - VERIFY_CHECK(m->data[m->limbs-1] != 0); - for (i = 0; i < m->limbs; i++) { - u[i] = (i < a->limbs) ? a->data[i] : 0; - v[i] = m->data[i]; - } - sn = NUM_LIMBS+1; - gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); - (void)gn; - VERIFY_CHECK(gn == 1); - VERIFY_CHECK(g[0] == 1); - r->neg = a->neg ^ m->neg; - if (sn < 0) { - mpn_sub(r->data, m->data, m->limbs, r->data, -sn); - r->limbs = m->limbs; - while (r->limbs > 1 && r->data[r->limbs-1]==0) { - r->limbs--; - } - } else { - r->limbs = sn; - } - memset(g, 0, sizeof(g)); - memset(u, 0, sizeof(u)); - memset(v, 0, sizeof(v)); -} - -static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { - int ret; - mpz_t ga, gb; - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); - - mpz_inits(ga, gb, NULL); - - mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); - mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); - if (a->neg) { - mpz_neg(ga, ga); - } - - ret = mpz_jacobi(ga, gb); - - mpz_clears(ga, gb, NULL); - - return ret; -} - -static int secp256k1_num_is_one(const secp256k1_num *a) { - return (a->limbs == 1 && a->data[0] == 1); -} - -static int secp256k1_num_is_zero(const secp256k1_num *a) { - return (a->limbs == 1 && a->data[0] == 0); -} - -static int secp256k1_num_is_neg(const secp256k1_num *a) { - return (a->limbs > 1 || a->data[0] != 0) && a->neg; -} - -static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { - if (a->limbs > b->limbs) { - return 1; - } - if (a->limbs < b->limbs) { - return -1; - } - return mpn_cmp(a->data, b->data, a->limbs); -} - -static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { - if (a->limbs > b->limbs) { - return 0; - } - if (a->limbs < b->limbs) { - return 0; - } - if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) { - return 0; - } - return mpn_cmp(a->data, b->data, a->limbs) == 0; -} - -static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) { - if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ - r->neg = a->neg; - if (a->limbs >= b->limbs) { - secp256k1_num_add_abs(r, a, b); - } else { - secp256k1_num_add_abs(r, b, a); - } - } else { - if (secp256k1_num_cmp(a, b) > 0) { - r->neg = a->neg; - secp256k1_num_sub_abs(r, a, b); - } else { - r->neg = b->neg ^ bneg; - secp256k1_num_sub_abs(r, b, a); - } - } -} - -static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - secp256k1_num_subadd(r, a, b, 0); -} - -static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - secp256k1_num_subadd(r, a, b, 1); -} - -static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { - mp_limb_t tmp[2*NUM_LIMBS+1]; - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); - - VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); - if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { - r->limbs = 1; - r->neg = 0; - r->data[0] = 0; - return; - } - if (a->limbs >= b->limbs) { - mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); - } else { - mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); - } - r->limbs = a->limbs + b->limbs; - if (r->limbs > 1 && tmp[r->limbs - 1]==0) { - r->limbs--; - } - VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); - mpn_copyi(r->data, tmp, r->limbs); - r->neg = a->neg ^ b->neg; - memset(tmp, 0, sizeof(tmp)); -} - -static void secp256k1_num_shift(secp256k1_num *r, int bits) { - if (bits % GMP_NUMB_BITS) { - /* Shift within limbs. */ - mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); - } - if (bits >= GMP_NUMB_BITS) { - int i; - /* Shift full limbs. */ - for (i = 0; i < r->limbs; i++) { - int index = i + (bits / GMP_NUMB_BITS); - if (index < r->limbs && index < 2*NUM_LIMBS) { - r->data[i] = r->data[index]; - } else { - r->data[i] = 0; - } - } - } - while (r->limbs>1 && r->data[r->limbs-1]==0) { - r->limbs--; - } -} - -static void secp256k1_num_negate(secp256k1_num *r) { - r->neg ^= 1; -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/num_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/num_impl.h deleted file mode 100644 index 0b0e3a072..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/num_impl.h +++ /dev/null @@ -1,24 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_IMPL_H_ -#define _SECP256K1_NUM_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "num.h" - -#if defined(USE_NUM_GMP) -#include "num_gmp_impl.h" -#elif defined(USE_NUM_NONE) -/* Nothing. */ -#else -#error "Please select num implementation" -#endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar.h deleted file mode 100644 index 27e9d8375..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar.h +++ /dev/null @@ -1,106 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_ -#define _SECP256K1_SCALAR_ - -#include "num.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low.h" -#elif defined(USE_SCALAR_4X64) -#include "scalar_4x64.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32.h" -#else -#error "Please select scalar implementation" -#endif - -/** Clear a scalar to prevent the leak of sensitive data. */ -static void secp256k1_scalar_clear(secp256k1_scalar *r); - -/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ -static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Access bits from a scalar. Not constant time. */ -static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Set a scalar from a big endian byte array. */ -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); - -/** Set a scalar to an unsigned integer. */ -static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); - -/** Convert a scalar to a byte array. */ -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); - -/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); - -/** Multiply two scalars (modulo the group order). */ -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Shift a scalar right by some amount strictly between 0 and 16, returning - * the low bits that were shifted off */ -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); - -/** Compute the square of a scalar (modulo the group order). */ -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the inverse of a scalar (modulo the group order). */ -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the complement of a scalar (modulo the group order). */ -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Check whether a scalar equals zero. */ -static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); - -/** Check whether a scalar equals one. */ -static int secp256k1_scalar_is_one(const secp256k1_scalar *a); - -/** Check whether a scalar, considered as an nonnegative integer, is even. */ -static int secp256k1_scalar_is_even(const secp256k1_scalar *a); - -/** Check whether a scalar is higher than the group order divided by 2. */ -static int secp256k1_scalar_is_high(const secp256k1_scalar *a); - -/** Conditionally negate a number, in constant time. - * Returns -1 if the number was negated, 1 otherwise */ -static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); - -#ifndef USE_NUM_NONE -/** Convert a scalar to a number. */ -static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); - -/** Get the order of the group as a number. */ -static void secp256k1_scalar_order_get_num(secp256k1_num *r); -#endif - -/** Compare two scalars. */ -static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); - -#ifdef USE_ENDOMORPHISM -/** Find r1 and r2 such that r1+r2*2^128 = a. */ -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -#endif - -/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ -static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h deleted file mode 100644 index cff406038..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h +++ /dev/null @@ -1,19 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint64_t d[4]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h deleted file mode 100644 index 56e7bd82a..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h +++ /dev/null @@ -1,949 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) -#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) -#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) -#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) -#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) -#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) -#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); - return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK(count < 32); - VERIFY_CHECK(offset + count <= 256); - if ((offset + count - 1) >> 6 == offset >> 6) { - return secp256k1_scalar_get_bits(a, offset, count); - } else { - VERIFY_CHECK((offset >> 6) + 1 < 4); - return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ - no |= (a->d[2] < SECP256K1_N_2); - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1); - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { - uint128_t t; - VERIFY_CHECK(overflow <= 1); - t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint64_t)r->d[3]; - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - uint128_t t = (uint128_t)a->d[0] + b->d[0]; - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[1] + b->d[1]; - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[2] + b->d[2]; - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)a->d[3] + b->d[3]; - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - overflow = t + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - uint128_t t; - VERIFY_CHECK(bit < 256); - bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ - t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); - r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); - r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); - r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; - t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); - r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; -#ifdef VERIFY - VERIFY_CHECK((t >> 64) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; - r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; - r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; - r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; - bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; - bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; - bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); - uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; - r->d[0] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; - r->d[1] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; - r->d[2] = t & nonzero; t >>= 64; - t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; - r->d[3] = t & nonzero; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[3] < SECP256K1_N_H_3); - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - uint64_t mask = !flag - 1; - uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; - uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); - r->d[0] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); - r->d[1] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); - r->d[2] = t & nonzero; t >>= 64; - t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); - r->d[3] = t & nonzero; - return 2 * (mask == 0) - 1; -} - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint64_t tl, th; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint64_t tl, th; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd2(a,b) { \ - uint64_t tl, th, th2, tl2; \ - { \ - uint128_t t = (uint128_t)a * b; \ - th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = t; \ - } \ - th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ - c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ - tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ - th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ - c0 += tl2; /* overflow is handled on the next line */ \ - th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ - c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ - c1 += th2; /* overflow is handled on the next line */ \ - c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)) ? 1 : 0; \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { -#ifdef USE_ASM_X86_64 - /* Reduce 512 bits into 385. */ - uint64_t m0, m1, m2, m3, m4, m5, m6; - uint64_t p0, p1, p2, p3, p4; - uint64_t c; - - __asm__ __volatile__( - /* Preload. */ - "movq 32(%%rsi), %%r11\n" - "movq 40(%%rsi), %%r12\n" - "movq 48(%%rsi), %%r13\n" - "movq 56(%%rsi), %%r14\n" - /* Initialize r8,r9,r10 */ - "movq 0(%%rsi), %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += n0 * c0 */ - "movq %8, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract m0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += l1 */ - "addq 8(%%rsi), %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += n1 * c0 */ - "movq %8, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n0 * c1 */ - "movq %9, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract m1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += l2 */ - "addq 16(%%rsi), %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n2 * c0 */ - "movq %8, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n1 * c1 */ - "movq %9, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n0 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract m2 */ - "movq %%r10, %q2\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += l3 */ - "addq 24(%%rsi), %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n3 * c0 */ - "movq %8, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n2 * c1 */ - "movq %9, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n1 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* extract m3 */ - "movq %%r8, %q3\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += n3 * c1 */ - "movq %9, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n2 */ - "addq %%r13, %%r9\n" - "adcq $0, %%r10\n" - "adcq $0, %%r8\n" - /* extract m4 */ - "movq %%r9, %q4\n" - /* (r10,r8) += n3 */ - "addq %%r14, %%r10\n" - "adcq $0, %%r8\n" - /* extract m5 */ - "movq %%r10, %q5\n" - /* extract m6 */ - "movq %%r8, %q6\n" - : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) - : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); - - /* Reduce 385 bits into 258. */ - __asm__ __volatile__( - /* Preload */ - "movq %q9, %%r11\n" - "movq %q10, %%r12\n" - "movq %q11, %%r13\n" - /* Initialize (r8,r9,r10) */ - "movq %q5, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += m4 * c0 */ - "movq %12, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract p0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += m1 */ - "addq %q6, %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += m5 * c0 */ - "movq %12, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += m4 * c1 */ - "movq %13, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract p1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += m2 */ - "addq %q7, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m6 * c0 */ - "movq %12, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m5 * c1 */ - "movq %13, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m4 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract p2 */ - "movq %%r10, %q2\n" - /* (r8,r9) += m3 */ - "addq %q8, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += m6 * c1 */ - "movq %13, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* (r8,r9) += m5 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - /* extract p3 */ - "movq %%r8, %q3\n" - /* (r9) += m6 */ - "addq %%r13, %%r9\n" - /* extract p4 */ - "movq %%r9, %q4\n" - : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) - : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); - - /* Reduce 258 bits into 256. */ - __asm__ __volatile__( - /* Preload */ - "movq %q5, %%r10\n" - /* (rax,rdx) = p4 * c0 */ - "movq %7, %%rax\n" - "mulq %%r10\n" - /* (rax,rdx) += p0 */ - "addq %q1, %%rax\n" - "adcq $0, %%rdx\n" - /* extract r0 */ - "movq %%rax, 0(%q6)\n" - /* Move to (r8,r9) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p1 */ - "addq %q2, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += p4 * c1 */ - "movq %8, %%rax\n" - "mulq %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* Extract r1 */ - "movq %%r8, 8(%q6)\n" - "xorq %%r8, %%r8\n" - /* (r9,r8) += p4 */ - "addq %%r10, %%r9\n" - "adcq $0, %%r8\n" - /* (r9,r8) += p2 */ - "addq %q3, %%r9\n" - "adcq $0, %%r8\n" - /* Extract r2 */ - "movq %%r9, 16(%q6)\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p3 */ - "addq %q4, %%r8\n" - "adcq $0, %%r9\n" - /* Extract r3 */ - "movq %%r8, 24(%q6)\n" - /* Extract c */ - "movq %%r9, %q0\n" - : "=g"(c) - : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); -#else - uint128_t c; - uint64_t c0, c1, c2; - uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; - uint64_t m0, m1, m2, m3, m4, m5; - uint32_t m6; - uint64_t p0, p1, p2, p3; - uint32_t p4; - - /* Reduce 512 bits into 385. */ - /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - sumadd(n0); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - sumadd(n1); - extract(m3); - muladd(n3, SECP256K1_N_C_1); - sumadd(n2); - extract(m4); - sumadd_fast(n3); - extract_fast(m5); - VERIFY_CHECK(c0 <= 1); - m6 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m4, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m5, SECP256K1_N_C_0); - muladd(m4, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m6, SECP256K1_N_C_0); - muladd(m5, SECP256K1_N_C_1); - sumadd(m4); - extract(p2); - sumadd_fast(m3); - muladd_fast(m6, SECP256K1_N_C_1); - sumadd_fast(m5); - extract_fast(p3); - p4 = c0 + m6; - VERIFY_CHECK(p4 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ - c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; - r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; - r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p2 + (uint128_t)p4; - r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; - c += p3; - r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; -#endif - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { -#ifdef USE_ASM_X86_64 - const uint64_t *pb = b->d; - __asm__ __volatile__( - /* Preload */ - "movq 0(%%rdi), %%r15\n" - "movq 8(%%rdi), %%rbx\n" - "movq 16(%%rdi), %%rcx\n" - "movq 0(%%rdx), %%r11\n" - "movq 8(%%rdx), %%r12\n" - "movq 16(%%rdx), %%r13\n" - "movq 24(%%rdx), %%r14\n" - /* (rax,rdx) = a0 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - /* Extract l0 */ - "movq %%rax, 0(%%rsi)\n" - /* (r8,r9,r10) = (rdx) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a0 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a1 * b0 */ - "movq %%rbx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l1 */ - "movq %%r8, 8(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a0 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a1 * b1 */ - "movq %%rbx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a2 * b0 */ - "movq %%rcx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l2 */ - "movq %%r9, 16(%%rsi)\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += a0 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Preload a3 */ - "movq 24(%%rdi), %%r15\n" - /* (r10,r8,r9) += a1 * b2 */ - "movq %%rbx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a2 * b1 */ - "movq %%rcx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a3 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Extract l3 */ - "movq %%r10, 24(%%rsi)\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a1 * b3 */ - "movq %%rbx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a2 * b2 */ - "movq %%rcx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a3 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l4 */ - "movq %%r8, 32(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a2 * b3 */ - "movq %%rcx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a3 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l5 */ - "movq %%r9, 40(%%rsi)\n" - /* (r10,r8) += a3 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - /* Extract l6 */ - "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ - "movq %%r8, 56(%%rsi)\n" - : "+d"(pb) - : "S"(l), "D"(a->d) - : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); -#else - /* 160 bit accumulator. */ - uint64_t c0 = 0, c1 = 0; - uint32_t c2 = 0; - - /* l[0..7] = a[0..3] * b[0..3]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l[3]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - extract(l[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - extract(l[5]); - muladd_fast(a->d[3], b->d[3]); - extract_fast(l[6]); - VERIFY_CHECK(c1 == 0); - l[7] = c0; -#endif -} - -static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { -#ifdef USE_ASM_X86_64 - __asm__ __volatile__( - /* Preload */ - "movq 0(%%rdi), %%r11\n" - "movq 8(%%rdi), %%r12\n" - "movq 16(%%rdi), %%r13\n" - "movq 24(%%rdi), %%r14\n" - /* (rax,rdx) = a0 * a0 */ - "movq %%r11, %%rax\n" - "mulq %%r11\n" - /* Extract l0 */ - "movq %%rax, 0(%%rsi)\n" - /* (r8,r9,r10) = (rdx,0) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += 2 * a0 * a1 */ - "movq %%r11, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l1 */ - "movq %%r8, 8(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += 2 * a0 * a2 */ - "movq %%r11, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a1 * a1 */ - "movq %%r12, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l2 */ - "movq %%r9, 16(%%rsi)\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += 2 * a0 * a3 */ - "movq %%r11, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += 2 * a1 * a2 */ - "movq %%r12, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Extract l3 */ - "movq %%r10, 24(%%rsi)\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += 2 * a1 * a3 */ - "movq %%r12, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a2 * a2 */ - "movq %%r13, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l4 */ - "movq %%r8, 32(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += 2 * a2 * a3 */ - "movq %%r13, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l5 */ - "movq %%r9, 40(%%rsi)\n" - /* (r10,r8) += a3 * a3 */ - "movq %%r14, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - /* Extract l6 */ - "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ - "movq %%r8, 56(%%rsi)\n" - : - : "S"(l), "D"(a->d) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); -#else - /* 160 bit accumulator. */ - uint64_t c0 = 0, c1 = 0; - uint32_t c2 = 0; - - /* l[0..7] = a[0..3] * b[0..3]. */ - muladd_fast(a->d[0], a->d[0]); - extract_fast(l[0]); - muladd2(a->d[0], a->d[1]); - extract(l[1]); - muladd2(a->d[0], a->d[2]); - muladd(a->d[1], a->d[1]); - extract(l[2]); - muladd2(a->d[0], a->d[3]); - muladd2(a->d[1], a->d[2]); - extract(l[3]); - muladd2(a->d[1], a->d[3]); - muladd(a->d[2], a->d[2]); - extract(l[4]); - muladd2(a->d[2], a->d[3]); - extract(l[5]); - muladd_fast(a->d[3], a->d[3]); - extract_fast(l[6]); - VERIFY_CHECK(c1 == 0); - l[7] = c0; -#endif -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef muladd2 -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint64_t l[8]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = r->d[0] & ((1 << n) - 1); - r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); - r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); - r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); - r->d[3] = (r->d[3] >> n); - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint64_t l[8]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - r1->d[0] = a->d[0]; - r1->d[1] = a->d[1]; - r1->d[2] = 0; - r1->d[3] = 0; - r2->d[0] = a->d[2]; - r2->d[1] = a->d[3]; - r2->d[2] = 0; - r2->d[3] = 0; -} -#endif - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint64_t l[8]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - VERIFY_CHECK(shift >= 256); - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 6; - shiftlow = shift & 0x3F; - shifthigh = 64 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h deleted file mode 100644 index 1319664f6..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h +++ /dev/null @@ -1,19 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint32_t d[8]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h deleted file mode 100644 index aae4f35c0..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h +++ /dev/null @@ -1,721 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) -#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) -#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) -#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) -#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) -#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (~SECP256K1_N_2) -#define SECP256K1_N_C_3 (~SECP256K1_N_3) -#define SECP256K1_N_C_4 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) -#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) -#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) -#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) -#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); - return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - VERIFY_CHECK(count < 32); - VERIFY_CHECK(offset + count <= 256); - if ((offset + count - 1) >> 5 == offset >> 5) { - return secp256k1_scalar_get_bits(a, offset, count); - } else { - VERIFY_CHECK((offset >> 5) + 1 < 8); - return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ - no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_4); - yes |= (a->d[4] > SECP256K1_N_4) & ~no; - no |= (a->d[3] < SECP256K1_N_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_3) & ~no; - no |= (a->d[2] < SECP256K1_N_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { - uint64_t t; - VERIFY_CHECK(overflow <= 1); - t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; - r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; - r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; - r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; - r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; - r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[5]; - r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[6]; - r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[7]; - r->d[7] = t & 0xFFFFFFFFUL; - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - uint64_t t = (uint64_t)a->d[0] + b->d[0]; - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[1] + b->d[1]; - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[2] + b->d[2]; - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[3] + b->d[3]; - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[4] + b->d[4]; - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[5] + b->d[5]; - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[6] + b->d[6]; - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[7] + b->d[7]; - r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; - overflow = t + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - uint64_t t; - VERIFY_CHECK(bit < 256); - bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ - t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); - r->d[7] = t & 0xFFFFFFFFULL; -#ifdef VERIFY - VERIFY_CHECK((t >> 32) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; - r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; - r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; - r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; - r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; - r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; - r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; - r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; - bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; - bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; - bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; - bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; - bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; - bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; - bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); - uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; - r->d[7] = t & nonzero; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[7] < SECP256K1_N_H_7); - yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; - no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ - no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - uint32_t mask = !flag - 1; - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); - uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); - r->d[7] = t & nonzero; - return 2 * (mask == 0) - 1; -} - - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd2(a,b) { \ - uint32_t tl, th, th2, tl2; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ - c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ - tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ - th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ - c0 += tl2; /* overflow is handled on the next line */ \ - th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ - c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ - c1 += th2; /* overflow is handled on the next line */ \ - c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)) ? 1 : 0; \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { - uint64_t c; - uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; - uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; - uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; - - /* 96 bit accumulator. */ - uint32_t c0, c1, c2; - - /* Reduce 512 bits into 385. */ - /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - muladd(n0, SECP256K1_N_C_2); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - muladd(n1, SECP256K1_N_C_2); - muladd(n0, SECP256K1_N_C_3); - extract(m3); - sumadd(l[4]); - muladd(n4, SECP256K1_N_C_0); - muladd(n3, SECP256K1_N_C_1); - muladd(n2, SECP256K1_N_C_2); - muladd(n1, SECP256K1_N_C_3); - sumadd(n0); - extract(m4); - sumadd(l[5]); - muladd(n5, SECP256K1_N_C_0); - muladd(n4, SECP256K1_N_C_1); - muladd(n3, SECP256K1_N_C_2); - muladd(n2, SECP256K1_N_C_3); - sumadd(n1); - extract(m5); - sumadd(l[6]); - muladd(n6, SECP256K1_N_C_0); - muladd(n5, SECP256K1_N_C_1); - muladd(n4, SECP256K1_N_C_2); - muladd(n3, SECP256K1_N_C_3); - sumadd(n2); - extract(m6); - sumadd(l[7]); - muladd(n7, SECP256K1_N_C_0); - muladd(n6, SECP256K1_N_C_1); - muladd(n5, SECP256K1_N_C_2); - muladd(n4, SECP256K1_N_C_3); - sumadd(n3); - extract(m7); - muladd(n7, SECP256K1_N_C_1); - muladd(n6, SECP256K1_N_C_2); - muladd(n5, SECP256K1_N_C_3); - sumadd(n4); - extract(m8); - muladd(n7, SECP256K1_N_C_2); - muladd(n6, SECP256K1_N_C_3); - sumadd(n5); - extract(m9); - muladd(n7, SECP256K1_N_C_3); - sumadd(n6); - extract(m10); - sumadd_fast(n7); - extract_fast(m11); - VERIFY_CHECK(c0 <= 1); - m12 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m8, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m9, SECP256K1_N_C_0); - muladd(m8, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m10, SECP256K1_N_C_0); - muladd(m9, SECP256K1_N_C_1); - muladd(m8, SECP256K1_N_C_2); - extract(p2); - sumadd(m3); - muladd(m11, SECP256K1_N_C_0); - muladd(m10, SECP256K1_N_C_1); - muladd(m9, SECP256K1_N_C_2); - muladd(m8, SECP256K1_N_C_3); - extract(p3); - sumadd(m4); - muladd(m12, SECP256K1_N_C_0); - muladd(m11, SECP256K1_N_C_1); - muladd(m10, SECP256K1_N_C_2); - muladd(m9, SECP256K1_N_C_3); - sumadd(m8); - extract(p4); - sumadd(m5); - muladd(m12, SECP256K1_N_C_1); - muladd(m11, SECP256K1_N_C_2); - muladd(m10, SECP256K1_N_C_3); - sumadd(m9); - extract(p5); - sumadd(m6); - muladd(m12, SECP256K1_N_C_2); - muladd(m11, SECP256K1_N_C_3); - sumadd(m10); - extract(p6); - sumadd_fast(m7); - muladd_fast(m12, SECP256K1_N_C_3); - sumadd_fast(m11); - extract_fast(p7); - p8 = c0 + m12; - VERIFY_CHECK(p8 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ - c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; - r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; - c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; - r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; - c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; - r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; - c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; - r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; - c += p4 + (uint64_t)p8; - r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; - c += p5; - r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; - c += p6; - r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; - c += p7; - r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { - /* 96 bit accumulator. */ - uint32_t c0 = 0, c1 = 0, c2 = 0; - - /* l[0..15] = a[0..7] * b[0..7]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l[3]); - muladd(a->d[0], b->d[4]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - muladd(a->d[4], b->d[0]); - extract(l[4]); - muladd(a->d[0], b->d[5]); - muladd(a->d[1], b->d[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - muladd(a->d[4], b->d[1]); - muladd(a->d[5], b->d[0]); - extract(l[5]); - muladd(a->d[0], b->d[6]); - muladd(a->d[1], b->d[5]); - muladd(a->d[2], b->d[4]); - muladd(a->d[3], b->d[3]); - muladd(a->d[4], b->d[2]); - muladd(a->d[5], b->d[1]); - muladd(a->d[6], b->d[0]); - extract(l[6]); - muladd(a->d[0], b->d[7]); - muladd(a->d[1], b->d[6]); - muladd(a->d[2], b->d[5]); - muladd(a->d[3], b->d[4]); - muladd(a->d[4], b->d[3]); - muladd(a->d[5], b->d[2]); - muladd(a->d[6], b->d[1]); - muladd(a->d[7], b->d[0]); - extract(l[7]); - muladd(a->d[1], b->d[7]); - muladd(a->d[2], b->d[6]); - muladd(a->d[3], b->d[5]); - muladd(a->d[4], b->d[4]); - muladd(a->d[5], b->d[3]); - muladd(a->d[6], b->d[2]); - muladd(a->d[7], b->d[1]); - extract(l[8]); - muladd(a->d[2], b->d[7]); - muladd(a->d[3], b->d[6]); - muladd(a->d[4], b->d[5]); - muladd(a->d[5], b->d[4]); - muladd(a->d[6], b->d[3]); - muladd(a->d[7], b->d[2]); - extract(l[9]); - muladd(a->d[3], b->d[7]); - muladd(a->d[4], b->d[6]); - muladd(a->d[5], b->d[5]); - muladd(a->d[6], b->d[4]); - muladd(a->d[7], b->d[3]); - extract(l[10]); - muladd(a->d[4], b->d[7]); - muladd(a->d[5], b->d[6]); - muladd(a->d[6], b->d[5]); - muladd(a->d[7], b->d[4]); - extract(l[11]); - muladd(a->d[5], b->d[7]); - muladd(a->d[6], b->d[6]); - muladd(a->d[7], b->d[5]); - extract(l[12]); - muladd(a->d[6], b->d[7]); - muladd(a->d[7], b->d[6]); - extract(l[13]); - muladd_fast(a->d[7], b->d[7]); - extract_fast(l[14]); - VERIFY_CHECK(c1 == 0); - l[15] = c0; -} - -static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { - /* 96 bit accumulator. */ - uint32_t c0 = 0, c1 = 0, c2 = 0; - - /* l[0..15] = a[0..7]^2. */ - muladd_fast(a->d[0], a->d[0]); - extract_fast(l[0]); - muladd2(a->d[0], a->d[1]); - extract(l[1]); - muladd2(a->d[0], a->d[2]); - muladd(a->d[1], a->d[1]); - extract(l[2]); - muladd2(a->d[0], a->d[3]); - muladd2(a->d[1], a->d[2]); - extract(l[3]); - muladd2(a->d[0], a->d[4]); - muladd2(a->d[1], a->d[3]); - muladd(a->d[2], a->d[2]); - extract(l[4]); - muladd2(a->d[0], a->d[5]); - muladd2(a->d[1], a->d[4]); - muladd2(a->d[2], a->d[3]); - extract(l[5]); - muladd2(a->d[0], a->d[6]); - muladd2(a->d[1], a->d[5]); - muladd2(a->d[2], a->d[4]); - muladd(a->d[3], a->d[3]); - extract(l[6]); - muladd2(a->d[0], a->d[7]); - muladd2(a->d[1], a->d[6]); - muladd2(a->d[2], a->d[5]); - muladd2(a->d[3], a->d[4]); - extract(l[7]); - muladd2(a->d[1], a->d[7]); - muladd2(a->d[2], a->d[6]); - muladd2(a->d[3], a->d[5]); - muladd(a->d[4], a->d[4]); - extract(l[8]); - muladd2(a->d[2], a->d[7]); - muladd2(a->d[3], a->d[6]); - muladd2(a->d[4], a->d[5]); - extract(l[9]); - muladd2(a->d[3], a->d[7]); - muladd2(a->d[4], a->d[6]); - muladd(a->d[5], a->d[5]); - extract(l[10]); - muladd2(a->d[4], a->d[7]); - muladd2(a->d[5], a->d[6]); - extract(l[11]); - muladd2(a->d[5], a->d[7]); - muladd(a->d[6], a->d[6]); - extract(l[12]); - muladd2(a->d[6], a->d[7]); - extract(l[13]); - muladd_fast(a->d[7], a->d[7]); - extract_fast(l[14]); - VERIFY_CHECK(c1 == 0); - l[15] = c0; -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef muladd2 -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint32_t l[16]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = r->d[0] & ((1 << n) - 1); - r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); - r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); - r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n)); - r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n)); - r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n)); - r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); - r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); - r->d[7] = (r->d[7] >> n); - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint32_t l[16]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - r1->d[0] = a->d[0]; - r1->d[1] = a->d[1]; - r1->d[2] = a->d[2]; - r1->d[3] = a->d[3]; - r1->d[4] = 0; - r1->d[5] = 0; - r1->d[6] = 0; - r1->d[7] = 0; - r2->d[0] = a->d[4]; - r2->d[1] = a->d[5]; - r2->d[2] = a->d[6]; - r2->d[3] = a->d[7]; - r2->d[4] = 0; - r2->d[5] = 0; - r2->d[6] = 0; - r2->d[7] = 0; -} -#endif - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint32_t l[16]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - VERIFY_CHECK(shift >= 256); - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 5; - shiftlow = shift & 0x1F; - shifthigh = 32 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_impl.h deleted file mode 100644 index f5b237640..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_impl.h +++ /dev/null @@ -1,370 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_IMPL_H_ -#define _SECP256K1_SCALAR_IMPL_H_ - -#include "group.h" -#include "scalar.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low_impl.h" -#elif defined(USE_SCALAR_4X64) -#include "scalar_4x64_impl.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32_impl.h" -#else -#error "Please select scalar implementation" -#endif - -#ifndef USE_NUM_NONE -static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) { - unsigned char c[32]; - secp256k1_scalar_get_b32(c, a); - secp256k1_num_set_bin(r, c, 32); -} - -/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ -static void secp256k1_scalar_order_get_num(secp256k1_num *r) { -#if defined(EXHAUSTIVE_TEST_ORDER) - static const unsigned char order[32] = { - 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,EXHAUSTIVE_TEST_ORDER - }; -#else - static const unsigned char order[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; -#endif - secp256k1_num_set_bin(r, order, 32); -} -#endif - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { -#if defined(EXHAUSTIVE_TEST_ORDER) - int i; - *r = 0; - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) - if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) - *r = i; - /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus - * have a composite group order; fix it in exhaustive_tests.c). */ - VERIFY_CHECK(*r != 0); -} -#else - secp256k1_scalar *t; - int i; - /* First compute x ^ (2^N - 1) for some values of N. */ - secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; - - secp256k1_scalar_sqr(&x2, x); - secp256k1_scalar_mul(&x2, &x2, x); - - secp256k1_scalar_sqr(&x3, &x2); - secp256k1_scalar_mul(&x3, &x3, x); - - secp256k1_scalar_sqr(&x4, &x3); - secp256k1_scalar_mul(&x4, &x4, x); - - secp256k1_scalar_sqr(&x6, &x4); - secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &x2); - - secp256k1_scalar_sqr(&x7, &x6); - secp256k1_scalar_mul(&x7, &x7, x); - - secp256k1_scalar_sqr(&x8, &x7); - secp256k1_scalar_mul(&x8, &x8, x); - - secp256k1_scalar_sqr(&x15, &x8); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x15, &x15); - } - secp256k1_scalar_mul(&x15, &x15, &x7); - - secp256k1_scalar_sqr(&x30, &x15); - for (i = 0; i < 14; i++) { - secp256k1_scalar_sqr(&x30, &x30); - } - secp256k1_scalar_mul(&x30, &x30, &x15); - - secp256k1_scalar_sqr(&x60, &x30); - for (i = 0; i < 29; i++) { - secp256k1_scalar_sqr(&x60, &x60); - } - secp256k1_scalar_mul(&x60, &x60, &x30); - - secp256k1_scalar_sqr(&x120, &x60); - for (i = 0; i < 59; i++) { - secp256k1_scalar_sqr(&x120, &x120); - } - secp256k1_scalar_mul(&x120, &x120, &x60); - - secp256k1_scalar_sqr(&x127, &x120); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x127, &x127); - } - secp256k1_scalar_mul(&x127, &x127, &x7); - - /* Then accumulate the final result (t starts at x127). */ - t = &x127; - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 5; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 10; i++) { /* 0000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 9; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 6; i++) { /* 00000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(r, t, &x6); /* 111111 */ -} - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - return !(a->d[0] & 1); -} -#endif - -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { -#if defined(USE_SCALAR_INV_BUILTIN) - secp256k1_scalar_inverse(r, x); -#elif defined(USE_SCALAR_INV_NUM) - unsigned char b[32]; - secp256k1_num n, m; - secp256k1_scalar t = *x; - secp256k1_scalar_get_b32(b, &t); - secp256k1_num_set_bin(&n, b, 32); - secp256k1_scalar_order_get_num(&m); - secp256k1_num_mod_inverse(&n, &n, &m); - secp256k1_num_get_bin(b, 32, &n); - secp256k1_scalar_set_b32(r, b, NULL); - /* Verify that the inverse was computed correctly, without GMP code. */ - secp256k1_scalar_mul(&t, &t, r); - CHECK(secp256k1_scalar_is_one(&t)); -#else -#error "Please select scalar inverse implementation" -#endif -} - -#ifdef USE_ENDOMORPHISM -#if defined(EXHAUSTIVE_TEST_ORDER) -/** - * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the - * full case we don't bother making k1 and k2 be small, we just want them to be - * nontrivial to get full test coverage for the exhaustive tests. We therefore - * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. - */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; - *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; -} -#else -/** - * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where - * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, - * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} - * - * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm - * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 - * and k2 have a small size. - * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: - * - * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} - * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} - * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives - * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and - * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2. - * - * g1, g2 are precomputed constants used to replace division with a rounded multiplication - * when decomposing the scalar for an endomorphism-based point multiplication. - * - * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve - * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. - * - * The derivation is described in the paper "Efficient Software Implementation of Public-Key - * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), - * Section 4.3 (here we use a somewhat higher-precision estimate): - * d = a1*b2 - b1*a2 - * g1 = round((2^272)*b2/d) - * g2 = round((2^272)*b1/d) - * - * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found - * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). - * - * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). - */ - -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - secp256k1_scalar c1, c2; - static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST( - 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, - 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL - ); - static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, - 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL - ); - static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL - ); - static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, - 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL - ); - static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, - 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL - ); - VERIFY_CHECK(r1 != a); - VERIFY_CHECK(r2 != a); - /* these _var calls are constant time since the shift amount is constant */ - secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); - secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); - secp256k1_scalar_mul(&c1, &c1, &minus_b1); - secp256k1_scalar_mul(&c2, &c2, &minus_b2); - secp256k1_scalar_add(r2, &c1, &c2); - secp256k1_scalar_mul(r1, r2, &minus_lambda); - secp256k1_scalar_add(r1, r1, a); -} -#endif -#endif - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_low.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_low.h deleted file mode 100644 index 5574c44c7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_low.h +++ /dev/null @@ -1,15 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef uint32_t secp256k1_scalar; - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h deleted file mode 100644 index 4f94441f4..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h +++ /dev/null @@ -1,114 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ - -#include "scalar.h" - -#include - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - return !(*a & 1); -} - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - if (offset < 32) - return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); - else - return 0; -} - -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - return secp256k1_scalar_get_bits(a, offset, count); -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; - return *r < *b; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - if (flag && bit < 32) - *r += (1 << bit); -#ifdef VERIFY - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); -#endif -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; - int i; - *r = 0; - for (i = 0; i < 32; i++) { - *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; - } - /* just deny overflow, it basically always happens */ - if (overflow) *overflow = 0; -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - memset(bin, 0, 32); - bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - return *a == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - if (*a == 0) { - *r = 0; - } else { - *r = EXHAUSTIVE_TEST_ORDER - *a; - } -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - return *a == 1; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - return *a > EXHAUSTIVE_TEST_ORDER / 2; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - if (flag) secp256k1_scalar_negate(r, r); - return flag ? -1 : 1; -} - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; -} - -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { - int ret; - VERIFY_CHECK(n > 0); - VERIFY_CHECK(n < 16); - ret = *r & ((1 << n) - 1); - *r >>= n; - return ret; -} - -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { - *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - *r1 = *a; - *r2 = 0; -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - return *a == *b; -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/secp256k1.c b/builder/crypto/secp256k1/libsecp256k1/src/secp256k1.c deleted file mode 100755 index 7d637bfad..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/secp256k1.c +++ /dev/null @@ -1,559 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include "include/secp256k1.h" - -#include "util.h" -#include "num_impl.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_gen_impl.h" -#include "ecdsa_impl.h" -#include "eckey_impl.h" -#include "hash_impl.h" - -#define ARG_CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - secp256k1_callback_call(&ctx->illegal_callback, #cond); \ - return 0; \ - } \ -} while(0) - -static void default_illegal_callback_fn(const char* str, void* data) { - fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); - abort(); -} - -static const secp256k1_callback default_illegal_callback = { - default_illegal_callback_fn, - NULL -}; - -static void default_error_callback_fn(const char* str, void* data) { - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} - -static const secp256k1_callback default_error_callback = { - default_error_callback_fn, - NULL -}; - - -struct secp256k1_context_struct { - secp256k1_ecmult_context ecmult_ctx; - secp256k1_ecmult_gen_context ecmult_gen_ctx; - secp256k1_callback illegal_callback; - secp256k1_callback error_callback; -}; - -secp256k1_context* secp256k1_context_create(unsigned int flags) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = default_illegal_callback; - ret->error_callback = default_error_callback; - - if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { - secp256k1_callback_call(&ret->illegal_callback, - "Invalid flags"); - free(ret); - return NULL; - } - - secp256k1_ecmult_context_init(&ret->ecmult_ctx); - secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); - - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { - secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); - } - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { - secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); - } - - return ret; -} - -secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = ctx->illegal_callback; - ret->error_callback = ctx->error_callback; - secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); - secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); - return ret; -} - -void secp256k1_context_destroy(secp256k1_context* ctx) { - if (ctx != NULL) { - secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); - secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); - - free(ctx); - } -} - -void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_illegal_callback_fn; - } - ctx->illegal_callback.fn = fun; - ctx->illegal_callback.data = data; -} - -void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_error_callback_fn; - } - ctx->error_callback.fn = fun; - ctx->error_callback.data = data; -} - -static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { - if (sizeof(secp256k1_ge_storage) == 64) { - /* When the secp256k1_ge_storage type is exactly 64 byte, use its - * representation inside secp256k1_pubkey, as conversion is very fast. - * Note that secp256k1_pubkey_save must use the same representation. */ - secp256k1_ge_storage s; - memcpy(&s, &pubkey->data[0], 64); - secp256k1_ge_from_storage(ge, &s); - } else { - /* Otherwise, fall back to 32-byte big endian for X and Y. */ - secp256k1_fe x, y; - secp256k1_fe_set_b32(&x, pubkey->data); - secp256k1_fe_set_b32(&y, pubkey->data + 32); - secp256k1_ge_set_xy(ge, &x, &y); - } - ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); - return 1; -} - -static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { - if (sizeof(secp256k1_ge_storage) == 64) { - secp256k1_ge_storage s; - secp256k1_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, 64); - } else { - VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); - secp256k1_fe_normalize_var(&ge->x); - secp256k1_fe_normalize_var(&ge->y); - secp256k1_fe_get_b32(pubkey->data, &ge->x); - secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); - } -} - -int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { - secp256k1_ge Q; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(input != NULL); - if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { - return 0; - } - secp256k1_pubkey_save(pubkey, &Q); - secp256k1_ge_clear(&Q); - return 1; -} - -int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { - secp256k1_ge Q; - size_t len; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); - len = *outputlen; - *outputlen = 0; - ARG_CHECK(output != NULL); - memset(output, 0, len); - ARG_CHECK(pubkey != NULL); - ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); - if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); - if (ret) { - *outputlen = len; - } - } - return ret; -} - -static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } -} - -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } -} - -int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input != NULL); - - if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; - } else { - memset(sig, 0, sizeof(*sig)); - return 0; - } -} - -int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); -} - -int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { - secp256k1_scalar r, s; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); - ret = secp256k1_scalar_is_high(&s); - if (sigout != NULL) { - if (ret) { - secp256k1_scalar_negate(&s, &s); - } - secp256k1_ecdsa_signature_save(sigout, &r, &s); - } - - return ret; -} - -int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_scalar_set_b32(&m, msg32, NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return (!secp256k1_scalar_is_high(&s) && - secp256k1_pubkey_load(ctx, &q, pubkey) && - secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); -} - -static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - unsigned char keydata[112]; - int keylen = 64; - secp256k1_rfc6979_hmac_sha256_t rng; - unsigned int i; - /* We feed a byte array to the PRNG as input, consisting of: - * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. - * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. - * - optionally 16 extra bytes with the algorithm name. - * Because the arguments have distinct fixed lengths it is not possible for - * different argument mixtures to emulate each other and result in the same - * nonces. - */ - memcpy(keydata, key32, 32); - memcpy(keydata + 32, msg32, 32); - if (data != NULL) { - memcpy(keydata + 64, data, 32); - keylen = 96; - } - if (algo16 != NULL) { - memcpy(keydata + keylen, algo16, 16); - keylen += 16; - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); - memset(keydata, 0, sizeof(keydata)); - for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - return 1; -} - -const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; -const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; - -int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned char nonce32[32]; - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - if (!overflow && !secp256k1_scalar_is_zero(&non)) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { - break; - } - } - count++; - } - memset(nonce32, 0, 32); - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_signature_save(signature, &r, &s); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { - secp256k1_scalar sec; - int ret; - int overflow; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = !overflow && !secp256k1_scalar_is_zero(&sec); - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { - secp256k1_gej pj; - secp256k1_ge p; - secp256k1_scalar sec; - int overflow; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); - if (ret) { - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); - secp256k1_ge_set_gej(&p, &pj); - secp256k1_pubkey_save(pubkey, &p); - } - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar term; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - - ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&term); - return ret; -} - -int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar term; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar factor; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&factor); - return ret; -} - -int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar factor; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - return 1; -} - -int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { - size_t i; - secp256k1_gej Qj; - secp256k1_ge Q; - - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(n >= 1); - ARG_CHECK(pubnonces != NULL); - - secp256k1_gej_set_infinity(&Qj); - - for (i = 0; i < n; i++) { - secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); - secp256k1_gej_add_ge(&Qj, &Qj, &Q); - } - if (secp256k1_gej_is_infinity(&Qj)) { - return 0; - } - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(pubnonce, &Q); - return 1; -} - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/main_impl.h" -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/testrand.h b/builder/crypto/secp256k1/libsecp256k1/src/testrand.h deleted file mode 100644 index f8efa93c7..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/testrand.h +++ /dev/null @@ -1,38 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_TESTRAND_H_ -#define _SECP256K1_TESTRAND_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -/* A non-cryptographic RNG used only for test infrastructure. */ - -/** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16); - -/** Generate a pseudorandom number in the range [0..2**32-1]. */ -static uint32_t secp256k1_rand32(void); - -/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or - * more. */ -static uint32_t secp256k1_rand_bits(int bits); - -/** Generate a pseudorandom number in the range [0..range-1]. */ -static uint32_t secp256k1_rand_int(uint32_t range); - -/** Generate a pseudorandom 32-byte array. */ -static void secp256k1_rand256(unsigned char *b32); - -/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ -static void secp256k1_rand256_test(unsigned char *b32); - -/** Generate pseudorandom bytes with long sequences of zero and one bits. */ -static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/testrand_impl.h b/builder/crypto/secp256k1/libsecp256k1/src/testrand_impl.h deleted file mode 100644 index 15c7b9f12..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/testrand_impl.h +++ /dev/null @@ -1,110 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_TESTRAND_IMPL_H_ -#define _SECP256K1_TESTRAND_IMPL_H_ - -#include -#include - -#include "testrand.h" -#include "hash.h" - -static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; -static uint32_t secp256k1_test_rng_precomputed[8]; -static int secp256k1_test_rng_precomputed_used = 8; -static uint64_t secp256k1_test_rng_integer; -static int secp256k1_test_rng_integer_bits_left = 0; - -SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) { - secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); -} - -SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { - if (secp256k1_test_rng_precomputed_used == 8) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); - secp256k1_test_rng_precomputed_used = 0; - } - return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; -} - -static uint32_t secp256k1_rand_bits(int bits) { - uint32_t ret; - if (secp256k1_test_rng_integer_bits_left < bits) { - secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left); - secp256k1_test_rng_integer_bits_left += 32; - } - ret = secp256k1_test_rng_integer; - secp256k1_test_rng_integer >>= bits; - secp256k1_test_rng_integer_bits_left -= bits; - ret &= ((~((uint32_t)0)) >> (32 - bits)); - return ret; -} - -static uint32_t secp256k1_rand_int(uint32_t range) { - /* We want a uniform integer between 0 and range-1, inclusive. - * B is the smallest number such that range <= 2**B. - * two mechanisms implemented here: - * - generate B bits numbers until one below range is found, and return it - * - find the largest multiple M of range that is <= 2**(B+A), generate B+A - * bits numbers until one below M is found, and return it modulo range - * The second mechanism consumes A more bits of entropy in every iteration, - * but may need fewer iterations due to M being closer to 2**(B+A) then - * range is to 2**B. The array below (indexed by B) contains a 0 when the - * first mechanism is to be used, and the number A otherwise. - */ - static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0}; - uint32_t trange, mult; - int bits = 0; - if (range <= 1) { - return 0; - } - trange = range - 1; - while (trange > 0) { - trange >>= 1; - bits++; - } - if (addbits[bits]) { - bits = bits + addbits[bits]; - mult = ((~((uint32_t)0)) >> (32 - bits)) / range; - trange = range * mult; - } else { - trange = range; - mult = 1; - } - while(1) { - uint32_t x = secp256k1_rand_bits(bits); - if (x < trange) { - return (mult == 1) ? x : (x % range); - } - } -} - -static void secp256k1_rand256(unsigned char *b32) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); -} - -static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) { - size_t bits = 0; - memset(bytes, 0, len); - while (bits < len * 8) { - int now; - uint32_t val; - now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31; - val = secp256k1_rand_bits(1); - while (now > 0 && bits < len * 8) { - bytes[bits / 8] |= val << (bits % 8); - now--; - bits++; - } - } -} - -static void secp256k1_rand256_test(unsigned char *b32) { - secp256k1_rand_bytes_test(b32, 32); -} - -#endif diff --git a/builder/crypto/secp256k1/libsecp256k1/src/tests.c b/builder/crypto/secp256k1/libsecp256k1/src/tests.c deleted file mode 100644 index 9ae7d3028..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/tests.c +++ /dev/null @@ -1,4525 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include - -#include - -#include "secp256k1.c" -#include "include/secp256k1.h" -#include "testrand_impl.h" - -#ifdef ENABLE_OPENSSL_TESTS -#include "openssl/bn.h" -#include "openssl/ec.h" -#include "openssl/ecdsa.h" -#include "openssl/obj_mac.h" -#endif - -#include "contrib/lax_der_parsing.c" -#include "contrib/lax_der_privatekey_parsing.c" - -#if !defined(VG_CHECK) -# if defined(VALGRIND) -# include -# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y)) -# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y)) -# else -# define VG_UNDEF(x,y) -# define VG_CHECK(x,y) -# endif -#endif - -static int count = 64; -static secp256k1_context *ctx = NULL; - -static void counting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts. */ - int32_t *p; - (void)str; - p = data; - (*p)++; -} - -static void uncounting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts (backwards). */ - int32_t *p; - (void)str; - p = data; - (*p)--; -} - -void random_field_element_test(secp256k1_fe *fe) { - do { - unsigned char b32[32]; - secp256k1_rand256_test(b32); - if (secp256k1_fe_set_b32(fe, b32)) { - break; - } - } while(1); -} - -void random_field_element_magnitude(secp256k1_fe *fe) { - secp256k1_fe zero; - int n = secp256k1_rand_int(9); - secp256k1_fe_normalize(fe); - if (n == 0) { - return; - } - secp256k1_fe_clear(&zero); - secp256k1_fe_negate(&zero, &zero, 0); - secp256k1_fe_mul_int(&zero, n - 1); - secp256k1_fe_add(fe, &zero); - VERIFY_CHECK(fe->magnitude == n); -} - -void random_group_element_test(secp256k1_ge *ge) { - secp256k1_fe fe; - do { - random_field_element_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { - secp256k1_fe_normalize(&ge->y); - break; - } - } while(1); -} - -void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; - do { - random_field_element_test(&gej->z); - if (!secp256k1_fe_is_zero(&gej->z)) { - break; - } - } while(1); - secp256k1_fe_sqr(&z2, &gej->z); - secp256k1_fe_mul(&z3, &z2, &gej->z); - secp256k1_fe_mul(&gej->x, &ge->x, &z2); - secp256k1_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; -} - -void random_scalar_order_test(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_rand256_test(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -void random_scalar_order(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_rand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -void run_context_tests(void) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - unsigned char ctmp[32]; - int32_t ecount; - int32_t ecount2; - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar msg, key, nonce; - secp256k1_scalar sigr, sigs; - - ecount = 0; - ecount2 = 10; - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); - CHECK(vrfy->error_callback.fn != sign->error_callback.fn); - - /*** clone and destroy all of them to make sure cloning was complete ***/ - { - secp256k1_context *ctx_tmp; - - ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); - } - - /* Verify that the error callback makes it across the clone. */ - CHECK(vrfy->error_callback.fn != sign->error_callback.fn); - /* And that it resets back to default. */ - secp256k1_context_set_error_callback(sign, NULL, NULL); - CHECK(vrfy->error_callback.fn == sign->error_callback.fn); - - /*** attempt to use them ***/ - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - - /* Verify context-type checking illegal-argument errors. */ - memset(ctmp, 1, 32); - CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); - CHECK(ecount == 1); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); - CHECK(ecount == 2); - VG_UNDEF(&sig, sizeof(sig)); - CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); - VG_CHECK(&sig, sizeof(sig)); - CHECK(ecount2 == 10); - CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); - CHECK(ecount2 == 11); - CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); - CHECK(ecount2 == 12); - CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); - CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); - CHECK(ecount == 2); - CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 13); - secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); - secp256k1_context_set_illegal_callback(sign, NULL, NULL); - - /* This shouldn't leak memory, due to already-set tests. */ - secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); - secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); - - /* obtain a working nonce */ - do { - random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try signing */ - CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try verifying */ - CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - - /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); - /* Defined as no-op. */ - secp256k1_context_destroy(NULL); -} - -/***** HASH TESTS *****/ - -void run_sha256_tests(void) { - static const char *inputs[8] = { - "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "For this sample, this 63-byte string will be used as input data", - "This is exactly 64 bytes long, not counting the terminating byte" - }; - static const unsigned char outputs[8][32] = { - {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, - {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, - {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, - {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, - {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, - {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, - {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, - {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} - }; - int i; - for (i = 0; i < 8; i++) { - unsigned char out[32]; - secp256k1_sha256_t hasher; - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - } - } -} - -void run_hmac_sha256_tests(void) { - static const char *keys[6] = { - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - "\x4a\x65\x66\x65", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - }; - static const char *inputs[6] = { - "\x48\x69\x20\x54\x68\x65\x72\x65", - "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", - "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" - }; - static const unsigned char outputs[6][32] = { - {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, - {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, - {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, - {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, - {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, - {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} - }; - int i; - for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256_t hasher; - unsigned char out[32]; - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(memcmp(out, outputs[i], 32) == 0); - } - } -} - -void run_rfc6979_hmac_sha256_tests(void) { - static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; - static const unsigned char out1[3][32] = { - {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, - {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, - {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} - }; - - static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; - static const unsigned char out2[3][32] = { - {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, - {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, - {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} - }; - - secp256k1_rfc6979_hmac_sha256_t rng; - unsigned char out[32]; - int i; - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out1[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out1[i], 32) != 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(memcmp(out, out2[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); -} - -/***** RANDOM TESTS *****/ - -void test_rand_bits(int rand32, int bits) { - /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to - * get a false negative chance below once in a billion */ - static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316}; - /* We try multiplying the results with various odd numbers, which shouldn't - * influence the uniform distribution modulo a power of 2. */ - static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011}; - /* We only select up to 6 bits from the output to analyse */ - unsigned int usebits = bits > 6 ? 6 : bits; - unsigned int maxshift = bits - usebits; - /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit - number, track all observed outcomes, one per bit in a uint64_t. */ - uint64_t x[6][27] = {{0}}; - unsigned int i, shift, m; - /* Multiply the output of all rand calls with the odd number m, which - should not change the uniformity of its distribution. */ - for (i = 0; i < rounds[usebits]; i++) { - uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); - CHECK((((uint64_t)r) >> bits) == 0); - for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { - uint32_t rm = r * mults[m]; - for (shift = 0; shift <= maxshift; shift++) { - x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1))); - } - } - } - for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { - for (shift = 0; shift <= maxshift; shift++) { - /* Test that the lower usebits bits of x[shift] are 1 */ - CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0); - } - } -} - -/* Subrange must be a whole divisor of range, and at most 64 */ -void test_rand_int(uint32_t range, uint32_t subrange) { - /* (1-1/subrange)^rounds < 1/10^9 */ - int rounds = (subrange * 2073) / 100; - int i; - uint64_t x = 0; - CHECK((range % subrange) == 0); - for (i = 0; i < rounds; i++) { - uint32_t r = secp256k1_rand_int(range); - CHECK(r < range); - r = r % subrange; - x |= (((uint64_t)1) << r); - } - /* Test that the lower subrange bits of x are 1. */ - CHECK(((~x) << (64 - subrange)) == 0); -} - -void run_rand_bits(void) { - size_t b; - test_rand_bits(1, 32); - for (b = 1; b <= 32; b++) { - test_rand_bits(0, b); - } -} - -void run_rand_int(void) { - static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432}; - static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64}; - unsigned int m, s; - for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) { - for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) { - test_rand_int(ms[m] * ss[s], ss[s]); - } - } -} - -/***** NUM TESTS *****/ - -#ifndef USE_NUM_NONE -void random_num_negate(secp256k1_num *num) { - if (secp256k1_rand_bits(1)) { - secp256k1_num_negate(num); - } -} - -void random_num_order_test(secp256k1_num *num) { - secp256k1_scalar sc; - random_scalar_order_test(&sc); - secp256k1_scalar_get_num(num, &sc); -} - -void random_num_order(secp256k1_num *num) { - secp256k1_scalar sc; - random_scalar_order(&sc); - secp256k1_scalar_get_num(num, &sc); -} - -void test_num_negate(void) { - secp256k1_num n1; - secp256k1_num n2; - random_num_order_test(&n1); /* n1 = R */ - random_num_negate(&n1); - secp256k1_num_copy(&n2, &n1); /* n2 = R */ - secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ - CHECK(secp256k1_num_is_zero(&n1)); - secp256k1_num_copy(&n1, &n2); /* n1 = R */ - secp256k1_num_negate(&n1); /* n1 = -R */ - CHECK(!secp256k1_num_is_zero(&n1)); - secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ - CHECK(secp256k1_num_is_zero(&n1)); - secp256k1_num_copy(&n1, &n2); /* n1 = R */ - secp256k1_num_negate(&n1); /* n1 = -R */ - CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); - secp256k1_num_negate(&n1); /* n1 = R */ - CHECK(secp256k1_num_eq(&n1, &n2)); -} - -void test_num_add_sub(void) { - int i; - secp256k1_scalar s; - secp256k1_num n1; - secp256k1_num n2; - secp256k1_num n1p2, n2p1, n1m2, n2m1; - random_num_order_test(&n1); /* n1 = R1 */ - if (secp256k1_rand_bits(1)) { - random_num_negate(&n1); - } - random_num_order_test(&n2); /* n2 = R2 */ - if (secp256k1_rand_bits(1)) { - random_num_negate(&n2); - } - secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ - secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ - secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ - secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ - CHECK(secp256k1_num_eq(&n1p2, &n2p1)); - CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); - secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1m2)); - CHECK(!secp256k1_num_eq(&n2m1, &n1)); - secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1)); - CHECK(!secp256k1_num_eq(&n2p1, &n1)); - secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ - CHECK(secp256k1_num_eq(&n2p1, &n1)); - - /* check is_one */ - secp256k1_scalar_set_int(&s, 1); - secp256k1_scalar_get_num(&n1, &s); - CHECK(secp256k1_num_is_one(&n1)); - /* check that 2^n + 1 is never 1 */ - secp256k1_scalar_get_num(&n2, &s); - for (i = 0; i < 250; ++i) { - secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ - secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ - CHECK(!secp256k1_num_is_one(&n1p2)); - } -} - -void test_num_mod(void) { - int i; - secp256k1_scalar s; - secp256k1_num order, n; - - /* check that 0 mod anything is 0 */ - random_scalar_order_test(&s); - secp256k1_scalar_get_num(&order, &s); - secp256k1_scalar_set_int(&s, 0); - secp256k1_scalar_get_num(&n, &s); - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); - - /* check that anything mod 1 is 0 */ - secp256k1_scalar_set_int(&s, 1); - secp256k1_scalar_get_num(&order, &s); - secp256k1_scalar_get_num(&n, &s); - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); - - /* check that increasing the number past 2^256 does not break this */ - random_scalar_order_test(&s); - secp256k1_scalar_get_num(&n, &s); - /* multiply by 2^8, which'll test this case with high probability */ - for (i = 0; i < 8; ++i) { - secp256k1_num_add(&n, &n, &n); - } - secp256k1_num_mod(&n, &order); - CHECK(secp256k1_num_is_zero(&n)); -} - -void test_num_jacobi(void) { - secp256k1_scalar sqr; - secp256k1_scalar small; - secp256k1_scalar five; /* five is not a quadratic residue */ - secp256k1_num order, n; - int i; - /* squares mod 5 are 1, 4 */ - const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; - - /* check some small values with 5 as the order */ - secp256k1_scalar_set_int(&five, 5); - secp256k1_scalar_get_num(&order, &five); - for (i = 0; i < 10; ++i) { - secp256k1_scalar_set_int(&small, i); - secp256k1_scalar_get_num(&n, &small); - CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); - } - - /** test large values with 5 as group order */ - secp256k1_scalar_get_num(&order, &five); - /* we first need a scalar which is not a multiple of 5 */ - do { - secp256k1_num fiven; - random_scalar_order_test(&sqr); - secp256k1_scalar_get_num(&fiven, &five); - secp256k1_scalar_get_num(&n, &sqr); - secp256k1_num_mod(&n, &fiven); - } while (secp256k1_num_is_zero(&n)); - /* next force it to be a residue. 2 is a nonresidue mod 5 so we can - * just multiply by two, i.e. add the number to itself */ - if (secp256k1_num_jacobi(&n, &order) == -1) { - secp256k1_num_add(&n, &n, &n); - } - - /* test residue */ - CHECK(secp256k1_num_jacobi(&n, &order) == 1); - /* test nonresidue */ - secp256k1_num_add(&n, &n, &n); - CHECK(secp256k1_num_jacobi(&n, &order) == -1); - - /** test with secp group order as order */ - secp256k1_scalar_order_get_num(&order); - random_scalar_order_test(&sqr); - secp256k1_scalar_sqr(&sqr, &sqr); - /* test residue */ - secp256k1_scalar_get_num(&n, &sqr); - CHECK(secp256k1_num_jacobi(&n, &order) == 1); - /* test nonresidue */ - secp256k1_scalar_mul(&sqr, &sqr, &five); - secp256k1_scalar_get_num(&n, &sqr); - CHECK(secp256k1_num_jacobi(&n, &order) == -1); - /* test multiple of the order*/ - CHECK(secp256k1_num_jacobi(&order, &order) == 0); - - /* check one less than the order */ - secp256k1_scalar_set_int(&small, 1); - secp256k1_scalar_get_num(&n, &small); - secp256k1_num_sub(&n, &order, &n); - CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ -} - -void run_num_smalltests(void) { - int i; - for (i = 0; i < 100*count; i++) { - test_num_negate(); - test_num_add_sub(); - test_num_mod(); - test_num_jacobi(); - } -} -#endif - -/***** SCALAR TESTS *****/ - -void scalar_test(void) { - secp256k1_scalar s; - secp256k1_scalar s1; - secp256k1_scalar s2; -#ifndef USE_NUM_NONE - secp256k1_num snum, s1num, s2num; - secp256k1_num order, half_order; -#endif - unsigned char c[32]; - - /* Set 's' to a random scalar, with value 'snum'. */ - random_scalar_order_test(&s); - - /* Set 's1' to a random scalar, with value 's1num'. */ - random_scalar_order_test(&s1); - - /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ - random_scalar_order_test(&s2); - secp256k1_scalar_get_b32(c, &s2); - -#ifndef USE_NUM_NONE - secp256k1_scalar_get_num(&snum, &s); - secp256k1_scalar_get_num(&s1num, &s1); - secp256k1_scalar_get_num(&s2num, &s2); - - secp256k1_scalar_order_get_num(&order); - half_order = order; - secp256k1_num_shift(&half_order, 1); -#endif - - { - int i; - /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - secp256k1_scalar_set_int(&n, 0); - for (i = 0; i < 256; i += 4) { - secp256k1_scalar t; - int j; - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); - for (j = 0; j < 4; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - - { - /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - int i = 0; - secp256k1_scalar_set_int(&n, 0); - while (i < 256) { - secp256k1_scalar t; - int j; - int now = secp256k1_rand_int(15) + 1; - if (now + i > 256) { - now = 256 - i; - } - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); - for (j = 0; j < now; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - i += now; - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - -#ifndef USE_NUM_NONE - { - /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ - secp256k1_num rnum; - secp256k1_num r2num; - secp256k1_scalar r; - secp256k1_num_add(&rnum, &snum, &s2num); - secp256k1_num_mod(&rnum, &order); - secp256k1_scalar_add(&r, &s, &s2); - secp256k1_scalar_get_num(&r2num, &r); - CHECK(secp256k1_num_eq(&rnum, &r2num)); - } - - { - /* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */ - secp256k1_scalar r; - secp256k1_num r2num; - secp256k1_num rnum; - secp256k1_num_mul(&rnum, &snum, &s2num); - secp256k1_num_mod(&rnum, &order); - secp256k1_scalar_mul(&r, &s, &s2); - secp256k1_scalar_get_num(&r2num, &r); - CHECK(secp256k1_num_eq(&rnum, &r2num)); - /* The result can only be zero if at least one of the factors was zero. */ - CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); - /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ - CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); - CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); - } - - { - secp256k1_scalar neg; - secp256k1_num negnum; - secp256k1_num negnum2; - /* Check that comparison with zero matches comparison with zero on the number. */ - CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); - /* Check that comparison with the half order is equal to testing for high scalar. */ - CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0)); - secp256k1_scalar_negate(&neg, &s); - secp256k1_num_sub(&negnum, &order, &snum); - secp256k1_num_mod(&negnum, &order); - /* Check that comparison with the half order is equal to testing for high scalar after negation. */ - CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0)); - /* Negating should change the high property, unless the value was already zero. */ - CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); - secp256k1_scalar_get_num(&negnum2, &neg); - /* Negating a scalar should be equal to (order - n) mod order on the number. */ - CHECK(secp256k1_num_eq(&negnum, &negnum2)); - secp256k1_scalar_add(&neg, &neg, &s); - /* Adding a number to its negation should result in zero. */ - CHECK(secp256k1_scalar_is_zero(&neg)); - secp256k1_scalar_negate(&neg, &neg); - /* Negating zero should still result in zero. */ - CHECK(secp256k1_scalar_is_zero(&neg)); - } - - { - /* Test secp256k1_scalar_mul_shift_var. */ - secp256k1_scalar r; - secp256k1_num one; - secp256k1_num rnum; - secp256k1_num rnum2; - unsigned char cone[1] = {0x01}; - unsigned int shift = 256 + secp256k1_rand_int(257); - secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); - secp256k1_num_mul(&rnum, &s1num, &s2num); - secp256k1_num_shift(&rnum, shift - 1); - secp256k1_num_set_bin(&one, cone, 1); - secp256k1_num_add(&rnum, &rnum, &one); - secp256k1_num_shift(&rnum, 1); - secp256k1_scalar_get_num(&rnum2, &r); - CHECK(secp256k1_num_eq(&rnum, &rnum2)); - } - - { - /* test secp256k1_scalar_shr_int */ - secp256k1_scalar r; - int i; - random_scalar_order_test(&r); - for (i = 0; i < 100; ++i) { - int low; - int shift = 1 + secp256k1_rand_int(15); - int expected = r.d[0] % (1 << shift); - low = secp256k1_scalar_shr_int(&r, shift); - CHECK(expected == low); - } - } -#endif - - { - /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ - if (!secp256k1_scalar_is_zero(&s)) { - secp256k1_scalar inv; -#ifndef USE_NUM_NONE - secp256k1_num invnum; - secp256k1_num invnum2; -#endif - secp256k1_scalar_inverse(&inv, &s); -#ifndef USE_NUM_NONE - secp256k1_num_mod_inverse(&invnum, &snum, &order); - secp256k1_scalar_get_num(&invnum2, &inv); - CHECK(secp256k1_num_eq(&invnum, &invnum2)); -#endif - secp256k1_scalar_mul(&inv, &inv, &s); - /* Multiplying a scalar with its inverse must result in one. */ - CHECK(secp256k1_scalar_is_one(&inv)); - secp256k1_scalar_inverse(&inv, &inv); - /* Inverting one must result in one. */ - CHECK(secp256k1_scalar_is_one(&inv)); -#ifndef USE_NUM_NONE - secp256k1_scalar_get_num(&invnum, &inv); - CHECK(secp256k1_num_is_one(&invnum)); -#endif - } - } - - { - /* Test commutativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - secp256k1_scalar r1, r2; - secp256k1_scalar b; - int i; - /* Test add_bit. */ - int bit = secp256k1_rand_bits(8); - secp256k1_scalar_set_int(&b, 1); - CHECK(secp256k1_scalar_is_one(&b)); - for (i = 0; i < bit; i++) { - secp256k1_scalar_add(&b, &b, &b); - } - r1 = s1; - r2 = s1; - if (!secp256k1_scalar_add(&r1, &r1, &b)) { - /* No overflow happened. */ - secp256k1_scalar_cadd_bit(&r2, bit, 1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - /* cadd is a noop when flag is zero */ - secp256k1_scalar_cadd_bit(&r2, bit, 0); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - } - - { - /* Test commutativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r1, &r1, &s); - secp256k1_scalar_add(&r2, &s2, &s); - secp256k1_scalar_add(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s2, &s); - secp256k1_scalar_mul(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test distributitivity of mul over add. */ - secp256k1_scalar r1, r2, t; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s1, &s); - secp256k1_scalar_mul(&t, &s2, &s); - secp256k1_scalar_add(&r2, &r2, &t); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test square. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_sqr(&r1, &s1); - secp256k1_scalar_mul(&r2, &s1, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test multiplicative identity. */ - secp256k1_scalar r1, v1; - secp256k1_scalar_set_int(&v1,1); - secp256k1_scalar_mul(&r1, &s1, &v1); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test additive identity. */ - secp256k1_scalar r1, v0; - secp256k1_scalar_set_int(&v0,0); - secp256k1_scalar_add(&r1, &s1, &v0); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test zero product property. */ - secp256k1_scalar r1, v0; - secp256k1_scalar_set_int(&v0,0); - secp256k1_scalar_mul(&r1, &s1, &v0); - CHECK(secp256k1_scalar_eq(&r1, &v0)); - } - -} - -void run_scalar_tests(void) { - int i; - for (i = 0; i < 128 * count; i++) { - scalar_test(); - } - - { - /* (-1)+1 should be zero. */ - secp256k1_scalar s, o; - secp256k1_scalar_set_int(&s, 1); - CHECK(secp256k1_scalar_is_one(&s)); - secp256k1_scalar_negate(&o, &s); - secp256k1_scalar_add(&o, &o, &s); - CHECK(secp256k1_scalar_is_zero(&o)); - secp256k1_scalar_negate(&o, &o); - CHECK(secp256k1_scalar_is_zero(&o)); - } - -#ifndef USE_NUM_NONE - { - /* A scalar with value of the curve order should be 0. */ - secp256k1_num order; - secp256k1_scalar zero; - unsigned char bin[32]; - int overflow = 0; - secp256k1_scalar_order_get_num(&order); - secp256k1_num_get_bin(bin, 32, &order); - secp256k1_scalar_set_b32(&zero, bin, &overflow); - CHECK(overflow == 1); - CHECK(secp256k1_scalar_is_zero(&zero)); - } -#endif - - { - /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); - } - - { - /* Static test vectors. - * These were reduced from ~10^12 random vectors based on comparison-decision - * and edge-case coverage on 32-bit and 64-bit implementations. - * The responses were generated with Sage 5.9. - */ - secp256k1_scalar x; - secp256k1_scalar y; - secp256k1_scalar z; - secp256k1_scalar zz; - secp256k1_scalar one; - secp256k1_scalar r1; - secp256k1_scalar r2; -#if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar zzv; -#endif - int overflow; - unsigned char chal[33][2][32] = { - {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, - {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, - 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, - {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, - 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, - {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, - 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, - 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, - {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, - {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, - {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, - {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, - {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, - 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, - {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, - 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, - {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, - 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, - 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, - {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, - {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} - }; - unsigned char res[33][2][32] = { - {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, - 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, - 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, - 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, - {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, - 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, - 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, - 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, - {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, - 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, - 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, - 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, - {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, - 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, - 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, - 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, - {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, - 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, - 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, - 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, - {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, - 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, - 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, - 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, - {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, - 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, - 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, - 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, - {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, - 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, - 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, - 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, - {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, - 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, - 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, - 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, - {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, - 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, - 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, - 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, - {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, - 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, - 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, - 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, - {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, - 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, - 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, - 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, - {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, - 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, - 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, - 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, - {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, - 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, - 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, - 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, - {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, - 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, - 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, - 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, - {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, - 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, - 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, - 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, - {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, - 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, - 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, - 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, - {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, - 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, - 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, - 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, - {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, - 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, - 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, - 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, - {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, - 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, - 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, - 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, - {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, - 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, - 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, - 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, - {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, - 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, - 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, - 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, - {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, - 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, - 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, - 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, - {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, - 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, - 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, - 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, - {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, - 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, - 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, - 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, - {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, - 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, - 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, - 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, - {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, - 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, - 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, - 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, - {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, - 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, - 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, - 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, - {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, - 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, - 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, - 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, - {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, - 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, - 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, - 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, - {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, - 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, - 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, - 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, - {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, - 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, - 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, - 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, - {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, - 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, - 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, - 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, - {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, - 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, - 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, - 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, - {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, - 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, - 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, - 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, - {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, - 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, - 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, - 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, - {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, - 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, - 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, - 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, - {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, - 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, - 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, - 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, - {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, - 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, - 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, - 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, - {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, - 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, - 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, - 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, - 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, - 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, - 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, - {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, - 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, - 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, - 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, - 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, - 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, - 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, - {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, - 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, - 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, - 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, - {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, - 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, - 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, - 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, - {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, - 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, - 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, - 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, - {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, - 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, - 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, - 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, - {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, - 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, - 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, - 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, - {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, - 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, - 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, - 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, - {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, - 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, - 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, - 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, - {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, - 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, - 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, - 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, - {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, - 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, - 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, - 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, - {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, - 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, - 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, - 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, - {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, - 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, - 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, - 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, - {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, - {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} - }; - secp256k1_scalar_set_int(&one, 1); - for (i = 0; i < 33; i++) { - secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_mul(&z, &x, &y); - CHECK(!secp256k1_scalar_check_overflow(&z)); - CHECK(secp256k1_scalar_eq(&r1, &z)); - if (!secp256k1_scalar_is_zero(&y)) { - secp256k1_scalar_inverse(&zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); -#if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar_inverse_var(&zzv, &y); - CHECK(secp256k1_scalar_eq(&zzv, &zz)); -#endif - secp256k1_scalar_mul(&z, &z, &zz); - CHECK(!secp256k1_scalar_check_overflow(&z)); - CHECK(secp256k1_scalar_eq(&x, &z)); - secp256k1_scalar_mul(&zz, &zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); - CHECK(secp256k1_scalar_eq(&one, &zz)); - } - secp256k1_scalar_mul(&z, &x, &x); - CHECK(!secp256k1_scalar_check_overflow(&z)); - secp256k1_scalar_sqr(&zz, &x); - CHECK(!secp256k1_scalar_check_overflow(&zz)); - CHECK(secp256k1_scalar_eq(&zz, &z)); - CHECK(secp256k1_scalar_eq(&r2, &zz)); - } - } -} - -/***** FIELD TESTS *****/ - -void random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} - -void random_fe_test(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256_test(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} - -void random_fe_non_zero(secp256k1_fe *nz) { - int tries = 10; - while (--tries >= 0) { - random_fe(nz); - secp256k1_fe_normalize(nz); - if (!secp256k1_fe_is_zero(nz)) { - break; - } - } - /* Infinitesimal probability of spurious failure here */ - CHECK(tries >= 0); -} - -void random_fe_non_square(secp256k1_fe *ns) { - secp256k1_fe r; - random_fe_non_zero(ns); - if (secp256k1_fe_sqrt(&r, ns)) { - secp256k1_fe_negate(ns, ns, 1); - } -} - -int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe an = *a; - secp256k1_fe bn = *b; - secp256k1_fe_normalize_weak(&an); - secp256k1_fe_normalize_var(&bn); - return secp256k1_fe_equal_var(&an, &bn); -} - -int check_fe_inverse(const secp256k1_fe *a, const secp256k1_fe *ai) { - secp256k1_fe x; - secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_fe_mul(&x, a, ai); - return check_fe_equal(&x, &one); -} - -void run_field_convert(void) { - static const unsigned char b32[32] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 - }; - static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - static const secp256k1_fe fe = SECP256K1_FE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - secp256k1_fe fe2; - unsigned char b322[32]; - secp256k1_fe_storage fes2; - /* Check conversions to fe. */ - CHECK(secp256k1_fe_set_b32(&fe2, b32)); - CHECK(secp256k1_fe_equal_var(&fe, &fe2)); - secp256k1_fe_from_storage(&fe2, &fes); - CHECK(secp256k1_fe_equal_var(&fe, &fe2)); - /* Check conversion from fe. */ - secp256k1_fe_get_b32(b322, &fe); - CHECK(memcmp(b322, b32, 32) == 0); - secp256k1_fe_to_storage(&fes2, &fe); - CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); -} - -int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe t = *b; -#ifdef VERIFY - t.magnitude = a->magnitude; - t.normalized = a->normalized; -#endif - return memcmp(a, &t, sizeof(secp256k1_fe)); -} - -void run_field_misc(void) { - secp256k1_fe x; - secp256k1_fe y; - secp256k1_fe z; - secp256k1_fe q; - secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); - int i, j; - for (i = 0; i < 5*count; i++) { - secp256k1_fe_storage xs, ys, zs; - random_fe(&x); - random_fe_non_zero(&y); - /* Test the fe equality and comparison operations. */ - CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); - CHECK(secp256k1_fe_equal_var(&x, &x)); - z = x; - secp256k1_fe_add(&z,&y); - /* Test fe conditional move; z is not normalized here. */ - q = x; - secp256k1_fe_cmov(&x, &z, 0); - VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); - secp256k1_fe_cmov(&x, &x, 1); - CHECK(fe_memcmp(&x, &z) != 0); - CHECK(fe_memcmp(&x, &q) == 0); - secp256k1_fe_cmov(&q, &z, 1); - VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); - CHECK(fe_memcmp(&q, &z) == 0); - secp256k1_fe_normalize_var(&x); - secp256k1_fe_normalize_var(&z); - CHECK(!secp256k1_fe_equal_var(&x, &z)); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (i&1)); - VERIFY_CHECK(q.normalized && q.magnitude == 1); - for (j = 0; j < 6; j++) { - secp256k1_fe_negate(&z, &z, j+1); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (j&1)); - VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); - } - secp256k1_fe_normalize_var(&z); - /* Test storage conversion and conditional moves. */ - secp256k1_fe_to_storage(&xs, &x); - secp256k1_fe_to_storage(&ys, &y); - secp256k1_fe_to_storage(&zs, &z); - secp256k1_fe_storage_cmov(&zs, &xs, 0); - secp256k1_fe_storage_cmov(&zs, &zs, 1); - CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); - secp256k1_fe_storage_cmov(&ys, &xs, 1); - CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); - secp256k1_fe_from_storage(&x, &xs); - secp256k1_fe_from_storage(&y, &ys); - secp256k1_fe_from_storage(&z, &zs); - /* Test that mul_int, mul, and add agree. */ - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&y, &x); - z = x; - secp256k1_fe_mul_int(&z, 3); - CHECK(check_fe_equal(&y, &z)); - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&z, &x); - CHECK(check_fe_equal(&z, &y)); - z = x; - secp256k1_fe_mul_int(&z, 5); - secp256k1_fe_mul(&q, &x, &fe5); - CHECK(check_fe_equal(&z, &q)); - secp256k1_fe_negate(&x, &x, 1); - secp256k1_fe_add(&z, &x); - secp256k1_fe_add(&q, &x); - CHECK(check_fe_equal(&y, &z)); - CHECK(check_fe_equal(&q, &y)); - } -} - -void run_field_inv(void) { - secp256k1_fe x, xi, xii; - int i; - for (i = 0; i < 10*count; i++) { - random_fe_non_zero(&x); - secp256k1_fe_inv(&xi, &x); - CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv(&xii, &xi); - CHECK(check_fe_equal(&x, &xii)); - } -} - -void run_field_inv_var(void) { - secp256k1_fe x, xi, xii; - int i; - for (i = 0; i < 10*count; i++) { - random_fe_non_zero(&x); - secp256k1_fe_inv_var(&xi, &x); - CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv_var(&xii, &xi); - CHECK(check_fe_equal(&x, &xii)); - } -} - -void run_field_inv_all_var(void) { - secp256k1_fe x[16], xi[16], xii[16]; - int i; - /* Check it's safe to call for 0 elements */ - secp256k1_fe_inv_all_var(xi, x, 0); - for (i = 0; i < count; i++) { - size_t j; - size_t len = secp256k1_rand_int(15) + 1; - for (j = 0; j < len; j++) { - random_fe_non_zero(&x[j]); - } - secp256k1_fe_inv_all_var(xi, x, len); - for (j = 0; j < len; j++) { - CHECK(check_fe_inverse(&x[j], &xi[j])); - } - secp256k1_fe_inv_all_var(xii, xi, len); - for (j = 0; j < len; j++) { - CHECK(check_fe_equal(&x[j], &xii[j])); - } - } -} - -void run_sqr(void) { - secp256k1_fe x, s; - - { - int i; - secp256k1_fe_set_int(&x, 1); - secp256k1_fe_negate(&x, &x, 1); - - for (i = 1; i <= 512; ++i) { - secp256k1_fe_mul_int(&x, 2); - secp256k1_fe_normalize(&x); - secp256k1_fe_sqr(&s, &x); - } - } -} - -void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { - secp256k1_fe r1, r2; - int v = secp256k1_fe_sqrt(&r1, a); - CHECK((v == 0) == (k == NULL)); - - if (k != NULL) { - /* Check that the returned root is +/- the given known answer */ - secp256k1_fe_negate(&r2, &r1, 1); - secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); - secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); - CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); - } -} - -void run_sqrt(void) { - secp256k1_fe ns, x, s, t; - int i; - - /* Check sqrt(0) is 0 */ - secp256k1_fe_set_int(&x, 0); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - - /* Check sqrt of small squares (and their negatives) */ - for (i = 1; i <= 100; i++) { - secp256k1_fe_set_int(&x, i); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - test_sqrt(&t, NULL); - } - - /* Consistency checks for large random values */ - for (i = 0; i < 10; i++) { - int j; - random_fe_non_square(&ns); - for (j = 0; j < count; j++) { - random_fe(&x); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - test_sqrt(&t, NULL); - secp256k1_fe_mul(&t, &s, &ns); - test_sqrt(&t, NULL); - } - } -} - -/***** GROUP TESTS *****/ - -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); - CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); -} - -/* This compares jacobian points including their Z, not just their geometric meaning. */ -int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { - secp256k1_gej a2; - secp256k1_gej b2; - int ret = 1; - ret &= a->infinity == b->infinity; - if (ret && !a->infinity) { - a2 = *a; - b2 = *b; - secp256k1_fe_normalize(&a2.x); - secp256k1_fe_normalize(&a2.y); - secp256k1_fe_normalize(&a2.z); - secp256k1_fe_normalize(&b2.x); - secp256k1_fe_normalize(&b2.y); - secp256k1_fe_normalize(&b2.z); - ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; - ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; - ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; - } - return ret; -} - -void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; secp256k1_fe_normalize_weak(&u2); - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; secp256k1_fe_normalize_weak(&s2); - CHECK(secp256k1_fe_equal_var(&u1, &u2)); - CHECK(secp256k1_fe_equal_var(&s1, &s2)); -} - -void test_ge(void) { - int i, i1; -#ifdef USE_ENDOMORPHISM - int runs = 6; -#else - int runs = 4; -#endif - /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). - * The second in each pair of identical points uses a random Z coordinate in the Jacobian form. - * All magnitudes are randomized. - * All 17*17 combinations of points are added to each other, using all applicable methods. - * - * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. - */ - secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); - secp256k1_fe zf; - secp256k1_fe zfi2, zfi3; - - secp256k1_gej_set_infinity(&gej[0]); - secp256k1_ge_clear(&ge[0]); - secp256k1_ge_set_gej_var(&ge[0], &gej[0]); - for (i = 0; i < runs; i++) { - int j; - secp256k1_ge g; - random_group_element_test(&g); -#ifdef USE_ENDOMORPHISM - if (i >= runs - 2) { - secp256k1_ge_mul_lambda(&g, &ge[1]); - } - if (i >= runs - 1) { - secp256k1_ge_mul_lambda(&g, &g); - } -#endif - ge[1 + 4 * i] = g; - ge[2 + 4 * i] = g; - secp256k1_ge_neg(&ge[3 + 4 * i], &g); - secp256k1_ge_neg(&ge[4 + 4 * i], &g); - secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); - secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); - for (j = 0; j < 4; j++) { - random_field_element_magnitude(&ge[1 + j + 4 * i].x); - random_field_element_magnitude(&ge[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].x); - random_field_element_magnitude(&gej[1 + j + 4 * i].y); - random_field_element_magnitude(&gej[1 + j + 4 * i].z); - } - } - - /* Compute z inverses. */ - { - secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); - for (i = 0; i < 4 * runs + 1; i++) { - if (i == 0) { - /* The point at infinity does not have a meaningful z inverse. Any should do. */ - do { - random_field_element_test(&zs[i]); - } while(secp256k1_fe_is_zero(&zs[i])); - } else { - zs[i] = gej[i].z; - } - } - secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1); - free(zs); - } - - /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - do { - random_field_element_test(&zf); - } while(secp256k1_fe_is_zero(&zf)); - random_field_element_magnitude(&zf); - secp256k1_fe_inv_var(&zfi3, &zf); - secp256k1_fe_sqr(&zfi2, &zfi3); - secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); - - for (i1 = 0; i1 < 1 + 4 * runs; i1++) { - int i2; - for (i2 = 0; i2 < 1 + 4 * runs; i2++) { - /* Compute reference result using gej + gej (var). */ - secp256k1_gej refj, resj; - secp256k1_ge ref; - secp256k1_fe zr; - secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - /* Check Z ratio. */ - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zrz, &refj.z)); - } - secp256k1_ge_set_gej_var(&ref, &refj); - - /* Test gej + ge with Z ratio result (var). */ - secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - ge_equals_gej(&ref, &resj); - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zrz, &resj.z)); - } - - /* Test gej + ge (var, with additional Z factor). */ - { - secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ - secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); - secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - random_field_element_magnitude(&ge2_zfi.x); - random_field_element_magnitude(&ge2_zfi.y); - secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); - ge_equals_gej(&ref, &resj); - } - - /* Test gej + ge (const). */ - if (i2 != 0) { - /* secp256k1_gej_add_ge does not support its second argument being infinity. */ - secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); - ge_equals_gej(&ref, &resj); - } - - /* Test doubling (var). */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { - secp256k1_fe zr2; - /* Normal doubling with Z ratio result. */ - secp256k1_gej_double_var(&resj, &gej[i1], &zr2); - ge_equals_gej(&ref, &resj); - /* Check Z ratio. */ - secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); - CHECK(secp256k1_fe_equal_var(&zr2, &resj.z)); - /* Normal doubling. */ - secp256k1_gej_double_var(&resj, &gej[i2], NULL); - ge_equals_gej(&ref, &resj); - } - - /* Test adding opposites. */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { - CHECK(secp256k1_ge_is_infinity(&ref)); - } - - /* Test adding infinity. */ - if (i1 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i1])); - CHECK(secp256k1_gej_is_infinity(&gej[i1])); - ge_equals_gej(&ref, &gej[i2]); - } - if (i2 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i2])); - CHECK(secp256k1_gej_is_infinity(&gej[i2])); - ge_equals_gej(&ref, &gej[i1]); - } - } - } - - /* Test adding all points together in random order equals infinity. */ - { - secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); - for (i = 0; i < 4 * runs + 1; i++) { - gej_shuffled[i] = gej[i]; - } - for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + secp256k1_rand_int(4 * runs + 1 - i); - if (swap != i) { - secp256k1_gej t = gej_shuffled[i]; - gej_shuffled[i] = gej_shuffled[swap]; - gej_shuffled[swap] = t; - } - } - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); - } - CHECK(secp256k1_gej_is_infinity(&sum)); - free(gej_shuffled); - } - - /* Test batch gej -> ge conversion with and without known z ratios. */ - { - secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - for (i = 0; i < 4 * runs + 1; i++) { - /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ - if (i < 4 * runs) { - secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); - } - } - secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_fe s; - random_fe_non_zero(&s); - secp256k1_gej_rescale(&gej[i], &s); - ge_equals_gej(&ge_set_table[i], &gej[i]); - ge_equals_gej(&ge_set_all[i], &gej[i]); - } - free(ge_set_table); - free(ge_set_all); - free(zr); - } - - free(ge); - free(gej); - free(zinv); -} - -void test_add_neg_y_diff_x(void) { - /* The point of this test is to check that we can add two points - * whose y-coordinates are negatives of each other but whose x - * coordinates differ. If the x-coordinates were the same, these - * points would be negatives of each other and their sum is - * infinity. This is cool because it "covers up" any degeneracy - * in the addition algorithm that would cause the xy coordinates - * of the sum to be wrong (since infinity has no xy coordinates). - * HOWEVER, if the x-coordinates are different, infinity is the - * wrong answer, and such degeneracies are exposed. This is the - * root of https://github.com/bitcoin-core/secp256k1/issues/257 - * which this test is a regression test for. - * - * These points were generated in sage as - * # secp256k1 params - * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) - * C = EllipticCurve ([F (0), F (7)]) - * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) - * N = FiniteField(G.order()) - * - * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F) - * x = polygen(N) - * lam = (1 - x^3).roots()[1][0] - * - * # random "bad pair" - * P = C.random_element() - * Q = -int(lam) * P - * print " P: %x %x" % P.xy() - * print " Q: %x %x" % Q.xy() - * print "P + Q: %x %x" % (P + Q).xy() - */ - secp256k1_gej aj = SECP256K1_GEJ_CONST( - 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, - 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, - 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, - 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d - ); - secp256k1_gej bj = SECP256K1_GEJ_CONST( - 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, - 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, - 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, - 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 - ); - secp256k1_gej sumj = SECP256K1_GEJ_CONST( - 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, - 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, - 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, - 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe - ); - secp256k1_ge b; - secp256k1_gej resj; - secp256k1_ge res; - secp256k1_ge_set_gej(&b, &bj); - - secp256k1_gej_add_var(&resj, &aj, &bj, NULL); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); - - secp256k1_gej_add_ge(&resj, &aj, &b); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); - - secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); - secp256k1_ge_set_gej(&res, &resj); - ge_equals_gej(&res, &sumj); -} - -void run_ge(void) { - int i; - for (i = 0; i < count * 32; i++) { - test_ge(); - } - test_add_neg_y_diff_x(); -} - -void test_ec_combine(void) { - secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_pubkey data[6]; - const secp256k1_pubkey* d[6]; - secp256k1_pubkey sd; - secp256k1_pubkey sd2; - secp256k1_gej Qj; - secp256k1_ge Q; - int i; - for (i = 1; i <= 6; i++) { - secp256k1_scalar s; - random_scalar_order_test(&s); - secp256k1_scalar_add(&sum, &sum, &s); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&data[i - 1], &Q); - d[i - 1] = &data[i - 1]; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&sd, &Q); - CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); - CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); - } -} - -void run_ec_combine(void) { - int i; - for (i = 0; i < count * 8; i++) { - test_ec_combine(); - } -} - -void test_group_decompress(const secp256k1_fe* x) { - /* The input itself, normalized. */ - secp256k1_fe fex = *x; - secp256k1_fe fez; - /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ - secp256k1_ge ge_quad, ge_even, ge_odd; - secp256k1_gej gej_quad; - /* Return values of the above calls. */ - int res_quad, res_even, res_odd; - - secp256k1_fe_normalize_var(&fex); - - res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); - res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); - res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); - - CHECK(res_quad == res_even); - CHECK(res_quad == res_odd); - - if (res_quad) { - secp256k1_fe_normalize_var(&ge_quad.x); - secp256k1_fe_normalize_var(&ge_odd.x); - secp256k1_fe_normalize_var(&ge_even.x); - secp256k1_fe_normalize_var(&ge_quad.y); - secp256k1_fe_normalize_var(&ge_odd.y); - secp256k1_fe_normalize_var(&ge_even.y); - - /* No infinity allowed. */ - CHECK(!ge_quad.infinity); - CHECK(!ge_even.infinity); - CHECK(!ge_odd.infinity); - - /* Check that the x coordinates check out. */ - CHECK(secp256k1_fe_equal_var(&ge_quad.x, x)); - CHECK(secp256k1_fe_equal_var(&ge_even.x, x)); - CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); - - /* Check that the Y coordinate result in ge_quad is a square. */ - CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); - - /* Check odd/even Y in ge_odd, ge_even. */ - CHECK(secp256k1_fe_is_odd(&ge_odd.y)); - CHECK(!secp256k1_fe_is_odd(&ge_even.y)); - - /* Check secp256k1_gej_has_quad_y_var. */ - secp256k1_gej_set_ge(&gej_quad, &ge_quad); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - do { - random_fe_test(&fez); - } while (secp256k1_fe_is_zero(&fez)); - secp256k1_gej_rescale(&gej_quad, &fez); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - secp256k1_gej_neg(&gej_quad, &gej_quad); - CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); - do { - random_fe_test(&fez); - } while (secp256k1_fe_is_zero(&fez)); - secp256k1_gej_rescale(&gej_quad, &fez); - CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); - secp256k1_gej_neg(&gej_quad, &gej_quad); - CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); - } -} - -void run_group_decompress(void) { - int i; - for (i = 0; i < count * 4; i++) { - secp256k1_fe fe; - random_fe_test(&fe); - test_group_decompress(&fe); - } -} - -/***** ECMULT TESTS *****/ - -void run_ecmult_chain(void) { - /* random starting point A (on the curve) */ - secp256k1_gej a = SECP256K1_GEJ_CONST( - 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, - 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, - 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, - 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f - ); - /* two random initial factors xn and gn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, - 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 - ); - secp256k1_scalar gn = SECP256K1_SCALAR_CONST( - 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, - 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de - ); - /* two small multipliers to be applied to xn and gn in every iteration: */ - static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); - static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); - /* accumulators with the resulting coefficients to A and G */ - secp256k1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - /* actual points */ - secp256k1_gej x; - secp256k1_gej x2; - int i; - - /* the point being computed */ - x = a; - for (i = 0; i < 200*count; i++) { - /* in each iteration, compute X = xn*X + gn*G; */ - secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); - /* also compute ae and ge: the actual accumulated factors for A and G */ - /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ - secp256k1_scalar_mul(&ae, &ae, &xn); - secp256k1_scalar_mul(&ge, &ge, &xn); - secp256k1_scalar_add(&ge, &ge, &gn); - /* modify xn and gn */ - secp256k1_scalar_mul(&xn, &xn, &xf); - secp256k1_scalar_mul(&gn, &gn, &gf); - - /* verify */ - if (i == 19999) { - /* expected result after 19999 iterations */ - secp256k1_gej rp = SECP256K1_GEJ_CONST( - 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, - 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, - 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, - 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 - ); - - secp256k1_gej_neg(&rp, &rp); - secp256k1_gej_add_var(&rp, &rp, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&rp)); - } - } - /* redo the computation, but directly with the resulting ae and ge coefficients: */ - secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); - secp256k1_gej_neg(&x2, &x2); - secp256k1_gej_add_var(&x2, &x2, &x, NULL); - CHECK(secp256k1_gej_is_infinity(&x2)); -} - -void test_point_times_order(const secp256k1_gej *point) { - /* X * (point + G) + (order-X) * (pointer + G) = 0 */ - secp256k1_scalar x; - secp256k1_scalar nx; - secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_gej res1, res2; - secp256k1_ge res3; - unsigned char pub[65]; - size_t psize = 65; - random_scalar_order_test(&x); - secp256k1_scalar_negate(&nx, &x); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ - secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ - secp256k1_gej_add_var(&res1, &res1, &res2, NULL); - CHECK(secp256k1_gej_is_infinity(&res1)); - CHECK(secp256k1_gej_is_valid_var(&res1) == 0); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - CHECK(secp256k1_ge_is_valid_var(&res3) == 0); - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); - psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); - /* check zero/one edge cases */ - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); - secp256k1_ge_set_gej(&res3, &res1); - ge_equals_gej(&res3, point); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); - secp256k1_ge_set_gej(&res3, &res1); - ge_equals_ge(&res3, &secp256k1_ge_const_g); -} - -void run_point_times_order(void) { - int i; - secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); - static const secp256k1_fe xr = SECP256K1_FE_CONST( - 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, - 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 - ); - for (i = 0; i < 500; i++) { - secp256k1_ge p; - if (secp256k1_ge_set_xo_var(&p, &x, 1)) { - secp256k1_gej j; - CHECK(secp256k1_ge_is_valid_var(&p)); - secp256k1_gej_set_ge(&j, &p); - CHECK(secp256k1_gej_is_valid_var(&j)); - test_point_times_order(&j); - } - secp256k1_fe_sqr(&x, &x); - } - secp256k1_fe_normalize_var(&x); - CHECK(secp256k1_fe_equal_var(&x, &xr)); -} - -void ecmult_const_random_mult(void) { - /* random starting point A (on the curve) */ - secp256k1_ge a = SECP256K1_GE_CONST( - 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, - 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, - 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, - 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d - ); - /* random initial factor xn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, - 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b - ); - /* expected xn * A (from sage) */ - secp256k1_ge expected_b = SECP256K1_GE_CONST( - 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, - 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, - 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, - 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 - ); - secp256k1_gej b; - secp256k1_ecmult_const(&b, &a, &xn); - - CHECK(secp256k1_ge_is_valid_var(&a)); - ge_equals_gej(&expected_b, &b); -} - -void ecmult_const_commutativity(void) { - secp256k1_scalar a; - secp256k1_scalar b; - secp256k1_gej res1; - secp256k1_gej res2; - secp256k1_ge mid1; - secp256k1_ge mid2; - random_scalar_order_test(&a); - random_scalar_order_test(&b); - - secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); - secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - secp256k1_ecmult_const(&res1, &mid1, &b); - secp256k1_ecmult_const(&res2, &mid2, &a); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - ge_equals_ge(&mid1, &mid2); -} - -void ecmult_const_mult_zero_one(void) { - secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_scalar negone; - secp256k1_gej res1; - secp256k1_ge res2; - secp256k1_ge point; - secp256k1_scalar_negate(&negone, &one); - - random_group_element_test(&point); - secp256k1_ecmult_const(&res1, &point, &zero); - secp256k1_ge_set_gej(&res2, &res1); - CHECK(secp256k1_ge_is_infinity(&res2)); - secp256k1_ecmult_const(&res1, &point, &one); - secp256k1_ge_set_gej(&res2, &res1); - ge_equals_ge(&res2, &point); - secp256k1_ecmult_const(&res1, &point, &negone); - secp256k1_gej_neg(&res1, &res1); - secp256k1_ge_set_gej(&res2, &res1); - ge_equals_ge(&res2, &point); -} - -void ecmult_const_chain_multiply(void) { - /* Check known result (randomly generated test problem from sage) */ - const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( - 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, - 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b - ); - const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( - 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, - 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, - 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, - 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 - ); - secp256k1_gej point; - secp256k1_ge res; - int i; - - secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); - for (i = 0; i < 100; ++i) { - secp256k1_ge tmp; - secp256k1_ge_set_gej(&tmp, &point); - secp256k1_ecmult_const(&point, &tmp, &scalar); - } - secp256k1_ge_set_gej(&res, &point); - ge_equals_gej(&res, &expected_point); -} - -void run_ecmult_const_tests(void) { - ecmult_const_mult_zero_one(); - ecmult_const_random_mult(); - ecmult_const_commutativity(); - ecmult_const_chain_multiply(); -} - -void test_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, two, t; - int wnaf[256]; - int zeroes = -1; - int i; - int bits; - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&two, 2); - bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); - CHECK(bits <= 256); - for (i = bits-1; i >= 0; i--) { - int v = wnaf[i]; - secp256k1_scalar_mul(&x, &x, &two); - if (v) { - CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ - zeroes=0; - CHECK((v & 1) == 1); /* check non-zero elements are odd */ - CHECK(v <= (1 << (w-1)) - 1); /* check range below */ - CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ - } else { - CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ - zeroes++; - } - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ -} - -void test_constant_wnaf_negate(const secp256k1_scalar *number) { - secp256k1_scalar neg1 = *number; - secp256k1_scalar neg2 = *number; - int sign1 = 1; - int sign2 = 1; - - if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { - secp256k1_scalar_negate(&neg1, &neg1); - sign1 = -1; - } - sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); - CHECK(sign1 == sign2); - CHECK(secp256k1_scalar_eq(&neg1, &neg2)); -} - -void test_constant_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, shift; - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num = *number; - - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&shift, 1 << w); - /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ -#ifdef USE_ENDOMORPHISM - for (i = 0; i < 16; ++i) { - secp256k1_scalar_shr_int(&num, 8); - } -#endif - skew = secp256k1_wnaf_const(wnaf, num, w); - - for (i = WNAF_SIZE(w); i >= 0; --i) { - secp256k1_scalar t; - int v = wnaf[i]; - CHECK(v != 0); /* check nonzero */ - CHECK(v & 1); /* check parity */ - CHECK(v > -(1 << w)); /* check range above */ - CHECK(v < (1 << w)); /* check range below */ - - secp256k1_scalar_mul(&x, &x, &shift); - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - /* Skew num because when encoding numbers as odd we use an offset */ - secp256k1_scalar_cadd_bit(&num, skew == 2, 1); - CHECK(secp256k1_scalar_eq(&x, &num)); -} - -void run_wnaf(void) { - int i; - secp256k1_scalar n = {{0}}; - - /* Sanity check: 1 and 2 are the smallest odd and even numbers and should - * have easier-to-diagnose failure modes */ - n.d[0] = 1; - test_constant_wnaf(&n, 4); - n.d[0] = 2; - test_constant_wnaf(&n, 4); - /* Random tests */ - for (i = 0; i < count; i++) { - random_scalar_order(&n); - test_wnaf(&n, 4+(i%10)); - test_constant_wnaf_negate(&n); - test_constant_wnaf(&n, 4 + (i % 10)); - } - secp256k1_scalar_set_int(&n, 0); - CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); - CHECK(secp256k1_scalar_is_zero(&n)); - CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); - CHECK(secp256k1_scalar_is_zero(&n)); -} - -void test_ecmult_constants(void) { - /* Test ecmult_gen() for [0..36) and [order-36..0). */ - secp256k1_scalar x; - secp256k1_gej r; - secp256k1_ge ng; - int i; - int j; - secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); - for (i = 0; i < 36; i++ ) { - secp256k1_scalar_set_int(&x, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); - for (j = 0; j < i; j++) { - if (j == i - 1) { - ge_equals_gej(&secp256k1_ge_const_g, &r); - } - secp256k1_gej_add_ge(&r, &r, &ng); - } - CHECK(secp256k1_gej_is_infinity(&r)); - } - for (i = 1; i <= 36; i++ ) { - secp256k1_scalar_set_int(&x, i); - secp256k1_scalar_negate(&x, &x); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); - for (j = 0; j < i; j++) { - if (j == i - 1) { - ge_equals_gej(&ng, &r); - } - secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g); - } - CHECK(secp256k1_gej_is_infinity(&r)); - } -} - -void run_ecmult_constants(void) { - test_ecmult_constants(); -} - -void test_ecmult_gen_blind(void) { - /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ - secp256k1_scalar key; - secp256k1_scalar b; - unsigned char seed32[32]; - secp256k1_gej pgej; - secp256k1_gej pgej2; - secp256k1_gej i; - secp256k1_ge pge; - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); - secp256k1_rand256(seed32); - b = ctx->ecmult_gen_ctx.blind; - i = ctx->ecmult_gen_ctx.initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); - CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); - CHECK(!gej_xyz_equals_gej(&i, &ctx->ecmult_gen_ctx.initial)); - secp256k1_ge_set_gej(&pge, &pgej); - ge_equals_gej(&pge, &pgej2); -} - -void test_ecmult_gen_blind_reset(void) { - /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ - secp256k1_scalar b; - secp256k1_gej initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); - b = ctx->ecmult_gen_ctx.blind; - initial = ctx->ecmult_gen_ctx.initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); - CHECK(secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); - CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); -} - -void run_ecmult_gen_blind(void) { - int i; - test_ecmult_gen_blind_reset(); - for (i = 0; i < 10; i++) { - test_ecmult_gen_blind(); - } -} - -#ifdef USE_ENDOMORPHISM -/***** ENDOMORPHISH TESTS *****/ -void test_scalar_split(void) { - secp256k1_scalar full; - secp256k1_scalar s1, slam; - const unsigned char zero[32] = {0}; - unsigned char tmp[32]; - - random_scalar_order_test(&full); - secp256k1_scalar_split_lambda(&s1, &slam, &full); - - /* check that both are <= 128 bits in size */ - if (secp256k1_scalar_is_high(&s1)) { - secp256k1_scalar_negate(&s1, &s1); - } - if (secp256k1_scalar_is_high(&slam)) { - secp256k1_scalar_negate(&slam, &slam); - } - - secp256k1_scalar_get_b32(tmp, &s1); - CHECK(memcmp(zero, tmp, 16) == 0); - secp256k1_scalar_get_b32(tmp, &slam); - CHECK(memcmp(zero, tmp, 16) == 0); -} - -void run_endomorphism_tests(void) { - test_scalar_split(); -} -#endif - -void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { - unsigned char pubkeyc[65]; - secp256k1_pubkey pubkey; - secp256k1_ge ge; - size_t pubkeyclen; - int32_t ecount; - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { - /* Smaller sizes are tested exhaustively elsewhere. */ - int32_t i; - memcpy(&pubkeyc[1], input, 64); - VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen); - for (i = 0; i < 256; i++) { - /* Try all type bytes. */ - int xpass; - int ypass; - int ysign; - pubkeyc[0] = i; - /* What sign does this point have? */ - ysign = (input[63] & 1) + 2; - /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ - xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); - /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ - ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && - ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); - if (xpass || ypass) { - /* These cases must parse. */ - unsigned char pubkeyo[65]; - size_t outl; - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - ecount = 0; - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - VG_UNDEF(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - VG_CHECK(pubkeyo, outl); - CHECK(outl == 33); - CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); - CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); - if (ypass) { - /* This test isn't always done because we decode with alternative signs, so the y won't match. */ - CHECK(pubkeyo[0] == ysign); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - secp256k1_pubkey_save(&pubkey, &ge); - VG_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - VG_UNDEF(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - VG_CHECK(pubkeyo, outl); - CHECK(outl == 65); - CHECK(pubkeyo[0] == 4); - CHECK(memcmp(&pubkeyo[1], input, 64) == 0); - } - CHECK(ecount == 0); - } else { - /* These cases must fail to parse. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - } - } - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); -} - -void run_ec_pubkey_parse_test(void) { -#define SECP256K1_EC_PARSE_TEST_NVALID (12) - const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { - { - /* Point with leading and trailing zeros in x and y serialization. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, - 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 - }, - { - /* Point with x equal to a 3rd root of unity.*/ - 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, - 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with largest x. (1/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, - 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, - }, - { - /* Point with largest x. (2/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, - 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, - }, - { - /* Point with smallest x. (1/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with smallest x. (2/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* Point with largest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with smallest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - } - }; -#define SECP256K1_EC_PARSE_TEST_NXVALID (4) - const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { - { - /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* x on curve, y is from y^2 = x^3 + 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 - } - }; -#define SECP256K1_EC_PARSE_TEST_NINVALID (7) - const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { - { - /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ - 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, - 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, - 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, - 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, - 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, - 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 - } - }; - const unsigned char pubkeyc[66] = { - /* Serialization of G. */ - 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, - 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, - 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, - 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, - 0xB8, 0x00 - }; - unsigned char sout[65]; - unsigned char shortkey[2]; - secp256k1_ge ge; - secp256k1_pubkey pubkey; - size_t len; - int32_t i; - int32_t ecount; - int32_t ecount2; - ecount = 0; - /* Nothing should be reading this far into pubkeyc. */ - VG_UNDEF(&pubkeyc[65], 1); - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - /* Zero length claimed, fail, zeroize, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(shortkey, 2); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 0) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* Length one claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 256 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - shortkey[0] = i; - VG_UNDEF(&shortkey[1], 1); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - /* Length two claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 65536 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - shortkey[0] = i & 255; - shortkey[1] = i >> 8; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - } - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 33) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, pubkeyc, 65) == 0); - CHECK(ecount == 2); - /* NULL input string. Illegal arg and zeroize output. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, NULL, 65) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 1); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 2); - /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 64) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 66) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); - CHECK(ecount == 1); - /* Valid parse. */ - memset(&pubkey, 0, sizeof(pubkey)); - ecount = 0; - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(ecount == 0); - VG_UNDEF(&ge, sizeof(ge)); - CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); - VG_CHECK(&ge.x, sizeof(ge.x)); - VG_CHECK(&ge.y, sizeof(ge.y)); - VG_CHECK(&ge.infinity, sizeof(ge.infinity)); - ge_equals_ge(&secp256k1_ge_const_g, &ge); - CHECK(ecount == 0); - /* secp256k1_ec_pubkey_serialize illegal args. */ - ecount = 0; - len = 65; - CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); - CHECK(ecount == 1); - CHECK(len == 0); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); - CHECK(ecount == 2); - len = 65; - VG_UNDEF(sout, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0); - VG_CHECK(sout, 65); - CHECK(ecount == 3); - CHECK(len == 0); - len = 65; - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, ~0) == 0); - CHECK(ecount == 4); - CHECK(len == 0); - len = 65; - VG_UNDEF(sout, 65); - CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - VG_CHECK(sout, 65); - CHECK(ecount == 4); - CHECK(len == 65); - /* Multiple illegal args. Should still set arg error only once. */ - ecount = 0; - ecount2 = 11; - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); - CHECK(ecount == 1); - /* Does the illegal arg callback actually change the behavior? */ - secp256k1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); - CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); - CHECK(ecount == 1); - CHECK(ecount2 == 10); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); - /* Try a bunch of prefabbed points with all possible encodings. */ - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { - ec_pubkey_parse_pointtest(valid[i], 1, 1); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { - ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { - ec_pubkey_parse_pointtest(invalid[i], 0, 0); - } -} - -void run_eckey_edge_case_test(void) { - const unsigned char orderc[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; - unsigned char ctmp[33]; - unsigned char ctmp2[33]; - secp256k1_pubkey pubkey; - secp256k1_pubkey pubkey2; - secp256k1_pubkey pubkey_one; - secp256k1_pubkey pubkey_negone; - const secp256k1_pubkey *pubkeys[3]; - size_t len; - int32_t ecount; - /* Group order is too large, reject. */ - CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Maximum value is too large, reject. */ - memset(ctmp, 255, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Zero is too small, reject. */ - memset(ctmp, 0, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* One must be accepted. */ - ctmp[31] = 0x01; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_one = pubkey; - /* Group order + 1 is too large, reject. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x42; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* -1 must be accepted. */ - ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); - VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_negone = pubkey; - /* Tweak of zero leaves the value changed. */ - memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); - CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); - memcpy(&pubkey2, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Multiply tweak of zero zeroizes the output. */ - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Overflowing key tweak zeroizes. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); - CHECK(memcmp(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Private key tweaks results in a key of zero. */ - ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); - CHECK(memcmp(zeros, ctmp2, 32) == 0); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Tweak computation wraps and results in a key of 1. */ - ctmp2[31] = 2; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); - CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Tweak mul * 2 = 1+1. */ - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Test argument errors. */ - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - CHECK(ecount == 0); - /* Zeroize pubkey on parse error. */ - memset(&pubkey, 0, 32); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - memset(&pubkey2, 0, 32); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); - CHECK(ecount == 2); - CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); - /* Plain argument errors. */ - ecount = 0; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); - CHECK(ecount == 1); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - memset(ctmp2, 0, 32); - ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); - CHECK(ecount == 2); - ecount = 0; - CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); - CHECK(ecount == 1); - memset(&pubkey, 1, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 2); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* secp256k1_ec_pubkey_combine tests. */ - ecount = 0; - pubkeys[0] = &pubkey_one; - VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 2); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 3); - pubkeys[0] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); - CHECK(memcmp(ctmp, ctmp2, 33) == 0); - /* Result is infinity. */ - pubkeys[0] = &pubkey_one; - pubkeys[1] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK(ecount == 3); - /* Passes through infinity but comes out one. */ - pubkeys[2] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); - CHECK(memcmp(ctmp, ctmp2, 33) == 0); - /* Adds to two. */ - pubkeys[1] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - CHECK(ecount == 3); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); -} - -void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { - secp256k1_scalar nonce; - do { - random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); -} - -void test_ecdsa_sign_verify(void) { - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar one; - secp256k1_scalar msg, key; - secp256k1_scalar sigr, sigs; - int recid; - int getrec; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - getrec = secp256k1_rand_bits(1); - random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); - if (getrec) { - CHECK(recid >= 0 && recid < 4); - } - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); -} - -void run_ecdsa_sign_verify(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_ecdsa_sign_verify(); - } -} - -/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ -static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void)msg32; - (void)key32; - (void)algo16; - memcpy(nonce32, data, 32); - return (counter == 0); -} - -static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that has a fatal error on the first counter value. */ - if (counter == 0) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); -} - -static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ - if (counter < 3) { - memset(nonce32, counter==0 ? 0 : 255, 32); - if (counter == 2) { - nonce32[31]--; - } - return 1; - } - if (counter < 5) { - static const unsigned char order[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; - memcpy(nonce32, order, 32); - if (counter == 4) { - nonce32[31]++; - } - return 1; - } - /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ - /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ - if (counter > 5) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); -} - -int is_empty_signature(const secp256k1_ecdsa_signature *sig) { - static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; - return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; -} - -void test_ecdsa_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - unsigned char privkey2[32]; - secp256k1_ecdsa_signature signature[6]; - secp256k1_scalar r, s; - unsigned char sig[74]; - size_t siglen = 74; - unsigned char pubkeyc[65]; - size_t pubkeyclen = 65; - secp256k1_pubkey pubkey; - unsigned char seckey[300]; - size_t seckeylen = 300; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - - /* Verify exporting and importing public key. */ - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); - memset(&pubkey, 0, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); - - /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); - CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); - CHECK(memcmp(privkey, privkey2, 32) == 0); - - /* Optionally tweak the keys using addition. */ - if (secp256k1_rand_int(3) == 0) { - int ret1; - int ret2; - unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); - CHECK(ret1 == ret2); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Optionally tweak the keys using multiplication. */ - if (secp256k1_rand_int(3) == 0) { - int ret1; - int ret2; - unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); - CHECK(ret1 == ret2); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); - CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Sign. */ - CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &signature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); - CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); - CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); - CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); - /* Verify. */ - CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); - /* Test lower-S form, malleate, verify and fail, test again, malleate again */ - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); - CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); - CHECK(memcmp(&signature[5], &signature[0], 64) == 0); - - /* Serialize/parse DER and verify again */ - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); - memset(&signature[0], 0, sizeof(signature[0])); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); - /* Serialize/destroy/parse DER and verify again. */ - siglen = 74; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); - sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || - secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); -} - -void test_random_pubkeys(void) { - secp256k1_ge elem; - secp256k1_ge elem2; - unsigned char in[65]; - /* Generate some randomly sized pubkeys. */ - size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; - if (secp256k1_rand_bits(2) == 0) { - len = secp256k1_rand_bits(6); - } - if (len == 65) { - in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); - } else { - in[0] = secp256k1_rand_bits(1) ? 2 : 3; - } - if (secp256k1_rand_bits(3) == 0) { - in[0] = secp256k1_rand_bits(8); - } - if (len > 1) { - secp256k1_rand256(&in[1]); - } - if (len > 33) { - secp256k1_rand256(&in[33]); - } - if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { - unsigned char out[65]; - unsigned char firstb; - int res; - size_t size = len; - firstb = in[0]; - /* If the pubkey can be parsed, it should round-trip... */ - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); - CHECK(size == len); - CHECK(memcmp(&in[1], &out[1], len-1) == 0); - /* ... except for the type of hybrid inputs. */ - if ((in[0] != 6) && (in[0] != 7)) { - CHECK(in[0] == out[0]); - } - size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); - CHECK(size == 65); - CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); - ge_equals_ge(&elem,&elem2); - /* Check that the X9.62 hybrid type is checked. */ - in[0] = secp256k1_rand_bits(1) ? 6 : 7; - res = secp256k1_eckey_pubkey_parse(&elem2, in, size); - if (firstb == 2 || firstb == 3) { - if (in[0] == firstb + 4) { - CHECK(res); - } else { - CHECK(!res); - } - } - if (res) { - ge_equals_ge(&elem,&elem2); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); - CHECK(memcmp(&in[1], &out[1], 64) == 0); - } - } -} - -void run_random_pubkeys(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_random_pubkeys(); - } -} - -void run_ecdsa_end_to_end(void) { - int i; - for (i = 0; i < 64*count; i++) { - test_ecdsa_end_to_end(); - } -} - -int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { - static const unsigned char zeroes[32] = {0}; -#ifdef ENABLE_OPENSSL_TESTS - static const unsigned char max_scalar[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 - }; -#endif - - int ret = 0; - - secp256k1_ecdsa_signature sig_der; - unsigned char roundtrip_der[2048]; - unsigned char compact_der[64]; - size_t len_der = 2048; - int parsed_der = 0, valid_der = 0, roundtrips_der = 0; - - secp256k1_ecdsa_signature sig_der_lax; - unsigned char roundtrip_der_lax[2048]; - unsigned char compact_der_lax[64]; - size_t len_der_lax = 2048; - int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; - -#ifdef ENABLE_OPENSSL_TESTS - ECDSA_SIG *sig_openssl; - const unsigned char *sigptr; - unsigned char roundtrip_openssl[2048]; - int len_openssl = 2048; - int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0; -#endif - - parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); - if (parsed_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; - valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); - } - if (valid_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; - roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; - } - - parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); - if (parsed_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; - valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); - } - if (valid_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; - roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; - } - - if (certainly_der) { - ret |= (!parsed_der) << 2; - } - if (certainly_not_der) { - ret |= (parsed_der) << 17; - } - if (valid_der) { - ret |= (!roundtrips_der) << 3; - } - - if (valid_der) { - ret |= (!roundtrips_der_lax) << 12; - ret |= (len_der != len_der_lax) << 13; - ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14; - } - ret |= (roundtrips_der != roundtrips_der_lax) << 15; - if (parsed_der) { - ret |= (!parsed_der_lax) << 16; - } - -#ifdef ENABLE_OPENSSL_TESTS - sig_openssl = ECDSA_SIG_new(); - sigptr = sig; - parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); - if (parsed_openssl) { - valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; - if (valid_openssl) { - unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); - valid_openssl = memcmp(tmp, max_scalar, 32) < 0; - } - if (valid_openssl) { - unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); - valid_openssl = memcmp(tmp, max_scalar, 32) < 0; - } - } - len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); - if (len_openssl <= 2048) { - unsigned char *ptr = roundtrip_openssl; - CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); - roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); - } else { - len_openssl = 0; - } - ECDSA_SIG_free(sig_openssl); - - ret |= (parsed_der && !parsed_openssl) << 4; - ret |= (valid_der && !valid_openssl) << 5; - ret |= (roundtrips_openssl && !parsed_der) << 6; - ret |= (roundtrips_der != roundtrips_openssl) << 7; - if (roundtrips_openssl) { - ret |= (len_der != (size_t)len_openssl) << 8; - ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9; - } -#endif - return ret; -} - -static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { - size_t i; - for (i = 0; i < ptrlen; i++) { - int shift = ptrlen - 1 - i; - if (shift >= 4) { - ptr[i] = 0; - } else { - ptr[i] = (val >> shift) & 0xFF; - } - } -} - -static void damage_array(unsigned char *sig, size_t *len) { - int pos; - int action = secp256k1_rand_bits(3); - if (action < 1 && *len > 3) { - /* Delete a byte. */ - pos = secp256k1_rand_int(*len); - memmove(sig + pos, sig + pos + 1, *len - pos - 1); - (*len)--; - return; - } else if (action < 2 && *len < 2048) { - /* Insert a byte. */ - pos = secp256k1_rand_int(1 + *len); - memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = secp256k1_rand_bits(8); - (*len)++; - return; - } else if (action < 4) { - /* Modify a byte. */ - sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); - return; - } else { /* action < 8 */ - /* Modify a bit. */ - sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); - return; - } -} - -static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { - int der; - int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; - size_t tlen, elen, glen; - int indet; - int n; - - *len = 0; - der = secp256k1_rand_bits(2) == 0; - *certainly_der = der; - *certainly_not_der = 0; - indet = der ? 0 : secp256k1_rand_int(10) == 0; - - for (n = 0; n < 2; n++) { - /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ - nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); - /* The length of the number in bytes (the first byte of which will always be nonzero) */ - nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; - CHECK(nlen[n] <= 232); - /* The top bit of the number. */ - nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); - /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ - nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); - /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ - nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); - if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { - *certainly_not_der = 1; - } - CHECK(nlen[n] + nzlen[n] <= 300); - /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ - nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); - if (!der) { - /* nlenlen[n] max 127 bytes */ - int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; - nlenlen[n] += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); - } - - /* The total length of the data to go, so far */ - tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; - CHECK(tlen <= 856); - - /* The length of the garbage inside the tuple. */ - elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; - if (elen != 0) { - *certainly_not_der = 1; - } - tlen += elen; - CHECK(tlen <= 980); - - /* The length of the garbage after the end of the tuple. */ - glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; - if (glen != 0) { - *certainly_not_der = 1; - } - CHECK(tlen + glen <= 990); - - /* Write the tuple header. */ - sig[(*len)++] = 0x30; - if (indet) { - /* Indeterminate length */ - sig[(*len)++] = 0x80; - *certainly_not_der = 1; - } else { - int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); - if (!der) { - int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; - tlenlen += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - if (tlenlen == 0) { - /* Short length notation */ - sig[(*len)++] = tlen; - } else { - /* Long length notation */ - sig[(*len)++] = 128 + tlenlen; - assign_big_endian(sig + *len, tlenlen, tlen); - *len += tlenlen; - } - tlen += tlenlen; - } - tlen += 2; - CHECK(tlen + glen <= 1119); - - for (n = 0; n < 2; n++) { - /* Write the integer header. */ - sig[(*len)++] = 0x02; - if (nlenlen[n] == 0) { - /* Short length notation */ - sig[(*len)++] = nlen[n] + nzlen[n]; - } else { - /* Long length notation. */ - sig[(*len)++] = 128 + nlenlen[n]; - assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); - *len += nlenlen[n]; - } - /* Write zero padding */ - while (nzlen[n] > 0) { - sig[(*len)++] = 0x00; - nzlen[n]--; - } - if (nlen[n] == 32 && !nlow[n]) { - /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ - int i; - for (i = 0; i < 16; i++) { - sig[(*len)++] = 0xFF; - } - nlen[n] -= 16; - } - /* Write first byte of number */ - if (nlen[n] > 0) { - sig[(*len)++] = nhbyte[n]; - nlen[n]--; - } - /* Generate remaining random bytes of number */ - secp256k1_rand_bytes_test(sig + *len, nlen[n]); - *len += nlen[n]; - nlen[n] = 0; - } - - /* Generate random garbage inside tuple. */ - secp256k1_rand_bytes_test(sig + *len, elen); - *len += elen; - - /* Generate end-of-contents bytes. */ - if (indet) { - sig[(*len)++] = 0; - sig[(*len)++] = 0; - tlen += 2; - } - CHECK(tlen + glen <= 1121); - - /* Generate random garbage outside tuple. */ - secp256k1_rand_bytes_test(sig + *len, glen); - *len += glen; - tlen += glen; - CHECK(tlen <= 1121); - CHECK(tlen == *len); -} - -void run_ecdsa_der_parse(void) { - int i,j; - for (i = 0; i < 200 * count; i++) { - unsigned char buffer[2048]; - size_t buflen = 0; - int certainly_der = 0; - int certainly_not_der = 0; - random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); - CHECK(buflen <= 2048); - for (j = 0; j < 16; j++) { - int ret = 0; - if (j > 0) { - damage_array(buffer, &buflen); - /* We don't know anything anymore about the DERness of the result */ - certainly_der = 0; - certainly_not_der = 0; - } - ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); - if (ret != 0) { - size_t k; - fprintf(stderr, "Failure %x on ", ret); - for (k = 0; k < buflen; k++) { - fprintf(stderr, "%02x ", buffer[k]); - } - fprintf(stderr, "\n"); - } - CHECK(ret == 0); - } - } -} - -/* Tests several edge cases. */ -void test_ecdsa_edge_cases(void) { - int t; - secp256k1_ecdsa_signature sig; - - /* Test the case where ECDSA recomputes a point that is infinity. */ - { - secp256k1_gej keyj; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_negate(&ss, &ss); - secp256k1_scalar_inverse(&ss, &ss); - secp256k1_scalar_set_int(&sr, 1); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); - secp256k1_ge_set_gej(&key, &keyj); - msg = ss; - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with r of zero fails. */ - { - const unsigned char pubkey_mods_zero[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x41 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 0); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with s of zero fails. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 0); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 1); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with message 0 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02 - }; - const unsigned char pubkey2[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x43 - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 2); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message 1 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, - 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, - 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, - 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, - 0x25 - }; - const unsigned char pubkey2[33] = { - 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, - 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, - 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, - 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, - 0x62 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message -1 passes. */ - { - const unsigned char pubkey[33] = { - 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, - 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, - 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, - 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, - 0xf1 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_negate(&msg, &msg); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); - secp256k1_scalar_set_int(&ss, 3); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); - } - - /* Signature where s would be zero. */ - { - secp256k1_pubkey pubkey; - size_t siglen; - int32_t ecount; - unsigned char signature[72]; - static const unsigned char nonce[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - static const unsigned char nonce2[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 - }; - const unsigned char key[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - unsigned char msg[32] = { - 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, - 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, - 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, - 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, - }; - ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); - msg[31] = 0xaa; - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1); - CHECK(ecount == 0); - CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); - CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); - CHECK(ecount == 6); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); - CHECK(ecount == 7); - /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); - CHECK(ecount == 8); - siglen = 72; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); - CHECK(ecount == 9); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); - CHECK(ecount == 10); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); - CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); - CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); - CHECK(ecount == 12); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); - CHECK(ecount == 13); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); - CHECK(ecount == 13); - siglen = 10; - /* Too little room for a signature does not fail via ARGCHECK. */ - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); - CHECK(ecount == 13); - ecount = 0; - CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); - CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); - CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); - CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); - CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); - CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); - CHECK(ecount == 5); - memset(signature, 255, 64); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); - CHECK(ecount == 5); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); - } - - /* Nonce function corner cases. */ - for (t = 0; t < 2; t++) { - static const unsigned char zero[32] = {0x00}; - int i; - unsigned char key[32]; - unsigned char msg[32]; - secp256k1_ecdsa_signature sig2; - secp256k1_scalar sr[512], ss; - const unsigned char *extra; - extra = t == 0 ? NULL : zero; - memset(msg, 0, 32); - msg[31] = 1; - /* High key results in signature failure. */ - memset(key, 0xFF, 32); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Zero key results in signature failure. */ - memset(key, 0, 32); - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Nonce function failure results in signature failure. */ - key[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_fail, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* The retry loop successfully makes its way to the first good value. */ - CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_retry, extra) == 1); - CHECK(!is_empty_signature(&sig)); - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function is deterministic. */ - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function changes output with different messages. */ - for(i = 0; i < 256; i++) { - int j; - msg[0] = i; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - msg[0] = 0; - msg[31] = 2; - /* The default nonce function changes output with different keys. */ - for(i = 256; i < 512; i++) { - int j; - key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - key[0] = 0; - } - - { - /* Check that optional nonce arguments do not have equivalent effect. */ - const unsigned char zeros[32] = {0}; - unsigned char nonce[32]; - unsigned char nonce2[32]; - unsigned char nonce3[32]; - unsigned char nonce4[32]; - VG_UNDEF(nonce,32); - VG_UNDEF(nonce2,32); - VG_UNDEF(nonce3,32); - VG_UNDEF(nonce4,32); - CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); - VG_CHECK(nonce,32); - CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); - VG_CHECK(nonce2,32); - CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); - VG_CHECK(nonce3,32); - CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); - VG_CHECK(nonce4,32); - CHECK(memcmp(nonce, nonce2, 32) != 0); - CHECK(memcmp(nonce, nonce3, 32) != 0); - CHECK(memcmp(nonce, nonce4, 32) != 0); - CHECK(memcmp(nonce2, nonce3, 32) != 0); - CHECK(memcmp(nonce2, nonce4, 32) != 0); - CHECK(memcmp(nonce3, nonce4, 32) != 0); - } - - - /* Privkey export where pubkey is the point at infinity. */ - { - unsigned char privkey[300]; - unsigned char seckey[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, - }; - size_t outlen = 300; - CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); - outlen = 300; - CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); - } -} - -void run_ecdsa_edge_cases(void) { - test_ecdsa_edge_cases(); -} - -#ifdef ENABLE_OPENSSL_TESTS -EC_KEY *get_openssl_key(const unsigned char *key32) { - unsigned char privkey[300]; - size_t privkeylen; - const unsigned char* pbegin = privkey; - int compr = secp256k1_rand_bits(1); - EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); - CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); - CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); - CHECK(EC_KEY_check_key(ec_key)); - return ec_key; -} - -void test_ecdsa_openssl(void) { - secp256k1_gej qj; - secp256k1_ge q; - secp256k1_scalar sigr, sigs; - secp256k1_scalar one; - secp256k1_scalar msg2; - secp256k1_scalar key, msg; - EC_KEY *ec_key; - unsigned int sigsize = 80; - size_t secp_sigsize = 80; - unsigned char message[32]; - unsigned char signature[80]; - unsigned char key32[32]; - secp256k1_rand256_test(message); - secp256k1_scalar_set_b32(&msg, message, NULL); - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(key32, &key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); - secp256k1_ge_set_gej(&q, &qj); - ec_key = get_openssl_key(key32); - CHECK(ec_key != NULL); - CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); - CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg2, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); - - random_sign(&sigr, &sigs, &key, &msg, NULL); - CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); - CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); - - EC_KEY_free(ec_key); -} - -void run_ecdsa_openssl(void) { - int i; - for (i = 0; i < 10*count; i++) { - test_ecdsa_openssl(); - } -} -#endif - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/tests_impl.h" -#endif - -int main(int argc, char **argv) { - unsigned char seed16[16] = {0}; - unsigned char run32[32] = {0}; - /* find iteration count */ - if (argc > 1) { - count = strtol(argv[1], NULL, 0); - } - - /* find random seed */ - if (argc > 2) { - int pos = 0; - const char* ch = argv[2]; - while (pos < 16 && ch[0] != 0 && ch[1] != 0) { - unsigned short sh; - if (sscanf(ch, "%2hx", &sh)) { - seed16[pos] = sh; - } else { - break; - } - ch += 2; - pos++; - } - } else { - FILE *frand = fopen("/dev/urandom", "r"); - if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { - uint64_t t = time(NULL) * (uint64_t)1337; - seed16[0] ^= t; - seed16[1] ^= t >> 8; - seed16[2] ^= t >> 16; - seed16[3] ^= t >> 24; - seed16[4] ^= t >> 32; - seed16[5] ^= t >> 40; - seed16[6] ^= t >> 48; - seed16[7] ^= t >> 56; - } - fclose(frand); - } - secp256k1_rand_seed(seed16); - - printf("test count = %i\n", count); - printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); - - /* initialize */ - run_context_tests(); - ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - if (secp256k1_rand_bits(1)) { - secp256k1_rand256(run32); - CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); - } - - run_rand_bits(); - run_rand_int(); - - run_sha256_tests(); - run_hmac_sha256_tests(); - run_rfc6979_hmac_sha256_tests(); - -#ifndef USE_NUM_NONE - /* num tests */ - run_num_smalltests(); -#endif - - /* scalar tests */ - run_scalar_tests(); - - /* field tests */ - run_field_inv(); - run_field_inv_var(); - run_field_inv_all_var(); - run_field_misc(); - run_field_convert(); - run_sqr(); - run_sqrt(); - - /* group tests */ - run_ge(); - run_group_decompress(); - - /* ecmult tests */ - run_wnaf(); - run_point_times_order(); - run_ecmult_chain(); - run_ecmult_constants(); - run_ecmult_gen_blind(); - run_ecmult_const_tests(); - run_ec_combine(); - - /* endomorphism tests */ -#ifdef USE_ENDOMORPHISM - run_endomorphism_tests(); -#endif - - /* EC point parser test */ - run_ec_pubkey_parse_test(); - - /* EC key edge cases */ - run_eckey_edge_case_test(); - -#ifdef ENABLE_MODULE_ECDH - /* ecdh tests */ - run_ecdh_tests(); -#endif - - /* ecdsa tests */ - run_random_pubkeys(); - run_ecdsa_der_parse(); - run_ecdsa_sign_verify(); - run_ecdsa_end_to_end(); - run_ecdsa_edge_cases(); -#ifdef ENABLE_OPENSSL_TESTS - run_ecdsa_openssl(); -#endif - -#ifdef ENABLE_MODULE_SCHNORR - /* Schnorr tests */ - run_schnorr_tests(); -#endif - -#ifdef ENABLE_MODULE_RECOVERY - /* ECDSA pubkey recovery tests */ - run_recovery_tests(); -#endif - - secp256k1_rand256(run32); - printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); - - /* shutdown */ - secp256k1_context_destroy(ctx); - - printf("no problems found\n"); - return 0; -} diff --git a/builder/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c b/builder/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c deleted file mode 100644 index b040bb073..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c +++ /dev/null @@ -1,470 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include - -#include - -#undef USE_ECMULT_STATIC_PRECOMPUTATION - -#ifndef EXHAUSTIVE_TEST_ORDER -/* see group_impl.h for allowable values */ -#define EXHAUSTIVE_TEST_ORDER 13 -#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ -#endif - -#include "include/secp256k1.h" -#include "group.h" -#include "secp256k1.c" -#include "testrand_impl.h" - -#ifdef ENABLE_MODULE_RECOVERY -#include "src/modules/recovery/main_impl.h" -#include "include/secp256k1_recovery.h" -#endif - -/** stolen from tests.c */ -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); - CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); -} - -void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { - secp256k1_fe z2s; - secp256k1_fe u1, u2, s1, s2; - CHECK(a->infinity == b->infinity); - if (a->infinity) { - return; - } - /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ - secp256k1_fe_sqr(&z2s, &b->z); - secp256k1_fe_mul(&u1, &a->x, &z2s); - u2 = b->x; secp256k1_fe_normalize_weak(&u2); - secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); - s2 = b->y; secp256k1_fe_normalize_weak(&s2); - CHECK(secp256k1_fe_equal_var(&u1, &u2)); - CHECK(secp256k1_fe_equal_var(&s1, &s2)); -} - -void random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { - return; - } - } while(1); -} -/** END stolen from tests.c */ - -int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, - const unsigned char *key32, const unsigned char *algo16, - void *data, unsigned int attempt) { - secp256k1_scalar s; - int *idata = data; - (void)msg32; - (void)key32; - (void)algo16; - /* Some nonces cannot be used because they'd cause s and/or r to be zero. - * The signing function has retry logic here that just re-calls the nonce - * function with an increased `attempt`. So if attempt > 0 this means we - * need to change the nonce to avoid an infinite loop. */ - if (attempt > 0) { - *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; - } - secp256k1_scalar_set_int(&s, *idata); - secp256k1_scalar_get_b32(nonce32, &s); - return 1; -} - -#ifdef USE_ENDOMORPHISM -void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { - int i; - for (i = 0; i < order; i++) { - secp256k1_ge res; - secp256k1_ge_mul_lambda(&res, &group[i]); - ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); - } -} -#endif - -void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j; - - /* Sanity-check (and check infinity functions) */ - CHECK(secp256k1_ge_is_infinity(&group[0])); - CHECK(secp256k1_gej_is_infinity(&groupj[0])); - for (i = 1; i < order; i++) { - CHECK(!secp256k1_ge_is_infinity(&group[i])); - CHECK(!secp256k1_gej_is_infinity(&groupj[i])); - } - - /* Check all addition formulae */ - for (j = 0; j < order; j++) { - secp256k1_fe fe_inv; - secp256k1_fe_inv(&fe_inv, &groupj[j].z); - for (i = 0; i < order; i++) { - secp256k1_ge zless_gej; - secp256k1_gej tmp; - /* add_var */ - secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_ge */ - if (j > 0) { - secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - /* add_ge_var */ - secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); - ge_equals_gej(&group[(i + j) % order], &tmp); - /* add_zinv_var */ - zless_gej.infinity = groupj[j].infinity; - zless_gej.x = groupj[j].x; - zless_gej.y = groupj[j].y; - secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); - ge_equals_gej(&group[(i + j) % order], &tmp); - } - } - - /* Check doubling */ - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - if (i > 0) { - secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - secp256k1_gej_double_var(&tmp, &groupj[i], NULL); - ge_equals_gej(&group[(2 * i) % order], &tmp); - } - - /* Check negation */ - for (i = 1; i < order; i++) { - secp256k1_ge tmp; - secp256k1_gej tmpj; - secp256k1_ge_neg(&tmp, &group[i]); - ge_equals_ge(&group[order - i], &tmp); - secp256k1_gej_neg(&tmpj, &groupj[i]); - ge_equals_gej(&group[order - i], &tmpj); - } -} - -void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { - int i, j, r_log; - for (r_log = 1; r_log < order; r_log++) { - for (j = 0; j < order; j++) { - for (i = 0; i < order; i++) { - secp256k1_gej tmp; - secp256k1_scalar na, ng; - secp256k1_scalar_set_int(&na, i); - secp256k1_scalar_set_int(&ng, j); - - secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); - ge_equals_gej(&group[(i * r_log + j) % order], &tmp); - - if (i > 0) { - secp256k1_ecmult_const(&tmp, &group[i], &ng); - ge_equals_gej(&group[(i * j) % order], &tmp); - } - } - } - } -} - -void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { - secp256k1_fe x; - unsigned char x_bin[32]; - k %= EXHAUSTIVE_TEST_ORDER; - x = group[k].x; - secp256k1_fe_normalize(&x); - secp256k1_fe_get_b32(x_bin, &x); - secp256k1_scalar_set_b32(r, x_bin, NULL); -} - -void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* Verify by calling verify */ - secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - secp256k1_scalar_get_b32(msg32, &msg_s); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} - -void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } - - /* We would like to verify zero-knowledge here by counting how often every - * possible (s, r) tuple appears, but because the group order is larger - * than the field order, when coercing the x-values to scalar values, some - * appear more often than others, so we are actually not zero-knowledge. - * (This effect also appears in the real code, but the difference is on the - * order of 1/2^128th the field order, so the deviation is not useful to a - * computationally bounded attacker.) - */ -} - -#ifdef ENABLE_MODULE_RECOVERY -void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - int i, j, k; - - /* Loop */ - for (i = 1; i < order; i++) { /* message */ - for (j = 1; j < order; j++) { /* key */ - for (k = 1; k < order; k++) { /* nonce */ - const int starting_k = k; - secp256k1_fe r_dot_y_normalized; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - int expected_recid; - int recid; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - /* Check directly */ - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - /* In computing the recid, there is an overflow condition that is disabled in - * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value - * will exceed the group order, and our signing code always holds out for r - * values that don't overflow, so with a proper overflow check the tests would - * loop indefinitely. */ - r_dot_y_normalized = group[k].y; - secp256k1_fe_normalize(&r_dot_y_normalized); - /* Also the recovery id is flipped depending if we hit the low-s branch */ - if ((k * s) % order == (i + r * j) % order) { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; - } else { - expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; - } - CHECK(recid == expected_recid); - - /* Convert to a standard sig then check */ - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k); - CHECK(r == expected_r); - CHECK((k * s) % order == (i + r * j) % order || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } -} - -void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { - /* This is essentially a copy of test_exhaustive_verify, with recovery added */ - int s, r, msg, key; - for (s = 1; s < order; s++) { - for (r = 1; r < order; r++) { - for (msg = 1; msg < order; msg++) { - for (key = 1; key < order; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int recid = 0; - int k, should_verify; - unsigned char msg32[32]; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - secp256k1_scalar_get_b32(msg32, &msg_s); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < order; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* We would like to try recovering the pubkey and checking that it matches, - * but pubkey recovery is impossible in the exhaustive tests (the reason - * being that there are 12 nonzero r values, 12 nonzero points, and no - * overlap between the sets, so there are no valid signatures). */ - - /* Verify by converting to a standard signature and calling verify */ - secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} -#endif - -int main(void) { - int i; - secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; - secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; - - /* Build context */ - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - /* TODO set z = 1, then do num_tests runs with random z values */ - - /* Generate the entire group */ - secp256k1_gej_set_infinity(&groupj[0]); - secp256k1_ge_set_gej(&group[0], &groupj[0]); - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - /* Set a different random z-value for each Jacobian point */ - secp256k1_fe z; - random_fe(&z); - - secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); - secp256k1_ge_set_gej(&group[i], &groupj[i]); - secp256k1_gej_rescale(&groupj[i], &z); - - /* Verify against ecmult_gen */ - { - secp256k1_scalar scalar_i; - secp256k1_gej generatedj; - secp256k1_ge generated; - - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - secp256k1_ge_set_gej(&generated, &generatedj); - - CHECK(group[i].infinity == 0); - CHECK(generated.infinity == 0); - CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); - CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); - } - } - - /* Run the tests */ -#ifdef USE_ENDOMORPHISM - test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); -#endif - test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); - -#ifdef ENABLE_MODULE_RECOVERY - test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); - test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); -#endif - - secp256k1_context_destroy(ctx); - return 0; -} - diff --git a/builder/crypto/secp256k1/libsecp256k1/src/util.h b/builder/crypto/secp256k1/libsecp256k1/src/util.h deleted file mode 100644 index 4092a86c9..000000000 --- a/builder/crypto/secp256k1/libsecp256k1/src/util.h +++ /dev/null @@ -1,113 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_UTIL_H_ -#define _SECP256K1_UTIL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include -#include -#include - -typedef struct { - void (*fn)(const char *text, void* data); - const void* data; -} secp256k1_callback; - -static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { - cb->fn(text, (void*)cb->data); -} - -#ifdef DETERMINISTIC -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s\n", msg); \ - abort(); \ -} while(0); -#else -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ - abort(); \ -} while(0) -#endif - -#ifdef HAVE_BUILTIN_EXPECT -#define EXPECT(x,c) __builtin_expect((x),(c)) -#else -#define EXPECT(x,c) (x) -#endif - -#ifdef DETERMINISTIC -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed"); \ - } \ -} while(0) -#else -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed: " #cond); \ - } \ -} while(0) -#endif - -/* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#if defined(COVERAGE) -#define VERIFY_CHECK(check) -#define VERIFY_SETUP(stmt) -#elif defined(VERIFY) -#define VERIFY_CHECK CHECK -#define VERIFY_SETUP(stmt) do { stmt; } while(0) -#else -#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) -#define VERIFY_SETUP(stmt) -#endif - -static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { - void *ret = malloc(size); - if (ret == NULL) { - secp256k1_callback_call(cb, "Out of memory"); - } - return ret; -} - -/* Macro for restrict, when available and not in a VERIFY build. */ -#if defined(SECP256K1_BUILD) && defined(VERIFY) -# define SECP256K1_RESTRICT -#else -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(3,0) -# define SECP256K1_RESTRICT __restrict__ -# elif (defined(_MSC_VER) && _MSC_VER >= 1400) -# define SECP256K1_RESTRICT __restrict -# else -# define SECP256K1_RESTRICT -# endif -# else -# define SECP256K1_RESTRICT restrict -# endif -#endif - -#if defined(_WIN32) -# define I64FORMAT "I64d" -# define I64uFORMAT "I64u" -#else -# define I64FORMAT "lld" -# define I64uFORMAT "llu" -#endif - -#if defined(HAVE___INT128) -# if defined(__GNUC__) -# define SECP256K1_GNUC_EXT __extension__ -# else -# define SECP256K1_GNUC_EXT -# endif -SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; -#endif - -#endif diff --git a/builder/crypto/secp256k1/panic_cb.go b/builder/crypto/secp256k1/panic_cb.go deleted file mode 100644 index a30b04f51..000000000 --- a/builder/crypto/secp256k1/panic_cb.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -//go:build !gofuzz && cgo -// +build !gofuzz,cgo - -package secp256k1 - -import "C" -import "unsafe" - -// Callbacks for converting libsecp256k1 internal faults into -// recoverable Go panics. - -//export secp256k1GoPanicIllegal -func secp256k1GoPanicIllegal(msg *C.char, data unsafe.Pointer) { - panic("illegal argument: " + C.GoString(msg)) -} - -//export secp256k1GoPanicError -func secp256k1GoPanicError(msg *C.char, data unsafe.Pointer) { - panic("internal error: " + C.GoString(msg)) -} diff --git a/builder/crypto/secp256k1/scalar_mult_cgo.go b/builder/crypto/secp256k1/scalar_mult_cgo.go deleted file mode 100644 index 8afa9d023..000000000 --- a/builder/crypto/secp256k1/scalar_mult_cgo.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -//go:build !gofuzz && cgo -// +build !gofuzz,cgo - -package secp256k1 - -import ( - "math/big" - "unsafe" -) - -/* - -#include "libsecp256k1/include/secp256k1.h" - -extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar); - -*/ -import "C" - -func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { - // Ensure scalar is exactly 32 bytes. We pad always, even if - // scalar is 32 bytes long, to avoid a timing side channel. - if len(scalar) > 32 { - panic("can't handle scalars > 256 bits") - } - // NOTE: potential timing issue - padded := make([]byte, 32) - copy(padded[32-len(scalar):], scalar) - scalar = padded - - // Do the multiplication in C, updating point. - point := make([]byte, 64) - readBits(Bx, point[:32]) - readBits(By, point[32:]) - - pointPtr := (*C.uchar)(unsafe.Pointer(&point[0])) - scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0])) - res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr) - - // Unpack the result and clear temporaries. - x := new(big.Int).SetBytes(point[:32]) - y := new(big.Int).SetBytes(point[32:]) - for i := range point { - point[i] = 0 - } - for i := range padded { - scalar[i] = 0 - } - if res != 1 { - return nil, nil - } - return x, y -} diff --git a/builder/crypto/secp256k1/scalar_mult_nocgo.go b/builder/crypto/secp256k1/scalar_mult_nocgo.go deleted file mode 100644 index 22f53ac6a..000000000 --- a/builder/crypto/secp256k1/scalar_mult_nocgo.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -//go:build gofuzz || !cgo -// +build gofuzz !cgo - -package secp256k1 - -import "math/big" - -func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { - panic("ScalarMult is not available when secp256k1 is built without cgo") -} diff --git a/builder/crypto/secp256k1/secp256.go b/builder/crypto/secp256k1/secp256.go deleted file mode 100644 index 61abc1eaf..000000000 --- a/builder/crypto/secp256k1/secp256.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -//go:build !gofuzz && cgo -// +build !gofuzz,cgo - -// Package secp256k1 wraps the bitcoin secp256k1 C library. -package secp256k1 - -/* -#cgo CFLAGS: -I./libsecp256k1 -#cgo CFLAGS: -I./libsecp256k1/src/ - -#ifdef __SIZEOF_INT128__ -# define HAVE___INT128 -# define USE_FIELD_5X52 -# define USE_SCALAR_4X64 -#else -# define USE_FIELD_10X26 -# define USE_SCALAR_8X32 -#endif - -#ifndef NDEBUG -# define NDEBUG -#endif - -#define USE_ENDOMORPHISM -#define USE_NUM_NONE -#define USE_FIELD_INV_BUILTIN -#define USE_SCALAR_INV_BUILTIN -#include "./libsecp256k1/src/secp256k1.c" -#include "./libsecp256k1/src/modules/recovery/main_impl.h" -#include "ext.h" - -typedef void (*callbackFunc) (const char* msg, void* data); -extern void secp256k1GoPanicIllegal(const char* msg, void* data); -extern void secp256k1GoPanicError(const char* msg, void* data); -*/ -import "C" - -import ( - "errors" - "math/big" - "unsafe" -) - -var context *C.secp256k1_context - -func init() { - // around 20 ms on a modern CPU. - context = C.secp256k1_context_create_sign_verify() - C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil) - C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil) -} - -var ( - ErrInvalidMsgLen = errors.New("invalid message length, need 32 bytes") - ErrInvalidSignatureLen = errors.New("invalid signature length") - ErrInvalidRecoveryID = errors.New("invalid signature recovery id") - ErrInvalidKey = errors.New("invalid private key") - ErrInvalidPubkey = errors.New("invalid public key") - ErrSignFailed = errors.New("signing failed") - ErrRecoverFailed = errors.New("recovery failed") -) - -// Sign creates a recoverable ECDSA signature. -// The produced signature is in the 65-byte [R || S || V] format where V is 0 or 1. -// -// The caller is responsible for ensuring that msg cannot be chosen -// directly by an attacker. It is usually preferable to use a cryptographic -// hash function on any input before handing it to this function. -func Sign(msg []byte, seckey []byte) ([]byte, error) { - if len(msg) != 32 { - return nil, ErrInvalidMsgLen - } - if len(seckey) != 32 { - return nil, ErrInvalidKey - } - seckeydata := (*C.uchar)(unsafe.Pointer(&seckey[0])) - if C.secp256k1_ec_seckey_verify(context, seckeydata) != 1 { - return nil, ErrInvalidKey - } - - var ( - msgdata = (*C.uchar)(unsafe.Pointer(&msg[0])) - noncefunc = C.secp256k1_nonce_function_rfc6979 - sigstruct C.secp256k1_ecdsa_recoverable_signature - ) - if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, nil) == 0 { - return nil, ErrSignFailed - } - - var ( - sig = make([]byte, 65) - sigdata = (*C.uchar)(unsafe.Pointer(&sig[0])) - recid C.int - ) - C.secp256k1_ecdsa_recoverable_signature_serialize_compact(context, sigdata, &recid, &sigstruct) - sig[64] = byte(recid) // add back recid to get 65 bytes sig - return sig, nil -} - -// RecoverPubkey returns the public key of the signer. -// msg must be the 32-byte hash of the message to be signed. -// sig must be a 65-byte compact ECDSA signature containing the -// recovery id as the last element. -func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) { - if len(msg) != 32 { - return nil, ErrInvalidMsgLen - } - if err := checkSignature(sig); err != nil { - return nil, err - } - - var ( - pubkey = make([]byte, 65) - sigdata = (*C.uchar)(unsafe.Pointer(&sig[0])) - msgdata = (*C.uchar)(unsafe.Pointer(&msg[0])) - ) - if C.secp256k1_ext_ecdsa_recover(context, (*C.uchar)(unsafe.Pointer(&pubkey[0])), sigdata, msgdata) == 0 { - return nil, ErrRecoverFailed - } - return pubkey, nil -} - -// VerifySignature checks that the given pubkey created signature over message. -// The signature should be in [R || S] format. -func VerifySignature(pubkey, msg, signature []byte) bool { - if len(msg) != 32 || len(signature) != 64 || len(pubkey) == 0 { - return false - } - sigdata := (*C.uchar)(unsafe.Pointer(&signature[0])) - msgdata := (*C.uchar)(unsafe.Pointer(&msg[0])) - keydata := (*C.uchar)(unsafe.Pointer(&pubkey[0])) - return C.secp256k1_ext_ecdsa_verify(context, sigdata, msgdata, keydata, C.size_t(len(pubkey))) != 0 -} - -// DecompressPubkey parses a public key in the 33-byte compressed format. -// It returns non-nil coordinates if the public key is valid. -func DecompressPubkey(pubkey []byte) (x, y *big.Int) { - if len(pubkey) != 33 { - return nil, nil - } - var ( - pubkeydata = (*C.uchar)(unsafe.Pointer(&pubkey[0])) - pubkeylen = C.size_t(len(pubkey)) - out = make([]byte, 65) - outdata = (*C.uchar)(unsafe.Pointer(&out[0])) - outlen = C.size_t(len(out)) - ) - if C.secp256k1_ext_reencode_pubkey(context, outdata, outlen, pubkeydata, pubkeylen) == 0 { - return nil, nil - } - return new(big.Int).SetBytes(out[1:33]), new(big.Int).SetBytes(out[33:]) -} - -// CompressPubkey encodes a public key to 33-byte compressed format. -func CompressPubkey(x, y *big.Int) []byte { - var ( - pubkey = S256().Marshal(x, y) - pubkeydata = (*C.uchar)(unsafe.Pointer(&pubkey[0])) - pubkeylen = C.size_t(len(pubkey)) - out = make([]byte, 33) - outdata = (*C.uchar)(unsafe.Pointer(&out[0])) - outlen = C.size_t(len(out)) - ) - if C.secp256k1_ext_reencode_pubkey(context, outdata, outlen, pubkeydata, pubkeylen) == 0 { - panic("libsecp256k1 error") - } - return out -} - -func checkSignature(sig []byte) error { - if len(sig) != 65 { - return ErrInvalidSignatureLen - } - if sig[64] >= 4 { - return ErrInvalidRecoveryID - } - return nil -} diff --git a/builder/crypto/secp256k1/secp256_test.go b/builder/crypto/secp256k1/secp256_test.go deleted file mode 100644 index 74408d06d..000000000 --- a/builder/crypto/secp256k1/secp256_test.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found in -// the LICENSE file. - -//go:build !gofuzz && cgo -// +build !gofuzz,cgo - -package secp256k1 - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "encoding/hex" - "io" - "testing" -) - -const TestCount = 1000 - -func generateKeyPair() (pubkey, privkey []byte) { - key, err := ecdsa.GenerateKey(S256(), rand.Reader) - if err != nil { - panic(err) - } - pubkey = elliptic.Marshal(S256(), key.X, key.Y) - - privkey = make([]byte, 32) - blob := key.D.Bytes() - copy(privkey[32-len(blob):], blob) - - return pubkey, privkey -} - -func csprngEntropy(n int) []byte { - buf := make([]byte, n) - if _, err := io.ReadFull(rand.Reader, buf); err != nil { - panic("reading from crypto/rand failed: " + err.Error()) - } - return buf -} - -func randSig() []byte { - sig := csprngEntropy(65) - sig[32] &= 0x70 - sig[64] %= 4 - return sig -} - -// tests for malleability -// highest bit of signature ECDSA s value must be 0, in the 33th byte -func compactSigCheck(t *testing.T, sig []byte) { - var b = int(sig[32]) - if b < 0 { - t.Errorf("highest bit is negative: %d", b) - } - if ((b >> 7) == 1) != ((b & 0x80) == 0x80) { - t.Errorf("highest bit: %d bit >> 7: %d", b, b>>7) - } - if (b & 0x80) == 0x80 { - t.Errorf("highest bit: %d bit & 0x80: %d", b, b&0x80) - } -} - -func TestSignatureValidity(t *testing.T) { - pubkey, seckey := generateKeyPair() - msg := csprngEntropy(32) - sig, err := Sign(msg, seckey) - if err != nil { - t.Errorf("signature error: %s", err) - } - compactSigCheck(t, sig) - if len(pubkey) != 65 { - t.Errorf("pubkey length mismatch: want: 65 have: %d", len(pubkey)) - } - if len(seckey) != 32 { - t.Errorf("seckey length mismatch: want: 32 have: %d", len(seckey)) - } - if len(sig) != 65 { - t.Errorf("sig length mismatch: want: 65 have: %d", len(sig)) - } - recid := int(sig[64]) - if recid > 4 || recid < 0 { - t.Errorf("sig recid mismatch: want: within 0 to 4 have: %d", int(sig[64])) - } -} - -func TestInvalidRecoveryID(t *testing.T) { - _, seckey := generateKeyPair() - msg := csprngEntropy(32) - sig, _ := Sign(msg, seckey) - sig[64] = 99 - _, err := RecoverPubkey(msg, sig) - if err != ErrInvalidRecoveryID { - t.Fatalf("got %q, want %q", err, ErrInvalidRecoveryID) - } -} - -func TestSignAndRecover(t *testing.T) { - pubkey1, seckey := generateKeyPair() - msg := csprngEntropy(32) - sig, err := Sign(msg, seckey) - if err != nil { - t.Errorf("signature error: %s", err) - } - pubkey2, err := RecoverPubkey(msg, sig) - if err != nil { - t.Errorf("recover error: %s", err) - } - if !bytes.Equal(pubkey1, pubkey2) { - t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) - } -} - -func TestSignDeterministic(t *testing.T) { - _, seckey := generateKeyPair() - msg := make([]byte, 32) - copy(msg, "hi there") - - sig1, err := Sign(msg, seckey) - if err != nil { - t.Fatal(err) - } - sig2, err := Sign(msg, seckey) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(sig1, sig2) { - t.Fatal("signatures not equal") - } -} - -func TestRandomMessagesWithSameKey(t *testing.T) { - pubkey, seckey := generateKeyPair() - keys := func() ([]byte, []byte) { - return pubkey, seckey - } - signAndRecoverWithRandomMessages(t, keys) -} - -func TestRandomMessagesWithRandomKeys(t *testing.T) { - keys := func() ([]byte, []byte) { - pubkey, seckey := generateKeyPair() - return pubkey, seckey - } - signAndRecoverWithRandomMessages(t, keys) -} - -func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) { - for i := 0; i < TestCount; i++ { - pubkey1, seckey := keys() - msg := csprngEntropy(32) - sig, err := Sign(msg, seckey) - if err != nil { - t.Fatalf("signature error: %s", err) - } - if sig == nil { - t.Fatal("signature is nil") - } - compactSigCheck(t, sig) - - // TODO: why do we flip around the recovery id? - sig[len(sig)-1] %= 4 - - pubkey2, err := RecoverPubkey(msg, sig) - if err != nil { - t.Fatalf("recover error: %s", err) - } - if pubkey2 == nil { - t.Error("pubkey is nil") - } - if !bytes.Equal(pubkey1, pubkey2) { - t.Fatalf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) - } - } -} - -func TestRecoveryOfRandomSignature(t *testing.T) { - pubkey1, _ := generateKeyPair() - msg := csprngEntropy(32) - - for i := 0; i < TestCount; i++ { - // recovery can sometimes work, but if so should always give wrong pubkey - pubkey2, _ := RecoverPubkey(msg, randSig()) - if bytes.Equal(pubkey1, pubkey2) { - t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) - } - } -} - -func TestRandomMessagesAgainstValidSig(t *testing.T) { - pubkey1, seckey := generateKeyPair() - msg := csprngEntropy(32) - sig, _ := Sign(msg, seckey) - - for i := 0; i < TestCount; i++ { - msg = csprngEntropy(32) - pubkey2, _ := RecoverPubkey(msg, sig) - // recovery can sometimes work, but if so should always give wrong pubkey - if bytes.Equal(pubkey1, pubkey2) { - t.Fatalf("iteration: %d: pubkey mismatch: do NOT want %x: ", i, pubkey2) - } - } -} - -// Useful when the underlying libsecp256k1 API changes to quickly -// check only recover function without use of signature function -func TestRecoverSanity(t *testing.T) { - msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") - sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301") - pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652") - pubkey2, err := RecoverPubkey(msg, sig) - if err != nil { - t.Fatalf("recover error: %s", err) - } - if !bytes.Equal(pubkey1, pubkey2) { - t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2) - } -} - -func BenchmarkSign(b *testing.B) { - _, seckey := generateKeyPair() - msg := csprngEntropy(32) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - Sign(msg, seckey) - } -} - -func BenchmarkRecover(b *testing.B) { - msg := csprngEntropy(32) - _, seckey := generateKeyPair() - sig, _ := Sign(msg, seckey) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - RecoverPubkey(msg, sig) - } -} diff --git a/builder/crypto/signature_cgo.go b/builder/crypto/signature_cgo.go deleted file mode 100644 index 2339e5201..000000000 --- a/builder/crypto/signature_cgo.go +++ /dev/null @@ -1,89 +0,0 @@ -// 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 . - -//go:build !nacl && !js && cgo && !gofuzz -// +build !nacl,!js,cgo,!gofuzz - -package crypto - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/crypto/secp256k1" -) - -// Ecrecover returns the uncompressed public key that created the given signature. -func Ecrecover(hash, sig []byte) ([]byte, error) { - return secp256k1.RecoverPubkey(hash, sig) -} - -// SigToPub returns the public key that created the given signature. -func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { - s, err := Ecrecover(hash, sig) - if err != nil { - return nil, err - } - - x, y := elliptic.Unmarshal(S256(), s) - return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil -} - -// Sign calculates an ECDSA signature. -// -// This function is susceptible to chosen plaintext attacks that can leak -// information about the private key that is used for signing. Callers must -// be aware that the given digest cannot be chosen by an adversary. Common -// solution is to hash any input before calculating the signature. -// -// The produced signature is in the [R || S || V] format where V is 0 or 1. -func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - if len(digestHash) != DigestLength { - return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash)) - } - seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8) - defer zeroBytes(seckey) - return secp256k1.Sign(digestHash, seckey) -} - -// VerifySignature checks that the given public key created signature over digest. -// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. -// The signature should have the 64 byte [R || S] format. -func VerifySignature(pubkey, digestHash, signature []byte) bool { - return secp256k1.VerifySignature(pubkey, digestHash, signature) -} - -// DecompressPubkey parses a public key in the 33-byte compressed format. -func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) { - x, y := secp256k1.DecompressPubkey(pubkey) - if x == nil { - return nil, errors.New("invalid public key") - } - return &ecdsa.PublicKey{X: x, Y: y, Curve: S256()}, nil -} - -// CompressPubkey encodes a public key to the 33-byte compressed format. -func CompressPubkey(pubkey *ecdsa.PublicKey) []byte { - return secp256k1.CompressPubkey(pubkey.X, pubkey.Y) -} - -// S256 returns an instance of the secp256k1 curve. -func S256() elliptic.Curve { - return secp256k1.S256() -} diff --git a/builder/crypto/signature_nocgo.go b/builder/crypto/signature_nocgo.go deleted file mode 100644 index 6d628d758..000000000 --- a/builder/crypto/signature_nocgo.go +++ /dev/null @@ -1,152 +0,0 @@ -// 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 . - -//go:build nacl || js || !cgo || gofuzz -// +build nacl js !cgo gofuzz - -package crypto - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "errors" - "fmt" - - "github.com/btcsuite/btcd/btcec/v2" - btc_ecdsa "github.com/btcsuite/btcd/btcec/v2/ecdsa" -) - -// Ecrecover returns the uncompressed public key that created the given signature. -func Ecrecover(hash, sig []byte) ([]byte, error) { - pub, err := sigToPub(hash, sig) - if err != nil { - return nil, err - } - bytes := pub.SerializeUncompressed() - return bytes, err -} - -func sigToPub(hash, sig []byte) (*btcec.PublicKey, error) { - if len(sig) != SignatureLength { - return nil, errors.New("invalid signature") - } - // Convert to btcec input format with 'recovery id' v at the beginning. - btcsig := make([]byte, SignatureLength) - btcsig[0] = sig[RecoveryIDOffset] + 27 - copy(btcsig[1:], sig) - - pub, _, err := btc_ecdsa.RecoverCompact(btcsig, hash) - return pub, err -} - -// SigToPub returns the public key that created the given signature. -func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { - pub, err := sigToPub(hash, sig) - if err != nil { - return nil, err - } - return pub.ToECDSA(), nil -} - -// Sign calculates an ECDSA signature. -// -// This function is susceptible to chosen plaintext attacks that can leak -// information about the private key that is used for signing. Callers must -// be aware that the given hash cannot be chosen by an adversary. Common -// solution is to hash any input before calculating the signature. -// -// The produced signature is in the [R || S || V] format where V is 0 or 1. -func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { - if len(hash) != 32 { - return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) - } - if prv.Curve != btcec.S256() { - return nil, errors.New("private key curve is not secp256k1") - } - // ecdsa.PrivateKey -> btcec.PrivateKey - var priv btcec.PrivateKey - if overflow := priv.Key.SetByteSlice(prv.D.Bytes()); overflow || priv.Key.IsZero() { - return nil, errors.New("invalid private key") - } - defer priv.Zero() - sig, err := btc_ecdsa.SignCompact(&priv, hash, false) // ref uncompressed pubkey - if err != nil { - return nil, err - } - // Convert to Ethereum signature format with 'recovery id' v at the end. - v := sig[0] - 27 - copy(sig, sig[1:]) - sig[RecoveryIDOffset] = v - return sig, nil -} - -// VerifySignature checks that the given public key created signature over hash. -// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. -// The signature should have the 64 byte [R || S] format. -func VerifySignature(pubkey, hash, signature []byte) bool { - if len(signature) != 64 { - return false - } - var r, s btcec.ModNScalar - if r.SetByteSlice(signature[:32]) { - return false // overflow - } - if s.SetByteSlice(signature[32:]) { - return false - } - sig := btc_ecdsa.NewSignature(&r, &s) - key, err := btcec.ParsePubKey(pubkey) - if err != nil { - return false - } - // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. - if s.IsOverHalfOrder() { - return false - } - return sig.Verify(hash, key) -} - -// DecompressPubkey parses a public key in the 33-byte compressed format. -func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) { - if len(pubkey) != 33 { - return nil, errors.New("invalid compressed public key length") - } - key, err := btcec.ParsePubKey(pubkey) - if err != nil { - return nil, err - } - return key.ToECDSA(), nil -} - -// CompressPubkey encodes a public key to the 33-byte compressed format. The -// provided PublicKey must be valid. Namely, the coordinates must not be larger -// than 32 bytes each, they must be less than the field prime, and it must be a -// point on the secp256k1 curve. This is the case for a PublicKey constructed by -// elliptic.Unmarshal (see UnmarshalPubkey), or by ToECDSA and ecdsa.GenerateKey -// when constructing a PrivateKey. -func CompressPubkey(pubkey *ecdsa.PublicKey) []byte { - // NOTE: the coordinates may be validated with - // btcec.ParsePubKey(FromECDSAPub(pubkey)) - var x, y btcec.FieldVal - x.SetByteSlice(pubkey.X.Bytes()) - y.SetByteSlice(pubkey.Y.Bytes()) - return btcec.NewPublicKey(&x, &y).SerializeCompressed() -} - -// S256 returns an instance of the secp256k1 curve. -func S256() elliptic.Curve { - return btcec.S256() -} diff --git a/builder/crypto/signature_test.go b/builder/crypto/signature_test.go deleted file mode 100644 index aecff76bf..000000000 --- a/builder/crypto/signature_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// 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 crypto - -import ( - "bytes" - "crypto/ecdsa" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" -) - -var ( - testmsg = hexutil.MustDecode("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008") - testsig = hexutil.MustDecode("0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301") - testpubkey = hexutil.MustDecode("0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652") - testpubkeyc = hexutil.MustDecode("0x02e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a") -) - -func TestEcrecover(t *testing.T) { - pubkey, err := Ecrecover(testmsg, testsig) - if err != nil { - t.Fatalf("recover error: %s", err) - } - if !bytes.Equal(pubkey, testpubkey) { - t.Errorf("pubkey mismatch: want: %x have: %x", testpubkey, pubkey) - } -} - -func TestVerifySignature(t *testing.T) { - sig := testsig[:len(testsig)-1] // remove recovery id - if !VerifySignature(testpubkey, testmsg, sig) { - t.Errorf("can't verify signature with uncompressed key") - } - if !VerifySignature(testpubkeyc, testmsg, sig) { - t.Errorf("can't verify signature with compressed key") - } - - if VerifySignature(nil, testmsg, sig) { - t.Errorf("signature valid with no key") - } - if VerifySignature(testpubkey, nil, sig) { - t.Errorf("signature valid with no message") - } - if VerifySignature(testpubkey, testmsg, nil) { - t.Errorf("nil signature valid") - } - if VerifySignature(testpubkey, testmsg, append(common.CopyBytes(sig), 1, 2, 3)) { - t.Errorf("signature valid with extra bytes at the end") - } - if VerifySignature(testpubkey, testmsg, sig[:len(sig)-2]) { - t.Errorf("signature valid even though it's incomplete") - } - wrongkey := common.CopyBytes(testpubkey) - wrongkey[10]++ - if VerifySignature(wrongkey, testmsg, sig) { - t.Errorf("signature valid with with wrong public key") - } -} - -// This test checks that VerifySignature rejects malleable signatures with s > N/2. -func TestVerifySignatureMalleable(t *testing.T) { - sig := hexutil.MustDecode("0x638a54215d80a6713c8d523a6adc4e6e73652d859103a36b700851cb0e61b66b8ebfc1a610c57d732ec6e0a8f06a9a7a28df5051ece514702ff9cdff0b11f454") - key := hexutil.MustDecode("0x03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") - msg := hexutil.MustDecode("0xd301ce462d3e639518f482c7f03821fec1e602018630ce621e1e7851c12343a6") - if VerifySignature(key, msg, sig) { - t.Error("VerifySignature returned true for malleable signature") - } -} - -func TestDecompressPubkey(t *testing.T) { - key, err := DecompressPubkey(testpubkeyc) - if err != nil { - t.Fatal(err) - } - if uncompressed := FromECDSAPub(key); !bytes.Equal(uncompressed, testpubkey) { - t.Errorf("wrong public key result: got %x, want %x", uncompressed, testpubkey) - } - if _, err := DecompressPubkey(nil); err == nil { - t.Errorf("no error for nil pubkey") - } - if _, err := DecompressPubkey(testpubkeyc[:5]); err == nil { - t.Errorf("no error for incomplete pubkey") - } - if _, err := DecompressPubkey(append(common.CopyBytes(testpubkeyc), 1, 2, 3)); err == nil { - t.Errorf("no error for pubkey with extra bytes at the end") - } -} - -func TestCompressPubkey(t *testing.T) { - key := &ecdsa.PublicKey{ - Curve: S256(), - X: math.MustParseBig256("0xe32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a"), - Y: math.MustParseBig256("0x0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652"), - } - compressed := CompressPubkey(key) - if !bytes.Equal(compressed, testpubkeyc) { - t.Errorf("wrong public key result: got %x, want %x", compressed, testpubkeyc) - } -} - -func TestPubkeyRandom(t *testing.T) { - const runs = 200 - - for i := 0; i < runs; i++ { - key, err := GenerateKey() - if err != nil { - t.Fatalf("iteration %d: %v", i, err) - } - pubkey2, err := DecompressPubkey(CompressPubkey(&key.PublicKey)) - if err != nil { - t.Fatalf("iteration %d: %v", i, err) - } - if !reflect.DeepEqual(key.PublicKey, *pubkey2) { - t.Fatalf("iteration %d: keys not equal", i) - } - } -} - -func BenchmarkEcrecoverSignature(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := Ecrecover(testmsg, testsig); err != nil { - b.Fatal("ecrecover error", err) - } - } -} - -func BenchmarkVerifySignature(b *testing.B) { - sig := testsig[:len(testsig)-1] // remove recovery id - for i := 0; i < b.N; i++ { - if !VerifySignature(testpubkey, testmsg, sig) { - b.Fatal("verify error") - } - } -} - -func BenchmarkDecompressPubkey(b *testing.B) { - for i := 0; i < b.N; i++ { - if _, err := DecompressPubkey(testpubkeyc); err != nil { - b.Fatal(err) - } - } -} diff --git a/builder/crypto/signify/signify.go b/builder/crypto/signify/signify.go deleted file mode 100644 index eb029e509..000000000 --- a/builder/crypto/signify/signify.go +++ /dev/null @@ -1,100 +0,0 @@ -// 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 . - -// signFile reads the contents of an input file and signs it (in armored format) -// with the key provided, placing the signature into the output file. - -package signify - -import ( - "bytes" - "crypto/ed25519" - "encoding/base64" - "errors" - "fmt" - "os" - "strings" - "time" -) - -var ( - errInvalidKeyHeader = errors.New("incorrect key header") - errInvalidKeyLength = errors.New("invalid, key length != 104") -) - -func parsePrivateKey(key string) (k ed25519.PrivateKey, header []byte, keyNum []byte, err error) { - keydata, err := base64.StdEncoding.DecodeString(key) - if err != nil { - return nil, nil, nil, err - } - if len(keydata) != 104 { - return nil, nil, nil, errInvalidKeyLength - } - if string(keydata[:2]) != "Ed" { - return nil, nil, nil, errInvalidKeyHeader - } - return keydata[40:], keydata[:2], keydata[32:40], nil -} - -// SignFile creates a signature of the input file. -// -// This accepts base64 keys in the format created by the 'signify' tool. -// The signature is written to the 'output' file. -func SignFile(input string, output string, key string, untrustedComment string, trustedComment string) error { - // Pre-check comments and ensure they're set to something. - if strings.IndexByte(untrustedComment, '\n') >= 0 { - return errors.New("untrusted comment must not contain newline") - } - if strings.IndexByte(trustedComment, '\n') >= 0 { - return errors.New("trusted comment must not contain newline") - } - if untrustedComment == "" { - untrustedComment = "verify with " + input + ".pub" - } - if trustedComment == "" { - trustedComment = fmt.Sprintf("timestamp:%d", time.Now().Unix()) - } - - filedata, err := os.ReadFile(input) - if err != nil { - return err - } - skey, header, keyNum, err := parsePrivateKey(key) - if err != nil { - return err - } - - // Create the main data signature. - rawSig := ed25519.Sign(skey, filedata) - var dataSig []byte - dataSig = append(dataSig, header...) - dataSig = append(dataSig, keyNum...) - dataSig = append(dataSig, rawSig...) - - // Create the comment signature. - var commentSigInput []byte - commentSigInput = append(commentSigInput, rawSig...) - commentSigInput = append(commentSigInput, []byte(trustedComment)...) - commentSig := ed25519.Sign(skey, commentSigInput) - - // Create the output file. - var out = new(bytes.Buffer) - fmt.Fprintln(out, "untrusted comment:", untrustedComment) - fmt.Fprintln(out, base64.StdEncoding.EncodeToString(dataSig)) - fmt.Fprintln(out, "trusted comment:", trustedComment) - fmt.Fprintln(out, base64.StdEncoding.EncodeToString(commentSig)) - return os.WriteFile(output, out.Bytes(), 0644) -} diff --git a/builder/crypto/signify/signify_fuzz.go b/builder/crypto/signify/signify_fuzz.go deleted file mode 100644 index 457af044d..000000000 --- a/builder/crypto/signify/signify_fuzz.go +++ /dev/null @@ -1,150 +0,0 @@ -// 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 . - -//go:build gofuzz -// +build gofuzz - -package signify - -import ( - "bufio" - "fmt" - "log" - "os" - "os/exec" - - fuzz "github.com/google/gofuzz" - "github.com/jedisct1/go-minisign" -) - -func Fuzz(data []byte) int { - if len(data) < 32 { - return -1 - } - tmpFile, err := os.CreateTemp("", "") - if err != nil { - panic(err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - testSecKey, testPubKey := createKeyPair() - // Create message - tmpFile.Write(data) - if err = tmpFile.Close(); err != nil { - panic(err) - } - // Fuzz comments - var untrustedComment string - var trustedComment string - f := fuzz.NewFromGoFuzz(data) - f.Fuzz(&untrustedComment) - f.Fuzz(&trustedComment) - fmt.Printf("untrusted: %v\n", untrustedComment) - fmt.Printf("trusted: %v\n", trustedComment) - - err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, untrustedComment, trustedComment) - if err != nil { - panic(err) - } - defer os.Remove(tmpFile.Name() + ".sig") - - signify := "signify" - path := os.Getenv("SIGNIFY") - if path != "" { - signify = path - } - - _, err := exec.LookPath(signify) - if err != nil { - panic(err) - } - - // Write the public key into the file to pass it as - // an argument to signify-openbsd - pubKeyFile, err := os.CreateTemp("", "") - if err != nil { - panic(err) - } - defer os.Remove(pubKeyFile.Name()) - defer pubKeyFile.Close() - pubKeyFile.WriteString("untrusted comment: signify public key\n") - pubKeyFile.WriteString(testPubKey) - pubKeyFile.WriteString("\n") - - cmd := exec.Command(signify, "-V", "-p", pubKeyFile.Name(), "-x", tmpFile.Name()+".sig", "-m", tmpFile.Name()) - if output, err := cmd.CombinedOutput(); err != nil { - panic(fmt.Sprintf("could not verify the file: %v, output: \n%s", err, output)) - } - - // Verify the signature using a golang library - sig, err := minisign.NewSignatureFromFile(tmpFile.Name() + ".sig") - if err != nil { - panic(err) - } - - pKey, err := minisign.NewPublicKey(testPubKey) - if err != nil { - panic(err) - } - - valid, err := pKey.VerifyFromFile(tmpFile.Name(), sig) - if err != nil { - panic(err) - } - if !valid { - panic("invalid signature") - } - return 1 -} - -func getKey(fileS string) (string, error) { - file, err := os.Open(fileS) - if err != nil { - log.Fatal(err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - // Discard the first line - scanner.Scan() - scanner.Scan() - return scanner.Text(), scanner.Err() -} - -func createKeyPair() (string, string) { - // Create key and put it in correct format - tmpKey, err := os.CreateTemp("", "") - if err != nil { - panic(err) - } - defer os.Remove(tmpKey.Name()) - defer os.Remove(tmpKey.Name() + ".pub") - defer os.Remove(tmpKey.Name() + ".sec") - cmd := exec.Command("signify", "-G", "-n", "-p", tmpKey.Name()+".pub", "-s", tmpKey.Name()+".sec") - if output, err := cmd.CombinedOutput(); err != nil { - panic(fmt.Sprintf("could not verify the file: %v, output: \n%s", err, output)) - } - secKey, err := getKey(tmpKey.Name() + ".sec") - if err != nil { - panic(err) - } - pubKey, err := getKey(tmpKey.Name() + ".pub") - if err != nil { - panic(err) - } - return secKey, pubKey -} diff --git a/builder/crypto/signify/signify_test.go b/builder/crypto/signify/signify_test.go deleted file mode 100644 index 9bac2c825..000000000 --- a/builder/crypto/signify/signify_test.go +++ /dev/null @@ -1,144 +0,0 @@ -// 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 . - -// signFile reads the contents of an input file and signs it (in armored format) -// with the key provided, placing the signature into the output file. - -package signify - -import ( - "crypto/rand" - "os" - "testing" - - "github.com/jedisct1/go-minisign" -) - -var ( - testSecKey = "RWRCSwAAAABVN5lr2JViGBN8DhX3/Qb/0g0wBdsNAR/APRW2qy9Fjsfr12sK2cd3URUFis1jgzQzaoayK8x4syT4G3Gvlt9RwGIwUYIQW/0mTeI+ECHu1lv5U4Wa2YHEPIesVPyRm5M=" - testPubKey = "RWTAPRW2qy9FjsBiMFGCEFv9Jk3iPhAh7tZb+VOFmtmBxDyHrFT8kZuT" -) - -func TestSignify(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - data := make([]byte, 1024) - rand.Read(data) - tmpFile.Write(data) - - if err = tmpFile.Close(); err != nil { - t.Fatal(err) - } - - err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "clé", "croissants") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name() + ".sig") - - // Verify the signature using a golang library - sig, err := minisign.NewSignatureFromFile(tmpFile.Name() + ".sig") - if err != nil { - t.Fatal(err) - } - - pKey, err := minisign.NewPublicKey(testPubKey) - if err != nil { - t.Fatal(err) - } - - valid, err := pKey.VerifyFromFile(tmpFile.Name(), sig) - if err != nil { - t.Fatal(err) - } - if !valid { - t.Fatal("invalid signature") - } -} - -func TestSignifyTrustedCommentTooManyLines(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - data := make([]byte, 1024) - rand.Read(data) - tmpFile.Write(data) - - if err = tmpFile.Close(); err != nil { - t.Fatal(err) - } - - err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "crois\nsants") - if err == nil || err.Error() == "" { - t.Fatalf("should have errored on a multi-line trusted comment, got %v", err) - } - defer os.Remove(tmpFile.Name() + ".sig") -} - -func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - data := make([]byte, 1024) - rand.Read(data) - tmpFile.Write(data) - - if err = tmpFile.Close(); err != nil { - t.Fatal(err) - } - - err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "crois\rsants", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name() + ".sig") -} - -func TestSignifyTrustedCommentEmpty(t *testing.T) { - tmpFile, err := os.CreateTemp("", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name()) - defer tmpFile.Close() - - data := make([]byte, 1024) - rand.Read(data) - tmpFile.Write(data) - - if err = tmpFile.Close(); err != nil { - t.Fatal(err) - } - - err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpFile.Name() + ".sig") -} diff --git a/builder/docs/audits/2017-04-25_Geth-audit_Truesec.pdf b/builder/docs/audits/2017-04-25_Geth-audit_Truesec.pdf deleted file mode 100644 index 702dc9956..000000000 Binary files a/builder/docs/audits/2017-04-25_Geth-audit_Truesec.pdf and /dev/null differ diff --git a/builder/docs/audits/2018-09-14_Clef-audit_NCC.pdf b/builder/docs/audits/2018-09-14_Clef-audit_NCC.pdf deleted file mode 100644 index 1a5c66f17..000000000 Binary files a/builder/docs/audits/2018-09-14_Clef-audit_NCC.pdf and /dev/null differ diff --git a/builder/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf b/builder/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf deleted file mode 100644 index 5d834e827..000000000 Binary files a/builder/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf and /dev/null differ diff --git a/builder/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf b/builder/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf deleted file mode 100644 index f490e1d0e..000000000 Binary files a/builder/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf and /dev/null differ diff --git a/builder/docs/builder/builder-diagram.png b/builder/docs/builder/builder-diagram.png deleted file mode 100644 index d1b4e66f7..000000000 Binary files a/builder/docs/builder/builder-diagram.png and /dev/null differ diff --git a/builder/docs/postmortems/2021-08-22-split-postmortem.md b/builder/docs/postmortems/2021-08-22-split-postmortem.md deleted file mode 100644 index 0986f00b6..000000000 --- a/builder/docs/postmortems/2021-08-22-split-postmortem.md +++ /dev/null @@ -1,266 +0,0 @@ -# Minority split 2021-08-27 post mortem - -This is a post-mortem concerning the minority split that occurred on Ethereum mainnet on block [13107518](https://etherscan.io/block/13107518), at which a minority chain split occurred. - -## Timeline - - -- 2021-08-17: Guido Vranken submitted a bounty report. Investigation started, root cause identified, patch variations discussed. -- 2021-08-18: Made public announcement over twitter about upcoming security release upcoming Tuesday. Downstream projects were also notified about the upcoming patch-release. -- 2021-08-24: Released [v1.10.8](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.8) containing the fix on Tuesday morning (CET). Erigon released [v2021.08.04](https://github.com/ledgerwatch/erigon/releases/tag/v2021.08.04). -- 2021-08-27: At 12:50:07 UTC, issue exploited. Analysis started roughly 30m later, - - - -## Bounty report - -### 2021-08-17 RETURNDATA corruption via datacopy - -On 2021-08-17, Guido Vranken submitted a report to bounty@ethereum.org. This coincided with a geth-meetup in Berlin, so the geth team could fairly quickly analyse the issue. - -He submitted a proof of concept which called the `dataCopy` precompile, where the input slice and output slice were overlapping but shifted. Doing a `copy` where the `src` and `dest` overlaps is not a problem in itself, however, the `returnData`slice was _also_ using the same memory as a backing-array. - -#### Technical details - -During CALL-variants, `geth` does not copy the input. This was changed at one point, to avoid a DoS attack reported by Hubert Ritzdorf, to avoid copying data a lot on repeated `CALL`s -- essentially combating a DoS via `malloc`. Further, the datacopy precompile also does not copy the data, but just returns the same slice. This is fine so far. - -After the execution of `dataCopy`, we copy the `ret` into the designated memory area, and this is what causes a problem. Because we're copying a slice of memory over a slice of memory, and this operation modifies (shifts) the data in the source -- the `ret`. So this means we wind up with corrupted returndata. - - -``` -1. Calling datacopy - - memory: [0, 1, 2, 3, 4] - in (mem[0:4]) : [0,1,2,3] - out (mem[1:5]): [1,2,3,4] - -2. dataCopy returns - - returndata (==in, mem[0:4]): [0,1,2,3] - -3. Copy in -> out - - => memory: [0,0,1,2,3] - => returndata: [0,0,1,2] -``` - - -#### Summary - -A memory-corruption bug within the EVM can cause a consensus error, where vulnerable nodes obtain a different `stateRoot` when processing a maliciously crafted transaction. This, in turn, would lead to the chain being split: mainnet splitting in two forks. - -#### Handling - -On the evening of 17th, we discussed options on how to handle it. We made a state test to reproduce the issue, and verified that neither `openethereum`, `nethermind` nor `besu` were affected by the same vulnerability, and started a full-sync with a patched version of `geth`. - -It was decided that in this specific instance, it would be possible to make a public announcement and a patch release: - -- The fix can be made pretty 'generically', e.g. always copying data on input to precompiles. -- The flaw is pretty difficult to find, given a generic fix in the call. The attacker needs to figure out that it concerns the precompiles, specifically the datcopy, and that it concerns the `RETURNDATA` buffer rather than the regular memory, and lastly the special circumstances to trigger it (overlapping but shifted input/output). - -Since we had merged the removal of `ETH65`, if the entire network were to upgrade, then nodes which have not yet implemented `ETH66` would be cut off from the network. After further discussions, we decided to: - -- Announce an upcoming security release on Tuesday (August 24th), via Twitter and official channels, plus reach out to downstream projects. -- Temporarily revert the `ETH65`-removal. -- Place the fix into the PR optimizing the jumpdest analysis [233381](https://github.com/ethereum/go-ethereum/pull/23381). -- After 4-8 weeks, release details about the vulnerability. - - -## Exploit - -At block [13107518](https://etherscan.io/block/13107518), mined at Aug-27-2021 12:50:07 PM +UTC, a minority chain split occurred. The discord user @AlexSSD7 notified the allcoredevs-channel on the Eth R&D discord, on Aug 27 13:09 UTC. - - -At 14:09 UTC, it was confirmed that the transaction `0x1cb6fb36633d270edefc04d048145b4298e67b8aa82a9e5ec4aa1435dd770ce4` had triggered the bug, leading to a minority-split of the chain. The term 'minority split' means that the majority of miners continued to mine on the correct chain. - -At 14:17 UTC, @mhswende tweeted out about the issue [2]. - -The attack was sent from an account funded from Tornado cash. - -It was also found that the same attack had been carried out on the BSC chain at roughly the same time -- at a block mined [12 minutes earlier](https://bscscan.com/tx/0xf667f820631f6adbd04a4c92274374034a3e41fa9057dc42cb4e787535136dce), at Aug-27-2021 12:38:30 PM +UTC. - -The blocks on the 'bad' chain were investigated, and Tim Beiko reached out to those mining operators on the minority chain who could be identified via block extradata. - - -## Lessons learned - - -### Disclosure decision - -The geth-team have an official policy regarding [vulnerability disclosure](https://geth.ethereum.org/docs/developers/geth-developer/disclosures). - -> The primary goal for the Geth team is the health of the Ethereum network as a whole, and the decision whether or not to publish details about a serious vulnerability boils down to minimizing the risk and/or impact of discovery and exploitation. - -In this case, it was decided that public pre-announce + patch would likely lead to sufficient update-window for a critical mass of nodes/miners to upgrade in time before it could be exploited. In hindsight, this was a dangerous decision, and it's unlikely that the same decision would be reached were a similar incident to happen again. - - -### Disclosure path - -Several subprojects were informed about the upcoming security patch: - -- Polygon/Matic -- MEV -- Avalanche -- Erigon -- BSC -- EWF -- Quorum -- ETC -- xDAI - -However, some were 'lost', and only notified later - -- Optimism -- Summa -- Harmony - -Action point: create a low-volume geth-announce@ethereum.org email list where dependent projects/operators can receive public announcements. -- This has been done. If you wish to receive release- and security announcements, sign up [here](https://groups.google.com/a/ethereum.org/g/geth-announce/about) - -### Fork monitoring - -The fork monitor behaved 'ok' during the incident, but had to be restarted during the evening. - -Action point: improve the resiliency of the forkmon, which is currently not performing great when many nodes are connected. - -Action point: enable push-based alerts to be sent from the forkmon, to speed up the fork detection. - - -## Links - -- [1] https://twitter.com/go_ethereum/status/1428051458763763721 -- [2] https://twitter.com/mhswende/status/1431259601530458112 - - -## Appendix - -### Subprojects - - -The projects were sent variations of the following text: -``` -We have identified a security issue with go-ethereum, and will issue a -new release (v1.10.8) on Tuesday next week. - -At this point, we will not disclose details about the issue, but -recommend downstream/dependent projects to be ready to take actions to -upgrade to the latest go-ethereum codebase. More information about the -issue will be disclosed at a later date. - -https://twitter.com/go_ethereum/status/1428051458763763721 - -``` -### Patch - -```diff -diff --git a/core/vm/instructions.go b/core/vm/instructions.go -index f7ef2f900e..6c8c6e6e6f 100644 ---- a/core/vm/instructions.go -+++ b/core/vm/instructions.go -@@ -669,6 +669,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt - } - stack.push(&temp) - if err == nil || err == ErrExecutionReverted { -+ ret = common.CopyBytes(ret) - scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) - } - scope.Contract.Gas += returnGas -@@ -703,6 +704,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ - } - stack.push(&temp) - if err == nil || err == ErrExecutionReverted { -+ ret = common.CopyBytes(ret) - scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) - } - scope.Contract.Gas += returnGas -@@ -730,6 +732,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext - } - stack.push(&temp) - if err == nil || err == ErrExecutionReverted { -+ ret = common.CopyBytes(ret) - scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) - } - scope.Contract.Gas += returnGas -@@ -757,6 +760,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) - } - stack.push(&temp) - if err == nil || err == ErrExecutionReverted { -+ ret = common.CopyBytes(ret) - scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) - } - scope.Contract.Gas += returnGas -diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go -index 9cf0c4e2c1..9fb83799c9 100644 ---- a/core/vm/interpreter.go -+++ b/core/vm/interpreter.go -@@ -262,7 +262,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( - // if the operation clears the return data (e.g. it has returning data) - // set the last return to the result of the operation. - if operation.returns { -- in.returnData = common.CopyBytes(res) -+ in.returnData = res - } - - switch { -``` - -### Statetest to test for the issue - -```json -{ - "trigger-issue": { - "env": { - "currentCoinbase": "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "currentDifficulty": "0x20000", - "currentGasLimit": "0x26e1f476fe1e22", - "currentNumber": "0x1", - "currentTimestamp": "0x3e8", - "previousHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "pre": { - "0x00000000000000000000000000000000000000bb": { - "code": "0x6001600053600260015360036002536004600353600560045360066005536006600260066000600060047f7ef0367e633852132a0ebbf70eb714015dd44bc82e1e55a96ef1389c999c1bcaf13d600060003e596000208055", - "storage": {}, - "balance": "0x5", - "nonce": "0x0" - }, - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "code": "0x", - "storage": {}, - "balance": "0xffffffff", - "nonce": "0x0" - } - }, - "transaction": { - "gasPrice": "0x1", - "nonce": "0x0", - "to": "0x00000000000000000000000000000000000000bb", - "data": [ - "0x" - ], - "gasLimit": [ - "0x7a1200" - ], - "value": [ - "0x01" - ], - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - }, - "out": "0x", - "post": { - "Berlin": [ - { - "hash": "2a38a040bab1e1fa499253d98b2fd363e5756ecc52db47dd59af7116c068368c", - "logs": "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "indexes": { - "data": 0, - "gas": 0, - "value": 0 - } - } - ] - } - } -} -``` - diff --git a/builder/eth/api.go b/builder/eth/api.go deleted file mode 100644 index 44e934fd0..000000000 --- a/builder/eth/api.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 eth - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// EthereumAPI provides an API to access Ethereum full node-related information. -type EthereumAPI struct { - e *Ethereum -} - -// NewEthereumAPI creates a new Ethereum protocol API for full nodes. -func NewEthereumAPI(e *Ethereum) *EthereumAPI { - return &EthereumAPI{e} -} - -// Etherbase is the address that mining rewards will be sent to. -func (api *EthereumAPI) Etherbase() (common.Address, error) { - return api.e.Etherbase() -} - -// Coinbase is the address that mining rewards will be sent to (alias for Etherbase). -func (api *EthereumAPI) Coinbase() (common.Address, error) { - return api.Etherbase() -} - -// Hashrate returns the POW hashrate. -func (api *EthereumAPI) Hashrate() hexutil.Uint64 { - return hexutil.Uint64(api.e.Miner().Hashrate()) -} - -// Mining returns an indication if this node is currently mining. -func (api *EthereumAPI) Mining() bool { - return api.e.IsMining() -} diff --git a/builder/eth/api_admin.go b/builder/eth/api_admin.go deleted file mode 100644 index 4a3ccb84e..000000000 --- a/builder/eth/api_admin.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2023 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 eth - -import ( - "compress/gzip" - "errors" - "fmt" - "io" - "os" - "strings" - - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" -) - -// AdminAPI is the collection of Ethereum full node related APIs for node -// administration. -type AdminAPI struct { - eth *Ethereum -} - -// NewAdminAPI creates a new instance of AdminAPI. -func NewAdminAPI(eth *Ethereum) *AdminAPI { - return &AdminAPI{eth: eth} -} - -// ExportChain exports the current blockchain into a local file, -// or a range of blocks if first and last are non-nil. -func (api *AdminAPI) ExportChain(file string, first *uint64, last *uint64) (bool, error) { - if first == nil && last != nil { - return false, errors.New("last cannot be specified without first") - } - if first != nil && last == nil { - head := api.eth.BlockChain().CurrentHeader().Number.Uint64() - last = &head - } - if _, err := os.Stat(file); err == nil { - // File already exists. Allowing overwrite could be a DoS vector, - // since the 'file' may point to arbitrary paths on the drive. - return false, errors.New("location would overwrite an existing file") - } - // Make sure we can create the file to export into - out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) - if err != nil { - return false, err - } - defer out.Close() - - var writer io.Writer = out - if strings.HasSuffix(file, ".gz") { - writer = gzip.NewWriter(writer) - defer writer.(*gzip.Writer).Close() - } - - // Export the blockchain - if first != nil { - if err := api.eth.BlockChain().ExportN(writer, *first, *last); err != nil { - return false, err - } - } else if err := api.eth.BlockChain().Export(writer); err != nil { - return false, err - } - return true, nil -} - -func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool { - for _, b := range bs { - if !chain.HasBlock(b.Hash(), b.NumberU64()) { - return false - } - } - - return true -} - -// ImportChain imports a blockchain from a local file. -func (api *AdminAPI) ImportChain(file string) (bool, error) { - // Make sure the can access the file to import - in, err := os.Open(file) - if err != nil { - return false, err - } - defer in.Close() - - var reader io.Reader = in - if strings.HasSuffix(file, ".gz") { - if reader, err = gzip.NewReader(reader); err != nil { - return false, err - } - } - - // Run actual the import in pre-configured batches - stream := rlp.NewStream(reader, 0) - - blocks, index := make([]*types.Block, 0, 2500), 0 - for batch := 0; ; batch++ { - // Load a batch of blocks from the input file - for len(blocks) < cap(blocks) { - block := new(types.Block) - if err := stream.Decode(block); err == io.EOF { - break - } else if err != nil { - return false, fmt.Errorf("block %d: failed to parse: %v", index, err) - } - // ignore the genesis block when importing blocks - if block.NumberU64() == 0 { - continue - } - blocks = append(blocks, block) - index++ - } - if len(blocks) == 0 { - break - } - - if hasAllBlocks(api.eth.BlockChain(), blocks) { - blocks = blocks[:0] - continue - } - // Import the batch and reset the buffer - if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil { - return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err) - } - blocks = blocks[:0] - } - return true, nil -} diff --git a/builder/eth/api_backend.go b/builder/eth/api_backend.go deleted file mode 100644 index 170218725..000000000 --- a/builder/eth/api_backend.go +++ /dev/null @@ -1,455 +0,0 @@ -// 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 eth - -import ( - "context" - "errors" - "math/big" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "github.com/google/uuid" -) - -// EthAPIBackend implements ethapi.Backend and tracers.Backend for full nodes -type EthAPIBackend struct { - extRPCEnabled bool - allowUnprotectedTxs bool - eth *Ethereum - gpo *gasprice.Oracle -} - -// ChainConfig returns the active chain configuration. -func (b *EthAPIBackend) ChainConfig() *params.ChainConfig { - return b.eth.blockchain.Config() -} - -func (b *EthAPIBackend) CurrentBlock() *types.Header { - return b.eth.blockchain.CurrentBlock() -} - -func (b *EthAPIBackend) SetHead(number uint64) { - b.eth.handler.downloader.Cancel() - b.eth.blockchain.SetHead(number) -} - -func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { - // Pending block is only known by the miner - if number == rpc.PendingBlockNumber { - block := b.eth.miner.PendingBlock() - if block == nil { - return nil, errors.New("pending block is not available") - } - return block.Header(), nil - } - // Otherwise resolve and return the block - if number == rpc.LatestBlockNumber { - return b.eth.blockchain.CurrentBlock(), nil - } - if number == rpc.FinalizedBlockNumber { - block := b.eth.blockchain.CurrentFinalBlock() - if block == nil { - return nil, errors.New("finalized block not found") - } - return block, nil - } - if number == rpc.SafeBlockNumber { - block := b.eth.blockchain.CurrentSafeBlock() - if block == nil { - return nil, errors.New("safe block not found") - } - return block, nil - } - return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil -} - -func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.HeaderByNumber(ctx, blockNr) - } - if hash, ok := blockNrOrHash.Hash(); ok { - header := b.eth.blockchain.GetHeaderByHash(hash) - if header == nil { - return nil, errors.New("header for hash not found") - } - if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { - return nil, errors.New("hash is not currently canonical") - } - return header, nil - } - return nil, errors.New("invalid arguments; neither block nor hash specified") -} - -func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return b.eth.blockchain.GetHeaderByHash(hash), nil -} - -func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { - // Pending block is only known by the miner - if number == rpc.PendingBlockNumber { - block := b.eth.miner.PendingBlock() - if block == nil { - return nil, errors.New("pending block is not available") - } - return block, nil - } - // Otherwise resolve and return the block - if number == rpc.LatestBlockNumber { - header := b.eth.blockchain.CurrentBlock() - return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil - } - if number == rpc.FinalizedBlockNumber { - header := b.eth.blockchain.CurrentFinalBlock() - if header == nil { - return nil, errors.New("finalized block not found") - } - return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil - } - if number == rpc.SafeBlockNumber { - header := b.eth.blockchain.CurrentSafeBlock() - if header == nil { - return nil, errors.New("safe block not found") - } - return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil - } - return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil -} - -func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return b.eth.blockchain.GetBlockByHash(hash), nil -} - -// GetBody returns body of a block. It does not resolve special block numbers. -func (b *EthAPIBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { - if number < 0 || hash == (common.Hash{}) { - return nil, errors.New("invalid arguments; expect hash and no special block numbers") - } - if body := b.eth.blockchain.GetBody(hash); body != nil { - return body, nil - } - return nil, errors.New("block body not found") -} - -func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.BlockByNumber(ctx, blockNr) - } - if hash, ok := blockNrOrHash.Hash(); ok { - header := b.eth.blockchain.GetHeaderByHash(hash) - if header == nil { - return nil, errors.New("header for hash not found") - } - if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { - return nil, errors.New("hash is not currently canonical") - } - block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64()) - if block == nil { - return nil, errors.New("header found, but block body is missing") - } - return block, nil - } - return nil, errors.New("invalid arguments; neither block nor hash specified") -} - -func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { - return b.eth.miner.PendingBlockAndReceipts() -} - -func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { - // Pending state is only known by the miner - if number == rpc.PendingBlockNumber { - block, state := b.eth.miner.Pending() - if block == nil || state == nil { - return nil, nil, errors.New("pending state is not available") - } - return state, block.Header(), nil - } - // Otherwise resolve the block number and return its state - header, err := b.HeaderByNumber(ctx, number) - if err != nil { - return nil, nil, err - } - if header == nil { - return nil, nil, errors.New("header not found") - } - stateDb, err := b.eth.BlockChain().StateAt(header.Root) - if err != nil { - return nil, nil, err - } - return stateDb, header, nil -} - -func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { - if blockNr, ok := blockNrOrHash.Number(); ok { - return b.StateAndHeaderByNumber(ctx, blockNr) - } - if hash, ok := blockNrOrHash.Hash(); ok { - header, err := b.HeaderByHash(ctx, hash) - if err != nil { - return nil, nil, err - } - if header == nil { - return nil, nil, errors.New("header for hash not found") - } - if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { - return nil, nil, errors.New("hash is not currently canonical") - } - stateDb, err := b.eth.BlockChain().StateAt(header.Root) - if err != nil { - return nil, nil, err - } - return stateDb, header, nil - } - return nil, nil, errors.New("invalid arguments; neither block nor hash specified") -} - -func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - return b.eth.blockchain.GetReceiptsByHash(hash), nil -} - -func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { - return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil -} - -func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { - if header := b.eth.blockchain.GetHeaderByHash(hash); header != nil { - return b.eth.blockchain.GetTd(hash, header.Number.Uint64()) - } - return nil -} - -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { - if vmConfig == nil { - vmConfig = b.eth.blockchain.GetVMConfig() - } - txContext := core.NewEVMTxContext(msg) - var context vm.BlockContext - if blockCtx != nil { - context = *blockCtx - } else { - context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) - } - return vm.NewEVM(context, txContext, state, b.ChainConfig(), *vmConfig) -} - -func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch) -} - -func (b *EthAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.eth.miner.SubscribePendingLogs(ch) -} - -func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - return b.eth.BlockChain().SubscribeChainEvent(ch) -} - -func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - return b.eth.BlockChain().SubscribeChainHeadEvent(ch) -} - -func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { - return b.eth.BlockChain().SubscribeChainSideEvent(ch) -} - -func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.eth.BlockChain().SubscribeLogsEvent(ch) -} - -func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction, private bool) error { - if private { - return b.eth.txPool.Add([]*types.Transaction{signedTx}, true, false, true)[0] - } else { - return b.eth.txPool.Add([]*types.Transaction{signedTx}, true, false, false)[0] - } -} - -func (b *EthAPIBackend) SendBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, uuid uuid.UUID, signingAddress common.Address, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash) error { - return b.eth.txPool.AddMevBundle(txs, big.NewInt(blockNumber.Int64()), uuid, signingAddress, minTimestamp, maxTimestamp, revertingTxHashes) -} - -func (b *EthAPIBackend) SendSBundle(ctx context.Context, sbundle *types.SBundle) error { - return b.eth.txPool.AddSBundle(sbundle) -} - -func (b *EthAPIBackend) CancelSBundles(ctx context.Context, hashes []common.Hash) { - b.eth.txPool.CancelSBundles(hashes) -} - -func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) { - pending := b.eth.txPool.Pending(txpool.PendingFilter{}) - var txs types.Transactions - for _, batch := range pending { - for _, lazy := range batch { - if tx := lazy.Resolve(); tx != nil { - txs = append(txs, tx) - } - } - } - return txs, nil -} - -func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction { - return b.eth.txPool.Get(hash) -} - -// GetTransaction retrieves the lookup along with the transaction itself associate -// with the given transaction hash. -// -// An error will be returned if the transaction is not found, and background -// indexing for transactions is still in progress. The error is used to indicate the -// scenario explicitly that the transaction might be reachable shortly. -// -// A null will be returned in the transaction is not found and background transaction -// indexing is already finished. The transaction is not existent from the perspective -// of node. -func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) { - lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash) - if err != nil { - return false, nil, common.Hash{}, 0, 0, err - } - if lookup == nil || tx == nil { - return false, nil, common.Hash{}, 0, 0, nil - } - return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil -} - -func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { - return b.eth.txPool.Nonce(addr), nil -} - -func (b *EthAPIBackend) Stats() (runnable int, blocked int) { - return b.eth.txPool.Stats() -} - -func (b *EthAPIBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { - return b.eth.txPool.Content() -} - -func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { - return b.eth.txPool.ContentFrom(addr) -} - -func (b *EthAPIBackend) TxPool() *txpool.TxPool { - return b.eth.txPool -} - -func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return b.eth.txPool.SubscribeTransactions(ch, true) -} - -func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress { - prog := b.eth.Downloader().Progress() - if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil { - prog.TxIndexFinishedBlocks = txProg.Indexed - prog.TxIndexRemainingBlocks = txProg.Remaining - } - return prog -} - -func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - return b.gpo.SuggestTipCap(ctx) -} - -func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) { - return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) -} - -func (b *EthAPIBackend) ChainDb() ethdb.Database { - return b.eth.ChainDb() -} - -func (b *EthAPIBackend) EventMux() *event.TypeMux { - return b.eth.EventMux() -} - -func (b *EthAPIBackend) AccountManager() *accounts.Manager { - return b.eth.AccountManager() -} - -func (b *EthAPIBackend) ExtRPCEnabled() bool { - return b.extRPCEnabled -} - -func (b *EthAPIBackend) UnprotectedAllowed() bool { - return b.allowUnprotectedTxs -} - -func (b *EthAPIBackend) RPCGasCap() uint64 { - return b.eth.config.RPCGasCap -} - -func (b *EthAPIBackend) RPCEVMTimeout() time.Duration { - return b.eth.config.RPCEVMTimeout -} - -func (b *EthAPIBackend) RPCTxFeeCap() float64 { - return b.eth.config.RPCTxFeeCap -} - -func (b *EthAPIBackend) BloomStatus() (uint64, uint64) { - sections, _, _ := b.eth.bloomIndexer.Sections() - return params.BloomBitsBlocks, sections -} - -func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { - for i := 0; i < bloomFilterThreads; i++ { - go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) - } -} - -func (b *EthAPIBackend) Engine() consensus.Engine { - return b.eth.engine -} - -func (b *EthAPIBackend) CurrentHeader() *types.Header { - return b.eth.blockchain.CurrentHeader() -} - -func (b *EthAPIBackend) Miner() *miner.Miner { - return b.eth.Miner() -} - -func (b *EthAPIBackend) StartMining() error { - return b.eth.StartMining() -} - -func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { - return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) -} - -func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { - return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) -} diff --git a/builder/eth/api_debug.go b/builder/eth/api_debug.go deleted file mode 100644 index 05010a396..000000000 --- a/builder/eth/api_debug.go +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2023 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 eth - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/trie" -) - -// DebugAPI is the collection of Ethereum full node APIs for debugging the -// protocol. -type DebugAPI struct { - eth *Ethereum -} - -// NewDebugAPI creates a new DebugAPI instance. -func NewDebugAPI(eth *Ethereum) *DebugAPI { - return &DebugAPI{eth: eth} -} - -// DumpBlock retrieves the entire state of the database at a given block. -func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { - opts := &state.DumpConfig{ - OnlyWithAddresses: true, - Max: AccountRangeMaxResults, // Sanity limit over RPC - } - if blockNr == rpc.PendingBlockNumber { - // If we're dumping the pending state, we need to request - // both the pending block as well as the pending state from - // the miner and operate on those - _, stateDb := api.eth.miner.Pending() - if stateDb == nil { - return state.Dump{}, errors.New("pending state is not available") - } - return stateDb.RawDump(opts), nil - } - var header *types.Header - switch blockNr { - case rpc.LatestBlockNumber: - header = api.eth.blockchain.CurrentBlock() - case rpc.FinalizedBlockNumber: - header = api.eth.blockchain.CurrentFinalBlock() - case rpc.SafeBlockNumber: - header = api.eth.blockchain.CurrentSafeBlock() - default: - block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) - if block == nil { - return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) - } - header = block.Header() - } - if header == nil { - return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) - } - stateDb, err := api.eth.BlockChain().StateAt(header.Root) - if err != nil { - return state.Dump{}, err - } - return stateDb.RawDump(opts), nil -} - -// Preimage is a debug API function that returns the preimage for a sha3 hash, if known. -func (api *DebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { - if preimage := rawdb.ReadPreimage(api.eth.ChainDb(), hash); preimage != nil { - return preimage, nil - } - return nil, errors.New("unknown preimage") -} - -// BadBlockArgs represents the entries in the list returned when bad blocks are queried. -type BadBlockArgs struct { - Hash common.Hash `json:"hash"` - Block map[string]interface{} `json:"block"` - RLP string `json:"rlp"` -} - -// GetBadBlocks returns a list of the last 'bad blocks' that the client has seen on the network -// and returns them as a JSON list of block hashes. -func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) { - var ( - blocks = rawdb.ReadAllBadBlocks(api.eth.chainDb) - results = make([]*BadBlockArgs, 0, len(blocks)) - ) - for _, block := range blocks { - var ( - blockRlp string - blockJSON map[string]interface{} - ) - if rlpBytes, err := rlp.EncodeToBytes(block); err != nil { - blockRlp = err.Error() // Hacky, but hey, it works - } else { - blockRlp = fmt.Sprintf("%#x", rlpBytes) - } - blockJSON = ethapi.RPCMarshalBlock(block, true, true, api.eth.APIBackend.ChainConfig()) - results = append(results, &BadBlockArgs{ - Hash: block.Hash(), - RLP: blockRlp, - Block: blockJSON, - }) - } - return results, nil -} - -// AccountRangeMaxResults is the maximum number of results to be returned per call -const AccountRangeMaxResults = 256 - -// AccountRange enumerates all accounts in the given block and start point in paging request -func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.Dump, error) { - var stateDb *state.StateDB - var err error - - if number, ok := blockNrOrHash.Number(); ok { - if number == rpc.PendingBlockNumber { - // If we're dumping the pending state, we need to request - // both the pending block as well as the pending state from - // the miner and operate on those - _, stateDb = api.eth.miner.Pending() - if stateDb == nil { - return state.Dump{}, errors.New("pending state is not available") - } - } else { - var header *types.Header - switch number { - case rpc.LatestBlockNumber: - header = api.eth.blockchain.CurrentBlock() - case rpc.FinalizedBlockNumber: - header = api.eth.blockchain.CurrentFinalBlock() - case rpc.SafeBlockNumber: - header = api.eth.blockchain.CurrentSafeBlock() - default: - block := api.eth.blockchain.GetBlockByNumber(uint64(number)) - if block == nil { - return state.Dump{}, fmt.Errorf("block #%d not found", number) - } - header = block.Header() - } - if header == nil { - return state.Dump{}, fmt.Errorf("block #%d not found", number) - } - stateDb, err = api.eth.BlockChain().StateAt(header.Root) - if err != nil { - return state.Dump{}, err - } - } - } else if hash, ok := blockNrOrHash.Hash(); ok { - block := api.eth.blockchain.GetBlockByHash(hash) - if block == nil { - return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex()) - } - stateDb, err = api.eth.BlockChain().StateAt(block.Root()) - if err != nil { - return state.Dump{}, err - } - } else { - return state.Dump{}, errors.New("either block number or block hash must be specified") - } - - opts := &state.DumpConfig{ - SkipCode: nocode, - SkipStorage: nostorage, - OnlyWithAddresses: !incompletes, - Start: start, - Max: uint64(maxResults), - } - if maxResults > AccountRangeMaxResults || maxResults <= 0 { - opts.Max = AccountRangeMaxResults - } - return stateDb.RawDump(opts), nil -} - -// StorageRangeResult is the result of a debug_storageRangeAt API call. -type StorageRangeResult struct { - Storage storageMap `json:"storage"` - NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie. -} - -type storageMap map[common.Hash]storageEntry - -type storageEntry struct { - Key *common.Hash `json:"key"` - Value common.Hash `json:"value"` -} - -// StorageRangeAt returns the storage at the given block height and transaction index. -func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) { - var block *types.Block - - block, err := api.eth.APIBackend.BlockByNumberOrHash(ctx, blockNrOrHash) - if err != nil { - return StorageRangeResult{}, err - } - if block == nil { - return StorageRangeResult{}, fmt.Errorf("block %v not found", blockNrOrHash) - } - _, _, statedb, release, err := api.eth.stateAtTransaction(ctx, block, txIndex, 0) - if err != nil { - return StorageRangeResult{}, err - } - defer release() - - return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult) -} - -func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) { - storageRoot := statedb.GetStorageRoot(address) - if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) { - return StorageRangeResult{}, nil // empty storage - } - id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot) - tr, err := trie.NewStateTrie(id, statedb.Database().TrieDB()) - if err != nil { - return StorageRangeResult{}, err - } - trieIt, err := tr.NodeIterator(start) - if err != nil { - return StorageRangeResult{}, err - } - it := trie.NewIterator(trieIt) - result := StorageRangeResult{Storage: storageMap{}} - for i := 0; i < maxResult && it.Next(); i++ { - _, content, _, err := rlp.Split(it.Value) - if err != nil { - return StorageRangeResult{}, err - } - e := storageEntry{Value: common.BytesToHash(content)} - if preimage := tr.GetKey(it.Key); preimage != nil { - preimage := common.BytesToHash(preimage) - e.Key = &preimage - } - result.Storage[common.BytesToHash(it.Key)] = e - } - // Add the 'next key' so clients can continue downloading. - if it.Next() { - next := common.BytesToHash(it.Key) - result.NextKey = &next - } - return result, nil -} - -// GetModifiedAccountsByNumber returns all accounts that have changed between the -// two blocks specified. A change is defined as a difference in nonce, balance, -// code hash, or storage hash. -// -// With one parameter, returns the list of accounts modified in the specified block. -func (api *DebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64) ([]common.Address, error) { - var startBlock, endBlock *types.Block - - startBlock = api.eth.blockchain.GetBlockByNumber(startNum) - if startBlock == nil { - return nil, fmt.Errorf("start block %x not found", startNum) - } - - if endNum == nil { - endBlock = startBlock - startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) - if startBlock == nil { - return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) - } - } else { - endBlock = api.eth.blockchain.GetBlockByNumber(*endNum) - if endBlock == nil { - return nil, fmt.Errorf("end block %d not found", *endNum) - } - } - return api.getModifiedAccounts(startBlock, endBlock) -} - -// GetModifiedAccountsByHash returns all accounts that have changed between the -// two blocks specified. A change is defined as a difference in nonce, balance, -// code hash, or storage hash. -// -// With one parameter, returns the list of accounts modified in the specified block. -func (api *DebugAPI) GetModifiedAccountsByHash(startHash common.Hash, endHash *common.Hash) ([]common.Address, error) { - var startBlock, endBlock *types.Block - startBlock = api.eth.blockchain.GetBlockByHash(startHash) - if startBlock == nil { - return nil, fmt.Errorf("start block %x not found", startHash) - } - - if endHash == nil { - endBlock = startBlock - startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) - if startBlock == nil { - return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) - } - } else { - endBlock = api.eth.blockchain.GetBlockByHash(*endHash) - if endBlock == nil { - return nil, fmt.Errorf("end block %x not found", *endHash) - } - } - return api.getModifiedAccounts(startBlock, endBlock) -} - -func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) { - if startBlock.Number().Uint64() >= endBlock.Number().Uint64() { - return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64()) - } - triedb := api.eth.BlockChain().TrieDB() - - oldTrie, err := trie.NewStateTrie(trie.StateTrieID(startBlock.Root()), triedb) - if err != nil { - return nil, err - } - newTrie, err := trie.NewStateTrie(trie.StateTrieID(endBlock.Root()), triedb) - if err != nil { - return nil, err - } - oldIt, err := oldTrie.NodeIterator([]byte{}) - if err != nil { - return nil, err - } - newIt, err := newTrie.NodeIterator([]byte{}) - if err != nil { - return nil, err - } - diff, _ := trie.NewDifferenceIterator(oldIt, newIt) - iter := trie.NewIterator(diff) - - var dirty []common.Address - for iter.Next() { - key := newTrie.GetKey(iter.Key) - if key == nil { - return nil, fmt.Errorf("no preimage found for hash %x", iter.Key) - } - dirty = append(dirty, common.BytesToAddress(key)) - } - return dirty, nil -} - -// GetAccessibleState returns the first number where the node has accessible -// state on disk. Note this being the post-state of that block and the pre-state -// of the next block. -// The (from, to) parameters are the sequence of blocks to search, which can go -// either forwards or backwards -func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) { - if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { - return 0, errors.New("state history is not yet available in path-based scheme") - } - db := api.eth.ChainDb() - var pivot uint64 - if p := rawdb.ReadLastPivotNumber(db); p != nil { - pivot = *p - log.Info("Found fast-sync pivot marker", "number", pivot) - } - var resolveNum = func(num rpc.BlockNumber) (uint64, error) { - // We don't have state for pending (-2), so treat it as latest - if num.Int64() < 0 { - block := api.eth.blockchain.CurrentBlock() - if block == nil { - return 0, errors.New("current block missing") - } - return block.Number.Uint64(), nil - } - return uint64(num.Int64()), nil - } - var ( - start uint64 - end uint64 - delta = int64(1) - lastLog time.Time - err error - ) - if start, err = resolveNum(from); err != nil { - return 0, err - } - if end, err = resolveNum(to); err != nil { - return 0, err - } - if start == end { - return 0, errors.New("from and to needs to be different") - } - if start > end { - delta = -1 - } - for i := int64(start); i != int64(end); i += delta { - if time.Since(lastLog) > 8*time.Second { - log.Info("Finding roots", "from", start, "to", end, "at", i) - lastLog = time.Now() - } - if i < int64(pivot) { - continue - } - h := api.eth.BlockChain().GetHeaderByNumber(uint64(i)) - if h == nil { - return 0, fmt.Errorf("missing header %d", i) - } - if ok, _ := api.eth.ChainDb().Has(h.Root[:]); ok { - return uint64(i), nil - } - } - return 0, errors.New("no state found") -} - -// SetTrieFlushInterval configures how often in-memory tries are persisted -// to disk. The value is in terms of block processing time, not wall clock. -// If the value is shorter than the block generation time, or even 0 or negative, -// the node will flush trie after processing each block (effectively archive mode). -func (api *DebugAPI) SetTrieFlushInterval(interval string) error { - if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { - return errors.New("trie flush interval is undefined for path-based scheme") - } - t, err := time.ParseDuration(interval) - if err != nil { - return err - } - api.eth.blockchain.SetTrieFlushInterval(t) - return nil -} - -// GetTrieFlushInterval gets the current value of in-memory trie flush interval -func (api *DebugAPI) GetTrieFlushInterval() (string, error) { - if api.eth.blockchain.TrieDB().Scheme() == rawdb.PathScheme { - return "", errors.New("trie flush interval is undefined for path-based scheme") - } - return api.eth.blockchain.GetTrieFlushInterval().String(), nil -} diff --git a/builder/eth/api_debug_test.go b/builder/eth/api_debug_test.go deleted file mode 100644 index 671e935be..000000000 --- a/builder/eth/api_debug_test.go +++ /dev/null @@ -1,222 +0,0 @@ -// 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 eth - -import ( - "bytes" - "fmt" - "reflect" - "strings" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/triedb" - "github.com/holiman/uint256" - "golang.org/x/exp/slices" -) - -var dumper = spew.ConfigState{Indent: " "} - -func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump { - result := statedb.RawDump(&state.DumpConfig{ - SkipCode: true, - SkipStorage: true, - OnlyWithAddresses: false, - Start: start.Bytes(), - Max: uint64(requestedNum), - }) - - if len(result.Accounts) != expectedNum { - t.Fatalf("expected %d results, got %d", expectedNum, len(result.Accounts)) - } - for addr, acc := range result.Accounts { - if strings.HasSuffix(addr, "pre") || acc.Address == nil { - t.Fatalf("account without prestate (address) returned: %v", addr) - } - if !statedb.Exist(*acc.Address) { - t.Fatalf("account not found in state %s", acc.Address.Hex()) - } - } - return result -} - -func TestAccountRange(t *testing.T) { - t.Parallel() - - var ( - statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true}) - sdb, _ = state.New(types.EmptyRootHash, statedb, nil) - addrs = [AccountRangeMaxResults * 2]common.Address{} - m = map[common.Address]bool{} - ) - - for i := range addrs { - hash := common.HexToHash(fmt.Sprintf("%x", i)) - addr := common.BytesToAddress(crypto.Keccak256Hash(hash.Bytes()).Bytes()) - addrs[i] = addr - sdb.SetBalance(addrs[i], uint256.NewInt(1)) - if _, ok := m[addr]; ok { - t.Fatalf("bad") - } else { - m[addr] = true - } - } - root, _ := sdb.Commit(0, true) - sdb, _ = state.New(root, statedb, nil) - - trie, err := statedb.OpenTrie(root) - if err != nil { - t.Fatal(err) - } - accountRangeTest(t, &trie, sdb, common.Hash{}, AccountRangeMaxResults/2, AccountRangeMaxResults/2) - // test pagination - firstResult := accountRangeTest(t, &trie, sdb, common.Hash{}, AccountRangeMaxResults, AccountRangeMaxResults) - secondResult := accountRangeTest(t, &trie, sdb, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults) - - hList := make([]common.Hash, 0) - for addr1, acc := range firstResult.Accounts { - // If address is non-available, then it makes no sense to compare - // them as they might be two different accounts. - if acc.Address == nil { - continue - } - if _, duplicate := secondResult.Accounts[addr1]; duplicate { - t.Fatalf("pagination test failed: results should not overlap") - } - hList = append(hList, crypto.Keccak256Hash(acc.Address.Bytes())) - } - // Test to see if it's possible to recover from the middle of the previous - // set and get an even split between the first and second sets. - slices.SortFunc(hList, common.Hash.Cmp) - middleH := hList[AccountRangeMaxResults/2] - middleResult := accountRangeTest(t, &trie, sdb, middleH, AccountRangeMaxResults, AccountRangeMaxResults) - missing, infirst, insecond := 0, 0, 0 - for h := range middleResult.Accounts { - if _, ok := firstResult.Accounts[h]; ok { - infirst++ - } else if _, ok := secondResult.Accounts[h]; ok { - insecond++ - } else { - missing++ - } - } - if missing != 0 { - t.Fatalf("%d hashes in the 'middle' set were neither in the first not the second set", missing) - } - if infirst != AccountRangeMaxResults/2 { - t.Fatalf("Imbalance in the number of first-test results: %d != %d", infirst, AccountRangeMaxResults/2) - } - if insecond != AccountRangeMaxResults/2 { - t.Fatalf("Imbalance in the number of second-test results: %d != %d", insecond, AccountRangeMaxResults/2) - } -} - -func TestEmptyAccountRange(t *testing.T) { - t.Parallel() - - var ( - statedb = state.NewDatabase(rawdb.NewMemoryDatabase()) - st, _ = state.New(types.EmptyRootHash, statedb, nil) - ) - // Commit(although nothing to flush) and re-init the statedb - st.Commit(0, true) - st, _ = state.New(types.EmptyRootHash, statedb, nil) - - results := st.RawDump(&state.DumpConfig{ - SkipCode: true, - SkipStorage: true, - OnlyWithAddresses: true, - Max: uint64(AccountRangeMaxResults), - }) - if bytes.Equal(results.Next, (common.Hash{}).Bytes()) { - t.Fatalf("Empty results should not return a second page") - } - if len(results.Accounts) != 0 { - t.Fatalf("Empty state should not return addresses: %v", results.Accounts) - } -} - -func TestStorageRangeAt(t *testing.T) { - t.Parallel() - - // Create a state where account 0x010000... has a few storage entries. - var ( - db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true}) - sdb, _ = state.New(types.EmptyRootHash, db, nil) - addr = common.Address{0x01} - keys = []common.Hash{ // hashes of Keys of storage - common.HexToHash("340dd630ad21bf010b4e676dbfa9ba9a02175262d1fa356232cfde6cb5b47ef2"), - common.HexToHash("426fcb404ab2d5d8e61a3d918108006bbb0a9be65e92235bb10eefbdb6dcd053"), - common.HexToHash("48078cfed56339ea54962e72c37c7f588fc4f8e5bc173827ba75cb10a63a96a5"), - common.HexToHash("5723d2c3a83af9b735e3b7f21531e5623d183a9095a56604ead41f3582fdfb75"), - } - storage = storageMap{ - keys[0]: {Key: &common.Hash{0x02}, Value: common.Hash{0x01}}, - keys[1]: {Key: &common.Hash{0x04}, Value: common.Hash{0x02}}, - keys[2]: {Key: &common.Hash{0x01}, Value: common.Hash{0x03}}, - keys[3]: {Key: &common.Hash{0x03}, Value: common.Hash{0x04}}, - } - ) - for _, entry := range storage { - sdb.SetState(addr, *entry.Key, entry.Value) - } - root, _ := sdb.Commit(0, false) - sdb, _ = state.New(root, db, nil) - - // Check a few combinations of limit and start/end. - tests := []struct { - start []byte - limit int - want StorageRangeResult - }{ - { - start: []byte{}, limit: 0, - want: StorageRangeResult{storageMap{}, &keys[0]}, - }, - { - start: []byte{}, limit: 100, - want: StorageRangeResult{storage, nil}, - }, - { - start: []byte{}, limit: 2, - want: StorageRangeResult{storageMap{keys[0]: storage[keys[0]], keys[1]: storage[keys[1]]}, &keys[2]}, - }, - { - start: []byte{0x00}, limit: 4, - want: StorageRangeResult{storage, nil}, - }, - { - start: []byte{0x40}, limit: 2, - want: StorageRangeResult{storageMap{keys[1]: storage[keys[1]], keys[2]: storage[keys[2]]}, &keys[3]}, - }, - } - for _, test := range tests { - result, err := storageRangeAt(sdb, root, addr, test.start, test.limit) - if err != nil { - t.Error(err) - } - if !reflect.DeepEqual(result, test.want) { - t.Fatalf("wrong result for range %#x.., limit %d:\ngot %s\nwant %s", - test.start, test.limit, dumper.Sdump(result), dumper.Sdump(&test.want)) - } - } -} diff --git a/builder/eth/api_miner.go b/builder/eth/api_miner.go deleted file mode 100644 index 764d0ae5e..000000000 --- a/builder/eth/api_miner.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2023 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 eth - -import ( - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// MinerAPI provides an API to control the miner. -type MinerAPI struct { - e *Ethereum -} - -// NewMinerAPI creates a new MinerAPI instance. -func NewMinerAPI(e *Ethereum) *MinerAPI { - return &MinerAPI{e} -} - -// Start starts the miner with the given number of threads. If threads is nil, -// the number of workers started is equal to the number of logical CPUs that are -// usable by this process. If mining is already running, this method adjust the -// number of threads allowed to use and updates the minimum price required by the -// transaction pool. -func (api *MinerAPI) Start() error { - return api.e.StartMining() -} - -// Stop terminates the miner, both at the consensus engine level as well as at -// the block creation level. -func (api *MinerAPI) Stop() { - api.e.StopMining() -} - -// SetExtra sets the extra data string that is included when this miner mines a block. -func (api *MinerAPI) SetExtra(extra string) (bool, error) { - if err := api.e.Miner().SetExtra([]byte(extra)); err != nil { - return false, err - } - return true, nil -} - -// SetGasPrice sets the minimum accepted gas price for the miner. -func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { - api.e.lock.Lock() - api.e.gasPrice = (*big.Int)(&gasPrice) - api.e.lock.Unlock() - - api.e.txPool.SetGasTip((*big.Int)(&gasPrice)) - api.e.Miner().SetGasTip((*big.Int)(&gasPrice)) - return true -} - -// SetGasLimit sets the gaslimit to target towards during mining. -func (api *MinerAPI) SetGasLimit(gasLimit hexutil.Uint64) bool { - api.e.Miner().SetGasCeil(uint64(gasLimit)) - return true -} - -// SetEtherbase sets the etherbase of the miner. -func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool { - api.e.SetEtherbase(etherbase) - return true -} - -// SetRecommitInterval updates the interval for miner sealing work recommitting. -func (api *MinerAPI) SetRecommitInterval(interval int) { - api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond) -} diff --git a/builder/eth/backend.go b/builder/eth/backend.go deleted file mode 100644 index 61d5d0f40..000000000 --- a/builder/eth/backend.go +++ /dev/null @@ -1,559 +0,0 @@ -// 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 eth implements the Ethereum protocol. -package eth - -import ( - "errors" - "fmt" - "math/big" - "runtime" - "sync" - - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/pruner" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/txpool/blobpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/internal/shutdowncheck" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/dnsdisc" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -// Config contains the configuration options of the ETH protocol. -// Deprecated: use ethconfig.Config instead. -type Config = ethconfig.Config - -// Ethereum implements the Ethereum full node service. -type Ethereum struct { - config *ethconfig.Config - - // Handlers - txPool *txpool.TxPool - - blockchain *core.BlockChain - handler *handler - ethDialCandidates enode.Iterator - snapDialCandidates enode.Iterator - merger *consensus.Merger - - // DB interfaces - chainDb ethdb.Database // Block chain database - - eventMux *event.TypeMux - engine consensus.Engine - accountManager *accounts.Manager - - bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests - bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports - closeBloomHandler chan struct{} - - APIBackend *EthAPIBackend - - miner *miner.Miner - gasPrice *big.Int - etherbase common.Address - - networkID uint64 - netRPCService *ethapi.NetAPI - - p2pServer *p2p.Server - - lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) - - shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully -} - -// New creates a new Ethereum object (including the -// initialisation of the common Ethereum object) -func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { - // Ensure configuration values are compatible and sane - if config.SyncMode == downloader.LightSync { - return nil, errors.New("can't run eth.Ethereum in light sync mode, light mode has been deprecated") - } - if !config.SyncMode.IsValid() { - return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) - } - if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(common.Big0) <= 0 { - log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice) - config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) - } - if config.NoPruning && config.TrieDirtyCache > 0 { - if config.SnapshotCache > 0 { - config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 - config.SnapshotCache += config.TrieDirtyCache * 2 / 5 - } else { - config.TrieCleanCache += config.TrieDirtyCache - } - config.TrieDirtyCache = 0 - } - log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) - - // Assemble the Ethereum object - chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false) - if err != nil { - return nil, err - } - scheme, err := rawdb.ParseStateScheme(config.StateScheme, chainDb) - if err != nil { - return nil, err - } - // Try to recover offline state pruning only in hash-based. - if scheme == rawdb.HashScheme { - if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil { - log.Error("Failed to recover state", "error", err) - } - } - // Transfer mining-related config to the ethash config. - chainConfig, err := core.LoadChainConfig(chainDb, config.Genesis) - if err != nil { - return nil, err - } - engine, err := ethconfig.CreateConsensusEngine(chainConfig, chainDb) - if err != nil { - return nil, err - } - networkID := config.NetworkId - if networkID == 0 { - networkID = chainConfig.ChainID.Uint64() - } - eth := &Ethereum{ - config: config, - merger: consensus.NewMerger(chainDb), - chainDb: chainDb, - eventMux: stack.EventMux(), - accountManager: stack.AccountManager(), - engine: engine, - closeBloomHandler: make(chan struct{}), - networkID: networkID, - gasPrice: config.Miner.GasPrice, - etherbase: config.Miner.Etherbase, - bloomRequests: make(chan chan *bloombits.Retrieval), - bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), - p2pServer: stack.Server(), - shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb), - } - bcVersion := rawdb.ReadDatabaseVersion(chainDb) - var dbVer = "" - if bcVersion != nil { - dbVer = fmt.Sprintf("%d", *bcVersion) - } - log.Info("Initialising Ethereum protocol", "network", networkID, "dbversion", dbVer) - - if !config.SkipBcVersionCheck { - if bcVersion != nil && *bcVersion > core.BlockChainVersion { - return nil, fmt.Errorf("database version is v%d, Geth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) - } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { - if bcVersion != nil { // only print warning on upgrade, not on init - log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) - } - rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) - } - } - var ( - vmConfig = vm.Config{ - EnablePreimageRecording: config.EnablePreimageRecording, - } - cacheConfig = &core.CacheConfig{ - TrieCleanLimit: config.TrieCleanCache, - TrieCleanNoPrefetch: config.NoPrefetch, - TrieDirtyLimit: config.TrieDirtyCache, - TrieDirtyDisabled: config.NoPruning, - TrieTimeLimit: config.TrieTimeout, - SnapshotLimit: config.SnapshotCache, - Preimages: config.Preimages, - StateHistory: config.StateHistory, - StateScheme: scheme, - } - ) - // Override the chain config with provided settings. - var overrides core.ChainOverrides - if config.OverrideCancun != nil { - overrides.OverrideCancun = config.OverrideCancun - } - if config.OverrideVerkle != nil { - overrides.OverrideVerkle = config.OverrideVerkle - } - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, eth.shouldPreserve, &config.TransactionHistory) - if err != nil { - return nil, err - } - eth.bloomIndexer.Start(eth.blockchain) - - if config.BlobPool.Datadir != "" { - config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir) - } - blobPool := blobpool.New(config.BlobPool, eth.blockchain) - - if config.TxPool.Journal != "" { - config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) - } - legacyPool := legacypool.New(config.TxPool, eth.blockchain) - - eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool, blobPool}) - if err != nil { - return nil, err - } - // Permit the downloader to use the trie cache allowance during fast sync - cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit - if eth.handler, err = newHandler(&handlerConfig{ - Database: chainDb, - Chain: eth.blockchain, - TxPool: eth.txPool, - Merger: eth.merger, - Network: networkID, - Sync: config.SyncMode, - BloomCache: uint64(cacheLimit), - EventMux: eth.eventMux, - RequiredBlocks: config.RequiredBlocks, - }); err != nil { - return nil, err - } - - eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock) - err = eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) - if err != nil { - return nil, err - } - - eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} - if eth.APIBackend.allowUnprotectedTxs { - log.Info("Unprotected transactions allowed") - } - gpoParams := config.GPO - if gpoParams.Default == nil { - gpoParams.Default = config.Miner.GasPrice - } - eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) - - // Setup DNS discovery iterators. - dnsclient := dnsdisc.NewClient(dnsdisc.Config{}) - eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...) - if err != nil { - return nil, err - } - eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...) - if err != nil { - return nil, err - } - - // Start the RPC service - eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID) - - // Register the backend on the node - stack.RegisterAPIs(eth.APIs()) - stack.RegisterProtocols(eth.Protocols()) - stack.RegisterLifecycle(eth) - - // Successful startup; push a marker and check previous unclean shutdowns. - eth.shutdownTracker.MarkStartup() - - return eth, nil -} - -func makeExtraData(extra []byte) []byte { - if len(extra) == 0 { - // create default extradata - extra, _ = rlp.EncodeToBytes([]interface{}{ - uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), - "geth", - runtime.Version(), - runtime.GOOS, - }) - } - if uint64(len(extra)) > params.MaximumExtraDataSize { - log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) - extra = nil - } - return extra -} - -// APIs return the collection of RPC services the ethereum package offers. -// NOTE, some of these services probably need to be moved to somewhere else. -func (s *Ethereum) APIs() []rpc.API { - apis := ethapi.GetAPIs(s.APIBackend, s.BlockChain()) - - // Append any APIs exposed explicitly by the consensus engine - apis = append(apis, s.engine.APIs(s.BlockChain())...) - - // Append all the local APIs and return - return append(apis, []rpc.API{ - { - Namespace: "eth", - Service: NewEthereumAPI(s), - }, { - Namespace: "miner", - Service: NewMinerAPI(s), - }, { - Namespace: "eth", - Service: downloader.NewDownloaderAPI(s.handler.downloader, s.blockchain, s.eventMux), - }, { - Namespace: "admin", - Service: NewAdminAPI(s), - }, { - Namespace: "debug", - Service: NewDebugAPI(s), - }, { - Namespace: "net", - Service: s.netRPCService, - }, - }...) -} - -func (s *Ethereum) RegisterBundleFetcher(fetcher txpool.IFetcher) { - s.txPool.RegisterBundleFetcher(fetcher) -} - -func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { - s.blockchain.ResetWithGenesisBlock(gb) -} - -func (s *Ethereum) Etherbase() (eb common.Address, err error) { - s.lock.RLock() - etherbase := s.etherbase - s.lock.RUnlock() - - if etherbase != (common.Address{}) { - return etherbase, nil - } - return common.Address{}, errors.New("etherbase must be explicitly specified") -} - -// isLocalBlock checks whether the specified block is mined -// by local miner accounts. -// -// We regard two types of accounts as local miner account: etherbase -// and accounts specified via `txpool.locals` flag. -func (s *Ethereum) isLocalBlock(header *types.Header) bool { - author, err := s.engine.Author(header) - if err != nil { - log.Warn("Failed to retrieve block author", "number", header.Number.Uint64(), "hash", header.Hash(), "err", err) - return false - } - // Check whether the given address is etherbase. - s.lock.RLock() - etherbase := s.etherbase - s.lock.RUnlock() - if author == etherbase { - return true - } - // Check whether the given address is specified by `txpool.local` - // CLI flag. - for _, account := range s.config.TxPool.Locals { - if account == author { - return true - } - } - return false -} - -// shouldPreserve checks whether we should preserve the given block -// during the chain reorg depending on whether the author of block -// is a local account. -func (s *Ethereum) shouldPreserve(header *types.Header) bool { - // The reason we need to disable the self-reorg preserving for clique - // is it can be probable to introduce a deadlock. - // - // e.g. If there are 7 available signers - // - // r1 A - // r2 B - // r3 C - // r4 D - // r5 A [X] F G - // r6 [X] - // - // In the round5, the in-turn signer E is offline, so the worst case - // is A, F and G sign the block of round5 and reject the block of opponents - // and in the round6, the last available signer B is offline, the whole - // network is stuck. - if _, ok := s.engine.(*clique.Clique); ok { - return false - } - return s.isLocalBlock(header) -} - -// SetEtherbase sets the mining reward address. -func (s *Ethereum) SetEtherbase(etherbase common.Address) { - s.lock.Lock() - s.etherbase = etherbase - s.lock.Unlock() - - s.miner.SetEtherbase(etherbase) -} - -// StartMining starts the miner with the given number of CPU threads. If mining -// is already running, this method adjust the number of threads allowed to use -// and updates the minimum price required by the transaction pool. -func (s *Ethereum) StartMining() error { - // If the miner was not running, initialize it - if !s.IsMining() { - // Propagate the initial price point to the transaction pool - s.lock.RLock() - price := s.gasPrice - s.lock.RUnlock() - s.txPool.SetGasTip(price) - - // Configure the local mining address - eb, err := s.Etherbase() - if err != nil { - log.Error("Cannot start mining without etherbase", "err", err) - return fmt.Errorf("etherbase missing: %v", err) - } - var cli *clique.Clique - if c, ok := s.engine.(*clique.Clique); ok { - cli = c - } else if cl, ok := s.engine.(*beacon.Beacon); ok { - if c, ok := cl.InnerEngine().(*clique.Clique); ok { - cli = c - } - } - if cli != nil { - wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) - if wallet == nil || err != nil { - log.Error("Etherbase account unavailable locally", "err", err) - return fmt.Errorf("signer missing: %v", err) - } - cli.Authorize(eb, wallet.SignData) - } - // If mining is started, we can disable the transaction rejection mechanism - // introduced to speed sync times. - s.handler.enableSyncedFeatures() - - go s.miner.Start() - } - return nil -} - -// StopMining terminates the miner, both at the consensus engine level as well as -// at the block creation level. -func (s *Ethereum) StopMining() { - // Update the thread count within the consensus engine - type threaded interface { - SetThreads(threads int) - } - if th, ok := s.engine.(threaded); ok { - th.SetThreads(-1) - } - // Stop the block creating itself - s.miner.Stop() -} - -func (s *Ethereum) IsMining() bool { return s.miner.Mining() } -func (s *Ethereum) Miner() *miner.Miner { return s.miner } - -func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } -func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } -func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool } -func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } -func (s *Ethereum) Engine() consensus.Engine { return s.engine } -func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } -func (s *Ethereum) IsListening() bool { return true } // Always listening -func (s *Ethereum) Downloader() *downloader.Downloader { return s.handler.downloader } -func (s *Ethereum) Synced() bool { return s.handler.synced.Load() } -func (s *Ethereum) SetSynced() { s.handler.enableSyncedFeatures() } -func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning } -func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } -func (s *Ethereum) Merger() *consensus.Merger { return s.merger } -func (s *Ethereum) SyncMode() downloader.SyncMode { - mode, _ := s.handler.chainSync.modeAndLocalHead() - return mode -} - -// Protocols returns all the currently configured -// network protocols to start. -func (s *Ethereum) Protocols() []p2p.Protocol { - protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.ethDialCandidates) - if s.config.SnapshotCache > 0 { - protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...) - } - return protos -} - -// Start implements node.Lifecycle, starting all internal goroutines needed by the -// Ethereum protocol implementation. -func (s *Ethereum) Start() error { - eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode()) - - // Start the bloom bits servicing goroutines - s.startBloomHandlers(params.BloomBitsBlocks) - - // Regularly update shutdown marker - s.shutdownTracker.Start() - - // Figure out a max peers count based on the server limits - maxPeers := s.p2pServer.MaxPeers - if s.config.LightServ > 0 { - if s.config.LightPeers >= s.p2pServer.MaxPeers { - return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, s.p2pServer.MaxPeers) - } - maxPeers -= s.config.LightPeers - } - // Start the networking layer and the light server if requested - s.handler.Start(maxPeers) - return nil -} - -// Stop implements node.Lifecycle, terminating all internal goroutines used by the -// Ethereum protocol. -func (s *Ethereum) Stop() error { - // Stop all the peer-related stuff first. - s.ethDialCandidates.Close() - s.snapDialCandidates.Close() - s.handler.Stop() - - // Then stop everything else. - s.bloomIndexer.Close() - close(s.closeBloomHandler) - s.txPool.Close() - s.miner.Close() - s.blockchain.Stop() - s.engine.Close() - - // Clean shutdown marker as the last thing before closing db - s.shutdownTracker.Stop() - - s.chainDb.Close() - s.eventMux.Stop() - - return nil -} diff --git a/builder/eth/block-validation/api.go b/builder/eth/block-validation/api.go deleted file mode 100644 index 30f02ac46..000000000 --- a/builder/eth/block-validation/api.go +++ /dev/null @@ -1,327 +0,0 @@ -package blockvalidation - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderApiCapella "github.com/attestantio/go-builder-client/api/capella" - builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/rpc" -) - -type BlacklistedAddresses []common.Address - -type AccessVerifier struct { - blacklistedAddresses map[common.Address]struct{} -} - -func (a *AccessVerifier) verifyTraces(tracer *logger.AccessListTracer) error { - log.Trace("x", "tracer.AccessList()", tracer.AccessList()) - for _, accessTuple := range tracer.AccessList() { - // TODO: should we ignore common.Address{}? - if _, found := a.blacklistedAddresses[accessTuple.Address]; found { - log.Info("bundle accesses blacklisted address", "address", accessTuple.Address) - return fmt.Errorf("blacklisted address %s in execution trace", accessTuple.Address.String()) - } - } - - return nil -} - -func (a *AccessVerifier) isBlacklisted(addr common.Address) error { - if _, present := a.blacklistedAddresses[addr]; present { - return fmt.Errorf("transaction from blacklisted address %s", addr.String()) - } - return nil -} - -func (a *AccessVerifier) verifyTransactions(signer types.Signer, txs types.Transactions) error { - for _, tx := range txs { - from, err := types.Sender(signer, tx) - if err == nil { - if _, present := a.blacklistedAddresses[from]; present { - return fmt.Errorf("transaction from blacklisted address %s", from.String()) - } - } - to := tx.To() - if to != nil { - if _, present := a.blacklistedAddresses[*to]; present { - return fmt.Errorf("transaction to blacklisted address %s", to.String()) - } - } - } - return nil -} - -func NewAccessVerifierFromFile(path string) (*AccessVerifier, error) { - bytes, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var ba BlacklistedAddresses - if err := json.Unmarshal(bytes, &ba); err != nil { - return nil, err - } - - blacklistedAddresses := make(map[common.Address]struct{}, len(ba)) - for _, address := range ba { - blacklistedAddresses[address] = struct{}{} - } - - return &AccessVerifier{ - blacklistedAddresses: blacklistedAddresses, - }, nil -} - -type BlockValidationConfig struct { - BlacklistSourceFilePath string - // If set to true, proposer payment is calculated as a balance difference of the fee recipient. - UseBalanceDiffProfit bool - // If set to true, withdrawals to the fee recipient are excluded from the balance difference. - ExcludeWithdrawals bool -} - -// Register adds catalyst APIs to the full node. -func Register(stack *node.Node, backend *eth.Ethereum, cfg BlockValidationConfig) error { - var accessVerifier *AccessVerifier - if cfg.BlacklistSourceFilePath != "" { - var err error - accessVerifier, err = NewAccessVerifierFromFile(cfg.BlacklistSourceFilePath) - if err != nil { - return err - } - } - - stack.RegisterAPIs([]rpc.API{ - { - Namespace: "flashbots", - Service: NewBlockValidationAPI(backend, accessVerifier, cfg.UseBalanceDiffProfit, cfg.ExcludeWithdrawals), - }, - }) - return nil -} - -type BlockValidationAPI struct { - eth *eth.Ethereum - accessVerifier *AccessVerifier - // If set to true, proposer payment is calculated as a balance difference of the fee recipient. - useBalanceDiffProfit bool - // If set to true, withdrawals to the fee recipient are excluded from the balance delta. - excludeWithdrawals bool -} - -// NewConsensusAPI creates a new consensus api for the given backend. -// The underlying blockchain needs to have a valid terminal total difficulty set. -func NewBlockValidationAPI(eth *eth.Ethereum, accessVerifier *AccessVerifier, useBalanceDiffProfit, excludeWithdrawals bool) *BlockValidationAPI { - return &BlockValidationAPI{ - eth: eth, - accessVerifier: accessVerifier, - useBalanceDiffProfit: useBalanceDiffProfit, - excludeWithdrawals: excludeWithdrawals, - } -} - -type BuilderBlockValidationRequest struct { - builderApiBellatrix.SubmitBlockRequest - RegisteredGasLimit uint64 `json:"registered_gas_limit,string"` -} - -func (api *BlockValidationAPI) ValidateBuilderSubmissionV1(params *BuilderBlockValidationRequest) error { - // no longer supported endpoint - if params.ExecutionPayload == nil { - return errors.New("nil execution payload") - } - payload := params.ExecutionPayload - block, err := engine.ExecutionPayloadV1ToBlock(payload) - if err != nil { - return err - } - - return api.validateBlock(block, params.Message, params.RegisteredGasLimit) -} - -type BuilderBlockValidationRequestV2 struct { - builderApiCapella.SubmitBlockRequest - RegisteredGasLimit uint64 `json:"registered_gas_limit,string"` -} - -func (r *BuilderBlockValidationRequestV2) UnmarshalJSON(data []byte) error { - params := &struct { - RegisteredGasLimit uint64 `json:"registered_gas_limit,string"` - }{} - err := json.Unmarshal(data, params) - if err != nil { - return err - } - r.RegisteredGasLimit = params.RegisteredGasLimit - - blockRequest := new(builderApiCapella.SubmitBlockRequest) - err = json.Unmarshal(data, &blockRequest) - if err != nil { - return err - } - r.SubmitBlockRequest = *blockRequest - return nil -} - -func (api *BlockValidationAPI) ValidateBuilderSubmissionV2(params *BuilderBlockValidationRequestV2) error { - // TODO: fuzztest, make sure the validation is sound - // TODO: handle context! - if params.ExecutionPayload == nil { - return errors.New("nil execution payload") - } - payload := params.ExecutionPayload - block, err := engine.ExecutionPayloadV2ToBlock(payload) - if err != nil { - return err - } - - return api.validateBlock(block, params.Message, params.RegisteredGasLimit) -} - -type BuilderBlockValidationRequestV3 struct { - builderApiDeneb.SubmitBlockRequest - ParentBeaconBlockRoot common.Hash `json:"parent_beacon_block_root"` - RegisteredGasLimit uint64 `json:"registered_gas_limit,string"` -} - -func (r *BuilderBlockValidationRequestV3) UnmarshalJSON(data []byte) error { - params := &struct { - ParentBeaconBlockRoot common.Hash `json:"parent_beacon_block_root"` - RegisteredGasLimit uint64 `json:"registered_gas_limit,string"` - }{} - err := json.Unmarshal(data, params) - if err != nil { - return err - } - r.RegisteredGasLimit = params.RegisteredGasLimit - r.ParentBeaconBlockRoot = params.ParentBeaconBlockRoot - - blockRequest := new(builderApiDeneb.SubmitBlockRequest) - err = json.Unmarshal(data, &blockRequest) - if err != nil { - return err - } - r.SubmitBlockRequest = *blockRequest - return nil -} - -func (api *BlockValidationAPI) ValidateBuilderSubmissionV3(params *BuilderBlockValidationRequestV3) error { - // TODO: fuzztest, make sure the validation is sound - payload := params.ExecutionPayload - blobsBundle := params.BlobsBundle - log.Info("blobs bundle", "blobs", len(blobsBundle.Blobs), "commits", len(blobsBundle.Commitments), "proofs", len(blobsBundle.Proofs)) - block, err := engine.ExecutionPayloadV3ToBlock(payload, blobsBundle, params.ParentBeaconBlockRoot) - if err != nil { - return err - } - - err = api.validateBlock(block, params.Message, params.RegisteredGasLimit) - if err != nil { - log.Error("invalid payload", "hash", block.Hash, "number", block.NumberU64(), "parentHash", block.ParentHash, "err", err) - return err - } - err = validateBlobsBundle(block.Transactions(), blobsBundle) - if err != nil { - log.Error("invalid blobs bundle", "err", err) - return err - } - return nil -} - -func (api *BlockValidationAPI) validateBlock(block *types.Block, msg *builderApiV1.BidTrace, registeredGasLimit uint64) error { - if msg.ParentHash != phase0.Hash32(block.ParentHash()) { - return fmt.Errorf("incorrect ParentHash %s, expected %s", msg.ParentHash.String(), block.ParentHash().String()) - } - - if msg.BlockHash != phase0.Hash32(block.Hash()) { - return fmt.Errorf("incorrect BlockHash %s, expected %s", msg.BlockHash.String(), block.Hash().String()) - } - - if msg.GasLimit != block.GasLimit() { - return fmt.Errorf("incorrect GasLimit %d, expected %d", msg.GasLimit, block.GasLimit()) - } - - if msg.GasUsed != block.GasUsed() { - return fmt.Errorf("incorrect GasUsed %d, expected %d", msg.GasUsed, block.GasUsed()) - } - - feeRecipient := common.BytesToAddress(msg.ProposerFeeRecipient[:]) - expectedProfit := msg.Value.ToBig() - - var vmconfig vm.Config - var tracer *logger.AccessListTracer = nil - if api.accessVerifier != nil { - if err := api.accessVerifier.isBlacklisted(block.Coinbase()); err != nil { - return err - } - if err := api.accessVerifier.isBlacklisted(feeRecipient); err != nil { - return err - } - if err := api.accessVerifier.verifyTransactions(types.LatestSigner(api.eth.BlockChain().Config()), block.Transactions()); err != nil { - return err - } - isPostMerge := true // the call is PoS-native - precompiles := vm.ActivePrecompiles(api.eth.APIBackend.ChainConfig().Rules(new(big.Int).SetUint64(block.NumberU64()), isPostMerge, block.Time())) - tracer = logger.NewAccessListTracer(nil, common.Address{}, common.Address{}, precompiles) - vmconfig = vm.Config{Tracer: tracer} - } - - err := api.eth.BlockChain().ValidatePayload(block, feeRecipient, expectedProfit, registeredGasLimit, vmconfig, api.useBalanceDiffProfit, api.excludeWithdrawals) - if err != nil { - return err - } - - if api.accessVerifier != nil && tracer != nil { - if err := api.accessVerifier.verifyTraces(tracer); err != nil { - return err - } - } - - log.Info("validated block", "hash", block.Hash(), "number", block.NumberU64(), "parentHash", block.ParentHash()) - return nil -} - -func validateBlobsBundle(txs types.Transactions, blobsBundle *builderApiDeneb.BlobsBundle) error { - var hashes []common.Hash - for _, tx := range txs { - hashes = append(hashes, tx.BlobHashes()...) - } - blobs := blobsBundle.Blobs - commits := blobsBundle.Commitments - proofs := blobsBundle.Proofs - - if len(blobs) != len(hashes) { - return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", len(blobs), len(hashes)) - } - if len(commits) != len(hashes) { - return fmt.Errorf("invalid number of %d blob commitments compared to %d blob hashes", len(commits), len(hashes)) - } - if len(proofs) != len(hashes) { - return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", len(proofs), len(hashes)) - } - - for i := range blobs { - if err := kzg4844.VerifyBlobProof(kzg4844.Blob(blobs[i]), kzg4844.Commitment(commits[i]), kzg4844.Proof(proofs[i])); err != nil { - return fmt.Errorf("invalid blob %d: %v", i, err) - } - } - log.Info("validated blobs bundle", "blobs", len(blobs), "commits", len(commits), "proofs", len(proofs)) - return nil -} diff --git a/builder/eth/block-validation/api_test.go b/builder/eth/block-validation/api_test.go deleted file mode 100644 index 4340e99b3..000000000 --- a/builder/eth/block-validation/api_test.go +++ /dev/null @@ -1,1114 +0,0 @@ -package blockvalidation - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - "os" - "testing" - "time" - - "github.com/attestantio/go-builder-client/api" - builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" - builderApiCapella "github.com/attestantio/go-builder-client/api/capella" - builderApiDeneb "github.com/attestantio/go-builder-client/api/deneb" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/attestantio/go-eth2-client/spec" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/deneb" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - beaconConsensus "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" - boostTypes "github.com/flashbots/go-boost-utils/types" - "github.com/flashbots/go-boost-utils/utils" - "github.com/holiman/uint256" - "github.com/stretchr/testify/require" -) - -/* Based on catalyst API tests */ - -var ( - // testKey is a private key to use for funding a tester account. - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - - // testAddr is the Ethereum address of the tester account. - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - - testValidatorKey, _ = crypto.HexToECDSA("28c3cd61b687fdd03488e167a5d84f50269df2a4c29a2cfb1390903aa775c5d0") - testValidatorAddr = crypto.PubkeyToAddress(testValidatorKey.PublicKey) - - testBuilderKeyHex = "0bfbbbc68fefd990e61ba645efb84e0a62e94d5fff02c9b1da8eb45fea32b4e0" - testBuilderKey, _ = crypto.HexToECDSA(testBuilderKeyHex) - testBuilderAddr = crypto.PubkeyToAddress(testBuilderKey.PublicKey) - - testBalance = big.NewInt(2e18) - - // This EVM code generates a log when the contract is created. - logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") -) - -func TestValidateBuilderSubmissionV1(t *testing.T) { - genesis, preMergeBlocks := generatePreMergeChain(20) - os.Setenv("BUILDER_TX_SIGNING_KEY", "0x28c3cd61b687fdd03488e167a5d84f50269df2a4c29a2cfb1390903aa775c5d0") - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewBlockValidationAPI(ethservice, nil, true, true) - parent := preMergeBlocks[len(preMergeBlocks)-1] - - api.eth.APIBackend.Miner().SetEtherbase(testValidatorAddr) - - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) - nonce := statedb.GetNonce(testAddr) - - tx1, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx1}, true, true, false) - - cc, _ := types.SignTx(types.NewContractCreation(nonce+1, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{cc}, true, true, false) - - baseFee := eip1559.CalcBaseFee(params.AllEthashProtocolChanges, preMergeBlocks[len(preMergeBlocks)-1].Header()) - tx2, _ := types.SignTx(types.NewTransaction(nonce+2, testAddr, big.NewInt(10), 21000, baseFee, nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx2}, true, true, false) - - execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time() + 5, - SuggestedFeeRecipient: testValidatorAddr, - }) - require.EqualValues(t, len(execData.Transactions), 4) - require.NoError(t, err) - - payload, err := ExecutableDataToExecutionPayload(execData) - require.NoError(t, err) - - proposerAddr := bellatrix.ExecutionAddress{} - copy(proposerAddr[:], testValidatorAddr[:]) - - blockRequest := &BuilderBlockValidationRequest{ - SubmitBlockRequest: builderApiBellatrix.SubmitBlockRequest{ - Signature: phase0.BLSSignature{}, - Message: &builderApiV1.BidTrace{ - ParentHash: phase0.Hash32(execData.ParentHash), - BlockHash: phase0.Hash32(execData.BlockHash), - ProposerFeeRecipient: proposerAddr, - GasLimit: execData.GasLimit, - GasUsed: execData.GasUsed, - }, - ExecutionPayload: payload, - }, - RegisteredGasLimit: execData.GasLimit, - } - - blockRequest.Message.Value = uint256.NewInt(190526394825529) - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "inaccurate payment") - blockRequest.Message.Value = uint256.NewInt(149830884438530) - require.NoError(t, api.ValidateBuilderSubmissionV1(blockRequest)) - - blockRequest.Message.GasLimit += 1 - blockRequest.ExecutionPayload.GasLimit += 1 - updatePayloadHash(t, blockRequest) - - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "incorrect gas limit set") - - blockRequest.Message.GasLimit -= 1 - blockRequest.ExecutionPayload.GasLimit -= 1 - updatePayloadHash(t, blockRequest) - - // TODO: test with contract calling blacklisted address - // Test tx from blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - testAddr: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "transaction from blacklisted address 0x71562b71999873DB5b286dF957af199Ec94617F7") - - // Test tx to blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - {0x16}: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "transaction to blacklisted address 0x1600000000000000000000000000000000000000") - - api.accessVerifier = nil - - blockRequest.Message.GasUsed = 10 - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "incorrect GasUsed 10, expected 119990") - blockRequest.Message.GasUsed = execData.GasUsed - - newTestKey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f290") - invalidTx, err := types.SignTx(types.NewTransaction(0, common.Address{}, new(big.Int).Mul(big.NewInt(2e18), big.NewInt(10)), 19000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), newTestKey) - require.NoError(t, err) - - txData, err := invalidTx.MarshalBinary() - require.NoError(t, err) - execData.Transactions = append(execData.Transactions, txData) - - invalidPayload, err := ExecutableDataToExecutionPayload(execData) - require.NoError(t, err) - invalidPayload.GasUsed = execData.GasUsed - copy(invalidPayload.ReceiptsRoot[:], hexutil.MustDecode("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")[:32]) - blockRequest.ExecutionPayload = invalidPayload - updatePayloadHash(t, blockRequest) - require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "could not apply tx 4", "insufficient funds for gas * price + value") -} - -func TestValidateBuilderSubmissionV2(t *testing.T) { - genesis, preMergeBlocks := generatePreMergeChain(20) - os.Setenv("BUILDER_TX_SIGNING_KEY", testBuilderKeyHex) - time := preMergeBlocks[len(preMergeBlocks)-1].Time() + 5 - genesis.Config.ShanghaiTime = &time - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewBlockValidationAPI(ethservice, nil, true, true) - parent := preMergeBlocks[len(preMergeBlocks)-1] - - api.eth.APIBackend.Miner().SetEtherbase(testBuilderAddr) - - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) - nonce := statedb.GetNonce(testAddr) - - tx1, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx1}, true, true, false) - - cc, _ := types.SignTx(types.NewContractCreation(nonce+1, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{cc}, true, true, false) - - baseFee := eip1559.CalcBaseFee(params.AllEthashProtocolChanges, preMergeBlocks[len(preMergeBlocks)-1].Header()) - tx2, _ := types.SignTx(types.NewTransaction(nonce+2, testAddr, big.NewInt(10), 21000, baseFee, nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx2}, true, true, false) - - withdrawals := []*types.Withdrawal{ - { - Index: 0, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - { - Index: 1, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - } - - execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time() + 5, - Withdrawals: withdrawals, - SuggestedFeeRecipient: testValidatorAddr, - }) - require.NoError(t, err) - require.EqualValues(t, len(execData.Withdrawals), 2) - require.EqualValues(t, len(execData.Transactions), 4) - - payload, err := ExecutableDataToExecutionPayloadV2(execData) - require.NoError(t, err) - - proposerAddr := bellatrix.ExecutionAddress{} - copy(proposerAddr[:], testValidatorAddr.Bytes()) - - blockRequest := &BuilderBlockValidationRequestV2{ - SubmitBlockRequest: builderApiCapella.SubmitBlockRequest{ - Signature: phase0.BLSSignature{}, - Message: &builderApiV1.BidTrace{ - ParentHash: phase0.Hash32(execData.ParentHash), - BlockHash: phase0.Hash32(execData.BlockHash), - ProposerFeeRecipient: proposerAddr, - GasLimit: execData.GasLimit, - GasUsed: execData.GasUsed, - // This value is actual profit + 1, validation should fail - Value: uint256.NewInt(149842511727213), - }, - ExecutionPayload: payload, - }, - RegisteredGasLimit: execData.GasLimit, - } - - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "inaccurate payment") - blockRequest.Message.Value = uint256.NewInt(149842511727212) - require.NoError(t, api.ValidateBuilderSubmissionV2(blockRequest)) - - blockRequest.Message.GasLimit += 1 - blockRequest.ExecutionPayload.GasLimit += 1 - updatePayloadHashV2(t, blockRequest) - - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "incorrect gas limit set") - - blockRequest.Message.GasLimit -= 1 - blockRequest.ExecutionPayload.GasLimit -= 1 - updatePayloadHashV2(t, blockRequest) - - // TODO: test with contract calling blacklisted address - // Test tx from blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - testAddr: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "transaction from blacklisted address 0x71562b71999873DB5b286dF957af199Ec94617F7") - - // Test tx to blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - {0x16}: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "transaction to blacklisted address 0x1600000000000000000000000000000000000000") - - api.accessVerifier = nil - - blockRequest.Message.GasUsed = 10 - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "incorrect GasUsed 10, expected 119996") - blockRequest.Message.GasUsed = execData.GasUsed - - newTestKey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f290") - invalidTx, err := types.SignTx(types.NewTransaction(0, common.Address{}, new(big.Int).Mul(big.NewInt(2e18), big.NewInt(10)), 19000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), newTestKey) - require.NoError(t, err) - - txData, err := invalidTx.MarshalBinary() - require.NoError(t, err) - execData.Transactions = append(execData.Transactions, txData) - - invalidPayload, err := ExecutableDataToExecutionPayloadV2(execData) - require.NoError(t, err) - invalidPayload.GasUsed = execData.GasUsed - copy(invalidPayload.ReceiptsRoot[:], hexutil.MustDecode("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")[:32]) - blockRequest.ExecutionPayload = invalidPayload - updatePayloadHashV2(t, blockRequest) - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(blockRequest), "could not apply tx 4", "insufficient funds for gas * price + value") -} - -func TestValidateBuilderSubmissionV3(t *testing.T) { - genesis, blocks := generateMergeChain(10, true) - - // Set cancun time to last block + 5 seconds - time := blocks[len(blocks)-1].Time() + 5 - genesis.Config.ShanghaiTime = &time - genesis.Config.CancunTime = &time - os.Setenv("BUILDER_TX_SIGNING_KEY", testBuilderKeyHex) - - n, ethservice := startEthService(t, genesis, blocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewBlockValidationAPI(ethservice, nil, true, false) - parent := ethservice.BlockChain().CurrentHeader() - - api.eth.APIBackend.Miner().SetEtherbase(testBuilderAddr) - - statedb, _ := ethservice.BlockChain().StateAt(parent.Root) - nonce := statedb.GetNonce(testAddr) - - tx1, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx1}, true, true, false) - - cc, _ := types.SignTx(types.NewContractCreation(nonce+1, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{cc}, true, true, false) - - baseFee := eip1559.CalcBaseFee(params.AllEthashProtocolChanges, parent) - tx2, _ := types.SignTx(types.NewTransaction(nonce+2, testAddr, big.NewInt(10), 21000, baseFee, nil), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx2}, true, true, false) - - withdrawals := []*types.Withdrawal{ - { - Index: 0, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - { - Index: 1, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - } - - execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: withdrawals, - SuggestedFeeRecipient: testValidatorAddr, - BeaconRoot: &common.Hash{42}, - }) - require.NoError(t, err) - require.EqualValues(t, len(execData.Withdrawals), 2) - require.EqualValues(t, len(execData.Transactions), 4) - - payload, err := ExecutableDataToExecutionPayloadV3(execData) - require.NoError(t, err) - - proposerAddr := bellatrix.ExecutionAddress{} - copy(proposerAddr[:], testValidatorAddr.Bytes()) - - blockRequest := &BuilderBlockValidationRequestV3{ - SubmitBlockRequest: builderApiDeneb.SubmitBlockRequest{ - Signature: phase0.BLSSignature{}, - Message: &builderApiV1.BidTrace{ - ParentHash: phase0.Hash32(execData.ParentHash), - BlockHash: phase0.Hash32(execData.BlockHash), - ProposerFeeRecipient: proposerAddr, - GasLimit: execData.GasLimit, - GasUsed: execData.GasUsed, - // This value is actual profit + 1, validation should fail - Value: uint256.NewInt(132912184722469), - }, - ExecutionPayload: payload, - BlobsBundle: &builderApiDeneb.BlobsBundle{ - Commitments: make([]deneb.KZGCommitment, 0), - Proofs: make([]deneb.KZGProof, 0), - Blobs: make([]deneb.Blob, 0), - }, - }, - RegisteredGasLimit: execData.GasLimit, - ParentBeaconBlockRoot: common.Hash{42}, - } - - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "inaccurate payment") - blockRequest.Message.Value = uint256.NewInt(132912184722468) - require.NoError(t, api.ValidateBuilderSubmissionV3(blockRequest)) - - blockRequest.Message.GasLimit += 1 - blockRequest.ExecutionPayload.GasLimit += 1 - updatePayloadHashV3(t, blockRequest) - - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "incorrect gas limit set") - - blockRequest.Message.GasLimit -= 1 - blockRequest.ExecutionPayload.GasLimit -= 1 - updatePayloadHashV3(t, blockRequest) - - // TODO: test with contract calling blacklisted address - // Test tx from blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - testAddr: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "transaction from blacklisted address 0x71562b71999873DB5b286dF957af199Ec94617F7") - - // Test tx to blacklisted address - api.accessVerifier = &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - {0x16}: {}, - }, - } - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "transaction to blacklisted address 0x1600000000000000000000000000000000000000") - - api.accessVerifier = nil - - blockRequest.Message.GasUsed = 10 - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "incorrect GasUsed 10, expected 119996") - blockRequest.Message.GasUsed = execData.GasUsed - - newTestKey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f290") - invalidTx, err := types.SignTx(types.NewTransaction(0, common.Address{}, new(big.Int).Mul(big.NewInt(2e18), big.NewInt(10)), 19000, big.NewInt(2*params.InitialBaseFee), nil), types.LatestSigner(ethservice.BlockChain().Config()), newTestKey) - require.NoError(t, err) - - txData, err := invalidTx.MarshalBinary() - require.NoError(t, err) - execData.Transactions = append(execData.Transactions, txData) - - invalidPayload, err := ExecutableDataToExecutionPayloadV3(execData) - require.NoError(t, err) - invalidPayload.GasUsed = execData.GasUsed - copy(invalidPayload.ReceiptsRoot[:], hexutil.MustDecode("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")[:32]) - blockRequest.ExecutionPayload = invalidPayload - updatePayloadHashV3(t, blockRequest) - require.ErrorContains(t, api.ValidateBuilderSubmissionV3(blockRequest), "could not apply tx 4", "insufficient funds for gas * price + value") -} - -func updatePayloadHash(t *testing.T, blockRequest *BuilderBlockValidationRequest) { - blockHash, err := utils.ComputeBlockHash(&api.VersionedExecutionPayload{Version: spec.DataVersionBellatrix, Bellatrix: blockRequest.ExecutionPayload}, nil) - require.NoError(t, err) - copy(blockRequest.Message.BlockHash[:], blockHash[:]) - copy(blockRequest.ExecutionPayload.BlockHash[:], blockHash[:]) -} - -func updatePayloadHashV2(t *testing.T, blockRequest *BuilderBlockValidationRequestV2) { - blockHash, err := utils.ComputeBlockHash(&api.VersionedExecutionPayload{Version: spec.DataVersionCapella, Capella: blockRequest.ExecutionPayload}, nil) - require.NoError(t, err) - copy(blockRequest.Message.BlockHash[:], blockHash[:]) - copy(blockRequest.ExecutionPayload.BlockHash[:], blockHash[:]) -} - -func updatePayloadHashV3(t *testing.T, blockRequest *BuilderBlockValidationRequestV3) { - root := phase0.Root(blockRequest.ParentBeaconBlockRoot) - blockHash, err := utils.ComputeBlockHash(&api.VersionedExecutionPayload{Version: spec.DataVersionDeneb, Deneb: blockRequest.ExecutionPayload}, &root) - require.NoError(t, err) - copy(blockRequest.Message.BlockHash[:], blockHash[:]) - copy(blockRequest.ExecutionPayload.BlockHash[:], blockHash[:]) -} - -func generatePreMergeChain(n int) (*core.Genesis, []*types.Block) { - db := rawdb.NewMemoryDatabase() - config := params.AllEthashProtocolChanges - genesis := &core.Genesis{ - Config: config, - Alloc: types.GenesisAlloc{testAddr: {Balance: testBalance}, testValidatorAddr: {Balance: testBalance}, testBuilderAddr: {Balance: testBalance}}, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: big.NewInt(0), - } - testNonce := uint64(0) - generate := func(_ int, g *core.BlockGen) { - g.OffsetTime(5) - g.SetExtra([]byte("test")) - tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(config), testKey) - g.AddTx(tx) - testNonce++ - } - gblock := genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) - engine := ethash.NewFaker() - blocks, _ := core.GenerateChain(config, gblock, engine, db, n, generate) - totalDifficulty := big.NewInt(0) - for _, b := range blocks { - totalDifficulty.Add(totalDifficulty, b.Difficulty()) - } - config.TerminalTotalDifficulty = totalDifficulty - return genesis, blocks -} - -func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { - config := *params.AllEthashProtocolChanges - engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker())) - if merged { - config.TerminalTotalDifficulty = common.Big0 - config.TerminalTotalDifficultyPassed = true - engine = beaconConsensus.NewFaker() - } - genesis := &core.Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{ - testAddr: {Balance: testBalance}, - params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")}, - }, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: big.NewInt(0), - } - testNonce := uint64(0) - generate := func(_ int, g *core.BlockGen) { - g.OffsetTime(5) - g.SetExtra([]byte("test")) - tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(&config), testKey) - g.AddTx(tx) - testNonce++ - } - _, blocks, _ := core.GenerateChainWithGenesis(genesis, engine, n, generate) - - if !merged { - totalDifficulty := big.NewInt(0) - for _, b := range blocks { - totalDifficulty.Add(totalDifficulty, b.Difficulty()) - } - config.TerminalTotalDifficulty = totalDifficulty - } - - return genesis, blocks -} - -// startEthService creates a full node instance for testing. -func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) (*node.Node, *eth.Ethereum) { - t.Helper() - - n, err := node.New(&node.Config{ - P2P: p2p.Config{ - ListenAddr: "0.0.0.0:0", - NoDiscovery: true, - MaxPeers: 25, - }, - }) - if err != nil { - t.Fatal("can't create node:", err) - } - - ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} - ethservice, err := eth.New(n, ethcfg) - if err != nil { - t.Fatal("can't create eth service:", err) - } - if err := n.Start(); err != nil { - t.Fatal("can't start node:", err) - } - if _, err := ethservice.BlockChain().InsertChain(blocks); err != nil { - n.Close() - t.Fatal("can't import test blocks:", err) - } - time.Sleep(500 * time.Millisecond) // give txpool enough time to consume head event - - ethservice.SetEtherbase(testAddr) - ethservice.SetSynced() - return n, ethservice -} - -func assembleBlock(api *BlockValidationAPI, parentHash common.Hash, params *engine.PayloadAttributes) (*engine.ExecutableData, error) { - args := &miner.BuildPayloadArgs{ - Parent: parentHash, - Timestamp: params.Timestamp, - FeeRecipient: params.SuggestedFeeRecipient, - GasLimit: params.GasLimit, - Random: params.Random, - Withdrawals: params.Withdrawals, - BeaconRoot: params.BeaconRoot, - } - - payload, err := api.eth.Miner().BuildPayload(args) - if err != nil { - return nil, err - } - - if payload := payload.ResolveFull(); payload != nil { - return payload.ExecutionPayload, nil - } - - return nil, errors.New("payload did not resolve") -} - -func TestBlacklistLoad(t *testing.T) { - file, err := os.CreateTemp(".", "blacklist") - require.NoError(t, err) - defer os.Remove(file.Name()) - - av, err := NewAccessVerifierFromFile(file.Name()) - require.Error(t, err) - require.Nil(t, av) - - ba := BlacklistedAddresses{common.Address{0x13}, common.Address{0x14}} - bytes, err := json.MarshalIndent(ba, "", " ") - require.NoError(t, err) - err = os.WriteFile(file.Name(), bytes, 0o644) - require.NoError(t, err) - - av, err = NewAccessVerifierFromFile(file.Name()) - require.NoError(t, err) - require.NotNil(t, av) - require.EqualValues(t, av.blacklistedAddresses, map[common.Address]struct{}{ - {0x13}: {}, - {0x14}: {}, - }) - - require.NoError(t, av.verifyTraces(logger.NewAccessListTracer(nil, common.Address{}, common.Address{}, nil))) - - acl := types.AccessList{ - types.AccessTuple{ - Address: common.Address{0x14}, - }, - } - tracer := logger.NewAccessListTracer(acl, common.Address{}, common.Address{}, nil) - require.ErrorContains(t, av.verifyTraces(tracer), "blacklisted address 0x1400000000000000000000000000000000000000 in execution trace") - - acl = types.AccessList{ - types.AccessTuple{ - Address: common.Address{0x15}, - }, - } - tracer = logger.NewAccessListTracer(acl, common.Address{}, common.Address{}, nil) - require.NoError(t, av.verifyTraces(tracer)) -} - -func ExecutableDataToExecutionPayload(data *engine.ExecutableData) (*bellatrix.ExecutionPayload, error) { - transactionData := make([]bellatrix.Transaction, len(data.Transactions)) - for i, tx := range data.Transactions { - transactionData[i] = bellatrix.Transaction(tx) - } - - baseFeePerGas := new(boostTypes.U256Str) - err := baseFeePerGas.FromBig(data.BaseFeePerGas) - if err != nil { - return nil, err - } - - return &bellatrix.ExecutionPayload{ - ParentHash: [32]byte(data.ParentHash), - FeeRecipient: [20]byte(data.FeeRecipient), - StateRoot: [32]byte(data.StateRoot), - ReceiptsRoot: [32]byte(data.ReceiptsRoot), - LogsBloom: types.BytesToBloom(data.LogsBloom), - PrevRandao: [32]byte(data.Random), - BlockNumber: data.Number, - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Timestamp: data.Timestamp, - ExtraData: data.ExtraData, - BaseFeePerGas: *baseFeePerGas, - BlockHash: [32]byte(data.BlockHash), - Transactions: transactionData, - }, nil -} - -func ExecutableDataToExecutionPayloadV2(data *engine.ExecutableData) (*capella.ExecutionPayload, error) { - transactionData := make([]bellatrix.Transaction, len(data.Transactions)) - for i, tx := range data.Transactions { - transactionData[i] = bellatrix.Transaction(tx) - } - - withdrawalData := make([]*capella.Withdrawal, len(data.Withdrawals)) - for i, withdrawal := range data.Withdrawals { - withdrawalData[i] = &capella.Withdrawal{ - Index: capella.WithdrawalIndex(withdrawal.Index), - ValidatorIndex: phase0.ValidatorIndex(withdrawal.Validator), - Address: bellatrix.ExecutionAddress(withdrawal.Address), - Amount: phase0.Gwei(withdrawal.Amount), - } - } - - baseFeePerGas := new(boostTypes.U256Str) - err := baseFeePerGas.FromBig(data.BaseFeePerGas) - if err != nil { - return nil, err - } - - return &capella.ExecutionPayload{ - ParentHash: [32]byte(data.ParentHash), - FeeRecipient: [20]byte(data.FeeRecipient), - StateRoot: [32]byte(data.StateRoot), - ReceiptsRoot: [32]byte(data.ReceiptsRoot), - LogsBloom: types.BytesToBloom(data.LogsBloom), - PrevRandao: [32]byte(data.Random), - BlockNumber: data.Number, - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Timestamp: data.Timestamp, - ExtraData: data.ExtraData, - BaseFeePerGas: *baseFeePerGas, - BlockHash: [32]byte(data.BlockHash), - Transactions: transactionData, - Withdrawals: withdrawalData, - }, nil -} - -func ExecutableDataToExecutionPayloadV3(data *engine.ExecutableData) (*deneb.ExecutionPayload, error) { - transactionData := make([]bellatrix.Transaction, len(data.Transactions)) - for i, tx := range data.Transactions { - transactionData[i] = bellatrix.Transaction(tx) - } - - withdrawalData := make([]*capella.Withdrawal, len(data.Withdrawals)) - for i, withdrawal := range data.Withdrawals { - withdrawalData[i] = &capella.Withdrawal{ - Index: capella.WithdrawalIndex(withdrawal.Index), - ValidatorIndex: phase0.ValidatorIndex(withdrawal.Validator), - Address: bellatrix.ExecutionAddress(withdrawal.Address), - Amount: phase0.Gwei(withdrawal.Amount), - } - } - - return &deneb.ExecutionPayload{ - ParentHash: [32]byte(data.ParentHash), - FeeRecipient: [20]byte(data.FeeRecipient), - StateRoot: [32]byte(data.StateRoot), - ReceiptsRoot: [32]byte(data.ReceiptsRoot), - LogsBloom: types.BytesToBloom(data.LogsBloom), - PrevRandao: [32]byte(data.Random), - BlockNumber: data.Number, - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Timestamp: data.Timestamp, - ExtraData: data.ExtraData, - BaseFeePerGas: uint256.MustFromBig(data.BaseFeePerGas), - BlockHash: [32]byte(data.BlockHash), - Transactions: transactionData, - Withdrawals: withdrawalData, - BlobGasUsed: *data.BlobGasUsed, - ExcessBlobGas: *data.ExcessBlobGas, - }, nil -} - -func WithdrawalToBlockRequestWithdrawal(withdrawals types.Withdrawals) []*capella.Withdrawal { - withdrawalsData := make([]*capella.Withdrawal, len(withdrawals)) - for i, withdrawal := range withdrawals { - withdrawalsData[i] = &capella.Withdrawal{ - Index: capella.WithdrawalIndex(i), - ValidatorIndex: phase0.ValidatorIndex(withdrawal.Validator), - Address: bellatrix.ExecutionAddress(withdrawal.Address), - Amount: phase0.Gwei(withdrawal.Amount), - } - } - return withdrawalsData -} - -type buildBlockArgs struct { - parentHash common.Hash - parentRoot common.Hash - feeRecipient common.Address - txs types.Transactions - random common.Hash - number uint64 - gasLimit uint64 - timestamp uint64 - extraData []byte - baseFeePerGas *big.Int - withdrawals types.Withdrawals -} - -func buildBlock(args buildBlockArgs, chain *core.BlockChain) (*engine.ExecutableData, error) { - header := &types.Header{ - ParentHash: args.parentHash, - Coinbase: args.feeRecipient, - Number: big.NewInt(int64(args.number)), - GasLimit: args.gasLimit, - Time: args.timestamp, - Extra: args.extraData, - BaseFee: args.baseFeePerGas, - MixDigest: args.random, - } - - err := chain.Engine().Prepare(chain, header) - if err != nil { - return nil, err - } - - statedb, err := chain.StateAt(args.parentRoot) - if err != nil { - return nil, err - } - - receipts := make([]*types.Receipt, 0, len(args.txs)) - gasPool := core.GasPool(header.GasLimit) - vmConfig := vm.Config{} - for i, tx := range args.txs { - statedb.SetTxContext(tx.Hash(), i) - receipt, err := core.ApplyTransaction(chain.Config(), chain, &args.feeRecipient, &gasPool, statedb, header, tx, &header.GasUsed, vmConfig, nil) - if err != nil { - return nil, err - } - receipts = append(receipts, receipt) - } - - block, err := chain.Engine().FinalizeAndAssemble(chain, header, statedb, args.txs, nil, receipts, args.withdrawals) - if err != nil { - return nil, err - } - - execData := engine.BlockToExecutableData(block, common.Big0, nil) - - return execData.ExecutionPayload, nil -} - -func executableDataToBlockValidationRequest(execData *engine.ExecutableData, proposer common.Address, value *big.Int, withdrawalsRoot common.Hash) (*BuilderBlockValidationRequestV2, error) { - payload, err := ExecutableDataToExecutionPayloadV2(execData) - if err != nil { - return nil, err - } - - proposerAddr := bellatrix.ExecutionAddress{} - copy(proposerAddr[:], proposer.Bytes()) - - value256, overflow := uint256.FromBig(value) - if overflow { - return nil, errors.New("could not convert value to uint256") - } - blockRequest := &BuilderBlockValidationRequestV2{ - SubmitBlockRequest: builderApiCapella.SubmitBlockRequest{ - Signature: phase0.BLSSignature{}, - Message: &builderApiV1.BidTrace{ - ParentHash: phase0.Hash32(execData.ParentHash), - BlockHash: phase0.Hash32(execData.BlockHash), - ProposerFeeRecipient: proposerAddr, - GasLimit: execData.GasLimit, - GasUsed: execData.GasUsed, - Value: value256, - }, - ExecutionPayload: payload, - }, - RegisteredGasLimit: execData.GasLimit, - } - return blockRequest, nil -} - -// This tests payment when the proposer fee recipient is the same as the coinbase -func TestValidateBuilderSubmissionV2_CoinbasePaymentDefault(t *testing.T) { - genesis, preMergeBlocks := generatePreMergeChain(20) - lastBlock := preMergeBlocks[len(preMergeBlocks)-1] - time := lastBlock.Time() + 5 - genesis.Config.ShanghaiTime = &time - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewBlockValidationAPI(ethservice, nil, true, true) - - baseFee := eip1559.CalcBaseFee(ethservice.BlockChain().Config(), lastBlock.Header()) - txs := make(types.Transactions, 0) - - statedb, _ := ethservice.BlockChain().StateAt(lastBlock.Root()) - nonce := statedb.GetNonce(testAddr) - signer := types.LatestSigner(ethservice.BlockChain().Config()) - - expectedProfit := uint64(0) - - tx1, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, big.NewInt(2*baseFee.Int64()), nil), signer, testKey) - txs = append(txs, tx1) - expectedProfit += 21000 * baseFee.Uint64() - - // this tx will use 56996 gas - tx2, _ := types.SignTx(types.NewContractCreation(nonce+1, new(big.Int), 1000000, big.NewInt(2*baseFee.Int64()), logCode), signer, testKey) - txs = append(txs, tx2) - expectedProfit += 56996 * baseFee.Uint64() - - tx3, _ := types.SignTx(types.NewTransaction(nonce+2, testAddr, big.NewInt(10), 21000, baseFee, nil), signer, testKey) - txs = append(txs, tx3) - - // this transaction sends 7 wei to the proposer fee recipient, this should count as a profit - tx4, _ := types.SignTx(types.NewTransaction(nonce+3, testValidatorAddr, big.NewInt(7), 21000, baseFee, nil), signer, testKey) - txs = append(txs, tx4) - expectedProfit += 7 - - // transactions from the proposer fee recipient - - // this transaction sends 3 wei from the proposer fee recipient to the proposer fee recipient and pays tip of baseFee - // this should not count as a profit (because balance does not increase) - // Base fee is burned from the balance so it should decrease decreasing the profit. - tx5, _ := types.SignTx(types.NewTransaction(0, testValidatorAddr, big.NewInt(3), 21000, big.NewInt(2*baseFee.Int64()), nil), signer, testValidatorKey) - txs = append(txs, tx5) - expectedProfit -= 21000 * baseFee.Uint64() - - // this tx sends 11 wei from the proposer fee recipient to some other address and burns 21000*baseFee - // this should count as negative profit - tx6, _ := types.SignTx(types.NewTransaction(1, testAddr, big.NewInt(11), 21000, baseFee, nil), signer, testValidatorKey) - txs = append(txs, tx6) - expectedProfit -= 11 + 21000*baseFee.Uint64() - - withdrawals := []*types.Withdrawal{ - { - Index: 0, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - { - Index: 1, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - } - withdrawalsRoot := types.DeriveSha(types.Withdrawals(withdrawals), trie.NewStackTrie(nil)) - - buildBlockArgs := buildBlockArgs{ - parentHash: lastBlock.Hash(), - parentRoot: lastBlock.Root(), - feeRecipient: testValidatorAddr, - txs: txs, - random: common.Hash{}, - number: lastBlock.NumberU64() + 1, - gasLimit: lastBlock.GasLimit(), - timestamp: lastBlock.Time() + 5, - extraData: nil, - baseFeePerGas: baseFee, - withdrawals: withdrawals, - } - - execData, err := buildBlock(buildBlockArgs, ethservice.BlockChain()) - require.NoError(t, err) - - value := big.NewInt(int64(expectedProfit)) - - req, err := executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.NoError(t, api.ValidateBuilderSubmissionV2(req)) - - // try to claim less profit than expected, should work - value.SetUint64(expectedProfit - 1) - - req, err = executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.NoError(t, api.ValidateBuilderSubmissionV2(req)) - - // try to claim more profit than expected, should fail - value.SetUint64(expectedProfit + 1) - - req, err = executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(req), "payment") -} - -func TestValidateBuilderSubmissionV2_Blocklist(t *testing.T) { - genesis, preMergeBlocks := generatePreMergeChain(20) - lastBlock := preMergeBlocks[len(preMergeBlocks)-1] - time := lastBlock.Time() + 5 - genesis.Config.ShanghaiTime = &time - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - accessVerifier := &AccessVerifier{ - blacklistedAddresses: map[common.Address]struct{}{ - testAddr: {}, - }, - } - - apiWithBlock := NewBlockValidationAPI(ethservice, accessVerifier, true, true) - apiNoBlock := NewBlockValidationAPI(ethservice, nil, true, true) - - baseFee := eip1559.CalcBaseFee(ethservice.BlockChain().Config(), lastBlock.Header()) - blockedTxs := make(types.Transactions, 0) - - statedb, _ := ethservice.BlockChain().StateAt(lastBlock.Root()) - - signer := types.LatestSigner(ethservice.BlockChain().Config()) - - nonce := statedb.GetNonce(testAddr) - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, baseFee, nil), signer, testKey) - blockedTxs = append(blockedTxs, tx) - - nonce = statedb.GetNonce(testBuilderAddr) - tx, _ = types.SignTx(types.NewTransaction(nonce, testAddr, big.NewInt(10), 21000, baseFee, nil), signer, testBuilderKey) - blockedTxs = append(blockedTxs, tx) - - withdrawalsRoot := types.DeriveSha(types.Withdrawals(nil), trie.NewStackTrie(nil)) - - for i, tx := range blockedTxs { - t.Run(fmt.Sprintf("tx %d", i), func(t *testing.T) { - buildBlockArgs := buildBlockArgs{ - parentHash: lastBlock.Hash(), - parentRoot: lastBlock.Root(), - feeRecipient: testValidatorAddr, - txs: types.Transactions{tx}, - random: common.Hash{}, - number: lastBlock.NumberU64() + 1, - gasLimit: lastBlock.GasLimit(), - timestamp: lastBlock.Time() + 5, - extraData: nil, - baseFeePerGas: baseFee, - withdrawals: nil, - } - - execData, err := buildBlock(buildBlockArgs, ethservice.BlockChain()) - require.NoError(t, err) - - req, err := executableDataToBlockValidationRequest(execData, testValidatorAddr, common.Big0, withdrawalsRoot) - require.NoError(t, err) - - require.NoError(t, apiNoBlock.ValidateBuilderSubmissionV2(req)) - require.ErrorContains(t, apiWithBlock.ValidateBuilderSubmissionV2(req), "blacklisted") - }) - } -} - -// This tests payment when the proposer fee recipient receives CL withdrawal. -func TestValidateBuilderSubmissionV2_ExcludeWithdrawals(t *testing.T) { - genesis, preMergeBlocks := generatePreMergeChain(20) - lastBlock := preMergeBlocks[len(preMergeBlocks)-1] - time := lastBlock.Time() + 5 - genesis.Config.ShanghaiTime = &time - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewBlockValidationAPI(ethservice, nil, true, true) - - baseFee := eip1559.CalcBaseFee(ethservice.BlockChain().Config(), lastBlock.Header()) - txs := make(types.Transactions, 0) - - statedb, _ := ethservice.BlockChain().StateAt(lastBlock.Root()) - nonce := statedb.GetNonce(testAddr) - signer := types.LatestSigner(ethservice.BlockChain().Config()) - - expectedProfit := uint64(0) - - tx1, _ := types.SignTx(types.NewTransaction(nonce, common.Address{0x16}, big.NewInt(10), 21000, big.NewInt(2*baseFee.Int64()), nil), signer, testKey) - txs = append(txs, tx1) - expectedProfit += 21000 * baseFee.Uint64() - - // this tx will use 56996 gas - tx2, _ := types.SignTx(types.NewContractCreation(nonce+1, new(big.Int), 1000000, big.NewInt(2*baseFee.Int64()), logCode), signer, testKey) - txs = append(txs, tx2) - expectedProfit += 56996 * baseFee.Uint64() - - tx3, _ := types.SignTx(types.NewTransaction(nonce+2, testAddr, big.NewInt(10), 21000, baseFee, nil), signer, testKey) - txs = append(txs, tx3) - - // this transaction sends 7 wei to the proposer fee recipient, this should count as a profit - tx4, _ := types.SignTx(types.NewTransaction(nonce+3, testValidatorAddr, big.NewInt(7), 21000, baseFee, nil), signer, testKey) - txs = append(txs, tx4) - expectedProfit += 7 - - withdrawals := []*types.Withdrawal{ - { - Index: 0, - Validator: 1, - Amount: 100, - Address: testAddr, - }, - { - Index: 1, - Validator: 1, - Amount: 17, - Address: testValidatorAddr, - }, - { - Index: 1, - Validator: 1, - Amount: 21, - Address: testValidatorAddr, - }, - } - withdrawalsRoot := types.DeriveSha(types.Withdrawals(withdrawals), trie.NewStackTrie(nil)) - - buildBlockArgs := buildBlockArgs{ - parentHash: lastBlock.Hash(), - parentRoot: lastBlock.Root(), - feeRecipient: testValidatorAddr, - txs: txs, - random: common.Hash{}, - number: lastBlock.NumberU64() + 1, - gasLimit: lastBlock.GasLimit(), - timestamp: lastBlock.Time() + 5, - extraData: nil, - baseFeePerGas: baseFee, - withdrawals: withdrawals, - } - - execData, err := buildBlock(buildBlockArgs, ethservice.BlockChain()) - require.NoError(t, err) - - value := big.NewInt(int64(expectedProfit)) - - req, err := executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.NoError(t, api.ValidateBuilderSubmissionV2(req)) - - // try to claim less profit than expected, should work - value.SetUint64(expectedProfit - 1) - - req, err = executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.NoError(t, api.ValidateBuilderSubmissionV2(req)) - - // try to claim more profit than expected, should fail - value.SetUint64(expectedProfit + 1) - - req, err = executableDataToBlockValidationRequest(execData, testValidatorAddr, value, withdrawalsRoot) - require.NoError(t, err) - require.ErrorContains(t, api.ValidateBuilderSubmissionV2(req), "payment") -} diff --git a/builder/eth/bloombits.go b/builder/eth/bloombits.go deleted file mode 100644 index 0cb7050d2..000000000 --- a/builder/eth/bloombits.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 eth - -import ( - "time" - - "github.com/ethereum/go-ethereum/common/bitutil" - "github.com/ethereum/go-ethereum/core/rawdb" -) - -const ( - // bloomServiceThreads is the number of goroutines used globally by an Ethereum - // instance to service bloombits lookups for all running filters. - bloomServiceThreads = 16 - - // bloomFilterThreads is the number of goroutines used locally per filter to - // multiplex requests onto the global servicing goroutines. - bloomFilterThreads = 3 - - // bloomRetrievalBatch is the maximum number of bloom bit retrievals to service - // in a single batch. - bloomRetrievalBatch = 16 - - // bloomRetrievalWait is the maximum time to wait for enough bloom bit requests - // to accumulate request an entire batch (avoiding hysteresis). - bloomRetrievalWait = time.Duration(0) -) - -// startBloomHandlers starts a batch of goroutines to accept bloom bit database -// retrievals from possibly a range of filters and serving the data to satisfy. -func (eth *Ethereum) startBloomHandlers(sectionSize uint64) { - for i := 0; i < bloomServiceThreads; i++ { - go func() { - for { - select { - case <-eth.closeBloomHandler: - return - - case request := <-eth.bloomRequests: - task := <-request - task.Bitsets = make([][]byte, len(task.Sections)) - for i, section := range task.Sections { - head := rawdb.ReadCanonicalHash(eth.chainDb, (section+1)*sectionSize-1) - if compVector, err := rawdb.ReadBloomBits(eth.chainDb, task.Bit, section, head); err == nil { - if blob, err := bitutil.DecompressBytes(compVector, int(sectionSize/8)); err == nil { - task.Bitsets[i] = blob - } else { - task.Error = err - } - } else { - task.Error = err - } - } - request <- task - } - } - }() - } -} diff --git a/builder/eth/catalyst/api.go b/builder/eth/catalyst/api.go deleted file mode 100644 index 8d7503237..000000000 --- a/builder/eth/catalyst/api.go +++ /dev/null @@ -1,896 +0,0 @@ -// 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 catalyst implements the temporary eth1/eth2 RPC integration. -package catalyst - -import ( - "errors" - "fmt" - "sync" - "time" - - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/internal/version" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/params/forks" - "github.com/ethereum/go-ethereum/rpc" -) - -// Register adds the engine API to the full node. -func Register(stack *node.Node, backend *eth.Ethereum) error { - log.Warn("Engine API enabled", "protocol", "eth") - stack.RegisterAPIs([]rpc.API{ - { - Namespace: "engine", - Service: NewConsensusAPI(backend), - Authenticated: true, - }, - }) - return nil -} - -const ( - // invalidBlockHitEviction is the number of times an invalid block can be - // referenced in forkchoice update or new payload before it is attempted - // to be reprocessed again. - invalidBlockHitEviction = 128 - - // invalidTipsetsCap is the max number of recent block hashes tracked that - // have lead to some bad ancestor block. It's just an OOM protection. - invalidTipsetsCap = 512 - - // beaconUpdateStartupTimeout is the time to wait for a beacon client to get - // attached before starting to issue warnings. - beaconUpdateStartupTimeout = 30 * time.Second - - // beaconUpdateConsensusTimeout is the max time allowed for a beacon client - // to send a consensus update before it's considered offline and the user is - // warned. - beaconUpdateConsensusTimeout = 2 * time.Minute - - // beaconUpdateWarnFrequency is the frequency at which to warn the user that - // the beacon client is offline. - beaconUpdateWarnFrequency = 5 * time.Minute -) - -// All methods provided over the engine endpoint. -var caps = []string{ - "engine_forkchoiceUpdatedV1", - "engine_forkchoiceUpdatedV2", - "engine_forkchoiceUpdatedV3", - "engine_exchangeTransitionConfigurationV1", - "engine_getPayloadV1", - "engine_getPayloadV2", - "engine_getPayloadV3", - "engine_newPayloadV1", - "engine_newPayloadV2", - "engine_newPayloadV3", - "engine_getPayloadBodiesByHashV1", - "engine_getPayloadBodiesByRangeV1", - "engine_getClientVersionV1", -} - -type ConsensusAPI struct { - eth *eth.Ethereum - - remoteBlocks *headerQueue // Cache of remote payloads received - localBlocks *payloadQueue // Cache of local payloads generated - - // The forkchoice update and new payload method require us to return the - // latest valid hash in an invalid chain. To support that return, we need - // to track historical bad blocks as well as bad tipsets in case a chain - // is constantly built on it. - // - // There are a few important caveats in this mechanism: - // - The bad block tracking is ephemeral, in-memory only. We must never - // persist any bad block information to disk as a bug in Geth could end - // up blocking a valid chain, even if a later Geth update would accept - // it. - // - Bad blocks will get forgotten after a certain threshold of import - // attempts and will be retried. The rationale is that if the network - // really-really-really tries to feed us a block, we should give it a - // new chance, perhaps us being racey instead of the block being legit - // bad (this happened in Geth at a point with import vs. pending race). - // - Tracking all the blocks built on top of the bad one could be a bit - // problematic, so we will only track the head chain segment of a bad - // chain to allow discarding progressing bad chains and side chains, - // without tracking too much bad data. - invalidBlocksHits map[common.Hash]int // Ephemeral cache to track invalid blocks and their hit count - invalidTipsets map[common.Hash]*types.Header // Ephemeral cache to track invalid tipsets and their bad ancestor - invalidLock sync.Mutex // Protects the invalid maps from concurrent access - - // Geth can appear to be stuck or do strange things if the beacon client is - // offline or is sending us strange data. Stash some update stats away so - // that we can warn the user and not have them open issues on our tracker. - lastTransitionUpdate time.Time - lastTransitionLock sync.Mutex - lastForkchoiceUpdate time.Time - lastForkchoiceLock sync.Mutex - lastNewPayloadUpdate time.Time - lastNewPayloadLock sync.Mutex - - forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method - newPayloadLock sync.Mutex // Lock for the NewPayload method -} - -// NewConsensusAPI creates a new consensus api for the given backend. -// The underlying blockchain needs to have a valid terminal total difficulty set. -func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI { - api := newConsensusAPIWithoutHeartbeat(eth) - go api.heartbeat() - return api -} - -// newConsensusAPIWithoutHeartbeat creates a new consensus api for the SimulatedBeacon Node. -func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI { - if eth.BlockChain().Config().TerminalTotalDifficulty == nil { - log.Warn("Engine API started but chain not configured for merge yet") - } - api := &ConsensusAPI{ - eth: eth, - remoteBlocks: newHeaderQueue(), - localBlocks: newPayloadQueue(), - invalidBlocksHits: make(map[common.Hash]int), - invalidTipsets: make(map[common.Hash]*types.Header), - } - eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor) - return api -} - -// ForkchoiceUpdatedV1 has several responsibilities: -// -// We try to set our blockchain to the headBlock. -// -// If the method is called with an empty head block: we return success, which can be used -// to check if the engine API is enabled. -// -// If the total difficulty was not reached: we return INVALID. -// -// If the finalizedBlockHash is set: we check if we have the finalizedBlockHash in our db, -// if not we start a sync. -// -// If there are payloadAttributes: we try to assemble a block with the payloadAttributes -// and return its payloadID. -func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if payloadAttributes != nil { - if payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals and beacon root not supported in V1")) - } - if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock, payloadAttributes.Timestamp) { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai")) - } - } - return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false) -} - -// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload -// attributes. It supports both PayloadAttributesV1 and PayloadAttributesV2. -func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if params != nil { - switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) { - case forks.Paris: - if params.Withdrawals != nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals before shanghai")) - } - case forks.Shanghai: - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals")) - } - default: - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called with paris and shanghai payloads")) - } - if params.BeaconRoot != nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("unexpected beacon root")) - } - } - return api.forkchoiceUpdated(update, params, engine.PayloadV2, false) -} - -// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root -// in the payload attributes. It supports only PayloadAttributesV3. -func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { - if params != nil { - // TODO(matt): according to https://github.com/ethereum/execution-apis/pull/498, - // payload attributes that are invalid should return error - // engine.InvalidPayloadAttributes. Once hive updates this, we should update - // on our end. - if params.Withdrawals == nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing withdrawals")) - } - if params.BeaconRoot == nil { - return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("missing beacon root")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) - } - } - // TODO(matt): the spec requires that fcu is applied when called on a valid - // hash, even if params are wrong. To do this we need to split up - // forkchoiceUpdate into a function that only updates the head and then a - // function that kicks off block construction. - return api.forkchoiceUpdated(update, params, engine.PayloadV3, false) -} - -func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) { - api.forkchoiceLock.Lock() - defer api.forkchoiceLock.Unlock() - - log.Trace("Engine API request received", "method", "ForkchoiceUpdated", "head", update.HeadBlockHash, "finalized", update.FinalizedBlockHash, "safe", update.SafeBlockHash) - if update.HeadBlockHash == (common.Hash{}) { - log.Warn("Forkchoice requested update to zero hash") - return engine.STATUS_INVALID, nil // TODO(karalabe): Why does someone send us this? - } - // Stash away the last update to warn the user if the beacon client goes offline - api.lastForkchoiceLock.Lock() - api.lastForkchoiceUpdate = time.Now() - api.lastForkchoiceLock.Unlock() - - // Check whether we have the block yet in our database or not. If not, we'll - // need to either trigger a sync, or to reject this forkchoice update for a - // reason. - block := api.eth.BlockChain().GetBlockByHash(update.HeadBlockHash) - if block == nil { - // If this block was previously invalidated, keep rejecting it here too - if res := api.checkInvalidAncestor(update.HeadBlockHash, update.HeadBlockHash); res != nil { - return engine.ForkChoiceResponse{PayloadStatus: *res, PayloadID: nil}, nil - } - // If the head hash is unknown (was not given to us in a newPayload request), - // we cannot resolve the header, so not much to do. This could be extended in - // the future to resolve from the `eth` network, but it's an unexpected case - // that should be fixed, not papered over. - header := api.remoteBlocks.get(update.HeadBlockHash) - if header == nil { - log.Warn("Forkchoice requested unknown head", "hash", update.HeadBlockHash) - return engine.STATUS_SYNCING, nil - } - // If the finalized hash is known, we can direct the downloader to move - // potentially more data to the freezer from the get go. - finalized := api.remoteBlocks.get(update.FinalizedBlockHash) - - // Header advertised via a past newPayload request. Start syncing to it. - // Before we do however, make sure any legacy sync in switched off so we - // don't accidentally have 2 cycles running. - if merger := api.eth.Merger(); !merger.TDDReached() { - merger.ReachTTD() - api.eth.Downloader().Cancel() - } - context := []interface{}{"number", header.Number, "hash", header.Hash()} - if update.FinalizedBlockHash != (common.Hash{}) { - if finalized == nil { - context = append(context, []interface{}{"finalized", "unknown"}...) - } else { - context = append(context, []interface{}{"finalized", finalized.Number}...) - } - } - log.Info("Forkchoice requested sync to new head", context...) - if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil { - return engine.STATUS_SYNCING, err - } - return engine.STATUS_SYNCING, nil - } - // Block is known locally, just sanity check that the beacon client does not - // attempt to push us back to before the merge. - if block.Difficulty().BitLen() > 0 || block.NumberU64() == 0 { - var ( - td = api.eth.BlockChain().GetTd(update.HeadBlockHash, block.NumberU64()) - ptd = api.eth.BlockChain().GetTd(block.ParentHash(), block.NumberU64()-1) - ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty - ) - if td == nil || (block.NumberU64() > 0 && ptd == nil) { - log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", update.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd) - return engine.STATUS_INVALID, errors.New("TDs unavailable for TDD check") - } - if td.Cmp(ttd) < 0 { - log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) - return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil - } - if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 { - log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) - return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil - } - } - valid := func(id *engine.PayloadID) engine.ForkChoiceResponse { - return engine.ForkChoiceResponse{ - PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash}, - PayloadID: id, - } - } - if rawdb.ReadCanonicalHash(api.eth.ChainDb(), block.NumberU64()) != update.HeadBlockHash { - // Block is not canonical, set head. - if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil { - return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err - } - } else if api.eth.BlockChain().CurrentBlock().Hash() == update.HeadBlockHash { - // If the specified head matches with our local head, do nothing and keep - // generating the payload. It's a special corner case that a few slots are - // missing and we are requested to generate the payload in slot. - } else { - // If the head block is already in our canonical chain, the beacon client is - // probably resyncing. Ignore the update. - log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number) - return valid(nil), nil - } - api.eth.SetSynced() - - // If the beacon client also advertised a finalized block, mark the local - // chain final and completely in PoS mode. - if update.FinalizedBlockHash != (common.Hash{}) { - if merger := api.eth.Merger(); !merger.PoSFinalized() { - merger.FinalizePoS() - } - // If the finalized block is not in our canonical tree, something is wrong - finalBlock := api.eth.BlockChain().GetBlockByHash(update.FinalizedBlockHash) - if finalBlock == nil { - log.Warn("Final block not available in database", "hash", update.FinalizedBlockHash) - return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not available in database")) - } else if rawdb.ReadCanonicalHash(api.eth.ChainDb(), finalBlock.NumberU64()) != update.FinalizedBlockHash { - log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", update.HeadBlockHash) - return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not in canonical chain")) - } - // Set the finalized block - api.eth.BlockChain().SetFinalized(finalBlock.Header()) - } - // Check if the safe block hash is in our canonical tree, if not something is wrong - if update.SafeBlockHash != (common.Hash{}) { - safeBlock := api.eth.BlockChain().GetBlockByHash(update.SafeBlockHash) - if safeBlock == nil { - log.Warn("Safe block not available in database") - return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not available in database")) - } - if rawdb.ReadCanonicalHash(api.eth.ChainDb(), safeBlock.NumberU64()) != update.SafeBlockHash { - log.Warn("Safe block not in canonical chain") - return engine.STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain")) - } - // Set the safe block - api.eth.BlockChain().SetSafe(safeBlock.Header()) - } - // If payload generation was requested, create a new block to be potentially - // sealed by the beacon client. The payload will be requested later, and we - // will replace it arbitrarily many times in between. - if payloadAttributes != nil { - args := &miner.BuildPayloadArgs{ - Parent: update.HeadBlockHash, - Timestamp: payloadAttributes.Timestamp, - FeeRecipient: payloadAttributes.SuggestedFeeRecipient, - GasLimit: payloadAttributes.GasLimit, - Random: payloadAttributes.Random, - Withdrawals: payloadAttributes.Withdrawals, - BeaconRoot: payloadAttributes.BeaconRoot, - Version: payloadVersion, - BlockHook: nil, - } - id := args.Id() - // If we already are busy generating this work, then we do not need - // to start a second process. - if api.localBlocks.has(id) { - return valid(&id), nil - } - // If the beacon chain is ran by a simulator, then transaction insertion, - // block insertion and block production will happen without any timing - // delay between them. This will cause flaky simulator executions due to - // the transaction pool running its internal reset operation on a back- - // ground thread. To avoid the racey behavior - in simulator mode - the - // pool will be explicitly blocked on its reset before continuing to the - // block production below. - if simulatorMode { - if err := api.eth.TxPool().Sync(); err != nil { - log.Error("Failed to sync transaction pool", "err", err) - return valid(nil), engine.InvalidPayloadAttributes.With(err) - } - } - payload, err := api.eth.Miner().BuildPayload(args) - if err != nil { - log.Error("Failed to build payload", "err", err) - return valid(nil), engine.InvalidPayloadAttributes.With(err) - } - api.localBlocks.put(id, payload) - return valid(&id), nil - } - return valid(nil), nil -} - -// ExchangeTransitionConfigurationV1 checks the given configuration against -// the configuration of the node. -func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.TransitionConfigurationV1) (*engine.TransitionConfigurationV1, error) { - log.Trace("Engine API request received", "method", "ExchangeTransitionConfiguration", "ttd", config.TerminalTotalDifficulty) - if config.TerminalTotalDifficulty == nil { - return nil, errors.New("invalid terminal total difficulty") - } - // Stash away the last update to warn the user if the beacon client goes offline - api.lastTransitionLock.Lock() - api.lastTransitionUpdate = time.Now() - api.lastTransitionLock.Unlock() - - ttd := api.eth.BlockChain().Config().TerminalTotalDifficulty - if ttd == nil || ttd.Cmp(config.TerminalTotalDifficulty.ToInt()) != 0 { - log.Warn("Invalid TTD configured", "geth", ttd, "beacon", config.TerminalTotalDifficulty) - return nil, fmt.Errorf("invalid ttd: execution %v consensus %v", ttd, config.TerminalTotalDifficulty) - } - if config.TerminalBlockHash != (common.Hash{}) { - if hash := api.eth.BlockChain().GetCanonicalHash(uint64(config.TerminalBlockNumber)); hash == config.TerminalBlockHash { - return &engine.TransitionConfigurationV1{ - TerminalTotalDifficulty: (*hexutil.Big)(ttd), - TerminalBlockHash: config.TerminalBlockHash, - TerminalBlockNumber: config.TerminalBlockNumber, - }, nil - } - return nil, errors.New("invalid terminal block hash") - } - return &engine.TransitionConfigurationV1{TerminalTotalDifficulty: (*hexutil.Big)(ttd)}, nil -} - -// GetPayloadV1 returns a cached payload by id. -func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) { - if !payloadID.Is(engine.PayloadV1) { - return nil, engine.UnsupportedFork - } - data, err := api.getPayload(payloadID, false) - if err != nil { - return nil, err - } - return data.ExecutionPayload, nil -} - -// GetPayloadV2 returns a cached payload by id. -func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { - if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) { - return nil, engine.UnsupportedFork - } - return api.getPayload(payloadID, false) -} - -// GetPayloadV3 returns a cached payload by id. -func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { - if !payloadID.Is(engine.PayloadV3) { - return nil, engine.UnsupportedFork - } - return api.getPayload(payloadID, false) -} - -func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) { - log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID) - data := api.localBlocks.get(payloadID, full) - if data == nil { - return nil, engine.UnknownPayload - } - return data, nil -} - -// NewPayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. -func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) - } - return api.newPayload(params, nil, nil) -} - -// NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. -func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) - } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - } else { - if params.Withdrawals != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai")) - } - } - if params.ExcessBlobGas != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil excessBlobGas pre-cancun")) - } - if params.BlobGasUsed != nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil blobGasUsed pre-cancun")) - } - return api.newPayload(params, nil, nil) -} - -// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. -func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { - if params.Withdrawals == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) - } - if params.ExcessBlobGas == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun")) - } - if params.BlobGasUsed == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun")) - } - - if versionedHashes == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun")) - } - if beaconRoot == nil { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) - } - - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { - return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads")) - } - return api.newPayload(params, versionedHashes, beaconRoot) -} - -func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) { - // The locking here is, strictly, not required. Without these locks, this can happen: - // - // 1. NewPayload( execdata-N ) is invoked from the CL. It goes all the way down to - // api.eth.BlockChain().InsertBlockWithoutSetHead, where it is blocked on - // e.g database compaction. - // 2. The call times out on the CL layer, which issues another NewPayload (execdata-N) call. - // Similarly, this also get stuck on the same place. Importantly, since the - // first call has not gone through, the early checks for "do we already have this block" - // will all return false. - // 3. When the db compaction ends, then N calls inserting the same payload are processed - // sequentially. - // Hence, we use a lock here, to be sure that the previous call has finished before we - // check whether we already have the block locally. - api.newPayloadLock.Lock() - defer api.newPayloadLock.Unlock() - - log.Trace("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash) - block, err := engine.ExecutableDataToBlock(params, versionedHashes, beaconRoot) - if err != nil { - log.Warn("Invalid NewPayload params", "params", params, "error", err) - return api.invalid(err, nil), nil - } - // Stash away the last update to warn the user if the beacon client goes offline - api.lastNewPayloadLock.Lock() - api.lastNewPayloadUpdate = time.Now() - api.lastNewPayloadLock.Unlock() - - // If we already have the block locally, ignore the entire execution and just - // return a fake success. - if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil { - log.Warn("Ignoring already known beacon payload", "number", params.Number, "hash", params.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) - hash := block.Hash() - return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil - } - // If this block was rejected previously, keep rejecting it - if res := api.checkInvalidAncestor(block.Hash(), block.Hash()); res != nil { - return *res, nil - } - // If the parent is missing, we - in theory - could trigger a sync, but that - // would also entail a reorg. That is problematic if multiple sibling blocks - // are being fed to us, and even more so, if some semi-distant uncle shortens - // our live chain. As such, payload execution will not permit reorgs and thus - // will not trigger a sync cycle. That is fine though, if we get a fork choice - // update after legit payload executions. - parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1) - if parent == nil { - return api.delayPayloadImport(block) - } - // We have an existing parent, do some sanity checks to avoid the beacon client - // triggering too early - var ( - ptd = api.eth.BlockChain().GetTd(parent.Hash(), parent.NumberU64()) - ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty - gptd = api.eth.BlockChain().GetTd(parent.ParentHash(), parent.NumberU64()-1) - ) - if ptd.Cmp(ttd) < 0 { - log.Warn("Ignoring pre-merge payload", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd) - return engine.INVALID_TERMINAL_BLOCK, nil - } - if parent.Difficulty().BitLen() > 0 && gptd != nil && gptd.Cmp(ttd) >= 0 { - log.Error("Ignoring pre-merge parent block", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd) - return engine.INVALID_TERMINAL_BLOCK, nil - } - if block.Time() <= parent.Time() { - log.Warn("Invalid timestamp", "parent", block.Time(), "block", block.Time()) - return api.invalid(errors.New("invalid timestamp"), parent.Header()), nil - } - // Another corner case: if the node is in snap sync mode, but the CL client - // tries to make it import a block. That should be denied as pushing something - // into the database directly will conflict with the assumptions of snap sync - // that it has an empty db that it can fill itself. - if api.eth.SyncMode() != downloader.FullSync { - return api.delayPayloadImport(block) - } - if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { - api.remoteBlocks.put(block.Hash(), block.Header()) - log.Warn("State not available, ignoring new payload") - return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil - } - log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number) - if err := api.eth.BlockChain().InsertBlockWithoutSetHead(block); err != nil { - log.Warn("NewPayloadV1: inserting block failed", "error", err) - - api.invalidLock.Lock() - api.invalidBlocksHits[block.Hash()] = 1 - api.invalidTipsets[block.Hash()] = block.Header() - api.invalidLock.Unlock() - - return api.invalid(err, parent.Header()), nil - } - // We've accepted a valid payload from the beacon client. Mark the local - // chain transitions to notify other subsystems (e.g. downloader) of the - // behavioral change. - if merger := api.eth.Merger(); !merger.TDDReached() { - merger.ReachTTD() - api.eth.Downloader().Cancel() - } - hash := block.Hash() - return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil -} - -// delayPayloadImport stashes the given block away for import at a later time, -// either via a forkchoice update or a sync extension. This method is meant to -// be called by the newpayload command when the block seems to be ok, but some -// prerequisite prevents it from being processed (e.g. no parent, or snap sync). -func (api *ConsensusAPI) delayPayloadImport(block *types.Block) (engine.PayloadStatusV1, error) { - // Sanity check that this block's parent is not on a previously invalidated - // chain. If it is, mark the block as invalid too. - if res := api.checkInvalidAncestor(block.ParentHash(), block.Hash()); res != nil { - return *res, nil - } - // Stash the block away for a potential forced forkchoice update to it - // at a later time. - api.remoteBlocks.put(block.Hash(), block.Header()) - - // Although we don't want to trigger a sync, if there is one already in - // progress, try to extend if with the current payload request to relieve - // some strain from the forkchoice update. - err := api.eth.Downloader().BeaconExtend(api.eth.SyncMode(), block.Header()) - if err == nil { - log.Debug("Payload accepted for sync extension", "number", block.NumberU64(), "hash", block.Hash()) - return engine.PayloadStatusV1{Status: engine.SYNCING}, nil - } - // Either no beacon sync was started yet, or it rejected the delivered - // payload as non-integratable on top of the existing sync. We'll just - // have to rely on the beacon client to forcefully update the head with - // a forkchoice update request. - if api.eth.SyncMode() == downloader.FullSync { - // In full sync mode, failure to import a well-formed block can only mean - // that the parent state is missing and the syncer rejected extending the - // current cycle with the new payload. - log.Warn("Ignoring payload with missing parent", "number", block.NumberU64(), "hash", block.Hash(), "parent", block.ParentHash(), "reason", err) - } else { - // In non-full sync mode (i.e. snap sync) all payloads are rejected until - // snap sync terminates as snap sync relies on direct database injections - // and cannot afford concurrent out-if-band modifications via imports. - log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash(), "reason", err) - } - return engine.PayloadStatusV1{Status: engine.SYNCING}, nil -} - -// setInvalidAncestor is a callback for the downloader to notify us if a bad block -// is encountered during the async sync. -func (api *ConsensusAPI) setInvalidAncestor(invalid *types.Header, origin *types.Header) { - api.invalidLock.Lock() - defer api.invalidLock.Unlock() - - api.invalidTipsets[origin.Hash()] = invalid - api.invalidBlocksHits[invalid.Hash()]++ -} - -// checkInvalidAncestor checks whether the specified chain end links to a known -// bad ancestor. If yes, it constructs the payload failure response to return. -func (api *ConsensusAPI) checkInvalidAncestor(check common.Hash, head common.Hash) *engine.PayloadStatusV1 { - api.invalidLock.Lock() - defer api.invalidLock.Unlock() - - // If the hash to check is unknown, return valid - invalid, ok := api.invalidTipsets[check] - if !ok { - return nil - } - // If the bad hash was hit too many times, evict it and try to reprocess in - // the hopes that we have a data race that we can exit out of. - badHash := invalid.Hash() - - api.invalidBlocksHits[badHash]++ - if api.invalidBlocksHits[badHash] >= invalidBlockHitEviction { - log.Warn("Too many bad block import attempt, trying", "number", invalid.Number, "hash", badHash) - delete(api.invalidBlocksHits, badHash) - - for descendant, badHeader := range api.invalidTipsets { - if badHeader.Hash() == badHash { - delete(api.invalidTipsets, descendant) - } - } - return nil - } - // Not too many failures yet, mark the head of the invalid chain as invalid - if check != head { - log.Warn("Marked new chain head as invalid", "hash", head, "badnumber", invalid.Number, "badhash", badHash) - for len(api.invalidTipsets) >= invalidTipsetsCap { - for key := range api.invalidTipsets { - delete(api.invalidTipsets, key) - break - } - } - api.invalidTipsets[head] = invalid - } - // If the last valid hash is the terminal pow block, return 0x0 for latest valid hash - lastValid := &invalid.ParentHash - if header := api.eth.BlockChain().GetHeader(invalid.ParentHash, invalid.Number.Uint64()-1); header != nil && header.Difficulty.Sign() != 0 { - lastValid = &common.Hash{} - } - failure := "links to previously rejected block" - return &engine.PayloadStatusV1{ - Status: engine.INVALID, - LatestValidHash: lastValid, - ValidationError: &failure, - } -} - -// invalid returns a response "INVALID" with the latest valid hash supplied by latest. -func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.PayloadStatusV1 { - var currentHash *common.Hash - if latestValid != nil { - if latestValid.Difficulty.BitLen() != 0 { - // Set latest valid hash to 0x0 if parent is PoW block - currentHash = &common.Hash{} - } else { - // Otherwise set latest valid hash to parent hash - h := latestValid.Hash() - currentHash = &h - } - } - errorMsg := err.Error() - return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: currentHash, ValidationError: &errorMsg} -} - -// heartbeat loops indefinitely, and checks if there have been beacon client updates -// received in the last while. If not - or if they but strange ones - it warns the -// user that something might be off with their consensus node. -// -// TODO(karalabe): Spin this goroutine down somehow -func (api *ConsensusAPI) heartbeat() { - // Sleep a bit on startup since there's obviously no beacon client yet - // attached, so no need to print scary warnings to the user. - time.Sleep(beaconUpdateStartupTimeout) - - // If the network is not yet merged/merging, don't bother continuing. - if api.eth.BlockChain().Config().TerminalTotalDifficulty == nil { - return - } - - var offlineLogged time.Time - - for { - // Sleep a bit and retrieve the last known consensus updates - time.Sleep(5 * time.Second) - - api.lastTransitionLock.Lock() - lastTransitionUpdate := api.lastTransitionUpdate - api.lastTransitionLock.Unlock() - - api.lastForkchoiceLock.Lock() - lastForkchoiceUpdate := api.lastForkchoiceUpdate - api.lastForkchoiceLock.Unlock() - - api.lastNewPayloadLock.Lock() - lastNewPayloadUpdate := api.lastNewPayloadUpdate - api.lastNewPayloadLock.Unlock() - - // If there have been no updates for the past while, warn the user - // that the beacon client is probably offline - if api.eth.BlockChain().Config().TerminalTotalDifficultyPassed || api.eth.Merger().TDDReached() { - if time.Since(lastForkchoiceUpdate) <= beaconUpdateConsensusTimeout || time.Since(lastNewPayloadUpdate) <= beaconUpdateConsensusTimeout { - offlineLogged = time.Time{} - continue - } - - if time.Since(offlineLogged) > beaconUpdateWarnFrequency { - if lastForkchoiceUpdate.IsZero() && lastNewPayloadUpdate.IsZero() { - if lastTransitionUpdate.IsZero() { - log.Warn("Post-merge network, but no beacon client seen. Please launch one to follow the chain!") - } else { - log.Warn("Beacon client online, but never received consensus updates. Please ensure your beacon client is operational to follow the chain!") - } - } else { - log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!") - } - offlineLogged = time.Now() - } - continue - } - } -} - -// ExchangeCapabilities returns the current methods provided by this node. -func (api *ConsensusAPI) ExchangeCapabilities([]string) []string { - return caps -} - -// GetClientVersionV1 exchanges client version data of this node. -func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engine.ClientVersionV1 { - log.Trace("Engine API request received", "method", "GetClientVersionV1", "info", info.String()) - commit := make([]byte, 4) - if vcs, ok := version.VCS(); ok { - commit = common.FromHex(vcs.Commit)[0:4] - } - return []engine.ClientVersionV1{ - { - Code: engine.ClientCode, - Name: engine.ClientName, - Version: params.VersionWithMeta, - Commit: hexutil.Encode(commit), - }, - } -} - -// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list -// of block bodies by the engine api. -func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 { - bodies := make([]*engine.ExecutionPayloadBodyV1, len(hashes)) - for i, hash := range hashes { - block := api.eth.BlockChain().GetBlockByHash(hash) - bodies[i] = getBody(block) - } - return bodies -} - -// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range -// of block bodies by the engine api. -func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) { - if start == 0 || count == 0 { - return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count)) - } - if count > 1024 { - return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count)) - } - // limit count up until current - current := api.eth.BlockChain().CurrentBlock().Number.Uint64() - last := uint64(start) + uint64(count) - 1 - if last > current { - last = current - } - bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count)) - for i := uint64(start); i <= last; i++ { - block := api.eth.BlockChain().GetBlockByNumber(i) - bodies = append(bodies, getBody(block)) - } - return bodies, nil -} - -func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 { - if block == nil { - return nil - } - - var ( - body = block.Body() - txs = make([]hexutil.Bytes, len(body.Transactions)) - withdrawals = body.Withdrawals - ) - - for j, tx := range body.Transactions { - txs[j], _ = tx.MarshalBinary() - } - - // Post-shanghai withdrawals MUST be set to empty slice instead of nil - if withdrawals == nil && block.Header().WithdrawalsHash != nil { - withdrawals = make([]*types.Withdrawal, 0) - } - - return &engine.ExecutionPayloadBodyV1{ - TransactionData: txs, - Withdrawals: withdrawals, - } -} diff --git a/builder/eth/catalyst/api_test.go b/builder/eth/catalyst/api_test.go deleted file mode 100644 index 9c9086f3a..000000000 --- a/builder/eth/catalyst/api_test.go +++ /dev/null @@ -1,1690 +0,0 @@ -// 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 catalyst - -import ( - "bytes" - "context" - crand "crypto/rand" - "fmt" - "math/big" - "math/rand" - "reflect" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - beaconConsensus "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/trie" - "github.com/mattn/go-colorable" -) - -var ( - // testKey is a private key to use for funding a tester account. - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - - // testAddr is the Ethereum address of the tester account. - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - - testBalance = big.NewInt(2e18) -) - -func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { - config := *params.AllEthashProtocolChanges - engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker())) - if merged { - config.TerminalTotalDifficulty = common.Big0 - config.TerminalTotalDifficultyPassed = true - engine = beaconConsensus.NewFaker() - } - genesis := &core.Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{ - testAddr: {Balance: testBalance}, - params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")}, - }, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - BaseFee: big.NewInt(params.InitialBaseFee), - Difficulty: big.NewInt(0), - } - testNonce := uint64(0) - generate := func(i int, g *core.BlockGen) { - g.OffsetTime(5) - g.SetExtra([]byte("test")) - tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(&config), testKey) - g.AddTx(tx) - testNonce++ - } - _, blocks, _ := core.GenerateChainWithGenesis(genesis, engine, n, generate) - - if !merged { - totalDifficulty := big.NewInt(0) - for _, b := range blocks { - totalDifficulty.Add(totalDifficulty, b.Difficulty()) - } - config.TerminalTotalDifficulty = totalDifficulty - } - - return genesis, blocks -} - -func TestEth2AssembleBlock(t *testing.T) { - genesis, blocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, blocks) - defer n.Close() - - api := NewConsensusAPI(ethservice) - signer := types.NewEIP155Signer(ethservice.BlockChain().Config().ChainID) - tx, err := types.SignTx(types.NewTransaction(uint64(10), blocks[9].Coinbase(), big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey) - if err != nil { - t.Fatalf("error signing transaction, err=%v", err) - } - ethservice.TxPool().Add([]*types.Transaction{tx}, true, false, false) - blockParams := engine.PayloadAttributes{ - Timestamp: blocks[9].Time() + 5, - } - // The miner needs to pick up on the txs in the pool, so a few retries might be - // needed. - if _, testErr := assembleWithTransactions(api, blocks[9].Hash(), &blockParams, 1); testErr != nil { - t.Fatal(testErr) - } -} - -// assembleWithTransactions tries to assemble a block, retrying until it has 'want', -// number of transactions in it, or it has retried three times. -func assembleWithTransactions(api *ConsensusAPI, parentHash common.Hash, params *engine.PayloadAttributes, want int) (execData *engine.ExecutableData, err error) { - for retries := 3; retries > 0; retries-- { - execData, err = assembleBlock(api, parentHash, params) - if err != nil { - return nil, err - } - if have, want := len(execData.Transactions), want; have != want { - err = fmt.Errorf("invalid number of transactions, have %d want %d", have, want) - continue - } - return execData, nil - } - return nil, err -} - -func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) { - genesis, blocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, blocks[:9]) - defer n.Close() - - api := NewConsensusAPI(ethservice) - - // Put the 10th block's tx in the pool and produce a new block - txs := blocks[9].Transactions() - api.eth.TxPool().Add(txs, false, true, false) - blockParams := engine.PayloadAttributes{ - Timestamp: blocks[8].Time() + 5, - } - // The miner needs to pick up on the txs in the pool, so a few retries might be - // needed. - if _, err := assembleWithTransactions(api, blocks[8].Hash(), &blockParams, blocks[9].Transactions().Len()); err != nil { - t.Fatal(err) - } -} - -func TestSetHeadBeforeTotalDifficulty(t *testing.T) { - genesis, blocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, blocks) - defer n.Close() - - api := NewConsensusAPI(ethservice) - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: blocks[5].Hash(), - SafeBlockHash: common.Hash{}, - FinalizedBlockHash: common.Hash{}, - } - if resp, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - t.Errorf("fork choice updated should not error: %v", err) - } else if resp.PayloadStatus.Status != engine.INVALID_TERMINAL_BLOCK.Status { - t.Errorf("fork choice updated before total terminal difficulty should be INVALID") - } -} - -func TestEth2PrepareAndGetPayload(t *testing.T) { - genesis, blocks := generateMergeChain(10, false) - // We need to properly set the terminal total difficulty - genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty()) - n, ethservice := startEthService(t, genesis, blocks[:9]) - defer n.Close() - - api := NewConsensusAPI(ethservice) - - // Put the 10th block's tx in the pool and produce a new block - txs := blocks[9].Transactions() - ethservice.TxPool().Add(txs, true, false, false) - blockParams := engine.PayloadAttributes{ - Timestamp: blocks[8].Time() + 5, - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: blocks[8].Hash(), - SafeBlockHash: common.Hash{}, - FinalizedBlockHash: common.Hash{}, - } - _, err := api.ForkchoiceUpdatedV1(fcState, &blockParams) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - // give the payload some time to be built - time.Sleep(100 * time.Millisecond) - payloadID := (&miner.BuildPayloadArgs{ - Parent: fcState.HeadBlockHash, - Timestamp: blockParams.Timestamp, - FeeRecipient: blockParams.SuggestedFeeRecipient, - GasLimit: blockParams.GasLimit, - Random: blockParams.Random, - BeaconRoot: blockParams.BeaconRoot, - Version: engine.PayloadV1, - }).Id() - execData, err := api.GetPayloadV1(payloadID) - if err != nil { - t.Fatalf("error getting payload, err=%v", err) - } - if len(execData.Transactions) != blocks[9].Transactions().Len() { - t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions)) - } - // Test invalid payloadID - var invPayload engine.PayloadID - copy(invPayload[:], payloadID[:]) - invPayload[0] = ^invPayload[0] - _, err = api.GetPayloadV1(invPayload) - if err == nil { - t.Fatal("expected error retrieving invalid payload") - } -} - -func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan core.RemovedLogsEvent, wantNew, wantRemoved int) { - t.Helper() - - if len(logsCh) != wantNew { - t.Fatalf("wrong number of log events: got %d, want %d", len(logsCh), wantNew) - } - if len(rmLogsCh) != wantRemoved { - t.Fatalf("wrong number of removed log events: got %d, want %d", len(rmLogsCh), wantRemoved) - } - // Drain events. - for i := 0; i < len(logsCh); i++ { - <-logsCh - } - for i := 0; i < len(rmLogsCh); i++ { - <-rmLogsCh - } -} - -func TestInvalidPayloadTimestamp(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - var ( - api = NewConsensusAPI(ethservice) - parent = ethservice.BlockChain().CurrentBlock() - ) - tests := []struct { - time uint64 - shouldErr bool - }{ - {0, true}, - {parent.Time, true}, - {parent.Time - 1, true}, - {parent.Time + 1, false}, - {uint64(time.Now().Unix()) + uint64(time.Minute), false}, - } - - for i, test := range tests { - t.Run(fmt.Sprintf("Timestamp test: %v", i), func(t *testing.T) { - params := engine.PayloadAttributes{ - Timestamp: test.time, - Random: crypto.Keccak256Hash([]byte{byte(123)}), - SuggestedFeeRecipient: parent.Coinbase, - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - SafeBlockHash: common.Hash{}, - FinalizedBlockHash: common.Hash{}, - } - _, err := api.ForkchoiceUpdatedV1(fcState, ¶ms) - if test.shouldErr && err == nil { - t.Fatalf("expected error preparing payload with invalid timestamp, err=%v", err) - } else if !test.shouldErr && err != nil { - t.Fatalf("error preparing payload with valid timestamp, err=%v", err) - } - }) - } -} - -func TestEth2NewBlock(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - var ( - api = NewConsensusAPI(ethservice) - parent = preMergeBlocks[len(preMergeBlocks)-1] - - // This EVM code generates a log when the contract is created. - logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - ) - // The event channels. - newLogCh := make(chan []*types.Log, 10) - rmLogsCh := make(chan core.RemovedLogsEvent, 10) - ethservice.BlockChain().SubscribeLogsEvent(newLogCh) - ethservice.BlockChain().SubscribeRemovedLogsEvent(rmLogsCh) - - for i := 0; i < 10; i++ { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root()) - nonce := statedb.GetNonce(testAddr) - tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx}, true, false, false) - - execData, err := assembleWithTransactions(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time() + 5, - }, 1) - if err != nil { - t.Fatalf("Failed to create the executable data %v", err) - } - block, err := engine.ExecutableDataToBlock(*execData, nil, nil) - if err != nil { - t.Fatalf("Failed to convert executable data to block %v", err) - } - newResp, err := api.NewPayloadV1(*execData) - switch { - case err != nil: - t.Fatalf("Failed to insert block: %v", err) - case newResp.Status != "VALID": - t.Fatalf("Failed to insert block: %v", newResp.Status) - case ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1: - t.Fatalf("Chain head shouldn't be updated") - } - checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: block.Hash(), - SafeBlockHash: block.Hash(), - FinalizedBlockHash: block.Hash(), - } - if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - t.Fatalf("Failed to insert block: %v", err) - } - if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { - t.Fatalf("Chain head should be updated, have %d want %d", have, want) - } - checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) - - parent = block - } - - // Introduce fork chain - var ( - head = ethservice.BlockChain().CurrentBlock().Number.Uint64() - ) - parent = preMergeBlocks[len(preMergeBlocks)-1] - for i := 0; i < 10; i++ { - execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time() + 6, - }) - if err != nil { - t.Fatalf("Failed to create the executable data %v", err) - } - block, err := engine.ExecutableDataToBlock(*execData, nil, nil) - if err != nil { - t.Fatalf("Failed to convert executable data to block %v", err) - } - newResp, err := api.NewPayloadV1(*execData) - if err != nil || newResp.Status != "VALID" { - t.Fatalf("Failed to insert block: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != head { - t.Fatalf("Chain head shouldn't be updated") - } - - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: block.Hash(), - SafeBlockHash: block.Hash(), - FinalizedBlockHash: block.Hash(), - } - if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - t.Fatalf("Failed to insert block: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() { - t.Fatalf("Chain head should be updated") - } - parent, head = block, block.NumberU64() - } -} - -func TestEth2DeepReorg(t *testing.T) { - // TODO (MariusVanDerWijden) TestEth2DeepReorg is currently broken, because it tries to reorg - // before the totalTerminalDifficulty threshold - /* - genesis, preMergeBlocks := generateMergeChain(core.TriesInMemory * 2, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - var ( - api = NewConsensusAPI(ethservice, nil) - parent = preMergeBlocks[len(preMergeBlocks)-core.TriesInMemory-1] - head = ethservice.BlockChain().CurrentBlock().Number.Uint64()() - ) - if ethservice.BlockChain().HasBlockAndState(parent.Hash(), parent.NumberU64()) { - t.Errorf("Block %d not pruned", parent.NumberU64()) - } - for i := 0; i < 10; i++ { - execData, err := api.assembleBlock(AssembleBlockParams{ - ParentHash: parent.Hash(), - Timestamp: parent.Time() + 5, - }) - if err != nil { - t.Fatalf("Failed to create the executable data %v", err) - } - block, err := ExecutableDataToBlock(ethservice.BlockChain().Config(), parent.Header(), *execData) - if err != nil { - t.Fatalf("Failed to convert executable data to block %v", err) - } - newResp, err := api.ExecutePayload(*execData) - if err != nil || newResp.Status != "VALID" { - t.Fatalf("Failed to insert block: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64()() != head { - t.Fatalf("Chain head shouldn't be updated") - } - if err := api.setHead(block.Hash()); err != nil { - t.Fatalf("Failed to set head: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64()() != block.NumberU64() { - t.Fatalf("Chain head should be updated") - } - parent, head = block, block.NumberU64() - } - */ -} - -// startEthService creates a full node instance for testing. -func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) (*node.Node, *eth.Ethereum) { - t.Helper() - - n, err := node.New(&node.Config{ - P2P: p2p.Config{ - ListenAddr: "0.0.0.0:0", - NoDiscovery: true, - MaxPeers: 25, - }}) - if err != nil { - t.Fatal("can't create node:", err) - } - - ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} - ethservice, err := eth.New(n, ethcfg) - if err != nil { - t.Fatal("can't create eth service:", err) - } - if err := n.Start(); err != nil { - t.Fatal("can't start node:", err) - } - if _, err := ethservice.BlockChain().InsertChain(blocks); err != nil { - n.Close() - t.Fatal("can't import test blocks:", err) - } - - ethservice.SetEtherbase(testAddr) - ethservice.SetSynced() - return n, ethservice -} - -func TestFullAPI(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - var ( - parent = ethservice.BlockChain().CurrentBlock() - // This EVM code generates a log when the contract is created. - logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - ) - - callback := func(parent *types.Header) { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root) - nonce := statedb.GetNonce(testAddr) - tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx}, true, false, false) - } - - setupBlocks(t, ethservice, 10, parent, callback, nil) -} - -func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal) []*types.Header { - api := NewConsensusAPI(ethservice) - var blocks []*types.Header - for i := 0; i < n; i++ { - callback(parent) - var w []*types.Withdrawal - if withdrawals != nil { - w = withdrawals[i] - } - - payload := getNewPayload(t, api, parent, w) - execResp, err := api.NewPayloadV2(*payload) - if err != nil { - t.Fatalf("can't execute payload: %v", err) - } - if execResp.Status != engine.VALID { - t.Fatalf("invalid status: %v", execResp.Status) - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: payload.BlockHash, - SafeBlockHash: payload.ParentHash, - FinalizedBlockHash: payload.ParentHash, - } - if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - t.Fatalf("Failed to insert block: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { - t.Fatal("Chain head should be updated") - } - if ethservice.BlockChain().CurrentFinalBlock().Number.Uint64() != payload.Number-1 { - t.Fatal("Finalized block should be updated") - } - parent = ethservice.BlockChain().CurrentBlock() - blocks = append(blocks, parent) - } - return blocks -} - -func TestExchangeTransitionConfig(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - // invalid ttd - api := NewConsensusAPI(ethservice) - config := engine.TransitionConfigurationV1{ - TerminalTotalDifficulty: (*hexutil.Big)(big.NewInt(0)), - TerminalBlockHash: common.Hash{}, - TerminalBlockNumber: 0, - } - if _, err := api.ExchangeTransitionConfigurationV1(config); err == nil { - t.Fatal("expected error on invalid config, invalid ttd") - } - // invalid terminal block hash - config = engine.TransitionConfigurationV1{ - TerminalTotalDifficulty: (*hexutil.Big)(genesis.Config.TerminalTotalDifficulty), - TerminalBlockHash: common.Hash{1}, - TerminalBlockNumber: 0, - } - if _, err := api.ExchangeTransitionConfigurationV1(config); err == nil { - t.Fatal("expected error on invalid config, invalid hash") - } - // valid config - config = engine.TransitionConfigurationV1{ - TerminalTotalDifficulty: (*hexutil.Big)(genesis.Config.TerminalTotalDifficulty), - TerminalBlockHash: common.Hash{}, - TerminalBlockNumber: 0, - } - if _, err := api.ExchangeTransitionConfigurationV1(config); err != nil { - t.Fatalf("expected no error on valid config, got %v", err) - } - // valid config - config = engine.TransitionConfigurationV1{ - TerminalTotalDifficulty: (*hexutil.Big)(genesis.Config.TerminalTotalDifficulty), - TerminalBlockHash: preMergeBlocks[5].Hash(), - TerminalBlockNumber: 6, - } - if _, err := api.ExchangeTransitionConfigurationV1(config); err != nil { - t.Fatalf("expected no error on valid config, got %v", err) - } -} - -/* -TestNewPayloadOnInvalidChain sets up a valid chain and tries to feed blocks -from an invalid chain to test if latestValidHash (LVH) works correctly. - -We set up the following chain where P1 ... Pn and P1†are valid while -P1' is invalid. -We expect -(1) The LVH to point to the current inserted payload if it was valid. -(2) The LVH to point to the valid parent on an invalid payload (if the parent is available). -(3) If the parent is unavailable, the LVH should not be set. - - CommonAncestor◄─▲── P1 ◄── P2 ◄─ P3 ◄─ ... ◄─ Pn - │ - └── P1' ◄─ P2' ◄─ P3' ◄─ ... ◄─ Pn' - │ - └── P1'' -*/ -func TestNewPayloadOnInvalidChain(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - var ( - api = NewConsensusAPI(ethservice) - parent = ethservice.BlockChain().CurrentBlock() - signer = types.LatestSigner(ethservice.BlockChain().Config()) - // This EVM code generates a log when the contract is created. - logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - ) - for i := 0; i < 10; i++ { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root) - tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{ - Nonce: statedb.GetNonce(testAddr), - Value: new(big.Int), - Gas: 1000000, - GasPrice: big.NewInt(2 * params.InitialBaseFee), - Data: logCode, - }) - ethservice.TxPool().Add([]*types.Transaction{tx}, false, true, false) - var ( - params = engine.PayloadAttributes{ - Timestamp: parent.Time + 1, - Random: crypto.Keccak256Hash([]byte{byte(i)}), - SuggestedFeeRecipient: parent.Coinbase, - } - fcState = engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - SafeBlockHash: common.Hash{}, - FinalizedBlockHash: common.Hash{}, - } - payload *engine.ExecutableData - resp engine.ForkChoiceResponse - err error - ) - for i := 0; ; i++ { - if resp, err = api.ForkchoiceUpdatedV1(fcState, ¶ms); err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - if resp.PayloadStatus.Status != engine.VALID { - t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status) - } - // give the payload some time to be built - time.Sleep(50 * time.Millisecond) - if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil { - t.Fatalf("can't get payload: %v", err) - } - if len(payload.Transactions) > 0 { - break - } - // No luck this time we need to update the params and try again. - params.Timestamp = params.Timestamp + 1 - if i > 10 { - t.Fatalf("payload should not be empty") - } - } - execResp, err := api.NewPayloadV1(*payload) - if err != nil { - t.Fatalf("can't execute payload: %v", err) - } - if execResp.Status != engine.VALID { - t.Fatalf("invalid status: %v", execResp.Status) - } - fcState = engine.ForkchoiceStateV1{ - HeadBlockHash: payload.BlockHash, - SafeBlockHash: payload.ParentHash, - FinalizedBlockHash: payload.ParentHash, - } - if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - t.Fatalf("Failed to insert block: %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { - t.Fatalf("Chain head should be updated") - } - parent = ethservice.BlockChain().CurrentBlock() - } -} - -func assembleBlock(api *ConsensusAPI, parentHash common.Hash, params *engine.PayloadAttributes) (*engine.ExecutableData, error) { - args := &miner.BuildPayloadArgs{ - Parent: parentHash, - Timestamp: params.Timestamp, - FeeRecipient: params.SuggestedFeeRecipient, - GasLimit: params.GasLimit, - Random: params.Random, - Withdrawals: params.Withdrawals, - BeaconRoot: params.BeaconRoot, - } - payload, err := api.eth.Miner().BuildPayload(args) - if err != nil { - return nil, err - } - return payload.ResolveFull().ExecutionPayload, nil -} - -func TestEmptyBlocks(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - commonAncestor := ethservice.BlockChain().CurrentBlock() - api := NewConsensusAPI(ethservice) - - // Setup 10 blocks on the canonical chain - setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil) - - // (1) check LatestValidHash by sending a normal payload (P1'') - payload := getNewPayload(t, api, commonAncestor, nil) - - status, err := api.NewPayloadV1(*payload) - if err != nil { - t.Fatal(err) - } - if status.Status != engine.VALID { - t.Errorf("invalid status: expected VALID got: %v", status.Status) - } - if !bytes.Equal(status.LatestValidHash[:], payload.BlockHash[:]) { - t.Fatalf("invalid LVH: got %v want %v", status.LatestValidHash, payload.BlockHash) - } - - // (2) Now send P1' which is invalid - payload = getNewPayload(t, api, commonAncestor, nil) - payload.GasUsed += 1 - payload = setBlockhash(payload) - // Now latestValidHash should be the common ancestor - status, err = api.NewPayloadV1(*payload) - if err != nil { - t.Fatal(err) - } - if status.Status != engine.INVALID { - t.Errorf("invalid status: expected INVALID got: %v", status.Status) - } - // Expect 0x0 on INVALID block on top of PoW block - expected := common.Hash{} - if !bytes.Equal(status.LatestValidHash[:], expected[:]) { - t.Fatalf("invalid LVH: got %v want %v", status.LatestValidHash, expected) - } - - // (3) Now send a payload with unknown parent - payload = getNewPayload(t, api, commonAncestor, nil) - payload.ParentHash = common.Hash{1} - payload = setBlockhash(payload) - // Now latestValidHash should be the common ancestor - status, err = api.NewPayloadV1(*payload) - if err != nil { - t.Fatal(err) - } - if status.Status != engine.SYNCING { - t.Errorf("invalid status: expected SYNCING got: %v", status.Status) - } - if status.LatestValidHash != nil { - t.Fatalf("invalid LVH: got %v wanted nil", status.LatestValidHash) - } -} - -func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Header, withdrawals []*types.Withdrawal) *engine.ExecutableData { - params := engine.PayloadAttributes{ - Timestamp: parent.Time + 1, - Random: crypto.Keccak256Hash([]byte{byte(1)}), - SuggestedFeeRecipient: parent.Coinbase, - Withdrawals: withdrawals, - } - - payload, err := assembleBlock(api, parent.Hash(), ¶ms) - if err != nil { - t.Fatal(err) - } - return payload -} - -// setBlockhash sets the blockhash of a modified ExecutableData. -// Can be used to make modified payloads look valid. -func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData { - txs, _ := decodeTransactions(data.Transactions) - number := big.NewInt(0) - number.SetUint64(data.Number) - header := &types.Header{ - ParentHash: data.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: data.FeeRecipient, - Root: data.StateRoot, - TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: data.ReceiptsRoot, - Bloom: types.BytesToBloom(data.LogsBloom), - Difficulty: common.Big0, - Number: number, - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Time: data.Timestamp, - BaseFee: data.BaseFeePerGas, - Extra: data.ExtraData, - MixDigest: data.Random, - } - block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) - data.BlockHash = block.Hash() - return data -} - -func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { - var txs = make([]*types.Transaction, len(enc)) - for i, encTx := range enc { - var tx types.Transaction - if err := tx.UnmarshalBinary(encTx); err != nil { - return nil, fmt.Errorf("invalid transaction %d: %v", i, err) - } - txs[i] = &tx - } - return txs, nil -} - -func TestTrickRemoteBlockCache(t *testing.T) { - // Setup two nodes - genesis, preMergeBlocks := generateMergeChain(10, false) - nodeA, ethserviceA := startEthService(t, genesis, preMergeBlocks) - nodeB, ethserviceB := startEthService(t, genesis, preMergeBlocks) - defer nodeA.Close() - defer nodeB.Close() - for nodeB.Server().NodeInfo().Ports.Listener == 0 { - time.Sleep(250 * time.Millisecond) - } - nodeA.Server().AddPeer(nodeB.Server().Self()) - nodeB.Server().AddPeer(nodeA.Server().Self()) - apiA := NewConsensusAPI(ethserviceA) - apiB := NewConsensusAPI(ethserviceB) - - commonAncestor := ethserviceA.BlockChain().CurrentBlock() - - // Setup 10 blocks on the canonical chain - setupBlocks(t, ethserviceA, 10, commonAncestor, func(parent *types.Header) {}, nil) - commonAncestor = ethserviceA.BlockChain().CurrentBlock() - - var invalidChain []*engine.ExecutableData - // create a valid payload (P1) - //payload1 := getNewPayload(t, apiA, commonAncestor) - //invalidChain = append(invalidChain, payload1) - - // create an invalid payload2 (P2) - payload2 := getNewPayload(t, apiA, commonAncestor, nil) - //payload2.ParentHash = payload1.BlockHash - payload2.GasUsed += 1 - payload2 = setBlockhash(payload2) - invalidChain = append(invalidChain, payload2) - - head := payload2 - // create some valid payloads on top - for i := 0; i < 10; i++ { - payload := getNewPayload(t, apiA, commonAncestor, nil) - payload.ParentHash = head.BlockHash - payload = setBlockhash(payload) - invalidChain = append(invalidChain, payload) - head = payload - } - - // feed the payloads to node B - for _, payload := range invalidChain { - status, err := apiB.NewPayloadV1(*payload) - if err != nil { - panic(err) - } - if status.Status == engine.VALID { - t.Error("invalid status: VALID on an invalid chain") - } - // Now reorg to the head of the invalid chain - resp, err := apiB.ForkchoiceUpdatedV1(engine.ForkchoiceStateV1{HeadBlockHash: payload.BlockHash, SafeBlockHash: payload.BlockHash, FinalizedBlockHash: payload.ParentHash}, nil) - if err != nil { - t.Fatal(err) - } - if resp.PayloadStatus.Status == engine.VALID { - t.Error("invalid status: VALID on an invalid chain") - } - time.Sleep(100 * time.Millisecond) - } -} - -func TestInvalidBloom(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - commonAncestor := ethservice.BlockChain().CurrentBlock() - api := NewConsensusAPI(ethservice) - - // Setup 10 blocks on the canonical chain - setupBlocks(t, ethservice, 10, commonAncestor, func(parent *types.Header) {}, nil) - - // (1) check LatestValidHash by sending a normal payload (P1'') - payload := getNewPayload(t, api, commonAncestor, nil) - payload.LogsBloom = append(payload.LogsBloom, byte(1)) - status, err := api.NewPayloadV1(*payload) - if err != nil { - t.Fatal(err) - } - if status.Status != engine.INVALID { - t.Errorf("invalid status: expected INVALID got: %v", status.Status) - } -} - -func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(100, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - api := NewConsensusAPI(ethservice) - - // Test parent already post TTD in FCU - parent := preMergeBlocks[len(preMergeBlocks)-2] - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - SafeBlockHash: common.Hash{}, - FinalizedBlockHash: common.Hash{}, - } - resp, err := api.ForkchoiceUpdatedV1(fcState, nil) - if err != nil { - t.Fatalf("error sending forkchoice, err=%v", err) - } - if resp.PayloadStatus != engine.INVALID_TERMINAL_BLOCK { - t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status) - } - - // Test parent already post TTD in NewPayload - args := &miner.BuildPayloadArgs{ - Parent: parent.Hash(), - Timestamp: parent.Time() + 1, - GasLimit: 0, - Random: crypto.Keccak256Hash([]byte{byte(1)}), - FeeRecipient: parent.Coinbase(), - } - payload, err := api.eth.Miner().BuildPayload(args) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - data := *payload.Resolve().ExecutionPayload - // We need to recompute the blockhash, since the miner computes a wrong (correct) blockhash - txs, _ := decodeTransactions(data.Transactions) - header := &types.Header{ - ParentHash: data.ParentHash, - UncleHash: types.EmptyUncleHash, - Coinbase: data.FeeRecipient, - Root: data.StateRoot, - TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), - ReceiptHash: data.ReceiptsRoot, - Bloom: types.BytesToBloom(data.LogsBloom), - Difficulty: common.Big0, - Number: new(big.Int).SetUint64(data.Number), - GasLimit: data.GasLimit, - GasUsed: data.GasUsed, - Time: data.Timestamp, - BaseFee: data.BaseFeePerGas, - Extra: data.ExtraData, - MixDigest: data.Random, - } - block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) - data.BlockHash = block.Hash() - // Send the new payload - resp2, err := api.NewPayloadV1(data) - if err != nil { - t.Fatalf("error sending NewPayload, err=%v", err) - } - if resp2 != engine.INVALID_TERMINAL_BLOCK { - t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status) - } -} - -// TestSimultaneousNewBlock does several parallel inserts, both as -// newPayLoad and forkchoiceUpdate. This is to test that the api behaves -// well even of the caller is not being 'serial'. -func TestSimultaneousNewBlock(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - var ( - api = NewConsensusAPI(ethservice) - parent = preMergeBlocks[len(preMergeBlocks)-1] - ) - for i := 0; i < 10; i++ { - execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ - Timestamp: parent.Time() + 5, - }) - if err != nil { - t.Fatalf("Failed to create the executable data %v", err) - } - // Insert it 10 times in parallel. Should be ignored. - { - var ( - wg sync.WaitGroup - testErr error - errMu sync.Mutex - ) - wg.Add(10) - for ii := 0; ii < 10; ii++ { - go func() { - defer wg.Done() - if newResp, err := api.NewPayloadV1(*execData); err != nil { - errMu.Lock() - testErr = fmt.Errorf("Failed to insert block: %w", err) - errMu.Unlock() - } else if newResp.Status != "VALID" { - errMu.Lock() - testErr = fmt.Errorf("Failed to insert block: %v", newResp.Status) - errMu.Unlock() - } - }() - } - wg.Wait() - if testErr != nil { - t.Fatal(testErr) - } - } - block, err := engine.ExecutableDataToBlock(*execData, nil, nil) - if err != nil { - t.Fatalf("Failed to convert executable data to block %v", err) - } - if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1 { - t.Fatalf("Chain head shouldn't be updated") - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: block.Hash(), - SafeBlockHash: block.Hash(), - FinalizedBlockHash: block.Hash(), - } - { - var ( - wg sync.WaitGroup - testErr error - errMu sync.Mutex - ) - wg.Add(10) - // Do each FCU 10 times - for ii := 0; ii < 10; ii++ { - go func() { - defer wg.Done() - if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { - errMu.Lock() - testErr = fmt.Errorf("Failed to insert block: %w", err) - errMu.Unlock() - } - }() - } - wg.Wait() - if testErr != nil { - t.Fatal(testErr) - } - } - if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { - t.Fatalf("Chain head should be updated, have %d want %d", have, want) - } - parent = block - } -} - -// TestWithdrawals creates and verifies two post-Shanghai blocks. The first -// includes zero withdrawals and the second includes two. -func TestWithdrawals(t *testing.T) { - genesis, blocks := generateMergeChain(10, true) - // Set shanghai time to last block + 5 seconds (first post-merge block) - time := blocks[len(blocks)-1].Time() + 5 - genesis.Config.ShanghaiTime = &time - - n, ethservice := startEthService(t, genesis, blocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewConsensusAPI(ethservice) - - // 10: Build Shanghai block with no withdrawals. - parent := ethservice.BlockChain().CurrentHeader() - blockParams := engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: make([]*types.Withdrawal, 0), - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - } - resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - if resp.PayloadStatus.Status != engine.VALID { - t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) - } - - // 10: verify state root is the same as parent - payloadID := (&miner.BuildPayloadArgs{ - Parent: fcState.HeadBlockHash, - Timestamp: blockParams.Timestamp, - GasLimit: blockParams.GasLimit, - FeeRecipient: blockParams.SuggestedFeeRecipient, - Random: blockParams.Random, - Withdrawals: blockParams.Withdrawals, - BeaconRoot: blockParams.BeaconRoot, - Version: engine.PayloadV2, - }).Id() - execData, err := api.GetPayloadV2(payloadID) - if err != nil { - t.Fatalf("error getting payload, err=%v", err) - } - if execData.ExecutionPayload.StateRoot != parent.Root { - t.Fatalf("mismatch state roots (got: %s, want: %s)", execData.ExecutionPayload.StateRoot, blocks[8].Root()) - } - - // 10: verify locally built block - if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil { - t.Fatalf("error validating payload: %v", err) - } else if status.Status != engine.VALID { - t.Fatalf("invalid payload") - } - - // 11: build shanghai block with withdrawal - aa := common.Address{0xaa} - bb := common.Address{0xbb} - blockParams = engine.PayloadAttributes{ - Timestamp: execData.ExecutionPayload.Timestamp + 5, - Withdrawals: []*types.Withdrawal{ - { - Index: 0, - Address: aa, - Amount: 32, - }, - { - Index: 1, - Address: bb, - Amount: 33, - }, - }, - } - fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash - _, err = api.ForkchoiceUpdatedV2(fcState, &blockParams) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - - // 11: verify locally build block. - payloadID = (&miner.BuildPayloadArgs{ - Parent: fcState.HeadBlockHash, - Timestamp: blockParams.Timestamp, - FeeRecipient: blockParams.SuggestedFeeRecipient, - GasLimit: blockParams.GasLimit, - Random: blockParams.Random, - Withdrawals: blockParams.Withdrawals, - BeaconRoot: blockParams.BeaconRoot, - Version: engine.PayloadV2, - }).Id() - execData, err = api.GetPayloadV2(payloadID) - if err != nil { - t.Fatalf("error getting payload, err=%v", err) - } - if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil { - t.Fatalf("error validating payload: %v", err) - } else if status.Status != engine.VALID { - t.Fatalf("invalid payload") - } - - // 11: set block as head. - fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash - _, err = api.ForkchoiceUpdatedV2(fcState, nil) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - - // 11: verify withdrawals were processed. - db, _, err := ethservice.APIBackend.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(execData.ExecutionPayload.Number)) - if err != nil { - t.Fatalf("unable to load db: %v", err) - } - for i, w := range blockParams.Withdrawals { - // w.Amount is in gwei, balance in wei - if db.GetBalance(w.Address).Uint64() != w.Amount*params.GWei { - t.Fatalf("failed to process withdrawal %d", i) - } - } -} - -func TestNilWithdrawals(t *testing.T) { - genesis, blocks := generateMergeChain(10, true) - // Set shanghai time to last block + 4 seconds (first post-merge block) - time := blocks[len(blocks)-1].Time() + 4 - genesis.Config.ShanghaiTime = &time - - n, ethservice := startEthService(t, genesis, blocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewConsensusAPI(ethservice) - parent := ethservice.BlockChain().CurrentHeader() - aa := common.Address{0xaa} - - type test struct { - blockParams engine.PayloadAttributes - wantErr bool - } - tests := []test{ - // Before Shanghai - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 2, - Withdrawals: nil, - }, - wantErr: false, - }, - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 2, - Withdrawals: make([]*types.Withdrawal, 0), - }, - wantErr: true, - }, - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 2, - Withdrawals: []*types.Withdrawal{ - { - Index: 0, - Address: aa, - Amount: 32, - }, - }, - }, - wantErr: true, - }, - // After Shanghai - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: nil, - }, - wantErr: true, - }, - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: make([]*types.Withdrawal, 0), - }, - wantErr: false, - }, - { - blockParams: engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: []*types.Withdrawal{ - { - Index: 0, - Address: aa, - Amount: 32, - }, - }, - }, - wantErr: false, - }, - } - - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - } - - for _, test := range tests { - var ( - err error - payloadVersion engine.PayloadVersion - shanghai = genesis.Config.IsShanghai(genesis.Config.LondonBlock, test.blockParams.Timestamp) - ) - if !shanghai { - payloadVersion = engine.PayloadV1 - _, err = api.ForkchoiceUpdatedV1(fcState, &test.blockParams) - } else { - payloadVersion = engine.PayloadV2 - _, err = api.ForkchoiceUpdatedV2(fcState, &test.blockParams) - } - if test.wantErr { - if err == nil { - t.Fatal("wanted error on fcuv2 with invalid withdrawals") - } - continue - } - if err != nil { - t.Fatalf("error preparing payload, err=%v", err) - } - - // 11: verify locally build block. - payloadID := (&miner.BuildPayloadArgs{ - Parent: fcState.HeadBlockHash, - Timestamp: test.blockParams.Timestamp, - FeeRecipient: test.blockParams.SuggestedFeeRecipient, - Random: test.blockParams.Random, - Version: payloadVersion, - }).Id() - execData, err := api.GetPayloadV2(payloadID) - if err != nil { - t.Fatalf("error getting payload, err=%v", err) - } - var status engine.PayloadStatusV1 - if !shanghai { - status, err = api.NewPayloadV1(*execData.ExecutionPayload) - } else { - status, err = api.NewPayloadV2(*execData.ExecutionPayload) - } - if err != nil { - t.Fatalf("error validating payload: %v", err.(*engine.EngineAPIError).ErrorData()) - } else if status.Status != engine.VALID { - t.Fatalf("invalid payload") - } - } -} - -func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) { - genesis, blocks := generateMergeChain(10, true) - // enable shanghai on the last block - time := blocks[len(blocks)-1].Header().Time + 1 - genesis.Config.ShanghaiTime = &time - n, ethservice := startEthService(t, genesis, blocks) - - var ( - parent = ethservice.BlockChain().CurrentBlock() - // This EVM code generates a log when the contract is created. - logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - ) - - callback := func(parent *types.Header) { - statedb, _ := ethservice.BlockChain().StateAt(parent.Root) - nonce := statedb.GetNonce(testAddr) - tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey) - ethservice.TxPool().Add([]*types.Transaction{tx}, false, false, false) - } - - withdrawals := make([][]*types.Withdrawal, 10) - withdrawals[0] = nil // should be filtered out by miner - withdrawals[1] = make([]*types.Withdrawal, 0) - for i := 2; i < len(withdrawals); i++ { - addr := make([]byte, 20) - crand.Read(addr) - withdrawals[i] = []*types.Withdrawal{ - {Index: rand.Uint64(), Validator: rand.Uint64(), Amount: rand.Uint64(), Address: common.BytesToAddress(addr)}, - } - } - - postShanghaiHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals) - postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders)) - for i, header := range postShanghaiHeaders { - postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64()) - } - return n, ethservice, append(blocks, postShanghaiBlocks...) -} - -func allHashes(blocks []*types.Block) []common.Hash { - var hashes []common.Hash - for _, b := range blocks { - hashes = append(hashes, b.Hash()) - } - return hashes -} -func allBodies(blocks []*types.Block) []*types.Body { - var bodies []*types.Body - for _, b := range blocks { - bodies = append(bodies, b.Body()) - } - return bodies -} - -func TestGetBlockBodiesByHash(t *testing.T) { - node, eth, blocks := setupBodies(t) - api := NewConsensusAPI(eth) - defer node.Close() - - tests := []struct { - results []*types.Body - hashes []common.Hash - }{ - // First pow block - { - results: []*types.Body{eth.BlockChain().GetBlockByNumber(0).Body()}, - hashes: []common.Hash{eth.BlockChain().GetBlockByNumber(0).Hash()}, - }, - // Last pow block - { - results: []*types.Body{blocks[9].Body()}, - hashes: []common.Hash{blocks[9].Hash()}, - }, - // First post-merge block - { - results: []*types.Body{blocks[10].Body()}, - hashes: []common.Hash{blocks[10].Hash()}, - }, - // Pre & post merge blocks - { - results: []*types.Body{blocks[0].Body(), blocks[9].Body(), blocks[14].Body()}, - hashes: []common.Hash{blocks[0].Hash(), blocks[9].Hash(), blocks[14].Hash()}, - }, - // unavailable block - { - results: []*types.Body{blocks[0].Body(), nil, blocks[14].Body()}, - hashes: []common.Hash{blocks[0].Hash(), {1, 2}, blocks[14].Hash()}, - }, - // same block multiple times - { - results: []*types.Body{blocks[0].Body(), nil, blocks[0].Body(), blocks[0].Body()}, - hashes: []common.Hash{blocks[0].Hash(), {1, 2}, blocks[0].Hash(), blocks[0].Hash()}, - }, - // all blocks - { - results: allBodies(blocks), - hashes: allHashes(blocks), - }, - } - - for k, test := range tests { - result := api.GetPayloadBodiesByHashV1(test.hashes) - for i, r := range result { - if !equalBody(test.results[i], r) { - t.Fatalf("test %v: invalid response: expected %+v got %+v", k, test.results[i], r) - } - } - } -} - -func TestGetBlockBodiesByRange(t *testing.T) { - node, eth, blocks := setupBodies(t) - api := NewConsensusAPI(eth) - defer node.Close() - - tests := []struct { - results []*types.Body - start hexutil.Uint64 - count hexutil.Uint64 - }{ - { - results: []*types.Body{blocks[9].Body()}, - start: 10, - count: 1, - }, - // Genesis - { - results: []*types.Body{blocks[0].Body()}, - start: 1, - count: 1, - }, - // First post-merge block - { - results: []*types.Body{blocks[9].Body()}, - start: 10, - count: 1, - }, - // Pre & post merge blocks - { - results: []*types.Body{blocks[7].Body(), blocks[8].Body(), blocks[9].Body(), blocks[10].Body()}, - start: 8, - count: 4, - }, - // unavailable block - { - results: []*types.Body{blocks[18].Body(), blocks[19].Body()}, - start: 19, - count: 3, - }, - // unavailable block - { - results: []*types.Body{blocks[19].Body()}, - start: 20, - count: 2, - }, - { - results: []*types.Body{blocks[19].Body()}, - start: 20, - count: 1, - }, - // whole range unavailable - { - results: make([]*types.Body, 0), - start: 22, - count: 2, - }, - // allBlocks - { - results: allBodies(blocks), - start: 1, - count: hexutil.Uint64(len(blocks)), - }, - } - - for k, test := range tests { - result, err := api.GetPayloadBodiesByRangeV1(test.start, test.count) - if err != nil { - t.Fatal(err) - } - if len(result) == len(test.results) { - for i, r := range result { - if !equalBody(test.results[i], r) { - t.Fatalf("test %d: invalid response: expected \n%+v\ngot\n%+v", k, test.results[i], r) - } - } - } else { - t.Fatalf("test %d: invalid length want %v got %v", k, len(test.results), len(result)) - } - } -} - -func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) { - node, eth, _ := setupBodies(t) - api := NewConsensusAPI(eth) - defer node.Close() - tests := []struct { - start hexutil.Uint64 - count hexutil.Uint64 - want *engine.EngineAPIError - }{ - // Genesis - { - start: 0, - count: 1, - want: engine.InvalidParams, - }, - // No block requested - { - start: 1, - count: 0, - want: engine.InvalidParams, - }, - // Genesis & no block - { - start: 0, - count: 0, - want: engine.InvalidParams, - }, - // More than 1024 blocks - { - start: 1, - count: 1025, - want: engine.TooLargeRequest, - }, - } - for i, tc := range tests { - result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count) - if err == nil { - t.Fatalf("test %d: expected error, got %v", i, result) - } - if have, want := err.Error(), tc.want.Error(); have != want { - t.Fatalf("test %d: have %s, want %s", i, have, want) - } - } -} - -func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool { - if a == nil && b == nil { - return true - } else if a == nil || b == nil { - return false - } - if len(a.Transactions) != len(b.TransactionData) { - return false - } - for i, tx := range a.Transactions { - data, _ := tx.MarshalBinary() - if !bytes.Equal(data, b.TransactionData[i]) { - return false - } - } - return reflect.DeepEqual(a.Withdrawals, b.Withdrawals) -} - -func TestBlockToPayloadWithBlobs(t *testing.T) { - header := types.Header{} - var txs []*types.Transaction - - inner := types.BlobTx{ - BlobHashes: make([]common.Hash, 1), - } - - txs = append(txs, types.NewTx(&inner)) - sidecars := []*types.BlobTxSidecar{ - { - Blobs: make([]kzg4844.Blob, 1), - Commitments: make([]kzg4844.Commitment, 1), - Proofs: make([]kzg4844.Proof, 1), - }, - } - - block := types.NewBlock(&header, txs, nil, nil, trie.NewStackTrie(nil)) - envelope := engine.BlockToExecutableData(block, nil, sidecars) - var want int - for _, tx := range txs { - want += len(tx.BlobHashes()) - } - if got := len(envelope.BlobsBundle.Commitments); got != want { - t.Fatalf("invalid number of commitments: got %v, want %v", got, want) - } - if got := len(envelope.BlobsBundle.Proofs); got != want { - t.Fatalf("invalid number of proofs: got %v, want %v", got, want) - } - if got := len(envelope.BlobsBundle.Blobs); got != want { - t.Fatalf("invalid number of blobs: got %v, want %v", got, want) - } - _, err := engine.ExecutableDataToBlock(*envelope.ExecutionPayload, make([]common.Hash, 1), nil) - if err != nil { - t.Error(err) - } -} - -// This checks that beaconRoot is applied to the state from the engine API. -func TestParentBeaconBlockRoot(t *testing.T) { - log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(colorable.NewColorableStderr(), log.LevelTrace, true))) - - genesis, blocks := generateMergeChain(10, true) - - // Set cancun time to last block + 5 seconds - time := blocks[len(blocks)-1].Time() + 5 - genesis.Config.ShanghaiTime = &time - genesis.Config.CancunTime = &time - - n, ethservice := startEthService(t, genesis, blocks) - ethservice.Merger().ReachTTD() - defer n.Close() - - api := NewConsensusAPI(ethservice) - - // 11: Build Shanghai block with no withdrawals. - parent := ethservice.BlockChain().CurrentHeader() - blockParams := engine.PayloadAttributes{ - Timestamp: parent.Time + 5, - Withdrawals: make([]*types.Withdrawal, 0), - BeaconRoot: &common.Hash{42}, - } - fcState := engine.ForkchoiceStateV1{ - HeadBlockHash: parent.Hash(), - } - resp, err := api.ForkchoiceUpdatedV3(fcState, &blockParams) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) - } - if resp.PayloadStatus.Status != engine.VALID { - t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) - } - - // 11: verify state root is the same as parent - payloadID := (&miner.BuildPayloadArgs{ - Parent: fcState.HeadBlockHash, - Timestamp: blockParams.Timestamp, - FeeRecipient: blockParams.SuggestedFeeRecipient, - Random: blockParams.Random, - Withdrawals: blockParams.Withdrawals, - BeaconRoot: blockParams.BeaconRoot, - Version: engine.PayloadV3, - }).Id() - execData, err := api.GetPayloadV3(payloadID) - if err != nil { - t.Fatalf("error getting payload, err=%v", err) - } - - // 11: verify locally built block - if status, err := api.NewPayloadV3(*execData.ExecutionPayload, []common.Hash{}, &common.Hash{42}); err != nil { - t.Fatalf("error validating payload: %v", err) - } else if status.Status != engine.VALID { - t.Fatalf("invalid payload") - } - - fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash - resp, err = api.ForkchoiceUpdatedV3(fcState, nil) - if err != nil { - t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData()) - } - if resp.PayloadStatus.Status != engine.VALID { - t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) - } - - // 11: verify beacon root was processed. - db, _, err := ethservice.APIBackend.StateAndHeaderByNumber(context.Background(), rpc.BlockNumber(execData.ExecutionPayload.Number)) - if err != nil { - t.Fatalf("unable to load db: %v", err) - } - var ( - timeIdx = common.BigToHash(big.NewInt(int64(execData.ExecutionPayload.Timestamp % 98304))) - rootIdx = common.BigToHash(big.NewInt(int64((execData.ExecutionPayload.Timestamp % 98304) + 98304))) - ) - - if num := db.GetState(params.BeaconRootsStorageAddress, timeIdx); num != timeIdx { - t.Fatalf("incorrect number stored: want %s, got %s", timeIdx, num) - } - if root := db.GetState(params.BeaconRootsStorageAddress, rootIdx); root != *blockParams.BeaconRoot { - t.Fatalf("incorrect root stored: want %s, got %s", *blockParams.BeaconRoot, root) - } -} - -// TestGetClientVersion verifies the expected version info is returned. -func TestGetClientVersion(t *testing.T) { - genesis, preMergeBlocks := generateMergeChain(10, false) - n, ethservice := startEthService(t, genesis, preMergeBlocks) - defer n.Close() - - api := NewConsensusAPI(ethservice) - info := engine.ClientVersionV1{ - Code: "TT", - Name: "test", - Version: "1.1.1", - Commit: "0x12345678", - } - infos := api.GetClientVersionV1(info) - if len(infos) != 1 { - t.Fatalf("expected only one returned client version, got %d", len(infos)) - } - info = infos[0] - if info.Code != engine.ClientCode || info.Name != engine.ClientName || info.Version != params.VersionWithMeta { - t.Fatalf("client info does match expected, got %s", info.String()) - } -} diff --git a/builder/eth/catalyst/queue.go b/builder/eth/catalyst/queue.go deleted file mode 100644 index 634dc1b2e..000000000 --- a/builder/eth/catalyst/queue.go +++ /dev/null @@ -1,158 +0,0 @@ -// 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 catalyst - -import ( - "sync" - - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/miner" -) - -// maxTrackedPayloads is the maximum number of prepared payloads the execution -// engine tracks before evicting old ones. Ideally we should only ever track the -// latest one; but have a slight wiggle room for non-ideal conditions. -const maxTrackedPayloads = 10 - -// maxTrackedHeaders is the maximum number of executed payloads the execution -// engine tracks before evicting old ones. These are tracked outside the chain -// during initial sync to allow ForkchoiceUpdate to reference past blocks via -// hashes only. For the sync target it would be enough to track only the latest -// header, but snap sync also needs the latest finalized height for the ancient -// limit. -const maxTrackedHeaders = 96 - -// payloadQueueItem represents an id->payload tuple to store until it's retrieved -// or evicted. -type payloadQueueItem struct { - id engine.PayloadID - payload *miner.Payload -} - -// payloadQueue tracks the latest handful of constructed payloads to be retrieved -// by the beacon chain if block production is requested. -type payloadQueue struct { - payloads []*payloadQueueItem - lock sync.RWMutex -} - -// newPayloadQueue creates a pre-initialized queue with a fixed number of slots -// all containing empty items. -func newPayloadQueue() *payloadQueue { - return &payloadQueue{ - payloads: make([]*payloadQueueItem, maxTrackedPayloads), - } -} - -// put inserts a new payload into the queue at the given id. -func (q *payloadQueue) put(id engine.PayloadID, payload *miner.Payload) { - q.lock.Lock() - defer q.lock.Unlock() - - copy(q.payloads[1:], q.payloads) - q.payloads[0] = &payloadQueueItem{ - id: id, - payload: payload, - } -} - -// get retrieves a previously stored payload item or nil if it does not exist. -func (q *payloadQueue) get(id engine.PayloadID, full bool) *engine.ExecutionPayloadEnvelope { - q.lock.RLock() - defer q.lock.RUnlock() - - for _, item := range q.payloads { - if item == nil { - return nil // no more items - } - if item.id == id { - if !full { - return item.payload.Resolve() - } - return item.payload.ResolveFull() - } - } - return nil -} - -// has checks if a particular payload is already tracked. -func (q *payloadQueue) has(id engine.PayloadID) bool { - q.lock.RLock() - defer q.lock.RUnlock() - - for _, item := range q.payloads { - if item == nil { - return false - } - if item.id == id { - return true - } - } - return false -} - -// headerQueueItem represents an hash->header tuple to store until it's retrieved -// or evicted. -type headerQueueItem struct { - hash common.Hash - header *types.Header -} - -// headerQueue tracks the latest handful of constructed headers to be retrieved -// by the beacon chain if block production is requested. -type headerQueue struct { - headers []*headerQueueItem - lock sync.RWMutex -} - -// newHeaderQueue creates a pre-initialized queue with a fixed number of slots -// all containing empty items. -func newHeaderQueue() *headerQueue { - return &headerQueue{ - headers: make([]*headerQueueItem, maxTrackedHeaders), - } -} - -// put inserts a new header into the queue at the given hash. -func (q *headerQueue) put(hash common.Hash, data *types.Header) { - q.lock.Lock() - defer q.lock.Unlock() - - copy(q.headers[1:], q.headers) - q.headers[0] = &headerQueueItem{ - hash: hash, - header: data, - } -} - -// get retrieves a previously stored header item or nil if it does not exist. -func (q *headerQueue) get(hash common.Hash) *types.Header { - q.lock.RLock() - defer q.lock.RUnlock() - - for _, item := range q.headers { - if item == nil { - return nil // no more items - } - if item.hash == hash { - return item.header - } - } - return nil -} diff --git a/builder/eth/catalyst/simulated_beacon.go b/builder/eth/catalyst/simulated_beacon.go deleted file mode 100644 index f1c5689e1..000000000 --- a/builder/eth/catalyst/simulated_beacon.go +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2023 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 catalyst - -import ( - "crypto/rand" - "errors" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum/beacon/engine" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -const devEpochLength = 32 - -// withdrawalQueue implements a FIFO queue which holds withdrawals that are -// pending inclusion. -type withdrawalQueue struct { - pending chan *types.Withdrawal -} - -// add queues a withdrawal for future inclusion. -func (w *withdrawalQueue) add(withdrawal *types.Withdrawal) error { - select { - case w.pending <- withdrawal: - break - default: - return errors.New("withdrawal queue full") - } - return nil -} - -// gatherPending returns a number of queued withdrawals up to a maximum count. -func (w *withdrawalQueue) gatherPending(maxCount int) []*types.Withdrawal { - withdrawals := []*types.Withdrawal{} - for { - select { - case withdrawal := <-w.pending: - withdrawals = append(withdrawals, withdrawal) - if len(withdrawals) == maxCount { - break - } - default: - return withdrawals - } - } -} - -type SimulatedBeacon struct { - shutdownCh chan struct{} - eth *eth.Ethereum - period uint64 - withdrawals withdrawalQueue - - feeRecipient common.Address - feeRecipientLock sync.Mutex // lock gates concurrent access to the feeRecipient - - engineAPI *ConsensusAPI - curForkchoiceState engine.ForkchoiceStateV1 - lastBlockTime uint64 -} - -// NewSimulatedBeacon constructs a new simulated beacon chain. -// Period sets the period in which blocks should be produced. -// -// - If period is set to 0, a block is produced on every transaction. -// via Commit, Fork and AdjustTime. -func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) { - block := eth.BlockChain().CurrentBlock() - current := engine.ForkchoiceStateV1{ - HeadBlockHash: block.Hash(), - SafeBlockHash: block.Hash(), - FinalizedBlockHash: block.Hash(), - } - engineAPI := newConsensusAPIWithoutHeartbeat(eth) - - // if genesis block, send forkchoiceUpdated to trigger transition to PoS - if block.Number.Sign() == 0 { - if _, err := engineAPI.ForkchoiceUpdatedV2(current, nil); err != nil { - return nil, err - } - } - return &SimulatedBeacon{ - eth: eth, - period: period, - shutdownCh: make(chan struct{}), - engineAPI: engineAPI, - lastBlockTime: block.Time, - curForkchoiceState: current, - withdrawals: withdrawalQueue{make(chan *types.Withdrawal, 20)}, - }, nil -} - -func (c *SimulatedBeacon) setFeeRecipient(feeRecipient common.Address) { - c.feeRecipientLock.Lock() - c.feeRecipient = feeRecipient - c.feeRecipientLock.Unlock() -} - -// Start invokes the SimulatedBeacon life-cycle function in a goroutine. -func (c *SimulatedBeacon) Start() error { - if c.period == 0 { - // if period is set to 0, do not mine at all - // this is used in the simulated backend where blocks - // are explicitly mined via Commit, AdjustTime and Fork - } else { - go c.loop() - } - return nil -} - -// Stop halts the SimulatedBeacon service. -func (c *SimulatedBeacon) Stop() error { - close(c.shutdownCh) - return nil -} - -// sealBlock initiates payload building for a new block and creates a new block -// with the completed payload. -func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp uint64) error { - if timestamp <= c.lastBlockTime { - timestamp = c.lastBlockTime + 1 - } - c.feeRecipientLock.Lock() - feeRecipient := c.feeRecipient - c.feeRecipientLock.Unlock() - - // Reset to CurrentBlock in case of the chain was rewound - if header := c.eth.BlockChain().CurrentBlock(); c.curForkchoiceState.HeadBlockHash != header.Hash() { - finalizedHash := c.finalizedBlockHash(header.Number.Uint64()) - c.setCurrentState(header.Hash(), *finalizedHash) - } - - var random [32]byte - rand.Read(random[:]) - fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{ - Timestamp: timestamp, - SuggestedFeeRecipient: feeRecipient, - Withdrawals: withdrawals, - Random: random, - }, engine.PayloadV2, true) - if err != nil { - return err - } - if fcResponse == engine.STATUS_SYNCING { - return errors.New("chain rewind prevented invocation of payload creation") - } - - envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true) - if err != nil { - return err - } - payload := envelope.ExecutionPayload - - var finalizedHash common.Hash - if payload.Number%devEpochLength == 0 { - finalizedHash = payload.BlockHash - } else { - if fh := c.finalizedBlockHash(payload.Number); fh == nil { - return errors.New("chain rewind interrupted calculation of finalized block hash") - } else { - finalizedHash = *fh - } - } - - // Mark the payload as canon - if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil { - return err - } - c.setCurrentState(payload.BlockHash, finalizedHash) - - // Mark the block containing the payload as canonical - if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil { - return err - } - c.lastBlockTime = payload.Timestamp - return nil -} - -// loop runs the block production loop for non-zero period configuration -func (c *SimulatedBeacon) loop() { - timer := time.NewTimer(0) - for { - select { - case <-c.shutdownCh: - return - case <-timer.C: - withdrawals := c.withdrawals.gatherPending(10) - if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil { - log.Warn("Error performing sealing work", "err", err) - } else { - timer.Reset(time.Second * time.Duration(c.period)) - } - } - } -} - -// finalizedBlockHash returns the block hash of the finalized block corresponding -// to the given number or nil if doesn't exist in the chain. -func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash { - var finalizedNumber uint64 - if number%devEpochLength == 0 { - finalizedNumber = number - } else { - finalizedNumber = (number - 1) / devEpochLength * devEpochLength - } - if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil { - fh := finalizedBlock.Hash() - return &fh - } - return nil -} - -// setCurrentState sets the current forkchoice state -func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) { - c.curForkchoiceState = engine.ForkchoiceStateV1{ - HeadBlockHash: headHash, - SafeBlockHash: headHash, - FinalizedBlockHash: finalizedHash, - } -} - -// Commit seals a block on demand. -func (c *SimulatedBeacon) Commit() common.Hash { - withdrawals := c.withdrawals.gatherPending(10) - if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil { - log.Warn("Error performing sealing work", "err", err) - } - return c.eth.BlockChain().CurrentBlock().Hash() -} - -// Rollback un-sends previously added transactions. -func (c *SimulatedBeacon) Rollback() { - // Flush all transactions from the transaction pools - maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1) - c.eth.TxPool().SetGasTip(maxUint256) - // Set the gas tip back to accept new transactions - // TODO (Marius van der Wijden): set gas tip to parameter passed by config - c.eth.TxPool().SetGasTip(big.NewInt(params.GWei)) -} - -// Fork sets the head to the provided hash. -func (c *SimulatedBeacon) Fork(parentHash common.Hash) error { - if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 { - return errors.New("pending block dirty") - } - parent := c.eth.BlockChain().GetBlockByHash(parentHash) - if parent == nil { - return errors.New("parent not found") - } - return c.eth.BlockChain().SetHead(parent.NumberU64()) -} - -// AdjustTime creates a new block with an adjusted timestamp. -func (c *SimulatedBeacon) AdjustTime(adjustment time.Duration) error { - if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 { - return errors.New("could not adjust time on non-empty block") - } - parent := c.eth.BlockChain().CurrentBlock() - if parent == nil { - return errors.New("parent not found") - } - withdrawals := c.withdrawals.gatherPending(10) - return c.sealBlock(withdrawals, parent.Time+uint64(adjustment)) -} - -func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) { - api := &api{sim} - if sim.period == 0 { - // mine on demand if period is set to 0 - go api.loop() - } - stack.RegisterAPIs([]rpc.API{ - { - Namespace: "dev", - Service: api, - Version: "1.0", - }, - }) -} diff --git a/builder/eth/catalyst/simulated_beacon_api.go b/builder/eth/catalyst/simulated_beacon_api.go deleted file mode 100644 index 73d0a5921..000000000 --- a/builder/eth/catalyst/simulated_beacon_api.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2023 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 catalyst - -import ( - "context" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -type api struct { - sim *SimulatedBeacon -} - -func (a *api) loop() { - var ( - newTxs = make(chan core.NewTxsEvent) - sub = a.sim.eth.TxPool().SubscribeTransactions(newTxs, true) - ) - defer sub.Unsubscribe() - - for { - select { - case <-a.sim.shutdownCh: - return - case w := <-a.sim.withdrawals.pending: - withdrawals := append(a.sim.withdrawals.gatherPending(9), w) - if err := a.sim.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil { - log.Warn("Error performing sealing work", "err", err) - } - case <-newTxs: - a.sim.Commit() - } - } -} - -func (a *api) AddWithdrawal(ctx context.Context, withdrawal *types.Withdrawal) error { - return a.sim.withdrawals.add(withdrawal) -} - -func (a *api) SetFeeRecipient(ctx context.Context, feeRecipient common.Address) { - a.sim.setFeeRecipient(feeRecipient) -} diff --git a/builder/eth/catalyst/simulated_beacon_test.go b/builder/eth/catalyst/simulated_beacon_test.go deleted file mode 100644 index fe7eb8199..000000000 --- a/builder/eth/catalyst/simulated_beacon_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2023 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 catalyst - -import ( - "context" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/params" -) - -func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.Node, *eth.Ethereum, *SimulatedBeacon) { - t.Helper() - - n, err := node.New(&node.Config{ - P2P: p2p.Config{ - ListenAddr: "127.0.0.1:8545", - NoDiscovery: true, - MaxPeers: 0, - }, - }) - if err != nil { - t.Fatal("can't create node:", err) - } - - ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256} - ethservice, err := eth.New(n, ethcfg) - if err != nil { - t.Fatal("can't create eth service:", err) - } - - simBeacon, err := NewSimulatedBeacon(1, ethservice) - if err != nil { - t.Fatal("can't create simulated beacon:", err) - } - - n.RegisterLifecycle(simBeacon) - - if err := n.Start(); err != nil { - t.Fatal("can't start node:", err) - } - - ethservice.SetSynced() - return n, ethservice, simBeacon -} - -// send 20 transactions, >10 withdrawals and ensure they are included in order -// send enough transactions to fill multiple blocks -func TestSimulatedBeaconSendWithdrawals(t *testing.T) { - var withdrawals []types.Withdrawal - txs := make(map[common.Hash]types.Transaction) - - var ( - // testKey is a private key to use for funding a tester account. - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - - // testAddr is the Ethereum address of the tester account. - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - ) - - // short period (1 second) for testing purposes - var gasLimit uint64 = 10_000_000 - genesis := core.DeveloperGenesisBlock(gasLimit, &testAddr) - node, ethService, mock := startSimulatedBeaconEthService(t, genesis) - _ = mock - defer node.Close() - - chainHeadCh := make(chan core.ChainHeadEvent, 10) - subscription := ethService.BlockChain().SubscribeChainHeadEvent(chainHeadCh) - defer subscription.Unsubscribe() - - // generate some withdrawals - for i := 0; i < 20; i++ { - withdrawals = append(withdrawals, types.Withdrawal{Index: uint64(i)}) - if err := mock.withdrawals.add(&withdrawals[i]); err != nil { - t.Fatal("addWithdrawal failed", err) - } - } - - // generate a bunch of transactions - signer := types.NewEIP155Signer(ethService.BlockChain().Config().ChainID) - for i := 0; i < 20; i++ { - tx, err := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, big.NewInt(1000), params.TxGas, big.NewInt(params.InitialBaseFee), nil), signer, testKey) - if err != nil { - t.Fatalf("error signing transaction, err=%v", err) - } - txs[tx.Hash()] = *tx - - if err := ethService.APIBackend.SendTx(context.Background(), tx, false); err != nil { - t.Fatal("SendTx failed", err) - } - } - - includedTxs := make(map[common.Hash]struct{}) - var includedWithdrawals []uint64 - - timer := time.NewTimer(12 * time.Second) - for { - select { - case evt := <-chainHeadCh: - for _, includedTx := range evt.Block.Transactions() { - includedTxs[includedTx.Hash()] = struct{}{} - } - for _, includedWithdrawal := range evt.Block.Withdrawals() { - includedWithdrawals = append(includedWithdrawals, includedWithdrawal.Index) - } - - // ensure all withdrawals/txs included. this will take two blocks b/c number of withdrawals > 10 - if len(includedTxs) == len(txs) && len(includedWithdrawals) == len(withdrawals) && evt.Block.Number().Cmp(big.NewInt(2)) == 0 { - return - } - case <-timer.C: - t.Fatal("timed out without including all withdrawals/txs") - } - } -} diff --git a/builder/eth/catalyst/tester.go b/builder/eth/catalyst/tester.go deleted file mode 100644 index 0922ac0ba..000000000 --- a/builder/eth/catalyst/tester.go +++ /dev/null @@ -1,97 +0,0 @@ -// 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 catalyst - -import ( - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" -) - -// FullSyncTester is an auxiliary service that allows Geth to perform full sync -// alone without consensus-layer attached. Users must specify a valid block hash -// as the sync target. -// -// This tester can be applied to different networks, no matter it's pre-merge or -// post-merge, but only for full-sync. -type FullSyncTester struct { - stack *node.Node - backend *eth.Ethereum - target common.Hash - closed chan struct{} - wg sync.WaitGroup -} - -// RegisterFullSyncTester registers the full-sync tester service into the node -// stack for launching and stopping the service controlled by node. -func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash) (*FullSyncTester, error) { - cl := &FullSyncTester{ - stack: stack, - backend: backend, - target: target, - closed: make(chan struct{}), - } - stack.RegisterLifecycle(cl) - return cl, nil -} - -// Start launches the beacon sync with provided sync target. -func (tester *FullSyncTester) Start() error { - tester.wg.Add(1) - go func() { - defer tester.wg.Done() - - // Trigger beacon sync with the provided block hash as trusted - // chain head. - err := tester.backend.Downloader().BeaconDevSync(downloader.FullSync, tester.target, tester.closed) - if err != nil { - log.Info("Failed to trigger beacon sync", "err", err) - } - - ticker := time.NewTicker(time.Second * 5) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - // Stop in case the target block is already stored locally. - if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil { - log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash()) - go tester.stack.Close() // async since we need to close ourselves - return - } - - case <-tester.closed: - return - } - } - }() - return nil -} - -// Stop stops the full-sync tester to stop all background activities. -// This function can only be called for one time. -func (tester *FullSyncTester) Stop() error { - close(tester.closed) - tester.wg.Wait() - return nil -} diff --git a/builder/eth/downloader/api.go b/builder/eth/downloader/api.go deleted file mode 100644 index 6b8cb98e2..000000000 --- a/builder/eth/downloader/api.go +++ /dev/null @@ -1,205 +0,0 @@ -// 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 downloader - -import ( - "context" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/rpc" -) - -// DownloaderAPI provides an API which gives information about the current -// synchronisation status. It offers only methods that operates on data that -// can be available to anyone without security risks. -type DownloaderAPI struct { - d *Downloader - chain *core.BlockChain - mux *event.TypeMux - installSyncSubscription chan chan interface{} - uninstallSyncSubscription chan *uninstallSyncSubscriptionRequest -} - -// NewDownloaderAPI creates a new DownloaderAPI. The API has an internal event loop that -// listens for events from the downloader through the global event mux. In case it receives one of -// these events it broadcasts it to all syncing subscriptions that are installed through the -// installSyncSubscription channel. -func NewDownloaderAPI(d *Downloader, chain *core.BlockChain, m *event.TypeMux) *DownloaderAPI { - api := &DownloaderAPI{ - d: d, - chain: chain, - mux: m, - installSyncSubscription: make(chan chan interface{}), - uninstallSyncSubscription: make(chan *uninstallSyncSubscriptionRequest), - } - go api.eventLoop() - return api -} - -// eventLoop runs a loop until the event mux closes. It will install and uninstall -// new sync subscriptions and broadcasts sync status updates to the installed sync -// subscriptions. -// -// The sync status pushed to subscriptions can be a stream like: -// >>> {Syncing: true, Progress: {...}} -// >>> {false} -// -// If the node is already synced up, then only a single event subscribers will -// receive is {false}. -func (api *DownloaderAPI) eventLoop() { - var ( - sub = api.mux.Subscribe(StartEvent{}) - syncSubscriptions = make(map[chan interface{}]struct{}) - checkInterval = time.Second * 60 - checkTimer = time.NewTimer(checkInterval) - - // status flags - started bool - done bool - - getProgress = func() ethereum.SyncProgress { - prog := api.d.Progress() - if txProg, err := api.chain.TxIndexProgress(); err == nil { - prog.TxIndexFinishedBlocks = txProg.Indexed - prog.TxIndexRemainingBlocks = txProg.Remaining - } - return prog - } - ) - defer checkTimer.Stop() - - for { - select { - case i := <-api.installSyncSubscription: - syncSubscriptions[i] = struct{}{} - if done { - i <- false - } - case u := <-api.uninstallSyncSubscription: - delete(syncSubscriptions, u.c) - close(u.uninstalled) - case event := <-sub.Chan(): - if event == nil { - return - } - switch event.Data.(type) { - case StartEvent: - started = true - } - case <-checkTimer.C: - if !started { - checkTimer.Reset(checkInterval) - continue - } - prog := getProgress() - if !prog.Done() { - notification := &SyncingResult{ - Syncing: true, - Status: prog, - } - for c := range syncSubscriptions { - c <- notification - } - checkTimer.Reset(checkInterval) - continue - } - for c := range syncSubscriptions { - c <- false - } - done = true - } - } -} - -// Syncing provides information when this nodes starts synchronising with the Ethereum network and when it's finished. -func (api *DownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error) { - notifier, supported := rpc.NotifierFromContext(ctx) - if !supported { - return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported - } - - rpcSub := notifier.CreateSubscription() - - go func() { - statuses := make(chan interface{}) - sub := api.SubscribeSyncStatus(statuses) - defer sub.Unsubscribe() - - for { - select { - case status := <-statuses: - notifier.Notify(rpcSub.ID, status) - case <-rpcSub.Err(): - return - case <-notifier.Closed(): - return - } - } - }() - - return rpcSub, nil -} - -// SyncingResult provides information about the current synchronisation status for this node. -type SyncingResult struct { - Syncing bool `json:"syncing"` - Status ethereum.SyncProgress `json:"status"` -} - -// uninstallSyncSubscriptionRequest uninstalls a syncing subscription in the API event loop. -type uninstallSyncSubscriptionRequest struct { - c chan interface{} - uninstalled chan interface{} -} - -// SyncStatusSubscription represents a syncing subscription. -type SyncStatusSubscription struct { - api *DownloaderAPI // register subscription in event loop of this api instance - c chan interface{} // channel where events are broadcasted to - unsubOnce sync.Once // make sure unsubscribe logic is executed once -} - -// Unsubscribe uninstalls the subscription from the DownloadAPI event loop. -// The status channel that was passed to subscribeSyncStatus isn't used anymore -// after this method returns. -func (s *SyncStatusSubscription) Unsubscribe() { - s.unsubOnce.Do(func() { - req := uninstallSyncSubscriptionRequest{s.c, make(chan interface{})} - s.api.uninstallSyncSubscription <- &req - - for { - select { - case <-s.c: - // drop new status events until uninstall confirmation - continue - case <-req.uninstalled: - return - } - } - }) -} - -// SubscribeSyncStatus creates a subscription that will broadcast new synchronisation updates. -// The given channel must receive interface values, the result can either. -func (api *DownloaderAPI) SubscribeSyncStatus(status chan interface{}) *SyncStatusSubscription { - api.installSyncSubscription <- status - return &SyncStatusSubscription{api: api, c: status} -} diff --git a/builder/eth/downloader/beacondevsync.go b/builder/eth/downloader/beacondevsync.go deleted file mode 100644 index 9a38fedd4..000000000 --- a/builder/eth/downloader/beacondevsync.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2023 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 downloader - -import ( - "errors" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" -) - -// BeaconDevSync is a development helper to test synchronization by providing -// a block hash instead of header to run the beacon sync against. -// -// The method will reach out to the network to retrieve the header of the sync -// target instead of receiving it from the consensus node. -// -// Note, this must not be used in live code. If the forkchcoice endpoint where -// to use this instead of giving us the payload first, then essentially nobody -// in the network would have the block yet that we'd attempt to retrieve. -func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan struct{}) error { - // Be very loud that this code should not be used in a live node - log.Warn("----------------------------------") - log.Warn("Beacon syncing with hash as target", "hash", hash) - log.Warn("This is unhealthy for a live node!") - log.Warn("----------------------------------") - - log.Info("Waiting for peers to retrieve sync target") - for { - // If the node is going down, unblock - select { - case <-stop: - return errors.New("stop requested") - default: - } - // Pick a random peer to sync from and keep retrying if none are yet - // available due to fresh startup - d.peers.lock.RLock() - var peer *peerConnection - for _, peer = range d.peers.peers { - break - } - d.peers.lock.RUnlock() - - if peer == nil { - time.Sleep(time.Second) - continue - } - // Found a peer, attempt to retrieve the header whilst blocking and - // retry if it fails for whatever reason - log.Info("Attempting to retrieve sync target", "peer", peer.id) - headers, metas, err := d.fetchHeadersByHash(peer, hash, 1, 0, false) - if err != nil || len(headers) != 1 { - log.Warn("Failed to fetch sync target", "headers", len(headers), "err", err) - time.Sleep(time.Second) - continue - } - // Head header retrieved, if the hash matches, start the actual sync - if metas[0] != hash { - log.Error("Received invalid sync target", "want", hash, "have", metas[0]) - time.Sleep(time.Second) - continue - } - return d.BeaconSync(mode, headers[0], headers[0]) - } -} diff --git a/builder/eth/downloader/beaconsync.go b/builder/eth/downloader/beaconsync.go deleted file mode 100644 index d3f75c852..000000000 --- a/builder/eth/downloader/beaconsync.go +++ /dev/null @@ -1,390 +0,0 @@ -// 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 downloader - -import ( - "fmt" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -// beaconBackfiller is the chain and state backfilling that can be commenced once -// the skeleton syncer has successfully reverse downloaded all the headers up to -// the genesis block or an existing header in the database. Its operation is fully -// directed by the skeleton sync's head/tail events. -type beaconBackfiller struct { - downloader *Downloader // Downloader to direct via this callback implementation - syncMode SyncMode // Sync mode to use for backfilling the skeleton chains - success func() // Callback to run on successful sync cycle completion - filling bool // Flag whether the downloader is backfilling or not - filled *types.Header // Last header filled by the last terminated sync loop - started chan struct{} // Notification channel whether the downloader inited - lock sync.Mutex // Mutex protecting the sync lock -} - -// newBeaconBackfiller is a helper method to create the backfiller. -func newBeaconBackfiller(dl *Downloader, success func()) backfiller { - return &beaconBackfiller{ - downloader: dl, - success: success, - } -} - -// suspend cancels any background downloader threads and returns the last header -// that has been successfully backfilled (potentially in a previous run), or the -// genesis. -func (b *beaconBackfiller) suspend() *types.Header { - // If no filling is running, don't waste cycles - b.lock.Lock() - filling := b.filling - filled := b.filled - started := b.started - b.lock.Unlock() - - if !filling { - return filled // Return the filled header on the previous sync completion - } - // A previous filling should be running, though it may happen that it hasn't - // yet started (being done on a new goroutine). Many concurrent beacon head - // announcements can lead to sync start/stop thrashing. In that case we need - // to wait for initialization before we can safely cancel it. It is safe to - // read this channel multiple times, it gets closed on startup. - <-started - - // Now that we're sure the downloader successfully started up, we can cancel - // it safely without running the risk of data races. - b.downloader.Cancel() - - // Sync cycle was just terminated, retrieve and return the last filled header. - // Can't use `filled` as that contains a stale value from before cancellation. - return b.downloader.blockchain.CurrentSnapBlock() -} - -// resume starts the downloader threads for backfilling state and chain data. -func (b *beaconBackfiller) resume() { - b.lock.Lock() - if b.filling { - // If a previous filling cycle is still running, just ignore this start - // request. // TODO(karalabe): We should make this channel driven - b.lock.Unlock() - return - } - b.filling = true - b.filled = nil - b.started = make(chan struct{}) - mode := b.syncMode - b.lock.Unlock() - - // Start the backfilling on its own thread since the downloader does not have - // its own lifecycle runloop. - go func() { - // Set the backfiller to non-filling when download completes - defer func() { - b.lock.Lock() - b.filling = false - b.filled = b.downloader.blockchain.CurrentSnapBlock() - b.lock.Unlock() - }() - // If the downloader fails, report an error as in beacon chain mode there - // should be no errors as long as the chain we're syncing to is valid. - if err := b.downloader.synchronise("", common.Hash{}, nil, nil, mode, true, b.started); err != nil { - log.Error("Beacon backfilling failed", "err", err) - return - } - // Synchronization succeeded. Since this happens async, notify the outer - // context to disable snap syncing and enable transaction propagation. - if b.success != nil { - b.success() - } - }() -} - -// setMode updates the sync mode from the current one to the requested one. If -// there's an active sync in progress, it will be cancelled and restarted. -func (b *beaconBackfiller) setMode(mode SyncMode) { - // Update the old sync mode and track if it was changed - b.lock.Lock() - updated := b.syncMode != mode - filling := b.filling - b.syncMode = mode - b.lock.Unlock() - - // If the sync mode was changed mid-sync, restart. This should never ever - // really happen, we just handle it to detect programming errors. - if !updated || !filling { - return - } - log.Error("Downloader sync mode changed mid-run", "old", mode.String(), "new", mode.String()) - b.suspend() - b.resume() -} - -// SetBadBlockCallback sets the callback to run when a bad block is hit by the -// block processor. This method is not thread safe and should be set only once -// on startup before system events are fired. -func (d *Downloader) SetBadBlockCallback(onBadBlock badBlockFn) { - d.badBlock = onBadBlock -} - -// BeaconSync is the post-merge version of the chain synchronization, where the -// chain is not downloaded from genesis onward, rather from trusted head announces -// backwards. -// -// Internally backfilling and state sync is done the same way, but the header -// retrieval and scheduling is replaced. -func (d *Downloader) BeaconSync(mode SyncMode, head *types.Header, final *types.Header) error { - return d.beaconSync(mode, head, final, true) -} - -// BeaconExtend is an optimistic version of BeaconSync, where an attempt is made -// to extend the current beacon chain with a new header, but in case of a mismatch, -// the old sync will not be terminated and reorged, rather the new head is dropped. -// -// This is useful if a beacon client is feeding us large chunks of payloads to run, -// but is not setting the head after each. -func (d *Downloader) BeaconExtend(mode SyncMode, head *types.Header) error { - return d.beaconSync(mode, head, nil, false) -} - -// beaconSync is the post-merge version of the chain synchronization, where the -// chain is not downloaded from genesis onward, rather from trusted head announces -// backwards. -// -// Internally backfilling and state sync is done the same way, but the header -// retrieval and scheduling is replaced. -func (d *Downloader) beaconSync(mode SyncMode, head *types.Header, final *types.Header, force bool) error { - // When the downloader starts a sync cycle, it needs to be aware of the sync - // mode to use (full, snap). To keep the skeleton chain oblivious, inject the - // mode into the backfiller directly. - // - // Super crazy dangerous type cast. Should be fine (TM), we're only using a - // different backfiller implementation for skeleton tests. - d.skeleton.filler.(*beaconBackfiller).setMode(mode) - - // Signal the skeleton sync to switch to a new head, however it wants - if err := d.skeleton.Sync(head, final, force); err != nil { - return err - } - return nil -} - -// findBeaconAncestor tries to locate the common ancestor link of the local chain -// and the beacon chain just requested. In the general case when our node was in -// sync and on the correct chain, checking the top N links should already get us -// a match. In the rare scenario when we ended up on a long reorganisation (i.e. -// none of the head links match), we do a binary search to find the ancestor. -func (d *Downloader) findBeaconAncestor() (uint64, error) { - // Figure out the current local head position - var chainHead *types.Header - - switch d.getMode() { - case FullSync: - chainHead = d.blockchain.CurrentBlock() - case SnapSync: - chainHead = d.blockchain.CurrentSnapBlock() - default: - chainHead = d.lightchain.CurrentHeader() - } - number := chainHead.Number.Uint64() - - // Retrieve the skeleton bounds and ensure they are linked to the local chain - beaconHead, beaconTail, _, err := d.skeleton.Bounds() - if err != nil { - // This is a programming error. The chain backfiller was called with an - // invalid beacon sync state. Ideally we would panic here, but erroring - // gives us at least a remote chance to recover. It's still a big fault! - log.Error("Failed to retrieve beacon bounds", "err", err) - return 0, err - } - var linked bool - switch d.getMode() { - case FullSync: - linked = d.blockchain.HasBlock(beaconTail.ParentHash, beaconTail.Number.Uint64()-1) - case SnapSync: - linked = d.blockchain.HasFastBlock(beaconTail.ParentHash, beaconTail.Number.Uint64()-1) - default: - linked = d.blockchain.HasHeader(beaconTail.ParentHash, beaconTail.Number.Uint64()-1) - } - if !linked { - // This is a programming error. The chain backfiller was called with a - // tail that's not linked to the local chain. Whilst this should never - // happen, there might be some weirdnesses if beacon sync backfilling - // races with the user (or beacon client) calling setHead. Whilst panic - // would be the ideal thing to do, it is safer long term to attempt a - // recovery and fix any noticed issue after the fact. - log.Error("Beacon sync linkup unavailable", "number", beaconTail.Number.Uint64()-1, "hash", beaconTail.ParentHash) - return 0, fmt.Errorf("beacon linkup unavailable locally: %d [%x]", beaconTail.Number.Uint64()-1, beaconTail.ParentHash) - } - // Binary search to find the ancestor - start, end := beaconTail.Number.Uint64()-1, number - if number := beaconHead.Number.Uint64(); end > number { - // This shouldn't really happen in a healthy network, but if the consensus - // clients feeds us a shorter chain as the canonical, we should not attempt - // to access non-existent skeleton items. - log.Warn("Beacon head lower than local chain", "beacon", number, "local", end) - end = number - } - for start+1 < end { - // Split our chain interval in two, and request the hash to cross check - check := (start + end) / 2 - - h := d.skeleton.Header(check) - n := h.Number.Uint64() - - var known bool - switch d.getMode() { - case FullSync: - known = d.blockchain.HasBlock(h.Hash(), n) - case SnapSync: - known = d.blockchain.HasFastBlock(h.Hash(), n) - default: - known = d.lightchain.HasHeader(h.Hash(), n) - } - if !known { - end = check - continue - } - start = check - } - return start, nil -} - -// fetchBeaconHeaders feeds skeleton headers to the downloader queue for scheduling -// until sync errors or is finished. -func (d *Downloader) fetchBeaconHeaders(from uint64) error { - var head *types.Header - _, tail, _, err := d.skeleton.Bounds() - if err != nil { - return err - } - // A part of headers are not in the skeleton space, try to resolve - // them from the local chain. Note the range should be very short - // and it should only happen when there are less than 64 post-merge - // blocks in the network. - var localHeaders []*types.Header - if from < tail.Number.Uint64() { - count := tail.Number.Uint64() - from - if count > uint64(fsMinFullBlocks) { - return fmt.Errorf("invalid origin (%d) of beacon sync (%d)", from, tail.Number) - } - localHeaders = d.readHeaderRange(tail, int(count)) - log.Warn("Retrieved beacon headers from local", "from", from, "count", count) - } - for { - // Some beacon headers might have appeared since the last cycle, make - // sure we're always syncing to all available ones - head, _, _, err = d.skeleton.Bounds() - if err != nil { - return err - } - // If the pivot became stale (older than 2*64-8 (bit of wiggle room)), - // move it ahead to HEAD-64 - d.pivotLock.Lock() - if d.pivotHeader != nil { - if head.Number.Uint64() > d.pivotHeader.Number.Uint64()+2*uint64(fsMinFullBlocks)-8 { - // Retrieve the next pivot header, either from skeleton chain - // or the filled chain - number := head.Number.Uint64() - uint64(fsMinFullBlocks) - - log.Warn("Pivot seemingly stale, moving", "old", d.pivotHeader.Number, "new", number) - if d.pivotHeader = d.skeleton.Header(number); d.pivotHeader == nil { - if number < tail.Number.Uint64() { - dist := tail.Number.Uint64() - number - if len(localHeaders) >= int(dist) { - d.pivotHeader = localHeaders[dist-1] - log.Warn("Retrieved pivot header from local", "number", d.pivotHeader.Number, "hash", d.pivotHeader.Hash(), "latest", head.Number, "oldest", tail.Number) - } - } - } - // Print an error log and return directly in case the pivot header - // is still not found. It means the skeleton chain is not linked - // correctly with local chain. - if d.pivotHeader == nil { - log.Error("Pivot header is not found", "number", number) - d.pivotLock.Unlock() - return errNoPivotHeader - } - // Write out the pivot into the database so a rollback beyond - // it will reenable snap sync and update the state root that - // the state syncer will be downloading - rawdb.WriteLastPivotNumber(d.stateDB, d.pivotHeader.Number.Uint64()) - } - } - d.pivotLock.Unlock() - - // Retrieve a batch of headers and feed it to the header processor - var ( - headers = make([]*types.Header, 0, maxHeadersProcess) - hashes = make([]common.Hash, 0, maxHeadersProcess) - ) - for i := 0; i < maxHeadersProcess && from <= head.Number.Uint64(); i++ { - header := d.skeleton.Header(from) - - // The header is not found in skeleton space, try to find it in local chain. - if header == nil && from < tail.Number.Uint64() { - dist := tail.Number.Uint64() - from - if len(localHeaders) >= int(dist) { - header = localHeaders[dist-1] - } - } - // The header is still missing, the beacon sync is corrupted and bail out - // the error here. - if header == nil { - return fmt.Errorf("missing beacon header %d", from) - } - headers = append(headers, header) - hashes = append(hashes, headers[i].Hash()) - from++ - } - if len(headers) > 0 { - log.Trace("Scheduling new beacon headers", "count", len(headers), "from", from-uint64(len(headers))) - select { - case d.headerProcCh <- &headerTask{ - headers: headers, - hashes: hashes, - }: - case <-d.cancelCh: - return errCanceled - } - } - // If we still have headers to import, loop and keep pushing them - if from <= head.Number.Uint64() { - continue - } - // If the pivot block is committed, signal header sync termination - if d.committed.Load() { - select { - case d.headerProcCh <- nil: - return nil - case <-d.cancelCh: - return errCanceled - } - } - // State sync still going, wait a bit for new headers and retry - log.Trace("Pivot not yet committed, waiting...") - select { - case <-time.After(fsHeaderContCheck): - case <-d.cancelCh: - return errCanceled - } - } -} diff --git a/builder/eth/downloader/downloader.go b/builder/eth/downloader/downloader.go deleted file mode 100644 index 6e7c5dcf0..000000000 --- a/builder/eth/downloader/downloader.go +++ /dev/null @@ -1,1845 +0,0 @@ -// 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 downloader contains the manual full chain synchronisation. -package downloader - -import ( - "errors" - "fmt" - "math/big" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state/snapshot" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" -) - -var ( - MaxBlockFetch = 128 // Amount of blocks to be fetched per retrieval request - MaxHeaderFetch = 192 // Amount of block headers to be fetched per retrieval request - MaxSkeletonSize = 128 // Number of header fetches to need for a skeleton assembly - MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request - - maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection) - maxHeadersProcess = 2048 // Number of header download results to import at once into the chain - maxResultsProcess = 2048 // Number of content download results to import at once into the chain - fullMaxForkAncestry uint64 = params.FullImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) - lightMaxForkAncestry uint64 = params.LightImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it) - - reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection - reorgProtHeaderDelay = 2 // Number of headers to delay delivering to cover mini reorgs - - fsHeaderSafetyNet = 2048 // Number of headers to discard in case a chain violation is detected - fsHeaderContCheck = 3 * time.Second // Time interval to check for header continuations during state download - fsMinFullBlocks = 64 // Number of blocks to retrieve fully even in snap sync -) - -var ( - errBusy = errors.New("busy") - errUnknownPeer = errors.New("peer is unknown or unhealthy") - errBadPeer = errors.New("action from bad peer ignored") - errStallingPeer = errors.New("peer is stalling") - errUnsyncedPeer = errors.New("unsynced peer") - errNoPeers = errors.New("no peers to keep download active") - errTimeout = errors.New("timeout") - errEmptyHeaderSet = errors.New("empty header set by peer") - errPeersUnavailable = errors.New("no peers available or all tried for download") - errInvalidAncestor = errors.New("retrieved ancestor is invalid") - errInvalidChain = errors.New("retrieved hash chain is invalid") - errInvalidBody = errors.New("retrieved block body is invalid") - errInvalidReceipt = errors.New("retrieved receipt is invalid") - errCancelStateFetch = errors.New("state data download canceled (requested)") - errCancelContentProcessing = errors.New("content processing canceled (requested)") - errCanceled = errors.New("syncing canceled (requested)") - errTooOld = errors.New("peer's protocol version too old") - errNoAncestorFound = errors.New("no common ancestor found") - errNoPivotHeader = errors.New("pivot header is not found") - ErrMergeTransition = errors.New("legacy sync reached the merge") -) - -// peerDropFn is a callback type for dropping a peer detected as malicious. -type peerDropFn func(id string) - -// badBlockFn is a callback for the async beacon sync to notify the caller that -// the origin header requested to sync to, produced a chain with a bad block. -type badBlockFn func(invalid *types.Header, origin *types.Header) - -// headerTask is a set of downloaded headers to queue along with their precomputed -// hashes to avoid constant rehashing. -type headerTask struct { - headers []*types.Header - hashes []common.Hash -} - -type Downloader struct { - mode atomic.Uint32 // Synchronisation mode defining the strategy used (per sync cycle), use d.getMode() to get the SyncMode - mux *event.TypeMux // Event multiplexer to announce sync operation events - - genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT) - queue *queue // Scheduler for selecting the hashes to download - peers *peerSet // Set of active peers from which download can proceed - - stateDB ethdb.Database // Database to state sync into (and deduplicate via) - - // Statistics - syncStatsChainOrigin uint64 // Origin block number where syncing started at - syncStatsChainHeight uint64 // Highest block number known when syncing started - syncStatsLock sync.RWMutex // Lock protecting the sync stats fields - - lightchain LightChain - blockchain BlockChain - - // Callbacks - dropPeer peerDropFn // Drops a peer for misbehaving - badBlock badBlockFn // Reports a block as rejected by the chain - - // Status - synchroniseMock func(id string, hash common.Hash) error // Replacement for synchronise during testing - synchronising atomic.Bool - notified atomic.Bool - committed atomic.Bool - ancientLimit uint64 // The maximum block number which can be regarded as ancient data. - - // Channels - headerProcCh chan *headerTask // Channel to feed the header processor new tasks - - // Skeleton sync - skeleton *skeleton // Header skeleton to backfill the chain with (eth2 mode) - - // State sync - pivotHeader *types.Header // Pivot block header to dynamically push the syncing state root - pivotLock sync.RWMutex // Lock protecting pivot header reads from updates - - SnapSyncer *snap.Syncer // TODO(karalabe): make private! hack for now - stateSyncStart chan *stateSync - - // Cancellation and termination - cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop) - cancelCh chan struct{} // Channel to cancel mid-flight syncs - cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers - cancelWg sync.WaitGroup // Make sure all fetcher goroutines have exited. - - quitCh chan struct{} // Quit channel to signal termination - quitLock sync.Mutex // Lock to prevent double closes - - // Testing hooks - syncInitHook func(uint64, uint64) // Method to call upon initiating a new sync run - bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch - receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch - chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) - - // Progress reporting metrics - syncStartBlock uint64 // Head snap block when Geth was started - syncStartTime time.Time // Time instance when chain sync started - syncLogTime time.Time // Time instance when status was last reported -} - -// LightChain encapsulates functions required to synchronise a light chain. -type LightChain interface { - // HasHeader verifies a header's presence in the local chain. - HasHeader(common.Hash, uint64) bool - - // GetHeaderByHash retrieves a header from the local chain. - GetHeaderByHash(common.Hash) *types.Header - - // CurrentHeader retrieves the head header from the local chain. - CurrentHeader() *types.Header - - // GetTd returns the total difficulty of a local block. - GetTd(common.Hash, uint64) *big.Int - - // InsertHeaderChain inserts a batch of headers into the local chain. - InsertHeaderChain([]*types.Header) (int, error) - - // SetHead rewinds the local chain to a new head. - SetHead(uint64) error -} - -// BlockChain encapsulates functions required to sync a (full or snap) blockchain. -type BlockChain interface { - LightChain - - // HasBlock verifies a block's presence in the local chain. - HasBlock(common.Hash, uint64) bool - - // HasFastBlock verifies a snap block's presence in the local chain. - HasFastBlock(common.Hash, uint64) bool - - // GetBlockByHash retrieves a block from the local chain. - GetBlockByHash(common.Hash) *types.Block - - // CurrentBlock retrieves the head block from the local chain. - CurrentBlock() *types.Header - - // CurrentSnapBlock retrieves the head snap block from the local chain. - CurrentSnapBlock() *types.Header - - // SnapSyncCommitHead directly commits the head block to a certain entity. - SnapSyncCommitHead(common.Hash) error - - // InsertChain inserts a batch of blocks into the local chain. - InsertChain(types.Blocks) (int, error) - - // InsertReceiptChain inserts a batch of receipts into the local chain. - InsertReceiptChain(types.Blocks, []types.Receipts, uint64) (int, error) - - // Snapshots returns the blockchain snapshot tree to paused it during sync. - Snapshots() *snapshot.Tree - - // TrieDB retrieves the low level trie database used for interacting - // with trie nodes. - TrieDB() *triedb.Database -} - -// New creates a new downloader to fetch hashes and blocks from remote peers. -func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn, success func()) *Downloader { - if lightchain == nil { - lightchain = chain - } - dl := &Downloader{ - stateDB: stateDb, - mux: mux, - queue: newQueue(blockCacheMaxItems, blockCacheInitialItems), - peers: newPeerSet(), - blockchain: chain, - lightchain: lightchain, - dropPeer: dropPeer, - headerProcCh: make(chan *headerTask, 1), - quitCh: make(chan struct{}), - SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()), - stateSyncStart: make(chan *stateSync), - syncStartBlock: chain.CurrentSnapBlock().Number.Uint64(), - } - // Create the post-merge skeleton syncer and start the process - dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success)) - - go dl.stateFetcher() - return dl -} - -// Progress retrieves the synchronisation boundaries, specifically the origin -// block where synchronisation started at (may have failed/suspended); the block -// or header sync is currently at; and the latest known block which the sync targets. -// -// In addition, during the state download phase of snap synchronisation the number -// of processed and the total number of known states are also returned. Otherwise -// these are zero. -func (d *Downloader) Progress() ethereum.SyncProgress { - // Lock the current stats and return the progress - d.syncStatsLock.RLock() - defer d.syncStatsLock.RUnlock() - - current := uint64(0) - mode := d.getMode() - switch { - case d.blockchain != nil && mode == FullSync: - current = d.blockchain.CurrentBlock().Number.Uint64() - case d.blockchain != nil && mode == SnapSync: - current = d.blockchain.CurrentSnapBlock().Number.Uint64() - case d.lightchain != nil: - current = d.lightchain.CurrentHeader().Number.Uint64() - default: - log.Error("Unknown downloader chain/mode combo", "light", d.lightchain != nil, "full", d.blockchain != nil, "mode", mode) - } - progress, pending := d.SnapSyncer.Progress() - - return ethereum.SyncProgress{ - StartingBlock: d.syncStatsChainOrigin, - CurrentBlock: current, - HighestBlock: d.syncStatsChainHeight, - SyncedAccounts: progress.AccountSynced, - SyncedAccountBytes: uint64(progress.AccountBytes), - SyncedBytecodes: progress.BytecodeSynced, - SyncedBytecodeBytes: uint64(progress.BytecodeBytes), - SyncedStorage: progress.StorageSynced, - SyncedStorageBytes: uint64(progress.StorageBytes), - HealedTrienodes: progress.TrienodeHealSynced, - HealedTrienodeBytes: uint64(progress.TrienodeHealBytes), - HealedBytecodes: progress.BytecodeHealSynced, - HealedBytecodeBytes: uint64(progress.BytecodeHealBytes), - HealingTrienodes: pending.TrienodeHeal, - HealingBytecode: pending.BytecodeHeal, - } -} - -// RegisterPeer injects a new download peer into the set of block source to be -// used for fetching hashes and blocks from. -func (d *Downloader) RegisterPeer(id string, version uint, peer Peer) error { - var logger log.Logger - if len(id) < 16 { - // Tests use short IDs, don't choke on them - logger = log.New("peer", id) - } else { - logger = log.New("peer", id[:8]) - } - logger.Trace("Registering sync peer") - if err := d.peers.Register(newPeerConnection(id, version, peer, logger)); err != nil { - logger.Error("Failed to register sync peer", "err", err) - return err - } - return nil -} - -// UnregisterPeer remove a peer from the known list, preventing any action from -// the specified peer. An effort is also made to return any pending fetches into -// the queue. -func (d *Downloader) UnregisterPeer(id string) error { - // Unregister the peer from the active peer set and revoke any fetch tasks - var logger log.Logger - if len(id) < 16 { - // Tests use short IDs, don't choke on them - logger = log.New("peer", id) - } else { - logger = log.New("peer", id[:8]) - } - logger.Trace("Unregistering sync peer") - if err := d.peers.Unregister(id); err != nil { - logger.Error("Failed to unregister sync peer", "err", err) - return err - } - d.queue.Revoke(id) - - return nil -} - -// LegacySync tries to sync up our local block chain with a remote peer, both -// adding various sanity checks as well as wrapping it with various log entries. -func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, mode SyncMode) error { - err := d.synchronise(id, head, td, ttd, mode, false, nil) - - switch err { - case nil, errBusy, errCanceled: - return err - } - if errors.Is(err, errInvalidChain) || errors.Is(err, errBadPeer) || errors.Is(err, errTimeout) || - errors.Is(err, errStallingPeer) || errors.Is(err, errUnsyncedPeer) || errors.Is(err, errEmptyHeaderSet) || - errors.Is(err, errPeersUnavailable) || errors.Is(err, errTooOld) || errors.Is(err, errInvalidAncestor) { - log.Warn("Synchronisation failed, dropping peer", "peer", id, "err", err) - if d.dropPeer == nil { - // The dropPeer method is nil when `--copydb` is used for a local copy. - // Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored - log.Warn("Downloader wants to drop peer, but peerdrop-function is not set", "peer", id) - } else { - d.dropPeer(id) - } - return err - } - if errors.Is(err, ErrMergeTransition) { - return err // This is an expected fault, don't keep printing it in a spin-loop - } - log.Warn("Synchronisation failed, retrying", "err", err) - return err -} - -// synchronise will select the peer and use it for synchronising. If an empty string is given -// it will use the best peer possible and synchronize if its TD is higher than our own. If any of the -// checks fail an error will be returned. This method is synchronous -func (d *Downloader) synchronise(id string, hash common.Hash, td, ttd *big.Int, mode SyncMode, beaconMode bool, beaconPing chan struct{}) error { - // The beacon header syncer is async. It will start this synchronization and - // will continue doing other tasks. However, if synchronization needs to be - // cancelled, the syncer needs to know if we reached the startup point (and - // inited the cancel channel) or not yet. Make sure that we'll signal even in - // case of a failure. - if beaconPing != nil { - defer func() { - select { - case <-beaconPing: // already notified - default: - close(beaconPing) // weird exit condition, notify that it's safe to cancel (the nothing) - } - }() - } - // Mock out the synchronisation if testing - if d.synchroniseMock != nil { - return d.synchroniseMock(id, hash) - } - // Make sure only one goroutine is ever allowed past this point at once - if !d.synchronising.CompareAndSwap(false, true) { - return errBusy - } - defer d.synchronising.Store(false) - - // Post a user notification of the sync (only once per session) - if d.notified.CompareAndSwap(false, true) { - log.Info("Block synchronisation started") - } - if mode == SnapSync { - // Snap sync will directly modify the persistent state, making the entire - // trie database unusable until the state is fully synced. To prevent any - // subsequent state reads, explicitly disable the trie database and state - // syncer is responsible to address and correct any state missing. - if d.blockchain.TrieDB().Scheme() == rawdb.PathScheme { - if err := d.blockchain.TrieDB().Disable(); err != nil { - return err - } - } - // Snap sync uses the snapshot namespace to store potentially flaky data until - // sync completely heals and finishes. Pause snapshot maintenance in the mean- - // time to prevent access. - if snapshots := d.blockchain.Snapshots(); snapshots != nil { // Only nil in tests - snapshots.Disable() - } - } - // Reset the queue, peer set and wake channels to clean any internal leftover state - d.queue.Reset(blockCacheMaxItems, blockCacheInitialItems) - d.peers.Reset() - - for _, ch := range []chan bool{d.queue.blockWakeCh, d.queue.receiptWakeCh} { - select { - case <-ch: - default: - } - } - for empty := false; !empty; { - select { - case <-d.headerProcCh: - default: - empty = true - } - } - // Create cancel channel for aborting mid-flight and mark the master peer - d.cancelLock.Lock() - d.cancelCh = make(chan struct{}) - d.cancelPeer = id - d.cancelLock.Unlock() - - defer d.Cancel() // No matter what, we can't leave the cancel channel open - - // Atomically set the requested sync mode - d.mode.Store(uint32(mode)) - - // Retrieve the origin peer and initiate the downloading process - var p *peerConnection - if !beaconMode { // Beacon mode doesn't need a peer to sync from - p = d.peers.Peer(id) - if p == nil { - return errUnknownPeer - } - } - if beaconPing != nil { - close(beaconPing) - } - return d.syncWithPeer(p, hash, td, ttd, beaconMode) -} - -func (d *Downloader) getMode() SyncMode { - return SyncMode(d.mode.Load()) -} - -// syncWithPeer starts a block synchronization based on the hash chain from the -// specified peer and head hash. -func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *big.Int, beaconMode bool) (err error) { - d.mux.Post(StartEvent{}) - defer func() { - // reset on error - if err != nil { - d.mux.Post(FailedEvent{err}) - } else { - latest := d.lightchain.CurrentHeader() - d.mux.Post(DoneEvent{latest}) - } - }() - mode := d.getMode() - - if !beaconMode { - log.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "td", td, "mode", mode) - } else { - log.Debug("Backfilling with the network", "mode", mode) - } - defer func(start time.Time) { - log.Debug("Synchronisation terminated", "elapsed", common.PrettyDuration(time.Since(start))) - }(time.Now()) - - // Look up the sync boundaries: the common ancestor and the target block - var latest, pivot, final *types.Header - if !beaconMode { - // In legacy mode, use the master peer to retrieve the headers from - latest, pivot, err = d.fetchHead(p) - if err != nil { - return err - } - } else { - // In beacon mode, use the skeleton chain to retrieve the headers from - latest, _, final, err = d.skeleton.Bounds() - if err != nil { - return err - } - if latest.Number.Uint64() > uint64(fsMinFullBlocks) { - number := latest.Number.Uint64() - uint64(fsMinFullBlocks) - - // Retrieve the pivot header from the skeleton chain segment but - // fallback to local chain if it's not found in skeleton space. - if pivot = d.skeleton.Header(number); pivot == nil { - _, oldest, _, _ := d.skeleton.Bounds() // error is already checked - if number < oldest.Number.Uint64() { - count := int(oldest.Number.Uint64() - number) // it's capped by fsMinFullBlocks - headers := d.readHeaderRange(oldest, count) - if len(headers) == count { - pivot = headers[len(headers)-1] - log.Warn("Retrieved pivot header from local", "number", pivot.Number, "hash", pivot.Hash(), "latest", latest.Number, "oldest", oldest.Number) - } - } - } - // Print an error log and return directly in case the pivot header - // is still not found. It means the skeleton chain is not linked - // correctly with local chain. - if pivot == nil { - log.Error("Pivot header is not found", "number", number) - return errNoPivotHeader - } - } - } - // If no pivot block was returned, the head is below the min full block - // threshold (i.e. new chain). In that case we won't really snap sync - // anyway, but still need a valid pivot block to avoid some code hitting - // nil panics on access. - if mode == SnapSync && pivot == nil { - pivot = d.blockchain.CurrentBlock() - } - height := latest.Number.Uint64() - - var origin uint64 - if !beaconMode { - // In legacy mode, reach out to the network and find the ancestor - origin, err = d.findAncestor(p, latest) - if err != nil { - return err - } - } else { - // In beacon mode, use the skeleton chain for the ancestor lookup - origin, err = d.findBeaconAncestor() - if err != nil { - return err - } - } - d.syncStatsLock.Lock() - if d.syncStatsChainHeight <= origin || d.syncStatsChainOrigin > origin { - d.syncStatsChainOrigin = origin - } - d.syncStatsChainHeight = height - d.syncStatsLock.Unlock() - - // Ensure our origin point is below any snap sync pivot point - if mode == SnapSync { - if height <= uint64(fsMinFullBlocks) { - origin = 0 - } else { - pivotNumber := pivot.Number.Uint64() - if pivotNumber <= origin { - origin = pivotNumber - 1 - } - // Write out the pivot into the database so a rollback beyond it will - // reenable snap sync - rawdb.WriteLastPivotNumber(d.stateDB, pivotNumber) - } - } - d.committed.Store(true) - if mode == SnapSync && pivot.Number.Uint64() != 0 { - d.committed.Store(false) - } - if mode == SnapSync { - // Set the ancient data limitation. If we are running snap sync, all block - // data older than ancientLimit will be written to the ancient store. More - // recent data will be written to the active database and will wait for the - // freezer to migrate. - // - // If the network is post-merge, use either the last announced finalized - // block as the ancient limit, or if we haven't yet received one, the head- - // a max fork ancestry limit. One quirky case if we've already passed the - // finalized block, in which case the skeleton.Bounds will return nil and - // we'll revert to head - 90K. That's fine, we're finishing sync anyway. - // - // For non-merged networks, if there is a checkpoint available, then calculate - // the ancientLimit through that. Otherwise calculate the ancient limit through - // the advertised height of the remote peer. This most is mostly a fallback for - // legacy networks, but should eventually be dropped. TODO(karalabe). - if beaconMode { - // Beacon sync, use the latest finalized block as the ancient limit - // or a reasonable height if no finalized block is yet announced. - if final != nil { - d.ancientLimit = final.Number.Uint64() - } else if height > fullMaxForkAncestry+1 { - d.ancientLimit = height - fullMaxForkAncestry - 1 - } else { - d.ancientLimit = 0 - } - } else { - // Legacy sync, use the best announcement we have from the remote peer. - // TODO(karalabe): Drop this pathway. - if height > fullMaxForkAncestry+1 { - d.ancientLimit = height - fullMaxForkAncestry - 1 - } else { - d.ancientLimit = 0 - } - } - frozen, _ := d.stateDB.Ancients() // Ignore the error here since light client can also hit here. - - // If a part of blockchain data has already been written into active store, - // disable the ancient style insertion explicitly. - if origin >= frozen && frozen != 0 { - d.ancientLimit = 0 - log.Info("Disabling direct-ancient mode", "origin", origin, "ancient", frozen-1) - } else if d.ancientLimit > 0 { - log.Debug("Enabling direct-ancient mode", "ancient", d.ancientLimit) - } - // Rewind the ancient store and blockchain if reorg happens. - if origin+1 < frozen { - if err := d.lightchain.SetHead(origin); err != nil { - return err - } - log.Info("Truncated excess ancient chain segment", "oldhead", frozen-1, "newhead", origin) - } - } - // Initiate the sync using a concurrent header and content retrieval algorithm - d.queue.Prepare(origin+1, mode) - if d.syncInitHook != nil { - d.syncInitHook(origin, height) - } - var headerFetcher func() error - if !beaconMode { - // In legacy mode, headers are retrieved from the network - headerFetcher = func() error { return d.fetchHeaders(p, origin+1, latest.Number.Uint64()) } - } else { - // In beacon mode, headers are served by the skeleton syncer - headerFetcher = func() error { return d.fetchBeaconHeaders(origin + 1) } - } - fetchers := []func() error{ - headerFetcher, // Headers are always retrieved - func() error { return d.fetchBodies(origin+1, beaconMode) }, // Bodies are retrieved during normal and snap sync - func() error { return d.fetchReceipts(origin+1, beaconMode) }, // Receipts are retrieved during snap sync - func() error { return d.processHeaders(origin+1, td, ttd, beaconMode) }, - } - if mode == SnapSync { - d.pivotLock.Lock() - d.pivotHeader = pivot - d.pivotLock.Unlock() - - fetchers = append(fetchers, func() error { return d.processSnapSyncContent() }) - } else if mode == FullSync { - fetchers = append(fetchers, func() error { return d.processFullSyncContent(ttd, beaconMode) }) - } - return d.spawnSync(fetchers) -} - -// spawnSync runs d.process and all given fetcher functions to completion in -// separate goroutines, returning the first error that appears. -func (d *Downloader) spawnSync(fetchers []func() error) error { - errc := make(chan error, len(fetchers)) - d.cancelWg.Add(len(fetchers)) - for _, fn := range fetchers { - fn := fn - go func() { defer d.cancelWg.Done(); errc <- fn() }() - } - // Wait for the first error, then terminate the others. - var err error - for i := 0; i < len(fetchers); i++ { - if i == len(fetchers)-1 { - // Close the queue when all fetchers have exited. - // This will cause the block processor to end when - // it has processed the queue. - d.queue.Close() - } - if got := <-errc; got != nil { - err = got - if got != errCanceled { - break // receive a meaningful error, bubble it up - } - } - } - d.queue.Close() - d.Cancel() - return err -} - -// cancel aborts all of the operations and resets the queue. However, cancel does -// not wait for the running download goroutines to finish. This method should be -// used when cancelling the downloads from inside the downloader. -func (d *Downloader) cancel() { - // Close the current cancel channel - d.cancelLock.Lock() - defer d.cancelLock.Unlock() - - if d.cancelCh != nil { - select { - case <-d.cancelCh: - // Channel was already closed - default: - close(d.cancelCh) - } - } -} - -// Cancel aborts all of the operations and waits for all download goroutines to -// finish before returning. -func (d *Downloader) Cancel() { - d.cancel() - d.cancelWg.Wait() -} - -// Terminate interrupts the downloader, canceling all pending operations. -// The downloader cannot be reused after calling Terminate. -func (d *Downloader) Terminate() { - // Close the termination channel (make sure double close is allowed) - d.quitLock.Lock() - select { - case <-d.quitCh: - default: - close(d.quitCh) - - // Terminate the internal beacon syncer - d.skeleton.Terminate() - } - d.quitLock.Unlock() - - // Cancel any pending download requests - d.Cancel() -} - -// fetchHead retrieves the head header and prior pivot block (if available) from -// a remote peer. -func (d *Downloader) fetchHead(p *peerConnection) (head *types.Header, pivot *types.Header, err error) { - p.log.Debug("Retrieving remote chain head") - mode := d.getMode() - - // Request the advertised remote head block and wait for the response - latest, _ := p.peer.Head() - fetch := 1 - if mode == SnapSync { - fetch = 2 // head + pivot headers - } - headers, hashes, err := d.fetchHeadersByHash(p, latest, fetch, fsMinFullBlocks-1, true) - if err != nil { - return nil, nil, err - } - // Make sure the peer gave us at least one and at most the requested headers - if len(headers) == 0 || len(headers) > fetch { - return nil, nil, fmt.Errorf("%w: returned headers %d != requested %d", errBadPeer, len(headers), fetch) - } - // The first header needs to be the head, validate against the request. If - // only 1 header was returned, make sure there's no pivot or there was not - // one requested. - head = headers[0] - if len(headers) == 1 { - if mode == SnapSync && head.Number.Uint64() > uint64(fsMinFullBlocks) { - return nil, nil, fmt.Errorf("%w: no pivot included along head header", errBadPeer) - } - p.log.Debug("Remote head identified, no pivot", "number", head.Number, "hash", hashes[0]) - return head, nil, nil - } - // At this point we have 2 headers in total and the first is the - // validated head of the chain. Check the pivot number and return, - pivot = headers[1] - if pivot.Number.Uint64() != head.Number.Uint64()-uint64(fsMinFullBlocks) { - return nil, nil, fmt.Errorf("%w: remote pivot %d != requested %d", errInvalidChain, pivot.Number, head.Number.Uint64()-uint64(fsMinFullBlocks)) - } - return head, pivot, nil -} - -// calculateRequestSpan calculates what headers to request from a peer when trying to determine the -// common ancestor. -// It returns parameters to be used for peer.RequestHeadersByNumber: -// -// from - starting block number -// count - number of headers to request -// skip - number of headers to skip -// -// and also returns 'max', the last block which is expected to be returned by the remote peers, -// given the (from,count,skip) -func calculateRequestSpan(remoteHeight, localHeight uint64) (int64, int, int, uint64) { - var ( - from int - count int - MaxCount = MaxHeaderFetch / 16 - ) - // requestHead is the highest block that we will ask for. If requestHead is not offset, - // the highest block that we will get is 16 blocks back from head, which means we - // will fetch 14 or 15 blocks unnecessarily in the case the height difference - // between us and the peer is 1-2 blocks, which is most common - requestHead := int(remoteHeight) - 1 - if requestHead < 0 { - requestHead = 0 - } - // requestBottom is the lowest block we want included in the query - // Ideally, we want to include the one just below our own head - requestBottom := int(localHeight - 1) - if requestBottom < 0 { - requestBottom = 0 - } - totalSpan := requestHead - requestBottom - span := 1 + totalSpan/MaxCount - if span < 2 { - span = 2 - } - if span > 16 { - span = 16 - } - - count = 1 + totalSpan/span - if count > MaxCount { - count = MaxCount - } - if count < 2 { - count = 2 - } - from = requestHead - (count-1)*span - if from < 0 { - from = 0 - } - max := from + (count-1)*span - return int64(from), count, span - 1, uint64(max) -} - -// findAncestor tries to locate the common ancestor link of the local chain and -// a remote peers blockchain. In the general case when our node was in sync and -// on the correct chain, checking the top N links should already get us a match. -// In the rare scenario when we ended up on a long reorganisation (i.e. none of -// the head links match), we do a binary search to find the common ancestor. -func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header) (uint64, error) { - // Figure out the valid ancestor range to prevent rewrite attacks - var ( - floor = int64(-1) - localHeight uint64 - remoteHeight = remoteHeader.Number.Uint64() - ) - mode := d.getMode() - switch mode { - case FullSync: - localHeight = d.blockchain.CurrentBlock().Number.Uint64() - case SnapSync: - localHeight = d.blockchain.CurrentSnapBlock().Number.Uint64() - default: - localHeight = d.lightchain.CurrentHeader().Number.Uint64() - } - p.log.Debug("Looking for common ancestor", "local", localHeight, "remote", remoteHeight) - - // Recap floor value for binary search - maxForkAncestry := fullMaxForkAncestry - if d.getMode() == LightSync { - maxForkAncestry = lightMaxForkAncestry - } - if localHeight >= maxForkAncestry { - // We're above the max reorg threshold, find the earliest fork point - floor = int64(localHeight - maxForkAncestry) - } - // If we're doing a light sync, ensure the floor doesn't go below the CHT, as - // all headers before that point will be missing. - if mode == LightSync { - // If we don't know the current CHT position, find it - if d.genesis == 0 { - header := d.lightchain.CurrentHeader() - for header != nil { - d.genesis = header.Number.Uint64() - if floor >= int64(d.genesis)-1 { - break - } - header = d.lightchain.GetHeaderByHash(header.ParentHash) - } - } - // We already know the "genesis" block number, cap floor to that - if floor < int64(d.genesis)-1 { - floor = int64(d.genesis) - 1 - } - } - - ancestor, err := d.findAncestorSpanSearch(p, mode, remoteHeight, localHeight, floor) - if err == nil { - return ancestor, nil - } - // The returned error was not nil. - // If the error returned does not reflect that a common ancestor was not found, return it. - // If the error reflects that a common ancestor was not found, continue to binary search, - // where the error value will be reassigned. - if !errors.Is(err, errNoAncestorFound) { - return 0, err - } - - ancestor, err = d.findAncestorBinarySearch(p, mode, remoteHeight, floor) - if err != nil { - return 0, err - } - return ancestor, nil -} - -func (d *Downloader) findAncestorSpanSearch(p *peerConnection, mode SyncMode, remoteHeight, localHeight uint64, floor int64) (uint64, error) { - from, count, skip, max := calculateRequestSpan(remoteHeight, localHeight) - - p.log.Trace("Span searching for common ancestor", "count", count, "from", from, "skip", skip) - headers, hashes, err := d.fetchHeadersByNumber(p, uint64(from), count, skip, false) - if err != nil { - return 0, err - } - // Wait for the remote response to the head fetch - number, hash := uint64(0), common.Hash{} - - // Make sure the peer actually gave something valid - if len(headers) == 0 { - p.log.Warn("Empty head header set") - return 0, errEmptyHeaderSet - } - // Make sure the peer's reply conforms to the request - for i, header := range headers { - expectNumber := from + int64(i)*int64(skip+1) - if number := header.Number.Int64(); number != expectNumber { - p.log.Warn("Head headers broke chain ordering", "index", i, "requested", expectNumber, "received", number) - return 0, fmt.Errorf("%w: %v", errInvalidChain, errors.New("head headers broke chain ordering")) - } - } - // Check if a common ancestor was found - for i := len(headers) - 1; i >= 0; i-- { - // Skip any headers that underflow/overflow our requested set - if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > max { - continue - } - // Otherwise check if we already know the header or not - h := hashes[i] - n := headers[i].Number.Uint64() - - var known bool - switch mode { - case FullSync: - known = d.blockchain.HasBlock(h, n) - case SnapSync: - known = d.blockchain.HasFastBlock(h, n) - default: - known = d.lightchain.HasHeader(h, n) - } - if known { - number, hash = n, h - break - } - } - // If the head fetch already found an ancestor, return - if hash != (common.Hash{}) { - if int64(number) <= floor { - p.log.Warn("Ancestor below allowance", "number", number, "hash", hash, "allowance", floor) - return 0, errInvalidAncestor - } - p.log.Debug("Found common ancestor", "number", number, "hash", hash) - return number, nil - } - return 0, errNoAncestorFound -} - -func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, remoteHeight uint64, floor int64) (uint64, error) { - hash := common.Hash{} - - // Ancestor not found, we need to binary search over our chain - start, end := uint64(0), remoteHeight - if floor > 0 { - start = uint64(floor) - } - p.log.Trace("Binary searching for common ancestor", "start", start, "end", end) - - for start+1 < end { - // Split our chain interval in two, and request the hash to cross check - check := (start + end) / 2 - - headers, hashes, err := d.fetchHeadersByNumber(p, check, 1, 0, false) - if err != nil { - return 0, err - } - // Make sure the peer actually gave something valid - if len(headers) != 1 { - p.log.Warn("Multiple headers for single request", "headers", len(headers)) - return 0, fmt.Errorf("%w: multiple headers (%d) for single request", errBadPeer, len(headers)) - } - // Modify the search interval based on the response - h := hashes[0] - n := headers[0].Number.Uint64() - - var known bool - switch mode { - case FullSync: - known = d.blockchain.HasBlock(h, n) - case SnapSync: - known = d.blockchain.HasFastBlock(h, n) - default: - known = d.lightchain.HasHeader(h, n) - } - if !known { - end = check - continue - } - header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists - if header.Number.Uint64() != check { - p.log.Warn("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check) - return 0, fmt.Errorf("%w: non-requested header (%d)", errBadPeer, header.Number) - } - start = check - hash = h - } - // Ensure valid ancestry and return - if int64(start) <= floor { - p.log.Warn("Ancestor below allowance", "number", start, "hash", hash, "allowance", floor) - return 0, errInvalidAncestor - } - p.log.Debug("Found common ancestor", "number", start, "hash", hash) - return start, nil -} - -// fetchHeaders keeps retrieving headers concurrently from the number -// requested, until no more are returned, potentially throttling on the way. To -// facilitate concurrency but still protect against malicious nodes sending bad -// headers, we construct a header chain skeleton using the "origin" peer we are -// syncing with, and fill in the missing headers using anyone else. Headers from -// other peers are only accepted if they map cleanly to the skeleton. If no one -// can fill in the skeleton - not even the origin peer - it's assumed invalid and -// the origin is dropped. -func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) error { - p.log.Debug("Directing header downloads", "origin", from) - defer p.log.Debug("Header download terminated") - - // Start pulling the header chain skeleton until all is done - var ( - skeleton = true // Skeleton assembly phase or finishing up - pivoting = false // Whether the next request is pivot verification - ancestor = from - mode = d.getMode() - ) - for { - // Pull the next batch of headers, it either: - // - Pivot check to see if the chain moved too far - // - Skeleton retrieval to permit concurrent header fetches - // - Full header retrieval if we're near the chain head - var ( - headers []*types.Header - hashes []common.Hash - err error - ) - switch { - case pivoting: - d.pivotLock.RLock() - pivot := d.pivotHeader.Number.Uint64() - d.pivotLock.RUnlock() - - p.log.Trace("Fetching next pivot header", "number", pivot+uint64(fsMinFullBlocks)) - headers, hashes, err = d.fetchHeadersByNumber(p, pivot+uint64(fsMinFullBlocks), 2, fsMinFullBlocks-9, false) // move +64 when it's 2x64-8 deep - - case skeleton: - p.log.Trace("Fetching skeleton headers", "count", MaxHeaderFetch, "from", from) - headers, hashes, err = d.fetchHeadersByNumber(p, from+uint64(MaxHeaderFetch)-1, MaxSkeletonSize, MaxHeaderFetch-1, false) - - default: - p.log.Trace("Fetching full headers", "count", MaxHeaderFetch, "from", from) - headers, hashes, err = d.fetchHeadersByNumber(p, from, MaxHeaderFetch, 0, false) - } - switch err { - case nil: - // Headers retrieved, continue with processing - - case errCanceled: - // Sync cancelled, no issue, propagate up - return err - - default: - // Header retrieval either timed out, or the peer failed in some strange way - // (e.g. disconnect). Consider the master peer bad and drop - d.dropPeer(p.id) - - // Finish the sync gracefully instead of dumping the gathered data though - for _, ch := range []chan bool{d.queue.blockWakeCh, d.queue.receiptWakeCh} { - select { - case ch <- false: - case <-d.cancelCh: - } - } - select { - case d.headerProcCh <- nil: - case <-d.cancelCh: - } - return fmt.Errorf("%w: header request failed: %v", errBadPeer, err) - } - // If the pivot is being checked, move if it became stale and run the real retrieval - var pivot uint64 - - d.pivotLock.RLock() - if d.pivotHeader != nil { - pivot = d.pivotHeader.Number.Uint64() - } - d.pivotLock.RUnlock() - - if pivoting { - if len(headers) == 2 { - if have, want := headers[0].Number.Uint64(), pivot+uint64(fsMinFullBlocks); have != want { - log.Warn("Peer sent invalid next pivot", "have", have, "want", want) - return fmt.Errorf("%w: next pivot number %d != requested %d", errInvalidChain, have, want) - } - if have, want := headers[1].Number.Uint64(), pivot+2*uint64(fsMinFullBlocks)-8; have != want { - log.Warn("Peer sent invalid pivot confirmer", "have", have, "want", want) - return fmt.Errorf("%w: next pivot confirmer number %d != requested %d", errInvalidChain, have, want) - } - log.Warn("Pivot seemingly stale, moving", "old", pivot, "new", headers[0].Number) - pivot = headers[0].Number.Uint64() - - d.pivotLock.Lock() - d.pivotHeader = headers[0] - d.pivotLock.Unlock() - - // Write out the pivot into the database so a rollback beyond - // it will reenable snap sync and update the state root that - // the state syncer will be downloading. - rawdb.WriteLastPivotNumber(d.stateDB, pivot) - } - // Disable the pivot check and fetch the next batch of headers - pivoting = false - continue - } - // If the skeleton's finished, pull any remaining head headers directly from the origin - if skeleton && len(headers) == 0 { - // A malicious node might withhold advertised headers indefinitely - if from+uint64(MaxHeaderFetch)-1 <= head { - p.log.Warn("Peer withheld skeleton headers", "advertised", head, "withheld", from+uint64(MaxHeaderFetch)-1) - return fmt.Errorf("%w: withheld skeleton headers: advertised %d, withheld #%d", errStallingPeer, head, from+uint64(MaxHeaderFetch)-1) - } - p.log.Debug("No skeleton, fetching headers directly") - skeleton = false - continue - } - // If no more headers are inbound, notify the content fetchers and return - if len(headers) == 0 { - // Don't abort header fetches while the pivot is downloading - if !d.committed.Load() && pivot <= from { - p.log.Debug("No headers, waiting for pivot commit") - select { - case <-time.After(fsHeaderContCheck): - continue - case <-d.cancelCh: - return errCanceled - } - } - // Pivot done (or not in snap sync) and no more headers, terminate the process - p.log.Debug("No more headers available") - select { - case d.headerProcCh <- nil: - return nil - case <-d.cancelCh: - return errCanceled - } - } - // If we received a skeleton batch, resolve internals concurrently - var progressed bool - if skeleton { - filled, hashset, proced, err := d.fillHeaderSkeleton(from, headers) - if err != nil { - p.log.Debug("Skeleton chain invalid", "err", err) - return fmt.Errorf("%w: %v", errInvalidChain, err) - } - headers = filled[proced:] - hashes = hashset[proced:] - - progressed = proced > 0 - from += uint64(proced) - } else { - // A malicious node might withhold advertised headers indefinitely - if n := len(headers); n < MaxHeaderFetch && headers[n-1].Number.Uint64() < head { - p.log.Warn("Peer withheld headers", "advertised", head, "delivered", headers[n-1].Number.Uint64()) - return fmt.Errorf("%w: withheld headers: advertised %d, delivered %d", errStallingPeer, head, headers[n-1].Number.Uint64()) - } - // If we're closing in on the chain head, but haven't yet reached it, delay - // the last few headers so mini reorgs on the head don't cause invalid hash - // chain errors. - if n := len(headers); n > 0 { - // Retrieve the current head we're at - var head uint64 - if mode == LightSync { - head = d.lightchain.CurrentHeader().Number.Uint64() - } else { - head = d.blockchain.CurrentSnapBlock().Number.Uint64() - if full := d.blockchain.CurrentBlock().Number.Uint64(); head < full { - head = full - } - } - // If the head is below the common ancestor, we're actually deduplicating - // already existing chain segments, so use the ancestor as the fake head. - // Otherwise, we might end up delaying header deliveries pointlessly. - if head < ancestor { - head = ancestor - } - // If the head is way older than this batch, delay the last few headers - if head+uint64(reorgProtThreshold) < headers[n-1].Number.Uint64() { - delay := reorgProtHeaderDelay - if delay > n { - delay = n - } - headers = headers[:n-delay] - hashes = hashes[:n-delay] - } - } - } - // If no headers have been delivered, or all of them have been delayed, - // sleep a bit and retry. Take care with headers already consumed during - // skeleton filling - if len(headers) == 0 && !progressed { - p.log.Trace("All headers delayed, waiting") - select { - case <-time.After(fsHeaderContCheck): - continue - case <-d.cancelCh: - return errCanceled - } - } - // Insert any remaining new headers and fetch the next batch - if len(headers) > 0 { - p.log.Trace("Scheduling new headers", "count", len(headers), "from", from) - select { - case d.headerProcCh <- &headerTask{ - headers: headers, - hashes: hashes, - }: - case <-d.cancelCh: - return errCanceled - } - from += uint64(len(headers)) - } - // If we're still skeleton filling snap sync, check pivot staleness - // before continuing to the next skeleton filling - if skeleton && pivot > 0 { - pivoting = true - } - } -} - -// fillHeaderSkeleton concurrently retrieves headers from all our available peers -// and maps them to the provided skeleton header chain. -// -// Any partial results from the beginning of the skeleton is (if possible) forwarded -// immediately to the header processor to keep the rest of the pipeline full even -// in the case of header stalls. -// -// The method returns the entire filled skeleton and also the number of headers -// already forwarded for processing. -func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) ([]*types.Header, []common.Hash, int, error) { - log.Debug("Filling up skeleton", "from", from) - d.queue.ScheduleSkeleton(from, skeleton) - - err := d.concurrentFetch((*headerQueue)(d), false) - if err != nil { - log.Debug("Skeleton fill failed", "err", err) - } - filled, hashes, proced := d.queue.RetrieveHeaders() - if err == nil { - log.Debug("Skeleton fill succeeded", "filled", len(filled), "processed", proced) - } - return filled, hashes, proced, err -} - -// fetchBodies iteratively downloads the scheduled block bodies, taking any -// available peers, reserving a chunk of blocks for each, waiting for delivery -// and also periodically checking for timeouts. -func (d *Downloader) fetchBodies(from uint64, beaconMode bool) error { - log.Debug("Downloading block bodies", "origin", from) - err := d.concurrentFetch((*bodyQueue)(d), beaconMode) - - log.Debug("Block body download terminated", "err", err) - return err -} - -// fetchReceipts iteratively downloads the scheduled block receipts, taking any -// available peers, reserving a chunk of receipts for each, waiting for delivery -// and also periodically checking for timeouts. -func (d *Downloader) fetchReceipts(from uint64, beaconMode bool) error { - log.Debug("Downloading receipts", "origin", from) - err := d.concurrentFetch((*receiptQueue)(d), beaconMode) - - log.Debug("Receipt download terminated", "err", err) - return err -} - -// processHeaders takes batches of retrieved headers from an input channel and -// keeps processing and scheduling them into the header chain and downloader's -// queue until the stream ends or a failure occurs. -func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error { - var ( - mode = d.getMode() - gotHeaders = false // Wait for batches of headers to process - ) - for { - select { - case <-d.cancelCh: - return errCanceled - - case task := <-d.headerProcCh: - // Terminate header processing if we synced up - if task == nil || len(task.headers) == 0 { - // Notify everyone that headers are fully processed - for _, ch := range []chan bool{d.queue.blockWakeCh, d.queue.receiptWakeCh} { - select { - case ch <- false: - case <-d.cancelCh: - } - } - // If we're in legacy sync mode, we need to check total difficulty - // violations from malicious peers. That is not needed in beacon - // mode and we can skip to terminating sync. - if !beaconMode { - // If no headers were retrieved at all, the peer violated its TD promise that it had a - // better chain compared to ours. The only exception is if its promised blocks were - // already imported by other means (e.g. fetcher): - // - // R , L : Both at block 10 - // R: Mine block 11, and propagate it to L - // L: Queue block 11 for import - // L: Notice that R's head and TD increased compared to ours, start sync - // L: Import of block 11 finishes - // L: Sync begins, and finds common ancestor at 11 - // L: Request new headers up from 11 (R's TD was higher, it must have something) - // R: Nothing to give - if mode != LightSync { - head := d.blockchain.CurrentBlock() - if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 { - return errStallingPeer - } - } - // If snap or light syncing, ensure promised headers are indeed delivered. This is - // needed to detect scenarios where an attacker feeds a bad pivot and then bails out - // of delivering the post-pivot blocks that would flag the invalid content. - // - // This check cannot be executed "as is" for full imports, since blocks may still be - // queued for processing when the header download completes. However, as long as the - // peer gave us something useful, we're already happy/progressed (above check). - if mode == SnapSync || mode == LightSync { - head := d.lightchain.CurrentHeader() - if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 { - return errStallingPeer - } - } - } - return nil - } - // Otherwise split the chunk of headers into batches and process them - headers, hashes := task.headers, task.hashes - - gotHeaders = true - for len(headers) > 0 { - // Terminate if something failed in between processing chunks - select { - case <-d.cancelCh: - return errCanceled - default: - } - // Select the next chunk of headers to import - limit := maxHeadersProcess - if limit > len(headers) { - limit = len(headers) - } - chunkHeaders := headers[:limit] - chunkHashes := hashes[:limit] - - // In case of header only syncing, validate the chunk immediately - if mode == SnapSync || mode == LightSync { - // Although the received headers might be all valid, a legacy - // PoW/PoA sync must not accept post-merge headers. Make sure - // that any transition is rejected at this point. - var ( - rejected []*types.Header - td *big.Int - ) - if !beaconMode && ttd != nil { - td = d.blockchain.GetTd(chunkHeaders[0].ParentHash, chunkHeaders[0].Number.Uint64()-1) - if td == nil { - // This should never really happen, but handle gracefully for now - log.Error("Failed to retrieve parent header TD", "number", chunkHeaders[0].Number.Uint64()-1, "hash", chunkHeaders[0].ParentHash) - return fmt.Errorf("%w: parent TD missing", errInvalidChain) - } - for i, header := range chunkHeaders { - td = new(big.Int).Add(td, header.Difficulty) - if td.Cmp(ttd) >= 0 { - // Terminal total difficulty reached, allow the last header in - if new(big.Int).Sub(td, header.Difficulty).Cmp(ttd) < 0 { - chunkHeaders, rejected = chunkHeaders[:i+1], chunkHeaders[i+1:] - if len(rejected) > 0 { - // Make a nicer user log as to the first TD truly rejected - td = new(big.Int).Add(td, rejected[0].Difficulty) - } - } else { - chunkHeaders, rejected = chunkHeaders[:i], chunkHeaders[i:] - } - break - } - } - } - if len(chunkHeaders) > 0 { - if n, err := d.lightchain.InsertHeaderChain(chunkHeaders); err != nil { - log.Warn("Invalid header encountered", "number", chunkHeaders[n].Number, "hash", chunkHashes[n], "parent", chunkHeaders[n].ParentHash, "err", err) - return fmt.Errorf("%w: %v", errInvalidChain, err) - } - } - if len(rejected) != 0 { - log.Info("Legacy sync reached merge threshold", "number", rejected[0].Number, "hash", rejected[0].Hash(), "td", td, "ttd", ttd) - return ErrMergeTransition - } - } - // Unless we're doing light chains, schedule the headers for associated content retrieval - if mode == FullSync || mode == SnapSync { - // If we've reached the allowed number of pending headers, stall a bit - for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { - select { - case <-d.cancelCh: - return errCanceled - case <-time.After(time.Second): - } - } - // Otherwise insert the headers for content retrieval - inserts := d.queue.Schedule(chunkHeaders, chunkHashes, origin) - if len(inserts) != len(chunkHeaders) { - return fmt.Errorf("%w: stale headers", errBadPeer) - } - } - headers = headers[limit:] - hashes = hashes[limit:] - origin += uint64(limit) - } - // Update the highest block number we know if a higher one is found. - d.syncStatsLock.Lock() - if d.syncStatsChainHeight < origin { - d.syncStatsChainHeight = origin - 1 - } - d.syncStatsLock.Unlock() - - // Signal the content downloaders of the availability of new tasks - for _, ch := range []chan bool{d.queue.blockWakeCh, d.queue.receiptWakeCh} { - select { - case ch <- true: - default: - } - } - } - } -} - -// processFullSyncContent takes fetch results from the queue and imports them into the chain. -func (d *Downloader) processFullSyncContent(ttd *big.Int, beaconMode bool) error { - for { - results := d.queue.Results(true) - if len(results) == 0 { - return nil - } - if d.chainInsertHook != nil { - d.chainInsertHook(results) - } - // Although the received blocks might be all valid, a legacy PoW/PoA sync - // must not accept post-merge blocks. Make sure that pre-merge blocks are - // imported, but post-merge ones are rejected. - var ( - rejected []*fetchResult - td *big.Int - ) - if !beaconMode && ttd != nil { - td = d.blockchain.GetTd(results[0].Header.ParentHash, results[0].Header.Number.Uint64()-1) - if td == nil { - // This should never really happen, but handle gracefully for now - log.Error("Failed to retrieve parent block TD", "number", results[0].Header.Number.Uint64()-1, "hash", results[0].Header.ParentHash) - return fmt.Errorf("%w: parent TD missing", errInvalidChain) - } - for i, result := range results { - td = new(big.Int).Add(td, result.Header.Difficulty) - if td.Cmp(ttd) >= 0 { - // Terminal total difficulty reached, allow the last block in - if new(big.Int).Sub(td, result.Header.Difficulty).Cmp(ttd) < 0 { - results, rejected = results[:i+1], results[i+1:] - if len(rejected) > 0 { - // Make a nicer user log as to the first TD truly rejected - td = new(big.Int).Add(td, rejected[0].Header.Difficulty) - } - } else { - results, rejected = results[:i], results[i:] - } - break - } - } - } - if err := d.importBlockResults(results); err != nil { - return err - } - if len(rejected) != 0 { - log.Info("Legacy sync reached merge threshold", "number", rejected[0].Header.Number, "hash", rejected[0].Header.Hash(), "td", td, "ttd", ttd) - return ErrMergeTransition - } - } -} - -func (d *Downloader) importBlockResults(results []*fetchResult) error { - // Check for any early termination requests - if len(results) == 0 { - return nil - } - select { - case <-d.quitCh: - return errCancelContentProcessing - default: - } - // Retrieve a batch of results to import - first, last := results[0].Header, results[len(results)-1].Header - log.Debug("Inserting downloaded chain", "items", len(results), - "firstnum", first.Number, "firsthash", first.Hash(), - "lastnum", last.Number, "lasthash", last.Hash(), - ) - blocks := make([]*types.Block, len(results)) - for i, result := range results { - blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals) - } - // Downloaded blocks are always regarded as trusted after the - // transition. Because the downloaded chain is guided by the - // consensus-layer. - if index, err := d.blockchain.InsertChain(blocks); err != nil { - if index < len(results) { - log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) - - // In post-merge, notify the engine API of encountered bad chains - if d.badBlock != nil { - head, _, _, err := d.skeleton.Bounds() - if err != nil { - log.Error("Failed to retrieve beacon bounds for bad block reporting", "err", err) - } else { - d.badBlock(blocks[index].Header(), head) - } - } - } else { - // The InsertChain method in blockchain.go will sometimes return an out-of-bounds index, - // when it needs to preprocess blocks to import a sidechain. - // The importer will put together a new list of blocks to import, which is a superset - // of the blocks delivered from the downloader, and the indexing will be off. - log.Debug("Downloaded item processing failed on sidechain import", "index", index, "err", err) - } - return fmt.Errorf("%w: %v", errInvalidChain, err) - } - return nil -} - -// processSnapSyncContent takes fetch results from the queue and writes them to the -// database. It also controls the synchronisation of state nodes of the pivot block. -func (d *Downloader) processSnapSyncContent() error { - // Start syncing state of the reported head block. This should get us most of - // the state of the pivot block. - d.pivotLock.RLock() - sync := d.syncState(d.pivotHeader.Root) - d.pivotLock.RUnlock() - - defer func() { - // The `sync` object is replaced every time the pivot moves. We need to - // defer close the very last active one, hence the lazy evaluation vs. - // calling defer sync.Cancel() !!! - sync.Cancel() - }() - - closeOnErr := func(s *stateSync) { - if err := s.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled && err != snap.ErrCancelled { - d.queue.Close() // wake up Results - } - } - go closeOnErr(sync) - - // To cater for moving pivot points, track the pivot block and subsequently - // accumulated download results separately. - // - // These will be nil up to the point where we reach the pivot, and will only - // be set temporarily if the synced blocks are piling up, but the pivot is - // still busy downloading. In that case, we need to occasionally check for - // pivot moves, so need to unblock the loop. These fields will accumulate - // the results in the meantime. - // - // Note, there's no issue with memory piling up since after 64 blocks the - // pivot will forcefully move so these accumulators will be dropped. - var ( - oldPivot *fetchResult // Locked in pivot block, might change eventually - oldTail []*fetchResult // Downloaded content after the pivot - ) - for { - // Wait for the next batch of downloaded data to be available. If we have - // not yet reached the pivot point, wait blockingly as there's no need to - // spin-loop check for pivot moves. If we reached the pivot but have not - // yet processed it, check for results async, so we might notice pivot - // moves while state syncing. If the pivot was passed fully, block again - // as there's no more reason to check for pivot moves at all. - results := d.queue.Results(oldPivot == nil) - if len(results) == 0 { - // If pivot sync is done, stop - if d.committed.Load() { - d.reportSnapSyncProgress(true) - return sync.Cancel() - } - // If sync failed, stop - select { - case <-d.cancelCh: - sync.Cancel() - return errCanceled - default: - } - } - if d.chainInsertHook != nil { - d.chainInsertHook(results) - } - d.reportSnapSyncProgress(false) - - // If we haven't downloaded the pivot block yet, check pivot staleness - // notifications from the header downloader - d.pivotLock.RLock() - pivot := d.pivotHeader - d.pivotLock.RUnlock() - - if oldPivot == nil { // no results piling up, we can move the pivot - if !d.committed.Load() { // not yet passed the pivot, we can move the pivot - if pivot.Root != sync.root { // pivot position changed, we can move the pivot - sync.Cancel() - sync = d.syncState(pivot.Root) - - go closeOnErr(sync) - } - } - } else { // results already piled up, consume before handling pivot move - results = append(append([]*fetchResult{oldPivot}, oldTail...), results...) - } - // Split around the pivot block and process the two sides via snap/full sync - if !d.committed.Load() { - latest := results[len(results)-1].Header - // If the height is above the pivot block by 2 sets, it means the pivot - // become stale in the network, and it was garbage collected, move to a - // new pivot. - // - // Note, we have `reorgProtHeaderDelay` number of blocks withheld, Those - // need to be taken into account, otherwise we're detecting the pivot move - // late and will drop peers due to unavailable state!!! - if height := latest.Number.Uint64(); height >= pivot.Number.Uint64()+2*uint64(fsMinFullBlocks)-uint64(reorgProtHeaderDelay) { - log.Warn("Pivot became stale, moving", "old", pivot.Number.Uint64(), "new", height-uint64(fsMinFullBlocks)+uint64(reorgProtHeaderDelay)) - pivot = results[len(results)-1-fsMinFullBlocks+reorgProtHeaderDelay].Header // must exist as lower old pivot is uncommitted - - d.pivotLock.Lock() - d.pivotHeader = pivot - d.pivotLock.Unlock() - - // Write out the pivot into the database so a rollback beyond it will - // reenable snap sync - rawdb.WriteLastPivotNumber(d.stateDB, pivot.Number.Uint64()) - } - } - P, beforeP, afterP := splitAroundPivot(pivot.Number.Uint64(), results) - if err := d.commitSnapSyncData(beforeP, sync); err != nil { - return err - } - if P != nil { - // If new pivot block found, cancel old state retrieval and restart - if oldPivot != P { - sync.Cancel() - sync = d.syncState(P.Header.Root) - - go closeOnErr(sync) - oldPivot = P - } - // Wait for completion, occasionally checking for pivot staleness - select { - case <-sync.done: - if sync.err != nil { - return sync.err - } - if err := d.commitPivotBlock(P); err != nil { - return err - } - oldPivot = nil - - case <-time.After(time.Second): - oldTail = afterP - continue - } - } - // Fast sync done, pivot commit done, full import - if err := d.importBlockResults(afterP); err != nil { - return err - } - } -} - -func splitAroundPivot(pivot uint64, results []*fetchResult) (p *fetchResult, before, after []*fetchResult) { - if len(results) == 0 { - return nil, nil, nil - } - if lastNum := results[len(results)-1].Header.Number.Uint64(); lastNum < pivot { - // the pivot is somewhere in the future - return nil, results, nil - } - // This can also be optimized, but only happens very seldom - for _, result := range results { - num := result.Header.Number.Uint64() - switch { - case num < pivot: - before = append(before, result) - case num == pivot: - p = result - default: - after = append(after, result) - } - } - return p, before, after -} - -func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *stateSync) error { - // Check for any early termination requests - if len(results) == 0 { - return nil - } - select { - case <-d.quitCh: - return errCancelContentProcessing - case <-stateSync.done: - if err := stateSync.Wait(); err != nil { - return err - } - default: - } - // Retrieve the batch of results to import - first, last := results[0].Header, results[len(results)-1].Header - log.Debug("Inserting snap-sync blocks", "items", len(results), - "firstnum", first.Number, "firsthash", first.Hash(), - "lastnumn", last.Number, "lasthash", last.Hash(), - ) - blocks := make([]*types.Block, len(results)) - receipts := make([]types.Receipts, len(results)) - for i, result := range results { - blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals) - receipts[i] = result.Receipts - } - if index, err := d.blockchain.InsertReceiptChain(blocks, receipts, d.ancientLimit); err != nil { - log.Debug("Downloaded item processing failed", "number", results[index].Header.Number, "hash", results[index].Header.Hash(), "err", err) - return fmt.Errorf("%w: %v", errInvalidChain, err) - } - return nil -} - -func (d *Downloader) commitPivotBlock(result *fetchResult) error { - block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals) - log.Debug("Committing snap sync pivot as new head", "number", block.Number(), "hash", block.Hash()) - - // Commit the pivot block as the new head, will require full sync from here on - if _, err := d.blockchain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{result.Receipts}, d.ancientLimit); err != nil { - return err - } - if err := d.blockchain.SnapSyncCommitHead(block.Hash()); err != nil { - return err - } - d.committed.Store(true) - return nil -} - -// DeliverSnapPacket is invoked from a peer's message handler when it transmits a -// data packet for the local node to consume. -func (d *Downloader) DeliverSnapPacket(peer *snap.Peer, packet snap.Packet) error { - switch packet := packet.(type) { - case *snap.AccountRangePacket: - hashes, accounts, err := packet.Unpack() - if err != nil { - return err - } - return d.SnapSyncer.OnAccounts(peer, packet.ID, hashes, accounts, packet.Proof) - - case *snap.StorageRangesPacket: - hashset, slotset := packet.Unpack() - return d.SnapSyncer.OnStorage(peer, packet.ID, hashset, slotset, packet.Proof) - - case *snap.ByteCodesPacket: - return d.SnapSyncer.OnByteCodes(peer, packet.ID, packet.Codes) - - case *snap.TrieNodesPacket: - return d.SnapSyncer.OnTrieNodes(peer, packet.ID, packet.Nodes) - - default: - return fmt.Errorf("unexpected snap packet type: %T", packet) - } -} - -// readHeaderRange returns a list of headers, using the given last header as the base, -// and going backwards towards genesis. This method assumes that the caller already has -// placed a reasonable cap on count. -func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Header { - var ( - current = last - headers []*types.Header - ) - for { - parent := d.lightchain.GetHeaderByHash(current.ParentHash) - if parent == nil { - break // The chain is not continuous, or the chain is exhausted - } - headers = append(headers, parent) - if len(headers) >= count { - break - } - current = parent - } - return headers -} - -// reportSnapSyncProgress calculates various status reports and provides it to the user. -func (d *Downloader) reportSnapSyncProgress(force bool) { - // Initialize the sync start time if it's the first time we're reporting - if d.syncStartTime.IsZero() { - d.syncStartTime = time.Now().Add(-time.Millisecond) // -1ms offset to avoid division by zero - } - // Don't report all the events, just occasionally - if !force && time.Since(d.syncLogTime) < 8*time.Second { - return - } - // Don't report anything until we have a meaningful progress - var ( - headerBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerHeaderTable) - bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable) - receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable) - ) - syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes) - if syncedBytes == 0 { - return - } - var ( - header = d.blockchain.CurrentHeader() - block = d.blockchain.CurrentSnapBlock() - ) - syncedBlocks := block.Number.Uint64() - d.syncStartBlock - if syncedBlocks == 0 { - return - } - // Retrieve the current chain head and calculate the ETA - latest, _, _, err := d.skeleton.Bounds() - if err != nil { - // We're going to cheat for non-merged networks, but that's fine - latest = d.pivotHeader - } - if latest == nil { - // This should really never happen, but add some defensive code for now. - // TODO(karalabe): Remove it eventually if we don't see it blow. - log.Error("Nil latest block in sync progress report") - return - } - var ( - left = latest.Number.Uint64() - block.Number.Uint64() - eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left) - - progress = fmt.Sprintf("%.2f%%", float64(block.Number.Uint64())*100/float64(latest.Number.Uint64())) - headers = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(header.Number.Uint64()), common.StorageSize(headerBytes).TerminalString()) - bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(bodyBytes).TerminalString()) - receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(receiptBytes).TerminalString()) - ) - log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta)) - d.syncLogTime = time.Now() -} diff --git a/builder/eth/downloader/downloader_test.go b/builder/eth/downloader/downloader_test.go deleted file mode 100644 index 2468e1a98..000000000 --- a/builder/eth/downloader/downloader_test.go +++ /dev/null @@ -1,1313 +0,0 @@ -// 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 downloader - -import ( - "fmt" - "math/big" - "os" - "strings" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -// downloadTester is a test simulator for mocking out local block chain. -type downloadTester struct { - freezer string - chain *core.BlockChain - downloader *Downloader - - peers map[string]*downloadTesterPeer - lock sync.RWMutex -} - -// newTester creates a new downloader test mocker. -func newTester(t *testing.T) *downloadTester { - return newTesterWithNotification(t, nil) -} - -// newTester creates a new downloader test mocker. -func newTesterWithNotification(t *testing.T, success func()) *downloadTester { - freezer := t.TempDir() - db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), freezer, "", false) - if err != nil { - panic(err) - } - t.Cleanup(func() { - db.Close() - }) - gspec := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - chain, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - panic(err) - } - tester := &downloadTester{ - freezer: freezer, - chain: chain, - peers: make(map[string]*downloadTesterPeer), - } - tester.downloader = New(db, new(event.TypeMux), tester.chain, nil, tester.dropPeer, success) - return tester -} - -// terminate aborts any operations on the embedded downloader and releases all -// held resources. -func (dl *downloadTester) terminate() { - dl.downloader.Terminate() - dl.chain.Stop() - - os.RemoveAll(dl.freezer) -} - -// sync starts synchronizing with a remote peer, blocking until it completes. -func (dl *downloadTester) sync(id string, td *big.Int, mode SyncMode) error { - head := dl.peers[id].chain.CurrentBlock() - if td == nil { - // If no particular TD was requested, load from the peer's blockchain - td = dl.peers[id].chain.GetTd(head.Hash(), head.Number.Uint64()) - } - // Synchronise with the chosen peer and ensure proper cleanup afterwards - err := dl.downloader.synchronise(id, head.Hash(), td, nil, mode, false, nil) - select { - case <-dl.downloader.cancelCh: - // Ok, downloader fully cancelled after sync cycle - default: - // Downloader is still accepting packets, can block a peer up - panic("downloader active post sync cycle") // panic will be caught by tester - } - return err -} - -// newPeer registers a new block download source into the downloader. -func (dl *downloadTester) newPeer(id string, version uint, blocks []*types.Block) *downloadTesterPeer { - dl.lock.Lock() - defer dl.lock.Unlock() - - peer := &downloadTesterPeer{ - dl: dl, - id: id, - chain: newTestBlockchain(blocks), - withholdHeaders: make(map[common.Hash]struct{}), - } - dl.peers[id] = peer - - if err := dl.downloader.RegisterPeer(id, version, peer); err != nil { - panic(err) - } - if err := dl.downloader.SnapSyncer.Register(peer); err != nil { - panic(err) - } - return peer -} - -// dropPeer simulates a hard peer removal from the connection pool. -func (dl *downloadTester) dropPeer(id string) { - dl.lock.Lock() - defer dl.lock.Unlock() - - delete(dl.peers, id) - dl.downloader.SnapSyncer.Unregister(id) - dl.downloader.UnregisterPeer(id) -} - -type downloadTesterPeer struct { - dl *downloadTester - id string - chain *core.BlockChain - - withholdHeaders map[common.Hash]struct{} -} - -// Head constructs a function to retrieve a peer's current head hash -// and total difficulty. -func (dlp *downloadTesterPeer) Head() (common.Hash, *big.Int) { - head := dlp.chain.CurrentBlock() - return head.Hash(), dlp.chain.GetTd(head.Hash(), head.Number.Uint64()) -} - -func unmarshalRlpHeaders(rlpdata []rlp.RawValue) []*types.Header { - var headers = make([]*types.Header, len(rlpdata)) - for i, data := range rlpdata { - var h types.Header - if err := rlp.DecodeBytes(data, &h); err != nil { - panic(err) - } - headers[i] = &h - } - return headers -} - -// RequestHeadersByHash constructs a GetBlockHeaders function based on a hashed -// origin; associated with a particular peer in the download tester. The returned -// function can be used to retrieve batches of headers from the particular peer. -func (dlp *downloadTesterPeer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { - // Service the header query via the live handler code - rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Hash: origin, - }, - Amount: uint64(amount), - Skip: uint64(skip), - Reverse: reverse, - }, nil) - headers := unmarshalRlpHeaders(rlpHeaders) - // If a malicious peer is simulated withholding headers, delete them - for hash := range dlp.withholdHeaders { - for i, header := range headers { - if header.Hash() == hash { - headers = append(headers[:i], headers[i+1:]...) - break - } - } - } - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - // Deliver the headers to the downloader - req := ð.Request{ - Peer: dlp.id, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockHeadersRequest)(&headers), - Meta: hashes, - Time: 1, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil -} - -// RequestHeadersByNumber constructs a GetBlockHeaders function based on a numbered -// origin; associated with a particular peer in the download tester. The returned -// function can be used to retrieve batches of headers from the particular peer. -func (dlp *downloadTesterPeer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { - // Service the header query via the live handler code - rlpHeaders := eth.ServiceGetBlockHeadersQuery(dlp.chain, ð.GetBlockHeadersRequest{ - Origin: eth.HashOrNumber{ - Number: origin, - }, - Amount: uint64(amount), - Skip: uint64(skip), - Reverse: reverse, - }, nil) - headers := unmarshalRlpHeaders(rlpHeaders) - // If a malicious peer is simulated withholding headers, delete them - for hash := range dlp.withholdHeaders { - for i, header := range headers { - if header.Hash() == hash { - headers = append(headers[:i], headers[i+1:]...) - break - } - } - } - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - // Deliver the headers to the downloader - req := ð.Request{ - Peer: dlp.id, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockHeadersRequest)(&headers), - Meta: hashes, - Time: 1, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil -} - -// RequestBodies constructs a getBlockBodies method associated with a particular -// peer in the download tester. The returned function can be used to retrieve -// batches of block bodies from the particularly requested peer. -func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { - blobs := eth.ServiceGetBlockBodiesQuery(dlp.chain, hashes) - - bodies := make([]*eth.BlockBody, len(blobs)) - for i, blob := range blobs { - bodies[i] = new(eth.BlockBody) - rlp.DecodeBytes(blob, bodies[i]) - } - var ( - txsHashes = make([]common.Hash, len(bodies)) - uncleHashes = make([]common.Hash, len(bodies)) - withdrawalHashes = make([]common.Hash, len(bodies)) - ) - hasher := trie.NewStackTrie(nil) - for i, body := range bodies { - txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher) - uncleHashes[i] = types.CalcUncleHash(body.Uncles) - } - req := ð.Request{ - Peer: dlp.id, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockBodiesResponse)(&bodies), - Meta: [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes}, - Time: 1, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil -} - -// RequestReceipts constructs a getReceipts method associated with a particular -// peer in the download tester. The returned function can be used to retrieve -// batches of block receipts from the particularly requested peer. -func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { - blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes) - - receipts := make([][]*types.Receipt, len(blobs)) - for i, blob := range blobs { - rlp.DecodeBytes(blob, &receipts[i]) - } - hasher := trie.NewStackTrie(nil) - hashes = make([]common.Hash, len(receipts)) - for i, receipt := range receipts { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) - } - req := ð.Request{ - Peer: dlp.id, - } - res := ð.Response{ - Req: req, - Res: (*eth.ReceiptsResponse)(&receipts), - Meta: hashes, - Time: 1, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil -} - -// ID retrieves the peer's unique identifier. -func (dlp *downloadTesterPeer) ID() string { - return dlp.id -} - -// RequestAccountRange fetches a batch of accounts rooted in a specific account -// trie, starting with the origin. -func (dlp *downloadTesterPeer) RequestAccountRange(id uint64, root, origin, limit common.Hash, bytes uint64) error { - // Create the request and service it - req := &snap.GetAccountRangePacket{ - ID: id, - Root: root, - Origin: origin, - Limit: limit, - Bytes: bytes, - } - slimaccs, proofs := snap.ServiceGetAccountRangeQuery(dlp.chain, req) - - // We need to convert to non-slim format, delegate to the packet code - res := &snap.AccountRangePacket{ - ID: id, - Accounts: slimaccs, - Proof: proofs, - } - hashes, accounts, _ := res.Unpack() - - go dlp.dl.downloader.SnapSyncer.OnAccounts(dlp, id, hashes, accounts, proofs) - return nil -} - -// RequestStorageRanges fetches a batch of storage slots belonging to one or -// more accounts. If slots from only one account is requested, an origin marker -// may also be used to retrieve from there. -func (dlp *downloadTesterPeer) RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error { - // Create the request and service it - req := &snap.GetStorageRangesPacket{ - ID: id, - Accounts: accounts, - Root: root, - Origin: origin, - Limit: limit, - Bytes: bytes, - } - storage, proofs := snap.ServiceGetStorageRangesQuery(dlp.chain, req) - - // We need to convert to demultiplex, delegate to the packet code - res := &snap.StorageRangesPacket{ - ID: id, - Slots: storage, - Proof: proofs, - } - hashes, slots := res.Unpack() - - go dlp.dl.downloader.SnapSyncer.OnStorage(dlp, id, hashes, slots, proofs) - return nil -} - -// RequestByteCodes fetches a batch of bytecodes by hash. -func (dlp *downloadTesterPeer) RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error { - req := &snap.GetByteCodesPacket{ - ID: id, - Hashes: hashes, - Bytes: bytes, - } - codes := snap.ServiceGetByteCodesQuery(dlp.chain, req) - go dlp.dl.downloader.SnapSyncer.OnByteCodes(dlp, id, codes) - return nil -} - -// RequestTrieNodes fetches a batch of account or storage trie nodes rooted in -// a specific state trie. -func (dlp *downloadTesterPeer) RequestTrieNodes(id uint64, root common.Hash, paths []snap.TrieNodePathSet, bytes uint64) error { - req := &snap.GetTrieNodesPacket{ - ID: id, - Root: root, - Paths: paths, - Bytes: bytes, - } - nodes, _ := snap.ServiceGetTrieNodesQuery(dlp.chain, req, time.Now()) - go dlp.dl.downloader.SnapSyncer.OnTrieNodes(dlp, id, nodes) - return nil -} - -// Log retrieves the peer's own contextual logger. -func (dlp *downloadTesterPeer) Log() log.Logger { - return log.New("peer", dlp.id) -} - -// assertOwnChain checks if the local chain contains the correct number of items -// of the various chain components. -func assertOwnChain(t *testing.T, tester *downloadTester, length int) { - // Mark this method as a helper to report errors at callsite, not in here - t.Helper() - - headers, blocks, receipts := length, length, length - if tester.downloader.getMode() == LightSync { - blocks, receipts = 1, 1 - } - if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers { - t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers) - } - if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != blocks { - t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks) - } - if rs := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1; rs != receipts { - t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts) - } -} - -func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) } -func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) } -func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) } - -func testCanonSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a small enough block chain to download - chain := testChainBase.shorten(blockCacheMaxItems - 15) - tester.newPeer("peer", protocol, chain.blocks[1:]) - - // Synchronise with the peer and make sure all relevant data was retrieved - if err := tester.sync("peer", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) -} - -// Tests that if a large batch of blocks are being downloaded, it is throttled -// until the cached blocks are retrieved. -func TestThrottling68Full(t *testing.T) { testThrottling(t, eth.ETH68, FullSync) } -func TestThrottling68Snap(t *testing.T) { testThrottling(t, eth.ETH68, SnapSync) } - -func testThrottling(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a long block chain to download and the tester - targetBlocks := len(testChainBase.blocks) - 1 - tester.newPeer("peer", protocol, testChainBase.blocks[1:]) - - // Wrap the importer to allow stepping - var blocked atomic.Uint32 - proceed := make(chan struct{}) - tester.downloader.chainInsertHook = func(results []*fetchResult) { - blocked.Store(uint32(len(results))) - <-proceed - } - // Start a synchronisation concurrently - errc := make(chan error, 1) - go func() { - errc <- tester.sync("peer", nil, mode) - }() - // Iteratively take some blocks, always checking the retrieval count - for { - // Check the retrieval count synchronously (! reason for this ugly block) - tester.lock.RLock() - retrieved := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 - tester.lock.RUnlock() - if retrieved >= targetBlocks+1 { - break - } - // Wait a bit for sync to throttle itself - var cached, frozen int - for start := time.Now(); time.Since(start) < 3*time.Second; { - time.Sleep(25 * time.Millisecond) - - tester.lock.Lock() - tester.downloader.queue.lock.Lock() - tester.downloader.queue.resultCache.lock.Lock() - { - cached = tester.downloader.queue.resultCache.countCompleted() - frozen = int(blocked.Load()) - retrieved = int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 - } - tester.downloader.queue.resultCache.lock.Unlock() - tester.downloader.queue.lock.Unlock() - tester.lock.Unlock() - - if cached == blockCacheMaxItems || - cached == blockCacheMaxItems-reorgProtHeaderDelay || - retrieved+cached+frozen == targetBlocks+1 || - retrieved+cached+frozen == targetBlocks+1-reorgProtHeaderDelay { - break - } - } - // Make sure we filled up the cache, then exhaust it - time.Sleep(25 * time.Millisecond) // give it a chance to screw up - tester.lock.RLock() - retrieved = int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1 - tester.lock.RUnlock() - if cached != blockCacheMaxItems && cached != blockCacheMaxItems-reorgProtHeaderDelay && retrieved+cached+frozen != targetBlocks+1 && retrieved+cached+frozen != targetBlocks+1-reorgProtHeaderDelay { - t.Fatalf("block count mismatch: have %v, want %v (owned %v, blocked %v, target %v)", cached, blockCacheMaxItems, retrieved, frozen, targetBlocks+1) - } - // Permit the blocked blocks to import - if blocked.Load() > 0 { - blocked.Store(uint32(0)) - proceed <- struct{}{} - } - } - // Check that we haven't pulled more blocks than available - assertOwnChain(t, tester, targetBlocks+1) - if err := <-errc; err != nil { - t.Fatalf("block synchronization failed: %v", err) - } -} - -// Tests that simple synchronization against a forked chain works correctly. In -// this test common ancestor lookup should *not* be short circuited, and a full -// binary search should be executed. -func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) } -func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) } -func TestForkedSync68Light(t *testing.T) { testForkedSync(t, eth.ETH68, LightSync) } - -func testForkedSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chainA := testChainForkLightA.shorten(len(testChainBase.blocks) + 80) - chainB := testChainForkLightB.shorten(len(testChainBase.blocks) + 81) - tester.newPeer("fork A", protocol, chainA.blocks[1:]) - tester.newPeer("fork B", protocol, chainB.blocks[1:]) - // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("fork A", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainA.blocks)) - - // Synchronise with the second peer and make sure that fork is pulled too - if err := tester.sync("fork B", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainB.blocks)) -} - -// Tests that synchronising against a much shorter but much heavier fork works -// currently and is not dropped. -func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) } -func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) } -func TestHeavyForkedSync68Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, LightSync) } - -func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chainA := testChainForkLightA.shorten(len(testChainBase.blocks) + 80) - chainB := testChainForkHeavy.shorten(len(testChainBase.blocks) + 79) - tester.newPeer("light", protocol, chainA.blocks[1:]) - tester.newPeer("heavy", protocol, chainB.blocks[1:]) - - // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("light", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainA.blocks)) - - // Synchronise with the second peer and make sure that fork is pulled too - if err := tester.sync("heavy", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainB.blocks)) -} - -// Tests that chain forks are contained within a certain interval of the current -// chain head, ensuring that malicious peers cannot waste resources by feeding -// long dead chains. -func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) } -func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) } -func TestBoundedForkedSync68Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, LightSync) } - -func testBoundedForkedSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chainA := testChainForkLightA - chainB := testChainForkLightB - tester.newPeer("original", protocol, chainA.blocks[1:]) - tester.newPeer("rewriter", protocol, chainB.blocks[1:]) - - // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("original", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainA.blocks)) - - // Synchronise with the second peer and ensure that the fork is rejected to being too old - if err := tester.sync("rewriter", nil, mode); err != errInvalidAncestor { - t.Fatalf("sync failure mismatch: have %v, want %v", err, errInvalidAncestor) - } -} - -// Tests that chain forks are contained within a certain interval of the current -// chain head for short but heavy forks too. These are a bit special because they -// take different ancestor lookup paths. -func TestBoundedHeavyForkedSync68Full(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH68, FullSync) -} -func TestBoundedHeavyForkedSync68Snap(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH68, SnapSync) -} -func TestBoundedHeavyForkedSync68Light(t *testing.T) { - testBoundedHeavyForkedSync(t, eth.ETH68, LightSync) -} - -func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a long enough forked chain - chainA := testChainForkLightA - chainB := testChainForkHeavy - tester.newPeer("original", protocol, chainA.blocks[1:]) - - // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("original", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chainA.blocks)) - - tester.newPeer("heavy-rewriter", protocol, chainB.blocks[1:]) - // Synchronise with the second peer and ensure that the fork is rejected to being too old - if err := tester.sync("heavy-rewriter", nil, mode); err != errInvalidAncestor { - t.Fatalf("sync failure mismatch: have %v, want %v", err, errInvalidAncestor) - } -} - -// Tests that a canceled download wipes all previously accumulated state. -func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) } -func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) } -func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) } - -func testCancel(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(MaxHeaderFetch) - tester.newPeer("peer", protocol, chain.blocks[1:]) - - // Make sure canceling works with a pristine downloader - tester.downloader.Cancel() - if !tester.downloader.queue.Idle() { - t.Errorf("download queue not idle") - } - // Synchronise with the peer, but cancel afterwards - if err := tester.sync("peer", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - tester.downloader.Cancel() - if !tester.downloader.queue.Idle() { - t.Errorf("download queue not idle") - } -} - -// Tests that synchronisation from multiple peers works as intended (multi thread sanity test). -func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) } -func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) } -func TestMultiSynchronisation68Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, LightSync) } - -func testMultiSynchronisation(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create various peers with various parts of the chain - targetPeers := 8 - chain := testChainBase.shorten(targetPeers * 100) - - for i := 0; i < targetPeers; i++ { - id := fmt.Sprintf("peer #%d", i) - tester.newPeer(id, protocol, chain.shorten(len(chain.blocks) / (i + 1)).blocks[1:]) - } - if err := tester.sync("peer #0", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) -} - -// Tests that synchronisations behave well in multi-version protocol environments -// and not wreak havoc on other nodes in the network. -func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) } -func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) } -func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) } - -func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a small enough block chain to download - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - // Create peers of every type - tester.newPeer("peer 68", eth.ETH68, chain.blocks[1:]) - - // Synchronise with the requested peer and make sure all blocks were retrieved - if err := tester.sync(fmt.Sprintf("peer %d", protocol), nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) - - // Check that no peers have been dropped off - for _, version := range []int{68} { - peer := fmt.Sprintf("peer %d", version) - if _, ok := tester.peers[peer]; !ok { - t.Errorf("%s dropped", peer) - } - } -} - -// Tests that if a block is empty (e.g. header only), no body request should be -// made, and instead the header should be assembled into a whole block in itself. -func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) } -func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) } -func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) } - -func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - // Create a block chain to download - chain := testChainBase - tester.newPeer("peer", protocol, chain.blocks[1:]) - - // Instrument the downloader to signal body requests - var bodiesHave, receiptsHave atomic.Int32 - tester.downloader.bodyFetchHook = func(headers []*types.Header) { - bodiesHave.Add(int32(len(headers))) - } - tester.downloader.receiptFetchHook = func(headers []*types.Header) { - receiptsHave.Add(int32(len(headers))) - } - // Synchronise with the peer and make sure all blocks were retrieved - if err := tester.sync("peer", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) - - // Validate the number of block bodies that should have been requested - bodiesNeeded, receiptsNeeded := 0, 0 - for _, block := range chain.blocks[1:] { - if mode != LightSync && (len(block.Transactions()) > 0 || len(block.Uncles()) > 0) { - bodiesNeeded++ - } - } - for _, block := range chain.blocks[1:] { - if mode == SnapSync && len(block.Transactions()) > 0 { - receiptsNeeded++ - } - } - if int(bodiesHave.Load()) != bodiesNeeded { - t.Errorf("body retrieval count mismatch: have %v, want %v", bodiesHave.Load(), bodiesNeeded) - } - if int(receiptsHave.Load()) != receiptsNeeded { - t.Errorf("receipt retrieval count mismatch: have %v, want %v", receiptsHave.Load(), receiptsNeeded) - } -} - -// Tests that headers are enqueued continuously, preventing malicious nodes from -// stalling the downloader by feeding gapped header chains. -func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) } -func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) } -func TestMissingHeaderAttack68Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, LightSync) } - -func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - attacker := tester.newPeer("attack", protocol, chain.blocks[1:]) - attacker.withholdHeaders[chain.blocks[len(chain.blocks)/2-1].Hash()] = struct{}{} - - if err := tester.sync("attack", nil, mode); err == nil { - t.Fatalf("succeeded attacker synchronisation") - } - // Synchronise with the valid peer and make sure sync succeeds - tester.newPeer("valid", protocol, chain.blocks[1:]) - if err := tester.sync("valid", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) -} - -// Tests that if requested headers are shifted (i.e. first is missing), the queue -// detects the invalid numbering. -func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) } -func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) } -func TestShiftedHeaderAttack68Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, LightSync) } - -func testShiftedHeaderAttack(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - // Attempt a full sync with an attacker feeding shifted headers - attacker := tester.newPeer("attack", protocol, chain.blocks[1:]) - attacker.withholdHeaders[chain.blocks[1].Hash()] = struct{}{} - - if err := tester.sync("attack", nil, mode); err == nil { - t.Fatalf("succeeded attacker synchronisation") - } - // Synchronise with the valid peer and make sure sync succeeds - tester.newPeer("valid", protocol, chain.blocks[1:]) - if err := tester.sync("valid", nil, mode); err != nil { - t.Fatalf("failed to synchronise blocks: %v", err) - } - assertOwnChain(t, tester, len(chain.blocks)) -} - -// Tests that a peer advertising a high TD doesn't get to stall the downloader -// afterwards by not sending any useful hashes. -func TestHighTDStarvationAttack68Full(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH68, FullSync) -} -func TestHighTDStarvationAttack68Snap(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH68, SnapSync) -} -func TestHighTDStarvationAttack68Light(t *testing.T) { - testHighTDStarvationAttack(t, eth.ETH68, LightSync) -} - -func testHighTDStarvationAttack(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(1) - tester.newPeer("attack", protocol, chain.blocks[1:]) - if err := tester.sync("attack", big.NewInt(1000000), mode); err != errStallingPeer { - t.Fatalf("synchronisation error mismatch: have %v, want %v", err, errStallingPeer) - } -} - -// Tests that misbehaving peers are disconnected, whilst behaving ones are not. -func TestBlockHeaderAttackerDropping68(t *testing.T) { testBlockHeaderAttackerDropping(t, eth.ETH68) } - -func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) { - // Define the disconnection requirement for individual hash fetch errors - tests := []struct { - result error - drop bool - }{ - {nil, false}, // Sync succeeded, all is well - {errBusy, false}, // Sync is already in progress, no problem - {errUnknownPeer, false}, // Peer is unknown, was already dropped, don't double drop - {errBadPeer, true}, // Peer was deemed bad for some reason, drop it - {errStallingPeer, true}, // Peer was detected to be stalling, drop it - {errUnsyncedPeer, true}, // Peer was detected to be unsynced, drop it - {errNoPeers, false}, // No peers to download from, soft race, no issue - {errTimeout, true}, // No hashes received in due time, drop the peer - {errEmptyHeaderSet, true}, // No headers were returned as a response, drop as it's a dead end - {errPeersUnavailable, true}, // Nobody had the advertised blocks, drop the advertiser - {errInvalidAncestor, true}, // Agreed upon ancestor is not acceptable, drop the chain rewriter - {errInvalidChain, true}, // Hash chain was detected as invalid, definitely drop - {errInvalidBody, false}, // A bad peer was detected, but not the sync origin - {errInvalidReceipt, false}, // A bad peer was detected, but not the sync origin - {errCancelContentProcessing, false}, // Synchronisation was canceled, origin may be innocent, don't drop - } - // Run the tests and check disconnection status - tester := newTester(t) - defer tester.terminate() - chain := testChainBase.shorten(1) - - for i, tt := range tests { - // Register a new peer and ensure its presence - id := fmt.Sprintf("test %d", i) - tester.newPeer(id, protocol, chain.blocks[1:]) - if _, ok := tester.peers[id]; !ok { - t.Fatalf("test %d: registered peer not found", i) - } - // Simulate a synchronisation and check the required result - tester.downloader.synchroniseMock = func(string, common.Hash) error { return tt.result } - - tester.downloader.LegacySync(id, tester.chain.Genesis().Hash(), big.NewInt(1000), nil, FullSync) - if _, ok := tester.peers[id]; !ok != tt.drop { - t.Errorf("test %d: peer drop mismatch for %v: have %v, want %v", i, tt.result, !ok, tt.drop) - } - } -} - -// Tests that synchronisation progress (origin block number, current block number -// and highest block number) is tracked and updated correctly. -func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) } -func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) } -func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) } - -func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - // Set a sync init hook to catch progress changes - starting := make(chan struct{}) - progress := make(chan struct{}) - - tester.downloader.syncInitHook = func(origin, latest uint64) { - starting <- struct{}{} - <-progress - } - checkProgress(t, tester.downloader, "pristine", ethereum.SyncProgress{}) - - // Synchronise half the blocks and check initial progress - tester.newPeer("peer-half", protocol, chain.shorten(len(chain.blocks) / 2).blocks[1:]) - pending := new(sync.WaitGroup) - pending.Add(1) - - go func() { - defer pending.Done() - if err := tester.sync("peer-half", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - checkProgress(t, tester.downloader, "initial", ethereum.SyncProgress{ - HighestBlock: uint64(len(chain.blocks)/2 - 1), - }) - progress <- struct{}{} - pending.Wait() - - // Synchronise all the blocks and check continuation progress - tester.newPeer("peer-full", protocol, chain.blocks[1:]) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("peer-full", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - checkProgress(t, tester.downloader, "completing", ethereum.SyncProgress{ - StartingBlock: uint64(len(chain.blocks)/2 - 1), - CurrentBlock: uint64(len(chain.blocks)/2 - 1), - HighestBlock: uint64(len(chain.blocks) - 1), - }) - - // Check final progress after successful sync - progress <- struct{}{} - pending.Wait() - checkProgress(t, tester.downloader, "final", ethereum.SyncProgress{ - StartingBlock: uint64(len(chain.blocks)/2 - 1), - CurrentBlock: uint64(len(chain.blocks) - 1), - HighestBlock: uint64(len(chain.blocks) - 1), - }) -} - -func checkProgress(t *testing.T, d *Downloader, stage string, want ethereum.SyncProgress) { - // Mark this method as a helper to report errors at callsite, not in here - t.Helper() - - p := d.Progress() - if p.StartingBlock != want.StartingBlock || p.CurrentBlock != want.CurrentBlock || p.HighestBlock != want.HighestBlock { - t.Fatalf("%s progress mismatch:\nhave %+v\nwant %+v", stage, p, want) - } -} - -// Tests that synchronisation progress (origin block number and highest block -// number) is tracked and updated correctly in case of a fork (or manual head -// revertal). -func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) } -func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) } -func TestForkedSyncProgress68Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, LightSync) } - -func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chainA := testChainForkLightA.shorten(len(testChainBase.blocks) + MaxHeaderFetch) - chainB := testChainForkLightB.shorten(len(testChainBase.blocks) + MaxHeaderFetch) - - // Set a sync init hook to catch progress changes - starting := make(chan struct{}) - progress := make(chan struct{}) - - tester.downloader.syncInitHook = func(origin, latest uint64) { - starting <- struct{}{} - <-progress - } - checkProgress(t, tester.downloader, "pristine", ethereum.SyncProgress{}) - - // Synchronise with one of the forks and check progress - tester.newPeer("fork A", protocol, chainA.blocks[1:]) - pending := new(sync.WaitGroup) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("fork A", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - - checkProgress(t, tester.downloader, "initial", ethereum.SyncProgress{ - HighestBlock: uint64(len(chainA.blocks) - 1), - }) - progress <- struct{}{} - pending.Wait() - - // Simulate a successful sync above the fork - tester.downloader.syncStatsChainOrigin = tester.downloader.syncStatsChainHeight - - // Synchronise with the second fork and check progress resets - tester.newPeer("fork B", protocol, chainB.blocks[1:]) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("fork B", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - checkProgress(t, tester.downloader, "forking", ethereum.SyncProgress{ - StartingBlock: uint64(len(testChainBase.blocks)) - 1, - CurrentBlock: uint64(len(chainA.blocks) - 1), - HighestBlock: uint64(len(chainB.blocks) - 1), - }) - - // Check final progress after successful sync - progress <- struct{}{} - pending.Wait() - checkProgress(t, tester.downloader, "final", ethereum.SyncProgress{ - StartingBlock: uint64(len(testChainBase.blocks)) - 1, - CurrentBlock: uint64(len(chainB.blocks) - 1), - HighestBlock: uint64(len(chainB.blocks) - 1), - }) -} - -// Tests that if synchronisation is aborted due to some failure, then the progress -// origin is not updated in the next sync cycle, as it should be considered the -// continuation of the previous sync and not a new instance. -func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) } -func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) } -func TestFailedSyncProgress68Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, LightSync) } - -func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - // Set a sync init hook to catch progress changes - starting := make(chan struct{}) - progress := make(chan struct{}) - - tester.downloader.syncInitHook = func(origin, latest uint64) { - starting <- struct{}{} - <-progress - } - checkProgress(t, tester.downloader, "pristine", ethereum.SyncProgress{}) - - // Attempt a full sync with a faulty peer - missing := len(chain.blocks)/2 - 1 - - faulter := tester.newPeer("faulty", protocol, chain.blocks[1:]) - faulter.withholdHeaders[chain.blocks[missing].Hash()] = struct{}{} - - pending := new(sync.WaitGroup) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("faulty", nil, mode); err == nil { - panic("succeeded faulty synchronisation") - } - }() - <-starting - checkProgress(t, tester.downloader, "initial", ethereum.SyncProgress{ - HighestBlock: uint64(len(chain.blocks) - 1), - }) - progress <- struct{}{} - pending.Wait() - afterFailedSync := tester.downloader.Progress() - - // Synchronise with a good peer and check that the progress origin remind the same - // after a failure - tester.newPeer("valid", protocol, chain.blocks[1:]) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("valid", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - checkProgress(t, tester.downloader, "completing", afterFailedSync) - - // Check final progress after successful sync - progress <- struct{}{} - pending.Wait() - checkProgress(t, tester.downloader, "final", ethereum.SyncProgress{ - CurrentBlock: uint64(len(chain.blocks) - 1), - HighestBlock: uint64(len(chain.blocks) - 1), - }) -} - -// Tests that if an attacker fakes a chain height, after the attack is detected, -// the progress height is successfully reduced at the next sync invocation. -func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) } -func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) } -func TestFakedSyncProgress68Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, LightSync) } - -func testFakedSyncProgress(t *testing.T, protocol uint, mode SyncMode) { - tester := newTester(t) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - - // Set a sync init hook to catch progress changes - starting := make(chan struct{}) - progress := make(chan struct{}) - tester.downloader.syncInitHook = func(origin, latest uint64) { - starting <- struct{}{} - <-progress - } - checkProgress(t, tester.downloader, "pristine", ethereum.SyncProgress{}) - - // Create and sync with an attacker that promises a higher chain than available. - attacker := tester.newPeer("attack", protocol, chain.blocks[1:]) - numMissing := 5 - for i := len(chain.blocks) - 2; i > len(chain.blocks)-numMissing; i-- { - attacker.withholdHeaders[chain.blocks[i].Hash()] = struct{}{} - } - pending := new(sync.WaitGroup) - pending.Add(1) - go func() { - defer pending.Done() - if err := tester.sync("attack", nil, mode); err == nil { - panic("succeeded attacker synchronisation") - } - }() - <-starting - checkProgress(t, tester.downloader, "initial", ethereum.SyncProgress{ - HighestBlock: uint64(len(chain.blocks) - 1), - }) - progress <- struct{}{} - pending.Wait() - afterFailedSync := tester.downloader.Progress() - - // Synchronise with a good peer and check that the progress height has been reduced to - // the true value. - validChain := chain.shorten(len(chain.blocks) - numMissing) - tester.newPeer("valid", protocol, validChain.blocks[1:]) - pending.Add(1) - - go func() { - defer pending.Done() - if err := tester.sync("valid", nil, mode); err != nil { - panic(fmt.Sprintf("failed to synchronise blocks: %v", err)) - } - }() - <-starting - checkProgress(t, tester.downloader, "completing", ethereum.SyncProgress{ - CurrentBlock: afterFailedSync.CurrentBlock, - HighestBlock: uint64(len(validChain.blocks) - 1), - }) - // Check final progress after successful sync. - progress <- struct{}{} - pending.Wait() - checkProgress(t, tester.downloader, "final", ethereum.SyncProgress{ - CurrentBlock: uint64(len(validChain.blocks) - 1), - HighestBlock: uint64(len(validChain.blocks) - 1), - }) -} - -func TestRemoteHeaderRequestSpan(t *testing.T) { - testCases := []struct { - remoteHeight uint64 - localHeight uint64 - expected []int - }{ - // Remote is way higher. We should ask for the remote head and go backwards - {1500, 1000, - []int{1323, 1339, 1355, 1371, 1387, 1403, 1419, 1435, 1451, 1467, 1483, 1499}, - }, - {15000, 13006, - []int{14823, 14839, 14855, 14871, 14887, 14903, 14919, 14935, 14951, 14967, 14983, 14999}, - }, - // Remote is pretty close to us. We don't have to fetch as many - {1200, 1150, - []int{1149, 1154, 1159, 1164, 1169, 1174, 1179, 1184, 1189, 1194, 1199}, - }, - // Remote is equal to us (so on a fork with higher td) - // We should get the closest couple of ancestors - {1500, 1500, - []int{1497, 1499}, - }, - // We're higher than the remote! Odd - {1000, 1500, - []int{997, 999}, - }, - // Check some weird edgecases that it behaves somewhat rationally - {0, 1500, - []int{0, 2}, - }, - {6000000, 0, - []int{5999823, 5999839, 5999855, 5999871, 5999887, 5999903, 5999919, 5999935, 5999951, 5999967, 5999983, 5999999}, - }, - {0, 0, - []int{0, 2}, - }, - } - reqs := func(from, count, span int) []int { - var r []int - num := from - for len(r) < count { - r = append(r, num) - num += span + 1 - } - return r - } - for i, tt := range testCases { - from, count, span, max := calculateRequestSpan(tt.remoteHeight, tt.localHeight) - data := reqs(int(from), count, span) - - if max != uint64(data[len(data)-1]) { - t.Errorf("test %d: wrong last value %d != %d", i, data[len(data)-1], max) - } - failed := false - if len(data) != len(tt.expected) { - failed = true - t.Errorf("test %d: length wrong, expected %d got %d", i, len(tt.expected), len(data)) - } else { - for j, n := range data { - if n != tt.expected[j] { - failed = true - break - } - } - } - if failed { - res := strings.ReplaceAll(fmt.Sprint(data), " ", ",") - exp := strings.ReplaceAll(fmt.Sprint(tt.expected), " ", ",") - t.Logf("got: %v\n", res) - t.Logf("exp: %v\n", exp) - t.Errorf("test %d: wrong values", i) - } - } -} - -// Tests that peers below a pre-configured checkpoint block are prevented from -// being fast-synced from, avoiding potential cheap eclipse attacks. -func TestBeaconSync68Full(t *testing.T) { testBeaconSync(t, eth.ETH68, FullSync) } -func TestBeaconSync68Snap(t *testing.T) { testBeaconSync(t, eth.ETH68, SnapSync) } - -func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) { - //log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - - var cases = []struct { - name string // The name of testing scenario - local int // The length of local chain(canonical chain assumed), 0 means genesis is the head - }{ - {name: "Beacon sync since genesis", local: 0}, - {name: "Beacon sync with short local chain", local: 1}, - {name: "Beacon sync with long local chain", local: blockCacheMaxItems - 15 - fsMinFullBlocks/2}, - {name: "Beacon sync with full local chain", local: blockCacheMaxItems - 15 - 1}, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - success := make(chan struct{}) - tester := newTesterWithNotification(t, func() { - close(success) - }) - defer tester.terminate() - - chain := testChainBase.shorten(blockCacheMaxItems - 15) - tester.newPeer("peer", protocol, chain.blocks[1:]) - - // Build the local chain segment if it's required - if c.local > 0 { - tester.chain.InsertChain(chain.blocks[1 : c.local+1]) - } - if err := tester.downloader.BeaconSync(mode, chain.blocks[len(chain.blocks)-1].Header(), nil); err != nil { - t.Fatalf("Failed to beacon sync chain %v %v", c.name, err) - } - select { - case <-success: - // Ok, downloader fully cancelled after sync cycle - if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != len(chain.blocks) { - t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, len(chain.blocks)) - } - case <-time.NewTimer(time.Second * 3).C: - t.Fatalf("Failed to sync chain in three seconds") - } - }) - } -} diff --git a/builder/eth/downloader/events.go b/builder/eth/downloader/events.go deleted file mode 100644 index 25255a3a7..000000000 --- a/builder/eth/downloader/events.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 downloader - -import "github.com/ethereum/go-ethereum/core/types" - -type DoneEvent struct { - Latest *types.Header -} -type StartEvent struct{} -type FailedEvent struct{ Err error } diff --git a/builder/eth/downloader/fetchers.go b/builder/eth/downloader/fetchers.go deleted file mode 100644 index cc4279b0d..000000000 --- a/builder/eth/downloader/fetchers.go +++ /dev/null @@ -1,115 +0,0 @@ -// 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 downloader - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" -) - -// fetchHeadersByHash is a blocking version of Peer.RequestHeadersByHash which -// handles all the cancellation, interruption and timeout mechanisms of a data -// retrieval to allow blocking API calls. -func (d *Downloader) fetchHeadersByHash(p *peerConnection, hash common.Hash, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) { - // Create the response sink and send the network request - start := time.Now() - resCh := make(chan *eth.Response) - - req, err := p.peer.RequestHeadersByHash(hash, amount, skip, reverse, resCh) - if err != nil { - return nil, nil, err - } - defer req.Close() - - // Wait until the response arrives, the request is cancelled or times out - ttl := d.peers.rates.TargetTimeout() - - timeoutTimer := time.NewTimer(ttl) - defer timeoutTimer.Stop() - - select { - case <-d.cancelCh: - return nil, nil, errCanceled - - case <-timeoutTimer.C: - // Header retrieval timed out, update the metrics - p.log.Debug("Header request timed out", "elapsed", ttl) - headerTimeoutMeter.Mark(1) - - return nil, nil, errTimeout - - case res := <-resCh: - // Headers successfully retrieved, update the metrics - headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest)))) - - // Don't reject the packet even if it turns out to be bad, downloader will - // disconnect the peer on its own terms. Simply delivery the headers to - // be processed by the caller - res.Done <- nil - - return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil - } -} - -// fetchHeadersByNumber is a blocking version of Peer.RequestHeadersByNumber which -// handles all the cancellation, interruption and timeout mechanisms of a data -// retrieval to allow blocking API calls. -func (d *Downloader) fetchHeadersByNumber(p *peerConnection, number uint64, amount int, skip int, reverse bool) ([]*types.Header, []common.Hash, error) { - // Create the response sink and send the network request - start := time.Now() - resCh := make(chan *eth.Response) - - req, err := p.peer.RequestHeadersByNumber(number, amount, skip, reverse, resCh) - if err != nil { - return nil, nil, err - } - defer req.Close() - - // Wait until the response arrives, the request is cancelled or times out - ttl := d.peers.rates.TargetTimeout() - - timeoutTimer := time.NewTimer(ttl) - defer timeoutTimer.Stop() - - select { - case <-d.cancelCh: - return nil, nil, errCanceled - - case <-timeoutTimer.C: - // Header retrieval timed out, update the metrics - p.log.Debug("Header request timed out", "elapsed", ttl) - headerTimeoutMeter.Mark(1) - - return nil, nil, errTimeout - - case res := <-resCh: - // Headers successfully retrieved, update the metrics - headerReqTimer.Update(time.Since(start)) - headerInMeter.Mark(int64(len(*res.Res.(*eth.BlockHeadersRequest)))) - - // Don't reject the packet even if it turns out to be bad, downloader will - // disconnect the peer on its own terms. Simply delivery the headers to - // be processed by the caller - res.Done <- nil - - return *res.Res.(*eth.BlockHeadersRequest), res.Meta.([]common.Hash), nil - } -} diff --git a/builder/eth/downloader/fetchers_concurrent.go b/builder/eth/downloader/fetchers_concurrent.go deleted file mode 100644 index 649aa2761..000000000 --- a/builder/eth/downloader/fetchers_concurrent.go +++ /dev/null @@ -1,380 +0,0 @@ -// 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 downloader - -import ( - "errors" - "sort" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -// timeoutGracePeriod is the amount of time to allow for a peer to deliver a -// response to a locally already timed out request. Timeouts are not penalized -// as a peer might be temporarily overloaded, however, they still must reply -// to each request. Failing to do so is considered a protocol violation. -var timeoutGracePeriod = 2 * time.Minute - -// typedQueue is an interface defining the adaptor needed to translate the type -// specific downloader/queue schedulers into the type-agnostic general concurrent -// fetcher algorithm calls. -type typedQueue interface { - // waker returns a notification channel that gets pinged in case more fetches - // have been queued up, so the fetcher might assign it to idle peers. - waker() chan bool - - // pending returns the number of wrapped items that are currently queued for - // fetching by the concurrent downloader. - pending() int - - // capacity is responsible for calculating how many items of the abstracted - // type a particular peer is estimated to be able to retrieve within the - // allotted round trip time. - capacity(peer *peerConnection, rtt time.Duration) int - - // updateCapacity is responsible for updating how many items of the abstracted - // type a particular peer is estimated to be able to retrieve in a unit time. - updateCapacity(peer *peerConnection, items int, elapsed time.Duration) - - // reserve is responsible for allocating a requested number of pending items - // from the download queue to the specified peer. - reserve(peer *peerConnection, items int) (*fetchRequest, bool, bool) - - // unreserve is responsible for removing the current retrieval allocation - // assigned to a specific peer and placing it back into the pool to allow - // reassigning to some other peer. - unreserve(peer string) int - - // request is responsible for converting a generic fetch request into a typed - // one and sending it to the remote peer for fulfillment. - request(peer *peerConnection, req *fetchRequest, resCh chan *eth.Response) (*eth.Request, error) - - // deliver is responsible for taking a generic response packet from the - // concurrent fetcher, unpacking the type specific data and delivering - // it to the downloader's queue. - deliver(peer *peerConnection, packet *eth.Response) (int, error) -} - -// concurrentFetch iteratively downloads scheduled block parts, taking available -// peers, reserving a chunk of fetch requests for each and waiting for delivery -// or timeouts. -func (d *Downloader) concurrentFetch(queue typedQueue, beaconMode bool) error { - // Create a delivery channel to accept responses from all peers - responses := make(chan *eth.Response) - - // Track the currently active requests and their timeout order - pending := make(map[string]*eth.Request) - defer func() { - // Abort all requests on sync cycle cancellation. The requests may still - // be fulfilled by the remote side, but the dispatcher will not wait to - // deliver them since nobody's going to be listening. - for _, req := range pending { - req.Close() - } - }() - ordering := make(map[*eth.Request]int) - timeouts := prque.New[int64, *eth.Request](func(data *eth.Request, index int) { - ordering[data] = index - }) - - timeout := time.NewTimer(0) - if !timeout.Stop() { - <-timeout.C - } - defer timeout.Stop() - - // Track the timed-out but not-yet-answered requests separately. We want to - // keep tracking which peers are busy (potentially overloaded), so removing - // all trace of a timed out request is not good. We also can't just cancel - // the pending request altogether as that would prevent a late response from - // being delivered, thus never unblocking the peer. - stales := make(map[string]*eth.Request) - defer func() { - // Abort all requests on sync cycle cancellation. The requests may still - // be fulfilled by the remote side, but the dispatcher will not wait to - // deliver them since nobody's going to be listening. - for _, req := range stales { - req.Close() - } - }() - // Subscribe to peer lifecycle events to schedule tasks to new joiners and - // reschedule tasks upon disconnections. We don't care which event happened - // for simplicity, so just use a single channel. - peering := make(chan *peeringEvent, 64) // arbitrary buffer, just some burst protection - - peeringSub := d.peers.SubscribeEvents(peering) - defer peeringSub.Unsubscribe() - - // Prepare the queue and fetch block parts until the block header fetcher's done - finished := false - for { - // Short circuit if we lost all our peers - if d.peers.Len() == 0 && !beaconMode { - return errNoPeers - } - // If there's nothing more to fetch, wait or terminate - if queue.pending() == 0 { - if len(pending) == 0 && finished { - return nil - } - } else { - // Send a download request to all idle peers, until throttled - var ( - idles []*peerConnection - caps []int - ) - for _, peer := range d.peers.AllPeers() { - pending, stale := pending[peer.id], stales[peer.id] - if pending == nil && stale == nil { - idles = append(idles, peer) - caps = append(caps, queue.capacity(peer, time.Second)) - } else if stale != nil { - if waited := time.Since(stale.Sent); waited > timeoutGracePeriod { - // Request has been in flight longer than the grace period - // permitted it, consider the peer malicious attempting to - // stall the sync. - peer.log.Warn("Peer stalling, dropping", "waited", common.PrettyDuration(waited)) - d.dropPeer(peer.id) - } - } - } - sort.Sort(&peerCapacitySort{idles, caps}) - - var ( - progressed bool - throttled bool - queued = queue.pending() - ) - for _, peer := range idles { - // Short circuit if throttling activated or there are no more - // queued tasks to be retrieved - if throttled { - break - } - if queued = queue.pending(); queued == 0 { - break - } - // Reserve a chunk of fetches for a peer. A nil can mean either that - // no more headers are available, or that the peer is known not to - // have them. - request, progress, throttle := queue.reserve(peer, queue.capacity(peer, d.peers.rates.TargetRoundTrip())) - if progress { - progressed = true - } - if throttle { - throttled = true - throttleCounter.Inc(1) - } - if request == nil { - continue - } - // Fetch the chunk and make sure any errors return the hashes to the queue - req, err := queue.request(peer, request, responses) - if err != nil { - // Sending the request failed, which generally means the peer - // was disconnected in between assignment and network send. - // Although all peer removal operations return allocated tasks - // to the queue, that is async, and we can do better here by - // immediately pushing the unfulfilled requests. - queue.unreserve(peer.id) // TODO(karalabe): This needs a non-expiration method - continue - } - pending[peer.id] = req - - ttl := d.peers.rates.TargetTimeout() - ordering[req] = timeouts.Size() - - timeouts.Push(req, -time.Now().Add(ttl).UnixNano()) - if timeouts.Size() == 1 { - timeout.Reset(ttl) - } - } - // Make sure that we have peers available for fetching. If all peers have been tried - // and all failed throw an error - if !progressed && !throttled && len(pending) == 0 && len(idles) == d.peers.Len() && queued > 0 && !beaconMode { - return errPeersUnavailable - } - } - // Wait for something to happen - select { - case <-d.cancelCh: - // If sync was cancelled, tear down the parallel retriever. Pending - // requests will be cancelled locally, and the remote responses will - // be dropped when they arrive - return errCanceled - - case event := <-peering: - // A peer joined or left, the tasks queue and allocations need to be - // checked for potential assignment or reassignment - peerid := event.peer.id - - if event.join { - // Sanity check the internal state; this can be dropped later - if _, ok := pending[peerid]; ok { - event.peer.log.Error("Pending request exists for joining peer") - } - if _, ok := stales[peerid]; ok { - event.peer.log.Error("Stale request exists for joining peer") - } - // Loop back to the entry point for task assignment - continue - } - // A peer left, any existing requests need to be untracked, pending - // tasks returned and possible reassignment checked - if req, ok := pending[peerid]; ok { - queue.unreserve(peerid) // TODO(karalabe): This needs a non-expiration method - delete(pending, peerid) - req.Close() - - if index, live := ordering[req]; live { - timeouts.Remove(index) - if index == 0 { - if !timeout.Stop() { - <-timeout.C - } - if timeouts.Size() > 0 { - _, exp := timeouts.Peek() - timeout.Reset(time.Until(time.Unix(0, -exp))) - } - } - delete(ordering, req) - } - } - if req, ok := stales[peerid]; ok { - delete(stales, peerid) - req.Close() - } - - case <-timeout.C: - // Retrieve the next request which should have timed out. The check - // below is purely for to catch programming errors, given the correct - // code, there's no possible order of events that should result in a - // timeout firing for a non-existent event. - req, exp := timeouts.Peek() - if now, at := time.Now(), time.Unix(0, -exp); now.Before(at) { - log.Error("Timeout triggered but not reached", "left", at.Sub(now)) - timeout.Reset(at.Sub(now)) - continue - } - // Stop tracking the timed out request from a timing perspective, - // cancel it, so it's not considered in-flight anymore, but keep - // the peer marked busy to prevent assigning a second request and - // overloading it further. - delete(pending, req.Peer) - stales[req.Peer] = req - - timeouts.Pop() // Popping an item will reorder indices in `ordering`, delete after, otherwise will resurrect! - if timeouts.Size() > 0 { - _, exp := timeouts.Peek() - timeout.Reset(time.Until(time.Unix(0, -exp))) - } - delete(ordering, req) - - // New timeout potentially set if there are more requests pending, - // reschedule the failed one to a free peer - fails := queue.unreserve(req.Peer) - - // Finally, update the peer's retrieval capacity, or if it's already - // below the minimum allowance, drop the peer. If a lot of retrieval - // elements expired, we might have overestimated the remote peer or - // perhaps ourselves. Only reset to minimal throughput but don't drop - // just yet. - // - // The reason the minimum threshold is 2 is that the downloader tries - // to estimate the bandwidth and latency of a peer separately, which - // requires pushing the measured capacity a bit and seeing how response - // times reacts, to it always requests one more than the minimum (i.e. - // min 2). - peer := d.peers.Peer(req.Peer) - if peer == nil { - // If the peer got disconnected in between, we should really have - // short-circuited it already. Just in case there's some strange - // codepath, leave this check in not to crash. - log.Error("Delivery timeout from unknown peer", "peer", req.Peer) - continue - } - if fails > 2 { - queue.updateCapacity(peer, 0, 0) - } else { - d.dropPeer(peer.id) - - // If this peer was the master peer, abort sync immediately - d.cancelLock.RLock() - master := peer.id == d.cancelPeer - d.cancelLock.RUnlock() - - if master { - d.cancel() - return errTimeout - } - } - - case res := <-responses: - // Response arrived, it may be for an existing or an already timed - // out request. If the former, update the timeout heap and perhaps - // reschedule the timeout timer. - index, live := ordering[res.Req] - if live { - timeouts.Remove(index) - if index == 0 { - if !timeout.Stop() { - <-timeout.C - } - if timeouts.Size() > 0 { - _, exp := timeouts.Peek() - timeout.Reset(time.Until(time.Unix(0, -exp))) - } - } - delete(ordering, res.Req) - } - // Delete the pending request (if it still exists) and mark the peer idle - delete(pending, res.Req.Peer) - delete(stales, res.Req.Peer) - - // Signal the dispatcher that the round trip is done. We'll drop the - // peer if the data turns out to be junk. - res.Done <- nil - res.Req.Close() - - // If the peer was previously banned and failed to deliver its pack - // in a reasonable time frame, ignore its message. - if peer := d.peers.Peer(res.Req.Peer); peer != nil { - // Deliver the received chunk of data and check chain validity - accepted, err := queue.deliver(peer, res) - if errors.Is(err, errInvalidChain) { - return err - } - // Unless a peer delivered something completely else than requested (usually - // caused by a timed out request which came through in the end), set it to - // idle. If the delivery's stale, the peer should have already been idled. - if !errors.Is(err, errStaleDelivery) { - queue.updateCapacity(peer, accepted, res.Time) - } - } - - case cont := <-queue.waker(): - // The header fetcher sent a continuation flag, check if it's done - if !cont { - finished = true - } - } - } -} diff --git a/builder/eth/downloader/fetchers_concurrent_bodies.go b/builder/eth/downloader/fetchers_concurrent_bodies.go deleted file mode 100644 index 5105fda66..000000000 --- a/builder/eth/downloader/fetchers_concurrent_bodies.go +++ /dev/null @@ -1,105 +0,0 @@ -// 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 downloader - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -// bodyQueue implements typedQueue and is a type adapter between the generic -// concurrent fetcher and the downloader. -type bodyQueue Downloader - -// waker returns a notification channel that gets pinged in case more body -// fetches have been queued up, so the fetcher might assign it to idle peers. -func (q *bodyQueue) waker() chan bool { - return q.queue.blockWakeCh -} - -// pending returns the number of bodies that are currently queued for fetching -// by the concurrent downloader. -func (q *bodyQueue) pending() int { - return q.queue.PendingBodies() -} - -// capacity is responsible for calculating how many bodies a particular peer is -// estimated to be able to retrieve within the allotted round trip time. -func (q *bodyQueue) capacity(peer *peerConnection, rtt time.Duration) int { - return peer.BodyCapacity(rtt) -} - -// updateCapacity is responsible for updating how many bodies a particular peer -// is estimated to be able to retrieve in a unit time. -func (q *bodyQueue) updateCapacity(peer *peerConnection, items int, span time.Duration) { - peer.UpdateBodyRate(items, span) -} - -// reserve is responsible for allocating a requested number of pending bodies -// from the download queue to the specified peer. -func (q *bodyQueue) reserve(peer *peerConnection, items int) (*fetchRequest, bool, bool) { - return q.queue.ReserveBodies(peer, items) -} - -// unreserve is responsible for removing the current body retrieval allocation -// assigned to a specific peer and placing it back into the pool to allow -// reassigning to some other peer. -func (q *bodyQueue) unreserve(peer string) int { - fails := q.queue.ExpireBodies(peer) - if fails > 2 { - log.Trace("Body delivery timed out", "peer", peer) - } else { - log.Debug("Body delivery stalling", "peer", peer) - } - return fails -} - -// request is responsible for converting a generic fetch request into a body -// one and sending it to the remote peer for fulfillment. -func (q *bodyQueue) request(peer *peerConnection, req *fetchRequest, resCh chan *eth.Response) (*eth.Request, error) { - peer.log.Trace("Requesting new batch of bodies", "count", len(req.Headers), "from", req.Headers[0].Number) - if q.bodyFetchHook != nil { - q.bodyFetchHook(req.Headers) - } - - hashes := make([]common.Hash, 0, len(req.Headers)) - for _, header := range req.Headers { - hashes = append(hashes, header.Hash()) - } - return peer.peer.RequestBodies(hashes, resCh) -} - -// deliver is responsible for taking a generic response packet from the concurrent -// fetcher, unpacking the body data and delivering it to the downloader's queue. -func (q *bodyQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - txs, uncles, withdrawals := packet.Res.(*eth.BlockBodiesResponse).Unpack() - hashsets := packet.Meta.([][]common.Hash) // {txs hashes, uncle hashes, withdrawal hashes} - - accepted, err := q.queue.DeliverBodies(peer.id, txs, hashsets[0], uncles, hashsets[1], withdrawals, hashsets[2]) - switch { - case err == nil && len(txs) == 0: - peer.log.Trace("Requested bodies delivered") - case err == nil: - peer.log.Trace("Delivered new batch of bodies", "count", len(txs), "accepted", accepted) - default: - peer.log.Debug("Failed to deliver retrieved bodies", "err", err) - } - return accepted, err -} diff --git a/builder/eth/downloader/fetchers_concurrent_headers.go b/builder/eth/downloader/fetchers_concurrent_headers.go deleted file mode 100644 index 8201f4ca7..000000000 --- a/builder/eth/downloader/fetchers_concurrent_headers.go +++ /dev/null @@ -1,97 +0,0 @@ -// 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 downloader - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -// headerQueue implements typedQueue and is a type adapter between the generic -// concurrent fetcher and the downloader. -type headerQueue Downloader - -// waker returns a notification channel that gets pinged in case more header -// fetches have been queued up, so the fetcher might assign it to idle peers. -func (q *headerQueue) waker() chan bool { - return q.queue.headerContCh -} - -// pending returns the number of headers that are currently queued for fetching -// by the concurrent downloader. -func (q *headerQueue) pending() int { - return q.queue.PendingHeaders() -} - -// capacity is responsible for calculating how many headers a particular peer is -// estimated to be able to retrieve within the allotted round trip time. -func (q *headerQueue) capacity(peer *peerConnection, rtt time.Duration) int { - return peer.HeaderCapacity(rtt) -} - -// updateCapacity is responsible for updating how many headers a particular peer -// is estimated to be able to retrieve in a unit time. -func (q *headerQueue) updateCapacity(peer *peerConnection, items int, span time.Duration) { - peer.UpdateHeaderRate(items, span) -} - -// reserve is responsible for allocating a requested number of pending headers -// from the download queue to the specified peer. -func (q *headerQueue) reserve(peer *peerConnection, items int) (*fetchRequest, bool, bool) { - return q.queue.ReserveHeaders(peer, items), false, false -} - -// unreserve is responsible for removing the current header retrieval allocation -// assigned to a specific peer and placing it back into the pool to allow -// reassigning to some other peer. -func (q *headerQueue) unreserve(peer string) int { - fails := q.queue.ExpireHeaders(peer) - if fails > 2 { - log.Trace("Header delivery timed out", "peer", peer) - } else { - log.Debug("Header delivery stalling", "peer", peer) - } - return fails -} - -// request is responsible for converting a generic fetch request into a header -// one and sending it to the remote peer for fulfillment. -func (q *headerQueue) request(peer *peerConnection, req *fetchRequest, resCh chan *eth.Response) (*eth.Request, error) { - peer.log.Trace("Requesting new batch of headers", "from", req.From) - return peer.peer.RequestHeadersByNumber(req.From, MaxHeaderFetch, 0, false, resCh) -} - -// deliver is responsible for taking a generic response packet from the concurrent -// fetcher, unpacking the header data and delivering it to the downloader's queue. -func (q *headerQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - headers := *packet.Res.(*eth.BlockHeadersRequest) - hashes := packet.Meta.([]common.Hash) - - accepted, err := q.queue.DeliverHeaders(peer.id, headers, hashes, q.headerProcCh) - switch { - case err == nil && len(headers) == 0: - peer.log.Trace("Requested headers delivered") - case err == nil: - peer.log.Trace("Delivered new batch of headers", "count", len(headers), "accepted", accepted) - default: - peer.log.Debug("Failed to deliver retrieved headers", "err", err) - } - return accepted, err -} diff --git a/builder/eth/downloader/fetchers_concurrent_receipts.go b/builder/eth/downloader/fetchers_concurrent_receipts.go deleted file mode 100644 index 3169f030b..000000000 --- a/builder/eth/downloader/fetchers_concurrent_receipts.go +++ /dev/null @@ -1,104 +0,0 @@ -// 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 downloader - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -// receiptQueue implements typedQueue and is a type adapter between the generic -// concurrent fetcher and the downloader. -type receiptQueue Downloader - -// waker returns a notification channel that gets pinged in case more receipt -// fetches have been queued up, so the fetcher might assign it to idle peers. -func (q *receiptQueue) waker() chan bool { - return q.queue.receiptWakeCh -} - -// pending returns the number of receipt that are currently queued for fetching -// by the concurrent downloader. -func (q *receiptQueue) pending() int { - return q.queue.PendingReceipts() -} - -// capacity is responsible for calculating how many receipts a particular peer is -// estimated to be able to retrieve within the allotted round trip time. -func (q *receiptQueue) capacity(peer *peerConnection, rtt time.Duration) int { - return peer.ReceiptCapacity(rtt) -} - -// updateCapacity is responsible for updating how many receipts a particular peer -// is estimated to be able to retrieve in a unit time. -func (q *receiptQueue) updateCapacity(peer *peerConnection, items int, span time.Duration) { - peer.UpdateReceiptRate(items, span) -} - -// reserve is responsible for allocating a requested number of pending receipts -// from the download queue to the specified peer. -func (q *receiptQueue) reserve(peer *peerConnection, items int) (*fetchRequest, bool, bool) { - return q.queue.ReserveReceipts(peer, items) -} - -// unreserve is responsible for removing the current receipt retrieval allocation -// assigned to a specific peer and placing it back into the pool to allow -// reassigning to some other peer. -func (q *receiptQueue) unreserve(peer string) int { - fails := q.queue.ExpireReceipts(peer) - if fails > 2 { - log.Trace("Receipt delivery timed out", "peer", peer) - } else { - log.Debug("Receipt delivery stalling", "peer", peer) - } - return fails -} - -// request is responsible for converting a generic fetch request into a receipt -// one and sending it to the remote peer for fulfillment. -func (q *receiptQueue) request(peer *peerConnection, req *fetchRequest, resCh chan *eth.Response) (*eth.Request, error) { - peer.log.Trace("Requesting new batch of receipts", "count", len(req.Headers), "from", req.Headers[0].Number) - if q.receiptFetchHook != nil { - q.receiptFetchHook(req.Headers) - } - hashes := make([]common.Hash, 0, len(req.Headers)) - for _, header := range req.Headers { - hashes = append(hashes, header.Hash()) - } - return peer.peer.RequestReceipts(hashes, resCh) -} - -// deliver is responsible for taking a generic response packet from the concurrent -// fetcher, unpacking the receipt data and delivering it to the downloader's queue. -func (q *receiptQueue) deliver(peer *peerConnection, packet *eth.Response) (int, error) { - receipts := *packet.Res.(*eth.ReceiptsResponse) - hashes := packet.Meta.([]common.Hash) // {receipt hashes} - - accepted, err := q.queue.DeliverReceipts(peer.id, receipts, hashes) - switch { - case err == nil && len(receipts) == 0: - peer.log.Trace("Requested receipts delivered") - case err == nil: - peer.log.Trace("Delivered new batch of receipts", "count", len(receipts), "accepted", accepted) - default: - peer.log.Debug("Failed to deliver retrieved receipts", "err", err) - } - return accepted, err -} diff --git a/builder/eth/downloader/metrics.go b/builder/eth/downloader/metrics.go deleted file mode 100644 index 23c033a8a..000000000 --- a/builder/eth/downloader/metrics.go +++ /dev/null @@ -1,42 +0,0 @@ -// 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 . - -// Contains the metrics collected by the downloader. - -package downloader - -import ( - "github.com/ethereum/go-ethereum/metrics" -) - -var ( - headerInMeter = metrics.NewRegisteredMeter("eth/downloader/headers/in", nil) - headerReqTimer = metrics.NewRegisteredTimer("eth/downloader/headers/req", nil) - headerDropMeter = metrics.NewRegisteredMeter("eth/downloader/headers/drop", nil) - headerTimeoutMeter = metrics.NewRegisteredMeter("eth/downloader/headers/timeout", nil) - - bodyInMeter = metrics.NewRegisteredMeter("eth/downloader/bodies/in", nil) - bodyReqTimer = metrics.NewRegisteredTimer("eth/downloader/bodies/req", nil) - bodyDropMeter = metrics.NewRegisteredMeter("eth/downloader/bodies/drop", nil) - bodyTimeoutMeter = metrics.NewRegisteredMeter("eth/downloader/bodies/timeout", nil) - - receiptInMeter = metrics.NewRegisteredMeter("eth/downloader/receipts/in", nil) - receiptReqTimer = metrics.NewRegisteredTimer("eth/downloader/receipts/req", nil) - receiptDropMeter = metrics.NewRegisteredMeter("eth/downloader/receipts/drop", nil) - receiptTimeoutMeter = metrics.NewRegisteredMeter("eth/downloader/receipts/timeout", nil) - - throttleCounter = metrics.NewRegisteredCounter("eth/downloader/throttle", nil) -) diff --git a/builder/eth/downloader/modes.go b/builder/eth/downloader/modes.go deleted file mode 100644 index d388b9ee4..000000000 --- a/builder/eth/downloader/modes.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 downloader - -import "fmt" - -// SyncMode represents the synchronisation mode of the downloader. -// It is a uint32 as it is used with atomic operations. -type SyncMode uint32 - -const ( - FullSync SyncMode = iota // Synchronise the entire blockchain history from full blocks - SnapSync // Download the chain and the state via compact snapshots - LightSync // Download only the headers and terminate afterwards -) - -func (mode SyncMode) IsValid() bool { - return mode >= FullSync && mode <= LightSync -} - -// String implements the stringer interface. -func (mode SyncMode) String() string { - switch mode { - case FullSync: - return "full" - case SnapSync: - return "snap" - case LightSync: - return "light" - default: - return "unknown" - } -} - -func (mode SyncMode) MarshalText() ([]byte, error) { - switch mode { - case FullSync: - return []byte("full"), nil - case SnapSync: - return []byte("snap"), nil - case LightSync: - return []byte("light"), nil - default: - return nil, fmt.Errorf("unknown sync mode %d", mode) - } -} - -func (mode *SyncMode) UnmarshalText(text []byte) error { - switch string(text) { - case "full": - *mode = FullSync - case "snap": - *mode = SnapSync - case "light": - *mode = LightSync - default: - return fmt.Errorf(`unknown sync mode %q, want "full", "snap" or "light"`, text) - } - return nil -} diff --git a/builder/eth/downloader/peer.go b/builder/eth/downloader/peer.go deleted file mode 100644 index 4c43af527..000000000 --- a/builder/eth/downloader/peer.go +++ /dev/null @@ -1,290 +0,0 @@ -// 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 . - -// Contains the active peer-set of the downloader, maintaining both failures -// as well as reputation metrics to prioritize the block retrievals. - -package downloader - -import ( - "errors" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/msgrate" -) - -const ( - maxLackingHashes = 4096 // Maximum number of entries allowed on the list or lacking items -) - -var ( - errAlreadyRegistered = errors.New("peer is already registered") - errNotRegistered = errors.New("peer is not registered") -) - -// peerConnection represents an active peer from which hashes and blocks are retrieved. -type peerConnection struct { - id string // Unique identifier of the peer - - rates *msgrate.Tracker // Tracker to hone in on the number of items retrievable per second - lacking map[common.Hash]struct{} // Set of hashes not to request (didn't have previously) - - peer Peer - - version uint // Eth protocol version number to switch strategies - log log.Logger // Contextual logger to add extra infos to peer logs - lock sync.RWMutex -} - -// Peer encapsulates the methods required to synchronise with a remote full peer. -type Peer interface { - Head() (common.Hash, *big.Int) - RequestHeadersByHash(common.Hash, int, int, bool, chan *eth.Response) (*eth.Request, error) - RequestHeadersByNumber(uint64, int, int, bool, chan *eth.Response) (*eth.Request, error) - - RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error) - RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error) -} - -// newPeerConnection creates a new downloader peer. -func newPeerConnection(id string, version uint, peer Peer, logger log.Logger) *peerConnection { - return &peerConnection{ - id: id, - lacking: make(map[common.Hash]struct{}), - peer: peer, - version: version, - log: logger, - } -} - -// Reset clears the internal state of a peer entity. -func (p *peerConnection) Reset() { - p.lock.Lock() - defer p.lock.Unlock() - - p.lacking = make(map[common.Hash]struct{}) -} - -// UpdateHeaderRate updates the peer's estimated header retrieval throughput with -// the current measurement. -func (p *peerConnection) UpdateHeaderRate(delivered int, elapsed time.Duration) { - p.rates.Update(eth.BlockHeadersMsg, elapsed, delivered) -} - -// UpdateBodyRate updates the peer's estimated body retrieval throughput with the -// current measurement. -func (p *peerConnection) UpdateBodyRate(delivered int, elapsed time.Duration) { - p.rates.Update(eth.BlockBodiesMsg, elapsed, delivered) -} - -// UpdateReceiptRate updates the peer's estimated receipt retrieval throughput -// with the current measurement. -func (p *peerConnection) UpdateReceiptRate(delivered int, elapsed time.Duration) { - p.rates.Update(eth.ReceiptsMsg, elapsed, delivered) -} - -// HeaderCapacity retrieves the peer's header download allowance based on its -// previously discovered throughput. -func (p *peerConnection) HeaderCapacity(targetRTT time.Duration) int { - cap := p.rates.Capacity(eth.BlockHeadersMsg, targetRTT) - if cap > MaxHeaderFetch { - cap = MaxHeaderFetch - } - return cap -} - -// BodyCapacity retrieves the peer's body download allowance based on its -// previously discovered throughput. -func (p *peerConnection) BodyCapacity(targetRTT time.Duration) int { - cap := p.rates.Capacity(eth.BlockBodiesMsg, targetRTT) - if cap > MaxBlockFetch { - cap = MaxBlockFetch - } - return cap -} - -// ReceiptCapacity retrieves the peers receipt download allowance based on its -// previously discovered throughput. -func (p *peerConnection) ReceiptCapacity(targetRTT time.Duration) int { - cap := p.rates.Capacity(eth.ReceiptsMsg, targetRTT) - if cap > MaxReceiptFetch { - cap = MaxReceiptFetch - } - return cap -} - -// MarkLacking appends a new entity to the set of items (blocks, receipts, states) -// that a peer is known not to have (i.e. have been requested before). If the -// set reaches its maximum allowed capacity, items are randomly dropped off. -func (p *peerConnection) MarkLacking(hash common.Hash) { - p.lock.Lock() - defer p.lock.Unlock() - - for len(p.lacking) >= maxLackingHashes { - for drop := range p.lacking { - delete(p.lacking, drop) - break - } - } - p.lacking[hash] = struct{}{} -} - -// Lacks retrieves whether the hash of a blockchain item is on the peers lacking -// list (i.e. whether we know that the peer does not have it). -func (p *peerConnection) Lacks(hash common.Hash) bool { - p.lock.RLock() - defer p.lock.RUnlock() - - _, ok := p.lacking[hash] - return ok -} - -// peeringEvent is sent on the peer event feed when a remote peer connects or -// disconnects. -type peeringEvent struct { - peer *peerConnection - join bool -} - -// peerSet represents the collection of active peer participating in the chain -// download procedure. -type peerSet struct { - peers map[string]*peerConnection - rates *msgrate.Trackers // Set of rate trackers to give the sync a common beat - events event.Feed // Feed to publish peer lifecycle events on - - lock sync.RWMutex -} - -// newPeerSet creates a new peer set top track the active download sources. -func newPeerSet() *peerSet { - return &peerSet{ - peers: make(map[string]*peerConnection), - rates: msgrate.NewTrackers(log.New("proto", "eth")), - } -} - -// SubscribeEvents subscribes to peer arrival and departure events. -func (ps *peerSet) SubscribeEvents(ch chan<- *peeringEvent) event.Subscription { - return ps.events.Subscribe(ch) -} - -// Reset iterates over the current peer set, and resets each of the known peers -// to prepare for a next batch of block retrieval. -func (ps *peerSet) Reset() { - ps.lock.RLock() - defer ps.lock.RUnlock() - - for _, peer := range ps.peers { - peer.Reset() - } -} - -// Register injects a new peer into the working set, or returns an error if the -// peer is already known. -// -// The method also sets the starting throughput values of the new peer to the -// average of all existing peers, to give it a realistic chance of being used -// for data retrievals. -func (ps *peerSet) Register(p *peerConnection) error { - // Register the new peer with some meaningful defaults - ps.lock.Lock() - if _, ok := ps.peers[p.id]; ok { - ps.lock.Unlock() - return errAlreadyRegistered - } - p.rates = msgrate.NewTracker(ps.rates.MeanCapacities(), ps.rates.MedianRoundTrip()) - if err := ps.rates.Track(p.id, p.rates); err != nil { - ps.lock.Unlock() - return err - } - ps.peers[p.id] = p - ps.lock.Unlock() - - ps.events.Send(&peeringEvent{peer: p, join: true}) - return nil -} - -// Unregister removes a remote peer from the active set, disabling any further -// actions to/from that particular entity. -func (ps *peerSet) Unregister(id string) error { - ps.lock.Lock() - p, ok := ps.peers[id] - if !ok { - ps.lock.Unlock() - return errNotRegistered - } - delete(ps.peers, id) - ps.rates.Untrack(id) - ps.lock.Unlock() - - ps.events.Send(&peeringEvent{peer: p, join: false}) - return nil -} - -// Peer retrieves the registered peer with the given id. -func (ps *peerSet) Peer(id string) *peerConnection { - ps.lock.RLock() - defer ps.lock.RUnlock() - - return ps.peers[id] -} - -// Len returns if the current number of peers in the set. -func (ps *peerSet) Len() int { - ps.lock.RLock() - defer ps.lock.RUnlock() - - return len(ps.peers) -} - -// AllPeers retrieves a flat list of all the peers within the set. -func (ps *peerSet) AllPeers() []*peerConnection { - ps.lock.RLock() - defer ps.lock.RUnlock() - - list := make([]*peerConnection, 0, len(ps.peers)) - for _, p := range ps.peers { - list = append(list, p) - } - return list -} - -// peerCapacitySort implements sort.Interface. -// It sorts peer connections by capacity (descending). -type peerCapacitySort struct { - peers []*peerConnection - caps []int -} - -func (ps *peerCapacitySort) Len() int { - return len(ps.peers) -} - -func (ps *peerCapacitySort) Less(i, j int) bool { - return ps.caps[i] > ps.caps[j] -} - -func (ps *peerCapacitySort) Swap(i, j int) { - ps.peers[i], ps.peers[j] = ps.peers[j], ps.peers[i] - ps.caps[i], ps.caps[j] = ps.caps[j], ps.caps[i] -} diff --git a/builder/eth/downloader/queue.go b/builder/eth/downloader/queue.go deleted file mode 100644 index 6ff858d75..000000000 --- a/builder/eth/downloader/queue.go +++ /dev/null @@ -1,957 +0,0 @@ -// 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 . - -// Contains the block download scheduler to collect download tasks and schedule -// them in an ordered, and throttled way. - -package downloader - -import ( - "errors" - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/params" -) - -const ( - bodyType = uint(0) - receiptType = uint(1) -) - -var ( - blockCacheMaxItems = 8192 // Maximum number of blocks to cache before throttling the download - blockCacheInitialItems = 2048 // Initial number of blocks to start fetching, before we know the sizes of the blocks - blockCacheMemory = 256 * 1024 * 1024 // Maximum amount of memory to use for block caching - blockCacheSizeWeight = 0.1 // Multiplier to approximate the average block size based on past ones -) - -var ( - errNoFetchesPending = errors.New("no fetches pending") - errStaleDelivery = errors.New("stale delivery") -) - -// fetchRequest is a currently running data retrieval operation. -type fetchRequest struct { - Peer *peerConnection // Peer to which the request was sent - From uint64 // Requested chain element index (used for skeleton fills only) - Headers []*types.Header // Requested headers, sorted by request order - Time time.Time // Time when the request was made -} - -// fetchResult is a struct collecting partial results from data fetchers until -// all outstanding pieces complete and the result as a whole can be processed. -type fetchResult struct { - pending atomic.Int32 // Flag telling what deliveries are outstanding - - Header *types.Header - Uncles []*types.Header - Transactions types.Transactions - Receipts types.Receipts - Withdrawals types.Withdrawals -} - -func newFetchResult(header *types.Header, fastSync bool) *fetchResult { - item := &fetchResult{ - Header: header, - } - if !header.EmptyBody() { - item.pending.Store(item.pending.Load() | (1 << bodyType)) - } else if header.WithdrawalsHash != nil { - item.Withdrawals = make(types.Withdrawals, 0) - } - if fastSync && !header.EmptyReceipts() { - item.pending.Store(item.pending.Load() | (1 << receiptType)) - } - return item -} - -// SetBodyDone flags the body as finished. -func (f *fetchResult) SetBodyDone() { - if v := f.pending.Load(); (v & (1 << bodyType)) != 0 { - f.pending.Add(-1) - } -} - -// AllDone checks if item is done. -func (f *fetchResult) AllDone() bool { - return f.pending.Load() == 0 -} - -// SetReceiptsDone flags the receipts as finished. -func (f *fetchResult) SetReceiptsDone() { - if v := f.pending.Load(); (v & (1 << receiptType)) != 0 { - f.pending.Add(-2) - } -} - -// Done checks if the given type is done already -func (f *fetchResult) Done(kind uint) bool { - v := f.pending.Load() - return v&(1< 0 -} - -// InFlightReceipts retrieves whether there are receipt fetch requests currently -// in flight. -func (q *queue) InFlightReceipts() bool { - q.lock.Lock() - defer q.lock.Unlock() - - return len(q.receiptPendPool) > 0 -} - -// Idle returns if the queue is fully idle or has some data still inside. -func (q *queue) Idle() bool { - q.lock.Lock() - defer q.lock.Unlock() - - queued := q.blockTaskQueue.Size() + q.receiptTaskQueue.Size() - pending := len(q.blockPendPool) + len(q.receiptPendPool) - - return (queued + pending) == 0 -} - -// ScheduleSkeleton adds a batch of header retrieval tasks to the queue to fill -// up an already retrieved header skeleton. -func (q *queue) ScheduleSkeleton(from uint64, skeleton []*types.Header) { - q.lock.Lock() - defer q.lock.Unlock() - - // No skeleton retrieval can be in progress, fail hard if so (huge implementation bug) - if q.headerResults != nil { - panic("skeleton assembly already in progress") - } - // Schedule all the header retrieval tasks for the skeleton assembly - q.headerTaskPool = make(map[uint64]*types.Header) - q.headerTaskQueue = prque.New[int64, uint64](nil) - q.headerPeerMiss = make(map[string]map[uint64]struct{}) // Reset availability to correct invalid chains - q.headerResults = make([]*types.Header, len(skeleton)*MaxHeaderFetch) - q.headerHashes = make([]common.Hash, len(skeleton)*MaxHeaderFetch) - q.headerProced = 0 - q.headerOffset = from - q.headerContCh = make(chan bool, 1) - - for i, header := range skeleton { - index := from + uint64(i*MaxHeaderFetch) - - q.headerTaskPool[index] = header - q.headerTaskQueue.Push(index, -int64(index)) - } -} - -// RetrieveHeaders retrieves the header chain assemble based on the scheduled -// skeleton. -func (q *queue) RetrieveHeaders() ([]*types.Header, []common.Hash, int) { - q.lock.Lock() - defer q.lock.Unlock() - - headers, hashes, proced := q.headerResults, q.headerHashes, q.headerProced - q.headerResults, q.headerHashes, q.headerProced = nil, nil, 0 - - return headers, hashes, proced -} - -// Schedule adds a set of headers for the download queue for scheduling, returning -// the new headers encountered. -func (q *queue) Schedule(headers []*types.Header, hashes []common.Hash, from uint64) []*types.Header { - q.lock.Lock() - defer q.lock.Unlock() - - // Insert all the headers prioritised by the contained block number - inserts := make([]*types.Header, 0, len(headers)) - for i, header := range headers { - // Make sure chain order is honoured and preserved throughout - hash := hashes[i] - if header.Number == nil || header.Number.Uint64() != from { - log.Warn("Header broke chain ordering", "number", header.Number, "hash", hash, "expected", from) - break - } - if q.headerHead != (common.Hash{}) && q.headerHead != header.ParentHash { - log.Warn("Header broke chain ancestry", "number", header.Number, "hash", hash) - break - } - // Make sure no duplicate requests are executed - // We cannot skip this, even if the block is empty, since this is - // what triggers the fetchResult creation. - if _, ok := q.blockTaskPool[hash]; ok { - log.Warn("Header already scheduled for block fetch", "number", header.Number, "hash", hash) - } else { - q.blockTaskPool[hash] = header - q.blockTaskQueue.Push(header, -int64(header.Number.Uint64())) - } - // Queue for receipt retrieval - if q.mode == SnapSync && !header.EmptyReceipts() { - if _, ok := q.receiptTaskPool[hash]; ok { - log.Warn("Header already scheduled for receipt fetch", "number", header.Number, "hash", hash) - } else { - q.receiptTaskPool[hash] = header - q.receiptTaskQueue.Push(header, -int64(header.Number.Uint64())) - } - } - inserts = append(inserts, header) - q.headerHead = hash - from++ - } - return inserts -} - -// Results retrieves and permanently removes a batch of fetch results from -// the cache. the result slice will be empty if the queue has been closed. -// Results can be called concurrently with Deliver and Schedule, -// but assumes that there are not two simultaneous callers to Results -func (q *queue) Results(block bool) []*fetchResult { - // Abort early if there are no items and non-blocking requested - if !block && !q.resultCache.HasCompletedItems() { - return nil - } - closed := false - for !closed && !q.resultCache.HasCompletedItems() { - // In order to wait on 'active', we need to obtain the lock. - // That may take a while, if someone is delivering at the same - // time, so after obtaining the lock, we check again if there - // are any results to fetch. - // Also, in-between we ask for the lock and the lock is obtained, - // someone can have closed the queue. In that case, we should - // return the available results and stop blocking - q.lock.Lock() - if q.resultCache.HasCompletedItems() || q.closed { - q.lock.Unlock() - break - } - // No items available, and not closed - q.active.Wait() - closed = q.closed - q.lock.Unlock() - } - // Regardless if closed or not, we can still deliver whatever we have - results := q.resultCache.GetCompleted(maxResultsProcess) - for _, result := range results { - // Recalculate the result item weights to prevent memory exhaustion - size := result.Header.Size() - for _, uncle := range result.Uncles { - size += uncle.Size() - } - for _, receipt := range result.Receipts { - size += receipt.Size() - } - for _, tx := range result.Transactions { - size += common.StorageSize(tx.Size()) - } - q.resultSize = common.StorageSize(blockCacheSizeWeight)*size + - (1-common.StorageSize(blockCacheSizeWeight))*q.resultSize - } - // Using the newly calibrated resultsize, figure out the new throttle limit - // on the result cache - throttleThreshold := uint64((common.StorageSize(blockCacheMemory) + q.resultSize - 1) / q.resultSize) - throttleThreshold = q.resultCache.SetThrottleThreshold(throttleThreshold) - - // With results removed from the cache, wake throttled fetchers - for _, ch := range []chan bool{q.blockWakeCh, q.receiptWakeCh} { - select { - case ch <- true: - default: - } - } - // Log some info at certain times - if time.Since(q.logTime) >= 60*time.Second { - q.logTime = time.Now() - - info := q.Stats() - info = append(info, "throttle", throttleThreshold) - log.Debug("Downloader queue stats", info...) - } - return results -} - -func (q *queue) Stats() []interface{} { - q.lock.RLock() - defer q.lock.RUnlock() - - return q.stats() -} - -func (q *queue) stats() []interface{} { - return []interface{}{ - "receiptTasks", q.receiptTaskQueue.Size(), - "blockTasks", q.blockTaskQueue.Size(), - "itemSize", q.resultSize, - } -} - -// ReserveHeaders reserves a set of headers for the given peer, skipping any -// previously failed batches. -func (q *queue) ReserveHeaders(p *peerConnection, count int) *fetchRequest { - q.lock.Lock() - defer q.lock.Unlock() - - // Short circuit if the peer's already downloading something (sanity check to - // not corrupt state) - if _, ok := q.headerPendPool[p.id]; ok { - return nil - } - // Retrieve a batch of hashes, skipping previously failed ones - send, skip := uint64(0), []uint64{} - for send == 0 && !q.headerTaskQueue.Empty() { - from, _ := q.headerTaskQueue.Pop() - if q.headerPeerMiss[p.id] != nil { - if _, ok := q.headerPeerMiss[p.id][from]; ok { - skip = append(skip, from) - continue - } - } - send = from - } - // Merge all the skipped batches back - for _, from := range skip { - q.headerTaskQueue.Push(from, -int64(from)) - } - // Assemble and return the block download request - if send == 0 { - return nil - } - request := &fetchRequest{ - Peer: p, - From: send, - Time: time.Now(), - } - q.headerPendPool[p.id] = request - return request -} - -// ReserveBodies reserves a set of body fetches for the given peer, skipping any -// previously failed downloads. Beside the next batch of needed fetches, it also -// returns a flag whether empty blocks were queued requiring processing. -func (q *queue) ReserveBodies(p *peerConnection, count int) (*fetchRequest, bool, bool) { - q.lock.Lock() - defer q.lock.Unlock() - - return q.reserveHeaders(p, count, q.blockTaskPool, q.blockTaskQueue, q.blockPendPool, bodyType) -} - -// ReserveReceipts reserves a set of receipt fetches for the given peer, skipping -// any previously failed downloads. Beside the next batch of needed fetches, it -// also returns a flag whether empty receipts were queued requiring importing. -func (q *queue) ReserveReceipts(p *peerConnection, count int) (*fetchRequest, bool, bool) { - q.lock.Lock() - defer q.lock.Unlock() - - return q.reserveHeaders(p, count, q.receiptTaskPool, q.receiptTaskQueue, q.receiptPendPool, receiptType) -} - -// reserveHeaders reserves a set of data download operations for a given peer, -// skipping any previously failed ones. This method is a generic version used -// by the individual special reservation functions. -// -// Note, this method expects the queue lock to be already held for writing. The -// reason the lock is not obtained in here is because the parameters already need -// to access the queue, so they already need a lock anyway. -// -// Returns: -// -// item - the fetchRequest -// progress - whether any progress was made -// throttle - if the caller should throttle for a while -func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common.Hash]*types.Header, taskQueue *prque.Prque[int64, *types.Header], - pendPool map[string]*fetchRequest, kind uint) (*fetchRequest, bool, bool) { - // Short circuit if the pool has been depleted, or if the peer's already - // downloading something (sanity check not to corrupt state) - if taskQueue.Empty() { - return nil, false, true - } - if _, ok := pendPool[p.id]; ok { - return nil, false, false - } - // Retrieve a batch of tasks, skipping previously failed ones - send := make([]*types.Header, 0, count) - skip := make([]*types.Header, 0) - progress := false - throttled := false - for proc := 0; len(send) < count && !taskQueue.Empty(); proc++ { - // the task queue will pop items in order, so the highest prio block - // is also the lowest block number. - header, _ := taskQueue.Peek() - - // we can ask the resultcache if this header is within the - // "prioritized" segment of blocks. If it is not, we need to throttle - - stale, throttle, item, err := q.resultCache.AddFetch(header, q.mode == SnapSync) - if stale { - // Don't put back in the task queue, this item has already been - // delivered upstream - taskQueue.PopItem() - progress = true - delete(taskPool, header.Hash()) - proc = proc - 1 - log.Error("Fetch reservation already delivered", "number", header.Number.Uint64()) - continue - } - if throttle { - // There are no resultslots available. Leave it in the task queue - // However, if there are any left as 'skipped', we should not tell - // the caller to throttle, since we still want some other - // peer to fetch those for us - throttled = len(skip) == 0 - break - } - if err != nil { - // this most definitely should _not_ happen - log.Warn("Failed to reserve headers", "err", err) - // There are no resultslots available. Leave it in the task queue - break - } - if item.Done(kind) { - // If it's a noop, we can skip this task - delete(taskPool, header.Hash()) - taskQueue.PopItem() - proc = proc - 1 - progress = true - continue - } - // Remove it from the task queue - taskQueue.PopItem() - // Otherwise unless the peer is known not to have the data, add to the retrieve list - if p.Lacks(header.Hash()) { - skip = append(skip, header) - } else { - send = append(send, header) - } - } - // Merge all the skipped headers back - for _, header := range skip { - taskQueue.Push(header, -int64(header.Number.Uint64())) - } - if q.resultCache.HasCompletedItems() { - // Wake Results, resultCache was modified - q.active.Signal() - } - // Assemble and return the block download request - if len(send) == 0 { - return nil, progress, throttled - } - request := &fetchRequest{ - Peer: p, - Headers: send, - Time: time.Now(), - } - pendPool[p.id] = request - return request, progress, throttled -} - -// Revoke cancels all pending requests belonging to a given peer. This method is -// meant to be called during a peer drop to quickly reassign owned data fetches -// to remaining nodes. -func (q *queue) Revoke(peerID string) { - q.lock.Lock() - defer q.lock.Unlock() - - if request, ok := q.headerPendPool[peerID]; ok { - q.headerTaskQueue.Push(request.From, -int64(request.From)) - delete(q.headerPendPool, peerID) - } - if request, ok := q.blockPendPool[peerID]; ok { - for _, header := range request.Headers { - q.blockTaskQueue.Push(header, -int64(header.Number.Uint64())) - } - delete(q.blockPendPool, peerID) - } - if request, ok := q.receiptPendPool[peerID]; ok { - for _, header := range request.Headers { - q.receiptTaskQueue.Push(header, -int64(header.Number.Uint64())) - } - delete(q.receiptPendPool, peerID) - } -} - -// ExpireHeaders cancels a request that timed out and moves the pending fetch -// task back into the queue for rescheduling. -func (q *queue) ExpireHeaders(peer string) int { - q.lock.Lock() - defer q.lock.Unlock() - - headerTimeoutMeter.Mark(1) - return q.expire(peer, q.headerPendPool, q.headerTaskQueue) -} - -// ExpireBodies checks for in flight block body requests that exceeded a timeout -// allowance, canceling them and returning the responsible peers for penalisation. -func (q *queue) ExpireBodies(peer string) int { - q.lock.Lock() - defer q.lock.Unlock() - - bodyTimeoutMeter.Mark(1) - return q.expire(peer, q.blockPendPool, q.blockTaskQueue) -} - -// ExpireReceipts checks for in flight receipt requests that exceeded a timeout -// allowance, canceling them and returning the responsible peers for penalisation. -func (q *queue) ExpireReceipts(peer string) int { - q.lock.Lock() - defer q.lock.Unlock() - - receiptTimeoutMeter.Mark(1) - return q.expire(peer, q.receiptPendPool, q.receiptTaskQueue) -} - -// expire is the generic check that moves a specific expired task from a pending -// pool back into a task pool. The syntax on the passed taskQueue is a bit weird -// as we would need a generic expire method to handle both types, but that is not -// supported at the moment at least (Go 1.19). -// -// Note, this method expects the queue lock to be already held. The reason the -// lock is not obtained in here is that the parameters already need to access -// the queue, so they already need a lock anyway. -func (q *queue) expire(peer string, pendPool map[string]*fetchRequest, taskQueue interface{}) int { - // Retrieve the request being expired and log an error if it's non-existent, - // as there's no order of events that should lead to such expirations. - req := pendPool[peer] - if req == nil { - log.Error("Expired request does not exist", "peer", peer) - return 0 - } - delete(pendPool, peer) - - // Return any non-satisfied requests to the pool - if req.From > 0 { - taskQueue.(*prque.Prque[int64, uint64]).Push(req.From, -int64(req.From)) - } - for _, header := range req.Headers { - taskQueue.(*prque.Prque[int64, *types.Header]).Push(header, -int64(header.Number.Uint64())) - } - return len(req.Headers) -} - -// DeliverHeaders injects a header retrieval response into the header results -// cache. This method either accepts all headers it received, or none of them -// if they do not map correctly to the skeleton. -// -// If the headers are accepted, the method makes an attempt to deliver the set -// of ready headers to the processor to keep the pipeline full. However, it will -// not block to prevent stalling other pending deliveries. -func (q *queue) DeliverHeaders(id string, headers []*types.Header, hashes []common.Hash, headerProcCh chan *headerTask) (int, error) { - q.lock.Lock() - defer q.lock.Unlock() - - var logger log.Logger - if len(id) < 16 { - // Tests use short IDs, don't choke on them - logger = log.New("peer", id) - } else { - logger = log.New("peer", id[:16]) - } - // Short circuit if the data was never requested - request := q.headerPendPool[id] - if request == nil { - headerDropMeter.Mark(int64(len(headers))) - return 0, errNoFetchesPending - } - delete(q.headerPendPool, id) - - headerReqTimer.UpdateSince(request.Time) - headerInMeter.Mark(int64(len(headers))) - - // Ensure headers can be mapped onto the skeleton chain - target := q.headerTaskPool[request.From].Hash() - - accepted := len(headers) == MaxHeaderFetch - if accepted { - if headers[0].Number.Uint64() != request.From { - logger.Trace("First header broke chain ordering", "number", headers[0].Number, "hash", hashes[0], "expected", request.From) - accepted = false - } else if hashes[len(headers)-1] != target { - logger.Trace("Last header broke skeleton structure ", "number", headers[len(headers)-1].Number, "hash", hashes[len(headers)-1], "expected", target) - accepted = false - } - } - if accepted { - parentHash := hashes[0] - for i, header := range headers[1:] { - hash := hashes[i+1] - if want := request.From + 1 + uint64(i); header.Number.Uint64() != want { - logger.Warn("Header broke chain ordering", "number", header.Number, "hash", hash, "expected", want) - accepted = false - break - } - if parentHash != header.ParentHash { - logger.Warn("Header broke chain ancestry", "number", header.Number, "hash", hash) - accepted = false - break - } - // Set-up parent hash for next round - parentHash = hash - } - } - // If the batch of headers wasn't accepted, mark as unavailable - if !accepted { - logger.Trace("Skeleton filling not accepted", "from", request.From) - headerDropMeter.Mark(int64(len(headers))) - - miss := q.headerPeerMiss[id] - if miss == nil { - q.headerPeerMiss[id] = make(map[uint64]struct{}) - miss = q.headerPeerMiss[id] - } - miss[request.From] = struct{}{} - - q.headerTaskQueue.Push(request.From, -int64(request.From)) - return 0, errors.New("delivery not accepted") - } - // Clean up a successful fetch and try to deliver any sub-results - copy(q.headerResults[request.From-q.headerOffset:], headers) - copy(q.headerHashes[request.From-q.headerOffset:], hashes) - - delete(q.headerTaskPool, request.From) - - ready := 0 - for q.headerProced+ready < len(q.headerResults) && q.headerResults[q.headerProced+ready] != nil { - ready += MaxHeaderFetch - } - if ready > 0 { - // Headers are ready for delivery, gather them and push forward (non blocking) - processHeaders := make([]*types.Header, ready) - copy(processHeaders, q.headerResults[q.headerProced:q.headerProced+ready]) - - processHashes := make([]common.Hash, ready) - copy(processHashes, q.headerHashes[q.headerProced:q.headerProced+ready]) - - select { - case headerProcCh <- &headerTask{ - headers: processHeaders, - hashes: processHashes, - }: - logger.Trace("Pre-scheduled new headers", "count", len(processHeaders), "from", processHeaders[0].Number) - q.headerProced += len(processHeaders) - default: - } - } - // Check for termination and return - if len(q.headerTaskPool) == 0 { - q.headerContCh <- false - } - return len(headers), nil -} - -// DeliverBodies injects a block body retrieval response into the results queue. -// The method returns the number of blocks bodies accepted from the delivery and -// also wakes any threads waiting for data delivery. -func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListHashes []common.Hash, - uncleLists [][]*types.Header, uncleListHashes []common.Hash, - withdrawalLists [][]*types.Withdrawal, withdrawalListHashes []common.Hash) (int, error) { - q.lock.Lock() - defer q.lock.Unlock() - - validate := func(index int, header *types.Header) error { - if txListHashes[index] != header.TxHash { - return errInvalidBody - } - if uncleListHashes[index] != header.UncleHash { - return errInvalidBody - } - if header.WithdrawalsHash == nil { - // nil hash means that withdrawals should not be present in body - if withdrawalLists[index] != nil { - return errInvalidBody - } - } else { // non-nil hash: body must have withdrawals - if withdrawalLists[index] == nil { - return errInvalidBody - } - if withdrawalListHashes[index] != *header.WithdrawalsHash { - return errInvalidBody - } - } - // Blocks must have a number of blobs corresponding to the header gas usage, - // and zero before the Cancun hardfork. - var blobs int - for _, tx := range txLists[index] { - // Count the number of blobs to validate against the header's blobGasUsed - blobs += len(tx.BlobHashes()) - - // Validate the data blobs individually too - if tx.Type() == types.BlobTxType { - if len(tx.BlobHashes()) == 0 { - return errInvalidBody - } - for _, hash := range tx.BlobHashes() { - if !kzg4844.IsValidVersionedHash(hash[:]) { - return errInvalidBody - } - } - if tx.BlobTxSidecar() != nil { - return errInvalidBody - } - } - } - if header.BlobGasUsed != nil { - if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated - return errInvalidBody - } - } else { - if blobs != 0 { - return errInvalidBody - } - } - return nil - } - - reconstruct := func(index int, result *fetchResult) { - result.Transactions = txLists[index] - result.Uncles = uncleLists[index] - result.Withdrawals = withdrawalLists[index] - result.SetBodyDone() - } - return q.deliver(id, q.blockTaskPool, q.blockTaskQueue, q.blockPendPool, - bodyReqTimer, bodyInMeter, bodyDropMeter, len(txLists), validate, reconstruct) -} - -// DeliverReceipts injects a receipt retrieval response into the results queue. -// The method returns the number of transaction receipts accepted from the delivery -// and also wakes any threads waiting for data delivery. -func (q *queue) DeliverReceipts(id string, receiptList [][]*types.Receipt, receiptListHashes []common.Hash) (int, error) { - q.lock.Lock() - defer q.lock.Unlock() - - validate := func(index int, header *types.Header) error { - if receiptListHashes[index] != header.ReceiptHash { - return errInvalidReceipt - } - return nil - } - reconstruct := func(index int, result *fetchResult) { - result.Receipts = receiptList[index] - result.SetReceiptsDone() - } - return q.deliver(id, q.receiptTaskPool, q.receiptTaskQueue, q.receiptPendPool, - receiptReqTimer, receiptInMeter, receiptDropMeter, len(receiptList), validate, reconstruct) -} - -// deliver injects a data retrieval response into the results queue. -// -// Note, this method expects the queue lock to be already held for writing. The -// reason this lock is not obtained in here is because the parameters already need -// to access the queue, so they already need a lock anyway. -func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, - taskQueue *prque.Prque[int64, *types.Header], pendPool map[string]*fetchRequest, - reqTimer metrics.Timer, resInMeter metrics.Meter, resDropMeter metrics.Meter, - results int, validate func(index int, header *types.Header) error, - reconstruct func(index int, result *fetchResult)) (int, error) { - // Short circuit if the data was never requested - request := pendPool[id] - if request == nil { - resDropMeter.Mark(int64(results)) - return 0, errNoFetchesPending - } - delete(pendPool, id) - - reqTimer.UpdateSince(request.Time) - resInMeter.Mark(int64(results)) - - // If no data items were retrieved, mark them as unavailable for the origin peer - if results == 0 { - for _, header := range request.Headers { - request.Peer.MarkLacking(header.Hash()) - } - } - // Assemble each of the results with their headers and retrieved data parts - var ( - accepted int - failure error - i int - hashes []common.Hash - ) - for _, header := range request.Headers { - // Short circuit assembly if no more fetch results are found - if i >= results { - break - } - // Validate the fields - if err := validate(i, header); err != nil { - failure = err - break - } - hashes = append(hashes, header.Hash()) - i++ - } - - for _, header := range request.Headers[:i] { - if res, stale, err := q.resultCache.GetDeliverySlot(header.Number.Uint64()); err == nil && !stale { - reconstruct(accepted, res) - } else { - // else: between here and above, some other peer filled this result, - // or it was indeed a no-op. This should not happen, but if it does it's - // not something to panic about - log.Error("Delivery stale", "stale", stale, "number", header.Number.Uint64(), "err", err) - failure = errStaleDelivery - } - // Clean up a successful fetch - delete(taskPool, hashes[accepted]) - accepted++ - } - resDropMeter.Mark(int64(results - accepted)) - - // Return all failed or missing fetches to the queue - for _, header := range request.Headers[accepted:] { - taskQueue.Push(header, -int64(header.Number.Uint64())) - } - // Wake up Results - if accepted > 0 { - q.active.Signal() - } - if failure == nil { - return accepted, nil - } - // If none of the data was good, it's a stale delivery - if accepted > 0 { - return accepted, fmt.Errorf("partial failure: %v", failure) - } - return accepted, fmt.Errorf("%w: %v", failure, errStaleDelivery) -} - -// Prepare configures the result cache to allow accepting and caching inbound -// fetch results. -func (q *queue) Prepare(offset uint64, mode SyncMode) { - q.lock.Lock() - defer q.lock.Unlock() - - // Prepare the queue for sync results - q.resultCache.Prepare(offset) - q.mode = mode -} diff --git a/builder/eth/downloader/queue_test.go b/builder/eth/downloader/queue_test.go deleted file mode 100644 index 50b9031a2..000000000 --- a/builder/eth/downloader/queue_test.go +++ /dev/null @@ -1,474 +0,0 @@ -// 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 downloader - -import ( - "fmt" - "math/big" - "math/rand" - "os" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "golang.org/x/exp/slog" -) - -// makeChain creates a chain of n blocks starting at and including parent. -// the returned hash chain is ordered head->parent. In addition, every 3rd block -// contains a transaction and every 5th an uncle to allow testing correct block -// reassembly. -func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Block, []types.Receipts) { - blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), testDB, n, func(i int, block *core.BlockGen) { - block.SetCoinbase(common.Address{seed}) - // Add one tx to every secondblock - if !empty && i%2 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) - tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) - if err != nil { - panic(err) - } - block.AddTx(tx) - } - }) - return blocks, receipts -} - -type chainData struct { - blocks []*types.Block - offset int -} - -var chain *chainData -var emptyChain *chainData - -func init() { - // Create a chain of blocks to import - targetBlocks := 128 - blocks, _ := makeChain(targetBlocks, 0, testGenesis, false) - chain = &chainData{blocks, 0} - - blocks, _ = makeChain(targetBlocks, 0, testGenesis, true) - emptyChain = &chainData{blocks, 0} -} - -func (chain *chainData) headers() []*types.Header { - hdrs := make([]*types.Header, len(chain.blocks)) - for i, b := range chain.blocks { - hdrs[i] = b.Header() - } - return hdrs -} - -func (chain *chainData) Len() int { - return len(chain.blocks) -} - -func dummyPeer(id string) *peerConnection { - p := &peerConnection{ - id: id, - lacking: make(map[common.Hash]struct{}), - } - return p -} - -func TestBasics(t *testing.T) { - numOfBlocks := len(emptyChain.blocks) - numOfReceipts := len(emptyChain.blocks) / 2 - - q := newQueue(10, 10) - if !q.Idle() { - t.Errorf("new queue should be idle") - } - q.Prepare(1, SnapSync) - if res := q.Results(false); len(res) != 0 { - t.Fatal("new queue should have 0 results") - } - - // Schedule a batch of headers - headers := chain.headers() - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - q.Schedule(headers, hashes, 1) - if q.Idle() { - t.Errorf("queue should not be idle") - } - if got, exp := q.PendingBodies(), chain.Len(); got != exp { - t.Errorf("wrong pending block count, got %d, exp %d", got, exp) - } - // Only non-empty receipts get added to task-queue - if got, exp := q.PendingReceipts(), 64; got != exp { - t.Errorf("wrong pending receipt count, got %d, exp %d", got, exp) - } - // Items are now queued for downloading, next step is that we tell the - // queue that a certain peer will deliver them for us - { - peer := dummyPeer("peer-1") - fetchReq, _, throttle := q.ReserveBodies(peer, 50) - if !throttle { - // queue size is only 10, so throttling should occur - t.Fatal("should throttle") - } - // But we should still get the first things to fetch - if got, exp := len(fetchReq.Headers), 5; got != exp { - t.Fatalf("expected %d requests, got %d", exp, got) - } - if got, exp := fetchReq.Headers[0].Number.Uint64(), uint64(1); got != exp { - t.Fatalf("expected header %d, got %d", exp, got) - } - } - if exp, got := q.blockTaskQueue.Size(), numOfBlocks-10; exp != got { - t.Errorf("expected block task queue to be %d, got %d", exp, got) - } - if exp, got := q.receiptTaskQueue.Size(), numOfReceipts; exp != got { - t.Errorf("expected receipt task queue to be %d, got %d", exp, got) - } - { - peer := dummyPeer("peer-2") - fetchReq, _, throttle := q.ReserveBodies(peer, 50) - - // The second peer should hit throttling - if !throttle { - t.Fatalf("should throttle") - } - // And not get any fetches at all, since it was throttled to begin with - if fetchReq != nil { - t.Fatalf("should have no fetches, got %d", len(fetchReq.Headers)) - } - } - if exp, got := q.blockTaskQueue.Size(), numOfBlocks-10; exp != got { - t.Errorf("expected block task queue to be %d, got %d", exp, got) - } - if exp, got := q.receiptTaskQueue.Size(), numOfReceipts; exp != got { - t.Errorf("expected receipt task queue to be %d, got %d", exp, got) - } - { - // The receipt delivering peer should not be affected - // by the throttling of body deliveries - peer := dummyPeer("peer-3") - fetchReq, _, throttle := q.ReserveReceipts(peer, 50) - if !throttle { - // queue size is only 10, so throttling should occur - t.Fatal("should throttle") - } - // But we should still get the first things to fetch - if got, exp := len(fetchReq.Headers), 5; got != exp { - t.Fatalf("expected %d requests, got %d", exp, got) - } - if got, exp := fetchReq.Headers[0].Number.Uint64(), uint64(1); got != exp { - t.Fatalf("expected header %d, got %d", exp, got) - } - } - if exp, got := q.blockTaskQueue.Size(), numOfBlocks-10; exp != got { - t.Errorf("expected block task queue to be %d, got %d", exp, got) - } - if exp, got := q.receiptTaskQueue.Size(), numOfReceipts-5; exp != got { - t.Errorf("expected receipt task queue to be %d, got %d", exp, got) - } - if got, exp := q.resultCache.countCompleted(), 0; got != exp { - t.Errorf("wrong processable count, got %d, exp %d", got, exp) - } -} - -func TestEmptyBlocks(t *testing.T) { - numOfBlocks := len(emptyChain.blocks) - - q := newQueue(10, 10) - - q.Prepare(1, SnapSync) - - // Schedule a batch of headers - headers := emptyChain.headers() - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - q.Schedule(headers, hashes, 1) - if q.Idle() { - t.Errorf("queue should not be idle") - } - if got, exp := q.PendingBodies(), len(emptyChain.blocks); got != exp { - t.Errorf("wrong pending block count, got %d, exp %d", got, exp) - } - if got, exp := q.PendingReceipts(), 0; got != exp { - t.Errorf("wrong pending receipt count, got %d, exp %d", got, exp) - } - // They won't be processable, because the fetchresults haven't been - // created yet - if got, exp := q.resultCache.countCompleted(), 0; got != exp { - t.Errorf("wrong processable count, got %d, exp %d", got, exp) - } - - // Items are now queued for downloading, next step is that we tell the - // queue that a certain peer will deliver them for us - // That should trigger all of them to suddenly become 'done' - { - // Reserve blocks - peer := dummyPeer("peer-1") - fetchReq, _, _ := q.ReserveBodies(peer, 50) - - // there should be nothing to fetch, blocks are empty - if fetchReq != nil { - t.Fatal("there should be no body fetch tasks remaining") - } - } - if q.blockTaskQueue.Size() != numOfBlocks-10 { - t.Errorf("expected block task queue to be %d, got %d", numOfBlocks-10, q.blockTaskQueue.Size()) - } - if q.receiptTaskQueue.Size() != 0 { - t.Errorf("expected receipt task queue to be %d, got %d", 0, q.receiptTaskQueue.Size()) - } - { - peer := dummyPeer("peer-3") - fetchReq, _, _ := q.ReserveReceipts(peer, 50) - - // there should be nothing to fetch, blocks are empty - if fetchReq != nil { - t.Fatal("there should be no receipt fetch tasks remaining") - } - } - if q.blockTaskQueue.Size() != numOfBlocks-10 { - t.Errorf("expected block task queue to be %d, got %d", numOfBlocks-10, q.blockTaskQueue.Size()) - } - if q.receiptTaskQueue.Size() != 0 { - t.Errorf("expected receipt task queue to be %d, got %d", 0, q.receiptTaskQueue.Size()) - } - if got, exp := q.resultCache.countCompleted(), 10; got != exp { - t.Errorf("wrong processable count, got %d, exp %d", got, exp) - } -} - -// XTestDelivery does some more extensive testing of events that happen, -// blocks that become known and peers that make reservations and deliveries. -// disabled since it's not really a unit-test, but can be executed to test -// some more advanced scenarios -func XTestDelivery(t *testing.T) { - // the outside network, holding blocks - blo, rec := makeChain(128, 0, testGenesis, false) - world := newNetwork() - world.receipts = rec - world.chain = blo - world.progress(10) - if false { - log.SetDefault(log.NewLogger(slog.NewTextHandler(os.Stdout, nil))) - } - q := newQueue(10, 10) - var wg sync.WaitGroup - q.Prepare(1, SnapSync) - wg.Add(1) - go func() { - // deliver headers - defer wg.Done() - c := 1 - for { - //fmt.Printf("getting headers from %d\n", c) - headers := world.headers(c) - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - l := len(headers) - //fmt.Printf("scheduling %d headers, first %d last %d\n", - // l, headers[0].Number.Uint64(), headers[len(headers)-1].Number.Uint64()) - q.Schedule(headers, hashes, uint64(c)) - c += l - } - }() - wg.Add(1) - go func() { - // collect results - defer wg.Done() - tot := 0 - for { - res := q.Results(true) - tot += len(res) - fmt.Printf("got %d results, %d tot\n", len(res), tot) - // Now we can forget about these - world.forget(res[len(res)-1].Header.Number.Uint64()) - } - }() - wg.Add(1) - go func() { - defer wg.Done() - // reserve body fetch - i := 4 - for { - peer := dummyPeer(fmt.Sprintf("peer-%d", i)) - f, _, _ := q.ReserveBodies(peer, rand.Intn(30)) - if f != nil { - var ( - emptyList []*types.Header - txset [][]*types.Transaction - uncleset [][]*types.Header - ) - numToSkip := rand.Intn(len(f.Headers)) - for _, hdr := range f.Headers[0 : len(f.Headers)-numToSkip] { - txset = append(txset, world.getTransactions(hdr.Number.Uint64())) - uncleset = append(uncleset, emptyList) - } - var ( - txsHashes = make([]common.Hash, len(txset)) - uncleHashes = make([]common.Hash, len(uncleset)) - ) - hasher := trie.NewStackTrie(nil) - for i, txs := range txset { - txsHashes[i] = types.DeriveSha(types.Transactions(txs), hasher) - } - for i, uncles := range uncleset { - uncleHashes[i] = types.CalcUncleHash(uncles) - } - time.Sleep(100 * time.Millisecond) - _, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil) - if err != nil { - fmt.Printf("delivered %d bodies %v\n", len(txset), err) - } - } else { - i++ - time.Sleep(200 * time.Millisecond) - } - } - }() - go func() { - defer wg.Done() - // reserve receiptfetch - peer := dummyPeer("peer-3") - for { - f, _, _ := q.ReserveReceipts(peer, rand.Intn(50)) - if f != nil { - var rcs [][]*types.Receipt - for _, hdr := range f.Headers { - rcs = append(rcs, world.getReceipts(hdr.Number.Uint64())) - } - hasher := trie.NewStackTrie(nil) - hashes := make([]common.Hash, len(rcs)) - for i, receipt := range rcs { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) - } - _, err := q.DeliverReceipts(peer.id, rcs, hashes) - if err != nil { - fmt.Printf("delivered %d receipts %v\n", len(rcs), err) - } - time.Sleep(100 * time.Millisecond) - } else { - time.Sleep(200 * time.Millisecond) - } - } - }() - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < 50; i++ { - time.Sleep(300 * time.Millisecond) - //world.tick() - //fmt.Printf("trying to progress\n") - world.progress(rand.Intn(100)) - } - for i := 0; i < 50; i++ { - time.Sleep(2990 * time.Millisecond) - } - }() - wg.Add(1) - go func() { - defer wg.Done() - for { - time.Sleep(990 * time.Millisecond) - fmt.Printf("world block tip is %d\n", - world.chain[len(world.chain)-1].Header().Number.Uint64()) - fmt.Println(q.Stats()) - } - }() - wg.Wait() -} - -func newNetwork() *network { - var l sync.RWMutex - return &network{ - cond: sync.NewCond(&l), - offset: 1, // block 1 is at blocks[0] - } -} - -// represents the network -type network struct { - offset int - chain []*types.Block - receipts []types.Receipts - lock sync.RWMutex - cond *sync.Cond -} - -func (n *network) getTransactions(blocknum uint64) types.Transactions { - index := blocknum - uint64(n.offset) - return n.chain[index].Transactions() -} -func (n *network) getReceipts(blocknum uint64) types.Receipts { - index := blocknum - uint64(n.offset) - if got := n.chain[index].Header().Number.Uint64(); got != blocknum { - fmt.Printf("Err, got %d exp %d\n", got, blocknum) - panic("sd") - } - return n.receipts[index] -} - -func (n *network) forget(blocknum uint64) { - index := blocknum - uint64(n.offset) - n.chain = n.chain[index:] - n.receipts = n.receipts[index:] - n.offset = int(blocknum) -} -func (n *network) progress(numBlocks int) { - n.lock.Lock() - defer n.lock.Unlock() - //fmt.Printf("progressing...\n") - newBlocks, newR := makeChain(numBlocks, 0, n.chain[len(n.chain)-1], false) - n.chain = append(n.chain, newBlocks...) - n.receipts = append(n.receipts, newR...) - n.cond.Broadcast() -} - -func (n *network) headers(from int) []*types.Header { - numHeaders := 128 - var hdrs []*types.Header - index := from - n.offset - - for index >= len(n.chain) { - // wait for progress - n.cond.L.Lock() - //fmt.Printf("header going into wait\n") - n.cond.Wait() - index = from - n.offset - n.cond.L.Unlock() - } - n.lock.RLock() - defer n.lock.RUnlock() - for i, b := range n.chain[index:] { - hdrs = append(hdrs, b.Header()) - if i >= numHeaders { - break - } - } - return hdrs -} diff --git a/builder/eth/downloader/resultstore.go b/builder/eth/downloader/resultstore.go deleted file mode 100644 index e4323c04e..000000000 --- a/builder/eth/downloader/resultstore.go +++ /dev/null @@ -1,195 +0,0 @@ -// 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 downloader - -import ( - "fmt" - "sync" - "sync/atomic" - - "github.com/ethereum/go-ethereum/core/types" -) - -// resultStore implements a structure for maintaining fetchResults, tracking their -// download-progress and delivering (finished) results. -type resultStore struct { - items []*fetchResult // Downloaded but not yet delivered fetch results - resultOffset uint64 // Offset of the first cached fetch result in the block chain - - // Internal index of first non-completed entry, updated atomically when needed. - // If all items are complete, this will equal length(items), so - // *important* : is not safe to use for indexing without checking against length - indexIncomplete atomic.Int32 - - // throttleThreshold is the limit up to which we _want_ to fill the - // results. If blocks are large, we want to limit the results to less - // than the number of available slots, and maybe only fill 1024 out of - // 8192 possible places. The queue will, at certain times, recalibrate - // this index. - throttleThreshold uint64 - - lock sync.RWMutex -} - -func newResultStore(size int) *resultStore { - return &resultStore{ - resultOffset: 0, - items: make([]*fetchResult, size), - throttleThreshold: uint64(size), - } -} - -// SetThrottleThreshold updates the throttling threshold based on the requested -// limit and the total queue capacity. It returns the (possibly capped) threshold -func (r *resultStore) SetThrottleThreshold(threshold uint64) uint64 { - r.lock.Lock() - defer r.lock.Unlock() - - limit := uint64(len(r.items)) - if threshold >= limit { - threshold = limit - } - r.throttleThreshold = threshold - return r.throttleThreshold -} - -// AddFetch adds a header for body/receipt fetching. This is used when the queue -// wants to reserve headers for fetching. -// -// It returns the following: -// -// stale - if true, this item is already passed, and should not be requested again -// throttled - if true, the store is at capacity, this particular header is not prio now -// item - the result to store data into -// err - any error that occurred -func (r *resultStore) AddFetch(header *types.Header, fastSync bool) (stale, throttled bool, item *fetchResult, err error) { - r.lock.Lock() - defer r.lock.Unlock() - - var index int - item, index, stale, throttled, err = r.getFetchResult(header.Number.Uint64()) - if err != nil || stale || throttled { - return stale, throttled, item, err - } - if item == nil { - item = newFetchResult(header, fastSync) - r.items[index] = item - } - return stale, throttled, item, err -} - -// GetDeliverySlot returns the fetchResult for the given header. If the 'stale' flag -// is true, that means the header has already been delivered 'upstream'. This method -// does not bubble up the 'throttle' flag, since it's moot at the point in time when -// the item is downloaded and ready for delivery -func (r *resultStore) GetDeliverySlot(headerNumber uint64) (*fetchResult, bool, error) { - r.lock.RLock() - defer r.lock.RUnlock() - - res, _, stale, _, err := r.getFetchResult(headerNumber) - return res, stale, err -} - -// getFetchResult returns the fetchResult corresponding to the given item, and -// the index where the result is stored. -func (r *resultStore) getFetchResult(headerNumber uint64) (item *fetchResult, index int, stale, throttle bool, err error) { - index = int(int64(headerNumber) - int64(r.resultOffset)) - throttle = index >= int(r.throttleThreshold) - stale = index < 0 - - if index >= len(r.items) { - err = fmt.Errorf("%w: index allocation went beyond available resultStore space "+ - "(index [%d] = header [%d] - resultOffset [%d], len(resultStore) = %d", errInvalidChain, - index, headerNumber, r.resultOffset, len(r.items)) - return nil, index, stale, throttle, err - } - if stale { - return nil, index, stale, throttle, nil - } - item = r.items[index] - return item, index, stale, throttle, nil -} - -// HasCompletedItems returns true if there are processable items available -// this method is cheaper than countCompleted -func (r *resultStore) HasCompletedItems() bool { - r.lock.RLock() - defer r.lock.RUnlock() - - if len(r.items) == 0 { - return false - } - if item := r.items[0]; item != nil && item.AllDone() { - return true - } - return false -} - -// countCompleted returns the number of items ready for delivery, stopping at -// the first non-complete item. -// -// The method assumes (at least) rlock is held. -func (r *resultStore) countCompleted() int { - // We iterate from the already known complete point, and see - // if any more has completed since last count - index := r.indexIncomplete.Load() - for ; ; index++ { - if index >= int32(len(r.items)) { - break - } - result := r.items[index] - if result == nil || !result.AllDone() { - break - } - } - r.indexIncomplete.Store(index) - return int(index) -} - -// GetCompleted returns the next batch of completed fetchResults -func (r *resultStore) GetCompleted(limit int) []*fetchResult { - r.lock.Lock() - defer r.lock.Unlock() - - completed := r.countCompleted() - if limit > completed { - limit = completed - } - results := make([]*fetchResult, limit) - copy(results, r.items[:limit]) - - // Delete the results from the cache and clear the tail. - copy(r.items, r.items[limit:]) - for i := len(r.items) - limit; i < len(r.items); i++ { - r.items[i] = nil - } - // Advance the expected block number of the first cache entry - r.resultOffset += uint64(limit) - r.indexIncomplete.Add(int32(-limit)) - - return results -} - -// Prepare initialises the offset with the given block number -func (r *resultStore) Prepare(offset uint64) { - r.lock.Lock() - defer r.lock.Unlock() - - if r.resultOffset < offset { - r.resultOffset = offset - } -} diff --git a/builder/eth/downloader/skeleton.go b/builder/eth/downloader/skeleton.go deleted file mode 100644 index 873ee950b..000000000 --- a/builder/eth/downloader/skeleton.go +++ /dev/null @@ -1,1248 +0,0 @@ -// 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 downloader - -import ( - "encoding/json" - "errors" - "fmt" - "math/rand" - "sort" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" -) - -// scratchHeaders is the number of headers to store in a scratch space to allow -// concurrent downloads. A header is about 0.5KB in size, so there is no worry -// about using too much memory. The only catch is that we can only validate gaps -// after they're linked to the head, so the bigger the scratch space, the larger -// potential for invalid headers. -// -// The current scratch space of 131072 headers is expected to use 64MB RAM. -const scratchHeaders = 131072 - -// requestHeaders is the number of header to request from a remote peer in a single -// network packet. Although the skeleton downloader takes into consideration peer -// capacities when picking idlers, the packet size was decided to remain constant -// since headers are relatively small and it's easier to work with fixed batches -// vs. dynamic interval fillings. -const requestHeaders = 512 - -// errSyncLinked is an internal helper error to signal that the current sync -// cycle linked up to the genesis block, this the skeleton syncer should ping -// the backfiller to resume. Since we already have that logic on sync start, -// piggy-back on that instead of 2 entrypoints. -var errSyncLinked = errors.New("sync linked") - -// errSyncMerged is an internal helper error to signal that the current sync -// cycle merged with a previously aborted subchain, thus the skeleton syncer -// should abort and restart with the new state. -var errSyncMerged = errors.New("sync merged") - -// errSyncReorged is an internal helper error to signal that the head chain of -// the current sync cycle was (partially) reorged, thus the skeleton syncer -// should abort and restart with the new state. -var errSyncReorged = errors.New("sync reorged") - -// errTerminated is returned if the sync mechanism was terminated for this run of -// the process. This is usually the case when Geth is shutting down and some events -// might still be propagating. -var errTerminated = errors.New("terminated") - -// errChainReorged is an internal helper error to signal that the header chain -// of the current sync cycle was (partially) reorged. -var errChainReorged = errors.New("chain reorged") - -// errChainGapped is an internal helper error to signal that the header chain -// of the current sync cycle is gaped with the one advertised by consensus client. -var errChainGapped = errors.New("chain gapped") - -// errChainForked is an internal helper error to signal that the header chain -// of the current sync cycle is forked with the one advertised by consensus client. -var errChainForked = errors.New("chain forked") - -func init() { - // Tuning parameters is nice, but the scratch space must be assignable in - // full to peers. It's a useless cornercase to support a dangling half-group. - if scratchHeaders%requestHeaders != 0 { - panic("Please make scratchHeaders divisible by requestHeaders") - } -} - -// subchain is a contiguous header chain segment that is backed by the database, -// but may not be linked to the live chain. The skeleton downloader may produce -// a new one of these every time it is restarted until the subchain grows large -// enough to connect with a previous subchain. -// -// The subchains use the exact same database namespace and are not disjoint from -// each other. As such, extending one to overlap the other entails reducing the -// second one first. This combined buffer model is used to avoid having to move -// data on disk when two subchains are joined together. -type subchain struct { - Head uint64 // Block number of the newest header in the subchain - Tail uint64 // Block number of the oldest header in the subchain - Next common.Hash // Block hash of the next oldest header in the subchain -} - -// skeletonProgress is a database entry to allow suspending and resuming a chain -// sync. As the skeleton header chain is downloaded backwards, restarts can and -// will produce temporarily disjoint subchains. There is no way to restart a -// suspended skeleton sync without prior knowledge of all prior suspension points. -type skeletonProgress struct { - Subchains []*subchain // Disjoint subchains downloaded until now - Finalized *uint64 // Last known finalized block number -} - -// headUpdate is a notification that the beacon sync should switch to a new target. -// The update might request whether to forcefully change the target, or only try to -// extend it and fail if it's not possible. -type headUpdate struct { - header *types.Header // Header to update the sync target to - final *types.Header // Finalized header to use as thresholds - force bool // Whether to force the update or only extend if possible - errc chan error // Channel to signal acceptance of the new head -} - -// headerRequest tracks a pending header request to ensure responses are to -// actual requests and to validate any security constraints. -// -// Concurrency note: header requests and responses are handled concurrently from -// the main runloop to allow Keccak256 hash verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. subchains). -// That is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type headerRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - - deliver chan *headerResponse // Channel to deliver successful response on - revert chan *headerRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - stale chan struct{} // Channel to signal the request was dropped - - head uint64 // Head number of the requested batch of headers -} - -// headerResponse is an already verified remote response to a header request. -type headerResponse struct { - peer *peerConnection // Peer from which this response originates - reqid uint64 // Request ID that this response fulfils - headers []*types.Header // Chain of headers -} - -// backfiller is a callback interface through which the skeleton sync can tell -// the downloader that it should suspend or resume backfilling on specific head -// events (e.g. suspend on forks or gaps, resume on successful linkups). -type backfiller interface { - // suspend requests the backfiller to abort any running full or snap sync - // based on the skeleton chain as it might be invalid. The backfiller should - // gracefully handle multiple consecutive suspends without a resume, even - // on initial startup. - // - // The method should return the last block header that has been successfully - // backfilled (in the current or a previous run), falling back to the genesis. - suspend() *types.Header - - // resume requests the backfiller to start running fill or snap sync based on - // the skeleton chain as it has successfully been linked. Appending new heads - // to the end of the chain will not result in suspend/resume cycles. - // leaking too much sync logic out to the filler. - resume() -} - -// skeleton represents a header chain synchronized after the merge where blocks -// aren't validated any more via PoW in a forward fashion, rather are dictated -// and extended at the head via the beacon chain and backfilled on the original -// Ethereum block sync protocol. -// -// Since the skeleton is grown backwards from head to genesis, it is handled as -// a separate entity, not mixed in with the logical sequential transition of the -// blocks. Once the skeleton is connected to an existing, validated chain, the -// headers will be moved into the main downloader for filling and execution. -// -// Opposed to the original Ethereum block synchronization which is trustless (and -// uses a master peer to minimize the attack surface), post-merge block sync starts -// from a trusted head. As such, there is no need for a master peer any more and -// headers can be requested fully concurrently (though some batches might be -// discarded if they don't link up correctly). -// -// Although a skeleton is part of a sync cycle, it is not recreated, rather stays -// alive throughout the lifetime of the downloader. This allows it to be extended -// concurrently with the sync cycle, since extensions arrive from an API surface, -// not from within (vs. legacy Ethereum sync). -// -// Since the skeleton tracks the entire header chain until it is consumed by the -// forward block filling, it needs 0.5KB/block storage. At current mainnet sizes -// this is only possible with a disk backend. Since the skeleton is separate from -// the node's header chain, storing the headers ephemerally until sync finishes -// is wasted disk IO, but it's a price we're going to pay to keep things simple -// for now. -type skeleton struct { - db ethdb.Database // Database backing the skeleton - filler backfiller // Chain syncer suspended/resumed by head events - - peers *peerSet // Set of peers we can sync from - idles map[string]*peerConnection // Set of idle peers in the current sync cycle - drop peerDropFn // Drops a peer for misbehaving - - progress *skeletonProgress // Sync progress tracker for resumption and metrics - started time.Time // Timestamp when the skeleton syncer was created - logged time.Time // Timestamp when progress was last logged to the user - pulled uint64 // Number of headers downloaded in this run - - scratchSpace []*types.Header // Scratch space to accumulate headers in (first = recent) - scratchOwners []string // Peer IDs owning chunks of the scratch space (pend or delivered) - scratchHead uint64 // Block number of the first item in the scratch space - - requests map[uint64]*headerRequest // Header requests currently running - - headEvents chan *headUpdate // Notification channel for new heads - terminate chan chan error // Termination channel to abort sync - terminated chan struct{} // Channel to signal that the syncer is dead - - // Callback hooks used during testing - syncStarting func() // callback triggered after a sync cycle is inited but before started -} - -// newSkeleton creates a new sync skeleton that tracks a potentially dangling -// header chain until it's linked into an existing set of blocks. -func newSkeleton(db ethdb.Database, peers *peerSet, drop peerDropFn, filler backfiller) *skeleton { - sk := &skeleton{ - db: db, - filler: filler, - peers: peers, - drop: drop, - requests: make(map[uint64]*headerRequest), - headEvents: make(chan *headUpdate), - terminate: make(chan chan error), - terminated: make(chan struct{}), - } - go sk.startup() - return sk -} - -// startup is an initial background loop which waits for an event to start or -// tear the syncer down. This is required to make the skeleton sync loop once -// per process but at the same time not start before the beacon chain announces -// a new (existing) head. -func (s *skeleton) startup() { - // Close a notification channel so anyone sending us events will know if the - // sync loop was torn down for good. - defer close(s.terminated) - - // Wait for startup or teardown. This wait might loop a few times if a beacon - // client requests sync head extensions, but not forced reorgs (i.e. they are - // giving us new payloads without setting a starting head initially). - for { - select { - case errc := <-s.terminate: - // No head was announced but Geth is shutting down - errc <- nil - return - - case event := <-s.headEvents: - // New head announced, start syncing to it, looping every time a current - // cycle is terminated due to a chain event (head reorg, old chain merge). - if !event.force { - event.errc <- errors.New("forced head needed for startup") - continue - } - event.errc <- nil // forced head accepted for startup - head := event.header - s.started = time.Now() - - for { - // If the sync cycle terminated or was terminated, propagate up when - // higher layers request termination. There's no fancy explicit error - // signalling as the sync loop should never terminate (TM). - newhead, err := s.sync(head) - switch { - case err == errSyncLinked: - // Sync cycle linked up to the genesis block, or the existent chain - // segment. Tear down the loop and restart it so, it can properly - // notify the backfiller. Don't account a new head. - head = nil - - case err == errSyncMerged: - // Subchains were merged, we just need to reinit the internal - // start to continue on the tail of the merged chain. Don't - // announce a new head, - head = nil - - case err == errSyncReorged: - // The subchain being synced got modified at the head in a - // way that requires resyncing it. Restart sync with the new - // head to force a cleanup. - head = newhead - - case err == errTerminated: - // Sync was requested to be terminated from within, stop and - // return (no need to pass a message, was already done internally) - return - - default: - // Sync either successfully terminated or failed with an unhandled - // error. Abort and wait until Geth requests a termination. - errc := <-s.terminate - errc <- err - return - } - } - } - } -} - -// Terminate tears down the syncer indefinitely. -func (s *skeleton) Terminate() error { - // Request termination and fetch any errors - errc := make(chan error) - s.terminate <- errc - err := <-errc - - // Wait for full shutdown (not necessary, but cleaner) - <-s.terminated - return err -} - -// Sync starts or resumes a previous sync cycle to download and maintain a reverse -// header chain starting at the head and leading towards genesis to an available -// ancestor. -// -// This method does not block, rather it just waits until the syncer receives the -// fed header. What the syncer does with it is the syncer's problem. -func (s *skeleton) Sync(head *types.Header, final *types.Header, force bool) error { - log.Trace("New skeleton head announced", "number", head.Number, "hash", head.Hash(), "force", force) - errc := make(chan error) - - select { - case s.headEvents <- &headUpdate{header: head, final: final, force: force, errc: errc}: - return <-errc - case <-s.terminated: - return errTerminated - } -} - -// sync is the internal version of Sync that executes a single sync cycle, either -// until some termination condition is reached, or until the current cycle merges -// with a previously aborted run. -func (s *skeleton) sync(head *types.Header) (*types.Header, error) { - // If we're continuing a previous merge interrupt, just access the existing - // old state without initing from disk. - if head == nil { - head = rawdb.ReadSkeletonHeader(s.db, s.progress.Subchains[0].Head) - } else { - // Otherwise, initialize the sync, trimming and previous leftovers until - // we're consistent with the newly requested chain head - s.initSync(head) - } - // Create the scratch space to fill with concurrently downloaded headers - s.scratchSpace = make([]*types.Header, scratchHeaders) - defer func() { s.scratchSpace = nil }() // don't hold on to references after sync - - s.scratchOwners = make([]string, scratchHeaders/requestHeaders) - defer func() { s.scratchOwners = nil }() // don't hold on to references after sync - - s.scratchHead = s.progress.Subchains[0].Tail - 1 // tail must not be 0! - - // If the sync is already done, resume the backfiller. When the loop stops, - // terminate the backfiller too. - linked := len(s.progress.Subchains) == 1 && - rawdb.HasHeader(s.db, s.progress.Subchains[0].Next, s.scratchHead) && - rawdb.HasBody(s.db, s.progress.Subchains[0].Next, s.scratchHead) && - rawdb.HasReceipts(s.db, s.progress.Subchains[0].Next, s.scratchHead) - if linked { - s.filler.resume() - } - defer func() { - // The filler needs to be suspended, but since it can block for a while - // when there are many blocks queued up for full-sync importing, run it - // on a separate goroutine and consume head messages that need instant - // replies. - done := make(chan struct{}) - go func() { - defer close(done) - filled := s.filler.suspend() - if filled == nil { - log.Error("Latest filled block is not available") - return - } - // If something was filled, try to delete stale sync helpers. If - // unsuccessful, warn the user, but not much else we can do (it's - // a programming error, just let users report an issue and don't - // choke in the meantime). - if err := s.cleanStales(filled); err != nil { - log.Error("Failed to clean stale beacon headers", "err", err) - } - }() - // Wait for the suspend to finish, consuming head events in the meantime - // and dropping them on the floor. - for { - select { - case <-done: - return - case event := <-s.headEvents: - event.errc <- errors.New("beacon syncer reorging") - } - } - }() - // Create a set of unique channels for this sync cycle. We need these to be - // ephemeral so a data race doesn't accidentally deliver something stale on - // a persistent channel across syncs (yup, this happened) - var ( - requestFails = make(chan *headerRequest) - responses = make(chan *headerResponse) - ) - cancel := make(chan struct{}) - defer close(cancel) - - log.Debug("Starting reverse header sync cycle", "head", head.Number, "hash", head.Hash(), "cont", s.scratchHead) - - // Whether sync completed or not, disregard any future packets - defer func() { - log.Debug("Terminating reverse header sync cycle", "head", head.Number, "hash", head.Hash(), "cont", s.scratchHead) - s.requests = make(map[uint64]*headerRequest) - }() - - // Start tracking idle peers for task assignments - peering := make(chan *peeringEvent, 64) // arbitrary buffer, just some burst protection - - peeringSub := s.peers.SubscribeEvents(peering) - defer peeringSub.Unsubscribe() - - s.idles = make(map[string]*peerConnection) - for _, peer := range s.peers.AllPeers() { - s.idles[peer.id] = peer - } - // Notify any tester listening for startup events - if s.syncStarting != nil { - s.syncStarting() - } - for { - // Something happened, try to assign new tasks to any idle peers - if !linked { - s.assignTasks(responses, requestFails, cancel) - } - // Wait for something to happen - select { - case event := <-peering: - // A peer joined or left, the tasks queue and allocations need to be - // checked for potential assignment or reassignment - peerid := event.peer.id - if event.join { - log.Debug("Joining skeleton peer", "id", peerid) - s.idles[peerid] = event.peer - } else { - log.Debug("Leaving skeleton peer", "id", peerid) - s.revertRequests(peerid) - delete(s.idles, peerid) - } - - case errc := <-s.terminate: - errc <- nil - return nil, errTerminated - - case event := <-s.headEvents: - // New head was announced, try to integrate it. If successful, nothing - // needs to be done as the head simply extended the last range. For now - // we don't seamlessly integrate reorgs to keep things simple. If the - // network starts doing many mini reorgs, it might be worthwhile handling - // a limited depth without an error. - if err := s.processNewHead(event.header, event.final); err != nil { - // If a reorg is needed, and we're forcing the new head, signal - // the syncer to tear down and start over. Otherwise, drop the - // non-force reorg. - if event.force { - event.errc <- nil // forced head reorg accepted - log.Info("Restarting sync cycle", "reason", err) - return event.header, errSyncReorged - } - event.errc <- err - continue - } - event.errc <- nil // head extension accepted - - // New head was integrated into the skeleton chain. If the backfiller - // is still running, it will pick it up. If it already terminated, - // a new cycle needs to be spun up. - if linked { - s.filler.resume() - } - - case req := <-requestFails: - s.revertRequest(req) - - case res := <-responses: - // Process the batch of headers. If though processing we managed to - // link the current subchain to a previously downloaded one, abort the - // sync and restart with the merged subchains. - // - // If we managed to link to the existing local chain or genesis block, - // abort sync altogether. - linked, merged := s.processResponse(res) - if linked { - log.Debug("Beacon sync linked to local chain") - return nil, errSyncLinked - } - if merged { - log.Debug("Beacon sync merged subchains") - return nil, errSyncMerged - } - // We still have work to do, loop and repeat - } - } -} - -// initSync attempts to get the skeleton sync into a consistent state wrt any -// past state on disk and the newly requested head to sync to. If the new head -// is nil, the method will return and continue from the previous head. -func (s *skeleton) initSync(head *types.Header) { - // Extract the head number, we'll need it all over - number := head.Number.Uint64() - - // Retrieve the previously saved sync progress - if status := rawdb.ReadSkeletonSyncStatus(s.db); len(status) > 0 { - s.progress = new(skeletonProgress) - if err := json.Unmarshal(status, s.progress); err != nil { - log.Error("Failed to decode skeleton sync status", "err", err) - } else { - // Previous sync was available, print some continuation logs - for _, subchain := range s.progress.Subchains { - log.Debug("Restarting skeleton subchain", "head", subchain.Head, "tail", subchain.Tail) - } - // Create a new subchain for the head (unless the last can be extended), - // trimming anything it would overwrite - headchain := &subchain{ - Head: number, - Tail: number, - Next: head.ParentHash, - } - for len(s.progress.Subchains) > 0 { - // If the last chain is above the new head, delete altogether - lastchain := s.progress.Subchains[0] - if lastchain.Tail >= headchain.Tail { - log.Debug("Dropping skeleton subchain", "head", lastchain.Head, "tail", lastchain.Tail) - s.progress.Subchains = s.progress.Subchains[1:] - continue - } - // Otherwise truncate the last chain if needed and abort trimming - if lastchain.Head >= headchain.Tail { - log.Debug("Trimming skeleton subchain", "oldhead", lastchain.Head, "newhead", headchain.Tail-1, "tail", lastchain.Tail) - lastchain.Head = headchain.Tail - 1 - } - break - } - // If the last subchain can be extended, we're lucky. Otherwise, create - // a new subchain sync task. - var extended bool - if n := len(s.progress.Subchains); n > 0 { - lastchain := s.progress.Subchains[0] - if lastchain.Head == headchain.Tail-1 { - lasthead := rawdb.ReadSkeletonHeader(s.db, lastchain.Head) - if lasthead.Hash() == head.ParentHash { - log.Debug("Extended skeleton subchain with new head", "head", headchain.Tail, "tail", lastchain.Tail) - lastchain.Head = headchain.Tail - extended = true - } - } - } - if !extended { - log.Debug("Created new skeleton subchain", "head", number, "tail", number) - s.progress.Subchains = append([]*subchain{headchain}, s.progress.Subchains...) - } - // Update the database with the new sync stats and insert the new - // head header. We won't delete any trimmed skeleton headers since - // those will be outside the index space of the many subchains and - // the database space will be reclaimed eventually when processing - // blocks above the current head (TODO(karalabe): don't forget). - batch := s.db.NewBatch() - - rawdb.WriteSkeletonHeader(batch, head) - s.saveSyncStatus(batch) - - if err := batch.Write(); err != nil { - log.Crit("Failed to write skeleton sync status", "err", err) - } - return - } - } - // Either we've failed to decode the previous state, or there was none. Start - // a fresh sync with a single subchain represented by the currently sent - // chain head. - s.progress = &skeletonProgress{ - Subchains: []*subchain{ - { - Head: number, - Tail: number, - Next: head.ParentHash, - }, - }, - } - batch := s.db.NewBatch() - - rawdb.WriteSkeletonHeader(batch, head) - s.saveSyncStatus(batch) - - if err := batch.Write(); err != nil { - log.Crit("Failed to write initial skeleton sync status", "err", err) - } - log.Debug("Created initial skeleton subchain", "head", number, "tail", number) -} - -// saveSyncStatus marshals the remaining sync tasks into leveldb. -func (s *skeleton) saveSyncStatus(db ethdb.KeyValueWriter) { - status, err := json.Marshal(s.progress) - if err != nil { - panic(err) // This can only fail during implementation - } - rawdb.WriteSkeletonSyncStatus(db, status) -} - -// processNewHead does the internal shuffling for a new head marker and either -// accepts and integrates it into the skeleton or requests a reorg. Upon reorg, -// the syncer will tear itself down and restart with a fresh head. It is simpler -// to reconstruct the sync state than to mutate it and hope for the best. -func (s *skeleton) processNewHead(head *types.Header, final *types.Header) error { - // If a new finalized block was announced, update the sync process independent - // of what happens with the sync head below - if final != nil { - if number := final.Number.Uint64(); s.progress.Finalized == nil || *s.progress.Finalized != number { - s.progress.Finalized = new(uint64) - *s.progress.Finalized = final.Number.Uint64() - - s.saveSyncStatus(s.db) - } - } - // If the header cannot be inserted without interruption, return an error for - // the outer loop to tear down the skeleton sync and restart it - number := head.Number.Uint64() - - lastchain := s.progress.Subchains[0] - if lastchain.Tail >= number { - // If the chain is down to a single beacon header, and it is re-announced - // once more, ignore it instead of tearing down sync for a noop. - if lastchain.Head == lastchain.Tail { - if current := rawdb.ReadSkeletonHeader(s.db, number); current.Hash() == head.Hash() { - return nil - } - } - // Not a noop / double head announce, abort with a reorg - return fmt.Errorf("%w, tail: %d, head: %d, newHead: %d", errChainReorged, lastchain.Tail, lastchain.Head, number) - } - if lastchain.Head+1 < number { - return fmt.Errorf("%w, head: %d, newHead: %d", errChainGapped, lastchain.Head, number) - } - if parent := rawdb.ReadSkeletonHeader(s.db, number-1); parent.Hash() != head.ParentHash { - return fmt.Errorf("%w, ancestor: %d, hash: %s, want: %s", errChainForked, number-1, parent.Hash(), head.ParentHash) - } - // New header seems to be in the last subchain range. Unwind any extra headers - // from the chain tip and insert the new head. We won't delete any trimmed - // skeleton headers since those will be outside the index space of the many - // subchains and the database space will be reclaimed eventually when processing - // blocks above the current head (TODO(karalabe): don't forget). - batch := s.db.NewBatch() - - rawdb.WriteSkeletonHeader(batch, head) - lastchain.Head = number - s.saveSyncStatus(batch) - - if err := batch.Write(); err != nil { - log.Crit("Failed to write skeleton sync status", "err", err) - } - return nil -} - -// assignTasks attempts to match idle peers to pending header retrievals. -func (s *skeleton) assignTasks(success chan *headerResponse, fail chan *headerRequest, cancel chan struct{}) { - // Sort the peers by download capacity to use faster ones if many available - idlers := &peerCapacitySort{ - peers: make([]*peerConnection, 0, len(s.idles)), - caps: make([]int, 0, len(s.idles)), - } - targetTTL := s.peers.rates.TargetTimeout() - for _, peer := range s.idles { - idlers.peers = append(idlers.peers, peer) - idlers.caps = append(idlers.caps, s.peers.rates.Capacity(peer.id, eth.BlockHeadersMsg, targetTTL)) - } - if len(idlers.peers) == 0 { - return - } - sort.Sort(idlers) - - // Find header regions not yet downloading and fill them - for task, owner := range s.scratchOwners { - // If we're out of idle peers, stop assigning tasks - if len(idlers.peers) == 0 { - return - } - // Skip any tasks already filling - if owner != "" { - continue - } - // If we've reached the genesis, stop assigning tasks - if uint64(task*requestHeaders) >= s.scratchHead { - return - } - // Found a task and have peers available, assign it - idle := idlers.peers[0] - - idlers.peers = idlers.peers[1:] - idlers.caps = idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.requests[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer - req := &headerRequest{ - peer: idle.id, - id: reqid, - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - head: s.scratchHead - uint64(task*requestHeaders), - } - s.requests[reqid] = req - delete(s.idles, idle.id) - - // Generate the network query and send it to the peer - go s.executeTask(idle, req) - - // Inject the request into the task to block further assignments - s.scratchOwners[task] = idle.id - } -} - -// executeTask executes a single fetch request, blocking until either a result -// arrives or a timeouts / cancellation is triggered. The method should be run -// on its own goroutine and will deliver on the requested channels. -func (s *skeleton) executeTask(peer *peerConnection, req *headerRequest) { - start := time.Now() - resCh := make(chan *eth.Response) - - // Figure out how many headers to fetch. Usually this will be a full batch, - // but for the very tail of the chain, trim the request to the number left. - // Since nodes may or may not return the genesis header for a batch request, - // don't even request it. The parent hash of block #1 is enough to link. - requestCount := requestHeaders - if req.head < requestHeaders { - requestCount = int(req.head) - } - peer.log.Trace("Fetching skeleton headers", "from", req.head, "count", requestCount) - netreq, err := peer.peer.RequestHeadersByNumber(req.head, requestCount, 0, true, resCh) - if err != nil { - peer.log.Trace("Failed to request headers", "err", err) - s.scheduleRevertRequest(req) - return - } - defer netreq.Close() - - // Wait until the response arrives, the request is cancelled or times out - ttl := s.peers.rates.TargetTimeout() - - timeoutTimer := time.NewTimer(ttl) - defer timeoutTimer.Stop() - - select { - case <-req.cancel: - peer.log.Debug("Header request cancelled") - s.scheduleRevertRequest(req) - - case <-timeoutTimer.C: - // Header retrieval timed out, update the metrics - peer.log.Warn("Header request timed out, dropping peer", "elapsed", ttl) - headerTimeoutMeter.Mark(1) - s.peers.rates.Update(peer.id, eth.BlockHeadersMsg, 0, 0) - s.scheduleRevertRequest(req) - - // At this point we either need to drop the offending peer, or we need a - // mechanism to allow waiting for the response and not cancel it. For now - // lets go with dropping since the header sizes are deterministic and the - // beacon sync runs exclusive (downloader is idle) so there should be no - // other load to make timeouts probable. If we notice that timeouts happen - // more often than we'd like, we can introduce a tracker for the requests - // gone stale and monitor them. However, in that case too, we need a way - // to protect against malicious peers never responding, so it would need - // a second, hard-timeout mechanism. - s.drop(peer.id) - - case res := <-resCh: - // Headers successfully retrieved, update the metrics - headers := *res.Res.(*eth.BlockHeadersRequest) - - headerReqTimer.Update(time.Since(start)) - s.peers.rates.Update(peer.id, eth.BlockHeadersMsg, res.Time, len(headers)) - - // Cross validate the headers with the requests - switch { - case len(headers) == 0: - // No headers were delivered, reject the response and reschedule - peer.log.Debug("No headers delivered") - res.Done <- errors.New("no headers delivered") - s.scheduleRevertRequest(req) - - case headers[0].Number.Uint64() != req.head: - // Header batch anchored at non-requested number - peer.log.Debug("Invalid header response head", "have", headers[0].Number, "want", req.head) - res.Done <- errors.New("invalid header batch anchor") - s.scheduleRevertRequest(req) - - case req.head >= requestHeaders && len(headers) != requestHeaders: - // Invalid number of non-genesis headers delivered, reject the response and reschedule - peer.log.Debug("Invalid non-genesis header count", "have", len(headers), "want", requestHeaders) - res.Done <- errors.New("not enough non-genesis headers delivered") - s.scheduleRevertRequest(req) - - case req.head < requestHeaders && uint64(len(headers)) != req.head: - // Invalid number of genesis headers delivered, reject the response and reschedule - peer.log.Debug("Invalid genesis header count", "have", len(headers), "want", headers[0].Number.Uint64()) - res.Done <- errors.New("not enough genesis headers delivered") - s.scheduleRevertRequest(req) - - default: - // Packet seems structurally valid, check hash progression and if it - // is correct too, deliver for storage - for i := 0; i < len(headers)-1; i++ { - if headers[i].ParentHash != headers[i+1].Hash() { - peer.log.Debug("Invalid hash progression", "index", i, "wantparenthash", headers[i].ParentHash, "haveparenthash", headers[i+1].Hash()) - res.Done <- errors.New("invalid hash progression") - s.scheduleRevertRequest(req) - return - } - } - // Hash chain is valid. The delivery might still be junk as we're - // downloading batches concurrently (so no way to link the headers - // until gaps are filled); in that case, we'll nuke the peer when - // we detect the fault. - res.Done <- nil - - select { - case req.deliver <- &headerResponse{ - peer: peer, - reqid: req.id, - headers: headers, - }: - case <-req.cancel: - } - } - } -} - -// revertRequests locates all the currently pending requests from a particular -// peer and reverts them, rescheduling for others to fulfill. -func (s *skeleton) revertRequests(peer string) { - // Gather the requests first, revertals need the lock too - var requests []*headerRequest - for _, req := range s.requests { - if req.peer == peer { - requests = append(requests, req) - } - } - // Revert all the requests matching the peer - for _, req := range requests { - s.revertRequest(req) - } -} - -// scheduleRevertRequest asks the event loop to clean up a request and return -// all failed retrieval tasks to the scheduler for reassignment. -func (s *skeleton) scheduleRevertRequest(req *headerRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertRequest cleans up a request and returns all failed retrieval tasks to -// the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertRequest. -func (s *skeleton) revertRequest(req *headerRequest) { - log.Trace("Reverting header request", "peer", req.peer, "reqid", req.id) - select { - case <-req.stale: - log.Trace("Header request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - delete(s.requests, req.id) - - // Remove the request from the tracked set and mark the task as not-pending, - // ready for rescheduling - s.scratchOwners[(s.scratchHead-req.head)/requestHeaders] = "" -} - -func (s *skeleton) processResponse(res *headerResponse) (linked bool, merged bool) { - res.peer.log.Trace("Processing header response", "head", res.headers[0].Number, "hash", res.headers[0].Hash(), "count", len(res.headers)) - - // Whether the response is valid, we can mark the peer as idle and notify - // the scheduler to assign a new task. If the response is invalid, we'll - // drop the peer in a bit. - s.idles[res.peer.id] = res.peer - - // Ensure the response is for a valid request - if _, ok := s.requests[res.reqid]; !ok { - // Some internal accounting is broken. A request either times out or it - // gets fulfilled successfully. It should not be possible to deliver a - // response to a non-existing request. - res.peer.log.Error("Unexpected header packet") - return false, false - } - delete(s.requests, res.reqid) - - // Insert the delivered headers into the scratch space independent of the - // content or continuation; those will be validated in a moment - head := res.headers[0].Number.Uint64() - copy(s.scratchSpace[s.scratchHead-head:], res.headers) - - // If there's still a gap in the head of the scratch space, abort - if s.scratchSpace[0] == nil { - return false, false - } - // Try to consume any head headers, validating the boundary conditions - batch := s.db.NewBatch() - for s.scratchSpace[0] != nil { - // Next batch of headers available, cross-reference with the subchain - // we are extending and either accept or discard - if s.progress.Subchains[0].Next != s.scratchSpace[0].Hash() { - // Print a log messages to track what's going on - tail := s.progress.Subchains[0].Tail - want := s.progress.Subchains[0].Next - have := s.scratchSpace[0].Hash() - - log.Warn("Invalid skeleton headers", "peer", s.scratchOwners[0], "number", tail-1, "want", want, "have", have) - - // The peer delivered junk, or at least not the subchain we are - // syncing to. Free up the scratch space and assignment, reassign - // and drop the original peer. - for i := 0; i < requestHeaders; i++ { - s.scratchSpace[i] = nil - } - s.drop(s.scratchOwners[0]) - s.scratchOwners[0] = "" - break - } - // Scratch delivery matches required subchain, deliver the batch of - // headers and push the subchain forward - var consumed int - for _, header := range s.scratchSpace[:requestHeaders] { - if header != nil { // nil when the genesis is reached - consumed++ - - rawdb.WriteSkeletonHeader(batch, header) - s.pulled++ - - s.progress.Subchains[0].Tail-- - s.progress.Subchains[0].Next = header.ParentHash - - // If we've reached an existing block in the chain, stop retrieving - // headers. Note, if we want to support light clients with the same - // code we'd need to switch here based on the downloader mode. That - // said, there's no such functionality for now, so don't complicate. - // - // In the case of full sync it would be enough to check for the body, - // but even a full syncing node will generate a receipt once block - // processing is done, so it's just one more "needless" check. - // - // The weird cascading checks are done to minimize the database reads. - linked = rawdb.HasHeader(s.db, header.ParentHash, header.Number.Uint64()-1) && - rawdb.HasBody(s.db, header.ParentHash, header.Number.Uint64()-1) && - rawdb.HasReceipts(s.db, header.ParentHash, header.Number.Uint64()-1) - if linked { - break - } - } - } - head := s.progress.Subchains[0].Head - tail := s.progress.Subchains[0].Tail - next := s.progress.Subchains[0].Next - - log.Trace("Primary subchain extended", "head", head, "tail", tail, "next", next) - - // If the beacon chain was linked to the local chain, completely swap out - // all internal progress and abort header synchronization. - if linked { - // Linking into the local chain should also mean that there are no - // leftover subchains, but in the case of importing the blocks via - // the engine API, we will not push the subchains forward. This will - // lead to a gap between an old sync cycle and a future one. - if subchains := len(s.progress.Subchains); subchains > 1 { - switch { - // If there are only 2 subchains - the current one and an older - // one - and the old one consists of a single block, then it's - // the expected new sync cycle after some propagated blocks. Log - // it for debugging purposes, explicitly clean and don't escalate. - case subchains == 2 && s.progress.Subchains[1].Head == s.progress.Subchains[1].Tail: - // Remove the leftover skeleton header associated with old - // skeleton chain only if it's not covered by the current - // skeleton range. - if s.progress.Subchains[1].Head < s.progress.Subchains[0].Tail { - log.Debug("Cleaning previous beacon sync state", "head", s.progress.Subchains[1].Head) - rawdb.DeleteSkeletonHeader(batch, s.progress.Subchains[1].Head) - } - // Drop the leftover skeleton chain since it's stale. - s.progress.Subchains = s.progress.Subchains[:1] - - // If we have more than one header or more than one leftover chain, - // the syncer's internal state is corrupted. Do try to fix it, but - // be very vocal about the fault. - default: - var context []interface{} - - for i := range s.progress.Subchains[1:] { - context = append(context, fmt.Sprintf("stale_head_%d", i+1)) - context = append(context, s.progress.Subchains[i+1].Head) - context = append(context, fmt.Sprintf("stale_tail_%d", i+1)) - context = append(context, s.progress.Subchains[i+1].Tail) - context = append(context, fmt.Sprintf("stale_next_%d", i+1)) - context = append(context, s.progress.Subchains[i+1].Next) - } - log.Error("Cleaning spurious beacon sync leftovers", context...) - s.progress.Subchains = s.progress.Subchains[:1] - - // Note, here we didn't actually delete the headers at all, - // just the metadata. We could implement a cleanup mechanism, - // but further modifying corrupted state is kind of asking - // for it. Unless there's a good enough reason to risk it, - // better to live with the small database junk. - } - } - break - } - // Batch of headers consumed, shift the download window forward - copy(s.scratchSpace, s.scratchSpace[requestHeaders:]) - for i := 0; i < requestHeaders; i++ { - s.scratchSpace[scratchHeaders-i-1] = nil - } - copy(s.scratchOwners, s.scratchOwners[1:]) - s.scratchOwners[scratchHeaders/requestHeaders-1] = "" - - s.scratchHead -= uint64(consumed) - - // If the subchain extended into the next subchain, we need to handle - // the overlap. Since there could be many overlaps (come on), do this - // in a loop. - for len(s.progress.Subchains) > 1 && s.progress.Subchains[1].Head >= s.progress.Subchains[0].Tail { - // Extract some stats from the second subchain - head := s.progress.Subchains[1].Head - tail := s.progress.Subchains[1].Tail - next := s.progress.Subchains[1].Next - - // Since we just overwrote part of the next subchain, we need to trim - // its head independent of matching or mismatching content - if s.progress.Subchains[1].Tail >= s.progress.Subchains[0].Tail { - // Fully overwritten, get rid of the subchain as a whole - log.Debug("Previous subchain fully overwritten", "head", head, "tail", tail, "next", next) - s.progress.Subchains = append(s.progress.Subchains[:1], s.progress.Subchains[2:]...) - continue - } else { - // Partially overwritten, trim the head to the overwritten size - log.Debug("Previous subchain partially overwritten", "head", head, "tail", tail, "next", next) - s.progress.Subchains[1].Head = s.progress.Subchains[0].Tail - 1 - } - // If the old subchain is an extension of the new one, merge the two - // and let the skeleton syncer restart (to clean internal state) - if rawdb.ReadSkeletonHeader(s.db, s.progress.Subchains[1].Head).Hash() == s.progress.Subchains[0].Next { - log.Debug("Previous subchain merged", "head", head, "tail", tail, "next", next) - s.progress.Subchains[0].Tail = s.progress.Subchains[1].Tail - s.progress.Subchains[0].Next = s.progress.Subchains[1].Next - - s.progress.Subchains = append(s.progress.Subchains[:1], s.progress.Subchains[2:]...) - merged = true - } - } - // If subchains were merged, all further available headers in the scratch - // space are invalid since we skipped ahead. Stop processing the scratch - // space to avoid dropping peers thinking they delivered invalid data. - if merged { - break - } - } - s.saveSyncStatus(batch) - if err := batch.Write(); err != nil { - log.Crit("Failed to write skeleton headers and progress", "err", err) - } - // Print a progress report making the UX a bit nicer - left := s.progress.Subchains[0].Tail - 1 - if linked { - left = 0 - } - if time.Since(s.logged) > 8*time.Second || left == 0 { - s.logged = time.Now() - - if s.pulled == 0 { - log.Info("Beacon sync starting", "left", left) - } else { - eta := float64(time.Since(s.started)) / float64(s.pulled) * float64(left) - log.Info("Syncing beacon headers", "downloaded", s.pulled, "left", left, "eta", common.PrettyDuration(eta)) - } - } - return linked, merged -} - -// cleanStales removes previously synced beacon headers that have become stale -// due to the downloader backfilling past the tracked tail. -func (s *skeleton) cleanStales(filled *types.Header) error { - number := filled.Number.Uint64() - log.Trace("Cleaning stale beacon headers", "filled", number, "hash", filled.Hash()) - - // If the filled header is below the linked subchain, something's corrupted - // internally. Report and error and refuse to do anything. - if number+1 < s.progress.Subchains[0].Tail { - return fmt.Errorf("filled header below beacon header tail: %d < %d", number, s.progress.Subchains[0].Tail) - } - // If nothing in subchain is filled, don't bother to do cleanup. - if number+1 == s.progress.Subchains[0].Tail { - return nil - } - var ( - start uint64 - end uint64 - batch = s.db.NewBatch() - ) - if number < s.progress.Subchains[0].Head { - // The skeleton chain is partially consumed, set the new tail as filled+1. - tail := rawdb.ReadSkeletonHeader(s.db, number+1) - if tail.ParentHash != filled.Hash() { - return fmt.Errorf("filled header is discontinuous with subchain: %d %s, please file an issue", number, filled.Hash()) - } - start, end = s.progress.Subchains[0].Tail, number+1 // remove headers in [tail, filled] - s.progress.Subchains[0].Tail = tail.Number.Uint64() - s.progress.Subchains[0].Next = tail.ParentHash - } else { - // The skeleton chain is fully consumed, set both head and tail as filled. - start, end = s.progress.Subchains[0].Tail, filled.Number.Uint64() // remove headers in [tail, filled) - s.progress.Subchains[0].Tail = filled.Number.Uint64() - s.progress.Subchains[0].Next = filled.ParentHash - - // If more headers were filled than available, push the entire subchain - // forward to keep tracking the node's block imports. - if number > s.progress.Subchains[0].Head { - end = s.progress.Subchains[0].Head + 1 // delete the entire original range, including the head - s.progress.Subchains[0].Head = number // assign a new head (tail is already assigned to this) - - // The entire original skeleton chain was deleted and a new one - // defined. Make sure the new single-header chain gets pushed to - // disk to keep internal state consistent. - rawdb.WriteSkeletonHeader(batch, filled) - } - } - // Execute the trimming and the potential rewiring of the progress - s.saveSyncStatus(batch) - for n := start; n < end; n++ { - // If the batch grew too big, flush it and continue with a new batch. - // The catch is that the sync metadata needs to reflect the actually - // flushed state, so temporarily change the subchain progress and - // revert after the flush. - if batch.ValueSize() >= ethdb.IdealBatchSize { - tmpTail := s.progress.Subchains[0].Tail - tmpNext := s.progress.Subchains[0].Next - - s.progress.Subchains[0].Tail = n - s.progress.Subchains[0].Next = rawdb.ReadSkeletonHeader(s.db, n).ParentHash - s.saveSyncStatus(batch) - - if err := batch.Write(); err != nil { - log.Crit("Failed to write beacon trim data", "err", err) - } - batch.Reset() - - s.progress.Subchains[0].Tail = tmpTail - s.progress.Subchains[0].Next = tmpNext - s.saveSyncStatus(batch) - } - rawdb.DeleteSkeletonHeader(batch, n) - } - if err := batch.Write(); err != nil { - log.Crit("Failed to write beacon trim data", "err", err) - } - return nil -} - -// Bounds retrieves the current head and tail tracked by the skeleton syncer -// and optionally the last known finalized header if any was announced and if -// it is still in the sync range. This method is used by the backfiller, whose -// life cycle is controlled by the skeleton syncer. -// -// Note, the method will not use the internal state of the skeleton, but will -// rather blindly pull stuff from the database. This is fine, because the back- -// filler will only run when the skeleton chain is fully downloaded and stable. -// There might be new heads appended, but those are atomic from the perspective -// of this method. Any head reorg will first tear down the backfiller and only -// then make the modification. -func (s *skeleton) Bounds() (head *types.Header, tail *types.Header, final *types.Header, err error) { - // Read the current sync progress from disk and figure out the current head. - // Although there's a lot of error handling here, these are mostly as sanity - // checks to avoid crashing if a programming error happens. These should not - // happen in live code. - status := rawdb.ReadSkeletonSyncStatus(s.db) - if len(status) == 0 { - return nil, nil, nil, errors.New("beacon sync not yet started") - } - progress := new(skeletonProgress) - if err := json.Unmarshal(status, progress); err != nil { - return nil, nil, nil, err - } - head = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Head) - if head == nil { - return nil, nil, nil, fmt.Errorf("head skeleton header %d is missing", progress.Subchains[0].Head) - } - tail = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Tail) - if tail == nil { - return nil, nil, nil, fmt.Errorf("tail skeleton header %d is missing", progress.Subchains[0].Tail) - } - if progress.Finalized != nil && tail.Number.Uint64() <= *progress.Finalized && *progress.Finalized <= head.Number.Uint64() { - final = rawdb.ReadSkeletonHeader(s.db, *progress.Finalized) - if final == nil { - return nil, nil, nil, fmt.Errorf("finalized skeleton header %d is missing", *progress.Finalized) - } - } - return head, tail, final, nil -} - -// Header retrieves a specific header tracked by the skeleton syncer. This method -// is meant to be used by the backfiller, whose life cycle is controlled by the -// skeleton syncer. -// -// Note, outside the permitted runtimes, this method might return nil results and -// subsequent calls might return headers from different chains. -func (s *skeleton) Header(number uint64) *types.Header { - return rawdb.ReadSkeletonHeader(s.db, number) -} diff --git a/builder/eth/downloader/skeleton_test.go b/builder/eth/downloader/skeleton_test.go deleted file mode 100644 index 2b108dfe9..000000000 --- a/builder/eth/downloader/skeleton_test.go +++ /dev/null @@ -1,975 +0,0 @@ -// 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 downloader - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -// hookedBackfiller is a tester backfiller with all interface methods mocked and -// hooked so tests can implement only the things they need. -type hookedBackfiller struct { - // suspendHook is an optional hook to be called when the filler is requested - // to be suspended. - suspendHook func() *types.Header - - // resumeHook is an optional hook to be called when the filler is requested - // to be resumed. - resumeHook func() -} - -// newHookedBackfiller creates a hooked backfiller with all callbacks disabled, -// essentially acting as a noop. -func newHookedBackfiller() backfiller { - return new(hookedBackfiller) -} - -// suspend requests the backfiller to abort any running full or snap sync -// based on the skeleton chain as it might be invalid. The backfiller should -// gracefully handle multiple consecutive suspends without a resume, even -// on initial startup. -func (hf *hookedBackfiller) suspend() *types.Header { - if hf.suspendHook != nil { - return hf.suspendHook() - } - return nil // we don't really care about header cleanups for now -} - -// resume requests the backfiller to start running fill or snap sync based on -// the skeleton chain as it has successfully been linked. Appending new heads -// to the end of the chain will not result in suspend/resume cycles. -func (hf *hookedBackfiller) resume() { - if hf.resumeHook != nil { - hf.resumeHook() - } -} - -// skeletonTestPeer is a mock peer that can only serve header requests from a -// pre-perated header chain (which may be arbitrarily wrong for testing). -// -// Requesting anything else from these peers will hard panic. Note, do *not* -// implement any other methods. We actually want to make sure that the skeleton -// syncer only depends on - and will only ever do so - on header requests. -type skeletonTestPeer struct { - id string // Unique identifier of the mock peer - headers []*types.Header // Headers to serve when requested - - serve func(origin uint64) []*types.Header // Hook to allow custom responses - - served atomic.Uint64 // Number of headers served by this peer - dropped atomic.Uint64 // Flag whether the peer was dropped (stop responding) -} - -// newSkeletonTestPeer creates a new mock peer to test the skeleton sync with. -func newSkeletonTestPeer(id string, headers []*types.Header) *skeletonTestPeer { - return &skeletonTestPeer{ - id: id, - headers: headers, - } -} - -// newSkeletonTestPeer creates a new mock peer to test the skeleton sync with, -// and sets an optional serve hook that can return headers for delivery instead -// of the predefined chain. Useful for emulating malicious behavior that would -// otherwise require dedicated peer types. -func newSkeletonTestPeerWithHook(id string, headers []*types.Header, serve func(origin uint64) []*types.Header) *skeletonTestPeer { - return &skeletonTestPeer{ - id: id, - headers: headers, - serve: serve, - } -} - -// RequestHeadersByNumber constructs a GetBlockHeaders function based on a numbered -// origin; associated with a particular peer in the download tester. The returned -// function can be used to retrieve batches of headers from the particular peer. -func (p *skeletonTestPeer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool, sink chan *eth.Response) (*eth.Request, error) { - // Since skeleton test peer are in-memory mocks, dropping the does not make - // them inaccessible. As such, check a local `dropped` field to see if the - // peer has been dropped and should not respond any more. - if p.dropped.Load() != 0 { - return nil, errors.New("peer already dropped") - } - // Skeleton sync retrieves batches of headers going backward without gaps. - // This ensures we can follow a clean parent progression without any reorg - // hiccups. There is no need for any other type of header retrieval, so do - // panic if there's such a request. - if !reverse || skip != 0 { - // Note, if other clients want to do these kinds of requests, it's their - // problem, it will still work. We just don't want *us* making complicated - // requests without a very strong reason to. - panic(fmt.Sprintf("invalid header retrieval: reverse %v, want true; skip %d, want 0", reverse, skip)) - } - // If the skeleton syncer requests the genesis block, panic. Whilst it could - // be considered a valid request, our code specifically should not request it - // ever since we want to link up headers to an existing local chain, which at - // worse will be the genesis. - if int64(origin)-int64(amount) < 0 { - panic(fmt.Sprintf("headers requested before (or at) genesis: origin %d, amount %d", origin, amount)) - } - // To make concurrency easier, the skeleton syncer always requests fixed size - // batches of headers. Panic if the peer is requested an amount other than the - // configured batch size (apart from the request leading to the genesis). - if amount > requestHeaders || (amount < requestHeaders && origin > uint64(amount)) { - panic(fmt.Sprintf("non-chunk size header batch requested: requested %d, want %d, origin %d", amount, requestHeaders, origin)) - } - // Simple reverse header retrieval. Fill from the peer's chain and return. - // If the tester has a serve hook set, try to use that before falling back - // to the default behavior. - var headers []*types.Header - if p.serve != nil { - headers = p.serve(origin) - } - if headers == nil { - headers = make([]*types.Header, 0, amount) - if len(p.headers) > int(origin) { // Don't serve headers if we're missing the origin - for i := 0; i < amount; i++ { - // Consider nil headers as a form of attack and withhold them. Nil - // cannot be decoded from RLP, so it's not possible to produce an - // attack by sending/receiving those over eth. - header := p.headers[int(origin)-i] - if header == nil { - continue - } - headers = append(headers, header) - } - } - } - p.served.Add(uint64(len(headers))) - - hashes := make([]common.Hash, len(headers)) - for i, header := range headers { - hashes[i] = header.Hash() - } - // Deliver the headers to the downloader - req := ð.Request{ - Peer: p.id, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockHeadersRequest)(&headers), - Meta: hashes, - Time: 1, - Done: make(chan error), - } - go func() { - sink <- res - if err := <-res.Done; err != nil { - log.Warn("Skeleton test peer response rejected", "err", err) - p.dropped.Add(1) - } - }() - return req, nil -} - -func (p *skeletonTestPeer) Head() (common.Hash, *big.Int) { - panic("skeleton sync must not request the remote head") -} - -func (p *skeletonTestPeer) RequestHeadersByHash(common.Hash, int, int, bool, chan *eth.Response) (*eth.Request, error) { - panic("skeleton sync must not request headers by hash") -} - -func (p *skeletonTestPeer) RequestBodies([]common.Hash, chan *eth.Response) (*eth.Request, error) { - panic("skeleton sync must not request block bodies") -} - -func (p *skeletonTestPeer) RequestReceipts([]common.Hash, chan *eth.Response) (*eth.Request, error) { - panic("skeleton sync must not request receipts") -} - -// Tests various sync initializations based on previous leftovers in the database -// and announced heads. -func TestSkeletonSyncInit(t *testing.T) { - // Create a few key headers - var ( - genesis = &types.Header{Number: big.NewInt(0)} - block49 = &types.Header{Number: big.NewInt(49)} - block49B = &types.Header{Number: big.NewInt(49), Extra: []byte("B")} - block50 = &types.Header{Number: big.NewInt(50), ParentHash: block49.Hash()} - ) - tests := []struct { - headers []*types.Header // Database content (beside the genesis) - oldstate []*subchain // Old sync state with various interrupted subchains - head *types.Header // New head header to announce to reorg to - newstate []*subchain // Expected sync state after the reorg - }{ - // Completely empty database with only the genesis set. The sync is expected - // to create a single subchain with the requested head. - { - head: block50, - newstate: []*subchain{{Head: 50, Tail: 50}}, - }, - // Empty database with only the genesis set with a leftover empty sync - // progress. This is a synthetic case, just for the sake of covering things. - { - oldstate: []*subchain{}, - head: block50, - newstate: []*subchain{{Head: 50, Tail: 50}}, - }, - // A single leftover subchain is present, older than the new head. The - // old subchain should be left as is and a new one appended to the sync - // status. - { - oldstate: []*subchain{{Head: 10, Tail: 5}}, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 10, Tail: 5}, - }, - }, - // Multiple leftover subchains are present, older than the new head. The - // old subchains should be left as is and a new one appended to the sync - // status. - { - oldstate: []*subchain{ - {Head: 20, Tail: 15}, - {Head: 10, Tail: 5}, - }, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 20, Tail: 15}, - {Head: 10, Tail: 5}, - }, - }, - // A single leftover subchain is present, newer than the new head. The - // newer subchain should be deleted and a fresh one created for the head. - { - oldstate: []*subchain{{Head: 65, Tail: 60}}, - head: block50, - newstate: []*subchain{{Head: 50, Tail: 50}}, - }, - // Multiple leftover subchain is present, newer than the new head. The - // newer subchains should be deleted and a fresh one created for the head. - { - oldstate: []*subchain{ - {Head: 75, Tail: 70}, - {Head: 65, Tail: 60}, - }, - head: block50, - newstate: []*subchain{{Head: 50, Tail: 50}}, - }, - - // Two leftover subchains are present, one fully older and one fully - // newer than the announced head. The head should delete the newer one, - // keeping the older one. - { - oldstate: []*subchain{ - {Head: 65, Tail: 60}, - {Head: 10, Tail: 5}, - }, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 10, Tail: 5}, - }, - }, - // Multiple leftover subchains are present, some fully older and some - // fully newer than the announced head. The head should delete the newer - // ones, keeping the older ones. - { - oldstate: []*subchain{ - {Head: 75, Tail: 70}, - {Head: 65, Tail: 60}, - {Head: 20, Tail: 15}, - {Head: 10, Tail: 5}, - }, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 20, Tail: 15}, - {Head: 10, Tail: 5}, - }, - }, - // A single leftover subchain is present and the new head is extending - // it with one more header. We expect the subchain head to be pushed - // forward. - { - headers: []*types.Header{block49}, - oldstate: []*subchain{{Head: 49, Tail: 5}}, - head: block50, - newstate: []*subchain{{Head: 50, Tail: 5}}, - }, - // A single leftover subchain is present and although the new head does - // extend it number wise, the hash chain does not link up. We expect a - // new subchain to be created for the dangling head. - { - headers: []*types.Header{block49B}, - oldstate: []*subchain{{Head: 49, Tail: 5}}, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 49, Tail: 5}, - }, - }, - // A single leftover subchain is present. A new head is announced that - // links into the middle of it, correctly anchoring into an existing - // header. We expect the old subchain to be truncated and extended with - // the new head. - { - headers: []*types.Header{block49}, - oldstate: []*subchain{{Head: 100, Tail: 5}}, - head: block50, - newstate: []*subchain{{Head: 50, Tail: 5}}, - }, - // A single leftover subchain is present. A new head is announced that - // links into the middle of it, but does not anchor into an existing - // header. We expect the old subchain to be truncated and a new chain - // be created for the dangling head. - { - headers: []*types.Header{block49B}, - oldstate: []*subchain{{Head: 100, Tail: 5}}, - head: block50, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - {Head: 49, Tail: 5}, - }, - }, - } - for i, tt := range tests { - // Create a fresh database and initialize it with the starting state - db := rawdb.NewMemoryDatabase() - - rawdb.WriteHeader(db, genesis) - for _, header := range tt.headers { - rawdb.WriteSkeletonHeader(db, header) - } - if tt.oldstate != nil { - blob, _ := json.Marshal(&skeletonProgress{Subchains: tt.oldstate}) - rawdb.WriteSkeletonSyncStatus(db, blob) - } - // Create a skeleton sync and run a cycle - wait := make(chan struct{}) - - skeleton := newSkeleton(db, newPeerSet(), nil, newHookedBackfiller()) - skeleton.syncStarting = func() { close(wait) } - skeleton.Sync(tt.head, nil, true) - - <-wait - skeleton.Terminate() - - // Ensure the correct resulting sync status - var progress skeletonProgress - json.Unmarshal(rawdb.ReadSkeletonSyncStatus(db), &progress) - - if len(progress.Subchains) != len(tt.newstate) { - t.Errorf("test %d: subchain count mismatch: have %d, want %d", i, len(progress.Subchains), len(tt.newstate)) - continue - } - for j := 0; j < len(progress.Subchains); j++ { - if progress.Subchains[j].Head != tt.newstate[j].Head { - t.Errorf("test %d: subchain %d head mismatch: have %d, want %d", i, j, progress.Subchains[j].Head, tt.newstate[j].Head) - } - if progress.Subchains[j].Tail != tt.newstate[j].Tail { - t.Errorf("test %d: subchain %d tail mismatch: have %d, want %d", i, j, progress.Subchains[j].Tail, tt.newstate[j].Tail) - } - } - } -} - -// Tests that a running skeleton sync can be extended with properly linked up -// headers but not with side chains. -func TestSkeletonSyncExtend(t *testing.T) { - // Create a few key headers - var ( - genesis = &types.Header{Number: big.NewInt(0)} - block49 = &types.Header{Number: big.NewInt(49)} - block49B = &types.Header{Number: big.NewInt(49), Extra: []byte("B")} - block50 = &types.Header{Number: big.NewInt(50), ParentHash: block49.Hash()} - block51 = &types.Header{Number: big.NewInt(51), ParentHash: block50.Hash()} - ) - tests := []struct { - head *types.Header // New head header to announce to reorg to - extend *types.Header // New head header to announce to extend with - newstate []*subchain // Expected sync state after the reorg - err error // Whether extension succeeds or not - }{ - // Initialize a sync and try to extend it with a subsequent block. - { - head: block49, - extend: block50, - newstate: []*subchain{ - {Head: 50, Tail: 49}, - }, - }, - // Initialize a sync and try to extend it with the existing head block. - { - head: block49, - extend: block49, - newstate: []*subchain{ - {Head: 49, Tail: 49}, - }, - }, - // Initialize a sync and try to extend it with a sibling block. - { - head: block49, - extend: block49B, - newstate: []*subchain{ - {Head: 49, Tail: 49}, - }, - err: errChainReorged, - }, - // Initialize a sync and try to extend it with a number-wise sequential - // header, but a hash wise non-linking one. - { - head: block49B, - extend: block50, - newstate: []*subchain{ - {Head: 49, Tail: 49}, - }, - err: errChainForked, - }, - // Initialize a sync and try to extend it with a non-linking future block. - { - head: block49, - extend: block51, - newstate: []*subchain{ - {Head: 49, Tail: 49}, - }, - err: errChainGapped, - }, - // Initialize a sync and try to extend it with a past canonical block. - { - head: block50, - extend: block49, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - }, - err: errChainReorged, - }, - // Initialize a sync and try to extend it with a past sidechain block. - { - head: block50, - extend: block49B, - newstate: []*subchain{ - {Head: 50, Tail: 50}, - }, - err: errChainReorged, - }, - } - for i, tt := range tests { - // Create a fresh database and initialize it with the starting state - db := rawdb.NewMemoryDatabase() - rawdb.WriteHeader(db, genesis) - - // Create a skeleton sync and run a cycle - wait := make(chan struct{}) - - skeleton := newSkeleton(db, newPeerSet(), nil, newHookedBackfiller()) - skeleton.syncStarting = func() { close(wait) } - skeleton.Sync(tt.head, nil, true) - - <-wait - if err := skeleton.Sync(tt.extend, nil, false); !errors.Is(err, tt.err) { - t.Errorf("test %d: extension failure mismatch: have %v, want %v", i, err, tt.err) - } - skeleton.Terminate() - - // Ensure the correct resulting sync status - var progress skeletonProgress - json.Unmarshal(rawdb.ReadSkeletonSyncStatus(db), &progress) - - if len(progress.Subchains) != len(tt.newstate) { - t.Errorf("test %d: subchain count mismatch: have %d, want %d", i, len(progress.Subchains), len(tt.newstate)) - continue - } - for j := 0; j < len(progress.Subchains); j++ { - if progress.Subchains[j].Head != tt.newstate[j].Head { - t.Errorf("test %d: subchain %d head mismatch: have %d, want %d", i, j, progress.Subchains[j].Head, tt.newstate[j].Head) - } - if progress.Subchains[j].Tail != tt.newstate[j].Tail { - t.Errorf("test %d: subchain %d tail mismatch: have %d, want %d", i, j, progress.Subchains[j].Tail, tt.newstate[j].Tail) - } - } - } -} - -// Tests that the skeleton sync correctly retrieves headers from one or more -// peers without duplicates or other strange side effects. -func TestSkeletonSyncRetrievals(t *testing.T) { - //log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - - // Since skeleton headers don't need to be meaningful, beyond a parent hash - // progression, create a long fake chain to test with. - chain := []*types.Header{{Number: big.NewInt(0)}} - for i := 1; i < 10000; i++ { - chain = append(chain, &types.Header{ - ParentHash: chain[i-1].Hash(), - Number: big.NewInt(int64(i)), - }) - } - // Some tests require a forking side chain to trigger cornercases. - var sidechain []*types.Header - for i := 0; i < len(chain)/2; i++ { // Fork at block #5000 - sidechain = append(sidechain, chain[i]) - } - for i := len(chain) / 2; i < len(chain); i++ { - sidechain = append(sidechain, &types.Header{ - ParentHash: sidechain[i-1].Hash(), - Number: big.NewInt(int64(i)), - Extra: []byte("B"), // force a different hash - }) - } - tests := []struct { - fill bool // Whether to run a real backfiller in this test case - unpredictable bool // Whether to ignore drops/serves due to uncertain packet assignments - - head *types.Header // New head header to announce to reorg to - peers []*skeletonTestPeer // Initial peer set to start the sync with - midstate []*subchain // Expected sync state after initial cycle - midserve uint64 // Expected number of header retrievals after initial cycle - middrop uint64 // Expected number of peers dropped after initial cycle - - newHead *types.Header // New header to anoint on top of the old one - newPeer *skeletonTestPeer // New peer to join the skeleton syncer - endstate []*subchain // Expected sync state after the post-init event - endserve uint64 // Expected number of header retrievals after the post-init event - enddrop uint64 // Expected number of peers dropped after the post-init event - }{ - // Completely empty database with only the genesis set. The sync is expected - // to create a single subchain with the requested head. No peers however, so - // the sync should be stuck without any progression. - // - // When a new peer is added, it should detect the join and fill the headers - // to the genesis block. - { - head: chain[len(chain)-1], - midstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: uint64(len(chain) - 1)}}, - - newPeer: newSkeletonTestPeer("test-peer", chain), - endstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: 1}}, - endserve: uint64(len(chain) - 2), // len - head - genesis - }, - // Completely empty database with only the genesis set. The sync is expected - // to create a single subchain with the requested head. With one valid peer, - // the sync is expected to complete already in the initial round. - // - // Adding a second peer should not have any effect. - { - head: chain[len(chain)-1], - peers: []*skeletonTestPeer{newSkeletonTestPeer("test-peer-1", chain)}, - midstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: 1}}, - midserve: uint64(len(chain) - 2), // len - head - genesis - - newPeer: newSkeletonTestPeer("test-peer-2", chain), - endstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: 1}}, - endserve: uint64(len(chain) - 2), // len - head - genesis - }, - // Completely empty database with only the genesis set. The sync is expected - // to create a single subchain with the requested head. With many valid peers, - // the sync is expected to complete already in the initial round. - // - // Adding a new peer should not have any effect. - { - head: chain[len(chain)-1], - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("test-peer-1", chain), - newSkeletonTestPeer("test-peer-2", chain), - newSkeletonTestPeer("test-peer-3", chain), - }, - midstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: 1}}, - midserve: uint64(len(chain) - 2), // len - head - genesis - - newPeer: newSkeletonTestPeer("test-peer-4", chain), - endstate: []*subchain{{Head: uint64(len(chain) - 1), Tail: 1}}, - endserve: uint64(len(chain) - 2), // len - head - genesis - }, - // This test checks if a peer tries to withhold a header - *on* the sync - // boundary - instead of sending the requested amount. The malicious short - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-skipper", append(append(append([]*types.Header{}, chain[:99]...), nil), chain[100:]...)), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 3, // len - head - genesis - missing - middrop: 1, // penalize shortened header deliveries - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 3) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test checks if a peer tries to withhold a header - *off* the sync - // boundary - instead of sending the requested amount. The malicious short - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-skipper", append(append(append([]*types.Header{}, chain[:50]...), nil), chain[51:]...)), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 3, // len - head - genesis - missing - middrop: 1, // penalize shortened header deliveries - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 3) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test checks if a peer tries to duplicate a header - *on* the sync - // boundary - instead of sending the correct sequence. The malicious duped - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], // We want to force the 100th header to be a request boundary - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-duper", append(append(append([]*types.Header{}, chain[:99]...), chain[98]), chain[100:]...)), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 2, // len - head - genesis - middrop: 1, // penalize invalid header sequences - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 2) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test checks if a peer tries to duplicate a header - *off* the sync - // boundary - instead of sending the correct sequence. The malicious duped - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], // We want to force the 100th header to be a request boundary - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-duper", append(append(append([]*types.Header{}, chain[:50]...), chain[49]), chain[51:]...)), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 2, // len - head - genesis - middrop: 1, // penalize invalid header sequences - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 2) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test checks if a peer tries to inject a different header - *on* - // the sync boundary - instead of sending the correct sequence. The bad - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], // We want to force the 100th header to be a request boundary - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-changer", - append( - append( - append([]*types.Header{}, chain[:99]...), - &types.Header{ - ParentHash: chain[98].Hash(), - Number: big.NewInt(int64(99)), - GasLimit: 1, - }, - ), chain[100:]..., - ), - ), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 2, // len - head - genesis - middrop: 1, // different set of headers, drop // TODO(karalabe): maybe just diff sync? - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 2) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test checks if a peer tries to inject a different header - *off* - // the sync boundary - instead of sending the correct sequence. The bad - // package should not be accepted. - // - // Joining with a new peer should however unblock the sync. - { - head: chain[requestHeaders+100], // We want to force the 100th header to be a request boundary - peers: []*skeletonTestPeer{ - newSkeletonTestPeer("header-changer", - append( - append( - append([]*types.Header{}, chain[:50]...), - &types.Header{ - ParentHash: chain[49].Hash(), - Number: big.NewInt(int64(50)), - GasLimit: 1, - }, - ), chain[51:]..., - ), - ), - }, - midstate: []*subchain{{Head: requestHeaders + 100, Tail: 100}}, - midserve: requestHeaders + 101 - 2, // len - head - genesis - middrop: 1, // different set of headers, drop - - newPeer: newSkeletonTestPeer("good-peer", chain), - endstate: []*subchain{{Head: requestHeaders + 100, Tail: 1}}, - endserve: (requestHeaders + 101 - 2) + (100 - 1), // midserve + lenrest - genesis - enddrop: 1, // no new drops - }, - // This test reproduces a bug caught during review (kudos to @holiman) - // where a subchain is merged with a previously interrupted one, causing - // pending data in the scratch space to become "invalid" (since we jump - // ahead during subchain merge). In that case it is expected to ignore - // the queued up data instead of trying to process on top of a shifted - // task set. - // - // The test is a bit convoluted since it needs to trigger a concurrency - // issue. First we sync up an initial chain of 2x512 items. Then announce - // 2x512+2 as head and delay delivering the head batch to fill the scratch - // space first. The delivery head should merge with the previous download - // and the scratch space must not be consumed further. - { - head: chain[2*requestHeaders], - peers: []*skeletonTestPeer{ - newSkeletonTestPeerWithHook("peer-1", chain, func(origin uint64) []*types.Header { - if origin == chain[2*requestHeaders+1].Number.Uint64() { - time.Sleep(100 * time.Millisecond) - } - return nil // Fallback to default behavior, just delayed - }), - newSkeletonTestPeerWithHook("peer-2", chain, func(origin uint64) []*types.Header { - if origin == chain[2*requestHeaders+1].Number.Uint64() { - time.Sleep(100 * time.Millisecond) - } - return nil // Fallback to default behavior, just delayed - }), - }, - midstate: []*subchain{{Head: 2 * requestHeaders, Tail: 1}}, - midserve: 2*requestHeaders - 1, // len - head - genesis - - newHead: chain[2*requestHeaders+2], - endstate: []*subchain{{Head: 2*requestHeaders + 2, Tail: 1}}, - endserve: 4 * requestHeaders, - }, - // This test reproduces a bug caught by (@rjl493456442) where a skeleton - // header goes missing, causing the sync to get stuck and/or panic. - // - // The setup requires a previously successfully synced chain up to a block - // height N. That results is a single skeleton header (block N) and a single - // subchain (head N, Tail N) being stored on disk. - // - // The following step requires a new sync cycle to a new side chain of a - // height higher than N, and an ancestor lower than N (e.g. N-2, N+2). - // In this scenario, when processing a batch of headers, a link point of - // N-2 will be found, meaning that N-1 and N have been overwritten. - // - // The link event triggers an early exit, noticing that the previous sub- - // chain is a leftover and deletes it (with it's skeleton header N). But - // since skeleton header N has been overwritten to the new side chain, we - // end up losing it and creating a gap. - { - fill: true, - unpredictable: true, // We have good and bad peer too, bad may be dropped, test too short for certainty - - head: chain[len(chain)/2+1], // Sync up until the sidechain common ancestor + 2 - peers: []*skeletonTestPeer{newSkeletonTestPeer("test-peer-oldchain", chain)}, - midstate: []*subchain{{Head: uint64(len(chain)/2 + 1), Tail: 1}}, - - newHead: sidechain[len(sidechain)/2+3], // Sync up until the sidechain common ancestor + 4 - newPeer: newSkeletonTestPeer("test-peer-newchain", sidechain), - endstate: []*subchain{{Head: uint64(len(sidechain)/2 + 3), Tail: uint64(len(chain) / 2)}}, - }, - } - for i, tt := range tests { - // Create a fresh database and initialize it with the starting state - db := rawdb.NewMemoryDatabase() - - rawdb.WriteBlock(db, types.NewBlockWithHeader(chain[0])) - rawdb.WriteReceipts(db, chain[0].Hash(), chain[0].Number.Uint64(), types.Receipts{}) - - // Create a peer set to feed headers through - peerset := newPeerSet() - for _, peer := range tt.peers { - peerset.Register(newPeerConnection(peer.id, eth.ETH68, peer, log.New("id", peer.id))) - } - // Create a peer dropper to track malicious peers - dropped := make(map[string]int) - drop := func(peer string) { - if p := peerset.Peer(peer); p != nil { - p.peer.(*skeletonTestPeer).dropped.Add(1) - } - peerset.Unregister(peer) - dropped[peer]++ - } - // Create a backfiller if we need to run more advanced tests - filler := newHookedBackfiller() - if tt.fill { - var filled *types.Header - - filler = &hookedBackfiller{ - resumeHook: func() { - var progress skeletonProgress - json.Unmarshal(rawdb.ReadSkeletonSyncStatus(db), &progress) - - for progress.Subchains[0].Tail < progress.Subchains[0].Head { - header := rawdb.ReadSkeletonHeader(db, progress.Subchains[0].Tail) - - rawdb.WriteBlock(db, types.NewBlockWithHeader(header)) - rawdb.WriteReceipts(db, header.Hash(), header.Number.Uint64(), types.Receipts{}) - - rawdb.DeleteSkeletonHeader(db, header.Number.Uint64()) - - progress.Subchains[0].Tail++ - progress.Subchains[0].Next = header.Hash() - } - filled = rawdb.ReadSkeletonHeader(db, progress.Subchains[0].Tail) - - rawdb.WriteBlock(db, types.NewBlockWithHeader(filled)) - rawdb.WriteReceipts(db, filled.Hash(), filled.Number.Uint64(), types.Receipts{}) - }, - - suspendHook: func() *types.Header { - prev := filled - filled = nil - - return prev - }, - } - } - // Create a skeleton sync and run a cycle - skeleton := newSkeleton(db, peerset, drop, filler) - skeleton.Sync(tt.head, nil, true) - - var progress skeletonProgress - // Wait a bit (bleah) for the initial sync loop to go to idle. This might - // be either a finish or a never-start hence why there's no event to hook. - check := func() error { - if len(progress.Subchains) != len(tt.midstate) { - return fmt.Errorf("test %d, mid state: subchain count mismatch: have %d, want %d", i, len(progress.Subchains), len(tt.midstate)) - } - for j := 0; j < len(progress.Subchains); j++ { - if progress.Subchains[j].Head != tt.midstate[j].Head { - return fmt.Errorf("test %d, mid state: subchain %d head mismatch: have %d, want %d", i, j, progress.Subchains[j].Head, tt.midstate[j].Head) - } - if progress.Subchains[j].Tail != tt.midstate[j].Tail { - return fmt.Errorf("test %d, mid state: subchain %d tail mismatch: have %d, want %d", i, j, progress.Subchains[j].Tail, tt.midstate[j].Tail) - } - } - return nil - } - - waitStart := time.Now() - for waitTime := 20 * time.Millisecond; time.Since(waitStart) < 2*time.Second; waitTime = waitTime * 2 { - time.Sleep(waitTime) - // Check the post-init end state if it matches the required results - json.Unmarshal(rawdb.ReadSkeletonSyncStatus(db), &progress) - if err := check(); err == nil { - break - } - } - if err := check(); err != nil { - t.Error(err) - continue - } - if !tt.unpredictable { - var served uint64 - for _, peer := range tt.peers { - served += peer.served.Load() - } - if served != tt.midserve { - t.Errorf("test %d, mid state: served headers mismatch: have %d, want %d", i, served, tt.midserve) - } - var drops uint64 - for _, peer := range tt.peers { - drops += peer.dropped.Load() - } - if drops != tt.middrop { - t.Errorf("test %d, mid state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop) - } - } - // Apply the post-init events if there's any - if tt.newHead != nil { - skeleton.Sync(tt.newHead, nil, true) - } - if tt.newPeer != nil { - if err := peerset.Register(newPeerConnection(tt.newPeer.id, eth.ETH68, tt.newPeer, log.New("id", tt.newPeer.id))); err != nil { - t.Errorf("test %d: failed to register new peer: %v", i, err) - } - } - // Wait a bit (bleah) for the second sync loop to go to idle. This might - // be either a finish or a never-start hence why there's no event to hook. - check = func() error { - if len(progress.Subchains) != len(tt.endstate) { - return fmt.Errorf("test %d, end state: subchain count mismatch: have %d, want %d", i, len(progress.Subchains), len(tt.endstate)) - } - for j := 0; j < len(progress.Subchains); j++ { - if progress.Subchains[j].Head != tt.endstate[j].Head { - return fmt.Errorf("test %d, end state: subchain %d head mismatch: have %d, want %d", i, j, progress.Subchains[j].Head, tt.endstate[j].Head) - } - if progress.Subchains[j].Tail != tt.endstate[j].Tail { - return fmt.Errorf("test %d, end state: subchain %d tail mismatch: have %d, want %d", i, j, progress.Subchains[j].Tail, tt.endstate[j].Tail) - } - } - return nil - } - waitStart = time.Now() - for waitTime := 20 * time.Millisecond; time.Since(waitStart) < 2*time.Second; waitTime = waitTime * 2 { - time.Sleep(waitTime) - // Check the post-init end state if it matches the required results - json.Unmarshal(rawdb.ReadSkeletonSyncStatus(db), &progress) - if err := check(); err == nil { - break - } - } - if err := check(); err != nil { - t.Error(err) - continue - } - // Check that the peers served no more headers than we actually needed - if !tt.unpredictable { - served := uint64(0) - for _, peer := range tt.peers { - served += peer.served.Load() - } - if tt.newPeer != nil { - served += tt.newPeer.served.Load() - } - if served != tt.endserve { - t.Errorf("test %d, end state: served headers mismatch: have %d, want %d", i, served, tt.endserve) - } - drops := uint64(0) - for _, peer := range tt.peers { - drops += peer.dropped.Load() - } - if tt.newPeer != nil { - drops += tt.newPeer.dropped.Load() - } - if drops != tt.enddrop { - t.Errorf("test %d, end state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop) - } - } - // Clean up any leftover skeleton sync resources - skeleton.Terminate() - } -} diff --git a/builder/eth/downloader/statesync.go b/builder/eth/downloader/statesync.go deleted file mode 100644 index 501af63ed..000000000 --- a/builder/eth/downloader/statesync.go +++ /dev/null @@ -1,123 +0,0 @@ -// 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 downloader - -import ( - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" -) - -// syncState starts downloading state with the given root hash. -func (d *Downloader) syncState(root common.Hash) *stateSync { - // Create the state sync - s := newStateSync(d, root) - select { - case d.stateSyncStart <- s: - // If we tell the statesync to restart with a new root, we also need - // to wait for it to actually also start -- when old requests have timed - // out or been delivered - <-s.started - case <-d.quitCh: - s.err = errCancelStateFetch - close(s.done) - } - return s -} - -// stateFetcher manages the active state sync and accepts requests -// on its behalf. -func (d *Downloader) stateFetcher() { - for { - select { - case s := <-d.stateSyncStart: - for next := s; next != nil; { - next = d.runStateSync(next) - } - case <-d.quitCh: - return - } - } -} - -// runStateSync runs a state synchronisation until it completes or another root -// hash is requested to be switched over to. -func (d *Downloader) runStateSync(s *stateSync) *stateSync { - log.Trace("State sync starting", "root", s.root) - - go s.run() - defer s.Cancel() - - for { - select { - case next := <-d.stateSyncStart: - return next - - case <-s.done: - return nil - } - } -} - -// stateSync schedules requests for downloading a particular state trie defined -// by a given state root. -type stateSync struct { - d *Downloader // Downloader instance to access and manage current peerset - root common.Hash // State root currently being synced - - started chan struct{} // Started is signalled once the sync loop starts - cancel chan struct{} // Channel to signal a termination request - cancelOnce sync.Once // Ensures cancel only ever gets called once - done chan struct{} // Channel to signal termination completion - err error // Any error hit during sync (set before completion) -} - -// newStateSync creates a new state trie download scheduler. This method does not -// yet start the sync. The user needs to call run to initiate. -func newStateSync(d *Downloader, root common.Hash) *stateSync { - return &stateSync{ - d: d, - root: root, - cancel: make(chan struct{}), - done: make(chan struct{}), - started: make(chan struct{}), - } -} - -// run starts the task assignment and response processing loop, blocking until -// it finishes, and finally notifying any goroutines waiting for the loop to -// finish. -func (s *stateSync) run() { - close(s.started) - s.err = s.d.SnapSyncer.Sync(s.root, s.cancel) - close(s.done) -} - -// Wait blocks until the sync is done or canceled. -func (s *stateSync) Wait() error { - <-s.done - return s.err -} - -// Cancel cancels the sync and waits until it has shut down. -func (s *stateSync) Cancel() error { - s.cancelOnce.Do(func() { - close(s.cancel) - }) - return s.Wait() -} diff --git a/builder/eth/downloader/testchain_test.go b/builder/eth/downloader/testchain_test.go deleted file mode 100644 index 46f3febd8..000000000 --- a/builder/eth/downloader/testchain_test.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2018 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 downloader - -import ( - "fmt" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/triedb" -) - -// Test chain parameters. -var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddress = crypto.PubkeyToAddress(testKey.PublicKey) - testDB = rawdb.NewMemoryDatabase() - - testGspec = &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults)) -) - -// The common prefix of all test chains: -var testChainBase *testChain - -// Different forks on top of the base chain: -var testChainForkLightA, testChainForkLightB, testChainForkHeavy *testChain - -var pregenerated bool - -func init() { - // Reduce some of the parameters to make the tester faster - fullMaxForkAncestry = 10000 - lightMaxForkAncestry = 10000 - blockCacheMaxItems = 1024 - fsHeaderSafetyNet = 256 - fsHeaderContCheck = 500 * time.Millisecond - - testChainBase = newTestChain(blockCacheMaxItems+200, testGenesis) - - var forkLen = int(fullMaxForkAncestry + 50) - var wg sync.WaitGroup - - // Generate the test chains to seed the peers with - wg.Add(3) - go func() { testChainForkLightA = testChainBase.makeFork(forkLen, false, 1); wg.Done() }() - go func() { testChainForkLightB = testChainBase.makeFork(forkLen, false, 2); wg.Done() }() - go func() { testChainForkHeavy = testChainBase.makeFork(forkLen, true, 3); wg.Done() }() - wg.Wait() - - // Generate the test peers used by the tests to avoid overloading during testing. - // These seemingly random chains are used in various downloader tests. We're just - // pre-generating them here. - chains := []*testChain{ - testChainBase, - testChainForkLightA, - testChainForkLightB, - testChainForkHeavy, - testChainBase.shorten(1), - testChainBase.shorten(blockCacheMaxItems - 15), - testChainBase.shorten((blockCacheMaxItems - 15) / 2), - testChainBase.shorten(blockCacheMaxItems - 15 - 5), - testChainBase.shorten(MaxHeaderFetch), - testChainBase.shorten(800), - testChainBase.shorten(800 / 2), - testChainBase.shorten(800 / 3), - testChainBase.shorten(800 / 4), - testChainBase.shorten(800 / 5), - testChainBase.shorten(800 / 6), - testChainBase.shorten(800 / 7), - testChainBase.shorten(800 / 8), - testChainBase.shorten(3*fsHeaderSafetyNet + 256 + fsMinFullBlocks), - testChainBase.shorten(fsMinFullBlocks + 256 - 1), - testChainForkLightA.shorten(len(testChainBase.blocks) + 80), - testChainForkLightB.shorten(len(testChainBase.blocks) + 81), - testChainForkLightA.shorten(len(testChainBase.blocks) + MaxHeaderFetch), - testChainForkLightB.shorten(len(testChainBase.blocks) + MaxHeaderFetch), - testChainForkHeavy.shorten(len(testChainBase.blocks) + 79), - } - wg.Add(len(chains)) - for _, chain := range chains { - go func(blocks []*types.Block) { - newTestBlockchain(blocks) - wg.Done() - }(chain.blocks[1:]) - } - wg.Wait() - - // Mark the chains pregenerated. Generating a new one will lead to a panic. - pregenerated = true -} - -type testChain struct { - blocks []*types.Block -} - -// newTestChain creates a blockchain of the given length. -func newTestChain(length int, genesis *types.Block) *testChain { - tc := &testChain{ - blocks: []*types.Block{genesis}, - } - tc.generate(length-1, 0, genesis, false) - return tc -} - -// makeFork creates a fork on top of the test chain. -func (tc *testChain) makeFork(length int, heavy bool, seed byte) *testChain { - fork := tc.copy(len(tc.blocks) + length) - fork.generate(length, seed, tc.blocks[len(tc.blocks)-1], heavy) - return fork -} - -// shorten creates a copy of the chain with the given length. It panics if the -// length is longer than the number of available blocks. -func (tc *testChain) shorten(length int) *testChain { - if length > len(tc.blocks) { - panic(fmt.Errorf("can't shorten test chain to %d blocks, it's only %d blocks long", length, len(tc.blocks))) - } - return tc.copy(length) -} - -func (tc *testChain) copy(newlen int) *testChain { - if newlen > len(tc.blocks) { - newlen = len(tc.blocks) - } - cpy := &testChain{ - blocks: append([]*types.Block{}, tc.blocks[:newlen]...), - } - return cpy -} - -// generate creates a chain of n blocks starting at and including parent. -// the returned hash chain is ordered head->parent. In addition, every 22th block -// contains a transaction and every 5th an uncle to allow testing correct block -// reassembly. -func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) { - blocks, _ := core.GenerateChain(testGspec.Config, parent, ethash.NewFaker(), testDB, n, func(i int, block *core.BlockGen) { - block.SetCoinbase(common.Address{seed}) - // If a heavy chain is requested, delay blocks to raise difficulty - if heavy { - block.OffsetTime(-9) - } - // Include transactions to the miner to make blocks more interesting. - if parent == tc.blocks[0] && i%22 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) - tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) - if err != nil { - panic(err) - } - block.AddTx(tx) - } - // if the block number is a multiple of 5, add a bonus uncle to the block - if i > 0 && i%5 == 0 { - block.AddUncle(&types.Header{ - ParentHash: block.PrevBlock(i - 2).Hash(), - Number: big.NewInt(block.Number().Int64() - 1), - }) - } - }) - tc.blocks = append(tc.blocks, blocks...) -} - -var ( - testBlockchains = make(map[common.Hash]*testBlockchain) - testBlockchainsLock sync.Mutex -) - -type testBlockchain struct { - chain *core.BlockChain - gen sync.Once -} - -// newTestBlockchain creates a blockchain database built by running the given blocks, -// either actually running them, or reusing a previously created one. The returned -// chains are *shared*, so *do not* mutate them. -func newTestBlockchain(blocks []*types.Block) *core.BlockChain { - // Retrieve an existing database, or create a new one - head := testGenesis.Hash() - if len(blocks) > 0 { - head = blocks[len(blocks)-1].Hash() - } - testBlockchainsLock.Lock() - if _, ok := testBlockchains[head]; !ok { - testBlockchains[head] = new(testBlockchain) - } - tbc := testBlockchains[head] - testBlockchainsLock.Unlock() - - // Ensure that the database is generated - tbc.gen.Do(func() { - if pregenerated { - panic("Requested chain generation outside of init") - } - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, testGspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if err != nil { - panic(err) - } - if n, err := chain.InsertChain(blocks); err != nil { - panic(fmt.Sprintf("block %d: %v", n, err)) - } - tbc.chain = chain - }) - return tbc.chain -} diff --git a/builder/eth/ethconfig/config.go b/builder/eth/ethconfig/config.go deleted file mode 100644 index ad664afb5..000000000 --- a/builder/eth/ethconfig/config.go +++ /dev/null @@ -1,179 +0,0 @@ -// 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 ethconfig contains the configuration of the ETH and LES protocols. -package ethconfig - -import ( - "errors" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/clique" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool/blobpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/params" -) - -// FullNodeGPO contains default gasprice oracle settings for full node. -var FullNodeGPO = gasprice.Config{ - Blocks: 20, - Percentile: 60, - MaxHeaderHistory: 1024, - MaxBlockHistory: 1024, - MaxPrice: gasprice.DefaultMaxPrice, - IgnorePrice: gasprice.DefaultIgnorePrice, -} - -// Defaults contains default settings for use on the Ethereum main net. -var Defaults = Config{ - SyncMode: downloader.SnapSync, - NetworkId: 0, // enable auto configuration of networkID == chainID - TxLookupLimit: 2350000, - TransactionHistory: 2350000, - StateHistory: params.FullImmutabilityThreshold, - LightPeers: 100, - DatabaseCache: 512, - TrieCleanCache: 154, - TrieDirtyCache: 256, - TrieTimeout: 60 * time.Minute, - SnapshotCache: 102, - FilterLogCacheSize: 32, - Miner: miner.DefaultConfig, - TxPool: legacypool.DefaultConfig, - BlobPool: blobpool.DefaultConfig, - RPCGasCap: 50000000, - RPCEVMTimeout: 5 * time.Second, - GPO: FullNodeGPO, - RPCTxFeeCap: 1, // 1 ether -} - -//go:generate go run github.com/fjl/gencodec -type Config -formats toml -out gen_config.go - -// Config contains configuration options for ETH and LES protocols. -type Config struct { - // The genesis block, which is inserted if the database is empty. - // If nil, the Ethereum main net block is used. - Genesis *core.Genesis `toml:",omitempty"` - - // Network ID separates blockchains on the peer-to-peer networking level. When left - // zero, the chain ID is used as network ID. - NetworkId uint64 - SyncMode downloader.SyncMode - - // This can be set to list of enrtree:// URLs which will be queried for - // for nodes to connect to. - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - - NoPruning bool // Whether to disable pruning and flush everything to disk - NoPrefetch bool // Whether to disable prefetching and only load state on demand - - // Deprecated, use 'TransactionHistory' instead. - TxLookupLimit uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. - TransactionHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose tx indices are reserved. - StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved. - - // State scheme represents the scheme used to store ethereum states and trie - // nodes on top. It can be 'hash', 'path', or none which means use the scheme - // consistent with persistent state. - StateScheme string `toml:",omitempty"` - - // RequiredBlocks is a set of block number -> hash mappings which must be in the - // canonical chain of all remote peers. Setting the option makes geth verify the - // presence of these blocks for every new peer connection. - RequiredBlocks map[uint64]common.Hash `toml:"-"` - - // Light client options - LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests - LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers - LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers - LightPeers int `toml:",omitempty"` // Maximum number of LES client peers - LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning - LightNoSyncServe bool `toml:",omitempty"` // Whether to serve light clients before syncing - - // Database options - SkipBcVersionCheck bool `toml:"-"` - DatabaseHandles int `toml:"-"` - DatabaseCache int - DatabaseFreezer string - - TrieCleanCache int - TrieDirtyCache int - TrieTimeout time.Duration - SnapshotCache int - Preimages bool - - // This is the number of blocks for which logs will be cached in the filter system. - FilterLogCacheSize int - - // Mining options - Miner miner.Config - - // Transaction pool options - TxPool legacypool.Config - BlobPool blobpool.Config - - // Gas Price Oracle options - GPO gasprice.Config - - // Enables tracking of SHA3 preimages in the VM - EnablePreimageRecording bool - - // Miscellaneous options - DocRoot string `toml:"-"` - - // RPCGasCap is the global gas cap for eth-call variants. - RPCGasCap uint64 - - // RPCEVMTimeout is the global timeout for eth-call. - RPCEVMTimeout time.Duration - - // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for - // send-transaction variants. The unit is ether. - RPCTxFeeCap float64 - - // OverrideCancun (TODO: remove after the fork) - OverrideCancun *uint64 `toml:",omitempty"` - - // OverrideVerkle (TODO: remove after the fork) - OverrideVerkle *uint64 `toml:",omitempty"` -} - -// CreateConsensusEngine creates a consensus engine for the given chain config. -// Clique is allowed for now to live standalone, but ethash is forbidden and can -// only exist on already merged networks. -func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) { - // If proof-of-authority is requested, set it up - if config.Clique != nil { - return beacon.New(clique.New(config.Clique, db)), nil - } - // If defaulting to proof-of-work, enforce an already merged network since - // we cannot run PoW algorithms anymore, so we cannot even follow a chain - // not coordinated by a beacon node. - if !config.TerminalTotalDifficultyPassed { - return nil, errors.New("ethash is only supported as a historical component of already merged networks") - } - return beacon.New(ethash.NewFaker()), nil -} diff --git a/builder/eth/ethconfig/gen_config.go b/builder/eth/ethconfig/gen_config.go deleted file mode 100644 index 2abddc9e0..000000000 --- a/builder/eth/ethconfig/gen_config.go +++ /dev/null @@ -1,268 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package ethconfig - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool/blobpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/gasprice" - "github.com/ethereum/go-ethereum/miner" -) - -// MarshalTOML marshals as TOML. -func (c Config) MarshalTOML() (interface{}, error) { - type Config struct { - Genesis *core.Genesis `toml:",omitempty"` - NetworkId uint64 - SyncMode downloader.SyncMode - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - NoPruning bool - NoPrefetch bool - TxLookupLimit uint64 `toml:",omitempty"` - TransactionHistory uint64 `toml:",omitempty"` - StateHistory uint64 `toml:",omitempty"` - StateScheme string `toml:",omitempty"` - RequiredBlocks map[uint64]common.Hash `toml:"-"` - LightServ int `toml:",omitempty"` - LightIngress int `toml:",omitempty"` - LightEgress int `toml:",omitempty"` - LightPeers int `toml:",omitempty"` - LightNoPrune bool `toml:",omitempty"` - LightNoSyncServe bool `toml:",omitempty"` - SkipBcVersionCheck bool `toml:"-"` - DatabaseHandles int `toml:"-"` - DatabaseCache int - DatabaseFreezer string - TrieCleanCache int - TrieDirtyCache int - TrieTimeout time.Duration - SnapshotCache int - Preimages bool - FilterLogCacheSize int - Miner miner.Config - TxPool legacypool.Config - BlobPool blobpool.Config - GPO gasprice.Config - EnablePreimageRecording bool - DocRoot string `toml:"-"` - RPCGasCap uint64 - RPCEVMTimeout time.Duration - RPCTxFeeCap float64 - OverrideCancun *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` - } - var enc Config - enc.Genesis = c.Genesis - enc.NetworkId = c.NetworkId - enc.SyncMode = c.SyncMode - enc.EthDiscoveryURLs = c.EthDiscoveryURLs - enc.SnapDiscoveryURLs = c.SnapDiscoveryURLs - enc.NoPruning = c.NoPruning - enc.NoPrefetch = c.NoPrefetch - enc.TxLookupLimit = c.TxLookupLimit - enc.TransactionHistory = c.TransactionHistory - enc.StateHistory = c.StateHistory - enc.StateScheme = c.StateScheme - enc.RequiredBlocks = c.RequiredBlocks - enc.LightServ = c.LightServ - enc.LightIngress = c.LightIngress - enc.LightEgress = c.LightEgress - enc.LightPeers = c.LightPeers - enc.LightNoPrune = c.LightNoPrune - enc.LightNoSyncServe = c.LightNoSyncServe - enc.SkipBcVersionCheck = c.SkipBcVersionCheck - enc.DatabaseHandles = c.DatabaseHandles - enc.DatabaseCache = c.DatabaseCache - enc.DatabaseFreezer = c.DatabaseFreezer - enc.TrieCleanCache = c.TrieCleanCache - enc.TrieDirtyCache = c.TrieDirtyCache - enc.TrieTimeout = c.TrieTimeout - enc.SnapshotCache = c.SnapshotCache - enc.Preimages = c.Preimages - enc.FilterLogCacheSize = c.FilterLogCacheSize - enc.Miner = c.Miner - enc.TxPool = c.TxPool - enc.BlobPool = c.BlobPool - enc.GPO = c.GPO - enc.EnablePreimageRecording = c.EnablePreimageRecording - enc.DocRoot = c.DocRoot - enc.RPCGasCap = c.RPCGasCap - enc.RPCEVMTimeout = c.RPCEVMTimeout - enc.RPCTxFeeCap = c.RPCTxFeeCap - enc.OverrideCancun = c.OverrideCancun - enc.OverrideVerkle = c.OverrideVerkle - return &enc, nil -} - -// UnmarshalTOML unmarshals from TOML. -func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { - type Config struct { - Genesis *core.Genesis `toml:",omitempty"` - NetworkId *uint64 - SyncMode *downloader.SyncMode - EthDiscoveryURLs []string - SnapDiscoveryURLs []string - NoPruning *bool - NoPrefetch *bool - TxLookupLimit *uint64 `toml:",omitempty"` - TransactionHistory *uint64 `toml:",omitempty"` - StateHistory *uint64 `toml:",omitempty"` - StateScheme *string `toml:",omitempty"` - RequiredBlocks map[uint64]common.Hash `toml:"-"` - LightServ *int `toml:",omitempty"` - LightIngress *int `toml:",omitempty"` - LightEgress *int `toml:",omitempty"` - LightPeers *int `toml:",omitempty"` - LightNoPrune *bool `toml:",omitempty"` - LightNoSyncServe *bool `toml:",omitempty"` - SkipBcVersionCheck *bool `toml:"-"` - DatabaseHandles *int `toml:"-"` - DatabaseCache *int - DatabaseFreezer *string - TrieCleanCache *int - TrieDirtyCache *int - TrieTimeout *time.Duration - SnapshotCache *int - Preimages *bool - FilterLogCacheSize *int - Miner *miner.Config - TxPool *legacypool.Config - BlobPool *blobpool.Config - GPO *gasprice.Config - EnablePreimageRecording *bool - DocRoot *string `toml:"-"` - RPCGasCap *uint64 - RPCEVMTimeout *time.Duration - RPCTxFeeCap *float64 - OverrideCancun *uint64 `toml:",omitempty"` - OverrideVerkle *uint64 `toml:",omitempty"` - } - var dec Config - if err := unmarshal(&dec); err != nil { - return err - } - if dec.Genesis != nil { - c.Genesis = dec.Genesis - } - if dec.NetworkId != nil { - c.NetworkId = *dec.NetworkId - } - if dec.SyncMode != nil { - c.SyncMode = *dec.SyncMode - } - if dec.EthDiscoveryURLs != nil { - c.EthDiscoveryURLs = dec.EthDiscoveryURLs - } - if dec.SnapDiscoveryURLs != nil { - c.SnapDiscoveryURLs = dec.SnapDiscoveryURLs - } - if dec.NoPruning != nil { - c.NoPruning = *dec.NoPruning - } - if dec.NoPrefetch != nil { - c.NoPrefetch = *dec.NoPrefetch - } - if dec.TxLookupLimit != nil { - c.TxLookupLimit = *dec.TxLookupLimit - } - if dec.TransactionHistory != nil { - c.TransactionHistory = *dec.TransactionHistory - } - if dec.StateHistory != nil { - c.StateHistory = *dec.StateHistory - } - if dec.StateScheme != nil { - c.StateScheme = *dec.StateScheme - } - if dec.RequiredBlocks != nil { - c.RequiredBlocks = dec.RequiredBlocks - } - if dec.LightServ != nil { - c.LightServ = *dec.LightServ - } - if dec.LightIngress != nil { - c.LightIngress = *dec.LightIngress - } - if dec.LightEgress != nil { - c.LightEgress = *dec.LightEgress - } - if dec.LightPeers != nil { - c.LightPeers = *dec.LightPeers - } - if dec.LightNoPrune != nil { - c.LightNoPrune = *dec.LightNoPrune - } - if dec.LightNoSyncServe != nil { - c.LightNoSyncServe = *dec.LightNoSyncServe - } - if dec.SkipBcVersionCheck != nil { - c.SkipBcVersionCheck = *dec.SkipBcVersionCheck - } - if dec.DatabaseHandles != nil { - c.DatabaseHandles = *dec.DatabaseHandles - } - if dec.DatabaseCache != nil { - c.DatabaseCache = *dec.DatabaseCache - } - if dec.DatabaseFreezer != nil { - c.DatabaseFreezer = *dec.DatabaseFreezer - } - if dec.TrieCleanCache != nil { - c.TrieCleanCache = *dec.TrieCleanCache - } - if dec.TrieDirtyCache != nil { - c.TrieDirtyCache = *dec.TrieDirtyCache - } - if dec.TrieTimeout != nil { - c.TrieTimeout = *dec.TrieTimeout - } - if dec.SnapshotCache != nil { - c.SnapshotCache = *dec.SnapshotCache - } - if dec.Preimages != nil { - c.Preimages = *dec.Preimages - } - if dec.FilterLogCacheSize != nil { - c.FilterLogCacheSize = *dec.FilterLogCacheSize - } - if dec.Miner != nil { - c.Miner = *dec.Miner - } - if dec.TxPool != nil { - c.TxPool = *dec.TxPool - } - if dec.BlobPool != nil { - c.BlobPool = *dec.BlobPool - } - if dec.GPO != nil { - c.GPO = *dec.GPO - } - if dec.EnablePreimageRecording != nil { - c.EnablePreimageRecording = *dec.EnablePreimageRecording - } - if dec.DocRoot != nil { - c.DocRoot = *dec.DocRoot - } - if dec.RPCGasCap != nil { - c.RPCGasCap = *dec.RPCGasCap - } - if dec.RPCEVMTimeout != nil { - c.RPCEVMTimeout = *dec.RPCEVMTimeout - } - if dec.RPCTxFeeCap != nil { - c.RPCTxFeeCap = *dec.RPCTxFeeCap - } - if dec.OverrideCancun != nil { - c.OverrideCancun = dec.OverrideCancun - } - if dec.OverrideVerkle != nil { - c.OverrideVerkle = dec.OverrideVerkle - } - return nil -} diff --git a/builder/eth/fetcher/block_fetcher.go b/builder/eth/fetcher/block_fetcher.go deleted file mode 100644 index 126eaaea7..000000000 --- a/builder/eth/fetcher/block_fetcher.go +++ /dev/null @@ -1,939 +0,0 @@ -// 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 fetcher contains the announcement based header, blocks or transaction synchronisation. -package fetcher - -import ( - "errors" - "math/rand" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/prque" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/trie" -) - -const ( - lightTimeout = time.Millisecond // Time allowance before an announced header is explicitly requested - arriveTimeout = 500 * time.Millisecond // Time allowance before an announced block/transaction is explicitly requested - gatherSlack = 100 * time.Millisecond // Interval used to collate almost-expired announces with fetches - fetchTimeout = 5 * time.Second // Maximum allotted time to return an explicitly requested block/transaction -) - -const ( - maxUncleDist = 7 // Maximum allowed backward distance from the chain head - maxQueueDist = 32 // Maximum allowed distance from the chain head to queue - hashLimit = 256 // Maximum number of unique blocks or headers a peer may have announced - blockLimit = 64 // Maximum number of unique blocks a peer may have delivered -) - -var ( - blockAnnounceInMeter = metrics.NewRegisteredMeter("eth/fetcher/block/announces/in", nil) - blockAnnounceOutTimer = metrics.NewRegisteredTimer("eth/fetcher/block/announces/out", nil) - blockAnnounceDropMeter = metrics.NewRegisteredMeter("eth/fetcher/block/announces/drop", nil) - blockAnnounceDOSMeter = metrics.NewRegisteredMeter("eth/fetcher/block/announces/dos", nil) - - blockBroadcastInMeter = metrics.NewRegisteredMeter("eth/fetcher/block/broadcasts/in", nil) - blockBroadcastOutTimer = metrics.NewRegisteredTimer("eth/fetcher/block/broadcasts/out", nil) - blockBroadcastDropMeter = metrics.NewRegisteredMeter("eth/fetcher/block/broadcasts/drop", nil) - blockBroadcastDOSMeter = metrics.NewRegisteredMeter("eth/fetcher/block/broadcasts/dos", nil) - - headerFetchMeter = metrics.NewRegisteredMeter("eth/fetcher/block/headers", nil) - bodyFetchMeter = metrics.NewRegisteredMeter("eth/fetcher/block/bodies", nil) - - headerFilterInMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/headers/in", nil) - headerFilterOutMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/headers/out", nil) - bodyFilterInMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/bodies/in", nil) - bodyFilterOutMeter = metrics.NewRegisteredMeter("eth/fetcher/block/filter/bodies/out", nil) -) - -var errTerminated = errors.New("terminated") - -// HeaderRetrievalFn is a callback type for retrieving a header from the local chain. -type HeaderRetrievalFn func(common.Hash) *types.Header - -// blockRetrievalFn is a callback type for retrieving a block from the local chain. -type blockRetrievalFn func(common.Hash) *types.Block - -// headerRequesterFn is a callback type for sending a header retrieval request. -type headerRequesterFn func(common.Hash, chan *eth.Response) (*eth.Request, error) - -// bodyRequesterFn is a callback type for sending a body retrieval request. -type bodyRequesterFn func([]common.Hash, chan *eth.Response) (*eth.Request, error) - -// headerVerifierFn is a callback type to verify a block's header for fast propagation. -type headerVerifierFn func(header *types.Header) error - -// blockBroadcasterFn is a callback type for broadcasting a block to connected peers. -type blockBroadcasterFn func(block *types.Block, propagate bool) - -// chainHeightFn is a callback type to retrieve the current chain height. -type chainHeightFn func() uint64 - -// headersInsertFn is a callback type to insert a batch of headers into the local chain. -type headersInsertFn func(headers []*types.Header) (int, error) - -// chainInsertFn is a callback type to insert a batch of blocks into the local chain. -type chainInsertFn func(types.Blocks) (int, error) - -// peerDropFn is a callback type for dropping a peer detected as malicious. -type peerDropFn func(id string) - -// blockAnnounce is the hash notification of the availability of a new block in the -// network. -type blockAnnounce struct { - hash common.Hash // Hash of the block being announced - number uint64 // Number of the block being announced (0 = unknown | old protocol) - header *types.Header // Header of the block partially reassembled (new protocol) - time time.Time // Timestamp of the announcement - - origin string // Identifier of the peer originating the notification - - fetchHeader headerRequesterFn // Fetcher function to retrieve the header of an announced block - fetchBodies bodyRequesterFn // Fetcher function to retrieve the body of an announced block -} - -// headerFilterTask represents a batch of headers needing fetcher filtering. -type headerFilterTask struct { - peer string // The source peer of block headers - headers []*types.Header // Collection of headers to filter - time time.Time // Arrival time of the headers -} - -// bodyFilterTask represents a batch of block bodies (transactions and uncles) -// needing fetcher filtering. -type bodyFilterTask struct { - peer string // The source peer of block bodies - transactions [][]*types.Transaction // Collection of transactions per block bodies - uncles [][]*types.Header // Collection of uncles per block bodies - time time.Time // Arrival time of the blocks' contents -} - -// blockOrHeaderInject represents a schedules import operation. -type blockOrHeaderInject struct { - origin string - - header *types.Header // Used for light mode fetcher which only cares about header. - block *types.Block // Used for normal mode fetcher which imports full block. -} - -// number returns the block number of the injected object. -func (inject *blockOrHeaderInject) number() uint64 { - if inject.header != nil { - return inject.header.Number.Uint64() - } - return inject.block.NumberU64() -} - -// number returns the block hash of the injected object. -func (inject *blockOrHeaderInject) hash() common.Hash { - if inject.header != nil { - return inject.header.Hash() - } - return inject.block.Hash() -} - -// BlockFetcher is responsible for accumulating block announcements from various peers -// and scheduling them for retrieval. -type BlockFetcher struct { - light bool // The indicator whether it's a light fetcher or normal one. - - // Various event channels - notify chan *blockAnnounce - inject chan *blockOrHeaderInject - - headerFilter chan chan *headerFilterTask - bodyFilter chan chan *bodyFilterTask - - done chan common.Hash - quit chan struct{} - - // Announce states - announces map[string]int // Per peer blockAnnounce counts to prevent memory exhaustion - announced map[common.Hash][]*blockAnnounce // Announced blocks, scheduled for fetching - fetching map[common.Hash]*blockAnnounce // Announced blocks, currently fetching - fetched map[common.Hash][]*blockAnnounce // Blocks with headers fetched, scheduled for body retrieval - completing map[common.Hash]*blockAnnounce // Blocks with headers, currently body-completing - - // Block cache - queue *prque.Prque[int64, *blockOrHeaderInject] // Queue containing the import operations (block number sorted) - queues map[string]int // Per peer block counts to prevent memory exhaustion - queued map[common.Hash]*blockOrHeaderInject // Set of already queued blocks (to dedup imports) - - // Callbacks - getHeader HeaderRetrievalFn // Retrieves a header from the local chain - getBlock blockRetrievalFn // Retrieves a block from the local chain - verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work - broadcastBlock blockBroadcasterFn // Broadcasts a block to connected peers - chainHeight chainHeightFn // Retrieves the current chain's height - insertHeaders headersInsertFn // Injects a batch of headers into the chain - insertChain chainInsertFn // Injects a batch of blocks into the chain - dropPeer peerDropFn // Drops a peer for misbehaving - - // Testing hooks - announceChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a hash from the blockAnnounce list - queueChangeHook func(common.Hash, bool) // Method to call upon adding or deleting a block from the import queue - fetchingHook func([]common.Hash) // Method to call upon starting a block (eth/61) or header (eth/62) fetch - completingHook func([]common.Hash) // Method to call upon starting a block body fetch (eth/62) - importedHook func(*types.Header, *types.Block) // Method to call upon successful header or block import (both eth/61 and eth/62) -} - -// NewBlockFetcher creates a block fetcher to retrieve blocks based on hash announcements. -func NewBlockFetcher(light bool, getHeader HeaderRetrievalFn, getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertHeaders headersInsertFn, insertChain chainInsertFn, dropPeer peerDropFn) *BlockFetcher { - return &BlockFetcher{ - light: light, - notify: make(chan *blockAnnounce), - inject: make(chan *blockOrHeaderInject), - headerFilter: make(chan chan *headerFilterTask), - bodyFilter: make(chan chan *bodyFilterTask), - done: make(chan common.Hash), - quit: make(chan struct{}), - announces: make(map[string]int), - announced: make(map[common.Hash][]*blockAnnounce), - fetching: make(map[common.Hash]*blockAnnounce), - fetched: make(map[common.Hash][]*blockAnnounce), - completing: make(map[common.Hash]*blockAnnounce), - queue: prque.New[int64, *blockOrHeaderInject](nil), - queues: make(map[string]int), - queued: make(map[common.Hash]*blockOrHeaderInject), - getHeader: getHeader, - getBlock: getBlock, - verifyHeader: verifyHeader, - broadcastBlock: broadcastBlock, - chainHeight: chainHeight, - insertHeaders: insertHeaders, - insertChain: insertChain, - dropPeer: dropPeer, - } -} - -// Start boots up the announcement based synchroniser, accepting and processing -// hash notifications and block fetches until termination requested. -func (f *BlockFetcher) Start() { - go f.loop() -} - -// Stop terminates the announcement based synchroniser, canceling all pending -// operations. -func (f *BlockFetcher) Stop() { - close(f.quit) -} - -// Notify announces the fetcher of the potential availability of a new block in -// the network. -func (f *BlockFetcher) Notify(peer string, hash common.Hash, number uint64, time time.Time, - headerFetcher headerRequesterFn, bodyFetcher bodyRequesterFn) error { - block := &blockAnnounce{ - hash: hash, - number: number, - time: time, - origin: peer, - fetchHeader: headerFetcher, - fetchBodies: bodyFetcher, - } - select { - case f.notify <- block: - return nil - case <-f.quit: - return errTerminated - } -} - -// Enqueue tries to fill gaps the fetcher's future import queue. -func (f *BlockFetcher) Enqueue(peer string, block *types.Block) error { - op := &blockOrHeaderInject{ - origin: peer, - block: block, - } - select { - case f.inject <- op: - return nil - case <-f.quit: - return errTerminated - } -} - -// FilterHeaders extracts all the headers that were explicitly requested by the fetcher, -// returning those that should be handled differently. -func (f *BlockFetcher) FilterHeaders(peer string, headers []*types.Header, time time.Time) []*types.Header { - log.Trace("Filtering headers", "peer", peer, "headers", len(headers)) - - // Send the filter channel to the fetcher - filter := make(chan *headerFilterTask) - - select { - case f.headerFilter <- filter: - case <-f.quit: - return nil - } - // Request the filtering of the header list - select { - case filter <- &headerFilterTask{peer: peer, headers: headers, time: time}: - case <-f.quit: - return nil - } - // Retrieve the headers remaining after filtering - select { - case task := <-filter: - return task.headers - case <-f.quit: - return nil - } -} - -// FilterBodies extracts all the block bodies that were explicitly requested by -// the fetcher, returning those that should be handled differently. -func (f *BlockFetcher) FilterBodies(peer string, transactions [][]*types.Transaction, uncles [][]*types.Header, time time.Time) ([][]*types.Transaction, [][]*types.Header) { - log.Trace("Filtering bodies", "peer", peer, "txs", len(transactions), "uncles", len(uncles)) - - // Send the filter channel to the fetcher - filter := make(chan *bodyFilterTask) - - select { - case f.bodyFilter <- filter: - case <-f.quit: - return nil, nil - } - // Request the filtering of the body list - select { - case filter <- &bodyFilterTask{peer: peer, transactions: transactions, uncles: uncles, time: time}: - case <-f.quit: - return nil, nil - } - // Retrieve the bodies remaining after filtering - select { - case task := <-filter: - return task.transactions, task.uncles - case <-f.quit: - return nil, nil - } -} - -// Loop is the main fetcher loop, checking and processing various notification -// events. -func (f *BlockFetcher) loop() { - // Iterate the block fetching until a quit is requested - var ( - fetchTimer = time.NewTimer(0) - completeTimer = time.NewTimer(0) - ) - <-fetchTimer.C // clear out the channel - <-completeTimer.C - defer fetchTimer.Stop() - defer completeTimer.Stop() - - for { - // Clean up any expired block fetches - for hash, announce := range f.fetching { - if time.Since(announce.time) > fetchTimeout { - f.forgetHash(hash) - } - } - // Import any queued blocks that could potentially fit - height := f.chainHeight() - for !f.queue.Empty() { - op := f.queue.PopItem() - hash := op.hash() - if f.queueChangeHook != nil { - f.queueChangeHook(hash, false) - } - // If too high up the chain or phase, continue later - number := op.number() - if number > height+1 { - f.queue.Push(op, -int64(number)) - if f.queueChangeHook != nil { - f.queueChangeHook(hash, true) - } - break - } - // Otherwise if fresh and still unknown, try and import - if (number+maxUncleDist < height) || (f.light && f.getHeader(hash) != nil) || (!f.light && f.getBlock(hash) != nil) { - f.forgetBlock(hash) - continue - } - if f.light { - f.importHeaders(op.origin, op.header) - } else { - f.importBlocks(op.origin, op.block) - } - } - // Wait for an outside event to occur - select { - case <-f.quit: - // BlockFetcher terminating, abort all operations - return - - case notification := <-f.notify: - // A block was announced, make sure the peer isn't DOSing us - blockAnnounceInMeter.Mark(1) - - count := f.announces[notification.origin] + 1 - if count > hashLimit { - log.Debug("Peer exceeded outstanding announces", "peer", notification.origin, "limit", hashLimit) - blockAnnounceDOSMeter.Mark(1) - break - } - if notification.number == 0 { - break - } - // If we have a valid block number, check that it's potentially useful - if dist := int64(notification.number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist { - log.Debug("Peer discarded announcement", "peer", notification.origin, "number", notification.number, "hash", notification.hash, "distance", dist) - blockAnnounceDropMeter.Mark(1) - break - } - // All is well, schedule the announce if block's not yet downloading - if _, ok := f.fetching[notification.hash]; ok { - break - } - if _, ok := f.completing[notification.hash]; ok { - break - } - f.announces[notification.origin] = count - f.announced[notification.hash] = append(f.announced[notification.hash], notification) - if f.announceChangeHook != nil && len(f.announced[notification.hash]) == 1 { - f.announceChangeHook(notification.hash, true) - } - if len(f.announced) == 1 { - f.rescheduleFetch(fetchTimer) - } - - case op := <-f.inject: - // A direct block insertion was requested, try and fill any pending gaps - blockBroadcastInMeter.Mark(1) - - // Now only direct block injection is allowed, drop the header injection - // here silently if we receive. - if f.light { - continue - } - f.enqueue(op.origin, nil, op.block) - - case hash := <-f.done: - // A pending import finished, remove all traces of the notification - f.forgetHash(hash) - f.forgetBlock(hash) - - case <-fetchTimer.C: - // At least one block's timer ran out, check for needing retrieval - request := make(map[string][]common.Hash) - - for hash, announces := range f.announced { - // In current LES protocol(les2/les3), only header announce is - // available, no need to wait too much time for header broadcast. - timeout := arriveTimeout - gatherSlack - if f.light { - timeout = 0 - } - if time.Since(announces[0].time) > timeout { - // Pick a random peer to retrieve from, reset all others - announce := announces[rand.Intn(len(announces))] - f.forgetHash(hash) - - // If the block still didn't arrive, queue for fetching - if (f.light && f.getHeader(hash) == nil) || (!f.light && f.getBlock(hash) == nil) { - request[announce.origin] = append(request[announce.origin], hash) - f.fetching[hash] = announce - } - } - } - // Send out all block header requests - for peer, hashes := range request { - log.Trace("Fetching scheduled headers", "peer", peer, "list", hashes) - - // Create a closure of the fetch and schedule in on a new thread - fetchHeader, hashes := f.fetching[hashes[0]].fetchHeader, hashes - go func(peer string) { - if f.fetchingHook != nil { - f.fetchingHook(hashes) - } - for _, hash := range hashes { - headerFetchMeter.Mark(1) - go func(hash common.Hash) { - resCh := make(chan *eth.Response) - - req, err := fetchHeader(hash, resCh) - if err != nil { - return // Legacy code, yolo - } - defer req.Close() - - timeout := time.NewTimer(2 * fetchTimeout) // 2x leeway before dropping the peer - defer timeout.Stop() - - select { - case res := <-resCh: - res.Done <- nil - f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersRequest), time.Now()) - - case <-timeout.C: - // The peer didn't respond in time. The request - // was already rescheduled at this point, we were - // waiting for a catchup. With an unresponsive - // peer however, it's a protocol violation. - f.dropPeer(peer) - } - }(hash) - } - }(peer) - } - // Schedule the next fetch if blocks are still pending - f.rescheduleFetch(fetchTimer) - - case <-completeTimer.C: - // At least one header's timer ran out, retrieve everything - request := make(map[string][]common.Hash) - - for hash, announces := range f.fetched { - // Pick a random peer to retrieve from, reset all others - announce := announces[rand.Intn(len(announces))] - f.forgetHash(hash) - - // If the block still didn't arrive, queue for completion - if f.getBlock(hash) == nil { - request[announce.origin] = append(request[announce.origin], hash) - f.completing[hash] = announce - } - } - // Send out all block body requests - for peer, hashes := range request { - log.Trace("Fetching scheduled bodies", "peer", peer, "list", hashes) - - // Create a closure of the fetch and schedule in on a new thread - if f.completingHook != nil { - f.completingHook(hashes) - } - fetchBodies := f.completing[hashes[0]].fetchBodies - bodyFetchMeter.Mark(int64(len(hashes))) - - go func(peer string, hashes []common.Hash) { - resCh := make(chan *eth.Response) - - req, err := fetchBodies(hashes, resCh) - if err != nil { - return // Legacy code, yolo - } - defer req.Close() - - timeout := time.NewTimer(2 * fetchTimeout) // 2x leeway before dropping the peer - defer timeout.Stop() - - select { - case res := <-resCh: - res.Done <- nil - // Ignoring withdrawals here, since the block fetcher is not used post-merge. - txs, uncles, _ := res.Res.(*eth.BlockBodiesResponse).Unpack() - f.FilterBodies(peer, txs, uncles, time.Now()) - - case <-timeout.C: - // The peer didn't respond in time. The request - // was already rescheduled at this point, we were - // waiting for a catchup. With an unresponsive - // peer however, it's a protocol violation. - f.dropPeer(peer) - } - }(peer, hashes) - } - // Schedule the next fetch if blocks are still pending - f.rescheduleComplete(completeTimer) - - case filter := <-f.headerFilter: - // Headers arrived from a remote peer. Extract those that were explicitly - // requested by the fetcher, and return everything else so it's delivered - // to other parts of the system. - var task *headerFilterTask - select { - case task = <-filter: - case <-f.quit: - return - } - headerFilterInMeter.Mark(int64(len(task.headers))) - - // Split the batch of headers into unknown ones (to return to the caller), - // known incomplete ones (requiring body retrievals) and completed blocks. - unknown, incomplete, complete, lightHeaders := []*types.Header{}, []*blockAnnounce{}, []*types.Block{}, []*blockAnnounce{} - for _, header := range task.headers { - hash := header.Hash() - - // Filter fetcher-requested headers from other synchronisation algorithms - if announce := f.fetching[hash]; announce != nil && announce.origin == task.peer && f.fetched[hash] == nil && f.completing[hash] == nil && f.queued[hash] == nil { - // If the delivered header does not match the promised number, drop the announcer - if header.Number.Uint64() != announce.number { - log.Trace("Invalid block number fetched", "peer", announce.origin, "hash", header.Hash(), "announced", announce.number, "provided", header.Number) - f.dropPeer(announce.origin) - f.forgetHash(hash) - continue - } - // Collect all headers only if we are running in light - // mode and the headers are not imported by other means. - if f.light { - if f.getHeader(hash) == nil { - announce.header = header - lightHeaders = append(lightHeaders, announce) - } - f.forgetHash(hash) - continue - } - // Only keep if not imported by other means - if f.getBlock(hash) == nil { - announce.header = header - announce.time = task.time - - // If the block is empty (header only), short circuit into the final import queue - if header.TxHash == types.EmptyTxsHash && header.UncleHash == types.EmptyUncleHash { - log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) - - block := types.NewBlockWithHeader(header) - block.ReceivedAt = task.time - - complete = append(complete, block) - f.completing[hash] = announce - continue - } - // Otherwise add to the list of blocks needing completion - incomplete = append(incomplete, announce) - } else { - log.Trace("Block already imported, discarding header", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) - f.forgetHash(hash) - } - } else { - // BlockFetcher doesn't know about it, add to the return list - unknown = append(unknown, header) - } - } - headerFilterOutMeter.Mark(int64(len(unknown))) - select { - case filter <- &headerFilterTask{headers: unknown, time: task.time}: - case <-f.quit: - return - } - // Schedule the retrieved headers for body completion - for _, announce := range incomplete { - hash := announce.header.Hash() - if _, ok := f.completing[hash]; ok { - continue - } - f.fetched[hash] = append(f.fetched[hash], announce) - if len(f.fetched) == 1 { - f.rescheduleComplete(completeTimer) - } - } - // Schedule the header for light fetcher import - for _, announce := range lightHeaders { - f.enqueue(announce.origin, announce.header, nil) - } - // Schedule the header-only blocks for import - for _, block := range complete { - if announce := f.completing[block.Hash()]; announce != nil { - f.enqueue(announce.origin, nil, block) - } - } - - case filter := <-f.bodyFilter: - // Block bodies arrived, extract any explicitly requested blocks, return the rest - var task *bodyFilterTask - select { - case task = <-filter: - case <-f.quit: - return - } - bodyFilterInMeter.Mark(int64(len(task.transactions))) - blocks := []*types.Block{} - // abort early if there's nothing explicitly requested - if len(f.completing) > 0 { - for i := 0; i < len(task.transactions) && i < len(task.uncles); i++ { - // Match up a body to any possible completion request - var ( - matched = false - uncleHash common.Hash // calculated lazily and reused - txnHash common.Hash // calculated lazily and reused - ) - for hash, announce := range f.completing { - if f.queued[hash] != nil || announce.origin != task.peer { - continue - } - if uncleHash == (common.Hash{}) { - uncleHash = types.CalcUncleHash(task.uncles[i]) - } - if uncleHash != announce.header.UncleHash { - continue - } - if txnHash == (common.Hash{}) { - txnHash = types.DeriveSha(types.Transactions(task.transactions[i]), trie.NewStackTrie(nil)) - } - if txnHash != announce.header.TxHash { - continue - } - // Mark the body matched, reassemble if still unknown - matched = true - if f.getBlock(hash) == nil { - block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i]) - block.ReceivedAt = task.time - blocks = append(blocks, block) - } else { - f.forgetHash(hash) - } - } - if matched { - task.transactions = append(task.transactions[:i], task.transactions[i+1:]...) - task.uncles = append(task.uncles[:i], task.uncles[i+1:]...) - i-- - continue - } - } - } - bodyFilterOutMeter.Mark(int64(len(task.transactions))) - select { - case filter <- task: - case <-f.quit: - return - } - // Schedule the retrieved blocks for ordered import - for _, block := range blocks { - if announce := f.completing[block.Hash()]; announce != nil { - f.enqueue(announce.origin, nil, block) - } - } - } - } -} - -// rescheduleFetch resets the specified fetch timer to the next blockAnnounce timeout. -func (f *BlockFetcher) rescheduleFetch(fetch *time.Timer) { - // Short circuit if no blocks are announced - if len(f.announced) == 0 { - return - } - // Schedule announcement retrieval quickly for light mode - // since server won't send any headers to client. - if f.light { - fetch.Reset(lightTimeout) - return - } - // Otherwise find the earliest expiring announcement - earliest := time.Now() - for _, announces := range f.announced { - if earliest.After(announces[0].time) { - earliest = announces[0].time - } - } - fetch.Reset(arriveTimeout - time.Since(earliest)) -} - -// rescheduleComplete resets the specified completion timer to the next fetch timeout. -func (f *BlockFetcher) rescheduleComplete(complete *time.Timer) { - // Short circuit if no headers are fetched - if len(f.fetched) == 0 { - return - } - // Otherwise find the earliest expiring announcement - earliest := time.Now() - for _, announces := range f.fetched { - if earliest.After(announces[0].time) { - earliest = announces[0].time - } - } - complete.Reset(gatherSlack - time.Since(earliest)) -} - -// enqueue schedules a new header or block import operation, if the component -// to be imported has not yet been seen. -func (f *BlockFetcher) enqueue(peer string, header *types.Header, block *types.Block) { - var ( - hash common.Hash - number uint64 - ) - if header != nil { - hash, number = header.Hash(), header.Number.Uint64() - } else { - hash, number = block.Hash(), block.NumberU64() - } - // Ensure the peer isn't DOSing us - count := f.queues[peer] + 1 - if count > blockLimit { - log.Debug("Discarded delivered header or block, exceeded allowance", "peer", peer, "number", number, "hash", hash, "limit", blockLimit) - blockBroadcastDOSMeter.Mark(1) - f.forgetHash(hash) - return - } - // Discard any past or too distant blocks - if dist := int64(number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist { - log.Debug("Discarded delivered header or block, too far away", "peer", peer, "number", number, "hash", hash, "distance", dist) - blockBroadcastDropMeter.Mark(1) - f.forgetHash(hash) - return - } - // Schedule the block for future importing - if _, ok := f.queued[hash]; !ok { - op := &blockOrHeaderInject{origin: peer} - if header != nil { - op.header = header - } else { - op.block = block - } - f.queues[peer] = count - f.queued[hash] = op - f.queue.Push(op, -int64(number)) - if f.queueChangeHook != nil { - f.queueChangeHook(hash, true) - } - log.Debug("Queued delivered header or block", "peer", peer, "number", number, "hash", hash, "queued", f.queue.Size()) - } -} - -// importHeaders spawns a new goroutine to run a header insertion into the chain. -// If the header's number is at the same height as the current import phase, it -// updates the phase states accordingly. -func (f *BlockFetcher) importHeaders(peer string, header *types.Header) { - hash := header.Hash() - log.Debug("Importing propagated header", "peer", peer, "number", header.Number, "hash", hash) - - go func() { - defer func() { f.done <- hash }() - // If the parent's unknown, abort insertion - parent := f.getHeader(header.ParentHash) - if parent == nil { - log.Debug("Unknown parent of propagated header", "peer", peer, "number", header.Number, "hash", hash, "parent", header.ParentHash) - return - } - // Validate the header and if something went wrong, drop the peer - if err := f.verifyHeader(header); err != nil && err != consensus.ErrFutureBlock { - log.Debug("Propagated header verification failed", "peer", peer, "number", header.Number, "hash", hash, "err", err) - f.dropPeer(peer) - return - } - // Run the actual import and log any issues - if _, err := f.insertHeaders([]*types.Header{header}); err != nil { - log.Debug("Propagated header import failed", "peer", peer, "number", header.Number, "hash", hash, "err", err) - return - } - // Invoke the testing hook if needed - if f.importedHook != nil { - f.importedHook(header, nil) - } - }() -} - -// importBlocks spawns a new goroutine to run a block insertion into the chain. If the -// block's number is at the same height as the current import phase, it updates -// the phase states accordingly. -func (f *BlockFetcher) importBlocks(peer string, block *types.Block) { - hash := block.Hash() - - // Run the import on a new thread - log.Debug("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash) - go func() { - defer func() { f.done <- hash }() - - // If the parent's unknown, abort insertion - parent := f.getBlock(block.ParentHash()) - if parent == nil { - log.Debug("Unknown parent of propagated block", "peer", peer, "number", block.Number(), "hash", hash, "parent", block.ParentHash()) - return - } - // Quickly validate the header and propagate the block if it passes - switch err := f.verifyHeader(block.Header()); err { - case nil: - // All ok, quickly propagate to our peers - blockBroadcastOutTimer.UpdateSince(block.ReceivedAt) - go f.broadcastBlock(block, true) - - case consensus.ErrFutureBlock: - // Weird future block, don't fail, but neither propagate - - default: - // Something went very wrong, drop the peer - log.Debug("Propagated block verification failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) - f.dropPeer(peer) - return - } - // Run the actual import and log any issues - if _, err := f.insertChain(types.Blocks{block}); err != nil { - log.Debug("Propagated block import failed", "peer", peer, "number", block.Number(), "hash", hash, "err", err) - return - } - // If import succeeded, broadcast the block - blockAnnounceOutTimer.UpdateSince(block.ReceivedAt) - go f.broadcastBlock(block, false) - - // Invoke the testing hook if needed - if f.importedHook != nil { - f.importedHook(nil, block) - } - }() -} - -// forgetHash removes all traces of a block announcement from the fetcher's -// internal state. -func (f *BlockFetcher) forgetHash(hash common.Hash) { - // Remove all pending announces and decrement DOS counters - if announceMap, ok := f.announced[hash]; ok { - for _, announce := range announceMap { - f.announces[announce.origin]-- - if f.announces[announce.origin] <= 0 { - delete(f.announces, announce.origin) - } - } - delete(f.announced, hash) - if f.announceChangeHook != nil { - f.announceChangeHook(hash, false) - } - } - // Remove any pending fetches and decrement the DOS counters - if announce := f.fetching[hash]; announce != nil { - f.announces[announce.origin]-- - if f.announces[announce.origin] <= 0 { - delete(f.announces, announce.origin) - } - delete(f.fetching, hash) - } - - // Remove any pending completion requests and decrement the DOS counters - for _, announce := range f.fetched[hash] { - f.announces[announce.origin]-- - if f.announces[announce.origin] <= 0 { - delete(f.announces, announce.origin) - } - } - delete(f.fetched, hash) - - // Remove any pending completions and decrement the DOS counters - if announce := f.completing[hash]; announce != nil { - f.announces[announce.origin]-- - if f.announces[announce.origin] <= 0 { - delete(f.announces, announce.origin) - } - delete(f.completing, hash) - } -} - -// forgetBlock removes all traces of a queued block from the fetcher's internal -// state. -func (f *BlockFetcher) forgetBlock(hash common.Hash) { - if insert := f.queued[hash]; insert != nil { - f.queues[insert.origin]-- - if f.queues[insert.origin] == 0 { - delete(f.queues, insert.origin) - } - delete(f.queued, hash) - } -} diff --git a/builder/eth/fetcher/block_fetcher_test.go b/builder/eth/fetcher/block_fetcher_test.go deleted file mode 100644 index cb7cbaf79..000000000 --- a/builder/eth/fetcher/block_fetcher_test.go +++ /dev/null @@ -1,949 +0,0 @@ -// 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 fetcher - -import ( - "errors" - "math/big" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" -) - -var ( - testdb = rawdb.NewMemoryDatabase() - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddress = crypto.PubkeyToAddress(testKey.PublicKey) - gspec = &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - genesis = gspec.MustCommit(testdb, triedb.NewDatabase(testdb, triedb.HashDefaults)) - unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit, BaseFee: big.NewInt(params.InitialBaseFee)}, nil, nil, nil, trie.NewStackTrie(nil)) -) - -// makeChain creates a chain of n blocks starting at and including parent. -// the returned hash chain is ordered head->parent. In addition, every 3rd block -// contains a transaction and every 5th an uncle to allow testing correct block -// reassembly. -func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) { - blocks, _ := core.GenerateChain(gspec.Config, parent, ethash.NewFaker(), testdb, n, func(i int, block *core.BlockGen) { - block.SetCoinbase(common.Address{seed}) - - // If the block number is multiple of 3, send a bonus transaction to the miner - if parent == genesis && i%3 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Timestamp()) - tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) - if err != nil { - panic(err) - } - block.AddTx(tx) - } - // If the block number is a multiple of 5, add a bonus uncle to the block - if i > 0 && i%5 == 0 { - block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 2).Hash(), Number: big.NewInt(int64(i - 1))}) - } - }) - hashes := make([]common.Hash, n+1) - hashes[len(hashes)-1] = parent.Hash() - blockm := make(map[common.Hash]*types.Block, n+1) - blockm[parent.Hash()] = parent - for i, b := range blocks { - hashes[len(hashes)-i-2] = b.Hash() - blockm[b.Hash()] = b - } - return hashes, blockm -} - -// fetcherTester is a test simulator for mocking out local block chain. -type fetcherTester struct { - fetcher *BlockFetcher - - hashes []common.Hash // Hash chain belonging to the tester - headers map[common.Hash]*types.Header // Headers belonging to the tester - blocks map[common.Hash]*types.Block // Blocks belonging to the tester - drops map[string]bool // Map of peers dropped by the fetcher - - lock sync.RWMutex -} - -// newTester creates a new fetcher test mocker. -func newTester(light bool) *fetcherTester { - tester := &fetcherTester{ - hashes: []common.Hash{genesis.Hash()}, - headers: map[common.Hash]*types.Header{genesis.Hash(): genesis.Header()}, - blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis}, - drops: make(map[string]bool), - } - tester.fetcher = NewBlockFetcher(light, tester.getHeader, tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertHeaders, tester.insertChain, tester.dropPeer) - tester.fetcher.Start() - - return tester -} - -// getHeader retrieves a header from the tester's block chain. -func (f *fetcherTester) getHeader(hash common.Hash) *types.Header { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.headers[hash] -} - -// getBlock retrieves a block from the tester's block chain. -func (f *fetcherTester) getBlock(hash common.Hash) *types.Block { - f.lock.RLock() - defer f.lock.RUnlock() - - return f.blocks[hash] -} - -// verifyHeader is a nop placeholder for the block header verification. -func (f *fetcherTester) verifyHeader(header *types.Header) error { - return nil -} - -// broadcastBlock is a nop placeholder for the block broadcasting. -func (f *fetcherTester) broadcastBlock(block *types.Block, propagate bool) { -} - -// chainHeight retrieves the current height (block number) of the chain. -func (f *fetcherTester) chainHeight() uint64 { - f.lock.RLock() - defer f.lock.RUnlock() - - if f.fetcher.light { - return f.headers[f.hashes[len(f.hashes)-1]].Number.Uint64() - } - return f.blocks[f.hashes[len(f.hashes)-1]].NumberU64() -} - -// insertChain injects a new headers into the simulated chain. -func (f *fetcherTester) insertHeaders(headers []*types.Header) (int, error) { - f.lock.Lock() - defer f.lock.Unlock() - - for i, header := range headers { - // Make sure the parent in known - if _, ok := f.headers[header.ParentHash]; !ok { - return i, errors.New("unknown parent") - } - // Discard any new blocks if the same height already exists - if header.Number.Uint64() <= f.headers[f.hashes[len(f.hashes)-1]].Number.Uint64() { - return i, nil - } - // Otherwise build our current chain - f.hashes = append(f.hashes, header.Hash()) - f.headers[header.Hash()] = header - } - return 0, nil -} - -// insertChain injects a new blocks into the simulated chain. -func (f *fetcherTester) insertChain(blocks types.Blocks) (int, error) { - f.lock.Lock() - defer f.lock.Unlock() - - for i, block := range blocks { - // Make sure the parent in known - if _, ok := f.blocks[block.ParentHash()]; !ok { - return i, errors.New("unknown parent") - } - // Discard any new blocks if the same height already exists - if block.NumberU64() <= f.blocks[f.hashes[len(f.hashes)-1]].NumberU64() { - return i, nil - } - // Otherwise build our current chain - f.hashes = append(f.hashes, block.Hash()) - f.blocks[block.Hash()] = block - } - return 0, nil -} - -// dropPeer is an emulator for the peer removal, simply accumulating the various -// peers dropped by the fetcher. -func (f *fetcherTester) dropPeer(peer string) { - f.lock.Lock() - defer f.lock.Unlock() - - f.drops[peer] = true -} - -// makeHeaderFetcher retrieves a block header fetcher associated with a simulated peer. -func (f *fetcherTester) makeHeaderFetcher(peer string, blocks map[common.Hash]*types.Block, drift time.Duration) headerRequesterFn { - closure := make(map[common.Hash]*types.Block) - for hash, block := range blocks { - closure[hash] = block - } - // Create a function that return a header from the closure - return func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { - // Gather the blocks to return - headers := make([]*types.Header, 0, 1) - if block, ok := closure[hash]; ok { - headers = append(headers, block.Header()) - } - // Return on a new thread - req := ð.Request{ - Peer: peer, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockHeadersRequest)(&headers), - Time: drift, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil - } -} - -// makeBodyFetcher retrieves a block body fetcher associated with a simulated peer. -func (f *fetcherTester) makeBodyFetcher(peer string, blocks map[common.Hash]*types.Block, drift time.Duration) bodyRequesterFn { - closure := make(map[common.Hash]*types.Block) - for hash, block := range blocks { - closure[hash] = block - } - // Create a function that returns blocks from the closure - return func(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { - // Gather the block bodies to return - transactions := make([][]*types.Transaction, 0, len(hashes)) - uncles := make([][]*types.Header, 0, len(hashes)) - - for _, hash := range hashes { - if block, ok := closure[hash]; ok { - transactions = append(transactions, block.Transactions()) - uncles = append(uncles, block.Uncles()) - } - } - // Return on a new thread - bodies := make([]*eth.BlockBody, len(transactions)) - for i, txs := range transactions { - bodies[i] = ð.BlockBody{ - Transactions: txs, - Uncles: uncles[i], - } - } - req := ð.Request{ - Peer: peer, - } - res := ð.Response{ - Req: req, - Res: (*eth.BlockBodiesResponse)(&bodies), - Time: drift, - Done: make(chan error, 1), // Ignore the returned status - } - go func() { - sink <- res - }() - return req, nil - } -} - -// verifyFetchingEvent verifies that one single event arrive on a fetching channel. -func verifyFetchingEvent(t *testing.T, fetching chan []common.Hash, arrive bool) { - t.Helper() - - if arrive { - select { - case <-fetching: - case <-time.After(time.Second): - t.Fatalf("fetching timeout") - } - } else { - select { - case <-fetching: - t.Fatalf("fetching invoked") - case <-time.After(10 * time.Millisecond): - } - } -} - -// verifyCompletingEvent verifies that one single event arrive on an completing channel. -func verifyCompletingEvent(t *testing.T, completing chan []common.Hash, arrive bool) { - t.Helper() - - if arrive { - select { - case <-completing: - case <-time.After(time.Second): - t.Fatalf("completing timeout") - } - } else { - select { - case <-completing: - t.Fatalf("completing invoked") - case <-time.After(10 * time.Millisecond): - } - } -} - -// verifyImportEvent verifies that one single event arrive on an import channel. -func verifyImportEvent(t *testing.T, imported chan interface{}, arrive bool) { - t.Helper() - - if arrive { - select { - case <-imported: - case <-time.After(time.Second): - t.Fatalf("import timeout") - } - } else { - select { - case <-imported: - t.Fatalf("import invoked") - case <-time.After(20 * time.Millisecond): - } - } -} - -// verifyImportCount verifies that exactly count number of events arrive on an -// import hook channel. -func verifyImportCount(t *testing.T, imported chan interface{}, count int) { - t.Helper() - - for i := 0; i < count; i++ { - select { - case <-imported: - case <-time.After(time.Second): - t.Fatalf("block %d: import timeout", i+1) - } - } - verifyImportDone(t, imported) -} - -// verifyImportDone verifies that no more events are arriving on an import channel. -func verifyImportDone(t *testing.T, imported chan interface{}) { - t.Helper() - - select { - case <-imported: - t.Fatalf("extra block imported") - case <-time.After(50 * time.Millisecond): - } -} - -// verifyChainHeight verifies the chain height is as expected. -func verifyChainHeight(t *testing.T, fetcher *fetcherTester, height uint64) { - t.Helper() - - if fetcher.chainHeight() != height { - t.Fatalf("chain height mismatch, got %d, want %d", fetcher.chainHeight(), height) - } -} - -// Tests that a fetcher accepts block/header announcements and initiates retrievals -// for them, successfully importing into the local chain. -func TestFullSequentialAnnouncements(t *testing.T) { testSequentialAnnouncements(t, false) } -func TestLightSequentialAnnouncements(t *testing.T) { testSequentialAnnouncements(t, true) } - -func testSequentialAnnouncements(t *testing.T, light bool) { - // Create a chain of blocks to import - targetBlocks := 4 * hashLimit - hashes, blocks := makeChain(targetBlocks, 0, genesis) - - tester := newTester(light) - defer tester.fetcher.Stop() - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - // Iteratively announce blocks until all are imported - imported := make(chan interface{}) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if light { - if header == nil { - t.Fatalf("Fetcher try to import empty header") - } - imported <- header - } else { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - } - for i := len(hashes) - 2; i >= 0; i-- { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - verifyImportEvent(t, imported, true) - } - verifyImportDone(t, imported) - verifyChainHeight(t, tester, uint64(len(hashes)-1)) -} - -// Tests that if blocks are announced by multiple peers (or even the same buggy -// peer), they will only get downloaded at most once. -func TestFullConcurrentAnnouncements(t *testing.T) { testConcurrentAnnouncements(t, false) } -func TestLightConcurrentAnnouncements(t *testing.T) { testConcurrentAnnouncements(t, true) } - -func testConcurrentAnnouncements(t *testing.T, light bool) { - // Create a chain of blocks to import - targetBlocks := 4 * hashLimit - hashes, blocks := makeChain(targetBlocks, 0, genesis) - - // Assemble a tester with a built in counter for the requests - tester := newTester(light) - firstHeaderFetcher := tester.makeHeaderFetcher("first", blocks, -gatherSlack) - firstBodyFetcher := tester.makeBodyFetcher("first", blocks, 0) - secondHeaderFetcher := tester.makeHeaderFetcher("second", blocks, -gatherSlack) - secondBodyFetcher := tester.makeBodyFetcher("second", blocks, 0) - - var counter atomic.Uint32 - firstHeaderWrapper := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { - counter.Add(1) - return firstHeaderFetcher(hash, sink) - } - secondHeaderWrapper := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { - counter.Add(1) - return secondHeaderFetcher(hash, sink) - } - // Iteratively announce blocks until all are imported - imported := make(chan interface{}) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if light { - if header == nil { - t.Fatalf("Fetcher try to import empty header") - } - imported <- header - } else { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - } - for i := len(hashes) - 2; i >= 0; i-- { - tester.fetcher.Notify("first", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), firstHeaderWrapper, firstBodyFetcher) - tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout+time.Millisecond), secondHeaderWrapper, secondBodyFetcher) - tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout-time.Millisecond), secondHeaderWrapper, secondBodyFetcher) - verifyImportEvent(t, imported, true) - } - verifyImportDone(t, imported) - - // Make sure no blocks were retrieved twice - if c := int(counter.Load()); c != targetBlocks { - t.Fatalf("retrieval count mismatch: have %v, want %v", c, targetBlocks) - } - verifyChainHeight(t, tester, uint64(len(hashes)-1)) -} - -// Tests that announcements arriving while a previous is being fetched still -// results in a valid import. -func TestFullOverlappingAnnouncements(t *testing.T) { testOverlappingAnnouncements(t, false) } -func TestLightOverlappingAnnouncements(t *testing.T) { testOverlappingAnnouncements(t, true) } - -func testOverlappingAnnouncements(t *testing.T, light bool) { - // Create a chain of blocks to import - targetBlocks := 4 * hashLimit - hashes, blocks := makeChain(targetBlocks, 0, genesis) - - tester := newTester(light) - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - // Iteratively announce blocks, but overlap them continuously - overlap := 16 - imported := make(chan interface{}, len(hashes)-1) - for i := 0; i < overlap; i++ { - imported <- nil - } - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if light { - if header == nil { - t.Fatalf("Fetcher try to import empty header") - } - imported <- header - } else { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - } - - for i := len(hashes) - 2; i >= 0; i-- { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - select { - case <-imported: - case <-time.After(time.Second): - t.Fatalf("block %d: import timeout", len(hashes)-i) - } - } - // Wait for all the imports to complete and check count - verifyImportCount(t, imported, overlap) - verifyChainHeight(t, tester, uint64(len(hashes)-1)) -} - -// Tests that announces already being retrieved will not be duplicated. -func TestFullPendingDeduplication(t *testing.T) { testPendingDeduplication(t, false) } -func TestLightPendingDeduplication(t *testing.T) { testPendingDeduplication(t, true) } - -func testPendingDeduplication(t *testing.T, light bool) { - // Create a hash and corresponding block - hashes, blocks := makeChain(1, 0, genesis) - - // Assemble a tester with a built in counter and delayed fetcher - tester := newTester(light) - headerFetcher := tester.makeHeaderFetcher("repeater", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("repeater", blocks, 0) - - delay := 50 * time.Millisecond - var counter atomic.Uint32 - headerWrapper := func(hash common.Hash, sink chan *eth.Response) (*eth.Request, error) { - counter.Add(1) - - // Simulate a long running fetch - resink := make(chan *eth.Response) - req, err := headerFetcher(hash, resink) - if err == nil { - go func() { - res := <-resink - time.Sleep(delay) - sink <- res - }() - } - return req, err - } - checkNonExist := func() bool { - return tester.getBlock(hashes[0]) == nil - } - if light { - checkNonExist = func() bool { - return tester.getHeader(hashes[0]) == nil - } - } - // Announce the same block many times until it's fetched (wait for any pending ops) - for checkNonExist() { - tester.fetcher.Notify("repeater", hashes[0], 1, time.Now().Add(-arriveTimeout), headerWrapper, bodyFetcher) - time.Sleep(time.Millisecond) - } - time.Sleep(delay) - - // Check that all blocks were imported and none fetched twice - if c := counter.Load(); c != 1 { - t.Fatalf("retrieval count mismatch: have %v, want %v", c, 1) - } - verifyChainHeight(t, tester, 1) -} - -// Tests that announcements retrieved in a random order are cached and eventually -// imported when all the gaps are filled in. -func TestFullRandomArrivalImport(t *testing.T) { testRandomArrivalImport(t, false) } -func TestLightRandomArrivalImport(t *testing.T) { testRandomArrivalImport(t, true) } - -func testRandomArrivalImport(t *testing.T, light bool) { - // Create a chain of blocks to import, and choose one to delay - targetBlocks := maxQueueDist - hashes, blocks := makeChain(targetBlocks, 0, genesis) - skip := targetBlocks / 2 - - tester := newTester(light) - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - // Iteratively announce blocks, skipping one entry - imported := make(chan interface{}, len(hashes)-1) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if light { - if header == nil { - t.Fatalf("Fetcher try to import empty header") - } - imported <- header - } else { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - } - for i := len(hashes) - 1; i >= 0; i-- { - if i != skip { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - time.Sleep(time.Millisecond) - } - } - // Finally announce the skipped entry and check full import - tester.fetcher.Notify("valid", hashes[skip], uint64(len(hashes)-skip-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - verifyImportCount(t, imported, len(hashes)-1) - verifyChainHeight(t, tester, uint64(len(hashes)-1)) -} - -// Tests that direct block enqueues (due to block propagation vs. hash announce) -// are correctly schedule, filling and import queue gaps. -func TestQueueGapFill(t *testing.T) { - // Create a chain of blocks to import, and choose one to not announce at all - targetBlocks := maxQueueDist - hashes, blocks := makeChain(targetBlocks, 0, genesis) - skip := targetBlocks / 2 - - tester := newTester(false) - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - // Iteratively announce blocks, skipping one entry - imported := make(chan interface{}, len(hashes)-1) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { imported <- block } - - for i := len(hashes) - 1; i >= 0; i-- { - if i != skip { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - time.Sleep(time.Millisecond) - } - } - // Fill the missing block directly as if propagated - tester.fetcher.Enqueue("valid", blocks[hashes[skip]]) - verifyImportCount(t, imported, len(hashes)-1) - verifyChainHeight(t, tester, uint64(len(hashes)-1)) -} - -// Tests that blocks arriving from various sources (multiple propagations, hash -// announces, etc) do not get scheduled for import multiple times. -func TestImportDeduplication(t *testing.T) { - // Create two blocks to import (one for duplication, the other for stalling) - hashes, blocks := makeChain(2, 0, genesis) - - // Create the tester and wrap the importer with a counter - tester := newTester(false) - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - var counter atomic.Uint32 - tester.fetcher.insertChain = func(blocks types.Blocks) (int, error) { - counter.Add(uint32(len(blocks))) - return tester.insertChain(blocks) - } - // Instrument the fetching and imported events - fetching := make(chan []common.Hash) - imported := make(chan interface{}, len(hashes)-1) - tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- hashes } - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { imported <- block } - - // Announce the duplicating block, wait for retrieval, and also propagate directly - tester.fetcher.Notify("valid", hashes[0], 1, time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - <-fetching - - tester.fetcher.Enqueue("valid", blocks[hashes[0]]) - tester.fetcher.Enqueue("valid", blocks[hashes[0]]) - tester.fetcher.Enqueue("valid", blocks[hashes[0]]) - - // Fill the missing block directly as if propagated, and check import uniqueness - tester.fetcher.Enqueue("valid", blocks[hashes[1]]) - verifyImportCount(t, imported, 2) - - if c := counter.Load(); c != 2 { - t.Fatalf("import invocation count mismatch: have %v, want %v", c, 2) - } -} - -// Tests that blocks with numbers much lower or higher than out current head get -// discarded to prevent wasting resources on useless blocks from faulty peers. -func TestDistantPropagationDiscarding(t *testing.T) { - // Create a long chain to import and define the discard boundaries - hashes, blocks := makeChain(3*maxQueueDist, 0, genesis) - head := hashes[len(hashes)/2] - - low, high := len(hashes)/2+maxUncleDist+1, len(hashes)/2-maxQueueDist-1 - - // Create a tester and simulate a head block being the middle of the above chain - tester := newTester(false) - - tester.lock.Lock() - tester.hashes = []common.Hash{head} - tester.blocks = map[common.Hash]*types.Block{head: blocks[head]} - tester.lock.Unlock() - - // Ensure that a block with a lower number than the threshold is discarded - tester.fetcher.Enqueue("lower", blocks[hashes[low]]) - time.Sleep(10 * time.Millisecond) - if !tester.fetcher.queue.Empty() { - t.Fatalf("fetcher queued stale block") - } - // Ensure that a block with a higher number than the threshold is discarded - tester.fetcher.Enqueue("higher", blocks[hashes[high]]) - time.Sleep(10 * time.Millisecond) - if !tester.fetcher.queue.Empty() { - t.Fatalf("fetcher queued future block") - } -} - -// Tests that announcements with numbers much lower or higher than out current -// head get discarded to prevent wasting resources on useless blocks from faulty -// peers. -func TestFullDistantAnnouncementDiscarding(t *testing.T) { testDistantAnnouncementDiscarding(t, false) } -func TestLightDistantAnnouncementDiscarding(t *testing.T) { testDistantAnnouncementDiscarding(t, true) } - -func testDistantAnnouncementDiscarding(t *testing.T, light bool) { - // Create a long chain to import and define the discard boundaries - hashes, blocks := makeChain(3*maxQueueDist, 0, genesis) - head := hashes[len(hashes)/2] - - low, high := len(hashes)/2+maxUncleDist+1, len(hashes)/2-maxQueueDist-1 - - // Create a tester and simulate a head block being the middle of the above chain - tester := newTester(light) - - tester.lock.Lock() - tester.hashes = []common.Hash{head} - tester.headers = map[common.Hash]*types.Header{head: blocks[head].Header()} - tester.blocks = map[common.Hash]*types.Block{head: blocks[head]} - tester.lock.Unlock() - - headerFetcher := tester.makeHeaderFetcher("lower", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("lower", blocks, 0) - - fetching := make(chan struct{}, 2) - tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- struct{}{} } - - // Ensure that a block with a lower number than the threshold is discarded - tester.fetcher.Notify("lower", hashes[low], blocks[hashes[low]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - select { - case <-time.After(50 * time.Millisecond): - case <-fetching: - t.Fatalf("fetcher requested stale header") - } - // Ensure that a block with a higher number than the threshold is discarded - tester.fetcher.Notify("higher", hashes[high], blocks[hashes[high]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - select { - case <-time.After(50 * time.Millisecond): - case <-fetching: - t.Fatalf("fetcher requested future header") - } -} - -// Tests that peers announcing blocks with invalid numbers (i.e. not matching -// the headers provided afterwards) get dropped as malicious. -func TestFullInvalidNumberAnnouncement(t *testing.T) { testInvalidNumberAnnouncement(t, false) } -func TestLightInvalidNumberAnnouncement(t *testing.T) { testInvalidNumberAnnouncement(t, true) } - -func testInvalidNumberAnnouncement(t *testing.T, light bool) { - // Create a single block to import and check numbers against - hashes, blocks := makeChain(1, 0, genesis) - - tester := newTester(light) - badHeaderFetcher := tester.makeHeaderFetcher("bad", blocks, -gatherSlack) - badBodyFetcher := tester.makeBodyFetcher("bad", blocks, 0) - - imported := make(chan interface{}) - announced := make(chan interface{}, 2) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if light { - if header == nil { - t.Fatalf("Fetcher try to import empty header") - } - imported <- header - } else { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - } - // Announce a block with a bad number, check for immediate drop - tester.fetcher.announceChangeHook = func(hash common.Hash, b bool) { - announced <- nil - } - tester.fetcher.Notify("bad", hashes[0], 2, time.Now().Add(-arriveTimeout), badHeaderFetcher, badBodyFetcher) - verifyAnnounce := func() { - for i := 0; i < 2; i++ { - select { - case <-announced: - continue - case <-time.After(1 * time.Second): - t.Fatal("announce timeout") - return - } - } - } - verifyAnnounce() - verifyImportEvent(t, imported, false) - tester.lock.RLock() - dropped := tester.drops["bad"] - tester.lock.RUnlock() - - if !dropped { - t.Fatalf("peer with invalid numbered announcement not dropped") - } - goodHeaderFetcher := tester.makeHeaderFetcher("good", blocks, -gatherSlack) - goodBodyFetcher := tester.makeBodyFetcher("good", blocks, 0) - // Make sure a good announcement passes without a drop - tester.fetcher.Notify("good", hashes[0], 1, time.Now().Add(-arriveTimeout), goodHeaderFetcher, goodBodyFetcher) - verifyAnnounce() - verifyImportEvent(t, imported, true) - - tester.lock.RLock() - dropped = tester.drops["good"] - tester.lock.RUnlock() - - if dropped { - t.Fatalf("peer with valid numbered announcement dropped") - } - verifyImportDone(t, imported) -} - -// Tests that if a block is empty (i.e. header only), no body request should be -// made, and instead the header should be assembled into a whole block in itself. -func TestEmptyBlockShortCircuit(t *testing.T) { - // Create a chain of blocks to import - hashes, blocks := makeChain(32, 0, genesis) - - tester := newTester(false) - defer tester.fetcher.Stop() - headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - // Add a monitoring hook for all internal events - fetching := make(chan []common.Hash) - tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- hashes } - - completing := make(chan []common.Hash) - tester.fetcher.completingHook = func(hashes []common.Hash) { completing <- hashes } - - imported := make(chan interface{}) - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { - if block == nil { - t.Fatalf("Fetcher try to import empty block") - } - imported <- block - } - // Iteratively announce blocks until all are imported - for i := len(hashes) - 2; i >= 0; i-- { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher) - - // All announces should fetch the header - verifyFetchingEvent(t, fetching, true) - - // Only blocks with data contents should request bodies - verifyCompletingEvent(t, completing, len(blocks[hashes[i]].Transactions()) > 0 || len(blocks[hashes[i]].Uncles()) > 0) - - // Irrelevant of the construct, import should succeed - verifyImportEvent(t, imported, true) - } - verifyImportDone(t, imported) -} - -// Tests that a peer is unable to use unbounded memory with sending infinite -// block announcements to a node, but that even in the face of such an attack, -// the fetcher remains operational. -func TestHashMemoryExhaustionAttack(t *testing.T) { - // Create a tester with instrumented import hooks - tester := newTester(false) - - imported, announces := make(chan interface{}), atomic.Int32{} - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { imported <- block } - tester.fetcher.announceChangeHook = func(hash common.Hash, added bool) { - if added { - announces.Add(1) - } else { - announces.Add(-1) - } - } - // Create a valid chain and an infinite junk chain - targetBlocks := hashLimit + 2*maxQueueDist - hashes, blocks := makeChain(targetBlocks, 0, genesis) - validHeaderFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack) - validBodyFetcher := tester.makeBodyFetcher("valid", blocks, 0) - - attack, _ := makeChain(targetBlocks, 0, unknownBlock) - attackerHeaderFetcher := tester.makeHeaderFetcher("attacker", nil, -gatherSlack) - attackerBodyFetcher := tester.makeBodyFetcher("attacker", nil, 0) - - // Feed the tester a huge hashset from the attacker, and a limited from the valid peer - for i := 0; i < len(attack); i++ { - if i < maxQueueDist { - tester.fetcher.Notify("valid", hashes[len(hashes)-2-i], uint64(i+1), time.Now(), validHeaderFetcher, validBodyFetcher) - } - tester.fetcher.Notify("attacker", attack[i], 1 /* don't distance drop */, time.Now(), attackerHeaderFetcher, attackerBodyFetcher) - } - if count := announces.Load(); count != hashLimit+maxQueueDist { - t.Fatalf("queued announce count mismatch: have %d, want %d", count, hashLimit+maxQueueDist) - } - // Wait for fetches to complete - verifyImportCount(t, imported, maxQueueDist) - - // Feed the remaining valid hashes to ensure DOS protection state remains clean - for i := len(hashes) - maxQueueDist - 2; i >= 0; i-- { - tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), validHeaderFetcher, validBodyFetcher) - verifyImportEvent(t, imported, true) - } - verifyImportDone(t, imported) -} - -// Tests that blocks sent to the fetcher (either through propagation or via hash -// announces and retrievals) don't pile up indefinitely, exhausting available -// system memory. -func TestBlockMemoryExhaustionAttack(t *testing.T) { - // Create a tester with instrumented import hooks - tester := newTester(false) - - imported, enqueued := make(chan interface{}), atomic.Int32{} - tester.fetcher.importedHook = func(header *types.Header, block *types.Block) { imported <- block } - tester.fetcher.queueChangeHook = func(hash common.Hash, added bool) { - if added { - enqueued.Add(1) - } else { - enqueued.Add(-1) - } - } - // Create a valid chain and a batch of dangling (but in range) blocks - targetBlocks := hashLimit + 2*maxQueueDist - hashes, blocks := makeChain(targetBlocks, 0, genesis) - attack := make(map[common.Hash]*types.Block) - for i := byte(0); len(attack) < blockLimit+2*maxQueueDist; i++ { - hashes, blocks := makeChain(maxQueueDist-1, i, unknownBlock) - for _, hash := range hashes[:maxQueueDist-2] { - attack[hash] = blocks[hash] - } - } - // Try to feed all the attacker blocks make sure only a limited batch is accepted - for _, block := range attack { - tester.fetcher.Enqueue("attacker", block) - } - time.Sleep(200 * time.Millisecond) - if queued := enqueued.Load(); queued != blockLimit { - t.Fatalf("queued block count mismatch: have %d, want %d", queued, blockLimit) - } - // Queue up a batch of valid blocks, and check that a new peer is allowed to do so - for i := 0; i < maxQueueDist-1; i++ { - tester.fetcher.Enqueue("valid", blocks[hashes[len(hashes)-3-i]]) - } - time.Sleep(100 * time.Millisecond) - if queued := enqueued.Load(); queued != blockLimit+maxQueueDist-1 { - t.Fatalf("queued block count mismatch: have %d, want %d", queued, blockLimit+maxQueueDist-1) - } - // Insert the missing piece (and sanity check the import) - tester.fetcher.Enqueue("valid", blocks[hashes[len(hashes)-2]]) - verifyImportCount(t, imported, maxQueueDist) - - // Insert the remaining blocks in chunks to ensure clean DOS protection - for i := maxQueueDist; i < len(hashes)-1; i++ { - tester.fetcher.Enqueue("valid", blocks[hashes[len(hashes)-2-i]]) - verifyImportEvent(t, imported, true) - } - verifyImportDone(t, imported) -} diff --git a/builder/eth/fetcher/tx_fetcher.go b/builder/eth/fetcher/tx_fetcher.go deleted file mode 100644 index ea7892d8d..000000000 --- a/builder/eth/fetcher/tx_fetcher.go +++ /dev/null @@ -1,1003 +0,0 @@ -// 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 fetcher - -import ( - "bytes" - "errors" - "fmt" - "math" - mrand "math/rand" - "sort" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" -) - -const ( - // maxTxAnnounces is the maximum number of unique transaction a peer - // can announce in a short time. - maxTxAnnounces = 4096 - - // maxTxRetrievals is the maximum number of transactions that can be fetched - // in one request. The rationale for picking 256 is to have a reasonabe lower - // bound for the transferred data (don't waste RTTs, transfer more meaningful - // batch sizes), but also have an upper bound on the sequentiality to allow - // using our entire peerset for deliveries. - // - // This number also acts as a failsafe against malicious announces which might - // cause us to request more data than we'd expect. - maxTxRetrievals = 256 - - // maxTxRetrievalSize is the max number of bytes that delivered transactions - // should weigh according to the announcements. The 128KB was chosen to limit - // retrieving a maximum of one blob transaction at a time to minimize hogging - // a connection between two peers. - maxTxRetrievalSize = 128 * 1024 - - // maxTxUnderpricedSetSize is the size of the underpriced transaction set that - // is used to track recent transactions that have been dropped so we don't - // re-request them. - maxTxUnderpricedSetSize = 32768 - - // maxTxUnderpricedTimeout is the max time a transaction should be stuck in the underpriced set. - maxTxUnderpricedTimeout = 5 * time.Minute - - // txArriveTimeout is the time allowance before an announced transaction is - // explicitly requested. - txArriveTimeout = 500 * time.Millisecond - - // txGatherSlack is the interval used to collate almost-expired announces - // with network fetches. - txGatherSlack = 100 * time.Millisecond -) - -var ( - // txFetchTimeout is the maximum allotted time to return an explicitly - // requested transaction. - txFetchTimeout = 5 * time.Second -) - -var ( - txAnnounceInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/in", nil) - txAnnounceKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/known", nil) - txAnnounceUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/underpriced", nil) - txAnnounceDOSMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/dos", nil) - - txBroadcastInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/in", nil) - txBroadcastKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/known", nil) - txBroadcastUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/underpriced", nil) - txBroadcastOtherRejectMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/otherreject", nil) - - txRequestOutMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/out", nil) - txRequestFailMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/fail", nil) - txRequestDoneMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/done", nil) - txRequestTimeoutMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/timeout", nil) - - txReplyInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/in", nil) - txReplyKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/known", nil) - txReplyUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/underpriced", nil) - txReplyOtherRejectMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/otherreject", nil) - - txFetcherWaitingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/waiting/peers", nil) - txFetcherWaitingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/waiting/hashes", nil) - txFetcherQueueingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/queueing/peers", nil) - txFetcherQueueingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/queueing/hashes", nil) - txFetcherFetchingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/fetching/peers", nil) - txFetcherFetchingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/fetching/hashes", nil) -) - -// txAnnounce is the notification of the availability of a batch -// of new transactions in the network. -type txAnnounce struct { - origin string // Identifier of the peer originating the notification - hashes []common.Hash // Batch of transaction hashes being announced - metas []*txMetadata // Batch of metadatas associated with the hashes (nil before eth/68) -} - -// txMetadata is a set of extra data transmitted along the announcement for better -// fetch scheduling. -type txMetadata struct { - kind byte // Transaction consensus type - size uint32 // Transaction size in bytes -} - -// txRequest represents an in-flight transaction retrieval request destined to -// a specific peers. -type txRequest struct { - hashes []common.Hash // Transactions having been requested - stolen map[common.Hash]struct{} // Deliveries by someone else (don't re-request) - time mclock.AbsTime // Timestamp of the request -} - -// txDelivery is the notification that a batch of transactions have been added -// to the pool and should be untracked. -type txDelivery struct { - origin string // Identifier of the peer originating the notification - hashes []common.Hash // Batch of transaction hashes having been delivered - metas []txMetadata // Batch of metadatas associated with the delivered hashes - direct bool // Whether this is a direct reply or a broadcast -} - -// txDrop is the notification that a peer has disconnected. -type txDrop struct { - peer string -} - -// TxFetcher is responsible for retrieving new transaction based on announcements. -// -// The fetcher operates in 3 stages: -// - Transactions that are newly discovered are moved into a wait list. -// - After ~500ms passes, transactions from the wait list that have not been -// broadcast to us in whole are moved into a queueing area. -// - When a connected peer doesn't have in-flight retrieval requests, any -// transaction queued up (and announced by the peer) are allocated to the -// peer and moved into a fetching status until it's fulfilled or fails. -// -// The invariants of the fetcher are: -// - Each tracked transaction (hash) must only be present in one of the -// three stages. This ensures that the fetcher operates akin to a finite -// state automata and there's do data leak. -// - Each peer that announced transactions may be scheduled retrievals, but -// only ever one concurrently. This ensures we can immediately know what is -// missing from a reply and reschedule it. -type TxFetcher struct { - notify chan *txAnnounce - cleanup chan *txDelivery - drop chan *txDrop - quit chan struct{} - - underpriced *lru.Cache[common.Hash, time.Time] // Transactions discarded as too cheap (don't re-fetch) - - // Stage 1: Waiting lists for newly discovered transactions that might be - // broadcast without needing explicit request/reply round trips. - waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast - waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist - waitslots map[string]map[common.Hash]*txMetadata // Waiting announcements grouped by peer (DoS protection) - - // Stage 2: Queue of transactions that waiting to be allocated to some peer - // to be retrieved directly. - announces map[string]map[common.Hash]*txMetadata // Set of announced transactions, grouped by origin peer - announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash - - // Stage 3: Set of transactions currently being retrieved, some which may be - // fulfilled and some rescheduled. Note, this step shares 'announces' from the - // previous stage to avoid having to duplicate (need it for DoS checks). - fetching map[common.Hash]string // Transaction set currently being retrieved - requests map[string]*txRequest // In-flight transaction retrievals - alternates map[common.Hash]map[string]struct{} // In-flight transaction alternate origins if retrieval fails - - // Callbacks - hasTx func(common.Hash) bool // Retrieves a tx from the local txpool - addTxs func([]*types.Transaction) []error // Insert a batch of transactions into local txpool - fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer - dropPeer func(string) // Drops a peer in case of announcement violation - - step chan struct{} // Notification channel when the fetcher loop iterates - clock mclock.Clock // Time wrapper to simulate in tests - rand *mrand.Rand // Randomizer to use in tests instead of map range loops (soft-random) -} - -// NewTxFetcher creates a transaction fetcher to retrieve transaction -// based on hash announcements. -func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher { - return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, dropPeer, mclock.System{}, nil) -} - -// NewTxFetcherForTests is a testing method to mock out the realtime clock with -// a simulated version and the internal randomness with a deterministic one. -func NewTxFetcherForTests( - hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string), - clock mclock.Clock, rand *mrand.Rand) *TxFetcher { - return &TxFetcher{ - notify: make(chan *txAnnounce), - cleanup: make(chan *txDelivery), - drop: make(chan *txDrop), - quit: make(chan struct{}), - waitlist: make(map[common.Hash]map[string]struct{}), - waittime: make(map[common.Hash]mclock.AbsTime), - waitslots: make(map[string]map[common.Hash]*txMetadata), - announces: make(map[string]map[common.Hash]*txMetadata), - announced: make(map[common.Hash]map[string]struct{}), - fetching: make(map[common.Hash]string), - requests: make(map[string]*txRequest), - alternates: make(map[common.Hash]map[string]struct{}), - underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize), - hasTx: hasTx, - addTxs: addTxs, - fetchTxs: fetchTxs, - dropPeer: dropPeer, - clock: clock, - rand: rand, - } -} - -// Notify announces the fetcher of the potential availability of a new batch of -// transactions in the network. -func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []common.Hash) error { - // Keep track of all the announced transactions - txAnnounceInMeter.Mark(int64(len(hashes))) - - // Skip any transaction announcements that we already know of, or that we've - // previously marked as cheap and discarded. This check is of course racy, - // because multiple concurrent notifies will still manage to pass it, but it's - // still valuable to check here because it runs concurrent to the internal - // loop, so anything caught here is time saved internally. - var ( - unknownHashes = make([]common.Hash, 0, len(hashes)) - unknownMetas = make([]*txMetadata, 0, len(hashes)) - - duplicate int64 - underpriced int64 - ) - for i, hash := range hashes { - switch { - case f.hasTx(hash): - duplicate++ - case f.isKnownUnderpriced(hash): - underpriced++ - default: - unknownHashes = append(unknownHashes, hash) - if types == nil { - unknownMetas = append(unknownMetas, nil) - } else { - unknownMetas = append(unknownMetas, &txMetadata{kind: types[i], size: sizes[i]}) - } - } - } - txAnnounceKnownMeter.Mark(duplicate) - txAnnounceUnderpricedMeter.Mark(underpriced) - - // If anything's left to announce, push it into the internal loop - if len(unknownHashes) == 0 { - return nil - } - announce := &txAnnounce{origin: peer, hashes: unknownHashes, metas: unknownMetas} - select { - case f.notify <- announce: - return nil - case <-f.quit: - return errTerminated - } -} - -// isKnownUnderpriced reports whether a transaction hash was recently found to be underpriced. -func (f *TxFetcher) isKnownUnderpriced(hash common.Hash) bool { - prevTime, ok := f.underpriced.Peek(hash) - if ok && prevTime.Before(time.Now().Add(-maxTxUnderpricedTimeout)) { - f.underpriced.Remove(hash) - return false - } - return ok -} - -// Enqueue imports a batch of received transaction into the transaction pool -// and the fetcher. This method may be called by both transaction broadcasts and -// direct request replies. The differentiation is important so the fetcher can -// re-schedule missing transactions as soon as possible. -func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool) error { - var ( - inMeter = txReplyInMeter - knownMeter = txReplyKnownMeter - underpricedMeter = txReplyUnderpricedMeter - otherRejectMeter = txReplyOtherRejectMeter - ) - if !direct { - inMeter = txBroadcastInMeter - knownMeter = txBroadcastKnownMeter - underpricedMeter = txBroadcastUnderpricedMeter - otherRejectMeter = txBroadcastOtherRejectMeter - } - // Keep track of all the propagated transactions - inMeter.Mark(int64(len(txs))) - - // Push all the transactions into the pool, tracking underpriced ones to avoid - // re-requesting them and dropping the peer in case of malicious transfers. - var ( - added = make([]common.Hash, 0, len(txs)) - metas = make([]txMetadata, 0, len(txs)) - ) - // proceed in batches - for i := 0; i < len(txs); i += 128 { - end := i + 128 - if end > len(txs) { - end = len(txs) - } - var ( - duplicate int64 - underpriced int64 - otherreject int64 - ) - batch := txs[i:end] - - for j, err := range f.addTxs(batch) { - // Track the transaction hash if the price is too low for us. - // Avoid re-request this transaction when we receive another - // announcement. - if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) { - f.underpriced.Add(batch[j].Hash(), batch[j].Time()) - } - // Track a few interesting failure types - switch { - case err == nil: // Noop, but need to handle to not count these - - case errors.Is(err, txpool.ErrAlreadyKnown): - duplicate++ - - case errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced): - underpriced++ - - default: - otherreject++ - } - added = append(added, batch[j].Hash()) - metas = append(metas, txMetadata{ - kind: batch[j].Type(), - size: uint32(batch[j].Size()), - }) - } - knownMeter.Mark(duplicate) - underpricedMeter.Mark(underpriced) - otherRejectMeter.Mark(otherreject) - - // If 'other reject' is >25% of the deliveries in any batch, sleep a bit. - if otherreject > 128/4 { - time.Sleep(200 * time.Millisecond) - log.Debug("Peer delivering stale transactions", "peer", peer, "rejected", otherreject) - } - } - select { - case f.cleanup <- &txDelivery{origin: peer, hashes: added, metas: metas, direct: direct}: - return nil - case <-f.quit: - return errTerminated - } -} - -// Drop should be called when a peer disconnects. It cleans up all the internal -// data structures of the given node. -func (f *TxFetcher) Drop(peer string) error { - select { - case f.drop <- &txDrop{peer: peer}: - return nil - case <-f.quit: - return errTerminated - } -} - -// Start boots up the announcement based synchroniser, accepting and processing -// hash notifications and block fetches until termination requested. -func (f *TxFetcher) Start() { - go f.loop() -} - -// Stop terminates the announcement based synchroniser, canceling all pending -// operations. -func (f *TxFetcher) Stop() { - close(f.quit) -} - -func (f *TxFetcher) loop() { - var ( - waitTimer = new(mclock.Timer) - timeoutTimer = new(mclock.Timer) - - waitTrigger = make(chan struct{}, 1) - timeoutTrigger = make(chan struct{}, 1) - ) - for { - select { - case ann := <-f.notify: - // Drop part of the new announcements if there are too many accumulated. - // Note, we could but do not filter already known transactions here as - // the probability of something arriving between this call and the pre- - // filter outside is essentially zero. - used := len(f.waitslots[ann.origin]) + len(f.announces[ann.origin]) - if used >= maxTxAnnounces { - // This can happen if a set of transactions are requested but not - // all fulfilled, so the remainder are rescheduled without the cap - // check. Should be fine as the limit is in the thousands and the - // request size in the hundreds. - txAnnounceDOSMeter.Mark(int64(len(ann.hashes))) - break - } - want := used + len(ann.hashes) - if want > maxTxAnnounces { - txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces)) - - ann.hashes = ann.hashes[:want-maxTxAnnounces] - ann.metas = ann.metas[:want-maxTxAnnounces] - } - // All is well, schedule the remainder of the transactions - idleWait := len(f.waittime) == 0 - _, oldPeer := f.announces[ann.origin] - - for i, hash := range ann.hashes { - // If the transaction is already downloading, add it to the list - // of possible alternates (in case the current retrieval fails) and - // also account it for the peer. - if f.alternates[hash] != nil { - f.alternates[hash][ann.origin] = struct{}{} - - // Stage 2 and 3 share the set of origins per tx - if announces := f.announces[ann.origin]; announces != nil { - announces[hash] = ann.metas[i] - } else { - f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} - } - continue - } - // If the transaction is not downloading, but is already queued - // from a different peer, track it for the new peer too. - if f.announced[hash] != nil { - f.announced[hash][ann.origin] = struct{}{} - - // Stage 2 and 3 share the set of origins per tx - if announces := f.announces[ann.origin]; announces != nil { - announces[hash] = ann.metas[i] - } else { - f.announces[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} - } - continue - } - // If the transaction is already known to the fetcher, but not - // yet downloading, add the peer as an alternate origin in the - // waiting list. - if f.waitlist[hash] != nil { - // Ignore double announcements from the same peer. This is - // especially important if metadata is also passed along to - // prevent malicious peers flip-flopping good/bad values. - if _, ok := f.waitlist[hash][ann.origin]; ok { - continue - } - f.waitlist[hash][ann.origin] = struct{}{} - - if waitslots := f.waitslots[ann.origin]; waitslots != nil { - waitslots[hash] = ann.metas[i] - } else { - f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} - } - continue - } - // Transaction unknown to the fetcher, insert it into the waiting list - f.waitlist[hash] = map[string]struct{}{ann.origin: {}} - f.waittime[hash] = f.clock.Now() - - if waitslots := f.waitslots[ann.origin]; waitslots != nil { - waitslots[hash] = ann.metas[i] - } else { - f.waitslots[ann.origin] = map[common.Hash]*txMetadata{hash: ann.metas[i]} - } - } - // If a new item was added to the waitlist, schedule it into the fetcher - if idleWait && len(f.waittime) > 0 { - f.rescheduleWait(waitTimer, waitTrigger) - } - // If this peer is new and announced something already queued, maybe - // request transactions from them - if !oldPeer && len(f.announces[ann.origin]) > 0 { - f.scheduleFetches(timeoutTimer, timeoutTrigger, map[string]struct{}{ann.origin: {}}) - } - - case <-waitTrigger: - // At least one transaction's waiting time ran out, push all expired - // ones into the retrieval queues - actives := make(map[string]struct{}) - for hash, instance := range f.waittime { - if time.Duration(f.clock.Now()-instance)+txGatherSlack > txArriveTimeout { - // Transaction expired without propagation, schedule for retrieval - if f.announced[hash] != nil { - panic("announce tracker already contains waitlist item") - } - f.announced[hash] = f.waitlist[hash] - for peer := range f.waitlist[hash] { - if announces := f.announces[peer]; announces != nil { - announces[hash] = f.waitslots[peer][hash] - } else { - f.announces[peer] = map[common.Hash]*txMetadata{hash: f.waitslots[peer][hash]} - } - delete(f.waitslots[peer], hash) - if len(f.waitslots[peer]) == 0 { - delete(f.waitslots, peer) - } - actives[peer] = struct{}{} - } - delete(f.waittime, hash) - delete(f.waitlist, hash) - } - } - // If transactions are still waiting for propagation, reschedule the wait timer - if len(f.waittime) > 0 { - f.rescheduleWait(waitTimer, waitTrigger) - } - // If any peers became active and are idle, request transactions from them - if len(actives) > 0 { - f.scheduleFetches(timeoutTimer, timeoutTrigger, actives) - } - - case <-timeoutTrigger: - // Clean up any expired retrievals and avoid re-requesting them from the - // same peer (either overloaded or malicious, useless in both cases). We - // could also penalize (Drop), but there's nothing to gain, and if could - // possibly further increase the load on it. - for peer, req := range f.requests { - if time.Duration(f.clock.Now()-req.time)+txGatherSlack > txFetchTimeout { - txRequestTimeoutMeter.Mark(int64(len(req.hashes))) - - // Reschedule all the not-yet-delivered fetches to alternate peers - for _, hash := range req.hashes { - // Skip rescheduling hashes already delivered by someone else - if req.stolen != nil { - if _, ok := req.stolen[hash]; ok { - continue - } - } - // Move the delivery back from fetching to queued - if _, ok := f.announced[hash]; ok { - panic("announced tracker already contains alternate item") - } - if f.alternates[hash] != nil { // nil if tx was broadcast during fetch - f.announced[hash] = f.alternates[hash] - } - delete(f.announced[hash], peer) - if len(f.announced[hash]) == 0 { - delete(f.announced, hash) - } - delete(f.announces[peer], hash) - delete(f.alternates, hash) - delete(f.fetching, hash) - } - if len(f.announces[peer]) == 0 { - delete(f.announces, peer) - } - // Keep track of the request as dangling, but never expire - f.requests[peer].hashes = nil - } - } - // Schedule a new transaction retrieval - f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) - - // No idea if we scheduled something or not, trigger the timer if needed - // TODO(karalabe): this is kind of lame, can't we dump it into scheduleFetches somehow? - f.rescheduleTimeout(timeoutTimer, timeoutTrigger) - - case delivery := <-f.cleanup: - // Independent if the delivery was direct or broadcast, remove all - // traces of the hash from internal trackers. That said, compare any - // advertised metadata with the real ones and drop bad peers. - for i, hash := range delivery.hashes { - if _, ok := f.waitlist[hash]; ok { - for peer, txset := range f.waitslots { - if meta := txset[hash]; meta != nil { - if delivery.metas[i].kind != meta.kind { - log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind) - f.dropPeer(peer) - } else if delivery.metas[i].size != meta.size { - if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 { - log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size) - - // Normally we should drop a peer considering this is a protocol violation. - // However, due to the RLP vs consensus format messyness, allow a few bytes - // wiggle-room where we only warn, but don't drop. - // - // TODO(karalabe): Get rid of this relaxation when clients are proven stable. - f.dropPeer(peer) - } - } - } - delete(txset, hash) - if len(txset) == 0 { - delete(f.waitslots, peer) - } - } - delete(f.waitlist, hash) - delete(f.waittime, hash) - } else { - for peer, txset := range f.announces { - if meta := txset[hash]; meta != nil { - if delivery.metas[i].kind != meta.kind { - log.Warn("Announced transaction type mismatch", "peer", peer, "tx", hash, "type", delivery.metas[i].kind, "ann", meta.kind) - f.dropPeer(peer) - } else if delivery.metas[i].size != meta.size { - if math.Abs(float64(delivery.metas[i].size)-float64(meta.size)) > 8 { - log.Warn("Announced transaction size mismatch", "peer", peer, "tx", hash, "size", delivery.metas[i].size, "ann", meta.size) - - // Normally we should drop a peer considering this is a protocol violation. - // However, due to the RLP vs consensus format messyness, allow a few bytes - // wiggle-room where we only warn, but don't drop. - // - // TODO(karalabe): Get rid of this relaxation when clients are proven stable. - f.dropPeer(peer) - } - } - } - delete(txset, hash) - if len(txset) == 0 { - delete(f.announces, peer) - } - } - delete(f.announced, hash) - delete(f.alternates, hash) - - // If a transaction currently being fetched from a different - // origin was delivered (delivery stolen), mark it so the - // actual delivery won't double schedule it. - if origin, ok := f.fetching[hash]; ok && (origin != delivery.origin || !delivery.direct) { - stolen := f.requests[origin].stolen - if stolen == nil { - f.requests[origin].stolen = make(map[common.Hash]struct{}) - stolen = f.requests[origin].stolen - } - stolen[hash] = struct{}{} - } - delete(f.fetching, hash) - } - } - // In case of a direct delivery, also reschedule anything missing - // from the original query - if delivery.direct { - // Mark the requesting successful (independent of individual status) - txRequestDoneMeter.Mark(int64(len(delivery.hashes))) - - // Make sure something was pending, nuke it - req := f.requests[delivery.origin] - if req == nil { - log.Warn("Unexpected transaction delivery", "peer", delivery.origin) - break - } - delete(f.requests, delivery.origin) - - // Anything not delivered should be re-scheduled (with or without - // this peer, depending on the response cutoff) - delivered := make(map[common.Hash]struct{}) - for _, hash := range delivery.hashes { - delivered[hash] = struct{}{} - } - cutoff := len(req.hashes) // If nothing is delivered, assume everything is missing, don't retry!!! - for i, hash := range req.hashes { - if _, ok := delivered[hash]; ok { - cutoff = i - } - } - // Reschedule missing hashes from alternates, not-fulfilled from alt+self - for i, hash := range req.hashes { - // Skip rescheduling hashes already delivered by someone else - if req.stolen != nil { - if _, ok := req.stolen[hash]; ok { - continue - } - } - if _, ok := delivered[hash]; !ok { - if i < cutoff { - delete(f.alternates[hash], delivery.origin) - delete(f.announces[delivery.origin], hash) - if len(f.announces[delivery.origin]) == 0 { - delete(f.announces, delivery.origin) - } - } - if len(f.alternates[hash]) > 0 { - if _, ok := f.announced[hash]; ok { - panic(fmt.Sprintf("announced tracker already contains alternate item: %v", f.announced[hash])) - } - f.announced[hash] = f.alternates[hash] - } - } - delete(f.alternates, hash) - delete(f.fetching, hash) - } - // Something was delivered, try to reschedule requests - f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) // Partial delivery may enable others to deliver too - } - - case drop := <-f.drop: - // A peer was dropped, remove all traces of it - if _, ok := f.waitslots[drop.peer]; ok { - for hash := range f.waitslots[drop.peer] { - delete(f.waitlist[hash], drop.peer) - if len(f.waitlist[hash]) == 0 { - delete(f.waitlist, hash) - delete(f.waittime, hash) - } - } - delete(f.waitslots, drop.peer) - if len(f.waitlist) > 0 { - f.rescheduleWait(waitTimer, waitTrigger) - } - } - // Clean up any active requests - var request *txRequest - if request = f.requests[drop.peer]; request != nil { - for _, hash := range request.hashes { - // Skip rescheduling hashes already delivered by someone else - if request.stolen != nil { - if _, ok := request.stolen[hash]; ok { - continue - } - } - // Undelivered hash, reschedule if there's an alternative origin available - delete(f.alternates[hash], drop.peer) - if len(f.alternates[hash]) == 0 { - delete(f.alternates, hash) - } else { - f.announced[hash] = f.alternates[hash] - delete(f.alternates, hash) - } - delete(f.fetching, hash) - } - delete(f.requests, drop.peer) - } - // Clean up general announcement tracking - if _, ok := f.announces[drop.peer]; ok { - for hash := range f.announces[drop.peer] { - delete(f.announced[hash], drop.peer) - if len(f.announced[hash]) == 0 { - delete(f.announced, hash) - } - } - delete(f.announces, drop.peer) - } - // If a request was cancelled, check if anything needs to be rescheduled - if request != nil { - f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) - f.rescheduleTimeout(timeoutTimer, timeoutTrigger) - } - - case <-f.quit: - return - } - // No idea what happened, but bump some sanity metrics - txFetcherWaitingPeers.Update(int64(len(f.waitslots))) - txFetcherWaitingHashes.Update(int64(len(f.waitlist))) - txFetcherQueueingPeers.Update(int64(len(f.announces) - len(f.requests))) - txFetcherQueueingHashes.Update(int64(len(f.announced))) - txFetcherFetchingPeers.Update(int64(len(f.requests))) - txFetcherFetchingHashes.Update(int64(len(f.fetching))) - - // Loop did something, ping the step notifier if needed (tests) - if f.step != nil { - f.step <- struct{}{} - } - } -} - -// rescheduleWait iterates over all the transactions currently in the waitlist -// and schedules the movement into the fetcher for the earliest. -// -// The method has a granularity of 'gatherSlack', since there's not much point in -// spinning over all the transactions just to maybe find one that should trigger -// a few ms earlier. -func (f *TxFetcher) rescheduleWait(timer *mclock.Timer, trigger chan struct{}) { - if *timer != nil { - (*timer).Stop() - } - now := f.clock.Now() - - earliest := now - for _, instance := range f.waittime { - if earliest > instance { - earliest = instance - if txArriveTimeout-time.Duration(now-earliest) < gatherSlack { - break - } - } - } - *timer = f.clock.AfterFunc(txArriveTimeout-time.Duration(now-earliest), func() { - trigger <- struct{}{} - }) -} - -// rescheduleTimeout iterates over all the transactions currently in flight and -// schedules a cleanup run when the first would trigger. -// -// The method has a granularity of 'gatherSlack', since there's not much point in -// spinning over all the transactions just to maybe find one that should trigger -// a few ms earlier. -// -// This method is a bit "flaky" "by design". In theory the timeout timer only ever -// should be rescheduled if some request is pending. In practice, a timeout will -// cause the timer to be rescheduled every 5 secs (until the peer comes through or -// disconnects). This is a limitation of the fetcher code because we don't trac -// pending requests and timed out requests separately. Without double tracking, if -// we simply didn't reschedule the timer on all-timeout then the timer would never -// be set again since len(request) > 0 => something's running. -func (f *TxFetcher) rescheduleTimeout(timer *mclock.Timer, trigger chan struct{}) { - if *timer != nil { - (*timer).Stop() - } - now := f.clock.Now() - - earliest := now - for _, req := range f.requests { - // If this request already timed out, skip it altogether - if req.hashes == nil { - continue - } - if earliest > req.time { - earliest = req.time - if txFetchTimeout-time.Duration(now-earliest) < gatherSlack { - break - } - } - } - *timer = f.clock.AfterFunc(txFetchTimeout-time.Duration(now-earliest), func() { - trigger <- struct{}{} - }) -} - -// scheduleFetches starts a batch of retrievals for all available idle peers. -func (f *TxFetcher) scheduleFetches(timer *mclock.Timer, timeout chan struct{}, whitelist map[string]struct{}) { - // Gather the set of peers we want to retrieve from (default to all) - actives := whitelist - if actives == nil { - actives = make(map[string]struct{}) - for peer := range f.announces { - actives[peer] = struct{}{} - } - } - if len(actives) == 0 { - return - } - // For each active peer, try to schedule some transaction fetches - idle := len(f.requests) == 0 - - f.forEachPeer(actives, func(peer string) { - if f.requests[peer] != nil { - return // continue in the for-each - } - if len(f.announces[peer]) == 0 { - return // continue in the for-each - } - var ( - hashes = make([]common.Hash, 0, maxTxRetrievals) - bytes uint64 - ) - f.forEachAnnounce(f.announces[peer], func(hash common.Hash, meta *txMetadata) bool { - // If the transaction is already fetching, skip to the next one - if _, ok := f.fetching[hash]; ok { - return true - } - // Mark the hash as fetching and stash away possible alternates - f.fetching[hash] = peer - - if _, ok := f.alternates[hash]; ok { - panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash])) - } - f.alternates[hash] = f.announced[hash] - delete(f.announced, hash) - - // Accumulate the hash and stop if the limit was reached - hashes = append(hashes, hash) - if len(hashes) >= maxTxRetrievals { - return false // break in the for-each - } - if meta != nil { // Only set eth/68 and upwards - bytes += uint64(meta.size) - if bytes >= maxTxRetrievalSize { - return false - } - } - return true // scheduled, try to add more - }) - // If any hashes were allocated, request them from the peer - if len(hashes) > 0 { - f.requests[peer] = &txRequest{hashes: hashes, time: f.clock.Now()} - txRequestOutMeter.Mark(int64(len(hashes))) - - go func(peer string, hashes []common.Hash) { - // Try to fetch the transactions, but in case of a request - // failure (e.g. peer disconnected), reschedule the hashes. - if err := f.fetchTxs(peer, hashes); err != nil { - txRequestFailMeter.Mark(int64(len(hashes))) - f.Drop(peer) - } - }(peer, hashes) - } - }) - // If a new request was fired, schedule a timeout timer - if idle && len(f.requests) > 0 { - f.rescheduleTimeout(timer, timeout) - } -} - -// forEachPeer does a range loop over a map of peers in production, but during -// testing it does a deterministic sorted random to allow reproducing issues. -func (f *TxFetcher) forEachPeer(peers map[string]struct{}, do func(peer string)) { - // If we're running production, use whatever Go's map gives us - if f.rand == nil { - for peer := range peers { - do(peer) - } - return - } - // We're running the test suite, make iteration deterministic - list := make([]string, 0, len(peers)) - for peer := range peers { - list = append(list, peer) - } - sort.Strings(list) - rotateStrings(list, f.rand.Intn(len(list))) - for _, peer := range list { - do(peer) - } -} - -// forEachAnnounce does a range loop over a map of announcements in production, -// but during testing it does a deterministic sorted random to allow reproducing -// issues. -func (f *TxFetcher) forEachAnnounce(announces map[common.Hash]*txMetadata, do func(hash common.Hash, meta *txMetadata) bool) { - // If we're running production, use whatever Go's map gives us - if f.rand == nil { - for hash, meta := range announces { - if !do(hash, meta) { - return - } - } - return - } - // We're running the test suite, make iteration deterministic - list := make([]common.Hash, 0, len(announces)) - for hash := range announces { - list = append(list, hash) - } - sortHashes(list) - rotateHashes(list, f.rand.Intn(len(list))) - for _, hash := range list { - if !do(hash, announces[hash]) { - return - } - } -} - -// rotateStrings rotates the contents of a slice by n steps. This method is only -// used in tests to simulate random map iteration but keep it deterministic. -func rotateStrings(slice []string, n int) { - orig := make([]string, len(slice)) - copy(orig, slice) - - for i := 0; i < len(orig); i++ { - slice[i] = orig[(i+n)%len(orig)] - } -} - -// sortHashes sorts a slice of hashes. This method is only used in tests in order -// to simulate random map iteration but keep it deterministic. -func sortHashes(slice []common.Hash) { - for i := 0; i < len(slice); i++ { - for j := i + 1; j < len(slice); j++ { - if bytes.Compare(slice[i][:], slice[j][:]) > 0 { - slice[i], slice[j] = slice[j], slice[i] - } - } - } -} - -// rotateHashes rotates the contents of a slice by n steps. This method is only -// used in tests to simulate random map iteration but keep it deterministic. -func rotateHashes(slice []common.Hash, n int) { - orig := make([]common.Hash, len(slice)) - copy(orig, slice) - - for i := 0; i < len(orig); i++ { - slice[i] = orig[(i+n)%len(orig)] - } -} diff --git a/builder/eth/fetcher/tx_fetcher_test.go b/builder/eth/fetcher/tx_fetcher_test.go deleted file mode 100644 index 4a62e579b..000000000 --- a/builder/eth/fetcher/tx_fetcher_test.go +++ /dev/null @@ -1,2030 +0,0 @@ -// 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 fetcher - -import ( - "errors" - "math/big" - "math/rand" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -var ( - // testTxs is a set of transactions to use during testing that have meaningful hashes. - testTxs = []*types.Transaction{ - types.NewTransaction(5577006791947779410, common.Address{0x0f}, new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(15352856648520921629, common.Address{0xbb}, new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(3916589616287113937, common.Address{0x86}, new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(9828766684487745566, common.Address{0xac}, new(big.Int), 0, new(big.Int), nil), - } - // testTxsHashes is the hashes of the test transactions above - testTxsHashes = []common.Hash{testTxs[0].Hash(), testTxs[1].Hash(), testTxs[2].Hash(), testTxs[3].Hash()} -) - -type announce struct { - hash common.Hash - kind *byte - size *uint32 -} - -func typeptr(t byte) *byte { return &t } -func sizeptr(n uint32) *uint32 { return &n } - -type doTxNotify struct { - peer string - hashes []common.Hash - types []byte - sizes []uint32 -} -type doTxEnqueue struct { - peer string - txs []*types.Transaction - direct bool -} -type doWait struct { - time time.Duration - step bool -} -type doDrop string -type doFunc func() - -type isWaitingWithMeta map[string][]announce -type isWaiting map[string][]common.Hash - -type isScheduledWithMeta struct { - tracking map[string][]announce - fetching map[string][]common.Hash - dangling map[string][]common.Hash -} -type isScheduled struct { - tracking map[string][]common.Hash - fetching map[string][]common.Hash - dangling map[string][]common.Hash -} -type isUnderpriced int - -// txFetcherTest represents a test scenario that can be executed by the test -// runner. -type txFetcherTest struct { - init func() *TxFetcher - steps []interface{} -} - -// Tests that transaction announcements are added to a waitlist, and none -// of them are scheduled for retrieval until the wait expires. -func TestTransactionFetcherWaiting(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Initial announcement to get something into the waitlist - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }), - // Announce from a new peer to check that no overwrite happens - doTxNotify{peer: "B", hashes: []common.Hash{{0x03}, {0x04}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - "B": {{0x03}, {0x04}}, - }), - // Announce clashing hashes but unique new peer - doTxNotify{peer: "C", hashes: []common.Hash{{0x01}, {0x04}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - "B": {{0x03}, {0x04}}, - "C": {{0x01}, {0x04}}, - }), - // Announce existing and clashing hashes from existing peer - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x03}, {0x05}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x05}}, - "B": {{0x03}, {0x04}}, - "C": {{0x01}, {0x04}}, - }), - isScheduled{tracking: nil, fetching: nil}, - - // Wait for the arrival timeout which should move all expired items - // from the wait list to the scheduler - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x05}}, - "B": {{0x03}, {0x04}}, - "C": {{0x01}, {0x04}}, - }, - fetching: map[string][]common.Hash{ // Depends on deterministic test randomizer - "A": {{0x02}, {0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - }, - }, - // Queue up a non-fetchable transaction and then trigger it with a new - // peer (weird case to test 1 line in the fetcher) - doTxNotify{peer: "C", hashes: []common.Hash{{0x06}, {0x07}}}, - isWaiting(map[string][]common.Hash{ - "C": {{0x06}, {0x07}}, - }), - doWait{time: txArriveTimeout, step: true}, - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x05}}, - "B": {{0x03}, {0x04}}, - "C": {{0x01}, {0x04}, {0x06}, {0x07}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x02}, {0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - }, - }, - doTxNotify{peer: "D", hashes: []common.Hash{{0x06}, {0x07}}}, - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x05}}, - "B": {{0x03}, {0x04}}, - "C": {{0x01}, {0x04}, {0x06}, {0x07}}, - "D": {{0x06}, {0x07}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x02}, {0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - "D": {{0x06}, {0x07}}, - }, - }, - }, - }) -} - -// Tests that transaction announcements with associated metadata are added to a -// waitlist, and none of them are scheduled for retrieval until the wait expires. -// -// This test is an extended version of TestTransactionFetcherWaiting. It's mostly -// to cover the metadata checks without bloating up the basic behavioral tests -// with all the useless extra fields. -func TestTransactionFetcherWaitingWithMeta(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Initial announcement to get something into the waitlist - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 222}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - }, - }), - // Announce from a new peer to check that no overwrite happens - doTxNotify{peer: "B", hashes: []common.Hash{{0x03}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{333, 444}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - }), - // Announce clashing hashes but unique new peer - doTxNotify{peer: "C", hashes: []common.Hash{{0x01}, {0x04}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{111, 444}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - }), - // Announce existing and clashing hashes from existing peer. Clashes - // should not overwrite previous announcements. - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x03}, {0x05}}, types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{999, 333, 555}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - }), - // Announce clashing hashes with conflicting metadata. Somebody will - // be in the wrong, but we don't know yet who. - doTxNotify{peer: "D", hashes: []common.Hash{{0x01}, {0x02}}, types: []byte{types.LegacyTxType, types.BlobTxType}, sizes: []uint32{999, 222}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "D": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, - {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, - }, - }), - isScheduled{tracking: nil, fetching: nil}, - - // Wait for the arrival timeout which should move all expired items - // from the wait list to the scheduler - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduledWithMeta{ - tracking: map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "D": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, - {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, - }, - }, - fetching: map[string][]common.Hash{ // Depends on deterministic test randomizer - "A": {{0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - "D": {{0x02}}, - }, - }, - // Queue up a non-fetchable transaction and then trigger it with a new - // peer (weird case to test 1 line in the fetcher) - doTxNotify{peer: "C", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}}, - isWaitingWithMeta(map[string][]announce{ - "C": { - {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, - {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, - }, - }), - doWait{time: txArriveTimeout, step: true}, - isScheduledWithMeta{ - tracking: map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, - {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, - }, - "D": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, - {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, - }, - }, - fetching: map[string][]common.Hash{ - "A": {{0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - "D": {{0x02}}, - }, - }, - doTxNotify{peer: "E", hashes: []common.Hash{{0x06}, {0x07}}, types: []byte{types.LegacyTxType, types.LegacyTxType}, sizes: []uint32{666, 777}}, - isScheduledWithMeta{ - tracking: map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(222)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(555)}, - }, - "B": { - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(333)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - }, - "C": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(111)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(444)}, - {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, - {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, - }, - "D": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(999)}, - {common.Hash{0x02}, typeptr(types.BlobTxType), sizeptr(222)}, - }, - "E": { - {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(666)}, - {common.Hash{0x07}, typeptr(types.LegacyTxType), sizeptr(777)}, - }, - }, - fetching: map[string][]common.Hash{ - "A": {{0x03}, {0x05}}, - "C": {{0x01}, {0x04}}, - "D": {{0x02}}, - "E": {{0x06}, {0x07}}, - }, - }, - }, - }) -} - -// Tests that transaction announcements skip the waiting list if they are -// already scheduled. -func TestTransactionFetcherSkipWaiting(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // Announce overlaps from the same peer, ensure the new ones end up - // in stage one, and clashing ones don't get double tracked - doTxNotify{peer: "A", hashes: []common.Hash{{0x02}, {0x03}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x03}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // Announce overlaps from a new peer, ensure new transactions end up - // in stage one and clashing ones get tracked for the new peer - doTxNotify{peer: "B", hashes: []common.Hash{{0x02}, {0x03}, {0x04}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x03}}, - "B": {{0x03}, {0x04}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - "B": {{0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - }, - }) -} - -// Tests that only a single transaction request gets scheduled to a peer -// and subsequent announces block or get allotted to someone else. -func TestTransactionFetcherSingletonRequesting(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // Announce a new set of transactions from the same peer and ensure - // they do not start fetching since the peer is already busy - doTxNotify{peer: "A", hashes: []common.Hash{{0x03}, {0x04}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x03}, {0x04}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x04}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // Announce a duplicate set of transactions from a new peer and ensure - // uniquely new ones start downloading, even if clashing. - doTxNotify{peer: "B", hashes: []common.Hash{{0x02}, {0x03}, {0x05}, {0x06}}}, - isWaiting(map[string][]common.Hash{ - "B": {{0x05}, {0x06}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}, {0x03}, {0x04}}, - "B": {{0x02}, {0x03}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - "B": {{0x03}}, - }, - }, - }, - }) -} - -// Tests that if a transaction retrieval fails, all the transactions get -// instantly schedule back to someone else or the announcements dropped -// if no alternate source is available. -func TestTransactionFetcherFailedRescheduling(t *testing.T) { - // Create a channel to control when tx requests can fail - proceed := make(chan struct{}) - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(origin string, hashes []common.Hash) error { - <-proceed - return errors.New("peer disconnected") - }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // While the original peer is stuck in the request, push in an second - // data source. - doTxNotify{peer: "B", hashes: []common.Hash{{0x02}}}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - "B": {{0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - }, - // Wait until the original request fails and check that transactions - // are either rescheduled or dropped - doFunc(func() { - proceed <- struct{}{} // Allow peer A to return the failure - }), - doWait{time: 0, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "B": {{0x02}}, - }, - fetching: map[string][]common.Hash{ - "B": {{0x02}}, - }, - }, - doFunc(func() { - proceed <- struct{}{} // Allow peer B to return the failure - }), - doWait{time: 0, step: true}, - isWaiting(nil), - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that if a transaction retrieval succeeds, all alternate origins -// are cleaned up. -func TestTransactionFetcherCleanup(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Request should be delivered - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that if a transaction retrieval succeeds, but the response is empty (no -// transactions available, then all are nuked instead of being rescheduled (yes, -// this was a bug)). -func TestTransactionFetcherCleanupEmpty(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Deliver an empty response and ensure the transaction is cleared, not rescheduled - doTxEnqueue{peer: "A", txs: []*types.Transaction{}, direct: true}, - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that non-returned transactions are either re-scheduled from a -// different peer, or self if they are after the cutoff point. -func TestTransactionFetcherMissingRescheduling(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}}, - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, - }, - }, - // Deliver the middle transaction requested, the one before which - // should be dropped and the one after re-requested. - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, // This depends on the deterministic random - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[2]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[2]}, - }, - }, - }, - }) -} - -// Tests that out of two transactions, if one is missing and the last is -// delivered, the peer gets properly cleaned out from the internal state. -func TestTransactionFetcherMissingCleanup(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1]}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1]}, - }, - }, - // Deliver the middle transaction requested, the one before which - // should be dropped and the one after re-requested. - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[1]}, direct: true}, // This depends on the deterministic random - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that transaction broadcasts properly clean up announcements. -func TestTransactionFetcherBroadcasts(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Set up three transactions to be in different stats, waiting, queued and fetching - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[2]}}, - - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[2]}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Broadcast all the transactions and ensure everything gets cleaned - // up, but the dangling request is left alone to avoid doing multiple - // concurrent requests. - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2]}, direct: false}, - isWaiting(nil), - isScheduled{ - tracking: nil, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Deliver the requested hashes - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2]}, direct: true}, - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that the waiting list timers properly reset and reschedule. -func TestTransactionFetcherWaitTimerResets(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}}, - }), - isScheduled{nil, nil, nil}, - doWait{time: txArriveTimeout / 2, step: false}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}}, - }), - isScheduled{nil, nil, nil}, - - doTxNotify{peer: "A", hashes: []common.Hash{{0x02}}}, - isWaiting(map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }), - isScheduled{nil, nil, nil}, - doWait{time: txArriveTimeout / 2, step: true}, - isWaiting(map[string][]common.Hash{ - "A": {{0x02}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}}, - }, - }, - - doWait{time: txArriveTimeout / 2, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}}, - }, - }, - }, - }) -} - -// Tests that if a transaction request is not replied to, it will time -// out and be re-scheduled for someone else. -func TestTransactionFetcherTimeoutRescheduling(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Push an initial announcement through to the scheduled stage - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }), - isScheduled{tracking: nil, fetching: nil}, - - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Wait until the delivery times out, everything should be cleaned up - doWait{time: txFetchTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: nil, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {}, - }, - }, - // Ensure that followup announcements don't get scheduled - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, - doWait{time: txArriveTimeout, step: true}, - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[1]}, - }, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {}, - }, - }, - // If the dangling request arrives a bit later, do not choke - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[1]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[1]}, - }, - }, - }, - }) -} - -// Tests that the fetching timeout timers properly reset and reschedule. -func TestTransactionFetcherTimeoutTimerResets(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "B", hashes: []common.Hash{{0x02}}}, - doWait{time: txArriveTimeout, step: true}, - - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}}, - "B": {{0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}}, - "B": {{0x02}}, - }, - }, - doWait{time: txFetchTimeout - txArriveTimeout, step: true}, - isScheduled{ - tracking: map[string][]common.Hash{ - "B": {{0x02}}, - }, - fetching: map[string][]common.Hash{ - "B": {{0x02}}, - }, - dangling: map[string][]common.Hash{ - "A": {}, - }, - }, - doWait{time: txArriveTimeout, step: true}, - isScheduled{ - tracking: nil, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {}, - "B": {}, - }, - }, - }, - }) -} - -// Tests that if thousands of transactions are announced, only a small -// number of them will be requested at a time. -func TestTransactionFetcherRateLimiting(t *testing.T) { - // Create a slew of transactions and announce them - var hashes []common.Hash - for i := 0; i < maxTxAnnounces; i++ { - hashes = append(hashes, common.Hash{byte(i / 256), byte(i % 256)}) - } - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Announce all the transactions, wait a bit and ensure only a small - // percentage gets requested - doTxNotify{peer: "A", hashes: hashes}, - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": hashes, - }, - fetching: map[string][]common.Hash{ - "A": hashes[1643 : 1643+maxTxRetrievals], - }, - }, - }, - }) -} - -// Tests that if huge transactions are announced, only a small number of them will -// be requested at a time, to keep the responses below a reasonable level. -func TestTransactionFetcherBandwidthLimiting(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Announce mid size transactions from A to verify that multiple - // ones can be piled into a single request. - doTxNotify{peer: "A", - hashes: []common.Hash{{0x01}, {0x02}, {0x03}, {0x04}}, - types: []byte{types.LegacyTxType, types.LegacyTxType, types.LegacyTxType, types.LegacyTxType}, - sizes: []uint32{48 * 1024, 48 * 1024, 48 * 1024, 48 * 1024}, - }, - // Announce exactly on the limit transactions to see that only one - // gets requested - doTxNotify{peer: "B", - hashes: []common.Hash{{0x05}, {0x06}}, - types: []byte{types.LegacyTxType, types.LegacyTxType}, - sizes: []uint32{maxTxRetrievalSize, maxTxRetrievalSize}, - }, - // Announce oversized blob transactions to see that overflows are ok - doTxNotify{peer: "C", - hashes: []common.Hash{{0x07}, {0x08}}, - types: []byte{types.BlobTxType, types.BlobTxType}, - sizes: []uint32{params.MaxBlobGasPerBlock, params.MaxBlobGasPerBlock}, - }, - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduledWithMeta{ - tracking: map[string][]announce{ - "A": { - {common.Hash{0x01}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, - {common.Hash{0x02}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, - {common.Hash{0x03}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, - {common.Hash{0x04}, typeptr(types.LegacyTxType), sizeptr(48 * 1024)}, - }, - "B": { - {common.Hash{0x05}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)}, - {common.Hash{0x06}, typeptr(types.LegacyTxType), sizeptr(maxTxRetrievalSize)}, - }, - "C": { - {common.Hash{0x07}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)}, - {common.Hash{0x08}, typeptr(types.BlobTxType), sizeptr(params.MaxBlobGasPerBlock)}, - }, - }, - fetching: map[string][]common.Hash{ - "A": {{0x02}, {0x03}, {0x04}}, - "B": {{0x06}}, - "C": {{0x08}}, - }, - }, - }, - }) -} - -// Tests that then number of transactions a peer is allowed to announce and/or -// request at the same time is hard capped. -func TestTransactionFetcherDoSProtection(t *testing.T) { - // Create a slew of transactions and to announce them - var hashesA []common.Hash - for i := 0; i < maxTxAnnounces+1; i++ { - hashesA = append(hashesA, common.Hash{0x01, byte(i / 256), byte(i % 256)}) - } - var hashesB []common.Hash - for i := 0; i < maxTxAnnounces+1; i++ { - hashesB = append(hashesB, common.Hash{0x02, byte(i / 256), byte(i % 256)}) - } - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - nil, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Announce half of the transaction and wait for them to be scheduled - doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2]}, - doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1]}, - doWait{time: txArriveTimeout, step: true}, - - // Announce the second half and keep them in the wait list - doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces]}, - doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]}, - - // Ensure the hashes are split half and half - isWaiting(map[string][]common.Hash{ - "A": hashesA[maxTxAnnounces/2 : maxTxAnnounces], - "B": hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": hashesA[:maxTxAnnounces/2], - "B": hashesB[:maxTxAnnounces/2-1], - }, - fetching: map[string][]common.Hash{ - "A": hashesA[1643 : 1643+maxTxRetrievals], - "B": append(append([]common.Hash{}, hashesB[maxTxAnnounces/2-3:maxTxAnnounces/2-1]...), hashesB[:maxTxRetrievals-2]...), - }, - }, - // Ensure that adding even one more hash results in dropping the hash - doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}}, - doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1]}, - - isWaiting(map[string][]common.Hash{ - "A": hashesA[maxTxAnnounces/2 : maxTxAnnounces], - "B": hashesB[maxTxAnnounces/2-1 : maxTxAnnounces], - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": hashesA[:maxTxAnnounces/2], - "B": hashesB[:maxTxAnnounces/2-1], - }, - fetching: map[string][]common.Hash{ - "A": hashesA[1643 : 1643+maxTxRetrievals], - "B": append(append([]common.Hash{}, hashesB[maxTxAnnounces/2-3:maxTxAnnounces/2-1]...), hashesB[:maxTxRetrievals-2]...), - }, - }, - }, - }) -} - -// Tests that underpriced transactions don't get rescheduled after being rejected. -func TestTransactionFetcherUnderpricedDedup(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - errs := make([]error, len(txs)) - for i := 0; i < len(errs); i++ { - if i%2 == 0 { - errs[i] = txpool.ErrUnderpriced - } else { - errs[i] = txpool.ErrReplaceUnderpriced - } - } - return errs - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Deliver a transaction through the fetcher, but reject as underpriced - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, - doWait{time: txArriveTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}, direct: true}, - isScheduled{nil, nil, nil}, - - // Try to announce the transaction again, ensure it's not scheduled back - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}}, // [2] is needed to force a step in the fetcher - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[2]}, - }), - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that underpriced transactions don't get rescheduled after being rejected, -// but at the same time there's a hard cap on the number of transactions that are -// tracked. -func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) { - // Temporarily disable fetch timeouts as they massively mess up the simulated clock - defer func(timeout time.Duration) { txFetchTimeout = timeout }(txFetchTimeout) - txFetchTimeout = 24 * time.Hour - - // Create a slew of transactions to max out the underpriced set - var txs []*types.Transaction - for i := 0; i < maxTxUnderpricedSetSize+1; i++ { - txs = append(txs, types.NewTransaction(rand.Uint64(), common.Address{byte(rand.Intn(256))}, new(big.Int), 0, new(big.Int), nil)) - } - hashes := make([]common.Hash, len(txs)) - for i, tx := range txs { - hashes[i] = tx.Hash() - } - // Generate a set of steps to announce and deliver the entire set of transactions - var steps []interface{} - for i := 0; i < maxTxUnderpricedSetSize/maxTxRetrievals; i++ { - steps = append(steps, doTxNotify{peer: "A", hashes: hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals]}) - steps = append(steps, isWaiting(map[string][]common.Hash{ - "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], - })) - steps = append(steps, doWait{time: txArriveTimeout, step: true}) - steps = append(steps, isScheduled{ - tracking: map[string][]common.Hash{ - "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], - }, - fetching: map[string][]common.Hash{ - "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], - }, - }) - steps = append(steps, doTxEnqueue{peer: "A", txs: txs[i*maxTxRetrievals : (i+1)*maxTxRetrievals], direct: true}) - steps = append(steps, isWaiting(nil)) - steps = append(steps, isScheduled{nil, nil, nil}) - steps = append(steps, isUnderpriced((i+1)*maxTxRetrievals)) - } - testTransactionFetcher(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - errs := make([]error, len(txs)) - for i := 0; i < len(errs); i++ { - errs[i] = txpool.ErrUnderpriced - } - return errs - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: append(steps, []interface{}{ - // The preparation of the test has already been done in `steps`, add the last check - doTxNotify{peer: "A", hashes: []common.Hash{hashes[maxTxUnderpricedSetSize]}}, - doWait{time: txArriveTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{txs[maxTxUnderpricedSetSize]}, direct: true}, - isUnderpriced(maxTxUnderpricedSetSize), - }...), - }) -} - -// Tests that unexpected deliveries don't corrupt the internal state. -func TestTransactionFetcherOutOfBoundDeliveries(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Deliver something out of the blue - isWaiting(nil), - isScheduled{nil, nil, nil}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: false}, - isWaiting(nil), - isScheduled{nil, nil, nil}, - - // Set up a few hashes into various stages - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[2]}}, - - isWaiting(map[string][]common.Hash{ - "A": {testTxsHashes[2]}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0], testTxsHashes[1]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - // Deliver everything and more out of the blue - doTxEnqueue{peer: "B", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2], testTxs[3]}, direct: true}, - isWaiting(nil), - isScheduled{ - tracking: nil, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - }, - }) -} - -// Tests that dropping a peer cleans out all internal data structures in all the -// live or dangling stages. -func TestTransactionFetcherDrop(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Set up a few hashes into various stages - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{{0x02}}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "A", hashes: []common.Hash{{0x03}}}, - - isWaiting(map[string][]common.Hash{ - "A": {{0x03}}, - }), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}, {0x02}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}}, - }, - }, - // Drop the peer and ensure everything's cleaned out - doDrop("A"), - isWaiting(nil), - isScheduled{nil, nil, nil}, - - // Push the node into a dangling (timeout) state - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - }, - }, - doWait{time: txFetchTimeout, step: true}, - isWaiting(nil), - isScheduled{ - tracking: nil, - fetching: nil, - dangling: map[string][]common.Hash{ - "A": {}, - }, - }, - // Drop the peer and ensure everything's cleaned out - doDrop("A"), - isWaiting(nil), - isScheduled{nil, nil, nil}, - }, - }) -} - -// Tests that dropping a peer instantly reschedules failed announcements to any -// available peer. -func TestTransactionFetcherDropRescheduling(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Set up a few hashes into various stages - doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, - doWait{time: txArriveTimeout, step: true}, - doTxNotify{peer: "B", hashes: []common.Hash{{0x01}}}, - - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "A": {{0x01}}, - "B": {{0x01}}, - }, - fetching: map[string][]common.Hash{ - "A": {{0x01}}, - }, - }, - // Drop the peer and ensure everything's cleaned out - doDrop("A"), - isWaiting(nil), - isScheduled{ - tracking: map[string][]common.Hash{ - "B": {{0x01}}, - }, - fetching: map[string][]common.Hash{ - "B": {{0x01}}, - }, - }, - }, - }) -} - -// Tests that announced transactions with the wrong transaction type or size will -// result in a dropped peer. -func TestInvalidAnnounceMetadata(t *testing.T) { - drop := make(chan string, 2) - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - func(peer string) { drop <- peer }, - ) - }, - steps: []interface{}{ - // Initial announcement to get something into the waitlist - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}, types: []byte{testTxs[0].Type(), testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[0].Size()), uint32(testTxs[1].Size())}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, - {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, - }, - }), - // Announce from new peers conflicting transactions - doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}, types: []byte{testTxs[0].Type()}, sizes: []uint32{1024 + uint32(testTxs[0].Size())}}, - doTxNotify{peer: "C", hashes: []common.Hash{testTxsHashes[1]}, types: []byte{1 + testTxs[1].Type()}, sizes: []uint32{uint32(testTxs[1].Size())}}, - isWaitingWithMeta(map[string][]announce{ - "A": { - {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, - {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, - }, - "B": { - {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))}, - }, - "C": { - {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, - }, - }), - // Schedule all the transactions for retrieval - doWait{time: txArriveTimeout, step: true}, - isWaitingWithMeta(nil), - isScheduledWithMeta{ - tracking: map[string][]announce{ - "A": { - {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(uint32(testTxs[0].Size()))}, - {testTxsHashes[1], typeptr(testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, - }, - "B": { - {testTxsHashes[0], typeptr(testTxs[0].Type()), sizeptr(1024 + uint32(testTxs[0].Size()))}, - }, - "C": { - {testTxsHashes[1], typeptr(1 + testTxs[1].Type()), sizeptr(uint32(testTxs[1].Size()))}, - }, - }, - fetching: map[string][]common.Hash{ - "A": {testTxsHashes[0]}, - "C": {testTxsHashes[1]}, - }, - }, - // Deliver the transactions and wait for B to be dropped - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}}, - doFunc(func() { <-drop }), - doFunc(func() { <-drop }), - }, - }) -} - -// This test reproduces a crash caught by the fuzzer. The root cause was a -// dangling transaction timing out and clashing on re-add with a concurrently -// announced one. -func TestTransactionFetcherFuzzCrash01(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Get a transaction into fetching mode and make it dangling with a broadcast - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, - - // Notify the dangling transaction once more and crash via a timeout - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txFetchTimeout, step: true}, - }, - }) -} - -// This test reproduces a crash caught by the fuzzer. The root cause was a -// dangling transaction getting peer-dropped and clashing on re-add with a -// concurrently announced one. -func TestTransactionFetcherFuzzCrash02(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Get a transaction into fetching mode and make it dangling with a broadcast - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, - - // Notify the dangling transaction once more, re-fetch, and crash via a drop and timeout - doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doDrop("A"), - doWait{time: txFetchTimeout, step: true}, - }, - }) -} - -// This test reproduces a crash caught by the fuzzer. The root cause was a -// dangling transaction getting rescheduled via a partial delivery, clashing -// with a concurrent notify. -func TestTransactionFetcherFuzzCrash03(t *testing.T) { - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { return nil }, - nil, - ) - }, - steps: []interface{}{ - // Get a transaction into fetching mode and make it dangling with a broadcast - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, - doWait{time: txFetchTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}}, - - // Notify the dangling transaction once more, partially deliver, clash&crash with a timeout - doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[1]}, direct: true}, - doWait{time: txFetchTimeout, step: true}, - }, - }) -} - -// This test reproduces a crash caught by the fuzzer. The root cause was a -// dangling transaction getting rescheduled via a disconnect, clashing with -// a concurrent notify. -func TestTransactionFetcherFuzzCrash04(t *testing.T) { - // Create a channel to control when tx requests can fail - proceed := make(chan struct{}) - - testTransactionFetcherParallel(t, txFetcherTest{ - init: func() *TxFetcher { - return NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - return make([]error, len(txs)) - }, - func(string, []common.Hash) error { - <-proceed - return errors.New("peer disconnected") - }, - nil, - ) - }, - steps: []interface{}{ - // Get a transaction into fetching mode and make it dangling with a broadcast - doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, - - // Notify the dangling transaction once more, re-fetch, and crash via an in-flight disconnect - doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, - doWait{time: txArriveTimeout, step: true}, - doFunc(func() { - proceed <- struct{}{} // Allow peer A to return the failure - }), - doWait{time: 0, step: true}, - doWait{time: txFetchTimeout, step: true}, - }, - }) -} - -func testTransactionFetcherParallel(t *testing.T, tt txFetcherTest) { - t.Parallel() - testTransactionFetcher(t, tt) -} - -func testTransactionFetcher(t *testing.T, tt txFetcherTest) { - // Create a fetcher and hook into it's simulated fields - clock := new(mclock.Simulated) - wait := make(chan struct{}) - - fetcher := tt.init() - fetcher.clock = clock - fetcher.step = wait - fetcher.rand = rand.New(rand.NewSource(0x3a29)) - - fetcher.Start() - defer fetcher.Stop() - - defer func() { // drain the wait chan on exit - for { - select { - case <-wait: - default: - return - } - } - }() - - // Crunch through all the test steps and execute them - for i, step := range tt.steps { - // Auto-expand certain steps to ones with metadata - switch old := step.(type) { - case isWaiting: - new := make(isWaitingWithMeta) - for peer, hashes := range old { - for _, hash := range hashes { - new[peer] = append(new[peer], announce{hash, nil, nil}) - } - } - step = new - - case isScheduled: - new := isScheduledWithMeta{ - tracking: make(map[string][]announce), - fetching: old.fetching, - dangling: old.dangling, - } - for peer, hashes := range old.tracking { - for _, hash := range hashes { - new.tracking[peer] = append(new.tracking[peer], announce{hash, nil, nil}) - } - } - step = new - } - // Process the original or expanded steps - switch step := step.(type) { - case doTxNotify: - if err := fetcher.Notify(step.peer, step.types, step.sizes, step.hashes); err != nil { - t.Errorf("step %d: %v", i, err) - } - <-wait // Fetcher needs to process this, wait until it's done - select { - case <-wait: - panic("wtf") - case <-time.After(time.Millisecond): - } - - case doTxEnqueue: - if err := fetcher.Enqueue(step.peer, step.txs, step.direct); err != nil { - t.Errorf("step %d: %v", i, err) - } - <-wait // Fetcher needs to process this, wait until it's done - - case doWait: - clock.Run(step.time) - if step.step { - <-wait // Fetcher supposed to do something, wait until it's done - } - - case doDrop: - if err := fetcher.Drop(string(step)); err != nil { - t.Errorf("step %d: %v", i, err) - } - <-wait // Fetcher needs to process this, wait until it's done - - case doFunc: - step() - - case isWaitingWithMeta: - // We need to check that the waiting list (stage 1) internals - // match with the expected set. Check the peer->hash mappings - // first. - for peer, announces := range step { - waiting := fetcher.waitslots[peer] - if waiting == nil { - t.Errorf("step %d: peer %s missing from waitslots", i, peer) - continue - } - for _, ann := range announces { - if meta, ok := waiting[ann.hash]; !ok { - t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, ann.hash) - } else { - if (meta == nil && (ann.kind != nil || ann.size != nil)) || - (meta != nil && (ann.kind == nil || ann.size == nil)) || - (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) { - t.Errorf("step %d, peer %s, hash %x: waitslot metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size) - } - } - } - for hash, meta := range waiting { - ann := announce{hash: hash} - if meta != nil { - ann.kind, ann.size = &meta.kind, &meta.size - } - if !containsAnnounce(announces, ann) { - t.Errorf("step %d, peer %s: announce %v extra in waitslots", i, peer, ann) - } - } - } - for peer := range fetcher.waitslots { - if _, ok := step[peer]; !ok { - t.Errorf("step %d: peer %s extra in waitslots", i, peer) - } - } - // Peer->hash sets correct, check the hash->peer and timeout sets - for peer, announces := range step { - for _, ann := range announces { - if _, ok := fetcher.waitlist[ann.hash][peer]; !ok { - t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, ann.hash, peer) - } - if _, ok := fetcher.waittime[ann.hash]; !ok { - t.Errorf("step %d: hash %x missing from waittime", i, ann.hash) - } - } - } - for hash, peers := range fetcher.waitlist { - if len(peers) == 0 { - t.Errorf("step %d, hash %x: empty peerset in waitlist", i, hash) - } - for peer := range peers { - if !containsHashInAnnounces(step[peer], hash) { - t.Errorf("step %d, hash %x: peer %s extra in waitlist", i, hash, peer) - } - } - } - for hash := range fetcher.waittime { - var found bool - for _, announces := range step { - if containsHashInAnnounces(announces, hash) { - found = true - break - } - } - if !found { - t.Errorf("step %d,: hash %x extra in waittime", i, hash) - } - } - - case isScheduledWithMeta: - // Check that all scheduled announces are accounted for and no - // extra ones are present. - for peer, announces := range step.tracking { - scheduled := fetcher.announces[peer] - if scheduled == nil { - t.Errorf("step %d: peer %s missing from announces", i, peer) - continue - } - for _, ann := range announces { - if meta, ok := scheduled[ann.hash]; !ok { - t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, ann.hash) - } else { - if (meta == nil && (ann.kind != nil || ann.size != nil)) || - (meta != nil && (ann.kind == nil || ann.size == nil)) || - (meta != nil && (meta.kind != *ann.kind || meta.size != *ann.size)) { - t.Errorf("step %d, peer %s, hash %x: announce metadata mismatch: want %v, have %v/%v", i, peer, ann.hash, meta, *ann.kind, *ann.size) - } - } - } - for hash, meta := range scheduled { - ann := announce{hash: hash} - if meta != nil { - ann.kind, ann.size = &meta.kind, &meta.size - } - if !containsAnnounce(announces, ann) { - t.Errorf("step %d, peer %s: announce %x extra in announces", i, peer, hash) - } - } - } - for peer := range fetcher.announces { - if _, ok := step.tracking[peer]; !ok { - t.Errorf("step %d: peer %s extra in announces", i, peer) - } - } - // Check that all announces required to be fetching are in the - // appropriate sets - for peer, hashes := range step.fetching { - request := fetcher.requests[peer] - if request == nil { - t.Errorf("step %d: peer %s missing from requests", i, peer) - continue - } - for _, hash := range hashes { - if !containsHash(request.hashes, hash) { - t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash) - } - } - for _, hash := range request.hashes { - if !containsHash(hashes, hash) { - t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash) - } - } - } - for peer := range fetcher.requests { - if _, ok := step.fetching[peer]; !ok { - if _, ok := step.dangling[peer]; !ok { - t.Errorf("step %d: peer %s extra in requests", i, peer) - } - } - } - for peer, hashes := range step.fetching { - for _, hash := range hashes { - if _, ok := fetcher.fetching[hash]; !ok { - t.Errorf("step %d, peer %s: hash %x missing from fetching", i, peer, hash) - } - } - } - for hash := range fetcher.fetching { - var found bool - for _, req := range fetcher.requests { - if containsHash(req.hashes, hash) { - found = true - break - } - } - if !found { - t.Errorf("step %d: hash %x extra in fetching", i, hash) - } - } - for _, hashes := range step.fetching { - for _, hash := range hashes { - alternates := fetcher.alternates[hash] - if alternates == nil { - t.Errorf("step %d: hash %x missing from alternates", i, hash) - continue - } - for peer := range alternates { - if _, ok := fetcher.announces[peer]; !ok { - t.Errorf("step %d: peer %s extra in alternates", i, peer) - continue - } - if _, ok := fetcher.announces[peer][hash]; !ok { - t.Errorf("step %d, peer %s: hash %x extra in alternates", i, hash, peer) - continue - } - } - for p := range fetcher.announced[hash] { - if _, ok := alternates[p]; !ok { - t.Errorf("step %d, hash %x: peer %s missing from alternates", i, hash, p) - continue - } - } - } - } - for peer, hashes := range step.dangling { - request := fetcher.requests[peer] - if request == nil { - t.Errorf("step %d: peer %s missing from requests", i, peer) - continue - } - for _, hash := range hashes { - if !containsHash(request.hashes, hash) { - t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash) - } - } - for _, hash := range request.hashes { - if !containsHash(hashes, hash) { - t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash) - } - } - } - // Check that all transaction announces that are scheduled for - // retrieval but not actively being downloaded are tracked only - // in the stage 2 `announced` map. - var queued []common.Hash - for _, announces := range step.tracking { - for _, ann := range announces { - var found bool - for _, hs := range step.fetching { - if containsHash(hs, ann.hash) { - found = true - break - } - } - if !found { - queued = append(queued, ann.hash) - } - } - } - for _, hash := range queued { - if _, ok := fetcher.announced[hash]; !ok { - t.Errorf("step %d: hash %x missing from announced", i, hash) - } - } - for hash := range fetcher.announced { - if !containsHash(queued, hash) { - t.Errorf("step %d: hash %x extra in announced", i, hash) - } - } - - case isUnderpriced: - if fetcher.underpriced.Len() != int(step) { - t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Len(), step) - } - - default: - t.Fatalf("step %d: unknown step type %T", i, step) - } - // After every step, cross validate the internal uniqueness invariants - // between stage one and stage two. - for hash := range fetcher.waittime { - if _, ok := fetcher.announced[hash]; ok { - t.Errorf("step %d: hash %s present in both stage 1 and 2", i, hash) - } - } - } -} - -// containsAnnounce returns whether an announcement is contained within a slice -// of announcements. -func containsAnnounce(slice []announce, ann announce) bool { - for _, have := range slice { - if have.hash == ann.hash { - if have.kind == nil || ann.kind == nil { - if have.kind != ann.kind { - return false - } - } else if *have.kind != *ann.kind { - return false - } - if have.size == nil || ann.size == nil { - if have.size != ann.size { - return false - } - } else if *have.size != *ann.size { - return false - } - return true - } - } - return false -} - -// containsHashInAnnounces returns whether a hash is contained within a slice -// of announcements. -func containsHashInAnnounces(slice []announce, hash common.Hash) bool { - for _, have := range slice { - if have.hash == hash { - return true - } - } - return false -} - -// containsHash returns whether a hash is contained within a hash slice. -func containsHash(slice []common.Hash, hash common.Hash) bool { - for _, have := range slice { - if have == hash { - return true - } - } - return false -} - -// Tests that a transaction is forgotten after the timeout. -func TestTransactionForgotten(t *testing.T) { - fetcher := NewTxFetcher( - func(common.Hash) bool { return false }, - func(txs []*types.Transaction) []error { - errs := make([]error, len(txs)) - for i := 0; i < len(errs); i++ { - errs[i] = txpool.ErrUnderpriced - } - return errs - }, - func(string, []common.Hash) error { return nil }, - func(string) {}, - ) - fetcher.Start() - defer fetcher.Stop() - // Create one TX which is 5 minutes old, and one which is recent - tx1 := types.NewTx(&types.LegacyTx{Nonce: 0}) - tx1.SetTime(time.Now().Add(-maxTxUnderpricedTimeout - 1*time.Second)) - tx2 := types.NewTx(&types.LegacyTx{Nonce: 1}) - - // Enqueue both in the fetcher. They will be immediately tagged as underpriced - if err := fetcher.Enqueue("asdf", []*types.Transaction{tx1, tx2}, false); err != nil { - t.Fatal(err) - } - // isKnownUnderpriced should trigger removal of the first tx (no longer be known underpriced) - if fetcher.isKnownUnderpriced(tx1.Hash()) { - t.Fatal("transaction should be forgotten by now") - } - // isKnownUnderpriced should not trigger removal of the second - if !fetcher.isKnownUnderpriced(tx2.Hash()) { - t.Fatal("transaction should be known underpriced") - } -} diff --git a/builder/eth/filters/api.go b/builder/eth/filters/api.go deleted file mode 100644 index 8cf701ec5..000000000 --- a/builder/eth/filters/api.go +++ /dev/null @@ -1,607 +0,0 @@ -// 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 filters - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math/big" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/rpc" -) - -var ( - errInvalidTopic = errors.New("invalid topic(s)") - errFilterNotFound = errors.New("filter not found") - errInvalidBlockRange = errors.New("invalid block range params") - errExceedMaxTopics = errors.New("exceed max topics") -) - -// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 -const maxTopics = 4 - -// filter is a helper struct that holds meta information over the filter type -// and associated subscription in the event system. -type filter struct { - typ Type - deadline *time.Timer // filter is inactive when deadline triggers - hashes []common.Hash - fullTx bool - txs []*types.Transaction - crit FilterCriteria - logs []*types.Log - s *Subscription // associated subscription in event system -} - -// FilterAPI offers support to create and manage filters. This will allow external clients to retrieve various -// information related to the Ethereum protocol such as blocks, transactions and logs. -type FilterAPI struct { - sys *FilterSystem - events *EventSystem - filtersMu sync.Mutex - filters map[rpc.ID]*filter - timeout time.Duration -} - -// NewFilterAPI returns a new FilterAPI instance. -func NewFilterAPI(system *FilterSystem, lightMode bool) *FilterAPI { - api := &FilterAPI{ - sys: system, - events: NewEventSystem(system, lightMode), - filters: make(map[rpc.ID]*filter), - timeout: system.cfg.Timeout, - } - go api.timeoutLoop(system.cfg.Timeout) - - return api -} - -// timeoutLoop runs at the interval set by 'timeout' and deletes filters -// that have not been recently used. It is started when the API is created. -func (api *FilterAPI) timeoutLoop(timeout time.Duration) { - var toUninstall []*Subscription - ticker := time.NewTicker(timeout) - defer ticker.Stop() - for { - <-ticker.C - api.filtersMu.Lock() - for id, f := range api.filters { - select { - case <-f.deadline.C: - toUninstall = append(toUninstall, f.s) - delete(api.filters, id) - default: - continue - } - } - api.filtersMu.Unlock() - - // Unsubscribes are processed outside the lock to avoid the following scenario: - // event loop attempts broadcasting events to still active filters while - // Unsubscribe is waiting for it to process the uninstall request. - for _, s := range toUninstall { - s.Unsubscribe() - } - toUninstall = nil - } -} - -// NewPendingTransactionFilter creates a filter that fetches pending transactions -// as transactions enter the pending state. -// -// It is part of the filter package because this filter can be used through the -// `eth_getFilterChanges` polling method that is also used for log filters. -func (api *FilterAPI) NewPendingTransactionFilter(fullTx *bool) rpc.ID { - var ( - pendingTxs = make(chan []*types.Transaction) - pendingTxSub = api.events.SubscribePendingTxs(pendingTxs) - ) - - api.filtersMu.Lock() - api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, fullTx: fullTx != nil && *fullTx, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} - api.filtersMu.Unlock() - - go func() { - for { - select { - case pTx := <-pendingTxs: - api.filtersMu.Lock() - if f, found := api.filters[pendingTxSub.ID]; found { - f.txs = append(f.txs, pTx...) - } - api.filtersMu.Unlock() - case <-pendingTxSub.Err(): - api.filtersMu.Lock() - delete(api.filters, pendingTxSub.ID) - api.filtersMu.Unlock() - return - } - } - }() - - return pendingTxSub.ID -} - -// NewPendingTransactions creates a subscription that is triggered each time a -// transaction enters the transaction pool. If fullTx is true the full tx is -// sent to the client, otherwise the hash is sent. -func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool) (*rpc.Subscription, error) { - notifier, supported := rpc.NotifierFromContext(ctx) - if !supported { - return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported - } - - rpcSub := notifier.CreateSubscription() - - go func() { - txs := make(chan []*types.Transaction, 128) - pendingTxSub := api.events.SubscribePendingTxs(txs) - defer pendingTxSub.Unsubscribe() - - chainConfig := api.sys.backend.ChainConfig() - - for { - select { - case txs := <-txs: - // To keep the original behaviour, send a single tx hash in one notification. - // TODO(rjl493456442) Send a batch of tx hashes in one notification - latest := api.sys.backend.CurrentHeader() - for _, tx := range txs { - if fullTx != nil && *fullTx { - rpcTx := ethapi.NewRPCPendingTransaction(tx, latest, chainConfig) - notifier.Notify(rpcSub.ID, rpcTx) - } else { - notifier.Notify(rpcSub.ID, tx.Hash()) - } - } - case <-rpcSub.Err(): - return - case <-notifier.Closed(): - return - } - } - }() - - return rpcSub, nil -} - -// NewBlockFilter creates a filter that fetches blocks that are imported into the chain. -// It is part of the filter package since polling goes with eth_getFilterChanges. -func (api *FilterAPI) NewBlockFilter() rpc.ID { - var ( - headers = make(chan *types.Header) - headerSub = api.events.SubscribeNewHeads(headers) - ) - - api.filtersMu.Lock() - api.filters[headerSub.ID] = &filter{typ: BlocksSubscription, deadline: time.NewTimer(api.timeout), hashes: make([]common.Hash, 0), s: headerSub} - api.filtersMu.Unlock() - - go func() { - for { - select { - case h := <-headers: - api.filtersMu.Lock() - if f, found := api.filters[headerSub.ID]; found { - f.hashes = append(f.hashes, h.Hash()) - } - api.filtersMu.Unlock() - case <-headerSub.Err(): - api.filtersMu.Lock() - delete(api.filters, headerSub.ID) - api.filtersMu.Unlock() - return - } - } - }() - - return headerSub.ID -} - -// NewHeads send a notification each time a new (header) block is appended to the chain. -func (api *FilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) { - notifier, supported := rpc.NotifierFromContext(ctx) - if !supported { - return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported - } - - rpcSub := notifier.CreateSubscription() - - go func() { - headers := make(chan *types.Header) - headersSub := api.events.SubscribeNewHeads(headers) - defer headersSub.Unsubscribe() - - for { - select { - case h := <-headers: - notifier.Notify(rpcSub.ID, h) - case <-rpcSub.Err(): - return - case <-notifier.Closed(): - return - } - } - }() - - return rpcSub, nil -} - -// Logs creates a subscription that fires for all new log that match the given filter criteria. -func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subscription, error) { - notifier, supported := rpc.NotifierFromContext(ctx) - if !supported { - return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported - } - - var ( - rpcSub = notifier.CreateSubscription() - matchedLogs = make(chan []*types.Log) - ) - - logsSub, err := api.events.SubscribeLogs(ethereum.FilterQuery(crit), matchedLogs) - if err != nil { - return nil, err - } - - go func() { - defer logsSub.Unsubscribe() - for { - select { - case logs := <-matchedLogs: - for _, log := range logs { - log := log - notifier.Notify(rpcSub.ID, &log) - } - case <-rpcSub.Err(): // client send an unsubscribe request - return - case <-notifier.Closed(): // connection dropped - return - } - } - }() - - return rpcSub, nil -} - -// FilterCriteria represents a request to create a new filter. -// Same as ethereum.FilterQuery but with UnmarshalJSON() method. -type FilterCriteria ethereum.FilterQuery - -// NewFilter creates a new filter and returns the filter id. It can be -// used to retrieve logs when the state changes. This method cannot be -// used to fetch logs that are already stored in the state. -// -// Default criteria for the from and to block are "latest". -// Using "latest" as block number will return logs for mined blocks. -// Using "pending" as block number returns logs for not yet mined (pending) blocks. -// In case logs are removed (chain reorg) previously returned logs are returned -// again but with the removed property set to true. -// -// In case "fromBlock" > "toBlock" an error is returned. -func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) { - logs := make(chan []*types.Log) - logsSub, err := api.events.SubscribeLogs(ethereum.FilterQuery(crit), logs) - if err != nil { - return "", err - } - - api.filtersMu.Lock() - api.filters[logsSub.ID] = &filter{typ: LogsSubscription, crit: crit, deadline: time.NewTimer(api.timeout), logs: make([]*types.Log, 0), s: logsSub} - api.filtersMu.Unlock() - - go func() { - for { - select { - case l := <-logs: - api.filtersMu.Lock() - if f, found := api.filters[logsSub.ID]; found { - f.logs = append(f.logs, l...) - } - api.filtersMu.Unlock() - case <-logsSub.Err(): - api.filtersMu.Lock() - delete(api.filters, logsSub.ID) - api.filtersMu.Unlock() - return - } - } - }() - - return logsSub.ID, nil -} - -// GetLogs returns logs matching the given argument that are stored within the state. -func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) { - if len(crit.Topics) > maxTopics { - return nil, errExceedMaxTopics - } - var filter *Filter - if crit.BlockHash != nil { - // Block filter requested, construct a single-shot filter - filter = api.sys.NewBlockFilter(*crit.BlockHash, crit.Addresses, crit.Topics) - } else { - // Convert the RPC block numbers into internal representations - begin := rpc.LatestBlockNumber.Int64() - if crit.FromBlock != nil { - begin = crit.FromBlock.Int64() - } - end := rpc.LatestBlockNumber.Int64() - if crit.ToBlock != nil { - end = crit.ToBlock.Int64() - } - if begin > 0 && end > 0 && begin > end { - return nil, errInvalidBlockRange - } - // Construct the range filter - filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics) - } - // Run the filter and return all the logs - logs, err := filter.Logs(ctx) - if err != nil { - return nil, err - } - return returnLogs(logs), err -} - -// UninstallFilter removes the filter with the given filter id. -func (api *FilterAPI) UninstallFilter(id rpc.ID) bool { - api.filtersMu.Lock() - f, found := api.filters[id] - if found { - delete(api.filters, id) - } - api.filtersMu.Unlock() - if found { - f.s.Unsubscribe() - } - - return found -} - -// GetFilterLogs returns the logs for the filter with the given id. -// If the filter could not be found an empty array of logs is returned. -func (api *FilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Log, error) { - api.filtersMu.Lock() - f, found := api.filters[id] - api.filtersMu.Unlock() - - if !found || f.typ != LogsSubscription { - return nil, errFilterNotFound - } - - var filter *Filter - if f.crit.BlockHash != nil { - // Block filter requested, construct a single-shot filter - filter = api.sys.NewBlockFilter(*f.crit.BlockHash, f.crit.Addresses, f.crit.Topics) - } else { - // Convert the RPC block numbers into internal representations - begin := rpc.LatestBlockNumber.Int64() - if f.crit.FromBlock != nil { - begin = f.crit.FromBlock.Int64() - } - end := rpc.LatestBlockNumber.Int64() - if f.crit.ToBlock != nil { - end = f.crit.ToBlock.Int64() - } - // Construct the range filter - filter = api.sys.NewRangeFilter(begin, end, f.crit.Addresses, f.crit.Topics) - } - // Run the filter and return all the logs - logs, err := filter.Logs(ctx) - if err != nil { - return nil, err - } - return returnLogs(logs), nil -} - -// GetFilterChanges returns the logs for the filter with the given id since -// last time it was called. This can be used for polling. -// -// For pending transaction and block filters the result is []common.Hash. -// (pending)Log filters return []Log. -func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) { - api.filtersMu.Lock() - defer api.filtersMu.Unlock() - - chainConfig := api.sys.backend.ChainConfig() - latest := api.sys.backend.CurrentHeader() - - if f, found := api.filters[id]; found { - if !f.deadline.Stop() { - // timer expired but filter is not yet removed in timeout loop - // receive timer value and reset timer - <-f.deadline.C - } - f.deadline.Reset(api.timeout) - - switch f.typ { - case BlocksSubscription: - hashes := f.hashes - f.hashes = nil - return returnHashes(hashes), nil - case PendingTransactionsSubscription: - if f.fullTx { - txs := make([]*ethapi.RPCTransaction, 0, len(f.txs)) - for _, tx := range f.txs { - txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig)) - } - f.txs = nil - return txs, nil - } else { - hashes := make([]common.Hash, 0, len(f.txs)) - for _, tx := range f.txs { - hashes = append(hashes, tx.Hash()) - } - f.txs = nil - return hashes, nil - } - case LogsSubscription, MinedAndPendingLogsSubscription: - logs := f.logs - f.logs = nil - return returnLogs(logs), nil - } - } - - return []interface{}{}, errFilterNotFound -} - -// returnHashes is a helper that will return an empty hash array case the given hash array is nil, -// otherwise the given hashes array is returned. -func returnHashes(hashes []common.Hash) []common.Hash { - if hashes == nil { - return []common.Hash{} - } - return hashes -} - -// returnLogs is a helper that will return an empty log array in case the given logs array is nil, -// otherwise the given logs array is returned. -func returnLogs(logs []*types.Log) []*types.Log { - if logs == nil { - return []*types.Log{} - } - return logs -} - -// UnmarshalJSON sets *args fields with given data. -func (args *FilterCriteria) UnmarshalJSON(data []byte) error { - type input struct { - BlockHash *common.Hash `json:"blockHash"` - FromBlock *rpc.BlockNumber `json:"fromBlock"` - ToBlock *rpc.BlockNumber `json:"toBlock"` - Addresses interface{} `json:"address"` - Topics []interface{} `json:"topics"` - } - - var raw input - if err := json.Unmarshal(data, &raw); err != nil { - return err - } - - if raw.BlockHash != nil { - if raw.FromBlock != nil || raw.ToBlock != nil { - // BlockHash is mutually exclusive with FromBlock/ToBlock criteria - return errors.New("cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other") - } - args.BlockHash = raw.BlockHash - } else { - if raw.FromBlock != nil { - args.FromBlock = big.NewInt(raw.FromBlock.Int64()) - } - - if raw.ToBlock != nil { - args.ToBlock = big.NewInt(raw.ToBlock.Int64()) - } - } - - args.Addresses = []common.Address{} - - if raw.Addresses != nil { - // raw.Address can contain a single address or an array of addresses - switch rawAddr := raw.Addresses.(type) { - case []interface{}: - for i, addr := range rawAddr { - if strAddr, ok := addr.(string); ok { - addr, err := decodeAddress(strAddr) - if err != nil { - return fmt.Errorf("invalid address at index %d: %v", i, err) - } - args.Addresses = append(args.Addresses, addr) - } else { - return fmt.Errorf("non-string address at index %d", i) - } - } - case string: - addr, err := decodeAddress(rawAddr) - if err != nil { - return fmt.Errorf("invalid address: %v", err) - } - args.Addresses = []common.Address{addr} - default: - return errors.New("invalid addresses in query") - } - } - - // topics is an array consisting of strings and/or arrays of strings. - // JSON null values are converted to common.Hash{} and ignored by the filter manager. - if len(raw.Topics) > 0 { - args.Topics = make([][]common.Hash, len(raw.Topics)) - for i, t := range raw.Topics { - switch topic := t.(type) { - case nil: - // ignore topic when matching logs - - case string: - // match specific topic - top, err := decodeTopic(topic) - if err != nil { - return err - } - args.Topics[i] = []common.Hash{top} - - case []interface{}: - // or case e.g. [null, "topic0", "topic1"] - for _, rawTopic := range topic { - if rawTopic == nil { - // null component, match all - args.Topics[i] = nil - break - } - if topic, ok := rawTopic.(string); ok { - parsed, err := decodeTopic(topic) - if err != nil { - return err - } - args.Topics[i] = append(args.Topics[i], parsed) - } else { - return errInvalidTopic - } - } - default: - return errInvalidTopic - } - } - } - - return nil -} - -func decodeAddress(s string) (common.Address, error) { - b, err := hexutil.Decode(s) - if err == nil && len(b) != common.AddressLength { - err = fmt.Errorf("hex has invalid length %d after decoding; expected %d for address", len(b), common.AddressLength) - } - return common.BytesToAddress(b), err -} - -func decodeTopic(s string) (common.Hash, error) { - b, err := hexutil.Decode(s) - if err == nil && len(b) != common.HashLength { - err = fmt.Errorf("hex has invalid length %d after decoding; expected %d for topic", len(b), common.HashLength) - } - return common.BytesToHash(b), err -} diff --git a/builder/eth/filters/api_test.go b/builder/eth/filters/api_test.go deleted file mode 100644 index 822bc826f..000000000 --- a/builder/eth/filters/api_test.go +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2016 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 filters - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rpc" -) - -func TestUnmarshalJSONNewFilterArgs(t *testing.T) { - var ( - fromBlock rpc.BlockNumber = 0x123435 - toBlock rpc.BlockNumber = 0xabcdef - address0 = common.HexToAddress("70c87d191324e6712a591f304b4eedef6ad9bb9d") - address1 = common.HexToAddress("9b2055d370f73ec7d8a03e965129118dc8f5bf83") - topic0 = common.HexToHash("3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1ca") - topic1 = common.HexToHash("9084a792d2f8b16a62b882fd56f7860c07bf5fa91dd8a2ae7e809e5180fef0b3") - topic2 = common.HexToHash("6ccae1c4af4152f460ff510e573399795dfab5dcf1fa60d1f33ac8fdc1e480ce") - ) - - // default values - var test0 FilterCriteria - if err := json.Unmarshal([]byte("{}"), &test0); err != nil { - t.Fatal(err) - } - if test0.FromBlock != nil { - t.Fatalf("expected nil, got %d", test0.FromBlock) - } - if test0.ToBlock != nil { - t.Fatalf("expected nil, got %d", test0.ToBlock) - } - if len(test0.Addresses) != 0 { - t.Fatalf("expected 0 addresses, got %d", len(test0.Addresses)) - } - if len(test0.Topics) != 0 { - t.Fatalf("expected 0 topics, got %d topics", len(test0.Topics)) - } - - // from, to block number - var test1 FilterCriteria - vector := fmt.Sprintf(`{"fromBlock":"%v","toBlock":"%v"}`, fromBlock, toBlock) - if err := json.Unmarshal([]byte(vector), &test1); err != nil { - t.Fatal(err) - } - if test1.FromBlock.Int64() != fromBlock.Int64() { - t.Fatalf("expected FromBlock %d, got %d", fromBlock, test1.FromBlock) - } - if test1.ToBlock.Int64() != toBlock.Int64() { - t.Fatalf("expected ToBlock %d, got %d", toBlock, test1.ToBlock) - } - - // single address - var test2 FilterCriteria - vector = fmt.Sprintf(`{"address": "%s"}`, address0.Hex()) - if err := json.Unmarshal([]byte(vector), &test2); err != nil { - t.Fatal(err) - } - if len(test2.Addresses) != 1 { - t.Fatalf("expected 1 address, got %d address(es)", len(test2.Addresses)) - } - if test2.Addresses[0] != address0 { - t.Fatalf("expected address %x, got %x", address0, test2.Addresses[0]) - } - - // multiple address - var test3 FilterCriteria - vector = fmt.Sprintf(`{"address": ["%s", "%s"]}`, address0.Hex(), address1.Hex()) - if err := json.Unmarshal([]byte(vector), &test3); err != nil { - t.Fatal(err) - } - if len(test3.Addresses) != 2 { - t.Fatalf("expected 2 addresses, got %d address(es)", len(test3.Addresses)) - } - if test3.Addresses[0] != address0 { - t.Fatalf("expected address %x, got %x", address0, test3.Addresses[0]) - } - if test3.Addresses[1] != address1 { - t.Fatalf("expected address %x, got %x", address1, test3.Addresses[1]) - } - - // single topic - var test4 FilterCriteria - vector = fmt.Sprintf(`{"topics": ["%s"]}`, topic0.Hex()) - if err := json.Unmarshal([]byte(vector), &test4); err != nil { - t.Fatal(err) - } - if len(test4.Topics) != 1 { - t.Fatalf("expected 1 topic, got %d", len(test4.Topics)) - } - if len(test4.Topics[0]) != 1 { - t.Fatalf("expected len(topics[0]) to be 1, got %d", len(test4.Topics[0])) - } - if test4.Topics[0][0] != topic0 { - t.Fatalf("got %x, expected %x", test4.Topics[0][0], topic0) - } - - // test multiple "AND" topics - var test5 FilterCriteria - vector = fmt.Sprintf(`{"topics": ["%s", "%s"]}`, topic0.Hex(), topic1.Hex()) - if err := json.Unmarshal([]byte(vector), &test5); err != nil { - t.Fatal(err) - } - if len(test5.Topics) != 2 { - t.Fatalf("expected 2 topics, got %d", len(test5.Topics)) - } - if len(test5.Topics[0]) != 1 { - t.Fatalf("expected 1 topic, got %d", len(test5.Topics[0])) - } - if test5.Topics[0][0] != topic0 { - t.Fatalf("got %x, expected %x", test5.Topics[0][0], topic0) - } - if len(test5.Topics[1]) != 1 { - t.Fatalf("expected 1 topic, got %d", len(test5.Topics[1])) - } - if test5.Topics[1][0] != topic1 { - t.Fatalf("got %x, expected %x", test5.Topics[1][0], topic1) - } - - // test optional topic - var test6 FilterCriteria - vector = fmt.Sprintf(`{"topics": ["%s", null, "%s"]}`, topic0.Hex(), topic2.Hex()) - if err := json.Unmarshal([]byte(vector), &test6); err != nil { - t.Fatal(err) - } - if len(test6.Topics) != 3 { - t.Fatalf("expected 3 topics, got %d", len(test6.Topics)) - } - if len(test6.Topics[0]) != 1 { - t.Fatalf("expected 1 topic, got %d", len(test6.Topics[0])) - } - if test6.Topics[0][0] != topic0 { - t.Fatalf("got %x, expected %x", test6.Topics[0][0], topic0) - } - if len(test6.Topics[1]) != 0 { - t.Fatalf("expected 0 topic, got %d", len(test6.Topics[1])) - } - if len(test6.Topics[2]) != 1 { - t.Fatalf("expected 1 topic, got %d", len(test6.Topics[2])) - } - if test6.Topics[2][0] != topic2 { - t.Fatalf("got %x, expected %x", test6.Topics[2][0], topic2) - } - - // test OR topics - var test7 FilterCriteria - vector = fmt.Sprintf(`{"topics": [["%s", "%s"], null, ["%s", null]]}`, topic0.Hex(), topic1.Hex(), topic2.Hex()) - if err := json.Unmarshal([]byte(vector), &test7); err != nil { - t.Fatal(err) - } - if len(test7.Topics) != 3 { - t.Fatalf("expected 3 topics, got %d topics", len(test7.Topics)) - } - if len(test7.Topics[0]) != 2 { - t.Fatalf("expected 2 topics, got %d topics", len(test7.Topics[0])) - } - if test7.Topics[0][0] != topic0 || test7.Topics[0][1] != topic1 { - t.Fatalf("invalid topics expected [%x,%x], got [%x,%x]", - topic0, topic1, test7.Topics[0][0], test7.Topics[0][1], - ) - } - if len(test7.Topics[1]) != 0 { - t.Fatalf("expected 0 topic, got %d topics", len(test7.Topics[1])) - } - if len(test7.Topics[2]) != 0 { - t.Fatalf("expected 0 topics, got %d topics", len(test7.Topics[2])) - } -} diff --git a/builder/eth/filters/bench_test.go b/builder/eth/filters/bench_test.go deleted file mode 100644 index 73b96b77a..000000000 --- a/builder/eth/filters/bench_test.go +++ /dev/null @@ -1,189 +0,0 @@ -// 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 filters - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/bitutil" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/node" -) - -func BenchmarkBloomBits512(b *testing.B) { - benchmarkBloomBits(b, 512) -} - -func BenchmarkBloomBits1k(b *testing.B) { - benchmarkBloomBits(b, 1024) -} - -func BenchmarkBloomBits2k(b *testing.B) { - benchmarkBloomBits(b, 2048) -} - -func BenchmarkBloomBits4k(b *testing.B) { - benchmarkBloomBits(b, 4096) -} - -func BenchmarkBloomBits8k(b *testing.B) { - benchmarkBloomBits(b, 8192) -} - -func BenchmarkBloomBits16k(b *testing.B) { - benchmarkBloomBits(b, 16384) -} - -func BenchmarkBloomBits32k(b *testing.B) { - benchmarkBloomBits(b, 32768) -} - -const benchFilterCnt = 2000 - -func benchmarkBloomBits(b *testing.B, sectionSize uint64) { - b.Skip("test disabled: this tests presume (and modify) an existing datadir.") - benchDataDir := node.DefaultDataDir() + "/geth/chaindata" - b.Log("Running bloombits benchmark section size:", sectionSize) - - db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", benchDataDir, err) - } - head := rawdb.ReadHeadBlockHash(db) - if head == (common.Hash{}) { - b.Fatalf("chain data not found at %v", benchDataDir) - } - - clearBloomBits(db) - b.Log("Generating bloombits data...") - headNum := rawdb.ReadHeaderNumber(db, head) - if headNum == nil || *headNum < sectionSize+512 { - b.Fatalf("not enough blocks for running a benchmark") - } - - start := time.Now() - cnt := (*headNum - 512) / sectionSize - var dataSize, compSize uint64 - for sectionIdx := uint64(0); sectionIdx < cnt; sectionIdx++ { - bc, err := bloombits.NewGenerator(uint(sectionSize)) - if err != nil { - b.Fatalf("failed to create generator: %v", err) - } - var header *types.Header - for i := sectionIdx * sectionSize; i < (sectionIdx+1)*sectionSize; i++ { - hash := rawdb.ReadCanonicalHash(db, i) - if header = rawdb.ReadHeader(db, hash, i); header == nil { - b.Fatalf("Error creating bloomBits data") - return - } - bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom) - } - sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*sectionSize-1) - for i := 0; i < types.BloomBitLength; i++ { - data, err := bc.Bitset(uint(i)) - if err != nil { - b.Fatalf("failed to retrieve bitset: %v", err) - } - comp := bitutil.CompressBytes(data) - dataSize += uint64(len(data)) - compSize += uint64(len(comp)) - rawdb.WriteBloomBits(db, uint(i), sectionIdx, sectionHead, comp) - } - //if sectionIdx%50 == 0 { - // b.Log(" section", sectionIdx, "/", cnt) - //} - } - - d := time.Since(start) - b.Log("Finished generating bloombits data") - b.Log(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") - b.Log(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) - - b.Log("Running filter benchmarks...") - start = time.Now() - - var ( - backend *testBackend - sys *FilterSystem - ) - for i := 0; i < benchFilterCnt; i++ { - if i%20 == 0 { - db.Close() - db, _ = rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - backend = &testBackend{db: db, sections: cnt} - sys = NewFilterSystem(backend, Config{}) - } - var addr common.Address - addr[0] = byte(i) - addr[1] = byte(i / 256) - filter := sys.NewRangeFilter(0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) - if _, err := filter.Logs(context.Background()); err != nil { - b.Error("filter.Logs error:", err) - } - } - - d = time.Since(start) - b.Log("Finished running filter benchmarks") - b.Log(" ", d, "total ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks") - db.Close() -} - -//nolint:unused -func clearBloomBits(db ethdb.Database) { - var bloomBitsPrefix = []byte("bloomBits-") - fmt.Println("Clearing bloombits data...") - it := db.NewIterator(bloomBitsPrefix, nil) - for it.Next() { - db.Delete(it.Key()) - } - it.Release() -} - -func BenchmarkNoBloomBits(b *testing.B) { - b.Skip("test disabled: this tests presume (and modify) an existing datadir.") - benchDataDir := node.DefaultDataDir() + "/geth/chaindata" - b.Log("Running benchmark without bloombits") - db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - if err != nil { - b.Fatalf("error opening database at %v: %v", benchDataDir, err) - } - head := rawdb.ReadHeadBlockHash(db) - if head == (common.Hash{}) { - b.Fatalf("chain data not found at %v", benchDataDir) - } - headNum := rawdb.ReadHeaderNumber(db, head) - - clearBloomBits(db) - - _, sys := newTestFilterSystem(b, db, Config{}) - - b.Log("Running filter benchmarks...") - start := time.Now() - filter := sys.NewRangeFilter(0, int64(*headNum), []common.Address{{}}, nil) - filter.Logs(context.Background()) - d := time.Since(start) - b.Log("Finished running filter benchmarks") - b.Log(" ", d, "total ", d*time.Duration(1000000)/time.Duration(*headNum+1), "per million blocks") - db.Close() -} diff --git a/builder/eth/filters/filter.go b/builder/eth/filters/filter.go deleted file mode 100644 index 83e3284a2..000000000 --- a/builder/eth/filters/filter.go +++ /dev/null @@ -1,422 +0,0 @@ -// 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 filters - -import ( - "context" - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" -) - -// Filter can be used to retrieve and filter logs. -type Filter struct { - sys *FilterSystem - - addresses []common.Address - topics [][]common.Hash - - block *common.Hash // Block hash if filtering a single block - begin, end int64 // Range interval if filtering multiple blocks - - matcher *bloombits.Matcher -} - -// NewRangeFilter creates a new filter which uses a bloom filter on blocks to -// figure out whether a particular block is interesting or not. -func (sys *FilterSystem) NewRangeFilter(begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter { - // Flatten the address and topic filter clauses into a single bloombits filter - // system. Since the bloombits are not positional, nil topics are permitted, - // which get flattened into a nil byte slice. - var filters [][][]byte - if len(addresses) > 0 { - filter := make([][]byte, len(addresses)) - for i, address := range addresses { - filter[i] = address.Bytes() - } - filters = append(filters, filter) - } - for _, topicList := range topics { - filter := make([][]byte, len(topicList)) - for i, topic := range topicList { - filter[i] = topic.Bytes() - } - filters = append(filters, filter) - } - size, _ := sys.backend.BloomStatus() - - // Create a generic filter and convert it into a range filter - filter := newFilter(sys, addresses, topics) - - filter.matcher = bloombits.NewMatcher(size, filters) - filter.begin = begin - filter.end = end - - return filter -} - -// NewBlockFilter creates a new filter which directly inspects the contents of -// a block to figure out whether it is interesting or not. -func (sys *FilterSystem) NewBlockFilter(block common.Hash, addresses []common.Address, topics [][]common.Hash) *Filter { - // Create a generic filter and convert it into a block filter - filter := newFilter(sys, addresses, topics) - filter.block = &block - return filter -} - -// newFilter creates a generic filter that can either filter based on a block hash, -// or based on range queries. The search criteria needs to be explicitly set. -func newFilter(sys *FilterSystem, addresses []common.Address, topics [][]common.Hash) *Filter { - return &Filter{ - sys: sys, - addresses: addresses, - topics: topics, - } -} - -// Logs searches the blockchain for matching log entries, returning all from the -// first block that contains matches, updating the start of the filter accordingly. -func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) { - // If we're doing singleton block filtering, execute and return - if f.block != nil { - header, err := f.sys.backend.HeaderByHash(ctx, *f.block) - if err != nil { - return nil, err - } - if header == nil { - return nil, errors.New("unknown block") - } - return f.blockLogs(ctx, header) - } - - var ( - beginPending = f.begin == rpc.PendingBlockNumber.Int64() - endPending = f.end == rpc.PendingBlockNumber.Int64() - ) - - // special case for pending logs - if beginPending && !endPending { - return nil, errInvalidBlockRange - } - - // Short-cut if all we care about is pending logs - if beginPending && endPending { - return f.pendingLogs(), nil - } - - resolveSpecial := func(number int64) (int64, error) { - var hdr *types.Header - switch number { - case rpc.LatestBlockNumber.Int64(), rpc.PendingBlockNumber.Int64(): - // we should return head here since we've already captured - // that we need to get the pending logs in the pending boolean above - hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber) - if hdr == nil { - return 0, errors.New("latest header not found") - } - case rpc.FinalizedBlockNumber.Int64(): - hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) - if hdr == nil { - return 0, errors.New("finalized header not found") - } - case rpc.SafeBlockNumber.Int64(): - hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber) - if hdr == nil { - return 0, errors.New("safe header not found") - } - default: - return number, nil - } - return hdr.Number.Int64(), nil - } - - var err error - // range query need to resolve the special begin/end block number - if f.begin, err = resolveSpecial(f.begin); err != nil { - return nil, err - } - if f.end, err = resolveSpecial(f.end); err != nil { - return nil, err - } - - logChan, errChan := f.rangeLogsAsync(ctx) - var logs []*types.Log - for { - select { - case log := <-logChan: - logs = append(logs, log) - case err := <-errChan: - if err != nil { - // if an error occurs during extraction, we do return the extracted data - return logs, err - } - // Append the pending ones - if endPending { - pendingLogs := f.pendingLogs() - logs = append(logs, pendingLogs...) - } - return logs, nil - } - } -} - -// rangeLogsAsync retrieves block-range logs that match the filter criteria asynchronously, -// it creates and returns two channels: one for delivering log data, and one for reporting errors. -func (f *Filter) rangeLogsAsync(ctx context.Context) (chan *types.Log, chan error) { - var ( - logChan = make(chan *types.Log) - errChan = make(chan error) - ) - - go func() { - defer func() { - close(errChan) - close(logChan) - }() - - // Gather all indexed logs, and finish with non indexed ones - var ( - end = uint64(f.end) - size, sections = f.sys.backend.BloomStatus() - err error - ) - if indexed := sections * size; indexed > uint64(f.begin) { - if indexed > end { - indexed = end + 1 - } - if err = f.indexedLogs(ctx, indexed-1, logChan); err != nil { - errChan <- err - return - } - } - - if err := f.unindexedLogs(ctx, end, logChan); err != nil { - errChan <- err - return - } - - errChan <- nil - }() - - return logChan, errChan -} - -// indexedLogs returns the logs matching the filter criteria based on the bloom -// bits indexed available locally or via the network. -func (f *Filter) indexedLogs(ctx context.Context, end uint64, logChan chan *types.Log) error { - // Create a matcher session and request servicing from the backend - matches := make(chan uint64, 64) - - session, err := f.matcher.Start(ctx, uint64(f.begin), end, matches) - if err != nil { - return err - } - defer session.Close() - - f.sys.backend.ServiceFilter(ctx, session) - - for { - select { - case number, ok := <-matches: - // Abort if all matches have been fulfilled - if !ok { - err := session.Error() - if err == nil { - f.begin = int64(end) + 1 - } - return err - } - f.begin = int64(number) + 1 - - // Retrieve the suggested block and pull any truly matching logs - header, err := f.sys.backend.HeaderByNumber(ctx, rpc.BlockNumber(number)) - if header == nil || err != nil { - return err - } - found, err := f.checkMatches(ctx, header) - if err != nil { - return err - } - for _, log := range found { - logChan <- log - } - - case <-ctx.Done(): - return ctx.Err() - } - } -} - -// unindexedLogs returns the logs matching the filter criteria based on raw block -// iteration and bloom matching. -func (f *Filter) unindexedLogs(ctx context.Context, end uint64, logChan chan *types.Log) error { - for ; f.begin <= int64(end); f.begin++ { - header, err := f.sys.backend.HeaderByNumber(ctx, rpc.BlockNumber(f.begin)) - if header == nil || err != nil { - return err - } - found, err := f.blockLogs(ctx, header) - if err != nil { - return err - } - for _, log := range found { - select { - case logChan <- log: - case <-ctx.Done(): - return ctx.Err() - } - } - } - return nil -} - -// blockLogs returns the logs matching the filter criteria within a single block. -func (f *Filter) blockLogs(ctx context.Context, header *types.Header) ([]*types.Log, error) { - if bloomFilter(header.Bloom, f.addresses, f.topics) { - return f.checkMatches(ctx, header) - } - return nil, nil -} - -// checkMatches checks if the receipts belonging to the given header contain any log events that -// match the filter criteria. This function is called when the bloom filter signals a potential match. -// skipFilter signals all logs of the given block are requested. -func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*types.Log, error) { - hash := header.Hash() - // Logs in cache are partially filled with context data - // such as tx index, block hash, etc. - // Notably tx hash is NOT filled in because it needs - // access to block body data. - cached, err := f.sys.cachedLogElem(ctx, hash, header.Number.Uint64()) - if err != nil { - return nil, err - } - logs := filterLogs(cached.logs, nil, nil, f.addresses, f.topics) - if len(logs) == 0 { - return nil, nil - } - // Most backends will deliver un-derived logs, but check nevertheless. - if len(logs) > 0 && logs[0].TxHash != (common.Hash{}) { - return logs, nil - } - - body, err := f.sys.cachedGetBody(ctx, cached, hash, header.Number.Uint64()) - if err != nil { - return nil, err - } - for i, log := range logs { - // Copy log not to modify cache elements - logcopy := *log - logcopy.TxHash = body.Transactions[logcopy.TxIndex].Hash() - logs[i] = &logcopy - } - return logs, nil -} - -// pendingLogs returns the logs matching the filter criteria within the pending block. -func (f *Filter) pendingLogs() []*types.Log { - block, receipts := f.sys.backend.PendingBlockAndReceipts() - if block == nil || receipts == nil { - return nil - } - if bloomFilter(block.Bloom(), f.addresses, f.topics) { - var unfiltered []*types.Log - for _, r := range receipts { - unfiltered = append(unfiltered, r.Logs...) - } - return filterLogs(unfiltered, nil, nil, f.addresses, f.topics) - } - return nil -} - -// includes returns true if the element is present in the list. -func includes[T comparable](things []T, element T) bool { - for _, thing := range things { - if thing == element { - return true - } - } - return false -} - -// filterLogs creates a slice of logs matching the given criteria. -func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log { - var check = func(log *types.Log) bool { - if fromBlock != nil && fromBlock.Int64() >= 0 && fromBlock.Uint64() > log.BlockNumber { - return false - } - if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber { - return false - } - if len(addresses) > 0 && !includes(addresses, log.Address) { - return false - } - // If the to filtered topics is greater than the amount of topics in logs, skip. - if len(topics) > len(log.Topics) { - return false - } - for i, sub := range topics { - if len(sub) == 0 { - continue // empty rule set == wildcard - } - if !includes(sub, log.Topics[i]) { - return false - } - } - return true - } - var ret []*types.Log - for _, log := range logs { - if check(log) { - ret = append(ret, log) - } - } - return ret -} - -func bloomFilter(bloom types.Bloom, addresses []common.Address, topics [][]common.Hash) bool { - if len(addresses) > 0 { - var included bool - for _, addr := range addresses { - if types.BloomLookup(bloom, addr) { - included = true - break - } - } - if !included { - return false - } - } - - for _, sub := range topics { - included := len(sub) == 0 // empty rule set == wildcard - for _, topic := range sub { - if types.BloomLookup(bloom, topic) { - included = true - break - } - } - if !included { - return false - } - } - return true -} diff --git a/builder/eth/filters/filter_system.go b/builder/eth/filters/filter_system.go deleted file mode 100644 index f98a1f84c..000000000 --- a/builder/eth/filters/filter_system.go +++ /dev/null @@ -1,606 +0,0 @@ -// 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 filters implements an ethereum filtering system for block, -// transactions and log events. -package filters - -import ( - "context" - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -// Config represents the configuration of the filter system. -type Config struct { - LogCacheSize int // maximum number of cached blocks (default: 32) - Timeout time.Duration // how long filters stay active (default: 5min) -} - -func (cfg Config) withDefaults() Config { - if cfg.Timeout == 0 { - cfg.Timeout = 5 * time.Minute - } - if cfg.LogCacheSize == 0 { - cfg.LogCacheSize = 32 - } - return cfg -} - -type Backend interface { - ChainDb() ethdb.Database - HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) - HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error) - GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) - GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) - GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) - PendingBlockAndReceipts() (*types.Block, types.Receipts) - - CurrentHeader() *types.Header - ChainConfig() *params.ChainConfig - SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription - SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription - SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription - SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription - SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription - - BloomStatus() (uint64, uint64) - ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) -} - -// FilterSystem holds resources shared by all filters. -type FilterSystem struct { - backend Backend - logsCache *lru.Cache[common.Hash, *logCacheElem] - cfg *Config -} - -// NewFilterSystem creates a filter system. -func NewFilterSystem(backend Backend, config Config) *FilterSystem { - config = config.withDefaults() - return &FilterSystem{ - backend: backend, - logsCache: lru.NewCache[common.Hash, *logCacheElem](config.LogCacheSize), - cfg: &config, - } -} - -type logCacheElem struct { - logs []*types.Log - body atomic.Value -} - -// cachedLogElem loads block logs from the backend and caches the result. -func (sys *FilterSystem) cachedLogElem(ctx context.Context, blockHash common.Hash, number uint64) (*logCacheElem, error) { - cached, ok := sys.logsCache.Get(blockHash) - if ok { - return cached, nil - } - - logs, err := sys.backend.GetLogs(ctx, blockHash, number) - if err != nil { - return nil, err - } - if logs == nil { - return nil, fmt.Errorf("failed to get logs for block #%d (0x%s)", number, blockHash.TerminalString()) - } - // Database logs are un-derived. - // Fill in whatever we can (txHash is inaccessible at this point). - flattened := make([]*types.Log, 0) - var logIdx uint - for i, txLogs := range logs { - for _, log := range txLogs { - log.BlockHash = blockHash - log.BlockNumber = number - log.TxIndex = uint(i) - log.Index = logIdx - logIdx++ - flattened = append(flattened, log) - } - } - elem := &logCacheElem{logs: flattened} - sys.logsCache.Add(blockHash, elem) - return elem, nil -} - -func (sys *FilterSystem) cachedGetBody(ctx context.Context, elem *logCacheElem, hash common.Hash, number uint64) (*types.Body, error) { - if body := elem.body.Load(); body != nil { - return body.(*types.Body), nil - } - body, err := sys.backend.GetBody(ctx, hash, rpc.BlockNumber(number)) - if err != nil { - return nil, err - } - elem.body.Store(body) - return body, nil -} - -// Type determines the kind of filter and is used to put the filter in to -// the correct bucket when added. -type Type byte - -const ( - // UnknownSubscription indicates an unknown subscription type - UnknownSubscription Type = iota - // LogsSubscription queries for new or removed (chain reorg) logs - LogsSubscription - // PendingLogsSubscription queries for logs in pending blocks - PendingLogsSubscription - // MinedAndPendingLogsSubscription queries for logs in mined and pending blocks. - MinedAndPendingLogsSubscription - // PendingTransactionsSubscription queries for pending transactions entering - // the pending state - PendingTransactionsSubscription - // BlocksSubscription queries hashes for blocks that are imported - BlocksSubscription - // LastIndexSubscription keeps track of the last index - LastIndexSubscription -) - -const ( - // txChanSize is the size of channel listening to NewTxsEvent. - // The number is referenced from the size of tx pool. - txChanSize = 4096 - // rmLogsChanSize is the size of channel listening to RemovedLogsEvent. - rmLogsChanSize = 10 - // logsChanSize is the size of channel listening to LogsEvent. - logsChanSize = 10 - // chainEvChanSize is the size of channel listening to ChainEvent. - chainEvChanSize = 10 -) - -type subscription struct { - id rpc.ID - typ Type - created time.Time - logsCrit ethereum.FilterQuery - logs chan []*types.Log - txs chan []*types.Transaction - headers chan *types.Header - installed chan struct{} // closed when the filter is installed - err chan error // closed when the filter is uninstalled -} - -// EventSystem creates subscriptions, processes events and broadcasts them to the -// subscription which match the subscription criteria. -type EventSystem struct { - backend Backend - sys *FilterSystem - lightMode bool - lastHead *types.Header - - // Subscriptions - txsSub event.Subscription // Subscription for new transaction event - logsSub event.Subscription // Subscription for new log event - rmLogsSub event.Subscription // Subscription for removed log event - pendingLogsSub event.Subscription // Subscription for pending log event - chainSub event.Subscription // Subscription for new chain event - - // Channels - install chan *subscription // install filter for event notification - uninstall chan *subscription // remove filter for event notification - txsCh chan core.NewTxsEvent // Channel to receive new transactions event - logsCh chan []*types.Log // Channel to receive new log event - pendingLogsCh chan []*types.Log // Channel to receive new log event - rmLogsCh chan core.RemovedLogsEvent // Channel to receive removed log event - chainCh chan core.ChainEvent // Channel to receive new chain event -} - -// NewEventSystem creates a new manager that listens for event on the given mux, -// parses and filters them. It uses the all map to retrieve filter changes. The -// work loop holds its own index that is used to forward events to filters. -// -// The returned manager has a loop that needs to be stopped with the Stop function -// or by stopping the given mux. -func NewEventSystem(sys *FilterSystem, lightMode bool) *EventSystem { - m := &EventSystem{ - sys: sys, - backend: sys.backend, - lightMode: lightMode, - install: make(chan *subscription), - uninstall: make(chan *subscription), - txsCh: make(chan core.NewTxsEvent, txChanSize), - logsCh: make(chan []*types.Log, logsChanSize), - rmLogsCh: make(chan core.RemovedLogsEvent, rmLogsChanSize), - pendingLogsCh: make(chan []*types.Log, logsChanSize), - chainCh: make(chan core.ChainEvent, chainEvChanSize), - } - - // Subscribe events - m.txsSub = m.backend.SubscribeNewTxsEvent(m.txsCh) - m.logsSub = m.backend.SubscribeLogsEvent(m.logsCh) - m.rmLogsSub = m.backend.SubscribeRemovedLogsEvent(m.rmLogsCh) - m.chainSub = m.backend.SubscribeChainEvent(m.chainCh) - m.pendingLogsSub = m.backend.SubscribePendingLogsEvent(m.pendingLogsCh) - - // Make sure none of the subscriptions are empty - if m.txsSub == nil || m.logsSub == nil || m.rmLogsSub == nil || m.chainSub == nil || m.pendingLogsSub == nil { - log.Crit("Subscribe for event system failed") - } - - go m.eventLoop() - return m -} - -// Subscription is created when the client registers itself for a particular event. -type Subscription struct { - ID rpc.ID - f *subscription - es *EventSystem - unsubOnce sync.Once -} - -// Err returns a channel that is closed when unsubscribed. -func (sub *Subscription) Err() <-chan error { - return sub.f.err -} - -// Unsubscribe uninstalls the subscription from the event broadcast loop. -func (sub *Subscription) Unsubscribe() { - sub.unsubOnce.Do(func() { - uninstallLoop: - for { - // write uninstall request and consume logs/hashes. This prevents - // the eventLoop broadcast method to deadlock when writing to the - // filter event channel while the subscription loop is waiting for - // this method to return (and thus not reading these events). - select { - case sub.es.uninstall <- sub.f: - break uninstallLoop - case <-sub.f.logs: - case <-sub.f.txs: - case <-sub.f.headers: - } - } - - // wait for filter to be uninstalled in work loop before returning - // this ensures that the manager won't use the event channel which - // will probably be closed by the client asap after this method returns. - <-sub.Err() - }) -} - -// subscribe installs the subscription in the event broadcast loop. -func (es *EventSystem) subscribe(sub *subscription) *Subscription { - es.install <- sub - <-sub.installed - return &Subscription{ID: sub.id, f: sub, es: es} -} - -// SubscribeLogs creates a subscription that will write all logs matching the -// given criteria to the given logs channel. Default value for the from and to -// block is "latest". If the fromBlock > toBlock an error is returned. -func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) { - if len(crit.Topics) > maxTopics { - return nil, errExceedMaxTopics - } - var from, to rpc.BlockNumber - if crit.FromBlock == nil { - from = rpc.LatestBlockNumber - } else { - from = rpc.BlockNumber(crit.FromBlock.Int64()) - } - if crit.ToBlock == nil { - to = rpc.LatestBlockNumber - } else { - to = rpc.BlockNumber(crit.ToBlock.Int64()) - } - - // only interested in pending logs - if from == rpc.PendingBlockNumber && to == rpc.PendingBlockNumber { - return es.subscribePendingLogs(crit, logs), nil - } - // only interested in new mined logs - if from == rpc.LatestBlockNumber && to == rpc.LatestBlockNumber { - return es.subscribeLogs(crit, logs), nil - } - // only interested in mined logs within a specific block range - if from >= 0 && to >= 0 && to >= from { - return es.subscribeLogs(crit, logs), nil - } - // interested in mined logs from a specific block number, new logs and pending logs - if from >= rpc.LatestBlockNumber && to == rpc.PendingBlockNumber { - return es.subscribeMinedPendingLogs(crit, logs), nil - } - // interested in logs from a specific block number to new mined blocks - if from >= 0 && to == rpc.LatestBlockNumber { - return es.subscribeLogs(crit, logs), nil - } - return nil, errInvalidBlockRange -} - -// subscribeMinedPendingLogs creates a subscription that returned mined and -// pending logs that match the given criteria. -func (es *EventSystem) subscribeMinedPendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { - sub := &subscription{ - id: rpc.NewID(), - typ: MinedAndPendingLogsSubscription, - logsCrit: crit, - created: time.Now(), - logs: logs, - txs: make(chan []*types.Transaction), - headers: make(chan *types.Header), - installed: make(chan struct{}), - err: make(chan error), - } - return es.subscribe(sub) -} - -// subscribeLogs creates a subscription that will write all logs matching the -// given criteria to the given logs channel. -func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { - sub := &subscription{ - id: rpc.NewID(), - typ: LogsSubscription, - logsCrit: crit, - created: time.Now(), - logs: logs, - txs: make(chan []*types.Transaction), - headers: make(chan *types.Header), - installed: make(chan struct{}), - err: make(chan error), - } - return es.subscribe(sub) -} - -// subscribePendingLogs creates a subscription that writes contract event logs for -// transactions that enter the transaction pool. -func (es *EventSystem) subscribePendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription { - sub := &subscription{ - id: rpc.NewID(), - typ: PendingLogsSubscription, - logsCrit: crit, - created: time.Now(), - logs: logs, - txs: make(chan []*types.Transaction), - headers: make(chan *types.Header), - installed: make(chan struct{}), - err: make(chan error), - } - return es.subscribe(sub) -} - -// SubscribeNewHeads creates a subscription that writes the header of a block that is -// imported in the chain. -func (es *EventSystem) SubscribeNewHeads(headers chan *types.Header) *Subscription { - sub := &subscription{ - id: rpc.NewID(), - typ: BlocksSubscription, - created: time.Now(), - logs: make(chan []*types.Log), - txs: make(chan []*types.Transaction), - headers: headers, - installed: make(chan struct{}), - err: make(chan error), - } - return es.subscribe(sub) -} - -// SubscribePendingTxs creates a subscription that writes transactions for -// transactions that enter the transaction pool. -func (es *EventSystem) SubscribePendingTxs(txs chan []*types.Transaction) *Subscription { - sub := &subscription{ - id: rpc.NewID(), - typ: PendingTransactionsSubscription, - created: time.Now(), - logs: make(chan []*types.Log), - txs: txs, - headers: make(chan *types.Header), - installed: make(chan struct{}), - err: make(chan error), - } - return es.subscribe(sub) -} - -type filterIndex map[Type]map[rpc.ID]*subscription - -func (es *EventSystem) handleLogs(filters filterIndex, ev []*types.Log) { - if len(ev) == 0 { - return - } - for _, f := range filters[LogsSubscription] { - matchedLogs := filterLogs(ev, f.logsCrit.FromBlock, f.logsCrit.ToBlock, f.logsCrit.Addresses, f.logsCrit.Topics) - if len(matchedLogs) > 0 { - f.logs <- matchedLogs - } - } -} - -func (es *EventSystem) handlePendingLogs(filters filterIndex, ev []*types.Log) { - if len(ev) == 0 { - return - } - for _, f := range filters[PendingLogsSubscription] { - matchedLogs := filterLogs(ev, nil, f.logsCrit.ToBlock, f.logsCrit.Addresses, f.logsCrit.Topics) - if len(matchedLogs) > 0 { - f.logs <- matchedLogs - } - } -} - -func (es *EventSystem) handleTxsEvent(filters filterIndex, ev core.NewTxsEvent) { - for _, f := range filters[PendingTransactionsSubscription] { - f.txs <- ev.Txs - } -} - -func (es *EventSystem) handleChainEvent(filters filterIndex, ev core.ChainEvent) { - for _, f := range filters[BlocksSubscription] { - f.headers <- ev.Block.Header() - } - if es.lightMode && len(filters[LogsSubscription]) > 0 { - es.lightFilterNewHead(ev.Block.Header(), func(header *types.Header, remove bool) { - for _, f := range filters[LogsSubscription] { - if f.logsCrit.FromBlock != nil && header.Number.Cmp(f.logsCrit.FromBlock) < 0 { - continue - } - if f.logsCrit.ToBlock != nil && header.Number.Cmp(f.logsCrit.ToBlock) > 0 { - continue - } - if matchedLogs := es.lightFilterLogs(header, f.logsCrit.Addresses, f.logsCrit.Topics, remove); len(matchedLogs) > 0 { - f.logs <- matchedLogs - } - } - }) - } -} - -func (es *EventSystem) lightFilterNewHead(newHeader *types.Header, callBack func(*types.Header, bool)) { - oldh := es.lastHead - es.lastHead = newHeader - if oldh == nil { - return - } - newh := newHeader - // find common ancestor, create list of rolled back and new block hashes - var oldHeaders, newHeaders []*types.Header - for oldh.Hash() != newh.Hash() { - if oldh.Number.Uint64() >= newh.Number.Uint64() { - oldHeaders = append(oldHeaders, oldh) - oldh = rawdb.ReadHeader(es.backend.ChainDb(), oldh.ParentHash, oldh.Number.Uint64()-1) - } - if oldh.Number.Uint64() < newh.Number.Uint64() { - newHeaders = append(newHeaders, newh) - newh = rawdb.ReadHeader(es.backend.ChainDb(), newh.ParentHash, newh.Number.Uint64()-1) - if newh == nil { - // happens when CHT syncing, nothing to do - newh = oldh - } - } - } - // roll back old blocks - for _, h := range oldHeaders { - callBack(h, true) - } - // check new blocks (array is in reverse order) - for i := len(newHeaders) - 1; i >= 0; i-- { - callBack(newHeaders[i], false) - } -} - -// filter logs of a single header in light client mode -func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.Address, topics [][]common.Hash, remove bool) []*types.Log { - if !bloomFilter(header.Bloom, addresses, topics) { - return nil - } - // Get the logs of the block - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - cached, err := es.sys.cachedLogElem(ctx, header.Hash(), header.Number.Uint64()) - if err != nil { - return nil - } - unfiltered := append([]*types.Log{}, cached.logs...) - for i, log := range unfiltered { - // Don't modify in-cache elements - logcopy := *log - logcopy.Removed = remove - // Swap copy in-place - unfiltered[i] = &logcopy - } - logs := filterLogs(unfiltered, nil, nil, addresses, topics) - // Txhash is already resolved - if len(logs) > 0 && logs[0].TxHash != (common.Hash{}) { - return logs - } - // Resolve txhash - body, err := es.sys.cachedGetBody(ctx, cached, header.Hash(), header.Number.Uint64()) - if err != nil { - return nil - } - for _, log := range logs { - // logs are already copied, safe to modify - log.TxHash = body.Transactions[log.TxIndex].Hash() - } - return logs -} - -// eventLoop (un)installs filters and processes mux events. -func (es *EventSystem) eventLoop() { - // Ensure all subscriptions get cleaned up - defer func() { - es.txsSub.Unsubscribe() - es.logsSub.Unsubscribe() - es.rmLogsSub.Unsubscribe() - es.pendingLogsSub.Unsubscribe() - es.chainSub.Unsubscribe() - }() - - index := make(filterIndex) - for i := UnknownSubscription; i < LastIndexSubscription; i++ { - index[i] = make(map[rpc.ID]*subscription) - } - - for { - select { - case ev := <-es.txsCh: - es.handleTxsEvent(index, ev) - case ev := <-es.logsCh: - es.handleLogs(index, ev) - case ev := <-es.rmLogsCh: - es.handleLogs(index, ev.Logs) - case ev := <-es.pendingLogsCh: - es.handlePendingLogs(index, ev) - case ev := <-es.chainCh: - es.handleChainEvent(index, ev) - - case f := <-es.install: - if f.typ == MinedAndPendingLogsSubscription { - // the type are logs and pending logs subscriptions - index[LogsSubscription][f.id] = f - index[PendingLogsSubscription][f.id] = f - } else { - index[f.typ][f.id] = f - } - close(f.installed) - - case f := <-es.uninstall: - if f.typ == MinedAndPendingLogsSubscription { - // the type are logs and pending logs subscriptions - delete(index[LogsSubscription], f.id) - delete(index[PendingLogsSubscription], f.id) - } else { - delete(index[f.typ], f.id) - } - close(f.err) - - // System stopped - case <-es.txsSub.Err(): - return - case <-es.logsSub.Err(): - return - case <-es.rmLogsSub.Err(): - return - case <-es.chainSub.Err(): - return - } - } -} diff --git a/builder/eth/filters/filter_system_test.go b/builder/eth/filters/filter_system_test.go deleted file mode 100644 index 99c012cc8..000000000 --- a/builder/eth/filters/filter_system_test.go +++ /dev/null @@ -1,977 +0,0 @@ -// Copyright 2016 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 filters - -import ( - "context" - "errors" - "fmt" - "math/big" - "math/rand" - "reflect" - "runtime" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -type testBackend struct { - db ethdb.Database - sections uint64 - txFeed event.Feed - logsFeed event.Feed - rmLogsFeed event.Feed - pendingLogsFeed event.Feed - chainFeed event.Feed - pendingBlock *types.Block - pendingReceipts types.Receipts -} - -func (b *testBackend) ChainConfig() *params.ChainConfig { - return params.TestChainConfig -} - -func (b *testBackend) CurrentHeader() *types.Header { - hdr, _ := b.HeaderByNumber(context.TODO(), rpc.LatestBlockNumber) - return hdr -} - -func (b *testBackend) ChainDb() ethdb.Database { - return b.db -} - -func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { - var ( - hash common.Hash - num uint64 - ) - switch blockNr { - case rpc.LatestBlockNumber: - hash = rawdb.ReadHeadBlockHash(b.db) - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - num = *number - case rpc.FinalizedBlockNumber: - hash = rawdb.ReadFinalizedBlockHash(b.db) - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - num = *number - case rpc.SafeBlockNumber: - return nil, errors.New("safe block not found") - default: - num = uint64(blockNr) - hash = rawdb.ReadCanonicalHash(b.db, num) - } - return rawdb.ReadHeader(b.db, hash, num), nil -} - -func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - return rawdb.ReadHeader(b.db, hash, *number), nil -} - -func (b *testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { - if body := rawdb.ReadBody(b.db, hash, uint64(number)); body != nil { - return body, nil - } - return nil, errors.New("block body not found") -} - -func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil { - if header := rawdb.ReadHeader(b.db, hash, *number); header != nil { - return rawdb.ReadReceipts(b.db, hash, *number, header.Time, params.TestChainConfig), nil - } - } - return nil, nil -} - -func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { - logs := rawdb.ReadLogs(b.db, hash, number) - return logs, nil -} - -func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { - return b.pendingBlock, b.pendingReceipts -} - -func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return b.txFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - return b.rmLogsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.logsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.pendingLogsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - return b.chainFeed.Subscribe(ch) -} - -func (b *testBackend) BloomStatus() (uint64, uint64) { - return params.BloomBitsBlocks, b.sections -} - -func (b *testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { - requests := make(chan chan *bloombits.Retrieval) - - go session.Multiplex(16, 0, requests) - go func() { - for { - // Wait for a service request or a shutdown - select { - case <-ctx.Done(): - return - - case request := <-requests: - task := <-request - - task.Bitsets = make([][]byte, len(task.Sections)) - for i, section := range task.Sections { - if rand.Int()%4 != 0 { // Handle occasional missing deliveries - head := rawdb.ReadCanonicalHash(b.db, (section+1)*params.BloomBitsBlocks-1) - task.Bitsets[i], _ = rawdb.ReadBloomBits(b.db, task.Bit, section, head) - } - } - request <- task - } - } - }() -} - -func newTestFilterSystem(t testing.TB, db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) { - backend := &testBackend{db: db} - sys := NewFilterSystem(backend, cfg) - return backend, sys -} - -// TestBlockSubscription tests if a block subscription returns block hashes for posted chain events. -// It creates multiple subscriptions: -// - one at the start and should receive all posted chain events and a second (blockHashes) -// - one that is created after a cutoff moment and uninstalled after a second cutoff moment (blockHashes[cutoff1:cutoff2]) -// - one that is created after the second cutoff moment (blockHashes[cutoff2:]) -func TestBlockSubscription(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - genesis = &core.Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - } - _, chain, _ = core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 10, func(i int, gen *core.BlockGen) {}) - chainEvents = []core.ChainEvent{} - ) - - for _, blk := range chain { - chainEvents = append(chainEvents, core.ChainEvent{Hash: blk.Hash(), Block: blk}) - } - - chan0 := make(chan *types.Header) - sub0 := api.events.SubscribeNewHeads(chan0) - chan1 := make(chan *types.Header) - sub1 := api.events.SubscribeNewHeads(chan1) - - go func() { // simulate client - i1, i2 := 0, 0 - for i1 != len(chainEvents) || i2 != len(chainEvents) { - select { - case header := <-chan0: - if chainEvents[i1].Hash != header.Hash() { - t.Errorf("sub0 received invalid hash on index %d, want %x, got %x", i1, chainEvents[i1].Hash, header.Hash()) - } - i1++ - case header := <-chan1: - if chainEvents[i2].Hash != header.Hash() { - t.Errorf("sub1 received invalid hash on index %d, want %x, got %x", i2, chainEvents[i2].Hash, header.Hash()) - } - i2++ - } - } - - sub0.Unsubscribe() - sub1.Unsubscribe() - }() - - time.Sleep(1 * time.Second) - for _, e := range chainEvents { - backend.chainFeed.Send(e) - } - - <-sub0.Err() - <-sub1.Err() -} - -// TestPendingTxFilter tests whether pending tx filters retrieve all pending transactions that are posted to the event mux. -func TestPendingTxFilter(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - - transactions = []*types.Transaction{ - types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - } - - hashes []common.Hash - ) - - fid0 := api.NewPendingTransactionFilter(nil) - - time.Sleep(1 * time.Second) - backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) - - timeout := time.Now().Add(1 * time.Second) - for { - results, err := api.GetFilterChanges(fid0) - if err != nil { - t.Fatalf("Unable to retrieve logs: %v", err) - } - - h := results.([]common.Hash) - hashes = append(hashes, h...) - if len(hashes) >= len(transactions) { - break - } - // check timeout - if time.Now().After(timeout) { - break - } - - time.Sleep(100 * time.Millisecond) - } - - if len(hashes) != len(transactions) { - t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes)) - return - } - for i := range hashes { - if hashes[i] != transactions[i].Hash() { - t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i]) - } - } -} - -// TestPendingTxFilterFullTx tests whether pending tx filters retrieve all pending transactions that are posted to the event mux. -func TestPendingTxFilterFullTx(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - - transactions = []*types.Transaction{ - types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), - } - - txs []*ethapi.RPCTransaction - ) - - fullTx := true - fid0 := api.NewPendingTransactionFilter(&fullTx) - - time.Sleep(1 * time.Second) - backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) - - timeout := time.Now().Add(1 * time.Second) - for { - results, err := api.GetFilterChanges(fid0) - if err != nil { - t.Fatalf("Unable to retrieve logs: %v", err) - } - - tx := results.([]*ethapi.RPCTransaction) - txs = append(txs, tx...) - if len(txs) >= len(transactions) { - break - } - // check timeout - if time.Now().After(timeout) { - break - } - - time.Sleep(100 * time.Millisecond) - } - - if len(txs) != len(transactions) { - t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(txs)) - return - } - for i := range txs { - if txs[i].Hash != transactions[i].Hash() { - t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash) - } - } -} - -// TestLogFilterCreation test whether a given filter criteria makes sense. -// If not it must return an error. -func TestLogFilterCreation(t *testing.T) { - var ( - db = rawdb.NewMemoryDatabase() - _, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - - testCases = []struct { - crit FilterCriteria - success bool - }{ - // defaults - {FilterCriteria{}, true}, - // valid block number range - {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, true}, - // "mined" block range to pending - {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, true}, - // new mined and pending blocks - {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, true}, - // from block "higher" than to block - {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}, false}, - // from block "higher" than to block - {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false}, - // from block "higher" than to block - {FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false}, - // from block "higher" than to block - {FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false}, - // topics more then 4 - {FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false}, - } - ) - - for i, test := range testCases { - id, err := api.NewFilter(test.crit) - if err != nil && test.success { - t.Errorf("expected filter creation for case %d to success, got %v", i, err) - } - if err == nil { - api.UninstallFilter(id) - if !test.success { - t.Errorf("expected testcase %d to fail with an error", i) - } - } - } -} - -// TestInvalidLogFilterCreation tests whether invalid filter log criteria results in an error -// when the filter is created. -func TestInvalidLogFilterCreation(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - _, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - ) - - // different situations where log filter creation should fail. - // Reason: fromBlock > toBlock - testCases := []FilterCriteria{ - 0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, - 1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, - 2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)}, - 3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, - } - - for i, test := range testCases { - if _, err := api.NewFilter(test); err == nil { - t.Errorf("Expected NewFilter for case #%d to fail", i) - } - } -} - -// TestLogFilterUninstall tests invalid getLogs requests -func TestInvalidGetLogsRequest(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - _, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - ) - - // Reason: Cannot specify both BlockHash and FromBlock/ToBlock) - testCases := []FilterCriteria{ - 0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)}, - 1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)}, - 2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, - 3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, - } - - for i, test := range testCases { - if _, err := api.GetLogs(context.Background(), test); err == nil { - t.Errorf("Expected Logs for case #%d to fail", i) - } - } -} - -// TestInvalidGetRangeLogsRequest tests getLogs with invalid block range -func TestInvalidGetRangeLogsRequest(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - _, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - ) - - if _, err := api.GetLogs(context.Background(), FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}); err != errInvalidBlockRange { - t.Errorf("Expected Logs for invalid range return error, but got: %v", err) - } -} - -// TestLogFilter tests whether log filters match the correct logs that are posted to the event feed. -func TestLogFilter(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - - firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") - secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222") - thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333") - notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999") - firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222") - notUsedTopic = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999") - - // posted twice, once as regular logs and once as pending logs. - allLogs = []*types.Log{ - {Address: firstAddr}, - {Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}, - {Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}, - {Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 2}, - {Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3}, - } - - expectedCase7 = []*types.Log{allLogs[3], allLogs[4], allLogs[0], allLogs[1], allLogs[2], allLogs[3], allLogs[4]} - expectedCase11 = []*types.Log{allLogs[1], allLogs[2], allLogs[1], allLogs[2]} - - testCases = []struct { - crit FilterCriteria - expected []*types.Log - id rpc.ID - }{ - // match all - 0: {FilterCriteria{}, allLogs, ""}, - // match none due to no matching addresses - 1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""}, - // match logs based on addresses, ignore topics - 2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""}, - // match none due to no matching topics (match with address) - 3: {FilterCriteria{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, ""}, - // match logs based on addresses and topics - 4: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""}, - // match logs based on multiple addresses and "or" topics - 5: {FilterCriteria{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[2:5], ""}, - // logs in the pending block - 6: {FilterCriteria{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, allLogs[:2], ""}, - // mined logs with block num >= 2 or pending logs - 7: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, expectedCase7, ""}, - // all "mined" logs with block num >= 2 - 8: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs[3:], ""}, - // all "mined" logs - 9: {FilterCriteria{ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs, ""}, - // all "mined" logs with 1>= block num <=2 and topic secondTopic - 10: {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""}, - // all "mined" and pending logs with topic firstTopic - 11: {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), Topics: [][]common.Hash{{firstTopic}}}, expectedCase11, ""}, - // match all logs due to wildcard topic - 12: {FilterCriteria{Topics: [][]common.Hash{nil}}, allLogs[1:], ""}, - } - ) - - // create all filters - for i := range testCases { - testCases[i].id, _ = api.NewFilter(testCases[i].crit) - } - - // raise events - time.Sleep(1 * time.Second) - if nsend := backend.logsFeed.Send(allLogs); nsend == 0 { - t.Fatal("Logs event not delivered") - } - if nsend := backend.pendingLogsFeed.Send(allLogs); nsend == 0 { - t.Fatal("Pending logs event not delivered") - } - - for i, tt := range testCases { - var fetched []*types.Log - timeout := time.Now().Add(1 * time.Second) - for { // fetch all expected logs - results, err := api.GetFilterChanges(tt.id) - if err != nil { - t.Fatalf("Unable to fetch logs: %v", err) - } - - fetched = append(fetched, results.([]*types.Log)...) - if len(fetched) >= len(tt.expected) { - break - } - // check timeout - if time.Now().After(timeout) { - break - } - - time.Sleep(100 * time.Millisecond) - } - - if len(fetched) != len(tt.expected) { - t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)) - return - } - - for l := range fetched { - if fetched[l].Removed { - t.Errorf("expected log not to be removed for log %d in case %d", l, i) - } - if !reflect.DeepEqual(fetched[l], tt.expected[l]) { - t.Errorf("invalid log on index %d for case %d", l, i) - } - } - } -} - -// TestPendingLogsSubscription tests if a subscription receives the correct pending logs that are posted to the event feed. -func TestPendingLogsSubscription(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, false) - - firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") - secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222") - thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333") - notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999") - firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222") - thirdTopic = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333") - fourthTopic = common.HexToHash("0x4444444444444444444444444444444444444444444444444444444444444444") - notUsedTopic = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999") - - allLogs = [][]*types.Log{ - {{Address: firstAddr, Topics: []common.Hash{}, BlockNumber: 0}}, - {{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}}, - {{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 2}}, - {{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3}}, - {{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 4}}, - { - {Address: thirdAddress, Topics: []common.Hash{firstTopic}, BlockNumber: 5}, - {Address: thirdAddress, Topics: []common.Hash{thirdTopic}, BlockNumber: 5}, - {Address: thirdAddress, Topics: []common.Hash{fourthTopic}, BlockNumber: 5}, - {Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 5}, - }, - } - - pendingBlockNumber = big.NewInt(rpc.PendingBlockNumber.Int64()) - - testCases = []struct { - crit ethereum.FilterQuery - expected []*types.Log - c chan []*types.Log - sub *Subscription - err chan error - }{ - // match all - { - ethereum.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - flattenLogs(allLogs), - nil, nil, nil, - }, - // match none due to no matching addresses - { - ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - nil, - nil, nil, nil, - }, - // match logs based on addresses, ignore topics - { - ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - append(flattenLogs(allLogs[:2]), allLogs[5][3]), - nil, nil, nil, - }, - // match none due to no matching topics (match with address) - { - ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - nil, - nil, nil, nil, - }, - // match logs based on addresses and topics - { - ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - append(flattenLogs(allLogs[3:5]), allLogs[5][0]), - nil, nil, nil, - }, - // match logs based on multiple addresses and "or" topics - { - ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - append(flattenLogs(allLogs[2:5]), allLogs[5][0]), - nil, nil, nil, - }, - // multiple pending logs, should match only 2 topics from the logs in block 5 - { - ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber}, - []*types.Log{allLogs[5][0], allLogs[5][2]}, - nil, nil, nil, - }, - // match none due to only matching new mined logs - { - ethereum.FilterQuery{}, - nil, - nil, nil, nil, - }, - // match none due to only matching mined logs within a specific block range - { - ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, - nil, - nil, nil, nil, - }, - // match all due to matching mined and pending logs - { - ethereum.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, - flattenLogs(allLogs), - nil, nil, nil, - }, - // match none due to matching logs from a specific block number to new mined blocks - { - ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, - nil, - nil, nil, nil, - }, - } - ) - - // create all subscriptions, this ensures all subscriptions are created before the events are posted. - // on slow machines this could otherwise lead to missing events when the subscription is created after - // (some) events are posted. - for i := range testCases { - testCases[i].c = make(chan []*types.Log) - testCases[i].err = make(chan error, 1) - - var err error - testCases[i].sub, err = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c) - if err != nil { - t.Fatalf("SubscribeLogs %d failed: %v\n", i, err) - } - } - - for n, test := range testCases { - i := n - tt := test - go func() { - defer tt.sub.Unsubscribe() - - var fetched []*types.Log - - timeout := time.After(1 * time.Second) - fetchLoop: - for { - select { - case logs := <-tt.c: - // Do not break early if we've fetched greater, or equal, - // to the number of logs expected. This ensures we do not - // deadlock the filter system because it will do a blocking - // send on this channel if another log arrives. - fetched = append(fetched, logs...) - case <-timeout: - break fetchLoop - } - } - - if len(fetched) != len(tt.expected) { - tt.err <- fmt.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)) - return - } - - for l := range fetched { - if fetched[l].Removed { - tt.err <- fmt.Errorf("expected log not to be removed for log %d in case %d", l, i) - return - } - if !reflect.DeepEqual(fetched[l], tt.expected[l]) { - tt.err <- fmt.Errorf("invalid log on index %d for case %d\n", l, i) - return - } - } - tt.err <- nil - }() - } - - // raise events - for _, ev := range allLogs { - backend.pendingLogsFeed.Send(ev) - } - - for i := range testCases { - err := <-testCases[i].err - if err != nil { - t.Fatalf("test %d failed: %v", i, err) - } - <-testCases[i].sub.Err() - } -} - -func TestLightFilterLogs(t *testing.T) { - t.Parallel() - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{}) - api = NewFilterAPI(sys, true) - signer = types.HomesteadSigner{} - - firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") - secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222") - thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333") - notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999") - firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222") - - // posted twice, once as regular logs and once as pending logs. - allLogs = []*types.Log{ - // Block 1 - {Address: firstAddr, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: 2, Index: 0}, - // Block 2 - {Address: firstAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 0}, - {Address: secondAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 1}, - {Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 3, Index: 2}, - // Block 3 - {Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 4, Index: 0}, - } - - testCases = []struct { - crit FilterCriteria - expected []*types.Log - id rpc.ID - }{ - // match all - 0: {FilterCriteria{}, allLogs, ""}, - // match none due to no matching addresses - 1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""}, - // match logs based on addresses, ignore topics - 2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""}, - // match logs based on addresses and topics - 3: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""}, - // all logs with block num >= 3 - 4: {FilterCriteria{FromBlock: big.NewInt(3), ToBlock: big.NewInt(5)}, allLogs[1:], ""}, - // all logs - 5: {FilterCriteria{FromBlock: big.NewInt(0), ToBlock: big.NewInt(5)}, allLogs, ""}, - // all logs with 1>= block num <=2 and topic secondTopic - 6: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(3), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""}, - } - - key, _ = crypto.GenerateKey() - addr = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - addr: {Balance: big.NewInt(params.Ether)}, - }, - } - receipts = []*types.Receipt{{ - Logs: []*types.Log{allLogs[0]}, - }, { - Logs: []*types.Log{allLogs[1], allLogs[2], allLogs[3]}, - }, { - Logs: []*types.Log{allLogs[4]}, - }} - ) - - _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 4, func(i int, b *core.BlockGen) { - if i == 0 { - return - } - receipts[i-1].Bloom = types.CreateBloom(types.Receipts{receipts[i-1]}) - b.AddUncheckedReceipt(receipts[i-1]) - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i - 1), To: &common.Address{}, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, key) - b.AddTx(tx) - }) - for i, block := range blocks { - rawdb.WriteBlock(db, block) - rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) - rawdb.WriteHeadBlockHash(db, block.Hash()) - if i > 0 { - rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), []*types.Receipt{receipts[i-1]}) - } - } - // create all filters - for i := range testCases { - id, err := api.NewFilter(testCases[i].crit) - if err != nil { - t.Fatal(err) - } - testCases[i].id = id - } - - // raise events - time.Sleep(1 * time.Second) - for _, block := range blocks { - backend.chainFeed.Send(core.ChainEvent{Block: block, Hash: common.Hash{}, Logs: allLogs}) - } - - for i, tt := range testCases { - var fetched []*types.Log - timeout := time.Now().Add(1 * time.Second) - for { // fetch all expected logs - results, err := api.GetFilterChanges(tt.id) - if err != nil { - t.Fatalf("Unable to fetch logs: %v", err) - } - fetched = append(fetched, results.([]*types.Log)...) - if len(fetched) >= len(tt.expected) { - break - } - // check timeout - if time.Now().After(timeout) { - break - } - - time.Sleep(100 * time.Millisecond) - } - - if len(fetched) != len(tt.expected) { - t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)) - return - } - - for l := range fetched { - if fetched[l].Removed { - t.Errorf("expected log not to be removed for log %d in case %d", l, i) - } - expected := *tt.expected[l] - blockNum := expected.BlockNumber - 1 - expected.BlockHash = blocks[blockNum].Hash() - expected.TxHash = blocks[blockNum].Transactions()[0].Hash() - if !reflect.DeepEqual(fetched[l], &expected) { - t.Errorf("invalid log on index %d for case %d", l, i) - } - } - } -} - -// TestPendingTxFilterDeadlock tests if the event loop hangs when pending -// txes arrive at the same time that one of multiple filters is timing out. -// Please refer to #22131 for more details. -func TestPendingTxFilterDeadlock(t *testing.T) { - t.Parallel() - timeout := 100 * time.Millisecond - - var ( - db = rawdb.NewMemoryDatabase() - backend, sys = newTestFilterSystem(t, db, Config{Timeout: timeout}) - api = NewFilterAPI(sys, false) - done = make(chan struct{}) - ) - - go func() { - // Bombard feed with txes until signal was received to stop - i := uint64(0) - for { - select { - case <-done: - return - default: - } - - tx := types.NewTransaction(i, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil) - backend.txFeed.Send(core.NewTxsEvent{Txs: []*types.Transaction{tx}}) - i++ - } - }() - - // Create a bunch of filters that will - // timeout either in 100ms or 200ms - subs := make([]*Subscription, 20) - for i := 0; i < len(subs); i++ { - fid := api.NewPendingTransactionFilter(nil) - f, ok := api.filters[fid] - if !ok { - t.Fatalf("Filter %s should exist", fid) - } - subs[i] = f.s - // Wait for at least one tx to arrive in filter - for { - hashes, err := api.GetFilterChanges(fid) - if err != nil { - t.Fatalf("Filter should exist: %v\n", err) - } - if len(hashes.([]common.Hash)) > 0 { - break - } - runtime.Gosched() - } - } - - // Wait until filters have timed out and have been uninstalled. - for _, sub := range subs { - select { - case <-sub.Err(): - case <-time.After(1 * time.Second): - t.Fatalf("Filter timeout is hanging") - } - } -} - -func flattenLogs(pl [][]*types.Log) []*types.Log { - var logs []*types.Log - for _, l := range pl { - logs = append(logs, l...) - } - return logs -} diff --git a/builder/eth/filters/filter_test.go b/builder/eth/filters/filter_test.go deleted file mode 100644 index 659ca5ce1..000000000 --- a/builder/eth/filters/filter_test.go +++ /dev/null @@ -1,390 +0,0 @@ -// 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 filters - -import ( - "context" - "encoding/json" - "math/big" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/triedb" -) - -func makeReceipt(addr common.Address) *types.Receipt { - receipt := types.NewReceipt(nil, false, 0) - receipt.Logs = []*types.Log{ - {Address: addr}, - } - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - return receipt -} - -func BenchmarkFilters(b *testing.B) { - var ( - db, _ = rawdb.NewLevelDBDatabase(b.TempDir(), 0, 0, "", false) - _, sys = newTestFilterSystem(b, db, Config{}) - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr1 = crypto.PubkeyToAddress(key1.PublicKey) - addr2 = common.BytesToAddress([]byte("jeff")) - addr3 = common.BytesToAddress([]byte("ethereum")) - addr4 = common.BytesToAddress([]byte("random addresses please")) - - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, - BaseFee: big.NewInt(params.InitialBaseFee), - Config: params.TestChainConfig, - } - ) - defer db.Close() - _, chain, receipts := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 100010, func(i int, gen *core.BlockGen) { - switch i { - case 2403: - receipt := makeReceipt(addr1) - gen.AddUncheckedReceipt(receipt) - gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) - case 1034: - receipt := makeReceipt(addr2) - gen.AddUncheckedReceipt(receipt) - gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) - case 34: - receipt := makeReceipt(addr3) - gen.AddUncheckedReceipt(receipt) - gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) - case 99999: - receipt := makeReceipt(addr4) - gen.AddUncheckedReceipt(receipt) - gen.AddUncheckedTx(types.NewTransaction(999, common.HexToAddress("0x999"), big.NewInt(999), 999, gen.BaseFee(), nil)) - } - }) - // The test txs are not properly signed, can't simply create a chain - // and then import blocks. TODO(rjl493456442) try to get rid of the - // manual database writes. - gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults)) - - for i, block := range chain { - rawdb.WriteBlock(db, block) - rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) - rawdb.WriteHeadBlockHash(db, block.Hash()) - rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), receipts[i]) - } - b.ResetTimer() - - filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil) - - for i := 0; i < b.N; i++ { - filter.begin = 0 - logs, _ := filter.Logs(context.Background()) - if len(logs) != 4 { - b.Fatal("expected 4 logs, got", len(logs)) - } - } -} - -func TestFilters(t *testing.T) { - var ( - db = rawdb.NewMemoryDatabase() - _, sys = newTestFilterSystem(t, db, Config{}) - // Sender account - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key1.PublicKey) - signer = types.NewLondonSigner(big.NewInt(1)) - // Logging contract - contract = common.Address{0xfe} - contract2 = common.Address{0xff} - abiStr = `[{"inputs":[],"name":"log0","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"}],"name":"log1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"}],"name":"log2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"}],"name":"log3","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"t1","type":"uint256"},{"internalType":"uint256","name":"t2","type":"uint256"},{"internalType":"uint256","name":"t3","type":"uint256"},{"internalType":"uint256","name":"t4","type":"uint256"}],"name":"log4","outputs":[],"stateMutability":"nonpayable","type":"function"}]` - /* - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.0 <0.9.0; - - contract Logger { - function log0() external { - assembly { - log0(0, 0) - } - } - - function log1(uint t1) external { - assembly { - log1(0, 0, t1) - } - } - - function log2(uint t1, uint t2) external { - assembly { - log2(0, 0, t1, t2) - } - } - - function log3(uint t1, uint t2, uint t3) external { - assembly { - log3(0, 0, t1, t2, t3) - } - } - - function log4(uint t1, uint t2, uint t3, uint t4) external { - assembly { - log4(0, 0, t1, t2, t3, t4) - } - } - } - */ - bytecode = common.FromHex("608060405234801561001057600080fd5b50600436106100575760003560e01c80630aa731851461005c5780632a4c08961461006657806378b9a1f314610082578063c670f8641461009e578063c683d6a3146100ba575b600080fd5b6100646100d6565b005b610080600480360381019061007b9190610143565b6100dc565b005b61009c60048036038101906100979190610196565b6100e8565b005b6100b860048036038101906100b391906101d6565b6100f2565b005b6100d460048036038101906100cf9190610203565b6100fa565b005b600080a0565b808284600080a3505050565b8082600080a25050565b80600080a150565b80828486600080a450505050565b600080fd5b6000819050919050565b6101208161010d565b811461012b57600080fd5b50565b60008135905061013d81610117565b92915050565b60008060006060848603121561015c5761015b610108565b5b600061016a8682870161012e565b935050602061017b8682870161012e565b925050604061018c8682870161012e565b9150509250925092565b600080604083850312156101ad576101ac610108565b5b60006101bb8582860161012e565b92505060206101cc8582860161012e565b9150509250929050565b6000602082840312156101ec576101eb610108565b5b60006101fa8482850161012e565b91505092915050565b6000806000806080858703121561021d5761021c610108565b5b600061022b8782880161012e565b945050602061023c8782880161012e565b935050604061024d8782880161012e565b925050606061025e8782880161012e565b9150509295919450925056fea264697066735822122073a4b156f487e59970dc1ef449cc0d51467268f676033a17188edafcee861f9864736f6c63430008110033") - - hash1 = common.BytesToHash([]byte("topic1")) - hash2 = common.BytesToHash([]byte("topic2")) - hash3 = common.BytesToHash([]byte("topic3")) - hash4 = common.BytesToHash([]byte("topic4")) - hash5 = common.BytesToHash([]byte("topic5")) - - gspec = &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - addr: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))}, - contract: {Balance: big.NewInt(0), Code: bytecode}, - contract2: {Balance: big.NewInt(0), Code: bytecode}, - }, - BaseFee: big.NewInt(params.InitialBaseFee), - } - ) - - contractABI, err := abi.JSON(strings.NewReader(abiStr)) - if err != nil { - t.Fatal(err) - } - - // Hack: GenerateChainWithGenesis creates a new db. - // Commit the genesis manually and use GenerateChain. - _, err = gspec.Commit(db, triedb.NewDatabase(db, nil)) - if err != nil { - t.Fatal(err) - } - chain, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { - switch i { - case 1: - data, err := contractABI.Pack("log1", hash1.Big()) - if err != nil { - t.Fatal(err) - } - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 0, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract, - Data: data, - }), signer, key1) - gen.AddTx(tx) - tx2, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 1, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract2, - Data: data, - }), signer, key1) - gen.AddTx(tx2) - case 2: - data, err := contractABI.Pack("log2", hash2.Big(), hash1.Big()) - if err != nil { - t.Fatal(err) - } - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 2, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract, - Data: data, - }), signer, key1) - gen.AddTx(tx) - case 998: - data, err := contractABI.Pack("log1", hash3.Big()) - if err != nil { - t.Fatal(err) - } - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 3, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract2, - Data: data, - }), signer, key1) - gen.AddTx(tx) - case 999: - data, err := contractABI.Pack("log1", hash4.Big()) - if err != nil { - t.Fatal(err) - } - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 4, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract, - Data: data, - }), signer, key1) - gen.AddTx(tx) - } - }) - var l uint64 - bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l) - if err != nil { - t.Fatal(err) - } - _, err = bc.InsertChain(chain) - if err != nil { - t.Fatal(err) - } - - // Set block 998 as Finalized (-3) - bc.SetFinalized(chain[998].Header()) - - // Generate pending block - pchain, preceipts := core.GenerateChain(gspec.Config, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) { - data, err := contractABI.Pack("log1", hash5.Big()) - if err != nil { - t.Fatal(err) - } - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: 5, - GasPrice: gen.BaseFee(), - Gas: 30000, - To: &contract, - Data: data, - }), signer, key1) - gen.AddTx(tx) - }) - sys.backend.(*testBackend).pendingBlock = pchain[0] - sys.backend.(*testBackend).pendingReceipts = preceipts[0] - - for i, tc := range []struct { - f *Filter - want string - err string - }{ - { - f: sys.NewBlockFilter(chain[2].Hash(), []common.Address{contract}, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{contract}, [][]common.Hash{{hash1, hash2, hash3, hash4}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(900, 999, []common.Address{contract}, [][]common.Hash{{hash3}}), - }, - { - f: sys.NewRangeFilter(990, int64(rpc.LatestBlockNumber), []common.Address{contract2}, [][]common.Hash{{hash3}}), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(1, 10, []common.Address{contract}, [][]common.Hash{{hash2}, {hash1}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(1, 10, nil, [][]common.Hash{{hash1, hash2}}), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xa8028c655b6423204c8edfbc339f57b042d6bec2b6a61145d76b7c08b4cccd42","transactionIndex":"0x0","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x0","removed":false},{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x2","transactionHash":"0xdba3e2ea9a7d690b722d70ee605fd67ba4c00d1d3aecd5cf187a7b92ad8eb3df","transactionIndex":"0x1","blockHash":"0x24417bb49ce44cfad65da68f33b510bf2a129c0d89ccf06acb6958b8585ccf34","logIndex":"0x1","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696332","0x0000000000000000000000000000000000000000000000000000746f70696331"],"data":"0x","blockNumber":"0x3","transactionHash":"0xdefe471992a07a02acdfbe33edaae22fbb86d7d3cec3f1b8e4e77702fb3acc1d","transactionIndex":"0x0","blockHash":"0x7a7556792ca7d37882882e2b001fe14833eaf81c2c7f865c9c771ec37a024f6b","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}}), - }, - { - f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), []common.Address{common.BytesToAddress([]byte("failmenow"))}, nil), - }, - { - f: sys.NewRangeFilter(0, int64(rpc.LatestBlockNumber), nil, [][]common.Hash{{common.BytesToHash([]byte("fail"))}, {hash1}}), - }, - { - f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(int64(rpc.FinalizedBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), - want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), - }, - { - f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - err: "safe header not found", - }, - { - f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), - err: "safe header not found", - }, - { - f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.SafeBlockNumber), nil, nil), - err: "safe header not found", - }, - { - f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil), - want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb360bad5265261c075ece02d3bf0e39498a6a76310482cdfd90588748e6c5ee0","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0xd5e8d4e4eb51a2a2a6ec20ef68a4c2801240743c8deb77a6a1d118ac3eefb725","logIndex":"0x0","removed":false}]`, - }, - { - f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), - err: errInvalidBlockRange.Error(), - }, - } { - logs, err := tc.f.Logs(context.Background()) - if err == nil && tc.err != "" { - t.Fatalf("test %d, expected error %q, got nil", i, tc.err) - } else if err != nil && err.Error() != tc.err { - t.Fatalf("test %d, expected error %q, got %q", i, tc.err, err.Error()) - } - if tc.want == "" && len(logs) == 0 { - continue - } - have, err := json.Marshal(logs) - if err != nil { - t.Fatal(err) - } - if string(have) != tc.want { - t.Fatalf("test %d, have:\n%s\nwant:\n%s", i, have, tc.want) - } - } - - t.Run("timeout", func(t *testing.T) { - f := sys.NewRangeFilter(0, -1, nil, nil) - ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour)) - defer cancel() - _, err := f.Logs(ctx) - if err == nil { - t.Fatal("expected error") - } - if err != context.DeadlineExceeded { - t.Fatalf("expected context.DeadlineExceeded, got %v", err) - } - }) -} diff --git a/builder/eth/gasestimator/gasestimator.go b/builder/eth/gasestimator/gasestimator.go deleted file mode 100644 index f07f98956..000000000 --- a/builder/eth/gasestimator/gasestimator.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2023 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 gasestimator - -import ( - "context" - "errors" - "fmt" - "math" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" -) - -// Options are the contextual parameters to execute the requested call. -// -// Whilst it would be possible to pass a blockchain object that aggregates all -// these together, it would be excessively hard to test. Splitting the parts out -// allows testing without needing a proper live chain. -type Options struct { - Config *params.ChainConfig // Chain configuration for hard fork selection - Chain core.ChainContext // Chain context to access past block hashes - Header *types.Header // Header defining the block context to execute in - State *state.StateDB // Pre-state on top of which to estimate the gas - - ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination -} - -// Estimate returns the lowest possible gas limit that allows the transaction to -// run successfully with the provided context options. It returns an error if the -// transaction would always revert, or if there are unexpected failures. -func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uint64) (uint64, []byte, error) { - // Binary search the gas limit, as it may need to be higher than the amount used - var ( - lo uint64 // lowest-known gas limit where tx execution fails - hi uint64 // lowest-known gas limit where tx execution succeeds - ) - // Determine the highest gas limit can be used during the estimation. - hi = opts.Header.GasLimit - if call.GasLimit >= params.TxGas { - hi = call.GasLimit - } - // Normalize the max fee per gas the call is willing to spend. - var feeCap *big.Int - if call.GasFeeCap != nil { - feeCap = call.GasFeeCap - } else if call.GasPrice != nil { - feeCap = call.GasPrice - } else { - feeCap = common.Big0 - } - // Recap the highest gas limit with account's available balance. - if feeCap.BitLen() != 0 { - balance := opts.State.GetBalance(call.From).ToBig() - - available := balance - if call.Value != nil { - if call.Value.Cmp(available) >= 0 { - return 0, nil, core.ErrInsufficientFundsForTransfer - } - available.Sub(available, call.Value) - } - allowance := new(big.Int).Div(available, feeCap) - - // If the allowance is larger than maximum uint64, skip checking - if allowance.IsUint64() && hi > allowance.Uint64() { - transfer := call.Value - if transfer == nil { - transfer = new(big.Int) - } - log.Debug("Gas estimation capped by limited funds", "original", hi, "balance", balance, - "sent", transfer, "maxFeePerGas", feeCap, "fundable", allowance) - hi = allowance.Uint64() - } - } - // Recap the highest gas allowance with specified gascap. - if gasCap != 0 && hi > gasCap { - log.Debug("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) - hi = gasCap - } - // If the transaction is a plain value transfer, short circuit estimation and - // directly try 21000. Returning 21000 without any execution is dangerous as - // some tx field combos might bump the price up even for plain transfers (e.g. - // unused access list items). Ever so slightly wasteful, but safer overall. - if len(call.Data) == 0 { - if call.To != nil && opts.State.GetCodeSize(*call.To) == 0 { - failed, _, err := execute(ctx, call, opts, params.TxGas) - if !failed && err == nil { - return params.TxGas, nil, nil - } - } - } - // We first execute the transaction at the highest allowable gas limit, since if this fails we - // can return error immediately. - failed, result, err := execute(ctx, call, opts, hi) - if err != nil { - return 0, nil, err - } - if failed { - if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) { - return 0, result.Revert(), result.Err - } - return 0, nil, fmt.Errorf("gas required exceeds allowance (%d)", hi) - } - // For almost any transaction, the gas consumed by the unconstrained execution - // above lower-bounds the gas limit required for it to succeed. One exception - // is those that explicitly check gas remaining in order to execute within a - // given limit, but we probably don't want to return the lowest possible gas - // limit for these cases anyway. - lo = result.UsedGas - 1 - - // There's a fairly high chance for the transaction to execute successfully - // with gasLimit set to the first execution's usedGas + gasRefund. Explicitly - // check that gas amount and use as a limit for the binary search. - optimisticGasLimit := (result.UsedGas + result.RefundedGas + params.CallStipend) * 64 / 63 - if optimisticGasLimit < hi { - failed, _, err = execute(ctx, call, opts, optimisticGasLimit) - if err != nil { - // This should not happen under normal conditions since if we make it this far the - // transaction had run without error at least once before. - log.Error("Execution error in estimate gas", "err", err) - return 0, nil, err - } - if failed { - lo = optimisticGasLimit - } else { - hi = optimisticGasLimit - } - } - // Binary search for the smallest gas limit that allows the tx to execute successfully. - for lo+1 < hi { - if opts.ErrorRatio > 0 { - // It is a bit pointless to return a perfect estimation, as changing - // network conditions require the caller to bump it up anyway. Since - // wallets tend to use 20-25% bump, allowing a small approximation - // error is fine (as long as it's upwards). - if float64(hi-lo)/float64(hi) < opts.ErrorRatio { - break - } - } - mid := (hi + lo) / 2 - if mid > lo*2 { - // Most txs don't need much higher gas limit than their gas used, and most txs don't - // require near the full block limit of gas, so the selection of where to bisect the - // range here is skewed to favor the low side. - mid = lo * 2 - } - failed, _, err = execute(ctx, call, opts, mid) - if err != nil { - // This should not happen under normal conditions since if we make it this far the - // transaction had run without error at least once before. - log.Error("Execution error in estimate gas", "err", err) - return 0, nil, err - } - if failed { - lo = mid - } else { - hi = mid - } - } - return hi, nil, nil -} - -// execute is a helper that executes the transaction under a given gas limit and -// returns true if the transaction fails for a reason that might be related to -// not enough gas. A non-nil error means execution failed due to reasons unrelated -// to the gas limit. -func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64) (bool, *core.ExecutionResult, error) { - // Configure the call for this specific execution (and revert the change after) - defer func(gas uint64) { call.GasLimit = gas }(call.GasLimit) - call.GasLimit = gasLimit - - // Execute the call and separate execution faults caused by a lack of gas or - // other non-fixable conditions - result, err := run(ctx, call, opts) - if err != nil { - if errors.Is(err, core.ErrIntrinsicGas) { - return true, nil, nil // Special case, raise gas limit - } - return true, nil, err // Bail out - } - return result.Failed(), result, nil -} - -// run assembles the EVM as defined by the consensus rules and runs the requested -// call invocation. -func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) { - // Assemble the call and the call context - var ( - msgContext = core.NewEVMTxContext(call) - evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil) - - dirtyState = opts.State.Copy() - evm = vm.NewEVM(evmContext, msgContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true}) - ) - // Monitor the outer context and interrupt the EVM upon cancellation. To avoid - // a dangling goroutine until the outer estimation finishes, create an internal - // context for the lifetime of this method call. - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - go func() { - <-ctx.Done() - evm.Cancel() - }() - // Execute the call, returning a wrapped error or the result - result, err := core.ApplyMessage(evm, call, new(core.GasPool).AddGas(math.MaxUint64)) - if vmerr := dirtyState.Error(); vmerr != nil { - return nil, vmerr - } - if err != nil { - return result, fmt.Errorf("failed with %d gas: %w", call.GasLimit, err) - } - return result, nil -} diff --git a/builder/eth/gasprice/feehistory.go b/builder/eth/gasprice/feehistory.go deleted file mode 100644 index d657eb6d9..000000000 --- a/builder/eth/gasprice/feehistory.go +++ /dev/null @@ -1,328 +0,0 @@ -// 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 gasprice - -import ( - "context" - "encoding/binary" - "errors" - "fmt" - "math" - "math/big" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" - "golang.org/x/exp/slices" -) - -var ( - errInvalidPercentile = errors.New("invalid reward percentile") - errRequestBeyondHead = errors.New("request beyond head block") -) - -const ( - // maxBlockFetchers is the max number of goroutines to spin up to pull blocks - // for the fee history calculation (mostly relevant for LES). - maxBlockFetchers = 4 -) - -// blockFees represents a single block for processing -type blockFees struct { - // set by the caller - blockNumber uint64 - header *types.Header - block *types.Block // only set if reward percentiles are requested - receipts types.Receipts - // filled by processBlock - results processedFees - err error -} - -type cacheKey struct { - number uint64 - percentiles string -} - -// processedFees contains the results of a processed block. -type processedFees struct { - reward []*big.Int - baseFee, nextBaseFee *big.Int - gasUsedRatio float64 -} - -// txGasAndReward is sorted in ascending order based on reward -type txGasAndReward struct { - gasUsed uint64 - reward *big.Int -} - -// processBlock takes a blockFees structure with the blockNumber, the header and optionally -// the block field filled in, retrieves the block from the backend if not present yet and -// fills in the rest of the fields. -func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) { - chainconfig := oracle.backend.ChainConfig() - if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil { - bf.results.baseFee = new(big.Int) - } - if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) { - bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header) - } else { - bf.results.nextBaseFee = new(big.Int) - } - bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit) - if len(percentiles) == 0 { - // rewards were not requested, return null - return - } - if bf.block == nil || (bf.receipts == nil && len(bf.block.Transactions()) != 0) { - log.Error("Block or receipts are missing while reward percentiles are requested") - return - } - - bf.results.reward = make([]*big.Int, len(percentiles)) - if len(bf.block.Transactions()) == 0 { - // return an all zero row if there are no transactions to gather data from - for i := range bf.results.reward { - bf.results.reward[i] = new(big.Int) - } - return - } - - sorter := make([]txGasAndReward, len(bf.block.Transactions())) - for i, tx := range bf.block.Transactions() { - reward, _ := tx.EffectiveGasTip(bf.block.BaseFee()) - sorter[i] = txGasAndReward{gasUsed: bf.receipts[i].GasUsed, reward: reward} - } - slices.SortStableFunc(sorter, func(a, b txGasAndReward) int { - return a.reward.Cmp(b.reward) - }) - - var txIndex int - sumGasUsed := sorter[0].gasUsed - - for i, p := range percentiles { - thresholdGasUsed := uint64(float64(bf.block.GasUsed()) * p / 100) - for sumGasUsed < thresholdGasUsed && txIndex < len(bf.block.Transactions())-1 { - txIndex++ - sumGasUsed += sorter[txIndex].gasUsed - } - bf.results.reward[i] = sorter[txIndex].reward - } -} - -// resolveBlockRange resolves the specified block range to absolute block numbers while also -// enforcing backend specific limitations. The pending block and corresponding receipts are -// also returned if requested and available. -// Note: an error is only returned if retrieving the head header has failed. If there are no -// retrievable blocks in the specified range then zero block count is returned with no error. -func (oracle *Oracle) resolveBlockRange(ctx context.Context, reqEnd rpc.BlockNumber, blocks uint64) (*types.Block, []*types.Receipt, uint64, uint64, error) { - var ( - headBlock *types.Header - pendingBlock *types.Block - pendingReceipts types.Receipts - err error - ) - - // Get the chain's current head. - if headBlock, err = oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err != nil { - return nil, nil, 0, 0, err - } - head := rpc.BlockNumber(headBlock.Number.Uint64()) - - // Fail if request block is beyond the chain's current head. - if head < reqEnd { - return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, reqEnd, head) - } - - // Resolve block tag. - if reqEnd < 0 { - var ( - resolved *types.Header - err error - ) - switch reqEnd { - case rpc.PendingBlockNumber: - if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil { - resolved = pendingBlock.Header() - } else { - // Pending block not supported by backend, process only until latest block. - resolved = headBlock - - // Update total blocks to return to account for this. - blocks-- - } - case rpc.LatestBlockNumber: - // Retrieved above. - resolved = headBlock - case rpc.SafeBlockNumber: - resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber) - case rpc.FinalizedBlockNumber: - resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber) - case rpc.EarliestBlockNumber: - resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.EarliestBlockNumber) - } - if resolved == nil || err != nil { - return nil, nil, 0, 0, err - } - // Absolute number resolved. - reqEnd = rpc.BlockNumber(resolved.Number.Uint64()) - } - - // If there are no blocks to return, short circuit. - if blocks == 0 { - return nil, nil, 0, 0, nil - } - // Ensure not trying to retrieve before genesis. - if uint64(reqEnd+1) < blocks { - blocks = uint64(reqEnd + 1) - } - return pendingBlock, pendingReceipts, uint64(reqEnd), blocks, nil -} - -// FeeHistory returns data relevant for fee estimation based on the specified range of blocks. -// The range can be specified either with absolute block numbers or ending with the latest -// or pending block. Backends may or may not support gathering data from the pending block -// or blocks older than a certain age (specified in maxHistory). The first block of the -// actually processed range is returned to avoid ambiguity when parts of the requested range -// are not available or when the head has changed during processing this request. -// Three arrays are returned based on the processed blocks: -// - reward: the requested percentiles of effective priority fees per gas of transactions in each -// block, sorted in ascending order and weighted by gas used. -// - baseFee: base fee per gas in the given block -// - gasUsedRatio: gasUsed/gasLimit in the given block -// -// Note: baseFee includes the next block after the newest of the returned range, because this -// value can be derived from the newest block. -func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedLastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) { - if blocks < 1 { - return common.Big0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks - } - maxFeeHistory := oracle.maxHeaderHistory - if len(rewardPercentiles) != 0 { - maxFeeHistory = oracle.maxBlockHistory - } - if blocks > maxFeeHistory { - log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory) - blocks = maxFeeHistory - } - for i, p := range rewardPercentiles { - if p < 0 || p > 100 { - return common.Big0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p) - } - if i > 0 && p <= rewardPercentiles[i-1] { - return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f >= #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p) - } - } - var ( - pendingBlock *types.Block - pendingReceipts []*types.Receipt - err error - ) - pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks) - if err != nil || blocks == 0 { - return common.Big0, nil, nil, nil, err - } - oldestBlock := lastBlock + 1 - blocks - - var next atomic.Uint64 - next.Store(oldestBlock) - results := make(chan *blockFees, blocks) - - percentileKey := make([]byte, 8*len(rewardPercentiles)) - for i, p := range rewardPercentiles { - binary.LittleEndian.PutUint64(percentileKey[i*8:(i+1)*8], math.Float64bits(p)) - } - for i := 0; i < maxBlockFetchers && i < int(blocks); i++ { - go func() { - for { - // Retrieve the next block number to fetch with this goroutine - blockNumber := next.Add(1) - 1 - if blockNumber > lastBlock { - return - } - - fees := &blockFees{blockNumber: blockNumber} - if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() { - fees.block, fees.receipts = pendingBlock, pendingReceipts - fees.header = fees.block.Header() - oracle.processBlock(fees, rewardPercentiles) - results <- fees - } else { - cacheKey := cacheKey{number: blockNumber, percentiles: string(percentileKey)} - - if p, ok := oracle.historyCache.Get(cacheKey); ok { - fees.results = p - results <- fees - } else { - if len(rewardPercentiles) != 0 { - fees.block, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber)) - if fees.block != nil && fees.err == nil { - fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash()) - fees.header = fees.block.Header() - } - } else { - fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber)) - } - if fees.header != nil && fees.err == nil { - oracle.processBlock(fees, rewardPercentiles) - if fees.err == nil { - oracle.historyCache.Add(cacheKey, fees.results) - } - } - // send to results even if empty to guarantee that blocks items are sent in total - results <- fees - } - } - } - }() - } - var ( - reward = make([][]*big.Int, blocks) - baseFee = make([]*big.Int, blocks+1) - gasUsedRatio = make([]float64, blocks) - firstMissing = blocks - ) - for ; blocks > 0; blocks-- { - fees := <-results - if fees.err != nil { - return common.Big0, nil, nil, nil, fees.err - } - i := fees.blockNumber - oldestBlock - if fees.results.baseFee != nil { - reward[i], baseFee[i], baseFee[i+1], gasUsedRatio[i] = fees.results.reward, fees.results.baseFee, fees.results.nextBaseFee, fees.results.gasUsedRatio - } else { - // getting no block and no error means we are requesting into the future (might happen because of a reorg) - if i < firstMissing { - firstMissing = i - } - } - } - if firstMissing == 0 { - return common.Big0, nil, nil, nil, nil - } - if len(rewardPercentiles) != 0 { - reward = reward[:firstMissing] - } else { - reward = nil - } - baseFee, gasUsedRatio = baseFee[:firstMissing+1], gasUsedRatio[:firstMissing] - return new(big.Int).SetUint64(oldestBlock), reward, baseFee, gasUsedRatio, nil -} diff --git a/builder/eth/gasprice/feehistory_test.go b/builder/eth/gasprice/feehistory_test.go deleted file mode 100644 index 1bcfb287a..000000000 --- a/builder/eth/gasprice/feehistory_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 gasprice - -import ( - "context" - "errors" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/rpc" -) - -func TestFeeHistory(t *testing.T) { - var cases = []struct { - pending bool - maxHeader, maxBlock uint64 - count uint64 - last rpc.BlockNumber - percent []float64 - expFirst uint64 - expCount int - expErr error - }{ - {false, 1000, 1000, 10, 30, nil, 21, 10, nil}, - {false, 1000, 1000, 10, 30, []float64{0, 10}, 21, 10, nil}, - {false, 1000, 1000, 10, 30, []float64{20, 10}, 0, 0, errInvalidPercentile}, - {false, 1000, 1000, 1000000000, 30, nil, 0, 31, nil}, - {false, 1000, 1000, 1000000000, rpc.LatestBlockNumber, nil, 0, 33, nil}, - {false, 1000, 1000, 10, 40, nil, 0, 0, errRequestBeyondHead}, - {true, 1000, 1000, 10, 40, nil, 0, 0, errRequestBeyondHead}, - {false, 20, 2, 100, rpc.LatestBlockNumber, nil, 13, 20, nil}, - {false, 20, 2, 100, rpc.LatestBlockNumber, []float64{0, 10}, 31, 2, nil}, - {false, 20, 2, 100, 32, []float64{0, 10}, 31, 2, nil}, - {false, 1000, 1000, 1, rpc.PendingBlockNumber, nil, 0, 0, nil}, - {false, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 1, nil}, - {true, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 2, nil}, - {true, 1000, 1000, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil}, - {false, 1000, 1000, 2, rpc.FinalizedBlockNumber, []float64{0, 10}, 24, 2, nil}, - {false, 1000, 1000, 2, rpc.SafeBlockNumber, []float64{0, 10}, 24, 2, nil}, - } - for i, c := range cases { - config := Config{ - MaxHeaderHistory: c.maxHeader, - MaxBlockHistory: c.maxBlock, - } - backend := newTestBackend(t, big.NewInt(16), c.pending) - oracle := NewOracle(backend, config) - - first, reward, baseFee, ratio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent) - backend.teardown() - expReward := c.expCount - if len(c.percent) == 0 { - expReward = 0 - } - expBaseFee := c.expCount - if expBaseFee != 0 { - expBaseFee++ - } - - if first.Uint64() != c.expFirst { - t.Fatalf("Test case %d: first block mismatch, want %d, got %d", i, c.expFirst, first) - } - if len(reward) != expReward { - t.Fatalf("Test case %d: reward array length mismatch, want %d, got %d", i, expReward, len(reward)) - } - if len(baseFee) != expBaseFee { - t.Fatalf("Test case %d: baseFee array length mismatch, want %d, got %d", i, expBaseFee, len(baseFee)) - } - if len(ratio) != c.expCount { - t.Fatalf("Test case %d: gasUsedRatio array length mismatch, want %d, got %d", i, c.expCount, len(ratio)) - } - if err != c.expErr && !errors.Is(err, c.expErr) { - t.Fatalf("Test case %d: error mismatch, want %v, got %v", i, c.expErr, err) - } - } -} diff --git a/builder/eth/gasprice/gasprice.go b/builder/eth/gasprice/gasprice.go deleted file mode 100644 index b71964981..000000000 --- a/builder/eth/gasprice/gasprice.go +++ /dev/null @@ -1,276 +0,0 @@ -// 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 gasprice - -import ( - "context" - "math/big" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/lru" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "golang.org/x/exp/slices" -) - -const sampleNumber = 3 // Number of transactions sampled in a block - -var ( - DefaultMaxPrice = big.NewInt(500 * params.GWei) - DefaultIgnorePrice = big.NewInt(2 * params.Wei) -) - -type Config struct { - Blocks int - Percentile int - MaxHeaderHistory uint64 - MaxBlockHistory uint64 - Default *big.Int `toml:",omitempty"` - MaxPrice *big.Int `toml:",omitempty"` - IgnorePrice *big.Int `toml:",omitempty"` -} - -// OracleBackend includes all necessary background APIs for oracle. -type OracleBackend interface { - HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) - BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) - GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) - PendingBlockAndReceipts() (*types.Block, types.Receipts) - ChainConfig() *params.ChainConfig - SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription -} - -// Oracle recommends gas prices based on the content of recent -// blocks. Suitable for both light and full clients. -type Oracle struct { - backend OracleBackend - lastHead common.Hash - lastPrice *big.Int - maxPrice *big.Int - ignorePrice *big.Int - cacheLock sync.RWMutex - fetchLock sync.Mutex - - checkBlocks, percentile int - maxHeaderHistory, maxBlockHistory uint64 - - historyCache *lru.Cache[cacheKey, processedFees] -} - -// NewOracle returns a new gasprice oracle which can recommend suitable -// gasprice for newly created transaction. -func NewOracle(backend OracleBackend, params Config) *Oracle { - blocks := params.Blocks - if blocks < 1 { - blocks = 1 - log.Warn("Sanitizing invalid gasprice oracle sample blocks", "provided", params.Blocks, "updated", blocks) - } - percent := params.Percentile - if percent < 0 { - percent = 0 - log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent) - } else if percent > 100 { - percent = 100 - log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent) - } - maxPrice := params.MaxPrice - if maxPrice == nil || maxPrice.Int64() <= 0 { - maxPrice = DefaultMaxPrice - log.Warn("Sanitizing invalid gasprice oracle price cap", "provided", params.MaxPrice, "updated", maxPrice) - } - ignorePrice := params.IgnorePrice - if ignorePrice == nil || ignorePrice.Int64() <= 0 { - ignorePrice = DefaultIgnorePrice - log.Warn("Sanitizing invalid gasprice oracle ignore price", "provided", params.IgnorePrice, "updated", ignorePrice) - } else if ignorePrice.Int64() > 0 { - log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice) - } - maxHeaderHistory := params.MaxHeaderHistory - if maxHeaderHistory < 1 { - maxHeaderHistory = 1 - log.Warn("Sanitizing invalid gasprice oracle max header history", "provided", params.MaxHeaderHistory, "updated", maxHeaderHistory) - } - maxBlockHistory := params.MaxBlockHistory - if maxBlockHistory < 1 { - maxBlockHistory = 1 - log.Warn("Sanitizing invalid gasprice oracle max block history", "provided", params.MaxBlockHistory, "updated", maxBlockHistory) - } - - cache := lru.NewCache[cacheKey, processedFees](2048) - headEvent := make(chan core.ChainHeadEvent, 1) - backend.SubscribeChainHeadEvent(headEvent) - go func() { - var lastHead common.Hash - for ev := range headEvent { - if ev.Block.ParentHash() != lastHead { - cache.Purge() - } - lastHead = ev.Block.Hash() - } - }() - - return &Oracle{ - backend: backend, - lastPrice: params.Default, - maxPrice: maxPrice, - ignorePrice: ignorePrice, - checkBlocks: blocks, - percentile: percent, - maxHeaderHistory: maxHeaderHistory, - maxBlockHistory: maxBlockHistory, - historyCache: cache, - } -} - -// SuggestTipCap returns a tip cap so that newly created transaction can have a -// very high chance to be included in the following blocks. -// -// Note, for legacy transactions and the legacy eth_gasPrice RPC call, it will be -// necessary to add the basefee to the returned number to fall back to the legacy -// behavior. -func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { - head, _ := oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber) - headHash := head.Hash() - - // If the latest gasprice is still available, return it. - oracle.cacheLock.RLock() - lastHead, lastPrice := oracle.lastHead, oracle.lastPrice - oracle.cacheLock.RUnlock() - if headHash == lastHead { - return new(big.Int).Set(lastPrice), nil - } - oracle.fetchLock.Lock() - defer oracle.fetchLock.Unlock() - - // Try checking the cache again, maybe the last fetch fetched what we need - oracle.cacheLock.RLock() - lastHead, lastPrice = oracle.lastHead, oracle.lastPrice - oracle.cacheLock.RUnlock() - if headHash == lastHead { - return new(big.Int).Set(lastPrice), nil - } - var ( - sent, exp int - number = head.Number.Uint64() - result = make(chan results, oracle.checkBlocks) - quit = make(chan struct{}) - results []*big.Int - ) - for sent < oracle.checkBlocks && number > 0 { - go oracle.getBlockValues(ctx, number, sampleNumber, oracle.ignorePrice, result, quit) - sent++ - exp++ - number-- - } - for exp > 0 { - res := <-result - if res.err != nil { - close(quit) - return new(big.Int).Set(lastPrice), res.err - } - exp-- - // Nothing returned. There are two special cases here: - // - The block is empty - // - All the transactions included are sent by the miner itself. - // In these cases, use the latest calculated price for sampling. - if len(res.values) == 0 { - res.values = []*big.Int{lastPrice} - } - // Besides, in order to collect enough data for sampling, if nothing - // meaningful returned, try to query more blocks. But the maximum - // is 2*checkBlocks. - if len(res.values) == 1 && len(results)+1+exp < oracle.checkBlocks*2 && number > 0 { - go oracle.getBlockValues(ctx, number, sampleNumber, oracle.ignorePrice, result, quit) - sent++ - exp++ - number-- - } - results = append(results, res.values...) - } - price := lastPrice - if len(results) > 0 { - slices.SortFunc(results, func(a, b *big.Int) int { return a.Cmp(b) }) - price = results[(len(results)-1)*oracle.percentile/100] - } - if price.Cmp(oracle.maxPrice) > 0 { - price = new(big.Int).Set(oracle.maxPrice) - } - oracle.cacheLock.Lock() - oracle.lastHead = headHash - oracle.lastPrice = price - oracle.cacheLock.Unlock() - - return new(big.Int).Set(price), nil -} - -type results struct { - values []*big.Int - err error -} - -// getBlockValues calculates the lowest transaction gas price in a given block -// and sends it to the result channel. If the block is empty or all transactions -// are sent by the miner itself(it doesn't make any sense to include this kind of -// transaction prices for sampling), nil gasprice is returned. -func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit int, ignoreUnder *big.Int, result chan results, quit chan struct{}) { - block, err := oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum)) - if block == nil { - select { - case result <- results{nil, err}: - case <-quit: - } - return - } - signer := types.MakeSigner(oracle.backend.ChainConfig(), block.Number(), block.Time()) - - // Sort the transaction by effective tip in ascending sort. - txs := block.Transactions() - sortedTxs := make([]*types.Transaction, len(txs)) - copy(sortedTxs, txs) - baseFee := block.BaseFee() - slices.SortFunc(sortedTxs, func(a, b *types.Transaction) int { - // It's okay to discard the error because a tx would never be - // accepted into a block with an invalid effective tip. - tip1, _ := a.EffectiveGasTip(baseFee) - tip2, _ := b.EffectiveGasTip(baseFee) - return tip1.Cmp(tip2) - }) - - var prices []*big.Int - for _, tx := range sortedTxs { - tip, _ := tx.EffectiveGasTip(baseFee) - if ignoreUnder != nil && tip.Cmp(ignoreUnder) == -1 { - continue - } - sender, err := types.Sender(signer, tx) - if err == nil && sender != block.Coinbase() { - prices = append(prices, tip) - if len(prices) >= limit { - break - } - } - } - select { - case result <- results{prices, nil}: - case <-quit: - } -} diff --git a/builder/eth/gasprice/gasprice_test.go b/builder/eth/gasprice/gasprice_test.go deleted file mode 100644 index 79217502f..000000000 --- a/builder/eth/gasprice/gasprice_test.go +++ /dev/null @@ -1,215 +0,0 @@ -// 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 gasprice - -import ( - "context" - "math" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -const testHead = 32 - -type testBackend struct { - chain *core.BlockChain - pending bool // pending block available -} - -func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { - if number > testHead { - return nil, nil - } - if number == rpc.EarliestBlockNumber { - number = 0 - } - if number == rpc.FinalizedBlockNumber { - return b.chain.CurrentFinalBlock(), nil - } - if number == rpc.SafeBlockNumber { - return b.chain.CurrentSafeBlock(), nil - } - if number == rpc.LatestBlockNumber { - number = testHead - } - if number == rpc.PendingBlockNumber { - if b.pending { - number = testHead + 1 - } else { - return nil, nil - } - } - return b.chain.GetHeaderByNumber(uint64(number)), nil -} - -func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { - if number > testHead { - return nil, nil - } - if number == rpc.EarliestBlockNumber { - number = 0 - } - if number == rpc.FinalizedBlockNumber { - number = rpc.BlockNumber(b.chain.CurrentFinalBlock().Number.Uint64()) - } - if number == rpc.SafeBlockNumber { - number = rpc.BlockNumber(b.chain.CurrentSafeBlock().Number.Uint64()) - } - if number == rpc.LatestBlockNumber { - number = testHead - } - if number == rpc.PendingBlockNumber { - if b.pending { - number = testHead + 1 - } else { - return nil, nil - } - } - return b.chain.GetBlockByNumber(uint64(number)), nil -} - -func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - return b.chain.GetReceiptsByHash(hash), nil -} - -func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { - if b.pending { - block := b.chain.GetBlockByNumber(testHead + 1) - return block, b.chain.GetReceiptsByHash(block.Hash()) - } - return nil, nil -} - -func (b *testBackend) ChainConfig() *params.ChainConfig { - return b.chain.Config() -} - -func (b *testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { - return nil -} - -func (b *testBackend) teardown() { - b.chain.Stop() -} - -// newTestBackend creates a test backend. OBS: don't forget to invoke tearDown -// after use, otherwise the blockchain instance will mem-leak via goroutines. -func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend { - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key.PublicKey) - config = *params.TestChainConfig // needs copy because it is modified below - gspec = &core.Genesis{ - Config: &config, - Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}}, - } - signer = types.LatestSigner(gspec.Config) - ) - config.LondonBlock = londonBlock - config.ArrowGlacierBlock = londonBlock - config.GrayGlacierBlock = londonBlock - config.TerminalTotalDifficulty = common.Big0 - engine := ethash.NewFaker() - - // Generate testing blocks - _, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) { - b.SetCoinbase(common.Address{1}) - - var txdata types.TxData - if londonBlock != nil && b.Number().Cmp(londonBlock) >= 0 { - txdata = &types.DynamicFeeTx{ - ChainID: gspec.Config.ChainID, - Nonce: b.TxNonce(addr), - To: &common.Address{}, - Gas: 30000, - GasFeeCap: big.NewInt(100 * params.GWei), - GasTipCap: big.NewInt(int64(i+1) * params.GWei), - Data: []byte{}, - } - } else { - txdata = &types.LegacyTx{ - Nonce: b.TxNonce(addr), - To: &common.Address{}, - Gas: 21000, - GasPrice: big.NewInt(int64(i+1) * params.GWei), - Value: big.NewInt(100), - Data: []byte{}, - } - } - b.AddTx(types.MustSignNewTx(key, signer, txdata)) - }) - // Construct testing chain - chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("Failed to create local chain, %v", err) - } - chain.InsertChain(blocks) - chain.SetFinalized(chain.GetBlockByNumber(25).Header()) - chain.SetSafe(chain.GetBlockByNumber(25).Header()) - return &testBackend{chain: chain, pending: pending} -} - -func (b *testBackend) CurrentHeader() *types.Header { - return b.chain.CurrentHeader() -} - -func (b *testBackend) GetBlockByNumber(number uint64) *types.Block { - return b.chain.GetBlockByNumber(number) -} - -func TestSuggestTipCap(t *testing.T) { - config := Config{ - Blocks: 3, - Percentile: 60, - Default: big.NewInt(params.GWei), - } - var cases = []struct { - fork *big.Int // London fork number - expect *big.Int // Expected gasprice suggestion - }{ - {nil, big.NewInt(params.GWei * int64(30))}, - {big.NewInt(0), big.NewInt(params.GWei * int64(30))}, // Fork point in genesis - {big.NewInt(1), big.NewInt(params.GWei * int64(30))}, // Fork point in first block - {big.NewInt(32), big.NewInt(params.GWei * int64(30))}, // Fork point in last block - {big.NewInt(33), big.NewInt(params.GWei * int64(30))}, // Fork point in the future - } - for _, c := range cases { - backend := newTestBackend(t, c.fork, false) - oracle := NewOracle(backend, config) - - // The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G - got, err := oracle.SuggestTipCap(context.Background()) - backend.teardown() - if err != nil { - t.Fatalf("Failed to retrieve recommended gas price: %v", err) - } - if got.Cmp(c.expect) != 0 { - t.Fatalf("Gas price mismatch, want %d, got %d", c.expect, got) - } - } -} diff --git a/builder/eth/handler.go b/builder/eth/handler.go deleted file mode 100644 index 65a17a9ad..000000000 --- a/builder/eth/handler.go +++ /dev/null @@ -1,696 +0,0 @@ -// 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 eth - -import ( - "errors" - "math" - "math/big" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/fetcher" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/triedb/pathdb" -) - -const ( - // txChanSize is the size of channel listening to NewTxsEvent. - // The number is referenced from the size of tx pool. - txChanSize = 4096 - - // txMaxBroadcastSize is the max size of a transaction that will be broadcasted. - // All transactions with a higher size will be announced and need to be fetched - // by the peer. - txMaxBroadcastSize = 4096 -) - -var syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge - -// txPool defines the methods needed from a transaction pool implementation to -// support all the operations needed by the Ethereum chain protocols. -type txPool interface { - // Has returns an indicator whether txpool has a transaction - // cached with the given hash. - Has(hash common.Hash) bool - - // Get retrieves the transaction from local txpool with given - // tx hash. - Get(hash common.Hash) *types.Transaction - - // Add should add the given transactions to the pool. - Add(txs []*types.Transaction, local bool, sync bool, private bool) []error - - // Pending should return pending transactions. - // The slice should be modifiable by the caller. - Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction - - // SubscribeTransactions subscribes to new transaction events. The subscriber - // can decide whether to receive notifications only for newly seen transactions - // or also for reorged out ones. - SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription - - // IsPrivateTxHash indicates if the transaction hash should not - // be broadcast on public channels - IsPrivateTxHash(hash common.Hash) bool -} - -// handlerConfig is the collection of initialization parameters to create a full -// node network handler. -type handlerConfig struct { - Database ethdb.Database // Database for direct sync insertions - Chain *core.BlockChain // Blockchain to serve data from - TxPool txPool // Transaction pool to propagate from - Merger *consensus.Merger // The manager for eth1/2 transition - Network uint64 // Network identifier to advertise - Sync downloader.SyncMode // Whether to snap or full sync - BloomCache uint64 // Megabytes to alloc for snap sync bloom - EventMux *event.TypeMux // Legacy event mux, deprecate for `feed` - RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges -} - -type handler struct { - networkID uint64 - forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node - - snapSync atomic.Bool // Flag whether snap sync is enabled (gets disabled if we already have blocks) - synced atomic.Bool // Flag whether we're considered synchronised (enables transaction processing) - - database ethdb.Database - txpool txPool - chain *core.BlockChain - maxPeers int - - downloader *downloader.Downloader - blockFetcher *fetcher.BlockFetcher - txFetcher *fetcher.TxFetcher - peers *peerSet - merger *consensus.Merger - - eventMux *event.TypeMux - txsCh chan core.NewTxsEvent - txsSub event.Subscription - minedBlockSub *event.TypeMuxSubscription - - requiredBlocks map[uint64]common.Hash - - // channels for fetcher, syncer, txsyncLoop - quitSync chan struct{} - - chainSync *chainSyncer - wg sync.WaitGroup - - handlerStartCh chan struct{} - handlerDoneCh chan struct{} -} - -// newHandler returns a handler for all Ethereum chain management protocol. -func newHandler(config *handlerConfig) (*handler, error) { - // Create the protocol manager with the base fields - if config.EventMux == nil { - config.EventMux = new(event.TypeMux) // Nicety initialization for tests - } - h := &handler{ - networkID: config.Network, - forkFilter: forkid.NewFilter(config.Chain), - eventMux: config.EventMux, - database: config.Database, - txpool: config.TxPool, - chain: config.Chain, - peers: newPeerSet(), - merger: config.Merger, - requiredBlocks: config.RequiredBlocks, - quitSync: make(chan struct{}), - handlerDoneCh: make(chan struct{}), - handlerStartCh: make(chan struct{}), - } - if config.Sync == downloader.FullSync { - // The database seems empty as the current block is the genesis. Yet the snap - // block is ahead, so snap sync was enabled for this node at a certain point. - // The scenarios where this can happen is - // * if the user manually (or via a bad block) rolled back a snap sync node - // below the sync point. - // * the last snap sync is not finished while user specifies a full sync this - // time. But we don't have any recent state for full sync. - // In these cases however it's safe to reenable snap sync. - fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() - if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { - h.snapSync.Store(true) - log.Warn("Switch sync mode from full sync to snap sync", "reason", "snap sync incomplete") - } else if !h.chain.HasState(fullBlock.Root) { - h.snapSync.Store(true) - log.Warn("Switch sync mode from full sync to snap sync", "reason", "head state missing") - } - } else { - head := h.chain.CurrentBlock() - if head.Number.Uint64() > 0 && h.chain.HasState(head.Root) { - // Print warning log if database is not empty to run snap sync. - log.Warn("Switch sync mode from snap sync to full sync", "reason", "snap sync complete") - } else { - // If snap sync was requested and our database is empty, grant it - h.snapSync.Store(true) - log.Info("Enabled snap sync", "head", head.Number, "hash", head.Hash()) - } - } - // If snap sync is requested but snapshots are disabled, fail loudly - if h.snapSync.Load() && config.Chain.Snapshots() == nil { - return nil, errors.New("snap sync not supported with snapshots disabled") - } - // Construct the downloader (long sync) - h.downloader = downloader.New(config.Database, h.eventMux, h.chain, nil, h.removePeer, h.enableSyncedFeatures) - if ttd := h.chain.Config().TerminalTotalDifficulty; ttd != nil { - if h.chain.Config().TerminalTotalDifficultyPassed { - log.Info("Chain post-merge, sync via beacon client") - } else { - head := h.chain.CurrentBlock() - if td := h.chain.GetTd(head.Hash(), head.Number.Uint64()); td.Cmp(ttd) >= 0 { - log.Info("Chain post-TTD, sync via beacon client") - } else { - log.Warn("Chain pre-merge, sync via PoW (ensure beacon client is ready)") - } - } - } else if h.chain.Config().TerminalTotalDifficultyPassed { - log.Error("Chain configured post-merge, but without TTD. Are you debugging sync?") - } - // Construct the fetcher (short sync) - validator := func(header *types.Header) error { - // All the block fetcher activities should be disabled - // after the transition. Print the warning log. - if h.merger.PoSFinalized() { - log.Warn("Unexpected validation activity", "hash", header.Hash(), "number", header.Number) - return errors.New("unexpected behavior after transition") - } - // Reject all the PoS style headers in the first place. No matter - // the chain has finished the transition or not, the PoS headers - // should only come from the trusted consensus layer instead of - // p2p network. - if beacon, ok := h.chain.Engine().(*beacon.Beacon); ok { - if beacon.IsPoSHeader(header) { - return errors.New("unexpected post-merge header") - } - } - return h.chain.Engine().VerifyHeader(h.chain, header) - } - heighter := func() uint64 { - return h.chain.CurrentBlock().Number.Uint64() - } - inserter := func(blocks types.Blocks) (int, error) { - // All the block fetcher activities should be disabled - // after the transition. Print the warning log. - if h.merger.PoSFinalized() { - var ctx []interface{} - ctx = append(ctx, "blocks", len(blocks)) - if len(blocks) > 0 { - ctx = append(ctx, "firsthash", blocks[0].Hash()) - ctx = append(ctx, "firstnumber", blocks[0].Number()) - ctx = append(ctx, "lasthash", blocks[len(blocks)-1].Hash()) - ctx = append(ctx, "lastnumber", blocks[len(blocks)-1].Number()) - } - log.Warn("Unexpected insertion activity", ctx...) - return 0, errors.New("unexpected behavior after transition") - } - // If snap sync is running, deny importing weird blocks. This is a problematic - // clause when starting up a new network, because snap-syncing miners might not - // accept each others' blocks until a restart. Unfortunately we haven't figured - // out a way yet where nodes can decide unilaterally whether the network is new - // or not. This should be fixed if we figure out a solution. - if !h.synced.Load() { - log.Warn("Syncing, discarded propagated block", "number", blocks[0].Number(), "hash", blocks[0].Hash()) - return 0, nil - } - if h.merger.TDDReached() { - // The blocks from the p2p network is regarded as untrusted - // after the transition. In theory block gossip should be disabled - // entirely whenever the transition is started. But in order to - // handle the transition boundary reorg in the consensus-layer, - // the legacy blocks are still accepted, but only for the terminal - // pow blocks. Spec: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3675.md#halt-the-importing-of-pow-blocks - for i, block := range blocks { - ptd := h.chain.GetTd(block.ParentHash(), block.NumberU64()-1) - if ptd == nil { - return 0, nil - } - td := new(big.Int).Add(ptd, block.Difficulty()) - if !h.chain.Config().IsTerminalPoWBlock(ptd, td) { - log.Info("Filtered out non-terminal pow block", "number", block.NumberU64(), "hash", block.Hash()) - return 0, nil - } - if err := h.chain.InsertBlockWithoutSetHead(block); err != nil { - return i, err - } - } - return 0, nil - } - return h.chain.InsertChain(blocks) - } - h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock, heighter, nil, inserter, h.removePeer) - - fetchTx := func(peer string, hashes []common.Hash) error { - p := h.peers.peer(peer) - if p == nil { - return errors.New("unknown peer") - } - return p.RequestTxs(hashes) - } - addTxs := func(txs []*types.Transaction) []error { - return h.txpool.Add(txs, false, false, false) - } - h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer) - h.chainSync = newChainSyncer(h) - return h, nil -} - -// protoTracker tracks the number of active protocol handlers. -func (h *handler) protoTracker() { - defer h.wg.Done() - var active int - for { - select { - case <-h.handlerStartCh: - active++ - case <-h.handlerDoneCh: - active-- - case <-h.quitSync: - // Wait for all active handlers to finish. - for ; active > 0; active-- { - <-h.handlerDoneCh - } - return - } - } -} - -// incHandlers signals to increment the number of active handlers if not -// quitting. -func (h *handler) incHandlers() bool { - select { - case h.handlerStartCh <- struct{}{}: - return true - case <-h.quitSync: - return false - } -} - -// decHandlers signals to decrement the number of active handlers. -func (h *handler) decHandlers() { - h.handlerDoneCh <- struct{}{} -} - -// runEthPeer registers an eth peer into the joint eth/snap peerset, adds it to -// various subsystems and starts handling messages. -func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error { - if !h.incHandlers() { - return p2p.DiscQuitting - } - defer h.decHandlers() - - // If the peer has a `snap` extension, wait for it to connect so we can have - // a uniform initialization/teardown mechanism - snap, err := h.peers.waitSnapExtension(peer) - if err != nil { - peer.Log().Error("Snapshot extension barrier failed", "err", err) - return err - } - - // Execute the Ethereum handshake - var ( - genesis = h.chain.Genesis() - head = h.chain.CurrentHeader() - hash = head.Hash() - number = head.Number.Uint64() - td = h.chain.GetTd(hash, number) - ) - forkID := forkid.NewID(h.chain.Config(), genesis, number, head.Time) - if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { - peer.Log().Debug("Ethereum handshake failed", "err", err) - return err - } - reject := false // reserved peer slots - if h.snapSync.Load() { - if snap == nil { - // If we are running snap-sync, we want to reserve roughly half the peer - // slots for peers supporting the snap protocol. - // The logic here is; we only allow up to 5 more non-snap peers than snap-peers. - if all, snp := h.peers.len(), h.peers.snapLen(); all-snp > snp+5 { - reject = true - } - } - } - // Ignore maxPeers if this is a trusted peer - if !peer.Peer.Info().Network.Trusted { - if reject || h.peers.len() >= h.maxPeers { - return p2p.DiscTooManyPeers - } - } - peer.Log().Debug("Ethereum peer connected", "name", peer.Name()) - - // Register the peer locally - if err := h.peers.registerPeer(peer, snap); err != nil { - peer.Log().Error("Ethereum peer registration failed", "err", err) - return err - } - defer h.unregisterPeer(peer.ID()) - - p := h.peers.peer(peer.ID()) - if p == nil { - return errors.New("peer dropped during handling") - } - // Register the peer in the downloader. If the downloader considers it banned, we disconnect - if err := h.downloader.RegisterPeer(peer.ID(), peer.Version(), peer); err != nil { - peer.Log().Error("Failed to register peer in eth syncer", "err", err) - return err - } - if snap != nil { - if err := h.downloader.SnapSyncer.Register(snap); err != nil { - peer.Log().Error("Failed to register peer in snap syncer", "err", err) - return err - } - } - h.chainSync.handlePeerEvent() - - // Propagate existing transactions. new transactions appearing - // after this will be sent via broadcasts. - h.syncTransactions(peer) - - // Create a notification channel for pending requests if the peer goes down - dead := make(chan struct{}) - defer close(dead) - - // If we have any explicit peer required block hashes, request them - for number, hash := range h.requiredBlocks { - resCh := make(chan *eth.Response) - - req, err := peer.RequestHeadersByNumber(number, 1, 0, false, resCh) - if err != nil { - return err - } - go func(number uint64, hash common.Hash, req *eth.Request) { - // Ensure the request gets cancelled in case of error/drop - defer req.Close() - - timeout := time.NewTimer(syncChallengeTimeout) - defer timeout.Stop() - - select { - case res := <-resCh: - headers := ([]*types.Header)(*res.Res.(*eth.BlockHeadersRequest)) - if len(headers) == 0 { - // Required blocks are allowed to be missing if the remote - // node is not yet synced - res.Done <- nil - return - } - // Validate the header and either drop the peer or continue - if len(headers) > 1 { - res.Done <- errors.New("too many headers in required block response") - return - } - if headers[0].Number.Uint64() != number || headers[0].Hash() != hash { - peer.Log().Info("Required block mismatch, dropping peer", "number", number, "hash", headers[0].Hash(), "want", hash) - res.Done <- errors.New("required block mismatch") - return - } - peer.Log().Debug("Peer required block verified", "number", number, "hash", hash) - res.Done <- nil - case <-timeout.C: - peer.Log().Warn("Required block challenge timed out, dropping", "addr", peer.RemoteAddr(), "type", peer.Name()) - h.removePeer(peer.ID()) - } - }(number, hash, req) - } - // Handle incoming messages until the connection is torn down - return handler(peer) -} - -// runSnapExtension registers a `snap` peer into the joint eth/snap peerset and -// starts handling inbound messages. As `snap` is only a satellite protocol to -// `eth`, all subsystem registrations and lifecycle management will be done by -// the main `eth` handler to prevent strange races. -func (h *handler) runSnapExtension(peer *snap.Peer, handler snap.Handler) error { - if !h.incHandlers() { - return p2p.DiscQuitting - } - defer h.decHandlers() - - if err := h.peers.registerSnapExtension(peer); err != nil { - if metrics.Enabled { - if peer.Inbound() { - snap.IngressRegistrationErrorMeter.Mark(1) - } else { - snap.EgressRegistrationErrorMeter.Mark(1) - } - } - peer.Log().Debug("Snapshot extension registration failed", "err", err) - return err - } - return handler(peer) -} - -// removePeer requests disconnection of a peer. -func (h *handler) removePeer(id string) { - peer := h.peers.peer(id) - if peer != nil { - peer.Peer.Disconnect(p2p.DiscUselessPeer) - } -} - -// unregisterPeer removes a peer from the downloader, fetchers and main peer set. -func (h *handler) unregisterPeer(id string) { - // Create a custom logger to avoid printing the entire id - var logger log.Logger - if len(id) < 16 { - // Tests use short IDs, don't choke on them - logger = log.New("peer", id) - } else { - logger = log.New("peer", id[:8]) - } - // Abort if the peer does not exist - peer := h.peers.peer(id) - if peer == nil { - logger.Error("Ethereum peer removal failed", "err", errPeerNotRegistered) - return - } - // Remove the `eth` peer if it exists - logger.Debug("Removing Ethereum peer", "snap", peer.snapExt != nil) - - // Remove the `snap` extension if it exists - if peer.snapExt != nil { - h.downloader.SnapSyncer.Unregister(id) - } - h.downloader.UnregisterPeer(id) - h.txFetcher.Drop(id) - - if err := h.peers.unregisterPeer(id); err != nil { - logger.Error("Ethereum peer removal failed", "err", err) - } -} - -func (h *handler) Start(maxPeers int) { - h.maxPeers = maxPeers - - // broadcast and announce transactions (only new ones, not resurrected ones) - h.wg.Add(1) - h.txsCh = make(chan core.NewTxsEvent, txChanSize) - h.txsSub = h.txpool.SubscribeTransactions(h.txsCh, false) - go h.txBroadcastLoop() - - // broadcast mined blocks - h.wg.Add(1) - h.minedBlockSub = h.eventMux.Subscribe(core.NewMinedBlockEvent{}) - go h.minedBroadcastLoop() - - // start sync handlers - h.wg.Add(1) - go h.chainSync.loop() - - // start peer handler tracker - h.wg.Add(1) - go h.protoTracker() -} - -func (h *handler) Stop() { - h.txsSub.Unsubscribe() // quits txBroadcastLoop - h.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop - - // Quit chainSync and txsync64. - // After this is done, no new peers will be accepted. - close(h.quitSync) - - // Disconnect existing sessions. - // This also closes the gate for any new registrations on the peer set. - // sessions which are already established but not added to h.peers yet - // will exit when they try to register. - h.peers.close() - h.wg.Wait() - - log.Info("Ethereum protocol stopped") -} - -// BroadcastBlock will either propagate a block to a subset of its peers, or -// will only announce its availability (depending what's requested). -func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { - // Disable the block propagation if the chain has already entered the PoS - // stage. The block propagation is delegated to the consensus layer. - if h.merger.PoSFinalized() { - return - } - // Disable the block propagation if it's the post-merge block. - if beacon, ok := h.chain.Engine().(*beacon.Beacon); ok { - if beacon.IsPoSHeader(block.Header()) { - return - } - } - hash := block.Hash() - peers := h.peers.peersWithoutBlock(hash) - - // If propagation is requested, send to a subset of the peer - if propagate { - // Calculate the TD of the block (it's not imported yet, so block.Td is not valid) - var td *big.Int - if parent := h.chain.GetBlock(block.ParentHash(), block.NumberU64()-1); parent != nil { - td = new(big.Int).Add(block.Difficulty(), h.chain.GetTd(block.ParentHash(), block.NumberU64()-1)) - } else { - log.Error("Propagating dangling block", "number", block.Number(), "hash", hash) - return - } - // Send the block to a subset of our peers - transfer := peers[:int(math.Sqrt(float64(len(peers))))] - for _, peer := range transfer { - peer.AsyncSendNewBlock(block, td) - } - log.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) - return - } - // Otherwise if the block is indeed in out own chain, announce it - if h.chain.HasBlock(hash, block.NumberU64()) { - for _, peer := range peers { - peer.AsyncSendNewBlockHash(block) - } - log.Trace("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) - } -} - -// BroadcastTransactions will propagate a batch of transactions -// - To a square root of all peers for non-blob transactions -// - And, separately, as announcements to all peers which are not known to -// already have the given transaction. -func (h *handler) BroadcastTransactions(txs types.Transactions) { - var ( - blobTxs int // Number of blob transactions to announce only - largeTxs int // Number of large transactions to announce only - - directCount int // Number of transactions sent directly to peers (duplicates included) - directPeers int // Number of peers that were sent transactions directly - annCount int // Number of transactions announced across all peers (duplicates included) - annPeers int // Number of peers announced about transactions - - txset = make(map[*ethPeer][]common.Hash) // Set peer->hash to transfer directly - annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce - ) - // Broadcast transactions to a batch of peers not knowing about it - for _, tx := range txs { - peers := h.peers.peersWithoutTransaction(tx.Hash()) - - var numDirect int - switch { - case tx.Type() == types.BlobTxType: - blobTxs++ - case tx.Size() > txMaxBroadcastSize: - largeTxs++ - default: - numDirect = int(math.Sqrt(float64(len(peers)))) - } - // Send the tx unconditionally to a subset of our peers - for _, peer := range peers[:numDirect] { - txset[peer] = append(txset[peer], tx.Hash()) - } - // For the remaining peers, send announcement only - for _, peer := range peers[numDirect:] { - annos[peer] = append(annos[peer], tx.Hash()) - } - } - for peer, hashes := range txset { - directPeers++ - directCount += len(hashes) - peer.AsyncSendTransactions(hashes) - } - for peer, hashes := range annos { - annPeers++ - annCount += len(hashes) - peer.AsyncSendPooledTransactionHashes(hashes) - } - log.Debug("Distributed transactions", "plaintxs", len(txs)-blobTxs-largeTxs, "blobtxs", blobTxs, "largetxs", largeTxs, - "bcastpeers", directPeers, "bcastcount", directCount, "annpeers", annPeers, "anncount", annCount) -} - -// minedBroadcastLoop sends mined blocks to connected peers. -func (h *handler) minedBroadcastLoop() { - defer h.wg.Done() - - for obj := range h.minedBlockSub.Chan() { - if ev, ok := obj.Data.(core.NewMinedBlockEvent); ok { - h.BroadcastBlock(ev.Block, true) // First propagate block to peers - h.BroadcastBlock(ev.Block, false) // Only then announce to the rest - } - } -} - -// txBroadcastLoop announces new transactions to connected peers. -func (h *handler) txBroadcastLoop() { - defer h.wg.Done() - for { - select { - case event := <-h.txsCh: - h.BroadcastTransactions(event.Txs) - case <-h.txsSub.Err(): - return - } - } -} - -// enableSyncedFeatures enables the post-sync functionalities when the initial -// sync is finished. -func (h *handler) enableSyncedFeatures() { - // Mark the local node as synced. - h.synced.Store(true) - - // If we were running snap sync and it finished, disable doing another - // round on next sync cycle - if h.snapSync.Load() { - log.Info("Snap sync complete, auto disabling") - h.snapSync.Store(false) - } - if h.chain.TrieDB().Scheme() == rawdb.PathScheme { - h.chain.TrieDB().SetBufferSize(pathdb.DefaultBufferSize) - } -} diff --git a/builder/eth/handler_eth.go b/builder/eth/handler_eth.go deleted file mode 100644 index f1284c10e..000000000 --- a/builder/eth/handler_eth.go +++ /dev/null @@ -1,139 +0,0 @@ -// 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 eth - -import ( - "errors" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// ethHandler implements the eth.Backend interface to handle the various network -// packets that are sent as replies or broadcasts. -type ethHandler handler - -func (h *ethHandler) Chain() *core.BlockChain { return h.chain } -func (h *ethHandler) TxPool() eth.TxPool { return h.txpool } - -// RunPeer is invoked when a peer joins on the `eth` protocol. -func (h *ethHandler) RunPeer(peer *eth.Peer, hand eth.Handler) error { - return (*handler)(h).runEthPeer(peer, hand) -} - -// PeerInfo retrieves all known `eth` information about a peer. -func (h *ethHandler) PeerInfo(id enode.ID) interface{} { - if p := h.peers.peer(id.String()); p != nil { - return p.info() - } - return nil -} - -// AcceptTxs retrieves whether transaction processing is enabled on the node -// or if inbound transactions should simply be dropped. -func (h *ethHandler) AcceptTxs() bool { - return h.synced.Load() -} - -// Handle is invoked from a peer's message handler when it receives a new remote -// message that the handler couldn't consume and serve itself. -func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error { - // Consume any broadcasts and announces, forwarding the rest to the downloader - switch packet := packet.(type) { - case *eth.NewBlockHashesPacket: - hashes, numbers := packet.Unpack() - return h.handleBlockAnnounces(peer, hashes, numbers) - - case *eth.NewBlockPacket: - return h.handleBlockBroadcast(peer, packet.Block, packet.TD) - - case *eth.NewPooledTransactionHashesPacket: - return h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes) - - case *eth.TransactionsPacket: - for _, tx := range *packet { - if tx.Type() == types.BlobTxType { - return errors.New("disallowed broadcast blob transaction") - } - } - return h.txFetcher.Enqueue(peer.ID(), *packet, false) - - case *eth.PooledTransactionsResponse: - return h.txFetcher.Enqueue(peer.ID(), *packet, true) - - default: - return fmt.Errorf("unexpected eth packet type: %T", packet) - } -} - -// handleBlockAnnounces is invoked from a peer's message handler when it transmits a -// batch of block announcements for the local node to process. -func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash, numbers []uint64) error { - // Drop all incoming block announces from the p2p network if - // the chain already entered the pos stage and disconnect the - // remote peer. - if h.merger.PoSFinalized() { - return errors.New("disallowed block announcement") - } - // Schedule all the unknown hashes for retrieval - var ( - unknownHashes = make([]common.Hash, 0, len(hashes)) - unknownNumbers = make([]uint64, 0, len(numbers)) - ) - for i := 0; i < len(hashes); i++ { - if !h.chain.HasBlock(hashes[i], numbers[i]) { - unknownHashes = append(unknownHashes, hashes[i]) - unknownNumbers = append(unknownNumbers, numbers[i]) - } - } - for i := 0; i < len(unknownHashes); i++ { - h.blockFetcher.Notify(peer.ID(), unknownHashes[i], unknownNumbers[i], time.Now(), peer.RequestOneHeader, peer.RequestBodies) - } - return nil -} - -// handleBlockBroadcast is invoked from a peer's message handler when it transmits a -// block broadcast for the local node to process. -func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, block *types.Block, td *big.Int) error { - // Drop all incoming block announces from the p2p network if - // the chain already entered the pos stage and disconnect the - // remote peer. - if h.merger.PoSFinalized() { - return errors.New("disallowed block broadcast") - } - // Schedule the block for import - h.blockFetcher.Enqueue(peer.ID(), block) - - // Assuming the block is importable by the peer, but possibly not yet done so, - // calculate the head hash and TD that the peer truly must have. - var ( - trueHead = block.ParentHash() - trueTD = new(big.Int).Sub(td, block.Difficulty()) - ) - // Update the peer's total difficulty if better than the previous - if _, td := peer.Head(); trueTD.Cmp(td) > 0 { - peer.SetHead(trueHead, trueTD) - h.chainSync.handlePeerEvent() - } - return nil -} diff --git a/builder/eth/handler_eth_test.go b/builder/eth/handler_eth_test.go deleted file mode 100644 index e6c8ca7cd..000000000 --- a/builder/eth/handler_eth_test.go +++ /dev/null @@ -1,599 +0,0 @@ -// 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 eth - -import ( - "fmt" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" -) - -// testEthHandler is a mock event handler to listen for inbound network requests -// on the `eth` protocol and convert them into a more easily testable form. -type testEthHandler struct { - blockBroadcasts event.Feed - txAnnounces event.Feed - txBroadcasts event.Feed -} - -func (h *testEthHandler) Chain() *core.BlockChain { panic("no backing chain") } -func (h *testEthHandler) TxPool() eth.TxPool { panic("no backing tx pool") } -func (h *testEthHandler) AcceptTxs() bool { return true } -func (h *testEthHandler) RunPeer(*eth.Peer, eth.Handler) error { panic("not used in tests") } -func (h *testEthHandler) PeerInfo(enode.ID) interface{} { panic("not used in tests") } - -func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error { - switch packet := packet.(type) { - case *eth.NewBlockPacket: - h.blockBroadcasts.Send(packet.Block) - return nil - - case *eth.NewPooledTransactionHashesPacket: - h.txAnnounces.Send(packet.Hashes) - return nil - - case *eth.TransactionsPacket: - h.txBroadcasts.Send(([]*types.Transaction)(*packet)) - return nil - - case *eth.PooledTransactionsResponse: - h.txBroadcasts.Send(([]*types.Transaction)(*packet)) - return nil - - default: - panic(fmt.Sprintf("unexpected eth packet type in tests: %T", packet)) - } -} - -// Tests that peers are correctly accepted (or rejected) based on the advertised -// fork IDs in the protocol handshake. -func TestForkIDSplit68(t *testing.T) { testForkIDSplit(t, eth.ETH68) } - -func testForkIDSplit(t *testing.T, protocol uint) { - t.Parallel() - - var ( - engine = ethash.NewFaker() - - configNoFork = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1)} - configProFork = ¶ms.ChainConfig{ - HomesteadBlock: big.NewInt(1), - EIP150Block: big.NewInt(2), - EIP155Block: big.NewInt(2), - EIP158Block: big.NewInt(2), - ByzantiumBlock: big.NewInt(3), - } - dbNoFork = rawdb.NewMemoryDatabase() - dbProFork = rawdb.NewMemoryDatabase() - - gspecNoFork = &core.Genesis{Config: configNoFork} - gspecProFork = &core.Genesis{Config: configProFork} - - chainNoFork, _ = core.NewBlockChain(dbNoFork, nil, gspecNoFork, nil, engine, vm.Config{}, nil, nil) - chainProFork, _ = core.NewBlockChain(dbProFork, nil, gspecProFork, nil, engine, vm.Config{}, nil, nil) - - _, blocksNoFork, _ = core.GenerateChainWithGenesis(gspecNoFork, engine, 2, nil) - _, blocksProFork, _ = core.GenerateChainWithGenesis(gspecProFork, engine, 2, nil) - - ethNoFork, _ = newHandler(&handlerConfig{ - Database: dbNoFork, - Chain: chainNoFork, - TxPool: newTestTxPool(), - Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()), - Network: 1, - Sync: downloader.FullSync, - BloomCache: 1, - }) - ethProFork, _ = newHandler(&handlerConfig{ - Database: dbProFork, - Chain: chainProFork, - TxPool: newTestTxPool(), - Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()), - Network: 1, - Sync: downloader.FullSync, - BloomCache: 1, - }) - ) - ethNoFork.Start(1000) - ethProFork.Start(1000) - - // Clean up everything after ourselves - defer chainNoFork.Stop() - defer chainProFork.Stop() - - defer ethNoFork.Stop() - defer ethProFork.Stop() - - // Both nodes should allow the other to connect (same genesis, next fork is the same) - p2pNoFork, p2pProFork := p2p.MsgPipe() - defer p2pNoFork.Close() - defer p2pProFork.Close() - - peerNoFork := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pNoFork), p2pNoFork, nil) - peerProFork := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pProFork), p2pProFork, nil) - defer peerNoFork.Close() - defer peerProFork.Close() - - errc := make(chan error, 2) - go func(errc chan error) { - errc <- ethNoFork.runEthPeer(peerProFork, func(peer *eth.Peer) error { return nil }) - }(errc) - go func(errc chan error) { - errc <- ethProFork.runEthPeer(peerNoFork, func(peer *eth.Peer) error { return nil }) - }(errc) - - for i := 0; i < 2; i++ { - select { - case err := <-errc: - if err != nil { - t.Fatalf("frontier nofork <-> profork failed: %v", err) - } - case <-time.After(250 * time.Millisecond): - t.Fatalf("frontier nofork <-> profork handler timeout") - } - } - // Progress into Homestead. Fork's match, so we don't care what the future holds - chainNoFork.InsertChain(blocksNoFork[:1]) - chainProFork.InsertChain(blocksProFork[:1]) - - p2pNoFork, p2pProFork = p2p.MsgPipe() - defer p2pNoFork.Close() - defer p2pProFork.Close() - - peerNoFork = eth.NewPeer(protocol, p2p.NewPeer(enode.ID{1}, "", nil), p2pNoFork, nil) - peerProFork = eth.NewPeer(protocol, p2p.NewPeer(enode.ID{2}, "", nil), p2pProFork, nil) - defer peerNoFork.Close() - defer peerProFork.Close() - - errc = make(chan error, 2) - go func(errc chan error) { - errc <- ethNoFork.runEthPeer(peerProFork, func(peer *eth.Peer) error { return nil }) - }(errc) - go func(errc chan error) { - errc <- ethProFork.runEthPeer(peerNoFork, func(peer *eth.Peer) error { return nil }) - }(errc) - - for i := 0; i < 2; i++ { - select { - case err := <-errc: - if err != nil { - t.Fatalf("homestead nofork <-> profork failed: %v", err) - } - case <-time.After(250 * time.Millisecond): - t.Fatalf("homestead nofork <-> profork handler timeout") - } - } - // Progress into Spurious. Forks mismatch, signalling differing chains, reject - chainNoFork.InsertChain(blocksNoFork[1:2]) - chainProFork.InsertChain(blocksProFork[1:2]) - - p2pNoFork, p2pProFork = p2p.MsgPipe() - defer p2pNoFork.Close() - defer p2pProFork.Close() - - peerNoFork = eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pNoFork), p2pNoFork, nil) - peerProFork = eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pProFork), p2pProFork, nil) - defer peerNoFork.Close() - defer peerProFork.Close() - - errc = make(chan error, 2) - go func(errc chan error) { - errc <- ethNoFork.runEthPeer(peerProFork, func(peer *eth.Peer) error { return nil }) - }(errc) - go func(errc chan error) { - errc <- ethProFork.runEthPeer(peerNoFork, func(peer *eth.Peer) error { return nil }) - }(errc) - - var successes int - for i := 0; i < 2; i++ { - select { - case err := <-errc: - if err == nil { - successes++ - if successes == 2 { // Only one side disconnects - t.Fatalf("fork ID rejection didn't happen") - } - } - case <-time.After(250 * time.Millisecond): - t.Fatalf("split peers not rejected") - } - } -} - -// Tests that received transactions are added to the local pool. -func TestRecvTransactions68(t *testing.T) { testRecvTransactions(t, eth.ETH68) } - -func testRecvTransactions(t *testing.T, protocol uint) { - t.Parallel() - - // Create a message handler, configure it to accept transactions and watch them - handler := newTestHandler() - defer handler.close() - - handler.handler.synced.Store(true) // mark synced to accept transactions - - txs := make(chan core.NewTxsEvent) - sub := handler.txpool.SubscribeTransactions(txs, false) - defer sub.Unsubscribe() - - // Create a source peer to send messages through and a sink handler to receive them - p2pSrc, p2pSink := p2p.MsgPipe() - defer p2pSrc.Close() - defer p2pSink.Close() - - src := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pSrc), p2pSrc, handler.txpool) - sink := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pSink), p2pSink, handler.txpool) - defer src.Close() - defer sink.Close() - - go handler.handler.runEthPeer(sink, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(handler.handler), peer) - }) - // Run the handshake locally to avoid spinning up a source handler - var ( - genesis = handler.chain.Genesis() - head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) - ) - if err := src.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { - t.Fatalf("failed to run protocol handshake") - } - // Send the transaction to the sink and verify that it's added to the tx pool - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil) - tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - - if err := src.SendTransactions([]*types.Transaction{tx}); err != nil { - t.Fatalf("failed to send transaction: %v", err) - } - select { - case event := <-txs: - if len(event.Txs) != 1 { - t.Errorf("wrong number of added transactions: got %d, want 1", len(event.Txs)) - } else if event.Txs[0].Hash() != tx.Hash() { - t.Errorf("added wrong tx hash: got %v, want %v", event.Txs[0].Hash(), tx.Hash()) - } - case <-time.After(2 * time.Second): - t.Errorf("no NewTxsEvent received within 2 seconds") - } -} - -// This test checks that pending transactions are sent. -func TestSendTransactions68(t *testing.T) { testSendTransactions(t, eth.ETH68) } - -func testSendTransactions(t *testing.T, protocol uint) { - t.Parallel() - - // Create a message handler and fill the pool with big transactions - handler := newTestHandler() - defer handler.close() - - insert := make([]*types.Transaction, 100) - for nonce := range insert { - tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), make([]byte, 10240)) - tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - insert[nonce] = tx - } - go handler.txpool.Add(insert, false, false, false) // Need goroutine to not block on feed - time.Sleep(250 * time.Millisecond) // Wait until tx events get out of the system (can't use events, tx broadcaster races with peer join) - - // Create a source handler to send messages through and a sink peer to receive them - p2pSrc, p2pSink := p2p.MsgPipe() - defer p2pSrc.Close() - defer p2pSink.Close() - - src := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pSrc), p2pSrc, handler.txpool) - sink := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pSink), p2pSink, handler.txpool) - defer src.Close() - defer sink.Close() - - go handler.handler.runEthPeer(src, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(handler.handler), peer) - }) - // Run the handshake locally to avoid spinning up a source handler - var ( - genesis = handler.chain.Genesis() - head = handler.chain.CurrentBlock() - td = handler.chain.GetTd(head.Hash(), head.Number.Uint64()) - ) - if err := sink.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain)); err != nil { - t.Fatalf("failed to run protocol handshake") - } - // After the handshake completes, the source handler should stream the sink - // the transactions, subscribe to all inbound network events - backend := new(testEthHandler) - - anns := make(chan []common.Hash) - annSub := backend.txAnnounces.Subscribe(anns) - defer annSub.Unsubscribe() - - bcasts := make(chan []*types.Transaction) - bcastSub := backend.txBroadcasts.Subscribe(bcasts) - defer bcastSub.Unsubscribe() - - go eth.Handle(backend, sink) - - // Make sure we get all the transactions on the correct channels - seen := make(map[common.Hash]struct{}) - for len(seen) < len(insert) { - switch protocol { - case 68: - select { - case hashes := <-anns: - for _, hash := range hashes { - if _, ok := seen[hash]; ok { - t.Errorf("duplicate transaction announced: %x", hash) - } - seen[hash] = struct{}{} - } - case <-bcasts: - t.Errorf("initial tx broadcast received on post eth/66") - } - - default: - panic("unsupported protocol, please extend test") - } - } - for _, tx := range insert { - if _, ok := seen[tx.Hash()]; !ok { - t.Errorf("missing transaction: %x", tx.Hash()) - } - } -} - -// Tests that transactions get propagated to all attached peers, either via direct -// broadcasts or via announcements/retrievals. -func TestTransactionPropagation68(t *testing.T) { testTransactionPropagation(t, eth.ETH68) } - -func testTransactionPropagation(t *testing.T, protocol uint) { - t.Parallel() - - // Create a source handler to send transactions from and a number of sinks - // to receive them. We need multiple sinks since a one-to-one peering would - // broadcast all transactions without announcement. - source := newTestHandler() - source.handler.snapSync.Store(false) // Avoid requiring snap, otherwise some will be dropped below - defer source.close() - - sinks := make([]*testHandler, 10) - for i := 0; i < len(sinks); i++ { - sinks[i] = newTestHandler() - defer sinks[i].close() - - sinks[i].handler.synced.Store(true) // mark synced to accept transactions - } - // Interconnect all the sink handlers with the source handler - for i, sink := range sinks { - sink := sink // Closure for gorotuine below - - sourcePipe, sinkPipe := p2p.MsgPipe() - defer sourcePipe.Close() - defer sinkPipe.Close() - - sourcePeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{byte(i + 1)}, "", nil, sourcePipe), sourcePipe, source.txpool) - sinkPeer := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, sink.txpool) - defer sourcePeer.Close() - defer sinkPeer.Close() - - go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(source.handler), peer) - }) - go sink.handler.runEthPeer(sinkPeer, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(sink.handler), peer) - }) - } - // Subscribe to all the transaction pools - txChs := make([]chan core.NewTxsEvent, len(sinks)) - for i := 0; i < len(sinks); i++ { - txChs[i] = make(chan core.NewTxsEvent, 1024) - - sub := sinks[i].txpool.SubscribeTransactions(txChs[i], false) - defer sub.Unsubscribe() - } - // Fill the source pool with transactions and wait for them at the sinks - txs := make([]*types.Transaction, 1024) - for nonce := range txs { - tx := types.NewTransaction(uint64(nonce), common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil) - tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) - txs[nonce] = tx - } - source.txpool.Add(txs, false, false, false) - - // Iterate through all the sinks and ensure they all got the transactions - for i := range sinks { - for arrived, timeout := 0, false; arrived < len(txs) && !timeout; { - select { - case event := <-txChs[i]: - arrived += len(event.Txs) - case <-time.After(2 * time.Second): - t.Errorf("sink %d: transaction propagation timed out: have %d, want %d", i, arrived, len(txs)) - timeout = true - } - } - } -} - -// Tests that blocks are broadcast to a sqrt number of peers only. -func TestBroadcastBlock1Peer(t *testing.T) { testBroadcastBlock(t, 1, 1) } -func TestBroadcastBlock2Peers(t *testing.T) { testBroadcastBlock(t, 2, 1) } -func TestBroadcastBlock3Peers(t *testing.T) { testBroadcastBlock(t, 3, 1) } -func TestBroadcastBlock4Peers(t *testing.T) { testBroadcastBlock(t, 4, 2) } -func TestBroadcastBlock5Peers(t *testing.T) { testBroadcastBlock(t, 5, 2) } -func TestBroadcastBlock8Peers(t *testing.T) { testBroadcastBlock(t, 9, 3) } -func TestBroadcastBlock12Peers(t *testing.T) { testBroadcastBlock(t, 12, 3) } -func TestBroadcastBlock16Peers(t *testing.T) { testBroadcastBlock(t, 16, 4) } -func TestBroadcastBloc26Peers(t *testing.T) { testBroadcastBlock(t, 26, 5) } -func TestBroadcastBlock100Peers(t *testing.T) { testBroadcastBlock(t, 100, 10) } - -func testBroadcastBlock(t *testing.T, peers, bcasts int) { - t.Parallel() - - // Create a source handler to broadcast blocks from and a number of sinks - // to receive them. - source := newTestHandlerWithBlocks(1) - defer source.close() - - sinks := make([]*testEthHandler, peers) - for i := 0; i < len(sinks); i++ { - sinks[i] = new(testEthHandler) - } - // Interconnect all the sink handlers with the source handler - var ( - genesis = source.chain.Genesis() - td = source.chain.GetTd(genesis.Hash(), genesis.NumberU64()) - ) - for i, sink := range sinks { - sink := sink // Closure for gorotuine below - - sourcePipe, sinkPipe := p2p.MsgPipe() - defer sourcePipe.Close() - defer sinkPipe.Close() - - sourcePeer := eth.NewPeer(eth.ETH68, p2p.NewPeerPipe(enode.ID{byte(i)}, "", nil, sourcePipe), sourcePipe, nil) - sinkPeer := eth.NewPeer(eth.ETH68, p2p.NewPeerPipe(enode.ID{0}, "", nil, sinkPipe), sinkPipe, nil) - defer sourcePeer.Close() - defer sinkPeer.Close() - - go source.handler.runEthPeer(sourcePeer, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(source.handler), peer) - }) - if err := sinkPeer.Handshake(1, td, genesis.Hash(), genesis.Hash(), forkid.NewIDWithChain(source.chain), forkid.NewFilter(source.chain)); err != nil { - t.Fatalf("failed to run protocol handshake") - } - go eth.Handle(sink, sinkPeer) - } - // Subscribe to all the transaction pools - blockChs := make([]chan *types.Block, len(sinks)) - for i := 0; i < len(sinks); i++ { - blockChs[i] = make(chan *types.Block, 1) - defer close(blockChs[i]) - - sub := sinks[i].blockBroadcasts.Subscribe(blockChs[i]) - defer sub.Unsubscribe() - } - // Initiate a block propagation across the peers - time.Sleep(100 * time.Millisecond) - header := source.chain.CurrentBlock() - source.handler.BroadcastBlock(source.chain.GetBlock(header.Hash(), header.Number.Uint64()), true) - - // Iterate through all the sinks and ensure the correct number got the block - done := make(chan struct{}, peers) - for _, ch := range blockChs { - ch := ch - go func() { - <-ch - done <- struct{}{} - }() - } - var received int - for { - select { - case <-done: - received++ - - case <-time.After(100 * time.Millisecond): - if received != bcasts { - t.Errorf("broadcast count mismatch: have %d, want %d", received, bcasts) - } - return - } - } -} - -// Tests that a propagated malformed block (uncles or transactions don't match -// with the hashes in the header) gets discarded and not broadcast forward. -func TestBroadcastMalformedBlock68(t *testing.T) { testBroadcastMalformedBlock(t, eth.ETH68) } - -func testBroadcastMalformedBlock(t *testing.T, protocol uint) { - t.Parallel() - - // Create a source handler to broadcast blocks from and a number of sinks - // to receive them. - source := newTestHandlerWithBlocks(1) - defer source.close() - - // Create a source handler to send messages through and a sink peer to receive them - p2pSrc, p2pSink := p2p.MsgPipe() - defer p2pSrc.Close() - defer p2pSink.Close() - - src := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pSrc), p2pSrc, source.txpool) - sink := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pSink), p2pSink, source.txpool) - defer src.Close() - defer sink.Close() - - go source.handler.runEthPeer(src, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(source.handler), peer) - }) - // Run the handshake locally to avoid spinning up a sink handler - var ( - genesis = source.chain.Genesis() - td = source.chain.GetTd(genesis.Hash(), genesis.NumberU64()) - ) - if err := sink.Handshake(1, td, genesis.Hash(), genesis.Hash(), forkid.NewIDWithChain(source.chain), forkid.NewFilter(source.chain)); err != nil { - t.Fatalf("failed to run protocol handshake") - } - // After the handshake completes, the source handler should stream the sink - // the blocks, subscribe to inbound network events - backend := new(testEthHandler) - - blocks := make(chan *types.Block, 1) - sub := backend.blockBroadcasts.Subscribe(blocks) - defer sub.Unsubscribe() - - go eth.Handle(backend, sink) - - // Create various combinations of malformed blocks - head := source.chain.CurrentBlock() - block := source.chain.GetBlock(head.Hash(), head.Number.Uint64()) - - malformedUncles := head - malformedUncles.UncleHash[0]++ - malformedTransactions := head - malformedTransactions.TxHash[0]++ - malformedEverything := head - malformedEverything.UncleHash[0]++ - malformedEverything.TxHash[0]++ - - // Try to broadcast all malformations and ensure they all get discarded - for _, header := range []*types.Header{malformedUncles, malformedTransactions, malformedEverything} { - block := types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles()) - if err := src.SendNewBlock(block, big.NewInt(131136)); err != nil { - t.Fatalf("failed to broadcast block: %v", err) - } - select { - case <-blocks: - t.Fatalf("malformed block forwarded") - case <-time.After(100 * time.Millisecond): - } - } -} diff --git a/builder/eth/handler_snap.go b/builder/eth/handler_snap.go deleted file mode 100644 index 767416ffd..000000000 --- a/builder/eth/handler_snap.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 eth - -import ( - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// snapHandler implements the snap.Backend interface to handle the various network -// packets that are sent as replies or broadcasts. -type snapHandler handler - -func (h *snapHandler) Chain() *core.BlockChain { return h.chain } - -// RunPeer is invoked when a peer joins on the `snap` protocol. -func (h *snapHandler) RunPeer(peer *snap.Peer, hand snap.Handler) error { - return (*handler)(h).runSnapExtension(peer, hand) -} - -// PeerInfo retrieves all known `snap` information about a peer. -func (h *snapHandler) PeerInfo(id enode.ID) interface{} { - if p := h.peers.peer(id.String()); p != nil { - if p.snapExt != nil { - return p.snapExt.info() - } - } - return nil -} - -// Handle is invoked from a peer's message handler when it receives a new remote -// message that the handler couldn't consume and serve itself. -func (h *snapHandler) Handle(peer *snap.Peer, packet snap.Packet) error { - return h.downloader.DeliverSnapPacket(peer, packet) -} diff --git a/builder/eth/handler_test.go b/builder/eth/handler_test.go deleted file mode 100644 index d1f9ec40c..000000000 --- a/builder/eth/handler_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// 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 eth - -import ( - "math/big" - "sort" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -var ( - // testKey is a private key to use for funding a tester account. - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - - // testAddr is the Ethereum address of the tester account. - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) -) - -// testTxPool is a mock transaction pool that blindly accepts all transactions. -// Its goal is to get around setting up a valid statedb for the balance and nonce -// checks. -type testTxPool struct { - pool map[common.Hash]*types.Transaction // Hash map of collected transactions - - txFeed event.Feed // Notification feed to allow waiting for inclusion - lock sync.RWMutex // Protects the transaction pool -} - -// newTestTxPool creates a mock transaction pool. -func newTestTxPool() *testTxPool { - return &testTxPool{ - pool: make(map[common.Hash]*types.Transaction), - } -} - -// Has returns an indicator whether txpool has a transaction -// cached with the given hash. -func (p *testTxPool) Has(hash common.Hash) bool { - p.lock.Lock() - defer p.lock.Unlock() - - return p.pool[hash] != nil -} - -// Get retrieves the transaction from local txpool with given -// tx hash. -func (p *testTxPool) Get(hash common.Hash) *types.Transaction { - p.lock.Lock() - defer p.lock.Unlock() - return p.pool[hash] -} - -// Add appends a batch of transactions to the pool, and notifies any -// listeners if the addition channel is non nil -func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool, private bool) []error { - p.lock.Lock() - defer p.lock.Unlock() - - for _, tx := range txs { - p.pool[tx.Hash()] = tx - } - p.txFeed.Send(core.NewTxsEvent{Txs: txs}) - return make([]error, len(txs)) -} - -// Pending returns all the transactions known to the pool -func (p *testTxPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction { - p.lock.RLock() - defer p.lock.RUnlock() - - batches := make(map[common.Address][]*types.Transaction) - for _, tx := range p.pool { - from, _ := types.Sender(types.HomesteadSigner{}, tx) - batches[from] = append(batches[from], tx) - } - for _, batch := range batches { - sort.Sort(types.TxByNonce(batch)) - } - pending := make(map[common.Address][]*txpool.LazyTransaction) - for addr, batch := range batches { - for _, tx := range batch { - pending[addr] = append(pending[addr], &txpool.LazyTransaction{ - Hash: tx.Hash(), - Tx: tx, - Time: tx.Time(), - GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()), - GasTipCap: uint256.MustFromBig(tx.GasTipCap()), - Gas: tx.Gas(), - BlobGas: tx.BlobGas(), - GasPrice: uint256.MustFromBig(tx.GasPrice()), - }) - } - } - return pending -} - -// SubscribeTransactions should return an event subscription of NewTxsEvent and -// send events to the given channel. -func (p *testTxPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool) event.Subscription { - return p.txFeed.Subscribe(ch) -} - -// IsPrivateTxHash always returns false in tests -func (p *testTxPool) IsPrivateTxHash(hash common.Hash) bool { - return false -} - -// testHandler is a live implementation of the Ethereum protocol handler, just -// preinitialized with some sane testing defaults and the transaction pool mocked -// out. -type testHandler struct { - db ethdb.Database - chain *core.BlockChain - txpool *testTxPool - handler *handler -} - -// newTestHandler creates a new handler for testing purposes with no blocks. -func newTestHandler() *testHandler { - return newTestHandlerWithBlocks(0) -} - -// newTestHandlerWithBlocks creates a new handler for testing purposes, with a -// given number of initial blocks. -func newTestHandlerWithBlocks(blocks int) *testHandler { - // Create a database pre-initialize with a genesis block - db := rawdb.NewMemoryDatabase() - gspec := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}}, - } - chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - - _, bs, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), blocks, nil) - if _, err := chain.InsertChain(bs); err != nil { - panic(err) - } - txpool := newTestTxPool() - - handler, _ := newHandler(&handlerConfig{ - Database: db, - Chain: chain, - TxPool: txpool, - Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()), - Network: 1, - Sync: downloader.SnapSync, - BloomCache: 1, - }) - handler.Start(1000) - - return &testHandler{ - db: db, - chain: chain, - txpool: txpool, - handler: handler, - } -} - -// close tears down the handler and all its internal constructs. -func (b *testHandler) close() { - b.handler.Stop() - b.chain.Stop() -} diff --git a/builder/eth/peer.go b/builder/eth/peer.go deleted file mode 100644 index 761877771..000000000 --- a/builder/eth/peer.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 eth - -import ( - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" -) - -// ethPeerInfo represents a short summary of the `eth` sub-protocol metadata known -// about a connected peer. -type ethPeerInfo struct { - Version uint `json:"version"` // Ethereum protocol version negotiated -} - -// ethPeer is a wrapper around eth.Peer to maintain a few extra metadata. -type ethPeer struct { - *eth.Peer - snapExt *snapPeer // Satellite `snap` connection -} - -// info gathers and returns some `eth` protocol metadata known about a peer. -func (p *ethPeer) info() *ethPeerInfo { - return ðPeerInfo{ - Version: p.Version(), - } -} - -// snapPeerInfo represents a short summary of the `snap` sub-protocol metadata known -// about a connected peer. -type snapPeerInfo struct { - Version uint `json:"version"` // Snapshot protocol version negotiated -} - -// snapPeer is a wrapper around snap.Peer to maintain a few extra metadata. -type snapPeer struct { - *snap.Peer -} - -// info gathers and returns some `snap` protocol metadata known about a peer. -func (p *snapPeer) info() *snapPeerInfo { - return &snapPeerInfo{ - Version: p.Version(), - } -} diff --git a/builder/eth/peerset.go b/builder/eth/peerset.go deleted file mode 100644 index c0c11e3e8..000000000 --- a/builder/eth/peerset.go +++ /dev/null @@ -1,273 +0,0 @@ -// 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 eth - -import ( - "errors" - "fmt" - "math/big" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/p2p" -) - -var ( - // errPeerSetClosed is returned if a peer is attempted to be added or removed - // from the peer set after it has been terminated. - errPeerSetClosed = errors.New("peerset closed") - - // errPeerAlreadyRegistered is returned if a peer is attempted to be added - // to the peer set, but one with the same id already exists. - errPeerAlreadyRegistered = errors.New("peer already registered") - - // errPeerNotRegistered is returned if a peer is attempted to be removed from - // a peer set, but no peer with the given id exists. - errPeerNotRegistered = errors.New("peer not registered") - - // errSnapWithoutEth is returned if a peer attempts to connect only on the - // snap protocol without advertising the eth main protocol. - errSnapWithoutEth = errors.New("peer connected on snap without compatible eth support") -) - -// peerSet represents the collection of active peers currently participating in -// the `eth` protocol, with or without the `snap` extension. -type peerSet struct { - peers map[string]*ethPeer // Peers connected on the `eth` protocol - snapPeers int // Number of `snap` compatible peers for connection prioritization - - snapWait map[string]chan *snap.Peer // Peers connected on `eth` waiting for their snap extension - snapPend map[string]*snap.Peer // Peers connected on the `snap` protocol, but not yet on `eth` - - lock sync.RWMutex - closed bool - quitCh chan struct{} // Quit channel to signal termination -} - -// newPeerSet creates a new peer set to track the active participants. -func newPeerSet() *peerSet { - return &peerSet{ - peers: make(map[string]*ethPeer), - snapWait: make(map[string]chan *snap.Peer), - snapPend: make(map[string]*snap.Peer), - quitCh: make(chan struct{}), - } -} - -// registerSnapExtension unblocks an already connected `eth` peer waiting for its -// `snap` extension, or if no such peer exists, tracks the extension for the time -// being until the `eth` main protocol starts looking for it. -func (ps *peerSet) registerSnapExtension(peer *snap.Peer) error { - // Reject the peer if it advertises `snap` without `eth` as `snap` is only a - // satellite protocol meaningful with the chain selection of `eth` - if !peer.RunningCap(eth.ProtocolName, eth.ProtocolVersions) { - return fmt.Errorf("%w: have %v", errSnapWithoutEth, peer.Caps()) - } - // Ensure nobody can double connect - ps.lock.Lock() - defer ps.lock.Unlock() - - id := peer.ID() - if _, ok := ps.peers[id]; ok { - return errPeerAlreadyRegistered // avoid connections with the same id as existing ones - } - if _, ok := ps.snapPend[id]; ok { - return errPeerAlreadyRegistered // avoid connections with the same id as pending ones - } - // Inject the peer into an `eth` counterpart is available, otherwise save for later - if wait, ok := ps.snapWait[id]; ok { - delete(ps.snapWait, id) - wait <- peer - return nil - } - ps.snapPend[id] = peer - return nil -} - -// waitExtensions blocks until all satellite protocols are connected and tracked -// by the peerset. -func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) { - // If the peer does not support a compatible `snap`, don't wait - if !peer.RunningCap(snap.ProtocolName, snap.ProtocolVersions) { - return nil, nil - } - // Ensure nobody can double connect - ps.lock.Lock() - - id := peer.ID() - if _, ok := ps.peers[id]; ok { - ps.lock.Unlock() - return nil, errPeerAlreadyRegistered // avoid connections with the same id as existing ones - } - if _, ok := ps.snapWait[id]; ok { - ps.lock.Unlock() - return nil, errPeerAlreadyRegistered // avoid connections with the same id as pending ones - } - // If `snap` already connected, retrieve the peer from the pending set - if snap, ok := ps.snapPend[id]; ok { - delete(ps.snapPend, id) - - ps.lock.Unlock() - return snap, nil - } - // Otherwise wait for `snap` to connect concurrently - wait := make(chan *snap.Peer) - ps.snapWait[id] = wait - ps.lock.Unlock() - - select { - case p := <-wait: - return p, nil - case <-ps.quitCh: - ps.lock.Lock() - delete(ps.snapWait, id) - ps.lock.Unlock() - return nil, errPeerSetClosed - } -} - -// registerPeer injects a new `eth` peer into the working set, or returns an error -// if the peer is already known. -func (ps *peerSet) registerPeer(peer *eth.Peer, ext *snap.Peer) error { - // Start tracking the new peer - ps.lock.Lock() - defer ps.lock.Unlock() - - if ps.closed { - return errPeerSetClosed - } - id := peer.ID() - if _, ok := ps.peers[id]; ok { - return errPeerAlreadyRegistered - } - eth := ðPeer{ - Peer: peer, - } - if ext != nil { - eth.snapExt = &snapPeer{ext} - ps.snapPeers++ - } - ps.peers[id] = eth - return nil -} - -// unregisterPeer removes a remote peer from the active set, disabling any further -// actions to/from that particular entity. -func (ps *peerSet) unregisterPeer(id string) error { - ps.lock.Lock() - defer ps.lock.Unlock() - - peer, ok := ps.peers[id] - if !ok { - return errPeerNotRegistered - } - delete(ps.peers, id) - if peer.snapExt != nil { - ps.snapPeers-- - } - return nil -} - -// peer retrieves the registered peer with the given id. -func (ps *peerSet) peer(id string) *ethPeer { - ps.lock.RLock() - defer ps.lock.RUnlock() - - return ps.peers[id] -} - -// peersWithoutBlock retrieves a list of peers that do not have a given block in -// their set of known hashes so it might be propagated to them. -func (ps *peerSet) peersWithoutBlock(hash common.Hash) []*ethPeer { - ps.lock.RLock() - defer ps.lock.RUnlock() - - list := make([]*ethPeer, 0, len(ps.peers)) - for _, p := range ps.peers { - if !p.KnownBlock(hash) { - list = append(list, p) - } - } - return list -} - -// peersWithoutTransaction retrieves a list of peers that do not have a given -// transaction in their set of known hashes. -func (ps *peerSet) peersWithoutTransaction(hash common.Hash) []*ethPeer { - ps.lock.RLock() - defer ps.lock.RUnlock() - - list := make([]*ethPeer, 0, len(ps.peers)) - for _, p := range ps.peers { - if !p.KnownTransaction(hash) { - list = append(list, p) - } - } - return list -} - -// len returns if the current number of `eth` peers in the set. Since the `snap` -// peers are tied to the existence of an `eth` connection, that will always be a -// subset of `eth`. -func (ps *peerSet) len() int { - ps.lock.RLock() - defer ps.lock.RUnlock() - - return len(ps.peers) -} - -// snapLen returns if the current number of `snap` peers in the set. -func (ps *peerSet) snapLen() int { - ps.lock.RLock() - defer ps.lock.RUnlock() - - return ps.snapPeers -} - -// peerWithHighestTD retrieves the known peer with the currently highest total -// difficulty, but below the given PoS switchover threshold. -func (ps *peerSet) peerWithHighestTD() *eth.Peer { - ps.lock.RLock() - defer ps.lock.RUnlock() - - var ( - bestPeer *eth.Peer - bestTd *big.Int - ) - for _, p := range ps.peers { - if _, td := p.Head(); bestPeer == nil || td.Cmp(bestTd) > 0 { - bestPeer, bestTd = p.Peer, td - } - } - return bestPeer -} - -// close disconnects all peers. -func (ps *peerSet) close() { - ps.lock.Lock() - defer ps.lock.Unlock() - - for _, p := range ps.peers { - p.Disconnect(p2p.DiscQuitting) - } - if !ps.closed { - close(ps.quitCh) - } - ps.closed = true -} diff --git a/builder/eth/protocols/eth/broadcast.go b/builder/eth/protocols/eth/broadcast.go deleted file mode 100644 index ad5395cb8..000000000 --- a/builder/eth/protocols/eth/broadcast.go +++ /dev/null @@ -1,199 +0,0 @@ -// 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 eth - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -const ( - // This is the target size for the packs of transactions or announcements. A - // pack can get larger than this if a single transactions exceeds this size. - maxTxPacketSize = 100 * 1024 -) - -// blockPropagation is a block propagation event, waiting for its turn in the -// broadcast queue. -type blockPropagation struct { - block *types.Block - td *big.Int -} - -// broadcastBlocks is a write loop that multiplexes blocks and block announcements -// to the remote peer. The goal is to have an async writer that does not lock up -// node internals and at the same time rate limits queued data. -func (p *Peer) broadcastBlocks() { - for { - select { - case prop := <-p.queuedBlocks: - if err := p.SendNewBlock(prop.block, prop.td); err != nil { - return - } - p.Log().Trace("Propagated block", "number", prop.block.Number(), "hash", prop.block.Hash(), "td", prop.td) - - case block := <-p.queuedBlockAnns: - if err := p.SendNewBlockHashes([]common.Hash{block.Hash()}, []uint64{block.NumberU64()}); err != nil { - return - } - p.Log().Trace("Announced block", "number", block.Number(), "hash", block.Hash()) - - case <-p.term: - return - } - } -} - -// broadcastTransactions is a write loop that schedules transaction broadcasts -// to the remote peer. The goal is to have an async writer that does not lock up -// node internals and at the same time rate limits queued data. -func (p *Peer) broadcastTransactions() { - var ( - queue []common.Hash // Queue of hashes to broadcast as full transactions - done chan struct{} // Non-nil if background broadcaster is running - fail = make(chan error, 1) // Channel used to receive network error - failed bool // Flag whether a send failed, discard everything onward - ) - for { - // If there's no in-flight broadcast running, check if a new one is needed - if done == nil && len(queue) > 0 { - // Pile transaction until we reach our allowed network limit - var ( - hashesCount uint64 - txs []*types.Transaction - size common.StorageSize - ) - for i := 0; i < len(queue) && size < maxTxPacketSize; i++ { - if tx := p.txpool.Get(queue[i]); tx != nil { - txs = append(txs, tx) - size += common.StorageSize(tx.Size()) - } - hashesCount++ - } - queue = queue[:copy(queue, queue[hashesCount:])] - - // If there's anything available to transfer, fire up an async writer - if len(txs) > 0 { - done = make(chan struct{}) - go func() { - if err := p.SendTransactions(txs); err != nil { - fail <- err - return - } - close(done) - p.Log().Trace("Sent transactions", "count", len(txs)) - }() - } - } - // Transfer goroutine may or may not have been started, listen for events - select { - case hashes := <-p.txBroadcast: - // If the connection failed, discard all transaction events - if failed { - continue - } - // New batch of transactions to be broadcast, queue them (with cap) - queue = append(queue, hashes...) - if len(queue) > maxQueuedTxs { - // Fancy copy and resize to ensure buffer doesn't grow indefinitely - queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxs:])] - } - - case <-done: - done = nil - - case <-fail: - failed = true - - case <-p.term: - return - } - } -} - -// announceTransactions is a write loop that schedules transaction broadcasts -// to the remote peer. The goal is to have an async writer that does not lock up -// node internals and at the same time rate limits queued data. -func (p *Peer) announceTransactions() { - var ( - queue []common.Hash // Queue of hashes to announce as transaction stubs - done chan struct{} // Non-nil if background announcer is running - fail = make(chan error, 1) // Channel used to receive network error - failed bool // Flag whether a send failed, discard everything onward - ) - for { - // If there's no in-flight announce running, check if a new one is needed - if done == nil && len(queue) > 0 { - // Pile transaction hashes until we reach our allowed network limit - var ( - count int - pending []common.Hash - pendingTypes []byte - pendingSizes []uint32 - size common.StorageSize - ) - for count = 0; count < len(queue) && size < maxTxPacketSize; count++ { - if tx := p.txpool.Get(queue[count]); tx != nil { - pending = append(pending, queue[count]) - pendingTypes = append(pendingTypes, tx.Type()) - pendingSizes = append(pendingSizes, uint32(tx.Size())) - size += common.HashLength - } - } - // Shift and trim queue - queue = queue[:copy(queue, queue[count:])] - - // If there's anything available to transfer, fire up an async writer - if len(pending) > 0 { - done = make(chan struct{}) - go func() { - if err := p.sendPooledTransactionHashes(pending, pendingTypes, pendingSizes); err != nil { - fail <- err - return - } - close(done) - p.Log().Trace("Sent transaction announcements", "count", len(pending)) - }() - } - } - // Transfer goroutine may or may not have been started, listen for events - select { - case hashes := <-p.txAnnounce: - // If the connection failed, discard all transaction events - if failed { - continue - } - // New batch of transactions to be broadcast, queue them (with cap) - queue = append(queue, hashes...) - if len(queue) > maxQueuedTxAnns { - // Fancy copy and resize to ensure buffer doesn't grow indefinitely - queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxAnns:])] - } - - case <-done: - done = nil - - case <-fail: - failed = true - - case <-p.term: - return - } - } -} diff --git a/builder/eth/protocols/eth/discovery.go b/builder/eth/protocols/eth/discovery.go deleted file mode 100644 index a7bdd47da..000000000 --- a/builder/eth/protocols/eth/discovery.go +++ /dev/null @@ -1,66 +0,0 @@ -// 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 eth - -import ( - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/rlp" -) - -// enrEntry is the ENR entry which advertises `eth` protocol on the discovery. -type enrEntry struct { - ForkID forkid.ID // Fork identifier per EIP-2124 - - // Ignore additional fields (for forward compatibility). - Rest []rlp.RawValue `rlp:"tail"` -} - -// ENRKey implements enr.Entry. -func (e enrEntry) ENRKey() string { - return "eth" -} - -// StartENRUpdater starts the `eth` ENR updater loop, which listens for chain -// head events and updates the requested node record whenever a fork is passed. -func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) { - var newHead = make(chan core.ChainHeadEvent, 10) - sub := chain.SubscribeChainHeadEvent(newHead) - - go func() { - defer sub.Unsubscribe() - for { - select { - case <-newHead: - ln.Set(currentENREntry(chain)) - case <-sub.Err(): - // Would be nice to sync with Stop, but there is no - // good way to do that. - return - } - } - }() -} - -// currentENREntry constructs an `eth` ENR entry based on the current state of the chain. -func currentENREntry(chain *core.BlockChain) *enrEntry { - head := chain.CurrentHeader() - return &enrEntry{ - ForkID: forkid.NewID(chain.Config(), chain.Genesis(), head.Number.Uint64(), head.Time), - } -} diff --git a/builder/eth/protocols/eth/dispatcher.go b/builder/eth/protocols/eth/dispatcher.go deleted file mode 100644 index ae98820cd..000000000 --- a/builder/eth/protocols/eth/dispatcher.go +++ /dev/null @@ -1,253 +0,0 @@ -// 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 eth - -import ( - "errors" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/p2p" -) - -var ( - // errDisconnected is returned if a request is attempted to be made to a peer - // that was already closed. - errDisconnected = errors.New("disconnected") - - // errDanglingResponse is returned if a response arrives with a request id - // which does not match to any existing pending requests. - errDanglingResponse = errors.New("response to non-existent request") - - // errMismatchingResponseType is returned if the remote peer sent a different - // packet type as a response to a request than what the local node expected. - errMismatchingResponseType = errors.New("mismatching response type") -) - -// Request is a pending request to allow tracking it and delivering a response -// back to the requester on their chosen channel. -type Request struct { - peer *Peer // Peer to which this request belongs for untracking - id uint64 // Request ID to match up replies to - - sink chan *Response // Channel to deliver the response on - cancel chan struct{} // Channel to cancel requests ahead of time - - code uint64 // Message code of the request packet - want uint64 // Message code of the response packet - data interface{} // Data content of the request packet - - Peer string // Demultiplexer if cross-peer requests are batched together - Sent time.Time // Timestamp when the request was sent -} - -// Close aborts an in-flight request. Although there's no way to notify the -// remote peer about the cancellation, this method notifies the dispatcher to -// discard any late responses. -func (r *Request) Close() error { - if r.peer == nil { // Tests mock out the dispatcher, skip internal cancellation - return nil - } - cancelOp := &cancel{ - id: r.id, - fail: make(chan error), - } - select { - case r.peer.reqCancel <- cancelOp: - if err := <-cancelOp.fail; err != nil { - return err - } - close(r.cancel) - return nil - case <-r.peer.term: - return errDisconnected - } -} - -// request is a wrapper around a client Request that has an error channel to -// signal on if sending the request already failed on a network level. -type request struct { - req *Request - fail chan error -} - -// cancel is a maintenance type on the dispatcher to stop tracking a pending -// request. -type cancel struct { - id uint64 // Request ID to stop tracking - fail chan error -} - -// Response is a reply packet to a previously created request. It is delivered -// on the channel assigned by the requester subsystem and contains the original -// request embedded to allow uniquely matching it caller side. -type Response struct { - id uint64 // Request ID to match up this reply to - recv time.Time // Timestamp when the request was received - code uint64 // Response packet type to cross validate with request - - Req *Request // Original request to cross-reference with - Res interface{} // Remote response for the request query - Meta interface{} // Metadata generated locally on the receiver thread - Time time.Duration // Time it took for the request to be served - Done chan error // Channel to signal message handling to the reader -} - -// response is a wrapper around a remote Response that has an error channel to -// signal on if processing the response failed. -type response struct { - res *Response - fail chan error -} - -// dispatchRequest schedules the request to the dispatcher for tracking and -// network serialization, blocking until it's successfully sent. -// -// The returned Request must either be closed before discarding it, or the reply -// must be waited for and the Response's Done channel signalled. -func (p *Peer) dispatchRequest(req *Request) error { - reqOp := &request{ - req: req, - fail: make(chan error), - } - req.cancel = make(chan struct{}) - req.peer = p - req.Peer = p.id - - select { - case p.reqDispatch <- reqOp: - return <-reqOp.fail - case <-p.term: - return errDisconnected - } -} - -// dispatchRequest fulfils a pending request and delivers it to the requested -// sink. -func (p *Peer) dispatchResponse(res *Response, metadata func() interface{}) error { - resOp := &response{ - res: res, - fail: make(chan error), - } - res.recv = time.Now() - res.Done = make(chan error) - - select { - case p.resDispatch <- resOp: - // Ensure the response is accepted by the dispatcher - if err := <-resOp.fail; err != nil { - return nil - } - // Request was accepted, run any postprocessing step to generate metadata - // on the receiver thread, not the sink thread - if metadata != nil { - res.Meta = metadata() - } - // Deliver the filled out response and wait until it's handled. This - // path is a bit funky as Go's select has no order, so if a response - // arrives to an already cancelled request, there's a 50-50% changes - // of picking on channel or the other. To avoid such cases delivering - // the packet upstream, check for cancellation first and only after - // block on delivery. - select { - case <-res.Req.cancel: - return nil // Request cancelled, silently discard response - default: - // Request not yet cancelled, attempt to deliver it, but do watch - // for fresh cancellations too - select { - case res.Req.sink <- res: - return <-res.Done // Response delivered, return any errors - case <-res.Req.cancel: - return nil // Request cancelled, silently discard response - } - } - - case <-p.term: - return errDisconnected - } -} - -// dispatcher is a loop that accepts requests from higher layer packages, pushes -// it to the network and tracks and dispatches the responses back to the original -// requester. -func (p *Peer) dispatcher() { - pending := make(map[uint64]*Request) - - for { - select { - case reqOp := <-p.reqDispatch: - req := reqOp.req - req.Sent = time.Now() - - requestTracker.Track(p.id, p.version, req.code, req.want, req.id) - err := p2p.Send(p.rw, req.code, req.data) - reqOp.fail <- err - - if err == nil { - pending[req.id] = req - } - - case cancelOp := <-p.reqCancel: - // Retrieve the pending request to cancel and short circuit if it - // has already been serviced and is not available anymore - req := pending[cancelOp.id] - if req == nil { - cancelOp.fail <- nil - continue - } - // Stop tracking the request - delete(pending, cancelOp.id) - cancelOp.fail <- nil - - case resOp := <-p.resDispatch: - res := resOp.res - res.Req = pending[res.id] - - // Independent if the request exists or not, track this packet - requestTracker.Fulfil(p.id, p.version, res.code, res.id) - - switch { - case res.Req == nil: - // Response arrived with an untracked ID. Since even cancelled - // requests are tracked until fulfillment, a dangling response - // means the remote peer implements the protocol badly. - resOp.fail <- errDanglingResponse - - case res.Req.want != res.code: - // Response arrived, but it's a different packet type than the - // one expected by the requester. Either the local code is bad, - // or the remote peer send junk. In neither cases can we handle - // the packet. - resOp.fail <- fmt.Errorf("%w: have %d, want %d", errMismatchingResponseType, res.code, res.Req.want) - - default: - // All dispatcher checks passed and the response was initialized - // with the matching request. Signal to the delivery routine that - // it can wait for a handler response and dispatch the data. - res.Time = res.recv.Sub(res.Req.Sent) - resOp.fail <- nil - - // Stop tracking the request, the response dispatcher will deliver - delete(pending, res.id) - } - - case <-p.term: - return - } - } -} diff --git a/builder/eth/protocols/eth/handler.go b/builder/eth/protocols/eth/handler.go deleted file mode 100644 index a9c605adb..000000000 --- a/builder/eth/protocols/eth/handler.go +++ /dev/null @@ -1,215 +0,0 @@ -// 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 eth - -import ( - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/params" -) - -const ( - // softResponseLimit is the target maximum size of replies to data retrievals. - softResponseLimit = 2 * 1024 * 1024 - - // maxHeadersServe is the maximum number of block headers to serve. This number - // is there to limit the number of disk lookups. - maxHeadersServe = 1024 - - // maxBodiesServe is the maximum number of block bodies to serve. This number - // is mostly there to limit the number of disk lookups. With 24KB block sizes - // nowadays, the practical limit will always be softResponseLimit. - maxBodiesServe = 1024 - - // maxReceiptsServe is the maximum number of block receipts to serve. This - // number is mostly there to limit the number of disk lookups. With block - // containing 200+ transactions nowadays, the practical limit will always - // be softResponseLimit. - maxReceiptsServe = 1024 -) - -// Handler is a callback to invoke from an outside runner after the boilerplate -// exchanges have passed. -type Handler func(peer *Peer) error - -// Backend defines the data retrieval methods to serve remote requests and the -// callback methods to invoke on remote deliveries. -type Backend interface { - // Chain retrieves the blockchain object to serve data. - Chain() *core.BlockChain - - // TxPool retrieves the transaction pool object to serve data. - TxPool() TxPool - - // AcceptTxs retrieves whether transaction processing is enabled on the node - // or if inbound transactions should simply be dropped. - AcceptTxs() bool - - // RunPeer is invoked when a peer joins on the `eth` protocol. The handler - // should do any peer maintenance work, handshakes and validations. If all - // is passed, control should be given back to the `handler` to process the - // inbound messages going forward. - RunPeer(peer *Peer, handler Handler) error - - // PeerInfo retrieves all known `eth` information about a peer. - PeerInfo(id enode.ID) interface{} - - // Handle is a callback to be invoked when a data packet is received from - // the remote peer. Only packets not consumed by the protocol handler will - // be forwarded to the backend. - Handle(peer *Peer, packet Packet) error -} - -// TxPool defines the methods needed by the protocol handler to serve transactions. -type TxPool interface { - // Get retrieves the transaction from the local txpool with the given hash. - Get(hash common.Hash) *types.Transaction - - // IsPrivateTxHash indicates if the transaction hash should not - // be broadcast on public channels - IsPrivateTxHash(hash common.Hash) bool -} - -// MakeProtocols constructs the P2P protocol definitions for `eth`. -func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol { - protocols := make([]p2p.Protocol, 0, len(ProtocolVersions)) - for _, version := range ProtocolVersions { - version := version // Closure - - protocols = append(protocols, p2p.Protocol{ - Name: ProtocolName, - Version: version, - Length: protocolLengths[version], - Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - peer := NewPeer(version, p, rw, backend.TxPool()) - defer peer.Close() - - return backend.RunPeer(peer, func(peer *Peer) error { - return Handle(backend, peer) - }) - }, - NodeInfo: func() interface{} { - return nodeInfo(backend.Chain(), network) - }, - PeerInfo: func(id enode.ID) interface{} { - return backend.PeerInfo(id) - }, - Attributes: []enr.Entry{currentENREntry(backend.Chain())}, - DialCandidates: dnsdisc, - }) - } - return protocols -} - -// NodeInfo represents a short summary of the `eth` sub-protocol metadata -// known about the host peer. -type NodeInfo struct { - Network uint64 `json:"network"` // Ethereum network ID (1=Mainnet, Goerli=5) - Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain - Genesis common.Hash `json:"genesis"` // SHA3 hash of the host's genesis block - Config *params.ChainConfig `json:"config"` // Chain configuration for the fork rules - Head common.Hash `json:"head"` // Hex hash of the host's best owned block -} - -// nodeInfo retrieves some `eth` protocol metadata about the running host node. -func nodeInfo(chain *core.BlockChain, network uint64) *NodeInfo { - head := chain.CurrentBlock() - hash := head.Hash() - - return &NodeInfo{ - Network: network, - Difficulty: chain.GetTd(hash, head.Number.Uint64()), - Genesis: chain.Genesis().Hash(), - Config: chain.Config(), - Head: hash, - } -} - -// Handle is invoked whenever an `eth` connection is made that successfully passes -// the protocol handshake. This method will keep processing messages until the -// connection is torn down. -func Handle(backend Backend, peer *Peer) error { - for { - if err := handleMessage(backend, peer); err != nil { - peer.Log().Debug("Message handling failed in `eth`", "err", err) - return err - } - } -} - -type msgHandler func(backend Backend, msg Decoder, peer *Peer) error -type Decoder interface { - Decode(val interface{}) error - Time() time.Time -} - -var eth68 = map[uint64]msgHandler{ - NewBlockHashesMsg: handleNewBlockhashes, - NewBlockMsg: handleNewBlock, - TransactionsMsg: handleTransactions, - NewPooledTransactionHashesMsg: handleNewPooledTransactionHashes, - GetBlockHeadersMsg: handleGetBlockHeaders, - BlockHeadersMsg: handleBlockHeaders, - GetBlockBodiesMsg: handleGetBlockBodies, - BlockBodiesMsg: handleBlockBodies, - GetReceiptsMsg: handleGetReceipts, - ReceiptsMsg: handleReceipts, - GetPooledTransactionsMsg: handleGetPooledTransactions, - PooledTransactionsMsg: handlePooledTransactions, -} - -// handleMessage is invoked whenever an inbound message is received from a remote -// peer. The remote connection is torn down upon returning any error. -func handleMessage(backend Backend, peer *Peer) error { - // Read the next message from the remote peer, and ensure it's fully consumed - msg, err := peer.rw.ReadMsg() - if err != nil { - return err - } - if msg.Size > maxMessageSize { - return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize) - } - defer msg.Discard() - - var handlers = eth68 - - // Track the amount of time it takes to serve the request and run the handler - if metrics.Enabled { - h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code) - defer func(start time.Time) { - sampler := func() metrics.Sample { - return metrics.ResettingSample( - metrics.NewExpDecaySample(1028, 0.015), - ) - } - metrics.GetOrRegisterHistogramLazy(h, nil, sampler).Update(time.Since(start).Microseconds()) - }(time.Now()) - } - if handler := handlers[msg.Code]; handler != nil { - return handler(backend, msg, peer) - } - return fmt.Errorf("%w: %v", errInvalidMsgCode, msg.Code) -} diff --git a/builder/eth/protocols/eth/handler_test.go b/builder/eth/protocols/eth/handler_test.go deleted file mode 100644 index fdf551ef2..000000000 --- a/builder/eth/protocols/eth/handler_test.go +++ /dev/null @@ -1,501 +0,0 @@ -// 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 eth - -import ( - "math" - "math/big" - "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/txpool/legacypool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" -) - -var ( - // testKey is a private key to use for funding a tester account. - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - - // testAddr is the Ethereum address of the tester account. - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) -) - -func u64(val uint64) *uint64 { return &val } - -// testBackend is a mock implementation of the live Ethereum message handler. Its -// purpose is to allow testing the request/reply workflows and wire serialization -// in the `eth` protocol without actually doing any data processing. -type testBackend struct { - db ethdb.Database - chain *core.BlockChain - txpool *txpool.TxPool -} - -// newTestBackend creates an empty chain and wraps it into a mock backend. -func newTestBackend(blocks int) *testBackend { - return newTestBackendWithGenerator(blocks, false, nil) -} - -// newTestBackend creates a chain with a number of explicitly defined blocks and -// wraps it into a mock backend. -func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int, *core.BlockGen)) *testBackend { - var ( - // Create a database pre-initialize with a genesis block - db = rawdb.NewMemoryDatabase() - config = params.TestChainConfig - engine consensus.Engine = ethash.NewFaker() - ) - - if shanghai { - config = ¶ms.ChainConfig{ - ChainID: big.NewInt(1), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: nil, - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - ArrowGlacierBlock: big.NewInt(0), - GrayGlacierBlock: big.NewInt(0), - MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: u64(0), - TerminalTotalDifficulty: big.NewInt(0), - TerminalTotalDifficultyPassed: true, - Ethash: new(params.EthashConfig), - } - engine = beacon.NewFaker() - } - - gspec := &core.Genesis{ - Config: config, - Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}}, - } - chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil) - - _, bs, _ := core.GenerateChainWithGenesis(gspec, engine, blocks, generator) - if _, err := chain.InsertChain(bs); err != nil { - panic(err) - } - for _, block := range bs { - chain.TrieDB().Commit(block.Root(), false) - } - txconfig := legacypool.DefaultConfig - txconfig.Journal = "" // Don't litter the disk with test journals - - pool := legacypool.New(txconfig, chain) - txpool, _ := txpool.New(txconfig.PriceLimit, chain, []txpool.SubPool{pool}) - - return &testBackend{ - db: db, - chain: chain, - txpool: txpool, - } -} - -// close tears down the transaction pool and chain behind the mock backend. -func (b *testBackend) close() { - b.txpool.Close() - b.chain.Stop() -} - -func (b *testBackend) Chain() *core.BlockChain { return b.chain } -func (b *testBackend) TxPool() TxPool { return b.txpool } - -func (b *testBackend) RunPeer(peer *Peer, handler Handler) error { - // Normally the backend would do peer maintenance and handshakes. All that - // is omitted and we will just give control back to the handler. - return handler(peer) -} -func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") } - -func (b *testBackend) AcceptTxs() bool { - panic("data processing tests should be done in the handler package") -} -func (b *testBackend) Handle(*Peer, Packet) error { - panic("data processing tests should be done in the handler package") -} - -// Tests that block headers can be retrieved from a remote chain based on user queries. -func TestGetBlockHeaders68(t *testing.T) { testGetBlockHeaders(t, ETH68) } - -func testGetBlockHeaders(t *testing.T, protocol uint) { - t.Parallel() - - backend := newTestBackend(maxHeadersServe + 15) - defer backend.close() - - peer, _ := newTestPeer("peer", protocol, backend) - defer peer.close() - - // Create a "random" unknown hash for testing - var unknown common.Hash - for i := range unknown { - unknown[i] = byte(i) - } - getHashes := func(from, limit uint64) (hashes []common.Hash) { - for i := uint64(0); i < limit; i++ { - hashes = append(hashes, backend.chain.GetCanonicalHash(from-1-i)) - } - return hashes - } - // Create a batch of tests for various scenarios - limit := uint64(maxHeadersServe) - tests := []struct { - query *GetBlockHeadersRequest // The query to execute for header retrieval - expect []common.Hash // The hashes of the block whose headers are expected - }{ - // A single random block should be retrievable by hash - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, - []common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()}, - }, - // A single random block should be retrievable by number - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 1}, - []common.Hash{backend.chain.GetBlockByNumber(limit / 2).Hash()}, - }, - // Multiple headers should be retrievable in both directions - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3}, - []common.Hash{ - backend.chain.GetBlockByNumber(limit / 2).Hash(), - backend.chain.GetBlockByNumber(limit/2 + 1).Hash(), - backend.chain.GetBlockByNumber(limit/2 + 2).Hash(), - }, - }, { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, - []common.Hash{ - backend.chain.GetBlockByNumber(limit / 2).Hash(), - backend.chain.GetBlockByNumber(limit/2 - 1).Hash(), - backend.chain.GetBlockByNumber(limit/2 - 2).Hash(), - }, - }, - // Multiple headers with skip lists should be retrievable - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, - []common.Hash{ - backend.chain.GetBlockByNumber(limit / 2).Hash(), - backend.chain.GetBlockByNumber(limit/2 + 4).Hash(), - backend.chain.GetBlockByNumber(limit/2 + 8).Hash(), - }, - }, { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, - []common.Hash{ - backend.chain.GetBlockByNumber(limit / 2).Hash(), - backend.chain.GetBlockByNumber(limit/2 - 4).Hash(), - backend.chain.GetBlockByNumber(limit/2 - 8).Hash(), - }, - }, - // The chain endpoints should be retrievable - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 0}, Amount: 1}, - []common.Hash{backend.chain.GetBlockByNumber(0).Hash()}, - }, - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 1}, - []common.Hash{backend.chain.CurrentBlock().Hash()}, - }, - { // If the peer requests a bit into the future, we deliver what we have - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64()}, Amount: 10}, - []common.Hash{backend.chain.CurrentBlock().Hash()}, - }, - // Ensure protocol limits are honored - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true}, - getHashes(backend.chain.CurrentBlock().Number.Uint64(), limit), - }, - // Check that requesting more than available is handled gracefully - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3}, - []common.Hash{ - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64()).Hash(), - }, - }, { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, - []common.Hash{ - backend.chain.GetBlockByNumber(4).Hash(), - backend.chain.GetBlockByNumber(0).Hash(), - }, - }, - // Check that requesting more than available is handled gracefully, even if mid skip - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3}, - []common.Hash{ - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 4).Hash(), - backend.chain.GetBlockByNumber(backend.chain.CurrentBlock().Number.Uint64() - 1).Hash(), - }, - }, { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, - []common.Hash{ - backend.chain.GetBlockByNumber(4).Hash(), - backend.chain.GetBlockByNumber(1).Hash(), - }, - }, - // Check a corner case where requesting more can iterate past the endpoints - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 2}, Amount: 5, Reverse: true}, - []common.Hash{ - backend.chain.GetBlockByNumber(2).Hash(), - backend.chain.GetBlockByNumber(1).Hash(), - backend.chain.GetBlockByNumber(0).Hash(), - }, - }, - // Check a corner case where skipping overflow loops back into the chain start - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, - []common.Hash{ - backend.chain.GetBlockByNumber(3).Hash(), - }, - }, - // Check a corner case where skipping overflow loops back to the same header - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: backend.chain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, - []common.Hash{ - backend.chain.GetBlockByNumber(1).Hash(), - }, - }, - // Check that non existing headers aren't returned - { - &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: unknown}, Amount: 1}, - []common.Hash{}, - }, { - &GetBlockHeadersRequest{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().Number.Uint64() + 1}, Amount: 1}, - []common.Hash{}, - }, - } - // Run each of the tests and verify the results against the chain - for i, tt := range tests { - // Collect the headers to expect in the response - var headers []*types.Header - for _, hash := range tt.expect { - headers = append(headers, backend.chain.GetBlockByHash(hash).Header()) - } - // Send the hash request and verify the response - p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{ - RequestId: 123, - GetBlockHeadersRequest: tt.query, - }) - if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, &BlockHeadersPacket{ - RequestId: 123, - BlockHeadersRequest: headers, - }); err != nil { - t.Errorf("test %d: headers mismatch: %v", i, err) - } - // If the test used number origins, repeat with hashes as the too - if tt.query.Origin.Hash == (common.Hash{}) { - if origin := backend.chain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { - tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0 - - p2p.Send(peer.app, GetBlockHeadersMsg, &GetBlockHeadersPacket{ - RequestId: 456, - GetBlockHeadersRequest: tt.query, - }) - expected := &BlockHeadersPacket{RequestId: 456, BlockHeadersRequest: headers} - if err := p2p.ExpectMsg(peer.app, BlockHeadersMsg, expected); err != nil { - t.Errorf("test %d by hash: headers mismatch: %v", i, err) - } - } - } - } -} - -// Tests that block contents can be retrieved from a remote chain based on their hashes. -func TestGetBlockBodies68(t *testing.T) { testGetBlockBodies(t, ETH68) } - -func testGetBlockBodies(t *testing.T, protocol uint) { - t.Parallel() - - gen := func(n int, g *core.BlockGen) { - if n%2 == 0 { - w := &types.Withdrawal{ - Address: common.Address{0xaa}, - Amount: 42, - } - g.AddWithdrawal(w) - } - } - - backend := newTestBackendWithGenerator(maxBodiesServe+15, true, gen) - defer backend.close() - - peer, _ := newTestPeer("peer", protocol, backend) - defer peer.close() - - // Create a batch of tests for various scenarios - limit := maxBodiesServe - tests := []struct { - random int // Number of blocks to fetch randomly from the chain - explicit []common.Hash // Explicitly requested blocks - available []bool // Availability of explicitly requested blocks - expected int // Total number of existing blocks to expect - }{ - {1, nil, nil, 1}, // A single random block should be retrievable - {10, nil, nil, 10}, // Multiple random blocks should be retrievable - {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable - {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned - {0, []common.Hash{backend.chain.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable - {0, []common.Hash{backend.chain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable - {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned - - // Existing and non-existing blocks interleaved should not cause problems - {0, []common.Hash{ - {}, - backend.chain.GetBlockByNumber(1).Hash(), - {}, - backend.chain.GetBlockByNumber(10).Hash(), - {}, - backend.chain.GetBlockByNumber(100).Hash(), - {}, - }, []bool{false, true, false, true, false, true, false}, 3}, - } - // Run each of the tests and verify the results against the chain - for i, tt := range tests { - // Collect the hashes to request, and the response to expect - var ( - hashes []common.Hash - bodies []*BlockBody - seen = make(map[int64]bool) - ) - for j := 0; j < tt.random; j++ { - for { - num := rand.Int63n(int64(backend.chain.CurrentBlock().Number.Uint64())) - if !seen[num] { - seen[num] = true - - block := backend.chain.GetBlockByNumber(uint64(num)) - hashes = append(hashes, block.Hash()) - if len(bodies) < tt.expected { - bodies = append(bodies, &BlockBody{Transactions: block.Transactions(), Uncles: block.Uncles(), Withdrawals: block.Withdrawals()}) - } - break - } - } - } - for j, hash := range tt.explicit { - hashes = append(hashes, hash) - if tt.available[j] && len(bodies) < tt.expected { - block := backend.chain.GetBlockByHash(hash) - bodies = append(bodies, &BlockBody{Transactions: block.Transactions(), Uncles: block.Uncles(), Withdrawals: block.Withdrawals()}) - } - } - - // Send the hash request and verify the response - p2p.Send(peer.app, GetBlockBodiesMsg, &GetBlockBodiesPacket{ - RequestId: 123, - GetBlockBodiesRequest: hashes, - }) - if err := p2p.ExpectMsg(peer.app, BlockBodiesMsg, &BlockBodiesPacket{ - RequestId: 123, - BlockBodiesResponse: bodies, - }); err != nil { - t.Fatalf("test %d: bodies mismatch: %v", i, err) - } - } -} - -// Tests that the transaction receipts can be retrieved based on hashes. -func TestGetBlockReceipts68(t *testing.T) { testGetBlockReceipts(t, ETH68) } - -func testGetBlockReceipts(t *testing.T, protocol uint) { - t.Parallel() - - // Define three accounts to simulate transactions with - acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") - acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") - acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) - acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) - - signer := types.HomesteadSigner{} - // Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test) - generator := func(i int, block *core.BlockGen) { - switch i { - case 0: - // In block 1, the test bank sends account #1 some ether. - tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(10_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) - block.AddTx(tx) - case 1: - // In block 2, the test bank sends some more ether to account #1. - // acc1Addr passes it on to account #2. - tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), acc1Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, testKey) - tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1_000_000_000_000_000), params.TxGas, block.BaseFee(), nil), signer, acc1Key) - block.AddTx(tx1) - block.AddTx(tx2) - case 2: - // Block 3 is empty but was mined by account #2. - block.SetCoinbase(acc2Addr) - block.SetExtra([]byte("yeehaw")) - case 3: - // Block 4 includes blocks 2 and 3 as uncle headers (with modified extra data). - b2 := block.PrevBlock(1).Header() - b2.Extra = []byte("foo") - block.AddUncle(b2) - b3 := block.PrevBlock(2).Header() - b3.Extra = []byte("foo") - block.AddUncle(b3) - } - } - // Assemble the test environment - backend := newTestBackendWithGenerator(4, false, generator) - defer backend.close() - - peer, _ := newTestPeer("peer", protocol, backend) - defer peer.close() - - // Collect the hashes to request, and the response to expect - var ( - hashes []common.Hash - receipts [][]*types.Receipt - ) - for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { - block := backend.chain.GetBlockByNumber(i) - - hashes = append(hashes, block.Hash()) - receipts = append(receipts, backend.chain.GetReceiptsByHash(block.Hash())) - } - // Send the hash request and verify the response - p2p.Send(peer.app, GetReceiptsMsg, &GetReceiptsPacket{ - RequestId: 123, - GetReceiptsRequest: hashes, - }) - if err := p2p.ExpectMsg(peer.app, ReceiptsMsg, &ReceiptsPacket{ - RequestId: 123, - ReceiptsResponse: receipts, - }); err != nil { - t.Errorf("receipts mismatch: %v", err) - } -} diff --git a/builder/eth/protocols/eth/handlers.go b/builder/eth/protocols/eth/handlers.go deleted file mode 100644 index 0275708a6..000000000 --- a/builder/eth/protocols/eth/handlers.go +++ /dev/null @@ -1,484 +0,0 @@ -// 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 eth - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" -) - -func handleGetBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { - // Decode the complex header query - var query GetBlockHeadersPacket - if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - response := ServiceGetBlockHeadersQuery(backend.Chain(), query.GetBlockHeadersRequest, peer) - return peer.ReplyBlockHeadersRLP(query.RequestId, response) -} - -// ServiceGetBlockHeadersQuery assembles the response to a header query. It is -// exposed to allow external packages to test protocol behavior. -func ServiceGetBlockHeadersQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue { - if query.Skip == 0 { - // The fast path: when the request is for a contiguous segment of headers. - return serviceContiguousBlockHeaderQuery(chain, query) - } else { - return serviceNonContiguousBlockHeaderQuery(chain, query, peer) - } -} - -func serviceNonContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest, peer *Peer) []rlp.RawValue { - hashMode := query.Origin.Hash != (common.Hash{}) - first := true - maxNonCanonical := uint64(100) - - // Gather headers until the fetch or network limits is reached - var ( - bytes common.StorageSize - headers []rlp.RawValue - unknown bool - lookups int - ) - for !unknown && len(headers) < int(query.Amount) && bytes < softResponseLimit && - len(headers) < maxHeadersServe && lookups < 2*maxHeadersServe { - lookups++ - // Retrieve the next header satisfying the query - var origin *types.Header - if hashMode { - if first { - first = false - origin = chain.GetHeaderByHash(query.Origin.Hash) - if origin != nil { - query.Origin.Number = origin.Number.Uint64() - } - } else { - origin = chain.GetHeader(query.Origin.Hash, query.Origin.Number) - } - } else { - origin = chain.GetHeaderByNumber(query.Origin.Number) - } - if origin == nil { - break - } - if rlpData, err := rlp.EncodeToBytes(origin); err != nil { - log.Crit("Unable to encode our own headers", "err", err) - } else { - headers = append(headers, rlp.RawValue(rlpData)) - bytes += common.StorageSize(len(rlpData)) - } - // Advance to the next header of the query - switch { - case hashMode && query.Reverse: - // Hash based traversal towards the genesis block - ancestor := query.Skip + 1 - if ancestor == 0 { - unknown = true - } else { - query.Origin.Hash, query.Origin.Number = chain.GetAncestor(query.Origin.Hash, query.Origin.Number, ancestor, &maxNonCanonical) - unknown = (query.Origin.Hash == common.Hash{}) - } - case hashMode && !query.Reverse: - // Hash based traversal towards the leaf block - var ( - current = origin.Number.Uint64() - next = current + query.Skip + 1 - ) - if next <= current { - infos, _ := json.MarshalIndent(peer.Peer.Info(), "", " ") - peer.Log().Warn("GetBlockHeaders skip overflow attack", "current", current, "skip", query.Skip, "next", next, "attacker", infos) - unknown = true - } else { - if header := chain.GetHeaderByNumber(next); header != nil { - nextHash := header.Hash() - expOldHash, _ := chain.GetAncestor(nextHash, next, query.Skip+1, &maxNonCanonical) - if expOldHash == query.Origin.Hash { - query.Origin.Hash, query.Origin.Number = nextHash, next - } else { - unknown = true - } - } else { - unknown = true - } - } - case query.Reverse: - // Number based traversal towards the genesis block - if query.Origin.Number >= query.Skip+1 { - query.Origin.Number -= query.Skip + 1 - } else { - unknown = true - } - - case !query.Reverse: - // Number based traversal towards the leaf block - query.Origin.Number += query.Skip + 1 - } - } - return headers -} - -func serviceContiguousBlockHeaderQuery(chain *core.BlockChain, query *GetBlockHeadersRequest) []rlp.RawValue { - count := query.Amount - if count > maxHeadersServe { - count = maxHeadersServe - } - if query.Origin.Hash == (common.Hash{}) { - // Number mode, just return the canon chain segment. The backend - // delivers in [N, N-1, N-2..] descending order, so we need to - // accommodate for that. - from := query.Origin.Number - if !query.Reverse { - from = from + count - 1 - } - headers := chain.GetHeadersFrom(from, count) - if !query.Reverse { - for i, j := 0, len(headers)-1; i < j; i, j = i+1, j-1 { - headers[i], headers[j] = headers[j], headers[i] - } - } - return headers - } - // Hash mode. - var ( - headers []rlp.RawValue - hash = query.Origin.Hash - header = chain.GetHeaderByHash(hash) - ) - if header != nil { - rlpData, _ := rlp.EncodeToBytes(header) - headers = append(headers, rlpData) - } else { - // We don't even have the origin header - return headers - } - num := header.Number.Uint64() - if !query.Reverse { - // Theoretically, we are tasked to deliver header by hash H, and onwards. - // However, if H is not canon, we will be unable to deliver any descendants of - // H. - if canonHash := chain.GetCanonicalHash(num); canonHash != hash { - // Not canon, we can't deliver descendants - return headers - } - descendants := chain.GetHeadersFrom(num+count-1, count-1) - for i, j := 0, len(descendants)-1; i < j; i, j = i+1, j-1 { - descendants[i], descendants[j] = descendants[j], descendants[i] - } - headers = append(headers, descendants...) - return headers - } - { // Last mode: deliver ancestors of H - for i := uint64(1); header != nil && i < count; i++ { - header = chain.GetHeaderByHash(header.ParentHash) - if header == nil { - break - } - rlpData, _ := rlp.EncodeToBytes(header) - headers = append(headers, rlpData) - } - return headers - } -} - -func handleGetBlockBodies(backend Backend, msg Decoder, peer *Peer) error { - // Decode the block body retrieval message - var query GetBlockBodiesPacket - if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - response := ServiceGetBlockBodiesQuery(backend.Chain(), query.GetBlockBodiesRequest) - return peer.ReplyBlockBodiesRLP(query.RequestId, response) -} - -// ServiceGetBlockBodiesQuery assembles the response to a body query. It is -// exposed to allow external packages to test protocol behavior. -func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequest) []rlp.RawValue { - // Gather blocks until the fetch or network limits is reached - var ( - bytes int - bodies []rlp.RawValue - ) - for lookups, hash := range query { - if bytes >= softResponseLimit || len(bodies) >= maxBodiesServe || - lookups >= 2*maxBodiesServe { - break - } - if data := chain.GetBodyRLP(hash); len(data) != 0 { - bodies = append(bodies, data) - bytes += len(data) - } - } - return bodies -} - -func handleGetReceipts(backend Backend, msg Decoder, peer *Peer) error { - // Decode the block receipts retrieval message - var query GetReceiptsPacket - if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - response := ServiceGetReceiptsQuery(backend.Chain(), query.GetReceiptsRequest) - return peer.ReplyReceiptsRLP(query.RequestId, response) -} - -// ServiceGetReceiptsQuery assembles the response to a receipt query. It is -// exposed to allow external packages to test protocol behavior. -func ServiceGetReceiptsQuery(chain *core.BlockChain, query GetReceiptsRequest) []rlp.RawValue { - // Gather state data until the fetch or network limits is reached - var ( - bytes int - receipts []rlp.RawValue - ) - for lookups, hash := range query { - if bytes >= softResponseLimit || len(receipts) >= maxReceiptsServe || - lookups >= 2*maxReceiptsServe { - break - } - // Retrieve the requested block's receipts - results := chain.GetReceiptsByHash(hash) - if results == nil { - if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { - continue - } - } - // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(results); err != nil { - log.Error("Failed to encode receipt", "err", err) - } else { - receipts = append(receipts, encoded) - bytes += len(encoded) - } - } - return receipts -} - -func handleNewBlockhashes(backend Backend, msg Decoder, peer *Peer) error { - // A batch of new block announcements just arrived - ann := new(NewBlockHashesPacket) - if err := msg.Decode(ann); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Mark the hashes as present at the remote node - for _, block := range *ann { - peer.markBlock(block.Hash) - } - // Deliver them all to the backend for queuing - return backend.Handle(peer, ann) -} - -func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error { - // Retrieve and decode the propagated block - ann := new(NewBlockPacket) - if err := msg.Decode(ann); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - if err := ann.sanityCheck(); err != nil { - return err - } - if hash := types.CalcUncleHash(ann.Block.Uncles()); hash != ann.Block.UncleHash() { - log.Warn("Propagated block has invalid uncles", "have", hash, "exp", ann.Block.UncleHash()) - return nil // TODO(karalabe): return error eventually, but wait a few releases - } - if hash := types.DeriveSha(ann.Block.Transactions(), trie.NewStackTrie(nil)); hash != ann.Block.TxHash() { - log.Warn("Propagated block has invalid body", "have", hash, "exp", ann.Block.TxHash()) - return nil // TODO(karalabe): return error eventually, but wait a few releases - } - ann.Block.ReceivedAt = msg.Time() - ann.Block.ReceivedFrom = peer - - // Mark the peer as owning the block - peer.markBlock(ann.Block.Hash()) - - return backend.Handle(peer, ann) -} - -func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error { - // A batch of headers arrived to one of our previous requests - res := new(BlockHeadersPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - metadata := func() interface{} { - hashes := make([]common.Hash, len(res.BlockHeadersRequest)) - for i, header := range res.BlockHeadersRequest { - hashes[i] = header.Hash() - } - return hashes - } - return peer.dispatchResponse(&Response{ - id: res.RequestId, - code: BlockHeadersMsg, - Res: &res.BlockHeadersRequest, - }, metadata) -} - -func handleBlockBodies(backend Backend, msg Decoder, peer *Peer) error { - // A batch of block bodies arrived to one of our previous requests - res := new(BlockBodiesPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - metadata := func() interface{} { - var ( - txsHashes = make([]common.Hash, len(res.BlockBodiesResponse)) - uncleHashes = make([]common.Hash, len(res.BlockBodiesResponse)) - withdrawalHashes = make([]common.Hash, len(res.BlockBodiesResponse)) - ) - hasher := trie.NewStackTrie(nil) - for i, body := range res.BlockBodiesResponse { - txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher) - uncleHashes[i] = types.CalcUncleHash(body.Uncles) - if body.Withdrawals != nil { - withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher) - } - } - return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes} - } - return peer.dispatchResponse(&Response{ - id: res.RequestId, - code: BlockBodiesMsg, - Res: &res.BlockBodiesResponse, - }, metadata) -} - -func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { - // A batch of receipts arrived to one of our previous requests - res := new(ReceiptsPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - metadata := func() interface{} { - hasher := trie.NewStackTrie(nil) - hashes := make([]common.Hash, len(res.ReceiptsResponse)) - for i, receipt := range res.ReceiptsResponse { - hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher) - } - return hashes - } - return peer.dispatchResponse(&Response{ - id: res.RequestId, - code: ReceiptsMsg, - Res: &res.ReceiptsResponse, - }, metadata) -} - -func handleNewPooledTransactionHashes(backend Backend, msg Decoder, peer *Peer) error { - // New transaction announcement arrived, make sure we have - // a valid and fresh chain to handle them - if !backend.AcceptTxs() { - return nil - } - ann := new(NewPooledTransactionHashesPacket) - if err := msg.Decode(ann); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - if len(ann.Hashes) != len(ann.Types) || len(ann.Hashes) != len(ann.Sizes) { - return fmt.Errorf("%w: message %v: invalid len of fields: %v %v %v", errDecode, msg, len(ann.Hashes), len(ann.Types), len(ann.Sizes)) - } - // Schedule all the unknown hashes for retrieval - for _, hash := range ann.Hashes { - peer.markTransaction(hash) - } - return backend.Handle(peer, ann) -} - -func handleGetPooledTransactions(backend Backend, msg Decoder, peer *Peer) error { - // Decode the pooled transactions retrieval message - var query GetPooledTransactionsPacket - if err := msg.Decode(&query); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - hashes, txs := answerGetPooledTransactions(backend, query.GetPooledTransactionsRequest) - return peer.ReplyPooledTransactionsRLP(query.RequestId, hashes, txs) -} - -func answerGetPooledTransactions(backend Backend, query GetPooledTransactionsRequest) ([]common.Hash, []rlp.RawValue) { - // Gather transactions until the fetch or network limits is reached - var ( - bytes int - hashes []common.Hash - txs []rlp.RawValue - ) - for _, hash := range query { - if bytes >= softResponseLimit { - break - } - // Retrieve the requested transaction, skipping if unknown to us - tx := backend.TxPool().Get(hash) - if tx == nil { - continue - } - // If known, encode and queue for response packet - if encoded, err := rlp.EncodeToBytes(tx); err != nil { - log.Error("Failed to encode transaction", "err", err) - } else { - hashes = append(hashes, hash) - txs = append(txs, encoded) - bytes += len(encoded) - } - } - return hashes, txs -} - -func handleTransactions(backend Backend, msg Decoder, peer *Peer) error { - // Transactions arrived, make sure we have a valid and fresh chain to handle them - if !backend.AcceptTxs() { - return nil - } - // Transactions can be processed, parse all of them and deliver to the pool - var txs TransactionsPacket - if err := msg.Decode(&txs); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - for i, tx := range txs { - // Validate and mark the remote transaction - if tx == nil { - return fmt.Errorf("%w: transaction %d is nil", errDecode, i) - } - peer.markTransaction(tx.Hash()) - } - return backend.Handle(peer, &txs) -} - -func handlePooledTransactions(backend Backend, msg Decoder, peer *Peer) error { - // Transactions arrived, make sure we have a valid and fresh chain to handle them - if !backend.AcceptTxs() { - return nil - } - // Transactions can be processed, parse all of them and deliver to the pool - var txs PooledTransactionsPacket - if err := msg.Decode(&txs); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - for i, tx := range txs.PooledTransactionsResponse { - // Validate and mark the remote transaction - if tx == nil { - return fmt.Errorf("%w: transaction %d is nil", errDecode, i) - } - peer.markTransaction(tx.Hash()) - } - requestTracker.Fulfil(peer.id, peer.version, PooledTransactionsMsg, txs.RequestId) - - return backend.Handle(peer, &txs.PooledTransactionsResponse) -} diff --git a/builder/eth/protocols/eth/handshake.go b/builder/eth/protocols/eth/handshake.go deleted file mode 100644 index ea16a85b1..000000000 --- a/builder/eth/protocols/eth/handshake.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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 eth - -import ( - "errors" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/p2p" -) - -const ( - // handshakeTimeout is the maximum allowed time for the `eth` handshake to - // complete before dropping the connection.= as malicious. - handshakeTimeout = 5 * time.Second -) - -// Handshake executes the eth protocol handshake, negotiating version number, -// network IDs, difficulties, head and genesis blocks. -func (p *Peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error { - // Send out own handshake in a new thread - errc := make(chan error, 2) - - var status StatusPacket // safe to read after two values have been received from errc - - go func() { - errc <- p2p.Send(p.rw, StatusMsg, &StatusPacket{ - ProtocolVersion: uint32(p.version), - NetworkID: network, - TD: td, - Head: head, - Genesis: genesis, - ForkID: forkID, - }) - }() - go func() { - errc <- p.readStatus(network, &status, genesis, forkFilter) - }() - timeout := time.NewTimer(handshakeTimeout) - defer timeout.Stop() - for i := 0; i < 2; i++ { - select { - case err := <-errc: - if err != nil { - markError(p, err) - return err - } - case <-timeout.C: - markError(p, p2p.DiscReadTimeout) - return p2p.DiscReadTimeout - } - } - p.td, p.head = status.TD, status.Head - - // TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times - // larger, it will still fit within 100 bits - if tdlen := p.td.BitLen(); tdlen > 100 { - return fmt.Errorf("too large total difficulty: bitlen %d", tdlen) - } - return nil -} - -// readStatus reads the remote handshake message. -func (p *Peer) readStatus(network uint64, status *StatusPacket, genesis common.Hash, forkFilter forkid.Filter) error { - msg, err := p.rw.ReadMsg() - if err != nil { - return err - } - if msg.Code != StatusMsg { - return fmt.Errorf("%w: first msg has code %x (!= %x)", errNoStatusMsg, msg.Code, StatusMsg) - } - if msg.Size > maxMessageSize { - return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize) - } - // Decode the handshake and make sure everything matches - if err := msg.Decode(&status); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - if status.NetworkID != network { - return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, network) - } - if uint(status.ProtocolVersion) != p.version { - return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version) - } - if status.Genesis != genesis { - return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis) - } - if err := forkFilter(status.ForkID); err != nil { - return fmt.Errorf("%w: %v", errForkIDRejected, err) - } - return nil -} - -// markError registers the error with the corresponding metric. -func markError(p *Peer, err error) { - if !metrics.Enabled { - return - } - m := meters.get(p.Inbound()) - switch errors.Unwrap(err) { - case errNetworkIDMismatch: - m.networkIDMismatch.Mark(1) - case errProtocolVersionMismatch: - m.protocolVersionMismatch.Mark(1) - case errGenesisMismatch: - m.genesisMismatch.Mark(1) - case errForkIDRejected: - m.forkidRejected.Mark(1) - case p2p.DiscReadTimeout: - m.timeoutError.Mark(1) - default: - m.peerError.Mark(1) - } -} diff --git a/builder/eth/protocols/eth/handshake_test.go b/builder/eth/protocols/eth/handshake_test.go deleted file mode 100644 index b9fd13d86..000000000 --- a/builder/eth/protocols/eth/handshake_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// 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 eth - -import ( - "errors" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// Tests that handshake failures are detected and reported correctly. -func TestHandshake68(t *testing.T) { testHandshake(t, ETH68) } - -func testHandshake(t *testing.T, protocol uint) { - t.Parallel() - - // Create a test backend only to have some valid genesis chain - backend := newTestBackend(3) - defer backend.close() - - var ( - genesis = backend.chain.Genesis() - head = backend.chain.CurrentBlock() - td = backend.chain.GetTd(head.Hash(), head.Number.Uint64()) - forkID = forkid.NewID(backend.chain.Config(), backend.chain.Genesis(), backend.chain.CurrentHeader().Number.Uint64(), backend.chain.CurrentHeader().Time) - ) - tests := []struct { - code uint64 - data interface{} - want error - }{ - { - code: TransactionsMsg, data: []interface{}{}, - want: errNoStatusMsg, - }, - { - code: StatusMsg, data: StatusPacket{10, 1, td, head.Hash(), genesis.Hash(), forkID}, - want: errProtocolVersionMismatch, - }, - { - code: StatusMsg, data: StatusPacket{uint32(protocol), 999, td, head.Hash(), genesis.Hash(), forkID}, - want: errNetworkIDMismatch, - }, - { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, td, head.Hash(), common.Hash{3}, forkID}, - want: errGenesisMismatch, - }, - { - code: StatusMsg, data: StatusPacket{uint32(protocol), 1, td, head.Hash(), genesis.Hash(), forkid.ID{Hash: [4]byte{0x00, 0x01, 0x02, 0x03}}}, - want: errForkIDRejected, - }, - } - for i, test := range tests { - // Create the two peers to shake with each other - app, net := p2p.MsgPipe() - defer app.Close() - defer net.Close() - - peer := NewPeer(protocol, p2p.NewPeer(enode.ID{}, "peer", nil), net, nil) - defer peer.Close() - - // Send the junk test with one peer, check the handshake failure - go p2p.Send(app, test.code, test.data) - - err := peer.Handshake(1, td, head.Hash(), genesis.Hash(), forkID, forkid.NewFilter(backend.chain)) - if err == nil { - t.Errorf("test %d: protocol returned nil error, want %q", i, test.want) - } else if !errors.Is(err, test.want) { - t.Errorf("test %d: wrong error: got %q, want %q", i, err, test.want) - } - } -} diff --git a/builder/eth/protocols/eth/metrics.go b/builder/eth/protocols/eth/metrics.go deleted file mode 100644 index 5e0aee39f..000000000 --- a/builder/eth/protocols/eth/metrics.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2023 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 eth - -import "github.com/ethereum/go-ethereum/metrics" - -// meters stores ingress and egress handshake meters. -var meters bidirectionalMeters - -// bidirectionalMeters stores ingress and egress handshake meters. -type bidirectionalMeters struct { - ingress *hsMeters - egress *hsMeters -} - -// get returns the corresponding meter depending if ingress or egress is -// desired. -func (h *bidirectionalMeters) get(ingress bool) *hsMeters { - if ingress { - return h.ingress - } - return h.egress -} - -// hsMeters is a collection of meters which track metrics related to the -// eth subprotocol handshake. -type hsMeters struct { - // peerError measures the number of errors related to incorrect peer - // behaviour, such as invalid message code, size, encoding, etc. - peerError metrics.Meter - - // timeoutError measures the number of timeouts. - timeoutError metrics.Meter - - // networkIDMismatch measures the number of network id mismatch errors. - networkIDMismatch metrics.Meter - - // protocolVersionMismatch measures the number of differing protocol - // versions. - protocolVersionMismatch metrics.Meter - - // genesisMismatch measures the number of differing genesises. - genesisMismatch metrics.Meter - - // forkidRejected measures the number of differing forkids. - forkidRejected metrics.Meter -} - -// newHandshakeMeters registers and returns handshake meters for the given -// base. -func newHandshakeMeters(base string) *hsMeters { - return &hsMeters{ - peerError: metrics.NewRegisteredMeter(base+"error/peer", nil), - timeoutError: metrics.NewRegisteredMeter(base+"error/timeout", nil), - networkIDMismatch: metrics.NewRegisteredMeter(base+"error/network", nil), - protocolVersionMismatch: metrics.NewRegisteredMeter(base+"error/version", nil), - genesisMismatch: metrics.NewRegisteredMeter(base+"error/genesis", nil), - forkidRejected: metrics.NewRegisteredMeter(base+"error/forkid", nil), - } -} - -func init() { - meters = bidirectionalMeters{ - ingress: newHandshakeMeters("eth/protocols/eth/ingress/handshake/"), - egress: newHandshakeMeters("eth/protocols/eth/egress/handshake/"), - } -} diff --git a/builder/eth/protocols/eth/peer.go b/builder/eth/protocols/eth/peer.go deleted file mode 100644 index ffd78b059..000000000 --- a/builder/eth/protocols/eth/peer.go +++ /dev/null @@ -1,493 +0,0 @@ -// 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 eth - -import ( - "math/big" - "math/rand" - "sync" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rlp" -) - -const ( - // maxKnownTxs is the maximum transactions hashes to keep in the known list - // before starting to randomly evict them. - maxKnownTxs = 32768 - - // maxKnownBlocks is the maximum block hashes to keep in the known list - // before starting to randomly evict them. - maxKnownBlocks = 1024 - - // maxQueuedTxs is the maximum number of transactions to queue up before dropping - // older broadcasts. - maxQueuedTxs = 4096 - - // maxQueuedTxAnns is the maximum number of transaction announcements to queue up - // before dropping older announcements. - maxQueuedTxAnns = 4096 - - // maxQueuedBlocks is the maximum number of block propagations to queue up before - // dropping broadcasts. There's not much point in queueing stale blocks, so a few - // that might cover uncles should be enough. - maxQueuedBlocks = 4 - - // maxQueuedBlockAnns is the maximum number of block announcements to queue up before - // dropping broadcasts. Similarly to block propagations, there's no point to queue - // above some healthy uncle limit, so use that. - maxQueuedBlockAnns = 4 -) - -// max is a helper function which returns the larger of the two given integers. -func max(a, b int) int { - if a > b { - return a - } - return b -} - -// Peer is a collection of relevant information we have about a `eth` peer. -type Peer struct { - id string // Unique ID for the peer, cached - - *p2p.Peer // The embedded P2P package peer - rw p2p.MsgReadWriter // Input/output streams for snap - version uint // Protocol version negotiated - - head common.Hash // Latest advertised head block hash - td *big.Int // Latest advertised head block total difficulty - - knownBlocks *knownCache // Set of block hashes known to be known by this peer - queuedBlocks chan *blockPropagation // Queue of blocks to broadcast to the peer - queuedBlockAnns chan *types.Block // Queue of blocks to announce to the peer - - txpool TxPool // Transaction pool used by the broadcasters for liveness checks - knownTxs *knownCache // Set of transaction hashes known to be known by this peer - txBroadcast chan []common.Hash // Channel used to queue transaction propagation requests - txAnnounce chan []common.Hash // Channel used to queue transaction announcement requests - - reqDispatch chan *request // Dispatch channel to send requests and track then until fulfillment - reqCancel chan *cancel // Dispatch channel to cancel pending requests and untrack them - resDispatch chan *response // Dispatch channel to fulfil pending requests and untrack them - - term chan struct{} // Termination channel to stop the broadcasters - lock sync.RWMutex // Mutex protecting the internal fields -} - -// NewPeer creates a wrapper for a network connection and negotiated protocol -// version. -func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter, txpool TxPool) *Peer { - peer := &Peer{ - id: p.ID().String(), - Peer: p, - rw: rw, - version: version, - knownTxs: newKnownCache(maxKnownTxs), - knownBlocks: newKnownCache(maxKnownBlocks), - queuedBlocks: make(chan *blockPropagation, maxQueuedBlocks), - queuedBlockAnns: make(chan *types.Block, maxQueuedBlockAnns), - txBroadcast: make(chan []common.Hash), - txAnnounce: make(chan []common.Hash), - reqDispatch: make(chan *request), - reqCancel: make(chan *cancel), - resDispatch: make(chan *response), - txpool: txpool, - term: make(chan struct{}), - } - // Start up all the broadcasters - go peer.broadcastBlocks() - go peer.broadcastTransactions() - go peer.announceTransactions() - go peer.dispatcher() - - return peer -} - -// Close signals the broadcast goroutine to terminate. Only ever call this if -// you created the peer yourself via NewPeer. Otherwise let whoever created it -// clean it up! -func (p *Peer) Close() { - close(p.term) -} - -// ID retrieves the peer's unique identifier. -func (p *Peer) ID() string { - return p.id -} - -// Version retrieves the peer's negotiated `eth` protocol version. -func (p *Peer) Version() uint { - return p.version -} - -// Head retrieves the current head hash and total difficulty of the peer. -func (p *Peer) Head() (hash common.Hash, td *big.Int) { - p.lock.RLock() - defer p.lock.RUnlock() - - copy(hash[:], p.head[:]) - return hash, new(big.Int).Set(p.td) -} - -// SetHead updates the head hash and total difficulty of the peer. -func (p *Peer) SetHead(hash common.Hash, td *big.Int) { - p.lock.Lock() - defer p.lock.Unlock() - - copy(p.head[:], hash[:]) - p.td.Set(td) -} - -// KnownBlock returns whether peer is known to already have a block. -func (p *Peer) KnownBlock(hash common.Hash) bool { - return p.knownBlocks.Contains(hash) -} - -// KnownTransaction returns whether peer is known to already have a transaction. -func (p *Peer) KnownTransaction(hash common.Hash) bool { - return p.knownTxs.Contains(hash) -} - -// markBlock marks a block as known for the peer, ensuring that the block will -// never be propagated to this particular peer. -func (p *Peer) markBlock(hash common.Hash) { - // If we reached the memory allowance, drop a previously known block hash - p.knownBlocks.Add(hash) -} - -// markTransaction marks a transaction as known for the peer, ensuring that it -// will never be propagated to this particular peer. -func (p *Peer) markTransaction(hash common.Hash) { - // If we reached the memory allowance, drop a previously known transaction hash - p.knownTxs.Add(hash) -} - -// SendTransactions sends transactions to the peer and includes the hashes -// in its transaction hash set for future reference. -// -// This method is a helper used by the async transaction sender. Don't call it -// directly as the queueing (memory) and transmission (bandwidth) costs should -// not be managed directly. -// -// The reasons this is public is to allow packages using this protocol to write -// tests that directly send messages without having to do the async queueing. -func (p *Peer) SendTransactions(txs types.Transactions) error { - // Mark all the transactions as known, but ensure we don't overflow our limits - for _, tx := range txs { - p.knownTxs.Add(tx.Hash()) - } - return p2p.Send(p.rw, TransactionsMsg, txs) -} - -// AsyncSendTransactions queues a list of transactions (by hash) to eventually -// propagate to a remote peer. The number of pending sends are capped (new ones -// will force old sends to be dropped) -func (p *Peer) AsyncSendTransactions(hashes []common.Hash) { - select { - case p.txBroadcast <- hashes: - // Mark all the transactions as known, but ensure we don't overflow our limits - p.knownTxs.Add(hashes...) - case <-p.term: - p.Log().Debug("Dropping transaction propagation", "count", len(hashes)) - } -} - -// sendPooledTransactionHashes sends transaction hashes (tagged with their type -// and size) to the peer and includes them in its transaction hash set for future -// reference. -// -// This method is a helper used by the async transaction announcer. Don't call it -// directly as the queueing (memory) and transmission (bandwidth) costs should -// not be managed directly. -func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash, types []byte, sizes []uint32) error { - // Mark all the transactions as known, but ensure we don't overflow our limits - p.knownTxs.Add(hashes...) - return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket{Types: types, Sizes: sizes, Hashes: hashes}) -} - -// AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually -// announce to a remote peer. The number of pending sends are capped (new ones -// will force old sends to be dropped) -func (p *Peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) { - select { - case p.txAnnounce <- hashes: - // Mark all the transactions as known, but ensure we don't overflow our limits - p.knownTxs.Add(hashes...) - case <-p.term: - p.Log().Debug("Dropping transaction announcement", "count", len(hashes)) - } -} - -// ReplyPooledTransactionsRLP is the response to RequestTxs. -func (p *Peer) ReplyPooledTransactionsRLP(id uint64, hashes []common.Hash, txs []rlp.RawValue) error { - // Mark all the transactions as known, but ensure we don't overflow our limits - p.knownTxs.Add(hashes...) - - // Not packed into PooledTransactionsResponse to avoid RLP decoding - return p2p.Send(p.rw, PooledTransactionsMsg, &PooledTransactionsRLPPacket{ - RequestId: id, - PooledTransactionsRLPResponse: txs, - }) -} - -// SendNewBlockHashes announces the availability of a number of blocks through -// a hash notification. -func (p *Peer) SendNewBlockHashes(hashes []common.Hash, numbers []uint64) error { - // Mark all the block hashes as known, but ensure we don't overflow our limits - p.knownBlocks.Add(hashes...) - - request := make(NewBlockHashesPacket, len(hashes)) - for i := 0; i < len(hashes); i++ { - request[i].Hash = hashes[i] - request[i].Number = numbers[i] - } - return p2p.Send(p.rw, NewBlockHashesMsg, request) -} - -// AsyncSendNewBlockHash queues the availability of a block for propagation to a -// remote peer. If the peer's broadcast queue is full, the event is silently -// dropped. -func (p *Peer) AsyncSendNewBlockHash(block *types.Block) { - select { - case p.queuedBlockAnns <- block: - // Mark all the block hash as known, but ensure we don't overflow our limits - p.knownBlocks.Add(block.Hash()) - default: - p.Log().Debug("Dropping block announcement", "number", block.NumberU64(), "hash", block.Hash()) - } -} - -// SendNewBlock propagates an entire block to a remote peer. -func (p *Peer) SendNewBlock(block *types.Block, td *big.Int) error { - // Mark all the block hash as known, but ensure we don't overflow our limits - p.knownBlocks.Add(block.Hash()) - return p2p.Send(p.rw, NewBlockMsg, &NewBlockPacket{ - Block: block, - TD: td, - }) -} - -// AsyncSendNewBlock queues an entire block for propagation to a remote peer. If -// the peer's broadcast queue is full, the event is silently dropped. -func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) { - select { - case p.queuedBlocks <- &blockPropagation{block: block, td: td}: - // Mark all the block hash as known, but ensure we don't overflow our limits - p.knownBlocks.Add(block.Hash()) - default: - p.Log().Debug("Dropping block propagation", "number", block.NumberU64(), "hash", block.Hash()) - } -} - -// ReplyBlockHeadersRLP is the response to GetBlockHeaders. -func (p *Peer) ReplyBlockHeadersRLP(id uint64, headers []rlp.RawValue) error { - return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket{ - RequestId: id, - BlockHeadersRLPResponse: headers, - }) -} - -// ReplyBlockBodiesRLP is the response to GetBlockBodies. -func (p *Peer) ReplyBlockBodiesRLP(id uint64, bodies []rlp.RawValue) error { - // Not packed into BlockBodiesResponse to avoid RLP decoding - return p2p.Send(p.rw, BlockBodiesMsg, &BlockBodiesRLPPacket{ - RequestId: id, - BlockBodiesRLPResponse: bodies, - }) -} - -// ReplyReceiptsRLP is the response to GetReceipts. -func (p *Peer) ReplyReceiptsRLP(id uint64, receipts []rlp.RawValue) error { - return p2p.Send(p.rw, ReceiptsMsg, &ReceiptsRLPPacket{ - RequestId: id, - ReceiptsRLPResponse: receipts, - }) -} - -// RequestOneHeader is a wrapper around the header query functions to fetch a -// single header. It is used solely by the fetcher. -func (p *Peer) RequestOneHeader(hash common.Hash, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching single header", "hash", hash) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetBlockHeadersMsg, - want: BlockHeadersMsg, - data: &GetBlockHeadersPacket{ - RequestId: id, - GetBlockHeadersRequest: &GetBlockHeadersRequest{ - Origin: HashOrNumber{Hash: hash}, - Amount: uint64(1), - Skip: uint64(0), - Reverse: false, - }, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestHeadersByHash fetches a batch of blocks' headers corresponding to the -// specified header query, based on the hash of an origin block. -func (p *Peer) RequestHeadersByHash(origin common.Hash, amount int, skip int, reverse bool, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching batch of headers", "count", amount, "fromhash", origin, "skip", skip, "reverse", reverse) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetBlockHeadersMsg, - want: BlockHeadersMsg, - data: &GetBlockHeadersPacket{ - RequestId: id, - GetBlockHeadersRequest: &GetBlockHeadersRequest{ - Origin: HashOrNumber{Hash: origin}, - Amount: uint64(amount), - Skip: uint64(skip), - Reverse: reverse, - }, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestHeadersByNumber fetches a batch of blocks' headers corresponding to the -// specified header query, based on the number of an origin block. -func (p *Peer) RequestHeadersByNumber(origin uint64, amount int, skip int, reverse bool, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching batch of headers", "count", amount, "fromnum", origin, "skip", skip, "reverse", reverse) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetBlockHeadersMsg, - want: BlockHeadersMsg, - data: &GetBlockHeadersPacket{ - RequestId: id, - GetBlockHeadersRequest: &GetBlockHeadersRequest{ - Origin: HashOrNumber{Number: origin}, - Amount: uint64(amount), - Skip: uint64(skip), - Reverse: reverse, - }, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestBodies fetches a batch of blocks' bodies corresponding to the hashes -// specified. -func (p *Peer) RequestBodies(hashes []common.Hash, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching batch of block bodies", "count", len(hashes)) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetBlockBodiesMsg, - want: BlockBodiesMsg, - data: &GetBlockBodiesPacket{ - RequestId: id, - GetBlockBodiesRequest: hashes, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestReceipts fetches a batch of transaction receipts from a remote node. -func (p *Peer) RequestReceipts(hashes []common.Hash, sink chan *Response) (*Request, error) { - p.Log().Debug("Fetching batch of receipts", "count", len(hashes)) - id := rand.Uint64() - - req := &Request{ - id: id, - sink: sink, - code: GetReceiptsMsg, - want: ReceiptsMsg, - data: &GetReceiptsPacket{ - RequestId: id, - GetReceiptsRequest: hashes, - }, - } - if err := p.dispatchRequest(req); err != nil { - return nil, err - } - return req, nil -} - -// RequestTxs fetches a batch of transactions from a remote node. -func (p *Peer) RequestTxs(hashes []common.Hash) error { - p.Log().Debug("Fetching batch of transactions", "count", len(hashes)) - id := rand.Uint64() - - requestTracker.Track(p.id, p.version, GetPooledTransactionsMsg, PooledTransactionsMsg, id) - return p2p.Send(p.rw, GetPooledTransactionsMsg, &GetPooledTransactionsPacket{ - RequestId: id, - GetPooledTransactionsRequest: hashes, - }) -} - -// knownCache is a cache for known hashes. -type knownCache struct { - hashes mapset.Set[common.Hash] - max int -} - -// newKnownCache creates a new knownCache with a max capacity. -func newKnownCache(max int) *knownCache { - return &knownCache{ - max: max, - hashes: mapset.NewSet[common.Hash](), - } -} - -// Add adds a list of elements to the set. -func (k *knownCache) Add(hashes ...common.Hash) { - for k.hashes.Cardinality() > max(0, k.max-len(hashes)) { - k.hashes.Pop() - } - for _, hash := range hashes { - k.hashes.Add(hash) - } -} - -// Contains returns whether the given item is in the set. -func (k *knownCache) Contains(hash common.Hash) bool { - return k.hashes.Contains(hash) -} - -// Cardinality returns the number of elements in the set. -func (k *knownCache) Cardinality() int { - return k.hashes.Cardinality() -} diff --git a/builder/eth/protocols/eth/peer_test.go b/builder/eth/protocols/eth/peer_test.go deleted file mode 100644 index efbbbc6ff..000000000 --- a/builder/eth/protocols/eth/peer_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// 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 . - -// This file contains some shares testing functionality, common to multiple -// different files and modules being tested. - -package eth - -import ( - "crypto/rand" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// testPeer is a simulated peer to allow testing direct network calls. -type testPeer struct { - *Peer - - net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging - app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side -} - -// newTestPeer creates a new peer registered at the given data backend. -func newTestPeer(name string, version uint, backend Backend) (*testPeer, <-chan error) { - // Create a message pipe to communicate through - app, net := p2p.MsgPipe() - - // Start the peer on a new thread - var id enode.ID - rand.Read(id[:]) - - peer := NewPeer(version, p2p.NewPeer(id, name, nil), net, backend.TxPool()) - errc := make(chan error, 1) - go func() { - defer app.Close() - - errc <- backend.RunPeer(peer, func(peer *Peer) error { - return Handle(backend, peer) - }) - }() - return &testPeer{app: app, net: net, Peer: peer}, errc -} - -// close terminates the local side of the peer, notifying the remote protocol -// manager of termination. -func (p *testPeer) close() { - p.Peer.Close() - p.app.Close() -} - -func TestPeerSet(t *testing.T) { - size := 5 - s := newKnownCache(size) - - // add 10 items - for i := 0; i < size*2; i++ { - s.Add(common.Hash{byte(i)}) - } - - if s.Cardinality() != size { - t.Fatalf("wrong size, expected %d but found %d", size, s.Cardinality()) - } - - vals := []common.Hash{} - for i := 10; i < 20; i++ { - vals = append(vals, common.Hash{byte(i)}) - } - - // add item in batch - s.Add(vals...) - if s.Cardinality() < size { - t.Fatalf("bad size") - } -} diff --git a/builder/eth/protocols/eth/protocol.go b/builder/eth/protocols/eth/protocol.go deleted file mode 100644 index 47e8d9724..000000000 --- a/builder/eth/protocols/eth/protocol.go +++ /dev/null @@ -1,358 +0,0 @@ -// 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 eth - -import ( - "errors" - "fmt" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/forkid" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" -) - -// Constants to match up protocol versions and messages -const ( - ETH68 = 68 -) - -// ProtocolName is the official short name of the `eth` protocol used during -// devp2p capability negotiation. -const ProtocolName = "eth" - -// ProtocolVersions are the supported versions of the `eth` protocol (first -// is primary). -var ProtocolVersions = []uint{ETH68} - -// protocolLengths are the number of implemented message corresponding to -// different protocol versions. -var protocolLengths = map[uint]uint64{ETH68: 17} - -// maxMessageSize is the maximum cap on the size of a protocol message. -const maxMessageSize = 10 * 1024 * 1024 - -const ( - StatusMsg = 0x00 - NewBlockHashesMsg = 0x01 - TransactionsMsg = 0x02 - GetBlockHeadersMsg = 0x03 - BlockHeadersMsg = 0x04 - GetBlockBodiesMsg = 0x05 - BlockBodiesMsg = 0x06 - NewBlockMsg = 0x07 - NewPooledTransactionHashesMsg = 0x08 - GetPooledTransactionsMsg = 0x09 - PooledTransactionsMsg = 0x0a - GetReceiptsMsg = 0x0f - ReceiptsMsg = 0x10 -) - -var ( - errNoStatusMsg = errors.New("no status message") - errMsgTooLarge = errors.New("message too long") - errDecode = errors.New("invalid message") - errInvalidMsgCode = errors.New("invalid message code") - errProtocolVersionMismatch = errors.New("protocol version mismatch") - errNetworkIDMismatch = errors.New("network ID mismatch") - errGenesisMismatch = errors.New("genesis mismatch") - errForkIDRejected = errors.New("fork ID rejected") -) - -// Packet represents a p2p message in the `eth` protocol. -type Packet interface { - Name() string // Name returns a string corresponding to the message type. - Kind() byte // Kind returns the message type. -} - -// StatusPacket is the network packet for the status message. -type StatusPacket struct { - ProtocolVersion uint32 - NetworkID uint64 - TD *big.Int - Head common.Hash - Genesis common.Hash - ForkID forkid.ID -} - -// NewBlockHashesPacket is the network packet for the block announcements. -type NewBlockHashesPacket []struct { - Hash common.Hash // Hash of one particular block being announced - Number uint64 // Number of one particular block being announced -} - -// Unpack retrieves the block hashes and numbers from the announcement packet -// and returns them in a split flat format that's more consistent with the -// internal data structures. -func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) { - var ( - hashes = make([]common.Hash, len(*p)) - numbers = make([]uint64, len(*p)) - ) - for i, body := range *p { - hashes[i], numbers[i] = body.Hash, body.Number - } - return hashes, numbers -} - -// TransactionsPacket is the network packet for broadcasting new transactions. -type TransactionsPacket []*types.Transaction - -// GetBlockHeadersRequest represents a block header query. -type GetBlockHeadersRequest struct { - Origin HashOrNumber // Block from which to retrieve headers - Amount uint64 // Maximum number of headers to retrieve - Skip uint64 // Blocks to skip between consecutive headers - Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis) -} - -// GetBlockHeadersPacket represents a block header query with request ID wrapping. -type GetBlockHeadersPacket struct { - RequestId uint64 - *GetBlockHeadersRequest -} - -// HashOrNumber is a combined field for specifying an origin block. -type HashOrNumber struct { - Hash common.Hash // Block hash from which to retrieve headers (excludes Number) - Number uint64 // Block hash from which to retrieve headers (excludes Hash) -} - -// EncodeRLP is a specialized encoder for HashOrNumber to encode only one of the -// two contained union fields. -func (hn *HashOrNumber) EncodeRLP(w io.Writer) error { - if hn.Hash == (common.Hash{}) { - return rlp.Encode(w, hn.Number) - } - if hn.Number != 0 { - return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number) - } - return rlp.Encode(w, hn.Hash) -} - -// DecodeRLP is a specialized decoder for HashOrNumber to decode the contents -// into either a block hash or a block number. -func (hn *HashOrNumber) DecodeRLP(s *rlp.Stream) error { - _, size, err := s.Kind() - switch { - case err != nil: - return err - case size == 32: - hn.Number = 0 - return s.Decode(&hn.Hash) - case size <= 8: - hn.Hash = common.Hash{} - return s.Decode(&hn.Number) - default: - return fmt.Errorf("invalid input size %d for origin", size) - } -} - -// BlockHeadersRequest represents a block header response. -type BlockHeadersRequest []*types.Header - -// BlockHeadersPacket represents a block header response over with request ID wrapping. -type BlockHeadersPacket struct { - RequestId uint64 - BlockHeadersRequest -} - -// BlockHeadersRLPResponse represents a block header response, to use when we already -// have the headers rlp encoded. -type BlockHeadersRLPResponse []rlp.RawValue - -// BlockHeadersRLPPacket represents a block header response with request ID wrapping. -type BlockHeadersRLPPacket struct { - RequestId uint64 - BlockHeadersRLPResponse -} - -// NewBlockPacket is the network packet for the block propagation message. -type NewBlockPacket struct { - Block *types.Block - TD *big.Int -} - -// sanityCheck verifies that the values are reasonable, as a DoS protection -func (request *NewBlockPacket) sanityCheck() error { - if err := request.Block.SanityCheck(); err != nil { - return err - } - //TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times - // larger, it will still fit within 100 bits - if tdlen := request.TD.BitLen(); tdlen > 100 { - return fmt.Errorf("too large block TD: bitlen %d", tdlen) - } - return nil -} - -// GetBlockBodiesRequest represents a block body query. -type GetBlockBodiesRequest []common.Hash - -// GetBlockBodiesPacket represents a block body query with request ID wrapping. -type GetBlockBodiesPacket struct { - RequestId uint64 - GetBlockBodiesRequest -} - -// BlockBodiesResponse is the network packet for block content distribution. -type BlockBodiesResponse []*BlockBody - -// BlockBodiesPacket is the network packet for block content distribution with -// request ID wrapping. -type BlockBodiesPacket struct { - RequestId uint64 - BlockBodiesResponse -} - -// BlockBodiesRLPResponse is used for replying to block body requests, in cases -// where we already have them RLP-encoded, and thus can avoid the decode-encode -// roundtrip. -type BlockBodiesRLPResponse []rlp.RawValue - -// BlockBodiesRLPPacket is the BlockBodiesRLPResponse with request ID wrapping. -type BlockBodiesRLPPacket struct { - RequestId uint64 - BlockBodiesRLPResponse -} - -// BlockBody represents the data content of a single block. -type BlockBody struct { - Transactions []*types.Transaction // Transactions contained within a block - Uncles []*types.Header // Uncles contained within a block - Withdrawals []*types.Withdrawal `rlp:"optional"` // Withdrawals contained within a block -} - -// Unpack retrieves the transactions and uncles from the range packet and returns -// them in a split flat format that's more consistent with the internal data structures. -func (p *BlockBodiesResponse) Unpack() ([][]*types.Transaction, [][]*types.Header, [][]*types.Withdrawal) { - // TODO(matt): add support for withdrawals to fetchers - var ( - txset = make([][]*types.Transaction, len(*p)) - uncleset = make([][]*types.Header, len(*p)) - withdrawalset = make([][]*types.Withdrawal, len(*p)) - ) - for i, body := range *p { - txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals - } - return txset, uncleset, withdrawalset -} - -// GetReceiptsRequest represents a block receipts query. -type GetReceiptsRequest []common.Hash - -// GetReceiptsPacket represents a block receipts query with request ID wrapping. -type GetReceiptsPacket struct { - RequestId uint64 - GetReceiptsRequest -} - -// ReceiptsResponse is the network packet for block receipts distribution. -type ReceiptsResponse [][]*types.Receipt - -// ReceiptsPacket is the network packet for block receipts distribution with -// request ID wrapping. -type ReceiptsPacket struct { - RequestId uint64 - ReceiptsResponse -} - -// ReceiptsRLPResponse is used for receipts, when we already have it encoded -type ReceiptsRLPResponse []rlp.RawValue - -// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping. -type ReceiptsRLPPacket struct { - RequestId uint64 - ReceiptsRLPResponse -} - -// NewPooledTransactionHashesPacket represents a transaction announcement packet on eth/68 and newer. -type NewPooledTransactionHashesPacket struct { - Types []byte - Sizes []uint32 - Hashes []common.Hash -} - -// GetPooledTransactionsRequest represents a transaction query. -type GetPooledTransactionsRequest []common.Hash - -// GetPooledTransactionsPacket represents a transaction query with request ID wrapping. -type GetPooledTransactionsPacket struct { - RequestId uint64 - GetPooledTransactionsRequest -} - -// PooledTransactionsResponse is the network packet for transaction distribution. -type PooledTransactionsResponse []*types.Transaction - -// PooledTransactionsPacket is the network packet for transaction distribution -// with request ID wrapping. -type PooledTransactionsPacket struct { - RequestId uint64 - PooledTransactionsResponse -} - -// PooledTransactionsRLPResponse is the network packet for transaction distribution, used -// in the cases we already have them in rlp-encoded form -type PooledTransactionsRLPResponse []rlp.RawValue - -// PooledTransactionsRLPPacket is PooledTransactionsRLPResponse with request ID wrapping. -type PooledTransactionsRLPPacket struct { - RequestId uint64 - PooledTransactionsRLPResponse -} - -func (*StatusPacket) Name() string { return "Status" } -func (*StatusPacket) Kind() byte { return StatusMsg } - -func (*NewBlockHashesPacket) Name() string { return "NewBlockHashes" } -func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg } - -func (*TransactionsPacket) Name() string { return "Transactions" } -func (*TransactionsPacket) Kind() byte { return TransactionsMsg } - -func (*GetBlockHeadersRequest) Name() string { return "GetBlockHeaders" } -func (*GetBlockHeadersRequest) Kind() byte { return GetBlockHeadersMsg } - -func (*BlockHeadersRequest) Name() string { return "BlockHeaders" } -func (*BlockHeadersRequest) Kind() byte { return BlockHeadersMsg } - -func (*GetBlockBodiesRequest) Name() string { return "GetBlockBodies" } -func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg } - -func (*BlockBodiesResponse) Name() string { return "BlockBodies" } -func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg } - -func (*NewBlockPacket) Name() string { return "NewBlock" } -func (*NewBlockPacket) Kind() byte { return NewBlockMsg } - -func (*NewPooledTransactionHashesPacket) Name() string { return "NewPooledTransactionHashes" } -func (*NewPooledTransactionHashesPacket) Kind() byte { return NewPooledTransactionHashesMsg } - -func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" } -func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg } - -func (*PooledTransactionsResponse) Name() string { return "PooledTransactions" } -func (*PooledTransactionsResponse) Kind() byte { return PooledTransactionsMsg } - -func (*GetReceiptsRequest) Name() string { return "GetReceipts" } -func (*GetReceiptsRequest) Kind() byte { return GetReceiptsMsg } - -func (*ReceiptsResponse) Name() string { return "Receipts" } -func (*ReceiptsResponse) Kind() byte { return ReceiptsMsg } diff --git a/builder/eth/protocols/eth/protocol_test.go b/builder/eth/protocols/eth/protocol_test.go deleted file mode 100644 index bc2545dea..000000000 --- a/builder/eth/protocols/eth/protocol_test.go +++ /dev/null @@ -1,248 +0,0 @@ -// 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 eth - -import ( - "bytes" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" -) - -// Tests that the custom union field encoder and decoder works correctly. -func TestGetBlockHeadersDataEncodeDecode(t *testing.T) { - // Create a "random" hash for testing - var hash common.Hash - for i := range hash { - hash[i] = byte(i) - } - // Assemble some table driven tests - tests := []struct { - packet *GetBlockHeadersRequest - fail bool - }{ - // Providing the origin as either a hash or a number should both work - {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}}}, - {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}}}, - - // Providing arbitrary query field should also work - {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Number: 314}, Amount: 314, Skip: 1, Reverse: true}}, - {fail: false, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash}, Amount: 314, Skip: 1, Reverse: true}}, - - // Providing both the origin hash and origin number must fail - {fail: true, packet: &GetBlockHeadersRequest{Origin: HashOrNumber{Hash: hash, Number: 314}}}, - } - // Iterate over each of the tests and try to encode and then decode - for i, tt := range tests { - bytes, err := rlp.EncodeToBytes(tt.packet) - if err != nil && !tt.fail { - t.Fatalf("test %d: failed to encode packet: %v", i, err) - } else if err == nil && tt.fail { - t.Fatalf("test %d: encode should have failed", i) - } - if !tt.fail { - packet := new(GetBlockHeadersRequest) - if err := rlp.DecodeBytes(bytes, packet); err != nil { - t.Fatalf("test %d: failed to decode packet: %v", i, err) - } - if packet.Origin.Hash != tt.packet.Origin.Hash || packet.Origin.Number != tt.packet.Origin.Number || packet.Amount != tt.packet.Amount || - packet.Skip != tt.packet.Skip || packet.Reverse != tt.packet.Reverse { - t.Fatalf("test %d: encode decode mismatch: have %+v, want %+v", i, packet, tt.packet) - } - } - } -} - -// TestEmptyMessages tests encoding of empty messages. -func TestEmptyMessages(t *testing.T) { - // All empty messages encodes to the same format - want := common.FromHex("c4820457c0") - - for i, msg := range []interface{}{ - // Headers - GetBlockHeadersPacket{1111, nil}, - BlockHeadersPacket{1111, nil}, - // Bodies - GetBlockBodiesPacket{1111, nil}, - BlockBodiesPacket{1111, nil}, - BlockBodiesRLPPacket{1111, nil}, - // Receipts - GetReceiptsPacket{1111, nil}, - ReceiptsPacket{1111, nil}, - // Transactions - GetPooledTransactionsPacket{1111, nil}, - PooledTransactionsPacket{1111, nil}, - PooledTransactionsRLPPacket{1111, nil}, - - // Headers - BlockHeadersPacket{1111, BlockHeadersRequest([]*types.Header{})}, - // Bodies - GetBlockBodiesPacket{1111, GetBlockBodiesRequest([]common.Hash{})}, - BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{})}, - BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{})}, - // Receipts - GetReceiptsPacket{1111, GetReceiptsRequest([]common.Hash{})}, - ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{})}, - // Transactions - GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest([]common.Hash{})}, - PooledTransactionsPacket{1111, PooledTransactionsResponse([]*types.Transaction{})}, - PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse([]rlp.RawValue{})}, - } { - if have, _ := rlp.EncodeToBytes(msg); !bytes.Equal(have, want) { - t.Errorf("test %d, type %T, have\n\t%x\nwant\n\t%x", i, msg, have, want) - } - } -} - -// TestMessages tests the encoding of all messages. -func TestMessages(t *testing.T) { - // Some basic structs used during testing - var ( - header *types.Header - blockBody *BlockBody - blockBodyRlp rlp.RawValue - txs []*types.Transaction - txRlps []rlp.RawValue - hashes []common.Hash - receipts []*types.Receipt - receiptsRlp rlp.RawValue - - err error - ) - header = &types.Header{ - Difficulty: big.NewInt(2222), - Number: big.NewInt(3333), - GasLimit: 4444, - GasUsed: 5555, - Time: 6666, - Extra: []byte{0x77, 0x88}, - } - // Init the transactions, taken from a different test - { - for _, hexrlp := range []string{ - "f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", - "f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", - } { - var tx *types.Transaction - rlpdata := common.FromHex(hexrlp) - if err := rlp.DecodeBytes(rlpdata, &tx); err != nil { - t.Fatal(err) - } - txs = append(txs, tx) - txRlps = append(txRlps, rlpdata) - } - } - // init the block body data, both object and rlp form - blockBody = &BlockBody{ - Transactions: txs, - Uncles: []*types.Header{header}, - } - blockBodyRlp, err = rlp.EncodeToBytes(blockBody) - if err != nil { - t.Fatal(err) - } - - hashes = []common.Hash{ - common.HexToHash("deadc0de"), - common.HexToHash("feedbeef"), - } - // init the receipts - { - receipts = []*types.Receipt{ - { - Status: types.ReceiptStatusFailed, - CumulativeGasUsed: 1, - Logs: []*types.Log{ - { - Address: common.BytesToAddress([]byte{0x11}), - Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, - Data: []byte{0x01, 0x00, 0xff}, - }, - }, - TxHash: hashes[0], - ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), - GasUsed: 111111, - }, - } - rlpData, err := rlp.EncodeToBytes(receipts) - if err != nil { - t.Fatal(err) - } - receiptsRlp = rlpData - } - - for i, tc := range []struct { - message interface{} - want []byte - }{ - { - GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{hashes[0], 0}, 5, 5, false}}, - common.FromHex("e8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580"), - }, - { - GetBlockHeadersPacket{1111, &GetBlockHeadersRequest{HashOrNumber{common.Hash{}, 9999}, 5, 5, false}}, - common.FromHex("ca820457c682270f050580"), - }, - { - BlockHeadersPacket{1111, BlockHeadersRequest{header}}, - common.FromHex("f90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), - }, - { - GetBlockBodiesPacket{1111, GetBlockBodiesRequest(hashes)}, - common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), - }, - { - BlockBodiesPacket{1111, BlockBodiesResponse([]*BlockBody{blockBody})}, - common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), - }, - { // Identical to non-rlp-shortcut version - BlockBodiesRLPPacket{1111, BlockBodiesRLPResponse([]rlp.RawValue{blockBodyRlp})}, - common.FromHex("f902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"), - }, - { - GetReceiptsPacket{1111, GetReceiptsRequest(hashes)}, - common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), - }, - { - ReceiptsPacket{1111, ReceiptsResponse([][]*types.Receipt{receipts})}, - common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), - }, - { - ReceiptsRLPPacket{1111, ReceiptsRLPResponse([]rlp.RawValue{receiptsRlp})}, - common.FromHex("f90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"), - }, - { - GetPooledTransactionsPacket{1111, GetPooledTransactionsRequest(hashes)}, - common.FromHex("f847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef"), - }, - { - PooledTransactionsPacket{1111, PooledTransactionsResponse(txs)}, - common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"), - }, - { - PooledTransactionsRLPPacket{1111, PooledTransactionsRLPResponse(txRlps)}, - common.FromHex("f8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb"), - }, - } { - if have, _ := rlp.EncodeToBytes(tc.message); !bytes.Equal(have, tc.want) { - t.Errorf("test %d, type %T, have\n\t%x\nwant\n\t%x", i, tc.message, have, tc.want) - } - } -} diff --git a/builder/eth/protocols/eth/tracker.go b/builder/eth/protocols/eth/tracker.go deleted file mode 100644 index 324fd2283..000000000 --- a/builder/eth/protocols/eth/tracker.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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 eth - -import ( - "time" - - "github.com/ethereum/go-ethereum/p2p/tracker" -) - -// requestTracker is a singleton tracker for eth/66 and newer request times. -var requestTracker = tracker.New(ProtocolName, 5*time.Minute) diff --git a/builder/eth/protocols/snap/discovery.go b/builder/eth/protocols/snap/discovery.go deleted file mode 100644 index 684ec7e63..000000000 --- a/builder/eth/protocols/snap/discovery.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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 snap - -import ( - "github.com/ethereum/go-ethereum/rlp" -) - -// enrEntry is the ENR entry which advertises `snap` protocol on the discovery. -type enrEntry struct { - // Ignore additional fields (for forward compatibility). - Rest []rlp.RawValue `rlp:"tail"` -} - -// ENRKey implements enr.Entry. -func (e enrEntry) ENRKey() string { - return "snap" -} diff --git a/builder/eth/protocols/snap/handler.go b/builder/eth/protocols/snap/handler.go deleted file mode 100644 index bd7ce9e71..000000000 --- a/builder/eth/protocols/snap/handler.go +++ /dev/null @@ -1,577 +0,0 @@ -// 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 snap - -import ( - "bytes" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" -) - -const ( - // softResponseLimit is the target maximum size of replies to data retrievals. - softResponseLimit = 2 * 1024 * 1024 - - // maxCodeLookups is the maximum number of bytecodes to serve. This number is - // there to limit the number of disk lookups. - maxCodeLookups = 1024 - - // stateLookupSlack defines the ratio by how much a state response can exceed - // the requested limit in order to try and avoid breaking up contracts into - // multiple packages and proving them. - stateLookupSlack = 0.1 - - // maxTrieNodeLookups is the maximum number of state trie nodes to serve. This - // number is there to limit the number of disk lookups. - maxTrieNodeLookups = 1024 - - // maxTrieNodeTimeSpent is the maximum time we should spend on looking up trie nodes. - // If we spend too much time, then it's a fairly high chance of timing out - // at the remote side, which means all the work is in vain. - maxTrieNodeTimeSpent = 5 * time.Second -) - -// Handler is a callback to invoke from an outside runner after the boilerplate -// exchanges have passed. -type Handler func(peer *Peer) error - -// Backend defines the data retrieval methods to serve remote requests and the -// callback methods to invoke on remote deliveries. -type Backend interface { - // Chain retrieves the blockchain object to serve data. - Chain() *core.BlockChain - - // RunPeer is invoked when a peer joins on the `eth` protocol. The handler - // should do any peer maintenance work, handshakes and validations. If all - // is passed, control should be given back to the `handler` to process the - // inbound messages going forward. - RunPeer(peer *Peer, handler Handler) error - - // PeerInfo retrieves all known `snap` information about a peer. - PeerInfo(id enode.ID) interface{} - - // Handle is a callback to be invoked when a data packet is received from - // the remote peer. Only packets not consumed by the protocol handler will - // be forwarded to the backend. - Handle(peer *Peer, packet Packet) error -} - -// MakeProtocols constructs the P2P protocol definitions for `snap`. -func MakeProtocols(backend Backend, dnsdisc enode.Iterator) []p2p.Protocol { - // Filter the discovery iterator for nodes advertising snap support. - dnsdisc = enode.Filter(dnsdisc, func(n *enode.Node) bool { - var snap enrEntry - return n.Load(&snap) == nil - }) - - protocols := make([]p2p.Protocol, len(ProtocolVersions)) - for i, version := range ProtocolVersions { - version := version // Closure - - protocols[i] = p2p.Protocol{ - Name: ProtocolName, - Version: version, - Length: protocolLengths[version], - Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error { - return backend.RunPeer(NewPeer(version, p, rw), func(peer *Peer) error { - return Handle(backend, peer) - }) - }, - NodeInfo: func() interface{} { - return nodeInfo(backend.Chain()) - }, - PeerInfo: func(id enode.ID) interface{} { - return backend.PeerInfo(id) - }, - Attributes: []enr.Entry{&enrEntry{}}, - DialCandidates: dnsdisc, - } - } - return protocols -} - -// Handle is the callback invoked to manage the life cycle of a `snap` peer. -// When this function terminates, the peer is disconnected. -func Handle(backend Backend, peer *Peer) error { - for { - if err := HandleMessage(backend, peer); err != nil { - peer.Log().Debug("Message handling failed in `snap`", "err", err) - return err - } - } -} - -// HandleMessage is invoked whenever an inbound message is received from a -// remote peer on the `snap` protocol. The remote connection is torn down upon -// returning any error. -func HandleMessage(backend Backend, peer *Peer) error { - // Read the next message from the remote peer, and ensure it's fully consumed - msg, err := peer.rw.ReadMsg() - if err != nil { - return err - } - if msg.Size > maxMessageSize { - return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize) - } - defer msg.Discard() - start := time.Now() - // Track the amount of time it takes to serve the request and run the handler - if metrics.Enabled { - h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code) - defer func(start time.Time) { - sampler := func() metrics.Sample { - return metrics.ResettingSample( - metrics.NewExpDecaySample(1028, 0.015), - ) - } - metrics.GetOrRegisterHistogramLazy(h, nil, sampler).Update(time.Since(start).Microseconds()) - }(start) - } - // Handle the message depending on its contents - switch { - case msg.Code == GetAccountRangeMsg: - // Decode the account retrieval request - var req GetAccountRangePacket - if err := msg.Decode(&req); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Service the request, potentially returning nothing in case of errors - accounts, proofs := ServiceGetAccountRangeQuery(backend.Chain(), &req) - - // Send back anything accumulated (or empty in case of errors) - return p2p.Send(peer.rw, AccountRangeMsg, &AccountRangePacket{ - ID: req.ID, - Accounts: accounts, - Proof: proofs, - }) - - case msg.Code == AccountRangeMsg: - // A range of accounts arrived to one of our previous requests - res := new(AccountRangePacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Ensure the range is monotonically increasing - for i := 1; i < len(res.Accounts); i++ { - if bytes.Compare(res.Accounts[i-1].Hash[:], res.Accounts[i].Hash[:]) >= 0 { - return fmt.Errorf("accounts not monotonically increasing: #%d [%x] vs #%d [%x]", i-1, res.Accounts[i-1].Hash[:], i, res.Accounts[i].Hash[:]) - } - } - requestTracker.Fulfil(peer.id, peer.version, AccountRangeMsg, res.ID) - - return backend.Handle(peer, res) - - case msg.Code == GetStorageRangesMsg: - // Decode the storage retrieval request - var req GetStorageRangesPacket - if err := msg.Decode(&req); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Service the request, potentially returning nothing in case of errors - slots, proofs := ServiceGetStorageRangesQuery(backend.Chain(), &req) - - // Send back anything accumulated (or empty in case of errors) - return p2p.Send(peer.rw, StorageRangesMsg, &StorageRangesPacket{ - ID: req.ID, - Slots: slots, - Proof: proofs, - }) - - case msg.Code == StorageRangesMsg: - // A range of storage slots arrived to one of our previous requests - res := new(StorageRangesPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Ensure the ranges are monotonically increasing - for i, slots := range res.Slots { - for j := 1; j < len(slots); j++ { - if bytes.Compare(slots[j-1].Hash[:], slots[j].Hash[:]) >= 0 { - return fmt.Errorf("storage slots not monotonically increasing for account #%d: #%d [%x] vs #%d [%x]", i, j-1, slots[j-1].Hash[:], j, slots[j].Hash[:]) - } - } - } - requestTracker.Fulfil(peer.id, peer.version, StorageRangesMsg, res.ID) - - return backend.Handle(peer, res) - - case msg.Code == GetByteCodesMsg: - // Decode bytecode retrieval request - var req GetByteCodesPacket - if err := msg.Decode(&req); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Service the request, potentially returning nothing in case of errors - codes := ServiceGetByteCodesQuery(backend.Chain(), &req) - - // Send back anything accumulated (or empty in case of errors) - return p2p.Send(peer.rw, ByteCodesMsg, &ByteCodesPacket{ - ID: req.ID, - Codes: codes, - }) - - case msg.Code == ByteCodesMsg: - // A batch of byte codes arrived to one of our previous requests - res := new(ByteCodesPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - requestTracker.Fulfil(peer.id, peer.version, ByteCodesMsg, res.ID) - - return backend.Handle(peer, res) - - case msg.Code == GetTrieNodesMsg: - // Decode trie node retrieval request - var req GetTrieNodesPacket - if err := msg.Decode(&req); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - // Service the request, potentially returning nothing in case of errors - nodes, err := ServiceGetTrieNodesQuery(backend.Chain(), &req, start) - if err != nil { - return err - } - // Send back anything accumulated (or empty in case of errors) - return p2p.Send(peer.rw, TrieNodesMsg, &TrieNodesPacket{ - ID: req.ID, - Nodes: nodes, - }) - - case msg.Code == TrieNodesMsg: - // A batch of trie nodes arrived to one of our previous requests - res := new(TrieNodesPacket) - if err := msg.Decode(res); err != nil { - return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) - } - requestTracker.Fulfil(peer.id, peer.version, TrieNodesMsg, res.ID) - - return backend.Handle(peer, res) - - default: - return fmt.Errorf("%w: %v", errInvalidMsgCode, msg.Code) - } -} - -// ServiceGetAccountRangeQuery assembles the response to an account range query. -// It is exposed to allow external packages to test protocol behavior. -func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePacket) ([]*AccountData, [][]byte) { - if req.Bytes > softResponseLimit { - req.Bytes = softResponseLimit - } - // Retrieve the requested state and bail out if non existent - tr, err := trie.New(trie.StateTrieID(req.Root), chain.TrieDB()) - if err != nil { - return nil, nil - } - it, err := chain.Snapshots().AccountIterator(req.Root, req.Origin) - if err != nil { - return nil, nil - } - // Iterate over the requested range and pile accounts up - var ( - accounts []*AccountData - size uint64 - last common.Hash - ) - for it.Next() { - hash, account := it.Hash(), common.CopyBytes(it.Account()) - - // Track the returned interval for the Merkle proofs - last = hash - - // Assemble the reply item - size += uint64(common.HashLength + len(account)) - accounts = append(accounts, &AccountData{ - Hash: hash, - Body: account, - }) - // If we've exceeded the request threshold, abort - if bytes.Compare(hash[:], req.Limit[:]) >= 0 { - break - } - if size > req.Bytes { - break - } - } - it.Release() - - // Generate the Merkle proofs for the first and last account - proof := trienode.NewProofSet() - if err := tr.Prove(req.Origin[:], proof); err != nil { - log.Warn("Failed to prove account range", "origin", req.Origin, "err", err) - return nil, nil - } - if last != (common.Hash{}) { - if err := tr.Prove(last[:], proof); err != nil { - log.Warn("Failed to prove account range", "last", last, "err", err) - return nil, nil - } - } - var proofs [][]byte - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - return accounts, proofs -} - -func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) { - if req.Bytes > softResponseLimit { - req.Bytes = softResponseLimit - } - // TODO(karalabe): Do we want to enforce > 0 accounts and 1 account if origin is set? - // TODO(karalabe): - Logging locally is not ideal as remote faults annoy the local user - // TODO(karalabe): - Dropping the remote peer is less flexible wrt client bugs (slow is better than non-functional) - - // Calculate the hard limit at which to abort, even if mid storage trie - hardLimit := uint64(float64(req.Bytes) * (1 + stateLookupSlack)) - - // Retrieve storage ranges until the packet limit is reached - var ( - slots [][]*StorageData - proofs [][]byte - size uint64 - ) - for _, account := range req.Accounts { - // If we've exceeded the requested data limit, abort without opening - // a new storage range (that we'd need to prove due to exceeded size) - if size >= req.Bytes { - break - } - // The first account might start from a different origin and end sooner - var origin common.Hash - if len(req.Origin) > 0 { - origin, req.Origin = common.BytesToHash(req.Origin), nil - } - var limit = common.MaxHash - if len(req.Limit) > 0 { - limit, req.Limit = common.BytesToHash(req.Limit), nil - } - // Retrieve the requested state and bail out if non existent - it, err := chain.Snapshots().StorageIterator(req.Root, account, origin) - if err != nil { - return nil, nil - } - // Iterate over the requested range and pile slots up - var ( - storage []*StorageData - last common.Hash - abort bool - ) - for it.Next() { - if size >= hardLimit { - abort = true - break - } - hash, slot := it.Hash(), common.CopyBytes(it.Slot()) - - // Track the returned interval for the Merkle proofs - last = hash - - // Assemble the reply item - size += uint64(common.HashLength + len(slot)) - storage = append(storage, &StorageData{ - Hash: hash, - Body: slot, - }) - // If we've exceeded the request threshold, abort - if bytes.Compare(hash[:], limit[:]) >= 0 { - break - } - } - if len(storage) > 0 { - slots = append(slots, storage) - } - it.Release() - - // Generate the Merkle proofs for the first and last storage slot, but - // only if the response was capped. If the entire storage trie included - // in the response, no need for any proofs. - if origin != (common.Hash{}) || (abort && len(storage) > 0) { - // Request started at a non-zero hash or was capped prematurely, add - // the endpoint Merkle proofs - accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), chain.TrieDB()) - if err != nil { - return nil, nil - } - acc, err := accTrie.GetAccountByHash(account) - if err != nil || acc == nil { - return nil, nil - } - id := trie.StorageTrieID(req.Root, account, acc.Root) - stTrie, err := trie.NewStateTrie(id, chain.TrieDB()) - if err != nil { - return nil, nil - } - proof := trienode.NewProofSet() - if err := stTrie.Prove(origin[:], proof); err != nil { - log.Warn("Failed to prove storage range", "origin", req.Origin, "err", err) - return nil, nil - } - if last != (common.Hash{}) { - if err := stTrie.Prove(last[:], proof); err != nil { - log.Warn("Failed to prove storage range", "last", last, "err", err) - return nil, nil - } - } - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - // Proof terminates the reply as proofs are only added if a node - // refuses to serve more data (exception when a contract fetch is - // finishing, but that's that). - break - } - } - return slots, proofs -} - -// ServiceGetByteCodesQuery assembles the response to a byte codes query. -// It is exposed to allow external packages to test protocol behavior. -func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [][]byte { - if req.Bytes > softResponseLimit { - req.Bytes = softResponseLimit - } - if len(req.Hashes) > maxCodeLookups { - req.Hashes = req.Hashes[:maxCodeLookups] - } - // Retrieve bytecodes until the packet size limit is reached - var ( - codes [][]byte - bytes uint64 - ) - for _, hash := range req.Hashes { - if hash == types.EmptyCodeHash { - // Peers should not request the empty code, but if they do, at - // least sent them back a correct response without db lookups - codes = append(codes, []byte{}) - } else if blob, err := chain.ContractCodeWithPrefix(hash); err == nil { - codes = append(codes, blob) - bytes += uint64(len(blob)) - } - if bytes > req.Bytes { - break - } - } - return codes -} - -// ServiceGetTrieNodesQuery assembles the response to a trie nodes query. -// It is exposed to allow external packages to test protocol behavior. -func ServiceGetTrieNodesQuery(chain *core.BlockChain, req *GetTrieNodesPacket, start time.Time) ([][]byte, error) { - if req.Bytes > softResponseLimit { - req.Bytes = softResponseLimit - } - // Make sure we have the state associated with the request - triedb := chain.TrieDB() - - accTrie, err := trie.NewStateTrie(trie.StateTrieID(req.Root), triedb) - if err != nil { - // We don't have the requested state available, bail out - return nil, nil - } - // The 'snap' might be nil, in which case we cannot serve storage slots. - snap := chain.Snapshots().Snapshot(req.Root) - // Retrieve trie nodes until the packet size limit is reached - var ( - nodes [][]byte - bytes uint64 - loads int // Trie hash expansions to count database reads - ) - for _, pathset := range req.Paths { - switch len(pathset) { - case 0: - // Ensure we penalize invalid requests - return nil, fmt.Errorf("%w: zero-item pathset requested", errBadRequest) - - case 1: - // If we're only retrieving an account trie node, fetch it directly - blob, resolved, err := accTrie.GetNode(pathset[0]) - loads += resolved // always account database reads, even for failures - if err != nil { - break - } - nodes = append(nodes, blob) - bytes += uint64(len(blob)) - - default: - var stRoot common.Hash - // Storage slots requested, open the storage trie and retrieve from there - if snap == nil { - // We don't have the requested state snapshotted yet (or it is stale), - // but can look up the account via the trie instead. - account, err := accTrie.GetAccountByHash(common.BytesToHash(pathset[0])) - loads += 8 // We don't know the exact cost of lookup, this is an estimate - if err != nil || account == nil { - break - } - stRoot = account.Root - } else { - account, err := snap.Account(common.BytesToHash(pathset[0])) - loads++ // always account database reads, even for failures - if err != nil || account == nil { - break - } - stRoot = common.BytesToHash(account.Root) - } - id := trie.StorageTrieID(req.Root, common.BytesToHash(pathset[0]), stRoot) - stTrie, err := trie.NewStateTrie(id, triedb) - loads++ // always account database reads, even for failures - if err != nil { - break - } - for _, path := range pathset[1:] { - blob, resolved, err := stTrie.GetNode(path) - loads += resolved // always account database reads, even for failures - if err != nil { - break - } - nodes = append(nodes, blob) - bytes += uint64(len(blob)) - - // Sanity check limits to avoid DoS on the store trie loads - if bytes > req.Bytes || loads > maxTrieNodeLookups || time.Since(start) > maxTrieNodeTimeSpent { - break - } - } - } - // Abort request processing if we've exceeded our limits - if bytes > req.Bytes || loads > maxTrieNodeLookups || time.Since(start) > maxTrieNodeTimeSpent { - break - } - } - return nodes, nil -} - -// NodeInfo represents a short summary of the `snap` sub-protocol metadata -// known about the host peer. -type NodeInfo struct{} - -// nodeInfo retrieves some `snap` protocol metadata about the running host node. -func nodeInfo(chain *core.BlockChain) *NodeInfo { - return &NodeInfo{} -} diff --git a/builder/eth/protocols/snap/handler_fuzzing_test.go b/builder/eth/protocols/snap/handler_fuzzing_test.go deleted file mode 100644 index 4e234ad21..000000000 --- a/builder/eth/protocols/snap/handler_fuzzing_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// 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 snap - -import ( - "bytes" - "encoding/binary" - "fmt" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - fuzz "github.com/google/gofuzz" -) - -func FuzzARange(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - doFuzz(data, &GetAccountRangePacket{}, GetAccountRangeMsg) - }) -} - -func FuzzSRange(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - doFuzz(data, &GetStorageRangesPacket{}, GetStorageRangesMsg) - }) -} - -func FuzzByteCodes(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - doFuzz(data, &GetByteCodesPacket{}, GetByteCodesMsg) - }) -} - -func FuzzTrieNodes(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { - doFuzz(data, &GetTrieNodesPacket{}, GetTrieNodesMsg) - }) -} - -func doFuzz(input []byte, obj interface{}, code int) { - bc := getChain() - defer bc.Stop() - fuzz.NewFromGoFuzz(input).Fuzz(obj) - var data []byte - switch p := obj.(type) { - case *GetTrieNodesPacket: - p.Root = trieRoot - data, _ = rlp.EncodeToBytes(obj) - default: - data, _ = rlp.EncodeToBytes(obj) - } - cli := &dummyRW{ - code: uint64(code), - data: data, - } - peer := NewFakePeer(65, "gazonk01", cli) - err := HandleMessage(&dummyBackend{bc}, peer) - switch { - case err == nil && cli.writeCount != 1: - panic(fmt.Sprintf("Expected 1 response, got %d", cli.writeCount)) - case err != nil && cli.writeCount != 0: - panic(fmt.Sprintf("Expected 0 response, got %d", cli.writeCount)) - } -} - -var trieRoot common.Hash - -func getChain() *core.BlockChain { - ga := make(types.GenesisAlloc, 1000) - var a = make([]byte, 20) - var mkStorage = func(k, v int) (common.Hash, common.Hash) { - var kB = make([]byte, 32) - var vB = make([]byte, 32) - binary.LittleEndian.PutUint64(kB, uint64(k)) - binary.LittleEndian.PutUint64(vB, uint64(v)) - return common.BytesToHash(kB), common.BytesToHash(vB) - } - storage := make(map[common.Hash]common.Hash) - for i := 0; i < 10; i++ { - k, v := mkStorage(i, i) - storage[k] = v - } - for i := 0; i < 1000; i++ { - binary.LittleEndian.PutUint64(a, uint64(i+0xff)) - acc := types.Account{Balance: big.NewInt(int64(i))} - if i%2 == 1 { - acc.Storage = storage - } - ga[common.BytesToAddress(a)] = acc - } - gspec := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: ga, - } - _, blocks, _ := core.GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *core.BlockGen) {}) - cacheConf := &core.CacheConfig{ - TrieCleanLimit: 0, - TrieDirtyLimit: 0, - TrieTimeLimit: 5 * time.Minute, - TrieCleanNoPrefetch: true, - SnapshotLimit: 100, - SnapshotWait: true, - } - trieRoot = blocks[len(blocks)-1].Root() - bc, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), cacheConf, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil) - if _, err := bc.InsertChain(blocks); err != nil { - panic(err) - } - return bc -} - -type dummyBackend struct { - chain *core.BlockChain -} - -func (d *dummyBackend) Chain() *core.BlockChain { return d.chain } -func (d *dummyBackend) RunPeer(*Peer, Handler) error { return nil } -func (d *dummyBackend) PeerInfo(enode.ID) interface{} { return "Foo" } -func (d *dummyBackend) Handle(*Peer, Packet) error { return nil } - -type dummyRW struct { - code uint64 - data []byte - writeCount int -} - -func (d *dummyRW) ReadMsg() (p2p.Msg, error) { - return p2p.Msg{ - Code: d.code, - Payload: bytes.NewReader(d.data), - ReceivedAt: time.Now(), - Size: uint32(len(d.data)), - }, nil -} - -func (d *dummyRW) WriteMsg(msg p2p.Msg) error { - d.writeCount++ - return nil -} diff --git a/builder/eth/protocols/snap/metrics.go b/builder/eth/protocols/snap/metrics.go deleted file mode 100644 index a7d071953..000000000 --- a/builder/eth/protocols/snap/metrics.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2023 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 snap - -import ( - metrics "github.com/ethereum/go-ethereum/metrics" -) - -var ( - ingressRegistrationErrorName = "eth/protocols/snap/ingress/registration/error" - egressRegistrationErrorName = "eth/protocols/snap/egress/registration/error" - - IngressRegistrationErrorMeter = metrics.NewRegisteredMeter(ingressRegistrationErrorName, nil) - EgressRegistrationErrorMeter = metrics.NewRegisteredMeter(egressRegistrationErrorName, nil) - - // deletionGauge is the metric to track how many trie node deletions - // are performed in total during the sync process. - deletionGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete", nil) - - // lookupGauge is the metric to track how many trie node lookups are - // performed to determine if node needs to be deleted. - lookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/lookup", nil) - - // boundaryAccountNodesGauge is the metric to track how many boundary trie - // nodes in account trie are met. - boundaryAccountNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/account", nil) - - // boundaryAccountNodesGauge is the metric to track how many boundary trie - // nodes in storage tries are met. - boundaryStorageNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/storage", nil) - - // smallStorageGauge is the metric to track how many storages are small enough - // to retrieved in one or two request. - smallStorageGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/small", nil) - - // largeStorageGauge is the metric to track how many storages are large enough - // to retrieved concurrently. - largeStorageGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/large", nil) - - // skipStorageHealingGauge is the metric to track how many storages are retrieved - // in multiple requests but healing is not necessary. - skipStorageHealingGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/noheal", nil) -) diff --git a/builder/eth/protocols/snap/peer.go b/builder/eth/protocols/snap/peer.go deleted file mode 100644 index c57931678..000000000 --- a/builder/eth/protocols/snap/peer.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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 snap - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p" -) - -// Peer is a collection of relevant information we have about a `snap` peer. -type Peer struct { - id string // Unique ID for the peer, cached - - *p2p.Peer // The embedded P2P package peer - rw p2p.MsgReadWriter // Input/output streams for snap - version uint // Protocol version negotiated - - logger log.Logger // Contextual logger with the peer id injected -} - -// NewPeer creates a wrapper for a network connection and negotiated protocol -// version. -func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer { - id := p.ID().String() - return &Peer{ - id: id, - Peer: p, - rw: rw, - version: version, - logger: log.New("peer", id[:8]), - } -} - -// NewFakePeer creates a fake snap peer without a backing p2p peer, for testing purposes. -func NewFakePeer(version uint, id string, rw p2p.MsgReadWriter) *Peer { - return &Peer{ - id: id, - rw: rw, - version: version, - logger: log.New("peer", id[:8]), - } -} - -// ID retrieves the peer's unique identifier. -func (p *Peer) ID() string { - return p.id -} - -// Version retrieves the peer's negotiated `snap` protocol version. -func (p *Peer) Version() uint { - return p.version -} - -// Log overrides the P2P logger with the higher level one containing only the id. -func (p *Peer) Log() log.Logger { - return p.logger -} - -// RequestAccountRange fetches a batch of accounts rooted in a specific account -// trie, starting with the origin. -func (p *Peer) RequestAccountRange(id uint64, root common.Hash, origin, limit common.Hash, bytes uint64) error { - p.logger.Trace("Fetching range of accounts", "reqid", id, "root", root, "origin", origin, "limit", limit, "bytes", common.StorageSize(bytes)) - - requestTracker.Track(p.id, p.version, GetAccountRangeMsg, AccountRangeMsg, id) - return p2p.Send(p.rw, GetAccountRangeMsg, &GetAccountRangePacket{ - ID: id, - Root: root, - Origin: origin, - Limit: limit, - Bytes: bytes, - }) -} - -// RequestStorageRanges fetches a batch of storage slots belonging to one or more -// accounts. If slots from only one account is requested, an origin marker may also -// be used to retrieve from there. -func (p *Peer) RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error { - if len(accounts) == 1 && origin != nil { - p.logger.Trace("Fetching range of large storage slots", "reqid", id, "root", root, "account", accounts[0], "origin", common.BytesToHash(origin), "limit", common.BytesToHash(limit), "bytes", common.StorageSize(bytes)) - } else { - p.logger.Trace("Fetching ranges of small storage slots", "reqid", id, "root", root, "accounts", len(accounts), "first", accounts[0], "bytes", common.StorageSize(bytes)) - } - requestTracker.Track(p.id, p.version, GetStorageRangesMsg, StorageRangesMsg, id) - return p2p.Send(p.rw, GetStorageRangesMsg, &GetStorageRangesPacket{ - ID: id, - Root: root, - Accounts: accounts, - Origin: origin, - Limit: limit, - Bytes: bytes, - }) -} - -// RequestByteCodes fetches a batch of bytecodes by hash. -func (p *Peer) RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error { - p.logger.Trace("Fetching set of byte codes", "reqid", id, "hashes", len(hashes), "bytes", common.StorageSize(bytes)) - - requestTracker.Track(p.id, p.version, GetByteCodesMsg, ByteCodesMsg, id) - return p2p.Send(p.rw, GetByteCodesMsg, &GetByteCodesPacket{ - ID: id, - Hashes: hashes, - Bytes: bytes, - }) -} - -// RequestTrieNodes fetches a batch of account or storage trie nodes rooted in -// a specific state trie. -func (p *Peer) RequestTrieNodes(id uint64, root common.Hash, paths []TrieNodePathSet, bytes uint64) error { - p.logger.Trace("Fetching set of trie nodes", "reqid", id, "root", root, "pathsets", len(paths), "bytes", common.StorageSize(bytes)) - - requestTracker.Track(p.id, p.version, GetTrieNodesMsg, TrieNodesMsg, id) - return p2p.Send(p.rw, GetTrieNodesMsg, &GetTrieNodesPacket{ - ID: id, - Root: root, - Paths: paths, - Bytes: bytes, - }) -} diff --git a/builder/eth/protocols/snap/protocol.go b/builder/eth/protocols/snap/protocol.go deleted file mode 100644 index 0db206b08..000000000 --- a/builder/eth/protocols/snap/protocol.go +++ /dev/null @@ -1,218 +0,0 @@ -// 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 snap - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" -) - -// Constants to match up protocol versions and messages -const ( - SNAP1 = 1 -) - -// ProtocolName is the official short name of the `snap` protocol used during -// devp2p capability negotiation. -const ProtocolName = "snap" - -// ProtocolVersions are the supported versions of the `snap` protocol (first -// is primary). -var ProtocolVersions = []uint{SNAP1} - -// protocolLengths are the number of implemented message corresponding to -// different protocol versions. -var protocolLengths = map[uint]uint64{SNAP1: 8} - -// maxMessageSize is the maximum cap on the size of a protocol message. -const maxMessageSize = 10 * 1024 * 1024 - -const ( - GetAccountRangeMsg = 0x00 - AccountRangeMsg = 0x01 - GetStorageRangesMsg = 0x02 - StorageRangesMsg = 0x03 - GetByteCodesMsg = 0x04 - ByteCodesMsg = 0x05 - GetTrieNodesMsg = 0x06 - TrieNodesMsg = 0x07 -) - -var ( - errMsgTooLarge = errors.New("message too long") - errDecode = errors.New("invalid message") - errInvalidMsgCode = errors.New("invalid message code") - errBadRequest = errors.New("bad request") -) - -// Packet represents a p2p message in the `snap` protocol. -type Packet interface { - Name() string // Name returns a string corresponding to the message type. - Kind() byte // Kind returns the message type. -} - -// GetAccountRangePacket represents an account query. -type GetAccountRangePacket struct { - ID uint64 // Request ID to match up responses with - Root common.Hash // Root hash of the account trie to serve - Origin common.Hash // Hash of the first account to retrieve - Limit common.Hash // Hash of the last account to retrieve - Bytes uint64 // Soft limit at which to stop returning data -} - -// AccountRangePacket represents an account query response. -type AccountRangePacket struct { - ID uint64 // ID of the request this is a response for - Accounts []*AccountData // List of consecutive accounts from the trie - Proof [][]byte // List of trie nodes proving the account range -} - -// AccountData represents a single account in a query response. -type AccountData struct { - Hash common.Hash // Hash of the account - Body rlp.RawValue // Account body in slim format -} - -// Unpack retrieves the accounts from the range packet and converts from slim -// wire representation to consensus format. The returned data is RLP encoded -// since it's expected to be serialized to disk without further interpretation. -// -// Note, this method does a round of RLP decoding and reencoding, so only use it -// once and cache the results if need be. Ideally discard the packet afterwards -// to not double the memory use. -func (p *AccountRangePacket) Unpack() ([]common.Hash, [][]byte, error) { - var ( - hashes = make([]common.Hash, len(p.Accounts)) - accounts = make([][]byte, len(p.Accounts)) - ) - for i, acc := range p.Accounts { - val, err := types.FullAccountRLP(acc.Body) - if err != nil { - return nil, nil, fmt.Errorf("invalid account %x: %v", acc.Body, err) - } - hashes[i], accounts[i] = acc.Hash, val - } - return hashes, accounts, nil -} - -// GetStorageRangesPacket represents an storage slot query. -type GetStorageRangesPacket struct { - ID uint64 // Request ID to match up responses with - Root common.Hash // Root hash of the account trie to serve - Accounts []common.Hash // Account hashes of the storage tries to serve - Origin []byte // Hash of the first storage slot to retrieve (large contract mode) - Limit []byte // Hash of the last storage slot to retrieve (large contract mode) - Bytes uint64 // Soft limit at which to stop returning data -} - -// StorageRangesPacket represents a storage slot query response. -type StorageRangesPacket struct { - ID uint64 // ID of the request this is a response for - Slots [][]*StorageData // Lists of consecutive storage slots for the requested accounts - Proof [][]byte // Merkle proofs for the *last* slot range, if it's incomplete -} - -// StorageData represents a single storage slot in a query response. -type StorageData struct { - Hash common.Hash // Hash of the storage slot - Body []byte // Data content of the slot -} - -// Unpack retrieves the storage slots from the range packet and returns them in -// a split flat format that's more consistent with the internal data structures. -func (p *StorageRangesPacket) Unpack() ([][]common.Hash, [][][]byte) { - var ( - hashset = make([][]common.Hash, len(p.Slots)) - slotset = make([][][]byte, len(p.Slots)) - ) - for i, slots := range p.Slots { - hashset[i] = make([]common.Hash, len(slots)) - slotset[i] = make([][]byte, len(slots)) - for j, slot := range slots { - hashset[i][j] = slot.Hash - slotset[i][j] = slot.Body - } - } - return hashset, slotset -} - -// GetByteCodesPacket represents a contract bytecode query. -type GetByteCodesPacket struct { - ID uint64 // Request ID to match up responses with - Hashes []common.Hash // Code hashes to retrieve the code for - Bytes uint64 // Soft limit at which to stop returning data -} - -// ByteCodesPacket represents a contract bytecode query response. -type ByteCodesPacket struct { - ID uint64 // ID of the request this is a response for - Codes [][]byte // Requested contract bytecodes -} - -// GetTrieNodesPacket represents a state trie node query. -type GetTrieNodesPacket struct { - ID uint64 // Request ID to match up responses with - Root common.Hash // Root hash of the account trie to serve - Paths []TrieNodePathSet // Trie node hashes to retrieve the nodes for - Bytes uint64 // Soft limit at which to stop returning data -} - -// TrieNodePathSet is a list of trie node paths to retrieve. A naive way to -// represent trie nodes would be a simple list of `account || storage` path -// segments concatenated, but that would be very wasteful on the network. -// -// Instead, this array special cases the first element as the path in the -// account trie and the remaining elements as paths in the storage trie. To -// address an account node, the slice should have a length of 1 consisting -// of only the account path. There's no need to be able to address both an -// account node and a storage node in the same request as it cannot happen -// that a slot is accessed before the account path is fully expanded. -type TrieNodePathSet [][]byte - -// TrieNodesPacket represents a state trie node query response. -type TrieNodesPacket struct { - ID uint64 // ID of the request this is a response for - Nodes [][]byte // Requested state trie nodes -} - -func (*GetAccountRangePacket) Name() string { return "GetAccountRange" } -func (*GetAccountRangePacket) Kind() byte { return GetAccountRangeMsg } - -func (*AccountRangePacket) Name() string { return "AccountRange" } -func (*AccountRangePacket) Kind() byte { return AccountRangeMsg } - -func (*GetStorageRangesPacket) Name() string { return "GetStorageRanges" } -func (*GetStorageRangesPacket) Kind() byte { return GetStorageRangesMsg } - -func (*StorageRangesPacket) Name() string { return "StorageRanges" } -func (*StorageRangesPacket) Kind() byte { return StorageRangesMsg } - -func (*GetByteCodesPacket) Name() string { return "GetByteCodes" } -func (*GetByteCodesPacket) Kind() byte { return GetByteCodesMsg } - -func (*ByteCodesPacket) Name() string { return "ByteCodes" } -func (*ByteCodesPacket) Kind() byte { return ByteCodesMsg } - -func (*GetTrieNodesPacket) Name() string { return "GetTrieNodes" } -func (*GetTrieNodesPacket) Kind() byte { return GetTrieNodesMsg } - -func (*TrieNodesPacket) Name() string { return "TrieNodes" } -func (*TrieNodesPacket) Kind() byte { return TrieNodesMsg } diff --git a/builder/eth/protocols/snap/range.go b/builder/eth/protocols/snap/range.go deleted file mode 100644 index 8c98c71d5..000000000 --- a/builder/eth/protocols/snap/range.go +++ /dev/null @@ -1,81 +0,0 @@ -// 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 snap - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/holiman/uint256" -) - -// hashRange is a utility to handle ranges of hashes, Split up the -// hash-space into sections, and 'walk' over the sections -type hashRange struct { - current *uint256.Int - step *uint256.Int -} - -// newHashRange creates a new hashRange, initiated at the start position, -// and with the step set to fill the desired 'num' chunks -func newHashRange(start common.Hash, num uint64) *hashRange { - left := new(big.Int).Sub(hashSpace, start.Big()) - step := new(big.Int).Div( - new(big.Int).Add(left, new(big.Int).SetUint64(num-1)), - new(big.Int).SetUint64(num), - ) - step256 := new(uint256.Int) - step256.SetFromBig(step) - - return &hashRange{ - current: new(uint256.Int).SetBytes32(start[:]), - step: step256, - } -} - -// Next pushes the hash range to the next interval. -func (r *hashRange) Next() bool { - next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) - if overflow { - return false - } - r.current = next - return true -} - -// Start returns the first hash in the current interval. -func (r *hashRange) Start() common.Hash { - return r.current.Bytes32() -} - -// End returns the last hash in the current interval. -func (r *hashRange) End() common.Hash { - // If the end overflows (non divisible range), return a shorter interval - next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) - if overflow { - return common.MaxHash - } - return next.SubUint64(next, 1).Bytes32() -} - -// incHash returns the next hash, in lexicographical order (a.k.a plus one) -func incHash(h common.Hash) common.Hash { - var a uint256.Int - a.SetBytes32(h[:]) - a.AddUint64(&a, 1) - return common.Hash(a.Bytes32()) -} diff --git a/builder/eth/protocols/snap/range_test.go b/builder/eth/protocols/snap/range_test.go deleted file mode 100644 index ea643f136..000000000 --- a/builder/eth/protocols/snap/range_test.go +++ /dev/null @@ -1,143 +0,0 @@ -// 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 snap - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -// Tests that given a starting hash and a density, the hash ranger can correctly -// split up the remaining hash space into a fixed number of chunks. -func TestHashRanges(t *testing.T) { - tests := []struct { - head common.Hash - chunks uint64 - starts []common.Hash - ends []common.Hash - }{ - // Simple test case to split the entire hash range into 4 chunks - { - head: common.Hash{}, - chunks: 4, - starts: []common.Hash{ - {}, - common.HexToHash("0x4000000000000000000000000000000000000000000000000000000000000000"), - common.HexToHash("0x8000000000000000000000000000000000000000000000000000000000000000"), - common.HexToHash("0xc000000000000000000000000000000000000000000000000000000000000000"), - }, - ends: []common.Hash{ - common.HexToHash("0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.HexToHash("0xbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.MaxHash, - }, - }, - // Split a divisible part of the hash range up into 2 chunks - { - head: common.HexToHash("0x2000000000000000000000000000000000000000000000000000000000000000"), - chunks: 2, - starts: []common.Hash{ - {}, - common.HexToHash("0x9000000000000000000000000000000000000000000000000000000000000000"), - }, - ends: []common.Hash{ - common.HexToHash("0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - common.MaxHash, - }, - }, - // Split the entire hash range into a non divisible 3 chunks - { - head: common.Hash{}, - chunks: 3, - starts: []common.Hash{ - {}, - common.HexToHash("0x5555555555555555555555555555555555555555555555555555555555555556"), - common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"), - }, - ends: []common.Hash{ - common.HexToHash("0x5555555555555555555555555555555555555555555555555555555555555555"), - common.HexToHash("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"), - common.MaxHash, - }, - }, - // Split a part of hash range into a non divisible 3 chunks - { - head: common.HexToHash("0x2000000000000000000000000000000000000000000000000000000000000000"), - chunks: 3, - starts: []common.Hash{ - {}, - common.HexToHash("0x6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"), - common.HexToHash("0xb555555555555555555555555555555555555555555555555555555555555556"), - }, - ends: []common.Hash{ - common.HexToHash("0x6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - common.HexToHash("0xb555555555555555555555555555555555555555555555555555555555555555"), - common.MaxHash, - }, - }, - // Split a part of hash range into a non divisible 3 chunks, but with a - // meaningful space size for manual verification. - // - The head being 0xff...f0, we have 14 hashes left in the space - // - Chunking up 14 into 3 pieces is 4.(6), but we need the ceil of 5 to avoid a micro-last-chunk - // - Since the range is not divisible, the last interval will be shorter, capped at 0xff...f - // - The chunk ranges thus needs to be [..0, ..5], [..6, ..b], [..c, ..f] - { - head: common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"), - chunks: 3, - starts: []common.Hash{ - {}, - common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"), - common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"), - }, - ends: []common.Hash{ - common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5"), - common.HexToHash("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"), - common.MaxHash, - }, - }, - } - for i, tt := range tests { - r := newHashRange(tt.head, tt.chunks) - - var ( - starts = []common.Hash{{}} - ends = []common.Hash{r.End()} - ) - for r.Next() { - starts = append(starts, r.Start()) - ends = append(ends, r.End()) - } - if len(starts) != len(tt.starts) { - t.Errorf("test %d: starts count mismatch: have %d, want %d", i, len(starts), len(tt.starts)) - } - for j := 0; j < len(starts) && j < len(tt.starts); j++ { - if starts[j] != tt.starts[j] { - t.Errorf("test %d, start %d: hash mismatch: have %x, want %x", i, j, starts[j], tt.starts[j]) - } - } - if len(ends) != len(tt.ends) { - t.Errorf("test %d: ends count mismatch: have %d, want %d", i, len(ends), len(tt.ends)) - } - for j := 0; j < len(ends) && j < len(tt.ends); j++ { - if ends[j] != tt.ends[j] { - t.Errorf("test %d, end %d: hash mismatch: have %x, want %x", i, j, ends[j], tt.ends[j]) - } - } - } -} diff --git a/builder/eth/protocols/snap/sort_test.go b/builder/eth/protocols/snap/sort_test.go deleted file mode 100644 index be0a8c570..000000000 --- a/builder/eth/protocols/snap/sort_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// 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 snap - -import ( - "bytes" - "fmt" - "testing" - - "github.com/ethereum/go-ethereum/common" -) - -func hexToNibbles(s string) []byte { - if len(s) >= 2 && s[0] == '0' && s[1] == 'x' { - s = s[2:] - } - var s2 []byte - for _, ch := range []byte(s) { - s2 = append(s2, '0') - s2 = append(s2, ch) - } - return common.Hex2Bytes(string(s2)) -} - -func TestRequestSorting(t *testing.T) { - // - Path 0x9 -> {0x19} - // - Path 0x99 -> {0x0099} - // - Path 0x01234567890123456789012345678901012345678901234567890123456789019 -> {0x0123456789012345678901234567890101234567890123456789012345678901, 0x19} - // - Path 0x012345678901234567890123456789010123456789012345678901234567890199 -> {0x0123456789012345678901234567890101234567890123456789012345678901, 0x0099} - var f = func(path string) string { - data := hexToNibbles(path) - return string(data) - } - var ( - hashes []common.Hash - paths []string - ) - for _, x := range []string{ - "0x9", - "0x012345678901234567890123456789010123456789012345678901234567890195", - "0x012345678901234567890123456789010123456789012345678901234567890197", - "0x012345678901234567890123456789010123456789012345678901234567890196", - "0x99", - "0x012345678901234567890123456789010123456789012345678901234567890199", - "0x01234567890123456789012345678901012345678901234567890123456789019", - "0x0123456789012345678901234567890101234567890123456789012345678901", - "0x01234567890123456789012345678901012345678901234567890123456789010", - "0x01234567890123456789012345678901012345678901234567890123456789011", - } { - paths = append(paths, f(x)) - hashes = append(hashes, common.Hash{}) - } - _, _, syncPaths, pathsets := sortByAccountPath(paths, hashes) - { - var b = new(bytes.Buffer) - for i := 0; i < len(syncPaths); i++ { - fmt.Fprintf(b, "\n%d. paths %x", i, syncPaths[i]) - } - want := ` -0. paths [0099] -1. paths [0123456789012345678901234567890101234567890123456789012345678901 00] -2. paths [0123456789012345678901234567890101234567890123456789012345678901 0095] -3. paths [0123456789012345678901234567890101234567890123456789012345678901 0096] -4. paths [0123456789012345678901234567890101234567890123456789012345678901 0097] -5. paths [0123456789012345678901234567890101234567890123456789012345678901 0099] -6. paths [0123456789012345678901234567890101234567890123456789012345678901 10] -7. paths [0123456789012345678901234567890101234567890123456789012345678901 11] -8. paths [0123456789012345678901234567890101234567890123456789012345678901 19] -9. paths [19]` - if have := b.String(); have != want { - t.Errorf("have:%v\nwant:%v\n", have, want) - } - } - { - var b = new(bytes.Buffer) - for i := 0; i < len(pathsets); i++ { - fmt.Fprintf(b, "\n%d. pathset %x", i, pathsets[i]) - } - want := ` -0. pathset [0099] -1. pathset [0123456789012345678901234567890101234567890123456789012345678901 00 0095 0096 0097 0099 10 11 19] -2. pathset [19]` - if have := b.String(); have != want { - t.Errorf("have:%v\nwant:%v\n", have, want) - } - } -} diff --git a/builder/eth/protocols/snap/sync.go b/builder/eth/protocols/snap/sync.go deleted file mode 100644 index 887a50775..000000000 --- a/builder/eth/protocols/snap/sync.go +++ /dev/null @@ -1,3210 +0,0 @@ -// 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 snap - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - gomath "math" - "math/big" - "math/rand" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/msgrate" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/trienode" - "golang.org/x/crypto/sha3" -) - -const ( - // minRequestSize is the minimum number of bytes to request from a remote peer. - // This number is used as the low cap for account and storage range requests. - // Bytecode and trienode are limited inherently by item count (1). - minRequestSize = 64 * 1024 - - // maxRequestSize is the maximum number of bytes to request from a remote peer. - // This number is used as the high cap for account and storage range requests. - // Bytecode and trienode are limited more explicitly by the caps below. - maxRequestSize = 512 * 1024 - - // maxCodeRequestCount is the maximum number of bytecode blobs to request in a - // single query. If this number is too low, we're not filling responses fully - // and waste round trip times. If it's too high, we're capping responses and - // waste bandwidth. - // - // Deployed bytecodes are currently capped at 24KB, so the minimum request - // size should be maxRequestSize / 24K. Assuming that most contracts do not - // come close to that, requesting 4x should be a good approximation. - maxCodeRequestCount = maxRequestSize / (24 * 1024) * 4 - - // maxTrieRequestCount is the maximum number of trie node blobs to request in - // a single query. If this number is too low, we're not filling responses fully - // and waste round trip times. If it's too high, we're capping responses and - // waste bandwidth. - maxTrieRequestCount = maxRequestSize / 512 - - // trienodeHealRateMeasurementImpact is the impact a single measurement has on - // the local node's trienode processing capacity. A value closer to 0 reacts - // slower to sudden changes, but it is also more stable against temporary hiccups. - trienodeHealRateMeasurementImpact = 0.005 - - // minTrienodeHealThrottle is the minimum divisor for throttling trie node - // heal requests to avoid overloading the local node and excessively expanding - // the state trie breadth wise. - minTrienodeHealThrottle = 1 - - // maxTrienodeHealThrottle is the maximum divisor for throttling trie node - // heal requests to avoid overloading the local node and exessively expanding - // the state trie bedth wise. - maxTrienodeHealThrottle = maxTrieRequestCount - - // trienodeHealThrottleIncrease is the multiplier for the throttle when the - // rate of arriving data is higher than the rate of processing it. - trienodeHealThrottleIncrease = 1.33 - - // trienodeHealThrottleDecrease is the divisor for the throttle when the - // rate of arriving data is lower than the rate of processing it. - trienodeHealThrottleDecrease = 1.25 -) - -var ( - // accountConcurrency is the number of chunks to split the account trie into - // to allow concurrent retrievals. - accountConcurrency = 16 - - // storageConcurrency is the number of chunks to split the a large contract - // storage trie into to allow concurrent retrievals. - storageConcurrency = 16 -) - -// ErrCancelled is returned from snap syncing if the operation was prematurely -// terminated. -var ErrCancelled = errors.New("sync cancelled") - -// accountRequest tracks a pending account range request to ensure responses are -// to actual requests and to validate any security constraints. -// -// Concurrency note: account requests and responses are handled concurrently from -// the main runloop to allow Merkle proof verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. task). That -// is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type accountRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - time time.Time // Timestamp when the request was sent - - deliver chan *accountResponse // Channel to deliver successful response on - revert chan *accountRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - timeout *time.Timer // Timer to track delivery timeout - stale chan struct{} // Channel to signal the request was dropped - - origin common.Hash // First account requested to allow continuation checks - limit common.Hash // Last account requested to allow non-overlapping chunking - - task *accountTask // Task which this request is filling (only access fields through the runloop!!) -} - -// accountResponse is an already Merkle-verified remote response to an account -// range request. It contains the subtrie for the requested account range and -// the database that's going to be filled with the internal nodes on commit. -type accountResponse struct { - task *accountTask // Task which this request is filling - - hashes []common.Hash // Account hashes in the returned range - accounts []*types.StateAccount // Expanded accounts in the returned range - - cont bool // Whether the account range has a continuation -} - -// bytecodeRequest tracks a pending bytecode request to ensure responses are to -// actual requests and to validate any security constraints. -// -// Concurrency note: bytecode requests and responses are handled concurrently from -// the main runloop to allow Keccak256 hash verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. task). That -// is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type bytecodeRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - time time.Time // Timestamp when the request was sent - - deliver chan *bytecodeResponse // Channel to deliver successful response on - revert chan *bytecodeRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - timeout *time.Timer // Timer to track delivery timeout - stale chan struct{} // Channel to signal the request was dropped - - hashes []common.Hash // Bytecode hashes to validate responses - task *accountTask // Task which this request is filling (only access fields through the runloop!!) -} - -// bytecodeResponse is an already verified remote response to a bytecode request. -type bytecodeResponse struct { - task *accountTask // Task which this request is filling - - hashes []common.Hash // Hashes of the bytecode to avoid double hashing - codes [][]byte // Actual bytecodes to store into the database (nil = missing) -} - -// storageRequest tracks a pending storage ranges request to ensure responses are -// to actual requests and to validate any security constraints. -// -// Concurrency note: storage requests and responses are handled concurrently from -// the main runloop to allow Merkle proof verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. tasks). That -// is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type storageRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - time time.Time // Timestamp when the request was sent - - deliver chan *storageResponse // Channel to deliver successful response on - revert chan *storageRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - timeout *time.Timer // Timer to track delivery timeout - stale chan struct{} // Channel to signal the request was dropped - - accounts []common.Hash // Account hashes to validate responses - roots []common.Hash // Storage roots to validate responses - - origin common.Hash // First storage slot requested to allow continuation checks - limit common.Hash // Last storage slot requested to allow non-overlapping chunking - - mainTask *accountTask // Task which this response belongs to (only access fields through the runloop!!) - subTask *storageTask // Task which this response is filling (only access fields through the runloop!!) -} - -// storageResponse is an already Merkle-verified remote response to a storage -// range request. It contains the subtries for the requested storage ranges and -// the databases that's going to be filled with the internal nodes on commit. -type storageResponse struct { - mainTask *accountTask // Task which this response belongs to - subTask *storageTask // Task which this response is filling - - accounts []common.Hash // Account hashes requested, may be only partially filled - roots []common.Hash // Storage roots requested, may be only partially filled - - hashes [][]common.Hash // Storage slot hashes in the returned range - slots [][][]byte // Storage slot values in the returned range - - cont bool // Whether the last storage range has a continuation -} - -// trienodeHealRequest tracks a pending state trie request to ensure responses -// are to actual requests and to validate any security constraints. -// -// Concurrency note: trie node requests and responses are handled concurrently from -// the main runloop to allow Keccak256 hash verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. task). That -// is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type trienodeHealRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - time time.Time // Timestamp when the request was sent - - deliver chan *trienodeHealResponse // Channel to deliver successful response on - revert chan *trienodeHealRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - timeout *time.Timer // Timer to track delivery timeout - stale chan struct{} // Channel to signal the request was dropped - - paths []string // Trie node paths for identifying trie node - hashes []common.Hash // Trie node hashes to validate responses - - task *healTask // Task which this request is filling (only access fields through the runloop!!) -} - -// trienodeHealResponse is an already verified remote response to a trie node request. -type trienodeHealResponse struct { - task *healTask // Task which this request is filling - - paths []string // Paths of the trie nodes - hashes []common.Hash // Hashes of the trie nodes to avoid double hashing - nodes [][]byte // Actual trie nodes to store into the database (nil = missing) -} - -// bytecodeHealRequest tracks a pending bytecode request to ensure responses are to -// actual requests and to validate any security constraints. -// -// Concurrency note: bytecode requests and responses are handled concurrently from -// the main runloop to allow Keccak256 hash verifications on the peer's thread and -// to drop on invalid response. The request struct must contain all the data to -// construct the response without accessing runloop internals (i.e. task). That -// is only included to allow the runloop to match a response to the task being -// synced without having yet another set of maps. -type bytecodeHealRequest struct { - peer string // Peer to which this request is assigned - id uint64 // Request ID of this request - time time.Time // Timestamp when the request was sent - - deliver chan *bytecodeHealResponse // Channel to deliver successful response on - revert chan *bytecodeHealRequest // Channel to deliver request failure on - cancel chan struct{} // Channel to track sync cancellation - timeout *time.Timer // Timer to track delivery timeout - stale chan struct{} // Channel to signal the request was dropped - - hashes []common.Hash // Bytecode hashes to validate responses - task *healTask // Task which this request is filling (only access fields through the runloop!!) -} - -// bytecodeHealResponse is an already verified remote response to a bytecode request. -type bytecodeHealResponse struct { - task *healTask // Task which this request is filling - - hashes []common.Hash // Hashes of the bytecode to avoid double hashing - codes [][]byte // Actual bytecodes to store into the database (nil = missing) -} - -// accountTask represents the sync task for a chunk of the account snapshot. -type accountTask struct { - // These fields get serialized to leveldb on shutdown - Next common.Hash // Next account to sync in this interval - Last common.Hash // Last account to sync in this interval - SubTasks map[common.Hash][]*storageTask // Storage intervals needing fetching for large contracts - - // These fields are internals used during runtime - req *accountRequest // Pending request to fill this task - res *accountResponse // Validate response filling this task - pend int // Number of pending subtasks for this round - - needCode []bool // Flags whether the filling accounts need code retrieval - needState []bool // Flags whether the filling accounts need storage retrieval - needHeal []bool // Flags whether the filling accounts's state was chunked and need healing - - codeTasks map[common.Hash]struct{} // Code hashes that need retrieval - stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval - - genBatch ethdb.Batch // Batch used by the node generator - genTrie *trie.StackTrie // Node generator from storage slots - - done bool // Flag whether the task can be removed -} - -// storageTask represents the sync task for a chunk of the storage snapshot. -type storageTask struct { - Next common.Hash // Next account to sync in this interval - Last common.Hash // Last account to sync in this interval - - // These fields are internals used during runtime - root common.Hash // Storage root hash for this instance - req *storageRequest // Pending request to fill this task - - genBatch ethdb.Batch // Batch used by the node generator - genTrie *trie.StackTrie // Node generator from storage slots - - done bool // Flag whether the task can be removed -} - -// healTask represents the sync task for healing the snap-synced chunk boundaries. -type healTask struct { - scheduler *trie.Sync // State trie sync scheduler defining the tasks - - trieTasks map[string]common.Hash // Set of trie node tasks currently queued for retrieval, indexed by node path - codeTasks map[common.Hash]struct{} // Set of byte code tasks currently queued for retrieval, indexed by code hash -} - -// SyncProgress is a database entry to allow suspending and resuming a snapshot state -// sync. Opposed to full and fast sync, there is no way to restart a suspended -// snap sync without prior knowledge of the suspension point. -type SyncProgress struct { - Tasks []*accountTask // The suspended account tasks (contract tasks within) - - // Status report during syncing phase - AccountSynced uint64 // Number of accounts downloaded - AccountBytes common.StorageSize // Number of account trie bytes persisted to disk - BytecodeSynced uint64 // Number of bytecodes downloaded - BytecodeBytes common.StorageSize // Number of bytecode bytes downloaded - StorageSynced uint64 // Number of storage slots downloaded - StorageBytes common.StorageSize // Number of storage trie bytes persisted to disk - - // Status report during healing phase - TrienodeHealSynced uint64 // Number of state trie nodes downloaded - TrienodeHealBytes common.StorageSize // Number of state trie bytes persisted to disk - BytecodeHealSynced uint64 // Number of bytecodes downloaded - BytecodeHealBytes common.StorageSize // Number of bytecodes persisted to disk -} - -// SyncPending is analogous to SyncProgress, but it's used to report on pending -// ephemeral sync progress that doesn't get persisted into the database. -type SyncPending struct { - TrienodeHeal uint64 // Number of state trie nodes pending - BytecodeHeal uint64 // Number of bytecodes pending -} - -// SyncPeer abstracts out the methods required for a peer to be synced against -// with the goal of allowing the construction of mock peers without the full -// blown networking. -type SyncPeer interface { - // ID retrieves the peer's unique identifier. - ID() string - - // RequestAccountRange fetches a batch of accounts rooted in a specific account - // trie, starting with the origin. - RequestAccountRange(id uint64, root, origin, limit common.Hash, bytes uint64) error - - // RequestStorageRanges fetches a batch of storage slots belonging to one or - // more accounts. If slots from only one account is requested, an origin marker - // may also be used to retrieve from there. - RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error - - // RequestByteCodes fetches a batch of bytecodes by hash. - RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error - - // RequestTrieNodes fetches a batch of account or storage trie nodes rooted in - // a specific state trie. - RequestTrieNodes(id uint64, root common.Hash, paths []TrieNodePathSet, bytes uint64) error - - // Log retrieves the peer's own contextual logger. - Log() log.Logger -} - -// Syncer is an Ethereum account and storage trie syncer based on snapshots and -// the snap protocol. It's purpose is to download all the accounts and storage -// slots from remote peers and reassemble chunks of the state trie, on top of -// which a state sync can be run to fix any gaps / overlaps. -// -// Every network request has a variety of failure events: -// - The peer disconnects after task assignment, failing to send the request -// - The peer disconnects after sending the request, before delivering on it -// - The peer remains connected, but does not deliver a response in time -// - The peer delivers a stale response after a previous timeout -// - The peer delivers a refusal to serve the requested state -type Syncer struct { - db ethdb.KeyValueStore // Database to store the trie nodes into (and dedup) - scheme string // Node scheme used in node database - - root common.Hash // Current state trie root being synced - tasks []*accountTask // Current account task set being synced - snapped bool // Flag to signal that snap phase is done - healer *healTask // Current state healing task being executed - update chan struct{} // Notification channel for possible sync progression - - peers map[string]SyncPeer // Currently active peers to download from - peerJoin *event.Feed // Event feed to react to peers joining - peerDrop *event.Feed // Event feed to react to peers dropping - rates *msgrate.Trackers // Message throughput rates for peers - - // Request tracking during syncing phase - statelessPeers map[string]struct{} // Peers that failed to deliver state data - accountIdlers map[string]struct{} // Peers that aren't serving account requests - bytecodeIdlers map[string]struct{} // Peers that aren't serving bytecode requests - storageIdlers map[string]struct{} // Peers that aren't serving storage requests - - accountReqs map[uint64]*accountRequest // Account requests currently running - bytecodeReqs map[uint64]*bytecodeRequest // Bytecode requests currently running - storageReqs map[uint64]*storageRequest // Storage requests currently running - - accountSynced uint64 // Number of accounts downloaded - accountBytes common.StorageSize // Number of account trie bytes persisted to disk - bytecodeSynced uint64 // Number of bytecodes downloaded - bytecodeBytes common.StorageSize // Number of bytecode bytes downloaded - storageSynced uint64 // Number of storage slots downloaded - storageBytes common.StorageSize // Number of storage trie bytes persisted to disk - - extProgress *SyncProgress // progress that can be exposed to external caller. - - // Request tracking during healing phase - trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests - bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests - - trienodeHealReqs map[uint64]*trienodeHealRequest // Trie node requests currently running - bytecodeHealReqs map[uint64]*bytecodeHealRequest // Bytecode requests currently running - - trienodeHealRate float64 // Average heal rate for processing trie node data - trienodeHealPend atomic.Uint64 // Number of trie nodes currently pending for processing - trienodeHealThrottle float64 // Divisor for throttling the amount of trienode heal data requested - trienodeHealThrottled time.Time // Timestamp the last time the throttle was updated - - trienodeHealSynced uint64 // Number of state trie nodes downloaded - trienodeHealBytes common.StorageSize // Number of state trie bytes persisted to disk - trienodeHealDups uint64 // Number of state trie nodes already processed - trienodeHealNops uint64 // Number of state trie nodes not requested - bytecodeHealSynced uint64 // Number of bytecodes downloaded - bytecodeHealBytes common.StorageSize // Number of bytecodes persisted to disk - bytecodeHealDups uint64 // Number of bytecodes already processed - bytecodeHealNops uint64 // Number of bytecodes not requested - - stateWriter ethdb.Batch // Shared batch writer used for persisting raw states - accountHealed uint64 // Number of accounts downloaded during the healing stage - accountHealedBytes common.StorageSize // Number of raw account bytes persisted to disk during the healing stage - storageHealed uint64 // Number of storage slots downloaded during the healing stage - storageHealedBytes common.StorageSize // Number of raw storage bytes persisted to disk during the healing stage - - startTime time.Time // Time instance when snapshot sync started - logTime time.Time // Time instance when status was last reported - - pend sync.WaitGroup // Tracks network request goroutines for graceful shutdown - lock sync.RWMutex // Protects fields that can change outside of sync (peers, reqs, root) -} - -// NewSyncer creates a new snapshot syncer to download the Ethereum state over the -// snap protocol. -func NewSyncer(db ethdb.KeyValueStore, scheme string) *Syncer { - return &Syncer{ - db: db, - scheme: scheme, - - peers: make(map[string]SyncPeer), - peerJoin: new(event.Feed), - peerDrop: new(event.Feed), - rates: msgrate.NewTrackers(log.New("proto", "snap")), - update: make(chan struct{}, 1), - - accountIdlers: make(map[string]struct{}), - storageIdlers: make(map[string]struct{}), - bytecodeIdlers: make(map[string]struct{}), - - accountReqs: make(map[uint64]*accountRequest), - storageReqs: make(map[uint64]*storageRequest), - bytecodeReqs: make(map[uint64]*bytecodeRequest), - - trienodeHealIdlers: make(map[string]struct{}), - bytecodeHealIdlers: make(map[string]struct{}), - - trienodeHealReqs: make(map[uint64]*trienodeHealRequest), - bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest), - trienodeHealThrottle: maxTrienodeHealThrottle, // Tune downward instead of insta-filling with junk - stateWriter: db.NewBatch(), - - extProgress: new(SyncProgress), - } -} - -// Register injects a new data source into the syncer's peerset. -func (s *Syncer) Register(peer SyncPeer) error { - // Make sure the peer is not registered yet - id := peer.ID() - - s.lock.Lock() - if _, ok := s.peers[id]; ok { - log.Error("Snap peer already registered", "id", id) - - s.lock.Unlock() - return errors.New("already registered") - } - s.peers[id] = peer - s.rates.Track(id, msgrate.NewTracker(s.rates.MeanCapacities(), s.rates.MedianRoundTrip())) - - // Mark the peer as idle, even if no sync is running - s.accountIdlers[id] = struct{}{} - s.storageIdlers[id] = struct{}{} - s.bytecodeIdlers[id] = struct{}{} - s.trienodeHealIdlers[id] = struct{}{} - s.bytecodeHealIdlers[id] = struct{}{} - s.lock.Unlock() - - // Notify any active syncs that a new peer can be assigned data - s.peerJoin.Send(id) - return nil -} - -// Unregister injects a new data source into the syncer's peerset. -func (s *Syncer) Unregister(id string) error { - // Remove all traces of the peer from the registry - s.lock.Lock() - if _, ok := s.peers[id]; !ok { - log.Error("Snap peer not registered", "id", id) - - s.lock.Unlock() - return errors.New("not registered") - } - delete(s.peers, id) - s.rates.Untrack(id) - - // Remove status markers, even if no sync is running - delete(s.statelessPeers, id) - - delete(s.accountIdlers, id) - delete(s.storageIdlers, id) - delete(s.bytecodeIdlers, id) - delete(s.trienodeHealIdlers, id) - delete(s.bytecodeHealIdlers, id) - s.lock.Unlock() - - // Notify any active syncs that pending requests need to be reverted - s.peerDrop.Send(id) - return nil -} - -// Sync starts (or resumes a previous) sync cycle to iterate over a state trie -// with the given root and reconstruct the nodes based on the snapshot leaves. -// Previously downloaded segments will not be redownloaded of fixed, rather any -// errors will be healed after the leaves are fully accumulated. -func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error { - // Move the trie root from any previous value, revert stateless markers for - // any peers and initialize the syncer if it was not yet run - s.lock.Lock() - s.root = root - s.healer = &healTask{ - scheduler: state.NewStateSync(root, s.db, s.onHealState, s.scheme), - trieTasks: make(map[string]common.Hash), - codeTasks: make(map[common.Hash]struct{}), - } - s.statelessPeers = make(map[string]struct{}) - s.lock.Unlock() - - if s.startTime == (time.Time{}) { - s.startTime = time.Now() - } - // Retrieve the previous sync status from LevelDB and abort if already synced - s.loadSyncStatus() - if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 { - log.Debug("Snapshot sync already completed") - return nil - } - defer func() { // Persist any progress, independent of failure - for _, task := range s.tasks { - s.forwardAccountTask(task) - } - s.cleanAccountTasks() - s.saveSyncStatus() - }() - - log.Debug("Starting snapshot sync cycle", "root", root) - - // Flush out the last committed raw states - defer func() { - if s.stateWriter.ValueSize() > 0 { - s.stateWriter.Write() - s.stateWriter.Reset() - } - }() - defer s.report(true) - // commit any trie- and bytecode-healing data. - defer s.commitHealer(true) - - // Whether sync completed or not, disregard any future packets - defer func() { - log.Debug("Terminating snapshot sync cycle", "root", root) - s.lock.Lock() - s.accountReqs = make(map[uint64]*accountRequest) - s.storageReqs = make(map[uint64]*storageRequest) - s.bytecodeReqs = make(map[uint64]*bytecodeRequest) - s.trienodeHealReqs = make(map[uint64]*trienodeHealRequest) - s.bytecodeHealReqs = make(map[uint64]*bytecodeHealRequest) - s.lock.Unlock() - }() - // Keep scheduling sync tasks - peerJoin := make(chan string, 16) - peerJoinSub := s.peerJoin.Subscribe(peerJoin) - defer peerJoinSub.Unsubscribe() - - peerDrop := make(chan string, 16) - peerDropSub := s.peerDrop.Subscribe(peerDrop) - defer peerDropSub.Unsubscribe() - - // Create a set of unique channels for this sync cycle. We need these to be - // ephemeral so a data race doesn't accidentally deliver something stale on - // a persistent channel across syncs (yup, this happened) - var ( - accountReqFails = make(chan *accountRequest) - storageReqFails = make(chan *storageRequest) - bytecodeReqFails = make(chan *bytecodeRequest) - accountResps = make(chan *accountResponse) - storageResps = make(chan *storageResponse) - bytecodeResps = make(chan *bytecodeResponse) - trienodeHealReqFails = make(chan *trienodeHealRequest) - bytecodeHealReqFails = make(chan *bytecodeHealRequest) - trienodeHealResps = make(chan *trienodeHealResponse) - bytecodeHealResps = make(chan *bytecodeHealResponse) - ) - for { - // Remove all completed tasks and terminate sync if everything's done - s.cleanStorageTasks() - s.cleanAccountTasks() - if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 { - return nil - } - // Assign all the data retrieval tasks to any free peers - s.assignAccountTasks(accountResps, accountReqFails, cancel) - s.assignBytecodeTasks(bytecodeResps, bytecodeReqFails, cancel) - s.assignStorageTasks(storageResps, storageReqFails, cancel) - - if len(s.tasks) == 0 { - // Sync phase done, run heal phase - s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel) - s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel) - } - // Update sync progress - s.lock.Lock() - s.extProgress = &SyncProgress{ - AccountSynced: s.accountSynced, - AccountBytes: s.accountBytes, - BytecodeSynced: s.bytecodeSynced, - BytecodeBytes: s.bytecodeBytes, - StorageSynced: s.storageSynced, - StorageBytes: s.storageBytes, - TrienodeHealSynced: s.trienodeHealSynced, - TrienodeHealBytes: s.trienodeHealBytes, - BytecodeHealSynced: s.bytecodeHealSynced, - BytecodeHealBytes: s.bytecodeHealBytes, - } - s.lock.Unlock() - // Wait for something to happen - select { - case <-s.update: - // Something happened (new peer, delivery, timeout), recheck tasks - case <-peerJoin: - // A new peer joined, try to schedule it new tasks - case id := <-peerDrop: - s.revertRequests(id) - case <-cancel: - return ErrCancelled - - case req := <-accountReqFails: - s.revertAccountRequest(req) - case req := <-bytecodeReqFails: - s.revertBytecodeRequest(req) - case req := <-storageReqFails: - s.revertStorageRequest(req) - case req := <-trienodeHealReqFails: - s.revertTrienodeHealRequest(req) - case req := <-bytecodeHealReqFails: - s.revertBytecodeHealRequest(req) - - case res := <-accountResps: - s.processAccountResponse(res) - case res := <-bytecodeResps: - s.processBytecodeResponse(res) - case res := <-storageResps: - s.processStorageResponse(res) - case res := <-trienodeHealResps: - s.processTrienodeHealResponse(res) - case res := <-bytecodeHealResps: - s.processBytecodeHealResponse(res) - } - // Report stats if something meaningful happened - s.report(false) - } -} - -// cleanPath is used to remove the dangling nodes in the stackTrie. -func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) { - if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db, path) { - rawdb.DeleteAccountTrieNode(batch, path) - deletionGauge.Inc(1) - } - if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db, owner, path) { - rawdb.DeleteStorageTrieNode(batch, owner, path) - deletionGauge.Inc(1) - } - lookupGauge.Inc(1) -} - -// loadSyncStatus retrieves a previously aborted sync status from the database, -// or generates a fresh one if none is available. -func (s *Syncer) loadSyncStatus() { - var progress SyncProgress - - if status := rawdb.ReadSnapshotSyncStatus(s.db); status != nil { - if err := json.Unmarshal(status, &progress); err != nil { - log.Error("Failed to decode snap sync status", "err", err) - } else { - for _, task := range progress.Tasks { - log.Debug("Scheduled account sync task", "from", task.Next, "last", task.Last) - } - s.tasks = progress.Tasks - for _, task := range s.tasks { - task := task // closure for task.genBatch in the stacktrie writer callback - - task.genBatch = ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.accountBytes += common.StorageSize(len(key) + len(value)) - }, - } - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - // Configure the dangling node cleaner and also filter out boundary nodes - // only in the context of the path scheme. Deletion is forbidden in the - // hash scheme, as it can disrupt state completeness. - options = options.WithCleaner(func(path []byte) { - s.cleanPath(task.genBatch, common.Hash{}, path) - }) - // Skip the left boundary if it's not the first range. - // Skip the right boundary if it's not the last range. - options = options.WithSkipBoundary(task.Next != (common.Hash{}), task.Last != common.MaxHash, boundaryAccountNodesGauge) - } - task.genTrie = trie.NewStackTrie(options) - for accountHash, subtasks := range task.SubTasks { - for _, subtask := range subtasks { - subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback - - subtask.genBatch = ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.storageBytes += common.StorageSize(len(key) + len(value)) - }, - } - owner := accountHash // local assignment for stacktrie writer closure - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - // Configure the dangling node cleaner and also filter out boundary nodes - // only in the context of the path scheme. Deletion is forbidden in the - // hash scheme, as it can disrupt state completeness. - options = options.WithCleaner(func(path []byte) { - s.cleanPath(subtask.genBatch, owner, path) - }) - // Skip the left boundary if it's not the first range. - // Skip the right boundary if it's not the last range. - options = options.WithSkipBoundary(subtask.Next != common.Hash{}, subtask.Last != common.MaxHash, boundaryStorageNodesGauge) - } - subtask.genTrie = trie.NewStackTrie(options) - } - } - } - s.lock.Lock() - defer s.lock.Unlock() - - s.snapped = len(s.tasks) == 0 - - s.accountSynced = progress.AccountSynced - s.accountBytes = progress.AccountBytes - s.bytecodeSynced = progress.BytecodeSynced - s.bytecodeBytes = progress.BytecodeBytes - s.storageSynced = progress.StorageSynced - s.storageBytes = progress.StorageBytes - - s.trienodeHealSynced = progress.TrienodeHealSynced - s.trienodeHealBytes = progress.TrienodeHealBytes - s.bytecodeHealSynced = progress.BytecodeHealSynced - s.bytecodeHealBytes = progress.BytecodeHealBytes - return - } - } - // Either we've failed to decode the previous state, or there was none. - // Start a fresh sync by chunking up the account range and scheduling - // them for retrieval. - s.tasks = nil - s.accountSynced, s.accountBytes = 0, 0 - s.bytecodeSynced, s.bytecodeBytes = 0, 0 - s.storageSynced, s.storageBytes = 0, 0 - s.trienodeHealSynced, s.trienodeHealBytes = 0, 0 - s.bytecodeHealSynced, s.bytecodeHealBytes = 0, 0 - - var next common.Hash - step := new(big.Int).Sub( - new(big.Int).Div( - new(big.Int).Exp(common.Big2, common.Big256, nil), - big.NewInt(int64(accountConcurrency)), - ), common.Big1, - ) - for i := 0; i < accountConcurrency; i++ { - last := common.BigToHash(new(big.Int).Add(next.Big(), step)) - if i == accountConcurrency-1 { - // Make sure we don't overflow if the step is not a proper divisor - last = common.MaxHash - } - batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.accountBytes += common.StorageSize(len(key) + len(value)) - }, - } - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - // Configure the dangling node cleaner and also filter out boundary nodes - // only in the context of the path scheme. Deletion is forbidden in the - // hash scheme, as it can disrupt state completeness. - options = options.WithCleaner(func(path []byte) { - s.cleanPath(batch, common.Hash{}, path) - }) - // Skip the left boundary if it's not the first range. - // Skip the right boundary if it's not the last range. - options = options.WithSkipBoundary(next != common.Hash{}, last != common.MaxHash, boundaryAccountNodesGauge) - } - s.tasks = append(s.tasks, &accountTask{ - Next: next, - Last: last, - SubTasks: make(map[common.Hash][]*storageTask), - genBatch: batch, - genTrie: trie.NewStackTrie(options), - }) - log.Debug("Created account sync task", "from", next, "last", last) - next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) - } -} - -// saveSyncStatus marshals the remaining sync tasks into leveldb. -func (s *Syncer) saveSyncStatus() { - // Serialize any partial progress to disk before spinning down - for _, task := range s.tasks { - if err := task.genBatch.Write(); err != nil { - log.Error("Failed to persist account slots", "err", err) - } - for _, subtasks := range task.SubTasks { - for _, subtask := range subtasks { - if err := subtask.genBatch.Write(); err != nil { - log.Error("Failed to persist storage slots", "err", err) - } - } - } - } - // Store the actual progress markers - progress := &SyncProgress{ - Tasks: s.tasks, - AccountSynced: s.accountSynced, - AccountBytes: s.accountBytes, - BytecodeSynced: s.bytecodeSynced, - BytecodeBytes: s.bytecodeBytes, - StorageSynced: s.storageSynced, - StorageBytes: s.storageBytes, - TrienodeHealSynced: s.trienodeHealSynced, - TrienodeHealBytes: s.trienodeHealBytes, - BytecodeHealSynced: s.bytecodeHealSynced, - BytecodeHealBytes: s.bytecodeHealBytes, - } - status, err := json.Marshal(progress) - if err != nil { - panic(err) // This can only fail during implementation - } - rawdb.WriteSnapshotSyncStatus(s.db, status) -} - -// Progress returns the snap sync status statistics. -func (s *Syncer) Progress() (*SyncProgress, *SyncPending) { - s.lock.Lock() - defer s.lock.Unlock() - pending := new(SyncPending) - if s.healer != nil { - pending.TrienodeHeal = uint64(len(s.healer.trieTasks)) - pending.BytecodeHeal = uint64(len(s.healer.codeTasks)) - } - return s.extProgress, pending -} - -// cleanAccountTasks removes account range retrieval tasks that have already been -// completed. -func (s *Syncer) cleanAccountTasks() { - // If the sync was already done before, don't even bother - if len(s.tasks) == 0 { - return - } - // Sync wasn't finished previously, check for any task that can be finalized - for i := 0; i < len(s.tasks); i++ { - if s.tasks[i].done { - s.tasks = append(s.tasks[:i], s.tasks[i+1:]...) - i-- - } - } - // If everything was just finalized just, generate the account trie and start heal - if len(s.tasks) == 0 { - s.lock.Lock() - s.snapped = true - s.lock.Unlock() - - // Push the final sync report - s.reportSyncProgress(true) - } -} - -// cleanStorageTasks iterates over all the account tasks and storage sub-tasks -// within, cleaning any that have been completed. -func (s *Syncer) cleanStorageTasks() { - for _, task := range s.tasks { - for account, subtasks := range task.SubTasks { - // Remove storage range retrieval tasks that completed - for j := 0; j < len(subtasks); j++ { - if subtasks[j].done { - subtasks = append(subtasks[:j], subtasks[j+1:]...) - j-- - } - } - if len(subtasks) > 0 { - task.SubTasks[account] = subtasks - continue - } - // If all storage chunks are done, mark the account as done too - for j, hash := range task.res.hashes { - if hash == account { - task.needState[j] = false - } - } - delete(task.SubTasks, account) - task.pend-- - - // If this was the last pending task, forward the account task - if task.pend == 0 { - s.forwardAccountTask(task) - } - } - } -} - -// assignAccountTasks attempts to match idle peers to pending account range -// retrievals. -func (s *Syncer) assignAccountTasks(success chan *accountResponse, fail chan *accountRequest, cancel chan struct{}) { - s.lock.Lock() - defer s.lock.Unlock() - - // Sort the peers by download capacity to use faster ones if many available - idlers := &capacitySort{ - ids: make([]string, 0, len(s.accountIdlers)), - caps: make([]int, 0, len(s.accountIdlers)), - } - targetTTL := s.rates.TargetTimeout() - for id := range s.accountIdlers { - if _, ok := s.statelessPeers[id]; ok { - continue - } - idlers.ids = append(idlers.ids, id) - idlers.caps = append(idlers.caps, s.rates.Capacity(id, AccountRangeMsg, targetTTL)) - } - if len(idlers.ids) == 0 { - return - } - sort.Sort(sort.Reverse(idlers)) - - // Iterate over all the tasks and try to find a pending one - for _, task := range s.tasks { - // Skip any tasks already filling - if task.req != nil || task.res != nil { - continue - } - // Task pending retrieval, try to find an idle peer. If no such peer - // exists, we probably assigned tasks for all (or they are stateless). - // Abort the entire assignment mechanism. - if len(idlers.ids) == 0 { - return - } - var ( - idle = idlers.ids[0] - peer = s.peers[idle] - cap = idlers.caps[0] - ) - idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.accountReqs[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer - req := &accountRequest{ - peer: idle, - id: reqid, - time: time.Now(), - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - origin: task.Next, - limit: task.Last, - task: task, - } - req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() { - peer.Log().Debug("Account range request timed out", "reqid", reqid) - s.rates.Update(idle, AccountRangeMsg, 0, 0) - s.scheduleRevertAccountRequest(req) - }) - s.accountReqs[reqid] = req - delete(s.accountIdlers, idle) - - s.pend.Add(1) - go func(root common.Hash) { - defer s.pend.Done() - - // Attempt to send the remote request and revert if it fails - if cap > maxRequestSize { - cap = maxRequestSize - } - if cap < minRequestSize { // Don't bother with peers below a bare minimum performance - cap = minRequestSize - } - if err := peer.RequestAccountRange(reqid, root, req.origin, req.limit, uint64(cap)); err != nil { - peer.Log().Debug("Failed to request account range", "err", err) - s.scheduleRevertAccountRequest(req) - } - }(s.root) - - // Inject the request into the task to block further assignments - task.req = req - } -} - -// assignBytecodeTasks attempts to match idle peers to pending code retrievals. -func (s *Syncer) assignBytecodeTasks(success chan *bytecodeResponse, fail chan *bytecodeRequest, cancel chan struct{}) { - s.lock.Lock() - defer s.lock.Unlock() - - // Sort the peers by download capacity to use faster ones if many available - idlers := &capacitySort{ - ids: make([]string, 0, len(s.bytecodeIdlers)), - caps: make([]int, 0, len(s.bytecodeIdlers)), - } - targetTTL := s.rates.TargetTimeout() - for id := range s.bytecodeIdlers { - if _, ok := s.statelessPeers[id]; ok { - continue - } - idlers.ids = append(idlers.ids, id) - idlers.caps = append(idlers.caps, s.rates.Capacity(id, ByteCodesMsg, targetTTL)) - } - if len(idlers.ids) == 0 { - return - } - sort.Sort(sort.Reverse(idlers)) - - // Iterate over all the tasks and try to find a pending one - for _, task := range s.tasks { - // Skip any tasks not in the bytecode retrieval phase - if task.res == nil { - continue - } - // Skip tasks that are already retrieving (or done with) all codes - if len(task.codeTasks) == 0 { - continue - } - // Task pending retrieval, try to find an idle peer. If no such peer - // exists, we probably assigned tasks for all (or they are stateless). - // Abort the entire assignment mechanism. - if len(idlers.ids) == 0 { - return - } - var ( - idle = idlers.ids[0] - peer = s.peers[idle] - cap = idlers.caps[0] - ) - idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.bytecodeReqs[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer - if cap > maxCodeRequestCount { - cap = maxCodeRequestCount - } - hashes := make([]common.Hash, 0, cap) - for hash := range task.codeTasks { - delete(task.codeTasks, hash) - hashes = append(hashes, hash) - if len(hashes) >= cap { - break - } - } - req := &bytecodeRequest{ - peer: idle, - id: reqid, - time: time.Now(), - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - hashes: hashes, - task: task, - } - req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() { - peer.Log().Debug("Bytecode request timed out", "reqid", reqid) - s.rates.Update(idle, ByteCodesMsg, 0, 0) - s.scheduleRevertBytecodeRequest(req) - }) - s.bytecodeReqs[reqid] = req - delete(s.bytecodeIdlers, idle) - - s.pend.Add(1) - go func() { - defer s.pend.Done() - - // Attempt to send the remote request and revert if it fails - if err := peer.RequestByteCodes(reqid, hashes, maxRequestSize); err != nil { - log.Debug("Failed to request bytecodes", "err", err) - s.scheduleRevertBytecodeRequest(req) - } - }() - } -} - -// assignStorageTasks attempts to match idle peers to pending storage range -// retrievals. -func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *storageRequest, cancel chan struct{}) { - s.lock.Lock() - defer s.lock.Unlock() - - // Sort the peers by download capacity to use faster ones if many available - idlers := &capacitySort{ - ids: make([]string, 0, len(s.storageIdlers)), - caps: make([]int, 0, len(s.storageIdlers)), - } - targetTTL := s.rates.TargetTimeout() - for id := range s.storageIdlers { - if _, ok := s.statelessPeers[id]; ok { - continue - } - idlers.ids = append(idlers.ids, id) - idlers.caps = append(idlers.caps, s.rates.Capacity(id, StorageRangesMsg, targetTTL)) - } - if len(idlers.ids) == 0 { - return - } - sort.Sort(sort.Reverse(idlers)) - - // Iterate over all the tasks and try to find a pending one - for _, task := range s.tasks { - // Skip any tasks not in the storage retrieval phase - if task.res == nil { - continue - } - // Skip tasks that are already retrieving (or done with) all small states - if len(task.SubTasks) == 0 && len(task.stateTasks) == 0 { - continue - } - // Task pending retrieval, try to find an idle peer. If no such peer - // exists, we probably assigned tasks for all (or they are stateless). - // Abort the entire assignment mechanism. - if len(idlers.ids) == 0 { - return - } - var ( - idle = idlers.ids[0] - peer = s.peers[idle] - cap = idlers.caps[0] - ) - idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.storageReqs[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer. If there are - // large contract tasks pending, complete those before diving into - // even more new contracts. - if cap > maxRequestSize { - cap = maxRequestSize - } - if cap < minRequestSize { // Don't bother with peers below a bare minimum performance - cap = minRequestSize - } - storageSets := cap / 1024 - - var ( - accounts = make([]common.Hash, 0, storageSets) - roots = make([]common.Hash, 0, storageSets) - subtask *storageTask - ) - for account, subtasks := range task.SubTasks { - for _, st := range subtasks { - // Skip any subtasks already filling - if st.req != nil { - continue - } - // Found an incomplete storage chunk, schedule it - accounts = append(accounts, account) - roots = append(roots, st.root) - subtask = st - break // Large contract chunks are downloaded individually - } - if subtask != nil { - break // Large contract chunks are downloaded individually - } - } - if subtask == nil { - // No large contract required retrieval, but small ones available - for account, root := range task.stateTasks { - delete(task.stateTasks, account) - - accounts = append(accounts, account) - roots = append(roots, root) - - if len(accounts) >= storageSets { - break - } - } - } - // If nothing was found, it means this task is actually already fully - // retrieving, but large contracts are hard to detect. Skip to the next. - if len(accounts) == 0 { - continue - } - req := &storageRequest{ - peer: idle, - id: reqid, - time: time.Now(), - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - accounts: accounts, - roots: roots, - mainTask: task, - subTask: subtask, - } - if subtask != nil { - req.origin = subtask.Next - req.limit = subtask.Last - } - req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() { - peer.Log().Debug("Storage request timed out", "reqid", reqid) - s.rates.Update(idle, StorageRangesMsg, 0, 0) - s.scheduleRevertStorageRequest(req) - }) - s.storageReqs[reqid] = req - delete(s.storageIdlers, idle) - - s.pend.Add(1) - go func(root common.Hash) { - defer s.pend.Done() - - // Attempt to send the remote request and revert if it fails - var origin, limit []byte - if subtask != nil { - origin, limit = req.origin[:], req.limit[:] - } - if err := peer.RequestStorageRanges(reqid, root, accounts, origin, limit, uint64(cap)); err != nil { - log.Debug("Failed to request storage", "err", err) - s.scheduleRevertStorageRequest(req) - } - }(s.root) - - // Inject the request into the subtask to block further assignments - if subtask != nil { - subtask.req = req - } - } -} - -// assignTrienodeHealTasks attempts to match idle peers to trie node requests to -// heal any trie errors caused by the snap sync's chunked retrieval model. -func (s *Syncer) assignTrienodeHealTasks(success chan *trienodeHealResponse, fail chan *trienodeHealRequest, cancel chan struct{}) { - s.lock.Lock() - defer s.lock.Unlock() - - // Sort the peers by download capacity to use faster ones if many available - idlers := &capacitySort{ - ids: make([]string, 0, len(s.trienodeHealIdlers)), - caps: make([]int, 0, len(s.trienodeHealIdlers)), - } - targetTTL := s.rates.TargetTimeout() - for id := range s.trienodeHealIdlers { - if _, ok := s.statelessPeers[id]; ok { - continue - } - idlers.ids = append(idlers.ids, id) - idlers.caps = append(idlers.caps, s.rates.Capacity(id, TrieNodesMsg, targetTTL)) - } - if len(idlers.ids) == 0 { - return - } - sort.Sort(sort.Reverse(idlers)) - - // Iterate over pending tasks and try to find a peer to retrieve with - for len(s.healer.trieTasks) > 0 || s.healer.scheduler.Pending() > 0 { - // If there are not enough trie tasks queued to fully assign, fill the - // queue from the state sync scheduler. The trie synced schedules these - // together with bytecodes, so we need to queue them combined. - var ( - have = len(s.healer.trieTasks) + len(s.healer.codeTasks) - want = maxTrieRequestCount + maxCodeRequestCount - ) - if have < want { - paths, hashes, codes := s.healer.scheduler.Missing(want - have) - for i, path := range paths { - s.healer.trieTasks[path] = hashes[i] - } - for _, hash := range codes { - s.healer.codeTasks[hash] = struct{}{} - } - } - // If all the heal tasks are bytecodes or already downloading, bail - if len(s.healer.trieTasks) == 0 { - return - } - // Task pending retrieval, try to find an idle peer. If no such peer - // exists, we probably assigned tasks for all (or they are stateless). - // Abort the entire assignment mechanism. - if len(idlers.ids) == 0 { - return - } - var ( - idle = idlers.ids[0] - peer = s.peers[idle] - cap = idlers.caps[0] - ) - idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.trienodeHealReqs[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer - if cap > maxTrieRequestCount { - cap = maxTrieRequestCount - } - cap = int(float64(cap) / s.trienodeHealThrottle) - if cap <= 0 { - cap = 1 - } - var ( - hashes = make([]common.Hash, 0, cap) - paths = make([]string, 0, cap) - pathsets = make([]TrieNodePathSet, 0, cap) - ) - for path, hash := range s.healer.trieTasks { - delete(s.healer.trieTasks, path) - - paths = append(paths, path) - hashes = append(hashes, hash) - if len(paths) >= cap { - break - } - } - // Group requests by account hash - paths, hashes, _, pathsets = sortByAccountPath(paths, hashes) - req := &trienodeHealRequest{ - peer: idle, - id: reqid, - time: time.Now(), - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - paths: paths, - hashes: hashes, - task: s.healer, - } - req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() { - peer.Log().Debug("Trienode heal request timed out", "reqid", reqid) - s.rates.Update(idle, TrieNodesMsg, 0, 0) - s.scheduleRevertTrienodeHealRequest(req) - }) - s.trienodeHealReqs[reqid] = req - delete(s.trienodeHealIdlers, idle) - - s.pend.Add(1) - go func(root common.Hash) { - defer s.pend.Done() - - // Attempt to send the remote request and revert if it fails - if err := peer.RequestTrieNodes(reqid, root, pathsets, maxRequestSize); err != nil { - log.Debug("Failed to request trienode healers", "err", err) - s.scheduleRevertTrienodeHealRequest(req) - } - }(s.root) - } -} - -// assignBytecodeHealTasks attempts to match idle peers to bytecode requests to -// heal any trie errors caused by the snap sync's chunked retrieval model. -func (s *Syncer) assignBytecodeHealTasks(success chan *bytecodeHealResponse, fail chan *bytecodeHealRequest, cancel chan struct{}) { - s.lock.Lock() - defer s.lock.Unlock() - - // Sort the peers by download capacity to use faster ones if many available - idlers := &capacitySort{ - ids: make([]string, 0, len(s.bytecodeHealIdlers)), - caps: make([]int, 0, len(s.bytecodeHealIdlers)), - } - targetTTL := s.rates.TargetTimeout() - for id := range s.bytecodeHealIdlers { - if _, ok := s.statelessPeers[id]; ok { - continue - } - idlers.ids = append(idlers.ids, id) - idlers.caps = append(idlers.caps, s.rates.Capacity(id, ByteCodesMsg, targetTTL)) - } - if len(idlers.ids) == 0 { - return - } - sort.Sort(sort.Reverse(idlers)) - - // Iterate over pending tasks and try to find a peer to retrieve with - for len(s.healer.codeTasks) > 0 || s.healer.scheduler.Pending() > 0 { - // If there are not enough trie tasks queued to fully assign, fill the - // queue from the state sync scheduler. The trie synced schedules these - // together with trie nodes, so we need to queue them combined. - var ( - have = len(s.healer.trieTasks) + len(s.healer.codeTasks) - want = maxTrieRequestCount + maxCodeRequestCount - ) - if have < want { - paths, hashes, codes := s.healer.scheduler.Missing(want - have) - for i, path := range paths { - s.healer.trieTasks[path] = hashes[i] - } - for _, hash := range codes { - s.healer.codeTasks[hash] = struct{}{} - } - } - // If all the heal tasks are trienodes or already downloading, bail - if len(s.healer.codeTasks) == 0 { - return - } - // Task pending retrieval, try to find an idle peer. If no such peer - // exists, we probably assigned tasks for all (or they are stateless). - // Abort the entire assignment mechanism. - if len(idlers.ids) == 0 { - return - } - var ( - idle = idlers.ids[0] - peer = s.peers[idle] - cap = idlers.caps[0] - ) - idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:] - - // Matched a pending task to an idle peer, allocate a unique request id - var reqid uint64 - for { - reqid = uint64(rand.Int63()) - if reqid == 0 { - continue - } - if _, ok := s.bytecodeHealReqs[reqid]; ok { - continue - } - break - } - // Generate the network query and send it to the peer - if cap > maxCodeRequestCount { - cap = maxCodeRequestCount - } - hashes := make([]common.Hash, 0, cap) - for hash := range s.healer.codeTasks { - delete(s.healer.codeTasks, hash) - - hashes = append(hashes, hash) - if len(hashes) >= cap { - break - } - } - req := &bytecodeHealRequest{ - peer: idle, - id: reqid, - time: time.Now(), - deliver: success, - revert: fail, - cancel: cancel, - stale: make(chan struct{}), - hashes: hashes, - task: s.healer, - } - req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() { - peer.Log().Debug("Bytecode heal request timed out", "reqid", reqid) - s.rates.Update(idle, ByteCodesMsg, 0, 0) - s.scheduleRevertBytecodeHealRequest(req) - }) - s.bytecodeHealReqs[reqid] = req - delete(s.bytecodeHealIdlers, idle) - - s.pend.Add(1) - go func() { - defer s.pend.Done() - - // Attempt to send the remote request and revert if it fails - if err := peer.RequestByteCodes(reqid, hashes, maxRequestSize); err != nil { - log.Debug("Failed to request bytecode healers", "err", err) - s.scheduleRevertBytecodeHealRequest(req) - } - }() - } -} - -// revertRequests locates all the currently pending requests from a particular -// peer and reverts them, rescheduling for others to fulfill. -func (s *Syncer) revertRequests(peer string) { - // Gather the requests first, revertals need the lock too - s.lock.Lock() - var accountReqs []*accountRequest - for _, req := range s.accountReqs { - if req.peer == peer { - accountReqs = append(accountReqs, req) - } - } - var bytecodeReqs []*bytecodeRequest - for _, req := range s.bytecodeReqs { - if req.peer == peer { - bytecodeReqs = append(bytecodeReqs, req) - } - } - var storageReqs []*storageRequest - for _, req := range s.storageReqs { - if req.peer == peer { - storageReqs = append(storageReqs, req) - } - } - var trienodeHealReqs []*trienodeHealRequest - for _, req := range s.trienodeHealReqs { - if req.peer == peer { - trienodeHealReqs = append(trienodeHealReqs, req) - } - } - var bytecodeHealReqs []*bytecodeHealRequest - for _, req := range s.bytecodeHealReqs { - if req.peer == peer { - bytecodeHealReqs = append(bytecodeHealReqs, req) - } - } - s.lock.Unlock() - - // Revert all the requests matching the peer - for _, req := range accountReqs { - s.revertAccountRequest(req) - } - for _, req := range bytecodeReqs { - s.revertBytecodeRequest(req) - } - for _, req := range storageReqs { - s.revertStorageRequest(req) - } - for _, req := range trienodeHealReqs { - s.revertTrienodeHealRequest(req) - } - for _, req := range bytecodeHealReqs { - s.revertBytecodeHealRequest(req) - } -} - -// scheduleRevertAccountRequest asks the event loop to clean up an account range -// request and return all failed retrieval tasks to the scheduler for reassignment. -func (s *Syncer) scheduleRevertAccountRequest(req *accountRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertAccountRequest cleans up an account range request and returns all failed -// retrieval tasks to the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertAccountRequest. -func (s *Syncer) revertAccountRequest(req *accountRequest) { - log.Debug("Reverting account request", "peer", req.peer, "reqid", req.id) - select { - case <-req.stale: - log.Trace("Account request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - s.lock.Lock() - delete(s.accountReqs, req.id) - s.lock.Unlock() - - // If there's a timeout timer still running, abort it and mark the account - // task as not-pending, ready for rescheduling - req.timeout.Stop() - if req.task.req == req { - req.task.req = nil - } -} - -// scheduleRevertBytecodeRequest asks the event loop to clean up a bytecode request -// and return all failed retrieval tasks to the scheduler for reassignment. -func (s *Syncer) scheduleRevertBytecodeRequest(req *bytecodeRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertBytecodeRequest cleans up a bytecode request and returns all failed -// retrieval tasks to the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertBytecodeRequest. -func (s *Syncer) revertBytecodeRequest(req *bytecodeRequest) { - log.Debug("Reverting bytecode request", "peer", req.peer) - select { - case <-req.stale: - log.Trace("Bytecode request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - s.lock.Lock() - delete(s.bytecodeReqs, req.id) - s.lock.Unlock() - - // If there's a timeout timer still running, abort it and mark the code - // retrievals as not-pending, ready for rescheduling - req.timeout.Stop() - for _, hash := range req.hashes { - req.task.codeTasks[hash] = struct{}{} - } -} - -// scheduleRevertStorageRequest asks the event loop to clean up a storage range -// request and return all failed retrieval tasks to the scheduler for reassignment. -func (s *Syncer) scheduleRevertStorageRequest(req *storageRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertStorageRequest cleans up a storage range request and returns all failed -// retrieval tasks to the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertStorageRequest. -func (s *Syncer) revertStorageRequest(req *storageRequest) { - log.Debug("Reverting storage request", "peer", req.peer) - select { - case <-req.stale: - log.Trace("Storage request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - s.lock.Lock() - delete(s.storageReqs, req.id) - s.lock.Unlock() - - // If there's a timeout timer still running, abort it and mark the storage - // task as not-pending, ready for rescheduling - req.timeout.Stop() - if req.subTask != nil { - req.subTask.req = nil - } else { - for i, account := range req.accounts { - req.mainTask.stateTasks[account] = req.roots[i] - } - } -} - -// scheduleRevertTrienodeHealRequest asks the event loop to clean up a trienode heal -// request and return all failed retrieval tasks to the scheduler for reassignment. -func (s *Syncer) scheduleRevertTrienodeHealRequest(req *trienodeHealRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertTrienodeHealRequest cleans up a trienode heal request and returns all -// failed retrieval tasks to the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertTrienodeHealRequest. -func (s *Syncer) revertTrienodeHealRequest(req *trienodeHealRequest) { - log.Debug("Reverting trienode heal request", "peer", req.peer) - select { - case <-req.stale: - log.Trace("Trienode heal request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - s.lock.Lock() - delete(s.trienodeHealReqs, req.id) - s.lock.Unlock() - - // If there's a timeout timer still running, abort it and mark the trie node - // retrievals as not-pending, ready for rescheduling - req.timeout.Stop() - for i, path := range req.paths { - req.task.trieTasks[path] = req.hashes[i] - } -} - -// scheduleRevertBytecodeHealRequest asks the event loop to clean up a bytecode heal -// request and return all failed retrieval tasks to the scheduler for reassignment. -func (s *Syncer) scheduleRevertBytecodeHealRequest(req *bytecodeHealRequest) { - select { - case req.revert <- req: - // Sync event loop notified - case <-req.cancel: - // Sync cycle got cancelled - case <-req.stale: - // Request already reverted - } -} - -// revertBytecodeHealRequest cleans up a bytecode heal request and returns all -// failed retrieval tasks to the scheduler for reassignment. -// -// Note, this needs to run on the event runloop thread to reschedule to idle peers. -// On peer threads, use scheduleRevertBytecodeHealRequest. -func (s *Syncer) revertBytecodeHealRequest(req *bytecodeHealRequest) { - log.Debug("Reverting bytecode heal request", "peer", req.peer) - select { - case <-req.stale: - log.Trace("Bytecode heal request already reverted", "peer", req.peer, "reqid", req.id) - return - default: - } - close(req.stale) - - // Remove the request from the tracked set - s.lock.Lock() - delete(s.bytecodeHealReqs, req.id) - s.lock.Unlock() - - // If there's a timeout timer still running, abort it and mark the code - // retrievals as not-pending, ready for rescheduling - req.timeout.Stop() - for _, hash := range req.hashes { - req.task.codeTasks[hash] = struct{}{} - } -} - -// processAccountResponse integrates an already validated account range response -// into the account tasks. -func (s *Syncer) processAccountResponse(res *accountResponse) { - // Switch the task from pending to filling - res.task.req = nil - res.task.res = res - - // Ensure that the response doesn't overflow into the subsequent task - last := res.task.Last.Big() - for i, hash := range res.hashes { - // Mark the range complete if the last is already included. - // Keep iteration to delete the extra states if exists. - cmp := hash.Big().Cmp(last) - if cmp == 0 { - res.cont = false - continue - } - if cmp > 0 { - // Chunk overflown, cut off excess - res.hashes = res.hashes[:i] - res.accounts = res.accounts[:i] - res.cont = false // Mark range completed - break - } - } - // Iterate over all the accounts and assemble which ones need further sub- - // filling before the entire account range can be persisted. - res.task.needCode = make([]bool, len(res.accounts)) - res.task.needState = make([]bool, len(res.accounts)) - res.task.needHeal = make([]bool, len(res.accounts)) - - res.task.codeTasks = make(map[common.Hash]struct{}) - res.task.stateTasks = make(map[common.Hash]common.Hash) - - resumed := make(map[common.Hash]struct{}) - - res.task.pend = 0 - for i, account := range res.accounts { - // Check if the account is a contract with an unknown code - if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { - if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { - res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} - res.task.needCode[i] = true - res.task.pend++ - } - } - // Check if the account is a contract with an unknown storage trie - if account.Root != types.EmptyRootHash { - if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) { - // If there was a previous large state retrieval in progress, - // don't restart it from scratch. This happens if a sync cycle - // is interrupted and resumed later. However, *do* update the - // previous root hash. - if subtasks, ok := res.task.SubTasks[res.hashes[i]]; ok { - log.Debug("Resuming large storage retrieval", "account", res.hashes[i], "root", account.Root) - for _, subtask := range subtasks { - subtask.root = account.Root - } - res.task.needHeal[i] = true - resumed[res.hashes[i]] = struct{}{} - } else { - res.task.stateTasks[res.hashes[i]] = account.Root - } - res.task.needState[i] = true - res.task.pend++ - } - } - } - // Delete any subtasks that have been aborted but not resumed. This may undo - // some progress if a new peer gives us less accounts than an old one, but for - // now we have to live with that. - for hash := range res.task.SubTasks { - if _, ok := resumed[hash]; !ok { - log.Debug("Aborting suspended storage retrieval", "account", hash) - delete(res.task.SubTasks, hash) - } - } - // If the account range contained no contracts, or all have been fully filled - // beforehand, short circuit storage filling and forward to the next task - if res.task.pend == 0 { - s.forwardAccountTask(res.task) - return - } - // Some accounts are incomplete, leave as is for the storage and contract - // task assigners to pick up and fill -} - -// processBytecodeResponse integrates an already validated bytecode response -// into the account tasks. -func (s *Syncer) processBytecodeResponse(res *bytecodeResponse) { - batch := s.db.NewBatch() - - var ( - codes uint64 - ) - for i, hash := range res.hashes { - code := res.codes[i] - - // If the bytecode was not delivered, reschedule it - if code == nil { - res.task.codeTasks[hash] = struct{}{} - continue - } - // Code was delivered, mark it not needed any more - for j, account := range res.task.res.accounts { - if res.task.needCode[j] && hash == common.BytesToHash(account.CodeHash) { - res.task.needCode[j] = false - res.task.pend-- - } - } - // Push the bytecode into a database batch - codes++ - rawdb.WriteCode(batch, hash, code) - } - bytes := common.StorageSize(batch.ValueSize()) - if err := batch.Write(); err != nil { - log.Crit("Failed to persist bytecodes", "err", err) - } - s.bytecodeSynced += codes - s.bytecodeBytes += bytes - - log.Debug("Persisted set of bytecodes", "count", codes, "bytes", bytes) - - // If this delivery completed the last pending task, forward the account task - // to the next chunk - if res.task.pend == 0 { - s.forwardAccountTask(res.task) - return - } - // Some accounts are still incomplete, leave as is for the storage and contract - // task assigners to pick up and fill. -} - -// processStorageResponse integrates an already validated storage response -// into the account tasks. -func (s *Syncer) processStorageResponse(res *storageResponse) { - // Switch the subtask from pending to idle - if res.subTask != nil { - res.subTask.req = nil - } - batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.storageBytes += common.StorageSize(len(key) + len(value)) - }, - } - var ( - slots int - oldStorageBytes = s.storageBytes - ) - // Iterate over all the accounts and reconstruct their storage tries from the - // delivered slots - for i, account := range res.accounts { - // If the account was not delivered, reschedule it - if i >= len(res.hashes) { - res.mainTask.stateTasks[account] = res.roots[i] - continue - } - // State was delivered, if complete mark as not needed any more, otherwise - // mark the account as needing healing - for j, hash := range res.mainTask.res.hashes { - if account != hash { - continue - } - acc := res.mainTask.res.accounts[j] - - // If the packet contains multiple contract storage slots, all - // but the last are surely complete. The last contract may be - // chunked, so check it's continuation flag. - if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) { - res.mainTask.needState[j] = false - res.mainTask.pend-- - smallStorageGauge.Inc(1) - } - // If the last contract was chunked, mark it as needing healing - // to avoid writing it out to disk prematurely. - if res.subTask == nil && !res.mainTask.needHeal[j] && i == len(res.hashes)-1 && res.cont { - res.mainTask.needHeal[j] = true - } - // If the last contract was chunked, we need to switch to large - // contract handling mode - if res.subTask == nil && i == len(res.hashes)-1 && res.cont { - // If we haven't yet started a large-contract retrieval, create - // the subtasks for it within the main account task - if tasks, ok := res.mainTask.SubTasks[account]; !ok { - var ( - keys = res.hashes[i] - chunks = uint64(storageConcurrency) - lastKey common.Hash - ) - if len(keys) > 0 { - lastKey = keys[len(keys)-1] - } - // If the number of slots remaining is low, decrease the - // number of chunks. Somewhere on the order of 10-15K slots - // fit into a packet of 500KB. A key/slot pair is maximum 64 - // bytes, so pessimistically maxRequestSize/64 = 8K. - // - // Chunk so that at least 2 packets are needed to fill a task. - if estimate, err := estimateRemainingSlots(len(keys), lastKey); err == nil { - if n := estimate / (2 * (maxRequestSize / 64)); n+1 < chunks { - chunks = n + 1 - } - log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "remaining", estimate, "chunks", chunks) - } else { - log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "chunks", chunks) - } - r := newHashRange(lastKey, chunks) - if chunks == 1 { - smallStorageGauge.Inc(1) - } else { - largeStorageGauge.Inc(1) - } - // Our first task is the one that was just filled by this response. - batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.storageBytes += common.StorageSize(len(key) + len(value)) - }, - } - owner := account // local assignment for stacktrie writer closure - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - options = options.WithCleaner(func(path []byte) { - s.cleanPath(batch, owner, path) - }) - // Keep the left boundary as it's the first range. - // Skip the right boundary if it's not the last range. - options = options.WithSkipBoundary(false, r.End() != common.MaxHash, boundaryStorageNodesGauge) - } - tasks = append(tasks, &storageTask{ - Next: common.Hash{}, - Last: r.End(), - root: acc.Root, - genBatch: batch, - genTrie: trie.NewStackTrie(options), - }) - for r.Next() { - batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.storageBytes += common.StorageSize(len(key) + len(value)) - }, - } - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - // Configure the dangling node cleaner and also filter out boundary nodes - // only in the context of the path scheme. Deletion is forbidden in the - // hash scheme, as it can disrupt state completeness. - options = options.WithCleaner(func(path []byte) { - s.cleanPath(batch, owner, path) - }) - // Skip the left boundary as it's not the first range - // Skip the right boundary if it's not the last range. - options = options.WithSkipBoundary(true, r.End() != common.MaxHash, boundaryStorageNodesGauge) - } - tasks = append(tasks, &storageTask{ - Next: r.Start(), - Last: r.End(), - root: acc.Root, - genBatch: batch, - genTrie: trie.NewStackTrie(options), - }) - } - for _, task := range tasks { - log.Debug("Created storage sync task", "account", account, "root", acc.Root, "from", task.Next, "last", task.Last) - } - res.mainTask.SubTasks[account] = tasks - - // Since we've just created the sub-tasks, this response - // is surely for the first one (zero origin) - res.subTask = tasks[0] - } - } - // If we're in large contract delivery mode, forward the subtask - if res.subTask != nil { - // Ensure the response doesn't overflow into the subsequent task - last := res.subTask.Last.Big() - // Find the first overflowing key. While at it, mark res as complete - // if we find the range to include or pass the 'last' - index := sort.Search(len(res.hashes[i]), func(k int) bool { - cmp := res.hashes[i][k].Big().Cmp(last) - if cmp >= 0 { - res.cont = false - } - return cmp > 0 - }) - if index >= 0 { - // cut off excess - res.hashes[i] = res.hashes[i][:index] - res.slots[i] = res.slots[i][:index] - } - // Forward the relevant storage chunk (even if created just now) - if res.cont { - res.subTask.Next = incHash(res.hashes[i][len(res.hashes[i])-1]) - } else { - res.subTask.done = true - } - } - } - // Iterate over all the complete contracts, reconstruct the trie nodes and - // push them to disk. If the contract is chunked, the trie nodes will be - // reconstructed later. - slots += len(res.hashes[i]) - - if i < len(res.hashes)-1 || res.subTask == nil { - // no need to make local reassignment of account: this closure does not outlive the loop - options := trie.NewStackTrieOptions() - options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) { - rawdb.WriteTrieNode(batch, account, path, hash, blob, s.scheme) - }) - if s.scheme == rawdb.PathScheme { - // Configure the dangling node cleaner only in the context of the - // path scheme. Deletion is forbidden in the hash scheme, as it can - // disrupt state completeness. - // - // Notably, boundary nodes can be also kept because the whole storage - // trie is complete. - options = options.WithCleaner(func(path []byte) { - s.cleanPath(batch, account, path) - }) - } - tr := trie.NewStackTrie(options) - for j := 0; j < len(res.hashes[i]); j++ { - tr.Update(res.hashes[i][j][:], res.slots[i][j]) - } - tr.Commit() - } - // Persist the received storage segments. These flat state maybe - // outdated during the sync, but it can be fixed later during the - // snapshot generation. - for j := 0; j < len(res.hashes[i]); j++ { - rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j]) - - // If we're storing large contracts, generate the trie nodes - // on the fly to not trash the gluing points - if i == len(res.hashes)-1 && res.subTask != nil { - res.subTask.genTrie.Update(res.hashes[i][j][:], res.slots[i][j]) - } - } - } - // Large contracts could have generated new trie nodes, flush them to disk - if res.subTask != nil { - if res.subTask.done { - root := res.subTask.genTrie.Commit() - if err := res.subTask.genBatch.Write(); err != nil { - log.Error("Failed to persist stack slots", "err", err) - } - res.subTask.genBatch.Reset() - - // If the chunk's root is an overflown but full delivery, - // clear the heal request. - accountHash := res.accounts[len(res.accounts)-1] - if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db, accountHash, nil, root) { - for i, account := range res.mainTask.res.hashes { - if account == accountHash { - res.mainTask.needHeal[i] = false - skipStorageHealingGauge.Inc(1) - } - } - } - } - if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize { - if err := res.subTask.genBatch.Write(); err != nil { - log.Error("Failed to persist stack slots", "err", err) - } - res.subTask.genBatch.Reset() - } - } - // Flush anything written just now and update the stats - if err := batch.Write(); err != nil { - log.Crit("Failed to persist storage slots", "err", err) - } - s.storageSynced += uint64(slots) - - log.Debug("Persisted set of storage slots", "accounts", len(res.hashes), "slots", slots, "bytes", s.storageBytes-oldStorageBytes) - - // If this delivery completed the last pending task, forward the account task - // to the next chunk - if res.mainTask.pend == 0 { - s.forwardAccountTask(res.mainTask) - return - } - // Some accounts are still incomplete, leave as is for the storage and contract - // task assigners to pick up and fill. -} - -// processTrienodeHealResponse integrates an already validated trienode response -// into the healer tasks. -func (s *Syncer) processTrienodeHealResponse(res *trienodeHealResponse) { - var ( - start = time.Now() - fills int - ) - for i, hash := range res.hashes { - node := res.nodes[i] - - // If the trie node was not delivered, reschedule it - if node == nil { - res.task.trieTasks[res.paths[i]] = res.hashes[i] - continue - } - fills++ - - // Push the trie node into the state syncer - s.trienodeHealSynced++ - s.trienodeHealBytes += common.StorageSize(len(node)) - - err := s.healer.scheduler.ProcessNode(trie.NodeSyncResult{Path: res.paths[i], Data: node}) - switch err { - case nil: - case trie.ErrAlreadyProcessed: - s.trienodeHealDups++ - case trie.ErrNotRequested: - s.trienodeHealNops++ - default: - log.Error("Invalid trienode processed", "hash", hash, "err", err) - } - } - s.commitHealer(false) - - // Calculate the processing rate of one filled trie node - rate := float64(fills) / (float64(time.Since(start)) / float64(time.Second)) - - // Update the currently measured trienode queueing and processing throughput. - // - // The processing rate needs to be updated uniformly independent if we've - // processed 1x100 trie nodes or 100x1 to keep the rate consistent even in - // the face of varying network packets. As such, we cannot just measure the - // time it took to process N trie nodes and update once, we need one update - // per trie node. - // - // Naively, that would be: - // - // for i:=0; i time.Second { - // Periodically adjust the trie node throttler - if float64(pending) > 2*s.trienodeHealRate { - s.trienodeHealThrottle *= trienodeHealThrottleIncrease - } else { - s.trienodeHealThrottle /= trienodeHealThrottleDecrease - } - if s.trienodeHealThrottle > maxTrienodeHealThrottle { - s.trienodeHealThrottle = maxTrienodeHealThrottle - } else if s.trienodeHealThrottle < minTrienodeHealThrottle { - s.trienodeHealThrottle = minTrienodeHealThrottle - } - s.trienodeHealThrottled = time.Now() - - log.Debug("Updated trie node heal throttler", "rate", s.trienodeHealRate, "pending", pending, "throttle", s.trienodeHealThrottle) - } -} - -func (s *Syncer) commitHealer(force bool) { - if !force && s.healer.scheduler.MemSize() < ethdb.IdealBatchSize { - return - } - batch := s.db.NewBatch() - if err := s.healer.scheduler.Commit(batch); err != nil { - log.Error("Failed to commit healing data", "err", err) - } - if err := batch.Write(); err != nil { - log.Crit("Failed to persist healing data", "err", err) - } - log.Debug("Persisted set of healing data", "type", "trienodes", "bytes", common.StorageSize(batch.ValueSize())) -} - -// processBytecodeHealResponse integrates an already validated bytecode response -// into the healer tasks. -func (s *Syncer) processBytecodeHealResponse(res *bytecodeHealResponse) { - for i, hash := range res.hashes { - node := res.codes[i] - - // If the trie node was not delivered, reschedule it - if node == nil { - res.task.codeTasks[hash] = struct{}{} - continue - } - // Push the trie node into the state syncer - s.bytecodeHealSynced++ - s.bytecodeHealBytes += common.StorageSize(len(node)) - - err := s.healer.scheduler.ProcessCode(trie.CodeSyncResult{Hash: hash, Data: node}) - switch err { - case nil: - case trie.ErrAlreadyProcessed: - s.bytecodeHealDups++ - case trie.ErrNotRequested: - s.bytecodeHealNops++ - default: - log.Error("Invalid bytecode processed", "hash", hash, "err", err) - } - } - s.commitHealer(false) -} - -// forwardAccountTask takes a filled account task and persists anything available -// into the database, after which it forwards the next account marker so that the -// task's next chunk may be filled. -func (s *Syncer) forwardAccountTask(task *accountTask) { - // Remove any pending delivery - res := task.res - if res == nil { - return // nothing to forward - } - task.res = nil - - // Persist the received account segments. These flat state maybe - // outdated during the sync, but it can be fixed later during the - // snapshot generation. - oldAccountBytes := s.accountBytes - - batch := ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.accountBytes += common.StorageSize(len(key) + len(value)) - }, - } - for i, hash := range res.hashes { - if task.needCode[i] || task.needState[i] { - break - } - slim := types.SlimAccountRLP(*res.accounts[i]) - rawdb.WriteAccountSnapshot(batch, hash, slim) - - // If the task is complete, drop it into the stack trie to generate - // account trie nodes for it - if !task.needHeal[i] { - full, err := types.FullAccountRLP(slim) // TODO(karalabe): Slim parsing can be omitted - if err != nil { - panic(err) // Really shouldn't ever happen - } - task.genTrie.Update(hash[:], full) - } - } - // Flush anything written just now and update the stats - if err := batch.Write(); err != nil { - log.Crit("Failed to persist accounts", "err", err) - } - s.accountSynced += uint64(len(res.accounts)) - - // Task filling persisted, push it the chunk marker forward to the first - // account still missing data. - for i, hash := range res.hashes { - if task.needCode[i] || task.needState[i] { - return - } - task.Next = incHash(hash) - } - // All accounts marked as complete, track if the entire task is done - task.done = !res.cont - - // Stack trie could have generated trie nodes, push them to disk (we need to - // flush after finalizing task.done. It's fine even if we crash and lose this - // write as it will only cause more data to be downloaded during heal. - if task.done { - task.genTrie.Commit() - } - if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done { - if err := task.genBatch.Write(); err != nil { - log.Error("Failed to persist stack account", "err", err) - } - task.genBatch.Reset() - } - log.Debug("Persisted range of accounts", "accounts", len(res.accounts), "bytes", s.accountBytes-oldAccountBytes) -} - -// OnAccounts is a callback method to invoke when a range of accounts are -// received from a remote peer. -func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, accounts [][]byte, proof [][]byte) error { - size := common.StorageSize(len(hashes) * common.HashLength) - for _, account := range accounts { - size += common.StorageSize(len(account)) - } - for _, node := range proof { - size += common.StorageSize(len(node)) - } - logger := peer.Log().New("reqid", id) - logger.Trace("Delivering range of accounts", "hashes", len(hashes), "accounts", len(accounts), "proofs", len(proof), "bytes", size) - - // Whether or not the response is valid, we can mark the peer as idle and - // notify the scheduler to assign a new task. If the response is invalid, - // we'll drop the peer in a bit. - defer func() { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.peers[peer.ID()]; ok { - s.accountIdlers[peer.ID()] = struct{}{} - } - select { - case s.update <- struct{}{}: - default: - } - }() - s.lock.Lock() - // Ensure the response is for a valid request - req, ok := s.accountReqs[id] - if !ok { - // Request stale, perhaps the peer timed out but came through in the end - logger.Warn("Unexpected account range packet") - s.lock.Unlock() - return nil - } - delete(s.accountReqs, id) - s.rates.Update(peer.ID(), AccountRangeMsg, time.Since(req.time), int(size)) - - // Clean up the request timeout timer, we'll see how to proceed further based - // on the actual delivered content - if !req.timeout.Stop() { - // The timeout is already triggered, and this request will be reverted+rescheduled - s.lock.Unlock() - return nil - } - // Response is valid, but check if peer is signalling that it does not have - // the requested data. For account range queries that means the state being - // retrieved was either already pruned remotely, or the peer is not yet - // synced to our head. - if len(hashes) == 0 && len(accounts) == 0 && len(proof) == 0 { - logger.Debug("Peer rejected account range request", "root", s.root) - s.statelessPeers[peer.ID()] = struct{}{} - s.lock.Unlock() - - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertAccountRequest(req) - return nil - } - root := s.root - s.lock.Unlock() - - // Reconstruct a partial trie from the response and verify it - keys := make([][]byte, len(hashes)) - for i, key := range hashes { - keys[i] = common.CopyBytes(key[:]) - } - nodes := make(trienode.ProofList, len(proof)) - for i, node := range proof { - nodes[i] = node - } - cont, err := trie.VerifyRangeProof(root, req.origin[:], keys, accounts, nodes.Set()) - if err != nil { - logger.Warn("Account range failed proof", "err", err) - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertAccountRequest(req) - return err - } - accs := make([]*types.StateAccount, len(accounts)) - for i, account := range accounts { - acc := new(types.StateAccount) - if err := rlp.DecodeBytes(account, acc); err != nil { - panic(err) // We created these blobs, we must be able to decode them - } - accs[i] = acc - } - response := &accountResponse{ - task: req.task, - hashes: hashes, - accounts: accs, - cont: cont, - } - select { - case req.deliver <- response: - case <-req.cancel: - case <-req.stale: - } - return nil -} - -// OnByteCodes is a callback method to invoke when a batch of contract -// bytes codes are received from a remote peer. -func (s *Syncer) OnByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error { - s.lock.RLock() - syncing := !s.snapped - s.lock.RUnlock() - - if syncing { - return s.onByteCodes(peer, id, bytecodes) - } - return s.onHealByteCodes(peer, id, bytecodes) -} - -// onByteCodes is a callback method to invoke when a batch of contract -// bytes codes are received from a remote peer in the syncing phase. -func (s *Syncer) onByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error { - var size common.StorageSize - for _, code := range bytecodes { - size += common.StorageSize(len(code)) - } - logger := peer.Log().New("reqid", id) - logger.Trace("Delivering set of bytecodes", "bytecodes", len(bytecodes), "bytes", size) - - // Whether or not the response is valid, we can mark the peer as idle and - // notify the scheduler to assign a new task. If the response is invalid, - // we'll drop the peer in a bit. - defer func() { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.peers[peer.ID()]; ok { - s.bytecodeIdlers[peer.ID()] = struct{}{} - } - select { - case s.update <- struct{}{}: - default: - } - }() - s.lock.Lock() - // Ensure the response is for a valid request - req, ok := s.bytecodeReqs[id] - if !ok { - // Request stale, perhaps the peer timed out but came through in the end - logger.Warn("Unexpected bytecode packet") - s.lock.Unlock() - return nil - } - delete(s.bytecodeReqs, id) - s.rates.Update(peer.ID(), ByteCodesMsg, time.Since(req.time), len(bytecodes)) - - // Clean up the request timeout timer, we'll see how to proceed further based - // on the actual delivered content - if !req.timeout.Stop() { - // The timeout is already triggered, and this request will be reverted+rescheduled - s.lock.Unlock() - return nil - } - - // Response is valid, but check if peer is signalling that it does not have - // the requested data. For bytecode range queries that means the peer is not - // yet synced. - if len(bytecodes) == 0 { - logger.Debug("Peer rejected bytecode request") - s.statelessPeers[peer.ID()] = struct{}{} - s.lock.Unlock() - - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertBytecodeRequest(req) - return nil - } - s.lock.Unlock() - - // Cross reference the requested bytecodes with the response to find gaps - // that the serving node is missing - hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) - hash := make([]byte, 32) - - codes := make([][]byte, len(req.hashes)) - for i, j := 0, 0; i < len(bytecodes); i++ { - // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - - for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { - j++ - } - if j < len(req.hashes) { - codes[j] = bytecodes[i] - j++ - continue - } - // We've either ran out of hashes, or got unrequested data - logger.Warn("Unexpected bytecodes", "count", len(bytecodes)-i) - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertBytecodeRequest(req) - return errors.New("unexpected bytecode") - } - // Response validated, send it to the scheduler for filling - response := &bytecodeResponse{ - task: req.task, - hashes: req.hashes, - codes: codes, - } - select { - case req.deliver <- response: - case <-req.cancel: - case <-req.stale: - } - return nil -} - -// OnStorage is a callback method to invoke when ranges of storage slots -// are received from a remote peer. -func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slots [][][]byte, proof [][]byte) error { - // Gather some trace stats to aid in debugging issues - var ( - hashCount int - slotCount int - size common.StorageSize - ) - for _, hashset := range hashes { - size += common.StorageSize(common.HashLength * len(hashset)) - hashCount += len(hashset) - } - for _, slotset := range slots { - for _, slot := range slotset { - size += common.StorageSize(len(slot)) - } - slotCount += len(slotset) - } - for _, node := range proof { - size += common.StorageSize(len(node)) - } - logger := peer.Log().New("reqid", id) - logger.Trace("Delivering ranges of storage slots", "accounts", len(hashes), "hashes", hashCount, "slots", slotCount, "proofs", len(proof), "size", size) - - // Whether or not the response is valid, we can mark the peer as idle and - // notify the scheduler to assign a new task. If the response is invalid, - // we'll drop the peer in a bit. - defer func() { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.peers[peer.ID()]; ok { - s.storageIdlers[peer.ID()] = struct{}{} - } - select { - case s.update <- struct{}{}: - default: - } - }() - s.lock.Lock() - // Ensure the response is for a valid request - req, ok := s.storageReqs[id] - if !ok { - // Request stale, perhaps the peer timed out but came through in the end - logger.Warn("Unexpected storage ranges packet") - s.lock.Unlock() - return nil - } - delete(s.storageReqs, id) - s.rates.Update(peer.ID(), StorageRangesMsg, time.Since(req.time), int(size)) - - // Clean up the request timeout timer, we'll see how to proceed further based - // on the actual delivered content - if !req.timeout.Stop() { - // The timeout is already triggered, and this request will be reverted+rescheduled - s.lock.Unlock() - return nil - } - - // Reject the response if the hash sets and slot sets don't match, or if the - // peer sent more data than requested. - if len(hashes) != len(slots) { - s.lock.Unlock() - s.scheduleRevertStorageRequest(req) // reschedule request - logger.Warn("Hash and slot set size mismatch", "hashset", len(hashes), "slotset", len(slots)) - return errors.New("hash and slot set size mismatch") - } - if len(hashes) > len(req.accounts) { - s.lock.Unlock() - s.scheduleRevertStorageRequest(req) // reschedule request - logger.Warn("Hash set larger than requested", "hashset", len(hashes), "requested", len(req.accounts)) - return errors.New("hash set larger than requested") - } - // Response is valid, but check if peer is signalling that it does not have - // the requested data. For storage range queries that means the state being - // retrieved was either already pruned remotely, or the peer is not yet - // synced to our head. - if len(hashes) == 0 && len(proof) == 0 { - logger.Debug("Peer rejected storage request") - s.statelessPeers[peer.ID()] = struct{}{} - s.lock.Unlock() - s.scheduleRevertStorageRequest(req) // reschedule request - return nil - } - s.lock.Unlock() - - // Reconstruct the partial tries from the response and verify them - var cont bool - - // If a proof was attached while the response is empty, it indicates that the - // requested range specified with 'origin' is empty. Construct an empty state - // response locally to finalize the range. - if len(hashes) == 0 && len(proof) > 0 { - hashes = append(hashes, []common.Hash{}) - slots = append(slots, [][]byte{}) - } - for i := 0; i < len(hashes); i++ { - // Convert the keys and proofs into an internal format - keys := make([][]byte, len(hashes[i])) - for j, key := range hashes[i] { - keys[j] = common.CopyBytes(key[:]) - } - nodes := make(trienode.ProofList, 0, len(proof)) - if i == len(hashes)-1 { - for _, node := range proof { - nodes = append(nodes, node) - } - } - var err error - if len(nodes) == 0 { - // No proof has been attached, the response must cover the entire key - // space and hash to the origin root. - _, err = trie.VerifyRangeProof(req.roots[i], nil, keys, slots[i], nil) - if err != nil { - s.scheduleRevertStorageRequest(req) // reschedule request - logger.Warn("Storage slots failed proof", "err", err) - return err - } - } else { - // A proof was attached, the response is only partial, check that the - // returned data is indeed part of the storage trie - proofdb := nodes.Set() - - cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], keys, slots[i], proofdb) - if err != nil { - s.scheduleRevertStorageRequest(req) // reschedule request - logger.Warn("Storage range failed proof", "err", err) - return err - } - } - } - // Partial tries reconstructed, send them to the scheduler for storage filling - response := &storageResponse{ - mainTask: req.mainTask, - subTask: req.subTask, - accounts: req.accounts, - roots: req.roots, - hashes: hashes, - slots: slots, - cont: cont, - } - select { - case req.deliver <- response: - case <-req.cancel: - case <-req.stale: - } - return nil -} - -// OnTrieNodes is a callback method to invoke when a batch of trie nodes -// are received from a remote peer. -func (s *Syncer) OnTrieNodes(peer SyncPeer, id uint64, trienodes [][]byte) error { - var size common.StorageSize - for _, node := range trienodes { - size += common.StorageSize(len(node)) - } - logger := peer.Log().New("reqid", id) - logger.Trace("Delivering set of healing trienodes", "trienodes", len(trienodes), "bytes", size) - - // Whether or not the response is valid, we can mark the peer as idle and - // notify the scheduler to assign a new task. If the response is invalid, - // we'll drop the peer in a bit. - defer func() { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.peers[peer.ID()]; ok { - s.trienodeHealIdlers[peer.ID()] = struct{}{} - } - select { - case s.update <- struct{}{}: - default: - } - }() - s.lock.Lock() - // Ensure the response is for a valid request - req, ok := s.trienodeHealReqs[id] - if !ok { - // Request stale, perhaps the peer timed out but came through in the end - logger.Warn("Unexpected trienode heal packet") - s.lock.Unlock() - return nil - } - delete(s.trienodeHealReqs, id) - s.rates.Update(peer.ID(), TrieNodesMsg, time.Since(req.time), len(trienodes)) - - // Clean up the request timeout timer, we'll see how to proceed further based - // on the actual delivered content - if !req.timeout.Stop() { - // The timeout is already triggered, and this request will be reverted+rescheduled - s.lock.Unlock() - return nil - } - - // Response is valid, but check if peer is signalling that it does not have - // the requested data. For bytecode range queries that means the peer is not - // yet synced. - if len(trienodes) == 0 { - logger.Debug("Peer rejected trienode heal request") - s.statelessPeers[peer.ID()] = struct{}{} - s.lock.Unlock() - - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertTrienodeHealRequest(req) - return nil - } - s.lock.Unlock() - - // Cross reference the requested trienodes with the response to find gaps - // that the serving node is missing - var ( - hasher = sha3.NewLegacyKeccak256().(crypto.KeccakState) - hash = make([]byte, 32) - nodes = make([][]byte, len(req.hashes)) - fills uint64 - ) - for i, j := 0, 0; i < len(trienodes); i++ { - // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(trienodes[i]) - hasher.Read(hash) - - for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { - j++ - } - if j < len(req.hashes) { - nodes[j] = trienodes[i] - fills++ - j++ - continue - } - // We've either ran out of hashes, or got unrequested data - logger.Warn("Unexpected healing trienodes", "count", len(trienodes)-i) - - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertTrienodeHealRequest(req) - return errors.New("unexpected healing trienode") - } - // Response validated, send it to the scheduler for filling - s.trienodeHealPend.Add(fills) - defer func() { - s.trienodeHealPend.Add(^(fills - 1)) - }() - response := &trienodeHealResponse{ - paths: req.paths, - task: req.task, - hashes: req.hashes, - nodes: nodes, - } - select { - case req.deliver <- response: - case <-req.cancel: - case <-req.stale: - } - return nil -} - -// onHealByteCodes is a callback method to invoke when a batch of contract -// bytes codes are received from a remote peer in the healing phase. -func (s *Syncer) onHealByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error { - var size common.StorageSize - for _, code := range bytecodes { - size += common.StorageSize(len(code)) - } - logger := peer.Log().New("reqid", id) - logger.Trace("Delivering set of healing bytecodes", "bytecodes", len(bytecodes), "bytes", size) - - // Whether or not the response is valid, we can mark the peer as idle and - // notify the scheduler to assign a new task. If the response is invalid, - // we'll drop the peer in a bit. - defer func() { - s.lock.Lock() - defer s.lock.Unlock() - if _, ok := s.peers[peer.ID()]; ok { - s.bytecodeHealIdlers[peer.ID()] = struct{}{} - } - select { - case s.update <- struct{}{}: - default: - } - }() - s.lock.Lock() - // Ensure the response is for a valid request - req, ok := s.bytecodeHealReqs[id] - if !ok { - // Request stale, perhaps the peer timed out but came through in the end - logger.Warn("Unexpected bytecode heal packet") - s.lock.Unlock() - return nil - } - delete(s.bytecodeHealReqs, id) - s.rates.Update(peer.ID(), ByteCodesMsg, time.Since(req.time), len(bytecodes)) - - // Clean up the request timeout timer, we'll see how to proceed further based - // on the actual delivered content - if !req.timeout.Stop() { - // The timeout is already triggered, and this request will be reverted+rescheduled - s.lock.Unlock() - return nil - } - - // Response is valid, but check if peer is signalling that it does not have - // the requested data. For bytecode range queries that means the peer is not - // yet synced. - if len(bytecodes) == 0 { - logger.Debug("Peer rejected bytecode heal request") - s.statelessPeers[peer.ID()] = struct{}{} - s.lock.Unlock() - - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertBytecodeHealRequest(req) - return nil - } - s.lock.Unlock() - - // Cross reference the requested bytecodes with the response to find gaps - // that the serving node is missing - hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) - hash := make([]byte, 32) - - codes := make([][]byte, len(req.hashes)) - for i, j := 0, 0; i < len(bytecodes); i++ { - // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - - for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { - j++ - } - if j < len(req.hashes) { - codes[j] = bytecodes[i] - j++ - continue - } - // We've either ran out of hashes, or got unrequested data - logger.Warn("Unexpected healing bytecodes", "count", len(bytecodes)-i) - // Signal this request as failed, and ready for rescheduling - s.scheduleRevertBytecodeHealRequest(req) - return errors.New("unexpected healing bytecode") - } - // Response validated, send it to the scheduler for filling - response := &bytecodeHealResponse{ - task: req.task, - hashes: req.hashes, - codes: codes, - } - select { - case req.deliver <- response: - case <-req.cancel: - case <-req.stale: - } - return nil -} - -// onHealState is a callback method to invoke when a flat state(account -// or storage slot) is downloaded during the healing stage. The flat states -// can be persisted blindly and can be fixed later in the generation stage. -// Note it's not concurrent safe, please handle the concurrent issue outside. -func (s *Syncer) onHealState(paths [][]byte, value []byte) error { - if len(paths) == 1 { - var account types.StateAccount - if err := rlp.DecodeBytes(value, &account); err != nil { - return nil // Returning the error here would drop the remote peer - } - blob := types.SlimAccountRLP(account) - rawdb.WriteAccountSnapshot(s.stateWriter, common.BytesToHash(paths[0]), blob) - s.accountHealed += 1 - s.accountHealedBytes += common.StorageSize(1 + common.HashLength + len(blob)) - } - if len(paths) == 2 { - rawdb.WriteStorageSnapshot(s.stateWriter, common.BytesToHash(paths[0]), common.BytesToHash(paths[1]), value) - s.storageHealed += 1 - s.storageHealedBytes += common.StorageSize(1 + 2*common.HashLength + len(value)) - } - if s.stateWriter.ValueSize() > ethdb.IdealBatchSize { - s.stateWriter.Write() // It's fine to ignore the error here - s.stateWriter.Reset() - } - return nil -} - -// hashSpace is the total size of the 256 bit hash space for accounts. -var hashSpace = new(big.Int).Exp(common.Big2, common.Big256, nil) - -// report calculates various status reports and provides it to the user. -func (s *Syncer) report(force bool) { - if len(s.tasks) > 0 { - s.reportSyncProgress(force) - return - } - s.reportHealProgress(force) -} - -// reportSyncProgress calculates various status reports and provides it to the user. -func (s *Syncer) reportSyncProgress(force bool) { - // Don't report all the events, just occasionally - if !force && time.Since(s.logTime) < 8*time.Second { - return - } - // Don't report anything until we have a meaningful progress - synced := s.accountBytes + s.bytecodeBytes + s.storageBytes - if synced == 0 { - return - } - accountGaps := new(big.Int) - for _, task := range s.tasks { - accountGaps.Add(accountGaps, new(big.Int).Sub(task.Last.Big(), task.Next.Big())) - } - accountFills := new(big.Int).Sub(hashSpace, accountGaps) - if accountFills.BitLen() == 0 { - return - } - s.logTime = time.Now() - estBytes := float64(new(big.Int).Div( - new(big.Int).Mul(new(big.Int).SetUint64(uint64(synced)), hashSpace), - accountFills, - ).Uint64()) - // Don't report anything until we have a meaningful progress - if estBytes < 1.0 { - return - } - elapsed := time.Since(s.startTime) - estTime := elapsed / time.Duration(synced) * time.Duration(estBytes) - - // Create a mega progress report - var ( - progress = fmt.Sprintf("%.2f%%", float64(synced)*100/estBytes) - accounts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.accountSynced), s.accountBytes.TerminalString()) - storage = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.storageSynced), s.storageBytes.TerminalString()) - bytecode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.bytecodeSynced), s.bytecodeBytes.TerminalString()) - ) - log.Info("Syncing: state download in progress", "synced", progress, "state", synced, - "accounts", accounts, "slots", storage, "codes", bytecode, "eta", common.PrettyDuration(estTime-elapsed)) -} - -// reportHealProgress calculates various status reports and provides it to the user. -func (s *Syncer) reportHealProgress(force bool) { - // Don't report all the events, just occasionally - if !force && time.Since(s.logTime) < 8*time.Second { - return - } - s.logTime = time.Now() - - // Create a mega progress report - var ( - trienode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.trienodeHealSynced), s.trienodeHealBytes.TerminalString()) - bytecode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.bytecodeHealSynced), s.bytecodeHealBytes.TerminalString()) - accounts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.accountHealed), s.accountHealedBytes.TerminalString()) - storage = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.storageHealed), s.storageHealedBytes.TerminalString()) - ) - log.Info("Syncing: state healing in progress", "accounts", accounts, "slots", storage, - "codes", bytecode, "nodes", trienode, "pending", s.healer.scheduler.Pending()) -} - -// estimateRemainingSlots tries to determine roughly how many slots are left in -// a contract storage, based on the number of keys and the last hash. This method -// assumes that the hashes are lexicographically ordered and evenly distributed. -func estimateRemainingSlots(hashes int, last common.Hash) (uint64, error) { - if last == (common.Hash{}) { - return 0, errors.New("last hash empty") - } - space := new(big.Int).Mul(math.MaxBig256, big.NewInt(int64(hashes))) - space.Div(space, last.Big()) - if !space.IsUint64() { - // Gigantic address space probably due to too few or malicious slots - return 0, errors.New("too few slots for estimation") - } - return space.Uint64() - uint64(hashes), nil -} - -// capacitySort implements the Sort interface, allowing sorting by peer message -// throughput. Note, callers should use sort.Reverse to get the desired effect -// of highest capacity being at the front. -type capacitySort struct { - ids []string - caps []int -} - -func (s *capacitySort) Len() int { - return len(s.ids) -} - -func (s *capacitySort) Less(i, j int) bool { - return s.caps[i] < s.caps[j] -} - -func (s *capacitySort) Swap(i, j int) { - s.ids[i], s.ids[j] = s.ids[j], s.ids[i] - s.caps[i], s.caps[j] = s.caps[j], s.caps[i] -} - -// healRequestSort implements the Sort interface, allowing sorting trienode -// heal requests, which is a prerequisite for merging storage-requests. -type healRequestSort struct { - paths []string - hashes []common.Hash - syncPaths []trie.SyncPath -} - -func (t *healRequestSort) Len() int { - return len(t.hashes) -} - -func (t *healRequestSort) Less(i, j int) bool { - a := t.syncPaths[i] - b := t.syncPaths[j] - switch bytes.Compare(a[0], b[0]) { - case -1: - return true - case 1: - return false - } - // identical first part - if len(a) < len(b) { - return true - } - if len(b) < len(a) { - return false - } - if len(a) == 2 { - return bytes.Compare(a[1], b[1]) < 0 - } - return false -} - -func (t *healRequestSort) Swap(i, j int) { - t.paths[i], t.paths[j] = t.paths[j], t.paths[i] - t.hashes[i], t.hashes[j] = t.hashes[j], t.hashes[i] - t.syncPaths[i], t.syncPaths[j] = t.syncPaths[j], t.syncPaths[i] -} - -// Merge merges the pathsets, so that several storage requests concerning the -// same account are merged into one, to reduce bandwidth. -// OBS: This operation is moot if t has not first been sorted. -func (t *healRequestSort) Merge() []TrieNodePathSet { - var result []TrieNodePathSet - for _, path := range t.syncPaths { - pathset := TrieNodePathSet(path) - if len(path) == 1 { - // It's an account reference. - result = append(result, pathset) - } else { - // It's a storage reference. - end := len(result) - 1 - if len(result) == 0 || !bytes.Equal(pathset[0], result[end][0]) { - // The account doesn't match last, create a new entry. - result = append(result, pathset) - } else { - // It's the same account as the previous one, add to the storage - // paths of that request. - result[end] = append(result[end], pathset[1]) - } - } - } - return result -} - -// sortByAccountPath takes hashes and paths, and sorts them. After that, it generates -// the TrieNodePaths and merges paths which belongs to the same account path. -func sortByAccountPath(paths []string, hashes []common.Hash) ([]string, []common.Hash, []trie.SyncPath, []TrieNodePathSet) { - var syncPaths []trie.SyncPath - for _, path := range paths { - syncPaths = append(syncPaths, trie.NewSyncPath([]byte(path))) - } - n := &healRequestSort{paths, hashes, syncPaths} - sort.Sort(n) - pathsets := n.Merge() - return n.paths, n.hashes, n.syncPaths, pathsets -} diff --git a/builder/eth/protocols/snap/sync_test.go b/builder/eth/protocols/snap/sync_test.go deleted file mode 100644 index b780868b4..000000000 --- a/builder/eth/protocols/snap/sync_test.go +++ /dev/null @@ -1,1976 +0,0 @@ -// 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 snap - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "fmt" - "math/big" - mrand "math/rand" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/testutil" - "github.com/ethereum/go-ethereum/trie/trienode" - "github.com/ethereum/go-ethereum/triedb" - "github.com/ethereum/go-ethereum/triedb/pathdb" - "github.com/holiman/uint256" - "golang.org/x/crypto/sha3" - "golang.org/x/exp/slices" -) - -func TestHashing(t *testing.T) { - t.Parallel() - - var bytecodes = make([][]byte, 10) - for i := 0; i < len(bytecodes); i++ { - buf := make([]byte, 100) - rand.Read(buf) - bytecodes[i] = buf - } - var want, got string - var old = func() { - hasher := sha3.NewLegacyKeccak256() - for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hash := hasher.Sum(nil) - got = fmt.Sprintf("%v\n%v", got, hash) - } - } - var new = func() { - hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) - var hash = make([]byte, 32) - for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - want = fmt.Sprintf("%v\n%v", want, hash) - } - } - old() - new() - if want != got { - t.Errorf("want\n%v\ngot\n%v\n", want, got) - } -} - -func BenchmarkHashing(b *testing.B) { - var bytecodes = make([][]byte, 10000) - for i := 0; i < len(bytecodes); i++ { - buf := make([]byte, 100) - rand.Read(buf) - bytecodes[i] = buf - } - var old = func() { - hasher := sha3.NewLegacyKeccak256() - for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Sum(nil) - } - } - var new = func() { - hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState) - var hash = make([]byte, 32) - for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - } - } - b.Run("old", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - old() - } - }) - b.Run("new", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - new() - } - }) -} - -type ( - accountHandlerFunc func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error - storageHandlerFunc func(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error - trieHandlerFunc func(t *testPeer, requestId uint64, root common.Hash, paths []TrieNodePathSet, cap uint64) error - codeHandlerFunc func(t *testPeer, id uint64, hashes []common.Hash, max uint64) error -) - -type testPeer struct { - id string - test *testing.T - remote *Syncer - logger log.Logger - accountTrie *trie.Trie - accountValues []*kv - storageTries map[common.Hash]*trie.Trie - storageValues map[common.Hash][]*kv - - accountRequestHandler accountHandlerFunc - storageRequestHandler storageHandlerFunc - trieRequestHandler trieHandlerFunc - codeRequestHandler codeHandlerFunc - term func() - - // counters - nAccountRequests int - nStorageRequests int - nBytecodeRequests int - nTrienodeRequests int -} - -func newTestPeer(id string, t *testing.T, term func()) *testPeer { - peer := &testPeer{ - id: id, - test: t, - logger: log.New("id", id), - accountRequestHandler: defaultAccountRequestHandler, - trieRequestHandler: defaultTrieRequestHandler, - storageRequestHandler: defaultStorageRequestHandler, - codeRequestHandler: defaultCodeRequestHandler, - term: term, - } - //stderrHandler := log.StreamHandler(os.Stderr, log.TerminalFormat(true)) - //peer.logger.SetHandler(stderrHandler) - return peer -} - -func (t *testPeer) setStorageTries(tries map[common.Hash]*trie.Trie) { - t.storageTries = make(map[common.Hash]*trie.Trie) - for root, trie := range tries { - t.storageTries[root] = trie.Copy() - } -} - -func (t *testPeer) ID() string { return t.id } -func (t *testPeer) Log() log.Logger { return t.logger } - -func (t *testPeer) Stats() string { - return fmt.Sprintf(`Account requests: %d -Storage requests: %d -Bytecode requests: %d -Trienode requests: %d -`, t.nAccountRequests, t.nStorageRequests, t.nBytecodeRequests, t.nTrienodeRequests) -} - -func (t *testPeer) RequestAccountRange(id uint64, root, origin, limit common.Hash, bytes uint64) error { - t.logger.Trace("Fetching range of accounts", "reqid", id, "root", root, "origin", origin, "limit", limit, "bytes", common.StorageSize(bytes)) - t.nAccountRequests++ - go t.accountRequestHandler(t, id, root, origin, limit, bytes) - return nil -} - -func (t *testPeer) RequestTrieNodes(id uint64, root common.Hash, paths []TrieNodePathSet, bytes uint64) error { - t.logger.Trace("Fetching set of trie nodes", "reqid", id, "root", root, "pathsets", len(paths), "bytes", common.StorageSize(bytes)) - t.nTrienodeRequests++ - go t.trieRequestHandler(t, id, root, paths, bytes) - return nil -} - -func (t *testPeer) RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error { - t.nStorageRequests++ - if len(accounts) == 1 && origin != nil { - t.logger.Trace("Fetching range of large storage slots", "reqid", id, "root", root, "account", accounts[0], "origin", common.BytesToHash(origin), "limit", common.BytesToHash(limit), "bytes", common.StorageSize(bytes)) - } else { - t.logger.Trace("Fetching ranges of small storage slots", "reqid", id, "root", root, "accounts", len(accounts), "first", accounts[0], "bytes", common.StorageSize(bytes)) - } - go t.storageRequestHandler(t, id, root, accounts, origin, limit, bytes) - return nil -} - -func (t *testPeer) RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error { - t.nBytecodeRequests++ - t.logger.Trace("Fetching set of byte codes", "reqid", id, "hashes", len(hashes), "bytes", common.StorageSize(bytes)) - go t.codeRequestHandler(t, id, hashes, bytes) - return nil -} - -// defaultTrieRequestHandler is a well-behaving handler for trie healing requests -func defaultTrieRequestHandler(t *testPeer, requestId uint64, root common.Hash, paths []TrieNodePathSet, cap uint64) error { - // Pass the response - var nodes [][]byte - for _, pathset := range paths { - switch len(pathset) { - case 1: - blob, _, err := t.accountTrie.GetNode(pathset[0]) - if err != nil { - t.logger.Info("Error handling req", "error", err) - break - } - nodes = append(nodes, blob) - default: - account := t.storageTries[(common.BytesToHash(pathset[0]))] - for _, path := range pathset[1:] { - blob, _, err := account.GetNode(path) - if err != nil { - t.logger.Info("Error handling req", "error", err) - break - } - nodes = append(nodes, blob) - } - } - } - t.remote.OnTrieNodes(t, requestId, nodes) - return nil -} - -// defaultAccountRequestHandler is a well-behaving handler for AccountRangeRequests -func defaultAccountRequestHandler(t *testPeer, id uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - keys, vals, proofs := createAccountRequestResponse(t, root, origin, limit, cap) - if err := t.remote.OnAccounts(t, id, keys, vals, proofs); err != nil { - t.test.Errorf("Remote side rejected our delivery: %v", err) - t.term() - return err - } - return nil -} - -func createAccountRequestResponse(t *testPeer, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) (keys []common.Hash, vals [][]byte, proofs [][]byte) { - var size uint64 - if limit == (common.Hash{}) { - limit = common.MaxHash - } - for _, entry := range t.accountValues { - if size > cap { - break - } - if bytes.Compare(origin[:], entry.k) <= 0 { - keys = append(keys, common.BytesToHash(entry.k)) - vals = append(vals, entry.v) - size += uint64(32 + len(entry.v)) - } - // If we've exceeded the request threshold, abort - if bytes.Compare(entry.k, limit[:]) >= 0 { - break - } - } - // Unless we send the entire trie, we need to supply proofs - // Actually, we need to supply proofs either way! This seems to be an implementation - // quirk in go-ethereum - proof := trienode.NewProofSet() - if err := t.accountTrie.Prove(origin[:], proof); err != nil { - t.logger.Error("Could not prove inexistence of origin", "origin", origin, "error", err) - } - if len(keys) > 0 { - lastK := (keys[len(keys)-1])[:] - if err := t.accountTrie.Prove(lastK, proof); err != nil { - t.logger.Error("Could not prove last item", "error", err) - } - } - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - return keys, vals, proofs -} - -// defaultStorageRequestHandler is a well-behaving storage request handler -func defaultStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, bOrigin, bLimit []byte, max uint64) error { - hashes, slots, proofs := createStorageRequestResponse(t, root, accounts, bOrigin, bLimit, max) - if err := t.remote.OnStorage(t, requestId, hashes, slots, proofs); err != nil { - t.test.Errorf("Remote side rejected our delivery: %v", err) - t.term() - } - return nil -} - -func defaultCodeRequestHandler(t *testPeer, id uint64, hashes []common.Hash, max uint64) error { - var bytecodes [][]byte - for _, h := range hashes { - bytecodes = append(bytecodes, getCodeByHash(h)) - } - if err := t.remote.OnByteCodes(t, id, bytecodes); err != nil { - t.test.Errorf("Remote side rejected our delivery: %v", err) - t.term() - } - return nil -} - -func createStorageRequestResponse(t *testPeer, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) (hashes [][]common.Hash, slots [][][]byte, proofs [][]byte) { - var size uint64 - for _, account := range accounts { - // The first account might start from a different origin and end sooner - var originHash common.Hash - if len(origin) > 0 { - originHash = common.BytesToHash(origin) - } - var limitHash = common.MaxHash - if len(limit) > 0 { - limitHash = common.BytesToHash(limit) - } - var ( - keys []common.Hash - vals [][]byte - abort bool - ) - for _, entry := range t.storageValues[account] { - if size >= max { - abort = true - break - } - if bytes.Compare(entry.k, originHash[:]) < 0 { - continue - } - keys = append(keys, common.BytesToHash(entry.k)) - vals = append(vals, entry.v) - size += uint64(32 + len(entry.v)) - if bytes.Compare(entry.k, limitHash[:]) >= 0 { - break - } - } - if len(keys) > 0 { - hashes = append(hashes, keys) - slots = append(slots, vals) - } - // Generate the Merkle proofs for the first and last storage slot, but - // only if the response was capped. If the entire storage trie included - // in the response, no need for any proofs. - if originHash != (common.Hash{}) || (abort && len(keys) > 0) { - // If we're aborting, we need to prove the first and last item - // This terminates the response (and thus the loop) - proof := trienode.NewProofSet() - stTrie := t.storageTries[account] - - // Here's a potential gotcha: when constructing the proof, we cannot - // use the 'origin' slice directly, but must use the full 32-byte - // hash form. - if err := stTrie.Prove(originHash[:], proof); err != nil { - t.logger.Error("Could not prove inexistence of origin", "origin", originHash, "error", err) - } - if len(keys) > 0 { - lastK := (keys[len(keys)-1])[:] - if err := stTrie.Prove(lastK, proof); err != nil { - t.logger.Error("Could not prove last item", "error", err) - } - } - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - break - } - } - return hashes, slots, proofs -} - -// createStorageRequestResponseAlwaysProve tests a cornercase, where the peer always -// supplies the proof for the last account, even if it is 'complete'. -func createStorageRequestResponseAlwaysProve(t *testPeer, root common.Hash, accounts []common.Hash, bOrigin, bLimit []byte, max uint64) (hashes [][]common.Hash, slots [][][]byte, proofs [][]byte) { - var size uint64 - max = max * 3 / 4 - - var origin common.Hash - if len(bOrigin) > 0 { - origin = common.BytesToHash(bOrigin) - } - var exit bool - for i, account := range accounts { - var keys []common.Hash - var vals [][]byte - for _, entry := range t.storageValues[account] { - if bytes.Compare(entry.k, origin[:]) < 0 { - exit = true - } - keys = append(keys, common.BytesToHash(entry.k)) - vals = append(vals, entry.v) - size += uint64(32 + len(entry.v)) - if size > max { - exit = true - } - } - if i == len(accounts)-1 { - exit = true - } - hashes = append(hashes, keys) - slots = append(slots, vals) - - if exit { - // If we're aborting, we need to prove the first and last item - // This terminates the response (and thus the loop) - proof := trienode.NewProofSet() - stTrie := t.storageTries[account] - - // Here's a potential gotcha: when constructing the proof, we cannot - // use the 'origin' slice directly, but must use the full 32-byte - // hash form. - if err := stTrie.Prove(origin[:], proof); err != nil { - t.logger.Error("Could not prove inexistence of origin", "origin", origin, - "error", err) - } - if len(keys) > 0 { - lastK := (keys[len(keys)-1])[:] - if err := stTrie.Prove(lastK, proof); err != nil { - t.logger.Error("Could not prove last item", "error", err) - } - } - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - break - } - } - return hashes, slots, proofs -} - -// emptyRequestAccountRangeFn is a rejects AccountRangeRequests -func emptyRequestAccountRangeFn(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - t.remote.OnAccounts(t, requestId, nil, nil, nil) - return nil -} - -func nonResponsiveRequestAccountRangeFn(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - return nil -} - -func emptyTrieRequestHandler(t *testPeer, requestId uint64, root common.Hash, paths []TrieNodePathSet, cap uint64) error { - t.remote.OnTrieNodes(t, requestId, nil) - return nil -} - -func nonResponsiveTrieRequestHandler(t *testPeer, requestId uint64, root common.Hash, paths []TrieNodePathSet, cap uint64) error { - return nil -} - -func emptyStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - t.remote.OnStorage(t, requestId, nil, nil, nil) - return nil -} - -func nonResponsiveStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - return nil -} - -func proofHappyStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - hashes, slots, proofs := createStorageRequestResponseAlwaysProve(t, root, accounts, origin, limit, max) - if err := t.remote.OnStorage(t, requestId, hashes, slots, proofs); err != nil { - t.test.Errorf("Remote side rejected our delivery: %v", err) - t.term() - } - return nil -} - -//func emptyCodeRequestHandler(t *testPeer, id uint64, hashes []common.Hash, max uint64) error { -// var bytecodes [][]byte -// t.remote.OnByteCodes(t, id, bytecodes) -// return nil -//} - -func corruptCodeRequestHandler(t *testPeer, id uint64, hashes []common.Hash, max uint64) error { - var bytecodes [][]byte - for _, h := range hashes { - // Send back the hashes - bytecodes = append(bytecodes, h[:]) - } - if err := t.remote.OnByteCodes(t, id, bytecodes); err != nil { - t.logger.Info("remote error on delivery (as expected)", "error", err) - // Mimic the real-life handler, which drops a peer on errors - t.remote.Unregister(t.id) - } - return nil -} - -func cappedCodeRequestHandler(t *testPeer, id uint64, hashes []common.Hash, max uint64) error { - var bytecodes [][]byte - for _, h := range hashes[:1] { - bytecodes = append(bytecodes, getCodeByHash(h)) - } - // Missing bytecode can be retrieved again, no error expected - if err := t.remote.OnByteCodes(t, id, bytecodes); err != nil { - t.test.Errorf("Remote side rejected our delivery: %v", err) - t.term() - } - return nil -} - -// starvingStorageRequestHandler is somewhat well-behaving storage handler, but it caps the returned results to be very small -func starvingStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - return defaultStorageRequestHandler(t, requestId, root, accounts, origin, limit, 500) -} - -func starvingAccountRequestHandler(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - return defaultAccountRequestHandler(t, requestId, root, origin, limit, 500) -} - -//func misdeliveringAccountRequestHandler(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, cap uint64) error { -// return defaultAccountRequestHandler(t, requestId-1, root, origin, 500) -//} - -func corruptAccountRequestHandler(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - hashes, accounts, proofs := createAccountRequestResponse(t, root, origin, limit, cap) - if len(proofs) > 0 { - proofs = proofs[1:] - } - if err := t.remote.OnAccounts(t, requestId, hashes, accounts, proofs); err != nil { - t.logger.Info("remote error on delivery (as expected)", "error", err) - // Mimic the real-life handler, which drops a peer on errors - t.remote.Unregister(t.id) - } - return nil -} - -// corruptStorageRequestHandler doesn't provide good proofs -func corruptStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - hashes, slots, proofs := createStorageRequestResponse(t, root, accounts, origin, limit, max) - if len(proofs) > 0 { - proofs = proofs[1:] - } - if err := t.remote.OnStorage(t, requestId, hashes, slots, proofs); err != nil { - t.logger.Info("remote error on delivery (as expected)", "error", err) - // Mimic the real-life handler, which drops a peer on errors - t.remote.Unregister(t.id) - } - return nil -} - -func noProofStorageRequestHandler(t *testPeer, requestId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - hashes, slots, _ := createStorageRequestResponse(t, root, accounts, origin, limit, max) - if err := t.remote.OnStorage(t, requestId, hashes, slots, nil); err != nil { - t.logger.Info("remote error on delivery (as expected)", "error", err) - // Mimic the real-life handler, which drops a peer on errors - t.remote.Unregister(t.id) - } - return nil -} - -// TestSyncBloatedProof tests a scenario where we provide only _one_ value, but -// also ship the entire trie inside the proof. If the attack is successful, -// the remote side does not do any follow-up requests -func TestSyncBloatedProof(t *testing.T) { - t.Parallel() - - testSyncBloatedProof(t, rawdb.HashScheme) - testSyncBloatedProof(t, rawdb.PathScheme) -} - -func testSyncBloatedProof(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme) - source := newTestPeer("source", t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - - source.accountRequestHandler = func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error { - var ( - proofs [][]byte - keys []common.Hash - vals [][]byte - ) - // The values - for _, entry := range t.accountValues { - if bytes.Compare(entry.k, origin[:]) < 0 { - continue - } - if bytes.Compare(entry.k, limit[:]) > 0 { - continue - } - keys = append(keys, common.BytesToHash(entry.k)) - vals = append(vals, entry.v) - } - // The proofs - proof := trienode.NewProofSet() - if err := t.accountTrie.Prove(origin[:], proof); err != nil { - t.logger.Error("Could not prove origin", "origin", origin, "error", err) - t.logger.Error("Could not prove origin", "origin", origin, "error", err) - } - // The bloat: add proof of every single element - for _, entry := range t.accountValues { - if err := t.accountTrie.Prove(entry.k, proof); err != nil { - t.logger.Error("Could not prove item", "error", err) - } - } - // And remove one item from the elements - if len(keys) > 2 { - keys = append(keys[:1], keys[2:]...) - vals = append(vals[:1], vals[2:]...) - } - for _, blob := range proof.List() { - proofs = append(proofs, blob) - } - if err := t.remote.OnAccounts(t, requestId, keys, vals, proofs); err != nil { - t.logger.Info("remote error on delivery (as expected)", "error", err) - t.term() - // This is actually correct, signal to exit the test successfully - } - return nil - } - syncer := setupSyncer(nodeScheme, source) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err == nil { - t.Fatal("No error returned from incomplete/cancelled sync") - } -} - -func setupSyncer(scheme string, peers ...*testPeer) *Syncer { - stateDb := rawdb.NewMemoryDatabase() - syncer := NewSyncer(stateDb, scheme) - for _, peer := range peers { - syncer.Register(peer) - peer.remote = syncer - } - return syncer -} - -// TestSync tests a basic sync with one peer -func TestSync(t *testing.T) { - t.Parallel() - - testSync(t, rawdb.HashScheme) - testSync(t, rawdb.PathScheme) -} - -func testSync(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - return source - } - syncer := setupSyncer(nodeScheme, mkSource("source")) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncTinyTriePanic tests a basic sync with one peer, and a tiny trie. This caused a -// panic within the prover -func TestSyncTinyTriePanic(t *testing.T) { - t.Parallel() - - testSyncTinyTriePanic(t, rawdb.HashScheme) - testSyncTinyTriePanic(t, rawdb.PathScheme) -} - -func testSyncTinyTriePanic(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(1, scheme) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - return source - } - syncer := setupSyncer(nodeScheme, mkSource("source")) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestMultiSync tests a basic sync with multiple peers -func TestMultiSync(t *testing.T) { - t.Parallel() - - testMultiSync(t, rawdb.HashScheme) - testMultiSync(t, rawdb.PathScheme) -} - -func testMultiSync(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - return source - } - syncer := setupSyncer(nodeScheme, mkSource("sourceA"), mkSource("sourceB")) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncWithStorage tests basic sync using accounts + storage + code -func TestSyncWithStorage(t *testing.T) { - t.Parallel() - - testSyncWithStorage(t, rawdb.HashScheme) - testSyncWithStorage(t, rawdb.PathScheme) -} - -func testSyncWithStorage(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 3000, true, false, false) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - return source - } - syncer := setupSyncer(scheme, mkSource("sourceA")) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all -func TestMultiSyncManyUseless(t *testing.T) { - t.Parallel() - - testMultiSyncManyUseless(t, rawdb.HashScheme) - testMultiSyncManyUseless(t, rawdb.PathScheme) -} - -func testMultiSyncManyUseless(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false) - - mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - - if !noAccount { - source.accountRequestHandler = emptyRequestAccountRangeFn - } - if !noStorage { - source.storageRequestHandler = emptyStorageRequestHandler - } - if !noTrieNode { - source.trieRequestHandler = emptyTrieRequestHandler - } - return source - } - - syncer := setupSyncer( - scheme, - mkSource("full", true, true, true), - mkSource("noAccounts", false, true, true), - mkSource("noStorage", true, false, true), - mkSource("noTrie", true, true, false), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all -func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) { - t.Parallel() - - testMultiSyncManyUselessWithLowTimeout(t, rawdb.HashScheme) - testMultiSyncManyUselessWithLowTimeout(t, rawdb.PathScheme) -} - -func testMultiSyncManyUselessWithLowTimeout(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false) - - mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - - if !noAccount { - source.accountRequestHandler = emptyRequestAccountRangeFn - } - if !noStorage { - source.storageRequestHandler = emptyStorageRequestHandler - } - if !noTrieNode { - source.trieRequestHandler = emptyTrieRequestHandler - } - return source - } - - syncer := setupSyncer( - scheme, - mkSource("full", true, true, true), - mkSource("noAccounts", false, true, true), - mkSource("noStorage", true, false, true), - mkSource("noTrie", true, true, false), - ) - // We're setting the timeout to very low, to increase the chance of the timeout - // being triggered. This was previously a cause of panic, when a response - // arrived simultaneously as a timeout was triggered. - syncer.rates.OverrideTTLLimit = time.Millisecond - - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestMultiSyncManyUnresponsive contains one good peer, and many which doesn't respond at all -func TestMultiSyncManyUnresponsive(t *testing.T) { - t.Parallel() - - testMultiSyncManyUnresponsive(t, rawdb.HashScheme) - testMultiSyncManyUnresponsive(t, rawdb.PathScheme) -} - -func testMultiSyncManyUnresponsive(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false) - - mkSource := func(name string, noAccount, noStorage, noTrieNode bool) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - - if !noAccount { - source.accountRequestHandler = nonResponsiveRequestAccountRangeFn - } - if !noStorage { - source.storageRequestHandler = nonResponsiveStorageRequestHandler - } - if !noTrieNode { - source.trieRequestHandler = nonResponsiveTrieRequestHandler - } - return source - } - - syncer := setupSyncer( - scheme, - mkSource("full", true, true, true), - mkSource("noAccounts", false, true, true), - mkSource("noStorage", true, false, true), - mkSource("noTrie", true, true, false), - ) - // We're setting the timeout to very low, to make the test run a bit faster - syncer.rates.OverrideTTLLimit = time.Millisecond - - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -func checkStall(t *testing.T, term func()) chan struct{} { - testDone := make(chan struct{}) - go func() { - select { - case <-time.After(time.Minute): // TODO(karalabe): Make tests smaller, this is too much - t.Log("Sync stalled") - term() - case <-testDone: - return - } - }() - return testDone -} - -// TestSyncBoundaryAccountTrie tests sync against a few normal peers, but the -// account trie has a few boundary elements. -func TestSyncBoundaryAccountTrie(t *testing.T) { - t.Parallel() - - testSyncBoundaryAccountTrie(t, rawdb.HashScheme) - testSyncBoundaryAccountTrie(t, rawdb.PathScheme) -} - -func testSyncBoundaryAccountTrie(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeBoundaryAccountTrie(scheme, 3000) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - return source - } - syncer := setupSyncer( - nodeScheme, - mkSource("peer-a"), - mkSource("peer-b"), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncNoStorageAndOneCappedPeer tests sync using accounts and no storage, where one peer is -// consistently returning very small results -func TestSyncNoStorageAndOneCappedPeer(t *testing.T) { - t.Parallel() - - testSyncNoStorageAndOneCappedPeer(t, rawdb.HashScheme) - testSyncNoStorageAndOneCappedPeer(t, rawdb.PathScheme) -} - -func testSyncNoStorageAndOneCappedPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme) - - mkSource := func(name string, slow bool) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - - if slow { - source.accountRequestHandler = starvingAccountRequestHandler - } - return source - } - - syncer := setupSyncer( - nodeScheme, - mkSource("nice-a", false), - mkSource("nice-b", false), - mkSource("nice-c", false), - mkSource("capped", true), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncNoStorageAndOneCodeCorruptPeer has one peer which doesn't deliver -// code requests properly. -func TestSyncNoStorageAndOneCodeCorruptPeer(t *testing.T) { - t.Parallel() - - testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.HashScheme) - testSyncNoStorageAndOneCodeCorruptPeer(t, rawdb.PathScheme) -} - -func testSyncNoStorageAndOneCodeCorruptPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme) - - mkSource := func(name string, codeFn codeHandlerFunc) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.codeRequestHandler = codeFn - return source - } - // One is capped, one is corrupt. If we don't use a capped one, there's a 50% - // chance that the full set of codes requested are sent only to the - // non-corrupt peer, which delivers everything in one go, and makes the - // test moot - syncer := setupSyncer( - nodeScheme, - mkSource("capped", cappedCodeRequestHandler), - mkSource("corrupt", corruptCodeRequestHandler), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -func TestSyncNoStorageAndOneAccountCorruptPeer(t *testing.T) { - t.Parallel() - - testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.HashScheme) - testSyncNoStorageAndOneAccountCorruptPeer(t, rawdb.PathScheme) -} - -func testSyncNoStorageAndOneAccountCorruptPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme) - - mkSource := func(name string, accFn accountHandlerFunc) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.accountRequestHandler = accFn - return source - } - // One is capped, one is corrupt. If we don't use a capped one, there's a 50% - // chance that the full set of codes requested are sent only to the - // non-corrupt peer, which delivers everything in one go, and makes the - // test moot - syncer := setupSyncer( - nodeScheme, - mkSource("capped", defaultAccountRequestHandler), - mkSource("corrupt", corruptAccountRequestHandler), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncNoStorageAndOneCodeCappedPeer has one peer which delivers code hashes -// one by one -func TestSyncNoStorageAndOneCodeCappedPeer(t *testing.T) { - t.Parallel() - - testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.HashScheme) - testSyncNoStorageAndOneCodeCappedPeer(t, rawdb.PathScheme) -} - -func testSyncNoStorageAndOneCodeCappedPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(3000, scheme) - - mkSource := func(name string, codeFn codeHandlerFunc) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.codeRequestHandler = codeFn - return source - } - // Count how many times it's invoked. Remember, there are only 8 unique hashes, - // so it shouldn't be more than that - var counter int - syncer := setupSyncer( - nodeScheme, - mkSource("capped", func(t *testPeer, id uint64, hashes []common.Hash, max uint64) error { - counter++ - return cappedCodeRequestHandler(t, id, hashes, max) - }), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - - // There are only 8 unique hashes, and 3K accounts. However, the code - // deduplication is per request batch. If it were a perfect global dedup, - // we would expect only 8 requests. If there were no dedup, there would be - // 3k requests. - // We expect somewhere below 100 requests for these 8 unique hashes. But - // the number can be flaky, so don't limit it so strictly. - if threshold := 100; counter > threshold { - t.Logf("Error, expected < %d invocations, got %d", threshold, counter) - } - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncBoundaryStorageTrie tests sync against a few normal peers, but the -// storage trie has a few boundary elements. -func TestSyncBoundaryStorageTrie(t *testing.T) { - t.Parallel() - - testSyncBoundaryStorageTrie(t, rawdb.HashScheme) - testSyncBoundaryStorageTrie(t, rawdb.PathScheme) -} - -func testSyncBoundaryStorageTrie(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 10, 1000, false, true, false) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - return source - } - syncer := setupSyncer( - scheme, - mkSource("peer-a"), - mkSource("peer-b"), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncWithStorageAndOneCappedPeer tests sync using accounts + storage, where one peer is -// consistently returning very small results -func TestSyncWithStorageAndOneCappedPeer(t *testing.T) { - t.Parallel() - - testSyncWithStorageAndOneCappedPeer(t, rawdb.HashScheme) - testSyncWithStorageAndOneCappedPeer(t, rawdb.PathScheme) -} - -func testSyncWithStorageAndOneCappedPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 300, 1000, false, false, false) - - mkSource := func(name string, slow bool) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - - if slow { - source.storageRequestHandler = starvingStorageRequestHandler - } - return source - } - - syncer := setupSyncer( - scheme, - mkSource("nice-a", false), - mkSource("slow", true), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncWithStorageAndCorruptPeer tests sync using accounts + storage, where one peer is -// sometimes sending bad proofs -func TestSyncWithStorageAndCorruptPeer(t *testing.T) { - t.Parallel() - - testSyncWithStorageAndCorruptPeer(t, rawdb.HashScheme) - testSyncWithStorageAndCorruptPeer(t, rawdb.PathScheme) -} - -func testSyncWithStorageAndCorruptPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false) - - mkSource := func(name string, handler storageHandlerFunc) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - source.storageRequestHandler = handler - return source - } - - syncer := setupSyncer( - scheme, - mkSource("nice-a", defaultStorageRequestHandler), - mkSource("nice-b", defaultStorageRequestHandler), - mkSource("nice-c", defaultStorageRequestHandler), - mkSource("corrupt", corruptStorageRequestHandler), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -func TestSyncWithStorageAndNonProvingPeer(t *testing.T) { - t.Parallel() - - testSyncWithStorageAndNonProvingPeer(t, rawdb.HashScheme) - testSyncWithStorageAndNonProvingPeer(t, rawdb.PathScheme) -} - -func testSyncWithStorageAndNonProvingPeer(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 100, 3000, true, false, false) - - mkSource := func(name string, handler storageHandlerFunc) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - source.storageRequestHandler = handler - return source - } - syncer := setupSyncer( - scheme, - mkSource("nice-a", defaultStorageRequestHandler), - mkSource("nice-b", defaultStorageRequestHandler), - mkSource("nice-c", defaultStorageRequestHandler), - mkSource("corrupt", noProofStorageRequestHandler), - ) - done := checkStall(t, term) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - close(done) - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncWithStorage tests basic sync using accounts + storage + code, against -// a peer who insists on delivering full storage sets _and_ proofs. This triggered -// an error, where the recipient erroneously clipped the boundary nodes, but -// did not mark the account for healing. -func TestSyncWithStorageMisbehavingProve(t *testing.T) { - t.Parallel() - - testSyncWithStorageMisbehavingProve(t, rawdb.HashScheme) - testSyncWithStorageMisbehavingProve(t, rawdb.PathScheme) -} - -func testSyncWithStorageMisbehavingProve(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems, storageTries, storageElems := makeAccountTrieWithStorageWithUniqueStorage(scheme, 10, 30, false) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - source.setStorageTries(storageTries) - source.storageValues = storageElems - source.storageRequestHandler = proofHappyStorageRequestHandler - return source - } - syncer := setupSyncer(nodeScheme, mkSource("sourceA")) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) -} - -// TestSyncWithUnevenStorage tests sync where the storage trie is not even -// and with a few empty ranges. -func TestSyncWithUnevenStorage(t *testing.T) { - t.Parallel() - - testSyncWithUnevenStorage(t, rawdb.HashScheme) - testSyncWithUnevenStorage(t, rawdb.PathScheme) -} - -func testSyncWithUnevenStorage(t *testing.T, scheme string) { - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - accountTrie, accounts, storageTries, storageElems := makeAccountTrieWithStorage(scheme, 3, 256, false, false, true) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = accountTrie.Copy() - source.accountValues = accounts - source.setStorageTries(storageTries) - source.storageValues = storageElems - source.storageRequestHandler = func(t *testPeer, reqId uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, max uint64) error { - return defaultStorageRequestHandler(t, reqId, root, accounts, origin, limit, 128) // retrieve storage in large mode - } - return source - } - syncer := setupSyncer(scheme, mkSource("source")) - if err := syncer.Sync(accountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - verifyTrie(scheme, syncer.db, accountTrie.Hash(), t) -} - -type kv struct { - k, v []byte -} - -func (k *kv) cmp(other *kv) int { - return bytes.Compare(k.k, other.k) -} - -func key32(i uint64) []byte { - key := make([]byte, 32) - binary.LittleEndian.PutUint64(key, i) - return key -} - -var ( - codehashes = []common.Hash{ - crypto.Keccak256Hash([]byte{0}), - crypto.Keccak256Hash([]byte{1}), - crypto.Keccak256Hash([]byte{2}), - crypto.Keccak256Hash([]byte{3}), - crypto.Keccak256Hash([]byte{4}), - crypto.Keccak256Hash([]byte{5}), - crypto.Keccak256Hash([]byte{6}), - crypto.Keccak256Hash([]byte{7}), - } -) - -// getCodeHash returns a pseudo-random code hash -func getCodeHash(i uint64) []byte { - h := codehashes[int(i)%len(codehashes)] - return common.CopyBytes(h[:]) -} - -// getCodeByHash convenience function to lookup the code from the code hash -func getCodeByHash(hash common.Hash) []byte { - if hash == types.EmptyCodeHash { - return nil - } - for i, h := range codehashes { - if h == hash { - return []byte{byte(i)} - } - } - return nil -} - -// makeAccountTrieNoStorage spits out a trie, along with the leafs -func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) { - var ( - db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) - accTrie = trie.NewEmpty(db) - entries []*kv - ) - for i := uint64(1); i <= uint64(n); i++ { - value, _ := rlp.EncodeToBytes(&types.StateAccount{ - Nonce: i, - Balance: uint256.NewInt(i), - Root: types.EmptyRootHash, - CodeHash: getCodeHash(i), - }) - key := key32(i) - elem := &kv{key, value} - accTrie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - slices.SortFunc(entries, (*kv).cmp) - - // Commit the state changes into db and re-create the trie - // for accessing later. - root, nodes, _ := accTrie.Commit(false) - db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) - - accTrie, _ = trie.New(trie.StateTrieID(root), db) - return db.Scheme(), accTrie, entries -} - -// makeBoundaryAccountTrie constructs an account trie. Instead of filling -// accounts normally, this function will fill a few accounts which have -// boundary hash. -func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) { - var ( - entries []*kv - boundaries []common.Hash - - db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) - accTrie = trie.NewEmpty(db) - ) - // Initialize boundaries - var next common.Hash - step := new(big.Int).Sub( - new(big.Int).Div( - new(big.Int).Exp(common.Big2, common.Big256, nil), - big.NewInt(int64(accountConcurrency)), - ), common.Big1, - ) - for i := 0; i < accountConcurrency; i++ { - last := common.BigToHash(new(big.Int).Add(next.Big(), step)) - if i == accountConcurrency-1 { - last = common.MaxHash - } - boundaries = append(boundaries, last) - next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) - } - // Fill boundary accounts - for i := 0; i < len(boundaries); i++ { - value, _ := rlp.EncodeToBytes(&types.StateAccount{ - Nonce: uint64(0), - Balance: uint256.NewInt(uint64(i)), - Root: types.EmptyRootHash, - CodeHash: getCodeHash(uint64(i)), - }) - elem := &kv{boundaries[i].Bytes(), value} - accTrie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - // Fill other accounts if required - for i := uint64(1); i <= uint64(n); i++ { - value, _ := rlp.EncodeToBytes(&types.StateAccount{ - Nonce: i, - Balance: uint256.NewInt(i), - Root: types.EmptyRootHash, - CodeHash: getCodeHash(i), - }) - elem := &kv{key32(i), value} - accTrie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - slices.SortFunc(entries, (*kv).cmp) - - // Commit the state changes into db and re-create the trie - // for accessing later. - root, nodes, _ := accTrie.Commit(false) - db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil) - - accTrie, _ = trie.New(trie.StateTrieID(root), db) - return db.Scheme(), accTrie, entries -} - -// makeAccountTrieWithStorageWithUniqueStorage creates an account trie where each accounts -// has a unique storage set. -func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { - var ( - db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) - accTrie = trie.NewEmpty(db) - entries []*kv - storageRoots = make(map[common.Hash]common.Hash) - storageTries = make(map[common.Hash]*trie.Trie) - storageEntries = make(map[common.Hash][]*kv) - nodes = trienode.NewMergedNodeSet() - ) - // Create n accounts in the trie - for i := uint64(1); i <= uint64(accounts); i++ { - key := key32(i) - codehash := types.EmptyCodeHash.Bytes() - if code { - codehash = getCodeHash(i) - } - // Create a storage trie - stRoot, stNodes, stEntries := makeStorageTrieWithSeed(common.BytesToHash(key), uint64(slots), i, db) - nodes.Merge(stNodes) - - value, _ := rlp.EncodeToBytes(&types.StateAccount{ - Nonce: i, - Balance: uint256.NewInt(i), - Root: stRoot, - CodeHash: codehash, - }) - elem := &kv{key, value} - accTrie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - - storageRoots[common.BytesToHash(key)] = stRoot - storageEntries[common.BytesToHash(key)] = stEntries - } - slices.SortFunc(entries, (*kv).cmp) - - // Commit account trie - root, set, _ := accTrie.Commit(true) - nodes.Merge(set) - - // Commit gathered dirty nodes into database - db.Update(root, types.EmptyRootHash, 0, nodes, nil) - - // Re-create tries with new root - accTrie, _ = trie.New(trie.StateTrieID(root), db) - for i := uint64(1); i <= uint64(accounts); i++ { - key := key32(i) - id := trie.StorageTrieID(root, common.BytesToHash(key), storageRoots[common.BytesToHash(key)]) - trie, _ := trie.New(id, db) - storageTries[common.BytesToHash(key)] = trie - } - return db.Scheme(), accTrie, entries, storageTries, storageEntries -} - -// makeAccountTrieWithStorage spits out a trie, along with the leafs -func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, boundary bool, uneven bool) (*trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) { - var ( - db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme)) - accTrie = trie.NewEmpty(db) - entries []*kv - storageRoots = make(map[common.Hash]common.Hash) - storageTries = make(map[common.Hash]*trie.Trie) - storageEntries = make(map[common.Hash][]*kv) - nodes = trienode.NewMergedNodeSet() - ) - // Create n accounts in the trie - for i := uint64(1); i <= uint64(accounts); i++ { - key := key32(i) - codehash := types.EmptyCodeHash.Bytes() - if code { - codehash = getCodeHash(i) - } - // Make a storage trie - var ( - stRoot common.Hash - stNodes *trienode.NodeSet - stEntries []*kv - ) - if boundary { - stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db) - } else if uneven { - stRoot, stNodes, stEntries = makeUnevenStorageTrie(common.BytesToHash(key), slots, db) - } else { - stRoot, stNodes, stEntries = makeStorageTrieWithSeed(common.BytesToHash(key), uint64(slots), 0, db) - } - nodes.Merge(stNodes) - - value, _ := rlp.EncodeToBytes(&types.StateAccount{ - Nonce: i, - Balance: uint256.NewInt(i), - Root: stRoot, - CodeHash: codehash, - }) - elem := &kv{key, value} - accTrie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - - // we reuse the same one for all accounts - storageRoots[common.BytesToHash(key)] = stRoot - storageEntries[common.BytesToHash(key)] = stEntries - } - slices.SortFunc(entries, (*kv).cmp) - - // Commit account trie - root, set, _ := accTrie.Commit(true) - nodes.Merge(set) - - // Commit gathered dirty nodes into database - db.Update(root, types.EmptyRootHash, 0, nodes, nil) - - // Re-create tries with new root - accTrie, err := trie.New(trie.StateTrieID(root), db) - if err != nil { - panic(err) - } - for i := uint64(1); i <= uint64(accounts); i++ { - key := key32(i) - id := trie.StorageTrieID(root, common.BytesToHash(key), storageRoots[common.BytesToHash(key)]) - trie, err := trie.New(id, db) - if err != nil { - panic(err) - } - storageTries[common.BytesToHash(key)] = trie - } - return accTrie, entries, storageTries, storageEntries -} - -// makeStorageTrieWithSeed fills a storage trie with n items, returning the -// not-yet-committed trie and the sorted entries. The seeds can be used to ensure -// that tries are unique. -func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) { - trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) - var entries []*kv - for i := uint64(1); i <= n; i++ { - // store 'x' at slot 'x' - slotValue := key32(i + seed) - rlpSlotValue, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(slotValue[:])) - - slotKey := key32(i) - key := crypto.Keccak256Hash(slotKey[:]) - - elem := &kv{key[:], rlpSlotValue} - trie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - slices.SortFunc(entries, (*kv).cmp) - root, nodes, _ := trie.Commit(false) - return root, nodes, entries -} - -// makeBoundaryStorageTrie constructs a storage trie. Instead of filling -// storage slots normally, this function will fill a few slots which have -// boundary hash. -func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) { - var ( - entries []*kv - boundaries []common.Hash - trie, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) - ) - // Initialize boundaries - var next common.Hash - step := new(big.Int).Sub( - new(big.Int).Div( - new(big.Int).Exp(common.Big2, common.Big256, nil), - big.NewInt(int64(accountConcurrency)), - ), common.Big1, - ) - for i := 0; i < accountConcurrency; i++ { - last := common.BigToHash(new(big.Int).Add(next.Big(), step)) - if i == accountConcurrency-1 { - last = common.MaxHash - } - boundaries = append(boundaries, last) - next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1)) - } - // Fill boundary slots - for i := 0; i < len(boundaries); i++ { - key := boundaries[i] - val := []byte{0xde, 0xad, 0xbe, 0xef} - - elem := &kv{key[:], val} - trie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - // Fill other slots if required - for i := uint64(1); i <= uint64(n); i++ { - slotKey := key32(i) - key := crypto.Keccak256Hash(slotKey[:]) - - slotValue := key32(i) - rlpSlotValue, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(slotValue[:])) - - elem := &kv{key[:], rlpSlotValue} - trie.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - slices.SortFunc(entries, (*kv).cmp) - root, nodes, _ := trie.Commit(false) - return root, nodes, entries -} - -// makeUnevenStorageTrie constructs a storage tries will states distributed in -// different range unevenly. -func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) { - var ( - entries []*kv - tr, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db) - chosen = make(map[byte]struct{}) - ) - for i := 0; i < 3; i++ { - var n int - for { - n = mrand.Intn(15) // the last range is set empty deliberately - if _, ok := chosen[byte(n)]; ok { - continue - } - chosen[byte(n)] = struct{}{} - break - } - for j := 0; j < slots/3; j++ { - key := append([]byte{byte(n)}, testutil.RandBytes(31)...) - val, _ := rlp.EncodeToBytes(testutil.RandBytes(32)) - - elem := &kv{key, val} - tr.MustUpdate(elem.k, elem.v) - entries = append(entries, elem) - } - } - slices.SortFunc(entries, (*kv).cmp) - root, nodes, _ := tr.Commit(false) - return root, nodes, entries -} - -func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *testing.T) { - t.Helper() - triedb := triedb.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme)) - accTrie, err := trie.New(trie.StateTrieID(root), triedb) - if err != nil { - t.Fatal(err) - } - accounts, slots := 0, 0 - accIt := trie.NewIterator(accTrie.MustNodeIterator(nil)) - for accIt.Next() { - var acc struct { - Nonce uint64 - Balance *big.Int - Root common.Hash - CodeHash []byte - } - if err := rlp.DecodeBytes(accIt.Value, &acc); err != nil { - log.Crit("Invalid account encountered during snapshot creation", "err", err) - } - accounts++ - if acc.Root != types.EmptyRootHash { - id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root) - storeTrie, err := trie.NewStateTrie(id, triedb) - if err != nil { - t.Fatal(err) - } - storeIt := trie.NewIterator(storeTrie.MustNodeIterator(nil)) - for storeIt.Next() { - slots++ - } - if err := storeIt.Err; err != nil { - t.Fatal(err) - } - } - } - if err := accIt.Err; err != nil { - t.Fatal(err) - } - t.Logf("accounts: %d, slots: %d", accounts, slots) -} - -// TestSyncAccountPerformance tests how efficient the snap algo is at minimizing -// state healing -func TestSyncAccountPerformance(t *testing.T) { - t.Parallel() - - testSyncAccountPerformance(t, rawdb.HashScheme) - testSyncAccountPerformance(t, rawdb.PathScheme) -} - -func testSyncAccountPerformance(t *testing.T, scheme string) { - // Set the account concurrency to 1. This _should_ result in the - // range root to become correct, and there should be no healing needed - defer func(old int) { accountConcurrency = old }(accountConcurrency) - accountConcurrency = 1 - - var ( - once sync.Once - cancel = make(chan struct{}) - term = func() { - once.Do(func() { - close(cancel) - }) - } - ) - nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100, scheme) - - mkSource := func(name string) *testPeer { - source := newTestPeer(name, t, term) - source.accountTrie = sourceAccountTrie.Copy() - source.accountValues = elems - return source - } - src := mkSource("source") - syncer := setupSyncer(nodeScheme, src) - if err := syncer.Sync(sourceAccountTrie.Hash(), cancel); err != nil { - t.Fatalf("sync failed: %v", err) - } - verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t) - // The trie root will always be requested, since it is added when the snap - // sync cycle starts. When popping the queue, we do not look it up again. - // Doing so would bring this number down to zero in this artificial testcase, - // but only add extra IO for no reason in practice. - if have, want := src.nTrienodeRequests, 1; have != want { - fmt.Print(src.Stats()) - t.Errorf("trie node heal requests wrong, want %d, have %d", want, have) - } -} - -func TestSlotEstimation(t *testing.T) { - for i, tc := range []struct { - last common.Hash - count int - want uint64 - }{ - { - // Half the space - common.HexToHash("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - 100, - 100, - }, - { - // 1 / 16th - common.HexToHash("0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - 100, - 1500, - }, - { - // Bit more than 1 / 16th - common.HexToHash("0x1000000000000000000000000000000000000000000000000000000000000000"), - 100, - 1499, - }, - { - // Almost everything - common.HexToHash("0xF000000000000000000000000000000000000000000000000000000000000000"), - 100, - 6, - }, - { - // Almost nothing -- should lead to error - common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), - 1, - 0, - }, - { - // Nothing -- should lead to error - common.Hash{}, - 100, - 0, - }, - } { - have, _ := estimateRemainingSlots(tc.count, tc.last) - if want := tc.want; have != want { - t.Errorf("test %d: have %d want %d", i, have, want) - } - } -} - -func newDbConfig(scheme string) *triedb.Config { - if scheme == rawdb.HashScheme { - return &triedb.Config{} - } - return &triedb.Config{PathDB: pathdb.Defaults} -} diff --git a/builder/eth/protocols/snap/tracker.go b/builder/eth/protocols/snap/tracker.go deleted file mode 100644 index 2cf59cc23..000000000 --- a/builder/eth/protocols/snap/tracker.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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 snap - -import ( - "time" - - "github.com/ethereum/go-ethereum/p2p/tracker" -) - -// requestTracker is a singleton tracker for request times. -var requestTracker = tracker.New(ProtocolName, time.Minute) diff --git a/builder/eth/state_accessor.go b/builder/eth/state_accessor.go deleted file mode 100644 index 526361a2b..000000000 --- a/builder/eth/state_accessor.go +++ /dev/null @@ -1,260 +0,0 @@ -// 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 eth - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/triedb" -) - -// noopReleaser is returned in case there is no operation expected -// for releasing state. -var noopReleaser = tracers.StateReleaseFunc(func() {}) - -func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { - var ( - current *types.Block - database state.Database - tdb *triedb.Database - report = true - origin = block.NumberU64() - ) - // The state is only for reading purposes, check the state presence in - // live database. - if readOnly { - // The state is available in live database, create a reference - // on top to prevent garbage collection and return a release - // function to deref it. - if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil { - eth.blockchain.TrieDB().Reference(block.Root(), common.Hash{}) - return statedb, func() { - eth.blockchain.TrieDB().Dereference(block.Root()) - }, nil - } - } - // The state is both for reading and writing, or it's unavailable in disk, - // try to construct/recover the state over an ephemeral trie.Database for - // isolating the live one. - if base != nil { - if preferDisk { - // Create an ephemeral trie.Database for isolating the live one. Otherwise - // the internal junks created by tracing will be persisted into the disk. - // TODO(rjl493456442), clean cache is disabled to prevent memory leak, - // please re-enable it for better performance. - database = state.NewDatabaseWithConfig(eth.chainDb, triedb.HashDefaults) - if statedb, err = state.New(block.Root(), database, nil); err == nil { - log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) - return statedb, noopReleaser, nil - } - } - // The optional base statedb is given, mark the start point as parent block - statedb, database, tdb, report = base, base.Database(), base.Database().TrieDB(), false - current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) - } else { - // Otherwise, try to reexec blocks until we find a state or reach our limit - current = block - - // Create an ephemeral trie.Database for isolating the live one. Otherwise - // the internal junks created by tracing will be persisted into the disk. - // TODO(rjl493456442), clean cache is disabled to prevent memory leak, - // please re-enable it for better performance. - tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults) - database = state.NewDatabaseWithNodeDB(eth.chainDb, tdb) - - // If we didn't check the live database, do check state over ephemeral database, - // otherwise we would rewind past a persisted block (specific corner case is - // chain tracing from the genesis). - if !readOnly { - statedb, err = state.New(current.Root(), database, nil) - if err == nil { - return statedb, noopReleaser, nil - } - } - // Database does not have the state for the given block, try to regenerate - for i := uint64(0); i < reexec; i++ { - if err := ctx.Err(); err != nil { - return nil, nil, err - } - if current.NumberU64() == 0 { - return nil, nil, errors.New("genesis state is missing") - } - parent := eth.blockchain.GetBlock(current.ParentHash(), current.NumberU64()-1) - if parent == nil { - return nil, nil, fmt.Errorf("missing block %v %d", current.ParentHash(), current.NumberU64()-1) - } - current = parent - - statedb, err = state.New(current.Root(), database, nil) - if err == nil { - break - } - } - if err != nil { - switch err.(type) { - case *trie.MissingNodeError: - return nil, nil, fmt.Errorf("required historical state unavailable (reexec=%d)", reexec) - default: - return nil, nil, err - } - } - } - // State is available at historical point, re-execute the blocks on top for - // the desired state. - var ( - start = time.Now() - logged time.Time - parent common.Hash - ) - for current.NumberU64() < origin { - if err := ctx.Err(); err != nil { - return nil, nil, err - } - // Print progress logs if long enough time elapsed - if time.Since(logged) > 8*time.Second && report { - log.Info("Regenerating historical state", "block", current.NumberU64()+1, "target", origin, "remaining", origin-current.NumberU64()-1, "elapsed", time.Since(start)) - logged = time.Now() - } - // Retrieve the next block to regenerate and process it - next := current.NumberU64() + 1 - if current = eth.blockchain.GetBlockByNumber(next); current == nil { - return nil, nil, fmt.Errorf("block #%d not found", next) - } - _, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{}) - if err != nil { - return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err) - } - // Finalize the state so any modifications are written to the trie - root, err := statedb.Commit(current.NumberU64(), eth.blockchain.Config().IsEIP158(current.Number())) - if err != nil { - return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w", - current.NumberU64(), current.Root().Hex(), err) - } - statedb, err = state.New(root, database, nil) - if err != nil { - return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err) - } - // Hold the state reference and also drop the parent state - // to prevent accumulating too many nodes in memory. - tdb.Reference(root, common.Hash{}) - if parent != (common.Hash{}) { - tdb.Dereference(parent) - } - parent = root - } - if report { - _, nodes, imgs := tdb.Size() // all memory is contained within the nodes return in hashdb - log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) - } - return statedb, func() { tdb.Dereference(block.Root()) }, nil -} - -func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) { - // Check if the requested state is available in the live chain. - statedb, err := eth.blockchain.StateAt(block.Root()) - if err == nil { - return statedb, noopReleaser, nil - } - // TODO historic state is not supported in path-based scheme. - // Fully archive node in pbss will be implemented by relying - // on state history, but needs more work on top. - return nil, nil, errors.New("historical state not available in path scheme yet") -} - -// stateAtBlock retrieves the state database associated with a certain block. -// If no state is locally available for the given block, a number of blocks -// are attempted to be reexecuted to generate the desired state. The optional -// base layer statedb can be provided which is regarded as the statedb of the -// parent block. -// -// An additional release function will be returned if the requested state is -// available. Release is expected to be invoked when the returned state is no -// longer needed. Its purpose is to prevent resource leaking. Though it can be -// noop in some cases. -// -// Parameters: -// - block: The block for which we want the state(state = block.Root) -// - reexec: The maximum number of blocks to reprocess trying to obtain the desired state -// - base: If the caller is tracing multiple blocks, the caller can provide the parent -// state continuously from the callsite. -// - readOnly: If true, then the live 'blockchain' state database is used. No mutation should -// be made from caller, e.g. perform Commit or other 'save-to-disk' changes. -// Otherwise, the trash generated by caller may be persisted permanently. -// - preferDisk: This arg can be used by the caller to signal that even though the 'base' is -// provided, it would be preferable to start from a fresh state, if we have it -// on disk. -func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { - if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme { - return eth.hashState(ctx, block, reexec, base, readOnly, preferDisk) - } - return eth.pathState(block) -} - -// stateAtTransaction returns the execution environment of a certain transaction. -func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { - // Short circuit if it's genesis block. - if block.NumberU64() == 0 { - return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") - } - // Create the parent state database - parent := eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) - if parent == nil { - return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) - } - // Lookup the statedb of parent block from the live database, - // otherwise regenerate it on the flight. - statedb, release, err := eth.stateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, vm.BlockContext{}, nil, nil, err - } - if txIndex == 0 && len(block.Transactions()) == 0 { - return nil, vm.BlockContext{}, statedb, release, nil - } - // Recompute transactions up to the target index. - signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) - for idx, tx := range block.Transactions() { - // Assemble the transaction call message and return if the requested offset - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) - if idx == txIndex { - return msg, context, statedb, release, nil - } - // Not yet the searched for transaction, execute on top of the current state - vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) - statedb.SetTxContext(tx.Hash(), idx) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) - } - // Ensure any modifications are committed to the state - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) - } - return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) -} diff --git a/builder/eth/sync.go b/builder/eth/sync.go deleted file mode 100644 index 5c1593b71..000000000 --- a/builder/eth/sync.go +++ /dev/null @@ -1,255 +0,0 @@ -// 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 eth - -import ( - "errors" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/log" -) - -const ( - forceSyncCycle = 10 * time.Second // Time interval to force syncs, even if few peers are available - defaultMinSyncPeers = 5 // Amount of peers desired to start syncing -) - -// syncTransactions starts sending all currently pending transactions to the given peer. -func (h *handler) syncTransactions(p *eth.Peer) { - var hashes []common.Hash - for _, batch := range h.txpool.Pending(txpool.PendingFilter{OnlyPlainTxs: true}) { - for _, tx := range batch { - // don't share any transactions marked as private - if !h.txpool.IsPrivateTxHash(tx.Hash) { - hashes = append(hashes, tx.Hash) - } - } - } - if len(hashes) == 0 { - return - } - p.AsyncSendPooledTransactionHashes(hashes) -} - -// chainSyncer coordinates blockchain sync components. -type chainSyncer struct { - handler *handler - force *time.Timer - forced bool // true when force timer fired - warned time.Time - peerEventCh chan struct{} - doneCh chan error // non-nil when sync is running -} - -// chainSyncOp is a scheduled sync operation. -type chainSyncOp struct { - mode downloader.SyncMode - peer *eth.Peer - td *big.Int - head common.Hash -} - -// newChainSyncer creates a chainSyncer. -func newChainSyncer(handler *handler) *chainSyncer { - return &chainSyncer{ - handler: handler, - peerEventCh: make(chan struct{}), - } -} - -// handlePeerEvent notifies the syncer about a change in the peer set. -// This is called for new peers and every time a peer announces a new -// chain head. -func (cs *chainSyncer) handlePeerEvent() bool { - select { - case cs.peerEventCh <- struct{}{}: - return true - case <-cs.handler.quitSync: - return false - } -} - -// loop runs in its own goroutine and launches the sync when necessary. -func (cs *chainSyncer) loop() { - defer cs.handler.wg.Done() - - cs.handler.blockFetcher.Start() - cs.handler.txFetcher.Start() - defer cs.handler.blockFetcher.Stop() - defer cs.handler.txFetcher.Stop() - defer cs.handler.downloader.Terminate() - - // The force timer lowers the peer count threshold down to one when it fires. - // This ensures we'll always start sync even if there aren't enough peers. - cs.force = time.NewTimer(forceSyncCycle) - defer cs.force.Stop() - - for { - if op := cs.nextSyncOp(); op != nil { - cs.startSync(op) - } - select { - case <-cs.peerEventCh: - // Peer information changed, recheck. - case err := <-cs.doneCh: - cs.doneCh = nil - cs.force.Reset(forceSyncCycle) - cs.forced = false - - // If we've reached the merge transition but no beacon client is available, or - // it has not yet switched us over, keep warning the user that their infra is - // potentially flaky. - if errors.Is(err, downloader.ErrMergeTransition) && time.Since(cs.warned) > 10*time.Second { - log.Warn("Local chain is post-merge, waiting for beacon client sync switch-over...") - cs.warned = time.Now() - } - case <-cs.force.C: - cs.forced = true - - case <-cs.handler.quitSync: - // Disable all insertion on the blockchain. This needs to happen before - // terminating the downloader because the downloader waits for blockchain - // inserts, and these can take a long time to finish. - cs.handler.chain.StopInsert() - cs.handler.downloader.Terminate() - if cs.doneCh != nil { - <-cs.doneCh - } - return - } - } -} - -// nextSyncOp determines whether sync is required at this time. -func (cs *chainSyncer) nextSyncOp() *chainSyncOp { - if cs.doneCh != nil { - return nil // Sync already running - } - // If a beacon client once took over control, disable the entire legacy sync - // path from here on end. Note, there is a slight "race" between reaching TTD - // and the beacon client taking over. The downloader will enforce that nothing - // above the first TTD will be delivered to the chain for import. - // - // An alternative would be to check the local chain for exceeding the TTD and - // avoid triggering a sync in that case, but that could also miss sibling or - // other family TTD block being accepted. - if cs.handler.chain.Config().TerminalTotalDifficultyPassed || cs.handler.merger.TDDReached() { - return nil - } - // Ensure we're at minimum peer count. - minPeers := defaultMinSyncPeers - if cs.forced { - minPeers = 1 - } else if minPeers > cs.handler.maxPeers { - minPeers = cs.handler.maxPeers - } - if cs.handler.peers.len() < minPeers { - return nil - } - // We have enough peers, pick the one with the highest TD, but avoid going - // over the terminal total difficulty. Above that we expect the consensus - // clients to direct the chain head to sync to. - peer := cs.handler.peers.peerWithHighestTD() - if peer == nil { - return nil - } - mode, ourTD := cs.modeAndLocalHead() - op := peerToSyncOp(mode, peer) - if op.td.Cmp(ourTD) <= 0 { - // We seem to be in sync according to the legacy rules. In the merge - // world, it can also mean we're stuck on the merge block, waiting for - // a beacon client. In the latter case, notify the user. - if ttd := cs.handler.chain.Config().TerminalTotalDifficulty; ttd != nil && ourTD.Cmp(ttd) >= 0 && time.Since(cs.warned) > 10*time.Second { - log.Warn("Local chain is post-merge, waiting for beacon client sync switch-over...") - cs.warned = time.Now() - } - return nil // We're in sync - } - return op -} - -func peerToSyncOp(mode downloader.SyncMode, p *eth.Peer) *chainSyncOp { - peerHead, peerTD := p.Head() - return &chainSyncOp{mode: mode, peer: p, td: peerTD, head: peerHead} -} - -func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) { - // If we're in snap sync mode, return that directly - if cs.handler.snapSync.Load() { - block := cs.handler.chain.CurrentSnapBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - return downloader.SnapSync, td - } - // We are probably in full sync, but we might have rewound to before the - // snap sync pivot, check if we should re-enable snap sync. - head := cs.handler.chain.CurrentBlock() - if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil { - if head.Number.Uint64() < *pivot { - block := cs.handler.chain.CurrentSnapBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - return downloader.SnapSync, td - } - } - // We are in a full sync, but the associated head state is missing. To complete - // the head state, forcefully rerun the snap sync. Note it doesn't mean the - // persistent state is corrupted, just mismatch with the head block. - if !cs.handler.chain.HasState(head.Root) { - block := cs.handler.chain.CurrentSnapBlock() - td := cs.handler.chain.GetTd(block.Hash(), block.Number.Uint64()) - log.Info("Reenabled snap sync as chain is stateless") - return downloader.SnapSync, td - } - // Nope, we're really full syncing - td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64()) - return downloader.FullSync, td -} - -// startSync launches doSync in a new goroutine. -func (cs *chainSyncer) startSync(op *chainSyncOp) { - cs.doneCh = make(chan error, 1) - go func() { cs.doneCh <- cs.handler.doSync(op) }() -} - -// doSync synchronizes the local blockchain with a remote peer. -func (h *handler) doSync(op *chainSyncOp) error { - // Run the sync cycle, and disable snap sync if we're past the pivot block - err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode) - if err != nil { - return err - } - h.enableSyncedFeatures() - - head := h.chain.CurrentBlock() - if head.Number.Uint64() > 0 { - // We've completed a sync cycle, notify all peers of new state. This path is - // essential in star-topology networks where a gateway node needs to notify - // all its out-of-date peers of the availability of a new block. This failure - // scenario will most often crop up in private and hackathon networks with - // degenerate connectivity, but it should be healthy for the mainnet too to - // more reliably update peers or the local TD state. - if block := h.chain.GetBlock(head.Hash(), head.Number.Uint64()); block != nil { - h.BroadcastBlock(block, false) - } - } - return nil -} diff --git a/builder/eth/sync_test.go b/builder/eth/sync_test.go deleted file mode 100644 index a31986730..000000000 --- a/builder/eth/sync_test.go +++ /dev/null @@ -1,95 +0,0 @@ -// 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 eth - -import ( - "testing" - "time" - - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/eth/protocols/snap" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// Tests that snap sync is disabled after a successful sync cycle. -func TestSnapSyncDisabling68(t *testing.T) { testSnapSyncDisabling(t, eth.ETH68, snap.SNAP1) } - -// Tests that snap sync gets disabled as soon as a real block is successfully -// imported into the blockchain. -func testSnapSyncDisabling(t *testing.T, ethVer uint, snapVer uint) { - t.Parallel() - - // Create an empty handler and ensure it's in snap sync mode - empty := newTestHandler() - if !empty.handler.snapSync.Load() { - t.Fatalf("snap sync disabled on pristine blockchain") - } - defer empty.close() - - // Create a full handler and ensure snap sync ends up disabled - full := newTestHandlerWithBlocks(1024) - if full.handler.snapSync.Load() { - t.Fatalf("snap sync not disabled on non-empty blockchain") - } - defer full.close() - - // Sync up the two handlers via both `eth` and `snap` - caps := []p2p.Cap{{Name: "eth", Version: ethVer}, {Name: "snap", Version: snapVer}} - - emptyPipeEth, fullPipeEth := p2p.MsgPipe() - defer emptyPipeEth.Close() - defer fullPipeEth.Close() - - emptyPeerEth := eth.NewPeer(ethVer, p2p.NewPeer(enode.ID{1}, "", caps), emptyPipeEth, empty.txpool) - fullPeerEth := eth.NewPeer(ethVer, p2p.NewPeer(enode.ID{2}, "", caps), fullPipeEth, full.txpool) - defer emptyPeerEth.Close() - defer fullPeerEth.Close() - - go empty.handler.runEthPeer(emptyPeerEth, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(empty.handler), peer) - }) - go full.handler.runEthPeer(fullPeerEth, func(peer *eth.Peer) error { - return eth.Handle((*ethHandler)(full.handler), peer) - }) - - emptyPipeSnap, fullPipeSnap := p2p.MsgPipe() - defer emptyPipeSnap.Close() - defer fullPipeSnap.Close() - - emptyPeerSnap := snap.NewPeer(snapVer, p2p.NewPeer(enode.ID{1}, "", caps), emptyPipeSnap) - fullPeerSnap := snap.NewPeer(snapVer, p2p.NewPeer(enode.ID{2}, "", caps), fullPipeSnap) - - go empty.handler.runSnapExtension(emptyPeerSnap, func(peer *snap.Peer) error { - return snap.Handle((*snapHandler)(empty.handler), peer) - }) - go full.handler.runSnapExtension(fullPeerSnap, func(peer *snap.Peer) error { - return snap.Handle((*snapHandler)(full.handler), peer) - }) - // Wait a bit for the above handlers to start - time.Sleep(250 * time.Millisecond) - - // Check that snap sync was disabled - op := peerToSyncOp(downloader.SnapSync, empty.handler.peers.peerWithHighestTD()) - if err := empty.handler.doSync(op); err != nil { - t.Fatal("sync failed:", err) - } - if empty.handler.snapSync.Load() { - t.Fatalf("snap sync not disabled after successful synchronisation") - } -} diff --git a/builder/eth/tracers/api.go b/builder/eth/tracers/api.go deleted file mode 100644 index 683310820..000000000 --- a/builder/eth/tracers/api.go +++ /dev/null @@ -1,1040 +0,0 @@ -// 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 tracers - -import ( - "bufio" - "context" - "encoding/json" - "errors" - "fmt" - "os" - "runtime" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -const ( - // defaultTraceTimeout is the amount of time a single transaction can execute - // by default before being forcefully aborted. - defaultTraceTimeout = 5 * time.Second - - // defaultTraceReexec is the number of blocks the tracer is willing to go back - // and reexecute to produce missing historical state necessary to run a specific - // trace. - defaultTraceReexec = uint64(128) - - // defaultTracechainMemLimit is the size of the triedb, at which traceChain - // switches over and tries to use a disk-backed database instead of building - // on top of memory. - // For non-archive nodes, this limit _will_ be overblown, as disk-backed tries - // will only be found every ~15K blocks or so. - defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024) - - // maximumPendingTraceStates is the maximum number of states allowed waiting - // for tracing. The creation of trace state will be paused if the unused - // trace states exceed this limit. - maximumPendingTraceStates = 128 -) - -var errTxNotFound = errors.New("transaction not found") - -// StateReleaseFunc is used to deallocate resources held by constructing a -// historical state for tracing purposes. -type StateReleaseFunc func() - -// Backend interface provides the common API services (that are provided by -// both full and light clients) with access to necessary functions. -type Backend interface { - HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) - HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) - BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) - BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) - GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) - RPCGasCap() uint64 - ChainConfig() *params.ChainConfig - Engine() consensus.Engine - ChainDb() ethdb.Database - StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) - StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) -} - -// API is the collection of tracing APIs exposed over the private debugging endpoint. -type API struct { - backend Backend -} - -// NewAPI creates a new API definition for the tracing methods of the Ethereum service. -func NewAPI(backend Backend) *API { - return &API{backend: backend} -} - -// chainContext constructs the context reader which is used by the evm for reading -// the necessary chain context. -func (api *API) chainContext(ctx context.Context) core.ChainContext { - return ethapi.NewChainContext(ctx, api.backend) -} - -// blockByNumber is the wrapper of the chain access function offered by the backend. -// It will return an error if the block is not found. -func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { - block, err := api.backend.BlockByNumber(ctx, number) - if err != nil { - return nil, err - } - if block == nil { - return nil, fmt.Errorf("block #%d not found", number) - } - return block, nil -} - -// blockByHash is the wrapper of the chain access function offered by the backend. -// It will return an error if the block is not found. -func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - block, err := api.backend.BlockByHash(ctx, hash) - if err != nil { - return nil, err - } - if block == nil { - return nil, fmt.Errorf("block %s not found", hash.Hex()) - } - return block, nil -} - -// blockByNumberAndHash is the wrapper of the chain access function offered by -// the backend. It will return an error if the block is not found. -// -// Note this function is friendly for the light client which can only retrieve the -// historical(before the CHT) header/block by number. -func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, error) { - block, err := api.blockByNumber(ctx, number) - if err != nil { - return nil, err - } - if block.Hash() == hash { - return block, nil - } - return api.blockByHash(ctx, hash) -} - -// TraceConfig holds extra parameters to trace functions. -type TraceConfig struct { - *logger.Config - Tracer *string - Timeout *string - Reexec *uint64 - // Config specific to given tracer. Note struct logger - // config are historically embedded in main object. - TracerConfig json.RawMessage -} - -// TraceCallConfig is the config for traceCall API. It holds one more -// field to override the state for tracing. -type TraceCallConfig struct { - TraceConfig - StateOverrides *ethapi.StateOverride - BlockOverrides *ethapi.BlockOverrides - TxIndex *hexutil.Uint -} - -// StdTraceConfig holds extra parameters to standard-json trace functions. -type StdTraceConfig struct { - logger.Config - Reexec *uint64 - TxHash common.Hash -} - -// txTraceResult is the result of a single transaction trace. -type txTraceResult struct { - TxHash common.Hash `json:"txHash"` // transaction hash - Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer - Error string `json:"error,omitempty"` // Trace failure produced by the tracer -} - -// blockTraceTask represents a single block trace task when an entire chain is -// being traced. -type blockTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing - block *types.Block // Block to trace the transactions from - release StateReleaseFunc // The function to release the held resource for this task - results []*txTraceResult // Trace results produced by the task -} - -// blockTraceResult represents the results of tracing a single block when an entire -// chain is being traced. -type blockTraceResult struct { - Block hexutil.Uint64 `json:"block"` // Block number corresponding to this trace - Hash common.Hash `json:"hash"` // Block hash corresponding to this trace - Traces []*txTraceResult `json:"traces"` // Trace results produced by the task -} - -// txTraceTask represents a single transaction trace task when an entire block -// is being traced. -type txTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing - index int // Transaction offset in the block -} - -// TraceChain returns the structured logs created during the execution of EVM -// between two blocks (excluding start) and returns them as a JSON object. -func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { // Fetch the block interval that we want to trace - from, err := api.blockByNumber(ctx, start) - if err != nil { - return nil, err - } - to, err := api.blockByNumber(ctx, end) - if err != nil { - return nil, err - } - if from.Number().Cmp(to.Number()) >= 0 { - return nil, fmt.Errorf("end block (#%d) needs to come after start block (#%d)", end, start) - } - // Tracing a chain is a **long** operation, only do with subscriptions - notifier, supported := rpc.NotifierFromContext(ctx) - if !supported { - return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported - } - sub := notifier.CreateSubscription() - - resCh := api.traceChain(from, to, config, notifier.Closed()) - go func() { - for result := range resCh { - notifier.Notify(sub.ID, result) - } - }() - return sub, nil -} - -// traceChain configures a new tracer according to the provided configuration, and -// executes all the transactions contained within. The tracing chain range includes -// the end block but excludes the start one. The return value will be one item per -// transaction, dependent on the requested tracer. -// The tracing procedure should be aborted in case the closed signal is received. -func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan interface{}) chan *blockTraceResult { - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - blocks := int(end.NumberU64() - start.NumberU64()) - threads := runtime.NumCPU() - if threads > blocks { - threads = blocks - } - var ( - pend = new(sync.WaitGroup) - ctx = context.Background() - taskCh = make(chan *blockTraceTask, threads) - resCh = make(chan *blockTraceTask, threads) - tracker = newStateTracker(maximumPendingTraceStates, start.NumberU64()) - ) - for th := 0; th < threads; th++ { - pend.Add(1) - go func() { - defer pend.Done() - - // Fetch and execute the block trace taskCh - for task := range taskCh { - var ( - signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) - blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) - ) - // Trace all the transactions contained within - for i, tx := range task.block.Transactions() { - msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) - txctx := &Context{ - BlockHash: task.block.Hash(), - BlockNumber: task.block.Number(), - TxIndex: i, - TxHash: tx.Hash(), - } - res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config) - if err != nil { - task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()} - log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) - break - } - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number())) - task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res} - } - // Tracing state is used up, queue it for de-referencing. Note the - // state is the parent state of trace block, use block.number-1 as - // the state number. - tracker.releaseState(task.block.NumberU64()-1, task.release) - - // Stream the result back to the result catcher or abort on teardown - select { - case resCh <- task: - case <-closed: - return - } - } - }() - } - // Start a goroutine to feed all the blocks into the tracers - go func() { - var ( - logged time.Time - begin = time.Now() - number uint64 - traced uint64 - failed error - statedb *state.StateDB - release StateReleaseFunc - ) - // Ensure everything is properly cleaned up on any exit path - defer func() { - close(taskCh) - pend.Wait() - - // Clean out any pending release functions of trace states. - tracker.callReleases() - - // Log the chain result - switch { - case failed != nil: - log.Warn("Chain tracing failed", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin), "err", failed) - case number < end.NumberU64(): - log.Warn("Chain tracing aborted", "start", start.NumberU64(), "end", end.NumberU64(), "abort", number, "transactions", traced, "elapsed", time.Since(begin)) - default: - log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin)) - } - close(resCh) - }() - // Feed all the blocks both into the tracer, as well as fast process concurrently - for number = start.NumberU64(); number < end.NumberU64(); number++ { - // Stop tracing if interruption was requested - select { - case <-closed: - return - default: - } - // Print progress logs if long enough time elapsed - if time.Since(logged) > 8*time.Second { - logged = time.Now() - log.Info("Tracing chain segment", "start", start.NumberU64(), "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin)) - } - // Retrieve the parent block and target block for tracing. - block, err := api.blockByNumber(ctx, rpc.BlockNumber(number)) - if err != nil { - failed = err - break - } - next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1)) - if err != nil { - failed = err - break - } - // Make sure the state creator doesn't go too far. Too many unprocessed - // trace state may cause the oldest state to become stale(e.g. in - // path-based scheme). - if err = tracker.wait(number); err != nil { - failed = err - break - } - // Prepare the statedb for tracing. Don't use the live database for - // tracing to avoid persisting state junks into the database. Switch - // over to `preferDisk` mode only if the memory usage exceeds the - // limit, the trie database will be reconstructed from scratch only - // if the relevant state is available in disk. - var preferDisk bool - if statedb != nil { - s1, s2, s3 := statedb.Database().TrieDB().Size() - preferDisk = s1+s2+s3 > defaultTracechainMemLimit - } - statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk) - if err != nil { - failed = err - break - } - // Clean out any pending release functions of trace state. Note this - // step must be done after constructing tracing state, because the - // tracing state of block next depends on the parent state and construction - // may fail if we release too early. - tracker.callReleases() - - // Send the block over to the concurrent tracers (if not in the fast-forward phase) - txs := next.Transactions() - select { - case taskCh <- &blockTraceTask{statedb: statedb.Copy(), block: next, release: release, results: make([]*txTraceResult, len(txs))}: - case <-closed: - tracker.releaseState(number, release) - return - } - traced += uint64(len(txs)) - } - }() - - // Keep reading the trace results and stream them to result channel. - retCh := make(chan *blockTraceResult) - go func() { - defer close(retCh) - var ( - next = start.NumberU64() + 1 - done = make(map[uint64]*blockTraceResult) - ) - for res := range resCh { - // Queue up next received result - result := &blockTraceResult{ - Block: hexutil.Uint64(res.block.NumberU64()), - Hash: res.block.Hash(), - Traces: res.results, - } - done[uint64(result.Block)] = result - - // Stream completed traces to the result channel - for result, ok := done[next]; ok; result, ok = done[next] { - if len(result.Traces) > 0 || next == end.NumberU64() { - // It will be blocked in case the channel consumer doesn't take the - // tracing result in time(e.g. the websocket connect is not stable) - // which will eventually block the entire chain tracer. It's the - // expected behavior to not waste node resources for a non-active user. - retCh <- result - } - delete(done, next) - next++ - } - } - }() - return retCh -} - -// TraceBlockByNumber returns the structured logs created during the execution of -// EVM and returns them as a JSON object. -func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) { - block, err := api.blockByNumber(ctx, number) - if err != nil { - return nil, err - } - return api.traceBlock(ctx, block, config) -} - -// TraceBlockByHash returns the structured logs created during the execution of -// EVM and returns them as a JSON object. -func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) { - block, err := api.blockByHash(ctx, hash) - if err != nil { - return nil, err - } - return api.traceBlock(ctx, block, config) -} - -// TraceBlock returns the structured logs created during the execution of EVM -// and returns them as a JSON object. -func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*txTraceResult, error) { - block := new(types.Block) - if err := rlp.DecodeBytes(blob, block); err != nil { - return nil, fmt.Errorf("could not decode block: %v", err) - } - return api.traceBlock(ctx, block, config) -} - -// TraceBlockFromFile returns the structured logs created during the execution of -// EVM and returns them as a JSON object. -func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) { - blob, err := os.ReadFile(file) - if err != nil { - return nil, fmt.Errorf("could not read file: %v", err) - } - return api.TraceBlock(ctx, blob, config) -} - -// TraceBadBlock returns the structured logs created during the execution of -// EVM against a block pulled from the pool of bad ones and returns them as a JSON -// object. -func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) { - block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash) - if block == nil { - return nil, fmt.Errorf("bad block %#x not found", hash) - } - return api.traceBlock(ctx, block, config) -} - -// StandardTraceBlockToFile dumps the structured logs created during the -// execution of EVM to the local file system and returns a list of files -// to the caller. -func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) { - block, err := api.blockByHash(ctx, hash) - if err != nil { - return nil, err - } - return api.standardTraceBlockToFile(ctx, block, config) -} - -// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list -// of intermediate roots: the stateroot after each transaction. -func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { - block, _ := api.blockByHash(ctx, hash) - if block == nil { - // Check in the bad blocks - block = rawdb.ReadBadBlock(api.backend.ChainDb(), hash) - } - if block == nil { - return nil, fmt.Errorf("block %#x not found", hash) - } - if block.NumberU64() == 0 { - return nil, errors.New("genesis is not traceable") - } - parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) - if err != nil { - return nil, err - } - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, err - } - defer release() - - var ( - roots []common.Hash - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - chainConfig = api.backend.ChainConfig() - vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) - ) - for i, tx := range block.Transactions() { - if err := ctx.Err(); err != nil { - return nil, err - } - var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) - txContext = core.NewEVMTxContext(msg) - vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) - ) - statedb.SetTxContext(tx.Hash(), i) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { - log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) - // We intentionally don't return the error here: if we do, then the RPC server will not - // return the roots. Most likely, the caller already knows that a certain transaction fails to - // be included, but still want the intermediate roots that led to that point. - // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be - // executable. - // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. - return roots, nil - } - // calling IntermediateRoot will internally call Finalize on the state - // so any modifications are written to the trie - roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects)) - } - return roots, nil -} - -// StandardTraceBadBlockToFile dumps the structured logs created during the -// execution of EVM against a block pulled from the pool of bad ones to the -// local file system and returns a list of files to the caller. -func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) { - block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash) - if block == nil { - return nil, fmt.Errorf("bad block %#x not found", hash) - } - return api.standardTraceBlockToFile(ctx, block, config) -} - -// traceBlock configures a new tracer according to the provided configuration, and -// executes all the transactions contained within. The return value will be one item -// per transaction, dependent on the requested tracer. -func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { - if block.NumberU64() == 0 { - return nil, errors.New("genesis is not traceable") - } - // Prepare base state - parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) - if err != nil { - return nil, err - } - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, err - } - defer release() - - // JS tracers have high overhead. In this case run a parallel - // process that generates states in one thread and traces txes - // in separate worker threads. - if config != nil && config.Tracer != nil && *config.Tracer != "" { - if isJS := DefaultDirectory.IsJS(*config.Tracer); isJS { - return api.traceBlockParallel(ctx, block, statedb, config) - } - } - // Native tracers have low overhead - var ( - txs = block.Transactions() - blockHash = block.Hash() - is158 = api.backend.ChainConfig().IsEIP158(block.Number()) - blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - results = make([]*txTraceResult, len(txs)) - ) - for i, tx := range txs { - // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - txctx := &Context{ - BlockHash: blockHash, - BlockNumber: block.Number(), - TxIndex: i, - TxHash: tx.Hash(), - } - res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config) - if err != nil { - return nil, err - } - results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res} - // Finalize the state so any modifications are written to the trie - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(is158) - } - return results, nil -} - -// traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread -// runs along and executes txes without tracing enabled to generate their prestate. -// Worker threads take the tasks and the prestate and trace them. -func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { - // Execute all the transaction contained within the block concurrently - var ( - txs = block.Transactions() - blockHash = block.Hash() - blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - results = make([]*txTraceResult, len(txs)) - pend sync.WaitGroup - ) - threads := runtime.NumCPU() - if threads > len(txs) { - threads = len(txs) - } - jobs := make(chan *txTraceTask, threads) - for th := 0; th < threads; th++ { - pend.Add(1) - go func() { - defer pend.Done() - // Fetch and execute the next transaction trace tasks - for task := range jobs { - msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) - txctx := &Context{ - BlockHash: blockHash, - BlockNumber: block.Number(), - TxIndex: task.index, - TxHash: txs[task.index].Hash(), - } - res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config) - if err != nil { - results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()} - continue - } - results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res} - } - }() - } - - // Feed the transactions into the tracers and return - var failed error -txloop: - for i, tx := range txs { - // Send the trace task over for execution - task := &txTraceTask{statedb: statedb.Copy(), index: i} - select { - case <-ctx.Done(): - failed = ctx.Err() - break txloop - case jobs <- task: - } - - // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - statedb.SetTxContext(tx.Hash(), i) - vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { - failed = err - break txloop - } - // Finalize the state so any modifications are written to the trie - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) - } - - close(jobs) - pend.Wait() - - // If execution failed in between, abort - if failed != nil { - return nil, failed - } - return results, nil -} - -// standardTraceBlockToFile configures a new tracer which uses standard JSON output, -// and traces either a full block or an individual transaction. The return value will -// be one filename per transaction traced. -func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) { - // If we're tracing a single transaction, make sure it's present - if config != nil && config.TxHash != (common.Hash{}) { - if !containsTx(block, config.TxHash) { - return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash) - } - } - if block.NumberU64() == 0 { - return nil, errors.New("genesis is not traceable") - } - parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) - if err != nil { - return nil, err - } - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, err - } - defer release() - - // Retrieve the tracing configurations, or use default values - var ( - logConfig logger.Config - txHash common.Hash - ) - if config != nil { - logConfig = config.Config - txHash = config.TxHash - } - logConfig.Debug = true - - // Execute transaction, either tracing all or just the requested one - var ( - dumps []string - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - chainConfig = api.backend.ChainConfig() - vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - canon = true - ) - // Check if there are any overrides: the caller may wish to enable a future - // fork when executing this block. Note, such overrides are only applicable to the - // actual specified block, not any preceding blocks that we have to go through - // in order to obtain the state. - // Therefore, it's perfectly valid to specify `"futureForkBlock": 0`, to enable `futureFork` - if config != nil && config.Overrides != nil { - // Note: This copies the config, to not screw up the main config - chainConfig, canon = overrideConfig(chainConfig, config.Overrides) - } - for i, tx := range block.Transactions() { - // Prepare the transaction for un-traced execution - var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) - txContext = core.NewEVMTxContext(msg) - vmConf vm.Config - dump *os.File - writer *bufio.Writer - err error - ) - // If the transaction needs tracing, swap out the configs - if tx.Hash() == txHash || txHash == (common.Hash{}) { - // Generate a unique temporary file to dump it into - prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4]) - if !canon { - prefix = fmt.Sprintf("%valt-", prefix) - } - dump, err = os.CreateTemp(os.TempDir(), prefix) - if err != nil { - return nil, err - } - dumps = append(dumps, dump.Name()) - - // Swap out the noop logger to the standard tracer - writer = bufio.NewWriter(dump) - vmConf = vm.Config{ - Tracer: logger.NewJSONLogger(&logConfig, writer), - EnablePreimageRecording: true, - } - } - // Execute the transaction and flush any traces to disk - vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) - statedb.SetTxContext(tx.Hash(), i) - _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)) - if writer != nil { - writer.Flush() - } - if dump != nil { - dump.Close() - log.Info("Wrote standard trace", "file", dump.Name()) - } - if err != nil { - return dumps, err - } - // Finalize the state so any modifications are written to the trie - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) - - // If we've traced the transaction we were looking for, abort - if tx.Hash() == txHash { - break - } - } - return dumps, nil -} - -// containsTx reports whether the transaction with a certain hash -// is contained within the specified block. -func containsTx(block *types.Block, hash common.Hash) bool { - for _, tx := range block.Transactions() { - if tx.Hash() == hash { - return true - } - } - return false -} - -// TraceTransaction returns the structured logs created during the execution of EVM -// and returns them as a JSON object. -func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) { - found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash) - if err != nil { - return nil, ethapi.NewTxIndexingError() - } - // Only mined txes are supported - if !found { - return nil, errTxNotFound - } - // It shouldn't happen in practice. - if blockNumber == 0 { - return nil, errors.New("genesis is not traceable") - } - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash) - if err != nil { - return nil, err - } - msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec) - if err != nil { - return nil, err - } - defer release() - - txctx := &Context{ - BlockHash: blockHash, - BlockNumber: block.Number(), - TxIndex: int(index), - TxHash: hash, - } - return api.traceTx(ctx, msg, txctx, vmctx, statedb, config) -} - -// TraceCall lets you trace a given eth_call. It collects the structured logs -// created during the execution of EVM if the given transaction was added on -// top of the provided block and returns them as a JSON object. -// If no transaction index is specified, the trace will be conducted on the state -// after executing the specified block. However, if a transaction index is provided, -// the trace will be conducted on the state after executing the specified transaction -// within the specified block. -func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) { - // Try to retrieve the specified block - var ( - err error - block *types.Block - statedb *state.StateDB - release StateReleaseFunc - ) - if hash, ok := blockNrOrHash.Hash(); ok { - block, err = api.blockByHash(ctx, hash) - } else if number, ok := blockNrOrHash.Number(); ok { - if number == rpc.PendingBlockNumber { - // We don't have access to the miner here. For tracing 'future' transactions, - // it can be done with block- and state-overrides instead, which offers - // more flexibility and stability than trying to trace on 'pending', since - // the contents of 'pending' is unstable and probably not a true representation - // of what the next actual block is likely to contain. - return nil, errors.New("tracing on top of pending is not supported") - } - block, err = api.blockByNumber(ctx, number) - } else { - return nil, errors.New("invalid arguments; neither block nor hash specified") - } - if err != nil { - return nil, err - } - // try to recompute the state - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - - if config != nil && config.TxIndex != nil { - _, _, statedb, release, err = api.backend.StateAtTransaction(ctx, block, int(*config.TxIndex), reexec) - } else { - statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, nil, true, false) - } - if err != nil { - return nil, err - } - defer release() - - vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - // Apply the customization rules if required. - if config != nil { - if err := config.StateOverrides.Apply(statedb); err != nil { - return nil, err - } - config.BlockOverrides.Apply(&vmctx) - } - // Execute the trace - msg, err := args.ToMessage(api.backend.RPCGasCap(), vmctx.BaseFee) - if err != nil { - return nil, err - } - - var traceConfig *TraceConfig - if config != nil { - traceConfig = &config.TraceConfig - } - return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig) -} - -// traceTx configures a new tracer according to the provided configuration, and -// executes the given message in the provided environment. The return value will -// be tracer dependent. -func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { - var ( - tracer Tracer - err error - timeout = defaultTraceTimeout - txContext = core.NewEVMTxContext(message) - ) - if config == nil { - config = &TraceConfig{} - } - // Default tracer is the struct logger - tracer = logger.NewStructLogger(config.Config) - if config.Tracer != nil { - tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig) - if err != nil { - return nil, err - } - } - vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true}) - - // Define a meaningful timeout of a single transaction trace - if config.Timeout != nil { - if timeout, err = time.ParseDuration(*config.Timeout); err != nil { - return nil, err - } - } - deadlineCtx, cancel := context.WithTimeout(ctx, timeout) - go func() { - <-deadlineCtx.Done() - if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) { - tracer.Stop(errors.New("execution timeout")) - // Stop evm execution. Note cancellation is not necessarily immediate. - vmenv.Cancel() - } - }() - defer cancel() - - // Call Prepare to clear out the statedb access list - statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit)); err != nil { - return nil, fmt.Errorf("tracing failed: %w", err) - } - return tracer.GetResult() -} - -// APIs return the collection of RPC services the tracer package offers. -func APIs(backend Backend) []rpc.API { - // Append all the local APIs and return - return []rpc.API{ - { - Namespace: "debug", - Service: NewAPI(backend), - }, - } -} - -// overrideConfig returns a copy of original with forks enabled by override enabled, -// along with a boolean that indicates whether the copy is canonical (equivalent to the original). -// Note: the Clique-part is _not_ deep copied -func overrideConfig(original *params.ChainConfig, override *params.ChainConfig) (*params.ChainConfig, bool) { - copy := new(params.ChainConfig) - *copy = *original - canon := true - - // Apply forks (after Berlin) to the copy. - if block := override.BerlinBlock; block != nil { - copy.BerlinBlock = block - canon = false - } - if block := override.LondonBlock; block != nil { - copy.LondonBlock = block - canon = false - } - if block := override.ArrowGlacierBlock; block != nil { - copy.ArrowGlacierBlock = block - canon = false - } - if block := override.GrayGlacierBlock; block != nil { - copy.GrayGlacierBlock = block - canon = false - } - if block := override.MergeNetsplitBlock; block != nil { - copy.MergeNetsplitBlock = block - canon = false - } - if timestamp := override.ShanghaiTime; timestamp != nil { - copy.ShanghaiTime = timestamp - canon = false - } - if timestamp := override.CancunTime; timestamp != nil { - copy.CancunTime = timestamp - canon = false - } - if timestamp := override.PragueTime; timestamp != nil { - copy.PragueTime = timestamp - canon = false - } - if timestamp := override.VerkleTime; timestamp != nil { - copy.VerkleTime = timestamp - canon = false - } - - return copy, canon -} diff --git a/builder/eth/tracers/api_test.go b/builder/eth/tracers/api_test.go deleted file mode 100644 index d8e4b9a4e..000000000 --- a/builder/eth/tracers/api_test.go +++ /dev/null @@ -1,997 +0,0 @@ -// 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 tracers - -import ( - "context" - "crypto/ecdsa" - "encoding/json" - "errors" - "fmt" - "math/big" - "reflect" - "sync/atomic" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - "golang.org/x/exp/slices" -) - -var ( - errStateNotFound = errors.New("state not found") - errBlockNotFound = errors.New("block not found") -) - -type testBackend struct { - chainConfig *params.ChainConfig - engine consensus.Engine - chaindb ethdb.Database - chain *core.BlockChain - - refHook func() // Hook is invoked when the requested state is referenced - relHook func() // Hook is invoked when the requested state is released -} - -// testBackend creates a new test backend. OBS: After test is done, teardown must be -// invoked in order to release associated resources. -func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend { - backend := &testBackend{ - chainConfig: gspec.Config, - engine: ethash.NewFaker(), - chaindb: rawdb.NewMemoryDatabase(), - } - // Generate blocks for testing - _, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator) - - // Import the canonical chain - cacheConfig := &core.CacheConfig{ - TrieCleanLimit: 256, - TrieDirtyLimit: 256, - TrieTimeLimit: 5 * time.Minute, - SnapshotLimit: 0, - TrieDirtyDisabled: true, // Archive mode - } - chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil, nil) - if err != nil { - t.Fatalf("failed to create tester chain: %v", err) - } - if n, err := chain.InsertChain(blocks); err != nil { - t.Fatalf("block %d: failed to insert into chain: %v", n, err) - } - backend.chain = chain - return backend -} - -func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - return b.chain.GetHeaderByHash(hash), nil -} - -func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { - if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { - return b.chain.CurrentHeader(), nil - } - return b.chain.GetHeaderByNumber(uint64(number)), nil -} - -func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return b.chain.GetBlockByHash(hash), nil -} - -func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { - if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { - return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil - } - return b.chain.GetBlockByNumber(uint64(number)), nil -} - -func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) { - tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash) - return tx != nil, tx, hash, blockNumber, index, nil -} - -func (b *testBackend) RPCGasCap() uint64 { - return 25000000 -} - -func (b *testBackend) ChainConfig() *params.ChainConfig { - return b.chainConfig -} - -func (b *testBackend) Engine() consensus.Engine { - return b.engine -} - -func (b *testBackend) ChainDb() ethdb.Database { - return b.chaindb -} - -// teardown releases the associated resources. -func (b *testBackend) teardown() { - b.chain.Stop() -} - -func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) { - statedb, err := b.chain.StateAt(block.Root()) - if err != nil { - return nil, nil, errStateNotFound - } - if b.refHook != nil { - b.refHook() - } - release := func() { - if b.relHook != nil { - b.relHook() - } - } - return statedb, release, nil -} - -func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { - parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) - if parent == nil { - return nil, vm.BlockContext{}, nil, nil, errBlockNotFound - } - statedb, release, err := b.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, vm.BlockContext{}, nil, nil, errStateNotFound - } - if txIndex == 0 && len(block.Transactions()) == 0 { - return nil, vm.BlockContext{}, statedb, release, nil - } - // Recompute transactions up to the target index. - signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time()) - for idx, tx := range block.Transactions() { - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - txContext := core.NewEVMTxContext(msg) - context := core.NewEVMBlockContext(block.Header(), b.chain, nil) - if idx == txIndex { - return msg, context, statedb, release, nil - } - vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{}) - if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) - } - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) - } - return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) -} - -func TestTraceCall(t *testing.T) { - t.Parallel() - - // Initialize test accounts - accounts := newAccounts(3) - genesis := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks := 10 - signer := types.HomesteadSigner{} - nonce := uint64(0) - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &accounts[1].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - nonce++ - - if i == genBlocks-2 { - // Transfer from account[0] to account[2] - tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &accounts[2].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - nonce++ - - // Transfer from account[0] to account[1] again - tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &accounts[1].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - nonce++ - } - }) - - uintPtr := func(i int) *hexutil.Uint { x := hexutil.Uint(i); return &x } - - defer backend.teardown() - api := NewAPI(backend) - var testSuite = []struct { - blockNumber rpc.BlockNumber - call ethapi.TransactionArgs - config *TraceCallConfig - expectErr error - expect string - }{ - // Standard JSON trace upon the genesis, plain transfer. - { - blockNumber: rpc.BlockNumber(0), - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: nil, - expectErr: nil, - expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`, - }, - // Standard JSON trace upon the head, plain transfer. - { - blockNumber: rpc.BlockNumber(genBlocks), - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: nil, - expectErr: nil, - expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`, - }, - // Upon the last state, default to the post block's state - { - blockNumber: rpc.BlockNumber(genBlocks - 1), - call: ethapi.TransactionArgs{ - From: &accounts[2].addr, - To: &accounts[0].addr, - Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))), - }, - config: nil, - expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`, - }, - // Before the first transaction, should be failed - { - blockNumber: rpc.BlockNumber(genBlocks - 1), - call: ethapi.TransactionArgs{ - From: &accounts[2].addr, - To: &accounts[0].addr, - Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))), - }, - config: &TraceCallConfig{TxIndex: uintPtr(0)}, - expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr), - }, - // Before the target transaction, should be failed - { - blockNumber: rpc.BlockNumber(genBlocks - 1), - call: ethapi.TransactionArgs{ - From: &accounts[2].addr, - To: &accounts[0].addr, - Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))), - }, - config: &TraceCallConfig{TxIndex: uintPtr(1)}, - expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr), - }, - // After the target transaction, should be succeed - { - blockNumber: rpc.BlockNumber(genBlocks - 1), - call: ethapi.TransactionArgs{ - From: &accounts[2].addr, - To: &accounts[0].addr, - Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))), - }, - config: &TraceCallConfig{TxIndex: uintPtr(2)}, - expectErr: nil, - expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`, - }, - // Standard JSON trace upon the non-existent block, error expects - { - blockNumber: rpc.BlockNumber(genBlocks + 1), - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: nil, - expectErr: fmt.Errorf("block #%d not found", genBlocks+1), - //expect: nil, - }, - // Standard JSON trace upon the latest block - { - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: nil, - expectErr: nil, - expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`, - }, - // Tracing on 'pending' should fail: - { - blockNumber: rpc.PendingBlockNumber, - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - To: &accounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: nil, - expectErr: errors.New("tracing on top of pending is not supported"), - }, - { - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - Input: &hexutil.Bytes{0x43}, // blocknumber - }, - config: &TraceCallConfig{ - BlockOverrides: ðapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))}, - }, - expectErr: nil, - expect: ` {"gas":53018,"failed":false,"returnValue":"","structLogs":[ - {"pc":0,"op":"NUMBER","gas":24946984,"gasCost":2,"depth":1,"stack":[]}, - {"pc":1,"op":"STOP","gas":24946982,"gasCost":0,"depth":1,"stack":["0x1337"]}]}`, - }, - } - for i, testspec := range testSuite { - result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config) - if testspec.expectErr != nil { - if err == nil { - t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr) - continue - } - if !reflect.DeepEqual(err.Error(), testspec.expectErr.Error()) { - t.Errorf("test %d: error mismatch, want '%v', got '%v'", i, testspec.expectErr, err) - } - } else { - if err != nil { - t.Errorf("test %d: expect no error, got %v", i, err) - continue - } - var have *logger.ExecutionResult - if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil { - t.Errorf("test %d: failed to unmarshal result %v", i, err) - } - var want *logger.ExecutionResult - if err := json.Unmarshal([]byte(testspec.expect), &want); err != nil { - t.Errorf("test %d: failed to unmarshal result %v", i, err) - } - if !reflect.DeepEqual(have, want) { - t.Errorf("test %d: result mismatch, want %v, got %v", i, testspec.expect, string(result.(json.RawMessage))) - } - } - } -} - -func TestTraceTransaction(t *testing.T) { - t.Parallel() - - // Initialize test accounts - accounts := newAccounts(2) - genesis := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - target := common.Hash{} - signer := types.HomesteadSigner{} - backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &accounts[1].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - target = tx.Hash() - }) - defer backend.chain.Stop() - api := NewAPI(backend) - result, err := api.TraceTransaction(context.Background(), target, nil) - if err != nil { - t.Errorf("Failed to trace transaction %v", err) - } - var have *logger.ExecutionResult - if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil { - t.Errorf("failed to unmarshal result %v", err) - } - if !reflect.DeepEqual(have, &logger.ExecutionResult{ - Gas: params.TxGas, - Failed: false, - ReturnValue: "", - StructLogs: []logger.StructLogRes{}, - }) { - t.Error("Transaction tracing result is different") - } - - // Test non-existent transaction - _, err = api.TraceTransaction(context.Background(), common.Hash{42}, nil) - if !errors.Is(err, errTxNotFound) { - t.Fatalf("want %v, have %v", errTxNotFound, err) - } -} - -func TestTraceBlock(t *testing.T) { - t.Parallel() - - // Initialize test accounts - accounts := newAccounts(3) - genesis := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks := 10 - signer := types.HomesteadSigner{} - var txHash common.Hash - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &accounts[1].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - txHash = tx.Hash() - }) - defer backend.chain.Stop() - api := NewAPI(backend) - - var testSuite = []struct { - blockNumber rpc.BlockNumber - config *TraceConfig - want string - expectErr error - }{ - // Trace genesis block, expect error - { - blockNumber: rpc.BlockNumber(0), - expectErr: errors.New("genesis is not traceable"), - }, - // Trace head block - { - blockNumber: rpc.BlockNumber(genBlocks), - want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), - }, - // Trace non-existent block - { - blockNumber: rpc.BlockNumber(genBlocks + 1), - expectErr: fmt.Errorf("block #%d not found", genBlocks+1), - }, - // Trace latest block - { - blockNumber: rpc.LatestBlockNumber, - want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), - }, - // Trace pending block - { - blockNumber: rpc.PendingBlockNumber, - want: fmt.Sprintf(`[{"txHash":"%v","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`, txHash), - }, - } - for i, tc := range testSuite { - result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config) - if tc.expectErr != nil { - if err == nil { - t.Errorf("test %d, want error %v", i, tc.expectErr) - continue - } - if !reflect.DeepEqual(err, tc.expectErr) { - t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err) - } - continue - } - if err != nil { - t.Errorf("test %d, want no error, have %v", i, err) - continue - } - have, _ := json.Marshal(result) - want := tc.want - if string(have) != want { - t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want) - } - } -} - -func TestTracingWithOverrides(t *testing.T) { - t.Parallel() - // Initialize test accounts - accounts := newAccounts(3) - storageAccount := common.Address{0x13, 37} - genesis := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - // An account with existing storage - storageAccount: { - Balance: new(big.Int), - Storage: map[common.Hash]common.Hash{ - common.HexToHash("0x03"): common.HexToHash("0x33"), - common.HexToHash("0x04"): common.HexToHash("0x44"), - }, - }, - }, - } - genBlocks := 10 - signer := types.HomesteadSigner{} - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &accounts[1].addr, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: b.BaseFee(), - Data: nil}), - signer, accounts[0].key) - b.AddTx(tx) - }) - defer backend.chain.Stop() - api := NewAPI(backend) - randomAccounts := newAccounts(3) - type res struct { - Gas int - Failed bool - ReturnValue string - } - var testSuite = []struct { - blockNumber rpc.BlockNumber - call ethapi.TransactionArgs - config *TraceCallConfig - expectErr error - want string - }{ - // Call which can only succeed if state is state overridden - { - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))}, - }, - }, - want: `{"gas":21000,"failed":false,"returnValue":""}`, - }, - // Invalid call without state overriding - { - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[1].addr, - Value: (*hexutil.Big)(big.NewInt(1000)), - }, - config: &TraceCallConfig{}, - expectErr: core.ErrInsufficientFunds, - }, - // Successful simple contract call - // - // // SPDX-License-Identifier: GPL-3.0 - // - // pragma solidity >=0.7.0 <0.8.0; - // - // /** - // * @title Storage - // * @dev Store & retrieve value in a variable - // */ - // contract Storage { - // uint256 public number; - // constructor() { - // number = block.number; - // } - // } - { - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[2].addr, - Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number() - }, - config: &TraceCallConfig{ - //Tracer: &tracer, - StateOverrides: ðapi.StateOverride{ - randomAccounts[2].addr: ethapi.OverrideAccount{ - Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")), - StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}), - }, - }, - }, - want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`, - }, - { // Override blocknumber - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - // BLOCKNUMBER PUSH1 MSTORE - Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")), - //&hexutil.Bytes{0x43}, // blocknumber - }, - config: &TraceCallConfig{ - BlockOverrides: ðapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))}, - }, - want: `{"gas":59537,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000001337"}`, - }, - { // Override blocknumber, and query a blockhash - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &accounts[0].addr, - Input: &hexutil.Bytes{ - 0x60, 0x00, 0x40, // BLOCKHASH(0) - 0x60, 0x00, 0x52, // STORE memory offset 0 - 0x61, 0x13, 0x36, 0x40, // BLOCKHASH(0x1336) - 0x60, 0x20, 0x52, // STORE memory offset 32 - 0x61, 0x13, 0x37, 0x40, // BLOCKHASH(0x1337) - 0x60, 0x40, 0x52, // STORE memory offset 64 - 0x60, 0x60, 0x60, 0x00, 0xf3, // RETURN (0-96) - - }, // blocknumber - }, - config: &TraceCallConfig{ - BlockOverrides: ðapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))}, - }, - want: `{"gas":72666,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`, - }, - /* - pragma solidity =0.8.12; - - contract Test { - uint private x; - - function test2() external { - x = 1337; - revert(); - } - - function test() external returns (uint) { - x = 1; - try this.test2() {} catch (bytes memory) {} - return x; - } - } - */ - { // First with only code override, not storage override - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[2].addr, - Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), // - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - randomAccounts[2].addr: ethapi.OverrideAccount{ - Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")), - }, - }, - }, - want: `{"gas":44100,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000001"}`, - }, - { // Same again, this time with storage override - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &randomAccounts[2].addr, - Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), // - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - randomAccounts[2].addr: ethapi.OverrideAccount{ - Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060325760003560e01c806366e41cb7146037578063f8a8fd6d14603f575b600080fd5b603d6057565b005b60456062565b60405190815260200160405180910390f35b610539600090815580fd5b60006001600081905550306001600160a01b03166366e41cb76040518163ffffffff1660e01b8152600401600060405180830381600087803b15801560a657600080fd5b505af192505050801560b6575060015b60e9573d80801560e1576040519150601f19603f3d011682016040523d82523d6000602084013e60e6565b606091505b50505b506000549056fea26469706673582212205ce45de745a5308f713cb2f448589177ba5a442d1a2eff945afaa8915961b4d064736f6c634300080c0033")), - State: newStates([]common.Hash{{}}, []common.Hash{{}}), - }, - }, - }, - //want: `{"gas":46900,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000539"}`, - want: `{"gas":44100,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000001"}`, - }, - { // No state override - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &storageAccount, - Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), // - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - storageAccount: ethapi.OverrideAccount{ - Code: newRPCBytes([]byte{ - // SLOAD(3) + SLOAD(4) (which is 0x77) - byte(vm.PUSH1), 0x04, - byte(vm.SLOAD), - byte(vm.PUSH1), 0x03, - byte(vm.SLOAD), - byte(vm.ADD), - // 0x77 -> MSTORE(0) - byte(vm.PUSH1), 0x00, - byte(vm.MSTORE), - // RETURN (0, 32) - byte(vm.PUSH1), 32, - byte(vm.PUSH1), 00, - byte(vm.RETURN), - }), - }, - }, - }, - want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000077"}`, - }, - { // Full state override - // The original storage is - // 3: 0x33 - // 4: 0x44 - // With a full override, where we set 3:0x11, the slot 4 should be - // removed. So SLOT(3)+SLOT(4) should be 0x11. - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &storageAccount, - Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), // - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - storageAccount: ethapi.OverrideAccount{ - Code: newRPCBytes([]byte{ - // SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x00) - byte(vm.PUSH1), 0x04, - byte(vm.SLOAD), - byte(vm.PUSH1), 0x03, - byte(vm.SLOAD), - byte(vm.ADD), - // 0x11 -> MSTORE(0) - byte(vm.PUSH1), 0x00, - byte(vm.MSTORE), - // RETURN (0, 32) - byte(vm.PUSH1), 32, - byte(vm.PUSH1), 00, - byte(vm.RETURN), - }), - State: newStates( - []common.Hash{common.HexToHash("0x03")}, - []common.Hash{common.HexToHash("0x11")}), - }, - }, - }, - want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000011"}`, - }, - { // Partial state override - // The original storage is - // 3: 0x33 - // 4: 0x44 - // With a partial override, where we set 3:0x11, the slot 4 as before. - // So SLOT(3)+SLOT(4) should be 0x55. - blockNumber: rpc.LatestBlockNumber, - call: ethapi.TransactionArgs{ - From: &randomAccounts[0].addr, - To: &storageAccount, - Data: newRPCBytes(common.Hex2Bytes("f8a8fd6d")), // - }, - config: &TraceCallConfig{ - StateOverrides: ðapi.StateOverride{ - storageAccount: ethapi.OverrideAccount{ - Code: newRPCBytes([]byte{ - // SLOAD(3) + SLOAD(4) (which is now 0x11 + 0x44) - byte(vm.PUSH1), 0x04, - byte(vm.SLOAD), - byte(vm.PUSH1), 0x03, - byte(vm.SLOAD), - byte(vm.ADD), - // 0x55 -> MSTORE(0) - byte(vm.PUSH1), 0x00, - byte(vm.MSTORE), - // RETURN (0, 32) - byte(vm.PUSH1), 32, - byte(vm.PUSH1), 00, - byte(vm.RETURN), - }), - StateDiff: &map[common.Hash]common.Hash{ - common.HexToHash("0x03"): common.HexToHash("0x11"), - }, - }, - }, - }, - want: `{"gas":25288,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000000055"}`, - }, - } - for i, tc := range testSuite { - result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config) - if tc.expectErr != nil { - if err == nil { - t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr) - continue - } - if !errors.Is(err, tc.expectErr) { - t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err) - } - continue - } - if err != nil { - t.Errorf("test %d: want no error, have %v", i, err) - continue - } - // Turn result into res-struct - var ( - have res - want res - ) - resBytes, _ := json.Marshal(result) - json.Unmarshal(resBytes, &have) - json.Unmarshal([]byte(tc.want), &want) - if !reflect.DeepEqual(have, want) { - t.Logf("result: %v\n", string(resBytes)) - t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, have, want) - } - } -} - -type Account struct { - key *ecdsa.PrivateKey - addr common.Address -} - -func newAccounts(n int) (accounts []Account) { - for i := 0; i < n; i++ { - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - accounts = append(accounts, Account{key: key, addr: addr}) - } - slices.SortFunc(accounts, func(a, b Account) int { return a.addr.Cmp(b.addr) }) - return accounts -} - -func newRPCBalance(balance *big.Int) **hexutil.Big { - rpcBalance := (*hexutil.Big)(balance) - return &rpcBalance -} - -func newRPCBytes(bytes []byte) *hexutil.Bytes { - rpcBytes := hexutil.Bytes(bytes) - return &rpcBytes -} - -func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash { - if len(keys) != len(vals) { - panic("invalid input") - } - m := make(map[common.Hash]common.Hash) - for i := 0; i < len(keys); i++ { - m[keys[i]] = vals[i] - } - return &m -} - -func TestTraceChain(t *testing.T) { - // Initialize test accounts - accounts := newAccounts(3) - genesis := &core.Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - }, - } - genBlocks := 50 - signer := types.HomesteadSigner{} - - var ( - ref atomic.Uint32 // total refs has made - rel atomic.Uint32 // total rels has made - nonce uint64 - ) - backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1] - // value: 1000 wei - // fee: 0 wei - for j := 0; j < i+1; j++ { - tx, _ := types.SignTx(types.NewTransaction(nonce, accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key) - b.AddTx(tx) - nonce += 1 - } - }) - backend.refHook = func() { ref.Add(1) } - backend.relHook = func() { rel.Add(1) } - api := NewAPI(backend) - - single := `{"txHash":"0x0000000000000000000000000000000000000000000000000000000000000000","result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}` - var cases = []struct { - start uint64 - end uint64 - config *TraceConfig - }{ - {0, 50, nil}, // the entire chain range, blocks [1, 50] - {10, 20, nil}, // the middle chain range, blocks [11, 20] - } - for _, c := range cases { - ref.Store(0) - rel.Store(0) - - from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start)) - to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end)) - resCh := api.traceChain(from, to, c.config, nil) - - next := c.start + 1 - for result := range resCh { - if have, want := uint64(result.Block), next; have != want { - t.Fatalf("unexpected tracing block, have %d want %d", have, want) - } - if have, want := len(result.Traces), int(next); have != want { - t.Fatalf("unexpected result length, have %d want %d", have, want) - } - for _, trace := range result.Traces { - trace.TxHash = common.Hash{} - blob, _ := json.Marshal(trace) - if have, want := string(blob), single; have != want { - t.Fatalf("unexpected tracing result, have\n%v\nwant:\n%v", have, want) - } - } - next += 1 - } - if next != c.end+1 { - t.Error("Missing tracing block") - } - - if nref, nrel := ref.Load(), rel.Load(); nref != nrel { - t.Errorf("Ref and deref actions are not equal, ref %d rel %d", nref, nrel) - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/calltrace_test.go b/builder/eth/tracers/internal/tracetest/calltrace_test.go deleted file mode 100644 index 6216a16ce..000000000 --- a/builder/eth/tracers/internal/tracetest/calltrace_test.go +++ /dev/null @@ -1,401 +0,0 @@ -// 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 tracetest - -import ( - "encoding/json" - "math/big" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/tests" -) - -type callContext struct { - Number math.HexOrDecimal64 `json:"number"` - Difficulty *math.HexOrDecimal256 `json:"difficulty"` - Time math.HexOrDecimal64 `json:"timestamp"` - GasLimit math.HexOrDecimal64 `json:"gasLimit"` - Miner common.Address `json:"miner"` -} - -// callLog is the result of LOG opCode -type callLog struct { - Address common.Address `json:"address"` - Topics []common.Hash `json:"topics"` - Data hexutil.Bytes `json:"data"` - Position hexutil.Uint `json:"position"` -} - -// callTrace is the result of a callTracer run. -type callTrace struct { - From common.Address `json:"from"` - Gas *hexutil.Uint64 `json:"gas"` - GasUsed *hexutil.Uint64 `json:"gasUsed"` - To *common.Address `json:"to,omitempty"` - Input hexutil.Bytes `json:"input"` - Output hexutil.Bytes `json:"output,omitempty"` - Error string `json:"error,omitempty"` - RevertReason string `json:"revertReason,omitempty"` - Calls []callTrace `json:"calls,omitempty"` - Logs []callLog `json:"logs,omitempty"` - Value *hexutil.Big `json:"value,omitempty"` - // Gencodec adds overridden fields at the end - Type string `json:"type"` -} - -// callTracerTest defines a single test to check the call tracer against. -type callTracerTest struct { - Genesis *core.Genesis `json:"genesis"` - Context *callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result *callTrace `json:"result"` -} - -// Iterates over all the input-output datasets in the tracer test harness and -// runs the JavaScript tracers against them. -func TestCallTracerLegacy(t *testing.T) { - testCallTracer("callTracerLegacy", "call_tracer_legacy", t) -} - -func TestCallTracerNative(t *testing.T) { - testCallTracer("callTracer", "call_tracer", t) -} - -func TestCallTracerNativeWithLog(t *testing.T) { - testCallTracer("callTracer", "call_tracer_withLog", t) -} - -func testCallTracer(tracerName string, dirPath string, t *testing.T) { - isLegacy := strings.HasSuffix(dirPath, "_legacy") - files, err := os.ReadDir(filepath.Join("testdata", dirPath)) - if err != nil { - t.Fatalf("failed to retrieve tracer test suite: %v", err) - } - for _, file := range files { - if !strings.HasSuffix(file.Name(), ".json") { - continue - } - file := file // capture range variable - t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { - t.Parallel() - - var ( - test = new(callTracerTest) - tx = new(types.Transaction) - ) - // Call tracer test found, read if from disk - if blob, err := os.ReadFile(filepath.Join("testdata", dirPath, file.Name())); err != nil { - t.Fatalf("failed to read testcase: %v", err) - } else if err := json.Unmarshal(blob, test); err != nil { - t.Fatalf("failed to parse testcase: %v", err) - } - if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil { - t.Fatalf("failed to parse testcase input: %v", err) - } - // Configure a blockchain with the given prestate - var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) - context = vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: test.Context.Miner, - BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: uint64(test.Context.Time), - Difficulty: (*big.Int)(test.Context.Difficulty), - GasLimit: uint64(test.Context.GasLimit), - BaseFee: test.Genesis.BaseFee, - } - state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) - ) - state.Close() - - tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) - if err != nil { - t.Fatalf("failed to create call tracer: %v", err) - } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) - if err != nil { - t.Fatalf("failed to prepare transaction for tracing: %v", err) - } - evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer}) - vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - if err != nil { - t.Fatalf("failed to execute transaction: %v", err) - } - // Retrieve the trace result and compare against the expected. - res, err := tracer.GetResult() - if err != nil { - t.Fatalf("failed to retrieve trace result: %v", err) - } - // The legacy javascript calltracer marshals json in js, which - // is not deterministic (as opposed to the golang json encoder). - if isLegacy { - // This is a tweak to make it deterministic. Can be removed when - // we remove the legacy tracer. - var x callTrace - json.Unmarshal(res, &x) - res, _ = json.Marshal(x) - } - want, err := json.Marshal(test.Result) - if err != nil { - t.Fatalf("failed to marshal test: %v", err) - } - if string(want) != string(res) { - t.Fatalf("trace mismatch\n have: %v\n want: %v\n", string(res), string(want)) - } - // Sanity check: compare top call's gas used against vm result - type simpleResult struct { - GasUsed hexutil.Uint64 - } - var topCall simpleResult - if err := json.Unmarshal(res, &topCall); err != nil { - t.Fatalf("failed to unmarshal top calls gasUsed: %v", err) - } - if uint64(topCall.GasUsed) != vmRet.UsedGas { - t.Fatalf("top call has invalid gasUsed. have: %d want: %d", topCall.GasUsed, vmRet.UsedGas) - } - }) - } -} - -func BenchmarkTracers(b *testing.B) { - files, err := os.ReadDir(filepath.Join("testdata", "call_tracer")) - if err != nil { - b.Fatalf("failed to retrieve tracer test suite: %v", err) - } - for _, file := range files { - if !strings.HasSuffix(file.Name(), ".json") { - continue - } - file := file // capture range variable - b.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(b *testing.B) { - blob, err := os.ReadFile(filepath.Join("testdata", "call_tracer", file.Name())) - if err != nil { - b.Fatalf("failed to read testcase: %v", err) - } - test := new(callTracerTest) - if err := json.Unmarshal(blob, test); err != nil { - b.Fatalf("failed to parse testcase: %v", err) - } - benchTracer("callTracer", test, b) - }) - } -} - -func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { - // Configure a blockchain with the given prestate - tx := new(types.Transaction) - if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { - b.Fatalf("failed to parse testcase input: %v", err) - } - signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) - origin, _ := signer.Sender(tx) - txContext := vm.TxContext{ - Origin: origin, - GasPrice: tx.GasPrice(), - } - context := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: test.Context.Miner, - BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: uint64(test.Context.Time), - Difficulty: (*big.Int)(test.Context.Difficulty), - GasLimit: uint64(test.Context.GasLimit), - } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) - if err != nil { - b.Fatalf("failed to prepare transaction for tracing: %v", err) - } - state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) - defer state.Close() - - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil) - if err != nil { - b.Fatalf("failed to create call tracer: %v", err) - } - evm := vm.NewEVM(context, txContext, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer}) - snap := state.StateDB.Snapshot() - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - if _, err = st.TransitionDb(); err != nil { - b.Fatalf("failed to execute transaction: %v", err) - } - if _, err = tracer.GetResult(); err != nil { - b.Fatal(err) - } - state.StateDB.RevertToSnapshot(snap) - } -} - -func TestInternals(t *testing.T) { - var ( - to = common.HexToAddress("0x00000000000000000000000000000000deadbeef") - origin = common.HexToAddress("0x00000000000000000000000000000000feed") - txContext = vm.TxContext{ - Origin: origin, - GasPrice: big.NewInt(1), - } - context = vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: common.Address{}, - BlockNumber: new(big.Int).SetUint64(8000000), - Time: 5, - Difficulty: big.NewInt(0x30000), - GasLimit: uint64(6000000), - } - ) - mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer { - tr, err := tracers.DefaultDirectory.New(name, nil, cfg) - if err != nil { - t.Fatalf("failed to create call tracer: %v", err) - } - return tr - } - - for _, tc := range []struct { - name string - code []byte - tracer tracers.Tracer - want string - }{ - { - // TestZeroValueToNotExitCall tests the calltracer(s) on the following: - // Tx to A, A calls B with zero value. B does not already exist. - // Expected: that enter/exit is invoked and the inner call is shown in the result - name: "ZeroValueToNotExitCall", - code: []byte{ - byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), // in and outs zero - byte(vm.DUP1), byte(vm.PUSH1), 0xff, byte(vm.GAS), // value=0,address=0xff, gas=GAS - byte(vm.CALL), - }, - tracer: mkTracer("callTracer", nil), - want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`, - }, - { - name: "Stack depletion in LOG0", - code: []byte{byte(vm.LOG3)}, - tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)), - want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`, - }, - { - name: "Mem expansion in LOG0", - code: []byte{ - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x0, - byte(vm.MSTORE), - byte(vm.PUSH1), 0xff, - byte(vm.PUSH1), 0x0, - byte(vm.LOG0), - }, - tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)), - want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"}],"value":"0x0","type":"CALL"}`, - }, - { - // Leads to OOM on the prestate tracer - name: "Prestate-tracer - CREATE2 OOM", - code: []byte{ - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x0, - byte(vm.MSTORE), - byte(vm.PUSH1), 0x1, - byte(vm.PUSH5), 0xff, 0xff, 0xff, 0xff, 0xff, - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x0, - byte(vm.CREATE2), - byte(vm.PUSH1), 0xff, - byte(vm.PUSH1), 0x0, - byte(vm.LOG0), - }, - tracer: mkTracer("prestateTracer", nil), - want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`, - }, - { - // CREATE2 which requires padding memory by prestate tracer - name: "Prestate-tracer - CREATE2 Memory padding", - code: []byte{ - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x0, - byte(vm.MSTORE), - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0xff, - byte(vm.PUSH1), 0x1, - byte(vm.PUSH1), 0x0, - byte(vm.CREATE2), - byte(vm.PUSH1), 0xff, - byte(vm.PUSH1), 0x0, - byte(vm.LOG0), - }, - tracer: mkTracer("prestateTracer", nil), - want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"0x91ff9a805d36f54e3e272e230f3e3f5c1b330804":{"balance":"0x0"}}`, - }, - } { - t.Run(tc.name, func(t *testing.T) { - state := tests.MakePreState(rawdb.NewMemoryDatabase(), - types.GenesisAlloc{ - to: types.Account{ - Code: tc.code, - }, - origin: types.Account{ - Balance: big.NewInt(500000000000000), - }, - }, false, rawdb.HashScheme) - defer state.Close() - - evm := vm.NewEVM(context, txContext, state.StateDB, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer}) - msg := &core.Message{ - To: &to, - From: origin, - Value: big.NewInt(0), - GasLimit: 80000, - GasPrice: big.NewInt(0), - GasFeeCap: big.NewInt(0), - GasTipCap: big.NewInt(0), - SkipAccountChecks: false, - } - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) - if _, err := st.TransitionDb(); err != nil { - t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err) - } - // Retrieve the trace result and compare against the expected - res, err := tc.tracer.GetResult() - if err != nil { - t.Fatalf("test %v: failed to retrieve trace result: %v", tc.name, err) - } - if string(res) != tc.want { - t.Errorf("test %v: trace mismatch\n have: %v\n want: %v\n", tc.name, string(res), tc.want) - } - }) - } -} diff --git a/builder/eth/tracers/internal/tracetest/flat_calltrace_test.go b/builder/eth/tracers/internal/tracetest/flat_calltrace_test.go deleted file mode 100644 index abee48891..000000000 --- a/builder/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package tracetest - -import ( - "encoding/json" - "fmt" - "math/big" - "os" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/tests" - - // Force-load the native, to trigger registration - "github.com/ethereum/go-ethereum/eth/tracers" -) - -// flatCallTrace is the result of a callTracerParity run. -type flatCallTrace struct { - Action flatCallTraceAction `json:"action"` - BlockHash common.Hash `json:"-"` - BlockNumber uint64 `json:"-"` - Error string `json:"error,omitempty"` - Result flatCallTraceResult `json:"result,omitempty"` - Subtraces int `json:"subtraces"` - TraceAddress []int `json:"traceAddress"` - TransactionHash common.Hash `json:"-"` - TransactionPosition uint64 `json:"-"` - Type string `json:"type"` - Time string `json:"-"` -} - -type flatCallTraceAction 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"` -} - -type flatCallTraceResult 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"` -} - -// flatCallTracerTest defines a single test to check the call tracer against. -type flatCallTracerTest struct { - Genesis core.Genesis `json:"genesis"` - Context callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result []flatCallTrace `json:"result"` -} - -func flatCallTracerTestRunner(tracerName string, filename string, dirPath string, t testing.TB) error { - // Call tracer test found, read if from disk - blob, err := os.ReadFile(filepath.Join("testdata", dirPath, filename)) - if err != nil { - return fmt.Errorf("failed to read testcase: %v", err) - } - test := new(flatCallTracerTest) - if err := json.Unmarshal(blob, test); err != nil { - return fmt.Errorf("failed to parse testcase: %v", err) - } - // Configure a blockchain with the given prestate - tx := new(types.Transaction) - if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { - return fmt.Errorf("failed to parse testcase input: %v", err) - } - signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) - context := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: test.Context.Miner, - BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: uint64(test.Context.Time), - Difficulty: (*big.Int)(test.Context.Difficulty), - GasLimit: uint64(test.Context.GasLimit), - } - state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) - defer state.Close() - - // Create the tracer, the EVM environment and run it - tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) - if err != nil { - return fmt.Errorf("failed to create call tracer: %v", err) - } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) - if err != nil { - return fmt.Errorf("failed to prepare transaction for tracing: %v", err) - } - evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer}) - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - - if _, err = st.TransitionDb(); err != nil { - return fmt.Errorf("failed to execute transaction: %v", err) - } - - // Retrieve the trace result and compare against the etalon - res, err := tracer.GetResult() - if err != nil { - return fmt.Errorf("failed to retrieve trace result: %v", err) - } - ret := make([]flatCallTrace, 0) - if err := json.Unmarshal(res, &ret); err != nil { - return fmt.Errorf("failed to unmarshal trace result: %v", err) - } - if !jsonEqualFlat(ret, test.Result) { - t.Logf("tracer name: %s", tracerName) - - // uncomment this for easier debugging - // have, _ := json.MarshalIndent(ret, "", " ") - // want, _ := json.MarshalIndent(test.Result, "", " ") - // t.Logf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want)) - - // uncomment this for harder debugging <3 meowsbits - // lines := deep.Equal(ret, test.Result) - // for _, l := range lines { - // t.Logf("%s", l) - // t.FailNow() - // } - - t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result) - } - return nil -} - -// Iterates over all the input-output datasets in the tracer parity test harness and -// runs the Native tracer against them. -func TestFlatCallTracerNative(t *testing.T) { - testFlatCallTracer("flatCallTracer", "call_tracer_flat", t) -} - -func testFlatCallTracer(tracerName string, dirPath string, t *testing.T) { - files, err := os.ReadDir(filepath.Join("testdata", dirPath)) - if err != nil { - t.Fatalf("failed to retrieve tracer test suite: %v", err) - } - for _, file := range files { - if !strings.HasSuffix(file.Name(), ".json") { - continue - } - file := file // capture range variable - t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { - t.Parallel() - - err := flatCallTracerTestRunner(tracerName, file.Name(), dirPath, t) - if err != nil { - t.Fatal(err) - } - }) - } -} - -// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to -// comparison -func jsonEqualFlat(x, y interface{}) bool { - xTrace := new([]flatCallTrace) - yTrace := new([]flatCallTrace) - if xj, err := json.Marshal(x); err == nil { - json.Unmarshal(xj, xTrace) - } else { - return false - } - if yj, err := json.Marshal(y); err == nil { - json.Unmarshal(yj, yTrace) - } else { - return false - } - return reflect.DeepEqual(xTrace, yTrace) -} - -func BenchmarkFlatCallTracer(b *testing.B) { - files, err := filepath.Glob("testdata/call_tracer_flat/*.json") - if err != nil { - b.Fatalf("failed to read testdata: %v", err) - } - - for _, file := range files { - filename := strings.TrimPrefix(file, "testdata/call_tracer_flat/") - b.Run(camel(strings.TrimSuffix(filename, ".json")), func(b *testing.B) { - for n := 0; n < b.N; n++ { - err := flatCallTracerTestRunner("flatCallTracer", filename, "call_tracer_flat", b) - if err != nil { - b.Fatal(err) - } - } - }) - } -} diff --git a/builder/eth/tracers/internal/tracetest/prestate_test.go b/builder/eth/tracers/internal/tracetest/prestate_test.go deleted file mode 100644 index 8a60123dc..000000000 --- a/builder/eth/tracers/internal/tracetest/prestate_test.go +++ /dev/null @@ -1,146 +0,0 @@ -// 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 tracetest - -import ( - "encoding/json" - "math/big" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/tests" -) - -// prestateTrace is the result of a prestateTrace run. -type prestateTrace = map[common.Address]*account - -type account struct { - Balance string `json:"balance"` - Code string `json:"code"` - Nonce uint64 `json:"nonce"` - Storage map[common.Hash]common.Hash `json:"storage"` -} - -// testcase defines a single test to check the stateDiff tracer against. -type testcase struct { - Genesis *core.Genesis `json:"genesis"` - Context *callContext `json:"context"` - Input string `json:"input"` - TracerConfig json.RawMessage `json:"tracerConfig"` - Result interface{} `json:"result"` -} - -func TestPrestateTracerLegacy(t *testing.T) { - testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", t) -} - -func TestPrestateTracer(t *testing.T) { - testPrestateDiffTracer("prestateTracer", "prestate_tracer", t) -} - -func TestPrestateWithDiffModeTracer(t *testing.T) { - testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", t) -} - -func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { - files, err := os.ReadDir(filepath.Join("testdata", dirPath)) - if err != nil { - t.Fatalf("failed to retrieve tracer test suite: %v", err) - } - for _, file := range files { - if !strings.HasSuffix(file.Name(), ".json") { - continue - } - file := file // capture range variable - t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { - t.Parallel() - - var ( - test = new(testcase) - tx = new(types.Transaction) - ) - // Call tracer test found, read if from disk - if blob, err := os.ReadFile(filepath.Join("testdata", dirPath, file.Name())); err != nil { - t.Fatalf("failed to read testcase: %v", err) - } else if err := json.Unmarshal(blob, test); err != nil { - t.Fatalf("failed to parse testcase: %v", err) - } - if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil { - t.Fatalf("failed to parse testcase input: %v", err) - } - // Configure a blockchain with the given prestate - var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) - context = vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: test.Context.Miner, - BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: uint64(test.Context.Time), - Difficulty: (*big.Int)(test.Context.Difficulty), - GasLimit: uint64(test.Context.GasLimit), - BaseFee: test.Genesis.BaseFee, - } - state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) - ) - defer state.Close() - - tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig) - if err != nil { - t.Fatalf("failed to create call tracer: %v", err) - } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) - if err != nil { - t.Fatalf("failed to prepare transaction for tracing: %v", err) - } - evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer}) - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - if _, err = st.TransitionDb(); err != nil { - t.Fatalf("failed to execute transaction: %v", err) - } - // Retrieve the trace result and compare against the expected - res, err := tracer.GetResult() - if err != nil { - t.Fatalf("failed to retrieve trace result: %v", err) - } - // The legacy javascript calltracer marshals json in js, which - // is not deterministic (as opposed to the golang json encoder). - if strings.HasSuffix(dirPath, "_legacy") { - // This is a tweak to make it deterministic. Can be removed when - // we remove the legacy tracer. - var x prestateTrace - json.Unmarshal(res, &x) - res, _ = json.Marshal(x) - } - want, err := json.Marshal(test.Result) - if err != nil { - t.Fatalf("failed to marshal test: %v", err) - } - if string(want) != string(res) { - t.Fatalf("trace mismatch\n have: %v\n want: %v\n", string(res), string(want)) - } - }) - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/create.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/create.json deleted file mode 100644 index df0b2872b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/create.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "context": { - "difficulty": "3755480783", - "gasLimit": "5401723", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294702", - "timestamp": "1513676146" - }, - "genesis": { - "alloc": { - "0x13e4acefe6a6700604929946e70e6443e4e73447": { - "balance": "0xcf3e0938579f000", - "code": "0x", - "nonce": "9", - "storage": {} - }, - "0x7dc9c9730689ff0b0fd506c67db815f12d90a448": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3757315409", - "extraData": "0x566961425443", - "gasLimit": "5406414", - "hash": "0xae107f592eebdd9ff8d6ba00363676096e6afb0e1007a7d3d0af88173077378d", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0xc927aa05a38bc3de864e95c33b3ae559d3f39c4ccd51cef6f113f9c50ba0caf1", - "nonce": "0x93363bbd2c95f410", - "number": "2294701", - "stateRoot": "0x6b6737d5bde8058990483e915866bd1578014baeff57bd5e4ed228a2bfad635c", - "timestamp": "1513676127", - "totalDifficulty": "7160808139332585" - }, - "input": "0xf907ef098504e3b29200830897be8080b9079c606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a1129a01060f46676a5dff6f407f0f51eb6f37f5c8c54e238c70221e18e65fc29d3ea65a0557b01c50ff4ffaac8ed6e5d31237a4ecbac843ab1bfe8bb0165a0060df7c54f", - "result": { - "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", - "gas": "0x897be", - "gasUsed": "0x897be", - "input": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11", - "output": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029", - "to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448", - "type": "CREATE", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json deleted file mode 100644 index 975616064..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/deep_calls.json +++ /dev/null @@ -1,409 +0,0 @@ -{ - "context": { - "difficulty": "117066904", - "gasLimit": "4712384", - "miner": "0x1977c248e1014cc103929dd7f154199c916e39ec", - "number": "25001", - "timestamp": "1479891545" - }, - "genesis": { - "alloc": { - "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a600035046302d05d3f811461008a5780630accce061461009c5780631ab9075a146100c757806331ed274614610102578063645a3b7214610133578063772fdae314610155578063a7f4377914610180578063ae5f80801461019e578063c9bded21146101ea578063f905c15a14610231575b61023a610002565b61023c600054600160a060020a031681565b61023a600435602435604435606435608435600254600160a060020a03166000141561024657610002565b61023a600435600254600160a060020a03166000148015906100f8575060025433600160a060020a03908116911614155b156102f457610002565b61023a60043560243560443560643560843560a43560c435600254600160a060020a03166000141561031657610002565b61023a600435602435600254600160a060020a0316600014156103d057610002565b61023a600435602435604435606435608435600254600160a060020a03166000141561046157610002565b61023a60025433600160a060020a0390811691161461051657610002565b61023a6004356024356044356060828152600160a060020a0382169060ff8516907fa6c2f0913db6f79ff0a4365762c61718973b3413d6e40382e704782a9a5099f690602090a3505050565b61023a600435602435600160a060020a038116606090815260ff8316907fee6348a7ec70f74e3d6cba55a53e9f9110d180d7698e9117fc466ae29a43e34790602090a25050565b61023c60035481565b005b6060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061029d57610002565b60408051858152602081018390528151600160a060020a03858116939087169260ff8a16927f5a690ecd0cb15c1c1fd6b6f8a32df0d4f56cb41a54fea7e94020f013595de796929181900390910190a45050505050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061036d57610002565b6040805186815260208101869052808201859052606081018490529051600160a060020a03831691889160ff8b16917fd65d9ddafbad8824e2bbd6f56cc9f4ac27ba60737035c10a321ea2f681c94d47919081900360800190a450505050505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061042757610002565b60408051828152905183917fa9c6cbc4bd352a6940479f6d802a1001550581858b310d7f68f7bea51218cda6919081900360200190a25050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104b857610002565b80600160a060020a031684600160a060020a03168660ff167f69bdaf789251e1d3a0151259c0c715315496a7404bce9fd0b714674685c2cab78686604051808381526020018281526020019250505060405180910390a45050505050565b600254600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x2cccf5e0538493c235d1c5ef6580f77d99e91396": { - "balance": "0x0", - "code": "0x606060405236156100775760e060020a600035046302d05d3f811461007f57806313bc6d4b146100915780633688a877146100b95780635188f9961461012f5780637eadc976146101545780638ad79680146101d3578063a43e04d814610238578063a7f437791461025e578063e16c7d981461027c575b61029f610002565b6102a1600054600160a060020a031681565b6102be600435600160a060020a03811660009081526002602052604090205460ff165b919050565b6102d26004356040805160208181018352600080835284815260038252835190849020805460026001821615610100026000190190911604601f8101849004840283018401909552848252929390929183018282801561037d5780601f106103525761010080835404028352916020019161037d565b61029f6004356024356000805433600160a060020a039081169116146104a957610002565b61034060043560008181526001602090815260408083205481517ff905c15a0000000000000000000000000000000000000000000000000000000081529151600160a060020a03909116928392839263f905c15a92600483810193919291829003018189876161da5a03f1156100025750506040515195945050505050565b60408051602060248035600481810135601f810185900485028601850190965285855261029f9581359591946044949293909201918190840183828082843750949650505050505050600054600160a060020a0390811633909116146104f657610002565b61029f6004355b600080548190600160a060020a0390811633909116146105a457610002565b61029f60005433600160a060020a0390811691161461072957610002565b6102a1600435600081815260016020526040902054600160a060020a03166100b4565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b820191906000526020600020905b81548152906001019060200180831161036057829003601f168201915b505050505090506100b4565b506000828152600160208181526040808420805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a038581168086526002909352818520805460ff191690941790935580517f1ab9075a0000000000000000000000000000000000000000000000000000000081523090931660048401525184939192631ab9075a926024828101939192829003018183876161da5a03f11561000257505060408051602081018690528082019290925243606083015260808083526003908301527f414444000000000000000000000000000000000000000000000000000000000060a0830152517f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d39181900360c00190a15b505050565b600083815260016020526040902054600160a060020a03838116911614156104d0576104a4565b600083815260016020526040812054600160a060020a031614610389576103898361023f565b600082815260036020908152604082208054845182855293839020919360026001831615610100026000190190921691909104601f90810184900483019391929186019083901061056a57805160ff19168380011785555b5061059a9291505b808211156105a05760008155600101610556565b8280016001018555821561054e579182015b8281111561054e57825182600050559160200191906001019061057c565b50505050565b5090565b600083815260016020526040812054600160a060020a031614156105c757610002565b50506000818152600160205260408082205481517fa7f437790000000000000000000000000000000000000000000000000000000081529151600160a060020a0391909116928392839263a7f4377992600483810193919291829003018183876161da5a03f11561000257505050600160005060008460001916815260200190815260200160002060006101000a815490600160a060020a0302191690556002600050600083600160a060020a0316815260200190815260200160002060006101000a81549060ff02191690557f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d383834360405180806020018560001916815260200184600160a060020a03168152602001838152602001828103825260038152602001807f44454c000000000000000000000000000000000000000000000000000000000081526020015060200194505050505060405180910390a1505050565b600054600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0684ac65a9fa32414dda56996f4183597d695987fdb82b145d722743891a6fe8": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "0x1cd76f78169a420d99346e3501dd3e541622c38a226f9b63e01cfebc69879dc7": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "0x8e54a4494fe5da016bfc01363f4f6cdc91013bb5434bd2a4a3359f13a23afa2f": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "0x94edf7f600ba56655fd65fca1f1424334ce369326c1dc3e53151dcd1ad06bc13": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xbbee47108b275f55f98482c6800f6372165e88b0330d3f5dae6419df4734366c": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "0xd38c0c4e84de118cfdcc775130155d83b8bbaaf23dc7f3c83a626b10473213bd": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xfb3aa5c655c2ec9d40609401f88d505d1da61afaa550e36ef5da0509ada257ba": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" - } - }, - "0x3e9286eafa2db8101246c2131c09b49080d00690": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063056d4470146100e957806316c66cc61461010c5780631ab9075a146101935780633ae1005c146101ce57806358541662146101fe5780635ed61af014610231578063644e3b791461025457806384dbac3b146102db578063949ae479146102fd5780639859387b14610321578063a7f4377914610340578063ab03fc261461035e578063e8161b7814610385578063e964d4e114610395578063f905c15a146103a5578063f92eb774146103ae575b6103be610002565b6103c0600054600160a060020a031681565b6103be6004356002546000908190600160a060020a031681141561040357610002565b6103dd60043560006108365b6040805160025460e360020a631c2d8fb30282527f636f6e747261637464620000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435600254600160a060020a03166000148015906101c4575060025433600160a060020a03908116911614155b1561088d57610002565b6103be600435602435604435606435600254600090819081908190600160a060020a03168114156108af57610002565b6103c0600435602435604435606435608435600254600090819081908190600160a060020a03168114156110e857610002565b6103be6004356002546000908190600160a060020a03168114156115ec57610002565b6103c06004356000611b635b6040805160025460e360020a631c2d8fb30282527f6d61726b6574646200000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435602435600254600160a060020a031660001415611bb557610002565b6103be600435602435600254600090600160a060020a0316811415611d2e57610002565b6103be600435600254600160a060020a031660001415611fc657610002565b6103be60025433600160a060020a0390811691161461207e57610002565b6103be600435602435604435600254600090600160a060020a031681141561208c57610002565b6103dd60043560006124b8610260565b6103c0600435600061250a610118565b6103f160035481565b6103f16004356000612561610260565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061046557610002565b8291506104e55b6040805160025460e360020a631c2d8fb30282527f63706f6f6c00000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f115610002575050604051519150505b90565b600160a060020a031663b2206e6d83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fb2206e6d0000000000000000000000000000000000000000000000000000000082526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f11561000257505060405151915061059b90506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f115610002575050506107355b6040805160025460e360020a631c2d8fb30282527f6c6f676d6772000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b50826120ee5b6040805160025460e360020a631c2d8fb30282527f6163636f756e7463746c0000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316630accce06600684600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150866040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050505050565b600160a060020a03166316c66cc6836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519150505b919050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061091157610002565b87935061091c610260565b600160a060020a031663bdbdb08685600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fbdbdb0860000000000000000000000000000000000000000000000000000000082526004820152602481018a905290516044808301935060209282900301816000876161da5a03f1156100025750506040515193506109ca90506106ba565b600160a060020a03166381982a7a8885876040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610a3661046c565b600160a060020a03166308636bdb85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517f08636bdb000000000000000000000000000000000000000000000000000000008252600482015260248101889052604481019290925251606482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919450600160a060020a03871692506314baa1b6916024828101926000929190829003018183876161da5a03f11561000257505050610b3561046c565b600160a060020a0316630a3b6ede85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038d16602482015290516044808301935060209282900301816000876161da5a03f115610002575050604051519150610bd590506106ba565b600160a060020a031663d5b205ce87838b6040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610c41610118565b600160a060020a031663988db79c888a6040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050610ca5610260565b600160a060020a031663f4f2821b896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610d6f5b6040805160025460e360020a631c2d8fb30282527f747261646564620000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316635f539d69896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610dc2610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928e9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610ec5610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928d9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610fc8610639565b600160a060020a031663645a3b7285600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151905061101e610260565b600160a060020a031663f92eb77488600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f115610002575050505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061114a57610002565b604051600254600160a060020a0316908a908a908a908a908a90611579806125b38339018087600160a060020a0316815260200186600160a060020a03168152602001856000191681526020018481526020018381526020018281526020019650505050505050604051809103906000f092506111c5610118565b600160a060020a031663b9858a288a856040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611229610260565b600160a060020a0316635188f99689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611288610260565b600160a060020a031663bdbdb08689896040518360e060020a0281526004018083600019168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750506040515192506112e590506106ba565b600160a060020a03166346d88e7d8a858a6040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506000604051808303816000876161da5a03f115610002575050506113516106ba565b600160a060020a03166381982a7a8a84866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050506113bd61046c565b600160a060020a0316632b58469689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f1156100025750505061141c61046c565b600160a060020a03166308636bdb8984866040518460e060020a028152600401808460001916815260200183815260200182600160a060020a0316815260200193505050506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919350600160a060020a03861692506314baa1b6916024828101926000929190829003018183876161da5a03f115610002575050506114d3610639565b6040805160e160020a630566670302815260016004820152602481018b9052600160a060020a0386811660448301528c811660648301526000608483018190529251931692630accce069260a480840193919291829003018183876161da5a03f11561000257505050611544610639565b600160a060020a031663645a3b728961155b610260565b600160a060020a031663f92eb7748c6040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448084019360009350829003018183876161da5a03f1156100025750939a9950505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061164e57610002565b82915061165961046c565b600160a060020a0316630a3b6ede83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f1156100025750506040515191506116f990506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f1156100025750505061179b6106ba565b600160a060020a031663d653078983600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517ff1ff78a0000000000000000000000000000000000000000000000000000000008252915191929163f1ff78a09160048181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f1156100025750505061189f610260565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506118f2610118565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050611945610639565b600160a060020a0316630accce06600484600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da44689181870191602091908190038801816000876161da5a03f115610002575050506040518051906020015060006040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050611a48610639565b600160a060020a031663645a3b7283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611a9e610260565b600160a060020a031663f92eb77486600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b600160a060020a03166381738c59836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611c1757610002565b611c1f610260565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060405151159050611c7457610002565b611c7c610260565b600160a060020a0316632243118a836040518260e060020a02815260040180826000191681526020019150506000604051808303816000876161da5a03f11561000257505050611cca610639565b600160a060020a031663ae5f8080600184846040518460e060020a028152600401808481526020018360001916815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611d9057610002565b5081611d9a610260565b600160a060020a031663581d5d6084846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505050611df5610639565b600160a060020a0316630accce06600283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630566670302825260048201949094526024810193909352600160a060020a038816604484015260006064840181905260848401819052905160a4808501949293509091829003018183876161da5a03f11561000257505050611eab610639565b600160a060020a031663645a3b7282600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611f01610260565b600160a060020a031663f92eb77485600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061202857610002565b612030610118565b600160a060020a0316639859387b826040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505050565b600254600160a060020a0316ff5b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f11561000257505060405151151590506106b457610002565b600160a060020a031663d65307898383600160a060020a031663f1ff78a06040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fd6530789000000000000000000000000000000000000000000000000000000008252600160a060020a039485166004830152602482015292891660448401525160648381019360009350829003018183876161da5a03f115610002575050506121a5610118565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506121f8610cf4565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505061224b610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d028252915191928a9290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f1156100025750505080600160a060020a031663ea71b02d6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a031660001490506124b25761239f610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fea71b02d000000000000000000000000000000000000000000000000000000008252915191928a92909163ea71b02d91600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f115610002575050505b50505050565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663213fe2b7836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663f92eb774836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f115610002575050604051519150610888905056606060405260405160c08061157983396101206040819052825160805160a051935160e0516101005160008054600160a060020a03199081163317909155600180546005805484168817905560048a90556006869055600b8590556008849055909116861760a060020a60ff02191690554360038190556002558686526101408390526101608190529396929594919390929091600160a060020a033016917f76885d242fb71c6f74a7e717416e42eff4d96faf54f6de75c6a0a6bbd8890c6b91a230600160a060020a03167fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff600b600050546040518082815260200191505060405180910390a250505050505061145e8061011b6000396000f3606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "16", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ef436dcbda6cd4a", - "code": "0x", - "nonce": "1634", - "storage": {} - }, - "0x7986bad81f4cbd9317f5a46861437dae58d69113": { - "balance": "0x0", - "code": "0x6060604052361561008d5760e060020a600035046302d05d3f811461009557806316c66cc6146100a75780631ab9075a146100d7578063213fe2b7146101125780639859387b1461013f578063988db79c1461015e578063a7f4377914610180578063b9858a281461019e578063c8e40fbf146101c0578063f4f2821b146101e8578063f905c15a14610209575b610212610002565b610214600054600160a060020a031681565b600160a060020a0360043581811660009081526005602052604081205461023193168114610257575060016101e3565b610212600435600254600160a060020a0316600014801590610108575060025433600160a060020a03908116911614155b1561025f57610002565b610214600435600160a060020a03811660009081526004602052604081205460ff16151561027557610002565b610212600435600254600160a060020a03166000141561029b57610002565b610212600435602435600254600160a060020a03166000141561050457610002565b61021260025433600160a060020a0390811691161461056757610002565b610212600435602435600254600160a060020a03166000141561057557610002565b610231600435600160a060020a03811660009081526004602052604090205460ff165b919050565b610212600435600254600090600160a060020a031681141561072057610002565b61024560035481565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060006101e3565b60028054600160a060020a031916821790555b50565b50600160a060020a038181166000908152600460205260409020546101009004166101e3565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506102fe57610002565b600160a060020a03811660009081526004602052604090205460ff161515610272576040516104028061092e833901809050604051809103906000f06004600050600083600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600083600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555050565b600160a060020a03821660009081526004602052604090205460ff1615156104725760405161040280610d30833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a03811660009081526006602052604090208054600160a060020a031916831790555b5050565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506103b957610002565b600254600160a060020a0316ff5b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506105d857610002565b600160a060020a03821660009081526004602052604090205460ff1615156106915760405161040280611132833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a031660009081526005602052604090208054600160a060020a0319169091179055565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f115610002575050604051511515905061078357610002565b50600160a060020a0381811660009081526005602090815260408083205490931680835260049091529190205460ff161561080f576040600081812054825160e260020a632e72bafd028152600160a060020a03868116600483015293516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260056020526040812054909116146108545760406000908120600160a060020a0384169091528054600160a060020a03191690555b50600160a060020a0381811660009081526006602090815260408083205490931680835260049091529190205460ff16156108e657600160a060020a038181166000908152604080518183205460e260020a632e72bafd028252868516600483015291516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260066020526040812054909116146105005760406000908120600160a060020a0384169091528054600160a060020a0319169055505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "7", - "storage": { - "0xffc4df2d4f3d2cffad590bed6296406ab7926ca9e74784f74a95191fa069a174": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - }, - "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f": { - "balance": "0x0", - "code": "0x606060405236156100ae5760e060020a600035046302d05d3f81146100b65780631ab9075a146100c85780632b68bb2d146101035780634cc927d7146101c557806351a34eb81461028e57806356ccb6f0146103545780635928d37f1461041d578063599efa6b146104e9578063759297bb146105b2578063771d50e11461067e578063a7f4377914610740578063f905c15a1461075e578063f92eb77414610767578063febf661214610836575b610902610002565b610904600054600160a060020a031681565b610902600435600254600160a060020a03166000148015906100f9575060025433600160a060020a03908116911614155b1561092057610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061094257610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610a0d57610002565b61090260043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ae957610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610bbc57610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610c9657610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610de057610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ebb57610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f9e57610002565b61090260025433600160a060020a0390811691161461106957610002565b61090e60035481565b61090e60043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750506040805180517ff92eb774000000000000000000000000000000000000000000000000000000008252600482018790529151919350600160a060020a038416925063f92eb774916024828101926020929190829003018188876161da5a03f11561000257505060405151949350505050565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061107757610002565b005b6060908152602090f35b60408051918252519081900360200190f35b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5ed61af000000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152925190959286169350635ed61af092602483810193919291829003018183876161da5a03f115610002575050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fab03fc2600000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015260248301899052808816604484015292519095928616935063ab03fc2692606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f949ae47900000000000000000000000000000000000000000000000000000000825233600160a060020a0390811660048401526024830188905292519095928616935063949ae47992604483810193919291829003018183876161da5a03f11561000257505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f46d88e7d000000000000000000000000000000000000000000000000000000008252600160a060020a0380891660048401523381166024840152604483018890529251909592861693506346d88e7d92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5315cdde00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a16602484015260448301889052925190959286169350635315cdde92606483810193919291829003018183876161da5a03f115610002575050604080517f5928d37f00000000000000000000000000000000000000000000000000000000815233600160a060020a03908116600483015287166024820152604481018690529051635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fe68e401c00000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015280891660248401526044830188905292519095928616935063e68e401c92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5152f381000000000000000000000000000000000000000000000000000000008252600160a060020a03808a1660048401528089166024840152604483018890523381166064840152925190959286169350635152f38192608483810193919291829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f056d447000000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015292519095928616935063056d447092602483810193919291829003018183876161da5a03f115610002575050505050565b600254600160a060020a0316ff5b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f3ae1005c00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a166024840152808916604484015260648301889052925190959286169350633ae1005c92608483810193919291829003018183876161da5a03f11561000257505050505050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000006195", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5842545553440000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" - } - }, - "0xcf00ffd997ad14939736f026006498e3f099baaf": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063031e7f5d146100e95780631ab9075a1461010b5780632243118a1461014657806327aad68a1461016557806338a699a4146101da5780635188f996146101f8578063581d5d601461021e57806381738c5914610246578063977da54014610269578063a07421ce14610288578063a7f43779146102be578063bdbdb086146102dc578063e1c7111914610303578063f4f2821b14610325578063f905c15a1461034a578063f92eb77414610353575b610387610002565b610389600054600160a060020a031681565b610387600435602435600254600160a060020a0316600014156103a857610002565b610387600435600254600160a060020a031660001480159061013c575060025433600160a060020a03908116911614155b1561042957610002565b610387600435600254600160a060020a03166000141561044b57610002565b6102ac60043560008181526004602081815260408320547f524d81d3000000000000000000000000000000000000000000000000000000006060908152610100909104600160a060020a031692839263524d81d3926064928188876161da5a03f1156100025750506040515192506103819050565b61039c60043560008181526004602052604090205460ff165b919050565b6103876004356024356002546000908190600160a060020a031681141561079457610002565b61038760043560243560025460009081908190600160a060020a031681141561080457610002565b61038960043560008181526004602052604081205460ff1615156109e357610002565b610387600435600254600160a060020a0316600014156109fb57610002565b600435600090815260096020526040902054670de0b6b3a764000090810360243502045b60408051918252519081900360200190f35b61038760025433600160a060020a03908116911614610a9257610002565b600435600090815260086020526040902054670de0b6b3a7640000602435909102046102ac565b610387600435602435600254600160a060020a031660001415610aa057610002565b61038760043560025460009081908190600160a060020a0316811415610b3657610002565b6102ac60035481565b6102ac600435600081815260076020908152604080832054600690925290912054670de0b6b3a76400000204805b50919050565b005b600160a060020a03166060908152602090f35b15156060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506103fe57610002565b60008281526004602052604090205460ff16151561041b57610002565b600860205260406000205550565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104a157610002565b604080516000838152600460205291909120805460ff1916600117905561040280610de2833901809050604051809103906000f0600460005060008360001916815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555066470de4df8200006008600050600083600019168152602001908152602001600020600050819055506703782dace9d9000060096000506000836000191681526020019081526020016000206000508190555050565b600460005060008560001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151821415905061060057838152600660209081526040808320839055600790915281208190555b81600160a060020a0316630a3b0a4f846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050600160a060020a038316808252600560209081526040808420879055805160e160020a6364a81ff102815290518694670de0b6b3a7640000949363c9503fe29360048181019492939183900301908290876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008660001916815260200190815260200160002060008282825054019250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000866000191681526020019081526020016000206000828282505401925050819055505b50505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f11561000257505060405151151590506107e957610002565b8381526004602052604081205460ff16151561056657610002565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f115610002575050604051511515905061085957610002565b849250670de0b6b3a764000083600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575060408051805160e160020a6364a81ff102825291519189028590049650600481810192602092909190829003018188876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b9391600481810192602092909190829003018189876161da5a03f115610002575050506040518051906020015002049050806006600050600085600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750604080518051855260208681528286208054989098039097557f2e94420f00000000000000000000000000000000000000000000000000000000815290518896600483810193919291829003018187876161da5a03f115610002575050604080515183526020939093525020805490910190555050505050565b60409020546101009004600160a060020a03166101f3565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610a5157610002565b60008181526004602052604090205460ff161515610a6e57610002565b6040600020805474ffffffffffffffffffffffffffffffffffffffffff1916905550565b600254600160a060020a0316ff5b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610af657610002565b60008281526004602052604090205460ff161515610b1357610002565b670de0b6b3a7640000811115610b2857610002565b600960205260406000205550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f1156100025750506040515115159050610b8b57610002565b600160a060020a038416815260056020908152604080832054808452600490925282205490935060ff161515610bc057610002565b600460005060008460001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663b9caebf4856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506005600050600085600160a060020a0316815260200190815260200160002060005060009055839050600082600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519190911115905061078e57670de0b6b3a764000081600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008560001916815260200190815260200160002060008282825054039250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000856000191681526020019081526020016000206000828282505403925050819055505050505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x3571d73f14f31a1463bd0a2f92f7fde1653d4e1ead7aedf4b0a5df02f16092ab": "0x0000000000000000000000000000000000000000000007d634e4c55188be0000", - "0x4e64fe2d1b72d95a0a31945cc6e4f4e524ac5ad56d6bd44a85ec7bc9cc0462c0": "0x000000000000000000000000000000000000000000000002b5e3af16b1880000" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117124093", - "extraData": "0xd5830105008650617269747986312e31322e31826d61", - "gasLimit": "4707788", - "hash": "0xad325e4c49145fb7a4058a68ac741cc8607a71114e23fc88083c7e881dd653e7", - "miner": "0x00714b9ac97fd6bd9325a059a70c9b9fa94ce050", - "mixHash": "0x0af918f65cb4af04b608fc1f14a849707696986a0e7049e97ef3981808bcc65f", - "nonce": "0x38dee147326a8d40", - "number": "25000", - "stateRoot": "0xc5d6bbcd46236fcdcc80b332ffaaa5476b980b01608f9708408cfef01b58bd5b", - "timestamp": "1479891517", - "totalDifficulty": "1895410389427" - }, - "input": "0xf88b8206628504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb80000000000000000000000000000000000000000000000280faf689c35ac00002aa0a7ee5b7877811bf671d121b40569462e722657044808dc1d6c4f1e4233ec145ba0417e7543d52b65738d9df419cbe40a708424f4d54b0fc145c0a64545a2bb1065", - "result": { - "calls": [ - { - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x31217", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x2a68d", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23ac9", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23366", - "gasUsed": "0x273", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x29f35", - "gasUsed": "0xf8d", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x28a9e", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x21d79", - "gasUsed": "0x24d", - "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x2165b", - "gasUsed": "0x334", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a8e8", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a2c6", - "gasUsed": "0x3cb", - "input": "0xc9503fe2", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19b72", - "gasUsed": "0x3cb", - "input": "0xc9503fe2", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19428", - "gasUsed": "0x305", - "input": "0x6f265b93", - "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x18d45", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1734e", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x20ee1", - "gasUsed": "0x5374", - "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1b6c1", - "gasUsed": "0x334", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1af69", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x143a5", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1a91d", - "gasUsed": "0x12fa", - "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x19177", - "gasUsed": "0x334", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18a22", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18341", - "gasUsed": "0x334", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x17bec", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1764e", - "gasUsed": "0x45c", - "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000", - "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x108ba", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x16e62", - "gasUsed": "0xebb", - "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x283b9", - "gasUsed": "0xc51c", - "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x30b4a", - "gasUsed": "0xedb7", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "gasUsed": "0x1810b", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json deleted file mode 100644 index 6a2cda7dc..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/delegatecall.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "context": { - "difficulty": "31927752", - "gasLimit": "4707788", - "miner": "0x5659922ce141eedbc2733678f9806c77b4eebee8", - "number": "11495", - "timestamp": "1479735917" - }, - "genesis": { - "alloc": { - "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a60003504630a0313a981146100875780630a3b0a4f146101095780630cd40fea1461021257806329092d0e1461021f5780634cd06a5f146103295780635dbe47e8146103395780637a9e5410146103d9578063825db5f7146103e6578063a820b44d146103f3578063efa52fb31461047a575b610002565b34610002576104fc600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a26333556e849091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f415610002575050604051519150505b919050565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f21ce24d4000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926321ce24d49260448082019391829003018186803b156100025760325a03f415610002575050505b50565b3461000257610512600181565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f89489a87000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926389489a879260448082019391829003018186803b156100025760325a03f4156100025750505061020f565b3461000257610528600435610403565b34610002576104fc600435604080516000602091820181905282517f7d65837a00000000000000000000000000000000000000000000000000000000815260048101829052600160a060020a0385166024820152925190927342b02b5deeb78f34cd5ac896473b63e6c99a71a292637d65837a92604480840193829003018186803b156100025760325a03f4156100025750506040515191506101049050565b3461000257610512600c81565b3461000257610512600081565b3461000257610528600061055660005b600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263685a1f3c9091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b346100025761053a600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263f775b6b59091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b604080519115158252519081900360200190f35b005b6040805160ff9092168252519081900360200190f35b60408051918252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b90509056", - "nonce": "1", - "storage": { - "0x4d140b25abf3c71052885c66f73ce07cff141c1afabffdaf5cba04d625b7ebcc": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "0x269296dddce321a6bcbaa2f0181127593d732cba": { - "balance": "0x0", - "code": "0x606060405236156101275760e060020a60003504630cd40fea811461012c578063173825d9146101395780631849cb5a146101c7578063285791371461030f5780632a58b3301461033f5780632cb0d48a146103565780632f54bf6e1461036a578063332b9f061461039d5780633ca8b002146103c55780633df4ddf4146103d557806341c0e1b5146103f457806347799da81461040557806362a51eee1461042457806366907d13146104575780637065cb48146104825780637a9e541014610496578063825db5f7146104a3578063949d225d146104b0578063a51687df146104c7578063b4da4e37146104e6578063b4e6850b146104ff578063bd7474ca14610541578063e75623d814610541578063e9938e1114610555578063f5d241d314610643575b610002565b3461000257610682600181565b34610002576106986004356106ff335b60006001600a9054906101000a9004600160a060020a0316600160a060020a0316635dbe47e8836000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100025760325a03f1156100025750506040515191506103989050565b3461000257604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a0360043581168752600586529589902089519788018a528054808816808a52605060020a91829004600160a060020a0316978a01889052600183015463ffffffff8082169d8c018e905264010000000082048116988c01899052604060020a90910416958a018690526002830154948a01859052600390920154808916938a01849052049096169690970186905293969495949293604080516001605060020a03998a16815297891660208901529590971686860152600160a060020a03909316606086015263ffffffff9182166080860152811660a08501521660c083015260e08201929092529051908190036101000190f35b346100025761069a60043560018054600091829160ff60f060020a909104161515141561063d5761072833610376565b34610002576106ae6004546001605060020a031681565b34610002576106986004356108b333610149565b346100025761069a6004355b600160a060020a03811660009081526002602052604090205460ff1615156001145b919050565b34610002576106986001805460ff60f060020a9091041615151415610913576108ed33610376565b346100025761069a600435610149565b34610002576106ae6003546001605060020a03605060020a9091041681565b346100025761069861091533610149565b34610002576106ae6003546001605060020a0360a060020a9091041681565b346100025761069a60043560243560018054600091829160ff60f060020a909104161515141561095e5761092633610376565b34610002576106986004356001805460ff60f060020a909104161515141561072557610a8b33610376565b3461000257610698600435610aa533610149565b3461000257610682600c81565b3461000257610682600081565b34610002576106ae6003546001605060020a031681565b34610002576106ca600154600160a060020a03605060020a9091041681565b346100025761069a60015460ff60f060020a9091041681565b346100025761069a60043560243560443560643560843560a43560c43560018054600091829160ff60f060020a9091041615151415610b5857610ad233610376565b3461000257610698600435610bd633610149565b34610002576106e6600435604080516101008181018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a03808b168752600586529589902089519788018a5280548088168952600160a060020a03605060020a918290041696890196909652600181015463ffffffff8082169b8a019b909b5264010000000081048b1695890195909552604060020a90940490981691860182905260028301549086015260039091015480841696850196909652940416918101919091525b50919050565b346100025761069a60043560243560443560643560843560a43560018054600091829160ff60f060020a9091041615151415610c8e57610bfb33610376565b6040805160ff9092168252519081900360200190f35b005b604080519115158252519081900360200190f35b604080516001605060020a039092168252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b6040805163ffffffff9092168252519081900360200190f35b1561012757600160a060020a0381166000908152600260205260409020805460ff191690555b50565b1561063d57506001605060020a0380831660009081526005602052604090208054909116151561075b576000915061063d565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610817905b8051600354600090819060016001605060020a0390911611610c995760038054605060020a60f060020a0319169055610ddf565b600380546001605060020a031981166000196001605060020a03928316011782558416600090815260056020526040812080547fffff000000000000000000000000000000000000000000000000000000000000168155600181810180546bffffffffffffffffffffffff191690556002820192909255909101805473ffffffffffffffffffffffffffffffffffffffff19169055915061063d565b1561012757600180547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a8302179055610725565b1561091357600480546001605060020a031981166001605060020a039091166001011790555b565b156101275733600160a060020a0316ff5b1561095e57506001605060020a03808416600090815260056020526040902080549091161515610965576000915061095e565b600191505b5092915050565b60038101546001605060020a0384811691161415610986576001915061095e565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610a12906107e3565b61095983825b80546003546001605060020a0391821691600091161515610de55760038054605060020a60a060020a031916605060020a84021760a060020a69ffffffffffffffffffff02191660a060020a84021781558301805473ffffffffffffffffffffffffffffffffffffffff19169055610ddf565b1561072557600480546001605060020a0319168217905550565b1561012757600160a060020a0381166000908152600260205260409020805460ff19166001179055610725565b15610b5857506001605060020a038088166000908152600560205260409020805490911615610b645760009150610b58565b6004546001605060020a0390811690891610610b3057600480546001605060020a03191660018a011790555b6003805460016001605060020a03821681016001605060020a03199092169190911790915591505b50979650505050505050565b80546001605060020a0319168817605060020a60f060020a031916605060020a880217815560018101805463ffffffff1916871767ffffffff0000000019166401000000008702176bffffffff00000000000000001916604060020a860217905560028101839055610b048982610a18565b156101275760018054605060020a60f060020a031916605060020a8302179055610725565b15610c8e57506001605060020a03808816600090815260056020526040902080549091161515610c2e5760009150610c8e565b8054605060020a60f060020a031916605060020a88021781556001808201805463ffffffff1916881767ffffffff0000000019166401000000008802176bffffffff00000000000000001916604060020a87021790556002820184905591505b509695505050505050565b6003546001605060020a03848116605060020a909204161415610d095760e084015160038054605060020a928302605060020a60a060020a031990911617808255919091046001605060020a031660009081526005602052604090200180546001605060020a0319169055610ddf565b6003546001605060020a0384811660a060020a909204161415610d825760c08401516003805460a060020a92830260a060020a69ffffffffffffffffffff021990911617808255919091046001605060020a03166000908152600560205260409020018054605060020a60a060020a0319169055610ddf565b505060c082015160e08301516001605060020a0380831660009081526005602052604080822060039081018054605060020a60a060020a031916605060020a8702179055928416825290200180546001605060020a031916831790555b50505050565b6001605060020a0384161515610e6457600380546001605060020a03605060020a9182900481166000908152600560205260409020830180546001605060020a0319908116871790915583548785018054918590049093168402605060020a60a060020a03199182161790911690915582549185029116179055610ddf565b506001605060020a038381166000908152600560205260409020600390810180549185018054605060020a60a060020a0319908116605060020a94859004909516808502959095176001605060020a0319168817909155815416918402919091179055801515610ef4576003805460a060020a69ffffffffffffffffffff02191660a060020a8402179055610ddf565b6003808401546001605060020a03605060020a9091041660009081526005602052604090200180546001605060020a031916831790555050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000113204f5d64c28326fd7bd05fd4ea855302d7f2ff00000000000000000000" - } - }, - "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2": { - "balance": "0x0", - "code": "0x6504032353da7150606060405236156100695760e060020a60003504631bf7509d811461006e57806321ce24d41461008157806333556e84146100ec578063685a1f3c146101035780637d65837a1461011757806389489a8714610140578063f775b6b5146101fc575b610007565b61023460043560006100fd82600061010d565b610246600435602435600160a060020a03811660009081526020839052604081205415156102cb57826001016000508054806001018281815481835581811511610278576000838152602090206102789181019083015b808211156102d057600081556001016100d8565b610248600435602435600182015481105b92915050565b6102346004356024355b60018101906100fd565b610248600435602435600160a060020a03811660009081526020839052604090205415156100fd565b61024660043560243580600160a060020a031632600160a060020a03161415156101f857600160a060020a038116600090815260208390526040902054156101f857600160a060020a038116600090815260208390526040902054600183018054909160001901908110156100075760009182526020808320909101805473ffffffffffffffffffffffffffffffffffffffff19169055600160a060020a038316825283905260408120556002820180546000190190555b5050565b61025c60043560243560008260010160005082815481101561000757600091825260209091200154600160a060020a03169392505050565b60408051918252519081900360200190f35b005b604080519115158252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b50505060009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a0385168352908590526040909120819055600284018054600101905590505b505050565b509056", - "nonce": "1", - "storage": {} - }, - "0xa529806c67cc6486d4d62024471772f47f6fd672": { - "balance": "0x67820e39ac8fe9800", - "code": "0x", - "nonce": "68", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "31912170", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0x0855914bdc581bccdc62591fd438498386ffb59ea4d5361ed5c3702e26e2c72f", - "miner": "0x334391aa808257952a462d1475562ee2106a6c90", - "mixHash": "0x64bb70b8ca883cadb8fbbda2c70a861612407864089ed87b98e5de20acceada6", - "nonce": "0x684129f283aaef18", - "number": "11494", - "stateRoot": "0x7057f31fe3dab1d620771adad35224aae43eb70e94861208bc84c557ff5b9d10", - "timestamp": "1479735912", - "totalDifficulty": "90744064339" - }, - "input": "0xf889448504a817c800832dc6c094269296dddce321a6bcbaa2f0181127593d732cba80a47065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e29a080ed81e4c5e9971a730efab4885566e2c868cd80bd4166d0ed8c287fdf181650a069d7c49215e3d4416ad239cd09dbb71b9f04c16b33b385d14f40b618a7a65115", - "result": { - "calls": [ - { - "calls": [ - { - "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "gas": "0x2bf459", - "gasUsed": "0x2aa", - "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2", - "type": "DELEGATECALL", - "value": "0x0" - } - ], - "from": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "gas": "0x2cae73", - "gasUsed": "0xa9d", - "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xa529806c67cc6486d4d62024471772f47f6fd672", - "gas": "0x2dc6c0", - "gasUsed": "0xbd55", - "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e", - "to": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json deleted file mode 100644 index bb16a4a43..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_create_oog_outer_throw.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "context": { - "difficulty": "3451177886", - "gasLimit": "4709286", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2290744", - "timestamp": "1513616439" - }, - "genesis": { - "alloc": { - "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a": { - "balance": "0x0", - "code": "0x606060405263ffffffff60e060020a6000350416633b91f50681146100505780635bb47808146100715780635f51fca01461008c578063bc7647a9146100ad578063f1bd0d7a146100c8575b610000565b346100005761006f600160a060020a03600435811690602435166100e9565b005b346100005761006f600160a060020a0360043516610152565b005b346100005761006f600160a060020a036004358116906024351661019c565b005b346100005761006f600160a060020a03600435166101fa565b005b346100005761006f600160a060020a0360043581169060243516610db8565b005b600160a060020a038083166000908152602081905260408120549091908116903316811461011657610000565b839150600160a060020a038316151561012d573392505b6101378284610e2e565b6101418284610db8565b61014a826101fa565b5b5b50505050565b600154600160a060020a03908116903316811461016e57610000565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b5b5050565b600254600160a060020a0390811690331681146101b857610000565b600160a060020a038381166000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19169184169190911790555b5b505050565b6040805160e260020a631a481fc102815260016024820181905260026044830152606482015262093a8060848201819052600060a4830181905260c06004840152601e60c48401527f736574456e7469747953746174757328616464726573732c75696e743829000060e484015292519091600160a060020a038516916369207f049161010480820192879290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526000602482018190526001604483015260606004830152602360648301527f626567696e506f6c6c28616464726573732c75696e7436342c626f6f6c2c626f60848301527f6f6c29000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f61646453746f636b28616464726573732c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f697373756553746f636b2875696e74382c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602160648301527f6772616e7453746f636b2875696e74382c75696e743235362c61646472657373608483015260f860020a60290260a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f115610000575050604080517f010555b8000000000000000000000000000000000000000000000000000000008152600160a060020a03338116602483015260006044830181905260606004840152603c60648401527f6772616e7456657374656453746f636b2875696e74382c75696e743235362c6160848401527f6464726573732c75696e7436342c75696e7436342c75696e743634290000000060a48401529251908716935063010555b89260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601260c48201527f626567696e53616c65286164647265737329000000000000000000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601a60648301527f7472616e7366657253616c6546756e64732875696e743235362900000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152602d60c48201527f7365744163636f756e74696e6753657474696e67732875696e743235362c756960e48201527f6e7436342c75696e7432353629000000000000000000000000000000000000006101048201529051600160a060020a03861692506369207f04916101248082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152603460648301527f637265617465526563757272696e6752657761726428616464726573732c756960848301527f6e743235362c75696e7436342c737472696e672900000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601b60648301527f72656d6f7665526563757272696e675265776172642875696e7429000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602360648301527f697373756552657761726428616464726573732c75696e743235362c7374726960848301527f6e6729000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f61737369676e53746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f72656d6f766553746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260026024808301919091526003604483015260006064830181905267ffffffffffffffff8616608484015260ff871660a484015260c0600484015260c48301919091527f7365744164647265737342796c617728737472696e672c616464726573732c6260e48301527f6f6f6c29000000000000000000000000000000000000000000000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152602160c48301527f73657453746174757342796c617728737472696e672c75696e74382c626f6f6c60e483015260f860020a6029026101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152603860c48301527f736574566f74696e6742796c617728737472696e672c75696e743235362c756960e48301527f6e743235362c626f6f6c2c75696e7436342c75696e74382900000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f115610000575050505b505050565b604080517f225553a4000000000000000000000000000000000000000000000000000000008152600160a060020a0383811660048301526002602483015291519184169163225553a49160448082019260009290919082900301818387803b156100005760325a03f115610000575050505b5050565b600082604051611fd280610f488339600160a060020a03909216910190815260405190819003602001906000f0801561000057905082600160a060020a03166308b027418260016040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b156100005760325a03f115610000575050604080517fa14e3ee300000000000000000000000000000000000000000000000000000000815260006004820181905260016024830152600160a060020a0386811660448401529251928716935063a14e3ee39260648084019382900301818387803b156100005760325a03f115610000575050505b5050505600606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029a165627a7a723058200e78a5f7e0f91739035d0fbf5eca02f79377210b722f63431f29a22e2880b3bd0029", - "nonce": "789", - "storage": { - "0xfe9ec0542a1c009be8b1f3acf43af97100ffff42eb736850fb038fa1151ad4d9": "0x000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8" - } - }, - "0x5cb4a6b902fcb21588c86c3517e797b07cdaadb9": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe4a13bc304682a903e9472f469c33801dd18d9e8": { - "balance": "0x33c763c929f62c4f", - "code": "0x", - "nonce": "14", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3451177886", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4713874", - "hash": "0x5d52a672417cd1269bf4f7095e25dcbf837747bba908cd5ef809dc1bd06144b5", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x01a12845ed546b94a038a7a03e8df8d7952024ed41ccb3db7a7ade4abc290ce1", - "nonce": "0x28c446f1cb9748c1", - "number": "2290743", - "stateRoot": "0x4898aceede76739daef76448a367d10015a2c022c9e7909b99a10fbf6fb16708", - "timestamp": "1513616414", - "totalDifficulty": "7146523769022564" - }, - "input": "0xf8aa0e8509502f9000830493e0941d3ddf7caf024f253487e18bc4a15b1a360c170a80b8443b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e829a0524564944fa419f5c189b5074044f89210c6d6b2d77ee8f7f12a927d59b636dfa0015b28986807a424b18b186ee6642d76739df36cad802d20e8c00e79a61d7281", - "result": { - "calls": [ - { - "error": "contract creation code storage out of gas", - "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "gas": "0x39ff0", - "gasUsed": "0x39ff0", - "input": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", - "type": "CREATE", - "value": "0x0" - } - ], - "error": "invalid jump destination", - "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8", - "gas": "0x493e0", - "gasUsed": "0x493e0", - "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8", - "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json deleted file mode 100644 index 9b45b52fe..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "genesis": { - "difficulty": "117067574", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712380", - "hash": "0xe05db05eeb3f288041ecb10a787df121c0ed69499355716e17c307de313a4486", - "miner": "0x0c062b329265c965deef1eede55183b3acb8f611", - "mixHash": "0xb669ae39118a53d2c65fd3b1e1d3850dd3f8c6842030698ed846a2762d68b61d", - "nonce": "0x2b469722b8e28c45", - "number": "24973", - "stateRoot": "0x532a5c3f75453a696428db078e32ae283c85cb97e4d8560dbdf022adac6df369", - "timestamp": "1479891145", - "totalDifficulty": "1892250259406", - "alloc": { - "0x6c06b16512b332e6cd8293a2974872674716ce18": { - "balance": "0x0", - "nonce": "1", - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d146036575b6000565b34600057604e60048080359060200190919050506050565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050505b5056", - "storage": {} - }, - "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31": { - "balance": "0x229ebbb36c3e0f20", - "nonce": "3", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 3, - "homesteadBlock": 0, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "byzantiumBlock": 1700000, - "constantinopleBlock": 4230000, - "petersburgBlock": 4939394, - "istanbulBlock": 6485846, - "muirGlacierBlock": 7117117, - "ethash": {} - } - }, - "context": { - "number": "24974", - "difficulty": "117067574", - "timestamp": "1479891162", - "gasLimit": "4712388", - "miner": "0xc822ef32e6d26e170b70cf761e204c1806265914" - }, - "input": "0xf889038504a81557008301f97e946c06b16512b332e6cd8293a2974872674716ce1880a42e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b1600002aa0e2a6558040c5d72bc59f2fb62a38993a314c849cd22fb393018d2c5af3112095a01bdb6d7ba32263ccc2ecc880d38c49d9f0c5a72d8b7908e3122b31356d349745", - "result": { - "type": "CALL", - "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31", - "to": "0x6c06b16512b332e6cd8293a2974872674716ce18", - "value": "0x0", - "gas": "0x1f97e", - "gasUsed": "0x72de", - "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json deleted file mode 100644 index ad0627ccd..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "genesis": { - "baseFeePerGas": "1000000000", - "difficulty": "1", - "extraData": "0x00000000000000000000000000000000000000000000000000000000000000003623191d4ccfbbdf09e8ebf6382a1f8257417bc10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "11500000", - "hash": "0x2af138b8a06e65b8dd0999df70b9e87609e9fc91ea201f08b1cc4f25ef01fcf6", - "miner": "0x0000000000000000000000000000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "number": "0", - "stateRoot": "0xa775801d572e9b79585eb131d18d79f8a0f71895455ab9a5b656911428e11708", - "timestamp": "0", - "totalDifficulty": "1", - "alloc": { - "0x3623191d4ccfbbdf09e8ebf6382a1f8257417bc1": { - "balance": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7" - }, - "0xd15abca351f79181dedfb6d019e382db90f3628a": { - "balance": "0x0" - } - }, - "config": { - "chainId": 1337, - "homesteadBlock": 0, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "muirGlacierBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "clique": { - "period": 0, - "epoch": 30000 - } - } - }, - "context": { - "number": "1", - "difficulty": "2", - "timestamp": "1665537018", - "gasLimit": "11511229", - "miner": "0x0000000000000000000000000000000000000000" - }, - "input": "0x02f9029d82053980849502f90085010c388d00832dc6c08080b90241608060405234801561001057600080fd5b50600060405161001f906100a2565b604051809103906000f08015801561003b573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c04062266040518163ffffffff1660e01b815260040160006040518083038186803b15801561008457600080fd5b505afa158015610098573d6000803e3d6000fd5b50505050506100af565b610145806100fc83390190565b603f806100bd6000396000f3fe6080604052600080fdfea264697066735822122077f7dbd3450d6e817079cf3fe27107de5768bb3163a402b94e2206b468eb025664736f6c63430008070033608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033c001a07566181071cabaf58b70fc41557eb813bfc7a24f5c58554e7fed0bf7c031f169a0420af50b5fe791a4d839e181a676db5250b415dfb35cb85d544db7a1475ae2cc", - "result": { - "from": "0x3623191d4ccfbbdf09e8ebf6382a1f8257417bc1", - "gas": "0x2dc6c0", - "gasUsed": "0x25590", - "input": "0x608060405234801561001057600080fd5b50600060405161001f906100a2565b604051809103906000f08015801561003b573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c04062266040518163ffffffff1660e01b815260040160006040518083038186803b15801561008457600080fd5b505afa158015610098573d6000803e3d6000fd5b50505050506100af565b610145806100fc83390190565b603f806100bd6000396000f3fe6080604052600080fdfea264697066735822122077f7dbd3450d6e817079cf3fe27107de5768bb3163a402b94e2206b468eb025664736f6c63430008070033608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033", - "output": "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012546869732063616c6c6564206661696c65640000000000000000000000000000", - "error": "execution reverted", - "revertReason": "This called failed", - "calls": [ - { - "from": "0xdebfb4b387033eac57af7b3de5116dd60056803b", - "gas": "0x2ba851", - "gasUsed": "0xe557", - "to": "0xd15abca351f79181dedfb6d019e382db90f3628a", - "input": "0x608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033", - "output": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033", - "value": "0x0", - "type": "CREATE" - }, - { - "from": "0xdebfb4b387033eac57af7b3de5116dd60056803b", - "gas": "0x2ac548", - "gasUsed": "0x1b2", - "to": "0xd15abca351f79181dedfb6d019e382db90f3628a", - "input": "0xc0406226", - "output": "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012546869732063616c6c6564206661696c65640000000000000000000000000000", - "error": "execution reverted", - "revertReason": "This called failed", - "type": "STATICCALL" - } - ], - "value": "0x0", - "type": "CREATE" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json deleted file mode 100644 index a023ed6d9..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "context": { - "difficulty": "3956606365", - "gasLimit": "5413248", - "miner": "0x00d8ae40d9a06d0e7a2877b62e32eb959afbe16d", - "number": "2295104", - "timestamp": "1513681256" - }, - "genesis": { - "alloc": { - "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76": { - "balance": "0x0", - "code": "0x60606040526004361061015e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680625b4487146101a257806311df9995146101cb578063278ecde11461022057806330adce0e146102435780633197cbb61461026c5780634bb278f3146102955780636103d70b146102aa57806363a599a4146102bf5780636a2d1cb8146102d457806375f12b21146102fd57806378e979251461032a578063801db9cc1461035357806386d1a69f1461037c5780638da5cb5b146103915780638ef26a71146103e65780639890220b1461040f5780639b39caef14610424578063b85dfb801461044d578063be9a6555146104a1578063ccb07cef146104b6578063d06c91e4146104e3578063d669e1d414610538578063df40503c14610561578063e2982c2114610576578063f02e030d146105c3578063f2fde38b146105d8578063f3283fba14610611575b600060149054906101000a900460ff1615151561017a57600080fd5b60075442108061018b575060085442115b15151561019757600080fd5b6101a03361064a565b005b34156101ad57600080fd5b6101b5610925565b6040518082815260200191505060405180910390f35b34156101d657600080fd5b6101de61092b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561022b57600080fd5b6102416004808035906020019091905050610951565b005b341561024e57600080fd5b610256610c48565b6040518082815260200191505060405180910390f35b341561027757600080fd5b61027f610c4e565b6040518082815260200191505060405180910390f35b34156102a057600080fd5b6102a8610c54565b005b34156102b557600080fd5b6102bd610f3e565b005b34156102ca57600080fd5b6102d261105d565b005b34156102df57600080fd5b6102e76110d5565b6040518082815260200191505060405180910390f35b341561030857600080fd5b6103106110e1565b604051808215151515815260200191505060405180910390f35b341561033557600080fd5b61033d6110f4565b6040518082815260200191505060405180910390f35b341561035e57600080fd5b6103666110fa565b6040518082815260200191505060405180910390f35b341561038757600080fd5b61038f611104565b005b341561039c57600080fd5b6103a4611196565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f157600080fd5b6103f96111bb565b6040518082815260200191505060405180910390f35b341561041a57600080fd5b6104226111c1565b005b341561042f57600080fd5b610437611296565b6040518082815260200191505060405180910390f35b341561045857600080fd5b610484600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061129c565b604051808381526020018281526020019250505060405180910390f35b34156104ac57600080fd5b6104b46112c0565b005b34156104c157600080fd5b6104c9611341565b604051808215151515815260200191505060405180910390f35b34156104ee57600080fd5b6104f6611354565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561054357600080fd5b61054b61137a565b6040518082815260200191505060405180910390f35b341561056c57600080fd5b610574611385565b005b341561058157600080fd5b6105ad600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506116c3565b6040518082815260200191505060405180910390f35b34156105ce57600080fd5b6105d66116db565b005b34156105e357600080fd5b61060f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611829565b005b341561061c57600080fd5b610648600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118fe565b005b600080670de0b6b3a7640000341015151561066457600080fd5b61069b610696670de0b6b3a7640000610688610258346119d990919063ffffffff16565b611a0c90919063ffffffff16565b611a27565b9150660221b262dd80006106ba60065484611a7e90919063ffffffff16565b111515156106c757600080fd5b600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156107d557600080fd5b6102c65a03f115156107e657600080fd5b5050506040518051905050610808828260010154611a7e90919063ffffffff16565b8160010181905550610827348260000154611a7e90919063ffffffff16565b816000018190555061084434600554611a7e90919063ffffffff16565b60058190555061085f82600654611a7e90919063ffffffff16565b6006819055503373ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c836040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e8583600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60025481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060085442108061096b5750651b48eb57e00060065410155b15151561097757600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154821415156109c757600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856000604051602001526040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1515610ac857600080fd5b6102c65a03f11515610ad957600080fd5b5050506040518051905050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610b7d57600080fd5b6102c65a03f11515610b8e57600080fd5b505050604051805190501515610ba357600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000811115610c4457610c433382611a9c565b5b5050565b60055481565b60085481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cb157600080fd5b600854421015610cd357660221b262dd8000600654141515610cd257600080fd5b5b651b48eb57e000600654108015610cf057506213c6806008540142105b151515610cfc57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501515610d7557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1515610e3a57600080fd5b6102c65a03f11515610e4b57600080fd5b5050506040518051905090506000811115610f2057600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610ef957600080fd5b6102c65a03f11515610f0a57600080fd5b505050604051805190501515610f1f57600080fd5b5b6001600960006101000a81548160ff02191690831515021790555050565b600080339150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114151515610f9657600080fd5b803073ffffffffffffffffffffffffffffffffffffffff163110151515610fbc57600080fd5b610fd181600254611b5090919063ffffffff16565b6002819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561105957fe5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110b857600080fd5b6001600060146101000a81548160ff021916908315150217905550565b670de0b6b3a764000081565b600060149054906101000a900460ff1681565b60075481565b651b48eb57e00081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561115f57600080fd5b600060149054906101000a900460ff16151561117a57600080fd5b60008060146101000a81548160ff021916908315150217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561121c57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050151561129457600080fd5b565b61025881565b600a6020528060005260406000206000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561131b57600080fd5b600060075414151561132c57600080fd5b4260078190555062278d004201600881905550565b600960009054906101000a900460ff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b660221b262dd800081565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113e557600080fd5b600654660221b262dd800003925061142b670de0b6b3a764000061141c610258670de0b6b3a76400006119d990919063ffffffff16565b81151561142557fe5b04611a27565b915081831115151561143c57600080fd5b600a60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561158c57600080fd5b6102c65a03f1151561159d57600080fd5b50505060405180519050506115bf838260010154611a7e90919063ffffffff16565b81600101819055506115dc83600654611a7e90919063ffffffff16565b6006819055503073ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c846040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561173657600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b151561181357600080fd5b6102c65a03f1151561182457600080fd5b505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561188457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156118fb57806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561195957600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561199557600080fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828402905060008414806119fa57508284828115156119f757fe5b04145b1515611a0257fe5b8091505092915050565b6000808284811515611a1a57fe5b0490508091505092915050565b6000611a416202a300600754611a7e90919063ffffffff16565b421015611a7557611a6e611a5f600584611a0c90919063ffffffff16565b83611a7e90919063ffffffff16565b9050611a79565b8190505b919050565b6000808284019050838110151515611a9257fe5b8091505092915050565b611aee81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a7e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611b4681600254611a7e90919063ffffffff16565b6002819055505050565b6000828211151515611b5e57fe5b8183039050929150505600a165627a7a72305820ec0d82a406896ccf20989b3d6e650abe4dc104e400837f1f58e67ef499493ae90029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008d69d00910d0b2afb2a99ed6c16c8129fa8e1751", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000e819f024b41358d2c08e3a868a5c5dd0566078d4", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000005a388981", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000005a3b38e6" - } - }, - "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826": { - "balance": "0x2a2dd979a35cf000", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe819f024b41358d2c08e3a868a5c5dd0566078d4": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c681461027257806370a08231146102ad5780638da5cb5b146102fa57806395d89b411461034f578063a9059cbb146103dd578063dd62ed3e14610437578063f2fde38b146104a3575b600080fd5b34156100ca57600080fd5b6100d26104dc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610515565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba61069c565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106a2565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610952565b6040518082815260200191505060405180910390f35b341561027d57600080fd5b6102936004808035906020019091905050610957565b604051808215151515815260200191505060405180910390f35b34156102b857600080fd5b6102e4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610abe565b6040518082815260200191505060405180910390f35b341561030557600080fd5b61030d610b07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561035a57600080fd5b610362610b2d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a2578082015181840152602081019050610387565b50505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e857600080fd5b61041d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b66565b604051808215151515815260200191505060405180910390f35b341561044257600080fd5b61048d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d01565b6040518082815260200191505060405180910390f35b34156104ae57600080fd5b6104da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d88565b005b6040805190810160405280600b81526020017f416c6c436f6465436f696e00000000000000000000000000000000000000000081525081565b6000808214806105a157506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156105ac57600080fd5b81600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061077683600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061080b83600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108618382610e7d90919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b600681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109b557600080fd5b610a0782600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a5f82600054610e7d90919063ffffffff16565b60008190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600481526020017f414c4c430000000000000000000000000000000000000000000000000000000081525081565b6000610bba82600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610c4f82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610de457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515610e5c5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000808284019050838110151515610e7357fe5b8091505092915050565b6000828211151515610e8b57fe5b8183039050929150505600a165627a7a7230582059f3ea3df0b054e9ab711f37969684ba83fe38f255ffe2c8d850d951121c51100029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3956606365", - "extraData": "0x566961425443", - "gasLimit": "5418523", - "hash": "0x6f37eb930a25da673ea1bb80fd9e32ddac19cdf7cd4bb2eac62cc13598624077", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0x10971cde68c587c750c23b8589ae868ce82c2c646636b97e7d9856470c5297c7", - "nonce": "0x810f923ff4b450a1", - "number": "2295103", - "stateRoot": "0xff403612573d76dfdaf4fea2429b77dbe9764021ae0e38dc8ac79a3cf551179e", - "timestamp": "1513681246", - "totalDifficulty": "7162347056825919" - }, - "input": "0xf86d808504e3b292008307dfa69433056b5dcac09a9b4becad0e1dcf92c19bd0af76880e92596fd62900008029a0e5f27bb66431f7081bb7f1f242003056d7f3f35414c352cd3d1848b52716dac2a07d0be78980edb0bd2a0678fc53aa90ea9558ce346b0d947967216918ac74ccea", - "result": { - "calls": [ - { - "error": "invalid opcode: INVALID", - "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "gas": "0x75fe3", - "gasUsed": "0x75fe3", - "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4", - "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4", - "type": "CALL", - "value": "0x0" - } - ], - "error": "execution reverted", - "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826", - "gas": "0x7dfa6", - "gasUsed": "0x7c1c8", - "input": "0x", - "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "type": "CALL", - "value": "0xe92596fd6290000" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.md b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.md deleted file mode 100644 index 2700578bd..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/inner_throw_outer_revert.md +++ /dev/null @@ -1,19 +0,0 @@ -This test tests out the trace generated by the deployment of this contract: - -```solidity -contract Revertor { - function run() public pure { - require(2 > 3, "This called failed"); - } -} - -contract Contract { - constructor() { - Revertor r = new Revertor(); - r.run(); - } -} -``` - -The trace should show a revert, with the revert reason for both the top-call as well -as the inner call. diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json deleted file mode 100644 index 333bdd038..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/oog.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "context": { - "difficulty": "3699098917", - "gasLimit": "5258985", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294631", - "timestamp": "1513675366" - }, - "genesis": { - "alloc": { - "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", - "nonce": "1", - "storage": { - "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" - } - }, - "0x94194bc2aaf494501d7880b61274a169f6502a54": { - "balance": "0xea8c39a876d19888d", - "code": "0x", - "nonce": "265", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3699098917", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5263953", - "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", - "nonce": "0xd1bdb150f6fd170e", - "number": "2294630", - "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", - "timestamp": "1513675347", - "totalDifficulty": "7160543502214733" - }, - "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", - "result": { - "error": "out of gas", - "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", - "gas": "0xca1d", - "gasUsed": "0xca1d", - "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", - "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json deleted file mode 100644 index 3207a298a..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "context": { - "difficulty": "3665057456", - "gasLimit": "5232723", - "miner": "0xf4d8e706cfb25c0decbbdd4d2e2cc10c66376a3f", - "number": "2294501", - "timestamp": "1513673601" - }, - "genesis": { - "alloc": { - "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9": { - "balance": "0x2a3fc32bcc019283", - "code": "0x", - "nonce": "10", - "storage": {} - }, - "0xabbcd5b340c80b5f1c0545c04c987b87310296ae": { - "balance": "0x0", - "code": "0x606060405236156100755763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632d0335ab811461007a578063548db174146100ab5780637f649783146100fc578063b092145e1461014d578063c3f44c0a14610186578063c47cf5de14610203575b600080fd5b341561008557600080fd5b610099600160a060020a0360043516610270565b60405190815260200160405180910390f35b34156100b657600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061028f95505050505050565b005b341561010757600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061029e95505050505050565b005b341561015857600080fd5b610172600160a060020a03600435811690602435166102ad565b604051901515815260200160405180910390f35b341561019157600080fd5b6100fa6004803560ff1690602480359160443591606435600160a060020a0316919060a49060843590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965050509235600160a060020a031692506102cd915050565b005b341561020e57600080fd5b61025460046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061056a95505050505050565b604051600160a060020a03909116815260200160405180910390f35b600160a060020a0381166000908152602081905260409020545b919050565b61029a816000610594565b5b50565b61029a816001610594565b5b50565b600160209081526000928352604080842090915290825290205460ff1681565b60008080600160a060020a038416158061030d5750600160a060020a038085166000908152600160209081526040808320339094168352929052205460ff165b151561031857600080fd5b6103218561056a565b600160a060020a038116600090815260208190526040808220549295507f19000000000000000000000000000000000000000000000000000000000000009230918891908b908b90517fff000000000000000000000000000000000000000000000000000000000000008089168252871660018201526c01000000000000000000000000600160a060020a038088168202600284015286811682026016840152602a8301869052841602604a820152605e810182805190602001908083835b6020831061040057805182525b601f1990920191602091820191016103e0565b6001836020036101000a0380198251168184511617909252505050919091019850604097505050505050505051809103902091506001828a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561049957600080fd5b5050602060405103519050600160a060020a03838116908216146104bc57600080fd5b600160a060020a0380841660009081526020819052604090819020805460010190559087169086905180828051906020019080838360005b8381101561050d5780820151818401525b6020016104f4565b50505050905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008661646e5a03f1915050151561055e57600080fd5b5b505050505050505050565b600060248251101561057e5750600061028a565b600160a060020a0360248301511690505b919050565b60005b825181101561060157600160a060020a033316600090815260016020526040812083918584815181106105c657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff19169115159190911790555b600101610597565b5b5050505600a165627a7a723058200027e8b695e9d2dea9f3629519022a69f3a1d23055ce86406e686ea54f31ee9c0029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3672229776", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5227619", - "hash": "0xa07b3d6c6bf63f5f981016db9f2d1d93033833f2c17e8bf7209e85f1faf08076", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x806e151ce2817be922e93e8d5921fa0f0d0fd213d6b2b9a3fa17458e74a163d0", - "nonce": "0xbc5d43adc2c30c7d", - "number": "2294500", - "stateRoot": "0xca645b335888352ef9d8b1ef083e9019648180b259026572e3139717270de97d", - "timestamp": "1513673552", - "totalDifficulty": "7160066586979149" - }, - "input": "0xf9018b0a8505d21dba00832dc6c094abbcd5b340c80b5f1c0545c04c987b87310296ae80b9012473b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0fd659d76a4edbd2a823e324c93f78ad6803b30ff4a9c8bce71ba82798975c70ca06571eecc0b765688ec6c78942c5ee8b585e00988c0141b518287e9be919bc48a", - "result": { - "error": "execution reverted", - "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9", - "gas": "0x2dc6c0", - "gasUsed": "0x719b", - "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", - "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json deleted file mode 100644 index f02e5c686..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/revert_reason.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "context": { - "difficulty": "2", - "gasLimit": "8000000", - "miner": "0x0000000000000000000000000000000000000000", - "number": "3212651", - "timestamp": "1597246515" - }, - "genesis": { - "alloc": { - "0xf58833cf0c791881b494eb79d461e08a1f043f52": { - "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063609ff1bd11610078578063609ff1bd146101af5780639e7b8d61146101cd578063a3ec138d14610211578063e2ba53f0146102ae576100a5565b80630121b93f146100aa578063013cf08b146100d85780632e4176cf146101215780635c19a95c1461016b575b600080fd5b6100d6600480360360208110156100c057600080fd5b81019080803590602001909291905050506102cc565b005b610104600480360360208110156100ee57600080fd5b8101908080359060200190929190505050610469565b604051808381526020018281526020019250505060405180910390f35b61012961049a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ad6004803603602081101561018157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bf565b005b6101b76108db565b6040518082815260200191505060405180910390f35b61020f600480360360208110156101e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610952565b005b6102536004803603602081101561022757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b53565b60405180858152602001841515151581526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390f35b6102b6610bb0565b6040518082815260200191505060405180910390f35b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154141561038a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f486173206e6f20726967687420746f20766f746500000000000000000000000081525060200191505060405180910390fd5b8060010160009054906101000a900460ff161561040f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f416c726561647920766f7465642e00000000000000000000000000000000000081525060200191505060405180910390fd5b60018160010160006101000a81548160ff02191690831515021790555081816002018190555080600001546002838154811061044757fe5b9060005260206000209060020201600101600082825401925050819055505050565b6002818154811061047657fe5b90600052602060002090600202016000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff1615610587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f596f7520616c726561647920766f7465642e000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e000081525060200191505060405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107cc57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f466f756e64206c6f6f7020696e2064656c65676174696f6e2e0000000000000081525060200191505060405180910390fd5b61062a565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156108bf578160000154600282600201548154811061089c57fe5b9060005260206000209060020201600101600082825401925050819055506108d6565b816000015481600001600082825401925050819055505b505050565b6000806000905060008090505b60028054905081101561094d57816002828154811061090357fe5b9060005260206000209060020201600101541115610940576002818154811061092857fe5b90600052602060002090600202016001015491508092505b80806001019150506108e8565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180610bde6028913960400191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff1615610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f54686520766f74657220616c726561647920766f7465642e000000000000000081525060200191505060405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414610b0957600080fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555050565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16908060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154905084565b60006002610bbc6108db565b81548110610bc657fe5b90600052602060002090600202016000015490509056fe4f6e6c79206368616972706572736f6e2063616e206769766520726967687420746f20766f74652ea26469706673582212201d282819f8f06fed792100d60a8b08809b081a34a1ecd225e83a4b41122165ed64736f6c63430006060033", - "nonce": "1", - "storage": { - "0x6200beec95762de01ce05f2a0e58ce3299dbb53c68c9f3254a242121223cdf58": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1": { - "balance": "0x57af9d6b3df812900", - "code": "0x", - "nonce": "6", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "IstanbulBlock": 1561651, - "chainId": 5, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf888068449504f80832dc6c094f58833cf0c791881b494eb79d461e08a1f043f5280a45c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf12da0264664db3e71fae1dbdaf2f53954be149ad3b7ba8a5054b4d89c70febfacc8b1a0212e8398757963f419681839ae8c5a54b411e252473c82d93dda68405ca63294", - "result": { - "error": "execution reverted", - "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "gas": "0x2dc6c0", - "gasUsed": "0x5940", - "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52", - "type": "CALL", - "value": "0x0", - "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000", - "revertReason": "Self-delegation is disallowed." - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json deleted file mode 100644 index 620df1d61..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/selfdestruct.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x61deadff", - "nonce": "1", - "storage": {} - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "calls": [ - { - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "gas": "0x0", - "gasUsed": "0x0", - "input": "0x", - "to": "0x000000000000000000000000000000000000dead", - "type": "SELFDESTRUCT", - "value": "0x4d87094125a369d9bd5" - } - ], - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "gasUsed": "0x6fcb", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json deleted file mode 100644 index 6c7d01de1..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "calls": [ - { - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "gas": "0x6d05", - "gasUsed": "0x0", - "input": "0x", - "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "type": "CALL", - "value": "0x6f05b59d3b20000" - } - ], - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "gasUsed": "0x9751", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple_onlytop.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple_onlytop.json deleted file mode 100644 index affb4ab03..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/simple_onlytop.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "tracerConfig": { - "onlyTopCall": true - }, - "result": { - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "gasUsed": "0x9751", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json deleted file mode 100644 index 499b449a6..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer/throw.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "context": { - "difficulty": "117009631", - "gasLimit": "4712388", - "miner": "0x294e5d6c39a36ce38af1dca70c1060f78dee8070", - "number": "25009", - "timestamp": "1479891666" - }, - "genesis": { - "alloc": { - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ecd70668f5d854a", - "code": "0x", - "nonce": "1638", - "storage": {} - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000061a9", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117066792", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0xe23e8d4562a1045b70cbc99fefb20c101a8f0fc8559a80d65fea8896e2f1d46e", - "miner": "0x71842f946b98800fe6feb49f0ae4e253259031c9", - "mixHash": "0x0aada9d6e93dd4db0d09c0488dc0a048fca2ccdc1f3fc7b83ba2a8d393a3a4ff", - "nonce": "0x70849d5838dee2e9", - "number": "25008", - "stateRoot": "0x1e01d2161794768c5b917069e73d86e8dca80cd7f3168c0597de420ab93a3b7b", - "timestamp": "1479891641", - "totalDifficulty": "1896347038589" - }, - "input": "0xf88b8206668504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb8000000000000000000000000000000000000000000000027fad02094277c000029a0692a3b4e7b2842f8dd7832e712c21e09f451f416c8976d5b8d02e8c0c2b4bea9a07645e90fc421b63dd755767fd93d3c03b4ec0c4d8fafa059558d08cf11d59750", - "result": { - "error": "invalid jump destination", - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "gasUsed": "0x3d090", - "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json deleted file mode 100644 index 617f52a14..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/big_slow.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "genesis": { - "difficulty": "50486697699375", - "extraData": "0xd783010406844765746887676f312e362e32856c696e7578", - "gasLimit": "4788482", - "hash": "0xf6bbc5bbe34d5c93fd5b4712cd498d1026b8b0f586efefe7fe30231ed6b8a1a5", - "miner": "0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1", - "mixHash": "0xabca93555584c0463ee5c212251dd002bb3a93a157e06614276f93de53d4fdb8", - "nonce": "0xa64136fcb9c2d4ca", - "number": "1719576", - "stateRoot": "0xab5eec2177a92d633e282936af66c46e24cfa8f2fdc2b8155f33885f483d06f3", - "timestamp": "1466150166", - "totalDifficulty": "28295412423546970038", - "alloc": { - "0xf8bda96b67036ee48107f2a0695ea673479dda56": { - "balance": "0x1529e844f9ecdeec", - "nonce": "33", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 1, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 3000000, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 1150000, - "byzantiumBlock": 8772000, - "constantinopleBlock": 9573000, - "petersburgBlock": 10500839, - "istanbulBlock": 10500839 - } - }, - "context": { - "number": "1719577", - "difficulty": "50486697732143", - "timestamp": "1466150178", - "gasLimit": "4788484", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" - }, - "input": "0xf874218504a817c800832318608080a35b620186a05a131560135760016020526000565b600080601f600039601f565b6000f31ba0575fa000a1f06659a7b6d3c7877601519a4997f04293f0dfa0eee6d8cd840c77a04c52ce50719ee2ff7a0c5753f4ee69c0340666f582dbb5148845a354ca726e4a", - "result": [ - { - "action": { - "from": "0xf8bda96b67036ee48107f2a0695ea673479dda56", - "gas": "0x231860", - "init": "0x5b620186a05a131560135760016020526000565b600080601f600039601f565b6000f3", - "value": "0x0" - }, - "blockNumber": 1719577, - "result": { - "address": "0xb2e6a2546c45889427757171ab05b8b438525b42", - "code": "0x", - "gasUsed": "0x219202" - }, - "subtraces": 0, - "traceAddress": [], - "type": "create" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json deleted file mode 100644 index c796804a4..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "genesis": { - "difficulty": "4671584", - "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", - "gasLimit": "9435026", - "hash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "mixHash": "0x3a44525624571c31344ba57780f7664098fe7cbeafe532bcdee76a23fc474ba0", - "nonce": "0x6dca647c00c72bbf", - "number": "1555278", - "stateRoot": "0x5f56d8323ee384b0c8d1de49d63e150e17283eea813483698362bc0ec9e0242a", - "timestamp": "1590795319", - "totalDifficulty": "2242614315030", - "alloc": { - "0x0000000000000000000000000000000000000004": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x62436e941792f02a5fb1", - "nonce": "265356", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555279", - "difficulty": "4669303", - "timestamp": "1590795340", - "gasLimit": "9444238", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf86f83040c8c843b9aca0083019f7880809b60206000600060006013600462030d40f26002556000516000550081a2a086ad228c89ad9664287b12a5602a635a803506904f4ce39795990ac4f945cd57a025b30ea8042d773f6c5b13d7cc1b3979f9f10ee674410b6a2112ce840d0302dc", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x19f78", - "init": "0x60206000600060006013600462030d40f260025560005160005500" - }, - "result": { - "gasUsed": "0xf3bc", - "code": "0x", - "address": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224" - }, - "traceAddress": [], - "subtraces": 0, - "transactionPosition": 74, - "transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4", - "blockNumber": 1555279, - "blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46", - "time": "209.346µs" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json deleted file mode 100644 index fb29e4966..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_oog.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "genesis": { - "difficulty": "4671584", - "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", - "gasLimit": "9425823", - "hash": "0x27dd7d052dbc8a29cc5b9487e1e41d842e7a643fcaea4964caa22b834964acaf", - "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", - "mixHash": "0xb4a050624f5d147fdf02857cbfd55da3ddc1451743acc5c163861584589c3034", - "nonce": "0x3c255875b17e0573", - "number": "1555277", - "stateRoot": "0x6290d79215a2eebc25d5e456b35876c6d78ffc1ea47bdd70e375ebb3cf325620", - "timestamp": "1590795308", - "totalDifficulty": "2242609643446", - "alloc": { - "0x0000000000000000000000000000000000000001": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x624329308610ab365fb1", - "nonce": "265194", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555278", - "difficulty": "4671584", - "timestamp": "1590795319", - "gasLimit": "9435026", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf8ee83040bea843b9aca008301a7588080b8997f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a6080510660005560005432146001550081a1a05b9a162d84bfe84faa7c176e21c26c0083645d4dd0d566547b7be2c2da0b4259a05b37ff12a4c27634cb0da6008d9b69726d415ff4694f9bc38c7806eb1fb60ae9", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x1a758", - "init": "0x7f18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c600052601c6020527f73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f6040527feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549606052602060806080600060006001610bb7f260025560a060020a60805106600055600054321460015500" - }, - "result": { - "gasUsed": "0xf3e9", - "code": "0x", - "address": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 141, - "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", - "blockNumber": 1555278, - "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b", - "time": "300.9µs" - }, - { - "type": "call", - "action": { - "from": "0x568c19ecb14b87e4aec29b4d2d700a3ad3fd0613", - "to": "0x0000000000000000000000000000000000000001", - "value": "0x0", - "gas": "0xbb7", - "input": "0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - "callType": "callcode" - }, - "error": "out of gas", - "traceAddress": [ - 0 - ], - "subtraces": 0, - "transactionPosition": 141, - "transactionHash": "0x1592cbda0d928b8d18eed98857942b91ade32d088e55b8bf63418917cb0231f1", - "blockNumber": 1555278, - "blockHash": "0x755bd54de4b2f5a7a589a10d69888b4ead48a6311d5d69f2f69ca85ec35fbe0b" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json deleted file mode 100644 index 3c1e370f9..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "genesis": { - "difficulty": "4683014", - "extraData": "0x537465762d63676574682d76312e31312e34", - "gasLimit": "9435044", - "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95", - "miner": "0x415aa6292d1db797a467b22139704956c030e62f", - "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575", - "nonce": "0x314fc90dee5e39a2", - "number": "1555274", - "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5", - "timestamp": "1590795228", - "totalDifficulty": "2242595605834", - "alloc": { - "0x0000000000000000000000000000000000000009": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x6242e3ccf48e66425fb1", - "nonce": "264981", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555275", - "difficulty": "4683014", - "timestamp": "1590795244", - "gasLimit": "9444256", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf87a83040b15843b9aca008301a0348080a636600060003760406103e8366000600060095af26001556103e851600255610408516003550081a1a0dd883fbbb489b640dadc8c1bf151767155228d0a1321f687f070f35f14374b05a02dd0ccb16a8de39bc8ee61381bbbbb54f0ab18422afd7b03c6163da1f5023934", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x1a034", - "init": "0x36600060003760406103e8366000600060095af26001556103e8516002556104085160035500" - }, - "error": "out of gas", - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 117, - "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", - "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "332.877µs" - }, - { - "type": "call", - "action": { - "from": "0x8832ef498070145c3a5b30f47fbca71fd7b1de9f", - "to": "0x0000000000000000000000000000000000000009", - "value": "0x0", - "gas": "0xc897", - "input": "0x", - "callType": "callcode" - }, - "error": "invalid input length", - "traceAddress": [ - 0 - ], - "subtraces": 0, - "transactionPosition": 117, - "transactionHash": "0x7fe4dec901e1a62c1a1d96b8267bb9ff9dc1f75def43aa45b998743455eff8f9", - "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json deleted file mode 100644 index 11bc4eae0..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/create.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "context": { - "difficulty": "3755480783", - "gasLimit": "5401723", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294702", - "timestamp": "1513676146" - }, - "genesis": { - "alloc": { - "0x13e4acefe6a6700604929946e70e6443e4e73447": { - "balance": "0xcf3e0938579f000", - "code": "0x", - "nonce": "9", - "storage": {} - }, - "0x7dc9c9730689ff0b0fd506c67db815f12d90a448": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3757315409", - "extraData": "0x566961425443", - "gasLimit": "5406414", - "hash": "0xae107f592eebdd9ff8d6ba00363676096e6afb0e1007a7d3d0af88173077378d", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0xc927aa05a38bc3de864e95c33b3ae559d3f39c4ccd51cef6f113f9c50ba0caf1", - "nonce": "0x93363bbd2c95f410", - "number": "2294701", - "stateRoot": "0x6b6737d5bde8058990483e915866bd1578014baeff57bd5e4ed228a2bfad635c", - "timestamp": "1513676127", - "totalDifficulty": "7160808139332585" - }, - "input": "0xf907ef098504e3b29200830897be8080b9079c606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a1129a01060f46676a5dff6f407f0f51eb6f37f5c8c54e238c70221e18e65fc29d3ea65a0557b01c50ff4ffaac8ed6e5d31237a4ecbac843ab1bfe8bb0165a0060df7c54f", - "result": [ - { - "action": { - "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", - "gas": "0x897be", - "init": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11", - "value": "0x0" - }, - "blockNumber": 2294702, - "result": { - "address": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448", - "code": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029", - "gasUsed": "0x897be" - }, - "subtraces": 0, - "traceAddress": [], - "type": "create" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json deleted file mode 100644 index 375a16361..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/deep_calls.json +++ /dev/null @@ -1,635 +0,0 @@ -{ - "context": { - "difficulty": "117066904", - "gasLimit": "4712384", - "miner": "0x1977c248e1014cc103929dd7f154199c916e39ec", - "number": "25001", - "timestamp": "1479891545" - }, - "genesis": { - "alloc": { - "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a600035046302d05d3f811461008a5780630accce061461009c5780631ab9075a146100c757806331ed274614610102578063645a3b7214610133578063772fdae314610155578063a7f4377914610180578063ae5f80801461019e578063c9bded21146101ea578063f905c15a14610231575b61023a610002565b61023c600054600160a060020a031681565b61023a600435602435604435606435608435600254600160a060020a03166000141561024657610002565b61023a600435600254600160a060020a03166000148015906100f8575060025433600160a060020a03908116911614155b156102f457610002565b61023a60043560243560443560643560843560a43560c435600254600160a060020a03166000141561031657610002565b61023a600435602435600254600160a060020a0316600014156103d057610002565b61023a600435602435604435606435608435600254600160a060020a03166000141561046157610002565b61023a60025433600160a060020a0390811691161461051657610002565b61023a6004356024356044356060828152600160a060020a0382169060ff8516907fa6c2f0913db6f79ff0a4365762c61718973b3413d6e40382e704782a9a5099f690602090a3505050565b61023a600435602435600160a060020a038116606090815260ff8316907fee6348a7ec70f74e3d6cba55a53e9f9110d180d7698e9117fc466ae29a43e34790602090a25050565b61023c60035481565b005b6060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061029d57610002565b60408051858152602081018390528151600160a060020a03858116939087169260ff8a16927f5a690ecd0cb15c1c1fd6b6f8a32df0d4f56cb41a54fea7e94020f013595de796929181900390910190a45050505050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061036d57610002565b6040805186815260208101869052808201859052606081018490529051600160a060020a03831691889160ff8b16917fd65d9ddafbad8824e2bbd6f56cc9f4ac27ba60737035c10a321ea2f681c94d47919081900360800190a450505050505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061042757610002565b60408051828152905183917fa9c6cbc4bd352a6940479f6d802a1001550581858b310d7f68f7bea51218cda6919081900360200190a25050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104b857610002565b80600160a060020a031684600160a060020a03168660ff167f69bdaf789251e1d3a0151259c0c715315496a7404bce9fd0b714674685c2cab78686604051808381526020018281526020019250505060405180910390a45050505050565b600254600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x2cccf5e0538493c235d1c5ef6580f77d99e91396": { - "balance": "0x0", - "code": "0x606060405236156100775760e060020a600035046302d05d3f811461007f57806313bc6d4b146100915780633688a877146100b95780635188f9961461012f5780637eadc976146101545780638ad79680146101d3578063a43e04d814610238578063a7f437791461025e578063e16c7d981461027c575b61029f610002565b6102a1600054600160a060020a031681565b6102be600435600160a060020a03811660009081526002602052604090205460ff165b919050565b6102d26004356040805160208181018352600080835284815260038252835190849020805460026001821615610100026000190190911604601f8101849004840283018401909552848252929390929183018282801561037d5780601f106103525761010080835404028352916020019161037d565b61029f6004356024356000805433600160a060020a039081169116146104a957610002565b61034060043560008181526001602090815260408083205481517ff905c15a0000000000000000000000000000000000000000000000000000000081529151600160a060020a03909116928392839263f905c15a92600483810193919291829003018189876161da5a03f1156100025750506040515195945050505050565b60408051602060248035600481810135601f810185900485028601850190965285855261029f9581359591946044949293909201918190840183828082843750949650505050505050600054600160a060020a0390811633909116146104f657610002565b61029f6004355b600080548190600160a060020a0390811633909116146105a457610002565b61029f60005433600160a060020a0390811691161461072957610002565b6102a1600435600081815260016020526040902054600160a060020a03166100b4565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b820191906000526020600020905b81548152906001019060200180831161036057829003601f168201915b505050505090506100b4565b506000828152600160208181526040808420805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a038581168086526002909352818520805460ff191690941790935580517f1ab9075a0000000000000000000000000000000000000000000000000000000081523090931660048401525184939192631ab9075a926024828101939192829003018183876161da5a03f11561000257505060408051602081018690528082019290925243606083015260808083526003908301527f414444000000000000000000000000000000000000000000000000000000000060a0830152517f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d39181900360c00190a15b505050565b600083815260016020526040902054600160a060020a03838116911614156104d0576104a4565b600083815260016020526040812054600160a060020a031614610389576103898361023f565b600082815260036020908152604082208054845182855293839020919360026001831615610100026000190190921691909104601f90810184900483019391929186019083901061056a57805160ff19168380011785555b5061059a9291505b808211156105a05760008155600101610556565b8280016001018555821561054e579182015b8281111561054e57825182600050559160200191906001019061057c565b50505050565b5090565b600083815260016020526040812054600160a060020a031614156105c757610002565b50506000818152600160205260408082205481517fa7f437790000000000000000000000000000000000000000000000000000000081529151600160a060020a0391909116928392839263a7f4377992600483810193919291829003018183876161da5a03f11561000257505050600160005060008460001916815260200190815260200160002060006101000a815490600160a060020a0302191690556002600050600083600160a060020a0316815260200190815260200160002060006101000a81549060ff02191690557f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d383834360405180806020018560001916815260200184600160a060020a03168152602001838152602001828103825260038152602001807f44454c000000000000000000000000000000000000000000000000000000000081526020015060200194505050505060405180910390a1505050565b600054600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0684ac65a9fa32414dda56996f4183597d695987fdb82b145d722743891a6fe8": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "0x1cd76f78169a420d99346e3501dd3e541622c38a226f9b63e01cfebc69879dc7": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "0x8e54a4494fe5da016bfc01363f4f6cdc91013bb5434bd2a4a3359f13a23afa2f": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "0x94edf7f600ba56655fd65fca1f1424334ce369326c1dc3e53151dcd1ad06bc13": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xbbee47108b275f55f98482c6800f6372165e88b0330d3f5dae6419df4734366c": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "0xd38c0c4e84de118cfdcc775130155d83b8bbaaf23dc7f3c83a626b10473213bd": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xfb3aa5c655c2ec9d40609401f88d505d1da61afaa550e36ef5da0509ada257ba": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" - } - }, - "0x3e9286eafa2db8101246c2131c09b49080d00690": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063056d4470146100e957806316c66cc61461010c5780631ab9075a146101935780633ae1005c146101ce57806358541662146101fe5780635ed61af014610231578063644e3b791461025457806384dbac3b146102db578063949ae479146102fd5780639859387b14610321578063a7f4377914610340578063ab03fc261461035e578063e8161b7814610385578063e964d4e114610395578063f905c15a146103a5578063f92eb774146103ae575b6103be610002565b6103c0600054600160a060020a031681565b6103be6004356002546000908190600160a060020a031681141561040357610002565b6103dd60043560006108365b6040805160025460e360020a631c2d8fb30282527f636f6e747261637464620000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435600254600160a060020a03166000148015906101c4575060025433600160a060020a03908116911614155b1561088d57610002565b6103be600435602435604435606435600254600090819081908190600160a060020a03168114156108af57610002565b6103c0600435602435604435606435608435600254600090819081908190600160a060020a03168114156110e857610002565b6103be6004356002546000908190600160a060020a03168114156115ec57610002565b6103c06004356000611b635b6040805160025460e360020a631c2d8fb30282527f6d61726b6574646200000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435602435600254600160a060020a031660001415611bb557610002565b6103be600435602435600254600090600160a060020a0316811415611d2e57610002565b6103be600435600254600160a060020a031660001415611fc657610002565b6103be60025433600160a060020a0390811691161461207e57610002565b6103be600435602435604435600254600090600160a060020a031681141561208c57610002565b6103dd60043560006124b8610260565b6103c0600435600061250a610118565b6103f160035481565b6103f16004356000612561610260565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061046557610002565b8291506104e55b6040805160025460e360020a631c2d8fb30282527f63706f6f6c00000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f115610002575050604051519150505b90565b600160a060020a031663b2206e6d83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fb2206e6d0000000000000000000000000000000000000000000000000000000082526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f11561000257505060405151915061059b90506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f115610002575050506107355b6040805160025460e360020a631c2d8fb30282527f6c6f676d6772000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b50826120ee5b6040805160025460e360020a631c2d8fb30282527f6163636f756e7463746c0000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316630accce06600684600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150866040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050505050565b600160a060020a03166316c66cc6836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519150505b919050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061091157610002565b87935061091c610260565b600160a060020a031663bdbdb08685600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fbdbdb0860000000000000000000000000000000000000000000000000000000082526004820152602481018a905290516044808301935060209282900301816000876161da5a03f1156100025750506040515193506109ca90506106ba565b600160a060020a03166381982a7a8885876040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610a3661046c565b600160a060020a03166308636bdb85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517f08636bdb000000000000000000000000000000000000000000000000000000008252600482015260248101889052604481019290925251606482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919450600160a060020a03871692506314baa1b6916024828101926000929190829003018183876161da5a03f11561000257505050610b3561046c565b600160a060020a0316630a3b6ede85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038d16602482015290516044808301935060209282900301816000876161da5a03f115610002575050604051519150610bd590506106ba565b600160a060020a031663d5b205ce87838b6040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610c41610118565b600160a060020a031663988db79c888a6040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050610ca5610260565b600160a060020a031663f4f2821b896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610d6f5b6040805160025460e360020a631c2d8fb30282527f747261646564620000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316635f539d69896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610dc2610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928e9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610ec5610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928d9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610fc8610639565b600160a060020a031663645a3b7285600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151905061101e610260565b600160a060020a031663f92eb77488600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f115610002575050505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061114a57610002565b604051600254600160a060020a0316908a908a908a908a908a90611579806125b38339018087600160a060020a0316815260200186600160a060020a03168152602001856000191681526020018481526020018381526020018281526020019650505050505050604051809103906000f092506111c5610118565b600160a060020a031663b9858a288a856040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611229610260565b600160a060020a0316635188f99689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611288610260565b600160a060020a031663bdbdb08689896040518360e060020a0281526004018083600019168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750506040515192506112e590506106ba565b600160a060020a03166346d88e7d8a858a6040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506000604051808303816000876161da5a03f115610002575050506113516106ba565b600160a060020a03166381982a7a8a84866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050506113bd61046c565b600160a060020a0316632b58469689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f1156100025750505061141c61046c565b600160a060020a03166308636bdb8984866040518460e060020a028152600401808460001916815260200183815260200182600160a060020a0316815260200193505050506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919350600160a060020a03861692506314baa1b6916024828101926000929190829003018183876161da5a03f115610002575050506114d3610639565b6040805160e160020a630566670302815260016004820152602481018b9052600160a060020a0386811660448301528c811660648301526000608483018190529251931692630accce069260a480840193919291829003018183876161da5a03f11561000257505050611544610639565b600160a060020a031663645a3b728961155b610260565b600160a060020a031663f92eb7748c6040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448084019360009350829003018183876161da5a03f1156100025750939a9950505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061164e57610002565b82915061165961046c565b600160a060020a0316630a3b6ede83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f1156100025750506040515191506116f990506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f1156100025750505061179b6106ba565b600160a060020a031663d653078983600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517ff1ff78a0000000000000000000000000000000000000000000000000000000008252915191929163f1ff78a09160048181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f1156100025750505061189f610260565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506118f2610118565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050611945610639565b600160a060020a0316630accce06600484600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da44689181870191602091908190038801816000876161da5a03f115610002575050506040518051906020015060006040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050611a48610639565b600160a060020a031663645a3b7283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611a9e610260565b600160a060020a031663f92eb77486600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b600160a060020a03166381738c59836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611c1757610002565b611c1f610260565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060405151159050611c7457610002565b611c7c610260565b600160a060020a0316632243118a836040518260e060020a02815260040180826000191681526020019150506000604051808303816000876161da5a03f11561000257505050611cca610639565b600160a060020a031663ae5f8080600184846040518460e060020a028152600401808481526020018360001916815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611d9057610002565b5081611d9a610260565b600160a060020a031663581d5d6084846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505050611df5610639565b600160a060020a0316630accce06600283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630566670302825260048201949094526024810193909352600160a060020a038816604484015260006064840181905260848401819052905160a4808501949293509091829003018183876161da5a03f11561000257505050611eab610639565b600160a060020a031663645a3b7282600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611f01610260565b600160a060020a031663f92eb77485600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061202857610002565b612030610118565b600160a060020a0316639859387b826040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505050565b600254600160a060020a0316ff5b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f11561000257505060405151151590506106b457610002565b600160a060020a031663d65307898383600160a060020a031663f1ff78a06040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fd6530789000000000000000000000000000000000000000000000000000000008252600160a060020a039485166004830152602482015292891660448401525160648381019360009350829003018183876161da5a03f115610002575050506121a5610118565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506121f8610cf4565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505061224b610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d028252915191928a9290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f1156100025750505080600160a060020a031663ea71b02d6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a031660001490506124b25761239f610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fea71b02d000000000000000000000000000000000000000000000000000000008252915191928a92909163ea71b02d91600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f115610002575050505b50505050565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663213fe2b7836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663f92eb774836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f115610002575050604051519150610888905056606060405260405160c08061157983396101206040819052825160805160a051935160e0516101005160008054600160a060020a03199081163317909155600180546005805484168817905560048a90556006869055600b8590556008849055909116861760a060020a60ff02191690554360038190556002558686526101408390526101608190529396929594919390929091600160a060020a033016917f76885d242fb71c6f74a7e717416e42eff4d96faf54f6de75c6a0a6bbd8890c6b91a230600160a060020a03167fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff600b600050546040518082815260200191505060405180910390a250505050505061145e8061011b6000396000f3606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "16", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ef436dcbda6cd4a", - "code": "0x", - "nonce": "1634", - "storage": {} - }, - "0x7986bad81f4cbd9317f5a46861437dae58d69113": { - "balance": "0x0", - "code": "0x6060604052361561008d5760e060020a600035046302d05d3f811461009557806316c66cc6146100a75780631ab9075a146100d7578063213fe2b7146101125780639859387b1461013f578063988db79c1461015e578063a7f4377914610180578063b9858a281461019e578063c8e40fbf146101c0578063f4f2821b146101e8578063f905c15a14610209575b610212610002565b610214600054600160a060020a031681565b600160a060020a0360043581811660009081526005602052604081205461023193168114610257575060016101e3565b610212600435600254600160a060020a0316600014801590610108575060025433600160a060020a03908116911614155b1561025f57610002565b610214600435600160a060020a03811660009081526004602052604081205460ff16151561027557610002565b610212600435600254600160a060020a03166000141561029b57610002565b610212600435602435600254600160a060020a03166000141561050457610002565b61021260025433600160a060020a0390811691161461056757610002565b610212600435602435600254600160a060020a03166000141561057557610002565b610231600435600160a060020a03811660009081526004602052604090205460ff165b919050565b610212600435600254600090600160a060020a031681141561072057610002565b61024560035481565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060006101e3565b60028054600160a060020a031916821790555b50565b50600160a060020a038181166000908152600460205260409020546101009004166101e3565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506102fe57610002565b600160a060020a03811660009081526004602052604090205460ff161515610272576040516104028061092e833901809050604051809103906000f06004600050600083600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600083600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555050565b600160a060020a03821660009081526004602052604090205460ff1615156104725760405161040280610d30833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a03811660009081526006602052604090208054600160a060020a031916831790555b5050565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506103b957610002565b600254600160a060020a0316ff5b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506105d857610002565b600160a060020a03821660009081526004602052604090205460ff1615156106915760405161040280611132833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a031660009081526005602052604090208054600160a060020a0319169091179055565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f115610002575050604051511515905061078357610002565b50600160a060020a0381811660009081526005602090815260408083205490931680835260049091529190205460ff161561080f576040600081812054825160e260020a632e72bafd028152600160a060020a03868116600483015293516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260056020526040812054909116146108545760406000908120600160a060020a0384169091528054600160a060020a03191690555b50600160a060020a0381811660009081526006602090815260408083205490931680835260049091529190205460ff16156108e657600160a060020a038181166000908152604080518183205460e260020a632e72bafd028252868516600483015291516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260066020526040812054909116146105005760406000908120600160a060020a0384169091528054600160a060020a0319169055505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "7", - "storage": { - "0xffc4df2d4f3d2cffad590bed6296406ab7926ca9e74784f74a95191fa069a174": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - }, - "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f": { - "balance": "0x0", - "code": "0x606060405236156100ae5760e060020a600035046302d05d3f81146100b65780631ab9075a146100c85780632b68bb2d146101035780634cc927d7146101c557806351a34eb81461028e57806356ccb6f0146103545780635928d37f1461041d578063599efa6b146104e9578063759297bb146105b2578063771d50e11461067e578063a7f4377914610740578063f905c15a1461075e578063f92eb77414610767578063febf661214610836575b610902610002565b610904600054600160a060020a031681565b610902600435600254600160a060020a03166000148015906100f9575060025433600160a060020a03908116911614155b1561092057610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061094257610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610a0d57610002565b61090260043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ae957610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610bbc57610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610c9657610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610de057610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ebb57610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f9e57610002565b61090260025433600160a060020a0390811691161461106957610002565b61090e60035481565b61090e60043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750506040805180517ff92eb774000000000000000000000000000000000000000000000000000000008252600482018790529151919350600160a060020a038416925063f92eb774916024828101926020929190829003018188876161da5a03f11561000257505060405151949350505050565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061107757610002565b005b6060908152602090f35b60408051918252519081900360200190f35b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5ed61af000000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152925190959286169350635ed61af092602483810193919291829003018183876161da5a03f115610002575050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fab03fc2600000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015260248301899052808816604484015292519095928616935063ab03fc2692606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f949ae47900000000000000000000000000000000000000000000000000000000825233600160a060020a0390811660048401526024830188905292519095928616935063949ae47992604483810193919291829003018183876161da5a03f11561000257505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f46d88e7d000000000000000000000000000000000000000000000000000000008252600160a060020a0380891660048401523381166024840152604483018890529251909592861693506346d88e7d92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5315cdde00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a16602484015260448301889052925190959286169350635315cdde92606483810193919291829003018183876161da5a03f115610002575050604080517f5928d37f00000000000000000000000000000000000000000000000000000000815233600160a060020a03908116600483015287166024820152604481018690529051635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fe68e401c00000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015280891660248401526044830188905292519095928616935063e68e401c92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5152f381000000000000000000000000000000000000000000000000000000008252600160a060020a03808a1660048401528089166024840152604483018890523381166064840152925190959286169350635152f38192608483810193919291829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f056d447000000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015292519095928616935063056d447092602483810193919291829003018183876161da5a03f115610002575050505050565b600254600160a060020a0316ff5b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f3ae1005c00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a166024840152808916604484015260648301889052925190959286169350633ae1005c92608483810193919291829003018183876161da5a03f11561000257505050505050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000006195", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5842545553440000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" - } - }, - "0xcf00ffd997ad14939736f026006498e3f099baaf": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063031e7f5d146100e95780631ab9075a1461010b5780632243118a1461014657806327aad68a1461016557806338a699a4146101da5780635188f996146101f8578063581d5d601461021e57806381738c5914610246578063977da54014610269578063a07421ce14610288578063a7f43779146102be578063bdbdb086146102dc578063e1c7111914610303578063f4f2821b14610325578063f905c15a1461034a578063f92eb77414610353575b610387610002565b610389600054600160a060020a031681565b610387600435602435600254600160a060020a0316600014156103a857610002565b610387600435600254600160a060020a031660001480159061013c575060025433600160a060020a03908116911614155b1561042957610002565b610387600435600254600160a060020a03166000141561044b57610002565b6102ac60043560008181526004602081815260408320547f524d81d3000000000000000000000000000000000000000000000000000000006060908152610100909104600160a060020a031692839263524d81d3926064928188876161da5a03f1156100025750506040515192506103819050565b61039c60043560008181526004602052604090205460ff165b919050565b6103876004356024356002546000908190600160a060020a031681141561079457610002565b61038760043560243560025460009081908190600160a060020a031681141561080457610002565b61038960043560008181526004602052604081205460ff1615156109e357610002565b610387600435600254600160a060020a0316600014156109fb57610002565b600435600090815260096020526040902054670de0b6b3a764000090810360243502045b60408051918252519081900360200190f35b61038760025433600160a060020a03908116911614610a9257610002565b600435600090815260086020526040902054670de0b6b3a7640000602435909102046102ac565b610387600435602435600254600160a060020a031660001415610aa057610002565b61038760043560025460009081908190600160a060020a0316811415610b3657610002565b6102ac60035481565b6102ac600435600081815260076020908152604080832054600690925290912054670de0b6b3a76400000204805b50919050565b005b600160a060020a03166060908152602090f35b15156060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506103fe57610002565b60008281526004602052604090205460ff16151561041b57610002565b600860205260406000205550565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104a157610002565b604080516000838152600460205291909120805460ff1916600117905561040280610de2833901809050604051809103906000f0600460005060008360001916815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555066470de4df8200006008600050600083600019168152602001908152602001600020600050819055506703782dace9d9000060096000506000836000191681526020019081526020016000206000508190555050565b600460005060008560001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151821415905061060057838152600660209081526040808320839055600790915281208190555b81600160a060020a0316630a3b0a4f846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050600160a060020a038316808252600560209081526040808420879055805160e160020a6364a81ff102815290518694670de0b6b3a7640000949363c9503fe29360048181019492939183900301908290876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008660001916815260200190815260200160002060008282825054019250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000866000191681526020019081526020016000206000828282505401925050819055505b50505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f11561000257505060405151151590506107e957610002565b8381526004602052604081205460ff16151561056657610002565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f115610002575050604051511515905061085957610002565b849250670de0b6b3a764000083600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575060408051805160e160020a6364a81ff102825291519189028590049650600481810192602092909190829003018188876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b9391600481810192602092909190829003018189876161da5a03f115610002575050506040518051906020015002049050806006600050600085600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750604080518051855260208681528286208054989098039097557f2e94420f00000000000000000000000000000000000000000000000000000000815290518896600483810193919291829003018187876161da5a03f115610002575050604080515183526020939093525020805490910190555050505050565b60409020546101009004600160a060020a03166101f3565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610a5157610002565b60008181526004602052604090205460ff161515610a6e57610002565b6040600020805474ffffffffffffffffffffffffffffffffffffffffff1916905550565b600254600160a060020a0316ff5b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610af657610002565b60008281526004602052604090205460ff161515610b1357610002565b670de0b6b3a7640000811115610b2857610002565b600960205260406000205550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f1156100025750506040515115159050610b8b57610002565b600160a060020a038416815260056020908152604080832054808452600490925282205490935060ff161515610bc057610002565b600460005060008460001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663b9caebf4856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506005600050600085600160a060020a0316815260200190815260200160002060005060009055839050600082600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519190911115905061078e57670de0b6b3a764000081600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008560001916815260200190815260200160002060008282825054039250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000856000191681526020019081526020016000206000828282505403925050819055505050505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x3571d73f14f31a1463bd0a2f92f7fde1653d4e1ead7aedf4b0a5df02f16092ab": "0x0000000000000000000000000000000000000000000007d634e4c55188be0000", - "0x4e64fe2d1b72d95a0a31945cc6e4f4e524ac5ad56d6bd44a85ec7bc9cc0462c0": "0x000000000000000000000000000000000000000000000002b5e3af16b1880000" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117124093", - "extraData": "0xd5830105008650617269747986312e31322e31826d61", - "gasLimit": "4707788", - "hash": "0xad325e4c49145fb7a4058a68ac741cc8607a71114e23fc88083c7e881dd653e7", - "miner": "0x00714b9ac97fd6bd9325a059a70c9b9fa94ce050", - "mixHash": "0x0af918f65cb4af04b608fc1f14a849707696986a0e7049e97ef3981808bcc65f", - "nonce": "0x38dee147326a8d40", - "number": "25000", - "stateRoot": "0xc5d6bbcd46236fcdcc80b332ffaaa5476b980b01608f9708408cfef01b58bd5b", - "timestamp": "1479891517", - "totalDifficulty": "1895410389427" - }, - "input": "0xf88b8206628504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb80000000000000000000000000000000000000000000000280faf689c35ac00002aa0a7ee5b7877811bf671d121b40569462e722657044808dc1d6c4f1e4233ec145ba0417e7543d52b65738d9df419cbe40a708424f4d54b0fc145c0a64545a2bb1065", - "result": [ - { - "action": { - "callType": "call", - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 25001, - "result": { - "gasUsed": "0x1810b", - "output": "0x" - }, - "subtraces": 2, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x31217", - "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f" - }, - "subtraces": 0, - "traceAddress": [0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x30b4a", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0xedb7", - "output": "0x" - }, - "subtraces": 4, - "traceAddress": [1], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x2a68d", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690" - }, - "subtraces": 0, - "traceAddress": [1, 0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x29f35", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0xf8d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 2, - "traceAddress": [1, 1], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23ac9", - "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" - }, - "subtraces": 0, - "traceAddress": [1, 1, 0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23366", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x273", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [1, 1, 1], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x28a9e", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690" - }, - "subtraces": 0, - "traceAddress": [1, 2], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x283b9", - "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0xc51c", - "output": "0x" - }, - "subtraces": 12, - "traceAddress": [1, 3], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x21d79", - "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x24d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [1, 3, 0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x2165b", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf" - }, - "subtraces": 0, - "traceAddress": [1, 3, 1], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x20ee1", - "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x5374", - "output": "0x" - }, - "subtraces": 6, - "traceAddress": [1, 3, 2], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a8e8", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x24d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a2c6", - "input": "0xc9503fe2", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x3cb", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 1], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19b72", - "input": "0xc9503fe2", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x3cb", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 2], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19428", - "input": "0x6f265b93", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x305", - "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 3], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x18d45", - "input": "0x2e94420f", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x229", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 4], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1734e", - "input": "0x2e94420f", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x229", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 2, 5], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1b6c1", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38" - }, - "subtraces": 0, - "traceAddress": [1, 3, 3], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1af69", - "input": "0x2e94420f", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x229", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 4], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1a91d", - "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x12fa", - "output": "0x" - }, - "subtraces": 1, - "traceAddress": [1, 3, 5], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x143a5", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x24d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [1, 3, 5, 0], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x19177", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38" - }, - "subtraces": 0, - "traceAddress": [1, 3, 6], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18a22", - "input": "0x2e94420f", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x229", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 7], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18341", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x334", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf" - }, - "subtraces": 0, - "traceAddress": [1, 3, 8], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x17bec", - "input": "0x2e94420f", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x229", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 9], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1764e", - "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x45c", - "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000" - }, - "subtraces": 0, - "traceAddress": [1, 3, 10], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x16e62", - "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0xebb", - "output": "0x" - }, - "subtraces": 1, - "traceAddress": [1, 3, 11], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x108ba", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x24d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [1, 3, 11, 0], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json deleted file mode 100644 index e5a37cbfd..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "context": { - "difficulty": "31927752", - "gasLimit": "4707788", - "miner": "0x5659922ce141eedbc2733678f9806c77b4eebee8", - "number": "11495", - "timestamp": "1479735917" - }, - "genesis": { - "alloc": { - "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a60003504630a0313a981146100875780630a3b0a4f146101095780630cd40fea1461021257806329092d0e1461021f5780634cd06a5f146103295780635dbe47e8146103395780637a9e5410146103d9578063825db5f7146103e6578063a820b44d146103f3578063efa52fb31461047a575b610002565b34610002576104fc600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a26333556e849091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f415610002575050604051519150505b919050565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f21ce24d4000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926321ce24d49260448082019391829003018186803b156100025760325a03f415610002575050505b50565b3461000257610512600181565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f89489a87000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926389489a879260448082019391829003018186803b156100025760325a03f4156100025750505061020f565b3461000257610528600435610403565b34610002576104fc600435604080516000602091820181905282517f7d65837a00000000000000000000000000000000000000000000000000000000815260048101829052600160a060020a0385166024820152925190927342b02b5deeb78f34cd5ac896473b63e6c99a71a292637d65837a92604480840193829003018186803b156100025760325a03f4156100025750506040515191506101049050565b3461000257610512600c81565b3461000257610512600081565b3461000257610528600061055660005b600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263685a1f3c9091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b346100025761053a600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263f775b6b59091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b604080519115158252519081900360200190f35b005b6040805160ff9092168252519081900360200190f35b60408051918252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b90509056", - "nonce": "1", - "storage": { - "0x4d140b25abf3c71052885c66f73ce07cff141c1afabffdaf5cba04d625b7ebcc": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "0x269296dddce321a6bcbaa2f0181127593d732cba": { - "balance": "0x0", - "code": "0x606060405236156101275760e060020a60003504630cd40fea811461012c578063173825d9146101395780631849cb5a146101c7578063285791371461030f5780632a58b3301461033f5780632cb0d48a146103565780632f54bf6e1461036a578063332b9f061461039d5780633ca8b002146103c55780633df4ddf4146103d557806341c0e1b5146103f457806347799da81461040557806362a51eee1461042457806366907d13146104575780637065cb48146104825780637a9e541014610496578063825db5f7146104a3578063949d225d146104b0578063a51687df146104c7578063b4da4e37146104e6578063b4e6850b146104ff578063bd7474ca14610541578063e75623d814610541578063e9938e1114610555578063f5d241d314610643575b610002565b3461000257610682600181565b34610002576106986004356106ff335b60006001600a9054906101000a9004600160a060020a0316600160a060020a0316635dbe47e8836000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100025760325a03f1156100025750506040515191506103989050565b3461000257604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a0360043581168752600586529589902089519788018a528054808816808a52605060020a91829004600160a060020a0316978a01889052600183015463ffffffff8082169d8c018e905264010000000082048116988c01899052604060020a90910416958a018690526002830154948a01859052600390920154808916938a01849052049096169690970186905293969495949293604080516001605060020a03998a16815297891660208901529590971686860152600160a060020a03909316606086015263ffffffff9182166080860152811660a08501521660c083015260e08201929092529051908190036101000190f35b346100025761069a60043560018054600091829160ff60f060020a909104161515141561063d5761072833610376565b34610002576106ae6004546001605060020a031681565b34610002576106986004356108b333610149565b346100025761069a6004355b600160a060020a03811660009081526002602052604090205460ff1615156001145b919050565b34610002576106986001805460ff60f060020a9091041615151415610913576108ed33610376565b346100025761069a600435610149565b34610002576106ae6003546001605060020a03605060020a9091041681565b346100025761069861091533610149565b34610002576106ae6003546001605060020a0360a060020a9091041681565b346100025761069a60043560243560018054600091829160ff60f060020a909104161515141561095e5761092633610376565b34610002576106986004356001805460ff60f060020a909104161515141561072557610a8b33610376565b3461000257610698600435610aa533610149565b3461000257610682600c81565b3461000257610682600081565b34610002576106ae6003546001605060020a031681565b34610002576106ca600154600160a060020a03605060020a9091041681565b346100025761069a60015460ff60f060020a9091041681565b346100025761069a60043560243560443560643560843560a43560c43560018054600091829160ff60f060020a9091041615151415610b5857610ad233610376565b3461000257610698600435610bd633610149565b34610002576106e6600435604080516101008181018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a03808b168752600586529589902089519788018a5280548088168952600160a060020a03605060020a918290041696890196909652600181015463ffffffff8082169b8a019b909b5264010000000081048b1695890195909552604060020a90940490981691860182905260028301549086015260039091015480841696850196909652940416918101919091525b50919050565b346100025761069a60043560243560443560643560843560a43560018054600091829160ff60f060020a9091041615151415610c8e57610bfb33610376565b6040805160ff9092168252519081900360200190f35b005b604080519115158252519081900360200190f35b604080516001605060020a039092168252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b6040805163ffffffff9092168252519081900360200190f35b1561012757600160a060020a0381166000908152600260205260409020805460ff191690555b50565b1561063d57506001605060020a0380831660009081526005602052604090208054909116151561075b576000915061063d565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610817905b8051600354600090819060016001605060020a0390911611610c995760038054605060020a60f060020a0319169055610ddf565b600380546001605060020a031981166000196001605060020a03928316011782558416600090815260056020526040812080547fffff000000000000000000000000000000000000000000000000000000000000168155600181810180546bffffffffffffffffffffffff191690556002820192909255909101805473ffffffffffffffffffffffffffffffffffffffff19169055915061063d565b1561012757600180547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a8302179055610725565b1561091357600480546001605060020a031981166001605060020a039091166001011790555b565b156101275733600160a060020a0316ff5b1561095e57506001605060020a03808416600090815260056020526040902080549091161515610965576000915061095e565b600191505b5092915050565b60038101546001605060020a0384811691161415610986576001915061095e565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610a12906107e3565b61095983825b80546003546001605060020a0391821691600091161515610de55760038054605060020a60a060020a031916605060020a84021760a060020a69ffffffffffffffffffff02191660a060020a84021781558301805473ffffffffffffffffffffffffffffffffffffffff19169055610ddf565b1561072557600480546001605060020a0319168217905550565b1561012757600160a060020a0381166000908152600260205260409020805460ff19166001179055610725565b15610b5857506001605060020a038088166000908152600560205260409020805490911615610b645760009150610b58565b6004546001605060020a0390811690891610610b3057600480546001605060020a03191660018a011790555b6003805460016001605060020a03821681016001605060020a03199092169190911790915591505b50979650505050505050565b80546001605060020a0319168817605060020a60f060020a031916605060020a880217815560018101805463ffffffff1916871767ffffffff0000000019166401000000008702176bffffffff00000000000000001916604060020a860217905560028101839055610b048982610a18565b156101275760018054605060020a60f060020a031916605060020a8302179055610725565b15610c8e57506001605060020a03808816600090815260056020526040902080549091161515610c2e5760009150610c8e565b8054605060020a60f060020a031916605060020a88021781556001808201805463ffffffff1916881767ffffffff0000000019166401000000008802176bffffffff00000000000000001916604060020a87021790556002820184905591505b509695505050505050565b6003546001605060020a03848116605060020a909204161415610d095760e084015160038054605060020a928302605060020a60a060020a031990911617808255919091046001605060020a031660009081526005602052604090200180546001605060020a0319169055610ddf565b6003546001605060020a0384811660a060020a909204161415610d825760c08401516003805460a060020a92830260a060020a69ffffffffffffffffffff021990911617808255919091046001605060020a03166000908152600560205260409020018054605060020a60a060020a0319169055610ddf565b505060c082015160e08301516001605060020a0380831660009081526005602052604080822060039081018054605060020a60a060020a031916605060020a8702179055928416825290200180546001605060020a031916831790555b50505050565b6001605060020a0384161515610e6457600380546001605060020a03605060020a9182900481166000908152600560205260409020830180546001605060020a0319908116871790915583548785018054918590049093168402605060020a60a060020a03199182161790911690915582549185029116179055610ddf565b506001605060020a038381166000908152600560205260409020600390810180549185018054605060020a60a060020a0319908116605060020a94859004909516808502959095176001605060020a0319168817909155815416918402919091179055801515610ef4576003805460a060020a69ffffffffffffffffffff02191660a060020a8402179055610ddf565b6003808401546001605060020a03605060020a9091041660009081526005602052604090200180546001605060020a031916831790555050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000113204f5d64c28326fd7bd05fd4ea855302d7f2ff00000000000000000000" - } - }, - "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2": { - "balance": "0x0", - "code": "0x6504032353da7150606060405236156100695760e060020a60003504631bf7509d811461006e57806321ce24d41461008157806333556e84146100ec578063685a1f3c146101035780637d65837a1461011757806389489a8714610140578063f775b6b5146101fc575b610007565b61023460043560006100fd82600061010d565b610246600435602435600160a060020a03811660009081526020839052604081205415156102cb57826001016000508054806001018281815481835581811511610278576000838152602090206102789181019083015b808211156102d057600081556001016100d8565b610248600435602435600182015481105b92915050565b6102346004356024355b60018101906100fd565b610248600435602435600160a060020a03811660009081526020839052604090205415156100fd565b61024660043560243580600160a060020a031632600160a060020a03161415156101f857600160a060020a038116600090815260208390526040902054156101f857600160a060020a038116600090815260208390526040902054600183018054909160001901908110156100075760009182526020808320909101805473ffffffffffffffffffffffffffffffffffffffff19169055600160a060020a038316825283905260408120556002820180546000190190555b5050565b61025c60043560243560008260010160005082815481101561000757600091825260209091200154600160a060020a03169392505050565b60408051918252519081900360200190f35b005b604080519115158252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b50505060009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a0385168352908590526040909120819055600284018054600101905590505b505050565b509056", - "nonce": "1", - "storage": {} - }, - "0xa529806c67cc6486d4d62024471772f47f6fd672": { - "balance": "0x67820e39ac8fe9800", - "code": "0x", - "nonce": "68", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "31912170", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0x0855914bdc581bccdc62591fd438498386ffb59ea4d5361ed5c3702e26e2c72f", - "miner": "0x334391aa808257952a462d1475562ee2106a6c90", - "mixHash": "0x64bb70b8ca883cadb8fbbda2c70a861612407864089ed87b98e5de20acceada6", - "nonce": "0x684129f283aaef18", - "number": "11494", - "stateRoot": "0x7057f31fe3dab1d620771adad35224aae43eb70e94861208bc84c557ff5b9d10", - "timestamp": "1479735912", - "totalDifficulty": "90744064339" - }, - "input": "0xf889448504a817c800832dc6c094269296dddce321a6bcbaa2f0181127593d732cba80a47065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e29a080ed81e4c5e9971a730efab4885566e2c868cd80bd4166d0ed8c287fdf181650a069d7c49215e3d4416ad239cd09dbb71b9f04c16b33b385d14f40b618a7a65115", - "result": [ - { - "action": { - "callType": "call", - "from": "0xa529806c67cc6486d4d62024471772f47f6fd672", - "gas": "0x2dc6c0", - "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e", - "to": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "value": "0x0" - }, - "blockNumber": 11495, - "result": { - "gasUsed": "0xbd55", - "output": "0x" - }, - "subtraces": 1, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "gas": "0x2cae73", - "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0xa9d", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 1, - "traceAddress": [0], - "type": "call" - }, - { - "action": { - "callType": "delegatecall", - "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "gas": "0x2bf459", - "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2", - "value": "0x0" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x2aa", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [0, 0], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json deleted file mode 100644 index 177912420..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/delegatecall_parent_value.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "genesis": { - "number": "566098", - "hash": "0xba134562590a59291892395a29c5088899c2c64d720135dad88f7f076cf55f5f", - "nonce": "0x4b281be9594e3eb3", - "mixHash": "0xdb4ec386166d9c0dc9ba147755ecbb87af9f0a22563cbda02c799efa4e29db6e", - "stateRoot": "0xfc01993ad96a8fb8790a093cea4f505f8db1b0e1143c5f57bb1d173db0baa9e3", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "difficulty": "1926740", - "totalDifficulty": "482216286599", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "19388354", - "timestamp": "1577558314", - "alloc": { - "0x6ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0xcbd5b9b25d1c38c2aad", - "nonce": "134969", - "code": "0x", - "storage": {} - }, - "0x91765918420bcb5ad22ee0997abed04056705798": { - "balance": "0x0", - "nonce": "1", - "code": "0x366000803760206000366000736ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc60325a03f41560015760206000f3", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "566099", - "difficulty": "1927680", - "timestamp": "1577558317", - "gasLimit": "19369422", - "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" - }, - "input": "0xf87983020f3985746a52880083015f909491765918420bcb5ad22ee0997abed04056705798888ac7230489e80000884e45375a4741394181a1a04b7260723fd02830754916b3bdf1537b6a851a7ae27c7e9296cfe1fc8275ec08a049d32158988eb717d61b4503b27c7583037c067daba1eb56f4bdfafc1b0045f6", - "result": [ - { - "action": { - "callType": "call", - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "gas": "0x15f90", - "input": "0x4e45375a47413941", - "to": "0x91765918420bcb5ad22ee0997abed04056705798", - "value": "0x8ac7230489e80000" - }, - "blockHash": "0xb05cc5c8f11df2b5d53ced342ee79e2805785f04c2f40add4539f27bd349f74e", - "blockNumber": 566099, - "result": { - "gasUsed": "0x5721", - "output": "0x4e45375a47413941000000000000000000000000000000000000000000000000" - }, - "subtraces": 1, - "traceAddress": [], - "transactionHash": "0x6e26dffe2f66186f03a2c36a16a4cd9724d07622c83746f1e35f988515713d4b", - "transactionPosition": 10, - "type": "call" - }, - { - "action": { - "callType": "delegatecall", - "from": "0x91765918420bcb5ad22ee0997abed04056705798", - "gas": "0x10463", - "input": "0x4e45375a47413941", - "to": "0x6ab9dd83108698b9ca8d03af3c7eb91c0e54c3fc", - "value": "0x8ac7230489e80000" - }, - "blockHash": "0xb05cc5c8f11df2b5d53ced342ee79e2805785f04c2f40add4539f27bd349f74e", - "blockNumber": 566099, - "result": { - "gasUsed": "0x0", - "output": "0x" - }, - "subtraces": 0, - "traceAddress": [ - 0 - ], - "transactionHash": "0x6e26dffe2f66186f03a2c36a16a4cd9724d07622c83746f1e35f988515713d4b", - "transactionPosition": 10, - "type": "call" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json deleted file mode 100644 index d977dbe30..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/gas.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "genesis": { - "difficulty": "4683014", - "extraData": "0x537465762d63676574682d76312e31312e34", - "gasLimit": "9435044", - "hash": "0x3452ca5005cb73cd60dfa488a7b124251168e564491f80eb66765e79d78cfd95", - "miner": "0x415aa6292d1db797a467b22139704956c030e62f", - "mixHash": "0x6037612618507ae70c74a72bc2580253662971db959cfbc06d3f8527d4d01575", - "nonce": "0x314fc90dee5e39a2", - "number": "1555274", - "stateRoot": "0x795751f3f96a5de1fd3944ddd78cbfe4ef10491e1086be47609869a30929d0e5", - "timestamp": "1590795228", - "totalDifficulty": "2242595605834", - "alloc": { - "0x0000000000000000000000000000000000000001": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x6242e3ccf48e66425fb1", - "nonce": "264882", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555275", - "difficulty": "4683014", - "timestamp": "1590795244", - "gasLimit": "9444256", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf9011583040ab2843b9aca008301a9c88080b8c0601b565b6000555b005b630badf00d6003565b63c001f00d6003565b7319e7e376e7c213b7e7e7e46cc70a5dd086daff2a7f22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda600052601b603f537f16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f6040527f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e40060605260206080607f60006000600161fffff2156007576080511460125760095681a1a07682fc43dbe1fb13c6474f5e70e121c826dd996168d8bb1d8ca7a63470127b46a00a25b308ba417b7770899e8f98a3f0c14aa9bf7db0edacfe4e78d00dbbd3c31e", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x1a9c8", - "init": "0x601b565b6000555b005b630badf00d6003565b63c001f00d6003565b7319e7e376e7c213b7e7e7e46cc70a5dd086daff2a7f22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda600052601b603f537f16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f6040527f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e40060605260206080607f60006000600161fffff21560075760805114601257600956" - }, - "result": { - "gasUsed": "0x137e5", - "code": "0x", - "address": "0x1a05d76017ca02010533a470e05e8925a0380d8f" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 18, - "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", - "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd", - "time": "453.925µs" - }, - { - "type": "call", - "action": { - "from": "0x1a05d76017ca02010533a470e05e8925a0380d8f", - "to": "0x0000000000000000000000000000000000000001", - "value": "0x0", - "gas": "0xc8c6", - "input": "0x22ae6da6b482f9b1b19b0b897c3fd43884180a1c5ee361e1107a1bc635649dda000000000000000000000000000000000000000000000000000000000000001b16433dce375ce6dc8151d3f0a22728bc4a1d9fd6ed39dfd18b4609331937367f306964c0cf5d74f04129fdc60b54d35b596dde1bf89ad92cb4123318f4c0e4", - "callType": "callcode" - }, - "result": { - "gasUsed": "0xbb8", - "output": "0x00000000000000000000000019e7e376e7c213b7e7e7e46cc70a5dd086daff2a" - }, - "traceAddress": [0], - "subtraces": 0, - "transactionPosition": 18, - "transactionHash": "0xc1c42a325856d513523aec464811923b2e2926f54015c7ba37877064cf889803", - "blockNumber": 1555275, - "blockHash": "0x80945caaff2fc67253cbb0217d2e5a307afde943929e97d8b36e58b88cbb02fd" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json deleted file mode 100644 index 0f28c07a9..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/include_precompiled.json +++ /dev/null @@ -1,832 +0,0 @@ -{ - "genesis": { - "number": "559197", - "hash": "0x0742a2bfab0452e2c634f3685b7e49ceb065c7000609b2b73f086e01fd1dfb58", - "nonce": "0x3060ad521440e1c2", - "mixHash": "0x59e7d4ae6cc3c38d23dac3f869b21984c7ba8f38070f4116a4941d9c403b6299", - "stateRoot": "0x68418fb5cf4afa9b807dc079e8cdde0e148ac2c8afb378e675465b5bed1fbd02", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "difficulty": "1813945", - "totalDifficulty": "469107641961", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "6321166", - "timestamp": "1577471202", - "alloc": { - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0xc5e6fdae52af83f7e28", - "nonce": "77947", - "code": "0x", - "storage": {} - }, - "0x774c398d763161f55b66a646f17edda4addad2ca": { - "balance": "0xf09ef316eff819ee488", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc": { - "balance": "0x0", - "nonce": "1", - "code": "0x60006121df537c01000000000000000000000000000000000000000000000000000000006000350463b041b2858114156100d257600435604052780100000000000000000000000000000000000000000000000060606060599059016000905260038152604051816020015260008160400152809050205404606052606051151561008f57600060a052602060a0f35b604051601c604459905901600090520163e0e9a17b601c82035260605160048201526020610100602483600030602d5a03f1506101005190501460c052602060c0f35b632cce81aa81141561019957600435610120526001610120511280156100f85780610143565b78010000000000000000000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540461012051135b905015610157576000610180526020610180f35b601c604459905901600090520163e0e9a17b601c82035261012051600482015260206101c0602483600030602d5a03f1506101c05190506101a05260206101a0f35b63e0e9a17b8114156102e957600435610120526604000000000002546101e0526007610200525b610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540413156102da575b6102005160050a610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e051816020015260008160400152809050205404031215610269576000610200511361026c565b60005b1561028157600161020051036102005261020b565b7c01000000000000000000000000000000000000000000000000000000006102005160200260020a606060605990590160009052600381526101e05181602001526001816040015280905020540204546101e0526101c0565b6101e051610280526020610280f35b63cef887b08114156103e757365990590160009052366004823760043560208201016102c0526024356102e052506060601c61014c5990590160009052016390fa337d601c8203526102c0516020601f602083035101046020026020018360048401526020820360648401528060c8840152808401935050506102e051602482015233604482015281600401599059016000905260648160648460006004601cf161039057fe5b60648101925060c882015180808582606487015160006004600a8705601201f16103b657fe5b5080840193505080830360206103a08284600030602d5a03f1506103a0519050905090509050610300526020610300f35b6390fa337d81141561065f57365990590160009052366004823760043560208201016102c0526024356102e0526044356103e052505a610400526020601c608c599059016000905201632b861629601c8203526102c0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161048a57fe5b602481019250604882015180808582602487015160006004600a8705601201f16104b057fe5b5080840193505080830360206104408284600030602d5a03f15061044051905090509050905061042052610420511561065e576102c05160208103516020599059016000905260208183856000600287604801f150805190509050905061046052602059905901600090526020816020610460600060026068f1508051905060005b6020811215610552578181601f031a816105400153600181019050610532565b5050610540516101e0526102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020555a61058052700100000000000000000000000000000000660400000000000154046105a0526104006105a0516103ff02056105c0526104006105a05161040102056105e0526105c0513a12156105f6576105c05161060052610615565b6105e0513a131561060e576105e05161060052610614565b3a610600525b5b6105805161040051036106005160020202610620526106205170010000000000000000000000000000000061060051021766040000000000015561042051610640526020610640f35b5b63d467ae0381141561073257600435604052602435610660526106605134121515610725576000341315610718576c01000000000000000000000000606060605990590160009052600381526040518160200152600381604001528090502054046103e0526000600060006000346103e051611388f115156106dd57fe5b601c60405990590160009052013481526103e0517f15e746bf513b8a58e4265cc1162d7fc445da5c9b1928d7cfcde2582735d4677f602083a2505b60016106a05260206106a0f35b60006106c05260206106c0f35b63ea4971ee811415610851576004356101e0526024356102e0526044356103e052601c606459905901600090520163d467ae03601c8203526101e05160048201526604000000000001546fffffffffffffffffffffffffffffffff16602482015260206106e060448334306123555a03f1506106e051905015156107bd576000610700526020610700f35b606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166102e0511215610844576102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020556001610760526020610760f35b6000610780526020610780f35b6387def0818114156108a3576004356101e0526c01000000000000000000000000606060605990590160009052600381526101e0518160200152600381604001528090502054046107a05260206107a0f35b630aece23c8114156108f4576004356101e052606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166107e05260206107e0f35b63fa14df6b811415610926576604000000000001546fffffffffffffffffffffffffffffffff16610820526020610820f35b63b8c48f8c811415610b1b576004356101e0526024356108405260443561086052600066040000000000035414151561096a576000610880526020610880f3610976565b60016604000000000003555b6101e051660400000000000255606060605990590160009052600381526101e05181602001526000816040015280905020546108a0526108a0610840518060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a600783015350506108a051606060605990590160009052600381526101e0518160200152600081604001528090502055606060605990590160009052600381526101e051816020015260008160400152809050205461094052601061094001610860518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061094051606060605990590160009052600381526101e051816020015260008160400152809050205560016109e05260206109e0f35b632b86162981141561179457365990590160009052366004823760043560208201016102c0525060483560005b6020811215610b68578181601f031a81610a600153600181019050610b48565b5050610a6051610a00526102c05160208103516020599059016000905260208183856000600287604801f1508051905090509050610a8052602059905901600090526020816020610a80600060026068f1508051905060005b6020811215610be1578181601f031a81610b600153600181019050610bc1565b5050610b60516101e05270010000000000000000000000000000000070010000000000000000000000000000000060606060599059016000905260038152610a005181602001526000816040015280905020540204610b8052610b80511515610c8b57601c602059905901600090520161272e6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610bc0526020610bc0f35b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204610be0526000610be051141515610d2e57601c60205990590160009052016127386101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610c20526020610c20f35b608c35610c40526301000000610c405160031a0262010000610c405160021a02610100610c405160011a02610c405160001a010101610c60526301000000610c605104610ca05262ffffff610c605116610cc0526003610ca051036101000a610cc05102610c805260006101e0511315610db057610c80516101e05112610db3565b60005b1561174d57780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a00518160200152600081604001528090502054046001016101205260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610d405250610d405160081a610d405160091a61010002610d4051600a1a6201000002610d4051600b1a630100000002010101610d005260006107e0610120510614158015610e7e5780610e8b565b6001660400000000000054145b905015610f0257610d0051610c6051141515610eae576000610d00511415610eb1565b60005b15610efd57601c602059905901600090520161271a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610da0526020610da0f35b6111b4565b6301000000610d005104610de05262ffffff610d005116610e00526003610de051036101000a610e005102610dc05260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610e605250610e605160041a610e605160051a61010002610e605160061a6201000002610e605160071a630100000002010101610e2052601c604459905901600090520163e0e9a17b601c8203526107e0610120510360048201526020610ec0602483600030602d5a03f150610ec0519050610ea05260806080599059016000905260038152610ea05181602001526002816040015260008160600152809050206002810154610f205250610f205160041a610f205160051a61010002610f205160061a6201000002610f205160071a630100000002010101610ee052610ee051610e20510362049d408112156110595762049d4090505b6249d40081131561106b576249d40090505b62127500610dc0518202047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156110ba577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505b600860076000835b80156110d9576002810490506001820191506110c2565b5080905001046000600382131515611103578160030360080260020a62ffffff841602905061111a565b6003820360080260020a8304905062ffffff811690505b6280000081161561113357610100810490506001820191505b6301000000820281179050905090509050610f6052610f6051610c6051141515611164576000610f60511415611167565b60005b156111b357601c60205990590160009052016127246101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000611040526020611040f35b5b6101e0516101e0516101e05166040000000000005455606060605990590160009052600381526101e0518160200152600081604001528090502054611060526008611060016604000000000000548060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061106051606060605990590160009052600381526101e0518160200152600081604001528090502055600166040000000000005401660400000000000055606060605990590160009052600381526101e0518160200152600081604001528090502054611100526111006001780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205404018060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061110051606060605990590160009052600381526101e051816020015260008160400152809050205560006111c05278010000000000000000000000000000000000000000000000006801000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205402046111e0526111c06111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350506001611260525b6008611260511215611515576112605160050a611280526001611280517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540407141561148757611260516004026111c0016111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a60038301535050611505565b611260516004026111c0017c01000000000000000000000000000000000000000000000000000000006112605160200260020a60606060599059016000905260038152610a00518160200152600181604001528090502054020480601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350505b60016112605101611260526113ec565b6111c051606060605990590160009052600381526101e05181602001526001816040015280905020555050608060805990590160009052600381526101e051816020015260028160400152600081606001528090502060005b600281121561159057806020026102c05101518282015560018101905061156e565b700100000000000000000000000000000000600003816020026102c051015116828201555050610c80517bffff0000000000000000000000000000000000000000000000000000056113e0526113e051610b805101610be052606060605990590160009052600381526101e051816020015260008160400152809050205461140052601061140001610be0518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061140051606060605990590160009052600381526101e0518160200152600081604001528090502055660400000000000354610be051121515611703576101e051660400000000000255610be0516604000000000003555b601c6020599059016000905201610120516101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a350610120516114a05260206114a0f35b601c602059905901600090520161276a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a35060006114c05260206114c0f35b630f5995ce8114156119a157365990590160009052366004823760043560208201016114e05260243561150052604435602082010161152052606435604052506114e05160208103516020599059016000905260208183856000600287604801f150805190509050905061156052602059905901600090526020816020611560600060026068f1508051905060005b6020811215611843578181601f031a816116400153600181019050611823565b50506116405161154052604060206114e051035114156118a457601c6020599059016000905201614e52611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a3506000611660526020611660f35b6080601c6101ac59905901600090520163bd136cb3601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff161192357fe5b6084810192506101488201518080858260c487015160006004600a8705601201f161194a57fe5b508084019350508083036020611680828434306123555a03f15061168051905090509050905061042052600161042051141561199357611540516116a05260206116a0f36119a0565b60006116c05260206116c0f35b5b63bd136cb3811415611d8c573659905901600090523660048237600435611540526024356115005260443560208201016115205260643560405250601c606459905901600090520163d467ae03601c82035260405160048201526060606059905901600090526003815260405181602001526003816040015280905020546bffffffffffffffffffffffff166024820152602061170060448334306123555a03f1506117005190501515611a9757601c6020599059016000905201614e2a611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e2a611720526020611720f35b601c6044599059016000905201633d73b705601c82035260405160048201526020611740602483600030602d5a03f15061174051905015611b1a57601c6020599059016000905201614e34611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e34611760526020611760f35b601c604459905901600090520163b041b285601c82035260405160048201526020611780602483600030602d5a03f1506117805190501515611b9e57601c6020599059016000905201614e3e611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e3e6117a05260206117a0f35b6060601c61014c59905901600090520163b7129afb601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360a4840152806101088401528084019350505081600401599059016000905260648160648460006004601cf1611c1557fe5b6064810192506101088201518080858260a487015160006004600a8705601201f1611c3c57fe5b5080840193505080830360206117e08284600030602d5a03f1506117e05190509050905090506117c0526080608059905901600090526003815260405181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006002820154046401000000006001830154020160005b6020811215611ce4578181601f031a816118a00153600181019050611cc4565b50506118a051905061180052611800516117c0511415611d4457601c60205990590160009052016001611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a35060016118c05260206118c0f35b601c6020599059016000905201614e48611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e486118e05260206118e0f35b63318a3fee81141561205657365990590160009052366004823760043560208201016114e0526024356115005260443560208201016115205260643560405260843561190052506080601c6101ac599059016000905201630f5995ce601c8203526114e0516020601f6020830351010460200260200183600484015260208203608484015280610108840152808401935050506115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff1611e7b57fe5b60848101925061010882015180808582608487015160006004600a8705601201f1611ea257fe5b508084019350506101488201518080858260c487015160006004600a8705601201f1611eca57fe5b508084019350508083036020611920828434306123555a03f15061192051905090509050905061154052600061154051141515612010576040601c60ec599059016000905201631c0b6367601c8203526114e0516020601f6020830351010460200260200183600484015260208203604484015280608884015280840193505050611540516024820152816004015990590160009052604481604484600060046018f1611f7357fe5b604481019250608882015180808582604487015160006004600a8705601201f1611f9957fe5b5080840193505080830360206119608284600061190051602d5a03f15061196051905090509050905061194052601c602059905901600090520161194051611540517f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061194051611980526020611980f35b601c602059905901600090520161753a60007f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061753a6119a05260206119a0f35b6309dd0e81811415612076576604000000000002546119c05260206119c0f35b63023948728114156120d2577801000000000000000000000000000000000000000000000000606060605990590160009052600381526604000000000002548160200152600081604001528090502054046119e05260206119e0f35b632c181929811415612139577001000000000000000000000000000000007001000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540204611a20526020611a20f35b637ca823d58114156122af576604000000000002546101e052700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611a60526000611260525b600a61126051121561224c57608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612230578181601f031a81611b200153600181019050612210565b5050611b205190506101e05260016112605101611260526121a8565b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611b4052611b4051611a605103611b80526020611b80f35b63b7129afb81141561246a57365990590160009052366004823760043561154052602435611500526044356020820101611520525061154051611ba0526020611520510351611bc0526000611260525b611bc05161126051121561245b5761126051602002611520510151611be05260026115005107611c00526001611c0051141561234a57611be051611c2052611ba051611c4052612368565b6000611c0051141561236757611ba051611c2052611be051611c40525b5b60405990590160009052611c205160005b6020811215612399578181601f031a81611ca00153600181019050612379565b5050611ca0518152611c405160005b60208112156123c8578181601f031a81611d2001536001810190506123a8565b5050611d2051602082015260205990590160009052602081604084600060026088f15080519050611d4052602059905901600090526020816020611d40600060026068f1508051905060005b6020811215612434578181601f031a81611de00153600181019050612414565b5050611de0519050611ba052600261150051056115005260016112605101611260526122ff565b611ba051611e00526020611e00f35b633d73b70581141561255b576004356040526604000000000002546101e0526000611260525b600661126051121561254e576101e05160405114156124b6576001611e20526020611e20f35b608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612532578181601f031a81611ec00153600181019050612512565b5050611ec05190506101e0526001611260510161126052612490565b6000611ee0526020611ee0f35b631f794436811415612737576004356101e052601c606459905901600090520163d467ae03601c8203526101e0516004820152606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff1660248201526020611f2060448334306123555a03f150611f20519050151561265657601c602059905901600090520160006101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350602159905901600090526001815260006020820152602081019050602060408203526020601f6020830351604001010460200260408203f3505b601c602059905901600090520160016101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350608060805990590160009052600381526101e0518160200152600281604001526000816060015280905020607059905901600090526050815260208101905060005b60028112156126f05780830154816020028301526001810190506126d1565b70010000000000000000000000000000000060000381840154168160200283015281905090509050602060408203526020601f6020830351604001010460200260408203f3505b6313f955e18114156128ca573659905901600090523660048237600435602082010161204052602435612060525060506120805260006120a052612080516120c0526000611260525b612060516112605112156128bb576120a051806120c051038080602001599059016000905281815260208101905090508180828286612040510160006004600a8705601201f16127cc57fe5b50809050905090506120e0526020601c608c599059016000905201632b861629601c8203526120e0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161284157fe5b602481019250604882015180808582602487015160006004600a8705601201f161286757fe5b5080840193505080830360206121a08284600030602d5a03f1506121a051905090509050905061042052612080516120a051016120a052612080516120c051016120c0526001611260510161126052612780565b610420516121c05260206121c0f35b50", - "storage": { - "0x292b7a8d467a95cffd303c7edd99875892cdb3eaee87e5ca29057dc88a09ffbd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4d2fcf8ac901ad7dcf5b1c3979801430d9979c87157230ae066a0276984c6ac7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xdf951a5d1d9283b06d4f1de58542f1e1e310d8d17aada46586ddb9598bc42894": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x9c8d09d387f3ba5dd4733e24c63e4d549864a7cd57a1bdf1fdd831a2a0184815": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4ab3b783bb170e11b0932a5ce8f5f343f67058b3925da271001a75ae498bd655": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x0000000000000000000000000000000000000004": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x0000000000000000000000000000000000000002": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "559198", - "difficulty": "1814830", - "timestamp": "1577471205", - "gasLimit": "6327338", - "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" - }, - "tracerConfig": { - "includePrecompiles": true - }, - "input": "0xf9026f8301307b85746a52880083124f80946cc68eb482a757c690dd151d2bd5e774ada38bdc80b9020413f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e00000000000000000000000000000000081a1a01c9e9d742c8e69daba2a026ccafdde618f2e44c96db281c2209c22f183ad03a2a049a61d267d22226896d4c065525819c238784c439dc2afa7d17fce76595730d1", - "result": [ - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "gas": "0x124f80", - "input": "0x13f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1c6ff", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 20, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1a", - "input": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x18", - "output": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67" - }, - "subtraces": 0, - "traceAddress": [ - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x15", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x15", - "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" - }, - "subtraces": 0, - "traceAddress": [ - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1e", - "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1b", - "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 2 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x114243", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 2, - "traceAddress": [ - 3 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x98", - "input": "0x04000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x60", - "output": "0xb099ea4048830027371dc31039920ae4fd19a641a7cbe57c198edd19d60f158a" - }, - "subtraces": 0, - "traceAddress": [ - 3, - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x68", - "input": "0xb099ea4048830027371dc31039920ae4fd19a641a7cbe57c198edd19d60f158a", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x48", - "output": "0x5b53875b0f1381589859adcf938980f4a8fb0af4c88450070000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 3, - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1a", - "input": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x18", - "output": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7" - }, - "subtraces": 0, - "traceAddress": [ - 4 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x15", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x15", - "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" - }, - "subtraces": 0, - "traceAddress": [ - 5 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1e", - "input": "0x0000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 6 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x110d3b", - "input": "0x2b86162900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 2, - "traceAddress": [ - 7 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x98", - "input": "0x040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae7", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x60", - "output": "0xa0c6939b58a99b0d940f4435ab7db7d54d6b7786e68e00d9ff3890d69f95565d" - }, - "subtraces": 0, - "traceAddress": [ - 7, - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x68", - "input": "0xa0c6939b58a99b0d940f4435ab7db7d54d6b7786e68e00d9ff3890d69f95565d", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x48", - "output": "0xabbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 7, - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1a", - "input": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x18", - "output": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303" - }, - "subtraces": 0, - "traceAddress": [ - 8 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x15", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x15", - "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" - }, - "subtraces": 0, - "traceAddress": [ - 9 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1e", - "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1b", - "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 10 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x10d833", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 2, - "traceAddress": [ - 11 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x98", - "input": "0x04000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc303", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x60", - "output": "0x6defff59ba277fa4511f8675ca98ca7d9c237c7433684490cf1ce09a9249e32f" - }, - "subtraces": 0, - "traceAddress": [ - 11, - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x68", - "input": "0x6defff59ba277fa4511f8675ca98ca7d9c237c7433684490cf1ce09a9249e32f", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x48", - "output": "0xe93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 11, - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1a", - "input": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x18", - "output": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de" - }, - "subtraces": 0, - "traceAddress": [ - 12 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x15", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x15", - "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" - }, - "subtraces": 0, - "traceAddress": [ - 13 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1e", - "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1b", - "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 14 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x10a328", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 2, - "traceAddress": [ - 15 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x98", - "input": "0x04000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x60", - "output": "0x996652142ffecd9cc272f376ca0e8228871a903772996289f847a6dbe2ce2698" - }, - "subtraces": 0, - "traceAddress": [ - 15, - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x68", - "input": "0x996652142ffecd9cc272f376ca0e8228871a903772996289f847a6dbe2ce2698", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x48", - "output": "0xf2e372a0b5b837116eee8f968840393d85975a15313468070000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 15, - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1a", - "input": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x18", - "output": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0" - }, - "subtraces": 0, - "traceAddress": [ - 16 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x15", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x15", - "output": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020" - }, - "subtraces": 0, - "traceAddress": [ - 17 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x1e", - "input": "0x000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000004", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1b", - "output": "0x000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 18 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x106e1d", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 2, - "traceAddress": [ - 19 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x98", - "input": "0x04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e0", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x60", - "output": "0xe57cf1c1d6132b9cfd9e90f54f907c038b47941b2a7f3800783af26e852ec116" - }, - "subtraces": 0, - "traceAddress": [ - 19, - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x68", - "input": "0xe57cf1c1d6132b9cfd9e90f54f907c038b47941b2a7f3800783af26e852ec116", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x0000000000000000000000000000000000000002", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x48", - "output": "0x8d5b6fafc6216500f9ef1ab16b30a59df9122d7de0f4910a0000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 19, - 1 - ], - "type": "call" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json deleted file mode 100644 index 6c4ce1806..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_create_oog_outer_throw.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "context": { - "difficulty": "3451177886", - "gasLimit": "4709286", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2290744", - "timestamp": "1513616439" - }, - "genesis": { - "alloc": { - "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a": { - "balance": "0x0", - "code": "0x606060405263ffffffff60e060020a6000350416633b91f50681146100505780635bb47808146100715780635f51fca01461008c578063bc7647a9146100ad578063f1bd0d7a146100c8575b610000565b346100005761006f600160a060020a03600435811690602435166100e9565b005b346100005761006f600160a060020a0360043516610152565b005b346100005761006f600160a060020a036004358116906024351661019c565b005b346100005761006f600160a060020a03600435166101fa565b005b346100005761006f600160a060020a0360043581169060243516610db8565b005b600160a060020a038083166000908152602081905260408120549091908116903316811461011657610000565b839150600160a060020a038316151561012d573392505b6101378284610e2e565b6101418284610db8565b61014a826101fa565b5b5b50505050565b600154600160a060020a03908116903316811461016e57610000565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b5b5050565b600254600160a060020a0390811690331681146101b857610000565b600160a060020a038381166000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19169184169190911790555b5b505050565b6040805160e260020a631a481fc102815260016024820181905260026044830152606482015262093a8060848201819052600060a4830181905260c06004840152601e60c48401527f736574456e7469747953746174757328616464726573732c75696e743829000060e484015292519091600160a060020a038516916369207f049161010480820192879290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526000602482018190526001604483015260606004830152602360648301527f626567696e506f6c6c28616464726573732c75696e7436342c626f6f6c2c626f60848301527f6f6c29000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f61646453746f636b28616464726573732c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f697373756553746f636b2875696e74382c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602160648301527f6772616e7453746f636b2875696e74382c75696e743235362c61646472657373608483015260f860020a60290260a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f115610000575050604080517f010555b8000000000000000000000000000000000000000000000000000000008152600160a060020a03338116602483015260006044830181905260606004840152603c60648401527f6772616e7456657374656453746f636b2875696e74382c75696e743235362c6160848401527f6464726573732c75696e7436342c75696e7436342c75696e743634290000000060a48401529251908716935063010555b89260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601260c48201527f626567696e53616c65286164647265737329000000000000000000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601a60648301527f7472616e7366657253616c6546756e64732875696e743235362900000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152602d60c48201527f7365744163636f756e74696e6753657474696e67732875696e743235362c756960e48201527f6e7436342c75696e7432353629000000000000000000000000000000000000006101048201529051600160a060020a03861692506369207f04916101248082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152603460648301527f637265617465526563757272696e6752657761726428616464726573732c756960848301527f6e743235362c75696e7436342c737472696e672900000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601b60648301527f72656d6f7665526563757272696e675265776172642875696e7429000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602360648301527f697373756552657761726428616464726573732c75696e743235362c7374726960848301527f6e6729000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f61737369676e53746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f72656d6f766553746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260026024808301919091526003604483015260006064830181905267ffffffffffffffff8616608484015260ff871660a484015260c0600484015260c48301919091527f7365744164647265737342796c617728737472696e672c616464726573732c6260e48301527f6f6f6c29000000000000000000000000000000000000000000000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152602160c48301527f73657453746174757342796c617728737472696e672c75696e74382c626f6f6c60e483015260f860020a6029026101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152603860c48301527f736574566f74696e6742796c617728737472696e672c75696e743235362c756960e48301527f6e743235362c626f6f6c2c75696e7436342c75696e74382900000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f115610000575050505b505050565b604080517f225553a4000000000000000000000000000000000000000000000000000000008152600160a060020a0383811660048301526002602483015291519184169163225553a49160448082019260009290919082900301818387803b156100005760325a03f115610000575050505b5050565b600082604051611fd280610f488339600160a060020a03909216910190815260405190819003602001906000f0801561000057905082600160a060020a03166308b027418260016040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b156100005760325a03f115610000575050604080517fa14e3ee300000000000000000000000000000000000000000000000000000000815260006004820181905260016024830152600160a060020a0386811660448401529251928716935063a14e3ee39260648084019382900301818387803b156100005760325a03f115610000575050505b5050505600606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029a165627a7a723058200e78a5f7e0f91739035d0fbf5eca02f79377210b722f63431f29a22e2880b3bd0029", - "nonce": "789", - "storage": { - "0xfe9ec0542a1c009be8b1f3acf43af97100ffff42eb736850fb038fa1151ad4d9": "0x000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8" - } - }, - "0x5cb4a6b902fcb21588c86c3517e797b07cdaadb9": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe4a13bc304682a903e9472f469c33801dd18d9e8": { - "balance": "0x33c763c929f62c4f", - "code": "0x", - "nonce": "14", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3451177886", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4713874", - "hash": "0x5d52a672417cd1269bf4f7095e25dcbf837747bba908cd5ef809dc1bd06144b5", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x01a12845ed546b94a038a7a03e8df8d7952024ed41ccb3db7a7ade4abc290ce1", - "nonce": "0x28c446f1cb9748c1", - "number": "2290743", - "stateRoot": "0x4898aceede76739daef76448a367d10015a2c022c9e7909b99a10fbf6fb16708", - "timestamp": "1513616414", - "totalDifficulty": "7146523769022564" - }, - "input": "0xf8aa0e8509502f9000830493e0941d3ddf7caf024f253487e18bc4a15b1a360c170a80b8443b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e829a0524564944fa419f5c189b5074044f89210c6d6b2d77ee8f7f12a927d59b636dfa0015b28986807a424b18b186ee6642d76739df36cad802d20e8c00e79a61d7281", - "result": [ - { - "action": { - "callType": "call", - "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8", - "gas": "0x493e0", - "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8", - "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "value": "0x0" - }, - "blockNumber": 2290744, - "error": "invalid jump destination", - "result": {}, - "subtraces": 1, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "gas": "0x39ff0", - "init": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", - "value": "0x0" - }, - "blockNumber": 0, - "error": "contract creation code storage out of gas", - "result": {}, - "subtraces": 0, - "traceAddress": [0], - "type": "create" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json deleted file mode 100644 index 4de08f2cc..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "genesis": { - "difficulty": "117067574", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712380", - "hash": "0xe05db05eeb3f288041ecb10a787df121c0ed69499355716e17c307de313a4486", - "miner": "0x0c062b329265c965deef1eede55183b3acb8f611", - "mixHash": "0xb669ae39118a53d2c65fd3b1e1d3850dd3f8c6842030698ed846a2762d68b61d", - "nonce": "0x2b469722b8e28c45", - "number": "24973", - "stateRoot": "0x532a5c3f75453a696428db078e32ae283c85cb97e4d8560dbdf022adac6df369", - "timestamp": "1479891145", - "totalDifficulty": "1892250259406", - "alloc": { - "0x6c06b16512b332e6cd8293a2974872674716ce18": { - "balance": "0x0", - "nonce": "1", - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d146036575b6000565b34600057604e60048080359060200190919050506050565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050505b5056", - "storage": {} - }, - "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31": { - "balance": "0x229ebbb36c3e0f20", - "nonce": "3", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 3, - "homesteadBlock": 0, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "byzantiumBlock": 1700000, - "constantinopleBlock": 4230000, - "petersburgBlock": 4939394, - "istanbulBlock": 6485846, - "muirGlacierBlock": 7117117, - "ethash": {} - } - }, - "context": { - "number": "24974", - "difficulty": "117067574", - "timestamp": "1479891162", - "gasLimit": "4712388", - "miner": "0xc822ef32e6d26e170b70cf761e204c1806265914" - }, - "input": "0xf889038504a81557008301f97e946c06b16512b332e6cd8293a2974872674716ce1880a42e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b1600002aa0e2a6558040c5d72bc59f2fb62a38993a314c849cd22fb393018d2c5af3112095a01bdb6d7ba32263ccc2ecc880d38c49d9f0c5a72d8b7908e3122b31356d349745", - "result": [ - { - "action": { - "callType": "call", - "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31", - "gas": "0x1f97e", - "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000", - "to": "0x6c06b16512b332e6cd8293a2974872674716ce18", - "value": "0x0" - }, - "blockNumber": 24974, - "result": { - "gasUsed": "0x72de", - "output": "0x" - }, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json deleted file mode 100644 index 70442fdb9..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_precompiled_wrong_gas.json +++ /dev/null @@ -1,219 +0,0 @@ -{ - "genesis": { - "number": "559197", - "hash": "0x0742a2bfab0452e2c634f3685b7e49ceb065c7000609b2b73f086e01fd1dfb58", - "nonce": "0x3060ad521440e1c2", - "mixHash": "0x59e7d4ae6cc3c38d23dac3f869b21984c7ba8f38070f4116a4941d9c403b6299", - "stateRoot": "0x68418fb5cf4afa9b807dc079e8cdde0e148ac2c8afb378e675465b5bed1fbd02", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "difficulty": "1813945", - "totalDifficulty": "469107641961", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "6321166", - "timestamp": "1577471202", - "alloc": { - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0xc5e6fdae52af83f7e28", - "nonce": "77947", - "code": "0x", - "storage": {} - }, - "0x774c398d763161f55b66a646f17edda4addad2ca": { - "balance": "0xf09ef316eff819ee488", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc": { - "balance": "0x0", - "nonce": "1", - "code": "0x60006121df537c01000000000000000000000000000000000000000000000000000000006000350463b041b2858114156100d257600435604052780100000000000000000000000000000000000000000000000060606060599059016000905260038152604051816020015260008160400152809050205404606052606051151561008f57600060a052602060a0f35b604051601c604459905901600090520163e0e9a17b601c82035260605160048201526020610100602483600030602d5a03f1506101005190501460c052602060c0f35b632cce81aa81141561019957600435610120526001610120511280156100f85780610143565b78010000000000000000000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540461012051135b905015610157576000610180526020610180f35b601c604459905901600090520163e0e9a17b601c82035261012051600482015260206101c0602483600030602d5a03f1506101c05190506101a05260206101a0f35b63e0e9a17b8114156102e957600435610120526604000000000002546101e0526007610200525b610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540413156102da575b6102005160050a610120517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e051816020015260008160400152809050205404031215610269576000610200511361026c565b60005b1561028157600161020051036102005261020b565b7c01000000000000000000000000000000000000000000000000000000006102005160200260020a606060605990590160009052600381526101e05181602001526001816040015280905020540204546101e0526101c0565b6101e051610280526020610280f35b63cef887b08114156103e757365990590160009052366004823760043560208201016102c0526024356102e052506060601c61014c5990590160009052016390fa337d601c8203526102c0516020601f602083035101046020026020018360048401526020820360648401528060c8840152808401935050506102e051602482015233604482015281600401599059016000905260648160648460006004601cf161039057fe5b60648101925060c882015180808582606487015160006004600a8705601201f16103b657fe5b5080840193505080830360206103a08284600030602d5a03f1506103a0519050905090509050610300526020610300f35b6390fa337d81141561065f57365990590160009052366004823760043560208201016102c0526024356102e0526044356103e052505a610400526020601c608c599059016000905201632b861629601c8203526102c0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161048a57fe5b602481019250604882015180808582602487015160006004600a8705601201f16104b057fe5b5080840193505080830360206104408284600030602d5a03f15061044051905090509050905061042052610420511561065e576102c05160208103516020599059016000905260208183856000600287604801f150805190509050905061046052602059905901600090526020816020610460600060026068f1508051905060005b6020811215610552578181601f031a816105400153600181019050610532565b5050610540516101e0526102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020555a61058052700100000000000000000000000000000000660400000000000154046105a0526104006105a0516103ff02056105c0526104006105a05161040102056105e0526105c0513a12156105f6576105c05161060052610615565b6105e0513a131561060e576105e05161060052610614565b3a610600525b5b6105805161040051036106005160020202610620526106205170010000000000000000000000000000000061060051021766040000000000015561042051610640526020610640f35b5b63d467ae0381141561073257600435604052602435610660526106605134121515610725576000341315610718576c01000000000000000000000000606060605990590160009052600381526040518160200152600381604001528090502054046103e0526000600060006000346103e051611388f115156106dd57fe5b601c60405990590160009052013481526103e0517f15e746bf513b8a58e4265cc1162d7fc445da5c9b1928d7cfcde2582735d4677f602083a2505b60016106a05260206106a0f35b60006106c05260206106c0f35b63ea4971ee811415610851576004356101e0526024356102e0526044356103e052601c606459905901600090520163d467ae03601c8203526101e05160048201526604000000000001546fffffffffffffffffffffffffffffffff16602482015260206106e060448334306123555a03f1506106e051905015156107bd576000610700526020610700f35b606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166102e0511215610844576102e0516c010000000000000000000000006103e0510217606060605990590160009052600381526101e05181602001526003816040015280905020556001610760526020610760f35b6000610780526020610780f35b6387def0818114156108a3576004356101e0526c01000000000000000000000000606060605990590160009052600381526101e0518160200152600381604001528090502054046107a05260206107a0f35b630aece23c8114156108f4576004356101e052606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff166107e05260206107e0f35b63fa14df6b811415610926576604000000000001546fffffffffffffffffffffffffffffffff16610820526020610820f35b63b8c48f8c811415610b1b576004356101e0526024356108405260443561086052600066040000000000035414151561096a576000610880526020610880f3610976565b60016604000000000003555b6101e051660400000000000255606060605990590160009052600381526101e05181602001526000816040015280905020546108a0526108a0610840518060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a600783015350506108a051606060605990590160009052600381526101e0518160200152600081604001528090502055606060605990590160009052600381526101e051816020015260008160400152809050205461094052601061094001610860518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061094051606060605990590160009052600381526101e051816020015260008160400152809050205560016109e05260206109e0f35b632b86162981141561179457365990590160009052366004823760043560208201016102c0525060483560005b6020811215610b68578181601f031a81610a600153600181019050610b48565b5050610a6051610a00526102c05160208103516020599059016000905260208183856000600287604801f1508051905090509050610a8052602059905901600090526020816020610a80600060026068f1508051905060005b6020811215610be1578181601f031a81610b600153600181019050610bc1565b5050610b60516101e05270010000000000000000000000000000000070010000000000000000000000000000000060606060599059016000905260038152610a005181602001526000816040015280905020540204610b8052610b80511515610c8b57601c602059905901600090520161272e6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610bc0526020610bc0f35b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204610be0526000610be051141515610d2e57601c60205990590160009052016127386101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610c20526020610c20f35b608c35610c40526301000000610c405160031a0262010000610c405160021a02610100610c405160011a02610c405160001a010101610c60526301000000610c605104610ca05262ffffff610c605116610cc0526003610ca051036101000a610cc05102610c805260006101e0511315610db057610c80516101e05112610db3565b60005b1561174d57780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a00518160200152600081604001528090502054046001016101205260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610d405250610d405160081a610d405160091a61010002610d4051600a1a6201000002610d4051600b1a630100000002010101610d005260006107e0610120510614158015610e7e5780610e8b565b6001660400000000000054145b905015610f0257610d0051610c6051141515610eae576000610d00511415610eb1565b60005b15610efd57601c602059905901600090520161271a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000610da0526020610da0f35b6111b4565b6301000000610d005104610de05262ffffff610d005116610e00526003610de051036101000a610e005102610dc05260806080599059016000905260038152610a005181602001526002816040015260008160600152809050206002810154610e605250610e605160041a610e605160051a61010002610e605160061a6201000002610e605160071a630100000002010101610e2052601c604459905901600090520163e0e9a17b601c8203526107e0610120510360048201526020610ec0602483600030602d5a03f150610ec0519050610ea05260806080599059016000905260038152610ea05181602001526002816040015260008160600152809050206002810154610f205250610f205160041a610f205160051a61010002610f205160061a6201000002610f205160071a630100000002010101610ee052610ee051610e20510362049d408112156110595762049d4090505b6249d40081131561106b576249d40090505b62127500610dc0518202047bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156110ba577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90505b600860076000835b80156110d9576002810490506001820191506110c2565b5080905001046000600382131515611103578160030360080260020a62ffffff841602905061111a565b6003820360080260020a8304905062ffffff811690505b6280000081161561113357610100810490506001820191505b6301000000820281179050905090509050610f6052610f6051610c6051141515611164576000610f60511415611167565b60005b156111b357601c60205990590160009052016127246101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a3506000611040526020611040f35b5b6101e0516101e0516101e05166040000000000005455606060605990590160009052600381526101e0518160200152600081604001528090502054611060526008611060016604000000000000548060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061106051606060605990590160009052600381526101e0518160200152600081604001528090502055600166040000000000005401660400000000000055606060605990590160009052600381526101e0518160200152600081604001528090502054611100526111006001780100000000000000000000000000000000000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205404018060181a82538060191a600183015380601a1a600283015380601b1a600383015380601c1a600483015380601d1a600583015380601e1a600683015380601f1a6007830153505061110051606060605990590160009052600381526101e051816020015260008160400152809050205560006111c05278010000000000000000000000000000000000000000000000006801000000000000000060606060599059016000905260038152610a0051816020015260008160400152809050205402046111e0526111c06111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350506001611260525b6008611260511215611515576112605160050a611280526001611280517801000000000000000000000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540407141561148757611260516004026111c0016111e05180601c1a825380601d1a600183015380601e1a600283015380601f1a60038301535050611505565b611260516004026111c0017c01000000000000000000000000000000000000000000000000000000006112605160200260020a60606060599059016000905260038152610a00518160200152600181604001528090502054020480601c1a825380601d1a600183015380601e1a600283015380601f1a600383015350505b60016112605101611260526113ec565b6111c051606060605990590160009052600381526101e05181602001526001816040015280905020555050608060805990590160009052600381526101e051816020015260028160400152600081606001528090502060005b600281121561159057806020026102c05101518282015560018101905061156e565b700100000000000000000000000000000000600003816020026102c051015116828201555050610c80517bffff0000000000000000000000000000000000000000000000000000056113e0526113e051610b805101610be052606060605990590160009052600381526101e051816020015260008160400152809050205461140052601061140001610be0518060101a82538060111a60018301538060121a60028301538060131a60038301538060141a60048301538060151a60058301538060161a60068301538060171a60078301538060181a60088301538060191a600983015380601a1a600a83015380601b1a600b83015380601c1a600c83015380601d1a600d83015380601e1a600e83015380601f1a600f830153505061140051606060605990590160009052600381526101e0518160200152600081604001528090502055660400000000000354610be051121515611703576101e051660400000000000255610be0516604000000000003555b601c6020599059016000905201610120516101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a350610120516114a05260206114a0f35b601c602059905901600090520161276a6101e0517f055e4f8dd3a534789b3feb8e0681afa2aee8713fdd6472f25b2c30dc7bf4e0f4600084a35060006114c05260206114c0f35b630f5995ce8114156119a157365990590160009052366004823760043560208201016114e05260243561150052604435602082010161152052606435604052506114e05160208103516020599059016000905260208183856000600287604801f150805190509050905061156052602059905901600090526020816020611560600060026068f1508051905060005b6020811215611843578181601f031a816116400153600181019050611823565b50506116405161154052604060206114e051035114156118a457601c6020599059016000905201614e52611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a3506000611660526020611660f35b6080601c6101ac59905901600090520163bd136cb3601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff161192357fe5b6084810192506101488201518080858260c487015160006004600a8705601201f161194a57fe5b508084019350508083036020611680828434306123555a03f15061168051905090509050905061042052600161042051141561199357611540516116a05260206116a0f36119a0565b60006116c05260206116c0f35b5b63bd136cb3811415611d8c573659905901600090523660048237600435611540526024356115005260443560208201016115205260643560405250601c606459905901600090520163d467ae03601c82035260405160048201526060606059905901600090526003815260405181602001526003816040015280905020546bffffffffffffffffffffffff166024820152602061170060448334306123555a03f1506117005190501515611a9757601c6020599059016000905201614e2a611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e2a611720526020611720f35b601c6044599059016000905201633d73b705601c82035260405160048201526020611740602483600030602d5a03f15061174051905015611b1a57601c6020599059016000905201614e34611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e34611760526020611760f35b601c604459905901600090520163b041b285601c82035260405160048201526020611780602483600030602d5a03f1506117805190501515611b9e57601c6020599059016000905201614e3e611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e3e6117a05260206117a0f35b6060601c61014c59905901600090520163b7129afb601c8203526115405160048201526115005160248201526115205160208103516020026020018360448401526020820360a4840152806101088401528084019350505081600401599059016000905260648160648460006004601cf1611c1557fe5b6064810192506101088201518080858260a487015160006004600a8705601201f1611c3c57fe5b5080840193505080830360206117e08284600030602d5a03f1506117e05190509050905090506117c0526080608059905901600090526003815260405181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006002820154046401000000006001830154020160005b6020811215611ce4578181601f031a816118a00153600181019050611cc4565b50506118a051905061180052611800516117c0511415611d4457601c60205990590160009052016001611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a35060016118c05260206118c0f35b601c6020599059016000905201614e48611540517fd008620948a1ed10f4fed82dc43cf79acad36dc6b7c2c924e27c9813193b83ad600084a350614e486118e05260206118e0f35b63318a3fee81141561205657365990590160009052366004823760043560208201016114e0526024356115005260443560208201016115205260643560405260843561190052506080601c6101ac599059016000905201630f5995ce601c8203526114e0516020601f6020830351010460200260200183600484015260208203608484015280610108840152808401935050506115005160248201526115205160208103516020026020018360448401526020820360c48401528061014884015280840193505050604051606482015281600401599059016000905260848160848460006004601ff1611e7b57fe5b60848101925061010882015180808582608487015160006004600a8705601201f1611ea257fe5b508084019350506101488201518080858260c487015160006004600a8705601201f1611eca57fe5b508084019350508083036020611920828434306123555a03f15061192051905090509050905061154052600061154051141515612010576040601c60ec599059016000905201631c0b6367601c8203526114e0516020601f6020830351010460200260200183600484015260208203604484015280608884015280840193505050611540516024820152816004015990590160009052604481604484600060046018f1611f7357fe5b604481019250608882015180808582604487015160006004600a8705601201f1611f9957fe5b5080840193505080830360206119608284600061190051602d5a03f15061196051905090509050905061194052601c602059905901600090520161194051611540517f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061194051611980526020611980f35b601c602059905901600090520161753a60007f2d0d11d0f27e21fab56a8712078721096066b7faaa8540a3ea566e70b97de2d4600084a35061753a6119a05260206119a0f35b6309dd0e81811415612076576604000000000002546119c05260206119c0f35b63023948728114156120d2577801000000000000000000000000000000000000000000000000606060605990590160009052600381526604000000000002548160200152600081604001528090502054046119e05260206119e0f35b632c181929811415612139577001000000000000000000000000000000007001000000000000000000000000000000006060606059905901600090526003815266040000000000025481602001526000816040015280905020540204611a20526020611a20f35b637ca823d58114156122af576604000000000002546101e052700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611a60526000611260525b600a61126051121561224c57608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612230578181601f031a81611b200153600181019050612210565b5050611b205190506101e05260016112605101611260526121a8565b700100000000000000000000000000000000700100000000000000000000000000000000606060605990590160009052600381526101e05181602001526000816040015280905020540204611b4052611b4051611a605103611b80526020611b80f35b63b7129afb81141561246a57365990590160009052366004823760043561154052602435611500526044356020820101611520525061154051611ba0526020611520510351611bc0526000611260525b611bc05161126051121561245b5761126051602002611520510151611be05260026115005107611c00526001611c0051141561234a57611be051611c2052611ba051611c4052612368565b6000611c0051141561236757611ba051611c2052611be051611c40525b5b60405990590160009052611c205160005b6020811215612399578181601f031a81611ca00153600181019050612379565b5050611ca0518152611c405160005b60208112156123c8578181601f031a81611d2001536001810190506123a8565b5050611d2051602082015260205990590160009052602081604084600060026088f15080519050611d4052602059905901600090526020816020611d40600060026068f1508051905060005b6020811215612434578181601f031a81611de00153600181019050612414565b5050611de0519050611ba052600261150051056115005260016112605101611260526122ff565b611ba051611e00526020611e00f35b633d73b70581141561255b576004356040526604000000000002546101e0526000611260525b600661126051121561254e576101e05160405114156124b6576001611e20526020611e20f35b608060805990590160009052600381526101e05181602001526002816040015260008160600152809050207c01000000000000000000000000000000000000000000000000000000006001820154046401000000008254020160005b6020811215612532578181601f031a81611ec00153600181019050612512565b5050611ec05190506101e0526001611260510161126052612490565b6000611ee0526020611ee0f35b631f794436811415612737576004356101e052601c606459905901600090520163d467ae03601c8203526101e0516004820152606060605990590160009052600381526101e05181602001526003816040015280905020546bffffffffffffffffffffffff1660248201526020611f2060448334306123555a03f150611f20519050151561265657601c602059905901600090520160006101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350602159905901600090526001815260006020820152602081019050602060408203526020601f6020830351604001010460200260408203f3505b601c602059905901600090520160016101e0517f60ab231f060fa320acea170017564b7ee77f477e6465a8c964380cffb270aaf4600084a350608060805990590160009052600381526101e0518160200152600281604001526000816060015280905020607059905901600090526050815260208101905060005b60028112156126f05780830154816020028301526001810190506126d1565b70010000000000000000000000000000000060000381840154168160200283015281905090509050602060408203526020601f6020830351604001010460200260408203f3505b6313f955e18114156128ca573659905901600090523660048237600435602082010161204052602435612060525060506120805260006120a052612080516120c0526000611260525b612060516112605112156128bb576120a051806120c051038080602001599059016000905281815260208101905090508180828286612040510160006004600a8705601201f16127cc57fe5b50809050905090506120e0526020601c608c599059016000905201632b861629601c8203526120e0516020601f6020830351010460200260200183600484015260208203602484015280604884015280840193505050816004015990590160009052602481602484600060046015f161284157fe5b602481019250604882015180808582602487015160006004600a8705601201f161286757fe5b5080840193505080830360206121a08284600030602d5a03f1506121a051905090509050905061042052612080516120a051016120a052612080516120c051016120c0526001611260510161126052612780565b610420516121c05260206121c0f35b50", - "storage": { - "0x292b7a8d467a95cffd303c7edd99875892cdb3eaee87e5ca29057dc88a09ffbd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4d2fcf8ac901ad7dcf5b1c3979801430d9979c87157230ae066a0276984c6ac7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xdf951a5d1d9283b06d4f1de58542f1e1e310d8d17aada46586ddb9598bc42894": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x9c8d09d387f3ba5dd4733e24c63e4d549864a7cd57a1bdf1fdd831a2a0184815": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4ab3b783bb170e11b0932a5ce8f5f343f67058b3925da271001a75ae498bd655": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x0000000000000000000000000000000000000004": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x0000000000000000000000000000000000000002": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "559198", - "difficulty": "1814830", - "timestamp": "1577471205", - "gasLimit": "6327338", - "miner": "0x774c398d763161f55b66a646f17edda4addad2ca" - }, - "input": "0xf9026f8301307b85746a52880083124f80946cc68eb482a757c690dd151d2bd5e774ada38bdc80b9020413f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e00000000000000000000000000000000081a1a01c9e9d742c8e69daba2a026ccafdde618f2e44c96db281c2209c22f183ad03a2a049a61d267d22226896d4c065525819c238784c439dc2afa7d17fce76595730d1", - "result": [ - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "gas": "0x124f80", - "input": "0x13f955e100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000019004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a67040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae704000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30304000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de04000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1c6ff", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 5, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x114243", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000afbe013b4a83b2f91f3d9b6627cf382394c4914fd2b7510700000000000000008621196eb526a0e02430b6dd5c72fd368e768977f3a8364861e5a471a8ae61a1028f745609c40b185f537a6700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 0 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x110d3b", - "input": "0x2b86162900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050040000005b53875b0f1381589859adcf938980f4a8fb0af4c8845007000000000000000075289d1c48c8f71deee521a76c8d92948cbe14343991998dfaea6b08596d97dcc891745609c40b18ae825ae700000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 1 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x10d833", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000abbacd8711f647ab97c6c9b9658eb9bef081e2cedb630f010000000000000000549bcab22422baef6c34af382b227e4b1a27bec3312e04dbb62fc315203c67f30f9d745609c40b180fdfc30300000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 2 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x10a328", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000e93433dde5128942e47e8722d37ec4dcc1c8a78cf9c4a4030000000000000000bf92c09e8e37b2c8ffbb4b9cadfccc563e474c4feae6997f52d56236fedafce20a9f745609c40b1840cc27de00000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 3 - ], - "type": "call" - }, - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "gas": "0x106e1d", - "input": "0x2b8616290000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005004000000f2e372a0b5b837116eee8f968840393d85975a1531346807000000000000000076bc91399edda1de98976ee0774e2ad3b21dd38ad9f5f34d2c816a832747fe7f4c9e745609c40b18e290e9e000000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x6cc68eb482a757c690dd151d2bd5e774ada38bdc", - "value": "0x0" - }, - "result": { - "address": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x27c3", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - "subtraces": 0, - "traceAddress": [ - 4 - ], - "type": "call" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json deleted file mode 100644 index bc9470871..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_throw_outer_revert.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "context": { - "difficulty": "3956606365", - "gasLimit": "5413248", - "miner": "0x00d8ae40d9a06d0e7a2877b62e32eb959afbe16d", - "number": "2295104", - "timestamp": "1513681256" - }, - "genesis": { - "alloc": { - "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76": { - "balance": "0x0", - "code": "0x60606040526004361061015e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680625b4487146101a257806311df9995146101cb578063278ecde11461022057806330adce0e146102435780633197cbb61461026c5780634bb278f3146102955780636103d70b146102aa57806363a599a4146102bf5780636a2d1cb8146102d457806375f12b21146102fd57806378e979251461032a578063801db9cc1461035357806386d1a69f1461037c5780638da5cb5b146103915780638ef26a71146103e65780639890220b1461040f5780639b39caef14610424578063b85dfb801461044d578063be9a6555146104a1578063ccb07cef146104b6578063d06c91e4146104e3578063d669e1d414610538578063df40503c14610561578063e2982c2114610576578063f02e030d146105c3578063f2fde38b146105d8578063f3283fba14610611575b600060149054906101000a900460ff1615151561017a57600080fd5b60075442108061018b575060085442115b15151561019757600080fd5b6101a03361064a565b005b34156101ad57600080fd5b6101b5610925565b6040518082815260200191505060405180910390f35b34156101d657600080fd5b6101de61092b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561022b57600080fd5b6102416004808035906020019091905050610951565b005b341561024e57600080fd5b610256610c48565b6040518082815260200191505060405180910390f35b341561027757600080fd5b61027f610c4e565b6040518082815260200191505060405180910390f35b34156102a057600080fd5b6102a8610c54565b005b34156102b557600080fd5b6102bd610f3e565b005b34156102ca57600080fd5b6102d261105d565b005b34156102df57600080fd5b6102e76110d5565b6040518082815260200191505060405180910390f35b341561030857600080fd5b6103106110e1565b604051808215151515815260200191505060405180910390f35b341561033557600080fd5b61033d6110f4565b6040518082815260200191505060405180910390f35b341561035e57600080fd5b6103666110fa565b6040518082815260200191505060405180910390f35b341561038757600080fd5b61038f611104565b005b341561039c57600080fd5b6103a4611196565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f157600080fd5b6103f96111bb565b6040518082815260200191505060405180910390f35b341561041a57600080fd5b6104226111c1565b005b341561042f57600080fd5b610437611296565b6040518082815260200191505060405180910390f35b341561045857600080fd5b610484600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061129c565b604051808381526020018281526020019250505060405180910390f35b34156104ac57600080fd5b6104b46112c0565b005b34156104c157600080fd5b6104c9611341565b604051808215151515815260200191505060405180910390f35b34156104ee57600080fd5b6104f6611354565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561054357600080fd5b61054b61137a565b6040518082815260200191505060405180910390f35b341561056c57600080fd5b610574611385565b005b341561058157600080fd5b6105ad600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506116c3565b6040518082815260200191505060405180910390f35b34156105ce57600080fd5b6105d66116db565b005b34156105e357600080fd5b61060f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611829565b005b341561061c57600080fd5b610648600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118fe565b005b600080670de0b6b3a7640000341015151561066457600080fd5b61069b610696670de0b6b3a7640000610688610258346119d990919063ffffffff16565b611a0c90919063ffffffff16565b611a27565b9150660221b262dd80006106ba60065484611a7e90919063ffffffff16565b111515156106c757600080fd5b600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156107d557600080fd5b6102c65a03f115156107e657600080fd5b5050506040518051905050610808828260010154611a7e90919063ffffffff16565b8160010181905550610827348260000154611a7e90919063ffffffff16565b816000018190555061084434600554611a7e90919063ffffffff16565b60058190555061085f82600654611a7e90919063ffffffff16565b6006819055503373ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c836040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e8583600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60025481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060085442108061096b5750651b48eb57e00060065410155b15151561097757600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154821415156109c757600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856000604051602001526040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1515610ac857600080fd5b6102c65a03f11515610ad957600080fd5b5050506040518051905050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610b7d57600080fd5b6102c65a03f11515610b8e57600080fd5b505050604051805190501515610ba357600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000811115610c4457610c433382611a9c565b5b5050565b60055481565b60085481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cb157600080fd5b600854421015610cd357660221b262dd8000600654141515610cd257600080fd5b5b651b48eb57e000600654108015610cf057506213c6806008540142105b151515610cfc57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501515610d7557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1515610e3a57600080fd5b6102c65a03f11515610e4b57600080fd5b5050506040518051905090506000811115610f2057600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610ef957600080fd5b6102c65a03f11515610f0a57600080fd5b505050604051805190501515610f1f57600080fd5b5b6001600960006101000a81548160ff02191690831515021790555050565b600080339150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114151515610f9657600080fd5b803073ffffffffffffffffffffffffffffffffffffffff163110151515610fbc57600080fd5b610fd181600254611b5090919063ffffffff16565b6002819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561105957fe5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110b857600080fd5b6001600060146101000a81548160ff021916908315150217905550565b670de0b6b3a764000081565b600060149054906101000a900460ff1681565b60075481565b651b48eb57e00081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561115f57600080fd5b600060149054906101000a900460ff16151561117a57600080fd5b60008060146101000a81548160ff021916908315150217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561121c57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050151561129457600080fd5b565b61025881565b600a6020528060005260406000206000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561131b57600080fd5b600060075414151561132c57600080fd5b4260078190555062278d004201600881905550565b600960009054906101000a900460ff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b660221b262dd800081565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113e557600080fd5b600654660221b262dd800003925061142b670de0b6b3a764000061141c610258670de0b6b3a76400006119d990919063ffffffff16565b81151561142557fe5b04611a27565b915081831115151561143c57600080fd5b600a60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561158c57600080fd5b6102c65a03f1151561159d57600080fd5b50505060405180519050506115bf838260010154611a7e90919063ffffffff16565b81600101819055506115dc83600654611a7e90919063ffffffff16565b6006819055503073ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c846040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561173657600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b151561181357600080fd5b6102c65a03f1151561182457600080fd5b505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561188457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156118fb57806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561195957600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561199557600080fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828402905060008414806119fa57508284828115156119f757fe5b04145b1515611a0257fe5b8091505092915050565b6000808284811515611a1a57fe5b0490508091505092915050565b6000611a416202a300600754611a7e90919063ffffffff16565b421015611a7557611a6e611a5f600584611a0c90919063ffffffff16565b83611a7e90919063ffffffff16565b9050611a79565b8190505b919050565b6000808284019050838110151515611a9257fe5b8091505092915050565b611aee81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a7e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611b4681600254611a7e90919063ffffffff16565b6002819055505050565b6000828211151515611b5e57fe5b8183039050929150505600a165627a7a72305820ec0d82a406896ccf20989b3d6e650abe4dc104e400837f1f58e67ef499493ae90029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008d69d00910d0b2afb2a99ed6c16c8129fa8e1751", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000e819f024b41358d2c08e3a868a5c5dd0566078d4", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000005a388981", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000005a3b38e6" - } - }, - "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826": { - "balance": "0x2a2dd979a35cf000", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe819f024b41358d2c08e3a868a5c5dd0566078d4": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c681461027257806370a08231146102ad5780638da5cb5b146102fa57806395d89b411461034f578063a9059cbb146103dd578063dd62ed3e14610437578063f2fde38b146104a3575b600080fd5b34156100ca57600080fd5b6100d26104dc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610515565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba61069c565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106a2565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610952565b6040518082815260200191505060405180910390f35b341561027d57600080fd5b6102936004808035906020019091905050610957565b604051808215151515815260200191505060405180910390f35b34156102b857600080fd5b6102e4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610abe565b6040518082815260200191505060405180910390f35b341561030557600080fd5b61030d610b07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561035a57600080fd5b610362610b2d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a2578082015181840152602081019050610387565b50505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e857600080fd5b61041d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b66565b604051808215151515815260200191505060405180910390f35b341561044257600080fd5b61048d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d01565b6040518082815260200191505060405180910390f35b34156104ae57600080fd5b6104da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d88565b005b6040805190810160405280600b81526020017f416c6c436f6465436f696e00000000000000000000000000000000000000000081525081565b6000808214806105a157506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156105ac57600080fd5b81600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061077683600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061080b83600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108618382610e7d90919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b600681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109b557600080fd5b610a0782600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a5f82600054610e7d90919063ffffffff16565b60008190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600481526020017f414c4c430000000000000000000000000000000000000000000000000000000081525081565b6000610bba82600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610c4f82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610de457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515610e5c5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000808284019050838110151515610e7357fe5b8091505092915050565b6000828211151515610e8b57fe5b8183039050929150505600a165627a7a7230582059f3ea3df0b054e9ab711f37969684ba83fe38f255ffe2c8d850d951121c51100029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3956606365", - "extraData": "0x566961425443", - "gasLimit": "5418523", - "hash": "0x6f37eb930a25da673ea1bb80fd9e32ddac19cdf7cd4bb2eac62cc13598624077", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0x10971cde68c587c750c23b8589ae868ce82c2c646636b97e7d9856470c5297c7", - "nonce": "0x810f923ff4b450a1", - "number": "2295103", - "stateRoot": "0xff403612573d76dfdaf4fea2429b77dbe9764021ae0e38dc8ac79a3cf551179e", - "timestamp": "1513681246", - "totalDifficulty": "7162347056825919" - }, - "input": "0xf86d808504e3b292008307dfa69433056b5dcac09a9b4becad0e1dcf92c19bd0af76880e92596fd62900008029a0e5f27bb66431f7081bb7f1f242003056d7f3f35414c352cd3d1848b52716dac2a07d0be78980edb0bd2a0678fc53aa90ea9558ce346b0d947967216918ac74ccea", - "result": [ - { - "action": { - "callType": "call", - "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826", - "gas": "0x7dfa6", - "input": "0x", - "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "value": "0xe92596fd6290000" - }, - "blockNumber": 2295104, - "error": "execution reverted", - "result": { - "gasUsed": "0x7c1c8" - }, - "subtraces": 1, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "gas": "0x75fe3", - "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4", - "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4", - "value": "0x0" - }, - "blockNumber": 0, - "error": "invalid opcode: INVALID", - "result": {}, - "subtraces": 0, - "traceAddress": [0], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json deleted file mode 100644 index 3fcc61fc8..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "genesis": { - "difficulty": "1808543", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "4875092", - "hash": "0x3851fdc18bd5f2314cf0c90439356f9a1fe157d7fb06c20e20b77954da903671", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "mixHash": "0x3d4e702d6058acf94c9547560f05536d45d515bd4f9014564ec41b5b4ff9578b", - "nonce": "0x1695153e7b16c1e7", - "number": "555461", - "stateRoot": "0xba8272acd0dfeb5f04376328e8bfc5b276b177697000c204a060f6f7b629ae32", - "timestamp": "1577423350", - "totalDifficulty": "462222992438", - "alloc": { - "0xcf5b3467dfa45cdc8e5358a7a1ba4deb02e5faed": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x16c102a3b09c02abdace", - "nonce": "19049", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "555462", - "difficulty": "1808543", - "timestamp": "1577423360", - "gasLimit": "4873701", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf90451824a6985746a52880083053e908080b903fb60606040525b60405161015b806102a0833901809050604051809103906000f0600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b610247806100596000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b9392505050566060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b50505681a1a0b9a85df655d3b6aa081e52d8c3db52c50c2bf97d9d993a980113b2262649c125a00d51e63880ca8ef4705914a71e7ff906834a9cdcff0cbd063ff4e43a5905890d", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x53e90", - "init": "0x60606040525b60405161015b806102a0833901809050604051809103906000f0600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b610247806100596000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b9392505050566060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056" - }, - "result": { - "gasUsed": "0x53e90", - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632ef9db1314610044578063e37678761461007157610042565b005b61005b6004803590602001803590602001506100ad565b6040518082815260200191505060405180910390f35b61008860048035906020018035906020015061008a565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000600060008484604051808381526020018281526020019250505060405180910390209150610120600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff167f6164640000000000000000000000000000000000000000000000000000000000846101e3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681868660405180807f616464000000000000000000000000000000000000000000000000000000000081526020015060200184815260200183815260200182815260200193505050506000604051808303816000866161da5a03f191505050600060005060008281526020019081526020016000206000505492506101db565b505092915050565b60004340848484604051808581526020018473ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140183815260200182815260200194505050505060405180910390209050610240565b939250505056", - "address": "0x9db7a1baf185a865ffee3824946ccd8958191e5e" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 23, - "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", - "blockNumber": 555462, - "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1", - "time": "1.147715ms" - }, - { - "type": "create", - "action": { - "from": "0x9db7a1baf185a865ffee3824946ccd8958191e5e", - "value": "0x0", - "gas": "0x30b34", - "init": "0x6060604052610148806100136000396000f30060606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056" - }, - "result": { - "gasUsed": "0x1009d", - "code": "0x60606040526000357c010000000000000000000000000000000000000000000000000000000090048063471407e614610044578063e37678761461007757610042565b005b6100616004803590602001803590602001803590602001506100b3565b6040518082815260200191505060405180910390f35b61008e600480359060200180359060200150610090565b005b8060006000506000848152602001908152602001600020600050819055505b5050565b6000818301905080506100c684826100d5565b8090506100ce565b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff16828260405180807f7265676973746572496e74000000000000000000000000000000000000000000815260200150602001838152602001828152602001925050506000604051808303816000866161da5a03f1915050505b505056", - "address": "0xcf5b3467dfa45cdc8e5358a7a1ba4deb02e5faed" - }, - "traceAddress": [0], - "subtraces": 0, - "transactionPosition": 23, - "transactionHash": "0xe267552ce8437a5bc7081385c99f912de5723ad34b958db215dbc41abd5f6c03", - "blockNumber": 555462, - "blockHash": "0x38bba9e3965b57205097ea5ec53fc403cf3941bec2e4c933faae244de5ca4ba1" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json deleted file mode 100644 index 0eaa3f867..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create2_action_gas.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "genesis": { - "difficulty": "4635413", - "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", - "gasLimit": "9289294", - "hash": "0x359775cf1a2ae2400e26ec68bf33bcfe38b7979c76b7e616f42c4ca7e7605e39", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "mixHash": "0x4b2a0ef121a9c7d732fa0fbd4166a0e1041d2da2b8cb677c61edabf8b7183b64", - "nonce": "0x2a8a64ad9757be55", - "number": "1555160", - "stateRoot": "0x95067c12148e2362fcd4a89df286ff0b1739ef097a40ca42ae7f698af9a9d913", - "timestamp": "1590793999", - "totalDifficulty": "2242063623471", - "alloc": { - "0x8785e369f0ef0a4e5c5a5f929680427dc75273a5": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x623145b285b3f551fa3f", - "nonce": "260617", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555161", - "difficulty": "4633150", - "timestamp": "1590794020", - "gasLimit": "9298364", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf85e8303fa09843b9aca0083019ed880808a6000600060006000f50081a2a0485ea410e210740eef8e6f6de11c530f46f8da80eecb02afbb6c5f61749ac015a068d72f1b0f1d3cb4e214d5def79b49a73e6ee91db2df83499a54c656c144600f", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x19ed8", - "init": "0x6000600060006000f500" - }, - "result": { - "gasUsed": "0x14c78", - "code": "0x", - "address": "0x2e8eded627eead210cb6143eb39ef7a3e44e4f00" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 31, - "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", - "blockNumber": 1555161, - "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171", - "time": "889.048µs" - }, - { - "type": "create", - "action": { - "from": "0x2e8eded627eead210cb6143eb39ef7a3e44e4f00", - "value": "0x0", - "gas": "0x5117", - "init": "0x" - }, - "result": { - "gasUsed": "0x0", - "code": "0x", - "address": "0x8785e369f0ef0a4e5c5a5f929680427dc75273a5" - }, - "traceAddress": [0], - "subtraces": 0, - "transactionPosition": 31, - "transactionHash": "0x1257b698c5833c54ce786734087002b097275abc3877af082b5c2a538e894a41", - "blockNumber": 1555161, - "blockHash": "0xb0793dd508dd106a19794b8ce1dfc0ff8d98c76aab61bf32a11799854149a171" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json deleted file mode 100644 index 132b84df3..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "genesis": { - "difficulty": "4639933", - "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", - "gasLimit": "9280188", - "hash": "0x9a5f3a98eb1c60f6e3f450658a9cea190157e7021d04f927b752ad6482cf9194", - "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", - "mixHash": "0x6b6f8fcaa54b8565c4c1ae7cf0a020e938a53007f4561e758b17bc05c9044d78", - "nonce": "0x773aba50dc51b462", - "number": "1555169", - "stateRoot": "0xc4b9703de3e59ff795baae2c3afa010cf039c37244a7a6af7f3f491a10601348", - "timestamp": "1590794111", - "totalDifficulty": "2242105342155", - "alloc": { - "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x62325b40cbbd0915c4b9", - "nonce": "260875", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555170", - "difficulty": "4642198", - "timestamp": "1590794112", - "gasLimit": "9289249", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf8658303fb0b843b9aca0083019ee48080915a600055600060006000f0505a6001550081a2a01a7deb3a16d967b766459ef486b00656c6581e5ad58968184a33701e27e0eb8aa07162ccdfe2018d64360a605310a62c399dd586c7282dd42a88c54f02f51d451f", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x19ee4", - "init": "0x5a600055600060006000f0505a60015500" - }, - "error": "out of gas", - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 63, - "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", - "blockNumber": 1555170, - "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e", - "time": "952.736µs" - }, - { - "type": "create", - "action": { - "from": "0x9c5cfe45b15eaff4ad617af4250189e26024a4f8", - "value": "0x0", - "gas": "0x3cb", - "init": "0x" - }, - "result": { - "gasUsed": "0x0", - "code": "0x", - "address": "0x5ac5599fc9df172c89ee7ec55ad9104ccbfed40d" - }, - "traceAddress": [0], - "subtraces": 0, - "transactionPosition": 63, - "transactionHash": "0x60e881fae3884657b5430925c5d0053535b45cce0b8188f2a6be1feee8bcc650", - "blockNumber": 1555170, - "blockHash": "0xea46fbf941d51bf1e4180fbf26d22fda3896f49c7f371d109c226de95dd7b02e" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json deleted file mode 100644 index 28e96684b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "genesis": { - "difficulty": "3244991", - "extraData": "0x", - "gasLimit": "7968787", - "hash": "0x62bbf18c203068a8793af8d8360d054f95a63bc62b87ade550861ed490af3f15", - "miner": "0x9f2659ffe7b3b467e46dcec3623392cf51635079", - "mixHash": "0xc8dec711fd1e03972b6a279a09dc0cd29c5171b60f42c4ce37c7c51ff445f776", - "nonce": "0x40b1bbcc25ddb804", - "number": "839246", - "stateRoot": "0x4bb3b02ec70b837651233957fb61a6ea3fc6a4244c1f55df7a713c154829ec0a", - "timestamp": "1581179375", - "totalDifficulty": "1023985623933", - "alloc": { - "0x76554b33410b6d90b7dc889bfed0451ad195f27e": { - "balance": "0x0", - "nonce": "1", - "code": "0x6080604052348015600f57600080fd5b506004361060505760003560e01c8063391521f414605557806355313dea14605d5780636d3d14161460655780638da5cb5b14606d578063b9d1e5aa1460b5575b600080fd5b605b60bd565b005b606360c8565b005b606b60ca565b005b607360cf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60bb60f4565b005b6020610123600af050565b005b600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565bfefea165627a7a723058202094d5aa5dbbd493e9a2c64c50b62eba4b109b2a12d2bb73a5d0d54982651fc80029", - "storage": {} - }, - "0xed69ab7145a9bae7152406d062c077c6ecc6ae18": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0xa3b31cbd5168d3c99756660d4b7625d679e12573": { - "balance": "0x569bc6535d3083fce", - "nonce": "26", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "839247", - "difficulty": "3213311", - "timestamp": "1581179571", - "gasLimit": "7961006", - "miner": "0x9f2659ffe7b3b467e46dcec3623392cf51635079" - }, - "input": "0xf86a1a8509502f9000830334509476554b33410b6d90b7dc889bfed0451ad195f27e8084391521f481a2a02e4ff0d171a860c8c7de2283978e2f225f9ba3ed4dec446b773c6b2d73ef22dea02a6a517528b491cb71b204f534db11a1c8059035f54d5bae347d1cab536bde2c", - "result": [ - { - "type": "call", - "action": { - "from": "0xa3b31cbd5168d3c99756660d4b7625d679e12573", - "to": "0x76554b33410b6d90b7dc889bfed0451ad195f27e", - "value": "0x0", - "gas": "0x33450", - "input": "0x391521f4", - "callType": "call" - }, - "result": { - "gasUsed": "0xd0b5", - "output": "0x" - }, - "traceAddress": [], - "subtraces": 0, - "transactionPosition": 26, - "transactionHash": "0xcb1090fa85d2a3da8326b75333e92b3dca89963c895d9c981bfdaa64643135e4", - "blockNumber": 839247, - "blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c", - "time": "182.267µs" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json deleted file mode 100644 index c3191d61b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_pointer_issue.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "genesis": { - "number": "13535", - "hash": "0x6f706fe8026edb51577b57685574dc152dba4e2ebfc8a50bb63a8c95a4f8818d", - "nonce": "0x0000000000000000", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x7f54db248a004ca182fe87fdfa6efda97163908b4f0cc84b36a6d60699d5d1be", - "miner": "0x0000000000000000000000000000000000000000", - "difficulty": "1", - "totalDifficulty": "24766", - "extraData": "0xf09f928e20407072796c616273206e6f64652d3020f09f928e000000000000001d32ac3baf238e163e18ed6d77b67b0b54b08ad9781dc4ffd93c5ede1ca12c5f21b36ac39c7ebb88dff65da91f5b9461f19873a02602230b931ba388a809119f00", - "gasLimit": "8000000", - "timestamp": "1549153003", - "alloc": { - "0x0b1ba0af832d7c05fd64161e0db78e85978e8082": { - "balance": "0x0", - "nonce": "1", - "code": "0x6080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461018757806323b872dd146101ae5780632e1a7d4d146101e5578063313ce567146101fd57806370a082311461022857806395d89b4114610256578063a9059cbb1461026b578063d0e30db0146100ae578063dd62ed3e1461029c575b6100b66102d0565b005b3480156100c457600080fd5b506100cd61031f565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101075781810151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014e57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff600435166024356103cb565b604080519115158252519081900360200190f35b34801561019357600080fd5b5061019c61043e565b60408051918252519081900360200190f35b3480156101ba57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610443565b3480156101f157600080fd5b506100b66004356105e3565b34801561020957600080fd5b50610212610678565b6040805160ff9092168252519081900360200190f35b34801561023457600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff60043516610681565b34801561026257600080fd5b506100cd610693565b34801561027757600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff6004351660243561070b565b3480156102a857600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff6004358116906024351661071f565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b820191906000526020600020905b8154815290600101906020018083116103a657829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b303190565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081205482111561047557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105655773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561052d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105ff57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f1935050505015801561063e573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b6000610718338484610443565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a72305820228981f11f47ad9630080069b0a81423fcfba5aa8e0f478a579c4bc080ba7e820029", - "storage": { - "0xbe8a6e3827dad84a671edac41a02b0f5b47b9d0339adb1e9411b9ba4e2118738": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x48bacb9266a570d521063ef5dd96e61686dbe788": { - "balance": "0x0", - "nonce": "1", - "code": "0x6080604052600436106101b65763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663288cdc9181146101bb578063297bb70b146101f15780632ac126221461021e5780633683ef8e1461024b5780633c28d8611461026d5780633e228bae1461029a5780633fd3c997146102ba5780634ac14782146102e75780634d0ae546146103075780634f9559b11461032757806350dde190146103475780636070410814610367578063642f2eaf1461039457806364a3bc15146103b457806377fcce68146103d45780637b8e3514146103f45780637e1d9808146104145780637e9d74dc1461043457806382c174d0146104615780638da5cb5b146104815780639363470214610496578063a3e20380146104b6578063b4be83d5146104d6578063bfc8bfce146104f6578063c585bb9314610516578063c75e0a8114610536578063d46b02c314610563578063d9bfa73e14610583578063db123b1a146105a3578063dd1c7d18146105c5578063e306f779146105e5578063e5fa431b146105fa578063eea086ba1461061a578063f2fde38b1461062f578063ffa1ad741461064f575b600080fd5b3480156101c757600080fd5b506101db6101d63660046148ee565b610664565b6040516101e89190615513565b60405180910390f35b3480156101fd57600080fd5b5061021161020c366004614811565b610676565b6040516101e891906157ed565b34801561022a57600080fd5b5061023e6102393660046148ee565b6107a1565b6040516101e89190615505565b34801561025757600080fd5b5061026b61026636600461492b565b6107b6565b005b34801561027957600080fd5b5061028d610288366004614a5f565b6108a3565b6040516101e891906157fb565b3480156102a657600080fd5b506102116102b5366004614b1f565b610a3a565b3480156102c657600080fd5b506102da6102d53660046149ee565b610a90565b6040516101e891906155cf565b3480156102f357600080fd5b5061026b6103023660046147dc565b610ab8565b34801561031357600080fd5b50610211610322366004614811565b610b85565b34801561033357600080fd5b5061026b6103423660046148ee565b610c75565b34801561035357600080fd5b50610211610362366004614811565b610e2a565b34801561037357600080fd5b506103876103823660046149ee565b610ebe565b6040516101e89190615425565b3480156103a057600080fd5b5061023e6103af3660046148ee565b610f0c565b3480156103c057600080fd5b506102116103cf366004614b1f565b610f21565b3480156103e057600080fd5b5061026b6103ef3660046147ac565b610fcc565b34801561040057600080fd5b5061023e61040f366004614772565b611106565b34801561042057600080fd5b5061021161042f3660046148a5565b611126565b34801561044057600080fd5b5061045461044f3660046147dc565b61128a565b6040516101e891906154f4565b34801561046d57600080fd5b5061023e61047c36600461490c565b61131f565b34801561048d57600080fd5b5061038761133f565b3480156104a257600080fd5b5061023e6104b1366004614993565b61135b565b3480156104c257600080fd5b506102116104d13660046148a5565b6118de565b3480156104e257600080fd5b506102116104f1366004614b1f565b6119f1565b34801561050257600080fd5b5061026b610511366004614b68565b611a6c565b34801561052257600080fd5b5061026b610531366004614754565b611d05565b34801561054257600080fd5b50610556610551366004614a2a565b611f30565b6040516101e8919061580a565b34801561056f57600080fd5b5061026b61057e366004614a2a565b61202a565b34801561058f57600080fd5b506101db61059e366004614772565b6120c6565b3480156105af57600080fd5b506105b86120e3565b6040516101e891906155be565b3480156105d157600080fd5b506102116105e03660046148a5565b61218e565b3480156105f157600080fd5b506101db612263565b34801561060657600080fd5b506102116106153660046148a5565b612269565b34801561062657600080fd5b506103876123db565b34801561063b57600080fd5b5061026b61064a366004614754565b6123f7565b34801561065b57600080fd5b506105b86124a8565b60046020526000908152604090205481565b61067e614386565b600080610689614386565b60005460ff16156106cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558751935091505b81831461076f57610758878381518110151561071957fe5b90602001906020020151878481518110151561073157fe5b90602001906020020151878581518110151561074957fe5b906020019060200201516124df565b9050610764848261257d565b600190910190610701565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055509392505050565b60056020526000908152604090205460ff1681565b73ffffffffffffffffffffffffffffffffffffffff831633146108465761080e848484848080601f0160208091040260200160405190810160405280939291908181526020018383808284375061135b945050505050565b1515610846576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061569d565b5050600091825260076020908152604080842073ffffffffffffffffffffffffffffffffffffffff9093168452919052902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6108ab6143af565b6108b36143de565b6108bb6143de565b6000805460ff16156108f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561016080890151610140808a01919091528901519088015261094588611f30565b925061095087611f30565b915061095a6125df565b905061096888848389612611565b61097487838388612611565b61097e88886127a9565b610992888885604001518560400151612809565b8051602081015190519195506109ad918a9186918190612990565b6020808501519081015190516109c99189918591908190612990565b6109e28882856020015186604001518860000151612aa9565b6109fb8782846020015185604001518860200151612aa9565b610a0788888387612b55565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550949350505050565b610a42614386565b6060610a4f858585612d2d565b9050608081825160208401305af48015610a8657815183526020820151602084015260408201516040840152606082015160608401525b505b509392505050565b600b6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60008054819060ff1615610af8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558151905b808214610b5857610b508382815181101515610b4157fe5b90602001906020020151612eff565b600101610b29565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550565b610b8d614386565b600080610b98614386565b60005460ff1615610bd5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558751935091505b81831461076f57610c5e8783815181101515610c1f57fe5b906020019060200201518784815181101515610c3757fe5b906020019060200201518785815181101515610c4f57fe5b90602001906020020151612f2a565b9050610c6a848261257d565b600190910190610c07565b6000805481908190819060ff1615610cb9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610cec6125df565b935073ffffffffffffffffffffffffffffffffffffffff84163314610d115733610d14565b60005b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600660209081526040808320938516835292905220549093506001860192509050808211610d8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061572d565b73ffffffffffffffffffffffffffffffffffffffff80851660008181526006602090815260408083209488168084529490915290819020859055517f82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f090610df3908690615513565b60405180910390a35050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055505050565b610e32614386565b600080610e3d614386565b86519250600091505b818314610eb457610e9d8783815181101515610e5e57fe5b906020019060200201518784815181101515610e7657fe5b906020019060200201518785815181101515610e8e57fe5b90602001906020020151610a3a565b9050610ea9848261257d565b600190910190610e46565b5050509392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff165b919050565b60096020526000908152604090205460ff1681565b610f29614386565b60005460ff1615610f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610f9c848484612f2a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055949350505050565b6000805460ff161561100a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561103d6125df565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600860209081526040808320948916808452949091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168715151790555192935090917fa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba891906110d1908690615505565b60405180910390a35050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550565b600860209081526000928352604080842090915290825290205460ff1681565b61112e614386565b6060600080600061113d614386565b60005460ff161561117a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815589518a919081106111b257fe5b906020019060200201516101600151945088519350600092505b828414611255578489848151811015156111e257fe5b906020019060200201516101600181905250611202888760200151612f7d565b915061122e898481518110151561121557fe5b9060200190602002015183898681518110151561074957fe5b905061123a868261257d565b6020860151881161124a57611255565b6001909201916111cc565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055509195945050505050565b606060006060600084519250826040519080825280602002602001820160405280156112d057816020015b6112bd6143de565b8152602001906001900390816112b55790505b509150600090505b808314610a88576112ff85828151811015156112f057fe5b90602001906020020151611f30565b828281518110151561130d57fe5b602090810290910101526001016112d8565b600760209081526000928352604080842090915290825290205460ff1681565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b600080600080600080600080600089511115156113a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061571d565b6113ad89612fc4565b7f010000000000000000000000000000000000000000000000000000000000000090049650600760ff88161061140f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061563d565b8660ff16600781111561141e57fe5b9550600086600781111561142e57fe5b1415611466576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061570d565b600186600781111561147457fe5b14156114bc578851156114b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157dd565b600097506118d0565b60028660078111156114ca57fe5b141561160557885160411461150b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155dd565b88600081518110151561151a57fe5b01602001517f010000000000000000000000000000000000000000000000000000000000000090819004810204945061155a89600163ffffffff61308816565b935061156d89602163ffffffff61308816565b925060018b86868660405160008152602001604052604051611592949392919061556e565b60206040516020810390808403906000865af11580156115b6573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8c811690821614995092506118d09050565b600386600781111561161357fe5b14156117b9578851604114611654576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155dd565b88600081518110151561166357fe5b01602001517f01000000000000000000000000000000000000000000000000000000000000009081900481020494506116a389600163ffffffff61308816565b93506116b689602163ffffffff61308816565b925060018b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061175757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161171a565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040805192909401829003822060008352910192839052611592945092508991899150889061556e565b60048660078111156117c757fe5b14156117df576117d88b8b8b6130d3565b97506118d0565b60058660078111156117ed57fe5b1415611850576117fc89613228565b73ffffffffffffffffffffffffffffffffffffffff808c1660009081526008602090815260408083209385168352929052205490915060ff16151561184457600097506118d0565b6117d8818c8c8c6132a1565b600686600781111561185e57fe5b141561189e5760008b815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290205460ff1697506118d0565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061563d565b505050505050509392505050565b6118e6614386565b60606000806000806118f6614386565b89600081518110151561190557fe5b906020019060200201516101400151955089519450600093505b8385146119e457858a8581518110151561193557fe5b6020908102909101015161014001528651611951908a90612f7d565b92506119948a8581518110151561196457fe5b9060200190602002015160a001518b8681518110151561198057fe5b9060200190602002015160800151856133fd565b91506119c08a858151811015156119a757fe5b90602001906020020151838a87815181101515610e8e57fe5b90506119cc878261257d565b865189116119d9576119e4565b60019093019261191f565b5050505050509392505050565b6119f9614386565b60005460ff1615611a36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610f9c8484846124df565b600a5460009073ffffffffffffffffffffffffffffffffffffffff1615611abf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b611b02611afd888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843750613453945050505050565b613694565b60008181526009602052604090205490915060ff1615611b4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061568d565b73ffffffffffffffffffffffffffffffffffffffff86163314611c1f57611ba6818785858080601f0160208091040260200160405190810160405280939291908181526020018383808284375061135b945050505050565b1515611bde576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157cd565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88161790555b6000818152600960205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555130908690869080838380828437820191505092505050600060405180830381855af49150501515611cb6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156bd565b73ffffffffffffffffffffffffffffffffffffffff86163314611cfc57600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b50505050505050565b6003546000908190819073ffffffffffffffffffffffffffffffffffffffff163314611d5d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061577d565b8392508273ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611dc457600080fd5b505af1158015611dd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611dfc9190810190614a0c565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152600b602052604090205490925073ffffffffffffffffffffffffffffffffffffffff1690508015611e81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061561d565b7fffffffff0000000000000000000000000000000000000000000000000000000082166000908152600b60205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616179055517fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c0319490611f2290849087906155a3565b60405180910390a150505050565b611f386143de565b611f41826136d1565b6020808301829052600091825260049052604090819020549082015260808201511515611f755760015b60ff168152610f07565b60a08201511515611f87576002611f6b565b60a0820151604082015110611f9d576005611f6b565b6101008201514210611fb0576004611f6b565b60208082015160009081526005909152604090205460ff1615611fd4576006611f6b565b610120820151825173ffffffffffffffffffffffffffffffffffffffff90811660009081526006602090815260408083206060880151909416835292905220541115612021576006611f6b565b60038152919050565b60005460ff1615612067576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561209b81612eff565b50600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b600660209081526000928352604080842090915290825290205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156121865780601f1061215b57610100808354040283529160200191612186565b820191906000526020600020905b81548152906001019060200180831161216957829003601f168201915b505050505081565b612196614386565b606060008060006121a5614386565b8860008151811015156121b457fe5b906020019060200201516101600151945088519350600092505b828414612257578489848151811015156121e457fe5b906020019060200201516101600181905250612204888760200151612f7d565b9150612230898481518110151561221757fe5b90602001906020020151838986815181101515610e8e57fe5b905061223c868261257d565b6020860151881161224c57612257565b6001909201916121ce565b50505050509392505050565b60025481565b612271614386565b6060600080600080612281614386565b60005460ff16156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061576d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781558a518b919081106122f657fe5b906020019060200201516101400151955089519450600093505b8385146123a557858a8581518110151561232657fe5b6020908102909101015161014001528651612342908a90612f7d565b92506123558a8581518110151561196457fe5b91506123818a8581518110151561236857fe5b90602001906020020151838a8781518110151561074957fe5b905061238d878261257d565b8651891161239a576123a5565b600190930192612310565b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905550929695505050505050565b600a5473ffffffffffffffffffffffffffffffffffffffff1681565b60035473ffffffffffffffffffffffffffffffffffffffff163314612448576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061577d565b73ffffffffffffffffffffffffffffffffffffffff8116156124a557600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b60408051808201909152600581527f322e302e30000000000000000000000000000000000000000000000000000000602082015281565b6124e7614386565b6124ef6143de565b60008060006124fd88611f30565b93506125076125df565b925061251588858589612611565b6125278860a001518560400151612f7d565b915061253387836136df565b9050612546888589848960000151612990565b61255088826136f5565b945061256788848660200151876040015189612aa9565b612572888487613756565b505050509392505050565b8151815161258b9190613864565b8252602080830151908201516125a19190613864565b6020830152604080830151908201516125ba9190613864565b6040830152606080830151908201516125d39190613864565b60609092019190915250565b600a5460009073ffffffffffffffffffffffffffffffffffffffff16818115612608578161260a565b335b9392505050565b825160ff1660031461264f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061579d565b606084015173ffffffffffffffffffffffffffffffffffffffff16156126c257606084015173ffffffffffffffffffffffffffffffffffffffff1633146126c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157ad565b602084015173ffffffffffffffffffffffffffffffffffffffff161561274d578173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff1614151561274d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155ed565b604083015115156127a35761276b836020015185600001518361135b565b15156127a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061565d565b50505050565b6127bb8260a001518260a001516138ae565b6127cd836080015183608001516138ae565b1015612805576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157bd565b5050565b6128116143af565b6000806000806128258960a0015188612f7d565b935061283a89608001518a60a0015186613909565b925061284a8860a0015187612f7d565b915061285f88608001518960a0015184613909565b90508084106128a25760208086018051839052805182018490525151865182015260808a015160a08b015187519092015161289a9290613909565b8551526128df565b845183905284516020908101859052855181015190860180519190915260a089015160808a01519151516128d69290613986565b60208087015101525b84515160208087015101516128f49190612f7d565b604086015284515160808a015160c08b0151612911929190613909565b85516040015284516020015160a08a015160e08b0151612932929190613909565b855160600152602085015151608089015160c08a0151612953929190613909565b8560200151604001818152505061297b8560200151602001518960a001518a60e00151613909565b60208601516060015250505050949350505050565b8215156129c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156dd565b82821115612a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156cd565b8460a00151612a16856040015184613864565b1115612a4e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906155fd565b612a5c8560800151836138ae565b612a6a828760a001516138ae565b1115612aa2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061575d565b5050505050565b612ab7828260200151613864565b600084815260046020908152604091829020929092558681015187518451938501518584015160608701516101408c01516101608d015196518b9873ffffffffffffffffffffffffffffffffffffffff9788169897909616967f0bcc4c97732e47d9946f229edb95f5b6323f601300e4690de719993f3c37112996612b46968f96339692959194909390615433565b60405180910390a45050505050565b60018054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008789161502019095169490940493840181900481028201810190925282815260609390929091830182828015612bfe5780601f10612bd357610100808354040283529160200191612bfe565b820191906000526020600020905b815481529060010190602001808311612be157829003601f168201915b50505050509050612c2685610140015186600001518660000151856020015160200151613a23565b61014084015184518651845160200151612c4293929190613a23565b612c5b8561014001518660000151858560400151613a23565b612c778186600001518760400151856000015160400151613a23565b612c938185600001518660400151856020015160400151613a23565b836040015173ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff161415612cfd57612cf881848760400151612cf3866000015160600151876020015160600151613864565b613a23565b612aa2565b612d1581848760400151856000015160600151613a23565b612aa281848660400151856020015160600151613a23565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b81811015612e34578351855260209485019490930192600101612e16565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b81811015612e7d578351855260209485019490930192600101612e5f565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b81811015612ec5578351855260209485019490930192600101612ea7565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b612f076143de565b612f1082611f30565b9050612f1c8282613bed565b612805828260200151613d04565b612f32614386565b612f3d8484846124df565b6020810151909150831461260a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061574d565b600082821115612fb9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061560d565b508082035b92915050565b6000808251111515613002576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156fd565b815182907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061303257fe5b016020015182517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01909252507f0100000000000000000000000000000000000000000000000000000000000000908190040290565b6000816020018351101515156130ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061562d565b50016020015190565b6040516000906060907f1626ba7e000000000000000000000000000000000000000000000000000000009061310e908790869060240161554e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093178352815191935090829081885afa8080156131ab576001811461321c57612572565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0c57414c4c45545f4552524f5200000000000000000000000000000000604052600060605260646000fd5b50505195945050505050565b60006014825110151515613268576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061578d565b613276826014845103613dab565b82517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec019092525090565b6040516000906060907f9363470200000000000000000000000000000000000000000000000000000000906132de90879087908790602401615521565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783528151919350908290818a5afa80801561337b57600181146133ec576133f1565b7f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f56414c494441544f525f4552524f5200000000000000000000000000604052600060605260646000fd5b825194505b50505050949350505050565b6000808311613438576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b61344b61344585846138ae565b84613e0c565b949350505050565b604080517f5a65726f45785472616e73616374696f6e2800000000000000000000000000006020808301919091527f75696e743235362073616c742c0000000000000000000000000000000000000060328301527f61646472657373207369676e6572416464726573732c00000000000000000000603f8301527f627974657320646174610000000000000000000000000000000000000000000060558301527f2900000000000000000000000000000000000000000000000000000000000000605f830152825180830384018152606090920192839052815160009384938493909282918401908083835b6020831061357c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161353f565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909216911617905260405191909301819003812089519097508995509093508392850191508083835b6020831061361257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016135d5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040805192909401829003822097825281019a909a525073ffffffffffffffffffffffffffffffffffffffff97909716968801969096525050606085015250506080909120919050565b600280546040517f190100000000000000000000000000000000000000000000000000000000000081529182015260228101919091526042902090565b6000612fbe611afd83613e23565b60008183106136ee578161260a565b5090919050565b6136fd614386565b6020810182905260a08301516080840151613719918491613909565b808252608084015160c0850151613731929190613909565b604082015260a083015160e084015161374b918491613909565b606082015292915050565b60018054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156137ff5780601f106137d4576101008083540402835291602001916137ff565b820191906000526020600020905b8154815290600101906020018083116137e257829003601f168201915b5050505050905061381f8461014001518560000151858560000151613a23565b6138388461016001518486600001518560200151613a23565b61385081856000015186604001518560400151613a23565b6127a3818486604001518560600151613a23565b6000828201838110156138a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061567d565b8091505b5092915050565b6000808315156138c157600091506138a7565b508282028284828115156138d157fe5b04146138a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061567d565b6000808311613944576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b61394f84848461427c565b15613438576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ad565b60008083116139c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b6139cc848484614301565b15613a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ad565b61344b613445613a1386856138ae565b613a1e866001612f7d565b613864565b600080600083118015613a6257508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b15613be5578551600310613aa2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061573d565b50506020848101517fffffffff00000000000000000000000000000000000000000000000000000000166000818152600b90925260409091205473ffffffffffffffffffffffffffffffffffffffff16801515613b2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906156ed565b604051660fffffffffffe0603f885101168060840182017fa85e59e40000000000000000000000000000000000000000000000000000000083526080600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff87166044840152856064840152608483015b81811015613bc757895181526020998a019901613baf565b61020084858403866000895af1801515613bdf573d85fd5b50505050505b505050505050565b805160009060ff16600314613c2e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061579d565b606083015173ffffffffffffffffffffffffffffffffffffffff1615613ca157606083015173ffffffffffffffffffffffffffffffffffffffff163314613ca1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c6906157ad565b613ca96125df565b835190915073ffffffffffffffffffffffffffffffffffffffff808316911614613cff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061566d565b505050565b6000818152600560205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558281015183516101408501516101608601519351859473ffffffffffffffffffffffffffffffffffffffff9485169493909316927fdc47b3613d9fe400085f6dbdc99453462279057e6207385042827ed6b1a62cf792613d9f923392906154b7565b60405180910390a45050565b600081601401835110151515613ded576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061578d565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000808284811515613e1a57fe5b04949350505050565b604080517f4f726465722800000000000000000000000000000000000000000000000000006020808301919091527f61646472657373206d616b6572416464726573732c000000000000000000000060268301527f616464726573732074616b6572416464726573732c0000000000000000000000603b8301527f6164647265737320666565526563697069656e74416464726573732c0000000060508301527f616464726573732073656e646572416464726573732c00000000000000000000606c8301527f75696e74323536206d616b65724173736574416d6f756e742c0000000000000060828301527f75696e743235362074616b65724173736574416d6f756e742c00000000000000609b8301527f75696e74323536206d616b65724665652c00000000000000000000000000000060b48301527f75696e743235362074616b65724665652c00000000000000000000000000000060c58301527f75696e743235362065787069726174696f6e54696d655365636f6e64732c000060d68301527f75696e743235362073616c742c0000000000000000000000000000000000000060f48301527f6279746573206d616b65724173736574446174612c00000000000000000000006101018301527f62797465732074616b65724173736574446174610000000000000000000000006101168301527f290000000000000000000000000000000000000000000000000000000000000061012a830152825161010b81840301815261012b90920192839052815160009384938493849391929182918401908083835b602083106140ab57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161406e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930181900381206101408b0151805191995095509093508392850191508083835b6020831061414657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614109565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930181900381206101608b0151805191985095509093508392850191508083835b602083106141e157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016141a4565b5181516020939093036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018019909116921691909117905260405192018290039091207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0890180516101408b018051610160909c0180519a84529881529288526101a0822091529890525050509190525090919050565b6000808084116142b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b8215806142c3575084155b156142d15760009150610a88565b838015156142db57fe5b85840990506142ea85846138ae565b6142f66103e8836138ae565b101595945050505050565b60008080841161433d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106c69061564d565b821580614348575084155b156143565760009150610a88565b8380151561436057fe5b8584099050836143708583612f7d565b81151561437957fe5b0690506142ea85846138ae565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b610120604051908101604052806143c4614386565b81526020016143d1614386565b8152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b600061260a82356158b0565b6000601f8201831361441b57600080fd5b813561442e6144298261583f565b615818565b81815260209384019390925082018360005b8381101561446c578135860161445688826145bc565b8452506020928301929190910190600101614440565b5050505092915050565b6000601f8201831361448757600080fd5b81356144956144298261583f565b81815260209384019390925082018360005b8381101561446c57813586016144bd888261460b565b84525060209283019291909101906001016144a7565b6000601f820183136144e457600080fd5b81356144f26144298261583f565b9150818183526020840193506020810190508385602084028201111561451757600080fd5b60005b8381101561446c578161452d888261454f565b845250602092830192919091019060010161451a565b600061260a82356158c9565b600061260a82356158ce565b600061260a82356158d1565b600061260a82516158d1565b600080601f8301841361458557600080fd5b50813567ffffffffffffffff81111561459d57600080fd5b6020830191508360018202830111156145b557600080fd5b9250929050565b6000601f820183136145cd57600080fd5b81356145db61442982615860565b915080825260208301602083018583830111156145f757600080fd5b614602838284615907565b50505092915050565b6000610180828403121561461e57600080fd5b614629610180615818565b9050600061463784846143fe565b8252506020614648848483016143fe565b602083015250604061465c848285016143fe565b6040830152506060614670848285016143fe565b60608301525060806146848482850161454f565b60808301525060a06146988482850161454f565b60a08301525060c06146ac8482850161454f565b60c08301525060e06146c08482850161454f565b60e0830152506101006146d58482850161454f565b610100830152506101206146eb8482850161454f565b6101208301525061014082013567ffffffffffffffff81111561470d57600080fd5b614719848285016145bc565b6101408301525061016082013567ffffffffffffffff81111561473b57600080fd5b614747848285016145bc565b6101608301525092915050565b60006020828403121561476657600080fd5b600061344b84846143fe565b6000806040838503121561478557600080fd5b600061479185856143fe565b92505060206147a2858286016143fe565b9150509250929050565b600080604083850312156147bf57600080fd5b60006147cb85856143fe565b92505060206147a285828601614543565b6000602082840312156147ee57600080fd5b813567ffffffffffffffff81111561480557600080fd5b61344b84828501614476565b60008060006060848603121561482657600080fd5b833567ffffffffffffffff81111561483d57600080fd5b61484986828701614476565b935050602084013567ffffffffffffffff81111561486657600080fd5b614872868287016144d3565b925050604084013567ffffffffffffffff81111561488f57600080fd5b61489b8682870161440a565b9150509250925092565b6000806000606084860312156148ba57600080fd5b833567ffffffffffffffff8111156148d157600080fd5b6148dd86828701614476565b93505060206148728682870161454f565b60006020828403121561490057600080fd5b600061344b848461454f565b6000806040838503121561491f57600080fd5b6000614791858561454f565b6000806000806060858703121561494157600080fd5b600061494d878761454f565b945050602061495e878288016143fe565b935050604085013567ffffffffffffffff81111561497b57600080fd5b61498787828801614573565b95989497509550505050565b6000806000606084860312156149a857600080fd5b60006149b4868661454f565b93505060206149c5868287016143fe565b925050604084013567ffffffffffffffff8111156149e257600080fd5b61489b868287016145bc565b600060208284031215614a0057600080fd5b600061344b848461455b565b600060208284031215614a1e57600080fd5b600061344b8484614567565b600060208284031215614a3c57600080fd5b813567ffffffffffffffff811115614a5357600080fd5b61344b8482850161460b565b60008060008060808587031215614a7557600080fd5b843567ffffffffffffffff811115614a8c57600080fd5b614a988782880161460b565b945050602085013567ffffffffffffffff811115614ab557600080fd5b614ac18782880161460b565b935050604085013567ffffffffffffffff811115614ade57600080fd5b614aea878288016145bc565b925050606085013567ffffffffffffffff811115614b0757600080fd5b614b13878288016145bc565b91505092959194509250565b600080600060608486031215614b3457600080fd5b833567ffffffffffffffff811115614b4b57600080fd5b614b578682870161460b565b93505060206149c58682870161454f565b60008060008060008060808789031215614b8157600080fd5b6000614b8d898961454f565b9650506020614b9e89828a016143fe565b955050604087013567ffffffffffffffff811115614bbb57600080fd5b614bc789828a01614573565b9450945050606087013567ffffffffffffffff811115614be657600080fd5b614bf289828a01614573565b92509250509295509295509295565b614c0a816158b0565b82525050565b6000614c1b826158ac565b808452602084019350614c2d836158a6565b60005b82811015614c5d57614c438683516153e5565b614c4c826158a6565b606096909601959150600101614c30565b5093949350505050565b614c0a816158c9565b614c0a816158ce565b614c0a816158d1565b6000614c8d826158ac565b808452614ca1816020860160208601615913565b614caa8161593f565b9093016020019392505050565b614c0a816158fc565b601281527f4c454e4754485f36355f52455155495245440000000000000000000000000000602082015260400190565b600d81527f494e56414c49445f54414b455200000000000000000000000000000000000000602082015260400190565b600e81527f4f524445525f4f56455246494c4c000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b601a81527f41535345545f50524f58595f414c52454144595f455849535453000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601581527f5349474e41545552455f554e535550504f525445440000000000000000000000602082015260400190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601781527f494e56414c49445f4f524445525f5349474e4154555245000000000000000000602082015260400190565b600d81527f494e56414c49445f4d414b455200000000000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b600f81527f494e56414c49445f54585f484153480000000000000000000000000000000000602082015260400190565b601181527f494e56414c49445f5349474e4154555245000000000000000000000000000000602082015260400190565b600e81527f524f554e44494e475f4552524f52000000000000000000000000000000000000602082015260400190565b601081527f4641494c45445f455845435554494f4e00000000000000000000000000000000602082015260400190565b600d81527f54414b45525f4f56455250415900000000000000000000000000000000000000602082015260400190565b601481527f494e56414c49445f54414b45525f414d4f554e54000000000000000000000000602082015260400190565b601a81527f41535345545f50524f58595f444f45535f4e4f545f4558495354000000000000602082015260400190565b602181527f475245415445525f5448414e5f5a45524f5f4c454e4754485f5245515549524560208201527f4400000000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f5349474e41545552455f494c4c4547414c000000000000000000000000000000602082015260400190565b601e81527f4c454e4754485f475245415445525f5448414e5f305f52455155495245440000602082015260400190565b601781527f494e56414c49445f4e45575f4f524445525f45504f4348000000000000000000602082015260400190565b601e81527f4c454e4754485f475245415445525f5448414e5f335f52455155495245440000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601281527f494e56414c49445f46494c4c5f50524943450000000000000000000000000000602082015260400190565b601281527f5245454e5452414e43595f494c4c4547414c0000000000000000000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4f524445525f554e46494c4c41424c4500000000000000000000000000000000602082015260400190565b600e81527f494e56414c49445f53454e444552000000000000000000000000000000000000602082015260400190565b601881527f4e454741544956455f5350524541445f52455155495245440000000000000000602082015260400190565b601481527f494e56414c49445f54585f5349474e4154555245000000000000000000000000602082015260400190565b601181527f4c454e4754485f305f5245515549524544000000000000000000000000000000602082015260400190565b805160808301906153738482614c70565b5060208201516153866020850182614c70565b5060408201516153996040850182614c70565b5060608201516127a36060850182614c70565b80516101208301906153be8482615362565b5060208201516153d16080850182615362565b5060408201516127a3610100850182614c70565b805160608301906153f6848261541c565b5060208201516154096020850182614c70565b5060408201516127a36040850182614c70565b614c0a816158f6565b60208101612fbe8284614c01565b6101008101615442828b614c01565b61544f602083018a614c01565b61545c6040830189614c70565b6154696060830188614c70565b6154766080830187614c70565b61548360a0830186614c70565b81810360c08301526154958185614c82565b905081810360e08301526154a98184614c82565b9a9950505050505050505050565b606081016154c58286614c01565b81810360208301526154d78185614c82565b905081810360408301526154eb8184614c82565b95945050505050565b6020808252810161260a8184614c10565b60208101612fbe8284614c67565b60208101612fbe8284614c70565b6060810161552f8286614c70565b61553c6020830185614c01565b81810360408301526154eb8184614c82565b6040810161555c8285614c70565b818103602083015261344b8184614c82565b6080810161557c8287614c70565b615589602083018661541c565b6155966040830185614c70565b6154eb6060830184614c70565b604081016155b18285614c79565b61260a6020830184614c01565b6020808252810161260a8184614c82565b60208101612fbe8284614cb7565b60208082528101612fbe81614cc0565b60208082528101612fbe81614cf0565b60208082528101612fbe81614d20565b60208082528101612fbe81614d50565b60208082528101612fbe81614d80565b60208082528101612fbe81614db0565b60208082528101612fbe81614e06565b60208082528101612fbe81614e36565b60208082528101612fbe81614e66565b60208082528101612fbe81614e96565b60208082528101612fbe81614ec6565b60208082528101612fbe81614ef6565b60208082528101612fbe81614f26565b60208082528101612fbe81614f56565b60208082528101612fbe81614f86565b60208082528101612fbe81614fb6565b60208082528101612fbe81614fe6565b60208082528101612fbe81615016565b60208082528101612fbe81615046565b60208082528101612fbe8161509c565b60208082528101612fbe816150cc565b60208082528101612fbe816150fc565b60208082528101612fbe8161512c565b60208082528101612fbe8161515c565b60208082528101612fbe8161518c565b60208082528101612fbe816151bc565b60208082528101612fbe816151ec565b60208082528101612fbe8161521c565b60208082528101612fbe81615272565b60208082528101612fbe816152a2565b60208082528101612fbe816152d2565b60208082528101612fbe81615302565b60208082528101612fbe81615332565b60808101612fbe8284615362565b6101208101612fbe82846153ac565b60608101612fbe82846153e5565b60405181810167ffffffffffffffff8111828210171561583757600080fd5b604052919050565b600067ffffffffffffffff82111561585657600080fd5b5060209081020190565b600067ffffffffffffffff82111561587757600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b151590565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b6000612fbe826158b0565b82818337506000910152565b60005b8381101561592e578181015183820152602001615916565b838111156127a35750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a72305820d41ee66f45c4d1637cb6e5f109447c6d5d7fef3204a685dc442151c0f029b7da6c6578706572696d656e74616cf50037", - "storage": { - "0x1458d05345aa0372fb580f207529f32cbb6e9242890d36a93225785d4496083e": "0x0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48" - } - }, - "0x5409ed021d9299bf6814279a6a1411a7e866a631": { - "balance": "0xac6bd1cc338c2000", - "nonce": "22", - "code": "0x", - "storage": {} - }, - "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c": { - "balance": "0x0", - "nonce": "1", - "code": "0x606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058201b5b70cf82a73dec658c2e60ab9a0f8e2ba01a74b66a6f5b0402f56d2ea0ffcf0029", - "storage": { - "0xd37b858806ebf992fe75c1dd1a61cc7625ea52328d19005ba6b8b62506ae5306": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - } - }, - "config": { - "chainId": 5, - "supportedProtocolVersions": [ - 67, - 66 - ], - "homesteadBlock": 0, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 1561651, - "berlinBlock": 4460644, - "londonBlock": 5062605, - "terminalTotalDifficulty": 10790000, - "terminalTotalDifficultyPassed": true, - "clique": { - "period": 15, - "epoch": 30000 - }, - "trustedCheckpoint": { - "sectionIndex": 210, - "sectionHead": "0xbb11eaf551a6c06f74a6c7bbfe1699cbf64b8f248b64691da916dd443176db2f", - "chtRoot": "0x9934ae326d00d9c7de2e074c0e51689efb7fa7fcba18929ff4279c27259c45e6", - "bloomRoot": "0x7fe3bd4fd45194aa8a5cfe5ac590edff1f870d3d98d3c310494e7f67613a87ff" - }, - "trustedCheckpointOracle": { - "address": "0x18ca0e045f0d772a851bc7e48357bcaab0a0795d", - "signers": [ - "0x4769bcad07e3b938b7f43eb7d278bc7cb9effb38", - "0x78d1ad571a1a09d60d9bbf25894b44e4c8859595", - "0x286834935f4a8cfb4ff4c77d5770c2775ae2b0e7", - "0xb86e2b0ab5a4b1373e40c51a7c712c70ba2f9f8e", - "0x0df8fa387c602ae62559cc4afa4972a7045d6707" - ], - "threshold": 2 - } - } - }, - "context": { - "number": "13536", - "difficulty": "1", - "timestamp": "1549153018", - "gasLimit": "8000000", - "miner": "0x0000000000000000000000000000000000000000", - "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e" - }, - "input": "0xf92e9e1684ee6b2800832c8c7f8080b92e4c60806040523480156200001157600080fd5b5060405162002d2c38038062002d2c83398101806040526200003791908101906200051d565b6000805433600160a060020a031991821617825560018054909116600160a060020a0386161790558251849084908490849081906200007e906004906020870190620003d0565b50825162000094906005906020860190620003d0565b50620000b0836010640100000000620019476200036f82021704565b9150620000cd846010640100000000620019476200036f82021704565b60028054600160a060020a03948516600160a060020a031991821617909155600380549285169290911691909117905550600154604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130181207f6070410800000000000000000000000000000000000000000000000000000000825291909216945063607041089350620001739250906004016200068e565b602060405180830381600087803b1580156200018e57600080fd5b505af1158015620001a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001c99190810190620004f4565b9050600160a060020a038116151562000219576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021090620006b0565b60405180910390fd5b6002546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b39062000268908490600019906004016200066f565b602060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002be9190810190620005a1565b506003546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b3906200030e908490600019906004016200066f565b602060405180830381600087803b1580156200032957600080fd5b505af11580156200033e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003649190810190620005a1565b50505050506200077a565b600081601401835110151515620003b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000210906200069e565b506014818301810151910190600160a060020a03165b92915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200041357805160ff191683800117855562000443565b8280016001018555821562000443579182015b828111156200044357825182559160200191906001019062000426565b506200045192915062000455565b5090565b6200047291905b808211156200045157600081556001016200045c565b90565b600062000483825162000711565b9392505050565b600062000483825162000742565b6000601f82018313620004aa57600080fd5b8151620004c1620004bb82620006e9565b620006c2565b91508082526020830160208301858383011115620004de57600080fd5b620004eb83828462000747565b50505092915050565b6000602082840312156200050757600080fd5b600062000515848462000475565b949350505050565b6000806000606084860312156200053357600080fd5b600062000541868662000475565b93505060208401516001604060020a038111156200055e57600080fd5b6200056c8682870162000498565b92505060408401516001604060020a038111156200058957600080fd5b620005978682870162000498565b9150509250925092565b600060208284031215620005b457600080fd5b60006200051584846200048a565b620005cd8162000711565b82525050565b620005cd816200071d565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601881527f554e524547495354455245445f41535345545f50524f58590000000000000000602082015260400190565b620005cd8162000472565b604081016200067f8285620005c2565b62000483602083018462000664565b60208101620003ca8284620005d3565b60208082528101620003ca81620005de565b60208082528101620003ca8162000634565b6040518181016001604060020a0381118282101715620006e157600080fd5b604052919050565b60006001604060020a038211156200070057600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b151590565b60005b83811015620007645781810151838201526020016200074a565b8381111562000774576000848401525b50505050565b6125a2806200078a6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf5003700000000000000000000000048bacb9266a570d521063ef5dd96e61686dbe788000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082000000000000000000000000000000000000000000000000000000001ba0a7c6b0c9a5cb47eb4a8449556851a943353640d4fe93a64eb89eff56245c27f1a00e0d13877bfb8842dc394fd206d041b1f76be95a371eff128c8c34812a1b24c8", - "result": [ - { - "action": { - "from": "0x5409ed021d9299bf6814279a6a1411a7e866a631", - "gas": "0x2c8c7f", - "init": "0x60806040523480156200001157600080fd5b5060405162002d2c38038062002d2c83398101806040526200003791908101906200051d565b6000805433600160a060020a031991821617825560018054909116600160a060020a0386161790558251849084908490849081906200007e906004906020870190620003d0565b50825162000094906005906020860190620003d0565b50620000b0836010640100000000620019476200036f82021704565b9150620000cd846010640100000000620019476200036f82021704565b60028054600160a060020a03948516600160a060020a031991821617909155600380549285169290911691909117905550600154604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130181207f6070410800000000000000000000000000000000000000000000000000000000825291909216945063607041089350620001739250906004016200068e565b602060405180830381600087803b1580156200018e57600080fd5b505af1158015620001a3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001c99190810190620004f4565b9050600160a060020a038116151562000219576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200021090620006b0565b60405180910390fd5b6002546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b39062000268908490600019906004016200066f565b602060405180830381600087803b1580156200028357600080fd5b505af115801562000298573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002be9190810190620005a1565b506003546040517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a039091169063095ea7b3906200030e908490600019906004016200066f565b602060405180830381600087803b1580156200032957600080fd5b505af11580156200033e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003649190810190620005a1565b50505050506200077a565b600081601401835110151515620003b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000210906200069e565b506014818301810151910190600160a060020a03165b92915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200041357805160ff191683800117855562000443565b8280016001018555821562000443579182015b828111156200044357825182559160200191906001019062000426565b506200045192915062000455565b5090565b6200047291905b808211156200045157600081556001016200045c565b90565b600062000483825162000711565b9392505050565b600062000483825162000742565b6000601f82018313620004aa57600080fd5b8151620004c1620004bb82620006e9565b620006c2565b91508082526020830160208301858383011115620004de57600080fd5b620004eb83828462000747565b50505092915050565b6000602082840312156200050757600080fd5b600062000515848462000475565b949350505050565b6000806000606084860312156200053357600080fd5b600062000541868662000475565b93505060208401516001604060020a038111156200055e57600080fd5b6200056c8682870162000498565b92505060408401516001604060020a038111156200058957600080fd5b620005978682870162000498565b9150509250925092565b600060208284031215620005b457600080fd5b60006200051584846200048a565b620005cd8162000711565b82525050565b620005cd816200071d565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601881527f554e524547495354455245445f41535345545f50524f58590000000000000000602082015260400190565b620005cd8162000472565b604081016200067f8285620005c2565b62000483602083018462000664565b60208101620003ca8284620005d3565b60208082528101620003ca81620005de565b60208082528101620003ca8162000634565b6040518181016001604060020a0381118282101715620006e157600080fd5b604052919050565b60006001604060020a038211156200070057600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b151590565b60005b83811015620007645781810151838201526020016200074a565b8381111562000774576000848401525b50505050565b6125a2806200078a6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf5003700000000000000000000000048bacb9266a570d521063ef5dd96e61686dbe788000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e808200000000000000000000000000000000000000000000000000000000", - "value": "0x0" - }, - "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", - "blockNumber": 13536, - "result": { - "address": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", - "code": "0x60806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318978e8281146100c8578063630f1e6c146100f25780638da5cb5b146101125780639395525c14610134578063f2fde38b14610147575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612388565b60405180910390fd5b005b6100db6100d6366004611df1565b610167565b6040516100e9929190612488565b60405180910390f35b3480156100fe57600080fd5b506100c661010d366004611eec565b6102f7565b34801561011e57600080fd5b50610127610388565b6040516100e99190612337565b6100db610142366004611d0b565b6103a4565b34801561015357600080fd5b506100c6610162366004611ce5565b61050a565b61016f6119fa565b6101776119fa565b6000806101826105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815261025c939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b820191906000526020600020905b81548152906001019060200180831161021057829003601f168201915b50505050508c600081518110151561024157fe5b6020908102909101015161014001519063ffffffff61069616565b156102875761026c8b8b8b6107c3565b935061028084600001518560600151610ac1565b90506102ae565b6102928b8b8b610b03565b9350836060015191506102a68883896107c3565b845190935090505b6102c2846020015184602001518888610d15565b6102e98b60008151811015156102d457fe5b90602001906020020151610140015182610f29565b505097509795505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610348576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b61038383838080601f01602080910402602001604051908101604052809392919081815260200183838082843750879450610f299350505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6103ac6119fa565b6103b46119fa565b60008060006103c16105bb565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152610441939092909183018282801561022d5780601f106102025761010080835404028352916020019161022d565b156104925761046a670de0b6b3a7640000610464670de0b6b3a76400008a611045565b3461108f565b92506104778b848c6110e7565b945061048b85600001518660600151610ac1565b90506104d6565b6104ad670d2f13f7789f0000670de0b6b3a76400003461108f565b92506104ba8b848c6110e7565b9450846060015191506104ce89838a6107c3565b855190945090505b6104ea856020015185602001518989610d15565b6104fc8b60008151811015156102d457fe5b505050965096945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461055b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612438565b73ffffffffffffffffffffffffffffffffffffffff8116156105b857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b600034116105f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612398565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016000604051808303818588803b15801561067b57600080fd5b505af115801561068f573d6000803e3d6000fd5b5050505050565b6000815183511480156107ba5750816040518082805190602001908083835b602083106106f257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106b5565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0180199092169116179052604051919093018190038120885190955088945090928392508401908083835b6020831061078757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161074a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b90505b92915050565b6107cb6119fa565b60608060008060008060006107de6119fa565b8a15156107ea57610ab2565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561088e5780601f106108635761010080835404028352916020019161088e565b820191906000526020600020905b81548152906001019060200180831161087157829003601f168201915b505060058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152969e509194509250840190508282801561093d5780601f106109125761010080835404028352916020019161093d565b820191906000526020600020905b81548152906001019060200180831161092057829003601f168201915b50505050509650600095508b519450600093505b838514610a7857878c8581518110151561096757fe5b6020908102909101015161014001528b5187908d908690811061098657fe5b60209081029091010151610160015261099f8b87610ac1565b9250610a068c858151811015156109b257fe5b9060200190602002015160a00151610a008e878151811015156109d157fe5b90602001906020020151608001518f888151811015156109ed57fe5b9060200190602002015160e00151610ac1565b8561128b565b9150610a418c85815181101515610a1957fe5b90602001906020020151838c87815181101515610a3257fe5b906020019060200201516112e6565b9050610a4d898261135e565b610a5f89600001518a60600151610ac1565b95508a8610610a6d57610a78565b600190930192610951565b8a861015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b50505050505050509392505050565b600082821115610afd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123b8565b50900390565b610b0b6119fa565b606080600080600080610b1c6119fa565b60008b6000815181101515610b2d57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929b5092909190830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505096508b519550600094505b848614610cdb57878c86815181101515610c0b57fe5b6020908102909101015161014001528b5187908d9087908110610c2a57fe5b6020908102909101015161016001528851610c46908c90610ac1565b9350610c898c86815181101515610c5957fe5b9060200190602002015160a001518d87815181101515610c7557fe5b90602001906020020151608001518661128b565b9250610cb58c86815181101515610c9c57fe5b90602001906020020151848c88815181101515610a3257fe5b9150610cc1898361135e565b5087518a8110610cd057610cdb565b600190940193610bf5565b8a811015610ab2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612418565b600080808066b1a2bc2ec50000861115610d5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612448565b610d658888611045565b935034841115610da1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123a8565b610dab3485610ac1565b9250610dc086670de0b6b3a76400008a61108f565b915082821115610dfc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612428565b6000831115610f1f576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610e5b9086906004016124a4565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506000821115610edb5760405173ffffffffffffffffffffffffffffffffffffffff86169083156108fc029084906000818181858888f19350505050158015610ed9573d6000803e3d6000fd5b505b610ee58383610ac1565b90506000811115610f1f57604051339082156108fc029083906000818181858888f19350505050158015610f1d573d6000803e3d6000fd5b505b5050505050505050565b6000610f3b838263ffffffff6113c016565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161415610fab57610fa6838361142d565b610383565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116141561101357610fa6838361161b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123f8565b600082820183811015611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b8091505b5092915050565b60008083116110ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d78584611703565b8461175e565b90505b9392505050565b6110ef6119fa565b60608060008060006110ff6119fa565b89600081518110151561110e57fe5b6020908102919091018101516101400151600580546040805160026001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190931692909204601f8101869004860283018601909152808252929950929091908301828280156111c65780601f1061119b576101008083540402835291602001916111c6565b820191906000526020600020905b8154815290600101906020018083116111a957829003601f168201915b5050505050945089519350600092505b82841461127e57858a848151811015156111ec57fe5b602090810290910101516101400152895185908b908590811061120b57fe5b90602001906020020151610160018190525061122b898860200151610ac1565b91506112578a8481518110151561123e57fe5b90602001906020020151838a86815181101515610a3257fe5b9050611263878261135e565b602087015189116112735761127e565b6001909201916111d6565b5050505050509392505050565b60008083116112c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123d8565b6110dd6110d76112d68685611703565b6112e1866001610ac1565b611045565b6112ee6119fa565b606060006112fd868686611775565b600154815191935073ffffffffffffffffffffffffffffffffffffffff1691506080908390602082016000855af1801561135457825184526020830151602085015260408301516040850152606083015160608501525b5050509392505050565b8151815161136c9190611045565b8252602080830151908201516113829190611045565b60208301526040808301519082015161139b9190611045565b6040830152606080830151908201516113b49190611045565b60609092019190915250565b600081600401835110151515611402576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612468565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b60008061144184601063ffffffff61194716565b604080517f7472616e7366657228616464726573732c75696e7432353629000000000000008152905190819003601901812091935073ffffffffffffffffffffffffffffffffffffffff8416919061149f903390879060240161236d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931783525181519192909182919080838360005b8381101561154357818101518382015260200161152b565b50505050905090810190601f1680156115705780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af1925050508015156115bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b3d156115dc575060003d602014156115dc5760206000803e506000515b801515611615576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612408565b50505050565b60008060018314611658576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612478565b61166984601063ffffffff61194716565b915061167c84602463ffffffff6119a816565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd906116d590309033908690600401612345565b600060405180830381600087803b1580156116ef57600080fd5b505af1158015610f1f573d6000803e3d6000fd5b6000808315156117165760009150611088565b5082820282848281151561172657fe5b0414611084576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123e8565b600080828481151561176c57fe5b04949350505050565b604080517fb4be83d5000000000000000000000000000000000000000000000000000000006020808301919091526060602483018181528751608485019081528884015160a48601529488015160c48501529087015160e4840152608087015161010484015260a087015161012484015260c087015161014484015260e08701516101648401526101008701516101848401526101208701516101a4840152610140870180516101c485019081526101608901516101e4860152610180905251805161020485018190529394919384936044870192849261022489019291820191601f82010460005b8181101561187c57835185526020948501949093019260010161185e565b50505050818103610160808401919091528a0151805180835260209283019291820191601f82010460005b818110156118c55783518552602094850194909301926001016118a7565b50505089845250848103602093840190815288518083529093918201918981019190601f82010460005b8181101561190d5783518552602094850194909301926001016118ef565b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08883030188525060405250505050509392505050565b600081601401835110151515611989576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd90612458565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006107ba83836000816020018351101515156119f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906123c8565b50016020015190565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b60006107ba8235612540565b6000601f82018313611a4057600080fd5b8135611a53611a4e826124d9565b6124b2565b81815260209384019390925082018360005b83811015611a915781358601611a7b8882611b41565b8452506020928301929190910190600101611a65565b5050505092915050565b6000601f82018313611aac57600080fd5b8135611aba611a4e826124d9565b81815260209384019390925082018360005b83811015611a915781358601611ae28882611b90565b8452506020928301929190910190600101611acc565b600080601f83018413611b0a57600080fd5b50813567ffffffffffffffff811115611b2257600080fd5b602083019150836001820283011115611b3a57600080fd5b9250929050565b6000601f82018313611b5257600080fd5b8135611b60611a4e826124fa565b91508082526020830160208301858383011115611b7c57600080fd5b611b8783828461255c565b50505092915050565b60006101808284031215611ba357600080fd5b611bae6101806124b2565b90506000611bbc8484611a23565b8252506020611bcd84848301611a23565b6020830152506040611be184828501611a23565b6040830152506060611bf584828501611a23565b6060830152506080611c0984828501611cd9565b60808301525060a0611c1d84828501611cd9565b60a08301525060c0611c3184828501611cd9565b60c08301525060e0611c4584828501611cd9565b60e083015250610100611c5a84828501611cd9565b61010083015250610120611c7084828501611cd9565b6101208301525061014082013567ffffffffffffffff811115611c9257600080fd5b611c9e84828501611b41565b6101408301525061016082013567ffffffffffffffff811115611cc057600080fd5b611ccc84828501611b41565b6101608301525092915050565b60006107ba8235612559565b600060208284031215611cf757600080fd5b6000611d038484611a23565b949350505050565b60008060008060008060c08789031215611d2457600080fd5b863567ffffffffffffffff811115611d3b57600080fd5b611d4789828a01611a9b565b965050602087013567ffffffffffffffff811115611d6457600080fd5b611d7089828a01611a2f565b955050604087013567ffffffffffffffff811115611d8d57600080fd5b611d9989828a01611a9b565b945050606087013567ffffffffffffffff811115611db657600080fd5b611dc289828a01611a2f565b9350506080611dd389828a01611cd9565b92505060a0611de489828a01611a23565b9150509295509295509295565b600080600080600080600060e0888a031215611e0c57600080fd5b873567ffffffffffffffff811115611e2357600080fd5b611e2f8a828b01611a9b565b9750506020611e408a828b01611cd9565b965050604088013567ffffffffffffffff811115611e5d57600080fd5b611e698a828b01611a2f565b955050606088013567ffffffffffffffff811115611e8657600080fd5b611e928a828b01611a9b565b945050608088013567ffffffffffffffff811115611eaf57600080fd5b611ebb8a828b01611a2f565b93505060a0611ecc8a828b01611cd9565b92505060c0611edd8a828b01611a23565b91505092959891949750929550565b600080600060408486031215611f0157600080fd5b833567ffffffffffffffff811115611f1857600080fd5b611f2486828701611af8565b93509350506020611f3786828701611cd9565b9150509250925092565b611f4a81612540565b82525050565b602381527f44454641554c545f46554e4354494f4e5f574554485f434f4e54524143545f4f60208201527f4e4c590000000000000000000000000000000000000000000000000000000000604082015260600190565b601181527f494e56414c49445f4d53475f56414c5545000000000000000000000000000000602082015260400190565b600d81527f4f564552534f4c445f5745544800000000000000000000000000000000000000602082015260400190565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f4449564953494f4e5f42595f5a45524f00000000000000000000000000000000602082015260400190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b600f81527f5452414e534645525f4641494c45440000000000000000000000000000000000602082015260400190565b601481527f434f4d504c4554455f46494c4c5f4641494c4544000000000000000000000000602082015260400190565b601a81527f494e53554646494349454e545f4554485f52454d41494e494e47000000000000602082015260400190565b601381527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000602082015260400190565b601881527f4645455f50455243454e544147455f544f4f5f4c415247450000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160808301906122f9848261232e565b50602082015161230c602085018261232e565b50604082015161231f604085018261232e565b50606082015161161560608501825b611f4a81612559565b602081016107bd8284611f41565b606081016123538286611f41565b6123606020830185611f41565b611d03604083018461232e565b6040810161237b8285611f41565b6110e0602083018461232e565b602080825281016107bd81611f50565b602080825281016107bd81611fa6565b602080825281016107bd81611fd6565b602080825281016107bd81612006565b602080825281016107bd81612036565b602080825281016107bd8161208c565b602080825281016107bd816120bc565b602080825281016107bd816120ec565b602080825281016107bd8161211c565b602080825281016107bd8161214c565b602080825281016107bd8161217c565b602080825281016107bd816121ac565b602080825281016107bd816121dc565b602080825281016107bd8161220c565b602080825281016107bd81612262565b602080825281016107bd816122b8565b610100810161249782856122e8565b6110e060808301846122e8565b602081016107bd828461232e565b60405181810167ffffffffffffffff811182821017156124d157600080fd5b604052919050565b600067ffffffffffffffff8211156124f057600080fd5b5060209081020190565b600067ffffffffffffffff82111561251157600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b828183375060009101525600a265627a7a72305820d9f418f11e0f91f06f6f9d22924be0add925495eeb76a6388b5417adb505eeb36c6578706572696d656e74616cf50037", - "gasUsed": "0x2c8c7f" - }, - "subtraces": 3, - "traceAddress": [], - "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", - "transactionPosition": 0, - "type": "create" - }, - { - "action": { - "callType": "call", - "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", - "gas": "0x1dba84", - "input": "0x60704108f47261b000000000000000000000000000000000000000000000000000000000", - "to": "0x48bacb9266a570d521063ef5dd96e61686dbe788", - "value": "0x0" - }, - "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", - "blockNumber": 13536, - "result": { - "gasUsed": "0x3d9", - "output": "0x0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48" - }, - "subtraces": 0, - "traceAddress": [ - 0 - ], - "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", - "transactionPosition": 0, - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", - "gas": "0x1dad2e", - "input": "0x095ea7b30000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "to": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082", - "value": "0x0" - }, - "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", - "blockNumber": 13536, - "result": { - "gasUsed": "0x56c8", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [ - 1 - ], - "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", - "transactionPosition": 0, - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x6000eca38b8b5bba64986182fe2a69c57f6b5414", - "gas": "0x1d4ee1", - "input": "0x095ea7b30000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "to": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c", - "value": "0x0" - }, - "blockHash": "0x6456fbd35a3a69a1709c324fad114d68507d2c8ab391e9adb128f9734c8e4ae8", - "blockNumber": 13536, - "result": { - "gasUsed": "0x56ca", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 0, - "traceAddress": [ - 2 - ], - "transactionHash": "0x6974f745a004f030bebb1c01d4595edbda2fafcf01c0bfbd5d335711e2a7b04e", - "transactionPosition": 0, - "type": "call" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json deleted file mode 100644 index bd6059fae..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/oog.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "context": { - "difficulty": "3699098917", - "gasLimit": "5258985", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294631", - "timestamp": "1513675366" - }, - "genesis": { - "alloc": { - "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", - "nonce": "1", - "storage": { - "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" - } - }, - "0x94194bc2aaf494501d7880b61274a169f6502a54": { - "balance": "0xea8c39a876d19888d", - "code": "0x", - "nonce": "265", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3699098917", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5263953", - "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", - "nonce": "0xd1bdb150f6fd170e", - "number": "2294630", - "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", - "timestamp": "1513675347", - "totalDifficulty": "7160543502214733" - }, - "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", - "result": [ - { - "action": { - "callType": "call", - "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", - "gas": "0xca1d", - "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", - "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", - "value": "0x0" - }, - "blockNumber": 2294631, - "error": "out of gas", - "result": {}, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json deleted file mode 100644 index 8888d3e68..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/option_convert_parity_errors.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "context": { - "difficulty": "3699098917", - "gasLimit": "5258985", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294631", - "timestamp": "1513675366" - }, - "genesis": { - "alloc": { - "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", - "nonce": "1", - "storage": { - "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" - } - }, - "0x94194bc2aaf494501d7880b61274a169f6502a54": { - "balance": "0xea8c39a876d19888d", - "code": "0x", - "nonce": "265", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3699098917", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5263953", - "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", - "nonce": "0xd1bdb150f6fd170e", - "number": "2294630", - "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", - "timestamp": "1513675347", - "totalDifficulty": "7160543502214733" - }, - "tracerConfig": { - "convertParityErrors": true - }, - "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", - "result": [ - { - "action": { - "callType": "call", - "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", - "gas": "0xca1d", - "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", - "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", - "value": "0x0" - }, - "blockNumber": 2294631, - "error": "Out of gas", - "result": {}, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json deleted file mode 100644 index 62baf333b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/result_output.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "genesis": { - "difficulty": "1911202", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "7842876", - "hash": "0x4d7bc82e0d56307094378e1a8fbfa6260986f621de95b5fe68a95248b3ba8efe", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "mixHash": "0xc102ad52677c391edab82cc895ca7a7e9fff3eed4fa966ecf7fb61ec1e84bb6b", - "nonce": "0x39f5b074e3437f3f", - "number": "553415", - "stateRoot": "0x8f89e79109c19fa00e72b400502448540dc4773ad92dddd341dbba20c710a3b5", - "timestamp": "1577396195", - "totalDifficulty": "458361299240", - "alloc": { - "0x531f76bad925f6a925474996c7d738c1008045f6": { - "balance": "0x0", - "nonce": "1", - "code": "0x6060604052361561008a576000357c01000000000000000000000000000000000000000000000000000000009004806301cb3b20146102bf57806329dcb0cf146102cc57806338af3eed146102ed5780636e66f6e9146103245780637a3a0e841461035b5780637b3e5e7b1461037c578063a035b1fe1461039d578063dc0d3dff146103be5761008a565b6102bd5b60003490506040604051908101604052803381526020018281526020015060066000506006600050805480919060010190908154818355818115116101365760020281600202836000526020600020918201910161013591906100ec565b808211156101315760006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160005060009055506001016100ec565b5090565b5b505050815481101561000257906000526020600020906002020160005060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060208201518160010160005055905050806002600082828250540192505081905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166390b98a11336004600050548404604051837c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750505060405151507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf633826001604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15b50565b005b6102ca6004506104c8565b005b6102d760045061043a565b6040518082815260200191505060405180910390f35b6102f8600450610402565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61032f60045061044c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610366600450610428565b6040518082815260200191505060405180910390f35b610387600450610431565b6040518082815260200191505060405180910390f35b6103a8600450610443565b6040518082815260200191505060405180910390f35b6103cf600480359060200150610472565b604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016000505481565b60026000505481565b60036000505481565b60046000505481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60066000508181548110156100025790600052602060002090600202016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010160005054905082565b6000600360005054421015156107d8576001600050546002600050541015156105cf57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000600260005054604051809050600060405180830381858888f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166002600050546000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a161079d565b7fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf66000600b600060405180848152602001838152602001828152602001935050505060405180910390a1600090505b60066000505481101561079c57600660005081815481101561000257906000526020600020906002020160005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166000600660005083815481101561000257906000526020600020906002020160005060010160005054604051809050600060405180830381858888f19350505050507fe842aea7a5f1b01049d752008c53c52890b1a6daf660cf39e8eec506112bbdf6600660005082815481101561000257906000526020600020906002020160005060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166006600050838154811015610002579060005260206000209060020201600050600101600050546000604051808473ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a15b806001019050805061061e565b5b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b5056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000b49180d443dc4ca6028de0031ac09337891fd8ce", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" - } - }, - "0xb49180d443dc4ca6028de0031ac09337891fd8ce": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x193e9986e2e3f0c58988", - "nonce": "2585", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "553416", - "difficulty": "1909336", - "timestamp": "1577396224", - "gasLimit": "7835218", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf870820a1985e8d4a5100083040b2894531f76bad925f6a925474996c7d738c1008045f6880de0b6b3a76400008081a2a08693170f040d9501b831b404d9e40fba040c5aef4b8974aedc20b3844aea7c32a0476861058ff9b8030c58bcba8be320acc855e4694a633c493fb50fbdb9455489", - "result": [ - { - "type": "call", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "to": "0x531f76bad925f6a925474996c7d738c1008045f6", - "value": "0xde0b6b3a7640000", - "gas": "0x40b28", - "input": "0x", - "callType": "call" - }, - "result": { - "gasUsed": "0x19c3e", - "output": "0x" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 5, - "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", - "blockNumber": 553416, - "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282", - "time": "617.42µs" - }, - { - "type": "call", - "action": { - "from": "0x531f76bad925f6a925474996c7d738c1008045f6", - "to": "0xb49180d443dc4ca6028de0031ac09337891fd8ce", - "value": "0x0", - "gas": "0x2164e", - "input": "0x90b98a11000000000000000000000000877bd459c9b7d8576b44e59e09d076c25946f4430000000000000000000000000000000000000000000000000000000000000001", - "callType": "call" - }, - "result": { - "gasUsed": "0x0", - "output": "0x" - }, - "traceAddress": [ - 0 - ], - "subtraces": 0, - "transactionPosition": 5, - "transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada", - "blockNumber": 553416, - "blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json deleted file mode 100644 index b0346d860..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "context": { - "difficulty": "3665057456", - "gasLimit": "5232723", - "miner": "0xf4d8e706cfb25c0decbbdd4d2e2cc10c66376a3f", - "number": "2294501", - "timestamp": "1513673601" - }, - "genesis": { - "alloc": { - "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9": { - "balance": "0x2a3fc32bcc019283", - "code": "0x", - "nonce": "10", - "storage": {} - }, - "0xabbcd5b340c80b5f1c0545c04c987b87310296ae": { - "balance": "0x0", - "code": "0x606060405236156100755763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632d0335ab811461007a578063548db174146100ab5780637f649783146100fc578063b092145e1461014d578063c3f44c0a14610186578063c47cf5de14610203575b600080fd5b341561008557600080fd5b610099600160a060020a0360043516610270565b60405190815260200160405180910390f35b34156100b657600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061028f95505050505050565b005b341561010757600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061029e95505050505050565b005b341561015857600080fd5b610172600160a060020a03600435811690602435166102ad565b604051901515815260200160405180910390f35b341561019157600080fd5b6100fa6004803560ff1690602480359160443591606435600160a060020a0316919060a49060843590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965050509235600160a060020a031692506102cd915050565b005b341561020e57600080fd5b61025460046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061056a95505050505050565b604051600160a060020a03909116815260200160405180910390f35b600160a060020a0381166000908152602081905260409020545b919050565b61029a816000610594565b5b50565b61029a816001610594565b5b50565b600160209081526000928352604080842090915290825290205460ff1681565b60008080600160a060020a038416158061030d5750600160a060020a038085166000908152600160209081526040808320339094168352929052205460ff165b151561031857600080fd5b6103218561056a565b600160a060020a038116600090815260208190526040808220549295507f19000000000000000000000000000000000000000000000000000000000000009230918891908b908b90517fff000000000000000000000000000000000000000000000000000000000000008089168252871660018201526c01000000000000000000000000600160a060020a038088168202600284015286811682026016840152602a8301869052841602604a820152605e810182805190602001908083835b6020831061040057805182525b601f1990920191602091820191016103e0565b6001836020036101000a0380198251168184511617909252505050919091019850604097505050505050505051809103902091506001828a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561049957600080fd5b5050602060405103519050600160a060020a03838116908216146104bc57600080fd5b600160a060020a0380841660009081526020819052604090819020805460010190559087169086905180828051906020019080838360005b8381101561050d5780820151818401525b6020016104f4565b50505050905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008661646e5a03f1915050151561055e57600080fd5b5b505050505050505050565b600060248251101561057e5750600061028a565b600160a060020a0360248301511690505b919050565b60005b825181101561060157600160a060020a033316600090815260016020526040812083918584815181106105c657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff19169115159190911790555b600101610597565b5b5050505600a165627a7a723058200027e8b695e9d2dea9f3629519022a69f3a1d23055ce86406e686ea54f31ee9c0029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3672229776", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5227619", - "hash": "0xa07b3d6c6bf63f5f981016db9f2d1d93033833f2c17e8bf7209e85f1faf08076", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x806e151ce2817be922e93e8d5921fa0f0d0fd213d6b2b9a3fa17458e74a163d0", - "nonce": "0xbc5d43adc2c30c7d", - "number": "2294500", - "stateRoot": "0xca645b335888352ef9d8b1ef083e9019648180b259026572e3139717270de97d", - "timestamp": "1513673552", - "totalDifficulty": "7160066586979149" - }, - "input": "0xf9018b0a8505d21dba00832dc6c094abbcd5b340c80b5f1c0545c04c987b87310296ae80b9012473b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0fd659d76a4edbd2a823e324c93f78ad6803b30ff4a9c8bce71ba82798975c70ca06571eecc0b765688ec6c78942c5ee8b585e00988c0141b518287e9be919bc48a", - "result": [ - { - "action": { - "callType": "call", - "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9", - "gas": "0x2dc6c0", - "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", - "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae", - "value": "0x0" - }, - "blockNumber": 2294501, - "error": "execution reverted", - "result": { - "gasUsed": "0x719b" - }, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json deleted file mode 100644 index 6759b05e5..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/revert_reason.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "context": { - "difficulty": "2", - "gasLimit": "8000000", - "miner": "0x0000000000000000000000000000000000000000", - "number": "3212651", - "timestamp": "1597246515" - }, - "genesis": { - "alloc": { - "0xf58833cf0c791881b494eb79d461e08a1f043f52": { - "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063609ff1bd11610078578063609ff1bd146101af5780639e7b8d61146101cd578063a3ec138d14610211578063e2ba53f0146102ae576100a5565b80630121b93f146100aa578063013cf08b146100d85780632e4176cf146101215780635c19a95c1461016b575b600080fd5b6100d6600480360360208110156100c057600080fd5b81019080803590602001909291905050506102cc565b005b610104600480360360208110156100ee57600080fd5b8101908080359060200190929190505050610469565b604051808381526020018281526020019250505060405180910390f35b61012961049a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ad6004803603602081101561018157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bf565b005b6101b76108db565b6040518082815260200191505060405180910390f35b61020f600480360360208110156101e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610952565b005b6102536004803603602081101561022757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b53565b60405180858152602001841515151581526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390f35b6102b6610bb0565b6040518082815260200191505060405180910390f35b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154141561038a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f486173206e6f20726967687420746f20766f746500000000000000000000000081525060200191505060405180910390fd5b8060010160009054906101000a900460ff161561040f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f416c726561647920766f7465642e00000000000000000000000000000000000081525060200191505060405180910390fd5b60018160010160006101000a81548160ff02191690831515021790555081816002018190555080600001546002838154811061044757fe5b9060005260206000209060020201600101600082825401925050819055505050565b6002818154811061047657fe5b90600052602060002090600202016000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff1615610587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f596f7520616c726561647920766f7465642e000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e000081525060200191505060405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107cc57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f466f756e64206c6f6f7020696e2064656c65676174696f6e2e0000000000000081525060200191505060405180910390fd5b61062a565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156108bf578160000154600282600201548154811061089c57fe5b9060005260206000209060020201600101600082825401925050819055506108d6565b816000015481600001600082825401925050819055505b505050565b6000806000905060008090505b60028054905081101561094d57816002828154811061090357fe5b9060005260206000209060020201600101541115610940576002818154811061092857fe5b90600052602060002090600202016001015491508092505b80806001019150506108e8565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180610bde6028913960400191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff1615610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f54686520766f74657220616c726561647920766f7465642e000000000000000081525060200191505060405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414610b0957600080fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555050565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16908060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154905084565b60006002610bbc6108db565b81548110610bc657fe5b90600052602060002090600202016000015490509056fe4f6e6c79206368616972706572736f6e2063616e206769766520726967687420746f20766f74652ea26469706673582212201d282819f8f06fed792100d60a8b08809b081a34a1ecd225e83a4b41122165ed64736f6c63430006060033", - "nonce": "1", - "storage": { - "0x6200beec95762de01ce05f2a0e58ce3299dbb53c68c9f3254a242121223cdf58": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1": { - "balance": "0x57af9d6b3df812900", - "code": "0x", - "nonce": "6", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "IstanbulBlock": 1561651, - "chainId": 5, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf888068449504f80832dc6c094f58833cf0c791881b494eb79d461e08a1f043f5280a45c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf12da0264664db3e71fae1dbdaf2f53954be149ad3b7ba8a5054b4d89c70febfacc8b1a0212e8398757963f419681839ae8c5a54b411e252473c82d93dda68405ca63294", - "result": [ - { - "action": { - "callType": "call", - "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "gas": "0x2dc6c0", - "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52", - "value": "0x0" - }, - "blockNumber": 3212651, - "error": "execution reverted", - "result": { - "gasUsed": "0x5940", - "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000" - }, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json deleted file mode 100644 index 74fd87cc6..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "genesis": { - "difficulty": "4628640", - "extraData": "0xd883010b05846765746888676f312e31342e33856c696e7578", - "gasLimit": "9244120", - "hash": "0x5a1f551897cc91265225b0453136ad8c7eef1c1c8b06139da4f2e6e710c1f4df", - "miner": "0x73f26d124436b0791169d63a3af29c2ae47765a3", - "mixHash": "0xd6735e63f8937fe0c5491e0d5836ec28467363be7ada5a2f979f9d107e2c831e", - "nonce": "0x7c35e34d2e328d7d", - "number": "1555145", - "stateRoot": "0x565873b05f71b98595133e37a52d79c3476ce820c05ebedaddd35541b0e894a3", - "timestamp": "1590793819", - "totalDifficulty": "2241994078605", - "alloc": { - "0x119f569a45e9d0089d51d7f9529f5ea9bf5785e2": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x622e8fced69d43eb8d97", - "nonce": "260140", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555146", - "difficulty": "4630900", - "timestamp": "1590793820", - "gasLimit": "9253146", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf8628303f82c843b9aca0083019ecc80808e605a600053600160006001f0ff0081a2a077f539ae2a58746bbfa6370fc423f946870efa32753d697d3729d361a428623aa0384ef9a5650d6630f5c1ddef616bffa5fc72a95a9314361d0918de066aa4475a", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x19ecc", - "init": "0x605a600053600160006001f0ff00" - }, - "result": { - "gasUsed": "0x102a1", - "code": "0x", - "address": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca" - }, - "traceAddress": [], - "subtraces": 1, - "transactionPosition": 14, - "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", - "blockNumber": 1555146, - "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e", - "time": "187.145µs" - }, - { - "type": "suicide", - "action": { - "address": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca", - "refundAddress": "0x0000000000000000000000000000000000000000", - "balance": "0x0" - }, - "result": null, - "traceAddress": [ - 0 - ], - "subtraces": 0, - "transactionPosition": 14, - "transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79", - "blockNumber": 1555146, - "blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json deleted file mode 100644 index a7244e974..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": [ - { - "action": { - "callType": "call", - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "value": "0x0" - }, - "blockNumber": 2289806, - "result": { - "gasUsed": "0x9751", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 1, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "gas": "0x6d05", - "input": "0x", - "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "value": "0x6f05b59d3b20000" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x0", - "output": "0x" - }, - "subtraces": 0, - "traceAddress": [0], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple_onlytop.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple_onlytop.json deleted file mode 100644 index 5fbdf55d2..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/simple_onlytop.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "tracerConfig": { - "onlyTopCall": true - }, - "result": [ - { - "action": { - "callType": "call", - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "value": "0x0" - }, - "blockNumber": 2289806, - "result": { - "gasUsed": "0x9751", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - "subtraces": 1, - "traceAddress": [], - "type": "call" - }, - { - "action": { - "callType": "call", - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "gas": "0x6d05", - "input": "0x", - "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "value": "0x6f05b59d3b20000" - }, - "blockNumber": 0, - "result": { - "gasUsed": "0x0", - "output": "0x" - }, - "subtraces": 0, - "traceAddress": [0], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json deleted file mode 100644 index 96060d554..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "genesis": { - "difficulty": "4673862", - "extraData": "0xd683010b05846765746886676f312e3133856c696e7578", - "gasLimit": "9471919", - "hash": "0x7f072150c5905c214966e3432d418910badcdbe510aceaac295b1d7059cc0ffc", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "mixHash": "0x113ced8fedb939fdc862008da7bdddde726f997c0e6dfba0e55613994757b489", - "nonce": "0x0f411a2e5552c5b7", - "number": "1555284", - "stateRoot": "0x9fe125b361b72d5479b24ad9be9964b74228c73a2dfb0065060a79b4a6dfaa1e", - "timestamp": "1590795374", - "totalDifficulty": "2242642335405", - "alloc": { - "0xe85df1413eebe1b191c26260e19783a274a6b041": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x6244c985ef1e48e84531", - "nonce": "265775", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "1555285", - "difficulty": "4676144", - "timestamp": "1590795378", - "gasLimit": "9481167", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf9014083040e2f843b9aca008301aab08080b8eb7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f05581a2a09db45e7846f193471f6d897fb6ff58b7ec41a9c6f63d10aca47d821c365981cba052ec320875625e16141a1a9e8b7993de863698fb699f93ae2cab26149bbb144f", - "result": [ - { - "type": "create", - "action": { - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "value": "0x0", - "gas": "0x1aab0", - "init": "0x7f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b57f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000945304eb96065b2a98b57a48a06ae28d285a71b5547f000000000000000000000000000000000000000000000000000000000000c3507f000000000000000000000000000000000000000000000000000000000000c3507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000037f055" - }, - "error": "out of gas", - "traceAddress": [], - "subtraces": 0, - "transactionPosition": 16, - "transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05", - "blockNumber": 1555285, - "blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f", - "time": "665.278µs" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json deleted file mode 100644 index 45ffbe2db..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/staticcall_precompiled.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "genesis": { - "difficulty": "2028219", - "extraData": "0xd883010906846765746888676f312e31332e35856c696e7578", - "gasLimit": "23481547", - "hash": "0x3c06114e88c26b52decfe4e5f6d4d51cfaaea0317b646017fac32fadbe7df9f5", - "miner": "0x2a1442b4fbabf7b5507c13ccf076a547abfaeb1b", - "mixHash": "0x46108f74220c5ab23651f93912b14fea37ed1380d22e10639a1f5651c98cb949", - "nonce": "0x426a5267e0b636fe", - "number": "567687", - "stateRoot": "0x7b4b193fe73ef87101c7c325954681861cc240c299d03459784b2b11c9c522ae", - "timestamp": "1577578008", - "totalDifficulty": "485254950048", - "alloc": { - "0x8521f13dd5e4bc3dab3cf0f01a195a5af899e851": { - "balance": "0x0", - "nonce": "1", - "code": "0x608060405260043610610251576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301ffc9a7146102565780630519ce79146102c857806306fdde031461031f578063095ea7b3146103af5780630a0f81681461040a5780631155dfe51461046157806318160ddd1461048c5780631b57cd44146104b7578063200b1e641461050657806327d7874c146105cb5780632ba73c151461061c5780633108e4d71461066d578063317676bf146106bc5780633f4ba83a1461071557806342842e0e1461072c57806346cb96fa146107a75780634e0a3379146107f65780635501d42d146108475780635c975abb146108a05780635fd8c710146108cf5780636352211e146108e65780636af04a571461096157806370a08231146109b85780637158798814610a1d5780637866928014610a6e5780638456cb5914610ae95780638462151c14610b0057806385ac788214610ba657806395787d2614610c2c57806395d89b4114610c6e57806396b5d99214610cfe578063990581b614610d795780639db797f014610e2d578063ab8f933a14610e80578063ad84202814610eab578063b047fb5014610ed6578063b355752214610f2d578063b9db15b414610f7c578063bc4006f514610fd2578063ca083be214611029578063cdd22c9314611082578063cec21acb146110d1578063e078d8b114611136578063e17b25af14611182578063e52ab74b146111d3578063f010432314611222578063fac9c51f1461129d578063fdb33429146112ec578063fffb147914611367575b600080fd5b34801561026257600080fd5b506102ae6004803603602081101561027957600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690602001909291905050506113e2565b604051808215151515815260200191505060405180910390f35b3480156102d457600080fd5b506102dd6116cb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561032b57600080fd5b506103346116f1565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610374578082015181840152602081019050610359565b50505050905090810190601f1680156103a15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103bb57600080fd5b50610408600480360360408110156103d257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061172a565b005b34801561041657600080fd5b5061041f6117c4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561046d57600080fd5b506104766117e9565b6040518082815260200191505060405180910390f35b34801561049857600080fd5b506104a16117f6565b6040518082815260200191505060405180910390f35b3480156104c357600080fd5b506104f0600480360360208110156104da57600080fd5b8101908080359060200190929190505050611806565b6040518082815260200191505060405180910390f35b34801561051257600080fd5b506105b5600480360360a081101561052957600080fd5b81019080803590602001909291908035906020019064010000000081111561055057600080fd5b82018360208201111561056257600080fd5b8035906020019184600183028401116401000000008311171561058457600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919050505061181e565b6040518082815260200191505060405180910390f35b3480156105d757600080fd5b5061061a600480360360208110156105ee57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611cac565b005b34801561062857600080fd5b5061066b6004803603602081101561063f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d86565b005b34801561067957600080fd5b506106a66004803603602081101561069057600080fd5b8101908080359060200190929190505050611e61565b6040518082815260200191505060405180910390f35b3480156106c857600080fd5b506106ff600480360360408110156106df57600080fd5b810190808035906020019092919080359060200190929190505050611e79565b6040518082815260200191505060405180910390f35b34801561072157600080fd5b5061072a611ea9565b005b34801561073857600080fd5b506107a56004803603606081101561074f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f86565b005b3480156107b357600080fd5b506107e0600480360360208110156107ca57600080fd5b8101908080359060200190929190505050612053565b6040518082815260200191505060405180910390f35b34801561080257600080fd5b506108456004803603602081101561081957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061206b565b005b34801561085357600080fd5b5061088a6004803603604081101561086a57600080fd5b810190808035906020019092919080359060200190929190505050612146565b6040518082815260200191505060405180910390f35b3480156108ac57600080fd5b506108b5612176565b604051808215151515815260200191505060405180910390f35b3480156108db57600080fd5b506108e4612189565b005b3480156108f257600080fd5b5061091f6004803603602081101561090957600080fd5b810190808035906020019092919050505061226d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561096d57600080fd5b506109766122e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109c457600080fd5b50610a07600480360360208110156109db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061230c565b6040518082815260200191505060405180910390f35b348015610a2957600080fd5b50610a6c60048036036020811015610a4057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612355565b005b348015610a7a57600080fd5b50610aa760048036036020811015610a9157600080fd5b8101908080359060200190929190505050612472565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610af557600080fd5b50610afe6124a5565b005b348015610b0c57600080fd5b50610b4f60048036036020811015610b2357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506125e9565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610b92578082015181840152602081019050610b77565b505050509050019250505060405180910390f35b348015610bb257600080fd5b50610c16600480360360c0811015610bc957600080fd5b810190808035906020019092919080359060200190929190803515159060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612737565b6040518082815260200191505060405180910390f35b610c5860048036036020811015610c4257600080fd5b8101908080359060200190929190505050612c0c565b6040518082815260200191505060405180910390f35b348015610c7a57600080fd5b50610c8361304b565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610cc3578082015181840152602081019050610ca8565b50505050905090810190601f168015610cf05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610d0a57600080fd5b50610d3760048036036020811015610d2157600080fd5b8101908080359060200190929190505050613084565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610d8557600080fd5b50610db260048036036020811015610d9c57600080fd5b81019080803590602001909291905050506130b7565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610df2578082015181840152602081019050610dd7565b50505050905090810190601f168015610e1f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610e3957600080fd5b50610e6660048036036020811015610e5057600080fd5b810190808035906020019092919050505061317b565b604051808215151515815260200191505060405180910390f35b348015610e8c57600080fd5b50610e956131b3565b6040518082815260200191505060405180910390f35b348015610eb757600080fd5b50610ec06131b9565b6040518082815260200191505060405180910390f35b348015610ee257600080fd5b50610eeb6131bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610f3957600080fd5b50610f6660048036036020811015610f5057600080fd5b81019080803590602001909291905050506131e5565b6040518082815260200191505060405180910390f35b348015610f8857600080fd5b50610fb560048036036020811015610f9f57600080fd5b81019080803590602001909291905050506131fd565b604051808381526020018281526020019250505060405180910390f35b348015610fde57600080fd5b50610fe7613235565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561103557600080fd5b5061106c6004803603604081101561104c57600080fd5b81019080803590602001909291908035906020019092919050505061325b565b6040518082815260200191505060405180910390f35b34801561108e57600080fd5b506110bb600480360360208110156110a557600080fd5b810190808035906020019092919050505061328b565b6040518082815260200191505060405180910390f35b3480156110dd57600080fd5b50611120600480360360208110156110f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506132ab565b6040518082815260200191505060405180910390f35b61116c6004803603604081101561114c57600080fd5b8101908080359060200190929190803590602001909291905050506132c3565b6040518082815260200191505060405180910390f35b34801561118e57600080fd5b506111d1600480360360208110156111a557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134ee565b005b3480156111df57600080fd5b5061120c600480360360208110156111f657600080fd5b810190808035906020019092919050505061358d565b6040518082815260200191505060405180910390f35b34801561122e57600080fd5b5061125b6004803603602081101561124557600080fd5b81019080803590602001909291905050506135ad565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156112a957600080fd5b506112d6600480360360208110156112c057600080fd5b81019080803590602001909291905050506135e0565b6040518082815260200191505060405180910390f35b3480156112f857600080fd5b506113256004803603602081101561130f57600080fd5b81019080803590602001909291905050506135f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561137357600080fd5b506113a06004803603602081101561138a57600080fd5b810190808035906020019092919050505061362b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060405180807f737570706f727473496e74657266616365286279746573342900000000000000815250601901905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611610575060405180807f746f6b656e734f664f776e6572286164647265737329000000000000000000008152506016019050604051809103902060405180807f736166655472616e7366657246726f6d28616464726573732c6164647265737381526020017f2c75696e743235362900000000000000000000000000000000000000000000008152506029019050604051809103902060405180807f617070726f766528616464726573732c75696e743235362900000000000000008152506018019050604051809103902060405180807f6f776e65724f662875696e7432353629000000000000000000000000000000008152506010019050604051809103902060405180807f62616c616e63654f6628616464726573732900000000000000000000000000008152506012019050604051809103902060405180807f746f74616c537570706c79282900000000000000000000000000000000000000815250600d019050604051809103902018181818187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806116c4575060405180807f73796d626f6c28290000000000000000000000000000000000000000000000008152506008019050604051809103902060405180807f6e616d652829000000000000000000000000000000000000000000000000000081525060060190506040518091039020187bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600781526020017f426974766965770000000000000000000000000000000000000000000000000081525081565b600260149054906101000a900460ff1615151561174657600080fd5b611750338261365e565b151561175b57600080fd5b61176581836136ca565b808273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600480549050905090565b6000600160048054905003905090565b60166020528060005260406000206000915090505481565b600085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506101006000825111801561187a575080825111155b151561188557600080fd5b33896005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156118f557600080fd5b6000878760405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506000600e6000838152602001908152602001600020541415156119b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5369676e617475726520416c726561647920557365640000000000000000000081525060200191505060405180910390fd5b600560008d815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018d60405160200180828152602001915050604051602081830303815290604052805190602001208b8b8b60405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611a80573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff16141515611aac57600080fd5b611ab4613a21565b6020604051908101604052808d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050815250905060006001600a839080600181540180825580915050906001820390600052602060002001600090919290919091506000820151816000019080519060200190611b54929190613a35565b5050500390508063ffffffff1681141515611b6e57600080fd5b7fe819187a0cf517f3c23c7bd6e6b11a3aec56ec3f2784dc69ac56ebac668748ee3382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a133600b600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508d600c600083815260200190815260200160002081905550600860008f81526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055508d600e600085815260200190815260200160002081905550809750505050505050509695505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611d0757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611d4357600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611de157600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611e1d57600080fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60116020528060005260406000206000915090505481565b600860205281600052604060002081815481101515611e9457fe5b90600052602060002001600091509150505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611f0457600080fd5b600260149054906101000a900460ff161515611f1f57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff16601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515611f7c57600080fd5b611f84613720565b565b600260149054906101000a900460ff16151515611fa257600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611fde57600080fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415151561201957600080fd5b61202333826137b3565b151561202e57600080fd5b612038838261365e565b151561204357600080fd5b61204e83838361381f565b505050565b600e6020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156120c657600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561210257600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600d6020528160005260406000208181548110151561216157fe5b90600052602060002001600091509150505481565b600260149054906101000a900460ff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156121e557600080fd5b60003073ffffffffffffffffffffffffffffffffffffffff16319050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612269573d6000803e3d6000fd5b5050565b60006005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515156122e157600080fd5b919050565b601860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156123b057600080fd5b600260149054906101000a900460ff1615156123cb57600080fd5b80601860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f450db8da6efbe9c22f2347f7c2021231df1fc58d3ae9a2fa75d39fa44619930581604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600b6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061254d57506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b806125a55750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156125b057600080fd5b600260149054906101000a900460ff161515156125cc57600080fd5b6001600260146101000a81548160ff021916908315150217905550565b606060006125f68361230c565b9050600081141561263a5760006040519080825280602002602001820160405280156126315781602001602082028038833980820191505090505b50915050612732565b60608160405190808252806020026020018201604052801561266b5781602001602082028038833980820191505090505b50905060006126786117f6565b905060008090506000600190505b8281111515612729578673ffffffffffffffffffffffffffffffffffffffff166005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561271c5780848381518110151561270557fe5b906020019060200201818152505081806001019250505b8080600101915050612686565b83955050505050505b919050565b600033876005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156127a957600080fd5b60008585604051602001808381526020018281526020019250505060405160208183030381529060405280519060200120905060008911156128715788601260008381526020019081526020016000205414151515612870576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f5369676e617475726520416c726561647920557365640000000000000000000081525060200191505060405180910390fd5b5b600560008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018b604051602001808281526020019150506040516020818303038152906040528051906020012089898960405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561293e573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1614151561296a57600080fd5b6000339050600073ffffffffffffffffffffffffffffffffffffffff16600b60008c815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515156129de57600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600b60008c815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612a4c57600080fd5b612a54613ab5565b6020604051908101604052808b1515815250905060006001600f8390806001815401808255809150509060018203906000526020600020016000909192909190915060008201518160000160006101000a81548160ff02191690831515021790555050500390508063ffffffff1681141515612acf57600080fd5b7fa10f25ef783c24056e27eb55eb6c0ac1c4863cd5eab7e657cd067926b3dce0648382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1826010600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600d60008d81526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055508b60116000838152602001908152602001600020819055508b60126000868152602001908152602001600020819055508096505050505050509695505050505050565b600034601354808210151515612c2157600080fd5b60003390506000600b600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515612c9a57600080fd5b8173ffffffffffffffffffffffffffffffffffffffff16600b600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151515612d0857600080fd5b612d10613acb565b602060405190810160405280348152509050600060016014839080600181540180825580915050906001820390600052602060002001600090919290919091506000820151816000015550500390508063ffffffff1681141515612d7357600080fd5b836015600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508760166000838152602001908152602001600020819055506000606434604602811515612dee57fe5b0490506000600d60008b815260200190815260200160002080549050823403811515612e1657fe5b049050600b60008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612e92573d6000803e3d6000fd5b5060008090505b600d60008c815260200190815260200160002080549050811015612fcf5760106000600d60008e815260200190815260200160002083815481101515612edb57fe5b9060005260206000200154815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612f5a573d6000803e3d6000fd5b5060176000858152602001908152602001600020600d60008d815260200190815260200160002082815481101515612f8e57fe5b906000526020600020015490806001815401808255809150509060018203906000526020600020016000909192909190915055508080600101915050612e99565b507f6ea1e5e03071ff9bad53b614eafcc00d29db646e9c351fcc00d45a4118d7c51a8684604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a18298505050505050505050919050565b6040805190810160405280600281526020017f425600000000000000000000000000000000000000000000000000000000000081525081565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606000600a838154811015156130ca57fe5b906000526020600020019050806000018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561316e5780601f106131435761010080835404028352916020019161316e565b820191906000526020600020905b81548152906001019060200180831161315157829003601f168201915b5050505050915050919050565b600080600f8381548110151561318d57fe5b9060005260206000200190508060000160009054906101000a900460ff16915050919050565b60035481565b60135481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60126020528060005260406000206000915090505481565b600080600060048481548110151561321157fe5b90600052602060002090600202019050806000015492508060010154915050915091565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60176020528160005260406000208181548110151561327657fe5b90600052602060002001600091509150505481565b600060086000838152602001908152602001600020805490509050919050565b60066020528060005260406000206000915090505481565b6000346003548082101515156132d857600080fd5b8460007f01000000000000000000000000000000000000000000000000000000000000000281600060208110151561330c57fe5b1a7f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415151561335e57600080fd5b8460007f01000000000000000000000000000000000000000000000000000000000000000281600060208110151561339257fe5b1a7f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141515156133e457600080fd5b60003390506133f1613adf565b60408051908101604052808a81526020018981525090506000600160048390806001815401808255809150509060018203906000526020600020906002020160009091929091909150600082015181600001556020820151816001015550500390508063ffffffff168114151561346757600080fd5b7f982bb66d9aa60573bc0a2066122e1466ecbc4c179a5e7c1c5b589345008ce69a8382604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a16134de6000848361381f565b8097505050505050505092915050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561354957600080fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600d6000838152602001908152602001600020805490509050919050565b60156020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c6020528060005260406000206000915090505481565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60106020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008273ffffffffffffffffffffffffffffffffffffffff166005600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b806007600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561377b57600080fd5b600260149054906101000a900460ff16151561379657600080fd5b6000600260146101000a81548160ff021916908315150217905550565b60008273ffffffffffffffffffffffffffffffffffffffff166007600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001019190505550816005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151561397d57600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906001900391905055506007600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b7f70a295484349ac4c2073cdca8ba026869fff31e0d35e268f820e44c9d25f4a2e838383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050565b602060405190810160405280606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613a7657805160ff1916838001178555613aa4565b82800160010185558215613aa4579182015b82811115613aa3578251825591602001919060010190613a88565b5b509050613ab19190613aff565b5090565b6020604051908101604052806000151581525090565b602060405190810160405280600081525090565b604080519081016040528060008019168152602001600080191681525090565b613b2191905b80821115613b1d576000816000905550600101613b05565b5090565b9056fea165627a7a72305820b73bf81476c95567782e45ebae5220573d46c55a9004c11243c470bc91f2d26d0029", - "storage": { - "0x05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa54c2b4154b4f221d71d6d5bc0ec905c931a021bb6fb138fc0495bb0373e2276": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x0000000000000000000000000000000000000001": { - "balance": "0x0", - "nonce": "0", - "code": "0x", - "storage": {} - }, - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0xcec3d4daf44926cc41e", - "nonce": "147795", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "567688", - "difficulty": "2028219", - "timestamp": "1577578023", - "gasLimit": "23504477", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf9018f8302415385746a52880083048196948521f13dd5e4bc3dab3cf0f01a195a5af899e85180b90124200b1e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9af799918107e9a339eba0584b8b60b35aae6f087c74f6bfc00c9301849b204d094ed65e09c76c2597f5516f9440aad2921e50dde096e7caaa65a536d4d9265e00000000000000000000000000000000000000000000000000000000000000504269747669657720697320616e20616d617a696e6720776562736974652e20596f752073686f756c6420646566696e6974656c792061646420796f75722070726f6475637420746f2069742e20e282bf0000000000000000000000000000000081a2a0686e4a69e1fa6cac6b4f751a3935ca5a371d720c34d3a7136988aa017a528ed5a07d993e607b665c24557d0eae166c21fe744e618ed3430902ac6206c63a331dc0", - "result": [ - { - "action": { - "author": "0x0000000000000000000000000000000000000000", - "address": "0x0000000000000000000000000000000000000000", - "balance": "0x0", - "callType": "call", - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "gas": "0x48196", - "input": "0x200b1e64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001b9af799918107e9a339eba0584b8b60b35aae6f087c74f6bfc00c9301849b204d094ed65e09c76c2597f5516f9440aad2921e50dde096e7caaa65a536d4d9265e00000000000000000000000000000000000000000000000000000000000000504269747669657720697320616e20616d617a696e6720776562736974652e20596f752073686f756c6420646566696e6974656c792061646420796f75722070726f6475637420746f2069742e20e282bf00000000000000000000000000000000", - "refundAddress": "0x0000000000000000000000000000000000000000", - "to": "0x8521f13dd5e4bc3dab3cf0f01a195a5af899e851", - "value": "0x0" - }, - "error": "execution reverted", - "result": { - "gasUsed": "0x947c" - }, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json deleted file mode 100644 index 16d43767d..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/suicide.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "genesis": { - "number": "553153", - "hash": "0x88bde20840880a1f3fba92121912a3cc0d3b26d76e4d914fbd85fc2e43da3b3f", - "nonce": "0x7be554ffe4b82fc2", - "mixHash": "0xf73d2ff3c16599c3b8a24b9ebde6c09583b5ee3f747d3cd37845d564f4c8d87a", - "stateRoot": "0x40b5f53d610108947688a04fb68838ff9c0aa0dd6e54156b682537192171ff5c", - "miner": "0x774c398d763161f55b66a646f17edda4addad2ca", - "difficulty": "1928226", - "totalDifficulty": "457857582215", - "extraData": "0xd983010907846765746888676f312e31332e358664617277696e", - "gasLimit": "7999473", - "timestamp": "1577392669", - "alloc": { - "0x877bd459c9b7d8576b44e59e09d076c25946f443": { - "balance": "0x19bb4ac611ca7a1fc881", - "nonce": "701", - "code": "0x", - "storage": {} - }, - "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91": { - "balance": "0x0", - "nonce": "1", - "code": "0x60606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000877bd459c9b7d8576b44e59e09d076c25946f443" - } - } - }, - "config": { - "chainId": 63, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 0, - "eip158Block": 0, - "ethash": {}, - "homesteadBlock": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 301243, - "petersburgBlock": 999983, - "istanbulBlock": 999983 - } - }, - "context": { - "number": "553154", - "difficulty": "1929167", - "timestamp": "1577392670", - "gasLimit": "8000000", - "miner": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "input": "0xf86c8202bd850ee6b280008344aa20948ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91808441c0e1b581a2a03f95ca5cdf7fd727630341c4c6aa1b64ccd9949bd9ecc72cfdd7ce17a2013a69a06d34795ef7fb0108a6dbee4ae0a1bdc48dcd2a4ee53bb6a33d45515af07bb9a8", - "result": [ - { - "action": { - "callType": "call", - "from": "0x877bd459c9b7d8576b44e59e09d076c25946f443", - "gas": "0x44aa20", - "input": "0x41c0e1b5", - "to": "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91", - "value": "0x0" - }, - "blockHash": "0xf641c3b0f82b07cd3a528adb9927dd83eeb4f1682e2bd523ed36888e0d82c9a9", - "blockNumber": 553154, - "result": { - "gasUsed": "0x347a", - "output": "0x" - }, - "subtraces": 1, - "traceAddress": [], - "transactionHash": "0x6af0a5c3188ffacae4d340d4a17e14fdb5a54187683a80ef241bde248189882b", - "transactionPosition": 15, - "type": "call" - }, - { - "action": { - "address": "0x8ee79c5b3f6e1d214d2c4fcf7ea4092a32e26e91", - "balance": "0x0", - "refundAddress": "0x877bd459c9b7d8576b44e59e09d076c25946f443" - }, - "blockHash": "0xf641c3b0f82b07cd3a528adb9927dd83eeb4f1682e2bd523ed36888e0d82c9a9", - "blockNumber": 553154, - "subtraces": 0, - "traceAddress": [ - 0 - ], - "transactionHash": "0x6af0a5c3188ffacae4d340d4a17e14fdb5a54187683a80ef241bde248189882b", - "transactionPosition": 15, - "type": "suicide" - } - ] -} \ No newline at end of file diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json deleted file mode 100644 index a001178a4..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_flat/throw.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "context": { - "difficulty": "117009631", - "gasLimit": "4712388", - "miner": "0x294e5d6c39a36ce38af1dca70c1060f78dee8070", - "number": "25009", - "timestamp": "1479891666" - }, - "genesis": { - "alloc": { - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ecd70668f5d854a", - "code": "0x", - "nonce": "1638", - "storage": {} - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000061a9", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117066792", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0xe23e8d4562a1045b70cbc99fefb20c101a8f0fc8559a80d65fea8896e2f1d46e", - "miner": "0x71842f946b98800fe6feb49f0ae4e253259031c9", - "mixHash": "0x0aada9d6e93dd4db0d09c0488dc0a048fca2ccdc1f3fc7b83ba2a8d393a3a4ff", - "nonce": "0x70849d5838dee2e9", - "number": "25008", - "stateRoot": "0x1e01d2161794768c5b917069e73d86e8dca80cd7f3168c0597de420ab93a3b7b", - "timestamp": "1479891641", - "totalDifficulty": "1896347038589" - }, - "input": "0xf88b8206668504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb8000000000000000000000000000000000000000000000027fad02094277c000029a0692a3b4e7b2842f8dd7832e712c21e09f451f416c8976d5b8d02e8c0c2b4bea9a07645e90fc421b63dd755767fd93d3c03b4ec0c4d8fafa059558d08cf11d59750", - "result": [ - { - "action": { - "callType": "call", - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "value": "0x0" - }, - "blockNumber": 25009, - "error": "invalid jump destination", - "result": {}, - "subtraces": 0, - "traceAddress": [], - "type": "call" - } - ] -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json deleted file mode 100644 index df0b2872b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/create.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "context": { - "difficulty": "3755480783", - "gasLimit": "5401723", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294702", - "timestamp": "1513676146" - }, - "genesis": { - "alloc": { - "0x13e4acefe6a6700604929946e70e6443e4e73447": { - "balance": "0xcf3e0938579f000", - "code": "0x", - "nonce": "9", - "storage": {} - }, - "0x7dc9c9730689ff0b0fd506c67db815f12d90a448": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3757315409", - "extraData": "0x566961425443", - "gasLimit": "5406414", - "hash": "0xae107f592eebdd9ff8d6ba00363676096e6afb0e1007a7d3d0af88173077378d", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0xc927aa05a38bc3de864e95c33b3ae559d3f39c4ccd51cef6f113f9c50ba0caf1", - "nonce": "0x93363bbd2c95f410", - "number": "2294701", - "stateRoot": "0x6b6737d5bde8058990483e915866bd1578014baeff57bd5e4ed228a2bfad635c", - "timestamp": "1513676127", - "totalDifficulty": "7160808139332585" - }, - "input": "0xf907ef098504e3b29200830897be8080b9079c606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a1129a01060f46676a5dff6f407f0f51eb6f37f5c8c54e238c70221e18e65fc29d3ea65a0557b01c50ff4ffaac8ed6e5d31237a4ecbac843ab1bfe8bb0165a0060df7c54f", - "result": { - "from": "0x13e4acefe6a6700604929946e70e6443e4e73447", - "gas": "0x897be", - "gasUsed": "0x897be", - "input": "0x606060405260405160208061077c83398101604052808051906020019091905050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600460006101000a81548160ff02191690831515021790555050610653806101296000396000f300606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029000000000000000000000000c65e620a3a55451316168d57e268f5702ef56a11", - "output": "0x606060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806305e4382a146100855780631c02708d146100ae5780632e1a7d4d146100c35780635114cb52146100e6578063a37dda2c146100fe578063ae200e7914610153578063b5769f70146101a8575b005b341561009057600080fd5b6100986101d1565b6040518082815260200191505060405180910390f35b34156100b957600080fd5b6100c16101d7565b005b34156100ce57600080fd5b6100e460048080359060200190919050506102eb565b005b6100fc6004808035906020019091905050610513565b005b341561010957600080fd5b6101116105d6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561015e57600080fd5b6101666105fc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101b357600080fd5b6101bb610621565b6040518082815260200191505060405180910390f35b60025481565b60011515600460009054906101000a900460ff1615151415156101f957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102a15750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156102ac57600080fd5b6000600460006101000a81548160ff0219169083151502179055506003543073ffffffffffffffffffffffffffffffffffffffff163103600281905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103935750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561039e57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561048357600060025411801561040757506002548111155b151561041257600080fd5b80600254036002819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561047e57600080fd5b610510565b600060035411801561049757506003548111155b15156104a257600080fd5b8060035403600381905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561050f57600080fd5b5b50565b60011515600460009054906101000a900460ff16151514151561053557600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561059657506003548160035401115b80156105bd575080600354013073ffffffffffffffffffffffffffffffffffffffff163110155b15156105c857600080fd5b806003540160038190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600354815600a165627a7a72305820c3b849e8440987ce43eae3097b77672a69234d516351368b03fe5b7de03807910029", - "to": "0x7dc9c9730689ff0b0fd506c67db815f12d90a448", - "type": "CREATE", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json deleted file mode 100644 index 80fc0b0ad..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/deep_calls.json +++ /dev/null @@ -1,415 +0,0 @@ -{ - "context": { - "difficulty": "117066904", - "gasLimit": "4712384", - "miner": "0x1977c248e1014cc103929dd7f154199c916e39ec", - "number": "25001", - "timestamp": "1479891545" - }, - "genesis": { - "alloc": { - "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a600035046302d05d3f811461008a5780630accce061461009c5780631ab9075a146100c757806331ed274614610102578063645a3b7214610133578063772fdae314610155578063a7f4377914610180578063ae5f80801461019e578063c9bded21146101ea578063f905c15a14610231575b61023a610002565b61023c600054600160a060020a031681565b61023a600435602435604435606435608435600254600160a060020a03166000141561024657610002565b61023a600435600254600160a060020a03166000148015906100f8575060025433600160a060020a03908116911614155b156102f457610002565b61023a60043560243560443560643560843560a43560c435600254600160a060020a03166000141561031657610002565b61023a600435602435600254600160a060020a0316600014156103d057610002565b61023a600435602435604435606435608435600254600160a060020a03166000141561046157610002565b61023a60025433600160a060020a0390811691161461051657610002565b61023a6004356024356044356060828152600160a060020a0382169060ff8516907fa6c2f0913db6f79ff0a4365762c61718973b3413d6e40382e704782a9a5099f690602090a3505050565b61023a600435602435600160a060020a038116606090815260ff8316907fee6348a7ec70f74e3d6cba55a53e9f9110d180d7698e9117fc466ae29a43e34790602090a25050565b61023c60035481565b005b6060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061029d57610002565b60408051858152602081018390528151600160a060020a03858116939087169260ff8a16927f5a690ecd0cb15c1c1fd6b6f8a32df0d4f56cb41a54fea7e94020f013595de796929181900390910190a45050505050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061036d57610002565b6040805186815260208101869052808201859052606081018490529051600160a060020a03831691889160ff8b16917fd65d9ddafbad8824e2bbd6f56cc9f4ac27ba60737035c10a321ea2f681c94d47919081900360800190a450505050505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f115610002575050604051511515905061042757610002565b60408051828152905183917fa9c6cbc4bd352a6940479f6d802a1001550581858b310d7f68f7bea51218cda6919081900360200190a25050565b60025460e060020a6313bc6d4b02606090815233600160a060020a0390811660645291909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104b857610002565b80600160a060020a031684600160a060020a03168660ff167f69bdaf789251e1d3a0151259c0c715315496a7404bce9fd0b714674685c2cab78686604051808381526020018281526020019250505060405180910390a45050505050565b600254600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x2cccf5e0538493c235d1c5ef6580f77d99e91396": { - "balance": "0x0", - "code": "0x606060405236156100775760e060020a600035046302d05d3f811461007f57806313bc6d4b146100915780633688a877146100b95780635188f9961461012f5780637eadc976146101545780638ad79680146101d3578063a43e04d814610238578063a7f437791461025e578063e16c7d981461027c575b61029f610002565b6102a1600054600160a060020a031681565b6102be600435600160a060020a03811660009081526002602052604090205460ff165b919050565b6102d26004356040805160208181018352600080835284815260038252835190849020805460026001821615610100026000190190911604601f8101849004840283018401909552848252929390929183018282801561037d5780601f106103525761010080835404028352916020019161037d565b61029f6004356024356000805433600160a060020a039081169116146104a957610002565b61034060043560008181526001602090815260408083205481517ff905c15a0000000000000000000000000000000000000000000000000000000081529151600160a060020a03909116928392839263f905c15a92600483810193919291829003018189876161da5a03f1156100025750506040515195945050505050565b60408051602060248035600481810135601f810185900485028601850190965285855261029f9581359591946044949293909201918190840183828082843750949650505050505050600054600160a060020a0390811633909116146104f657610002565b61029f6004355b600080548190600160a060020a0390811633909116146105a457610002565b61029f60005433600160a060020a0390811691161461072957610002565b6102a1600435600081815260016020526040902054600160a060020a03166100b4565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156103325780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b820191906000526020600020905b81548152906001019060200180831161036057829003601f168201915b505050505090506100b4565b506000828152600160208181526040808420805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a038581168086526002909352818520805460ff191690941790935580517f1ab9075a0000000000000000000000000000000000000000000000000000000081523090931660048401525184939192631ab9075a926024828101939192829003018183876161da5a03f11561000257505060408051602081018690528082019290925243606083015260808083526003908301527f414444000000000000000000000000000000000000000000000000000000000060a0830152517f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d39181900360c00190a15b505050565b600083815260016020526040902054600160a060020a03838116911614156104d0576104a4565b600083815260016020526040812054600160a060020a031614610389576103898361023f565b600082815260036020908152604082208054845182855293839020919360026001831615610100026000190190921691909104601f90810184900483019391929186019083901061056a57805160ff19168380011785555b5061059a9291505b808211156105a05760008155600101610556565b8280016001018555821561054e579182015b8281111561054e57825182600050559160200191906001019061057c565b50505050565b5090565b600083815260016020526040812054600160a060020a031614156105c757610002565b50506000818152600160205260408082205481517fa7f437790000000000000000000000000000000000000000000000000000000081529151600160a060020a0391909116928392839263a7f4377992600483810193919291829003018183876161da5a03f11561000257505050600160005060008460001916815260200190815260200160002060006101000a815490600160a060020a0302191690556002600050600083600160a060020a0316815260200190815260200160002060006101000a81549060ff02191690557f8ac68d4e97d65912f220b4c5f87978b8186320a5e378c1369850b5b5f90323d383834360405180806020018560001916815260200184600160a060020a03168152602001838152602001828103825260038152602001807f44454c000000000000000000000000000000000000000000000000000000000081526020015060200194505050505060405180910390a1505050565b600054600160a060020a0316ff", - "nonce": "1", - "storage": { - "0x0684ac65a9fa32414dda56996f4183597d695987fdb82b145d722743891a6fe8": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "0x1cd76f78169a420d99346e3501dd3e541622c38a226f9b63e01cfebc69879dc7": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "0x8e54a4494fe5da016bfc01363f4f6cdc91013bb5434bd2a4a3359f13a23afa2f": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "0x94edf7f600ba56655fd65fca1f1424334ce369326c1dc3e53151dcd1ad06bc13": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xbbee47108b275f55f98482c6800f6372165e88b0330d3f5dae6419df4734366c": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "0xd38c0c4e84de118cfdcc775130155d83b8bbaaf23dc7f3c83a626b10473213bd": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xfb3aa5c655c2ec9d40609401f88d505d1da61afaa550e36ef5da0509ada257ba": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113" - } - }, - "0x3e9286eafa2db8101246c2131c09b49080d00690": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063056d4470146100e957806316c66cc61461010c5780631ab9075a146101935780633ae1005c146101ce57806358541662146101fe5780635ed61af014610231578063644e3b791461025457806384dbac3b146102db578063949ae479146102fd5780639859387b14610321578063a7f4377914610340578063ab03fc261461035e578063e8161b7814610385578063e964d4e114610395578063f905c15a146103a5578063f92eb774146103ae575b6103be610002565b6103c0600054600160a060020a031681565b6103be6004356002546000908190600160a060020a031681141561040357610002565b6103dd60043560006108365b6040805160025460e360020a631c2d8fb30282527f636f6e747261637464620000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435600254600160a060020a03166000148015906101c4575060025433600160a060020a03908116911614155b1561088d57610002565b6103be600435602435604435606435600254600090819081908190600160a060020a03168114156108af57610002565b6103c0600435602435604435606435608435600254600090819081908190600160a060020a03168114156110e857610002565b6103be6004356002546000908190600160a060020a03168114156115ec57610002565b6103c06004356000611b635b6040805160025460e360020a631c2d8fb30282527f6d61726b6574646200000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b6103be600435602435600254600160a060020a031660001415611bb557610002565b6103be600435602435600254600090600160a060020a0316811415611d2e57610002565b6103be600435600254600160a060020a031660001415611fc657610002565b6103be60025433600160a060020a0390811691161461207e57610002565b6103be600435602435604435600254600090600160a060020a031681141561208c57610002565b6103dd60043560006124b8610260565b6103c0600435600061250a610118565b6103f160035481565b6103f16004356000612561610260565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061046557610002565b8291506104e55b6040805160025460e360020a631c2d8fb30282527f63706f6f6c00000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f115610002575050604051519150505b90565b600160a060020a031663b2206e6d83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fb2206e6d0000000000000000000000000000000000000000000000000000000082526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f11561000257505060405151915061059b90506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f115610002575050506107355b6040805160025460e360020a631c2d8fb30282527f6c6f676d6772000000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b50826120ee5b6040805160025460e360020a631c2d8fb30282527f6163636f756e7463746c0000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316630accce06600684600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150866040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050505050565b600160a060020a03166316c66cc6836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519150505b919050565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061091157610002565b87935061091c610260565b600160a060020a031663bdbdb08685600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fbdbdb0860000000000000000000000000000000000000000000000000000000082526004820152602481018a905290516044808301935060209282900301816000876161da5a03f1156100025750506040515193506109ca90506106ba565b600160a060020a03166381982a7a8885876040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610a3661046c565b600160a060020a03166308636bdb85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517f08636bdb000000000000000000000000000000000000000000000000000000008252600482015260248101889052604481019290925251606482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919450600160a060020a03871692506314baa1b6916024828101926000929190829003018183876161da5a03f11561000257505050610b3561046c565b600160a060020a0316630a3b6ede85600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038d16602482015290516044808301935060209282900301816000876161da5a03f115610002575050604051519150610bd590506106ba565b600160a060020a031663d5b205ce87838b6040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f11561000257505050610c41610118565b600160a060020a031663988db79c888a6040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050610ca5610260565b600160a060020a031663f4f2821b896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610d6f5b6040805160025460e360020a631c2d8fb30282527f747261646564620000000000000000000000000000000000000000000000000060048301529151600092600160a060020a03169163e16c7d98916024828101926020929190829003018187876161da5a03f1156100025750506040515191506104e29050565b600160a060020a0316635f539d69896040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050610dc2610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928e9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610ec5610639565b600160a060020a0316630accce06600386600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6315b1ea01028252915191928e928d9263ad8f500891600482810192602092919082900301816000876161da5a03f11561000257505050604051805190602001506040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050610fc8610639565b600160a060020a031663645a3b7285600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151905061101e610260565b600160a060020a031663f92eb77488600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f115610002575050505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061114a57610002565b604051600254600160a060020a0316908a908a908a908a908a90611579806125b38339018087600160a060020a0316815260200186600160a060020a03168152602001856000191681526020018481526020018381526020018281526020019650505050505050604051809103906000f092506111c5610118565b600160a060020a031663b9858a288a856040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611229610260565b600160a060020a0316635188f99689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611288610260565b600160a060020a031663bdbdb08689896040518360e060020a0281526004018083600019168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750506040515192506112e590506106ba565b600160a060020a03166346d88e7d8a858a6040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506000604051808303816000876161da5a03f115610002575050506113516106ba565b600160a060020a03166381982a7a8a84866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050506113bd61046c565b600160a060020a0316632b58469689856040518360e060020a028152600401808360001916815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f1156100025750505061141c61046c565b600160a060020a03166308636bdb8984866040518460e060020a028152600401808460001916815260200183815260200182600160a060020a0316815260200193505050506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630a5d50db028252600482018190529151919350600160a060020a03861692506314baa1b6916024828101926000929190829003018183876161da5a03f115610002575050506114d3610639565b6040805160e160020a630566670302815260016004820152602481018b9052600160a060020a0386811660448301528c811660648301526000608483018190529251931692630accce069260a480840193919291829003018183876161da5a03f11561000257505050611544610639565b600160a060020a031663645a3b728961155b610260565b600160a060020a031663f92eb7748c6040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448084019360009350829003018183876161da5a03f1156100025750939a9950505050505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061164e57610002565b82915061165961046c565b600160a060020a0316630a3b6ede83600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63051db76f0282526004820152600160a060020a038816602482015290516044808301935060209282900301816000876161da5a03f1156100025750506040515191506116f990506106ba565b600160a060020a031663d5b205ce83600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a636ad902e7028252600160a060020a0390811660048301526024820187905288166044820152905160648281019350600092829003018183876161da5a03f1156100025750505061179b6106ba565b600160a060020a031663d653078983600160a060020a03166336da44686040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517ff1ff78a0000000000000000000000000000000000000000000000000000000008252915191929163f1ff78a09160048181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150866040518460e060020a0281526004018084600160a060020a0316815260200183815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f1156100025750505061189f610260565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506118f2610118565b600160a060020a031663f4f2821b846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050611945610639565b600160a060020a0316630accce06600484600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d02825291519192899290916336da44689181870191602091908190038801816000876161da5a03f115610002575050506040518051906020015060006040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f11561000257505050611a48610639565b600160a060020a031663645a3b7283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611a9e610260565b600160a060020a031663f92eb77486600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b600160a060020a03166381738c59836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611c1757610002565b611c1f610260565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f11561000257505060405151159050611c7457610002565b611c7c610260565b600160a060020a0316632243118a836040518260e060020a02815260040180826000191681526020019150506000604051808303816000876161da5a03f11561000257505050611cca610639565b600160a060020a031663ae5f8080600184846040518460e060020a028152600401808481526020018360001916815260200182600160a060020a0316815260200193505050506000604051808303816000876161da5a03f115610002575050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f1156100025750506040515115159050611d9057610002565b5081611d9a610260565b600160a060020a031663581d5d6084846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506000604051808303816000876161da5a03f11561000257505050611df5610639565b600160a060020a0316630accce06600283600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a630566670302825260048201949094526024810193909352600160a060020a038816604484015260006064840181905260848401819052905160a4808501949293509091829003018183876161da5a03f11561000257505050611eab610639565b600160a060020a031663645a3b7282600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519050611f01610260565b600160a060020a031663f92eb77485600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a633e4baddd028252600482015290516024828101935060209282900301816000876161da5a03f11561000257505060408051805160e060020a86028252600482019490945260248101939093525160448381019360009350829003018183876161da5a03f11561000257505050505050565b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061202857610002565b612030610118565b600160a060020a0316639859387b826040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505050565b600254600160a060020a0316ff5b6040805160025460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f11561000257505060405151151590506106b457610002565b600160a060020a031663d65307898383600160a060020a031663f1ff78a06040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fd6530789000000000000000000000000000000000000000000000000000000008252600160a060020a039485166004830152602482015292891660448401525160648381019360009350829003018183876161da5a03f115610002575050506121a5610118565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506121f8610cf4565b600160a060020a031663f4f2821b856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f1156100025750505061224b610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e360020a6306db488d028252915191928a9290916336da446891600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f1156100025750505080600160a060020a031663ea71b02d6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a031660001490506124b25761239f610639565b600160a060020a0316630accce06600583600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fea71b02d000000000000000000000000000000000000000000000000000000008252915191928a92909163ea71b02d91600482810192602092919082900301816000876161da5a03f1156100025750505060405180519060200150886040518660e060020a028152600401808681526020018560001916815260200184600160a060020a0316815260200183600160a060020a03168152602001828152602001955050505050506000604051808303816000876161da5a03f115610002575050505b50505050565b600160a060020a03166338a699a4836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663213fe2b7836040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191506108889050565b600160a060020a031663f92eb774836040518260e060020a02815260040180826000191681526020019150506020604051808303816000876161da5a03f115610002575050604051519150610888905056606060405260405160c08061157983396101206040819052825160805160a051935160e0516101005160008054600160a060020a03199081163317909155600180546005805484168817905560048a90556006869055600b8590556008849055909116861760a060020a60ff02191690554360038190556002558686526101408390526101608190529396929594919390929091600160a060020a033016917f76885d242fb71c6f74a7e717416e42eff4d96faf54f6de75c6a0a6bbd8890c6b91a230600160a060020a03167fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff600b600050546040518082815260200191505060405180910390a250505050505061145e8061011b6000396000f3606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "16", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ef436dcbda6cd4a", - "code": "0x", - "nonce": "1634", - "storage": {} - }, - "0x7986bad81f4cbd9317f5a46861437dae58d69113": { - "balance": "0x0", - "code": "0x6060604052361561008d5760e060020a600035046302d05d3f811461009557806316c66cc6146100a75780631ab9075a146100d7578063213fe2b7146101125780639859387b1461013f578063988db79c1461015e578063a7f4377914610180578063b9858a281461019e578063c8e40fbf146101c0578063f4f2821b146101e8578063f905c15a14610209575b610212610002565b610214600054600160a060020a031681565b600160a060020a0360043581811660009081526005602052604081205461023193168114610257575060016101e3565b610212600435600254600160a060020a0316600014801590610108575060025433600160a060020a03908116911614155b1561025f57610002565b610214600435600160a060020a03811660009081526004602052604081205460ff16151561027557610002565b610212600435600254600160a060020a03166000141561029b57610002565b610212600435602435600254600160a060020a03166000141561050457610002565b61021260025433600160a060020a0390811691161461056757610002565b610212600435602435600254600160a060020a03166000141561057557610002565b610231600435600160a060020a03811660009081526004602052604090205460ff165b919050565b610212600435600254600090600160a060020a031681141561072057610002565b61024560035481565b005b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060006101e3565b60028054600160a060020a031916821790555b50565b50600160a060020a038181166000908152600460205260409020546101009004166101e3565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506102fe57610002565b600160a060020a03811660009081526004602052604090205460ff161515610272576040516104028061092e833901809050604051809103906000f06004600050600083600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600083600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555050565b600160a060020a03821660009081526004602052604090205460ff1615156104725760405161040280610d30833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a03811660009081526006602052604090208054600160a060020a031916831790555b5050565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506103b957610002565b600254600160a060020a0316ff5b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f11561000257505060405151151590506105d857610002565b600160a060020a03821660009081526004602052604090205460ff1615156106915760405161040280611132833901809050604051809103906000f06004600050600084600160a060020a0316815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555060016004600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff021916908302179055505b600160a060020a03828116600090815260046020819052604080518184205460e060020a630a3b0a4f02825286861693820193909352905161010090920490931692630a3b0a4f926024828101939192829003018183876161da5a03f11561000257505050600160a060020a031660009081526005602052604090208054600160a060020a0319169091179055565b6002546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602482810192602092919082900301816000876161da5a03f115610002575050604051511515905061078357610002565b50600160a060020a0381811660009081526005602090815260408083205490931680835260049091529190205460ff161561080f576040600081812054825160e260020a632e72bafd028152600160a060020a03868116600483015293516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260056020526040812054909116146108545760406000908120600160a060020a0384169091528054600160a060020a03191690555b50600160a060020a0381811660009081526006602090815260408083205490931680835260049091529190205460ff16156108e657600160a060020a038181166000908152604080518183205460e260020a632e72bafd028252868516600483015291516101009092049093169263b9caebf4926024828101939192829003018183876161da5a03f115610002575050505b600160a060020a03828116600090815260066020526040812054909116146105005760406000908120600160a060020a0384169091528054600160a060020a0319169055505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "7", - "storage": { - "0xffc4df2d4f3d2cffad590bed6296406ab7926ca9e74784f74a95191fa069a174": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - }, - "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f": { - "balance": "0x0", - "code": "0x606060405236156100ae5760e060020a600035046302d05d3f81146100b65780631ab9075a146100c85780632b68bb2d146101035780634cc927d7146101c557806351a34eb81461028e57806356ccb6f0146103545780635928d37f1461041d578063599efa6b146104e9578063759297bb146105b2578063771d50e11461067e578063a7f4377914610740578063f905c15a1461075e578063f92eb77414610767578063febf661214610836575b610902610002565b610904600054600160a060020a031681565b610902600435600254600160a060020a03166000148015906100f9575060025433600160a060020a03908116911614155b1561092057610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061094257610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610a0d57610002565b61090260043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ae957610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610bbc57610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610c9657610002565b61090260043560243560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610de057610002565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610ebb57610002565b60025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b02606452610902916000918291600160a060020a03169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f9e57610002565b61090260025433600160a060020a0390811691161461106957610002565b61090e60035481565b61090e60043560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750506040805180517ff92eb774000000000000000000000000000000000000000000000000000000008252600482018790529151919350600160a060020a038416925063f92eb774916024828101926020929190829003018188876161da5a03f11561000257505060405151949350505050565b61090260043560243560443560025460e360020a631c2d8fb302606090815260aa60020a6a18dbdb9d1c9858dd18dd1b026064526000918291600160a060020a039091169063e16c7d989060849060209060248187876161da5a03f1156100025750505060405180519060200150905080600160a060020a03166316c66cc6336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051511515905061107757610002565b005b6060908152602090f35b60408051918252519081900360200190f35b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5ed61af000000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152925190959286169350635ed61af092602483810193919291829003018183876161da5a03f115610002575050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fab03fc2600000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015260248301899052808816604484015292519095928616935063ab03fc2692606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f949ae47900000000000000000000000000000000000000000000000000000000825233600160a060020a0390811660048401526024830188905292519095928616935063949ae47992604483810193919291829003018183876161da5a03f11561000257505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f46d88e7d000000000000000000000000000000000000000000000000000000008252600160a060020a0380891660048401523381166024840152604483018890529251909592861693506346d88e7d92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5315cdde00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a16602484015260448301889052925190959286169350635315cdde92606483810193919291829003018183876161da5a03f115610002575050604080517f5928d37f00000000000000000000000000000000000000000000000000000000815233600160a060020a03908116600483015287166024820152604481018690529051635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517fe68e401c00000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015280891660248401526044830188905292519095928616935063e68e401c92606483810193919291829003018183876161da5a03f1156100025750505050505050565b6040805160025460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f5152f381000000000000000000000000000000000000000000000000000000008252600160a060020a03808a1660048401528089166024840152604483018890523381166064840152925190959286169350635152f38192608483810193919291829003018183876161da5a03f115610002575050505050505050565b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f056d447000000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015292519095928616935063056d447092602483810193919291829003018183876161da5a03f115610002575050505050565b600254600160a060020a0316ff5b6040805160025460e360020a631c2d8fb302825260aa60020a6a18dbdb9d1c9858dd18dd1b0260048301529151600160a060020a03929092169163e16c7d9891602481810192602092909190829003018188876161da5a03f1156100025750506040805180517f3ae1005c00000000000000000000000000000000000000000000000000000000825233600160a060020a039081166004840152808a166024840152808916604484015260648301889052925190959286169350633ae1005c92608483810193919291829003018183876161da5a03f11561000257505050505050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396" - } - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000006195", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5842545553440000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000" - } - }, - "0xcf00ffd997ad14939736f026006498e3f099baaf": { - "balance": "0x0", - "code": "0x606060405236156100cf5760e060020a600035046302d05d3f81146100d7578063031e7f5d146100e95780631ab9075a1461010b5780632243118a1461014657806327aad68a1461016557806338a699a4146101da5780635188f996146101f8578063581d5d601461021e57806381738c5914610246578063977da54014610269578063a07421ce14610288578063a7f43779146102be578063bdbdb086146102dc578063e1c7111914610303578063f4f2821b14610325578063f905c15a1461034a578063f92eb77414610353575b610387610002565b610389600054600160a060020a031681565b610387600435602435600254600160a060020a0316600014156103a857610002565b610387600435600254600160a060020a031660001480159061013c575060025433600160a060020a03908116911614155b1561042957610002565b610387600435600254600160a060020a03166000141561044b57610002565b6102ac60043560008181526004602081815260408320547f524d81d3000000000000000000000000000000000000000000000000000000006060908152610100909104600160a060020a031692839263524d81d3926064928188876161da5a03f1156100025750506040515192506103819050565b61039c60043560008181526004602052604090205460ff165b919050565b6103876004356024356002546000908190600160a060020a031681141561079457610002565b61038760043560243560025460009081908190600160a060020a031681141561080457610002565b61038960043560008181526004602052604081205460ff1615156109e357610002565b610387600435600254600160a060020a0316600014156109fb57610002565b600435600090815260096020526040902054670de0b6b3a764000090810360243502045b60408051918252519081900360200190f35b61038760025433600160a060020a03908116911614610a9257610002565b600435600090815260086020526040902054670de0b6b3a7640000602435909102046102ac565b610387600435602435600254600160a060020a031660001415610aa057610002565b61038760043560025460009081908190600160a060020a0316811415610b3657610002565b6102ac60035481565b6102ac600435600081815260076020908152604080832054600690925290912054670de0b6b3a76400000204805b50919050565b005b600160a060020a03166060908152602090f35b15156060908152602090f35b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506103fe57610002565b60008281526004602052604090205460ff16151561041b57610002565b600860205260406000205550565b6002805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f11561000257505060405151151590506104a157610002565b604080516000838152600460205291909120805460ff1916600117905561040280610de2833901809050604051809103906000f0600460005060008360001916815260200190815260200160002060005060000160016101000a815481600160a060020a030219169083021790555066470de4df8200006008600050600083600019168152602001908152602001600020600050819055506703782dace9d9000060096000506000836000191681526020019081526020016000206000508190555050565b600460005060008560001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151821415905061060057838152600660209081526040808320839055600790915281208190555b81600160a060020a0316630a3b0a4f846040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f11561000257505050600160a060020a038316808252600560209081526040808420879055805160e160020a6364a81ff102815290518694670de0b6b3a7640000949363c9503fe29360048181019492939183900301908290876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008660001916815260200190815260200160002060008282825054019250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000866000191681526020019081526020016000206000828282505401925050819055505b50505050565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f11561000257505060405151151590506107e957610002565b8381526004602052604081205460ff16151561056657610002565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f115610002575050604051511515905061085957610002565b849250670de0b6b3a764000083600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575060408051805160e160020a6364a81ff102825291519189028590049650600481810192602092909190829003018188876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b9391600481810192602092909190829003018189876161da5a03f115610002575050506040518051906020015002049050806006600050600085600160a060020a0316632e94420f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750604080518051855260208681528286208054989098039097557f2e94420f00000000000000000000000000000000000000000000000000000000815290518896600483810193919291829003018187876161da5a03f115610002575050604080515183526020939093525020805490910190555050505050565b60409020546101009004600160a060020a03166101f3565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610a5157610002565b60008181526004602052604090205460ff161515610a6e57610002565b6040600020805474ffffffffffffffffffffffffffffffffffffffffff1916905550565b600254600160a060020a0316ff5b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b906084906020906024816000876161da5a03f1156100025750506040515115159050610af657610002565b60008281526004602052604090205460ff161515610b1357610002565b670de0b6b3a7640000811115610b2857610002565b600960205260406000205550565b60025460e060020a6313bc6d4b02606090815233600160a060020a03908116606452909116906313bc6d4b9060849060209060248187876161da5a03f1156100025750506040515115159050610b8b57610002565b600160a060020a038416815260056020908152604080832054808452600490925282205490935060ff161515610bc057610002565b600460005060008460001916815260200190815260200160002060005060000160019054906101000a9004600160a060020a0316915081600160a060020a031663b9caebf4856040518260e060020a0281526004018082600160a060020a031681526020019150506000604051808303816000876161da5a03f115610002575050506005600050600085600160a060020a0316815260200190815260200160002060005060009055839050600082600160a060020a031663524d81d36040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519190911115905061078e57670de0b6b3a764000081600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e060020a636f265b930282529151919291636f265b939160048181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001500204600660005060008560001916815260200190815260200160002060008282825054039250508190555080600160a060020a031663c9503fe26040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015060076000506000856000191681526020019081526020016000206000828282505403925050819055505050505056606060405260008054600160a060020a031916331790556103de806100246000396000f3606060405236156100615760e060020a600035046302d05d3f81146100695780630a3b0a4f1461007b5780630d327fa7146100f6578063524d81d314610109578063a7f4377914610114578063b9caebf414610132578063bbec3bae14610296575b6102ce610002565b6102d0600054600160a060020a031681565b6102ce600435600254600090600160a060020a03168114156102ed5760028054600160a060020a03199081168417808355600160a060020a03808616855260036020526040852060018101805493831694909316939093179091559154815461010060a860020a031916921661010002919091179055610372565b6102d0600254600160a060020a03165b90565b6102e3600154610106565b6102ce60005433600160a060020a039081169116146103c657610002565b6102ce600435600160a060020a038116600090815260036020526040812054819060ff16801561016457506001548190115b1561029157506040808220600180820154915461010090819004600160a060020a039081168087528587209093018054600160a060020a031916948216948517905583865293909420805461010060a860020a03191694820294909417909355600254909190811690841614156101e85760028054600160a060020a031916821790555b600254600160a060020a0390811690841614156102105760028054600160a060020a03191690555b6003600050600084600160a060020a0316815260200190815260200160002060006000820160006101000a81549060ff02191690556000820160016101000a815490600160a060020a0302191690556001820160006101000a815490600160a060020a03021916905550506001600081815054809291906001900391905055505b505050565b600160a060020a036004358181166000908152600360205260408120600101546002546102d09491821691168114156103d4576103d8565b005b600160a060020a03166060908152602090f35b6060908152602090f35b60028054600160a060020a03908116835260036020526040808420805461010060a860020a0319808216610100808a029190911790935590829004841680875283872060019081018054600160a060020a03199081168b179091559654868a168952949097209687018054949095169390951692909217909255835416908202179091555b60016003600050600084600160a060020a0316815260200190815260200160002060005060000160006101000a81548160ff0219169083021790555060016000818150548092919060010191905055505050565b600054600160a060020a0316ff5b8091505b5091905056", - "nonce": "3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x3571d73f14f31a1463bd0a2f92f7fde1653d4e1ead7aedf4b0a5df02f16092ab": "0x0000000000000000000000000000000000000000000007d634e4c55188be0000", - "0x4e64fe2d1b72d95a0a31945cc6e4f4e524ac5ad56d6bd44a85ec7bc9cc0462c0": "0x000000000000000000000000000000000000000000000002b5e3af16b1880000" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117124093", - "extraData": "0xd5830105008650617269747986312e31322e31826d61", - "gasLimit": "4707788", - "hash": "0xad325e4c49145fb7a4058a68ac741cc8607a71114e23fc88083c7e881dd653e7", - "miner": "0x00714b9ac97fd6bd9325a059a70c9b9fa94ce050", - "mixHash": "0x0af918f65cb4af04b608fc1f14a849707696986a0e7049e97ef3981808bcc65f", - "nonce": "0x38dee147326a8d40", - "number": "25000", - "stateRoot": "0xc5d6bbcd46236fcdcc80b332ffaaa5476b980b01608f9708408cfef01b58bd5b", - "timestamp": "1479891517", - "totalDifficulty": "1895410389427" - }, - "input": "0xf88b8206628504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb80000000000000000000000000000000000000000000000280faf689c35ac00002aa0a7ee5b7877811bf671d121b40569462e722657044808dc1d6c4f1e4233ec145ba0417e7543d52b65738d9df419cbe40a708424f4d54b0fc145c0a64545a2bb1065", - "result": { - "calls": [ - { - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x31217", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e7472616374617069000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x2a68d", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23ac9", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e7472616374646200000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000007986bad81f4cbd9317f5a46861437dae58d69113", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x23366", - "gasUsed": "0x273", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x7986bad81f4cbd9317f5a46861437dae58d69113", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x29f35", - "gasUsed": "0xf8d", - "input": "0x16c66cc6000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x28a9e", - "gasUsed": "0x334", - "input": "0xe16c7d98636f6e747261637463746c000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x21d79", - "gasUsed": "0x24d", - "input": "0x13bc6d4b000000000000000000000000b4fe7aa695b326c9d219158d2ca50db77b39f99f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x2165b", - "gasUsed": "0x334", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a8e8", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1a2c6", - "gasUsed": "0x3cb", - "input": "0xc9503fe2", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19b72", - "gasUsed": "0x3cb", - "input": "0xc9503fe2", - "output": "0x0000000000000000000000000000000000000000000000008ac7230489e80000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x19428", - "gasUsed": "0x305", - "input": "0x6f265b93", - "output": "0x0000000000000000000000000000000000000000000000283c7b9181eca20000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x18d45", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "gas": "0x1734e", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x20ee1", - "gasUsed": "0x5374", - "input": "0x581d5d60000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "output": "0x", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1b6c1", - "gasUsed": "0x334", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1af69", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x143a5", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1a91d", - "gasUsed": "0x12fa", - "input": "0x0accce0600000000000000000000000000000000000000000000000000000000000000025842545553440000000000000000000000000000000000000000000000000000000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x19177", - "gasUsed": "0x334", - "input": "0xe16c7d986c6f676d67720000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000002a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18a22", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x18341", - "gasUsed": "0x334", - "input": "0xe16c7d986d61726b65746462000000000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000cf00ffd997ad14939736f026006498e3f099baaf", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x17bec", - "gasUsed": "0x229", - "input": "0x2e94420f", - "output": "0x5842545553440000000000000000000000000000000000000000000000000000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - }, - { - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x1764e", - "gasUsed": "0x45c", - "input": "0xf92eb7745842545553440000000000000000000000000000000000000000000000000000", - "output": "0x00000000000000000000000000000000000000000000002816d180e30c390000", - "to": "0xcf00ffd997ad14939736f026006498e3f099baaf", - "type": "CALL", - "value": "0x0" - }, - { - "calls": [ - { - "from": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "gas": "0x108ba", - "gasUsed": "0x24d", - "input": "0x13bc6d4b0000000000000000000000003e9286eafa2db8101246c2131c09b49080d00690", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x2cccf5e0538493c235d1c5ef6580f77d99e91396", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "gas": "0x16e62", - "gasUsed": "0xebb", - "input": "0x645a3b72584254555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002816d180e30c390000", - "output": "0x", - "to": "0x2a98c5f40bfa3dee83431103c535f6fae9a8ad38", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "gas": "0x283b9", - "gasUsed": "0xc51c", - "input": "0x949ae479000000000000000000000000c212e03b9e060e36facad5fd8f4435412ca22e6b0000000000000000000000000000000000000000000000280faf689c35ac0000", - "output": "0x", - "to": "0x3e9286eafa2db8101246c2131c09b49080d00690", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "gas": "0x30b4a", - "gasUsed": "0xedb7", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "output": "0x", - "to": "0xb4fe7aa695b326c9d219158d2ca50db77b39f99f", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "gasUsed": "0x1810b", - "input": "0x51a34eb80000000000000000000000000000000000000000000000280faf689c35ac0000", - "output": "0x", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json deleted file mode 100644 index 2cd28bacc..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/delegatecall.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "context": { - "difficulty": "31927752", - "gasLimit": "4707788", - "miner": "0x5659922ce141eedbc2733678f9806c77b4eebee8", - "number": "11495", - "timestamp": "1479735917" - }, - "genesis": { - "alloc": { - "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a60003504630a0313a981146100875780630a3b0a4f146101095780630cd40fea1461021257806329092d0e1461021f5780634cd06a5f146103295780635dbe47e8146103395780637a9e5410146103d9578063825db5f7146103e6578063a820b44d146103f3578063efa52fb31461047a575b610002565b34610002576104fc600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a26333556e849091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f415610002575050604051519150505b919050565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f21ce24d4000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926321ce24d49260448082019391829003018186803b156100025760325a03f415610002575050505b50565b3461000257610512600181565b346100025761051060043560006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a2637d65837a9091336000604051602001526040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515115905061008257604080517f89489a87000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a038416602483015291517342b02b5deeb78f34cd5ac896473b63e6c99a71a2926389489a879260448082019391829003018186803b156100025760325a03f4156100025750505061020f565b3461000257610528600435610403565b34610002576104fc600435604080516000602091820181905282517f7d65837a00000000000000000000000000000000000000000000000000000000815260048101829052600160a060020a0385166024820152925190927342b02b5deeb78f34cd5ac896473b63e6c99a71a292637d65837a92604480840193829003018186803b156100025760325a03f4156100025750506040515191506101049050565b3461000257610512600c81565b3461000257610512600081565b3461000257610528600061055660005b600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263685a1f3c9091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b346100025761053a600435600060006000507342b02b5deeb78f34cd5ac896473b63e6c99a71a263f775b6b59091846000604051602001526040518360e060020a028152600401808381526020018281526020019250505060206040518083038186803b156100025760325a03f4156100025750506040515191506101049050565b604080519115158252519081900360200190f35b005b6040805160ff9092168252519081900360200190f35b60408051918252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b90509056", - "nonce": "1", - "storage": { - "0x4d140b25abf3c71052885c66f73ce07cff141c1afabffdaf5cba04d625b7ebcc": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "0x269296dddce321a6bcbaa2f0181127593d732cba": { - "balance": "0x0", - "code": "0x606060405236156101275760e060020a60003504630cd40fea811461012c578063173825d9146101395780631849cb5a146101c7578063285791371461030f5780632a58b3301461033f5780632cb0d48a146103565780632f54bf6e1461036a578063332b9f061461039d5780633ca8b002146103c55780633df4ddf4146103d557806341c0e1b5146103f457806347799da81461040557806362a51eee1461042457806366907d13146104575780637065cb48146104825780637a9e541014610496578063825db5f7146104a3578063949d225d146104b0578063a51687df146104c7578063b4da4e37146104e6578063b4e6850b146104ff578063bd7474ca14610541578063e75623d814610541578063e9938e1114610555578063f5d241d314610643575b610002565b3461000257610682600181565b34610002576106986004356106ff335b60006001600a9054906101000a9004600160a060020a0316600160a060020a0316635dbe47e8836000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100025760325a03f1156100025750506040515191506103989050565b3461000257604080516101008082018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a0360043581168752600586529589902089519788018a528054808816808a52605060020a91829004600160a060020a0316978a01889052600183015463ffffffff8082169d8c018e905264010000000082048116988c01899052604060020a90910416958a018690526002830154948a01859052600390920154808916938a01849052049096169690970186905293969495949293604080516001605060020a03998a16815297891660208901529590971686860152600160a060020a03909316606086015263ffffffff9182166080860152811660a08501521660c083015260e08201929092529051908190036101000190f35b346100025761069a60043560018054600091829160ff60f060020a909104161515141561063d5761072833610376565b34610002576106ae6004546001605060020a031681565b34610002576106986004356108b333610149565b346100025761069a6004355b600160a060020a03811660009081526002602052604090205460ff1615156001145b919050565b34610002576106986001805460ff60f060020a9091041615151415610913576108ed33610376565b346100025761069a600435610149565b34610002576106ae6003546001605060020a03605060020a9091041681565b346100025761069861091533610149565b34610002576106ae6003546001605060020a0360a060020a9091041681565b346100025761069a60043560243560018054600091829160ff60f060020a909104161515141561095e5761092633610376565b34610002576106986004356001805460ff60f060020a909104161515141561072557610a8b33610376565b3461000257610698600435610aa533610149565b3461000257610682600c81565b3461000257610682600081565b34610002576106ae6003546001605060020a031681565b34610002576106ca600154600160a060020a03605060020a9091041681565b346100025761069a60015460ff60f060020a9091041681565b346100025761069a60043560243560443560643560843560a43560c43560018054600091829160ff60f060020a9091041615151415610b5857610ad233610376565b3461000257610698600435610bd633610149565b34610002576106e6600435604080516101008181018352600080835260208084018290528385018290526060808501839052608080860184905260a080870185905260c080880186905260e09788018690526001605060020a03808b168752600586529589902089519788018a5280548088168952600160a060020a03605060020a918290041696890196909652600181015463ffffffff8082169b8a019b909b5264010000000081048b1695890195909552604060020a90940490981691860182905260028301549086015260039091015480841696850196909652940416918101919091525b50919050565b346100025761069a60043560243560443560643560843560a43560018054600091829160ff60f060020a9091041615151415610c8e57610bfb33610376565b6040805160ff9092168252519081900360200190f35b005b604080519115158252519081900360200190f35b604080516001605060020a039092168252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b6040805163ffffffff9092168252519081900360200190f35b1561012757600160a060020a0381166000908152600260205260409020805460ff191690555b50565b1561063d57506001605060020a0380831660009081526005602052604090208054909116151561075b576000915061063d565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610817905b8051600354600090819060016001605060020a0390911611610c995760038054605060020a60f060020a0319169055610ddf565b600380546001605060020a031981166000196001605060020a03928316011782558416600090815260056020526040812080547fffff000000000000000000000000000000000000000000000000000000000000168155600181810180546bffffffffffffffffffffffff191690556002820192909255909101805473ffffffffffffffffffffffffffffffffffffffff19169055915061063d565b1561012757600180547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f060020a8302179055610725565b1561091357600480546001605060020a031981166001605060020a039091166001011790555b565b156101275733600160a060020a0316ff5b1561095e57506001605060020a03808416600090815260056020526040902080549091161515610965576000915061095e565b600191505b5092915050565b60038101546001605060020a0384811691161415610986576001915061095e565b604080516101008101825282546001605060020a038082168352600160a060020a03605060020a92839004166020840152600185015463ffffffff80821695850195909552640100000000810485166060850152604060020a90049093166080830152600284015460a0830152600384015480841660c08401520490911660e0820152610a12906107e3565b61095983825b80546003546001605060020a0391821691600091161515610de55760038054605060020a60a060020a031916605060020a84021760a060020a69ffffffffffffffffffff02191660a060020a84021781558301805473ffffffffffffffffffffffffffffffffffffffff19169055610ddf565b1561072557600480546001605060020a0319168217905550565b1561012757600160a060020a0381166000908152600260205260409020805460ff19166001179055610725565b15610b5857506001605060020a038088166000908152600560205260409020805490911615610b645760009150610b58565b6004546001605060020a0390811690891610610b3057600480546001605060020a03191660018a011790555b6003805460016001605060020a03821681016001605060020a03199092169190911790915591505b50979650505050505050565b80546001605060020a0319168817605060020a60f060020a031916605060020a880217815560018101805463ffffffff1916871767ffffffff0000000019166401000000008702176bffffffff00000000000000001916604060020a860217905560028101839055610b048982610a18565b156101275760018054605060020a60f060020a031916605060020a8302179055610725565b15610c8e57506001605060020a03808816600090815260056020526040902080549091161515610c2e5760009150610c8e565b8054605060020a60f060020a031916605060020a88021781556001808201805463ffffffff1916881767ffffffff0000000019166401000000008802176bffffffff00000000000000001916604060020a87021790556002820184905591505b509695505050505050565b6003546001605060020a03848116605060020a909204161415610d095760e084015160038054605060020a928302605060020a60a060020a031990911617808255919091046001605060020a031660009081526005602052604090200180546001605060020a0319169055610ddf565b6003546001605060020a0384811660a060020a909204161415610d825760c08401516003805460a060020a92830260a060020a69ffffffffffffffffffff021990911617808255919091046001605060020a03166000908152600560205260409020018054605060020a60a060020a0319169055610ddf565b505060c082015160e08301516001605060020a0380831660009081526005602052604080822060039081018054605060020a60a060020a031916605060020a8702179055928416825290200180546001605060020a031916831790555b50505050565b6001605060020a0384161515610e6457600380546001605060020a03605060020a9182900481166000908152600560205260409020830180546001605060020a0319908116871790915583548785018054918590049093168402605060020a60a060020a03199182161790911690915582549185029116179055610ddf565b506001605060020a038381166000908152600560205260409020600390810180549185018054605060020a60a060020a0319908116605060020a94859004909516808502959095176001605060020a0319168817909155815416918402919091179055801515610ef4576003805460a060020a69ffffffffffffffffffff02191660a060020a8402179055610ddf565b6003808401546001605060020a03605060020a9091041660009081526005602052604090200180546001605060020a031916831790555050505056", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000113204f5d64c28326fd7bd05fd4ea855302d7f2ff00000000000000000000" - } - }, - "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2": { - "balance": "0x0", - "code": "0x6504032353da7150606060405236156100695760e060020a60003504631bf7509d811461006e57806321ce24d41461008157806333556e84146100ec578063685a1f3c146101035780637d65837a1461011757806389489a8714610140578063f775b6b5146101fc575b610007565b61023460043560006100fd82600061010d565b610246600435602435600160a060020a03811660009081526020839052604081205415156102cb57826001016000508054806001018281815481835581811511610278576000838152602090206102789181019083015b808211156102d057600081556001016100d8565b610248600435602435600182015481105b92915050565b6102346004356024355b60018101906100fd565b610248600435602435600160a060020a03811660009081526020839052604090205415156100fd565b61024660043560243580600160a060020a031632600160a060020a03161415156101f857600160a060020a038116600090815260208390526040902054156101f857600160a060020a038116600090815260208390526040902054600183018054909160001901908110156100075760009182526020808320909101805473ffffffffffffffffffffffffffffffffffffffff19169055600160a060020a038316825283905260408120556002820180546000190190555b5050565b61025c60043560243560008260010160005082815481101561000757600091825260209091200154600160a060020a03169392505050565b60408051918252519081900360200190f35b005b604080519115158252519081900360200190f35b60408051600160a060020a039092168252519081900360200190f35b50505060009283526020808420909201805473ffffffffffffffffffffffffffffffffffffffff191686179055600160a060020a0385168352908590526040909120819055600284018054600101905590505b505050565b509056", - "nonce": "1", - "storage": {} - }, - "0xa529806c67cc6486d4d62024471772f47f6fd672": { - "balance": "0x67820e39ac8fe9800", - "code": "0x", - "nonce": "68", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "31912170", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0x0855914bdc581bccdc62591fd438498386ffb59ea4d5361ed5c3702e26e2c72f", - "miner": "0x334391aa808257952a462d1475562ee2106a6c90", - "mixHash": "0x64bb70b8ca883cadb8fbbda2c70a861612407864089ed87b98e5de20acceada6", - "nonce": "0x684129f283aaef18", - "number": "11494", - "stateRoot": "0x7057f31fe3dab1d620771adad35224aae43eb70e94861208bc84c557ff5b9d10", - "timestamp": "1479735912", - "totalDifficulty": "90744064339" - }, - "input": "0xf889448504a817c800832dc6c094269296dddce321a6bcbaa2f0181127593d732cba80a47065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e29a080ed81e4c5e9971a730efab4885566e2c868cd80bd4166d0ed8c287fdf181650a069d7c49215e3d4416ad239cd09dbb71b9f04c16b33b385d14f40b618a7a65115", - "result": { - "calls": [ - { - "calls": [ - { - "from": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "gas": "0x2bf459", - "gasUsed": "0x2aa", - "input": "0x7d65837a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x42b02b5deeb78f34cd5ac896473b63e6c99a71a2", - "type": "DELEGATECALL" - } - ], - "from": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "gas": "0x2cae73", - "gasUsed": "0xa9d", - "input": "0x5dbe47e8000000000000000000000000a529806c67cc6486d4d62024471772f47f6fd672", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x13204f5d64c28326fd7bd05fd4ea855302d7f2ff", - "type": "CALL", - "value": "0x0" - } - ], - "from": "0xa529806c67cc6486d4d62024471772f47f6fd672", - "gas": "0x2dc6c0", - "gasUsed": "0xbd55", - "input": "0x7065cb480000000000000000000000001523e55a1ca4efbae03355775ae89f8d7699ad9e", - "output": "0x", - "to": "0x269296dddce321a6bcbaa2f0181127593d732cba", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json deleted file mode 100644 index 07fda21d4..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_create_oog_outer_throw.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "context": { - "difficulty": "3451177886", - "gasLimit": "4709286", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2290744", - "timestamp": "1513616439" - }, - "genesis": { - "alloc": { - "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a": { - "balance": "0x0", - "code": "0x606060405263ffffffff60e060020a6000350416633b91f50681146100505780635bb47808146100715780635f51fca01461008c578063bc7647a9146100ad578063f1bd0d7a146100c8575b610000565b346100005761006f600160a060020a03600435811690602435166100e9565b005b346100005761006f600160a060020a0360043516610152565b005b346100005761006f600160a060020a036004358116906024351661019c565b005b346100005761006f600160a060020a03600435166101fa565b005b346100005761006f600160a060020a0360043581169060243516610db8565b005b600160a060020a038083166000908152602081905260408120549091908116903316811461011657610000565b839150600160a060020a038316151561012d573392505b6101378284610e2e565b6101418284610db8565b61014a826101fa565b5b5b50505050565b600154600160a060020a03908116903316811461016e57610000565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b5b5050565b600254600160a060020a0390811690331681146101b857610000565b600160a060020a038381166000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19169184169190911790555b5b505050565b6040805160e260020a631a481fc102815260016024820181905260026044830152606482015262093a8060848201819052600060a4830181905260c06004840152601e60c48401527f736574456e7469747953746174757328616464726573732c75696e743829000060e484015292519091600160a060020a038516916369207f049161010480820192879290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526000602482018190526001604483015260606004830152602360648301527f626567696e506f6c6c28616464726573732c75696e7436342c626f6f6c2c626f60848301527f6f6c29000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f61646453746f636b28616464726573732c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601960c48201527f697373756553746f636b2875696e74382c75696e74323536290000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602160648301527f6772616e7453746f636b2875696e74382c75696e743235362c61646472657373608483015260f860020a60290260a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f115610000575050604080517f010555b8000000000000000000000000000000000000000000000000000000008152600160a060020a03338116602483015260006044830181905260606004840152603c60648401527f6772616e7456657374656453746f636b2875696e74382c75696e743235362c6160848401527f6464726573732c75696e7436342c75696e7436342c75696e743634290000000060a48401529251908716935063010555b89260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152601260c48201527f626567696e53616c65286164647265737329000000000000000000000000000060e48201529051600160a060020a03861692506369207f04916101048082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601a60648301527f7472616e7366657253616c6546756e64732875696e743235362900000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260016024820181905260026044830152606482015267ffffffffffffffff8416608482015260ff851660a482015260c06004820152602d60c48201527f7365744163636f756e74696e6753657474696e67732875696e743235362c756960e48201527f6e7436342c75696e7432353629000000000000000000000000000000000000006101048201529051600160a060020a03861692506369207f04916101248082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152603460648301527f637265617465526563757272696e6752657761726428616464726573732c756960848301527f6e743235362c75696e7436342c737472696e672900000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152601b60648301527f72656d6f7665526563757272696e675265776172642875696e7429000000000060848301529151600160a060020a038716935063de64e15c9260a48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a63379938570281526002602482015260006044820181905260606004830152602360648301527f697373756552657761726428616464726573732c75696e743235362c7374726960848301527f6e6729000000000000000000000000000000000000000000000000000000000060a48301529151600160a060020a038716935063de64e15c9260c48084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f61737369676e53746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a6337993857028152600160248201819052604482015260606004820152602260648201527f72656d6f766553746f636b2875696e74382c616464726573732c75696e743235608482015260f060020a6136290260a48201529051600160a060020a038616925063de64e15c9160c48082019260009290919082900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc102815260026024808301919091526003604483015260006064830181905267ffffffffffffffff8616608484015260ff871660a484015260c0600484015260c48301919091527f7365744164647265737342796c617728737472696e672c616464726573732c6260e48301527f6f6f6c29000000000000000000000000000000000000000000000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152602160c48301527f73657453746174757342796c617728737472696e672c75696e74382c626f6f6c60e483015260f860020a6029026101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f1156100005750506040805160e260020a631a481fc1028152600260248201526003604482015260006064820181905267ffffffffffffffff8516608483015260ff861660a483015260c06004830152603860c48301527f736574566f74696e6742796c617728737472696e672c75696e743235362c756960e48301527f6e743235362c626f6f6c2c75696e7436342c75696e74382900000000000000006101048301529151600160a060020a03871693506369207f04926101248084019391929182900301818387803b156100005760325a03f115610000575050505b505050565b604080517f225553a4000000000000000000000000000000000000000000000000000000008152600160a060020a0383811660048301526002602483015291519184169163225553a49160448082019260009290919082900301818387803b156100005760325a03f115610000575050505b5050565b600082604051611fd280610f488339600160a060020a03909216910190815260405190819003602001906000f0801561000057905082600160a060020a03166308b027418260016040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b156100005760325a03f115610000575050604080517fa14e3ee300000000000000000000000000000000000000000000000000000000815260006004820181905260016024830152600160a060020a0386811660448401529251928716935063a14e3ee39260648084019382900301818387803b156100005760325a03f115610000575050505b5050505600606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029a165627a7a723058200e78a5f7e0f91739035d0fbf5eca02f79377210b722f63431f29a22e2880b3bd0029", - "nonce": "789", - "storage": { - "0xfe9ec0542a1c009be8b1f3acf43af97100ffff42eb736850fb038fa1151ad4d9": "0x000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8" - } - }, - "0x5cb4a6b902fcb21588c86c3517e797b07cdaadb9": { - "balance": "0x0", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe4a13bc304682a903e9472f469c33801dd18d9e8": { - "balance": "0x33c763c929f62c4f", - "code": "0x", - "nonce": "14", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3451177886", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4713874", - "hash": "0x5d52a672417cd1269bf4f7095e25dcbf837747bba908cd5ef809dc1bd06144b5", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x01a12845ed546b94a038a7a03e8df8d7952024ed41ccb3db7a7ade4abc290ce1", - "nonce": "0x28c446f1cb9748c1", - "number": "2290743", - "stateRoot": "0x4898aceede76739daef76448a367d10015a2c022c9e7909b99a10fbf6fb16708", - "timestamp": "1513616414", - "totalDifficulty": "7146523769022564" - }, - "input": "0xf8aa0e8509502f9000830493e0941d3ddf7caf024f253487e18bc4a15b1a360c170a80b8443b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e829a0524564944fa419f5c189b5074044f89210c6d6b2d77ee8f7f12a927d59b636dfa0015b28986807a424b18b186ee6642d76739df36cad802d20e8c00e79a61d7281", - "result": { - "calls": [ - { - "error": "internal failure", - "from": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "gas": "0x39ff0", - "gasUsed": "0x39ff0", - "input": "0x606060405234620000005760405160208062001fd283398101604052515b805b600a8054600160a060020a031916600160a060020a0383161790555b506001600d819055600e81905560408051808201909152600c8082527f566f74696e672053746f636b00000000000000000000000000000000000000006020928301908152600b805460008290528251601860ff1990911617825590947f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9600291831615610100026000190190921604601f0193909304830192906200010c565b828001600101855582156200010c579182015b828111156200010c578251825591602001919060010190620000ef565b5b50620001309291505b808211156200012c576000815560010162000116565b5090565b50506040805180820190915260038082527f43565300000000000000000000000000000000000000000000000000000000006020928301908152600c805460008290528251600660ff1990911617825590937fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c760026001841615610100026000190190931692909204601f010481019291620001f7565b82800160010185558215620001f7579182015b82811115620001f7578251825591602001919060010190620001da565b5b506200021b9291505b808211156200012c576000815560010162000116565b5090565b50505b505b611da280620002306000396000f3006060604052361561019a5763ffffffff60e060020a600035041662e1986d811461019f57806302a72a4c146101d657806306eb4e421461020157806306fdde0314610220578063095ea7b3146102ad578063158ccb99146102dd57806318160ddd146102f85780631cf65a781461031757806323b872dd146103365780632c71e60a1461036c57806333148fd6146103ca578063435ebc2c146103f55780635eeb6e451461041e578063600e85b71461043c5780636103d70b146104a157806362c1e46a146104b05780636c182e99146104ba578063706dc87c146104f057806370a082311461052557806377174f851461055057806395d89b411461056f578063a7771ee3146105fc578063a9059cbb14610629578063ab377daa14610659578063b25dbb5e14610685578063b89a73cb14610699578063ca5eb5e1146106c6578063cbcf2e5a146106e1578063d21f05ba1461070e578063d347c2051461072d578063d96831e114610765578063dd62ed3e14610777578063df3c211b146107a8578063e2982c21146107d6578063eb944e4c14610801575b610000565b34610000576101d4600160a060020a036004351660243567ffffffffffffffff6044358116906064358116906084351661081f565b005b34610000576101ef600160a060020a0360043516610a30565b60408051918252519081900360200190f35b34610000576101ef610a4f565b60408051918252519081900360200190f35b346100005761022d610a55565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516602435610ae3565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516610b4e565b005b34610000576101ef610b89565b60408051918252519081900360200190f35b34610000576101ef610b8f565b60408051918252519081900360200190f35b34610000576102c9600160a060020a0360043581169060243516604435610b95565b604080519115158252519081900360200190f35b3461000057610388600160a060020a0360043516602435610bb7565b60408051600160a060020a039096168652602086019490945267ffffffffffffffff928316858501529082166060850152166080830152519081900360a00190f35b34610000576101ef600160a060020a0360043516610c21565b60408051918252519081900360200190f35b3461000057610402610c40565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d4600160a060020a0360043516602435610c4f565b005b3461000057610458600160a060020a0360043516602435610cc9565b60408051600160a060020a03909716875260208701959095528585019390935267ffffffffffffffff9182166060860152811660808501521660a0830152519081900360c00190f35b34610000576101d4610d9e565b005b6101d4610e1e565b005b34610000576104d3600160a060020a0360043516610e21565b6040805167ffffffffffffffff9092168252519081900360200190f35b3461000057610402600160a060020a0360043516610ead565b60408051600160a060020a039092168252519081900360200190f35b34610000576101ef600160a060020a0360043516610ef9565b60408051918252519081900360200190f35b34610000576101ef610f18565b60408051918252519081900360200190f35b346100005761022d610f1e565b604080516020808252835181830152835191928392908301918501908083838215610273575b80518252602083111561027357601f199092019160209182019101610253565b505050905090810190601f16801561029f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576102c9600160a060020a0360043516610fac565b604080519115158252519081900360200190f35b34610000576102c9600160a060020a0360043516602435610fc2565b604080519115158252519081900360200190f35b3461000057610402600435610fe2565b60408051600160a060020a039092168252519081900360200190f35b34610000576101d46004351515610ffd565b005b34610000576102c9600160a060020a036004351661104c565b604080519115158252519081900360200190f35b34610000576101d4600160a060020a0360043516611062565b005b34610000576102c9600160a060020a0360043516611070565b604080519115158252519081900360200190f35b34610000576101ef6110f4565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351667ffffffffffffffff602435166110fa565b60408051918252519081900360200190f35b34610000576101d4600435611121565b005b34610000576101ef600160a060020a03600435811690602435166111c6565b60408051918252519081900360200190f35b34610000576101ef6004356024356044356064356084356111f3565b60408051918252519081900360200190f35b34610000576101ef600160a060020a036004351661128c565b60408051918252519081900360200190f35b34610000576101d4600160a060020a036004351660243561129e565b005b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff848116908416101561086457610000565b8367ffffffffffffffff168267ffffffffffffffff16101561088557610000565b8267ffffffffffffffff168267ffffffffffffffff1610156108a657610000565b506040805160a081018252600160a060020a033381168252602080830188905267ffffffffffffffff80871684860152858116606085015287166080840152908816600090815260039091529190912080546001810180835582818380158290116109615760030281600302836000526020600020918201910161096191905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050916000526020600020906003020160005b5082518154600160a060020a031916600160a060020a03909116178155602083015160018201556040830151600290910180546060850151608086015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff00000000000000001916604060020a918516919091021777ffffffffffffffff000000000000000000000000000000001916608060020a939091169290920291909117905550610a268686610fc2565b505b505050505050565b600160a060020a0381166000908152600360205260409020545b919050565b60055481565b600b805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b600a5433600160a060020a03908116911614610b6957610000565b600a8054600160a060020a031916600160a060020a0383161790555b5b50565b60005481565b60005b90565b6000610ba2848484611600565b610bad8484846116e2565b90505b9392505050565b600360205281600052604060002081815481101561000057906000526020600020906003020160005b5080546001820154600290920154600160a060020a03909116935090915067ffffffffffffffff80821691604060020a8104821691608060020a9091041685565b600160a060020a0381166000908152600860205260409020545b919050565b600a54600160a060020a031681565b600a5433600160a060020a03908116911614610c6a57610000565b610c7660005482611714565b6000908155600160a060020a038316815260016020526040902054610c9b9082611714565b600160a060020a038316600090815260016020526040812091909155610cc390839083611600565b5b5b5050565b6000600060006000600060006000600360008a600160a060020a0316600160a060020a0316815260200190815260200160002088815481101561000057906000526020600020906003020160005b508054600182015460028301546040805160a081018252600160a060020a039094168085526020850184905267ffffffffffffffff808416928601839052604060020a8404811660608701819052608060020a9094041660808601819052909c50929a509197509095509350909150610d90904261172d565b94505b509295509295509295565b33600160a060020a038116600090815260066020526040902054801515610dc457610000565b8030600160a060020a0316311015610ddb57610000565b600160a060020a0382166000818152600660205260408082208290555183156108fc0291849190818181858888f193505050501515610cc357610000565b5b5050565b5b565b600160a060020a03811660009081526003602052604081205442915b81811015610ea557600160a060020a03841660009081526003602052604090208054610e9a9190839081101561000057906000526020600020906003020160005b5060020154604060020a900467ffffffffffffffff168461177d565b92505b600101610e3d565b5b5050919050565b600160a060020a0380821660009081526007602052604081205490911615610eef57600160a060020a0380831660009081526007602052604090205416610ef1565b815b90505b919050565b600160a060020a0381166000908152600160205260409020545b919050565b600d5481565b600c805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610adb5780601f10610ab057610100808354040283529160200191610adb565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505050505081565b60006000610fb983610c21565b1190505b919050565b6000610fcf338484611600565b610fd983836117ac565b90505b92915050565b600460205260009081526040902054600160a060020a031681565b8015801561101a575061100f33610ef9565b61101833610c21565b115b1561102457610000565b33600160a060020a03166000908152600960205260409020805460ff19168215151790555b50565b60006000610fb983610ef9565b1190505b919050565b610b8533826117dc565b5b50565b600a54604080516000602091820181905282517fcbcf2e5a000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015293519194939093169263cbcf2e5a92602480830193919282900301818787803b156100005760325a03f115610000575050604051519150505b919050565b600e5481565b6000610fd961110984846118b2565b61111385856119b6565b611a05565b90505b92915050565b600a5433600160a060020a0390811691161461113c57610000565b61114860005482611a1f565b600055600554600190101561116c57600a5461116c90600160a060020a0316611a47565b5b600a54600160a060020a03166000908152600160205260409020546111929082611a1f565b600a8054600160a060020a039081166000908152600160205260408120939093559054610b8592911683611600565b5b5b50565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b92915050565b6000600060008487101561120a5760009250611281565b8387111561121a57879250611281565b61123f6112308961122b888a611714565b611a90565b61123a8689611714565b611abc565b915081925061124e8883611714565b905061127e8361127961126a8461122b8c8b611714565b611a90565b61123a888b611714565b611abc565b611a1f565b92505b505095945050505050565b60066020526000908152604090205481565b600160a060020a03821660009081526003602052604081208054829190849081101561000057906000526020600020906003020160005b50805490925033600160a060020a039081169116146112f357610000565b6040805160a0810182528354600160a060020a0316815260018401546020820152600284015467ffffffffffffffff80821693830193909352604060020a810483166060830152608060020a900490911660808201526113539042611af9565b600160a060020a0385166000908152600360205260409020805491925090849081101561000057906000526020600020906003020160005b508054600160a060020a031916815560006001820181905560029091018054600160c060020a0319169055600160a060020a0385168152600360205260409020805460001981019081101561000057906000526020600020906003020160005b50600160a060020a03851660009081526003602052604090208054859081101561000057906000526020600020906003020160005b5081548154600160a060020a031916600160a060020a03918216178255600180840154908301556002928301805493909201805467ffffffffffffffff191667ffffffffffffffff948516178082558354604060020a908190048616026fffffffffffffffff000000000000000019909116178082559254608060020a9081900490941690930277ffffffffffffffff00000000000000000000000000000000199092169190911790915584166000908152600360205260409020805460001981018083559190829080158290116115485760030281600302836000526020600020918201910161154891905b8082111561095d578054600160a060020a031916815560006001820155600281018054600160c060020a0319169055600301610926565b5090565b5b505050600160a060020a033316600090815260016020526040902054611570915082611a1f565b600160a060020a03338116600090815260016020526040808220939093559086168152205461159f9082611714565b600160a060020a038086166000818152600160209081526040918290209490945580518581529051339093169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35b50505050565b600160a060020a0383161561166e576116466008600061161f86610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611714565b6008600061165386610ead565b600160a060020a031681526020810191909152604001600020555b600160a060020a038216156116dc576116b46008600061168d85610ead565b600160a060020a0316600160a060020a031681526020019081526020016000205482611a1f565b600860006116c185610ead565b600160a060020a031681526020810191909152604001600020555b5b505050565b600083826116f082426110fa565b8111156116fc57610000565b611707868686611b1b565b92505b5b50509392505050565b600061172283831115611b4d565b508082035b92915050565b6000610fd983602001518367ffffffffffffffff16856080015167ffffffffffffffff16866040015167ffffffffffffffff16876060015167ffffffffffffffff166111f3565b90505b92915050565b60008167ffffffffffffffff168367ffffffffffffffff1610156117a15781610fd9565b825b90505b92915050565b600033826117ba82426110fa565b8111156117c657610000565b6117d08585611b5d565b92505b5b505092915050565b6117e582610ef9565b6117ee83610c21565b11156117f957610000565b600160a060020a03811660009081526009602052604090205460ff16158015611834575081600160a060020a031681600160a060020a031614155b1561183e57610000565b61184782611070565b1561185157610000565b611864828261185f85610ef9565b611600565b600160a060020a0382811660009081526007602052604090208054600160a060020a031916918316918217905561189a82610ead565b600160a060020a031614610cc357610000565b5b5050565b600160a060020a038216600090815260036020526040812054815b818110156119885761197d836112796003600089600160a060020a0316600160a060020a0316815260200190815260200160002084815481101561000057906000526020600020906003020160005b506040805160a0810182528254600160a060020a031681526001830154602082015260029092015467ffffffffffffffff80821692840192909252604060020a810482166060840152608060020a900416608082015287611af9565b611a1f565b92505b6001016118cd565b600160a060020a0385166000908152600160205260409020546117d09084611714565b92505b505092915050565b600060006119c384611070565b80156119d157506000600d54115b90506119fb816119e9576119e485610ef9565b6119ec565b60005b6111138686611b7b565b611a05565b91505b5092915050565b60008183106117a15781610fd9565b825b90505b92915050565b6000828201611a3c848210801590611a375750838210155b611b4d565b8091505b5092915050565b611a508161104c565b15611a5a57610b85565b6005805460009081526004602052604090208054600160a060020a031916600160a060020a038416179055805460010190555b50565b6000828202611a3c841580611a37575083858381156100005704145b611b4d565b8091505b5092915050565b60006000611acc60008411611b4d565b8284811561000057049050611a3c838581156100005706828502018514611b4d565b8091505b5092915050565b6000610fd98360200151611b0d858561172d565b611714565b90505b92915050565b60008382611b2982426110fa565b811115611b3557610000565b611707868686611b8f565b92505b5b50509392505050565b801515610b8557610000565b5b50565b6000611b6883611a47565b610fd98383611c92565b90505b92915050565b6000610fd983610ef9565b90505b92915050565b600160a060020a038084166000908152600260209081526040808320338516845282528083205493861683526001909152812054909190611bd09084611a1f565b600160a060020a038086166000908152600160205260408082209390935590871681522054611bff9084611714565b600160a060020a038616600090815260016020526040902055611c228184611714565b600160a060020a038087166000818152600260209081526040808320338616845282529182902094909455805187815290519288169391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3600191505b509392505050565b60003382611ca082426110fa565b811115611cac57610000565b6117d08585611cc2565b92505b5b505092915050565b600160a060020a033316600090815260016020526040812054611ce59083611714565b600160a060020a033381166000908152600160205260408082209390935590851681522054611d149083611a1f565b600160a060020a038085166000818152600160209081526040918290209490945580518681529051919333909316927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a35060015b929150505600a165627a7a72305820bfa5ddd3fecf3f43aed25385ec7ec3ef79638c2e58d99f85d9a3cc494183bf160029000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182", - "type": "CREATE", - "value": "0x0" - } - ], - "error": "invalid jump destination", - "from": "0xe4a13bc304682a903e9472f469c33801dd18d9e8", - "gas": "0x493e0", - "gasUsed": "0x493e0", - "input": "0x3b91f506000000000000000000000000a14bdd7e5666d784dcce98ad24d383a6b1cd4182000000000000000000000000e4a13bc304682a903e9472f469c33801dd18d9e8", - "to": "0x1d3ddf7caf024f253487e18bc4a15b1a360c170a", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_instafail.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_instafail.json deleted file mode 100644 index 16e413623..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_instafail.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "genesis": { - "difficulty": "117067574", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712380", - "hash": "0xe05db05eeb3f288041ecb10a787df121c0ed69499355716e17c307de313a4486", - "miner": "0x0c062b329265c965deef1eede55183b3acb8f611", - "mixHash": "0xb669ae39118a53d2c65fd3b1e1d3850dd3f8c6842030698ed846a2762d68b61d", - "nonce": "0x2b469722b8e28c45", - "number": "24973", - "stateRoot": "0x532a5c3f75453a696428db078e32ae283c85cb97e4d8560dbdf022adac6df369", - "timestamp": "1479891145", - "totalDifficulty": "1892250259406", - "alloc": { - "0x6c06b16512b332e6cd8293a2974872674716ce18": { - "balance": "0x0", - "nonce": "1", - "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d146036575b6000565b34600057604e60048080359060200190919050506050565b005b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050505b5056", - "storage": {} - }, - "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31": { - "balance": "0x229ebbb36c3e0f20", - "nonce": "3", - "code": "0x", - "storage": {} - } - }, - "config": { - "chainId": 3, - "homesteadBlock": 0, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "byzantiumBlock": 1700000, - "constantinopleBlock": 4230000, - "petersburgBlock": 4939394, - "istanbulBlock": 6485846, - "muirGlacierBlock": 7117117, - "ethash": {} - } - }, - "context": { - "number": "24974", - "difficulty": "117067574", - "timestamp": "1479891162", - "gasLimit": "4712388", - "miner": "0xc822ef32e6d26e170b70cf761e204c1806265914" - }, - "input": "0xf889038504a81557008301f97e946c06b16512b332e6cd8293a2974872674716ce1880a42e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b1600002aa0e2a6558040c5d72bc59f2fb62a38993a314c849cd22fb393018d2c5af3112095a01bdb6d7ba32263ccc2ecc880d38c49d9f0c5a72d8b7908e3122b31356d349745", - "result": { - "type": "CALL", - "from": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31", - "to": "0x6c06b16512b332e6cd8293a2974872674716ce18", - "value": "0x0", - "gas": "0x1f97e", - "gasUsed": "0x72de", - "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000", - "output": "0x", - "calls": [ - { - "type": "CALL", - "from": "0x6c06b16512b332e6cd8293a2974872674716ce18", - "to": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31", - "value": "0x14d1120d7b160000", - "error": "internal failure", - "input": "0x" - } - ] - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json deleted file mode 100644 index a023ed6d9..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/inner_throw_outer_revert.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "context": { - "difficulty": "3956606365", - "gasLimit": "5413248", - "miner": "0x00d8ae40d9a06d0e7a2877b62e32eb959afbe16d", - "number": "2295104", - "timestamp": "1513681256" - }, - "genesis": { - "alloc": { - "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76": { - "balance": "0x0", - "code": "0x60606040526004361061015e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680625b4487146101a257806311df9995146101cb578063278ecde11461022057806330adce0e146102435780633197cbb61461026c5780634bb278f3146102955780636103d70b146102aa57806363a599a4146102bf5780636a2d1cb8146102d457806375f12b21146102fd57806378e979251461032a578063801db9cc1461035357806386d1a69f1461037c5780638da5cb5b146103915780638ef26a71146103e65780639890220b1461040f5780639b39caef14610424578063b85dfb801461044d578063be9a6555146104a1578063ccb07cef146104b6578063d06c91e4146104e3578063d669e1d414610538578063df40503c14610561578063e2982c2114610576578063f02e030d146105c3578063f2fde38b146105d8578063f3283fba14610611575b600060149054906101000a900460ff1615151561017a57600080fd5b60075442108061018b575060085442115b15151561019757600080fd5b6101a03361064a565b005b34156101ad57600080fd5b6101b5610925565b6040518082815260200191505060405180910390f35b34156101d657600080fd5b6101de61092b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561022b57600080fd5b6102416004808035906020019091905050610951565b005b341561024e57600080fd5b610256610c48565b6040518082815260200191505060405180910390f35b341561027757600080fd5b61027f610c4e565b6040518082815260200191505060405180910390f35b34156102a057600080fd5b6102a8610c54565b005b34156102b557600080fd5b6102bd610f3e565b005b34156102ca57600080fd5b6102d261105d565b005b34156102df57600080fd5b6102e76110d5565b6040518082815260200191505060405180910390f35b341561030857600080fd5b6103106110e1565b604051808215151515815260200191505060405180910390f35b341561033557600080fd5b61033d6110f4565b6040518082815260200191505060405180910390f35b341561035e57600080fd5b6103666110fa565b6040518082815260200191505060405180910390f35b341561038757600080fd5b61038f611104565b005b341561039c57600080fd5b6103a4611196565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f157600080fd5b6103f96111bb565b6040518082815260200191505060405180910390f35b341561041a57600080fd5b6104226111c1565b005b341561042f57600080fd5b610437611296565b6040518082815260200191505060405180910390f35b341561045857600080fd5b610484600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061129c565b604051808381526020018281526020019250505060405180910390f35b34156104ac57600080fd5b6104b46112c0565b005b34156104c157600080fd5b6104c9611341565b604051808215151515815260200191505060405180910390f35b34156104ee57600080fd5b6104f6611354565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561054357600080fd5b61054b61137a565b6040518082815260200191505060405180910390f35b341561056c57600080fd5b610574611385565b005b341561058157600080fd5b6105ad600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506116c3565b6040518082815260200191505060405180910390f35b34156105ce57600080fd5b6105d66116db565b005b34156105e357600080fd5b61060f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611829565b005b341561061c57600080fd5b610648600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506118fe565b005b600080670de0b6b3a7640000341015151561066457600080fd5b61069b610696670de0b6b3a7640000610688610258346119d990919063ffffffff16565b611a0c90919063ffffffff16565b611a27565b9150660221b262dd80006106ba60065484611a7e90919063ffffffff16565b111515156106c757600080fd5b600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15156107d557600080fd5b6102c65a03f115156107e657600080fd5b5050506040518051905050610808828260010154611a7e90919063ffffffff16565b8160010181905550610827348260000154611a7e90919063ffffffff16565b816000018190555061084434600554611a7e90919063ffffffff16565b60058190555061085f82600654611a7e90919063ffffffff16565b6006819055503373ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c836040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e8583600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60025481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060085442108061096b5750651b48eb57e00060065410155b15151561097757600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154821415156109c757600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856000604051602001526040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1515610ac857600080fd5b6102c65a03f11515610ad957600080fd5b5050506040518051905050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610b7d57600080fd5b6102c65a03f11515610b8e57600080fd5b505050604051805190501515610ba357600080fd5b600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015490506000600a60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055506000811115610c4457610c433382611a9c565b5b5050565b60055481565b60085481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610cb157600080fd5b600854421015610cd357660221b262dd8000600654141515610cd257600080fd5b5b651b48eb57e000600654108015610cf057506213c6806008540142105b151515610cfc57600080fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501515610d7557600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b1515610e3a57600080fd5b6102c65a03f11515610e4b57600080fd5b5050506040518051905090506000811115610f2057600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68826000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1515610ef957600080fd5b6102c65a03f11515610f0a57600080fd5b505050604051805190501515610f1f57600080fd5b5b6001600960006101000a81548160ff02191690831515021790555050565b600080339150600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008114151515610f9657600080fd5b803073ffffffffffffffffffffffffffffffffffffffff163110151515610fbc57600080fd5b610fd181600254611b5090919063ffffffff16565b6002819055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050151561105957fe5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156110b857600080fd5b6001600060146101000a81548160ff021916908315150217905550565b670de0b6b3a764000081565b600060149054906101000a900460ff1681565b60075481565b651b48eb57e00081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561115f57600080fd5b600060149054906101000a900460ff16151561117a57600080fd5b60008060146101000a81548160ff021916908315150217905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561121c57600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050151561129457600080fd5b565b61025881565b600a6020528060005260406000206000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561131b57600080fd5b600060075414151561132c57600080fd5b4260078190555062278d004201600881905550565b600960009054906101000a900460ff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b660221b262dd800081565b60008060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113e557600080fd5b600654660221b262dd800003925061142b670de0b6b3a764000061141c610258670de0b6b3a76400006119d990919063ffffffff16565b81151561142557fe5b04611a27565b915081831115151561143c57600080fd5b600a60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b151561158c57600080fd5b6102c65a03f1151561159d57600080fd5b50505060405180519050506115bf838260010154611a7e90919063ffffffff16565b81600101819055506115dc83600654611a7e90919063ffffffff16565b6006819055503073ffffffffffffffffffffffffffffffffffffffff167ff3c1c7c0eb1328ddc834c4c9e579c06d35f443bf1102b034653624a239c7a40c846040518082815260200191505060405180910390a27fd1dc370699ae69fb860ed754789a4327413ec1cd379b93f2cbedf449a26b0e856000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600554604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561173657600080fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2fde38b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b151561181357600080fd5b6102c65a03f1151561182457600080fd5b505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561188457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415156118fb57806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561195957600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561199557600080fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828402905060008414806119fa57508284828115156119f757fe5b04145b1515611a0257fe5b8091505092915050565b6000808284811515611a1a57fe5b0490508091505092915050565b6000611a416202a300600754611a7e90919063ffffffff16565b421015611a7557611a6e611a5f600584611a0c90919063ffffffff16565b83611a7e90919063ffffffff16565b9050611a79565b8190505b919050565b6000808284019050838110151515611a9257fe5b8091505092915050565b611aee81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a7e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611b4681600254611a7e90919063ffffffff16565b6002819055505050565b6000828211151515611b5e57fe5b8183039050929150505600a165627a7a72305820ec0d82a406896ccf20989b3d6e650abe4dc104e400837f1f58e67ef499493ae90029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008d69d00910d0b2afb2a99ed6c16c8129fa8e1751", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000e819f024b41358d2c08e3a868a5c5dd0566078d4", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000005a388981", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000005a3b38e6" - } - }, - "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826": { - "balance": "0x2a2dd979a35cf000", - "code": "0x", - "nonce": "0", - "storage": {} - }, - "0xe819f024b41358d2c08e3a868a5c5dd0566078d4": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c681461027257806370a08231146102ad5780638da5cb5b146102fa57806395d89b411461034f578063a9059cbb146103dd578063dd62ed3e14610437578063f2fde38b146104a3575b600080fd5b34156100ca57600080fd5b6100d26104dc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610515565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba61069c565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106a2565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610952565b6040518082815260200191505060405180910390f35b341561027d57600080fd5b6102936004808035906020019091905050610957565b604051808215151515815260200191505060405180910390f35b34156102b857600080fd5b6102e4600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610abe565b6040518082815260200191505060405180910390f35b341561030557600080fd5b61030d610b07565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561035a57600080fd5b610362610b2d565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103a2578082015181840152602081019050610387565b50505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e857600080fd5b61041d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b66565b604051808215151515815260200191505060405180910390f35b341561044257600080fd5b61048d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d01565b6040518082815260200191505060405180910390f35b34156104ae57600080fd5b6104da600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610d88565b005b6040805190810160405280600b81526020017f416c6c436f6465436f696e00000000000000000000000000000000000000000081525081565b6000808214806105a157506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156105ac57600080fd5b81600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905061077683600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061080b83600160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506108618382610e7d90919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b600681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156109b557600080fd5b610a0782600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610a5f82600054610e7d90919063ffffffff16565b60008190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050919050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040805190810160405280600481526020017f414c4c430000000000000000000000000000000000000000000000000000000081525081565b6000610bba82600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e7d90919063ffffffff16565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610c4f82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e5f90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610de457600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515610e5c5780600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b6000808284019050838110151515610e7357fe5b8091505092915050565b6000828211151515610e8b57fe5b8183039050929150505600a165627a7a7230582059f3ea3df0b054e9ab711f37969684ba83fe38f255ffe2c8d850d951121c51100029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3956606365", - "extraData": "0x566961425443", - "gasLimit": "5418523", - "hash": "0x6f37eb930a25da673ea1bb80fd9e32ddac19cdf7cd4bb2eac62cc13598624077", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "mixHash": "0x10971cde68c587c750c23b8589ae868ce82c2c646636b97e7d9856470c5297c7", - "nonce": "0x810f923ff4b450a1", - "number": "2295103", - "stateRoot": "0xff403612573d76dfdaf4fea2429b77dbe9764021ae0e38dc8ac79a3cf551179e", - "timestamp": "1513681246", - "totalDifficulty": "7162347056825919" - }, - "input": "0xf86d808504e3b292008307dfa69433056b5dcac09a9b4becad0e1dcf92c19bd0af76880e92596fd62900008029a0e5f27bb66431f7081bb7f1f242003056d7f3f35414c352cd3d1848b52716dac2a07d0be78980edb0bd2a0678fc53aa90ea9558ce346b0d947967216918ac74ccea", - "result": { - "calls": [ - { - "error": "invalid opcode: INVALID", - "from": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "gas": "0x75fe3", - "gasUsed": "0x75fe3", - "input": "0xa9059cbb000000000000000000000000d4fcab9f0a6dc0493af47c864f6f17a8a5e2e82600000000000000000000000000000000000000000000000000000000000002f4", - "to": "0xe819f024b41358d2c08e3a868a5c5dd0566078d4", - "type": "CALL", - "value": "0x0" - } - ], - "error": "execution reverted", - "from": "0xd4fcab9f0a6dc0493af47c864f6f17a8a5e2e826", - "gas": "0x7dfa6", - "gasUsed": "0x7c1c8", - "input": "0x", - "to": "0x33056b5dcac09a9b4becad0e1dcf92c19bd0af76", - "type": "CALL", - "value": "0xe92596fd6290000" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json deleted file mode 100644 index 333bdd038..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/oog.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "context": { - "difficulty": "3699098917", - "gasLimit": "5258985", - "miner": "0xd049bfd667cb46aa3ef5df0da3e57db3be39e511", - "number": "2294631", - "timestamp": "1513675366" - }, - "genesis": { - "alloc": { - "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62": { - "balance": "0x0", - "code": "0x6060604052600436106100ba576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100bf578063095ea7b31461014d57806318160ddd146101a757806323b872dd146101d0578063313ce5671461024957806342966c68146102785780635a3b7e42146102b357806370a082311461034157806379cc67901461038e57806395d89b41146103e8578063a9059cbb14610476578063dd62ed3e146104b8575b600080fd5b34156100ca57600080fd5b6100d2610524565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015857600080fd5b61018d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061055d565b604051808215151515815260200191505060405180910390f35b34156101b257600080fd5b6101ba6105ea565b6040518082815260200191505060405180910390f35b34156101db57600080fd5b61022f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506105f0565b604051808215151515815260200191505060405180910390f35b341561025457600080fd5b61025c610910565b604051808260ff1660ff16815260200191505060405180910390f35b341561028357600080fd5b6102996004808035906020019091905050610915565b604051808215151515815260200191505060405180910390f35b34156102be57600080fd5b6102c6610a18565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103065780820151818401526020810190506102eb565b50505050905090810190601f1680156103335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034c57600080fd5b610378600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a51565b6040518082815260200191505060405180910390f35b341561039957600080fd5b6103ce600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a69565b604051808215151515815260200191505060405180910390f35b34156103f357600080fd5b6103fb610bf8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043b578082015181840152602081019050610420565b50505050905090810190601f1680156104685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561048157600080fd5b6104b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610c31565b005b34156104c357600080fd5b61050e600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610e34565b6040518082815260200191505060405180910390f35b6040805190810160405280600881526020017f446f70616d696e6500000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905092915050565b60005481565b6000808373ffffffffffffffffffffffffffffffffffffffff161415151561061757600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561066557600080fd5b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156106f157fe5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561077c57600080fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561096557600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a260019050919050565b6040805190810160405280600981526020017f446f706d6e20302e32000000000000000000000000000000000000000000000081525081565b60016020528060005260406000206000915090505481565b600081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ab957600080fd5b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610b4457600080fd5b81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508160008082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5836040518082815260200191505060405180910390a26001905092915050565b6040805190810160405280600581526020017f444f504d4e00000000000000000000000000000000000000000000000000000081525081565b60008273ffffffffffffffffffffffffffffffffffffffff1614151515610c5757600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610ca557600080fd5b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610d3157fe5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60026020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058206d93424f4e7b11929b8276a269038402c10c0ddf21800e999916ddd9dff4a7630029", - "nonce": "1", - "storage": { - "0x296b66049cc4f9c8bf3d4f14752add261d1a980b39bdd194a7897baf39ac7579": "0x0000000000000000000000000000000000000000033b2e3c9fc9653f9e72b1e0" - } - }, - "0x94194bc2aaf494501d7880b61274a169f6502a54": { - "balance": "0xea8c39a876d19888d", - "code": "0x", - "nonce": "265", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3699098917", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5263953", - "hash": "0x03a0f62a8106793dafcfae7b75fd2654322062d585a19cea568314d7205790dc", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x15482cc64b7c00a947f5bf015dfc010db1a6a668c74df61974d6a7848c174408", - "nonce": "0xd1bdb150f6fd170e", - "number": "2294630", - "stateRoot": "0x1ab1a534e84cc787cda1db21e0d5920ab06017948075b759166cfea7274657a1", - "timestamp": "1513675347", - "totalDifficulty": "7160543502214733" - }, - "input": "0xf8ab820109855d21dba00082ca1d9443064693d3d38ad6a7cb579e0d6d9718c8aa6b6280b844a9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f90001ba0ce3ad83f5530136467b7c2bb225f406bd170f4ad59c254e5103c34eeabb5bd69a0455154527224a42ab405cacf0fe92918a75641ce4152f8db292019a5527aa956", - "result": { - "error": "out of gas", - "from": "0x94194bc2aaf494501d7880b61274a169f6502a54", - "gas": "0xca1d", - "gasUsed": "0xca1d", - "input": "0xa9059cbb000000000000000000000000e77b1ac803616503510bed0086e3a7be2627a69900000000000000000000000000000000000000000000000000000009502f9000", - "to": "0x43064693d3d38ad6a7cb579e0d6d9718c8aa6b62", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json deleted file mode 100644 index 3207a298a..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "context": { - "difficulty": "3665057456", - "gasLimit": "5232723", - "miner": "0xf4d8e706cfb25c0decbbdd4d2e2cc10c66376a3f", - "number": "2294501", - "timestamp": "1513673601" - }, - "genesis": { - "alloc": { - "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9": { - "balance": "0x2a3fc32bcc019283", - "code": "0x", - "nonce": "10", - "storage": {} - }, - "0xabbcd5b340c80b5f1c0545c04c987b87310296ae": { - "balance": "0x0", - "code": "0x606060405236156100755763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632d0335ab811461007a578063548db174146100ab5780637f649783146100fc578063b092145e1461014d578063c3f44c0a14610186578063c47cf5de14610203575b600080fd5b341561008557600080fd5b610099600160a060020a0360043516610270565b60405190815260200160405180910390f35b34156100b657600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061028f95505050505050565b005b341561010757600080fd5b6100fa600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965061029e95505050505050565b005b341561015857600080fd5b610172600160a060020a03600435811690602435166102ad565b604051901515815260200160405180910390f35b341561019157600080fd5b6100fa6004803560ff1690602480359160443591606435600160a060020a0316919060a49060843590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965050509235600160a060020a031692506102cd915050565b005b341561020e57600080fd5b61025460046024813581810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061056a95505050505050565b604051600160a060020a03909116815260200160405180910390f35b600160a060020a0381166000908152602081905260409020545b919050565b61029a816000610594565b5b50565b61029a816001610594565b5b50565b600160209081526000928352604080842090915290825290205460ff1681565b60008080600160a060020a038416158061030d5750600160a060020a038085166000908152600160209081526040808320339094168352929052205460ff165b151561031857600080fd5b6103218561056a565b600160a060020a038116600090815260208190526040808220549295507f19000000000000000000000000000000000000000000000000000000000000009230918891908b908b90517fff000000000000000000000000000000000000000000000000000000000000008089168252871660018201526c01000000000000000000000000600160a060020a038088168202600284015286811682026016840152602a8301869052841602604a820152605e810182805190602001908083835b6020831061040057805182525b601f1990920191602091820191016103e0565b6001836020036101000a0380198251168184511617909252505050919091019850604097505050505050505051809103902091506001828a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561049957600080fd5b5050602060405103519050600160a060020a03838116908216146104bc57600080fd5b600160a060020a0380841660009081526020819052604090819020805460010190559087169086905180828051906020019080838360005b8381101561050d5780820151818401525b6020016104f4565b50505050905090810190601f16801561053a5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008661646e5a03f1915050151561055e57600080fd5b5b505050505050505050565b600060248251101561057e5750600061028a565b600160a060020a0360248301511690505b919050565b60005b825181101561060157600160a060020a033316600090815260016020526040812083918584815181106105c657fe5b90602001906020020151600160a060020a031681526020810191909152604001600020805460ff19169115159190911790555b600101610597565b5b5050505600a165627a7a723058200027e8b695e9d2dea9f3629519022a69f3a1d23055ce86406e686ea54f31ee9c0029", - "nonce": "1", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3672229776", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "5227619", - "hash": "0xa07b3d6c6bf63f5f981016db9f2d1d93033833f2c17e8bf7209e85f1faf08076", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0x806e151ce2817be922e93e8d5921fa0f0d0fd213d6b2b9a3fa17458e74a163d0", - "nonce": "0xbc5d43adc2c30c7d", - "number": "2294500", - "stateRoot": "0xca645b335888352ef9d8b1ef083e9019648180b259026572e3139717270de97d", - "timestamp": "1513673552", - "totalDifficulty": "7160066586979149" - }, - "input": "0xf9018b0a8505d21dba00832dc6c094abbcd5b340c80b5f1c0545c04c987b87310296ae80b9012473b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0fd659d76a4edbd2a823e324c93f78ad6803b30ff4a9c8bce71ba82798975c70ca06571eecc0b765688ec6c78942c5ee8b585e00988c0141b518287e9be919bc48a", - "result": { - "error": "execution reverted", - "from": "0x0f6cef2b7fbb504782e35aa82a2207e816a2b7a9", - "gas": "0x2dc6c0", - "gasUsed": "0x719b", - "input": "0x73b40a5c000000000000000000000000400de2e016bda6577407dfc379faba9899bc73ef0000000000000000000000002cc31912b2b0f3075a87b3640923d45a26cef3ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064d79d8e6c7265636f76657279416464726573730000000000000000000000000000000000000000000000000000000000383e3ec32dc0f66d8fe60dbdc2f6815bdf73a988383e3ec32dc0f66d8fe60dbdc2f6815bdf73a98800000000000000000000000000000000000000000000000000000000000000000000000000000000", - "to": "0xabbcd5b340c80b5f1c0545c04c987b87310296ae", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json deleted file mode 100644 index 5c7e5629e..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/revert_reason.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "context": { - "difficulty": "2", - "gasLimit": "8000000", - "miner": "0x0000000000000000000000000000000000000000", - "number": "3212651", - "timestamp": "1597246515" - }, - "genesis": { - "alloc": { - "0xf58833cf0c791881b494eb79d461e08a1f043f52": { - "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063609ff1bd11610078578063609ff1bd146101af5780639e7b8d61146101cd578063a3ec138d14610211578063e2ba53f0146102ae576100a5565b80630121b93f146100aa578063013cf08b146100d85780632e4176cf146101215780635c19a95c1461016b575b600080fd5b6100d6600480360360208110156100c057600080fd5b81019080803590602001909291905050506102cc565b005b610104600480360360208110156100ee57600080fd5b8101908080359060200190929190505050610469565b604051808381526020018281526020019250505060405180910390f35b61012961049a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ad6004803603602081101561018157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bf565b005b6101b76108db565b6040518082815260200191505060405180910390f35b61020f600480360360208110156101e357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610952565b005b6102536004803603602081101561022757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b53565b60405180858152602001841515151581526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390f35b6102b6610bb0565b6040518082815260200191505060405180910390f35b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154141561038a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f486173206e6f20726967687420746f20766f746500000000000000000000000081525060200191505060405180910390fd5b8060010160009054906101000a900460ff161561040f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f416c726561647920766f7465642e00000000000000000000000000000000000081525060200191505060405180910390fd5b60018160010160006101000a81548160ff02191690831515021790555081816002018190555080600001546002838154811061044757fe5b9060005260206000209060020201600101600082825401925050819055505050565b6002818154811061047657fe5b90600052602060002090600202016000915090508060000154908060010154905082565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff1615610587576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f596f7520616c726561647920766f7465642e000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610629576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e000081525060200191505060405180910390fd5b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107cc57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f466f756e64206c6f6f7020696e2064656c65676174696f6e2e0000000000000081525060200191505060405180910390fd5b61062a565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156108bf578160000154600282600201548154811061089c57fe5b9060005260206000209060020201600101600082825401925050819055506108d6565b816000015481600001600082825401925050819055505b505050565b6000806000905060008090505b60028054905081101561094d57816002828154811061090357fe5b9060005260206000209060020201600101541115610940576002818154811061092857fe5b90600052602060002090600202016001015491508092505b80806001019150506108e8565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180610bde6028913960400191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff1615610aba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f54686520766f74657220616c726561647920766f7465642e000000000000000081525060200191505060405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414610b0957600080fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018190555050565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16908060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154905084565b60006002610bbc6108db565b81548110610bc657fe5b90600052602060002090600202016000015490509056fe4f6e6c79206368616972706572736f6e2063616e206769766520726967687420746f20766f74652ea26469706673582212201d282819f8f06fed792100d60a8b08809b081a34a1ecd225e83a4b41122165ed64736f6c63430006060033", - "nonce": "1", - "storage": { - "0x6200beec95762de01ce05f2a0e58ce3299dbb53c68c9f3254a242121223cdf58": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1": { - "balance": "0x57af9d6b3df812900", - "code": "0x", - "nonce": "6", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "IstanbulBlock":1561651, - "chainId": 5, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf888068449504f80832dc6c094f58833cf0c791881b494eb79d461e08a1f043f5280a45c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf12da0264664db3e71fae1dbdaf2f53954be149ad3b7ba8a5054b4d89c70febfacc8b1a0212e8398757963f419681839ae8c5a54b411e252473c82d93dda68405ca63294", - "result": { - "error": "execution reverted", - "from": "0xf7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "gas": "0x2dc6c0", - "gasUsed": "0x5940", - "input": "0x5c19a95c000000000000000000000000f7579c3d8a669c89d5ed246a22eb6db8f6fedbf1", - "to": "0xf58833cf0c791881b494eb79d461e08a1f043f52", - "type": "CALL", - "value": "0x0", - "output": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e53656c662d64656c65676174696f6e20697320646973616c6c6f7765642e0000" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json deleted file mode 100644 index 11b23a990..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/selfdestruct.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x61deadff", - "nonce": "1", - "storage": {} - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "calls": [ - { - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "input": "0x", - "to": "0x000000000000000000000000000000000000dEaD", - "type": "SELFDESTRUCT", - "value": "0x4d87094125a369d9bd5" - } - ], - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "gasUsed": "0x6fcb", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "output": "0x", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json deleted file mode 100644 index 37723f17d..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/simple.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "calls": [ - { - "from": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "input": "0x", - "to": "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "type": "CALL", - "value": "0x6f05b59d3b20000" - } - ], - "from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb", - "gas": "0x15f90", - "gasUsed": "0x9751", - "input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json deleted file mode 100644 index 499b449a6..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_legacy/throw.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "context": { - "difficulty": "117009631", - "gasLimit": "4712388", - "miner": "0x294e5d6c39a36ce38af1dca70c1060f78dee8070", - "number": "25009", - "timestamp": "1479891666" - }, - "genesis": { - "alloc": { - "0x70c9217d814985faef62b124420f8dfbddd96433": { - "balance": "0x4ecd70668f5d854a", - "code": "0x", - "nonce": "1638", - "storage": {} - }, - "0xc212e03b9e060e36facad5fd8f4435412ca22e6b": { - "balance": "0x0", - "code": "0x606060405236156101745760e060020a600035046302d05d3f811461017c57806304a7fdbc1461018e5780630e90f957146101fb5780630fb5a6b41461021257806314baa1b61461021b57806317fc45e21461023a5780632b096926146102435780632e94420f1461025b578063325a19f11461026457806336da44681461026d5780633f81a2c01461027f5780633fc306821461029757806345ecd3d7146102d45780634665096d146102dd5780634e71d92d146102e657806351a34eb8146103085780636111bb951461032d5780636f265b93146103445780637e9014e11461034d57806390ba009114610360578063927df5e014610393578063a7f437791461046c578063ad8f50081461046e578063bc6d909414610477578063bdec3ad114610557578063c19d93fb1461059a578063c9503fe2146105ad578063e0a73a93146105b6578063ea71b02d146105bf578063ea8a1af0146105d1578063ee4a96f9146105f3578063f1ff78a01461065c575b61046c610002565b610665600054600160a060020a031681565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600554600090600160a060020a0390811633909116146106a857610002565b61068260015460a060020a900460ff166000145b90565b61069660085481565b61046c600435600154600160a060020a03166000141561072157610002565b610696600d5481565b610696600435600f8160068110156100025750015481565b61069660045481565b61069660035481565b610665600554600160a060020a031681565b61069660043560158160068110156100025750015481565b6106966004355b600b54600f5460009160028202808203928083039290810191018386101561078357601054840186900394505b50505050919050565b61069660025481565b61069660095481565b61046c600554600090600160a060020a03908116339091161461085857610002565b61046c600435600554600090600160a060020a03908116339091161461092e57610002565b6106826001805460a060020a900460ff161461020f565b610696600b5481565b61068260075460a060020a900460ff1681565b6106966004355b600b54601554600091600282028082039280830392908101910183861015610a6c5760165494506102cb565b61046c6004356024356044356040805160015460e360020a631c2d8fb302825260b260020a691858d8dbdd5b9d18dd1b02600483015291516000928392600160a060020a03919091169163e16c7d9891602481810192602092909190829003018187876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610b4657610002565b005b610696600a5481565b61046c60006000600060006000600160009054906101000a9004600160a060020a0316600160a060020a031663e16c7d986040518160e060020a028152600401808060b260020a691858d8dbdd5b9d18dd1b0281526020015060200190506020604051808303816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663c4b0c96a336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515115159050610f1757610002565b61046c5b60015b60058160ff16101561071e57600f6001820160ff166006811015610002578101549060ff83166006811015610002570154101561129057610002565b61069660015460a060020a900460ff1681565b61069660065481565b610696600c5481565b610665600754600160a060020a031681565b61046c600554600090600160a060020a0390811633909116146112c857610002565b6040805160c081810190925261046c9160049160c4918390600690839083908082843760408051808301909152929750909561018495509193509091908390839080828437509095505050505050600154600090600160a060020a03168114156113fb57610002565b610696600e5481565b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60408051918252519081900360200190f35b5060005b60068160ff16101561070857828160ff166006811015610002576020020151600f60ff831660068110156100025701558160ff82166006811015610002576020020151601560ff831660068110156100025701556001016106ac565b61071061055b565b505050565b600e8054820190555b50565b6040805160015460e060020a6313bc6d4b02825233600160a060020a03908116600484015292519216916313bc6d4b9160248181019260209290919082900301816000876161da5a03f115610002575050604051511515905061071557610002565b83861015801561079257508286105b156107b457600f546010546011548689039082030291909104900394506102cb565b8286101580156107c55750600b5486105b156107e757600f546011546012548589039082030291909104900394506102cb565b600b5486108015906107f857508186105b1561081d57600b54600f546012546013549289039281039290920204900394506102cb565b81861015801561082c57508086105b1561084e57600f546013546014548489039082030291909104900394506102cb565b60145494506102cb565b60015460a060020a900460ff1660001461087157610002565b600254600a01431161088257610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150905080600160a060020a031663771d50e16040518160e060020a0281526004018090506000604051808303816000876161da5a03f1156100025750505050565b60015460a060020a900460ff1660001461094757610002565b600254600a01431161095857610002565b6040805160015460e360020a631c2d8fb302825260a860020a6a636f6e74726163746170690260048301529151600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180517f51a34eb8000000000000000000000000000000000000000000000000000000008252600482018690529151919350600160a060020a03841692506351a34eb8916024808301926000929190829003018183876161da5a03f11561000257505050600b8290554360025560408051838152905130600160a060020a0316917fa609f6bd4ad0b4f419ddad4ac9f0d02c2b9295c5e6891469055cf73c2b568fff919081900360200190a25050565b838610158015610a7b57508286105b15610a9d576015546016546017548689039082900302919091040194506102cb565b828610158015610aae5750600b5486105b15610ad0576015546017546018548589039082900302919091040194506102cb565b600b548610801590610ae157508186105b15610b0657600b546015546018546019549289039281900392909202040194506102cb565b818610158015610b1557508086105b15610b3757601554601954601a548489039082900302919091040194506102cb565b601a54860181900394506102cb565b60015460a060020a900460ff16600014610b5f57610002565b6001805460a060020a60ff02191660a060020a17908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919450600160a060020a038516925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604080518051600a556005547ffebf661200000000000000000000000000000000000000000000000000000000825233600160a060020a03908116600484015216602482015260448101879052905163febf661291606480820192600092909190829003018183876161da5a03f115610002575050508215610cc7576007805473ffffffffffffffffffffffffffffffffffffffff191633179055610dbb565b6040805160055460065460e060020a63599efa6b028352600160a060020a039182166004840152602483015291519184169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050604080516006547f56ccb6f000000000000000000000000000000000000000000000000000000000825233600160a060020a03166004830152602482015290516356ccb6f091604480820192600092909190829003018183876161da5a03f115610002575050600580546007805473ffffffffffffffffffffffffffffffffffffffff19908116600160a060020a038416179091551633179055505b6007805460a060020a60ff02191660a060020a87810291909117918290556008544301600955900460ff1615610df757600a54610e039061029e565b600a54610e0b90610367565b600c55610e0f565b600c555b600c54670de0b6b3a7640000850204600d55600754600554604080517f759297bb000000000000000000000000000000000000000000000000000000008152600160a060020a039384166004820152918316602483015260448201879052519184169163759297bb91606481810192600092909190829003018183876161da5a03f11561000257505060408051600754600a54600d54600554600c5460a060020a850460ff161515865260208601929092528486019290925260608401529251600160a060020a0391821694509281169230909116917f3b3d1986083d191be01d28623dc19604728e29ae28bdb9ba52757fdee1a18de2919081900360800190a45050505050565b600954431015610f2657610002565b6001805460a060020a900460ff1614610f3e57610002565b6001805460a060020a60ff0219167402000000000000000000000000000000000000000017908190556040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f1156100025750506040805180516004805460e260020a633e4baddd028452908301529151919750600160a060020a038816925063f92eb77491602482810192602092919082900301816000876161da5a03f115610002575050604051516007549095506000945060a060020a900460ff1615905061105c57600a5484111561105757600a54600d54670de0b6b3a7640000918603020492505b61107e565b600a5484101561107e57600a54600d54670de0b6b3a764000091869003020492505b60065483111561108e5760065492505b6006548390039150600083111561111857604080516005546007547f5928d37f000000000000000000000000000000000000000000000000000000008352600160a060020a0391821660048401528116602483015260448201869052915191871691635928d37f91606481810192600092909190829003018183876161da5a03f115610002575050505b600082111561117a576040805160055460e060020a63599efa6b028252600160a060020a0390811660048301526024820185905291519187169163599efa6b91604481810192600092909190829003018183876161da5a03f115610002575050505b6040805185815260208101849052808201859052905130600160a060020a0316917f89e690b1d5aaae14f3e85f108dc92d9ab3763a58d45aed8b59daedbbae8fe794919081900360600190a260008311156112285784600160a060020a0316634cc927d785336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f11561000257505050611282565b84600160a060020a0316634cc927d7600a60005054336040518360e060020a0281526004018083815260200182600160a060020a03168152602001925050506000604051808303816000876161da5a03f115610002575050505b600054600160a060020a0316ff5b60156001820160ff166006811015610002578101549060ff8316600681101561000257015411156112c057610002565b60010161055e565b60015460a060020a900460ff166000146112e157610002565b600254600a0143116112f257610002565b6001546040805160e360020a631c2d8fb302815260a860020a6a636f6e74726163746170690260048201529051600160a060020a03929092169163e16c7d989160248181019260209290919082900301816000876161da5a03f11561000257505060408051805160055460065460e060020a63599efa6b028452600160a060020a03918216600485015260248401529251909450918416925063599efa6b916044808301926000929190829003018183876161da5a03f1156100025750505080600160a060020a0316632b68bb2d6040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050600054600160a060020a03169050ff5b6001546040805160e060020a6313bc6d4b02815233600160a060020a039081166004830152915191909216916313bc6d4b91602480830192602092919082900301816000876161da5a03f11561000257505060405151151590506106a85761000256", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000002cccf5e0538493c235d1c5ef6580f77d99e91396", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000061a9", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000070c9217d814985faef62b124420f8dfbddd96433" - } - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "117066792", - "extraData": "0xd783010502846765746887676f312e372e33856c696e7578", - "gasLimit": "4712388", - "hash": "0xe23e8d4562a1045b70cbc99fefb20c101a8f0fc8559a80d65fea8896e2f1d46e", - "miner": "0x71842f946b98800fe6feb49f0ae4e253259031c9", - "mixHash": "0x0aada9d6e93dd4db0d09c0488dc0a048fca2ccdc1f3fc7b83ba2a8d393a3a4ff", - "nonce": "0x70849d5838dee2e9", - "number": "25008", - "stateRoot": "0x1e01d2161794768c5b917069e73d86e8dca80cd7f3168c0597de420ab93a3b7b", - "timestamp": "1479891641", - "totalDifficulty": "1896347038589" - }, - "input": "0xf88b8206668504a817c8008303d09094c212e03b9e060e36facad5fd8f4435412ca22e6b80a451a34eb8000000000000000000000000000000000000000000000027fad02094277c000029a0692a3b4e7b2842f8dd7832e712c21e09f451f416c8976d5b8d02e8c0c2b4bea9a07645e90fc421b63dd755767fd93d3c03b4ec0c4d8fafa059558d08cf11d59750", - "result": { - "error": "invalid jump destination", - "from": "0x70c9217d814985faef62b124420f8dfbddd96433", - "gas": "0x3d090", - "gasUsed": "0x3d090", - "input": "0x51a34eb8000000000000000000000000000000000000000000000027fad02094277c0000", - "to": "0xc212e03b9e060e36facad5fd8f4435412ca22e6b", - "type": "CALL", - "value": "0x0" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json deleted file mode 100644 index dbece7229..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "genesis": { - "difficulty": "11934798510088", - "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", - "gasLimit": "3141592", - "hash": "0xfc543a4a551afbd4a6c5d6d49041371e6bb58b1108c12aaec7f487ce656bb97f", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", - "mixHash": "0xa6a1e67fc68da76b8d9cc3ce1c45d5e1f4bbd96b5dcfddbe0017d7fa99903ead", - "nonce": "0x5f00c600268b4659", - "number": "995200", - "stateRoot": "0x3579328470dd2aef5b9da69f5480cbe0d375e653b530ab3c1aee0da5e1ff4c94", - "timestamp": "1455322761", - "totalDifficulty": "7077231809278509672", - "alloc": { - "0x200edd17f30485a8735878661960cd7a9a95733f": { - "balance": "0x0", - "code": "0x3660008037602060003660003473273930d21e01ee25e4c219b63259d214872220a261235a5a03f21560015760206000f3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000104": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf04": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf05": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf06": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa611e7c895a426c0477bc9e280db9c3b1e456dc6310ffcf23926ef5186c1facc": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c410e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c410f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c4110": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x273930d21e01ee25e4c219b63259d214872220a2": { - "balance": "0x0", - "code": "0x606060405236156100da5760e060020a6000350463173825d9811461012c5780632f54bf6e146101875780634123cb6b146101af57806352375093146101b857806354fd4d50146101c25780635c52c2f5146101cc578063659010e7146101fd5780637065cb4814610207578063746c91711461023b578063797af62714610244578063b20d30a914610257578063b61d27f61461028b578063b75c7dc6146102ac578063ba51a6df146102db578063c2cf73261461030f578063cbf0b0c01461034d578063f00d4b5d14610381578063f1736d86146103ba575b6103c4600034111561012a5760408051600160a060020a033216815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b6103c46004356000600036436040518084848082843750505090910190815260405190819003602001902090506106c9815b600160a060020a03321660009081526101026020526040812054818082811415610c3f57610d97565b6103c66004355b600160a060020a03811660009081526101026020526040812054115b919050565b6103c660015481565b6103c66101075481565b6103c66101085481565b6103c46000364360405180848480828437505050909101908152604051908190036020019020905061081a8161015e565b6103c66101065481565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506106418161015e565b6103c660005481565b6103c66004355b600081610a7d8161015e565b6103c46004356000364360405180848480828437505050909101908152604051908190036020019020905061080e8161015e565b6103c66004803590602480359160443591820191013560006108393261018e565b6103c4600435600160a060020a033216600090815261010260205260408120549080828114156103d857610457565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506107888161015e565b6103c6600435602435600082815261010360209081526040808320600160a060020a038516845261010290925282205482818114156107e157610805565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506108288161015e565b6103c46004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104e28161015e565b6103c66101055481565b005b60408051918252519081900360200190f35b50506000828152610103602052604081206001810154600284900a9290831611156104575780546001828101805492909101835590839003905560408051600160a060020a03321681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b50505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a1505b505050565b15610457576104f08361018e565b156104fb57506104dd565b600160a060020a03841660009081526101026020526040812054925082141561052457506104dd565b61045d5b6101045460005b81811015610ee457610104805461010991600091849081101561000257600080516020610f9f83398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f6992601f9290920104810190610a65565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561063c5761064f8261018e565b1561065a575061063e565b610662610528565b60015460fa90106106775761067561068c565b505b60015460fa90106105a2575061063e565b6107465b600060015b600154811015610a79575b600154811080156106bc5750600281610100811015610002570154600014155b15610d9f5760010161069c565b156104dd57600160a060020a0383166000908152610102602052604081205492508214156106f7575061063c565b6001600160005054036000600050541115610712575061063c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610688610528565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561063c5760015482111561079d575061063e565b60008290556107aa610528565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001820154600282900a908116600014156108005760009350610805565b600193505b50505092915050565b1561063c575061010555565b1561063e5760006101065550565b1561063c5781600160a060020a0316ff5b15610a555761084d846000610e793261018e565b15610909577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00432858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a5592505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061093990508161024b565b15801561095c575060008181526101096020526040812054600160a060020a0316145b15610a555760008181526101096020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a5d579182015b82811115610a5d5782358260005055916020019190600101906109b1565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328132868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b506109cf9291505b80821115610a795760008155600101610a65565b5090565b15610c2c5760008381526101096020526040812054600160a060020a031614610c2c5760408051600091909120805460018201546002929092018054600160a060020a0392909216939091819083908015610afd57820191906000526020600020905b815481529060010190602001808311610ae057829003601f168201915b505091505060006040518083038185876185025a03f150505060008481526101096020908152604080519281902080546001820154600160a060020a033281811688529587018b905293860181905292166060850181905260a06080860181815260029390930180549187018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975094958a959293909160c083019084908015610bcf57820191906000526020600020905b815481529060010190602001808311610bb257829003601f168201915b5050965050505050505060405180910390a160008381526101096020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c3292601f9290920104810190610a65565b50919050565b50505060019150506101aa565b60008581526101036020526040812080549093501415610cc7576000805483556001838101919091556101048054918201808255828015829011610c9657818360005260206000209182019101610c969190610a65565b50505060028301819055610104805487929081101561000257600091909152600080516020610f9f83398151915201555b506001810154600283900a90811660001415610d975760408051600160a060020a03321681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610d84576000858152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f9f8339815191529290920181905580825560018083018290556002909201559450610d979050565b8154600019018255600182018054821790555b505050919050565b5b60018054118015610dc257506001546002906101008110156100025701546000145b15610dd65760018054600019019055610da0565b60015481108015610df95750600154600290610100811015610002570154600014155b8015610e1357506002816101008110156100025701546000145b15610e7457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b610691565b156101aa5761010754610e8f5b62015180420490565b1115610ea857600061010655610ea3610e86565b610107555b6101065480830110801590610ec65750610106546101055490830111155b15610edc575061010680548201905560016101aa565b5060006101aa565b61063c6101045460005b81811015610f745761010480548290811015610002576000918252600080516020610f9f833981519152015414610f6157610104805461010391600091849081101561000257600080516020610f9f83398151915201548252506020919091526040812081815560018101829055600201555b600101610eee565b50505060010161052f565b61010480546000808355919091526104dd90600080516020610f9f83398151915290810190610a6556004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe" - }, - "0x4f5777744b500616697cb655dcb02ee6cd51deb5": { - "balance": "0xb0983f1b83eec290", - "nonce": "2" - }, - "0xf8b483dba2c3b7176a3da549ad41a48bb3121069": { - "balance": "0x16969a0ba2c2d384d07", - "nonce": "67521" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "995201", - "difficulty": "11940626048551", - "timestamp": "1455322773", - "gasLimit": "3141592", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069" - }, - "input": "0xf89102850a954d522e8303308594200edd17f30485a8735878661960cd7a9a95733f888ac7230489e80000a4ba51a6df00000000000000000000000000000000000000000000000000000000000000001ca04f2cc45b96f965296382b2e9b657e90808301d5179035a5d91a2de7b912def20a056e19271ea4e19e4e034f38e925e312beed4d300c267160eeb2f565c42deb578", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0x4f5777744b500616697cb655dcb02ee6cd51deb5", - "gas": "0x33085", - "gasUsed": "0x1a9e5", - "to": "0x200edd17f30485a8735878661960cd7a9a95733f", - "input": "0xba51a6df0000000000000000000000000000000000000000000000000000000000000000", - "output": "0xba51a6df00000000000000000000000000000000000000000000000000000000", - "calls": [ - { - "from": "0x200edd17f30485a8735878661960cd7a9a95733f", - "gas": "0x2c263", - "gasUsed": "0x1b0e4", - "to": "0x273930d21e01ee25e4c219b63259d214872220a2", - "input": "0xba51a6df0000000000000000000000000000000000000000000000000000000000000000", - "logs": [ - { - "address": "0x200edd17f30485a8735878661960cd7a9a95733f", - "topics": [ - "0xe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda" - ], - "data": "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5be96016bb57376da7a6d296e0a405ee1501778227dfa604df0a81cb1ae018598", - "position": "0x0" - }, - { - "address": "0x200edd17f30485a8735878661960cd7a9a95733f", - "topics": [ - "0xacbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000", - "position": "0x0" - } - ], - "value": "0x8ac7230489e80000", - "type": "CALLCODE" - } - ], - "value": "0x8ac7230489e80000", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json deleted file mode 100644 index 2b03dbb8d..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json +++ /dev/null @@ -1,413 +0,0 @@ -{ - "genesis": { - "difficulty": "80344740444880", - "extraData": "0x7777772e62772e636f6d", - "gasLimit": "1498600", - "hash": "0xf5d85a80bdbc5d28a16b8eb0d1b9dd18316ddc3655c7d5c901b67acdb7700037", - "miner": "0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1", - "mixHash": "0x433ae590edf0e7ba9aac698bb7d3be2300e3e79d175db13528ff3e79a3f93910", - "nonce": "0x084adce0020c6fd8", - "number": "2340152", - "stateRoot": "0x38295a2634c9c62d48bcbf2ef2ae83768b9055c1f5e6469d17a5d1bcb052072e", - "timestamp": "1475034708", - "totalDifficulty": "66488249547380413902", - "alloc": { - "0x01e60b511fced1eb2b5b40991eb1dfd171a6df42": { - "balance": "0x0", - "code": "0x6060604052361561008d5760e060020a600035046306fdde03811461008f578063095ea7b3146100a557806318160ddd1461012457806323b872dd1461012f578063313ce567146101dc578063475a9fa9146101f057806370a0823114610215578063721a37d21461024357806395d89b411461008f578063a9059cbb14610268578063dd62ed3e146102e7575b005b61031d6040805160208101909152600081525b90565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db63c6605267600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b6102316003546100a2565b61038b60043560243560443560008054604080517fa00bfa1100000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038781166024830152868116604483015260648201869052929092166084830152517319ee743d2e356d5f0e4d97cc09b96d06e933d0db9163a00bfa119160a482810192602092919082900301818660325a03f4156100025750506040515195945050505050565b604080516000815290519081900360200190f35b61038b6004356024356000805433600160a060020a0390811691161461039f57610002565b600160a060020a03600435166000908152600160205260409020545b60408051918252519081900360200190f35b61038b6004356024356000805433600160a060020a039081169116146103ce57610002565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db6388d5fecb600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b610231600435602435600160a060020a038281166000908152600260209081526040808320938516835292905220545b92915050565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561037d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b604080519115158252519081900360200190f35b50600160a060020a03821660009081526001602081905260409091208054830190556003805483019055610317565b600160a060020a038316600090815260016020526040902054821161040a57506040600020805482900390556003805482900390556001610317565b50600061031756", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000012098a4651fb262f7", - "0xfae22198212900725daa5db635d1fda7b0fa195adaabdc806a7267959c3d8ae4": "0x00000000000000000000000000000000000000000000000026cbcbc35aaa62f7" - } - }, - "0x19ee743d2e356d5f0e4d97cc09b96d06e933d0db": { - "balance": "0x0", - "code": "0x6503060000000050606060405260e060020a600035046388d5fecb811461003c578063a00bfa11146100e3578063c6605267146102dc575b610007565b610356600435602435604435600160a060020a0333166000908152602084905260408120548290108015906100715750600082115b1561036a57600160a060020a0333811660008181526020878152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161034f565b610356600435602435604435606435608435600160a060020a03841660009081526020869052604081205483901080159061011e5750600083115b80156101bb5750600160a060020a0385811660009081526001880160209081526040808320339094168352929052205483901015806101bb575081600160a060020a0316631934d55a86336040518360e060020a0281526004018083600160a060020a0316815260200182600160a060020a03168152602001925050506020604051808303816000876161da5a03f1156100075750506040515190505b1561037257600160a060020a038481166000908152602088815260408083208054880190558884168084528184208054899003905581517f1934d55a00000000000000000000000000000000000000000000000000000000815260048101919091523385166024820152905193861693631934d55a936044838101949383900301908290876161da5a03f115610007575050604051511515905061028957600160a060020a038581166000908152600188016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3506001610376565b610356600435602435604435600160a060020a033381166000818152600186016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b9392505050565b604080519115158252519081900360200190f35b50600061034f565b5060005b9594505050505056" - }, - "0x3de712784baf97260455ae25fb74f574ec9c1add": { - "balance": "0x23c8352f33854625", - "nonce": "80" - }, - "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd": { - "balance": "0x0", - "nonce": "29", - "code": "0x606060405236156100cf5760e060020a600035046307d5b82681146100d157806315e812ad146101775780631934d55a1461018d5780631d007f5f146101c65780631f0c1e0c146101ee5780633983d5c41461022b5780634025b29314610243578063428d64bd1461030f578063481b659d146104b557806357bcccb6146104f45780638c172fa21461052f5780639ba5b4e9146105ea578063a4a7cf5c146106ca578063b11e3b82146106ed578063c51cf179146107a6578063d6911046146107c2578063eff6be2f146109cb575b005b6109f2600435602435600082815260016020908152604080832060049081015482517f23b872dd00000000000000000000000000000000000000000000000000000000815233600160a060020a0390811693820193909352308316602482015260448101879052925185948594859493909316926323b872dd9260648281019392829003018187876161da5a03f1156100025750506040515115159050610a6d57610002565b6004545b60408051918252519081900360200190f35b6109f2600435602435600160a060020a0382811660009081526003602090815260408083209385168352929052205460ff165b92915050565b6109f2600435600080546101009004600160a060020a039081163390911614610be757610002565b610a066004356024356000828152600160205260408120600901805483908110156100025750815260209020810154600160a060020a03166101c0565b61017b6004355b600454620f4240908202045b919050565b6109f26004356024356000805b600084815260016020526040902060090154811015610c13576040600090812090859052600160205260090180548290811015610002576000918252604080516020808520909301547f721a37d2000000000000000000000000000000000000000000000000000000008252600160a060020a03338116600484015260248301899052925192169363721a37d293604483810194919391929183900301908290876161da5a03f1156100025750506040515115159050610c8d57610002565b604080516024803560048181013560208181028087018201909752818652610a2396833596939560449501929182919085019084908082843750949650505050505050604080516020818101835260008083528351918201909352828152909190819081905b8551831015610c9f57600091505b600160005060008785815181101561000257602090810290910181015182528101919091526040016000206009015460ff831610156104a957600060016000506000888681518110156100025760209081029091018101518252810191909152604001600020600901805460ff85169081101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a03166370a08231896040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191909111159050610f59576001600050600087858151811015610002576020908102909101810151825281019190915260400160002060090154909301600201925b60019290920191610375565b6109f260043533600160a060020a039081166000908152600360209081526040808320938516835292905220805460ff1916600190811790915561023e565b6109f260043533600160a060020a039081166000908152600360209081526040808320938516835292905220805460ff19169055600161023e565b60048035600090815260016020818152604092839020600981015481548551968301546002840154600385015460088601546005870154600688015499880154600790980154958c52600160a060020a03888116998d019990995260a060020a90970460ff90811615158c8c015260608c019390935260808b019190915260a08a019490945290851660c08901529290931660e087015261010086019390935216151561012084015261014083015251908190036101600190f35b60408051600480358082013560208181028086018201909652818552610a23959394602494909385019291829190850190849080828437509496505050505050506040805160208181018352600080835283519182019093528281529091908190815b8551831015610f93576000600260005060008886815181101561000257602090810290910181015182528101919091526040016000205411156106be576002600050600087858151811015610002576020908102909101810151825281019190915260400160002054909301600201925b6001929092019161064d565b61017b6004356000805481908190819081908190819060ff161561115757610002565b6040805160e4356004818101356020818102808601820190965281855261017b95833595602480359660443596606435966084359660a4359660c4359693956101049501929182919085019084908082843750949650505050505050600080808080808d81148061076657508c801561076657508a8c12155b80610774575060028a60ff16105b80610788575087600160a060020a03166000145b8061079c575088600160a060020a03166000145b1561177157611760565b61017b600435600454620f42409081039082020481900361023e565b60408051600480358082013560208181028086018201909652818552610a23959394602494909385019291829190850190849080828437509496505093359350506044359150506064356040805160208181018352600080835283519182019093528281529091908190815b8851831015611cee576000600102600160005060008b8681518110156100025760209081029091018101518252810191909152604001600020541180156108c7575087600160a060020a0316600014806108c7575087600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060050154600160a060020a0316145b8015610925575086600160a060020a031660001480610925575086600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060040154600160a060020a0316145b8015610983575085600160a060020a031660001480610983575085600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060010154600160a060020a0316145b156109bf57600160005060008a858151811015610002576020908102909101810151825281019190915260400160002060090154909301600c01925b6001929092019161082e565b6109f26004356000805433600160a060020a03908116610100909204161461234c57610002565b604080519115158252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050019250505060405180910390f35b610a7685610232565b92508285039150600083118015610b00575060008681526001602090815260408083206004908101548251855460e060020a63a9059cbb0282526101009004600160a060020a039081169382019390935260248101899052925191169363a9059cbb936044848101949193929183900301908290876161da5a03f115610002575050604051511590505b15610b0a57610002565b5060005b60008681526001602052604090206009015460ff82161015610bd35760406000908120908790526001602052600901805460ff831690811015610002576000918252604080516020808520909301547f475a9fa9000000000000000000000000000000000000000000000000000000008252600160a060020a03338116600484015260248301889052925192169363475a9fa993604483810194919391929183900301908290876161da5a03f1156100025750506040515115159050610bdf57610002565b50600195945050505050565b600101610b0e565b506000805474ffffffffffffffffffffffffffffffffffffffff0019166101008302179055600161023e565b6000848152600160209081526040808320600490810154825160e060020a63a9059cbb028152600160a060020a033381169382019390935260248101899052925191169363a9059cbb936044848101949193929183900301908290876161da5a03f1156100025750506040515115159050610c9557610002565b600101610250565b5060019392505050565b83604051805910610cad5750595b908082528060200260200182016040528015610cc4575b506000945084935090505b8551831015610f6557600091505b600160005060008785815181101561000257602090810290910181015182528101919091526040016000206009015460ff83161015610f7b57600060016000506000888681518110156100025760209081029091018101518252810191909152604001600020600901805460ff85169081101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a03166370a08231896040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191909111159050610f8757858381518110156100025790602001906020020151600190048185815181101561000257602090810290910101528551600190600090889086908110156100025760209081029091018101518252810191909152604001600020600901548151829060018701908110156100025760209081029091010152600091505b600160005060008785815181101561000257602090810290910181015182528101919091526040016000206009015460ff83161015610f6f5760016000506000878581518110156100025760209081029091018101518252810191909152604001600020600901805460ff84169081101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a03166370a08231886040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051518251909150829060ff8516870160020190811015610002576020908102909101015260019190910190610e49565b60019190910190610383565b9695505050505050565b6002820160ff16909301925b60019290920191610ccf565b60019190910190610cdd565b83604051805910610fa15750595b908082528060200260200182016040528015610fb8575b506000945084935091505b85518310156111125760006002600050600088868151811015610002576020908102909101810151825281019190915260400160002054111561114b578583815181101561000257906020019060200201516001900482858151811015610002576020908102909101015285516002906000908890869081101561000257602090810290910181015182528101919091526040016000205482518390600187019081101561000257602090810290910101525060005b600260005060008785815181101561000257602090810290910181015182528101919091526040016000205481101561111b5760026000506000878581518110156100025760209081029091018101518252810191909152604001600020805482908110156100025760009182526020909120015482518390868401600201908110156100025760209081029091010152600101611079565b50949350505050565b60026000506000878581518110156100025750506020858102890181015182528290526040902054909401909301925b60019290920191610fc3565b6000805460ff191660019081178255898252602052604090206007015460ff1615156112e85760406000818120600581015483516006909201547f5101770200000000000000000000000000000000000000000000000000000000835260048301529251600160a060020a0393909316926351017702926024838101936020939290839003909101908290876161da5a03f115610002575050604051511515905061120457611338611347565b6000888152600160209081526040808320815160058201546006909201547f5d1a3b8200000000000000000000000000000000000000000000000000000000825260048201529151600160a060020a039190911693635d1a3b82936024808501949193929183900301908290876161da5a03f1156100025750505060405180519060200150600160005060008a600019168152602001908152602001600020600050600801600050819055506001600160005060008a60001916815260200190815260200160002060005060070160006101000a81548160ff021916908302179055505b6000888152600160208190526040909120015460a060020a900460ff16156113535760406000908120908990526001602052600281015460089091015412156115435760009450611598565b8596505b505050505050919050565b6113345b6000805460ff19169055565b6000888152600160205260409020600981018054600890920154909181101561000257600091825260208083206040805193909101547f70a08231000000000000000000000000000000000000000000000000000000008452600160a060020a03338116600486015291519116936370a082319360248181019493929183900301908290876161da5a03f115610002575050604051519650505b600091505b60008881526001602052604090206009015460ff831610156116d65760406000908120908990526001602052600901805460ff84169081101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a03166370a08231336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604080515160008b81526001602052919091206009018054919350915060ff84169081101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a031663721a37d233836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061175057610002565b60008881526001602052604090206003810154600890910154131561156c576127109450611598565b600088815260016020526040902060028101546003820154600890920154918190039103612710020594505b6000888152600160208190526040909120600901805461271088810361ffff16975087810396509286929181101561000257906000526020600020900160009054906101000a9004600160a060020a0316600160a060020a03166370a08231336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604080515160008d815260016020529182206009018054919094029389935091908110156100025790815260208120909054906101000a9004600160a060020a0316600160a060020a03166370a08231336040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750505060405180519060200150020104955085506113ed565b6000888152600160209081526040808320600490810154825160e060020a63a9059cbb028152600160a060020a0333811693820193909352602481018c9052925191169363a9059cbb936044848101949193929183900301908290876161da5a03f115610002575050604051511515905061134357610002565b600191909101906113f2565b8495505b505050505098975050505050505050565b8d8d8d8d8d8d8d8d604051808960001916815260200188151560f860020a0281526001018781526020018681526020018560ff1660f860020a02815260010184600160a060020a03166c0100000000000000000000000002815260140183600160a060020a03166c010000000000000000000000000281526014018280519060200190602002808383829060006004602084601f0104600302600f01f1509050019850505050505050505060405180910390209450600060010260016000506000876000191681526020019081526020016000206000506000016000505460001916111561185e57611760565b87600160a060020a031663c91d7e9c886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f150905001925050506040604051808303816000876161da5a03f1156100025750506040518051602091909101519095509350506000841180156119bd575082600160a060020a03166323b872dd3330876040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506020604051808303816000876161da5a03f11561000257505060405151159050806119bd575082600160a060020a031663095ea7b389866040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511590505b156119c757610002565b87600160a060020a031663c1b06513886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f150905001925050506020604051808303816000876161da5a03f115610002575050604051519250506000821415611a5257610002565b60008e81526002602052604090208054600181018083558281838015829011611a9e57818360005260206000209182019101611a9e91905b80821115611c975760008155600101611a8a565b50505091909060005260206000209001600087909190915055508d60016000506000876000191681526020019081526020016000206000506000016000508190555087600160005060008760001916815260200190815260200160002060005060050160006101000a815481600160a060020a0302191690830217905550816001600050600087600019168152602001908152602001600020600050600601600050819055508c600160005060008760001916815260200190815260200160002060005060010160146101000a81548160ff021916908302179055508b6001600050600087600019168152602001908152602001600020600050600201600050819055508a60016000506000876000191681526020019081526020016000206000506003016000508190555088600160005060008760001916815260200190815260200160002060005060040160006101000a815481600160a060020a030219169083021790555033600160005060008760001916815260200190815260200160002060005060010160006101000a815481600160a060020a0302191690830217905550600090505b8960ff168160ff16101561175c57600085815260016020819052604090912060090180549182018082559091908281838015829011611c9b57600083815260209020611c9b918101908301611a8a565b5090565b5050509190906000526020600020900160006040516104368061236c833901809050604051809103906000f0825473ffffffffffffffffffffffffffffffffffffffff1916179091555050600101611c47565b83604051805910611cfc5750595b908082528060200260200182016040528015611d13575b506000945084935091505b8851831015611fa2576000600102600160005060008b868151811015610002576020908102909101810151825281019190915260400160002054118015611db7575087600160a060020a031660001480611db7575087600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060050154600160a060020a0316145b8015611e15575086600160a060020a031660001480611e15575086600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060040154600160a060020a0316145b8015611e73575085600160a060020a031660001480611e73575085600160a060020a0316600160005060008b868151811015610002576020908102909101810151825281019190915260400160002060010154600160a060020a0316145b15611fe5578883815181101561000257906020019060200201516001900482858151811015610002576020908102909101015288516001906000908b908690811015610002576020908102909101810151825281019190915260400160002054825183906001870190811015610002576020908102909101015288516001906000908b9086908110156100025760209081029091018101518252810191909152604001600020600101548251600160a060020a03919091169083906002870190811015610002576020908102909101015288516001906000908b90869081101561000257602090810290910181015182528101919091526040016000206001015460a060020a900460ff1615611ff157600182856003018151811015610002576020908102909101015261200c565b50979650505050505050565b600160005060008a858151811015610002576020908102909101810151825281019190915260400160002060090154909301600c01925b60019290920191611d1e565b60008285600301815181101561000257602090810290910101525b600160005060008a858151811015610002576020908102909101810151825281019190915260400160002060020154825183906004870190811015610002576020908102909101015288516001906000908b908690811015610002576020908102909101810151825281019190915260400160002060030154825183906005870190811015610002576020908102909101015288516001906000908b9086908110156100025760209081029091018101518252810191909152604001600020600401548251600160a060020a03919091169083906006870190811015610002576020908102909101015288516001906000908b9086908110156100025760209081029091018101518252810191909152604001600020600501548251600160a060020a03919091169083906007870190811015610002576020908102909101015288516001906000908b908690811015610002576020908102909101810151825281019190915260400160002060060154825183906008870190811015610002576020908102909101015288516001906000908b90869081101561000257602090810290910181015182528101919091526040016000206007015460ff16156121ee576001828560090181518110156100025760209081029091010152612209565b60008285600901815181101561000257602090810290910101525b600160005060008a85815181101561000257602090810290910181015182528101919091526040016000206008015482518390600a870190811015610002576020908102909101015288516001906000908b90869081101561000257602090810290910181015182528101919091526040016000206009015482518390600b87019081101561000257602090810290910101525060005b600160005060008a858151811015610002576020908102909101810151825281019190915260400160002060090154811015611fae57600160005060008a858151811015610002576020908102909101810151825281019190915260400160002060090180548290811015610002576000918252602090912001548251600160a060020a0391909116908390868401600c019081101561000257602090810290910101526001016122a0565b620f424082101561236457506004819055600161023e565b50600061023e56606060405260008054600160a060020a03191633179055610412806100246000396000f36060604052361561008d5760e060020a600035046306fdde03811461008f578063095ea7b3146100a557806318160ddd1461012457806323b872dd1461012f578063313ce567146101dc578063475a9fa9146101f057806370a0823114610215578063721a37d21461024357806395d89b411461008f578063a9059cbb14610268578063dd62ed3e146102e7575b005b61031d6040805160208101909152600081525b90565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db63c6605267600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b6102316003546100a2565b61038b60043560243560443560008054604080517fa00bfa1100000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038781166024830152868116604483015260648201869052929092166084830152517319ee743d2e356d5f0e4d97cc09b96d06e933d0db9163a00bfa119160a482810192602092919082900301818660325a03f4156100025750506040515195945050505050565b604080516000815290519081900360200190f35b61038b6004356024356000805433600160a060020a0390811691161461039f57610002565b600160a060020a03600435166000908152600160205260409020545b60408051918252519081900360200190f35b61038b6004356024356000805433600160a060020a039081169116146103ce57610002565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db6388d5fecb600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b610231600435602435600160a060020a038281166000908152600260209081526040808320938516835292905220545b92915050565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561037d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b604080519115158252519081900360200190f35b50600160a060020a03821660009081526001602081905260409091208054830190556003805483019055610317565b600160a060020a038316600090815260016020526040902054821161040a57506040600020805482900390556003805482900390556001610317565b50600061031756", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000950ca4a06c78934a148b7a3ff3ea8fc366f77a0600", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x00000000000000000000000000000000000000000000000000000000000007d0", - "0x6b8ad191d0fa8204d4eafca22ce4ec42425fde2eecf25ce484ecc76765b9a937": "0x00000000000000000000000001e60b511fced1eb2b5b40991eb1dfd171a6df42", - "0x6b8ad191d0fa8204d4eafca22ce4ec42425fde2eecf25ce484ecc76765b9a938": "0x000000000000000000000000f4cbd7e037b80c2e67b80512d482685f15b1fb28", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e854": "0x446374989d279847d0dbc6708a9c76a419fe9831d42c78bc89473f559a00d915", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e855": "0x00000000000000000000000061d76c05cd2aa9ed5135e21e52fff188b02089d4", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e856": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e857": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e858": "0x00000000000000000000000092f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e859": "0x000000000000000000000000529c4cb814029b8bb32acb516ea3a4b07fdae350", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e85a": "0x846fd373887ade3ab7703750294876afa61cf56303f5f014a4d80d04f508a1f1", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e85b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e85c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x71dbd1e5cfc57324881ede454ea48ef3502c5c0b0454ccd622624a7061c2e85d": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - }, - "0x61c808d82a3ac53231750dadc13c777b59310bd9": { - "balance": "0x90a7af5d4755984561", - "nonce": "197408" - }, - "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5": { - "balance": "0x0", - "code": "0x606060405236156100a35760e060020a6000350463031d973e81146100a557806316181bb7146100da5780635aa97eeb146103b1578063674cc1f5146104f75780636da84ec0146105d7578063929e626e146105fe578063a0bde7e8146106ac578063bbd4f8541461078b578063c1fd43391461098e578063c3c95c7b14610a88578063db833e3a14610afe578063df6c13c314610cfe578063ebb7119414610d13575b005b610d4960043560008181526020819052604081206004015481908390600160a060020a039081163390911614610dcb57610002565b610d0160043560243560443560643560008481526020819052604080822054815160e160020a63460b97d1028152600481018290529151909183918291829182916000805160206123dd83398151915291638c172fa29160248181019261016092909190829003018187876161da5a03f1156100025750506040805160a081015160c08201517fc51cf179000000000000000000000000000000000000000000000000000000008352600483018d90529251909750919550600160a060020a038616926323b872dd92339230929163c51cf1799160248181019260209290919082900301818b876161da5a03f11561000257505060408051805160e060020a6323b872dd028252600160a060020a039586166004830152939094166024850152918d01604484015250516064828101926020929190829003018187876161da5a03f11561000257505060405151159050806102e8575082600160a060020a031663095ea7b36000805160206123dd8339815191526000805160206123dd833981519152600160a060020a031663c51cf1798c6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a63095ea7b30282526004820193909352918d0160248301525160448281019350602092829003018187876161da5a03f115610002575050604051511590505b806103a757506000805160206123dd833981519152600160a060020a03166307d5b826866000805160206123dd833981519152600160a060020a031663c51cf1798c6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e160020a6303eadc130282526004820194909452928d016024840152516044838101936020935082900301816000876161da5a03f115610002575050604051511590505b15610fcd57610002565b60408051600480358082013560208181028086018201909652818552610d5d9593946024949093850192918291908501908490808284375094965050933593505050506040805160208181018352600080835283519182019093528281529091908190815b86518310156112c757600060010260006000506000898681518110156100025760209081029091018101518252810191909152604001600020541180156104af575085600160a060020a0316600014806104af575085600160a060020a03166000600050600089868151811015610002576020908102909101810151825281019190915260400160002060040154600160a060020a0316145b156104eb576000600050600088858151811015610002576020908102909101810151825281019190915260400160002060070154909301600901925b60019290920191610416565b60408051600480358082013560208181028086018201909652818552610d5d959394602494909385019291829190850190849080828437509496505050505050506040805160208181018352600080835283519182019093528281529091908190815b8551831015611713576000600160005060008886815181101561000257602090810290910181015182528101919091526040016000205411156105cb576001600050600087858151811015610002576020908102909101810151825281019190915260400160002054909301600201925b6001929092019161055a565b610d016004356024355b60009182526020829052604090912060010154620f424091020490565b610da760043561200060405190810160405280610100905b6000815260200190600190039081610616575050604080516120008101909152610100815b600081526020019060019003908161063b5750600090505b60008481526020819052604090206007015460ff821610156118d8576040600020600701805460ff8316908110156100025760009182526020909120810154908390610100811015610002576020020152600101610653565b610d5d600435604080516020818101835260008083528351808301855281815285825291819052835193812060070154929391929091600191909101908059106106f35750595b90808252806020026020018201604052801561070a575b509150428260008151811015610002576020919091019190915290505b60008481526020819052604090206007015460ff821610156118d8576040600020600701805460ff83169081101561000257906000526020600020900160005054828260010160ff1681518110156100025760209081029091010152600101610727565b610d0160043560243560443560643560008481526020819052604080822054815160e160020a63460b97d102815260048101919091529051829182918291829182916000805160206123dd83398151915291638c172fa29160248181019261016092909190829003018187876161da5a03f1156100025750505060405180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200150505050509a50505050505050600060005060008b60001916815260200190815260200160002060005060050160009054906101000a9004600160a060020a0316600160a060020a0316630439978d8b600060005060008e60001916815260200190815260200160002060005060030160005054600060005060008f6000191681526020019081526020016000206000506007016000508d8d6040518660e060020a0281526004018086600019168152602001858152602001806020018460ff168152602001838152602001828103825285818154815260200191508054801561095657602002820191906000526020600020905b81600050548152602001906001019080831161093f575b505096505050505050506020604051808303816000876161da5a03f1156100025750506040515194505060008414156118e357610fc0565b610d01600435602435604435606435600060006000600060006000805160206123dd833981519152600160a060020a0316638c172fa28a6040518260e060020a0281526004018082600019168152602001915050610160604051808303816000876161da5a03f1156100025750506040805160a081015160c08201518d83526c01000000000000000000000000600160a060020a033381168202602086810191909152908d16909102603485015284516048948190039490940190932080875292869052928520600301549097509195509350821415905080610a7357506207a12088115b80610a7e5750836000145b15611cc857611cbc565b60048035600090815260208181526040918290206002810154815484516001840154600385015497850154600586015460069096015493835295820152808601929092526060820195909552600160a060020a039283166080820152911660a082015260c0810192909252519081900360e00190f35b610d0160043560243560443560643560008481526020819052604080822054815160e160020a63460b97d10281526004810191909152905182918291829182916000805160206123dd83398151915291638c172fa291602482810192610160929190829003018187876161da5a03f1156100025750505060405180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200180519060200150505050509950505050505050600060005060008a60001916815260200190815260200160002060005060050160009054906101000a9004600160a060020a0316600160a060020a031663f47cd6718a600060005060008d60001916815260200190815260200160002060005060030160005054600060005060008e6000191681526020019081526020016000206000506007016000508c8c6040518660e060020a0281526004018086600019168152602001858152602001806020018460ff1681526020018381526020018281038252858181548152602001915080548015610cc657602002820191906000526020600020905b816000505481526020019060010190808311610caf575b505096505050505050506020604051808303816000876161da5a03f11561000257505060405151935050600083141561201957611cbc565b60005b60408051918252519081900360200190f35b610d0160043560008181526020819052604081206004015481908190849033600160a060020a039081169116146122df57610002565b604080519115158252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190602002808383829060006004602084601f0104600302600f01f1509050019250505060405180910390f35b6040518082612000808381846000600461030ff15090500191505060405180910390f35b600091505b60008481526020819052604090206007015460ff83161015610eed576040600081812086825260208281528351915460e260020a6307c30783028352600483015260ff8616602483015292516000805160206123dd83398151915293631f0c1e0c9360448481019492939283900301908290876161da5a03f115610002575050604080515160008781526020819052919091206007018054600160a060020a0392909216925063a9059cbb9133919060ff871690811015610002579060005260206000209001600050546040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f1156100025750506040515115159050610f7357610002565b60406000908120602082815282825560018201839055600282018390556003820183905560048201805473ffffffffffffffffffffffffffffffffffffffff19908116909155600583018054909116905560068201839055600782018054848255908452908320919291610fa7918101905b80821115610fb45760008155600101610f5f565b6000848152602081905260408120600701805460ff8516908110156100025790825260208220015560019190910190610dd0565b5060019695505050505050565b5090565b818385010195505b5050505050949350505050565b6040805160e260020a6307c307830281526004810187905260ff8b16602482015290516000805160206123dd83398151915291631f0c1e0c91604482810192602092919082900301816000876161da5a03f11561000257505060408051805160e060020a63095ea7b302825230600160a060020a039081166004840152602483018d905292519216925063095ea7b391604482810192602092919082900301816000876161da5a03f115610002575050604051511515905061108e57610002565b604080517fdb833e3a000000000000000000000000000000000000000000000000000000008152600481018c905260ff8b166024820152604481018a905260648101899052905130600160a060020a03169163db833e3a91608482810192602092919082900301816000876161da5a03f11561000257505060405151925050600082141561111b57610002565b5060005b838160ff1610156111f75760ff808a169082161461125b576040805160e260020a6307c307830281526004810187905260ff8316602482015290516000805160206123dd83398151915291631f0c1e0c91604482810192602092919082900301816000876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600160a060020a033381166004840152602483018d905292519216925063a9059cbb91604482810192602092919082900301816000876161da5a03f115610002575050604051511515905061125b57610002565b82600160a060020a031663a9059cbb33846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061126357610002565b60010161111f565b816000805160206123dd833981519152600160a060020a031663c51cf1798a6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f115610002575050604051518a01919091039650610fc09050565b836040518059106112d55750595b9080825280602002602001820160405280156112ec575b506000945084935091505b86518310156116c65760006001026000600050600089868151811015610002576020908102909101810151825281019190915260400160002054118015611390575085600160a060020a031660001480611390575085600160a060020a03166000600050600089868151811015610002576020908102909101810151825281019190915260400160002060040154600160a060020a0316145b1561170757868381518110156100025790602001906020020151600190048285815181101561000257602090810290910101528651600090819089908690811015610002576020908102909101810151825281019190915260400160002054825183906001870190811015610002576020908102909101015286516000908190899086908110156100025760209081029091018101518252810191909152604001600020600101548251839060028701908110156100025760209081029091010152865160009081908990869081101561000257602090810290910181015182528101919091526040016000206002015482518390600387019081101561000257602090810290910101528651600090819089908690811015610002576020908102909101810151825281019190915260400160002060030154825183906004870190811015610002576020908102909101015286516000908190899086908110156100025760209081029091018101518252810191909152604001600020600401548251600160a060020a03919091169083906005870190811015610002576020908102909101015286516000908190899086908110156100025760209081029091018101518252810191909152604001600020600501548251600160a060020a03919091169083906006870190811015610002576020908102909101015286516000908190899086908110156100025760209081029091018101518252810191909152604001600020600601548251839060078701908110156100025760209081029091010152865160009081908990869081101561000257602090810290910181015182528101919091526040016000206007015482518390600887019081101561000257602090810290910101525060005b60006000506000888581518110156100025760209081029091018101518252810191909152604001600020600701548110156116d0576000600050600088858151811015610002576020908102909101810151825281019190915260400160002060070180548290811015610002579060005260206000209001600050548282866009010181518110156100025760209081029091010152600101611626565b5095945050505050565b6000600050600088858151811015610002576020908102909101810151825281019190915260400160002060070154909301600901925b600192909201916112f7565b836040518059106117215750595b908082528060200260200182016040528015611738575b506000945084935091505b8551831015611892576000600160005060008886815181101561000257602090810290910181015182528101919091526040016000205411156118cc578583815181101561000257906020019060200201516001900482858151811015610002576020908102909101015285516001906000908890869081101561000257602090810290910181015182528101919091526040016000205482518390600187019081101561000257602090810290910101525060005b600160005060008785815181101561000257602090810290910181015182528101919091526040016000205481101561189b57600160005060008785815181101561000257602090810290910181015182528101919091526040016000208054829081101561000257600091825260209091200154825183908684016002019081101561000257602090810290910101526001016117f9565b50949350505050565b6001600050600087858151811015610002575050602085810289018101518252919091526040902054909301600201925b60019290920191611743565b8192505b5050919050565b6118ed8a856105e1565b92506000805160206123dd833981519152600160a060020a031663c51cf179896040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f1156100025750506040515192505083830182018790111561195857610fc0565b84600160a060020a03166323b872dd333085878901016040518460e060020a0281526004018084600160a060020a0316815260200183600160a060020a0316815260200182815260200193505050506020604051808303816000876161da5a03f1156100025750506040515115905080611a3557506040805160e060020a63095ea7b30281526000805160206123dd833981519152600482015285840160248201529051600160a060020a0387169163095ea7b391604482810192602092919082900301816000876161da5a03f115610002575050604051511590505b80611aa9575060008a81526020818152604080832054815160e160020a6303eadc130281526004810191909152878601602482015290516000805160206123dd833981519152936307d5b826936044848101949193929183900301908290876161da5a03f115610002575050604051511590505b15611ab357610002565b5060005b60008a81526020819052604090206007015460ff82161015611b06576040600020600701805485919060ff84169081101561000257600091825260209091200180549091019055600101611ab7565b604060009081208b8252602091909152600701805460ff8b169081101561000257600091825260209091200154881115611b3f57610002565b60008a815260208190526040902060028101805485019055600701805489919060ff8c1690811015610002579060005260206000209001600050805491909103905560008a81526020818152604080832054815160e260020a6307c30783028152600481019190915260ff8d16602482015290516000805160206123dd83398151915293631f0c1e0c936044848101949193929183900301908290876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600160a060020a033381166004840152602483018d905292519216925063a9059cbb91604482810192602092919082900301816000876161da5a03f1156100025750506040515115159050610fb857610002565b505050600092835250602080832090910184905583825281905260409020600181018990556003810188905589815560048101805473ffffffffffffffffffffffffffffffffffffffff199081163317909155600582018054909116881790554360069091015590935083905b50505050949350505050565b82600160a060020a03166323b872dd33306000805160206123dd833981519152600160a060020a031663c51cf1798c6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a6323b872dd028252600160a060020a039586166004830152939094166024850152918c0160448401525051606482810192602092919082900301816000876161da5a03f1156100025750506040515115905080611e45575082600160a060020a031663095ea7b36000805160206123dd8339815191526000805160206123dd833981519152600160a060020a031663c51cf1798b6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e060020a63095ea7b30282526004820193909352918c016024830152516044828101935060209282900301816000876161da5a03f115610002575050604051511590505b80611f0457506000805160206123dd833981519152600160a060020a03166307d5b8268a6000805160206123dd833981519152600160a060020a031663c51cf1798b6040518260e060020a028152600401808281526020019150506020604051808303816000876161da5a03f11561000257505060408051805160e160020a6303eadc130282526004820194909452928c016024840152516044838101936020935082900301816000876161da5a03f115610002575050604051511590505b15611f0e57610002565b83604051805910611f1c5750595b908082528060200260200182016040528015611f33575b506000838152602081815260408220600701805484518083558285529383902091949082019392018215611f86579160200282015b82811115611f86578251826000505591602001919060010190611f68565b50611f92929150610f5f565b5050600090505b838160ff161015611fda576000828152602081905260409020600701805488919060ff84169081101561000257600091825260209091200155600101611f99565b600089815260016020819052604090912080549182018082559091908281838015829011611c4f57600083815260209020611c4f918101908301610f5f565b61202389846105e1565b915085828403101561203457611cbc565b60008981526020818152604080832054815160e260020a6307c30783028152600481019190915260ff8c16602482015290516000805160206123dd83398151915293631f0c1e0c936044848101949193929183900301908290876161da5a03f11561000257505060408051805160e060020a6323b872dd028252600160a060020a0333811660048401523081166024840152604483018c90529251921692506323b872dd91606482810192602092919082900301816000876161da5a03f115610002575050604051511590508061218d57506000805160206123dd833981519152600160a060020a0316634025b293600060005060008c60001916815260200190815260200160002060005060000160005054856040518360e060020a0281526004018083600019168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511590505b1561219757610002565b6000898152602081905260409020600701805488919060ff8b16908110156100025760009182526020822001805490920190915590505b60008981526020819052604090206007015460ff82161015612254576040600020600701805484919060ff84169081101561000257600091825260209091200154106122d0576000898152602081905260409020600701805484919060ff84169081101561000257906000526020600020900160005080549190910390556001016121ce565b600089815260208181526040808320600201805486019055805160e060020a63a9059cbb028152600160a060020a033381166004830152868803602483015291519188169363a9059cbb93604483810194919391929183900301908290876161da5a03f11561000257505060405151151590506122d557610002565b610002565b8183039450611cbc565b60008581526020819052604080822054815160e160020a63460b97d1028152600481019190915290516000805160206123dd83398151915292638c172fa292602481810193610160939092839003909101908290876161da5a03f1156100025750506040805160c001516000888152602081905291822060020180549083905590955093508311905080156123ca575082600160a060020a031663a9059cbb33846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511590505b156123d457610002565b819350506118dc560000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd", - "storage": { - "0x50ff25f5e9a51687bca1c50f3544d5eef8202f228d3de791691a137aecb6b360": "0x00000000000000000000000000000000000000000000000026566ea1ec2f6a9b", - "0x50ff25f5e9a51687bca1c50f3544d5eef8202f228d3de791691a137aecb6b361": "0x00000000000000000000000000000000000000000000000072aa5b7e04d56a9b", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed86c": "0xd9a4ffe21d19763887176173d08241e8393c1dfd208f29193dfecdf854b664ac", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed86d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed86e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed86f": "0x0000000000000000000000000000000000000000000000004563918244f40000", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed871": "0x0000000000000000000000008695e5e79dab06fbbb05f445316fa4edb0da30f0", - "0x642f3c12d3cd25d9b946d8c2ec97f080f4efcff18301a6dcade5a6be0c5ed873": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - }, - "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0": { - "balance": "0x0", - "code": "0x606060405260e060020a60003504630439978d811461003157806308f028d514610115578063f47cd6711461026e575b005b60408051604435600481810135602081810285810182019096528185526103509583359560248035966064959294910192829185019084908082843750949650509335935050608435915050600060006040604051908101604052806002905b60008152602001906001900390816100915790505060006000600061271073ef3487d24a0702703e04a26cef479e313c8fc7ae6324d4e90a604060020a8c51026040518260e060020a028152600401808281526020019150506020604051808303818660325a03f41561000257505060405151919091049550610398905089610157565b60408051600480358082013560208181028086018201909652818552610362959394602494909385019291829190850190849080828437509496505050505050505b6040604051908101604052806002905b6000815260200190600190039081610167575050604080518082019091526002815b600081526020019060019003908161018957905050600083600081518110156100025760209081029091010151825283518490600090811015610002576020908102909101810151908301525060005b83518160ff1610156104a7578351825190859060ff8416908110156100025790602001906020020151101561022357838160ff168151811015610002576020908102909101015182525b60208201518451859060ff8416908110156100025790602001906020020151111561026657838160ff168151811015610002576020908102909101810151908301525b6001016101d9565b60408051604435600481810135602081810285810182019096528185526103509583359560248035966064959294910192829185019084908082843750949650509335935050608435915050600060006040604051908101604052806002905b60008152602001906001900390816102ce579050506000600061271073ef3487d24a0702703e04a26cef479e313c8fc7ae6324d4e90a604060020a8b51026040518260e060020a028152600401808281526020019150506020604051808303818660325a03f415610002575050604051519190910494506104ae905088610157565b60408051918252519081900360200190f35b60408051908190839080838184600060046015f15090500191505060405180910390f35b8095505b505050505095945050505050565b935061044d85858b8d5b6000806127108304815b85518160ff16101561051d5773ef3487d24a0702703e04a26cef479e313c8fc7ae63872fb2b589848a6000909060200201518a8660ff1681518110156100025760209081029091010151038b600060200201518c600190906020020151030304026040518260e060020a028152600401808281526020019150506020604051808303818660325a03f4156100025750506040515190930192506001016103ac565b925086898960ff16815181101561000257602090810290910101805191909103905261047b85858b8d6103a2565b915050604060020a620186a0620186a28484036127108d0402020404868111156103865786955061038a565b5092915050565b6020810180518801905292506104c684848a8c6103a2565b915085888860ff16815181101561000257602090810290910101805190910190526104f384848a8c6103a2565b9050604060020a620186a06127108b04838503026201869e02040494505050505095945050505050565b87604060020a73ef3487d24a0702703e04a26cef479e313c8fc7ae6324d4e90a866040518260e060020a028152600401808281526020019150506020604051808303818660325a03f4156100025750506040515190910291909104999850505050505050505056" - }, - "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2": { - "balance": "0xa6e361612cc228000", - "code": "0x6060604052361561008d5760e060020a600035046306fdde03811461008f578063095ea7b3146100ed57806318160ddd1461016257806323b872dd1461016b578063313ce567146102565780636c11bcd31461026257806370a08231146102d057806395d89b41146102f5578063a9059cbb14610353578063d0febe4c146103f8578063dd62ed3e14610439575b005b6040805160038054602060026001831615610100026000190190921691909104601f810182900482028401820190945283835261046d939083018282801561052e5780601f106105035761010080835404028352916020019161052e565b61042560043560243533600160a060020a03908116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b6104db60025481565b610425600435602435604435600160a060020a0383166000908152602081905260408120548290108015906101be575060016020908152604080832033600160a060020a03168452909152812054829010155b80156101ca5750600082115b1561053657600160a060020a0383811660008181526020818152604080832080548801905588851680845281842080548990039055600183528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a350600161053a565b6104ed60055460ff1681565b61042560043533600160a060020a0316600090815260208190526040812054821161054157604081208054839003905560028054839003905580821180156102c6575060405133600160a060020a0316908290849082818181858883f19350505050155b1561054957610002565b6104db600435600160a060020a0381166000908152602081905260409020545b919050565b61046d6004805460408051602060026000196101006001871615020190941693909304601f8101849004840282018401909252818152929183018282801561052e5780601f106105035761010080835404028352916020019161052e565b61042560043560243533600160a060020a03166000908152602081905260408120548290108015906103855750600082115b156105515733600160a060020a0390811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161015c565b33600160a060020a0316600090815260208190526040902080543490810190915560028054909101905560015b604080519115158252519081900360200190f35b6104db600435602435600160a060020a0382811660009081526001602090815260408083209385168352929052205461015c565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156104cd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051918252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b81548152906001019060200180831161051157829003601f168201915b505050505081565b5060005b9392505050565b5060006102f0565b5060016102f0565b50600061015c56", - "storage": { - "0x3830062b39ca7888048a385f112e36aef7258a27d84eb6e31312c298e5954da3": "0x0000000000000000000000000000000000000000000000035fe3763f1973ab3b", - "0x527b1dd758d53f706730e0fb37a8de5c38d8b4cd17fbe1cfa285480a00f55bf4": "0x000000000000000000000000000000000000000000000003ab97b2fc29ad66c6", - "0x52cb6de4baff82acfb6977b64d52b9ac011f8af34631d933997b7649a84d716f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8f0cfa08792bcd3de052a3bb7bd54f8a62c44b02ba16ff336e9a881c348cca21": "0x000000000000000000000000000000000000000000046ba103abb9d1301f1b2e", - "0xa29249eda6f9f8d0c67b7a4f954f6ba7a9f1bb3f216b2fedc6db8def03c47746": "0x00000000000000000000000000000000000000000000000007a93ebd870d6684", - "0xbe1e23f4b08159a01ee61379749e9b484f5947aaeeb008ce7c97d1c56d3eeb8b": "0x0000000000000000000000000000000000000000000000000dfecc50c6f7d5cd" - } - }, - "0xef3487d24a0702703e04a26cef479e313c8fc7ae": { - "balance": "0x0", - "code": "0x6503060000000050606060405260e060020a600035046324d4e90a8114610031578063872fb2b514610078575b610007565b61013c6004356000680171547652b82fe177818080808061014e886000604060020a82048160bf605f5b6001830182146103c4578060020a8410156103ce579050806103d2565b61013c600435604060020a67b17217f7d1cf79ac81830281900482810460020a680100000016aee6e8ef67b172182739bc0e46858406908102869004673d7f78a624cfb9b582800288900490810288900491909101670e359bcfeb6e45319183028890049182028890040167027601df2fc048dc91830288900491820288900401665808a728816ee89183028890049182028890040166095dedef350bc991830288900491820297909704969096019190910182810295905b505050505050919050565b60408051918252519081900360200190f35b94508460020a88049350604060020a9250604060020a600a029150819050604060020a83680443b9c5adb08cc45f0204810390508050604060020a8484020492508250604060020a83680f0a52590f17c71a3f0204810190508050604060020a8484020492508250604060020a83682478f22e787502b0230204810390508050604060020a8484020492508250604060020a836848c6de1480526b8d4c0204810190508050604060020a8484020492508250604060020a836870c18cae824656408c0204810390508050604060020a8484020492508250604060020a8368883c81ec0ce7abebb20204810190508050604060020a8484020492508250604060020a836881814da94fe52ca9f50204810390508050604060020a8484020492508250604060020a8368616361924625d1acf50204810190508050604060020a8484020492508250604060020a836839f9a16fb9292a608d0204810390508050604060020a8484020492508250604060020a83681b3049a5740b21d65f0204810190508050604060020a8484020492508250604060020a836809ee1408bd5ad96f3e0204810390508050604060020a8484020492508250604060020a836802c465c91703b7a7f40204810190508050604060020a8484020492508250604060020a8367918d2d5f045a4d630204810390508050604060020a8484020492508250604060020a836714ca095145f44f780204810190508050604060020a8484020492508250604060020a836701d806fc412c1b990204810390508050604060020a8484020492508250604060020a836613950b4e1e89cc020481019050805085604060020a8383604060020a8902010302049650610131565b5090949350505050565b9150815b5060028282010461005b56" - }, - "0xf4cbd7e037b80c2e67b80512d482685f15b1fb28": { - "balance": "0x0", - "code": "0x6060604052361561008d5760e060020a600035046306fdde03811461008f578063095ea7b3146100a557806318160ddd1461012457806323b872dd1461012f578063313ce567146101dc578063475a9fa9146101f057806370a0823114610215578063721a37d21461024357806395d89b411461008f578063a9059cbb14610268578063dd62ed3e146102e7575b005b61031d6040805160208101909152600081525b90565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db63c6605267600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b6102316003546100a2565b61038b60043560243560443560008054604080517fa00bfa1100000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038781166024830152868116604483015260648201869052929092166084830152517319ee743d2e356d5f0e4d97cc09b96d06e933d0db9163a00bfa119160a482810192602092919082900301818660325a03f4156100025750506040515195945050505050565b604080516000815290519081900360200190f35b61038b6004356024356000805433600160a060020a0390811691161461039f57610002565b600160a060020a03600435166000908152600160205260409020545b60408051918252519081900360200190f35b61038b6004356024356000805433600160a060020a039081169116146103ce57610002565b61038b60043560243560007319ee743d2e356d5f0e4d97cc09b96d06e933d0db6388d5fecb600160005085856040518460e060020a0281526004018084815260200183600160a060020a0316815260200182815260200193505050506020604051808303818660325a03f4156100025750506040515191506103179050565b610231600435602435600160a060020a038281166000908152600260209081526040808320938516835292905220545b92915050565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561037d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b604080519115158252519081900360200190f35b50600160a060020a03821660009081526001602081905260409091208054830190556003805483019055610317565b600160a060020a038316600090815260016020526040902054821161040a57506040600020805482900390556003805482900390556001610317565b50600061031756", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000012098a4651fb262f7", - "0xfae22198212900725daa5db635d1fda7b0fa195adaabdc806a7267959c3d8ae4": "0x000000000000000000000000000000000000000000000000731fb89f735062f7", - "0xfd73dc2251dc113619c6fcc1c142e797f06e77a178cc37fe300a56823b741ef7": "0x0000000000000000000000000000000000000000000000008ac7230489e80000" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "2340153", - "difficulty": "80383973372327", - "timestamp": "1475034716", - "gasLimit": "1500062", - "miner": "0x61c808d82a3ac53231750dadc13c777b59310bd9" - }, - "input": "0xf8ea508504a817c80083084398946ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba580b884bbd4f854e9efd3ab89acad6a3edf9828c3b00ed1c4a74e974d05d32d3b2fb15aa16fc3770000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000080d29fa5cccfadac1ba0690ce7a4cf8590c636a1799ebf2cc52229714c47da72ee406fb9bd7d29e52440a017b6ce39e8876965afa2a1c579a592eb1af146506ccdbfc2c9ea422b13dca438", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0x3de712784baf97260455ae25fb74f574ec9c1add", - "gas": "0x84398", - "gasUsed": "0x27ec3", - "to": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "input": "0xbbd4f854e9efd3ab89acad6a3edf9828c3b00ed1c4a74e974d05d32d3b2fb15aa16fc3770000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000080d29fa5cccfadac", - "output": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "calls": [ - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x77e82", - "gasUsed": "0x54c", - "to": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "input": "0x8c172fa2d9a4ffe21d19763887176173d08241e8393c1dfd208f29193dfecdf854b664ac", - "output": "0x446374989d279847d0dbc6708a9c76a419fe9831d42c78bc89473f559a00d91500000000000000000000000061d76c05cd2aa9ed5135e21e52fff188b02089d4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000092f1dbea03ce08225e31e95cc926ddbe0198e6f2000000000000000000000000529c4cb814029b8bb32acb516ea3a4b07fdae350846fd373887ade3ab7703750294876afa61cf56303f5f014a4d80d04f508a1f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x7737b", - "gasUsed": "0x3fe1", - "to": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "input": "0x0439978de9efd3ab89acad6a3edf9828c3b00ed1c4a74e974d05d32d3b2fb15aa16fc3770000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000026566ea1ec2f6a9b00000000000000000000000000000000000000000000000072aa5b7e04d56a9b", - "output": "0x0000000000000000000000000000000000000000000000008060b57e2e0c99aa", - "calls": [ - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x770ef", - "gasUsed": "0xc24", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x24d4e90a0000000000000000000000000000000000000000000000020000000000000000", - "output": "0x000000000000000000000000000000000000000000000000b17217f7d1cf79ab", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x75eb2", - "gasUsed": "0x265", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x872fb2b5000000000000000000000000000000000000000000000000c330b3f7006420b8", - "output": "0x00000000000000000000000000000000000000000000000224bf7df2c80f0878", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x75aad", - "gasUsed": "0x25b", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x872fb2b50000000000000000000000000000000000000000000000000000000000000000", - "output": "0x00000000000000000000000000000000000000000000000100000016aee6e8ef", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x75737", - "gasUsed": "0xc24", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x24d4e90a00000000000000000000000000000000000000000000000324bf7e0976f5f167", - "output": "0x0000000000000000000000000000000000000000000000012535c5e5f87ee0d2", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x748c7", - "gasUsed": "0x265", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x872fb2b5000000000000000000000000000000000000000000000000c330b3f7006420b8", - "output": "0x00000000000000000000000000000000000000000000000224bf7df2c80f0878", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x744c2", - "gasUsed": "0x265", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x872fb2b500000000000000000000000000000000000000000000000237d37fe5d297a500", - "output": "0x0000000000000000000000000000000000000000000000093088c407fcbbce38", - "type": "DELEGATECALL", - "value": "0x0" - }, - { - "from": "0x8695e5e79dab06fbbb05f445316fa4edb0da30f0", - "gas": "0x74142", - "gasUsed": "0xc99", - "to": "0xef3487d24a0702703e04a26cef479e313c8fc7ae", - "input": "0x24d4e90a00000000000000000000000000000000000000000000000b554841fac4cad6b0", - "output": "0x0000000000000000000000000000000000000000000000026d7fc130d6a74cbe", - "type": "DELEGATECALL", - "value": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x731be", - "gasUsed": "0x241", - "to": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "input": "0xc51cf179000000000000000000000000000000000000000000000000de0b6b3a76400000", - "output": "0x0000000000000000000000000000000000000000000000000071ea279ec31402", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x72df4", - "gasUsed": "0x468b", - "to": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "input": "0x23b872dd0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba500000000000000000000000000000000000000000000000080d29fa5cccfadac", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add", - "0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5" - ], - "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x6e627", - "gasUsed": "0x56d6", - "to": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "input": "0x095ea7b30000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "topics": [ - "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", - "0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd" - ], - "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x68dae", - "gasUsed": "0xd6f0", - "to": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "input": "0x07d5b826d9a4ffe21d19763887176173d08241e8393c1dfd208f29193dfecdf854b664ac00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "gas": "0x629ff", - "gasUsed": "0x468b", - "to": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "input": "0x23b872dd0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba50000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd" - ], - "data": "0x00000000000000000000000000000000000000000000000080d29fa5cccfadac", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "gas": "0x5e0df", - "gasUsed": "0x31af", - "to": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "input": "0xa9059cbb000000000000000000000000950ca4a06c78934a148b7a3ff3ea8fc366f77a060000000000000000000000000000000000000000000000000041f50e27d56848", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x92f1dbea03ce08225e31e95cc926ddbe0198e6f2", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000005aae5c59d642e5fd45b427df6ed478b49d55fefd", - "0x000000000000000000000000950ca4a06c78934a148b7a3ff3ea8fc366f77a06" - ], - "data": "0x0000000000000000000000000000000000000000000000000041f50e27d56848", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "gas": "0x5ac6b", - "gasUsed": "0x29ae", - "to": "0x01e60b511fced1eb2b5b40991eb1dfd171a6df42", - "input": "0x475a9fa90000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba50000000000000000000000000000000000000000000000008090aa97a4fa4564", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "gas": "0x57fed", - "gasUsed": "0x29ae", - "to": "0xf4cbd7e037b80c2e67b80512d482685f15b1fb28", - "input": "0x475a9fa90000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba50000000000000000000000000000000000000000000000008090aa97a4fa4564", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x56030", - "gasUsed": "0x265", - "to": "0x5aae5c59d642e5fd45b427df6ed478b49d55fefd", - "input": "0x1f0c1e0cd9a4ffe21d19763887176173d08241e8393c1dfd208f29193dfecdf854b664ac0000000000000000000000000000000000000000000000000000000000000001", - "output": "0x000000000000000000000000f4cbd7e037b80c2e67b80512d482685f15b1fb28", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "gas": "0x55cc3", - "gasUsed": "0x339f", - "to": "0xf4cbd7e037b80c2e67b80512d482685f15b1fb28", - "input": "0xa9059cbb0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add000000000000000000000000000000000000000000000000de0b6b3a76400000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0xf4cbd7e037b80c2e67b80512d482685f15b1fb28", - "gas": "0x55a8a", - "gasUsed": "0x30f7", - "to": "0x19ee743d2e356d5f0e4d97cc09b96d06e933d0db", - "input": "0x88d5fecb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add000000000000000000000000000000000000000000000000de0b6b3a76400000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0xf4cbd7e037b80c2e67b80512d482685f15b1fb28", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006ca7f214ab2ddbb9a8e1a1e2c8550e3164e9dba5", - "0x0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add" - ], - "data": "0x000000000000000000000000000000000000000000000000de0b6b3a76400000", - "position": "0x0" - } - ], - "type": "DELEGATECALL", - "value": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json deleted file mode 100644 index 263e88d6e..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json +++ /dev/null @@ -1,2327 +0,0 @@ -{ - "genesis": { - "difficulty": "59917798787272", - "extraData": "0xe4b883e5bda9e7a59ee4bb99e9b1bc", - "gasLimit": "4712380", - "hash": "0xae82afe3630b001a34ad4c51695dacb17872ebee4dadd2de88b1a16671871da4", - "miner": "0x61c808d82a3ac53231750dadc13c777b59310bd9", - "mixHash": "0x23c2289cdee8a397cf36db9ffa3419503bed54eb09e988b3c7a3587a090e6fc1", - "nonce": "0x94dc83e0044f49c8", - "number": "1881283", - "stateRoot": "0x6e3832bc2e4e66170a1e716449083e08fbb70e7b2a9f1f34e0c57e66ce40c50f", - "timestamp": "1468467284", - "totalDifficulty": "37186898441932102239", - "alloc": { - "0x0000000000000000000000000000000000000004": { - "balance": "0x0" - }, - "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e": { - "balance": "0x0", - "code": "0x606060405236156100f05760e060020a600035046303afc23581146100f257806313af4035146101145780631838e26614610136578063186ef9621461014d57806327df8c501461016f578063295d5866146101915780634162169f146101b35780634dfc3db6146101c55780636637b882146101e8578063839d3f7f1461020a57806386c9b5361461021d5780638da5cb5b1461022f5780639093a5e714610241578063b199efb514610263578063b262b9ae14610275578063b9f34aa114610297578063be9a6555146102a9578063d1c3c84a146102c7578063e26fc92b146102d9578063e8d9f074146102eb575b005b6100f0600435600054600160a060020a03908116339091161461034057610002565b6100f0600435600054600160a060020a03908116339091161461035557610002565b6102fd60006000600060006000600061036a6101c9565b6100f0600435600054600160a060020a0390811633909116146108a157610002565b6100f0600435600054600160a060020a0390811633909116146108b657610002565b6100f0600435600054600160a060020a0390811633909116146108cb57610002565b61030f600154600160a060020a031681565b6102fd5b60008054600160a060020a0390811633909116146108e0575060015b90565b6100f0600435600054600160a060020a03908116339091161461098857610002565b61032c60075460a060020a900460ff1681565b61030f600454600160a060020a031681565b61030f600054600160a060020a031681565b6100f0600435600054600160a060020a03908116339091161461099d57610002565b61030f600254600160a060020a031681565b6100f0600435600054600160a060020a0390811633909116146109b257610002565b61030f600754600160a060020a031681565b6100f060005433600160a060020a03908116911614610a1a57610002565b61030f600354600160a060020a031681565b61030f600554600160a060020a031681565b61030f600654600160a060020a031681565b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b60048054600160a060020a0319168217905550565b60008054600160a060020a0319168217905550565b945060008514610380578495505b505050505090565b6002546040805160015460e060020a634162169f0282529151600160a060020a039283169390921691634162169f9160048181019260209290919082900301816000876161da5a03f11561000257505060405151600160a060020a031690911490506103ef5760649550610378565b600260009054906101000a9004600160a060020a0316600160a060020a0316634dfc3db66040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519450506000841461045857836064019550610378565b6040805160015460035460e060020a634162169f0283529251600160a060020a039182169390911691634162169f91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a031690911490506104c65760c89550610378565b600360009054906101000a9004600160a060020a0316600160a060020a0316634dfc3db66040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519350506000831461052f578260c8019550610378565b604080516001546004805460e060020a634162169f0284529351600160a060020a039283169490921692634162169f928183019260209282900301816000876161da5a03f11561000257505060405151600160a060020a0316909114905061059b5761012c9550610378565b60408051600480547f4dfc3db60000000000000000000000000000000000000000000000000000000083529251600160a060020a039390931692634dfc3db692808301926020929182900301816000876161da5a03f1156100025750506040515192505060008214610613578161012c019550610378565b6040805160015460055460e060020a634162169f0283529251600160a060020a039182169390911691634162169f91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a03169091149050610682576101909550610378565b600560009054906101000a9004600160a060020a0316600160a060020a0316634dfc3db66040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151915050600081146106ec5780610190019550610378565b6040805160015460065460e060020a634162169f0283529251600160a060020a039182169390911691634162169f91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a0316909114905061075b576101f49550610378565b6040805160065460e060020a638da5cb5b028252915130600160a060020a03908116931691638da5cb5b91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a031690911490506107c6576101f59550610378565b6040805160075460015460e060020a634162169f0283529251600160a060020a03938416939190911691634162169f91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a03169091149050610836576102589550610378565b6040805160075460e060020a638da5cb5b028252915130600160a060020a03908116931691638da5cb5b91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a03169091149050610378576102599550610378565b60038054600160a060020a0319168217905550565b60058054600160a060020a0319168217905550565b60068054600160a060020a0319168217905550565b600154600160a060020a0316600014156108fc575060026101e5565b600654600160a060020a031660001415610918575060036101e5565b600754600160a060020a031660001415610934575060046101e5565b600254600160a060020a031660001415610950575060056101e5565b600354600160a060020a03166000141561096c575060066101e5565b600454600160a060020a0316600014156101e5575060076101e5565b60018054600160a060020a0319168217905550565b60078054600160a060020a0319168217905550565b60028054600160a060020a0319168217905550565b600260009054906101000a9004600160a060020a0316600160a060020a031663975057e76040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050505b565b610a8a600154604080517f4b6753bc0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a031691634b6753bc916004828101926020929190829003018187876161da5a03f11561000257505060405151421191506101e59050565b1515610a9557610a18565b60075460a060020a900460ff1615610e93576111556040805160015460065460e060020a6370a08231028352600160a060020a039081166004840152925160009384939216916370a08231916024808301926020929190829003018187876161da5a03f1156100025750506040515191909111159050610c61576040805160065460025460015460e060020a6370a08231028452600160a060020a0392831660048501819052945163a9059cbb949284169391909116916370a0823191602482810192602092919082900301818a876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600482019490945260248101939093525160448084019360209350829003018187876161da5a03f1156100025750506040805160025460e060020a63a8618f71028252600160a060020a031660048201819052915191925063a8618f71916024828101926020929190829003018187876161da5a03f11561000257505060405151159050610c6157600260009054906101000a9004600160a060020a0316600160a060020a031663975057e76040518160e060020a0281526004018090506000604051808303816000876161da5a03f11561000257506001925050505b6001546007546040805160e060020a6370a08231028152600160a060020a0392831660048201529051600093909216916370a0823191602481810192602092909190829003018187876161da5a03f1156100025750506040515191909111159050610e1b576040805160075460025460015460e060020a6370a08231028452600160a060020a0392831660048501819052945163a9059cbb949284169391909116916370a0823191602482810192602092919082900301816000876161da5a03f11561000257505060408051805160e060020a63a9059cbb02825260048201949094526024810193909352516044838101936020935082900301816000876161da5a03f1156100025750506040805160025460e060020a63a8618f71028252600160a060020a031660048201819052915191925063a8618f7191602482810192602092919082900301816000876161da5a03f11561000257505060405151159050610e1b57600260009054906101000a9004600160a060020a0316600160a060020a031663975057e76040518160e060020a0281526004018090506000604051808303816000876161da5a03f11561000257506001925050505b8015610e7257600260009054906101000a9004600160a060020a0316600160a060020a0316632e64cec16040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050505b6007805474ff00000000000000000000000000000000000000001916905550565b600260009054906101000a9004600160a060020a0316600160a060020a0316632e64cec16040518160e060020a0281526004018090506000604051808303816000876161da5a03f115610002575050505b60048054604080517ffc3407160000000000000000000000000000000000000000000000000000000081529051600160a060020a03929092169263fc340716928282019260009290829003018183876161da5a03f115610002575050600354604080517fd95f98ce0000000000000000000000000000000000000000000000000000000081529051600160a060020a0392909216925063d95f98ce916004828101926000929190829003018183876161da5a03f11561000257505050620f42405a11156109c7576109c76001546005546040805160e060020a6370a08231028152600160a060020a039283166004820152905192909116916370a082319160248181019260209290919082900301816000876161da5a03f1156100025750506040515160001415905061108357604080516002546005547fd0679d34000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015260016024840152925192169163d0679d349160448181019260209290919082900301816000876161da5a03f115610002575050505b5b600554604080517f400e39490000000000000000000000000000000000000000000000000000000081529051600a92600160a060020a03169163400e394991600482810192602092919082900301816000876161da5a03f1156100025750506040515191909110905080156110fb5750620aae605a115b15610a1857600560009054906101000a9004600160a060020a0316600160a060020a031663ff2f4bd26040518160e060020a0281526004018090506000604051808303816000876161da5a03f11561000257505050611084565b610ee456", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000001f835a0247b0063c04ef22006ebe57c5f11977cc4" - } - }, - "0x304a554a310c7e546dfe434669c62820b7d83490": { - "balance": "0x3034f5ca7d45e17df1d83", - "nonce": "3", - "code": "0x6060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638b15a605146106c95780638d7af473146106d257806396d7f3f5146106e1578063a1da2fb9146106ea578063a3912ec814610704578063a9059cbb1461070f578063b7bc2c841461073f578063baac53001461074b578063be7c29c1146107b1578063c9d27afe14610817578063cc9ae3f61461082d578063cdef91d014610841578063dbde198814610859578063dd62ed3e1461087e578063e33734fd146108b2578063e5962195146108c6578063e66f53b7146108de578063eceb2945146108f0578063f8c80d261461094f575b610966600f546000906234bc000142108015610239575060125433600160a060020a03908116911614155b156109785761098033610752565b6109866004356000805482908110156100025750808052600e8202600080516020612a3683398151915201905060038101546004820154600683015460018401548454600786015460058701546009880154600a890154600d8a0154600160a060020a039586169b509599600201989760ff81811698610100909204811697949691951693168c565b61096660043560243533600160a060020a03908116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b61096660105481565b610a7d600754600160a060020a031681565b610a7d600e54600160a060020a031681565b61096660165481565b6109665b60004262127500600f60005054031115610de557506014610983565b610a7d601254600160a060020a031681565b60408051602060248035600481810135601f810185900485028601850190965285855261096695813595919460449492939092019181908401838280828437509496505050505050506000600060006000600060003411156116a857610002565b6109666004356024356044355b60115460009060ff1680156104315750600f5442115b80156124e957506124e78461044b565b6109666000610980335b600160a060020a0381166000908152600b602052604081205481908114156129cb57610b99565b61096660065481565b6109665b600d5430600160a060020a03163103610983565b610966600f5481565b61096660043560046020526000908152604090205460ff1681565b61096660043560243560006124cb610831565b610a9a6000341115610ba457610002565b604080516020604435600481810135601f8101849004840285018401909552848452610966948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a435915050600060006110c1336105ec565b61096660043560096020526000908152604090205481565b61096660015481565b610a9a60043530600160a060020a031633600160a060020a03161415806105db5750600160a060020a03811660009081526004602052604090205460ff16155b156121cb576121c8565b6109666004355b600160a060020a0381166000908152601460205260409020545b919050565b6109666004356024356000600034111561259957610002565b610966600062e6b680420360026000505410806106505750600354600160a060020a0390811633909116145b80156106645750600254621274ff19420190105b156126145750426002908155600180549091028155610983565b610966600435600a6020526000908152604090205481565b610966600435602435600060006000600060006000341115611ba157610002565b610a7d600854600160a060020a031681565b610966600c5481565b61096660005460001901610983565b61096660025481565b61096660043560006000600060003411156121fc57610002565b6109665b6001610983565b6109666004356024355b60115460009060ff16801561072f5750600f5442115b801561248757506124853361044b565b61096660115460ff1681565b6109666004355b60006000600f600050544210801561076a5750600034115b80156107a457506011546101009004600160a060020a0316600014806107a457506011546101009004600160a060020a0390811633909116145b15610b9f57610a9c61037f565b610a7d600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610606565b61096660043560243560006000610e1b336105ec565b6109665b6000600034111561247c57610002565b61096660043560056020526000908152604090205481565b610966600435602435604435600061252f845b6000600060003411156127ac57610002565b610966600435602435600160a060020a0382811660009081526015602090815260408083209385168352929052205461033f565b610a9a600435600034111561254557610002565b610966600435600b6020526000908152604090205481565b610a7d600354600160a060020a031681565b604080516020606435600481810135601f81018490048402850184019095528484526109669481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561103257610002565b610a7d6011546101009004600160a060020a031681565b60408051918252519081900360200190f35b610980610708565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590610b4c575060115460ff16155b15610b94576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a15b600191505b50919050565b610002565b600f5442118015610bb8575060115460ff16155b15610de357601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040516012549051600160a060020a039190911631109050610cc9576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b33600160a060020a0316600081815260136020526040808220549051909181818185876185025a03f19250505015610de35733600160a060020a03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d6013600050600033600160a060020a03168152602001908152602001600020600050546040518082815260200191505060405180910390a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f60005054031115610e13576201518062127500600f60005054034203046014019050610983565b50601e610983565b60001415610e2857610002565b6000341115610e3657610002565b6000805485908110156100025750600160a060020a03331681527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e600e8602908101602052604090912054600080516020612a3683398151915291909101915060ff1680610eb05750600c810160205260406000205460ff165b80610ebf575060038101544210155b15610ec957610002565b8215610f0f5733600160a060020a03166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff19166001179055610f4b565b33600160a060020a0316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b33600160a060020a03166000908152600b60205260408120541415610f77576040600020849055610feb565b33600160a060020a03166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e909102015460038201541115610feb5733600160a060020a03166000908152600b602052604090208490555b60408051848152905133600160a060020a03169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6000805487908110156100025750808052600e8702600080516020612a3683398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156110ce57610002565b82801561111857508660001415806110e857508451600014155b806111005750600354600160a060020a038981169116145b8061110b5750600034115b80611118575062093a8084105b1561112257610002565b8215801561114257506111348861115c565b158061114257506212750084105b156111fe57610002565b83546118e590600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff16806111f15750601254600160a060020a039081169083161480156111f15750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156129a157506001610606565b6249d40084111561120e57610002565b60115460ff1615806112215750600f5442105b806112365750600c5434108015611236575082155b1561124057610002565b42844201101561124f57610002565b30600160a060020a031633600160a060020a0316141561126e57610002565b60008054600181018083559091908280158290116112a557600e0281600e0283600052602060002091820191016112a5919061136a565b505060008054929450918491508110156100025750808052600e8302600080516020612a368339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b019083901061146257805160ff19168380011785555b5061149292915061144a565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561145e578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f81901061143057505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220611344929091028101905b8082111561145e57600080825560018201818155600283019190915560039091018054600160a060020a03191690556113fc565b601f0160209004906000526020600020908101906113ae91905b8082111561145e576000815560010161144a565b5090565b82800160010185558215611338579182015b82811115611338578251826000505591602001919060010190611474565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561157857600881018054600181018083559091908280158290116115735760040281600402836000526020600020918201910161157391906113fc565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156116485780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a36833981519152019050600781015490945060ff166116e757620d2f006116ec565b622398805b600485015490935060ff16801561170857506003840154830142115b15611716576117b887611890565b600384015442108061172d5750600484015460ff16155b806117ae57508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b1561114c57610002565b61169e565b60048401805461ff001916610100179055835460019550600160a060020a03908116309091161480159061180157508354600754600160a060020a03908116911614155b801561181d57506008548454600160a060020a03908116911614155b801561183957508354601254600160a060020a03908116911614155b801561185557506003548454600160a060020a03908116911614155b1561188b5760018401805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190555b611663875b6000600060005082815481101561000257908052600e02600080516020612a36833981519152018150600481015490915060ff16156118d757600d80546006830154900390555b600401805460ff1916905550565b15156118f45761190087611890565b6001915061193161047f565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050505061169e565b6001850154111561194157600091505b50600a8301546009840154865191019060049010801590611986575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b80156119b6575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b80156119e6575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b8015611a16575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b8015611a45575030600160a060020a0316600090815260056020526040902054611a4290611a5d61047f565b81105b15611a4f57600091505b6001840154611a8090611a5f565b015b30600160a060020a03166000908152600560205260408120546129a961047f565b8110611ad457604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050501515611abc57610002565b4260025560165460059004811115611ad45760056001555b6001840154611ae290611a5f565b8110158015611af85750600a8401546009850154115b8015611b015750815b1561188b578360000160009054906101000a9004600160a060020a0316600160a060020a0316846001016000505487604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611b7d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f19250505015156117bd57610002565b611baa336105ec565b60001415611bb757610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a36833981519152919091019450421080611c1957506003840154622398800142115b80611c3257508354600160a060020a0390811690871614155b80611c425750600784015460ff16155b80611c68575033600160a060020a03166000908152600b8501602052604090205460ff16155b80611c9c575033600160a060020a03166000908152600b60205260409020548714801590611c9c5750604060009081205414155b15611ca657610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611e1257611efc86604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506106069050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090505433600160a060020a031660009081526014602052604081205460088801805493909102939093049550908110156100025790815260208120905060030154604080517fbaac530000000000000000000000000000000000000000000000000000000000815233600160a060020a0390811660048301529151929091169163baac53009186916024808301926020929190829003018185886185025a03f11561000257505060405151600014159150611f78905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611f5757610002565b600d5430600160a060020a0316311015611f7057610002565b611d9561047f565b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090506002015433600160a060020a0390811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a0390811682526020828101939093526040918201600090812080549095019094553016835260059091529020548290101561205357610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a039081168352929052604080822080549094019093553090911681522054819010156120c657610002565b30600160a060020a0390811660009081526009602090815260408083208054869003905533909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a36121383361086c565b5033600160a060020a03166000908152601460209081526040808320805460168054919091039055839055600a9091528120556001945061169e565b30600160a060020a0390811660008181526005602090815260408083208054958716808552828520805490970190965584845283905560099091528082208054948352908220805490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f192505050151561217457610002565b33600160a060020a03818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935197995091969195929092169363d2cc718f936004848101949193929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204101561229d57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a0316815260200190815260200160002060005054020403905083156123ec57600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061245457610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061245457610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b6109803361086c565b155b80156124a257506124a23384845b6000600061293a856105ec565b80156124be57506124be83836000600034111561261c57610002565b15610b9f5750600161033f565b15156124d657610002565b6124e08383610719565b905061033f565b155b80156124fb57506124fb848484612495565b80156125185750612518848484600060003411156126c157610002565b15610b9f57506001612528565b90505b9392505050565b151561253a57610002565b61252584848461041b565b30600160a060020a031633600160a060020a031614158061258a575030600160a060020a031660009081526005602052604090205460649061258561047f565b010481115b1561259457610002565b600c55565b600354600160a060020a0390811633909116146125b557610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a250600161033f565b506000610983565b33600160a060020a03166000908152601460205260409020548290108015906126455750600082115b156126b957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161033f565b50600061033f565b600160a060020a03841660009081526014602052604090205482901080159061270a5750601560209081526040600081812033600160a060020a03168252909252902054829010155b80156127165750600082115b156127a457600160a060020a03838116600081815260146020908152604080832080548801905588851680845281842080548990039055601583528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001612528565b506000612528565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061281a866105ec565b0204101561282757610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f115610002575050604051519050612895866105ec565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061291357610002565b600160a060020a0383166000908152600a6020526040902080548201905560019150610b99565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561296857610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610606565b0160030260166000505483020460016000505460166000505404019050610606565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a368339815191520190506003810154909150421115610b9457600160a060020a0383166000908152600b602052604081208190559150610b9956290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000057870858", - "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c18941301", - "0x0000000000000000000000000000000000000000000000000000000000000016": "0x00000000000000000000000000000000000000000003034f5ca7d45e17df199b", - "0x0421a2c4dbea98e8df669bb77238b62677daa210c5fbc46600627f90c03d0f08": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e572": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e573": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e574": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e575": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e577": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e578": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e579": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e581": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e582": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e583": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e584": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e586": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e587": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e590": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e591": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e592": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e593": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e595": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5aa": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ab": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ac": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ad": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ae": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5af": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ba": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5be": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bf": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ca": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5da": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5db": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5e9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ee": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ef": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5f7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5fc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x330b9432081afd3b64172d5df1f72ca72fc17e7e729ceb8b7529f91eee8b3f23": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x33f9bdb745e7edb1789dd1d68f40f693940aa8313b4f6bdc543be443dbc85e63": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4830270ad35536baba417a92ea24656430586a37c90999b53c4d72ef1090cc9d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4b16ba88f291613070529c10c8bdc41e973e2e2aa412ed92254cdca71ccfbc89": "0x00000000000000000000000000000000000000000001819451f999d617dafa76", - "0x6546a4760869a51d07a75a31f00531836c32152c06dc88ac342da52fac5d939e": "0x000000000000000000000000000000000000000000000026b8b4a0b1e8292492", - "0x6796d25b854f17a11b940a9ff2822335f7d9bd1b85fbcd9d1f5cf742099d477a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x711886c99bc7a6e316551823dca012bd5b4381b57cec388f72c4b8105c1ed4ad": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x74024021ec74dc59b0fa1b66e9f430163a5e1128785ec9495f9686628ca7cc2b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x79a0e9ff42282e7cbcb539e164f024ab90021633de05f600fff6d16305888d26": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x81ffe0a69ee20c37e3f3ba834da8b20475846fcde1f4a39fdfc628a2560076aa": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8f85b96a91f601f62149f5dd6a35d6168f6de5bc047a18e3cf7b97a3843c6ffd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x946f68a04a200ebe87f2f896f7f6c08f4e22813db910c8a6d6abf17611ce3ffb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x9c1ad2f16775f94ffd360e8bc716f86016a3fcf90992b5b4f3312353efd1bd61": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa66ae63934365a757bf33d70ca0a28352da4c2fe6cb147bf29d69fbea3a706e0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa7653edcf1403f7ce2f75784d5f34ca5f57ff110bd0c3abbdcc5a84f101dc83a": "0x00000000000000000000000000000000000000000001819451f999d617dafa93", - "0xa87317e3ffd5ed16f357bd31427bd97cbb35fc51ad1e00feec89bdfe82c5dba4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xaa535eb427f7963e49601f9032ee6b62a9f72b6b3c610a5f11faf8dc68a97e2a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xaade287f2b81ac58dcc6ee0c381cde85b6aa7a9a769be73605f1af9453a340a0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xb56a086d82c3921c13c13d1d53f18bbbe36d9d1c4862be8339a5171feb94c164": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xb6ab9f1541f42dc4feba15ccd18bc3af7c8f99cafb184ab65539883a68c7a1a9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xbad9e5f7dc3001078ea6433993a2f145c2ef9af1c5137a35e9c173c208990249": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xc319152db8781ef1f12090aad94325d650e39c8a20285c7e02959817118f3f28": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xde65b6d76ea4a5547af9707e6e099bba6f16dbc7b5cf97fb8fedc82583b38de0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xdf71c8506c3cf85e2e677b60ec28fe60eb820775001bdce289e3253f304f22e8": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x4fd27b205895e698fa350f7ea57cec8a21927fcd": { - "balance": "0x0", - "nonce": "11", - "code": "0x606060405236156100f05760e060020a600035046303afc23581146100f257806313af403514610114578063186ef962146101365780632e64cec11461015857806331962cdc146101d2578063365a86fc146101f45780634162169f146102065780634dfc3db61461021857806365f13792146102585780636637b88214610441578063715d832f146104625780637452c2e61461048457806386c9b536146105005780638da5cb5b14610512578063975057e714610524578063a8618f711461059f578063d0679d341461061b578063d1c3c84a14610698578063d9d35966146106aa578063f3273907146106c9575b005b6100f0600435600054600160a060020a03908116339091161461072e57610002565b6100f0600435600054600160a060020a03908116339091161461074457610002565b6100f0600435600054600160a060020a03908116339091161461075957610002565b6100f06000805481908190600160a060020a0390811633909116148015906101905750600154600160a060020a039081163390911614155b80156101ac5750600254600160a060020a039081163390911614155b80156101c85750600354600160a060020a039081163390911614155b1561076e57610002565b6100f0600435600054600160a060020a039081163390911614610a5d57610002565b6106eb600154600160a060020a031681565b6106eb600454600160a060020a031681565b61070860008054600160a060020a03908116339091161480159061024c5750600154600160a060020a039081163390911614155b15610a72575060015b90565b6107086004355b600060006000600060006000600460009054906101000a9004600160a060020a0316600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150945084600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604080518051600480547f81f03fcb000000000000000000000000000000000000000000000000000000008452600160a060020a038d81169285019290925293519198509290921692506381f03fcb916024828101926020929190829003018187876161da5a03f115610002575050604080518051600480547f18160ddd0000000000000000000000000000000000000000000000000000000084529351919750600160a060020a039390931693506318160ddd92828101926020929190829003018187876161da5a03f1156100025750506040805180516004805460e060020a6370a08231028452600160a060020a038d81169285019290925293519196509290921692506370a08231916024828101926020929190829003018187876161da5a03f11561000257505060405151909402919091049695505050505050565b6100f060043560005433600160a060020a03908116911614610ad957610002565b6100f06004356000805433600160a060020a03908116911614610aff57610002565b61071a600435600080548190819033600160a060020a039081169116148015906104be5750600154600160a060020a039081163390911614155b80156104da5750600254600160a060020a039081163390911614155b80156104f65750600354600160a060020a039081163390911614155b15610be657610002565b6106eb600354600160a060020a031681565b6106eb600054600160a060020a031681565b6100f06000805481908190819033600160a060020a0390811691161480159061055d5750600154600160a060020a039081163390911614155b80156105795750600254600160a060020a039081163390911614155b80156105955750600354600160a060020a039081163390911614155b15610c4457610002565b61071a6004355b60006000600460009054906101000a9004600160a060020a0316600160a060020a03166381f03fcb846040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519150610da490508361025f565b61071a60043560243560008054819033600160a060020a039081169116148015906106565750600154600160a060020a039081163390911614155b80156106725750600254600160a060020a039081163390911614155b801561068e5750600354600160a060020a039081163390911614155b15610dac57610002565b6106eb600254600160a060020a031681565b6100f06000805433600160a060020a03908116911614610ec457610002565b6106eb6004356000805433600160a060020a03908116911614610fd357610002565b60408051600160a060020a03929092168252519081900360200190f35b60408051918252519081900360200190f35b604080519115158252519081900360200190f35b60038054600160a060020a031916821790555b50565b60008054600160a060020a0319168217905550565b60028054600160a060020a0319168217905550565b30925061077a836105a6565b1561082557600480546006546040805160e060020a6370a08231028152600160a060020a038881169582019590955290519284169363a9059cbb9392169184916370a0823191602482810192602092919082900301816000876161da5a03f11561000257505060408051805160e060020a63a9059cbb02825260048201949094526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b600091505b6005548210156108f45760058054600454600160a060020a0316916370a0823191859081101561000257600091825260408051600080516020611089833981519152929092015460e060020a6370a08231028352600160a060020a0316600483015251602482810193602093839003909101908290876161da5a03f115610002575050604051519150506000811115610a51576108f96005600050838154811015610002576000919091526000805160206110898339815191520154600160a060020a03166105a6565b505050565b15156109c25760058054600454600160a060020a0316916323b872dd918590811015610002575060009081526040805160008051602061108983398151915287015460e060020a6323b872dd028252600160a060020a03908116600483015230166024820152604481018690529051606482810193602093839003909101908290876161da5a03f1156100025750506040805183815290517f92da44f6982cd1ca7a9c851f8c39b26c80c235d7bb9fd59bce334fa634a1728b92509081900360200190a1610a51565b60058054600454600160a060020a0316916323b872dd918590811015610002575060009081526006546040805160008051602061108983398151915288015460e060020a6323b872dd028252600160a060020a0390811660048301529290921660248301526044820186905251606482810193602093839003909101908290876161da5a03f115610002575050505b6001919091019061082a565b60018054600160a060020a0319168217905550565b600454600160a060020a031660001415610a8e57506002610255565b600354600160a060020a031660001415610aaa57506003610255565b600254600160a060020a031660001415610ac657506004610255565b6005546000141561025557506005610255565b6005546000901115610aea57610002565b60048054600160a060020a0319168217905550565b5060005b81811015610b5a57600580546001818101808455930192909190828015829011610b5e576000839052610b5e906000805160206110898339815191529081019083015b80821115610bd65760008155600101610b46565b5050565b5050604051600454600160a060020a0316925090506082806110078339018082600160a060020a03168152602001915050604051809103906000f06005805460001981019081101561000257600091909152600080516020611089833981519152018054600160a060020a0319169091179055610b03565b5090565b600092505b5050919050565b600091505b600554821015610bda57600580548390811015610002576000919091526000805160206110898339815191520154600160a060020a0390811691508416811415610c385760019250610bdf565b60019190910190610beb565b600460009054906101000a9004600160a060020a0316600160a060020a03166370a08231306040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519450506000841415610cbb575b50505050565b600554600093506004900460010191505b81831015610cb557506005805460045442850182900692600160a060020a03919091169163a9059cbb9190849081101561000257600091825260408051600080516020611089833981519152929092015460e060020a63a9059cbb028352600160a060020a03166004830152868904602483015251604482810193602093839003909101908290876161da5a03f11561000257505060408051848704815290517fc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b92509081900360200190a160019290920191610ccc565b901192915050565b600460009054906101000a9004600160a060020a0316600160a060020a03166370a08231306040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f1156100025750506040515191505082811015610e5f57604080516020810185905281517f703690365b2d63b5b9ec4471a919cdd5924f745170399a5d24927fd07d81a04d929181900390910190a1600091505b5092915050565b604080516004805460e060020a63a9059cbb028352600160a060020a038881169284019290925260248301879052925192169163a9059cbb9160448082019260209290919082900301816000876161da5a03f115610002575060019350610e58915050565b600480546006546040805160e060020a6370a08231028152600160a060020a0392831694810194909452519116916370a0823191602482810192602092919082900301816000876161da5a03f11561000257505060405151915050600081111561074157604080516004805460065460e060020a6323b872dd028452600160a060020a039081169284019290925230821660248401526044830185905292519216916323b872dd9160648181019260209290919082900301816000876161da5a03f1156100025750505060405180519060200150507f32e95f921f72e9e736ccad1cc1c0ef6e3c3c08204eb74e9ee4ae8f98e195e3f0816040518082815260200191505060405180910390a150565b600580548390811015610002576000919091526000805160206110898339815191520154600160a060020a03169291505056006060604052604051602080608283396080604081905291517f095ea7b3000000000000000000000000000000000000000000000000000000008352600160a060020a0333811660845260001960a4819052919384939184169163095ea7b39160c491906044816000876161da5a03f115600257505033600160a060020a03169050ff036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000a", - "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db6": "0x0000000000000000000000007ccbc69292c7a6d7b538c91f3b283de97906cf30", - "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db7": "0x0000000000000000000000001b9ec8ba24630b75a7a958153ffff56dd6d4b6a2", - "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db8": "0x000000000000000000000000c3a2c744ad1f5253c736875b93bacce5b01b060b" - } - }, - "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f": { - "balance": "0x0", - "code": "0x606060405236156100da5760e060020a600035046303afc23581146100dc57806309f180f9146100fe5780630a39ce021461016c57806310aa1caa146101a057806313af40351461021e57806331962cdc14610240578063365a86fc146102625780634162169f146102745780634dfc3db6146102865780636637b882146102c65780636de45dee146102e85780638da5cb5b146103285780639137c1a71461033a578063b199efb51461035c578063b3a69f861461036e578063d5d7ff3c1461040b578063d95f98ce1461044b578063fe39084c146104b5575b005b6100da600435600054600160a060020a0390811633909116146104f657610002565b6104c76004355b6002546040805160e060020a6381f03fcb028152600160a060020a0384811660048301529151600093849384939116916381f03fcb91602481810192602092909190829003018187876161da5a03f1156100025750506040515192506105199050846101a7565b6104d960043560068054829081101561000257506000526000805160206110cf8339815191520154600160a060020a031681565b6104c76004355b604080516003547f65f13792000000000000000000000000000000000000000000000000000000008252600160a060020a038481166004840152925160009391909116916365f13792916024828101926020929190829003018187876161da5a03f115610002575050604051516001019392505050565b6100da600435600054600160a060020a03908116339091161461052c57610002565b6100da600435600054600160a060020a03908116339091161461054157610002565b6104d9600154600160a060020a031681565b6104d9600254600160a060020a031681565b6104c760008054600160a060020a0390811633909116148015906102ba5750600154600160a060020a039081163390911614155b15610556575060015b90565b6100da600435600054600160a060020a03908116339091161461063c57610002565b6100da600435600054600160a060020a03908116339091161480159061031e5750600154600160a060020a039081163390911614155b1561065157610002565b6104d9600054600160a060020a031681565b6100da600435600054600160a060020a03908116339091161461081b57610002565b6104d9600354600160a060020a031681565b6104c75b6000805b6006548110156108175760068054600254600160a060020a0316916370a08231918490811015610002576000918252604080516000805160206110cf833981519152929092015460e060020a6370a08231028352600160a060020a0316600483015251602482810193602093839003909101908290876161da5a03f11561000257505060405151929092019150600101610376565b6100da6004356000805433600160a060020a039081169116148015906104415750600154600160a060020a039081163390911614155b1561083057610002565b6100da60006000600060006000600060006000600060006000600060009054906101000a9004600160a060020a0316600160a060020a031633600160a060020a0316141580156104ab5750600154600160a060020a039081163390911614155b1561092d57610002565b6104d9600454600160a060020a031681565b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b60048054600160a060020a031916821790555b50565b81810392505b5050919050565b90508082111561050c5760009250610512565b60008054600160a060020a0319168217905550565b60018054600160a060020a0319168217905550565b600254600160a060020a031660001415610572575060026102c3565b600354600160a060020a03166000141561058e575060036102c3565b600354604080517fd1c3c84a000000000000000000000000000000000000000000000000000000008152905130600160a060020a0390811693169163d1c3c84a91600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a0316909114905061060d575060046102c3565b60065460001415610620575060056102c3565b600454600160a060020a0316600014156102c3575060066102c3565b60028054600160a060020a0319168217905550565b6106ab816000805b6006548110156110bc5782600160a060020a03166006600050828154811015610002576000919091526000805160206110cf8339815191520154600160a060020a031614156110c757600191506110c1565b156106b557610509565b600354604080517f7452c2e6000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291519290911691637452c2e69160248181019260209290919082900301816000876161da5a03f1156100025750506040515115905061072d57610509565b30600160a060020a031681600160a060020a0316148061075b5750600354600160a060020a03908116908216145b806107745750600154600160a060020a03908116908216145b1561077e57610509565b60068054600181018083559091908280158290116107bf578183600052602060002091820191016107bf91905b8082111561081757600081556001016107ab565b505060068054849350909150600019810190811015610002575080546000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3e018054600160a060020a031916909117905550565b5090565b60038054600160a060020a0319168217905550565b5060005b6006548110156109215781600160a060020a03166006600050828154811015610002576000919091526000805160206110cf8339815191520154600160a060020a0316141561092557600680546000198101908110156100025760009182526000805160206110cf83398151915201909054906101000a9004600160a060020a03166006600050828154811015610002576000805160206110cf833981519152018054600160a060020a0319169092179091558054600019810180835590919082801582901161091c5761091c906000805160206110cf8339815191529081019083016107ab565b505050505b5050565b600101610834565b6002546040805160e060020a6381f03fcb02815230600160a060020a0381811660048401529251909e5092909116916381f03fcb9160248181019260209290919082900301816000876161da5a03f115610002575050604051519a505060008a14156109c1576040517f044c61dab36644651a1f82d87d6494a3a6450a6edde20b9baf45e374fb2d0bb990600090a1610e04565b6109c9610372565b6040805160025460e060020a6370a08231028252600160a060020a038f811660048401529251939c50909116916370a082319160248181019260209290919082900301816000876161da5a03f115610002575050604051519850606497505086881015610ade57604080516003547fd0679d34000000000000000000000000000000000000000000000000000000008252600160a060020a038e811660048401528b8b036024840152925192169163d0679d349160448082019260209290919082900301816000876161da5a03f1156100025750506040515115159050610ad8576040517f044c61dab36644651a1f82d87d6494a3a6450a6edde20b9baf45e374fb2d0bb990600090a1610e04565b86975087505b600095505b600654861015610b2457610d8e6006600050878154811015610002576000919091526000805160206110cf8339815191520154600160a060020a0316610105565b6040805160025460e060020a6381f03fcb028252600160a060020a038e8116600484015292519216916381f03fcb9160248181019260209290919082900301816000876161da5a03f11561000257505050604051805190602001509250600260009054906101000a9004600160a060020a0316600160a060020a03166370a082318c6040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f11561000257505060405151600097509250505b600654861015610e045760068054600254600160a060020a0316916370a082319189908110156100025760009182526000805160206110cf83398151915201546040805160e060020a6370a08231028152600160a060020a0392909216600483015251602482810193602093839003909101908290876161da5a03f115610002575050604051518084028b900495509150506000841115610d82577ff340c079d598119636d42046c6a2d2faf7a68c04aecee516f0e0b8a9e79b86666006600050878154811015610002576000919091526000805160206110cf833981519152015460408051600160a060020a03929092168252602082018790528386048c900482820152519081900360600190a160025460068054600160a060020a03929092169163a9059cbb919089908110156100025760009182526000805160206110cf83398151915201546040805160e060020a63a9059cbb028152600160a060020a039290921660048301526024820189905251604482810193602093839003909101908290876161da5a03f115610002575050505b60019590950194610bed565b9450898589020493508760001415610e11577fdb0f19c627ca59a2db73b1e1e8c4853f34a58afa92b29331e56c75144fa0c84c6006600050878154811015610002576000919091526000805160206110cf833981519152015460408051600160a060020a03929092168252519081900360200190a15b5050505050505050505050565b87841115610e84577f211d59fc569e166e12f7ca82135d85b1f178f636fefe40d168f0113cf07f818f6006600050878154811015610002576000919091526000805160206110cf833981519152015460408051600160a060020a03929092168252519081900360200190a1879350610ee8565b7f4b0bc4f25f8d0b92d2e12b686ba96cd75e4e69325e6cf7b1f3119d14eaf2cbdf6006600050878154811015610002576000919091526000805160206110cf833981519152015460408051600160a060020a03929092168252519081900360200190a15b60008411156110b05760068054998501997ff340c079d598119636d42046c6a2d2faf7a68c04aecee516f0e0b8a9e79b86669190889081101561000257600091909152604080516000805160206110cf8339815191529290920154600160a060020a0316825260208201879052818101889052519081900360600190a160025460068054600160a060020a03929092169163a9059cbb91908990811015610002576000918252604080516000805160206110cf833981519152929092015460e060020a63a9059cbb028352600160a060020a031660048301526024820189905251604482810193602093839003909101908290876161da5a03f1156100025750506040805160025460e060020a6370a08231028252600160a060020a038f811660048401529251921692506370a0823191602482810192602092919082900301816000876161da5a03f115610002575050506040518051906020015097508750600260009054906101000a9004600160a060020a0316600160a060020a03166381f03fcb8c6040518260e060020a0281526004018082600160a060020a031681526020019150506020604051808303816000876161da5a03f115610002575050604051519a50505b60019590950194610ae3565b600091505b50919050565b60010161065956f652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526" - } - }, - "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc": { - "balance": "0x4563918244f400000", - "code": "0x606060405236156100da5760e060020a600035046313af40358114610145578063186ef9621461016757806331962cdc14610189578063365a86fc146101ab5780634162169f146101bd57806348c981e2146101cf5780634dfc3db61461020f57806361bc221a146102505780636637b882146102595780636c0e29601461027b5780638da5cb5b146104795780638f2b29a71461048b5780639137c1a714610602578063b199efb514610624578063b826c4fd14610636578063d1c3c84a1461063f578063d2f0ad9214610651578063fc340716146106bf575b6107236002546040805160e060020a630e7082030281529051600092600160a060020a031691630e708203916004828101926020929190829003018187876161da5a03f1156100025750506040515133600160a060020a039081169116149050610737575060015b90565b610861600435600054600160a060020a03908116339091161461089257610002565b610861600435600054600160a060020a0390811633909116146108a757610002565b610861600435600054600160a060020a0390811633909116146108bc57610002565b610863600154600160a060020a031681565b610863600254600160a060020a031681565b610861600435600054600160a060020a0390811633909116148015906102055750600154600160a060020a039081163390911614155b156108d157610002565b61088060008054600160a060020a0390811633909116148015906102435750600154600160a060020a039081163390911614155b156108fa57506001610142565b61088060055481565b610861600435600054600160a060020a0390811633909116146109e857610002565b6108805b6000600060006000600060006000600060006000600260009054906101000a9004600160a060020a0316600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150985088600160a060020a03163130600160a060020a03163101975088600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160025460035460e060020a6381f03fcb028452600160a060020a0390811660048501529351919b5090921692506381f03fcb916024828101926020929190829003018187876161da5a03f11561000257505060408051805160025460e060020a6318160ddd0283529251909950600160a060020a039290921692506318160ddd916004828101926020929190829003018187876161da5a03f11561000257505060408051805160025460035460e060020a6370a08231028452600160a060020a039081166004850152935191995090921692506370a08231916024828101926020929190829003018187876161da5a03f115610002575050506040518051906020015093508784860202925088600160a060020a03163188880103840291508585029050808210156109fd57610a05565b610863600054600160a060020a031681565b61088060043560006000600060006000600260009054906101000a9004600160a060020a0316600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150935083600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051600254815160035460e060020a6381f03fcb028452600160a060020a0390811660048501529351909750921692506381f03fcb916024808301926020929190829003018187876161da5a03f11561000257505060408051805160025460e060020a6318160ddd0283529251909550600160a060020a039290921692506318160ddd916004828101926020929190829003018187876161da5a03f115610002575050506040518051906020015090508581038183020486820387850204039450845084945050505050919050565b610861600435600054600160a060020a039081163390911614610a1157610002565b610863600354600160a060020a031681565b61088060065481565b610863600454600160a060020a031681565b6108806004355b6040805160025460035460e060020a6370a08231028352600160a060020a039081166004840152925160009384939216916370a08231916024828101926020929190829003018187876161da5a03f115610002575050604051519093046001019392505050565b61086160006000600060006000600060006000600060009054906101000a9004600160a060020a0316600160a060020a031633600160a060020a0316141580156107195750600154600160a060020a039081163390911614155b15610cbc57610002565b604080519115158252519081900360200190f35b600654600554600019909101901115610803576040805160025460035460e060020a6370a0823102835230600160a060020a03908116600485015293519184169363a9059cbb9391169160019185916370a082319160248082019260209290919082900301816000876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600482019590955260001994909401602485015251604480850194602094509192509082900301816000876161da5a03f115610002575060019250610142915050565b6005805460010190556040805160025460e160020a63664d71fb0282529151600160a060020a03929092169163cc9ae3f69160048181019260209290919082900301816000876161da5a03f115610002575060019250610142915050565b005b60408051600160a060020a03929092168252519081900360200190f35b60408051918252519081900360200190f35b60008054600160a060020a0319168217905550565b60048054600160a060020a0319168217905550565b60018054600160a060020a0319168217905550565b604051600160a060020a0382811691309091163190600081818185876185025a03f15050505050565b600254600160a060020a03166000141561091657506002610142565b600354600160a060020a03166000141561093257506003610142565b600454600160a060020a03166000141561094e57506004610142565b600354604080517f86c9b536000000000000000000000000000000000000000000000000000000008152905130600160a060020a039081169316916386c9b53691600482810192602092919082900301816000876161da5a03f11561000257505060405151600160a060020a031690911490506109cd57506005610142565b30600160a060020a0316316000141561014257506006610142565b60028054600160a060020a0319168217905550565b808203830499505b50505050505050505090565b60038054600160a060020a0319168217905550565b6006819055600354604080517fd0679d34000000000000000000000000000000000000000000000000000000008152600160a060020a038981166004830152938b04602482018190529151919750919092169163d0679d349160448181019260209290919082900301816000876161da5a03f11561000257505060408051600160055530600160a060020a031631815290517f7027eecbd2a688fc1fa281702b311ed7168571514adfd17014a55d828cb4338292509081900360200190a1604051600160a060020a0389811691309091163190600081818185876185025a03f15050604080517fd2cc718f000000000000000000000000000000000000000000000000000000008152905163d2cc718f9250600482810192602092919082900301816000876161da5a03f11561000257505060408051805160025460e060020a6370a08231028352600160a060020a038a81166004850152935191975090921692506370a0823191602482810192602092919082900301816000876161da5a03f11561000257505060408051805160025460e060020a6381f03fcb028352600160a060020a038a81166004850152935191965090921692506381f03fcb91602482810192602092919082900301816000876161da5a03f11561000257505060408051805160025460e160020a63664d71fb0283529251909450600160a060020a0392909216925063cc9ae3f691600482810192602092919082900301816000876161da5a03f115610002575050604080516002546004805460e060020a63a9059cbb028452600160a060020a03908116918401919091526001602484015292519216925063a9059cbb91604482810192602092919082900301816000876161da5a03f115610002575050505b5050505050505050565b6002546040805160e060020a630e7082030281529051600160a060020a0390921691630e7082039160048181019260209290919082900301816000876161da5a03f115610002575050604051519850610d15905061027f565b60408051600160a060020a038b1631815290519198507f07cf7e805770612a8b2ee8e0bcbba8aa908df5f85fbc4f9e2ef384cf75315038919081900360200190a187600160a060020a03163130600160a060020a0316310195508660001480610d7e5750856000145b15610db1576040517f30090d86c52e12fbc1213c1ecf7e193d6ce4a5c838c8c41d06c1a9daea8a2cec90600090a1610cb2565b309450610a268761065856", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b": { - "balance": "0x0", - "code": "0x606060405236156100985760e060020a6000350463013cf08b811461009a57806313af4035146100d757806331962cdc146100f9578063365a86fc1461011b578063400e39491461012d5780634162169f146101375780634dfc3db6146101495780636637b8821461018a5780638da5cb5b146101ac578063e66f53b7146101be578063e90956cf146101d0578063ff2f4bd2146101f2575b005b61024460043560048054829081101561000257506000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b015481565b610098600435600054600160a060020a03908116339091161461026157610002565b610098600435600054600160a060020a03908116339091161461027657610002565b61024e600154600160a060020a031681565b6102446004545b90565b61024e600254600160a060020a031681565b61024460008054600160a060020a03908116339091161480159061017d5750600154600160a060020a039081163390911614155b1561028b57506001610134565b610098600435600054600160a060020a0390811633909116146102c157610002565b61024e600054600160a060020a031681565b61024e600354600160a060020a031681565b610098600435600054600160a060020a0390811633909116146102d657610002565b6100986000606081815260a06040526080828152825491929091819033600160a060020a0390811691161480159061023a5750600154600160a060020a039081163390911614155b1561031857610002565b6060908152602090f35b600160a060020a03166060908152602090f35b60008054600160a060020a0319168217905550565b60018054600160a060020a0319168217905550565b600254600160a060020a03168114156102a657506002610134565b600354600160a060020a031681141561013457506003610134565b60028054600160a060020a0319168217905550565b60038054600160a060020a0319168217905550565b50508054839250600019810190811015610002579060005260206000209001600050819055505b50505050565b6002547f70a082310000000000000000000000000000000000000000000000000000000060a090815230600160a060020a0390811660a45291909116906370a082319060c49060209060248187876161da5a03f11561000257505060405151821415905061038557610312565b60006040518059106103945750595b9080825280602002602001820160405250935062093a809150600260009054906101000a9004600160a060020a0316600160a060020a031663612e45a3600360009054906101000a9004600160a060020a0316600086888760016040518760e060020a0281526004018087600160a060020a03168152602001868152602001806020018060200185815260200184151581526020018381038352878181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156104815780820380516001836020036101000a031916815260200191505b508381038252868181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156104da5780820380516001836020036101000a031916815260200191505b50985050505050505050506020604051808303816000876161da5a03f1156100025750506040515160048054600181018083559294509250908280158290116102eb578183600052602060002091820191016102eb91905b808211156105465760008155600101610532565b509056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd1a0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd1a1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd1a2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd1a3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd1a4": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0xad3ecf23c0c8983b07163708be6d763b5f056193": { - "balance": "0x0", - "code": "0x606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b9291505056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0xbe3ae5cb97c253dda67181c6e34e43f5c275e08b": { - "balance": "0x167d285b38143c04f", - "nonce": "68" - }, - "0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89": { - "balance": "0x9651c71936", - "code": "0x606060405236156100b95760e060020a600035046313af4035811461019e57806326f5a8c9146101c1578063371fa854146101ca5780634162169f146101d35780634c8fe526146101e55780635970c915146101f757806361bc221a14610209578063625e847d146102125780636637b882146102325780637f9f519f146102555780638da5cb5b14610278578063a9059cbb1461028a578063c4463c80146102b0578063c9d27afe146102df578063e66f53b714610305575b6103176002547f0e708203000000000000000000000000000000000000000000000000000000006060908152600091600160a060020a031690630e7082039060649060209060048187876161da5a03f1156100025750506040515133600160a060020a039081169116149050610329576040805133600160a060020a03166020820152818152600f818301527f636f6e73747563746f72206661696c0000000000000000000000000000000000606082015290517fa6af7265d7ede5fbf0ee375956b52b362800d4f92e268809bef5fdf2a57924b89181900360800190a15060015b90565b61031760043560008054600160a060020a03908116339091161461049257610002565b61047560055481565b61047560045481565b61047f600254600160a060020a031681565b61047f600654600160a060020a031681565b61047f600754600160a060020a031681565b61047560035481565b61031760008054600160a060020a0390811633909116146104ef57610002565b61031760043560008054600160a060020a03908116339091161461057a57610002565b61031760043560008054600160a060020a0390811633909116146105d757610002565b61047f600054600160a060020a031681565b61031760043560243560008054600160a060020a03908116339091161461060f57610002565b61031760043560243560443560643560843560008054600160a060020a0390811633909116146106a657610002565b61031760043560243560008054600160a060020a0390811633909116146107bb57610002565b61047f600154600160a060020a031681565b60408051918252519081900360200190f35b60055460035460001990910190111561040257604080516002546006547f70a0823100000000000000000000000000000000000000000000000000000000835230600160a060020a03908116600485015293519184169363a9059cbb9391169184916370a0823191602480830192602092919082900301818a876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600482019490945260248101939093525160448084019360209350829003018187876161da5a03f11561000257505060016003819055915061019b9050565b6040805160038054600190810190915560025460048054925460e260020a632099877102855290840192909252600160a060020a03918216602484015292519216916382661dc491604480820192602092909190829003018187876161da5a03f11561000257506001925061019b915050565b6060908152602090f35b600160a060020a03166060908152602090f35b600160a060020a03821660609081527f3edd90e7770f06fafde38004653b33870066c33bfc923ff6102acd601f85dfbc90602090a181600060006101000a815481600160a060020a0302191690830217905550600190505b919050565b6001600355600754600160a060020a03908116908290301631606082818181858883f15050604080516002546001546004805460e260020a632099877102855290840152600160a060020a0390811660248401529251921694506382661dc493506044808201935060209291829003018187876161da5a03f11561000257506001925061019b915050565b6002805473ffffffffffffffffffffffffffffffffffffffff1916831790819055600160a060020a031660609081527fce6a5015a40a2ec38ce912a63bca374d85386207c6927d284292449f1431082290602090a15060016104ea565b600582905560608281527fbab6859bc098da798dbdc4860f0fee7467d703dadd975799e8c258b46a37d3de90602090a15060016104ea565b60025460e060020a63a9059cbb026060908152600160a060020a0385811660645260848590529091169063a9059cbb9060a49060209060448187876161da5a03f11561000257505060408051600160a060020a03861681526020810185905281517f69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de293509081900390910190a15060015b92915050565b6006805473ffffffffffffffffffffffffffffffffffffffff1990811686179091556001600381905580548216871790556004879055600584905560078054909116831790819055600160a060020a03908116908290301631606082818181858883f15050604080516002546004805460015460e260020a632099877102855291840152600160a060020a0390811660248401529251921694506382661dc493506044808201935060209291829003018187876161da5a03f11561000257505060408051600454600654908252600160a060020a0316602082015281517fa1ab731770d71027cd294cc0af5c8f5ec3c2ff5dbe6b75d68963d17192f8377b93509081900390910190a150600195945050505050565b6002547fc9d27afe0000000000000000000000000000000000000000000000000000000060609081526064859052831515608452600160a060020a039091169063c9d27afe9060a49060209060448187876161da5a03f11561000257505060408051858152841515602082015281517f8bfa1f40665434b48e7becc865cc0586ce3d6d2388521c05d4db87536ac8279993509081900390910190a15060016106a056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490" - } - }, - "0xea674fdde714fd979de3edf0f56aa9716b898ec8": { - "balance": "0x4ab3566739e7b24371", - "nonce": "286339" - }, - "0xf835a0247b0063c04ef22006ebe57c5f11977cc4": { - "balance": "0x9645db5736", - "code": "0x606060405236156100b95760e060020a600035046313af4035811461019e57806326f5a8c9146101c1578063371fa854146101ca5780634162169f146101d35780634c8fe526146101e55780635970c915146101f757806361bc221a14610209578063625e847d146102125780636637b882146102325780637f9f519f146102555780638da5cb5b14610278578063a9059cbb1461028a578063c4463c80146102b0578063c9d27afe146102df578063e66f53b714610305575b6103176002547f0e708203000000000000000000000000000000000000000000000000000000006060908152600091600160a060020a031690630e7082039060649060209060048187876161da5a03f1156100025750506040515133600160a060020a039081169116149050610329576040805133600160a060020a03166020820152818152600f818301527f636f6e73747563746f72206661696c0000000000000000000000000000000000606082015290517fa6af7265d7ede5fbf0ee375956b52b362800d4f92e268809bef5fdf2a57924b89181900360800190a15060015b90565b61031760043560008054600160a060020a03908116339091161461049257610002565b61047560055481565b61047560045481565b61047f600254600160a060020a031681565b61047f600654600160a060020a031681565b61047f600754600160a060020a031681565b61047560035481565b61031760008054600160a060020a0390811633909116146104ef57610002565b61031760043560008054600160a060020a03908116339091161461057a57610002565b61031760043560008054600160a060020a0390811633909116146105d757610002565b61047f600054600160a060020a031681565b61031760043560243560008054600160a060020a03908116339091161461060f57610002565b61031760043560243560443560643560843560008054600160a060020a0390811633909116146106a657610002565b61031760043560243560008054600160a060020a0390811633909116146107bb57610002565b61047f600154600160a060020a031681565b60408051918252519081900360200190f35b60055460035460001990910190111561040257604080516002546006547f70a0823100000000000000000000000000000000000000000000000000000000835230600160a060020a03908116600485015293519184169363a9059cbb9391169184916370a0823191602480830192602092919082900301818a876161da5a03f11561000257505060408051805160e060020a63a9059cbb028252600482019490945260248101939093525160448084019360209350829003018187876161da5a03f11561000257505060016003819055915061019b9050565b6040805160038054600190810190915560025460048054925460e260020a632099877102855290840192909252600160a060020a03918216602484015292519216916382661dc491604480820192602092909190829003018187876161da5a03f11561000257506001925061019b915050565b6060908152602090f35b600160a060020a03166060908152602090f35b600160a060020a03821660609081527f3edd90e7770f06fafde38004653b33870066c33bfc923ff6102acd601f85dfbc90602090a181600060006101000a815481600160a060020a0302191690830217905550600190505b919050565b6001600355600754600160a060020a03908116908290301631606082818181858883f15050604080516002546001546004805460e260020a632099877102855290840152600160a060020a0390811660248401529251921694506382661dc493506044808201935060209291829003018187876161da5a03f11561000257506001925061019b915050565b6002805473ffffffffffffffffffffffffffffffffffffffff1916831790819055600160a060020a031660609081527fce6a5015a40a2ec38ce912a63bca374d85386207c6927d284292449f1431082290602090a15060016104ea565b600582905560608281527fbab6859bc098da798dbdc4860f0fee7467d703dadd975799e8c258b46a37d3de90602090a15060016104ea565b60025460e060020a63a9059cbb026060908152600160a060020a0385811660645260848590529091169063a9059cbb9060a49060209060448187876161da5a03f11561000257505060408051600160a060020a03861681526020810185905281517f69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de293509081900390910190a15060015b92915050565b6006805473ffffffffffffffffffffffffffffffffffffffff1990811686179091556001600381905580548216871790556004879055600584905560078054909116831790819055600160a060020a03908116908290301631606082818181858883f15050604080516002546004805460015460e260020a632099877102855291840152600160a060020a0390811660248401529251921694506382661dc493506044808201935060209291829003018187876161da5a03f11561000257505060408051600454600654908252600160a060020a0316602082015281517fa1ab731770d71027cd294cc0af5c8f5ec3c2ff5dbe6b75d68963d17192f8377b93509081900390910190a150600195945050505050565b6002547fc9d27afe0000000000000000000000000000000000000000000000000000000060609081526064859052831515608452600160a060020a039091169063c9d27afe9060a49060209060448187876161da5a03f11561000257505060408051858152841515602082015281517f8bfa1f40665434b48e7becc865cc0586ce3d6d2388521c05d4db87536ac8279993509081900390910190a15060016106a056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000003e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000304a554a310c7e546dfe434669c62820b7d83490" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "1881284", - "difficulty": "59917798852808", - "timestamp": "1468467296", - "gasLimit": "4712388", - "miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8" - }, - "input": "0xf869448505d21dba00833567e09403e3d4561a8f8e975fdcd798d32857a20cf25e7e8084be9a65551ba0d4dd5fff30e83fbe630bb0fd67eeefe9e3aad0c3ee870a2b6e80fc40191bc7d4a074f93b546bfad60f3cae8e4aafef835237095d6618334154a24df4b4d49d9359", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0xbe3ae5cb97c253dda67181c6e34e43f5c275e08b", - "gas": "0x3567e0", - "gasUsed": "0x26e1ef", - "to": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "input": "0xbe9a6555", - "calls": [ - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x34affa", - "gasUsed": "0x1ef", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x4b6753bc", - "output": "0x0000000000000000000000000000000000000000000000000000000057870858", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x34abef", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "output": "0x00000000000000000000000000000000000000000001819451f999d617dafa93", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x34a705", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "output": "0x00000000000000000000000000000000000000000001819451f999d617dafa93", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x34a31a", - "gasUsed": "0xa2f3", - "to": "0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "input": "0xa9059cbb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa93", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "gas": "0x343e8c", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa93", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000c0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd" - ], - "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa93", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89", - "topics": [ - "0x69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de2" - ], - "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa93", - "position": "0x1" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x33ff04", - "gasUsed": "0x168e", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0xa8618f710000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x339a3b", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x3395a4", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x339363", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x339129", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x338cfa", - "gasUsed": "0x13f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x18160ddd", - "output": "0x00000000000000000000000000000000000000000003034f5ca7d45e17df199b", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x338a75", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x00000000000000000000000000000000000000000001819451f999d617dafa93", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x33e6f2", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000f835a0247b0063c04ef22006ebe57c5f11977cc4", - "output": "0x00000000000000000000000000000000000000000001819451f999d617dafa76", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x33e208", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000f835a0247b0063c04ef22006ebe57c5f11977cc4", - "output": "0x00000000000000000000000000000000000000000001819451f999d617dafa76", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x33de20", - "gasUsed": "0x685b", - "to": "0xf835a0247b0063c04ef22006ebe57c5f11977cc4", - "input": "0xa9059cbb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa76", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0xf835a0247b0063c04ef22006ebe57c5f11977cc4", - "gas": "0x337992", - "gasUsed": "0x5fca", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa76", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000f835a0247b0063c04ef22006ebe57c5f11977cc4", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd" - ], - "data": "0x00000000000000000000000000000000000000000001819451f999d617dafa76", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0xf835a0247b0063c04ef22006ebe57c5f11977cc4", - "topics": [ - "0x69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c7dc7cd545266326de2" - ], - "data": "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd00000000000000000000000000000000000000000001819451f999d617dafa76", - "position": "0x1" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x3374a2", - "gasUsed": "0x168e", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0xa8618f710000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x330fd9", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x330b42", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x330901", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x3306c7", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x330298", - "gasUsed": "0x13f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x18160ddd", - "output": "0x00000000000000000000000000000000000000000003034f5ca7d45e17df199b", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x330013", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f509", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x33490b", - "gasUsed": "0x3f781", - "to": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "input": "0xfc340716", - "calls": [ - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32e30d", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32e037", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32dd7b", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32daf9", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32d6ab", - "gasUsed": "0x13f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x18160ddd", - "output": "0x00000000000000000000000000000000000000000003034f5ca7d45e17df199b", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32d400", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f509", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x32c975", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f509", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x3276d3", - "gasUsed": "0xa49d", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0xd0679d340000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x320fe1", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f509", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x320b5b", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc" - ], - "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x3164e1", - "gasUsed": "0x4e91", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0x", - "value": "0x4563918244f400000", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x3115cc", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x311382", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "output": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x310f37", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x310ae9", - "gasUsed": "0x1446e", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xcc9ae3f6", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x30a397", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x309fc1", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x309c45", - "gasUsed": "0x122af", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0x0221038a0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc0000000000000000000000000000000000000000000000022b1c8c12279fffff", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "gas": "0x301e6f", - "gasUsed": "0x10068", - "to": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "input": "0x", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2fbb97", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2fa477", - "gasUsed": "0xe7b6", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xcc9ae3f6", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x2f3d25", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x2f394f", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x2f35d3", - "gasUsed": "0x8b5f", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0x0221038a0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc0000000000000000000000000000000000000000000000022b1c8c12279fffff", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "gas": "0x2eb7fd", - "gasUsed": "0x6918", - "to": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "input": "0x", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2e5525", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2e5168", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "output": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccd", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2e4d69", - "gasUsed": "0x5fca", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccc", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd" - ], - "data": "0x0000000000000000000000000000000000000000000181a7ae53ea2f0bef8ccc", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x22b1c8c12279fffff", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "topics": [ - "0x9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc", - "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc" - ], - "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff", - "position": "0x1" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x22b1c8c12279fffff", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "topics": [ - "0x9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc", - "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc" - ], - "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff", - "position": "0x1" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "gas": "0x2fc505", - "gasUsed": "0xd4fa", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f0000000000000000000000000000000000000000000000000000000000000001", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc", - "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "topics": [ - "0x07cf7e805770612a8b2ee8e0bcbba8aa908df5f85fbc4f9e2ef384cf75315038" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000", - "position": "0x6" - }, - { - "address": "0x6e715ab4f598eacf0016b9b35ef33e4141844ccc", - "topics": [ - "0x7027eecbd2a688fc1fa281702b311ed7168571514adfd17014a55d828cb43382" - ], - "data": "0x000000000000000000000000000000000000000000000004563918244f400000", - "position": "0x8" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2f5092", - "gasUsed": "0x14e37", - "to": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "input": "0xd95f98ce", - "calls": [ - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2eea7c", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "output": "0x000000000000000000000000000000000000000000000004563918244f3ffffe", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2ee4cb", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x000000000000000000000000000000000000000000000026b8b4a0b1e8292492", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2edfff", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2edb9a", - "gasUsed": "0x6994", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0xd0679d340000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f0000000000000000000000000000000000000000000000000000000000000063", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2e7519", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f508", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2e7093", - "gasUsed": "0x5fca", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f0000000000000000000000000000000000000000000000000000000000000063", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000063", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e6f59", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e6afa", - "gasUsed": "0x1113", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0x65f13792000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x0000000000000000000000000000000000000000000000000037bc5737aa7ba8", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2e06f9", - "gasUsed": "0x15f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x0e708203", - "output": "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2e04b8", - "gasUsed": "0x113", - "to": "0xad3ecf23c0c8983b07163708be6d763b5f056193", - "input": "0xd2cc718f", - "output": "0x000000000000000000000000000000000000000000000004563918244f400000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2e027b", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2dfe4c", - "gasUsed": "0x13f", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x18160ddd", - "output": "0x00000000000000000000000000000000000000000003034f5ca7d45e17df199b", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2dfbc7", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x000000000000000000000000000000000000000000000026b8b4a0b1e8292492", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e5281", - "gasUsed": "0x329", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x81f03fcb0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "output": "0x000000000000000000000000000000000000000000000004563918244f3ffffe", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e4dcc", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "output": "0x0000000000000000000000000000000000000000000000000000000000000064", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e4857", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a08231000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "output": "0x000000000000000000000000000000000000000000000026b8b4a0b1e8292492", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "gas": "0x2e3bae", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb000000000000000000000000da4a4626d3e16e094de3225a751aab7128e965260000000000000000000000000000000000000000000000000000000000000064", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000006dbfc63479ffc031f23e94dc91befa38bec2c25f", - "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000064", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "topics": [ - "0x4b0bc4f25f8d0b92d2e12b686ba96cd75e4e69325e6cf7b1f3119d14eaf2cbdf" - ], - "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e96526", - "position": "0x6" - }, - { - "address": "0x6dbfc63479ffc031f23e94dc91befa38bec2c25f", - "topics": [ - "0xf340c079d598119636d42046c6a2d2faf7a68c04aecee516f0e0b8a9e79b8666" - ], - "data": "0x000000000000000000000000da4a4626d3e16e094de3225a751aab7128e9652600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000", - "position": "0x9" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2e00dc", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2dfc58", - "gasUsed": "0xa3bb", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0xd0679d340000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b0000000000000000000000000000000000000000000000000000000000000001", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2d9648", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f4a5", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0x2d91c2", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b0000000000000000000000000000000000000000000000000000000000000001", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2d57a6", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2d5515", - "gasUsed": "0x3478d", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x2ceffb", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x2ce86e", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2a0c87", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x2a09f6", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x29a4dc", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x299d4f", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000002", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000002" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x26fc00", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000002", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x26f96f", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x269455", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x268cc8", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000003", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x23eb79", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000003", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x23e8e8", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x2383ce", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x237c41", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000004", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000004" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x20daf2", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000004", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x20d861", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x207347", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x206bba", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000005", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000005" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1dca6b", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000005", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1dc7da", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1d62c0", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1d5b33", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000006", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000006" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1ab9e4", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000006", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1ab753", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1a5239", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1a4aac", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000007", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000007" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x17a95d", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000007", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x17a6cc", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1741b2", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x173a25", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000008", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000008" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1498d6", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000008", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x149645", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x14312b", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x14299e", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000009", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x0000000000000000000000000000000000000000000000000000000000000009" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x11884f", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x0000000000000000000000000000000000000000000000000000000000000009", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0x1185be", - "gasUsed": "0x30cf5", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0xff2f4bd2", - "calls": [ - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x1120a4", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000007498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "gas": "0x111917", - "gasUsed": "0x29e8d", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x612e45a3000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "output": "0x000000000000000000000000000000000000000000000000000000000000000a", - "calls": [ - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x304a554a310c7e546dfe434669c62820b7d83490", - "gas": "0x3", - "gasUsed": "0x3", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x", - "error": "out of gas", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f", - "0x000000000000000000000000000000000000000000000000000000000000000a" - ], - "data": "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000", - "position": "0x2" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0xe77c8", - "gasUsed": "0x112", - "to": "0x7498bb5749c9801f1f7e490baf5f966dbfe4e97b", - "input": "0x400e3949", - "output": "0x000000000000000000000000000000000000000000000000000000000000000a", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x03e3d4561a8f8e975fdcd798d32857a20cf25e7e", - "gas": "0xe7537", - "gasUsed": "0x1eafd", - "to": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "input": "0x975057e7", - "calls": [ - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0xe0f53", - "gasUsed": "0x314", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0x70a082310000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "output": "0x000000000000000000000000000000000000000000030328a3f333ac2fb5f4a4", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0xe096d", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000007ccbc69292c7a6d7b538c91f3b283de97906cf3000000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000007ccbc69292c7a6d7b538c91f3b283de97906cf30" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0xd6871", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb0000000000000000000000001b9ec8ba24630b75a7a958153ffff56dd6d4b6a200000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x0000000000000000000000001b9ec8ba24630b75a7a958153ffff56dd6d4b6a2" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "gas": "0xcc775", - "gasUsed": "0x9a62", - "to": "0x304a554a310c7e546dfe434669c62820b7d83490", - "input": "0xa9059cbb000000000000000000000000c3a2c744ad1f5253c736875b93bacce5b01b060b00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x304a554a310c7e546dfe434669c62820b7d83490", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000004fd27b205895e698fa350f7ea57cec8a21927fcd", - "0x000000000000000000000000c3a2c744ad1f5253c736875b93bacce5b01b060b" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "topics": [ - "0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x2" - }, - { - "address": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "topics": [ - "0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x3" - }, - { - "address": "0x4fd27b205895e698fa350f7ea57cec8a21927fcd", - "topics": [ - "0xc6d8c0af6d21f291e7c359603aa97e0ed500f04db6e983b9fce75a91c6b8da6b" - ], - "data": "0x00000000000000000000000000000000000000000001010d8bfbbbe40fe7518c", - "position": "0x4" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json deleted file mode 100644 index 66d458200..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json +++ /dev/null @@ -1,580 +0,0 @@ -{ - "genesis": { - "difficulty": "7507253814130", - "extraData": "0xd783010400844765746887676f312e352e31856c696e7578", - "gasLimit": "3141592", - "hash": "0x3d9d19618f67bbb7708403fe9bda131fbade0449d2ac12bf3b140b4269112826", - "miner": "0x63a9975ba31b0b9626b34300f7f627147df1f526", - "mixHash": "0x50aaa8973eadd4bbfc7f5b59d5be52f6a1be2d38f40b5a0786a24b90257520da", - "nonce": "0x3547956c62c256b9", - "number": "595531", - "stateRoot": "0x79d00dd270bffc48d89fa55842f63f840981121378da8c6de4d479535f25ed6a", - "timestamp": "1448471472", - "totalDifficulty": "3448100174991667199", - "alloc": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x44dc051cccdfd2e132", - "nonce": "39602" - }, - "0x350e0ffc780a6a75b44cc52e1ff9092870668945": { - "balance": "0xe37111b7c79406c0", - "code": "0x606060405236156100f05760e060020a60003504631ff6c70581146100f257806347980c0d146100fd57806353ba9c2f146101085780635ea8cd12146101c957806369d640fd146101f05780637ce3489b146102405780637d1bb97a1461026b5780637fd6f15c146103e55780638bf50628146103f057806390a248f814610411578063a8f37bb214610438578063b019e0171461046a578063b4c70cea1461059b578063cf955f34146106a1578063d229b54b146106bd578063d54b4a04146106e4578063e021fadb146106f1578063e45be8eb14610858578063eddfa7c814610863578063f2a75fe41461095d575b005b6109a5621e84845481565b6109a5621e84865481565b6109b76004356024356000808080806003876103e881101561000257506107d0880201866103e8811015610002579090600202016000505461ffff168152602081019190915260400160002054600160a060020a031692506003856103e881101561000257506107d0860201846103e88110156100025790906002020160005054620100009004600390810b9250856103e881101561000257506107d0860201846103e8811015610002579090600202016000506001015490509250925092565b6100f0600435621e848354600160a060020a0390811633909116141561026857621e848755565b6109e36004356024356003826103e881101561000257506107d0830201816103e88110156100025790906002020160005080546001919091015461ffff821693506201000090910460030b915083565b6100f0600435621e848354600160a060020a0390811633909116141561026857621e84858190555b50565b610a0a600435617d00604051908101604052806103e8905b600081526020019060019003908161028357505060408051617d0081019091526103e8815b60008152602001906001900390816102a857505060408051617d0081019091526103e8815b60008152602001906001900390816102cd5750600090505b6103e861ffff82161015610d09576000806003836103e8811015610002576107d002018150876103e881101561000257600202016000505461ffff168152602081019190915260400160002054600160a060020a031684826103e8811015610002575050602082028501526003816103e8811015610002576107d00201600050856103e8811015610002579090600202016000505462010000900460030b83826103e8811015610002575050600390810b60208302850152816103e8811015610002576107d00201600050856103e8811015610002579090600202016000506001015482826103e8811015610002575050602082028301526001016102e5565b6109a5621e84855481565b610a59600435600060208190529081526040902054600160a060020a031681565b6100f0600435621e848354600160a060020a0390811633909116141561026857621e848655565b6100f060043560243560443560643560843560a435610a8e868684866101000288620100000286607f02010101610870565b604080516004803580820135602081810280860182019096528185526100f09593946024949093850192918291908501908490808284375050604080518735808a013560208181028085018201909552818452989a996044999398509190910195509350839250850190849080828437505060408051606435808a013560208181028085018201909552818452989a9935999860849850929650602491909101945092508291908501908490808284375050604080519635808901356020818102808b018201909452818a5297999860a4989097506024929092019550935083925085019084908082843750949650505050505050621e848354600090600160a060020a03908116339091161415610a8e575b8551811015610a8e57606060405190810160405280610d1186610ebc565b60408051602060248035600481810135601f81018590048502860185019096528585526109a5958135959194604494929390920191819084018382808284375094965050933593505050505b6000831515610699577ffd33e90d0eac940755277aa91045b95664988beeeafc4ed7d1281a6d83afbc003384846040518084600160a060020a03168152602001806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106895780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15b509192915050565b610a7660043560016020526000908152604090205461ffff1681565b6100f0600435621e848354600160a060020a0390811633909116141561026857621e848455565b610a7660025461ffff1681565b604080516004803580820135602081810280860182019096528185526109a59593946024949093850192918291908501908490808284375050604080518735808a013560208181028085018201909552818452989a9960449993985091909101955093508392508501908490808284375050604080519635808901356020818102808b018201909452818a529799986064989097506024929092019550935083925085019084908082843750506040805196358089013560208181028a81018201909452818a5297999860849890975060249290920195509350839250850190849080828437509496505050505050506000600060006000610ad68751895114606060405190810160405280602381526020017f446966666572656e74206e756d626572206f66207856616c732061732079566181526020017f6c732e00000000000000000000000000000000000000000000000000000000008152602001508a516105e7565b6109a5621e84875481565b6100f06004356024356044355b6000610a96848484345b6000808080808060038a6103e8811015610002576107d00201896103e88110156100025760020201805461ffff16825260208290526040822054621e8484546001830154621e848654939850600160a060020a03928316975060649181028290049650929092029190910492503316841415610f4d57610fbc82341015606060405190810160405280602e81526020017f4368616e67696e6720796f7572206f776e20706978656c20636f73747320313081526020017f25206f66206974732076616c7565000000000000000000000000000000000000815260200150846105e7565b6100f0621e848354600160a060020a039081163390911614156109a357604051621e848354600160a060020a03908116916000913016319082818181858883f150505050505b565b60408051918252519081900360200190f35b60408051600160a060020a0394909416845260039290920b602084015282820152519081900360600190f35b6040805161ffff94909416845260039290920b602084015282820152519081900360600190f35b6040518084617d008083818460006004610bc7f150918201918591508083818460006004610bc7f15061fa00840192508491508083818460006004610bc7f15062017700965092945050505050f35b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b505050505050565b90506000811115610ac25760405133600160a060020a031690600090839082818181858883f150505050505b50505050565b93505b505050949350505050565b1580610b4e5750610b4c8651895114606060405190810160405280602481526020017f446966666572656e74206e756d626572206f66207856616c7320617320636f6c81526020017f6f72732e000000000000000000000000000000000000000000000000000000008152602001508a516105e7565b155b80610bc55750610bc38551895114606060405190810160405280602481526020017f446966666572656e74206e756d626572206f66207856616c732061732070726981526020017f6365732e000000000000000000000000000000000000000000000000000000008152602001508a516105e7565b155b15610bd35760009350610acb565b5034915060009050805b8751811015610c63578481815181101561000257602090810290910101519092039160008310610d0157610cfb88828151811015610002579060200190602002015188838151811015610002579060200190602002015188848151811015610002579060200190602002015188858151811015610002579060200190602002015161087a565b6000821115610c8d5760405133600160a060020a031690600090849082818181858883f150505050505b610ac86000841015606060405190810160405280602181526020017f56616c756520776173206c657373207468616e2073756d206f6620707269636581526020017f7300000000000000000000000000000000000000000000000000000000000000815260200150856105e7565b91909101905b600101610bdd565b509193909250565b8152602001848381518110156100025790602001906020020151815260200183838151811015610002579060200190602002015181526020015060036000508783815181101561000257906020019060200201516103e8811015610002576107d002016000508683815181101561000257906020019060200201516103e8811015610002576002020160005081518154602084015160e060020a90810204620100000261ffff199190911690911765ffffffff00001916178155604091909101516001919091015560010161057d565b8454600061ffff919091161115610e225750604051621e84855460649088020490600160a060020a03851690600090838a039082818181858883f150505050505b845460018601546040805161ffff8e811682528d166020820152600160a060020a038881168284015262010000909404600390810b810b606083015260808201939093523390931660a0840152908a900b60c083015260e08201899052517fcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42918190036101000190a1606060405190810160405280611143335b600160a060020a03811660009081526001602052604081205461ffff1690811415610f485750604060008181206002805461ffff1981811661ffff928316600190810191821790945591821685526020858152958520805473ffffffffffffffffffffffffffffffffffffffff191688179055600160a060020a03871690945293528054909116821790555b919050565b60408051621e848754606082018352602182527f4d696e696d756d20706978656c2070726963652069732035302066696e6e657960208301527f2e00000000000000000000000000000000000000000000000000000000000000928201929092526110c29134101590896105e7565b1515610fca578695506110b5565b33600160a060020a031684600160a060020a03161415610de157604080518654600188015461ffff8e811684528d166020840152600160a060020a03881683850181905262010000909204600390810b810b60608501526080840182905260a0840192909252908b900b60c083015260e082015290517fcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42918190036101000190a18760038b6103e8811015610002576107d002018a6103e88110156100025760020201805465ffffffff0000191660e060020a92830292909204620100000291909117905581870395505b5050505050949350505050565b15806111365750610fbc83341015606060405190810160405280603281526020017f56616c7565206d7573742062652031302520686967686572207468616e20637581526020017f7272656e7420706978656c2070726963652e0000000000000000000000000000815260200150856105e7565b15610fca578695506110b5565b8152602081018a905260400188905260038b6103e8811015610002576107d002018a6103e8811015610002576002020160005081518154602084015160e060020a90810204620100000261ffff199190911690911765ffffffff000019161781556040919091015160019190910155600095506110b556", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000175901": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000175902": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000175903": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000175904": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760c7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760c8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760c9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760ca": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760cb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760cc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760cd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760ce": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760cf": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d1": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d2": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760d9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760da": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760db": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760dc": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760dd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760de": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760df": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001760e0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000176897": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000176898": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000176899": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000017689f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768a0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768a7": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768a8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768a9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768aa": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768ab": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768ac": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768ad": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768ae": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768af": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001768b0": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c37": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c38": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c39": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c3f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c40": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c45": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c46": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c47": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c48": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c49": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c4f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000196c50": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197407": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197408": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197409": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019740f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197410": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197411": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197412": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197413": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197414": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197415": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197416": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197417": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197418": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197419": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000019741f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197420": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197be3": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000197be4": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000000000000000000000000000000000000001e8484": "0x000000000000000000000000000000000000000000000000000000000000006e", - "0x00000000000000000000000000000000000000000000000000000000001e8486": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x00000000000000000000000000000000000000000000000000000000001e8487": "0x0000000000000000000000000000000000000000000000000011c37937e08000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xe1723559c995b1804c0512df6fe6d061eeb47aff37a3ced3b93f0c1bef247540": "0x0000000000000000000000000000000000000000000000000000000000000007" - } - }, - "0x3fcb0342353c541e210013aaddc2e740b9a33d08": { - "balance": "0x6a0e4be198f18400", - "nonce": "17" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "595532", - "difficulty": "7503588162862", - "timestamp": "1448471495", - "gasLimit": "3141592", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" - }, - "input": "0xf91a7311850ba43b7400832dc6c094350e0ffc780a6a75b44cc52e1ff90928706689458803782dace9d90000b91a04e021fadb000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000013a00000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fd000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000002fd0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000032fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebebffffffffffffffffffffffffffffffffffffffffffffffffffffffffff888888ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff636363fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e53ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080001ca0e8a879dd98a39d735b866ff64d84e9c144a17bcab106cf2f1327b1272db06aaca02ab279a2459b5e30dfea0bc8a888c7d2a190740090352b4a7aded30c45490af9", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0x3fcb0342353c541e210013aaddc2e740b9a33d08", - "gas": "0x2dc6c0", - "gasUsed": "0x2570bf", - "to": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "input": "0xe021fadb000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000013a00000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fd000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000002fd0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000032fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebebffffffffffffffffffffffffffffffffffffffffffffffffffffffffff888888ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff636363fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e53ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e08000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logs": [ - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebeb0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8888880000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b30000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e30000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3e0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdb0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f40000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000341000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b00000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a00000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5b0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a90000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b90000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6363630000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f90000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9c0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f80000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e530000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - }, - { - "address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945", - "topics": [ - "0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b0000000000000000000000000000000000000000000000000011c37937e08000", - "position": "0x0" - } - ], - "value": "0x3782dace9d90000", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json deleted file mode 100644 index 762ccbe58..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "genesis": { - "difficulty": "45944156141275", - "extraData": "0xd783010406844765746887676f312e342e32856c696e7578", - "gasLimit": "4714680", - "hash": "0x3c41811ab60f232565db6cfafb939d96255b9f678a203181c6f537d6c22d7e6f", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5", - "mixHash": "0x8b736c63e05d381ae593d584b63fef5c31b04a3cea72bd5a3c92f95f4f7040e8", - "nonce": "0xce8ffb5c1ad942ec", - "number": "1725115", - "stateRoot": "0xca08a341c1f95fcba0821c4a27662ef162d39e1f9f5722717531f510d54112b0", - "timestamp": "1466232982", - "totalDifficulty": "28554024908214037524", - "alloc": { - "0x0000000000000000000000000000000000000004": { - "balance": "0x0" - }, - "0x1d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed": { - "balance": "0x0", - "code": "0x606060405260e060020a600035046338cc483181146038578063767800de14604f578063a6f9dae1146060578063d1d80fdf14607e575b005b600054600160a060020a03165b6060908152602090f35b6045600054600160a060020a031681565b603660043560015433600160a060020a03908116911614609c576002565b603660043560015433600160a060020a0390811691161460be576002565b6001805473ffffffffffffffffffffffffffffffffffffffff19168217905550565b6000805473ffffffffffffffffffffffffffffffffffffffff1916821790555056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000088e1315687aec48a72786c6b3b3f075208b62713" - } - }, - "0x50739060a2c32dc076e507ae1a893aab28ecfe68": { - "balance": "0x6a8ecefb09f7c4141", - "code": "0x606060405236156101745760e060020a6000350463058aace1811461017f578063061e494f146101905780630d1fce421461021e57806311610c251461029157806312253a6c146102b5578063132ae5e9146102d357806316d190e3146102dc57806329e206bd146102e5578063337b68ba1461030a57806338bbfa50146103135780633f683b6a146104115780634dc6b523146104245780634e69d5601461042d57806366d16cc31461044a578063724ae9d014610453578063758971e81461046f5780637cf0ffcb146104965780638ca17995146104a35780639619367d146104b7578063a96a5a5b146104c0578063adc2c98a146104c9578063b70d0b3b146104d2578063bc99cc37146104db578063c4bc5da5146104e4578063cafb220214610502578063d28442ef1461050b578063d4c80edf14610514578063df06f9061461051d578063e8b5e51f14610527578063f738e5ca14610546578063f8b2cb4f14610553578063fa968eea14610594575b610661610663610295565b6106616000341115610eab57610002565b61066560043560006000600060006000600f6000508054905086101561021657600f8054879081101561000257505050507f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80284015490819052600e602052604090912080546001820154600283015460039390930154600160a060020a03929092169450925b509193509193565b6106965b601254601354601154600c5460009391019091010330600160a060020a0316318190101561028957604080517f62616e6b726f6c6c5f6d69736d61746368000000000000000000000000000000815290519081900360110190a05030600160a060020a0316315b8091505b5090565b6106615b600060006000600d60149054906101000a900460ff16156106ef57610002565b610661600d5433600160a060020a03908116911614610fd657610002565b610696600a5481565b61069660045481565b6106616004355b600d5460009033600160a060020a0390811691161461101c57610002565b61069660125481565b60408051602060248035600481810135601f81018590048502860185019096528585526106619581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760649791965060249190910194509092508291508401838280828437509496505050505050506000600060006000610a18600080546040805160e060020a6338cc483102815290518392600160a060020a0316916338cc4831916004828101926020929190829003018187876161da5a03f11561000257505060405151915050600160a060020a0381168214156114635761140b6000610939565b610696600d5460a060020a900460ff1681565b61069660085481565b6106a8600060006000600060006000600060006000610f8d610222565b61069660115481565b6106965b600a54600654600091829182911015610ef857610f33565b6106616004355b600d54600090819033600160a060020a0390811691161461108657610002565b61066161066360006102ec565b6106616004356000341115610e7957610002565b61069660055481565b61069660025481565b61069660035481565b61069660075481565b61069660065481565b610661600d5433600160a060020a03908116911614610ffc57610002565b610696600c5481565b61069660135481565b61069660105481565b610696600f545b90565b610661600d54600090819060a060020a900460ff1615610c8057610002565b6106616106636000610476565b6106966004355b600160a060020a0381166000908152600b602052604081205481901180156105845750600c548190115b15610ebd57600c54610ec6610222565b610696600080546040805160e060020a6338cc483102815290518392600160a060020a0316916338cc4831916004828101926020929190829003018187876161da5a03f11561000257505060408051805160e260020a630bbceb33028252620249f06024830152600482018390526003604483015260ea60020a621554930260648301529151600160a060020a03929092169250632ef3accc916084828101926020929190829003018187876161da5a03f1156100025750506040515160055481019350915061028d9050565b005b565b60408051600160a060020a039590951685526020850193909352838301919091526060830152519081900360800190f35b60408051918252519081900360200190f35b60408051998a5260208a0198909852888801969096526060880194909452608087019290925260a086015260c085015260e084015261010083015251908190036101200190f35b600060009054906101000a9004600160a060020a0316600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e260020a630bbceb33028252620249f06024830152600482018390526003604483015260ea60020a621554930260648301529151600160a060020a03929092169250632ef3accc91608480830192602092919082900301816000876161da5a03f1156100025750506040515193505034839010156107c257610002565b82340391506127106107d2610222565b600460005054020460026000505460026000505460036000505461271003038402041115801561080457506005548210155b1561095a576040805180820182526003815260ea60020a62155493026020828101919091528251608081018452604381527f6a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e818301527f2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174818501527f612e30000000000000000000000000000000000000000000000000000000000060608201528351610160810190945261012c80855261095f94919261175690830139620249f0600060006000600060009054906101000a9004600160a060020a0316600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151915050600160a060020a03811682141561118c5761113460005b600060006115ef731d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed5b3b90565b610002565b6040805160808101825233815260208181018681526000838501818152606085018a8152878352600e90945293519490208054600160a060020a031916909417845551600184810191909155915160028401555160039290920191909155600f8054918201808255929350918281838015829011610a0057818360005260206000209182019101610a0091905b8082111561028d57600081556001016109ec565b5050506000928352506020909120018190555b505050565b600160a060020a031633600160a060020a0316141515610a3757610002565b6000878152600e6020526040812060018101549095501115610c5257600d5460a060020a900460ff166000148015610aa15750612710610a75610222565b600460005054020460026000505460026000505460036000505461271003038660010160005054020411155b15610b4957610b968660006114e28260006040805160208101909152600090819052828180805b8351811015610b3e57603060f860020a02848281518110156100025790602001015160f860020a900460f860020a0210158015610b295750603960f860020a02848281518110156100025790602001015160f860020a900460f860020a0211155b156116cb578115611722578560001415611719575b509095945050505050565b60018401548454610c5291600160a060020a0391909116905b604051600160a060020a038316906161a89083906000818181858888f193505050501515610d005760138054820190555050565b92506001831080610ba8575061271083115b15610bc75783546001850154610c5291600160a060020a031690610b62565b6000878152600e6020526040902060029081018490555460001984011015610c5b57506002546003546001850154855461271092909203029190910490610c7190600160a060020a031682610b62565b60018401546000190191505b601380546007546127109085020590810190915560118054918403909101905560018401546010805490910190555b50505050505050565b8354610c1790600160a060020a03166001610b62565b60018401548190039150610c23565b33600160a060020a03166000908152600b60205260408120541115610ca757610cc5610cab565b610d045b6011546012546000918291829114610a13576114e9610222565b33600160a060020a03166000908152600b6020908152604080832054835260099091529020600101805434908101909155600c805490910190555b5050565b600a5460065460009350901015610d6557600a80546001019081905591505b600082111561095a576000828152600960205260408120600101541115610deb576040600020805460019190910154610dc591600160a060020a031690610e7f565b5060015b600a548111610d23576000818152600960205260409020600101543490108015610db457508160001480610db457506040600081812060019081015485835292822001549083905290105b15610dbd579050805b600101610d69565b600082815260096020908152604080832054600160a060020a03168352600b9091528120555b600082815260096020526040812060010154148015610e2357506040600081812054600160a060020a03168152600b60205290812054145b1561095a5760008281526009602090815260408083208054600160a060020a03191633908117825534600192909201829055600c8054909201909155600160a060020a03168352600b9091529020829055610d00565b610ea833825b600160a060020a0382166000908152600b602052604081205481901115610a1357611578610cab565b50565b61066333610eb83361055a565b610e7f565b5060005b919050565b600160a060020a0384166000908152600b60209081526040808320548352600990915290206001015402049050610ec1565b5060015b600a548111610f38578160001480610f5b5750600082815260096020526040902054610f6c90600160a060020a031661055a565b92505b505090565b600082815260096020526040902054610f3090600160a060020a031661055a565b105b15610f64579050805b600101610efc565b600082815260096020526040902054610f5990600160a060020a031661055a565b601154600254600354600454600554601054939492939192909190610fb0610457565b600f60005080549050985098509850985098509850985098509850909192939495969798565b600d805474ff0000000000000000000000000000000000000000191660a060020a179055565b600d805474ff000000000000000000000000000000000000000019169055565b5060015b600a54811161104e5760008181526009602052604090205461107e90600160a060020a0316610eb88161055a565b8115610d0057604051600d54600160a060020a03908116916000913016319082818181858883f150505050505050565b600101611020565b82156110bb57506000905060015b600a5481116110e55760008181526009602052604090206001015490910190600101611094565b601354604051600d54600160a060020a03169160009182818181858883f150505060135550505050565b816000148015611101575060135430600160a060020a03163114155b1561112f57604051600d54600160a060020a03908116916000913016319082818181858883f1505050601355505b610a13565b50600060009054906101000a9004600160a060020a0316600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519150505b60018054600160a060020a0319168217908190556040805160e260020a630bbceb330281526024810187905260048181019283528a5160448301528a51600160a060020a039490941693632ef3accc938c938a939192839260649290920191602087810192918291859183918691600091601f850104600f02600301f150905090810190601f1680156112335780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050604051519250503a8402670de0b6b3a76400000182111561127c5750600091505b50949350505050565b600160009054906101000a9004600160a060020a0316600160a060020a03166385dee34c8360008a8a8a8a6040518760e060020a028152600401808681526020018060200180602001806020018581526020018481038452888181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156113275780820380516001836020036101000a031916815260200191505b508481038352878181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156113805780820380516001836020036101000a031916815260200191505b508481038252868181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156113d95780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038185886185025a03f11561000257505060405151945061127392505050565b50600060009054906101000a9004600160a060020a0316600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051519150505b60018054600160a060020a031916821790819055604080517fc281d19e0000000000000000000000000000000000000000000000000000000081529051600160a060020a03929092169163c281d19e9160048181019260209290919082900301816000876161da5a03f115610002575050604051519250610524915050565b9050610ec1565b9150600190505b600a54811161151a5760008181526009602052604090205461155990600160a060020a031661055a565b600c8390558282148015906115325750600a54600090115b1561154e5760138054848403908101909155600c805490910190555b601154601255505050565b60008281526009602052604090206001908101829055930192016114f0565b6115818361055a565b821115611594576115918361055a565b91505b50600160a060020a0382166000908152600b602090815260408083205483526009909152902060010180548290039055600c8054829003905560085460138054612710928402929092049182019055610a1383828403610b62565b1115611623575060008054600160a060020a031916731d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed1790556001610ec1565b6000611642739efbea6358bed926b293d2ce63a730d6d98d43dd610956565b1115611678575060008054739efbea6358bed926b293d2ce63a730d6d98d43dd600160a060020a03199091161790556001610ec1565b60006116977320e12a1f859b3feae5fb2a0a32c18f5a65555bbf610956565b1115610ebd575060008054600160a060020a0319167320e12a1f859b3feae5fb2a0a32c18f5a65555bbf1790556001610ec1565b8381815181101561000257016020015160f860020a90819004027f2e00000000000000000000000000000000000000000000000000000000000000141561171157600191505b600101610ac8565b60001995909501945b600a83029250825060308482815181101561000257016020015160f860020a90819004810204909301602f19019250611711564244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000001d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000088e1315687aec48a72786c6b3b3f075208b62713", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000009c4", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000000000000000000000000000000000000000000000000000be", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000064", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000000000000000000000000000002c68af0bb140000", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000006ad2ff8ba84afdcdc", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x000000000000000000000000a1b5f95be71ffa2f86adefcaa0028c46fe825161", - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000022", - "0x0000000000000000000000000000000000000000000000000000000000000011": "0xffffffffffffffffffffffffffffffffffffffffffffffffd14ae0a37b4cc1d4", - "0x0000000000000000000000000000000000000000000000000000000000000012": "0xffffffffffffffffffffffffffffffffffffffffffffffffd5ab72be30cb5f50", - "0x0000000000000000000000000000000000000000000000000000000000000013": "0xffffffffffffffffd5bbd8ce9d1eb44232ca20eb5b4319ac5e1982d2c94bc3cb", - "0x8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac824": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xe950f1be9a49788ef79ea4e854ed56155a7f60661724f41e3af5f799203a1eb9": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xe950f1be9a49788ef79ea4e854ed56155a7f60661724f41e3af5f799203a1eba": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xe950f1be9a49788ef79ea4e854ed56155a7f60661724f41e3af5f799203a1ebb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xe950f1be9a49788ef79ea4e854ed56155a7f60661724f41e3af5f799203a1ebc": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x61c808d82a3ac53231750dadc13c777b59310bd9": { - "balance": "0x12f621ea72fef44f848", - "nonce": "51830" - }, - "0x6412becf35cc7e2a9e7e47966e443f295e1e4f4a": { - "balance": "0xfb5dbfc0d448e70", - "nonce": "6" - }, - "0x88e1315687aec48a72786c6b3b3f075208b62713": { - "balance": "0x24b9f2c5dc266dc6", - "code": "0x606060405236156101535760e060020a60003504630f825673811461018f57806323dc42e7146102135780632ef3accc146102ad578063453629781461033b578063480a434d146103d5578063524f3889146103de5780635c242c591461043f57806360f66701146104de57806362b3b8331461056757806368742da6146105eb578063688dcfd71461062b578063757004371461065857806377228659146106f25780637d242ae5146107cd5780637e1c42051461085357806381ade3071461033b57806385dee34c14610932578063a2ec191a14610a0c578063adf59f9914610213578063ae81584314610658578063b5bfdd7314610a64578063bf1fe42014610af2578063c281d19e14610b32578063c51be90f14610b44578063ca6ad1e414610bdd578063d959701614610bff578063db37e42f14610cb6578063de4b326214610d6d578063e839e65e14610daf575b61065660025433600160a060020a039081169116148015906101855750600154600160a060020a039081163390911614155b15610e8a57610002565b6106566004808035906020019082018035906020019191908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650505050505050600254600160a060020a0390811633909116148015906102095750600154600160a060020a039081163390911614155b15610ebb57610002565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760649791965060249190910194509092508291508401838280828437509496505050505050506000610f2084848462030d406104cb565b610e8c6004808035906020019082018035906020019191908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050933593505050506000610f288383335b6000600062030d40841115801561032d5750600160a060020a03831681526020819052604081205481145b1561184e5760009150611846565b610e8c6004808035906020019082018035906020019191908080601f01602080910402602001604051908101604052809392919081815260200183838082843750506040805160208835808b0135601f81018390048302840183019094528383529799986044989297509190910194509092508291508401838280828437509496505050505050506000610f286000848462030d406104cb565b610e8c60085481565b610e8c6004808035906020019082018035906020019191908080601f016020809104026020016040519081016040528093929190818152602001838380828437509496505050505050506000610f2f82336000610f288362030d4084610302565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050505b600083826000600061113d848433610302565b6106566004808035906020019082018035906020019191908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050505050505080604051808280519060200190808383829060006004602084601f0104600f02600301f150905001915050604051809103902060046000508190555050565b6106566004808035906020019082018035906020019191908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650505050505050600254600160a060020a0390811633909116148015906105e15750600154600160a060020a039081163390911614155b1561119757610002565b610656600435600254600160a060020a0390811633909116148015906106215750600154600160a060020a039081163390911614155b156111f957610002565b600160a060020a0333166000908152600660205260409020805460ff191660f860020a600435041790555b005b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050505b6000610f1d858585856104cb565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760849791965060249190910194509092508291508401838280828437509496505050505050506000610f1d8585858562030d4061091f565b60408051602060248035600481810135601f81018590048502860185019096528585526106569581359591946044949293909201918190840183828082843750949650505050505050600254600090600160a060020a0390811633909116148015906108495750600154600160a060020a039081163390911614155b1561121f57610002565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505050505b6000848260006000611516848433610302565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760849791965060249190910194509092508291508401838280828437509496505093359350505050600061156b868686868661091f565b6106566004808035906020019082018035906020019191908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650509335935050505061157282600083610ab5565b6106566004808035906020019082018035906020019191908080601f016020809104026020016040519081016040528093929190818152602001838380828437509496505093359350506044359150505b600254600090600160a060020a039081163390911614801590610ae85750600154600160a060020a039081163390911614155b1561157657610002565b610656600435600254600160a060020a039081163390911614801590610b285750600154600160a060020a039081163390911614155b1561162f57610002565b610e9e600154600160a060020a031681565b60408051602060248035600481810135601f8101859004850286018501909652858552610e8c9581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050506000610f1d858585856106e4565b600160a060020a03331660009081526007602052604090206004359055610656565b604080516004803580820135602081810285810182019096528185526106569593946024949093850192918291908501908490808284375050604080518735808a013560208181028085018201909552818452989a99604499939850919091019550935083925085019084908082843750949650505050505050600254600090600160a060020a039081163390911614801590610cac5750600154600160a060020a039081163390911614155b1561163457610002565b604080516004803580820135602081810285810182019096528185526106569593946024949093850192918291908501908490808284375050604080518735808a013560208181028085018201909552818452989a99604499939850919091019550935083925085019084908082843750949650505050505050600254600090600160a060020a039081163390911614801590610d635750600154600160a060020a039081163390911614155b1561168f57610002565b61065660043560025460009033600160a060020a03908116911614801590610da55750600154600160a060020a039081163390911614155b1561170557610002565b610e8c6004808035906020019082018035906020019191908080601f01602080910402602001604051908101604052809392919081815260200183838082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760649791965060249190910194509092508291508401838280828437509496505050505050506000610f20600085858562030d4061091f565b565b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b60006003600050600083604051808280519060200190808383829060006004602084601f0104600f02600301f1509050019150506040518091039020815260200190815260200160002060006101000a81548160ff0219169083021790555050565b90505b949350505050565b9392505050565b92915050565b6000600050600033600160a060020a031681526020019081526020016000206000505433600160a060020a031630600160a060020a03160101604051808281526020019150506040518091039020945084506000600050600033600160a060020a031681526020019081526020016000206000818150548092919060010191905055507fb76d0edd90c6a07aa3ff7a222d7f5933e29c6acc660c059c97837f05c4ca1a8433868b8b8b8b6006600050600033600160a060020a0316815260200190815260200160002060009054906101000a900460f860020a026007600050600033600160a060020a03168152602001908152602001600020600050546040518089600160a060020a0316815260200188815260200187815260200180602001806020018681526020018581526020018481526020018381038352888181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156110c35780820380516001836020036101000a031916815260200191505b508381038252878181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561111c5780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390a150505050949350505050565b91503482901061119257813403905060008111156111765760405133600160a060020a031690600090839082818181858883f150505050505b42624f1a000189118061118857504586115b15610f3557610002565b610002565b60016003600050600083604051808280519060200190808383829060006004602084601f0104600f02600301f1509050019150506040518091039020815260200190815260200160002060006101000a81548160ff0219169083021790555050565b604051600160a060020a03828116916000913016319082818181858883f1505050505050565b50600882905560005b600b548110156112a757600b8054600a91600091849081101561000257508054600080516020611883833981519152850154835260209390935260408220548602926009929190859081101561000257908252600080516020611883833981519152018150548152602081019190915260400160002055600101611228565b505050565b6000600050600033600160a060020a031681526020019081526020016000206000505433600160a060020a031630600160a060020a03160101604051808281526020019150506040518091039020945084506000600050600033600160a060020a031681526020019081526020016000206000818150548092919060010191905055507faf30e4d66b2f1f23e63ef4591058a897f67e6867233e33ca3508b982dcc4129b33868c8c8c8c8c6006600050600033600160a060020a0316815260200190815260200160002060009054906101000a900460f860020a026007600050600033600160a060020a0316815260200190815260200160002060005054604051808a600160a060020a0316815260200189815260200188815260200180602001806020018060200187815260200186815260200185815260200184810384528a8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561143f5780820380516001836020036101000a031916815260200191505b508481038352898181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156114985780820380516001836020036101000a031916815260200191505b508481038252888181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156114f15780820380516001836020036101000a031916815260200191505b509c5050505050505050505050505060405180910390a1505050505b95945050505050565b915034829010611192578134039050600081111561154f5760405133600160a060020a031690600090839082818181858883f150505050505b42624f1a00018a118061156157504586115b156112ac57610002565b905061150d565b5050565b8383604051808380519060200190808383829060006004602084601f0104600f02600301f150905001828152600101925050506040518091039020905080600b600050600b600050805480919060010190908154818355818115116115fe578183600052602060002091820191016115fe91905b8082111561162b57600081556001016115ea565b5050508154811015610002576000918252602080832090910192909255918252600a905260409020555050565b5090565b600555565b5060005b81518110156112a7578281815181101561000257906020019060200201516007600050600084848151811015610002576020908102909101810151600160a060020a03168252919091526040902055600101611638565b5060005b81518110156112a75782818151811015610002579060200190602002015160f860020a026006600050600084848151811015610002576020908102909101810151600160a060020a031682529190915260409020805460f860020a90920460ff19909216919091179055600101611693565b50600881905560005b600b5481101561157257600b8054600a91600091849081101561000257600080516020611883833981519152015482526020929092526040812054825490850292600992918590811015610002576000805160206118838339815191520154825250602091909152604090205560010161170e565b60096000506000866006600050600087600160a060020a0316815260200190815260200160002060009054906101000a900460f860020a02604051808380519060200190808383829060006004602084601f0104600f02600301f150905001828152600101925050506040518091039020815260200190815260200160002060005054915081506007600050600084600160a060020a03168152602001908152602001600020600050549050806000141561183d57506005545b83810291909101905b509392505050565b600454600014801590611875575060045460009081526003602052604090205460ff166001145b156117835760009150611846560175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000004": "0xbb130806898f085471286ecb4f3966fcbe090ba29e4f9d194ee9e9062f6b61ae", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x00000000000000000000000000000000000000000000000000000004a817c800", - "0x797fdd0f6c82412493cfa2aacdc9999c10e5d0c9aa3f05a8a289b1b3918c6db8": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8d90a37db271d62339ebfe84641d1ebdaf56fd5d50861d795eacb410dbb57630": "0x000000000000000000000000000000000000000000000000000cf4e712e8d654", - "0x9864048b6d6c99ecd7fcaecf663fbe1036a6e1fc00cec0a3eb25684dd08184c2": "0x0000000000000000000000000000000000000000000000000000000000000011", - "0xca9ea8077ddc97a21c029df4b19819e51903e11d4bfc7564a622a192cefd6356": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xf34e44a0672ef76b852374cc47d9772eb4e5e41fa79fba61dcfc9cf7d50418d5": "0x0000000000000000000000000000000000000000000000000000000000000022" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "1725116", - "difficulty": "45966589844033", - "timestamp": "1466232988", - "gasLimit": "4716972", - "miner": "0x61c808d82a3ac53231750dadc13c777b59310bd9" - }, - "input": "0xf86d068504e3b2920083030d409450739060a2c32dc076e507ae1a893aab28ecfe68880429d069189e0000801ca04e403b46022c2098e41d3a0e561881ac368cd330637239da85759c1b4f44ab24a072a88235d98959283c00af411bd663b0da8703e05a94d3673aca37d0a39b7e07", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0x6412becf35cc7e2a9e7e47966e443f295e1e4f4a", - "gas": "0x30d40", - "gasUsed": "0x249eb", - "to": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "input": "0x", - "calls": [ - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x257af", - "gasUsed": "0xbc", - "to": "0x1d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed", - "input": "0x38cc4831", - "output": "0x00000000000000000000000088e1315687aec48a72786c6b3b3f075208b62713", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x255a1", - "gasUsed": "0x73a", - "to": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "input": "0x2ef3accc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000355524c0000000000000000000000000000000000000000000000000000000000", - "output": "0x00000000000000000000000000000000000000000000000000179d63013c5654", - "calls": [ - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x24680", - "gasUsed": "0xbc", - "to": "0x1d3b2638a7cc9f2cb3d298a3da7a90b67e5506ed", - "input": "0x38cc4831", - "output": "0x00000000000000000000000088e1315687aec48a72786c6b3b3f075208b62713", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x22f3b", - "gasUsed": "0x73a", - "to": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "input": "0x2ef3accc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000355524c0000000000000000000000000000000000000000000000000000000000", - "output": "0x00000000000000000000000000000000000000000000000000179d63013c5654", - "calls": [ - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x30", - "gasUsed": "0x18", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x6a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e30", - "output": "0x6a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e30", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x99", - "gasUsed": "0x2d", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d", - "output": "0x4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "gas": "0x2083e", - "gasUsed": "0x4417", - "to": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "input": "0x85dee34c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000249f0000000000000000000000000000000000000000000000000000000000000000355524c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000436a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d0000000000000000000000000000000000000000", - "output": "0xd1b13c1538a940417bf0e73b2498634436753c854c7fb971224d971bd2ae3e88", - "calls": [ - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x12", - "gasUsed": "0x12", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x55524c", - "output": "0x55524c", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x30", - "gasUsed": "0x18", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x6a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e30", - "output": "0x6a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e30", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "gas": "0x99", - "gasUsed": "0x2d", - "to": "0x0000000000000000000000000000000000000004", - "input": "0x4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d", - "output": "0x4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x88e1315687aec48a72786c6b3b3f075208b62713", - "topics": [ - "0xaf30e4d66b2f1f23e63ef4591058a897f67e6867233e33ca3508b982dcc4129b" - ], - "data": "0x00000000000000000000000050739060a2c32dc076e507ae1a893aab28ecfe68d1b13c1538a940417bf0e73b2498634436753c854c7fb971224d971bd2ae3e8800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000249f011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000355524c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000436a736f6e2868747470733a2f2f6170692e72616e646f6d2e6f72672f6a736f6e2d7270632f312f696e766f6b65292e726573756c742e72616e646f6d2e646174612e300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012c4244584a68725670424a35336f3243786c4a526c51745a4a4b5a714c5974354951652b37335944533448744e6a5335486f64624942337476666f773755717579416b303835566b4c6e4c3945704b67777157517a375a4c64477673516c526432734b78496f6c4e673944626e6650737047714c684c62625953566e4e38437776736a7041586353536f33632b34634e774339307946346f4e69626b764433797461706f5a37676f5453796f5559546677536a6e773374692b484a5648374e332b633069774f43715a6a4464734751556358336d33532f494857624f4f5151356f734f344c626a33476730783155644e7466557a5943465937396e7a596757495145464375524249306e364e42764251573732372b4f73445259304a2f392f676a74387563696248576963303d0000000000000000000000000000000000000000", - "position": "0x4" - } - ], - "value": "0x179d63013c5654", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0x50739060a2c32dc076e507ae1a893aab28ecfe68", - "topics": [], - "data": "0x62616e6b726f6c6c5f6d69736d61746368", - "position": "0x2" - } - ], - "value": "0x429d069189e0000", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json deleted file mode 100644 index 64941dd4d..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "genesis": { - "difficulty": "8430028481555", - "extraData": "0xd783010302844765746887676f312e352e31856c696e7578", - "gasLimit": "3141592", - "hash": "0xde66937783697293f2e529d2034887c531535d78afa8c9051511ae12ba48fbea", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226", - "mixHash": "0xba28a43bfbca4a2effbb76bb70d03482a8a0c92e2883ff36cbac3d7c6dbb7df5", - "nonce": "0xa3827ec0a82fe823", - "number": "765824", - "stateRoot": "0x8d96cb027a29f8ca0ccd6d31f9ea0656136ec8030ecda70bb9231849ed6f41a2", - "timestamp": "1451389443", - "totalDifficulty": "4838314986494741271", - "alloc": { - "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb": { - "balance": "0x14203bee2ea6fbe8c", - "nonce": "34" - }, - "0xe2fe6b13287f28e193333fdfe7fedf2f6df6124a": { - "balance": "0x2717a9c870a286f4350" - }, - "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd": { - "balance": "0x0", - "code": "0x606060405260e060020a600035046306fdde038114610047578063313ce567146100a457806370a08231146100b057806395d89b41146100c8578063a9059cbb14610123575b005b61015260008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156101f55780601f106101ca576101008083540402835291602001916101f5565b6101c060025460ff1681565b6101c060043560036020526000908152604090205481565b610152600180546020601f6002600019610100858716150201909316929092049182018190040260809081016040526060828152929190828280156101f55780601f106101ca576101008083540402835291602001916101f5565b610045600435602435600160a060020a033316600090815260036020526040902054819010156101fd57610002565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156101b25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116101d857829003601f168201915b505050505081565b600160a060020a03821660009081526040902054808201101561021f57610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505056", - "storage": { - "0x1dae8253445d3a5edbe8200da9fc39bc4f11db9362181dc1b640d08c3c2fb4d6": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba52aac7f255d80a49abcf003d6af4752aba5a9531cae94fde7ac8d72191d67": "0x000000000000000000000000000000000000000000000000000000000178e460" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "765825", - "difficulty": "8425912256743", - "timestamp": "1451389488", - "gasLimit": "3141592", - "miner": "0xe2fe6b13287f28e193333fdfe7fedf2f6df6124a" - }, - "input": "0xf8aa22850ba43b740083024d4594f4eced2f682ce333f96f2d8966c613ded8fc95dd80b844a9059cbb000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb00000000000000000000000000000000000000000000000000000000009896801ca067da548a2e0f381a957b9b51f086073375d6bfc7312cbc9540b3647ccab7db11a042c6e5b34bc7ba821e9c25b166fa13d82ad4b0d044d16174d5587d4f04ecfcd1", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb", - "gas": "0x24d45", - "gasUsed": "0xc6a5", - "to": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd", - "input": "0xa9059cbb000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb0000000000000000000000000000000000000000000000000000000000989680", - "logs": [ - { - "address": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x000000000000000000000000d1220a0cf47c7b9be7a2e6ba89f429762e7b9adb", - "0x000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000989680", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json deleted file mode 100644 index 30346d07f..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_failed.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "genesis": { - "difficulty": "56311715121637", - "extraData": "0x7777772e62772e636f6d", - "gasLimit": "4712388", - "hash": "0x20d3b8daa046f2f10564d84ccbe6d0a8842d8d52bc6d623e23c38050a8f73776", - "miner": "0xbcdfc35b86bedf72f0cda046a3c16829a2ef41d1", - "mixHash": "0x75029f90d7de3f9e3d5eac4a25019f9ac5d0041641d1ef17e7759e45699d4224", - "nonce": "0x54ff3b34fa1d9c97", - "number": "1968179", - "stateRoot": "0x6420003b1779cca3bcdab698c239bbc63623c0a7e4deeedbdb8190b9e7fd7520", - "timestamp": "1469713675", - "totalDifficulty": "42284028928878034360", - "alloc": { - "0x10abb5efecdc09581f8b7cb95791fe2936790b4e": { - "balance": "0x81f158e2814b4ab624c", - "code": "0x6060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638b15a605146106c95780638d7af473146106d257806396d7f3f5146106e1578063a1da2fb9146106ea578063a3912ec814610704578063a9059cbb1461070f578063b7bc2c841461073f578063baac53001461074b578063be7c29c1146107b1578063c9d27afe14610817578063cc9ae3f61461082d578063cdef91d014610841578063dbde198814610859578063dd62ed3e1461087e578063e33734fd146108b2578063e5962195146108c6578063e66f53b7146108de578063eceb2945146108f0578063f8c80d261461094f575b610966600f546000906234bc000142108015610239575060125433600160a060020a03908116911614155b156109785761098033610752565b6109866004356000805482908110156100025750808052600e8202600080516020612a3683398151915201905060038101546004820154600683015460018401548454600786015460058701546009880154600a890154600d8a0154600160a060020a039586169b509599600201989760ff81811698610100909204811697949691951693168c565b61096660043560243533600160a060020a03908116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b61096660105481565b610a7d600754600160a060020a031681565b610a7d600e54600160a060020a031681565b61096660165481565b6109665b60004262127500600f60005054031115610de557506014610983565b610a7d601254600160a060020a031681565b60408051602060248035600481810135601f810185900485028601850190965285855261096695813595919460449492939092019181908401838280828437509496505050505050506000600060006000600060003411156116a857610002565b6109666004356024356044355b60115460009060ff1680156104315750600f5442115b80156124e957506124e78461044b565b6109666000610980335b600160a060020a0381166000908152600b602052604081205481908114156129cb57610b99565b61096660065481565b6109665b600d5430600160a060020a03163103610983565b610966600f5481565b61096660043560046020526000908152604090205460ff1681565b61096660043560243560006124cb610831565b610a9a6000341115610ba457610002565b604080516020604435600481810135601f8101849004840285018401909552848452610966948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a435915050600060006110c1336105ec565b61096660043560096020526000908152604090205481565b61096660015481565b610a9a60043530600160a060020a031633600160a060020a03161415806105db5750600160a060020a03811660009081526004602052604090205460ff16155b156121cb576121c8565b6109666004355b600160a060020a0381166000908152601460205260409020545b919050565b6109666004356024356000600034111561259957610002565b610966600062e6b680420360026000505410806106505750600354600160a060020a0390811633909116145b80156106645750600254621274ff19420190105b156126145750426002908155600180549091028155610983565b610966600435600a6020526000908152604090205481565b610966600435602435600060006000600060006000341115611ba157610002565b610a7d600854600160a060020a031681565b610966600c5481565b61096660005460001901610983565b61096660025481565b61096660043560006000600060003411156121fc57610002565b6109665b6001610983565b6109666004356024355b60115460009060ff16801561072f5750600f5442115b801561248757506124853361044b565b61096660115460ff1681565b6109666004355b60006000600f600050544210801561076a5750600034115b80156107a457506011546101009004600160a060020a0316600014806107a457506011546101009004600160a060020a0390811633909116145b15610b9f57610a9c61037f565b610a7d600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610606565b61096660043560243560006000610e1b336105ec565b6109665b6000600034111561247c57610002565b61096660043560056020526000908152604090205481565b610966600435602435604435600061252f845b6000600060003411156127ac57610002565b610966600435602435600160a060020a0382811660009081526015602090815260408083209385168352929052205461033f565b610a9a600435600034111561254557610002565b610966600435600b6020526000908152604090205481565b610a7d600354600160a060020a031681565b604080516020606435600481810135601f81018490048402850184019095528484526109669481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561103257610002565b610a7d6011546101009004600160a060020a031681565b60408051918252519081900360200190f35b610980610708565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590610b4c575060115460ff16155b15610b94576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a15b600191505b50919050565b610002565b600f5442118015610bb8575060115460ff16155b15610de357601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040516012549051600160a060020a039190911631109050610cc9576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b33600160a060020a0316600081815260136020526040808220549051909181818185876185025a03f19250505015610de35733600160a060020a03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d6013600050600033600160a060020a03168152602001908152602001600020600050546040518082815260200191505060405180910390a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f60005054031115610e13576201518062127500600f60005054034203046014019050610983565b50601e610983565b60001415610e2857610002565b6000341115610e3657610002565b6000805485908110156100025750600160a060020a03331681527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e600e8602908101602052604090912054600080516020612a3683398151915291909101915060ff1680610eb05750600c810160205260406000205460ff165b80610ebf575060038101544210155b15610ec957610002565b8215610f0f5733600160a060020a03166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff19166001179055610f4b565b33600160a060020a0316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b33600160a060020a03166000908152600b60205260408120541415610f77576040600020849055610feb565b33600160a060020a03166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e909102015460038201541115610feb5733600160a060020a03166000908152600b602052604090208490555b60408051848152905133600160a060020a03169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6000805487908110156100025750808052600e8702600080516020612a3683398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156110ce57610002565b82801561111857508660001415806110e857508451600014155b806111005750600354600160a060020a038981169116145b8061110b5750600034115b80611118575062093a8084105b1561112257610002565b8215801561114257506111348861115c565b158061114257506212750084105b156111fe57610002565b83546118e590600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff16806111f15750601254600160a060020a039081169083161480156111f15750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156129a157506001610606565b6249d40084111561120e57610002565b60115460ff1615806112215750600f5442105b806112365750600c5434108015611236575082155b1561124057610002565b42844201101561124f57610002565b30600160a060020a031633600160a060020a0316141561126e57610002565b60008054600181018083559091908280158290116112a557600e0281600e0283600052602060002091820191016112a5919061136a565b505060008054929450918491508110156100025750808052600e8302600080516020612a368339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b019083901061146257805160ff19168380011785555b5061149292915061144a565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561145e578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f81901061143057505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220611344929091028101905b8082111561145e57600080825560018201818155600283019190915560039091018054600160a060020a03191690556113fc565b601f0160209004906000526020600020908101906113ae91905b8082111561145e576000815560010161144a565b5090565b82800160010185558215611338579182015b82811115611338578251826000505591602001919060010190611474565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561157857600881018054600181018083559091908280158290116115735760040281600402836000526020600020918201910161157391906113fc565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156116485780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a36833981519152019050600781015490945060ff166116e757620d2f006116ec565b622398805b600485015490935060ff16801561170857506003840154830142115b15611716576117b887611890565b600384015442108061172d5750600484015460ff16155b806117ae57508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b1561114c57610002565b61169e565b60048401805461ff001916610100179055835460019550600160a060020a03908116309091161480159061180157508354600754600160a060020a03908116911614155b801561181d57506008548454600160a060020a03908116911614155b801561183957508354601254600160a060020a03908116911614155b801561185557506003548454600160a060020a03908116911614155b1561188b5760018401805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190555b611663875b6000600060005082815481101561000257908052600e02600080516020612a36833981519152018150600481015490915060ff16156118d757600d80546006830154900390555b600401805460ff1916905550565b15156118f45761190087611890565b6001915061193161047f565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050505061169e565b6001850154111561194157600091505b50600a8301546009840154865191019060049010801590611986575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b80156119b6575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b80156119e6575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b8015611a16575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b8015611a45575030600160a060020a0316600090815260056020526040902054611a4290611a5d61047f565b81105b15611a4f57600091505b6001840154611a8090611a5f565b015b30600160a060020a03166000908152600560205260408120546129a961047f565b8110611ad457604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050501515611abc57610002565b4260025560165460059004811115611ad45760056001555b6001840154611ae290611a5f565b8110158015611af85750600a8401546009850154115b8015611b015750815b1561188b578360000160009054906101000a9004600160a060020a0316600160a060020a0316846001016000505487604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611b7d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f19250505015156117bd57610002565b611baa336105ec565b60001415611bb757610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a36833981519152919091019450421080611c1957506003840154622398800142115b80611c3257508354600160a060020a0390811690871614155b80611c425750600784015460ff16155b80611c68575033600160a060020a03166000908152600b8501602052604090205460ff16155b80611c9c575033600160a060020a03166000908152600b60205260409020548714801590611c9c5750604060009081205414155b15611ca657610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611e1257611efc86604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506106069050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090505433600160a060020a031660009081526014602052604081205460088801805493909102939093049550908110156100025790815260208120905060030154604080517fbaac530000000000000000000000000000000000000000000000000000000000815233600160a060020a0390811660048301529151929091169163baac53009186916024808301926020929190829003018185886185025a03f11561000257505060405151600014159150611f78905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611f5757610002565b600d5430600160a060020a0316311015611f7057610002565b611d9561047f565b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090506002015433600160a060020a0390811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a0390811682526020828101939093526040918201600090812080549095019094553016835260059091529020548290101561205357610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a039081168352929052604080822080549094019093553090911681522054819010156120c657610002565b30600160a060020a0390811660009081526009602090815260408083208054869003905533909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a36121383361086c565b5033600160a060020a03166000908152601460209081526040808320805460168054919091039055839055600a9091528120556001945061169e565b30600160a060020a0390811660008181526005602090815260408083208054958716808552828520805490970190965584845283905560099091528082208054948352908220805490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f192505050151561217457610002565b33600160a060020a03818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935197995091969195929092169363d2cc718f936004848101949193929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204101561229d57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a0316815260200190815260200160002060005054020403905083156123ec57600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061245457610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061245457610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b6109803361086c565b155b80156124a257506124a23384845b6000600061293a856105ec565b80156124be57506124be83836000600034111561261c57610002565b15610b9f5750600161033f565b15156124d657610002565b6124e08383610719565b905061033f565b155b80156124fb57506124fb848484612495565b80156125185750612518848484600060003411156126c157610002565b15610b9f57506001612528565b90505b9392505050565b151561253a57610002565b61252584848461041b565b30600160a060020a031633600160a060020a031614158061258a575030600160a060020a031660009081526005602052604090205460649061258561047f565b010481115b1561259457610002565b600c55565b600354600160a060020a0390811633909116146125b557610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a250600161033f565b506000610983565b33600160a060020a03166000908152601460205260409020548290108015906126455750600082115b156126b957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161033f565b50600061033f565b600160a060020a03841660009081526014602052604090205482901080159061270a5750601560209081526040600081812033600160a060020a03168252909252902054829010155b80156127165750600082115b156127a457600160a060020a03838116600081815260146020908152604080832080548801905588851680845281842080548990039055601583528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001612528565b506000612528565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061281a866105ec565b0204101561282757610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f115610002575050604051519050612895866105ec565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061291357610002565b600160a060020a0383166000908152600a6020526040902080548201905560019150610b99565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561296857610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610606565b0160030260166000505483020460016000505460166000505404019050610606565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a368339815191520190506003810154909150421115610b9457600160a060020a0383166000908152600b602052604081208190559150610b9956290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", - "nonce": "3", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000057bda071", - "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c18941301", - "0x0000000000000000000000000000000000000000000000000000000000000012": "0x000000000000000000000000fde8d5f77ef48bb7bf5766c7404691b9ee1dfca7", - "0x0000000000000000000000000000000000000000000000000000000000000016": "0x00000000000000000000000000000000000000000000081f158e2814b4ab624c", - "0x7ffc832d0c7f56b16d03bf3ff14bc4dd6a6cb1ec75841f7397362f4a9be4d392": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xaccfa2662c944e8eae80b7720d9d232eb6809c18f6c8da65189acbb38069d869": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x630a0cd35d5bd57e61410fda76fea850225cda18": { - "balance": "0x0", - "code": "0x6060604052361561006c5760e060020a60003504630121b93f81146100e15780636637b882146101615780636dbf2fa0146101935780638da5cb5b1461026a578063a6f9dae11461027c578063beabacc8146102ae578063d979f5aa14610322578063e1fa763814610354575b61050b600060006000600460005054111561051d576004805460001901905560015460035460055460e260020a6320998771026060908152606492909252600160a060020a03908116608452909116906382661dc49060a49060209060448187876161da5a03f11561000257506105c3915050565b6105cb60043560005433600160a060020a039081169116141561015e57600180547fc9d27afe0000000000000000000000000000000000000000000000000000000060609081526064849052608492909252600160a060020a03169063c9d27afe9060a4906020906044816000876161da5a03f115610002575050505b50565b6105cb60043560005433600160a060020a039081169116141561015e5760018054600160a060020a0319168217905550565b60806020604435600481810135601f8101849004909302840160405260608381526105cb9482359460248035956064949391019190819083828082843750949650505050505050600054600160a060020a039081163390911614156102655782600160a060020a03168282604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561024b5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f1505050505b505050565b6105cd600054600160a060020a031681565b6105cb60043560005433600160a060020a039081169116141561015e5760008054600160a060020a0319168217905550565b6105cb6004356024356044356000805433600160a060020a039081169116141561031c5760e060020a63a9059cbb026060908152600160a060020a03848116606452608484905285929083169163a9059cbb9160a4916020916044908290876161da5a03f115610002575050505b50505050565b6105cb60043560005433600160a060020a039081169116141561015e5760028054600160a060020a0319168217905550565b6105cb60043560243560005433600160a060020a03908116911614156105075760015460e060020a6370a0823102606090815230600160a060020a0390811660645291909116906370a08231906084906020906024816000876161da5a03f1156100025750506040805180516006556002546001547f1a695230000000000000000000000000000000000000000000000000000000008352600160a060020a039081166004840152925192169250631a695230916024828101926000929190829003018183876161da5a03f1156100025750505060048181556003839055600154604080517f013cf08b00000000000000000000000000000000000000000000000000000000815292830185905251600160a060020a03919091169163013cf08b91602482810192602092919082900301816000876161da5a03f11561000257505060408051805160058054600160a060020a0319169091179081905560015460035460e260020a63209987710284526004840152600160a060020a0391821660248401529251921692506382661dc491604482810192602092919082900301816000876161da5a03f115610002575050505b5050565b60408051918252519081900360200190f35b60015460e060020a6370a0823102606090815230600160a060020a0390811660645291909116906370a082319060849060209060248187876161da5a03f11561000257505060408051805160015460025460e060020a63a9059cbb028452600160a060020a039081166004850152602484018390529351919550909216925063a9059cbb916044828101926020929190829003018188876161da5a03f115610002575050505b600191505090565b005b6060908152602090f3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000e6002189a74b43e6868b20c1311bc108e38aac57", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c189413", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000006e073c0e1bd5af550239025dffcfb37175acedd3", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x6e073c0e1bd5af550239025dffcfb37175acedd3": { - "balance": "0x0", - "code": "0x606060405260e060020a60003504631a69523081146100475780636dbf2fa01461006d5780638da5cb5b14610144578063a6f9dae114610156578063beabacc814610196575b005b610045600435600080548190819032600160a060020a0390811691161461022957610002565b60806020604435600481810135601f8101849004909302840160405260608381526100459482359460248035956064949391019190819083828082843750949650505050505050600054600160a060020a0390811633909116141561013f5782600160a060020a03168282604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101255780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f1505050505b505050565b61021f600054600160a060020a031681565b61004560043560005433600160a060020a0390811691161415610193576000805473ffffffffffffffffffffffffffffffffffffffff1916821790555b50565b6100456004356024356044356000805433600160a060020a0390811691161415610343577fa9059cbb000000000000000000000000000000000000000000000000000000006060908152600160a060020a03808516606452608484905285929083169163a9059cbb9160a4916020916044908290876161da5a03f1156100025750505050505050565b6060908152602090f35b7f70a0823100000000000000000000000000000000000000000000000000000000606090815230600160a060020a039081166064528594508416906370a082319060849060209060248187876161da5a03f1156100025750506040805180517f18160ddd00000000000000000000000000000000000000000000000000000000825291519194506318160ddd916004828101926020929190829003018187876161da5a03f11561000257505050604051805190602001509050808211156102ee579050805b82600160a060020a031663a9059cbb33846040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050505b5050505056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000e6002189a74b43e6868b20c1311bc108e38aac57" - } - }, - "0xbb9bc244d798123fde783fcc1c72d3bb8c189413": { - "balance": "0x53d2c8df046dd3db5", - "code": "0x6060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638b15a605146106c95780638d7af473146106d257806396d7f3f5146106e1578063a1da2fb9146106ea578063a3912ec814610704578063a9059cbb1461070f578063b7bc2c841461073f578063baac53001461074b578063be7c29c1146107b1578063c9d27afe14610817578063cc9ae3f61461082d578063cdef91d014610841578063dbde198814610859578063dd62ed3e1461087e578063e33734fd146108b2578063e5962195146108c6578063e66f53b7146108de578063eceb2945146108f0578063f8c80d261461094f575b610966600f546000906234bc000142108015610239575060125433600160a060020a03908116911614155b156109785761098033610752565b6109866004356000805482908110156100025750808052600e8202600080516020612a3683398151915201905060038101546004820154600683015460018401548454600786015460058701546009880154600a890154600d8a0154600160a060020a039586169b509599600201989760ff81811698610100909204811697949691951693168c565b61096660043560243533600160a060020a03908116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b61096660105481565b610a7d600754600160a060020a031681565b610a7d600e54600160a060020a031681565b61096660165481565b6109665b60004262127500600f60005054031115610de557506014610983565b610a7d601254600160a060020a031681565b60408051602060248035600481810135601f810185900485028601850190965285855261096695813595919460449492939092019181908401838280828437509496505050505050506000600060006000600060003411156116a857610002565b6109666004356024356044355b60115460009060ff1680156104315750600f5442115b80156124e957506124e78461044b565b6109666000610980335b600160a060020a0381166000908152600b602052604081205481908114156129cb57610b99565b61096660065481565b6109665b600d5430600160a060020a03163103610983565b610966600f5481565b61096660043560046020526000908152604090205460ff1681565b61096660043560243560006124cb610831565b610a9a6000341115610ba457610002565b604080516020604435600481810135601f8101849004840285018401909552848452610966948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a435915050600060006110c1336105ec565b61096660043560096020526000908152604090205481565b61096660015481565b610a9a60043530600160a060020a031633600160a060020a03161415806105db5750600160a060020a03811660009081526004602052604090205460ff16155b156121cb576121c8565b6109666004355b600160a060020a0381166000908152601460205260409020545b919050565b6109666004356024356000600034111561259957610002565b610966600062e6b680420360026000505410806106505750600354600160a060020a0390811633909116145b80156106645750600254621274ff19420190105b156126145750426002908155600180549091028155610983565b610966600435600a6020526000908152604090205481565b610966600435602435600060006000600060006000341115611ba157610002565b610a7d600854600160a060020a031681565b610966600c5481565b61096660005460001901610983565b61096660025481565b61096660043560006000600060003411156121fc57610002565b6109665b6001610983565b6109666004356024355b60115460009060ff16801561072f5750600f5442115b801561248757506124853361044b565b61096660115460ff1681565b6109666004355b60006000600f600050544210801561076a5750600034115b80156107a457506011546101009004600160a060020a0316600014806107a457506011546101009004600160a060020a0390811633909116145b15610b9f57610a9c61037f565b610a7d600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610606565b61096660043560243560006000610e1b336105ec565b6109665b6000600034111561247c57610002565b61096660043560056020526000908152604090205481565b610966600435602435604435600061252f845b6000600060003411156127ac57610002565b610966600435602435600160a060020a0382811660009081526015602090815260408083209385168352929052205461033f565b610a9a600435600034111561254557610002565b610966600435600b6020526000908152604090205481565b610a7d600354600160a060020a031681565b604080516020606435600481810135601f81018490048402850184019095528484526109669481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561103257610002565b610a7d6011546101009004600160a060020a031681565b60408051918252519081900360200190f35b610980610708565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590610b4c575060115460ff16155b15610b94576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a15b600191505b50919050565b610002565b600f5442118015610bb8575060115460ff16155b15610de357601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040516012549051600160a060020a039190911631109050610cc9576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b33600160a060020a0316600081815260136020526040808220549051909181818185876185025a03f19250505015610de35733600160a060020a03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d6013600050600033600160a060020a03168152602001908152602001600020600050546040518082815260200191505060405180910390a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f60005054031115610e13576201518062127500600f60005054034203046014019050610983565b50601e610983565b60001415610e2857610002565b6000341115610e3657610002565b6000805485908110156100025750600160a060020a03331681527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e600e8602908101602052604090912054600080516020612a3683398151915291909101915060ff1680610eb05750600c810160205260406000205460ff165b80610ebf575060038101544210155b15610ec957610002565b8215610f0f5733600160a060020a03166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff19166001179055610f4b565b33600160a060020a0316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b33600160a060020a03166000908152600b60205260408120541415610f77576040600020849055610feb565b33600160a060020a03166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e909102015460038201541115610feb5733600160a060020a03166000908152600b602052604090208490555b60408051848152905133600160a060020a03169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6000805487908110156100025750808052600e8702600080516020612a3683398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156110ce57610002565b82801561111857508660001415806110e857508451600014155b806111005750600354600160a060020a038981169116145b8061110b5750600034115b80611118575062093a8084105b1561112257610002565b8215801561114257506111348861115c565b158061114257506212750084105b156111fe57610002565b83546118e590600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff16806111f15750601254600160a060020a039081169083161480156111f15750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156129a157506001610606565b6249d40084111561120e57610002565b60115460ff1615806112215750600f5442105b806112365750600c5434108015611236575082155b1561124057610002565b42844201101561124f57610002565b30600160a060020a031633600160a060020a0316141561126e57610002565b60008054600181018083559091908280158290116112a557600e0281600e0283600052602060002091820191016112a5919061136a565b505060008054929450918491508110156100025750808052600e8302600080516020612a368339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b019083901061146257805160ff19168380011785555b5061149292915061144a565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561145e578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f81901061143057505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220611344929091028101905b8082111561145e57600080825560018201818155600283019190915560039091018054600160a060020a03191690556113fc565b601f0160209004906000526020600020908101906113ae91905b8082111561145e576000815560010161144a565b5090565b82800160010185558215611338579182015b82811115611338578251826000505591602001919060010190611474565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561157857600881018054600181018083559091908280158290116115735760040281600402836000526020600020918201910161157391906113fc565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156116485780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a36833981519152019050600781015490945060ff166116e757620d2f006116ec565b622398805b600485015490935060ff16801561170857506003840154830142115b15611716576117b887611890565b600384015442108061172d5750600484015460ff16155b806117ae57508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b1561114c57610002565b61169e565b60048401805461ff001916610100179055835460019550600160a060020a03908116309091161480159061180157508354600754600160a060020a03908116911614155b801561181d57506008548454600160a060020a03908116911614155b801561183957508354601254600160a060020a03908116911614155b801561185557506003548454600160a060020a03908116911614155b1561188b5760018401805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190555b611663875b6000600060005082815481101561000257908052600e02600080516020612a36833981519152018150600481015490915060ff16156118d757600d80546006830154900390555b600401805460ff1916905550565b15156118f45761190087611890565b6001915061193161047f565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050505061169e565b6001850154111561194157600091505b50600a8301546009840154865191019060049010801590611986575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b80156119b6575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b80156119e6575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b8015611a16575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b8015611a45575030600160a060020a0316600090815260056020526040902054611a4290611a5d61047f565b81105b15611a4f57600091505b6001840154611a8090611a5f565b015b30600160a060020a03166000908152600560205260408120546129a961047f565b8110611ad457604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050501515611abc57610002565b4260025560165460059004811115611ad45760056001555b6001840154611ae290611a5f565b8110158015611af85750600a8401546009850154115b8015611b015750815b1561188b578360000160009054906101000a9004600160a060020a0316600160a060020a0316846001016000505487604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611b7d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f19250505015156117bd57610002565b611baa336105ec565b60001415611bb757610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a36833981519152919091019450421080611c1957506003840154622398800142115b80611c3257508354600160a060020a0390811690871614155b80611c425750600784015460ff16155b80611c68575033600160a060020a03166000908152600b8501602052604090205460ff16155b80611c9c575033600160a060020a03166000908152600b60205260409020548714801590611c9c5750604060009081205414155b15611ca657610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611e1257611efc86604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506106069050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090505433600160a060020a031660009081526014602052604081205460088801805493909102939093049550908110156100025790815260208120905060030154604080517fbaac530000000000000000000000000000000000000000000000000000000000815233600160a060020a0390811660048301529151929091169163baac53009186916024808301926020929190829003018185886185025a03f11561000257505060405151600014159150611f78905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611f5757610002565b600d5430600160a060020a0316311015611f7057610002565b611d9561047f565b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090506002015433600160a060020a0390811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a0390811682526020828101939093526040918201600090812080549095019094553016835260059091529020548290101561205357610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a039081168352929052604080822080549094019093553090911681522054819010156120c657610002565b30600160a060020a0390811660009081526009602090815260408083208054869003905533909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a36121383361086c565b5033600160a060020a03166000908152601460209081526040808320805460168054919091039055839055600a9091528120556001945061169e565b30600160a060020a0390811660008181526005602090815260408083208054958716808552828520805490970190965584845283905560099091528082208054948352908220805490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f192505050151561217457610002565b33600160a060020a03818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935197995091969195929092169363d2cc718f936004848101949193929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204101561229d57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a0316815260200190815260200160002060005054020403905083156123ec57600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061245457610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061245457610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b6109803361086c565b155b80156124a257506124a23384845b6000600061293a856105ec565b80156124be57506124be83836000600034111561261c57610002565b15610b9f5750600161033f565b15156124d657610002565b6124e08383610719565b905061033f565b155b80156124fb57506124fb848484612495565b80156125185750612518848484600060003411156126c157610002565b15610b9f57506001612528565b90505b9392505050565b151561253a57610002565b61252584848461041b565b30600160a060020a031633600160a060020a031614158061258a575030600160a060020a031660009081526005602052604090205460649061258561047f565b010481115b1561259457610002565b600c55565b600354600160a060020a0390811633909116146125b557610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a250600161033f565b506000610983565b33600160a060020a03166000908152601460205260409020548290108015906126455750600082115b156126b957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161033f565b50600061033f565b600160a060020a03841660009081526014602052604090205482901080159061270a5750601560209081526040600081812033600160a060020a03168252909252902054829010155b80156127165750600082115b156127a457600160a060020a03838116600081815260146020908152604080832080548801905588851680845281842080548990039055601583528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001612528565b506000612528565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061281a866105ec565b0204101561282757610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f115610002575050604051519050612895866105ec565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061291357610002565b600160a060020a0383166000908152600a6020526040902080548201905560019150610b99565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561296857610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610606565b0160030260166000505483020460016000505460166000505404019050610606565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a368339815191520190506003810154909150421115610b9457600160a060020a0383166000908152600b602052604081208190559150610b9956290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", - "nonce": "3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000120", - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000057495e10", - "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000016": "0x000000000000000000000000000000000000000000098b4d3b425f8c368391b2", - "0x29066f14bd0b438bb3db8771a65febf0be7574be7528f87e7ae11aafc2b2c3ac": "0x000000000000000000000000000000000000000000000025d57ab057892050fc", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f443": "0x000000000000000000000000b3b10eff47b9c0b3e5579bf1c25872111667e650", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f444": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f445": "0x0000000000000000000000000000000000000000000000000000000000000093", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f446": "0x00000000000000000000000000000000000000000000000000000000579a07ea", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f447": "0x0000000000000000000000000000000000000000000000000000000000000101", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f448": "0x63c103e1feea47a9bf6c0dce1349da1a95b96532661d43063ab8e52b3e2a844b", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f449": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f44a": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f44b": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f44c": "0x00000000000000000000000000000000000000000000000001620725a3de2009", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f44d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3f450": "0x000000000000000000000000b3b10eff47b9c0b3e5579bf1c25872111667e650", - "0x3987ba2457a57cc6778cce06d8c58970029977d834f0de345c7a495612cbb060": "0x00000000000000000000000000000000000000000000081f2acc2a62590de041", - "0x3987ba2457a57cc6778cce06d8c58970029977d834f0de345c7a495612cbb061": "0x000000000000000000000000000000000000000000098b4d3b425f8c368391b2", - "0x3987ba2457a57cc6778cce06d8c58970029977d834f0de345c7a495612cbb062": "0x00000000000000000000000000000000000000000000003635c9adc5dea00000", - "0x3987ba2457a57cc6778cce06d8c58970029977d834f0de345c7a495612cbb063": "0x00000000000000000000000010abb5efecdc09581f8b7cb95791fe2936790b4e", - "0x6f125332c6f598e8798f0c277f4b1052ac80cd02ff2eebe0c7f362d63b6959ef": "0x000000000000000000000000000000000000000000000000008dc9007b27b5a9", - "0x793bebaf0ea12c858c08547e9aa88b849bba94bb6933c7bdb0fecbb707ecf5c7": "0x00000000000000000000000000000000000000000000076d52eebfbfbfc172e5", - "0xaccfa2662c944e8eae80b7720d9d232eb6809c18f6c8da65189acbb38069d869": "0x000000000000000000000000000000000000000000000000000289739e60e3e2", - "0xb6e4d5c52e0c64fb49c5a97cacdbcf8bd94b5bd4d490590326a19d27eaf543ae": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xbe273e24e8bd646e29d1fb5a924a12a8585095b9f45a317fc708165a127fdd70": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xc34fc4bc1a730d3f836c9ac5124865056e88f3776b63662e34976bdb47549077": "0x000000000000000000000000000000000000000000000036353be4c563784a57", - "0xe2112d92b8a1d00a569b85fbe7a384a5c9f74f5ff8478647397cb58dde254ffa": "0x53706c697420666f722070656f706c652077686f2073656e74206d6f6e657920", - "0xe2112d92b8a1d00a569b85fbe7a384a5c9f74f5ff8478647397cb58dde254ffb": "0x746f207468652044414f20616674657220746865204861726420466f726b2062", - "0xe2112d92b8a1d00a569b85fbe7a384a5c9f74f5ff8478647397cb58dde254ffc": "0x79206d697374616b650000000000000000000000000000000000000000000000", - "0xf60322aa1a2e769d412b36e4a9def4300f7540bf1bc9e0f4691786a9100145fa": "0x0000000000000000000000000000000000000000000000000000000062188dd2", - "0xf735edeea40e4ec771f49da7f7b854b398a1ad43f8a9617d43e53d3093e9fdc0": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xf7905fa5d54027d5d59f4678dda481331babad2d3d0fdefd552afbce2e74c07e": "0x0000000000000000000000000000000000000000000000000000000000000110" - } - }, - "0xe6002189a74b43e6868b20c1311bc108e38aac57": { - "balance": "0x29129264d1ae4848b", - "nonce": "45" - }, - "0xea674fdde714fd979de3edf0f56aa9716b898ec8": { - "balance": "0x1601bbe4c58ec73210", - "nonce": "337736" - }, - "0xfde8d5f77ef48bb7bf5766c7404691b9ee1dfca7": { - "balance": "0x0", - "code": "0x606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b9291505056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "1968180", - "difficulty": "56311715252709", - "timestamp": "1469713694", - "gasLimit": "4712388", - "miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8" - }, - "input": "0xf8aa2d850c2b6f9f7e830aae6094630a0cd35d5bd57e61410fda76fea850225cda1880b844e1fa7638000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000001ba0563f81ca66b2c618bf4be9470fab88fff1b44eb5c33a9c73a68e8b26fbaa7c8da041464789c49fee77d2e053ff0705bc845fe2a78a35e478132371f294bb594021", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0xe6002189a74b43e6868b20c1311bc108e38aac57", - "gas": "0xaae60", - "gasUsed": "0xaae60", - "to": "0x630a0cd35d5bd57e61410fda76fea850225cda18", - "input": "0xe1fa763800000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000", - "error": "invalid jump destination", - "calls": [ - { - "from": "0x630a0cd35d5bd57e61410fda76fea850225cda18", - "gas": "0x9f5a0", - "gasUsed": "0x314", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x70a08231000000000000000000000000630a0cd35d5bd57e61410fda76fea850225cda18", - "output": "0x000000000000000000000000000000000000000000000000000289739e60e3e2", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x630a0cd35d5bd57e61410fda76fea850225cda18", - "gas": "0x9a327", - "gasUsed": "0x67b0", - "to": "0x6e073c0e1bd5af550239025dffcfb37175acedd3", - "input": "0x1a695230000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c189413", - "calls": [ - { - "from": "0x6e073c0e1bd5af550239025dffcfb37175acedd3", - "gas": "0x93ff6", - "gasUsed": "0x314", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x70a082310000000000000000000000006e073c0e1bd5af550239025dffcfb37175acedd3", - "output": "0x000000000000000000000000000000000000000000000025d57ab057892050fc", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e073c0e1bd5af550239025dffcfb37175acedd3", - "gas": "0x93c42", - "gasUsed": "0x13f", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x18160ddd", - "output": "0x000000000000000000000000000000000000000000098b4d3b425f8c368391b2", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x6e073c0e1bd5af550239025dffcfb37175acedd3", - "gas": "0x939ba", - "gasUsed": "0x5fca", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0xa9059cbb000000000000000000000000630a0cd35d5bd57e61410fda76fea850225cda18000000000000000000000000000000000000000000000025d57ab057892050fc", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x630a0cd35d5bd57e61410fda76fea850225cda18", - "gas": "0x8d8b6", - "gasUsed": "0x7be", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x013cf08b0000000000000000000000000000000000000000000000000000000000000110", - "output": "0x000000000000000000000000b3b10eff47b9c0b3e5579bf1c25872111667e6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000579a07ea0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000163c103e1feea47a9bf6c0dce1349da1a95b96532661d43063ab8e52b3e2a844b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001620725a3de20090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b3b10eff47b9c0b3e5579bf1c25872111667e650000000000000000000000000000000000000000000000000000000000000004953706c697420666f722070656f706c652077686f2073656e74206d6f6e657920746f207468652044414f20616674657220746865204861726420466f726b206279206d697374616b650000000000000000000000000000000000000000000000", - "value": "0x0", - "type": "CALL" - }, - { - "from": "0x630a0cd35d5bd57e61410fda76fea850225cda18", - "gas": "0x880f8", - "gasUsed": "0x880f8", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x82661dc40000000000000000000000000000000000000000000000000000000000000110000000000000000000000000b3b10eff47b9c0b3e5579bf1c25872111667e650", - "error": "invalid jump destination", - "calls": [ - { - "from": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "gas": "0x7f910", - "gasUsed": "0xd20f", - "to": "0x10abb5efecdc09581f8b7cb95791fe2936790b4e", - "input": "0xbaac5300000000000000000000000000630a0cd35d5bd57e61410fda76fea850225cda18", - "output": "0x0000000000000000000000000000000000000000000000000000000000000001", - "calls": [ - { - "from": "0x10abb5efecdc09581f8b7cb95791fe2936790b4e", - "gas": "0x76e12", - "gasUsed": "0x13f9", - "to": "0xfde8d5f77ef48bb7bf5766c7404691b9ee1dfca7", - "input": "0x", - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x20320625e3126cb0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - } - ], - "value": "0x0", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json deleted file mode 100644 index 6faf898a0..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "genesis": { - "difficulty": "45372803248884", - "extraData": "0x65746865726d696e652e6f7267202855533129", - "gasLimit": "4712388", - "hash": "0xa2b18cc64ec062676680f2bb2d880205dcd372f4396722f2294d3fceece96193", - "miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8", - "mixHash": "0xce7c26a9238b249edcdcd51f0ea1ad0e632e872daf9a09f039d918bcaeb7194f", - "nonce": "0x849d49e634e93bb5", - "number": "1646451", - "stateRoot": "0x2bd193b9911caf43204960cc7661ce864bf0bac7f9b60191aa02bbff24f061fb", - "timestamp": "1465103859", - "totalDifficulty": "24813742796574158431", - "alloc": { - "0x01115b41bd2731353dd3e6abf44818fdc035aaf1": { - "balance": "0x16d99e16e809000", - "nonce": "23" - }, - "0x61c808d82a3ac53231750dadc13c777b59310bd9": { - "balance": "0x6a636960e34bd696f4", - "nonce": "36888" - }, - "0xbb9bc244d798123fde783fcc1c72d3bb8c189413": { - "balance": "0x9b37460cdbcba74181f81", - "code": "0x6060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638b15a605146106c95780638d7af473146106d257806396d7f3f5146106e1578063a1da2fb9146106ea578063a3912ec814610704578063a9059cbb1461070f578063b7bc2c841461073f578063baac53001461074b578063be7c29c1146107b1578063c9d27afe14610817578063cc9ae3f61461082d578063cdef91d014610841578063dbde198814610859578063dd62ed3e1461087e578063e33734fd146108b2578063e5962195146108c6578063e66f53b7146108de578063eceb2945146108f0578063f8c80d261461094f575b610966600f546000906234bc000142108015610239575060125433600160a060020a03908116911614155b156109785761098033610752565b6109866004356000805482908110156100025750808052600e8202600080516020612a3683398151915201905060038101546004820154600683015460018401548454600786015460058701546009880154600a890154600d8a0154600160a060020a039586169b509599600201989760ff81811698610100909204811697949691951693168c565b61096660043560243533600160a060020a03908116600081815260156020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b61096660105481565b610a7d600754600160a060020a031681565b610a7d600e54600160a060020a031681565b61096660165481565b6109665b60004262127500600f60005054031115610de557506014610983565b610a7d601254600160a060020a031681565b60408051602060248035600481810135601f810185900485028601850190965285855261096695813595919460449492939092019181908401838280828437509496505050505050506000600060006000600060003411156116a857610002565b6109666004356024356044355b60115460009060ff1680156104315750600f5442115b80156124e957506124e78461044b565b6109666000610980335b600160a060020a0381166000908152600b602052604081205481908114156129cb57610b99565b61096660065481565b6109665b600d5430600160a060020a03163103610983565b610966600f5481565b61096660043560046020526000908152604090205460ff1681565b61096660043560243560006124cb610831565b610a9a6000341115610ba457610002565b604080516020604435600481810135601f8101849004840285018401909552848452610966948135946024803595939460649492939101918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505060a435915050600060006110c1336105ec565b61096660043560096020526000908152604090205481565b61096660015481565b610a9a60043530600160a060020a031633600160a060020a03161415806105db5750600160a060020a03811660009081526004602052604090205460ff16155b156121cb576121c8565b6109666004355b600160a060020a0381166000908152601460205260409020545b919050565b6109666004356024356000600034111561259957610002565b610966600062e6b680420360026000505410806106505750600354600160a060020a0390811633909116145b80156106645750600254621274ff19420190105b156126145750426002908155600180549091028155610983565b610966600435600a6020526000908152604090205481565b610966600435602435600060006000600060006000341115611ba157610002565b610a7d600854600160a060020a031681565b610966600c5481565b61096660005460001901610983565b61096660025481565b61096660043560006000600060003411156121fc57610002565b6109665b6001610983565b6109666004356024355b60115460009060ff16801561072f5750600f5442115b801561248757506124853361044b565b61096660115460ff1681565b6109666004355b60006000600f600050544210801561076a5750600034115b80156107a457506011546101009004600160a060020a0316600014806107a457506011546101009004600160a060020a0390811633909116145b15610b9f57610a9c61037f565b610a7d600435600060006000508281548110156100025750508080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56b600e83020180548290811015610002575081526020902060030154600160a060020a0316610606565b61096660043560243560006000610e1b336105ec565b6109665b6000600034111561247c57610002565b61096660043560056020526000908152604090205481565b610966600435602435604435600061252f845b6000600060003411156127ac57610002565b610966600435602435600160a060020a0382811660009081526015602090815260408083209385168352929052205461033f565b610a9a600435600034111561254557610002565b610966600435600b6020526000908152604090205481565b610a7d600354600160a060020a031681565b604080516020606435600481810135601f81018490048402850184019095528484526109669481359460248035956044359560849492019190819084018382808284375094965050505050505060006000600034111561103257610002565b610a7d6011546101009004600160a060020a031681565b60408051918252519081900360200190f35b610980610708565b90505b90565b604051808d600160a060020a031681526020018c8152602001806020018b81526020018a815260200189815260200188815260200187815260200186815260200185815260200184815260200183600160a060020a0316815260200182810382528c818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610a635780601f10610a3857610100808354040283529160200191610a63565b820191906000526020600020905b815481529060010190602001808311610a4657829003601f168201915b50509d505050505050505050505050505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b005b604051601254601434908102939093049350600160a060020a03169183900390600081818185876185025a03f150505050600160a060020a038316600081815260146020908152604080832080548601905560168054860190556013825291829020805434019055815184815291517fdbccb92686efceafb9bb7e0394df7f58f71b954061b81afb57109bf247d3d75a9281900390910190a260105460165410801590610b4c575060115460ff16155b15610b94576011805460ff1916600117905560165460408051918252517ff381a3e2428fdda36615919e8d9c35878d9eb0cf85ac6edf575088e80e4c147e9181900360200190a15b600191505b50919050565b610002565b600f5442118015610bb8575060115460ff16155b15610de357601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040516012549051600160a060020a039190911631109050610cc9576040805160125460e060020a63d2cc718f0282529151600160a060020a039290921691630221038a913091849163d2cc718f91600482810192602092919082900301816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a039490941660048201526024810193909352516044838101936020935082900301816000876161da5a03f115610002575050505b33600160a060020a0316600081815260136020526040808220549051909181818185876185025a03f19250505015610de35733600160a060020a03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d6013600050600033600160a060020a03168152602001908152602001600020600050546040518082815260200191505060405180910390a26014600050600033600160a060020a0316815260200190815260200160002060005054601660008282825054039250508190555060006014600050600033600160a060020a031681526020019081526020016000206000508190555060006013600050600033600160a060020a03168152602001908152602001600020600050819055505b565b4262054600600f60005054031115610e13576201518062127500600f60005054034203046014019050610983565b50601e610983565b60001415610e2857610002565b6000341115610e3657610002565b6000805485908110156100025750600160a060020a03331681527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56e600e8602908101602052604090912054600080516020612a3683398151915291909101915060ff1680610eb05750600c810160205260406000205460ff165b80610ebf575060038101544210155b15610ec957610002565b8215610f0f5733600160a060020a03166000908152601460209081526040808320546009850180549091019055600b84019091529020805460ff19166001179055610f4b565b33600160a060020a0316600090815260146020908152604080832054600a850180549091019055600c84019091529020805460ff191660011790555b33600160a060020a03166000908152600b60205260408120541415610f77576040600020849055610feb565b33600160a060020a03166000908152600b60205260408120548154811015610002579080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566600e909102015460038201541115610feb5733600160a060020a03166000908152600b602052604090208490555b60408051848152905133600160a060020a03169186917f86abfce99b7dd908bec0169288797f85049ec73cbe046ed9de818fab3a497ae09181900360200190a35092915050565b6000805487908110156100025750808052600e8702600080516020612a3683398151915201905090508484846040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020816005016000505414915050949350505050565b600014156110ce57610002565b82801561111857508660001415806110e857508451600014155b806111005750600354600160a060020a038981169116145b8061110b5750600034115b80611118575062093a8084105b1561112257610002565b8215801561114257506111348861115c565b158061114257506212750084105b156111fe57610002565b83546118e590600160a060020a03165b600160a060020a03811660009081526004602052604081205460ff16806111f15750601254600160a060020a039081169083161480156111f15750601260009054906101000a9004600160a060020a0316600160a060020a031663d2cc718f6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604051516006541190505b156129a157506001610606565b6249d40084111561120e57610002565b60115460ff1615806112215750600f5442105b806112365750600c5434108015611236575082155b1561124057610002565b42844201101561124f57610002565b30600160a060020a031633600160a060020a0316141561126e57610002565b60008054600181018083559091908280158290116112a557600e0281600e0283600052602060002091820191016112a5919061136a565b505060008054929450918491508110156100025750808052600e8302600080516020612a368339815191520190508054600160a060020a031916891781556001818101899055875160028084018054600082815260209081902096975091959481161561010002600019011691909104601f908101829004840193918b019083901061146257805160ff19168380011785555b5061149292915061144a565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561145e578054600160a060020a03191681556000600182810182905560028084018054848255909281161561010002600019011604601f81901061143057505b506000600383018190556004808401805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220611344929091028101905b8082111561145e57600080825560018201818155600283019190915560039091018054600160a060020a03191690556113fc565b601f0160209004906000526020600020908101906113ae91905b8082111561145e576000815560010161144a565b5090565b82800160010185558215611338579182015b82811115611338578251826000505591602001919060010190611474565b50508787866040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f150905001935050505060405180910390208160050160005081905550834201816003016000508190555060018160040160006101000a81548160ff02191690830217905550828160070160006101000a81548160ff02191690830217905550821561157857600881018054600181018083559091908280158290116115735760040281600402836000526020600020918201910161157391906113fc565b505050505b600d8082018054600160a060020a031916331790553460068301819055815401905560408051600160a060020a038a16815260208181018a9052918101859052608060608201818152895191830191909152885185937f5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f938d938d938a938e93929160a084019185810191908190849082908590600090600490601f850104600f02600301f150905090810190601f1680156116485780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a2509695505050505050565b6040805186815260208101839052815189927fdfc78bdca8e3e0b18c16c5c99323c6cb9eb5e00afde190b4e7273f5158702b07928290030190a25b5050505092915050565b6000805488908110156100025750808052600e8802600080516020612a36833981519152019050600781015490945060ff166116e757620d2f006116ec565b622398805b600485015490935060ff16801561170857506003840154830142115b15611716576117b887611890565b600384015442108061172d5750600484015460ff16155b806117ae57508360000160009054906101000a9004600160a060020a03168460010160005054876040518084600160a060020a0316606060020a0281526014018381526020018280519060200190808383829060006004602084601f0104600f02600301f15090500193505050506040518091039020846005016000505414155b1561114c57610002565b61169e565b60048401805461ff001916610100179055835460019550600160a060020a03908116309091161480159061180157508354600754600160a060020a03908116911614155b801561181d57506008548454600160a060020a03908116911614155b801561183957508354601254600160a060020a03908116911614155b801561185557506003548454600160a060020a03908116911614155b1561188b5760018401805430600160a060020a031660009081526005602052604090208054919091019055546006805490910190555b611663875b6000600060005082815481101561000257908052600e02600080516020612a36833981519152018150600481015490915060ff16156118d757600d80546006830154900390555b600401805460ff1916905550565b15156118f45761190087611890565b6001915061193161047f565b604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050505061169e565b6001850154111561194157600091505b50600a8301546009840154865191019060049010801590611986575085600081518110156100025790602001015160f860020a900460f860020a02606860f860020a02145b80156119b6575085600181518110156100025790602001015160f860020a900460f860020a02603760f860020a02145b80156119e6575085600281518110156100025790602001015160f860020a900460f860020a0260ff60f860020a02145b8015611a16575085600381518110156100025790602001015160f860020a900460f860020a02601e60f860020a02145b8015611a45575030600160a060020a0316600090815260056020526040902054611a4290611a5d61047f565b81105b15611a4f57600091505b6001840154611a8090611a5f565b015b30600160a060020a03166000908152600560205260408120546129a961047f565b8110611ad457604051600d8501546006860154600160a060020a0391909116916000919082818181858883f193505050501515611abc57610002565b4260025560165460059004811115611ad45760056001555b6001840154611ae290611a5f565b8110158015611af85750600a8401546009850154115b8015611b015750815b1561188b578360000160009054906101000a9004600160a060020a0316600160a060020a0316846001016000505487604051808280519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611b7d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185876185025a03f19250505015156117bd57610002565b611baa336105ec565b60001415611bb757610002565b60008054889081101561000257508052600e87027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e566810154600080516020612a36833981519152919091019450421080611c1957506003840154622398800142115b80611c3257508354600160a060020a0390811690871614155b80611c425750600784015460ff16155b80611c68575033600160a060020a03166000908152600b8501602052604090205460ff16155b80611c9c575033600160a060020a03166000908152600b60205260409020548714801590611c9c5750604060009081205414155b15611ca657610002565b600884018054600090811015610002579081526020812060030154600160a060020a03161415611e1257611efc86604051600090600160a060020a038316907f9046fefd66f538ab35263248a44217dcb70e2eb2cd136629e141b8b8f9f03b60908390a260408051600e547fe2faf044000000000000000000000000000000000000000000000000000000008252600160a060020a03858116600484015260248301859052604483018590526223988042016064840152925192169163e2faf04491608480820192602092909190829003018187876161da5a03f1156100025750506040515191506106069050565b6008850180546000908110156100025781815260208082209390935530600160a060020a031681526005909252604082205481549092908110156100025790815260208120905060020155601654600885018054600090811015610002579081526020812090506001015560048401805461ff0019166101001790555b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090505433600160a060020a031660009081526014602052604081205460088801805493909102939093049550908110156100025790815260208120905060030154604080517fbaac530000000000000000000000000000000000000000000000000000000000815233600160a060020a0390811660048301529151929091169163baac53009186916024808301926020929190829003018185886185025a03f11561000257505060405151600014159150611f78905057610002565b60088501805460009081101561000257818152602081206003018054600160a060020a03191690931790925580549091908110156100025790815260208120905060030154600160a060020a031660001415611f5757610002565b600d5430600160a060020a0316311015611f7057610002565b611d9561047f565b6008840180546000908110156100025781548282526020822060010154929190811015610002579081526020812090506002015433600160a060020a0390811660009081526014602090815260408083205430909416835260058083528184205460099093529083205460088b018054969095029690960497509487020494508593929091908290811015610002575260208120815060030154600160a060020a0390811682526020828101939093526040918201600090812080549095019094553016835260059091529020548290101561205357610002565b30600160a060020a031660009081526005602052604081208054849003905560088501805483926009929091829081101561000257508152602080822060030154600160a060020a039081168352929052604080822080549094019093553090911681522054819010156120c657610002565b30600160a060020a0390811660009081526009602090815260408083208054869003905533909316808352601482528383205484519081529351929390927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a36121383361086c565b5033600160a060020a03166000908152601460209081526040808320805460168054919091039055839055600a9091528120556001945061169e565b30600160a060020a0390811660008181526005602090815260408083208054958716808552828520805490970190965584845283905560099091528082208054948352908220805490940190935590815290555b50565b604051600160a060020a0382811691309091163190600081818185876185025a03f192505050151561217457610002565b33600160a060020a03818116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f028352935197995091969195929092169363d2cc718f936004848101949193929183900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a03168152602001908152602001600020600050540204101561229d57610002565b600160a060020a03338116600090815260096020908152604080832054815160065460085460e060020a63d2cc718f02835293519296909593169363d2cc718f93600483810194929383900301908290876161da5a03f11561000257505050604051805190602001506005600050600033600160a060020a0316815260200190815260200160002060005054020403905083156123ec57600860009054906101000a9004600160a060020a0316600160a060020a0316630221038a83600160a060020a0316630e7082036040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060408051805160e160020a63011081c5028252600160a060020a031660048201526024810186905290516044808301935060209282900301816000876161da5a03f115610002575050604051511515905061245457610002565b6040805160085460e160020a63011081c5028252600160a060020a038581166004840152602483018590529251921691630221038a9160448082019260209290919082900301816000876161da5a03f115610002575050604051511515905061245457610002565b600160a060020a03331660009081526009602052604090208054909101905550600192915050565b6109803361086c565b155b80156124a257506124a23384845b6000600061293a856105ec565b80156124be57506124be83836000600034111561261c57610002565b15610b9f5750600161033f565b15156124d657610002565b6124e08383610719565b905061033f565b155b80156124fb57506124fb848484612495565b80156125185750612518848484600060003411156126c157610002565b15610b9f57506001612528565b90505b9392505050565b151561253a57610002565b61252584848461041b565b30600160a060020a031633600160a060020a031614158061258a575030600160a060020a031660009081526005602052604090205460649061258561047f565b010481115b1561259457610002565b600c55565b600354600160a060020a0390811633909116146125b557610002565b600160a060020a038316600081815260046020908152604091829020805460ff191686179055815185815291517f73ad2a153c8b67991df9459024950b318a609782cee8c7eeda47b905f9baa91f9281900390910190a250600161033f565b506000610983565b33600160a060020a03166000908152601460205260409020548290108015906126455750600082115b156126b957600160a060020a03338116600081815260146020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161033f565b50600061033f565b600160a060020a03841660009081526014602052604090205482901080159061270a5750601560209081526040600081812033600160a060020a03168252909252902054829010155b80156127165750600082115b156127a457600160a060020a03838116600081815260146020908152604080832080548801905588851680845281842080548990039055601583528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001612528565b506000612528565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f11561000257505060405151905061281a866105ec565b0204101561282757610002565b600160a060020a038381166000908152600a6020908152604080832054601654600754835160e060020a63d2cc718f02815293519296919591169363d2cc718f9360048181019492939183900301908290876161da5a03f115610002575050604051519050612895866105ec565b0204039050600760009054906101000a9004600160a060020a0316600160a060020a0316630221038a84836040518360e060020a0281526004018083600160a060020a03168152602001828152602001925050506020604051808303816000876161da5a03f115610002575050604051511515905061291357610002565b600160a060020a0383166000908152600a6020526040902080548201905560019150610b99565b600160a060020a0386166000908152600a602052604090205480850291909104915081111561296857610002565b600160a060020a038581166000908152600a60205260408082208054859003905591861681522080548201905560019150509392505050565b506000610606565b0160030260166000505483020460016000505460166000505404019050610606565b600160a060020a0383166000908152600b6020526040812054815481101561000257818052600e02600080516020612a368339815191520190506003810154909150421115610b9457600160a060020a0383166000908152600b602052604081208190559150610b9956290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563", - "nonce": "3", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000057495e10", - "0x0000000000000000000000000000000000000000000000000000000000000012": "0x000000000000000000000000807640a13483f8ac783c557fcdf27be11ea4ac7a" - } - }, - "0xcf1476387d780169410d4e936d75a206fda2a68c": { - "balance": "0x15fd0ad66ea7000", - "code": "0x606060405236156100b95760e060020a6000350463173825d9811461010b5780632f54bf6e1461015f5780634123cb6b146101875780635c52c2f5146101905780637065cb48146101ba578063746c9171146101e7578063797af627146101f0578063b20d30a914610203578063b61d27f614610230578063b75c7dc614610251578063ba51a6df14610280578063c2cf7326146102ad578063cbf0b0c0146102eb578063f00d4b5d14610318578063f1736d861461034a575b61035460003411156101095760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b610354600435600060003660405180838380828437820191505092505050604051809103902061064a815b600160a060020a03331660009081526101026020526040812054818082811415610c6657610dbf565b6103566004355b600160a060020a03811660009081526101026020526040812054115b919050565b61035660015481565b61035460003660405180838380828437820191505092505050604051809103902061078b81610136565b6103546004356000366040518083838082843782019150509250505060405180910390206105c681610136565b61035660005481565b6103566004355b600081610a2781610136565b61035460043560003660405180838380828437820191505092505050604051809103902061077f81610136565b6103566004803590602480359160443591820191013560006107aa33610166565b610354600435600160a060020a03331660009081526101026020526040812054908082811415610368576103e7565b61035460043560003660405180838380828437820191505092505050604051809103902061070881610136565b610356600435602435600082815261010360209081526040808320600160a060020a0385168452610102909252822054828181141561076157610776565b61035460043560003660405180838380828437820191505092505050604051809103902061079981610136565b610354600435602435600060003660405180838380828437820191505092505050604051809103902061047281610136565b6103566101055481565b005b60408051918252519081900360200190f35b50506000828152610103602052604081206001810154600284900a9290831611156103e75780546001828101805492909101835590839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b50505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a1505b505050565b156103e75761048083610166565b1561048b575061046d565b600160a060020a0384166000908152610102602052604081205492508214156104b4575061046d565b6103ed5b6101045460005b81811015610f0b57610104805461010891600091849081101561000257600080516020610fd88339815191520154825250602091909152604081208054600160a060020a0319168155600181810183905560028281018054858255939493909281161561010002600019011604601f819010610f9057505b5050506001016104bf565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005055600154600160a060020a03831660008181526101026020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b505b50565b156105c1576105d482610166565b156105df57506105c3565b6105e76104b8565b60015460fa90106105fa576105fa61060f565b60015460fa901061054257506105c3565b6106c75b60015b6001548110156105c3575b6001548110801561063d5750600281610100811015610002570154600014155b15610dc75760010161061d565b1561046d57600160a060020a03831660009081526101026020526040812054925082141561067857506105c1565b600160016000505403600060005054111561069357506105c1565b600060028361010081101561000257508301819055600160a060020a0384168152610102602052604081205561060b6104b8565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b156105c15760015482111561071d57506105c3565b600082905561072a6104b8565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001820154600282900a9081166000141593505b50505092915050565b156105c1575061010555565b156105c35760006101065550565b156105c15781600160a060020a0316ff5b156109eb576107be846000610ea133610166565b1561087d577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00433858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843782019150509250505060006040518083038185876185025a03f150600093506109eb92505050565b6000364360405180848480828437820191505082815260200193505050506040518091039020905080506108b0816101f7565b1580156108d3575060008181526101086020526040812054600160a060020a0316145b156109eb5760008181526101086020908152604082208054600160a060020a0319168817815560018181018890556002918201805481865294849020909491821615610100026000190190911691909104601f9081019290920481019185919087908390106109f35760ff198135168380011785555b506109659291505b80821115610a235760008155600101610951565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328133868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b82800160010185558215610949579182015b82811115610949578235826000505591602001919060010190610a05565b5090565b15610aaa5760008381526101086020526040812054600160a060020a031614610aaa5760408051600091909120805460018281015460029384018054600160a060020a0394909416959194909391928392859291811615610100026000190116048015610adb5780601f10610ab057610100808354040283529160200191610adb565b50919050565b820191906000526020600020905b815481529060010190602001808311610abe57829003601f168201915b505091505060006040518083038185876185025a03f1505050600084815261010860209081526040918290208054600180830154855133600160a060020a0381811683529682018c9052968101829052929094166060830181905260a06080840181815260029586018054948516156101000260001901909416959095049084018190527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a97508a95949193919060c083019084908015610bdd5780601f10610bb257610100808354040283529160200191610bdd565b820191906000526020600020905b815481529060010190602001808311610bc057829003601f168201915b5050965050505050505060405180910390a16000838152610108602052604081208054600160a060020a0319168155600181810183905560028281018054858255939493909281161561010002600019011604601f819010610c4857505b5050506001915050610182565b601f016020900490600052602060002090810190610c3b9190610951565b60008581526101036020526040812080549093501415610cee576000805483556001838101919091556101048054918201808255828015829011610cbd57818360005260206000209182019101610cbd9190610951565b50505060028301819055610104805487929081101561000257600091909152600080516020610fd883398151915201555b506001810154600283900a90811660001415610dbf5760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610dac576000858152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610fd8833981519152929092018190558082556001828101829055600292909201559450610dbf9050565b8154600019018255600182018054821790555b505050919050565b5b60018054118015610dea57506001546002906101008110156100025701546000145b15610dfe5760018054600019019055610dc8565b60015481108015610e215750600154600290610100811015610002570154600014155b8015610e3b57506002816101008110156100025701546000145b15610e9c57600154600290610100811015610002578101549082610100811015610002579090016000505580610102600060028361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b610612565b156101825761010754610eb75b62015180420490565b1115610ed057600061010655610ecb610eae565b610107555b6101065480830110801590610eed57506101055461010654830111155b15610f0357506101068054820190556001610182565b506000610182565b6105c16101045460005b81811015610fae5761010480548290811015610002576000918252600080516020610fd8833981519152015414610f8857610104805461010391600091849081101561000257600080516020610fd883398151915201548252506020919091526040812081815560018101829055600201555b600101610f15565b601f0160209004906000526020600020908101906105379190610951565b610104805460008083559190915261046d90600080516020610fd883398151915290810190610951564c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000105": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000106": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000107": "0x000000000000000000000000000000000000000000000000000000000000423d", - "0xcabd288dcb1ace4f49c34e8ac2d843772952b4226b3c832bdb4ac1ddca0f7c05": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "1646452", - "difficulty": "45328493887096", - "timestamp": "1465103894", - "gasLimit": "4712388", - "miner": "0x61c808d82a3ac53231750dadc13c777b59310bd9" - }, - "input": "0xf9018b178504a817c80083030d4094cf1476387d780169410d4e936d75a206fda2a68c80b90124b61d27f6000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c189413000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000088613930353963626230303030303030303030303030303030303030303030303039306433633138313264653236363962663830376264373735386365623165333439376163376534303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030316336626635323633343030300000000000000000000000000000000000000000000000001ca0f1ae5ea07b1d00eb5e06fc854124ee0234ec61c8b393147f9d030804a75c98daa01d045d7633012cca74e30e975c3d00d11b4243dd8648f2e78d652f3a8aaafceb", - "tracerConfig": { - "withLog": true - }, - "result": { - "from": "0x01115b41bd2731353dd3e6abf44818fdc035aaf1", - "gas": "0x30d40", - "gasUsed": "0x288c9", - "to": "0xcf1476387d780169410d4e936d75a206fda2a68c", - "input": "0xb61d27f6000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c18941300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008861393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030000000000000000000000000000000000000000000000000", - "output": "0x0000000000000000000000000000000000000000000000000000000000000000", - "calls": [ - { - "from": "0xcf1476387d780169410d4e936d75a206fda2a68c", - "gas": "0x1e30b", - "gasUsed": "0x1e30b", - "to": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "input": "0x61393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030", - "error": "invalid jump destination", - "value": "0x0", - "type": "CALL" - } - ], - "logs": [ - { - "address": "0xcf1476387d780169410d4e936d75a206fda2a68c", - "topics": [ - "0x92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd004" - ], - "data": "0x00000000000000000000000001115b41bd2731353dd3e6abf44818fdc035aaf10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c1894130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008861393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030", - "position": "0x0" - } - ], - "value": "0x0", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json b/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json deleted file mode 100644 index e73081107..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "genesis": { - "difficulty": "11934798510088", - "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", - "gasLimit": "3141592", - "hash": "0xfc543a4a551afbd4a6c5d6d49041371e6bb58b1108c12aaec7f487ce656bb97f", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", - "mixHash": "0xa6a1e67fc68da76b8d9cc3ce1c45d5e1f4bbd96b5dcfddbe0017d7fa99903ead", - "nonce": "0x5f00c600268b4659", - "number": "995200", - "stateRoot": "0x3579328470dd2aef5b9da69f5480cbe0d375e653b530ab3c1aee0da5e1ff4c94", - "timestamp": "1455322761", - "totalDifficulty": "7077231809278509672", - "alloc": { - "0x200edd17f30485a8735878661960cd7a9a95733f": { - "balance": "0x0", - "code": "0x3660008037602060003660003473273930d21e01ee25e4c219b63259d214872220a261235a5a03f21560015760206000f3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000104": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x4c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf04": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf05": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x8ba1097eb3abe3dc1b51faa48445d593bf968f722e20b67bb62a87495836bf06": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa611e7c895a426c0477bc9e280db9c3b1e456dc6310ffcf23926ef5186c1facc": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c410e": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c410f": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xac682d343707aadf06c2c4c3692831d9e7ba711099ef36f9efb8bb29be8c4110": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x273930d21e01ee25e4c219b63259d214872220a2": { - "balance": "0x0", - "code": "0x606060405236156100da5760e060020a6000350463173825d9811461012c5780632f54bf6e146101875780634123cb6b146101af57806352375093146101b857806354fd4d50146101c25780635c52c2f5146101cc578063659010e7146101fd5780637065cb4814610207578063746c91711461023b578063797af62714610244578063b20d30a914610257578063b61d27f61461028b578063b75c7dc6146102ac578063ba51a6df146102db578063c2cf73261461030f578063cbf0b0c01461034d578063f00d4b5d14610381578063f1736d86146103ba575b6103c4600034111561012a5760408051600160a060020a033216815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b565b6103c46004356000600036436040518084848082843750505090910190815260405190819003602001902090506106c9815b600160a060020a03321660009081526101026020526040812054818082811415610c3f57610d97565b6103c66004355b600160a060020a03811660009081526101026020526040812054115b919050565b6103c660015481565b6103c66101075481565b6103c66101085481565b6103c46000364360405180848480828437505050909101908152604051908190036020019020905061081a8161015e565b6103c66101065481565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506106418161015e565b6103c660005481565b6103c66004355b600081610a7d8161015e565b6103c46004356000364360405180848480828437505050909101908152604051908190036020019020905061080e8161015e565b6103c66004803590602480359160443591820191013560006108393261018e565b6103c4600435600160a060020a033216600090815261010260205260408120549080828114156103d857610457565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506107888161015e565b6103c6600435602435600082815261010360209081526040808320600160a060020a038516845261010290925282205482818114156107e157610805565b6103c4600435600036436040518084848082843750505090910190815260405190819003602001902090506108288161015e565b6103c46004356024356000600036436040518084848082843750505090910190815260405190819003602001902090506104e28161015e565b6103c66101055481565b005b60408051918252519081900360200190f35b50506000828152610103602052604081206001810154600284900a9290831611156104575780546001828101805492909101835590839003905560408051600160a060020a03321681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b50505050565b600160a060020a03831660028361010081101561000257508301819055600160a060020a03851660008181526101026020908152604080832083905584835291829020869055815192835282019290925281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a1505b505050565b15610457576104f08361018e565b156104fb57506104dd565b600160a060020a03841660009081526101026020526040812054925082141561052457506104dd565b61045d5b6101045460005b81811015610ee457610104805461010991600091849081101561000257600080516020610f9f83398151915201548252506020918252604081208054600160a060020a0319168155600181018290556002810180548382559083528383209193610f6992601f9290920104810190610a65565b60018054810190819055600160a060020a038316906002906101008110156100025790900160005081905550600160005054610102600050600084600160a060020a03168152602001908152602001600020600050819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3826040518082600160a060020a0316815260200191505060405180910390a15b505b50565b1561063c5761064f8261018e565b1561065a575061063e565b610662610528565b60015460fa90106106775761067561068c565b505b60015460fa90106105a2575061063e565b6107465b600060015b600154811015610a79575b600154811080156106bc5750600281610100811015610002570154600014155b15610d9f5760010161069c565b156104dd57600160a060020a0383166000908152610102602052604081205492508214156106f7575061063c565b6001600160005054036000600050541115610712575061063c565b600060028361010081101561000257508301819055600160a060020a03841681526101026020526040812055610688610528565b5060408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a1505050565b1561063c5760015482111561079d575061063e565b60008290556107aa610528565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15050565b506001820154600282900a908116600014156108005760009350610805565b600193505b50505092915050565b1561063c575061010555565b1561063e5760006101065550565b1561063c5781600160a060020a0316ff5b15610a555761084d846000610e793261018e565b15610909577f92ca3a80853e6663fa31fa10b99225f18d4902939b4c53a9caae9043f6efd00432858786866040518086600160a060020a0316815260200185815260200184600160a060020a031681526020018060200182810382528484828181526020019250808284378201915050965050505050505060405180910390a184600160a060020a03168484846040518083838082843750505090810191506000908083038185876185025a03f15060009350610a5592505050565b6000364360405180848480828437505050909101908152604051908190036020019020915061093990508161024b565b15801561095c575060008181526101096020526040812054600160a060020a0316145b15610a555760008181526101096020908152604082208054600160a060020a03191688178155600181018790556002018054858255818452928290209092601f01919091048101908490868215610a5d579182015b82811115610a5d5782358260005055916020019190600101906109b1565b50507f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328132868887876040518087815260200186600160a060020a0316815260200185815260200184600160a060020a03168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b949350505050565b506109cf9291505b80821115610a795760008155600101610a65565b5090565b15610c2c5760008381526101096020526040812054600160a060020a031614610c2c5760408051600091909120805460018201546002929092018054600160a060020a0392909216939091819083908015610afd57820191906000526020600020905b815481529060010190602001808311610ae057829003601f168201915b505091505060006040518083038185876185025a03f150505060008481526101096020908152604080519281902080546001820154600160a060020a033281811688529587018b905293860181905292166060850181905260a06080860181815260029390930180549187018290527fe7c957c06e9a662c1a6c77366179f5b702b97651dc28eee7d5bf1dff6e40bb4a975094958a959293909160c083019084908015610bcf57820191906000526020600020905b815481529060010190602001808311610bb257829003601f168201915b5050965050505050505060405180910390a160008381526101096020908152604082208054600160a060020a031916815560018101839055600281018054848255908452828420919392610c3292601f9290920104810190610a65565b50919050565b50505060019150506101aa565b60008581526101036020526040812080549093501415610cc7576000805483556001838101919091556101048054918201808255828015829011610c9657818360005260206000209182019101610c969190610a65565b50505060028301819055610104805487929081101561000257600091909152600080516020610f9f83398151915201555b506001810154600283900a90811660001415610d975760408051600160a060020a03321681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a1815460019011610d84576000858152610103602052604090206002015461010480549091908110156100025760406000908120600080516020610f9f8339815191529290920181905580825560018083018290556002909201559450610d979050565b8154600019018255600182018054821790555b505050919050565b5b60018054118015610dc257506001546002906101008110156100025701546000145b15610dd65760018054600019019055610da0565b60015481108015610df95750600154600290610100811015610002570154600014155b8015610e1357506002816101008110156100025701546000145b15610e7457600154600290610100811015610002578101549082610100811015610002578101919091558190610102906000908361010081101561000257810154825260209290925260408120929092556001546101008110156100025701555b610691565b156101aa5761010754610e8f5b62015180420490565b1115610ea857600061010655610ea3610e86565b610107555b6101065480830110801590610ec65750610106546101055490830111155b15610edc575061010680548201905560016101aa565b5060006101aa565b61063c6101045460005b81811015610f745761010480548290811015610002576000918252600080516020610f9f833981519152015414610f6157610104805461010391600091849081101561000257600080516020610f9f83398151915201548252506020919091526040812081815560018101829055600201555b600101610eee565b50505060010161052f565b61010480546000808355919091526104dd90600080516020610f9f83398151915290810190610a6556004c0be60200faa20559308cb7b5a1bb3255c16cb1cab91f525b5ae7a03d02fabe" - }, - "0x4f5777744b500616697cb655dcb02ee6cd51deb5": { - "balance": "0xb0983f1b83eec290", - "nonce": "2" - }, - "0xf8b483dba2c3b7176a3da549ad41a48bb3121069": { - "balance": "0x16969a0ba2c2d384d07", - "nonce": "67521" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "995201", - "difficulty": "11940626048551", - "timestamp": "1455322773", - "gasLimit": "3141592", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069" - }, - "input": "0xf89102850a954d522e8303308594200edd17f30485a8735878661960cd7a9a95733f888ac7230489e80000a4ba51a6df00000000000000000000000000000000000000000000000000000000000000001ca04f2cc45b96f965296382b2e9b657e90808301d5179035a5d91a2de7b912def20a056e19271ea4e19e4e034f38e925e312beed4d300c267160eeb2f565c42deb578", - "tracerConfig": { - "withLog": true, - "onlyTopCall": true - }, - "result": { - "from": "0x4f5777744b500616697cb655dcb02ee6cd51deb5", - "gas": "0x33085", - "gasUsed": "0x1a9e5", - "to": "0x200edd17f30485a8735878661960cd7a9a95733f", - "input": "0xba51a6df0000000000000000000000000000000000000000000000000000000000000000", - "output": "0xba51a6df00000000000000000000000000000000000000000000000000000000", - "value": "0x8ac7230489e80000", - "type": "CALL" - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json deleted file mode 100644 index a34d3b759..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_existing_contract.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "genesis": { - "difficulty": "6217248151198", - "extraData": "0xd783010103844765746887676f312e342e32856c696e7578", - "gasLimit": "3141592", - "hash": "0xe8bff55fe3e61936ef321cf3afaeb1ba2f7234e1e89535fa8ae39963caebe9c3", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5", - "mixHash": "0x03da00d5a15a064e5ebddf53cd0aaeb9a8aff0f40c0fb031a74f463d11ec83b8", - "nonce": "0x6575fe08c4167044", - "number": "243825", - "stateRoot": "0x47182fe2e6e740b8a76f82fe5c527d6ad548f805274f21792cf4047235b24fbf", - "timestamp": "1442424328", - "totalDifficulty": "1035061827427752845", - "alloc": { - "0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": { - "balance": "0xc820f93200f4000", - "nonce": "0x5E", - "code": "0x" - }, - "0x332b656504f4eabb44c8617a42af37461a34e9dc": { - "balance": "0x11faea4f35e5af80000", - "code": "0x" - }, - "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5": { - "balance": "0xbf681825be002ac452", - "nonce": "0x70FA", - "code": "0x" - }, - "0x82effbaaaf28614e55b2ba440fb198e0e5789b0f": { - "balance": "0xb3d0ac5cb94df6f6b0", - "nonce": "0x1", - "code": "0x" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "243826", - "difficulty": "6214212385501", - "timestamp": "1442424353", - "gasLimit": "3141592", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5" - }, - "input": "0xf8e85e850ba43b7400830f42408080b89660606040527382effbaaaf28614e55b2ba440fb198e0e5789b0f600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600a80608c6000396000f30060606040526008565b001ca0340b21661e5bb85a46319a15f33a362e5c0f02faa7cdbf9c5808b2134da968eaa0226e6788f8c20e211d436ab7f6298ef32fa4c23a509eeeaac0880d115c17bc3f", - "result": { - "0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": { - "balance": "0xc820f93200f4000", - "nonce": 94 - }, - "0x332b656504f4eabb44c8617a42af37461a34e9dc": { - "balance": "0x11faea4f35e5af80000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5": { - "balance": "0xbf681825be002ac452", - "nonce": 28922 - }, - "0x82effbaaaf28614e55b2ba440fb198e0e5789b0f": { - "balance": "0xb3d0ac5cb94df6f6b0", - "nonce": 1 - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json deleted file mode 100644 index 7204bfcbf..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer/simple.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "nonce": 22 - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "nonce": 1, - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "nonce": 29072 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_legacy/simple.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_legacy/simple.json deleted file mode 100644 index 44b1f08dd..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_legacy/simple.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "result": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": 22, - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": 1, - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": 29072, - "storage": {} - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create.json deleted file mode 100644 index 1b0962247..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "genesis": { - "difficulty": "13756228101629", - "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", - "gasLimit": "3141592", - "hash": "0x58b7a87b6ba10b46b4e251d64ebc3d9822dd82218eaf24dff6796f6f1f687251", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", - "mixHash": "0x5984b9a316116bd890e6e5f4c52d655184b0d7aa74821e1382d7760f9803c1dd", - "nonce": "0xea4bb4997242c681", - "number": "1061221", - "stateRoot": "0x5402c04d481414248d824c3b61e924e0c9307adbc9fbaae774a74cce30a4163d", - "timestamp": "1456458069", - "totalDifficulty": "7930751135586064334", - "alloc": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x9fb6b81e112638b886", - "nonce": "217865", - "code": "0x" - }, - "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { - "balance": "0x15b6828e22bb12188", - "nonce": "747", - "code": "0x" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "ethash": {} - } - }, - "context": { - "number": "1061222", - "difficulty": "13749511193633", - "timestamp": "1456458097", - "gasLimit": "3141592", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" - }, - "input": "0xf905498202eb850ba43b7400830f42408080b904f460606040526040516102b43803806102b48339016040526060805160600190602001505b5b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b806001600050908051906020019082805482825590600052602060002090601f01602090048101928215609e579182015b82811115609d5782518260005055916020019190600101906081565b5b50905060c5919060a9565b8082111560c1576000818150600090555060010160a9565b5090565b50505b506101dc806100d86000396000f30060606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001ee7b225f6964223a225a473466784a7245323639384866623839222c22666f726d5f736f75726365223a22434c54523031222c22636f6d6d69746d656e745f64617465223a22222c22626f72726f7765725f6e616d65223a22222c22626f72726f7765725f616464726573735f6c696e6531223a22222c22626f72726f7765725f616464726573735f6c696e6532223a22222c22626f72726f7765725f636f6e74616374223a22222c22626f72726f7765725f7374617465223a22222c22626f72726f7765725f74797065223a22222c2270726f70657274795f61646472657373223a22222c226c6f616e5f616d6f756e745f7772697474656e223a22222c226c6f616e5f616d6f756e74223a22222c224c54565f7772697474656e223a22222c224c5456223a22222c2244534352223a22222c2270726f70657274795f74797065223a22222c2270726f70657274795f6465736372697074696f6e223a22222c226c656e646572223a22222c2267756172616e746f7273223a22222c226c696d69746564223a22222c226361705f616d6f756e74223a22222c226361705f70657263656e745f7772697474656e223a22222c226361705f70657263656e74616765223a22222c227465726d5f7772697474656e223a22222c227465726d223a22222c22657874656e64223a22227d0000000000000000000000000000000000001ba027d54712289af34f0ec0f06092745104d68e5801cd17097bc1104111f855258da070ec9f1c942d9bedf89f9660a684d3bb8cd9c2ac7f6dd883cb3e26a193180244", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x9fb6b81e112638b886", - "nonce": 217865 - }, - "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { - "balance": "0x15b6828e22bb12188", - "nonce": 747 - } - }, - "post": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x9fb71abdd2621d8886" - }, - "0x40f2f445da6c9047554683fb382fba6769717116": { - "code": "0x60606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610044578063cfae32171461005157610042565b005b61004f6004506100ca565b005b61005c60045061015e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156100bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561015b57600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b60206040519081016040528060008152602001506001600050805480601f016020809104026020016040519081016040528092919081815260200182805480156101cd57820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505090506101d9565b9056", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f0c5cef39b17c213cfe090a46b8c7760ffb7928a", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000000000000000001ee", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6": "0x7b225f6964223a225a473466784a7245323639384866623839222c22666f726d", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf7": "0x5f736f75726365223a22434c54523031222c22636f6d6d69746d656e745f6461", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8": "0x7465223a22222c22626f72726f7765725f6e616d65223a22222c22626f72726f", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9": "0x7765725f616464726573735f6c696e6531223a22222c22626f72726f7765725f", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa": "0x616464726573735f6c696e6532223a22222c22626f72726f7765725f636f6e74", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb": "0x616374223a22222c22626f72726f7765725f7374617465223a22222c22626f72", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfc": "0x726f7765725f74797065223a22222c2270726f70657274795f61646472657373", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfd": "0x223a22222c226c6f616e5f616d6f756e745f7772697474656e223a22222c226c", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfe": "0x6f616e5f616d6f756e74223a22222c224c54565f7772697474656e223a22222c", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cff": "0x224c5456223a22222c2244534352223a22222c2270726f70657274795f747970", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d00": "0x65223a22222c2270726f70657274795f6465736372697074696f6e223a22222c", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d01": "0x226c656e646572223a22222c2267756172616e746f7273223a22222c226c696d", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d02": "0x69746564223a22222c226361705f616d6f756e74223a22222c226361705f7065", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d03": "0x7263656e745f7772697474656e223a22222c226361705f70657263656e746167", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d04": "0x65223a22222c227465726d5f7772697474656e223a22222c227465726d223a22", - "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0d05": "0x222c22657874656e64223a22227d000000000000000000000000000000000000" - } - }, - "0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": { - "balance": "0x15b058920efcc5188", - "nonce": 748 - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json deleted file mode 100644 index 561ead05b..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "genesis": { - "baseFeePerGas": "51088069741", - "difficulty": "14315558652874667", - "extraData": "0xd883010a10846765746888676f312e31362e35856c696e7578", - "gasLimit": "30058590", - "hash": "0xdf6b95183f99054fb6541e3b482c0109c9f6be40553cff24efa3ac76736adbf5", - "miner": "0xb7e390864a90b7b923c9f9310c6f98aafe43f707", - "mixHash": "0x8d76b0d32e42ab277dbf00836eabef76674cd70ae2bb53718175069ad6b6147e", - "nonce": "0x8d3a1c010ad2c687", - "number": "14707767", - "stateRoot": "0x8a50c896a6f7eb1f3479337db981fa10ce316281cb4dd2f07487be9ca27dae6b", - "timestamp": "1651623275", - "alloc": { - "0x0000000000000000000000000000000000000000": { - "balance": "0x268fd0b894b8c4f6d1f" - }, - "0x13b152c9f50878ffaf3de41e192653bda545d889": { - "balance": "0x0", - "nonce": "1", - "code": "0x363d3d373d3d3d363d73059ffafdc6ef594230de44f824e2bd0a51ca5ded5af43d82803e903d91602b57fd5bf3" - }, - "0x808b4da0be6c9512e948521452227efc619bea52": { - "balance": "0x2cdb96c56db040b43", - "nonce": "1223932" - }, - "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": { - "balance": "0x38079b28689d40240e", - "nonce": "44" - }, - "0xffa397285ce46fb78c588a9e993286aac68c37cd": { - "balance": "0x0", - "nonce": "747319", - "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063b97a23191461003b578063fb90b3201461006f575b600080fd5b6100436100bd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100bb6004803603604081101561008557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506100e1565b005b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282604051602001808373ffffffffffffffffffffffffffffffffffffffff1660601b815260140182815260200192505050604051602081830303815290604052805190602001209050600061015960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168361024d565b90508073ffffffffffffffffffffffffffffffffffffffff166319ab453c856040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff168152602001915050600060405180830381600087803b1580156101c457600080fd5b505af11580156101d8573d6000803e3d6000fd5b505050507fa35ea2cc726861482a50a162c72aad60965cc64641d419cd4d675036238b52048185604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a150505050565b6000808360601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152836037826000f5925050509291505056fea2646970667358221220c87b2492828fdd7dad3175a32a98ff07fc0eedf106536f2eddd9a016971c56a764736f6c63430007050033", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000059ffafdc6ef594230de44f824e2bd0a51ca5ded" - } - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "terminalTotalDifficultyPassed": true, - "ethash": {} - } - }, - "context": { - "number": "14707768", - "difficulty": "14322823549655084", - "timestamp": "1651623279", - "gasLimit": "30029237", - "miner": "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7" - }, - "input": "0x02f8b4018312acfc8459682f00851a46bcf47a8302b1a194ffa397285ce46fb78c588a9e993286aac68c37cd80b844fb90b3200000000000000000000000002a549b4af9ec39b03142da6dc32221fc390b553300000000000000000000000000000000000000000000000000000000000cb3d5c001a03002079d2873f7963c4278200c43aa71efad262b2150bc8524480acfc38b5faaa077d44aa09d56b9cf99443c7f55aaad1bbae9cfb5bbb9de31eaf7a8f9e623e980", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x808b4da0be6c9512e948521452227efc619bea52": { - "balance": "0x2cdb96c56db040b43", - "nonce": 1223932 - }, - "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": { - "balance": "0x38079b28689d40240e", - "nonce": 44 - } - }, - "post": { - "0x808b4da0be6c9512e948521452227efc619bea52": { - "balance": "0x2cd987071ba2346b6", - "nonce": 1223933 - }, - "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": { - "balance": "0x38079c19423e44b30e" - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_suicide.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_suicide.json deleted file mode 100644 index fdeb0e506..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_suicide.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "genesis": { - "difficulty": "6217248151198", - "extraData": "0xd783010103844765746887676f312e342e32856c696e7578", - "gasLimit": "3141592", - "hash": "0xe8bff55fe3e61936ef321cf3afaeb1ba2f7234e1e89535fa8ae39963caebe9c3", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5", - "mixHash": "0x03da00d5a15a064e5ebddf53cd0aaeb9a8aff0f40c0fb031a74f463d11ec83b8", - "nonce": "0x6575fe08c4167044", - "number": "243825", - "stateRoot": "0x47182fe2e6e740b8a76f82fe5c527d6ad548f805274f21792cf4047235b24fbf", - "timestamp": "1442424328", - "totalDifficulty": "1035061827427752845", - "alloc": { - "0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": { - "balance": "0xc820f93200f4000", - "nonce": "0x5E", - "code": "0x" - }, - "0x332b656504f4eabb44c8617a42af37461a34e9dc": { - "balance": "0x11faea4f35e5af80000", - "code": "0x", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5": { - "balance": "0xbf681825be002ac452", - "nonce": "0x70FA", - "code": "0x" - }, - "0x82effbaaaf28614e55b2ba440fb198e0e5789b0f": { - "balance": "0xb3d0ac5cb94df6f6b0", - "nonce": "0x1", - "code": "0x" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "ethash": {} - } - }, - "context": { - "number": "243826", - "difficulty": "6214212385501", - "timestamp": "1442424353", - "gasLimit": "3141592", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5" - }, - "input": "0xf8e85e850ba43b7400830f42408080b89660606040527382effbaaaf28614e55b2ba440fb198e0e5789b0f600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600a80608c6000396000f30060606040526008565b001ca0340b21661e5bb85a46319a15f33a362e5c0f02faa7cdbf9c5808b2134da968eaa0226e6788f8c20e211d436ab7f6298ef32fa4c23a509eeeaac0880d115c17bc3f", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": { - "balance": "0xc820f93200f4000", - "nonce": 94 - }, - "0x332b656504f4eabb44c8617a42af37461a34e9dc": { - "balance": "0x11faea4f35e5af80000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5": { - "balance": "0xbf681825be002ac452", - "nonce": 28922 - }, - "0x82effbaaaf28614e55b2ba440fb198e0e5789b0f": { - "balance": "0xb3d0ac5cb94df6f6b0", - "nonce": 1 - } - }, - "post": { - "0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": { - "balance": "0xc7d4d88af8b4c00", - "nonce": 95 - }, - "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5": { - "balance": "0xbf681ce7c870aeb852" - }, - "0x82effbaaaf28614e55b2ba440fb198e0e5789b0f": { - "balance": "0x1d37f515017a8eef6b0" - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create.json deleted file mode 100644 index 9c0030a0a..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/inner_create.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "genesis": { - "difficulty": "13707196986889", - "extraData": "0xd983010302844765746887676f312e342e328777696e646f7773", - "gasLimit": "3141592", - "hash": "0x607b38fe7e94427ee8f3b9a62375c67f953f8d49e05dbfd0145f9d3bac142193", - "miner": "0xf8b483dba2c3b7176a3da549ad41a48bb3121069", - "mixHash": "0x98c74c9e76fd0078157e1696e4334a7e787396459693a84536d8b96414dafd5d", - "nonce": "0x77a5a0a73ad8745e", - "number": "1062502", - "stateRoot": "0x1df615df5fdbc8d5397bf3574f462f6d9696428eb8796d8e9252bccc8e3a8996", - "timestamp": "1456480432", - "totalDifficulty": "7948153536501153741", - "alloc": { - "0x0000000000000000000000000000000000000004": { - "balance": "0x0", - "code": "0x" - }, - "0x1deeda36e15ec9e80f3d7414d67a4803ae45fc80": { - "balance": "0x0", - "code": "0x650200d2f18c7350606060405236156100c15760e060020a60003504630bd295e681146100c65780630fd1f94e1461017d5780630fee183d1461018c578063349501b7146101ad5780635054d98a146101c75780637c0278fc146101ef5780637e92656214610287578063a0943154146102f6578063a1873db61461030e578063a9d2293d14610355578063b5d0f16e146103ad578063c17e6817146103ce578063cc3471af1461046a578063da46be0a1461047a578063f55627531461052a575b610007565b6105d36004356024356044355b60006000600030915081600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515191505080841080610173575081600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015060ff16810184115b1561100d57610007565b6105d3600060f0610f6d61046e565b6105d3600435602435604435606435600081600202831015610ff657610fee565b6105d36004355b600081600014156109115750600161098f565b6105d36004355b6008810154600090819062010000900460ff16156105f257600691506105ec565b60408051602060248035600481810135601f81018590048502860185019096528585526105e5958135959194604494929390920191819084018382808284375094965050505050505060006004825103836001016000508181546001816001161561010002031660029004825481601f106108005782601f1061083a575b826008026101000360020a80910402828001178355610851565b6105e5600435602435604051600090600160a060020a038316907f398bd6b21ae4164ec322fb0eb8c2eb6277f36fd41903fbbed594dfe125591281908390a26007830154819010610e415760078301546005840154610e3f9162010000909104600160a060020a0316906103d8565b6105d3600435602435600060006000611064856101ce565b6105d36004356024356044356004830154600090819030908410156110e4577f4e4f545f454e4f5547485f47415300000000000000000000000000000000000091506112dd565b6105d35b60006000309050600a81600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515160091901935050505b5090565b6105d36004356024355b60008282111561099e578183606402049050610998565b6105d36004356024355b600030600160a060020a0316318211156103fa57600160a060020a0330163191505b6000821115610994577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc84846040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100075750839250610998915050565b6105d35b6000600f610f6d610359565b6105e560043560243560443560643560843560088501805461ff00191661010017905584543090600090819081908190819060a060020a900460e060020a02811480156104db575060018b8101546002918116156101000260001901160481145b156109b3578a5460028c0154600160a060020a039190911690895a60405191900391906000818181858888f193505050508b60080160006101000a81548160ff02191690830217905550610bfa565b6105d36004355b6000600060006000309250600a83600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151600919019350505081851115610eb05782600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450610ea89050565b60408051918252519081900360200190f35b005b600291505b50919050565b6008830154610100900460ff161561060d57600591506105ec565b30905080600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515143610109011015905061066457600091506105ec565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515143600a01101590506106d3576005830154620100009004600160a060020a0316600014156105e757600191506105ec565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151431015905061072357600391506105ec565b80600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015060ff1681600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519190910143101590506107bf57600491506105ec565b600791506105ec565b5081800160010183558181151161085157601f016020900481601f016020900483600052602060002091820191016108519190610826565b82601f106107c8575082600052602060002080549082601f016020900481019061090691905b808211156103a95760008155600101610826565b60ff19168360005260206000205581800160010183555b5050505060048251111561090c575060005b6001838101546002918116156101000260001901160481101561090c57818160040181518110156100075790602001015160f860020a900460f860020a02836001016000508281546001816001161561010002031660029004811015610007578154600116156108e25790600052602060002090602091828204019190065b601f036101000a81548160ff0219169060f860020a84040217905550600101610863565b5061026d565b505050565b604080517f5f5f6469672875696e74323536290000000000000000000000000000000000008152815190819003600e01812060e060020a9081900481028190049081028252600019850160048301529151600160a060020a03301692916102bc86029160248281019260009291908290030181838887f19450505050505b919050565b5060005b92915050565b818360020203836064020460c8039050610998565b8a5460a060020a900460e060020a0260001415610a23578a5460028c0154600160a060020a039190911690895a03908d6001016000506040518082805460018160011615610100020316600290048015610ae55780601f10610aba57610100808354040283529160200191610ae5565b60018b8101546002918116156101000260001901160460001415610b1a578a5460028c0154600160a060020a039190911690895a03908d60000160149054906101000a900460e060020a0260e060020a900491906040518360e060020a028152600401809050600060405180830381858988f19450505050508b60080160006101000a81548160ff02191690830217905550610bfa565b820191906000526020600020905b815481529060010190602001808311610ac857829003601f168201915b5050915050600060405180830381858888f193505050508b60080160006101000a81548160ff02191690830217905550610bfa565b8a5460028c0154600160a060020a039190911690895a03908d60000160149054906101000a900460e060020a0260e060020a900491908e6001016000506040518460e060020a0281526004018082805460018160011615610100020316600290048015610bc85780601f10610b9d57610100808354040283529160200191610bc8565b820191906000526020600020905b815481529060010190602001808311610bab57829003601f168201915b5050915050600060405180830381858988f19450505050508b60080160006101000a81548160ff021916908302179055505b85600160a060020a031663938b5f326040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750505060405180519060200150600160a060020a031660405180807f75706461746544656661756c745061796d656e742829000000000000000000008152602001506016019050604051809103902060e060020a8091040260e060020a90046040518160e060020a0281526004018090506000604051808303816000876161da5a03f15050505060038b0154610cc8903a6103b7565b60058c0154909550620100009004600160a060020a03908116908a161415610cf65760068b01549350610d38565b85600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450505b6064858502048b6007016000505401925060648587600160a060020a031663625cc4656040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505050604051805190602001500204915060008b60070160005081905550865a8b03013a029050610db7898285016103d8565b9250610dd773d3cda913deb6f67967b99d67acdfa1712c293601836103d8565b6040805160088e01548482526020820187905281830184905260ff1660608201529051919350600160a060020a038b16917f4538b7ec91dae8fada01e66a052482086d3e690c3db5a80457fbcd55457b4ae19181900360800190a25050505050505050505050565b505b309050610e8c81600160a060020a031663ae45850b6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040515190316103d8565b505050600801805462ff0000191662010000179055565b600093505b505050919050565b600e19919091019081851115610f075782600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051519450610ea89050565b60ef19919091019081851115610ea357818503905060f08184600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050506040518051906020015002049350610ea8565b03905090565b6006860181905560058601805475ffffffffffffffffffffffffffffffffffffffff000019166201000087021790556007860184905560408051600160a060020a0387168152602081019290925280517fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9281900390910190a15b949350505050565b610f7343610531565b600192505b50509392505050565b60108185031015610fff576005860154620100009004600160a060020a03166000148061105057506005860154620100009004600160a060020a03908116908616145b9250611004565b600092505b505092915050565b91503090506000821480156110c4575080600160a060020a031663ae45850b6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505060405151600160a060020a039081169086161490505b156110d2576001925061105c565b6007821415611057576001925061105c565b6008860154610100900460ff161561111e577f414c52454144595f43414c4c454400000000000000000000000000000000000091506112dd565b80600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610007575050604051514310905080611206575080600160a060020a031663a06db7dc6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100075750506040805180517f0a16697a000000000000000000000000000000000000000000000000000000008252915160ff9092169291630a16697a9160048181019260209290919082900301816000876161da5a03f1156100075750506040515191909101431190505b15611233577f4e4f545f494e5f43414c4c5f57494e444f57000000000000000000000000000091506112dd565b61123e8686436100d3565b151561126c577f4e4f545f415554484f52495a454400000000000000000000000000000000000091506112dd565b6005860154600061ffff91909116118015611299575032600160a060020a031685600160a060020a031614155b80156112b4575060058601546112b29061ffff166101b4565b155b156112dd577f535441434b5f544f4f5f4445455000000000000000000000000000000000000091505b60008214610fff5760408051600160a060020a03871681526020810184905281517fdcb278834ca505ad219cf8e4b5d11f026080abef6ec68e249ea5e4d9bb3dc7b2929181900390910190a16000925061100456" - }, - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x98e1c608601c2496b2", - "nonce": "218916", - "code": "0x" - }, - "0x651913977e8140c323997fce5e03c19e0015eebf": { - "balance": "0x0", - "code": "0x", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { - "balance": "0x0", - "nonce": "237", - "code": "0x6060604052361561027c5760e060020a600035046301991313811461027e57806303d22885146102ca5780630450991814610323578063049ae734146103705780630ce46c43146103c35780630e85023914610602578063112e39a8146106755780631b4fa6ab146106c25780631e74a2d3146106d057806326a7985a146106fd5780633017fe2414610753578063346cabbc1461075c578063373a1bc3146107d55780633a9e74331461081e5780633c2c21a01461086e5780633d9ce89b146108ba578063480b70bd1461092f578063481078431461097e57806348f0518714610a0e5780634c471cde14610a865780634db3da8314610b09578063523ccfa814610b4f578063586a69fa14610be05780635a9f2def14610c3657806364ee49fe14610caf57806367beaccb14610d055780636840246014610d74578063795b9a6f14610dca5780637b55c8b514610e415780637c73f84614610ee15780638c0e156d14610f145780638c1d01c814610f605780638e46afa914610f69578063938c430714610fc0578063971c803f146111555780639772c982146111ac57806398c9cdf41461122857806398e00e541461127f5780639f927be7146112d5578063a00aede914611383578063a1c0539d146113d3578063aff21c6514611449578063b152f19e14611474578063b549793d146114cb578063b5b33eda1461154b578063bbc6eb1f1461159b578063c0f68859146115ab578063c3a2c0c314611601578063c43d05751461164b578063d8e5c04814611694578063dbfef71014611228578063e29fb547146116e7578063e6470fbe1461173a578063ea27a8811461174c578063ee77fe86146117d1578063f158458c14611851575b005b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387876020604051908101604052806000815260200150612225610f6d565b61188260043560243560443560643560843560a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338b8a6020604051908101604052806000815260200150896125196106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a026020604051908101604052806000815260200150611e4a610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503389896020604051908101604052806000815260200150886124e86106c6565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750506040805160a08082019092529597963596608435969095506101449450925060a491506005908390839080828437509095505050505050604080518082018252600160a060020a03338116825288166020820152815160c0810190925260009173e54d323f9ef17c1f0dede47ecc86a9718fe5ea349163e3042c0f91600191908a908a9089908b90808b8b9090602002015181526020018b60016005811015610002579090602002015181526020018b60026005811015610002579090602002015181526020018b60036005811015610002579090602002015181526020018b6004600581101561000257909060200201518152602001348152602001506040518860e060020a02815260040180888152602001876002602002808383829060006004602084601f0104600f02600301f150905001868152602001806020018560ff1681526020018461ffff168152602001836006602002808383829060006004602084601f0104600f02600301f1509050018281038252868181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d25780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038160008760325a03f2156100025750506040515191506124cd9050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808787611e64610f6d565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611d28610f6d565b61189f5b6000611bf8611159565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881600060005054611a9561159f565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346326a7985a6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b760075b90565b604080516020606435600481810135601f8101849004840285018401909552848452611882948135946024803595604435956084949201919081908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160013389898861224b610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386866020604051908101604052806000815260200150611e64610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333896020604051908101604052806000815260200150886123bc6106c6565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387866020604051908101604052806000815260200150611f8d610f6d565b60408051602060248035600481810135601f810185900485028601850190965285855261188295813595919460449492939092019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808888612225610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503388886020604051908101604052806000815260200150612388610f6d565b611882600435604080517fc4144b2600000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163c4144b26916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133888888612238610f6d565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338b8b8b896126536106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333866020604051908101604052806000815260200150611e4a610f6d565b6118b76004355b604080517fed5bd7ea00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163ed5bd7ea916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b61189f600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463586a69fa6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650509335935050606435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808989612388610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a896020604051908101604052806000815260200150886124d76106c6565b6040805160206004803580820135601f8101849004840285018401909552848452611882949193602493909291840191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808587611e4a610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a8a60206040519081016040528060008152602001508961262d6106c6565b604080516020606435600481810135601f810184900484028501840190955284845261188294813594602480359560443595608494920191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338888876120c7610f6d565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437505060408051608080820190925295979635969561010495509350608492508591508390839080828437509095505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989898961263a6106c6565b6118b7600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881858585611ba361122c565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050333388602060405190810160405280600081526020015061236e610f6d565b6118b760005481565b6118c95b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea34638e46afa96040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a43560c43560e43561010435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338e8e8d8f8e8e8e8e8e346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156111195780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519b9a5050505050505050505050565b61189f5b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463971c803f6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650509335935050608435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989896123a2610f6d565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398c9cdf46040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398e00e546040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600435604080517fe6ce3a6a000000000000000000000000000000000000000000000000000000008152600160048201527f3e3d0000000000000000000000000000000000000000000000000000000000006024820152604481018390529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163e6ce3a6a916064818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a0260206040519081016040528060008152602001506121ef610f6d565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338787876120b5610f6d565b6118b7600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88183611b4561159f565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463b152f19e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808b8b8961262d6106c6565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386600060e060020a026020604051908101604052806000815260200150612200610f6d565b6118b75b60005460649004610759565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463c0f688596040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611bff610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333876020604051908101604052806000815260200150612200610f6d565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387600060e060020a026020604051908101604052806000815260200150612213610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338a60206040519081016040528060008152602001508961250c6106c6565b61027c6000600060006118e033610b56565b6118b7600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881868686866040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b949350505050565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338a8a8a886124fa6106c6565b6118b7600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88184846000611b4f61122c565b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b15611a905733925082600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fc6803622000000000000000000000000000000000000000000000000000000008252915191945063c680362291600482810192602092919082900301816000876161da5a03f11561000257505060405151905080156119d1575082600160a060020a031663d379be236040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a03166000141590505b80156119dd5750600082115b80156119ec5750600054600190115b15611a90578183600160a060020a031663830953ab6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040515160640291909104915050604281118015611a4d5750600054829011155b15611a675760008054612710612711909102049055611a90565b602181108015611a7a5750600054829010155b15611a90576000805461271061270f9091020490555b505050565b6000611a9f61122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b919050565b6000611af261122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b9392505050565b9050610759565b611c076106c6565b6000611c11611478565b611c1961122c565b600054611c2461159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611cf25780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b611d306106c6565b60008b611d3b61122c565b600054611d4661159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611e145780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b409050565b611e526106c6565b6000611e5c611478565b611d3b61122c565b611e6c6106c6565b6000611e76611478565b611e7e61122c565b600054611e8961159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611f575780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b9d9050565b611f956106c6565b8b611f9e611478565b611fa661122c565b600054611fb161159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561207f5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611bf19050565b6120bd6106c6565b6000611f9e611478565b6120cf6106c6565b8b6120d8611478565b6120e061122c565b6000546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156121b95780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506117c99050565b6121f76106c6565b8b611e76611478565b6122086106c6565b60008b611e7e61122c565b61221b6106c6565b8a8c611fa661122c565b61222d6106c6565b60008b611fa661122c565b6122406106c6565b60008b6120e061122c565b6122536106c6565b8c8b61225d61122c565b60005461226861159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156123365780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f21561000257505060405151979650505050505050565b6123766106c6565b60008c8c600060005054611fb161159f565b6123906106c6565b60008c8c6000600050546120eb61159f565b6123aa6106c6565b60008c8c60006000505461226861159f565b60008d8d6000600050546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561249c5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150505b9695505050505050565b8e8d8d6000600050546123ce61159f565b60008d8d60006000505461226861159f565b60008d8d6000600050546123ce61159f565b60008e8e8d61226861159f565b8f8e8e8d61252561159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156125f35780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519998505050505050505050565b60008e8e8d6123ce61159f565b8a5160208c015160408d015160608e015161226861159f565b60008e8e8d61252561159f56", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000011f8119429ed3a", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", - "0x031b9ec274101cc3ccff4d6d98ef4513742dadbaadba538bff48b88403253234": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x20ef51bb8ea9e8e8d5e2c17d28e47285698893c1017db4b4e40b792358a3dbc7": "0x0000000000000000000000000000000000000000000000000000000000000004", - "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abd": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", - "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abf": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8ac2": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfb": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfc": "0x00000000000000000000000000000000000000000000000000000000000f6897", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfd": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dfe": "0x0000000000000000000000002859ddf2877c46d54e67b6becdb1cafb8ef4a458", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794dff": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", - "0x37a551428681c06e6f97b79bb6c8c325935dc1a51b31a982594f40f2dd794e00": "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x3b20a4b931bc4ae9450774ee52b8f5da1b248d23e61cd20c09b25662f73894fd": "0x0000000000000000000000000000000000000000000000000000000000000006", - "0x3b99aee1e3090227401ac2055c861246ca6ec62f426b4b4d74df88510f841b89": "0x0000000000000000000000000000000000000000000000000000000000000007", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef711": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef712": "0x0000000000000000000000000000000000000000000000000000000000102ce9", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef713": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef714": "0x00000000000000000000000016917c151bb1399852a0741eb7b317b443e2cfa3", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef715": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef716": "0x0000000000000000000000000000000000000000000000000000000000000004", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a3fe": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a3ff": "0x00000000000000000000000000000000000000000000000000000000000fff67", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a400": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a401": "0x00000000000000000000000010fc2e8ba5f40336c3576ffaa25177f1cdedf836", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a402": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", - "0x5d866e5ddc53cb4c50f232302c51f03204d70c867baf663c9211cc229676a403": "0x0000000000000000000000000000000000000000000000000000000000000006", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5ba": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bb": "0x000000000000000000000000000000000000000000000000000000000010347b", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bc": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bd": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5be": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bf": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2751": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2752": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2753": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2754": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2755": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2756": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a7": "0x000000000000000000000000b7df3c43a8b13ecf45777c267404e15c7cdb04c9", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a8": "0x00000000000000000000000000000000000000000000000000000000000fe13d", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826a9": "0x000000000000000000000000f5d861791e76fa01433e0d7421aee565290e4afe", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826aa": "0x00000000000000000000000063110531142fb314118164ff579ba52746504408", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826ab": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", - "0xa9e249fecbfa0518be95c32972ad551c71206081844335006bb2a349490826ac": "0x0000000000000000000000000000000000000000000000000000000000000007", - "0xac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c890780": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xccd2cbc946692be8ade97db99353304e3af0fa6202f93649d4e185ad8b1f385c": "0x0000000000000000000000000000000000000000000000000000000000000004", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4ef": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f0": "0x00000000000000000000000000000000000000000000000000000000001030b3", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f1": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f2": "0x000000000000000000000000dd87a67740c2acf48a31829783a095a81c3628d9", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f3": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f4": "0x0000000000000000000000000000000000000000000000000000000000000003", - "0xdabde47554d6a6cfcff3c968abb145f298585fafa9e24c10fc526269794bd626": "0x0000000000000000000000000000000000000000000000000000000000000003", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db7": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db8": "0x000000000000000000000000000000000000000000000000000000000010365c", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64db9": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dba": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbb": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbc": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdec": "0x000000000000000000000000fd97a0d81cc92eecd52452831930b27889925ef0", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bded": "0x0000000000000000000000000000000000000000000000000000000000101dc2", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdee": "0x000000000000000000000000c5ef24ec3bf0e3522cfc8e53f3e076b043547ce1", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdef": "0x000000000000000000000000173243e117a6382211b1ac91eeb262f4a7021c16", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdf0": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", - "0xfbba286dd5525a6ed3322411df4f261c98e43b123fef71777adc2b44d705bdf1": "0x0000000000000000000000000000000000000000000000000000000000000005" - } - }, - "0x741467b251fca923d6229c4b439078b55dca233b": { - "balance": "0x29c613529e8218f8", - "code": "0x606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000007dd677b54fc954824a7bc49bd26cbdfa12c75adf", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000011f79bd42b0c7c", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000002dfeff8fca5d", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000003defb9627dd677b54fc954824a7bc49bd26cbdfa12c75adf", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000ba43b7400", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x00000000000000000000000000000000000000000000000000000000001e8480", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000a", - "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000006c8f2a135f6ed072de4503bd7c4999a1a17f824b", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x000000000000000000000000000000000000000000000000000000000010365c", - "0x000000000000000000000000000000000000000000000000000000000000000e": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "0x7c1eb207c07e7ab13cf245585bd03d0fa478d034": { - "balance": "0x0", - "code": "0x650200d2f18c7350606060405236156100a05760e060020a60003504630e9f1a3c81146100a55780632b4096b4146100c95780636ec13982146100eb578063a3119e571461010d578063a749f19b1461012f578063ab7366f714610151578063bacd69581461017f578063bfdf87c0146101c2578063c4144b26146101e1578063caa46c9c1461023c578063e6ce3a6a14610297578063ed5bd7ea146102b6575b610007565b6102d960043560243560008181526001830160205260409020600401545b92915050565b6102d960043560243560008181526001830160205260409020600301546100c3565b6102d960043560243560008181526001830160205260409020600201546100c3565b6102d960043560243560008181526001838101602052604090912001546100c3565b6102d960043560243560008181526001830160205260409020600501546100c3565b6102eb6004356024355b600081815260018301602052604081208054829182918291908614610790576101b9565b6102eb600435602435604435600082815260018401602052604081205481908190819086141561068a576040812060010154851415610680575b50505050505050565b6102d960043560243560008181526001830160205260409020546100c3565b6102d96004356024355b6040805160c08101825260008082526020828101829052828401829052606083018290526080830182905260a08301829052848252600186019052918220805490919083908114156102fb576102f2565b6102d96004356024355b6040805160c08101825260008082526020828101829052828401829052606083018290526080830182905260a08301829052848252600186019052918220805490919083908114156104c0576102f2565b6102d960043560243560443582546000908181811415610a6557610a8c565b6102d96004356024356000818152600183016020526040812060050154116100c3565b60408051918252519081900360200190f35b005b815193505b50505092915050565b60048301546000146103d257600483810154600090815260018881016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015460608201529181015460808301526005015460a082015291505b60608201516000146102ed57606091820151600090815260018781016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015493810193909352600481015460808401526005015460a0830152610364565b600283015460001461045b5750506002810154600081815260018681016020908152604092839020835160c081018552865481529286015491830191909152918101929092526003830154606083015260048301546080830152600583015460a08301525b81516003820154141561044d57805493506102f2565b600281015460001415610464575b600093506102f2565b6040805160c08101825282548152600183810154602083810191909152600285015483850181905260038601546060850152600486015460808501526005959095015460a0840152600094855290890190529120909150610437565b600383015460001461059757600383810154600090815260018881016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252918101546060830152600481015460808301526005015460a082015291505b60808201516000146102ed57608091820151600090815260018781016020908152604092839020835160c081018552815481529281015491830191909152600281015492820192909252600382015460608201526004820154938101939093526005015460a0830152610529565b600283015460001461045b5750506002810154600081815260018681016020908152604092839020835160c081018552865481529286015491830191909152918101929092526003830154606083015260048301546080830152600583015460a08301525b81516004820154141561061257805493506102f2565b6002810154600014156106245761045b565b6040805160c08101825282548152600183810154602083810191909152600285015483850181905260038601546060850152600486015460808501526005959095015460a08401526000948552908901905291209091506105fc565b61068a878761015b565b86546000925082141561069b578587555b508554600090815260018701602052604090205b8054600014156107255785815560028101829055600181018590556101b987875b60008181526001830160205260408120905b8154610d8e9085905b60008181526001830160205260408082206004810154835281832060059081015460038301548552929093209092015403905b5092915050565b60018101548154925085126107625760048101546000141561074957600481018690555b60040154600090815260018701602052604090206106af565b60038101546000141561077757600381018690555b60030154600090815260018701602052604090206106af565b600381015460001415806107a957506004810154600014155b156107cf576003810154600014610826578054600188019060009061083b908a90610246565b6002810154600014610a285760028101546000908152600188016020526040902060038101548254919550141561080857600060038501555b60048401548154141561081d57600060048501555b83549150610a2d565b80546001880190600090610852908a906101eb565b815260208101919091526040016000209450610865565b8152602081019190915260400160002094505b600285015460009081526001880160205260409020600381015486549195509092508214156108b9576004850154600385018190556000146108b95760048501546000908152604090208454600282015592505b60048401548554141561091357600385015460048501819055600014610913578660010160005060008660030160005054815260200190815260200160002060005092508250836000016000505483600201600050819055505b60028082015490860181905560001461098457866001016000506000826002016000505481526020019081526020016000206000509350835080600001600050548460030160005054141561096a57845460038501555b60048401548154141561097f57845460048501555b610989565b845487555b6003818101549086018190556000146109d6578660010160005060008260030160005054815260200190815260200160002060005092508250846000016000505483600201600050819055505b600481810154908601819055600014610a23578660010160005060008260040160005054815260200190815260200160002060005092508250846000016000505483600201600050819055505b610a2d565b600087555b6000808255600182018190556002820181905560038201819055600482018190556005820181905582146101b9576101b987836106d0565b50600081815260018601602052604090205b6001810154610a95908686610ad4565b805492505b50509392505050565b15610b915760fa60020a600f02851480610ab6575060f060020a613c3d0285145b15610af157600481015460001415610b3a5780549250610a8c565b86865b600060f960020a601f02831415610ce357508083135b9392505050565b60f960020a601f02851480610b0d575060f060020a613e3d0285145b80610b1f575060f060020a613d3d0285145b15610b9157600381015460001415610bc85780549250610a8c565b610b73610ad1878360040160005054600081815260018301602052604081205b600381015460001415610d61576001810154915061071e565b15610a87576004015460009081526001860160205260409020610a77565b60fa60020a600f02851480610bad575060f060020a613c3d0285145b15610c1f57600381015460001415610c565760009250610a8c565b610c01610ad1878360030160005054600081815260018301602052604081205b600481015460001415610d48576001810154915061071e565b15610a87576003015460009081526001860160205260409020610a77565b60f960020a601f02851480610c3b575060f060020a613e3d0285145b15610c6f57600481015460001415610ca25760009250610a8c565b6003015460009081526001860160205260409020610a77565b60f060020a613d3d02851415610cde57600181015484901215610cbb57600481015460001415610ca25760009250610a8c565b6004015460009081526001860160205260409020610a77565b600181015484901315610cde57600381015460001415610c565760009250610a8c565b610a77565b60fa60020a600f02831415610cfb5750808312610aea565b60f060020a613e3d02831415610d15575080831215610aea565b60f060020a613c3d02831415610d2f575080831315610aea565b60f060020a613d3d028314156100a05750828114610aea565b6004015460009081526001840160205260409020610be8565b6003015460009081526001840160205260409020610b5a565b600282015460001415610fbd575b50505050565b90508060021415610e2657610daa8483600301600050546106eb565b6000191415610dc457610dc4848360030160005054610dfe565b8154610e269085905b60008181526001830160205260408120600381015490919081908190811415610ffb57610007565b8154610e5a9085905b60008181526001830160205260408120600481015490919081908190811415610e7f57610007565b806001191415610e5a57610e418483600401600050546106eb565b60011415610df557610df5848360040160005054610dcd565b8060001913158015610e6d575060018113155b15610d7a578154610d7a908590610f7a565b6004840180546000908152600188016020526040812060028088015490820181905592829055945014610f0f57856001016000506000856002016000505481526020019081526020016000206000509150836000016000505482600301600050541415610efa57826000016000505482600301600050819055505b835460048301541415610f0f57825460048301555b6003830154600014610f40575060038201546000908152600186016020526040902080546004850155835460028201555b82546002808601919091558454600385015583015460001415610f7157826000016000505486600001600050819055505b8354610fe69087905b6000818152600183016020526040808220600381015483528183206005908101546004830154855292842001549092610fd99291908183106110fa5750816100c3565b60029091015460009081526001840160205260409020906106e2565b6001016005820155505050565b8254610ff3908790610f7a565b505050505050565b600384018054600090815260018801602052604081206002808801549082018190559282905594501461108b5785600101600050600085600201600050548152602001908152602001600020600050915083600001600050548260030160005054141561107657826000016000505482600301600050819055505b83546004830154141561108b57825460048301555b60048301546000146110bd57506004820154600081815260018701602052604090206003850191909155835460028201555b82546002808601919091558454600485015583015460001415610f7157826000016000505486600001600050819055508354610fe6908790610f7a565b50806100c356" - }, - "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { - "balance": "0xd7a58f5b73b4b6c4", - "code": "0x606060405236156100985760e060020a60003504633896002781146100e15780633defb962146100ea5780633f4be8891461010c5780634136aa351461011f5780634a420138146101a057806369c1a7121461028c5780638129fc1c146102955780638da5cb5b146102a6578063ae45850b146102b8578063af3309d8146102cc578063ea8a1af0146102d5578063ead50da3146102f4575b610308671bc16d674ec8000030600160a060020a03163110156100df57600554604051600160a060020a03918216916000913091909116319082818181858883f150505050505b565b61030a60005481565b610308671bc16d674ec8000030600160a060020a031631101561040f576100df565b61031c600454600160a060020a03165b90565b61030a5b600080548190118015610199575060408051600480547f0a16697a0000000000000000000000000000000000000000000000000000000083529251600160a060020a039390931692630a16697a928083019260209291829003018187876161da5a03f1156100025750506040515160ff01431090505b905061011c565b6103085b600354600554604080517f8c0e156d0000000000000000000000000000000000000000000000000000000081527f3defb96200000000000000000000000000000000000000000000000000000000600482015260a060020a90920461ffff1643016024830152621e8480604483015251600092600160a060020a031691638c0e156d916729a2241af62c000091606481810192602092909190829003018185886185025a03f1156100025750506040515192600160a060020a0384161491506102899050576004805473ffffffffffffffffffffffffffffffffffffffff1916821790555b50565b61030a60015481565b61030860008054146103f2576100df565b61031c600554600160a060020a031681565b61031c600354600160a060020a031661011c565b61030a60025481565b610308600554600160a060020a03908116339091161461035157610002565b61033960055460a060020a900461ffff1681565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b6004546000600160a060020a03919091163111156103c75760408051600480547fea8a1af00000000000000000000000000000000000000000000000000000000083529251600160a060020a03939093169263ea8a1af0928083019260009291829003018183876161da5a03f115610002575050505b600554604051600160a060020a03918216916000913091909116319082818181858883f15050505050565b426000556100df6101a4565b600280546001908101909155429055565b600454600160a060020a03908116339091161461042b576100df565b610433610123565b151561043e576100df565b6103fe6101a456", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000056be5b99", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000056d0009b", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000008b", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000006c8f2a135f6ed072de4503bd7c4999a1a17f824b", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000001e0d3cda913deb6f67967b99d67acdfa1712c293601" - } - }, - "0x89efe605e9ecbe22849cd85d5449cc946c26f8f3": { - "balance": "0x0", - "code": "0x650200d2f18c73506060604052361561007f5760e060020a600035046312c82bcc81146100845780635548c837146100a55780635c54305e146101015780636b103966146101555780637fcf532c14610189578063b1df3d80146101d5578063b5bc6dbb146101ee578063c6ab451414610225578063e62af6c114610293575b610007565b6102c56004356024356000620186a05a10156103855761030083835a610232565b6102d760043560243560443581600160a060020a031683600160a060020a03167f47a08955ce2b7f21ea62ff0024e1ea0ad87430953554a87e6bc65d777f18e639836040518082815260200191505060405180910390a3505050565b6102d760043560243560443560408051838152602081018390528151600160a060020a038616927f9b24879829bed3003de08d5c5d7e18dcbb8dc76faebd95cafc5d4dec8c61a3a5928290030190a2505050565b6102d76004356024356044355b600160a060020a03821660009081526020849052604090205480820110156102d957610007565b6102d7600435602435604080518281529051600160a060020a038416917fd0c5cf41ee8ebf084ad0bce53de7cbc6e4693d9b53a4019ca36a2f91cdc20b3a919081900360200190a25050565b6102c560043560243560443560006102fc848484610162565b6102c5600435602435604435600160a060020a03821660009081526020849052604081205482901061032b576103338484846102a0565b6102c56004356024356044355b60006000831180156102605750604051600160a060020a038516908290859082818181858883f19350505050155b156102fc57604051600160a060020a03851690839085906000818181858888f1935050505015156102fc57506000610300565b6102d76004356024356044355b600160a060020a03821660009081526020849052604090205481111561030757610007565b60408051918252519081900360200190f35b005b600160a060020a0382166000908152602084905260409020805482019055505050565b5060015b9392505050565b600160a060020a038216600090815260208490526040902080548290039055505050565b506000610300565b604051600160a060020a03841690600090849082818181858883f1935050505015156102fc57604051600160a060020a038416908390600081818185876185025a03f19250505015156102fc57610007565b6103008383620186a061023256" - }, - "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { - "balance": "0xffe9b09a5c474dca", - "nonce": "975", - "code": "0x" - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x4f5807198e238f13e", - "nonce": "283", - "code": "0x" - }, - "0xe54d323f9ef17c1f0dede47ecc86a9718fe5ea34": { - "balance": "0x0", - "code": "0x650200d2f18c7350606060405236156100ab5760e060020a600035046326a7985a81146100b057806350d4e411146100be57806354fd4d501461023d578063586a69fa1461025d5780638e46afa91461026857806396cff3df14610272578063971c803f1461029657806398c9cdf4146102a157806398e00e54146102ae578063b152f19e146102b8578063c0f68859146102c4578063e3042c0f146102cf578063ea27a88114610461575b610007565b6102845b60006104cb6102a5565b604080516020601f60843560048181013592830184900484028501840190955281845261047f948035946024803595604435956064359560a494930191819084018382808284375094965050933593505060c43591505060e435610104356101243561014435610164356101843560006101806040519081016040528060008152602001600081526020016000815260200160206040519081016040528060008152602001508152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200150610180604051908101604052808f81526020018e81526020018d81526020018c81526020018981526020018b81526020018a81526020018881526020018781526020018681526020018581526020018481526020015090506104d48f825b600060006000600a43018460e0015110156105de577f544f4f5f534f4f4e0000000000000000000000000000000000000000000000009150610524565b604080516000808252600760208301528183015290519081900360600190f35b61049c5b6103e85b90565b6104b460ff610265565b62030d403a0260026024356004350102015b60408051918252519081900360200190f35b61049c5b600a610265565b6102845b62030d40610265565b6102846010610265565b61028443600a01610265565b6102845b6020610265565b60408051808201825261047f916004803592909160649190602490600290839083908082843780516020601f608435808c01359182018390048302840183019094528083529499983598975060a49650909450910191908190840183828082843750506040805160c0818101909252959796359660c435969095506101a49450925060e491506006908390839080828437509095505050505050604080516101808181018352600080835260208381018290528385018290528451908101855281815260608401526080830181905260a0830181905260c0830181905260e0830181905261010083018190526101208301819052610140830181905261016083018190528351918201909352808984505181526020018960015060209081015182528101899052604081018890526060018484505181526020810187905260408101869052606001846001506020908101518252018460025060400151815260200184600350606001518152602001846004506080015181526020018460055060a00151905290506104e78982610200565b6102846004356024356044356064355b3a0291909201600202010190565b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b6040805160ff929092168252519081900360200190f35b45039050610265565b9f9e505050505050505050505050505050565b9998505050505050505050565b8461016001511015610524577f494e53554646494349454e545f46554e4453000000000000000000000000000091505b600082146106ed576040805185518482529151600160a060020a0392909216917f513485fc54ef019ef1bc1ea683ef7d5d522f2865224ae10871ff992749c0ba4f9181900360200190a27389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc85600001518661016001516040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f215610007575050505b505092915050565b8360c0015161ffff166105ef61029a565b61ffff1611806106115750610602610261565b61ffff168460c0015161ffff16115b1561063e577f535441434b5f434845434b5f4f55545f4f465f52414e474500000000000000009150610524565b6106466102c8565b8460a0015160ff16101561067c577f47524143455f544f4f5f53484f525400000000000000000000000000000000009150610524565b6106846102a5565b84610100015110806106a157506106996100b4565b846101000151115b156106ce577f52455155495245445f4741535f4f55545f4f465f52414e4745000000000000009150610524565b6104f48461012001518561014001518660800151876101000151610471565b83610160015184600001518560e001518660a001518760200151886040015189606001518a608001518b61010001518c60c001518d61012001518e6101400151604051611078806108fa833901808c600160a060020a031681526020018b81526020018a60ff16815260200189600160a060020a03168152602001888152602001806020018781526020018681526020018561ffff1681526020018481526020018381526020018281038252888181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156107ec5780820380516001836020036101000a031916815260200191505b509c505050505050505050505050506040518091039082f090509050737c1eb207c07e7ab13cf245585bd03d0fa478d03463bacd69588683600160a060020a031660010284600160a060020a0316630a16697a6040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000757505050604051805190602001506040518460e060020a02815260040180848152602001838152602001828152602001935050505060006040518083038160008760325a03f21561000757505060408051600160a060020a038416815290517f2b05d346f0b0b9fd470024751c52d3b5dac5c37796f077c1a66241f2eada44b792509081900360200190a18092506105d656606060405260405161107838038061107883398101604052805160805160a05160c05160e05161010051610120516101405161016051610180516101a051999a98999798969795969490940194929391929091908a84848a8a8a8a88886101008051600c8054600160a060020a031990811633179091556000805482168d1781556001868155600286815560078e90556008805461ffff19168e1790553a600655600380547c01000000000000000000000000000000000000000000000000000000008d04740100000000000000000000000000000000000000000260a060020a63ffffffff0219919096168e17169490941790935588516004805493819052956020601f9385161590910260001901909316939093048101919091047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b908101939091608091909101908390106101ee57805160ff19168380011785555b5061017a9291505b8082111561021e5760008155600101610166565b5050826003600050600201600050819055505050505050505050508a600060006101000a815481600160a060020a030219169083021790555089600d6000508190555088600e60006101000a81548160ff021916908302179055505050505050505050505050610e56806102226000396000f35b8280016001018555821561015e579182015b8281111561015e578251826000505591602001919060010190610200565b509056606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "ethash": {} - } - }, - "context": { - "number": "1062503", - "difficulty": "13700504019867", - "timestamp": "1456480446", - "gasLimit": "3141592", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" - }, - "input": "0xf86b8203cf850ba43b740083200b2094741467b251fca923d6229c4b439078b55dca233b8084614619541ca078293714f69a810356f1ee29dc686ec2ca3a0e5448e1ef6322c77369ebdd26c2a01c3836fa363548959554ee5360361be9db4aea9eb7c31f61550f0e9a10138adf", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x98e1c608601c2496b2", - "nonce": 218916 - }, - "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { - "balance": "0x0", - "nonce": 237, - "code": "0x6060604052361561027c5760e060020a600035046301991313811461027e57806303d22885146102ca5780630450991814610323578063049ae734146103705780630ce46c43146103c35780630e85023914610602578063112e39a8146106755780631b4fa6ab146106c25780631e74a2d3146106d057806326a7985a146106fd5780633017fe2414610753578063346cabbc1461075c578063373a1bc3146107d55780633a9e74331461081e5780633c2c21a01461086e5780633d9ce89b146108ba578063480b70bd1461092f578063481078431461097e57806348f0518714610a0e5780634c471cde14610a865780634db3da8314610b09578063523ccfa814610b4f578063586a69fa14610be05780635a9f2def14610c3657806364ee49fe14610caf57806367beaccb14610d055780636840246014610d74578063795b9a6f14610dca5780637b55c8b514610e415780637c73f84614610ee15780638c0e156d14610f145780638c1d01c814610f605780638e46afa914610f69578063938c430714610fc0578063971c803f146111555780639772c982146111ac57806398c9cdf41461122857806398e00e541461127f5780639f927be7146112d5578063a00aede914611383578063a1c0539d146113d3578063aff21c6514611449578063b152f19e14611474578063b549793d146114cb578063b5b33eda1461154b578063bbc6eb1f1461159b578063c0f68859146115ab578063c3a2c0c314611601578063c43d05751461164b578063d8e5c04814611694578063dbfef71014611228578063e29fb547146116e7578063e6470fbe1461173a578063ea27a8811461174c578063ee77fe86146117d1578063f158458c14611851575b005b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387876020604051908101604052806000815260200150612225610f6d565b61188260043560243560443560643560843560a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338b8a6020604051908101604052806000815260200150896125196106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a026020604051908101604052806000815260200150611e4a610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503389896020604051908101604052806000815260200150886124e86106c6565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750506040805160a08082019092529597963596608435969095506101449450925060a491506005908390839080828437509095505050505050604080518082018252600160a060020a03338116825288166020820152815160c0810190925260009173e54d323f9ef17c1f0dede47ecc86a9718fe5ea349163e3042c0f91600191908a908a9089908b90808b8b9090602002015181526020018b60016005811015610002579090602002015181526020018b60026005811015610002579090602002015181526020018b60036005811015610002579090602002015181526020018b6004600581101561000257909060200201518152602001348152602001506040518860e060020a02815260040180888152602001876002602002808383829060006004602084601f0104600f02600301f150905001868152602001806020018560ff1681526020018461ffff168152602001836006602002808383829060006004602084601f0104600f02600301f1509050018281038252868181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156105d25780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038160008760325a03f2156100025750506040515191506124cd9050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808787611e64610f6d565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611d28610f6d565b61189f5b6000611bf8611159565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881600060005054611a9561159f565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346326a7985a6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b760075b90565b604080516020606435600481810135601f8101849004840285018401909552848452611882948135946024803595604435956084949201919081908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160013389898861224b610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386866020604051908101604052806000815260200150611e64610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333896020604051908101604052806000815260200150886123bc6106c6565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387866020604051908101604052806000815260200150611f8d610f6d565b60408051602060248035600481810135601f810185900485028601850190965285855261188295813595919460449492939092019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808888612225610f6d565b611882600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503388886020604051908101604052806000815260200150612388610f6d565b611882600435604080517fc4144b2600000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163c4144b26916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437509496505093359350505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133888888612238610f6d565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a43560c435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338b8b8b896126536106c6565b611882600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333866020604051908101604052806000815260200150611e4a610f6d565b6118b76004355b604080517fed5bd7ea00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a03831660248201529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163ed5bd7ea916044818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b61189f600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463586a69fa6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f81018590048502860185019096528585526118829581359591946044949293909201918190840183828082843750949650509335935050606435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808989612388610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a896020604051908101604052806000815260200150886124d76106c6565b6040805160206004803580820135601f8101849004840285018401909552848452611882949193602493909291840191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808587611e4a610f6d565b61188260043560243560443560643560843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050338a8a60206040519081016040528060008152602001508961262d6106c6565b604080516020606435600481810135601f810184900484028501840190955284845261188294813594602480359560443595608494920191908190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338888876120c7610f6d565b604080516020604435600481810135601f81018490048402850184019095528484526118829481359460248035959394606494929391019181908401838280828437505060408051608080820190925295979635969561010495509350608492508591508390839080828437509095505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989898961263a6106c6565b6118b7600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881858585611ba361122c565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001600050333388602060405190810160405280600081526020015061236e610f6d565b6118b760005481565b6118c95b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea34638e46afa96040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a43560c43560e43561010435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338e8e8d8f8e8e8e8e8e346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156111195780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519b9a5050505050505050505050565b61189f5b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463971c803f6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650509335935050608435915050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338989896123a2610f6d565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398c9cdf46040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346398e00e546040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600435604080517fe6ce3a6a000000000000000000000000000000000000000000000000000000008152600160048201527f3e3d0000000000000000000000000000000000000000000000000000000000006024820152604481018390529051600091737c1eb207c07e7ab13cf245585bd03d0fa478d0349163e6ce3a6a916064818101926020929091908290030181878760325a03f215610002575050604051519150611b409050565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503385600060e060020a0260206040519081016040528060008152602001506121ef610f6d565b604080516020604435600481810135601f8101849004840285018401909552848452611882948135946024803595939460649492939101918190840183828082843750949650505050505050600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338787876120b5610f6d565b6118b7600435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88183611b4561159f565b6118b75b600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463b152f19e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b60408051602060248035600481810135601f8101859004850286018501909652858552611882958135959194604494929390920191819084018382808284375094965050933593505060643591505060843560a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600133808b8b8961262d6106c6565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503386600060e060020a026020604051908101604052806000815260200150612200610f6d565b6118b75b60005460649004610759565b6118b7600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463c0f688596040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506107599050565b611882600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333600060e060020a026020604051908101604052806000815260200150611bff610f6d565b611882600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503333876020604051908101604052806000815260200150612200610f6d565b611882600435602435604435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e41160016000503387600060e060020a026020604051908101604052806000815260200150612213610f6d565b611882600435602435604435606435608435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e411600160005033338a60206040519081016040528060008152602001508961250c6106c6565b61027c6000600060006118e033610b56565b6118b7600435602435604435606435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a881868686866040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b949350505050565b604080516020604435600481810135601f810184900484028501840190955284845261188294813594602480359593946064949293910191819084018382808284375094965050933593505060843591505060a435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea346350d4e4116001338a8a8a886124fa6106c6565b6118b7600435602435600073e54d323f9ef17c1f0dede47ecc86a9718fe5ea3463ea27a88184846000611b4f61122c565b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b60408051918252519081900360200190f35b6040805160ff929092168252519081900360200190f35b15611a905733925082600160a060020a031663c6502da86040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040805180517fc6803622000000000000000000000000000000000000000000000000000000008252915191945063c680362291600482810192602092919082900301816000876161da5a03f11561000257505060405151905080156119d1575082600160a060020a031663d379be236040518160e060020a0281526004018090506020604051808303816000876161da5a03f11561000257505060405151600160a060020a03166000141590505b80156119dd5750600082115b80156119ec5750600054600190115b15611a90578183600160a060020a031663830953ab6040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750506040515160640291909104915050604281118015611a4d5750600054829011155b15611a675760008054612710612711909102049055611a90565b602181108015611a7a5750600054829010155b15611a90576000805461271061270f9091020490555b505050565b6000611a9f61122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b919050565b6000611af261122c565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b6040518560e060020a0281526004018085815260200184815260200183815260200182815260200194505050505060206040518083038160008760325a03f215610002575050604051519150505b9392505050565b9050610759565b611c076106c6565b6000611c11611478565b611c1961122c565b600054611c2461159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611cf25780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506107599050565b611d306106c6565b60008b611d3b61122c565b600054611d4661159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611e145780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b409050565b611e526106c6565b6000611e5c611478565b611d3b61122c565b611e6c6106c6565b6000611e76611478565b611e7e61122c565b600054611e8961159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015611f575780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611b9d9050565b611f956106c6565b8b611f9e611478565b611fa661122c565b600054611fb161159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561207f5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150611bf19050565b6120bd6106c6565b6000611f9e611478565b6120cf6106c6565b8b6120d8611478565b6120e061122c565b6000546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156121b95780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f2156100025750506040515191506117c99050565b6121f76106c6565b8b611e76611478565b6122086106c6565b60008b611e7e61122c565b61221b6106c6565b8a8c611fa661122c565b61222d6106c6565b60008b611fa661122c565b6122406106c6565b60008b6120e061122c565b6122536106c6565b8c8b61225d61122c565b60005461226861159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156123365780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f21561000257505060405151979650505050505050565b6123766106c6565b60008c8c600060005054611fb161159f565b6123906106c6565b60008c8c6000600050546120eb61159f565b6123aa6106c6565b60008c8c60006000505461226861159f565b60008d8d6000600050546120eb61159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f16801561249c5780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519150505b9695505050505050565b8e8d8d6000600050546123ce61159f565b60008d8d60006000505461226861159f565b60008d8d6000600050546123ce61159f565b60008e8e8d61226861159f565b8f8e8e8d61252561159f565b346040518e60e060020a028152600401808e81526020018d600160a060020a031681526020018c600160a060020a031681526020018b8152602001806020018a60ff1681526020018961ffff16815260200188815260200187815260200186815260200185815260200184815260200183815260200182810382528b8181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156125f35780820380516001836020036101000a031916815260200191505b509e50505050505050505050505050505060206040518083038160008760325a03f215610002575050604051519998505050505050505050565b60008e8e8d6123ce61159f565b8a5160208c015160408d015160608e015161226861159f565b60008e8e8d61252561159f56", - "storage": { - "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abf": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef715": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bc": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bd": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bf": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f1": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f3": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f4": "0x0000000000000000000000000000000000000000000000000000000000000003", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbc": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "0x741467b251fca923d6229c4b439078b55dca233b": { - "balance": "0x29c613529e8218f8", - "code": "0x606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256" - }, - "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { - "balance": "0xd7a58f5b73b4b6c4", - "code": "0x606060405236156100985760e060020a60003504633896002781146100e15780633defb962146100ea5780633f4be8891461010c5780634136aa351461011f5780634a420138146101a057806369c1a7121461028c5780638129fc1c146102955780638da5cb5b146102a6578063ae45850b146102b8578063af3309d8146102cc578063ea8a1af0146102d5578063ead50da3146102f4575b610308671bc16d674ec8000030600160a060020a03163110156100df57600554604051600160a060020a03918216916000913091909116319082818181858883f150505050505b565b61030a60005481565b610308671bc16d674ec8000030600160a060020a031631101561040f576100df565b61031c600454600160a060020a03165b90565b61030a5b600080548190118015610199575060408051600480547f0a16697a0000000000000000000000000000000000000000000000000000000083529251600160a060020a039390931692630a16697a928083019260209291829003018187876161da5a03f1156100025750506040515160ff01431090505b905061011c565b6103085b600354600554604080517f8c0e156d0000000000000000000000000000000000000000000000000000000081527f3defb96200000000000000000000000000000000000000000000000000000000600482015260a060020a90920461ffff1643016024830152621e8480604483015251600092600160a060020a031691638c0e156d916729a2241af62c000091606481810192602092909190829003018185886185025a03f1156100025750506040515192600160a060020a0384161491506102899050576004805473ffffffffffffffffffffffffffffffffffffffff1916821790555b50565b61030a60015481565b61030860008054146103f2576100df565b61031c600554600160a060020a031681565b61031c600354600160a060020a031661011c565b61030a60025481565b610308600554600160a060020a03908116339091161461035157610002565b61033960055460a060020a900461ffff1681565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b6040805161ffff929092168252519081900360200190f35b6004546000600160a060020a03919091163111156103c75760408051600480547fea8a1af00000000000000000000000000000000000000000000000000000000083529251600160a060020a03939093169263ea8a1af0928083019260009291829003018183876161da5a03f115610002575050505b600554604051600160a060020a03918216916000913091909116319082818181858883f15050505050565b426000556100df6101a4565b600280546001908101909155429055565b600454600160a060020a03908116339091161461042b576100df565b610433610123565b151561043e576100df565b6103fe6101a456", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000056d0009b", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000008b", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b" - } - }, - "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { - "balance": "0xffe9b09a5c474dca", - "nonce": 975 - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x4f5807198e238f13e", - "nonce": 283 - } - }, - "post": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x98e2b02f14529b1eb2" - }, - "0x651913977e8140c323997fce5e03c19e0015eebf": { - "balance": "0x29a2241af62c0000", - "code": "0x606060405236156101a05760e060020a60003504630924120081146101c25780630a16697a146101cf5780630fd1f94e146101d8578063137c638b1461022e57806321835af61461023b57806324032866146102545780632f95b833146102d65780633017fe24146102e55780633233c686146102ef57806337f4c00e146102fa5780634500054f146103055780634e417a98146103785780634e71d92d146103e15780634f059a43146103f35780636146195414610451578063625cc4651461046157806367ce940d1461046a5780637d298ee314610477578063830953ab146104f9578063938b5f321461050457806395ee122114610516578063974654f41461052a578063a06db7dc14610535578063a9d2293d14610541578063ae45850b14610597578063b0f07e44146105a9578063c19d93fb146105cb578063c6502da81461062e578063c680362214610637578063ca94692d1461064a578063cc3471af14610673578063d379be23146106c9578063d62457f6146106e3578063ea8a1af0146106ee578063f5562753146107f3578063f6b4dfb414610854575b610868600080548190600160a060020a03908116339091161461087a57610994565b610868600b5460ff165b90565b610868600d5481565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630fd1f94e6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6108685b62012cc86101cc565b61086860043560008160001415610dc65750600161084f565b6108686004356024356000731deeda36e15ec9e80f3d7414d67a4803ae45fc80630bd295e6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150505b92915050565b61099860085461ffff166101cc565b61086860026101cc565b610868600a546101cc565b6108686006546101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a09431546003600050336040518360e060020a0281526004018083815260200182600160a060020a031681526020019250505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b6109af60408051602081810183526000825282516004805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015610a7d5780601f10610a5257610100808354040283529160200191610a7d565b61086860006000600180610b7b6105cf565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753436040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1d6000600480610c986105cf565b61086860025481565b6108685b620186a06101cc565b6108686004356024355b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a1873db6600360005085856040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506102d09050565b6108686009546101cc565b610a1f600c54600160a060020a031681565b610868600b5462010000900460ff166101cc565b6108686007546101cc565b610a3c600e5460ff1681565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063a9d2293d6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600054600160a060020a031681565b610868600080548190600160a060020a039081163390911614610a8957610994565b6108685b6000731deeda36e15ec9e80f3d7414d67a4803ae45fc80635054d98a60036000506040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b61086860015481565b610868600b54610100900460ff166101cc565b61086860035474010000000000000000000000000000000000000000900460e060020a026101cc565b6108686000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063cc3471af6040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506101cc9050565b610a1f600854620100009004600160a060020a03166101cc565b6108686005546101cc565b610a1d604080517fa09431540000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc809163a0943154916044808301926020929190829003018160008760325a03f215610002575050604051511590506107f157604080517f7e9265620000000000000000000000000000000000000000000000000000000081526003600482015233600160a060020a031660248201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091637e9265629160448083019260009291908290030181838760325a03f215610002575050505b565b6108686004356000731deeda36e15ec9e80f3d7414d67a4803ae45fc8063f5562753836040518260e060020a0281526004018082815260200191505060206040518083038160008760325a03f215610002575050604051519150505b919050565b610a1f600354600160a060020a03166101cc565b60408051918252519081900360200190f35b60045460006002600183161561010002600019019092169190910411156108a45760009150610994565b6108ac6105cf565b9050600081141580156108c0575060018114155b80156108cd575060028114155b156108db5760009150610994565b600480546000828152602060026001841615610100026000190190931692909204601f908101929092047f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9081019236929083901061095d5782800160ff198235161785555b5061098d9291505b808211156109945760008155600101610949565b82800160010185558215610941579182015b8281111561094157823582600050559160200191906001019061096f565b5050600191505b5090565b6040805161ffff9092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f168015610a0f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b005b60408051600160a060020a03929092168252519081900360200190f35b6040805160ff9092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311610a6057829003601f168201915b505050505090506101cc565b6004546000600260018316156101000260001901909216919091041115610ab35760009150610994565b610abb6105cf565b905060008114158015610acf575060018114155b8015610adc575060028114155b15610aea5760009150610994565b604080517f7c0278fc000000000000000000000000000000000000000000000000000000008152600360048201818152602483019384523660448401819052731deeda36e15ec9e80f3d7414d67a4803ae45fc8094637c0278fc946000939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050505090565b1415610c8557604080516001547f0fee183d0000000000000000000000000000000000000000000000000000000082526003600483015233600160a060020a0316602483015234604483015260648201529051731deeda36e15ec9e80f3d7414d67a4803ae45fc8091630fee183d916084828101926020929190829003018160008760325a03f21561000257505060405151925050811515610c8a577389efe605e9ecbe22849cd85d5449cc946c26f8f36312c82bcc33346040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515115159050610c8a57610002565b505090565b81925050610994565b505b50565b1415610c93575a9150610cab3383610481565b1515610cb75750610c95565b731deeda36e15ec9e80f3d7414d67a4803ae45fc8063da46be0a60038433610cdd61046e565b610ce5610232565b6040518660e060020a0281526004018086815260200185815260200184600160a060020a031681526020018381526020018281526020019550505050505060006040518083038160008760325a03f21561000257505050610c933360408051600080547fc17e6817000000000000000000000000000000000000000000000000000000008352600160a060020a03908116600484015230163160248301529151731deeda36e15ec9e80f3d7414d67a4803ae45fc809263c17e68179260448082019360209390928390039091019082908760325a03f2156100025750505050565b30600160a060020a031660405180807f5f5f6469672875696e7432353629000000000000000000000000000000000000815260200150600e019050604051809103902060e060020a8091040260e060020a9004600184036040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f292505050151561084f5761000256", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000007dd677b54fc954824a7bc49bd26cbdfa12c75adf", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000011f8119429ed3a", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000002e002d006b55", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x00000000000000003defb9627dd677b54fc954824a7bc49bd26cbdfa12c75adf", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000ba43b7400", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x00000000000000000000000000000000000000000000000000000000001e8480", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000a", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000006c8f2a135f6ed072de4503bd7c4999a1a17f824b", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000103847", - "0x000000000000000000000000000000000000000000000000000000000000000e": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b": { - "nonce": 238, - "storage": { - "0x26cba0705aade77fa0f9275b68d01fb71206a44abd3a4f5a838f7241efbc8abf": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x49f03a2c2f4fd666a32141fb324283b6f84a1d07b5fa435669fdb55766aef715": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bc": "0x000000000000000000000000a4d91b341f0e9a7000be916a668408b463f4c38c", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bd": "0x000000000000000000000000d7b0e93fa8386b17fb5d1cf934076203dcc122f3", - "0x95e05d02b91af970cb4998107e8613455258880676e00b819c12d675e60de5bf": "0x0000000000000000000000000000000000000000000000000000000000000003", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2751": "0x000000000000000000000000651913977e8140c323997fce5e03c19e0015eebf", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2752": "0x0000000000000000000000000000000000000000000000000000000000103847", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2753": "0x000000000000000000000000741467b251fca923d6229c4b439078b55dca233b", - "0x99d5294a34e2d6d560a223237786adc8b5651c09094b9ecd56e6ae7abc2a2756": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f1": "0x00000000000000000000000042e69cd0a17ae9992f9ad93d136c4bb0d95e3230", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f3": "0x000000000000000000000000c9a2bfd279fe57e7651e5d9f29bb1793c9a1cf01", - "0xd3a5582b3eff6ef8ee90f3962e9d598a3f4b7d07840356c9b8fd7b494879b4f4": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbb": "0x000000000000000000000000651913977e8140c323997fce5e03c19e0015eebf", - "0xf7518490c515b9fc8e7fe713b647fe88eacefc92d616fa9454e61fe9aab64dbc": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - }, - "0x741467b251fca923d6229c4b439078b55dca233b": { - "balance": "0x0", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000101" - } - }, - "0x7dd677b54fc954824a7bc49bd26cbdfa12c75adf": { - "balance": "0xd6c5f42b8502a0e3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000056d020be", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000008c", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000651913977e8140c323997fce5e03c19e0015eebf" - } - }, - "0xb834e3edfc1a927bdcecb67a9d0eccbd752a5bb3": { - "balance": "0x10002e64ebd492a46", - "nonce": 976 - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x4f5809f97e1c8bb9b" - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json deleted file mode 100644 index 01cc3c505..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/simple.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "context": { - "difficulty": "3502894804", - "gasLimit": "4722976", - "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", - "number": "2289806", - "timestamp": "1513601314" - }, - "genesis": { - "alloc": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "code": "0x", - "nonce": "22", - "storage": {} - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "nonce": "1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "code": "0x", - "nonce": "29072", - "storage": {} - } - }, - "config": { - "byzantiumBlock": 1700000, - "chainId": 3, - "daoForkSupport": true, - "eip150Block": 0, - "eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d", - "eip155Block": 10, - "eip158Block": 10, - "ethash": {}, - "homesteadBlock": 0 - }, - "difficulty": "3509749784", - "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", - "gasLimit": "4727564", - "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", - "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", - "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", - "nonce": "0x4eb12e19c16d43da", - "number": "2289805", - "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", - "timestamp": "1513601261", - "totalDifficulty": "7143276353481064" - }, - "input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x0", - "nonce": 22 - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x0" - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d87094125a369d9bd5", - "nonce": 1, - "code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d77678137ac1b775", - "nonce": 29072 - } - }, - "post": { - "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { - "balance": "0x6f05b59d3b20000" - }, - "0x1585936b53834b021f68cc13eeefdec2efc8e724": { - "balance": "0x420eed1bd6c00" - }, - "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": { - "balance": "0x4d869a3b70062eb9bd5", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b95e" - } - }, - "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": { - "balance": "0x1780d7725724a9044b75", - "nonce": 29073 - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/suicide.json b/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/suicide.json deleted file mode 100644 index 5021bda19..000000000 --- a/builder/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/suicide.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "genesis": { - "difficulty": "5697691613344", - "extraData": "0xd783010202844765746887676f312e342e32856c696e7578", - "gasLimit": "3141592", - "hash": "0x2004021ae3545cf8abba1ec97a7e401157cee9e847131e2f4c75ce38610040cc", - "miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5", - "mixHash": "0x651f01d13fb801c602e1544ab80b3bc32888ea40ef298efa52ec3df983b558ee", - "nonce": "0xdf23f0da925518a6", - "number": "422908", - "stateRoot": "0xd914c6440edf9f4a6f997a9b3ecb6e1a9ca2310f74b0b6890c0d0d4a3c28e4d3", - "timestamp": "1445530335", - "totalDifficulty": "2148894717741690476", - "alloc": { - "0x2861bf89b6c640c79040d357c1e9513693ef5d3f": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a600035046312055e8f8114610084578063185061da146100b157806322beb9b9146100d5578063245a03ec146101865780633fa4f245146102a657806341c0e1b5146102af578063890eba68146102cb578063b29f0835146102de578063d6b4485914610308578063dd012a15146103b9575b005b6001805474ff0000000000000000000000000000000000000000191660a060020a60043502179055610082565b6100826001805475ff00000000000000000000000000000000000000000019169055565b61008260043560015460e060020a6352afbc3302606090815230600160a060020a039081166064527fb29f0835000000000000000000000000000000000000000000000000000000006084527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060a45243840160c490815260ff60a060020a85041660e452600061010481905291909316926352afbc339261012492918183876161da5a03f1156100025750505050565b6100826004356024356001547fb0f07e440000000000000000000000000000000000000000000000000000000060609081526064839052600160a060020a039091169063b0f07e449060849060009060248183876161da5a03f150604080516001547f73657449742875696e74323536290000000000000000000000000000000000008252825191829003600e018220878352835192839003602001832060e060020a6352afbc33028452600160a060020a03308116600486015260e060020a9283900490920260248501526044840152438901606484015260a060020a820460ff1694830194909452600060a483018190529251931694506352afbc33935060c48181019391829003018183876161da5a03f115610002575050505050565b6103c460025481565b61008260005433600160a060020a039081169116146103ce575b565b6103c460015460a860020a900460ff1681565b6100826001805475ff000000000000000000000000000000000000000000191660a860020a179055565b61008260043560015460e060020a6352afbc3302606090815230600160a060020a039081166064527f185061da000000000000000000000000000000000000000000000000000000006084527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060a45243840160c490815260ff60a060020a85041660e452600061010481905291909316926352afbc339261012492918183876161da5a03f1156100025750505050565b600435600255610082565b6060908152602090f35b6001547f6ff96d17000000000000000000000000000000000000000000000000000000006060908152600160a060020a0330811660645290911690632e1a7d4d908290636ff96d17906084906020906024816000876161da5a03f1156100025750506040805180517f2e1a7d4d0000000000000000000000000000000000000000000000000000000082526004820152905160248281019350600092829003018183876161da5a03f115610002575050600054600160a060020a03169050ff", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000ff30c9e568f133adce1f1ea91e189613223fc461b9" - } - }, - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x326601cc6cf364f6b9", - "nonce": "12122", - "code": "0x" - }, - "0x30c9e568f133adce1f1ea91e189613223fc461b9": { - "balance": "0x8b83c417dd78000", - "nonce": "2", - "code": "0x606060405236156102ea5760e060020a6000350463022bc71f81146102f757806303d6d7b61461037f578063086ae9e4146103ec57806309c975df146104595780631145a20f146104c657806312d67c5f146104e75780631302188c146104f15780631ae460e5146104fc57806323306ed614610573578063234917d4146105ca57806329917954146106375780632a472ae81461071d5780632e1a7d4d1461078a578063306b031d1461087f57806333613cbe1461089d57806334c19b93146108c257806335b281531461092f5780633664a0ea146109b85780633c941423146109c35780633cbfed7414610a3b57806350a3bd3914610a4957806352afbc3314610a735780635539d40014610c2a5780635a5383ac14610c3e57806360b831e514610cb55780636164947214610d7f578063685c234a14610d8a5780636ffc089614610de0578063741b3c3914610e4d5780637542861514610ed25780637772a38014610f5557806377b19cd514610ff057806378bc64601461105d5780638b37e656146110ca5780638baced64146111375780638dd5e298146111b157806393423e9c146111de57806394d2b21b1461120257806394f3f81d1461121657806398e00e54146112665780639f927be7146112bc578063a502aae81461136a578063a6c01cfd146113e8578063a9743c68146113fa578063aa4cc01f14611467578063b010d94a146114d4578063b0171fa41461154e578063b0ac4c8c146115cc578063b0f07e4414611635578063b35594601461171c578063c0f6885914611739578063c3daab961461178f578063c630f92b146117bb578063c831391d146117e5578063cd062734146117f0578063d0e30db01461185d578063db681e5414611865578063e40986551461190c578063e850f3ae14611979578063ed2b8e0b146119e6578063f340fa01146119f1578063f828c3fa14611ae8578063f8b1185314611b07578063f9f447eb14611b24578063fc30052214611b91578063fcf3691814611bfe575b6112645b611c86336119f8565b611c88600435604080517fc4144b260000000000000000000000000000000000000000000000000000000081526010600482015260248101839052905160009173ce642b6a82e72147ceade0e72c786ba8eaeb31d79163c4144b26916044818101926020929091908290030181878760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b637d613b346000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63da40fd616000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c9a60043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63c68efc486000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b61126460043560243560443560643560843561200185858585856000610a89565b611c886004545b90565b611c886005546104ee565b611c886040805160e160020a6333f8a36702815260066004820152600160a060020a0333166024820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f916367f146ce916044818101926020929091908290030181878760325a03f2156100025750506040515191506104ee9050565b611c885b60007327b1b436e4699a012cc8698e33c8f3e1c035c28b6323306ed66040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506104ee9050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63e99a66856000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611264604080517f317c152d00000000000000000000000000000000000000000000000000000000815260066004820152600160a060020a0333166024820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163317c152d916044818101926020929091908290030181878760325a03f2156100025750506040805180517ff1173928000000000000000000000000000000000000000000000000000000008252600160a060020a0333166004830152602482018190529151919363f1173928926044838101938290030181838760325a03f2156100025750505050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63707378396000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611264600435604080517fb5bc6dbb00000000000000000000000000000000000000000000000000000000815260126004820152600160a060020a033316602482015260448101839052905173d3cb18959b0435864ff33010fa83be60afc04b229163b5bc6dbb916064828101926020929190829003018160008760325a03f21561000257505060405151159050611d255773d3cb18959b0435864ff33010fa83be60afc04b22637fcf532c33836040518360e060020a0281526004018083600160a060020a031681526020018281526020019250505060006040518083038160008760325a03f21561000257505050611ae5565b611c886004356000818152600e60205260409020600201545b919050565b611c886004355b600160a060020a0381166000908152600f6020526040902054610898565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63fc4730126000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611264600435604080517fa95d3e76000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a0384811660248401523316604483015291517327b1b436e4699a012cc8698e33c8f3e1c035c28b9263a95d3e7692606481810193918290030181838760325a03f2156100025750505050565b611c886002546104ee565b611c9a60043560243560007327b1b436e4699a012cc8698e33c8f3e1c035c28b6398213db6600060005085856040518460e060020a02815260040180848152602001838152602001828152602001935050505060206040518083038160008760325a03f215610002575050604051519150610dda9050565b611c886000611e0a336108a4565b611264600073c895c144d0b0f88417cf9e14e03e6abc82c0af3f635748147e600633611ec2610577565b61126460043560243560443560643560843560a4355b604080517ff1924efb000000000000000000000000000000000000000000000000000000008152600060048201819052600160a060020a03338116602484015289166044830152606482018890526084820187905260a4820186905260ff851660c483015260e48201849052915182917327b1b436e4699a012cc8698e33c8f3e1c035c28b9163f1924efb91610104818101926020929091908290030181878760325a03f2156100025750506040805180517f5a1230bf000000000000000000000000000000000000000000000000000000008252600160a060020a0333811660048401528c166024830152604482018b9052606482018a90526084820189905260ff881660a483015260c482018790529151919450635a1230bf9160e48083019260209291908290030181878760325a03f215610002575050604051519183149050612008577327b1b436e4699a012cc8698e33c8f3e1c035c28b6318b753ab82846040518360e060020a028152600401808381526020018281526020019250505060006040518083038160008760325a03f21561000257505050612056565b611c9a600154600160a060020a03166104ee565b611c886040805160e560020a6304b47bb902815260066004820152600160a060020a0333166024820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163968f7720916044818101926020929091908290030181878760325a03f2156100025750506040515191506104ee9050565b6112646004357327b1b436e4699a012cc8698e33c8f3e1c035c28b637e853f3d600060005083336040518460e060020a0281526004018084815260200183815260200182600160a060020a03168152602001935050505060206040518083038160008760325a03f21561000257505060405151159050611ae5577327b1b436e4699a012cc8698e33c8f3e1c035c28b63ab2af349826040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f2156100025750505050565b611c886008546104ee565b611c88600435602435604080516c01000000000000000000000000600160a060020a03858116820283528416026014820152815160289181900391909101902060009081526015602052205460ff165b92915050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63b506054f6000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611264604080517f068e3ef100000000000000000000000000000000000000000000000000000000815260066004820152600160a060020a0333166024820152346044820152905173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163068e3ef19160648281019260009291908290030181838760325a03f21561000257505050565b611cb76004356040805160208181018352600080835284815260138252838120600d0154815260148252835190849020805460026001821615610100026000190190911604601f81018490048402830184019095528482529293909291830182828015611fb85780601f10611f8d57610100808354040283529160200191611fb8565b611c886004356024355b604080517fa163a32500000000000000000000000000000000000000000000000000000000815260066004820152600160a060020a038416602482015260448101839052905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163a163a325916064818101926020929091908290030181878760325a03f215610002575050604051519150610dda9050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63775f20f96000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b637517a7c96000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c9a60043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63250687836000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c886004356040805160e160020a6333f8a36702815260066004820152600160a060020a0383166024820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f916367f146ce916044818101926020929091908290030181878760325a03f2156100025750506040515191506108989050565b611c88600435600073c895c144d0b0f88417cf9e14e03e6abc82c0af3f6354e37911600684611e6d610577565b611c88600435600160a060020a038116600090815260126020526040902054610898565b611c9a600054600160a060020a03166104ee565b604080516c01000000000000000000000000600435600160a060020a0390811682028352331602601482015281516028918190039190910190206000908152601560205220805460ff191690555b005b611c8860007327b1b436e4699a012cc8698e33c8f3e1c035c28b6398e00e546040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506104ee9050565b611c88600435604080517fe6ce3a6a000000000000000000000000000000000000000000000000000000008152601060048201527f3e3d000000000000000000000000000000000000000000000000000000000000602482015260448101839052905160009173ce642b6a82e72147ceade0e72c786ba8eaeb31d79163e6ce3a6a916064818101926020929091908290030181878760325a03f2156100025750506040515191506108989050565b611c88604080517f8f00e61a00000000000000000000000000000000000000000000000000000000815260066004820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f91638f00e61a916024818101926020929091908290030181878760325a03f2156100025750506040515191506104ee9050565b611c886004356000611e113383610f5f565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63dd382dd36000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63aebd65476000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c886004356040805160e560020a6304b47bb902815260066004820152600160a060020a0383166024820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163968f7720916044818101926020929091908290030181878760325a03f2156100025750506040515191506108989050565b611c88604080517fc75e8f8800000000000000000000000000000000000000000000000000000000815260066004820152905160009173c895c144d0b0f88417cf9e14e03e6abc82c0af3f9163c75e8f88916024818101926020929091908290030181878760325a03f2156100025750506040515191506104ee9050565b611cb760408051602081810183526000825282516003805460026000196001831615610100020190911604601f81018490048402830184019095528482529293909291830182828015611fef5780601f10611fc457610100808354040283529160200191611fef565b611264604080517fa89713750000000000000000000000000000000000000000000000000000000081526000600482018181526024830193845236604484018190527327b1b436e4699a012cc8698e33c8f3e1c035c28b9463a89713759484939190606401848480828437820191505094505050505060006040518083038160008760325a03f215610002575050604080516005547f321f45840000000000000000000000000000000000000000000000000000000082526004820152905163321f4584916024818101926000929091908290030181838760325a03f21561000257505050565b611c886004356000818152600e6020526040902060030154610898565b611c8860007327b1b436e4699a012cc8698e33c8f3e1c035c28b63c0f688596040518160e060020a02815260040180905060206040518083038160008760325a03f2156100025750506040515191506104ee9050565b61126460043573c895c144d0b0f88417cf9e14e03e6abc82c0af3f63dd8abb6c60063384611db7610577565b611c88600073c895c144d0b0f88417cf9e14e03e6abc82c0af3f6354e37911600633611e18610577565b611c886007546104ee565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63125935846000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b6112646102ee565b611c886004356000818152601360209081526040805181842060038101546004828101547f38f4c9eb0000000000000000000000000000000000000000000000000000000085526006918501919091526024840182905260ff160160448301529151919273c895c144d0b0f88417cf9e14e03e6abc82c0af3f926338f4c9eb9260648181019392918290030181888760325a03f21561000257505060405151949350505050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63fae644646000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63b3a5e2556000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c886006546104ee565b6112646004355b604080517fb1df3d8000000000000000000000000000000000000000000000000000000000815260126004820152600160a060020a0383166024820152346044820152905173d3cb18959b0435864ff33010fa83be60afc04b229163b1df3d80916064828101926020929190829003018160008760325a03f215610002575050604080517f5548c837000000000000000000000000000000000000000000000000000000008152600160a060020a033381166004830152841660248201523460448201529051635548c837916064818101926000929091908290030181838760325a03f215610002575050505b50565b611264600435602435604435606435611ffb8484848460ff6000610a89565b611c886004356000818152600e6020526040902060010154610898565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b63c9abdb7c6000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611c8860043560007327b1b436e4699a012cc8698e33c8f3e1c035c28b6386b0aac96000600050846040518360e060020a028152600401808381526020018281526020019250505060206040518083038160008760325a03f2156100025750506040515191506108989050565b611264600435604080517f25fea09900000000000000000000000000000000000000000000000000000000815260006004820181905260248201849052600160a060020a033316604483015291517327b1b436e4699a012cc8698e33c8f3e1c035c28b926325fea09992606481810193918290030181838760325a03f2156100025750505050565b565b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015611d175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600160a060020a0333166000818152601260205260408051818320547f5c54305e00000000000000000000000000000000000000000000000000000000825260048201949094526024810185905260448101939093525173d3cb18959b0435864ff33010fa83be60afc04b2292635c54305e9260648281019391928290030181838760325a03f2156100025750505050565b6040518560e060020a0281526004018085815260200184600160a060020a0316815260200183815260200182815260200194505050505060006040518083038160008760325a03f2156100025750505050565b90506104ee565b9050610898565b6040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506104ee9050565b6040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040515191506108989050565b6040518460e060020a0281526004018084815260200183600160a060020a03168152602001828152602001935050505060206040518083038160008760325a03f2156100025750506040805180517f6a704d7b000000000000000000000000000000000000000000000000000000008252600160a060020a033316600483015260248201819052915191935073c895c144d0b0f88417cf9e14e03e6abc82c0af3f9250636a704d7b9160448281019260009291908290030181838760325a03f2156100025750505050565b820191906000526020600020905b815481529060010190602001808311611f9b57829003601f168201915b50505050509050610898565b820191906000526020600020905b815481529060010190602001808311611fd257829003601f168201915b505050505090506104ee565b50505050565b5050505050565b7327b1b436e4699a012cc8698e33c8f3e1c035c28b635ca1bad5826040518260e060020a0281526004018082815260200191505060006040518083038160008760325a03f215610002575050505b505050505050505056", - "storage": { - "0x18b039f13c5f33908f0960616cb3e44029c716366508c54d555096d6e1fa5145": "0x00000000000000000000000000000000000000000000000008b83c417dd78000" - } - }, - "0xd3cb18959b0435864ff33010fa83be60afc04b22": { - "balance": "0x0", - "code": "0x650105e11e10f850606060405236156100695760e060020a60003504635548c837811461006e5780635c54305e146100ca5780636b1039661461011e5780637fcf532c14610152578063b1df3d801461019e578063b5bc6dbb146101b7578063e62af6c1146101ee575b610007565b61022060043560243560443581600160a060020a031683600160a060020a03167f47a08955ce2b7f21ea62ff0024e1ea0ad87430953554a87e6bc65d777f18e639836040518082815260200191505060405180910390a3505050565b61022060043560243560443560408051838152602081018390528151600160a060020a038616927f9b24879829bed3003de08d5c5d7e18dcbb8dc76faebd95cafc5d4dec8c61a3a5928290030190a2505050565b6102206004356024356044355b600160a060020a038216600090815260208490526040902054808201101561023457610007565b610220600435602435604080518281529051600160a060020a038416917fd0c5cf41ee8ebf084ad0bce53de7cbc6e4693d9b53a4019ca36a2f91cdc20b3a919081900360200190a25050565b610222600435602435604435600061025784848461012b565b610222600435602435604435600160a060020a0382166000908152602084905260408120548290106102865761028e8484846101fb565b6102206004356024356044355b600160a060020a03821660009081526020849052604090205481111561026257610007565b005b60408051918252519081900360200190f35b600160a060020a0382166000908152602084905260409020805482019055505050565b5060015b9392505050565b600160a060020a038216600090815260208490526040902080548290039055505050565b50600061025b565b604051600160a060020a03841690600090849082818181858883f19350505050151561025757604051600160a060020a038416908390600081818185876185025a03f19250505015156102575761000756" - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x1ff0509d9d6821e26", - "nonce": "138", - "code": "0x" - } - }, - "config": { - "chainId": 1, - "homesteadBlock": 1150000, - "daoForkBlock": 1920000, - "daoForkSupport": true, - "eip150Block": 2463000, - "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", - "eip155Block": 2675000, - "eip158Block": 2675000, - "byzantiumBlock": 4370000, - "constantinopleBlock": 7280000, - "petersburgBlock": 7280000, - "istanbulBlock": 9069000, - "muirGlacierBlock": 9200000, - "berlinBlock": 12244000, - "londonBlock": 12965000, - "arrowGlacierBlock": 13773000, - "grayGlacierBlock": 15050000, - "ethash": {} - } - }, - "context": { - "number": "422909", - "difficulty": "5694909537365", - "timestamp": "1445530357", - "gasLimit": "3141592", - "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226" - }, - "input": "0xf86a818a850ba43b7400832d8a40942861bf89b6c640c79040d357c1e9513693ef5d3f808441c0e1b51ca0b8de64a9a04d699f5938efa5431ca7c80500f6accb329da43aadabd4eab84f17a035b969c198f694be991a2a5b287250e19e852efd0ccba30bd50707277bfbc9aa", - "tracerConfig": { - "diffMode": true - }, - "result": { - "pre": { - "0x2861bf89b6c640c79040d357c1e9513693ef5d3f": { - "balance": "0x0", - "code": "0x606060405236156100825760e060020a600035046312055e8f8114610084578063185061da146100b157806322beb9b9146100d5578063245a03ec146101865780633fa4f245146102a657806341c0e1b5146102af578063890eba68146102cb578063b29f0835146102de578063d6b4485914610308578063dd012a15146103b9575b005b6001805474ff0000000000000000000000000000000000000000191660a060020a60043502179055610082565b6100826001805475ff00000000000000000000000000000000000000000019169055565b61008260043560015460e060020a6352afbc3302606090815230600160a060020a039081166064527fb29f0835000000000000000000000000000000000000000000000000000000006084527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060a45243840160c490815260ff60a060020a85041660e452600061010481905291909316926352afbc339261012492918183876161da5a03f1156100025750505050565b6100826004356024356001547fb0f07e440000000000000000000000000000000000000000000000000000000060609081526064839052600160a060020a039091169063b0f07e449060849060009060248183876161da5a03f150604080516001547f73657449742875696e74323536290000000000000000000000000000000000008252825191829003600e018220878352835192839003602001832060e060020a6352afbc33028452600160a060020a03308116600486015260e060020a9283900490920260248501526044840152438901606484015260a060020a820460ff1694830194909452600060a483018190529251931694506352afbc33935060c48181019391829003018183876161da5a03f115610002575050505050565b6103c460025481565b61008260005433600160a060020a039081169116146103ce575b565b6103c460015460a860020a900460ff1681565b6100826001805475ff000000000000000000000000000000000000000000191660a860020a179055565b61008260043560015460e060020a6352afbc3302606090815230600160a060020a039081166064527f185061da000000000000000000000000000000000000000000000000000000006084527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060a45243840160c490815260ff60a060020a85041660e452600061010481905291909316926352afbc339261012492918183876161da5a03f1156100025750505050565b600435600255610082565b6060908152602090f35b6001547f6ff96d17000000000000000000000000000000000000000000000000000000006060908152600160a060020a0330811660645290911690632e1a7d4d908290636ff96d17906084906020906024816000876161da5a03f1156100025750506040805180517f2e1a7d4d0000000000000000000000000000000000000000000000000000000082526004820152905160248281019350600092829003018183876161da5a03f115610002575050600054600160a060020a03169050ff", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000d3cda913deb6f67967b99d67acdfa1712c293601", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000ff30c9e568f133adce1f1ea91e189613223fc461b9" - } - }, - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x326601cc6cf364f6b9", - "nonce": 12122 - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x1ff0509d9d6821e26", - "nonce": 138 - } - }, - "post": { - "0x2a65aca4d5fc5b5c859090a6c34d164135398226": { - "balance": "0x326604ee5f5eecd2b9" - }, - "0xd3cda913deb6f67967b99d67acdfa1712c293601": { - "balance": "0x1ff01e7e76afa4226", - "nonce": 139 - } - } - } -} diff --git a/builder/eth/tracers/internal/tracetest/util.go b/builder/eth/tracers/internal/tracetest/util.go deleted file mode 100644 index 95d292c92..000000000 --- a/builder/eth/tracers/internal/tracetest/util.go +++ /dev/null @@ -1,72 +0,0 @@ -package tracetest - -import ( - "strings" - "unicode" - - // Force-load native and js packages, to trigger registration - _ "github.com/ethereum/go-ethereum/eth/tracers/js" - _ "github.com/ethereum/go-ethereum/eth/tracers/native" -) - -// To generate a new callTracer test, copy paste the makeTest method below into -// a Geth console and call it with a transaction hash you which to export. - -/* -// makeTest generates a callTracer test by running a prestate reassembled and a -// call trace run, assembling all the gathered information into a test case. -var makeTest = function(tx, rewind) { - // Generate the genesis block from the block, transaction and prestate data - var block = eth.getBlock(eth.getTransaction(tx).blockHash); - var genesis = eth.getBlock(block.parentHash); - - delete genesis.gasUsed; - delete genesis.logsBloom; - delete genesis.parentHash; - delete genesis.receiptsRoot; - delete genesis.sha3Uncles; - delete genesis.size; - delete genesis.transactions; - delete genesis.transactionsRoot; - delete genesis.uncles; - - genesis.gasLimit = genesis.gasLimit.toString(); - genesis.number = genesis.number.toString(); - genesis.timestamp = genesis.timestamp.toString(); - - genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind}); - for (var key in genesis.alloc) { - var nonce = genesis.alloc[key].nonce; - if (nonce) { - genesis.alloc[key].nonce = nonce.toString(); - } - } - genesis.config = admin.nodeInfo.protocols.eth.config; - - // Generate the call trace and produce the test input - var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind}); - delete result.time; - - console.log(JSON.stringify({ - genesis: genesis, - context: { - number: block.number.toString(), - difficulty: block.difficulty, - timestamp: block.timestamp.toString(), - gasLimit: block.gasLimit.toString(), - miner: block.miner, - }, - input: eth.getRawTransaction(tx), - result: result, - }, null, 2)); -} -*/ - -// camel converts a snake cased input string into a camel cased output. -func camel(str string) string { - pieces := strings.Split(str, "_") - for i := 1; i < len(pieces); i++ { - pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:] - } - return strings.Join(pieces, "") -} diff --git a/builder/eth/tracers/js/bigint.go b/builder/eth/tracers/js/bigint.go deleted file mode 100644 index 9aeb33042..000000000 --- a/builder/eth/tracers/js/bigint.go +++ /dev/null @@ -1,20 +0,0 @@ -// 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 js - -// bigIntegerJS is the minified version of https://github.com/peterolson/BigInteger.js. -const bigIntegerJS = `var bigInt=function(undefined){"use strict";var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),LOG_MAX_INT=Math.log(MAX_INT);function Integer(v,radix){if(typeof v==="undefined")return Integer[0];if(typeof radix!=="undefined")return+radix===10?parseValue(v):parseBase(v,radix);return parseValue(v)}function BigInteger(value,sign){this.value=value;this.sign=sign;this.isSmall=false}BigInteger.prototype=Object.create(Integer.prototype);function SmallInteger(value){this.value=value;this.sign=value<0;this.isSmall=true}SmallInteger.prototype=Object.create(Integer.prototype);function isPrecise(n){return-MAX_INT0)return Math.floor(n);return Math.ceil(n)}function add(a,b){var l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE,sum,i;for(i=0;i=base?1:0;r[i]=sum-carry*base}while(i0)r.push(carry);return r}function addAny(a,b){if(a.length>=b.length)return add(a,b);return add(b,a)}function addSmall(a,carry){var l=a.length,r=new Array(l),base=BASE,sum,i;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign){return this.subtract(n.negate())}var a=this.value,b=n.value;if(n.isSmall){return new BigInteger(addSmall(a,Math.abs(b)),this.sign)}return new BigInteger(addAny(a,b),this.sign)};BigInteger.prototype.plus=BigInteger.prototype.add;SmallInteger.prototype.add=function(v){var n=parseValue(v);var a=this.value;if(a<0!==n.sign){return this.subtract(n.negate())}var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),a<0)};SmallInteger.prototype.plus=SmallInteger.prototype.add;function subtract(a,b){var a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE,i,difference;for(i=0;i=0){value=subtract(a,b)}else{value=subtract(b,a);sign=!sign}value=arrayToSmall(value);if(typeof value==="number"){if(sign)value=-value;return new SmallInteger(value)}return new BigInteger(value,sign)}function subtractSmall(a,b,sign){var l=a.length,r=new Array(l),carry=-b,base=BASE,i,difference;for(i=0;i=0)};SmallInteger.prototype.minus=SmallInteger.prototype.subtract;BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)};SmallInteger.prototype.negate=function(){var sign=this.sign;var small=new SmallInteger(-this.value);small.sign=!sign;return small};BigInteger.prototype.abs=function(){return new BigInteger(this.value,false)};SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))};function multiplyLong(a,b){var a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE,product,carry,i,a_i,b_j;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}function shiftLeft(x,n){var r=[];while(n-- >0)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(n<=30)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n);var ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));var product=addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n));trim(product);return product}function useKaratsuba(l1,l2){return-.012*l1-.012*l2+15e-6*l1*l2>0}BigInteger.prototype.multiply=function(v){var n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign,abs;if(n.isSmall){if(b===0)return Integer[0];if(b===1)return this;if(b===-1)return this.negate();abs=Math.abs(b);if(abs=0;shift--){quotientDigit=base-1;if(remainder[shift+b_l]!==divisorMostSignificantDigit){quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)}carry=0;borrow=0;l=divisor.length;for(i=0;ib_l){highx=(highx+1)*base}guess=Math.ceil(highx/highy);do{check=multiplySmall(b,guess);if(compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess);part=subtract(part,check)}result.reverse();return[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var length=value.length,quotient=createArray(length),base=BASE,i,q,remainder,divisor;remainder=0;for(i=length-1;i>=0;--i){divisor=remainder*base+value[i];q=truncate(divisor/lambda);remainder=divisor-q*lambda;quotient[i]=q|0}return[quotient,remainder|0]}function divModAny(self,v){var value,n=parseValue(v);var a=self.value,b=n.value;var quotient;if(b===0)throw new Error("Cannot divide by zero");if(self.isSmall){if(n.isSmall){return[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]}return[Integer[0],self]}if(n.isSmall){if(b===1)return[self,Integer[0]];if(b==-1)return[self.negate(),Integer[0]];var abs=Math.abs(b);if(absb.length?1:-1}for(var i=a.length-1;i>=0;i--){if(a[i]!==b[i])return a[i]>b[i]?1:-1}return 0}BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall)return 1;return compareAbs(a,b)};SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;if(n.isSmall){b=Math.abs(b);return a===b?0:a>b?1:-1}return-1};BigInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(this.sign!==n.sign){return n.sign?1:-1}if(n.isSmall){return this.sign?-1:1}return compareAbs(a,b)*(this.sign?-1:1)};BigInteger.prototype.compareTo=BigInteger.prototype.compare;SmallInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall){return a==b?0:a>b?1:-1}if(a<0!==n.sign){return a<0?-1:1}return a<0?1:-1};SmallInteger.prototype.compareTo=SmallInteger.prototype.compare;BigInteger.prototype.equals=function(v){return this.compare(v)===0};SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals;BigInteger.prototype.notEquals=function(v){return this.compare(v)!==0};SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals;BigInteger.prototype.greater=function(v){return this.compare(v)>0};SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater;BigInteger.prototype.lesser=function(v){return this.compare(v)<0};SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser;BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0};SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals;BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0};SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals;BigInteger.prototype.isEven=function(){return(this.value[0]&1)===0};SmallInteger.prototype.isEven=function(){return(this.value&1)===0};BigInteger.prototype.isOdd=function(){return(this.value[0]&1)===1};SmallInteger.prototype.isOdd=function(){return(this.value&1)===1};BigInteger.prototype.isPositive=function(){return!this.sign};SmallInteger.prototype.isPositive=function(){return this.value>0};BigInteger.prototype.isNegative=function(){return this.sign};SmallInteger.prototype.isNegative=function(){return this.value<0};BigInteger.prototype.isUnit=function(){return false};SmallInteger.prototype.isUnit=function(){return Math.abs(this.value)===1};BigInteger.prototype.isZero=function(){return false};SmallInteger.prototype.isZero=function(){return this.value===0};BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v);var value=n.value;if(value===0)return false;if(value===1)return true;if(value===2)return this.isEven();return this.mod(n).equals(Integer[0])};SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy;function isBasicPrime(v){var n=v.abs();if(n.isUnit())return false;if(n.equals(2)||n.equals(3)||n.equals(5))return true;if(n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5))return false;if(n.lesser(25))return true}BigInteger.prototype.isPrime=function(){var isPrime=isBasicPrime(this);if(isPrime!==undefined)return isPrime;var n=this.abs(),nPrev=n.prev();var a=[2,3,5,7,11,13,17,19],b=nPrev,d,t,i,x;while(b.isEven())b=b.divide(2);for(i=0;i-MAX_INT)return new SmallInteger(value-1);return new BigInteger(MAX_INT_ARR,true)};var powersOfTwo=[1];while(2*powersOfTwo[powersOfTwo.length-1]<=BASE)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];function shift_isSmall(n){return(typeof n==="number"||typeof n==="string")&&+Math.abs(n)<=BASE||n instanceof BigInteger&&n.value.length<=1}BigInteger.prototype.shiftLeft=function(n){if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftRight(-n);var result=this;while(n>=powers2Length){result=result.multiply(highestPower2);n-=powers2Length-1}return result.multiply(powersOfTwo[n])};SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft;BigInteger.prototype.shiftRight=function(n){var remQuo;if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}n=+n;if(n<0)return this.shiftLeft(-n);var result=this;while(n>=powers2Length){if(result.isZero())return result;remQuo=divModAny(result,highestPower2);result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0];n-=powers2Length-1}remQuo=divModAny(result,powersOfTwo[n]);return remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]};SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight;function bitwise(x,y,fn){y=parseValue(y);var xSign=x.isNegative(),ySign=y.isNegative();var xRem=xSign?x.not():x,yRem=ySign?y.not():y;var xDigit=0,yDigit=0;var xDivMod=null,yDivMod=null;var result=[];while(!xRem.isZero()||!yRem.isZero()){xDivMod=divModAny(xRem,highestPower2);xDigit=xDivMod[1].toJSNumber();if(xSign){xDigit=highestPower2-1-xDigit}yDivMod=divModAny(yRem,highestPower2);yDigit=yDivMod[1].toJSNumber();if(ySign){yDigit=highestPower2-1-yDigit}xRem=xDivMod[0];yRem=yDivMod[0];result.push(fn(xDigit,yDigit))}var sum=fn(xSign?1:0,ySign?1:0)!==0?bigInt(-1):bigInt(0);for(var i=result.length-1;i>=0;i-=1){sum=sum.multiply(highestPower2).add(bigInt(result[i]))}return sum}BigInteger.prototype.not=function(){return this.negate().prev()};SmallInteger.prototype.not=BigInteger.prototype.not;BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})};SmallInteger.prototype.and=BigInteger.prototype.and;BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})};SmallInteger.prototype.or=BigInteger.prototype.or;BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})};SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I;function roughLOB(n){var v=n.value,x=typeof v==="number"?v|LOBMASK_I:v[0]+v[1]*BASE|LOBMASK_BI;return x&-x}function max(a,b){a=parseValue(a);b=parseValue(b);return a.greater(b)?a:b}function min(a,b){a=parseValue(a);b=parseValue(b);return a.lesser(b)?a:b}function gcd(a,b){a=parseValue(a).abs();b=parseValue(b).abs();if(a.equals(b))return a;if(a.isZero())return b;if(b.isZero())return a;var c=Integer[1],d,t;while(a.isEven()&&b.isEven()){d=Math.min(roughLOB(a),roughLOB(b));a=a.divide(d);b=b.divide(d);c=c.multiply(d)}while(a.isEven()){a=a.divide(roughLOB(a))}do{while(b.isEven()){b=b.divide(roughLOB(b))}if(a.greater(b)){t=b;b=a;a=t}b=b.subtract(a)}while(!b.isZero());return c.isUnit()?a:a.multiply(c)}function lcm(a,b){a=parseValue(a).abs();b=parseValue(b).abs();return a.divide(gcd(a,b)).multiply(b)}function randBetween(a,b){a=parseValue(a);b=parseValue(b);var low=min(a,b),high=max(a,b);var range=high.subtract(low).add(1);if(range.isSmall)return low.add(Math.floor(Math.random()*range));var length=range.value.length-1;var result=[],restricted=true;for(var i=length;i>=0;i--){var top=restricted?range.value[i]:BASE;var digit=truncate(Math.random()*top);result.unshift(digit);if(digit=absBase){if(c==="1"&&absBase===1)continue;throw new Error(c+" is not a valid digit in base "+base+".")}else if(c.charCodeAt(0)-87>=absBase){throw new Error(c+" is not a valid digit in base "+base+".")}}}if(2<=base&&base<=36){if(length<=LOG_MAX_INT/Math.log(base)){var result=parseInt(text,base);if(isNaN(result)){throw new Error(c+" is not a valid digit in base "+base+".")}return new SmallInteger(parseInt(text,base))}}base=parseValue(base);var digits=[];var isNegative=text[0]==="-";for(i=isNegative?1:0;i");digits.push(parseValue(text.slice(start+1,i)))}else throw new Error(c+" is not a valid character")}return parseBaseFromArray(digits,base,isNegative)};function parseBaseFromArray(digits,base,isNegative){var val=Integer[0],pow=Integer[1],i;for(i=digits.length-1;i>=0;i--){val=val.add(digits[i].times(pow));pow=pow.times(base)}return isNegative?val.negate():val}function stringify(digit){var v=digit.value;if(typeof v==="number")v=[v];if(v.length===1&&v[0]<=35){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(v[0])}return"<"+v+">"}function toBase(n,base){base=bigInt(base);if(base.isZero()){if(n.isZero())return"0";throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1)){if(n.isZero())return"0";if(n.isNegative())return new Array(1-n).join("10");return"1"+new Array(+n).join("01")}var minusSign="";if(n.isNegative()&&base.isPositive()){minusSign="-";n=n.abs()}if(base.equals(1)){if(n.isZero())return"0";return minusSign+new Array(+n+1).join(1)}var out=[];var left=n,divmod;while(left.isNegative()||left.compareAbs(base)>=0){divmod=left.divmod(base);left=divmod.quotient;var digit=divmod.remainder;if(digit.isNegative()){digit=base.minus(digit).abs();left=left.next()}out.push(stringify(digit))}out.push(stringify(left));return minusSign+out.reverse().join("")}BigInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!==10)return toBase(this,radix);var v=this.value,l=v.length,str=String(v[--l]),zeros="0000000",digit;while(--l>=0){digit=String(v[l]);str+=zeros.slice(digit.length)+digit}var sign=this.sign?"-":"";return sign+str};SmallInteger.prototype.toString=function(radix){if(radix===undefined)radix=10;if(radix!=10)return toBase(this,radix);return String(this.value)};BigInteger.prototype.toJSON=SmallInteger.prototype.toJSON=function(){return this.toString()};BigInteger.prototype.valueOf=function(){return+this.toString()};BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf;SmallInteger.prototype.valueOf=function(){return this.value};SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return new SmallInteger(x);throw"Invalid integer: "+v}var sign=v[0]==="-";if(sign)v=v.slice(1);var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+split.join("e"));if(split.length===2){var exp=split[1];if(exp[0]==="+")exp=exp.slice(1);exp=+exp;if(exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0];var decimalPlace=text.indexOf(".");if(decimalPlace>=0){exp-=text.length-decimalPlace-1;text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)}if(exp<0)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0");v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);var r=[],max=v.length,l=LOG_BASE,min=max-l;while(max>0){r.push(+v.slice(min,max));min-=l;if(min<0)min=0;max-=l}trim(r);return new BigInteger(r,sign)}function parseNumberValue(v){if(isPrecise(v)){if(v!==truncate(v))throw new Error(v+" is not an integer.");return new SmallInteger(v)}return parseStringValue(v.toString())}function parseValue(v){if(typeof v==="number"){return parseNumberValue(v)}if(typeof v==="string"){return parseStringValue(v)}return v}for(var i=0;i<1e3;i++){Integer[i]=new SmallInteger(i);if(i>0)Integer[-i]=new SmallInteger(-i)}Integer.one=Integer[1];Integer.zero=Integer[0];Integer.minusOne=Integer[-1];Integer.max=max;Integer.min=min;Integer.gcd=gcd;Integer.lcm=lcm;Integer.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger};Integer.randBetween=randBetween;Integer.fromArray=function(digits,base,isNegative){return parseBaseFromArray(digits.map(parseValue),parseValue(base||10),isNegative)};return Integer}();if(typeof module!=="undefined"&&module.hasOwnProperty("exports")){module.exports=bigInt}if(typeof define==="function"&&define.amd){define("big-integer",[],function(){return bigInt})}; bigInt` diff --git a/builder/eth/tracers/js/goja.go b/builder/eth/tracers/js/goja.go deleted file mode 100644 index 07c138bae..000000000 --- a/builder/eth/tracers/js/goja.go +++ /dev/null @@ -1,992 +0,0 @@ -// 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 ( - "encoding/json" - "errors" - "fmt" - "math/big" - - "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" - "github.com/ethereum/go-ethereum/eth/tracers" - jsassets "github.com/ethereum/go-ethereum/eth/tracers/js/internal/tracers" -) - -var assetTracers = make(map[string]string) - -// init retrieves the JavaScript transaction tracers included in go-ethereum. -func init() { - var err error - assetTracers, err = jsassets.Load() - if err != nil { - panic(err) - } - 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 -// hex strings into big ints. -var bigIntProgram = goja.MustCompile("bigInt", bigIntegerJS, false) - -type toBigFn = func(vm *goja.Runtime, val string) (goja.Value, error) -type toBufFn = func(vm *goja.Runtime, val []byte) (goja.Value, error) -type fromBufFn = func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error) - -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. - return vm.New(bufType, vm.ToValue(vm.NewArrayBuffer(val))) -} - -func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString bool) ([]byte, error) { - obj := buf.ToObject(vm) - switch obj.ClassName() { - case "String": - if !allowString { - break - } - return common.FromHex(obj.String()), nil - - case "Array": - var b []byte - if err := vm.ExportTo(buf, &b); err != nil { - return nil, err - } - return b, nil - - case "Object": - if !obj.Get("constructor").SameAs(bufType) { - break - } - b := obj.Export().([]byte) - return b, nil - } - return nil, errors.New("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 *vm.EVM - toBig toBigFn // Converts a hex string into a JS bigint - toBuf toBufFn // Converts a []byte into a JS buffer - fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte - ctx map[string]goja.Value // KV-bag passed to JS in `result` - activePrecompiles []common.Address // List of active precompiles at current block - traceStep bool // True if tracer object exposes a `step()` method - traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods - gasLimit uint64 // Amount of gas bought for the whole tx - err error // Any error that should stop tracing - obj *goja.Object // Trace object - - // Methods exposed by tracer - result goja.Callable - fault goja.Callable - step goja.Callable - enter goja.Callable - exit goja.Callable - - // Underlying structs being passed into JS - log *steplog - frame *callframe - frameResult *callframeResult - - // Goja-wrapping of types prepared for JS consumption - logValue goja.Value - dbValue goja.Value - frameValue goja.Value - frameResultValue goja.Value -} - -// 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()) - t := &jsTracer{ - vm: vm, - ctx: make(map[string]goja.Value), - } - - t.setTypeConverters() - t.setBuiltinFunctions() - - if ctx == nil { - ctx = new(tracers.Context) - } - if ctx.BlockHash != (common.Hash{}) { - blockHash, err := t.toBuf(vm, ctx.BlockHash.Bytes()) - if err != nil { - return nil, err - } - t.ctx["blockHash"] = blockHash - if ctx.TxHash != (common.Hash{}) { - t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex) - txHash, err := t.toBuf(vm, ctx.TxHash.Bytes()) - if err != nil { - return nil, err - } - t.ctx["txHash"] = txHash - } - } - - ret, err := vm.RunString("(" + code + ")") - if err != nil { - return nil, err - } - // Check tracer's interface for required and optional methods. - obj := ret.ToObject(vm) - result, ok := goja.AssertFunction(obj.Get("result")) - if !ok { - return nil, errors.New("trace object must expose a function result()") - } - fault, ok := goja.AssertFunction(obj.Get("fault")) - if !ok { - return nil, errors.New("trace object must expose a function fault()") - } - step, ok := goja.AssertFunction(obj.Get("step")) - t.traceStep = ok - enter, hasEnter := goja.AssertFunction(obj.Get("enter")) - exit, hasExit := goja.AssertFunction(obj.Get("exit")) - if hasEnter != hasExit { - return nil, errors.New("trace object must expose either both or none of enter() and exit()") - } - t.traceFrame = hasEnter - t.obj = obj - t.step = step - t.enter = enter - 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, - op: &opObj{vm: vm}, - memory: &memoryObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf}, - stack: &stackObj{vm: vm, toBig: t.toBig}, - contract: &contractObj{vm: vm, toBig: t.toBig, toBuf: t.toBuf}, - } - t.frame = &callframe{vm: vm, toBig: t.toBig, toBuf: t.toBuf} - t.frameResult = &callframeResult{vm: vm, toBuf: t.toBuf} - t.frameValue = t.frame.setupObject() - t.frameResultValue = t.frameResult.setupObject() - t.logValue = t.log.setupObject() - return t, nil -} - -// CaptureTxStart implements the Tracer interface and is invoked at the beginning of -// transaction processing. -func (t *jsTracer) CaptureTxStart(gasLimit uint64) { - t.gasLimit = gasLimit -} - -// CaptureTxEnd implements the Tracer interface and is invoked at the end of -// transaction processing. -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 *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - cancel := func(err error) { - t.err = err - t.env.Cancel() - } - t.env = env - db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} - t.dbValue = db.setupObject() - if create { - t.ctx["type"] = t.vm.ToValue("CREATE") - } else { - t.ctx["type"] = t.vm.ToValue("CALL") - } - fromVal, err := t.toBuf(t.vm, from.Bytes()) - if err != nil { - cancel(err) - return - } - t.ctx["from"] = fromVal - toVal, err := t.toBuf(t.vm, to.Bytes()) - if err != nil { - cancel(err) - return - } - t.ctx["to"] = toVal - inputVal, err := t.toBuf(t.vm, input) - if err != nil { - cancel(err) - return - } - t.ctx["input"] = inputVal - t.ctx["gas"] = t.vm.ToValue(t.gasLimit) - gasPriceBig, err := t.toBig(t.vm, env.TxContext.GasPrice.String()) - if err != nil { - cancel(err) - return - } - t.ctx["gasPrice"] = gasPriceBig - valueBig, err := t.toBig(t.vm, value.String()) - if err != nil { - cancel(err) - return - } - 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, env.Context.Time) - t.activePrecompiles = vm.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 *vm.ScopeContext, rData []byte, depth int, err error) { - if !t.traceStep { - return - } - if t.err != nil { - return - } - - log := t.log - log.op.op = op - log.memory.memory = scope.Memory - log.stack.stack = scope.Stack - log.contract.contract = scope.Contract - 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) - } -} - -// CaptureFault implements the Tracer interface to trace an execution fault -func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { - if t.err != nil { - return - } - // Other log fields have been already set as part of the last CaptureState. - t.log.err = err - if _, err := t.fault(t.obj, t.logValue, t.dbValue); err != nil { - t.onError("fault", err) - } -} - -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { - if err != nil { - t.ctx["error"] = t.vm.ToValue(err.Error()) - } - outputVal, err := t.toBuf(t.vm, output) - if err != nil { - t.err = err - return - } - t.ctx["output"] = outputVal -} - -// 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) { - if !t.traceFrame { - return - } - if t.err != nil { - return - } - - t.frame.typ = typ.String() - t.frame.from = from - t.frame.to = to - t.frame.input = common.CopyBytes(input) - t.frame.gas = uint(gas) - t.frame.value = nil - if value != nil { - t.frame.value = new(big.Int).SetBytes(value.Bytes()) - } - - if _, err := t.enter(t.obj, t.frameValue); err != nil { - t.onError("enter", err) - } -} - -// CaptureExit is called when EVM exits a scope, even if the scope didn't -// execute any code. -func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) { - if !t.traceFrame { - return - } - - t.frameResult.gasUsed = uint(gasUsed) - t.frameResult.output = common.CopyBytes(output) - t.frameResult.err = err - - if _, err := t.exit(t.obj, t.frameResultValue); err != nil { - t.onError("exit", err) - } -} - -// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error -func (t *jsTracer) GetResult() (json.RawMessage, error) { - ctx := t.vm.ToValue(t.ctx) - res, err := t.result(t.obj, ctx, t.dbValue) - if err != nil { - return nil, wrapError("result", err) - } - encoded, err := json.Marshal(res) - if err != nil { - return nil, err - } - return json.RawMessage(encoded), t.err -} - -// Stop terminates execution of the tracer at the first opportune moment. -func (t *jsTracer) Stop(err error) { - t.vm.Interrupt(err) -} - -// onError is called anytime the running JS code is interrupted -// and returns an error. It in turn pings the EVM to cancel its -// execution. -func (t *jsTracer) onError(context string, err error) { - t.err = wrapError(context, err) - // `env` is set on CaptureStart which comes before any JS execution. - // So it should be non-nil. - t.env.Cancel() -} - -func wrapError(context string, err error) error { - return fmt.Errorf("%v in server-side tracer function '%v'", err, context) -} - -// setBuiltinFunctions injects Go functions which are available to tracers into the environment. -// It depends on type converters having been set up. -func (t *jsTracer) setBuiltinFunctions() { - vm := t.vm - // TODO: load console from goja-nodejs - vm.Set("toHex", func(v goja.Value) string { - b, err := t.fromBuf(vm, v, false) - if err != nil { - vm.Interrupt(err) - return "" - } - return hexutil.Encode(b) - }) - 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 { - vm.Interrupt(err) - return nil - } - b = common.BytesToHash(b).Bytes() - res, err := t.toBuf(vm, b) - if err != nil { - vm.Interrupt(err) - return nil - } - return res - }) - vm.Set("toAddress", func(v goja.Value) goja.Value { - a, err := t.fromBuf(vm, v, true) - if err != nil { - vm.Interrupt(err) - return nil - } - a = common.BytesToAddress(a).Bytes() - res, err := t.toBuf(vm, a) - if err != nil { - vm.Interrupt(err) - return nil - } - return res - }) - vm.Set("toContract", func(from goja.Value, nonce uint) goja.Value { - a, err := t.fromBuf(vm, from, true) - if err != nil { - vm.Interrupt(err) - return nil - } - addr := common.BytesToAddress(a) - b := crypto.CreateAddress(addr, uint64(nonce)).Bytes() - res, err := t.toBuf(vm, b) - if err != nil { - vm.Interrupt(err) - return nil - } - return res - }) - 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) - return nil - } - addr := common.BytesToAddress(a) - code, err := t.fromBuf(vm, initcode, true) - if err != nil { - vm.Interrupt(err) - return nil - } - code = common.CopyBytes(code) - codeHash := crypto.Keccak256(code) - b := crypto.CreateAddress2(addr, common.HexToHash(salt), codeHash).Bytes() - res, err := t.toBuf(vm, b) - if err != nil { - vm.Interrupt(err) - return nil - } - return res - }) - vm.Set("isPrecompiled", func(v goja.Value) bool { - a, err := t.fromBuf(vm, v, true) - if err != nil { - vm.Interrupt(err) - return false - } - addr := common.BytesToAddress(a) - for _, p := range t.activePrecompiles { - if p == addr { - return true - } - } - return false - }) - vm.Set("slice", func(slice goja.Value, start, end int64) goja.Value { - b, err := t.fromBuf(vm, slice, false) - if err != nil { - vm.Interrupt(err) - return nil - } - if start < 0 || start > end || end > int64(len(b)) { - vm.Interrupt(fmt.Sprintf("Tracer accessed out of bound memory: available %d, offset %d, size %d", len(b), start, end-start)) - return nil - } - res, err := t.toBuf(vm, b[start:end]) - if err != nil { - vm.Interrupt(err) - return nil - } - return res - }) -} - -// setTypeConverters sets up utilities for converting Go types into those -// suitable for JS consumption. -func (t *jsTracer) setTypeConverters() error { - // Inject bigint logic. - // TODO: To be replaced after goja adds support for native JS bigint. - toBigCode, err := t.vm.RunProgram(bigIntProgram) - if err != nil { - return err - } - // Used to create JS bigint objects from go. - toBigFn, ok := goja.AssertFunction(toBigCode) - if !ok { - return errors.New("failed to bind bigInt func") - } - toBigWrapper := func(vm *goja.Runtime, val string) (goja.Value, error) { - return toBigFn(goja.Undefined(), vm.ToValue(val)) - } - t.toBig = toBigWrapper - // NOTE: We need this workaround to create JS buffers because - // goja doesn't at the moment expose constructors for typed arrays. - // - // Cache uint8ArrayType once to be used every time for less overhead. - uint8ArrayType := t.vm.Get("Uint8Array") - toBufWrapper := func(vm *goja.Runtime, val []byte) (goja.Value, error) { - return toBuf(vm, uint8ArrayType, val) - } - t.toBuf = toBufWrapper - fromBufWrapper := func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byte, error) { - return fromBuf(vm, uint8ArrayType, buf, allowString) - } - t.fromBuf = fromBufWrapper - return nil -} - -type opObj struct { - vm *goja.Runtime - op vm.OpCode -} - -func (o *opObj) ToNumber() int { - return int(o.op) -} - -func (o *opObj) ToString() string { - return o.op.String() -} - -func (o *opObj) IsPush() bool { - return o.op.IsPush() -} - -func (o *opObj) setupObject() *goja.Object { - obj := o.vm.NewObject() - 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 -} - -type memoryObj struct { - memory *vm.Memory - vm *goja.Runtime - toBig toBigFn - toBuf toBufFn -} - -func (mo *memoryObj) Slice(begin, end int64) goja.Value { - b, err := mo.slice(begin, end) - if err != nil { - mo.vm.Interrupt(err) - return nil - } - res, err := mo.toBuf(mo.vm, b) - if err != nil { - mo.vm.Interrupt(err) - return nil - } - return res -} - -// slice returns the requested range of memory as a byte slice. -func (mo *memoryObj) slice(begin, end int64) ([]byte, error) { - if end == begin { - return []byte{}, nil - } - if end < begin || begin < 0 { - return nil, fmt.Errorf("tracer accessed out of bound memory: offset %d, end %d", begin, end) - } - slice, err := tracers.GetMemoryCopyPadded(mo.memory, begin, end-begin) - if err != nil { - return nil, err - } - return slice, nil -} - -func (mo *memoryObj) GetUint(addr int64) goja.Value { - value, err := mo.getUint(addr) - if err != nil { - mo.vm.Interrupt(err) - return nil - } - res, err := mo.toBig(mo.vm, value.String()) - if err != nil { - mo.vm.Interrupt(err) - return nil - } - return res -} - -// 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, 32) - } - return new(big.Int).SetBytes(mo.memory.GetPtr(addr, 32)), nil -} - -func (mo *memoryObj) Length() int { - return mo.memory.Len() -} - -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 -} - -type stackObj struct { - stack *vm.Stack - vm *goja.Runtime - toBig toBigFn -} - -func (s *stackObj) Peek(idx int) goja.Value { - value, err := s.peek(idx) - if err != nil { - s.vm.Interrupt(err) - return nil - } - res, err := s.toBig(s.vm, value.String()) - if err != nil { - s.vm.Interrupt(err) - return nil - } - return res -} - -// 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 s.stack.Back(idx).ToBig(), nil -} - -func (s *stackObj) Length() int { - return len(s.stack.Data()) -} - -func (s *stackObj) setupObject() *goja.Object { - o := s.vm.NewObject() - o.Set("peek", s.vm.ToValue(s.Peek)) - o.Set("length", s.vm.ToValue(s.Length)) - return o -} - -type dbObj struct { - db vm.StateDB - vm *goja.Runtime - toBig toBigFn - toBuf toBufFn - fromBuf fromBufFn -} - -func (do *dbObj) GetBalance(addrSlice goja.Value) goja.Value { - a, err := do.fromBuf(do.vm, addrSlice, false) - if err != nil { - do.vm.Interrupt(err) - return nil - } - addr := common.BytesToAddress(a) - value := do.db.GetBalance(addr) - res, err := do.toBig(do.vm, value.String()) - if err != nil { - do.vm.Interrupt(err) - return nil - } - return res -} - -func (do *dbObj) GetNonce(addrSlice goja.Value) uint64 { - a, err := do.fromBuf(do.vm, addrSlice, false) - if err != nil { - do.vm.Interrupt(err) - return 0 - } - addr := common.BytesToAddress(a) - return do.db.GetNonce(addr) -} - -func (do *dbObj) GetCode(addrSlice goja.Value) goja.Value { - a, err := do.fromBuf(do.vm, addrSlice, false) - if err != nil { - do.vm.Interrupt(err) - return nil - } - addr := common.BytesToAddress(a) - code := do.db.GetCode(addr) - res, err := do.toBuf(do.vm, code) - if err != nil { - do.vm.Interrupt(err) - return nil - } - return res -} - -func (do *dbObj) GetState(addrSlice goja.Value, hashSlice goja.Value) goja.Value { - a, err := do.fromBuf(do.vm, addrSlice, false) - if err != nil { - do.vm.Interrupt(err) - return nil - } - addr := common.BytesToAddress(a) - h, err := do.fromBuf(do.vm, hashSlice, false) - if err != nil { - do.vm.Interrupt(err) - return nil - } - hash := common.BytesToHash(h) - state := do.db.GetState(addr, hash).Bytes() - res, err := do.toBuf(do.vm, state) - if err != nil { - do.vm.Interrupt(err) - return nil - } - return res -} - -func (do *dbObj) Exists(addrSlice goja.Value) bool { - a, err := do.fromBuf(do.vm, addrSlice, false) - if err != nil { - do.vm.Interrupt(err) - return false - } - addr := common.BytesToAddress(a) - return do.db.Exist(addr) -} - -func (do *dbObj) setupObject() *goja.Object { - o := do.vm.NewObject() - 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 - vm *goja.Runtime - toBig toBigFn - toBuf toBufFn -} - -func (co *contractObj) GetCaller() goja.Value { - caller := co.contract.Caller().Bytes() - res, err := co.toBuf(co.vm, caller) - if err != nil { - co.vm.Interrupt(err) - return nil - } - return res -} - -func (co *contractObj) GetAddress() goja.Value { - addr := co.contract.Address().Bytes() - res, err := co.toBuf(co.vm, addr) - if err != nil { - co.vm.Interrupt(err) - return nil - } - return res -} - -func (co *contractObj) GetValue() goja.Value { - value := co.contract.Value() - res, err := co.toBig(co.vm, value.String()) - if err != nil { - co.vm.Interrupt(err) - return nil - } - return res -} - -func (co *contractObj) GetInput() goja.Value { - input := common.CopyBytes(co.contract.Input) - res, err := co.toBuf(co.vm, input) - if err != nil { - co.vm.Interrupt(err) - return nil - } - return res -} - -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 -} - -type callframe struct { - vm *goja.Runtime - toBig toBigFn - toBuf toBufFn - - typ string - from common.Address - to common.Address - input []byte - gas uint - value *big.Int -} - -func (f *callframe) GetType() string { - return f.typ -} - -func (f *callframe) GetFrom() goja.Value { - from := f.from.Bytes() - res, err := f.toBuf(f.vm, from) - if err != nil { - f.vm.Interrupt(err) - return nil - } - return res -} - -func (f *callframe) GetTo() goja.Value { - to := f.to.Bytes() - res, err := f.toBuf(f.vm, to) - if err != nil { - f.vm.Interrupt(err) - return nil - } - return res -} - -func (f *callframe) GetInput() goja.Value { - input := f.input - res, err := f.toBuf(f.vm, input) - if err != nil { - f.vm.Interrupt(err) - return nil - } - return res -} - -func (f *callframe) GetGas() uint { - return f.gas -} - -func (f *callframe) GetValue() goja.Value { - if f.value == nil { - return goja.Undefined() - } - res, err := f.toBig(f.vm, f.value.String()) - if err != nil { - f.vm.Interrupt(err) - return nil - } - return res -} - -func (f *callframe) setupObject() *goja.Object { - o := f.vm.NewObject() - 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 -} - -type callframeResult struct { - vm *goja.Runtime - toBuf toBufFn - - gasUsed uint - output []byte - err error -} - -func (r *callframeResult) GetGasUsed() uint { - return r.gasUsed -} - -func (r *callframeResult) GetOutput() goja.Value { - res, err := r.toBuf(r.vm, r.output) - if err != nil { - r.vm.Interrupt(err) - return nil - } - return res -} - -func (r *callframeResult) GetError() goja.Value { - if r.err != nil { - return r.vm.ToValue(r.err.Error()) - } - return goja.Undefined() -} - -func (r *callframeResult) setupObject() *goja.Object { - o := r.vm.NewObject() - 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 -} - -type steplog struct { - vm *goja.Runtime - - op *opObj - memory *memoryObj - stack *stackObj - contract *contractObj - - pc uint64 - gas uint64 - cost uint64 - depth int - refund uint64 - err error -} - -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 { - return l.vm.ToValue(l.err.Error()) - } - return goja.Undefined() -} - -func (l *steplog) setupObject() *goja.Object { - o := l.vm.NewObject() - // Setup basic fields. - 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. - 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 -} diff --git a/builder/eth/tracers/js/internal/tracers/4byte_tracer_legacy.js b/builder/eth/tracers/js/internal/tracers/4byte_tracer_legacy.js deleted file mode 100644 index e4714b8bf..000000000 --- a/builder/eth/tracers/js/internal/tracers/4byte_tracer_legacy.js +++ /dev/null @@ -1,86 +0,0 @@ -// 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 . - -// 4byteTracer 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 -// } -{ - // ids aggregates the 4byte ids found. - ids : {}, - - // callType returns 'false' for non-calls, or the peek-index for the first param - // after 'value', i.e. meminstart. - callType: function(opstr){ - switch(opstr){ - case "CALL": case "CALLCODE": - // gas, addr, val, memin, meminsz, memout, memoutsz - return 3; // stack ptr to memin - - case "DELEGATECALL": case "STATICCALL": - // gas, addr, memin, meminsz, memout, memoutsz - return 2; // stack ptr to memin - } - return false; - }, - - // store save the given identifier and datasize. - store: function(id, size){ - var key = "" + toHex(id) + "-" + size; - this.ids[key] = this.ids[key] + 1 || 1; - }, - - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - // Skip any opcodes that are not internal calls - var ct = this.callType(log.op.toString()); - if (!ct) { - return; - } - // Skip any pre-compile invocations, those are just fancy opcodes - if (isPrecompiled(toAddress(log.stack.peek(1).toString(16)))) { - return; - } - // Gather internal call details - var inSz = log.stack.peek(ct + 1).valueOf(); - if (inSz >= 4) { - var inOff = log.stack.peek(ct).valueOf(); - this.store(log.memory.slice(inOff, inOff + 4), inSz-4); - } - }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) { }, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx) { - // Save the outer calldata also - if (ctx.input.length >= 4) { - this.store(slice(ctx.input, 0, 4), ctx.input.length-4) - } - return this.ids; - }, -} diff --git a/builder/eth/tracers/js/internal/tracers/bigram_tracer.js b/builder/eth/tracers/js/internal/tracers/bigram_tracer.js deleted file mode 100644 index 421c360af..000000000 --- a/builder/eth/tracers/js/internal/tracers/bigram_tracer.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2018 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 . - -{ - // hist is the counters of opcode bigrams - hist: {}, - // lastOp is last operation - lastOp: '', - // execution depth of last op - lastDepth: 0, - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - var op = log.op.toString(); - var depth = log.getDepth(); - if (depth == this.lastDepth){ - var key = this.lastOp+'-'+op; - if (this.hist[key]){ - this.hist[key]++; - } - else { - this.hist[key] = 1; - } - } - this.lastOp = op; - this.lastDepth = depth; - }, - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) {}, - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx) { - return this.hist; - }, -} diff --git a/builder/eth/tracers/js/internal/tracers/call_tracer_legacy.js b/builder/eth/tracers/js/internal/tracers/call_tracer_legacy.js deleted file mode 100644 index 0760bb1e3..000000000 --- a/builder/eth/tracers/js/internal/tracers/call_tracer_legacy.js +++ /dev/null @@ -1,250 +0,0 @@ -// 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 . - -// callTracer is a full blown transaction tracer that extracts and reports all -// the internal calls made by a transaction, along with any useful information. -{ - // callstack is the current recursive call stack of the EVM execution. - callstack: [{}], - - // descended tracks whether we've just descended from an outer transaction into - // an inner call. - descended: false, - - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - // Capture any errors immediately - var error = log.getError(); - if (error !== undefined) { - this.fault(log, db); - return; - } - // We only care about system opcodes, faster if we pre-check once - var syscall = (log.op.toNumber() & 0xf0) == 0xf0; - if (syscall) { - var op = log.op.toString(); - } - // If a new contract is being created, add to the call stack - if (syscall && (op == 'CREATE' || op == "CREATE2")) { - var inOff = log.stack.peek(1).valueOf(); - var inEnd = inOff + log.stack.peek(2).valueOf(); - - // Assemble the internal call report and store for completion - var call = { - type: op, - from: toHex(log.contract.getAddress()), - input: toHex(log.memory.slice(inOff, inEnd)), - gasIn: log.getGas(), - gasCost: log.getCost(), - value: '0x' + log.stack.peek(0).toString(16) - }; - this.callstack.push(call); - this.descended = true - return; - } - // If a contract is being self destructed, gather that as a subcall too - if (syscall && op == 'SELFDESTRUCT') { - var left = this.callstack.length; - if (this.callstack[left-1].calls === undefined) { - this.callstack[left-1].calls = []; - } - this.callstack[left-1].calls.push({ - type: op, - from: toHex(log.contract.getAddress()), - to: toHex(toAddress(log.stack.peek(0).toString(16))), - gasIn: log.getGas(), - gasCost: log.getCost(), - value: '0x' + db.getBalance(log.contract.getAddress()).toString(16) - }); - return - } - // If a new method invocation is being done, add to the call stack - if (syscall && (op == 'CALL' || op == 'CALLCODE' || op == 'DELEGATECALL' || op == 'STATICCALL')) { - // Skip any pre-compile invocations, those are just fancy opcodes - var to = toAddress(log.stack.peek(1).toString(16)); - if (isPrecompiled(to)) { - return - } - var off = (op == 'DELEGATECALL' || op == 'STATICCALL' ? 0 : 1); - - var inOff = log.stack.peek(2 + off).valueOf(); - var inEnd = inOff + log.stack.peek(3 + off).valueOf(); - - // Assemble the internal call report and store for completion - var call = { - type: op, - from: toHex(log.contract.getAddress()), - to: toHex(to), - input: toHex(log.memory.slice(inOff, inEnd)), - gasIn: log.getGas(), - gasCost: log.getCost(), - outOff: log.stack.peek(4 + off).valueOf(), - outLen: log.stack.peek(5 + off).valueOf() - }; - if (op != 'DELEGATECALL' && op != 'STATICCALL') { - call.value = '0x' + log.stack.peek(2).toString(16); - } - this.callstack.push(call); - this.descended = true - return; - } - // If we've just descended into an inner call, retrieve it's true allowance. We - // need to extract if from within the call as there may be funky gas dynamics - // with regard to requested and actually given gas (2300 stipend, 63/64 rule). - if (this.descended) { - if (log.getDepth() >= this.callstack.length) { - this.callstack[this.callstack.length - 1].gas = log.getGas(); - } else { - // TODO(karalabe): The call was made to a plain account. We currently don't - // have access to the true gas amount inside the call and so any amount will - // mostly be wrong since it depends on a lot of input args. Skip gas for now. - } - this.descended = false; - } - // If an existing call is returning, pop off the call stack - if (syscall && op == 'REVERT') { - this.callstack[this.callstack.length - 1].error = "execution reverted"; - return; - } - if (log.getDepth() == this.callstack.length - 1) { - // Pop off the last call and get the execution results - var call = this.callstack.pop(); - - if (call.type == 'CREATE' || call.type == "CREATE2") { - // If the call was a CREATE, retrieve the contract address and output code - call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost - log.getGas()).toString(16); - delete call.gasIn; delete call.gasCost; - - var ret = log.stack.peek(0); - if (!ret.equals(0)) { - call.to = toHex(toAddress(ret.toString(16))); - call.output = toHex(db.getCode(toAddress(ret.toString(16)))); - } else if (call.error === undefined) { - call.error = "internal failure"; // TODO(karalabe): surface these faults somehow - } - } else { - // If the call was a contract call, retrieve the gas usage and output - if (call.gas !== undefined) { - call.gasUsed = '0x' + bigInt(call.gasIn - call.gasCost + call.gas - log.getGas()).toString(16); - } - var ret = log.stack.peek(0); - if (!ret.equals(0)) { - call.output = toHex(log.memory.slice(call.outOff, call.outOff + call.outLen)); - } else if (call.error === undefined) { - call.error = "internal failure"; // TODO(karalabe): surface these faults somehow - } - delete call.gasIn; delete call.gasCost; - delete call.outOff; delete call.outLen; - } - if (call.gas !== undefined) { - call.gas = '0x' + bigInt(call.gas).toString(16); - } - // Inject the call into the previous one - var left = this.callstack.length; - if (this.callstack[left-1].calls === undefined) { - this.callstack[left-1].calls = []; - } - this.callstack[left-1].calls.push(call); - } - }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) { - // If the topmost call already reverted, don't handle the additional fault again - if (this.callstack[this.callstack.length - 1].error !== undefined) { - return; - } - // Pop off the just failed call - var call = this.callstack.pop(); - call.error = log.getError(); - - // Consume all available gas and clean any leftovers - if (call.gas !== undefined) { - call.gas = '0x' + bigInt(call.gas).toString(16); - call.gasUsed = call.gas - } - delete call.gasIn; delete call.gasCost; - delete call.outOff; delete call.outLen; - - // Flatten the failed call into its parent - var left = this.callstack.length; - if (left > 0) { - if (this.callstack[left-1].calls === undefined) { - this.callstack[left-1].calls = []; - } - this.callstack[left-1].calls.push(call); - return; - } - // Last call failed too, leave it in the stack - this.callstack.push(call); - }, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx, db) { - var result = { - type: ctx.type, - from: toHex(ctx.from), - to: toHex(ctx.to), - value: '0x' + ctx.value.toString(16), - gas: '0x' + bigInt(ctx.gas).toString(16), - gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16), - input: toHex(ctx.input), - output: toHex(ctx.output), - }; - if (this.callstack[0].calls !== undefined) { - result.calls = this.callstack[0].calls; - } - if (this.callstack[0].error !== undefined) { - result.error = this.callstack[0].error; - } else if (ctx.error !== undefined) { - result.error = ctx.error; - } - if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) { - delete result.output; - } - return this.finalize(result); - }, - - // finalize recreates a call object using the final desired field order for json - // serialization. This is a nicety feature to pass meaningfully ordered results - // to users who don't interpret it, just display it. - finalize: function(call) { - var sorted = { - type: call.type, - from: call.from, - to: call.to, - value: call.value, - gas: call.gas, - gasUsed: call.gasUsed, - input: call.input, - output: call.output, - error: call.error, - calls: call.calls, - } - for (var key in sorted) { - if (sorted[key] === undefined) { - delete sorted[key]; - } - } - if (sorted.calls !== undefined) { - for (var i=0; i. - -// evmdisTracer returns sufficient information from a trace to perform evmdis-style -// disassembly. -{ - stack: [{ops: []}], - - npushes: {0: 0, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1, 10: 1, 11: 1, 16: 1, 17: 1, 18: 1, 19: 1, 20: 1, 21: 1, 22: 1, 23: 1, 24: 1, 25: 1, 26: 1, 32: 1, 48: 1, 49: 1, 50: 1, 51: 1, 52: 1, 53: 1, 54: 1, 55: 0, 56: 1, 57: 0, 58: 1, 59: 1, 60: 0, 64: 1, 65: 1, 66: 1, 67: 1, 68: 1, 69: 1, 80: 0, 81: 1, 82: 0, 83: 0, 84: 1, 85: 0, 86: 0, 87: 0, 88: 1, 89: 1, 90: 1, 91: 0, 96: 1, 97: 1, 98: 1, 99: 1, 100: 1, 101: 1, 102: 1, 103: 1, 104: 1, 105: 1, 106: 1, 107: 1, 108: 1, 109: 1, 110: 1, 111: 1, 112: 1, 113: 1, 114: 1, 115: 1, 116: 1, 117: 1, 118: 1, 119: 1, 120: 1, 121: 1, 122: 1, 123: 1, 124: 1, 125: 1, 126: 1, 127: 1, 128: 2, 129: 3, 130: 4, 131: 5, 132: 6, 133: 7, 134: 8, 135: 9, 136: 10, 137: 11, 138: 12, 139: 13, 140: 14, 141: 15, 142: 16, 143: 17, 144: 2, 145: 3, 146: 4, 147: 5, 148: 6, 149: 7, 150: 8, 151: 9, 152: 10, 153: 11, 154: 12, 155: 13, 156: 14, 157: 15, 158: 16, 159: 17, 160: 0, 161: 0, 162: 0, 163: 0, 164: 0, 240: 1, 241: 1, 242: 1, 243: 0, 244: 0, 255: 0}, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function() { return this.stack[0].ops; }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) { }, - - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - var frame = this.stack[this.stack.length - 1]; - - var error = log.getError(); - if (error) { - frame["error"] = error; - } else if (log.getDepth() == this.stack.length) { - opinfo = { - op: log.op.toNumber(), - depth : log.getDepth(), - result: [], - }; - if (frame.ops.length > 0) { - var prevop = frame.ops[frame.ops.length - 1]; - for(var i = 0; i < this.npushes[prevop.op]; i++) - prevop.result.push(log.stack.peek(i).toString(16)); - } - switch(log.op.toString()) { - case "CALL": case "CALLCODE": - var instart = log.stack.peek(3).valueOf(); - var insize = log.stack.peek(4).valueOf(); - opinfo["gas"] = log.stack.peek(0).valueOf(); - opinfo["to"] = log.stack.peek(1).toString(16); - opinfo["value"] = log.stack.peek(2).toString(); - opinfo["input"] = log.memory.slice(instart, instart + insize); - opinfo["error"] = null; - opinfo["return"] = null; - opinfo["ops"] = []; - this.stack.push(opinfo); - break; - case "DELEGATECALL": case "STATICCALL": - var instart = log.stack.peek(2).valueOf(); - var insize = log.stack.peek(3).valueOf(); - opinfo["op"] = log.op.toString(); - opinfo["gas"] = log.stack.peek(0).valueOf(); - opinfo["to"] = log.stack.peek(1).toString(16); - opinfo["input"] = log.memory.slice(instart, instart + insize); - opinfo["error"] = null; - opinfo["return"] = null; - opinfo["ops"] = []; - this.stack.push(opinfo); - break; - case "RETURN": case "REVERT": - var out = log.stack.peek(0).valueOf(); - var outsize = log.stack.peek(1).valueOf(); - frame.return = log.memory.slice(out, out + outsize); - break; - case "STOP": case "SELFDESTRUCT": - frame.return = log.memory.slice(0, 0); - break; - case "JUMPDEST": - opinfo["pc"] = log.getPC(); - } - if(log.op.isPush()) { - opinfo["len"] = log.op.toNumber() - 0x5e; - } - frame.ops.push(opinfo); - } else { - this.stack = this.stack.slice(0, log.getDepth()); - } - } -} diff --git a/builder/eth/tracers/js/internal/tracers/noop_tracer_legacy.js b/builder/eth/tracers/js/internal/tracers/noop_tracer_legacy.js deleted file mode 100644 index fe7ddc85a..000000000 --- a/builder/eth/tracers/js/internal/tracers/noop_tracer_legacy.js +++ /dev/null @@ -1,29 +0,0 @@ -// 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 . - -// noopTracer is just the barebone boilerplate code required from a JavaScript -// object to be usable as a transaction tracer. -{ - // step is invoked for every opcode that the VM executes. - step: function(log, db) { }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) { }, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx, db) { return {}; } -} diff --git a/builder/eth/tracers/js/internal/tracers/opcount_tracer.js b/builder/eth/tracers/js/internal/tracers/opcount_tracer.js deleted file mode 100644 index f7984c741..000000000 --- a/builder/eth/tracers/js/internal/tracers/opcount_tracer.js +++ /dev/null @@ -1,32 +0,0 @@ -// 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 . - -// opcountTracer is a sample tracer that just counts the number of instructions -// executed by the EVM before the transaction terminated. -{ - // count tracks the number of EVM instructions executed. - count: 0, - - // step is invoked for every opcode that the VM executes. - step: function(log, db) { this.count++ }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) { }, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx, db) { return this.count } -} diff --git a/builder/eth/tracers/js/internal/tracers/prestate_tracer_legacy.js b/builder/eth/tracers/js/internal/tracers/prestate_tracer_legacy.js deleted file mode 100644 index 2757b8b14..000000000 --- a/builder/eth/tracers/js/internal/tracers/prestate_tracer_legacy.js +++ /dev/null @@ -1,115 +0,0 @@ -// 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 . - -// prestateTracer outputs sufficient information to create a local execution of -// the transaction from a custom assembled genesis block. -{ - // prestate is the genesis that we're building. - prestate: null, - - // lookupAccount injects the specified account into the prestate object. - lookupAccount: function(addr, db){ - var acc = toHex(addr); - if (this.prestate[acc] === undefined) { - this.prestate[acc] = { - balance: '0x' + db.getBalance(addr).toString(16), - nonce: db.getNonce(addr), - code: toHex(db.getCode(addr)), - storage: {} - }; - } - }, - - // lookupStorage injects the specified storage entry of the given account into - // the prestate object. - lookupStorage: function(addr, key, db){ - var acc = toHex(addr); - var idx = toHex(key); - - if (this.prestate[acc].storage[idx] === undefined) { - this.prestate[acc].storage[idx] = toHex(db.getState(addr, key)); - } - }, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx, db) { - if (this.prestate === null) { - this.prestate = {}; - // If tx is transfer-only, the recipient account - // hasn't been populated. - this.lookupAccount(ctx.to, db); - } - - // At this point, we need to deduct the 'value' from the - // outer transaction, and move it back to the origin - this.lookupAccount(ctx.from, db); - - var fromBal = bigInt(this.prestate[toHex(ctx.from)].balance.slice(2), 16); - var toBal = bigInt(this.prestate[toHex(ctx.to)].balance.slice(2), 16); - - this.prestate[toHex(ctx.to)].balance = '0x'+toBal.subtract(ctx.value).toString(16); - this.prestate[toHex(ctx.from)].balance = '0x'+fromBal.add(ctx.value).add(ctx.gasUsed * ctx.gasPrice).toString(16); - - // Decrement the caller's nonce, and remove empty create targets - this.prestate[toHex(ctx.from)].nonce--; - if (ctx.type == 'CREATE') { - // We can blibdly delete the contract prestate, as any existing state would - // have caused the transaction to be rejected as invalid in the first place. - delete this.prestate[toHex(ctx.to)]; - } - // Return the assembled allocations (prestate) - return this.prestate; - }, - - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - // Add the current account if we just started tracing - if (this.prestate === null){ - this.prestate = {}; - // Balance will potentially be wrong here, since this will include the value - // sent along with the message. We fix that in 'result()'. - this.lookupAccount(log.contract.getAddress(), db); - } - // Whenever new state is accessed, add it to the prestate - switch (log.op.toString()) { - case "EXTCODECOPY": case "EXTCODESIZE": case "EXTCODEHASH": case "BALANCE": - this.lookupAccount(toAddress(log.stack.peek(0).toString(16)), db); - break; - case "CREATE": - var from = log.contract.getAddress(); - this.lookupAccount(toContract(from, db.getNonce(from)), db); - break; - case "CREATE2": - var from = log.contract.getAddress(); - // stack: salt, size, offset, endowment - var offset = log.stack.peek(1).valueOf() - var size = log.stack.peek(2).valueOf() - var end = offset + size - this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db); - break; - case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL": - this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db); - break; - case 'SSTORE':case 'SLOAD': - this.lookupStorage(log.contract.getAddress(), toWord(log.stack.peek(0).toString(16)), db); - break; - } - }, - - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) {} -} diff --git a/builder/eth/tracers/js/internal/tracers/tracers.go b/builder/eth/tracers/js/internal/tracers/tracers.go deleted file mode 100644 index 6547f1b08..000000000 --- a/builder/eth/tracers/js/internal/tracers/tracers.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 tracers contains the actual JavaScript tracer assets. -package tracers - -import ( - "embed" - "io/fs" - "strings" - "unicode" -) - -//go:embed *.js -var files embed.FS - -// Load reads the built-in JS tracer files embedded in the binary and -// returns a mapping of tracer name to source. -func Load() (map[string]string, error) { - var assetTracers = make(map[string]string) - err := fs.WalkDir(files, ".", func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - if d.IsDir() { - return nil - } - b, err := fs.ReadFile(files, path) - if err != nil { - return err - } - name := camel(strings.TrimSuffix(path, ".js")) - assetTracers[name] = string(b) - return nil - }) - return assetTracers, err -} - -// camel converts a snake cased input string into a camel cased output. -func camel(str string) string { - pieces := strings.Split(str, "_") - for i := 1; i < len(pieces); i++ { - pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:] - } - return strings.Join(pieces, "") -} diff --git a/builder/eth/tracers/js/internal/tracers/trigram_tracer.js b/builder/eth/tracers/js/internal/tracers/trigram_tracer.js deleted file mode 100644 index 8756490df..000000000 --- a/builder/eth/tracers/js/internal/tracers/trigram_tracer.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2018 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 . - -{ - // hist is the map of trigram counters - hist: {}, - // lastOp is last operation - lastOps: ['',''], - lastDepth: 0, - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - var depth = log.getDepth(); - if (depth != this.lastDepth){ - this.lastOps = ['','']; - this.lastDepth = depth; - return; - } - var op = log.op.toString(); - var key = this.lastOps[0]+'-'+this.lastOps[1]+'-'+op; - if (this.hist[key]){ - this.hist[key]++; - } - else { - this.hist[key] = 1; - } - this.lastOps[0] = this.lastOps[1]; - this.lastOps[1] = op; - }, - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) {}, - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx) { - return this.hist; - }, -} diff --git a/builder/eth/tracers/js/internal/tracers/unigram_tracer.js b/builder/eth/tracers/js/internal/tracers/unigram_tracer.js deleted file mode 100644 index 51107d8f3..000000000 --- a/builder/eth/tracers/js/internal/tracers/unigram_tracer.js +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2018 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 . - -{ - // hist is the map of opcodes to counters - hist: {}, - // nops counts number of ops - nops: 0, - // step is invoked for every opcode that the VM executes. - step: function(log, db) { - var op = log.op.toString(); - if (this.hist[op]){ - this.hist[op]++; - } - else { - this.hist[op] = 1; - } - this.nops++; - }, - // fault is invoked when the actual execution of an opcode fails. - fault: function(log, db) {}, - - // result is invoked when all the opcodes have been iterated over and returns - // the final result of the tracing. - result: function(ctx) { - return this.hist; - }, -} diff --git a/builder/eth/tracers/js/tracer_test.go b/builder/eth/tracers/js/tracer_test.go deleted file mode 100644 index b7f269377..000000000 --- a/builder/eth/tracers/js/tracer_test.go +++ /dev/null @@ -1,320 +0,0 @@ -// 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 js - -import ( - "encoding/json" - "errors" - "math/big" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -type account struct{} - -func (account) SubBalance(amount *big.Int) {} -func (account) AddBalance(amount *big.Int) {} -func (account) SetAddress(common.Address) {} -func (account) Value() *big.Int { return nil } -func (account) SetBalance(*uint256.Int) {} -func (account) SetNonce(uint64) {} -func (account) Balance() *uint256.Int { return nil } -func (account) Address() common.Address { return common.Address{} } -func (account) SetCode(common.Hash, []byte) {} -func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} - -type dummyStatedb struct { - state.StateDB -} - -func (*dummyStatedb) GetRefund() uint64 { return 1337 } -func (*dummyStatedb) GetBalance(addr common.Address) *uint256.Int { return new(uint256.Int) } - -type vmContext struct { - blockCtx vm.BlockContext - txCtx vm.TxContext -} - -func testCtx() *vmContext { - return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} -} - -func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) { - var ( - env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer}) - gasLimit uint64 = 31000 - startGas uint64 = 10000 - value = uint256.NewInt(0) - contract = vm.NewContract(account{}, account{}, value, startGas) - ) - contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} - if contractCode != nil { - contract.Code = contractCode - } - - tracer.CaptureTxStart(gasLimit) - tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value.ToBig()) - ret, err := env.Interpreter().Run(contract, []byte{}, false) - tracer.CaptureEnd(ret, startGas-contract.Gas, err) - // Rest gas assumes no refund - tracer.CaptureTxEnd(contract.Gas) - if err != nil { - return nil, err - } - return tracer.GetResult() -} - -func TestTracer(t *testing.T) { - execTracer := func(code string, contract []byte) ([]byte, string) { - t.Helper() - tracer, err := newJsTracer(code, nil, nil) - if err != nil { - t.Fatal(err) - } - ret, err := runTrace(tracer, testCtx(), params.TestChainConfig, contract) - if err != nil { - return nil, err.Error() // Stringify to allow comparison without nil checks - } - return ret, "" - } - for i, tt := range []struct { - code string - want string - fail string - contract []byte - }{ - { // tests that we don't panic on bad arguments to memory access - code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}", - want: ``, - fail: "tracer accessed out of bound memory: offset -1, end -2 at step (:1:53(13)) in server-side tracer function 'step'", - }, { // tests that we don't panic on bad arguments to stack peeks - code: "{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}", - want: ``, - fail: "tracer accessed out of bound stack: size 0, index -1 at step (:1:53(11)) in server-side tracer function 'step'", - }, { // tests that we don't panic on bad arguments to memory getUint - code: "{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}", - want: ``, - fail: "tracer accessed out of bound memory: available 0, offset -64, size 32 at step (:1:58(11)) in server-side tracer function 'step'", - }, { // tests some general counting - code: "{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}", - want: `3`, - }, { // tests that depth is reported correctly - code: "{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}", - want: `[0,1,2]`, - }, { // tests memory length - code: "{lengths: [], step: function(log) { this.lengths.push(log.memory.length()); }, fault: function() {}, result: function() { return this.lengths; }}", - want: `[0,0,0]`, - }, { // tests to-string of opcodes - code: "{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}", - want: `["PUSH1","PUSH1","STOP"]`, - }, { // tests gasUsed - code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed; }}", - want: `"100000.21006"`, - }, { - code: "{res: null, step: function(log) {}, fault: function() {}, result: function() { return toWord('0xffaa') }}", - want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":255,"31":170}`, - }, { // test feeding a buffer back into go - code: "{res: null, step: function(log) { var address = log.contract.getAddress(); this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}", - want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`, - }, { - code: "{res: null, step: function(log) { var address = '0x0000000000000000000000000000000000000000'; this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}", - want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`, - }, { - code: "{res: null, step: function(log) { var address = Array.prototype.slice.call(log.contract.getAddress()); this.res = toAddress(address); }, fault: function() {}, result: function() { return this.res }}", - want: `{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}`, - }, { - code: "{res: [], step: function(log) { var op = log.op.toString(); if (op === 'MSTORE8' || op === 'STOP') { this.res.push(log.memory.slice(0, 2)) } }, fault: function() {}, result: function() { return this.res }}", - want: `[{"0":0,"1":0},{"0":255,"1":0}]`, - contract: []byte{byte(vm.PUSH1), byte(0xff), byte(vm.PUSH1), byte(0x00), byte(vm.MSTORE8), byte(vm.STOP)}, - }, { - code: "{res: [], step: function(log) { if (log.op.toString() === 'STOP') { this.res.push(log.memory.slice(5, 1025 * 1024)) } }, fault: function() {}, result: function() { return this.res }}", - want: "", - fail: "reached limit for padding memory slice: 1049568 at step (:1:83(20)) in server-side tracer function 'step'", - contract: []byte{byte(vm.PUSH1), byte(0xff), byte(vm.PUSH1), byte(0x00), byte(vm.MSTORE8), byte(vm.STOP)}, - }, - } { - if have, err := execTracer(tt.code, tt.contract); tt.want != string(have) || tt.fail != err { - t.Errorf("testcase %d: expected return value to be \n'%s'\n\tgot\n'%s'\nerror to be\n'%s'\n\tgot\n'%s'\n\tcode: %v", i, tt.want, string(have), tt.fail, err, tt.code) - } - } -} - -func TestHalt(t *testing.T) { - timeout := errors.New("stahp") - tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil) - if err != nil { - t.Fatal(err) - } - go func() { - time.Sleep(1 * time.Second) - tracer.Stop(timeout) - }() - if _, err = runTrace(tracer, testCtx(), params.TestChainConfig, nil); !strings.Contains(err.Error(), "stahp") { - t.Errorf("Expected timeout error, got %v", err) - } -} - -func TestHaltBetweenSteps(t *testing.T) { - tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil) - if err != nil { - t.Fatal(err) - } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer}) - scope := &vm.ScopeContext{ - Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), - } - tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0)) - tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil) - timeout := errors.New("stahp") - tracer.Stop(timeout) - tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil) - - if _, err := tracer.GetResult(); !strings.Contains(err.Error(), timeout.Error()) { - t.Errorf("Expected timeout error, got %v", err) - } -} - -// testNoStepExec tests a regular value transfer (no exec), and accessing the statedb -// in 'result' -func TestNoStepExec(t *testing.T) { - execTracer := func(code string) []byte { - t.Helper() - tracer, err := newJsTracer(code, nil, nil) - if err != nil { - t.Fatal(err) - } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer}) - tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0)) - tracer.CaptureEnd(nil, 0, nil) - ret, err := tracer.GetResult() - if err != nil { - t.Fatal(err) - } - return ret - } - for i, tt := range []struct { - code string - want string - }{ - { // tests that we don't panic on accessing the db methods - code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx, db){ return db.getBalance(ctx.to)} }", - want: `"0"`, - }, - } { - if have := execTracer(tt.code); tt.want != string(have) { - t.Errorf("testcase %d: expected return value to be %s got %s\n\tcode: %v", i, tt.want, string(have), tt.code) - } - } -} - -func TestIsPrecompile(t *testing.T) { - chaincfg := ¶ms.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), LondonBlock: big.NewInt(0), TerminalTotalDifficulty: nil, Ethash: new(params.EthashConfig), Clique: nil} - chaincfg.ByzantiumBlock = big.NewInt(100) - chaincfg.IstanbulBlock = big.NewInt(200) - chaincfg.BerlinBlock = big.NewInt(300) - txCtx := vm.TxContext{GasPrice: big.NewInt(100000)} - tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) - if err != nil { - t.Fatal(err) - } - - blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)} - res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) - if err != nil { - t.Error(err) - } - if string(res) != "false" { - t.Errorf("tracer should not consider blake2f as precompile in byzantium") - } - - tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) - blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)} - res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) - if err != nil { - t.Error(err) - } - if string(res) != "true" { - t.Errorf("tracer should consider blake2f as precompile in istanbul") - } -} - -func TestEnterExit(t *testing.T) { - // test that either both or none of enter() and exit() are defined - if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil); err == nil { - t.Fatal("tracer creation should've failed without exit() definition") - } - if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil); err != nil { - t.Fatal(err) - } - // test that the enter and exit method are correctly invoked and the values passed - tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context), nil) - if err != nil { - t.Fatal(err) - } - scope := &vm.ScopeContext{ - Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), - } - tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int)) - tracer.CaptureExit([]byte{}, 400, nil) - - have, err := tracer.GetResult() - if err != nil { - t.Fatal(err) - } - want := `{"enters":1,"exits":1,"enterGas":1000,"gasUsed":400}` - if string(have) != want { - t.Errorf("Number of invocations of enter() and exit() is wrong. Have %s, want %s\n", have, want) - } -} - -func TestSetup(t *testing.T) { - // Test empty config - _, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil) - if err != nil { - t.Error(err) - } - - cfg, err := json.Marshal(map[string]string{"foo": "bar"}) - if err != nil { - t.Fatal(err) - } - // Test no setup func - _, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg) - if err != nil { - t.Fatal(err) - } - // Test config value - tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", new(tracers.Context), cfg) - if err != nil { - t.Fatal(err) - } - have, err := tracer.GetResult() - if err != nil { - t.Fatal(err) - } - if string(have) != `"bar"` { - t.Errorf("tracer returned wrong result. have: %s, want: \"bar\"\n", string(have)) - } -} diff --git a/builder/eth/tracers/logger/access_list_tracer.go b/builder/eth/tracers/logger/access_list_tracer.go deleted file mode 100644 index 766ee4e4b..000000000 --- a/builder/eth/tracers/logger/access_list_tracer.go +++ /dev/null @@ -1,183 +0,0 @@ -// 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 logger - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" -) - -// accessList is an accumulator for the set of accounts and storage slots an EVM -// contract execution touches. -type accessList map[common.Address]accessListSlots - -// accessListSlots is an accumulator for the set of storage slots within a single -// contract that an EVM contract execution touches. -type accessListSlots map[common.Hash]struct{} - -// newAccessList creates a new accessList. -func newAccessList() accessList { - return make(map[common.Address]accessListSlots) -} - -// addAddress adds an address to the accesslist. -func (al accessList) addAddress(address common.Address) { - // Set address if not previously present - if _, present := al[address]; !present { - al[address] = make(map[common.Hash]struct{}) - } -} - -// addSlot adds a storage slot to the accesslist. -func (al accessList) addSlot(address common.Address, slot common.Hash) { - // Set address if not previously present - al.addAddress(address) - - // Set the slot on the surely existent storage set - al[address][slot] = struct{}{} -} - -// equal checks if the content of the current access list is the same as the -// content of the other one. -func (al accessList) equal(other accessList) bool { - // Cross reference the accounts first - if len(al) != len(other) { - return false - } - // Given that len(al) == len(other), we only need to check that - // all the items from al are in other. - for addr := range al { - if _, ok := other[addr]; !ok { - return false - } - } - - // Accounts match, cross reference the storage slots too - for addr, slots := range al { - otherslots := other[addr] - - if len(slots) != len(otherslots) { - return false - } - // Given that len(slots) == len(otherslots), we only need to check that - // all the items from slots are in otherslots. - for hash := range slots { - if _, ok := otherslots[hash]; !ok { - return false - } - } - } - return true -} - -// accesslist converts the accesslist to a types.AccessList. -func (al accessList) accessList() types.AccessList { - acl := make(types.AccessList, 0, len(al)) - for addr, slots := range al { - tuple := types.AccessTuple{Address: addr, StorageKeys: []common.Hash{}} - for slot := range slots { - tuple.StorageKeys = append(tuple.StorageKeys, slot) - } - acl = append(acl, tuple) - } - return acl -} - -// AccessListTracer is a tracer that accumulates touched accounts and storage -// slots into an internal set. -type AccessListTracer struct { - excl map[common.Address]struct{} // Set of account to exclude from the list - list accessList // Set of accounts and storage slots touched -} - -// NewAccessListTracer creates a new tracer that can generate AccessLists. -// An optional AccessList can be specified to occupy slots and addresses in -// the resulting accesslist. -func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompiles []common.Address) *AccessListTracer { - excl := map[common.Address]struct{}{ - from: {}, to: {}, - } - for _, addr := range precompiles { - excl[addr] = struct{}{} - } - list := newAccessList() - for _, al := range acl { - if _, ok := excl[al.Address]; !ok { - list.addAddress(al.Address) - } - for _, slot := range al.StorageKeys { - list.addSlot(al.Address, slot) - } - } - return &AccessListTracer{ - excl: excl, - list: list, - } -} - -func (a *AccessListTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { -} - -// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist. -func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - stack := scope.Stack - stackData := stack.Data() - stackLen := len(stackData) - if (op == vm.SLOAD || op == vm.SSTORE) && stackLen >= 1 { - slot := common.Hash(stackData[stackLen-1].Bytes32()) - a.list.addSlot(scope.Contract.Address(), slot) - } - if (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT) && stackLen >= 1 { - addr := common.Address(stackData[stackLen-1].Bytes20()) - if _, ok := a.excl[addr]; !ok { - a.list.addAddress(addr) - } - } - if (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE) && stackLen >= 5 { - addr := common.Address(stackData[stackLen-2].Bytes20()) - if _, ok := a.excl[addr]; !ok { - a.list.addAddress(addr) - } - } -} - -func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { -} - -func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {} - -func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { -} - -func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {} - -func (*AccessListTracer) CaptureTxStart(gasLimit uint64) {} - -func (*AccessListTracer) CaptureTxEnd(restGas uint64) {} - -// AccessList returns the current accesslist maintained by the tracer. -func (a *AccessListTracer) AccessList() types.AccessList { - return a.list.accessList() -} - -// Equal returns if the content of two access list traces are equal. -func (a *AccessListTracer) Equal(other *AccessListTracer) bool { - return a.list.equal(other.list) -} diff --git a/builder/eth/tracers/logger/account_touch_tracer.go b/builder/eth/tracers/logger/account_touch_tracer.go deleted file mode 100644 index 899bcee2c..000000000 --- a/builder/eth/tracers/logger/account_touch_tracer.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 flashbots -// 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 logger - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" -) - -type AccountTouchTracer struct { - touched map[common.Address]struct{} -} - -// NewAccountTouchTracer creates new AccountTouchTracer -// that collect all addresses touched in the given tx -// including tx sender and tx.to from the top level call -func NewAccountTouchTracer() *AccountTouchTracer { - return &AccountTouchTracer{ - touched: make(map[common.Address]struct{}), - } -} - -func (t *AccountTouchTracer) TouchedAddressesSet() map[common.Address]struct{} { - return t.touched -} - -func (t *AccountTouchTracer) TouchedAddresses() []common.Address { - result := make([]common.Address, 0, len(t.touched)) - - for address := range t.touched { - result = append(result, address) - } - return result -} - -func (t *AccountTouchTracer) CaptureTxStart(uint64) {} - -func (t *AccountTouchTracer) CaptureTxEnd(uint64) {} - -func (t *AccountTouchTracer) CaptureStart(_ *vm.EVM, from common.Address, to common.Address, _ bool, _ []byte, _ uint64, _ *big.Int) { - t.touched[from] = struct{}{} - t.touched[to] = struct{}{} -} - -func (t *AccountTouchTracer) CaptureEnd([]byte, uint64, error) {} - -func (t *AccountTouchTracer) CaptureEnter(_ vm.OpCode, _ common.Address, to common.Address, _ []byte, _ uint64, _ *big.Int) { - t.touched[to] = struct{}{} -} - -func (t *AccountTouchTracer) CaptureExit([]byte, uint64, error) {} - -func (t *AccountTouchTracer) CaptureState(_ uint64, op vm.OpCode, _, _ uint64, scope *vm.ScopeContext, _ []byte, _ int, _ error) { - stack := scope.Stack - stackData := stack.Data() - stackLen := len(stackData) - if (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT) && stackLen >= 1 { - addr := common.Address(stackData[stackLen-1].Bytes20()) - t.touched[addr] = struct{}{} - } -} - -func (t *AccountTouchTracer) CaptureFault(uint64, vm.OpCode, uint64, uint64, *vm.ScopeContext, int, error) { -} diff --git a/builder/eth/tracers/logger/gen_structlog.go b/builder/eth/tracers/logger/gen_structlog.go deleted file mode 100644 index b406cb344..000000000 --- a/builder/eth/tracers/logger/gen_structlog.go +++ /dev/null @@ -1,118 +0,0 @@ -// Code generated by github.com/fjl/gencodec. DO NOT EDIT. - -package logger - -import ( - "encoding/json" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/holiman/uint256" -) - -var _ = (*structLogMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (s StructLog) MarshalJSON() ([]byte, error) { - type StructLog struct { - Pc uint64 `json:"pc"` - Op vm.OpCode `json:"op"` - Gas math.HexOrDecimal64 `json:"gas"` - GasCost math.HexOrDecimal64 `json:"gasCost"` - Memory hexutil.Bytes `json:"memory,omitempty"` - MemorySize int `json:"memSize"` - Stack []hexutil.U256 `json:"stack"` - ReturnData hexutil.Bytes `json:"returnData,omitempty"` - Storage map[common.Hash]common.Hash `json:"-"` - Depth int `json:"depth"` - RefundCounter uint64 `json:"refund"` - Err error `json:"-"` - OpName string `json:"opName"` - ErrorString string `json:"error,omitempty"` - } - var enc StructLog - enc.Pc = s.Pc - enc.Op = s.Op - enc.Gas = math.HexOrDecimal64(s.Gas) - enc.GasCost = math.HexOrDecimal64(s.GasCost) - enc.Memory = s.Memory - enc.MemorySize = s.MemorySize - if s.Stack != nil { - enc.Stack = make([]hexutil.U256, len(s.Stack)) - for k, v := range s.Stack { - enc.Stack[k] = hexutil.U256(v) - } - } - enc.ReturnData = s.ReturnData - enc.Storage = s.Storage - enc.Depth = s.Depth - enc.RefundCounter = s.RefundCounter - enc.Err = s.Err - enc.OpName = s.OpName() - enc.ErrorString = s.ErrorString() - return json.Marshal(&enc) -} - -// UnmarshalJSON unmarshals from JSON. -func (s *StructLog) UnmarshalJSON(input []byte) error { - type StructLog struct { - Pc *uint64 `json:"pc"` - Op *vm.OpCode `json:"op"` - Gas *math.HexOrDecimal64 `json:"gas"` - GasCost *math.HexOrDecimal64 `json:"gasCost"` - Memory *hexutil.Bytes `json:"memory,omitempty"` - MemorySize *int `json:"memSize"` - Stack []hexutil.U256 `json:"stack"` - ReturnData *hexutil.Bytes `json:"returnData,omitempty"` - Storage map[common.Hash]common.Hash `json:"-"` - Depth *int `json:"depth"` - RefundCounter *uint64 `json:"refund"` - Err error `json:"-"` - } - var dec StructLog - if err := json.Unmarshal(input, &dec); err != nil { - return err - } - if dec.Pc != nil { - s.Pc = *dec.Pc - } - if dec.Op != nil { - s.Op = *dec.Op - } - if dec.Gas != nil { - s.Gas = uint64(*dec.Gas) - } - if dec.GasCost != nil { - s.GasCost = uint64(*dec.GasCost) - } - if dec.Memory != nil { - s.Memory = *dec.Memory - } - if dec.MemorySize != nil { - s.MemorySize = *dec.MemorySize - } - if dec.Stack != nil { - s.Stack = make([]uint256.Int, len(dec.Stack)) - for k, v := range dec.Stack { - s.Stack[k] = uint256.Int(v) - } - } - if dec.ReturnData != nil { - s.ReturnData = *dec.ReturnData - } - if dec.Storage != nil { - s.Storage = dec.Storage - } - if dec.Depth != nil { - s.Depth = *dec.Depth - } - if dec.RefundCounter != nil { - s.RefundCounter = *dec.RefundCounter - } - if dec.Err != nil { - s.Err = dec.Err - } - return nil -} diff --git a/builder/eth/tracers/logger/logger.go b/builder/eth/tracers/logger/logger.go deleted file mode 100644 index 2b36f9f49..000000000 --- a/builder/eth/tracers/logger/logger.go +++ /dev/null @@ -1,467 +0,0 @@ -// 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 logger - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "io" - "math/big" - "strings" - "sync/atomic" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -// Storage represents a contract's storage. -type Storage map[common.Hash]common.Hash - -// Copy duplicates the current storage. -func (s Storage) Copy() Storage { - cpy := make(Storage, len(s)) - for key, value := range s { - cpy[key] = value - } - return cpy -} - -// Config are the configuration options for structured logger the EVM -type Config struct { - EnableMemory bool // enable memory capture - DisableStack bool // disable stack capture - DisableStorage bool // disable storage capture - EnableReturnData bool // enable return data capture - Debug bool // print output during capture end - Limit int // maximum length of output, but zero means unlimited - // Chain overrides, can be used to execute a trace using future fork rules - Overrides *params.ChainConfig `json:"overrides,omitempty"` -} - -//go:generate go run github.com/fjl/gencodec -type StructLog -field-override structLogMarshaling -out gen_structlog.go - -// StructLog is emitted to the EVM each cycle and lists information about the current internal state -// prior to the execution of the statement. -type StructLog struct { - Pc uint64 `json:"pc"` - Op vm.OpCode `json:"op"` - Gas uint64 `json:"gas"` - GasCost uint64 `json:"gasCost"` - Memory []byte `json:"memory,omitempty"` - MemorySize int `json:"memSize"` - Stack []uint256.Int `json:"stack"` - ReturnData []byte `json:"returnData,omitempty"` - Storage map[common.Hash]common.Hash `json:"-"` - Depth int `json:"depth"` - RefundCounter uint64 `json:"refund"` - Err error `json:"-"` -} - -// overrides for gencodec -type structLogMarshaling struct { - Gas math.HexOrDecimal64 - GasCost math.HexOrDecimal64 - Memory hexutil.Bytes - ReturnData hexutil.Bytes - Stack []hexutil.U256 - OpName string `json:"opName"` // adds call to OpName() in MarshalJSON - ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON -} - -// OpName formats the operand name in a human-readable format. -func (s *StructLog) OpName() string { - return s.Op.String() -} - -// ErrorString formats the log's error as a string. -func (s *StructLog) ErrorString() string { - if s.Err != nil { - return s.Err.Error() - } - return "" -} - -// StructLogger is an EVM state logger and implements EVMLogger. -// -// StructLogger can capture state based on the given Log configuration and also keeps -// a track record of modified storage which is used in reporting snapshots of the -// contract their storage. -type StructLogger struct { - cfg Config - env *vm.EVM - - storage map[common.Address]Storage - logs []StructLog - output []byte - err error - gasLimit uint64 - usedGas uint64 - - interrupt atomic.Bool // Atomic flag to signal execution interruption - reason error // Textual reason for the interruption -} - -// NewStructLogger returns a new logger -func NewStructLogger(cfg *Config) *StructLogger { - logger := &StructLogger{ - storage: make(map[common.Address]Storage), - } - if cfg != nil { - logger.cfg = *cfg - } - return logger -} - -// Reset clears the data held by the logger. -func (l *StructLogger) Reset() { - l.storage = make(map[common.Address]Storage) - l.output = make([]byte, 0) - l.logs = l.logs[:0] - l.err = nil -} - -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - l.env = env -} - -// CaptureState logs a new structured log message and pushes it out to the environment -// -// CaptureState also tracks SLOAD/SSTORE ops to track storage change. -func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - // If tracing was interrupted, set the error and stop - if l.interrupt.Load() { - return - } - // check if already accumulated the specified number of logs - if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) { - return - } - - memory := scope.Memory - stack := scope.Stack - contract := scope.Contract - // Copy a snapshot of the current memory state to a new buffer - var mem []byte - if l.cfg.EnableMemory { - mem = make([]byte, len(memory.Data())) - copy(mem, memory.Data()) - } - // Copy a snapshot of the current stack state to a new buffer - var stck []uint256.Int - if !l.cfg.DisableStack { - stck = make([]uint256.Int, len(stack.Data())) - for i, item := range stack.Data() { - stck[i] = item - } - } - stackData := stack.Data() - stackLen := len(stackData) - // Copy a snapshot of the current storage to a new container - var storage Storage - if !l.cfg.DisableStorage && (op == vm.SLOAD || op == vm.SSTORE) { - // initialise new changed values storage container for this contract - // if not present. - if l.storage[contract.Address()] == nil { - l.storage[contract.Address()] = make(Storage) - } - // capture SLOAD opcodes and record the read entry in the local storage - if op == vm.SLOAD && stackLen >= 1 { - var ( - address = common.Hash(stackData[stackLen-1].Bytes32()) - value = l.env.StateDB.GetState(contract.Address(), address) - ) - l.storage[contract.Address()][address] = value - storage = l.storage[contract.Address()].Copy() - } else if op == vm.SSTORE && stackLen >= 2 { - // capture SSTORE opcodes and record the written entry in the local storage. - var ( - value = common.Hash(stackData[stackLen-2].Bytes32()) - address = common.Hash(stackData[stackLen-1].Bytes32()) - ) - l.storage[contract.Address()][address] = value - storage = l.storage[contract.Address()].Copy() - } - } - var rdata []byte - if l.cfg.EnableReturnData { - rdata = make([]byte, len(rData)) - copy(rdata, rData) - } - // create a new snapshot of the EVM. - log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err} - l.logs = append(l.logs, log) -} - -// CaptureFault implements the EVMLogger interface to trace an execution fault -// while running an opcode. -func (l *StructLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { -} - -// CaptureEnd is called after the call finishes to finalize the tracing. -func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error) { - l.output = output - l.err = err - if l.cfg.Debug { - fmt.Printf("%#x\n", output) - if err != nil { - fmt.Printf(" error: %v\n", err) - } - } -} - -func (l *StructLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { -} - -func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) { -} - -func (l *StructLogger) GetResult() (json.RawMessage, error) { - // Tracing aborted - if l.reason != nil { - return nil, l.reason - } - failed := l.err != nil - returnData := common.CopyBytes(l.output) - // Return data when successful and revert reason when reverted, otherwise empty. - returnVal := fmt.Sprintf("%x", returnData) - if failed && l.err != vm.ErrExecutionReverted { - returnVal = "" - } - return json.Marshal(&ExecutionResult{ - Gas: l.usedGas, - Failed: failed, - ReturnValue: returnVal, - StructLogs: formatLogs(l.StructLogs()), - }) -} - -// Stop terminates execution of the tracer at the first opportune moment. -func (l *StructLogger) Stop(err error) { - l.reason = err - l.interrupt.Store(true) -} - -func (l *StructLogger) CaptureTxStart(gasLimit uint64) { - l.gasLimit = gasLimit -} - -func (l *StructLogger) CaptureTxEnd(restGas uint64) { - l.usedGas = l.gasLimit - restGas -} - -// StructLogs returns the captured log entries. -func (l *StructLogger) StructLogs() []StructLog { return l.logs } - -// Error returns the VM error captured by the trace. -func (l *StructLogger) Error() error { return l.err } - -// Output returns the VM return value captured by the trace. -func (l *StructLogger) Output() []byte { return l.output } - -// WriteTrace writes a formatted trace to the given writer -func WriteTrace(writer io.Writer, logs []StructLog) { - for _, log := range logs { - fmt.Fprintf(writer, "%-16spc=%08d gas=%v cost=%v", log.Op, log.Pc, log.Gas, log.GasCost) - if log.Err != nil { - fmt.Fprintf(writer, " ERROR: %v", log.Err) - } - fmt.Fprintln(writer) - - if len(log.Stack) > 0 { - fmt.Fprintln(writer, "Stack:") - for i := len(log.Stack) - 1; i >= 0; i-- { - fmt.Fprintf(writer, "%08d %s\n", len(log.Stack)-i-1, log.Stack[i].Hex()) - } - } - if len(log.Memory) > 0 { - fmt.Fprintln(writer, "Memory:") - fmt.Fprint(writer, hex.Dump(log.Memory)) - } - if len(log.Storage) > 0 { - fmt.Fprintln(writer, "Storage:") - for h, item := range log.Storage { - fmt.Fprintf(writer, "%x: %x\n", h, item) - } - } - if len(log.ReturnData) > 0 { - fmt.Fprintln(writer, "ReturnData:") - fmt.Fprint(writer, hex.Dump(log.ReturnData)) - } - fmt.Fprintln(writer) - } -} - -// WriteLogs writes vm logs in a readable format to the given writer -func WriteLogs(writer io.Writer, logs []*types.Log) { - for _, log := range logs { - fmt.Fprintf(writer, "LOG%d: %x bn=%d txi=%x\n", len(log.Topics), log.Address, log.BlockNumber, log.TxIndex) - - for i, topic := range log.Topics { - fmt.Fprintf(writer, "%08d %x\n", i, topic) - } - - fmt.Fprint(writer, hex.Dump(log.Data)) - fmt.Fprintln(writer) - } -} - -type mdLogger struct { - out io.Writer - cfg *Config - env *vm.EVM -} - -// NewMarkdownLogger creates a logger which outputs information in a format adapted -// for human readability, and is also a valid markdown table -func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger { - l := &mdLogger{out: writer, cfg: cfg} - if l.cfg == nil { - l.cfg = &Config{} - } - return l -} - -func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.env = env - if !create { - fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n", - from.String(), to.String(), - input, gas, value) - } else { - fmt.Fprintf(t.out, "From: `%v`\nCreate at: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n", - from.String(), to.String(), - input, gas, value) - } - - fmt.Fprintf(t.out, ` -| Pc | Op | Cost | Stack | RStack | Refund | -|-------|-------------|------|-----------|-----------|---------| -`) -} - -// CaptureState also tracks SLOAD/SSTORE ops to track storage change. -func (t *mdLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - stack := scope.Stack - fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost) - - if !t.cfg.DisableStack { - // format stack - var a []string - for _, elem := range stack.Data() { - a = append(a, elem.Hex()) - } - b := fmt.Sprintf("[%v]", strings.Join(a, ",")) - fmt.Fprintf(t.out, "%10v |", b) - } - fmt.Fprintf(t.out, "%10v |", t.env.StateDB.GetRefund()) - fmt.Fprintln(t.out, "") - if err != nil { - fmt.Fprintf(t.out, "Error: %v\n", err) - } -} - -func (t *mdLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { - fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err) -} - -func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, err error) { - fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n", - output, gasUsed, err) -} - -func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { -} - -func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} - -func (*mdLogger) CaptureTxStart(gasLimit uint64) {} - -func (*mdLogger) CaptureTxEnd(restGas uint64) {} - -// ExecutionResult groups all structured logs emitted by the EVM -// while replaying a transaction in debug mode as well as transaction -// execution status, the amount of gas used and the return value -type ExecutionResult struct { - Gas uint64 `json:"gas"` - Failed bool `json:"failed"` - ReturnValue string `json:"returnValue"` - StructLogs []StructLogRes `json:"structLogs"` -} - -// StructLogRes stores a structured log emitted by the EVM while replaying a -// transaction in debug mode -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 *[]string `json:"stack,omitempty"` - ReturnData string `json:"returnData,omitempty"` - Memory *[]string `json:"memory,omitempty"` - Storage *map[string]string `json:"storage,omitempty"` - RefundCounter uint64 `json:"refund,omitempty"` -} - -// formatLogs formats EVM returned structured logs for json output -func formatLogs(logs []StructLog) []StructLogRes { - formatted := make([]StructLogRes, len(logs)) - for index, trace := range logs { - formatted[index] = StructLogRes{ - Pc: trace.Pc, - Op: trace.Op.String(), - Gas: trace.Gas, - GasCost: trace.GasCost, - Depth: trace.Depth, - Error: trace.ErrorString(), - RefundCounter: trace.RefundCounter, - } - if trace.Stack != nil { - stack := make([]string, len(trace.Stack)) - for i, stackValue := range trace.Stack { - stack[i] = stackValue.Hex() - } - formatted[index].Stack = &stack - } - if trace.ReturnData != nil && len(trace.ReturnData) > 0 { - formatted[index].ReturnData = hexutil.Bytes(trace.ReturnData).String() - } - if trace.Memory != nil { - memory := make([]string, 0, (len(trace.Memory)+31)/32) - for i := 0; i+32 <= len(trace.Memory); i += 32 { - memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32])) - } - formatted[index].Memory = &memory - } - if trace.Storage != nil { - storage := make(map[string]string) - for i, storageValue := range trace.Storage { - storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue) - } - formatted[index].Storage = &storage - } - } - return formatted -} diff --git a/builder/eth/tracers/logger/logger_json.go b/builder/eth/tracers/logger/logger_json.go deleted file mode 100644 index a2cb4cd9f..000000000 --- a/builder/eth/tracers/logger/logger_json.go +++ /dev/null @@ -1,102 +0,0 @@ -// 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 logger - -import ( - "encoding/json" - "io" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/vm" -) - -type JSONLogger struct { - encoder *json.Encoder - cfg *Config - env *vm.EVM -} - -// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects -// into the provided stream. -func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger { - l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg} - if l.cfg == nil { - l.cfg = &Config{} - } - return l -} - -func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - l.env = env -} - -func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) { - // TODO: Add rData to this interface as well - l.CaptureState(pc, op, gas, cost, scope, nil, depth, err) -} - -// CaptureState outputs state information on the logger. -func (l *JSONLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - memory := scope.Memory - stack := scope.Stack - - log := StructLog{ - Pc: pc, - Op: op, - Gas: gas, - GasCost: cost, - MemorySize: memory.Len(), - Depth: depth, - RefundCounter: l.env.StateDB.GetRefund(), - Err: err, - } - if l.cfg.EnableMemory { - log.Memory = memory.Data() - } - if !l.cfg.DisableStack { - log.Stack = stack.Data() - } - if l.cfg.EnableReturnData { - log.ReturnData = rData - } - l.encoder.Encode(log) -} - -// CaptureEnd is triggered at end of execution. -func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error) { - type endLog struct { - Output string `json:"output"` - GasUsed math.HexOrDecimal64 `json:"gasUsed"` - Err string `json:"error,omitempty"` - } - var errMsg string - if err != nil { - errMsg = err.Error() - } - l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg}) -} - -func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { -} - -func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {} - -func (l *JSONLogger) CaptureTxStart(gasLimit uint64) {} - -func (l *JSONLogger) CaptureTxEnd(restGas uint64) {} diff --git a/builder/eth/tracers/logger/logger_test.go b/builder/eth/tracers/logger/logger_test.go deleted file mode 100644 index 1d8eb320f..000000000 --- a/builder/eth/tracers/logger/logger_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// 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 logger - -import ( - "encoding/json" - "errors" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" -) - -type dummyContractRef struct { - calledForEach bool -} - -func (dummyContractRef) Address() common.Address { return common.Address{} } -func (dummyContractRef) Value() *big.Int { return new(big.Int) } -func (dummyContractRef) SetCode(common.Hash, []byte) {} -func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) { - d.calledForEach = true -} -func (d *dummyContractRef) SubBalance(amount *big.Int) {} -func (d *dummyContractRef) AddBalance(amount *big.Int) {} -func (d *dummyContractRef) SetBalance(*big.Int) {} -func (d *dummyContractRef) SetNonce(uint64) {} -func (d *dummyContractRef) Balance() *big.Int { return new(big.Int) } - -type dummyStatedb struct { - state.StateDB -} - -func (*dummyStatedb) GetRefund() uint64 { return 1337 } -func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} } -func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {} - -func TestStoreCapture(t *testing.T) { - var ( - logger = NewStructLogger(nil) - env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger}) - contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000) - ) - contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} - var index common.Hash - logger.CaptureStart(env, common.Address{}, contract.Address(), false, nil, 0, nil) - _, err := env.Interpreter().Run(contract, []byte{}, false) - if err != nil { - t.Fatal(err) - } - if len(logger.storage[contract.Address()]) == 0 { - t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), - len(logger.storage[contract.Address()])) - } - exp := common.BigToHash(big.NewInt(1)) - if logger.storage[contract.Address()][index] != exp { - t.Errorf("expected %x, got %x", exp, logger.storage[contract.Address()][index]) - } -} - -// Tests that blank fields don't appear in logs when JSON marshalled, to reduce -// logs bloat and confusion. See https://github.com/ethereum/go-ethereum/issues/24487 -func TestStructLogMarshalingOmitEmpty(t *testing.T) { - tests := []struct { - name string - log *StructLog - want string - }{ - {"empty err and no fields", &StructLog{}, - `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, - {"with err", &StructLog{Err: errors.New("this failed")}, - `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP","error":"this failed"}`}, - {"with mem", &StructLog{Memory: make([]byte, 2), MemorySize: 2}, - `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memory":"0x0000","memSize":2,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, - {"with 0-size mem", &StructLog{Memory: make([]byte, 0)}, - `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - blob, err := json.Marshal(tt.log) - if err != nil { - t.Fatal(err) - } - if have, want := string(blob), tt.want; have != want { - t.Fatalf("mismatched results\n\thave: %v\n\twant: %v", have, want) - } - }) - } -} diff --git a/builder/eth/tracers/native/4byte.go b/builder/eth/tracers/native/4byte.go deleted file mode 100644 index 5a2c4f911..000000000 --- a/builder/eth/tracers/native/4byte.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" -) - -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 atomic.Bool // 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 *vm.EVM, 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 = vm.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 vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { - // Skip if tracing was interrupted - if t.interrupt.Load() { - return - } - if len(input) < 4 { - return - } - // primarily we want to avoid CREATE/CREATE2/SELFDESTRUCT - if op != vm.DELEGATECALL && op != vm.STATICCALL && - op != vm.CALL && op != vm.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 - t.interrupt.Store(true) -} - -func bytesToHex(s []byte) string { - return "0x" + common.Bytes2Hex(s) -} diff --git a/builder/eth/tracers/native/call.go b/builder/eth/tracers/native/call.go deleted file mode 100644 index be9b58a4c..000000000 --- a/builder/eth/tracers/native/call.go +++ /dev/null @@ -1,289 +0,0 @@ -// 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/ethereum/go-ethereum/accounts/abi" - "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/eth/tracers" - "github.com/ethereum/go-ethereum/log" -) - -//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"` - // Position of the log relative to subcalls within the same trace - // See https://github.com/ethereum/go-ethereum/pull/28389 for details - Position hexutil.Uint `json:"position"` -} - -type callFrame struct { - Type vm.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 == vm.CREATE || f.Type == vm.CREATE2 { - f.To = nil - } - if !errors.Is(err, vm.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 atomic.Bool // 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 vm.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 *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - toCopy := to - t.callstack[0] = callFrame{ - Type: vm.CALL, - From: from, - To: &toCopy, - Input: common.CopyBytes(input), - Gas: t.gasLimit, - Value: value, - } - if create { - t.callstack[0].Type = vm.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 vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - // skip if the previous op caused an error - if err != nil { - return - } - // 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 > 1 { - return - } - // Skip if tracing was interrupted - if t.interrupt.Load() { - return - } - switch op { - case vm.LOG0, vm.LOG1, vm.LOG2, vm.LOG3, vm.LOG4: - size := int(op - vm.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, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(mStart.Uint64()), int64(mSize.Uint64())) - if err != nil { - // mSize was unrealistically large - log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "callTracer", "offset", mStart, "size", mSize) - return - } - - log := callLog{ - Address: scope.Contract.Address(), - Topics: topics, - Data: hexutil.Bytes(data), - Position: hexutil.Uint(len(t.callstack[len(t.callstack)-1].Calls)), - } - 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 vm.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 t.interrupt.Load() { - 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 - t.interrupt.Store(true) -} - -// 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/builder/eth/tracers/native/call_flat.go b/builder/eth/tracers/native/call_flat.go deleted file mode 100644 index 266ab9900..000000000 --- a/builder/eth/tracers/native/call_flat.go +++ /dev/null @@ -1,381 +0,0 @@ -// 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/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" -) - -//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 - } - } - - // Create inner call tracer with default configuration, don't forward - // the OnlyTopCall or WithLog to inner for now - tracer, err := tracers.DefaultDirectory.New("callTracer", ctx, nil) - 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 *vm.EVM, 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 = vm.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 vm.OpCode, gas, cost uint64, scope *vm.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 vm.OpCode, gas, cost uint64, scope *vm.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 vm.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 == vm.CALL || typ == vm.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 vm.CREATE, vm.CREATE2: - frame = newFlatCreate(input) - case vm.SELFDESTRUCT: - frame = newFlatSelfdestruct(input) - case vm.CALL, vm.STATICCALL, vm.CALLCODE, vm.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 != vm.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(vm.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(vm.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 newFlatSelfdestruct(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/builder/eth/tracers/native/gen_account_json.go b/builder/eth/tracers/native/gen_account_json.go deleted file mode 100644 index 4c39cbc38..000000000 --- a/builder/eth/tracers/native/gen_account_json.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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/builder/eth/tracers/native/gen_callframe_json.go b/builder/eth/tracers/native/gen_callframe_json.go deleted file mode 100644 index c44f38390..000000000 --- a/builder/eth/tracers/native/gen_callframe_json.go +++ /dev/null @@ -1,107 +0,0 @@ -// 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/ethereum/go-ethereum/core/vm" -) - -var _ = (*callFrameMarshaling)(nil) - -// MarshalJSON marshals as JSON. -func (c callFrame) MarshalJSON() ([]byte, error) { - type callFrame0 struct { - Type vm.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 *vm.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/builder/eth/tracers/native/gen_flatcallaction_json.go b/builder/eth/tracers/native/gen_flatcallaction_json.go deleted file mode 100644 index c07560698..000000000 --- a/builder/eth/tracers/native/gen_flatcallaction_json.go +++ /dev/null @@ -1,110 +0,0 @@ -// 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/builder/eth/tracers/native/gen_flatcallresult_json.go b/builder/eth/tracers/native/gen_flatcallresult_json.go deleted file mode 100644 index e9fa5e44d..000000000 --- a/builder/eth/tracers/native/gen_flatcallresult_json.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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/builder/eth/tracers/native/mux.go b/builder/eth/tracers/native/mux.go deleted file mode 100644 index db8ddd643..000000000 --- a/builder/eth/tracers/native/mux.go +++ /dev/null @@ -1,138 +0,0 @@ -// 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/builder/eth/tracers/native/noop.go b/builder/eth/tracers/native/noop.go deleted file mode 100644 index 3beecd8ab..000000000 --- a/builder/eth/tracers/native/noop.go +++ /dev/null @@ -1,77 +0,0 @@ -// 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/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers" -) - -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 *vm.EVM, 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 vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { -} - -// CaptureFault implements the EVMLogger interface to trace an execution fault. -func (t *noopTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { -} - -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *noopTracer) CaptureEnter(typ vm.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/builder/eth/tracers/native/prestate.go b/builder/eth/tracers/native/prestate.go deleted file mode 100644 index d7e10173c..000000000 --- a/builder/eth/tracers/native/prestate.go +++ /dev/null @@ -1,297 +0,0 @@ -// 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/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/log" -) - -//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 *vm.EVM - pre state - post state - create bool - to common.Address - gasLimit uint64 // Amount of gas bought for the whole tx - config prestateTracerConfig - interrupt atomic.Bool // 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 *vm.EVM, 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 vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { - if err != nil { - return - } - // Skip if tracing was interrupted - if t.interrupt.Load() { - return - } - stack := scope.Stack - stackData := stack.Data() - stackLen := len(stackData) - caller := scope.Contract.Address() - switch { - case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE): - slot := common.Hash(stackData[stackLen-1].Bytes32()) - t.lookupStorage(caller, slot) - case stackLen >= 1 && (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT): - addr := common.Address(stackData[stackLen-1].Bytes20()) - t.lookupAccount(addr) - if op == vm.SELFDESTRUCT { - t.deleted[caller] = true - } - case stackLen >= 5 && (op == vm.DELEGATECALL || op == vm.CALL || op == vm.STATICCALL || op == vm.CALLCODE): - addr := common.Address(stackData[stackLen-2].Bytes20()) - t.lookupAccount(addr) - case op == vm.CREATE: - nonce := t.env.StateDB.GetNonce(caller) - addr := crypto.CreateAddress(caller, nonce) - t.lookupAccount(addr) - t.created[addr] = true - case stackLen >= 4 && op == vm.CREATE2: - offset := stackData[stackLen-2] - size := stackData[stackLen-3] - init, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(offset.Uint64()), int64(size.Uint64())) - if err != nil { - log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "prestateTracer", "offset", offset, "size", size) - return - } - 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).ToBig() - 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 - t.interrupt.Store(true) -} - -// 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).ToBig(), - 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/builder/eth/tracers/tracers.go b/builder/eth/tracers/tracers.go deleted file mode 100644 index 7b43b7cf8..000000000 --- a/builder/eth/tracers/tracers.go +++ /dev/null @@ -1,123 +0,0 @@ -// 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 tracers is a manager for transaction tracing engines. -package tracers - -import ( - "encoding/json" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" -) - -// 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) - 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 -// allows collecting the tracing result. -type Tracer interface { - vm.EVMLogger - GetResult() (json.RawMessage, error) - // Stop terminates execution of the tracer at the first opportune moment. - Stop(err error) -} - -type ctorFn func(*Context, json.RawMessage) (Tracer, error) -type jsCtorFn func(string, *Context, json.RawMessage) (Tracer, error) - -type elem struct { - ctor ctorFn - isJS bool -} - -// 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. 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 - } - // JS eval will execute JS code - return true -} - -const ( - memoryPadLimit = 1024 * 1024 -) - -// GetMemoryCopyPadded returns offset + size as a new slice. -// It zero-pads the slice if it extends beyond memory bounds. -func GetMemoryCopyPadded(m *vm.Memory, offset, size int64) ([]byte, error) { - if offset < 0 || size < 0 { - return nil, errors.New("offset or size must not be negative") - } - if int(offset+size) < m.Len() { // slice fully inside memory - return m.GetCopy(offset, size), nil - } - paddingNeeded := int(offset+size) - m.Len() - if paddingNeeded > memoryPadLimit { - return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded) - } - cpy := make([]byte, size) - if overlap := int64(m.Len()) - offset; overlap > 0 { - copy(cpy, m.GetPtr(offset, overlap)) - } - return cpy, nil -} diff --git a/builder/eth/tracers/tracers_test.go b/builder/eth/tracers/tracers_test.go deleted file mode 100644 index 6ac266e06..000000000 --- a/builder/eth/tracers/tracers_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// 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 tracers - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/tests" -) - -func BenchmarkTransactionTrace(b *testing.B) { - key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - from := crypto.PubkeyToAddress(key.PublicKey) - gas := uint64(1000000) // 1M gas - to := common.HexToAddress("0x00000000000000000000000000000000deadbeef") - signer := types.LatestSignerForChainID(big.NewInt(1337)) - tx, err := types.SignNewTx(key, signer, - &types.LegacyTx{ - Nonce: 1, - GasPrice: big.NewInt(500), - Gas: gas, - To: &to, - }) - if err != nil { - b.Fatal(err) - } - txContext := vm.TxContext{ - Origin: from, - GasPrice: tx.GasPrice(), - } - context := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - Coinbase: common.Address{}, - BlockNumber: new(big.Int).SetUint64(uint64(5)), - Time: 5, - Difficulty: big.NewInt(0xffffffff), - GasLimit: gas, - BaseFee: big.NewInt(8), - } - alloc := types.GenesisAlloc{} - // The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns - // the address - loop := []byte{ - byte(vm.JUMPDEST), // [ count ] - byte(vm.PUSH1), 0, // jumpdestination - byte(vm.JUMP), - } - alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = types.Account{ - Nonce: 1, - Code: loop, - Balance: big.NewInt(1), - } - alloc[from] = types.Account{ - Nonce: 1, - Code: []byte{}, - Balance: big.NewInt(500000000000000), - } - state := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme) - defer state.Close() - - // Create the tracer, the EVM environment and run it - tracer := logger.NewStructLogger(&logger.Config{ - Debug: false, - //DisableStorage: true, - //EnableMemory: false, - //EnableReturnData: false, - }) - evm := vm.NewEVM(context, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer}) - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) - if err != nil { - b.Fatalf("failed to prepare transaction for tracing: %v", err) - } - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < b.N; i++ { - snap := state.StateDB.Snapshot() - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) - _, err = st.TransitionDb() - if err != nil { - b.Fatal(err) - } - state.StateDB.RevertToSnapshot(snap) - if have, want := len(tracer.StructLogs()), 244752; have != want { - b.Fatalf("trace wrong, want %d steps, have %d", want, have) - } - tracer.Reset() - } -} - -func TestMemCopying(t *testing.T) { - for i, tc := range []struct { - memsize int64 - offset int64 - size int64 - wantErr string - wantSize int - }{ - {0, 0, 100, "", 100}, // Should pad up to 100 - {0, 100, 0, "", 0}, // No need to pad (0 size) - {100, 50, 100, "", 100}, // Should pad 100-150 - {100, 50, 5, "", 5}, // Wanted range fully within memory - {100, -50, 0, "offset or size must not be negative", 0}, // Error - {0, 1, 1024*1024 + 1, "reached limit for padding memory slice: 1048578", 0}, // Error - {10, 0, 1024*1024 + 100, "reached limit for padding memory slice: 1048666", 0}, // Error - - } { - mem := vm.NewMemory() - mem.Resize(uint64(tc.memsize)) - cpy, err := GetMemoryCopyPadded(mem, tc.offset, tc.size) - if want := tc.wantErr; want != "" { - if err == nil { - t.Fatalf("test %d: want '%v' have no error", i, want) - } - if have := err.Error(); want != have { - t.Fatalf("test %d: want '%v' have '%v'", i, want, have) - } - continue - } - if err != nil { - t.Fatalf("test %d: unexpected error: %v", i, err) - } - if want, have := tc.wantSize, len(cpy); have != want { - t.Fatalf("test %d: want %v have %v", i, want, have) - } - } -} diff --git a/builder/eth/tracers/tracker.go b/builder/eth/tracers/tracker.go deleted file mode 100644 index 136be37f5..000000000 --- a/builder/eth/tracers/tracker.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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 tracers - -import ( - "fmt" - "sync" -) - -// stateTracker is an auxiliary tool used to cache the release functions of all -// used trace states, and to determine whether the creation of trace state needs -// to be paused in case there are too many states waiting for tracing. -type stateTracker struct { - limit int // Maximum number of states allowed waiting for tracing - oldest uint64 // The number of the oldest state which is still using for trace - used []bool // List of flags indicating whether the trace state has been used up - releases []StateReleaseFunc // List of trace state release functions waiting to be called - cond *sync.Cond - lock *sync.RWMutex -} - -// newStateTracker initializes the tracker with provided state limits and -// the number of the first state that will be used. -func newStateTracker(limit int, oldest uint64) *stateTracker { - lock := new(sync.RWMutex) - return &stateTracker{ - limit: limit, - oldest: oldest, - used: make([]bool, limit), - cond: sync.NewCond(lock), - lock: lock, - } -} - -// releaseState marks the state specified by the number as released and caches -// the corresponding release functions internally. -func (t *stateTracker) releaseState(number uint64, release StateReleaseFunc) { - t.lock.Lock() - defer t.lock.Unlock() - - // Set the state as used, the corresponding flag is indexed by - // the distance between the specified state and the oldest state - // which is still using for trace. - t.used[int(number-t.oldest)] = true - - // If the oldest state is used up, update the oldest marker by moving - // it to the next state which is not used up. - if number == t.oldest { - var count int - for _, used := range t.used { - if !used { - break - } - count += 1 - } - t.oldest += uint64(count) - copy(t.used, t.used[count:]) - - // Clean up the array tail since they are useless now. - for i := t.limit - count; i < t.limit; i++ { - t.used[i] = false - } - // Fire the signal to all waiters that oldest marker is updated. - t.cond.Broadcast() - } - t.releases = append(t.releases, release) -} - -// callReleases invokes all cached release functions. -func (t *stateTracker) callReleases() { - t.lock.Lock() - defer t.lock.Unlock() - - for _, release := range t.releases { - release() - } - t.releases = t.releases[:0] -} - -// wait blocks until the accumulated trace states are less than the limit. -func (t *stateTracker) wait(number uint64) error { - t.lock.Lock() - defer t.lock.Unlock() - - for { - if number < t.oldest { - return fmt.Errorf("invalid state number %d head %d", number, t.oldest) - } - if number < t.oldest+uint64(t.limit) { - // number is now within limit, wait over - return nil - } - t.cond.Wait() - } -} diff --git a/builder/eth/tracers/tracker_test.go b/builder/eth/tracers/tracker_test.go deleted file mode 100644 index 46f6ac8e5..000000000 --- a/builder/eth/tracers/tracker_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// 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 tracers - -import ( - "reflect" - "testing" - "time" -) - -func TestTracker(t *testing.T) { - var cases = []struct { - limit int - calls []uint64 - expHead uint64 - }{ - // Release in order - { - limit: 3, - calls: []uint64{0, 1, 2}, - expHead: 3, - }, - { - limit: 3, - calls: []uint64{0, 1, 2, 3, 4, 5}, - expHead: 6, - }, - - // Release out of order - { - limit: 3, - calls: []uint64{1, 2, 0}, - expHead: 3, - }, - { - limit: 3, - calls: []uint64{1, 2, 0, 5, 4, 3}, - expHead: 6, - }, - } - for _, c := range cases { - tracker := newStateTracker(c.limit, 0) - for _, call := range c.calls { - tracker.releaseState(call, func() {}) - } - tracker.lock.RLock() - head := tracker.oldest - tracker.lock.RUnlock() - - if head != c.expHead { - t.Fatalf("Unexpected head want %d got %d", c.expHead, head) - } - } - - var calls = []struct { - number uint64 - expUsed []bool - expHead uint64 - }{ - // Release the first one, update the oldest flag - { - number: 0, - expUsed: []bool{false, false, false, false, false}, - expHead: 1, - }, - // Release the second one, oldest shouldn't be updated - { - number: 2, - expUsed: []bool{false, true, false, false, false}, - expHead: 1, - }, - // Release the forth one, oldest shouldn't be updated - { - number: 4, - expUsed: []bool{false, true, false, true, false}, - expHead: 1, - }, - // Release the first one, the first two should all be cleaned, - // and the remaining flags should all be left-shifted. - { - number: 1, - expUsed: []bool{false, true, false, false, false}, - expHead: 3, - }, - // Release the first one, the first two should all be cleaned - { - number: 3, - expUsed: []bool{false, false, false, false, false}, - expHead: 5, - }, - } - tracker := newStateTracker(5, 0) // limit = 5, oldest = 0 - for _, call := range calls { - tracker.releaseState(call.number, nil) - tracker.lock.RLock() - if !reflect.DeepEqual(tracker.used, call.expUsed) { - t.Fatalf("Unexpected used array") - } - if tracker.oldest != call.expHead { - t.Fatalf("Unexpected head") - } - tracker.lock.RUnlock() - } -} - -func TestTrackerWait(t *testing.T) { - var ( - tracker = newStateTracker(5, 0) // limit = 5, oldest = 0 - result = make(chan error, 1) - doCall = func(number uint64) { - go func() { - result <- tracker.wait(number) - }() - } - checkNoWait = func() { - select { - case <-result: - return - case <-time.NewTimer(time.Second).C: - t.Fatal("No signal fired") - } - } - checkWait = func() { - select { - case <-result: - t.Fatal("Unexpected signal") - case <-time.NewTimer(time.Millisecond * 100).C: - } - } - ) - // States [0, 5) should all be available - doCall(0) - checkNoWait() - - doCall(4) - checkNoWait() - - // State 5 is not available - doCall(5) - checkWait() - - // States [1, 6) are available - tracker.releaseState(0, nil) - checkNoWait() - - // States [1, 6) are available - doCall(7) - checkWait() - - // States [2, 7) are available - tracker.releaseState(1, nil) - checkWait() - - // States [3, 8) are available - tracker.releaseState(2, nil) - checkNoWait() -} diff --git a/builder/ethclient/ethclient.go b/builder/ethclient/ethclient.go deleted file mode 100644 index 5c3cb79dd..000000000 --- a/builder/ethclient/ethclient.go +++ /dev/null @@ -1,727 +0,0 @@ -// Copyright 2016 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 ethclient provides a client for the Ethereum RPC API. -package ethclient - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" -) - -// Client defines typed wrappers for the Ethereum RPC API. -type Client struct { - c *rpc.Client -} - -// Dial connects a client to the given URL. -func Dial(rawurl string) (*Client, error) { - return DialContext(context.Background(), rawurl) -} - -// DialContext connects a client to the given URL with context. -func DialContext(ctx context.Context, rawurl string) (*Client, error) { - c, err := rpc.DialContext(ctx, rawurl) - if err != nil { - return nil, err - } - return NewClient(c), nil -} - -// NewClient creates a client that uses the given RPC client. -func NewClient(c *rpc.Client) *Client { - return &Client{c} -} - -// Close closes the underlying RPC connection. -func (ec *Client) Close() { - ec.c.Close() -} - -// Client gets the underlying RPC client. -func (ec *Client) Client() *rpc.Client { - return ec.c -} - -// Blockchain Access - -// ChainID retrieves the current chain ID for transaction replay protection. -func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { - var result hexutil.Big - err := ec.c.CallContext(ctx, &result, "eth_chainId") - if err != nil { - return nil, err - } - return (*big.Int)(&result), err -} - -// BlockByHash returns the given full block. -// -// Note that loading full blocks requires two requests. Use HeaderByHash -// if you don't need all transactions or uncle headers. -func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { - return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) -} - -// BlockByNumber returns a block from the current canonical chain. If number is nil, the -// latest known block is returned. -// -// Note that loading full blocks requires two requests. Use HeaderByNumber -// if you don't need all transactions or uncle headers. -func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true) -} - -// BlockNumber returns the most recent block number -func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) { - var result hexutil.Uint64 - err := ec.c.CallContext(ctx, &result, "eth_blockNumber") - return uint64(result), err -} - -// PeerCount returns the number of p2p peers as reported by the net_peerCount method. -func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { - var result hexutil.Uint64 - err := ec.c.CallContext(ctx, &result, "net_peerCount") - return uint64(result), err -} - -// BlockReceipts returns the receipts of a given block number or hash. -func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { - var r []*types.Receipt - err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) - if err == nil && r == nil { - return nil, ethereum.NotFound - } - return r, err -} - -type rpcBlock struct { - Hash common.Hash `json:"hash"` - Transactions []rpcTransaction `json:"transactions"` - UncleHashes []common.Hash `json:"uncles"` - Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` -} - -func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { - var raw json.RawMessage - err := ec.c.CallContext(ctx, &raw, method, args...) - if err != nil { - return nil, err - } - - // Decode header and transactions. - var head *types.Header - if err := json.Unmarshal(raw, &head); err != nil { - return nil, err - } - // When the block is not found, the API returns JSON null. - if head == nil { - return nil, ethereum.NotFound - } - - var body rpcBlock - if err := json.Unmarshal(raw, &body); err != nil { - return nil, err - } - // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. - if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { - return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles") - } - if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { - return nil, errors.New("server returned empty uncle list but block header indicates uncles") - } - if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 { - return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions") - } - if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 { - return nil, errors.New("server returned empty transaction list but block header indicates transactions") - } - // Load uncles because they are not included in the block response. - var uncles []*types.Header - if len(body.UncleHashes) > 0 { - uncles = make([]*types.Header, len(body.UncleHashes)) - reqs := make([]rpc.BatchElem, len(body.UncleHashes)) - for i := range reqs { - reqs[i] = rpc.BatchElem{ - Method: "eth_getUncleByBlockHashAndIndex", - Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))}, - Result: &uncles[i], - } - } - if err := ec.c.BatchCallContext(ctx, reqs); err != nil { - return nil, err - } - for i := range reqs { - if reqs[i].Error != nil { - return nil, reqs[i].Error - } - if uncles[i] == nil { - return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:]) - } - } - } - // Fill the sender cache of transactions in the block. - txs := make([]*types.Transaction, len(body.Transactions)) - for i, tx := range body.Transactions { - if tx.From != nil { - setSenderFromServer(tx.tx, *tx.From, body.Hash) - } - txs[i] = tx.tx - } - return types.NewBlockWithHeader(head).WithBody(txs, uncles).WithWithdrawals(body.Withdrawals), nil -} - -// HeaderByHash returns the block header with the given hash. -func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - var head *types.Header - err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) - if err == nil && head == nil { - err = ethereum.NotFound - } - return head, err -} - -// HeaderByNumber returns a block header from the current canonical chain. If number is -// nil, the latest known header is returned. -func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - var head *types.Header - err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) - if err == nil && head == nil { - err = ethereum.NotFound - } - return head, err -} - -type rpcTransaction struct { - tx *types.Transaction - txExtraInfo -} - -type txExtraInfo struct { - BlockNumber *string `json:"blockNumber,omitempty"` - BlockHash *common.Hash `json:"blockHash,omitempty"` - From *common.Address `json:"from,omitempty"` -} - -func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { - if err := json.Unmarshal(msg, &tx.tx); err != nil { - return err - } - return json.Unmarshal(msg, &tx.txExtraInfo) -} - -// TransactionByHash returns the transaction with the given hash. -func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { - var json *rpcTransaction - err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash) - if err != nil { - return nil, false, err - } else if json == nil { - return nil, false, ethereum.NotFound - } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { - return nil, false, errors.New("server returned transaction without signature") - } - if json.From != nil && json.BlockHash != nil { - setSenderFromServer(json.tx, *json.From, *json.BlockHash) - } - return json.tx, json.BlockNumber == nil, nil -} - -// TransactionSender returns the sender address of the given transaction. The transaction -// must be known to the remote node and included in the blockchain at the given block and -// index. The sender is the one derived by the protocol at the time of inclusion. -// -// There is a fast-path for transactions retrieved by TransactionByHash and -// TransactionInBlock. Getting their sender address can be done without an RPC interaction. -func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { - // Try to load the address from the cache. - sender, err := types.Sender(&senderFromServer{blockhash: block}, tx) - if err == nil { - return sender, nil - } - - // It was not found in cache, ask the server. - var meta struct { - Hash common.Hash - From common.Address - } - if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil { - return common.Address{}, err - } - if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() { - return common.Address{}, errors.New("wrong inclusion block/index") - } - return meta.From, nil -} - -// TransactionCount returns the total number of transactions in the given block. -func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { - var num hexutil.Uint - err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash) - return uint(num), err -} - -// TransactionInBlock returns a single transaction at index in the given block. -func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { - var json *rpcTransaction - err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) - if err != nil { - return nil, err - } - if json == nil { - return nil, ethereum.NotFound - } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { - return nil, errors.New("server returned transaction without signature") - } - if json.From != nil && json.BlockHash != nil { - setSenderFromServer(json.tx, *json.From, *json.BlockHash) - } - return json.tx, err -} - -// TransactionReceipt returns the receipt of a transaction by transaction hash. -// Note that the receipt is not available for pending transactions. -func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - var r *types.Receipt - err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) - if err == nil && r == nil { - return nil, ethereum.NotFound - } - return r, err -} - -// SyncProgress retrieves the current progress of the sync algorithm. If there's -// no sync currently running, it returns nil. -func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { - var raw json.RawMessage - if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil { - return nil, err - } - // Handle the possible response types - var syncing bool - if err := json.Unmarshal(raw, &syncing); err == nil { - return nil, nil // Not syncing (always false) - } - var p *rpcProgress - if err := json.Unmarshal(raw, &p); err != nil { - return nil, err - } - return p.toSyncProgress(), nil -} - -// SubscribeNewHead subscribes to notifications about the current blockchain head -// on the given channel. -func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { - sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads") - if err != nil { - // Defensively prefer returning nil interface explicitly on error-path, instead - // of letting default golang behavior wrap it with non-nil interface that stores - // nil concrete type value. - return nil, err - } - return sub, nil -} - -// State Access - -// NetworkID returns the network ID for this client. -func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) { - version := new(big.Int) - var ver string - if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil { - return nil, err - } - if _, ok := version.SetString(ver, 10); !ok { - return nil, fmt.Errorf("invalid net_version result %q", ver) - } - return version, nil -} - -// BalanceAt returns the wei balance of the given account. -// The block number can be nil, in which case the balance is taken from the latest known block. -func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { - var result hexutil.Big - err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber)) - return (*big.Int)(&result), err -} - -// BalanceAtHash returns the wei balance of the given account. -func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) { - var result hexutil.Big - err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) - return (*big.Int)(&result), err -} - -// StorageAt returns the value of key in the contract storage of the given account. -// The block number can be nil, in which case the value is taken from the latest known block. -func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber)) - return result, err -} - -// StorageAtHash returns the value of key in the contract storage of the given account. -func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false)) - return result, err -} - -// CodeAt returns the contract code of the given account. -// The block number can be nil, in which case the code is taken from the latest known block. -func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber)) - return result, err -} - -// CodeAtHash returns the contract code of the given account. -func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) - return result, err -} - -// NonceAt returns the account nonce of the given account. -// The block number can be nil, in which case the nonce is taken from the latest known block. -func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { - var result hexutil.Uint64 - err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber)) - return uint64(result), err -} - -// NonceAtHash returns the account nonce of the given account. -func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) { - var result hexutil.Uint64 - err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) - return uint64(result), err -} - -// Filters - -// FilterLogs executes a filter query. -func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { - var result []types.Log - arg, err := toFilterArg(q) - if err != nil { - return nil, err - } - err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg) - return result, err -} - -// SubscribeFilterLogs subscribes to the results of a streaming filter query. -func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { - arg, err := toFilterArg(q) - if err != nil { - return nil, err - } - sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg) - if err != nil { - // Defensively prefer returning nil interface explicitly on error-path, instead - // of letting default golang behavior wrap it with non-nil interface that stores - // nil concrete type value. - return nil, err - } - return sub, nil -} - -func toFilterArg(q ethereum.FilterQuery) (interface{}, error) { - arg := map[string]interface{}{ - "address": q.Addresses, - "topics": q.Topics, - } - if q.BlockHash != nil { - arg["blockHash"] = *q.BlockHash - if q.FromBlock != nil || q.ToBlock != nil { - return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock") - } - } else { - if q.FromBlock == nil { - arg["fromBlock"] = "0x0" - } else { - arg["fromBlock"] = toBlockNumArg(q.FromBlock) - } - arg["toBlock"] = toBlockNumArg(q.ToBlock) - } - return arg, nil -} - -// Pending State - -// PendingBalanceAt returns the wei balance of the given account in the pending state. -func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { - var result hexutil.Big - err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending") - return (*big.Int)(&result), err -} - -// PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. -func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending") - return result, err -} - -// PendingCodeAt returns the contract code of the given account in the pending state. -func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { - var result hexutil.Bytes - err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending") - return result, err -} - -// PendingNonceAt returns the account nonce of the given account in the pending state. -// This is the nonce that should be used for the next transaction. -func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { - var result hexutil.Uint64 - err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending") - return uint64(result), err -} - -// PendingTransactionCount returns the total number of transactions in the pending state. -func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) { - var num hexutil.Uint - err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending") - return uint(num), err -} - -// Contract Calling - -// CallContract executes a message call transaction, which is directly executed in the VM -// of the node, but never mined into the blockchain. -// -// blockNumber selects the block height at which the call runs. It can be nil, in which -// case the code is taken from the latest known block. Note that state from very old -// blocks might not be available. -func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - var hex hexutil.Bytes - err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber)) - if err != nil { - return nil, err - } - return hex, nil -} - -// CallContractAtHash is almost the same as CallContract except that it selects -// the block by block hash instead of block height. -func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) { - var hex hexutil.Bytes - err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) - if err != nil { - return nil, err - } - return hex, nil -} - -// PendingCallContract executes a message call transaction using the EVM. -// The state seen by the contract call is the pending state. -func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { - var hex hexutil.Bytes - err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending") - if err != nil { - return nil, err - } - return hex, nil -} - -// SuggestGasPrice retrieves the currently suggested gas price to allow a timely -// execution of a transaction. -func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - var hex hexutil.Big - if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil { - return nil, err - } - return (*big.Int)(&hex), nil -} - -// SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to -// allow a timely execution of a transaction. -func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { - var hex hexutil.Big - if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil { - return nil, err - } - return (*big.Int)(&hex), nil -} - -type feeHistoryResultMarshaling struct { - OldestBlock *hexutil.Big `json:"oldestBlock"` - Reward [][]*hexutil.Big `json:"reward,omitempty"` - BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` - GasUsedRatio []float64 `json:"gasUsedRatio"` -} - -// FeeHistory retrieves the fee market history. -func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { - var res feeHistoryResultMarshaling - if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil { - return nil, err - } - reward := make([][]*big.Int, len(res.Reward)) - for i, r := range res.Reward { - reward[i] = make([]*big.Int, len(r)) - for j, r := range r { - reward[i][j] = (*big.Int)(r) - } - } - baseFee := make([]*big.Int, len(res.BaseFee)) - for i, b := range res.BaseFee { - baseFee[i] = (*big.Int)(b) - } - return ðereum.FeeHistory{ - OldestBlock: (*big.Int)(res.OldestBlock), - Reward: reward, - BaseFee: baseFee, - GasUsedRatio: res.GasUsedRatio, - }, nil -} - -// EstimateGas tries to estimate the gas needed to execute a specific transaction based on -// the current pending state of the backend blockchain. There is no guarantee that this is -// the true gas limit requirement as other transactions may be added or removed by miners, -// but it should provide a basis for setting a reasonable default. -func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { - var hex hexutil.Uint64 - err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) - if err != nil { - return 0, err - } - return uint64(hex), nil -} - -// SendTransaction injects a signed transaction into the pending pool for execution. -// -// If the transaction was a contract creation use the TransactionReceipt method to get the -// contract address after the transaction has been mined. -func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { - data, err := tx.MarshalBinary() - if err != nil { - return err - } - return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) -} - -func toBlockNumArg(number *big.Int) string { - if number == nil { - return "latest" - } - if number.Sign() >= 0 { - return hexutil.EncodeBig(number) - } - // It's negative. - if number.IsInt64() { - return rpc.BlockNumber(number.Int64()).String() - } - // It's negative and large, which is invalid. - return fmt.Sprintf("", number) -} - -func toCallArg(msg ethereum.CallMsg) interface{} { - arg := map[string]interface{}{ - "from": msg.From, - "to": msg.To, - } - if len(msg.Data) > 0 { - arg["input"] = hexutil.Bytes(msg.Data) - } - if msg.Value != nil { - arg["value"] = (*hexutil.Big)(msg.Value) - } - if msg.Gas != 0 { - arg["gas"] = hexutil.Uint64(msg.Gas) - } - if msg.GasPrice != nil { - arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) - } - if msg.GasFeeCap != nil { - arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap) - } - if msg.GasTipCap != nil { - arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap) - } - if msg.AccessList != nil { - arg["accessList"] = msg.AccessList - } - if msg.BlobGasFeeCap != nil { - arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap) - } - if msg.BlobHashes != nil { - arg["blobVersionedHashes"] = msg.BlobHashes - } - return arg -} - -// rpcProgress is a copy of SyncProgress with hex-encoded fields. -type rpcProgress struct { - StartingBlock hexutil.Uint64 - CurrentBlock hexutil.Uint64 - HighestBlock hexutil.Uint64 - - PulledStates hexutil.Uint64 - KnownStates hexutil.Uint64 - - SyncedAccounts hexutil.Uint64 - SyncedAccountBytes hexutil.Uint64 - SyncedBytecodes hexutil.Uint64 - SyncedBytecodeBytes hexutil.Uint64 - SyncedStorage hexutil.Uint64 - SyncedStorageBytes hexutil.Uint64 - HealedTrienodes hexutil.Uint64 - HealedTrienodeBytes hexutil.Uint64 - HealedBytecodes hexutil.Uint64 - HealedBytecodeBytes hexutil.Uint64 - HealingTrienodes hexutil.Uint64 - HealingBytecode hexutil.Uint64 - TxIndexFinishedBlocks hexutil.Uint64 - TxIndexRemainingBlocks hexutil.Uint64 -} - -func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress { - if p == nil { - return nil - } - return ðereum.SyncProgress{ - StartingBlock: uint64(p.StartingBlock), - CurrentBlock: uint64(p.CurrentBlock), - HighestBlock: uint64(p.HighestBlock), - PulledStates: uint64(p.PulledStates), - KnownStates: uint64(p.KnownStates), - SyncedAccounts: uint64(p.SyncedAccounts), - SyncedAccountBytes: uint64(p.SyncedAccountBytes), - SyncedBytecodes: uint64(p.SyncedBytecodes), - SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes), - SyncedStorage: uint64(p.SyncedStorage), - SyncedStorageBytes: uint64(p.SyncedStorageBytes), - HealedTrienodes: uint64(p.HealedTrienodes), - HealedTrienodeBytes: uint64(p.HealedTrienodeBytes), - HealedBytecodes: uint64(p.HealedBytecodes), - HealedBytecodeBytes: uint64(p.HealedBytecodeBytes), - HealingTrienodes: uint64(p.HealingTrienodes), - HealingBytecode: uint64(p.HealingBytecode), - TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks), - TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks), - } -} diff --git a/builder/ethclient/ethclient_test.go b/builder/ethclient/ethclient_test.go deleted file mode 100644 index 0d2675f8d..000000000 --- a/builder/ethclient/ethclient_test.go +++ /dev/null @@ -1,757 +0,0 @@ -// Copyright 2016 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 ethclient - -import ( - "bytes" - "context" - "errors" - "math/big" - "reflect" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -// Verify that Client implements the ethereum interfaces. -var ( - _ = ethereum.ChainReader(&Client{}) - _ = ethereum.TransactionReader(&Client{}) - _ = ethereum.ChainStateReader(&Client{}) - _ = ethereum.ChainSyncReader(&Client{}) - _ = ethereum.ContractCaller(&Client{}) - _ = ethereum.GasEstimator(&Client{}) - _ = ethereum.GasPricer(&Client{}) - _ = ethereum.LogFilterer(&Client{}) - _ = ethereum.PendingStateReader(&Client{}) - // _ = ethereum.PendingStateEventer(&Client{}) - _ = ethereum.PendingContractCaller(&Client{}) -) - -func TestToFilterArg(t *testing.T) { - blockHashErr := errors.New("cannot specify both BlockHash and FromBlock/ToBlock") - addresses := []common.Address{ - common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"), - } - blockHash := common.HexToHash( - "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb", - ) - - for _, testCase := range []struct { - name string - input ethereum.FilterQuery - output interface{} - err error - }{ - { - "without BlockHash", - ethereum.FilterQuery{ - Addresses: addresses, - FromBlock: big.NewInt(1), - ToBlock: big.NewInt(2), - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "0x1", - "toBlock": "0x2", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with nil fromBlock and nil toBlock", - ethereum.FilterQuery{ - Addresses: addresses, - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "0x0", - "toBlock": "latest", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with negative fromBlock and negative toBlock", - ethereum.FilterQuery{ - Addresses: addresses, - FromBlock: big.NewInt(-1), - ToBlock: big.NewInt(-1), - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "fromBlock": "pending", - "toBlock": "pending", - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with blockhash", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - Topics: [][]common.Hash{}, - }, - map[string]interface{}{ - "address": addresses, - "blockHash": blockHash, - "topics": [][]common.Hash{}, - }, - nil, - }, - { - "with blockhash and from block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - FromBlock: big.NewInt(1), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - { - "with blockhash and to block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - ToBlock: big.NewInt(1), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - { - "with blockhash and both from / to block", - ethereum.FilterQuery{ - Addresses: addresses, - BlockHash: &blockHash, - FromBlock: big.NewInt(1), - ToBlock: big.NewInt(2), - Topics: [][]common.Hash{}, - }, - nil, - blockHashErr, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - output, err := toFilterArg(testCase.input) - if (testCase.err == nil) != (err == nil) { - t.Fatalf("expected error %v but got %v", testCase.err, err) - } - if testCase.err != nil { - if testCase.err.Error() != err.Error() { - t.Fatalf("expected error %v but got %v", testCase.err, err) - } - } else if !reflect.DeepEqual(testCase.output, output) { - t.Fatalf("expected filter arg %v but got %v", testCase.output, output) - } - }) - } -} - -var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - testBalance = big.NewInt(2e15) -) - -var genesis = &core.Genesis{ - Config: params.AllEthashProtocolChanges, - Alloc: types.GenesisAlloc{testAddr: {Balance: testBalance}}, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - BaseFee: big.NewInt(params.InitialBaseFee), -} - -var testTx1 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{ - Nonce: 0, - Value: big.NewInt(12), - GasPrice: big.NewInt(params.InitialBaseFee), - Gas: params.TxGas, - To: &common.Address{2}, -}) - -var testTx2 = types.MustSignNewTx(testKey, types.LatestSigner(genesis.Config), &types.LegacyTx{ - Nonce: 1, - Value: big.NewInt(8), - GasPrice: big.NewInt(params.InitialBaseFee), - Gas: params.TxGas, - To: &common.Address{2}, -}) - -func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { - // Generate test chain. - blocks := generateTestChain() - - // Create node - n, err := node.New(&node.Config{}) - if err != nil { - t.Fatalf("can't create new node: %v", err) - } - // Create Ethereum Service - config := ðconfig.Config{Genesis: genesis} - ethservice, err := eth.New(n, config) - if err != nil { - t.Fatalf("can't create new ethereum service: %v", err) - } - // Import the test chain. - if err := n.Start(); err != nil { - t.Fatalf("can't start test node: %v", err) - } - if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil { - t.Fatalf("can't import test blocks: %v", err) - } - // Ensure the tx indexing is fully generated - for ; ; time.Sleep(time.Millisecond * 100) { - progress, err := ethservice.BlockChain().TxIndexProgress() - if err == nil && progress.Done() { - break - } - } - return n, blocks -} - -func generateTestChain() []*types.Block { - generate := func(i int, g *core.BlockGen) { - g.OffsetTime(5) - g.SetExtra([]byte("test")) - if i == 1 { - // Test transactions are included in block #2. - g.AddTx(testTx1) - g.AddTx(testTx2) - } - } - _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 2, generate) - return append([]*types.Block{genesis.ToBlock()}, blocks...) -} - -func TestEthClient(t *testing.T) { - backend, chain := newTestBackend(t) - client := backend.Attach() - defer backend.Close() - defer client.Close() - - tests := map[string]struct { - test func(t *testing.T) - }{ - "Header": { - func(t *testing.T) { testHeader(t, chain, client) }, - }, - "BalanceAt": { - func(t *testing.T) { testBalanceAt(t, client) }, - }, - "TxInBlockInterrupted": { - func(t *testing.T) { testTransactionInBlock(t, client) }, - }, - "ChainID": { - func(t *testing.T) { testChainID(t, client) }, - }, - "GetBlock": { - func(t *testing.T) { testGetBlock(t, client) }, - }, - "StatusFunctions": { - func(t *testing.T) { testStatusFunctions(t, client) }, - }, - "CallContract": { - func(t *testing.T) { testCallContract(t, client) }, - }, - "CallContractAtHash": { - func(t *testing.T) { testCallContractAtHash(t, client) }, - }, - "AtFunctions": { - func(t *testing.T) { testAtFunctions(t, client) }, - }, - "TransactionSender": { - func(t *testing.T) { testTransactionSender(t, client) }, - }, - } - - t.Parallel() - for name, tt := range tests { - t.Run(name, tt.test) - } -} - -func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) { - tests := map[string]struct { - block *big.Int - want *types.Header - wantErr error - }{ - "genesis": { - block: big.NewInt(0), - want: chain[0].Header(), - }, - "first_block": { - block: big.NewInt(1), - want: chain[1].Header(), - }, - "future_block": { - block: big.NewInt(1000000000), - want: nil, - wantErr: ethereum.NotFound, - }, - } - for name, tt := range tests { - t.Run(name, func(t *testing.T) { - ec := NewClient(client) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - - got, err := ec.HeaderByNumber(ctx, tt.block) - if !errors.Is(err, tt.wantErr) { - t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr) - } - if got != nil && got.Number != nil && got.Number.Sign() == 0 { - got.Number = big.NewInt(0) // hack to make DeepEqual work - } - if !reflect.DeepEqual(got, tt.want) { - t.Fatalf("HeaderByNumber(%v) got = %v, want %v", tt.block, got, tt.want) - } - }) - } -} - -func testBalanceAt(t *testing.T, client *rpc.Client) { - tests := map[string]struct { - account common.Address - block *big.Int - want *big.Int - wantErr error - }{ - "valid_account_genesis": { - account: testAddr, - block: big.NewInt(0), - want: testBalance, - }, - "valid_account": { - account: testAddr, - block: big.NewInt(1), - want: testBalance, - }, - "non_existent_account": { - account: common.Address{1}, - block: big.NewInt(1), - want: big.NewInt(0), - }, - "future_block": { - account: testAddr, - block: big.NewInt(1000000000), - want: big.NewInt(0), - wantErr: errors.New("header not found"), - }, - } - for name, tt := range tests { - t.Run(name, func(t *testing.T) { - ec := NewClient(client) - ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) - defer cancel() - - got, err := ec.BalanceAt(ctx, tt.account, tt.block) - if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) { - t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr) - } - if got.Cmp(tt.want) != 0 { - t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want) - } - }) - } -} - -func testTransactionInBlock(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - // Get current block by number. - block, err := ec.BlockByNumber(context.Background(), nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // Test tx in block not found. - if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 20); err != ethereum.NotFound { - t.Fatal("error should be ethereum.NotFound") - } - - // Test tx in block found. - tx, err := ec.TransactionInBlock(context.Background(), block.Hash(), 0) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if tx.Hash() != testTx1.Hash() { - t.Fatalf("unexpected transaction: %v", tx) - } - - tx, err = ec.TransactionInBlock(context.Background(), block.Hash(), 1) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if tx.Hash() != testTx2.Hash() { - t.Fatalf("unexpected transaction: %v", tx) - } -} - -func testChainID(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - id, err := ec.ChainID(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 { - t.Fatalf("ChainID returned wrong number: %+v", id) - } -} - -func testGetBlock(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - // Get current block number - blockNumber, err := ec.BlockNumber(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if blockNumber != 2 { - t.Fatalf("BlockNumber returned wrong number: %d", blockNumber) - } - // Get current block by number - block, err := ec.BlockByNumber(context.Background(), new(big.Int).SetUint64(blockNumber)) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if block.NumberU64() != blockNumber { - t.Fatalf("BlockByNumber returned wrong block: want %d got %d", blockNumber, block.NumberU64()) - } - // Get current block by hash - blockH, err := ec.BlockByHash(context.Background(), block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if block.Hash() != blockH.Hash() { - t.Fatalf("BlockByHash returned wrong block: want %v got %v", block.Hash().Hex(), blockH.Hash().Hex()) - } - // Get header by number - header, err := ec.HeaderByNumber(context.Background(), new(big.Int).SetUint64(blockNumber)) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if block.Header().Hash() != header.Hash() { - t.Fatalf("HeaderByNumber returned wrong header: want %v got %v", block.Header().Hash().Hex(), header.Hash().Hex()) - } - // Get header by hash - headerH, err := ec.HeaderByHash(context.Background(), block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if block.Header().Hash() != headerH.Hash() { - t.Fatalf("HeaderByHash returned wrong header: want %v got %v", block.Header().Hash().Hex(), headerH.Hash().Hex()) - } -} - -func testStatusFunctions(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - // Sync progress - progress, err := ec.SyncProgress(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if progress != nil { - t.Fatalf("unexpected progress: %v", progress) - } - - // NetworkID - networkID, err := ec.NetworkID(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if networkID.Cmp(big.NewInt(1337)) != 0 { - t.Fatalf("unexpected networkID: %v", networkID) - } - - // SuggestGasPrice - gasPrice, err := ec.SuggestGasPrice(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gasPrice.Cmp(big.NewInt(1000000000)) != 0 { - t.Fatalf("unexpected gas price: %v", gasPrice) - } - - // SuggestGasTipCap - gasTipCap, err := ec.SuggestGasTipCap(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gasTipCap.Cmp(big.NewInt(234375000)) != 0 { - t.Fatalf("unexpected gas tip cap: %v", gasTipCap) - } - - // FeeHistory - history, err := ec.FeeHistory(context.Background(), 1, big.NewInt(2), []float64{95, 99}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - want := ðereum.FeeHistory{ - OldestBlock: big.NewInt(2), - Reward: [][]*big.Int{ - { - big.NewInt(234375000), - big.NewInt(234375000), - }, - }, - BaseFee: []*big.Int{ - big.NewInt(765625000), - big.NewInt(671627818), - }, - GasUsedRatio: []float64{0.008912678667376286}, - } - if !reflect.DeepEqual(history, want) { - t.Fatalf("FeeHistory result doesn't match expected: (got: %v, want: %v)", history, want) - } -} - -func testCallContractAtHash(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - // EstimateGas - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 21000, - Value: big.NewInt(1), - } - gas, err := ec.EstimateGas(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gas != 21000 { - t.Fatalf("unexpected gas price: %v", gas) - } - block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1)) - if err != nil { - t.Fatalf("BlockByNumber error: %v", err) - } - // CallContract - if _, err := ec.CallContractAtHash(context.Background(), msg, block.Hash()); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func testCallContract(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - // EstimateGas - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 21000, - Value: big.NewInt(1), - } - gas, err := ec.EstimateGas(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gas != 21000 { - t.Fatalf("unexpected gas price: %v", gas) - } - // CallContract - if _, err := ec.CallContract(context.Background(), msg, big.NewInt(1)); err != nil { - t.Fatalf("unexpected error: %v", err) - } - // PendingCallContract - if _, err := ec.PendingCallContract(context.Background(), msg); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func testAtFunctions(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - - block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1)) - if err != nil { - t.Fatalf("BlockByNumber error: %v", err) - } - - // send a transaction for some interesting pending status - sendTransaction(ec) - time.Sleep(100 * time.Millisecond) - - // Check pending transaction count - pending, err := ec.PendingTransactionCount(context.Background()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if pending != 1 { - t.Fatalf("unexpected pending, wanted 1 got: %v", pending) - } - // Query balance - balance, err := ec.BalanceAt(context.Background(), testAddr, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - hashBalance, err := ec.BalanceAtHash(context.Background(), testAddr, block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if balance.Cmp(hashBalance) == 0 { - t.Fatalf("unexpected balance at hash: %v %v", balance, hashBalance) - } - penBalance, err := ec.PendingBalanceAt(context.Background(), testAddr) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if balance.Cmp(penBalance) == 0 { - t.Fatalf("unexpected balance: %v %v", balance, penBalance) - } - // NonceAt - nonce, err := ec.NonceAt(context.Background(), testAddr, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - hashNonce, err := ec.NonceAtHash(context.Background(), testAddr, block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if hashNonce == nonce { - t.Fatalf("unexpected nonce at hash: %v %v", nonce, hashNonce) - } - penNonce, err := ec.PendingNonceAt(context.Background(), testAddr) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if penNonce != nonce+1 { - t.Fatalf("unexpected nonce: %v %v", nonce, penNonce) - } - // StorageAt - storage, err := ec.StorageAt(context.Background(), testAddr, common.Hash{}, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - hashStorage, err := ec.StorageAtHash(context.Background(), testAddr, common.Hash{}, block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(storage, hashStorage) { - t.Fatalf("unexpected storage at hash: %v %v", storage, hashStorage) - } - penStorage, err := ec.PendingStorageAt(context.Background(), testAddr, common.Hash{}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(storage, penStorage) { - t.Fatalf("unexpected storage: %v %v", storage, penStorage) - } - // CodeAt - code, err := ec.CodeAt(context.Background(), testAddr, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - hashCode, err := ec.CodeAtHash(context.Background(), common.Address{}, block.Hash()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(code, hashCode) { - t.Fatalf("unexpected code at hash: %v %v", code, hashCode) - } - penCode, err := ec.PendingCodeAt(context.Background(), testAddr) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(code, penCode) { - t.Fatalf("unexpected code: %v %v", code, penCode) - } -} - -func testTransactionSender(t *testing.T, client *rpc.Client) { - ec := NewClient(client) - ctx := context.Background() - - // Retrieve testTx1 via RPC. - block2, err := ec.HeaderByNumber(ctx, big.NewInt(2)) - if err != nil { - t.Fatal("can't get block 1:", err) - } - tx1, err := ec.TransactionInBlock(ctx, block2.Hash(), 0) - if err != nil { - t.Fatal("can't get tx:", err) - } - if tx1.Hash() != testTx1.Hash() { - t.Fatalf("wrong tx hash %v, want %v", tx1.Hash(), testTx1.Hash()) - } - - // The sender address is cached in tx1, so no additional RPC should be required in - // TransactionSender. Ensure the server is not asked by canceling the context here. - canceledCtx, cancel := context.WithCancel(context.Background()) - cancel() - <-canceledCtx.Done() // Ensure the close of the Done channel - sender1, err := ec.TransactionSender(canceledCtx, tx1, block2.Hash(), 0) - if err != nil { - t.Fatal(err) - } - if sender1 != testAddr { - t.Fatal("wrong sender:", sender1) - } - - // Now try to get the sender of testTx2, which was not fetched through RPC. - // TransactionSender should query the server here. - sender2, err := ec.TransactionSender(ctx, testTx2, block2.Hash(), 1) - if err != nil { - t.Fatal(err) - } - if sender2 != testAddr { - t.Fatal("wrong sender:", sender2) - } -} - -func sendTransaction(ec *Client) error { - chainID, err := ec.ChainID(context.Background()) - if err != nil { - return err - } - nonce, err := ec.PendingNonceAt(context.Background(), testAddr) - if err != nil { - return err - } - - signer := types.LatestSignerForChainID(chainID) - tx, err := types.SignNewTx(testKey, signer, &types.LegacyTx{ - Nonce: nonce, - To: &common.Address{2}, - Value: big.NewInt(1), - Gas: 22000, - GasPrice: big.NewInt(params.InitialBaseFee), - }) - if err != nil { - return err - } - return ec.SendTransaction(context.Background(), tx) -} diff --git a/builder/ethclient/gethclient/gethclient.go b/builder/ethclient/gethclient/gethclient.go deleted file mode 100644 index 73d05d499..000000000 --- a/builder/ethclient/gethclient/gethclient.go +++ /dev/null @@ -1,344 +0,0 @@ -// 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 gethclient provides an RPC client for geth-specific APIs. -package gethclient - -import ( - "context" - "encoding/json" - "fmt" - "math/big" - "runtime" - "runtime/debug" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rpc" -) - -// Client is a wrapper around rpc.Client that implements geth-specific functionality. -// -// If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead. -type Client struct { - c *rpc.Client -} - -// New creates a client that uses the given RPC client. -func New(c *rpc.Client) *Client { - return &Client{c} -} - -// CreateAccessList tries to create an access list for a specific transaction based on the -// current pending state of the blockchain. -func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*types.AccessList, uint64, string, error) { - type accessListResult struct { - Accesslist *types.AccessList `json:"accessList"` - Error string `json:"error,omitempty"` - GasUsed hexutil.Uint64 `json:"gasUsed"` - } - var result accessListResult - if err := ec.c.CallContext(ctx, &result, "eth_createAccessList", toCallArg(msg)); err != nil { - return nil, 0, "", err - } - return result.Accesslist, uint64(result.GasUsed), result.Error, nil -} - -// AccountResult is the result of a GetProof operation. -type AccountResult struct { - Address common.Address `json:"address"` - AccountProof []string `json:"accountProof"` - Balance *big.Int `json:"balance"` - CodeHash common.Hash `json:"codeHash"` - Nonce uint64 `json:"nonce"` - StorageHash common.Hash `json:"storageHash"` - StorageProof []StorageResult `json:"storageProof"` -} - -// StorageResult provides a proof for a key-value pair. -type StorageResult struct { - Key string `json:"key"` - Value *big.Int `json:"value"` - Proof []string `json:"proof"` -} - -// GetProof returns the account and storage values of the specified account including the Merkle-proof. -// The block number can be nil, in which case the value is taken from the latest known block. -func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []string, blockNumber *big.Int) (*AccountResult, error) { - type storageResult struct { - Key string `json:"key"` - Value *hexutil.Big `json:"value"` - Proof []string `json:"proof"` - } - - type accountResult struct { - Address common.Address `json:"address"` - AccountProof []string `json:"accountProof"` - Balance *hexutil.Big `json:"balance"` - CodeHash common.Hash `json:"codeHash"` - Nonce hexutil.Uint64 `json:"nonce"` - StorageHash common.Hash `json:"storageHash"` - StorageProof []storageResult `json:"storageProof"` - } - - // Avoid keys being 'null'. - if keys == nil { - keys = []string{} - } - - var res accountResult - err := ec.c.CallContext(ctx, &res, "eth_getProof", account, keys, toBlockNumArg(blockNumber)) - // Turn hexutils back to normal datatypes - storageResults := make([]StorageResult, 0, len(res.StorageProof)) - for _, st := range res.StorageProof { - storageResults = append(storageResults, StorageResult{ - Key: st.Key, - Value: st.Value.ToInt(), - Proof: st.Proof, - }) - } - result := AccountResult{ - Address: res.Address, - AccountProof: res.AccountProof, - Balance: res.Balance.ToInt(), - Nonce: uint64(res.Nonce), - CodeHash: res.CodeHash, - StorageHash: res.StorageHash, - StorageProof: storageResults, - } - return &result, err -} - -// CallContract executes a message call transaction, which is directly executed in the VM -// of the node, but never mined into the blockchain. -// -// blockNumber selects the block height at which the call runs. It can be nil, in which -// case the code is taken from the latest known block. Note that state from very old -// blocks might not be available. -// -// overrides specifies a map of contract states that should be overwritten before executing -// the message call. -// Please use ethclient.CallContract instead if you don't need the override functionality. -func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount) ([]byte, error) { - var hex hexutil.Bytes - err := ec.c.CallContext( - ctx, &hex, "eth_call", toCallArg(msg), - toBlockNumArg(blockNumber), overrides, - ) - return hex, err -} - -// CallContractWithBlockOverrides executes a message call transaction, which is directly executed -// in the VM of the node, but never mined into the blockchain. -// -// blockNumber selects the block height at which the call runs. It can be nil, in which -// case the code is taken from the latest known block. Note that state from very old -// blocks might not be available. -// -// overrides specifies a map of contract states that should be overwritten before executing -// the message call. -// -// blockOverrides specifies block fields exposed to the EVM that can be overridden for the call. -// -// Please use ethclient.CallContract instead if you don't need the override functionality. -func (ec *Client) CallContractWithBlockOverrides(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int, overrides *map[common.Address]OverrideAccount, blockOverrides BlockOverrides) ([]byte, error) { - var hex hexutil.Bytes - err := ec.c.CallContext( - ctx, &hex, "eth_call", toCallArg(msg), - toBlockNumArg(blockNumber), overrides, blockOverrides, - ) - return hex, err -} - -// GCStats retrieves the current garbage collection stats from a geth node. -func (ec *Client) GCStats(ctx context.Context) (*debug.GCStats, error) { - var result debug.GCStats - err := ec.c.CallContext(ctx, &result, "debug_gcStats") - return &result, err -} - -// MemStats retrieves the current memory stats from a geth node. -func (ec *Client) MemStats(ctx context.Context) (*runtime.MemStats, error) { - var result runtime.MemStats - err := ec.c.CallContext(ctx, &result, "debug_memStats") - return &result, err -} - -// SetHead sets the current head of the local chain by block number. -// Note, this is a destructive action and may severely damage your chain. -// Use with extreme caution. -func (ec *Client) SetHead(ctx context.Context, number *big.Int) error { - return ec.c.CallContext(ctx, nil, "debug_setHead", toBlockNumArg(number)) -} - -// GetNodeInfo retrieves the node info of a geth node. -func (ec *Client) GetNodeInfo(ctx context.Context) (*p2p.NodeInfo, error) { - var result p2p.NodeInfo - err := ec.c.CallContext(ctx, &result, "admin_nodeInfo") - return &result, err -} - -// SubscribeFullPendingTransactions subscribes to new pending transactions. -func (ec *Client) SubscribeFullPendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (*rpc.ClientSubscription, error) { - return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions", true) -} - -// SubscribePendingTransactions subscribes to new pending transaction hashes. -func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- common.Hash) (*rpc.ClientSubscription, error) { - return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") -} - -func toBlockNumArg(number *big.Int) string { - if number == nil { - return "latest" - } - if number.Sign() >= 0 { - return hexutil.EncodeBig(number) - } - // It's negative. - if number.IsInt64() { - return rpc.BlockNumber(number.Int64()).String() - } - // It's negative and large, which is invalid. - return fmt.Sprintf("", number) -} - -func toCallArg(msg ethereum.CallMsg) interface{} { - arg := map[string]interface{}{ - "from": msg.From, - "to": msg.To, - } - if len(msg.Data) > 0 { - arg["input"] = hexutil.Bytes(msg.Data) - } - if msg.Value != nil { - arg["value"] = (*hexutil.Big)(msg.Value) - } - if msg.Gas != 0 { - arg["gas"] = hexutil.Uint64(msg.Gas) - } - if msg.GasPrice != nil { - arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) - } - if msg.GasFeeCap != nil { - arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap) - } - if msg.GasTipCap != nil { - arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap) - } - if msg.AccessList != nil { - arg["accessList"] = msg.AccessList - } - return arg -} - -// OverrideAccount specifies the state of an account to be overridden. -type OverrideAccount struct { - // Nonce sets nonce of the account. Note: the nonce override will only - // be applied when it is set to a non-zero value. - Nonce uint64 - - // Code sets the contract code. The override will be applied - // when the code is non-nil, i.e. setting empty code is possible - // using an empty slice. - Code []byte - - // Balance sets the account balance. - Balance *big.Int - - // State sets the complete storage. The override will be applied - // when the given map is non-nil. Using an empty map wipes the - // entire contract storage during the call. - State map[common.Hash]common.Hash - - // StateDiff allows overriding individual storage slots. - StateDiff map[common.Hash]common.Hash -} - -func (a OverrideAccount) MarshalJSON() ([]byte, error) { - type acc struct { - Nonce hexutil.Uint64 `json:"nonce,omitempty"` - Code string `json:"code,omitempty"` - Balance *hexutil.Big `json:"balance,omitempty"` - State interface{} `json:"state,omitempty"` - StateDiff map[common.Hash]common.Hash `json:"stateDiff,omitempty"` - } - - output := acc{ - Nonce: hexutil.Uint64(a.Nonce), - Balance: (*hexutil.Big)(a.Balance), - StateDiff: a.StateDiff, - } - if a.Code != nil { - output.Code = hexutil.Encode(a.Code) - } - if a.State != nil { - output.State = a.State - } - return json.Marshal(output) -} - -// BlockOverrides specifies the set of header fields to override. -type BlockOverrides struct { - // Number overrides the block number. - Number *big.Int - // Difficulty overrides the block difficulty. - Difficulty *big.Int - // Time overrides the block timestamp. Time is applied only when - // it is non-zero. - Time uint64 - // GasLimit overrides the block gas limit. GasLimit is applied only when - // it is non-zero. - GasLimit uint64 - // Coinbase overrides the block coinbase. Coinbase is applied only when - // it is different from the zero address. - Coinbase common.Address - // Random overrides the block extra data which feeds into the RANDOM opcode. - // Random is applied only when it is a non-zero hash. - Random common.Hash - // BaseFee overrides the block base fee. - BaseFee *big.Int -} - -func (o BlockOverrides) MarshalJSON() ([]byte, error) { - type override struct { - Number *hexutil.Big `json:"number,omitempty"` - Difficulty *hexutil.Big `json:"difficulty,omitempty"` - Time hexutil.Uint64 `json:"time,omitempty"` - GasLimit hexutil.Uint64 `json:"gasLimit,omitempty"` - Coinbase *common.Address `json:"coinbase,omitempty"` - Random *common.Hash `json:"random,omitempty"` - BaseFee *hexutil.Big `json:"baseFee,omitempty"` - } - - output := override{ - Number: (*hexutil.Big)(o.Number), - Difficulty: (*hexutil.Big)(o.Difficulty), - Time: hexutil.Uint64(o.Time), - GasLimit: hexutil.Uint64(o.GasLimit), - BaseFee: (*hexutil.Big)(o.BaseFee), - } - if o.Coinbase != (common.Address{}) { - output.Coinbase = &o.Coinbase - } - if o.Random != (common.Hash{}) { - output.Random = &o.Random - } - return json.Marshal(output) -} diff --git a/builder/ethclient/gethclient/gethclient_test.go b/builder/ethclient/gethclient/gethclient_test.go deleted file mode 100644 index 158886475..000000000 --- a/builder/ethclient/gethclient/gethclient_test.go +++ /dev/null @@ -1,570 +0,0 @@ -// 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 gethclient - -import ( - "bytes" - "context" - "encoding/json" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/ethash" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) - testContract = common.HexToAddress("0xbeef") - testEmpty = common.HexToAddress("0xeeee") - testSlot = common.HexToHash("0xdeadbeef") - testValue = crypto.Keccak256Hash(testSlot[:]) - testBalance = big.NewInt(2e15) -) - -func newTestBackend(t *testing.T) (*node.Node, []*types.Block) { - // Generate test chain. - genesis, blocks := generateTestChain() - // Create node - n, err := node.New(&node.Config{}) - if err != nil { - t.Fatalf("can't create new node: %v", err) - } - // Create Ethereum Service - config := ðconfig.Config{Genesis: genesis} - ethservice, err := eth.New(n, config) - if err != nil { - t.Fatalf("can't create new ethereum service: %v", err) - } - filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{}) - n.RegisterAPIs([]rpc.API{{ - Namespace: "eth", - Service: filters.NewFilterAPI(filterSystem, false), - }}) - - // Import the test chain. - if err := n.Start(); err != nil { - t.Fatalf("can't start test node: %v", err) - } - if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil { - t.Fatalf("can't import test blocks: %v", err) - } - return n, blocks -} - -func generateTestChain() (*core.Genesis, []*types.Block) { - genesis := &core.Genesis{ - Config: params.AllEthashProtocolChanges, - Alloc: types.GenesisAlloc{ - testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}}, - testContract: {Nonce: 1, Code: []byte{0x13, 0x37}}, - testEmpty: {Balance: big.NewInt(1)}, - }, - ExtraData: []byte("test genesis"), - Timestamp: 9000, - } - generate := func(i int, g *core.BlockGen) { - g.OffsetTime(5) - g.SetExtra([]byte("test")) - } - _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 1, generate) - blocks = append([]*types.Block{genesis.ToBlock()}, blocks...) - return genesis, blocks -} - -func TestGethClient(t *testing.T) { - backend, _ := newTestBackend(t) - client := backend.Attach() - defer backend.Close() - defer client.Close() - - tests := []struct { - name string - test func(t *testing.T) - }{ - { - "TestGetProof1", - func(t *testing.T) { testGetProof(t, client, testAddr) }, - }, { - "TestGetProof2", - func(t *testing.T) { testGetProof(t, client, testContract) }, - }, { - "TestGetProofEmpty", - func(t *testing.T) { testGetProof(t, client, testEmpty) }, - }, { - "TestGetProofNonExistent", - func(t *testing.T) { testGetProofNonExistent(t, client) }, - }, { - "TestGetProofCanonicalizeKeys", - func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) }, - }, { - "TestGCStats", - func(t *testing.T) { testGCStats(t, client) }, - }, { - "TestMemStats", - func(t *testing.T) { testMemStats(t, client) }, - }, { - "TestGetNodeInfo", - func(t *testing.T) { testGetNodeInfo(t, client) }, - }, { - "TestSubscribePendingTxHashes", - func(t *testing.T) { testSubscribePendingTransactions(t, client) }, - }, { - "TestSubscribePendingTxs", - func(t *testing.T) { testSubscribeFullPendingTransactions(t, client) }, - }, { - "TestCallContract", - func(t *testing.T) { testCallContract(t, client) }, - }, { - "TestCallContractWithBlockOverrides", - func(t *testing.T) { testCallContractWithBlockOverrides(t, client) }, - }, - // The testaccesslist is a bit time-sensitive: the newTestBackend imports - // one block. The `testAcessList` fails if the miner has not yet created a - // new pending-block after the import event. - // Hence: this test should be last, execute the tests serially. - { - "TestAccessList", - func(t *testing.T) { testAccessList(t, client) }, - }, { - "TestSetHead", - func(t *testing.T) { testSetHead(t, client) }, - }, - } - for _, tt := range tests { - t.Run(tt.name, tt.test) - } -} - -func testAccessList(t *testing.T, client *rpc.Client) { - ec := New(client) - // Test transfer - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 21000, - GasPrice: big.NewInt(875000000), - Value: big.NewInt(1), - } - al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if vmErr != "" { - t.Fatalf("unexpected vm error: %v", vmErr) - } - if gas != 21000 { - t.Fatalf("unexpected gas used: %v", gas) - } - if len(*al) != 0 { - t.Fatalf("unexpected length of accesslist: %v", len(*al)) - } - // Test reverting transaction - msg = ethereum.CallMsg{ - From: testAddr, - To: nil, - Gas: 100000, - GasPrice: big.NewInt(1000000000), - Value: big.NewInt(1), - Data: common.FromHex("0x608060806080608155fd"), - } - al, gas, vmErr, err = ec.CreateAccessList(context.Background(), msg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if vmErr == "" { - t.Fatalf("wanted vmErr, got none") - } - if gas == 21000 { - t.Fatalf("unexpected gas used: %v", gas) - } - if len(*al) != 1 || al.StorageKeys() != 1 { - t.Fatalf("unexpected length of accesslist: %v", len(*al)) - } - // address changes between calls, so we can't test for it. - if (*al)[0].Address == common.HexToAddress("0x0") { - t.Fatalf("unexpected address: %v", (*al)[0].Address) - } - if (*al)[0].StorageKeys[0] != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000081") { - t.Fatalf("unexpected storage key: %v", (*al)[0].StorageKeys[0]) - } -} - -func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) { - ec := New(client) - ethcl := ethclient.NewClient(client) - result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil) - if err != nil { - t.Fatal(err) - } - if result.Address != addr { - t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr) - } - // test nonce - if nonce, _ := ethcl.NonceAt(context.Background(), addr, nil); result.Nonce != nonce { - t.Fatalf("invalid nonce, want: %v got: %v", nonce, result.Nonce) - } - // test balance - if balance, _ := ethcl.BalanceAt(context.Background(), addr, nil); result.Balance.Cmp(balance) != 0 { - t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance) - } - // test storage - if len(result.StorageProof) != 1 { - t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof)) - } - for _, proof := range result.StorageProof { - if proof.Key != testSlot.String() { - t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key) - } - slotValue, _ := ethcl.StorageAt(context.Background(), addr, common.HexToHash(proof.Key), nil) - if have, want := common.BigToHash(proof.Value), common.BytesToHash(slotValue); have != want { - t.Fatalf("addr %x, invalid storage proof value: have: %v, want: %v", addr, have, want) - } - } - // test code - code, _ := ethcl.CodeAt(context.Background(), addr, nil) - if have, want := result.CodeHash, crypto.Keccak256Hash(code); have != want { - t.Fatalf("codehash wrong, have %v want %v ", have, want) - } -} - -func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) { - ec := New(client) - - // Tests with non-canon input for storage keys. - // Here we check that the storage key is canonicalized. - result, err := ec.GetProof(context.Background(), testAddr, []string{"0x0dEadbeef"}, nil) - if err != nil { - t.Fatal(err) - } - if result.StorageProof[0].Key != "0xdeadbeef" { - t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key) - } - if result, err = ec.GetProof(context.Background(), testAddr, []string{"0x000deadbeef"}, nil); err != nil { - t.Fatal(err) - } - if result.StorageProof[0].Key != "0xdeadbeef" { - t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key) - } - - // If the requested storage key is 32 bytes long, it will be returned as is. - hashSizedKey := "0x00000000000000000000000000000000000000000000000000000000deadbeef" - result, err = ec.GetProof(context.Background(), testAddr, []string{hashSizedKey}, nil) - if err != nil { - t.Fatal(err) - } - if result.StorageProof[0].Key != hashSizedKey { - t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key) - } -} - -func testGetProofNonExistent(t *testing.T, client *rpc.Client) { - addr := common.HexToAddress("0x0001") - ec := New(client) - result, err := ec.GetProof(context.Background(), addr, nil, nil) - if err != nil { - t.Fatal(err) - } - if result.Address != addr { - t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr) - } - // test nonce - if result.Nonce != 0 { - t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce) - } - // test balance - if result.Balance.Cmp(big.NewInt(0)) != 0 { - t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance) - } - // test storage - if have := len(result.StorageProof); have != 0 { - t.Fatalf("invalid storage proof, want 0 proof, got %v proof(s)", have) - } - // test codeHash - if have, want := result.CodeHash, (common.Hash{}); have != want { - t.Fatalf("codehash wrong, have %v want %v ", have, want) - } - // test codeHash - if have, want := result.StorageHash, (common.Hash{}); have != want { - t.Fatalf("storagehash wrong, have %v want %v ", have, want) - } -} - -func testGCStats(t *testing.T, client *rpc.Client) { - ec := New(client) - _, err := ec.GCStats(context.Background()) - if err != nil { - t.Fatal(err) - } -} - -func testMemStats(t *testing.T, client *rpc.Client) { - ec := New(client) - stats, err := ec.MemStats(context.Background()) - if err != nil { - t.Fatal(err) - } - if stats.Alloc == 0 { - t.Fatal("Invalid mem stats retrieved") - } -} - -func testGetNodeInfo(t *testing.T, client *rpc.Client) { - ec := New(client) - info, err := ec.GetNodeInfo(context.Background()) - if err != nil { - t.Fatal(err) - } - - if info.Name == "" { - t.Fatal("Invalid node info retrieved") - } -} - -func testSetHead(t *testing.T, client *rpc.Client) { - ec := New(client) - err := ec.SetHead(context.Background(), big.NewInt(0)) - if err != nil { - t.Fatal(err) - } -} - -func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) { - ec := New(client) - ethcl := ethclient.NewClient(client) - // Subscribe to Transactions - ch := make(chan common.Hash) - ec.SubscribePendingTransactions(context.Background(), ch) - // Send a transaction - chainID, err := ethcl.ChainID(context.Background()) - if err != nil { - t.Fatal(err) - } - // Create transaction - tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil) - signer := types.LatestSignerForChainID(chainID) - signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey) - if err != nil { - t.Fatal(err) - } - signedTx, err := tx.WithSignature(signer, signature) - if err != nil { - t.Fatal(err) - } - // Send transaction - err = ethcl.SendTransaction(context.Background(), signedTx) - if err != nil { - t.Fatal(err) - } - // Check that the transaction was sent over the channel - hash := <-ch - if hash != signedTx.Hash() { - t.Fatalf("Invalid tx hash received, got %v, want %v", hash, signedTx.Hash()) - } -} - -func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) { - ec := New(client) - ethcl := ethclient.NewClient(client) - // Subscribe to Transactions - ch := make(chan *types.Transaction) - ec.SubscribeFullPendingTransactions(context.Background(), ch) - // Send a transaction - chainID, err := ethcl.ChainID(context.Background()) - if err != nil { - t.Fatal(err) - } - // Create transaction - tx := types.NewTransaction(1, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil) - signer := types.LatestSignerForChainID(chainID) - signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey) - if err != nil { - t.Fatal(err) - } - signedTx, err := tx.WithSignature(signer, signature) - if err != nil { - t.Fatal(err) - } - // Send transaction - err = ethcl.SendTransaction(context.Background(), signedTx) - if err != nil { - t.Fatal(err) - } - // Check that the transaction was sent over the channel - tx = <-ch - if tx.Hash() != signedTx.Hash() { - t.Fatalf("Invalid tx hash received, got %v, want %v", tx.Hash(), signedTx.Hash()) - } -} - -func testCallContract(t *testing.T, client *rpc.Client) { - ec := New(client) - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 21000, - GasPrice: big.NewInt(1000000000), - Value: big.NewInt(1), - } - // CallContract without override - if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), nil); err != nil { - t.Fatalf("unexpected error: %v", err) - } - // CallContract with override - override := OverrideAccount{ - Nonce: 1, - } - mapAcc := make(map[common.Address]OverrideAccount) - mapAcc[testAddr] = override - if _, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestOverrideAccountMarshal(t *testing.T) { - om := map[common.Address]OverrideAccount{ - {0x11}: { - // Zero-valued nonce is not overridden, but simply dropped by the encoder. - Nonce: 0, - }, - {0xaa}: { - Nonce: 5, - }, - {0xbb}: { - Code: []byte{1}, - }, - {0xcc}: { - // 'code', 'balance', 'state' should be set when input is - // a non-nil but empty value. - Code: []byte{}, - Balance: big.NewInt(0), - State: map[common.Hash]common.Hash{}, - // For 'stateDiff' the behavior is different, empty map - // is ignored because it makes no difference. - StateDiff: map[common.Hash]common.Hash{}, - }, - } - - marshalled, err := json.MarshalIndent(&om, "", " ") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - expected := `{ - "0x1100000000000000000000000000000000000000": {}, - "0xaa00000000000000000000000000000000000000": { - "nonce": "0x5" - }, - "0xbb00000000000000000000000000000000000000": { - "code": "0x01" - }, - "0xcc00000000000000000000000000000000000000": { - "code": "0x", - "balance": "0x0", - "state": {} - } -}` - - if string(marshalled) != expected { - t.Error("wrong output:", string(marshalled)) - t.Error("want:", expected) - } -} - -func TestBlockOverridesMarshal(t *testing.T) { - for i, tt := range []struct { - bo BlockOverrides - want string - }{ - { - bo: BlockOverrides{}, - want: `{}`, - }, - { - bo: BlockOverrides{ - Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"), - }, - want: `{"coinbase":"0x1111111111111111111111111111111111111111"}`, - }, - { - bo: BlockOverrides{ - Number: big.NewInt(1), - Difficulty: big.NewInt(2), - Time: 3, - GasLimit: 4, - BaseFee: big.NewInt(5), - }, - want: `{"number":"0x1","difficulty":"0x2","time":"0x3","gasLimit":"0x4","baseFee":"0x5"}`, - }, - } { - marshalled, err := json.Marshal(&tt.bo) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if string(marshalled) != tt.want { - t.Errorf("Testcase #%d failed. expected\n%s\ngot\n%s", i, tt.want, string(marshalled)) - } - } -} - -func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) { - ec := New(client) - msg := ethereum.CallMsg{ - From: testAddr, - To: &common.Address{}, - Gas: 50000, - GasPrice: big.NewInt(1000000000), - Value: big.NewInt(1), - } - override := OverrideAccount{ - // Returns coinbase address. - Code: common.FromHex("0x41806000526014600cf3"), - } - mapAcc := make(map[common.Address]OverrideAccount) - mapAcc[common.Address{}] = override - res, err := ec.CallContract(context.Background(), msg, big.NewInt(0), &mapAcc) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(res, common.FromHex("0x0000000000000000000000000000000000000000")) { - t.Fatalf("unexpected result: %x", res) - } - - // Now test with block overrides - bo := BlockOverrides{ - Coinbase: common.HexToAddress("0x1111111111111111111111111111111111111111"), - } - res, err = ec.CallContractWithBlockOverrides(context.Background(), msg, big.NewInt(0), &mapAcc, bo) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !bytes.Equal(res, common.FromHex("0x1111111111111111111111111111111111111111")) { - t.Fatalf("unexpected result: %x", res) - } -} diff --git a/builder/ethclient/signer.go b/builder/ethclient/signer.go deleted file mode 100644 index f827d4eb5..000000000 --- a/builder/ethclient/signer.go +++ /dev/null @@ -1,62 +0,0 @@ -// 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 ethclient - -import ( - "errors" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -// senderFromServer is a types.Signer that remembers the sender address returned by the RPC -// server. It is stored in the transaction's sender address cache to avoid an additional -// request in TransactionSender. -type senderFromServer struct { - addr common.Address - blockhash common.Hash -} - -var errNotCached = errors.New("sender not cached") - -func setSenderFromServer(tx *types.Transaction, addr common.Address, block common.Hash) { - // Use types.Sender for side-effect to store our signer into the cache. - types.Sender(&senderFromServer{addr, block}, tx) -} - -func (s *senderFromServer) Equal(other types.Signer) bool { - os, ok := other.(*senderFromServer) - return ok && os.blockhash == s.blockhash -} - -func (s *senderFromServer) Sender(tx *types.Transaction) (common.Address, error) { - if s.addr == (common.Address{}) { - return common.Address{}, errNotCached - } - return s.addr, nil -} - -func (s *senderFromServer) ChainID() *big.Int { - panic("can't sign with senderFromServer") -} -func (s *senderFromServer) Hash(tx *types.Transaction) common.Hash { - panic("can't sign with senderFromServer") -} -func (s *senderFromServer) SignatureValues(tx *types.Transaction, sig []byte) (R, S, V *big.Int, err error) { - panic("can't sign with senderFromServer") -} diff --git a/builder/ethclient/simulated/backend.go b/builder/ethclient/simulated/backend.go deleted file mode 100644 index 0c2a0b453..000000000 --- a/builder/ethclient/simulated/backend.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2023 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 simulated - -import ( - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/catalyst" - "github.com/ethereum/go-ethereum/eth/downloader" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -) - -// Client exposes the methods provided by the Ethereum RPC client. -type Client interface { - ethereum.BlockNumberReader - ethereum.ChainReader - ethereum.ChainStateReader - ethereum.ContractCaller - ethereum.GasEstimator - ethereum.GasPricer - ethereum.GasPricer1559 - ethereum.FeeHistoryReader - ethereum.LogFilterer - ethereum.PendingStateReader - ethereum.PendingContractCaller - ethereum.TransactionReader - ethereum.TransactionSender - ethereum.ChainIDReader -} - -// simClient wraps ethclient. This exists to prevent extracting ethclient.Client -// from the Client interface returned by Backend. -type simClient struct { - *ethclient.Client -} - -// Backend is a simulated blockchain. You can use it to test your contracts or -// other code that interacts with the Ethereum chain. -type Backend struct { - eth *eth.Ethereum - beacon *catalyst.SimulatedBeacon - client simClient -} - -// NewBackend creates a new simulated blockchain that can be used as a backend for -// contract bindings in unit tests. -// -// A simulated backend always uses chainID 1337. -func NewBackend(alloc types.GenesisAlloc, options ...func(nodeConf *node.Config, ethConf *ethconfig.Config)) *Backend { - // Create the default configurations for the outer node shell and the Ethereum - // service to mutate with the options afterwards - nodeConf := node.DefaultConfig - nodeConf.DataDir = "" - nodeConf.P2P = p2p.Config{NoDiscovery: true} - - ethConf := ethconfig.Defaults - ethConf.Genesis = &core.Genesis{ - Config: params.AllDevChainProtocolChanges, - GasLimit: ethconfig.Defaults.Miner.GasCeil, - Alloc: alloc, - } - ethConf.SyncMode = downloader.FullSync - ethConf.TxPool.NoLocals = true - - for _, option := range options { - option(&nodeConf, ðConf) - } - // Assemble the Ethereum stack to run the chain with - stack, err := node.New(&nodeConf) - if err != nil { - panic(err) // this should never happen - } - sim, err := newWithNode(stack, ðConf, 0) - if err != nil { - panic(err) // this should never happen - } - return sim -} - -// newWithNode sets up a simulated backend on an existing node. The provided node -// must not be started and will be started by this method. -func newWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*Backend, error) { - backend, err := eth.New(stack, conf) - if err != nil { - return nil, err - } - // Register the filter system - filterSystem := filters.NewFilterSystem(backend.APIBackend, filters.Config{}) - stack.RegisterAPIs([]rpc.API{{ - Namespace: "eth", - Service: filters.NewFilterAPI(filterSystem, false), - }}) - // Start the node - if err := stack.Start(); err != nil { - return nil, err - } - // Set up the simulated beacon - beacon, err := catalyst.NewSimulatedBeacon(blockPeriod, backend) - if err != nil { - return nil, err - } - // Reorg our chain back to genesis - if err := beacon.Fork(backend.BlockChain().GetCanonicalHash(0)); err != nil { - return nil, err - } - return &Backend{ - eth: backend, - beacon: beacon, - client: simClient{ethclient.NewClient(stack.Attach())}, - }, nil -} - -// Close shuts down the simBackend. -// The simulated backend can't be used afterwards. -func (n *Backend) Close() error { - if n.client.Client != nil { - n.client.Close() - n.client = simClient{} - } - if n.beacon != nil { - err := n.beacon.Stop() - n.beacon = nil - return err - } - return nil -} - -// Commit seals a block and moves the chain forward to a new empty block. -func (n *Backend) Commit() common.Hash { - return n.beacon.Commit() -} - -// Rollback removes all pending transactions, reverting to the last committed state. -func (n *Backend) Rollback() { - n.beacon.Rollback() -} - -// Fork creates a side-chain that can be used to simulate reorgs. -// -// This function should be called with the ancestor block where the new side -// chain should be started. Transactions (old and new) can then be applied on -// top and Commit-ed. -// -// Note, the side-chain will only become canonical (and trigger the events) when -// it becomes longer. Until then CallContract will still operate on the current -// canonical chain. -// -// There is a % chance that the side chain becomes canonical at the same length -// to simulate live network behavior. -func (n *Backend) Fork(parentHash common.Hash) error { - return n.beacon.Fork(parentHash) -} - -// AdjustTime changes the block timestamp and creates a new block. -// It can only be called on empty blocks. -func (n *Backend) AdjustTime(adjustment time.Duration) error { - return n.beacon.AdjustTime(adjustment) -} - -// Client returns a client that accesses the simulated chain. -func (n *Backend) Client() Client { - return n.client -} diff --git a/builder/ethclient/simulated/backend_test.go b/builder/ethclient/simulated/backend_test.go deleted file mode 100644 index a8fd7913c..000000000 --- a/builder/ethclient/simulated/backend_test.go +++ /dev/null @@ -1,308 +0,0 @@ -// 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 simulated - -import ( - "context" - "crypto/ecdsa" - "math/big" - "math/rand" - "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/params" -) - -var _ bind.ContractBackend = (Client)(nil) - -var ( - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddr = crypto.PubkeyToAddress(testKey.PublicKey) -) - -func simTestBackend(testAddr common.Address) *Backend { - return NewBackend( - types.GenesisAlloc{ - testAddr: {Balance: big.NewInt(10000000000000000)}, - }, - ) -} - -func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) { - client := sim.Client() - - // create a signed transaction to send - head, _ := client.HeaderByNumber(context.Background(), nil) // Should be child's, good enough - gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei)) - addr := crypto.PubkeyToAddress(key.PublicKey) - chainid, _ := client.ChainID(context.Background()) - nonce, err := client.PendingNonceAt(context.Background(), addr) - if err != nil { - return nil, err - } - tx := types.NewTx(&types.DynamicFeeTx{ - ChainID: chainid, - Nonce: nonce, - GasTipCap: big.NewInt(params.GWei), - GasFeeCap: gasPrice, - Gas: 21000, - To: &addr, - }) - return types.SignTx(tx, types.LatestSignerForChainID(chainid), key) -} - -func TestNewBackend(t *testing.T) { - sim := NewBackend(types.GenesisAlloc{}) - defer sim.Close() - - client := sim.Client() - num, err := client.BlockNumber(context.Background()) - if err != nil { - t.Fatal(err) - } - if num != 0 { - t.Fatalf("expected 0 got %v", num) - } - // Create a block - sim.Commit() - num, err = client.BlockNumber(context.Background()) - if err != nil { - t.Fatal(err) - } - if num != 1 { - t.Fatalf("expected 1 got %v", num) - } -} - -func TestAdjustTime(t *testing.T) { - sim := NewBackend(types.GenesisAlloc{}) - defer sim.Close() - - client := sim.Client() - block1, _ := client.BlockByNumber(context.Background(), nil) - - // Create a block - if err := sim.AdjustTime(time.Minute); err != nil { - t.Fatal(err) - } - block2, _ := client.BlockByNumber(context.Background(), nil) - prevTime := block1.Time() - newTime := block2.Time() - if newTime-prevTime != uint64(time.Minute) { - t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime) - } -} - -func TestSendTransaction(t *testing.T) { - sim := simTestBackend(testAddr) - defer sim.Close() - - client := sim.Client() - ctx := context.Background() - - signedTx, err := newTx(sim, testKey) - if err != nil { - t.Errorf("could not create transaction: %v", err) - } - // send tx to simulated backend - err = client.SendTransaction(ctx, signedTx) - if err != nil { - t.Errorf("could not add tx to pending block: %v", err) - } - sim.Commit() - block, err := client.BlockByNumber(ctx, big.NewInt(1)) - if err != nil { - t.Errorf("could not get block at height 1: %v", err) - } - - if signedTx.Hash() != block.Transactions()[0].Hash() { - t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash()) - } -} - -// TestFork check that the chain length after a reorg is correct. -// Steps: -// 1. Save the current block which will serve as parent for the fork. -// 2. Mine n blocks with n ∈ [0, 20]. -// 3. Assert that the chain length is n. -// 4. Fork by using the parent block as ancestor. -// 5. Mine n+1 blocks which should trigger a reorg. -// 6. Assert that the chain length is n+1. -// Since Commit() was called 2n+1 times in total, -// having a chain length of just n+1 means that a reorg occurred. -func TestFork(t *testing.T) { - t.Parallel() - testAddr := crypto.PubkeyToAddress(testKey.PublicKey) - sim := simTestBackend(testAddr) - defer sim.Close() - - client := sim.Client() - ctx := context.Background() - - // 1. - parent, _ := client.HeaderByNumber(ctx, nil) - - // 2. - n := int(rand.Int31n(21)) - for i := 0; i < n; i++ { - sim.Commit() - } - - // 3. - b, _ := client.BlockNumber(ctx) - if b != uint64(n) { - t.Error("wrong chain length") - } - - // 4. - sim.Fork(parent.Hash()) - - // 5. - for i := 0; i < n+1; i++ { - sim.Commit() - } - - // 6. - b, _ = client.BlockNumber(ctx) - if b != uint64(n+1) { - t.Error("wrong chain length") - } -} - -// TestForkResendTx checks that re-sending a TX after a fork -// is possible and does not cause a "nonce mismatch" panic. -// Steps: -// 1. Save the current block which will serve as parent for the fork. -// 2. Send a transaction. -// 3. Check that the TX is included in block 1. -// 4. Fork by using the parent block as ancestor. -// 5. Mine a block, Re-send the transaction and mine another one. -// 6. Check that the TX is now included in block 2. -func TestForkResendTx(t *testing.T) { - t.Parallel() - testAddr := crypto.PubkeyToAddress(testKey.PublicKey) - sim := simTestBackend(testAddr) - defer sim.Close() - - client := sim.Client() - ctx := context.Background() - - // 1. - parent, _ := client.HeaderByNumber(ctx, nil) - - // 2. - tx, err := newTx(sim, testKey) - if err != nil { - t.Fatalf("could not create transaction: %v", err) - } - client.SendTransaction(ctx, tx) - sim.Commit() - - // 3. - receipt, _ := client.TransactionReceipt(ctx, tx.Hash()) - if h := receipt.BlockNumber.Uint64(); h != 1 { - t.Errorf("TX included in wrong block: %d", h) - } - - // 4. - if err := sim.Fork(parent.Hash()); err != nil { - t.Errorf("forking: %v", err) - } - - // 5. - sim.Commit() - if err := client.SendTransaction(ctx, tx); err != nil { - t.Fatalf("sending transaction: %v", err) - } - sim.Commit() - receipt, _ = client.TransactionReceipt(ctx, tx.Hash()) - if h := receipt.BlockNumber.Uint64(); h != 2 { - t.Errorf("TX included in wrong block: %d", h) - } -} - -func TestCommitReturnValue(t *testing.T) { - t.Parallel() - testAddr := crypto.PubkeyToAddress(testKey.PublicKey) - sim := simTestBackend(testAddr) - defer sim.Close() - - client := sim.Client() - ctx := context.Background() - - // Test if Commit returns the correct block hash - h1 := sim.Commit() - cur, _ := client.HeaderByNumber(ctx, nil) - if h1 != cur.Hash() { - t.Error("Commit did not return the hash of the last block.") - } - - // Create a block in the original chain (containing a transaction to force different block hashes) - head, _ := client.HeaderByNumber(ctx, nil) // Should be child's, good enough - gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) - _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil) - tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey) - client.SendTransaction(ctx, tx) - - h2 := sim.Commit() - - // Create another block in the original chain - sim.Commit() - - // Fork at the first bock - if err := sim.Fork(h1); err != nil { - t.Errorf("forking: %v", err) - } - - // Test if Commit returns the correct block hash after the reorg - h2fork := sim.Commit() - if h2 == h2fork { - t.Error("The block in the fork and the original block are the same block!") - } - if header, err := client.HeaderByHash(ctx, h2fork); err != nil || header == nil { - t.Error("Could not retrieve the just created block (side-chain)") - } -} - -// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork -// block's parent rather than the canonical head's parent. -func TestAdjustTimeAfterFork(t *testing.T) { - t.Parallel() - testAddr := crypto.PubkeyToAddress(testKey.PublicKey) - sim := simTestBackend(testAddr) - defer sim.Close() - - client := sim.Client() - ctx := context.Background() - - sim.Commit() // h1 - h1, _ := client.HeaderByNumber(ctx, nil) - - sim.Commit() // h2 - sim.Fork(h1.Hash()) - sim.AdjustTime(1 * time.Second) - sim.Commit() - - head, _ := client.HeaderByNumber(ctx, nil) - if head.Number.Uint64() == 2 && head.ParentHash != h1.Hash() { - t.Errorf("failed to build block on fork") - } -} diff --git a/builder/ethclient/simulated/options.go b/builder/ethclient/simulated/options.go deleted file mode 100644 index 6db995c91..000000000 --- a/builder/ethclient/simulated/options.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2024 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 simulated - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" -) - -// WithBlockGasLimit configures the simulated backend to target a specific gas limit -// when producing blocks. -func WithBlockGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) { - return func(nodeConf *node.Config, ethConf *ethconfig.Config) { - ethConf.Genesis.GasLimit = gaslimit - ethConf.Miner.GasCeil = gaslimit - } -} - -// WithCallGasLimit configures the simulated backend to cap eth_calls to a specific -// gas limit when running client operations. -func WithCallGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) { - return func(nodeConf *node.Config, ethConf *ethconfig.Config) { - ethConf.RPCGasCap = gaslimit - } -} - -// WithMinerMinTip configures the simulated backend to require a specific minimum -// gas tip for a transaction to be included. -// -// 0 is not possible as a live Geth node would reject that due to DoS protection, -// so the simulated backend will replicate that behavior for consistency. -func WithMinerMinTip(tip *big.Int) func(nodeConf *node.Config, ethConf *ethconfig.Config) { - if tip == nil || tip.Cmp(new(big.Int)) <= 0 { - panic("invalid miner minimum tip") - } - return func(nodeConf *node.Config, ethConf *ethconfig.Config) { - ethConf.Miner.GasPrice = tip - } -} diff --git a/builder/ethclient/simulated/options_test.go b/builder/ethclient/simulated/options_test.go deleted file mode 100644 index 9ff2be5ff..000000000 --- a/builder/ethclient/simulated/options_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2024 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 simulated - -import ( - "context" - "math/big" - "strings" - "testing" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" -) - -// Tests that the simulator starts with the initial gas limit in the genesis block, -// and that it keeps the same target value. -func TestWithBlockGasLimitOption(t *testing.T) { - // Construct a simulator, targeting a different gas limit - sim := NewBackend(types.GenesisAlloc{}, WithBlockGasLimit(12_345_678)) - defer sim.Close() - - client := sim.Client() - genesis, err := client.BlockByNumber(context.Background(), big.NewInt(0)) - if err != nil { - t.Fatalf("failed to retrieve genesis block: %v", err) - } - if genesis.GasLimit() != 12_345_678 { - t.Errorf("genesis gas limit mismatch: have %v, want %v", genesis.GasLimit(), 12_345_678) - } - // Produce a number of blocks and verify the locked in gas target - sim.Commit() - head, err := client.BlockByNumber(context.Background(), big.NewInt(1)) - if err != nil { - t.Fatalf("failed to retrieve head block: %v", err) - } - if head.GasLimit() != 12_345_678 { - t.Errorf("head gas limit mismatch: have %v, want %v", head.GasLimit(), 12_345_678) - } -} - -// Tests that the simulator honors the RPC call caps set by the options. -func TestWithCallGasLimitOption(t *testing.T) { - // Construct a simulator, targeting a different gas limit - sim := NewBackend(types.GenesisAlloc{ - testAddr: {Balance: big.NewInt(10000000000000000)}, - }, WithCallGasLimit(params.TxGas-1)) - defer sim.Close() - - client := sim.Client() - _, err := client.CallContract(context.Background(), ethereum.CallMsg{ - From: testAddr, - To: &testAddr, - Gas: 21000, - }, nil) - if !strings.Contains(err.Error(), core.ErrIntrinsicGas.Error()) { - t.Fatalf("error mismatch: have %v, want %v", err, core.ErrIntrinsicGas) - } -} diff --git a/builder/ethdb/batch.go b/builder/ethdb/batch.go deleted file mode 100644 index 541f40c83..000000000 --- a/builder/ethdb/batch.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2018 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 ethdb - -// IdealBatchSize defines the size of the data batches should ideally add in one -// write. -const IdealBatchSize = 100 * 1024 - -// Batch is a write-only database that commits changes to its host database -// when Write is called. A batch cannot be used concurrently. -type Batch interface { - KeyValueWriter - - // ValueSize retrieves the amount of data queued up for writing. - ValueSize() int - - // Write flushes any accumulated data to disk. - Write() error - - // Reset resets the batch for reuse. - Reset() - - // Replay replays the batch contents. - Replay(w KeyValueWriter) error -} - -// Batcher wraps the NewBatch method of a backing data store. -type Batcher interface { - // NewBatch creates a write-only database that buffers changes to its host db - // until a final write is called. - NewBatch() Batch - - // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. - NewBatchWithSize(size int) Batch -} - -// HookedBatch wraps an arbitrary batch where each operation may be hooked into -// to monitor from black box code. -type HookedBatch struct { - Batch - - OnPut func(key []byte, value []byte) // Callback if a key is inserted - OnDelete func(key []byte) // Callback if a key is deleted -} - -// Put inserts the given value into the key-value data store. -func (b HookedBatch) Put(key []byte, value []byte) error { - if b.OnPut != nil { - b.OnPut(key, value) - } - return b.Batch.Put(key, value) -} - -// Delete removes the key from the key-value data store. -func (b HookedBatch) Delete(key []byte) error { - if b.OnDelete != nil { - b.OnDelete(key) - } - return b.Batch.Delete(key) -} diff --git a/builder/ethdb/database.go b/builder/ethdb/database.go deleted file mode 100644 index 4d4817daf..000000000 --- a/builder/ethdb/database.go +++ /dev/null @@ -1,192 +0,0 @@ -// 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 ethdb defines the interfaces for an Ethereum data store. -package ethdb - -import "io" - -// KeyValueReader wraps the Has and Get method of a backing data store. -type KeyValueReader interface { - // Has retrieves if a key is present in the key-value data store. - Has(key []byte) (bool, error) - - // Get retrieves the given key if it's present in the key-value data store. - Get(key []byte) ([]byte, error) -} - -// KeyValueWriter wraps the Put method of a backing data store. -type KeyValueWriter interface { - // Put inserts the given value into the key-value data store. - Put(key []byte, value []byte) error - - // Delete removes the key from the key-value data store. - Delete(key []byte) error -} - -// KeyValueStater wraps the Stat method of a backing data store. -type KeyValueStater interface { - // Stat returns a particular internal stat of the database. - Stat(property string) (string, error) -} - -// Compacter wraps the Compact method of a backing data store. -type Compacter interface { - // Compact flattens the underlying data store for the given key range. In essence, - // deleted and overwritten versions are discarded, and the data is rearranged to - // reduce the cost of operations needed to access them. - // - // A nil start is treated as a key before all keys in the data store; a nil limit - // is treated as a key after all keys in the data store. If both is nil then it - // will compact entire data store. - Compact(start []byte, limit []byte) error -} - -// KeyValueStore contains all the methods required to allow handling different -// key-value data stores backing the high level database. -type KeyValueStore interface { - KeyValueReader - KeyValueWriter - KeyValueStater - Batcher - Iteratee - Compacter - Snapshotter - io.Closer -} - -// AncientReaderOp contains the methods required to read from immutable ancient data. -type AncientReaderOp interface { - // HasAncient returns an indicator whether the specified data exists in the - // ancient store. - HasAncient(kind string, number uint64) (bool, error) - - // Ancient retrieves an ancient binary blob from the append-only immutable files. - Ancient(kind string, number uint64) ([]byte, error) - - // AncientRange retrieves multiple items in sequence, starting from the index 'start'. - // It will return - // - at most 'count' items, - // - if maxBytes is specified: at least 1 item (even if exceeding the maxByteSize), - // but will otherwise return as many items as fit into maxByteSize. - // - if maxBytes is not specified, 'count' items will be returned if they are present - AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) - - // Ancients returns the ancient item numbers in the ancient store. - Ancients() (uint64, error) - - // Tail returns the number of first stored item in the freezer. - // This number can also be interpreted as the total deleted item numbers. - Tail() (uint64, error) - - // AncientSize returns the ancient size of the specified category. - AncientSize(kind string) (uint64, error) -} - -// AncientReader is the extended ancient reader interface including 'batched' or 'atomic' reading. -type AncientReader interface { - AncientReaderOp - - // ReadAncients runs the given read operation while ensuring that no writes take place - // on the underlying freezer. - ReadAncients(fn func(AncientReaderOp) error) (err error) -} - -// AncientWriter contains the methods required to write to immutable ancient data. -type AncientWriter interface { - // ModifyAncients runs a write operation on the ancient store. - // If the function returns an error, any changes to the underlying store are reverted. - // The integer return value is the total size of the written data. - ModifyAncients(func(AncientWriteOp) error) (int64, error) - - // TruncateHead discards all but the first n ancient data from the ancient store. - // After the truncation, the latest item can be accessed it item_n-1(start from 0). - TruncateHead(n uint64) (uint64, error) - - // TruncateTail discards the first n ancient data from the ancient store. The already - // deleted items are ignored. After the truncation, the earliest item can be accessed - // is item_n(start from 0). The deleted items may not be removed from the ancient store - // immediately, but only when the accumulated deleted data reach the threshold then - // will be removed all together. - TruncateTail(n uint64) (uint64, error) - - // Sync flushes all in-memory ancient store data to disk. - Sync() error - - // MigrateTable processes and migrates entries of a given table to a new format. - // The second argument is a function that takes a raw entry and returns it - // in the newest format. - MigrateTable(string, func([]byte) ([]byte, error)) error -} - -// AncientWriteOp is given to the function argument of ModifyAncients. -type AncientWriteOp interface { - // Append adds an RLP-encoded item. - Append(kind string, number uint64, item interface{}) error - - // AppendRaw adds an item without RLP-encoding it. - AppendRaw(kind string, number uint64, item []byte) error -} - -// AncientStater wraps the Stat method of a backing data store. -type AncientStater interface { - // AncientDatadir returns the path of root ancient directory. Empty string - // will be returned if ancient store is not enabled at all. The returned - // path can be used to construct the path of other freezers. - AncientDatadir() (string, error) -} - -// Reader contains the methods required to read data from both key-value as well as -// immutable ancient data. -type Reader interface { - KeyValueReader - AncientReader -} - -// Writer contains the methods required to write data to both key-value as well as -// immutable ancient data. -type Writer interface { - KeyValueWriter - AncientWriter -} - -// Stater contains the methods required to retrieve states from both key-value as well as -// immutable ancient data. -type Stater interface { - KeyValueStater - AncientStater -} - -// AncientStore contains all the methods required to allow handling different -// ancient data stores backing immutable chain data store. -type AncientStore interface { - AncientReader - AncientWriter - io.Closer -} - -// Database contains all the methods required by the high level database to not -// only access the key-value data store but also the chain freezer. -type Database interface { - Reader - Writer - Batcher - Iteratee - Stater - Compacter - Snapshotter - io.Closer -} diff --git a/builder/ethdb/dbtest/testsuite.go b/builder/ethdb/dbtest/testsuite.go deleted file mode 100644 index 29bd24364..000000000 --- a/builder/ethdb/dbtest/testsuite.go +++ /dev/null @@ -1,537 +0,0 @@ -// 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 dbtest - -import ( - "bytes" - "crypto/rand" - "reflect" - "sort" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" - "golang.org/x/exp/slices" -) - -// TestDatabaseSuite runs a suite of tests against a KeyValueStore database -// implementation. -func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) { - t.Run("Iterator", func(t *testing.T) { - tests := []struct { - content map[string]string - prefix string - start string - order []string - }{ - // Empty databases should be iterable - {map[string]string{}, "", "", nil}, - {map[string]string{}, "non-existent-prefix", "", nil}, - - // Single-item databases should be iterable - {map[string]string{"key": "val"}, "", "", []string{"key"}}, - {map[string]string{"key": "val"}, "k", "", []string{"key"}}, - {map[string]string{"key": "val"}, "l", "", nil}, - - // Multi-item databases should be fully iterable - { - map[string]string{"k1": "v1", "k5": "v5", "k2": "v2", "k4": "v4", "k3": "v3"}, - "", "", - []string{"k1", "k2", "k3", "k4", "k5"}, - }, - { - map[string]string{"k1": "v1", "k5": "v5", "k2": "v2", "k4": "v4", "k3": "v3"}, - "k", "", - []string{"k1", "k2", "k3", "k4", "k5"}, - }, - { - map[string]string{"k1": "v1", "k5": "v5", "k2": "v2", "k4": "v4", "k3": "v3"}, - "l", "", - nil, - }, - // Multi-item databases should be prefix-iterable - { - map[string]string{ - "ka1": "va1", "ka5": "va5", "ka2": "va2", "ka4": "va4", "ka3": "va3", - "kb1": "vb1", "kb5": "vb5", "kb2": "vb2", "kb4": "vb4", "kb3": "vb3", - }, - "ka", "", - []string{"ka1", "ka2", "ka3", "ka4", "ka5"}, - }, - { - map[string]string{ - "ka1": "va1", "ka5": "va5", "ka2": "va2", "ka4": "va4", "ka3": "va3", - "kb1": "vb1", "kb5": "vb5", "kb2": "vb2", "kb4": "vb4", "kb3": "vb3", - }, - "kc", "", - nil, - }, - // Multi-item databases should be prefix-iterable with start position - { - map[string]string{ - "ka1": "va1", "ka5": "va5", "ka2": "va2", "ka4": "va4", "ka3": "va3", - "kb1": "vb1", "kb5": "vb5", "kb2": "vb2", "kb4": "vb4", "kb3": "vb3", - }, - "ka", "3", - []string{"ka3", "ka4", "ka5"}, - }, - { - map[string]string{ - "ka1": "va1", "ka5": "va5", "ka2": "va2", "ka4": "va4", "ka3": "va3", - "kb1": "vb1", "kb5": "vb5", "kb2": "vb2", "kb4": "vb4", "kb3": "vb3", - }, - "ka", "8", - nil, - }, - } - for i, tt := range tests { - // Create the key-value data store - db := New() - for key, val := range tt.content { - if err := db.Put([]byte(key), []byte(val)); err != nil { - t.Fatalf("test %d: failed to insert item %s:%s into database: %v", i, key, val, err) - } - } - // Iterate over the database with the given configs and verify the results - it, idx := db.NewIterator([]byte(tt.prefix), []byte(tt.start)), 0 - for it.Next() { - if len(tt.order) <= idx { - t.Errorf("test %d: prefix=%q more items than expected: checking idx=%d (key %q), expecting len=%d", i, tt.prefix, idx, it.Key(), len(tt.order)) - break - } - if !bytes.Equal(it.Key(), []byte(tt.order[idx])) { - t.Errorf("test %d: item %d: key mismatch: have %s, want %s", i, idx, string(it.Key()), tt.order[idx]) - } - if !bytes.Equal(it.Value(), []byte(tt.content[tt.order[idx]])) { - t.Errorf("test %d: item %d: value mismatch: have %s, want %s", i, idx, string(it.Value()), tt.content[tt.order[idx]]) - } - idx++ - } - if err := it.Error(); err != nil { - t.Errorf("test %d: iteration failed: %v", i, err) - } - if idx != len(tt.order) { - t.Errorf("test %d: iteration terminated prematurely: have %d, want %d", i, idx, len(tt.order)) - } - db.Close() - } - }) - - t.Run("IteratorWith", func(t *testing.T) { - db := New() - defer db.Close() - - keys := []string{"1", "2", "3", "4", "6", "10", "11", "12", "20", "21", "22"} - sort.Strings(keys) // 1, 10, 11, etc - - for _, k := range keys { - if err := db.Put([]byte(k), nil); err != nil { - t.Fatal(err) - } - } - - { - it := db.NewIterator(nil, nil) - got, want := iterateKeys(it), keys - if err := it.Error(); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("Iterator: got: %s; want: %s", got, want) - } - } - - { - it := db.NewIterator([]byte("1"), nil) - got, want := iterateKeys(it), []string{"1", "10", "11", "12"} - if err := it.Error(); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("IteratorWith(1,nil): got: %s; want: %s", got, want) - } - } - - { - it := db.NewIterator([]byte("5"), nil) - got, want := iterateKeys(it), []string{} - if err := it.Error(); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("IteratorWith(5,nil): got: %s; want: %s", got, want) - } - } - - { - it := db.NewIterator(nil, []byte("2")) - got, want := iterateKeys(it), []string{"2", "20", "21", "22", "3", "4", "6"} - if err := it.Error(); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("IteratorWith(nil,2): got: %s; want: %s", got, want) - } - } - - { - it := db.NewIterator(nil, []byte("5")) - got, want := iterateKeys(it), []string{"6"} - if err := it.Error(); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("IteratorWith(nil,5): got: %s; want: %s", got, want) - } - } - }) - - t.Run("KeyValueOperations", func(t *testing.T) { - db := New() - defer db.Close() - - key := []byte("foo") - - if got, err := db.Has(key); err != nil { - t.Error(err) - } else if got { - t.Errorf("wrong value: %t", got) - } - - value := []byte("hello world") - if err := db.Put(key, value); err != nil { - t.Error(err) - } - - if got, err := db.Has(key); err != nil { - t.Error(err) - } else if !got { - t.Errorf("wrong value: %t", got) - } - - if got, err := db.Get(key); err != nil { - t.Error(err) - } else if !bytes.Equal(got, value) { - t.Errorf("wrong value: %q", got) - } - - if err := db.Delete(key); err != nil { - t.Error(err) - } - - if got, err := db.Has(key); err != nil { - t.Error(err) - } else if got { - t.Errorf("wrong value: %t", got) - } - }) - - t.Run("Batch", func(t *testing.T) { - db := New() - defer db.Close() - - b := db.NewBatch() - for _, k := range []string{"1", "2", "3", "4"} { - if err := b.Put([]byte(k), nil); err != nil { - t.Fatal(err) - } - } - - if has, err := db.Has([]byte("1")); err != nil { - t.Fatal(err) - } else if has { - t.Error("db contains element before batch write") - } - - if err := b.Write(); err != nil { - t.Fatal(err) - } - - { - it := db.NewIterator(nil, nil) - if got, want := iterateKeys(it), []string{"1", "2", "3", "4"}; !reflect.DeepEqual(got, want) { - t.Errorf("got: %s; want: %s", got, want) - } - } - - b.Reset() - - // Mix writes and deletes in batch - b.Put([]byte("5"), nil) - b.Delete([]byte("1")) - b.Put([]byte("6"), nil) - - b.Delete([]byte("3")) // delete then put - b.Put([]byte("3"), nil) - - b.Put([]byte("7"), nil) // put then delete - b.Delete([]byte("7")) - - if err := b.Write(); err != nil { - t.Fatal(err) - } - - { - it := db.NewIterator(nil, nil) - if got, want := iterateKeys(it), []string{"2", "3", "4", "5", "6"}; !reflect.DeepEqual(got, want) { - t.Errorf("got: %s; want: %s", got, want) - } - } - }) - - t.Run("BatchReplay", func(t *testing.T) { - db := New() - defer db.Close() - - want := []string{"1", "2", "3", "4"} - b := db.NewBatch() - for _, k := range want { - if err := b.Put([]byte(k), nil); err != nil { - t.Fatal(err) - } - } - - b2 := db.NewBatch() - if err := b.Replay(b2); err != nil { - t.Fatal(err) - } - - if err := b2.Replay(db); err != nil { - t.Fatal(err) - } - - it := db.NewIterator(nil, nil) - if got := iterateKeys(it); !reflect.DeepEqual(got, want) { - t.Errorf("got: %s; want: %s", got, want) - } - }) - - t.Run("Snapshot", func(t *testing.T) { - db := New() - defer db.Close() - - initial := map[string]string{ - "k1": "v1", "k2": "v2", "k3": "", "k4": "", - } - for k, v := range initial { - db.Put([]byte(k), []byte(v)) - } - snapshot, err := db.NewSnapshot() - if err != nil { - t.Fatal(err) - } - for k, v := range initial { - got, err := snapshot.Get([]byte(k)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(got, []byte(v)) { - t.Fatalf("Unexpected value want: %v, got %v", v, got) - } - } - - // Flush more modifications into the database, ensure the snapshot - // isn't affected. - var ( - update = map[string]string{"k1": "v1-b", "k3": "v3-b"} - insert = map[string]string{"k5": "v5-b"} - delete = map[string]string{"k2": ""} - ) - for k, v := range update { - db.Put([]byte(k), []byte(v)) - } - for k, v := range insert { - db.Put([]byte(k), []byte(v)) - } - for k := range delete { - db.Delete([]byte(k)) - } - for k, v := range initial { - got, err := snapshot.Get([]byte(k)) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(got, []byte(v)) { - t.Fatalf("Unexpected value want: %v, got %v", v, got) - } - } - for k := range insert { - got, err := snapshot.Get([]byte(k)) - if err == nil || len(got) != 0 { - t.Fatal("Unexpected value") - } - } - for k := range delete { - got, err := snapshot.Get([]byte(k)) - if err != nil || len(got) == 0 { - t.Fatal("Unexpected deletion") - } - } - }) - - t.Run("OperatonsAfterClose", func(t *testing.T) { - db := New() - db.Put([]byte("key"), []byte("value")) - db.Close() - if _, err := db.Get([]byte("key")); err == nil { - t.Fatalf("expected error on Get after Close") - } - if _, err := db.Has([]byte("key")); err == nil { - t.Fatalf("expected error on Get after Close") - } - if err := db.Put([]byte("key2"), []byte("value2")); err == nil { - t.Fatalf("expected error on Put after Close") - } - if err := db.Delete([]byte("key")); err == nil { - t.Fatalf("expected error on Delete after Close") - } - - b := db.NewBatch() - if err := b.Put([]byte("batchkey"), []byte("batchval")); err != nil { - t.Fatalf("expected no error on batch.Put after Close, got %v", err) - } - if err := b.Write(); err == nil { - t.Fatalf("expected error on batch.Write after Close") - } - }) -} - -// BenchDatabaseSuite runs a suite of benchmarks against a KeyValueStore database -// implementation. -func BenchDatabaseSuite(b *testing.B, New func() ethdb.KeyValueStore) { - var ( - keys, vals = makeDataset(1_000_000, 32, 32, false) - sKeys, sVals = makeDataset(1_000_000, 32, 32, true) - ) - // Run benchmarks sequentially - b.Run("Write", func(b *testing.B) { - benchWrite := func(b *testing.B, keys, vals [][]byte) { - b.ResetTimer() - b.ReportAllocs() - - db := New() - defer db.Close() - - for i := 0; i < len(keys); i++ { - db.Put(keys[i], vals[i]) - } - } - b.Run("WriteSorted", func(b *testing.B) { - benchWrite(b, sKeys, sVals) - }) - b.Run("WriteRandom", func(b *testing.B) { - benchWrite(b, keys, vals) - }) - }) - b.Run("Read", func(b *testing.B) { - benchRead := func(b *testing.B, keys, vals [][]byte) { - db := New() - defer db.Close() - - for i := 0; i < len(keys); i++ { - db.Put(keys[i], vals[i]) - } - b.ResetTimer() - b.ReportAllocs() - - for i := 0; i < len(keys); i++ { - db.Get(keys[i]) - } - } - b.Run("ReadSorted", func(b *testing.B) { - benchRead(b, sKeys, sVals) - }) - b.Run("ReadRandom", func(b *testing.B) { - benchRead(b, keys, vals) - }) - }) - b.Run("Iteration", func(b *testing.B) { - benchIteration := func(b *testing.B, keys, vals [][]byte) { - db := New() - defer db.Close() - - for i := 0; i < len(keys); i++ { - db.Put(keys[i], vals[i]) - } - b.ResetTimer() - b.ReportAllocs() - - it := db.NewIterator(nil, nil) - for it.Next() { - } - it.Release() - } - b.Run("IterationSorted", func(b *testing.B) { - benchIteration(b, sKeys, sVals) - }) - b.Run("IterationRandom", func(b *testing.B) { - benchIteration(b, keys, vals) - }) - }) - b.Run("BatchWrite", func(b *testing.B) { - benchBatchWrite := func(b *testing.B, keys, vals [][]byte) { - b.ResetTimer() - b.ReportAllocs() - - db := New() - defer db.Close() - - batch := db.NewBatch() - for i := 0; i < len(keys); i++ { - batch.Put(keys[i], vals[i]) - } - batch.Write() - } - b.Run("BenchWriteSorted", func(b *testing.B) { - benchBatchWrite(b, sKeys, sVals) - }) - b.Run("BenchWriteRandom", func(b *testing.B) { - benchBatchWrite(b, keys, vals) - }) - }) -} - -func iterateKeys(it ethdb.Iterator) []string { - keys := []string{} - for it.Next() { - keys = append(keys, string(it.Key())) - } - sort.Strings(keys) - it.Release() - return keys -} - -// randomHash generates a random blob of data and returns it as a hash. -func randBytes(len int) []byte { - buf := make([]byte, len) - if n, err := rand.Read(buf); n != len || err != nil { - panic(err) - } - return buf -} - -func makeDataset(size, ksize, vsize int, order bool) ([][]byte, [][]byte) { - var keys [][]byte - var vals [][]byte - for i := 0; i < size; i += 1 { - keys = append(keys, randBytes(ksize)) - vals = append(vals, randBytes(vsize)) - } - if order { - slices.SortFunc(keys, func(a, b []byte) int { return bytes.Compare(a, b) }) - } - return keys, vals -} diff --git a/builder/ethdb/iterator.go b/builder/ethdb/iterator.go deleted file mode 100644 index 2b49c93a9..000000000 --- a/builder/ethdb/iterator.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 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 ethdb - -// Iterator iterates over a database's key/value pairs in ascending key order. -// -// When it encounters an error any seek will return false and will yield no key/ -// value pairs. The error can be queried by calling the Error method. Calling -// Release is still necessary. -// -// An iterator must be released after use, but it is not necessary to read an -// iterator until exhaustion. An iterator is not safe for concurrent use, but it -// is safe to use multiple iterators concurrently. -type Iterator interface { - // Next moves the iterator to the next key/value pair. It returns whether the - // iterator is exhausted. - Next() bool - - // Error returns any accumulated error. Exhausting all the key/value pairs - // is not considered to be an error. - Error() error - - // Key returns the key of the current key/value pair, or nil if done. The caller - // should not modify the contents of the returned slice, and its contents may - // change on the next call to Next. - Key() []byte - - // Value returns the value of the current key/value pair, or nil if done. The - // caller should not modify the contents of the returned slice, and its contents - // may change on the next call to Next. - Value() []byte - - // Release releases associated resources. Release should always succeed and can - // be called multiple times without causing error. - Release() -} - -// Iteratee wraps the NewIterator methods of a backing data store. -type Iteratee interface { - // NewIterator creates a binary-alphabetical iterator over a subset - // of database content with a particular key prefix, starting at a particular - // initial key (or after, if it does not exist). - // - // Note: This method assumes that the prefix is NOT part of the start, so there's - // no need for the caller to prepend the prefix to the start - NewIterator(prefix []byte, start []byte) Iterator -} diff --git a/builder/ethdb/leveldb/leveldb.go b/builder/ethdb/leveldb/leveldb.go deleted file mode 100644 index e58efbddb..000000000 --- a/builder/ethdb/leveldb/leveldb.go +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright 2018 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 . - -//go:build !js -// +build !js - -// Package leveldb implements the key-value database layer based on LevelDB. -package leveldb - -import ( - "fmt" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/errors" - "github.com/syndtr/goleveldb/leveldb/filter" - "github.com/syndtr/goleveldb/leveldb/opt" - "github.com/syndtr/goleveldb/leveldb/util" -) - -const ( - // degradationWarnInterval specifies how often warning should be printed if the - // leveldb database cannot keep up with requested writes. - degradationWarnInterval = time.Minute - - // minCache is the minimum amount of memory in megabytes to allocate to leveldb - // read and write caching, split half and half. - minCache = 16 - - // minHandles is the minimum number of files handles to allocate to the open - // database files. - minHandles = 16 - - // metricsGatheringInterval specifies the interval to retrieve leveldb database - // compaction, io and pause stats to report to the user. - metricsGatheringInterval = 3 * time.Second -) - -// Database is a persistent key-value store. Apart from basic data storage -// functionality it also supports batch writes and iterating over the keyspace in -// binary-alphabetical order. -type Database struct { - fn string // filename for reporting - db *leveldb.DB // LevelDB instance - - compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskSizeGauge metrics.Gauge // Gauge for tracking the size of all the levels in the database - diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written - memCompGauge metrics.Gauge // Gauge for tracking the number of memory compaction - level0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in level0 - nonlevel0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in non0 level - seekCompGauge metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt - manualMemAllocGauge metrics.Gauge // Gauge to track the amount of memory that has been manually allocated (not a part of runtime/GC) - - levelsGauge []metrics.Gauge // Gauge for tracking the number of tables in levels - - quitLock sync.Mutex // Mutex protecting the quit channel access - quitChan chan chan error // Quit channel to stop the metrics collection before closing the database - - log log.Logger // Contextual logger tracking the database path -} - -// New returns a wrapped LevelDB object. The namespace is the prefix that the -// metrics reporting should use for surfacing internal stats. -func New(file string, cache int, handles int, namespace string, readonly bool) (*Database, error) { - return NewCustom(file, namespace, func(options *opt.Options) { - // Ensure we have some minimal caching and file guarantees - if cache < minCache { - cache = minCache - } - if handles < minHandles { - handles = minHandles - } - // Set default options - options.OpenFilesCacheCapacity = handles - options.BlockCacheCapacity = cache / 2 * opt.MiB - options.WriteBuffer = cache / 4 * opt.MiB // Two of these are used internally - if readonly { - options.ReadOnly = true - } - }) -} - -// NewCustom returns a wrapped LevelDB object. The namespace is the prefix that the -// metrics reporting should use for surfacing internal stats. -// The customize function allows the caller to modify the leveldb options. -func NewCustom(file string, namespace string, customize func(options *opt.Options)) (*Database, error) { - options := configureOptions(customize) - logger := log.New("database", file) - usedCache := options.GetBlockCacheCapacity() + options.GetWriteBuffer()*2 - logCtx := []interface{}{"cache", common.StorageSize(usedCache), "handles", options.GetOpenFilesCacheCapacity()} - if options.ReadOnly { - logCtx = append(logCtx, "readonly", "true") - } - logger.Info("Allocated cache and file handles", logCtx...) - - // Open the db and recover any potential corruptions - db, err := leveldb.OpenFile(file, options) - if _, corrupted := err.(*errors.ErrCorrupted); corrupted { - db, err = leveldb.RecoverFile(file, nil) - } - if err != nil { - return nil, err - } - // Assemble the wrapper with all the registered metrics - ldb := &Database{ - fn: file, - db: db, - log: logger, - quitChan: make(chan chan error), - } - ldb.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil) - ldb.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil) - ldb.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil) - ldb.diskSizeGauge = metrics.NewRegisteredGauge(namespace+"disk/size", nil) - ldb.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil) - ldb.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil) - ldb.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil) - ldb.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil) - ldb.memCompGauge = metrics.NewRegisteredGauge(namespace+"compact/memory", nil) - ldb.level0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/level0", nil) - ldb.nonlevel0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/nonlevel0", nil) - ldb.seekCompGauge = metrics.NewRegisteredGauge(namespace+"compact/seek", nil) - ldb.manualMemAllocGauge = metrics.NewRegisteredGauge(namespace+"memory/manualalloc", nil) - - // Start up the metrics gathering and return - go ldb.meter(metricsGatheringInterval, namespace) - return ldb, nil -} - -// configureOptions sets some default options, then runs the provided setter. -func configureOptions(customizeFn func(*opt.Options)) *opt.Options { - // Set default options - options := &opt.Options{ - Filter: filter.NewBloomFilter(10), - DisableSeeksCompaction: true, - } - // Allow caller to make custom modifications to the options - if customizeFn != nil { - customizeFn(options) - } - return options -} - -// Close stops the metrics collection, flushes any pending data to disk and closes -// all io accesses to the underlying key-value store. -func (db *Database) Close() error { - db.quitLock.Lock() - defer db.quitLock.Unlock() - - if db.quitChan != nil { - errc := make(chan error) - db.quitChan <- errc - if err := <-errc; err != nil { - db.log.Error("Metrics collection failed", "err", err) - } - db.quitChan = nil - } - return db.db.Close() -} - -// Has retrieves if a key is present in the key-value store. -func (db *Database) Has(key []byte) (bool, error) { - return db.db.Has(key, nil) -} - -// Get retrieves the given key if it's present in the key-value store. -func (db *Database) Get(key []byte) ([]byte, error) { - dat, err := db.db.Get(key, nil) - if err != nil { - return nil, err - } - return dat, nil -} - -// Put inserts the given value into the key-value store. -func (db *Database) Put(key []byte, value []byte) error { - return db.db.Put(key, value, nil) -} - -// Delete removes the key from the key-value store. -func (db *Database) Delete(key []byte) error { - return db.db.Delete(key, nil) -} - -// NewBatch creates a write-only key-value store that buffers changes to its host -// database until a final write is called. -func (db *Database) NewBatch() ethdb.Batch { - return &batch{ - db: db.db, - b: new(leveldb.Batch), - } -} - -// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -func (db *Database) NewBatchWithSize(size int) ethdb.Batch { - return &batch{ - db: db.db, - b: leveldb.MakeBatch(size), - } -} - -// NewIterator creates a binary-alphabetical iterator over a subset -// of database content with a particular key prefix, starting at a particular -// initial key (or after, if it does not exist). -func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - return db.db.NewIterator(bytesPrefixRange(prefix, start), nil) -} - -// NewSnapshot creates a database snapshot based on the current state. -// The created snapshot will not be affected by all following mutations -// happened on the database. -// Note don't forget to release the snapshot once it's used up, otherwise -// the stale data will never be cleaned up by the underlying compactor. -func (db *Database) NewSnapshot() (ethdb.Snapshot, error) { - snap, err := db.db.GetSnapshot() - if err != nil { - return nil, err - } - return &snapshot{db: snap}, nil -} - -// Stat returns a particular internal stat of the database. -func (db *Database) Stat(property string) (string, error) { - if property == "" { - property = "leveldb.stats" - } else if !strings.HasPrefix(property, "leveldb.") { - property = "leveldb." + property - } - return db.db.GetProperty(property) -} - -// Compact flattens the underlying data store for the given key range. In essence, -// deleted and overwritten versions are discarded, and the data is rearranged to -// reduce the cost of operations needed to access them. -// -// A nil start is treated as a key before all keys in the data store; a nil limit -// is treated as a key after all keys in the data store. If both is nil then it -// will compact entire data store. -func (db *Database) Compact(start []byte, limit []byte) error { - return db.db.CompactRange(util.Range{Start: start, Limit: limit}) -} - -// Path returns the path to the database directory. -func (db *Database) Path() string { - return db.fn -} - -// meter periodically retrieves internal leveldb counters and reports them to -// the metrics subsystem. -func (db *Database) meter(refresh time.Duration, namespace string) { - // Create the counters to store current and previous compaction values - compactions := make([][]int64, 2) - for i := 0; i < 2; i++ { - compactions[i] = make([]int64, 4) - } - // Create storages for states and warning log tracer. - var ( - errc chan error - merr error - - stats leveldb.DBStats - iostats [2]int64 - delaystats [2]int64 - lastWritePaused time.Time - ) - timer := time.NewTimer(refresh) - defer timer.Stop() - - // Iterate ad infinitum and collect the stats - for i := 1; errc == nil && merr == nil; i++ { - // Retrieve the database stats - // Stats method resets buffers inside therefore it's okay to just pass the struct. - err := db.db.Stats(&stats) - if err != nil { - db.log.Error("Failed to read database stats", "err", err) - merr = err - continue - } - // Iterate over all the leveldbTable rows, and accumulate the entries - for j := 0; j < len(compactions[i%2]); j++ { - compactions[i%2][j] = 0 - } - compactions[i%2][0] = stats.LevelSizes.Sum() - for _, t := range stats.LevelDurations { - compactions[i%2][1] += t.Nanoseconds() - } - compactions[i%2][2] = stats.LevelRead.Sum() - compactions[i%2][3] = stats.LevelWrite.Sum() - // Update all the requested meters - if db.diskSizeGauge != nil { - db.diskSizeGauge.Update(compactions[i%2][0]) - } - if db.compTimeMeter != nil { - db.compTimeMeter.Mark(compactions[i%2][1] - compactions[(i-1)%2][1]) - } - if db.compReadMeter != nil { - db.compReadMeter.Mark(compactions[i%2][2] - compactions[(i-1)%2][2]) - } - if db.compWriteMeter != nil { - db.compWriteMeter.Mark(compactions[i%2][3] - compactions[(i-1)%2][3]) - } - var ( - delayN = int64(stats.WriteDelayCount) - duration = stats.WriteDelayDuration - paused = stats.WritePaused - ) - if db.writeDelayNMeter != nil { - db.writeDelayNMeter.Mark(delayN - delaystats[0]) - } - if db.writeDelayMeter != nil { - db.writeDelayMeter.Mark(duration.Nanoseconds() - delaystats[1]) - } - // If a warning that db is performing compaction has been displayed, any subsequent - // warnings will be withheld for one minute not to overwhelm the user. - if paused && delayN-delaystats[0] == 0 && duration.Nanoseconds()-delaystats[1] == 0 && - time.Now().After(lastWritePaused.Add(degradationWarnInterval)) { - db.log.Warn("Database compacting, degraded performance") - lastWritePaused = time.Now() - } - delaystats[0], delaystats[1] = delayN, duration.Nanoseconds() - - var ( - nRead = int64(stats.IORead) - nWrite = int64(stats.IOWrite) - ) - if db.diskReadMeter != nil { - db.diskReadMeter.Mark(nRead - iostats[0]) - } - if db.diskWriteMeter != nil { - db.diskWriteMeter.Mark(nWrite - iostats[1]) - } - iostats[0], iostats[1] = nRead, nWrite - - db.memCompGauge.Update(int64(stats.MemComp)) - db.level0CompGauge.Update(int64(stats.Level0Comp)) - db.nonlevel0CompGauge.Update(int64(stats.NonLevel0Comp)) - db.seekCompGauge.Update(int64(stats.SeekComp)) - - for i, tables := range stats.LevelTablesCounts { - // Append metrics for additional layers - if i >= len(db.levelsGauge) { - db.levelsGauge = append(db.levelsGauge, metrics.NewRegisteredGauge(namespace+fmt.Sprintf("tables/level%v", i), nil)) - } - db.levelsGauge[i].Update(int64(tables)) - } - - // Sleep a bit, then repeat the stats collection - select { - case errc = <-db.quitChan: - // Quit requesting, stop hammering the database - case <-timer.C: - timer.Reset(refresh) - // Timeout, gather a new set of stats - } - } - - if errc == nil { - errc = <-db.quitChan - } - errc <- merr -} - -// batch is a write-only leveldb batch that commits changes to its host database -// when Write is called. A batch cannot be used concurrently. -type batch struct { - db *leveldb.DB - b *leveldb.Batch - size int -} - -// Put inserts the given value into the batch for later committing. -func (b *batch) Put(key, value []byte) error { - b.b.Put(key, value) - b.size += len(key) + len(value) - return nil -} - -// Delete inserts the a key removal into the batch for later committing. -func (b *batch) Delete(key []byte) error { - b.b.Delete(key) - b.size += len(key) - return nil -} - -// ValueSize retrieves the amount of data queued up for writing. -func (b *batch) ValueSize() int { - return b.size -} - -// Write flushes any accumulated data to disk. -func (b *batch) Write() error { - return b.db.Write(b.b, nil) -} - -// Reset resets the batch for reuse. -func (b *batch) Reset() { - b.b.Reset() - b.size = 0 -} - -// Replay replays the batch contents. -func (b *batch) Replay(w ethdb.KeyValueWriter) error { - return b.b.Replay(&replayer{writer: w}) -} - -// replayer is a small wrapper to implement the correct replay methods. -type replayer struct { - writer ethdb.KeyValueWriter - failure error -} - -// Put inserts the given value into the key-value data store. -func (r *replayer) Put(key, value []byte) { - // If the replay already failed, stop executing ops - if r.failure != nil { - return - } - r.failure = r.writer.Put(key, value) -} - -// Delete removes the key from the key-value data store. -func (r *replayer) Delete(key []byte) { - // If the replay already failed, stop executing ops - if r.failure != nil { - return - } - r.failure = r.writer.Delete(key) -} - -// bytesPrefixRange returns key range that satisfy -// - the given prefix, and -// - the given seek position -func bytesPrefixRange(prefix, start []byte) *util.Range { - r := util.BytesPrefix(prefix) - r.Start = append(r.Start, start...) - return r -} - -// snapshot wraps a leveldb snapshot for implementing the Snapshot interface. -type snapshot struct { - db *leveldb.Snapshot -} - -// Has retrieves if a key is present in the snapshot backing by a key-value -// data store. -func (snap *snapshot) Has(key []byte) (bool, error) { - return snap.db.Has(key, nil) -} - -// Get retrieves the given key if it's present in the snapshot backing by -// key-value data store. -func (snap *snapshot) Get(key []byte) ([]byte, error) { - return snap.db.Get(key, nil) -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (snap *snapshot) Release() { - snap.db.Release() -} diff --git a/builder/ethdb/leveldb/leveldb_test.go b/builder/ethdb/leveldb/leveldb_test.go deleted file mode 100644 index d8c638601..000000000 --- a/builder/ethdb/leveldb/leveldb_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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 leveldb - -import ( - "testing" - - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/dbtest" - "github.com/syndtr/goleveldb/leveldb" - "github.com/syndtr/goleveldb/leveldb/storage" -) - -func TestLevelDB(t *testing.T) { - t.Run("DatabaseSuite", func(t *testing.T) { - dbtest.TestDatabaseSuite(t, func() ethdb.KeyValueStore { - db, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - t.Fatal(err) - } - return &Database{ - db: db, - } - }) - }) -} - -func BenchmarkLevelDB(b *testing.B) { - dbtest.BenchDatabaseSuite(b, func() ethdb.KeyValueStore { - db, err := leveldb.Open(storage.NewMemStorage(), nil) - if err != nil { - b.Fatal(err) - } - return &Database{ - db: db, - } - }) -} diff --git a/builder/ethdb/memorydb/memorydb.go b/builder/ethdb/memorydb/memorydb.go deleted file mode 100644 index 2a939f9a1..000000000 --- a/builder/ethdb/memorydb/memorydb.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2018 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 memorydb implements the key-value database layer based on memory maps. -package memorydb - -import ( - "errors" - "sort" - "strings" - "sync" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" -) - -var ( - // errMemorydbClosed is returned if a memory database was already closed at the - // invocation of a data access operation. - errMemorydbClosed = errors.New("database closed") - - // errMemorydbNotFound is returned if a key is requested that is not found in - // the provided memory database. - errMemorydbNotFound = errors.New("not found") - - // errSnapshotReleased is returned if callers want to retrieve data from a - // released snapshot. - errSnapshotReleased = errors.New("snapshot released") -) - -// Database is an ephemeral key-value store. Apart from basic data storage -// functionality it also supports batch writes and iterating over the keyspace in -// binary-alphabetical order. -type Database struct { - db map[string][]byte - lock sync.RWMutex -} - -// New returns a wrapped map with all the required database interface methods -// implemented. -func New() *Database { - return &Database{ - db: make(map[string][]byte), - } -} - -// NewWithCap returns a wrapped map pre-allocated to the provided capacity with -// all the required database interface methods implemented. -func NewWithCap(size int) *Database { - return &Database{ - db: make(map[string][]byte, size), - } -} - -// Close deallocates the internal map and ensures any consecutive data access op -// fails with an error. -func (db *Database) Close() error { - db.lock.Lock() - defer db.lock.Unlock() - - db.db = nil - return nil -} - -// Has retrieves if a key is present in the key-value store. -func (db *Database) Has(key []byte) (bool, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - if db.db == nil { - return false, errMemorydbClosed - } - _, ok := db.db[string(key)] - return ok, nil -} - -// Get retrieves the given key if it's present in the key-value store. -func (db *Database) Get(key []byte) ([]byte, error) { - db.lock.RLock() - defer db.lock.RUnlock() - - if db.db == nil { - return nil, errMemorydbClosed - } - if entry, ok := db.db[string(key)]; ok { - return common.CopyBytes(entry), nil - } - return nil, errMemorydbNotFound -} - -// Put inserts the given value into the key-value store. -func (db *Database) Put(key []byte, value []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - if db.db == nil { - return errMemorydbClosed - } - db.db[string(key)] = common.CopyBytes(value) - return nil -} - -// Delete removes the key from the key-value store. -func (db *Database) Delete(key []byte) error { - db.lock.Lock() - defer db.lock.Unlock() - - if db.db == nil { - return errMemorydbClosed - } - delete(db.db, string(key)) - return nil -} - -// NewBatch creates a write-only key-value store that buffers changes to its host -// database until a final write is called. -func (db *Database) NewBatch() ethdb.Batch { - return &batch{ - db: db, - } -} - -// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -func (db *Database) NewBatchWithSize(size int) ethdb.Batch { - return &batch{ - db: db, - } -} - -// NewIterator creates a binary-alphabetical iterator over a subset -// of database content with a particular key prefix, starting at a particular -// initial key (or after, if it does not exist). -func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - db.lock.RLock() - defer db.lock.RUnlock() - - var ( - pr = string(prefix) - st = string(append(prefix, start...)) - keys = make([]string, 0, len(db.db)) - values = make([][]byte, 0, len(db.db)) - ) - // Collect the keys from the memory database corresponding to the given prefix - // and start - for key := range db.db { - if !strings.HasPrefix(key, pr) { - continue - } - if key >= st { - keys = append(keys, key) - } - } - // Sort the items and retrieve the associated values - sort.Strings(keys) - for _, key := range keys { - values = append(values, db.db[key]) - } - return &iterator{ - index: -1, - keys: keys, - values: values, - } -} - -// NewSnapshot creates a database snapshot based on the current state. -// The created snapshot will not be affected by all following mutations -// happened on the database. -func (db *Database) NewSnapshot() (ethdb.Snapshot, error) { - return newSnapshot(db), nil -} - -// Stat returns a particular internal stat of the database. -func (db *Database) Stat(property string) (string, error) { - return "", errors.New("unknown property") -} - -// Compact is not supported on a memory database, but there's no need either as -// a memory database doesn't waste space anyway. -func (db *Database) Compact(start []byte, limit []byte) error { - return nil -} - -// Len returns the number of entries currently present in the memory database. -// -// Note, this method is only used for testing (i.e. not public in general) and -// does not have explicit checks for closed-ness to allow simpler testing code. -func (db *Database) Len() int { - db.lock.RLock() - defer db.lock.RUnlock() - - return len(db.db) -} - -// keyvalue is a key-value tuple tagged with a deletion field to allow creating -// memory-database write batches. -type keyvalue struct { - key string - value []byte - delete bool -} - -// batch is a write-only memory batch that commits changes to its host -// database when Write is called. A batch cannot be used concurrently. -type batch struct { - db *Database - writes []keyvalue - size int -} - -// Put inserts the given value into the batch for later committing. -func (b *batch) Put(key, value []byte) error { - b.writes = append(b.writes, keyvalue{string(key), common.CopyBytes(value), false}) - b.size += len(key) + len(value) - return nil -} - -// Delete inserts the a key removal into the batch for later committing. -func (b *batch) Delete(key []byte) error { - b.writes = append(b.writes, keyvalue{string(key), nil, true}) - b.size += len(key) - return nil -} - -// ValueSize retrieves the amount of data queued up for writing. -func (b *batch) ValueSize() int { - return b.size -} - -// Write flushes any accumulated data to the memory database. -func (b *batch) Write() error { - b.db.lock.Lock() - defer b.db.lock.Unlock() - - if b.db.db == nil { - return errMemorydbClosed - } - for _, keyvalue := range b.writes { - if keyvalue.delete { - delete(b.db.db, keyvalue.key) - continue - } - b.db.db[keyvalue.key] = keyvalue.value - } - return nil -} - -// Reset resets the batch for reuse. -func (b *batch) Reset() { - b.writes = b.writes[:0] - b.size = 0 -} - -// Replay replays the batch contents. -func (b *batch) Replay(w ethdb.KeyValueWriter) error { - for _, keyvalue := range b.writes { - if keyvalue.delete { - if err := w.Delete([]byte(keyvalue.key)); err != nil { - return err - } - continue - } - if err := w.Put([]byte(keyvalue.key), keyvalue.value); err != nil { - return err - } - } - return nil -} - -// iterator can walk over the (potentially partial) keyspace of a memory key -// value store. Internally it is a deep copy of the entire iterated state, -// sorted by keys. -type iterator struct { - index int - keys []string - values [][]byte -} - -// Next moves the iterator to the next key/value pair. It returns whether the -// iterator is exhausted. -func (it *iterator) Next() bool { - // Short circuit if iterator is already exhausted in the forward direction. - if it.index >= len(it.keys) { - return false - } - it.index += 1 - return it.index < len(it.keys) -} - -// Error returns any accumulated error. Exhausting all the key/value pairs -// is not considered to be an error. A memory iterator cannot encounter errors. -func (it *iterator) Error() error { - return nil -} - -// Key returns the key of the current key/value pair, or nil if done. The caller -// should not modify the contents of the returned slice, and its contents may -// change on the next call to Next. -func (it *iterator) Key() []byte { - // Short circuit if iterator is not in a valid position - if it.index < 0 || it.index >= len(it.keys) { - return nil - } - return []byte(it.keys[it.index]) -} - -// Value returns the value of the current key/value pair, or nil if done. The -// caller should not modify the contents of the returned slice, and its contents -// may change on the next call to Next. -func (it *iterator) Value() []byte { - // Short circuit if iterator is not in a valid position - if it.index < 0 || it.index >= len(it.keys) { - return nil - } - return it.values[it.index] -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (it *iterator) Release() { - it.index, it.keys, it.values = -1, nil, nil -} - -// snapshot wraps a batch of key-value entries deep copied from the in-memory -// database for implementing the Snapshot interface. -type snapshot struct { - db map[string][]byte - lock sync.RWMutex -} - -// newSnapshot initializes the snapshot with the given database instance. -func newSnapshot(db *Database) *snapshot { - db.lock.RLock() - defer db.lock.RUnlock() - - copied := make(map[string][]byte, len(db.db)) - for key, val := range db.db { - copied[key] = common.CopyBytes(val) - } - return &snapshot{db: copied} -} - -// Has retrieves if a key is present in the snapshot backing by a key-value -// data store. -func (snap *snapshot) Has(key []byte) (bool, error) { - snap.lock.RLock() - defer snap.lock.RUnlock() - - if snap.db == nil { - return false, errSnapshotReleased - } - _, ok := snap.db[string(key)] - return ok, nil -} - -// Get retrieves the given key if it's present in the snapshot backing by -// key-value data store. -func (snap *snapshot) Get(key []byte) ([]byte, error) { - snap.lock.RLock() - defer snap.lock.RUnlock() - - if snap.db == nil { - return nil, errSnapshotReleased - } - if entry, ok := snap.db[string(key)]; ok { - return common.CopyBytes(entry), nil - } - return nil, errMemorydbNotFound -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (snap *snapshot) Release() { - snap.lock.Lock() - defer snap.lock.Unlock() - - snap.db = nil -} diff --git a/builder/ethdb/memorydb/memorydb_test.go b/builder/ethdb/memorydb/memorydb_test.go deleted file mode 100644 index 51499c3b1..000000000 --- a/builder/ethdb/memorydb/memorydb_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2018 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 memorydb - -import ( - "encoding/binary" - "testing" - - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/dbtest" -) - -func TestMemoryDB(t *testing.T) { - t.Run("DatabaseSuite", func(t *testing.T) { - dbtest.TestDatabaseSuite(t, func() ethdb.KeyValueStore { - return New() - }) - }) -} - -// BenchmarkBatchAllocs measures the time/allocs for storing 120 kB of data -func BenchmarkBatchAllocs(b *testing.B) { - b.ReportAllocs() - var key = make([]byte, 20) - var val = make([]byte, 100) - // 120 * 1_000 -> 120_000 == 120kB - for i := 0; i < b.N; i++ { - batch := New().NewBatch() - for j := uint64(0); j < 1000; j++ { - binary.BigEndian.PutUint64(key, j) - binary.BigEndian.PutUint64(val, j) - batch.Put(key, val) - } - batch.Write() - } -} diff --git a/builder/ethdb/pebble/pebble.go b/builder/ethdb/pebble/pebble.go deleted file mode 100644 index af4686cf5..000000000 --- a/builder/ethdb/pebble/pebble.go +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright 2023 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 pebble implements the key-value database layer based on pebble. -package pebble - -import ( - "bytes" - "fmt" - "runtime" - "sync" - "sync/atomic" - "time" - - "github.com/cockroachdb/pebble" - "github.com/cockroachdb/pebble/bloom" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/metrics" -) - -const ( - // minCache is the minimum amount of memory in megabytes to allocate to pebble - // read and write caching, split half and half. - minCache = 16 - - // minHandles is the minimum number of files handles to allocate to the open - // database files. - minHandles = 16 - - // metricsGatheringInterval specifies the interval to retrieve pebble database - // compaction, io and pause stats to report to the user. - metricsGatheringInterval = 3 * time.Second -) - -// Database is a persistent key-value store based on the pebble storage engine. -// Apart from basic data storage functionality it also supports batch writes and -// iterating over the keyspace in binary-alphabetical order. -type Database struct { - fn string // filename for reporting - db *pebble.DB // Underlying pebble storage engine - - compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction - compReadMeter metrics.Meter // Meter for measuring the data read during compaction - compWriteMeter metrics.Meter // Meter for measuring the data written during compaction - writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction - writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction - diskSizeGauge metrics.Gauge // Gauge for tracking the size of all the levels in the database - diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read - diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written - memCompGauge metrics.Gauge // Gauge for tracking the number of memory compaction - level0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in level0 - nonlevel0CompGauge metrics.Gauge // Gauge for tracking the number of table compaction in non0 level - seekCompGauge metrics.Gauge // Gauge for tracking the number of table compaction caused by read opt - manualMemAllocGauge metrics.Gauge // Gauge for tracking amount of non-managed memory currently allocated - - levelsGauge []metrics.Gauge // Gauge for tracking the number of tables in levels - - quitLock sync.RWMutex // Mutex protecting the quit channel and the closed flag - quitChan chan chan error // Quit channel to stop the metrics collection before closing the database - closed bool // keep track of whether we're Closed - - log log.Logger // Contextual logger tracking the database path - - activeComp int // Current number of active compactions - compStartTime time.Time // The start time of the earliest currently-active compaction - compTime atomic.Int64 // Total time spent in compaction in ns - level0Comp atomic.Uint32 // Total number of level-zero compactions - nonLevel0Comp atomic.Uint32 // Total number of non level-zero compactions - writeDelayStartTime time.Time // The start time of the latest write stall - writeDelayCount atomic.Int64 // Total number of write stall counts - writeDelayTime atomic.Int64 // Total time spent in write stalls - - writeOptions *pebble.WriteOptions -} - -func (d *Database) onCompactionBegin(info pebble.CompactionInfo) { - if d.activeComp == 0 { - d.compStartTime = time.Now() - } - l0 := info.Input[0] - if l0.Level == 0 { - d.level0Comp.Add(1) - } else { - d.nonLevel0Comp.Add(1) - } - d.activeComp++ -} - -func (d *Database) onCompactionEnd(info pebble.CompactionInfo) { - if d.activeComp == 1 { - d.compTime.Add(int64(time.Since(d.compStartTime))) - } else if d.activeComp == 0 { - panic("should not happen") - } - d.activeComp-- -} - -func (d *Database) onWriteStallBegin(b pebble.WriteStallBeginInfo) { - d.writeDelayStartTime = time.Now() -} - -func (d *Database) onWriteStallEnd() { - d.writeDelayTime.Add(int64(time.Since(d.writeDelayStartTime))) -} - -// panicLogger is just a noop logger to disable Pebble's internal logger. -// -// TODO(karalabe): Remove when Pebble sets this as the default. -type panicLogger struct{} - -func (l panicLogger) Infof(format string, args ...interface{}) { -} - -func (l panicLogger) Errorf(format string, args ...interface{}) { -} - -func (l panicLogger) Fatalf(format string, args ...interface{}) { - panic(fmt.Errorf("fatal: "+format, args...)) -} - -// New returns a wrapped pebble DB object. The namespace is the prefix that the -// metrics reporting should use for surfacing internal stats. -func New(file string, cache int, handles int, namespace string, readonly bool, ephemeral bool) (*Database, error) { - // Ensure we have some minimal caching and file guarantees - if cache < minCache { - cache = minCache - } - if handles < minHandles { - handles = minHandles - } - logger := log.New("database", file) - logger.Info("Allocated cache and file handles", "cache", common.StorageSize(cache*1024*1024), "handles", handles) - - // The max memtable size is limited by the uint32 offsets stored in - // internal/arenaskl.node, DeferredBatchOp, and flushableBatchEntry. - // - // - MaxUint32 on 64-bit platforms; - // - MaxInt on 32-bit platforms. - // - // It is used when slices are limited to Uint32 on 64-bit platforms (the - // length limit for slices is naturally MaxInt on 32-bit platforms). - // - // Taken from https://github.com/cockroachdb/pebble/blob/master/internal/constants/constants.go - maxMemTableSize := (1<<31)<<(^uint(0)>>63) - 1 - - // Two memory tables is configured which is identical to leveldb, - // including a frozen memory table and another live one. - memTableLimit := 2 - memTableSize := cache * 1024 * 1024 / 2 / memTableLimit - - // The memory table size is currently capped at maxMemTableSize-1 due to a - // known bug in the pebble where maxMemTableSize is not recognized as a - // valid size. - // - // TODO use the maxMemTableSize as the maximum table size once the issue - // in pebble is fixed. - if memTableSize >= maxMemTableSize { - memTableSize = maxMemTableSize - 1 - } - db := &Database{ - fn: file, - log: logger, - quitChan: make(chan chan error), - writeOptions: &pebble.WriteOptions{Sync: !ephemeral}, - } - opt := &pebble.Options{ - // Pebble has a single combined cache area and the write - // buffers are taken from this too. Assign all available - // memory allowance for cache. - Cache: pebble.NewCache(int64(cache * 1024 * 1024)), - MaxOpenFiles: handles, - - // The size of memory table(as well as the write buffer). - // Note, there may have more than two memory tables in the system. - MemTableSize: uint64(memTableSize), - - // MemTableStopWritesThreshold places a hard limit on the size - // of the existent MemTables(including the frozen one). - // Note, this must be the number of tables not the size of all memtables - // according to https://github.com/cockroachdb/pebble/blob/master/options.go#L738-L742 - // and to https://github.com/cockroachdb/pebble/blob/master/db.go#L1892-L1903. - MemTableStopWritesThreshold: memTableLimit, - - // The default compaction concurrency(1 thread), - // Here use all available CPUs for faster compaction. - MaxConcurrentCompactions: func() int { return runtime.NumCPU() }, - - // Per-level options. Options for at least one level must be specified. The - // options for the last level are used for all subsequent levels. - Levels: []pebble.LevelOptions{ - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - {TargetFileSize: 2 * 1024 * 1024, FilterPolicy: bloom.FilterPolicy(10)}, - }, - ReadOnly: readonly, - EventListener: &pebble.EventListener{ - CompactionBegin: db.onCompactionBegin, - CompactionEnd: db.onCompactionEnd, - WriteStallBegin: db.onWriteStallBegin, - WriteStallEnd: db.onWriteStallEnd, - }, - Logger: panicLogger{}, // TODO(karalabe): Delete when this is upstreamed in Pebble - } - // Disable seek compaction explicitly. Check https://github.com/ethereum/go-ethereum/pull/20130 - // for more details. - opt.Experimental.ReadSamplingMultiplier = -1 - - // Open the db and recover any potential corruptions - innerDB, err := pebble.Open(file, opt) - if err != nil { - return nil, err - } - db.db = innerDB - - db.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil) - db.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil) - db.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil) - db.diskSizeGauge = metrics.NewRegisteredGauge(namespace+"disk/size", nil) - db.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil) - db.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil) - db.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil) - db.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil) - db.memCompGauge = metrics.NewRegisteredGauge(namespace+"compact/memory", nil) - db.level0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/level0", nil) - db.nonlevel0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/nonlevel0", nil) - db.seekCompGauge = metrics.NewRegisteredGauge(namespace+"compact/seek", nil) - db.manualMemAllocGauge = metrics.NewRegisteredGauge(namespace+"memory/manualalloc", nil) - - // Start up the metrics gathering and return - go db.meter(metricsGatheringInterval, namespace) - return db, nil -} - -// Close stops the metrics collection, flushes any pending data to disk and closes -// all io accesses to the underlying key-value store. -func (d *Database) Close() error { - d.quitLock.Lock() - defer d.quitLock.Unlock() - // Allow double closing, simplifies things - if d.closed { - return nil - } - d.closed = true - if d.quitChan != nil { - errc := make(chan error) - d.quitChan <- errc - if err := <-errc; err != nil { - d.log.Error("Metrics collection failed", "err", err) - } - d.quitChan = nil - } - return d.db.Close() -} - -// Has retrieves if a key is present in the key-value store. -func (d *Database) Has(key []byte) (bool, error) { - d.quitLock.RLock() - defer d.quitLock.RUnlock() - if d.closed { - return false, pebble.ErrClosed - } - _, closer, err := d.db.Get(key) - if err == pebble.ErrNotFound { - return false, nil - } else if err != nil { - return false, err - } - closer.Close() - return true, nil -} - -// Get retrieves the given key if it's present in the key-value store. -func (d *Database) Get(key []byte) ([]byte, error) { - d.quitLock.RLock() - defer d.quitLock.RUnlock() - if d.closed { - return nil, pebble.ErrClosed - } - dat, closer, err := d.db.Get(key) - if err != nil { - return nil, err - } - ret := make([]byte, len(dat)) - copy(ret, dat) - closer.Close() - return ret, nil -} - -// Put inserts the given value into the key-value store. -func (d *Database) Put(key []byte, value []byte) error { - d.quitLock.RLock() - defer d.quitLock.RUnlock() - if d.closed { - return pebble.ErrClosed - } - return d.db.Set(key, value, d.writeOptions) -} - -// Delete removes the key from the key-value store. -func (d *Database) Delete(key []byte) error { - d.quitLock.RLock() - defer d.quitLock.RUnlock() - if d.closed { - return pebble.ErrClosed - } - return d.db.Delete(key, nil) -} - -// NewBatch creates a write-only key-value store that buffers changes to its host -// database until a final write is called. -func (d *Database) NewBatch() ethdb.Batch { - return &batch{ - b: d.db.NewBatch(), - db: d, - } -} - -// NewBatchWithSize creates a write-only database batch with pre-allocated buffer. -func (d *Database) NewBatchWithSize(size int) ethdb.Batch { - return &batch{ - b: d.db.NewBatchWithSize(size), - db: d, - } -} - -// snapshot wraps a pebble snapshot for implementing the Snapshot interface. -type snapshot struct { - db *pebble.Snapshot -} - -// NewSnapshot creates a database snapshot based on the current state. -// The created snapshot will not be affected by all following mutations -// happened on the database. -// Note don't forget to release the snapshot once it's used up, otherwise -// the stale data will never be cleaned up by the underlying compactor. -func (d *Database) NewSnapshot() (ethdb.Snapshot, error) { - snap := d.db.NewSnapshot() - return &snapshot{db: snap}, nil -} - -// Has retrieves if a key is present in the snapshot backing by a key-value -// data store. -func (snap *snapshot) Has(key []byte) (bool, error) { - _, closer, err := snap.db.Get(key) - if err != nil { - if err != pebble.ErrNotFound { - return false, err - } else { - return false, nil - } - } - closer.Close() - return true, nil -} - -// Get retrieves the given key if it's present in the snapshot backing by -// key-value data store. -func (snap *snapshot) Get(key []byte) ([]byte, error) { - dat, closer, err := snap.db.Get(key) - if err != nil { - return nil, err - } - ret := make([]byte, len(dat)) - copy(ret, dat) - closer.Close() - return ret, nil -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (snap *snapshot) Release() { - snap.db.Close() -} - -// upperBound returns the upper bound for the given prefix -func upperBound(prefix []byte) (limit []byte) { - for i := len(prefix) - 1; i >= 0; i-- { - c := prefix[i] - if c == 0xff { - continue - } - limit = make([]byte, i+1) - copy(limit, prefix) - limit[i] = c + 1 - break - } - return limit -} - -// Stat returns the internal metrics of Pebble in a text format. It's a developer -// method to read everything there is to read independent of Pebble version. -// -// The property is unused in Pebble as there's only one thing to retrieve. -func (d *Database) Stat(property string) (string, error) { - return d.db.Metrics().String(), nil -} - -// Compact flattens the underlying data store for the given key range. In essence, -// deleted and overwritten versions are discarded, and the data is rearranged to -// reduce the cost of operations needed to access them. -// -// A nil start is treated as a key before all keys in the data store; a nil limit -// is treated as a key after all keys in the data store. If both is nil then it -// will compact entire data store. -func (d *Database) Compact(start []byte, limit []byte) error { - // There is no special flag to represent the end of key range - // in pebble(nil in leveldb). Use an ugly hack to construct a - // large key to represent it. - // Note any prefixed database entry will be smaller than this - // flag, as for trie nodes we need the 32 byte 0xff because - // there might be a shared prefix starting with a number of - // 0xff-s, so 32 ensures than only a hash collision could touch it. - // https://github.com/cockroachdb/pebble/issues/2359#issuecomment-1443995833 - if limit == nil { - limit = bytes.Repeat([]byte{0xff}, 32) - } - return d.db.Compact(start, limit, true) // Parallelization is preferred -} - -// Path returns the path to the database directory. -func (d *Database) Path() string { - return d.fn -} - -// meter periodically retrieves internal pebble counters and reports them to -// the metrics subsystem. -func (d *Database) meter(refresh time.Duration, namespace string) { - var errc chan error - timer := time.NewTimer(refresh) - defer timer.Stop() - - // Create storage and warning log tracer for write delay. - var ( - compTimes [2]int64 - writeDelayTimes [2]int64 - writeDelayCounts [2]int64 - compWrites [2]int64 - compReads [2]int64 - - nWrites [2]int64 - ) - - // Iterate ad infinitum and collect the stats - for i := 1; errc == nil; i++ { - var ( - compWrite int64 - compRead int64 - nWrite int64 - - stats = d.db.Metrics() - compTime = d.compTime.Load() - writeDelayCount = d.writeDelayCount.Load() - writeDelayTime = d.writeDelayTime.Load() - nonLevel0CompCount = int64(d.nonLevel0Comp.Load()) - level0CompCount = int64(d.level0Comp.Load()) - ) - writeDelayTimes[i%2] = writeDelayTime - writeDelayCounts[i%2] = writeDelayCount - compTimes[i%2] = compTime - - for _, levelMetrics := range stats.Levels { - nWrite += int64(levelMetrics.BytesCompacted) - nWrite += int64(levelMetrics.BytesFlushed) - compWrite += int64(levelMetrics.BytesCompacted) - compRead += int64(levelMetrics.BytesRead) - } - - nWrite += int64(stats.WAL.BytesWritten) - - compWrites[i%2] = compWrite - compReads[i%2] = compRead - nWrites[i%2] = nWrite - - if d.writeDelayNMeter != nil { - d.writeDelayNMeter.Mark(writeDelayCounts[i%2] - writeDelayCounts[(i-1)%2]) - } - if d.writeDelayMeter != nil { - d.writeDelayMeter.Mark(writeDelayTimes[i%2] - writeDelayTimes[(i-1)%2]) - } - if d.compTimeMeter != nil { - d.compTimeMeter.Mark(compTimes[i%2] - compTimes[(i-1)%2]) - } - if d.compReadMeter != nil { - d.compReadMeter.Mark(compReads[i%2] - compReads[(i-1)%2]) - } - if d.compWriteMeter != nil { - d.compWriteMeter.Mark(compWrites[i%2] - compWrites[(i-1)%2]) - } - if d.diskSizeGauge != nil { - d.diskSizeGauge.Update(int64(stats.DiskSpaceUsage())) - } - if d.diskReadMeter != nil { - d.diskReadMeter.Mark(0) // pebble doesn't track non-compaction reads - } - if d.diskWriteMeter != nil { - d.diskWriteMeter.Mark(nWrites[i%2] - nWrites[(i-1)%2]) - } - // See https://github.com/cockroachdb/pebble/pull/1628#pullrequestreview-1026664054 - manuallyAllocated := stats.BlockCache.Size + int64(stats.MemTable.Size) + int64(stats.MemTable.ZombieSize) - d.manualMemAllocGauge.Update(manuallyAllocated) - d.memCompGauge.Update(stats.Flush.Count) - d.nonlevel0CompGauge.Update(nonLevel0CompCount) - d.level0CompGauge.Update(level0CompCount) - d.seekCompGauge.Update(stats.Compact.ReadCount) - - for i, level := range stats.Levels { - // Append metrics for additional layers - if i >= len(d.levelsGauge) { - d.levelsGauge = append(d.levelsGauge, metrics.NewRegisteredGauge(namespace+fmt.Sprintf("tables/level%v", i), nil)) - } - d.levelsGauge[i].Update(level.NumFiles) - } - - // Sleep a bit, then repeat the stats collection - select { - case errc = <-d.quitChan: - // Quit requesting, stop hammering the database - case <-timer.C: - timer.Reset(refresh) - // Timeout, gather a new set of stats - } - } - errc <- nil -} - -// batch is a write-only batch that commits changes to its host database -// when Write is called. A batch cannot be used concurrently. -type batch struct { - b *pebble.Batch - db *Database - size int -} - -// Put inserts the given value into the batch for later committing. -func (b *batch) Put(key, value []byte) error { - b.b.Set(key, value, nil) - b.size += len(key) + len(value) - return nil -} - -// Delete inserts the a key removal into the batch for later committing. -func (b *batch) Delete(key []byte) error { - b.b.Delete(key, nil) - b.size += len(key) - return nil -} - -// ValueSize retrieves the amount of data queued up for writing. -func (b *batch) ValueSize() int { - return b.size -} - -// Write flushes any accumulated data to disk. -func (b *batch) Write() error { - b.db.quitLock.RLock() - defer b.db.quitLock.RUnlock() - if b.db.closed { - return pebble.ErrClosed - } - return b.b.Commit(b.db.writeOptions) -} - -// Reset resets the batch for reuse. -func (b *batch) Reset() { - b.b.Reset() - b.size = 0 -} - -// Replay replays the batch contents. -func (b *batch) Replay(w ethdb.KeyValueWriter) error { - reader := b.b.Reader() - for { - kind, k, v, ok := reader.Next() - if !ok { - break - } - // The (k,v) slices might be overwritten if the batch is reset/reused, - // and the receiver should copy them if they are to be retained long-term. - if kind == pebble.InternalKeyKindSet { - w.Put(k, v) - } else if kind == pebble.InternalKeyKindDelete { - w.Delete(k) - } else { - return fmt.Errorf("unhandled operation, keytype: %v", kind) - } - } - return nil -} - -// pebbleIterator is a wrapper of underlying iterator in storage engine. -// The purpose of this structure is to implement the missing APIs. -// -// The pebble iterator is not thread-safe. -type pebbleIterator struct { - iter *pebble.Iterator - moved bool - released bool -} - -// NewIterator creates a binary-alphabetical iterator over a subset -// of database content with a particular key prefix, starting at a particular -// initial key (or after, if it does not exist). -func (d *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - iter, _ := d.db.NewIter(&pebble.IterOptions{ - LowerBound: append(prefix, start...), - UpperBound: upperBound(prefix), - }) - iter.First() - return &pebbleIterator{iter: iter, moved: true, released: false} -} - -// Next moves the iterator to the next key/value pair. It returns whether the -// iterator is exhausted. -func (iter *pebbleIterator) Next() bool { - if iter.moved { - iter.moved = false - return iter.iter.Valid() - } - return iter.iter.Next() -} - -// Error returns any accumulated error. Exhausting all the key/value pairs -// is not considered to be an error. -func (iter *pebbleIterator) Error() error { - return iter.iter.Error() -} - -// Key returns the key of the current key/value pair, or nil if done. The caller -// should not modify the contents of the returned slice, and its contents may -// change on the next call to Next. -func (iter *pebbleIterator) Key() []byte { - return iter.iter.Key() -} - -// Value returns the value of the current key/value pair, or nil if done. The -// caller should not modify the contents of the returned slice, and its contents -// may change on the next call to Next. -func (iter *pebbleIterator) Value() []byte { - return iter.iter.Value() -} - -// Release releases associated resources. Release should always succeed and can -// be called multiple times without causing error. -func (iter *pebbleIterator) Release() { - if !iter.released { - iter.iter.Close() - iter.released = true - } -} diff --git a/builder/ethdb/pebble/pebble_test.go b/builder/ethdb/pebble/pebble_test.go deleted file mode 100644 index 1d5611f21..000000000 --- a/builder/ethdb/pebble/pebble_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2023 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 pebble - -import ( - "testing" - - "github.com/cockroachdb/pebble" - "github.com/cockroachdb/pebble/vfs" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/dbtest" -) - -func TestPebbleDB(t *testing.T) { - t.Run("DatabaseSuite", func(t *testing.T) { - dbtest.TestDatabaseSuite(t, func() ethdb.KeyValueStore { - db, err := pebble.Open("", &pebble.Options{ - FS: vfs.NewMem(), - }) - if err != nil { - t.Fatal(err) - } - return &Database{ - db: db, - } - }) - }) -} - -func BenchmarkPebbleDB(b *testing.B) { - dbtest.BenchDatabaseSuite(b, func() ethdb.KeyValueStore { - db, err := pebble.Open("", &pebble.Options{ - FS: vfs.NewMem(), - }) - if err != nil { - b.Fatal(err) - } - return &Database{ - db: db, - } - }) -} diff --git a/builder/ethdb/remotedb/remotedb.go b/builder/ethdb/remotedb/remotedb.go deleted file mode 100644 index c1c803caf..000000000 --- a/builder/ethdb/remotedb/remotedb.go +++ /dev/null @@ -1,154 +0,0 @@ -// 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 remotedb implements the key-value database layer based on a remote geth -// node. Under the hood, it utilises the `debug_dbGet` method to implement a -// read-only database. -// There really are no guarantees in this database, since the local geth does not -// exclusive access, but it can be used for basic diagnostics of a remote node. -package remotedb - -import ( - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rpc" -) - -// Database is a key-value lookup for a remote database via debug_dbGet. -type Database struct { - remote *rpc.Client -} - -func (db *Database) Has(key []byte) (bool, error) { - if _, err := db.Get(key); err != nil { - return false, nil - } - return true, nil -} - -func (db *Database) Get(key []byte) ([]byte, error) { - var resp hexutil.Bytes - err := db.remote.Call(&resp, "debug_dbGet", hexutil.Bytes(key)) - if err != nil { - return nil, err - } - return resp, nil -} - -func (db *Database) HasAncient(kind string, number uint64) (bool, error) { - if _, err := db.Ancient(kind, number); err != nil { - return false, nil - } - return true, nil -} - -func (db *Database) Ancient(kind string, number uint64) ([]byte, error) { - var resp hexutil.Bytes - err := db.remote.Call(&resp, "debug_dbAncient", kind, number) - if err != nil { - return nil, err - } - return resp, nil -} - -func (db *Database) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { - panic("not supported") -} - -func (db *Database) Ancients() (uint64, error) { - var resp uint64 - err := db.remote.Call(&resp, "debug_dbAncients") - return resp, err -} - -func (db *Database) Tail() (uint64, error) { - panic("not supported") -} - -func (db *Database) AncientSize(kind string) (uint64, error) { - panic("not supported") -} - -func (db *Database) ReadAncients(fn func(op ethdb.AncientReaderOp) error) (err error) { - return fn(db) -} - -func (db *Database) Put(key []byte, value []byte) error { - panic("not supported") -} - -func (db *Database) Delete(key []byte) error { - panic("not supported") -} - -func (db *Database) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) { - panic("not supported") -} - -func (db *Database) TruncateHead(n uint64) (uint64, error) { - panic("not supported") -} - -func (db *Database) TruncateTail(n uint64) (uint64, error) { - panic("not supported") -} - -func (db *Database) Sync() error { - return nil -} - -func (db *Database) MigrateTable(s string, f func([]byte) ([]byte, error)) error { - panic("not supported") -} - -func (db *Database) NewBatch() ethdb.Batch { - panic("not supported") -} - -func (db *Database) NewBatchWithSize(size int) ethdb.Batch { - panic("not supported") -} - -func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { - panic("not supported") -} - -func (db *Database) Stat(property string) (string, error) { - panic("not supported") -} - -func (db *Database) AncientDatadir() (string, error) { - panic("not supported") -} - -func (db *Database) Compact(start []byte, limit []byte) error { - return nil -} - -func (db *Database) NewSnapshot() (ethdb.Snapshot, error) { - panic("not supported") -} - -func (db *Database) Close() error { - db.remote.Close() - return nil -} - -func New(client *rpc.Client) ethdb.Database { - return &Database{ - remote: client, - } -} diff --git a/builder/ethdb/snapshot.go b/builder/ethdb/snapshot.go deleted file mode 100644 index 03b7794a7..000000000 --- a/builder/ethdb/snapshot.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 ethdb - -type Snapshot interface { - // Has retrieves if a key is present in the snapshot backing by a key-value - // data store. - Has(key []byte) (bool, error) - - // Get retrieves the given key if it's present in the snapshot backing by - // key-value data store. - Get(key []byte) ([]byte, error) - - // Release releases associated resources. Release should always succeed and can - // be called multiple times without causing error. - Release() -} - -// Snapshotter wraps the Snapshot method of a backing data store. -type Snapshotter interface { - // NewSnapshot creates a database snapshot based on the current state. - // The created snapshot will not be affected by all following mutations - // happened on the database. - // Note don't forget to release the snapshot once it's used up, otherwise - // the stale data will never be cleaned up by the underlying compactor. - NewSnapshot() (Snapshot, error) -} diff --git a/builder/ethstats/ethstats.go b/builder/ethstats/ethstats.go deleted file mode 100644 index 61ceec443..000000000 --- a/builder/ethstats/ethstats.go +++ /dev/null @@ -1,835 +0,0 @@ -// Copyright 2016 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 ethstats implements the network stats reporting service. -package ethstats - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math/big" - "net/http" - "runtime" - "strconv" - "strings" - "sync" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/mclock" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - ethproto "github.com/ethereum/go-ethereum/eth/protocols/eth" - "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/miner" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/rpc" - "github.com/gorilla/websocket" -) - -const ( - // historyUpdateRange is the number of blocks a node should report upon login or - // history request. - historyUpdateRange = 50 - - // txChanSize is the size of channel listening to NewTxsEvent. - // The number is referenced from the size of tx pool. - txChanSize = 4096 - // chainHeadChanSize is the size of channel listening to ChainHeadEvent. - chainHeadChanSize = 10 - - messageSizeLimit = 15 * 1024 * 1024 -) - -// backend encompasses the bare-minimum functionality needed for ethstats reporting -type backend interface { - SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription - SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription - CurrentHeader() *types.Header - HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) - GetTd(ctx context.Context, hash common.Hash) *big.Int - Stats() (pending int, queued int) - SyncProgress() ethereum.SyncProgress -} - -// fullNodeBackend encompasses the functionality necessary for a full node -// reporting to ethstats -type fullNodeBackend interface { - backend - BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) - CurrentBlock() *types.Header - SuggestGasTipCap(ctx context.Context) (*big.Int, error) -} - -// miningNodeBackend encompasses the functionality necessary for a mining node -// reporting to ethstats -type miningNodeBackend interface { - fullNodeBackend - Miner() *miner.Miner -} - -// Service implements an Ethereum netstats reporting daemon that pushes local -// chain statistics up to a monitoring server. -type Service struct { - server *p2p.Server // Peer-to-peer server to retrieve networking infos - backend backend - engine consensus.Engine // Consensus engine to retrieve variadic block fields - - node string // Name of the node to display on the monitoring page - pass string // Password to authorize access to the monitoring page - host string // Remote address of the monitoring service - - pongCh chan struct{} // Pong notifications are fed into this channel - histCh chan []uint64 // History request block numbers are fed into this channel - - headSub event.Subscription - txSub event.Subscription -} - -// connWrapper is a wrapper to prevent concurrent-write or concurrent-read on the -// websocket. -// -// From Gorilla websocket docs: -// -// Connections support one concurrent reader and one concurrent writer. Applications are -// responsible for ensuring that -// - no more than one goroutine calls the write methods -// NextWriter, SetWriteDeadline, WriteMessage, WriteJSON, EnableWriteCompression, -// SetCompressionLevel concurrently; and -// - that no more than one goroutine calls the -// read methods NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, -// SetPingHandler concurrently. -// -// The Close and WriteControl methods can be called concurrently with all other methods. -type connWrapper struct { - conn *websocket.Conn - - rlock sync.Mutex - wlock sync.Mutex -} - -func newConnectionWrapper(conn *websocket.Conn) *connWrapper { - conn.SetReadLimit(messageSizeLimit) - return &connWrapper{conn: conn} -} - -// WriteJSON wraps corresponding method on the websocket but is safe for concurrent calling -func (w *connWrapper) WriteJSON(v interface{}) error { - w.wlock.Lock() - defer w.wlock.Unlock() - - return w.conn.WriteJSON(v) -} - -// ReadJSON wraps corresponding method on the websocket but is safe for concurrent calling -func (w *connWrapper) ReadJSON(v interface{}) error { - w.rlock.Lock() - defer w.rlock.Unlock() - - return w.conn.ReadJSON(v) -} - -// Close wraps corresponding method on the websocket but is safe for concurrent calling -func (w *connWrapper) Close() error { - // The Close and WriteControl methods can be called concurrently with all other methods, - // so the mutex is not used here - return w.conn.Close() -} - -// parseEthstatsURL parses the netstats connection url. -// URL argument should be of the form -// If non-erroring, the returned slice contains 3 elements: [nodename, pass, host] -func parseEthstatsURL(url string) (parts []string, err error) { - err = fmt.Errorf("invalid netstats url: \"%s\", should be nodename:secret@host:port", url) - - hostIndex := strings.LastIndex(url, "@") - if hostIndex == -1 || hostIndex == len(url)-1 { - return nil, err - } - preHost, host := url[:hostIndex], url[hostIndex+1:] - - passIndex := strings.LastIndex(preHost, ":") - if passIndex == -1 { - return []string{preHost, "", host}, nil - } - nodename, pass := preHost[:passIndex], "" - if passIndex != len(preHost)-1 { - pass = preHost[passIndex+1:] - } - - return []string{nodename, pass, host}, nil -} - -// New returns a monitoring service ready for stats reporting. -func New(node *node.Node, backend backend, engine consensus.Engine, url string) error { - parts, err := parseEthstatsURL(url) - if err != nil { - return err - } - ethstats := &Service{ - backend: backend, - engine: engine, - server: node.Server(), - node: parts[0], - pass: parts[1], - host: parts[2], - pongCh: make(chan struct{}), - histCh: make(chan []uint64, 1), - } - - node.RegisterLifecycle(ethstats) - return nil -} - -// Start implements node.Lifecycle, starting up the monitoring and reporting daemon. -func (s *Service) Start() error { - // Subscribe to chain events to execute updates on - chainHeadCh := make(chan core.ChainHeadEvent, chainHeadChanSize) - s.headSub = s.backend.SubscribeChainHeadEvent(chainHeadCh) - txEventCh := make(chan core.NewTxsEvent, txChanSize) - s.txSub = s.backend.SubscribeNewTxsEvent(txEventCh) - go s.loop(chainHeadCh, txEventCh) - - log.Info("Stats daemon started") - return nil -} - -// Stop implements node.Lifecycle, terminating the monitoring and reporting daemon. -func (s *Service) Stop() error { - s.headSub.Unsubscribe() - s.txSub.Unsubscribe() - log.Info("Stats daemon stopped") - return nil -} - -// loop keeps trying to connect to the netstats server, reporting chain events -// until termination. -func (s *Service) loop(chainHeadCh chan core.ChainHeadEvent, txEventCh chan core.NewTxsEvent) { - // Start a goroutine that exhausts the subscriptions to avoid events piling up - var ( - quitCh = make(chan struct{}) - headCh = make(chan *types.Block, 1) - txCh = make(chan struct{}, 1) - ) - go func() { - var lastTx mclock.AbsTime - - HandleLoop: - for { - select { - // Notify of chain head events, but drop if too frequent - case head := <-chainHeadCh: - select { - case headCh <- head.Block: - default: - } - - // Notify of new transaction events, but drop if too frequent - case <-txEventCh: - if time.Duration(mclock.Now()-lastTx) < time.Second { - continue - } - lastTx = mclock.Now() - - select { - case txCh <- struct{}{}: - default: - } - - // node stopped - case <-s.txSub.Err(): - break HandleLoop - case <-s.headSub.Err(): - break HandleLoop - } - } - close(quitCh) - }() - - // Resolve the URL, defaulting to TLS, but falling back to none too - path := fmt.Sprintf("%s/api", s.host) - urls := []string{path} - - // url.Parse and url.IsAbs is unsuitable (https://github.com/golang/go/issues/19779) - if !strings.Contains(path, "://") { - urls = []string{"wss://" + path, "ws://" + path} - } - - errTimer := time.NewTimer(0) - defer errTimer.Stop() - // Loop reporting until termination - for { - select { - case <-quitCh: - return - case <-errTimer.C: - // Establish a websocket connection to the server on any supported URL - var ( - conn *connWrapper - err error - ) - dialer := websocket.Dialer{HandshakeTimeout: 5 * time.Second} - header := make(http.Header) - header.Set("origin", "http://localhost") - for _, url := range urls { - c, _, e := dialer.Dial(url, header) - err = e - if err == nil { - conn = newConnectionWrapper(c) - break - } - } - if err != nil { - log.Warn("Stats server unreachable", "err", err) - errTimer.Reset(10 * time.Second) - continue - } - // Authenticate the client with the server - if err = s.login(conn); err != nil { - log.Warn("Stats login failed", "err", err) - conn.Close() - errTimer.Reset(10 * time.Second) - continue - } - go s.readLoop(conn) - - // Send the initial stats so our node looks decent from the get go - if err = s.report(conn); err != nil { - log.Warn("Initial stats report failed", "err", err) - conn.Close() - errTimer.Reset(0) - continue - } - // Keep sending status updates until the connection breaks - fullReport := time.NewTicker(15 * time.Second) - - for err == nil { - select { - case <-quitCh: - fullReport.Stop() - // Make sure the connection is closed - conn.Close() - return - - case <-fullReport.C: - if err = s.report(conn); err != nil { - log.Warn("Full stats report failed", "err", err) - } - case list := <-s.histCh: - if err = s.reportHistory(conn, list); err != nil { - log.Warn("Requested history report failed", "err", err) - } - case head := <-headCh: - if err = s.reportBlock(conn, head); err != nil { - log.Warn("Block stats report failed", "err", err) - } - if err = s.reportPending(conn); err != nil { - log.Warn("Post-block transaction stats report failed", "err", err) - } - case <-txCh: - if err = s.reportPending(conn); err != nil { - log.Warn("Transaction stats report failed", "err", err) - } - } - } - fullReport.Stop() - - // Close the current connection and establish a new one - conn.Close() - errTimer.Reset(0) - } - } -} - -// readLoop loops as long as the connection is alive and retrieves data packets -// from the network socket. If any of them match an active request, it forwards -// it, if they themselves are requests it initiates a reply, and lastly it drops -// unknown packets. -func (s *Service) readLoop(conn *connWrapper) { - // If the read loop exits, close the connection - defer conn.Close() - - for { - // Retrieve the next generic network packet and bail out on error - var blob json.RawMessage - if err := conn.ReadJSON(&blob); err != nil { - log.Warn("Failed to retrieve stats server message", "err", err) - return - } - // If the network packet is a system ping, respond to it directly - var ping string - if err := json.Unmarshal(blob, &ping); err == nil && strings.HasPrefix(ping, "primus::ping::") { - if err := conn.WriteJSON(strings.ReplaceAll(ping, "ping", "pong")); err != nil { - log.Warn("Failed to respond to system ping message", "err", err) - return - } - continue - } - // Not a system ping, try to decode an actual state message - var msg map[string][]interface{} - if err := json.Unmarshal(blob, &msg); err != nil { - log.Warn("Failed to decode stats server message", "err", err) - return - } - log.Trace("Received message from stats server", "msg", msg) - if len(msg["emit"]) == 0 { - log.Warn("Stats server sent non-broadcast", "msg", msg) - return - } - command, ok := msg["emit"][0].(string) - if !ok { - log.Warn("Invalid stats server message type", "type", msg["emit"][0]) - return - } - // If the message is a ping reply, deliver (someone must be listening!) - if len(msg["emit"]) == 2 && command == "node-pong" { - select { - case s.pongCh <- struct{}{}: - // Pong delivered, continue listening - continue - default: - // Ping routine dead, abort - log.Warn("Stats server pinger seems to have died") - return - } - } - // If the message is a history request, forward to the event processor - if len(msg["emit"]) == 2 && command == "history" { - // Make sure the request is valid and doesn't crash us - request, ok := msg["emit"][1].(map[string]interface{}) - if !ok { - log.Warn("Invalid stats history request", "msg", msg["emit"][1]) - select { - case s.histCh <- nil: // Treat it as an no indexes request - default: - } - continue - } - list, ok := request["list"].([]interface{}) - if !ok { - log.Warn("Invalid stats history block list", "list", request["list"]) - return - } - // Convert the block number list to an integer list - numbers := make([]uint64, len(list)) - for i, num := range list { - n, ok := num.(float64) - if !ok { - log.Warn("Invalid stats history block number", "number", num) - return - } - numbers[i] = uint64(n) - } - select { - case s.histCh <- numbers: - continue - default: - } - } - // Report anything else and continue - log.Info("Unknown stats message", "msg", msg) - } -} - -// nodeInfo is the collection of meta information about a node that is displayed -// on the monitoring page. -type nodeInfo struct { - Name string `json:"name"` - Node string `json:"node"` - Port int `json:"port"` - Network string `json:"net"` - Protocol string `json:"protocol"` - API string `json:"api"` - Os string `json:"os"` - OsVer string `json:"os_v"` - Client string `json:"client"` - History bool `json:"canUpdateHistory"` -} - -// authMsg is the authentication infos needed to login to a monitoring server. -type authMsg struct { - ID string `json:"id"` - Info nodeInfo `json:"info"` - Secret string `json:"secret"` -} - -// login tries to authorize the client at the remote server. -func (s *Service) login(conn *connWrapper) error { - // Construct and send the login authentication - infos := s.server.NodeInfo() - - var protocols []string - for _, proto := range s.server.Protocols { - protocols = append(protocols, fmt.Sprintf("%s/%d", proto.Name, proto.Version)) - } - var network string - if info := infos.Protocols["eth"]; info != nil { - network = fmt.Sprintf("%d", info.(*ethproto.NodeInfo).Network) - } else { - return errors.New("no eth protocol available") - } - auth := &authMsg{ - ID: s.node, - Info: nodeInfo{ - Name: s.node, - Node: infos.Name, - Port: infos.Ports.Listener, - Network: network, - Protocol: strings.Join(protocols, ", "), - API: "No", - Os: runtime.GOOS, - OsVer: runtime.GOARCH, - Client: "0.1.1", - History: true, - }, - Secret: s.pass, - } - login := map[string][]interface{}{ - "emit": {"hello", auth}, - } - if err := conn.WriteJSON(login); err != nil { - return err - } - // Retrieve the remote ack or connection termination - var ack map[string][]string - if err := conn.ReadJSON(&ack); err != nil || len(ack["emit"]) != 1 || ack["emit"][0] != "ready" { - return errors.New("unauthorized") - } - return nil -} - -// report collects all possible data to report and send it to the stats server. -// This should only be used on reconnects or rarely to avoid overloading the -// server. Use the individual methods for reporting subscribed events. -func (s *Service) report(conn *connWrapper) error { - if err := s.reportLatency(conn); err != nil { - return err - } - if err := s.reportBlock(conn, nil); err != nil { - return err - } - if err := s.reportPending(conn); err != nil { - return err - } - if err := s.reportStats(conn); err != nil { - return err - } - return nil -} - -// reportLatency sends a ping request to the server, measures the RTT time and -// finally sends a latency update. -func (s *Service) reportLatency(conn *connWrapper) error { - // Send the current time to the ethstats server - start := time.Now() - - ping := map[string][]interface{}{ - "emit": {"node-ping", map[string]string{ - "id": s.node, - "clientTime": start.String(), - }}, - } - if err := conn.WriteJSON(ping); err != nil { - return err - } - // Wait for the pong request to arrive back - select { - case <-s.pongCh: - // Pong delivered, report the latency - case <-time.After(5 * time.Second): - // Ping timeout, abort - return errors.New("ping timed out") - } - latency := strconv.Itoa(int((time.Since(start) / time.Duration(2)).Nanoseconds() / 1000000)) - - // Send back the measured latency - log.Trace("Sending measured latency to ethstats", "latency", latency) - - stats := map[string][]interface{}{ - "emit": {"latency", map[string]string{ - "id": s.node, - "latency": latency, - }}, - } - return conn.WriteJSON(stats) -} - -// blockStats is the information to report about individual blocks. -type blockStats struct { - Number *big.Int `json:"number"` - Hash common.Hash `json:"hash"` - ParentHash common.Hash `json:"parentHash"` - Timestamp *big.Int `json:"timestamp"` - Miner common.Address `json:"miner"` - GasUsed uint64 `json:"gasUsed"` - GasLimit uint64 `json:"gasLimit"` - Diff string `json:"difficulty"` - TotalDiff string `json:"totalDifficulty"` - Txs []txStats `json:"transactions"` - TxHash common.Hash `json:"transactionsRoot"` - Root common.Hash `json:"stateRoot"` - Uncles uncleStats `json:"uncles"` -} - -// txStats is the information to report about individual transactions. -type txStats struct { - Hash common.Hash `json:"hash"` -} - -// uncleStats is a custom wrapper around an uncle array to force serializing -// empty arrays instead of returning null for them. -type uncleStats []*types.Header - -func (s uncleStats) MarshalJSON() ([]byte, error) { - if uncles := ([]*types.Header)(s); len(uncles) > 0 { - return json.Marshal(uncles) - } - return []byte("[]"), nil -} - -// reportBlock retrieves the current chain head and reports it to the stats server. -func (s *Service) reportBlock(conn *connWrapper, block *types.Block) error { - // Gather the block details from the header or block chain - details := s.assembleBlockStats(block) - - // Short circuit if the block detail is not available. - if details == nil { - return nil - } - // Assemble the block report and send it to the server - log.Trace("Sending new block to ethstats", "number", details.Number, "hash", details.Hash) - - stats := map[string]interface{}{ - "id": s.node, - "block": details, - } - report := map[string][]interface{}{ - "emit": {"block", stats}, - } - return conn.WriteJSON(report) -} - -// assembleBlockStats retrieves any required metadata to report a single block -// and assembles the block stats. If block is nil, the current head is processed. -func (s *Service) assembleBlockStats(block *types.Block) *blockStats { - // Gather the block infos from the local blockchain - var ( - header *types.Header - td *big.Int - txs []txStats - uncles []*types.Header - ) - - // check if backend is a full node - fullBackend, ok := s.backend.(fullNodeBackend) - if ok { - // Retrieve current chain head if no block is given. - if block == nil { - head := fullBackend.CurrentBlock() - block, _ = fullBackend.BlockByNumber(context.Background(), rpc.BlockNumber(head.Number.Uint64())) - } - // Short circuit if no block is available. It might happen when - // the blockchain is reorging. - if block == nil { - return nil - } - header = block.Header() - td = fullBackend.GetTd(context.Background(), header.Hash()) - - txs = make([]txStats, len(block.Transactions())) - for i, tx := range block.Transactions() { - txs[i].Hash = tx.Hash() - } - uncles = block.Uncles() - } else { - // Light nodes would need on-demand lookups for transactions/uncles, skip - if block != nil { - header = block.Header() - } else { - header = s.backend.CurrentHeader() - } - td = s.backend.GetTd(context.Background(), header.Hash()) - txs = []txStats{} - } - - // Assemble and return the block stats - author, _ := s.engine.Author(header) - - return &blockStats{ - Number: header.Number, - Hash: header.Hash(), - ParentHash: header.ParentHash, - Timestamp: new(big.Int).SetUint64(header.Time), - Miner: author, - GasUsed: header.GasUsed, - GasLimit: header.GasLimit, - Diff: header.Difficulty.String(), - TotalDiff: td.String(), - Txs: txs, - TxHash: header.TxHash, - Root: header.Root, - Uncles: uncles, - } -} - -// reportHistory retrieves the most recent batch of blocks and reports it to the -// stats server. -func (s *Service) reportHistory(conn *connWrapper, list []uint64) error { - // Figure out the indexes that need reporting - indexes := make([]uint64, 0, historyUpdateRange) - if len(list) > 0 { - // Specific indexes requested, send them back in particular - indexes = append(indexes, list...) - } else { - // No indexes requested, send back the top ones - head := s.backend.CurrentHeader().Number.Int64() - start := head - historyUpdateRange + 1 - if start < 0 { - start = 0 - } - for i := uint64(start); i <= uint64(head); i++ { - indexes = append(indexes, i) - } - } - // Gather the batch of blocks to report - history := make([]*blockStats, len(indexes)) - for i, number := range indexes { - fullBackend, ok := s.backend.(fullNodeBackend) - // Retrieve the next block if it's known to us - var block *types.Block - if ok { - block, _ = fullBackend.BlockByNumber(context.Background(), rpc.BlockNumber(number)) // TODO ignore error here ? - } else { - if header, _ := s.backend.HeaderByNumber(context.Background(), rpc.BlockNumber(number)); header != nil { - block = types.NewBlockWithHeader(header) - } - } - // If we do have the block, add to the history and continue - if block != nil { - history[len(history)-1-i] = s.assembleBlockStats(block) - continue - } - // Ran out of blocks, cut the report short and send - history = history[len(history)-i:] - break - } - // Assemble the history report and send it to the server - if len(history) > 0 { - log.Trace("Sending historical blocks to ethstats", "first", history[0].Number, "last", history[len(history)-1].Number) - } else { - log.Trace("No history to send to stats server") - } - stats := map[string]interface{}{ - "id": s.node, - "history": history, - } - report := map[string][]interface{}{ - "emit": {"history", stats}, - } - return conn.WriteJSON(report) -} - -// pendStats is the information to report about pending transactions. -type pendStats struct { - Pending int `json:"pending"` -} - -// reportPending retrieves the current number of pending transactions and reports -// it to the stats server. -func (s *Service) reportPending(conn *connWrapper) error { - // Retrieve the pending count from the local blockchain - pending, _ := s.backend.Stats() - // Assemble the transaction stats and send it to the server - log.Trace("Sending pending transactions to ethstats", "count", pending) - - stats := map[string]interface{}{ - "id": s.node, - "stats": &pendStats{ - Pending: pending, - }, - } - report := map[string][]interface{}{ - "emit": {"pending", stats}, - } - return conn.WriteJSON(report) -} - -// nodeStats is the information to report about the local node. -type nodeStats struct { - Active bool `json:"active"` - Syncing bool `json:"syncing"` - Mining bool `json:"mining"` - Hashrate int `json:"hashrate"` - Peers int `json:"peers"` - GasPrice int `json:"gasPrice"` - Uptime int `json:"uptime"` -} - -// reportStats retrieves various stats about the node at the networking and -// mining layer and reports it to the stats server. -func (s *Service) reportStats(conn *connWrapper) error { - // Gather the syncing and mining infos from the local miner instance - var ( - mining bool - hashrate int - syncing bool - gasprice int - ) - // check if backend is a full node - if fullBackend, ok := s.backend.(fullNodeBackend); ok { - if miningBackend, ok := s.backend.(miningNodeBackend); ok { - mining = miningBackend.Miner().Mining() - hashrate = int(miningBackend.Miner().Hashrate()) - } - - sync := fullBackend.SyncProgress() - syncing = !sync.Done() - - price, _ := fullBackend.SuggestGasTipCap(context.Background()) - gasprice = int(price.Uint64()) - if basefee := fullBackend.CurrentHeader().BaseFee; basefee != nil { - gasprice += int(basefee.Uint64()) - } - } else { - sync := s.backend.SyncProgress() - syncing = !sync.Done() - } - // Assemble the node stats and send it to the server - log.Trace("Sending node details to ethstats") - - stats := map[string]interface{}{ - "id": s.node, - "stats": &nodeStats{ - Active: true, - Mining: mining, - Hashrate: hashrate, - Peers: s.server.PeerCount(), - GasPrice: gasprice, - Syncing: syncing, - Uptime: 100, - }, - } - report := map[string][]interface{}{ - "emit": {"stats", stats}, - } - return conn.WriteJSON(report) -} diff --git a/builder/ethstats/ethstats_test.go b/builder/ethstats/ethstats_test.go deleted file mode 100644 index 60322f765..000000000 --- a/builder/ethstats/ethstats_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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 ethstats - -import ( - "strconv" - "testing" -) - -func TestParseEthstatsURL(t *testing.T) { - cases := []struct { - url string - node, pass, host string - }{ - { - url: `"debug meowsbits":mypass@ws://mordor.dash.fault.dev:3000`, - node: "debug meowsbits", pass: "mypass", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `"debug @meowsbits":mypass@ws://mordor.dash.fault.dev:3000`, - node: "debug @meowsbits", pass: "mypass", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `"debug: @meowsbits":mypass@ws://mordor.dash.fault.dev:3000`, - node: "debug: @meowsbits", pass: "mypass", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `name:@ws://mordor.dash.fault.dev:3000`, - node: "name", pass: "", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `name@ws://mordor.dash.fault.dev:3000`, - node: "name", pass: "", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `:mypass@ws://mordor.dash.fault.dev:3000`, - node: "", pass: "mypass", host: "ws://mordor.dash.fault.dev:3000", - }, - { - url: `:@ws://mordor.dash.fault.dev:3000`, - node: "", pass: "", host: "ws://mordor.dash.fault.dev:3000", - }, - } - - for i, c := range cases { - parts, err := parseEthstatsURL(c.url) - if err != nil { - t.Fatal(err) - } - node, pass, host := parts[0], parts[1], parts[2] - - // unquote because the value provided will be used as a CLI flag value, so unescaped quotes will be removed - nodeUnquote, err := strconv.Unquote(node) - if err == nil { - node = nodeUnquote - } - - if node != c.node { - t.Errorf("case=%d mismatch node value, got: %v ,want: %v", i, node, c.node) - } - if pass != c.pass { - t.Errorf("case=%d mismatch pass value, got: %v ,want: %v", i, pass, c.pass) - } - if host != c.host { - t.Errorf("case=%d mismatch host value, got: %v ,want: %v", i, host, c.host) - } - } -} diff --git a/builder/event/event.go b/builder/event/event.go deleted file mode 100644 index 25a2c2e45..000000000 --- a/builder/event/event.go +++ /dev/null @@ -1,217 +0,0 @@ -// 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 event deals with subscriptions to real-time events. -package event - -import ( - "errors" - "fmt" - "reflect" - "sync" - "time" -) - -// TypeMuxEvent is a time-tagged notification pushed to subscribers. -type TypeMuxEvent struct { - Time time.Time - Data interface{} -} - -// A TypeMux dispatches events to registered receivers. Receivers can be -// registered to handle events of certain type. Any operation -// called after mux is stopped will return ErrMuxClosed. -// -// The zero value is ready to use. -// -// Deprecated: use Feed -type TypeMux struct { - mutex sync.RWMutex - subm map[reflect.Type][]*TypeMuxSubscription - stopped bool -} - -// ErrMuxClosed is returned when Posting on a closed TypeMux. -var ErrMuxClosed = errors.New("event: mux closed") - -// Subscribe creates a subscription for events of the given types. The -// subscription's channel is closed when it is unsubscribed -// or the mux is closed. -func (mux *TypeMux) Subscribe(types ...interface{}) *TypeMuxSubscription { - sub := newsub(mux) - mux.mutex.Lock() - defer mux.mutex.Unlock() - if mux.stopped { - // set the status to closed so that calling Unsubscribe after this - // call will short circuit. - sub.closed = true - close(sub.postC) - } else { - if mux.subm == nil { - mux.subm = make(map[reflect.Type][]*TypeMuxSubscription, len(types)) - } - for _, t := range types { - rtyp := reflect.TypeOf(t) - oldsubs := mux.subm[rtyp] - if find(oldsubs, sub) != -1 { - panic(fmt.Sprintf("event: duplicate type %s in Subscribe", rtyp)) - } - subs := make([]*TypeMuxSubscription, len(oldsubs)+1) - copy(subs, oldsubs) - subs[len(oldsubs)] = sub - mux.subm[rtyp] = subs - } - } - return sub -} - -// Post sends an event to all receivers registered for the given type. -// It returns ErrMuxClosed if the mux has been stopped. -func (mux *TypeMux) Post(ev interface{}) error { - event := &TypeMuxEvent{ - Time: time.Now(), - Data: ev, - } - rtyp := reflect.TypeOf(ev) - mux.mutex.RLock() - if mux.stopped { - mux.mutex.RUnlock() - return ErrMuxClosed - } - subs := mux.subm[rtyp] - mux.mutex.RUnlock() - for _, sub := range subs { - sub.deliver(event) - } - return nil -} - -// Stop closes a mux. The mux can no longer be used. -// Future Post calls will fail with ErrMuxClosed. -// Stop blocks until all current deliveries have finished. -func (mux *TypeMux) Stop() { - mux.mutex.Lock() - defer mux.mutex.Unlock() - for _, subs := range mux.subm { - for _, sub := range subs { - sub.closewait() - } - } - mux.subm = nil - mux.stopped = true -} - -func (mux *TypeMux) del(s *TypeMuxSubscription) { - mux.mutex.Lock() - defer mux.mutex.Unlock() - for typ, subs := range mux.subm { - if pos := find(subs, s); pos >= 0 { - if len(subs) == 1 { - delete(mux.subm, typ) - } else { - mux.subm[typ] = posdelete(subs, pos) - } - } - } -} - -func find(slice []*TypeMuxSubscription, item *TypeMuxSubscription) int { - for i, v := range slice { - if v == item { - return i - } - } - return -1 -} - -func posdelete(slice []*TypeMuxSubscription, pos int) []*TypeMuxSubscription { - news := make([]*TypeMuxSubscription, len(slice)-1) - copy(news[:pos], slice[:pos]) - copy(news[pos:], slice[pos+1:]) - return news -} - -// TypeMuxSubscription is a subscription established through TypeMux. -type TypeMuxSubscription struct { - mux *TypeMux - created time.Time - closeMu sync.Mutex - closing chan struct{} - closed bool - - // these two are the same channel. they are stored separately so - // postC can be set to nil without affecting the return value of - // Chan. - postMu sync.RWMutex - readC <-chan *TypeMuxEvent - postC chan<- *TypeMuxEvent -} - -func newsub(mux *TypeMux) *TypeMuxSubscription { - c := make(chan *TypeMuxEvent) - return &TypeMuxSubscription{ - mux: mux, - created: time.Now(), - readC: c, - postC: c, - closing: make(chan struct{}), - } -} - -func (s *TypeMuxSubscription) Chan() <-chan *TypeMuxEvent { - return s.readC -} - -func (s *TypeMuxSubscription) Unsubscribe() { - s.mux.del(s) - s.closewait() -} - -func (s *TypeMuxSubscription) Closed() bool { - s.closeMu.Lock() - defer s.closeMu.Unlock() - return s.closed -} - -func (s *TypeMuxSubscription) closewait() { - s.closeMu.Lock() - defer s.closeMu.Unlock() - if s.closed { - return - } - close(s.closing) - s.closed = true - - s.postMu.Lock() - defer s.postMu.Unlock() - close(s.postC) - s.postC = nil -} - -func (s *TypeMuxSubscription) deliver(event *TypeMuxEvent) { - // Short circuit delivery if stale event - if s.created.After(event.Time) { - return - } - // Otherwise deliver the event - s.postMu.RLock() - defer s.postMu.RUnlock() - - select { - case s.postC <- event: - case <-s.closing: - } -} diff --git a/builder/event/event_test.go b/builder/event/event_test.go deleted file mode 100644 index 84b37eca3..000000000 --- a/builder/event/event_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// 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 event - -import ( - "math/rand" - "sync" - "testing" - "time" -) - -type testEvent int - -func TestSubCloseUnsub(t *testing.T) { - // the point of this test is **not** to panic - var mux TypeMux - mux.Stop() - sub := mux.Subscribe(0) - sub.Unsubscribe() -} - -func TestSub(t *testing.T) { - mux := new(TypeMux) - defer mux.Stop() - - sub := mux.Subscribe(testEvent(0)) - go func() { - if err := mux.Post(testEvent(5)); err != nil { - t.Errorf("Post returned unexpected error: %v", err) - } - }() - ev := <-sub.Chan() - - if ev.Data.(testEvent) != testEvent(5) { - t.Errorf("Got %v (%T), expected event %v (%T)", - ev, ev, testEvent(5), testEvent(5)) - } -} - -func TestMuxErrorAfterStop(t *testing.T) { - mux := new(TypeMux) - mux.Stop() - - sub := mux.Subscribe(testEvent(0)) - if _, isopen := <-sub.Chan(); isopen { - t.Errorf("subscription channel was not closed") - } - if err := mux.Post(testEvent(0)); err != ErrMuxClosed { - t.Errorf("Post error mismatch, got: %s, expected: %s", err, ErrMuxClosed) - } -} - -func TestUnsubscribeUnblockPost(t *testing.T) { - mux := new(TypeMux) - defer mux.Stop() - - sub := mux.Subscribe(testEvent(0)) - unblocked := make(chan bool) - go func() { - mux.Post(testEvent(5)) - unblocked <- true - }() - - select { - case <-unblocked: - t.Errorf("Post returned before Unsubscribe") - default: - sub.Unsubscribe() - <-unblocked - } -} - -func TestSubscribeDuplicateType(t *testing.T) { - mux := new(TypeMux) - expected := "event: duplicate type event.testEvent in Subscribe" - - defer func() { - err := recover() - if err == nil { - t.Errorf("Subscribe didn't panic for duplicate type") - } else if err != expected { - t.Errorf("panic mismatch: got %#v, expected %#v", err, expected) - } - }() - mux.Subscribe(testEvent(1), testEvent(2)) -} - -func TestMuxConcurrent(t *testing.T) { - mux := new(TypeMux) - defer mux.Stop() - - recv := make(chan int) - poster := func() { - for { - err := mux.Post(testEvent(0)) - if err != nil { - return - } - } - } - sub := func(i int) { - time.Sleep(time.Duration(rand.Intn(99)) * time.Millisecond) - sub := mux.Subscribe(testEvent(0)) - <-sub.Chan() - sub.Unsubscribe() - recv <- i - } - - go poster() - go poster() - go poster() - nsubs := 1000 - for i := 0; i < nsubs; i++ { - go sub(i) - } - - // wait until everyone has been served - counts := make(map[int]int, nsubs) - for i := 0; i < nsubs; i++ { - counts[<-recv]++ - } - for i, count := range counts { - if count != 1 { - t.Errorf("receiver %d called %d times, expected only 1 call", i, count) - } - } -} - -func emptySubscriber(mux *TypeMux) { - s := mux.Subscribe(testEvent(0)) - go func() { - for range s.Chan() { - } - }() -} - -func BenchmarkPost1000(b *testing.B) { - var ( - mux = new(TypeMux) - subscribed, done sync.WaitGroup - nsubs = 1000 - ) - subscribed.Add(nsubs) - done.Add(nsubs) - for i := 0; i < nsubs; i++ { - go func() { - s := mux.Subscribe(testEvent(0)) - subscribed.Done() - for range s.Chan() { - } - done.Done() - }() - } - subscribed.Wait() - - // The actual benchmark. - b.ResetTimer() - for i := 0; i < b.N; i++ { - mux.Post(testEvent(0)) - } - - b.StopTimer() - mux.Stop() - done.Wait() -} - -func BenchmarkPostConcurrent(b *testing.B) { - var mux = new(TypeMux) - defer mux.Stop() - emptySubscriber(mux) - emptySubscriber(mux) - emptySubscriber(mux) - - var wg sync.WaitGroup - poster := func() { - for i := 0; i < b.N; i++ { - mux.Post(testEvent(0)) - } - wg.Done() - } - wg.Add(5) - for i := 0; i < 5; i++ { - go poster() - } - wg.Wait() -} - -// for comparison -func BenchmarkChanSend(b *testing.B) { - c := make(chan interface{}) - defer close(c) - closed := make(chan struct{}) - go func() { - for range c { - } - }() - - for i := 0; i < b.N; i++ { - select { - case c <- i: - case <-closed: - } - } -} diff --git a/builder/event/example_feed_test.go b/builder/event/example_feed_test.go deleted file mode 100644 index 9b5ad50df..000000000 --- a/builder/event/example_feed_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 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 event_test - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/event" -) - -func ExampleFeed_acknowledgedEvents() { - // This example shows how the return value of Send can be used for request/reply - // interaction between event consumers and producers. - var feed event.Feed - type ackedEvent struct { - i int - ack chan<- struct{} - } - - // Consumers wait for events on the feed and acknowledge processing. - done := make(chan struct{}) - defer close(done) - for i := 0; i < 3; i++ { - ch := make(chan ackedEvent, 100) - sub := feed.Subscribe(ch) - go func() { - defer sub.Unsubscribe() - for { - select { - case ev := <-ch: - fmt.Println(ev.i) // "process" the event - ev.ack <- struct{}{} - case <-done: - return - } - } - }() - } - - // The producer sends values of type ackedEvent with increasing values of i. - // It waits for all consumers to acknowledge before sending the next event. - for i := 0; i < 3; i++ { - acksignal := make(chan struct{}) - n := feed.Send(ackedEvent{i, acksignal}) - for ack := 0; ack < n; ack++ { - <-acksignal - } - } - // Output: - // 0 - // 0 - // 0 - // 1 - // 1 - // 1 - // 2 - // 2 - // 2 -} diff --git a/builder/event/example_scope_test.go b/builder/event/example_scope_test.go deleted file mode 100644 index 825a8deea..000000000 --- a/builder/event/example_scope_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2016 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 event_test - -import ( - "fmt" - "sync" - - "github.com/ethereum/go-ethereum/event" -) - -// This example demonstrates how SubscriptionScope can be used to control the lifetime of -// subscriptions. -// -// Our example program consists of two servers, each of which performs a calculation when -// requested. The servers also allow subscribing to results of all computations. -type divServer struct{ results event.Feed } -type mulServer struct{ results event.Feed } - -func (s *divServer) do(a, b int) int { - r := a / b - s.results.Send(r) - return r -} - -func (s *mulServer) do(a, b int) int { - r := a * b - s.results.Send(r) - return r -} - -// The servers are contained in an App. The app controls the servers and exposes them -// through its API. -type App struct { - divServer - mulServer - scope event.SubscriptionScope -} - -func (s *App) Calc(op byte, a, b int) int { - switch op { - case '/': - return s.divServer.do(a, b) - case '*': - return s.mulServer.do(a, b) - default: - panic("invalid op") - } -} - -// The app's SubscribeResults method starts sending calculation results to the given -// channel. Subscriptions created through this method are tied to the lifetime of the App -// because they are registered in the scope. -func (s *App) SubscribeResults(op byte, ch chan<- int) event.Subscription { - switch op { - case '/': - return s.scope.Track(s.divServer.results.Subscribe(ch)) - case '*': - return s.scope.Track(s.mulServer.results.Subscribe(ch)) - default: - panic("invalid op") - } -} - -// Stop stops the App, closing all subscriptions created through SubscribeResults. -func (s *App) Stop() { - s.scope.Close() -} - -func ExampleSubscriptionScope() { - // Create the app. - var ( - app App - wg sync.WaitGroup - divs = make(chan int) - muls = make(chan int) - ) - - // Run a subscriber in the background. - divsub := app.SubscribeResults('/', divs) - mulsub := app.SubscribeResults('*', muls) - wg.Add(1) - go func() { - defer wg.Done() - defer fmt.Println("subscriber exited") - defer divsub.Unsubscribe() - defer mulsub.Unsubscribe() - for { - select { - case result := <-divs: - fmt.Println("division happened:", result) - case result := <-muls: - fmt.Println("multiplication happened:", result) - case <-divsub.Err(): - return - case <-mulsub.Err(): - return - } - } - }() - - // Interact with the app. - app.Calc('/', 22, 11) - app.Calc('*', 3, 4) - - // Stop the app. This shuts down the subscriptions, causing the subscriber to exit. - app.Stop() - wg.Wait() - - // Output: - // division happened: 2 - // multiplication happened: 12 - // subscriber exited -} diff --git a/builder/event/example_subscription_test.go b/builder/event/example_subscription_test.go deleted file mode 100644 index 5c76b55d9..000000000 --- a/builder/event/example_subscription_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 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 event_test - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/event" -) - -func ExampleNewSubscription() { - // Create a subscription that sends 10 integers on ch. - ch := make(chan int) - sub := event.NewSubscription(func(quit <-chan struct{}) error { - for i := 0; i < 10; i++ { - select { - case ch <- i: - case <-quit: - fmt.Println("unsubscribed") - return nil - } - } - return nil - }) - - // This is the consumer. It reads 5 integers, then aborts the subscription. - // Note that Unsubscribe waits until the producer has shut down. - for i := range ch { - fmt.Println(i) - if i == 4 { - sub.Unsubscribe() - break - } - } - // Output: - // 0 - // 1 - // 2 - // 3 - // 4 - // unsubscribed -} diff --git a/builder/event/example_test.go b/builder/event/example_test.go deleted file mode 100644 index 29938e853..000000000 --- a/builder/event/example_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// 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 event - -import "fmt" - -func ExampleTypeMux() { - type someEvent struct{ I int } - type otherEvent struct{ S string } - type yetAnotherEvent struct{ X, Y int } - - var mux TypeMux - - // Start a subscriber. - done := make(chan struct{}) - sub := mux.Subscribe(someEvent{}, otherEvent{}) - go func() { - for event := range sub.Chan() { - fmt.Printf("Received: %#v\n", event.Data) - } - fmt.Println("done") - close(done) - }() - - // Post some events. - mux.Post(someEvent{5}) - mux.Post(yetAnotherEvent{X: 3, Y: 4}) - mux.Post(someEvent{6}) - mux.Post(otherEvent{"whoa"}) - - // Stop closes all subscription channels. - // The subscriber goroutine will print "done" - // and exit. - mux.Stop() - - // Wait for subscriber to return. - <-done - - // Output: - // Received: event.someEvent{I:5} - // Received: event.someEvent{I:6} - // Received: event.otherEvent{S:"whoa"} - // done -} diff --git a/builder/event/feed.go b/builder/event/feed.go deleted file mode 100644 index d94bd820f..000000000 --- a/builder/event/feed.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2016 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 event - -import ( - "errors" - "reflect" - "sync" -) - -var errBadChannel = errors.New("event: Subscribe argument does not have sendable channel type") - -// Feed implements one-to-many subscriptions where the carrier of events is a channel. -// Values sent to a Feed are delivered to all subscribed channels simultaneously. -// -// Feeds can only be used with a single type. The type is determined by the first Send or -// Subscribe operation. Subsequent calls to these methods panic if the type does not -// match. -// -// The zero value is ready to use. -type Feed struct { - once sync.Once // ensures that init only runs once - sendLock chan struct{} // sendLock has a one-element buffer and is empty when held.It protects sendCases. - removeSub chan interface{} // interrupts Send - sendCases caseList // the active set of select cases used by Send - - // The inbox holds newly subscribed channels until they are added to sendCases. - mu sync.Mutex - inbox caseList - etype reflect.Type -} - -// This is the index of the first actual subscription channel in sendCases. -// sendCases[0] is a SelectRecv case for the removeSub channel. -const firstSubSendCase = 1 - -type feedTypeError struct { - got, want reflect.Type - op string -} - -func (e feedTypeError) Error() string { - return "event: wrong type in " + e.op + " got " + e.got.String() + ", want " + e.want.String() -} - -func (f *Feed) init(etype reflect.Type) { - f.etype = etype - f.removeSub = make(chan interface{}) - f.sendLock = make(chan struct{}, 1) - f.sendLock <- struct{}{} - f.sendCases = caseList{{Chan: reflect.ValueOf(f.removeSub), Dir: reflect.SelectRecv}} -} - -// Subscribe adds a channel to the feed. Future sends will be delivered on the channel -// until the subscription is canceled. All channels added must have the same element type. -// -// The channel should have ample buffer space to avoid blocking other subscribers. -// Slow subscribers are not dropped. -func (f *Feed) Subscribe(channel interface{}) Subscription { - chanval := reflect.ValueOf(channel) - chantyp := chanval.Type() - if chantyp.Kind() != reflect.Chan || chantyp.ChanDir()&reflect.SendDir == 0 { - panic(errBadChannel) - } - sub := &feedSub{feed: f, channel: chanval, err: make(chan error, 1)} - - f.once.Do(func() { f.init(chantyp.Elem()) }) - if f.etype != chantyp.Elem() { - panic(feedTypeError{op: "Subscribe", got: chantyp, want: reflect.ChanOf(reflect.SendDir, f.etype)}) - } - - f.mu.Lock() - defer f.mu.Unlock() - // Add the select case to the inbox. - // The next Send will add it to f.sendCases. - cas := reflect.SelectCase{Dir: reflect.SelectSend, Chan: chanval} - f.inbox = append(f.inbox, cas) - return sub -} - -func (f *Feed) remove(sub *feedSub) { - // Delete from inbox first, which covers channels - // that have not been added to f.sendCases yet. - ch := sub.channel.Interface() - f.mu.Lock() - index := f.inbox.find(ch) - if index != -1 { - f.inbox = f.inbox.delete(index) - f.mu.Unlock() - return - } - f.mu.Unlock() - - select { - case f.removeSub <- ch: - // Send will remove the channel from f.sendCases. - case <-f.sendLock: - // No Send is in progress, delete the channel now that we have the send lock. - f.sendCases = f.sendCases.delete(f.sendCases.find(ch)) - f.sendLock <- struct{}{} - } -} - -// Send delivers to all subscribed channels simultaneously. -// It returns the number of subscribers that the value was sent to. -func (f *Feed) Send(value interface{}) (nsent int) { - rvalue := reflect.ValueOf(value) - - f.once.Do(func() { f.init(rvalue.Type()) }) - if f.etype != rvalue.Type() { - panic(feedTypeError{op: "Send", got: rvalue.Type(), want: f.etype}) - } - - <-f.sendLock - - // Add new cases from the inbox after taking the send lock. - f.mu.Lock() - f.sendCases = append(f.sendCases, f.inbox...) - f.inbox = nil - f.mu.Unlock() - - // Set the sent value on all channels. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = rvalue - } - - // Send until all channels except removeSub have been chosen. 'cases' tracks a prefix - // of sendCases. When a send succeeds, the corresponding case moves to the end of - // 'cases' and it shrinks by one element. - cases := f.sendCases - for { - // Fast path: try sending without blocking before adding to the select set. - // This should usually succeed if subscribers are fast enough and have free - // buffer space. - for i := firstSubSendCase; i < len(cases); i++ { - if cases[i].Chan.TrySend(rvalue) { - nsent++ - cases = cases.deactivate(i) - i-- - } - } - if len(cases) == firstSubSendCase { - break - } - // Select on all the receivers, waiting for them to unblock. - chosen, recv, _ := reflect.Select(cases) - if chosen == 0 /* <-f.removeSub */ { - index := f.sendCases.find(recv.Interface()) - f.sendCases = f.sendCases.delete(index) - if index >= 0 && index < len(cases) { - // Shrink 'cases' too because the removed case was still active. - cases = f.sendCases[:len(cases)-1] - } - } else { - cases = cases.deactivate(chosen) - nsent++ - } - } - - // Forget about the sent value and hand off the send lock. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = reflect.Value{} - } - f.sendLock <- struct{}{} - return nsent -} - -type feedSub struct { - feed *Feed - channel reflect.Value - errOnce sync.Once - err chan error -} - -func (sub *feedSub) Unsubscribe() { - sub.errOnce.Do(func() { - sub.feed.remove(sub) - close(sub.err) - }) -} - -func (sub *feedSub) Err() <-chan error { - return sub.err -} - -type caseList []reflect.SelectCase - -// find returns the index of a case containing the given channel. -func (cs caseList) find(channel interface{}) int { - for i, cas := range cs { - if cas.Chan.Interface() == channel { - return i - } - } - return -1 -} - -// delete removes the given case from cs. -func (cs caseList) delete(index int) caseList { - return append(cs[:index], cs[index+1:]...) -} - -// deactivate moves the case at index into the non-accessible portion of the cs slice. -func (cs caseList) deactivate(index int) caseList { - last := len(cs) - 1 - cs[index], cs[last] = cs[last], cs[index] - return cs[:last] -} - -// func (cs caseList) String() string { -// s := "[" -// for i, cas := range cs { -// if i != 0 { -// s += ", " -// } -// switch cas.Dir { -// case reflect.SelectSend: -// s += fmt.Sprintf("%v<-", cas.Chan.Interface()) -// case reflect.SelectRecv: -// s += fmt.Sprintf("<-%v", cas.Chan.Interface()) -// } -// } -// return s + "]" -// } diff --git a/builder/event/feed_test.go b/builder/event/feed_test.go deleted file mode 100644 index 74e8587a8..000000000 --- a/builder/event/feed_test.go +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright 2016 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 event - -import ( - "errors" - "fmt" - "reflect" - "sync" - "testing" - "time" -) - -func TestFeedPanics(t *testing.T) { - { - var f Feed - f.Send(2) - want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(0)} - if err := checkPanic(want, func() { f.Send(uint64(2)) }); err != nil { - t.Error(err) - } - } - { - var f Feed - ch := make(chan int) - f.Subscribe(ch) - want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(0)} - if err := checkPanic(want, func() { f.Send(uint64(2)) }); err != nil { - t.Error(err) - } - } - { - var f Feed - f.Send(2) - want := feedTypeError{op: "Subscribe", got: reflect.TypeOf(make(chan uint64)), want: reflect.TypeOf(make(chan<- int))} - if err := checkPanic(want, func() { f.Subscribe(make(chan uint64)) }); err != nil { - t.Error(err) - } - } - { - var f Feed - if err := checkPanic(errBadChannel, func() { f.Subscribe(make(<-chan int)) }); err != nil { - t.Error(err) - } - } - { - var f Feed - if err := checkPanic(errBadChannel, func() { f.Subscribe(0) }); err != nil { - t.Error(err) - } - } -} - -func checkPanic(want error, fn func()) (err error) { - defer func() { - panic := recover() - if panic == nil { - err = errors.New("didn't panic") - } else if !reflect.DeepEqual(panic, want) { - err = fmt.Errorf("panicked with wrong error: got %q, want %q", panic, want) - } - }() - fn() - return nil -} - -func TestFeed(t *testing.T) { - var feed Feed - var done, subscribed sync.WaitGroup - subscriber := func(i int) { - defer done.Done() - - subchan := make(chan int) - sub := feed.Subscribe(subchan) - timeout := time.NewTimer(2 * time.Second) - defer timeout.Stop() - subscribed.Done() - - select { - case v := <-subchan: - if v != 1 { - t.Errorf("%d: received value %d, want 1", i, v) - } - case <-timeout.C: - t.Errorf("%d: receive timeout", i) - } - - sub.Unsubscribe() - select { - case _, ok := <-sub.Err(): - if ok { - t.Errorf("%d: error channel not closed after unsubscribe", i) - } - case <-timeout.C: - t.Errorf("%d: unsubscribe timeout", i) - } - } - - const n = 1000 - done.Add(n) - subscribed.Add(n) - for i := 0; i < n; i++ { - go subscriber(i) - } - subscribed.Wait() - if nsent := feed.Send(1); nsent != n { - t.Errorf("first send delivered %d times, want %d", nsent, n) - } - if nsent := feed.Send(2); nsent != 0 { - t.Errorf("second send delivered %d times, want 0", nsent) - } - done.Wait() -} - -func TestFeedSubscribeSameChannel(t *testing.T) { - var ( - feed Feed - done sync.WaitGroup - ch = make(chan int) - sub1 = feed.Subscribe(ch) - sub2 = feed.Subscribe(ch) - _ = feed.Subscribe(ch) - ) - expectSends := func(value, n int) { - if nsent := feed.Send(value); nsent != n { - t.Errorf("send delivered %d times, want %d", nsent, n) - } - done.Done() - } - expectRecv := func(wantValue, n int) { - for i := 0; i < n; i++ { - if v := <-ch; v != wantValue { - t.Errorf("received %d, want %d", v, wantValue) - } - } - } - - done.Add(1) - go expectSends(1, 3) - expectRecv(1, 3) - done.Wait() - - sub1.Unsubscribe() - - done.Add(1) - go expectSends(2, 2) - expectRecv(2, 2) - done.Wait() - - sub2.Unsubscribe() - - done.Add(1) - go expectSends(3, 1) - expectRecv(3, 1) - done.Wait() -} - -func TestFeedSubscribeBlockedPost(t *testing.T) { - var ( - feed Feed - nsends = 2000 - ch1 = make(chan int) - ch2 = make(chan int) - wg sync.WaitGroup - ) - defer wg.Wait() - - feed.Subscribe(ch1) - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - - sub2 := feed.Subscribe(ch2) - defer sub2.Unsubscribe() - - // We're done when ch1 has received N times. - // The number of receives on ch2 depends on scheduling. - for i := 0; i < nsends; { - select { - case <-ch1: - i++ - case <-ch2: - } - } -} - -func TestFeedUnsubscribeBlockedPost(t *testing.T) { - var ( - feed Feed - nsends = 200 - chans = make([]chan int, 2000) - subs = make([]Subscription, len(chans)) - bchan = make(chan int) - bsub = feed.Subscribe(bchan) - wg sync.WaitGroup - ) - for i := range chans { - chans[i] = make(chan int, nsends) - } - - // Queue up some Sends. None of these can make progress while bchan isn't read. - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - // Subscribe the other channels. - for i, ch := range chans { - subs[i] = feed.Subscribe(ch) - } - // Unsubscribe them again. - for _, sub := range subs { - sub.Unsubscribe() - } - // Unblock the Sends. - bsub.Unsubscribe() - wg.Wait() -} - -// Checks that unsubscribing a channel during Send works even if that -// channel has already been sent on. -func TestFeedUnsubscribeSentChan(t *testing.T) { - var ( - feed Feed - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch2) - wg sync.WaitGroup - ) - defer sub2.Unsubscribe() - - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - - // Wait for the value on ch1. - <-ch1 - // Unsubscribe ch1, removing it from the send cases. - sub1.Unsubscribe() - - // Receive ch2, finishing Send. - <-ch2 - wg.Wait() - - // Send again. This should send to ch2 only, so the wait group will unblock - // as soon as a value is received on ch2. - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - <-ch2 - wg.Wait() -} - -func TestFeedUnsubscribeFromInbox(t *testing.T) { - var ( - feed Feed - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch1) - sub3 = feed.Subscribe(ch2) - ) - if len(feed.inbox) != 3 { - t.Errorf("inbox length != 3 after subscribe") - } - if len(feed.sendCases) != 1 { - t.Errorf("sendCases is non-empty after unsubscribe") - } - - sub1.Unsubscribe() - sub2.Unsubscribe() - sub3.Unsubscribe() - if len(feed.inbox) != 0 { - t.Errorf("inbox is non-empty after unsubscribe") - } - if len(feed.sendCases) != 1 { - t.Errorf("sendCases is non-empty after unsubscribe") - } -} - -func BenchmarkFeedSend1000(b *testing.B) { - var ( - done sync.WaitGroup - feed Feed - nsubs = 1000 - ) - subscriber := func(ch <-chan int) { - for i := 0; i < b.N; i++ { - <-ch - } - done.Done() - } - done.Add(nsubs) - for i := 0; i < nsubs; i++ { - ch := make(chan int, 200) - feed.Subscribe(ch) - go subscriber(ch) - } - - // The actual benchmark. - b.ResetTimer() - for i := 0; i < b.N; i++ { - if feed.Send(i) != nsubs { - panic("wrong number of sends") - } - } - - b.StopTimer() - done.Wait() -} diff --git a/builder/event/feedof.go b/builder/event/feedof.go deleted file mode 100644 index 4a24e37f1..000000000 --- a/builder/event/feedof.go +++ /dev/null @@ -1,164 +0,0 @@ -// 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 event - -import ( - "reflect" - "sync" -) - -// FeedOf implements one-to-many subscriptions where the carrier of events is a channel. -// Values sent to a Feed are delivered to all subscribed channels simultaneously. -// -// The zero value is ready to use. -type FeedOf[T any] struct { - once sync.Once // ensures that init only runs once - sendLock chan struct{} // sendLock has a one-element buffer and is empty when held.It protects sendCases. - removeSub chan chan<- T // interrupts Send - sendCases caseList // the active set of select cases used by Send - - // The inbox holds newly subscribed channels until they are added to sendCases. - mu sync.Mutex - inbox caseList -} - -func (f *FeedOf[T]) init() { - f.removeSub = make(chan chan<- T) - f.sendLock = make(chan struct{}, 1) - f.sendLock <- struct{}{} - f.sendCases = caseList{{Chan: reflect.ValueOf(f.removeSub), Dir: reflect.SelectRecv}} -} - -// Subscribe adds a channel to the feed. Future sends will be delivered on the channel -// until the subscription is canceled. -// -// The channel should have ample buffer space to avoid blocking other subscribers. Slow -// subscribers are not dropped. -func (f *FeedOf[T]) Subscribe(channel chan<- T) Subscription { - f.once.Do(f.init) - - chanval := reflect.ValueOf(channel) - sub := &feedOfSub[T]{feed: f, channel: channel, err: make(chan error, 1)} - - // Add the select case to the inbox. - // The next Send will add it to f.sendCases. - f.mu.Lock() - defer f.mu.Unlock() - cas := reflect.SelectCase{Dir: reflect.SelectSend, Chan: chanval} - f.inbox = append(f.inbox, cas) - return sub -} - -func (f *FeedOf[T]) remove(sub *feedOfSub[T]) { - // Delete from inbox first, which covers channels - // that have not been added to f.sendCases yet. - f.mu.Lock() - index := f.inbox.find(sub.channel) - if index != -1 { - f.inbox = f.inbox.delete(index) - f.mu.Unlock() - return - } - f.mu.Unlock() - - select { - case f.removeSub <- sub.channel: - // Send will remove the channel from f.sendCases. - case <-f.sendLock: - // No Send is in progress, delete the channel now that we have the send lock. - f.sendCases = f.sendCases.delete(f.sendCases.find(sub.channel)) - f.sendLock <- struct{}{} - } -} - -// Send delivers to all subscribed channels simultaneously. -// It returns the number of subscribers that the value was sent to. -func (f *FeedOf[T]) Send(value T) (nsent int) { - rvalue := reflect.ValueOf(value) - - f.once.Do(f.init) - <-f.sendLock - - // Add new cases from the inbox after taking the send lock. - f.mu.Lock() - f.sendCases = append(f.sendCases, f.inbox...) - f.inbox = nil - f.mu.Unlock() - - // Set the sent value on all channels. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = rvalue - } - - // Send until all channels except removeSub have been chosen. 'cases' tracks a prefix - // of sendCases. When a send succeeds, the corresponding case moves to the end of - // 'cases' and it shrinks by one element. - cases := f.sendCases - for { - // Fast path: try sending without blocking before adding to the select set. - // This should usually succeed if subscribers are fast enough and have free - // buffer space. - for i := firstSubSendCase; i < len(cases); i++ { - if cases[i].Chan.TrySend(rvalue) { - nsent++ - cases = cases.deactivate(i) - i-- - } - } - if len(cases) == firstSubSendCase { - break - } - // Select on all the receivers, waiting for them to unblock. - chosen, recv, _ := reflect.Select(cases) - if chosen == 0 /* <-f.removeSub */ { - index := f.sendCases.find(recv.Interface()) - f.sendCases = f.sendCases.delete(index) - if index >= 0 && index < len(cases) { - // Shrink 'cases' too because the removed case was still active. - cases = f.sendCases[:len(cases)-1] - } - } else { - cases = cases.deactivate(chosen) - nsent++ - } - } - - // Forget about the sent value and hand off the send lock. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = reflect.Value{} - } - f.sendLock <- struct{}{} - return nsent -} - -type feedOfSub[T any] struct { - feed *FeedOf[T] - channel chan<- T - errOnce sync.Once - err chan error -} - -func (sub *feedOfSub[T]) Unsubscribe() { - sub.errOnce.Do(func() { - sub.feed.remove(sub) - close(sub.err) - }) -} - -func (sub *feedOfSub[T]) Err() <-chan error { - return sub.err -} diff --git a/builder/event/feedof_test.go b/builder/event/feedof_test.go deleted file mode 100644 index 846afc9ee..000000000 --- a/builder/event/feedof_test.go +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2016 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 event - -import ( - "sync" - "testing" - "time" -) - -func TestFeedOf(t *testing.T) { - var feed FeedOf[int] - var done, subscribed sync.WaitGroup - subscriber := func(i int) { - defer done.Done() - - subchan := make(chan int) - sub := feed.Subscribe(subchan) - timeout := time.NewTimer(2 * time.Second) - defer timeout.Stop() - subscribed.Done() - - select { - case v := <-subchan: - if v != 1 { - t.Errorf("%d: received value %d, want 1", i, v) - } - case <-timeout.C: - t.Errorf("%d: receive timeout", i) - } - - sub.Unsubscribe() - select { - case _, ok := <-sub.Err(): - if ok { - t.Errorf("%d: error channel not closed after unsubscribe", i) - } - case <-timeout.C: - t.Errorf("%d: unsubscribe timeout", i) - } - } - - const n = 1000 - done.Add(n) - subscribed.Add(n) - for i := 0; i < n; i++ { - go subscriber(i) - } - subscribed.Wait() - if nsent := feed.Send(1); nsent != n { - t.Errorf("first send delivered %d times, want %d", nsent, n) - } - if nsent := feed.Send(2); nsent != 0 { - t.Errorf("second send delivered %d times, want 0", nsent) - } - done.Wait() -} - -func TestFeedOfSubscribeSameChannel(t *testing.T) { - var ( - feed FeedOf[int] - done sync.WaitGroup - ch = make(chan int) - sub1 = feed.Subscribe(ch) - sub2 = feed.Subscribe(ch) - _ = feed.Subscribe(ch) - ) - expectSends := func(value, n int) { - if nsent := feed.Send(value); nsent != n { - t.Errorf("send delivered %d times, want %d", nsent, n) - } - done.Done() - } - expectRecv := func(wantValue, n int) { - for i := 0; i < n; i++ { - if v := <-ch; v != wantValue { - t.Errorf("received %d, want %d", v, wantValue) - } - } - } - - done.Add(1) - go expectSends(1, 3) - expectRecv(1, 3) - done.Wait() - - sub1.Unsubscribe() - - done.Add(1) - go expectSends(2, 2) - expectRecv(2, 2) - done.Wait() - - sub2.Unsubscribe() - - done.Add(1) - go expectSends(3, 1) - expectRecv(3, 1) - done.Wait() -} - -func TestFeedOfSubscribeBlockedPost(t *testing.T) { - var ( - feed FeedOf[int] - nsends = 2000 - ch1 = make(chan int) - ch2 = make(chan int) - wg sync.WaitGroup - ) - defer wg.Wait() - - feed.Subscribe(ch1) - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - - sub2 := feed.Subscribe(ch2) - defer sub2.Unsubscribe() - - // We're done when ch1 has received N times. - // The number of receives on ch2 depends on scheduling. - for i := 0; i < nsends; { - select { - case <-ch1: - i++ - case <-ch2: - } - } -} - -func TestFeedOfUnsubscribeBlockedPost(t *testing.T) { - var ( - feed FeedOf[int] - nsends = 200 - chans = make([]chan int, 2000) - subs = make([]Subscription, len(chans)) - bchan = make(chan int) - bsub = feed.Subscribe(bchan) - wg sync.WaitGroup - ) - for i := range chans { - chans[i] = make(chan int, nsends) - } - - // Queue up some Sends. None of these can make progress while bchan isn't read. - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - // Subscribe the other channels. - for i, ch := range chans { - subs[i] = feed.Subscribe(ch) - } - // Unsubscribe them again. - for _, sub := range subs { - sub.Unsubscribe() - } - // Unblock the Sends. - bsub.Unsubscribe() - wg.Wait() -} - -// Checks that unsubscribing a channel during Send works even if that -// channel has already been sent on. -func TestFeedOfUnsubscribeSentChan(t *testing.T) { - var ( - feed FeedOf[int] - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch2) - wg sync.WaitGroup - ) - defer sub2.Unsubscribe() - - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - - // Wait for the value on ch1. - <-ch1 - // Unsubscribe ch1, removing it from the send cases. - sub1.Unsubscribe() - - // Receive ch2, finishing Send. - <-ch2 - wg.Wait() - - // Send again. This should send to ch2 only, so the wait group will unblock - // as soon as a value is received on ch2. - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - <-ch2 - wg.Wait() -} - -func TestFeedOfUnsubscribeFromInbox(t *testing.T) { - var ( - feed FeedOf[int] - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch1) - sub3 = feed.Subscribe(ch2) - ) - if len(feed.inbox) != 3 { - t.Errorf("inbox length != 3 after subscribe") - } - if len(feed.sendCases) != 1 { - t.Errorf("sendCases is non-empty after unsubscribe") - } - - sub1.Unsubscribe() - sub2.Unsubscribe() - sub3.Unsubscribe() - if len(feed.inbox) != 0 { - t.Errorf("inbox is non-empty after unsubscribe") - } - if len(feed.sendCases) != 1 { - t.Errorf("sendCases is non-empty after unsubscribe") - } -} - -func BenchmarkFeedOfSend1000(b *testing.B) { - var ( - done sync.WaitGroup - feed FeedOf[int] - nsubs = 1000 - ) - subscriber := func(ch <-chan int) { - for i := 0; i < b.N; i++ { - <-ch - } - done.Done() - } - done.Add(nsubs) - for i := 0; i < nsubs; i++ { - ch := make(chan int, 200) - feed.Subscribe(ch) - go subscriber(ch) - } - - // The actual benchmark. - b.ResetTimer() - for i := 0; i < b.N; i++ { - if feed.Send(i) != nsubs { - panic("wrong number of sends") - } - } - - b.StopTimer() - done.Wait() -} diff --git a/builder/event/multisub.go b/builder/event/multisub.go deleted file mode 100644 index 5c8d2df48..000000000 --- a/builder/event/multisub.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2023 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 event - -// JoinSubscriptions joins multiple subscriptions to be able to track them as -// one entity and collectively cancel them of consume any errors from them. -func JoinSubscriptions(subs ...Subscription) Subscription { - return NewSubscription(func(unsubbed <-chan struct{}) error { - // Unsubscribe all subscriptions before returning - defer func() { - for _, sub := range subs { - sub.Unsubscribe() - } - }() - // Wait for an error on any of the subscriptions and propagate up - errc := make(chan error, len(subs)) - for i := range subs { - go func(sub Subscription) { - select { - case err := <-sub.Err(): - if err != nil { - errc <- err - } - case <-unsubbed: - } - }(subs[i]) - } - - select { - case err := <-errc: - return err - case <-unsubbed: - return nil - } - }) -} diff --git a/builder/event/multisub_test.go b/builder/event/multisub_test.go deleted file mode 100644 index c92bcfae9..000000000 --- a/builder/event/multisub_test.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2023 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 event - -import ( - "testing" - "time" -) - -func TestMultisub(t *testing.T) { - // Create a double subscription and ensure events propagate through - var ( - feed1 Feed - feed2 Feed - ) - sink1 := make(chan int, 1) - sink2 := make(chan int, 1) - - sub1 := feed1.Subscribe(sink1) - sub2 := feed2.Subscribe(sink2) - - sub := JoinSubscriptions(sub1, sub2) - - feed1.Send(1) - select { - case n := <-sink1: - if n != 1 { - t.Errorf("sink 1 delivery mismatch: have %d, want %d", n, 1) - } - default: - t.Error("sink 1 missing delivery") - } - - feed2.Send(2) - select { - case n := <-sink2: - if n != 2 { - t.Errorf("sink 2 delivery mismatch: have %d, want %d", n, 2) - } - default: - t.Error("sink 2 missing delivery") - } - // Unsubscribe and ensure no more events are delivered - sub.Unsubscribe() - select { - case <-sub.Err(): - case <-time.After(50 * time.Millisecond): - t.Error("multisub didn't propagate closure") - } - - feed1.Send(11) - select { - case n := <-sink1: - t.Errorf("sink 1 unexpected delivery: %d", n) - default: - } - - feed2.Send(22) - select { - case n := <-sink2: - t.Errorf("sink 2 unexpected delivery: %d", n) - default: - } -} - -func TestMutisubPartialUnsubscribe(t *testing.T) { - // Create a double subscription but terminate one half, ensuring no error - // is propagated yet up to the outer subscription - var ( - feed1 Feed - feed2 Feed - ) - sink1 := make(chan int, 1) - sink2 := make(chan int, 1) - - sub1 := feed1.Subscribe(sink1) - sub2 := feed2.Subscribe(sink2) - - sub := JoinSubscriptions(sub1, sub2) - - sub1.Unsubscribe() - select { - case <-sub.Err(): - t.Error("multisub propagated closure") - case <-time.After(50 * time.Millisecond): - } - // Ensure that events cross only the second feed - feed1.Send(1) - select { - case n := <-sink1: - t.Errorf("sink 1 unexpected delivery: %d", n) - default: - } - - feed2.Send(2) - select { - case n := <-sink2: - if n != 2 { - t.Errorf("sink 2 delivery mismatch: have %d, want %d", n, 2) - } - default: - t.Error("sink 2 missing delivery") - } - // Unsubscribe and ensure no more events are delivered - sub.Unsubscribe() - select { - case <-sub.Err(): - case <-time.After(50 * time.Millisecond): - t.Error("multisub didn't propagate closure") - } - - feed1.Send(11) - select { - case n := <-sink1: - t.Errorf("sink 1 unexpected delivery: %d", n) - default: - } - - feed2.Send(22) - select { - case n := <-sink2: - t.Errorf("sink 2 unexpected delivery: %d", n) - default: - } -} - -func TestMultisubFullUnsubscribe(t *testing.T) { - // Create a double subscription and terminate the multi sub, ensuring an - // error is propagated up. - var ( - feed1 Feed - feed2 Feed - ) - sink1 := make(chan int, 1) - sink2 := make(chan int, 1) - - sub1 := feed1.Subscribe(sink1) - sub2 := feed2.Subscribe(sink2) - - sub := JoinSubscriptions(sub1, sub2) - sub.Unsubscribe() - select { - case <-sub.Err(): - case <-time.After(50 * time.Millisecond): - t.Error("multisub didn't propagate closure") - } - // Ensure no more events are delivered - feed1.Send(1) - select { - case n := <-sink1: - t.Errorf("sink 1 unexpected delivery: %d", n) - default: - } - - feed2.Send(2) - select { - case n := <-sink2: - t.Errorf("sink 2 unexpected delivery: %d", n) - default: - } -} diff --git a/builder/event/subscription.go b/builder/event/subscription.go deleted file mode 100644 index 07e059c6d..000000000 --- a/builder/event/subscription.go +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2016 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 event - -import ( - "context" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common/mclock" -) - -// Subscription represents a stream of events. The carrier of the events is typically a -// channel, but isn't part of the interface. -// -// Subscriptions can fail while established. Failures are reported through an error -// channel. It receives a value if there is an issue with the subscription (e.g. the -// network connection delivering the events has been closed). Only one value will ever be -// sent. -// -// The error channel is closed when the subscription ends successfully (i.e. when the -// source of events is closed). It is also closed when Unsubscribe is called. -// -// The Unsubscribe method cancels the sending of events. You must call Unsubscribe in all -// cases to ensure that resources related to the subscription are released. It can be -// called any number of times. -type Subscription interface { - Err() <-chan error // returns the error channel - Unsubscribe() // cancels sending of events, closing the error channel -} - -// NewSubscription runs a producer function as a subscription in a new goroutine. The -// channel given to the producer is closed when Unsubscribe is called. If fn returns an -// error, it is sent on the subscription's error channel. -func NewSubscription(producer func(<-chan struct{}) error) Subscription { - s := &funcSub{unsub: make(chan struct{}), err: make(chan error, 1)} - go func() { - defer close(s.err) - err := producer(s.unsub) - s.mu.Lock() - defer s.mu.Unlock() - if !s.unsubscribed { - if err != nil { - s.err <- err - } - s.unsubscribed = true - } - }() - return s -} - -type funcSub struct { - unsub chan struct{} - err chan error - mu sync.Mutex - unsubscribed bool -} - -func (s *funcSub) Unsubscribe() { - s.mu.Lock() - if s.unsubscribed { - s.mu.Unlock() - return - } - s.unsubscribed = true - close(s.unsub) - s.mu.Unlock() - // Wait for producer shutdown. - <-s.err -} - -func (s *funcSub) Err() <-chan error { - return s.err -} - -// Resubscribe calls fn repeatedly to keep a subscription established. When the -// subscription is established, Resubscribe waits for it to fail and calls fn again. This -// process repeats until Unsubscribe is called or the active subscription ends -// successfully. -// -// Resubscribe applies backoff between calls to fn. The time between calls is adapted -// based on the error rate, but will never exceed backoffMax. -func Resubscribe(backoffMax time.Duration, fn ResubscribeFunc) Subscription { - return ResubscribeErr(backoffMax, func(ctx context.Context, _ error) (Subscription, error) { - return fn(ctx) - }) -} - -// A ResubscribeFunc attempts to establish a subscription. -type ResubscribeFunc func(context.Context) (Subscription, error) - -// ResubscribeErr calls fn repeatedly to keep a subscription established. When the -// subscription is established, ResubscribeErr waits for it to fail and calls fn again. This -// process repeats until Unsubscribe is called or the active subscription ends -// successfully. -// -// The difference between Resubscribe and ResubscribeErr is that with ResubscribeErr, -// the error of the failing subscription is available to the callback for logging -// purposes. -// -// ResubscribeErr applies backoff between calls to fn. The time between calls is adapted -// based on the error rate, but will never exceed backoffMax. -func ResubscribeErr(backoffMax time.Duration, fn ResubscribeErrFunc) Subscription { - s := &resubscribeSub{ - waitTime: backoffMax / 10, - backoffMax: backoffMax, - fn: fn, - err: make(chan error), - unsub: make(chan struct{}, 1), - } - go s.loop() - return s -} - -// A ResubscribeErrFunc attempts to establish a subscription. -// For every call but the first, the second argument to this function is -// the error that occurred with the previous subscription. -type ResubscribeErrFunc func(context.Context, error) (Subscription, error) - -type resubscribeSub struct { - fn ResubscribeErrFunc - err chan error - unsub chan struct{} - unsubOnce sync.Once - lastTry mclock.AbsTime - lastSubErr error - waitTime, backoffMax time.Duration -} - -func (s *resubscribeSub) Unsubscribe() { - s.unsubOnce.Do(func() { - s.unsub <- struct{}{} - <-s.err - }) -} - -func (s *resubscribeSub) Err() <-chan error { - return s.err -} - -func (s *resubscribeSub) loop() { - defer close(s.err) - var done bool - for !done { - sub := s.subscribe() - if sub == nil { - break - } - done = s.waitForError(sub) - sub.Unsubscribe() - } -} - -func (s *resubscribeSub) subscribe() Subscription { - subscribed := make(chan error) - var sub Subscription - for { - s.lastTry = mclock.Now() - ctx, cancel := context.WithCancel(context.Background()) - go func() { - rsub, err := s.fn(ctx, s.lastSubErr) - sub = rsub - subscribed <- err - }() - select { - case err := <-subscribed: - cancel() - if err == nil { - if sub == nil { - panic("event: ResubscribeFunc returned nil subscription and no error") - } - return sub - } - // Subscribing failed, wait before launching the next try. - if s.backoffWait() { - return nil // unsubscribed during wait - } - case <-s.unsub: - cancel() - <-subscribed // avoid leaking the s.fn goroutine. - return nil - } - } -} - -func (s *resubscribeSub) waitForError(sub Subscription) bool { - defer sub.Unsubscribe() - select { - case err := <-sub.Err(): - s.lastSubErr = err - return err == nil - case <-s.unsub: - return true - } -} - -func (s *resubscribeSub) backoffWait() bool { - if time.Duration(mclock.Now()-s.lastTry) > s.backoffMax { - s.waitTime = s.backoffMax / 10 - } else { - s.waitTime *= 2 - if s.waitTime > s.backoffMax { - s.waitTime = s.backoffMax - } - } - - t := time.NewTimer(s.waitTime) - defer t.Stop() - select { - case <-t.C: - return false - case <-s.unsub: - return true - } -} - -// SubscriptionScope provides a facility to unsubscribe multiple subscriptions at once. -// -// For code that handle more than one subscription, a scope can be used to conveniently -// unsubscribe all of them with a single call. The example demonstrates a typical use in a -// larger program. -// -// The zero value is ready to use. -type SubscriptionScope struct { - mu sync.Mutex - subs map[*scopeSub]struct{} - closed bool -} - -type scopeSub struct { - sc *SubscriptionScope - s Subscription -} - -// Track starts tracking a subscription. If the scope is closed, Track returns nil. The -// returned subscription is a wrapper. Unsubscribing the wrapper removes it from the -// scope. -func (sc *SubscriptionScope) Track(s Subscription) Subscription { - sc.mu.Lock() - defer sc.mu.Unlock() - if sc.closed { - return nil - } - if sc.subs == nil { - sc.subs = make(map[*scopeSub]struct{}) - } - ss := &scopeSub{sc, s} - sc.subs[ss] = struct{}{} - return ss -} - -// Close calls Unsubscribe on all tracked subscriptions and prevents further additions to -// the tracked set. Calls to Track after Close return nil. -func (sc *SubscriptionScope) Close() { - sc.mu.Lock() - defer sc.mu.Unlock() - if sc.closed { - return - } - sc.closed = true - for s := range sc.subs { - s.s.Unsubscribe() - } - sc.subs = nil -} - -// Count returns the number of tracked subscriptions. -// It is meant to be used for debugging. -func (sc *SubscriptionScope) Count() int { - sc.mu.Lock() - defer sc.mu.Unlock() - return len(sc.subs) -} - -func (s *scopeSub) Unsubscribe() { - s.s.Unsubscribe() - s.sc.mu.Lock() - defer s.sc.mu.Unlock() - delete(s.sc.subs, s) -} - -func (s *scopeSub) Err() <-chan error { - return s.s.Err() -} diff --git a/builder/event/subscription_test.go b/builder/event/subscription_test.go deleted file mode 100644 index 743d0bf67..000000000 --- a/builder/event/subscription_test.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2016 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 event - -import ( - "context" - "errors" - "fmt" - "reflect" - "testing" - "time" -) - -var errInts = errors.New("error in subscribeInts") - -func subscribeInts(max, fail int, c chan<- int) Subscription { - return NewSubscription(func(quit <-chan struct{}) error { - for i := 0; i < max; i++ { - if i >= fail { - return errInts - } - select { - case c <- i: - case <-quit: - return nil - } - } - return nil - }) -} - -func TestNewSubscriptionError(t *testing.T) { - t.Parallel() - - channel := make(chan int) - sub := subscribeInts(10, 2, channel) -loop: - for want := 0; want < 10; want++ { - select { - case got := <-channel: - if got != want { - t.Fatalf("wrong int %d, want %d", got, want) - } - case err := <-sub.Err(): - if err != errInts { - t.Fatalf("wrong error: got %q, want %q", err, errInts) - } - if want != 2 { - t.Fatalf("got errInts at int %d, should be received at 2", want) - } - break loop - } - } - sub.Unsubscribe() - - err, ok := <-sub.Err() - if err != nil { - t.Fatal("got non-nil error after Unsubscribe") - } - if ok { - t.Fatal("channel still open after Unsubscribe") - } -} - -func TestResubscribe(t *testing.T) { - t.Parallel() - - var i int - nfails := 6 - sub := Resubscribe(100*time.Millisecond, func(ctx context.Context) (Subscription, error) { - // fmt.Printf("call #%d @ %v\n", i, time.Now()) - i++ - if i == 2 { - // Delay the second failure a bit to reset the resubscribe interval. - time.Sleep(200 * time.Millisecond) - } - if i < nfails { - return nil, errors.New("oops") - } - sub := NewSubscription(func(unsubscribed <-chan struct{}) error { return nil }) - return sub, nil - }) - - <-sub.Err() - if i != nfails { - t.Fatalf("resubscribe function called %d times, want %d times", i, nfails) - } -} - -func TestResubscribeAbort(t *testing.T) { - t.Parallel() - - done := make(chan error, 1) - sub := Resubscribe(0, func(ctx context.Context) (Subscription, error) { - select { - case <-ctx.Done(): - done <- nil - case <-time.After(2 * time.Second): - done <- errors.New("context given to resubscribe function not canceled within 2s") - } - return nil, nil - }) - - sub.Unsubscribe() - if err := <-done; err != nil { - t.Fatal(err) - } -} - -func TestResubscribeWithErrorHandler(t *testing.T) { - t.Parallel() - - var i int - nfails := 6 - subErrs := make([]string, 0) - sub := ResubscribeErr(100*time.Millisecond, func(ctx context.Context, lastErr error) (Subscription, error) { - i++ - var lastErrVal string - if lastErr != nil { - lastErrVal = lastErr.Error() - } - subErrs = append(subErrs, lastErrVal) - sub := NewSubscription(func(unsubscribed <-chan struct{}) error { - if i < nfails { - return fmt.Errorf("err-%v", i) - } else { - return nil - } - }) - return sub, nil - }) - - <-sub.Err() - if i != nfails { - t.Fatalf("resubscribe function called %d times, want %d times", i, nfails) - } - - expectedSubErrs := []string{"", "err-1", "err-2", "err-3", "err-4", "err-5"} - if !reflect.DeepEqual(subErrs, expectedSubErrs) { - t.Fatalf("unexpected subscription errors %v, want %v", subErrs, expectedSubErrs) - } -} - -func TestResubscribeWithCompletedSubscription(t *testing.T) { - t.Parallel() - - quitProducerAck := make(chan struct{}) - quitProducer := make(chan struct{}) - - sub := ResubscribeErr(100*time.Millisecond, func(ctx context.Context, lastErr error) (Subscription, error) { - return NewSubscription(func(unsubscribed <-chan struct{}) error { - select { - case <-quitProducer: - quitProducerAck <- struct{}{} - return nil - case <-unsubscribed: - return nil - } - }), nil - }) - - // Ensure producer has started and exited before Unsubscribe - close(quitProducer) - <-quitProducerAck - sub.Unsubscribe() -} diff --git a/builder/flashbotsextra/cmd/bundle_fetcher.go b/builder/flashbotsextra/cmd/bundle_fetcher.go deleted file mode 100644 index eec01acf6..000000000 --- a/builder/flashbotsextra/cmd/bundle_fetcher.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "time" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/flashbotsextra" - "github.com/ethereum/go-ethereum/log" -) - -func main() { - // Test bundle fetcher - // log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - mevBundleCh := make(chan []types.MevBundle) - blockNumCh := make(chan int64) - db, err := flashbotsextra.NewDatabaseService("postgres://postgres:postgres@localhost:5432/test?sslmode=disable") - if err != nil { - panic(err) - } - bundleFetcher := flashbotsextra.NewBundleFetcher(nil, db, blockNumCh, mevBundleCh, false) - - go bundleFetcher.Run() - log.Info("waiting for mev bundles") - go func() { - blockNum := []int64{15232009, 15232008, 15232010} - for _, num := range blockNum { - <-time.After(time.Second) - blockNumCh <- num - } - }() - for bundles := range mevBundleCh { - for _, bundle := range bundles { - log.Info("bundle info", "blockNum", bundle.BlockNumber, "txsLength", len(bundle.Txs)) - } - } -} diff --git a/builder/flashbotsextra/database.go b/builder/flashbotsextra/database.go deleted file mode 100644 index 7d7a92991..000000000 --- a/builder/flashbotsextra/database.go +++ /dev/null @@ -1,115 +0,0 @@ -package flashbotsextra - -import ( - "context" - "math/big" - "time" - - apiv1 "github.com/attestantio/go-builder-client/api/v1" - builderApiV1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/jmoiron/sqlx" - _ "github.com/lib/pq" -) - -const ( - highPrioLimitSize = 500 - lowPrioLimitSize = 100 -) - -type BlockConsumer interface { - ConsumeBuiltBlock(block *types.Block, blockValue *big.Int, OrdersClosedAt time.Time, sealedAt time.Time, commitedBundles []types.SimulatedBundle, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle, bidTrace *builderApiV1.BidTrace) error -} -type IDatabaseService interface { - GetPriorityBundles(ctx context.Context, blockNum int64, isHighPrio bool) ([]DbBundle, error) - GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error) -} - -type NilDbService struct{} - -func (NilDbService) ConsumeBuiltBlock(block *types.Block, blockValue *big.Int, OrdersClosedAt time.Time, sealedAt time.Time, commitedBundles []types.SimulatedBundle, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle, bidTrace *apiv1.BidTrace) error { - return nil -} - -func (NilDbService) GetPriorityBundles(ctx context.Context, blockNum int64, isHighPrio bool) ([]DbBundle, error) { - return []DbBundle{}, nil -} - -func (NilDbService) GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error) { - return []types.LatestUuidBundle{}, nil -} - -type DatabaseService struct { - db *sqlx.DB - - insertMissingBundleStmt *sqlx.NamedStmt - fetchPrioBundlesStmt *sqlx.NamedStmt - fetchGetLatestUuidBundlesStmt *sqlx.NamedStmt -} - -func NewDatabaseService(postgresDSN string) (*DatabaseService, error) { - db, err := sqlx.Connect("postgres", postgresDSN) - if err != nil { - return nil, err - } - - insertMissingBundleStmt, err := db.PrepareNamed("insert into bundles (bundle_hash, param_signed_txs, param_block_number, param_timestamp, received_timestamp, param_reverting_tx_hashes, coinbase_diff, total_gas_used, state_block_number, gas_fees, eth_sent_to_coinbase, bundle_uuid) values (:bundle_hash, :param_signed_txs, :param_block_number, :param_timestamp, :received_timestamp, :param_reverting_tx_hashes, :coinbase_diff, :total_gas_used, :state_block_number, :gas_fees, :eth_sent_to_coinbase, :bundle_uuid) on conflict do nothing returning id") - if err != nil { - return nil, err - } - - fetchPrioBundlesStmt, err := db.PrepareNamed("select bundle_hash, param_signed_txs, param_block_number, param_timestamp, received_timestamp, param_reverting_tx_hashes, coinbase_diff, total_gas_used, state_block_number, gas_fees, eth_sent_to_coinbase, bundle_uuid from bundles where is_high_prio = :is_high_prio and coinbase_diff*1e18/total_gas_used > 1000000000 and param_block_number = :param_block_number order by coinbase_diff/total_gas_used DESC limit :limit") - if err != nil { - return nil, err - } - - fetchGetLatestUuidBundlesStmt, err := db.PrepareNamed("select replacement_uuid, signing_address, bundle_hash, bundle_uuid from latest_uuid_bundle where target_block_number = :target_block_number") - if err != nil { - return nil, err - } - - return &DatabaseService{ - db: db, - insertMissingBundleStmt: insertMissingBundleStmt, - fetchPrioBundlesStmt: fetchPrioBundlesStmt, - fetchGetLatestUuidBundlesStmt: fetchGetLatestUuidBundlesStmt, - }, nil -} - -func Min(l, r int) int { - if l < r { - return l - } - return r -} - -func (ds *DatabaseService) GetPriorityBundles(ctx context.Context, blockNum int64, isHighPrio bool) ([]DbBundle, error) { - var bundles []DbBundle - arg := map[string]interface{}{"param_block_number": uint64(blockNum), "is_high_prio": isHighPrio, "limit": lowPrioLimitSize} - if isHighPrio { - arg["limit"] = highPrioLimitSize - } - if err := ds.fetchPrioBundlesStmt.SelectContext(ctx, &bundles, arg); err != nil { - return nil, err - } - return bundles, nil -} - -func (ds *DatabaseService) GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error) { - var dstLatestBundles []DbLatestUuidBundle - kwArg := map[string]interface{}{"target_block_number": blockNum} - if err := ds.fetchGetLatestUuidBundlesStmt.SelectContext(ctx, &dstLatestBundles, kwArg); err != nil { - return nil, err - } - latestBundles := make([]types.LatestUuidBundle, 0, len(dstLatestBundles)) - for _, dbLub := range dstLatestBundles { - latestBundles = append(latestBundles, types.LatestUuidBundle{ - Uuid: dbLub.Uuid, - SigningAddress: common.HexToAddress(dbLub.SigningAddress), - BundleHash: common.HexToHash(dbLub.BundleHash), - BundleUUID: dbLub.BundleUUID, - }) - } - return latestBundles, nil -} diff --git a/builder/flashbotsextra/database_test.go b/builder/flashbotsextra/database_test.go deleted file mode 100644 index ab5a6ba2f..000000000 --- a/builder/flashbotsextra/database_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package flashbotsextra - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" -) - -func simpleTx(nonce uint64) *types.Transaction { - value := big.NewInt(1000000000000000) // in wei (0.001 eth) - gasLimit := uint64(21000) // in units - gasPrice := big.NewInt(1000000000) - - toAddress := common.HexToAddress("0x7777492a736CD894Cb12DFE5e944047499AEF7a0") - var data []byte - return types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: &toAddress, - Value: value, - Gas: gasLimit, - GasPrice: gasPrice, - Data: data, - }) -} - -func TestBundleUUIDHash(t *testing.T) { - tx1 := simpleTx(1) - tx2 := simpleTx(2) - bts1, err := tx1.MarshalBinary() - require.Nil(t, err) - bts2, err := tx2.MarshalBinary() - require.Nil(t, err) - _, _ = bts1, bts2 - t.Run("no reverts", func(t *testing.T) { - b := types.MevBundle{ - BlockNumber: big.NewInt(1), - Hash: common.HexToHash("0x135a7f22459b2102d51de2d6704512a03e1e2d2059c34bcbb659f4ba65e9f92c"), - } - - require.Equal(t, "5171315f-6ba4-52b2-866e-e2390d422d81", b.ComputeUUID().String()) - }) - t.Run("one revert", func(t *testing.T) { - b := types.MevBundle{ - BlockNumber: big.NewInt(1), - Hash: common.HexToHash("0x135a7f22459b2102d51de2d6704512a03e1e2d2059c34bcbb659f4ba65e9f92c"), - RevertingTxHashes: []common.Hash{ - tx1.Hash(), - }, - } - - require.Equal(t, "49dada39-6db2-500e-ae59-6cc18b2c19e0", b.ComputeUUID().String()) - }) -} diff --git a/builder/flashbotsextra/database_types.go b/builder/flashbotsextra/database_types.go deleted file mode 100644 index 866609d80..000000000 --- a/builder/flashbotsextra/database_types.go +++ /dev/null @@ -1,64 +0,0 @@ -package flashbotsextra - -import ( - "time" - - "github.com/google/uuid" -) - -type BuiltBlock struct { - BlockId uint64 `db:"block_id"` - BlockNumber uint64 `db:"block_number"` - Profit string `db:"profit"` - Slot uint64 `db:"slot"` - Hash string `db:"hash"` - GasLimit uint64 `db:"gas_limit"` - GasUsed uint64 `db:"gas_used"` - BaseFee uint64 `db:"base_fee"` - ParentHash string `db:"parent_hash"` - ProposerPubkey string `db:"proposer_pubkey"` - ProposerFeeRecipient string `db:"proposer_fee_recipient"` - BuilderPubkey string `db:"builder_pubkey"` - Timestamp uint64 `db:"timestamp"` - TimestampDatetime time.Time `db:"timestamp_datetime"` - OrdersClosedAt time.Time `db:"orders_closed_at"` - SealedAt time.Time `db:"sealed_at"` -} - -type BuiltBlockBundle struct { - BlockId uint64 `db:"block_id"` - BundleId *uint64 `db:"bundle_id"` - BlockNumber uint64 `db:"block_number"` - BundleHash string `db:"bundle_hash"` -} - -type DbBundle struct { - DbId uint64 `db:"id"` - BundleHash string `db:"bundle_hash"` - BundleUUID uuid.UUID `db:"bundle_uuid"` - - ParamSignedTxs string `db:"param_signed_txs"` - ParamBlockNumber uint64 `db:"param_block_number"` - ParamTimestamp *uint64 `db:"param_timestamp"` - ReceivedTimestamp time.Time `db:"received_timestamp"` - ParamRevertingTxHashes *string `db:"param_reverting_tx_hashes"` - - CoinbaseDiff string `db:"coinbase_diff"` - TotalGasUsed uint64 `db:"total_gas_used"` - StateBlockNumber uint64 `db:"state_block_number"` - GasFees string `db:"gas_fees"` - EthSentToCoinbase string `db:"eth_sent_to_coinbase"` -} - -type DbLatestUuidBundle struct { - Uuid uuid.UUID `db:"replacement_uuid"` - SigningAddress string `db:"signing_address"` - BundleHash string `db:"bundle_hash"` - BundleUUID uuid.UUID `db:"bundle_uuid"` -} - -type DbUsedSBundle struct { - BlockId uint64 `db:"block_id"` - Hash []byte `db:"hash"` - Inserted bool `db:"inserted"` -} diff --git a/builder/flashbotsextra/fetcher.go b/builder/flashbotsextra/fetcher.go deleted file mode 100644 index 9b966dc7e..000000000 --- a/builder/flashbotsextra/fetcher.go +++ /dev/null @@ -1,171 +0,0 @@ -package flashbotsextra - -import ( - "context" - "errors" - "math/big" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/log" - "golang.org/x/crypto/sha3" -) - -type Fetcher interface { - Run() error -} - -type bundleFetcher struct { - db IDatabaseService - backend *eth.Ethereum - blockNumCh chan int64 - bundlesCh chan []types.MevBundle - shouldPushToTxPool bool // Added for testing -} - -func NewBundleFetcher(backend *eth.Ethereum, db IDatabaseService, blockNumCh chan int64, bundlesCh chan []types.MevBundle, shouldPushToTxPool bool) *bundleFetcher { - return &bundleFetcher{ - db: db, - backend: backend, - blockNumCh: blockNumCh, - bundlesCh: bundlesCh, - shouldPushToTxPool: shouldPushToTxPool, - } -} - -func (b *bundleFetcher) Run() { - log.Info("Start bundle fetcher") - if b.shouldPushToTxPool { - eventCh := make(chan core.ChainHeadEvent) - b.backend.BlockChain().SubscribeChainHeadEvent(eventCh) - pushBlockNum := func() { - for currentBlockNum := range eventCh { - b.blockNumCh <- currentBlockNum.Block.Header().Number.Int64() - } - } - addMevBundle := func() { - log.Info("Start receiving mev bundles") - for bundles := range b.bundlesCh { - b.backend.TxPool().AddMevBundles(bundles) - } - } - go pushBlockNum() - go addMevBundle() - } - pushMevBundles := func(bundles []DbBundle) { - mevBundles := make([]types.MevBundle, 0) - for _, bundle := range bundles { - mevBundle, err := b.dbBundleToMevBundle(bundle) - if err != nil { - log.Error("failed to convert db bundle to mev bundle", "err", err) - continue - } - mevBundles = append(mevBundles, *mevBundle) - } - if len(mevBundles) > 0 { - b.bundlesCh <- mevBundles - } - } - go b.fetchAndPush(context.Background(), pushMevBundles) -} - -func (b *bundleFetcher) GetLatestUuidBundles(ctx context.Context, blockNum int64) ([]types.LatestUuidBundle, error) { - return b.db.GetLatestUuidBundles(ctx, blockNum) -} - -func (b *bundleFetcher) fetchAndPush(ctx context.Context, pushMevBundles func(bundles []DbBundle)) { - var currentBlockNum int64 - lowPrioBundleTicker := time.NewTicker(time.Second * 2) - defer lowPrioBundleTicker.Stop() - - for { - select { - case currentBlockNum = <-b.blockNumCh: - ctxH, cancelH := context.WithTimeout(ctx, time.Second*3) - bundles, err := b.db.GetPriorityBundles(ctxH, currentBlockNum+1, true) - cancelH() - if err != nil { - log.Error("failed to fetch high prio bundles", "err", err) - continue - } - log.Debug("Fetching High prio bundles", "size", len(bundles), "currentlyBuiltBlockNum", currentBlockNum+1) - if len(bundles) != 0 { - pushMevBundles(bundles) - } - - case <-lowPrioBundleTicker.C: - if currentBlockNum == 0 { - continue - } - ctxL, cancelL := context.WithTimeout(ctx, time.Second*3) - bundles, err := b.db.GetPriorityBundles(ctxL, currentBlockNum+1, false) - cancelL() - if err != nil { - log.Error("failed to fetch low prio bundles", "err", err) - continue - } - log.Debug("Fetching low prio bundles", "len", len(bundles), "currentlyBuiltBlockNum", currentBlockNum+1) - if len(bundles) != 0 { - pushMevBundles(bundles) - } - case <-ctx.Done(): - close(b.bundlesCh) - return - } - } -} - -func (b *bundleFetcher) dbBundleToMevBundle(arg DbBundle) (*types.MevBundle, error) { - signedTxsStr := strings.Split(arg.ParamSignedTxs, ",") - if len(signedTxsStr) == 0 { - return nil, errors.New("bundle missing txs") - } - if arg.ParamBlockNumber == 0 { - return nil, errors.New("bundle missing blockNumber") - } - - var txs types.Transactions - for _, txStr := range signedTxsStr { - decodedTx, err := hexutil.Decode(txStr) - if err != nil { - log.Error("could not decode bundle tx", "id", arg.DbId, "err", err) - continue - } - tx := new(types.Transaction) - if err := tx.UnmarshalBinary(decodedTx); err != nil { - log.Error("could not unmarshal bundle decoded tx", "id", arg.DbId, "err", err) - continue - } - txs = append(txs, tx) - } - var paramRevertingTxHashes []string - if arg.ParamRevertingTxHashes != nil { - paramRevertingTxHashes = strings.Split(*arg.ParamRevertingTxHashes, ",") - } - revertingTxHashesStrings := paramRevertingTxHashes - revertingTxHashes := make([]common.Hash, len(revertingTxHashesStrings)) - for _, rTxHashStr := range revertingTxHashesStrings { - revertingTxHashes = append(revertingTxHashes, common.HexToHash(rTxHashStr)) - } - var minTimestamp uint64 - if arg.ParamTimestamp != nil { - minTimestamp = *arg.ParamTimestamp - } - bundleHasher := sha3.NewLegacyKeccak256() - for _, tx := range txs { - bundleHasher.Write(tx.Hash().Bytes()) - } - bundleHash := common.BytesToHash(bundleHasher.Sum(nil)) - return &types.MevBundle{ - Txs: txs, - BlockNumber: new(big.Int).SetUint64(arg.ParamBlockNumber), - MinTimestamp: minTimestamp, - RevertingTxHashes: revertingTxHashes, - Hash: bundleHash, - }, nil -} diff --git a/builder/flashbotsextra/rpc_block_service.go b/builder/flashbotsextra/rpc_block_service.go deleted file mode 100644 index e9a3504f4..000000000 --- a/builder/flashbotsextra/rpc_block_service.go +++ /dev/null @@ -1,36 +0,0 @@ -package flashbotsextra - -import ( - "math/big" - "time" - - apiv1 "github.com/attestantio/go-builder-client/api/v1" - "github.com/ethereum/go-ethereum/core/types" - "github.com/flashbots/go-utils/jsonrpc" -) - -type RpcBlockClient struct { - URL string -} - -func NewRpcBlockClient(URL string) *RpcBlockClient { - return &RpcBlockClient{URL: URL} -} - -func (r *RpcBlockClient) ConsumeBuiltBlock(block *types.Block, blockValue *big.Int, ordersClosedAt time.Time, sealedAt time.Time, commitedBundles []types.SimulatedBundle, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle, bidTrace *apiv1.BidTrace) error { - reqrpc := jsonrpc.JSONRPCRequest{ - ID: nil, - Method: "block_consumeBuiltBlock", - Version: "2.0", - Params: []interface{}{block.Header(), blockValue, ordersClosedAt, sealedAt, commitedBundles, allBundles, usedSbundles, bidTrace}, - } - - resp, err := jsonrpc.SendJSONRPCRequest(reqrpc, r.URL) - if err != nil { - return err - } - if resp.Error != nil { - return resp.Error - } - return nil -} diff --git a/builder/go.mod b/builder/go.mod deleted file mode 100644 index dfe1cc158..000000000 --- a/builder/go.mod +++ /dev/null @@ -1,171 +0,0 @@ -module github.com/ethereum/go-ethereum - -go 1.22 - -require ( - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 - github.com/Microsoft/go-winio v0.6.1 - github.com/VictoriaMetrics/fastcache v1.12.1 - github.com/attestantio/go-builder-client v0.4.2 - github.com/attestantio/go-eth2-client v0.19.9-0.20231223220704-fa404f5364c5 - github.com/aws/aws-sdk-go-v2 v1.21.2 - github.com/aws/aws-sdk-go-v2/config v1.18.45 - github.com/aws/aws-sdk-go-v2/credentials v1.13.43 - github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 - github.com/btcsuite/btcd/btcec/v2 v2.2.1 - github.com/cenkalti/backoff/v4 v4.2.1 - github.com/cespare/cp v0.1.0 - github.com/chainbound/shardmap v0.0.2 - github.com/cloudflare/cloudflare-go v0.79.0 - github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 - github.com/consensys/gnark-crypto v0.12.1 - github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 - github.com/crate-crypto/go-kzg-4844 v0.7.0 - github.com/davecgh/go-spew v1.1.1 - github.com/deckarep/golang-set/v2 v2.1.0 - github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 - github.com/ethereum/c-kzg-4844 v0.4.0 - github.com/fatih/color v1.15.0 - github.com/ferranbt/fastssz v0.1.4-0.20240724090034-31cd371f8688 - github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e - github.com/fjl/memsize v0.0.2 - github.com/flashbots/go-boost-utils v1.8.0 - github.com/flashbots/go-utils v0.4.8 - github.com/fsnotify/fsnotify v1.6.0 - github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff - github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 - github.com/gofrs/flock v0.8.1 - github.com/golang-jwt/jwt/v4 v4.5.0 - github.com/golang/protobuf v1.5.3 - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb - github.com/google/gofuzz v1.2.0 - github.com/google/uuid v1.3.0 - github.com/gorilla/handlers v1.5.2 - github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.4.2 - github.com/grafana/pyroscope-go/godeltaprof v0.1.7 - github.com/graph-gophers/graphql-go v1.3.0 - github.com/hashicorp/go-bexpr v0.1.10 - github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 - github.com/holiman/bloomfilter/v2 v2.0.3 - github.com/holiman/uint256 v1.2.4 - github.com/huin/goupnp v1.3.0 - github.com/influxdata/influxdb-client-go/v2 v2.4.0 - github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c - github.com/jackpal/go-nat-pmp v1.0.2 - github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 - github.com/jmoiron/sqlx v1.3.5 - github.com/julienschmidt/httprouter v1.3.0 - github.com/karalabe/usb v0.0.2 - github.com/kylelemons/godebug v1.1.0 - github.com/lib/pq v1.2.0 - github.com/mattn/go-colorable v0.1.13 - github.com/mattn/go-isatty v0.0.20 - github.com/olekukonko/tablewriter v0.0.5 - github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 - github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 - github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc - github.com/rs/cors v1.7.0 - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible - github.com/status-im/keycard-go v0.2.0 - github.com/stretchr/testify v1.8.4 - github.com/supranational/blst v0.3.11 - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/tyler-smith/go-bip39 v1.1.0 - github.com/urfave/cli/v2 v2.25.7 - go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.17.0 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa - golang.org/x/sync v0.5.0 - golang.org/x/sys v0.16.0 - golang.org/x/text v0.14.0 - golang.org/x/time v0.3.0 - golang.org/x/tools v0.15.0 - gopkg.in/natefinch/lumberjack.v2 v2.0.0 - gopkg.in/yaml.v3 v3.0.1 -) - -require ( - github.com/emicklei/dot v1.6.2 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/goccy/go-yaml v1.11.2 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/minio/sha256-simd v1.0.1 // indirect - github.com/naoina/go-stringutil v0.1.0 // indirect - github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.23.0 // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect -) - -require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect - github.com/DataDog/zstd v1.5.2 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect - github.com/aws/smithy-go v1.15.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/deepmap/oapi-codegen v1.6.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.4 // indirect - github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/kilic/bls12-381 v0.1.0 // indirect - github.com/klauspost/compress v1.17.3 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/naoina/toml v0.1.1 - github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pkg/errors v0.9.1 - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect - github.com/rivo/uniseg v0.2.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.18.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect -) diff --git a/builder/go.sum b/builder/go.sum deleted file mode 100644 index 1ab78598f..000000000 --- a/builder/go.sum +++ /dev/null @@ -1,749 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= -github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -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/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/attestantio/go-builder-client v0.4.2 h1:EycfAFqQV+ooc2z6hmTsbuH4TCLknr0aO0nHLHLMpJM= -github.com/attestantio/go-builder-client v0.4.2/go.mod h1:e02i/WO4fjs3/u9oIZEjiC8CK1Qyxy4cpiMMGKx4VqQ= -github.com/attestantio/go-eth2-client v0.19.9-0.20231223220704-fa404f5364c5 h1:ctoIKRi7PM4VM3FsULwYBwlse4fiwx5FWWSQd6FcsrI= -github.com/attestantio/go-eth2-client v0.19.9-0.20231223220704-fa404f5364c5/go.mod h1:mZve1kV9Ctj0I1HH9gdg+MnI8lZ+Cb2EktEtOYrBlsM= -github.com/aws/aws-sdk-go-v2 v1.21.2 h1:+LXZ0sgo8quN9UOKXXzAWRT3FWd4NxeXWOZom9pE7GA= -github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= -github.com/aws/aws-sdk-go-v2/config v1.18.45 h1:Aka9bI7n8ysuwPeFdm77nfbyHCAKQ3z9ghB3S/38zes= -github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= -github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8= -github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 h1:PIktER+hwIG286DqXyvVENjgLTAwGgoeriLDD5C+YlQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 h1:nFBQlGtkbPzp/NjZLuFxRqmT91rLJkgvsEQs68h962Y= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 h1:JRVhO25+r3ar2mKGP7E0LDl8K9/G36gjlqca5iQbaqc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 h1:hze8YsjSh8Wl1rYa1CJpRmXP21BvOBuc76YhW0HsuQ4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 h1:WWZA/I2K4ptBS1kg0kV1JbBtG/umed0vwHRrmcr9z7k= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= -github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 h1:/RPQNjh1sDIezpXaFIkZb7MlXnSyAqjVdAwcJuGYTqg= -github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= -github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 h1:JuPGc7IkOP4AaqcZSIcyqLpFSqBWK32rM9+a1g6u73k= -github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 h1:HFiiRkf1SdaAmV3/BHOFZ9DjFynPHj8G/UIO1lQS+fk= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg= -github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 h1:0BkLfgeDjfZnZ+MhB3ONb01u9pwFYTCZVhlsSSBvlbU= -github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= -github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8= -github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= -github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -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/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chainbound/shardmap v0.0.2 h1:yB1weccdm2vC6dnqzzLwPIvyAnRj7815mJWbkPybiYw= -github.com/chainbound/shardmap v0.0.2/go.mod h1:TBvIzhHyFUbt+oa3UzbijobTUh221st6xIbuki7WzPc= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M= -github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= -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-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -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/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/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/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/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= -github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -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-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= -github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -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/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A= -github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= -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.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/ferranbt/fastssz v0.1.4-0.20240724090034-31cd371f8688 h1:k70X5h1haHaSbpD/9fcjtvAUEVlRlOKtdpvN7Mzhcv4= -github.com/ferranbt/fastssz v0.1.4-0.20240724090034-31cd371f8688/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= -github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= -github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flashbots/go-boost-utils v1.8.0 h1:z3K1hw+Fbl9AGMNQKnK7Bvf0M/rKgjfruAEvra+Z8Mg= -github.com/flashbots/go-boost-utils v1.8.0/go.mod h1:Ry1Rw8Lx5v1rpAR0+IvR4sV10jYAeQaGVM3vRD8mYdM= -github.com/flashbots/go-utils v0.4.8 h1:WDJXryrqShGq4HFe+p1kGjObXSqzT7Sy/+9YvFpr5tM= -github.com/flashbots/go-utils v0.4.8/go.mod h1:dBmSv4Cpqij4xKP50bdisAvFIo4/EgsY97BMpVjPzr0= -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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= -github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getkin/kin-openapi v0.53.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/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/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= -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.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ= -github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -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.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -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/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -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.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -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/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/gofuzz v1.0.0/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/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= -github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/pyroscope-go/godeltaprof v0.1.7 h1:C11j63y7gymiW8VugJ9ZW0pWfxTZugdSJyC48olk5KY= -github.com/grafana/pyroscope-go/godeltaprof v0.1.7/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= -github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/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.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= -github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= -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.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= -github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/go-clone v1.6.0 h1:HMo5uvg4wgfiy5FoGOqlFLQED/VGRm2D9Pi8g1FXPGc= -github.com/huandu/go-clone/generic v1.6.0 h1:Wgmt/fUZ28r16F2Y3APotFD59sHk1p78K0XLdbUYN5U= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -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/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= -github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= -github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= -github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -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/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY= -github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= -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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= -github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -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/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= -github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -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/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/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/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -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/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8= -github.com/naoina/toml v0.1.1/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/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -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.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 h1:cZC+usqsYgHtlBaGulVnZ1hfKAi8iWtujBnRLQE698c= -github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY= -github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw= -github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= -github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o= -github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc/go.mod h1:S8xSOnV3CgpNrWd0GQ/OoQfMtlg2uPRSuTzcSGrzwK8= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -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 v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -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/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/trailofbits/go-fuzz-utils v0.0.0-20210901195358-9657fcfd256c h1:4WU+p200eLYtBsx3M5CKXvkjVdf5SC3W9nMg37y0TFI= -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/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10 h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -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.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -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/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/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.27/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.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= -go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -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/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-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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -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-20181220203305-927f97764cc3/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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20191116160921-f9c825593386/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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/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-20210423082822-04245dca01da/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-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-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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.1.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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-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-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-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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -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-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= -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-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -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/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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= -gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/builder/graphql/graphiql.go b/builder/graphql/graphiql.go deleted file mode 100644 index 823df0c64..000000000 --- a/builder/graphql/graphiql.go +++ /dev/null @@ -1,88 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2016 Muhammed Thanish -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package graphql - -import ( - "encoding/json" - "net/http" - "path/filepath" - - "github.com/ethereum/go-ethereum/graphql/internal/graphiql" - "github.com/ethereum/go-ethereum/log" -) - -// GraphiQL is an in-browser IDE for exploring GraphiQL APIs. -// This handler returns GraphiQL when requested. -// -// For more information, see https://github.com/graphql/graphiql. -type GraphiQL struct{} - -func respOk(w http.ResponseWriter, body []byte, ctype string) { - w.Header().Set("Content-Type", ctype) - w.Header().Set("X-Content-Type-Options", "nosniff") - w.Write(body) -} - -func respErr(w http.ResponseWriter, msg string, code int) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(code) - errMsg, _ := json.Marshal(struct { - Error string - }{Error: msg}) - w.Write(errMsg) -} - -func (h GraphiQL) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - respErr(w, "only GET allowed", http.StatusMethodNotAllowed) - return - } - switch r.URL.Path { - case "/graphql/ui/graphiql.min.css": - data, err := graphiql.Assets.ReadFile(filepath.Base(r.URL.Path)) - if err != nil { - log.Warn("Error loading graphiql asset", "err", err) - respErr(w, "internal error", http.StatusInternalServerError) - return - } - respOk(w, data, "text/css") - case "/graphql/ui/graphiql.min.js", - "/graphql/ui/react.production.min.js", - "/graphql/ui/react-dom.production.min.js": - data, err := graphiql.Assets.ReadFile(filepath.Base(r.URL.Path)) - if err != nil { - log.Warn("Error loading graphiql asset", "err", err) - respErr(w, "internal error", http.StatusInternalServerError) - return - } - respOk(w, data, "application/javascript; charset=utf-8") - default: - data, err := graphiql.Assets.ReadFile("index.html") - if err != nil { - log.Warn("Error loading graphiql asset", "err", err) - respErr(w, "internal error", http.StatusInternalServerError) - return - } - respOk(w, data, "text/html") - } -} diff --git a/builder/graphql/graphql.go b/builder/graphql/graphql.go deleted file mode 100644 index d42c24451..000000000 --- a/builder/graphql/graphql.go +++ /dev/null @@ -1,1547 +0,0 @@ -// 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 graphql provides a GraphQL interface to Ethereum node data. -package graphql - -import ( - "context" - "errors" - "fmt" - "math/big" - "sort" - "strconv" - "strings" - "sync" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/rpc" -) - -var ( - errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") - errInvalidBlockRange = errors.New("invalid from and to block combination: from > to") -) - -type Long int64 - -// ImplementsGraphQLType returns true if Long implements the provided GraphQL type. -func (b Long) ImplementsGraphQLType(name string) bool { return name == "Long" } - -// UnmarshalGraphQL unmarshals the provided GraphQL query data. -func (b *Long) UnmarshalGraphQL(input interface{}) error { - var err error - switch input := input.(type) { - case string: - // uncomment to support hex values - if strings.HasPrefix(input, "0x") { - // apply leniency and support hex representations of longs. - value, err := hexutil.DecodeUint64(input) - *b = Long(value) - return err - } else { - value, err := strconv.ParseInt(input, 10, 64) - *b = Long(value) - return err - } - case int32: - *b = Long(input) - case int64: - *b = Long(input) - case float64: - *b = Long(input) - default: - err = fmt.Errorf("unexpected type %T for Long", input) - } - return err -} - -// Account represents an Ethereum account at a particular block. -type Account struct { - r *Resolver - address common.Address - blockNrOrHash rpc.BlockNumberOrHash -} - -// getState fetches the StateDB object for an account. -func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { - state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) - return state, err -} - -func (a *Account) Address(ctx context.Context) (common.Address, error) { - return a.address, nil -} - -func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) { - state, err := a.getState(ctx) - if err != nil { - return hexutil.Big{}, err - } - balance := state.GetBalance(a.address).ToBig() - if balance == nil { - return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address) - } - return hexutil.Big(*balance), nil -} - -func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { - // Ask transaction pool for the nonce which includes pending transactions - if blockNr, ok := a.blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber { - nonce, err := a.r.backend.GetPoolNonce(ctx, a.address) - if err != nil { - return 0, err - } - return hexutil.Uint64(nonce), nil - } - state, err := a.getState(ctx) - if err != nil { - return 0, err - } - return hexutil.Uint64(state.GetNonce(a.address)), nil -} - -func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) { - state, err := a.getState(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return state.GetCode(a.address), nil -} - -func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) { - state, err := a.getState(ctx) - if err != nil { - return common.Hash{}, err - } - return state.GetState(a.address, args.Slot), nil -} - -// Log represents an individual log message. All arguments are mandatory. -type Log struct { - r *Resolver - transaction *Transaction - log *types.Log -} - -func (l *Log) Transaction(ctx context.Context) *Transaction { - return l.transaction -} - -func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { - return &Account{ - r: l.r, - address: l.log.Address, - blockNrOrHash: args.NumberOrLatest(), - } -} - -func (l *Log) Index(ctx context.Context) hexutil.Uint64 { - return hexutil.Uint64(l.log.Index) -} - -func (l *Log) Topics(ctx context.Context) []common.Hash { - return l.log.Topics -} - -func (l *Log) Data(ctx context.Context) hexutil.Bytes { - return l.log.Data -} - -// AccessTuple represents EIP-2930 -type AccessTuple struct { - address common.Address - storageKeys []common.Hash -} - -func (at *AccessTuple) Address(ctx context.Context) common.Address { - return at.address -} - -func (at *AccessTuple) StorageKeys(ctx context.Context) []common.Hash { - return at.storageKeys -} - -// Withdrawal represents a withdrawal of value from the beacon chain -// by a validator. For details see EIP-4895. -type Withdrawal struct { - index uint64 - validator uint64 - address common.Address - amount uint64 -} - -func (w *Withdrawal) Index(ctx context.Context) hexutil.Uint64 { - return hexutil.Uint64(w.index) -} - -func (w *Withdrawal) Validator(ctx context.Context) hexutil.Uint64 { - return hexutil.Uint64(w.validator) -} - -func (w *Withdrawal) Address(ctx context.Context) common.Address { - return w.address -} - -func (w *Withdrawal) Amount(ctx context.Context) hexutil.Uint64 { - return hexutil.Uint64(w.amount) -} - -// Transaction represents an Ethereum transaction. -// backend and hash are mandatory; all others will be fetched when required. -type Transaction struct { - r *Resolver - hash common.Hash // Must be present after initialization - mu sync.Mutex - // mu protects following resources - tx *types.Transaction - block *Block - index uint64 -} - -// resolve returns the internal transaction object, fetching it if needed. -// It also returns the block the tx belongs to, unless it is a pending tx. -func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block) { - t.mu.Lock() - defer t.mu.Unlock() - if t.tx != nil { - return t.tx, t.block - } - // Try to return an already finalized transaction - found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash) - if found { - t.tx = tx - blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) - t.block = &Block{ - r: t.r, - numberOrHash: &blockNrOrHash, - hash: blockHash, - } - t.index = index - return t.tx, t.block - } - // No finalized transaction, try to retrieve it from the pool - t.tx = t.r.backend.GetPoolTransaction(t.hash) - return t.tx, nil -} - -func (t *Transaction) Hash(ctx context.Context) common.Hash { - return t.hash -} - -func (t *Transaction) InputData(ctx context.Context) hexutil.Bytes { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Bytes{} - } - return tx.Data() -} - -func (t *Transaction) Gas(ctx context.Context) hexutil.Uint64 { - tx, _ := t.resolve(ctx) - if tx == nil { - return 0 - } - return hexutil.Uint64(tx.Gas()) -} - -func (t *Transaction) GasPrice(ctx context.Context) hexutil.Big { - tx, block := t.resolve(ctx) - if tx == nil { - return hexutil.Big{} - } - switch tx.Type() { - case types.DynamicFeeTxType: - if block != nil { - if baseFee, _ := block.BaseFeePerGas(ctx); baseFee != nil { - // price = min(gasTipCap + baseFee, gasFeeCap) - return (hexutil.Big)(*math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee.ToInt()), tx.GasFeeCap())) - } - } - return hexutil.Big(*tx.GasPrice()) - default: - return hexutil.Big(*tx.GasPrice()) - } -} - -func (t *Transaction) EffectiveGasPrice(ctx context.Context) (*hexutil.Big, error) { - tx, block := t.resolve(ctx) - if tx == nil { - return nil, nil - } - // Pending tx - if block == nil { - return nil, nil - } - header, err := block.resolveHeader(ctx) - if err != nil || header == nil { - return nil, err - } - if header.BaseFee == nil { - return (*hexutil.Big)(tx.GasPrice()), nil - } - return (*hexutil.Big)(math.BigMin(new(big.Int).Add(tx.GasTipCap(), header.BaseFee), tx.GasFeeCap())), nil -} - -func (t *Transaction) MaxFeePerGas(ctx context.Context) *hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - switch tx.Type() { - case types.DynamicFeeTxType, types.BlobTxType: - return (*hexutil.Big)(tx.GasFeeCap()) - default: - return nil - } -} - -func (t *Transaction) MaxPriorityFeePerGas(ctx context.Context) *hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - switch tx.Type() { - case types.DynamicFeeTxType, types.BlobTxType: - return (*hexutil.Big)(tx.GasTipCap()) - default: - return nil - } -} - -func (t *Transaction) MaxFeePerBlobGas(ctx context.Context) *hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - return (*hexutil.Big)(tx.BlobGasFeeCap()) -} - -func (t *Transaction) BlobVersionedHashes(ctx context.Context) *[]common.Hash { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - if tx.Type() != types.BlobTxType { - return nil - } - blobHashes := tx.BlobHashes() - return &blobHashes -} - -func (t *Transaction) EffectiveTip(ctx context.Context) (*hexutil.Big, error) { - tx, block := t.resolve(ctx) - if tx == nil { - return nil, nil - } - // Pending tx - if block == nil { - return nil, nil - } - header, err := block.resolveHeader(ctx) - if err != nil || header == nil { - return nil, err - } - if header.BaseFee == nil { - return (*hexutil.Big)(tx.GasPrice()), nil - } - - tip, err := tx.EffectiveGasTip(header.BaseFee) - if err != nil { - return nil, err - } - return (*hexutil.Big)(tip), nil -} - -func (t *Transaction) Value(ctx context.Context) (hexutil.Big, error) { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Big{}, nil - } - if tx.Value() == nil { - return hexutil.Big{}, fmt.Errorf("invalid transaction value %x", t.hash) - } - return hexutil.Big(*tx.Value()), nil -} - -func (t *Transaction) Nonce(ctx context.Context) hexutil.Uint64 { - tx, _ := t.resolve(ctx) - if tx == nil { - return 0 - } - return hexutil.Uint64(tx.Nonce()) -} - -func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) *Account { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - to := tx.To() - if to == nil { - return nil - } - return &Account{ - r: t.r, - address: *to, - blockNrOrHash: args.NumberOrLatest(), - } -} - -func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) *Account { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - signer := types.LatestSigner(t.r.backend.ChainConfig()) - from, _ := types.Sender(signer, tx) - return &Account{ - r: t.r, - address: from, - blockNrOrHash: args.NumberOrLatest(), - } -} - -func (t *Transaction) Block(ctx context.Context) *Block { - _, block := t.resolve(ctx) - return block -} - -func (t *Transaction) Index(ctx context.Context) *hexutil.Uint64 { - _, block := t.resolve(ctx) - // Pending tx - if block == nil { - return nil - } - index := hexutil.Uint64(t.index) - return &index -} - -// getReceipt returns the receipt associated with this transaction, if any. -func (t *Transaction) getReceipt(ctx context.Context) (*types.Receipt, error) { - _, block := t.resolve(ctx) - // Pending tx - if block == nil { - return nil, nil - } - receipts, err := block.resolveReceipts(ctx) - if err != nil { - return nil, err - } - return receipts[t.index], nil -} - -func (t *Transaction) Status(ctx context.Context) (*hexutil.Uint64, error) { - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return nil, err - } - if len(receipt.PostState) != 0 { - return nil, nil - } - ret := hexutil.Uint64(receipt.Status) - return &ret, nil -} - -func (t *Transaction) GasUsed(ctx context.Context) (*hexutil.Uint64, error) { - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return nil, err - } - ret := hexutil.Uint64(receipt.GasUsed) - return &ret, nil -} - -func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*hexutil.Uint64, error) { - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return nil, err - } - ret := hexutil.Uint64(receipt.CumulativeGasUsed) - return &ret, nil -} - -func (t *Transaction) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil, nil - } - if tx.Type() != types.BlobTxType { - return nil, nil - } - - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return nil, err - } - ret := hexutil.Uint64(receipt.BlobGasUsed) - return &ret, nil -} - -func (t *Transaction) BlobGasPrice(ctx context.Context) (*hexutil.Big, error) { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil, nil - } - if tx.Type() != types.BlobTxType { - return nil, nil - } - - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return nil, err - } - ret := (*hexutil.Big)(receipt.BlobGasPrice) - return ret, nil -} - -func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) { - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil || receipt.ContractAddress == (common.Address{}) { - return nil, err - } - return &Account{ - r: t.r, - address: receipt.ContractAddress, - blockNrOrHash: args.NumberOrLatest(), - }, nil -} - -func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) { - _, block := t.resolve(ctx) - // Pending tx - if block == nil { - return nil, nil - } - h, err := block.Hash(ctx) - if err != nil { - return nil, err - } - return t.getLogs(ctx, h) -} - -// getLogs returns log objects for the given tx. -// Assumes block hash is resolved. -func (t *Transaction) getLogs(ctx context.Context, hash common.Hash) (*[]*Log, error) { - var ( - filter = t.r.filterSystem.NewBlockFilter(hash, nil, nil) - logs, err = filter.Logs(ctx) - ) - if err != nil { - return nil, err - } - var ret []*Log - // Select tx logs from all block logs - ix := sort.Search(len(logs), func(i int) bool { return uint64(logs[i].TxIndex) >= t.index }) - for ix < len(logs) && uint64(logs[ix].TxIndex) == t.index { - ret = append(ret, &Log{ - r: t.r, - transaction: t, - log: logs[ix], - }) - ix++ - } - return &ret, nil -} - -func (t *Transaction) Type(ctx context.Context) *hexutil.Uint64 { - tx, _ := t.resolve(ctx) - txType := hexutil.Uint64(tx.Type()) - return &txType -} - -func (t *Transaction) AccessList(ctx context.Context) *[]*AccessTuple { - tx, _ := t.resolve(ctx) - if tx == nil { - return nil - } - accessList := tx.AccessList() - ret := make([]*AccessTuple, 0, len(accessList)) - for _, al := range accessList { - ret = append(ret, &AccessTuple{ - address: al.Address, - storageKeys: al.StorageKeys, - }) - } - return &ret -} - -func (t *Transaction) R(ctx context.Context) hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Big{} - } - _, r, _ := tx.RawSignatureValues() - return hexutil.Big(*r) -} - -func (t *Transaction) S(ctx context.Context) hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Big{} - } - _, _, s := tx.RawSignatureValues() - return hexutil.Big(*s) -} - -func (t *Transaction) V(ctx context.Context) hexutil.Big { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Big{} - } - v, _, _ := tx.RawSignatureValues() - return hexutil.Big(*v) -} - -func (t *Transaction) YParity(ctx context.Context) (*hexutil.Big, error) { - tx, _ := t.resolve(ctx) - if tx == nil || tx.Type() == types.LegacyTxType { - return nil, nil - } - v, _, _ := tx.RawSignatureValues() - ret := hexutil.Big(*v) - return &ret, nil -} - -func (t *Transaction) Raw(ctx context.Context) (hexutil.Bytes, error) { - tx, _ := t.resolve(ctx) - if tx == nil { - return hexutil.Bytes{}, nil - } - return tx.MarshalBinary() -} - -func (t *Transaction) RawReceipt(ctx context.Context) (hexutil.Bytes, error) { - receipt, err := t.getReceipt(ctx) - if err != nil || receipt == nil { - return hexutil.Bytes{}, err - } - return receipt.MarshalBinary() -} - -type BlockType int - -// Block represents an Ethereum block. -// backend, and numberOrHash are mandatory. All other fields are lazily fetched -// when required. -type Block struct { - r *Resolver - numberOrHash *rpc.BlockNumberOrHash // Field resolvers assume numberOrHash is always present - mu sync.Mutex - // mu protects following resources - hash common.Hash // Must be resolved during initialization - header *types.Header - block *types.Block - receipts []*types.Receipt -} - -// resolve returns the internal Block object representing this block, fetching -// it if necessary. -func (b *Block) resolve(ctx context.Context) (*types.Block, error) { - b.mu.Lock() - defer b.mu.Unlock() - if b.block != nil { - return b.block, nil - } - if b.numberOrHash == nil { - latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - b.numberOrHash = &latest - } - var err error - b.block, err = b.r.backend.BlockByNumberOrHash(ctx, *b.numberOrHash) - if b.block != nil { - b.hash = b.block.Hash() - if b.header == nil { - b.header = b.block.Header() - } - } - return b.block, err -} - -// resolveHeader returns the internal Header object for this block, fetching it -// if necessary. Call this function instead of `resolve` unless you need the -// additional data (transactions and uncles). -func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) { - b.mu.Lock() - defer b.mu.Unlock() - if b.header != nil { - return b.header, nil - } - if b.numberOrHash == nil && b.hash == (common.Hash{}) { - return nil, errBlockInvariant - } - var err error - b.header, err = b.r.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash) - if err != nil { - return nil, err - } - if b.hash == (common.Hash{}) { - b.hash = b.header.Hash() - } - return b.header, nil -} - -// resolveReceipts returns the list of receipts for this block, fetching them -// if necessary. -func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) { - b.mu.Lock() - defer b.mu.Unlock() - if b.receipts != nil { - return b.receipts, nil - } - receipts, err := b.r.backend.GetReceipts(ctx, b.hash) - if err != nil { - return nil, err - } - b.receipts = receipts - return receipts, nil -} - -func (b *Block) Number(ctx context.Context) (hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return 0, err - } - - return hexutil.Uint64(header.Number.Uint64()), nil -} - -func (b *Block) Hash(ctx context.Context) (common.Hash, error) { - b.mu.Lock() - defer b.mu.Unlock() - return b.hash, nil -} - -func (b *Block) GasLimit(ctx context.Context) (hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return 0, err - } - return hexutil.Uint64(header.GasLimit), nil -} - -func (b *Block) GasUsed(ctx context.Context) (hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return 0, err - } - return hexutil.Uint64(header.GasUsed), nil -} - -func (b *Block) BaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - if header.BaseFee == nil { - return nil, nil - } - return (*hexutil.Big)(header.BaseFee), nil -} - -func (b *Block) NextBaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - chaincfg := b.r.backend.ChainConfig() - if header.BaseFee == nil { - // Make sure next block doesn't enable EIP-1559 - if !chaincfg.IsLondon(new(big.Int).Add(header.Number, common.Big1)) { - return nil, nil - } - } - nextBaseFee := eip1559.CalcBaseFee(chaincfg, header) - return (*hexutil.Big)(nextBaseFee), nil -} - -func (b *Block) Parent(ctx context.Context) (*Block, error) { - if _, err := b.resolveHeader(ctx); err != nil { - return nil, err - } - if b.header == nil || b.header.Number.Uint64() < 1 { - return nil, nil - } - var ( - num = rpc.BlockNumber(b.header.Number.Uint64() - 1) - hash = b.header.ParentHash - numOrHash = rpc.BlockNumberOrHash{ - BlockNumber: &num, - BlockHash: &hash, - } - ) - return &Block{ - r: b.r, - numberOrHash: &numOrHash, - hash: hash, - }, nil -} - -func (b *Block) Difficulty(ctx context.Context) (hexutil.Big, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return hexutil.Big{}, err - } - return hexutil.Big(*header.Difficulty), nil -} - -func (b *Block) Timestamp(ctx context.Context) (hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return 0, err - } - return hexutil.Uint64(header.Time), nil -} - -func (b *Block) Nonce(ctx context.Context) (hexutil.Bytes, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return header.Nonce[:], nil -} - -func (b *Block) MixHash(ctx context.Context) (common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return common.Hash{}, err - } - return header.MixDigest, nil -} - -func (b *Block) TransactionsRoot(ctx context.Context) (common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return common.Hash{}, err - } - return header.TxHash, nil -} - -func (b *Block) StateRoot(ctx context.Context) (common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return common.Hash{}, err - } - return header.Root, nil -} - -func (b *Block) ReceiptsRoot(ctx context.Context) (common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return common.Hash{}, err - } - return header.ReceiptHash, nil -} - -func (b *Block) OmmerHash(ctx context.Context) (common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return common.Hash{}, err - } - return header.UncleHash, nil -} - -func (b *Block) OmmerCount(ctx context.Context) (*hexutil.Uint64, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - count := hexutil.Uint64(len(block.Uncles())) - return &count, err -} - -func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - ret := make([]*Block, 0, len(block.Uncles())) - for _, uncle := range block.Uncles() { - blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) - ret = append(ret, &Block{ - r: b.r, - numberOrHash: &blockNumberOrHash, - header: uncle, - hash: uncle.Hash(), - }) - } - return &ret, nil -} - -func (b *Block) ExtraData(ctx context.Context) (hexutil.Bytes, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return header.Extra, nil -} - -func (b *Block) LogsBloom(ctx context.Context) (hexutil.Bytes, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return header.Bloom.Bytes(), nil -} - -func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) { - hash, err := b.Hash(ctx) - if err != nil { - return hexutil.Big{}, err - } - td := b.r.backend.GetTd(ctx, hash) - if td == nil { - return hexutil.Big{}, fmt.Errorf("total difficulty not found %x", hash) - } - return hexutil.Big(*td), nil -} - -func (b *Block) RawHeader(ctx context.Context) (hexutil.Bytes, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return rlp.EncodeToBytes(header) -} - -func (b *Block) Raw(ctx context.Context) (hexutil.Bytes, error) { - block, err := b.resolve(ctx) - if err != nil { - return hexutil.Bytes{}, err - } - return rlp.EncodeToBytes(block) -} - -// BlockNumberArgs encapsulates arguments to accessors that specify a block number. -type BlockNumberArgs struct { - // TODO: Ideally we could use input unions to allow the query to specify the - // block parameter by hash, block number, or tag but input unions aren't part of the - // standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488 - Block *Long -} - -// NumberOr returns the provided block number argument, or the "current" block number or hash if none -// was provided. -func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { - if a.Block != nil { - blockNr := rpc.BlockNumber(*a.Block) - return rpc.BlockNumberOrHashWithNumber(blockNr) - } - return current -} - -// NumberOrLatest returns the provided block number argument, or the "latest" block number if none -// was provided. -func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash { - return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) -} - -func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - return &Account{ - r: b.r, - address: header.Coinbase, - blockNrOrHash: args.NumberOrLatest(), - }, nil -} - -func (b *Block) TransactionCount(ctx context.Context) (*hexutil.Uint64, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - count := hexutil.Uint64(len(block.Transactions())) - return &count, err -} - -func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - ret := make([]*Transaction, 0, len(block.Transactions())) - for i, tx := range block.Transactions() { - ret = append(ret, &Transaction{ - r: b.r, - hash: tx.Hash(), - tx: tx, - block: b, - index: uint64(i), - }) - } - return &ret, nil -} - -func (b *Block) TransactionAt(ctx context.Context, args struct{ Index Long }) (*Transaction, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - txs := block.Transactions() - if args.Index < 0 || int(args.Index) >= len(txs) { - return nil, nil - } - tx := txs[args.Index] - return &Transaction{ - r: b.r, - hash: tx.Hash(), - tx: tx, - block: b, - index: uint64(args.Index), - }, nil -} - -func (b *Block) OmmerAt(ctx context.Context, args struct{ Index Long }) (*Block, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - uncles := block.Uncles() - if args.Index < 0 || int(args.Index) >= len(uncles) { - return nil, nil - } - uncle := uncles[args.Index] - blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) - return &Block{ - r: b.r, - numberOrHash: &blockNumberOrHash, - header: uncle, - hash: uncle.Hash(), - }, nil -} - -func (b *Block) WithdrawalsRoot(ctx context.Context) (*common.Hash, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - // Pre-shanghai blocks - if header.WithdrawalsHash == nil { - return nil, nil - } - return header.WithdrawalsHash, nil -} - -func (b *Block) Withdrawals(ctx context.Context) (*[]*Withdrawal, error) { - block, err := b.resolve(ctx) - if err != nil || block == nil { - return nil, err - } - // Pre-shanghai blocks - if block.Header().WithdrawalsHash == nil { - return nil, nil - } - ret := make([]*Withdrawal, 0, len(block.Withdrawals())) - for _, w := range block.Withdrawals() { - ret = append(ret, &Withdrawal{ - index: w.Index, - validator: w.Validator, - address: w.Address, - amount: w.Amount, - }) - } - return &ret, nil -} - -func (b *Block) BlobGasUsed(ctx context.Context) (*hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - if header.BlobGasUsed == nil { - return nil, nil - } - ret := hexutil.Uint64(*header.BlobGasUsed) - return &ret, nil -} - -func (b *Block) ExcessBlobGas(ctx context.Context) (*hexutil.Uint64, error) { - header, err := b.resolveHeader(ctx) - if err != nil { - return nil, err - } - if header.ExcessBlobGas == nil { - return nil, nil - } - ret := hexutil.Uint64(*header.ExcessBlobGas) - return &ret, nil -} - -// BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside -// a block. -type BlockFilterCriteria struct { - Addresses *[]common.Address // restricts matches to events created by specific contracts - - // The Topic list restricts matches to particular event topics. Each event has a list - // of topics. Topics matches a prefix of that list. An empty element slice matches any - // topic. Non-empty elements represent an alternative that matches any of the - // contained topics. - // - // Examples: - // {} or nil matches any topic list - // {{A}} matches topic A in first position - // {{}, {B}} matches any topic in first position, B in second position - // {{A}, {B}} matches topic A in first position, B in second position - // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position - Topics *[][]common.Hash -} - -// runFilter accepts a filter and executes it, returning all its results as -// `Log` objects. -func runFilter(ctx context.Context, r *Resolver, filter *filters.Filter) ([]*Log, error) { - logs, err := filter.Logs(ctx) - if err != nil || logs == nil { - return nil, err - } - ret := make([]*Log, 0, len(logs)) - for _, log := range logs { - ret = append(ret, &Log{ - r: r, - transaction: &Transaction{r: r, hash: log.TxHash}, - log: log, - }) - } - return ret, nil -} - -func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) { - var addresses []common.Address - if args.Filter.Addresses != nil { - addresses = *args.Filter.Addresses - } - var topics [][]common.Hash - if args.Filter.Topics != nil { - topics = *args.Filter.Topics - } - // Construct the range filter - hash, err := b.Hash(ctx) - if err != nil { - return nil, err - } - filter := b.r.filterSystem.NewBlockFilter(hash, addresses, topics) - - // Run the filter and return all the logs - return runFilter(ctx, b.r, filter) -} - -func (b *Block) Account(ctx context.Context, args struct { - Address common.Address -}) (*Account, error) { - return &Account{ - r: b.r, - address: args.Address, - blockNrOrHash: *b.numberOrHash, - }, nil -} - -// CallData encapsulates arguments to `call` or `estimateGas`. -// All arguments are optional. -type CallData struct { - From *common.Address // The Ethereum address the call is from. - To *common.Address // The Ethereum address the call is to. - Gas *Long // The amount of gas provided for the call. - GasPrice *hexutil.Big // The price of each unit of gas, in wei. - MaxFeePerGas *hexutil.Big // The max price of each unit of gas, in wei (1559). - MaxPriorityFeePerGas *hexutil.Big // The max tip of each unit of gas, in wei (1559). - Value *hexutil.Big // The value sent along with the call. - Data *hexutil.Bytes // Any data sent with the call. -} - -// CallResult encapsulates the result of an invocation of the `call` accessor. -type CallResult struct { - data hexutil.Bytes // The return data from the call - gasUsed hexutil.Uint64 // The amount of gas used - status hexutil.Uint64 // The return status of the call - 0 for failure or 1 for success. -} - -func (c *CallResult) Data() hexutil.Bytes { - return c.data -} - -func (c *CallResult) GasUsed() hexutil.Uint64 { - return c.gasUsed -} - -func (c *CallResult) Status() hexutil.Uint64 { - return c.status -} - -func (b *Block) Call(ctx context.Context, args struct { - Data ethapi.TransactionArgs -}) (*CallResult, error) { - result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap()) - if err != nil { - return nil, err - } - status := hexutil.Uint64(1) - if result.Failed() { - status = 0 - } - - return &CallResult{ - data: result.ReturnData, - gasUsed: hexutil.Uint64(result.UsedGas), - status: status, - }, nil -} - -func (b *Block) EstimateGas(ctx context.Context, args struct { - Data ethapi.TransactionArgs -}) (hexutil.Uint64, error) { - return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap()) -} - -type Pending struct { - r *Resolver -} - -func (p *Pending) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { - txs, err := p.r.backend.GetPoolTransactions() - return hexutil.Uint64(len(txs)), err -} - -func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) { - txs, err := p.r.backend.GetPoolTransactions() - if err != nil { - return nil, err - } - ret := make([]*Transaction, 0, len(txs)) - for i, tx := range txs { - ret = append(ret, &Transaction{ - r: p.r, - hash: tx.Hash(), - tx: tx, - index: uint64(i), - }) - } - return &ret, nil -} - -func (p *Pending) Account(ctx context.Context, args struct { - Address common.Address -}) *Account { - pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - return &Account{ - r: p.r, - address: args.Address, - blockNrOrHash: pendingBlockNr, - } -} - -func (p *Pending) Call(ctx context.Context, args struct { - Data ethapi.TransactionArgs -}) (*CallResult, error) { - pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) - result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap()) - if err != nil { - return nil, err - } - status := hexutil.Uint64(1) - if result.Failed() { - status = 0 - } - - return &CallResult{ - data: result.ReturnData, - gasUsed: hexutil.Uint64(result.UsedGas), - status: status, - }, nil -} - -func (p *Pending) EstimateGas(ctx context.Context, args struct { - Data ethapi.TransactionArgs -}) (hexutil.Uint64, error) { - latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap()) -} - -// Resolver is the top-level object in the GraphQL hierarchy. -type Resolver struct { - backend ethapi.Backend - filterSystem *filters.FilterSystem -} - -func (r *Resolver) Block(ctx context.Context, args struct { - Number *Long - Hash *common.Hash -}) (*Block, error) { - if args.Number != nil && args.Hash != nil { - return nil, errors.New("only one of number or hash must be specified") - } - var numberOrHash rpc.BlockNumberOrHash - if args.Number != nil { - if *args.Number < 0 { - return nil, nil - } - number := rpc.BlockNumber(*args.Number) - numberOrHash = rpc.BlockNumberOrHashWithNumber(number) - } else if args.Hash != nil { - numberOrHash = rpc.BlockNumberOrHashWithHash(*args.Hash, false) - } else { - numberOrHash = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) - } - block := &Block{ - r: r, - numberOrHash: &numberOrHash, - } - // Resolve the header, return nil if it doesn't exist. - // Note we don't resolve block directly here since it will require an - // additional network request for light client. - h, err := block.resolveHeader(ctx) - if err != nil { - return nil, err - } else if h == nil { - return nil, nil - } - return block, nil -} - -func (r *Resolver) Blocks(ctx context.Context, args struct { - From *Long - To *Long -}) ([]*Block, error) { - if args.From == nil { - return nil, errors.New("from block number must be specified") - } - from := rpc.BlockNumber(*args.From) - - var to rpc.BlockNumber - if args.To != nil { - to = rpc.BlockNumber(*args.To) - } else { - to = rpc.BlockNumber(r.backend.CurrentBlock().Number.Int64()) - } - if to < from { - return nil, errInvalidBlockRange - } - var ret []*Block - for i := from; i <= to; i++ { - numberOrHash := rpc.BlockNumberOrHashWithNumber(i) - block := &Block{ - r: r, - numberOrHash: &numberOrHash, - } - // Resolve the header to check for existence. - // Note we don't resolve block directly here since it will require an - // additional network request for light client. - h, err := block.resolveHeader(ctx) - if err != nil { - return nil, err - } else if h == nil { - // Blocks after must be non-existent too, break. - break - } - ret = append(ret, block) - if err := ctx.Err(); err != nil { - return nil, err - } - } - return ret, nil -} - -func (r *Resolver) Pending(ctx context.Context) *Pending { - return &Pending{r} -} - -func (r *Resolver) Transaction(ctx context.Context, args struct{ Hash common.Hash }) *Transaction { - tx := &Transaction{ - r: r, - hash: args.Hash, - } - // Resolve the transaction; if it doesn't exist, return nil. - t, _ := tx.resolve(ctx) - if t == nil { - return nil - } - return tx -} - -func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hexutil.Bytes }) (common.Hash, error) { - tx := new(types.Transaction) - if err := tx.UnmarshalBinary(args.Data); err != nil { - return common.Hash{}, err - } - hash, err := ethapi.SubmitTransaction(ctx, r.backend, tx, false) - return hash, err -} - -// FilterCriteria encapsulates the arguments to `logs` on the root resolver object. -type FilterCriteria struct { - FromBlock *Long // beginning of the queried range, nil means genesis block - ToBlock *Long // end of the range, nil means latest block - Addresses *[]common.Address // restricts matches to events created by specific contracts - - // The Topic list restricts matches to particular event topics. Each event has a list - // of topics. Topics matches a prefix of that list. An empty element slice matches any - // topic. Non-empty elements represent an alternative that matches any of the - // contained topics. - // - // Examples: - // {} or nil matches any topic list - // {{A}} matches topic A in first position - // {{}, {B}} matches any topic in first position, B in second position - // {{A}, {B}} matches topic A in first position, B in second position - // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position - Topics *[][]common.Hash -} - -func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria }) ([]*Log, error) { - // Convert the RPC block numbers into internal representations - begin := rpc.LatestBlockNumber.Int64() - if args.Filter.FromBlock != nil { - begin = int64(*args.Filter.FromBlock) - } - end := rpc.LatestBlockNumber.Int64() - if args.Filter.ToBlock != nil { - end = int64(*args.Filter.ToBlock) - } - if begin > 0 && end > 0 && begin > end { - return nil, errInvalidBlockRange - } - var addresses []common.Address - if args.Filter.Addresses != nil { - addresses = *args.Filter.Addresses - } - var topics [][]common.Hash - if args.Filter.Topics != nil { - topics = *args.Filter.Topics - } - // Construct the range filter - filter := r.filterSystem.NewRangeFilter(begin, end, addresses, topics) - return runFilter(ctx, r, filter) -} - -func (r *Resolver) GasPrice(ctx context.Context) (hexutil.Big, error) { - tipcap, err := r.backend.SuggestGasTipCap(ctx) - if err != nil { - return hexutil.Big{}, err - } - if head := r.backend.CurrentHeader(); head.BaseFee != nil { - tipcap.Add(tipcap, head.BaseFee) - } - return (hexutil.Big)(*tipcap), nil -} - -func (r *Resolver) MaxPriorityFeePerGas(ctx context.Context) (hexutil.Big, error) { - tipcap, err := r.backend.SuggestGasTipCap(ctx) - if err != nil { - return hexutil.Big{}, err - } - return (hexutil.Big)(*tipcap), nil -} - -func (r *Resolver) ChainID(ctx context.Context) (hexutil.Big, error) { - return hexutil.Big(*r.backend.ChainConfig().ChainID), nil -} - -// SyncState represents the synchronisation status returned from the `syncing` accessor. -type SyncState struct { - progress ethereum.SyncProgress -} - -func (s *SyncState) StartingBlock() hexutil.Uint64 { - return hexutil.Uint64(s.progress.StartingBlock) -} -func (s *SyncState) CurrentBlock() hexutil.Uint64 { - return hexutil.Uint64(s.progress.CurrentBlock) -} -func (s *SyncState) HighestBlock() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HighestBlock) -} -func (s *SyncState) SyncedAccounts() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedAccounts) -} -func (s *SyncState) SyncedAccountBytes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedAccountBytes) -} -func (s *SyncState) SyncedBytecodes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedBytecodes) -} -func (s *SyncState) SyncedBytecodeBytes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedBytecodeBytes) -} -func (s *SyncState) SyncedStorage() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedStorage) -} -func (s *SyncState) SyncedStorageBytes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.SyncedStorageBytes) -} -func (s *SyncState) HealedTrienodes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealedTrienodes) -} -func (s *SyncState) HealedTrienodeBytes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealedTrienodeBytes) -} -func (s *SyncState) HealedBytecodes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealedBytecodes) -} -func (s *SyncState) HealedBytecodeBytes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealedBytecodeBytes) -} -func (s *SyncState) HealingTrienodes() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealingTrienodes) -} -func (s *SyncState) HealingBytecode() hexutil.Uint64 { - return hexutil.Uint64(s.progress.HealingBytecode) -} -func (s *SyncState) TxIndexFinishedBlocks() hexutil.Uint64 { - return hexutil.Uint64(s.progress.TxIndexFinishedBlocks) -} -func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 { - return hexutil.Uint64(s.progress.TxIndexRemainingBlocks) -} - -// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not -// yet received the latest block headers from its pears. In case it is synchronizing: -// - startingBlock: block number this node started to synchronize from -// - currentBlock: block number this node is currently importing -// - highestBlock: block number of the highest block header this node has received from peers -// - syncedAccounts: number of accounts downloaded -// - syncedAccountBytes: number of account trie bytes persisted to disk -// - syncedBytecodes: number of bytecodes downloaded -// - syncedBytecodeBytes: number of bytecode bytes downloaded -// - syncedStorage: number of storage slots downloaded -// - syncedStorageBytes: number of storage trie bytes persisted to disk -// - healedTrienodes: number of state trie nodes downloaded -// - healedTrienodeBytes: number of state trie bytes persisted to disk -// - healedBytecodes: number of bytecodes downloaded -// - healedBytecodeBytes: number of bytecodes persisted to disk -// - healingTrienodes: number of state trie nodes pending -// - healingBytecode: number of bytecodes pending -// - txIndexFinishedBlocks: number of blocks whose transactions are indexed -// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet -func (r *Resolver) Syncing() (*SyncState, error) { - progress := r.backend.SyncProgress() - - // Return not syncing if the synchronisation already completed - if progress.Done() { - return nil, nil - } - // Otherwise gather the block sync stats - return &SyncState{progress}, nil -} diff --git a/builder/graphql/graphql_test.go b/builder/graphql/graphql_test.go deleted file mode 100644 index 1dda10205..000000000 --- a/builder/graphql/graphql_test.go +++ /dev/null @@ -1,485 +0,0 @@ -// 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 graphql - -import ( - "context" - "encoding/json" - "fmt" - "io" - "math/big" - "net/http" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/beacon" - "github.com/ethereum/go-ethereum/consensus/ethash" - "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/crypto" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - - "github.com/stretchr/testify/assert" -) - -func TestBuildSchema(t *testing.T) { - ddir := t.TempDir() - // Copy config - conf := node.DefaultConfig - conf.DataDir = ddir - stack, err := node.New(&conf) - if err != nil { - t.Fatalf("could not create new node: %v", err) - } - defer stack.Close() - // Make sure the schema can be parsed and matched up to the object model. - if _, err := newHandler(stack, nil, nil, []string{}, []string{}); err != nil { - t.Errorf("Could not construct GraphQL handler: %v", err) - } -} - -// Tests that a graphQL request is successfully handled when graphql is enabled on the specified endpoint -func TestGraphQLBlockSerialization(t *testing.T) { - stack := createNode(t) - defer stack.Close() - genesis := &core.Genesis{ - Config: params.AllEthashProtocolChanges, - GasLimit: 11500000, - Difficulty: big.NewInt(1048576), - } - newGQLService(t, stack, false, genesis, 10, func(i int, gen *core.BlockGen) {}) - // start node - if err := stack.Start(); err != nil { - t.Fatalf("could not start node: %v", err) - } - - for i, tt := range []struct { - body string - want string - code int - }{ - { // Should return latest block - body: `{"query": "{block{number}}","variables": null}`, - want: `{"data":{"block":{"number":"0xa"}}}`, - code: 200, - }, - { // Should return info about latest block - body: `{"query": "{block{number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":{"number":"0xa","gasUsed":"0x0","gasLimit":"0xaf79e0"}}}`, - code: 200, - }, - { - body: `{"query": "{block(number:0){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":{"number":"0x0","gasUsed":"0x0","gasLimit":"0xaf79e0"}}}`, - code: 200, - }, - { - body: `{"query": "{block(number:-1){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":null}}`, - code: 200, - }, - { - body: `{"query": "{block(number:-500){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":null}}`, - code: 200, - }, - { - body: `{"query": "{block(number:\"0\"){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":{"number":"0x0","gasUsed":"0x0","gasLimit":"0xaf79e0"}}}`, - code: 200, - }, - { - body: `{"query": "{block(number:\"-33\"){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":null}}`, - code: 200, - }, - { - body: `{"query": "{block(number:\"1337\"){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":null}}`, - code: 200, - }, - { - body: `{"query": "{block(number:\"0x0\"){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"data":{"block":{"number":"0x0","gasUsed":"0x0","gasLimit":"0xaf79e0"}}}`, - //want: `{"errors":[{"message":"strconv.ParseInt: parsing \"0x0\": invalid syntax"}],"data":{}}`, - code: 200, - }, - { - body: `{"query": "{block(number:\"a\"){number,gasUsed,gasLimit}}","variables": null}`, - want: `{"errors":[{"message":"strconv.ParseInt: parsing \"a\": invalid syntax"}],"data":{}}`, - code: 400, - }, - { - body: `{"query": "{bleh{number}}","variables": null}"`, - want: `{"errors":[{"message":"Cannot query field \"bleh\" on type \"Query\".","locations":[{"line":1,"column":2}]}]}`, - code: 400, - }, - // should return `estimateGas` as decimal - { - body: `{"query": "{block{ estimateGas(data:{}) }}"}`, - want: `{"data":{"block":{"estimateGas":"0xd221"}}}`, - code: 200, - }, - // should return `status` as decimal - { - body: `{"query": "{block {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}"}`, - want: `{"data":{"block":{"number":"0xa","call":{"data":"0x","status":"0x1"}}}}`, - code: 200, - }, - { - body: `{"query": "{blocks {number}}"}`, - want: `{"errors":[{"message":"from block number must be specified","path":["blocks"]}],"data":null}`, - code: 400, - }, - } { - resp, err := http.Post(fmt.Sprintf("%s/graphql", stack.HTTPEndpoint()), "application/json", strings.NewReader(tt.body)) - if err != nil { - t.Fatalf("could not post: %v", err) - } - bodyBytes, err := io.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - t.Fatalf("could not read from response body: %v", err) - } - if have := string(bodyBytes); have != tt.want { - t.Errorf("testcase %d %s,\nhave:\n%v\nwant:\n%v", i, tt.body, have, tt.want) - } - if tt.code != resp.StatusCode { - t.Errorf("testcase %d %s,\nwrong statuscode, have: %v, want: %v", i, tt.body, resp.StatusCode, tt.code) - } - if ctype := resp.Header.Get("Content-Type"); ctype != "application/json" { - t.Errorf("testcase %d \nwrong Content-Type, have: %v, want: %v", i, ctype, "application/json") - } - } -} - -func TestGraphQLBlockSerializationEIP2718(t *testing.T) { - // Account for signing txes - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - funds = big.NewInt(1000000000000000) - dad = common.HexToAddress("0x0000000000000000000000000000000000000dad") - ) - stack := createNode(t) - defer stack.Close() - genesis := &core.Genesis{ - Config: params.AllEthashProtocolChanges, - GasLimit: 11500000, - Difficulty: big.NewInt(1048576), - Alloc: types.GenesisAlloc{ - address: {Balance: funds}, - // The address 0xdad sloads 0x00 and 0x01 - dad: { - Code: []byte{byte(vm.PC), byte(vm.PC), byte(vm.SLOAD), byte(vm.SLOAD)}, - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - BaseFee: big.NewInt(params.InitialBaseFee), - } - signer := types.LatestSigner(genesis.Config) - newGQLService(t, stack, false, genesis, 1, func(i int, gen *core.BlockGen) { - gen.SetCoinbase(common.Address{1}) - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{ - Nonce: uint64(0), - To: &dad, - Value: big.NewInt(100), - Gas: 50000, - GasPrice: big.NewInt(params.InitialBaseFee), - }) - gen.AddTx(tx) - tx, _ = types.SignNewTx(key, signer, &types.AccessListTx{ - ChainID: genesis.Config.ChainID, - Nonce: uint64(1), - To: &dad, - Gas: 30000, - GasPrice: big.NewInt(params.InitialBaseFee), - Value: big.NewInt(50), - AccessList: types.AccessList{{ - Address: dad, - StorageKeys: []common.Hash{{0}}, - }}, - }) - gen.AddTx(tx) - }) - // start node - if err := stack.Start(); err != nil { - t.Fatalf("could not start node: %v", err) - } - - for i, tt := range []struct { - body string - want string - code int - }{ - { - body: `{"query": "{block {number transactions { from { address } to { address } value hash type accessList { address storageKeys } index}}}"}`, - want: `{"data":{"block":{"number":"0x1","transactions":[{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x64","hash":"0xd864c9d7d37fade6b70164740540c06dd58bb9c3f6b46101908d6339db6a6a7b","type":"0x0","accessList":[],"index":"0x0"},{"from":{"address":"0x71562b71999873db5b286df957af199ec94617f7"},"to":{"address":"0x0000000000000000000000000000000000000dad"},"value":"0x32","hash":"0x19b35f8187b4e15fb59a9af469dca5dfa3cd363c11d372058c12f6482477b474","type":"0x1","accessList":[{"address":"0x0000000000000000000000000000000000000dad","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000000"]}],"index":"0x1"}]}}}`, - code: 200, - }, - } { - resp, err := http.Post(fmt.Sprintf("%s/graphql", stack.HTTPEndpoint()), "application/json", strings.NewReader(tt.body)) - if err != nil { - t.Fatalf("could not post: %v", err) - } - bodyBytes, err := io.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - t.Fatalf("could not read from response body: %v", err) - } - if have := string(bodyBytes); have != tt.want { - t.Errorf("testcase %d %s,\nhave:\n%v\nwant:\n%v", i, tt.body, have, tt.want) - } - if tt.code != resp.StatusCode { - t.Errorf("testcase %d %s,\nwrong statuscode, have: %v, want: %v", i, tt.body, resp.StatusCode, tt.code) - } - } -} - -// Tests that a graphQL request is not handled successfully when graphql is not enabled on the specified endpoint -func TestGraphQLHTTPOnSamePort_GQLRequest_Unsuccessful(t *testing.T) { - stack := createNode(t) - defer stack.Close() - if err := stack.Start(); err != nil { - t.Fatalf("could not start node: %v", err) - } - body := strings.NewReader(`{"query": "{block{number}}","variables": null}`) - resp, err := http.Post(fmt.Sprintf("%s/graphql", stack.HTTPEndpoint()), "application/json", body) - if err != nil { - t.Fatalf("could not post: %v", err) - } - resp.Body.Close() - // make sure the request is not handled successfully - assert.Equal(t, http.StatusNotFound, resp.StatusCode) -} - -func TestGraphQLConcurrentResolvers(t *testing.T) { - var ( - key, _ = crypto.GenerateKey() - addr = crypto.PubkeyToAddress(key.PublicKey) - dadStr = "0x0000000000000000000000000000000000000dad" - dad = common.HexToAddress(dadStr) - genesis = &core.Genesis{ - Config: params.AllEthashProtocolChanges, - GasLimit: 11500000, - Difficulty: big.NewInt(1048576), - Alloc: types.GenesisAlloc{ - addr: {Balance: big.NewInt(params.Ether)}, - dad: { - // LOG0(0, 0), LOG0(0, 0), RETURN(0, 0) - Code: common.Hex2Bytes("60006000a060006000a060006000f3"), - Nonce: 0, - Balance: big.NewInt(0), - }, - }, - } - signer = types.LatestSigner(genesis.Config) - stack = createNode(t) - ) - defer stack.Close() - - var tx *types.Transaction - handler, chain := newGQLService(t, stack, false, genesis, 1, func(i int, gen *core.BlockGen) { - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)}) - gen.AddTx(tx) - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 1, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)}) - gen.AddTx(tx) - tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{To: &dad, Nonce: 2, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)}) - gen.AddTx(tx) - }) - // start node - if err := stack.Start(); err != nil { - t.Fatalf("could not start node: %v", err) - } - - for i, tt := range []struct { - body string - want string - }{ - // Multiple txes race to get/set the block hash. - { - body: "{block { transactions { logs { account { address } } } } }", - want: fmt.Sprintf(`{"block":{"transactions":[{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]},{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]},{"logs":[{"account":{"address":"%s"}},{"account":{"address":"%s"}}]}]}}`, dadStr, dadStr, dadStr, dadStr, dadStr, dadStr), - }, - // Multiple fields of a tx race to resolve it. Happens in this case - // because resolving the tx body belonging to a log is delayed. - { - body: `{block { logs(filter: {}) { transaction { nonce value gasPrice }}}}`, - want: `{"block":{"logs":[{"transaction":{"nonce":"0x0","value":"0x0","gasPrice":"0x3b9aca00"}},{"transaction":{"nonce":"0x0","value":"0x0","gasPrice":"0x3b9aca00"}},{"transaction":{"nonce":"0x1","value":"0x0","gasPrice":"0x3b9aca00"}},{"transaction":{"nonce":"0x1","value":"0x0","gasPrice":"0x3b9aca00"}},{"transaction":{"nonce":"0x2","value":"0x0","gasPrice":"0x3b9aca00"}},{"transaction":{"nonce":"0x2","value":"0x0","gasPrice":"0x3b9aca00"}}]}}`, - }, - // Multiple txes of a block race to set/retrieve receipts of a block. - { - body: "{block { transactions { status gasUsed } } }", - want: `{"block":{"transactions":[{"status":"0x1","gasUsed":"0x5508"},{"status":"0x1","gasUsed":"0x5508"},{"status":"0x1","gasUsed":"0x5508"}]}}`, - }, - // Multiple fields of block race to resolve header and body. - { - body: "{ block { number hash gasLimit ommerCount transactionCount totalDifficulty } }", - want: fmt.Sprintf(`{"block":{"number":"0x1","hash":"%s","gasLimit":"0xaf79e0","ommerCount":"0x0","transactionCount":"0x3","totalDifficulty":"0x200000"}}`, chain[len(chain)-1].Hash()), - }, - // Multiple fields of a block race to resolve the header and body. - { - body: fmt.Sprintf(`{ transaction(hash: "%s") { block { number hash gasLimit ommerCount transactionCount } } }`, tx.Hash()), - want: fmt.Sprintf(`{"transaction":{"block":{"number":"0x1","hash":"%s","gasLimit":"0xaf79e0","ommerCount":"0x0","transactionCount":"0x3"}}}`, chain[len(chain)-1].Hash()), - }, - // Account fields race the resolve the state object. - { - body: fmt.Sprintf(`{ block { account(address: "%s") { balance transactionCount code } } }`, dadStr), - want: `{"block":{"account":{"balance":"0x0","transactionCount":"0x0","code":"0x60006000a060006000a060006000f3"}}}`, - }, - // Test values for a non-existent account. - { - body: fmt.Sprintf(`{ block { account(address: "%s") { balance transactionCount code } } }`, "0x1111111111111111111111111111111111111111"), - want: `{"block":{"account":{"balance":"0x0","transactionCount":"0x0","code":"0x"}}}`, - }, - } { - res := handler.Schema.Exec(context.Background(), tt.body, "", map[string]interface{}{}) - if res.Errors != nil { - t.Fatalf("failed to execute query for testcase #%d: %v", i, res.Errors) - } - have, err := json.Marshal(res.Data) - if err != nil { - t.Fatalf("failed to encode graphql response for testcase #%d: %s", i, err) - } - if string(have) != tt.want { - t.Errorf("response unmatch for testcase #%d.\nExpected:\n%s\nGot:\n%s\n", i, tt.want, have) - } - } -} - -func TestWithdrawals(t *testing.T) { - var ( - key, _ = crypto.GenerateKey() - addr = crypto.PubkeyToAddress(key.PublicKey) - - genesis = &core.Genesis{ - Config: params.AllEthashProtocolChanges, - GasLimit: 11500000, - Difficulty: common.Big1, - Alloc: types.GenesisAlloc{ - addr: {Balance: big.NewInt(params.Ether)}, - }, - } - signer = types.LatestSigner(genesis.Config) - stack = createNode(t) - ) - defer stack.Close() - - handler, _ := newGQLService(t, stack, true, genesis, 1, func(i int, gen *core.BlockGen) { - tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{To: &common.Address{}, Gas: 100000, GasPrice: big.NewInt(params.InitialBaseFee)}) - gen.AddTx(tx) - gen.AddWithdrawal(&types.Withdrawal{ - Validator: 5, - Address: common.Address{}, - Amount: 10, - }) - }) - // start node - if err := stack.Start(); err != nil { - t.Fatalf("could not start node: %v", err) - } - - for i, tt := range []struct { - body string - want string - }{ - // Genesis block has no withdrawals. - { - body: "{block(number: 0) { withdrawalsRoot withdrawals { index } } }", - want: `{"block":{"withdrawalsRoot":null,"withdrawals":null}}`, - }, - { - body: "{block(number: 1) { withdrawalsRoot withdrawals { validator amount } } }", - want: `{"block":{"withdrawalsRoot":"0x8418fc1a48818928f6692f148e9b10e99a88edc093b095cb8ca97950284b553d","withdrawals":[{"validator":"0x5","amount":"0xa"}]}}`, - }, - } { - res := handler.Schema.Exec(context.Background(), tt.body, "", map[string]interface{}{}) - if res.Errors != nil { - t.Fatalf("failed to execute query for testcase #%d: %v", i, res.Errors) - } - have, err := json.Marshal(res.Data) - if err != nil { - t.Fatalf("failed to encode graphql response for testcase #%d: %s", i, err) - } - if string(have) != tt.want { - t.Errorf("response unmatch for testcase #%d.\nhave:\n%s\nwant:\n%s", i, have, tt.want) - } - } -} - -func createNode(t *testing.T) *node.Node { - stack, err := node.New(&node.Config{ - HTTPHost: "127.0.0.1", - HTTPPort: 0, - WSHost: "127.0.0.1", - WSPort: 0, - HTTPTimeouts: node.DefaultConfig.HTTPTimeouts, - }) - if err != nil { - t.Fatalf("could not create node: %v", err) - } - return stack -} - -func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Genesis, genBlocks int, genfunc func(i int, gen *core.BlockGen)) (*handler, []*types.Block) { - ethConf := ðconfig.Config{ - Genesis: gspec, - NetworkId: 1337, - TrieCleanCache: 5, - TrieDirtyCache: 5, - TrieTimeout: 60 * time.Minute, - SnapshotCache: 5, - } - var engine consensus.Engine = ethash.NewFaker() - if shanghai { - engine = beacon.NewFaker() - chainCfg := gspec.Config - chainCfg.TerminalTotalDifficultyPassed = true - chainCfg.TerminalTotalDifficulty = common.Big0 - // GenerateChain will increment timestamps by 10. - // Shanghai upgrade at block 1. - shanghaiTime := uint64(5) - chainCfg.ShanghaiTime = &shanghaiTime - } - ethBackend, err := eth.New(stack, ethConf) - if err != nil { - t.Fatalf("could not create eth backend: %v", err) - } - // Create some blocks and import them - chain, _ := core.GenerateChain(params.AllEthashProtocolChanges, ethBackend.BlockChain().Genesis(), - engine, ethBackend.ChainDb(), genBlocks, genfunc) - _, err = ethBackend.BlockChain().InsertChain(chain) - if err != nil { - t.Fatalf("could not create import blocks: %v", err) - } - // Set up handler - filterSystem := filters.NewFilterSystem(ethBackend.APIBackend, filters.Config{}) - handler, err := newHandler(stack, ethBackend.APIBackend, filterSystem, []string{}, []string{}) - if err != nil { - t.Fatalf("could not create graphql service: %v", err) - } - return handler, chain -} diff --git a/builder/graphql/internal/graphiql/build.go b/builder/graphql/internal/graphiql/build.go deleted file mode 100644 index 0065c1112..000000000 --- a/builder/graphql/internal/graphiql/build.go +++ /dev/null @@ -1,8 +0,0 @@ -package graphiql - -import ( - "embed" -) - -//go:embed *.js *.css *.html -var Assets embed.FS diff --git a/builder/graphql/internal/graphiql/graphiql.min.css b/builder/graphql/internal/graphiql/graphiql.min.css deleted file mode 100644 index 521452299..000000000 --- a/builder/graphql/internal/graphiql/graphiql.min.css +++ /dev/null @@ -1,337 +0,0 @@ -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAC80AA4AAAAAVTAAAC7cAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoFOG5JCHDYGYACCWBEMCoGBAOoVC4NaAAE2AiQDhzAEIAWDCgcgG/JGo6Kq1zUjEcLGASoGnAv+MoEbQ7A+yIsRMaSqAH+x1tYTX0OAvwSG6Gnrf1VwxGnKQe5khBE+tEwjJJnl4f/39/9zH3wYTYp0ApGJBFek79HVxOSqxnvfW8fza2ve/3+bDaKWCouyQIHzUEAlImQJWZCoUGiJVCINFmUxaEEFDxMwUE8x+vSs0zs9gbEtUOt5+nf46f2redKa+RgB44pNjY1bKkA4gAaHdRjNfbr07S5vRmAFgEt6PXefZnfWp411rPPJDtDpNB9bu2gDXFTU/SrYr7QBGv6av3h1FWmwKhzogW1gXz/q/m+bb5WFCh76QhNtX2ZS2gglnsLhs//TZbYja2R4OtKzA3shb3GERZVLC9hUWKH0R5I1M4vSkVaGXRPv7RHtrZOnAGCVMkVpOkConAq5oqa6dF3aFrmowvPvn6i9WDxg1tRefhp/gB+LExjQhBdfRstouIxoFOipBSwYNtfkZYAjWYpznajtsdQCKLYbjyAiXY/PrZ9xbxfh7m/XQvLKY423auq+f0olGBYAd2HkbGcI2cMKYsMG4sAJ4sIVzos3JAAPEiQIwhcGiRILSZAISZEGyZIFyVUIKVEKqVQJqVYNqVMHadAEadECOeIIpEsPpN9JiMAjyBNPIM+9gLzyFoJgQCOgDQziwh1IQAIaUKeFGPtx6lyaX6bbNtD84frK9TR/7ezYRBNa/23bJhwIiwRAAjIgIyYNxMUdzu8jgAHhxj2zwyo+pnlY5ZPazg6ZqjT0Loxv/6gmxYhhee7JeQOp9eApRZlFr8wiWbaanHx8Aq/N87DyuMUV62R1R5AmpqXLeomnfUYUaF6q8Pg+Vzrxtmh63qW+acoKWEkJfXXiy1vwWjPbDnDXJNa+zrWc1L6P0M9e/K11//hLeGYvSOjd04+l76vO1ccnDzs+9xOAO35k/juy1hdd6Wu3PnjcBRI7mib6tHdVc3vP9J0L6zDjj00yNZpa+qzVtPHBlvcsDg6I0/2jGZJwms3oy02LrrBgc6JYd3VzJcLTHL2+d8JlTtfhst0RiMV+dm9V2N/Tr9Dhh2KZzsXEvSVqv8aJ/t05ikZmnZMWZh3rZrXxHdVqDAoKCH6rypYwkUILuq/bSF5XK7eBNDVxpSPixl8DiR4jO1iw4hev2pmBgu3nZzFi5cpX6FBc+p8exw0QGHTKaUOEhp0xYdJls+Zdc90NN92yYNGyPz3yzHMvURj2OofeF1p7yW1R1b8d7ifNtYak9S9kSX0muc+l0mVln6ruE01W0dN1JBSHpNaVXD9U+JQtnPhceW2nuSXIDPuRQz8L1anqw30d6AU0p+9INj5L7W1pvaiwL1Viqiai+fp9Sz9BmvoYiWH/5tCPQvtWVb9q7juYOd4Vj2hseo1fHwpJVWT/WXJfS+uyso6p7yNNRKHw+SMxhs2krucQ27LJnulCezqfozNNahuf8Vu4wr5Q1jBVrXK4J9Q3VRO25lZi3GH7PQrOa5L6Mn9+pLI3VVM39SiPm1YjGuMcj2RY4cciIsvv6/24TK73QzbGL/SQovd+CZ1hT7HpLQ6dFYp5d109S2a+5iF/5MOxnUbXWTaju7l1wkk63ee8EWPGaXU8aSZmM6OOuB0wFnCWxFih8UMRgImHLRBdMLr96GIwxWIrhBwiqgRTKbZuYnrQHMdyAsdJDANoBjGdwjYEI0Q2DHMG2XkkI4O63qaaAEyT2C5DZuHm4a6huE7KDTQ3SbmFZoGURTTLRPxJ0iOiniA8I+E5SS8HfcvcYX0PTOtiSvNmCCyUYz6KxFUW/lxW1QCjR6wXzWuAADXoV5riZLWqGmFqZUFLuT8hwI3gNRukjBH8BLnRVNFQUHol8qle8MR0hH5AXowhQNQPnSjlFFYBqn60pmieSUmaoqKoKqpy1VKqp4jVTefF5kcFEigvzGaQuoq1+UvBFx7DqmSnjAmfZkyAiiUjvuEXwKrT+ATK0FVAMWoElCnDx5OSt8IKTCHSWNoj9sNFwIpliUxyClKeI+nLQM7nWu5kJV8Hlc1GvKugWBJeopKSolTlaPpzKiO5nrt5kn8GK5t3FVTugsotQGUWVCZB5RmorIBK6YBEFegFDLELmAcsAw4CZ4AbwEiGnunUZW80gXiR2aeXB888OvMpH778clvP375Ys7F+xwQKEizES6/ii7fsfoxZ9olUaR5biTaHly5DpizZcuTK88BD+QoUGjMaezKnXFCkmLXdcdfB2NX3a2+UueetVkcIcrpSYVFsgO+A9AF4B5p8BJ0WQLEXZJ89DfSj6MSUiRgRVpbfAVfIeXKbXk3QXIWAAzNlOWxZVKJRiAJpwlGYilkyeDPlK7EsgGygO8OkuVea0943N1qrxJuKFsA21quXc0fIskBQRMJSERPJrEkUSVFx2IO47RgaWDQHcHuRTVW+3tCSpDBUgvSS5mSOJbtWDNumUG3GblmoblUYAA9kIAF9zqL8hSgZY1HSVex2VkirkoRExLN1nYoQyyR4YAolcrpkGJomCDxvWo1QMqpoW1rKhHT3tju06zCUSaViX5ZplgVBEjpOB7hzoUK9C3he02RZ4pe4lNF4TWHj8WwRGe2ZkVweGRCcwu1wQdxHN7rRDfOXf6cuFHymU40lIqdUbVgiG9OcJBSZeB19jywI2jjDkGIyvZ5dQpbFK+vzZbig+8IeY7U9uC73znT5cVJtYhvzoAQJeJ0UeHMRxiOYjHFSkGXrQhXGf6PkR1DK/o0KAEqJvPE7osjSg2TzqzbMekWSU71ztpPj1BraN9iaOZOn+OYH7GbeeY2YYQlxGGA/Qiw2p0MzXKcpeRfXPA8oGmKpA60e07q8yWsxnoLscZizoVw0rZ3IZtPaMxz7oGk1nn06gx0schwtQqsPxQLmguVHekl8EvHnrVDui9Ovbm7/98aJ57d6sn4k4ljm0qgPrraIe4mrMJs2WruHwahxCdecqU8EO0/mod19L/dQiSfjbf+qpwhiV7Y7myqZ4zGsKqU9l8nM7uYHKrWSD4+Vu+op7EOrp1WjA9g5iUqQZOINZ2jdhwykTSmDGXFZrOZ5Fd6YBVdXx+oKIsfzItL4dK1IH2Hg5KhISu9ae+dRNX66uYlLUjQbF7CQwU2QMS5ihhb3S5WsGlKwN7fd7RMYhAWAef6Loq2ZlpYU7SvwhYPyoyTg0z7kcjZhNbuYfjthtcpnNsYrIXMBzIMlOyGRScfAUh1EC1rbMe/k9R5uX+L4cYZG+POa6GSPEXLvRCxgIIU+FC2cxxQNkoJPwEKwp8kiRChwGmdzO4ebFKZBN8lyqgy5akZ6RYNVTzUJfQ6qijBFH6OJZy5PfhA4WMzAlRCci43yPvEyu1YE93+QzQ44nGXiNo3gE+B07gQ7D86FXH1/sYrDMrTKw6VzGuqsNpPAYEDaBr48s8IREoYixIwQ+FFjTJddfDHohD60rPY2Cj3TC9wDDvynURdS4B653OWMnKFvhB7i0Nh/4/ycw7ClqQjPhVrdhgOtabwqD4vC1GSLtcruqqLSi08b0sctZFsxQEcvb8T39CbmS0j1RCvpe6YL/Hghfv7wpL3xvJOXLDakQXz23A6eTcl43QghF3CaYL4U84JgHsrEr4P1inFTvGRjlzt1vbSD807udkiRYyZ+/WJR5pk+tGZV4aDHRBtIpdO9Cn6gC1zn4ga2vAmW8/g7qFtQMuxPaazxBggjVlTC/0ZbEiCxZYMhRjzq1esbisUbPEcQTGdXmNtWVjJWl/TM+zTWcoCxwXT+8mdW1Br/hY8fcRKk+fhw6SOOmf8gw8CgS6SzMd7mWlPpzf6ndSD8xyHrzCSA+x09k7syz10ruZ29EznBQ4x9yu5HxnWndL4ZYEXu3rzb5Y16oYTd96hsB5P6DXdSXztmOww5UnXgNP6PUmrEA+AtXMlVn7HSk7vuU40VJxREOftWl7k5ovoapE14t727Vg5BkFJruqF/lVKDKXCBcR9lumB21r2pG4q0gVyzOnVT7NuxiooVs0vVu5xwbn3b9TZPL6Uj4oqRAipomlegaCblNTCwpFVkZKyHrcAoX/multkQ/r6q3xan09IWA6lsTNEMNnWoW67vcke29VS73NzWvexgi+enG+apJYGNLiMZKSxrCwtyiyRBkWae9y7RteEqaxYObtbCDtOx6j2M9X0mBpZAlankhxty1378EIMLmidBDaoKS7obmb5iubkIC0DA4O8wrwQWkhGw852CyTOJ07kozg44bmwS5CFQwXkz5s8TZwlFZbI1bxGmMQVluFLb/evvvASAI3r6OnmbRsJx4CTTvWQmeIyHMiJI+htujuzdOjigE32EGq8z9V6I7nI+B+A57zmJzckX84bByJyou9hD53g0u4PNTgIOZ5kVB0EZC5ZoIF27wDqCMpR7c2ISFyvdhV0NRzBEOviwkkv4tUwLOXeCwcK7FC5oX2xGToLTttPdDzpM1RX85R+nrLkWxcRoxhV/ZLPdyanN28a17HZb/77yRuLHTJUnZYkTuUL3rwuHP3h34mZyRFP5M0wSi8YV4g/jSq5eoRizM+9NUWC8uv8URrleQd10k6d0LM/Y5fbXl5GIE+pnCBIyXZWp3HnHazMsL2fO5ZeybjIW6slph2zlN5eplEXlSHfgSimyHmRiLg0zriGD03PmGdmNjNqInKpNzHJ1vMBhQnYDv11U6r6nIFDbhFBkFc4Vx00ErCGQOY1W9HQIXQxnwGafWsnujG/muam0Z/if7mX+FIGpXnXXJw5m+pDA0kdLwBfSvrtKFvlgmnOq+8V2cB6KLvcUkfQrUFQyL+0pF13zZd8j9HSQom+YnKnWxH+E07KeDLjxpcLZ5kdBtkh2M3xTcii4Q5ALnMecKm0GJeb8yVU2mX+Si0MlaPEJ5DeOAhXJyzw0iTiexC0Sk+aYhxR7JlFOrvjFtNazAGXFRqydiaPcuMsq9iTI5W3GmJYy4Y3gn5VmQqFCuYCxSsefYAJYYiUxx/7wikMw+tdEbV+9o0t05LD5r1g0B7eF84v7gIfdyhkgCWbwIG8gUURzzBM+MBKftuHIp0i+83GgqoZYxpbJlcjWDkoUqD2FbTfTbC+lzm2MF3SJkQTnfpd9lNQNFqI31q2YUZ6QCrC5jMj3pArcgW7DSdTZE5FCJubxD0B+OiKy8Yk0GiV+qqr/kKwluZHOlN0tweuIS02bj8NvWFugBz4r15zLXhIky7WM2S8EQspo3NHLcrJR9pJgNDz6UmoMiJHdXkdA1UXA/tK+bqb9W7Mh3u8JFuvMDlZwzNo8Yv219F59YC9+EJvPjP9OaiQl7eS1KcS6NMfO4ov4V0XqF3z/JtMcyUCfgQ7O0zrSTM3dajwfv1VXoCP6EjMhTdc9rMBHie/ctavi6WC7JHaRJSk20v8vxEW5FnNY15Hbq/VKf9lxcQHpC/Vf7XphMXsDApbe33u8dqHJW2LEb52EU8E8CMPl1x4u7sbL0CkBJY92TGby+SgwXGj+vlG+yBuV+bJthED1za76wz4c9eIjM6x2N2nCWmqJs3DIFTW6Glhr/lkEx4RhjACqlXsgvMz2R01x0r79wArK65nzCcUK0Pkity/M+p1iTeVfXxYdwvvwP+739QIKjc7xx0uw83ekptb54abkuPhCcFQU7yylXc9Nw4Zw/8yQLUJON3SJxWYeGsFr8MEn5PH1QkmsLKwlBDWTkztdPhtVt+B8rL3A+RN8Ep/Dn6qIrlhyjjbTVgpysG58bIk6jJmQTeiO06JVeVdz8SN4YXWIm+m+2xFI/Gok1t2i18SE39npUd0gLT5c2ngWr0NV82Jn42eECZftLTiHqrEuPHGQyiOEnGEQwpo820I0Ve79k1UjKdZS8+uv0lK8AF0o9/gmcpjVU8d4X/VoTwTZlBafdCgQ88DqfEMmWHEUL1tGUvKhQPwQNr0iNQwfBjSK/xxUoshePFWtV/1wfMMq8y20c2TE182uVX+fT76JmezhsGueueBpzrq+JqmMIbUxYHZ5MJs/3rjC0hlZedx3VIvZsvL3ebbu+ZUbc7DNXKpUqqwUwqLAQ8dfnvB/Za4haOfWte64vYNba7Bb7IStStKQ303YAxJJ6Kz3JufeM+J4Jeo9TiuhHfn/9L0VYLgwQlySPPAQVM5nuZwSY9f+GDiHwlG7q4p1W+8UnoFOpFs84BSLxo9TTctF+FlpIeCBmo0sdLYUFSfuENSYo9a9O7et/+sKJHVFMTypFh6uRqe3HsD6mre00P0K9tHtgrzgqZAxYygE9TjbfDRyyOUr6/BmTs1heFaRjU+SJiiyC6JJp9P8aOGxWX5YL6kqwjg9JeEWnXh6hYd1NujX/gSvuCi6zX4f2HLxDiOtvyoTT0FVlSipCsiVWfhucHBmmIBO0Ord7TqnN+tcpeocAenAZ0P/0d5M0o5M0m7D3hqxXpak2Bh7SRAEvyhNMvO35Nu9ZEa91de/MVZ8L2UaOmYWdl3h9lbuihtz1J1FNSOb0EITSnjSdF7nGIxJyk6rT6rmidhdFTq/YTz9MAjEn2mHfWjuVItUr1CMj3r4HNchYLcwzk8TB1HI1g4X2nHamRcOO1WsY/FdpIP3jo/QJk8QiwNYySAgyxjvACy8zpNhL1Z5nbQA3GrQHzKkOwmX1N/vpEpoM7LVU4aQZgolS36Zcq+j4KOY0yWh85WHitfNlX84PBc6vKJZ4XuJlKTWSBl69SBYONY3x9SNxtY1YHX/aObSDbtu0hK7DiSOHEisep74Wv+swz8PQHNhy+HRPGaiSMzh7EyUjs4XiUecA1Hhhkc30TLx4QF7iLNAjw3W8j1GiaDn1s6Q+fXoOv7pJXX0HFDiqqtScTOUr+Z8wIqdwYzLzq4mjoNcC1heFFxgLwlGRCRcDSRcp/eE0dHA1UXAvjjQLEmx7/RYuonIypd+kptos14Bpevp+l+SaWV9kM9TyLV+orVl3L7qdFIyGnwlWedO4pkFGGwPEnNePwfO5gLQEx7hJdCfRffR0hupRatLo5aXKWZx0p3XsKPYo61pwyAT67sV7sDbFc44+9Kaz69lzf9cyf7gp2oBpRMtnBxmfGphKg6618jdJU2l+DHiLUX/5yaQa1lXyMXO1t+swMuImQ69/vOg/dyYcp90CLualvCWXE2KthQsmx4xjdBNwxbx7/9THoN+bNtTunjbMGPGsBGMpm7n2i8JHZYSE5c+rmz/snptciLLZkJoOxHrO/HyjISo+h2AuOAUF4otdXeAm7sHKvXj2JwG9uHvJ4+hXjTZSTtIa5pyt1Q2SyPsSSEJNX/YJWC9aPEcqU4AuEMs3xcFoyoe3Uni6DycBbkmMKhsxJ/moObSNE1p5/oYosbSYWy+2H7+Rluf3VzEwNxrxPFcextMDxuOTsowXa0t0D5aMmzLx7GrhzFb0bZ9/qTUo0onRIP33YO2f5R4pi+m7jmWpGBKymDiWtSnWkNO5+eQIrS/uiKJgdeM/eJjh0UhGD/t9KerdQ7RxTs9ZGsiwGzYsihFOR4NovP3JM5uNBJuMnayZle3kA5gRYr7uMPgO/MOCWDqPL2e3vlpdmwO8l3oydhduwpjVBAl4kN3deW74qB2+kwAqksU9+kHGi+nf9Y3DMKwjoCA89QEwoRkslb+v/XbrxOd+Nx9Sk8/kAL5RX54LDEg0DtRwa3Lo1TEDEDEVgHDTI07/evJWTwUNfkq2R0cfkDqJ51+ISac2M5RxhZ1a2OyjYOHGRZONJVzkhnO6heG7zRGok+xD8bDSvMlEhiBuuDzxTD5jszAgz+O4R6o0FrRLKVuDK/D265yOpPvDiXf26qha2p3yhPPSRTlp9wbTr5HC7JNsEXOWGKcaHjyPdAONDTYbvcTOkkj04wW5sB/i0P4H4wZw/Pc2rPbzIbl+2BbV4b1+V8oBJWmMPaLeLomuOAgyzM5p1ye+t3DdaDvO3ENf4+RVs6Te4qPZmH9xKfPxt8luLVUYNrIkw78NpHF88bqicvNm4+dA50n5sQT0hz+jzT5GWbHtPO6CAm9acnAg1XwoMkHmR8XiG78jweop58fmeuLp2GCXt2+k9zaDlZN/FA8FoTq42R9jwErsKD3D18+No4vi4ldmwC768O7aMBhq8Nwj5XwrLWw9qFwTrdL0MPOF5x97lHguRu61sZtXivcvDamZ+2UZp5hM9vMcLB4UmOPOWG1xhMy3BPkxd3GlZ8zF061eM0j4eyLMzuszwTjTmPcza75Hvc0+0lsf1LTM3ZEsGtt/Oa1wi1rY3vWTvWtubR5jRDJd4h9ksYec5KVpieYqa1h3l18Ln3dKGrMOJqyiydxZBZLQIvh+8eiEx0zsXrUUyhdYZwwahylsMz+87s6nrfXH5vOZYe8XA+wTrZP4ea720vUkYcdMSv99O6nkjMyHcMyneFitJ4h8k6S7YDQaWRtRQ5qzJYukxv+4pX1Zvc+2LPrkHKPb0AVFlPt3K1G5pozciu+FokvQUh0SIzUrA5BvHpApAJ/ER48Gp3Ay0SHUV+O9OHfEtZWr8fRF12uT/6Ub2gkZju9vq/A6eHU9MPO2CcnRDqeSk4hWmjNbpRdXSRVHzDYj7ncZv3q8Rx2MsM/MimG+ngLcOsUIBm7EODfR4niLIpGhm7gnaBG0bIPzrzll+rZY+47XNgRpab2yeHb+EcxTyJ9tKhPuWSigZXGTMrPqyAOA7dOdrpb0HMEY8pzIufZrBoEhSGF9S50x7Jg63BMD+TqpeE0ca2Dkk3sDY6P3+Si6hiPW1LqiFOLqq0EJ4bNL93rkBS8Neoo7kOknSs+W1LvS7eXqPlG6gBunfhnRUFPKyaiYOQ1v1P8Fv6PIu0zcUDfbnex3/k1U8P4Av5VnvoP5kRzZDgp3p2ykOnEJQ0ExD9kQ/xXohw2VnddSr30BOnLj+3//wqiDtZdBycl8ZZG0vuyMrwQHy9z+8GukRJvbkLvS0o7fq2Vun1jH64tTCTO9BoM2DPKUyc5sZuSsOG+LW025PJ0IVAPUBKM8qUXVPf2NabxVST66SGYWbXas6Ie1pJgBho24q4b9n9QCPrruLGhWqW7uOX2KG6uUTEj0HAQ6hncLCE3a0DpohL2GA7INmxUNvR/rSiTMASyySc1zymh+ykKbZsldexFcidYmNBYfN8QSAY1qPxBVlvkRFMDxQOfm0sGD4FUUK3mNFnloeIsqAWaS0UNgXTUUY02DcmrUnLLv9RmlKTChkDqQItGi6rEnIbCkx/KIp/rinQaJGcCLcrNFCQChkCSF7W+ZE6qQiJg+41ik8l/pYHT14F+6sA/UjNehmJFqTcnDyTjYajdW9WmULCMtxOCx7SzGr5OqrNJUUmRY7hoyz2y3ib39daiyN2Ob4GHEfWHJNJ3Hx81P86MCyoJxv2x/MPS5d67fBFytg7ZSzo2Q8u6aU5iJ1vrmxnmiaaBGjUsLzoc/e0qLbT1lF49YGXPMhH1awBWoFhEozvsMTNroNY9Fh1cp8ydvvugA9+HSm2VTdMaRkh1WMsTsaENOvLjt6+ewDl1Z8maImvltLCAnXwT5EnkJHH4Gm+H1N7See7JrsgBiywUy9TahJu2pYq8m6NluSEHKYG1m6y2ifn2GZWK08PzotDjPRlzcJbAE/faLUqENwIzUDy6zvWA+Monvq6cAlY4avBTsi05u0ypbiSfaCiWzGSYdWtQ8UqMLynK3ymZ1inhjtFryh2pkw/n+/ExwrSsvoEb8dYFTmu3mxwY4nwJNn+XVGYXvk7BPXXE7EC29ODAXhHxao3PCuOjmtSqBuwB/g+deXeU3lTeX4qHYMIDuSuSReuYuE1XyXQqngLwKl1oHr1fprh6+woz21Csofb/Z8WFeCc++5DS03dcfpv64vWkK+roKVYY2h5EOgCwYfjHMYfoH72vdwrUD//X7xD9f59I3M9+p9gffR+tjm9o/dXvHPVvL2h8VZNKa4N1rxiiYUdB4w5omdf8nbj2gFbCmslAiIgggjSTQZzC88MFTqL/Bu4iLICRAYo1z8WjB7i16tHW20D6ufTuPXZJEhmD0rmgufiZ5h4V6AlusD/IPQyIIAdHJB/UKkl1iwryAPfQ/a6d3To6IG4Q5xvFOSrYKzE8JNCd/0mc5Hl5FIprTLAbYm0usrxr8tARxDo7IIUgueeyTYkJ9ED7edhEiyFuUOQ3qlvkKAlaHJ25PI3pBXd4hU7ktL9guH3qmH1Qhh9dov16v31guu+x9336GRyv3832KBs3GF9/nr+bGt88qWxVb2y9aXx7bqyKZf1vNpvH9z9D3ra7fqvW3bCZ+9HHxmxHpQ7oLskY+GvnBcNYGjKNdedUJofli2+TX/B9qfbYHrD9fvm+/glF+Hw4b5qZIXouJ2VfeYxPaF3m1l4D7hZrEVfR9PyadNwNAgyNfT0UnTNjveH3XdJKf5c0u+bE+jim7DcIRGcQL8WfJuSYL3eAeFJ++Xm8ER94REyxw4aB5IQdjGjj4814dL0n2bCkATdzWmuTGOtjFrInQqrku9Mpsb/RAV3469LQVU63HCan8gZnVlZhQ1elLkle6L55Ek5BbOuXq1O29XPbMz25ACjA5xN5t0RyOb1fYVBDrSZJqaWZncEqKm7LwJPB6UkW/Yo55wvwkTWfH6+UOq7/XLnhc2B06Sj7omAsMitQa7VSe9W8Nwssthj2Mgjte+fnOZoXKlWn9tnND+cGJ3Bun8Zi5frb/pZXYJtj2WBU6RhLQ+Yqt644IrvYK/tby9zo87vwcf6g3XwaXFMhV2+WIAfe4ByvzjKxOy6FR2uuUX6aj/yQQzKTHsA0cMV+UZFbv385OWR3dUUSs58V2Iub8H+SyJtlfzlisYm2m8fx7NiWbzv0TA+pwo7owg4svwYOYrcT9i8wcznHvvxyRs+ZKjVtrER2bkV3EX5iaxuii7c9+U7xS9IaHOwV5vF2s8adragEu5ud/YHeQPZi+cl06MkqWy8Qop0FxOAP5QdyU5jLuZ7Hh1GlFXv8xdqtKg80//1/yzmCh1WG28yiBNZ+tZdbHL7N+IjHIqaAtlSfsNygZ6R0lemO29GflJFD8PJZhUmV+7SdsFPA7MRztuTuzEYH4EQk7yY5kxy7iRx5ppsfhom2+BGJV9kX1yA/7dYgl72gfL9UKP+B7i47P/mpgojD88ewI8hWMk91ual5F8sfVfZI3sxJtLKxeEwfX0f0ueK5uLIYqOTLhMvWBqJRlMGtjReJSz3LkhQfY0myD/NXe4196SAl3kGXrR3k1n6k5oo8oat1DNOBp/PutBuYSIGihsBylmoex7A74MAnGW6tMtDZJ1KqnDp81QZ69IBXnGoaQ/t9lfbrBfLNFak7lpfAd9iiaEegiFxhlVxBjWj9gujxjUbCzcaWFOxgivxW6erNUpc9xPy5wyAPtK5I72H9aewhfuuV1ILVxRH+bqeYBTHsIxz5GA9NKPpLpQ6BgZ5kP/zbGa7I7RcLzpPNvEivq0IGarR4/npxKxuakeYdYhZ/SiPegYeIA5sXwPJheNAd2fk9DQcxH9Sn7ayuUp7pp4q79SOmjRx2tFiQi5fgt+aMrr8GO/E8dKXc9YNU0SY/Be9+cn4Z6GM+78yvS7/rJbrw0TskoRLFhOE4LVaXO5eBeaEKe2OTELc9Iff3g9PVcOJ48+ZWJtoYx6M77Q+GT0R+O4RHJflGvY1MvSV9R0/6tSymov6aRG+oREPzUtOSE+23jgMdIMyvXanvJbuN0/npo0BdrSZDsbZBJIKVcai8ihiAW+0E2V+dewNKFwXRlcKYyhFOAiFzfOrMYaSzV1yhPmptierNxDlhRJb5ziAbaOiwuCJ3c0gkrlqye+xsDdKyFFestNtQonrLQ+52+nYDPdL0GQSnonbKXmQ4y1+9bqfa14mdxN92B2jJjoun/gb4BokAqh+rafRsHdaFzbmoVpjqLGzF8n/rJP77svvjxiwUwHKn2bGzOirA4KJYpFyLo1T+g/un2dPPmefoOeWXP4aVYGP4g7eMc+cpsSlVB/AcfLyGncE5lF15EK8GuSOwabrNl1tvLZFx9/Vp0fEV5hBnev2ne/jo6O05M0SJSa2LxPPxC42sdHZJYXnxhrivdWM8NsB4nL0kIGCW9OwN5wJnXvvjo5XbAQYWUDrewMllJyQ3p5BgBeYpT95xxsXm13984gc84zGWhqQllKCWF8QN5CBmdxJY9hQ7Vn+MxLOaKoSa9xlYQMnERP+xJKU1J+LgjCQGD0leKcjETuDemeE2QpEvk5u32O60yGmnXjShqKAANq8HRHhYAPl2oR823oX9RWgJDp7/A69FggXykJbnys4dmeV4ISH8U+GWWpgOEc7P8MdcsRzHTTt9ISuOGh9QEEDMIrmWbGg7k8fOFYlOSc3Eg0GuZRv8B9EZvqGsHokX9EhzRYdkkv1mRhJ5t6HXU2+iPNdVijSBBbB5AwweHkBayvb/MN6KylBtD6URKm5RHB3wUKKmTbpctmVNcy+wbKg2ok1Rms+OlmNpKC2VFE2xph8S0O6ATE0/xB9yp9lLtC7QqSBe8w2GiUudtFJKUb3tgzoD1iCcTOLWVkHPyEFWlkhiSmYmLg3c2r/gATy7wxmhRxV15xqW/87u3xQoVejWB1Ilag/OVodYuQbrJPjTid1bMiSbRGKCS0NxOHJGpnYaEkrd6I40e3+XYEwJuDUUGLL7hiXs+MnRWgla7PS9bgzLRpAsVVkeORxs5ROzIcX7IMmJU8ZqFVBhL0lsKUFVc2SH+jvaMG7FaVJNZzQ/WP9BprS8bw9jxm3TZhuTvQGt1AvGFGUUwOGd3KbCu0WfZ6IDP0JqnuL0wlbxtu0Ov8V0J9bmwCOl9ypdELHYBq45ZUVV3W6XtX8R6agGgYMPx6dXxIfwoUwnWT8dKMcb8eYJzjFwyRcwOj1U1Wx27jVppUzvIClYFQYQvsnlIm800YU14U3TIr06mr3+2e9YTGVvdCVsVLn6xu5notkOS6/lBoUpK5u2ECYmFjFFpI61GFgu7GH+zPCmXE7au3KyCtWj5ousHtgjcZH4/4fYVbIVzVbzu5ZCqNcPNIsOupgdTDerRQPoF0n1vuZXniTW3DKdj0Kw7hDXKRj0pLufpp0iL+azUDV8zbZAoTu0o1EsiusjxWKtgSNTvCSsAB8vcfvGrlwn/986g5uoB4Wabiv1N87IQxP3ZAWMYJI5LTblEGjGi12Va/GTa1mii5+j7NsVvgvx8fZydxlsAALYvBPA5GEBxJCvvk9IdecDvA4duSByDBRyO71ka6Ih4e9vdRN9W1jm5JHaEekWZi9q2w1MW6otuy1qzZMjVdCAmqdF+mC+bux6GTODFTdwsBk7jB5XSaSMADO3dZIc1IjVo7/DYs/RkiV+bQzw1eUdIbwpmdWTrP3dKB+7ExgvJBLOAxHelJtHNCH+7wl72BnMqPrkRjgNci3w8yCfW8sH1dJTUaUpwtfOSER2sXf2t9YrI89uQ0zwsPvqMLDqNAnukZETZWjjY27rQ5SvdmrtD1jnbP9s3cefN7thfLG/wq2dU50dpSd7bqr5O+ftPnafko8R8cfGEo71c2v7wsKD5Fp67a+RwO5PruOfw2g1ultvsJ1ulKt/unm9HGzYYvBMm7oMXrq2BGPIwM4+r1kZ0Vx5Duucpxb9N8WkHnt29au+6Sz9S47rl2HmlqmVklyR7xHKpRbBSKy1c3vL/1O7TGup49ZWaqTc+KnVq/XqXUoZ6H1cGXz7+D+S45b9uI1b27o8dam7WKP4z+CpFgBNWAMAa0AB+aFdQAGCcFgdc7HecGhYfSfjnkhDM4PtZD0ArCMTX6U2BV+9eGMA3w2AqTIRhLfIeLDEFM9jSRm7jtfLhAbWx7iwFnCLu0ObmIx7Y6pMuOMtMu6B6TKpFG+WiXZbedercvScSXEHvHa0bfrkpjL/MvaSDvyQXsrYUbxWJtTxpkLcsAYjg4qgBRAmWjYpEWbwH2KrUvzk6gKIEkEpIhEAMxySv76oGWxHuatnw7pM0V49J5H5FRWJQ3eDRwYWBq4qCDRzUydSwLSQKdahgLxX/1LEpADSQQaY3QBHAamMkkabkb4nDV12uKzAuVCY4sBPa2ExJuZLhS4VSeRE+bA8IC8vsUYA24h2YZ0GtG/1nUNGSMN35NZEBukQAHFNUAbtRJZcT6FEJvULAeJRsFhPhn7MCCBntC0socKr18T3CtwCKd4bQP7oN2wRgArAJC3FGrlL25Q8gNA6dDK8w1JFulRpnSBnKpwl7QslishHlwbgKEB4vbZohvWHhb6Dwg3stjVAI2qciKgIbAPoLZEj6Esg/uo7jAyikGER/+PaUrxVRmfxehl7ifVlFBEvsHKICtaWXcOpgaenHcVpSzxedvKJTNytD1DT6q/dhwGDU+sHeNN42MfPL4Ext7GIw6V7GzWbmR6/DRc/gnbpbpZVjGJ26+LbhXSLdBthdBtKRPpFXUQbCjtTyJci16hZTEidEojRvXIbC7Jm0XE3DG7UCJsW7RmkV1jJaP1+x/ky1tfocMOOZI7MNRSu6LCKuRbBAlBeXtTurh27GDsBiSn7FTXUS3KmmNNojxdHidv5rWeWxnWwfi5TuY70x14cNf47c3brOC/itJeEQZl5119uDKlpJXurPQ7q7jxy7QJ1mpSP+9FAv8Wxw7a5r9a7ucfk/X/pP3O5eaPV3TMC4vu498WREShuHTnmfbMezz0OfT3r93079PD1KLYahmftSrSe7tDom9QfRSr5XTk7l5mCctP+QBcUw6dBPvjQ9uW0xL4cZp1g3ldRmstC+zo/Z9Yuqo1ynNigQ5wzc+KGKdkSX0u5TVX3xZjsD+265rybE2zwoUmX83ZW6zur1IyVY2Pw1kOBdIc5qHOGkF5ReX3dVn2V+A1w7TZEK2/y1w/BK9rEmQLtIqodE3JffwevSxdnFqX2s3viRAnk3zZA/75cz2MDAVnPV6fxuzeLY+P/qLLPAHj0p+hrwNuH4+//bft/6YX1cywMDca7S6DuhisCUL9NKbrhLwB0R2uC76tWoB1Ov0E63fLhdmCkxSWW0VQxilPxfcPq2V9ijunNyy7mtP4zaGpzuHaHzyqazGNPKYnM19POrOF2rb2WV71vFKvm7Trij690omLH8nxQsl8ugOr9eDGd/QrWX/Ky3bpJZnckezxdNKaK6RT1St6oHk/X8or+mItbVrTnR7vWDyrJpxsjuino7PxBL3l01wz/7JKanfSib8t+IHKT2eV3OvsXi1mklTM9H92270c85yXb3UNzxq17nrP3HKETZvy2LvfKOAhNjF35y4n1Xt444CeS2V4SN6scbWz3SAiOHpusMAHVV6CGAVAr3SOjov/bFrfrOdPcpIsH5d1lmKjeySTT9Tf1E93j27Bdk8wsrXTzjn6Cae9AI8MTN/cZZZzuaWE4VdTPT7v2HPW5Ijpn+eVHFyPRmb3q+PzGbRpdS7rUsTMTR/W0qPymO5gOFNqbW2P6S7PcK1no7FQwTST1+YtRbtA9Koy2DL0J4ZAyxinrz7T0+2ro6+F0Mes6k2Ubd5hN+xzrrevEMO3PJgPrk6OnvI+2TZfPLKOdRC3L+KGwnkMaB5c+5vjzZ6/kdmdXnuqhMHuUd+zxrWxKoEJuP561mb+QkkgL246eqIeGqIOiaIMWZCiMnolREKVR1dpQ0Wn62UA7tEpEe7SOCpWoiF7oie6vIsqi4bEnmW8OPT/hP+iZCvqjc1uzfeh+ZcPpigzOoy9GjkXEbH7Ht/jJBwR8V0GKK5L0kp3BLbAOyG+brCcYDhX1gUWAbAQiwlfAJP4IHFfChYkRJJoqRpBxDe8vi7MbTEWKkixGqBD7xVG2iZ6NXamyPSI1XwkXNKaFCDw6dKcjhEcdtXmslAbppiAxEtgNpOO4kQIuQhy1QLov/cRQvP47KjfcFcaNFQo8ApOg07GZASOEdzQop9WGIj1OFEO6nZhIdULFUfa5QXRwRIwQul6QCPQ01qHWmG7KnC0nxbVRfEV6cBBfQPAFagEA) - format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, - U+FE2E-FE2F; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAByUAA4AAAAANagAABw8AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmobllYcNgZgAIIEEQwKw3y2PwuCEAABNgIkA4QcBCAFgwoHIBvkLKOipNV2jiiCjQMF4peCvzqwwRj5aGHyaBhljLHOdnTs2BiTuV25u1Hu0SDvNTVqKC5bf7FJY/2tfvWUhxyhsU9yefhvf/C/596ZO/MENLIS7fkLWag/SRVe3dEZrMT5e53l+5IMzCtYQMlmeYFA9gLZC4DVXbgFmj6TOlVKwipFmaK64Wlu/+5ueYNtbESZjQXaZAxjCCpRNoKjU6Id+aFFMKYyaoQxYtAywMYxqhTQ/vBPdI/vedmZTYC+6udyoVIBzj3aX1+exrsHsGWqXShK7WrWx5UudbrMrsCMRWlnesTTrfK6WAaWgf9eG2zfRQtUtE5SVEBVcvpT/E3C9vzUkmry11e6UhpapxbAcjihCQ9h0pP85adnbZG95a9SXK7putfXuvdKSmuEBK3SrxW0G+IsC2qNBweGwAAA72iOhQUwFtv+RXfa4Civ8G7GmqvL12C2mdRFYfNNEQkiEkQGCUf/fQ3XR7QxxALR33neIsGoATgNo+Tnh8SQEAYDadAAadICadMF6dED6TMAGTIEmbYAWbIB2fIAQTBgNDAaAhIwUlANYu/+nhEI//XZ3YTwvzvlDQj/t9vfhjB07cLuNmghakaABHRAR+8TEKsSkPJSBLB9SgfNQbNsb65Ft/i3F+VVc22uDZ3drmVx0HTFEzceQoeaob2ub5N1b1Wv1u1zTauP629yC/koi6cUl8nPYD04sq1Xx/dt4S2hvWjdbbkJrb/N53Dytwms3YYAtvGISlYGi22i7hA3SiY8i7pqqDGbIjPCHmuAp/1ZRIhXIMtKvrugCkXk9foEJQb0jPh64OmxaDhwTnywcUbLvY2vnhErvnsQ395nLAGmiDZn7yaGCNUYl3ViPFFTqJ893pqiIh5uSgw3rSisulmk17dQxZQR+Z7mNlqqTeZpidXQ0hYH4nkdBYLwB0E93DvRZtCh3/p7g+hL+3jEJQ6YFS8EbDsuhWcrNCDB4hD0jl/gEcvYD2uI7fkNjSXo+Fnj05VQxjZL/f+VHl1rHAL7rkBT7Ro6mLJOtbs7JCSxzfLXS4kiEsRUM1WWJyUl/+8SfW/2q9rjgV7PhUmKT0BQSFhEVExcQg0SjVGrTr0GjZo0a9GqDYuTwStq16Vbrz79ho0YN2HGnHmLlghKlq1Zt2FLRdWOXfsOHDlx6todL19vhHoj1jKyOUwijQmx9Um2IJ3zmfrkkEchzyfQzp2GLvSin0eQLTSn0hvVlu0BB5sfNe64BacVXzFf13xvWQ/1k/DVKGSbNibAN6wCd2gvuGaVhPGDjYv1Ddk8pkmNtUn2dWR6CR1XjKsaH1v60ATd2HzhH6QBWqEqH2VU45V06zzHIMsdlh+mVeKNGW8zV3Cwh4Yp+Poq0IpQJkxcUxmyJZivBEfF/bvuyF5ktMbL1KmHowzDGdQzqFsoMI2l5yb/Mhy9LA2+CR1NGqYhUCjRFHKn/JAZW/xalh4YzWKBxoQ8jTYiVnEN35lsSrZpwyyAKxpX++ShUTdGMIoRiDCqRpmDcwNmcjMYcQyEmRFiVDZ/aIkJ28KseV6yRemKM4Yc8igwr3C7oZO7gF70Y4T3gAM+vgOnuMI94+PmZUetuOaUwDE2Zk4HmrsbIVEc8hCwm+434zDzCXC3uQpXuWxPZHAMx3AlOy5wMOjk/BGFE1zjTsTHqH/mB9zByQDlHbBCQBusqViRUrrohyFjtZv5kHGCuxUSXAtQ0mxLhpEctVyUr3MWwlcH09pQfHQtmWiPNdJru8CD9kiqQT0NG+iNsW7FRCPw2zGNNU/tdkqcSUVaa5hbBjO/75gu8dU7DFlflR8IbyxrohMwUSYcM2YyfO2kPFiGi0UJNBi18mfmjmA8QwCC4YMAOwPO+hFPiTJUDYs2V41MK5i3OZAIBNpsvhVpedleOyz2oq1iJRXfL/2LpkfvwuRy9K7MR25PPozoePJNbP4ACRCYKAfRGJmbBtGUZw4mYtzCMChq8m46zauZSs+5UGBGkFNqgTF0ipgsCRhPTUlFRAL0xHSkNCRRmqR5UXlUGJ9yI1gVNIhGlYOubXpAL6Pl1Tg13AYp0moAAEiytlk0oPszgSjqxAopBXE8iBWIhFLtlecRCdGuV5Z217mwciu/8r/cDzy2xeqR+3xjSiIC5bFyEKR59x+2/9jyC4AOXmBkSg789rcDynw/A3gH4OI7qwNe6GlA3lw4vLz+o0Mvk32he5vwv0yM2lRgeUnel3WyWbbJyfnpAnOskhFLs0rWzYyclDnvjH+JbEFb/dP6549hLSiG158G7v60u0zzmeE3y3Z/5OcltVUQVhLhPUfD7wNWrVpUI4Joc52QKCnoXuD0diWlpO3JyMrJ21cQCfPBxeC74MHYesiZcxcuZfdxo67cuzYG5fRBLFZ5hQdsaaz10GHqR2DszyDdANJRhnOFu/VI9ACmFT2CTXuPlpoPxG2CT4U9Ag8as699fI2AYrsvpXgBkqkG5R4daD1fFKDBHDi2tCNIOGhSIQlQ2KfS3Ge3TjCQKCl1i5CGAgtYnBuj98X5HTnNToAg+PPbBadQNYUksig3QEkJJ0lD1LqglfNxpx7X+TJjEqihDJtmXh++5rmF84nyF84lHnshMJZg2x1FHt8ZGDEi+1H9AVtVbjA0bityQi5j80dWNoc7TlT9P559D+CMOVJ5K4QwWZBZYk/5opa90NBvwJ2ngFH5MbrmhNHmxy0VQs9IUYSmy4u4WUJpGOKY+1M1laVT+WqVbNCX5Y9/G8O2qZjconuBk+uey0/7AU5OyNHADjXwBTfnYWEOigvIUED/iQIvB1bY3zghjd1CWGtPPhNKHG5oPb4tkSwLR0w2XjmjHvvhaWWOHHp2UwqMSadTsdRiBxEfWHjTBzk///7VfmNtjHwn6dXhHeLooL/5i2UNp1/Pss2IViOFleEbVasODTurQba/4ohhk0stUgGTsJserYfZyyuxUD8Mb1jpJQIbS/u6/kWY4KlvfGIUvBhQvIeSWZybh8IUJKM4y6hz+ZpJw34lKTKwWc4XBwrP6mc4Bf5ErLFkUtiigesa8L7RwBw6UDc/BLnuwfODrKmg0ySAa+3QF8uNh71Pnw8VNU6lY+vDUSLPBdAFOxRRvEWtpezH+LFPmF2+KXkgkhCioAUHQ9pndnp21MDWYJ02UC1BVCvFcWBzMnWa9Ao7ocgZFMSwCbyA8xijQp4wvzQn5LfP4diNz1UVyN0vY0kkZd4dp7tFjs4NMou4+Ja4MDxCk0d4MfgZQ9nAd2HyHxIuZ5QH/yVb/U1I8bFZMMxovqxotGJ/fb+AK+r5CnFWitF5bPrIV4tZuxJdD6b8zFdy6wP9SPfOBzB4Nw8Vb/3jbd+XZ7OCWr1I/kkgHPhfymTnrj5Z4uSMQMrvD+2H35Jcpy7mOUhkZg46bVeNx7IslIKMLg7e0fM/QWQJjdD8MMIGj7hTDOo5RVB1BXLSYCGcXhCUpRR46DOyHPmRYI83G5+MnTBnONsUpiAp4COMFMHCkKIZAe9gCzY08X37u2c4noW6RHqsTS/dHM70fiBaUQjTbaMOV86y340qD2RUV4WcXH8HEfKY6ki10byVWCuEyMiyNx9vom+1ZJtx313Tr3QyS/oQrPmg/sqIP0HeNdN9tXWsaTH7cM3jxKVVX3HDGtEHjOJ0JXbam7ybiSqYtn0fcXX0qKDzp0M22iHXDiYoF/eoNOa5Dcdi0ZjfXfPi24ETZnsbrSFypmCWFyMWz6sFkTSFxkKiWVZm0ls8RvhkbZFbOoRCGRHuZPvyklU/o44qKxMBL7Vv5ArHDLCve0pS7xbyh90IP453DoWDbzSQV1UQD09R1e2lzlCjpCtHmFl2c80jP/2FkmDRIrI23CYtVAdZYEextEdF0UiRTC1Wyhu/KLa6modmMTf46cW5/NPi129KA2pRTVTD1vHDr2QfQ5ji4wQ1LlGfHs8s8Yl7d9v5AMvhI06XABYvFarjuUDyEhcg0OXo/SyLgCN9/qYtfoL9HpwSGpZTe1ph2LsUHKcMcMrB8KdWyWdSvcvX7LbYVhNcyPw14+LWMivSdhBdnUz2k/S4FeaB7Moig6DHIWQ3iWs3bwRg1gDQKdW7Q6SNH8FGwoLA2/PYJMQcNaF67dVz8cVhOpEFgBPzJPaPyEH1mL8bN/+RuYe1wFYnvI1D2JiW7IMPwUm4wNESaVPKCaMMcHyUchsY/Y7At949v/XrDvWUAU79TbeWWgPA8FaVB46MNVOBLuOVu+jLXUgT0jdMes1DvW4n3IZ8kQcFtGCwrlDYeFZs4BT9+GP8b8Wxymc394GN5zmU5cId/MIf+g7lcNrTYIf23SSqdoEly3a30ncLMOh34c4gj5/YLKy3hkPBGtb5HFYbIkRW1hKWkasHtEJlHC8/KaKK2Vh++ttUJAJ5w47cKzUBq2Nfsz8lIfWYn4rbV+kBwPKo/VHNHRoDoqV5arNU7/aFpVO5WiDzdSY1muIbkRGEXACgb4DWTJah8fi/Ac1KuTpgR1FY2e5J1fdnhP2QKld1UnPcoK0XbKx8n9C5pQtwbypvT4spRRKgZxx8OLFC/sVYPSCdJ9pau1pDl6AEa4oJFxCsQ1I6GDehMoTHJxdayGGMZQeo/bFMKIupZrz1czSo4N4g2ROMLjiCb3QBIt4gJTKk5ucQRZGhcCnSMECogtVx6uiZ11Ip4V1hSB4SlXrFQstu0AWid92GS3NVsiXBaUqAaykQV5L4xyq33u1rVyFXXEZqocu5QMHxmISQR88ozguHNDSkKKn6fSEKmRLLvLVK5PivfZ17yTzRSx7YFm4aBb1MvPSXnC5Dy03/fy4+HomEXiVa/pBII99nk+ZThvVccFpED+9YR9gSZltfaSK74y+akrx9Yh2RWPi1SLYKnD4gTy+OwXeE+sE8xMHXlsil6rwvAnTviMQ6JBt59AnzinKRizmb4pJ1FclB3DKscCcSc5FIuP4tqN9Mvh2zh6c6Z45vwCV8ryqFiqDOOiT9OYAY15wsoMuQ1r5Zor7E5aCdVvK1+7IzsW5YR6/0VlNXuAIa5iNZleAi65aTPZTIBAtPtsR8froOr9D8LFUl9VPjrlXJd6CQKk/f0bZ983wErg9W16NS0kfPI/7n9lmr+5EqNzUAyRJLyZyvve3kvTzRlwf5uyVzRYt1lH11ol4BUPoOJvZvyQNiLol/jAsONQ+R/MtTghBfKCUZ8k4BuORgRBeYnyOpA/10WhlZhtZAGeA4AVb9GVeDCPiV7gOmJbRf51sL93vAA9DCIrVLqn/D3DcEZd+DanLJCZIR0UnhkB9cusenVH3jVKVcA2DgVs5n0BboOodNxt42rh7Tvq9+c6cvPPml1+Hux+QHw48wK3/aYBWlnI0Yhec7sLfUG0McLsKZmJacAxXg/BjH/pAe6MCOLFCbaJ07vo8qkbfQFrx2rc04uX9Btg4xlspmhGHvT+xEpD0THnx543DaAMS9LJaKJPsFpnoiQH7paPUtT941O1XQCxY/kuuoLdtmJ+RZ2dU7+fxNqJ/73wrVB7FNKdRA8i3/SH8EmDXTAIOTvb0M+oy8mZbtM2xpMGrFa3uQGC5nrsOx8Ksdga/qyVto8Uq5+oC+wqmGZejVdUivLBN6dtK54ZTzS6BXQiszfH4YDIEZEbWR0rJtaUopwmfpA4WLNhsNQHxTLjVU0sMvyg8BZnZOvJOOy6eceBfg61B3mWMA3SQ1z4y8hV6rGYw8gyUcPT7eWlZ2u8QEBmcycu6w61nsTJj9fWsYeqykj+hVcsuLd8srZcxrSrXG/PtHsLX/UFp9uKSXxJ20kCAoAKqLprvUAinuruE+6D1m4SOlktqPspx3W1fgXdCwe3zc9QyoB/k2QaivBXj31BQ/RBuK2HTulhElUNI9JCQV8xBgOTBs5rxqeFUJaabazq/PUL8MMM9zKAJl///FT5SFqkuIlsuxFlI5KpH4EvHO/2X8Ex6ACIc1YcYjuw81MlKee/tATydl2BewDtr2akedaOd2CsDJiDUqbHjqniuBki11v1Z6c0YpWL/1ddU2ftlM+h0SJY9S+IyilF2AqO7o4uwRb5CtzhotIPURl66t5cFgJfk7UXxtTS0MluRbZRqLxKU4QB/LjZM/kpJ+bbU8aY2Cczoc+B1wuchRbYM+QAPTskKjlnrDVry2u1xxN5wPDx/2rwLruJw77DGyjNlCHzGSgrFJAtb2I8e3Vki8ulJ4wvoy49MTQnU4hs7mh8E7MDlKrae2bV2cVDwa8gkjFgTINVq+r1RwsCZKqBDRZwtZ2FWaGv9YL1iepfR9BPu6caVx2fFIBWYGr/r3AFDK3RGlCNdk9CUhCRh+kUp5HdgzdgL/ARsLd/l7zuBSsW6GnPdaeVou+/xhIfLzn+QL0FgvnQV/Krh6mMLtvuUP44+Yld26vuulhnxhCTySndpae9XTkar9vNtuR6+0ooFSPQcXZnuD9u/F5qJvFL/wHH9EHjic/AeymjPB9v6/PhAn4PwwKXLrmqXtG3sxEdDLuAuLlISTxltNt5Z8VXGVvrde3iWdaGPoGaOvc7qv+nRp2aPMrECYW66Y5gKfg8O8c25A0XBdl0KrJDug0hsBKiT+sQAgAG9TiLHELMF5MznLYOQsNnms9AW0+P6IzhrgetcKZRD1bE1tYYW0TyAs2Rw1kY6fwS0C0MQqEKP0gioS/1gW2J3q4hT1Z92js+ml6KaiKHNhperJD6onuWeEm+AROOyHhpa2liI4/nIwjDHANR/w8hr4Kjq6vNr9oinYpIlr2sSybpqolpbaPATAvrPvebwpQdfe4oIlFG9DNXkOKGk/H1dAZdCLYuJdYvbLC4brtf0xDOwVz/QOM0+4DBLWYtkcgJizrltDzlCKA3pWOr8T1AClbKDGP8Yj8Y9xCWHErVrERx9TSWChoKEzhtH5FziYmcDliWAKolptHwRaacfeTUkVuqnAkeEmc+PQ14auNNhUqsDOFuuXv+6RlLPdO1DwfZ2D1rjubBZ2jRY2UBLZTRDvrmzWHgO+XEaXaPcsZDOEX8yFXODHRTcVjDi9PHcYgxPiYlt0U3ElSi+2VEh3ARvdGeaQ+hpmD/fCgPFGBhDC6tNKzhAL77Vuw89FRzXMhIzWm1VwGWX6yrog6T8hXIMySea7V6dpKqFaqAOsS/lWgtvwmiCWaioIhMpaFLhq6pLnTq2jNebgRMkEMX3/Tn8ov3NdNyBXHuOi9CIRuqmIyx0NdBgqVFOXBdpVhtG+6z2gp1DdO+ma/ce5B06cNaak5mJvwdFr7RSrgCLm2OccBG/qgnJvzHtBGgYKjpewyXGuvIgAVN00zX6oSE3939eDlz42q+7+DxQiDbUoGy3+1sbrQOmFahUs3Xur1qFIV4nLKPP8dQsEWPNnIQ54WYdmfB43CKL5DCvStIV5nYkk7w7zvlD63YBNz6vtIbYX/XI5IDqElrdZ3wA34CJ7+zqCJ0Ydq75d+ffOoz2YYkTwAX+/HGAdr0fbICzME47KoyRFdjg+6c4TYOayrDG6cbWJiEIaE5i/yGzCBuTg4SFMAPQi7NIwGgHA0GDHNnnTfQYS8V75t5C7mHaxYpsLRpvg5RHnhMRiWkcUqsHpZZr9IvSL8erFPdb8czvMsrGX0Kxf1TX4s0Tj8xYmyAZwyvk7uArFO4FdlbUyh+H4rFokE0nqplUS6Gtl7jfVpiF7DOlrk8n7Yze+IdBlGEepsWlwCeL1lOCA4Upurs1TYOetfczd//5kwWKILZRzR9G2ApAdw+932VyHBZjebbKzO9dAu1UGMWWI4CN0v/yGa6g14oN5WqryMEGRHUZO96gEGo7H9LL/gWJMw0NCEiFrsbGxHd1UoMNwk/M4MN7Umwn0aQXm0piI7sHTrqugDMXeRC+gBhaWVhhwIV+km8HVy8l/o+kRIVFbVWBFFLmXxejgr5fH3JCwXMC0vPgX7JFu3KeCj8+qQdhQSietxoPP9WxlGFBjU/381EONsYr37q4p564r38NPojXpbtY/5VB50sGsGA30deQRHKf7/1RKM+fZcbPHQPVgwWTL+iZOqh2vBO7JOUyFeCa6iZ2I5L4ipRCY1OKel+lIApL/kpSMP08u6G81eIm3N3Q2gEzg645UGyXUnoDNi4LNoZs3Je3W8a+8lBN6Srh7VlKaOWczln229HkONsY/c42vHx/O61xCYi6F/PivnTc6CFT7vGTyeAYPT2VsCqctEr2Taxcdo+AwuPv2jTZsQD0gRsSmhEDRUHWYpBs9rd047ZDhOoUQ6VU0TXz23S4ejgYjdzxacYE8QAj5L2MDwgsBEyG2ULa7nHU5IDuF3xdcvgZHQnXRFsuSGRq07MSViehY5AHS8eFBGYCuuYXaInFw3ZDsyx02iBbO3SMKqL0ivrMi8CwJA4r30qWKqJ0lmn83/+7LxufUN+CHkcP7HuXyaYP2ew0K+ktPpamLbe9sfrHO4XEjYEtJgMrxQGl3t5UHqJxPa9LscGSgW0pG2FiuZgd5MpgyRAqX4SSVUpGp+5FNWqIQdhGxeIRIvFHCrG4opZIqlXhJqZVYaZRW6cUQ2JW+wpfNKbOyKLvYSBkSh1dVsanTTzH7UlZljFxlbedWxbSLMjXtozEDuzUM/YHgXaR71KKEqkq7DBXfpy2MR/73rWbis1r9L34CtoD8aiXKg/xi1dQJulRekf39iD6Vx/gY1lahv1zFHVlQDlYV799g1atSPJmVH3Edz3hxBe569cpyQ1WqDG/zzHJn61ETK1k+jI9u8uGX4j6a5lcR+MatEf0hNKzKrm/y9GRzfNPnS2YaZkNprrMmZ10+E0PfBfyvjV/y5fHZfCz4oP81+1wrrUg/+D1lFtXUqcoMNEjf9BaV0b1dWkL6W0QDoPgHTpSZuEp5V2du1Sxpxg4MIMc3YRYCukUTn7Lf02OjOfGbVKEBwLs/6vYCPk9nvvjd8u8PonFjwchgAAnU6/5nACOmSjP/33wHQK9bbvXAuafkJNLvoMyMJzOMXTn7w8oHT8G+tuqcM+T5B+zt7ZbZOpoFVKfCN/iHEcKXq5+zlvrZin9m0c9oSI8XfpxiaFDUEQf/VEXJ0fdv5+OPtII6Vgmfz8hvqsJ+8OnqOP5YRufnpvy18u2myM28hv0SsW+ZeDglQpsiv9HRPtPev3jTWyW7Vn6sFnLvBLmd83Jf4GdS0+rYv791zp+YnHOK44M5Rsipjfj9EyXnD99EoOc4eiKjbTswE47+yzh8C1uuZ4rqg2s6uwz09RCcD8YuVWcNTlU1XJvcbBxNw+Dx5r6bF69v7ZRdQSc2NdJ4ggQ/2FxfvAJWql6fEhG0Gq9nsSaonu6B7IUhefSlFPyEjTqgnnQPmuh0gD9RVETvOlkIAXVCPVEP1BUhIKs+F0S1PvfNmTN7fVs/4A2zMSJVvF1OYCbpR2yW4VAeAZwHtGsRpTlguXXGPTocdyWuFQl7w+I+912r2oif5T9p4ORga1as2udVh1FL3V7tKq7Zm8o37rRNQHG2wWbvkFv2VFO2x2bXYZgSqjEVS4Z97jSzaHP4SGH/SO+UsRizZw2ynQnUmnrN2ISPbOaFSCI30qo2NKkjpqSLqhZNGeXX7lpBJ2Xb6Xmv4R5L8vhPLgmPTJHFwEEsg7i+2i0AAAA=) - format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAAMwAA4AAAAABZgAAALdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiYbIBw2BmAANBEMCoI4ghsLEAABNgIkAxwEIAWDCgcgG3YEyI7DdHsjE9IUV+CFDh74vPL9/MmgO0un0soqjWt7En2kQoCMtXsRxyxkMqP9iO6NfSiUaLJuoRIKnhI0+ImbcWOB5XOAFVmCgxZQQmuBJRhZtsUCXm/492Dyuk2YZJdkdApZeOzyEQgKOwDgRjASBEEBVmAlgACtOHEhpjLyyrACMAB0vaLa6cAw5bc5bvhA2uwO7zXAyKPmkYNnAJgBxLEMDxFLqVBPI6EQ/daTr/QOAgfCngRoZc4UZiL623qCkf/oHVsfRCOuAIbJyF4ajQQKQLmQhNBAA4aygH9b19Xw4iAC8DkKM6WrYw/ABMAOWEAamA7sgBWACgAUSlc3SCmlc95o45idYD92Qt/+5gF19v3FALtB9+7dq/h6/Ljyu/zzYfnngwdlHxO+k39nOcO/e7nPf2vCoo3HVlmNTdnWwW3JZffuVU6cQX14kb3qUGOOJ+mjP9iMeb1Nivq5gXpJUWm+cmVK56e6PjI2uce23hHlG48vyDvym5/5q+wbkjq90rN+z53D6zXqmVUPVshZoVtrZgc4vleS1NNrni6VR8I/vTrpzpPwu1+1Pel4xBIzK16W3KcLNnVGl2RGZHbPXBAvhw4M02Ci/t0BBfw/p79XS9V7CKAMF0++DK9rtI/7MXvGATjz0TEA4K4oef476t9dS555BAoLBYCA6ei/FSzVgvg/cIR45gpTaLWeLiB+oa4xJuTks7r7/xwCmCzlpoJKALCDQmkyEsCsN0mELUADghGsGgAF6c9IXkabDYyqg6WMkZd9z7BT5gaphhhqnOH66aOvkTQhggQLpsk0xBB9DNSLJttgPQTQJBtoIE0JEY2wb+1lhF6GG62XngKUGKLFECMNkW2kZgP10+M31GZUwfojwkU0uAcQkISKFNtqGMlau3vIjjRUjMANjYkDNKeouYh7CRBmuD4CHQgHG6GXET8oT7ZU6QqUStddiABBJPSv6P315AAA) - format('woff2'); - unicode-range: U+1F00-1FFF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABX0AA4AAAAAJRAAABWfAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbjEocNgZgAIFkEQwKrnCmEwuBSAABNgIkA4MMBCAFgwoHIBv2HiMRwsYBgKA2n+CvErg5YHVUkRAJo8aMqlEXjSMQVVUI6BratcEu3sY+K7ZekZeA+A0njZBklodqv8j3p3tmdw+YExmNDtAheGKX00EoHxYmFQmkWBjkHp7m9u9iY7vbmoqRigEWosAXkErltiNG5XAoTBmcQQn+AUahfoRWfpmA0V8wEmSBYEEbCfqjFvQsfYGTMtEF8B8A/Q/gH/Cv6Te7j3ct9L3rjt41CA3K4LLvWjZl/uaX4W9oNRdKPr2H7jgL6jQS1ZoqpSsOBRLXhEI4hwUJGhujCVj/LcbY6dJ0qD2ma4OVuMgfXDi53SubwDhW8tKexpmpkSF27EEcOWQ+hyzkkMUc4mIyd7WCu/HmPmK5VAppTwWWnVdAgFxyvMoF0LPPDSWAw3VF+bnA4ab8dBlwuD1ZIQcOoNtuyJcDHgiHPlDsNFpZIAmo0nzO01UoYE+jI1djPK62RW11i25b2/4sa0daU8CIV+Tk/iiJyuiU+hla6b4Ymsp/SdD1c54WYrICuy+DAnm6W+LBnUx2DVCOxqn53kqk+eZrgq/O7P74j7aIk+5z1vtg/Lj/SWHqK7OfGWUqjh35+oQWvdQg5a8d64pqw6dbvqMlDoZHj9/Hqzc//TxeY5mToe174gl9Z2qQ2k6OWKlP6mwi72fEfM5dCn1fuVRWDLlqPpr+5U0wKzsnN69AwUJFihUvWSYoW75ipWq16ukbmVpY29ja2Tt6ePnhBCWL28URN/PpHCv5T5T4q/x99f/W/pTgmIFEvTPrMyTHpKDfQEq9k9YnsWzjXOPAqJZx/QNGx+0O2H/ieADJ9pDrobwvLQ+NPoSCJKiS9/QinokZEfdBwqSUmbS3Ml7L+pQzpeCZomdKxpQ9V/FIlVrNsNNnLmdun3vUeh3x/dyv1v9zsohPMc+kvQPJct4o+FT0qaRH2UcVU04/3X70+sz3R/8fcWJ6pX0AKeW8UyJS9vn282uv78//n0kRUyBZwZSi7rpTUKV4vGPTou4R915OoDAtpyEtOMnIj2+88H6FmJjZl74WQtCEkH6QWskdmBHdVzXOyN7z9J0QnpmAT/CWEBf3VfQL+YMeADgBd9lWQyarMqSzhjI5ZQpmS8BMgHrJp7T308pXIEzBBP9AHPaSPg71xrOet8zDhtfrai2qaYvr4jS8hvswNPU21BZfBHfetK0hy+KIMIwZS0AojprPaRZfjs6DNz2+orBJiFuI5Zak3ErSdxWBmPHHBYPATjrPdEsTM4h3IG36hMlLTnJwzpsLNBsGASu5UIdIzeLJQcz5o4MnTE7iJBDQsrij4tG6YfDJJcYByHmkBCAv1CBxJnsvRfuhFDugJdqgzd427d48qhCZN+1GA/rTfSkw7UxPJD6W0QDoeuLB7D2fd0FEAICiIrQD/AfAjbMjDYhALwDkWf0UcRHEa9ajdRBQ5Ki+e9+AB0EPVdTE3miOU3Eh7sajeBLa+p941D73ztgXrXE6Lsa96P8r+Lfz37MAS4U+w/5/s/5NBzG0GmcHN8DFrraJCQ+mvrOKJzPnbjxAIAtBglkKEcpKGJFw1h9TaZNerS07a0UhiEmQosVwEkfKWaxFFltiqWVcLBf/uycfe8PFSrwO3r+VK4B+Elh8AUwPAtP5wAK0bRDQGcBbcXtDy6lIWQLCkOYkCcv3g6hsTUcXrpMjTORn8GfKQH7nOEwmi4WyuJiQhzMZLCbGF+ixWPosNoriOB1FUCFfD0VRBttQT890jglb35BpzXW0EAowJtfU2UifbSPkCgzNmJbz7XEzI0NLPofiKqmsHIZMys2BZByKE41ReBG2iZ2AU8nVGkJNaIpZr7AEaXc1HanTSlJSRXFGexA8ik/M4gqxRBEvCKXcRJztgkIimmoLcUWRVZQsJWYlar9YilrCWyoR8VCt02aXl2iHh0mdWPNUrBkcJNSU7rLUDTNojVjzhJQNir+hSraaPs9SYvoeSSElwxXZWE4WVpiDF8pwpRRLLMZJPiEgKc6qKE3WnTBWl0m0cVI3rJM2iQ3zbNHpSJ1NBYGaSK3wa4txqnHA9Vy/eUnfss4nqdxsSqq2HrRJ8SlJtUQlicaoxFZdALYeaOrz7dRmYjero/HM/6FM/fkKSY0Dun6gI/MG7Pr4QLoBiqPEKD6FFxWn8ospFslWaock2mFSN9YDi/D+4KskQuVgtHpqnI7CdRqM5BM8iktwqDojxBRnCQsV3KYmC3OQDCe7YdNHrwgCI9dx3RhJ4gp1sChTFemOG1DqdIU6HZmIS9XjRDQWpx3iqC8bUXiebpgkSfw0oAhWVw3FrWp4jAnbNQ8SaoIkWJSyyaTZBTcS3/HXStQS7dCsmhJjGVJRd4aMAzuF0jw4ZpuwWbrMjgdfv4iUNzS4JhuTkJkUrsR0XDG+3oBYIya0hEotUouDNE8JY/W4d9LsBZZRTf4F4itiol2mQNUp0XbIfzNxM4oh4UJXjYaQoLRaUSwmKCLN4xpbbE1JPEW3SiQT6w5nZnJIitCJx2JKjGq11JqUcZMfF3PVyZqng+sTg+PFXFudZGiTSeZAi2niKOUhkzqsDiDU/lMPSVHV4iKNHz6HaFum0koSlBglOXN1uYMdeY7SYhVnxERlA2o0mocakbpFEqWzbbWfjdPNbRLDmShMeshEg3e5EmqrduKjzjA7EWG9H5lm4p6eJ5Fisi6kdJ13JbnAeDC54aZ5bLl2iLTSZRGVpCH0wRKyQiPdFL5OWfKq5ufhPGqKJTUvwatDxDW0kHxKSoxVw7FeScSN4Ol4yohgnXYIkyt+XOxE/8hxNZ4ULZkt3rEG0UNQSl1xLkl911XG4dGKIiQgQElHhRXUi9RMRie5Lq0ZrMOVPLcbDcdRdwhCTbArxZHRTdaa24+0Q6SRzsONo3UB+WqNOI7siMw0r6s6iDiGaYksKZaYoPU/uExyH9cgbq0BJZPQIzOLIKm0mC1WP1Lz4kicyPg6avBXGCPDs2I0/S4urkSnnVoiic3CqFithCBvz+0BtFM9SLoU0PT4ZX6bPuKFY80IFL8DikfAiv7N4beou4s3nmoX0E5d8DR5qTwG3LmaUz+Bl89vs8/w+2azk+2TzjHknB6LybHbHbH4XLDj3B4Oxd64rnwjMv8IB2w7UcrZwMrOlW1BLQBow81pMcgds/pyruZUkdnRK5EDaaD4sqLpdj7CZa7m1OXcDbdmXwHopeYGl4BVi/pq1NiI66R6Jnq+tFWbR9n1AxvxKe5si2NPy+/iK6V6bgpy9FXt5vk2xxQkLSg6DSjuFlXksHxzrjgzfoz781hE3iUQKVTBD7Zt/IN2hKb0Tm22KBDXF9xB1MhXS8YskrXEp8wgLf5kK2+sjtZzYHAfsh15UlfpxJ+CvWg3657vRi6jf5jO/V+4BcSsTFk52TOaACMzH3i9/L65H2dWHfUBh28e5u3gFm8/tA2JBmCjEfRyDASX9B9Vr9lRP+DYWt6xYHr50Fr1ALS8a/n06smgO30gRfPh6au5Az9I9S8lOupHVT4Ar+ttzOpppoc90pSzZkeHTA6CORXhVdCNXdJ/OAcMBEcP/Pe+thaphH7bFfM7az/neB3+Ye/LADndh7lRWZ0Gx8B1CZnXOAq9uHBcWVSdhlTDN0cMu8Hxf4xTv7tmo++mYvu6nQHs9hh2/ee+exynSyOvfmxawD468uki1/niSN9dYDLulpHHjHJkdu+Bu2lJ9Yyz1t14j1uLIF/+fTNUFREcrenk+Q2BNg3w8OJ//rcA/oNueLmBpgfyiAcF77k78m5k391pU4MCWzUwMfQ89XOkAsw9tuPqbj3Vyjmc+njkkpPzpZHTg7vqT7915lzqH7kAxR8FgQcEHRwDgXefbjpYZH/quFB8am0fsKlfwvZ1AG5f9v1uWve7cbnnE+SbJXMGTXb29q6W3nTuu4IMIF/NGd/gKOZaPMpy8EaQcZuBzwGk2P1qVVoKfB39P2+rxy0Aq2nXDrzah1yg/2U6Fwi3AKeeKntFVb/z11MdvPRTv4E59TvN8lNxojyfmdY/R8o5Rfc6xaDgMsdAcE6T83Fn8PkxtuQzfIpR0zrXoHX+RpVnYnt5GOUIVqq/7tYbqsn+wt3Nbfzlb4OadsT2xFXbU7tpQ9U5M9y93Iaf/zaqbUfsz19pmdA/vqu3hc0Yw0/SJgZcvVr12/feacT7f+3P6o1owH96Pxg/eGLeEmd8WWo3742H5QdDn+wrvrLHFloX0xGSfTmaw/ClezGzN9WkGmGpbVdAcVOdqNfI/htPqZcD//j9zSrkODrxR2A3sgXen3Uiwci4+YVZvQZqgucuFZZbnO0U6dUdhbfCvRsLXjBU9EyP1OgDEZWb4nWwWb0O+Ni5MXwMijwC9vC/MFUR16sRbsP3HdeQE3CnmeEkFjz/D+CeR6/RyHqn2tJQNBIuzz2QDrXCiish113PHKZXo13vTO6DhfY9PyMPtex23iXNhviFiRcYm7n3TP69h/yMyKXi+93cA6d5G1QXdNkseRF0uATLZSZllSQjMqhjp0DOGPtOVeUaVAZdOMatYK/PbEhCDwLTg+CKgclNu+s2FayIh13EG3zs42mgP/ueXjvS9iNUBO1aLmwqXbUFEivCGjnSnV4BncFtpsIbdqKv82360UrkcpX4I3uPveGZwX9aLBeE2EVt92pah3ph1ZLVs6FQBXrtocVdzo7ikVxOJf/mJEBfbN4fz4xmBFFx2XAOdDyHJ+kE3KP4xZuoCsp0aRUzf2Gem1zjbR1agKymqZ7+col5/VdUfRKuOQ2g4HxpCpxbF4tHCvY8pg0A033Ap/eUYUnfy/perfFjZvDcrCDTB76qxcxyZl3vobhoYVgU06cowUou+n7elp+4u8xw7yBxSKppHTC2c9ffUdt4EWlHDj7Rv453irvwzrXiVawf2uAOZF0Ho1zw6v1GgmGhEm7bEvwOOQjnhz1Pbtg1DdO6kHNM2jsomOFr1r0k2HCN4Vl34x2cDVAQxjtHr0JOTM39+NdjI4NtcBpcnbo3Bp7BY3cD8x43RrmjowEtKBy2WYnX+fP7ZZCsDi9nFDgA44l33XN+5diJhWvLhHza4cENkcliK8XmMJMBZr+tgrf0JfOY9foSvPYv0BEzttjH1JzJYsVyUnfK9wEVMK3bCm5MneAdwWXrf5hZHW31zsbXBg3I+iExMFXyy3c+Ww+TRscW+IhmCwwN8J0XH51YIXVM34+Ksc7W+J2RPXAZVOwAAvc118l3ORrQQyK83zIOefO9QS6UW4dXyGoqMGFzl/5/rs30kCPY7sXLk9zxD/x+Vy+aD7fJyAfwVpyRLKgr+XKnpAS6hKQUJTG6nc541RxCdsDdDwx+ZOTQW1JP5iJF0PEBi24wpzPiJ6RHxzzxI6DnZpakIWXo5SHTKx4WnKUpYvP9rswq1D+nUeofF6PyD2b454YZDj9acYsu6HHjHTjw/2QNCLJtFsC7Ogw/Mi3eL3V4QFsHfk5Pv8bYiHrTV1tZfXF0HF4G3M5U7spvlCEq9PoLk/OMmBBGnqIiBc6G20vJaeCZ2paVV8ciAq2PWZSHL5YCGZRxgLUnp2aN6QE5MNV3y92LSuODsv2hVtqQgm5gwCyz3twF2W9GSzkVK/sg2gnk+EfDB7m1AOK8NH+1wnxCeLwNr40RV5VkF88RlLNl23fnGhU/YmXs2bYO2gLd2Cf9nV1pOhu1ENEnHnTZpFy3fCekXaHXFran6J3le4HlnW5YVJfG7oM3Q38hXmpX3Ak5FOuVmA/pPW2t/CyIutVF3Htu+dhP9Peaia4108wQJBAtVjbkGWP7TgPR/pUBW4PLYmlQA7YtvCIIfsJyD1+yqttpfgITylmzNQLqpIfMWXpf+JBVtmBzN+REMUt5T+XNLwePIDKorkQo2/z1BT0D3pXn1Q9vQ+O184F/fv7iRJZlt0N/af62vHNoEXxWEfWYs9UlrAtyicxMw8RZqQS8CT5Yb7DLouOafb+Q3WPFPnz/1n5kN3LwIb/VLTkMizeLYG5bd36LnRuJBCA1cigAis1iRgObAcaCv1zSlWQ45PW308E7Bt6Qy9oD+5OcLqYF/FJsEtjyitQ/FL0qGEqVWCWClILmEnpcbN+Got8uVCBy6GAZP2fLt2f0JLh0g+sQbTN9v8+kp1wBmR2KTQKhYXAMFrukD4pQBb6mH0a3etR6o4Ns10z7b+cc/qb50svXqMRQB+IeZt4EeMv8o6FCheNebyQSuv50uPCJYYTV0lejHvULvPagvpfMJYRPwaq7ogIzWatDmQT1g9n7LcaXYDAE2gEoYDBOAB9AB8wY/78VaAfosbwGXMyo3QvSibWurlyATrzrO/2f7dlJnBVquHBEk1r4XaMDVFRIQzryUQ8ZyEQMcWQhGznIY9xmg6F+nZ9Wd4t4df6FlqN9T+Mpq/4uduTW9VfxfMddAgvZ8PdNRseFS5tsM45GKEADJmwuq9Q//Y6owz2eQB0XeC5sWr/27oowUvOoMcAutbIy/s+3ru21ljVtj9A6CeRjw7MagXy9Zr9eQ79jeNdZoE10L5Ka6tY2qKzHuYylkd+vLKrZMBsKnbp+irv3YmCvG/XW/SAa/Q4WlGsT714YjhzvygYtrKnOpt0x8hfZwd4iZWcapXaP6s2LhR6T4uNfgTWV0t2N42liYqxk939yzPSvtL1mW/qwl1kTidEVGPN5Rbq4X02nVa6Ns/9PSnsXyoH4TmTGXPnzftaPv+p6eXa48f6wxz6U8f7PsAEB2t4121oKG1+ux28MkzkAeO8T3wkAPofWfvPXin81i9B5ARgTDGACZrf/zwJgsSEa/+UeA6A3nQx1XRyU5iGn34G+pU7mS+5ZwL3v5d4cBOUU99EXC3qSwvzo1v1ZR06VOs/WL+Zkvc1CfvGAPAINoXk10XjaM87CpgdZxzczMJ/at08vr9N9jewuqp5UYvV9fFNZQ/0wcc9S2ZfCMldgttaneK8i8/jkSo7JBWWZxy43Kmi1tqekzsUgz/xRUubVs1wuXB48OA1VpZ/MXsa7F4kYchlZZU3OlzlsZLT5Mwqqse+tX5tDne0Kkm5Uqh7AstUSYaD2dg2FexYHSYmjFsg2WSa7ZIlwECbCU49Kj1UPghnCppTsPiAIcJ3dDEnQQABWAA28BZ2Xc/h8CCiZALgS4PpCWBIALs7pizC1aXy0L42D3ZJuF3ffKwehD/jIs16RfNkyZVEQWWKRxaqHSIA8wTxX+sBB5FI5SW8DclNri50CVqbXYbp8m6JO42ToPCkaFDJIdLLcyWTqcFK0dCQ6sqA3NY/cEjgtW8qVu8Gka5xgIZFI4XpunBUWSieoYr1knc7J9c2XyXlqOrl5WWDIUCn04SdcVOUsNPGDFkGA+hWoW9OcAA==) - format('woff2'); - unicode-range: U+0370-03FF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAA8YAA4AAAAAIAwAAA7AAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGjQbhlocNgZgAIEAEQwKqgSlAAuCFgABNgIkA4QoBCAFgwoHIBt7G6OilpNWKhD8VYINh9o6+IoibkckFlELYovEnhpqEw5rTn/e1suwBSjaNcu4suz9n3jcWQcRrZXVPXCMsw+MIR+FMuwj40/HiI9xLIFVlPzc/Dy/zT/3XR5pAGb8ja8LKxcWukgzwYhaYGNU/ZQFxqLUVbuKhLd+MV/4m+w5Zhh/TqIcXmFFha2pbQiiNXT2bz+xUcQ2ClBzETSjEUCShW9ljKqw9VUk7wy62bj2txdropFFKSzBta/GGt+Y27eGWiiWyt7ti0gzFst8qOChQ0ge4e4Xlam50l6yu9/9571CniizBRTuQZii8rm9Jr3MJgXO5YHQ3fG/aiWhUC9UCdG2QoIRVa66XrCQtr6N6d8LoO2fUBohjoNU0/lfEUIVAcAkglGnCGlSg8wqhwgFeZAnQEDWpEUo2+9j5/Cu5Dy+i3cj9dodvLthT+/jQXc+j+9jQ4rqABCgQFVZgfgbAXENFhRCfbAhSLvJmn6RxTicVSDHB8Ca+Dznc0Prx37oR1d4uq/bnwjmW1rxklSRuTn+CMHl/qVl73Pmgos3js84a3+7n77Iq+1vE+1Fe3EhBXNMmbNkzZa9pZZz5IzPDdJur1AZsxYCloY5KVb4Id2f00SQWKZSyXIZxEFWb0ciZZweIg8biEPPNMhI8ZFLF97yWrRtwsAfKm+mqTSkjNRXIJrSEARYZDpddprdgvERSxcFBLCwysSIBqbLTaXhv2f1A0M8oA30gf5m+sC+2Pj79CaTVAsJ99HmgMzkreYnj7uutWi3UZCfeEK3Tp7cg4LQ/QaGwOPB9geMQt8AsFuWoEsXXiiY1jpMckLx8uE3sWE+MOLIUDHqk+R+m7xPvo7+098gHWLLQNHq1djde79LPpSvKM6AiH99Hmb+irlbd3fp3ZrbtzYPEtmzFO10pFtaeULsgC6LMEdY/2D3Brv7XjMJlrmHZcjjUJMYXcIDQaKhRP2xtyjW4vtCx/AR2IYtAaVikUCEbFqOgZggNHw9TiTV0zivDoHumy5YOohObF03tTrQ4VJlsBoLVDxVP/tDiqGrWr4E+6dyMcgcXBHwjcvr/Wio6T8/k2j3OHZ7eEDLUvDYK0qwnHYVzdyxP6a+hhg6UzcgxO0qdGIquQ71IHGYGYFAgyY689cq3+BFK+UiisgwhzE80guq+evJ7BabrUvK89hDJ6GjaKnXnHitv5Kiv71suv9EU0JXyUb011Rpa9fDLWF9SPrArCFyfg46z168k3t2zuGwtbZT1/xVsaOxlwjJ7KV+eFNfSxJie1oCtpsVqnixnwdz5u2z4oToO5UhpzRdZZMnPr1WRb0EyaYInb9lcHiuauG7pwjRQ8pZyD+89BCy7roasB0G/tFty5j8x3YGm069vWUZqwXisRsa+XTgOhfV/vxvhS0czgPe3oieIlQz2Spt5ypuqKo4fvp2+SIadwu6N9UfWxL75NKakCgf59Aidg4vWB9lT4ud57P8FGjmUT8XYDza6guZC2dpxRBWBi89oRP77VGElIrA6MCemtZEzOKmnqPApyu9WSAF3ksWM8OYQDxnfYS2X+7t9b9Ys+Bp6vl409pkS8dxps+CulHTNUbAluhid+nMSJBU6dB07+5VxIcfL+sJyb2PfcTKD8qEwLQYzAApmcHCQOhpnK38zNesrPt9GAWVoSAMu+fy1x3OO2aaIRnikpKp5Wq3s4dhKdEn8MNHNTpF8nOSHI2uvRsuCCB3X/1Hvhs2KFQQJzdlfCHbyWzHiD6tNK/OtKP4Iv6oTf+Ao82ctyoJgsYG2PdbyJmmKw24GJ9vKTHiPCYcyOmWm7V4D+WLusFvhQI4Q0qYoqt695xlHuBq4nxuxC12FVN0bYqZdp3dWv6/GLeQZyXqPUzRDQife3X1jsGFjkDF3SGGih4lJ+Fbc656cy7M77xWfXL+KZDGaxo0lg/jarRdQiti/KN64OEeYHkxQoOTg1Egqg6WXysFevCW+hMb4tEo3j0j1++jQlmjPMe+IPZG7d7Wa3i3yuAfaRwrnL7aVwBntBUGqxhnRPnEThy6KcpCyh6GIW7aJvFu3IS33aPuWyBVIqrjuqJQJzVn0Ou9fUMXjiX6SzzfwTuFY/i+HufuKnZvJ+NuyVZiGO+do48TDlQHpvs0p77olAj34NKGKB/nsEuJSOFUEjHcZdIhCyfyBcnDcH8na8ZuJ6/i3HETuX+C8BQK6oI/i9aVooM1gT/kmpS4XU2/XlZV4RJ0qMbvs0yj3EgL61X9bbdEqjMjI1ssIPyIluCo/XLptIB1rOwcsQCLiem7yuNwKrZw6zRux41z3Mm0XdL0vasNKW6rNzoTB8mYfrpIUcqasfsH+tmqCoZHDea9KqaeIxzc2PJND7xwvqdxsEMea+cfe0HjEzw2nd8D69PPTch6nhvipm2unCIr8P/T3G1GPJoPt7uacVpUcHxDzUmk3vw7apHGZ5xwVNhG1CV0RKIenNnv9c62liKv93C/g58BKSxXqCDObE39QHZQ4tWH9U7POCj2DBMPcHFrBCO1iLupF/RXajiqRVOiyZY11ZMG8j1Kzs3kdOPlRryX8pM3H3ELYY/c13SvAU9Tvhvp/eRsBYN566dxdtkq2Y3h3Pxa+YbsgQwdziq8inG4ypu1ZxCX4n1VPp/lG+fp/TS3HOmpzOpNwJWUo/fUjyZiF3p2RqUQJ+D/qv0/g7tQonUlUTZTzK1pBeVT5+b2M5PylRq67/zKbiGu4vdyapef4ZT2iv++xUZ85i+NTuaOh+D5oE52pK9rkGRE8P9Rjs3fOoM7cPNlxfFHkXaAFjv4Se9UKfanensobAYrlzdy9Sh5dGyklWArycbCyuxlVv7f9ZtwLqqvQ9n1QK3bjF3htCfLAbYe3mQl5hQHzT8tvWniSWjH51BZCfniQKRxJ8YB9XrrJMPszqtKraJYBsOR6dohF7OFEIcQG6hb+jRZbrCy4Ytc190n72O+u+0K/KiIVW+OhdVZCSOsM74QyW8m6hNRCKpDOHUrOuBrc137WvmqWW+Ykz5pekYdK+3a33Xesm7n2TdEM9hanBkr79zfedaVbEz2zG9C42AreNDYM3lzQgqW5MRIHnfroBdTNiaUcpcZmElNWU84zXd2WSnfKb8fDYOdVzsn1r3f/Owhkx/ou9QweWXoBT3+Oi7TJTDQgZexYsNbNmSFH7zNtT44OJ0MNr22MYW98XkoB9UmhYoRmbIJFamn7uNw8u6F0sJtv7mz3EPfs3A+Edau0g0Ws2N04UBKIcpFdemhNQin5yORRsaEDH19UKSr4ZZ1oS6EludGhdkfmsB5XhbfVteJ0POCy6ltu9WbdycW5sB32JZko3yQsWLh0qZc86629z4/JuEij7bwof4Ec7Nc+9j/DfgWeNz5AAQPAJCCHjJC1gRJGrSAAJ/X/10iV+QSC2CgmAY/shNMh18hpAxcEuTlkDmyMizaBN5AU5pQbgAoAIYAdiARDIJGShoMSeQxWJFRp4cxwdeBjsONlkrjsTQ6ARvSkCaEj+gkTIg6cTLs3NhmIIIHWendyzREcarpFFJBk7mYTilvX0aPuuKjdDq0tZROq0WjM6Ejvjyjjrwx87gCKTRmHpvvLyAVlnTBRHIj0yU05Bm505C+sHEfcu30+pcoAx1zQHbS2MFXOu6wVkrjJ2l0wkH9KU0ceUQn7Q2uc3L3nPoYNj8ip524AU+BdEC1QyneD1RqLObISfKS4gHDlGeJFUyTZgp4a7IBigCtM/T6WuFoyDDY8lgoyKTGGztjBKSlhZqWQ7Z4CdLSQlFakC2ehbS0YIsO2eJJSNs91GWj141Rl1UD5bxaJ49MgcqmtYiUzJ2L4rlz/tHQa8mRhkyHjfuBLDu9/lPKICd5HxhLMvsZ0flRQhzJBKAhf4irAiKEbaruhDCQE1KrDO0LmjsXm+bO+UtDryJ3GjKxP3A/oCtD7P03SJXc7RekRgQAYoAWxCXXGoEY4ATiiotU4D5ox5qmLCZw2ceZpxNf1W141usmAJD7RO/XO4hjwL5cedhoT84LX+UOMCu7GA7QX37Kk/bYuqtHQHsy2n7OFXBLa9WhyscvAnGs9ozYEsxRf87Mxm3FKYWPiyjd/d7peoekWgb2j//py51391nW3IoUXC377AfbJKxVYgBMbMPDbKX4y2H83DKdHy7F+qFQb20L5Nm+hx/Ut7PNEviUcmc2YoB3FrdniRGJi9OHSj5Pd4d7pt4uqZaJJzLOvZQ7t/ZT1kxHaj50xmDbhHWaI8AdoIfHXwZ6K1uQq1cPREr6Vj6Z7vsIr2osSx5dVjU6487j9hjTduP2JC6i9MjRZuu9NtUydJCXY3zVvig/GSnQdWOwTQLN5osL8KQ9jcaa4tQez29CO5EIamI/x7UHxxrXZjwSF/J0LSGgXHvsXis4xbZR8snSvk7474vX+QUPZxOTBBdjX8a1BYfAtad66hjFkcws6VAl8Iuxe23RlCkiqPde+TkMTzlOAAG68Hqx6cZAyHPJX1rtAoBPvxwjAH/k/vPN5uefzJorDUKGAhCk7v7LAJlhUeyvl7uB/CCaYVCaEfjA5D+48Y5lGvYdj5V9KFk9l6jcwWip6JYumbPjjHnGsjp58OMFK5kFPzcSUMY71OUwN/+yOj6y3AcvV5zl1CflL/sy98o2qRx/0fAObsL/j7jefYpoKPXinOv8PLcZL1/5eu7w5VSJcyrFPfVS8HI42lh7hvT4SIW1ZvqY02TfZc5sceQG4UPVry+jRS5e9K29zL7IkmpteFBt0qA9irCg2RoYb6YMQMBALWXeSAKgCKXjUAlIewyTZAA8Apws8h4Jip7LRldmUSs702p1X0bjN1p011kuJEmWI1WMKNHS6TJjwjTJ0+UmSQGJJ5x8pUQRjFZwLAjxy9wX8zRWF+bNQqkyh+ECRtwlCR+EdH0lrDDxC0dHlEfrjtx7GytNDHiiJsGo05w1e4WjrV3xxYy6p0tmxzgBWbqRaHyyMEvIiORUUYxtoUT1elpBX0OHcsa3jge+xSo+kwmM+AFiLIEIAAAA) - format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+1EA0-1EF9, U+20AB; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAACI0AA4AAAAARUwAACHdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGkAbjgwcgTAGYACDFBEMCuRQ1QQLg3oAATYCJAOHcAQgBYMKByAbkzqjoqTVgkfwlwk8kKE3XiIhIgKsVW3TdG3TuIGqASL+pV+AIzTjRTyFY3CirY+QZJZAWiOq0pPuOSAAB8KfMIQSSZFifPIIO/l5fm5/7rsLNmCMjRxIlGCMKgMcKRVKKZKKSCugKKmiCCqxUa3NEIYxUKGtQPsrZSV+bUCHM3spV9aR/gYPF58gHiGHOqvswcOM4QCgaB6oBCxHGn/sW4V2OQeoZB7buGiesCgBQbK8myPw+9aGzNnsXzlx3FqwaJHXPTUqsdLw6XWWreQvZbQ0s1rNxXZYO+NRiGucHouWi8p++v6W/PV3ec5wG+uI7d0ckfbAIeCiOaYuAFQh1ZlU6dKlaNOlTlOlqgFL4KLs2Ja0nIUzI0aIvLW+7FXLEx0r09XFKqaYYAqyTbK/7sgCgWHj3twHgcySFcSGHWQFZ0gUPqTKbwhCAGvAQGDxq9GxCOmEk9z9Qe/6zJT4OXJzSvTGyB3r0hJWCN1+Y0oCMCEMcsCaNxrBog8q0djtfyRgTNMGqn0Qk9Te3tOHXdJFZqWIsdGacrp7tNfbZseM4689XgPSt+aaPbDset2PZtscIfhjErts/Mycfp9stNX7Rqsfm9flBWADy+P62fmx+7oXbmbc2amrN4LiF0742hlps8f8QJq54BQnvGU/tNnTvrMRWawacTJR7rrxUqg6py2jZTfZ6X7PANbBrH0OSfW1iwkmSdOZ0VZfIPce6bzOjAwcm6mciHfRnREsG0iC3dDvwi7a5uV7PwcmIcneBDkexrjPTmYtG2saKJytFydegg/I7tdXb6T8Wf4qf/t/8YhDfQAJYydKjPU2iLNRvE0SJEqSLEWqNJttkS7DVttk2W6HbDly5cm3T7ESB5Qqx1elRp0GTVq0aXfIYUccdcxxJ5zUQahTF5HTBgwZMeayq6676ba77rnvgYceeeyJp/4zZcZLr73xznsffPTJZ198NesbxE4PBCBiwp61odB+ZcgeXgR01O5wKpLRVqWt5ujWozBpkSA4DNbpFuVrYJ+sKq+vr04izCDNINYHE4N4pgEs20Yl7+hGpGKWb5x1oJr9EtA+gGD59NGBsq7GiSyMQJoGZ78WKYTp4IBXRW5kJl2WYQCOrmWVgU9pmAbslKiaEC4xISYlFog77o7U7IZphWDUaGOWOJ15trsGu7PsAzVYneflEUsmEgZbaKp6XOcEyhlIYOjXrZNDICgg+eGnX35DCL36IKS6gcqwfJyJcQAZ9Ie6KYitTb/pC2KO0myj/xNgizTauJ9OPtvLGVCA5voU+AdumqsbaECPA/KwLqRBA+4KzfoNYCiKFDkvjZPYIaOEDJIN3ZgfRmEZbuETayM2dkR27I/SaAphfIo5QqVZtqCtQu1otZ19VfupoaHR6qhjOp3TN3tujoDWCVbohX6YhFW4h3+Ex3p3emN0GL+a0k6pHaWW0xe1WaNFe91ZvXOs24BaD1SM0UdduGtW7y7+67yOa76K+w3AsvbfP06KdT35yH2f+PPcFOA3L+TmiGZN3KMVJyzzHGfIDSrwe07oXmpfjsnR76U69Ro0atKsRStbS6r2uiy1zEX9hgwbMSpG7Gnio/fMcxMmnXfBgEHf+UMIEoiaszbA/wHxb+BJsOrjYN0fAebXQT4Aqgebvt1tHROxXyVYM4VgOQPHW8EuAxwFfk1rx8nRuTOrJCaSMEN5bRwUDVFw8GlWYPF9YlCR+DkugTVgKgS4BzKwNYdGe1M3DD0m6opugMxtISSWkNQN/UCO00gaBoiUqRfMS8GFyyUiIqkQNVTJrdykumzInD1PAjAJEaCASYOoXu96HSKyLEvLwhunbDdTr+m61ucWu1qXpp3VN6I5djsDX71TK7PzdywU6fzEQiJJBoIDOBtPiruuq6rSFfP4VtsvKVjW91Q1ETmvfGCUdnlliai+HolV5S0Ouqq0JEVKa2QtJVkaE/DS5i67LBqPrynvhwTHIWXyi+NxHnG6no9WDnbJGoz9vKC1bWP0mjtHmajkHJ4eQPdNCaM7mDNgjGweFh16r4eX5URS9D02cRidpbWkrslJmNtcfQiJjOZzUeWS2t6Tc3RkA9zaZeBcp2Mv1frJqxxCi4SJ65/HJ0c9aq+QQyzLZeX8lSCRBYl4vdhkufzdtMcRmSFuHijHtDDUlMFzC7FMAWYp5bW0jiWZmvpraDyBJqafib57n8M1rKV+PQpjLaigt/duufjArEeOnO9+x/rj7W/tNoKwbd7yNrImjLVByqAFO1rk31VuoNG2i2tXy7z7KaHliZI2jtLdYZv+/c2hehKcgVbNT+gw6LmNpJ+9wby3K56m9Lsob03z438br//j/gv/i3VO/6T5w7tLlvyt/+8V9L2r+7+Zv7Oz5RnszYFtq1BY03acdowIHtCSSdi/kKOGLQPSO4xD8S+g15HAYZ8daIseWbjcpKR85FTQ+oA7+tc20x8jWADGf9GjR3GGBMXLW2NN5WMGF6YuBhjzY22HGCxe3/lrdn5dcaC70NCdCXaq9Uea7x62eKofp7Tmz+aSgModOeVdLpHVNRXsAW6UuEAOHPQ9LGvypDdy4rKoSIex6Z85Ao41PtIctZFXtjPtu3LaGm/RdunnYVApOdepDjmlKUmzNNu553sHLHGXDfXlit1Pt3/3bY6cGVbkDHqHXO3I16QZi3l3/+b/rcKphd8erepj8ezsr4/0OCIIqK3Xrne5hPw8YhRnJrTqcyTeBnaUI6kZzFLZx6acFEHLDKhCy1A63Ue61Koh4xtiNihMS8pBVdJI+xUFT/ZkeSQF8o9MJyguKaxDqeije0aObL+qlpkHm8OEoQOD+jUbV1/WPrDd4ZDzAg6rfnoSPfa4q8xPMKqglQXZcK9NTqjNc91a88v1ZcM6c1zauXhAZte+Lrw93CpeHHznPdChcSlbZl7osHx5FnFFxfAGlh4sy6WvdCqkd2QLUXak7+17up1sfeDOlrf3ei8NrYkmZlCYN/agOaGk7LnzWfbS+CyWELD0jTwNRk2v/xuLhP0N1TiuTY7eVh9UokUudEXY77e/frurwDqXn/pfDxdxSbtN2UovOSMvai9/Gfl/d8NX4/8z5HsDB+CRd2YiOy8k59PSOMcsPhWZBh2jNawOh4dW5Gyc6Jqqxz7FFEkUlkuIZNCM2nKw8A0eifFubKyhjRx1UA8YZFITna8jXf8T41icY4ZWhYejqUVLgabcaytZbso628RnLIMtMvSl3Lp7epsh2h7b/HCDJu/dfCDxnjLI39pV6Y4FGRgs2iXP/ZzTC8VvR7RFu/QKF7dnx4HIRTP7F6nfCkzj5ccqHQn5PszGOZrbAFdWZUYtp1XfDq+Vgi2ttGkxs9xajtSlVqYI4zD0MKzxIhEch4cUYJxjb2J8ixlPDZR93NveZehQPM375c23VyLP1Mn0lpNl89uNOTcZxq7nQUoHZtzzOzd7HQ1lO+2ftJrv8qJcb1rR+GQXCAUD2bOvM5RwcFX3oHbEfcoV5RGvp6hEOjfNnMwOh+XrZNbHJdrGzQuYxHC0a9ucLrt2n2jti5ijBTcNydnMydDTLTDOg0+sYvIN4zaow2nHfHB/u5n8n5/WStYfArJwCEeHApkqm+e45aNk+lQTRmGFKAyD1a0sz5Ftl4w3C9tYZOHZ5crPMtrBVfamwYQDdZK8i7i0I/ED+QD2oXsw07nOCVsppKv4I1CmxFLGk4qol/RHS+e3PJ+8iny65ME+LCCN1JgeB1uZcWEmnILORCuFfprLwqUVW01RBUsqavMZuKtHXTijdZqew6juOFmGYSnRFBWEx1Rq83+8BJW6Pu87UWCbku+dmNerSPFPKWHAZx9wFl50iVFIOIVKiPHszA8SAsoWlwrRfGZNB3EZf3rFvH2Ovmd/2Q4spvxRmc9kFRFuw033DqLbpG3xtk4uKjUAw960xtEnOvd745NH0LsPSOKgLwarGeXeoM9SVa+xZ6/hC/jWM8lBMT09sSQRbcVHmlg5oN5897zflIM12DY0M/SltUjVT+cWsGrrVWqD1bn2gVaAUGa22WCo+bvjpUUu3+Jq4LD3ANOhKSg1fFEHc4CtPRoFcVIOcX3B+PSMLE+U8k8Ugzd7L3E1e/MPcjU5wz6yaV5qQG3qGL6Lv6lJzOL1Jrw8+aiwjhbmlIA8VPGgDO/EtwW7uLIvCTvyoODpAdxL+sHRnwu3w3F372h3D891EUzDxxnWML1QeKPUbCJGagxes+HAcCUzm5GVW1yAtQDuuZUu3yB2Pb6sUruA9YmWcfDsp6jdRD5xPXHjGHl7L9B2FpXmokJ0Ol86mV1+2b3cbKW6cq7cHA/3n/p/XTFRCJMpm0cpO8QgkVtfqYnFueA5zhpmyLPE8s8Gwyp1juBLFtLzH2pO8qSmcQlxe2vkf8xiev6js/TUx8zKPSeLsIB8U8hpoOc/gb6LuIN3TMX0awPVDGhty8YUeU/7tduEx6jTi3GkQeo80rxjVF3haYgY//Dwuf6dmlA58VoDOb9dV+F1rZZKLZlTtSQqY1al7pEyH37xt3L4W0Gr+1HJVd1rIIpX1S/f045L0CkhtYB2TOniTC9IBtDC1yStQaGoZI2Mhwgk1uSWXvGOR4exeIjRvEqR5K4wzrxTFIiqAy3d9f4rhGOijZIREm6ro+BlbjiqSVNccxQY0QWHLoVtIHahc4WrZqUr7Vk1+7+9LCzCR/CVx0cOA9qQnBeO9xHn7iv0G6zFPEra5t3gq8ZuLabdyM8iunF4dqyZiNkObazU7CIxrsCdk5TzC0TyRMnGulhUS8lsDfhqW1aH44jmXf5f4Av7Ep7SlJ1YyWyspU3syiPacd+4RA9hR7Gj+w7KlhZcy8cNeHdZ7CreunsJiH0tkWivM6qRhuUy25PawU9NUVhCupqVSYjx2j3aGe2SDtqq1+V/XCFvQmOR1oExCesONOIcfEqgWsRem58vxFFEeYzPAE7n9LCJkvW1G3ATTmv2/2RbVksuxb3fmbdBkd1TXH0GC1DpVdaZzUOiLaPersyiMqINp3dKRJJEzB4QwVS35JBNt97eW5eNGMfC8FkUVgfKUTZSd8XsytaGAmRvLytT5nIrV7lKalaspsIo/nzrKpchnugXQ/OX4h3LU7v7OKRjfkJi9tq3n64GxI/AVDezHUSg5GCrkLF7/0Ucg0qCOD6Czuu4CVfdYgu3jHRvHvMLZu2uJyJQ4w6FmK3Xe9JHpRJC09ehwziyTqJMUSQ5ZANKUbbKhQcbzuJKfPDKoUSbia1CW/yMm1/guRv17w/9w6iQZ9VV/HtfXIx3oYH9Qd+lyhmHBJIfSp85J1B4tM0ZRVFEECFYE3uBkUYN8ZTMyCyKwkXE4IRCDyzCFf4SJyNrJfxQ559vJ4GzPYVfgzU9oVeHkbhnsdjivQ+1j1Lyf087akFXz+GKLkDeG6JXoTDEM3xHc5EKy14QrHTWsKaKnEyOSq8Y9UwijqFnQ7i6G0JSN0VHoP2BoD5ut5g8rFQylNRoIE/x8NTcIM23k+VtRBurJfM21V1QKrmwmAzX4nbkDeJqXD7OOpN6TpTW52ZAcnbz4RH95A3NEvlyPf2h7hgsawL5Mhux2l2bMio2UYo0KaP625wgaespYb1SaGYqsQ3G9HU+7KTcIuycmTIV0wE4y99wjd02yW7tPnjND+fwVygdWOTHNFepVFUsAum2IOnazzcvM7jiiedHGhdJ1018OidjeG7i5iWwclQoVigpBpX/4aWxbgMccspRxTuJ6BPJFQTe2EaWiZJ0ipUcX1wAG5MgiBuuSgp/5agrbOYI6pfdW8bhWzqxTnhqZnSvvQUecm04zWtbtaD35YajpBkIN1q4heg8MxG+g7iGczLzWvk35oxSaZnShwPEE8vq7RO5Df/QRjXfRZH73GNrSCLSb/bCr5oXTA46Yw+6x0LTLa7Wyfg86Y/ufGn5UnAGuQx0JtTE//BpNj6IDh+n7aM1/O16OAGSAZKxARlBOBbtj2MEnGLJ8H93nEXxqDlQ073pcD/egU5sd33C3CO7+bwEb79UXE5WLAShWltXrlnhnvRlwgpHVO9ib7Xg/WXIaEuSDJZwDQq07TLfRBypNaujr921ju4VHQLzp71jUPCC6PJ82H99Uy5lWIEawKqpp3zcXYxWo1CtFs+ufVc3b6NcVQ1R16aYm3SU0/JNgi+fjf9ci2+yAlmEq5rDaJdCbhEx9ljtnNQa8Eq7dVra/1YbKzVn31nyXnxykNXJ1aOuYtWX0K7nb5+xbo8pGXH4cxyBiCM4bc/uJA5uqolBDXhLc8CXSuUU3IsDv+mSfKXiPEkd6E1rHHm6fRE3L1FkrNlnojlCc+ld9iVlWKt/BKYKbRwRNF5N8LraE1rrHu9L3jcvveLIp2rfBaUWL2lfxXwp3/DFp1g/ed8e/ejTvlA/tb4PlNlxrbaKec1LcmZ60uoqzBXyyi2yn4ogUF7I3IKVjl0U87H5Cva8yiSDAp1eZpi6Q4pUVIpYZlgoUi9IkvJPAiU5W/nqos7zuBlXTsr1Uu9g+bbzZytQ9Vqq1Xhx96kPbfsRYCjd0EKqx0mFElOL+/kLBphKdR+TPzo8WIcMI+Q1SsSdq9ISmNFSd4+DJ/sEencogqvcx962FPBCuQiJtYya3jMCoo24FKB1gMe9Y55DnEZwKsleeVg6Qm30mrPGkdqGVtKvWafPxjkogrGa5iWT03IA9E2PDdHuktjt587ykf1tlYNeCwrVr9Hu/GuXL2mXTpI7OXxBgExD5FTLN+p3qz6RihiG5ey9xI28lFlyDSme0655fchOrqGdmMY7KyNpKQWs7EbQclWxV15PWk8WuJec0ZdpkOfxyYPl98txH+mvni5i7QBn8vmKyTI8SPrN1fwrmwf6Ol6DOKNwpbRPBCvrgExZRstmddmVeCVtpDhQsrcV78bni1d9lynX0fxran6oYV964ya8jzQ2yRlLwA4SGZv3ReNN+ERJ8HfwjRbOe5AgvaWItb8SFK7dGr9AT8ySL6t//i9DQDzEXxnK988Maqv3nvgwluMbR1Rq6V0z4D99UPpQU10rmRbpeEwhLitvCNdg/n25nlkrepEa1/rF2a24M5gS6MfOAc6sjVRUqXxbn1iAfG7PO+i1YK/2bamoQtBJ89yJxEUB3xjlpsyKcpg+kIsvki9Qle/IZnRlraXFp+asJQ6TSxOWbN+65TadNHU5kmitsuD/gZC0JLrH+jCwcPjEKEVJhzsOVRJMeek40CYHCg/VE1LzmAnXZBgVCMyG70tmHS3NxltR6UGUUQqUgznYCXz8Je2AOeNvWPf5SPiNPdH5AJjmGSg4Z3uQb0pqAFqdsy3IPyV5nf/SNQu5nk4+YZb2C7heLiBP2HEzgyRWJ9ihTyuUcQZvgZ/nmijkQwjlc8Fm5qlkQubOMN3roqdG/oRafCZFclNWUShSeb7BDjUGqicBN3qutuZ2mXKvSXAbQOGHa2y0k0PQGp5zRISTY9hqP8dlOzTUG2OM1qrpVoJG90P5yvw4Gs2e7lTD2JBLFK0lvCm5TaqSzmDm/YNRN3EQs+flN+2maTeJaOymAsXajM3mnudDvwdejK+Q4CmW+UVcRqq1b1VrVqD1ujo36E5HQT6rib27Xj6rSu6k0lX5bxfIh/CFm1ThOaDERWZE4ARc1c7IsizGVz7Lg717JQS2HH+gLEC67H1L/i9PP3/Jd3rh3+EIbidBWwrCone4sEhsr21kybNnJsuuZHy/0N8lyAzs0x40UG2Pg/CuY4PJDQYKFHcvDVe6wF6WB3FoY7nk7k11uQlb9g1BhJlIZly4DtKJrpDgdlLifuCSRYvJw26dCR2Qjqo3rBiUjGMdFlOHAB7qujt56HF/1+McZUGja/8ljuBlz0T35NNDE12yEy85gjFyfxNHkMN4fJr0+HXb4w7tFouNDv2nlvTHOvQft+4/DP2RzOg1ZjS5O1tvu2lIylw52/+cQ283PwLcbqtKUslV1gUzF5G521oVWvlB0jJEZzdVyS98KTmb7CeiKAcDNDF/NvWkKLldaezytaMYyqwjrMUSd4wuKvMvMsP6OfyLBl/fQdvEdr20Dxz+aSh9ehFx+HdA8C1085n8fJAJy4LIj40oOcgRyaz2mzZHlp7lpCBYUcGaAb0wHHPDpW6/aefcyeuUbZbSD2uT2akT6Fv0ZWtwqUPk0G2RsVgdXOr2gD0P0zw4dy+6c46cQK4ombXODzZpiv8lKBfDJg3xXIKNX++iX9RkDTElWamk+RfVlHC186QvcjofpePAmJe4WaG91P9dkRvNed5ZkcoR9jZyDL1ovSBUJeeqKOcKX2d4Tu+B5jWR2hnuAvMNr7Xmj4ngOMvBkCU2ZF1SqRtTKrysUju248EfuE15/ZbZJ3trwZdPwaBY6Cir6wBVAzXMvTKZuyq24yAAkssjHypj50h5MlaZRnLiEbsjCm3UCNNQFJ0YyyeScOZJ2i4ua2QuZSSJGZFmgvx91nmR4tdsT9hHI7fg+BWkTWSlaXBsjHAN3iqfwfA5XjLvNvzZG8fhx4GuRfLYN1F29VOnqFhn3upQB8fwaCfHkGAfHslrmWZpzDK2lgOoUpbGBK7cxI5WzO9mJqtehKCUKjGHL07YcX189XVVX1f9eXrT/wd+z2dhYfntb2YqZ9vF0lG3hzj8weecRar8WbDlWT6TmLIUS+dmKnfDindVFmdnOHBLnkNY0HNLr/PDjLn7vYped9XOniV63ZeR8fClmYBok7noylWjSfZxjw74j6dj5/Czz8zlZEPDq7HUnYNj5fbbFz5wdP3OuwpvhJVQ7LulwOxoWiDN5q2UnBi6jdZVGPCSvvcW62QGW66uWnx3Xu2+jgr1vV8rzMtjJNb6eJPgmACfB+RPDKXxa+Bj5X8g15E/mMTed1dcrC8WYCcsYGaQZqBFCcmMiLzQUlQGmq33kphRkNCykYPRPRIv9SuDG5aUohohQjaNYw6tUlULCwCFXYLsDJTtY8Ju8Rgoo1hvj2sox+oo1xOQR6Et3AoePg9meAo6m1BNI7djpacWRehyhdrkD2CSRHZSirlFXawAW9ADy7Crx85A+gbj0eKr8ldRl85ngtjKMInV8EkKVZq4YyiIAV1a4VG8CMzIMLFa0JPJNUMVGiHo/mHPJWF61q7nJKzZghmExDKqPW+lZVSWUGIrq+vxgPw6AIhL9/gNzdPker4LtqO58YsVlqZU0wNEM68V7xwJqcD19jBXnKJl4gMhHbEevPz0tE3Ug+UFYZjGosNY1SlsCL6kPjx0l6MUVXUxCatV5wCbt0WdbbmF+8qw6ebSSo/H9BRt88NC6GmYhAqmX7JL0dN8SJl617APS6oQ+Z6UXHfs8kJ2YtXqhl21+aEbVFndK6zV+aSEGssr+GGV9zIOwQqV9wSu6FfpVVlknqJfVb0Kq8pNRT/0nWA75gNehQFbcAaSsIsxZ6DszK+YSZQCoBBSP4wVHouWRivct0VQ7+pJWNNwQtcKOWuipi7geYYayyQKgGXiFUBtkCyZfbTt6HuJvOnpT9jwhSh43kgSWEbm0LKw0S0SsZVhEJbIECmlS8s9MsPecjdJMu8VSQCQPfKQKBgu8UQsYrkKiGLexaCRF0ujbIcXw9BfoZQh3suq3IIOMGG3qAQEgKZJugfQxIeOEqaTgH+vL8Kc1VMh1UzXjxzF4sRhHdW+Oc39zJwokoSN2z1QuTz2bdgUDMMIIIoGJ0zJYoOjnDiZruXkQyHjmo9YCF3DW0FIee9Ig6JyYv2eYr4pAEDhkZGSmE9eeU5AYREmNE+KDbTUvkeehpa0s3XxszmjUpZdUUYuYTdyXTlcdmD79ohYw0O3oEp0fXRV7cRzsLG7AP+vuaOt+Mx1/zObev2/qbA6gHx0LmNar0aGsoY3Hh9Thmw/UXf/LPO+knd9SFq9mJ/zKk71Oi8WFopqTYdFkGxFBNiC/OZ34Fav2o75vTQ+4lhv8n8/saiaVXo870OVqg4Th0EzS0Cmv8BSqKuQlrNHfwAUo5r+UFWVhrWV/6vJoy2jwu0S+r3zCupg+sNvz5XmdcC8mCxov+9rMncYH+HWfdljG7eiqsz+uf7Aklv9IbKwkqjvm+qorOWgWXOZF5ukb4Xh4pR+hx7fUulU86I1ffx6DVut3uPRWByHMyCcrUwvzcYMs2tT+bZaGu7cXrUcDX2o6p3e4ekDwLe2Z4F4QhYt2UhbaAly1P3+eGp8EbLqN/1rEHGvx5IgvV5WmjKDY70a9X6Cr6HKkoeG/2w5cVmfg8NAvuevYrpOOkwjDWjV0J+4O/6GQr5k8Px6PS182Nx6nfcLoR5tcdP6qLbwtPSuXpmrWvmf2hGbQZNLwGEuItPIQjzfJ8q7HVcvbnFQaECjWq1nvU/xyBRbL6sxawqpV6PW3y5qxpQ4IVNlxEMopVUj1ODO5usi6HPwPpiPnS3kgL4M8Ovsh+1V2znm3Tjjb70F8lN9i/fA9ClF9f5u77BMtfrgE3MFwHzfvAK7Xu26gUCjWls757CurbNggP/uKQ6Kk+2j4dn6qx3tIx+MN6BRqxi3jd1xcVPUhUx9PzfGp15bGiq6UCLax8adelbk84rmOH0LLJ+QZTH4PpDPcEfHebklXlvYLkHT2cyR5ecPPQLa9uslK3yqt1ZmyT8klFcBwAd/luUC8E34/uaX1d9xmvsqqQg0BECA+Y5FCmDVjUwV/+IvAugVG9v5/8QXZQ3in6BvVh1VlNY12WaqlPzXoPvJ7KVsmx7X9EXPl7pk2TRuAnhG9XDpeQubbDM/jzncWWLHOwazy+HsqLfZW7lfkpvJY5ocThnHLfU4ZjRSelOPdxjGtHL5SYNbwriPWvpSz3SO7aj/fY4O3FaGlz5C+jNypp5qy5Tv4+LRVOl7yzQe/9fY71YFDacxBNiZyDqPc+uZzOMbboZYnFa0mhbtHsc8E+nEd6Y9lk87Wa5dIzYzreiJYvM+wfGvaCRNy6bOUJyyYv4UHFT07jGI5kCEdnWky9P2kYHmW6+BlX8A/P+d8ZGe++rr4KKP9axXWc6mj0EbFFDvp/FSClwzFL0b1JduVDMRc4t/NZUCZe1oSKIf/vTlZDPB0jzmcCur2bwgfdNFyBlSO12EfPbtAKfn9DzpcSTkHPmZLkLekTtoon98I2v2wO1UJe+dSfx4I4PrdBND7SCt0A9yDQ0h37RZacvGLY+hNGb7knwDgW1oDvoINNAhNEOpZzXw0OZ5ogOXaNpPigdJDE1DfzOFoH9oFVMAemVTAboNbALQLLQLYi5YM9AlUomph2nCdMAkwc3RC0FeUPflzDwOEPB/BygIRIYA1gINsRkKBKwiBoaSBuAqwMUQKWtkQo2LYRxb9kiKkek54FJ0tacrg7+beP+TJWcuaYNY66XRYMKIsTA1OEuMkx4vequuEkTiuvaKHN/oa81TWTfaHxwtxZZp3ChcvhJFTHKa64rsOvGVR43cf1SNVx7oJptqA3hCSDJ3pClLtgEe1dLseTGoNE0SG4aCpLtck5FkXTYal2IpYhnmoyUE76YqrjuV8jjy5OfxxUGUGsGgZqWIq9RBAAA=) - format('woff2'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, - U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAADGMAA4AAAAAWyAAADEzAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbmWQchV4GYACDIBEMCv886AILhAoAATYCJAOIEAQgBYMKByAbZ0wT7jBjHICxQe4g+S8SbPeQiQpRInToLKePPxGOhTMcUcL4M/miSRWxMQ1YOUKSWZ7/z7+e/7mrdp3u+0Bm/MjoDGRGpt8pxZHLvYbn7fbefze2G8ZKqC3aMhrEztjZK2etnazVJaeMJkVbQykpO+2tYW0Bl62mU0VMX3dfTn359t+MKSV06g8AV6TZHSVSI1PjNC6wZc8luVqHS8uBw/Hzu5fIXWkNH8JtcACzp/+/qe3bub47rGWvz9mHSGnIPlQuOlILR8vZpqKo3tw3Y8+bN+MwtkFCjrLPQSOTJBFsESXSmJRyaS1xN3tJ0VDFXKVYNOSip4OOugw/xgp/7TP3oeLulUYIYjlSvjK53y+tgxrbOz0opcYAAuIoRA5NXr/2b3etYBjuX453h6HY4CBIiyMoShQoSRIoRQooXTooSxYoRx6oVQfMqB8gCAMcBzgJBJQaYp6YY6y3De62tzewABsf1gr2BxsfdcrDD2x8fDk0AGwEH/eI4ADBjTIIAqjxuRNbN5CoJlyv4AB3NEWIJ6fzFBJSCeVkQbIsWYW8g1BLdCS6k1WIvsRQYjaxlnieOElWIy4QV8nRJAyaM8EYUj6plpxIGsBaN8nppBUTiSpkweVlyTumqyg1BRUBEmvSPxkEhe0/wQFHTzxmgCRRdf0p1slilsyuk3XnNd27nKl2+Vd56VTXBiD3FcgXykTj23mfhDT6x/WAzEsfBtKhp+0j438AFan7oDkeUyp53luqM+9buYIj6jSF8LFCe9jPiUS+CrcgfFg/kkP+zIVPlXtZavZfmTrxAGUV4fC/cnKXK5nPyyyLqA7rdG91sQovZDHT6v4+TmPO5E0asLBzNQv5gA6Ql1iR9+XNcT5IXZZSQos/kVMpyFnASZjJzdgih6cJZGMaEQ0TaO1qC7JqXmfl+n2LDmTZZfVCRL2GzTfPTsi9/VVy2Bd1RN5QW5Cj5q3gVk9jw0knlbSQsMkeEp6vBEA4NCMrdYdPNkTpwAdtA+pCxR7gFMbk+uHtfxbYyuV7WQuaEdMgVxyIZbQ/M7efkbd/wdmdeWs5xafyfPwJxAJIOyxjVp/acq51+Ku0eoBPeC9L4avD8lXN9boWyIzjLLHy81104RBQ0XBssMlmW2y13Q677bGXIiUqVB1w0CF69BkwZsqMOSvWbNlx4KRCpWo1Ro254qpxE6657oabbrntgSkPPTJt1rIVL6x66533Pvjok+9++OmX3yClTMNRIUgV2wHCZgmDOJG2AzPC2DK5DbGicPhBiSCtPKOT13Q30IMjYA6W1a2ywiav2GaVwybzfFmVoFbWkzEWK1fgKozDBFwznuWZ5zAH87AAi8ZSXluGFXgBq/AO3sMH+AifjM955Qt8hW/G96z6MQLZ5VJ7f5thrDEk5Tg8pUxRyRLVvHEgs2YhcQPgybcuTHKaShJcplmFzy7jjh3Ois1mSTGUnnxZOQGHTpA61uLIAhccAgJAg9eKYcHYZQQKeUc5wWN4AjPwtLEIAiaqpS6fTSerdAF6cAQsSb3M02EFpkqCaqgxlrJqGVbgBawaPzH9gt+NqXTyhi7owRGwhDxYgmVYgRewOndEnwBru9hhITD35TvAe/gAH+FTYzxmUrGhCmqhntyENxzwGJ7ADDxtTGVAmjGYVDdPoqMpZIfqnZXvAR/gI3yaPLIuo6zznl2eQ+hZoZ4vXNwQo593o/AVKGlhhIGSBfTSjNxBUOqPQ6tMs9aEXP6x9IrNrcCDaZCeS7JyUV3ugyrDA+mjg/aEGEGEJwOOZRCTYdhzRzbYAmebPciUHPTztegQowcmyaDpGqYsSLFismybrmPP0XrZTTepUGuz+jurYNSq7d76xNJ3v9nBKOpHERRBCZDgYJiNTMwmxrKZQVsYngKj2M6odjBhuxm0hwlSYnTKjEKFiVNlovYzpgOM5iAToMUItBmRjhJyD0mAk2ZKmhNDLFyiq/U4QOZgbA6MzFEx3AZiWElEFZRE0uKW1aolJECCp6bQmGsw1yfHcsNteA9Mgx57imJ2a0rzzCKCpaZClq0ieVuM884nKKUxsp9tIlgiC1kpQSxiwthKEFFFICmMHDGMghJBLoXZC4bZpxj4IQXJKIQcFEAqMomEeqAjpCBmiBCXQizBoKOMxsbF45eABEmKfnOSwuQSw+QVQ2XKCSOKLBREFgqmBF2GEgYkKAxLxJCMVCCmV0EUEXGs89k3eCS1sW5zdFcMwAAMuOlglIc/kXsMpP/POnsCuY/38XIB5RTWVm9/fEDYMcB7PNfNHwx8zgSDkSdzg8tPJ3OfQFGoUoN2PGddRP6kadcBVCHe6r5a0lD4Nj9bbKNv/7O6NHhztxlgEDO6lRWY2T0MZ1rc+0hjYUAhFU8ERORnwFTTFmuDyYhHgGREJAAg3Q9HpvdtEuoT+rP4EoK/wPPfwI7/gPzvLsYjIiFzcTce1+IeUJTQTt9VhOlYKdQNgrWNMRnWPz2dMO1ohcBFf/z1z38IwGcKQgyIk4SpRnPOeRKECBMhSqyzdA1BmEo4uYJbDJXLhyoO1gq8HIE9TCmKXj26ncRzSp/T+vFholEMiBYi1BlnDRoybAQEFcO484fxFwqDEbQGsGiEAqJpHnfBejq40AqF6yZCyhRHATvhRO878ZfbUqjeWspCQ60wpTo4zESbYQKCC0bNrUJ4YL1+7QbqQnp4fo+nzzQfn6XnAlcC7gK4COAO9zDWARDI3w38Ax65qx5AGnwLQN9y8UiThuTAVKchSDTDVe6PqztSg0cCHC9eg249LrjqjhXv/Yc7y3yMjKvjyXh6ESZ9JH2s9GnS4tJS0rLSG6V3S6tIaxZCC93bnSz73////89/cDxpDU7o0euicZNe+FA7y0zZOqdKi0pLbvUuaeV5V75liUwuE8olwHTUlLnZRuVw6O/EX/7/+39bMJfFX5LkuQTxYkQadw4Unn9/nvysBHbpBdW1t1R7W1vmE5Xvby+aZNT9ve0XnyzFY0/MeGpWqjTPPDdn3oJF6TL2vK+JTFk+++Krb77L9gOEIcHy34kA1QAw9gD4F3DCC4Fzb+uAvg4YfwSwVGo0Wx/CQ2AUowEbRLBQC5cqH3H2B3Rs80LAWiiLqaRi80HAKlijMPt0XGURP0cBAJspRFHokF1BLLBFI5DXrL9FyFuaKmFW+SjEJdHGT5jEvo/ZBL7rFnjILzyWll2tkQYWJenZ1WM1TnpCTpMG9JT/wfyJtRvv6XZEooquJm8nOdqrqbrSOgOjga2v3BZOzHjFChcYsK25VGaG87jpwORWWE7g95tVGgM/IReSV06lNLMgickRjRQtMmX648w5sc+nd0vC+5lxhRjLPjtLjszdi0+0xikYjDG94I4pgIkWHj0W1esh2UTHmEUuSC6UqelnGn5uOtXI1kEwvPbkgz8fOzOPTFdc8pRywVOnQaWAkdbOeOhiPUEHTAzuSGyS6IStZUaK4yJtKzRk4mVOGkPXLCcJYx5UsZXDLFKngaK1LrTPupjPipztRt6YCo9oUZ4jdLlKNc8dY5YzpECflyvHPPnhwC8zMeo1tryYQMeICx4GdviUlen9o2b6ipKBZ7lpemuknwZWDzTH/T4ZkgqXPXSrqjRG466WDKVd8NJOK+1ch2k4c+Gbj80j0521CgTLN7PfPXxq1EhvTaw2OeMa1XegWg6kxMdxJM/NZWs825J14iK1nKioS63WHES5S1Oh1D3VnVqmfJJelgXDTPBqEOQo61oV98mszcc1xkJe4bdCYJZIkx+fUpDw8GlmCrahmd43nUgIkuURGZYWkigyxwtts5aujBXLBAlpcVQZ21srAaNd1f8ZL5jMdS5+LW4cpVMsJHke8WWMnOKTFHI9lU2IVZuHcj1Q25N997duK5lRxiY5vGaVbxxzHRx6dlDCpZ5r+nWSrAwkK4NUMny6quLlvjPTM6fMaGnf2e7d+TzpkWRdEGzBucwESjkaSrg6DBN+eepbK7SSqaLGLBOV476CgX4/6dHDmgdSESz357kkLaGKnrJFtqpk/RzlZYSybs76cCA0SV0wHL4GCtiOnvvnk+GFXppzmyEQcPAbUgFmNK8qFLMvlAw3ye1R0MQzLahq4UuyVXnQCaSj7YcHN0M7ZLPjH9Xmcjjwo73XK9ZyeT3zza5svCUQOMoSuHxRRdqAuJhNXiITxGqCZrqxQnP7g1vg3NuOVuuvV8KAZ1+HyFpKqWWiRvjwLpatpEOQYd4s4TSTF1uOBnLarcE21slPtxRzAk2PE0sDzxyG6SloTmPTDoQ+BNccj9Am9tpSEgiR0pKZYa6yYZpRamENGngQjnrbrmEccxdTey86pVVUq6/Ap7nRHRWP7dKduCF784Em3IVfd84XXArItTWw1d7NbnlFNV2O9vWOHXMNL/DUXIAhcM8hvaDMfNNrkSknA95fi2lW2d8dtcv2V5Qe3W4TFGC8KHapIkV/fN4Z7EhIEEr22T86Ndeko1LTRTKyDASL+wwn75Aod3r8z8fO5Uema59IaIy+ofn39yIWb6XVOZdVPdQKQ65j7TCIdQqZWi7VNYxvldNJlQZ0JQT8HRjRmnV9XGjyeMM7gJQ9yZrfwLQd8GxT4ysZawcEoJDk6PRpjDVBSnTnl8TZO0efnba6CFjz5N4Lu/o4pnpgJsYYlKGS/vmdtj36YiiB3aCEqeOn5QL0L+81UnhdvCoovhKjtao36jh1GMZr0JjAeregp//Q/N4C8JlhzlHeE91DpYqQEGVg5aoy7lxjdWUP0c5YjYEgWW/Mp2qv7jdnKccNze2NVb5QpURarH9OIKE9idBRRwYjy4HkShZWqdkSHmhnUjFBdqGNOzDr7ClOg/PoOOVZ9YU/ta1OkXlOZ0g8PNAsI8OalT6u2ikutT3apm1mTNT7NtLAKaQ0ZUHJctsT6AqGAgGKoXwRYWFthZx1+YfxahuQUcsVnRqc+0ZEj6hE+miVbZPsv58RdJmdS5U8Eq+r3OpQJ4MMkCY7jPk5Mr0lnQVyTW2goz+Lqnhp1z58wxS0rIncwuW9lYgZjDHBfcmhRxsJZJhZcfwjDfxBT11lN+W5czM6h4LZOboDru7nYhnOKmuLi5oyZ1dOtFiWu3OLFxSvbTvKNg+LbeV5pJnluuVr3fcTU8h4Qz9SRiRmu9Ah2GvQp6d0Cmca12b+ohqIb0Y91kowe+loFyQXfF6C54/lMFi0X/z52Jl79OlvCb6ZqimivF/1+9yAgLiKsrXqbJria/OtE0WBVt7MWH64o+S9bK28cVkKP9fOBF59kg/VVe0QTdaOJk+XVz8vwr8ARTZyJrWUq8hLaR3GWbxb3BW7O6i4IGPZ2EHbvDWi/QN/uAWDKPJpkVzkjuLiile0XGwQaiptNr1rujl5iUirRsPTvEfbqd5cHcjtXjwQHpK+S2nJGxQxX10kLq+OiL/dcXn/0n1qFuXtTddf/O7LhaTmpdkqSheK24dPfaMaexDnuBdM3d7jttkU2JJlovQoom8yT3RJDtj7in6l1HQXhTFLAptK892ojBLnzCwip5V+Sb8Nw7ybZ2tTvLLbox2tiVJ1lDyCUeyYlXOUy4/9l7jDdx7ceRfRPUd/x7dfiFhUBOq2shM+JJfWlRcoVnuau5pqjMH47jrK2I4a1MdZi5K0UWaLqXcoRhErGD4tfOLVzUSeAXE/Ha97CXDMQx8mrz7czExQoQQmDMRZFnFz+NEIrJ8UlFMrofJGKzat17Orm4FyKTmQdLi5aFr9FTcNN8CWdlJJ4GWUtMJ2a/bXT66dqdnhJ4eLTzB67MyQMY4Cx/vouLYcltz69zIXZ6Sc8sywCsxyC+R4sxchSk4jAQGnC3gOvRc9bxJ772LUe0irmNdP8HnnlkAmWfwu9jGZVXST/OFGUS3bnIJGunjNgcx5O53TQbm3UqoQ5Zh3rav2BI2qe5A1gtEFswTPc2T1Pli8tOvqTpexfYXhYvFtCzbQ/QG4zQtBu7i34eYxgOeNIQ97gCeykrXC31MjFk8g6JAJHRDYUd1MKRU6LyFkxaj9eHdYYfuQA+oAomUBZnbHgPG3DNK7QpMMMP6alxxcrvpVVlVYWrUikvk/ofxDJJtdcbyo8vhvpRU7Yy3nWceZ7jsfp37ei3fL/kp0+QV2seLJlj4Jf5z195dE0kcpTQ8f8oQ3PineNFsiWfiBceE0sdiz1g0LhMXJ1ACSpX0Myz8vXK2K4ErrXLo7wpE5XyR7sUmk7SVlkE9JDq0Jg/GwMxVIT12NRPntxES8ASOtvyMWRcKiLmKcE61goPtwPM5E0/GjBnR3p5iQDAlH1D0OQ03o4UExeYKPQXmdxDj8YVpuf28CioDFHcREvAYt+1TPgXic8WFndagFXT2iyxoR9GdqQ7c/oYxpX1x19gl6u2oD7QTG4O2ioCNbDXRSiIHU5kcTTSgdnuwkxpO6buQXu/yItU0Xrj4h/q+qq/bLdd3AnoxJNAKX59oN0rCyEEZbT18MO5nhF5dHRE+J5kruvZWevsYUbydTc01zbiQQ8cg+4p1o8KwYpOpLr/Tx0Z7jRuIxtaFzkVEE+PuOr4q77TZuawjvCnE9dKJaAVld2c9n+sDWGkOJYCsYrCK/DB/guq8PKnC5htWYrhU6gzlTLYEomhG00SgQCtxlV651VMGPXa9iW8xOOJosMysS5AK2NtGzpXqzjG8MvOjbb6712gcASdZLPyRfIles/JRg+rpF8FlqRrx8BjTdBX+hyx8n9MT1gBrYFdusSJBvAo84Z9CZP8S3UI+ks+7TdkX6zqe4QTTwjfAK0yfpyL7ao0vdTjVPo0eCw7i/Fwg5uO5pmRdbZeghQBdHOk9IxXffWT8P7Afo7jeTM6ROSlyWBgPHhXJFyS7O7e2sfNoxbrYHSkYnG9g5fYCWln17ISAV60cP7jHamBdu3Lezvz9yAYijXREgtT+bFk4L4ab6wiBYn8kK6QPM08y5ETiAJp/S+0meOR0x+1w3uXQTQwTGRN9PoCE0+5zI6wd4bkRmEEpAHVXUREp4UmoiygZgb9HLMfHyURXTARXTVMHwXejF1R33x3lJN66BJ0/P3nso3qnCzTumlgD74SUa6w77uYjAJOqBUzP4gQ5CRFSKF0xAvecEqujpUb1hSBcGbo8Fqvw+gdp140jiveHLjAw+CoZN0QbT1GTOU0Gpa/gT6M4y4yLRW7pPM7Q8S0W5wBl2hMjbEA5DE7OdVS7G6iAS132OWU222VLmbAV0Wg7uDDt4dede0R8iFSPgcOoBkn9mb5iSw17bfqIv4+Ka1WtoBM3MM3opsVVDqcqGe/WbiA70s/jF86gH3XjMSjGhBkaUB6EYeLKBHk8NicwJgHHoZDVhnQzF3TvLGXFhVTEthOLlm+YM/WF1IdgdnKhn2GJgCoNhY5z+DDWJVpDx/klyCupBVz4Tb2K+EvXqYanRO/DyAjUbHiL26tQPW9QWsNeBqIuZoGrfNjcUg+udoJf7s+JO7nUGhIQ9f6SHHkeLFe29G73uJji4TmGrRIOc+6GtEsflwI57+ZaYNP93tFihEoxdNwHUKmnBTif9nEy0YwMEoqgOlmG2yAMmBzKtTwN285erPNiGzt6gNzP5Q21RXi7WwuXfDzFqP05eZygMz813AP0PgtbQ35pmkNGVj4VALp9aQ26oMJrhJcFsLNUjVZ6sLoFLd8aK8XxLCp1w2oe1ktOOPUVRf78sU4WJ/ccknheeAO2ow1Q8NNtq+TwQa61Suwen6y+LW3nzxrFLmHBbsfrN+WSnp/2nDuA6QzFfnH3pF0rqT1XnbNxFEZk3QOlurNHVmGs7w3gtbDxv8JDY88hWoCowxesEz2fH6X2syS8+Lhucz5ACGGNrVhbH222pm0HmmSJGDD3sWEoYkqtmgITeJEYQzcffLw63BgA91uSWeU3iAj4duxbPfYcvRKYUQ2aEgk5ANAF3E70HhMVh2s4FETiC+yO7/rdQOf4o/kz+dC6qwF2t2d1twFMQBfrAKa6S8CWyrtyBsujdsIxNcw87Cx5sJMoty56hJDKqT/aWIHAAO+FugyYkalPOnItE3TmT++5ANTjFhJs84mr+Lyie5UdToMO7qOspHNAH87GphKh3pApCuG4ZfxOz5iR2HX1YZd4bomQVlMSjYcIfiU1Mdg525MqJh0XwHi7GX1VbV6IGgOiR0IbxF0keGPEPuorBcwA33BgYBkrL7hNB+UKUvMX5cgtdQHefU0eHKRHcfC6MRh0n2IlgbeOD8+aLwpOIGVse+9ScI2m+/i5g19ZL1NoO5ngOyFryBL40bhlr/K50Xm6HwvW2aGYXMjVP2IQ4bzu7CogekE71pWn6nmtwfimWcmkW3GFgwsnGbiaE/cBX4yPV3U6sCbGsDZlAD9BXKdIX5L1LI1nI3eFkE3OxAj9WNl2C0tC9inQF1gtMDT9aMVuIRnA/xDf/r3HARtlVWdOLYRnMf37HvMKa3Pz+88E6DVA1WsXMFIhOq0xA1gAo8QymJ7MD/37SE9DPBHeSg7/ha/BxavZ1olzL41G3UC52JynI/7iYOdmManGg1zuWMF4xVTT0UqLgA+PpXi7YGcIvkS3/BONBt4GJh8G43ux8sATeL7OvUDJ5d4r3zHvSJsBLDii8UslMYMQm5aUiWQAU70YIHR/W6z5YuS6V/YEcWTT4wT0DS8Fuc/0m8HEjgJyWU5wEM+GZFHoQp/S6Qeke/bViSYL/XXRB3zeXPCwTLASHjRPihwEpqb5SBg0nAaMp9hWGEHtYfmt2RaJOC5jheZSUxzILGrQllI/di3Z7xsyjpDwZpITMMCuzenNQBX6SJ36ckvIUHADrv5x8sB3Pa2WH8a6AcxfRSY0uid2fjxP3AHLLwQkRjdlL61p4XcQleeS2JWQNbk0XcQPvDNjSlNK+bVXxidmD+1CRr7h6eEVvYhK4Tr17PLf5fo294LDTFkHz9JvgZa2sRC1evGq/e+QXibonYuVgc8vqINMqc0ikgsvRORsIqF95zZwB+SZA+ZYYyDl6NlCkYphplTkCpMcGqc9PNTyMbXxYD36VR4uXRwPZ/if5NzfcAnx/yc2lWa0oH/bxiKnkLtGLyyOAakl2dgx0hPYw31HAkA9IjknFN0z8YTsaHmM0HhXBGQhPMe/nWMFqq30GG59lgi6+H9WVdMTaHRwyE+W05JGvJURjo8gxf31cG3MA8P0PJBUMohrUM4u7LODXY44VeVX7onYU2mPyULW5Gfmg+jTTD+BFkjOsCRVx7AQMj9S2aw4+WDocyjz6hV6pzq4p+PoiMwd1oBszHe0A+gQlO6NcbOiR8KUtTkiDEBqWAcykOM155DspsVg/ck7w2sNntoIWdkhCzjAqQ6cWCOe38oWwfL86L1hLiGq2/KxaUod8scZ0i0/gE+caWpRhzeszG2rJ8+nJWCs6N0UawNQIahSzUVZx6q0UdBxllHgd1XB5GAA5t7hYa92OGjo4JBAX2AoiKBpdbaL5rawEsUY3O2+nRrjbkClU/hM6hobSnQV850Tz5yi7u4C5lAgvH3czNgobRk5Z6yJbqZrrJG8L/biBPwYn3JStPANcChtQIuqrkMzhOKWk8JA7VuppehlFiA9wsHzvWh90AoU2WnxQLanFF6OR78x7QIQzkFd9FlXA4pvss2Fj/PBxEz1mTgnWgiJOkdxwfOYA4IPFfuqYSv/G7LvXdzC6HNAgdKgDYu4qtAfDnMrm46lQXZ0lUKJ7N0msivZlWEqCkffx7k0FxvD8pWHQ+Ckv/lCIrB9CCioP4CY4vf5w09L/KljsZ7YCPhDVVBWOzCi4iDxhvo24acWp2+gEqrrL4YVf7Q+bMLdlZ9RjrrAhXtgz+vZAxDgtwD7CBbYjtzpSiQifOqYCRN1VxTKLjg+iSlR0YxwrN2LRPNHztb8p1SgDXiqw/8MoE2LXlf17m5eH0uHlApvvtFJGWwX1XfFznQCCBjksMscds8EqHL0uMEKJdkbUyKgcd5SDjc4LD4BDu0Q5zVnEG8kx2DByi3Ym85laT5oAJzKtYMhHp8COjzMvDqj2RrUoqNKWsL+gDqVjI9NgfanxAHKKlz7WFnvq+l1QUkwXqoD8ecIFfIwWO/vmOY/bOjhzrDCgwQtWorAyB456dhnKxIYfgW2ozILU61ZLMofu/LL1AvG44PIaJGMERtYzuFnyw4pvTYnnCPnfBlphE7w5hMpOA2ji43EUOkCN7W/IujSHhK22ooPba6rwQXj3iLJxo0CsCz4fQ9X9wC7kmIcrLLACa6fU5PFXRPPHAhu2CBEMjWR86OVqLA0/6FdNTT5Wd0E0/4I8HtzyjU8eRdWodIp9NmSIH3ruyBaczhFTDewS3qeRlCJo5L/Qu0DbH1G3AxdkBVWy6ZoqfeDgCSBUojIs9UClhIh2ibrtKiFaqPTg1m0URRuLwfuTG7KenVpLFLvSV7KjZPa83P9wFTQyRTlbJjavf5dGuIup6TAFypYsUazFdke1GGr/unPgZbmzePlh0cJt5sy9EpWSIjlg1r9uT8k7dpfEbRM9ZkYxUaBwmrz2ldSiipmju3jofa1tFJn30uOnHDwNyHlyKlKfoLYUsz5tD+ijFzNXzheDkF/T2luZUvNSdy7bB2rSipUNpL5CbexMqfK2wJo9Be/YneJ3THUF0ouJjMLH5LVvJW7vcvHxAob3KfTGy9M5MA6L5g7qHD6cgcm1htZgAicuT+aicMzP3tpMY/+hI97HWB6gr6uFUip4Xvyr8fY6J9QjL9A5P3kNrCY5w9pgcecuIJg2OXJ8jfwqX+F1+JrCYXouNUCOEnl3MDVccNs8f9tc8tri62WdvtwUZ1SBv/KfvkjG8kJqwZljEvc5lUc9r2OSta8law7DwM2ST8VvNYjX1kr9Eb0h9PUCvg1dmCTyhgDBxyXKHR1DVU0CiWt/KYrXgoNqAUNp59BVlBFXm+FfUJ+2xoJsxS6zlvYKDa3NjQ8q6Yvio2GYGd5bEVDUXbzWimrNKjARc40ILsuP37kQzAjSu1Mf7YdC0cO4wlmBaHqw7q26SD8Uhh7FFcwA2RTx2rInc3d+CMWqSDarCsWo7FM/p6S+Vyhmj2SzqhqLW7kzAUh0UpPIAP9eoaRMDKR8HQAaH8+wzt9z8vSktdN71t6YhdPo4zLlaj/AWxyMS9I8CsxgyV47V5Im1cA3QNDaeMPHYM5r+pm7nq4+tBaiX1p3uEL09lx4G80tUa/0E+NSymJQOhwIZXhTTJz8GebaUrSQ14Sq3a0KQuV0N/39otBETbRnt1AxRdeRG74F0Fts6HvrOc/PdTRso9fNfxgS2D40Z28+TTNLevlgaykqRMcf0VvJLpyR209qYR6qbsSX5AO8haaLDXSE8YWS/+hsgoGRjQbWQZA9f09M6DYinINDyODZQCznnNDN//AibgQZPOdH2G4Qurro5nD9EjoFJUbzbAVHha8vuhwdHwaUASTSfK2BsPNIz84y2CciGjnjggdj2gJA2lYRgpEFFmi140UNheJ/Mj4ZRqPUUnLMXltlWpxm1BFbDYl8h6OY16FwfQew71TEgAIxRLJhEwi7q/GOe6H4+WJboQnhG8uuttcuoL7MvTtySJGnJifO3AyLw4aQ3sxpFPsyPTXx0fUQaGf/3T01EjsSsMc0m2RuCkA2rjSRELRFw8lE3kCO5EyjWEltZ2ZbcAg6lgT17ZoaqCQxH+hAd82serUD1lguUNISzhPOzwOMsTMooKHBEzrD+FLojrj1NR7QBSYXxnqa7NfdqWhhfNRpn9EeRSsLsGXRykWk3FmtrlmtLly0PEyttoko+FlOpEIOnKjW5oS4bnE1p+pxtT6oA2P92SpACe0pTYARMDsO50GMLo/9NFoYA4RCPQ2BOrTf72EyuStQ0r6W4l4fGReH5YXhnAnhFephW1EiLqA/MRWGw9IY/4pd6ooqaraH3GkeuTgrACS+gRc7NxwHYksqnlyy+RbyQBE2gHeuJZ2WGaCOqTSygwOyTsAMY33rqX6m1hMgaEv8cA+b+8eZoOeVPH4fWigIBK7wQPMU2K/G+vh3F/gHL6mpgDbtREmUhnn0BJVhyK8FL+BO1faiTsmngtfV1V4WM/tE0t0ChcD6qSu5qGGMVknQZrZMTpShPNQwTisjaDHb7o3rnyE76QQbQCOMG8TwIpkQPfT8daAp5IbQ3YBOO9XfrMHbzdk2PJgWTHNxCLGHLjA1kOVwGrBbP1/noW507hqjhTFwvjfEw9ZCtPTroe098x975BlDdycngF8gsFFwlsQ5r2pt4DWKV9QffHhQvHyfNrvHSCay3+ku2GQabYQzTgjCG0YauidHGOPt/wEJxtHGwFCwBYUax1RXjLzw6cQtA+cdcuHYqbPzzvHYLZQYldxcfuf/jhByFL3dcnj+YL06V+H4P+gnZbbNLdfAqwbHx/3myH2WubCrSAcZUgzldofrKQeh87g/GzbRhYqBFJ+3a/1bcAe8XmAMU5Jyx976FgkDRaUBgSme94ijDAA5lyqZ8fSIxLwwBO7zqUtHWWlhtwZ9ImE96jlFKyE5nvhMPZK+16+oRDlQjtz0YqgbnYJBuiqVPvqB0CPblWLprehbXLY/3FF/n7OarZJjFNn0iJ8J8sYyygULgQ4QjIRn7XdZtJ/hoCLY3k3OJR//e/rxPKBaUr0sI22QFyzwZVj2sQXKf58chP6w0UrG4ET7JRQPe+L0njKzWGHnSRoFNN/EWC9gA2tV9RT2ZGZFHOSVacF6XXWlrW+vg8iWQKotSc/GSvX03mNYR+2eOopTugvF2MMOKC9zeBt3BtNsRVpryXOpSdgwes5mT9ALsj7NZqSgKhQQgPg+le9KVPxux3lYntqtVTuzryxjMknZf2ViX1wHrgCNXme3M7IThrhYPI7/ROoCUFuwvi595pqI4k5P3e1bFzST+x9wtL+Pw02wacnEE9pu9ShNAQW3jyURrggTLdk19YT3GXnQGtrL/voWyr0ZFkO4KWm3dh1h766TpeSUXbbXB/0/1qJJthUb05PSHD8tnJSDTcxIDdEcwaHLopyWHPL1xBhsELnHOJP5Qvsa+n0UkzP7UR3qXsRGaIMHcOZF3BoveBxxK2wI+/NrcZnYyBOwuOF4qHzgJQ22TbM0QQV6UufMEqxX2LqVZa33CerBe2zl6/g/0SVq3WzQhDYQPYJl0eiChX5Mp174+pP0fQU5siHBkJycVw42LRlFwnMhW11PPZ3GYuHJOL0ZZgY7qj/WiewXmuiEdeELAvbHa6iNqwfDGDgSKOfYOf0ZnwqH8yx+CJSuXYfbtrtW9xjSwIUG57tjGbjLM2JDQjirguAmf5SDu7gi3K8lU+GONVcplv8FR0KdaUaetkBR8wOjGAa2n2yrxJhCdF/A3BsJbRPjbMyCQyyhdWKMjUVwkIvFAUc5BSNtU4d96lsVjHWByvIsNSAqzWHDbf7sDgtMyj+KQD0Wm2MPJeZ81GCD1dpAIC7McdPj5oiniaT1s7jrZgHjgbCbXlixSJZwch87ct0cwIm76gcXiGSzfPgMJ9kZgOS99EPKxcvXdPaL1mz84FHu2ZpZJVYC/MfqPWj4g3cIDbQy9fa3FsPbBB6zNfP0sQQUiVPJcXPJHNvUSsBy4xsQLNGp4KUCE67LH8v8w88Z2LWwJpikR9CmRqSlBWGOWIwMriFIMhzOo7d71349DYRiukUze4RiWw7QVMRfQJuSNTJNPutcYQO8d03+UrRQbKhIZhjQaGFfjtqpVahdYOMg6quZezc3yEHUumw833jcxmi8gG4SCQ645siJl8sBO8rurlbR/BZAdxMfiHALduyF2jBVVktEri5wVwBcQjKLNKtHovkPV12lFL7AAaD81SNRSNUtIoDhyAqev+Zq5d+YLT5erPXRYAv0h2e2OHEElqf5V21PDTNSuO3+hePQVF9AqOIntAn1YTqwI1Po7mK8lYl+qAMzN2iIKFQH7wqAi1BmnmY1LZr/SL4pkOJxg1hFGE3aSiX5UQ4ehnlQXepS12y2Cz0m4Mn0S2X4ip6eutgBLWGg0PlNZiQF9rqnt7v/JpRZoDvOi+U/l1wI1NPNVD/f+XgKRu+offio8nif3ka7dP3E1vKywuPZMP4Gu0ROOWGPk72qrZqCncE12+ud1/VP43A4sLWeOkK2F9ZoVKa6o7XUJJR4mlpJi2L3dJ/JtLxq/d/Z6Insjs7Tu3egGFcsFZMc5fQRULw7loKXnGDzweL1zDyastVbOMlrTXv16xfYj8Y9/7v5/MtJZVkHoJUWln9fJMVEpfP34WOJqSgYH9NTnQxDYWECzrUEkNwDoLqlKVHDTk2Lp/ESrBtdS0um/sUs50wNPaBvWDHeDx91sv43Kuqi5OgI3SC9fXC1yB7uN9lJ0FZ2ireysvdW1QMNvDFez1hxn3CSLQjWJwRm6PqpoDDMuzEhFmPGYQXhOBdCUo2urSLyRr6NsREwBGaGj55TU1dUPGhxyM2U/v5rqaaQpWexQ1FX1dE2VGGX4X5w6ZDBIVu/qDx8ID66ty0JxsNUHqVgl9BdMPdgBy0+o9rh6AkTtF8/bts2Iy/5AxZ2BHU7lSNAw+PATssDF3ZuEL0sXhEHbIKrhsXLhwPi//i85LqqEPX56P/qST5j/tsvAFyB/Q8AdtgKZohNBJEZAuZx3ez4f/6Fx0sl/xzWcDyo3lBOgCv1MBqVFJ4oFtKI8cZF04tZoT6gx2m57kmor1yDN8WAeZ3UNGpoa/k5MPiWWkzupcDzkWq6WcUeGBWlDNRVHjdUWXvZrLV2Zbq62Z6dB4GhDZ6QUQO9UKnz9FN6n35a70d+SADi/wG8kiQgEHovq7GGxhU2aNpZs3xKkZMYVp8T8/3coLAgVDmpb+3uNgoqvtRxkxFVl/Pd36Klf18dJolhdSkx33jctyDKJ2rmXWKYiMT8xMd9c9bfZSvu9Xdb0J9dSiQxbAgm5pf4BoUlW/vTvmXR7Ssr6ncvRZIYVu8S832J+5aCf6A3nvO0yLAZgAho8wBnQ+RxbLzwaTih8qhaxIwCH1B9HazxoK+nAS/qeqg/TS9yz864r2zM6dd8Y9iGsMsFyt3bQgQoT45nZmPNY31zzXhNN/fNiQD/PiyJ4UNsK7DEt1GCt3QbPDrNxn9AJQSxwnfoi1LoUOv7wMwGqCgkYCUKowiKamKaOvHTULJuDSmYGNM63nITALbrLgLo8J7cxf5k6q7Np2pu7dQcZmFea7NRMfPnaQIqp9XkGwTW9atHv4bnQP3Er1zntI2cLpuyqrfYejg1A71zHtw4ylp4Cm0A3CKf2tx9bqNmrCyewpE5vkS5B5XJHlnomFgaXTSyx8w6q3EUmxufrviRO16vYR2jYLxaQ3yzMj+tPupZbcU1oQOYjT9DbKwdAthATgL9ip0i6K/TXxF/z06m9xXbX/j8FAs9HO6f6xpVoN+3Owy7JAM9YJwNgtg8n3j67+XRyudFFVjP2smIyItFJyqRaetWJvwHj5oN6Z3imO2vdmBdh8LdWZ13NgAzmtrCi8us173f1njX/O1pHw7PlTajlVdzbgNE/7DMnBkpVADqK+s/NIxv6K+t9pF11Vqgz1qvcRlWe+0GgPoIYOPsZkNqAxwbSstBa76xwIwYnS1TWXP8arNG60YCWS1cNhpnAn2t2uMiTxLvjT1/8QTnRftibGpWmobvY7kyVn9NKM2/5kDG4oVxaF0DAePSUw79mNjvlNv/d5LYHgB88U8sBQD4UZn95pfS3ymywT4EhgwDUMDu8QcaAEdncOyf/1kB/IDjHqpROXeO94/PJ3UcAY2RZqLvMmtP+mvQcM9SKXed45Rj41wKpiu/DmRQhSkYCsSGkL3zQAoi0hvwE0RgD+AhGAKhDtSrldZrctWbmvnHkwbj+ydKZfZr2WFAc4nnZD+nukSELhmqHULSgtYyF7WKKS3mtRlKv0javtptkrqKlrOIfk9PLbfvUukWm7pL+2Lz6l+atzdG+0Ue9GntfTKvh1j+T2UXtqmJnrqMZ3aSRqDJ1rC7Paxtcdrt60hvpDVGhPrzxrWJtfXG9lqK4PxJms3bHpFqs8hURtBqjzzqEHqj09qmAIVRQqNN2c2bAtZziXMxY3MgLUm+Xcsq1TsySCZ3wfGxf5PmY+sy69x8XsXYvYZGreR738zs1PVkW8d1JhudvWzaStK2nsus9H18sNrbbRgL7MeCgBFlqrlZnlNiBlNLfcvEWPBsFrk4ewisQYObAOjfOOrnQO7vjiS15W1ezqS7gVK3kdoqcLqcfUfSbC7lTslcfaWwC2SxE6YzT5XIaCyITpud/4F6C1ADAFiXaNvEVFWF3qqQVWWpHBMGxh1lYyClo03DUqU8HDkNR9gsyvuxwK09mfayVx2lq61Yd7DQrfOzAGB/o4vteYkYP21NLL+1DzHCIAXbgQqKUAhukAVF0AjxIx3tyTcUCynAdXrrCHsK48w6hBV++/tJ4ShCsYVYUAbNYVgZZmHzohCkMNtfQmFHIVdGCPsyaAm3ijCLKTsKNQJau7SmaTkqr838aKmdz1JD6bMRCwLVoJAwK3gQwAnAgJ2DAAL2PCGwyQB4IMCuB9E4Aqb7roeIC984bj28jQolYaQP3F8GC5M0cAWKEsyHF2+hpO2yw86nIU0Hl4P582isJ4AbBanugn+bmaAK4UgPHXoIFs4pdwpuistVIFTq0dW78OfDrWu8dKusVKRC+EAF2AMKO++2j6p14/dVm5Qnkh8qkIrtT4yQCgvxQC4pDwq0XjAv29MeAiyXIa40oHwNWoyYKyVvgdrxD7Dw5dx8uTsCAAAA) - format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, - U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, - U+FEFF, U+FFFD; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAC6UAA4AAAAAVOgAAC47AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoFOG5JCHDYGYACCWBEMCoGAEOheC4NaAAE2AiQDhzAEIAWDMgcgG2NGs6Ks7ponijIxGo+oHN0g+C8TOLkK6xAJI1V1fGp1NOoKtBcNQ+jK0/er5q85h4SzDEe8WLZfkSCOKOEITU4Rnwd6/3g7TyHQ0ahSi1ij2km3cPl5j2i//ezdvQweIILwKJNIxSZSouqRPuABEiJISCk2KYoooFKC/ZUwC/MrBigqYIMNz/939Pm7u86tem1ZIQhQMCsagWEmDYB/wBl/nXv9mXnbGcl/vRQgh+vj1yfc3Xsjzc9+r81LDpG/Dlu7aO44XHSHWLKkMYSgi4w036noBt5siPv/4ttPlSYdky5YSNTTjNX9XX/aofghnitDBSjj/2ya7Y53NtFmjxRiBbFofF2Imi5Fs/tHHu/saAUr3T2BQTK8M11Ox3pySFbgALAMVUCV5ZAOAeoAlemSorqmTdvlHOKi7UKQu3lApxxKe2sPD5glEhX1Wqo4k044REC6Hp9eYy39Z057lYxgww1R3lPsIWJzuLs4REiDPBFxfKciGLYzdk/6O6hkCTOIDQeII0eIK3eIJy84fwGQMOGQSJEQiThIshSITDpknWxInjxIgWJIuQpIlSrINtsgu+yCVKuF1KuH7LEH0uwgpE07pNMw5JVXkFFvIGM+QBAMKAVUgUE8+QAREAElaFiI6PN+yBhaH3urltD6en7uYlq/GmuW0YIWf161DBfCJgSIgBiI8WWDsDjTyQME0C6z4pPLw05/Sd2ws88bKytSlWk5PDBBmTZYN0qHIz7JTyHX37xFzmVhjGbRrNLkx30Twb6A67BsPwIUiYt2I4/vjJASwuuO4AEKuZpbdZRKxD9k9R3qUN+D8BKMlKy0t/vt4LjZkkoA7qb8Hu2VDuczdfMZesyFT876DROd0XtDyNa7n/NuvrPcffgyasLXYQqQKrBpeEjwErXxUVKPHwGJTcFzfe3RWJWk/R1XYTlW+H2RKEPoYEforOi1pD5tx8UF4WivNZdgZotEb8UP+GXe0jI29OyOJOh1mkFzHPXzeEbhWhqvU4AV7iszFu62l/bud2h3rxmll4VW9j09wq+Q3JeVEwue/Y9miqphgxuKggLVkm4th2AwU80Zetd2FmluxzKQujRc7ekuLM67R/QstYIdB8HhqjJClJj+blIpChQqVhaW/ggedFiHTl26HdWj1zHHndPnksuuu+mW2+646577nnhu2IhRb1GY9THXPhVbFZmdsLWfbO8XdfWCZHcCWUZHZHZUVkdU9bVtfaW2I+hiu0FGI2W2UFajZPeZ4n5R1S7belVtW9X1MjKzfubar2L72dZ+tb1f1fUzmtg+lNl7svpAdi8o7ltVWLZhqusD9f0Cqe0LJGb9xLWfxfaDrf2uruMwsR0nZKJx7E3BfSY6xJLogmb2new+Udn/7O6wWjyIYz/jM+v6HIri6lOjaENljtgejaPGymxZrXnHosUr7huVjbO1W23vEbubpRZHXaswAmxoEiVnuymjb2V1WFXv2JZVv9xGfkeowJPvW3QYySE2kiA7xBRWyvez0CffkT4KRnREQnqTHkJn1m6Ovcu1l8ViBtWxkSC6zq4DuoY+mkvMqPfsa36gHtkR7eb0+pxy2n/OmpX5qq7EGFpKGgIrYOzg7PE5oAlGEYYlHEcEuih0MeikWFJwFEPK8JRjqcBxAN9BNIexHcHVjqEDTReWbhw9ML3IjsEcR3YKyemkyjupY2QsfTguQS7DXYe7ieIWkdto7hC5i+YekftonmB6Ts4wnlcII4RGyXmb9CXbB2H+OpkzRmCjwEiFus/sT7JVAmOgFaukCoigi2Flca+zVQqL6YJ2WCkZNoJaN7SpIPkp4CfIKXUxDQVlJEO+dOY8Sp0Iu4XsDAwBXeeq46FcOqUYNoFk8iSRlKQlqohiUczFmVTMLsxMPkl3Pn1DAtmRMQRR3W5Z8o2oicdQF2kF0P/D8P5QOmMEG/4BzDs1z6AKnQSkPaaz2VXhZiwbr4QVunYi6sMa+H68CFg6K0nJTFE2Z09a05FTuZmHeZnvg7JyI+gM6YyEJznrUpKtaUxbunM6t/IorzI1WFa+M+Q9Anl3AXmXQV4fyBsBeS9BXgUQEQONgE7MgUnALGAfcAC4AnRnZsR+zWyDCQkXHbdq4csvju74tUBBgmPbSIjQUDOpNodEiBQl2ltj4WXKTzzVrsMrWbK98PKwZDlyrZdng3wFNvrfM4WKFPvPmdDTcb8BJTalbR96pDR0vfs771V67IMGewwkiQoLQVln8l++5Ohn4EdQ5jyo+Rukm0D83tGA3YMuKEnETKySUHc4Rdr8WbUUNF2GcEgpKY2oa1JRQ2gpjRnOKGUKCQ6EnDqcApAKRAcpMb2kacV9d8NZnXhjIUQsgRVEJNeGodi+QwZaXvo8hu86hsMNxZEPBiUiU0kT0jIsVbQxz3U5Wk2YftM1DfI5mqH3Mc+GbKiBHKiFfEXd/O2Y4AOepjlu6AXOF+INaaCesiyIF2qakUvq/PqwzchNojC0bcvKksNeuOOkkdfxkmXxevpzVhQmUgz2vi3D0Nd11+TZoZjF5kONqtaN5Hmu9SflxmnRK+fTVC+SgVphRvKuKAq4hkkPzj+1MUYbJ5MnJowMkDJ4IvIhmEdZoL2Epl2JeOZryGIAMJLE05SAntMFXqOdzZUUcIqfl6Xpz3DFcEjeSYSvdlFvenBEnSqgq4lnXVd/ralhVf2u69+urgpkrs83u72NkeUJGv58+3h0QQtiQqCUrr20sRnkANu+Jx9aQZi9j2nNtePuSAHeP8WGNZm0DkwNC5iyxN7YbXBYnLW88Sg5lY6IineotgSfx7Sx5fPtnbsnRyqQY6mhqwDkrKkBPxSsTQ2DBJ6sU5lZ3830uATWVr2KravL2z8tv0aZJUcMQuE9f7Af35cGdh8hvocrcoLpTImaZLiMzjp7jh5bZYi2W4OcS5lhwGy9p2vBmX36/kbmR3Pzsooqx8zJ4VeBU3wvZGq7LeyQyYufMh4HsvseegOjjhlMv8ejWICSuzbIGYp/Sil4HJMqru0MwUCsdbG0DnJ04b+wwvQLFkGJN4ZmiV8bpwtTr7ta9QnX7bOdGZGvw4p+0g4CEkaFdb3CxED9eAEGwmIE2gvgqtOHdDA+ZjMNGcW+btlhAa7CHYqJqaDhkIDfEGGuXZkPtQl9+x/7B0xbeSoYxuENj5x+Z8BrQREYaUOe7lqZ4eI667EYLwwA9Fp/ePU/t4a8MAlAwOFN9UWt6CjY9Lik4D3x5v55OnYDJYpay6aX8s0IfHMEXkDOi9FYAWlOTsIaSMPklvdnZRcsrSJXYaj0an0Jrh4q1I4WxUpawINs1ifbDLqwhv2Uo7DxuEnVmmujMTsVmpDVWR+iu7oJFgPDoNzAJ9vUkdLXxlW8p42vYdB74VAFAqSkKXBKRiFYC3iC1J4/lmHN5EWYCbZIDSjcHIYsphDj76hdnFyapW7b307jGyEm67ZBqnDOBPVmAbvQnwMdfqBZ6uo+06id6tPX9+IV7Lcpo/FZMfev0RZJEq2dq0AihXaCT1p7q7MXV9Qxi/Biqe2uIOCb25vv9Tmf9/U+VFA3U+enn+sBUi/tuVZ5quaUxutWADFKByJJq8CWuoDRDDT55m/Zw05mkHcoEDxE2aBlx1xog009drVNUMBiENsdAXJesywU4qY8fw1WTFOW36dw5vPdEq8G4ZOfFN4LgY9qTWzMOzpd9/p0xrQl8YLhrog5RPv6VDBjk2tlExwcozt7ygo+RZa3VTrByYsWGwojE2j41EW7bs8P00IwtfRJJu6uatron9KDVbxbJj29IQ/Ay6gXCGq8YipggFDG5AmTyawYKLgA7QvWPp+yxzKC/1Ef9P8pb7Q7RMwXNTmc/e23HWzIL7jauiWdDmbCxEUrHzG31kia/aqz3RIPr/ANyO7i2VpQRc4lUqV32ZLoIyXnwKPHJLYTITsxJVZ+MOPQKt/wb6uHnOetIG3ggiGbQrNsLkMZt2VvTlVPuo/yyMxutVvEfukfEvFARHJGMpRbufW81GMGoWAFInWk8zAE06JPgs0DI63mPkshgC33W+7KN+nkphTcbc5QOhsa1Lw61+SG29Iy9asb67ZV27fIJ3p7T9CiUxFGrmIkXZPtVgCNwSPyZMh6WHEXb6p52LK7pdu5ZvUzPb/qenmrXzR3L6VTNijMxKKuKOhJHtHwKbFksiQMdmtKTtGhVT5A1sqMNNTXXl1TgyVgcHBA5cW+PH9J2etIRLGaowwqTgb/Xcc0D/RT795ZkiUqVgzVedeekCqf3lPggrW4YtaZ8OyKfH5pqDXa7NmDSkuYJy8O1tDnNYMj+4ytVzdytExD4vqypL/5FrV1PvW+3ad07UicjWg+K0RC+BCdLpk8tlXV/9j3eVMZ1zA5pZlzUAmwMMBnHHBCEJpcMe3Sa9vi4QxFn2GdBe8GJ710o32qySr7e7UaOwbGF6nPTYpU6cXHY76/xtB75hCJxgJRvusKG7Sa/MwOsWsHBDDCYit7KMimKD+OC3gqeXfmyKzQST5NJuPZKyGolq7ABja2dNMgIFkwm0vhpgRk5sIuPBqn4WMCiLKM3hjhgP6OChdvbtr9hUUuUXtDoKrUe9dF05KprmGdjo3awku1picsCubMAGvYrEMyq7CpKnoKTcqnbXuTP9h0/d/XwiSTpjwMH9pNZcTeuDCRfON2rjQwX3gyN/8RBU1uTI/GhqVrAYYgPfdM4fohVek21nmbG8LlVKPXpPxVjBTEHYM0xwDuVUU/2g23POPRbRxBG/Pp1q3UpIo4FTGdeKQnJQnB73YHW6ZAEn7c3H2v6NNzcPPbjOdCXMXCj0K//D4IPxWKiXEGDHlcZ0OUAqD6mVmQLdaUHQmw2KAP9gnvPKWkqoylP95SOm0MxAf+PcQZPCBQ8CtvOtiIDy1pWb4h2m8+8v6kMOhtoptfs09aUwqJryku13H9LXZA8a4ztLbGMep9xjQAznIJXswSVBhzETIf6bhTKJvMFECHFMWm35YPNBCy32N9rj6FFRufhu6YWIOooWabJ3M0Gs49D6TO83hkAJAovHwr2UdG+uu9OAosQYE4UGxyndPqZ8k0bgwpNmpPgekdd7UjbnR9zc7nvObOH59Vdof5gv3epxqvndmf8FLsdk7aJ/Iu0lqLkj5ThfpD2CP8D5Uy9p2ozSiVYfuIp181xwQbqZGUqIU9a4O8MRHdaSEsNyi1dDx3QHylnnOhc5f6tT1WVVZQOpVUJEsqmuYMdU7HBspiAqdhwRRnqHMKNEc7WR5+mql+ln2iUx7jeUGaG9d0s74l+FW73L33v3bwElRgDzakT1HqyNlmjjv5MV6HK17hD3FQY0yRshavKmVG+XbVspoUqLGkeP0TshA/LAcf2JGhT3tDO1ZwpwA/TLxgib+B88jICdb2kSnW/pFe9WthMN+wKZM5X+P/5Xf5T4UFwgV6YyYXuSCdOX1TZa56sx/9R7CGIKWMBNuOzy7MrsHL0YlOUjGlTX5wvBqx7LxcBXHrMAckdWFajCNy+Pqd99zTUCd+4Tp3n9sviu98efT8iD1ab3tF43oyFO2JoHtTzO3XwNtrHig/iuc2DHTJxo5boclYKRos851i7xJz67b/+7BpM96B33nR8zzQL80TL8X3fCU9IzPBQllwoIx2Iz8H248HyKIXTHKPwf2ySTklrfhO1DNC/m+R35gNOcuvyheV4OElLrd1sovwYrx5Gn4KyrGbxWEfGFvm8vbXkd8Vl2BX8auaCh9Y0a3UvMx6CdpN5G1Kz7EIeSZBX/edJgVy+sAowZ9u7esKiimDRRWH8Gq0fYh/JuX4RNopew1mZj5WgKILqCnkCe4BmGSrym3YjX+sqMJL0ZXNAT9ZuzmHaiifyrfim9DlysAfzB0fUoiYiFxfLBPb3y88SArNi6wKwXfh3ruNAlgZFHf49/BfqFz9nE+KP3Ym05KFbbpjtB9wPND9KXmu8HvhzJPY1ZInON3kiSVZa9ovTmJ4aE+B8MINEytzfUMry9WLLSxCLGzSM4ytzdUkrjf0+9bcHJaMMusV6+sgLhmiF7gPT7jPNY/svCY+LzXZJSc+z1x6ZaP9hugoj0ywbhSknHYzcjjU9AevRkfbKVtpjUTXm7OIaeepz02VYV5I5s60HeeTQ9ftfuK2Dj0gfNfXFJ/A+0kXWYpDwvJ6VrGsToo80E4jO60lB1ctvrvcqPGEdFOk9p0WkGBbAhlOlY42i+++DcaqihYVHXOJX8IqB84E47zZBGh4ON3AX82XG40R7qz+/To/HztPusRQvC9XuYWRH9sYg+0kaoNW7TFffm01pDQdJEXRW5i2PhRzDycwufCWtvFkdRFegBp253UAUZZh4eB4BnS+z/x6fdFdz0VfGYsugOjbyLNvNP5L2s1zNAJsN46UucN8cS505oMRf2XhrLbzCtUeU9Oef+f9WDH/u8hGNoV/Xz9VebJq9lu3T1Pun3MWEKFhRT7ytNcJ3+By75jf/8RCFcczE27PGPjfcdCZSzs26tbnFI9siGrmkRt4F/Gka8sYmEfYOPmgQmeaBT+jk3QbVA4fhcQCD6pdbpSjP+aLKjxYdpNUyYba/51z0AD+oRWWjJjRDYuq1M4es2Ax2qg54vRnaH4aLVfl9OSLlgaGgteNCa87L9QeWcyZch2bcP1AXa2LSaIqgpTo6gXgZJ7alJAylZBSfzHFXLNAsKhOaSy4PjZ4Kja49FjwEo1ukz/qoJ1il9uYzohlBGYnxaMotDeJG/INqLKKk9MxZWiYmH7IOsG9iaWHLfI/RI5jnNJ6P8JYdQfBmyJnvwAeviEjEuXgfXmshFnnbysY9ID4EtgMdc74t04Z6v/03f/963PM4Audm3qKtX2kPZmuXGVh9JszgHzkrvByyI335n2U27BpJ+w83jCtvMDokHtNf34u0l1FFl0yeZFoHmeRxd8uwsCrmdfKlSyvXnAYH0Ufvyg8dbg85XCFsz54A4l0Y17WQVAKL/gLr/yZ5A5ybi3++019HDt1wbTnBA/loSOb2TJWTFKGBAfzx+SanOIsbBtxY2jJh1+gfm2SEo415Pfm4Jvwjmrxtm+gPWoveI9XYPdyMj5Rd5HSrcvP6AjqDmDPcIygjIBJuOwSrUlmuIm9sPLz0QKH7gmcLWV5t/6lFe9/CZpaUu1aJtLOHr24Re8wZ3qeAiwNn0XYBaZFGtioWmbjTkRM1s4HLtlYB3pyBt/5DlmGerp4Z3jQbYRF+4njoNJeCx4oypZqkehkbWmPpGvYq8aBse1Hz3EkRR12/iVgbGn2zW3Ks/pZ/T0dwcOrufaHnGmj2HcExXeYvOAZaquD5XYzRo/ZJK1JphU2aDR67XoDuMldNvCjSHeqtLNdg29A+0Kleywd9uTMk9tO7mt+vP4xWLwmlE069OzEbHK600w6DexyHJiEFeGZHrSjmRO0pkxXtb5tEDFhJfGTC+1HN5/yTxs5TBqvCbZiZFSR3LC1ohDmBFS+HIIO/GY/tZHegt++NizspBAwa1nAQ/BHWYFMN/qaNT72OIgHy91RdgzH5TlQ4/I7boSshWL8TJnXNHvHfF7DDjRRXoG34beGSd3PgfDzSnPBL5L857mC8kELSk7AVpCOdtK/4bNvcadu4HFoj5eGQ0XLY/wUfvOncJA+QkzTv5Hs5hM29l7mWDheki9IX7DfdAJr7Mn2zi6WWBCWlytcB8sdQkfMpEeUBj+/PIb7oQo7tdUbtpzEW/CuUX6vtH1ibQdubWHqInUjUqT8JGnHZKrfWA6Zr3ZsdMKi0ziSNt+gY2SmaGxyEU7A/c8YLcxexuN+/CXjvFmrcluLscEEXjOzKvab5zxCwSgrie5Jc7CKdCJAycK5GZz1A+x+Eg/xXyT6h+3FzGwn7txc+uIlqA0M0cKZrdn9uXg5099B67Ur6yNegt3OSX9HqsJdWK49kFzmz3aBaZAmV1qOK30bINrxW8Oo51mwT4onfpvkqZYBym2S1avpcXa6Nlu8UV4M32UY6HHFHXdDk7Dz+Asu72IjOF5Y9gQwetmWY9f6P95YsfdbabrGnR85Vp1TTdG29t+gQRSuKzqrJ3LbIfqtudHsJdvI7NWawU/GfMJ9UTw0RPkoqdt9eixuZWuOXeszqB1zv5X+rE3Ovm27kzBb3dbW4TtIglZgGsRjb41FgfqwwRpR+8SYMNzWqWnAh6zNNo1H+L1J0e3FwVOLQzgZntlZRDR2Ns55KsY/Dm2EBqlc4ZLIqcXBc17PegUIvhf3PU1ZcGAARIrts6+9eXCL1fn4YdxwE6fhleA/hZZJxVZ3Jqm8mqnvvaZh3LHZRVogFeYo9f4v6Z+jCjZmQaIGT4kPJolE/ZSkjcp/Nw6MlyHJvCQkPpC3qYsUhR2Oc01nJKCCWTKLnIubzW8ZBAWlFsX6NeGrMbuDTpnF9dHOE48eSoYbOXteCs7ehIkbRiiRt1RT1eIXSCEvTbBRdTaN6SwLx5wmKSuW7hkRJiHUQHxxGorgzuTYFkoK9wUtPnJBdBs5iX15/uQTtKqM4MZwoouW+21PmbfxBCmZKLiws01P2pLHjmNJ0jPWE7tBfFHRorF19y2cayDYNibkDuJQkPCaJNrCS+0ni1VPTMINY4fJ5bS62/6HrPBqop7Z/kBzK8GN5YTkrvapjF60oROPJ3LPVu79FFPuzLQSFI6S9yq3CL8KwFuAIb+FgDfw1XYWVGJD+ZnTlDqy1NTcsij4lMHlMzHqHxnUzNxNPH62/PNBSCKwAwUnhZZG1cT9J8snD0Kw4cHCXrCaw6uvIb5UbsVL8YsVfr85O+QEDbXoS1kVfol4oUB7rH0g8A45RP0zUPIjdow8vU4On/MJKNnRu2DeejxMP81r3L7r6LY0xFV4AP7L89RG4ifZaZ3/oCUBBasHn+2Xqd1anK7Vl8lzMElUcOffpKeavQFoYijl9oHS+k71S8r4S3DgJawZ4GgqrO0DhZR29YsqxChKV9phqLDEk+a+l/hYu1IY2g9y4fuNuhzZZuaMV7uW3cgWyvZavk2+F9Q9rBUSjwL9f79Zq1lDeFNOaZikcUlJPu4oyCfs19onFl4NET/+x2NZJCYuzP5A6saPJywVhhwFubB43Yw35E5yb9wKUcxRAM/CrjPUi4Tougdf+SkXLidRaJ/bXNuqfbdIWag7w/UxO9+Dr/KM+/M+LroWgtaXCTd4COxYyM02yAKPJEoKBetW5H5cUeDkQLH1cLHGArGsTXLFnsIAHbx5E61zlFqssjdZK1knXt3UcDqPnw9ylLgNyXHok6+oxzZUgZ/WmJDKC9wPzEhuYr0fWPfYJpPqE20HmVmqE7PvfhjvInxQub3YYv22DvwgfuST4D91TPVhWaIssB0TDrSQtUbU/+A2uI1JkKszkSjjxqlcfDP7orEmttrSudEaC83kpmoyViBLM48d2DtqsVpVvEa6vkRsajCdxy8Y1WyeXeMj5KTbe0xyA5uBGcFJ3OMP0qHw/4XwflzHY9BeL03HytZH+FnSlV+C/uSR2Nl7XCsAy88RZtW7WO+tXOZyYaazKLcL560GF134Mtx7en7ViQeN8Y8+GkyaxJek9O7U+i/+yK1T468zF+V2yeVCZsp3y+hsxcMtdohfNY+xUCXA/TPxGp+iMka/A2/ONLkSu/pyzqWFKrrYlpSWWPwAgLpswjKuRqt2jtw1+mzS7vrdtUPEIfzmK1LXSniS9JS54snEvn65fbRYcpbnVm+8DoHu8V+H3FP/tI6tOqm581ebe+rfNrr0T5un7E/buPUxmF8/0zYh5UcLaEaqyuUcgfkTPH7cYdB6CmxrQTiSxuFR2htAQArwxKvcOMzQVYQ50Ivsvfi314SIQNnzrVzGSeUmzThnM5CPlHd0dForKjmpUAlaRl8p3omRfuAdH+MlASLSxQPNiqyTo3gtO/QBSSTyjisr3GaH834EchK8EAuKl+R4kXJkIZXikxzphUrkars1258UwZQ7qkBpVLGhYl+Gs8fs8GQBgtal3omRvoAkp8RlA6Uld9uco7KD6ZZ7b7e6TDIHtUxWL17P8V1pYcNd1qaD67vCYtnLdjW7XSscdf9b0pQiTl+zlU76Z+NfQ5DbKrMdugsEsyDI1XzZNl3QiyQp+qB//tNZ30nvfE7XhEqXopIguazOmh04e3r3r7/JhyT/Gn9gW15QebJv1I4NxodmmS+woJvzEpI3xeOG4P1b0Ro5iryL1/qA8ap8l/XJPo7pYcaRaD8KlYagSa7Vk0fAS8oqOoTX4p1PSYNz4i3Ek335SOKf44E24qG5Hq8WpRegpbZqLvlSH4to0xBeMs12D7RabPfubsEnKiUYt2UWoW/4m8Q7NUmyFs1Zz0xmJhRmyPCe+PR3pFVi/FV2UXvkUyX2KCNmiFnM3vcFP6q7uvu9i/I9VkbqllTcH5wiiFnsBR/jzuku4d/5vfGrYNG7PXPHPOPiP3ossCTSY+HfRoOZDrnRsOa+2Q72yHzVwkMv1Lt3z+lytz80/pYT7Lh9h5v6xd1zL4vlusAsLLkjLmmKtX/8mniwLzY8hx6+IuZ84XsF0OcdzrU7NEFrkpWqDaY7dATHd5i85BtqiUFJ4CaLCXRWG/Bh9Ux8cGkA4mS7HAdWiwfdNvCFDj274ttXAK7hqxJVES6NT9vDmPHviyvXF1aGbQ+BiYiJ8++xm7/OdLdd3ZUxr2AXI4ydnrs1Fy8H5ysTtG2yXbQmmahfLSng0Sh/h9y0qs12L74ZjeVufsfZQfVieCq2LZpv6jpMyN9LRNU3VqRT0/0ZFbsP5GL68vs/asjNuS3fVEW5kJ2GbcF7bvN7TGB1vNpjPc0n/U6sGDTTFPtaVj86XL5gpv5LmpvBzVxyG8V4ifpkOVjeFnbjRYYlS/JQBbpVHUzh7pIoPv1CP0OSu7KTr/mXle5IJEZt9MPkXYNa5C7wK3iZ8YPV/r7YOryqj1QvcOLmqN6v31EagnZWcA8EJUkiRE3sPJJXtT2WSJr9HeYYjXuJB5twkhdjoziBtf3NNG3GQ9L5r5cHcUFokT6pNtApHrif3rOLdjRjgtaUsTkee2S6SgRqmp32V2MdGeUtXLP5e0w1AulJ8usOmsgmXOYil8tY9KFR581Dxt3vopv2lyFz0jI2lT+7tFGlvE5U84TXZOwwbuq4EpP4qBnRG414KYJg5gTI8ylZsWtB+/th3DeFxw6Xps9ETm5gfj5Wjp2vP64HwCRP1AHUphRV5XamTb5S3l3q/g5AFqmB2hpHT6vSdzfgt/AxOeIduNJd5EqMQtBxthvNjpVaU7weq8MGbGZfSnFT/RrpR4TQV2OriaS0vGisiBi8YHIT4gWl2K3ikHFBScyc6FPkbU1gigWtXmh7V3Gsm7hCXNZSfseObiW7LMyLXmOLqon1JenZ5iEvJfB1XyBWnm20uQ9ZJTjQrL1dYftaqnTt18F9wj+C5b/MNvOSyiVD+VezqIuNf+P8gWS8tsQGmDJmfEHGWvwPgmP+lfN2jLLq2Ps+T3UtWt2VqlG4hRHKil9blEDqBctaSbb5HaYgJnUmZEsSs6e5mu/kjw9dbkamjnzxxcB5eaqDiVskkhgdjwelHjOngV046wTTKFP+6PULTUtteMp9t9TNhf2uY7bT6IPO98EziH1kWfWKPQpXOAmzL1yxmNd+CO/GP7eG6yqel6s0+4TYfjQ3XlHrzlKsCbttq3z5R998uJBuwR5fNb99OpTlSDPnxG2RgbHRiJv6tfTZR061HVTomGS10wt3XP4l2Ypfwt9+oJz6hofHZ/iiRPxwLieRm5dSmofvhDnHQG+bzF48KFVqPtW7X6HnPbuDvnHHpWlJFXYBf/OecvID4OGSnCC0Fu/M5yRx89M2bcCrYU4vmFnUBggVvXLIUIrfkUZdoxfQy3bf/yet7rjjS+Kh9ehwJVvGTUwsi8GBQnt6SuTVlV499Gdt9SIIEE6xtr/Zm4uqR4cDhd6jwPMh+XHmqUb8nHvFlyRA2ehIOTednZQA09g5kYUdm4RXC/OwWtxHFm8xwbzfvUhHK+lVBbV9PpmJwnnhz4EVjoeRn5QG0s+0YLIGXyWfwuNn8d14113y8fm3E0zCZHgWqrsp7FR3o6BIX6krysEjUkmWEL6OGuGxzot4gdSvV8KOpnRWisLZUWoYqF/XgUnfhtjnKIlb2nYvD1ULaqLmkK2sFtr0b6BW65IBhXPD3wJzBL9f/y/x/3fmANqJ6jsoNXBkTE0cZkusjVt2n8jAnQSOz4DrSHXkVSfNG9mzHXZiW7KIFKoDPTmf/BGpnNkPNzJBibCgjcYApYHvcIa41kypJJzCUiU6TopW6SRXqPJXG+iBygMZLCkrPiFZgmuCysA0jPj8jH2O+4yUaq3snk5xN4iQky24iSvu0Z66WJvvEl60IHE7OOLWC2gOvGxWfMD6QBzKalS678BQJtpMM3d3dkeaoNzHhDPE/Q7aZsI5Yl2UXoIhc52xt8t/oNCo+elSY76LZId28m5YSHJkr6c6rnF0wMBq++uqzfvNF/xgniOCRFfEKYyaobljgrWlzWmM/TYLddSd75ZQWzUIxizhsRP/84oAypkD+GG8/SbvCBjiqf9C+0ze3bi+B3cUXjb3o0irVTpYjsE3rmfco7gsjbiTgBeOMZ8qQSAv8DmwAolA2kCG3XjvbuwQ6r7Gawfvwk5Gqt3CRcY6fSWUNjWCJVIYnhT5VAt2ALXfYHVq/YuVxOxFg4nZsbgjePN435qTO0uv4xlhts5MZNzT0bUyW/VJRirno8kgbuCz5176X7rjxPHvmxbUeYXRBa7CffjnpmQluea5JKXus8pqNYfgWlLp7dybaVmD9qJ3E8r/af+hWVHtmBnlWxOxrejILXjJm+n1HphHaEOlXNYOINp9UGgM2kEkDFPiSfVxA9cicrBy/GpF0DfWNjve7t1/PpdtgYMo3mLVqYBlGzJaz4rq6EFB1Oi4TNDweN2rfj24TKKHFp5FV3e+W0Q6wKX/e330VsBu96gkiHKuDTvYKMGsr+nL1Aak4gFbb66OrnUHyPDiD7QOwl5g9z/MPcqSKVyn/upHLajrGqsdBnY1nspiy5hhNbIibAM6m8ON+Ab0jY399MgarBb9TJCdomVyf+lGOS/QM1/uQYqkFDec44Q3Y/cJygu85yvgAYWJCagc68tgR7Ei8iUFcAbUL4H+q+Iy5dYyWJ7UHpcUImtNxYbn0MJXRMch3wp7IicDZ03CiuvzGPJHb13ciyzQZ7XzlVq5c9rnM2CB0Oax2uA3yY+SMWJzWrn1tOrZabWzT5Yu/jj53LPGFTV8TGmYwvoBc/ZmSVS++rUy65qP4HkbXG5PgN6gTrve8WyvePDSgl8IFmqsvDnviyTc/PWijPMrL7mjF8UXp/D83IL5lqfPBqoEOtVrHvslvwJ/9kjq+miCpXH65SP6clbNODzuLCyT7igVb/9VFPy0PcMwO6ncZO4QM5M5/16yFAyqHu68++D3RTDqQT7mWhEbz5/4URb6L1TO+cRGAC3QBgBtUEb2aAVQgCDcZy6qWO982DLzVcHDBE1NdOwj5wNgHYW0DO9VCC7WV3BfTFWIWGyk4HESSzyG5RRsAM9XiGXYRMGXormQLbq6DFIFD8dUhQjCRgoegukKqR4bKkSPpeoy7Y3t885oQgtti9w61obGmU1h3WAxNvMP/QOb8APDNmHdCK9sItYAwAMhsBQjg1oHaag30b5iDuGN2GITcLgUH5h5RRQ6REQaAGb4SVHsopZjH0qbaTR1U/ucmdMS2X5iZr/ERWYRMrAxcHEH0eiy3kQZc0HLsXbKqHDmKyUmnYf0kAnm9AslNA+UR3Pt8pAXIYNizmfRmxRm/kMY4gtkY+2GWcxqn0YcPpuJz6YrlpcinA+Ux2zt8iiHKuNKeXgdOWhh2RtEbYcCUkOruR7FGQpR004g7gyL9RTYjhl+tFIqlzA1cqZoK9qZttR2R2SG7YysYS6ksKuhNXhxTphrHi4FhrFIViGkeYhF03Pk18A5KihAE8+DWgBzPrNoh01aJHwF2wJGW22gETsoz51GK8AyhduzlAgtLl1mkWcy3Y4vJWJjBT3C8xXsFDZRUFGcxKqKGWmROGpmsdsvtVXK7vhhDz+TCVTan7qz96r2tl3HqOEtvGxIrD9ehSfcbZN9NCnyLJHNkzbfzovp7JF0jS2NGR3vZMk2YjkbkDYqRopCrNxBwUbuSUEguyBIZMlVS7K0V89oPnYOeDoM3qbJOFXeNwWxPJcdhrdf/lTTCt+tp5lkLagBuorK0DlWVxxpIPtp/lfeBlOaZVpANm3/kQ7SPnPbktv3URw3cXw+XzLmMpXbIy1zgej2XGfiIvKuGFb2kcXJtyb9bG9uMXQ6l/EGRy9mjEHcbDrbDIq+Pxo9AoqsmifDU9oP0htHmbhj69u8Jefg1wiefdHiaxTdMJ0407mT40YbpE+OhqV9Hyz7lS3Ejen+nwmUram4dFvNTbESffH7qHQiLUeBqO/Wk7lBG2Rb9geKIB0we7Mmh67FMsf17agd3JKORTuxMKiYNZeZ8LJoxS1tciiaL9G57zJ9FKnH5DWKat/LfX9o7yX8ac+aHrp0Q1y2YBtnxgcgW3TokkFab/rogCLPD4NYZ/+DvrRkSckGOHYb8XRy5wMK1WwEVbCTc1hQkNemmQ+7FtM/l/vtWqcg7lggydkAzb5xu0hHQkDc8PWNZ4otpifL/ium+ADAuz95bwA/PLn9+Wv1/0MvGY8UGBoMIAJFl1wmQPGuLvmGjQforrMb/bV2irCAUQ6IXnbTGHX/KIlMAu2poP28lPEekhYsSlz61OVrB3PB3iwnziyLE2dpjGgj5IuVrrVkfe7Jdae9K9WddekJFR3b4r0LJ65EHE0mK84/nOcwyD+XQDqzSdr6KT225s5BK8/aNuc0lSmmPSW9mgm1E+NC3lMffc7LnsJ26pEgoqynGC/ibOi5GSZOLsX1knucJMfF2Z1H/SgJ2fNYxpna/m3BPKOYj22PbeuO0IrNpbcHCGeQ6PGd8blIHHq4sv5v7/gJSxKT/NWSqsko6qmLj7ywrcJBxHT/5RVDVnltMch/AwrYAIULUGGZnLs6OWmTaOcfxRxfpqQDN6GX8oBO6HhnrM27tUemlU6eEw+beqqo7Xj7p0D8xmnnE8XTQHs24T14dPZVvE0SmdccRqmD0e3JQ6gfF17zwIX0Sx4PJ+OvcKLIz4xZaem3IQoKaYzw8OnAzLmpoJMkvM2hnb8UjxPt7UI8MWxTTjfl/ZTDDFc9Wjaggwnoybynty+y2t1s9kJtQxeacFujrfxU9PlO7fNzlfZOw0h/tSYiy2eTLQOwekx4bfVeHdWeWwdsGzqdp852P9NDUQlQoGpPelhb8mIqzgL+HTxBDwxhD0TBBizgCoTBk3apCYI0qMLbQBFWyk5FgB1Y0S7YgzU1BZqDIniBJ7jX2QVZMEzaN+hsW+JOoB/wpDTgD850aaAhMIdV9dj6J6HXRoVpdDJ0B21BJ5OAgL9sJuKFRORismpYN+TDlIqJgkNpcWAaIF2JzBJ0JYYp40rcXBtzE1eSaDmMyNLdBWXz8AMsJEmWSSpWtBipVBnQo08cqmwkqbo9XuS17SQKp8NWKyje48bMU4gskldGkpJ1FhFgbm9hYRSlRlQ5Dn5yY6VJYCdVqHixwqm7V625l4hQiljgiXiRTjtDppai794UtJcWiYZ0rVQmM6NLxHSm4zojWeitI+lIIhXtZIxESpSSpUCmNexYsOLEnfFFiD4mPTgI30CQiHAGAAA=) - format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, - U+FE2E-FE2F; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAB0wAA4AAAAAN9AAABzZAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmobmnocNgZgAIIEEQwKw1i2CQuCEAABNgIkA4QcBCAFgzIHIBv6LhXc9d0OQlLmtmQkQtg4gChsLYqSwfiU/X+9wI0hUv/ESljasdKOLTGMi44Ndgq6GqWg9LAyZSaQ1p2jO4gS3GO52RdM1zk/kVej1lvvb916njBD4+ETR2hyip0e/N39agQ2E4uSVEGghOwN6WYXpPWQqgRRjyha0wCtB/EaOgzLb9Pfu/Z2gDPJbgFAHz8PpANbQIyq/SvsAQrZCnUkaTL5UDx0hBQuWtrOtqcReJzBYjAGoQxOv0HSnf+5Fg+TUohWeR0q3kQ9Xiap+ObpzxX5eZrb+/dvcVuzkW1i0QoGPSIFiZZMqRKkVCpMjGZmYBZmYCEg1jDBJrQZ7OWgjSirppuMh67lD7df+KNVl3LJKjTepvzfWpntSoeoAgjCbWLjo3T1r05N/66uAe7XIZoFwNkwKiChowYCfEDgLutynkDoGHfenroNPE9TZ/PasmSEjKyMd5djvg7F/LDlMaaaXgSHm8Ya4L+51R3vQjmWFlJe/PwkCLK2ZIrao1UIT8JdOgs824sX1UVVRHw3Xqt23FhdSz4iQYIXwkPStQfxtJicUREbHtUNErA+XstdorxXhhhYQOwU4mZQLz8NoimLpbwszcvTK/f00Rv9MAVWD5hHoyHg/hM1M9mJs0WgvXv1d53w1MtvE76H5udu0FuuqwYoqA48EAPIkMRoo5z23dR7BEQaIAEAVZTcQn6kRdCesSro1vQjrGf0cVbFR8pNZlYwpjHK3tsuxjHGKNOAac5cyeYw1zNllJg1TkmoWGotdWCWP0W9omQsyZkZz0Hy2iDHMg8yr2S1szaynrEG2UqsHxJkyzkrwXcDIFjt7g8ZEAZmHbOmP2gzIzaOXD+slZWIT+mkOqGroajYAWm/ra+8xcyPglVJPHNXew50oO5nsx6bFd1Xn1ybYF0feLpL2M+nnkqOI256UcjrotQawk89RYYtoDPxnjgioWbbyctYjKeoqus0jPMfLCe7mjK6GPfaEguW1wYE0h7Qbq/1DexBJhQjoq4WpHG9Lg76FngorPD9NMndQbWkG59P0aJ3oPoW/emn6fuKrU5LX8A1xfdc12PaN2Daeic32Tp53hfEBkd25/b3slLKr9Cs2aqBqhosGijCdXnIbTxH821ua0erQbGbl06BWv7/hiiUipqGlo6egZGJmYWNnYOTi5uHl49fQFBIWBwGR6AxOLyMgqIz567duvPgkaCk4sWrNx9EVTV1TS0dPX0DYwg0iCaIIY8lnT2aJ0QkE9Yzrm9COjFINU8nQTfTIME02CG0cap8msYZspjzWVLY43m6FgoSCxIPkgySCpIOgvWOAAoajoxF6xdSiI2rZmlAi75/MDmatlr0YIKGdww5LGmyr26E+pRuzI0bSVKkC9YDAimg4chQ7BfSiE2o5mhEW2Sd9t0/YdI3bck2tAsaa3t6FooWI06SFOmCBRAiBTQcGYqKPRtii2mHHTrhYDHJuhAWBAwkBAYz/2EYhmE+wTAMwzB/Fn7BMP9hGK5/a9tW+ijKJCoIDY3eOvMq2C42YWsSktIUIEq+Vf00Rd5PAxah2YbAXvDC5YkKjpitlIq1ZaMStsFqD/TWysvgZfCuRQuFwDs+D1uVoIAlIpNw3i5QECwqrarrOk7l4QK0SRpbswXC9M5wJ1xonZ0sxTrpkVs+A7HcechSxdN40ccwLM3WtiRLpCgooJhZPR1N4zJg4GCg4YacYVILdUGFSYIsVBpDfD7NtSGUWX1oiGSJLeNCkhRpsbOEQEkDR4aiDWjZ7dHnj4myxpGH23bDN7BcojIurIu5cSFJinTB0hFAQklTmL5wmIEiDVr0+WMyPgvPkqdemj1qYw/Gz5eFe5IIL3CVsLCmNSJXMMmbjkU9BoynswKz2cRKkgZ3lLVpvPmyHYCPWLjc5A3TEc58tHC2LraxB2PlxXoAmXkmnUKdKTlYtT19MCecCf8okavYgh918qA6QHkiVS1tyG5GwLpRqVICNE6SCoR7fH0sm6dvg8eq4BbU27poGDYgW/V0vzqPIbN+eLrv8FJ/gSkucoHOe1X6yn+NTx9WYIvCuXz8YraAHLvTopyXSkJvA5ONt+3AlpvdVZxwGZxsooCrplZqYYAdetlhgE709NZDpK42lEtTHNhaPZTgUQiGdGKInZxNdZCsmJAniuVL/xHv4lqGI11JSAR+XBM9deUC929Y1sDT2/6fb9hW1X3DocK5fkpFsHH3A2qZ9TsItY/6IRthOn9VIHQddHGHEN5mAyiQQ3Lq4FLAulOKCBDtOvlRARAACPCAA1ygAQMAMNBBiAl8YOSbXjLphIFsXVhbFCYQECUAPVMREXYpmADBkjObjYEHmAIgJVgRIEBAonQafVPWJUI0cIqYFDGBDXROQhYhYAAnCLAkbGAAFA1QV139DHQNXUfXOVcHqKQw0VZMlo6tsDnQOmsOQJqzW8V3RE8AIP6TL/M9O3xlCIBI0H6nwzhA9OmcoAWtAwCkZUn/qBasCAhSLB9mlIRRKQfqyyBI/cyIXdwTmobs/VhPTAASSIPMjH08sjrSZugfZfkQwN9Lf/3LFCBs8wMAlN2pVCBtQXQEG9w8I0SxH/OqAq0SndVRr+b5YcmzB2bjq/c3z8Jqf3GO+MbqIqJiGuISklKa0lsGYoq44lgxp03zvnz78but5TvxZ2Lg1ONGHTfMiaxEqiggnlb9CEYfvBugRJBPux9NErA6DMgUC+F8jXRo+8/ovis1ZsGEVYfsNKnpcG4JjInf2oImukkG3hA5lR8mTwN8MaP0XJSCjW66AZlb18JeVmpEPvD+tscCG3PkbP2Xee8h1lYOBSluu0ocK8FDDtm9vN2Y72q2SJe7bivwfL4PXuBgwhQh/j9lNpchGJubnL707o1fp98RIwhiCy+ZkUPeK1Kd3MfQnwylwQY2w3rG3rsd/TD8Y9aoUPiufU7DihXZsOibVZ/0uAixK2Kx8+wb0SgBMcWKM2fqGh0PRsxhNWkf7IZK3tzHTshyS3DLSYM4AEJd7zM1Rz5oQ9/6udmdzSpyF87GmLCZ5V9WnukFDqUnAvqHe+/LCQMKKeWMLKdEnhTNtCQEXDxtJabVw3fU9lmDtK85hKC9V4l6fqVq2Ifb1mRIkR+ab7GNU6G3NadUxKih1UTbnAzVotmsxScIO+H+B39qgO68ZbdJZN4bu4upZc9TL8MD+GBCzDI2+sYV6Jy0OzxnT9hQumEV0wu0CqpQv1AS3tjJpNpK+PaIrYBonpXLUBOd6EuYiBTvvYE0zPTIRx+EUfHux/uMNDHsGxx2bCPTSXInDG3892+2OXkBV3Aa1unZgpiGVheZV7yBw7ZSCrCsRsfKhiCP7LVqOq53R5QYgmZG4ED/Pj8gciKpbFaB3JrG1exAceodolPsYsVEmkGY/hGrkteC680JxFcNIxctBiie7RSMgLjRFRvSF7UFsQigOhR6BooNbcEJqKyDBAoPwWm5R8WEXiHpKx08IEqDmhbf4W9WK5ElmJs769CAG7aHXSfK2BumZn0tQ991pkTauqMt1ccOiI+Y4bwNhe+6XdDI63ZCTwub+A8Fw2y0GYipqISboN2Z7EFAVTixA25TvgaQ2HYXDmfcqthuYF1/FZsB98gghDlwzcFdvnImQnDToJUWsH/7HqSYdXyb/GW2gHe2UeL2lHFKv8qxiod4c4CmAg5tbr8I6Z7ldudzykvuZ2sLKfy2NljsiY77yaD5wOZOM3+rdgSlxq/7C5DqTnTQXmmG73k627EPRnpi9T+HCKBDIwMCWQeACBfx7pYeIwLv8tEnSHREjGzD3mPRihpLVIKyfQJ07CBdddMElCETWZsCNyNm6yYje1ZcftBJyL1AuZIovkzKiBcumSouOeyw3ese9F7veVMd9/ImgfgRMk34ZWtG+afXQgubvTtpF9Plvt7rN/d1Dzjp3GDRCkQJPAEff7T8/JCxrzYGmvAkTpYzmn4zfUQB3eWrgIsCo+9UFSozAe7SM2jlxDM4fX/tqDzG8/a5z+fNxYz1Im6zI5x7lo0kzz1Bo4hwdf5eImBj32Fq9Vlaa5uNQFDQyTMFsBX3FzYA2Dj88grrOS7ebdJwJ7KkOsVZk7+WmZERoZbZNf7Ki3y8DwwswY6ioGx1sI0gi0TsSJSHokjiOtRxRQbhuuqB9bD7qgRbh02kyKawhIOBE8Z0zDRMmoZOot9RY6fxa+fUVOStpGDXK5qRht8wN6411LC30jfdpPNAk57HUUFAYwjL7LK/sJe93YBR8AoUjMHsjrf2bi/WLH3pC+Fm6a+vh+0R/mDIvy89BZ9h6Cp3v7B/NN5fM3w7PYt7Se/D6K7VbhcJyOrJ5yVwo/0zYjDj2BvI68jgRigdu08HAPSGp3pv3XmjuIa4XZg1Sm+jpdmsOGOmtGYn8Qj/YzI+/iS7cmqyiY3k0+/6H0UVzChG9LQDaSF+hALLbRpYza6xdT29RefKGv4FaZvutXV2DXZQI0upzE6pHOPfl47FBWfHBo/BVNngC5OB6UGpjPX2v0a/2thtfA0/+ERd/AncgdM4Eq9cLs6F2emXDrkcR/o8M7vb1/78H65ardykKQb9d1KuT4B+ZoAt/4JU5jNUEqJf4bKP+yMpoMPjLt2eBb6ieuJB6TIZo5teYOnaKhfru6v+DX6IQZsto+WbL6jhRPvv7eL2KDHjaImzjmSHBRCF+GxLzizqPXWo/E453kW+4ur8gHy1YDXm/y9hAP8SXBf2m/z6i1xTQZU7qgS53OTkyhRyDkBmYOAIt3lAxt00cFD3WgRMmdOTy5mi98zqrtxTcbl46syPphcFoL/0zsEHRuPQdFhteUEnrkNHpLQqxg7Fc0MdiOvk6ylKyCOcUboHx2YI0SOLW/u9s5AUX7gu2Oj1h+E/RRG92C1BxY5X9K6nQuW6pSw/xiKJC/yOryNuVkV8Zq+eJNzUTf9UtYK4iq/qK33mxmxnluSuiUftZEn1skKbsOfx6PvG47Rg/hkwTgpk2ft7AmeYfd5y+KrYzMG1r8FFYmohcWoodXUENWNLTmaH/Nbj+1rRV3uB6PQTg2LlZk5zi5rY0kGy97vBjua91XlO9uCoJVjbjr/UN+AadGVV0G9uO39nJ2O0rhFXo8srg39xWj5nkLFLi/yJXGJTn3grLbwkqiEMt2G/duMgbg7DGxZ4KYs2VDCuVxYR23BYRhgxIrB78giEKfmVO3A0tEV7nCOWcb5ak45ESUB9AFqOw4u830zLqcZZxPqT0DpVEKHjYn/Dj76fbBg/tRftRI9Ooo5BQJLFPhLknuq6khugam+jfsGXfoSMLmi/45FFSNHHK2jNACDfSH9fWJLpCOP4eLj8Gs1R5V+tqVSqeMeMj9QvOBzs/ZQ+Sfxz+USe8LQVio73LCZS7PUl5ilsH0MZiC/cMLVbNGuOne1CcxubMBuHZTkm9ou0L3LmY95Fi0DVF9TnGt0EvpXfH5he+EBVHO2oxOVobXtJL5C1OTbOrifAsWKgNngq8i9Iy6BSdlaJ15+tP7j+GHjhUldnkIxeoJ/fkCvCR2aj/yG5UzV44wpeLicprSQHJxENmll1Y/D5c3WvuYGk4anWGw/+lxReIHuE3kFLzdhnrrpmG/EQ/2WwBqvnfE1eTRbRQvbfnTf4HXSvfGCG03oKj+TjGtrBVt1G8MIbBFCN+7OirrFKBXctyR/a3OaBPaks9YZFM/8I+shA+Sszi5gbXkySySVXtzYUPQ5gC1ER6m0SFvCSUqtiMah62yUkxMvCpv+F1/Dfgs/yb1j8/4Em5SYk5Wq1W/Z8zOdD8zmXoN21vHRuTGp+PAY38cAru6hS1eXoEx78ofhAcmnM+XJxirj+JC2S2KNasN8s2RN0ry0EOX3pGHfT+0QA0bl5q3XM2OZ1ngCHewM188L+wxv4ZwjO8W+Z//+hMmjRzDe/Fg8zWngVL5sbm5LzLbi/jv5sFbXeOmokYMZSIt1rzWxTbpVPIbf5/YEF68kQzM5U6Ux6J1joYwNuizJ7kjJkzX3XXMxYpF8umt6t+jF0TVyorHr2aw6FWujtM/2nC4YZTkXrl7Hj2MEFKYkoGm1IEYT9AGZ2/dGx2Fr0khx7yD0iuEksi5geuJOewD5mMDjAXnAHwXv6qW+AI0tzolAhPlPCTVI5f1tp9gHQuQQO96UTuac6W3d8lvf4+HnmBLkg9cs6Y0Eb47/8s2jJisJC+vr+yV/kS/+VoPXw2jH1qcY7vTv7yorQjAV0hUumr5IXJdjkyzUrELDggt76wYa5pfNrBdv5PXt4NW7dSw4Qqw1PDRue3j7Uls7lrxFsP6Jk2LUDpJMvvjfCeqJtNVcaGGeoOUKFrejts1XPKZFQWHmzIRQLq3jJtUVJeAxhmGdnxpS380L44LtZ1M8i3qpj6i78Dn35pvTU+bLM+Qq/OLSURrsxOX8raP+Ucpvf7waATHZACbcihxflX5C+ycc9MLI5TfPxvODQBe9fLKyD0qzQaf/gFYyrvAv82+b/ZSj3wHCJyHjxsBBK9qzmZXOiE/MSMaiJyn0DDHrC8rFJ9MehH6jTV438tqfBosf0zsKqfKKJvHHf4vMf0L02wogk1pYdLMTVuLdDp+kHGL6TiAZxPdFfmDPKbKMts687YSTq3kI8xwTJGIBFo+I3JJ5L0Y/EBvH9aU5bucvg9Yj3bpvkqfnE79ZLw8sQTSpFU16aHL3A7zyVzaprvf4/fu1H4N+X6ka+5qXGV6bjUVgywahyVw1Mfjt+FN8UCR/Iy4xmvcQ1+GJ9wC9+ixhTkpnuOvXvZwULG9XEUX2MSM/iDq9J5qd6FrSuaSs+54YKXFxqWQF0Jwt6ZHi6H5FJrOsVrxNzaqLXgQ77vOUaaMLhU3ocmdupdbc8vJXCctFisunj5mvEtetGnO8QRiQ7MRe02y/yJL7uOQj35EurXawjiasA3sjsS1RPdtF8tQdh5qm4sJIRje2uJU+pnpwGfzxktnDd5lV+DSBiiGactYVhwrJmw/yv+8ud9w1X98uw2jfrkvXgH1HPtkynbcPVsx5jvm3mLv7YZCWYG6lCOgVnRc120LItwG5kbH7rA48Cohc9OYFbPyHb8MUefjk+LAdx5SbyMGjs6QIfFO3ItEl2s7eVoHQX3oIhYDf9OnAYpaNep8AVYGJr+aOw78jv4/Ydq8DDnUWSneX+e5H0hiT2mr4SzjHUBdtmS/YByxGqJ9sg4pzxu2vX14KX/OXZAYz0Vo09PM/QG7Bnmmo/1wince7RpqMbNz8ufkyhvD7UjjgfaN3gyFXjEbezba5nR6COCLYBePI8Z4B1ZK4PtT93mOrJ9dQ+0wTaFR42yFbN7+aw/107LQfUhtaOwm2+n43CxvIvx9NSCTdw0PTcMey55ZF94/pHxGG2b4Dy/hJ8qvCIFTOAST5aRddml12ON3j/157pO4PaX0VPjSm/Zqn9AFtGA9fHcoTan9NO9eQcPq/VicRjswUKsHTYLj5APrwP3Xwqd9zYecTEJdSOndNA8yLSFMI4w/8qDEi0BziMhQ41qOYu9oCdC6oH3vAnvDYuZCjDgUTisfkCz9vAnr/QwOP1fejFN/uY61nb8O1rL6me7Bna59SCVOYFPYRAlB/M8WK5OC9xxrASCuzZyaKKyxIJ7ld30J6A/PGAzrk6b1QQy/d4AcyEst4bYWlQhU/U+o7xWqYI17ag4bp6vAPfeknb9wLIAN8sD3yRFjjZE9S32jAKgxqhpPK4/ROt0dO4Bp+rDfrHb5OX371fUGcdOS2XKCTOF0Q8YJReBbdzAr0LFyPfqURseLE/kU1uP6O0kx5WEbYyFOcQW65Se2DhUssv/puHbOv69etI16Pu01xayABqPaPvwmBsr6urDfoGJmZXIRAVhcC087uJ2Z8q63fgdtR6V+50rkzxwOXzmxehhXyNM+5TizX78kckxpzcMqICRZUzM+jDnB+7O9R3dKhtHVHfSsLArsWoLFrk9QJY8eV77kWmErX4VPViGb9NpIZmmDyn9eIbr9D+5+GBaV44hmisndbhB+pbnTjFIY1gQ1ouyLkPe8mbh5jtrE0T76532DfNl/iYTrk8uplcKr68KJCR3KLeLVwaeiPP0tT6ISxBBYEcN2HVRgry1rbZd44sRK7P7IGLN156PWvd8DRwtSzNvv48glBeCMt5nZOLBwlG4oNq079W1u/EHaj5vtyJjMPDWcckenxlo8tRzJ255MEq9e1VqutHNNYr2xFMDGwVF1pFjVhH2c0c4DgwzGA2c5sHzi5arpkX+h7MbLKfbmw9/pmp+RBk3On2VGn2UJ0uWHv3Yiuux5vOsjroTvyt/eeb8Srcc45q3YkYobax9siFiEvkRVA+jBCbeAfkjmJTucGaZNhEqVvMXioe4d+Xjot8FNmZikNglbInIeX0qFcTF1lIRVrHnF8+qATGfUXyq/bZeai/djv5kLmSkd9+4ndUHVFF9KemXMYlP4Gell6YQWSi9WncMFHRSUeJyoDnwWesViqv/tCfyFa0Ej5m5d8mK2TAyK9eXoKWofVx8GGXDyqLFnq9BFZ8Re+t8FSiBp2r9Zfx2nQE3c3jn6tX4V5859WBF8EBWYtxDV73nfaczgGLRvKWP/7lj8+rby8UlBO0673HezW0dYkCeAH3HdcNO6y7rL59I9XfMBT1N/bv+EF5w2Yg0nUDDABggKpRZBUm0Sy1cXTTgYJkUkdvbwZr0SEgajbx2jxMA9OXxpCnQIrmpTkRg+6pBPzgwIQrLQ8POnwEyEnEkvOH7nZRQBEVKfsQbTqo/qw0l9zVXERJYm91fRXSv+SbXqCsbNsJlUZ/fOPqwqHrqQFlKTp1y5vufenFp/+qPfG/XwDAEJDHDguMALnrWDEBxKSSzj7gaYcFeEJMeEkZAVr+KwzvtGOq66S8QHkfvd40mNxjQE5wjnWhOka1Cirgh9FvYhVVE1os7brM2a8cSW8Y1VJxaZd0i6YT6ls0B3gF5TNYz+Jhbg+GID0pA9KxnrDojzGMVz/ewXBpuH/tIhfLPppZIkxqmHYDc17cXt+p9ad1Ph5mSFG0R3RG89d1sTn3c4yH28nS+sYRrQ8ahh0rx4orSofSBt8+AgBC9+1R/P4N5c/7Y+UHAADOv4qtAAD3h9frT+L/PpXzZCCAAgIAABAAI/FyACizZNCNuATQfv2lqlarpV4D+g1oxr0pXxiWqqgk+YPrGc65TOIPkyMM9/39ZSZaQgEY5ozufO9zs8bVWNGJsbmTBprjX3OSxSKx/Rg2qK2vfXTd6YMr053Z4PIU01kJxslgRrWKUT3RUJZiHo9+efwYbWPrq5p+PtOtN11x0no+x2lUFcNa0S8Z1rXN+dZ9+hXrwkkw9Vw0tX6q3jcYZZBuzeJ+DMzO05Ymik2y6SwJpTzp5dut14NAIcWU40snpX1ZL+mkiHIry3rNu6SsciQ+2E3qjqa8+8jlD/ftWEEPe5A+3R1EL0v6IP64UnHu3trn+2gdUwFezSvnWkV4ftMtFhihBL1bc5QeToGUx7UR0CTQA4U7VYVb1SMHVA7URqAX2Hk5gdxTYY7bGBAH3VAHqA2gh/qAbkiLEr78N3bBhvWbDwQAVVZR4IsWSNhbMSXmEDZkQjQMiKTW2BAwF4GKkLkEcCBnLoZJKgqSc2lgYBeh97PLv6qwov9Sr1iQXr4XT541HXO+uIGOiUSC4om+Ky9M+SSwYmIj74F8hmwEWHZmbl1bsVTCfBMfjTS9Y1yElVMtHyh1H7yHQxUI+x+/yVNebCwm8lMisZa5+IQE7+9jOiRLOZBrjFRVkO3WO2hNRlc9rFxmJap7Msle2acybJCNRUnB8AqPtIj4neykQB5QlZI+AAA=) - format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAANUAA4AAAAABbwAAAMBAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiYbIBw2BmAANBEMCoI0ghgLEAABNgIkAxwEIAWDMgcgG5sECK4GbGM62A+KOMNGmZWUwcdhKI9l4Sh/WwYP/3af9w0W4ERa2bOg405uoSptTooGKkF8HniO5b+Iojvye4dReBbNtVHwcLQTG2gBzQfYOqjJ/XYU/jItwgxa4I3czM4Fj9LAAnlHz+dzgSO71Jqn2QML8H66dROj0qAFLYnRhtm0b89/erW/v8l/LA6we9gCizDBtQzSf4EtkcwDT6RtmgYEQXnDKGQslZyX/CkQSFgBAE4ERggEAgmwACwQgADMsONAJKVkFWEBgAJgwMz1NlLWec3G+jtZu+rXO1i7rx/sZi0AEwB5WVY28FUE1CORQAjvtSPftAwCQQjGAbTUfm4qwrvbNmDEf5pjR4JoxElAiYiMWjQyIAEy4EBGAA4UNKCgIMC7a5Cej2sCAA+SMEEyYA2AMQBWgCmQAObACrAAQAUAJCSDMEDmo7CztfXoRGu7SUeVdbvosOq6N6PHnZ2yf9l3eXPj/q2qXdkjBL+qrix1cYsqzItOvXfRPaMXkUvPeFWoxr7tZB8gfxIhMauBapmSUhO8d3O8wUt0MoI7UAxLzt0/zhCwJnVHrsPYXenm8suPeLYORWqn/3wwK6Qp+frDiYGvxHSXFzoXfpihfmlODl9oFbOqKa8nXbZgd6axNivh4JS8xEZKChij/nuDBPx/MrxQA/WBACCtK44947xa66g/k0YcALjxaesDuBuQP/7x/3bTwmQACVMkAAQYd/7HYBqK1H97hriqWIzlN7cD8Qu1mY6Ql7eR9v8qAcCY/apKqAgArEBCCmOEAExoJiOUENTgBAI3NSBhwSjIbLboV0Blo3PIiN06hxVFfmrr0WtMvzYtWg3SBPDjz58mVY8eLTrpNOm6NfKhidepk6ZAbgbym+oG6PoN0zXxUaBHgx6Demiy6Zq0GdIl3aB6ndo04r7WvSV0/Qa0Nd2+yKcNFCrSvh/6dNKO3xV33aBeEXxNZKTyQUaverfOR49+LZno1XUboBt4oSzpEiXLUSjZDgF8+JHBMIY0KQAA) - format('woff2'); - unicode-range: U+1F00-1FFF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABU0AA4AAAAAJLgAABTeAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbi3YcNgZgAIFkEQwKrkSlZwuBSAABNgIkA4MMBCAFgzIHIBueHrOiVpNataT4nwk2nboHhRIwDgpKyhjHLyLzQxmFwTYyDE5esZ3+2EabADRB2gAnegV3sg2h4vmn/cH/ujNn5kEfUoTVzJCo7tDcxAh1qBL7aK6c2RAfYY5oH5jywGzfVxj2dQKMqiNV1SGa2/3fsqgYgzZIg4jcRiiRIlUD6TaSLHVGBGIUGIlSIiAWaB/Nlf92N3lGYYsKSKjZnfSTB8DmMi27e2FKIBTaKlRVsztJrgQ/v1ar83g3J/7Bm3pohA6p0P68Qebt32Vvzv+J+e5iNnizRruQrw0imsSTJfEmoUCohFIvESLYkJkG86bdWhrvEfNUcXTtnhaEruXzgVaEu0VRWgYqCFQSqCJQjUANMogmzaJVj+izItbskHExWMtGIeDVV4+zjD3+RFc+yF6RlRIHstekRMaC7I2haQkgC2+4KiUBmJDOA0pVozaXNfBR9QCXV2CAnZZ/Pa939bym2tY015bSKkq/1bW5rl2W3bLb9zSVW4Drhr5Xrw/3s6jw6wK1JMm+D+n/woA6vO4yKdplbgIyweLmY2gZzWw+oG+f+/mW70DuJgYtfT7LzTxPyqddT+nC3/NdfLWlUjfjXEzmQ/hpKLyQ98ii2GeJyRwXTdK9mWCse91WkQMY68rJFB88T8t35mpaolV7x53YfELcGYe/k5e+Q8OkBTnHYqOSF4OEEujtXNjCIqJi4hKSUjJyiiqq1KhTr1m7bj36DRk1YdKUaTPmrFizRZJMikLoKiGpjpWa4NUnWmPomkLTHApWNF+toulu2I0Yi3nKgC9LYMKUrGeVRDIh1kjzTns2qSeP9MP0pJk8NMecFu5MvKMmX6zA/fX9Q5TOL5OXchlXyJRSLinno0o+qMoi3UyrVXFduLL6vNeQVxpzV1Mea84LjsgLhbwUIlcyZi3jNgFs8XbW2ZDJIg2tfzlzKEN1ZtUKbMD8DXNXQz5pzDQnsB/gtQLeJN4m5izUdKksg2nSRk5D9WyKQs/IZRNpGuhaSpjhGY1WObToSmatUWx1JnL5ZiO7F4xkJqXyAGWpz01EMiOaMnHN14SjHwXF8xU3i1ZZWLxpN73ceAqTchLyIBv2QRYchjzI1TkEbetj5cxPxG81MA2TYoHqf182swq5rkjT+39QyZjqzKjJ6TL4ACPwvPgGZpVcE6wV0i7YziJlYTFgz06wSoJTcyZeux6CfnM0C5WIWhExayJu64faUNggA4GImLpCRlmSyTJArnQhQdaTUlJopaw1sgZU7ypr6OEVYGgoYhCPTOddtBvLdjIHMufBjQi9q30D8MqGOGCoW0HhivaBxX30m1mMYRKTOyZX24T8t6yqO5dvKWY8MQzAsmM2BOifOGgAttxzR98dn3SWhwPAfk8fm+A/AFev2NuADZ8FqEOHuBI2prgBmrIZBgrWtzvfgonB94d6Td/a27u4n+rD/W5/2MfyH/R7xOPX9W29sx/qp/ut/qDq9O/Rf48AgdPYjW7/N/rfSMgHsINW4FzQnGsrQe1COnTqEn7aIocMixoxWnLsMePiJtgmJT7+OJkeb0rarDmOeQsWLVlGrVpTZUW1GrXq1GvQaP2LmZ7EKSRh4BXwgf9FYOwMVr0KLHcx4+QVV2Bww8AOyAZgR0TFTAKBMZhV3EvUu2AsNqQDS9LuB4/kVg9nIEAakUChYKh0Etsk91wOkcQ08QqFo2oYDIWCw0AMCzosvVYEqoQgyKYVaV4v0TbyETaLINHkqBSblnAxWVLyxFhZiRT0Sioxaa/G0+vRiXi6Zpzgqf6qMzwKSFfUSjihado5YLh79B8qKJo+FF/xdsZkMlr6To3QREwg/1Z5syFRpJPGSR1WRZchQqfBxXCvElCFwlTFk8zNkqOywH1Jozx2tXrde299rYZi3F/j8hyYUCJzj+MouoariaLpw5/zWB0WCylI6bQBtlJsuLccTCwFl1fCy8BJ66uZzMLZRmjB7AZshWCpiXFLqMjZ+pax70kYJ4g3vdADAy+STlWm6dCBArat+kIJvSkOqDI74f6iAA6NRLZV66doUoUfq975RbXQxEgnLi0r3ZerpoaNaNtv8/mYTGpIneZ0iko225hRgGG6ATv8jFaUUQFVCVL6ZPgE2AwMokMDZTmtsllFK0U39mkUrSheCG2eXAF9/PgHgEJfotR+I+o9dmaSuSLeJiIkgrGO+A9EKvYluMiT4dFRQ3pTajHWl9veBQLEMja6I+NcAZBPIQSUPOluNyL7529e9N4yW178bFRuj4sN7tkVOYyfugKg5w2paeMcad1xefLsQSWpM09kB4uLqzoNTXGmScx8wUOVlR8LTv706zKwnzRrdE29H0sexg7yeBbE9/nzNc3zNHXCm5409hjYGLDVoJ4MDuqTFBLMiY5L9ryuwp4SXqdQ+CuWGi42IIFQY6ro8cALgu77TvsSb6Jv7b9xxbjOkP/JQkGGdIzmAxbccBfRMaV17ab6OH+KR4NEzlTuvmgg55yjyo/ZiaWA7KO3jerpxRvkVdVjPk97M9g1R7fFn8Gek9FO5zVe6ONDwK8lVlcLslVyp3v09KACk89xQwUmt85+2eYA7GhJolY3o2BkbMODdnNr+lhgpjFOnbr1/OBYib21aZpysKN9OmVax6cxd/D5qSIpSPpukN+4CIbSDC6CzbQR2F1wtTFvzdtHjnInQ2MDSg0NJmd5k/L2KvwzFd3KPmtoB3g3lJ0pTcCObzcF8NQLDplpnvYEQRGUjJ/cURmn3HTKPmjU7Tj7EwD/mL8sMJCeAvsFbj96Z4hwh008elN4nYEWhV/w3sBFhqVETU68vNhzRDiiRwVkDedsHC0ISHPeZnOxPwqyNFzQ6a9AyDljFvXSpX5nd/S4c/VY4TBr5xSNeX+M7yuGg+ZVgBVfhZEbARbPLLLL+EQWvW+HSGAFEgjB2gc+3P3eJD018Wtmt/jHZ8XdYf5Agz4qPg8+grlb1CPMR4sx/kqh/bh06g3V6cWhBvfrKEjvzKbFUqP8UzdB/Ol3YMueVGqY9OlRHADQoV9l63ahR2W4mX5NvIs30mrXaAeqlhLLMhLLlumj4uXNgRnRgctAZ4k+Kl4C+ik3jrueOf4g05p2t3z/a1reILNNiQPUJsVUfoBaWoAt/Zp4iT9XEKRW4nqY+i0+YI/nQ4NoUPlJPo1N5rMPVs8bKEWOkFoCQnYtOlYoWsI34XKM3XayooVDte/gEwi45CVs9jrLKkqU/6F91E5pwmZsnN7JjJAANBde3pGpR5wiHi9+UAyHMG+pKt9AtnygvLe/DTABfzBuMx8Z/fjNGJFFygbKGVnUhISyRIwBAFMTEyep2yeWqF0Tx3gjYUDboDOLoq360uwh6wWnmKOjO7PmOgOk/D9zUFGT1x1A+hGsyk6txoL1w3O8YQXFg+seG97ljQCFQeCozGjZDT/VNsIqZLh+40/qbvrgXvxizVZYidysC/xB2fExFRMdkeePZqFdlzi92NCCyMYQuAv67jbcSM3E+4BTayTC4V8u3/guJcJ4AXCu3VljZ61nYGdrtc7GJsTGQZRpZG/NBUpX+DitrYH8Y+PIeDxfCtNUgu6C/tmETvY8+ajxE5pgU3w1Eue1TnB5jmH3HDRfM3N1a7/k5r7OxM31ULubE7g1mOo8OEe+ajznfNCx4eCaH9K2ynJANsrq3RXfnUBr7ODMYa1d3nq6Ng6hTCcrQ2hnw2U6W9no3xzdUNfWwUvPwQY4lkxU7+IfiX5NXARWHRPPsyXEgkWQNTxMTj0F1qNZx1QuHZUM96hDR4uylvFNuJT1ni3Kqf69hQfxT2viFZmz4s4U3SyCBzDjLO4c0R4fXd33EtiFG/+f+wtWTlhxj1oxVx0Tf6IbiQFIDfeoDPfSbdzGVa6Nw2KtfJWRAlC2dBaKm9m/P/5A7/CD+7gWleEPcu1K1r5m0jXXeSNV2v+A2dU/90j/OJiHq2mt/b8la/sxvP5l3sAb8v+S9z2tfQhI1/VCtcPLvTOsxpzBUkrhoT3EK+cMdWuZO7MGS2gF4iby2dPAkGVRKjtwVXoPf2lZ8Ffrh7n2d0mHjCWHjBeKzy3lp70Xl3w+5+pgQsPK/KSI7+O/gfw7deoD+sprsO4GJNpdfD3m3HOzYjQdU+95wFNa6d6c6q37SBtVlUnZKHPiiBqzpRM2wTedkVxOL0VoGEq8fx/ybr0HNobG+T/DZdihtMvY466f3ZBAH4qzifM2v3BkD3LkOe7oig2qnMEq1khpPjoE+dt1SwwcvPFIuF+qF1KMhlZ53FxVkQczMc0PJY6BlceunoBPHlP6qJdfpAWuDDyFTyOWlN5/nlCMNsFUL+HwHD29j57ReGU8TjI2GilMJUUTfH3jPWEw0pDPjCQcUXHyaECSO+roydQIv2pfTDGQOQFumkX//qfCUXQ7O+/9igz/zgEO5x1u++yQGIlFdutyrhSv3Yy4xljupLkmrjlSOqhexWM37f65UF4PK+GVsg2L1G3Mc8//NcvRHdRdS3E1fG10U1iOEM1AO8/KnaHmRZ4OVshCu05J9YNVmsTjk94X3eMQB8weyv478BDm+aGGGWAd4eDuh5R6EG1YmWLsfaA4dAQkFPMJTnlRbhtQf6SWT3VaIMQU7nvpkYtchh/7gR1WLLfvw9L4V9xTNHAj76Cpn7JjCHQkdr3qzIo5YO7Qv9NNLo3HCJCjUCv7tcSH2DQV7mUgyzdhl1TuOwrb4PZHrAvko4J58lW+izo1vxQthxE5hG2sBfJVYzDNPgGvYJBZF4K94oiulYLja8xJeAmCKeBMsOe+NDCWtuF0eg1zirwwCy24p3jnwBZ9NIwD5yyfQjd0lOwWDhSPGhMMyCtXO6MaN+nnnCSckWxkSwelgmAgCWR2/DwBV3fRSkzzRg1ZgHJ5l3YQkhwpHxMNN1+n8DgKKy/0NrW3tVFPvAbmE8+3qPnl7Aogu8keoCElQOVaLhh6uJtZS9oYUhQsV6z6us8EX4/xEvXFuuZvfmvlUBM609Kqb6XyLJkDiDUnbg2s9dEIroC++P2K117UlK8ELtty9oW5aLKxlk6o+gzjnC3H02FEZaivJfFIzjz7P6yXe24DSDOjJwTcdHCs33YPcxDemCFcR21xthRvnddLy2JMHwxJD8EsxJw3SCiCaWjzYU4LKW0FPokf64bGILXnpduBhqH7EXjzLf7IK4AJ58f7wBS07YJEh77c3LwwTr3VFFeHem4ZiHXNjKm2dqrTdWi9bXYesq6w5RFdQ+DEy0DQogHGdTV6w465hZJKWIVcqff7Td+uxP2lq/zaGKxDVwvkYXxwthBJQJsG5boSfGQwkYEZfFSEth4DluyswAhPKWcLcJVzxEs7CMlGsgaoO0IcnbgXtwG5b8Zx2zEuiItxUOF27OVUKg9boJwzDtb3kcZov/auX27bDfvQE2PEC2rxDeCnnldJ7t+0T/oNq3UvoTSgfEfSpngyOYcYllQaLJNUQk3r3roFKUPu10d+o9bIfPVcRZER3p0PbBjiDS8iA2hBVL0A63MMrJ8wJhmUNXLPH7ehkgcIuSqiV4h2OjFP8czC274WsrTwzrzwwVvuUxulJa+Zea+PBKvVaExUbZAciVcMVErWe+1y3243jRahGdZbLgdgc1pZuw3tvhvYEZyVZem7klEBzOyT629lFJILyQUrssdRAxG5kPUyuWfycSfcjOwSSUWUTD7EtcPBGWQs+JU2cFQRFjmTWGmqb6V/38DmomcyA8Zo+atUppDValRReG0IOowzUGInHNe5xaGeZp1/cb8F7oJtT5lDBobJUjRl5ttTLmvXrknyQQqdfEiuQDWVyJoyz6wMFiLtntKGl9UsUR3bXR1+cClQsafCLQXYMq6csDwAzW+ByM5iEUA7kUoTVdELcVwCGoPsE0lFl84+w+2CbbPYl/D/471khHss2BIU+gNPnJe+LupQYTKGzSZ9T8QG4HJ3SDXxZr5x3+EdVYmHCtCt0EhTdiegTziEIqVZmg2GI5ojf15NJok75AT9RUXrr+vo+WJFNZpN6187/P1vu2UCU6TcbSw34otto71ytIVMPtD2wAJT4G0AvLEi539dOSQgXGeK402BSFU3E7Mg1bwStUPpa/WtGCt+wfDyseGwgCOHPFoooIgSyqigihrqaO5o+Gv0pH8xQ3HmBL9wDWYmBRZ7YBaQYZZQFirGdFd/bLBBB7f5SuhHF3rD7iKaer/sXCd6bi9V57pCqtkg0PwS15zTpP/Xh53uZEOSf74EPNOsl0NdkC6gnptWCcrgFSMqadxvxPi0vaaNQKaHEWQ/0XjRFSVY01PJr91+7jWZMMQ0Qq8F45WkTAZ+gGRqUcAorIBw2zQNMD+E++aMzfTgjptQ3ESwC7QbZyTlSvAks5q+3wqS6LsC6sxsGUwreQJ0kvV/aOHuz0W+ta1zhcVMltnswAX1aBlryUxplHde/b9VfMh7BOt4vGjkv3HS6XXwojp3WsGXahpyMjEZUx8CbddNNpTrsksM098IMisB4L3fFgXAF+j946+e/0ZXZa5MRUgIwAJW3Pg/BcCqgzRJ/4cdAfBl7TxX9J0inGb5Cxj7p6s+yVU8Sxy1HZqJhlqok+Yo14TGKKcDqO70ovf1NVfqmi91PJOVrqWP2+tpvrPteVV87I+VL9EEy6pS8xMOB4HoaM7ACLAxZHO4RGA8blWJ8nKMmB2V0ocpqW7QWYOZ7D+JKlFzOcoX1kElsqpcXGuTUN7p6/+Y1xPrlZiR4morkeaSclGOFsd++qOXxYzl1B6eFe58Oltc5e+IT9CoTVQzSczYIjC04jc8RVsb8i7Q6rZqJ4hoN0hJgFZArskxuSVHtBu0S7Q79k7pzzmlQFdLpIzcToRA93ckLeCQ8oHQjByMh+dd6QADaxVwMQCmoZCNaYTqaRoj721xdhon6yvw5o871Tn+ARuXrjy7cezQkTu2WtVquom2IZeWKM7szzriwi7KPRjOwrOl6hbxfiaZvvGQ9B6K9aUdgrti24TU+di9cyON3naGdndX67WTWpiAb4EkdeEWaHudJm3evU2Wu1eZmJx3vnOlVVWHj0w1o65s632U9I3DYJdZWF2skW+D37gRfQZMmuOq4ucnVWNAvgGJsacFAA==) - format('woff2'); - unicode-range: U+0370-03FF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAA9MAA4AAAAAIFwAAA72AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGjQbhlocNgZgAIEAEQwKqiylBguCFgABNgIkA4QoBCAFgzIHIBupGwPuMGwckGFhtxH8MyEbMsSab4QwqaKI5gOnPv8mF8P+xTyVHcbb5D/Pr61z3/vv/5mhhlDCwrGwajAac1aMRiyiyobexbESjDUKI3sjjYx5BK2t2ePAUgRLEzGL1RLeoK0rV4zZVi3+ry715RzSN4Z5LeAENJW/pADAeO6pPAXXIk0EK+HU9yQrhHO3WHh6KWVg8D9jA9WohGXbCoM7tWba29vd/w3NdFO4SQp4swVUtYCSXZW4bO9CmyvwPVOoRPmU2BEI06lQAOwA2FeRUxWmuta9rNAVztY3f+o9z3bjghCqcYziKvP++18RCOMIAID6GM6NG1KdJ+KjGCEMYA+wRwACGNTXjDKMA0eg4ZyVHIuGe3JYDBqeQanxaIiONTkeRsSRGwAgAAMwLswgJQhAvlMADuGVJoNJ46glGwMyQV1AhbxPLkTy2TzyO1ks38vPd7gsX8loF2C+ceEXpSYjgEM+TC9P5ca9mxs+jXhj+ZSyjsh75ZP8W0bLY/K5rMDKBXHQWGttteero8666q4nP330Qzz+lxI9H00BzVOvipYCCIG9tjJetNaSaXdptIeM5J5mKNLrKoqgRAUk6gB6Gr38ypFXqP7J9hGOVBi0qXP9g6Kn/QSkuhQMARQuV1B7CKWFj15+5agABDGyDM+gALgu7vqH1JGNJww3hLWhCZq2MIF9NinPzvM0ek+AKKItQM18cf7aEoB9Sd6r2K88oH7T4H6gYN4bVdggvCoM3ugBAKUXVfDmjVdy384NRx6K2LtfnRGnBidnakxRYbiSqmq/qf2u9hfvjVICxMhIPhRJFbS1dkXtt7Xf89ckGwGS207Z0m1Rd6x3ut4pv3WzeZpJtg/c7JRksZRw8gBUQkDXAnQF9oG4ALEAr+8GiByGrodRZLAADQlRAP1kf/Y/2BR+m3T8q7DMdC891TRLIR2yU03L9zI8M9828/1cN78g1c50LRNycoybnGGbtr+ITM/1HeEGorc/ZaDR7Y8MpEM4tZaAs6Tfbn6Jc9ETPs5jbCJgKJzMycK5Oa6p2sgV09MoBcW5kHwLKkYTVIhArjO048UCAklfXmzADhpJS9we8rgvSD24d8ulNFGvAeX3ivapQNRax5MqrMX7W3LalT7I2bjEbLXoOT6BtkBA+K+L2MNy2n4ib/ic2BaecszW4hlEZ4O2bQ4ZD2vb8u8VJX74o9Zf1kd/KmOqPPQtbFqhFMrpwFv4FrnW6fxy+KmtahmNVLVA4+3CXecQEJCeATtA0Q/Gd1QsFAdhdxJBdPlihB81yFPvwAEhuF96qV7zNMyuNYfpVmWiL2ghWOL0AxkH1cQSt6TEOB2n14XjZg8MtC9YAvWiz4vGv32IkIcEaxwy9Yx45eGEMYoh5vWAkLL4CJUwoctxs2T8wx9/KiQyrel7taNS8zjfpcsfMTPfsYIyrxyYWSIc7u4ksbmo4u1AiSg7YkgEreULCR3QSuohSyxMW4J7NqXMko1hfvqi8EPFt7A/mFDvq3/y/YPfK7Wfm0GyUsR36eJ2lCojRctCDXLfJxwPt+9a8L6j2hUtaCHlQdomVmYQ5fQyWU6opRNrXFf/y8JqoeabIV59i3Y1GiLZv3I4/T/E1h5EI02jkaaosevfmdLnpw1bKl8t+k9efX7j7/YAo+vW8UP+H5+aft9xv7+6Vu/vvcPWw2i66apXm2DpUwnh5dhH7XbSub3Hrqb1smdTd6M6apTCphC7941b++HhAduWOKzy0EWJ2NZ70yeNZXn8+LzM1vqH+t0zrs3gm5TbDqb3GPahyjD8Ut3HFten/G/+XepLDQzDL380DL/iXJK2JJsX8B2LPMoNKb8hWR7YWtun3pqxhs8T67umlAo8h3PqHs5Bg9Bru/5oYcOcPTXzcxfzMtpbJQq1De4nni8ihwGjhrrGZLOfKHmIvd9zUkOmzL8xPI2q+KmLxpXDvmoBTdzp5mYLTel/rv7FRBSsCDWM1npZBsKvluuvpfpL0/PYaj4uPaLpS+Nu/OaUkFe0ns+nnffVQ83HPu6n5oy1BlARDykacrVFbgEv5Gs+4YtrGbtcGPzMbpaP8+ql6pPCInaen2/g8cwhYr1uatayaFqoTC3OyPOb9H80vVt5QIx3Oop2cYGGvgFDYf/C7mSnF+fdfPv5H7MOtJg7WgZYp/n3R39v4/KF/NXPVl5C58rHfXFY6LRxsfa6bDYvprO/jP9sP+9ZihIZOjmAZbHVx9zWiqCpYdZJfAEfvbDdOIdMbTg2RWdP38sjqSSk03a7zNQDL9IOtzPpc5KVpWLSDN0Mwwu7nZ1uYs/44f+qPm4f8uU/bGhvZ9cDq0ayhL4NLB0S7EY0+ogao1Crc4vLGLzz7HqHEWd/c0qYXLiOB2N+5IhTPKORNtq1skx/eVouW8XHp7V5+6HW+neeP7/w+HlDtx1RwwxRAVOGUxEPLR5ytUVOIU9jy/fB6cwbOvRz/YXdmJr9UatQ87oNXugcM2pD0f88nU6O7jV4qGPoFJeZu+oMdejrFq6EKvldglfWTx29OtvJz0MXpd85/Uo+36jcdza9L9ciRWy7A+mTxrDV6h3Z6C2G1HFesVS8LplDQbSlf9eB4T5eOQ4/VTqUJ6+La+jYj/Wlvlr/+o7t2/6n3BC32rnff5LMIoMnj+FZbO0x93VqEMsNnhtEPsQ1xz02akMwvEFVo5tRhvQityWb4PL7b3cu2sUE1n3U1/kVn8v+zQu/Z5x1H3uKU5flStvlWd9wlNtcx82r1q2207dtfdPtooDULtWcNGWZmPCXULtkqP3QQOdsdHz/0nkvS128adFRTs2ci2A+9Ug/c9+iAj6Dli+cuhVKaabfT/4H0WXeE7v0qaUTPC5Fd2lzdBDzCp2r6ZOmzZ9Ir+eNcZ06hNUIg2n1Qwfr/QmG4iXR3GjMSbKrxipY7opa+j4w44PZ0t8aNNjPt+OA3pXWgX3Q+m5haa31pfBds02L2JlRykrYigwKWU88fgrlk1dyi4sr/Y/EwdTgzrJXX/ZNK9tW9tBsXf8IUr8BnWb+c2Aq88vzoM+XZZmBJZWGM+i0+tHaWRVnK66iw+fda1MMuS4B+uD4gcLqGJXOpg5DPxZd6FGGTnMfrZlbdrLshuV5+YObOr8RYzvXi+vSwdlUp1eAu77fsIAudZO7asYZNXrDd02VwgZ91hjzP90vHcepQ+UwP9imi65KKaTpVJlGYWuIx+TRrNHt/r7ioU97M0qUl0zgs+wn9eN/umSycfPdS+FbrUqL3pZRQjOpIpvC1hKPy6WZ5JV00Kgfvu16H/Ip8k9eWXt4mJdu8PjovtVjn/RpmLy99jD0SSzdU2v97risYuxWd6Z1q37EMKjW2Ytmv43Hl5f+73/MitPK1/r/eS5QE3Wz5q/K53th2XwTrCEUABqIWpGZRPYeFAFQbctyGnXD1ahZfkU6D16RL3CW1AljKQm9INuQqbFwATVTAJWoVx6B94x6pS60T+ZENerCnBIHVU14RnWjKpLfc8cy3lJTJVs+soLn5KqU3jdZxTMSTavf1QNrBC+8JbPefTSEl0W12qgmtYqqaKnfXN+xzwh6plnpqWCDvKlL/shUlQ2/BrUSja5WyqcpSLoOBuyYnw5ImFP+Jz/mlFFQVcZZ6hZVwT0psYQd5KOkZs9Zxn5qo+S2H1nBTvJSSvObrGIH2btrs6uG/Vvsp66D6Fil7ThIdfB5qFo5t0gpaev5RKimE0l7w2BqpsCPphF0prSZ2h0Im2EjjEaagxgyyj2Q5iA9Msr9kOYgjoxyT6Q5iCGj3ANpDtIH9OpYpZ9qWL2tZSq1he5RS2MBydCGYoY2uJkTDagjc0oWVJXJSO2iKjiUkuqV2wAnaZr8hHX0IoCdocnUdRWKtdgZJpgeg1AH6oU96Uj5HHusnCxRDDb9eoH+2DM7Vb6F7qk7+SFP28QX2EO81o49YQzW09UwRlzgEZrMQXqH8h92kTsavh3jDPnqXRvVJwiH69m2Dv3PeiVorDIOkyGmyA/xKCBXA8oWrRZM8jF/Lx6hPcAtWhu4AUyKlwiUD0VLrSks8rHSWnxAJSD8NbPcZeujuKj4V9vmKltEFUy2hfw/ZUhb+YBG29V8r+qhbSsViWquDG5xv1WzvGKqdrOl8pe6Hv6e81yt6OPQfLd8olIb8DK9d+i6Nb2r6aB77lf1TltYi499ska2Jcp+UYXONqvClKGOAEQ7TuRTl5oP27gN4oNX3Nb2looANVdm7qoTWXD31x60VI6p6/F/kYq+Tq1bLyphBtj1k5sAVqhOltK2gPmIKnlf3hHTi78Qc1BRV5xFR1u50kgZRhP5iGgHiHxsV/O9akttW6mIU3M93iKy0HiBdjP3d3U98O+Rij5OzbdAJSz8V6M21NrCLB8KocLjvTgf+RDxgdisRG1BbEV2ZV2MaCmqYEGp0lrpdF+hA0abrM1aLz86Ikg8R2dcahLyJeIOsRURlRGb9RqUuai0VQp/USV32ewVF6XTfYsPmPlATV8r8UG+ti3CUwUIAKvncistaMtEpy4fdJ46AMDJ184tAOB3Gvb6a88fv+szdSlgUJgAAARosTZ7QO8rstmC94DYgUk3JXw+QvFF0xdAtJOrlTg0Yp3RXoQjRngiUDmFSl4is1gJzitdYVJi0Flph85MIChp6KiMhYVfk7uYFWeVa+jM3GASUQhU8mEWMxCo/AELv06Mx8DGT+Im8OMP4HsF/xVzeDkp/CP+K4Er+Ev8yWkAoloRSTtJqc3dFSZvcoMb78318f5+2W8557bwsVeI0/XzMRKkZEKu28vtW75zw9plg2FTAMa1WBYEbK0fL6ZYvkeAEuWqG0UgAOAIDOugIoBOOI6yHsAEoFTiZYLK2MtUOR8z+1RUoaFNQMXXb9XRCJ/5SZAoS7IoESKl8tZGK62Ltt76SdB4Gius0wHihWgR6smA2HHDqkUKaYVJKa1k6dkK1YKxEgQ7kJrtzZ+Nj5ImzoBkBYkl1zZEvKp3FqN6WCmiIOL1ghbRtnx1Vr+qb9O1a96ba49PlaiTlgXMCLUQNU4UZIVp4axkEdArs8PEDxlKQfZAA/7rSR5kuD6aK/pOrXCQ70FGCzUBAA==) - format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+1EA0-1EF9, U+20AB; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAACJEAA4AAAAARTQAACHrAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGkAbjgwcgTAGYACDFBEMCuQQ1CoLg3oAATYCJAOHcAQgBYMyByAbYTpFB2LYOAAQ8m8bRbBxQATaNIqSwUgH/5cJ3BwwO1YiloiAQlXt2uraW609q+MVEUfLxD9oI//kf3GY/Ix2rMRHhFjiGgI7QmOf5MJ/tbf9mQ6zKUo02CQc2SgUhdXrBMKCTQrFD/pt35/n5/bnvrdIWNFhgFQqkSNqgKAgSGUpUooIRmMmYGM2oWIw/UpY3xFEa1WRNZVVK+/RATsCUm+ZHZFQQPIdu7dICskhTKdF7AoTVu0FXk/4jzYzb5dIAyG2l/oA9bnj9ktvzjPZMS3y2P+wtYvmjoNFcwBUkTQyhGBwXull9AEGgM//XG/2ZaAnUwTHIFTrKmVyMy//vcCHoRMofKTML2GmyA5dT22FAWbJilDx7iq1Rq9RqywfDyikXftae7PZ7TcBntDWqmS2MjXCRaOkSUWo2Ag5H3BCQJ7wSF1OASpD9irSHAknzjh3Nk3N4axFgWKM8u/wnW/aJ+06HIwImitSkxkhPKf310yladsxhdi+kH6/EjQYMQDAOQyRKTOIBRuIHWdIpE5Itz8gCAaYA+YQoAGm1C1HOPZ4dwFonp+XngiaF6dHJYDmFeGZyaAJXX5hejKwIGJ4AGgAAxgObTCIJm4LEAB9NTaS3w9sxQAC8DfSCi83P4CKnTSl6cxI6nM+aq8ePc/3UdNAdzVX81Kft/VVtYrX51jUM8vgf3hee98kCc1mor52Ar1f/T2oS86+dvF+zMJmzs1WT58ULd9rIqF3bVu1nmqtC5oiWRz8meJ1SV+0FTZOXdFko/jGrgDt1DTneuGD1Wq1DgCsseqoRp/afFXad//W3KhrqffZ2CzM+i7CgbtMeZJ6yTdMBusi3cXFn/qOC1SlGRlWxFKDTBP7NKtHesM3LflHGhJnseIlSiZE9GRKfOLOf84PZ/7/4hGHEoKEsBEpWqw48RIkSpIsRao06TJkypINk5ObX1BYVFxSWlZe0djU3Nq+obO7d3P/wOD2HTt37d6zd9/+AweHDx05duIyQIQJZVxIWV6UVd2007Id5/283//f9x9z84UGsXEcAk+2dexDQ6K24tidRYBEPg0ZcTonJnCmN23Zg1AECK4D6/qpPW/MxNnxGYonhhmF3SGijlQ1jiGJUTaDfPIorBWXnjzsyNwWgxoBJ+vPSE3a6HZSOAzhGF69xIBHA+1PELtZTXfEozC4yVyNoqMjIUePicwAujCAwS4T2BVXR3ihTJjB6HVbsBP366ed4a7M5nTbAGVmZ3t5WLSRYEyQhzXT1YFEgKAB0Y+L48FgJBH85Be/+QOCOeschDA2MBgOjfeymIMI8uE0BG07Lvb3RW/SatL5AE40m7pND2d4OQMKUNmCBP+Al9nTQBl6AkAcnMOUKcP3Be66h0OdEKL0+bhng4gU4ogdGqEVemEabuET6yImiqMkWqI9BmI4vjURJtdMW9C2oXiEYtWJH4q/lJWVh0p7SntLh0qnS+eGuSIRaNCm4IRmaIdBmIV7CCIsYu1abY2DbX6b9JAUD1csPfFdca7NYGlH61OlsydQlwGKBRStKEBhCs3uSF2sQ3WwttXG+gOgVv//fgsnD4wRX4sTw9sr4OPp3u1jd7etG+jcQYDbJxeuEXwOA3n45Mxa5XxMiPombbZFv60GbDNoiCWrof3tbW2liy4ZNeaKq6LFiBXnjbcmTDrvgstGLCKAYCiwEhEHwABA+xvgACYPgM2jBRg9A+JBMDxo/2aaLAqbD2NqnoUMegodn/hb+hj5fsxaphNXx0llYYQKBZxi/kpAS1LA53dZ4XvliAjkIccTWucnFeWrwq107oPTt+6NGLjIoZeZDk0PNTVc+zY0j3mwwKKAh3xh/jPtxNEGwBod9ibyMbarx92mmshENYyAqqu+diDPL3RGnu8WCzws2ynOFLkGROrgMZyWXG2dksfHdg6P7Q44zHhmbsd8Es4NzQccRB7LppjzJ9g80nme63wweKhsTwkp1xC2a6xV92PJ1c79nrm97j3Bmeo8hNPBSTmIQtrFu0lKVjIRTylzz3IoOGWt0n3BSOZkiD2Ee0Va5JFJmEpfuiyz0h1AGWUdtinaJpSOaX+j6dU9TSy5yX4m4pTntRJiey+e1bLmMv+iR/Z4Ke92ybClZKF3HXsG2PYScTBL9Qxd3ufNDcRJY2GNnfYdcy5Y25L28MIUQYWbCALjdrDYy1DlYS9n5YqhGDgEbDBrCCrQutjteT9LRNry6yHtAQfYS4u7sJtFWYZbRo3XBg+lwkcn7g0KYccU0ZVTh2rWXYJuV4vVtRQQiVEUdgviLd2CbuoGQ65KS0xAslhfG1UFxrNRVcVbUY8oEJDqJjKtPKoe/ejESK0koArfWsNSg2W4Mmxv4sQxuolIo9ao7qDsKspvuef/sIU3zTO/5pwZo3/X+Ex2wLGA286niRQytzHrEa0TED6mFzjkBJJ+fqNBg5Rw17AvKAmwKuDPRZ7MYzyR1nl23T14qa2muu3cNiVzX7mmRrbTcRxJEsnbh62CC2RE8aQCMl6uxaVQJu8fLwXIzeP5l3oTM6IlLxtF0/N+lrN2LpBYS/JzGmwH2E3cSd56y1Xv2c//eGkcIGS/IXDyN1syhuBwXT8H3hV7kdcx+Jjf8tPFw0MaOfAPgiJHkmV09b05o5ibletOZ/++WGi2iz9OQT2/ol53N9vpANoYumK5Os8vpopT54ABo8O4Wl8EocBUfuXU/NfPzWlm+frpmc/SHelYsA03JgDam4CEJJldGX4TGYslJaKjjaJaMgp5YRYiACA2LTghRpLMHIRBlIS0KyUglT+a4hacIm3hN7PY5So35EAoVxEBWMTt6zdFn59vG8oW8wd6JD/FpsOlRDvfrq0da+sQHDPKWhaZRfISOYeADZja/HfRJpooCmMncJDdip0sci/1vERKkcFQRZrANoYGi7qPgjl9ptKZ4jK5gY5Tsj5GzCG7KLIv/6CJmoSFh9n2qPQpw00MoQPQfjFNG3vmuLVc0JroyLRkoNAQ5SHF0OcPKSN7a5TfaqEjK2u6RJQIC+9bq6MrfvSfZaoX4b3y7M2XldEVjqtzDEWfv/89htd21Wf23LgDy4Yo8wXImPj2d1/X/8X3Pj5t/9PCBTd6XZ/HuftkiLJVEV2hJ+nHMvLZO2ZomXZBOYwSJJphPOxcZTFaPnkcvOKEjpEoe1osrPAr8oovW69SkVqs4uzUBc09HdRO19NTH9ODoYlFU0y5nUU0+Ent24lIOZ+AoHnZlyBs8MUiVsBnNAeCF3RMxODxWu9tpjKpWogic0/PA78tBYKMqx2rZLHfP4bxpt4T08WAwqX6z7o2WTlZdywsgYQxNFvw5qA6WICf6xp2M6SShjHg4HmxbNDonJa4AcCcconEXUUiUhNZkwye4iDkstfT6hSm1c599zU18qeqGw6cluLK7DHiuXhix8wjoiuFUjXhUCy+9VxOx5SGOE5mXY1RFd1iudfsdcuPfhYOKxOL62TqM+swMCYV0U2+jiTr/kucTgxJRn+qF3vYS14L2Z5lCVOSs0hayd79WCbg7w4+rLDsfqFskbWjiHar8o9loTRD2WIHl5UI3AVW+vj5Ns0OvUeXLkSg5TPg/uFm6PYf0FztUSAOj+JRa4FIZpc7Zn+l50wN4CikFoXgYHrPT2W/L01fY/g1e/vwz/8Uu9YHAX/ghfqUl9g3vB67W5T1jbSJmGZfe9FUevNe7Cn+l0KemSf05tZnY9sIL35ozHArKVHk6OVH00IDMUma53LQEh8broPjpKNZKyUv0DwVrt0ysd97GRuapkfKtsEVwm/1lzKbSKmU1s7BKhysDeodPC7sUL2+uX1/m9Ru9ju2OYIVJ84sPnbRIZX3WSN/2Bxc4ZxXjFr8EdQCL4pLv1N6SDmrMoaUs3z6k8fx5/jCD/EXQpCASdJuwvOfWp8ka1EA8XDzeC06gKcGG8urq1yQgvqFlOrs+34WxR8NL8aFZMeGLMKyBTV/AUyOHTeBNvW/4gP5xbv4TfzxR+qVeWBOX8Aj8OYqXh4YpF897n7GwAll9nVtmf/fqqZVpkOJBzbXy9Wu5/59gaDxbpgpCNbIDHYQHxteEHwpDdWodD/MnEsK7va+725yqPsqn8mlC7j2ZO1hlKJHSi1AALcJe1yWs0DuIxVaeHRyYgP2NU3iT3BQoS8QC8xs6hnRQYd6mYPSlDhiov7J7LBgrAi/vDFXn/qeerziXgW+j/CWqToHG/Ukw/U8/DfnBsz+mWLdoDVuv73R4nGQGGn/HyEq21ctliGWmpSbgpMBjC4VS7QcdvRWmPA894TSTC7oOvsrqhGrwR6kplzDS+eBlJZelIFloq1pzDBu8TkXvuy0z7GXtE5qftPx3xGdqBlmsgruEioXgFxQV1WKctDWOPCanj7J3DC9wByaPqZ2cz34zg/T/MZVZvjcT/gz/K+INq5B87u9QPO7w67P6s3Hq/Ej3dIttIyH4HYoXtrB6Y/q9uEvJIG6XKW6kKQx/BUn2Mpl2t6BdNGZpxW11bYH036uU+dmNBDB/PoXtesKigfNHhrdVrsJCnvhx/kClfMFoBF579hj3X/QcUK+qrAHb0Qnh4k15D1SI1+6EdM1wIebkI+5oXRvhv0XRIoo6Xzgl4WG8bFbrG2+v8lBS6XQ6/18VOJyXf1WKlT3R9ICyXZ8d/iwT4DKo9m+b4AWX3nwTngqVo9GGoIWxDapsvo2/Ptc14IfxO+9Pfo6JDjLH6/H+38QX5EYYK/A3dFAHS8vwobwtdkxy4Ss4/BQPKWodjfeiY5Ok87pBM84kwqC24JQLR5R631Xt7Aar8G3L8IvbiN2u2b9Z3qrNnuoj/Sxpha7gd/QkP7MjNlNKc3bHI+6CKV1OUX2Ya/i0Y9tZ4gh4hfBKGkNzSnIBxwVOAO1xDv1VegQHlysnvwE6EbyCg+0fz8kpqGbEdY+Rc2h5V14Br6jWq6Q5VaYuwXfhI5PUM4v+27tK4vi1hQIsGpCZJnglWF2JZ6DDV6Q3gcyGSPVTXvxbrThEedsxonZrNN8dUZeOVaBYiooGaRZ1g4QAmOWPmoxe4Nn6uxxqc2db2LOd20r83ABeSMLRma3xM4zhzvRf04s7oXnmiUyGxgbNsrzLJz5h9rcXcxUdmDl6gTnx6uyLQLM7nOWWhHr6x/otuLNuGUCAoYNjxy/5iC7wZKXXlV3Co9C1UFSrht3X8I34113OWcyz85mnXczEs+swNpxwZBGwV1h1hm+TXLPrRKtzqV0sGfpRy1ANtNSqrh+4zF8E9Z2n3M283SanQvvjJFdilWjqGpKBr57uFyUWVu68K9NbXg9ut6y9hezS3xvD/lbYzteh641h/xkbPycQYiNLA7C8rChS7ydxPDSqLYwfBMe2GW0lplL9gMd+7XPVvTiayrLpo1/vN6CVH5yeyumsgU6l7HWq7o7jQeSjhDa/p0/hPaip+dQ9ydAfH8BH3mlejQzg+Wc7BXGAkgnCdGFXfe8s7BhNHMdbZ4GFBARFACrM11A1dhWh3RK8cjpqBBtLtHGFdOYET/nynMrQPlDjJrIuP1KR/bpkGBffH75STwW1UdYHKbnZp6ZzTpvpEotSCf0EcMqKBW0g3wMXsNKto/2jFBhyGIkdCpkapRkZPFW+5X/qyNwIsTvBUmbN18l6puPA5t7ZtAfS3HS4Jul0AVaC2B6SVPlkr/CnpobuOqIqfwQ8MbGTRzt9A0dHWzN7O3D7J1zco2d7FQsXW/uD0I7OzB/x9gss7kP5AJAwVL3NoziS1+tFIihxEPZO4iosZYoHtTgw8haXgsJqRCzzO/NrJ+2XdTwTdXRdJNNEqqjDMvrlfyymGhBHgTwevF8l6zOo3Dpa8JBNIF5cugXi4yun0Pn8JL1Kc1HRn6Y5jJLWLtde66ZyvVsUcEEXF+tB6usPUoJ2wkTIu0fmQ13xAmORCfNB0sn1qGDhElJtV+sXHDays0442vktnfwL96Njhwgt1O3Eg69P48Yrv76rMxsLABl+zFcvnBI4fldz33z0WNCUElPzUn8EvEKU+YRr3Ezsya7Lx0JUKeRq6b5Thuz+9ZGW0+m10Vp3dsF8VhrCN2z2cPZ7P6HdVhbtU71ce9Ec2Yj2CuJZYXc9/Do7XuNh6BQ1bCWHmi7l1JBuixD9uVu6UE/6juQPwpWjOzogba7WWXkK8sT3haIWXVE+9pGQGep1zfxcrpcS2hRWy6255zCAbofeB29tpspuPZQPKW4Zhe+HjpjBWN4jhY5kDvQSL1dVogN4iFZBt/nFXb/kGmalW7as/JInC8tLqjED9XikXXed3ULavAsbMsp8J87UCg/UEA3YmynfME4yVy5gdzlaFEHZS9HC9a+odnKp7JB/O/ACzf2ZvD3ftEe7i/8gy6tB01+Sjsoy4G8X+JXR7keoVMQsVz1el5KWaWGbE+lZlrbIsirlXQZyvVuMiqZEKbVN+jK9dbpFj+dhcCqYZbEjNSxxzeHkKUbV3UsZEmZykiMXKUSPVNpg80Xyh1VxF9XiiArsJTcVHXgNL4V2/hOYiTrjdTRO2PbkA3Yc1RHm7XKFE9n3XeXJjXUE8rxyDjKAxUhfdQCFBkb+iWHn13fjYbDJZedOHPJO2a92GrGUA+4cO/jhE8yD/QJfvQgiWaLb0gsmOrLrt7dWY8NYnddFK5V+Smdw2gHs62kR8RiFG7dsF+yv+9xK/bsht3dM+FMD6qdeEJrNizlVo9Q7W9x9l8dG0B26D+lc0n6ufK7qBkPBuSPbKVH8g49ubob2URLLDmdoDUkO0rzGQFnbjP2oDR/gbyVVLTSq4udELCn9hWejUYD7bx8xCJLOJXHlHyYTrxoQiShymr9NvXMwKF8cXtpShz1aPmdKnwvYZqtOtdCjiUmGp3JDluNDZEmRFr/wVuJ3d9H/FbfgcLRARdr92ht2QKm2wCzJX1XkqaYM+aEnMgu6mLGhi8JD4hvjKSmP6ZjseuLV+N52M5LUrtI4Vjh+g3heB62/bL0XrI3+GkMa72Oo2XX8nr3AefRw4lb9IQ1Kh+c2F/xDdiLougpVuvm36kuc3MhORxofY8BvA1i+wd3DdGphvqveeNKyOyXVJBF2EwM/U1Rsd6H4bOGnQ8KoxYMo1ypozdHB60dWYoXvZaWKF9iqCeDusBzHJ9cKvEultfZ/WeqvBwbJV6lyzyUaG6ll8dtjcU6Cb2hNv121jdtIWNwJzGatovhsppsJ/AE8zkh+ySW2bOv+yKOlrNrQV0jZlfXXZxlyG2f4bFGcDAZ+0CtPNVdjVegLV2lB4HQkGvv5nEWWBr+Zk5OSbirg4m5k324D98BxLf7BlcWh/jmZQqCKgpDArMy4v0C9W2XGbg4hwSLLzNwdQE1TFjuT/J3Sd96hd7isFSAAmMTkR92mJwFVhs/0rNLG0Klx+OtDC56YrKRG8jUtLLOdejbxtXcUm9MLgp050W/z+vc99f5QdcZA/acR1y0m2tYuAM/NsqFHxES5riSr6Di6+1+95taFagOvWe2TYfS6nrjcRarII0ugW3FCvsVqI5gAvMmfJe2cC97U3NXh4E2d0ewO5KeSBlMF1KOpMcpXY2xyBJaZCWBnv5DpURuaXDoTkzt+l+1aw4QoaY4vGknyLT2snO7pFs6OP1SY7y5K8Qj+I2n5GNCoIzuxoNQUSUzlt1vItOix8rVgdUPxu7L9d+T7cx685/9+mTWiy3MbFxnt96Ce/P/JHz0ya98XiVCdeN+ut/7O4W2nW0ryjkekz8ftss6QkRH9anojW9izRnWOT7PFfKHltsYtY9UXFlCaw+EyM6Jjw2nQwF2fk3MTjw5F3RIszqkU25lfmXoOma7V3UNbS2nqZ/cA7DKYemtkqo/rVVlcv1brQYuyfW/feI8R3POuez8nen8Vr7/AjYwINdfSqn6Rqq6V1z1Uu9qkvFAv+JAbLmhPdiQPdC2s2Nwh0tW0idsT1iA4QbzQULnTd6IwSqhka0bj5pTTvBB1MHszfaHlcmzKH40u5Zjhq4izZHM48LUIdkR2sNxHM7Lh8gvUo4oHZHv34d4bieQfP9hXcofOPqxQb3go3z/MMqdOocp9I+DdzkqPu4+UmvAddMjf5jEZ7JgKdYxMgk0WZQNYO/w65GsPx58F7yONZns/LLnDjdKXpzTvEaqaQbdjNzHQd7HHjI3XCLIwuqbveCQLiK7yd4f5avvP4gyUDkvPGDaX/3uVIBEkST3LGPjRT3342qtYiZIsugTSdb/Tdai/YRXJMXPZHcwHIzt0zr9i3WGksxMkD8wqzxOjiWUuh/31crtFOZtWgxzDNJ4Oat6w1B6WdAz7UNL787C8/em2u8XtN5fVbtxhRN/VfXG1YKrC/AeFlnX2U/NF+eNgBNvjhlLoqqD1axiZlJ6ZTxuBBAlUU46ne51XaJ4FZ+VReCeCUZRPL/XMldvvNpAKMGbTtIaLLnHiV6jUWIe6bpdfbT4lVeOyN934PkLfAkyXQng2pXvGVrJyxHzHWX4q42C/mRNg8LuBtCU3DgH4he3Q/c7r6R4D/fwGAePhJiuyPAwJ8zbRr3Tz1BPUTMC5AJ0SgO8CyWyJPJus7IVH4NjasMJhd3Hk/Kudre8peGVx6WHd/4k8Pe/huVHr07r46fT58B0uHpBYfd56WahXPMkWE5xrlMqOAuUDs6469wy1Lq8khZ2Utm6G5Bocm+52BmgpSN7p2XkuOzQeaAhPFfcarmh+5BmN3o233Ak1tjmVoDx8eG8M/zoX9l4NNZsyQVW7B7AWQ7y9YaN67zvDvw2i7DjgpxGfUh0I/t8/MUocZ3guPRNOdb4ldMLrgVeMvX5aVyp/kbJwXPzG0zzvKiBe/9bAq2cW8j3Kta9ZjVcwd5l7S/2gcPR7KAz8O8CaAIHAMiwhOANgJkgiPWoEsmT3DK8FH3QSD34jSy2SaDnS3gK+EgPmYTJh1oAEIU++oncmPxVFfJcYC5OwhUFDtzQIyQIYxn+AZVfdkX04lxXozSJq6AXWUNKASKMcIHw15JXUXwZ2eaDomtJ5B74iRh7/DSQbqgXORlxmgdU0l3hXq4r31JXh/9I6cpK1vlohccvBOmG7iOB4WkloPJ2GNrwr1EjIpARFIM27oI41aSV2QdfFAK68BSVxUpmPm2i36T0RAVhq/REevpf8UWHwjrgi6LrV6h27vF+a4uUVpGG34HSI278wokoGM0SQGVctRG9J0Z/tEcm7UR+aes1mCIs1i2vSM0nXK5BbFxffLlVx3RCtGlUWGgsfeNh9QARqHa971XZQvtf5RZr1w+Fm+/Hp8Ea12+Ky5LmcggAgrBoXbrCyPY7hmnX0C//vHO9GPTcpv8P9phesLsqn5Z7BmPDmWmhKsy6VzSXerkFTql+7IK2ru+oDAvNpc80CuNpTuV5zpC2+5rlGmOUliyHPmDPxcXXOpfdnqRBtAIjTtvVIqmwWLm0yzDf6j5TD57QEvdYyyvmOstGtjRZYRVhZRAlcGngETDGGde7lfvtcBZBQnj6GqbOso3O8zykMA7l+UjL3HOZBJTYMtSHP5V7FES8dPeekXEP0WwZ7kGy1CUu2OViCoOVajVOkc6VrRWlK3y10g6F9VZXnFYCGuUWnbFKufkLddrVrfK5znXvJ2vYBfxT2JGx3xIga8RcOUrJZDkM69+qdNmmXSobCWHo+m1E128kb0XMG/GqWTN02VDNlb0VTuOutWqIpMWR186TRl7rAkF4Rwo8LcfLdiMvE/j2IawwlpMsKtAon/4yrKRPN0cyQcJV0ineOcBR2H0mPF41u6CQUVBJKUrZdnjpVVxlukcklXrYackarovGFJ/9S1KjgUGiI5Tzrh7/M636OOblcA0B8fE8RLVmwmAUyqXPjulSKvFAyVNTYYfP5QdR8ovJJLsxq4/+owPgXi4ciJYX5AS8H/OtE0ELxJfTjmV9yEcD2/EXxufqT4ERDxRMdfaBKbIJ2K2QSERIwBdTcrrX4nJG2A0EMijID2y5NpkQ1z+a5rXY2Gt7UXnvXIkJ/J9RKGPgJ08DPGBFFKLL3uMz1TY/5M4220z14/sg31ZzBZp2Dld2+RiV+JSxP/i5U5Fxfeh9fVBanAJnOI4j9adpif97tKv5htbikGmx42UvKwj8AXAG/MVpQgn4YbOta4njIwPUtsIxqTZf5CHjhvYBYM38wHpa3zNNYrEriWuRHBuQuTj+O3yDlnynMiQT+L8dh4Sdqoxp5jUTWnkANZsKwQ9tcqaxeyxFPuzow2mCBfyeAfVGCE+FvlFfu58uaFl+1yCCOuXFmVwX+foYeFQOmHb0WwOJi7WYV3tbjPDR7t10/avx+itFwHIfAaSEvvXfVM1hlvH8diBtqeli03SxFoFMp2pZs35tVFhT73PFXIZfM6Gf82g2pkMHmk2F8IfQxiZjXRuvaXx8p1MEJ8Do4GkqB+TfHcGAZKdhkDpWjsE5PC56B8QP06Q+AP5Lh11Qqt23ORG0vB0/DqKoBhjdMu2I10xPHQgkaiC7ZqmllROG+W/5sMniAEJ4MsfrMU3q0yF+Lf/kVDHo7/go9kt6Ew1VYhyYiOqS6i+7d15cBiI5TBjJbmEXPmNWyaFl5TmvueURLkOVI0A8OVaSJbANrq7SWtbEaZ/uF5/ACD4QwHba3Oey6SF1qz8oMhsAwOvPbF0AeAvfn38fdXw0yd3IgKHCANDA6IqFATA5IBSp9ZsAel4ywOCdIh1H+wfIfWso5USlPK2etBCP40hfCdlEq1ky7kHwLvSJde54hEg2VkRL6JPe+Z6i3i/qSxlrxmsn+piBfrzeeX3lWb0b2e2pdllmPYFlN6ITSa3FHoTZiKAUf8UgSGFL+xk3sfoazJ7FvI12FXSQb/30eATj5205q3t1zP/TB890b3U1ENbmWqOJHoz8qyYjSYxNxHuKpf0ey2ym23hUewmV7k6lOVPKdGo9BbuRQDFjebbR4mecNb2KSVbIH5PH+E25xAkaTFb3A8O3BBNP8M+ICMN2+m2OtctHvV6x7WsRJQSO78BwCEdxvbcWhivmaLZsYw2tgYP8iMTKe+y6Istei5WrajpD6r3fph9f6o7v0NF2BgmJ4HNalKjnWNYv6mv9NekL2jdbBM/Q2tki+FmUCCw9XTwjyraS4Tn8mS1GHOAdIlHSeHg8jGpaNRtRlC1PNjYw7giUooO2Ij7wGhGC39G8iWib2SuzCSBaiIEvYYrIIR6+jBgiMlFKVZ+sRHPd6CBPSttlmoXIVUQa8ZsrhPgjqugBxFXtBcTWNwcQWUQXpFqoua8lWoneQ5+oMVA1/vn4dTXXPWpEr/JBIMBAC0kBiOLOYAkMdiCSfLixaDjUqQA8AakHIiu0B4YhtwdOW+WwhB5EmvYJpPD9hmIEfmL/zykhb39xYsTKpMyAHn3WRZmzFMlvlSiqT1fJIuhyW0dIzPEt1jNEHiUroqTLHnlkosJXivVcyHSVecx+vHGyJHGVKVyiOBHqBZWf9YAl7Axx0JPrFXTrDJmyrH5BU9PF01katXszpbKwggVzuG6oTapwO4ouWeliQAvdKMmr5BnYnjtX9hx58hO6TkUfSA8ONAcUT6QEAAAA) - format('woff2'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, - U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -@font-face { - font-family: Roboto; - font-style: italic; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAADG8AA4AAAAAW2AAADFlAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbmh4chV4GYACDIBEMCv8Y51ULhAoAATYCJAOIEAQgBYMyByAbnEwF020+cjtA0f4jC0RROjjDgv+LBNuY9sOFiWKgQPLJXw1FMxltslhMMMlrEEKRdTC2ze1PrI3xwuZPnDh7wCXj42fgOB81l4fe/r7/naRybr8PWCOAXvPvGdX18/zc/tx3F0mNSGkxARVJUaI2KnJESbSAoFIlYaGOj4E2tJGo3wpUVDDTSpvSCu60gn8ZCPqMqzLY1K5ChVxV8c2bBcEDhSOavv/aMuZavxuJGWRNtf6vhu5MY7tMhojTUJfh7Q0Ol/iQzOG4JqeY7xdmWImJ//+qZi2u3uCMSDn9yaXglFl0TlXmuOjcunQFPAAkPj4gZZ8DcqLCsSE5kZID6Uw5QHKIoQupJJ3pTKescY671bbrbsvNTb/d1l0KVeq2KNtdqK1/5mjYZ8l2LHLEM2eoObtrOAhhjCKEMEerjvnrs4t11riU82tehlOjczsaNIVA5ZMVBCHDl3EzBAZ1GyGWAiBZsiCFCiHFiiFlyiCVKiFb1EAG7EEY9x2CEMAkwBQQULxYeXMmomYVksoWVnZusDQ0KyUOlkamhMfC0rjgtARYCig2PCXBvEUhEAdA1eODxGAQ4N2qLvk1kABsQMmnn+1Zp5RQGulmdCd6FD2A0k4NoIbRo6gx1DRqFbWdepp6lZ5AfUqdp++mEbQgWgT9QFQeou2gDdCP0ybovEs/S/tssTiKbsa+YQDmRi1IoO9mrzxwvO3sjwcEfRWQACbsZpj7HiaknXW8NuxZc3btY7A3cvm+bl4ufN0rr+zdbX1CV/vcF2z2cu+qKCY87mXFxJ1THo7q/qCE7yF3P39SDWeXQA8WRX/vpHzB6fW5zvxhcurf2RJfHPKUT+2HNvOnycwfF/OuUzuq6wLeNXHaX2965Bc9AT3vVaPbU6Mjv/hMz7otL/ZOMY22UDdRYk31tPcioFdEk3EyahNDu5qbUvuyWUVeHQBuIh1qounlvocJ76+y9y0DU0fsNrh06gXu2EVs0PO98XL+m97stCfiLGxKp1P/LOY0LfCcuqbq/sXFPyV20XafXa61kJ/Yq0Nf5AWXup/e77xmk2PmL5PwbB21OrHS5lu3irgB8p9a71qt7Wty91T9iyq6vHZ92brnkmcxqcVu9oh47S6UTBNTrFzS885Nw3mpbjCKrzfXYTk1X7zu0DVbEOTehqXGv4bf34UNEgomFg51GpZZbgUt2tbRsZ4ufYaMGNtoEy4eO46cuXDlwYsPX/4CNWnWqs24CZOmTJtxznkXXHTJZTfcdMv/bnvguRdemrforXfe++Cjb7774adfEP2cQGJInJGljEl6QBLCSRptGSSyt8Rma+qZ0EybPnGWPWTdGzYBLmzhCvfGHr3g3Ws+zfMPWeNkS6FddqYxkYlJTGEaMzhnPOyhR3iMJ3iKZ8ZcbzzHC7zEPN7iHd7jAz4an3rtM77gq/Gted/HEd9GL1/sRQQvQgrnkOn3iGFzjFpg3AMPkCSLy3LR4OrsXkVDaoJHZ/h2TXxxcktQmLmyBlXWg4RNnCnR9fhTwTiAMFh4o4RSVD5HodlbBhN3cBf3cH/TUihEMF3PUjHWzbMBXNjCnSNkjcqmvWwutKJNzoHneIGXch7jh+InfjVGmmvGZN0CmwAXtnBHDebwHC/wEvP3TsIjzstavkRDYyrXnh4iaW9bviu8xwd83CyZSCXE0IJ2dPLmWMACFrCABZPNcljXzAZc2MauJXGvSs+k+WKqOcm5xHO8wEvMG29L8g7v8QEfW8dUO8ird3x7BGP3gmmf/ZmYwOutj19DClfjQhg95V0U6gpzydvEHt3mpcy6NL4Dcrt0de/dyhpV2VkdzfJUZwVVoE7wuhObc8cEcZQhwMQCEREEseaYuuVIVtFBp2+jK7VkTQYXIc8uU4EzN0t4CBU+mar8BFBTlamhSbtlOp+ypnHztCz6yN03v/gi6MpAUiRFcpAzEYSlQoaGELVMIMsFmaZg0BJM2kLSOoHoCHH6gs1AMBgKWUZC2gYhwliwbBTCLAWFlaCy9iV27EADSbqIdE2BuQkqD8HhI+j8hBh/QRcghFQp6ntdJKUFX+49zzqJdu1MA3JmZSITziGcb03UBZeR3XAbcsd9DA8ik+WhZyjmMiU8N49mcSLJWx/hd0RB96NbiieJkqgU14IoSaodxBWlRYSVQxEklRS9iLA+BUHPF2LYgUF0kiAOCROTRLjFXIhtKsSNMJEizB2BeAoWb5/MMAsN0RT7t01EqE5BqJmINGgkSZVESZxESTwSN4aSBFEUwZMIohMT1OI8RJKwyQaffEUmWrforyQ9hIAJlEAJd58CjLCExHgo+8c7R4LquOjIYGgU1N54d1wCPx4EcYmhcXDk11AKnEya9I2lteYzwIC67Nes224CI85SetVt5wENqGvu9G6hSK7tgtFsPZc3CxY2dfykUIjN1lQhttr802ibrT5ePSJQ0ICGgoqug1AhHc2F1UQmIDphNgGMQ0ig+7+2faTP6A/nz6GET/VwAQf+BZkrE8moaOgTGk0nXdIY8MwUA3BNzCWqkUEIKosoVmOeD2cvwm6s0pz12x9//SvgpYJKJUseoRXLKafJkSBJijSZhWoF4gjNSKe2JxORRrVwX44MMGx1DGEHhgP2G3SQwJD/DIc8vEC2PCIvLlWao0Ycc9wJJyHINoQwcYiWafA7b1EBpJIMFCt82pkN+MIvSRRphRs7Ko6L6NGz/H6Hn3LHtdHdMB57AwhRe1ThZJfhBEGPjuOU8hkZ9Gv7OlBmlyPtExHPm9zwMZ0M5gc2BuYArL/55++nEMj/B/gL9hu1VlCCbgLESl1AiRJ8KjQ1DUWWglTO/81qAybIaMCk8nUbtN8ZU6544Z1/ZcniWk/WqXq33p+jKk1QmlhpGiVZpSVKKkpLldYpGSpZKB2udL/ySkXsb/77k/8AJqWkW4/9Djhr2lUvvS9riovjBlMrSSvJ7/laJYP7LvlHzlHOMRI5ukVv/j+b7ZSGQ930Z+bP4T+HHm99XNk/I0WPNz/Of5zzOPPx9OOIx/6PNR99e1T0cDvaBwcAwVn7StC+Duyeh8Hxvx3fuBDGYfab8U+/CIrhDtxN7J77HihR6qFHHnviqWfKlH9jfiUVKn3y2RdffVPlO4RAQ2T+jkqXWF3HwOaRYLKjwczzA8RioH6DuV3Vo72PkGEoSUgQEj9lfeUnfBtgdSroxE5FIFyRV2r47DQEokYiRWTUSbVtYQ42gHKCcBJt5XakA9eeQHouQ94Y9LBa3GoPtof00epvcUuRWkZM3PuvMcElvSDMlaYtmR5Em93wHDAbJNcnhzKrgBvyQf+exM8ZqCsiR5u1liD9kuXkq4sU9fAvWHqxy9DGaQ196U1TBSMjVrUplTWlbb+j3teiE0z7CKvltPSBewicpGamtpShgCQGW3QCs8tpyPLOgWqU20VlzrH3ZyLaEoO0zCpk13svkpzDPnr0MDzgjCGAgUvcBky70XVJuqZKbtIzJ8+oGFrzU3jytZkayiH5d9bTwoWZ0u8cshxALCqsZyvg1SGQEOv7oQhEB0IvjHfrbXXWKkvOEYnYGAR33LJGbcynBrVGBLKWpDbSOJ6ziFTKWtxWMDDvHnZE7e8dmWHzO9vT8TrFMgRN7N3NlkljJMhiZ2yI0lMfl1WM+7z0gvpVrOWjcQLNWOhpOKXx6A7Jq9HMpmYl2rnwhQXK/R/Sd4qMmcXhP1e5SpVQBDVZLmKJV7GPXgChB7y/qAD26haoyE8q1cUSWFRomaNwdEMaZrLx4VV2Y154RoFePSVNmAEu00aRy1LLkX960CXOZ7f6i3qGZf/5sTUamdIXlfUev9mv2PEthmlikfjxI3GcwXTghJlFfXVnhRKGHf2IfoVxkb2IHmPfcqSGRjf8iQANrpz6QzUnHqcpxzp8tuICudqFf4VDkJhnG5KM742TuULaSMdwq1eKw6seUGMmIKusdsPmetxCjJylXJRXtDZQGxNq7JY97tRB+x50l0lMu+ou1mC8ba3SRvmjF6tlVBiYZ40bqbDkQ14cDlHPGmlIarCX5zqbHt24Is2l2UZDvUXLw47C357zTTgdeCzaMOmPC65c0QU8AuNBxf+qGgez9NmX7KyjjkZXpJmVYGPDaI7kpfAsUf/SLOgNXQ8nu7hiTVZyOshglnNYm9BgBAv2qCNSEYw+Nfft/FZR6FFmPsR/KhFRJhZ+bUqZ7NphZ1ZoYfBSOTX8bW2vpqix4Db7CYRxAp0Ie/NLmYx67TS5XqF3DbOHPIZsK9RQ8tiImhFs2f6uKjsKS1T6OXudhxtMkweln75hAJ8NUp4IOzkPWrPAm5THCzmlcDCICiWazKVdvucf2UuAPZrPiaf7KG+zraKPt0KLOj53GFZbZ01x09+21huf8FqTfqvpJxHEHb+WwXnEaZqPDIlAj/3gWmdZ5ZHg+tEDaIo1sD5LOYaSyOy/O4Vu8YqQNL2qj91ngIMnl1SNe5tUr2DI4U6fQq/bEYsOqO7iAAZ54tdwnYMV5EUVU9Dl3T+MMdojY6ogK0bUwbtloPm9oPIpH4dnEdMvvASpdccGleXTq6wVDCTIOXlY4k+g66hASEQPkEyLeYqMK2c/Gqw2XT8ysGIEMVSJL4WNqGSpUD0BJ1qrI4p+FH3i8IVizzZwhqRYX+vhUKEXavCetkQKv1lLraM1B14fBmbPjmLUu17WohQhdyuRXHcc0IMQOjIQhSZ8G+roT2BRSFn/3a3u8kfIC+Wis6cL+pLNXC28vuHmFEU7l0Le8xMShB9XMLlxlO8NiWjvSlcy8lQj/SxjlaaxorbmEZuhP7EGSnWvOS4aTT9xo/+sbeYY52M5tdKUw28qFbtDkhsf1aQO6IWLRpksAgtsXh6Nte/PF7qK3mD5dpsYKHNajVmwCEsrGRJ9R+k0gae0tmPxshHo1lCLr1juRi0W3cbD1JRposaNmCUZnZTKe4iPBR85BiYM6hlRGUif+0iFZhV08jx0hHFszU1/QqCH9e+JySMxLgIWCUMsWKPDU0IzdZqJvPy43ONcDezoc2zUhpLgP/vyIPexd5iuq3Td+3cDFjmNtC/q1Eqc++vorOfKqOPPEf4wupGj+Bj18KKKZa39yzX0EDEm5N17likPVZbXKexdWe0TgdZA32mumT25+DTHZ5KeR1ZiUjVXUVZUAqgQdeUuvXT1Etifn6YZ9ChKOnf3zAWlOE0ZluRo7+8NnLp7kHG84YLfbnU/Spoajqb/eq6nCy3ufrHC4qjLO3WfxafegLt8+8akW7W8B+6gOnCkE5XJpaqnAuBM/F5Zu/ENUUniLK+iJw6bgtY44Fml3qOmuCpSTYyzLM55xd/21m8hK1fNQ9H2GbOqIdhJwUmcDb3Aa2h8/qgdPw4bJSo2ZL2Ipfr65Ool+mPyQRPcfA64OKklV4OxrU4l5/cjxIGsuwynWAwk7nqUD+WcUaL1ioExlDHrk385BJ4tpPOO6T3tXlmb1kklZZFVrlvVJ1J0NQ4MD/f6+S3Jk/lC5fzZzQ6f+kVyYnTDA5bkFkcno3t+DIFhQ6oDnB1+TP77D55s/vYeLtMbZ56a+JE0Eo4Aub3U3NjE+wRZRGvnKHSjK0JKr48mhngcae27pXYm2Uy4aDqWLRO4MtA0ZsPH8nqWU0ohLmsIJmnRH4ReCs/LT1+QujP8kz1xj1ePLH80z97riGXpGXQ89J2peL2vlp0X73qCFlIrtPhnONYsQml5Q3BxSR0aJVIs2dNNK5Aaeyi5XPGAuV+iyev56A1x8E5poD6pGIoIvp1v+H5AuE22Sd/8rQcsBvkZDy637/TqpoRhomuQMoHa2l3hRIr/eAteMh9Y/IWOdNfEFdmCJPeze+V20ml3v3/ZubHuG62Jmb9F/3xqCrVOSUiFSKS0k5+aTBEI/AxNVGjPOkMhvLtrWt+Kqcp+okniWW8lBATyqEF1QQ+EoY9VPEnugzIl951+/ihxFd7rfTIJ0PSg6G9Z/WQKel+s2LmUwu7uQmsCmh5lWgqdkg5XGUyfgZ5esff8SjGc/uue9mff342Qu5Y0LeiLcB8J49Thr2nPMjtcVhgYTmBa4YvWm4gHzitjCLqvhArEPS0umwCyYAKH+wGZKlpkmf6OmfGsByP/CuSPwX3wIn0C/1zSYGrEs60vtOem8Hj1wY5WIM2P882ocmHuZW2/PiQ0tMzWtexN6z+U6/iZoP9KrpO8o2sPWnJje9ceb/p41Vy8/o0R78Pgkj00vdn/DpyFP0U0W6ek18HWunsK2JcZe57dHhbXuNOx7MH2JY0f6KcXaPlu1R6EL8pNZAXTbB1jX4YvHC0UusMYXLhxQkx1rF1tfJfMwQ+00wtAyQ8vC0ZRqC4FlL5MFeH6PdTNZDuhipH+QpyHmvdQ8ylcVsWRPar5iXoe9UOeHgxLmj3FRM+zZ9Tbj8o9+acQb9tDzSPbs8uO7S7EOailn1xMMmHUjAwq55EsDFyCR91cmDy6A8nawDH4g6cf1VpoMcNB93NkhgPoFTAPT25J5m1I1KjeyNzzbHYf9iManB3rSB4k76h2vnOm401zlxzxredBSrhrsPsHsSHgIH8KH0dvHhxRMIeMdSkfkyQqAkXSmYGRGVTcTbfQ8o0OMS5wZkZ7Wdvo2YRGgbREhmt2hxM+DJttdeIc9L/Fq251p4avU7sEp9H5UM1gD72SvdFHzlCXo0CmO1hdVauc7XunKZOPc/rH9+mXplju/O3giw/RJP9jKEeB1KdrUp4O3ZLpq/wEPM/ViVLDGz0bhXYE5yjd45TGw8pZ5eSlD5J4gpe2gjSNBymWO14C1Trfkd8hm6526aZMt8ZX0KH9W43/g3uasZ3dUI8Dz8jQ1m60x4ELZrkT616snoSHnJN49DfxDLg07lKsvUZq9QPSCTz2jXgGPJrN0t9r9cXX0orrWMnapCddlCzS9hMKF1dvYEYwX/dSnrBM4qFwgdVXnZildmvTBTUYOyon8LPY3SdSygrwzvfGCbhpm3D+G6CX1t5cSK8kTuH7s6whkQvPnt7v21IOsti6APhteYwoRoh/kh/yR5XJbL8FoKWVH70bkg9j+PFd1lFKaOlAvtGgI2NSmzW+9NNNnA3jEVHHccYbwIERaSFEHG4uZ8YzE1JSY4lmgOV3UgXKYwf1zRf1zEPEu7RVL/7R2r4nOikkGY7dOH33p9K1NRF+4QaZI2iKKXpD9K6qxC18GD99Qh55RgkPS/FBCUTjLqEtzJzo5ij0IWzVN9gwOcI5d/YMkrnueLN4826chnrzbe8zC5k1NQtzBeXEIP5/UWiUFqP4n0nY7gYb2yOOaIuXljMjjFHg3+CJYsX+I1zOyg/sARt3Ba1JBay1Y/HWkrEbYD6hL3p7Md1L3+MgNZp1RnHhBh7Fcw9Zh0Q/iuTy1lt3k33ZJ5hzUzidOBTqPSw+TGOEhRb5o2jUUMuMY0SEZ/uhWLStMvAnzduN74J8UMFmRjjN3z3ZCfmigkL4OjqL6FdNr5YXN6Ek1J/u/IhZzqqr/fCsuAynEYNJgVcpBaQYua5Nyb3lFpJi57h3uKjYTYvHCsKWRKFnsyfOxV3fhHZRvLxjYU2yxKNlLxfSlM/qfkhb9Qc2cVhWqucs45ItVWas4G6B9lONOe1kvvJZ/cK0lT9g415mrt/B8/ue+ceK8lOtNxQ4o6QQEbc3IDL079opLMDnLrH3CAlO7swK93fnVC83pDAteX8DYwcb3fpfE1bAC5KwQ3wux76orYpIRlmHaF2U7k6HJ/uLkRsq0TfTKtXNSdCweeKFK7a6i1H24VLDm0ZWufUf8AChXvdaqSSNcoo6GMW8W9UJ/WiQJ7ul0v35GKj0tunh6/h+xxlF7wTBDHGGkOlp0cXT+HpB/IvxdltSTzSRkh4jb1vw/mxhIUnwU3UO9K65Ku93YaxRFzwU7Rd8/zBrDvEGDeGbgtPwBhbOs4dFZ9/HeCsG76Hw2dNqL98P1jlMEcDvzRGKZUd4p0Zi6vGnkN2Syg6RPn6TAmCjnntqzxyF3uMq4moe/z2liZxsXnFWT7pjH3Eb/6ZR57+Q2jKr0omdpHuf1Oc5JbRwasSqQ8kBnoQkw2EVaAhPCirhCOUQf6PkGYaDwsxFXfN9Y0TfHDNMth6mSD/V7ss0UZJodY29pRiM11ZZ2J8ZUDnXsd6sSfVCl2W9JWwQi9aPifrW0Uo+Y9U8gQFw4ZRjpGrMMNoK9/ILPtJaKRmbUvuU+M5dCZfwXfz1U773FiTgKWUP6e53jdeSFciD/F/tpQp0ACf5rJdXUz4jBVVfE8vS0ybfhG8KvkX7p0f5f4OVXw9XfQXdw/5NYDz7s2RW/ttVfAHfekWf+gLsuTM4FNeWimfB2pTpI3YnODyltPbmzi9/HuV1MtsVxcHkXJHqucznLxHUnwvYbj7qaT4WwpOCr24LBQHqJXb/sT/H+7Q4XZdXDZXv5NM4TDeOOOvoSyjFDJP6Ch6cGuJWYcZXajsl19C+USzKY7DmKf4fgzLzKzlH36SKFeE91MbulaZFk+PWjKQH+RB5eKwhcw39Bf1I8bViPEh6zFb5DDny/vKa/vDBHP4uclF0dv33X+WCLCrbWy6SxU5IKEskrQNYSeBxZXp/5b9PjszHNxChyvxCzjW0aVdI8dpV+D/eStwszPpJacPudHemh3H94AItmhy/9mhGoA8xTn4fxbYmJ6w7lh7kRfRRnvzT+AgN2pLB2sr/Xj8Pi7+eiZxnVPdfbjC85S1E2f/rLSocLBNKFUqKz0zEVIBlRvMltv5n6aTwxOHU/7Raak7zyR/h1UQ5MZuUOIMLvgAlOSUvlUhD3cnsIE7+KRue7Jzz4fuMRnp2zZGfoY2oFub5OVdJJV+BmlNZWoAyUHc0OM7NjbB3zH1l980dVr0QAi5fBAzXS8rzPM5rfAf//qeX1Bmul78yXK+IVvHbsnEZHm6R3spIvQFOG5VLkqU1yYJ3onwBBWyHYqQtrH6p9AsWKG5qciVqbynqgneYZCqXZnoFVqzrzWKtULtvfF3snnix+Erted0pEUj5d+LgkmWq/T6M74FqnNQtZDA4t6B6TmHJQf0bOpdVL4DCPljOv9ol/MKzW+FkDafpeg0wJgWPOVOrHwPTqnZrx6sbkDvn/lnTC8oWfb/Pz3bd2rXz1in4dDpH+XQOqIddO3xL8y9sPypfmtuKq9GIgFxO3Ss1vtCC2FwPZ05sNmGLUpxY5guIErq5cdaVjwR48qLITpefVO8VUujhfh7abHNO7WISlHWFMTypZjw7MEmR5vRVMM5vzicOYd8ydf4dkQF4G6uZWdCP27HgAeks841mvHe2G6rFITX2Z1aW15EyiNZTEoNUN3g56IaKIkRdHgEjpuTgleAkogqNb/H+KtSkItK+4++byq34IL72+NBDfx++O67CXZ/IDygsMFfgDGyhXyrKI/qwX3rkyrciR+CGcGJexR7ciA7NUU6t9pm3puT41HujChxa4XRVM7cMl+P+b/CDU01cLg95w6xbJtrXTnlVXkGcx+fVpd+wI/fQCrI6YlAzqaAyI8886EEM+rTzBNlf+CzoxPsyrLydIZQ+W9ajONwtnCqz6+74IBp1FJU5dWy1G8T6C7kIhd/y8qb/IQVLBbGeCvKVqlI0hH3y1RL+B6aOvMLssp83yMnoQqixc15tQFEzTsUDZXK5Ira5mZ24CR15Qju98qOxiyyK9s1xI8pIYYVuD9all+AMoveM9CDIpI6X1ezDLWjHTbGTqUcX+cd5aqysIqIYRRbTUimLzn/PgLXInDBcPC+uZ20/Wm/H0zXgcesL7W1AXseQldYisevEf43og5UI58zdpZtldrB2NMiLG1rzhlbSNvr3sIFrBacvlaYbevB9yEV6cZSLu6et1qNLRrEIWD3tyBsOsjuMxFNKK4/hcFTmLcVt2DOKO3DzVbETaScX+adtdYTTiolt2K1PPefqW/4JHqxlvrAS5JVJ2y66yDxkCLJpRlL5VQ2HcRNRf13sZNrxbe/U9L2x0guIMhReRkvFX787bJREOpvxu5p6XIXObfX7wW4W3tdKfV+9DVeimVr/76yGN6mkqLB8byKL6BsV30UOLgivD8JN2LNZx4+dSXUFExcZTk8J9WJZPrEbB6UGEW9FLO/eBtHEnLK9OAKaIpzGiQzWh40kG6LAp8YHleLgfNenqzIrMZ/oPgXmSzh7a2iX8s9SsQ/75i6Nuwn8g1kM/p2Z1oZb0fBTyilN37cka6LMp8oT8YgEi2nPxXXJhTiZ6ByS64XV5n53tNqwb0nhnF1/uB6DVHbCtjpCuRMaV4qEqNhZXfKkDJPq/54eQvvQ7VOo5TUgnrsbDzkm2deyfeSszBUmPSgjpIjc5mtOfEKA5s+hjjlAHqHeHuCVZgMq601XU44tGT4e7r+MQzbhEurzwqe44rY5KLuPVR4WvV9xeHA1BQZjsotGcBSqCjX8j5mZdmKRf1pHhZ6TQmonBxXTihla/mv2IRzTlQjFf5TdDC+zwgzfwkZR52XzbxX6DMcDnvk/m6DoGD5e9sD9wTD8/f9vsESH4nuZ741J9CTxvVrz9O9w1N/1HmWZ+JfSf3cJZwtRzoledyLRSp2nn8h00/gKeqNLlUfdFfaWn8cq43ryfXAxomNt2zux/XIX7HRZWaUMkaEp+pL7Sx7pO4ZEqtSetVQhy99RmhgJtNFd30PzVHhOWBF7igxgnN0n8uJ0H0TcPbpp2TflTypjp3wSueytPDuF59h6b4G+bsXO9Vvfi+6Su2C/npVTxhAdmqYr3F3yUN81JBzsesWZ+8dfbsdOKI+bmmqmqlxGKJ85wT4wda8OO6NC28Rkc1VFC78oYV840HCR3kf8WlJqZMC142Nbrr4B17an3o4HXwY90eZIjvNDYFffnOqS13w1ofUmRrZim8FDdjFHeu6L8lnl1Y/HVz8tVtp2DbU+CPZNcsG15N309zG+ubDoLrFfpNArYBeheu636owFClWVG5Ia6VCZalryUzi/aup2VD4exudvUw+/BVKAc4QL9kb5pexE+VeaKlNgbBJ9uOAEHsNlWU3FGa0tm2Xd6O5i2zzlwtNSWhtL4msPpA7hEVSevGd7ZtvuGuMRzoDMTFFHwo6mUu2iFKF485mWzCichK9m1t4WTofXm2rJeKHJ+HrWlllQDXWOCOBMnXsg26QuXakh26ius+rrulUrD7wVxlvV/L337eq5v8Bh04blHtF65RjFM4+LvzwGS+Ur7EPTUUGRrF20zNp977zqiEfo5xPSxHtyTF5mBspsD2a5iGeMmNRreamIp4t/Zh+djAiMY/WyDy6/8hTdxK+f0SbfADk2NTsKJSP71S7abG+J0pwk1xVzqfWKmbocvkT54Q1jm/ILDDnJEgWj5iA+eUnX0mzNOksLU31z8yBz64zM9VZmypDSfvb/BszMwGKtG7NhZFczrse9/7MH6GFiJ67c60A7cMtuXNsEJG9rLyfkh7Jr5L/JyZF4PE9TYoCyZGRMSuwCkE6go9jm7pF00bNi537BGdIItrkzkh6sIdJQIfnoNithKzGEFCZqvcXHJWaeh/tMn8aHscz4Vl+IP22t4OccH5OZjYNQyvHc3ZHQp0+m8GyJdCwbsY/NSBDkFqIstKWBnrvex4BVyyu09DaWrXR1JsKN08KZoPchfWI1jl6ydyWkXJOYfBDkf3kCS30JlSuYRXm3Zvh5RBte2juzSnKveGeUwqP+Jqz3d/Zo6tFEHacdNFcXDLWk7aWkJEpqha3NakroElYm0xg1WHCAGRCw0twUby0vAC4KM2vYO+hFVAKs+JzVIdPRDkJhB1FC7+4EFIJKm1EUTu7aGYvCUXlDZYzveps1eo4Ork46Nlq6rq6wsrjYXnHKbkPxbOr5Hvxh8jbKnKWI/zJYMm4Au1tdpcrcpYNcmGZRBwoMzayGDwM980BTIcpH9UWkSFJeQ7qDUXt8AAKJHfGuo3Z68TQzLivYD8nZHgNaVH9WLiogmtNJwStsPJzV+ctwAZFworAK5aLmongBYK9opOuil8DyyiD5gZwHKBhpXgb5G4bh8VQ3KVJ7CdGEvXNovRyyWwP/C7lHxm9Bcc767mMLIpZ3QcybmnSdePaXMyN2fQX9yUoYXP9l7Zg0trPvGbV30DeytxvqsefCBF7xYKObEIobSh8go+oKsrD3FmcWf1UF/Gk9HLL+gqZsc3yKFKj1T27FO6cYzWRTod5rl5pxNR4YZ7SSTenxEbv7fZKOUIMsYi2RA4pNY0ZQLamhFlGWyBHF8hmhENPASPXYG+DhzM2IYycwnLmB9sgFpYSJeCyK/Ievn8BH8MwF1m6h/8b2xvkHuHO2rDQ04vLqewjKrJ8cxCZB5ErXR4uuy8zCBRdUJlJ0myTEM2cZnSvhFUZGuGWBSnqMyU+zjqofJtEm+d33/gX5c1PUJvAQb8PZNvzGQzD6LvYgekI4iDHP5umcO4VO4c0hibXD45/0MtmbRfZwW2f05Fo7lQk3jovG7CZj+wJSP+nJv2XzMjuuCJMsyVZLZ1c8CUQHSU8lVX+IZIKyhEBb6jw8gO+vhEaFz6/99OYX6KxcFL4paL3r9vwx2oz2VQglsWMSc6Ix0BaZN5zlrv37Oo0H8KmTrDZtVY/AFjnT8KTV4eXNOvFStMFvEyfxXpRkYn42wjTOi+/FsEldE27JyyulJeiv8TPyWucbQbO18LXE3kRaEacMrLo5qSdcdGz39f7GLWj4AHUbvZs09OI0YnHd14ikpRMeKN2VZbMgRgnObr7rko1ukbw3t5aP4FHyFFvmpnh1B7s8vT0FuaFGHe5Sg10m+teNdbpHUirDNa7thhiizp/pUGtvrX/9ZSBRX7a67IhTnAG7GgzdxX1aTcwl/2O6Sw7s4rypqCDy8cTmwHvMAtbW8nePSktwJY7xws2BlY/KN2YejfWx6dPyGX2wfnvRTJZxJnVqfdA2Uj7ae1h4Gzsjqi+Y4JN2XpEeBFMzq//VZm8bLzO259WP2tvqG/Dsr/U4WNd8MbB1HC10stlgZMsjs2sN5opCfP/r9vZt7Q+xPwpQCdraCvXXEospYzJUF05nK/pUtR25I58lYdsHPvmr/ELq1KrYxzlCG7ZHuJiGQmOB43vhIqbc1oC8+kxi7ymFA0xXMBmT5vSW0y4W5xK7cHBaEPFWQq97MXp5Vs7Owf4z+WhC4hL53tV+uAQH57s91cysGFIp4cHpK4VoEzAaF/GADvyiPUqY071mg9zuQyyx+n4uuizmMmX/D7bqtLn9mQFrkHEgspmsMKMUti3qQnduK4xqrqJZky2pqQXl4KrI6W7Ci1u2o2R0xF/bqX/4Eh7DMyyZWxK1daySmM5IooXUEmDSZWZ8wSQb8dEhX237fsEcrkSjNZ7fhRsWSDw2++E+SjbROyneRwlSoH4YpiYTXQK53k1Drs5QkrV+yy7bOBuqmYsdGHx+KzpCpLUOtpzFaJVoBQj3u/iU5Pu7ZKW5eRfn+nvyU2NcPdeYrlxrY+3vI7xyLdcGNjS8YqYXbAmQvhSzYe1ZB0I2bAeVnlzYGIjeN3hxCpwIuXCQPSKb7hBTLZcv33mVk6P+AkTEId0hukquQKHvqkS52hOQWc53DK+QLZBruSGWrfIIZI2zHBO6ZLYrjtyQPyyalH35oVWWY+pO6TrFkZsKR0RT82ag8xc5NDcnyAcl8gNkKaG5KYE+iam+oM7sL9xxtwS7lg6DWOiee8XiLqWHNrb2FYN3QqaDHikywwF0zITdaea5jJCspCjCB6UoUy5nyaagZuJ+Zdh3TusBkK4ekNy8W7q625RiLfEOhaAtCtoXA1QC0HY0un/1QLB0tbfkZh8wn/u6P2jIKM8sNyFArkg/ayyr3F8uvu5kmd3xVLvjlSIBRWDsEm+gMm4AjvTxsm7F4SZgO6mc+nVtDNvDDnWupP503tqkWaRxjmV6CxSHL9Nny9zfptKjGHwxixM28c8IEPJne/8/6woW52Z1O4EdJnP47dhxFIdmD3dHUfjL84V52z5hBUofeTizHw39pANBJEj98LeZM8geNahzJQ2ms7RT0XUD4kX6eFlkHexJ5rzgzADpo0/ODWIRz1S08tEChJyFwyOAZcwzD4dQ9msVEfLzRaGbpqXCyr6ZvsI+7MBbS7R3hZeDaZmL0acrpx/A+BWT9x8+7uhxl/qW8QoGGhvquqpQ/gWx7SsNNusE+hn5mGj62p3zOb/3PG+YRCLBis6r00e30U7bUrUeilmMKw8yGoRrxXYNHSzHYHvF0K+nQrWi/YKD8h8lE90JPiF5SOKgYqIXwadIjsHza036f2Ik9ENBrtFPbueIwk5fVsnBN8fQ4L29az9LgV5RRv0T2QYr0G3MNENxqKgYp+K8ox2FKAO1FuLwg7BR9bHA2iYzLMDE1ArUzNXYrUGpRJ+PVoyjhX9E1hacgrMPdxWhcrRdQK+mWEif/fNohrZvl32H+YrldG+Pdc72bsErYKDzSOelo/k9sg0RkGuzbJOnpUa4MU7CiQfyS1E+akgnQomcFgd3AxyKYwbyshAf1aY+OG6tqb3WVi8m0llTy2GdZo7VnqUrTLSjPc4vXfEBhnR5+nbx2VU4hVww0r8ZFeCqg7Q6c4kb+MEdE9Y2VjqqcTXfN9rAtNKQZrjb69i6RjutNAOLUnmtBvmfWmmLO5XHGsEyactRhT1H4rP+77z5zi0P7EdZiyPA2/8QYD4Q+wUwAjGowc6gAVFkDVFARHQl3bUw1IVsQE1300U3Si2dH/aDHdGccQ8SB5qfLyAERg+8BpqxHyyItgWDmOhAHYYAqwNEB2HnrtoK+p+A3SUTUMYqISLCJJCahpqQI6jpZvb8ZuRcEMOQtxedAaNVsQBVDQGkEm04gGZdoA/p/+nD+iFaYDkcU8j+o5fIA30ST2ia6LI6n8wHWxTfoqtm88vX7FofN6krgJa/cExZtmJsLdUlhjSMrHI8f4XLg4RqMdaXJ0+37FrH58d4T6uzLfJ+Nl96dm2mzo/JPeHavLSM1gmLkpJDNr+yF9cWOtt1KWdP2hQauCV5PZtfni+u9YQ7SYXGBjoVWPYhw6C76HaAN5DYSJtft0Nx2CQLrMZWc3RCa960IeSGULvOJb053MTSWjrmQNqy2OKSHx38hV3O+y5LZagABC4p23YLXaNJoLuS7RzXxPra4rpti4g5IRV6+9Bh3Zuc5nirTeDSoKLQf51kyR8xpqSZiELNJElSJK3JaNKy05B8WoEUL0FzhvsOwmBYag7A4w/lIfVe6wvnx3I13LJ1fKScDDdcVW1/24NQ8DOPgb5Q32fIOLkf0Fj/pn5Ge42PvrZGcaT6s9k6GkoteZDVFIA3HwCWzo9xoGBhta0u9iFVtaL+6y+c0VzvgLxa1Uj9AZU0qC/6SY21uWmCnMpP/YSBWlO/kOmf88HuTzNqybLP6ANt0X6YbqXXHeqlZDgeHOmC3maQ3sJ3RitDjO+vQfi4fmf3t2iAeHZkfNA3ljKsB3Upb7F220BOtWPIRfi+NEA/c7RSbL7syiNd6Ho5bBrzzRddqxZ0PROjB/RNy1Vyvt0fAKlQYn3+qwEVlfsXLMf9g/VHDqQ/vkJ7Gy6M8nUQAxCde1DAtjJQvu8/sHb9f/5b/Wfnl30Ke1sxf//CIOd3bgBCvOZAXMLbszUDzEEmm8rD45YkMQfWnVHXfpdG45b2uY7F5wagcSonBrF6n7b0vrlBn0QHsVAX8MmXkYrKiBUjHCu9+4za/BFayLTdh+PQz0FAnXsqa86dc7Hwht/HZMYA8PpPzWIAfFFcfvpp+ucmPXMsFYGOOKtXwOiQcRbAhOVfqb8hVwb0mOFwJdqVwtTg78f3tc5Or9bqiWlGkcqsn3K4AyxafNTVM6LqVO5omSLDn3E5k5W1kW5dT7vJ5+Y7GQTegYmloMMHoSiD0WzXVhkry9Nsbb+tjRAhIU6rXdUw/LK262RfvKPR5YR3eRoRH9L+3Okittc0qEbWhzccP3jNuHe4uZHVJSN2CmQUFk9rto5Ri7PauwzfLqxteOhofMrxmNQTR/J5XZHvmo1BPrjs5suiVWVWrXI+jKlEFJGQpR+xjEKHUT0vMJLyW3hj106x/E5WTE9U6x0u3DT3xY4jGERUTkcKozrhXgyTfO1iFD547YmwfllG+5DH2rU8XNt+Wftolz+UPqRs6Wv5Vul8EeHsoi2/9ly0WNDa8i0X4n7eb2muDUsEtAKn22XccFegN5suqP5vLtaRq694zNYia72Z6MkH7Y68aqSzMvIzX3zcGjz+1BL9AccGiqFBW2O7mtdH7lkeq6n2MBJxkEZcIDc0EY4LWEUm40i0IvLzUhWnMirmNGIza9cLUe/ys0142P5RbgKlAugTax8YisopB8oxVeV89jWKo42tqf7KnnpWZy+1rkbzr0H5o1Xlk/pKWKRyiAWLEaM9atnGToHD11YXMLYsv/oqn0VKvCaVys/ahxQGJKEKGtahCmHIQyUakTM+EKn861iuwL1t01d9rvJQN8x/FZzymCtp1zHfHBwP+SrWxFIyfLmGXLWpG1ePdPJg/sdDvnI1sZQPHteNwa9ffl3zU1L79VlaLiPaOCpqX24aBErYSpIHMgQwGaiIFVD0xxoTAUMxAdgNaBshsgI2IrBkboQtU7Jd0kZkSw2Col9/sULcfGcuUZIsKaJFipJGyVra1oxOJdYSLS/ihG+WK0EoTWlqENftYlapqgzXOFyK9JZhF9LlLzJkIq2oxH5aGo0vHrejYHHHUxu6PF3pUnlERKmiUQl5oXnwOnqM0k/Xcz1Vq6M5u1VxEkNagzKk5mp+kuDMcJoSpYh0jMVwCVvKVBrZ4TJnyYGrqNWJlPYfYPHbNR0kzAAA) - format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, - U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, - U+FEFF, U+FFFD; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAChwAA4AAAAATiAAACgaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoFOG5JCHDYGYACCWBEMCvMI3BYLg1oAATYCJAOHMAQgBYJ0ByAb3T9FB2LYOAAglrxtJELYOABUw9YoSngMI/i/TLCNmT9WC4twiJLUlJ4ZsavRKHQioGS7EZWN5R0c4mDd73UtXuPfCFPxnHBrr4UHwI2QxsTy0Gf39Lenq3r2Q86ISI4AhQAjOSZ0cuLtTh/wc/t7G2OAVAlKlE0IH3UWWEikEtkDRouAlCM2cpISggx6Q2QjxQDpEPWDYmA0qnA54AllfYjT7acZJE5FHIaeqe7u0+U7KziYWUlWALgDrKmPdvfAwLqzjB9PmkZnd5LdhuqkDxdVXiog6TaEdf5+bmNxo2RClesqX45FKA16JYo9+TLH/k9n2c4Y3lp3F2AoSuyuqfJSpehmvrRjzcgyyAuiIzkkH0o+AsOSd4NduAcgewNeCDBXTK9PmzJVmbbeqwJY1G14eDsxfr34S6EKQ/v5y+DSHC+Fk2Vg812FqjCRwf9/+/3q3DX76fmYDMlXJzRqNLmIaiISCpUYxXQMtQS1Z5fhw6w/x/JH7TplkV6YVG8o/eNPqQKFG4BHoIg7AwehRRdCnz6EsRsQpsygWbOBcOIM4coVwos3RIBgiDDhEJEIEHHiIBIlQ6TLgCAiQuTIgSAjQxQogihRAnHPPYgq1RB1HkJQrUCsW4d4ZQvijW0IBApYEFgaCsKUBVCAAsxPznEs2+2gdxMUjogI8gGFY4JcvUHhRMcQP1CAnHBUkB/wQnATBCjAAAz4EUBavNv1MSzA+iEWFvEkueO7KE7ufGdnxAUecRR2b9pRuqubK6unpJbwDFz1pVukeILeMDozl8wEPpcurwfwHCqvwgLaMG5OhGX4PSi8Jm20iQ94SuTkvVLk26b+q6b6f99gDZRJoS/59q47jBRbOcAdHn+1DZcl7wZ8hD7z+uDhxL1jztgWQbXj+rEY8EVl6n3aQJ9r1ycB6j+SgTPX0q3WetsrMvgsULTC7GkjQl2xvI52fHg0rt6OkqLgl7RZjgabyqoTrymFWnpWDEcn6My8HrXMGtnh8eEeasyRoTfc03eYvn3oPVylP7Zoss/WeG32uH6B1pfYpMpUmlthX2roQ8MY1Z94JwhdqTtVN/aFjhcECwvyKjsejuCkNGi9rVCdqojjoISJ87Quduy3wFF21gXadNmnK9+FG48yXJBgiZIkS0tLvwWr1WtE1aRZi1Zt2nXowTDkiedGjHppzLgJk+YtW7HpldewcI0yboFnRiIqkd0HuX1SnB4EoXdY4dsU0StRbSK2Iad1RW3i4Nk9+IxFFCWqpwgtSe4TYqFyeqooQ8WlY4XrI+M+8+yj7D7L7a3iJrDzbEZEE6KaRmhAcq8RccnBqbhpJX2CKGoVBq4PjPvIs23ZfVHcDhTPdjiN2Ok3wr4l7hT3t3c9orcIzcusW34rivBB6PdRLVyxauUzjhEWx/vRPGvhcalPEFXhHY/MR3JbMvOWXbbcGuQXpQiP4og2Aqz1HhatRuB7LaoVxMbkgMSlSrUxrZgPn8P1WAhzYy+sjTnRRWkfEUPaLlbB9pgDY7Dy2FM44Gqm3zjjnvC0GXzHN0mcXs/5c8HP8K5+BkfHTWev3d+fVoOHeLps6Lp0e4wrfX3vo6g6awIJuABFG5oOfrrY2cNywsUZDxcc3HDwwCEIl2A8kiHS8EnHJQOP+/hVY1ePWwNeD+3TiF0TLs14tEJpw6odSgdWdBhdjc3dJ5sewYWBxxDEE2jPoY3AGiXsJXZjhI1jN0HYJHbzOC0TsoLPOhabBL0i5HXjGLN3NZTTjfQ5YMENu8x3hD2lWwVjfvtqypy97hIi5KLeIninh7EgLqUJutZrgVw6XCaQBwn70/L7frDDWnkk1ueke9GRMl+Wrygsweai07HP6cS1QlzqdSVVFYpEkSkyTYbWOfR/v2tcUu7CgLw5VUFZhX3VD7n1/AJnvD+w456GWqARDinQ4C/A0WPhAFKQOwCxZVIzKehjAEVb0tYgWMp2nmevTsrVtVQcHv4REbcjK+5FbTQGPUZiJtbiSyK5aAr0DuLQcI6AiIyUyI7SqIvm6IrRmI31+JqoXKx3MJsFs3HA7AmYMcBsE8zWwCzjgEIGWBPY2CVgf+Bw4BLgeuAuYAs4mypVuZ5M5HRRWquGJat1dOkGW3bs17aOA8dUM1adB1y4cuPutTfpxZm3kGJWXReFYNVasnls0WLEihMvQaJbFi1Jcluybo9STylTrxSpZO6MWXdS18/3rf9lmrON4h4EChtU73gAfgSUL4DPwMJbgaXuBHEeGH4INFDPIE+MFz3kKkwZvw6Jmk+9ujDQWhQDhPFq6FJXeYmAyehRJlnBgyvjl5NygEqgwUJubUdr6vvl9lDVXoKc4Cki/G+1BscWNfWy8ypD9lp7IvD/t0JI0cB2l0VJW5WdkjlWNIhsl8YbjaF6p8eeaV/1v46S/yTqoIEZJrjocQz/fl7k/XOSJPwm9DQesceqSjARwlghaR0bPQgmZxKX5WnqnLVFedpVJb7IuSNNzPOJBQpsakWu9aCPYxqXqWvnviwvMCYRE2HJDW9/ZjEQLEcznuz1suVoT2ThUFsjCErgcIBMOV4LVrn5E89/rpj7f6j+KlwQVgagtFSz4dCLYIljCJ2I0Q89ZPIinwJk4hwo4K/NsFgZz+TS/Am3/lkDBqqfQJ+5HE2QN2WOtpW4kTOaTHFvgtkeXW895TMP/YLid1WDFYn5m0jMCSsAnLOlGpVTStis2Qg8D0o8KhY1sASmy5IKwTAT1+b+LEqfcmx3eSdUiVRrd6seLMZEyDoQtuikqZpiYvgkEgtiSxdbD33AXNKBtqZS+AKUnSptpthGIxt/yqTRIJFy4Ed8TotXnrdsCuL5q36U9+q5VRHmUES8NPL8uDGEwwjClagIVvNz1bjexkhDKVsbA0m/TF7rvyHQgxLZcErNDbBPbGZIVyRE9AkzhbY5Y5jwQCbU85Ii6xszbeOIBljgLu007iqHOXLM1gqfvBKaxEF38dPnsi2qLl1mmg3cgtJ2Oqg0OK8XVh9RI+D+npQxATbHjmWxSKgNTz/rgFu6LjkljB76mDjkn2pKPnmU0SRHHmi/ghKSl6NLrMju8NkOBVnGmdpPs5h6TGeGyz/+uEIm0POl1qxdZ5rhIdTSqtZPjwCJar5nhbYC+tD0OfDDQFkmIZPnBcNo6FQk7E0oorkbdAftH7UpwPEommUH+xGjgy5uO7D7HXLJofQAU1pGEF4oYSUVA0qwfg+7a/Spk6KDfRBam5cDV9Br08z4SD5XdI6FG9GVWztwyZTtu1LEcdItKPOUkc0BZT/uaGxYctKWX1Y0UgQL4l7ZmtJHbp96JpdVGOwJamoHSJAJrVCgRvFZOkGLp5DIPoo+6Q4mJuTJfvPt0ePIJILwqFN0ERg5eCZeFq5eEoDUxcI577SvlJ5PJqeBl6vDu8FIJ1lQpY/e22PpiJD4KdIgo3KbYqomWDO9kVdY41Me+neYQPl3xjLR3o1XKA1JWDa78XYbXx9QWIi3FeIWsiBkNJaRO6fJyKfGi0NP2g0wpWEkxOURHCpqNd4AglwpgmkvT84VEJuglA8noTXNkEV/g4uDIRjgSFBTrMsmXNVTVn/jqxTVU3FOXTscEy9+ntXUtKX2p+i2jro/nIctXvBeagks6LIyLNb42aS6JzMsKFVmrTC74s3DON9V4/HpJ3Gy+BuJs/+MMlz7dfTcaUDRzB1c1ZVYL9bmXkr+umTFghMndupAE0hn9HQWrhE8jK7sz5mgAvAOrktOherzNo4hTahf/LgBYCoiX862fXBWE68DRpz2Mu7GHDBJJm3uIfisdyFznRQiVhJQhA4T53lUhPkH+4o51lJ0IoFdHcdVIgiHubyRbA5wvGk2nnM04C9bgDaRVlCogPnkYXREPEH1mLYQBCoptNEExZxB0dO5w46TjNs2pGX9RKTuWLmyrbrt04FXnsv1mwc4Lm4Z0+Dk1g3YnN20KTb41i21PrttXW+tPjIyw/zhYTJi6cURzLsKgmBWzDzkKDBKhUp0g+lb2mxurbVhYlQqEDU1fwvtLVN4beseLLRRlkOHLr7OqUFd87cnvNnNkE5CBNKhbWIWTlqHtYeLgIlJ82K7lLG2+1YOY7DSppQlbSmiWStx5SqV4d1qlsoXifwYwjwnWjQL3AhkJ4YPwWbBcmvcyNcD3yW6s00+zpHUUf+MFFdVkH9lBghRviSrpWsnempfLSjNoyTjPQJum1xc02raNLtbJm5KkooJSxEMQFOQvYgppwG6NzgaBuwEXerwc0u8cELvENbwaTmF4IUrzEVyICt3XYrOJybPxkYYHZHHfWUh58op6JM8LBlYotWXTRG5IMxqTBY+ibQ5WXmpBcO0xHW60v4HPjW1vD6vjC2UGb24Cs5KRR6Szth8GoowPoJn01Sv1n6/9/AWBorzTl7swWQjFqvUPYjX9aM2BxLiUMRqu8NkVpKc3WvLKLE7zD7lYVWn5sLUl1WSExHfeptAZBRjrbGaVJs0DW4K0rJj7SxjLfQaJCKZlhapJoPVLg+47EXvgTVB+HGaUqwCbNEOBcrAvR/xz6R3Oo+at3aL9wGSNxnaEepWYBbSNd05pWAPdGYTlH3sGfxeqfDxMr0DBFNSteyMvz5lxHJNpsVxMvk5S/6YPFOR4JyHBidHHjNdSbOCyypeIN20+1sjw3nRIN5ng7Q4mO2ibqdMkquGNKmJH1XRHEodfwO0N4oA/CRxQHa6qPvFEDqB4qhX6dWyrJjkxHkd2SfeQdnWQLUVsPLXr0ccOZosvIM+bUEzMReP64ZghBw11Y+Pm9Cy12MZ/7r00O9CNPKc4LLMfwxBhDRBM2voAjoWyJlo8u3KHqW0PUXGH2JUyQdNixNi3Pldw9PBhLVLwzFt02Ofg//Byd1ZBr8bn/au/U/XnS82ytCIbQpii4YkaQ8t2wT0neo2oqvTMJwbIzilRA3KDFBrZKaoA837d7/VgH78iNiWxM/3KPVA9fRnd1XZKxvfiKCEN5miDfeLSJ0veX5lvBsQaS6tuyveAhdQZeEsSyUlgKHmUCYmw8EoDphly2UMwFAZQctBTAivCoKYEPVgf+W3+FHd/BSf88HNopyDk/n8DqcE3xVglF07nXUBW02tZ6/JPo288BwnanLU1Tdy1GRpTD1G0KOCXe0vBVFfvH+NS9Doz7hRv0E7lH8SMPw9gOGfoLjB4csJNifWn41NL226nnI/tTGz9HxsDVwmo+bnJZ2JkgxJ92/CIhz+x24cl9RS+rw1rRbob1tNHYODAp2TnLXoxkGkfvOwrgk6uuJTnrw57166eZGljNYy8eaQebAjnE9wzgnHWjay2IRW9zv7LbEogCQl+Mtscm77hzlsQyPWI/O2Z0bhU4ZsV8Ew2Mn/2FbseewXr0YDVqhjC/ZLHny0o/q9k7WTPHqbalTy0SS/PoU8BnoCiwJSn2TKIn8vZsZPvBVC6y+h7zX333FKNjypGWCe/JI/+GkAuZwvW4Ibm55cCII3OiJJA+aohGe05xDi4e9vlWwvr4+mASvQwErhHuHPcmrWEq/KXy4K/udqWvYir8pvGlvr/bn0jKrFoeaaxfTU6jn4+nD3zqyjsI/M9I/cH7kzPjKOwtPwjpun79iguNqaC9eizBVOkoCdh660y2FfUTnFp8Bqan3Cx4dgFeXj3XD0hK9PNOc/VTj5Srg0qxRCAyCY20HtucP6KQy1I79FYNqAfF2In2nKh38isQgGq4KY5BYN0zXbjOquenLJesPSiqm3b6SHZ5qvcQd/1sfWruBGExWTCwYNZp7jr+Ft8CxrY8PjvFy87vuLySX4iwGk6yXaQu82Q5A03xv6njb/odWCc+t474hJ3krKBlM6jg6Se4aLXMd+yOVFfZtJj4CXb/68DXnBWl06lEKP9L5OSEvi3XjmRKoQTOESi07JgxNJMxGV2ZxVOXjyNV0D7WsG+logP/VvlFOx1kdxYE6RBJKbm7Uq7Gt/2Ulf2EfgMob/MWD4mYChxoKK074i4YbpOi4m772YvZ1sCrcX02tLmPcIakeUwQflldO5opVMYBfgS1ToFmlF5uirIn0/u+Ggkn62Y1hgoa8xrehv5+Dzb9Qc+nNNc1nHCO3craqn9O/NmbRrmS7eAbetdEr3+nNX32JApR/XXCfSu9nM8jpCrDd0WwR9QIldcIg2/Hc/y38CW/RPCLNqo0y0CXQS8ovzGflVReQPb//1NW4khFfhGXhKQvh630OJCmQXzlw5ElKTUhBXn+7BCInp2HC7s8c13+caVeWnBKb/+mVf7RF33BK7ExnBbfnpJXQiHs6xtFJaiKi8aLj8hfo9e07HJ518EWI6gaEr9f5yA4afY78Gt7SF7IOULORiSaANq7OX6luOTweZUOwk+Fl/RUqtWzXY0gF/0trQAkO2QnuedEmUt5BkUZ8BvSSop41p7XHwgbDfj48zqOUJ5giQU5IqHvf/1w7CqnZeG6h/7/4B5O0y+kS3/yJ/kLXPopDjovIz0hG48UK8pe5uacMTLmT3POX8uxEBOul+kWgDU3hTBPWGynE/U22YOJyhiqqseS/xU2wL1ILLPpfRcQ1woWk6YZo2naA49X+Cki37qnBPLIPGiBHtWbXjSFD8H0585tcLtnB1SnC92pmx3dL0eKKcrG0eYST76OKjvFcNjK5P7cWdhukBnl7xjgbWPgbBtOLhRyygdgtHw9GEJFWFaDiaMCw+T35Bx9GfRngPrz7Ajqpsg4YaDkcvCxDK5RMm7Vaw6FRctmTX7+L4IzACP/dE0Fdf42gCQhsCccI35ORouA8AtJGPI3QcferjFA3Ooiu9K2mVLqQU6KanREjGPZscRXou07RZPm7GRUiK0cG0f38HMtVVVr7QR3+Ko3GSBTwCvWyt/IKcEZBKbHe+G21GtQ2t7XPxmmBR/iqZH/ZzOuVO6+5KNdUt445beEHHvlJSfi4XMY8K7qZUmcHVhT7fOjNlC1WLJrPA7ul56FVgykYFpjoFxacQZIdko6OSPb0iUqJlwGoSN0cdHng4aJFjlzNS3dMLjYu0JXC1Crnh5BfuPkefc3cJt7F0CQHXJTjigtM0EqUjE8M6Ey/bUdO4HnLPVfpVTY2YLn7PgDAXRz+CMwIiiRpDLIxseUxJ/ZboP5E/Q/TB/RJy6wgLZk2CLCG2FC1RUZMt3sRYtBzBodpJuiKYuPXwLP/FjiXoCHUMj1tkKntJG7mN/V5+fWJCH43KYhte3efkN/YHw7PEeBlNXsnTxPa69kftFHLbgNQU9YHUVeqAg2XO4HXYORx6hHaEEHa4W7wSd098Evd4i6EUixOxELGAVItkgRvmjbry2toplHTod9pky90wu84OZfCg8C1kItpcHX9o7DAdR3+CL983VwSOiu9tT6BmYph4yIqKL0CSLnkywwZSKPGR6PRbjBjUzPbE56PJSc0OSbz7X18FUjv6+fDYGEZiuUdy+QVH/zgy2kBvQohBcen/lTfRuiwupIdEI7lNZdZs7VdDYQAPzQYelFwDj7lleTuxBVU73ttNd0bodLIjfeNodz+U241I/VX3iH46jr48JrGkcxXdW4hfLJLduP3QnKg86lccm3wy/9gyZqbZPa4i6Hj84ZT6hH62zVW1dJSvZ7zme21ChFp6tXNkZUIZqCUBJSeCTZOlIP/2xX0tVaTaUo4/fEE/+DhK4Ggw++UYE3/kVMGhp+9q07Rdw6xkpzUbcz89fHKyzb3qEKLUU6sdb0Q9ELmk9O56uQgqHypFgCvn4NUzLK+dyjyPrW3KOB4utvouDhnR5mwf5Ud/FER/e8G5z+Vu+/A/7GdB7PY4dol9r0T+Xr2TNcl1kGOTnRL1ZyXl7jL3yV8qjCuOnIUVHahSmiw+uqyVO9uOj1ROhUuhUvEycbyJF0+SksLdX0Kdxi+JG6JXkusk86gvYf6ssLOoc7GE3sd6rUOCOUMHJXt+8+foZYhM4rpNndBkEb91mXha7KYEdwDIOMhxhW5JhNHwa3Io/0OPWVfz2dJlHGku2RLlfCu2yxUCRAk3mkumNIljHawUxieOdEoH0PxpkrOHlnhnFw+1HfCm+bRIzCosXr3tJBH6/AExeNRF0onm6CgVOFqVHfDUSdqNBvptjV2zu9O4ydndroCmm6rmquaNNwNoM6/Rz3UmZz50U5wDilPPpQcWJoF3ej2zPjL+TrCzf1E6LsWP4uLOjD1mFC/dYXhWNDCAJ07OL8bb77AW72NjT7Eef03DY54lbietQhrhityVmp75Xmlmz1zNS7tcRZ0ibacKxiiafpLZM1+Tb2KTTJCJsk5JHktv096Dm3+Io3HXjJYm/IxjXDsYe9wwWrLH+KdokH9n4/kf0eZrN/QRfxyhoa/oQdn0YRT7qju7+sb7OHjpRtdEpzNTfWwf/6sJ5aUfVxsHKpqEHp8Zcazpv72mDMl/lNJvklhkhYmUtD4oK32Ontx72s9SjCZAWTQtgHpwQn5OtiDs+3RqWsvuak2ja2aa662iuTbJmrz5eJQvmHdLPbgcKVPbplGzmiFVdzlSru65j3TdVYJMXZdO1RZZrk4rQrIWlP6Tja4CeCMO3pUwC6L3hfxjvP3k4rgDgo4y/RRTzoQi52J8PMUYJtd44UjVYlRLOi5YTwOkvgjraeCCIa0tCpRufb4Z5P442P1mgKKCsqKc8pLgzWB3W/sQN9NAlcuKx+WUtb6ahrjZ2kuSjm+joKjGerFTVvEETkIVByKwjv0n9ihve3DpAgrWFTrRCl6ebYgwcbjqgK4s744wrtyk/YH3z/SinCyvXaee3bQ4w3woeTH/8mW5IeWJIN784165Ij90dAPJuapxZeCoOvogknNF81rfUTjiKqqpOMd8OsCI9uT3MOlMTUEBu6PtcQYXD9/h+3f4Pz6ju/lHp/q43ckPVa8RFZPTsE6oLL6LOJy1cLpywBfv6wqa63zvPUl+BF9X30iLU8EDAQR2GmDma9nCA9KG+9blWTvRHUUTKTU3cjEmOQ9M2l2DfN0s3VQc88d7O9Z84KwyL9ue6CaSTczqfQZPn02MtN3LKR+m6kbZ5wM+uyLoGSfHodqkEEElYqxUeH4Esak6P2AjZxlTX56a1fToz0fbDKO93D2PzCh+j+M9IBf0L8XB1UqcMRJ2alvw+cne3F7XvKOp61Tu1FHUMJxBZVKbPaWiC/nFCaRf8bvHGKbvd0Cl6UXKC3pZUYHp00iv4bV67EuVbRDOubAcdD4/OhUYZctlna0KOi4fp04UhJRlI+cEhp81w1yKROT4RyysFX/rGcJFp6TS79LoGXmB8per+WJKxCjJyLzo7K77pZUbtLJPZXScK1hJHZhpvp6hWd8s3kTR7K9vCpEeK78FlWE5f+bu72wf7rlGwDskCtZtFLr/fpQe1v5K9c82xY/d1c59f0SCan74Toi2o5b7VsaPJvwLZ8eIsWbQZnA2p50O1cxKX82N4avGvejnKqJo29Rnn2bW7KYq0hllfHaM+v+z0pu+jzhtxBYbCDp+qJmmBLsGoWihCddL8FfTIQLE2kTDyeEIE4knx0eNAEaACRiefL5/9fZHQUCggp/cT/7B+amCXhHHN1OlqQhCodQRKEhJLFXPU8Rzhku1e/Cptw6UjuF8n/fm+/tZ9NwMzNFTrvKbsCWTkho56c+Q1ss0XZbxh/tFScI32K/witEhtYQYNp1qz76vhTcaZ7x4uR8NqbfChbvCEnpGR6zz+av6y/OtDAlmAq0ZEr/LSChxm0s+MbaLS1+ft1SZKGb+HlOTQVs9lp5r3nxAYaLg0Q/Mb/4z/EBYw+2cHBclgfjEJ0O+Ab80T+uhH3GnuXzIKxWYBAHr2PBvQpwnfrJ9F99CyHezGMPI8ODYIAhCjHOvxIu1Vlvn/gdR/vxKxG+nt+7UEyuR5mn4sK1Th1dBRJ6a/TybAazomjpa8TljrgL985pabjZTz+M78kCwFbe2HT2nrq4p/5wKdzZrq/IlLXebQxPuf+LAYUy/ojPe8OZAkYZQW/XBCxZXQ/ewqM/iS1V3zgwrZtqUmPML4WqXWLjnVWTmxzdAZYr/DsUbCLlrs1xvtgb7OF+v3p73CO1OYAQVFUSllhPxJVUZlAwyKPeV4QtcITTj/QTP69WBvn1by7emXSMeJ9IDSyjRGRW5ETLq2FIy4FSDz/cChiq9yfbx2dDf/1fQPlOn7dNL8+ISKJRUAK1XbJ+HB2FnHeV1ngkYIXPwQwKJqEh02cX7dKHLiiSUL7p383Ufb/Fph8wS0l8y5RYanNnY1s71d3gm6NN6EDu7cIMUhDSKfoSmacw0g7jr4UHEFanBf59NTP2I1qd5ty0wNsT2BpWNk8qSc5aXG+4+Tqk2ydaHP3hKEQXJjkz89Z8Dxfs9/Ho5/GbHcf4KC9rI0MRKMxhJeoHuRNM1ZujC5kp0VCz695fDQ5ew3Hoa+NtZIQBbk4i5vT8SWohKQedrVrUeTxKJZUM/39rtvI1K8WdN0CqZfYHkMSLA10zHlGATisHkifahFu7nl3Rpt6mim+AhnlxbAYWEJIw6D1n6Nerz2PD6pvPSVTS2tjbX0WFI76KnllEQl693C6ouK4aYHg7MDiAtvEHKmr+IkA4torzdTE1ulXVff6QGw3qFuY6Ow3rnPbRuBHMS3KWQW3at83AplH/rx+X49jcdLIINE0jP0V1Iz4UxGnjwfYfafiPfyzfW0k5rBVWBsqvCVQKCRRuViGbFjZvsevc5x4W5G1ccLPGGPpHt6Dp0k8bTFiFDJSoqCinwftWNxz9s7gAqGORRb7ra+OkkITnP0TR0u+Y8HcQcjw4jbkh15M+ZhDt16NYOLP3Q4/hgmZCzH2eDmsqLny9oONr0z2naiot1iL43EtWKrkM/0HjZLGyiREXh0W9fcXfdRze3Y+nQKViJLcwVQep5G3MOshdXLd42x6UmXS6vn0bG/yY6TjaGBKYjefmoJFSB2ghdvpnfCqyQ5MgnSz5gFG+PWBoiFpECgc3ieWCKzu+raVjkUfkmQQ79PpWWRrPXPJbldOZOYuFCi+SDqnmQfMW/QImjbHY6WAfqJSE5o1hfzXmaWwilIO59W4tub8d2gVhfpRspjeSt62wbrB+AhBWjUtCkiw3NRwhiafvQo6/f02rRzZ3YTjAn4keI1KJn5BBmYnr3H7cSzNnNgX8CMlwpqcq1X26eNWfPJY0WynRnZGZXM5PDQusJ5Ug/pZ+KtEaDcnMagUwAmYymzD8VfjIJpN/xu8eYN99tg5QbHejgRv4C1bWN5LMqXMWLl1N734I8i9G7T/8FfAqjUfLoMGP43Y7CHwJ9If7wYx5w1TPrH5If+sZSHo9yQfiy3Ap9hUKm9DcUfD4mB+oW8lP/uLB1xvo78jt2Ox/1yl7cFzrzNfl1Db1mgbygGoN7sBCx06C3sCRzbhvKew0l/zze+MOSUjIxN3Lt4NfmxLpfiQSqL661aKz+10bkxu4iU44wp3fu7Faz212uBljbIWAdB4tKuQSLJc7t3cMHUe5T1ndUzw/yE82B8uYIUFQeoCyFbJ9QSdUBwKZIQU01PuOKMwhpeMVRxTXUVS/Y4Um740lLJ4nqhbApLkVN9Tw4lK+iqvh4Q2q7S1vp3RodFT5sntizTvdkvl2zvaeiVk+ohjYOK65ysqw3L4dGmjG58UDUuZeMM34C3f462SdEwQHhuAvYt5lx6lFhoLwU985lJdJ2udMyVn8lk/EumMghK24bXIYx9tlRvT9YvpfLmime2vd3kmCSPeQUPLcKIDIjIn4g6pPUKXp8P+NiUBnWe7Qt85OYmiXvTxRBLh5YPlDnyQXyqfwpl1C8LS59xyMjIjqK+X0jcjBIPDQgWljKLq4s0SF68t40kKvDoizV7EtFvJxeFpTxfJf8OuPalnI9lUPlPNpJClR2vI2r7GunQ1s8S3npiG3SgHC1BhtHZGVJ+DJmryOJoiQxzU2qwNJRZRV21FuP3FEeW+R5HezxpGSYCOzUzTrE4/rSt+8MrPgglzmDzy9y+U9lkKMa/qKu8gUp2c1OxCmiUmXtz0B4NSD9hYGVgFffyXr4btmtlVURytaAXqRv/vlhUeDBqaiWcb9i/49t2Ud8KngJSSW0fTDnA6d5InelHYor4+drZbtaYuXhTOV3O2KsgVTlbu6j7eMspamomvnjsmEHzASsy4ppreZHKKkGO4CbdA2ZP4tNSHo6dONu0/WAPlcCrsfHcdcOViBX28F+OpyXkXCL+La96b9ALJAvso4vsBphIEwbfOXsZzQZ67UtazGZUB/6woFnVRvJsaMeDwg7d1CcHFjZoQOUUxuLg3GTUYwQaMGx+vEOgFxp5Obbd+r/Octfp/0KDvRPYNxHVQMJNEIYqBV/h1GMbcz+nLPs7pK/zXHaur4Nw84c1BvHmg8ywqMKr/EAi/6u1ueAJhC97SoGUfIm/joj1nxQGALJ3uax5rkax929+zP7+VPCoHNEyW0wJGf7vfEgl1xd1fH0+3Y8a7uEJ12o2UDXGbHxgajmsmP5DwnEG2jsDuqz2aQZtPUFlUh5bmv7vlM/NIANpgLJSXXYd0DFzRSfSHTzJmBlXMi15M1/cTKtO/v68jTUOQykg/p9Azii79Sd0IcAwxqLM6u4xQ7hOfcX2/45AHjl13hdAD4tJn/+rOdNzac8JxiYDwqggPHEiRNgvp1DiUkHaiof9vFjTefiN3GZgXK1g3nagfxPeKSrzVa1wwkd7bfajBMWg1SSxZkYwRP78w1lNpHIPs6zDQ/pcZd1/eZIHSZcLbjWOpljZP/UmAzKT0VxilP1Ej/8ZgfmHopgTZnKKlAUw4hzFrIfLxOPHkbZqilrKSWWfkYiJUZFusip1gqbFKHgZREUxWGiOEodz10lUaK4zjocltzDQknocxnZFLdj4sOsL47HdOR3BTHucFzDMy5guO3zqI3JyTWk+Vi0j2OKQpZRXaCXgdwjjXVyEA40xQtKWW1EFDc5MTpGzJNCQ4tL/BEC5rpbFCjNc0OV0v/iyx9v7JrinWJ73kUpriZSpceCpsAgjuXEmyOhLNQcnYqTXUXEKGzprmSiC/lPbcwpHkfVZCviHBXUtoeY7wXGBN8UdSaOOjIep5Y2JPMRUpC4p7/fwEviiqlNycXo7ssFslqr5V9Kset4NmuKFMTGrzZ2FI+GatsFJZnMNmp4RA3P6ICrD5xNRWdCw5H4yrzlsmybXJoZ9TxGJbSZBFbEyHSlhbo4/lLbytyNr8LiINdsIJtSrqULUkNRik+OV5KslNNciNzL795eKqssZO/3Jn02x5L1fNrCflzAuAM+AXuAQ8AOYBRwA7gAHmAY8MlYhkHANGAVXAMswjNTZzoAd4ArxgLuAdcMC6wALAK+AJ+A96osYBZwuFzb1tzUlYQJhA/gk8kA/gHPbGwghLzE9E+eqQxCN+m/83T/Jw7158MOQgvCZAwI8KMswm7CCFzN2mw21JpYr+PO4QYNifmAgwHeLghOdrugcPMaiK4fyEJ2wVCA34XVAZSHyu0musv8BYgQxJM7DyGknKRMxewgRYs/wQY+XPeozY8zRa45wD4ZE2UtmMtdve8qSFixXCgOLH9OTxwCUpa7UJ47BrHZDkGCeWp+urHifFWnnLWk/hTMYCf2oD0YIgCOkomGc8UAD3gFnXlwpag8qGAly5NzwX5ga2MlerRddpWBG047YUdBGdrDYXUvLgA=) - format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, - U+FE2E-FE2F; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABk8AA4AAAAAMeQAABjlAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmobllYcNgZgAIIEEQwKvFCudguCEAABNgIkA4QcBCAFgnQHIBsFKRPuMGMcANsgD4qiYjAY/JcJ3BiCt0FdjAhHwWJRoioVqofQRAWsbcdwTFm4VHx7x170Z4aVJ4CJpSM09kkuD19r5euZ7pndAJE+GUSbimK0DOUJdFSEZVYuUQf/gOZ2v2AbOQatAoIgKJWjyqKqDZxgUqXQG2UOxPhRwwaUKqMwkjYw4J/4e2Ln75t5u0CpFnBBkkJAtNf/mqa7Uv9vV3uFpwBcAcoEEDXXqrQi6RPJxyQfIOEBsBN8zYds5+hm/L1wwAuo56ZGGuaybvxqbFuxZTAnS/sRUWKK/v/rLFvd+eNzxruVdjcECkLRJR12VNX6X7Klp28ZB/StIdKy7fAgVGHsCSpDCOn0KalpkqJqs1U2p09R1lEH4kj3W0SBhy50MQwQBdH3fCHt3Pp1dCIqInIRT9TM2ddeo9VlfSrbhII1+69FgsELwGYY3KRJQyhQglClCqFJE0KbLgTVAYhDDkHYsodw5AjhxR8iUBREjFwIBAYYAgyBAAkYZBdFuNVrDzmD3J+MxGiQ+5sYEgVy/wKSY0EOcmRfYiyQIXgJAiSgAioUVSC2IEDK8+CApWOshcOMwwwvT4zHW+EPE9n4O8R4YjyRc+wfj1/mMOPm8z/EQeO4zTFEkCJ+JCgTTAi+xBeEMsJVwiZxIZ9R18jhLPQE1MVJVGWrZxJziAVENnGEuE6cqhzx+/Q+kvMBhpgMOIC6I1IXiGI/AVN8lDHxtkVg5NXlVx29kzHyC9HfNU2febXXfdMGiHXGGOlYTZLlwZQGK5yhW7HicNFYFiz/Rm7fe4KmMxsrLhYbutMQq/FYm+9xKbHieyoxe9njc6TN73vdJ9SXHHMin96D/t6Cj01N3eor0kMf4IlPSjRwVNtipfVWOirsNjJyeSCuN9xREIdBkJ0zH8p0KrRL58eljZtOP966SHwllwdsk9dKbQMfCLBXDDZ/u4WuY/7Oly3mtNfrXYMVX2I835JLjXnLOgMbcQXEcoPy6UAji3rTGLWMUiwRASF2lxFZSXwp7s5d9akLR6PmioFRKE2stwzVDWr9J5AY2UnGLrLk7CZPwR57KVKiQpUadRo0adGmQ5ceKn0GTFiyYu2Ag2zYsuPEmRt33nz5CRAoSLBQESJFiREnXoJEyVKkyZAp2wlSdjZBtgkKrVPqG9Ve02qKfuMMW2LcOJPGmTXOvHEWjbNskHXj9jfuAGADO3Lm2kF9E9eE+NYlASkXTOu99JZkKjpWlK0pp2rlNolgZ31k6/xaDbLspTjwUF+STTwW3j/RewqtUuo71T7S0sqwlUiNCdoorijeo/SKcvuAP1avSAeRDDJZtb88QYp2Sq4NAwJMaV8ZTsiCKSqjWKY4PFFuL3HZ2QqZNshOgYkUlVJqDWpF0EQc/7k80pcJau8LeEMH8gTCFrwteCtwUe1deNI+3pIBClN8LPtgXx854ROESzA+iXhKuZMwn3TXlqMwSt+S6R3ZGcn3hoIiRT6+Up+Y9pkTBYHiPIrfw9wW1XiDRbzBayyyRTKAeQO+xL7gjVnAqS9kGXEXzG2NEP2WstLvDFtmrMikYAZzWJClQ9aF/XQAsIEdnCkJSKH0O5CJY8ghbFy6Lq0N2RzhGBBc1Df7UHqwNwisQnIEEqPkvkidlAGcuCAPgy4y7ZoNpmJyUjJBBSZmzGmk4ZKBbJyQHG6ifrIMaB+H9rj3gLgMUCEavWWF21r/k6MSlTiNVNwycGITgUFLUCLT1jhxmNZ6UsqetRCWsWDoNdv1USTyXaWFgrqBT9gVRs041Ev2TXDdNrn3BnZ3lFb3U30INxwjPL16c21//PufBCwKv0PxslWGfQSutdwzgCFPiAETpuTLbRdMVxsDWzSDD4taQ7xkZKMTR5CNDBzRq2CJEtEnU85mw7Ju0G35mcF3nQmRgwSPdMs2pO7Ddu1yFB60LfoMWT1fydP3ahn/QSGdCRsrYweltp8+6HhHuRAyMQlRDPyhNDYe/LHXGIzC8BNDw7AxM3gxDmQcCmXBQHVxUiQCQ2BjuLdKAkbgxY0HHgGoceBHxIdgleyyo0VLg/vwO4UgwggBQJx2OvDPGR5QyyH0QCxeWB0kn8wBACCTdB6THVEfCZ/R/IpsIuLCYQ/cJgQBN5vhjNNFAAEypNd1TI5JMGkmfVVpkFgXW09f5+upCB6UB0UDpOn0odY/hb4AVH/PMXnD637aWYPJwM4fDfwH2P++UIEU5CkgLyzMU10KNqzAceAYWIiOsyxHQfs4MHluVsmW2S775eLcMVM4tkCGm5dVs1W2z0WZucr1kVhDxvQ+/DN/aS4QhIduBi4/0iVedvImzWfb7X9+CnQrg8gJtnvvSb7td8CWcAEUb4EfPUIlynch+RZ4aYkMGTGWxIQpM+aSWdwSsmyyajrR5NBjHWU57Iij966Ri2NyZHOFVNqFia29wg1dGvbaboH2LBh8DqTjIG0CbIWswM24AJNgnOYs5qNZiREsx8okttlWK7DnvHVz2/fhIPFyVkLickBEfZBc4/N+CY/JOJtRWS5CwUZX2TDBpaz0awUQeeP9bY8lNubIafOXxWIP2PLD1G9ZQYrbLhwnT24t2+YrXm7MR1WbpXHCl7rWwPO2xRIHEyYP8a8wPDBmGLEp+fwyKLbNpSwijnJiVPRV74J1j6KBeE7q0KWje5YT6ecLbIkUz27p+rNl6/6jfxNaEHVaiMag54wjx4jioQjLMLmRQwzHuNDT7CBoIDmAJBosfost0e7f8LnyqhAl7l5J9U7ay42+DTqvdepWct6IdGKfLFYuK9xR05+i6UQ8LX0LqiJWcswFzi/o8pyKSzCdYvg9de9vb+CByFvsQFDLS/SYWE0p9JxJug4afNN9UgI2GUvEHGuQzOrsDcRGLkhTiM126adm7GYOrmQlf1zNyXBN4Sj3Rmn0CtHAjLpPJoTtyQNu9PCqsMhkJi915gvHU+PgfrG4LrAVBPVyxQ109zdYYePPpnm+2CK4ZjN/9jNGuaLnqXzZc5bVYISZo6UWcUzYh7mBa+l3lxxV4ZDppzseWWu5RufVQakjF7gsKeeO9XBsRFyLjp5HoXoccbS9Ws1iki+WL0PZXuWoMsLGhbdtBwciprdUuCjZL36RDJNaSZnmHQy7efi5/1uqyB5ZtIuly/aGFUYmVPlsxeSQS6qf/wIuHBQ4D1ZwxL0zqcWS+K/qSDI66UjCEvZzw8ddYgRcESv325ovZ4qWRVnS10/kHsX8vBFwb92iEJmoNHkbgEQeuy2AD0/5BK8W5GUjrsidxbQ/tWEdo9rlSlvia0fNf1m9uB4yju7D3KG+yOdIcxI4JuZ0F8/m83xpGEnTWuogpuVfTClRXpm0zCRl6qVjWWyvfeiqcyru7faGruoGE+2qDrg3Rt9fTly2dHEexPGMs8vkWrsQ5r84woqy5tT6YFoB0z4lVh6FJsuWW1vGg0V2ZNGW1q7KV0zneTpW9rAnsGHh7IQXPkbPiKaSkF5E1sRjB+SXFMI7I4vCUfhaULnG9OrRtvUOnqu994Ex2eqY07byfIQ0/J5cNJLDvYlDn9uwstcq5TEW2TPRWYlMxd7fT6/GUsz8f+Wu4Ol/g1A0Oxiyo7445MEQ8TUM6vAvpw/XKW3+owMpX51Y6cLlhYa9NJTutLOTHCanFs1oueVK6gUV2g6db/JYRZmSH75ocFqrKgOyVU5nLSmf5ZFvssuVtQynrXfvVdnPIZL+sXrsUUgSEsLf9U+JnBHNw6qyYiu8z6GFzZEpIp6mxkX2vrDqsBGE87jKoRCQxDJuySF3MbvkgFqNoz9kEq0tNDYSjPScGEnzteUpCsOwxM/Wgv6S6iBbu0J8y4bKAp+/0LfFinGJPTZkUTZJWS9jS8RJfNFuTYFE/dhUoERlbPF7vOId7q4H+XuAZ97DhngDnsBPs0xd4kp724hFfE4jPlgwGD8ceDrrgfR9Zpv0NPN+p9jSzzZoBzzz2bfvd9mhSTVBe1KkTt/Ovvfv5UfdNm7DkxfOZhIkjM9LH604Ep1+LrpwO9gcHxF/L7H5HaOdoJ03XKRBYlz7KIIRXhwQvdJSXXF7jO9P/rf7Ip0NF4u2XQcjTGMa7nltLeCZpXWTU2lgnw0DjS8a2YBnshNfJA5A2m9vEVRvMAcI45tfxudXnj9iHzl9jpZWUg4nQZzRcfur7xOPnRz9aECToyu9B3Eh5o57jFfvt0d9Hf6gHYvVpTumqij+Ol2+LLAvaZ8pNCK0Mi+T2kp0kScRE8WmnBcvX+NsKzSZ7kOwo4LdN8cEMRtRfyYkUNYwL+YvhOtRh3ijYku8a4NTxMWfrjUeF+hFZ2j06gJMMOxPoUwBntLPf7uTdaEgb07zVnozPD7zfDFEJ0zn7ezzx+OvYQdjoR6RfQnyWySH7NzrDY+7zrUD61OXS0BSYkJQbpA1yyGx4p5bavckC0tfLZd1I6/nuVV7SFu/KHZ+6JYUAIcEnglIrUo3Zv59VnB88pMQ1uY5tr7z3tnAU3bqpvFup8YoSUPxlU38JRK8hLxTF8AFpaIPJZRioo94ZkVHgWAX9ZbuNkO1sp+aRiZmTt0UCcVYLW3IToQXeMrVH/734kzhc7Laf5669M1X50qekdX+osSulvm8/OZnDzvbnuWdaZ0H0zf8P18rDdyPP0xCAb/QTkyLPzd4940sx23srerJ021OZXjH0ku5NROgulPyYLyjqD7DyTbJPvfVrWu3F3vLWIeyYwJDEtyszSPMBQ0vuTimuxV/uIrSHnrFM/xRnPfZ6MSIo87w4+rS2bkA4Wjpmd9lv8tmo6UDhGfgGy/f3b0Ptmm+DuZ5Jm3BXSHgG35wZ7B8jOgu5SHgcPFSio4+TLjjyh7q75PAA3jFJVsOLiwqC5RyZzMYJdzNpemVVgdt91vZ2liDOZ7SB6wNlDCPgT0ZTnKUEQjN37Qd7LekcD6sUclZ51/uxL75hpRXVxaVIflN5U0VZ5Ra+txBfV0k2AwY/8jnBgs0OVuYv4YteqmlthJ9wot8otZSMeb/0dm+Y2pFPMfgl4YfIKvPsUqAp4CYCe9Od5lLpwsR49oEb46gSI1PnKs7BnQSJ0388hprc7Jrqs8gICKjN5LGDox8jYHXvf3w8QVWqWakhsUXMKD7ZovLr6A+PzO58twZDBwIoZCZ9buvba7MY55NDoxA5elcRnuzwh024ClVdeHAlfYBXmCErTwKwgbC1JObCVH6uiLfYrbue/eRTy+wyuHZ8fQuyfgV1lVmZ1Xl5yHgnRDSHyIUygZMmk9EbDDPlGRsGOAF+iwfpHwTvMS9GRkAB2hVNVXsqubqyuVPW3evvaWlNaez0+toaW/uXpWgI0ugZ6GQ3Hb6fPblvHB28tFbb0PPrvMs3A3Jao5VAZetNzLv1ou/hp7oPcFOulGVV8sqTgcDXFfd9WJM+REw32DiHghUnAoUoDwQ7EKYgHdeFgqnnJ8n1AQKrtm8lNLs1Ujy8E9X97Jzx1d6YiPUg0/IukvitGdBJ1dCkgF8lRWczS2VPFwVdETmHuve9lby8pfgsq3gIle2bh9hTQf3LLx/MjK/2C8exgrb3j/zeejRzKe7wLkR0np85/m3ruwpwKFcJs5H8grfcUk49vfKLOaFHhek993TugkiQsyMNhj9/upOBcbDmIfXGLFS/o1mP39VoIvwy/Ry9FzCLj64j3x+jdkDeNELnm4yfgWKeedMs9w3plC6KHv5EGolsgW97iCsAf9GwOnJtusXixquPOJBlgzrDL+NCLAqWqpFrwwIL4pgPjI5Wwo0B4sH8zUwjLbvEpvi7yGmqc6ObeGoL1MgPBg/MuG9UTOGeVKoTWq3/9HSdewVtZ84RInFSoyR36+NAp6ppvE7h1FfAuJG/DWMUpBL+vt4nfyS/3zK8rOcogWS9Iany9/iH3vPiQZYG1cdiT+Xtf2MBEOOcVv0fEn71crT9TebyFcbhs6crR++d77hNtRSW+beV5Qc9Eh3kwwQTs31KV+ofaSyYKWenOhi2/R9T+kSTnUD9w80kxrXGlnUK0CrMLaNOscrQr6G0s9No0ZrRihMqaz8suFEyGZg1DFDm0FnaMrTn2kqPqRXwv3H2Cj7qGj/K19OmvJnUFqjHEpyDwmkhVjezv9yvaNvsqlyv1uGvUyPcU/5uyvs7tWbNbft8uIjIo8H2HpF2yahNYM9ONDMoaJUVEhSQwilosLw7PGpJywqaygjavDVJcKo2hcw0aRSWY3xQmX8whVLdNwBurkHyaab85/ACGyui2AtP1BRAaG3AtnCTrt2odRlAHRkZYRFZU2vTKOAoI2rjSxqCOhjGVEMlBFccRqCiHzjWrdc/o6i05bSvrfHtXYtjYndCrCQvIS2mW53uTkmtmHB5nt87lWW8Vs+tvnh0/16qp03j3dnUl/zFxlmnpgH0j0qi75KR+nH+WdbTJWhl3U6QzJ7eGoU6TdH9+NWFrMzJMVZIBRMpefRUfo5OovqbAJUEOz6J0+vGsJzdP4JkUXqZorYLWS6u7Hp6V3WUJPp76RKgfCESB/P2MQgBFzueW1HRc3KqCy6rmYl3NCZkP/XpU7cDCo64sr0SWm/Gxw5iVP9IVmVujlz+mzX0stWZmj+2dC087e4GiqqyniKy5ngEosTnCVyDE3x7OBcJNVl/Xt5umicROabx86iVBSV72qZF2c8f9DR+jzvbOs8GCRTqaxmkf+MR3zsMNnYusiy510oPD9oF+XvDnJhnGEZwSCniUpgMivuu2Fouy62d1QZOvCWKNKsw7yl0sMT4j1P+cnaYFGUUcW4hl6TAGtaUGkawYOJ80lrvRsY+wKzGyTqk3/M5pbdXJ4nXGESwgtOhtPOM0k1ZVVlpPqqy2C4Tq2RuIGZ6Cornei+iZltdBBuFhCsfstATOlOzqRDLdwTwrzdGgkCIcnhrg4JfoEALg0r59Fa6evYMWZF5Ryrd4hzhZNFZbXfN+8u69Mk4O8dRh/D3hYXt+gxfYWVhZfQS5paa6vPQHUKRoM9qGCmJYrl6FtfP5dH9ihoyjT+bGRRfxmgkGlaE1YQdtagGu3VZbHoPrW30Zo6lNXYhAv0jXR19o4Av5AAkXVx5pccJGgR8lhWMDYWBTxzWNYiIeEWSOd3FNSZnwmt4u/xpb0Dzt++gMvpH1avRqouU149q/iclD2cMZDTWnG+oO5wnEdFZmTI48xAelyHwNSHCmxi3sNjAzl3quhVjVkz5clgKPbLuIbzTmm9FxT7HCcHknVJGzE0d2rT9PyNRUwvDL2Q6b4/iPqb9LrL7j69Wya+Rn6Wseb1+uQDvEDz/+D3t1nlz+72C61d7eVfk+O/Mq937OTVRzDzEIDWNvcQM7Bkkvr2p6ifA4mwmVQofgXOsOEp8LlUKiupSqYUSVhAzE2Jk0v8ISWJJGhTe8VrHzXGzYiMR0p1xss4GB8jM4oUMGw23kNT35gwE2HiUqz7Ajn1AtCsv4cnW1+l6C8T9Hek1V3bkkI9ZqLrxxeIa03HLwTeen5/UnvZtU9Ms0CH+2FFW/niM/6DmtxWf78Az0Be2xJ0gNzTmrkF0onCjGlQbd9ra/X1PC5MnaBMnWj/ZaXtYdOXGW7FbW+5fBOWXYKPraXwD2wHzUYdSqcyta9LKm/s/aTDCzdtj88cqWncJT3gmxZTcj5nWz4Ta1SD/VN5wys+mkbe1z9L1Bb+HqyZmUoB1J9g6fr2rQvaWFe+8qNu1M4H6WC5F92gWj337/8eTB6Wfeey8sWurcxhYmYIy7btimHi80eAavaoIVx7fuwZg//EiR0AvFkeKgP+Io7/Nif/myapdpKALgxAAu3RAW7Q3WC1/D8gFjOno904eYKdP/WCMt/2mYdvXy1pk/fEXdpfSm5NJK3Fab9/t9FsqcuNvnlADYHeK4N3GsZTzBjyeVbkP5+if4p4zRF5I8Xv/KRwBgkfdyEvmqxnU/WJdHySdOwNnbsFezZY1qeY2oeh49IYbRfmcmm6OOpvc9umn/126dh2KktgcxU57bxrm6nifQrzzca8FOT7Refi0TdY6Xu3WyvKY6IFTIna4+XCTFG+UoSGzH3q1IyjmmmguEtqp1ZNq3HmyO8TwdOrn9hD2E1Xc+sUz08SV9sn9yOyEXxPzdJgKhMeHw/ziAbtvotpeCb+eTxZkKZTpPhD1bS7dGIV2UUmgdbkfEzjFRKBWOSza7DliSY70Ptd+AU2n7smuwanAuHt4A9VeaPnh5AIBKISq6Zws+6q+CGkST/H6qWN4MsVZQhwQyFhzvCs9HSZjTmCf6aOUFhI7gLbAXcwgpvvwRi8Ipdj18tx7WA8OekHc9iurpKXMxbzr11kNIoQJlwyKeofxqQmyNqiuF2PFnL4/WIFUSbTBdEZR7VMYlWIJFaJUlsFU15UnMBCshCpMCk5BZhwNRIliZCx3lDepkGHfpCVOjarKA3hzjuKR6VCLI2UDYpnCrIoRKo4iSFUKGILQ8TGpKSqPGQ/c5af4KElpRh/kCosgIgUbAIAAA==) - format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAALsAA4AAAAABWAAAAKbAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiYbIBw2BmAANBEMCoIYgXsLEAABNgIkAxwEIAWCdAcgG0AEAB6HcYyyEjO2Dy0eKLv4XvfsrGs+wIhEBOHOERRRTI2158fc/aln0WYmSJq8uTRSIgUyIVMqpfa/7uYHCqzWDuHREj0f5UuuL+ZAokTaYgiIs5sF5aUutjO7QhBlgMaYvCAIIqqoCggoq0+HjRlX70MGclDLyR3Z8fb0q/ectzCv30obmLesvO5hBhRhcp7kToaLpaRXpL0htKmb5C3rIgzUIwA1fnqrhHSbqXhA3v+sK1wRtcWuhdyg9E5tGXERkaAhroCGeNqCnJxAm6m1Sb58SICvFhXFWnVAAWQoYRjYADJUQQqIYm0uSZKkfpYv1sv21dm9b7kWbV6i3BQ2Z/sOf/hl+ezXH88LRz75pnLuq4/MO/Zx+eyHc3x9VDn3yfx9n1ILyusq3ps75y90fVZ657PJ2iXgF+odHbvzv7Lrm+uTsPR0WJqYcelN7180rHDDnbeWbrx0QHht49uXjCzffOsd5RsvGvHe4yF5o+Ej97/ZMP62+Z+3Wz/08CtZ/FezhpdvG/nb6PMhC9vNvHFx3Du9X47etewROuONg4L0v2eI+L9X7dt0evq+gNihfvWttiuWK4f8VmxWBM/+WK8b8F6Y9evfLf57r9SjuA2URBAobPm/Smni3y3+n1TqgQEACsl5awAI/5AetjNp65A+/38vDAUXaayPL4CMKHYkEFC0DlfIlbAMegyqlmGU2eSTO58TTHX2xLyWvlczc/wY7eDo5WxlYenKyMvNg9Go5MAatqis2Jty2oytLaPupFxOlsgFObsjM05dBxMHVwcMbeFma4xFh8jZxUr2e62Th09I7Bd96I2RI3gzYzqKcsHjqZzGjsamlojTwdmCy9bKFNm7IBcudRU5BU09BQ5eTm5coMaMAw==) - format('woff2'); - unicode-range: U+1F00-1FFF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABMAAA4AAAAAIkQAABKpAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbjEocNgZgAIFkEQwKqTygfguBSAABNgIkA4MMBCAFgnQHIBtLHFWHQtg4AAgt+xD8f52gxWG1uR5EatWEsKGGtrrROAfbhgbsqkcTXk+8cSb2t2LbKz7fybPEC/ukeYa3NyHy/D9ptl4bLoAhSAAYADqGVSx0WQHh8fA07v9/zew9c855UgO/QqKTM9GVxCaWLiSi/R+i08U+4Of29xZE90hzRJVRRI2MqR/4UtI5wcAcNqPDApToUSUYjSpcT+QXXn5a+zaz/t9buUVDpmsnSVyZE7W9V3YRW6gkIqFwHZOEz8yZNyAkBtwZfVEjWAD/BrYL002IehYA///at/ruuWv2EJXQqGQIjZBoM3fW3rxv6/Pmr9n8VURk8MZm0uZNVBEb8CpidRMVQqs0Ks39/d7Xgqlu7zjk2DtDHDX28bUfHg0KCwA3QGEkSBBCijSEPHkIRYoQODgINWoQxx2HOOkUBJ4+hKFzEBe4QyBQwDZgGwRowBZSlGAuvdzKCWRuiw0LAJm7wrz8QeZ+t4ggkIHcd0dYELBBsOACaEAHOg5XQDmgtY9ggGOdJj4KarR21W7Qz/TrvSATe1mvCVRcGIQsiPhIjudoTloJ9TammqzPCWpOKuQ6axSCCp8HA/KFIYINo9VM94B67NppH7YAxm/eIPgij8SuR9/C0+8g3w7F39v8Khj8omzm0JiaZ7l444qvMsAnstouq7pYcvKt26TYqlOZOp/mJ234mjCY7oC4/Q72ir1cq9LY7kUvhugtCr+ZRfcFBtgx2lKDfxZa1hkGB1THTUvPyMzKyc0rKCpWonSZsuUrVqpWq56+kamFtY2tnb2jh5cfistNTLY41vTWc0Tlt1JiorKd6v7UNokwHGZi9R6uH6IMq1ydMgn1rlpfRdJRmagylrRQ9X8wSrX7wf57xx+gdCNMI/I+t4wYHQHKxAGV7JALzIgsitkVtyrpMGVL2oas/Zw1BTOKZpQsK5tVMapqTM200xmXh7ezHie8Lvqe9TvhfxYvsB+ZkbItEy9nU8F+0X5Jt7I9FWtO92/3vM743vO/hxLpkbIrk1DOthIxZQe3B689vg/+D1CBNZl4BWuKtouuAZWi0czWdTk4ZkdOQ2FdrEOKceLJHzd+0wWMrsyKIltHLuRXgyFRKyTrHWXsjlU/FIkacrKon6Kntufn0ETrkHjtUzZx0OTqC6s5ahb0BMBjGGDX48uHpcSXF6uKK0JchdfXpeg0wFjTPqXa6SsWQFiDFb6Luektmdq8Z4N7KWCGjUUnqNY6taI0wwYMwVS4D8YXV8Vobo5NszGGXZSBIBHg1IxjKHIstSPR0KKPlhFHzFwyLuwcF3GBi7rSqWIQgkywQkGgLEkLqWlaJt0CsSUNvS5YEjCWsAQUMwYImNwr842jowi8Y0JM0ECRu8FuAChFDxQ923Z0unuLcwCxjCQA8YcZJC5aBgzsP0q0DIqgBEpsLDHu+aMk8qmWAwvGG0MDtMOyI/ED7w5w6K5Hip6vuNrWFPTiRkxM+Atw56KsgxjkXUCePcgnLgYd7oDlvukRcYy33g9gg0YTz0VG5AUpyNEYAzEa72Oi/hVP1PefFflRGw1BicF4d5pl/fn6M0AiIr/QgnXf9XgDCB4AABE8gAPE94GPX0tAW0dXUMjE1EzY3ELE0krUWsxG3NZOwl5SysHRydnF9cxZ5fMXVM6pqqlrHDt+4uL/Pd3HoagcekDvhbgCTP6+eLs90q6MoH0XWoC+krZxS+EoCYJFlnB3fDNhsjLv3F6rHRznZNCbKlonoDXRTkarIDSk1xxI0hACMNKSaDkhRJiO8/HtVemw6+9IFsLMf/H6jjqkCdNzYE55UXgcEqNlGh71xtqjUT4WUtgMhAUsBp1IQS1Z/FgqgwWjVjmi+W3f/f3MKgU+hVbE2IjswKEiAju0NnCsyMZA2kupofZawvnCLDaexe5ahpUONJt+mt5el9lAKtf24NHBRs6rzUOs99eZy/8b8GgtZY9MltWmGGuqj+p9Fg9n7M5yyy8gvzv8NNEfh0dgdBjGRnFpDJctsFewLwYJITYh7PBN0BrrYwbxY7/h0QnPSolGWtH63Ue/y4Z4EKp+1e/Kt4/e9xUUWRKeRdCiB3lzJEcBdb2ZjENDUI400MCh/mHC5jzQvUVwyqpzwwIoJjIWK31xHDHkUc/VTp2lebQ898VFDAKRlbHESclgpk5H+xb3iviP8hg4P5KLcqj6lG1B1KtVaZGdLcf5Umbu77GiUrmjP5L+yG204DQDTJEXhbzQG07pacEr9XiMQfxkxrYhqKY4rzY11lJf+JFPKTImoiOXyHnnZrg5BR0L3d4MduY6f4S5Ar246Lkw5lRVaT1wuCWp83bSKgdeEHPftgFmimisMyfUZvGLuxp3hlw0i3MTEx03iOW+Ic3EXcoVrwRk8k2qJWNISIsyMjKGMSK7fUxrNZ5lcpxFlebvufLghpowjgyFnLLWmsyDxh/UChbdWgt5G61X1rjeMh5x2yMGsrD48ScfBTnlD6yvOH8rk5YsyosXLxnL7PnxlMo7l4Hy1a9w0eUVuQFmw0navrwA8XHJL1Ot6PaQyD4MlRkRrLHSt/9yWN8BF/hpYvp6lpVr8CjHgFtpvfx47sCIA9uQ6DYk1JjXevTO1RRv0eRL1EHqelsRLT/g5eRbJefedI6L5bbPYyLm1kVzqnMoUbeOqubEM+Rsiuy3UzTtY6a7GqJ2x+yuJZ6rOkak0a2y+3nqY5po5NDaJxkb+kp70Fj05xbbMG8L4hcnpjUqbgqjiZ5bo6PDUH2us5/S/GLntZp13empNkvqa4E9+m6fcRm6h9UEEjanZT+VYOA0rFyaxlzEiIWozs524XDLVyWK9Pl1fl9ah4FaFUOaa7luwJI/mAPtbNDGicZR/xiXDklopOMBv2gyrXdXex9Qr0QP+Z7EOLlnlX/v2716wJK3/vx9/2Zw7lmfQqRY6uv47v/z61fvMWl7dsllN+NoRXRLJa4XXQuISQ/IFgIdFCkaM1tZCVhyftWHsWiwi4cO0hypHbDk9rC5sA6ILo0FAnUNr7eP/Db5zbpWokwtbhUEuMnC3XVr88cFez/J7iFMLc8XHivhuHLyN8amDm7M3b3jrBXu5JGPTxvY5dVPZOvQ3iU/pL+XdwoZ8Xufq89w/+EThnvZeuOtCPoNV9PLt1yoL/6/3os0UoZYUL/B9zSevPLvsRwOjNFRv7lUnC2rzUlLrC3PQnmCeSTHGGA52vLb86HKG+QMEy/globeTcxSvU76nFz+ODv8bhE8x4hTU6IeuaLtoumWzMCpCv1KqRw1aiJ71bdMOCdTffXPXFr2LJvaX+aqmJ8L6XkzpTvxu5Hu+Z3JjMzbM31P781kpN2dhP2fbF26LXxG+Ey+G/gWoHE+jwsIuHqOGOD/SAEXGHBtecGA+xg+Fm55l0f0aReLUfB36cIuJN/PtzMbbwTsFOR9Us0Oe6Kq8jgsC1qH/UcoeMrg+YyB+S6mNaUNYJnQfRxuFwIiPKnNnrQpulJ9pjhRb4jlaIWcZvvt/QdyXuT7UsfJznqArbDiL5ADLVQ+tgR7OmE8S5u2vuGwd0N7NwePjLYynPv9fCvaVC5fl8a/9jwqLk1+KH6c/AaiK+or67Hhup8rP2M1WAqqCsCODTpIjOZ0X54mWzgYaVZlrfyXvWC+YJIzWjVDUYRjUt9qUJCW/aOiKuvH39Ra9JPOJz/RJ5X3C67uhJvddHmJauw8Pvu6o68BTf8M3TaAz3nxon2g+J9F6yCouTOW8zyauM/cwVZ9/Wg7r4qF0EFY5WGTR23ztbPDrbqJAr66DlggpQmUCqI2ktc6vji0/VgJ3a+QzRG8tV056+cVrX4rmJIh+aeKVPO7PFMQ9SyxJlrdz2umkgo6VLwwkm7DSeVJPbDIl64j1L1rXxY4YqVb1OoeItSwZWgYP8ntTHlk39jq1HQvuWAJpMe7OzanHp93K3bFxSkldiaOfN8deRF9aYgC2IaA2KZRgvcN75Rk/4DCTCBoP8vWuZRcWp0QlV4XgCoqcY65FgX0nOz/y7TwPkcmKQu8XT9bgHnsS+pg1ZP0pBNIdRH+qounqU4ApWSUCdMlWxr5eepG7hyNzGfm20202RIYdxlCunYFuWYwLbV6oDf13tRVvtTaYRBWsc5ziwotC7RvLP/7unf4GzmfMqzvKukWa16wenuQ8v1pVqNJlqd/SPI5i5qj7oKFDSxoHSfHXLyfVuNFTTpncMWe76upHa+Jqw1i5P/A4LibI1XdCWekYe3qrXSuJCExV/d6oZDBtRLgvIFnSIku72991A1DFxrtU/2J8RcSXMSt2Sl40JeI199ymJ/esURrjGhvWc/PbRqi1ecUpU8u39xPTU7fX5YalZZdyf2BydhDloC3Gy+vG6yn6g9FxhzmP2TEgM151z3aVuySwHNn9V5JB2yxpoK1tZS2s5Dtih37MuMoXx328qaPNW4RMsvhpDTd/5JumdXeztPWSSVFL5De8tqQ7AoWPaLUoY2qn57PHVMtgmM2o46sJW5F/Z5+lK9eSXBu7WAhLlI+sfhKNfKamhssA6acpIosveN6+n5+EUjJJTWS6kvNQBpj8+aQn+EP6O/P87Z1hRLpKNSqkK3h/+gMTznkPUgp7OwayZlPisz+WA+SYzYtq2PPnwQlJQbfKJt6JobRdU+SdhOyvWwn4n7HXNvNaYXRRNFYwZljS+MbfFAoifo5kQqmz0hCffns7BmxmzMpGVP0yv9MSeTBp5R00DvBIf+qeuJmetWnoYc1I+lpVUOgnV8XXpzkp0gvn2CpQbgWkQe5+eeLUoGrAJ+iNpBQ/+MlZjVSrCtkn5cWdKY6++aRiWLwZ/vXZfVf9+Jprrt43qhJpz969Jx6m3/YL+1qaOJCRsK3wkNxOQzXSONrr3rurtk6zL26j4kGDqDWjX96n7eT+hSzFivQGbnFixZSoefqaxz4y485zrlK+Yx03F4m8TWAkBE+TYBmdyh0iRAQ8vAOrkkdakPq/Qmhi8M0u2kCXcmHPJyjqs37TjtyEbUx0c2jqpyiyZtgmhf+0oHuDvKeutM/9PXrR9NGxC47vexqREJuyZ1PIkz8kzWvKEXVDd1PL1NNOfztk0jNacK+mJ78gm6QMKRZ+KngTnB1NcNLFvXJmkjayKXi27Rkk2VsDGX7JAs1Tc8QHOUvgNszUqrugx72JvUHBw67Drv795tVuNp0GyJKL7IBQo+uN+81tuhD3xu6vHTGL+QOQqJtokVIIXcILpcXgUnK/LFrW4HDX3TT5beTB1r/GaIETDHKldelz0df1E4ihfLpdfNpsN1NNHvpb/gsMZB/CQcw8YB+CgyN8yUADVvYm2FSNC2Ph4qm65UMkci0r3epgES22xM3L/qlEKluhrjZ+UuhtjtNV00kwiINsiMt0iE9MiAjMiEzsiAbY81y6HBVyBmoUWy9dbYTKD2Yr0XWr2h5rlg/oxWlCQI4NnPOWI3yuJbLf9Q58iIHcjPOrLZuXI9sE8MD1GCYo6H/uJorUZ++UzRZd6xl4Ii1s+Ae/gS82P1bbJgTAuPg1C15kJdLdvKYYzkvKm3QHph6tVrbmOBiOAwb8Mfc5Y/6oxlh03uQ1fufCXA5uPge1uPHcvgr0B7wDdpxXofNGVXbg358YQOfgBq8KlgZ3ofT7Nu4Gq/uNy5o62c8f/GsrYyeeB61HdvztNxNt9jXF+2qo245pWWT83VGKGurvyDxznOvPJY2vTevxG69OIj3OKdWuFvQaNClgedPvN5rSot7RCb/lIAA/fgek3NTiS5Wrf/p+JcA+OKvoAzAL83hv5/zn/GV6jIcWEEBNLC4f5MJYHUVFPfXgj5XXY13W2TwtHBbA+NMQilHrc8M9eP5KB3n1cDkz9/6LCNe1GDCVC+1utfTOYo1v+SSOc7HAvE4wytTlXUe+RkelmT2KhmFdt5wZg2jjugI5TN0qGeumPHCU7q7xqOJ9UhzbjgIzSSe2aImUZQz1ZW045HSAjNVbmaJ68W6Moh0bPPKbvJBWGvUcrVK7POi7FHLdZS5PIvFJUlsGtTUNGMx5tfIKPnxvE52XGmPglod6sU1vGujF1f5HGi8dZoFMc1DQ3NrXKMRyDd5I7/kieZBc6L5GLOyvpFHEmqF6iTJ732AALfJxsMJFgKwA3SoE2ggwJI3NCRXwI1AG45gcmk4CgvCxuiwMYaGY8mIGU4Ti1CVVxZOFMPgkNgwPx/fCDF1VbVssJhpsMY8wGt08yAPZaFfgYCgQ7MMV5VXeK7CopLyVK6oYHeGCIKUT2S7cAOlC67C/UgG9QblFo2Tmk7cJ202gUvUXU9OCF4lw2ihDIiQXHhAwktVwWGNoCL8amGvIJ8inPdkZW5obOMoJM5HlSraakb/CJ4AAA==) - format('woff2'); - unicode-range: U+0370-03FF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAA2oAA4AAAAAHqAAAA1TAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGjQbhlocNgZgAIEAEQwKpzCiKguCFgABNgIkA4QoBCAFgnQHIBsPGqOiVnFWWRD8RUImd2GxGAljk2gcqPUJjX6sRnWJIw3uCR6ILv03uzO7gQrfXeBCSq30KiEFfa2TEv5Mbw7wtEszkukgZUI6op2o/++etP84lubf8X9FzbJCVahWuCRlnD6ISTaXVKgpMU2KIFDiUma3cM5CAO9TYmtx0+R5cq20u5dkNv+cR87kv6onZPvCFF2VuMve8aZED8QKiF2Fq6okYMcadRWgdLWuFVrja5ge0Jp+eZyjhlmj1Dj6/FaEwCAIAIiChEl6BEDIiCgIcdQhEBhAABCAAATgRxQaMFSs7OYHSm0HE6mg1LEPngJK3Vpnp4MSSNf2RDrwgBBEegAQgAEYpMUI0BoBCFKRQKDI6pIgIa0gCov/+IGCT1qA6lfABv0x1N1O17/1r1GluCv6q17tAeI7Oj6jQYbBQ79pLm8ttupnyKl18VD9gdtyVL/0H+V9vVrv15/0StKCEEg8uuhjiDGmmGOJNbbY4wgZhMz6Cwa+xKEOkMvpM5CHYBhprq9DOMnoQhBrcogNeVVtqWIS5U10RjuioKoP4IvNd5i/7BJL4OYmMKEbYOaFDyZGoC/2OyDICAUSApCchNKV5IPMwfkO85cHBGBZDUxFmIHrUjERmrVs/cKQEpACckBumhzQPxetj27KCaIVBWqx0gdEaNjYvE4HAzAmKaxbwJ17lFDbkww2wgjbYoEXOtiLDQgDWQEgi6tVwpABTeTkTG8rB8JAt9ufER5QLGGKNEJVJIlVYtX13fXT9W/YFq1BGCJEqIhEsVKsuFa6frh+xc9JxwLa9J72DvB2fj7reannM54+yd7KIikOgX5KPllaE0zyFIy4cKAUYNwF2QBQPQDTAQDKLE3YYfYUw8ID0ZOAhRo/dr1wkebt8zGRjuUoNGOLCbZWTAeXBdla1qLxQ+/rW9IMTMKvlWQJBkIZgjL86fO/PdTzpEf8xB+r+duvefnrH4yiETPKkEGeJxsYe37P/vFSk7t6Qni4EPrdJftzKewFwtWCacRnOedfdRMNmxAKNTsn6Na43kdvRIwa3sfoex3ZZ3JPALnMPgp2pSAkVbFKbIeyQHwmbNpwVwiqjh7/ceslqcxrF6rXojf+leic8KIihlLCGavY91EOU86D3May+x/+2j/+38b6ii9C2Bh5VLNppQKHqegUdR01i7DQRIsPDLrnPKtp/rSPhT4MdtlwqxInVbaj6gANEgS6jm/c0h69hiqF8HYzKblTWlWVadWIMlVnPjrEOoNgs6zF9O5yV+0mOkODdf1rRElraARrybSCtdlnmXA1YhT7b/lD/h+hXTls/Zq+xnfW16W4zAshCUiV8nTXsswQDadaM1XchmKDvU2MP7cushlqHGCTlzHUULp8J/fIdXPT0aQdLDzMcNZ+bG+cR/hNG3hryBYiabqUjJJsvkqsPFj5WPCFUGd/94Ph4UIJe34vN7jyMmaQu9TMz3HmRZ9CeU6ZeAtgtNOMqTTgg3/ey1UmkjgJCTcpeX1Ym9qiMxGnPRvlbntO78ry9e+NlDbGBsrHy5aB8swZvnJrIHnHUJ5j1Jk9d31GaXvGs8g6O9tEnOt8Y1Y5v81bV9hmZ9jcPiLQq+kP7ruY3vjW9f8bruSUM0GkVKqtW73PZdTDYNmv2QTy/NmRB8u3LY9NLC4N36HdraEPHoS2nSV9LDQod5dioxZ0ev+nwLn2wQqh+JQ47Vt3FG1j9OyeqXOQ8n5Pw9YUIiuWFptA9+7TfbTxgJ0rKebEj3nRjUN+JTVeEhyR8GRWg7ON+0ZDRPS/H3MfPZI+2iAZi80+lB41xw99KvDPAWv3ggsTPF7LPtVbuFjbc4ka6R6lC/sRsWpI6qPpo6+8z2C6PzZHdh2d0maiZ/5yvQJrLqbte6HXgnHe2a4g5qSJ/dAw2Sz5rCtX924lIUWpKRASs2LYnyeTZ9wLyecNXD7ov2dTZ98NyZea7LO5/lbStKm7Z3dtvJs0eeYW+Ud17Vp6aduek5w6lnzw+7lblZbxJxf38DmI+2SOM9kKPm8X+CiiYsD8dC07ucq2i+ueOSr3BdKd4Zm/4jyqnbp+6PrTiKAW3xQjywKf3uTevaYVGjdXs2GKWQq1x1g23wLrzFxLzrf7AmX9tmz9uHhxpNViDHXG3SrZagv8PmySrmQ4bF7m0dNZRHuXPST12ZQZFyZOxuwybUd1y1/JX2XynNDyoX+eTpp5P0jv/wPPurNpU6dvJ4fs3Xhr6pQjN/z9uNbHr9WkjpHLnmvH/Ss589O8kaGK+f+/lTq/Zu5pbx9BHT1o8v68RGPtRYUIR0I30Gn3xa9v3lznXB/Ht+BeaI6/O3htO8fUnPwFWHUPZ8zDnQz6rx91G0ILi9/dqtRWR/zyfEOtroMawiP7uk3DQ3MUrZALlVP3WVhNVnLWaqZU3eo8ry++oWXN2m5sVObELzsPprNravGCYrTUqntD1sRa/2Ldvca1SlZN8LAq1PT+4p6n2yMa/W5huHVs4/K54eP5w2En54wmCra7enrTMm8XR8NVb68GjSfEiXvprzafSoaz38TNeOhwEZVlzU3hFaYxhI6iBVY1r1pum11oWwbf+SaNn2NPvCrtTrQ16l5ZxZnorJG2jLu1jdrQSkqhJR01PUz3/UVrjnVAY50nYmXWWOookdhuWLVU1UquFoXPhVBUFS2XyVlipeU9s8O9vF6d4hWsQHJFb3evzJlQM8Z3dxtVLVMl4SQLJ/m6uBMxswHVNCJ+xNRLX92d7Kgz6lcp8uCcWHxswbGRS/bLb1huyMnEK+Mtill3UqgsSv3z9clfafiZ+M+7tLfFw+epGDEwADbZ+CqKsIiD9CEAU7RDlxQYEiQRkCBLMAeFmcwrWWtaSOdkFUT7868oLPiQJAFg8HUpEuQYKl1G5pTvBcacsoMQGs4RoVVmEd7pX2QRnBCWgRHdbBbJSSEeGNn9DYvihGDyj+p2fftiEeOUMNK7jRjEeqhm0bwWmiyaFv1P9zBaMCwthvcjZ4d0MNpjSXGUY1GwFmtXSwq1WNuajoKxv+QgfoKL7dooYU65R/gwp6wihDpoFViZhaOZdCycZmEWGN7kXxZBu3AOjGhhs0g6hHJgZOIbFkW74POPanGd2zC9U9g1ogJsCRoBU5LTjGtHCLJpLnBJol1mCqyCG4g7bJA5WIkAkAfLISswp+IRTswpmwih4TwTOpkW4W06gZjJK2ENeXQdEDN5LSQhj64jZDamQhYOug6IefobYaJXBdgJDAGh6HTintAVwmxXXLKov6i1qD93mFNxiHLMKTsJoQ6eCMMyC0dX6ahLsQJXRAb034KFyHtAvMBbsJQhrwQmeIHQCBEi2slVYSdEIS1WlyzqLyot6s8t5lSoqMecsl2nUge3BVZm4ej8zVGXYtX/cAI1iBXsCL6ENAndlphT7hIYc0oXeITj+wB8QY5wCU5OO6OlxZhBfiU/Vuh2ADBSL/AxXjQHoJw2F91187W6qfeDMcTOrZeB0Up9IEl/kvO2HLX6k3lXvSUY5EHbCCFvddNjAQ7vaiWpVunuXW2+lh55IX2DReV1R8LlQas56YC+IEN14LV/sLVX3M6jTZVxt408LEC7+lBJ7j42HjabECTxIC/k2qW6ySbvVokpD4no/UXWwoDtM1j3sMbB3G7qk88b+0IVuWo162+YdFGnpIHJPiPtv7Kls7WXPOw32rqy7nZ5PQv2g/jn4EtAPLEqWePdIkqVh/HyeCJRnWLAGsUaSs3TpYH04LGO7UNYd7Oovpb2sSK61UyCzPe4PiXq0sCnFF9rL4pHebSpMu520WALaO87ZOv2jY5oC1GhJFZvsXc1toyxd1GQXCVps5xXoTQpx7wrzd4rSF9rUTHEkrTtVkRxq0/wuIfVC2phdQ97F2OLhL2r0+VMgnGfcketktGrTI80e28RXVARyj1W6i1u72W5aAECMCLTflw7uEUkd8nfPll8AODUtzS5AbgtfH79N/bntq+ODwXAFwMAAXY3bwD4VhVhbzU+Nl+UTjEbaQdY/P9LUkWRkI1sMjTZpcoZoPLSKM8TbC5FGoMxlSGkybG4ZSnCxXemyVaay87UmqfIaFQyVJ7FLf5jiSoFl7NprmaSJL8wyTzKJjOZCvM4Q4E/LYE/Rc1uZpiTjDY/0MP8qVvKIDqbv+hsrmC0Ocxoc5KxKhxmbby8AebR+8VvvYyX5vo4WWRtCIdq0PHA+8LbbiNi/W1MOkXGe8p7Y6TCCfGJ8f3l/WsNpYSx6VMytbftRXOfrKBa0T6w9rVl2NkYbhBgCjPYUPxgvFYIAgMjCiYE4EMHUIT0BVoCjgoCaEkNgujS1Yx3lUAVMeRTCwfDlxpEA+hUIINMCiBIIoFEspFBDx10vWgZyGQYkKSCJ3QmnVi07LYROXWVT7KTwtrxsACHINc1jEMLHzKIcXI2F1VMIIdUooVyQDQBhSRnemlZq0wfY8yVdDfO04PmwIsbh4JMzND2QJ5dS2DPHO2xIn0cLTIgSNiSSlIsCSdd55lQ0MYNZ+xxxANfHNHUkaUDyoLpLsShAA==) - format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+1EA0-1EF9, U+20AB; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAB44AA4AAAAAQKAAAB3hAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGkAbjgwcgTAGYACDFBEMCts8zA4Lg3oAATYCJAOHcAQgBYJ0ByAbBzazETFsHAB5cO4TRclghIL/MhHmoW/sii3JkCwIpmm2o8EQIDh8squu9JqOff+iQjf1biM+8RcrvTvece45JKlkeYjs6P9P9XT17F44fIAcwUEi6lMpFJE7/QM/t95fEYcIjIqRJjGQGgZRKYMR5URGpCKegjKkN0A2mNCCDHoYMKLNwKrDoCz0CH8K3PbrMABNLZi8I53ljHbl084I7Aei8kMtYPer3WN+IMvTyAlb90UTgh6oaMK1IYR1ivIDcHO5B9xTY1F62qQ9HEIjhNkz61vW+HudZavvL020NBMd6YD+zjgKcU/T8/TARaV9smT4+xfkBdsXj3TH3j2yfeQ9lg+03qBvQ9wBwB37GMoQVkRFd6mSKiXg9FinbYGrFHUTCLeqqGT3nsNGZAhuEBGRzNzvNV2uwkxa9CB7bxEPBPBXjjr+TggoogBsBgXLmAkEiTmEJTuICAyIahsQCBSwAFgAAQKYR8NumL32cfYGrTMzkhJA69ykyHjQuigsmQpakAvPTqKCGIQoSYAAClBI2A5uRIss/4QB2tCGlT7mCjUsgAHDt3LvJ0jCj14kSvTam+zU+y+Pv3Xvs/qjhVs3rWUVmnzdV8ecFzzauuRZvVwQvh3vqs7nLOxrfnPeVW/lOV12b9eqk+Az827t88kw5jsvffR2bnP20BoZ8VoqomU/ct6gJfWdrimvJhU8+eSwvFEuy+boVmyo2m10E1ZpqUNBlxlcaNg77hmfm/F2Ae143UrY0nAXzy0JG8mkuz3jZ5n7PxO34COVLwnYdbzneR5KWCRZ04BjJ0acBFRfYD3oqz5taBmtovX/F4+w7l8gQpiLECVGrDjxEhxCdViiI5LQJEuRKk26TFmy5TjqmFzH5TmBrshZJcpUYKh2DksdjgZNmrVo1abdBR06XdSFq1uvfoPGTJgyY86C62667a77HnjokceeeGrRM6+99d5Hnyz57Iuvvlm2YtWadQhzAxAAiwv20gVOjr6V+JlFgCSQjXZUKs4S58m1TGSqgoFAy2BJVtwLODKzaLk0n6AsaosBW45u1ruKoeCKfoUbebwPahazPbl0I6BHR0GODBweasY4TpaqHlDQUDDTcdmLiCALg2Ofha0WmzraagDkKks1OOEAR8B4JAr6WAfrY/0kI6iLLqXUtIyYQNGrJmnB4eBDnQnMD7HwJTA5ws0lp09SIkJIXkYrVQP0TT7AAqLvtk0SCoo0jJ9++W0DAuWyKxCY2wbcGJaPrrdHCSzI+9MAxKo6aPihqLu0kfR9FKykbJ7Had9D3ezAPEB1OQ7+B+eMNQUIkEcAdYfkIiBA/xVo+QpoyFsKJm4E9mEOCxeLY2loxrbQC+NwCo8Ijeg4GseiOMqCE9z4FptFoRiXgFVCeVflk8qryv8hrEZoJLQTLhC6CcOEK6r4zU0CsiQkQiu2h36YhHN4Bzli/KT66Or4u8gekPIuyrnKK8p/79hAaO7AI1yea78A9BjQo3rk2YHcD67eNPp/d9f5yg0ApsV///hqs2MXX1Fe/nj554UB+PkrL5yetz0//5zz3BkQYK/Pfuwh+CwBlA9LzW7VXsdQ5M7EwlanHsd5DRqZ2XvT/vbeZ79RfBMmTZkWJVqMWM+98NIrV40YM+4HbwgUQajeLQb4PyD+DTwGZrcFC78DxrdBvRfcPPTLN9umLdRpAWXkfrLYdejNrDbOng5Ojrvp62g4XHBUQRsmpHTc95NTokBwHxx+zu6jj/fToaiqf3GROhhTTEdiXY9rGW1LM3M62r7dkNaH6VCdd0X7eJs2CSX60LZ6nJ7e1UjqZIzWWV3tMeY8R7sis4d3aJ2k8Y79yZ7o8J50d7J/X7ozMiYxxI09WsecmfjcAa2VOmKOaK3DMEzTfWEY7j+8Z7fZQ0brODb1dF/90G51iQ6cio4eaaSSNWV5NVobz1ZxLZV0mIQLupNMSvdP2vopbKd/uPrm1BfqGEDBlXqWpHr+lENpf9pWxFVCbEcnqc6gLg1Ig0xSTQX4Y7Gm84Ki+Py/W5Wan13gh+0rKkbMpNAkiXUWchLPUzgqiTqCXHLI2F0bKKXc5VsFzYWJsRSpJoVTTWpNfDBAqBUlP8KwlBZSu0x6/gTu+Thhm5L83VjTozrvn+wK0J2k0gxx8d1+H9udNveA8ionCEr+6w6VTo2I1AZb4oLsMnC71Lof+2jn54a49toCh5ZyL1w8kya1nI3w3bVcQU1hi+casA2ljg0oOFVokRuvuUIhdB3jw2pRWwdccR6UCLOVeqSt7OGu9vfcpS4YiKbou0Rk81Q7bU0YckF2YxHzqMygngMbnTw2FwGkvYouIO+2OmQz7IsF5isedr6UELpy+ZuJZMD3OppCv1thaySckOHR9rk6lofOSaLnXKeFH9oImmol39KloaXX/BLPr1Bf7XzAldWt4jb8oMY21MhATsHCZir5gV+A/H3ZVWqz6uQLY8SRqia10N8d5NTxhiMknl6KBAyknZl1+Hc6hoSspAF2yLrktDDEEUkP4S5QZIJL2zx/pMsOH6vU+xbjb1yUFBsgbaia+6GinJ4Jz1NyJIKQi3qinfNSH02HqTDpSAbpRNZKJmGa5i35vnqEUbSwvZFmidKHa1PR9s3e/aBiy3eRsotyDm600fJQFB5Rr12vIA2EkqXPqA3/rYWgQTM1301jJa79AJEBbb/8fW3jQhGAKOLivlWMCTJwEwsDGSjiachUryUHmeJmhikioksURIEgbsHLKyRzMC0CmaFFH7J4+Gv9t1AxlEjLf77WlZCwMHzIyVVTAID4ekxNCTX2C41l0YYQmQ3kckt40p0e8L1vMHsCbjV9PfM6imxpaIRYq9FJPgBZADAOQ36u22ubThyoapr+X+rjiD/9NgT/pwIRq7vjre0EMKWEbw4Hq1oYjLWWKJlgO+DwGGIGexvcoABMn2a0cUDOEo6xeIZhGkWWkrYmUCMK5jSEN7e14mkFLcrJk2e7UFardo4c6pUjq/4XrvKAnvCy13lAa9MoD1P+L50tGb7cVv1oj0ZiLTewTP3/WNaue9+2uEZDMSaKg0TivITMbkP+Uj06Qv48PRftPIGYiTAQdA1oMSaKkLFryCvJipqJow3GeJZdgSQsFfKBXbI0r03OoXcWN/lpLiQ8xsMMZG3HYRr1RRId5REk0WRPGxKcrqUM76ad+dXnlFXe5axIrElK9DNqZIqQdcIVXj1G2DVNQ3GamHnfQqCjBxio65aOpZDZFJKql/XzWKiHbI8QLSIZjgfqU59tzb4h0OU4YD+Ido+KAw8WPiI9SAql918AhP3oNIVds0D4y98j36xRKFug9vWwMSSL4kYnrZtjFcI1IAFgdo3z5AChfSF3Ax+AySdHl7ZkuzzoyNX4NiZ5138FFAq9TrOOR6comDy+InOZQsFkhjRrGQBaa1eSinE7xANVwaCnnbFGVtehpCB40iCLN72ZTMpbi6CTfrVfE7VdhqP1qnSvkc+yQhv9hZCt3kWk1k04GLU+we1cDZdOLP87E535CsKPJmphHMKhxnOP3fmf7/7zbgUnXilNKOiL2XsrO7wga0ptktuqdo872SP39UcruBy/Lv9O+fcXlNERI/p8iYFQY9cHGZT0G75sZ/M5xtDNrRtFnydleurbSxR6oQ2w3HNX1VvYhjATcp1tqNU0jmwxlEiZe/Ydv5l/HyTuIbAfxUnDLLJYgOWWs+/cTYO9YycoJ0YByz3FnlqhgMvoiEOsYAy3B9/MMEDmjjnox0q/kfqgfG/UkKDGnxIFSFt/ThhJ4Oja23nUioF7LvA5zziW0keTniXxIe2nbQS9fi5f4Nbv/249Wl6cGc0pKMxLK6uEUyDf2D209L8Fb5668WFvnlaD9juIre1h0WoZfJCX4ipNNL5Dv67mbSxOUXpzrlzpbpUE2Vhb89ukfTc8nG/0zGqvRUePgHtZ2/3i/QIt3A6h1jIT5Frs7VIL4faOLuHWYvN7VxH0DclLAzclUevxG7eVecPzoqg/cNXZ18XRy/zVd8Hn9wvKZvOIPrEi10s/bituLc/Ory9mghb4FHy3fXG9qkPixVPGJ1rufAb/3xZG9Vl29uEARmZc5EJmeMPhbvzd9wx0En36GP/fsaqGKk7W/cpkcEiRuAtYiRH78rzDjgLHJu4zuAbYJ1tVvyogyMsXVx+zOy9yGjo62U/g1ZzCyPYOCfTP8+LlP7d1KY+Lqr/hS0txuyQmNKWp0lR8smaXNJY7ChF3sx4/VqGUqoyqLP9ZPAWTWguWRgnxTZ44+0cRmOYyK5gVoNT4uA7RfA7bN41H7sne+oW+wjYY/tjnE0ZLOkI5SbEb9khiTPilXrozjG5YqdT0E1uj+50LULN7Vuo97UcLg315lPI0gYAuTHBKywSFuojRAhU2bf1hfsXAt0cCnV0CMWdPxRbVzI2qX6qehYOav/7TGblKPb6HBzhoF6RR86cuLxn8HMINMW+c4rqzlj2rOgqYt8AZ/xRPWFHjZP55evb4nY9SaJdFdF3PxJnwfDd9i0S//JsStLlE5nnxMmVRAXp+DYRq/v24kz9FLRRMayPc/rl8SnlOIfmGUlPLOvIZzDMh1GOjVz8ReSuDlTfzuzzYX7xr2vOZt0DSazCTMemHypvnLUByzOHDgfmhmi5oHuCABz48Em9aWftQQk5gVkI8SPaRBk0U9hErfuzZb27pdUlCeTfV0EglPQh4a7T0bOMFc8JT3SkvG8fvpTwCH3dfBPhGEiYttXDutUenoUtHaGoENv0eby45NiknOj9TOPr68OTS+wHLGmkeCfB9JGx+1rmZxP7ukSBQqy7777PTxYtixP+3sNN/vygseypG/MMT7Gt+RC9qejrd0/qUfrrlEeygVTCIA+Y1wCP1obIDS1qMroCeqopToqesWaOXK8395IvBrqE3VyqGnXMPhUce8bOzirWS3HfBxzPdr/T9RV7edFBiI5mHCT6TkBR71BtkU8xxc8VzdRaG5haELIY93iY7p/JM3WTxJA70c+Pjj97q7JuBiVHepe8zd21YeB6JC9b1mwnajIfvIzHEaHvE0HsY+EbS0BavnVvHd1bCZ9Gt47umFPa8jNjyVM1ahIE/GOOkGrH9kKyGzhyYMjKYQQWaXnLO1XtOAM4nSDshIXsQjZ07R/JtoP9Wur64HvBT8OIfzUpQ6q2SLwurSyzGxbn5Guju/hUmqHISUhKBJkres0B+ZYzlDlb14u+7Mu2lJPg+4ukzyk+nwQIv5HmQa84Wv7syEuM1Edb5fnl2VGMR+/+CYURznzllLYyublUQSW2eDgskum8ZMM5T8zoSeCBDJF7hri8ksfm95j4vQ4paLnUwWa86F5/7xB/KjIktPOQxKFG83HeJ1uVJ9Nzv2ukbe/s9fKQ9xHV1Xq2sSHf6ciCflX4gkWHPcpD6/CYZKTzk5RIbbIjeQ6toFzsjr/LvyTIAfNoy/7w4U0wN2WFfnh25MFZtzs76+7ygJMZHzaEimzK3UDFkNEam+vY/tz/T8iiyb8CX6tUVY1nY/JgHjhO3Lt8iHBPl4fuFFWQKVvGqLpta+THQdtc4e8okA5+zyOFDxlbjqy1eBU1fJS2OLYLPMGkYri7EX4uXPBdEn30+LvJ+90eQLnfCeeXs+yP2sGilJ3fk7P88H6THI1l7s3b3abih2ChrG14Ng5sUF3Do1nZe7T6PLdUu+wpu2u2+Gxcn8mpizWJiAJ9MEqmmdc73Dt5A5kQamwfPdby9a3dbnh77UUg9ltPl/u/uYRLUX4TWrivnzbwkpYsyDQYX62EIr7Tf3yZlTQC1qrDYdMZ0VudsMMvvgw4l3c178py5VH8zq20RI/qYqPb49mvQQl+YR7W0DNTsE99S9tTKwjY6GHOh+EI60nzxEsfMS1KqLGDvBfRY5jy45WHlkyDUUrEPrkfcLjUXvtDxraYmFBec92+LC24v+QKsX0GjrktdWTuGjszJIf1b7o3807YCByi5DPXr+van26RH2PRMVH9jiMKhon4lxPpbHxUKLAEfjntJwuSC8rrb3Jv8f/JgahV9W8oevR58IO5rJX1lZXVoGy46jorrcsIKsVJTtEsAaW9SeXtbd5UZMWfO7h1SDiprbk+37PqlUZn14wE9A25++Psx+RqupX66YDgz3j678KTY6/lwRoNkwRb5nIJK0Iv4Ilxd2VbRVi2yvjURFKV8Ktvqhf+KH/ktLswC7ZMPMhrLRJrK05m2Tq4Otq4udiB4z4+yf4RqKbl+WclBwZkpHZkZQ5kZjj66llZEPSuLcEtror6FDRytTQz0tXfVMxVJt9kVGBAV7RtwsjrTGAzePk3IPBm8o5e8r0NxB5uYhYtPLwxRp4WaqqrsMrHSBs17m/uh05agM/lIhwE5y7YUsqNdWKidbWiwg3NYiK+1+gHbTfW1ltU18bB94hFUOWJslFwDtZxwsZXVUT77XNychcEWptdSfvlZWnEqOMOckuqS1OHUCiB63HdDWdXsC1yEWkGWSzoxDwkVRFm35zSj88/nsLAD02ufZ64u3ukeiT+adTj2eHUOdiA4xw+d7wU+tI7nVc8r7Fw/jO1/z/4w+uFR1aMK2n7MqDu6GDNiuqpnRi5/jC9fqNjdy0xL7ddBy9XFQOjrC/PWVjeDygnbPtXF+IF3l6eQWUMeYLkZc0sj+P5i3DBuzuEldbTwDJ1ZdaroBDIPJNrdT35P+BFP8qtat/NvVS1HvhzyefnWLxoW9XKpaqEUaajKa1qt0cAnyz5PehVOGCWq8YcS+Qnq/N73y+yiKj/mHkXOGCt9K+IW1lBafu7AuD5OpkOGC7saSV0to+irITznYxFpVLDi8EiyFaRFns3+I1HJkNPF60H4jeMdCDSakkb1pphTB6dXx5pc96cThoeXmOOqCmPMt3HryVYDBuUHK/czfAMCOjBvHL182P6wt0li6YC7WPKsNqtKvHu998mSmchr8RjI/pUN5+Ikg6y0WXjdK+sCcjosFlg0oCOQW8Umgk1d7vHigavUHqbVj6MFjCK/k3qYVl/+4qtdQWa2CvmD7uqRdwRMktYgbwZ5xsKUqSzw5s4S2MLIgyneJEoRl/BMdZYHGxJu+BH8DfaN0zdYNx7JfRL/PH8P924ZQk67uWoGnuOU0o+11J4FMsxLjt36+F+YApV75KCaBnTXTp5MZ3SUa/KvJbbHhdfE0RMfh/t7R61lbfPUddKKRt2EifoYO7sE5Ghwt3OQaw/o9RRmM7NBQTrpypPBpOP3bSlke+vwEAc7cpCtPSVki/S2Vl9dQ/2bxjq43Ukl3jaL8ySdgaLeyctz8eqA6ftHmaPHtux9t9/35+/sQHE/T7598C9++Qc0f3N7Q2FzE/nRDNNsJI+5AaQnjN8bf2J8n3nf+g47in3X+v1afwPDH5kfXdf7ZtfHzMfDa/4d103uGve4WrQdUdIafyrpQBITNrj7MHIP0N9N4G2z3li2sbrlC+Z/3WvqJ5HcDhpDztTENBxP1PvMH3bF9lCSYTwUCWEBj9DCq/1JdVd5/n2PbihBiN/jcyi/62UeqeYI2d71hLl6ustx7tt+b6y4KRYdsTlaIsA6JIDRjuoDiqIixpDwCAw1XmGozc0/WLx6pmP/qEbvIsEPr6O1MAaRqiEYS4gxFX6ComUARLZ3M9Bw7ayyU3QCljzQUQ7ehn+15HAEwnDalR1WqBKEPNxNPBYgesrCsVJ5CM9JgkBgBFBd8Gkm0IF1JCwtilOYgbiDtnqtH8+VTGg8PMOrNB4NBq+j1fCH4vlyVctO0QRY+mCvkOPxxCSU2MWfCTely70ygkpKYYH/Ia59b9gKppYalEXR6/vDUdHrGnCKY48PK69j9wCJxuV3QlqpWmr8JuzGcaIYlvZEpGwMsGpCLZYBYxFiH9lhiG2JfTfoD/EWQo6K6RdTRxKf3mFRQqQVREHDkg2GRSFHwtTej9w3MOhzr47pE76JV5zi8twkcQqTuQEmFlppPYyYllhBQPqR42YjQStkILp4HUIyjAON892A2Lt1ckphcaLnY5jjbZbeOYKGcseQDlOfDFUO2StuER8mxM0HwCR6pbmd89sbDQiAKfz2kv6DlyhRx2/3/IzhnWlRU7ajaHkAi2yPGWi4Ttx59aMOAFZI/6kKOVKmephgNZNyBx1h6sNzGS8Zjqhqfqdpsqiroh8lQNH3FezLASeMEXJU5hkslXA1GiRGu7jWeBJmp+gZi/2y3imCXkdfwxiwCiGqOIdTWCjO3vtHcQvrMCJuXgAs3dE+JtluqAa8TIkypM0119ofHXWNMdkF0XwVdCxVoLJTUAG3IOUOmsNYayM57IZgA0Iss2HJDMXMJGyPSB8jlxmJ23ioo8qX3ZeUj0KVieUSiFseWTfWAbf3NGR5LPwCKF2xLXHYtPeIbfWm1RVMU2knGBNzR45RCgrnh+lGiifmEsAoT6zi5pzF64EZRGxB4o4gBkQJn+W161Uxj6FC2yAM4aDsQADkoG5zHqSCdaPCNk8c6+yoLkh2RxeYYAIWiQTCvPIlERwkh0IA/mw60ItuWJ1vWjdZfGlGLLkUQa48VjhU7jl8aqGl7XVpdpaNopGH0vKk+nD0E8zHZakBL5c/x2z7fw7Ur42WQgfmroai7z7tq5Cew2p2lo3ywkMBI4zxlnYDuEEXU5+OfsiT77ACr1uWDwU5bkyc+16aE2Yr9y3KmcJ0MPx8tOiDoNww6nSWkNPyU18gF7WvvYcckRf6EtlzlO+312b9fEB28o/05PaNyS1icoLVjFtHjMG+lL+Sq2hyGhxzgqHuruaNhr3PLKbjqfXhxNqSbapIA4/J3FYaicpB2WpksCSEWYn4TULI0Z7numW3WvbS/AAo00eBcfhtQMRJSMxXxUkob3WV8OblfPkYqX0phdpvBfWluic7pWxcIjwUth1z07OgftNPLD9SESchO7m8dCjqnupqQxT03eBh2jdpNBE6x+GSipOLmBPiZCNW19K5zdK57051wc11GDO5hHIb5ZvmWjq5qJilGhGIo9EE/fdlqWWgs7vaPqopGDQ8zSXK2mvWaRNE2UP40rIW5DHcgiqS3c6g/WE0sgvkjxvAYlA/oN2kJ6eBm9E2+IJ6Q534g+ENjdL2M2+O6cd+cwWMx46WXPtSy26I1N6QSmOuoJ5Z9zRon11UfOTNyf60+HkO9AftCCaFoF034UpTfCol16HcHj5V13pxerwouRy2vpL8hGH2b5lXy8glodM1TAeTZaBuGlec3HyxG2mbAqptMETQ6lOPAGXNZd9zDn8VunXvPwTlZgDw5Z/FNwHgp+H5998Kc/eE9GZowCwUQIDxokkEYHZ/kzg5gk6f7OP/A12ENYj/gdyOYhpKywPaKn3jEtYgaTKzT1vRNljjGCamzrl2b3+0/W3KXKn1s9Y6wr1OIaYe+ihnX71ua/0W36EWplzPtAY6VPUE1xNC6z4hNQe5xqDHsqL42EeqqKJYVjuiFdY49FoiqPSjV4LQwiJUz1fQ0HYNs6SHH/wHf5FDu7MlT1ZsSB4z+0rmSm18rrVAUJ0WmjWU4rdzlaamulErO6hlofO1QGn8UZ/5Qgqvv8mjImuZoCxBr6sKCrq/WY2FDxPahiJFQ5zj/X5nVTpllJ30hylZ5Y+DJdBRMHcKmNuuxrKtzYKaD5VWomUmVWv+R6XtQs/HVKqanTUZIe2FpBuV4bqYghY8MBSXfuz4qy5DCNTb+6s6hVhYfS1NKNZAh3JYGcx2hgTWOTDlhK70Su0TIrByWM8MCawdVpdRtPtg/O4sQQuoBy1xt/dANpb7Rsu2xjQ4PFYUHZgrxAdWnVFdcWJZeYzaPH49Sr5a7prWiotzRN2a/fKaIR6OCjGEyOgieFFKNK8cQSja3C9ICG4SIg3xmyUC8YeowiUAcTUuBYitYw5AZGEUEMPDyB09YZZw6cFlYsTAsDjn43KE1gQSdkOfBwjwf8WkecNCABaBArUWHASYEQUNqbPAKaDkRYg46EURFedGn3Zj8GJpSffiKGKni/I2zOrfESijUKxoMZIR6NNDNITAzmFVpQSRe3RARaETtKighGrPakorRiPRbGaSVJEi6Gj0sHBGyWBKjpYiQRiIfEkSmlhKbY10RhkwZtZJa2OfXNqf0FzdkEQkujgtoSNM4pJMESOSjgSTZqQbjUWZERV6nbsuZw6s2HDlFVHtPgbqQUtOqseJAAA=) - format('woff2'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, - U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAACsUAA4AAAAAVCgAACq8AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbmWQchV4GYACDIBEMCvFc2nILhAoAATYCJAOIEAQgBYJ0ByAbwUVFRu7K4K3wKGrW3tQT/F8ncHL9WA+iQ7QIGY3GJUkUrj3IFSM3ZkP06sjHedMv9NTQeo+XL8dkXEi5mtV3TvoRkswS1PvHfz0HFx/cDSFHRgih8nVOR2BOZIAi8s0Bze1+xYgaYRSgYBIplRJS0iE1alRIjsGAkWlAy6A3VCpULDBpSTv97/drdv6+K7ZiUqElpjOECsXjxTtJXu4LVKFU0JqVsai3DQ7w9TQAjnRaM7JkmNFKD0Q1t3fVA612ZfvuEjbogAXTSEknJUXzBEV7339HpWwH/vn+57TgkghdV1mju01/GJHwqPb8nJpRBHc8Cvv/r7NsdYe9QYdwFHaZot2zZbhOUaWopCdptP9/eYwL9iyRRkvyzJysPYtywAvYBYgqHHuB0F2QK+SSoUuZk6JJ22XLEMM/tXSWzctS+qfbUuUJiXDr5OWSvtk0VCuqF4cKwiExEhsJjkEBMcoZw0pFCaWE6vdk2S/fBtHu1o3yLALSFKLEmx0fP/sRJaBwAXAYFDai1CH0uEDEiIFIlgyRKhWCjAyRKROCKgeiQTOUMT8gEChgCbACAgREDARY5JgzMPvsZ2wFYqfEkIggdgbJOwDEznUPDwIxyDmnkYKAB4ILP0AABSgI2kD+hwCiv4IBDngSZ/JMHtKGkpl/FpmVZ6mhanQZvWbl0X8MH7PGqvHWeH/WHNfHnTl2QonkRk3alDtVzUlTH9V3ZvK0pbKz8sxPfoNSUKksNL14ApJKyC8MavoEA+bzF/U5aC+5xSr75cs2HNKVts/XeudmC5odX7XbtmKzFbC/gvziCALnet+lLgeXGIFyyYMgm0OFPmqCH0BEh58gOkfOMvF8q8R6r16HW8AahDeurRj3m3Y5Xz2YJI/rRzHmzz1j/mRoes3uUSxvUOwJ4/8q0uZbrbXbZrtiXJ9aiGFhD/Wyp27pnnW5/t5UhxchJ1vvA05DexdvimfsTsUNWd1Gha1hfZ3RGliNg3gyu/GZtrtxp1jm7I0H3A3lULJ7vm4r+RYnR49v3GLbTryGNls7Ncvyoadxfxkm541y/OPIfWt91E8RSlZMKdN5wT7PAyP7iluLasu2YgtPVuWKx5+5WyGGFP88viuLa/Z9m7xQtfB4kwwFeaHhE1H4Gtue0hxBCT0LQwmrgdh520IrovXL/DJ9XMaRn9JmM73BHVXMU2Q/bKNeNy5ffV2nR0C+0DlS2th8BwMYOOw48BF13AknnSJJiiw58hQoUqZCjToNhowYM3OBBUs27Dhw5MxVqTIVKo0ZN2HSlGkzZt12x11z5i147Imnlmzasm3HW++898FHn3z3w0+//IZQzKcwlPFTQaBG0BJBCL4UIoUnBRF2iyeaNiQWfoAifnot0+81A4EhzsMS1vlt2mLfKw7tcBaWk7HyhipWo/J42pjAJKYwjRl5OZetYBVrWMdLeSNf28QWtrGDd3iPD/iIT/LnfOULvuKb/D13/HAQjo3cV/cqFDtckrMWlmIuUM4NKvmGWi5ZgmFS0NnbBPeLex8eJp+yqZdjUwLfAfGdkJwmyJkrM+thcOKnhbfsrHPHB+AGB14LLhTpm3Ak8h0li2d4jhdYDNwDhwe77tNNoN8OA2CI87CmECzH26V4lCkqUClv5I5NbGEbO/JPPH7hdyA7/d4wgCHOwxo52MAmtrCNndmjGeFmR4YjXjiWGXsH3uMDPuJTIBZPpiGgHFWooVjxBm/wBm/wRiGQnTEhZjDPb1kS2/I4YvcuYu/BB3zEp8VHO5pj7HrPsRVonLlFqy/cExvFqHe5/QoiueRwYct1Auu48h6JzKhi2/SUnSfy3IFdF9/dp9amDjlHZOaw6nwEUZZ0CCOcEEw2Cj+caRRYLASPUAj/QRN1EsYZclgpUkegR98+hqKDjKOHXGDlMBuJcIge5cTFMVnR40pVOaHmrxLG7JD01ifWvvvNEYoCBvawhwPmQIxQxLTPcfE6IcRJYUmIjaTYSUmQrBBy4qcoTkpio6z9VLSXqnioiYO6uOkJ55xY6FcEYhyAN5hjCxiWCM2qwhLvAD7DGiMCZ7FyEZcsz7JjbexRTuXAzpWJVKUqIcMciFsUMW4GyuzveN02B2veU4hnFrFZkiiHZS/hbEQFbNqB9/Y2xjufoPc1sfpZ30MnvPBu8OPViiCpA/g9TmygnFaPItLvIW8DRV6FcrbCReEANlgRgA9u2OFJxLEhxHn1CG2gwWygWSOErTjYV7AUOvDAb3BKRSjZQsm5jShWQpBUeOGHF/4NfqN4QQDnUXSCghV2w5LskAmRoGOd/+wbLPg675861oMgggj6moTt1PODA4H8f+u8guxz/XzcoUShqnPTuUERgUA/N9iTCH23Dklw48Ke1uil4vtpbPKUqdOEbsAw1+97ahbQgWXPo/WEEMG9Lazk6X4WWkLw5tAZc4Ay3dMGWRxuMmp11PnVgkDA365wWLB+Myjf1JwuD5kJFoAVdGJlYLYHBtS7xFrETtvl8Q24sK4Pb+D8H8j/JrexWOCx9jC+x9yZDLodd+8e34YelAkzEW0QSJzRqBPHbp8WKE04Ag3D/vjrn/8IwDOBICjY7yCUChxuuuUAAYL22GufQeYh/FDKYFxrPQ0RJXKhKwV/A7g/gglKETbXtWvTga5Tl249eqHEYtMnVphw/QYwMA26AYEogOKFCIUoHAoKv0MAlcMGwRF8tKEIqOEIEoExIUEeBZ8Xf736Tg/rnXPDq7j/PLNNNEA50az1m2uUzSGQeaMbOfJgQb+ty4JYR82ob7i4AfxcSrqsahM4GOsWw/7fZvqgCfLvA//A6Z+KAkKQuwFt904nNINoV6hiDRJJ9WMi+9vVATRh4YGlEtVp027IpHu2vPcfkQ7LcqNMludlcV2U0Cy0WGgNof1Ch4VEhMSEZIWUhXSFwoXahA8ihH/////tP8BSQurUa3fdsCn3bfsQ0mHhcd/VQnuFDh61jJBSsSK/tUE4RwnkCFBB/gXpkPKr8Xf6/97/ez6nrWaat0jK6iWJ4kSbWr3ImcTK95UrlguRVtchZNXuqvZxWJ5v1BL3wsnGPCpv3/wUqZ557oVFS9KkW7Zi1Zp1L5FllL0PCYpMn33x1TffZfkBgYKHyv+wHBANgDIB+Ass/Q6seSRA2x6UrwG6SpT6mCOw0JBclApUdzRUqtlDlYXWZoNyVJsiQI2kjIbYHS8vBF6IBApjOcZbBLOjAZAapRSdi0RlVEgdDPsQojfJMC2tHsyLNu+O5oPz+n1O4bMCZxOAu26FV7gFtmzdYJDGEES02VWxGbvvKDKbmzmgzfnb6TOJ1yYmO0NZL2UQyhNPvtKwDY2FQA3YSuqmdEKThQ7ALo7NoKy0NK6TfnMrmWM+Ax8Oq5wCX8W8ylxJL2vCMDVMrxiqZPOYS33ajDn4+VTaBEQmxKWY2d6IRSuMd6veGk5OmGB6wx1zANMWclWsRtZGKkMtTkU//jP7//2j5CfnWIBJMKGCs+qr+Sjf60+JacwbPcE3fGxCNfZnK463Z6AIXUhnLRWZJWHFFhkWCBS7qQYo8d+tqwQNhOvasubhhqVibhDuO1QTRp/CiA+qvWde8aFB7oHUPPZbNxKNS9yORm7IeULvrOYcQkSmBaqbjSbvvhm6UVFGu2IH2rvc/muVn9qolVjv7SyiXqaTi1KOtFn5GCs7MXahx7JpN0Ycb0XrQz2KjSjwHer4qDo8NO+XKCG9zW2SONSzjkhY9oRqG+G+c6N1beyYdiKYoQ1psI5X+N67MEHVE6hqW/t8OxROxb40I9OSFj9oEka2i2tIGMihToDCmfJeW1sLIYifk7SpUE2GF0NmQnV4T4Ba0EYzGhD3x61zNWhwHJZs9LwL75ZRjakYOb08mw7NRhTTqHj1USJZe5JGWJADe906Ia94s2GL852aXIICBVruhhniOuaQ4WS1D1kKtljxoKDbSZxrTitUp0BJu/Ink9G5lsQ8p4Nf/x/pVv8Nkx9Gv8/01E7Gp/4/N/Vx1hKdfHD869fHH8QknNNtdYFFJbQ7zV217bVfbSqiCvjS/tPB0MHKXb8+oiVd6gWgVK/kZDXr4whK+UcXfW4csTIjgRvCXXI3BE4YWdSoLyRc1Qb3R6UQPql6WZzxacfHUMizcbEbeqy8srH6lFvMkWSqHSNXyjdz2vqOWuR5LC5vLaPi/Bt6CBX96AYMWEoJqaF31cdg9m2U6oTb5KmmYVND+U/xSkZ59lLpDb3Z2suHblNfUkRanxnQ7ZanM64+572Y6WWMb5QdHf2c7DzwXum2nT5TD6bHXa51610RHmkFTyIrnC9IGzX6o5Yl4emM5lNK5pweC2UueQVv3Q33IH8yQShn8EUl5KCich9ZUmNKeEY5txrRLt/9WcrdLi1zK6raiZwyQm5G6GAblVJwneyeqzt1VqjSSfIrU85b5lFGaD50ABTCtcq5iR7nNKJlu1E0dxp26X9lLgYRLL+52qi9rkGHuCTuEfJiqtvUd5z2YqDuPWhZEDd2a6MAOVY2k1V5uOOS9zIz0V0SVjTg0VJJ7e9V9Rb+6IINUotrMcmlhl074e0Zca1btCobazgtreiB0ruHLg1KHsFig7WYevYAZVKMjVeXehrhkvOaryWu8W6UtSMTVeLF5U5IbXB4KT3037btwSl9Y9G3sBRxGMh1Fl1Df0P0CLkjtHXz2C1plHvcpy12CfmVPkt5NBnzqtUorppIwaPidYNnG7a24NW1BCgB3g3XloRYFdhMcTVzU5lBGRYTOI4779l9D6u8suB+sguMoCyhnqwNIZXOD6FjSV2cfb5hXMtSmgeaJoNT2jHnGGLlx+AovHoDk6gMob4H+Se2aAh5REtyqCDibkkbS7jKTptLBa73SwWnKHHRHCJU83Yd9VXgwxnF0E5/zsMed3vksZRhwYbJjFIr8ICmEMb6zqklQXhxuWa1D8VbI9ZK/tVuPdAJGQNOqAVBCl4u9d/D9hQr+4+27aaV/39YH8PW1Sn9arFqS5ikZZype7VLr9Ir8JtTbgp3r7mI2vIAGCmAs+FQT50iNFnTWAF9dbt/mQyfsANIAgzLC03WRhk9WYknOm0n3dMAJ6uCn3uIODyZBmkl3PSa57Lh1QSSTbZJ3AWyk5tJ7OeQhJ7nDc1dVb52UYipp/xw42Eqr8Ym5Gnc4tfNftlJ6LS9iuvH+uLcUkgHKR+75TiCI3eNgvgwWrJhCMH5sFAXxpNduzOJtnf07vahQXklEZ+39E3i+p2sjHLmpei8Stni+OgljmpY09h3SIauarooGpBA2WG0O7ydf9FySk/xhWf5QWqnOYdqEW2WZeDL7yjvsD6d9CjKvkl8O8vxDMoCIxaXq0HZssU2mT3zs1+DbXRKhK6nN9TV0E5mRCpmrZYAe6+Mya9751KVpr+4MTe11rq04UblLjT1J6ZTea2d88NB4IZZkwdlnRbQeMMKFNFelWUTNd91KCCjCce8kpSpdLH+vC7pw0aPyztF/Z6++MMCtYj2FSURcv3sCi2UoeaDisijpF6pZId2ccKyA9s02bVGIvERR4fRQaXa8Omo0ail0JvKkBLTyCGPhyRd2r10JglV6s2jjYaZwMPUqbd1KcgUq1M4yeksHLNycz2p53fvpQHbGO60IOag4STPiry6Vymld9H8/Zf0kR5agIiAz51ZYcchXOCWWn7WjZPYwkzl5nSMQKkTYLL+l+8GAwGhbxLe5s5L47ECXw/TruOmJJn7zzPKfpeKbVz2ktKbp1NKfAzTcjx+8CP4rpTiIJXfhUb1O5QfzVf1OQEDfz/YOz6DOolp7lTYSwHn4zPHK2QTa+SMEqsGd6RHx4lxwNLH0d5OgGXhTdGLfM8e9bIejThTEGc0OFQ0wrzAKEexpTiRGO8QS/QHXuvoQ97B8DabM6MZHP6U483Kadctvc9k1XVHUQ9dqKWJhJfyOt6hbt/ruJb5e1W3vGoR/HiU4kE+OcopKaFMZl5z9H791VsPGvheFC82CjJf3x3ISb9GikqIDbqYFi3l0RJpXu3fPHu3jzBUNMTgebg1yaDmF5NTixMAV1SW2tCcmn61haKf1tCQnNLcQM3Emdp6GenbuFsbmlp7F1l7WxztlkxtaMI1NlL1PceY+rBmP4IMrD2sjcxsPA317Tysfnzy1ToTTvLVAi+yX3jH1XC3CC2afsPYYFPJ2PV0O7uioAv+pjopOsm1jf+Lxns/lt1IhlqTuj4LyNpjo8KYYI8mlobYlMiyHNTRTbcIWoSFjqS0jbqOp52xhWsQcC/k8wcnw3IxpJmuR9e+t0zSE43JD2bexh8Eq5TsA1bN4a6iIWmG0e2vLUFBdyW87IN9qoFYSHkE8wMiIfTQ1rfqkLuZWEiqwTvryErgv/JE3F68RDwYb1vO6nQiULxUxmGCK86ZcaR7b7wDnHzJWdJRcod5x/0P3cyEdGFffecUdFZjb763xwxwHN4p3QGamxSN1CEl0U7KAXp8rRhOvAY0LwfqLam82V2RQ8t811o6+/b10hmU0gDH69THtNzkBWTpxBvKKjUz7RHqJTxjPginNPFOHgJZZvp3yeBEqxprUmZ+WFZZVTZjBvX92e3X851PeE+kN7yAvZ4y1BSkOJ0E/7NcSiij/c/G2Nzus1HX2E6/01GiKR2Xxv/3FbDUxwwrzkwk51BTL1VmFCBUUHTfnS2dtWBalAaeGPs4cfzz1MSsLdx9ZrjwqtXkdLa/OmVqF7e69gn1fOTzAs+NDp54WmJkckFHZUENPS1GV44F5L52Vos8Qf//PlwlpU7dWmefX/vCOfcArflXv8CmyQLzgOZaG3rYWren/kVMQm5/cUneAGhbG4j2GoyKFu/lL3sK6uNygaRmd8lQqbTBqJv/Vu4//LN6IzLpZqiUm2RwM3Hg9ZOR4TdPWMNcYyvKf5WU/ijISU0pzOX12h9IJocHp1GW0yjLmVSQXU9S0q2zdEtkxnmvUgqCdm/HUZ7+0N6j0GxGtsAcqzq+gf66xfvTuSr0qKVRX/XLmNhCZnlx7jCwpIb+GZcVjiuQFY4dB7UrEtr12praddog3ZVVhLol7x5bIO8eNwxe5UikdKaxZQrZ0iXQLzDS72JcgCMDqV+f7Lv5cLazo76ZGGBgXjasuo5/9hDrv7F/fLKnd1CuUd4qy8IoN3+bcIfrajTqVqHfhUunzNRlTxK2CkOpK9huQtq5UtOZs5PdUWxf2b/TiGLDDxx6TncdIz2+I+33y2e1q4F9PzthqS/u3fufnivt1zTXQjhzzEvtVIO8j7rgxb/Fa0aUvQXVB/EelLhJkQl6k8gCfaJr3/vvTdAMWPri23djwxfDqjxPRQhRBpLG/67sKDZxqJErsmJZDmuUiySWJBCjqUTaQTBJntu/dfjXO5RCqEL27TxZ1qsdO3tQghsje9sbKksG7nP/znk7saerriXvQPcYLVTeOtpYIw/TznP6WBK7NoZwyhMiZpe/8f23/rFDWEBAHVUfhVmqrgYsvbDm0XwUqI6meqYOA5ZOrpn85Akmw0OGfnhfehdfQ4ksMnvJUMZPcENg5/DCsLyQyMgkF0DU1xWhIWK9pIH+hSoeME+CkfrlekcNh0nLpBGIerSWINVLH2F58Ov1g2cfl6aHEyjUlKiCYiDD/qudA2+ene198r0d1RSxK+Jb4FfVVR2WpY3AfgH6ofGr1/ynKHyW1/PQRmXhofkygtvZwdq49eLzHh4jVrep+BcfnyEwL2h+TFNnaaS3sTYVKCJ3/R7ma7G1tHWwNdE0F24h6Hv8g333+VFfA34/PMxg3uZC/QFfJWWvHxn73nN9npnHb3y3qbKvuJKXmXKlMhflBeaE5kfpUtHW6Nsp0TKf9XnNR+hIZ2tuzRaGALkjeKsXev66fyRc9rhlbGOC8MfM+jf8ymNKwUyKtLUfx1z+7nFaU2F8Rh2tFMTAmvLt3OpcWRthdbHkVVjS7ZiRtMaS8tya+GD7klh/7zuxHleCO/nmt0vQpOypSyNpo2VXyurjHheHg2EEYR6whCHAEh7VXASja/RluAvYF9zC7w8gyNrqrec17dfrr7S117yArH/7MZ0PhSfoLcK99AewPntg6EQbAf3jMm/hj+Mdh8e4jm6MCArQOwjjooJBgkF84aIdglj6MJzQSXESX7/94PHShvdZn7MvnyzdebAGXvNxz58f8cw/MnzEFXURFKu0qo/lSW+k8NZ8zwGh3p0hwFGGymKAZSAGUOl0uhhOnA5QkhSbJGLLRkp/YY3A/quDN9faTj2+dPJxKygllRaVFsGhq89rEdEVOPGf9cik9O66Oz3UZmDu9li7h5FCPdM99ZkXSCXjtpGDj5joK5+KRW15vmTbVtqL6C/nW03ZhrmDNor3x8szw3eD8/DxLYADhlpwVtbqSfQA5mb+3cx+s+Z5q+ae9MK7oJbiWRjFYt+BcYpoHPcMWsKIwZGasK9PM4r6Pjxjae9g8c0l++VUzA4fHSyfARfRn68lhm4FJcsxAAct+LCgjMkbb2R/DOAGSu+R6ebVHy3K2iilD8CYb5FP6JNIfeyfxdzkR7sCaJMldG3XeJZHhpmMVohtxn1C2GxI6WXegsNcLNkZFbDd2kprDb7OuNmiucpavCPv4O7rQdqmbbeCq+jf3VMjk0FUfFSz0MMfHx9GrHgq27gGRRa0ZZSUZjkHXRq+9Uqa8am/+H5Gx4Wad1YVLRmlD4Dfsj+2ZMIWlXKbcQfCfYODHTJcRU3QDMABA6wZyoypw+KBxASHOGIA8Pco9yseUJMu+i6nrqltOUg4fCZIXqFp6AiML2HR8dZTr/eINPdcuzq2EPEMrKuvBeC7qoyJiqTOvrzQLm/S5hrphY1eYMyG+5ESfDJi2XzmmBNvtvu0KwQZysDXo4zNiKucRvY/rDI4iNXG/13OpC3xSP/jrIn+tUotWOSR/sPA9zQ8y865tjjV1bSYndn4DLTWeb+viY9MhMSzMgD7vBkfFUKdGVsXxQ2g+ysfUZosi7AWha3pVQ/BRfT/7omJ4aAkFmILYJ8zMMFRzPEdqT8DLMyqR+nXbPIJtrmXydXzcDKsqES6T7MCGMo9qHiHvEaFmyAlfOR8iMVelauWpmHm6av9HQMbN4uYxkmBHt6htvo6fjr8aq3WFtG2+dvXGSlTjiFX3RgYpywiyS/RCvZGaOJmabO1WvKaWkJxJQZ8evEJxVm1E7QJHMgkBQQkPmjvmYbxYcbgt+l5vWo+hjIdPvziGdO4uVdXOWdvmvJN0K37r6oKg69HuYQnTI4HLVfCd1V5gNPyFPfYqWL4dv191lN3QaLI459FP4ueEEXcBR/DWy7usdOTB+TWvDgXRXQ5SvhcfM8Le50I3HtMYhaUSmJKHSmilvuMy+VSISqQLt21cWPq83z+/Kf7SN/11S4ZUdJ97f2zLxvsGuw351CEu1qgw1kMuFvFQPg1q4ljXdzusey5sHt7/31tURJdunMVBh6+n8+f/zx7o2ftujSYfmatYT7NNLgk11RoePSUqaW/Sx1S13+XakzV6Kj7OWLsEuYKza1NMM8/ylFsnIEfDsMUr8JoFrsObMLENG3fLuNVl/DUgcWj8zMH6ULrjJViwaFH2OKlKFU82oYDWV5UqDksQRW+2iRaOgVxxbMsXquuw6OnvrydvrX0qHMoIDEu2C+5PAGP1qgG3Q8hNakP7tUkp2ckk7OyfSpn54IvF5QkZxQUV0eNjddEF5WmUkrKAy/fHveuyaWlZiij4uJIj8Zi1sdiQx7G2cHGo0NCx6LurQIId++TLVkIuodN0L2mG6+rPaKtHq9+TT2BRR7jT6GAcw9zzzTzGxP08ztuMqx0pfQzvJrQkxsh02f1FLNC7jKQlO6SKsq1cDf7HN/7ar2SQ0FOFcHMXlstqXMZXg1sU8s76LW7jITGCmpuHclD76wZWfOwWZN+iJtS0uEW+z1G+80IRl565+TN0rQOXKCb8Fl66dllEQFn7XilocR2aD+V4lXV+2Rd3lZXU33jYV8Q/dbDyrrWK8UFni5Wji4BmXGh0YtZuTg5WXr/S22rPUa4psl7bfOdQFtLtTChob6O72rNUVLzLNPeaDLJcJJpPzvRbWt0f3LCaK7XFvyGO63PWydFJcf5BDdEtRHlMuL1TOVl69h9WpMz08tzyaru+8wdY0/bHmfmhliAnbqsC6isRTHx6fUaYP/Ue4w0iWZ6dfV8TVXCba1VQnz1T6ChLxY5F/jLm1IS4i5pxkhDuZoNlif/EUOI25WE7rhUpY/YaikYmqh6ZYHMpmAdrQ7wx4Z9iyr9fQsq/PwLin39iov/CSgYnlNSNjRSOGtkSjQyhBOFNsRSYk1jTXJpcnUjP/9nnTIdaKmwJZ7eR/TWk/6jev7ceaVqUkMhvjwxyNff39K0I48GPEUXrYz0VaXEd88pGcmcrPa4HBufWRnte1bPQWtv0Qmaf3M8Je1aQkCNuKmKzjkDFdnQSsQO+CZhlV20GATklGPg8sXK8Cm1UiGmciOe5ERuKTQ3WNjOlgbIeKst/N/HC6z/tjgBS4eCp3+aPFYlr5Ny4VB32f4C99oQGs7fzEZW8sxPd/yRdHhXUW3/RDHJI5wALFc9awZHKyoHhxuMapkjcjdHrl3GermFWlm6kLxNPd1CLS+4BiJucL4R/E4kukb0D7N58AeGkQK94kMcGUjd6u3+8YXp7vba68QQLZOCYdVcioqfqYsYEQJhXG5yd9zWz2Lp/WXdfI9NSw0ECCPWvNHThxfBzsDQTN80MtbA1MApgRIqGjYyNyMVYNNsTbngVpFL27o55Gt5WVrqx4XxF6/m1PyjMBFRNU3PL+7ZR3Uo3kENBdk0pc05+86miFiGOmjEXMx+aQpi6aJ7Cl/4Ro4kjrJsvSQoMQFLZ9wQEcitLYmOqy3JANBl2N6fe8XsGe+qTbg0qydr5DJIs84wrp3t7LvQc9rxVAU3+bR8QIizhZyh640Cm8wL9llzVi4+/nbPRcF0lR+b0a1pveac0zjYVlq93r60Yh0QGOvrRw280E+gfewZDOuwkLZQN2238Xu4DbthT3Ed7beKi6LPv9PIqI7WCCkxqDYUeLsRjlADLU38nOTRcmFFLTxZ+4+kpReArJ7AD5Zy55rwP09o5IwXSdEr5MLgnbnk5CvRoZKj2dnPCg08hlJSHfqkFGveyV/PupFk4IlL5dzDkWXglF9/qzG7YSwpoWxtALQf2m0NbLkq5UfPdlIOSsMkfih0iH6hY/+sZtGCnE8aFMZ73xkt16yJ+7tCyfO1FjEsivecvVM0oDDqFmTTu2KQ1fjMu6fPJsiyw1eb2vCcAdqkg/Was9QxFEJSR+UaWjOVmRCSB+ad/KTLf4upXNAi35bF87fkcnwz37nfHH7NVUdhlvQ1D4R6c+YSuYjtIxvInNKj0VfgJlYX/fc5JTdzOlzVU9N7jBRyb/fv6/A5XPOVcfKNqADDBErq14w7weqeah6TIeRFFsl/A/j+2ifUzNrHc311T7My6he07z/2LL4skMm1P4FSDFJe79jKi5uLmss5vnKHgEhEkm1cuKNTbERbbMxAbIyRtaS2jrSUjpaHtq60jJYeyG4uEmPTnU52u6m1HTxZIx2HC4imOh8Nc1USPnJaUUcceLb4/PSdElEFlIHwi25TwFok6KvvlIyi5fWngKfbJGTv9zVwSETlRzK8vD1mIPuMr74DBVXGYFwlejxc1NBuQubVALf7gL+CsQ0KdnIMJTqL2gYGujgHBdnBIVEkO0cslU8sLQe4wnqX6i4zF8lBcuFyoM+/XSSf+7A84VASerT7wbVwb2G+2qhD0T8OHsOyd8V3ZXYldLFiDx7+7E8+zFdPFAm6Sp/FDl5KSMpMArVNYWqmHJWS6bAvhJZLyw3Z5/BlqnDacbroQgqod1F1SnVgtsRcUqfeuZmbIS2qhyvjpUOjfP0DXJZoS62G05spi/WM4zOefhhQdnLGoKdHJLQN9Xd6n1IF7FNGiTpanmOJ5PIjuizTll9zqfJaCxjKgz1GGDm85iAVtMgWKp/vdTft2D3NDx+Vn501FHMkGyU1lBTn1WYhibcJhaeVLsm5Oqk4aEo4Gs84zLbMGnVjZhJO1bTj07qZh97vnp9NV+leLm3PoVa2Qm3ulYp2ak5pK1JVhRvOSkd3d49S09A9gJ/d+H8IzE4FpAQ0VzdHYb2jsfVxuyvC7BCcIp2/nOYs0Kx50CgplxITX5tHjmlIwHpVsnoka+kb6aqbGBsZtoBI6uFUXnZE8Lm+MSmSnBcVXlOeRm24Vip7f+nlHUxCvqzxaW4RKwsrDTUT0/hz5+Eq04nZ4FQwkRIAWdqRkQpZyqn+tdE81y37axu6/YpUiPQpiUhIHLOgTMiZKKlrGCnJyZ9XSuSbJfX92Q0pie2Qbadv8FVDV9M7MjszMeZybXJm5VVUoVpVNp/bpZJU99hql5PnVC1NQ4uZqsp5Sx0tQxNQ28jgmKgBc8Nu70dlpVO3DZcOX/r3QvWJW//8nenJCz+Oqxdr9Ys/ABsj/AEwIuT3E+a4x0oPHJ4lJv7af/7ZtaGb/0J/3VKw68IfPGG354td1uz62Auf++nlsRr7vCEzPA6KdaKtHh6I0ll6lQE/dZAulc659gEY/2umObnq4q9meJVOMFsaOqC/bMlRWWjA3WqAdysY8HesdqCMQAfldm+um1ss3XbaLttte1K91+Ds/wdm/0EzAo8AqpfX1sZEg13qLqlQ0LoRa8jNNbOcZyKUP/r7aTJLC/PQ4vhszHqY3zl5qet3aIMbsbLcXEXj/sYRd3VrdCPIu7mpOe5fSJDBy+8gG6csQtHKtq8JN9frxTzboZphfR0wCUre9k6HQuVGLKaba3zc35egZgGlqieOLACRg7oXfBrknt+M552Nyfltr7GdpfmKPejTjYY19BMiGELNSpsEaTveYNxfLtQ93b/UDUR85YleF0vkwdtoqxY4UycFy+Dcs5a4pC3DmbrEllPzSCgL9p6YsvbYpO39iVXemrzgbM4BnHv9fw4HYKeAowxB9rC3a1+yNlgjC/2HaDD+yE/VO9NuuMGw/bqAXngsb74P8l+TX1dg03VyYTmsfeBFpdWrds+urEbXXtagX9vbmQteQ3DL3/dBVwq15VQR+eLrM8XyHekyOPBRbYKFPADckF9nzgMKpbIMdjrznVOq+0CMMn87R9YIbOzW3kc5xzWYsdq6bbjzS7EePLE3I9g7hbyTcGHH2YJyTe8nWo4UTlSfg6CvNSrcykQ6Db/Byydf1KuLp31cM2j7jdrgZvm/CuLyuB8dlCPx5S72w0Ly+JGletr0iUVEZG8uK4silB3bBfdX9tGYllEhbfiNG7QnmhR4Ls6rAWCr/iY4UeVz5PTqfr5pppwFn7OD8twschLEGf0/3ATKLvj+38OWGGx5nz4uG9TP+huOnIuRGwBqzHbpEyi+s5gdVGTBhfOfdA3UuN5nhP0V3RuhHFV52yYY+unHgbZDH+fyPPsJk4+rj+h0FZERB2WyVO+UxkRqtlf/0T9gGbDD3PIIUDZYxb3wuum5VX/H75sA8OJPvBIAvBMWv/068HdhlprCgBkKIMB47gIHwHzgseqf0UkhOseKhs7mpbX+bW/VshzqCg2lvRU1iYLuIr/5yXt589k3pJdpYpXkYMtkugocKvJEywF51RjhORYGWuAMF8ijAmkwQUixvdYH5Oh0svEyGC9lTQK5Tjn/keR/FR1svzV3eVFXQ3PLFkaMq8PE3p48RVx/8yffMblkusvwR7OqTpLIy6EWN3DeampDzGeSdJeS3fc4OO6j1jGg1OZwt1k2+4iCauCE5GOtdjRPFUyJqRXPQeAkyG5SnCaV66hx3lNUWwK38ZUdH+XEbg4NF+kfVY1ooDb/5+ryONrb2Vx3r0JocauxNj+Uukp4QMPp+t3JOkNQmF3V1lyfdWDz9VCpUT5qc+M3DRxvD6svizteK2w7HI4d78eQ4ylUWEdcnCCXHqN8di1yy18p7Rz3/Z62XTz1kiJuKCrqLp0tqDB+CycRe66wJsMu3kXWjzzzR0nwmaH7ic1Po8uexltxmBraKOowwnToEief/lA4TpXi+KVyrOf70eV+xjWXdjFnUtzwg7gPCeTte7g8aMiLcm4yO6kodazM890vqJaRKF+XrO6gqFxEZF3tzxUq5T2Flsj1IuAzBZpakCONSnWYvw0DmHbiFCuLBeZQhwIcYQNlmMFwnMxNus8liWSGjBCVGsOW+8TlHt0ZCwezVsRJjY+mIAjnKlXovtytXeCiNxxJSjbxkLiWVRD3iHejiF3Wr5ysUuLLe7WDnPOGI/mhEN8IaP3SuqY58V6f7gJlrUGah9edkQEB0YBGkBUsBGAZKFAbwkGAyUVoSGMFcDzQ7Y/g4LI/Chf/XHR/Lgb2xxITvT/OQTWry8UKk447wSExJD8f33AhGSlpUy2kH6yqn+gdaBjkKcG0EhBDFtYiTMu8ve1NipwJL4kkEexhEU5Gbp8IonsRNjIpzE8EhYbEINmzKkhGP+tnTOJ3Cu4OD1GWNKVRTKLAQqzb09dbojHShGTCz3MiiLDmlzQ21NEztXRCHEetVJlzSc29OgAA) - format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, - U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, - U+FEFF, U+FFFD; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAChwAA4AAAAATeAAACgaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGoFOG5JCHDYGYACCWBEMCvI82x4Lg1oAATYCJAOHMAQgBYMAByAbcT9FB2LYOAAQlrxDFMHGgYhg7wv+LxPMMdTZwdcAokVZdtu6RLW2UUDAMvAbzZ4j0u2S99aGde5X9nYZLo8RBVE8cz/ziI9IIx2hsU9yf6C5/bvdgpElUiKlIGkMA6ENkDRIGSmVI0aPDP0gFj1qoiBp0GVi0dYXJuYUHnju5981VVmCjIc7w3k0B1KTz2Y/Cgf0o2mPp/+Wsb87U/V613FQAqHQIQuFClkirPwW+afv362q6gMtVf/DsOf2cg0vvM3O4NPdzA4j3mvSUAnMZjCdnkUeRGKpRucwnAmqcD3gCWVZxcs/tQMPwPr2Toq7D0ZhBA+fWm5pLolxQRiTsrNzhdLu/v/ZTNsd76xPmzX9ECsMPVdARctFOfu1b6TZ0Qr2zs9a7YHAJCkso86kM+kMVIWLhlmS7ehCzFWK3kWXdCna1C1wmaJt0sbWSrOImtKwHO4R5x9/Su4Fx+oN7ec3pBJ8N1JXHSbD5btBxdL64RmbEBAY3Hq/9fdh7HIECcLYaYizzkJYsIKwYQtlxx7CBRnCjRvEFd4QAYIhwoRDRIqGiBMHkSgFIlMWRJ48iAIFEFddhfhPKUSZMoibbkJUqoaga4RgeAPx3nuIFasQ6z5CIDAAOAEIw0DYuAAAoZeanZz9sN0XZ6xB/jMlyAfkvwe5eYP8n8shfiAPWX0N8gNeCG6CIFtiqJtf9GvxXgISaYUFoBbxXMhQubGvc726uLHg5rjExJR0Tx3ZrOKw5Wn/QhIIl5GeLXqGlHXOU+EEm1DHutZHMAYTy4QF+DDhMBH8epbUgFiWLMcX9MywrBWln49cqDPvQ4V3wayqvCnfluUTUl0J7HbL755hb8JZNZvW55+vesv6HJ231QTzFndzWbOdc8i2zl2YaW7Qf5NqnzZydd7kCi/4mZFannpkiTG74hVPfJrDMXEFG0XiGV61ZftA1KS6oDHeeAP3jKIKTrQnWVM/au+s0gpuLGx6JGRpNknnE/R87HG7/X3q08E1N5tZM1rsYm4z4/l9NPux8A3c1CCHpdjQ7GTZ6Lb13GlycjkCAkpX5OMRbE4ySW9DY+dXaipDaJs3ojPG4jQ/aul0PNNO51SvCq6551maBRVcYsmllFGX/glWV19TjO7W3L3u11JrD3rUY4OGjJkwacq0GbPmvPDaG8tWrCEgeZ6Fl3mRjOJz+b4qtOU62xDRPocXYTmKlaIsl2epAu8rtRw7L/FFcIsiuSjuRVssxZY8dyswUqnarhsKj2STBSYvm/IxFWK6bhORl6dRzBZloWj9pVgrLy4FcbpuoTJbEKXehkPylYVNXj6Wb9t1n8Lw8kmoR3TWRE4W8wgJf3vfKTaK9qJs3V3zptL4Qpy1mTyS2OS5Z8GxKIkvxOTlXpzcKkQXpWTHE/MpxWrZvMuXX6GGromqNB7X5SGirfclgrSaKMJaUd6UZ7oCYbzulpx2Vfj0rZF6IkS4yRViSjiVE/o2lcf6/ifqxImwExxRu+P52JE0d9ZMFobyQsa5E8tBMibGQEbJ/86R+2jx8unUVlZtz6lB4/101XTo1O3hfeW83xYwNOkYEHAcMEwBdQr4nQYiJyBwAS5k4OEK7NyBnSewCwIuwcAjBRAZwCcTuGQBjyrgVw1E9cCtAXg1AocmILoLXJqBx33AaAG8VsB4AHgdgNMp2cYr2CoT4PIYeAwCYghQY4CaAIJJEDYFRNMgbAaIZkHYHBC9AE6vQcgb4PMesJZB0AoIWZPsJRtbDaN3CDgTY2BxI3zm40jcJ2+Agh52HAmVLY5u0AJ1mAYevFW9Hk5cWVXWGnpmBBLiEKpMwhTCt8CtbQ8RAdLHwZ9a7CAeIc2s4OtgYDG2Pjpxwqk1ijOjkDHF0R8pTV6VVGVVWSnLGhvATnDnaPTa7RscwG2qCZBqXEJvuR+HcK9aeg4AjD+aG4NunCsw8A/AfZUcIA05AgBsu4wM0lAHMzYpiIoxYEMGQpb77cLCRF3iH0poycnN1KYpHZnI07zLdhEcbwX2DsAuQk5AIpOa/NwKPc3pzGSe5X2+F4Pj2zvgzzPwZwYA/BkCfx6DP8vgzzvwJwsAQhaAHAAtegAuAXABQANQDIAO4AiSZRUqmVQTrBfltWpcdOk3unyJA0dOv7a+s8u15o7o6rhy487DmvX64r/wssZM/16UaG+9qzZPLQZVrDjxEiRK8sqiZDQpunXVnvIneqRKo5Ofeia9dv1wN3yQ7bmPbrgJgcEGEwR4AAB8AgDIC4AFwF0EQp8Azk0kx9snDfPj2QmX1DwUzSr3I4rZnsxV4KazY0KQuDQbrywA7HwxcI2zw1xZJWHD5VmoyqDaKJyscpqjkz68f7LUJy6TZMjXsyGBTFpTFyxonNXoVAXBK+0RqSefAlovCIp7zRt82uqT0UeNC68eabzREGvrdZ4TXocmmhWkYD1RsgYezAYhPBKxSIn4L5uSmEH33PYFeM6NZWmoZWzp0TlTuLIqS+esrdvL7Nr7to4j9KKuj2+9hmHQ2OKiv3OXFts0bnPXvEqCGte/dZxZlK2+x2IMVoKF7B+O5qvBIc79qe2ZIEetij/Rwrm+btakPVN9/M1ilf/npsR0YlRrBCW4YSK+CmBFQujrC3m+S8Ju4LHpH4nkYnJysgUVZxSJlOEfwx0uD7/GUZVIIPF5RdEjGmu8ReZm/0Af7uv5obkxNwuXvMKEb9rW1YbViRmrKxkPVLHPjRCrUuB8wyfx31SJC6Nswq2GEtXJdqucBTyVVflWFI9zuqybkrG4M4ci584piF0xKvC7dDZutTg/3uCJCYrLhUseQJkfkHC2z5f4odJxAoxLNLxC90Y6jrVmk8BeFvnl7t3h02X1SWGkYoNSa9v6o4H4GMjKTE/0XLrT4JTxJ63l9bQdeBsVy3Qi6aWJAGq/sGaSew6pnQIp0OzUgzA0ZmkKQKmtrRNiMBEVtmfeMNGBreSPDRm+vvA2zXhCBe2aS5P7KP6IJJSe6LBqz5Ei56TaOnWHeMhXMl445QWnFZOTK803ANrivZFmoBgL63JZ9voy6IknS+56R+f1DWvsvzpzWB19DIVc8mhfy6E5YI9dnpv9XEuRKw5QatQBLigNO8rTPRAhL1ec03hBwiMZFPTqL6H1E8/2X26SPWgBVUSts8n7TTMBJnmS17rjY3dML++JaWooj3xhV5mDb/e6xR3zRy5FfTvPH36NYQnfQbWiBzQOhBQ5NNFlU3ZY8czbQpnpgWi8Bxd3AwmPyNunMbt7pGj8G3WPuemhnnQlaZ/XfHpFTPbEoXsrmVvI0fu0cbgtWw41hmEIFPMty575POf9RhrpscIm4jKmFha8ldjdERqNKyPqlpb5Yx5lYIPBpkfcNt06HruzrseKVty0SzgorGALbNwvz73l6DSgh9lhy2KT0YjMaVMpauc79mWKtENlDTy3TB2zK78JVdAuz2w0NxmcWeZ0qlUa9vL2OCOdWSGZlmkf3HPSIYY7a0S3/otI0hwP2NMc3nI11Yw9k91we3kEECrWpHCdgDlKgVPNtLWLhKGF7ZcohA1gH5q3RQuqQ9w7NZqlbv+7Q/1JSsRXVky4J1YD2CPfs4lhm3aRb+QksBZc9Vpr2pq+7e74y7VGwdNegL6iDqZspLMjt1Jnr8RJxqWejmg8fkGF2cv10t+bZuJfdfXPvbXIcnSO+jdgneHNNkGGrihbmX3tuFWAEnFZT8yqnElEyFDQS3jJ53msXUKaLu4COb31KjLUCrih9oZ+oCV2U1jMFR+7uoOwQr9Bt92PkKHU0+XtBzRHBaRjrQ8Ozo1y3CQFhrEGQiXh6c+Yk3OS0PGjp1kWoJsDDYDyY76UIooOLWxMbUjT5MpGtDmhdDPZeE/yZN6kAJsENoaioZ5z9T6yMnd4KpCjOCpsYhmKimZZ+fN/YMfwcGHb1NT++2n6XSxcXVa/7cv+z7yc67dNKC1uT3ly6Y4N2FzcuokbcsdWvL64c91urT0+S6b5Y9NoJtq1FUS2QwazKM5dkkAXKnwc2dalH0j3pZVp7m0ibj1VOxm7aGk9cUJ1swGfbRL3K1/xsqijM9l37rdPcj1YUsMhGj22xTLFtjLevfZzfUhAaH1sl06a5+KxUWpZ5NA6lwq5AYkMHJNyzWTEcMzt9QSBF4I/CnlM8mQnAD0w0wsUUvbYpS5zi9z53h46FDv09lxT+YJVojc2chBiJIEjP9H1EnHf9yVWXllTdsCXgLOYk7njJJRI7JaqdR+PaAxBj4Ixj3iVnFNCGAC5ZsgD8e2siOrkW3FY9TOPfWXUmyzb8TLyQhRynZg28M31dCzs9s3yYP161d7Nj6uDvmW1UuX/42VRsAIlj+oMsGJZnUf7cGq0+lWhln14YqScT09o6NNdhLFMLPs6Rt/oMIJoYsJ+05ZQ0851tewu+ahpupMSENXDo1YamhshBb24benKkLp/2j7Bhwb5F8LHMN5mGnOeJedx7kuL1Sk58BTb1HRQH8Xjjccj/qw26c1yh6jVaDNjR3aTh/qjFmumg2K/pX94qWuvDJo1ip02Q2eQ02g6RRnbLeCtwrRLt2ZpjZJWHntwl3JkNfTJtiRwpF2S2XLbrM26mbBffNrpp+pyqeXm21xNN9Lt9yvk83Yn4ZYadaZZaBh5yyzmagub0aLuwO0yDo5dK/mrhwGp878QcWE8cXe0tM5dntMa6UQkrkSHFYGqUlwYKhXuHOL24SIK3ADReAvoQTmilsrUuhnkg3XH9oLaiObS8RGrr9mvNYY7Ww4Zegzpa24s529xTe+Qx1uq9GD2CEH4GR3bxE15VZk5T4U1CO8QjVBO8RXNKNgUNy6YLDxnJxCQCAWZYem0Lu+Z7QMtFGGZPvsoB8V9FtqJWcSe87O7a6ap2WYfFcU+wDH6UDd7wBH4EgzD/ucIX7qNIg6piAMKN4wTzh65pEwDw+6X0AhennNwVN1KK9SSIOvGWJINZbCRJatm7MDs7guh9X3YX41sFTkHMEOpE3lHeGvvbe7FiXxh8V3PT8+uZHxF1uM/1fwoLypKFiiF40Hpto87R9oAx7g7dj/fFizigJWSkfIXcIy/jhmOLLjJAhyDBbv7GeIG9uJa9sanxm9F48WXXVrE5y6Lxr1N+X8ZsHjfvFCgx19/765gffEJmLKcLzbkr3flpxfpwhwLu9WK1FS0AfLB+msHrqrm/s53p7HLA8t/lnvGEkGx4I46l9yD6SeLCoeFjgjJ9yy2TcuB31+zu6KSiddE/4lKFlwTA/Qfh2FwRE35eHtaA7T9X2Rs7eDqbOVlqcu8GFoycj7m4buHmPr1fEVbPkyjCdXw91hiSoqDrZG9JRxusAv3Qs+uoK6hjcNuoUvEvajYD4Li8pOtt7jWFdQ+LNw+LJYODQoMaj2Yyf1eU+2t9wpXZgIeXnH4+yS2PvygvrVZSW0LLTJImtCLLwqL7YALAmuSsluSd6L/vcvKWPwqhnHpZU++Xhpe7UlLiNZ1fnaFXf+ma2QGb/QkP4ESGA3CvX1haa2XsOm9zI4AZ3vHfON4HBPwwAQz+Zsx/5ZSC1/yirGvs92K/LOcVrzCr/Zvi606ret76qP2isxHlPCMLoD5cTL3KUEbOc6ngQuB3DZypoKc8N3u5SIqvvzahfez9mbXjL29nriZrL1InzYecPO2Gnr6Yfr6rvr6YXr6Q2rCf1dBq5Kz6UYThAZAArfV9wdWslrajLf9NN6rcv0SAsNXLdQ9KOIpYOYs+Dfjlu6ZeSsaY7Dp+o3PdRuPjO0c3S/YBV3Q2+TPZ7X1v/FLSqANInOfMR/THrClXy2jpV058sSk0vDQ1ImDcW2kFNLIdJ8HEu5odNLeTKN5jUxN46H2SQb6UCCBSWKCNNZ8WWDfd6mSyN/PM5Nh/gt8TqWzp2TfCrdNlz+rZVZmeGxajyhwyzY8iz+4Rcw/gAIHWlapTaXyTaXUVr1TJkmmJnogn7zz5aHSn6OysajSDlKFy1PKRLwMsfcb8TfohyzfWmYBjnEdtHr0E4Rzuqs3//7GbAurbYuGsUL/FxY5gH7bYf2D69lPYkV8WMBF+vjvj4gg7yhzSkSQ4w84qdt7Ui9L2e5xjjAp/lEx8+jf/bytoxSzi46BZ04cdTrlNdgwPY0pOBFt6+4Sf0FvqxRtH50n3AVtOVJivnjVeAX2nb/Al4j3AlhJbU6xCeYUuptdA4ifmeuOEjoJYL4VUh7CCqG7BuvstiK01GjYOZU5s5yLLzip363aLUAkwcG+PS4FwbG+eUF2rPDE9g33rN+Cz/vI4ZXeByhKcfTYvn2rv0t++kZ3R7EcS+MiaHdi3KKy/dLrhu5wwkkcQ6/zXArfuH4EueHcPOONYy0/FNPgJrjIdibf0B0JsiU4eqktEKd2DcHN1j0/xaTut6lcIt9964FDBoOP+eyz04yUkpMTBLOVUp6nY7cVGTiOFVibYE1Bekzo1cZypWoQnU1UvvXZN2o4eUzwxxdEpdmf059flOKy04P9MmKjEPB4JlBWnFxwnb6EW8CMYQhPGUu3Mgsz+MpYIp/lCFv3eKrzD8FY1GT2YY5qxs99WKE10JoNWwjbIg2BvsW9+HvMe3E/m5XdNazwSt9qgmqZtcHbNUqWqKe2Kuig/Ca2EWZ72nU7ijYZo9GjloHXvLb0Qi9cuuhpqW9uZ+jc2HT/DpKk52Bqec7X7OhWzv+t7cNvykEDS9oibc1UT3/91QRWXVQ9k8RkeCs37afhqjWPwkkDEokZpiEQwc9D/8Q4DcOC5uwm9cRlgXH4pyyI8qiRmGNKo5XKk1NMkgbwMVsqW5gkZm9lLxOOoRQnCpNi96QB3jK9HIQ8X2/MDZ5hngnzvOzjQhbmZEL8uy/J/XbulX7VH4d7YYnE3OXw+aL7hQpXRxsAaYEMm1BP8xXX4MZhj6BX7CossdKIPy9T8qIG3X3bQ1ccQsNs3WOucaRa11hxJcZkg48QA1n4+XlmxacioGJjcuvLPPIXG+oe7+gVGBeOItgQnwTyZV8qBQXHOVIzPH7+snvQKcsta7Rt7lVvE7MpyMrbyMrNO6jpW1OQnbf5qUuj7yMoa5FkD/3oxSyPNzYszzxCv5Aa6xo1mZqyMhXUz3aurhdtXDxtERDTN29h7y6SYCupcz7Nb9NfsY9u9H5A3lZv3jnfGUtofT/2Zz3hVr4mZvh+pqv54kUElAksov9mnnx7h7Ys451CQ+xeiolF10UR06Kz/C6Ge+DMlzFu4U3D5JBZzF+BlzcGmCQmHFanU+nv6MHZtXhpN8a2NI6Bl/Kwqv4BS8IOIr0idh7CP8QLSWvi90k/ynt/knGiZFEyVLt78t8zzZXIqv0NvKcH5a/S99a1qKn8HhOrmp+Q0/vvR2gJca8yZ/QR7hBhkpifQndfAONyxb/o12fYp8EsHyQu1C/H85IFy56aE+KLiQlg+WDe/nrBE5myHBi6XjMNCc3IeN/0KKfgi29CL/t5u2eQgXvMu0B1CAxEDmBub1WoUJx8MVEdSZ6FMsrQ73yb5HrZndrlS1aLSFqJSqkzYGL1gsXmBQVgovylE4+s185AEQMKtMimNUwS83mlwLNvQi/7eLtnkf57W/UdfRCi+huk5CrjmOQVuWtQ6DP7REtA9B3ffRy2//rZ1ta1KRiy91Vdi2uJCrdbESqNkV6OnAiE1Gg3pnraYBovUf9mfskku5DwVUER4gQE/z0aZOQl0S7y6kdFlrlzmO2eZyfri7cbpw7GoC7eObrncuMPFLUg/jE1tFug7RNmfqKQkFdb9J4d5c8rmeIQFioWFGYfB4sgRrFqBl/tNR3MmMN8kb5A4+r5svtyq+V/wrMuwot7n9mxB282LxMXu4jPHmyAmfztaNZSauELflH2DWf6Pl5NK1oSUEG++3gn5fGkIjwpiflXXl1JKuSJB574pEJwThcPFPdb+q5VV1oc+RhZELVC5KOEk3y+Se1lcMF7XwFnAWdK90WZSX034Uct0rKVw7zlkrPCy6Q/VO+FPGfIuix1gLomyxuEkbCR46OMH13gQNCGLCdFgYWbiP8WLus8cDlCNunb5JnBRFaknCpOjy52exLM5F+82tsl6dfm+1DylcIi38vX8g8lvNt8Oi7vj72L5hcsdl+8fzXh4l1zSec2ZzPp83eLEm0azKQ928DckDGx+QteCS9+/T21FFgWWLY08f82Oie9uMWaHHNyy4oTiHPLclL3a0nYToGggFhP6bv0PU3GKk324alfgp6evDTZVx/3GnIPmfmJLUToWuzzrPVQdwpvBP0K446XyzD6c2x2taXfOdclt6d55g3ah46/XO3sNb0UEr0dbRmif87BH7xGPo2A1yBtoWeVyFbu1LRrlSZnlSb7+HSbkKcnb0pdJ9J31l98MnIeWanvqqMBa5E2QLkU2xJrsCoOqrGiDqORZoUfpebJkD/uM1I7Rr/4mjJFoKQcJNk2WPJ7Mmtedwm0Nj/faXAT5sKYV5qlZmRfSZRG/HmRmh/d7+7XEbZiF0y5EBjfVbPrdkyHP3INLj2WrjOOla29f7zpbZY03ShWjj7sIUM3iZeltxnWLxXK0U9TpWpBtUiaygD4LAveDHgFosJCX17JpvJ6Xjm4OywdlGgKESASBoo2r5K6oYjkb6EP0kXCFvokfyjqTgLVb0zrII+HwR7WAaryaqpyaouC1sEeDk4h7jaB6vqq++XUjL/bhLg7OGVkByV7eVUt/MUSJ1RVZDnGroqYpPZpi5NVZS9YZotbXpei0gqadBools6GzmjFnW6KxWClThJfRs9EuVw0MmHorFocedIodeKavr7coNpsEG9eMwYGeweVl5ACQ12DfuWD6G6kwOCkUa8yKGvjZDG+wwMcrl5WM7NZln9PwD6dK7Gbn3ygVb5J/p1+EhJGofmQU4oiDtJ/6t0/FZaTGYMcYqmZFwXF+pJBH8P/zbfYi+Ln4hF+QTug+UoIwgTci7dE3yvxbQNv5fGbuDtx3RFFupFvT8YUG/F6RfqSL7jLnA8FH+LtGlkdDUFOohIT2hNTmnuQSGu2Lgo/fJzksPkVU0QKt+js8ISeGSRh3bBoOhdfUpxtNsAkDTGnO0isEJ/lOLHf5+RG+cZFX0b1iXW/+K/83yFxNzA1IOkgNoe0n9YdaC5tPl+/RdpinB8sHVSYaAIdl4CGANan533zrhn15IPMNsnvaqCF1EfVb4UV96UyfJSaVFLw1Ro6ICZgmeHo0ev9ORabHgLCKnvP9TmEhRYXABb6J2N6U8oLZy3HM92BKKB7pzCGsA/7+rL9Q3rW659MfYiCZ7ZHQkVxSewIM6wqjEnKBIcAoTfNRgVGDzr3NdRoYx4ON0Xvfnsrc8495m1329MX+GZ12rsRg9Gvn7TaerZ08QPyHcN2AlcCRZNc51yMb2cT5xud6BesHRpvw5lc/o58bcrh3JV9J7F6ky846CPMUwVRplX/jcaczC58H9nZslFY3PVvPHw2ruAM74XNbHq4t4tLbZT3UZq6Bin8CojOfXLue9h3WTZ+lbXMEFBeczoAfPfCt3t7e1+2VEUwIwoEMIsnVUFknjGHXDU7bOSL3Vcu500ki1YP1fN91EnEn/ixfGUb92sDXo/DNtPLgAubXp7Rwt89CYxzW+egLl6So5yvsoGTCUl5Gx6/qdiMJ64iy5N/J0NYUvzjWwXHHouo2ljtO1oiUjVLb2nNVGos2EW4WQZsMmTjJE/tkZGF7rt1hmp9egpPVaTu+fhItf33qDC76RU8FZgT+y0wJRMvkfy4oLbI44BkH36rMzbcqMadljj6+ZX8oqiw1wglAwoD2AI78obYB96101gMXZfcUfzFxbP/Gzwh+iMUCxwbjDk3Kna+b3B2aK9NCdplXf/GCBkOy0xKZ2tcaI/TRrdJBcRCGTGxMX8Bt/6gu7/WkME1oHM8quNarBcUORARJLHR24uC5vbHVYa53A99dKIfry2pnw1QEOrT9Qk+5f3k5jEJRg3I6TmZpk1h37z+f6y6WFNDrb++0pS/CFvc/Zyva1qqvf0hHPi27DeWB3cojEGR5xs9/eJrHzLeucc8TGQ50WI9KTlU18JrSXmZ9XBAP8ytLxNKwrtGRBfWH/UIbXxMW/KIfBjPdE5N8oksiPUq/i+hIKcODpNLhYbi512+7HNw7GzqmOCfDxjNKbxSdF5qaEh6bgQGgj7tZs1OCP76gNESYq2edkC807DRiKn0M4nT25IOe0cRA3R2688oxmwYrxyTkxYSmpVHAXDgYl/S7i13Dddj3kXMznrqByPxrWgN2n1i7pPwBdVWTAJSHf3zXVImoNatV5pH299g2Rcbzhl5JAZTH4/foNSGZRkE4vRh5fJ4dT4k+oROc9mNu/4C3MzY6j/y9nEscpZNx0TTFQlsQe9U/p/Rtthl5WHEHamh/HielF6F3q0i1B73i4rxADXej8h5s4uIUzaGihbp1nzanywSy4aOrm92lWFuBhASTGLvrCJdPW1oYvHoDq5HcARZqjzYZNp2AFcHxXbQM5ELcUH+H4WEMT2qXzCYl8NvltzeG2GItPF6MvnpxVMJZw4fCiOYlDMwjKTAmKQQaC6B5ncz2aeuWJKl0MfSS+Fkrwv5N+rNGDpIj1xnvZvHc2ujhDP2h2JwZlUNkGBd1Qu6IUs3RaS4iM7729JKkVMjQRQ2j9fcu3a9zjawPE0+4Ue9h1ahHbpPv+9yUxxA3JAq6u83iZm9/Y+7QT04hMjvxitczazHWCHx0Rvwbh4szpENL7jfRK+h908MfhIyP8DARCEl/isDUTE9A93QBucqGQa2Z5yO+yMxzWhlTXyWmkd9f0fL7kB7HrH17FCX9IvGiqHGgPrtDkYHk8TsZnQzZxELCzcjB4RciclFG0+MfxSzV36IODf0JaaGEvgToUOwXrC0RASp52n6T0K4rOFNyoXjD5L175T1rXZBa+/6jWgkIQkTjCnUGt2WZ/Cfh/NIetzYhi9cbDyHGOghRuH87h8lMhAL9OZ0U8vabrWfklejfr1Lz+90OqnS5XIkPSi9q0K6pOAhSGot9YzHjfdQrPtl/h+4Tm6LQ8FY0Fmb5wVEC8INezN6rXitLciGDohLIiYYzT9R9nFflGgMHh39utkT1okPBPWqW2vMf7SGOEdWQmY3xvMWl+56318u21C1+EqXftUXxKu/PNPbw/9evBMSnVsbRH6u2Tr0qOyOP2jMpJTRy0DPvz5gANOuGXXeh0itYTM35i4mZI0Rh/wvXzIrMgrg6tc5Ft2MA/k547d9f+C/pfFj+uNHfx+9fXM4ip832R9/5o3vN1k36+h1HtfHbpV+B+oU2/TWdDm9/NFQ38IfNrAl+W1OjNHHBlmD8/R5JtUnvf3M//lW5xp9rXSrtI/eJ+XFXSbh/CX7lDgcay5KKSz8r/BWigrj6cExAXLqXGZlctEBFNAOfFq0d+EfsudKbiGdnsDbxjlMHidz87VlAsiDAgAowG5EAjkOBMBi43YGxC5VC8LVHSYDTSF72TR4B98KQFUNnBu9bWDVqLqBBlM2A5tJtQyUpnGps1TIwDyjygbWkR40UBuiiNgqNapBBppK2QxsBtUy0GTKbuDmqKaBXXalLQPcqlBapxzRDqjYlCvArZ0ykckejp0LfoNytNdMgBmEIaBoYP2oRgCNyGPwIBMROUaopwpSWFOEW+jpLdGVnfdUwaAwNhuAcrTjaPmqfPAOkr9zyzlAcGTntoaHhZ0KjZec8vHAjSBlI0LkZd3Nbsxu5BiGzXpSdphKitsIviMHKc+yEKfZQAS+5PAgEuEixbxUcUowoJPwK3g7JDgpNl4PwhNSJaISZqO8EMgji2CEQASJ5XOxrQiUI6fNsG4GqkJQFFaQk1JNsY6o0w/LyLKlagbkUI52BDcmR1DjxkOjmqimjokeBBCSNCUQCQZtv7eEnEH0sGLQRUcJTL1NhXV+LFXSYZrTBiJ6sIEkcsCcbgS3AKLK2QbCQw+O8GBCYB/HyQorBMRou3LDnttx7iHJ9XbFWIaUWeVzOJ87eVak2sZtlSobxyQ9aNwGNGmVQFUMn2jURsfnXUuje922d73Cg8CcLrdHb2Wiz9U0kRvPoemdRYvLEwCFF7WLSw6tb5HlPid8ldxxOAbJfgdzPySlycbOlRw9PaSQvCQ0Mk+UiCyRIgokmzQQp/KK6FC5qHlBmYuaFfQV60CKvpf1pa7k6HMyqHWdThqL+6bnHZ91TtcCTsdGqAhhKTJ68UEDgJsEzS/ZUhXeFtivYe1NgK10irns4O4aM+736WHfPqYXKbHtdfbSOfty1ofj+ch4OH5uC4Kc/qkM0pfTfARJuY4c70kYELZrD0mAn/T5UuFfJa6zJFzan84/XSUNM2Jsf98BoV8Gkx1MUs4p3AG2t/awSoYjtmeL/bGS89LFzp8xj0d23Fcj1nvEdH9O7BJxlkv3dcxupbgk/iMawOZ6Wx5CIJqxPbrvT5VcGDDXc0w4YV2R9g2J2aiF1yneO8jmEmWRPNdxZ0f2xyzOR5zXt+dCGxdDF1EbU49O/b07sgH2Fa2dAHrpI6UAP1jskAMdd0a/W0fxACpXSRhl2NN3nFP3zZB80c+3ojSRQyRZnMW7X/jSb1f79uhllIyYoQD0fwCc96dwYs9CAGCaT8+yPv3NeI7+YxO7AwBA3zvfMwCA+ZDlf7/l/p9/2N+DARBhAAAggLC+OAGIKypwncREdW9XnyKZXD1G5AqQE4la4e8R7qEpbJPCQ0/5QmaC5t23l1TKSylvEaLWLkWNeZLs1KdZJRAl2WLjP0CfSZyRZA7nS6UreX+fJ0wOcTk56uIZLfSUYgpYnNhQpaUzCDdIx5lzh5mvO4SzwLQ1CltLpexwpGmyS4DcnuN9XpI8YSQj7GyuocVPTkrIDNo3v4p2btsTd07x9L3vFstU6pgLiMd+uxRdGwRo5QSJy/PLntBTPweVzWdxXZXw0FC+fsmJNMXzK81Gckoq84rjReXyDMtQ6hgI8TC5+u45xT47fAHL3SrB+t8opVL/LVd5dpQVdhcazmOogMLQRGdLaaRR7xKEZ5Zkx+b37bec7pebOtlTRKsVjo3iDoUruaZ6QY99loyVzjbqKPPIjss9QilGpJY6lQaQ72/ZecWpIeISLKQ0SSNHOL17tDJyEyF7FKl0N5k2KU0q6mgrrDjaoiqcCDlNZZEqdvb0DhmkdTbh/e5BKSGkSgDL2eQ5ixzHytEqOpAoJjkuZD2kN2V011+Fc0N4seCQ/WxKJ9PdDGojfkyp9DiZs11uFZXe7rE/eDejhQSiYI17g52PezDzhzd3LHDeEU9EDzHEeUFEERvEAkWIMOLJvzmCiDSiin1DFPGdF+dNIHaIFf9G7BFrPvd8iygiXogn4t7nNyKLGFbML6XjL0dPUH8QT54F8Uec+dygDuVK2Ll5Z0xgf22w3/foXorBbtQ71C3UkzuAAPgkhzAzOKEETlaCacHf74qNOxQSJQKAI4ClbRHiHLfF4BZRi6ZrsbQtjjyawEOrf6zcrA3Q5y8ARRAvHjyFkKZBjboJSjPmzwA+3HZsyg+ZqjjpEJ+4ZbYMFoVbX3ATJKx4rlQdz5/Lk4T40s4mS15C+eYIj4nn43KM2AaDBPOSfiBE9VRNh+hg9T9kun8VZFYLAUgOGDW8oOqygCrI1J7dqPIXxEP4REtkbvyQRfCz3hmm9BkyY9VJFYi8GlTvmHaWXAE=) - format('woff2'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, - U+FE2E-FE2F; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABnoAA4AAAAANCAAABmTAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmobmnocNgZgAIIEEQwKvFyuQwuCEAABNgIkA4QcBCAFgwAHIBsCKxNuLDxsHADb+BwnipK9GMj+6wROh0BumfMiQUaoWDWaO4tGa4WtoMBMtavqtY9jb+C3vkgTR9zAS1e/IWxxDF8nN8NnIySZbQnEMfLSJu0/j0DNGWDPYAygn5QTdsbNTj30B5rbv1uyEcI2asaoFhtnA2LT5ogc1WNUbGR+OkdahUGpWImfEQbGTnvg5bSUZNmnbZKdUhrPBMAA8r0bfrNviW+exRNAwgNgAnCj14Z0y0NEpndEJQYcwb5mQTQJojV027rMxWjbnm5QEFNrXv7Xrv7PmovbEC2FaJXXoeJN1OMyScVP/kE693vn3tyqdjdUGoXedOBNAVFUJpNf7wKFUdmHn6u0efc3V8CUeEo8Qp4+X2FqTP7/2fTe/MlCFv9mMVvKzdGU56aUhTJbVhXyMlOCA3YFBSyBjai9ugrjSG1PWFVbm5WaYS8hpY9WXEMXvMakfb2MWbr52d5cqHmLkIcY4+hYuy0CMCADAO7DgBSoUYOALkMIGDOGwEYbIbCZCQSYDkLgsMMQsGQNAVu2EGBxgYAbPwgE4EEAAQyAHQA7gAAIAFugwQDO/GqtA7Re7BdToPVm0ZsArY/fVzTQgvi9WtBAFgIyQAMIAA1AA4pysAgAgdOCA4B0J64Ft4B3w78kpxJ2Es6QXxKWyankVDJFlVKJBsTkHesiniN+kdCSMJHIlZSSqJP4QaKRl0kHSd6kGtLgsuYl0jTpB/lg7DfdhLjnMQrZ5GrdueRycgP5Jfm9pBL5m/RIUiyWlNo2AIZcDj7xgbZnYUhn4TmaYuMAe71aExdfJRh1662Hv6ACRMfT/eQdS1+FqzHMnKLtNTIHvZ1t9L5Z2tvq26cn0FsoM/MF3NaHPhWQE8Odm1Y1m8XWUiIUPXPFURGoC+h94P4qovl0+DoWstdquk2j8bQnimSrGXrLcRuWXLiCtqipOwDa772Bxj6YJGsQoeZ5U0xLwe8sCO8Ki/x2Gub5UHV2t3o+1Q36BGpsOXn4GRbKWrjNx3NH8LTie+X1fh0KcI7+Ht10m3i9LRJtbpfc9IrSKqyYiKhaoJqGiwWKimls5bZ6stj2WEu0IbqVb50DXC78RtajZy8srGzsHJxc3Dx8/AKCQsIiomLiEpJS0vIQKExFFVRHaut4651Pvvjqux8oXX0jYxMzDNbcwsra1t7B0YXaYwhLCEceTzp/tEiYTCakV7BfVDomBJtnm2CX6ZjgFurOY5Oe81ma5MjizudJ4Y8X6VYqRC5EPkQxRClEOQTSJwwgUAEEyQ6LqRRMk9gsS2CNA/8C1+TWulU7xYKrO3J40nDX7qT6xs6cMU8UUUI5Q3qCgQRQAQSJTjGVhmkKm2PpuYbykwfjX8G16NYKs8euWFge6VUqWg55FFFCOUMiYUICqACCRIdMjUvhGmZrHLQPHjdclV8QXAEGJAgA2AAAAADADwAAAAAAMFwBAIANAAA8kaaI8pTkmZoFJTs9tyZW+lKaToG4sG3sgpMsaZLBDW+RZB6zBQHb9awr4kkZGHktyaRnMTjCXpRvLbDTcVByU/KQSUhGjMrrp2kVqCCJ8CTQyttUKDJd7d0UpRvqpR6bZmEgCwjmQXBjMJxnTqfsJl6Ie3xbjKJSz3qOZ7HMHsOx0c1yT7JCijYpkBmRjZJbXAMw4MCABic4puGXoLoqGF/AtyoLwTTechmkMrP1hkyW3Ma8oIgSykRiYgKCFQCCRIdLYM1dDQf8xZX8gvVAlrb5jsqGY0zRyxnzgiJKKGdIOgzAQbCCrNoPCJJAB0usccBfXM8ogmZpYZGterYB98ClUSHdi0JEAjc+2N7MHIgbML6VtmT2OOJiRAiV2IikiBMwaTAKL1LIAcoRFopXWqnaCciWZzvmQrgB98CFgqQ3BFdmKltLkuQGrDlc+YlYOpP8pJDrMduWbPNI5REUDEhlsw54d82idp48RRmQM/7jSUTw9Lm1TMLelgit5AgqbFM2UIvUyPLNsfYuBl/6NtJjBW/eDyVKM4FElzUnc69/zMRhfZVaMaCx7tezUUCT35tivCsdl50BKgYVR45cHdcSpMsyiW2owDkze9WGIeyhH3sYQjfs6PdG8KgtUE4ZgrCAD3LBE2cZvAUGIfJ0HFO1xYuH5Jv4vR94T27l+EG3MiUD/bEWFtHHuPubYk+7B+r2tOJGo53iSbMbjucCDR8uiNbefRDdtQs2cAr7S8IQxJnctVIncQ6FuQgo2gQykEERBqgvAvfbEwBOkAEpkAY8EAF0IIAcCVgBRKDYMxtwTG7rGVV5kgCM0gJUEXgEuVkRA7rZ2Z+EBRnAeiAi2TMAACaq57AIcD3+JLxGNDYkkkAwCVwNASJIXXWTMYwRAax2k/7ocrXEGqEm1B6rBrz0LG/dceXxDR6gKmoDCMZ+VZ/Cbm6ELuUbfkzX7pEY2J2geo4AywCvZ0UDFUgtIJkloEIFFkAD0AGcgQUk9XDwxZwi6sPA4DRzbe5Nq3TOguy7cu/fPxJwWmmcFmmd+Sm47z0ksR0CcHDr76M3JQhtp90HPr/cJyyqHKhxFHjwCyHdxld2p8WDttSpo8Gvhyu9uTIQfuSvEkNG8g9/Rdy0UDvstEuY3fYwZSac+cjgXqWFMkVpo822YsSKEz/W2h2VIFWiYxAexzD/SAk/PCGzpb/AjAXbh0H4g7AHqJTt+fbIEhiBuJjc3Rxgt8dob4utMtg4aH47bDFn6Owmp3CA/Hu/oMS/eYKV2V4cVr6MJ1bIUoBnzL6UVEWCwP453QseBUsq6T2XAN5zER6+eAR34B5HSMW9T3irfATAt7iMwB4YXjyIAo85DQbFqN0HlFI4hMdI1U74qgUOL+9ShFfP7sNteMgYPEeUD09TqqKmRk/OQr2RzmwdNa6wUstXskUqfcM6zyeBdf946aRPYOQe7dYzIuq4R9tW0o7qjtwgcBq9n7TmGIYFSqNLptTKWLFiHj0q+ZSTmK/DRfefOzgCpfC24Co2YPlYLlrWVqXFbLvB4eZXl2lX/Ldx+rwpxcKoQoFyLbjyqKlvnDOH2c5GycoBge1treXklM9OuD4TxSOpfsixxdR0ROg3yHqGJiVyQbhOGLpPa3Ejp9rNtxHg8XtZzrEYAjm1OPaf3zwXO42LCHQ0Si6wztuoQ+fR7thfZwzB2iPuXaoIsS87f2p4BPHkS2BxWHdFr8hgmEXjFamJuQtDw9MoRjkFE3mBoXal0pCv3E4j0KRO/Lbu1d5rK8uPt6WZt77W5z6p5aGoUlnX0SHVcoB4l+nOzOiW04E6hrRShH3hbWU3I9d8/aOMK9EV48M3F34vFsNB9clEGFvEI/DGvPCI9sssJbVded8VU5py2oIeVF3qBaOtk1i3+uJ5wxxmo6d6Cgmo5cCyxlyn+Uu0unAGd6kWs9LhFs1qtV0FupWAV+YaPeZ4wnomp5STp1pOWtZuvnlv1qFEF7z5W+F3TS1Cg0pB5xk+TdvrWpqFMcrln9SHuDX1Tcm64p+jQQiQzqbJ0gFfK4kGVJgNfDkw0AZvPTfnY5y1MiPXq6ZyDXJCcqId6lnXlH4oec8PA77s1gfK3SdVah52+aR6zNNotIm5EZxNjvcJM6yGRjm8DA7QmGY8zzzK3mA15xOup5nplLTDT1fJZbyBfclM16MdM7ip1SwBdd7zz/6ZoEDbT2hexkSVi3jy1EkfWNyj3iBRuUBItU1W66kgj1l0uC2S88Jco8MMJX6lVcrIUa+nfovKZum+7tmYVlmRpoD5CQL540a4VBz7wciAV3iNl762mJyrQHrO/ENNbmPG+aRkdFuUW6z+nVxa2mr7pia3nZH7P2T1CG50mP1BW0m9O8Ku5y8VltRt1W9lqZArQHVjT1lRTzyyaLouj0lL1HoiDOFsCs4TuKZiHZ7zgG3yjiCn7lpDAGAWXQjr1v7eO7DbHE0/UrGVabyiWTc5GUnObU9nqEogfQTXp1NRrFY6e1F2ZTYzyneLCQ/LfZCPWqdoj5YsGbnrk6Lxa5rBaJpabzZlXFJqRzg1/S6PL10HKj8mJKPyoBtCfYR2H9Bje0aHUM8VKSia+SxJGUmKYm2iTVejlAdmZr+qEEtnP7END8+tSQt0LX09Yyy6rLSzMLoZczVSwkDO0VOZDCajYUvDqVZLQ62Q5f4I2tym3ZUPXRQjgBeMYD0dAE+US97L+SwZOVOPRRzTEUcsbF9ntzHClqjmKZhRixBIuK9puc+CYsAL0J/IjREPv1ov/QhGoiB2kvDiu3z+LeVIXoTPzDzO8OwvTqqvm3+0c/IPsOx7Lr+gj/vdI9GUtxZzO/1OwVbZ9oGvmnjFT2K5qsLM3GbBF2Qh6WPbz8aSEh61EnaGZh67cn7sDOAFfRODhcfAJhHEaVlpS4AXLDllOYmhVgx4gRiMeALx0hTu+2Phz9lJcXhoeACby4+ETeFNPTdrbmxnVlf70vpVqerX9Q1g9Q0B3dyBvtFh3wdbTysl0YVuQ/SHrkqJ099q/cDm//7HRaaUroE+WlfpLrhn+6h0r9tZD0pHyW54KMaJhpG2pjOAvLf/cg7f0jb474f8Vavb+N+R4bc1S1OPlRaXDMaM03LiuZy87DhkCxzCCW8K/wqvTaSATlHDOmmN01NXX2mbyG+V17r26syUBqgUT41JG8kDdllybxi3rXHybEY3nPlcss/e0cPFzsd2N3oyomLseNylt5cwXQuFOsfkMD374/f+mUhJS3M8ZuFgCyeo82vURGsaYpff5mS9+qKMcbtO5lVVRrZ685Njd7s89SWb1XpEZ8nG3qUQo0JiIQFlooiSicWB1H0HTLbs259qsR8Um5gVLU09tWb3rpwwjsKkNNJK/9wstWrjlmfSi1/IKpMXJOqi/wozSmcpxssiidaMCz/SL59tyr4cFZl1AcwwlL8zelf6fcMRFPDPp0kBvklnbk5rEb7iGxIvckt2R0/viSsNTz4HzzX3+Jr93GCrPXS8NfvD+eFrny7/h1p4ORyz9jiw08Rxx+qdDccso44Xfh0c4d11Dmt1/Yg7Gung7uK+H+DRpLvMQdpRDaknIY9DZGyXO0CTgh+sF6+wdOFrN9nFTV8v3HdwMKVbqjkojmwiAP7RsfWmZhwzMw8zM46p2W3jdP2AuhnkaUbXIRllorB2aC6+t1Lr843ih00P7k89sN8UzMKFdUJhNFWBzW4QC5MuPqooOIATLmYXaYb+VfwskPuwDJcysripwMnl5/EjGdlLwtSJQLB8+0x+Xh/3q5fclL8J7sTclfzpBlENkuKHb0RlUU5ufa+QOPV3TEx42SGsLirhU6vA+kH9unJ4Hx7/IO0OTSzEbRZeUl4vQ3RTO8+r2T0Weozo5GP8mHRv5e3O51K68fmFEWG5uVEIKIftTfQTG+lXLQbEj/EmV/1AVaITowfI5JZrvxZSX5kCXnBQUXIsHNAQfvZMpudJET7MjorHsmKjKrJ5KwfEQs6EK5A0BUtzSXNLgBcMeS95j4LpiLDWVa9uMSBmlDdB+/kJMSRhWc38T6KbmJsZFpiVEIOAw1f2F/Zl9jfi2ohjdl67ZcY0eaVzZzWD6e2K/9ErwEoU3hguDu/wCNu22o441Lae5VztInYpPeG8rq9lNZXEhM0j6m5FYQkBBaEscWTK2XfsnD+0ZyPukc1+a6N0EzsSRvTn/lT8Coi9GCN2qkzk8hviPGNyAzM7bzdIwR68YIxPS2t/k45LMmD9SHCXxJR9UaF2WP2XMmPwjOEp975pLzxyK2yHvz5rQzRDQ4MGzFkthTZKablcZ0e5jExJK9AvoZeU2qmlpdLtnWVycuUdSjdRcn7bhamzg+fvdMnLoDJKbeemBk6zuzN0bYQCqt6C81qwnEWx0zvqdQR4yVmYvyO+B5lxEWU9jbqtoOwpmLswJ547O8eQZQug5x40feqgMl47uRnrliM8QZohBz8t9jZ/UuHHImKwmMXfWDyhckoKRz1Lh6nZf9xhzK96S1F6kC/9dLyeUqtLeUVVHTP4x5gJDPGJYKYuuzhLrlqsuKhBFA2saC3cAhMxd3NNJFsFv/Rx8vMQHDptNrcSy6pXSl8YdrT6K80bwN/+b6NMU3f/BPpv002FrsRYYe67FCk3RVn4jnwGvGDt9XcxGRmZH+BDdhoPtBuXJ77Lvpd6T1adfSOnDRZOP8u+r89Yab1z84jnnrg0y2a1MkZNIz0/v7jwGodX01yV0h0dldojyE5tgDzm6dfzFQWHHDinGD7yMTxW2evqKeKENPk8P+0Sofv23ejE69gHsPEB5zFHxLwNiVc9gs3HCNXS1Z+5pTiR6bDpD8ByalvlCHekdcHMZiBpAB1I/NWvx15vR9D91hbajraHfW/TtcV6bzKCbVjK/mNcS/Wzu8+VfBWMx47bhpT7iEwjTpw66W1rZsXa69LTO9iApJo6HrC1DrDcLsr7PHx29E0jrMcxRUzR/dap7cICxJ0xXSgTFfjp9Rrw8a0btsMecyYT5ayncikrOj4KDsEozYq8v4skpE7Csh4Nu8KYiU7ojjfr3b2HMteDHDrUPIQy0evN11GgoJwWDsrMhh3YKOcoNIp1tRvspEn3Np8//OKO6P4/ee7+RhX0gfJpO/PVHaKWUaveexiJ/82Ctw+H3fQ1PHyTtOHlRtdDDX5tvoakUWU976ArIOHBRLktXJRbRMW82mME06iPo7z363cPbx1GD3O8Xf3d3BWkUFAsZnJtE69mxxUxj98DJijSbmLu2Y/9PthbAxMOvP3Eu8FiNwe2fhi9DjMckxH9lY6LJ9knmjycjgIklU0yUfNwSr3roTVyJX8cFWrW0Qhvq1mPsJ5Rr9CXZEOxciX374u0gphb7ICzEbOOEZxj7LhyyXT7NjvplLhcSOFP0O+Qfo5/v2t5XwpLezA2gjLRM9rf9Zy0o1qzL3D/m+/4xmSKcmbmssXLg+66vpWeZQtXbiDnnc097K0+m0yf9DkJ2uHdku84GcOncJmY/jPXWyzyZS75b4u5vBjs4uBUuC8Jj3bXdNa0oW2SsKP7ZKQX3kqI8YzsHXUPFxK1MMo/iTrCK9/eYoeEBOeIcFZgbBEpm9V2SokKu5qYUb+uYYTna+sWrlxD5jl0Gpci3brYA5bIKM2GbNFD+p86KWLuWjzhdfzIfnfrowDcmuZKtEH9q+ZXKBMtS7zFKc+Thyzc7VigMzjE+Ip24jp6zsWmoayOrHq0ntGxTssbMQ+xUbYlE8zMFyVIdcIZ+GvX74LCpgHOew7K/LBVBFEhVa4lrhlGtRevmFy63GJZdfbqzgtXG3rwLiw/G6tTfu42zix/ayuWvxu12FGKsZFM/gZ4gSTDQ1paBKZBXcHzyNfZI6vTfTN6hvHDGEymIl34Xs4+Xrtvxo4K1szMli8Gpd2JF4fmJvJi032crYt87TwmE51bgocVHn+ukQgvnMxYim1M+y811RdMulmRPtgjs1iPiJ5Rz4gZkiaW2Muviqbxw8GwAyfyc/0TOqBbWxDfBdvX4x7hlnFjHdHKRRhly76JSvMO82EzIC/r0Lo7HQ00u4K/ouUPy39pZgW9bhwwWogAZGYrDcQOJxjeqkhOCUCCyg5S33K7BzkhwCltJAm0gbHZCcNkjWcQgTP4xDC2hgiv6gP2idVCSkgIaaOSCBlBECuErKAYqpGOXUcqW65QEIqCbpQTUNMBKz+ezTbwwatcE0qGlkSr/fMs/Tby99FuzzzzJQLdGbe5SdfBchaq+lf7xMEO6n3V4ztQzki3RZnL699Rv7y3v0EeniSoBLll7tAIorYE6xo03iSB4frYhSVQCcrYUFysNDfbuj7kq6mO4o2pzkI2ijbRmUaHoZTOSNlv+FIJV2Svj7WmRtL9ilZ9qNsrP9CwQUBd4J1zqq7/TUt2I0oa+cgo9YyVx44s9ngnjVEstXyrP04mBugLTUOn8BN47YQjhTrU28ewfnEg8uvRCrSQurE+rgYPzfJAepaIif6a82G/uaO6w9QAAWx/EVAIgKZ+6namtHNO2/9LKG8A4M8XOSMA/iK2//5oLD0iOWyEAZuAAUAATP9jBtj0G+y5vEfd5RerfvRsHvEGxDIoO5SSguLaip18e/1exc1UY4YwLEkonshLOR+7VivOFwsHWbqt2Lq0dyoPsWuSENeQf2cuq0wSm6oOJQEYfZYUlsexVQpudHk9VkRGqKw+lbVMrU7y3khnuJGncrCsqw6FJQH5gwAas4FCPnag2hRXO8Miw9bhzKp+K6wMubNS+fytfNApjd8qiwj5Zc1v2qvLn1QyDivz5PVTePmD9uBYkwqOZDl+BsrLCqoDC5Z5KQX9O/V6wD4f4PXZnEcu/vgovhQxRlCG3ny97WxGqoIMpp0h64XU248pa4Ywn2Qsw6zj27LXi98wkl86KqlU/qb50EE6fcbrMqVKr2hVPoXUK4iOoza6o17KFVXV1dyE1Ie0a3sh5SPGrOhWqdIrvxUPmpuEvjr5kU1VhzYuar5p04g4GVCBAPghjwJL+CtjtvIVxuq6cQPYsIDgSNuhj8EpCNA5nYIBGeDeFqu7LS4+BQ9a+CTAnc+/Kyt1/Ff67yz27UYGhlYeBP/ny8BCbEAm8qZ6ZyTQKF4WDph2txqY5ZXtWdIubJTdFFtF/iBWyQOoqY2szWAcLHbqexZvSgtLI0Nbh3d1SEwKy+1jhpbwqERqxkryfYht5vUdq6QG5T1ejIUBp3lSB0Pj5BJFNYQSRF27G4/laT+exYVVows=) - format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAAMAAA4AAAAABWwAAAKuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGiYbIBw2BmAANBEMCoIYgXkLEAABNgIkAxwEIAWDAAcgG0oEAB6D426JQgSiDJGrY+EepR5ejwf4/fWd+/C1EBKYZDS7sRFxHTf9uCJn/m9Of4qsOwRQBbqEex0QSbKziM9Pj42dA85/tYTLU84Cj+f+PIAlq3AtV5GCrQWUqr11TNFedSEUjKs7rSju46fX7RWCSHFAeYQcQRBEKIqiAgIKlGZBdO5a3w4akEBWj6orkgSzThrq5iF0WjfiKGe7e/0dAHkwOR8nW+GblHR72hyEGmzEl02NcDPu9oBKt35NVVBcoyEuIJNhau72SE3EHkhapkdqCiZGhBhliQWUJVETSCQCNfr8o/boWoBjI3miLHqQC4ojH22AaUBxFAUpIBJlJeIVGIvLFI6PlFi4hGYVs0brZ4ZZlT0rbz1SLT+50xlW3X269vh2x+CpO/n7bw02ebvIys0wMkpteMHUIq4PGfxCRBdKjxXGaDRIc42rK+a/qgeebsfBvjGMiQ14cnJjW8fSe6fHlr2NIrgbeH2jS+k9X+md9WJP/5IvZ8LRg1cQ3gz+dJMePnr2/6ZSiy3c9rHc87Zj4tqOx0WLe1U0VR2OOEt9kq4gV/r/NBEyVbPvpL70poCoTunu3LVVZ4nW3xWV8gAKP5VqBMD10Pruq+7/52x5c4B8EQjkzs5oyJ/1JzxT0mgEACA3XjUZACFDut7UuAEqPZepikCuTcprJBVAcSJREzIBeaYSC4kSGAs2BJU5IFLcQjt+sxNAqr55kwOx947iBrvVCRYwpBuDQusVLFWyFCmCVcEwCg8JVsPPK1GwEjxesNZJv6dyHtID6dYP8UnUCvPAemHBGiA+jD6CVgilD8+tWyfSPRiYXwVJDNNkydPUzvrRmeBZvFdArqSTDSCJ3ALcvDp0JBHWjTK8pb0Qvx7N35CkXo0yFRq1qZAgVaJkYiA7H3AA) - format('woff2'); - unicode-range: U+1F00-1FFF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAABK8AA4AAAAAIgAAABJmAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbi3YcNgZgAIFkEQwKqUCgdAuBSAABNgIkA4MMBCAFgwAHIBv5G7MREWwcAAjqiQT/ZYJtzPyxTqRrsF1IYVrRiFiApETA1++dMFq11kZtOhdxHMTvna14XthLn3dGSDLLg/3yf+feJLvv07tDOZClulqMQCikLU04jMMxKJjN/62Zf2Zn6Q/sAXIBXSvkMaRJCZJ8M3t1ycm+ClNhKzzhQnWV6OBa295MdqJv5linkmiJxg/83P7PZUGHMCpH9J/UqI7hqE/HyFAf5qgQjBlEGRlMe0AB/E+trYhYqhYSodDoJpHmFSLRpl9DxF99b+bPbd/9Mul3vXfutinJdmq2SYcgiepGYMWE4fI/gv9/7tXmntsM+A1QMfsJvRlBau7lFt/Ph5aTlIjyh6Qqqytc/ghL4MaOQM7h8RPOAfrZ2RbDVNs3+l+IXHLYYLCHNa0644xAgqSirxU1gIOBlbiLdAndYX0II8IgTDII0wzCLIOwyCBc4cKu4dlNFXaHP9sWTtyR4MD5NAYg9s17mSKyvOboCQrPyOmJoPAqPSoBFN6HZSaDApjwIj0ZeEAw0AKQ1TnJabIHH6vLIPPQAK6M/SiIkW0IU27qT8eZPitTe9bPj6GSZmEW1pHZLyhh6Y3R1dDHYxFqzxOMK4/vhwnFgAZIozS6RzpKqz0eAxqnF9ScZH1kM+i7/1xvAP04Y7L9rQhtAYwt7Zvs6TSmx2iNmchBkcSIjOt7rG1iUNHKPzN5BupWHYpP4V451W06ZyFJ0F6gTvCrVCv5dke0eIM5HaA9+0OgHG/SdfBq/gtKLPcNkwIYfJxc3Dy8/AKCwqIS0jAECo2XV1ZR19I1MDQyNjGztXcmF5gV75JuhfcjmtBT2C5cJ76diLsGUSvXDGrE3EmBe4hOOWmQJOeK88ShqHxc5Zt63PibyVezb8RcH3g+IKryH9Q/gBANq3AgGhFPSt5J5aQzsDI8hQxQATqGCWM/4r7j/5kHlnfWYduf9hGnsPNPlzCtcFk0kMpDtPAssowqoz9iStiUedm6ZB84lVxKxMIpcjqZQgnM80M0HyWj06J5PlqDcxZobuk0lbmuv83aUzqnCUTrUNHOiAQSgl8gevQrQZF5h4sj4rQ8Dwl5a/xliEVJmXXEy02EKZShAC3IQR/KUNKLpHSRd6mCXOKfAgoIJlJ1/lkkK/4sQS2Vkf4JTy+BmPkmvIM1uB95FcqnWBTlH6kO3trKI3TzAK4GJoJpJobFK0ngtgpmuMsDJ6xuTMKW4eyZpPMHlQKhWxM3cGDAYTZhhckJ27QA/wa60QNCXJgBMppdD10DUqDc99jNkVEE37EeTVjgY/exq9/DeykXkpfTJwS4+z7lAGL3IgDMEWyQuIpCLvfjL0cQhzIoY5bxm4E+YE1Ad4zvyyrVVTrAkIQdiR3REyB08wfsXrl+w8UGzKI0bi/wH+Dl2jVhAOwHJKGopPgIU9F04QlCYEwEPwd/io4QPFR11EZzDAY15mIlNuN63O4gSuvz10dLDMdYzMdq7Izy/Z9kDABEZEYPFEaKEQcE2qy2uCQLuO1aZ9jlORQUlThvXPdt2JLQYQ+nx5GkASlD0h9AITPurayQKQ+evHjz4cuPup1AGrY0EUgUGoN1+DXTbVzID1qEz+Bnbx6A3AJrFxjFYNiCBWg/wQF2BrwOZmbLSOegl+CA4wfcef99OCx1J6eWH5zMwg7GZgyMBXX0URAqJXSEjUaGgQqxQfph2Cy1EGecJxxRB/pCn+5At/p+x1i7bG0JB9REf5MJA9012xqp4QbV2Nwddg4Oht3NLb2NhqIyFYpBaTsqspIhs65IVtRLvStJ1ztgrUod2LYscl0PGPOhnFh6iWR4BA3UCNma0DUCSYrIlTobr5Y52om1M/28oqhCuoLOXhmrO/e8E1QN/HYroSQb27LWzczisvfRSbQcZ5wRFdgkFlgSHhD9ChWhHs5u27MiFWCoWDOVdOGeKhZUqahfoYCyjtit6qNGaGJkWDPsxSFU6gMatNbK2hBXrFOv1ezB1MpY3TkZ+OaomFe/80ecEanr5tO+DHB1z2COtNcnCCzU/AGOjFByeZY/geQ6njv3OVyHyQLM+gyokWSlehRVSTF94DWEyrFXXGuEBorAVGEwhskefTMVImhipSJrBHOP0o67tW0FyLKuxzj0NJPPrSM3sdexZ5EHkwd0JE/6iqOTDRkFpFwRXz7KSx2BRwCbCBSTWcayAiv1XQOwRx4JirxUMiboo6yFoHCBr0tPoLWCrY3NYVFNJN4PhW9M3EPDngAloTrnZWSyfro3Ijk6S26GI5gXBUtpIrgtNYs46LbMr9nhnBMrd9xVJIYCskvWkICQugdLG2iCgeOkJZJW0rKuvZrjO17NOMPXB2uG0Yq0EWCYKlB5WaPzuIfkZV/Jaem+jsQ4UPBopGny7O+n3CQk8qLw6YmeVtL50fGV97LmeXdb0WrGOLL6wRQmqj7mQlyz46YdJFat/gkYf3XZgbcPqdeGCEXyHrvKQx9ZM9WTABtljQX68egqAu+9iazbIEeMIztTXLCkBKPSGgawR9roqGzXnNGE/YSBCytXxYtlV7FGEueLgtmyTMV535FH98G/IcalXkmsunu84y7nwPY3Oe5dgZmnU4C8fDC1BzhTW3Ykytry6a+S9b63/CTC7uMjU/BB00cFtsgkdNb4KpllmW9qHM8nTw473U1BW3ml0fJbzacKAt3iadT4y63LIUzhnPt8RayRUSHjhkTDPM0k0K36YW5sycJGSh5JPQPPSevb3tr+vmy5/rfZPL3vKNEAQ6WhogIBw8xbbEX6wp79YhCFBFUiQSiY0/LQzXJnlomivpDJorJE4I5dDwAKYKj0X8hlWmRCf4xqlmQhNW8D++CHYONV0eyyrLgXb9D4ud+k0vjwxJyQ4p9gkl7tfX5hdRYw1LH1yWZvcCsERkVNxR5gqHvBNcEM6GcAhsoAvcyRM1dau3qy5tTonrZ4qewlVTWQuEwVswwU0w206e35qUiR2MvwKbGbYSKFT+mVwS0V9pQorKzLAShNcnL+A7fn47dbzPlOTYwJnGozhW33W21WcKiRfCdazeAmA707jfw3MgvIe8+v85hj/00e/IRGcQmerxf+O25v57bIpz21Vc2KuoIjpIbafMQAHNAvr7z89/LiegkotQxpccrN7Fx4pGgo+D9BhYuPZnfkIHnPeUwEV9Ihsi+Ca+kQhaIVtlWjEQ0Bs4/rkgPgrNCfv/+ikvKAR5TtLctAzr+XVW2v+DT3d1mOVy3+rFyeG6ldJmfXLMIfHS4P7D/hTMIN4RECAzC3vLXNLUgWFpEWib+PuKY5fSZBxJKQh9T6FsX/RzjCRyc8wXoFxLeQHfUv7gLmPtStEOycyu2dCIed7MyIDnbw+WTKqV3CLtXL5axaH8esmh7w6BOf1Pg0Au712VdFys0+6toCaqTYXrxEMywyXw68jH0kPaDwg0qXfUX1TQXPladCJQtA0Cafv3g+pTL6C1N5RzsOM60H3Wq14D8z2sE/9Jdp9CiM3jlQLrUUolhyS76i/pD8QeWBhJWLqxexFk4/r/zEZCh3rneCmxkwXhbJ/79DBq2L29WYxVVs+zXiNZOO5+utFQCTtP0hFKq++q9JzU+kdhg9ujd6HIXUVP/sH6jbQ2pHUON7/3va03+2B3OmCz04ZWDW3zcw2YE53Y3tpYLuRYtioYZzx7/t/WX6IaT5Q4TEyPoiJKyB+n7A+AE99Rf+L5zIgMebGZI53DBMWu2511jfdXcj8kOBAEli68/a3fjobFxf+HSdOLpv5Cimt0FiKqqdJBsffXPtK5jeJGCZcqx5W4Qn8I5DukNRgxcuPRf/zcn2Qo82Fd3GV/zCrI98ilRrVXHVqq46o4AGCq20rW93xkPCu3w0jqgWLRZvfPuwc5Tsfm0XMKMZuefvpjg0+6dmBYUW5sce8nHrTausTE4iN0ZD7pztTeAkfNj/JyzAs0bfFhZg/wec6PdNN0Zm7FIFncUutenGOfsZ6QYtEJ84PxJE1sS7yT+elrc+55VBHZ3Zr5QW8FeMqcwqHqpcIGeXL0wfaVxNFCJXnoMQrcDYgjBJb9nQI7Ztv0auL+9PNu0akZ39gtMcTY1C7OOunt7ZYWoxzfOODi/yNd/tRs2t3WIeA6Oj1Kb+H16JVnMJnkZ+9sIPiaE45zA3G/Kcm3FeZGC0tXiSVIzYJS27WEOXGik51wcMo0sgSCOwF5PaLkyfusREi6R7JAfFxrZZkXnpBDC/mG70y+7Fkz9maLV3ej8cXj//cRitdlnmpuYmeTUthby6eePzTZXtnO2npBVkBURpBDZjQROV0UU7IW8RPV7glf+XmO2JcxGbJMp6Yb8CarlTNynTRyV5hf/HNVYRAW7/e9L2tkwyg0xTZ8FQ936VrE9OhZfDrHjVldpwifDCChFispyiq0ESYpMz70IojrDFuyjLfmSycJAs0M2apjQNXWpQS1LMrQs7htBedOapgn1LXr+9CdZU4Z2Wv38Pxzx63smlPJCPdH76V5eXe/eJ2IWJOBKK/mCXSQpBqZpntpLyTk3M5tLSo0nnB0C21Jn28eHCy7DEjNC04oUTYiUtXXivEENNdyDaFiw5GBREKig7qSnNmXF90v+4B9uKvdl/HlSCzQsS+1zTv3ryh0fFTc+5VVEcn9llHiNEnWal0dL5nKzChXM9xeNZpPKzYHKJHOt6+ISOYpQ81UU1UQBt6Ol+4TQIyxGqUYNpjW8HmF4niX9Lf4XjQJm8Wdt+BndaIZITdUhc/2AkH53u3t5kY+WwgMQMdq63SBRm9zbltXyoLf/bTJdWYhPdou+2UERGzrcjbbVLmQYmoCdHKGkWO7Yxgn6Wwv/5yHN+NE6PQ3STvo2SYNMG1k/0t8Hih4sB50koE8J+PBe66hsQ0kOx/ueG1AW3+/viy53Dfi4V+Fb7xvAmfu1twKOQ9nrtFt5QXlewK/ZpsWDLuv+HcesGgr4p8QGRyS+qTw5PLCvJ25Y/4JvLh0Zpa0ePL2wtaNuzd3nJJOYNxktaoTqTdM1tQZbOvPNLJYIcEmpNFJW/QFMi4iwVKHwMHrk2KUszVYrs+Xn7mLwI1QSIsigp1O89i1tRXfwc8Ezews/nruLFx/S6U2bCeYCAQvUbnSIcpqK6l9xXHAKj2oDy9u9npD68LcjBfQU4BOyja2O0MtKQpxs/Qu9cvqCb48BcmK54ud+zE+s/cTwf9+vgt/AljqP5xPZUczQyR2wdDCDAQhswFYgALNDxCQOJtBqbNCxlKarIstl4EMAElQB7BibonuMhR6iP+pGOaavOlvphYkEAJHTRw0b0McAQESUq1GiwwRwpTG/p8GEMvXRz/A99DM/vGK5AjqOonERZSEtL0OEPCBm98yJdsR2bsNXVTKPsh6X0fkzL+2gFhh3KyAzjPPjjxYdMtX9Z4cpgDx90/2sDPk6rMRru+IAyX4gbBdIxCxmDiKRZjP7FoqHmSxsLpJYIY7oflN+saKV1cX/p4plTVBTH8BgcwVWtnTIoEdswb118MQUs8SBcOLr5whWNB24CHqiCWeA2KEvvxvQmaZatrO1XXJlgtbkkL0ShzSdHnl+whdHY8qOti7BFzQ9nzYIdUg8yIQlGfHnjdNa8hdCSOM0CxH0L6vXe9OaaCcUsT8MWIo9NV+djsuAXbRDAlD22UUcm5LDRXxbRHQC+f21UB8AvxP3335G9W3uBuwxgDzgABsCauNkB9hKoMfvEs0DgZLVnUSvSIMc+KA98xQFvshylzqJMc8PFDm9WBEtnlqly0SUx6HwAXzzi+RQzeodr1nOJH4SiTFAuaO6fuz471M8gV9BGXuPOZumuZaKVI6AM+bJRYo3pzp21qS/s6wTLCpCQpbzzirbkYq0qeWao0BRzQZ0ryEEZ84TRjCeU/O5Jh5f8hWlgmo1Rxyv1ul5Y2yxrhctCEZ0TSJnbyJJGx+cXyfKNqrObPM03rboaKssNqZTuzxNdqQP5a1YtaEL14GxwbzDyQLpJM+klTVQPqhPVh2oVl1joZ8b1PbUTJL3XgAB4poGQIQyq+iRkAtckwcWOvhAKGJoVwEOALWbQ5biYg4Gy2Wk3i/FiF8b8Ck/kv8EaWHYFLKRIRZYuToxYmaSQcESY79OSwoUlilq+I1kEdVEpINE1JasZqIjKVlHSkUSJpG56ivAImYaUQavSjMySRMkfI0uisAne89NliFOTlQDKpXByutw51q3xNOEjPRUBFvBbV3cpyoeJECuKui2bLoaGL74UVZM1iwyx6rNjwYozj6TiVSTghHCyWzpeJAA=) - format('woff2'); - unicode-range: U+0370-03FF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAA2QAA4AAAAAHpwAAA05AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGjQbhlocNgZgAIEAEQwKpyCiAguCFgABNgIkA4QoBCAFgwAHIBvzGSMD9YOxSif4qwPz0HjxoHC9VRNbrMu/12kLLcb/5dFJkAyh0DCYQABqQVD7hmAGzfIo/4k/8899o8ALZ4VCytZgim8X1vbXSKk3P7+/99yvLGmCnpXn1FfyhvB+f5FagPgStyR8kP87bfntzf9vCnc4PA/hUOgM9tZ3O7ENQqEEaozVJgy1CWz36yYeaBRQZEFQSKmFVAH8X01TKv3d/p/dz00uqGnOCfsA5ILCOgsLIdKmyIp0bqWzlFZZCAmvpUEHN4DDYAAgAZDElqjeg6N0eSgukSleVCbzvyIQgwsAAGlsmHB+SKQIJMsvQgyAA+BAAALYpKlzDK29MyjOWJmF4grDGCgeV5WHIrQ9ZR7cEJdwAIAABsDgMwRaIwD5JAVwBn0qhE3bhzqZED5wH9ChbwNV0I/Gbp7Y8MvXnHL8+34hgHxO8x7nho4BIfruwvrFlXJejpEXr95QP5TKdnycP82rfo+/2cIHccrW0TMwMjEzb9GyVes2IdH/CXRWWWoABZK/QyHXnNr4t92jdch8kcaXGAOXvZup6l10nhMX0N8CsFLyssunnZMSac8IgwZAgqUFmUGzUj8AiaSwIQA3qBLkFg5fAuVllk8PQATTamBesoC+kDLBQjVbbxgUSZJkSXanLIgvQOsTs6yhL9IgrpAAUB3Pzx6vAjA6hXjSSo4rD6lWA2NtUJnQk/6SwASgu6ozQBLoOwDgZQWMJCSBGZHt8OQQOEffex8JDxgkMfISH/kSimD/c/9L//ukv/R/gAzyEC/5UAsN+b/3v/C/Kl+UzgQ0M/eZw//1erjoYYUbC+5fXXwxAzuriHEqlgb9H270mw0AZLrcCoBxDOCVAdEVYPEAAHG3XLofczKvYcmEVkXI0Pi76yaAs3tnYQ7udZFZMXmincQeacG0eexkHk5jx4xx0drpYq2EkW487uIKpW4VLtxFl9sZ7nGRueLdMWN8/HD925L4kb8r3mXjiLfHOqKcTmOI0d3wjPEifTtO2xh7/MTL67a8mxebU+qlW/MeXmjWNPXalne+KSZesOf/T/Ey5bYt7y7h2OXEPHshwxnRh1axnsJ0s9ioQLWFS8XqjowxcmB+iMA4jGKGxnuyiQi0YFvWD9DVVp1Mm89Tu0hTA40TfCidkFVhx2b0D/DZ/h6wUlKuFXHcPJ0XL4JzRczTkvE2YTqO3LS+9k/0aSU6zBKp0PodOK0dPYA0pTRZlaUcLk8X628YDcOg9Uo1i63iArYw58MJ97UvQCAgRvUGt134eMzpzPt+OuaJ4Btax4S7MlXeW5ftLl0o2RKrSgVqt0q7yKD0fhTmvVIthpIjLNPUhm0HNKspGd+lN273ov6JSROz8bmfV2hK78GgOqRwzjYMAcNqaJWgbJw1D+657xwJbNHsBuZl1kiO7ZB5msExOrcIeXk7Z9FQreio2YzPnL3VN3FIK4RL4osobCD9ggo3q7E0cnxZ31HbKVAa835F+/XOWPzl0xj8BWM0hX9+/Wc6SrFyL/NsC4TyTq4x/L09+tYPGGjtZqI5MlC+SJPiwxrjsHdb+Thl2Epcd/+vp9ug4uDZVju3bG8EYuWq3bVlVvjuE8Ba+QmY3lx9vgTy/b0Gofx7mQpONs5bpun7u6vvz6WqOPuJv1hP3T9PAnrY9Nlm0fn76P9v9PNW7t3Pcn3/wGV7e/TT8cXltSWcxfej/+f6CK1/ygpaM9q/ZAUdykzcUblQCZKCpw47hSPATHuNITHdbXubcgfAxqdLtZs6eriY+5qpfm4VWbfdYtz8w+3o/fcX8zb3GoOB8Zq/jk7JznZsruVgBuqnfbhXcM/fviP4XwIbl+3BfdPH518VefG8Y/zGyKUaU/erTqqMmjANWobd86e88P841rwxL//uWYzhtseW+XV99G8+09MSKrtc9rapf+cxOp907Amfih2UACa8LPuSokvXzM3QzpUtVSuQoRUA9TO+G2femllx44mxvbC0jP54e1bVU19h8wXub7Nmv+XsmGovWIgdkT8LCu/s3TtxbeXo3p5tn6eP/4Uojbd+LnsHb+xvrjD621c7ex6XeL71dNu2EH39lLZRe0tIEFYSEeEF96BO2sH/NquRqsax+vSx92PRy6L/ZJjb/xs8+aX8S5gad2uitfBFr/qP+s3IoT85baY95uSYlOa/Ytz75H2z4fOdSwptxOv+49EYZfww9tOtmRUPZ1VAhXoN7sqyXu2VVnEsNSZ8P/rj3VmVj8MK0MdKI7oKZvF2f7/bvlbHSaixJ5vP9lrsb/2YN55aPlzUjsIXuyN8Q7nimbWkahVMfdJH8eKP7CtL6yvql5zEYQtQaN3d8f/Vcw+vKGk9VFsnQzcAgRLDHvQfX+qSObFnub9iMwIFg+r3b6rSucz3rYpntCyEnFd3ZWmAq8alBpZhx/3R691SsV49bTxN3HpWombNDO2aftqaGVo1QNHTMxp7G0FhgXT6N35ZJRzbBZGsUy63lr5C8T5HN4TuSAExeTd+YH9/9tvCpsKzYkX+uPq/rREl9l7MO2edTuj7w8g2jee2u/YG7+1ajUJQSxHvt2wMlwm3RyRUnCR9ZuXb1JEJVI7Cn/hnLkQKl7JDS6buVWzZXqnI6CqccXPiWkVVbumsmDO+Mnfs1ngUFrCjuK7H1nePKtRtpdu/MYvK8jvWeUCyQenqNQzkil2NVpG10J7Fllwsnb9tMq4uUq9MNYWHQsNWev4Xl9IYn2+rVJ0yNQO6CsUWuPTb+2nLTqyZk7govUdsvY7+miIzaub3r0rD6rkzvTNx/y7l/PWTwtHcEz/LFf5jX8U5d3b/tHP20zOtt8fe7101+BRGBjgAhTi8QSspgoNPBIhMjNdypAwRnEv/opY4rCEZ1avIvEaUVGuHgh33F3Z8Cm4fAcJ7/IIIbMseP1eFakWCwKLyIoEXQ+rJ2EFsPRLJuSESKdhLAlpK/TciFXuIQkutd9VOs/qwotPqn+SZiF2VtN+9ZCC2nms9HU9JtEcifdRHTp+UNklk4AlJaxkjITLxHK18TeYY6cy8S4sGFjeaiFYKke/ABq6aYkAjEvg2qYsEng6px2M2KfdIxFejJJIxlXi15AohkYJZJK6lVH0jUjGT6LXUKlftNKuPMDqt6kmeidhVKFWC8a9UpR4qg1iMjBBrPLTWKP4ASOkGd4CNqjjBBFBPE2/U/4BPIGEED6kBRc5Rj6cxKHKJejwtQJGL1ONpDopcoh5PC1Bw0fKLWKm5axKZGEYnJCGjxBobQDOpnYpPascmkSCoSU4k8HpIPR7nSLJHIr4NJd0vsAF0xOv0d2lh/gkAvASSlm2cz9GCl5TKaO/8giAZwzXWOqSZ1E6lNTs2YiWcnnQghtfpTxDNL5I6jQlo/RiiHTqGGFIEVr4Oj/QZarT0GMY3R1UEH7H1WVUZ6guPIaA6f1MmEinTgKBgwxc6EABM0AO2Ex+bDxBVFSNa6xD7Le7qEcBYqCR0M2CMFe8xTof4nBLECB1i38Ub4AD8nJKGw6yDcS4BfOZyAQkYrc2v2G9ef1k6UyCnyRG1FTKAn8oEeHSRg7pOjrI591BlLXtYPUe4P2wTrGRCJMHgGoyiYItyiLJIWpI3l6WMZyDuImg2cQMBo4kZ5AS8PjGAqWWmQyFyGpXg4g0ShFtt7NiUCTqPKsZ0kY2Milysnlbpyx6GO/eHbYOVsp8k/AQY3r4LAPosx3PvOuoSMEbqU1GJOEP3IwpmsYoG5mKuxI3QXYdkpmaYDgXJzEhXhXTcyQRkUuSgbpOxNnKvykX2kHqO5KK2CVYycRINLSN7lcSezEhAMAmZlI+Jb8wMMinMzDmxvBvjevE5AWPEuIl952WfKzqTL6dRvFRS0IwIXvGGboTIUCrLxCNmzmESjZnBi+DlUObP/FzAcJhudo7LP7cwIzNBBd8o8Q3G5r98WAIQACPV93vL+zZnt+JrS4wFAMDeZ96CAJBHZqEPaZ/zrA6WcABWGAAAAlRf0wFY+6iYWQXbhQfds1kBuoKR+c2LJvDxLAQNCD+JLHQXMhjHH0Cxr8GMIIpwC7TmGWjA9dHEIMA4XoQGPAwj2FM4jK8wkL9FA4MeC0QeWvImNBDtGMc/IZo9Q5AlYBi7xGjgszLwmZFNYSFDYRgnwGhOoA2SAMNys7VQL2z0W2+4vYHx9BqDXjfj1ugPea5ucWPFs6H+EsseGAvWvYTE9NkW6fk6jBSjMbk9aBBgZLwY3+JIydwi3aazol0qmhOThVn3YulgxbpovJwf0WAQBJhtgUgHnAgAuMBgNLgQwKI7O0o8ALQHkk5iPegGl5ErsvKKHLqQ4cuWgL+rdWnqnzqByCKjEEiqtK62TpaYtkkwwFnYuNt4r5r2ckFlc07MjiLa2LgNI9NT2Ztmoa/ghUClirT9YgdFw1lsQihjPdvUi0SZgnJ4J2qzp2dk5mvl0aLpGkhmliiaahGjremZmNuvKn9Mk0BG2Cx3vMLwns9H0bJn26p1B06ta7hoaLMbzEz39gYAAA==) - format('woff2'); - unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, - U+01AF-01B0, U+1EA0-1EF9, U+20AB; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAAB38AA4AAAAAQFAAAB2lAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGkAbjgwcgTAGYACDFBEMCtpgyyoLg3oAATYCJAOHcAQgBYMAByAbrzVFB2LYOABo7N+XKCoG0eD/OoEbQ/R9SCk6Co0tw5CRuS8arZIo5VZbrrY7musceT/cbsXfaJajqVAAOHS7rE8Nn8E0r4xcj9HQSGLyENo9/J/JJtkHuhJYwShF1IA6foB35wd+br2/gj4YtEodZQCDdvSQBQNGiaBUW0hECBYl9qgQBtJtn2AVZZEzThmyRLewajg+hAIAdLoB5bmyit47tW/GLfGMZG+h//8rgFZ49FiVpWy2tGZniPyORbvwKuEd0KOOc6348XObtI1W8dDIX5AUyVXE7t+boXK2LbWT3F8dhkf+XpfZ6vt/TbSGQreO4Vg3o8h3IegPpt+bpGiAi2r11tJK+v4m2tzISLthXVAO6JBCXDGsfcBcB6Ho0lRpytRpey7aMh2wOd/POiNw2t4rRgif8IlggjHafX/fcy1BZNpqHogH+uw11Nr+nq4NgppcfiAEFEEA1oaCpc8AgsgMgoQC4acE4ootCAQKmAeYBwIEMBdFB2C233H3/SkfGXvGSZSPDTv6RMoneZ91CmXIiUefcQohCEGiAAEUoMBTBXeihZZ/wgB96MMypQZqmKdZPXzQjEIQPkzdzMx5F7pHSX7VYxqc2zyfPbE+8nv+gzX0A9fMMYTOgwm9iCQbTxy5blecK0pwLZNcmpRFOid1I3yi2E2ImXRhM5dfHFde8kMgF+c243zuLR90nqpa9gtDHPabzAjD54QfJ2UuaDdD1rhQmwT3snJ0sSlgAULZ5lgR50/VSVufLiyNLqnKlQiMN+nZzUzOr4S+lsfmY/BYlEMQN4k8Raaf1L6M0QqQD7GuOOe7yOjzgTUNOBRBQpxwyiqsZ8n2pUYbiI1+/LN4xKFcDcKdGVmhjHU+xJRLbX3Mte3Hed3P+6WmpeefO3+xoKjkyrUbt8oqqqprauvqGxpvNzWzWu60d44MRpPZYrXZESMIozg5HG+P1+f7L0krVq1Zt2ET23c/IMx0QABYXLHzFjiO/g/hy4oADVd3mIlKhDkJcxnfQkynKhgIdDpYoFt458GozIkWFufGnS5IQAdbGJpbGyqCgjN1gTv5mDaoWdzhu3k7LhkdBRkVGBHq1uEcWVDeAAUNBXML3Pl8+JHOC85+Ttg8oamjf3QAxleWquPcAxwu/ZnIa2F1rIW1ovSgTjr1yFZISQZQCB7iSZe0x167r8Bsz20OXIHBvow9LG2SImEhOoUyVXyCMs9RhhAc2yYKBUUcxv9++2MLAqVPPwTmvrFuKVKh6+3xHRa0O5s2iOXphOFzAQVAjXH3s2XmaMEB2mmvvXZiFiC/MA7+gmPGqwXkIPcB6qaNRY4c9L9CQ+si0BAtYuKyT8aOzGDhYv5YMJRCJQihH/SwD88IjKRIjgtREGXBivXYQZVFv7guFzJbyWQCW+a3nJxcJdVTA7VQD/WzyM4OAVkg8KEcqqEVBmEdTuEVQXEiM5r9f4rkqclsKZMCmzLf/RVU3aeb+qLyhEAGiTNA/0B66bGt3g39bbnmK7/i2wowzb/9x4/VjjVdfS+/PnDea8P3z53pp7pT+ansZG0hwPaMsC3xUTywhz/VvTf0Pob8v0433HQLU5lyFSoZMrprr4sxE0OGjRk3YVKAwOfEN/+d9z74aMCgEaN+cYJA4YbKHfMD/B8Q/wbuB3MuAua9EYzPg3o7uHto12931YRQbR6l6zDc/ToounKPdAly+el2BMWezuzCY3QXQmvw5u7CKFAJAd9lCe183x74zk/iw4zvRrHiVoHTX8veWNrQa2KAVmorCRbigTVraLwTs8ZeOyYCsO6d6S04BBPEVCIAbVRU6hTb3GSSF9vaEylmcQmAUpbUVgG83+2vA1QZU37EUbZZShnT3x5eciZ3dfr+SzVh13mjxaSs5ehkeLpWnuBpIcVICTfqQW9Id6fp9TeLbfw/h0dFPdtNZMCbcko4Fh0uv0JL8A9Nhr/iY8skRVTCgiyCDlolCZXi7hxY8Nnr2lxb0W+pZy506FhhKZTKRHFSpqxltXDmjRFGtlmDjyYSinWH+q5Ru27iszSiG4o3a5qsP4a05nC1pslZwtKDz/p8+bUybYQCGuoUVGKUOcinJnMM6kEHlFsluef/bG+3Nw5mBtQmrJL5b9fyV3pIayJqSLnCZcn8naZPHHA2j3p2ByIMato33Ag/nuo6oXSidxdhCaXAZWgWcFHoQC9+ozpv6rCY8X751GLOwVSRl3AR8BaGYF1m2+gK1dfE2L4Eb9aI8s02Ti0y5Yb05kduAiWFi3Fu4xDeWsIIitnf1VVHE3udxp5vIo6HmS6y7np8qMshc/+5klDq5+JFRsKacj5oEQx4OjbkCkcVJfz2rCwf/04Pm4WyyN6xqmdrNfeDjFHT2kZmnVLtd5JL5awo3/S+9lG94VOvxcqbKoFn5nerXGKx0fz0bbT6lnFwveYIMZ6tXcRAid9yyEJHT25KyLEIDsaUE79YPeAhySbXtLFGE15XWg43df1LjLHvBDg30ZiLxccCF0Hihevc3W96kQJL0Xu0+7r7HAuoWCcLYzVS8C9cKT9ePtEb0IxRhlzvPoQq4TCzSu2l9BitPW9VXZG6Zqo6lBwDzkIx62UIoa7WhzcxAe8jdRmgUmPUlmBuw3T+UnPcUvPy9Cd41LTq6MfiFNMQOjRGxEsjISMD1ygoYNgFYlp54ZwclTHXJRZgqDikSBiRXAd9dKzEgUlKWEgNupR/ZHRLG6QgV2IjQZkg4mYCYQQUcZ5qvvkOndY/f3rGuNjfOD6w7835+RGNGtNGq0i6mDJDBZ+bYA3iCGuZjgAegPI5gezJzKSxGuYDrWS5PwvlAPaGixmYGG9CeHV2JxlZQKmmTudk2EXZkkt4gP4r2WmEWHawYbfzm5Aslc46A1lDeMjiGPboAFk8PTFyIB7puqAMoTuzhfHgZZAsDYA6PxQr0BRq+W/5rP8uk4160NsehfdozCOq/qCgr9z5JnNto6WN3ZjYObD1nIht4AzhW6cyGijUMUda1EsvSrOE/D3wTUK2H+0WzwSsqjQokISBICOiA2XF9QmByLevVc3cumBct9zNeISa8ToylJDoYCqbGfESgtsqEl7lEQOZ2r9GG9leVIx5Zaf5iB2do2lm5lEvSJYM0iVQ3DKpjPIm5UST2qrYcJrQwLe4ZbhUDPTyBQOtrMbhqwLKC90rta9AhzrNkmleWBKVJ5bRZzh/RU+5RYGOzgB1E+thYgYHZs2SORBl9lgBwp5tQmlHoEX//nLIoljzgqYL6CRno0Af9HI+Zew8DDpeBjBZQ7PW2tD+lm2PpqKyc40MFOKeB7IhU1luS/sSTRupOrGF0Eqt3mxNV2xSFBJQVe5MKOJgjQ0iQlm5omKFy6AMuVFzb9a4cI3vTBpCozXeQhh1nITLWecm76kuvtAmwtV4brGVGJ/4x531T7vu2Ml9uWS+Mx6f0j0lbz6Rxyds0I3Sv2i4VccA+/wY2t8NsKNwmmXUGl/0fBkacc9B3NFgpOmoE+nApeDPmleIZHH7ylT/dwxsW16KfdqP+f0sd+UFDdRUzoNLB4Xq7mwoYSVWOcLXC86er2KtI59Sv9X+qiguzhS5BkWAfb5peF9DheE92sPKg4S6cV6/Bemqydn/kU/2K/d/j4FJ2Fnnod6ZLsA+33KvrcAZjFuDrYK3Afv8jXvMFitgQL9tgERwa6dUVakO6n6YlWHYLvaetd0f/t+L46pnfUd9C/02gWkZsT+y58CQKtinACc7L9vMvtv2yPPgwC0OYJ/ngHomi7P9GPPjm4Vfi/c5EWERJwNisqJBN6KyaUJqLRryGuu2tXZn/Du6/wBcnC6eKfizJ9gzzpI+5Cat40bR1/N7yVTpBZ926VlvyZT3FsYG+1DYVi3i4TF1VFXbBAS22H9sfVpIwjfeaRFtLDGFRw5zJZb4Rj98fbEZzHIwm68itZVdgPzWab0HW13btvOzniCtef+/bsAR/vC0IH8sUYfsIfCP8RYm5UJKaGRGcjrCBwaPo72yAj2DA80mEqZZMvOLpSunsx8kccLOp2Qm5AR72hWGOPrdT/GsDu0Qf7p2kzui4H7udkJF9pWMjBCgYxYmFrYWRu6lA32Odf+TquCv/yrxrtzjPCgovHJRUWcC7MqCBDHULTEsa1PYSUW4TYUthmVtCSqShf3Is3Bq27ZFUia9VPKvpExhqRSkTvPOGFVqiJp9uyfLhIMpg8WDxSBX9HhGQF0M0NPcluExtRX3u3NvQ9daMcXJ3c/LMdjBjO0aeXXmSOLAhwFU46cCVWdhVBM1yfLPvfTsbHdnspsDGNw+Fh2MtllE+0U2TftHzvMooaV+cakuDG++x3Ysot2iot2ikuvhtgorqRFsFf8sq482BkfvYwPOa77TJ9I7Br5obm5UJXVFFh/KeEBKLY5K7gEXkWUZhU2Z8oS/H87lvVmXQvmM8mZevxZdE5SVlmDm9TyE1+KWX1yeUMJDPFfsmQSwV+R8OzDWHZzCe+KV1Bz3jx+jP/oQGWGXTmdUxualJdOCIpoH1tU2flRk9EQVkhNfH4orjMnoB/HRsajcjqOYs6PsnlAvN48CSiqWDYcNyWwiG5E0INMyKDQDfQo1g0wFiUri1erKplsWj4ZcCLGo9ArRf7a+enj8lPdj71F0j312ipdG+qKkIPmP3/5AXJSICz2TMfGCURVZ9fRO0zgyNMkeCnT1DHIMchGlwCJ7CjMwUGAUJcQmgtgCEZcQfXHUAZt2l90f6OLjX0jJQLE3BVvlW4l/53OKXglJ8X7iZsZtLeSWLOIJfze5a3L7fuYMdlfmD8ZG5/XBfm23X9o1B5MX2MRP2Jgj+dd19sBLJfMQi1/aDirtR2ryv/Z2jKwOXmGTA92c7fxoJgbuxntMyp1tY48UbLSNZT70DK/x/oY5HO3m6+VLBek5c67BtkE3E5zpvro+B3EbSV3/1rZWLiAMhYQkjrPa7o/2s3seNLQYJ/GwN10EC01Gw5cVfARxanlpfmkKn0Fcafr45mMn/Dz26g1aeuGtj9CK7kbff25uJGlbBTeJMV0cJA+bjZy6pfh01xjjKmC/dtYiWURZWPhZWESRLKYIP759QKeKv/lmM4jogZio+igYo6qKpQuCGyKv4XJIZPV9amQFBkb2LESGQpqg489ORwUdXdb78Syhy4rju0WmL9trBsZKZ4ODQvfvy7bKdKujxXUXV0ZGAi3mii1EmlrHz/s5n68p2Lw+BEaGQ/SH5GRZX6KzUzYb9DjAVb3/jEyhoo1ucB0nvLdtvUS385hm1nOOWazJ5us3Vxo+D1KOeQS4HAtzIW3gCzhd4+9OZaRlTSKzK6ivuZ3cZy/fyMoNOThMrbLUf2Sql9JFzCbOPB4LRKI9yOZutlqty75Juf8kjcmcORFb+/mFHJEnn7/k/3C01Kz9Te6ueygFg7gP7hdv6l439d7ntXjw2wTu6qKDbiouTO34nEGgK041T/Ub4+rCL2tzq37rPPt8sz7ah36x9gtNyeXJ/EP52hz+hPIEFKfk1btl4zCPvJ48SGMT2bDacLpxk7jJOsxoPnCTv+uALkiLBH4mF9IpeItnCrJTlQtPWbINUhWxhToFWZbZFzPVC7bhLRvsilmA/XVn/3gdmSUwEU+M79JU+S4mxvnBzveRqCiIjRH5i8Pqxlhtc/B4sa1nuNryosB4vGEC60WM2+ngS1YBcmwi5F3vGB5hmbqISnZd1aroKYVOEUWSJy33Eebd27V7NSXaWoRxwWbKS2JIBO34aJmRdFPtk5L+F8J9j2W7uwdA1SJr+i6rbbCSaic44GPBg49pmqlqq/LpGB5pMT4qKtnrangDGgOnwR4FknFYi2GDW3bKamz56WlpvZUxj+IVnKvRbznCPzu3l0Tdty6eWmgcFOWyBM58TtGH3CKSRnBYTdaR1gBFkwTkxh5m3NZSbvG8iBqyQd0+Nfl9wPdf3esTPO6pZe0LPXNj3Me4/0t3yChsPV9Zxqu5iA2m3/vzcgrOzBxDR+ggpUOMh5bO4RpyqODACWLC0AmQwzAWRPb/lL0a9+dFfibMrcJKTj1v9nlmtPNZZRsd2xuWxo9JPCJM5+hz+PB2qdOhsaCj85VvtPha0bVhAUGRC7BHKeDS1Ue84uIlohI8D0CjfSmp+ZpyufikDpIVNYNGJQH3oq66FuQkN1hXx8Iy6S1BLGCfe3JcfUK0l3dYfH1SnNBDDXMzdQ0zU4K6CckHfq5AvrM+zV3zEOXAU9Fz1P1unuEnj7Wzj4Nu5OdTSZe8VFKCDBuklanqRVynkoo9DzJddZRdNEA5c2c1Vxu/oPb5jVo3pK7QgnxsacFedKtgd5ptkKcfRX5bQf6eguJDeYUdOL4v4S5RMWa7/qWW4OLq6gNdjGxsKDyWML+uSyZnUMghFMsMsiWYz4fFhLHDwqfCo9hRMaAtP0vYk23q1AXTUjMOQftOHROvusREx1y/eBnDnPn9uWT5RdcPz6AgT5eA1CAs0/QiEROjC0fCx58zn1+GuKvbeiuOq5zVJ8wnl92B+srR+XLk65YkW6HoMru0ZNWj5EJeKl3D7en+fRbgq5016GYsYar8ecAezphdjeyeadTNXX8A+3z+LGdEojWSa3MctBJ2LPgOvxaxTDBS3PfEOJPDyMxh1sqVTTO/RFJ+u1MSPEVTFGWeOTpavXJmqm3mlknmC6PMDyOTYVJl1TZlJyGj7FsZ9ciKCOBkxkztenb3GAJhjNh7exCZobNJJ119gh2i2ESpIuJTtohdiIsXBDZ9r4Pe1dnXMLd7z7ZsF7OLyu8XHrXbkG2YssDsF0P6mB90E35n9IsOq5CoFqTldUviGcSAPfZdXzMejIt+v9SyEvSb0Wy/LFb5qmlK6LGcgCzHDkq3Q9PcxOjSWu3zhKvPBXTvNoElfmcFHxcb4etbj+eJuL9yniQul5vKYsh59t51ysq9HEEXbB3SsvW/DWilh7xTRZ1Eiwyyu2AsZfXM3hJ2ceje1M3JFnYPSgR9+u2+x2zQJiyTljnL9+/eP46/fkypbcj+eTQrvM5GGR0nmeuq5VxITAzNPxePMoKXoh++fVn0wnv1entKfEYNtMxdzWm4c0359lPnlgCb84GxJ55YWFs53w3Ya9os54xqgbHSZGtqGCrOb5oBbg7doPVf9o36G7Bronjp+3Bx6hvbk7621sf9bKyCfBj2Id4+VkoEJcV1JZVNRSUtwAfsT3MwOYHEQ+aTTFendmjN763vjduA92CStzhScXeWs06+fjUtTYugIjq5jN687My7o/WjF9gXlsGwEP8Qv4V/Uv9EdeRe+r0J1Ycr/PFVz+ufC6zxVvH/6v+rWuXPRrOdpRDJMunJ9nNF3mHUg0Ul7t9Lh4on4C+ulv/QjnEC+zTfSX4k1y5SO1BM4LRMY1aWx8ljxrMxZXZRg0O1hL/CAIb9A34MHvuUuGecmnh4swg8+wUflGbMJxpN2broa4W9xGHdQ6DI9/X+/XZCH8/wEJe8MN7vPIvd2ANYDR4Y7a1hoJgYI/mER+wmuxp9ymWPTDAQxM6OsDOmyFZ+hh5QTAEYK2nGUND53d69TKcaNjo8a4lMj5pwAthCeGRumufdibRtGE4yAsMY3QPJqyL1/5hLIkgPcyxjEzbHQLHSG8bpVmeR6XEqyGDaKngYSHMrkXYw4zkdHiCynq0l0MpGutWZZHpUhhOI2g57FK+Yn/Il31CRxHiPpB+HYXKmKBHumE+yzYNlwh+0lfwjCiG1ylwhpIzbslWGlDEg4uxvwOiizR9xOfJW2bfQezW63UFmSvxlW4DlIwqFb/WEvyiCMoPJEjVVfcsETizemN6wf0VUm6awYETT3n6mCFs6LnkUrzg5XY94EYIGpfDWpwyKc5Wj0GNmNivRw2/WzIQSS78eS5TrwwEQIL6eSomyEOZh2LRA9z+uo53An5lebGNhiWAuiFjFJuyDcQyxCoHYMNtslAs8gYzw9TO8w3i/ZpzBqumabsOo+FSOKgW8Ydo0uf01He2dwkSC8Xmyd64gklSqC8AA1M0UrbgBFK04lL9kr8idCsC0CVMO56apDk6k7ctERYyeism+AlNRuihakQcta3kNQLjSPP2Zcb8lYjHJ1p3QR/tbOtt9wqEtCDeS/Qm7ErEkC/x+Ow14FOsgR4hibYHO3Iwgip/hORO/LnAtOVAUvCQSSXKQGtc9ixe/hjtMckE03eTV7V1AFHqEhKlCDxQem+Zaf01HW69gbUmz9AaJ6Yp4BkJ0MuN9pPB6NiH/nipQunCL0hGie9I1Sw3Qy4N0jXgC8OpOI1Dap0TpczFZoqWpb8k/SeUiU4KH+Xwbhl3EQWej0W1cxwxxqBOEstHYyBnvUezrTBjJ9tUVDpKEzxK1kiXjCRS9Ou/ILKTSLOVKnnRS7r5O7wy74MECbSJNtNGui2wTZnjBnBpjd5YA/8/cSt+nrs6fFeW3b9RY8KBtO7Y4avefrZ6Q3BeSW1PKuLt8SYCO4utIx8CxPzrw1jxC9k6/vfUNWwTqF6NJ7R7rKAzevX/l2B++9mzK+C//S34X/x0xqe4hRG66PlpzmJzhB9FMab/k93LfCTN2chsr7E/E+toSS44Fw79Hj7wTKNeP2nmLQy5qa3k/s3/Nbum4VpPvpKPHf/Pulu/T3pGYXOpWY4Fp37rY5twA8dC4S0V+e8rtvokTfQw1yULDqJ/tBX28v7VoOrSSvlYNjF6H88VbbdRzFpQjxksQ0ZjVjjs8oZFLM1uLfPar+QHANn8HOE/q4qMeUJjtCI0lTOiSakteP4JklbbQa5JWpi+ow7g1Scq4m1/idekOHN+NehJAyQGMi77jGPWol6utT9RnYP5XkJV5tk+i57eZybaJPogwmQttTJgMhGpbPPuNxNmau1xbbcaB1Vi4/VUd1syZPB3qO23TVQJQibibVHq6RB1F/3hANFN/tZ8pfYE1+fjdbAmkKKV7JOhuAeptB9YG/RejPnnQPuoILlC/+VD4p93maQWKnQy+etTjUD+81gFENKW9Zfqy40j+BONBIwk1v72MjgjOslUYUzAyGuP293heb2KABBXctHGY3njlsNOiCzs8f3Wgn7BGXz9fWmg6uSTp6HRmtsq5pof7fY3FzV9SiXF8L8u0yYHrtJ8YUxOtkAqo64zBT4djsatUNLlh3ew4OcDHw48AZeWFbvw/jDbnN/oHt9QcAHjrz8LqAHwdDr//o7g9x+M2RzgwJxRAgPGkiR9gzhNdwl/zO4HYnej/Qz4/axATaPvBt4MCGlFRzao5/zVoYUJas6JCUlHPUGt8bc6pYEQ8ZhONrD5f/ds8y6q+8m25vsSRF6G+x1U/Zzdchy4306xOjlYCRs3gmtE51lwO9YzYwiexINmOml4yn/z+U0INF1vPY5RH1p9ByaOXOtz1DNFtk/ywiL92DkMm9+GVa+Wa0CLk5JiZP1uG4D6MWnMw6gpGY5Et0i7UUuerH4XCIN8KXaw5kgq/vJbDvjzKhT3Lpd7EaJUS66boopztGHEdlhQNLGFDgsjCJ7W0iik29g7PxQ2yaOWENDDbEmC2DMadWW3n2UPJ9y6lcxQq6qrke76E9oN81aFay8k3D4yWSHX4yDo2WA7dLpZWJQWrqLnkr3ohZ3lFrdTlp3WEr06OAlYGs711HExU1KRDK71HdI6AlcN6bhUhD6HVRZPyTkvnLaL7qBu94+4ORaLwAeeNfkdF5ZeYHZgr5AdWDRlSveysxof9ZfK5ZcgW5MCVwbowqzIH+XAVyCFkRqNuU4Ns3jN5dIbmPi1ucI8h05C/24WQf8gqXAOQV/1agNy6agBkFrIL1CN07RpZU1bLlmsPrhM9B7rHXV/9QYzqD+XXZRkQ4P8uEGcLa+4o84ECtTYcBJhDADSkzgkcAoqMkOYhowiK8aLbXgxkLGVZJg58o0OQkwkW/nMBxS4pWKAgEeRoIdCsJDkUp4MUT/AfmuYUX+qmeQOdyHPopuGm6a+b/YWJKtf1o87BaT4FRUTk2DRbg0U62RMdKNIJ3n3IWQoTLpieGgSpd2rTZzjWuPqhw6sBoyOEItKocHSzOm+hm+nrOrU/daeFCTRPiOnboKdGNsMRzxqNBUu2HBVVG6KWAG13fhkSPwA=) - format('woff2'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, - U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -@font-face { - font-family: Roboto; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(data:font/woff2;base64,d09GMgABAAAAACtAAA4AAAAAVDQAACrqAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGmQbmh4chV4GYACDIBEMCvEg2jgLhAoAATYCJAOIEAQgBYMAByAbzUVFB3LGOAA2hoZ6FOV6NB5F6aCsCf6vE7gxBPND66LCKDAU4igzi9aJiBMRT1JycnUrasRHaHnjqSMIxc/03DZoXwLEnmJ7dL/z6jNwnI+ay8P3es//OkpuHj5Ywub0gGpWVvYP/Nx6fwUtFQZGnlIxBEeOyJyUuFE5RktLtFQ4EBSbLPMUC5BS6YGRRzqtHYFhZteKH6gCpKLEXcmUOGw6YME0ktNJl6J5wKIhqK/6/1KWjiDBnwD4h7y9bcsxsjDhALi7QAL7VpoT8D4XdZIIKXcuWw9F68sxDbi0zu52vm43+Z8U1IwC1rspzcJOAT8EShAAVzbLdPtGWycw6TnUmhVekD2FBr3LQeLUQbTbI91qdnbFD9q7J93TSk+Ch9OZtDJIDxRRZiDev3fVvfkBIwNwChTZoZ1xkDhz5jhEChIHYeLQmYk+75Ezh6ElfGQ1/I01gXIKFuwUhIqdQm0Uc1zOPj0SExGJ/M0vm2d6HRlEgqQSJEixe1wff2trjULXjJuxQk0EXrcMJ15gLi0qIdDLLy4JCicAW0JhdZIqhBYniHDhEPHiIRIlQtDQIFKlQqTLhKjXBGXAdwgECpgGzAQBEkQ4BJjihPMw629oYAGn9gsP9oNTBwV7XoZTh7uSA+AU5LADggOAC4ITH0ACMpDxaAXxTwJS+wYG2LiLGXqH3o7aXR/UB5PBZ3Dqynqn3mPw6Uk9uU/ry/pH/ewQ0C/2a0PjBDXZe+I1tEf3rkn+pH64NxkkMDf0TvYUBvsM6mhrOKHVZ0DA0IhWKuBeS++7gxoWhwHDw1O2HSRk45vF/vGxJYd0Zv3ji6nR0gth4Oc+RWmvOH1Zs+3FPoKn2yolkjHtylIyvF78rVHxHcHYRqxx/NKrVhV0Wd9g6bb4hbUCzGa66J3Gkm/1Ne8bII7sx3YWzSiL3VWGreob8hl3YGuLpf88ac+VFkAs94nIq/rwhYP1uI+9Krv6OlJ9rVeFG08Mt9g2DkB8wh3CE/PZWBANLWUmeSykZFP7m9Hiiq4G3wR6v+XAOOIatzsDmhF26MDU8RWYGzjmOalz89U+/gUjt7CuGcKjSZ/sIQVLtR5n/Zzyt7u1L+LZwUxrE+a5YAyOatS+A/qUncR42TN0Tnpy1YvRm0eB92oiqbVkxk9Iji9CjS+kTTE0u6e6QSlN7xm1oeJNJHhkFW30og+B2xe/uEIG62jWtdxY01jj/HlE1tOW6i5Lsm91hZ4F4a4aZfx8cyc6MHDYsON10mlnnHWOBEkyZMmRpwhPmQpVl+jSY8CYKTPmrNiwY8+Rs0JFSpQaMGjIsBGjxoybMGnKtOdeeOl/r7yzbMWqNRs2bdm2Y9c33/3w0y8IxRiEgcdH2SkqBLwjAMEbzCRxjZt48qadDALxkKSIj1a8R4wvdAx0QR/MwdLZKlbYxmd2scbRWObEigVlrMKlwQiGYBhGYBTGpPe99wHmYQEW4aO01BfLsAKrsAabsAXbsAO7EqPP9mAfvkrfWvO9gLCPPrark1BscIof/4elGB/gY4lyrFOJd97BMCNMs40BZu/dWcwwMcgqHrOPJ/zDT1QEiA8NtGiVGtUwOPBRw70uLHLFCzgA7PCFc7rovgxHPDYpZXgNc/AG3gYLwuHCFrYs5kGMNTqALuiDJY5gmZUV7lmRoARK2RKwDCuwytaQfuDyE345I4qiCBtirNMx0AV9sIRMWIJlWIFVWOsdQw8fG9LscQ+1mJjHYpMVshlsS7ANO7AbjMUVVDxQDGVQgZPDOqzDOqzDukwwL2IU0QFd0LfMI4iluluHEHtsMju25LAMK7AKa9JmQbZgG3Zgd9PRjsdNNrHFPj5A44gVarHHdbBQ9GJztj5DxK8KnFhjMe4OzpiJnOltLKt4xaZi1MX+0S4qpk69V6FFn9ToVR7P4uS9jKRAdkAPx/B9UPjgEjAVggsKz3e0k87COE8WC0Wq07sWImG6OMigHmLKwmFWjrGrxzlwckJaPa1QmTMq/hU3YI2EDbssffOLPRR5DxGMYESb6AWUU4Sdxu0MxFlY4lhJYCNJgAyELD6KOChhhSdCmZCLuKhgp+oALTjamBAn/4wdc8McMxjmQLPAxAovOywc8HDEwgmntMX0UbcFFTNFP/LunTJlI4wmeqkiBo1BGf+N24RpWM+9gnjtLVbvrLJ77yOcpcpv2RpmG58Ym3ahPxCx+PEUjDPc4X7w1Rc3gVA7voWjjfJfgiJOkAwUOSgKkzPCjjUs4Q9vDoQtXCO8owuh7wuJLehgNpolENbY2U5shDeYhXlzSARKBpRMGyxHFLhOIFTCTfgIN+HL8umHC4DgOCpOgiIshA2YOtYgQRK0zH4MX2EJc5z7T5LoRgJIAAm4+mCs+x8Z6A+0f7zTAzIOn3m7wnVGypwbDz9G8Qf64cfd/eD2t1wwPDi6keq/aeOjWGUrUqURXY9eime9Mg5wYFpnVy0xRGA9MwtbeEMzNTFYPzdgMmrLdazwb7uV4T7bb6sfLAAkzOUFDhOWC6B45VRSIQfBEiAsBI1dAFIXDIh30rCIOCq+778EZyzKxjpm/QXxT1OOxYQZS4P0zZg9mQC6Ebdv7W3RiqpGtEIgaXFBCZj/8WmG0og9Fb1+++Ovfwh4PiEpE3EQSgl2Dz0iip8AQUKEFdWH8EEpgnk0bZQjrrsGXWT89eD5CCZQ8rFq16bVTXQdOt3SpRtKBFa3RbiK7I4ed91z3wMIRC4UD35Q/JChoPA5BFwVWCHYhzc9ngB3WnLCMRokNOS8Jv5q1Z2P637mEVOnh6HpMVQPVXiT6DfRIJlAILePrjenPVjQbm0yIM3Fq8qHvDKANRE4GywENoO5HywbbWVMBAKIPx38BQf2JRnEIHcB6qqNTowY9KOQ+GwhIvyYdPlXq40RYDED08Wo0qrNY8NmrNjyD1kmmecHeTjP5bdzo8QGsalis4mJiB0WOyZ2SkxGDC+mKUYWaz366DGev//+/R//wHRiqlRr067XiFmrtodUMjPcb1YxIbGDRywtpnRvpfgaS45GP/7oAwqIPyDswo+X/h/9v/v/rs+z5lPTRyRhPlaMSGFG5r04Ev/w7cO57/OQFu0QG/eq3Os7LI9U++P47PEGPPth/OEnSPTanDfeeocqyXsfzFuw6COa5B/ML4kUqRj27PvqmzTfIVCYoeKfGQGpAvIE+AtMfwPMvjpAXRzkrwGawvP26COw0JBGFAcUQ/9LkdrAlYEW60BEjSwCKJWpAqWTZkI1tY40lMc9Yez7jKgoAGlnBN2ITBUpEGFE+uOIrIahduptmF1s9hW1YLKQv8bkqeUVYwO0aRZ4RkqBpXhT+9kVhgia3QyrodFEdeQE0NR+nX8yy8rVde0oqZu1hskosly4UnJRBhOwtuLLbCMezqxC0xPAqhaTJzPOw44ZRSeYfn5L+XazSGPgEyLziLl2I0YCVcfkiL5ZphQzLT8+EUn8vBmvAuoj5mKY+NpZ1EYiohJEOCTGBOMrLpgCmFDo0TAfGA2EB04lavx7Ef99eTHKc4yARWeCiYoyLViklAv30KWtfeI0Pl1DBLXrRz3yCdxF3KAhciaVX9lMAyCxYoGZYE4i5Q+07FMLhEqAUqZCOVMlWfy5LmAuYDYJgKCCePxJ03mCPHvb9NkMMw0qgY+R+2bovdrSEoz0y7vlVpH2n5ZdkaQYPPc/nZryHBhn7UpgytzTy2J0VS+Hab6o/brZcFD9Z9OqXDK8HWwNqLdjNvt60PNZCWmhLUHZ1Pdr+6p0SWEHvB0V0II+MzXIxMuMeR3AQUO0BKjwtLZ+30HgYXsTjtPda7Co1ZwoPu30NHc9pvfouehcM5Yn/HATkUmghXbHZ4qU+/R43DWd3j25iDR7/D6tIjwrP2GBJemvhPUHt7XhYKdGOWmRcqEHwhFyB7os84Qe5lFIcEp840mCy22oiu1mN5ZYrjcRqNYBjw6AOi6OigRY8JrtOrJbeAxiEcHEO+all22NkAToavSCiek2qcyY3+hbM6jba9OMSj86XNnKfH5Rl+XWZ+5j8z9ZPKMaXWl3am5xKSpN9wfDf98Rd3qSKZbn1AaxKhbuNOeW8s/YuH2uLteYLy/7kLHr2hisQucSlEv1JSHSfBOT1huc3J07lifWuGvGqdxxcJ0p5xyTB7vcZfBy9yCUqmRL8BjdKUXkeC6p0WRquDwm4fWH2qpygok6E8sdOc7EMasY7XGEyfrWZMaktTs5bhP/l6r9wQ8Xl4zOKmQoSVg8Ua+h3XybZMWX3rNro7cvHOj8oWVMKOkCpGdCntuamdwuayVac4jdyhr11FO2sC3hbm7k22RoUkN3PvTN06wiTBQz9Qq7Kb55XqjpTM6ncjFXYX2MIgfdRO10zV3AHbhbMMYkJCumGFnFEoiRe7igGcZrtsu4r7pf+MmC+i2CymcuY6UojqXMa0njFKepxXTWnHLgVn3KoEQ7Hm6tTDtpa0O2O2EujBtnjfPoUowiEzVQMKr4K3rUJwBXtqborN5PNiUl/p4KKqEmApXRhlD/EXIjSGCDaUdArfin/YAsCvhHOVo4HDjoanp1DWRS2Kb9Vqy1QCd7AL/HxrYHr/kkiaDRsTuTWaYZHahPkCm1q3MdXeasbaqVlmmPS7rDPHLjEGy57TAS9iE4wzXthq01Rtsa9odVJt6eO2bvOFyQyTaNBAIhq82zSKCT/lKxrwznvYtANn8ZAJectCw1qYWTZJITG/fJjREL66lwmFPeQc89GWsXXVX6RlEHQaJKqm8IO9AVJ28PIQtQWKgNmolzKayMWOGejVjhuVRZiA92nlxH5KYedFY1kmVIwhDbNaZYfhOxL5JOtMMlKjS9YWD4nOhr2qGFScHTd1n6U8FHID/TQ6+YRgmDZ0TtB1WKpoGGUSZNw6RMcycprwqtI0KllQU0nYQU2HTnIIHmqt+kRhNd4hTAPBYgh+lXwl6varl5QcxjVXxiGvPGDI1TC0ls5wFnFLYJoi4EyNYN19uYzy8uy63D1ZWkJelLiDLCGm1RJLrPSflFtyE8B+Uln6Pdge6YQTMzLxyzsKnQomrFKT8Iv8lOwzcP+9dUjwtGYtZXEYdk1PRtLf6V7cDEEv+LJsWfcVrxafsWk1OF50n/kEXMq3aRnRUnIhpYFi1kz0XMwIpUPDaK+emdhx/ovqLVQYiuhh3ioNuMOkYAXfOEJWldejZDpfdKUlCnx0Zh0EBECa8NZU/iTarvXd9aojaGk/1gb2J29/T+Li5gEgmo+TMeBCoMohS5zXcdzWIkp5Mt6g8WWsj9KdM8QWG7C2NwYlyfne/u9Hce0VUYFtIQY7Qa4bjQebDGoghI1D6mhUI/SshZY3jELMtfciLNbJDiZF6lvnyx1WWOHrpnG3EJLiDi+yE2Ik3xKYJWxFTuztQD1ijFxT+UP5rF6d9NRW1fw3UQWjt4jTCR2Bw7OV5Pi4rUHt7Mcbaz74QU2wcKRrAEO0ZUtfRqBPoaYULZGdOfK8BXFW/VHyH/cR5NtTQb+MjXyn5N5G29/6C1nAAlflM7Nuf9RR/3pd7intjF4SDw2bBEpVw4vx10IxzRtN2ZmrcbSkihuIcDC13qD8nBfbTQRlCOD/cvvUZTOjGMYZrnOWUeJhy/RrL2oxgxb3GKz3XGpmzcjW2aRNlRKeqc43AcJXH2stqyeJKmH/8h/HaHkoRBQaMAS+SSeAWue/Wnn648Hb5I+FlOgUCUpZ7U/w6eJoECQfoT2iV4YDhUQur/0jHpk4OqWXHIIifNT5Vb1svpAWkGXM3xFBcSvFAYYg5V4H2YFv+Z5B/p7zC7lX4W3xNs0UwfOg5CoX7Rg8YdGdo1QskGd0jNjtEqLaB83P2nL7g/vdp7I+E2u0uq0wrZYgv9WI1GHFPefaIhuvUJQkYDF0VFSVcv7ggoKRB1qb0Bt1zosYR09vbzKae5Ybp4Xr+4kW5utQKrpMio5DasbDj4wt242crN1bh3Fb+2JjVQFObLPz7nQUYqyvJywC8brZNrUfv1Yy9aeeeq3rYJPdwb3I0JynZ1ueztak3y+beeY+zuJZdk1zT9pIdnoLJ/iP/51jAjJiaVHBziDzjZImpTY1pGY2OqTmJjQ1pye21GE1bLwOKSqr6Frq6WgWWMnhXx6HFJWltdckprXSYxob5RqLk+tQmjaWSlStAx09fXNjRXUTUw1/vDiCKeJwdHEcEyxdO/sfqqBUm9QLtlZpheOX4vzd6+yEffjSikfzE07xlHdMuL3yKmLqVkOmpp4VgkyVQlZDnUjuIZH43kNVt4xQTor720UrI0USeaOwNXd6IwrRJzF2KNVyMrtrST1CQyM0jtt5lEwFKiea44UoKWpLatE1EGJpfeh5d9M6MRJGgFV9vfSgsKFI5mpn6RSI5V2VKOpTHNAN/ApKS1fOMFMqf1LU7HM8FyLXLWIyzZvreOdAjkeMK5j0ej3kd1rHfEvI8pWIcKYoKhkt05Gmg9fAPt4OvzHMyZOQY5gPefpq4BXklXT1NNX5esawC9UY+Pv7zwGNSPeeI/q26vb8qjJH/jPyvtbH2WQknu8k4FPooIDexCPdabvDISQQnsQQ3Cv91rPMKnFGaPAOFZwxKXD9mmzNiHHOseEp8VzUgKez5PyXu+9/yBf8RmeqF7VC0IuRPzAyHhip+PX3CQW3SQPSMo5M5zL+rc97kBt6hWt/9Cz0TdjBhkX33zlO3DPYZLXKj/lfjQ4KvJkbQswEszdQ90azI0Kbi80xqvfp1GN0W7HIG2J0bvOJ9qnrb3UIqdXWFZeP+v+zCKW2S9+4XDNzLIIyiqMi0ptSRc3f6YGcjz3xk7PIFivBYYIUfc7nt/4P/3GJ7nc5xqWPNYcofTl9smVNvDeno3kh+9iq5mjq0DDc+zJzzP/juhN3YGdoBwQvKyf72TxBXZiDvkXvT8q9eYhceUyLuBUo4SfvWX7229npzaes0hY+oXR30ek+h/OSr2bUTk4d/O/hH3LpM9Pfwo9/woILXoGh5X0/uR/U321U8v4jPfIkRezTT3chfUobHjL1HLo284dWPNj+k6VycOPI1qpaZGN4BciOEHhqwppU/WlMwAVQa707hTsNOYE3yK9F3ckkfIffIIeQscW5LUyvsfFEYRnRzc7Kx8XMwZCH19amBsfuJOTWF5RJiaHpLFkFfW1blEKGZB+zeS31Mc2493Yo+6LxZL69P09XKvb3GPHrgRg+2/FmARd9ZKTUaaZyjJK2EO28YVpJpMGBQf6AhmXmfbTnM43D1jcfv0zsmUkWlJ37+XX9pNOD5lPcnG/a4rbufrD6+5jpJLT8jsyboZpvLOTofMzq/zSASmz8JFKXNZihnTMU/6x2MUOrP74fqn9pAPWDrjGzI06HG50vs/ypE4etQU7s0+f/aIcGgSxffjKubC3e8hVJKbX4Rzwlcw6pjjX/sP86OduTZLAjWaMp2jxNV0a+ckVnDzN3dZbtq1Ovo2sha/3vitpqAgibdUzmuyve9cS43ypO5MrZJk0xCrx5JI3cjz78ia6cbUj0FQDU6z6r0/3gNYesdkV64VqHT66vn+ASy9fLKqQw+M4aGRl6Bv5x3huiJZ1FSwnnKwKOPQ1sGF72dxTM30PdR60PowpqPf1PrQ+d4zYBoHv5PTk/l0++OU7vQbKn/PZJkQTypb/OcJZv/l0rflqd/kYLK/VxgtFOTIte3DkzajJb216Y/0Qerxgf/OQ/ZYwXju2/XBoSG6iKaDiKwDkd3654XiRZbcukWeuwrFzQvoCaZB8OdMPgvLaSfOdHFw/ALTxc6Xeeo8rbc6+FqvX4JZsxfXtT5314OnuYAAz39jdm8jjbU9gHy22L6HrW/s+vdV9sFDfD42F/YO/3nyUmjjz/lxyeTMmLCQrIxoRAFMcztnEsQpNj/6a/Lk9ia16ewzHV00+A/m650/jTXBnyzXe1gamvKaJUWk6Dca/OZeeJmbMRgtq+3EcUDlFyYuKy6IQo1NRNhA8UmoC83b2debMBw1Rj/8cbloIzB5OuZ38LW4pKgUX2eTPJK5x1Scc33QbYGXWxXM5Nyp1D9RNcnFVCoJ9DFLw0u/lvonE0H/BX1q7Qznt58nWTcmf0/n5hVnn5AdhvyLgieuCogN0ffF6uj8YFLtw4nR+cWPpe9yW5zm7jrNmP2X2y/OE9rcHtrP4UzeDSmOE3ee9L07rcivxH+q/13PkxMQ8MeoQ+hwYpHQX6HDeUXCED/GOn6xVoKPsD55pGopOPrqbB3gdnrgYREwfXQzIBs8vX2qu/ATwGtPCTB9dOvDBsDt9BCIbl/fMTl97mXL2WoKlM5+XPC4AMSufzLOIT47oMepWseFNdZM3U1tg54fC4i6X8zRw8Xc14zAsKWUjFtHP1p4hGpdyz1jxY1q14nR+jmZmJzsaKXtYAYax3h+z58deuSbwkZ+CzhgiPtEdg4vnGTexdEjb4ZUXEp9RMioDI5sQlpAsc0+1BdtuIz2oLSPeVI+spxEC39jOrPUtzuPvb2MdggJdQiJbYa20/SYVjA68XNVfKDVN/QcA3Dwli3QL/H2o89Suzt1MT2UAk3qtHp8QUjsPbDhXT18bPfwjai/C5np77aFUW4DrEllpaENPrSEKILLKxKrRqVHRDpX1AwPU/iVKHhKq+uqc+8aGegiELmxD0Pl2m+5vO16SwPTE7/Xzw/e9Y1j9Xsj/IJ5fyF00Q1vHJwTSK0NT0+I1fUh33y0fWFnv4Z6LyRPO/qtZkReGPUhCAwMhqTetsOkDTDuBbk4OOUS47EMwAEDYhl4BiKkqK1LJeoqKhB1qNo6IFiLL6mvba/UmO21kQxHJdbwfVh4M3M5wJVP7yH6TudMTuT0PwgRhtg3/+sEAnx4XNAV6vBr4zpK3ctb7UNI7wij19vW2cfcx4aPCMuMUcyjR7kXQ7gYeOBfwuOiQrMHzLAJE4yH3jZunnlEKoqBB6NTldF/P6bkv+ESZl1jror4tZR6fZlH8u8uc0Pqg68pj+/WZjwOD01/ABoonl8fz/V2ksgIA7Bz8yz+pPie4flTuB3sjbiHYQWEiHm16OvkhHtgdPLv6tnhbt8YDtIrwM4xfvsGNvd/Et/dr094QM7WiljXolwjU+/CfzIO32QalGKXGPg1bJh1RpnsIZg7qUbS+CZjdrrbuiHjy/3b/ZuPixna3g5WJh66qoqOKodUb1gZhVvn7nQNJs04X21wXcdYhjq4u7jrgMgLNabHXY8dVHGXzjU9MBMwFJLz7OzqZALJXhIpeojeNTXwkHFvuqVDJYaFgV+GHzKc5rhfgmT8M8Fa/G/QkDJu+bzBQ8aPrq58XBnloeI32hffLd4BeDHlzqnHZ3mC/f8rL69wWp7Q5WOHr/Zv3qFFlt67cW3I7Tx46uCgLmJ0zEFwUA4HsX2E/oDKEy9FB41LwMXbxQ3n/GKhr7Nv8TnqVte7m1IS6a0K2B+vFlrtWu0/vsD+aFUAC44GwD1qAJG5m4rov7Or3Zbdlp9n0H9vKkqkd0t3LN0dXejv7F8Yut+51CUNhgM89Ifvr+lFKRSnqIud0jDwtuhr6Z7L16PisxPVj57WMA+0gKaCJwgVhXBRFBSJemrqRD1FBaKeuhpRD4zabEO9scZL6OTByRzRz6Ofbx+dOPz24IuJI7ePLozOl4v2/I8uXcI5U8j2KwcUgEiPaYXflribyZcsemBMeNzM51yAPa6neqSUaWf8x6frq6979p19fJxsveJ9mHcURkBj9nJFzMR4eXRcYkYWLcW9dGjUrzYrNyMrM7skuLe/hJydl5mdd51UMd7nWpqWkZmtmBAZ5j/1kPz2IcVvatNv4gH5/UOy3wQc4zXGunBYjH0ukkiTKJS48PuCbKFsmmzRd6sxbkjmEF0WHV3+ugw6fSM9zTY097ttHEOfvx55NbMDAaWhKeEZTsaGSXb35O9LP/R3KPbvabQlSGkkezTzTKxss81PMkjZsWGRaU5mFqFWCd59QbZF0v4mfPqil09HmbpZ5ot3yn4IFqeYJrsA9oWVtLpGiIaGh4ZGiLrGqOTTZwxoLVoUtVcTHjzvutL+6HlFTWttQZmLvZmNg1dyCCXEO8ne1tbErY5aX3CQu7mmkqum9IhFyRGuegJPU+ERU66G8Xu2esNxusN9NJ+/NBNH+/t0Ru7bgnMvl4aBaVRIQoRvQENYm5dMLFlNR1qylcOnPS4ltTibetFV2MQ5/oz58cZUkj5YKkvZwMWjIaOYyBYNsHrFfN2mXBPK/C0wZ2daaCZc3EKLpoSqEg7KBNTgNK5zlfZVGaipG5YnZWk5qMhra+MdIBNk69hvVtwEIcogqbj8bWGJn39JyduyclKynKa2nKymPomo76NDhLMDidYj1tRXVM8Rz/BXvCd+mQ6aQkeJR/RBTJCXxjkLWbyamvw9cmNRclZp7NXLvp6uVulBV4Fr0N+U6nrcQlWScOr4PffayISsG2G+oTTp/DPXSPTorOTmmCv3TmnKXrw0fM4zCRyAVx74+cQHQEgTH4Vk2MSTGvFhPAz8B5ylPSkv3EC+fxewc0BlNllh/vPyBcvflaOApUPmGF7XkKZniFc21CWo6euCCqquQCTXt4VSiktR1xY/d0H7mDHmSBogJXfxoxK5ASG8wER2rXrUL/+4r16n8n5/ecXDgZp2jJuDv4mR3WVwMXFNu2Fs5ODnBZR8JFI2W8fIy9fWheTk6mBr4+s+CG/t5kz/9MJoT13JDXsHQyJLMN9XeUVtPWp5ynQ/6gElCBI4zb/eMT8mK0efH6JxFZ4YOsg7Vmgq5R0ukgwGl5XVlNXyCvB3LuUKAp4AZscWWfdnV22inl1BU/ZGf7+3xosCDd72zqFrHlbXGnJ3y3rhonKv/ox27BF3vJVF8qKrt0dM9f9dOZx3wlDOd4n0c1WIQhfa2ePeGB3h3mTsnmcAlr47t/I1Ojv+fXpiOAIRu6Yvlzam77+816Qq4qoZxE84fZ5g3pFnkqLf8qpn2KT5lI1k/0TMCXlXW0sNKS27tmSTZBOb6FFDU3sXkx70VzBy4fuTXkUweGFOo4/cLKvYaPn0mGjv5GVjH2yjvsOT+7tn6EMANYE2gjzfQH1JvcOcVlhOSyUp9enUaSnMXpKP68En48efDHojoU7aag5G0p2r7jGpB2IGD1/xCwfZk4J/mHPM6qNxSzkZaQvR0QspBUErU1HU3CA7ycbo8AmaoV/LlWjT6rN6/RtSdNqtUEO/ayvIv0TBKCatoSAmoyEgMGWkDTSCtfee733t0NTVD9bV09SQMs/Qx9TcxoNpaJPxSrq6Ja6LnxsiWR/VvpbjOTNQROihMxxtDxFzF47TUwW7cmWXXM+5LCu1rWKuz1dyOG1TJROZ8hg0gnm+LYr3d9R3zlTFOOsbQh9aPInbxdQn3A0hO5PAwDMgeBbc63nDG5hz89iRJnxrNjdrQWOkojn8lfDKH7Xqva8jedDdm13xCod9dfs03Jfv65gFu1PfOcXnfyTRCea3Hf3g5QZqPaWZNS27nGJ77ay2lFG5tuokIexbeltS29ePHOdRO8zNSXfDQ5N6eutpD8MoyXdVue5ZhqbwhnULBwaFg6zsF7aBgtL80j4OTt4s4Pc65xgb0RwV6uIq+26OieCakVAjiEsQLkmKq6q74e6AHOVTQEyOy+k4H+UWkVM64vlM850scFaqspU9ZSMB3PUikQZ2VFRW0Ys0cPaaBdY9qAHbBFROxd319pmF1rMRhhYxqLy8uSRw8JwBukoM+khBlY3N3YPL8lck3b8R6J6zzkQXTMzddvd8C8yJaOewMA/v0DC3k04hId7uYcGIAygLfb3WcCSJ9z2zAQ7canoir2Z/zYImv/+17IT8jQMe2LYbLUUBTmKiE6EH4+DkESakNbM1Tj52bex//xP5Q6IeFp30POpZWN3CXOOe6RHnAapJLJFk1cir5MCDqXFR1Kikg4GbD9LuU+5nOmeA6q4/6GkPB8zd0oMY3+4++xST3KNGwidGUyWCA91dXDVfdL2geYe4WqbgkieH3mCP/eipMWa+/q5w+2X/YISGBGCXGYvUZjLzg06OJktczTNoZNq0gPoMbM6NWBVwfimo0cyUGTOX9+zADGF7B/9aQfeUPU0vrv56QXZlGhIzwZP3n1KsrLODsh1B3N5gzG68eVzvFuY04VzF3VJ1Nvk4ClS/CGxSqSxvys6taKooKi9vy8mubK24x9ZECUZV9DSFBqKLge1JP/hXhJOSc6Fzzf0aL+Ywv+8PyXP3dl+Aa4xMwfp1C968OWJielJE2I2ijPjWRMTtLsY0mBKtqK6hrkGE48ePFeekOLG7amteptAyI0Ibimh5zfWlUk+3Vt8XNF5QO75yIidWTkNLngxtLWYtg2YxXdfD4DqBHCSfeDGOVBV+LaMm7HJc4sUgebJvCSU+oYQiekRu144gQfo32L3ebDVodVrC5QCsyKkp2sXQUqPDmmqo6dV1yHXl/9+8+gC8eVlhpm4tRse1dNQIsjIEQyUFZQ1QrTt7bOjs3rHBjQcDdOjMuN98P+LfB+tRTV/ur5l4/ntbm2xSR/sywCng+QXABDz/fhVTOM2psJLDARePxlv5JVeJmIHorWLxVyExxafjhbZ4PYvcqk6imGc/PQ8pvds21WVnZ6kPaC0ivtQo0YsqyN4kSbW2us/B4F1CQv4C8DqQMJAU5gqTLdFbNL1/UbI3eQr4TaYpoJ9EA7lKdJBvg3a4WaSLHWKneEvsIt0Wjsg/EEMOAin+56RybpAXdHLYHM10PMlfQympP/SagYOyDQ2F1Uk2NVJWskkkcloKT2Pxi5ydo2ltqCCUkpJDr0npT3KLXAjVjMJQCrnQa6HQnxRuhrRfsmnIzEnwogx5LcqQOVGGvHXJ+BLWUDIj3KISoYtKjR2FkUDEVaZGEK0DNLUBLHEDRDsatrgMzt4KViCd3CllWSRrEMMmKqKuvxqIugZBpCMa1rl4SYeT9MGa5/3wUeaJhDzmeBQEN4Ju5rFlB8N8NLktmhNLl7mxo4S9Q+3cnyTesDUiN0VbYuSybdiKvKRTDUc1ESCObtK6cvGyIThSRASIIBEShAVekdnIQe8hjM+nUVQbrg6Abtm5AT0+FYvnJ87nxn4qr6bEx56UUttaSytJpYkjFLe1Be281sJEeqe18775/9p9Fdm/FhUpCeZps/eWXxXLW50IQgXUCx3ApbHfziSAFXJpftTo9HNmbm49PRT52xizdsDQutvukZ8VV/WWds7KNWobGOtbqt3h81E61gbZg/xs60bMLHn7PIUHtHV7+UVUEM+LqPcun9d4sX5pg/JB3bxXWUTVYpYYBeluzagB+Qw8MRE9deeOx+58wXsmH7Q5+/O8Yv043MvDpaBiH5Ro935oB1FBRmIC9TPB7tTWrw7gQvZsX41J3JwT4/Fi2a9GzO3UNlsHriTf+ogukC5vP2SBfAieuCMd2H5Gi/MxbUg4KH+1r4xZm0oHcCHtuiFtUqh7fbODC1GQ2MfNyksKpZfMyu/EZh1Q9jIBabkKyAHl24C6dhu0Z/wwWUk7N7p4hgdSJf12RxST31mO8bPyYESXRx4B8nyz4N8eNnI+cPF3ZuEJAF75uZcE4NNh9t3PE/+/GBwmV4EBCiCB/vCRHWA4bOUe1fBaUy2Qarmch6iPa+e8gKxcxLMucqm7e7XNc2+HWCU7ZnlcXH7qTEklWik0U7+DuQoxX5RczkHdmK9DI5iCMchCPFBAC3zubcd8REJaJV65XaoRcuo5cWXJxf4M+2aOp7HLb0q8Gl5+pRnz7APBSO2mQ1ZXU6+40NhmwSLZIxvWLka78UM861L/ynpOr77Z76qC6HYBT89KsnE5W+cx1Q+ZZCnUYoPPd4W9HEaulEHn60lVC3Y1XlSVZFypedP1meeXLtRUZvWK8MwmOiPRvS9gscnovl6kq8LrNewX0pN51nflKP3chLkeK7TsE2i7jlacI2UZu7U1yzcpZpT2x0e0maLkw2g1mkft5tTKOVYCtvSflPqdXUni2GmyLjkyyyLr6i9W3tgbpYVVbNXjnL+6mDdNIZcKqvfllg1aWd21zMV/tuJKg9BffN86tlm23X9MOmveZYl6nxRfqybDRuVbx+XXVSldH53awLvm0KgpjGuhhCwiq+/i0ePZlxX5uVNYeSWi8oF0L0gAtEWUd5LiUy/39IBMmiZd+PgVUYTCTDpPSGn10nIwv+zLopS5kL+SqxmcGgv/mqiiNhKqD1zoj9OxAJMVOMzK4gB9UAA5MAZDQ75taPP6mq6aITCPpTLwpZZ99jHLuWYT3zJYd42ZpHlUCZGK0aJUNqH44yzaYhQF0TSH696eHXTJ3NVgSBaJLrcsT9yJt2TOFqMEC8W8IfDti29rfCb2b8/iKqm1S1QFxycjGgJSlUWAESwEYAaQoZaGgwATXtCQOgB7AukAhAinA1A4hTWi240YHIB1Co3hEFt3lZOFYS/sBQaFB/t6+5DFpCWlUkCMGKjg9/MM1g1wF2dqA/jFzbr5VZF5VsszOCSYx8EyC3TLQO4QM2wWfCn+Pcy7yfq53sBKCr7qywOcgPgcGQVlX80KpsNeQComB+ElEgm1xF2DMnNftfUUDwz2Zn5i7gMP8Myu4mSgq6FlZF74BRcxyZ8859XXowI=) - format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, - U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, - U+FEFF, U+FFFD; -} - -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAADhUAA8AAAAAVfwAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAAHIAAACmCwIKakdQT1MAAAHMAAAAIAAAACBEdkx1R1NVQgAAAewAAABAAAAAQodMa01PUy8yAAACLAAAAFQAAABgc+SqD1NUQVQAAAKAAAAAKgAAAC55kWzdY21hcAAAAqwAAAFAAAABxDJPUwdnYXNwAAAD7AAAAAgAAAAIAAAAEGdseWYAAAP0AAAvawAASRaIk5X9aGVhZAAAM2AAAAA2AAAANhL1JvtoaGVhAAAzmAAAAB8AAAAkAzn+dWhtdHgAADO4AAABdwAAA7RA9GIebG9jYQAANTAAAAHhAAAB5vJU4EVtYXhwAAA3FAAAABwAAAAgAWACg25hbWUAADcwAAABCwAAAkgzWFNlcG9zdAAAODwAAAAWAAAAIP+fADN42h3DsTFFUQAFwD0vhQwyKQCQAgARNAENKEAMAHQAEEEPQANK+Xf+7KyoNAPOVFq1F9GhS/QYFCNFjJkQU+bEQhFLRaxYExu2xI5dsedAHDkWp87FVRE37sRDEU9FvHgTH77ETxF//qWo0FgfaprNFW0AAAABAAAACgAcAB4AAURGTFQACAAEAAAAAP//AAAAAAAAeNpjYGRgYOBisGNwYGBzcfMJYVBLrizKYTBIL0rNZjDISSzJYzCoyszLAJKVlZUMBgwsDEDw/z8DHAAAwqUNgnjaY2Bh2ck4gYGVgYHlC8skBgaGSRCaaTWDEVMFkObm4GQFUgwsIAIZOIe4ODEcYElg1Wff87eGgYGjhPlFAgPD/PvXgWbJsiYClSgwsAIA3zcQA3jaY2AEQg4gZmAQAZMyDEzl6RklICYDEwMziGRkYpwApPYwMAAAOVADUwAAeNpiYGBgAmJmIBYBkoxgmoVxA5DmYuAAyjGxVLL0s6xn1f//n4GBJYGli2USyyYgGwYYgeoABcEDchgAAACwPGOn2TY7b51t27Zt2zZq27btnzQJEOgqurqlm9u6u6OHu3q6p5f7enugj4f6eqSfx/p7YoCnBnqmiytOaXZai0GeG+yFIV4a6pVhXhvujRHeGumdUd4b7YMxPhnns/G+mOCrib6Z5LsAP0z20xS/TPXbdH/N8M9MswSZLVigEHOEmivMPOHmi/DfApEWirJItMViLBFrqTjLxFsuwQqJVkqySrLVUqyRaq0066RbL8MGmTbKskm2zXJskWurPNvk267ADoV2KrJLsd1K7FFqrzL7lNuvwgGVDqpySLXDahxR66g6x9Q7rsEJjU5qMtZH0/xxRquz2pzT7ryOTicvZ3UAAQAB//8AD3jahVsHXBPJ98/MbhKxoAECCoLGCIgNJYRYAOkg0pEmioIgiiBNxa5I71KsKBZaQEDOw16venrdcnpe88rPcr3rCRn+bydF4PB/HwkmQ/a977x5/e3yWF5Q7z52Gf9tHsMT8ibx7Hm8UIlIYimSiJCRQDrBSi53cJDbW0knCIT0o72Dg8zO2FhsJBAy9txbMf1aEDuq+1emoecGUo43MByX7Gu7YJyt6chhxqZO4dbhsdZRCRsmWVhM4l78t/+5uZIf8/wYZo1NTY2VAs/AuYHDhgnMDM2ko1xXOa5aO5L8zX113JQpPMyz4fHYAn4soBvK47lKGCmSISmSMMxy1VdrjqOrX6Krp1V16No3aCk5yo99fhj9gh/wcO9juO4KXDeSZ6C5TiKUGErE9AXX42qyavkrqAb/KiY2K9Ba0pyIIog58UcLqtWkysi0MjKmDP2GH/EQrxvomQG9YUBNBCTULyFqQYRgnNHzgNE3Ym+RGRXEpIQfWw5XRPc+YeX8LJ6Ux/OcYIXl9gZUdiZCKxCnPhYbGRvL7BwUIom1RCQQ4Mz633KX1n+YWnAyeNW8kvAFpamuofUbfLKdyG9i9NGSmyZ1yPHnk2joyUh/35S5s+bk3Dty7fm6CeNRwy5Vmp0XDzh+wOMx32gwqhHK4bec+YZ8gOx6fkR25AN+bEn3qZISdkEJyHYJIAwFhCN5ZnCFERZINTgBpoFwFJZOwKJRBjI7AzY0/Rtl87fp6d82K79JP723o2PvwZaOvfjER+TKqVeQ852PkduZk+TqJ8gQTST3yU/w72sk4QGPaNLEHgUeo3kTOR4CgdACmwin45ezctiaFFu0dMIZm1WHsuo+S8v8BnhmdO0/0XHgcEvHAXyi6s/zcwz9chJ8kqoWnECOL3gbISn5jPyo5Y14enBmzSCP4cCZkTLwIzM0hB+2+eZ3dYefvN5R3XjnUCOnNOzI7t/4sd0xLO4m7DHuWme4NkMty1AZQvAj5X6WX0PTke1FshGdvkZaSOMF1MmPVf2CRap81Ri8RlWFv+SutoWrs+HqIZy2SEWIo4A7O4ntVZSC0ruwoeonLGKCVAH4JMioCM5BxMp443iTebwEI6oi1gKNvclkGvuzpuojRpzOwGfQH+bC5Kk2HitMZrcm1p0mv9bmrbcvDZka2+r/1lvEP6B8+r6OioSH8+bor9fz9Jq/4GR1fUdkxtIx5tsnWpw5pCoO9EIjNyTEJYDS9P4JCC4Bgmm8OTxXwGxnIDYSStQKakKRvAyPiYMDomjod62sEPxFYmXFJHQ1sKqH+klJc6PsAhxzw5OqFfNy4kua7t9atDRCvsh1unuJS+Ym83F55NnCXWuC3d2XzxymjxKiokegTUwgKyM//qqwflVpY5VpOycmblXEyeqGE+GpsYB+3MSlQcExqvvrYuNXLl0sX4s+3XuxqZ3TtcLeJ8wj/n2w+PGwBxORVA0aUGssD3BqrQ4gzlNWj5q7P6LoZHjcuZ3RxfKfc8vnpIcs2j55yib+ffHzuSULA4qf1tf9UzHPadgHHxeeXbzCBeu7eHOcDoG8xCAvU54EOFngF3Lq5yI1wkD+/IXFwcE5noG+l5bvv5ee8UFp3tVEjMmidYeGYUumHN3aVDt/hm3qHDdgeORZ+dZHR8xsDdAnTR0tx0GbNsC+fuG/xRNx2mTU51DkYN14eaz/jPAp06ZsDyrtIJf4b3XPC3A1Em0WS2qLWFkeh7Ya0JqzMo2dq7HpsJpoDw+OFS/afT1h5fWamhuJK9+tKSwpKiwsKmRlBX83H31WVvi0sf5ZSdH12x/duHHz5nWOLolkHgFdtbxBwAqZyFo0kLRW3nji0koH/Qrl7P3hZcf9orvacnIdVodE7pxis5WVeblnPp8rxqODFwAbEHkBCPz0oji1wBHnQ9ky1pyz5Ng+hixj7vxcWPP4alu+8trh/AaG39PNmvcsYGx7PmZOcXa4mUSxcrhuJOBD+lho7YwVXARBrJyUW6afKjFN2TZ/7CyyqwvMejJr3v356pPr9PMNfNcGA6HlzKHeXq3nFwggRnI0R8PnfWDbYqApZaSGgEUmgn+AxhA+i6R42JYPlX/daz616cCmM433/mp7f9MBXKbKxJ/iQtV57EVfG1TW3BrQ84LTmQ0e0lZ7NtRHao7IWmGsORsrqVQB7+hbjfnhmdW3MwOyA8L3xmz/oaHqn0Wrgy+mHn0lrHLxn0Y3/QvDAvPDMtv841b8j5+16FhS2Ob5w4TBlas3v5m+ImaZl9/e7CWZDtW28YG+cTO8nVeGhQGWZtibHuxtFI+XCXvioCAZODB7AwVqbhPo66E/v2ozHEb0wen5bOra7c++8/wwPleHhsR0u4N8msl99pKQ5fF5xjwr8GUgHqmCP5CSIeiHZmMKE33MXqot8LBEPT/2ZXDDb0fokHXG4V7eS4wzhyzcWUyCkFVx8WB8BXr28b5jXBUK1zG+8fZwYpq4BicmoCcmh8+FdFecFjB9tKCQRE8MTTuYYrpyZ7i1J5nThYrRCn5sjzA8Z8lc/ZKRs1ZFMA97ipn1oO0JGtmIeOI+dqjPRTLOEDk3b1iWveGovdhjw/bgjafimYZ2gNtdnBM6q8jBY3zC6c3Y6PlhoMDoostQsB1jiDAimkmxUki7pCLuvEchoPfztu6/CfkBordrZXXZXvQ+xBrCu//eg8+A7hZVR1EjmohzKUnY5UJNvmHO6RFPZIT76I8hZAJYpzam/6AJhf+0Fj4IWOVdu+zU68NVx3CM/uWGtbXzlgV8ws8iStLwKznfEBsY7+L+DOlVIf69IFmiRwJwkfR+z1YCQzvgYmwMYQLrosN0GtAVMoFAm9zIuZOHN87wF2xlzeIxHnYhu5YtW28xPi1+7tqY2TKPMcopLtIZCx1kfq0LZ0udZ5hZukzix3p+Su688R35NWt1QnzyvIqfT7yBpnzqmfaY/FV/+uaimM3oBpmVFW+ZcGlvIxrxJBVOxwgkmga4jDkfFwt8NbYilcplWo+H5BKJGNm3ly6tCe+o7uo88HB78W+HVBfRePQAov9U++y1B7cWR58tPfhGNGuZnc35ziCQaiNIFbJjek5iKXfQAl2qpMvoQMEh4VKHgt6vvjrBhskLkvc92LT9f/uWbpwdNjXIMbIkSh9dJ3Z6YWXRfkut4Qw796jyIP14YjOrATk9eowcj9lMyjAzXfxRZ9Wpr1fajOYxuvxXALqiD1ZJ018kgQ0ihcTEhibA50kBKUBWDWTnVMxMo/nMte7ZOFVViT2qq4EAzxd+naBZtL5a41y5bYCQGDU9mYYeuvXl8eP3qpDf58ivjfxMfr5eRYqnYTwNPNYF/jJVmsqWkv+s2xInq2qwV0kJYFwA1BNormTEecdMQwl1hPCPQUjO5T5ihKwl4gUPcNJHx+ozWjKakIC8nYVskV0aOU/m8fHn+C/VMC5/oq8inJAJ1JMzVbV40bZt3A4s4dcjugND3lgu3mQBZImJRGTSh5thX26Wx7FUoLqruIddr9XvX9y+5MBj8n0WGopGpJMvyXI+3o1gRzUFqmo0gHn8Wo75WtVBHLV9O/BuJGHsMKEI9jYBMrSZID11fFOAXiuMIKzQbN4ECe2pk3YwtpQjMDiAYcKXWipM0JVtO3yqM1ZWBZxyXbsvIj5l8gIvrH/qwN7be5Z+9VDlhZpUHYyUDEPLfMkf6eQ3v+ckTJ4X5rZk1tBhrllRKKYmyVlvqKm1hbW3FB9CVZt24ruhO9C3lbtU99kVYXfvhh0Frwd6z+6mceobHq+fF4ygXnAW/L2en0XrIXUIQZwTNFTnRuxq0Tgjq2ki8t5lkngBze22SFsy1WMc+51ATz67ezOYx0rmTkaioQgoU0rCdwVWnE3AiTzsLUAeoAcGEG0bNPXEZF3Vw5GnfsLazkCkzfSRNYhPHcYZfYzmZxY6OhZmZnC/M6Lmzo1a5OiKro2OSBR7N+3ZlH6g0TA810SJHB98jlzbW8hrD74mrzfnISM0DeK2MXlMbsK/X1Q/7DDNL1AH7u7PNzQngv3mAtZtoDd8TVUkAQ0Rcs6akZO3SdF1ZqahqqKdicvLQ737uhXwTZbXCvtYQP20IWQe1nCdUGKNXgRjuQzcCQMeG8ioc2GFgwPD0TxurHq9GC8OSJ3oOtFNNte1/fD3r37SvnXLhnof5HP2R4gHu3Y9e2Zrlik2ne+ft3nfHv7kb68TG3Qnf1dsxLHQaPSl2ptj3miIpG9Q3HCuCaDbUgUaNNtg39hpZqNH+P/OOSrJfGRViXoGzzzgHL2IlMs84BzBI4CH+eUPjvMl4LyHcjbQcdZ4C1oGsXuKzacMJ3MOd3QcQ00XyQz0900Nq+eqdeDVLmIPjgmnc5dA+nuBlhEXMTVEdISAKroe19oat9oehZ4mO1DT66RKBkcaoyaDwkmrmhQuIcd4mHqxXfSEROCL5TKJmOkLzHcfqvA4wqHafpFEog9usuNyckjyQEwmGl+or/GCUrlEQwC7F7/yGzpWigoukWB05zYuUa1jr+9TXcLu9GLMawXZ5FHZiLSyEdLQD74IXmxesfnUEctUz9rb8ZB2tVAqOWEDAhD988OcfAuA/zmqXVxWCl0Jpg8FxgtlGpA/jhOvjg50ntOXbltcrsrQEWB4CtDOY9QTmnC6GctdDS/DAfpoOEBfsR75vAPveDf/QLufm1uWl1C+g9NTd6krp6dN7NvdczjXzuS3lau6cGCI3/yQcr9Fz2/Zmq3llDU3a/9+QE8zvFwqgRH9JAAvNpdTjDjYPROn2Tt7o9sBqNJ9e/casqXgHcbw5vw/HRE0nXlRQUFypeCSX1pgQt8AZzZ3F0ftey1pc0PwYrdcX/ftiXNjWtOQfcC+Tb6h1TGrdvl6FlzPHXL81Qo/P6ekXE/jeuT8qAOaJtHurmvlM2fn3Dv8zrN0UrXiQlfXsvgjMZG18bFX62L2fnj2ekbcsqO7Dy/lkG4nE9hUQGrI+foEDkj/VNzaUBf0AVefKnkit6eJODu3oSDTI2b81NEustlzFi1eXXA6JNa1MjD96rrUy+vW7lYsmnejupn8VncUjZg59WBS3ObxBiuGj3G2d8+R8bM83NIVtquf3nr/2RqvaRlOUdrUgGYjIP2l/aVvyMleLhEy1pzu+baTEHakgVr87Nxue/a93bshGmg7EgIuj+AoOQOlbf01GfXpc7DbOGo9x//d7tCQ/mhA0wNqI6CYqPG0hpzPlEolckQp8zXajbsMf32ll8cmlptP0VfFnkSHT0KvrLx7hlpb+Jbdq9mPQVuAWoJOz0z6eMBBsm6N2qnCBubeWqCDZ+DabJ4F32eq9k4iZjDyeOu6vwaSZuU951Ec+g5NHYQ4tRKg7sN1H6kkBokU+ErXnfYtNC54Q1xgcgYJA5p66hUNnTGDU1JLGLdcvt2xozhlvxNy7vi0nR3KyaQv1Ta/SDVVjbA5GSPIENbws2D/UprPG0EK27eXoYveiGa30zGyp38SG8lkYvg7uwYzqiAmJC9oSYZtqOJoVvm99RkfFG45n0hiA7J89LCB0HV1zxO7sRmi0Yk1ufmF+IZIbtb12fLZkpW2wfuR/PG3yOvEPvIhck768sSZz+NJrNuKSfaW7lYrygpAZxGRAz4uPrnS+PTDItBkbZcTNJlP8xxajwtZ+JaYfus3Ho9KLoqdSissI67zmEmjBA39Ek5+Ck6SA0N6c/tbaNE5kmJLvsfWZR2iZ1+RL/25UE5dZB0/lquTVMuCVBUotKq06sEH5DiJ6hPMuZO3hhMrAr4GgItqlYQRYNp5YBSGiNbDzJ02cn2myUyF50IHP4nTLLlZADP9QKGnJaK59Xtk5RXS3ZKywDJ7rEf2r9dwTLcNLX6p942iWqvu5AyA3zeO4Efg292k6hxEXxOQ+oFFzf0CE+ZVAvJsmsWLaFTR0VKoUY8n5m1t6Nv2rloOat+gpK7NNVarq5HNXlIlMzIT0Nh/18olb4+Yal48WMUMOgvgOOlaAv1ztMobC9QhAYJowUgZI669AChlhmoRy5nbAc2TWT5G73bcRQw7sSHg9zfOoXsHSz0tORnjD+fvK14h7nFjLpskl+524aqanmDmhFbQoFW07qJahTRapVsVfKJb/RHBqnbWABqJeTxtx4hea6S+djKHPQqsLZB2wsdB9gKW9KIil+nqdYy4Yt3AOIphGGe9rtqEKs+owGu5PUhv83d1td9uRj2VypGqhOFNeK+BgynS/5+bLNE9nDSS5v+Rcx370Uzy5q8Ik9+/43BQjhRtoBrtHzp7oaviF3tQd6HoqrF6VcVhLoNqX8qPhWvG05itUzha6WgLa6SudoTYfvmeLEXk/Op1Bw7vzvu9IKHlgyUbvyR70UXVMWaS6q/NxlJ32+SZzgfzsrOK405kZr+RwkxD5yp3EezMYaDdJ8EZwGBCMfyMdKsUmUkfvLS6oatjtKs8ps9Ew5hn/u+ZBrIzUEiMDQzVbdn+Uw3Cb9rLV20UHKyv2zcc7xy251/TjZ6/kfCfZ+QZu/rpL7887Ychog8y2ocR3IVVc/XqDwhWaQ+K7s1UvTcxT7f6iW71xxerwvW61Z9SudUEnRzM1N/9EU4IjQKLcNVEXW2UpPUNtudCAL5loCrXhUJa4HC0aP+J0hqrkx4LeU8UW66pe8ZwWpoAbp4Z4GXU1JG6knr9ypXlGg/p6NJeh49z3NAT8hYpfqeysp+/EQ6h3AnKy+NOyhx4ZWt4AadYoD3QHffNR5i7rZwvttS4tLqepVxmMuNCv8xkIMP+KYpu32CpVtxsiOfN+1+vH68xVOaYDLoeC7D+oP5PDHhoC3uijKtWLGWaeYsxXlr5KB+Z/vxFO0l5+PWBzvDq6PPlH3yHhz8/XIady2pXbpRzezPo/Y6tBkpc5iJT2w3NaUGalI4mwhoCbS5Lh//oGk0tZRqTguw7YvnbuzOzNlfFefksnjpnRvXWjjXr947smDPLxmsKn9/BCqL2jI0+VVhzO72g4UTVhuWxa9IzmN9RCVnXM7JuFyNQjV0W76Gsmb9h3pzN3uefpMAe7UCztlFk6vrcGoKS8b94y7UWDm9YWBEKmTHZja5tp3ZPj3KTh9rx+W0sf/HRnp8qahoOd3ad6UXCO/fMTYrKULIB6UyI8G474A5Mt7pf+iEFryjcVJ67tvitSx2XJCxPE2fCAAONEKESyoH2IsCJqPlK1DlNJYoAylH7lqL9H5EC8gWyq2nYf4TsZt4sgtyUH/vGlcQD8SaqQziwcGNFXmb3earlwGFo7//Y3X12KR9MwpY0Ikto30ifZRZkNXbM1kqWH7mn550E08nS8aNm4OEdlyYOH2c5Y66Z8gT+YqBQ+RvHeuX/cQNHqeZgB2LY8nh/vA+3yzjAUMtpE517yrXRlJ744IDwbHIHAuyUtpTAHb5tsxWTvSbz+e2AZTeeG0qD7WXs1nNf1eq7f+2/cYB2ayfOEIdYmuOPg8+pXKVIp1S0SpBQ/tS++vPXxyiX1DLHDcmmA5F7FnWE+TulevH5rXz+gi01eD7esW+faofqSEj9hj/u5W/w7Kh1WT9vzia38vd2OEEszAJOSZoZxoDaSCakb7Vaz2qHQ4rpmPsPby/8ZkWcf2vmwsKghQWBj42+ia4Ke6V+zaXQxCjSW33k8baYfWH+Of4b7/CzwsJWOnvPjFsQsNy22mFtzI49fl7LYlakXN2UXBM6dPj8DUFrGqK5fVvosqQJ/86SDAfkZP0ypcPtpGzG6BmzPMIc/CY4znIwDRjgUgbNzzieehApX+POm2YmXF8LIW5ShZBEyCkYZYaOdt7+sJn8iOacfPpjC3IgJiiBf1UK2jVz7sR4qm9wzH/i4SDqcTgBup8PcPYBYk61aqJa04BXCnixA1S/LWhmq62VpXJd01skQbSeS/m98OoKt/UHF62OX7DFtyIrEF8np22QbRs5iuL4sasvb0uoXzuvTJGTUVnWPRlXJOGVqjiVE+fFRgGXNq5PAnykwAdpvZi61ap1ioYi0CrNHRGjIE3ZmPnpgT9Plj0hG8Kzq/O/w/5isgkpyHXUjoMdru7YemYF5F82qrv4DB5XlF+Wo5rPj60gMyvgVgvQYe39AqDDQppLaWb48HkI1emT8BmSRDU+V4h1/L4tIHTNDwf4qX440qc3xb6SRnakNfVrAzG9f4COVNA8Xcr56Ih+3mBgJBIY6mouOoMXRXCHNY46h4sTR1hYzZiLfwlIl3rQZkqnf65k3lynNW5C+bqobRXGWg8BuvOxxkOQBdBWMQKtyslaUeiBmnX9lqatqkOwNzmgq6caPI43Bfb5H70d1LeDtDO/tuPfHZ6OJqJPPgH/Mrnt/2vxAJRyra+hVYEjjZiauUrmy+Yq0Irrbr+2dHd4R80vP9Q+3Fb0W53qmyuo619TFSuum8/wHgHVRfQUR9C6Vga2QkecHHkFR5M7VYgN2KkObakzC6ta8tblpsaLhb8e6uxAy/5G5sxliOnL12xXqLryGiveiCdQPH3Iw70hJOJFhRT6/8jJjstbNNkEbtJWSBFg7cZjfPzzt+zdg1r6VUiC3kcQua5pcq2RgHsCpznuIvBwjISRWoPsrWViiUKtSZYSTpUYJO/frhWNuSm0tUDPLGzZW3uM7qrMsMHECRYjJKicRCKTVCO9MRNt0aqCKkVO5YHXm/bbV5H7qDkbflllkyj4lZ09c82R319FPc8PZ7OLSE7TD03r0Se7sK/qNLzWqqbgAtVGXAAYkwBtAr0HRQRaZMnpUSbojoEOnABDrJdRJy0R87nkXlOa0ej7Cp62PHq8DE9VeWL9ry1MnLz9ya9dDjmZSE5eq/soEY18a8QUiyKmu8hiyogq2zdRgApVPj9cyTqSnvfJkzNr2WaSXORSjqLePNpjD0EfndHGZyEg835pjUy5M++1k1cH1MjDOU4vK5E1XQ3wGJp7M8Bj6NO5hzXoWhFrTrM60WAtdDwi7aOmPx+0nk3bk3ap8cGfxz9MRj8RQyxHj8lC1EZfo1XvcmscvWSgP5SVUbukiZKuiqP2MOjwXipF2y8nbdq5IbDdJyjo8zXrLqVtXOyzxW/r3eLaz3yDfLuyKisLc2/j1ZFeC4NmTE+Y6zFv+7KoVDOh40q/1L1+EY7J8nlJURELOf7XwYAe0XsaqOygkEScTgNjxDxSDh9KXN5TDtdDF+Buhm/RT4lXfHoaWXNitOKaMxPB2d55kH6cYAhvFJ3RD6ABRNRNCtR/Rs9cqx8uJAHv1guHC9EZtDK32NNbQL7rP6TPUbMsvWPfs41jGXJo+0RmW08iCUdWuWzRgCk9vSuFntMo6uk192rAZ0N6bq0A9ibs01CNkUpUlzgpRMxNpWPb8v0HlVExfo0zKOfLDq711egIWbsq2mUWugd73QJnbw80IKenfkY9Z6fuxVCqdWUIqKOx3h//knq94PEvgf4LN7hkY5djsIPW+jM7jvrBm2lktk3C4g0J6Fb3t0AO0J0B9HqgBRZ976jRSQxSrRd3aUw9dmtl6r0jcVfnh7gW++crhxN99OvIuuwF5a5BPq+zsvw/Ghu7S12cUmfMaLmQd7x+mt2auU7aOnAzlch3NPatg90o+BY8I8pVDImFWOeDwaDlMjl6sakbaKj4r7Lqu+u3fVpC3m9vRz5HDgdtX7Cbb/FL/jfe+7cVHHZnWvLvq+YQD2nc4g3Lgf5e4LcL9iSkeqGZdVtq8zk634bt9b/VCbleudKK7y4sdQubGeectVGESkimoDzZOWbqIudan5wribGvgQDdS8lU1tx41uxV1jYnDuada548aYWzc95fzXXdu+CcfGBnSay5dsrtqi76oMiUm0CegS+gE6+SI+RQG3oFLSZ6HRUV3Hkz1T0pQBrn508iepxmrwQqDUCFgfM2AGvXeHqATdMDIIjPFqomNeLfVCMXIscP0Ox6QogK/UFGAB1hCUmkZPf1ACGGs282F6j9x1RbOOVz3PDpgZY9TTXNSEbeX8VVMgnkBskZidNZHKY6jj4mtvT1B/pgMZmF3llM7FDrjh2QpXsBj2vAQ8gbBVzGAxcNXo6DoaGGA+rD2qsReZCL6AL5NaXn7xXkd/KqEJvpqSZ9jP65cbh6/sH5NbCVWSXEoR+39q1be5ZRLDeIA/eC0z4KU+3hgilQn0zRTrRhoE3rL834WmMsmvG2dpj9Su5O5fm0au+YINKMjqo6mZlkXk39m8lXt6ZkTg3xRW5+5E8YYgc9I2GzCsMSUgyGW/m5RS/YgRZV7CT7yvYnFvjqDzObZG7jYyVcsfCnnxae5nQ9lESy6VTXv+Xx+nmHy9QbZICkWtjN9Fx1U2utYiL0Nak8gyz+mbB06QQPqcOo8aMmWI0i4D16tjHD05cbGqQJBZNn9CRylCklQQH0ACpo7+PhQe4OyF7wPhdYmS7jsnbGfebT/e/rE1hr3T7IBZuPTixcaLzg8sn8nW3nR2++RkpTC52ci9esyXdyKUgOVigCg+fOJlFbxe7rlmhm07/mn1uJctQ31Klvriu4ceeTGzfu3bpBJ7CAMAK0guUNpXYOqiDlsmzGTHXsolKJvxSrvsKL8/JUoOxl8K33SRTzNXx/FNXUSZzm9w9K1AxEoEkDmznM7CV+S3NnTZCf3BheFNjzIxDPNd7mT8fXdo7eyqMofXVUnOeK4PW+pfFkOzWPvfn5z1+3NUsxGuMVVLR5zz4O8QyIKa/SGGv2sihrSeM6xNp3Gn+419YBsbar6d73rW8n41GbzL35L4u4RSQYWRVx55ZMpFzchXPbSs/te8RxvsVNq4Fzn2k1v++Emd1TYuHFV1krb6EZl0gd2v8uafhITRSSAohMrZTTD0TMadktLtsFakaaXBeEpKUklsqloluti2JmIYtOch5tPUtenRWzCGhEPnyIlMRM9Q56/PQpGc2h8gc6y+FO1OGAinozzngVHCpLCdc5w9fRgfdIg1KpbANYPVfQTfIJOY/laiT8t8Q9+1Hrvfx8jtZIboZO730cxclW8WJvDIyu0VDlFWR3mRxAB98jxy4ou1E9q2fUd19M7U6g0gZyAm/50sl1SgkcQiyxUyrRB0qNfNAdMgX254Yud3+rrb1OAQ315BrUqV/dsVuJ3hGR+SQFSFQrmeri4p6UgRQuAoqtQGGw6fFWOCiKgLHQ8Fc7eLgSOM4C+1TClZqpd6bmKjRQoftpvlg0C1d2kBu4NhDqoImuM+d5Hz+m5zYvKFkxRJa/OqOSKnRVzxquyk8FhQ7J27gXaiC0f0FgoFdKSMx+SEo43Jkwu/and2g7QEeJdi6Avm5C/cIbgJu00r6VCfvce8zsrewM8syNyT04v/BKlnDTfu95c+e5uu7LIfctg+22V3vkLBHuupmefKPEc4Pip9onlyODixYezYtq3OlXHF4d5Ru+2C/g8I0KdrSh+L2PS7siinf83qrsKTYdD+jOkAk0FzHkzRh8Xq3oH7N1npPCxMk5jTCuXjqOjqtnRy2OCiyaE+L5+pJDX6xd90Vdwiu+Ie4FXoWdwWUDZ9Wb7CetmetR8FcjBHEnpzRbW0D2SignL9gVO7v/OSMhPTE5E1hq7sVHt41IgZJsV580U1Pak8pUloIFZkIccIIr6Z3z6g6wCAtIykmun9FBUqBKus709DQwi3tY4sfxSuXy2f6azZcipGnBIDaO02zVmasojxy/9ufTq6QN5X5AHmh0DE9Fv5ENqJAYq95Hb/I0c+wwDXY6x56C5RJNJsGn5HGjwc+t3YysVWXRisrRhFJzb8ya5+ZyuSHsgxLmkO0BSrGU0hjdtH6QTJaN5RB6901ntWIZJKnlYV1mzPBMNM8XDEIVx6WgL/rSZPRU7TgUGQ1O812g+Zh/h06a+8cPGj4g33aJDYnLdZjgcGLzrpaeb5V4adbSlQtXxG1sr1EV8N8weD4F8LzGzRCBCp/m21oLH4Qam039TWxwXJ5cqgCSSiCpOZJBKYshHwij8dmG0/JQ7STaWD2K5g9yD75Bn1vwxTPNkw1G28v2bissRJ1M4I4Av5WzQuY0La14L2Xl5ZzLNzEi61aXDEO/MFm4yzl2KjeFtnPYvmX7hgO+Uyck2brDnfmHnlXCYwncnfn3lB0t7RCTxETOoYKYpFRPqMMgUmnv1xcIAC33mVaggiHwrS30W78STs8+gah9hzX/14SaM5KXTag/URYgs1Okc8Zd1Bq/bkLTOfKFf5q6ewnBGjytI3pT1buA2D7fGFNcryS/kqgBkToUTmgRcBVpdUcCTYp+0+krSnJytL61c4ynj+Xc6dIR4xkbWu1RX1lJvu/8ojDMOtlkdvLrh1GrprjjKF8nUbQu/e/Z9JsvMB8Zogk5/YCi5n6BA/PeA9TLgPbLZtPmJAKotChr84o8vfl9L87V4YN7tzT15JhBK0rNYBrqyrkdcVqjKfue721eQqvL9x1cwGh2kdykaBcFutGTXKSeSa8CbK1AV93NgFzHygpQMcb9JtLWzF2/YzZClu1qfpfP8i2O+H55sRW9mlfg6Ys56pgJO7tRNQnfi78RpnrOmqtm4g+1sgUNok8IUQ0aptagn3Sr/Ee61Ue/wqr2WR7QvuE8XT+EXrtZfS3tYnD5tRnY08S+9SvmagBIUIyMxPTsrOUvqlifxvdj0z7a9d6PmME/qbpQxc7SSsSW7wrM8wjwPglV7NPm43/nIYM/TKeJs/lD+PCA2KcWty9OmZU5xw1QUH4U62k11l6dZdDVLepViph2WPiPdZneoz8QyHkziYT8z1w9i3b9z1n09Pi6rfYrPfcmlx6qP9SR51V1O3PTXdKOTqnqGClBWSTSJsgx2nPegZryjdlRJ3Nz3kxmXNHf5TmqC46AgXZZ+O8Ahm0UwxMeT7f6SLf66EWtQld3aFd5jLaC0c6iBz53g9S1NEP9U/8nb9Bh1cPh+Zs35/duLdLDpkMK+j+Cozp2trUVlyqbmpT9uV9Wc8fcKu1P0NVc9epfuh4L3ZVhn13RVfrdbA1+3aqgQLf6OJBbpbGHfnen+rsPuSm0I9jAGNa87xTahJYsOJ/z8z5K/IWR6itd2k07/bQ3Qynl6KTG8iqAK9Q+mhm0xeAzaHU5ZMhVRujBq6+mwWBY60+mq8uj51ApFRUNcCrAmLyXlwe0o4GLv4bLy+bcfXIIZunPPzv0cVqq1H9lEwN5DcwrIE+B7blSHwZRIbYPdUtOYW0pxXd+f6ah+JDMZ1ZSIgmolhK5NyEzE+SmfcoN7HsE1TMDOmn8DOzCQXNn5eAjZctBsz9Nf89QZCJiAgO2Bw5pcZ81Y74NnfyF7VE1J1X6Bu1NjE6aZGAZ5ha23MrHziVl7rSpsfFHWsy89m/En6ts4lM8W/Z4ZcE40OPS9yls4d/Hjj6viJ6XP2fx+x+WnFqUVrg4PdseDWUfG3f7gecRA95skMMksIkXjTNrad+pM+2jmryYTLNZfH5868q8Zp9lt99evTk75+9/Pn6QtW6FXYKTItqBz8e/qZnn5pzYGZm0PGrnsUNrdlmeiXL0bN0LyEBK+0FDp9G4p54762bN8IZyM0QKpKCa+z80bfWWnTtJA4r5+Ot3ThPy+VHk6sXpMdqfq6FeWTuGJKJ3xWS8pkDFvGHcOVAOkwfMkxg+nfma/PtMQrzHT59gOnw81j9+zWSklUMQPuuXE3R8juN0v+kwiObzl9Qap5o6p712CNWRIWg1+efkNyWR0zwr05HvUNLmGddX8oAhGjDUA4bBp87yQRDgKeR+ayuyalvvlxfcNsd5qp8tn22H8X4tKvKjYdQFXVUlk8XAUzWU/DOAJY0kPzDf0NpowOyXBlWptYQGWizihr2bNzQsiHXaGBRQFrU3zzHJ7oYB2un9xvq7Twu+ZGXuc5Ntp4V0ln932cQETconfBsXZIIMW37P4WYGsDMv2NkYbpbtObg89THSDLlxy7L9UcpYf8cUD5Zpw3zvrGoSRzqZICNy0Sz0UCq2Hqr6OTPFU1m9IGPurKyAwje3OmIBaiotJYu4PTWB9/TQ9PiF/W7a0I2vBzEmGeM67P3cwl1Va89AT/+b/UV3Nodtc1q8MfXS2tQvgoJ82oOydm5KwquLFkZEJc2TJ8+N9N+TEpQymxm7JmLJDnePuQnTZwQt9IrkvMVCyKZ6aDYledkMW5u34U/7uKYjSrJ+9Ahr56Ve3pZzbKXDJf38Ev/NQXI44DYBptdtnN7Q/g1S9724+TVfrcdiOso6g0yfnmg7efQfZH7yw4+IvrfZVEuL4eNQ8U8m+laKoP4ujzgap5rMTnmrAdUVkD84tQUrjIQYrgS5CnhjqP1zPOSGln0a6CKhSGZCHx0VinT2b8WW/Y5GnPv0BhmRmjcnvCIqINb6xF79yemznWKnTomU2YbIxoNyEKT6Bn26A71pXPR3Y8vTfGc5EUEzZbtbaGGIl+pHF5+Arr01p0IgygzjnuqiFbMJVBMKQKI5QQgE1pqTlSBDEwZRDC+vK/Du75LXpyQnnEyKXZVwaj1q6ul4WHMbvS/ctsw/0c1Pdjxlc+fi6JZ1bccxJp2LkoeifCaKORa/Ojpm55hJFavja0IgtfzMmvihWxeUU6bF2SyseFZ35Gm5ptC4r+xs7QCvr33WFry+iEZnzROx8NmAzgbgrlja39HNxVG/5yx6fdCXPj2/9euCMZnJ5Ppq1RsD2mBM70+aXosIdG/mQF/2Xx0Xe2/TaRPHgUuzbP/cGNQimDEISJO6S91mOvtA88XdOXi1YohdQVJGlU4/QCd3qT0b8X55H6ZPF4jq6ZT+lYDhf+DC5uTt48fRnLYzL+kFoTtad9f97X/1g0pA2ta0Tzim79OG2tilmYkL0WzlNr9tvs/Pnr95P/3OPuLWgVqNoUeQNGFx+NWctr0ZtQGMSTG9c/Z9sIwJoJEMxKeJmom4zixeYhXoL244/l5ps29UV1F7knKX/pyjioi8qZO3+izPnGm/Ep1WVbE/QNJ4+J/yTWQomEJ1cGTBKhfV307ePq8eKT7D3S3Tm0wiaN32nxNz/4BUXamJ07R1W0TftKelX93G7/2Be4pJnRfSqZUtnZeb0Hm5QiZCMNwRghuTqxWMGTgrF3/NuI9FH5t6sF+qvv1nxSg9sblNu4l0rLGeKarKuHXQrnZf1/3mrhkHYbp8qoIbkleQBegUJt9VnVnj2V5h4pzUVYbKwcKelCIliYQXp+VPiAl6ApgSuQk57TWJtRPyBAlF1OcmKcjN4NYWDiHqizwR3fh9lJ6l3DWu4HiQcl0qSiIu2KXnprmb47Sh5Jvvh/iMxd+Yewt+LGWYh9u6toagyKCjm06258WUYaj3Sg2c086W9CxAJ0s52KUkALRqPuBZPXhtrpmKX1eSutEjrZ2gNgfvPmGEhPHg8pLBS/NkdWaCtE8G8kZzujodq0teE/jt4EDfY6EI85rvregs6uhoLen88SnaMSL7/R1YQNiajlFMQE/XqLYa1KN6/hpRick2HtJOa+gcUkSf7oUIzPlF0E9hHxa4ZePmKaZmx0ebLb1+pK729Whl1n7Q/1j9OGXWGjSqKoeoDtY8yNcnm8Sodnh6RzyuVa3dmidiDkMU1s4/edOBC0cda580BoYGChkdS6mNQa4Adjq7sGaNLV0O7EvcOtJkS9z+akfr3dKJw8a4Ozq6jD46xsXR0c1U38qSNY8nDy4+Jn+uW5u6CTG/XUSS5RmXO5clNSyOq1vUY0x+SjgYubghaekrV9IByzVswzzBF3gMzR3F15gJ2KaqCjwxMmT/ZA4JClhv3mO2k8e7ynPhKiIzvoip5j8CvTeh8RtCh9o1SPq8R0UznJ1nTJs3D6VOd3aebjtvHl/kON3Wycl2uqP2fx7WcgDeQqAFUUkBL2RYu/v1+51V9/hTUbQXOStD0f7kPA8hX74PE89/h0PqCtkQE696iE35PlCaIrSWSJnZvPH0CWCuxyQTDxxd45YlwQaZy8M9Ul0d11g7jPWVyN3JI4fx31YNWe7oFjHF1CR2pMiSo1VN5IyU58QTg9VABaFJkYQcMRooGT3TxNVWds7jFZYGFrOtM3YGNDo5TQvwlk6TCYX5giEZoV5Zy0B+pgIeUyX4hBXyHkFc+wVWDPjfMgeF62HlsWZlvkDBLBecgZUnmhXNTgQwB+JxaGz5I5gcwRA6meh/6wIO98sOGbLWONzbK0a8dkjYTv6I/ncioKkCPWaHkAXqv/YSXs//AaUcDTsAAAEAAAAFAIMbFkmEXw889QADB9AAAAAA2wktdwAAAADdVa6+8iv8GAlQCWAAAAAGAAIAAAAAAAB42mNgZGBg3/O3hoGBM+GT9rcNnAFAEVTwAgCTpQasAHjaXdMzYOhQGIbhnGvbtm1v17Zt27Ztq7bNpbb2qe7UTvU7fOXwxPl1kmYe1hqMbuZRlcu+DNuRhJ06bo0FmIinPFfC/gl+4grey1BcV4xeWAR72YnpOKhYGzAY3WryYxmWYzhs0VfvzZIueACnevFDZRl66t5jzFTexbitHBOV28JBsRcjSYptj5Hav9WzwzG60ay2Sk09Lxv0LOp3umgOppPquY3+Ot6rPqcobxvsw3YMxGUMQGucRKd6a+RFXcWKPw85nK8De+sYWuKn+jqBWAThPa5rdjfgrxgX8RlLcARj1eNfrNd754CqKq1DIiYpfrqsREe4wAshmIXzynVfx6dh4ZNqiUckussV1Z6l/LFI0LNH8bTe9/kT76Wm3+uIlff1+OO6aA5mnmbxWvM9jSfoolq+oq3uvdds7bABQ7BF92v+iyTqKlLfz5HI+QkUcHwYS9FXfU1HtGWZrtTR13Q1y8wF8970MV3MUo4mmnHV0dcStgB42gXBAwDjQAAAsNq2t/X6tm3btm3btm3btm3bto0EgqDyUGtoMrQGegr9hdPDbeHR8Cr4IIIiTZFZyEXkIxqgldB26AR0BnoAI7FkWEusIzYF24U9wS28MT4eP49/IkKiMjGReEK8Ib6QDpmUbE+OJE+TfymaSkdVpXpQ06gd1A3aorPQI+lr9Gf6N5OEKc30ZlYx55i/bFm2BtuAbc0uZ69xOJeMq8aN5qZxC7mV3BbuLfeDx3iRL8pX4Gvzzfi5/Ap+M7+PP8lf4e/zvwRCyC10E4YIK4VvYg6xpbhafCq+lYDUUlos3ZR5ubhcXq4u95ZPKZKSS2muTFXeqDnVFmoHdYZ6Q/2h5dGKaGW0dtps7ax2VSf0QnpTfYy+T/9jFDZKG5WNHsZg46Tx0ARmFbO+OcxcZV4wP1uGlc2qbE2yHtqp7OJ2A3uEvda+6WBOMqeyM89Z6Wx09jjf3SRuJbeLu8C95N51X7gf3N9eZi+fV9Kr4o32pnkLvTXeA++1981HfN63fODn8Yv7vfwt/g3/QZAj6BwsCZ7FErHKsVGx03E0ni3eK345fjv+OMEkqiVmJQ6HcJgu7BseDT8CF5QFk8ECsBpcBC/At8iPCkQlo0pR7ahxNDAa9R/zOY7nAAAAeNpjYGRgYPjExMaQwFDBwAXmIQAzAwsALeMB5njalJDFWYQxEEAf7lxxyA13d+eC63Xd5XccCqCWrYECqIBukHyD60ZfMj5AJdcUUVBcAeRAuIBWcsKF1HInXMQC98LF9BXUC5fQWLAmXEpXgV+4lpGCGzQXQHXBrbD2yTIGJmfYJIgRx0UxxACDjNDLE+mtOCBOBMUaCWwCKG0Z1n872Bgknzik7RfxcIljYOOg6NB+XUwcpuinnxgJreERpI8QBhn6cTHI4pDijH4k0muczm9jb7zmvUfkiTzSBLAZpY8Bnf00yxywwtITffb5Zt37yf73WOqT9hERbBwSugL1Fj2PiNIj6ZBDCJsEJi4Ofdp3mj4MbGL0s80aGzwunCEVZh4AkbdX7QB42mNgZgCD/3MYjIAUIwMaAAAqlAHSAAA=) - format('woff'); - unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, - U+FE2E-FE2F; -} -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAAB4cAA8AAAAAKSgAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAADYAAABAAdsBp0dQT1MAAAGQAAAAIAAAACBEdkx1R1NVQgAAAbAAAABAAAAAQodMa01PUy8yAAAB8AAAAFYAAABgc4zF9lNUQVQAAAJIAAAAKgAAAC55kWzdY21hcAAAAnQAAAC/AAABEGjeCRlnYXNwAAADNAAAAAgAAAAIAAAAEGdseWYAAAM8AAAXagAAINJZlxASaGVhZAAAGqgAAAA2AAAANhL1JvtoaGVhAAAa4AAAAB8AAAAkAzn9jmhtdHgAABsAAAAAxwAAARIsXijQbG9jYQAAG8gAAAESAAABElQQS61tYXhwAAAc3AAAABwAAAAgAPYCg25hbWUAABz4AAABCwAAAkgzWFNlcG9zdAAAHgQAAAAWAAAAIP+fADN42mNgZGBi4GOAAAMgm5VBisEGKGrH4AYkPRh8gaQ/Qx6QLGCoBZJA9UCVPCAMZDMAAGrQA4MAAAABAAAACgAcAB4AAURGTFQACAAEAAAAAP//AAAAAAAAeNpjYGRgYOBisGNwYGBzcfMJYVBLrizKYTBIL0rNZjDISSzJYzCoyszLAJKVlZUMBgwsDEDw/z8DHAAAwqUNgnjaY2Bh2ck4gYGVgYHlC8skBgaGSRCaaTWDEVMFkObm4GQFUgwsIAIIOBigwDnExYnhAAuDohj7nr81QIkS5hcJDAzz718HmiXLmghUosDACgDVgg+uAAB42mNgBEIOIGZgEAGTMgxM5ekZJSAmAxMDM4hkZGKcAKT2MDAAADlQA1MAAHjaHchDQgVQFAbgr7rzbBvTbL1su0bZ9h5qDWFcK2ohuc75jWjEIOlXo/49+ECCuN8lOmSEwtAQOsNKuA+v+Snf3wQhMxSFxhAJd+Hlf/MR98sC4G1DlAREsOfRMyhQqF+ODu0iunRr1aZHhTJVGmXIlCVbnnxFipUoVa5ajTq16jVo1qJJp159Bg0ZNmLchGkzZs1ZsG7Dlk3bduw7sOfUlWuTptwYdeLYmXMXDh25tGjeml25xgy4/QFZryhCAAABAAH//wAPeNp9WQdck0naf+ctiRUMVURwYwQsSAshqHQp0jtSBI2KDRCRjiAi0rFgd7HRsWH5LHv23ns/D/vd7a6eu+7ZhQzf805CxGs/JclM3uf/1HnmPxOKpUK61rNTuPMUQwmp4ZQ9RYWLRWIzkViE9ASSoeYymYODzN5cMlQgJEN7BwepnYGBvp5AyNjzH/XJYyHsgI63TGPnZdT6g47ukGQ/a/8h1oO0+xoMco6yiFJYxCTmDDc1Hc7/cee/3J7FJXytp1mDQYMMWgVeweOC+/YVGOsaSwa4z3aanaGNP/KPDhk1iqKpERTFlnEKsK4PRbmLGQmSIgkSM8w05dO5O9DJJ+jkQeVmdOEFmozrOMXXLeh3+hl4cwrk5CDXl9LjMdztzc0lEpHUzoVm7FWfHHT1tGgJeGtnSoMXAqEpzSwKLQ15/VI6J04urym49iSv+LeYNYcm42UoPG5XVYRvpkdgTQIqnpVmiYV69pPpC5nTsEcK5uatj7XgFOLg0sSYBX7a/byqKApRhV2/sqlcNmUC2u0MDIXmfBQF+noGBqBbbiiAuA2jZfY6w+irZQfDFO41wWknM1OPZ2askce6Xl7Vgv/YXIf6c9meHmly66RPd659nus9er5zTCNy/vkX5FTP6+gAL415L0GHSKwvVv0J0TaEMU3P73zGaOmxd7DNcmxYxSmWgUQLSPRWSSggyxAIkRj+mEnKz7t20b120UuV6ZxCeZj2/rqF13CdopgXag0qfBm8ypgX+Dqy6/wHssPXOUVVx4GqKta/Cp6v6fqVeQ7P6/IWQYChOCzkxGUZL/Z8dNLB8sQzYYGxq51X1OJZnKJzVtSOqgg353RHi5/qGIq30RlsBCMoA8DQlTBWtL2MkTCmNNScRFeqq8uaBbWMYgT0L21fEI0Yxqwh6J9P7/HJp2/4rq1MNu2UMVdM0patcVNag4JQZjcFlRQP+QiHfGhTxoCrR/N1y8efr2Id4QCwlBYN0JHa6bDhaS9aW16mpb1saX2RdnBdW9u6jdva1tG7b+ITB/Yil3u3kMehffjkfaSLhuFH+A38e47EvI6fwfJYsLwPZdCj5hwc5FBf8FECxcYyWyNWJlw4qVgddbji7cY9bWjKR2TC/JRUIFfulxVn152OxohT3IA4TASLbcHi0YAFAJpQkiVpbmFFk+X4fW0ZmtKsbdazunUfJs6ccLggYmWs/ZKs8gsp8y8VL78TNcNve7R/gb/b+uKkQ/NQQdahmZMiMsYHy9Mmjk/wlQxPXJ0yc2tcaECax7jRMV7jonwshsSTKggBvyaTVQhZBS9kYiG9YxcOY7V12Ksd9uzVNWvgKRd4ar6qVsKlCMF/Cf9/2gVkhayP4lx08ALehpuOoD1QYb/TImWp0oieq1xJP+FjVwHeilgpNYQaSVGJesQrC4G660il6i5kQTzWR7CERDAGl5kjIy1HeM4wHLN95uaD+G1tSZZ9dZilYnvguXM4MGiZ1fq25Yl/dx2rldXby9vXf9+qhrbo+ZONTAqHmR7apKwM9kbaOYlTE3kvD4EFvcGCwaC/e4mam38XZBJjuim4YmyY1+n4TY8zMh9vTtzrFza+zLt8T+jSPPvhc8d5ln1o2tyxwtl5nrX11VvVe8N57zYBtj5gD6LEEENTWqpR8F1TReCi2NwcBXIRlaGhxV7BfsembXiYNv96dcnJmTSNYzM39aXNmGXoTl6tr4116liPyk8NWz8vK/h5q7G1Drrf3LZtB2izgFX7K3eP4kAfv27FMqlcpIocpI9EUiCET/QZ3IYP1re6HIj/cVlrdIJTctTgVs62tLRR+VN4eONKJUN/mTzRIWSkEnFnAPcPyLBQ0IfqTekDrqYboO59AFyhn6ARna+QFz6H4h3Hj3eUeXqyJp2zSkoY3RL0xtNW6uUltfWkkAqLNQGsHkjfpDVCfPRO4GgmD/T2p4xIXxGwQgsXWvYvqpm8zfjuvcEb35ZhP3TK0dPT0cHDA3Cq97xZMWzxoFkHltJfe9pAU6sgKyasVN0TVDnQ5MSQZBsSBaVHx665lDjr0urVl2fOurK6vKqivLyinJWWfWyp+7y0/FNTw+eqikt3b16+fPv2JcC9hKMJroga0hPXQiQUSQ0JslBkoIY2p7dWt/jF7K/YNbt1udbYOvnEklEjCvyLl9jPYaUAveXLsjzcR587tyo0umy2m/Kjs8/FO5WH4viKBfuZ16BnFKnY/9gV1E1B/1sDoa1zl0qS56XUxSTuzy485uHntGJG/ixpXtLMDVGLrqQtv+Q5xaUuIy7AxttxsLHP/LiYIq/xtvNHyAKdrZxtTYwD8qfOq3INH5cqdQULUiGL7qwJ2U9gtUN3Vi1765OoBO+48P7TSbwTLbmOn9GW6A+cg8qxgfIaOguSC3AMKwNJbYgQ0qL5hMr53R2xMrzMLO1A1aCUhb6DHfGK/dA+RrImHe1J+zK1SnX8MkIhp9OYTV1d3exAIAA8io87jJ05BdTJQEAViqH5ssRz4DOkE5MYMVdEymOwdwyp+GMjrkcZ589PWR0VuZpTrMA5px9tOhoB7SlBed0qP2NGrgy0EC5BtNCgBaEBvM+ghVPpkIhYdx3lsl2cYn0HTzm6ulRPCPUE5vzuTwmoJTPBOtWsoIRiVDUvFOmqpbdv5+UFJbhdDznidhUMS1H4ETub7Ca6UPdDiIwYwqQj1+XEsP8JoFcAACORi6WG8MYyXp1vokZKzS1M7WkarzUdaDZirBUdhQwqTUb164w/39/SpJJTdNjU1IxI3ofE7ah6Fe64iX85kDYS+yLzmhr8CKzvZhXgL0tpxkJj8EZMvCkepZkV3IdZlswuhiJEfNzZ9ZyC9AcwSZeR6kqBX8ArowtjkYTum3+j9cPDlgN5P+Ydanr4Yee1vB950kH/mS7naQf5y1Fa8HOA5w0rdAzsgdbf1pGwRzVrFpFEIu9Or3qboG1X3U0PKgqKWpdQ+Lpx5ZfYpNCjqXV7I2smvde7HVgeGVwamb4zcOqMv3HZsfVzIhf49hWG1iQtOJs2I2GKd8C6ovh0h1XW04P9ptr4uMyKjOzBnSCP6eATbwqS8v1UR45adgq0eqP3T3fq9sVaUD8T8vavCWQvAiX502bUK6FjPESMyAtZiJg5iVgZRWlmjTWzxYiP4zGYXQO6+vFxJDRNSjZUus+WtrZ61HwU26CPt+kqZSYoO0p78iHj0YgcqbwRqsqz5NFMu14Ry3XU+zcUD1lxjFyX7b0LL7UZaOPoGekQMNTJ0WFQEM+k2Kt41gncsS3F36xosGfR2wt0AqATZkYqo9c328mYI2M1x4IxVHiPiAm72aZYxTSZqezlDgdeDy9FWBNB6UNQ1MwZxgwZq9kHjPsRVBl8X87ngXQOpkfnKMdxw8LnbUwZNGtxlIUXHrsfVaIZQAGFUcXx47SqtB1nT2T+3lnJZAEqQRF8gEhJSaRKIDgMNajrPLuWq4XObUR2an0DHdEAWqgvkZnz9FAuM9Si9YGc6IpUxUbv+vIWv97+D+XbL3RSteea5ubmNZ7VXG2GDr6IH+Ib+EK/3NzeaCyYNxw56mR8YKY92K98rcX83Gmk9Vq5/8E03kPCnIiH/UkfS1THTaTaZ8kuJAfNZGsigUS6S4ty6uz1PXMKQ3MPTGcaof0oOyqLwx0rHDx/SDy4gNb7ugUQaKoFusgSkgPATlfzfTlpGy0841/ANwfoCtbsra9bakgfgBjHgwXhat5PJFR/bHhnnwbUZyPqwyeP7yXsTf6P59eg5wbpiiLYjQi+bk/JG5Umlv39usVVitib34GorCWeM7zmRCkjQWoEmtpjsATX8BaH4zJk3m0xRZOaDya28qz7P/d8NOfGF2RS8bYWL0arf/77pFVRkTWcAtOXnm49Ew2hy1Hut12cm7RQDngI8Ko0u0gPPImsJ2L93c/IpPyPWpz/T7rm7btJKyIiVmog2UvrldnKgzaAWSCnGA037kPp8FaGi8jZmdUYKRuAIKu/Lez4iPFrOFu516xaug5d2wOA1KOrz/4CJuYr2yqa0DB6CUks2MnAqoYHKENSqSIekJwyGC1Gtba/WUuf//Chq/3wUSttMzsPy1hDC/Hgfk70kCGmMQXuS3mjr7b/do29raw99LzQb+h8I/fUw6vo35ULlHvsFuduLea1AY0l2nSowbw2BxWnkWgOkbrwZqBSdu7T+4y7Ncfwy+3bkcmVH36IzvcAJcpH6NTtjUfC6MNKb35EmyujlTeRZX52bTasAXLaIau+L1nl6TCeDp3/h+/Oz0Jgiqb0v56gT5UcDonxXhsya392f3qKcmOv9J/S0tfbTXK9tnonfr+hnj9He7klSW3ib+6tOfhitt/otLHxmoM0oiJAl6z7rE6J9Ogeu4suMFNas6kM+oKGln/ZXv4saLZP7ZQDp/sp6+kEreONGbWuU4Luc9m4FTe+xYcbFcHT3cZ/Rr1XIu5hiHSmZyJ4qD5Lg4cCiuoekx1UoNpBET9LTtDkKSEfh65PEPcUkmXCNr5n8UJyGmPG6uAT8qUJB3a3Tc+Nz7Zow8d5MjNO5nHjAtZFz5cX+AxTLmRvreg+B5eCr3rUMBJZHX3+7GtOW6i3GR0dQ/VZUsOXeq9o9tl7dXmTD1Pa2lreb+dZv9jhI2L8vGMsR8Vy2XX47Gs419W0oFEXlAshs3vQCOS8bM6Xe/e+JsHr/S9JvN7x6p7Wn6xS3m4kQTzTHgbkRUW1pfxmdA23n0aeObmoT9ex21tql5V9Iif7EcoHdKj8zMJTDyoXV1eXksjgP0hkCDNSxwVqkhwNeoZHLEQ/y2tiD+wOq02xjI6XdMeIGa/D3sLjbL0hSrer9qaYVUtCMmPRUE24SLyswe4i0te0us9ShgCL+BMusxd34eCzb/Zg4LspKG0/XVBaOkf5hhYxIcogeh/ks/tcC/nUInW9DsaGXDtlC2jQ0oWwWA3BeXWwSY1baA6EmksKuQvNKPwksZlBbtN8R/cRLsv1zfYtSPRckiKhLU+Vp++cMv/KksLLWe6tGwJTJ3Htxfq29iaGTlO35vV+ffyaa9OGkxudK9J35demP1i37XVeAepzqx1Zn5YZW9qCj0/BxxGsFNa2hYZnCdUGiEXqA0s304IAkE+0V/HJ2bF55UvyLuXi+eH/N9UpwuZFaWlInhvu/DIrfyErdcuNCcsc0r8wZ26FG6utrV8qEHT+HBEbGGi8xCs+ypvn0k6g2Yg14fmDAnIlFKO/ttKP9ZRPWZOlED3V94KxsEaCyRopCoWcqGY5i24mLRUhIsuk7FReUYsL0Q/4Y8dLHoal7GFXsSJnTR3o6aYaJs0TaT4BYhWBRmTXYp5HKf3jbFxH9h+IlLi2X2/jEa5W9KhO/ErgY1LNfK0y9ebgBJJcUTEy78lxFFFxouZcUfjQCvwI7cahyLwC7O4+70PWB1CascAM/AgnfizS18xyP8PsADJbqA8x4XPAVoC1MFCI/hOJpvvPu9n8/tn2n+atnXes6dn7HTeS0RusS8vQLzgC7SR/A5VX+DkeLxm09FGdEt1J6qDKehTZfyTUEgkqPD4nb3FO8K4JISHtczOPzcudNCE/oOBBZe1f/EL89mfX1JQvuUsnRXtHhNhYJY7zdC2cEpNqLHSaFZC6LmCiU7LMdU7MxAjQz5/KmJ/VJz2+cTnIEd9pQDFifm7t1we7XW3t1xsdgTPeS/Rm5okJnU2sCdabccGFmchHicgLekGUokmUSvG3WTPN7CKyuu7w+yzoAqaYriHNoO5O6x1kcwxvRhuu4MabAB+FtpMYvcYkE0SO1Fmcqs6GU2RfeMV0AppI3bE0OyvT2YqzBva3cJns7WM21lrST8wbz9TgV3sel0daJBuOST69BW3nMSIBOQ4w9FS3mebmcgkD/ww0t5naAXUjBBzd61brL71YljPd4vf4xS0ejmYi989RjqPPRZ2LVH5lTZS29I2e8fzXO1xXbNfaiq63ont4FHjogY53vOR9I7ccpBb1qZ7yPVg5kWVMmVWdKbxmEl8crZYyIBVMbsfIWJugFINfYwiK+hQslrFj9HBZKy5kTao7U5maapBSn/JByoigkDHJpVF3LmEVjwFd2dwj4DFW1Di+L4q+64D8vcm/XMZ1383IRebm4p7XKXS/9ZbTZLMzbT2K4q0nDV8/XGEVX+gmy5ttP2nUGp8JE3ws3UYMd0GbbL2HD3Oz9A1y4x7pY1YuLf/Y1PypUj4G6+nTaIy88lNz08dya7npiWfPTtnb0flWNjY2ylJb2emnz06AH+Teg/g1kEQDUs3chmjoqiqFWCuDpKiNZG63Ou2ctmFja0xCQJMNKfTjDu4Nq9BWnDE7zs0RPeR5LHSpAhLR/oCiJs6cqidJWztfQG6RX5WJD8fLsyYQYlW7QZSCZ8Ag+a9sPbhTZzPquxH11UjU8H+gSwG6noDEf2PrT3g9cd3iFUQRs/o7EHLP9YivpB5sXQ1A2DoaoTIa+Do3XiUKMp1g6yiyQsnZhqS5J12HHKLGG42nwjN+momno4yrz+eUp0I574+pS15YFwCfbPBYxeK0+YDlAVjjAUsLsvA9Vk+qjv6Wv+ZBVsGfq3F7By1dsTxkkd8agDngs3FRRZ0XU7sY2+IxZtMnL5jO12I+YNqTWOpTRmpUNdXV/QbJM4DBPrd+T71U9svvwYEROW5FtFs9oG5vOLSIWDkajxmROCknEd3hXeejJQS+vhU+DqTEBPe/EHZSxfeNr/z1l3Mn7vYXmrlPcXcZLLMU9zKkHYYNz1yYBeA7mg4c3s+sw693Pq2Ks0gb6DT3RC1qxlbYUVGRMwN0QXrYZtJ1TNW6/hNfVx8O2o1LTs1OOlF4Gnc2NyP2rMTMf65TDqjJcF+WnVfjRusrX/MjVK38iOcZRUVnRqj7CvOadARDquf9uWkPxk4IO1mbPa+76Zbp+wJCvIv983bro+fYpN//FQUVewX5norc8jQz4wkrdXRKth7Z0lJyZNto62QXF9WN+r/rMPh+35ID1/t2/2NZf2dW6sOtU0/6hrlXBpa29sNa6K325iL/Ze4hE06z0tJ3TU0d1W7OqTY2246U7GgYbTd3nDP41X3LDX7pUJox2aV1Vbs0w8+SO2nylB55Sn3nDmMROcOngqXzwFIDatj3d8vdRNuFNhzak2czqKAhOLB+Uc6PQYLS5uZSYdiP6ckBpiF+AeGm4ay0+OOOxs+VRU+qsSXkYvyK22mVl28X/jRt2p8W3bwM+maD/isk4wMJb1B1SIi+BYm5VAyE25BhJE/ScpNzEYObE1OTn55CizthiTf9k1k7cWpiXInRyA1Jm7dCd/qLBQ4gXATH8V5RZjz3BTANz9aie/BsQrQlMqkMpaEw3Oa6H35OsAhKD3T1jrWcOJn8qlBfz91rLMW/BvA/K8jnrpvpPzTvhwmFGfSZqbHkBwZ2R+lKPm7psBc4gx8s3wUT9YFu6qrINhIx+bdxxR2csg/JkbQNp6woK1NeRJeYzs5GZlInCxaDlCO8LOfySBzIL9rufHczZfgzEzAoe/4GBekD6v+67o9/9KgXEvYSFLY/6NW3L92ADd4r0m3t5isUGXbSjClOo0Y5OY+0JBdlG3pPqqwPVfrChYSib+WDAvpgx6jqava3uefLFl+cl3KhdPHFtPSmhqYG+N9E0ciYEzGruJ+pvuRER364UHUCcY/PqMLGxcVmtKsrSrVycbGydnXlRE5W1s7O1lZO3e8UQmlsO+MkMKMYQDKTcwyHk2P5ycPL/wHfZnMUEygYS7415CzoriCcYC8Yu2J7LM+sBwkoZqXgPiukCqF6f4fnU7mfGRehMXmeE5qhayhNiqcLjR/FNsK3SfDteKGeBu1TAI4cLdRbsSmW5/HW3BumWPCB0iY+aRYkHHDoqICisF4Z+hN9vBP0M3pFFnNvnJImGI3z8xtnNCHJicj2B9le/13WIEotu5jrbz/dz8hdLnc38ptuD15YCnozi4QseFHahanO/wexyY1KAAAAAQAAAAUAg4V762hfDzz1AAMH0AAAAADbCS13AAAAAN1Vrr7yK/wYCVAJYAAAAAYAAgAAAAAAAHjaY2BkYGDf87eGgYEz4ZP2tw2cAUARVMAIAJK+BcUAeNpi2QAoeQ4gGgqjKAB/vxBAgCwCmBGDomhDEYDRMjCEkOLJEBZDYIDnITAAjwDggckADwYBIMAABMKi7sznHFwXjp6WhYm10lKuY2hloKdrqjLT9B0+FOpIZqyltkh7G1gL9l0pBfNwqKM0jKxM9JyEhq47cQ3xJenacW1gpG8Z8r8fQ5fRbVNvvtL5hmMzQdOjWvAZ+m7UCnWovBqHM5l3c7eh9uvCi125QhW2O5oy99Ejp+kgPaXn1EhZekjtcPQPfPVGPwAAAABQAGwArQDfAPgBEAEoAUoBdQGnAc4CEwImAkUChgK0AusDFwM9A1MDfwOrA98EIAQ9BF8EZwSSBJoEqwS2BM4FCgUSBR0FKAVQBZYFtgXBBcwF6AXzBhcGHwYnBi8GQgZKBlIGWgZ9BogGwwbLBvEHDAclB0gHYgeKB7QH3ggVCEUITQiDCLYIvgjJCNEI+Qk1CV4JkQmxCbkKAwpAClAKWwpzCqwKtAq/CsoK8gsyC1ILXQtoC4QLjwuxC9oL8gv6DA0MFQwdDDAMOAxDDJwMpAzGDOMM/A0fDTkNXw2JDbYN7A4eDiYOWA6KDpIOnQ6lDq0O5Q8QD0kPaQ+5D98P7g/9EAYQFRAkEEIQYBBpAAB42mNgZGBg6GBiY0hgqGDgAvMQgJmBBQAitQF8eNqUkMVZhDEQQB/uXHHIDXd354Lrdd3ldxwKoJatgQKogG6QfIPrRl8yPkAl1xRRUFwB5EC4gFZywoXUcidcxAL3wsX0FdQLl9BYsCZcSleBX7iWkYIbNBdAdcGtsPbJMgYmZ9gkiBHHRTHEAIOM0MsT6a04IE4ExRoJbAIobRnWfzvYGCSfOKTtF/FwiWNg46Do0H5dTBym6KefGAmt4RGkjxAGGfpxMcjikOKMfiTSa5zOb2NvvOa9R+SJPNIEsBmljwGd/TTLHLDC0hN99vlm3fvJ/vdY6pP2ERFsHBK6AvUWPY+I0iPpkEMImwQmLg592neaPgxsYvSzzRobPC6cIRVmHgCRt1ftAHjaY2BmAIP/cxiMgBQjAxoAACqUAdIAAA==) - format('woff'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAABi0AA8AAAAANBwAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAADcAAABGBYUFO0dQT1MAAAGQAAAAIAAAACBEdkx1R1NVQgAAAbAAAADBAAAB4vpb18RPUy8yAAACdAAAAFQAAABgjIUE3lNUQVQAAALIAAAAKgAAAC55kWzdY21hcAAAAvQAAAGLAAACIBAyEFBnYXNwAAAEgAAAAAgAAAAIAAAAEGdseWYAAASIAAAPfAAAJNCqXJsiaGVhZAAAFAQAAAA2AAAANhL1JvtoaGVhAAAUPAAAACAAAAAkAzn+kmhtdHgAABRcAAABDwAABDa4CRTXbG9jYQAAFWwAAAIFAAACLqxBo89tYXhwAAAXdAAAABwAAAAgAYQCg25hbWUAABeQAAABCwAAAkgzWFNlcG9zdAAAGJwAAAAWAAAAIP+fADN42h3EAQaAQBQFwHnLlqhYe5cOFkDH7gJ9YUY0J+DSLDa3eLySnl6vOeqRUc9MEQ37L3x1RALJAAABAAAACgAcAB4AAURGTFQACAAEAAAAAP//AAAAAAAAeNqNzQFHA3EYx/HP878123W12gAKUicggBAggREkATWTSmc4g+sF9LIC9GJ6DbEGZo44Hx7w9XsEclem+tc30zvlvKkr5Uv9/K6sZsuF8uNt8bq+TdMo9WC1Eoj5rFoaICHZUah8+lrrI8ldyoSxcI5ASDITF7h179iDR2dCKDb1yVadbNchjATCQJJLDo2FpDDafD6SIfwKpwLZZv0HgZ4kDNVsLX57Muwsb9ntpPjHXsu+UctBJ0mYqPkD7fYe1wAAAHjaY2Bh2ck4gYGVgYHlC8skBgaGSRCaaTWDEVMFkObm4GQFUgwsDgyowDnExYnhgDyD/D/2PX9rGBg4SphfJDAwzL9/HWiWLGsiUIkCAysA/o4Q5XjaY2AEQg4gZmAQAZMyDEzl6RklICYDEwMziGRkYpwApPYwMAAAOVADUwAAeNpVyjMAkGsUBuDnu7atc21n27ZtY8zW2lZrtm1ryq4/2zVl1+ErvIAX8ZEXpQf/pRfewp++9ZK34tV4Nz6Or+OXKBKlolLUiXrRIBpF7xgac2JNbIt9cTGuxe07dwjxWrwXn8W38WsUjbJR9VG6SfSLYTEv1sXOOBBX4sadO1nP7M1sUPZe1otsYPZq1vvwncO3D98ie9PzlTyt7z1bJdHHTlfSW+mTlD8Vxr/+878ccsoltzxmm2OueeZbYKFFSiiplNLKKKuc8ho44KBDDssccdQxTTXTXAsttdJaGwMNMspoY4y12BIbbbLDTsed8K3vfO8HP/rJz34xyWRTTDXNdDPMVEBBhRRWRFHFFHfWOeddcNEll13RQUeddNZFV910N8RQww0zwmAjfe0bX/pKpFdcSy+nj9N7JhhvonFm+ds/8sonf3otvZHessxyK6y01CqVVFZBxfR6ejO9bbc99tpnsy122a+xJhpqpE56J72b3nfaKWecdFUttbXVTvv0YXr1LvqUgCwAAAEAAf//AA942kRSA5TkQBTs7mCN4RqZnH3R2bZt27Zt27Zt27ZtMz33g3sbV95nVSEWVfTPZBtyxxGDAlA6pCBURXAIqR2CA7t50ZdGVTVNVdKIPj7AhIqmyZLX63HzAYxifHrMsIps5J+PzNK/p/HKZKcrqW3prGWSssZGhHhj81VPW71R2lrNeqZLTExn3NzxX5dbcvV/LyasNzbWu5IvViFPhZAQPs4VJ0YWapW3VdcI+t0ITcqYERGUHiF2BNcIpgtGqJDAiFjGIhYYpon+oP0afPA+Prhdn49PPMYN6CKu0e8F+AN5iDD6A3lxkBcCWQ7BI1h3AF6FKSWk89+HTLibvUKzTaBRY7hG4yFjBWQEWRmNYH/RITsEuJm6+s9160jgOjJO78I10neT4r8XIIg/jxDz2O5g1VfhqTKP6Xks/X2LJXqeazTmz7YxY9gyY2CTev5XbBWuB4pAcZDhJgZvRFWcBovOgEgi+ogj0ilLTrZKp8crVzzp1OnJipWPO22fsX79jLmr1s8gGy7SA9s24fzXLuHCOzbTg9exC6eit+k7OB9hAUGPF7BDba4RcOWFHkqaNCKsIWlaDjfPw6foECSWWVh1cv0TBxtNrb571Me5G9fjht9xArOzTb8c+lZ1SI9Fh2tSzDW6ABtmhWqDoFog1IJcYB7LZONGmvUgboc7bSUu/R1xMBX18mQz9J4C+yWwsr2fZRJjR9M0UT7e4/bCKGAmUnvaqWYtT02derpFyzNTR44ZNXLkqJGsPOL7ikU/x438sWzJzzGjTl29ePr05cun/P7/DuB5mAgBtpUFTExs6waYMbGtC2DWxDbvgDkT2xwB5k1sbwk4ABm61gNs6CTCFj4exnZGgbRyilYeNwmQ4ZfmhGXSkJqtJ5ca3pfW/zBgeL+ns+c86Te63yfasO/Q0pPZ5x2/nnxPP+cbNLYwjrj3COdasuQfV/UAezkTRQG8/euxH9a2bdu2bdu2GawdrW0Ga4Vr27Y60+09be5rJ87voefe08zIc4/uyS81FkytpBvvz38dwomTriflosR2KkvnXNCAo0GNtzHd1pCtAT1RLrLKsM9gD8ghVlnLsjLD+7IHxUOroO0ZFA+Jm/CmiodlMngXeH/2iMwMj8KHskfFb3nMdgM+nN2QGrmWHj7Ndh2eTNbVMJfiKeTQmCd9c/8nSddkTA+x6jpUzqY3hTV+Eis2llxV7CsFq70tKE2f0qMZWFN5tClrao92gdKe0ng0CqUtpfWoAaUdpfPoZbzflDfsNCxeUcPWDsUD4jy5nAPvyx4UdakZuVDxkOubFA+LPvBD8P7sETEKDe8mRzNx8GTivkY5TymeQnyBj7E9hJwRN/9S5G+neECMRP6S8L7sQfM78pRVPOR6c8XDIgW8O7w/e0Rkg+vwYexR8wO9iVKDj2A3zM/kVgdyzBXvzjsPcw1WPIXY4Jw/cjadP/w/8do0Zw/kmLeIz9uxF/W6LEmOuYr5vCx7cZ83Zy/h8+7k2ENJn+vk2EMpn2vk2ENpX871dCohZxSeKE6gxy3wGewBcZpOGnkc3pc9KCZi//sUD4kh8HGKh0V5+Dx4f/aIqAvPAx/GHhWp0GNu+Ah2Q6RFjzvI0VeC2+MdzLVM8RTiXOzewEkTjZ00rh5ixUljHcadQrsx3N1cw26GwmewB8QC7KYYfDR70PyCmUopHnK9n+JhkR8+TvGIKEtuNSTHTInurOMx62zFU4hD8FV0ByL/P27OA8hfke4c5P/X9TbInxvelz1kPqXnit/w/uwR8wh8BXw4u2HORydFyZEn4ObsjDwRxVOICrG7GZ3863SSGNNDrHqQ/uOgrU4n/7mdXMVMI2xvkTgjwXbdmWkxZiru3PP8/aD5FTsuo3jI9X6Kcyc+505kZcWjoiDe10qKG6IodtMQPg3u7XCWz7lDraOc7fufeG2Ghj2QYw9dfD7C9hbotqvrM8llcf6fbvx98jLs3X3ej72Hz8ex9/R5ZfZePv9bmVnAJ65lYTwe6qWU6liFMvID2tdS9tGQMFaj4+4+s9N23N1dn7u7e8u67z53d3f3Vwl7kpATBsL4DPT/hXO/e7nn8pERkS9BrmTYdZFPmCDkyCJikJYj823VtA0e+IoKpzNTzckxiVKkfG6KlKftnWb3XbmkJmWQsy40NyOneNL26Q89MfXek+3rlrc5RodGFBaPWcJUB05uI2t6n5G/GezKOp4+c/KqcYcmkOlk9k09Jw689vRz/yqZduu+G+8foeTAW6F3RoCPweCiTI+vvnzMtL4K/euQ4ix6RTWd+fD+DZfuXdPRNKPl+yt2Pb3x0I7lK9b8fe3CN8dNGnHjmE0Htrb+lXx//LSpbcHqlf6JLRe2btxszd88edZW6bzzlw4uHzuxcbIy+oXyVPpTxhvN0nYrb61RB+F4axk8dfr6Ufm1tdTfrzx+e/7o8XXLJve5vdR2TWpuNjXi70z1zRd2r7Qzg9r3BWrHDu4lqX+3PhDMywmOLJo8DWpvg5nlMn0JK9Qu8ZVYY2fmJd+Tr84lf53fMnjGEFfZicbjd9Enjvd8MmpYrnWLrey6E5GInvQhMVvUd+xP8lSmUE3+fRW3OVYt+DvBdHaO8j5Z86LRv4Ja9NEz0zuPTDlWe/trTx1fOXhHaPch32qmWn5f7rq46/KAIKfZ6f+QPJm1752n5F+kkS/+70h4hvJtC8YsBs8FMIISwTWz1mrVvAjZnHLSnxT0OfLaxuufu335vNqlU7z5fZi+e+XIlX/6YsXd91Bv9NasXF4x8/qNK8jUy5QV9kLFLVDRHa1IKZaVskrQ91VnUvZc1Xat1+uz6k9hCk4mzxG88vIl27Lyt86/4iLBeUlZeVrhcEEIFtxQGBSEYUWZFQ6m70L53T9/Kv+4bu2KzST93Z/JkgWr/3r/3NabZ86/dnpPnvzVoqunzry5dc4Df1sViWh7ngtBL6xRTzQ2mzCh/EGDCkgt/zajKdea0dQ+BhWRpn1j0A6k6V8bNIw04zWDOnRKdD1nUD/S7hjKYwV7DLXjtT0GZR9FKmtUPqCcCFiB3oIUR6sgrc8l12wJWgg1Nju5xh+M1wTUYN2TabD6ybXUPvGaiFraN/FaB2rwfsRpYdQyXovXeNQoY+7amabOb622z+aaUf4VgwpILblmNOUrM5rablARaZpoUIdOia4BBvUj7VapegqqztZpfgNmlH/YoAJSy3dmNOVxM5raZFARaVqxQTuQpsfQMNIMzqAOnRJdvQb1I+2OoTxWsBuU8UYpT9KQyRJrwG7vPZ1qM1FDqLKB06mwmgmqgCqsanIVVvd0KqxygiqimlacqHagmm6ihlHN4BJVHlUqdjW0Tz91vuu1PVViRvnLDSogtbxkRlPuNaOpLoOKSNMiBu1Ami4bNIw043ODOnRKdL1nUD/S7hjKYwV7DLXjtT0GZR9FKr8HQTN67VdEGpEP2cOlpY/c6L3fkpjnNhvvsCWkB5qtlKRKtyjKl7gkyeUJBqd9Vi//9FB8pmD/JrldwaDLLemPpFv+cNivvZbYrHFOfvJZJ52YZtqjNshH4R8P/GBZKv/UkHc2fhb/Oqz3r6fYQT8/qH5chAR+YBT9TnhJzHO6VM1rvLNWAbonMtHhGo8keWDFyOUuUXTB8h3xjhrmKK0saC1tbfpdKOjoV1Xc6myXv4z3zLwScHkCAY8roD+S51dWedy1DfMrq4a4vBPH9e4wS27qLt+g7X2JMKF8p0EFpJYfzGjKU2Y0NWRQEWlaP4M6dEp0EQb1I+1WqZosVWcbNb8tZpT/N1AtIap0E84tkcLckApIYW6JFOZmRmFuSEWkMDekHUjT+xo0jDTDYlCHTmEdDOpH2h1Deaxgj6F2vLbHoOyjSNUbXRrFPqo5fV+TyRJ2udrdkiRfrDQKbNzpnzXIP1NXxgfvpO19abJAfi4OodOTOSQPR42Rjyn9Dj+k/F7+uYF87vQOseHllmQG0aHe+/Xn2vu2ZJ4vBL/K0USuUA6rSlHUT4C2stgT4IX4OZz5AJAzkkwnEtG+/6idsRn7JZHynQYVkEK/JFLoFzMK/YJURAr9grQDKfQL0jBS6BekDp1CvxjUj7Q7hvJYwa5R+YDyjU+j6h2HnQbHGpCtTqvaTNQQqqx0OpXvTFQFVGFVk6uwuqdTU0OJqogqrHaC2oEqrHqCGkY1w5Ko8qhSsatBHpYP0AMjDzEcSQMnyVaWoIdyfoKGXmHhXOkkD3vl2Zz/3el3groB1FFRFXqaioyWZ9dw/pN3Tldq5bAO+iaOZziil1JqfdD7b+qJyBrljuVItct4vky7B0PNcUmZ2QsX+20F0rGAu6iq7OXPsz3F7gBBkcWslb6I/UTt2aT9Sh6CpqtUO9AtisrxwVoFt9JSbkF/BAermDdpgXOofh0+lmbl9ukK/OOJL08/G1BdzJf0Ls5OZKku4P5N9FjIpKgJ07fXW9bap9Q3zbSvtTTtZL6ctC1QFJo1K1QU2DYJXpsFK3EDxxN2eK3pyUI9ZXpgsA7tNJhXWTnEVTthnOKjmW2kF7KPqi5LvCX0wt6PqSK2caey4kUcQV/IvczwxG/wTn8DV3vYr+g93E9mrie37BqvuG6onw2uJ+1hvxLaGgvrmpvrChvbBKjWxPnoBVwnVJOVakCi84B39BcZvOi7hcjU3hlvtT1Xn9CiJWsvnVReVTy8/2z5wKqZc2ZOzMmeWuBWXvUM/Rr1HrtbW2faSRU+emIPu7tE3mhX5vABcxX1BBeCUX+Fxn9VJdcAaYmS16DCR3DNU1xIHVfbSfllTm0njXNLBTb/4oXZmRIXCriLPdlfvFJWVQRbCfaSxGyj53ACjJwDr7TxtPPUfUgTc1YdvEvZiwuW1OUWSFyV3NafPHaesSW1OiMS66ALrNMBTnLrliwAJ0Yd8PP5y6f4GY91YC3ouL4IX3lw1bWxfpzymv7k9fF+hqp1xNg66Afr3OUKan6y9Do3BjxFsD4vl51X6FHr5DC76Ju5DiJD/b9zn9FfPG8z37esMyB5KsW88oGLa6I7uLS12dcS3cHLmF1bHQGl//KlYfXkBHU718/XtzNFZjB76Ou4cHREsItj8j7zEe9Y5CzPEz2eoNhkPuKe+mFSgTsQcAcqXokbjyaLmY/oCzGjnDZD0eVqrsesFAyqWSlZMiKgej+ofsnpq2P+OWqac5KkGqhtZ16hb8Psco7J5WwTypkDSSSifybAKfCT+hnxPPTzB9F+hl6grmjefYLdLbfbyYORiH6qwtU/K58weveDJ4Yg4s+U/wPnoep6AAEAAAAFAIOtEGX+Xw889QADB9AAAAAA2wktdwAAAADdVa6+8iv8GAlQCWAAAAAGAAIAAAAAAAB42mNgZGBg3/O3hoGBM+GT9rcNnAFAERTAyAoAksQFynjatc8BR0NRGAbgewiojAhaClBDprIUKhEUUQLSiIBBoiwRQGUEG0kQsAljRMUCAsiivzDpP5RaDxsAFzPXw7nf+36c01eLNknxQ4UGWb5IU4rJszRIk4LWOKNssccAg7IkKYC4Hd6o9tX+LrmiwpNZjVdO2DHLsMA2+wQi2S4H7bvHdu+4d37hgVMKTDIhq3LdeS+tZw5lM8yRw05rgwtuWWzv/n5z43+afvtpaD1ypDPLPDlOWWZJtsG5bja+Gx1TpsgZJeo0yCDvuXKMYg+ddakUo97R6FKmd0IhikKOPEM0zZIckmeKBOuMkGZNL0HB+T00fZ9hOayyEobCYEiGsTAccuEj5OWJfyvlf0EAeNoFwQMAHDEQAMCL8XtJHrVt27Zt27Zt27Zt27Zt253xPK+819ob4s3xtnjPkEFJUAVUAzVALVAH1AMNQCPQQXQGXUeP0Xv0G0scwfFxapwdF8blcS3cFHfAvfEwPBHPwcvxJrwXn8BX8AP8Bv8gjARJHJKCZCEFSBlSgzQhHUgfMoJMIQvIGrKDHCEXyB3ygnyhiPo0Bk1CM9A8tAStQhvQNrQHHULH01l0Gd1E99FT9Bp9RN/RX0ywMIvHUrFsrBArx2qyJqwD68NGsClsAVvDdrAj7AK7w16wLxxxn8fgSXgGnoeX4GP4af5TxBQJRWXRRxwSZ8UN8Vi8Ez8lk07GkkllBplbFpMVZR3ZSvaQw+QUuUhukPvkGXlLvpDfFFa+iq4SqbQqhyqsyqmaqolqr3qpoWqCmq2WqY1qjzquLqtH6qNG2ul4Oq3Oo0vrWrql7qEH63F6pl6i1+td+qi+oG/rZ/qj/hOQgfKB6YFvgMGH6JAI0kIOKAzloCY0gfbQC4bCBJgNy2Aj7IHjcAnuwgv47Bfxp/p/jDRhE9ekMJlNPlPSVDH1TSvT1Qw0E8x8s87sNWfMbfPK/LTKRrfJbDqb15axVWx7O9UusZvtRfvdcWddGpfV5XU1XHPXwfV0U91OdzeIg0mD9YLTgkeDn0M5QgVC5UPVQ/VDzf8Deh+O1wAAAHjaY2BkYGAUY2JjSGCoYOAC8pABMwMLABbLAQt42pSQxVmEMRBAH+5cccgNd3fngut13eV3HAqglq2BAqiAbpB8g+tGXzI+QCXXFFFQXAHkQLiAVnLChdRyJ1zEAvfCxfQV1AuX0FiwJlxKV4FfuJaRghs0F0B1wa2w9skyBiZn2CSIEcdFMcQAg4zQyxPprTggTgTFGglsAihtGdZ/O9gYJJ84pO0X8XCJY2DjoOjQfl1MHKbop58YCa3hEaSPEAYZ+nExyOKQ4ox+JNJrnM5vY2+85r1H5Ik80gSwGaWPAZ39NMscsMLSE332+Wbd+8n+91jqk/YREWwcEroC9RY9j4jSI+mQQwibBCYuDn3ad5o+DGxi9LPNGhs8LpwhFWYeAJG3V+0AeNpjYGYAg/9zGIyAFCMDGgAAKpQB0gAA) - format('woff'); - unicode-range: U+1F00-1FFF; -} -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAACNoAA8AAAAAMZAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAADMAAABAAiECUEdQT1MAAAGMAAAAIAAAACBEdkx1R1NVQgAAAawAAACuAAABIPeB00hPUy8yAAACXAAAAFYAAABgcXSo31NUQVQAAAK0AAAAKgAAAC55kWzdY21hcAAAAuAAAADFAAABEjB9MLtnYXNwAAADqAAAAAgAAAAIAAAAEGdseWYAAAOwAAAb2AAAJs7kVKgLaGVhZAAAH4gAAAA2AAAANhL1JvtoaGVhAAAfwAAAAB8AAAAkAzn+KGhtdHgAAB/gAAABBwAAAnLQ1V1sbG9jYQAAIOgAAAE+AAABPvRh6ottYXhwAAAiKAAAABwAAAAgAQwCg25hbWUAACJEAAABCwAAAkgzWFNlcG9zdAAAI1AAAAAWAAAAIP+fADN42h3DMQqAMBQFsLwPbuLuLO5eUMSxY2/cUkJEOQCPsjld4vaKb4pfE32KKOxrGIPTBHIAAAEAAAAKABwAHgABREZMVAAIAAQAAAAA//8AAAAAAAB42k3Ng25FURRF0XFRNyiC2rYZ1ogb1rb5+lH9xddTNytzB3tBhELTVuXOzq+uad3P3F1oPb47PNd6sftwpfX19Ook3Ewmo1UK2awI0f7uxYN8xARyFNvw5C0oF7FCvRKR0kAtIoGg1KAho8ZEQY2/nup/nuTbEwX1BATyhc7AhEmRWKOe36VqCSLLgeYAyW/vOCKkYpFKk/xrLJenUq16jdr1GBBcBo3zDtcUF4EAAHjaY2Bh2ck4gYGVgYHlC8skBgaGSRCaaTWDEVMFkObm4GQFUgwsQLkGBiTgHOLixHCAuYD5P/uevzUMDBwlzC8SGBjm378ONEuWNRGoRIGBFQARghFeAAB42mNgBEIOIGZgEAGTMgxM5ekZJSAmAxMDM4hkZGKcAKT2MDAAADlQA1MAAHjaLcm1QRgAEAXQRy7WxW2BtPHg7jYH7u7uDhVuFVQwBmzBBvS4nXzFMwQ+Cgn37LlrfPVWeB0dMRDTMRuLsRsHcRQncRY3NzdEY3TH6F0zH0uxH4dxHKdxft/A5SGXU5eTXG6CBF999xMpPGGeZqTeYZoWy1akazWtTbsOC75Zs+G3eX/89U+iJFWSpWjQqEmFWpVq1KlWL1e/AXnyFRg0pE+GTpm6ZOmWrUeOXsNGjBpTaNySIhOKlZg0pVSZ8luXDDdmAAAAAAEAAf//AA942p1aB1hTSde+M/cmsVAMEIIgIlKisoASIBZ6syFBUCAoVbGBFAUpyiqgIB2RZsUOqCC6frq7+u1i77p9V7dYtuj23iQZ/zOTLPL15/mfNZs7586cOXPOe8qcwAlc5LM2IVl0meM5CTeO8+S4aHupvZPUXoosxA5jnb28vL29PJ0dxoolbOjp7a30sLSUWYglvCd9lLFpkcKI/h/4A9rrqHOMmbldxiz32Xbu1qbDLa19YxQxKQpNWsG40aPH0Y/o8p9vLRMlPt2HBUtra8tOcah6mnr4cLGNuY3DiMDlPstzTclvdKqdiwuHufEcJ1SIUkC6YRwXaM87ICVyQPY8v0h3P/MI6vsE9Z3S7UZXHqEksleU8rQdfY8fwGnOwToVrBvOWVAegZ7Ozg4OUqWHH+Y99U/e5hYm2AFO6zEawynEktGY3zC3PPLrT5UrFqhUW4pvfVJU9p2m+XQSqUPRC7qr583MC5qzJRGVLct5gUgsPJPwlbxFJGglEWW3xStEKfbq8jTN2lmmRqHVHIe4fpDAhknABUrtZfb6jwR1IUIwXqV9wJtYCG+TifVEXi1KqYMVHbBiqH5FClgAhJTaw4dfqPujuxsP6ca1utWiFN2rOOxpO93hNsfxjww76Pl7wf+9+EfkNvLQfoM8yG1RSnX/36qrhdnVMH/Lsy/5hzDfnEoEhwfDKVSWlqAKL7rsoWv6qc1pF6LmxDf5Nuwgy0Qp2mUxR6rnBfiunqx4eS/P1YE93gIZm4EHzw0FKUFEczAIWGR9d/cwPPqq7gsc8AHI+CIu1VXqLKmUvrACxOZgEGjuwLthTy/egR+NAUEO5kpzc8EposOFF+MnPX8ijHjeaX/ET/ffpabEd2a2VGWM1nrxN2xz6poDdO4g0lz+GDdIV2YgBRrNy6i2kBv2ovqyJDZIMlS892v0LTIatlc4I0/feiBSFyFK6Q+w3fHRWnyc6g9zCc++FKJF+ZwpZwOyWWCKZOzlaUZxbSYZAfrB0hFmSg8zITrnUWfHpzk5n3Z0Pso51drT07qzq6cVH3uDvP6348jv3TdR0OkTpO89ZI4cyT3yLfz3ENnTPR6DnPEg5zDOchAKvb1VgDh4dAD4CfyeeY2JV/pSmmJerfxhZ28PSv4N2fIvpxerdCe9yvL3no8jSJRyB7i9D9xigZsxJ6c2V3oIsr/4IMaXOisqu/wnklV8u+PSUVTx4UdJW6JeEqV8+fb9PVcTyDNRCqnT7fLeXLC3BrQYCfySmHdxgcAD8CPBR7pJlGBqJtzs9xRuNjfDLD+YtUqPs2glYvam/xZdQW7I/SwpRKeukC5y8AzqBct/j6W6ct1InKlrxJ9QS7nD6hJYPUS/B6IccG8vce9DK1HOSWyu+xZLeTAPPgGz62G2PcwGdKXZS+y9EMgkQxH4TZl2E/5Al83PammpFQKaKBZfJ3F8kXgYaGMkQ7RYkCj8MMUyMgQmGrD4ot3knXdH7fyhgsxC5yaHhEz2DgoSbLU1vd82OJZaL/tbLX66CX0bMkkZGqqcFAJ8twIubAWlARf6cEeZsfAnHyuWWYDPUE3j+OZracuuNTVdX7rsRtPm6srNmys3C8qK3zr2/lG7+feD+/+orrz2zhvXr7/11jXge43ECbaie5yUs6PyslBq4K2QSqQIgqzU0sDaGeVM3RFf0zFLc7Kye3knOha7yWV88eyyjZ4rRPd052ZFAPv2P+uKyDCZZKXu8fIA3W++06++XXV6AegcjQAtBoIWRbCPhEYSIdBMV9ctSmnrh6A42H9g5mrwGRr/kBImepqpUMdRsclQ9Mv9o+bDiQmYdEbRyeY5wlVwyFd2oyGJ/cGD1ksMsQo+LE7xqcL1fm/qvXSX06DJoaDJ0UyPcokzyyQQqNgxVfLnasUdi0+ER4aVzS46JkMPia3RSyURZaERM8/Nb7+fl/uJoJzsk+E+oaNj05kuV/cMP7+KXw/u7m/41z2YPp8HNhXAR7+pAvZ4Yd/by7I+2JPaNzMqsGpOeacRMUE/mO4umV0XGDnjvKAs//ngwf6aAN+siRO7zmw6st/VI3OaL/fs2V+RUyzmxBwds6zExoiNWbZhY0zHBv3TsQXHDcpiPF0fiOyRHNnjK6ivfx/qSyfHMMtcopTW/kuUG8scbDXPuDOfYOMRbMx0z8YCcOcH4hjPmTNkwZlF/yWa8Y5kCdqO3AfHtNMtPT0tO7p6WnBBg+Y/RrXvyAM0lkrAMg+TQMQkYlmBjSUctckkGBfDedlpWbCA0546RWpJVTd6mR5W6OsPgAmwluUHtnbIP51uKDvdNhjLme4kNAKlQZZD9APBQZBrS3mxLpEXj9Qe279/P162dy+OaW8HLgadAJdh/8TVko1ZXGbj4UziRhiPhl2MmH0of+QFX4gfR7zwOW0u0hGer9H5ols4n1hvacR2eFRTI3GgvFgUZbyMGW8W8djYlJ1ABuMdwFsKccqexm1LM9kILJE5eDlz1OG8zE0wxBS5udSbuT7u1v707PvD35JnP+pwen1YW+ehzrbpdaKU3Ubk9z+fceTXIfv2DUHDEfcbMjLaDakm/GjT7TNDeTvtw6F/v9ncPYtKwaI2k8KEndDGkLmtqMfqMyXsKVXCpuwZS6SY6/hgSW9lT8/h6t5vfkcbjEtubcBiIjT1jOAjtCdHHG1CWt3Tc0QnIy8CxwSOY7hzgDONFUNYNJOD4pTPUScDpkogeZuxY8WtaJxZvo4kfr++vPiz7Ts+La4q/pEkr9s4q1H4IvuXq9+Rn3xLaoKQ6ccP0ZT9+8mVhx+Tn0NqSvyQ8XdXf8l+7nelYmfqd4CHHaSNavzZBeoxjM7r6bqfGT2LWp3RBQN9D6O3UPwyushAv8LoxyhqGH2YgX6f0Yczi1K6qYHuw+g9HGeYP8lA/4Qb8A/xewb+Yq4NDeCCUU311CHULp/B3JuGHGwo+vibuktQ8U0zFHxn4FQzYO0KNms4rKYxl8JTimC6E3wwT0KFsSRM17YN/7BNuNYGgZ6fg3pIFEa9JPIfPUCmjxok8x+iBnBB/yVqYOEIOvBvyyCSiRqBV+D/KIYQ10zmCXPgDGNhN4Ue6go32MwPKyHVMwRZWspZNY7vTI/Ndi9IbzwbH7ZNewopRpFv2m8vCtlZmts6q4nMy3VOjHjB19fFZ//Xh4qfnEpvKr6/te6VYk9XTbY6YxtEXB2c1o3VEaawG6QA0JcHuBjLhvyaseoAcgClz4x3q6SJEUcZmTZaWOIaQ37kuVpY7/Q86qQgOUIKe7mTAinRDvRbE/Ehagfgo9U1owuXcXeQrhmnt7bGBOIkWKM0xD8BYpoRXc0rWdBXITnP3yCrijqwef8p9F0F8XsFjX3xqTAZjYeY+K5t/wyBnzZO+yWsvEY0lAeTwJizhcinlDnYD1Tc/PPi3UsJGuP3fvSR7l2owtGPt4kJtro7KSLLMdAxyMMnsLt9y5bnNTnRuNusllnPnLNpbVsLWGU2yNoBOJAxPdFUifRlmjnYBVQmbDCyNR831ZY86CUxfWjGu4rwBP+x3lbCI17k4afbZijfwtETTapi+HDwClvKkXlFCPOKXbo5zCvYTgz/IXr8S/5D9pL/t1rcVNvFx4b8P5MXSMFqaOYHRiwurof9s2B/28E1CkBxUIniSCVxxDcrTkWlBG5R5/TlZb2Wl9usive/vrWD/Lh7LzIW5YcE5ajc039/+9YfmWGuq3w1B5Dv4yfIZ9+/5DjYMxD2nDSwJ42TwvOahTmGoWRBf/SS6t3kp86t1/3jVS2r817LWnRyXcS+6Kj486L8feTik8fkwgGN7yrXsMw/br39e7q7KicwFHY0nAp0PRN2NOWauQJdWeAdeMP2Zm9m6988K6JvwGfynj0WAqCSsubGM7nAXZS8uSXTiUJhwmwwqAL2wyo3jIhmo0am2r7Uc+h4xbTZycZmNvNfjH/pRlxPQ0ZeZrpTxOyQkTbqpYLSt6EYeerukO8nuJrWGS2MyZlbGY2M0Ij92vqKu7ffvGCvObRpX28I1c4pEiuEie5yHs8rOslonn79o5IcHFR/PYFIUgkVDk9feTozqjJqemPBzBev5yb0zrJRNS5Sl6lfObbSYnnoquDqZbkFnSkvie7Oa89aXhthJHlB05yzsW/p9LBc/ymBpYn7DpWo8hLX5tRseTpZLnpY9upikCgGJIoXvGg1FyhHYjHViLfKGWMqjpmZnD92hKhdjOwqxliZ2donrV7reyS0LHuc4OWsNV90o8IyoP1geA1yRibvTvGNJFpy6u+0KqwAS3jBfcCJ8xiMvYEoCBo3VMcq/Zc5w6XhgoDXrdgROj8kPzR2qfuy2M0n4/wLj2U1v50ds0WTEbPosLKucNvmytapm0X3/KYs9nSaGeTu4+kwufpaW9rphqiqJ9VFZzeNnVw4V7M2UHci8I2Wo5dfO5XfvJTq/xDIFQI4mABSMXn+qVg3SKMcLLFSyZucLM9v2bj61MwF4T9tK7ldULk+M2t1X+7ij+bOD9mnLqxYt+I19ChKE5ceoMyeOi+8cUVBkVReFJOwzt9jyvIJjpHzZsTQ3T8mwRB5L3HOVNdiblBSkAxOGmacirZvVIKx1fvko6aAqqxljRE79oTGrnJJnVf1amIDcvnSOmPNOPKOTHRp1SvkQX9p6ppw5zEBCeqco9MLXkgNd3Ybb+u+sqO8GkmQ3dFhRkIVrQNJHP9E8DLc/Bio9AFBQi9HYO7RWA4o69te1ymPiJq2MmZU51jzXcMsRuCQPkF5oLE/WyaMz9jk6x05QYfwxRXHAyzNAkKtYzQcr79Xgr1NoQazN3j+oEiH7EdjimdEd7N3w/9wu0QHdR+I/As08Wv8yC8LCv0FPIH3yxfdO0l6vnlMDr32Kor95gmKfkV749IfeXl/8Ctzfjh37occOFEx7Goh2HJSGltV9tLB1vRCD8lOC/RHaviEBS6uDvUz6o7w9XXax3OCLKRrzR3a6wGl3bA+RfCEaGnJ0I9oQHDDCsSDa+qVwm+pI37IOTDZd+rUePU4kus71rzTxkrwTCVLyfVgP9OqoeODJqAe9CT5XrwuH3ctPakByVIg3iSI7jO+SjcMuuXl1JskzhjYK9DnIaMiyzNH5XblR42amrF+bvfM4hWupHefYJu4YY603Gx6fm/RN6SW/BoVsBBCydJPteGONNoeBxs+E2wh2jawaOsP0TdMUNLqPOW5z9KMftc+fsUa/8MRpenjUWQXSalFSmT7yWQ/DfmI7DrL73bu/xnWXwJEqsFuU5jNBmNeAg//AFA/rAco7+XJwiO72l7LvBQdFbpnzoaakqyfLH7QlE5Xd5bnN4bs2hUWED9xzNzZ2X31av9Fma6+WaGFV0X3pvikubosXZy2om1W0cz0wvAJzmHJ4RS0doERkxxecJI7RmbsytFsmO8+RB68fE56K6vvDF0LOLUZq++MYbwQ7M4b+iNgKpHUgonvJXWSQb3F5FWi2i78pqu376oEFKlt9pzmZu9sMy0xkj+uVfPHkS5FHWRcZftiIT6ZUSMMHV5ibCqhsesMiRNGsh4Jy2FmUkN0lkogTdMM8byTgdM+vxN/ujq21rvz7q267AnrZ5dWqlYJSvKIPG162ubrQ4bL+EvghKab7t8iv/uHvnOl+uUFoPcbZL5gB3s4Ddb7v48HTM8vZ++bP98/L27+Fo2ycsPihvDW9llxOYr0peuPxJTcF5Qevtku4zQ9JYvyo92dZi5WZ24PLXCImT3eY6Kje/6JisPfFgNamB4ThfHsVuMhyGVOCmcTPBB2FfJ/bAfhilWITyUPIxN2rPKrLt+0OS5407w1y682bLmxfM19YbxEqLXA2DbmwMY3r9946/AlDzz+1qHDf1ZU/n5w308VVJMR0Fv4E+w0jLOGHQ12gegq/0dPlfK/6gomhasn24S1xn+VTB3WzbF+en2XYFsjMh1RbmWWoYse8Fu8nfaH4SQ2wNkK+NJQY2CkZIwpUrGCf2w1qvpuwZ43OzNTvJfHeslHCbYbybPtZ77OOtqNP9R5Zmc6L9xTkIWGtVJZg8HqK8EiozjFgNUlYHKqCzOVUoyZcQxFAmCA2Yd3OrIr962G9ofvTB/XOVnlnrd88sas0KnGh0uCAQQ/kZ9e+abQiJRYomZz8uBlZJNx6BmXXXg0zRgbV11ctjFxxwJiZnHn6vt9VIIMskCYLkziTFjUgGAsB+CAvymc2ANSIan/ypW+i9G6g+RiWuCSBQtVvLSTHEojZw+ijUuESf4777Uv0Ukc8M78hsvVmZOn2ehSN+iW2+Cfs6j1o+GEOaCz0dRj9DpSMt2xcz6/NuOuwrUu1jZHrGySru3ZveP8gs78bdBUTDFJ7czPRCMay4huZ9ODchNSJEM7jHJ6FuMdutziTVKe9cW8wDJrYRc3g2VYK56aBzM9UrwZqhwvldTwyJAuWDoFbG9bWmwqX5e6bauPotnBcfjIYB+fAKu9IwN8fIKsTZydBNvF5MHZJ+SXvNysIsT/eBbZL1r1Wm/yigMLU3fHay3Jt2k74xYeWJF0/PUciBssP4jVUA/GsKp8+1juL6ro8QC15eEAVeIwQN3JqAxnjEOqnkPgAJVyMFBbuAEq5WCg7uQGYhfjYDaIA9MSoy4ZRGVVKqNG6KlmlMpqFkaN0lNTKJVlc0adp6f6Uwx9CPnAUvBikZHdN9BAJhMsdVl4iy7BekKnnQy924hue5/o1C3AFwvaaWfYCdCRzWIqvVUCIEQ0gtrLRIB23N1J/O3GTg714vO1Zc5KD/7S006ZaGV4hZGRqAbzQ2nHmlZ8zNetDH1X2naVIJGzM0sY1Njy1zuGDUPnLlcTX5ydlyAeZiKpdpkk2BKLtL/P5GOvao/IxzSXupZu2xt+VfuLOliu74Hy/cwvudDBJbLhGjHQaMbGy/aFzwnMik6uV29viC/0j4rbu6ztg9VFn8inTMlwVkQfr3n3qkKR7uuxuf/I4Z82UB0a+qugw42Gm4RG+2HwLnjDdmVv8gw3iUb6hlY6JI510A13ulDQlPl/66N3H479N510RDJlqEPw/Pf9dMRVk3n850Ipu63IqYea4H+XHHhWQfvx/LSuxPYlS+pn+2+rSG6Mbm2fkbTcb3VUVEteSHJ3blxeyGih1Dh7Q7BcPi1rSWpuhItdUFpUeltY7vjYEKXK2Wpk0JKdq9YeWmZt6eASTHHUT2LglLaGyoi1MAy3EDTQcMAz0TtyMnPB3M5waBTYRwSRUHRjZpyLYFsdubB/s5VQkt0QpjMxMt0sAyY81wPaxqKHrMtjA5oDfKnM5bwJRhDhRApzGMpNsATvahpiN23ik/W3PH3tyGR33t5DN2b1OW8fOwl7IR8V+mJ1LDqiIktXNKzEI2s+rzqsRqUr6ld6jworrqLVqD+Jh50+hicJQyOSIyV8kMDpw7oCunYjMKfwx24riOXXaM4S8oREIiuUfVruJNtp49BCLj4V8oq1Q3g+XbdM9HEVaSW25LUVj+5EyoqQWw+yQUdQRB04G7eOaARPVi3IOEdOCdoa1L2Qg7WQQoXkEnPmBrzeDRDFiwkvkbAKUxqx0inEwX/itLCje4jRlQp0/HJ5V16CxMhoKCp/YZK2LG+hZDg8V7h4EM3EUekWI8OifhR/3LIdtU3bymdMbdLuHlO60bF4a80KsybdmMhQOX/brmmTw7qm2uXmW/ED6keY2wXaNxPdA82rBt09De5jgg2VOgMvg9rg27pEpWID3AU/3CVti/OyS9o6b0r2wfT952PjW1+NjWpLVa3WzM/zc0xN8FkRslhYcvnVANG9iDW+C9oybIzmnd0Z11mh7kKB968j9+tppTXk7lcfP8uAnwYXtUaPsfdocok+Ue7vB7jfRm/wIOU45u0DGZ12WQdKU2gODvxcT7vN2CJue1JXQpSmyN9/fdLCrKZV6AtiffduSseKQ28v/kKu3p6N8smuVTkVyF175rfCXE1WctWFrcm7E46RK7dJOomn6NSAX8eK3gU72nEuLP9SBRlcTaGQs+pMLtHXYwh8QQ4flVQhxXVNN5evvlUuaqiurVkt1G2urEWN15evvomkgrBPEAQ5X/bF9kNfrkUlkqtnTt7EGzcI18+cgm+h9PGOg0B/jViFaM+HkRkydCuM9wtB74G9pKCJdhZPoTaPHojFTv8rpw62ncJ99NhZ+an8TG2gfyC/dXJ4y9aUdabytQsb62dMzrSzGzrST6Xysdpn5eM9xc/a2H4Mv7HYaLioBA9Zmkp+OvyVIc8KP3Uho9Rlxw/F6/PsO/Jv9Gl2QceJZVR3a0FW6gMizoLWlqH/A/GoHUB+4nLFYQA5AzaAvDQvYcgwo6EYQG5qQHXNmKbnqFYHW/LX/xXVZ8hcVquPoB3oQDdM62UVDZTwDzEvHNRDGWE2CO08MhmfmLCqbVana1FObYmlrkfkXDlvY9WGdVtzOu/e2XIh1XP5jiXJO8ncUWPkpmbh9bmiqDgXc4sIPzy7LX7xe6ePnX1wh1iL8FA0FBmvu9+y5PU2zbzBv9pBxkobKHL/ta1giQ+qK6dGhZ5P2PVxbt7Hu9OOz4oKrgjb3Du3tshzXOa0EP3vgL6+2e7uN9+sOR5NM5bhd2G4CUm5QRkMxnI2NvwOC2Nzdj8cB+NEQJEFYMhcaQ7/HHjQEu/AU3Dz49Y/uHjvs/kHJwgiAX1x4D0sFs0icaJL2qe8uP9TPNwrvXSe9kd+aHBR7jRtssFLNHA2AThCrzsWfNEB/dcrkgbXEMt9ePYX9KIUVwMXpZu12eM3zCqDi1JZucjnv1+V4EyoilTw4569JIi5bfRMqANyswTNpHVKGlPq8+yLOtzUHspIN7dIpYfabfsktbu7etKkue7uczmMWkkb/pMnnDG7jXjAIvZ3GtQy5oN+VPfGMWEJUvm+tuSghJCwhISwkIQJs9DspECnWRNJDap1iw1OxC8lBgelpAS5zXChEnagp7yEjxdLuGqOw2ZAOQyUYXw8yFyL6YxO0gZjAuMaMBzS3+MNtbjh5qrQq9CSdWaUhtJYJeWvOFq0j7ARue9UR2qcJcM7Oy3D1UmVroKtzmPpEV+59XLnOQtdVV6aMeQ2tIN0J5a3zU3x5/8JHVZ0jA7yGn4469U26cfkN344RwRTrknoFWL7qHYNczgeJIMeKTp4+OznvAYP0f1BV9wXjuO3Re1wjlbcDDq1EUn5raLHkNPlMJ/pT8l0aT/oGVVO9POb6Orvj7Lc/Pzc3P39RVIfN3dfX3c3n7++YeePRbb4TfEw9jc/g+yBY1QhISrv4GDxsIE/ZABJrMUc3yh+T5BwLXDS72G9ASecCZOE/XRguGTitKW5LfMdJ9kE2yWSipyFSQvnmY2Is3Kj5/1Q6MTvi9XsvHJegZ1OlBWK1WNIoYy+vcPfxQ9FpQNvR16tLxOV2pMCeMuj0cLnfIPEgdXMNvoZkkGS2w8+RfTJgjU1oANX94AAdGGivz9ViMTBkfRaCP5urgEBrm7+f33T8xl2Blvt4Lj/A+xlbMkAAQAAAAUAg3o9v/hfDzz1AAMH0AAAAADbCS13AAAAAN1Vrr7yK/wYCVAJYAAAAAYAAgAAAAAAAHjaY2BkYGDf87eGgYEz4ZP2tw2cAUARVDAbAJNYBl8AeNpNzwFHQ1EYBuBdBiQKQSkgCkwSoJIgIiMiDAEQgUAlQJTMdlWGAO0mWgsahknCxMZgmAliP2JSD+64eLyO8533c9LVVJZF3hkS0aJAh1UicgzokmWNDHkahDTT1WBCRrFarDDaEd8vMiSf6G7RYSmxs0SOiAFFsmSYYo0Zcuj8++CIW14YoxJ3Z/hhK7Hzhl+uWabJtjezaUmOLuesssF5nMe8sccFZfoUCTnjmQNeWeeTkHHqfBGyQ4tNDtllhbOEVkLICseUKdJjnga1hJArhlRY55R7SuwzyQl1aomOJguYCS6JuCPiicf4b2aDh5FUKviWM/SZdr6UvaAdzAXtf9Y0xqwAAAAAUABsAK0AxgDeAPYBGAExAVwBfgGwAdcB/wISAjECSAJeAooCtgLrAvwDHAMvA2EDkwObA6MDqwOzA8oD0gPaA+IEGwQjBCsEQQRJBFEEbAR0BHwEhASiBKoEsgTtBPUFHgVXBWMFbwV7BYcFkwWfBasFtgXBBdQF9QX9BjYGbAaMBqsGzQcBByoHNgdBB3kHgQezB7sH7Af5CAYISgiTCL4JCglJCYgJtgnxChEKPgpqCnIKkgrlCu0LHAtOC4kLwQvuDBcMWAyIDLsNAQ0MDRcNIg0tDTgNQw1ODVkNZA1vDXoNlw23DeMOEQ4eDisOXg6eDsgO/Q8zD4cP2hAXEF8QtRDyETwRahFyEXoRghGqEeQR7BIIEjUSPhJGEk4SgRKJEpESmxKqErIS2BLvEvgTExMiEzETXxNnAAB42mNgZGBgmMfExpDAUMHABeYhADMDCwAlBwGSeNqUkMVZhDEQQB/uXHHIDXd354Lrdd3ldxwKoJatgQKogG6QfIPrRl8yPkAl1xRRUFwB5EC4gFZywoXUcidcxAL3wsX0FdQLl9BYsCZcSleBX7iWkYIbNBdAdcGtsPbJMgYmZ9gkiBHHRTHEAIOM0MsT6a04IE4ExRoJbAIobRnWfzvYGCSfOKTtF/FwiWNg46Do0H5dTBym6KefGAmt4RGkjxAGGfpxMcjikOKMfiTSa5zOb2NvvOa9R+SJPNIEsBmljwGd/TTLHLDC0hN99vlm3fvJ/vdY6pP2ERFsHBK6AvUWPY+I0iPpkEMImwQmLg592neaPgxsYvSzzRobPC6cIRVmHgCRt1ftAHjaY2BmAIP/cxiMgBQjAxoAACqUAdIAAA==) - format('woff'); - unicode-range: U+0370-03FF; -} -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAACF0AA8AAAAANPgAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAALcAAAEeENMPgUdQT1MAAAIQAAAAIAAAACBEdkx1R1NVQgAAAjAAAACqAAAA7qtPmPVPUy8yAAAC3AAAAFoAAABgbptl81NUQVQAAAM4AAAAKgAAAC55kWzdY21hcAAAA2QAAAE6AAABwMYS7sJnYXNwAAAEoAAAAAgAAAAIAAAAEGdseWYAAASoAAAYlQAAJ2AKUboxaGVhZAAAHUAAAAA2AAAANhL1JvtoaGVhAAAdeAAAAB8AAAAkAzn+V2htdHgAAB2YAAAA4QAAA2DBYoWjbG9jYQAAHnwAAAG3AAABzmtRYgJtYXhwAAAgNAAAABwAAAAgAVQCg25hbWUAACBQAAABCwAAAkgzWFNlcG9zdAAAIVwAAAAWAAAAIP+fADN42mJgZGBi4GMAA0Y+IFsLiFmAomyAhuVBtwIAisFwz4LZthHMtm0rmG3btm3bjvZot/nTLywTqECdakGb6sKQGsOMWjKBDRyoExO4MOHbjXrAm/rCnwYyQTBCaTiiaRwSaTIyaBZyaT4KaTFKaTkqaTUT1KKBNqGZtqKTdqOPDmCQDjPBKCbpNGboHJboCtbpFnboHhMc4Iie4IJe4Zbe44W+4ZN+44f+4Z8KlABoAJwACngyH1YAAAEAAAAKABwAHgABREZMVAAIAAQAAAAA//8AAAAAAAB42k3KgUZDUQCA4e9sV64QyBBywRDYGyQlpTtLAuLUTGo6FhPcPUV6giTUK0S1N9s4Lgb/j/8XsC15s3VyWl/rT5p5Eh/m909iGr/MDBbT2aO4aJpGVMBqBbrDUV3pXdYXlf2r0bDSzy3QOrTuyH96niS7mXuZFQK0TxB0lUoHAoJSx47CsXOfvgWFI2c+fG0cPaXo1p2xX3/+LXMpDRy6MfXq3c8aobUpZQAAeNpjYGHZyTiBgZWBgeULyyQGBoZJEJppNYMRUwWQ5ubgZAVSDCwLGBh4gPJcDFDgHOLixHCAkUFRmH3P3xoGBo4S5hcJDAzz718HmiXLmghUosDACgD45RBUAAB42mNgBEIOIGZgEAGTMgxM5ekZJSAmAxMDM4hkZGKcAKT2MDAAADlQA1MAAHjaNcrDopVhAADA+f5sW0fZtm27Ntm2bdu2beM1wivUMlzfWQ8i5EFZeQSUlTfcQUxMXkKTMDSsC4dCWlQlal19a/Vz1X/HYrH7sVext/EyaWkEoVkYkTH+RhUzxoaM8StrvMwdkNYE/g/k5zV+XP9Rmh8Fvj8WxGzwjlAylCdUJiQgxAB5TBGZLK+pCpqpsNmKmKOQWYqbp4T5ylqilIXKWKycpUpbpKIVKliuslUqWamatapaI2WzhI1i1kvaJK6GDWrZqo7tdqhnlwb2qG+3hvZqZJ8mDmjmsKYOOai5I1o7oaVjWjmuvTM6OqeDszq7oJvLurqki4v6uKG363q5ZogHBrqrv9sGu2+AOwa5Z7jHRntujPFemeiNCV7Lb7q2Tunuir5uGumpYR4Z4YmxXvjqczrSAlY6AAAAAQAB//8AD3jajZkHXBTXt8fvnbITMQILLGtA1HWFVZG6LEtbsKHSmxSpwR5BkWoPNppUxfq3K0Y0kX/sPfGlYu81XdPtaSqwwztzZxkgL+V9lPadO+f8zr3nnlsWMSi6fR3zOvsJohGHBiEvhOJUcpWjXCXHNjL1ACedzttb5+WkHiDjyJ9e3t5aT1tbhY2Mo72EXxWkWTRj2fqUbmg7ixv7W1n3yw51C+vnZmfR09bOkKBJyNSMnzxnUN++g4Qv9pOXV6ex6S3bKcbWzs62URYc5R/Vs6fM3tpebTn8jYA3Ciz4P4Sm/ZydEYUGI8SUsZmgzgyh4SpajbVYjVU0PdH41cy38ekv8enDxs3403s4g9/GZrZswU+or9vbxfdkv8ucEEYIydBXPJLoEYnew4TyOsGHiXLoBraCn1T7j9D6ffBtgaxMvlWcylqlIF+ggarn35i4D6+inir4wVNwAb9rKk7kHfgIHFYvyqnmXar516rxM+qH9nbRHmcDflji5zO0CH5iVNz+E5PDzkYO4MXTVsk5Cf0tU9jY2mo9vfVKGfTwQErnZTWQOl92ODZz+Iqo3NOFOe8VFqzWJwedrd/FP9u8DfdiZ48akat3y3p+7cKLmaNd8gzjG7Dhhx9xwHaIUfRBfHMm3xWok8sl/iVa2oU7SPyLrlzWIvE7aJnQV2gXxBYDffUqsoMovFwptVqu9Qyk9DbmtBpSCpLGil4XvqB+zPaG0Pp5IcdC3ty2L57/CDvN/e7YDOrIwdvZA1uPus298/Y7v25OVLOZ3iv43xBNRmwS2KWRJeoLlhUqHfvX1qkdxlJ6ieghbOWfPdBsaWnkXzuBqIh60guvkrz48iugHb5lMtSLjFMr/G0PWnqCDjmkgPjF4d2Y5ykqr+1r2tyGuca71/LKSjazBiyQN0gWWopZOAh1UE4u0S+HSFTWItE7zp30iETviZTXCUoIJRmLSojCFBgdHWSSGqHgAU5CzpD5KqaUOdWRUnKVRiWXyaj8Hc+WZey4lFO2P+aNoMqEsKqc4XE75oxdbOCfKfDltKvKzTjg8X5stj8pInSGv4/f0ttbP20pHNAfN9QZZ3mOBiWiRxKhrRihn0Q5B4l+EUCo8SNBnUSbDZ0WWiR6xwCRkBHpIfZ1JlQjGG65Cr7oVOOLvXupV/ZS1cZ8NtN4nBrdskXIPwbav0PaWwijo5beYSFjmJ5Nxj+amigzHNWaJBQJ09snqVH3SkpM49+D6LUX9ZLevIgQfc803uJo6+C7jr7HX8SebQ+xJ3+RzaxsPVRZyYRVQnsl/5QZDO0hjuBASicIhle0cjW8ZiOTMRwuOXcnhlduNX7f3MxY+da2o+Yam/KvV9ORre/V1jIj6tqUhbf3z7YCRcQ36de+Uv3qoC0SvYM76RGJ3hMprxPUS/RGdWfb5xL9BguRrmj/if4GlFsLfWdjTkFJ1+hJruiEgL9xyTpcPvnD2IjkVYa6Dfw0NrNtWsLbleOGGfJ9NEe30UjIdbDBUKQPHcU+nCiMy1Xo2dVk/vaAkYQhscZajNW4eO9eM6pvs/F7athtGIk3qSXGCqOtoPAqZMlqoltD7NxyAYXYAux4gB0WrAjjymGLJqrAhs1s9dtA6pLwnNS3wWJ9a1cg4Kb38kxchm76tgsUfIA1id4KktpKlENn8Xjj6xBDDHDXjhjiNFiJiYL1Y6l3w4zvN1GFNvhKLn57VttSUU5n9lqBWtyXVgi5iF0pnZDBtrw95nrItj3Aj/CrZtuYE8qs+oZoYyS8O8xhw+fzqX2Q0VJOChG5EY2f0Z1ULtEvjYRCPOBPorfEmswnEhUWaACMa+eQ6rSwatN/0kX9EJkzcIR6hNZ/+N4t47pr5BPd7PMVdiERJfPXrcG7/1oyhdIgA+LY2eDPHvzZUDK1qQZBCbLiLCGrKLmlldbTionLvde4635u7v1djfdyD69talq7cXfTWuq/l/n3D+3DgTeu4BFH9vOnb2JrPJC/yz+Cf99gFUQq+iDzwss0LyTKFUn085TOtkckCvMC0UAHAh1NVA4GnaBN0UWro5LjMMdp9Hqs50AwKZlWci8nJypp1zf5gnD4fh9PWxvlwZ8yH70mygMH2hbvXTuqblbTmhE17GxBeNdALmn45Natad9rWjOZ8JkLIJ7HF57PwP2x9cUXs0SdoIiMtI840qwweudgpOfD6JkjpdCbMhmH1VgtVDZPhvNyIiugN6Mdvy4Dr7vMlx9vwhPaMXd83dbm5lUN9FdT/zNJadxERRn3sZkfvl+Sz6O54Eu0Snz5dfiSqFyiXyJCIatAgURvGYVakQi96gGj7CKqkkoF2Sg6aVwpsknsvo9R9qUYj6Kvt639PXHq2OMLx61M9lpWVP7pjLwzS2uvJUwJ3ZMUtjBs2LqlWUdm4YVFR6amjisYGaXPTRyZHqIeNHnVjKlbU2LCc0f4u4wP9k8Yo+mXRmYIUUJiCRRjseykcol+2ZNQXi2oluj9l51tHST6hdgW4u7a9tZLIe769t9gl7gUOYm7NAWGbXC3+CF8jQ6ToIWJ5eVNBdc8y+bX3/luxgeLwuYM0alifBasvHETTw3Znr6kdtc9dmmUfyY/77UP9hcfyLBTFPWSl5asWP5qAa5VDa1Y1TaUvvHpZ4LnaBidDLIHFlc2nYqj3t7LxzIWVsz5Vi/m/OrViJJa0cJ6FadTKbCp7UvqOP9CbE6dLCujLMVXIFLxHdJXwWJf8YTyasGSRO9bEmr8qBu9xZtWDqaftHKQ7nASyomNuHgw/XIvVNacy36nvrSsHpaNtMrrRbOvL6d3tCVu2rhxE70bLIs2yJwONc1piXJFEoU5LbU9ItF7mFBeJ6iQ6I3znRbSJfo17rTwXKTSCgiVndlF9q9oOK2m4b/W2hr+M7uufrt5y08fNNXvvLFpp7B3YCxan0HhS2eoVp4he2vyLsnDGGlOdVAHiX6BJCq7KdHbuLOtvUTvEk1uQBeDplfEcRcWTi317ru822k8A+cepKyNjyg5DXWY2g82SGviL0H0x6EOSvyJ9PYrEuXsJXoXXGBUC1QF/kDNZDjp6LBKyKJI6oqirYS6bZxFh65ZU80MWwWrvdiWxJwsxjwESVQu0S8dJSprkegdp84ThqN0kvgONaPOFc5RWsu+GyHNVEIDRRotWSY0WaTThcpZAW3ljBb1Q0MgEhtSiTQy0/lVqzWdZzWkSimwsB+Gv6FM0SeGDB08aorSd8/UzYf5pxtKiryqYodm7on4+GM+IrLGdV1T7eTvg/zMi3oEjw4J21+/oykpL+M1h+KBfY9sMi6PGo0t5kyeMBl0iQpkCtA1gei6/FSibLNEr4mU7yuoFSnZy3/c/hOi23+D1qcgCheovsOFmgPLFKfqcib825iU3t6YRETaOjlheKJycqInH2xgjN+bT5/uP94zMmBZwvR6fdDSSZVv3b2WnJGoSx7uOrJyWP48h34l/ItxdTNjRo6c6NHTHE8en9ILz6OjGC3/8Klec6BxsFO+m1/6hDcS99c3/DchJxN6oN/AjOiYdOPdwsxJ0zJSdQX4ztqTb+2F6MQoZH4Q3RQS83m5kGlHgPaA2PrA+EjhOHVbOMi6Qe2MqvCLDf4gbdMXBYVfbJ68LzR2ZNno8ndjqud5DZrpP6rs952bW+sMhllubuevVO2LA4+ibdlg8DhN9Jj0RKJ2Er30l/RiJ2VbJHo26QmiUDnskX9g7yIr1B9GQylXa/6kmkgWz1fQ2UGN9Zb+6xMr9idMOLYkZbnu8bIav9zY5OIhzvPYu4oW/8pxkcuf79j8sjbI0PPilfKjqVOGUebDxggRRIH/c+xdxgnN+ETIiJsUiyYiGlUDrwAFLOpNViE4Xah0jv+q5OEm/gS/Gyc2rrL0W5+4fJ8gKLlS92Rpjd+suPHFzs7zWY/S0t3/oAmi3wS+FTBidkgFnvtSnVnY7VLIlGo4gh23PCZmaXBU6KmJ62/n5l2sKjk9laL45MJNPSlHugZfm7chxN0tx28EONz6ombhD1vt3azwzbeadr8NPUC8kfkzS5w/CiRRZ4le6kLNJHq2k7LNEr2mEPZ+m3gdiUKB3JEeck9hTplmCdcxl7zxvwVH95063ckjsL/e0aqvryZvSfJ+/sC/hNuvn0vkGLWLluNKZa/kxY0tisPNf98BQn8v5ZOYeKYaGVAI9LcgpnO7ISNTW1TFEJFaG2kHphbD0JukB1JsRyWAh4zKa+S68Smp6fsW6saoevcLiHlv+u5M/uXTxg/i1rm/WVRQP6Z8ysnyxf6+KQnT31tQ8tZsPr147oJFswoLmerNCrMhJcnTtqeamVn69HXyDF8Uu+Gt4OosQ7RGE+EbFj4nUvu6o3vN5Kyd6Vgx6FjF9KzlSwpmz4fREKMh41kkjuevndRZohe70PEmaoGame2Mw+nOJ2ZS+7O/CrXkDAzsT+wNZCOskmSwyO6L7D05YdnMDTyU9p+axqT0gOyEPo3sDePRuLiGlUaaepmR6B09xIjZD4Ue15jssOQGS5haWv1f2aM+5Jv4w9sbu1uFGdTwF4ZBNdHHLQHV8037gEmg+hlCDMc4oB7gS7pZoL7Eg9t+xsH8x4xD27SSEtq6BOIW25Lee1PsPVrI5Uw+iW6VmSFbON25mnZfnCaQ7nrvgMULWpIRqi6/0z8t/7Hac2xVQTA/933jtyf2YZkuOFinHzmSGuM9apQ3/AIKolecX+661H5Uyvw42rftJ9CjXIwfjfLQBgdrPUZ1/JQUss2Swms0obwOdJuZqBM6S5O92YnOmDjpjau0MJbvQ0zzoFd6ifEwEA9FbiDmbeav3+iz8WkZHwrCqt59VDdwid20Q9VUC+kheI9xIpm0jKyhF1EZOQFfBy95QsUk/YyxugcFI8j4806U/AtjC77K2zcyDryT8RQVhL/Ep1qc2I8Fe9eNHwnvgb1S8aaqp2DtDFibCuokaxirBHPu/ABK8SWYuyaaUxtPUzr8Y+t9aIvRHFg3noBZOYmpy/ItBEZNzIxwT3B2cS6OrmriT7EftwZFDreRz1eoNlQwWhIbeZ+7B1oqSGzn24/jxg7O3pT4TYh6osCNHwn+CCfa55qsMJ9LFO42qJ7GqYiS1LHklAmHX1aD/49KfAKnjmnlr4zBRd3kUi23Z/zn+Ax6THfV0qwklRbly7XKLvPINJHO1PYa9j8pG6obe4dHB86I78M4rIxJJLNncXaJwTtmsBGjjtlD9g+14mpOxhUDbWW/QuZoIEJxJLE5Ti3WPOu/dFfsGmSjip0UYGM3srzu1eGnUzbUNPaOiDbMjO/DfmVw7R0YvPeRlau9W0CL6h+VOEtKLiFCobchTok2UyR6PoVE7yDsP8E9SWNJi1pSSP80qmJaUHDKUGVELKkj0CnvQ1nxXf1uluu8/mOK86k40ECKiUkWRF8PY+kA1sV7FnFxkhYrZZdyTyWvPjN52plVq85OnXZuVXllRXl5RTmjLftj17YX1eXPd+54UVlx5vrls2evXj0DsRC7pM6sFusMQhItk+iFKImyzRK9hoSaVM+3Au0j3a38SZujkubgn8Zab62XNimCUFBa15wFSmvPZk87h0dUj3dps4+sSvUwWqaXVRrmjS8vN8zpLvynwfzvIW2XZ/ItQ3DvdNp9XNGZa6sORZ+5uuZgNOgjSkjerO/MG0El48h4IaWw88wXr2aVXTedHJROa51eS19raMAD+xmaaocGD/RQeavnNnndrJGv6L2Ytl/8cklNL7M1PXq808SPWEwd+66Y3wgeiW3icYPo0YAk6izRSyI1fiToMFEONbfnw08s9Cr9AEbWmeyL//I+xXSd0uXqgXKbW63OnjVj2/jJB2cXnxoRGlA3ZcE07bysqesTFp3LrT0z6vXAbQUp4e6jffrYj8lLGb84eKRH3mBdhMHV4OFgH75gwqzKoDj/HG0QKCMKSBRbxCgskESdJXpJpLxaUCvR6y//qu1Fsa3xo25tm8mdyhbIol5sf6SEeE3VRq3T6vRyOH6aqhDTy/s/oXuO/vJLI8624RvTsv0nOesGDtpfRRUseWLDG5cYa5JS+9jC6ErWWOTQsYLjv7FK1/Nv8Qs+pxb8X+PU6cWLjYV/4QGiED38AlHsNNXc3ahY4Lxa8Czx60I1EDiMc1feDJzUB+EsAauDdeeaIIdk1JjU4tyElMQNzo215oGH09avZRyMttNSJ46iudb7NdHxO+opHmwTG2S27pFmq0gfysokSmar2JZtlug1sS2vE1QQKp48P0JIspwjtb7ShXISvUoiUUN+V0MkcG+S2eXaREvfeFy+6sfT75Q2frqltIFm22A6toXRbm1X6ENgTXyP5Nm+jvkpUWeJXuyk7A8SPdOlraNEzxE98/nxjA70WAgrtDklVF69Wrg5YXR8jWPuoUq7GW+G9PHh6w5iVzyEcWj9PGt/oXmpVWhBDAicSG8Cy8QGUXFYUtFBHSUq+ruAEP0d+Ot+Z7KBCrVt46mxxu+pb2tri+lXVy4BC6QtifmYGLMCSdRZope6UDOJniVUPJn+YTqZcuhbOOc8kdYmTlqFvg2WZiKhW0Q6TrJM6DGRJgNAbXwuvY/cHvYXejZO6DK56RP+7pec4v0mraLbsO1yrDA2VC4sK9PnJvlP6E/bJnjHBI0dEa3T4+xDVCJt1vZHmx01rmHPge0pG9NcPXO1vnOLluUsWGQ8wwRSfgijW7BS3mLvklNlZ41TqDi13EYcPnHyQg2k7oVmB/l4pg1ODMG04vHAkMLYgOBk58bG0Dr2rp3DfKU8InLdsrbDRVuzIwfOUY0tzqezlq1KLIkQ4is23Y72QnKkED9Dgmhgk2NOqbEGK1n4wqqm4gkrcoYuHVR2ZS0/xY1a42nM9qLWecJ1n949d6Iud1s8zpqOvbPtc7A2GzHE6mTTp47WqK9gF27nSY+p5Y5CJsCXpuNuXK3Gttj/OXaoeLqhhj9JNRhTcYLV5tdXx4+rT2tgMy/d2f5REs8+LizEvZYtW+ZdNj/rTT1iyI3YYPBig3qDjwHC7S6YFC3qteJiwNEmbyo1jdX41FerNo9cWfS57dmWpMKAZw+f0tltq+hs3sPSAq+/wpdTbtUL1qbP8VuS1DN2SfyZD+1wHXh1zysw5hu3UmFCZu+F7PkURsaJfJas60gGc8qC0uhhWLxIHkhbRepQ1Z7d6xZU+s09uXhC6Yi76w9EvBE7YkK4W4Kzq3OxckMF3f/K5ytmZex/+52UEW8kNM3/+NSsZWs3td027RzB4yGyqwuRPl8X76/l1G4cyzdt55twLBvCN9e0LaSX1mAf0IjvGz+izsHaaQ4au+8CqQyXIHPLSVP8rHsHVRtc7TzUN3+2dLN3NSAK27Nyup79AfwIe16IrSPPVV1+xxXugYHuLkFBOMc1MNDVLSiIlQe4uhkMbq4BHT9BwResA3VFZkY0dzlgUQn6UaP03iNHysykcxK0zmU+pwNkjogW9tp6lmb57GQBHq99CE9ns4iOkPmRp5CQVHskn+4l86vbk4xAtTXzG71JVgZPOXhuraT18IWtN6z+4O67K2+zQ3HKaP6oFqdE8MfBlhXzM71F5oxk0FbjqGU5DZ4QjS1yca/wl8zPcY8fxx3q3go8qh31SjounP81l38W/ULmPO7Ro3GHoZUL85BeLFMgC9JbpkpApg4Vl/zm6FcKFImjQ1IVBa+ELGIexi802IWlpYXZGRbGg+p5zE3aW5bz/9irJg2f5Os7afiwyb6+k4d5+Pt7aH19ZTn6ND+fNG/vNB+/NH2qQedlMHjpDKDJgnWkt8k4pBA1dV5+Svl4QRcxwnGAe+8s9fQQn7Bhjn097KdrsllHdw83V+8xme7uzi7ecTHCqISyY+lJbDPpd0g4ehKUbTt27CLhWQGvpn2hJtrCMyh9eq3izx/7ULvTYqzyJyaMyhkeMFPj3SdUpRvJ/+Dd//7KVyYGjEh0tlNmWsgdBVv1vI5WI4OgebLyL26e6B52U7OcPDtvliJ3GgzdLo5Gz34d7LTRRuoTNl/ME1pDuazPymDzrfiN5lDfO+YEIxPv07GdDNErZTcZDgl7/CdAPpe9Sl2WtQA5KxCwmMP+QAdy9sQiyzniCzhXy0/i7O8mN8DTLHg6krOR8vJ5OB/vwtnUbUoW7Fux9+mNXBFYuyBaA/KM3sI5IBmxpuE0jtRK3CvU2BqGLTiHW/Fbt8bfQqTdd9BO3jX74kNJ9oW1cvL4W7fit0ErN/YRvVT2+19lX0L44lgh+8aMTofsi1/KPgrIGvuaf2io/2tjswJA21z2Y1rHpYO2K6bYLWQ29FbZcyBXTSREpqcnyo4AuWYipjGXwY4WCTr3MotpSsaJ8WMNVbyU5+NkXCJ/RSs8Zf9LQ59JTxcv41vjOMcE/muv/wW3XUYGAAAAAAEAAAAFAIO0QZ2aXw889QADB9AAAAAA2wktdwAAAADdVa6+8iv8GAlQCWAAAAAGAAIAAAAAAAB42mNgZGBg3/O3hoGBM+GT9rcNnAFAEVRwCgCThwaOAHjafNIBBwJBEIbh/TgIRCEKEBLS/wgqEBICEBJRCiEoJDkACXAgggQIwEmhIigQBBABRQ03S63ZrMdrWKw1zkIVSPrX+xZQPYHH93SfFmWBRxzujsS4pgnbBxCm9oJqqkg8QcViYyhZuKQgmPwREmQNY4P+yxLPw1/vR0CtBAOSJyMytegLfJLi3lmVq63ZkfmkbeEzcDXX4mBwLWYC/4+koPtla1jpd/L8Iidjx+dkqRSuzgIJXNBAC1FE6GTQQRg5NOHihSviOKOO2mdAGRDUZ6wEynoCZdcyrgUAqEsMUwAAAHjaBcEDtCAhAADAsNUid7Zt27Zt27ZtPp5t27Zt2/b9GQBANdAJ9AUjwBSwDRwCXyCAHMaDqWA1OBJOgXPgergLHoUX4G34HCVDGVEeVBxVQq3QSDQFLUNn0HX0CL1FPzDGqXE2XB7Xwq1wNzwQj8Ez8Gp8Ft/Aj/E7L41Xz2vpdfH6e4e8s94Pgokk8UkT0p70IkPJBDKbXCJPyX8a0tg0GS1BK9N6tCXtQvvTUXQRXUt30MP0HH1KP9DfjLJELC3LwQqz8qwWa8o6sNVsGzvIzvrZ/IJ+e7+XP9Sf4M/2T/nXglhBxaBO0DzoFPQNzoQ5wyJh+bBO2DwcHW4M94SXwrtRyihLVCgqG7WMukYToznRxuhidDd6GX3hgGfi1XhDPpsv4Kv5LUGFEYlEWtFJ9BVLxQaxWxyXvnQyiUwvc8miso2cKxfL9XK3vCtfyM/ynwpVbJVMFVJlVQ3VWLVTE9RstUBtUwfVGXVdPVbv1E/t6WK6l56vLxlhypimZoBZYLabY+aqeWP+W2uz2UZ2hJ1mt9lb9qX9aH857KxL7jK4Iq666+r6ueFugpvhFroNMdkFeqsAeNpjYGRgYHjGxMaQwFDBwAXmIQAzAwsALJ8B2njalJDFWYQxEEAf7lxxyA13d+eC63Xd5XccCqCWrYECqIBukHyD60ZfMj5AJdcUUVBcAeRAuIBWcsKF1HInXMQC98LF9BXUC5fQWLAmXEpXgV+4lpGCGzQXQHXBrbD2yTIGJmfYJIgRx0UxxACDjNDLE+mtOCBOBMUaCWwCKG0Z1n872Bgknzik7RfxcIljYOOg6NB+XUwcpuinnxgJreERpI8QBhn6cTHI4pDijH4k0muczm9jb7zmvUfkiTzSBLAZpY8Bnf00yxywwtITffb5Zt37yf73WOqT9hERbBwSugL1Fj2PiNIj6ZBDCJsEJi4Ofdp3mj4MbGL0s80aGzwunCEVZh4AkbdX7QB42mNgZgCD/3MYjIAUIwMaAAAqlAHSAAA=) - format('woff'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, - U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} -@font-face { - font-family: Fira Code; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(data:font/woff;base64,d09GRgABAAAAAGmoAA8AAAAAw9QAAQABAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAABWAAAAD4AAABSBboFKkdQT1MAAAGYAAAAIAAAACBEdkx1R1NVQgAAAbgAAB2lAABDmkK5r6FPUy8yAAAfYAAAAFsAAABgbi0j31NUQVQAAB+8AAAAKgAAAC55kWzdY21hcAAAH+gAAAG8AAACfnQbS85nYXNwAAAhpAAAAAgAAAAIAAAAEGdseWYAACGsAABAtQAAb2ymrer7aGVhZAAAYmQAAAA2AAAANhL1JvtoaGVhAABinAAAACAAAAAkAzn+tmhtdHgAAGK8AAACZwAABdbECm3rbG9jYQAAZSQAAANBAAADhkisLKVtYXhwAABoaAAAABwAAAAgAjACg25hbWUAAGiEAAABCwAAAkgzWFNlcG9zdAAAaZAAAAAWAAAAIP+fADN42gXBgQWAQBgG0Pf9IKQ5bo4gLZKQFkhyG92IvSfKAliVSWxid4jTJW6PeH2i6yotTTIyRBRmzMIPDl0G6QAAAAEAAAAKABwAHgABREZMVAAIAAQAAAAA//8AAAAAAAB42lzJA5QgMRRE0Zc21rZt27Zt27Zt27Zt27ZtW9kcTgc3qfoIwOOLVgGrUJFSlbjRsHuHVtxo2qFxS260qt+pDUl6NG/TjBs9unfvzg224eQvUjIemfLXKByPQgXzV4pHpYIVpI1K5q8Rj07lSsnpoEqyZ1KlCvK/CP7+xQQEGjp+iGwEshnIViDbgewEshvIHj4GqM4A1fmEali/VSdKNGrTtrWI0qRD/YYiVqu2DVuJJMpUygzKbMo8ykLKEspybTq37iCqAI0IT0SiEpM4xCchiUlOatKTiazkIDf5KEQxSlKWClSmOrWoQz0a0IgmNKMlbehAF3rQh/4MZAjDGMEoxjKeiUxmKtOZyWzmsYBFLGU5q1jDOjayma1sZye72ct+DnKYoxznJKc5y3kucYVr3OQ2d3nAI57wnFe84R0f+cI3fvBbOMITkURUEUPEFvFEIkAgAB0NHUPlcEpfGUoZVukqPaWtdJSIFFoVbYB2QrumPdETyX1K7Vzy1tAn6Kvke88wjE7GMDOG+8P9YaYy96j3nFXJ/WE1sV5If9ll7Gb2DvuSU+j/zKngXPHmeHOcR24zv5Rfyu3ivnJ/eI43Trar/H8MjwOs3mAUQGf+NmsbQ9u8YrZthLNtBrNtBLO9YLZt2/a+XN/oHAf8WvuKEbd9mG9m+qJvtb8guz673l/b/x0+Dh8PlAhMBn1p8CxWBCsSvB2aihUJLQ87eM1wy/B74jZxO/w30jN9MTI68j4aiDaP9o/uj96MYTEvtjl2Nl413jl+Uawef5xoKlZP9EzcFauD+TrZVpouTU92Td7UMlom+TzVPtUdxOjU9dTT1M90y3Tf9OH0xfT9jJFpnFmdOZhNZJnsUsC1N+fLUbmVue35VF7Lz81vhhDIglZDB+EErMB7AfFVpCnSEzmK3Ec/A+IQthTbjVt4Tbw5fhp/ShhEY+IsoH5JVibbkhvJ4xRCWdRl6ilt0LXpxfROphSDMUOZ2cxrtgTbku3LHmbvcgpXm1vM7eRL8Rg/lJ/Nv+Z/CgGhozBUOC08FQ3g1FRcLx6UQhInjQVmS+WMXE6eLK+V/yo+BVEGKxOVhWpI5dTh6lzNB5wZbTOIszqia/p6/Wg5A0Rd46zx24yZglnV7GqONuea682z5m1Lsurane3B9lR7s/3aPmxft187hRzI6Q1ivHMVxEu3AERD9yyIh570v5SzAY8qO+v4+547CZCEEIYwhGw2hJANw2was2GYHULEwGaRRoyAiBgpphQRIyIiRdxSRJ40pXSLETEiRkoRY8R0l+KWImKkkW4pIg8PIiLy8FC60oh0i4iUIg/1f9/z3jv3MvF77/Oemfs77zn/93zOnTNhmxqbWppWNT2bVzKvel5yXpJY55ihxZiB+7EqDmBd9GJlHKTPYnV8jot4PHfyJ7gr4FsF3z1YS91YTXuxnvZhRfVgTd2mb/CP8XL+cdmBOukzRFg/71Ie1/ErVMBJTlKhXw/PuvS9b2fuXmmlYsolkt2lkhzQKGy+5BN2HsbV5/OE8lz4M+2BOmXqotzvPRK+nz6X4SAFKD+HPsZniPFuGn2Y/8TXLAfBu9RZihMjdUuNtYyaERsjdVmhRPInFPHUUnvsK8hPksnkqFn/FyW/XPIDcWq7lmTKQAnR4HL9V+H9h4iR/gN93Y0U/kXonST2vpWIjWcXiJnGy7OriCRaTj8hp/HM7OjsqBCTPp1uhxdpT0TdculFxI0H8HpPmS15BjV1pa8p8/tt9n5y+Bf4NV7mxgCLUjU10GLstdvc2hoXuQbVRY2L0gdtHCBpijSmG9Pp3endwpx0vXtBZ4vGUizxlaXL4F0I3u5RvM8lnvOYzJzH6RahE0EJ7DY5c27PuZ1OCo1lojRzyfCH/rMYX73tGsr2u5eNEeQiRebss5eN8dU9uOqhs0NjLHFjfHXrq2VgHdZAJ0udbozLEOMypC4t1Vq3Qmeue2kNmRgxX9GPG/wYqyglY7nRrW9OxDXUF3l1uRdhwwNyGh682vxqM5FoloLdItNwC1G6xKRupG6AV2i8Za5X6hy8ToEWWKZ19aFcX+qxsBczUXEEtoqXjRxVqt81lNzQsMGLKtWDqFa6l086QVoaWlK9GtWCWXehmNaopoDxrKsgVdbAKrRkC+ouaihSv8xqvS599fMSVQTrqJxqqUlm/Q1rqVpPffYFKJanyolE5zzyClW5Uj2Ogj9VktHIg8ZPoeWM11m8JFtr1lFrszd6WrMOYEW0z25XLYO8xapVpR5bweYqCWmhPetFKwWtkdazcQ314/LX832snPvuJcQk7yXvgd5UzWq3XPIayHlrYNO15AmsrhNIXRb3IgE/QPkjj3XyimvQuIJU9ZND5CSH3EsIm3Vgx+BzDKmNqCZZA3ZQI0pITSWw3dbAXta6tsB7C1KX1WQiSrbRzP8kooRrKJVA6kVUgohK3MsnuSC5yVy+aiOauX4m+nnmQ42oFoxnroDdsgb2fbbkzAvwvoDUZXVeRODHaJ4fUSXV03xaSmtkBa7yzdtFWrFDtCKV/okfApkr5uXXIr823k0kcdSAlGtk9epR4JqQmZkYUg8oL3D3HjkS0SgqRh8lqZmWIaItUmeZb6TtKkC7CpCKJr1DXP9UTO6nu+/vial//Q0y9Temyz3u2mAXNMZZ6nHKNSGpTFT1h6g+cLeXxoZibKVVtIF2SJ3tvnmai6G5GKl330QGVuS+B/kiJ7hOom1FXrWY5xmDZ2z6XBvtK9tBcjXaNAiBPXRNyGwvPpDr1BS4uxCINk6NGOF1tJ32SZ3HxZzEg5lFMxGR1nqQIomb9U/dS5ip6pzWAr4bnufrh+uHhTqT8yZtqXP797JGNcf1ndRedxXstDXQRlCuO0Oc2IX29NX3WV/Vqkedm+q767uVhp9jBvln+TXpp7fpIqdG2k0m54mZyXmv5HotKHlMTsnjuod1D238hf2F/YjhtsY51y1XuA9+l0EvKrMlB8mUDNbZGfADmWgKy8jwr3Gz35PVlKYWWb+dMu57xUz9XqTe+GFG1O9wLyH88rtgG+CzAannsxI+K+tXvvyOjXTc7nG7QVs00nluuXFbQFLWwOZryUrUVInUZa95kcoc+aAbJd7HKE4NmJ3ttIm66IDEuc01lNyG1IuhAzF0uJeNobJn6krQFfBagdTzaoZXc33zS0VCuOoZWD188J8tF90R3QFWobG/7npF14MUWANboKP+mMwrj5G67AcDc/UGPII7ZAtW1iaZqWddQ6mzicMakczcV44nuhPdVn/qzYojoIfgdSix3bLx98ZjhiY6NKYPgvH4a/DaCrpcma1tDcqtScwX1uLFhBouk6HT9K8SV6E78xBjm4x7D/Uj5yLdooc8muWZZMYTMTPjCVKNc8YwOTOG3UvjTE15CnoVXleRusypjU+tnDIMOgQ6hNR6FtRGwQbABpCSzPezIPtB9iP1FLqg0DWjK9qsI7FtxmbQzfDajFTKJdaBtIO0I/XKtaJc64xW9IRHGikyo3FGY7QZ72xdLdEW8Lj24CIZ1RRIsTWwH9ayhNoJqctaM6Maf49eCc9I2dF300G3ruoNYiZ+Ln7Oi6IaqyJ+wr1sDBWR8vOgLfA6Ej8izKl5NOV++QnQFGi397kTfwOkAuQNvLMzYHf0Evg6jX+xxH8aZJk1sCVW9aU7KNcUb1I/fwZES8nQIH03tPYX0Wppg4NyA2LmpYHyy0RaF1bbSwfKz5SfsVFMmV8+GnQXvHaVv6UtSE6pffEh6GbQzeUHtL8rohXE5Z0a749KvAXwagHdqMxqpFAuVb5S2LLwMxh9BxEzXo/S2//ZnvWBqJj5QBSpxv0BvH6A3EsI13TC3idT8z5S9am5gdhv4NpkI56AC/S8RrxcIn4f5IQ1sB/XkodR02GkLlvhRQzeRZNG2ttfjroGhdoJtZ76y3idUOZeVn30hcRa4gl5qt4mc30pInhkDewnbcnEu+jd29Hb6pcZ35vyzPrGSBEkul2Dz0Ci34sAe4sTPZDoSfRoBC0z3gP1RuxDsg9cgvpm0I3KbMlm1NSeWKks9FnHv4IYmonxbhanOC3ROMipQDRQGbNxxnbUUK4qPyUqHei7MtA8nxEo2lMzesYjZSEVOsM/p5+oX3R1nlcZWzujBDWcVJUPi0oEbenC6xFlVmUr2rJpRreycFtq+RetCidGUintjB9HDUtV5SOycg+iHXdB5yqzKhj9xNUZCWVhlSb+JVWpE5URxi9+ScxULY0Pe+MXHySnqil+Na7P0dM2xKtAz2o0Py3lioirSvF6TJkt2YmacuO9ysI9O8TbtGe/lBVNK62W+fyGmKlZU2r8+bwOq2np5PuT79toqDjWTjz5pkbzM8S4/tYtHVuA0a5G3lnNseXjqC86+ZiycExf5jEo68Z0gr5Cl0fqodJiMVNaPG2hFxOic0rNtNS0lI1p0rNJz4inVWlMP+uWm3QXkdwALfIZgZwjM/lc5VNhHZloYvsR0Z/Rt0aKYPJe11Bu7/QaL4LJO8iZvGN66fRSjWDbpG3E00drBOslgnXwwzqufqjMllyAmhZU3xL28+FdERG8b3fF/+RZcrRrKD8aqUZS8oickkfuZSOJPYg9AH1PI/kFGZmbIJesgW3UkqfJlJxG6rJf9CIBP0TzR1KfPixmpg8jVfXpV8mZftW9tB9aJrWAenP1l6QfUiDHrIFt1pK9qKkXqcs+mlGfvoPqR1KfGhczU+NIVX1qjJypMfey6hXNFc2gEVX/ZbdcRR3svjWwrbZkxQ1430Dqsl/JqFecoeVhdbsyaKeYge301N1+hOHSlRHHxbRK1T8m5YphLWpE22S17NDydWRgdZLzcS8GKVMQOp/Ml1IfDZ2LLJDa1/qmMSF6A1tO5J/SLtB4fhUp84+qX60a0Y6QcmFIeYyUaclS9ts05biv3EBmyuEphzPKU/aq8k6p5XXrJzlvBHhDeA3wTngyXpPIyToJyj/tm+rmD5DJH0AqurwKpFd1O9Vjt5hLPuFpgWykhYG71VQwglqrNWr21eaSoSQltZX3Yd6u80n1KJM2CpH2ffC59jXzdmlfGjlZink3rFVe8xTzLpCpPFd5ThW3I++kKn5KPY6C9SkJa/0qN+upWjp7DPM2Wpt23NdqJzPt8LTAGE7zxvDT0pZm9Usj5w3lvuKYGih9HD4jnthUFfmmaug4U0VIRe3FhajzvpjmT7uFaG69mNaRLQK5pNF8Rj0GxVyyx4sD5AgtDNz1UH52P0/baW3qRl9tE/aW9ql6okiHkbdY1brVYzHYXCXhffsMfU/2bTyzZLW+Q/Si1so6fD1DpqytrM3qlWEtVT6QV82vvI38BqT+WJQlNJ69sh+cUb9TyIkq96Mq3upGxeTvZRVUh5YvlZGotMY1/khEyXAZl1mt/G4Qg3w9t6qABz1V7X3+2DDdVRKecz9hT3LpHC/JVpfREYuk/J7YRyZSHalW9U4QWCRm76fsxPtcVe/REquJnYdKwuptqn7+OfUFtErm/DvWplX7c/4IZllsWsy/34f7XD3/Yjrn9X7lfY1hv/C/Uu+1slaVByOBxzclkq9m9cMKiaTXWmWvr/wmVvqblW/699twv80pJPJjWK8xHJAYLqjfMuTAlAdigMewxPA1XpK9/s2Atam+ounFGtg2dVtGcaqn2CuKf61+m5GzTHlY8Z/g4yqeoPPBM0goLqe1tFXm037fVLdiF5mKXUjde1N0Ytw2sK1insdaeKydUC/3PKESZLmY3FMf3nufcwe1RNI1IZ8NfL6X0uuBuwIqCq5XOc1dL7PuobUS/xvzlPfIlAyVDGmM0cJrYFfgcVwInppwPySvfu+VdGtMn5PeO601HUDOVuWh3oMHNPE6wMns8co5aK3M/+zL2UOmbKBsILBH9Kri78t+Xat+a5HTqTykyLXc7ipyQneusd5aldHahd48RmfoEt1lI89yp3zTGCYdJTPpKFJ7kvlk7BmwA64JcV54v3B47Fu43yVmva68cB13m8Uk9lF78H61mFfvUjIwbx2eBzXUPKmRWM32ej3eJ8S8cqUoV1pS6d/nkQOLwsj2Lb3t9VbMW9N/IL01z5aIXXNNeF9mrsQGqS5wdyx4xq5nbh32V87iRmuxHi+G4hoysa5Yl2392KsFvWBl8NgixCk9P/ZswW6wPLA1wji2GPP8kbzKPfXjfZPG22/rnXAFrFZJeCYN0mNp7ducfG6Gr6CNsoZ6fCOtrYvMhK4JXpR1+Y/AtojZKKvGlue/h/s1Yv6cm+B9Th6VkRrU2tKuCf9jLzaQcvrBwF0RjRv5aWHyJWsTl/rfuM6QmTh/4nyrO7Ee5Ji8evmHkF/pjNZTyHLkRTWuz6vHdjAlz62CtTxfnzlnZT8rlO62xpnvn2/I81s686zAcdV6Wz1WgMWUhLToCt2RkbnI6ZGfFUpLffP0UK40D6ltWzfsiZjX9rtkJt/Fd1IdE5DrGs8XZEyuqN+Qa8KPe1GB9FMscHeAcrP7oCQuFngSLikJPglP2hF4En5HV94jiUWIrK901u+wW/V32HS24qQT1ibf8ldyH1p5CbPCKhbKnLCKJ9SjE+wtJWGtDn5Nn9BSI2i1iAVaN6kh2LrY4UDrTqpHibYORFqXeE5xo1XkhCoGPwm30C6p97K16HpPNzZEJroyulLuzZiB0ZvAjsNjkRCONuD+kLx6JbpRIqH7ZK7sbnK+w0tknQzD1zt7PKUlVhGPf6zEj3l8GxnejJizeidWo9bsa5aRiSVjSV2LnSDaO/YzDuwJWFSJr5G/DhofHUlj4jlrk/xnkYkn9VTFalQgb71qDKpHD1ibknDfb9K+r+PUCForrRXd9LUWkSm6WHTRahW/g7xB1TqjHgmwASVhrY9ZLfR66n+/bpxoYGYNBdeNEsb11bAifZmNPmN99T9fN4G53BdUNIcCime9daOKIKL4tSxFRxW/NoJis7XYOV8xSSZ2MnZSFWuR16+K76pHFKxHSUiLI/Rl/Zw+kaXlfzaP0/kvqmZcYlzCavEQ8kpV65x69IGNVvJ8u0bZdnFyBK311go2+1oryRSsKVijWsuRt0y1zqtHA9h8JeF25Wi73h6xXWQtssufk/fJRLZGtlotuou8dap1QT0ugi1X8ny7WMfrKyPM/33Wcpb7Wp1kchbkLMicMeSkVOuieqwGq1ISbleutusLz7VrgWjFrcWivhbmfwyXakVBHqjWJZl7X9ZnpvvIue7zcOtGa+su/z/PxC7Lzr0g60zsb4JnYsEnFujlSZnG7H51OqwVHPSUnTbMlz0Fe3S+rEDedlX+W/VIg61X8vxZ8H09Cx5hbppn1sY/8rTM+9jD74y/o628h7yrqvV36nEB7KyS57XuWi26OILWXt88rZ1kzE6kVmsHyCbV+nv1aHdNyHVfi80Cmhe4S9P47PEzVWonfbViqPWb/sz4mf2qdgMpI3rxY7TZ7PC5to/vSvu+nd2u8SXWxvmfvuPhP27luJWZdTBukSrdtB5Fd8AalITXQRN/RD9zZmW3qmjAN9KaeskU9SLVVoG8qVq3ZIY1qd9m14R/3VMEaaNXAneLnvseu5BW2GdJ7rCWl+fpMuak+5fnqlsk57s85q5+z/qKSwsbQJOgVzLnnGO8M/1vaD1RsONKwrPpL+ip3RFGmrl0Tc3/fKJzoTPVzsDn0z+qRx8sqoRxHX1O8Qk07fz9wv9zR/im1P8XWTvCcGhHaAntCIVS5v+rfFdq+fMs5X8OKS8MKRdJmc+P/B1q1CNrhf5+NOoOmcI9hXv8+6u4346UZNQ3gLwrr3Kf65ZdpdF9S0scAVukJDz/82jIPmHTl7JHfVSHtQLytTEP8+/n31ct94z+lmp9Wz3SYBeVhLRoiPP1mWvWyG3PfeKb6uViH8i9i9TqPYBdF/PyzyP/fK6et+a4ZU9pPP+iHv2uCXngxQOyh34scLeD8v3Tvjjm+EraYEuPPUKGNoKSfvtLejNgrK57Oftx6E/5+3mul0eNgTymP9XZUYVSK4T/m9a+QP1B9MQ/FfqtVesVhQHJzV6ZnWg3xp/O++dLJ1D2FOkZTeSOrDwbz3fUYx/u9ivJ6PXIGBUGNFr0d7QKuyJyVgdXRI495zHwZa4ErOZjXMnH+SR/ns/gesfrj5xq1f+u9MdfgpPmFAb4yefm5jh4ynxBDmISusz/fW4LrFRK/Dux7kAx2Bh4FSD6CRiFZnodzwEfpFbkfoK66JO0iz5Fu+nT9CZ9xq+pRl+JnkKD9d9fBFdsrihskSjq9IztAL1F99hwCddyM7fxRu7iXvTAWb7G9wyZUlNr5pvlpsNsN3tNnzllLpib5r6T55Q79c4Cp83Z4Ox0ep1jzrvOVedBpDBSEamPNEfkd9OCpJgpSEb0bKSg0przyN6bN3AfhUcUqRCqRu4V4khEYn/m9b6j37fl145insgxfoHLuJyn8Cd5F+/mbt7HPfzbvJ8P8O/y7/MR7uN+lDaj2k0MK3oYdezM1GkI7DJyLzvrbb3iu5rvgkPfWZ7x5Stgg8gddJoCvmt4kDgffk4i4NsP1kQmv8kpzviaat4LzTuwZwHfbbi/hNxLZtj3ZV5r9x9z2WVMwpaCNYINBhhWVN5VsKMBlsD9dlhPgKH1Y46ABVrPxs4Ws0EZE8v5kcmtp+HM/sMs/X8FpM8amBG/NJ0BORryGwDpseb7zaX9iLMu5NcJUibm+3GENiL7bMhvJTEfs6Z+TAtRf6l6OUJSIBUhUoUWnw6RqPSrRxh6mC2y286HnUfuGsmLZHafnBO8WFiO+C2EnZKn76BfH/z6OB7wa4V2E/yKg374fRK/UQKon67VK7B76sfE3rdwOkUGdlm9rVIjXgfxPahBaK7Sanj2Y/8hLbmfTOQZWW3Sc8WU5m2D7xrNY/0MS9q8yLu4bw/WHLmAu1YhoywZvQ53jUEf/ZdYQiT+LwV4iY4ZOFSYctzzIfeUk5cEdshiGiVruRzj8dtYtZ8EH2VPksQ3FfJegVqG+Ld4vvxbpAxvohx+Aat/P1b9rgCPg78I/jv8B/ypAC+Senr8enJGVFtMES7lXv5D/vUAbQCdwge4j3cHaBVFaCgrrkL4lmE36udukAhUwhrsrKa1/qdCrf/JW6YzdQwxWCt9nLbLeC2hFb5PecAnQhMoRt9n/86C2p779EVpyXGkfJvoTaWF+qtBNw3RNXqf3bbW8QJu4w28E31zlAf5Mt/hJ6bAlJu0WWrWmh1mn3nLDJnr5oETkWeZpWImd6njPd00WXOu2Xt+F/d18KhDmtnhTxAb+abE+f4Of1hbVIC0kKM8gT/Nb/Ie3su/xwf5EH+O/whRDfBbsl/s5g3Exi23MVMPr4A9Re5Tp03rgi9qmQ/+DL7NAd8a2DByh53ajC/0YsQ5O+BbEvAlsA6s9Q7HqK+ejPAeYmPX8Fhh2JFlr78WYEMoDTVz1meGztNbsq+TsELxOyC7uhjYOPG7RF0g80N+m0BqxXw/6K4ijpwL+bWAvGNN/WS3pOvqVeTtlnQrRKIos80nTMYdDX/X6oXyE8kbL6v7NVn1+jdKfEtyop63RH8h4D1fvdfDez0fD3tHcuFxMOC9zHo798g497jT9ybd0+3YTxDfVICvCPBZWkc/MTcpB9H+W6ZjEl7hUcy5P+JPh1c4F4+4widgdh7lN2UdXszaRfAkxJ/lP+bPBNhCsMP8ef6NAEuCHeIB3hNgFWBBRV3RWAlv8V7cO6qW9TzNXchdqvPLkV5ngvEW/5OiHncwIp4oHhXE0CMhsex/o5p9OqNloEL3dGXfUJWioArZ0S8Rj1MBlckhlXEyVnVZKiijKl2qssWq0NGQylqp8wXxWBZQKRuhLV8MqMylxX6Z7VpOTydog54VGFyNhBUh/zeBef6qaVWNco2jERYVMsV+o6A54HgSx+tXsOJf5yUYrR8KRVQiEQ0E/g64wdslqUONeKq/7y9XzUpZlyXoRdVWI54WqL+SVoe+w384pP0R0T7hf4+tld9oN9Oe4PcTfQ55SfSmQtdRpRNkqA2p5PoxH1IjrvZjflNjni5zFnXwb/p/x2igY1dxXGbAEs1ZrkY847lvVFNRmsnQZfgGW/ojoZa2hlq6WFp6+T8Ay31tswAAAHjaY2Bh2ck4gYGVgYHlC8skBgaGSRCaaTWDEVMFkObm4GQFUgwsDQwM6kD5bCDmYAAC5xAXJ4YDDLz//rPv+VsDFCxhfpHAwDD//nWgWbKsiUAlCgysAEDREo0AeNpjYARCDiBmYBABkzIMTOXpGSUgJgMTAzOIZGRinACk9jAwAAA5UANTAAB42nWLM3idYQCF31PEtvPdG9tObdt2m9q27a61bW+1bfzZn3qOl/pweoFaQG3Ar2pV83VqlQD5GOoQhDtpFDCPCmWoS60rtW7UelPrnXE1fibERBi7iTWFpqmZYo7Y7LaNts12H7t/eUVFBeCOIZ1CdlSRnX8hfU2QCashC/5FKhjoClBhg/If5Z/L35a/KQ2xrgJYm6wV1l5rsJVhzbdSPp77ePZj5MeQWvEIyAU68wa0jV+kNdrAf6UojmNxTokqVmtKuc4NziqdwzzgEOc5wlHlKls5nFQrhDMuuOGBL374E0AoYYQTicFOIsmkkEoa6eSQSx75FHKbC9xRIU90imKa0owWtKI9HehIJ3rSi970pR8DGUkJoxnDOMYzhalMYzqzuKlO3FK+ojmheCUrQSnqrLY6oXYs4p0KeKj2Oq+OymM3e3RaRWrDaV1gF4t5zwH2c5BT1KUWtXGkDg444YoPnnjhTQiBBBGMOzZiiSKaeGKUSRzZZJBJFgUkMZaG1KM+jWlAI5rQnHa0pg1t6UEXutKNlgxgKIMYzHCGKIthTGYCE5nEDEYxkwRG8Ia3vOAVr3lZCYILfzYAAQAB//8AD3janFoHWFNJ175zS7I2NEBARVAMEBEEIYTQQg+9g0iHoChdOgIqSkekKFgRuys2VNaG23TX3vu3vbtuX91mgVz+c2/CJfr374GE5M3MOe8pc+bMBIzEIoY3kWnURYzA+NgszAHDok0FpuYCUwHS54lmWkiljo5SBwvRTB6ffevg6CixNzAQ6vP4hAPzUsgOiyAnDT4h9gxdRb0zdPWm5wbZBk+3nTpxnMFUeaw4VimOz1g6y8RkFvOgLr64m0mlvNyFkwZTpxr08hThruHjxvGM9IxEk7yy3LJKJtL/MEOnW1lhOGaJYWQjpQR2YzHMy5QQIQkSIVOCWKD6Mv8gOvsFOntStQ1d+gal0jsp5cvt6Hf8q+Fh9Ty+Ps8CQxiG8dDbFMahxhz6DsahvIccOoBGxxpx6BktNIVD3x1Fec849D34gw//AOj7wH0ipqvhbso31TMVsg+wAe+ksxYcQ134EyFtuQiV0PsWo/m0MR2KgjvV5rTSc1rpKa3oKf4YInQO5MlA3jhMn9Ho5WBhIRIJJPbuOOGgfuWop6+DiyCC9iY4RIbHN8GJlZENET9/K8lOlMnWLr/xRWXtb/HrT6XSbSg68XBLTGCpd+jaFFSbWWhN8/UdUvFLpQto7zyaKtiUIKaUpuENGfFVQRPHK1owsK16+EdyCVWOGYN2ewNDvgWTGTyhvoEB6JYZ8iAXzHCpg64Zfr3xZJTSa2144dnSJe+VlqyXJXhc7dxHP922E02gyn29C2W2Oc/u3Xie7zenSB6/B8kf/4DcdjG+rKZFjA7w5VjWl+8vAF9i+8D2SLB9PDaVsdwG11gu09chWIMNDHSJTSHLOv137QnqrAwcCFyx89g8+jyyqHg0kIefOv5RrtngaduKjw8e+nPbfBGldFxL/4URbOQWglwCm4SZgGShqZT6r6Xju1UNRI1aQ/C61zUQVEND2H+tBPw2CFqMmMiBBgEEX/3go/2IpnG8aOgrQkefvEfPbacNWyhlG3iBncHmr446f+diHGrMoe/M5lDeQw4dsBoda8ShZ6yACRIC6glMxowwETE8zuHTVN8dIqyEQMJkjaobOADrRIi2FKItwjDFTAsmrrD6R8Kug4+EXWAqNhXweHjx7qd1qbtvLWnsj8zyaIkNXrPEK3r30oBVcvqpEN1Ovmu4Dbn91o/G9seFBuW5OrnUfrTj0svSmTPQng5Vgb0fsGOjPEbtJ6WA4SYRmMKDSFI9P3wYf+Mw3qoqppSqM7jfy+3M+JsYRnyj8avaq1J4lhLf0DeR/dAvyJ6+SSlbBk+0tJDBLeATdjzrVQOuKoygxhz6Dsah4NURdACNjjXi0DOI4bF2+Efia+Chx3gVliCURLGM9Y6UofP1nJyTTRkfRoUmdMk7uulMSjmUGXuwJcZTXuwkPr2TwNogw++C7evZTITYKMF0PSRBUOuqDx8ei5tcVn2Pe34Etq/Aa1TNKlCO0ESYYQczKMZbEiaOE/vwEn1KOejSDVxHPgeuxsCVj46heFUasJUDDm5kLPDSExE2uIOUEBEmONR0kZ5ET480D9tnRfDwH/peIBwRhPnusD++fMAUV/xW4IbVuSZDUuKacWHbek+VLZgSSRzRjp0usEEmhJCJHrLBpUz8DGgjxB/D2/kz+hWNH7uTfNswp3NPhCoMqHoad39WhR+DeIJ3WRlsHZ2hrqM0s/aTIQ+jIQ8nYkbAWB/niTTZCMmoy58E3sYFk3Ql9rpkdOE3vfu+LSz8dl/vN4UnN/b1bdy6v28jfuQ2/f6JY8j9wR3kfaqfPvsQ6SEz+hP6V/j5GpmCZrUONjNmcpkxghpz6DsYh/IecugAGh1rxKBcZhCAmsFYP4Y7W7OBsVDLAnNDPh/x+WKZDMn4YAa7pHQFUNnxuH1fFzPmwPO3KHNjuB39ro7fhnA75G5QfXijb0dB3wbvNqqcMUfbvFtiOmFwR/L34kElGZK/DKz87cazPDQD6d18XjDK/hnHU71XqQC9R5UDy1nq2g5blQE8C01hF2GfGS8DY0PW2RqSaJ+5nxneIqSnyHz4SELfIAPkuIEq2dTH/F/3Ut9rrSyrKl1RJsmhyseOb/V+dKi1/zf/1rETUAZKfYzc97bRz+gb8KNCPGR/fbAYYv0YMiCBUkLtN9Da4RwdZfrAQMRUK3uS2BGzLuXSWWVX7JnmJ1uP9qG0f5AxcTpnuUx1XFpbvvODOBpRylsg7V8gbT5Im4AZMhVCYk8KR+QgtVxoblDtxRdI2Phr94VDqPHTz1LXRr1FKX+89+WOy8n0MKWk21Q9jk1Ld64BeYn0m+RO8NJkzAzkqTdYQ74N/t8npOPybGVz6sxTllk95ds+LSj+BjKz6PjmI31btu/v24IfWffXGRe9kNqMgOx1wUeQ22iG6iMR/Sn9iyZDQfc1sKUKbNHBDDW6oThoPMIf2f9JSfymVLTpNt10pg+lDyP+mU07Ll/u2kN8uXjLQkNVDx6uOkYpP3y/vpjGKphVOx/ibgcWzVHL5AoX6xkLsQ2uafm093pDE5y0K/tq58a/5y8OOLM8Zl2CQ11Z06W8oiu17fdiFwUdiAteHuy5qTbnVAFaXnZqcVJMiU+4rHC+T0qgaFZGV97iHYmRIYXernPiFa6x/uLpyWwtjwD7UplOD5gwVklN+fjBw3QUOVGXvD7oQF5fv15dacnpXKVlCVswJUZfXWzJ6YU3Wtqu5R7qbGjshNqU3HK/rPz+amL30PyerVt7iP2wAtQy2LU+l1vrI6gxh76DcSjvIYcOoNGxRhyq3gXswIJq4MbDsAy2TZXgSajkCC05TkvevkBufbkdPsQQU9/JfUwvAzZA4YVfiR5bd/fd/W7b9h8/6Ovc+6BnL1NvyYmDT6FGppD4IE3uYua6w9wi9Y4XLUHqHQJ+F1xCNsj2HboCnbxE76f3vo2Owl7xOy5QNaim4PmqdfgXzGxbmL0KZr+h9jFiJOBHj9K2Z1EeKjyO66l+xQUEFGa8H6xkR7N+clL7aTwjox1QU3UHkQFFQoogUkIUht8RDtXjH6kKiKANG1pJz642riaac7XmnILJ5GZABaQEm47NBhn6bG6JeZrzhUSiOW+I2bwTIqbDgPeQeMTbs60tfRcZOh9YvO0k/aS7vsxhTZS18kDohQt0aFibzaa+9ozvPVx0ysYo/AKD+zt398UVpU4xrjYzOdWjWh3uhyYuzUjPgPipGfBcgJcby+utJ6OoFYceH0Wpxxx6VGusOYf2a6FLOPSEFsrn0JNPMIwY/gvQd8ELczAXzIupubAx8E21Oun/1ieGjo6I9Qg7FqowfGJqYUFkHN9Dqr7Xyc52jbcPc6uLze6UedQubHnzk3sJqfOlCV42Pi2exZXG0+vp5zEd+ZE+PgvsxumgjPjECaiSCCcl9C9PZOK3ei0tim1dUtKz5vd37jkSu0QJHpxulhoRmaL6pFS5MDM1SVqCPt74zpuHmVheAStmUZ9gAmw62MCdDoG4mC8SyPTs2TrCcBcYGKBCl42JrX0RaQNNpzLHd/b+VtfmtCQyrt7KcjnRFRLd9Gzv9hdtdXnUBeHLjdfvrT6VmOWp+sc9iMm6U6BnDHhrGmQM5yCLV4sTU5vwveHNLlGKD5J7Pi8p/XxbxrGgKJ9Gv6ajka2VDrPyXX0b/967bbBDLi+wtb1+Z82xaCY+p2gRIxvio2DjczqMsawJerrHYJku04t4GQpE4td0gsKRDhic79HbOcl18/zm/tj0gZrE1VKwzaUwKqF6tlUl9YnwpWtLTNjqZ7u3vWj3kI+7eafpdNIiT1zH05/R1AC2WfLGYaZMBfGSWbAl2FBmyDfQFei/qhQ+4yMHCzFXjEE9it5lX6wwj9sgb8lY1t9b9qBjxa2q0g8LF/U4T2tK24qOE4RkhzJgRdj2qtZ95ML9k0U6dXq2pl1xK6voMvrr3ucNxZ/3dH1eFeBdfd1vl+qJyHN6eHTQ5oq33n7IsOsBdkLw/FTMFNiZ4KP5+cp1gCYJUSgVszoyslYRHvTugs0fFRbdXFN/djGO0wmlPeNwc6IN3avsDpxru8TFG9yx43nb8sc7jGx10cM3+/YfhFiw2tiVGahemUKMQ6049PgoSj3m0KNaY805tF/I5A9UczIGojlZ++QqFEIBgzookkoYUwjZvNXujpIief4SlKFLH+4dHMzooz4xMVpuYBAb/7BuaIDwr7ub3hYKXqml48h5ZCsmZ7R4Mf4YyXsLsTowaseQrJ8k+tyeKlIvaZnGe+44NbKS4UPS1MFnU3xiUsqx5VJ/08nT3SLfy96vpF886f0getPcFWUlnf5Ni95pWuXqnBib/d6y+jfL6ZTqimUrC0pLydZtwrGz6xMydyWNHTvJycTCPmRlVPebitYceYRYHOocHLI0TJJmPrctI2dvChLOGmjOzlldU1JexXjnChSkH6kHmD6zL6jrLrjFgU0yPrxChe4nkre09caluOXGTuulHqhOR0fvWaci8Bep8x0jZqsQ9SGTK0/By3zeWNgbhCCJO4+hkXsiMBn/AlkO/YQU9AWU7OTj4yT19SWNhzLr6wm9evSrr51EoZDY+WJILYs0BllakkZnc5Mg5uqxbNZEqbOGGEWtOPT4KEo95tCjWmPHcugxLdScQ/sJxsr36TiiEqycgE1RdyEkX+yOS18zlKjcRt9/MG3rk0Y6CJ1z8vV1cvT2BtZrjv7aYVYzNfNEK/5S22Icu8/u7Z9gFGszQqIxOPiedKUtcMHnqpfoLm3USxrTFqp3cQ/0BXr3pQV1gYneUqhUv8NLActGawNhKOELlKFzY63mWFVHrOmj36UuDHqEeekLqoSm3c2khPUezCc/oy6AlQnqcyI+TrUY5GYAn2BY+SJ2zYymBF/7hcRwZE8iqiXJblsnO9smW/dMdrZLtO6uG2uVE+6WPcUql5RYr6gYeoL/vSDO1Wfo5shf0rhSHu0c5R46koOgDTKneESqWqUmDa+0T/A8l9jd2js5JMI9b9400nhd5Hw2CVfl1ssdIy1ViIkOPBGD1JeYDtOjR7MB4fNF6vWm918Krrbx0DeNWuimP9WnqWO819nE7rbeyaER8vx506gv5TaT3RWHf9W1MbJ1e2n6X+kED7Lc2R0+Wb3DYwyTTvCrMSlRn1tZD2pVc0OtZY8nrL+SkXmlq+vq4sxrXU0tzU1NzU2kpPGffTuft8KuuPt5S/OV+7evXr179wpoY+Wy2Z6mznYM41ArDj0+ilKPOfSo1lhzDu2HZwLrpAdh7DTurPoaY3NDgg8/Yj2Znozb/Bj6wL/jcg7wb7+am3kNebfGzxkyCluTZKealNLYIq+Mb2qSL33VnB8t6b8Dh27n0y9no8kpxNyYsiv3uk5EXLm74XgEx4/P8OP8SQwPAnoT/GkGXbdM0zHxXm+ZOLrqpNSurpSmT6rt6yGQ6g+dRYudY+1D3VbG5G+YZb6yrHRDgN/GsmXVM81q6cj06Oj09LBwNJCQMAHlk/5sd2Q0V0/THmUrEwrVlhSkxJc23rj70Qdvf333Gsm2RdAV0XFs5NVd0WhLJOCzCWjILJ1R7+1Ysy8o/njz4azedh2XnbL5TD8UXFvnkE1K1C1RJT1WSF3ojIxrZBoiuf9lpjfCRvRw3RdbubV1oVf0QPfVncCpQkdG9VCfqM4FhY3q4uepHr+mqRNq3mNSoumGwLUyiUAs0E5n7W4IN0td66jT3uu8Obb1YEji8UO1dY45UXE1oJCU+PkUv3QV4pMjg0EjNESN0A6dTEhXt0M4dg+qjjnpgBkyvV6xVAK7s6mhdpsHPhTqSWUS4t6ePchsuryv3VphZmfqKKroc3jYJlg7eRVhtOpFTduEsRvGjDnUR3uvwgceVdNbMcTkFfEzWGHFdJH/9QlXc8AVjh6GcduKVlFuQd7O+Izj5dXvege5dSxalimpzFm8OXbltcL2K75p7jtLEkPm+jlNM/IvSoxfpfCxK7KUhspt5HbGRiHL0gtaPKJdl0g8gMFZyOEkiJhsJC90CKG+CcGp00TLhpQ6uBOa1pktVo54ZObWOBtfH5vI8orIxQcWhq+Q+ponW2eUuiRkJDrb+ilsZ0YHFCztfUh9ElgT4xrj7uhs4RDsn9CQUbI9SjSzWGiUleOZoJD7JXu5hLlJPa3Nwxxrugevklb3P2V2ke3AbAI1A/yOZah3D7YvkgmgR9LsKuQExy1BB07/8UcvytWne5NzXRdaSc1m9a/BS2p+16dVNaq2uKRpBmxHwXTPsHvrje5JAgilWCMZFcYmzu+2goR3P5m8eSNprDLITFrgS/AHv22LmLe7E6ehCrAy2Dq3hKtzI6gVhx4fRanHHHpUa6w5hzJ1DjEXH6QMuPGAG3NKR4iU0as+pOv6kR2aQxoPfgvb9DKijhkrgrGtMBaOvkqto7qEePBbU9cPZw819F7a3rCHoIYGYU4wYTt0hzjBzAN9pBfMG8fMQwimqI/qcNKupw9e+uvZWfoQqrtJf4Vbo6f0UtREG6huoPMws4qOJ6UwcyLDTgdnWguZmqSUbjMvPNEyNW9F4DQnuuM4skGzge1nOf2lOg26QSWRQGEB0QN2szJYz5VzntOg1GMOPcp64waU1keg79XzfDceZDBE4wFw7fxde3s1MX5dzX9Rl88qGAnnsD+Jn8hp7C28IUJ8hMQIyRBRnUN/jMTwRN/PQdbsEzntlbfspyN9I3Xu/9k3EteGztTX4x/UoX+4LkrTnYGsf6M7A4FfjHZn+7Xkcl2W8v/WZSkHd3NdFvH+evDSs4UYBrXHmL05lEAiaf9yeaX1SwTuOvl705tPl618Xt/+R2PL8/rOH94/2Nh7aeuu61v2XN6y5fqady/1MNnKZJ/2QzsbX38w+/x1JuJQg6ZDdtuwdUgo+B9uYRBEQ+u+Afft3WtqauEeaWDXHtK87/G10swUy1UBNnHd6NHQb/iMkjUrEiPdCiyoT9bX0CVzrMflvSFzcpavLW9Y4xYTYDC1dObUl+9u3EhURgSFhMklwOcs8PkN+EyEajH99b5Do1+7W4pbfnLBwpPLlp9amHEap4Z+R435NTX5+StXUp/kXmysuVyQf7Gh9mIBo4X8YOPOnZs379y5EfSsh+w1osohT43UenQFI3e1hvCsb4KP3HsaGiIxHvfld999+cWjR19Ur5vhs9g/tsrLuSLHmg5yp8rpDvoAvZ9uR4VoPopFBY30n/TN7s+aPcuGr92ki+06h5pLmV3zPcjrceyN4Fj1jRslNmfMwX/upc8Hoi3oraFHcM93iaw9u5QenNXcDHlWBt74BFhO43YInM+sS3dyNCS4Uc3AQu+1Px/Em4VDN7Z+2h45o7Z4UY1XSdRlqnxhX37qiUt/dLc3r/9q/+rlPiUNfqEJC9mbx8WQw7+AbJtRL/O19jquVRCJZGpXcAqn1LybGVQZGNmWsPRf7cWPwgtdd8d07ApeGVUijPQpD9mUm9Dgmxx3kSpP7kmJborT4YWvzSl/Pz8uLUnhu7EmvciuXpIbWbTUw3NxdDDjmQ7mFhGY8DRVg1nySCAi9HCzNfQ6/MuhJfiXu5AhVe46tLmhEnUO7UEn0D7Ghi1gwyClZG8j+KbaPc+rJgBxkYC4OUX1lUehe8GBlOLb7cs+jMj0WBvftMm7UCFPcWuklA102MwpGR80N98uigtb6Omxd8eSlTJDQ/zoyI44RXM3zvUHuKGhvrYOsTYBG/ZbAHx7RIOLt22Wc/6WMIQ3bKqtlecH5uyRkL59+TlHc0oulq/oy7WreESVW4qLjI076b+Pe9G/ntlRWOu0cmFXyaKUc52bPi5NPfZi83co4jTD5MPhX4k/1DfLCrG6QN/owaeoKglbvbnk6TWrILtrge0c9rt5K8yJvc3nc37hbhzcIcVNcIJpfHRwzfUR0/CMxJr4e1lx446Se+s67+RtXJ63JLRqrW9w51L/ipQ385zT3da2dWxWPQpsSk5LW1VWWkNOWdjp4XRmZUH/osVH86uPODt0Fac2xllazqsbepmcG2A+NaJ8fmnjWmJ8eILzdFlhSmZlJVhTP/yQJKlSTDyShThTox3NHGUyR3AqV2n4ozUA99lwecG8fvqnc+LziGygCORakdqwur5s8QYfJD9UWtyfsfQqVbp66PBt+ssP6qQrZRsfH0o7dCtxz7ae9pL0dXFF2edXd15djOFINPwX0YK3MVUA9Dto6Xv1rs0A/ysqKCgmKiQoaqOiOWNRs59f86KMZgXyLklblJ9VsLgoYVNS0qaEpA0J8RsxhNph3ZriNUyMlAK+2FwiwNef9UOmheiLrIX7VSswGOMAYyrxNu4bHHZd49wyA63EYq/OFShDoHq4/bC33Hmuck5GZd+q1WjAIz3NoyJLWRBmPcfByjG0tYyRJwZbmkCe2pPCkZBrrwT1WoYXIys5q3K1Z3hszM51ETvlSTYFzqFB/v7JE33lPpWyTEmYYgPelhYl9ZkwwScgodDRI8RS7DDb3jrGfE6c2axoZ1tGqzlY0YxvwHSgYxBCdy5FhoREJhFKhITRWrob6Sz7/uz4hvyCgoI0dFFC1x08WA6zZMC1AvxjArNep8iuVXCGkPU8UbF3eUSXW8KsBbKAAG83o8AZeejRePqkScjMxbWfFpfYuYeZm7s5SSW6k5CyrFpHkA0VBc3S+GIa+w2menFya/OVUyExE4qeWjMxcWaQTVIyaZ0V5JGnCK8Nz24NCOwqcCqVfKJMGW/hLVMEeqNngklpGeI5s+P9/bOc4zenxm9IMDKhn0bN9LD0nOvkALZ5DD8lCvEarfWJW7YiGZ2L2090QV+Vp2MEMgJ+69nYz2Tr72iwuNXJGu8AuzC3MkcXZnGU27zEQ+s2vDkvVO65rbJuY0lZ2tKo6Ih4+nZwokzmHejvjX7w8eBNDfZIyM+b7xwqEPi5B6Wl0+usZk8y8xZb2yP/GRYCgdmMKWJzxl8Ww38T7cBHnznRZTg6yrSdxBCj9GBNjKxHtOTwgIUkXeFd7Af3u+v3DtLDx+2SLNC8CL/o0MXCyHgjC6t434AMh86Vp48Zo6Sp+iGhjnaSOdB3IhH+EdFCFfH4WBso/g6QdvwrwpRKB6QdkK8AcQCkksoHpEODiPH7RBOLrNUg5jCmmSoDZJ0GkcGYClZOpwaZxc3q0iAe+C2ikFICsh6QLwExgjHr2TEbNGMs8AdEO4tsVCPAsIwwJZ9rGJaxDMuAIalhWMYyzAZdpIZhGcuwDBiO1zAsw5DqGirApcSnGAERFyNDeow7aeOGCnJwLAcjhp/DLjhAQXZgYyErsGgYQalrB/qvy0MUM31oJVNXiggjzy51qdhxyMfdyU5pvajyyMrVauEdmqpDf/yfCgfopUHvWxq9U17V++qCTmD1rWD14W8xi3ti1fdnJ9QveVWLqkN7rcNNDcg/QeWDfCvMRS0f/R/r02sE8jxIG/nQ7srVHhGx83Z2RuyAmrXEOSwowA9qlptvlWOmQ6hiPRGvpvbo7PgRaohOi3L0hjIWGK8pY5YSq3kjZWwQ1yaMIbQPugo+CmROXRkOr5YNtM8m3F4SYWMTIbEPt9liF25rG25nF2lrGwnzNtOb8ZcwT4erwIRIj11FeJwiWWCwa1OaiSgJBaZ4mwXZ0q2oxcB/lk8ys/5ODP+IvyBo2Icmszq5f6YUgH7uDTqR7OuXnOznmzw7aI76xRqvtDQv39RUQmgTYJXi461UgrSN9CZW2gRsqjYT9tJT69jjiMf6JQsMgZX3qFwUnOplHjSXXoNabeBLevwtVqg3SGdOC57DP5EF2HPgacichsu1mJr/N689Q51dQ0NdnUNRR7izc2ios3M4WjeCFTmFhTk5h4c7v/aX8ckd8Mnn7P9ATVR/N67NHT8m2KivdAkNdXEOCaGUQxlE92BXmMwpPNxJFsbOpkvxz4lHmtl6Ir1XZm+b+uHkQGYwzMbHDOUSXeizMCdZeLjMiZmNvcX+D1e5ev/g7maEIvYihmuEXxE5v+pYSkBObuB+/+zsgKYM/w3uS+PuBbuEhbk4AcPyuNbwtIro8OxoRbhyZUJogve8ZEVo3OLUwRVarLG7dAyJAetxGr2ceD2WgPZJ04LlIsUbGbeBii7Q69/I6p1/v6LyWGpgTm4A8WjEKtosWlmdGJLgHZukCIlblBYPfJbGRGTH+DFVeR96SfCJBKhVB4CGLoZQBhoggoke1nuvfrvHg2TO9/TMV/jle3jkQzOyROGX5+6R76fId2f6UyV2gQwn69lVoGfOpwhDPT0ZYS6m9HBiAl0nQbXPGh49aniGamHFTSDr6ZzGbUX02XQURvenI8+ibY2IKc4YbOSkH6XUnM8IiVAEOWwKD7iJYh8SwhQeEiEyBXi9664Tszvm0J9bd8zZdkS+6y3rjrnIwrrDdocqHYnk9KdEB62ooQ+jaOZRg96uZfQxj1pagd4G3lnD9qQ/L5qpzvOhRj1tIuIabrrxHnm/+lm0DPGzGoi4Jp7A+4WRG+O9E1gy/oIs4vGwQ1jJ8DB4oBQ8IIX3J7CjzOrGmuHzberV7fX/WN3I+j8vb2Dzgv6BmMfrYO/T4KAKhxGcOWvoygx1CLTfMXtnTtyux1VVj3fF5e7MluLvbH12YyA1qR4ZoNhvv0OxyKAuKW3g2jOIciJIOqWR5GCDQyHWZf4ljbloIgi+NHtnbtzu76uqvt8dl7Mz2xF/p+fZtYG0pDr6J/rAd9/Csfen+qTUgRsgCfuZfko08hrZvBXCNymGegbseZJP8KC4C+E0JNNjGnopHCXFhIU7TjQGlntRs8dYxCv8EszGzKY8lwbGbClzGzvrDcvGhoZGyzdmjXUr7eY11hn7yelFMfnuE8a75sXTi9z9pgFUkYSWKVLsGuam+KIVSRV+xmCNJXC4oOFgz6lWk9HBR1RDdzNCBlmCRvm4WW9ImqoqmyVqjTGB5d484LUgMmzBrDdm87zLgniNjEK6xjdlboNdioKuYxTWTfNzR1vi81zGTfDMj0Fb5CyHgv+o7TsAoji6x6fs3kkSC6IiKggCHqggiHCUowuIiEhVlCIGoiD2Ehv2XqJgTTHWxIYVDaYY8083PTGmfWlfTL70HhW82+H/ZvbuWA5Ufk1YdnfKazPz5s17M2uTGy3TFfOdS0nW3b14Br7OjuG87/XJ1Y2fbUFQKg1Kxaml4p2t+1Tj2L04jx3TFTc885DOUA0yfY340x/Js6LXgRn5Gu1H/GtqeH1PyNmq5sRDDrzPEFkYxRN/aXpznXgp0FoHIcg5reZkQg48qzVK2Q5pZJOfrUYp/YHt2LaN+whfw58C/inQj9+BfozxGbadKJiiTuocpZni8Nvjo2PGdXJ9YkVmT/eZMTk5MX3Cg9hhPL1rJCLoX2w7vSLquYs5Q1vTt+XrTQ0cfHJ8dOyYTt0PrWwFtJ94iwqwouA46LP0qm6AiiPebkmDgujRQ275SpzyY+Py7nM9sDrLzR2fBoxj71MxSukcrltUEM5n1c5R/Vq8cSyf0qcBi5+KJfuOnFznnHTpeWBFhmsfjiQ2v5Or4ETeEZObG9PbGKwS79XiDWFcR58liuDEkQ/y7/zY2DGcViDcgVbE20dT07F9CkxAgFpT3h2dmxvtHiZQqnw9gaZJTpI/0qGO0LZ6DDYXxuqNlJex/bi4jP1FTpaxvbgEnk7F470L8YF4dj8rtT+2ghOPjbg7NlDrLZP9VYZL2N6yrfwBjjSUkTS8J54VLWQl8fgx+yPnZAGaRo0cjp0aaixlT+Jxpez6iViBMZaVOJS04iOr2PVSPI49WQrw98YKoLGI4BR6kZZDZJyKUUdDxA+e5Hml7zMeH3jSi6SD0sAvDvV3eP1/oqwoSTr1/aAvJFlzn24aRL6jOcL7yx0mejVuBOqXkFTPJGNBdFFoaFF0gTHJE8eW71qfE5axq27honO7MsJy1u/iEC4DhOtWCNz/YlQdb9w5Tco4hJjC0NDCGBXCFBXCuUUL62wQiAVGLx0tRrNeHbdecI0hjY0TSCMf2HzM0wYCpUZZS92r6ooQ69VAaOEjtOgRWqgWhwrYkopfhx7uJU4/ADfgxIIL7gA8hoYMEStlGj/fPWdhfvKkbDB74yJGhFuW0Puj0mLSY9LKs0YGxkykNCZiboZptKmvf98a3NfPAx4ncprz2a8kVbcR+QsvGpAMq0mXHsLryJ3okCA2cA4N5Loa1jouMYTvyGHXib/y8dQyjHMnJWd5l07lrzMOje0WvbCsbEFMN4LHHKAv79JtXBFXwAqqqlzEPDGhMGFl6LpFeFlIRlifNX2GZoTgzYtXDG6YqH8caFHWNbmR4UID36vR1IBNWUe3KfeRf3DATqvC1ic3PKNPRtTyKGjtd6AOt0gMLW0SEJC4tDYJtml2d41tohwmFdFKPrngaJ8ovqr+v7OdQt61zg7E8jReRevpZET57J0ILSo72GmpEmq8njw1Lm5qsjDVeDs/obXWQMcr34OV7YpTJQM6ZolDCIEF2NQFQU7jp00/4gVqjjkLcuDOZqklGobAXWrsDFZydzpH9C5XIRHuuOWXw6rJ1+GddrccpWMsRxsztaspuqrF25zqara6pobt1yyygjXPnMaXgPpZ0iHJgMPYDEHbz+bP4U6VNMg5L/z74iRbmcaWxu2x55X3+OIiPD2dbruTYX/dZr1LK9pj4VNLPZ5Ev7DLzC4xx7ajX5hPSNnmE8xT04A2kSwQjRgbJxoR2vBt4DWYMmip2qZwIYVaS0/RhkmQ46Tm3NwKOXA3j1ZL8FZGuoYUlEFnSKWCHhfkiQahCE073tZWvV0GnXHrW7nPrW8Vl1bGrOXrVkn2Nr4VX1wcnwR2bo+A1AGFiYkTJiizWiUhSUHoKv1Ckq3Uemnk15og65tNksq8gqTkgoLkpIIBqYGDUwfwJxv+5VYzmwQFpA4cmBrAkYFcT7HdVrme4PIEnCdAvpDDnGFs/CqXQM4p66g5JeQpN1wFiS8Se7I7Cz0x0KHviXXsHd7/sXa7m42aBa70tf1F2+Uqtcve1u+IWryb0ukX8gGb/k/ivherxNjcNXTfCvxWQ7L+mYbkukRd13jmoooDIenm7BY1O2vrqpfFndeXfP7eeV+FeqkwrlRXK041NXhRdTUfhyUgj6r/wTjEN6wCUVL+F8ehZHkTdBfEc0QLDUc59lW+pKUGom1GDTntpnkLkDo0qyAz1EqrW3bl0uR7mqlVku/qLBg9ZWRsysRU4GHJ2PSCYbmFnSMWVPyp5aK9nPI43wLgFFqS75YSY8bIW5C2hxe6wPzpGTrPPPbVO5FsG0h0STtoamoyX0OwZ1NaDePnvHkF10Po/DuQfvMyeoWulc+I9NF4EIL7zclifJ0Xmo2YjyAn+rj0G9ToDnYP7o5DMfYNob6usrrXwNcoj6RZlpPkRSVGKT/bDf8UwpzhDC37jN3YhYOZbMI/SB8pf9cqv5zH53DdZaXx9LENbM4sWN2Mn4w3bDh6FuhrbBpC9+uyBR27URDgr28ah7j+HqKuvcXYDkEokYLl0KZfwkvYALLj+vxgFKlWCtr0VJAk80XVVcEc1/B3Ngo+vN0CX9Ar1uWC3uF3pxe3a+1+MIoGW55rm4nvzO6CCfnzdq3v72Lu3Gzv6h84VVfeqnXWDk6tNl+7GuQVdQV/Z2LN660LfMkCfZrmyiVizHkLy8iLeunhwnfxY5EMrAtkt/qJv8rnd3NqSanshQb2Arl0J7pUesiHLejxBpRw3ZWegvr59Ye+6v+VMuZutOCP6QY4co/JljsSA9QMUb2roqXiUTq01e2pcBVt1bZuNsS0mDsP3o5Cc4VljyquWgfF7F0+o8itwnP2Q9WdrJrszk2Mv29LNfcevmHaysnrs7w0Sk4yX0SIXrb6L1WZ30XWvraZ+X3vA+cDtwaxL4O2Bu897XOgLn7rMOwLf/Ypi7C3D/tcdwxm+nLLA5Swm8vZOjyfX8ux00r8OfPh10p2EzvBRhi2Z/lyvvIawn08QIs7t5mSoOO3SYQ3v3whj12WVzb+a3wbbX0GZMxKhDA/2Uaeb0NIK+Ad0Zsr2A56VLdVYAzjOF3vglPWdVWX0sTQX1WVt9ycpJgbfe5CRoeTUtpDz09NW/z50fsxWfQjKMw9k4x3IO7DJ9kPv701PmfcB0044iWNumxqsuSD3v9U6P168x/qvLQhCOS3HPy/RJet7t1J5F4GJwL20EApQHEaT160dFVWc3exXKRMqWW+i/E5MvVWNvcdA0x3gHnNCvOcgFn/GJ/r3of0pWq6mNvgbp3r6oWNji3XEaLqjiGUrR7tm04ee0o5rhw7Tx4TRwJfN4fLJYDDWlJKwZ0Qkkvi0AuAAT9NupDvdOE6PfrGGmu9TDqT6yLlGqRcQ7jpF+InvUyeQ1RdQ3aTPiF+27cLL7M9R/gXGumbPAfg8jq0njwH2Fyk0whwxQFXTb+gq9LLkgyWnptodV+xb/y2drkcClsE4MK2e73GPg8cIexzFlpXV0dnwR88v7WJHgkLh1VgaS5W74IG2PfyslXP3WvbQ5bogMnR5u52/PhxugL+KL9qzGzyfUvw9IaDdU2AY22E4k7eAMcIBfsWB0SznXjRfzFKoeJ8uRknDOU2cXrZcOIKtvK2WLGH5dv2oBXRGEe8DprsDni1Y7f9OCm0ZrpUbl+DiP6J+QUjrxu5ogTgf9ivfBFiayrlG74CsdV8+TY1pU/MftInFqc2a6KUljXjNTXJa1hR3Mm1NqtKZhOsmBZqV0zauhQus4m+aIkh19gvvP7l1kAaf1Gp0AEsQYWmH7tq4N0GLn2G/GwJpB80pLSCjxe3hUeyrNbicaRZXJ+qMM29OLjG6tsSDZrEGkewa5IJIo5gzXlZm/OJNQeV8hxN7MFeB33I3qafy3nihIEznxi0m8Fc1ZNo/VW3qzP5KW5BRE5CZcTK7TuXR01NyAxfGLfz+RfzTiyV89iH+uDAGcH93nr/ykXDkAeDgpzYZ9ivJ+79zdYftnfFgbxvJ6Ft0hTpJZilBwMd4nyBeuRSONBd9epOWIPeoG7MMRq0B0nOnA2pSkleHHy28mQ/vwH9TleeC16YnFIVcrbyrJehv+dp0n3JypVLlixfLr10ztPHy/ts5engpalpS0NOTj3jBf+gXMiSEalVwec2Pbxm7e7da9c8zPvhBganW3T7YcU2AAU3y8DgLDzFKvvq2VC4q2Jwceb0UB2nzZXUzX8mZlLkqrSyU5V5x5eufej9xNLYPRNPXco8uHDtm/mNWeXp03T72ZWO4yIrwuKdWLjX5AOLig/PdmZfYHenWfHT43I7kAGR9Rsztz1wLw4wX2Gd/N/JmU/2dSrJSZ4YgDBKAV0bCVacQbsjUs83bnnZzuF054IjBtjUYYQrzIfcmrwjMdc407Si1h3/7M588bk+bHrPPTWF1YOCawrft3g/02crPdXnQADuLD8YELDQx3P/xTnPzLt4KtZw0mMA1t2Y98ycPxhCmO/fEft3+zmc4YSfbvbNMvzQAp91yPnK+sRZQ2anTpmOH2cTA0aRJ7pZHh89rMuhQ+OPyQ+OLsiLMS568M+5DVmbB21Z1yv9gWiM5mJU8eQEwJQBmErkEjECcYjA4KV+kwB+QjD/kUrY4t9Bu/Zh355hP+Ce7Icf2dLncXoHnC6XKFnzjs9l17D73OPzyEllLVkgzhLgGdJmsRdI7Igp0WwFgtyV6FEpQEq0fyNIxedMDuH17ME9bDFeJSWymZvZHLxpM97Ca3xPfOllchFR1SdGLyse5OLu3ZBzC3egT9HXBCxX3puhHxuMrjS9/Pp12y99rdL2UtkAML5HJfSyVCV2T/RWIWLtbgTNM8eEZ/I5UXOR+i1b2FPpRr43wZhOu8DTyJHwxEfbFY0H1O6/o19YbtB74LI6EoDu0yhBItIhNbLDFRL8o1jYW0qMdIj5qpYWrnMoq0au6JlMJYa8OE7pIB1azjJY2iL8r1r1myLAWYiq7bSy5VSQo9iTfX2AfY098YuKhxTCPtrMLmPjZjzAUqxGUcfg16V86iXOE6jxEKM9UCLiN/hRaxikf3OYJL7IMN8jaxH14pGQ4dboSMnwqKh5o0Tb4Y7QdvVIVveF89Z7RLlA6lke7r0F8rdJHpK7bovgTrUDyUG8sJ79wf48hxfqtihb8GesP5nJYZ1hY2mT5C4iOC028htAm/EjZ862k1n0NZ9ue7v0lgc/ljE6v7/+3iNHeozMKF4fILkrQyYdj3btVd4/vSDAGJrvyd6BE2fK2fLdmSWxFCGg07fpE2mzvMbaPwaiKCF3g3ZnvvbZ4LiL3+Gd/llpSS+nhqis0dGmjAzliPXBVLQiKWlFUeGq5ORVZIHmRV6TfGt3Mv53cXlJ5cQplQUUTXxg4hT+NH9sTV7O9vHjt+eMqR6r4PyavNxt48dvyx1TM1aMK6MUKZ1AOrvvaCWtt6TSnpYfpBOs1zHW6yDejXdB7HselAyQTkgpONpm40LqSpQmBdC/dTocxCPiTdCbpMuyUURcsR6DrKH9QDvzEwNkZhl7vp/J7Uk3kze7VCYblQ9mYoNH7GDzeSktMN6dfTqTQ2i6IF2WfhcQnEGL88CrEXO1To67mfrhhDIF2rcMx3ub3KTfzecGx7tjw0zlAxI4k33mERckjeRjyqUpTdoG2jAEJYh+SdXvCoHjxrsTEVLuIiY1tfH5NkJrfw3zcbEf1lNP6xkfvbo2tc/gJQtixkX2wh26JlaOnrra9N6F5GU5/eMMg4f2kDzHHdtQ8t2yCWuwm9v6UvdkU3LmwPv6RsN2/wNXf19kYXVPmMaX+ATmR817bxWWmzwClDOVMwcUHflq2ZbG5ypSZs6YW6Yse/XFiTty47Ldia4LsA5qD2aTRfJc5IuGaDW6IM2ru7ezYEPMvqFqtBVrvzZHAscdyCoLmZpWXpEwYxgZVOdRfmjOY68UHtw1vjyg4Bie2zB5RXRUVVnOan8ZzsgVRIbPzI8uj1ulfG3Ii55/cdKjr/bVdc+fG5O/Y7wyqmTL8OErRhtDEEa5bKyUL5eougLmXLhU7CFS/iP/fuTQF9PgIz5ySWPHHrqqxod70B/xlHNTZ9RXco4+bJpLP4U2CUWJjhy5qpZFW0cVDCqT1nGhU4uHiSyyYNrehMyoBTm5FYYpZQe3FCWExd9/Yua0o/FZUUtzcuf4VZQdrJmQEB47qTY0cIhxxwb4sx0OTQTN9g8YFRcQY+wXtmZe5nI//4qUcSuTooNnDhiUlhAYHeZlXPNg5jJ//ynDxq9MVt7oP35AZGJ0SP/xg4wJsYjC2G6U5spXQQYDUGTrr1a5ajjTbE8TJklzC1mPBtf+sXTpH7W1fy9b9ndd+uTQFMMov4ypk3PCsr0TBszJeejpcTsyqi8VF1+q3nqpqPh5+eph9l1tLfvu8GHcu7YW9z78l8EwwbPPos2rl/T3LPGJeOnC4iN5D236tXrrrxs3/rq1+tdNSEKF+EspE+jtArZjAAp1PEMUQ1wdyNIPEWaet8Eb+pmrd3fREmTspv+sXfufTZu+Xzdq04Xy2fXl5fWzZ58vLz+/9UZ6RO2q3eGzTkTFRsbJVzd8v3nTd+vWfbep4sLmjKIZF2fPenb69Gdnzb44Y+nRuFFdfvn0UxIyptY/OAth5EZyxRcse6lfW+vf3+hN4aeH2Kbh7Qw/sIJzkco9FnbDBOsKVs7WUUycZ/e5WvUq+XBynlxi+Qe/M7hsiPIUGTG4bDAbTB5TSsljM5R3yBD+JQo6id4nTk+5t3nKXHNQG7+Ws72wcHtO1vaiou1ZAVkhIVkByZWVcGB0U2np5tQRmx64f2Pqg/65CYljBhTfPxEsIdJROUIO6jsgqs5T5OBOfYcb+5wmIETIfU2h5IAuXczqIteFlziwc+dOXboSSV41n+R/EcJ4KiqgiSRG/U4frJnBp8fPlpJHjh6FRTiJObeorm7ROV5yOnai8XiN3aaJZ4F4TVUVIgBjB40ntNmGkNX8QfhDNojQJUv+WLKEr2/6glZxtWqVsaisDc3idRfNgv+rqkj5RquKaA7zvb0uIt//H6gt6ZH2luQxznr2Kz2s2yglo+9ts5xyAfZGzNcVQ9oPtjSWrhzBdfoOkgFnqhFPnKnuE2g4IXqFyBF+K7jf2IcQ0eFMeJOuX25Kxz/LW0VbdURdrDYOv3B3DP0E4xslu6Wg3VIHaYV5ye7d9C9LJ3lr40VdIr+UiFolSJd4axaZQaYiesu1KZ1kCGhO4ptZWji3Tu2mTzkAcQCAiPIwQKgDCLL48pWtLgvWVmxZSbJMg9UYgdXYAOhHESiO44W4TvdAAusxKk7lQS/WgfYO9SBGzYIshjSvyDCgMgKiNzNrDw2bf37NkJG7l42Kn/d44dq8DTWl8/YviVcXZ4mzkzeI5RmppFlK70HEX4mBldrnHQKTBp1JHzNAx/zcRlZWFxTvXTCy4yuXqEv40HPJCc6ULOartZ1T7sM+5ivKc50Sqkozt5FTnWbw9RpeDyEvFvApzuD2ssWIHgUrOBG52L+vpn5d02oPs7FijbGHpu0RCw5isK402Ey41HUHwjd/BihlAKW3FYoWkgaa8s8ey3kbQAeYWrga2MR8RcT5PkI61LU5zqcx1+1BPnYf/pW57GE9W8b1VrCOm1kX/Mdm/DciFu+21xxq7Nu+5qA3Z6Pj9AtpqN37w0vaSzdHuqWhmiA3VS41xZPJ8nJeS/RJvl2NXxBlNSiXpNQo8wVX/rd+gkkaHoUfxv9ewdzYBXGTL6xjPff3BY6bUD5wvFHdO5etrnh81dsAOseyeRh1s3xvGW9/lDYy0zFmWs4N1hXNj8BFHUCKtELqhlCiHZbmFqkF2X7oWkRI+ssdIjn1conVQ+UtVgEwGKCZwGrBeiyHerVyt/4TvZhd6+3j407GK4d8Y92x+2Lla/m5e7/8O0G75eFKBXvVw9fdZXvPKE/2agUpGbF9O41w9MFaSpGTNNYWD07sjkVPaRkPHsEXgpaTcsTtosF1fH14jnSrJb6to8GINvSEvhgpcHQUJ3GtWNoMPpsrVGz697RR6Lvh7XjHgDTXyemgtSbJW6VkXGzTyY0YNGsEpKXgIvNoW+o/55vS0ccitRD0sEgFHr6G+XmWfFjw4OzIA4VBZXnQ0kj1lnL5Jn0UpHyv5fq3O2V8lnkzrzoSXUvClddrlReewl/hL/GYxod0s/j8amLv0Pf+p3pRr1Lx85304oFFzXpR+dhDOcVl/D/Xinmvsh1qE/C9OznATaSGm5T/ET9WdU/bpe61bOm3/6/pfS2HpKNmCrCOnACrhrWPHI2GtQ2bzzX61d5j8Zca/WobIQBLfGnBcYRogDoODwf97TgiHFU5Hwm7QdvGy8thJDwgerfgpelf9HFZVr+WlYkBfagTpY9bJlpK6WO0k+Uvyz+yrLxcqzxPEmqVV/C3+GvmCXGziShfwtJGgDXJNn4aeoD23ANpKXhy86iyrEHONFu6InXGSxGSvuXxNeA6gUaquw9F5M6AQ9X9d3iZcgRBiRvfQq2bUCsFLxewVGoR+5gutUcTVX8Vd7Y3gcuKvjbOQqmyjq5aIxxXyvFFZFGtpVO0PjYBcUlD3UioK8axXbfLzUD+tsckLYUt4Wmjk1EOoIHDFPwSrad9pM7oPyqHiJgPW/0KY9GkdvsVRGhe/Gq8YiFWX1kMhV8XGDnezW6Hdroces3auGpQWPrQrh7ZLd1q+arDrcTQyS80ZWDYnic3hfeN9rF5JtrpltD3jhwad2BTP61vTnjrepYtWxmWlO7TwVzAfRVWvwW04glo24XSFeuOScE/BTYpv7t27yQB9xRkQbmYRLgYVEUoPGLF1K8izD/WlFIyLGlCiinW398UmVw6PCQ5Mm6cLQVyJySlbprcTTpBPJWvF2N3/yG+vkP82TVyPbHYz2Ty45f30CFeZL/sExToMTA2diBPypgWTHyUvcreChw5KMh1u2vQIByJsGU5fp0upV4owGFnt2MT2ZuK6jXbvEdnlqW0FnlgWsbkkY6bvuFXK0D1dyIiN/ORs1QJ8ipA5UCDo5Ba3dXohlao2rsLxs0CJff4RYcnl6QED4uIyx+WVJJsivNTJThsQkp0nN8AeC5O0qQLyW7pNzncPyY6uSRJlblfXNRwtQbIX6QPK4H0KY7yzxZSf1LyCQiwS90nNNTHEB7RX9MKyWoztXWRZa0aCBEYf5PoAvl31IHbkImgMrH4HhFYUP70gPkW2yW8vTtxH0kHFiuZyz2+5vk1NXw/XS34Y/PkNaCJTOa14ms8psuQjqdSE02UPXR6nGs9yzyd/kjjpQcgJU9NgTJzIeUapIzhKSL6GApRwcN3iT5aLX4s0RcscfSFG/PVO5m0i1Xscgw8SiZuMvBLRGe18FGiBqI1Oqt8tRMgaGoCj0AVLpEPg67eYNWkEtvrQCmKd6TOmdZZ0uHaq6FKS43kyK1q9XvBZYMhvWxJV760pOsMAsZz2+Ef+dkOgWj5UVvOzgmp3wnl6VJRsAUPD9ksMwceBHYXDeYsFakWJUDiOMlBgJSCt9r3YFDS0QGWRhpkLKlUtsPlIFoHaDV2aEQLDWBp4QAMv+02vrgE2A6NBHhJ+L4XSEAZvnMnj+jquzYOFeXwFOllukBTDi5rm9uospaj9a3K0Tf5fzagKYcatfCyreUaHcvpzSYEspSu2NtY7MjSyMe6xgMtDft9Y4nBAGrFAMPPyNWM2SSZzC9LJnmk5SJNtFy0/MVVQtUSV2PApClTJgUYXZdI0VfZ/sX4Ahu+GBfbEJNO1vtHYriv6z3UrWbu3Bq30F7r2BK8okIZwLpV4BViv4KGPj7W2qRHehnEBKLCvwr8VT3DAh+orHwgMKxnFV1wW1RI4tzTZ+3Q3Zv5bgnflzML3MoFtw7JBczcikuyWtWFb7AwG490ciuEFSIF38Q3EZIt0zWccYulewvunIhVxsDbIOlD8yCL2Y5CirrK9lVxmVbhCQ4McugtZSjhvg5tbMdjtONQPoe58fM6TVvZ4P7k2B5aiaHENuXVjTynDCPPsb8FyVXNgqq6g3SQaA+tTHoBfFA4XqpEMPbVTm3x5ipppSwrJWyKaA78Jgtl7o5Tkh/XSK52yVS0ml6Ipod1UXWU1iIRIxCfcgALSoccbwUKUU1/ckI9YNzxbUcYO5L++q058qYr9uZUqa7CHv7Bvr7B/uwb4ndnmqmm7ziJ9gQ8zRLCoBx70J8aDHYM5DP7owNsTY8kmn7iZIfJobF4fMny8W1AIKLpE13UeloJUk/LW3QoW+QgQgHEkbOmJlsPkJLxLtsKw9ZCoIN3N0cchayrRclH7GuRJHvth7W1RbkU/KgmXnndDvMxe6oW+542sD/eJvZ9bWDf2wb2/W1iP2BLRRi/LfmSevkzEfFs+UVekhYQ6+KZXWpy6Z0gfxYd6GZKOv2Hy6DegdG83XrLznSb/D26V2hI9ct0or6X5hmvD4qJCQqIjcXTA2NiAgfHxsrOpsDB0dGDA022O9DwhexO3tfdI+ZI7Ucc8ozDhhnDEhN199g/9gelZ0qfU5POV8QhwMVDZVY5jic+s+UXyH1QRjRdFylyXWUDaRrFiobqIrceG8frdpV+ont1A0Xs3uAbIusNeOJo3Hkm7jiyUfop+7ffss8Dbwulj2iYbno7vg48Nr40IqI0Pq4sIqIsLjgqKjgkIkI33VgYGV4YFlYYHlkIp09Dh0ZHDw2NBuydZV+6X6cXWref9htltkgdeTs0PcG3X1DPKd4VqeFpcb4ewb0rDJWyb1Dw4MCwlJKgoIEBYdmZnJMR8nBaKr+OqNr7aanyH9JLHr6M581h3jQCeVr/nxbY69PdMbZJjhZmdp19f96w6fGmaYawPiO8QhPZ92Ge12o63G9KGDOwl2tJZ2dfbrP20iFao/tI0uPT0Id+53Eg+Xsao+8tMMt6X/w2nhnCSvW9Pxt3CHKnQG6ivptd/jdHstwAfbete1T5y3/SvXp3IX+Z733xJTW44wjFnIY7690/zt23L/djjnWB/AoN1RcB1vMcK6R01nWj+3Q3IeUpNcXGpU6HLyAO+4S0nBKdXsWMDWTpSsaydfox7P0QniufokCtPXf5KmbO1vvmsa+H/n/vNtYKAAAAAAEAAAAFAINF8JSAXw889QADB9AAAAAA2wktdwAAAADdVa6+8iv8GAlQCWAAAAAGAAIAAAAAAAB42mNgZGBg3/O3hoGBM+GT9rcNnAFAERTAqAkAkugF7njaldMDkCNhEIbh/s+2bRTOtm3btm3bZuFs27Zt28rk5k/m3rrMVs16d1JPfd2dMSJtk1rIHjzrHXkcI21rkR1mYCox2RRrcSUIs3GD9eICUhxrbc2DZ3nIt7iLpriIhqiF2UHIjegogZy2mWiOycGzfpHnsdc2CROwPAiHMBbn8T0ER3ELg2ztcR7KzrnBs0zyvGO9m3Yew0qcD8JgZERPDHW4jLk47jivQZBI21ztyEs4hvk4ggHoiFlYgpU4ibEYz/PLiJnIh6zIjILIhpJIiSzhWM/fOiIenrFlwAuT2Vosxm4s5BxKkdcB2Ykb9jrtqVujCzoDbMMMEhp7XTfZlPxIZkcvVHWuh7PM0pGlIWiHsxBAbScf2u7T77RnqwE12FYRX7EfPD+9LdI2IwJZGY0jbfNMIpdiPzXfgPs+4uIkfVXme8nL9OXZriK1YGukbd749Lf5n/vv6susNfVF8EzNl8zOk+vgZpbHYYyN2jzsSxe9bozRSE1/nfwN+J239cl338hApIuj5hzNYoAe75i3g4DFX96S8jJFKsp8qckgo4yVt/IXN2WbbCMbYq5sl8z8MwD+Fuut9VYSSlepz36KSnNJLmMjxI4QS1hUd9VTdddpPXs9+7zVjc2/z/9N6lmse+iCro/mTZ3R1ddz1LRcO3+k1u2MZJ7qbvVrt/FMFzPq/e8X6Xa6jZFETzCS/XmlxUimK5pr9WY92tWYapNv72Yx65NZzLvSL61PEWIDFj9x++a6p0pLBq7Ls85vZ60uq5TqseqtBqoEaoiKq6qofioFR+pKP1jFpdusNv8Dwsk8NgB42mzBA4wdURQA0Id5nD+8g9q2HdS2bds2gtq2bduMartBHdTGxnsOQqgO6oEGo3FoKlqAVqNt6CaOcVXcAI/Bu/EVfAs/xW/wZ2KTyqQ1GUzGkalkAVlNzpKH5C35SrPSyrQenUCn00V0Ld1BvxiGUcXobcw3bjDEKrImbBibyGawxWwdO8Rus0/c5il5fl6KD+eT+Ey+hK/nu/hRkUE0EOPEVHFKerKKrC9bya5ygFyiqMquaqr2qpcaqiao6WqROqeeaqJtXVF31av1Nn1Xv9Dv9TeTm9XNRuZm81EiSFRNDE4csJiVx6plNbU6WL2tYdYMa4t10XplfbSxHduZ7PJ2V3uuvffPr045Z5Cz3bnofHLLuE3dae4194VXyhvqrfX2e4/8VH5Rv6O/2t/r/4BCUBoqQE1oBK2hC/SFYTAepsBcWAbrYQcch29B7mBCsCI4GjwPvbBy2CmcGJ4Mf0Q8yhxVjkZHU6Ml0ZpoSzKvR1/idHGbeFW8N76Q9Eb8NH4Xf0shf3cFD0BwxAAAAGubZxufU5Latm3btm3b7qC2bdu2bQ6KXSLN7w5RixhL7CZuEF9JkSxIViNbkwPJCeRa8hz5kIpLeVQnagx1nvpEJ6YJuirdiF5FX6Ef0p+YsswQZiIzj3nIJmItthP7mINcXq4cN5Abxz3ia/ML+adCJCwWnoqa2FccKS4X14sHxKviA/Gl+ElKLGWQeKmuNEU6JaeSi8gN5X7ybHmv/FHhFUfJqhT6aw9ln5pZraQOV9f9vFe9pj7WEmqhVlirqbXTxmlbtCPaLT2j3lYfpI/Vp/53k37VyGUMNRabyc365krzppXG4qzw9yJWRaup9clOYKeyadu2y9nt7ZH2W4dwCjktnb7ODGe7c8cl3WruCPeYe8G97T6LkbE+sfeABeVBTdAV9AejwBSwFKwBp8B3L6k32XvmA3+7f9V/6L/yPwcJgigoHVQNugczgpXB5uBccDP4GiYJ2dAPC4ZVw5bh1vBJZEW1o4HRmugZzACLwPZwNFwLt8ND8Ay8Bh/CN/AbSorSIxYZKESlUUc0Ak1Hy9BW9BCnxizOj0vg6rgZ7oUH4zF4Cl6M1/0AyhMX1gAAAHjaY2BkYGA8xMTGkMBQwcAF5CEDZgYWACjvAbd42pSQxVmEMRBAH+5cccgNd3fngut13eV3HAqglq2BAqiAbpB8g+tGXzI+QCXXFFFQXAHkQLiAVnLChdRyJ1zEAvfCxfQV1AuX0FiwJlxKV4FfuJaRghs0F0B1wa2w9skyBiZn2CSIEcdFMcQAg4zQyxPprTggTgTFGglsAihtGdZ/O9gYJJ84pO0X8XCJY2DjoOjQfl1MHKbop58YCa3hEaSPEAYZ+nExyOKQ4ox+JNJrnM5vY2+85r1H5Ik80gSwGaWPAZ39NMscsMLSE332+Wbd+8n+91jqk/YREWwcEroC9RY9j4jSI+mQQwibBCYuDn3ad5o+DGxi9LPNGhs8LpwhFWYeAJG3V+0AeNpjYGYAg/9zGIyAFCMDGgAAKpQB0gAA) - format('woff'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, - U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, - U+FEFF, U+FFFD; -} - -.graphiql-container *{box-sizing:border-box}.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal{--color-primary: 320, 95%, 43%;--color-secondary: 242, 51%, 61%;--color-tertiary: 188, 100%, 36%;--color-info: 208, 100%, 46%;--color-success: 158, 60%, 42%;--color-warning: 36, 100%, 41%;--color-error: 13, 93%, 58%;--color-neutral: 219, 28%, 32%;--color-base: 219, 28%, 100%;--alpha-secondary: .76;--alpha-tertiary: .5;--alpha-background-heavy: .15;--alpha-background-medium: .1;--alpha-background-light: .07;--font-family: "Roboto", sans-serif;--font-family-mono: "Fira Code", monospace;--font-size-hint:.75rem;--font-size-inline-code:.8125rem;--font-size-body:.9375rem;--font-size-h4:1.125rem;--font-size-h3:1.375rem;--font-size-h2:1.8125rem;--font-weight-regular: 400;--font-weight-medium: 500;--line-height: 1.5;--px-2: 2px;--px-4: 4px;--px-6: 6px;--px-8: 8px;--px-10: 10px;--px-12: 12px;--px-16: 16px;--px-20: 20px;--px-24: 24px;--border-radius-2: 2px;--border-radius-4: 4px;--border-radius-8: 8px;--border-radius-12: 12px;--popover-box-shadow: 0px 6px 20px rgba(59, 76, 106, .13), 0px 1.34018px 4.46726px rgba(59, 76, 106, .0774939), 0px .399006px 1.33002px rgba(59, 76, 106, .0525061);--popover-border: none;--sidebar-width: 60px;--toolbar-width: 40px;--session-header-height: 51px}@media (prefers-color-scheme: dark){body:not(.graphiql-light) .graphiql-container,body:not(.graphiql-light) .CodeMirror-info,body:not(.graphiql-light) .CodeMirror-lint-tooltip,body:not(.graphiql-light) reach-portal{--color-primary: 338, 100%, 67%;--color-secondary: 243, 100%, 77%;--color-tertiary: 188, 100%, 44%;--color-info: 208, 100%, 72%;--color-success: 158, 100%, 42%;--color-warning: 30, 100%, 80%;--color-error: 13, 100%, 58%;--color-neutral: 219, 29%, 78%;--color-base: 219, 29%, 18%;--popover-box-shadow: none;--popover-border: 1px solid hsl(var(--color-neutral))}}body.graphiql-dark .graphiql-container,body.graphiql-dark .CodeMirror-info,body.graphiql-dark .CodeMirror-lint-tooltip,body.graphiql-dark reach-portal{--color-primary: 338, 100%, 67%;--color-secondary: 243, 100%, 77%;--color-tertiary: 188, 100%, 44%;--color-info: 208, 100%, 72%;--color-success: 158, 100%, 42%;--color-warning: 30, 100%, 80%;--color-error: 13, 100%, 58%;--color-neutral: 219, 29%, 78%;--color-base: 219, 29%, 18%;--popover-box-shadow: none;--popover-border: 1px solid hsl(var(--color-neutral))}:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal),:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal):is(button){color:hsla(var(--color-neutral),1);font-family:var(--font-family);font-size:var(--font-size-body);font-weight:var(----font-weight-regular);line-height:var(--line-height)}:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal) input{color:hsla(var(--color-neutral),1);font-family:var(--font-family);font-size:var(--font-size-caption)}:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal) input::placeholder{color:hsla(var(--color-neutral),var(--alpha-secondary))}:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal) a{color:hsl(var(--color-primary))}:is(.graphiql-container,.CodeMirror-info,.CodeMirror-lint-tooltip,reach-portal) a:focus{outline:hsl(var(--color-primary)) auto 1px}.graphiql-un-styled,button.graphiql-un-styled{all:unset;border-radius:var(--border-radius-4);cursor:pointer}:is(.graphiql-un-styled,button.graphiql-un-styled):hover{background-color:hsla(var(--color-neutral),var(--alpha-background-light))}:is(.graphiql-un-styled,button.graphiql-un-styled):active{background-color:hsla(var(--color-neutral),var(--alpha-background-medium))}:is(.graphiql-un-styled,button.graphiql-un-styled):focus{outline:hsla(var(--color-neutral),var(--alpha-background-heavy)) auto 1px}.graphiql-button,button.graphiql-button{background-color:hsla(var(--color-neutral),var(--alpha-background-light));border:none;border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),1);cursor:pointer;font-size:var(--font-size-body);padding:var(--px-8) var(--px-12)}:is(.graphiql-button,button.graphiql-button):hover,:is(.graphiql-button,button.graphiql-button):active{background-color:hsla(var(--color-neutral),var(--alpha-background-medium))}:is(.graphiql-button,button.graphiql-button):focus{outline:hsla(var(--color-neutral),var(--alpha-background-heavy)) auto 1px}.graphiql-button-success:is(.graphiql-button,button.graphiql-button){background-color:hsla(var(--color-success),var(--alpha-background-heavy))}.graphiql-button-error:is(.graphiql-button,button.graphiql-button){background-color:hsla(var(--color-error),var(--alpha-background-heavy))}.graphiql-button-group{background-color:hsla(var(--color-neutral),var(--alpha-background-light));border-radius:calc(var(--border-radius-4) + var(--px-4));display:flex;padding:var(--px-4)}.graphiql-button-group>button.graphiql-button{background-color:transparent}.graphiql-button-group>button.graphiql-button:hover{background-color:hsla(var(--color-neutral),var(--alpha-background-light))}.graphiql-button-group>button.graphiql-button.active{background-color:hsl(var(--color-base));cursor:default}.graphiql-button-group>*+*{margin-left:var(--px-8)}:root{--reach-dialog: 1}[data-reach-dialog-overlay]{background:hsla(0,0%,0%,.33);position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto}[data-reach-dialog-content]{width:50vw;margin:10vh auto;background:white;padding:2rem;outline:none}[data-reach-dialog-overlay]{align-items:center;background-color:hsla(var(--color-neutral),var(--alpha-background-heavy));display:flex;justify-content:center;z-index:10}[data-reach-dialog-content]{background-color:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-12);box-shadow:var(--popover-box-shadow);margin:0;max-height:80vh;max-width:80vw;overflow:auto;padding:0;width:unset}.graphiql-dialog-close>svg{color:hsla(var(--color-neutral),var(--alpha-secondary));display:block;height:var(--px-12);padding:var(--px-12);width:var(--px-12)}:root{--reach-listbox: 1}[data-reach-listbox-popover]{display:block;position:absolute;min-width:-moz-fit-content;min-width:-webkit-min-content;min-width:min-content;padding:.25rem 0;background:hsl(0,0%,100%);outline:none;border:solid 1px hsla(0,0%,0%,.25)}[data-reach-listbox-popover]:focus-within{box-shadow:0 0 4px Highlight;outline:-webkit-focus-ring-color auto 4px}[data-reach-listbox-popover][hidden]{display:none}[data-reach-listbox-list]{margin:0;padding:0;list-style:none}[data-reach-listbox-list]:focus{box-shadow:none;outline:none}[data-reach-listbox-option]{display:block;margin:0;padding:.25rem .5rem;white-space:nowrap;user-select:none}[data-reach-listbox-option][data-current-nav]{background:hsl(211,81%,46%);color:#fff}[data-reach-listbox-option][data-current-selected]{font-weight:bolder}[data-reach-listbox-option][data-current-selected][data-confirming]{animation:flash .1s;animation-iteration-count:1}[data-reach-listbox-option][aria-disabled=true]{opacity:.5}[data-reach-listbox-button]{display:inline-flex;align-items:center;justify-content:space-between;padding:1px 10px 2px;border:1px solid;border-color:rgb(216,216,216) rgb(209,209,209) rgb(186,186,186);cursor:default;user-select:none}[data-reach-listbox-button][aria-disabled=true]{opacity:.5}[data-reach-listbox-arrow]{margin-left:.5rem;display:block;font-size:.5em}[data-reach-listbox-group-label]{display:block;margin:0;padding:.25rem .5rem;white-space:nowrap;user-select:none;font-weight:bolder}@keyframes flash{0%{background:hsla(211,81%,36%,1);color:#fff;opacity:1}50%{opacity:.5;background:inherit;color:inherit}to{background:hsla(211,81%,36%,1);color:#fff;opacity:1}}:root{--reach-menu-button: 1}[data-reach-menu]{position:relative}[data-reach-menu-popover]{display:block;position:absolute}[data-reach-menu-popover][hidden]{display:none}[data-reach-menu-list],[data-reach-menu-items]{display:block;white-space:nowrap;border:solid 1px hsla(0,0%,0%,.25);background:hsla(0,100%,100%,.99);outline:none;padding:1rem 0;font-size:85%}[data-reach-menu-item]{display:block;user-select:none}[data-reach-menu-item]{cursor:pointer;display:block;color:inherit;font:inherit;text-decoration:initial;padding:5px 20px}[data-reach-menu-item][data-selected]{background:hsl(211,81%,36%);color:#fff;outline:none}[data-reach-menu-item][aria-disabled]{opacity:.5;cursor:not-allowed}[data-reach-listbox-popover],[data-reach-menu-list]{background-color:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-8);box-shadow:var(--popover-box-shadow);font-size:inherit;max-width:250px;padding:var(--px-4)}[data-reach-listbox-option],[data-reach-menu-item]{border-radius:var(--border-radius-4);font-size:inherit;margin:var(--px-4);overflow:hidden;padding:var(--px-6) var(--px-8);text-overflow:ellipsis;white-space:nowrap}[data-reach-listbox-option][data-selected],[data-reach-menu-item][data-selected],[data-reach-listbox-option][data-current-nav],[data-reach-menu-item][data-current-nav],[data-reach-listbox-option]:hover,[data-reach-menu-item]:hover{background-color:hsla(var(--color-neutral),var(--alpha-background-light));color:inherit}[data-reach-listbox-option]:not(:first-child),[data-reach-menu-item]:not(:first-child){margin-top:0}[data-reach-listbox-button]{border:none;cursor:pointer;padding:0}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) blockquote{margin-left:0;margin-right:0;padding-left:var(--px-8)}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) code,:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) pre{border-radius:var(--border-radius-4);font-family:var(--font-family-mono);font-size:var(--font-size-inline-code)}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) code{padding:var(--px-2)}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) pre{overflow:auto;padding:var(--px-6) var(--px-8)}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) pre code{background-color:initial;border-radius:0;padding:0}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) ol,:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) ul{padding-left:var(--px-16)}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) ol{list-style-type:decimal}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) ul{list-style-type:disc}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation) img{border-radius:var(--border-radius-4);max-height:120px;max-width:100%}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation)>:first-child{margin-top:0}:is(.graphiql-markdown-description,.graphiql-markdown-deprecation,.CodeMirror-hint-information-description,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-description,.CodeMirror-info .info-deprecation)>:last-child{margin-bottom:0}:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description) a{color:hsl(var(--color-primary));text-decoration:none}:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description) a:hover{text-decoration:underline}:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description) blockquote{border-left:1.5px solid hsla(var(--color-neutral),var(--alpha-tertiary))}:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description) code,:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description) pre{background-color:hsla(var(--color-neutral),var(--alpha-background-light));color:hsla(var(--color-neutral),1)}:is(.graphiql-markdown-description,.CodeMirror-hint-information-description,.CodeMirror-info .info-description)>*{margin:var(--px-12) 0}:is(.graphiql-markdown-deprecation,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation) a{color:hsl(var(--color-warning));text-decoration:underline}:is(.graphiql-markdown-deprecation,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation) blockquote{border-left:1.5px solid hsl(var(--color-warning))}:is(.graphiql-markdown-deprecation,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation) code,:is(.graphiql-markdown-deprecation,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation) pre{background-color:hsla(var(--color-warning),var(--alpha-background-heavy))}:is(.graphiql-markdown-deprecation,.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation)>*{margin:var(--px-8) 0}.graphiql-markdown-preview>:not(:first-child){display:none}.CodeMirror-hint-information-deprecation,.CodeMirror-info .info-deprecation{background-color:hsla(var(--color-warning),var(--alpha-background-light));border:1px solid hsl(var(--color-warning));border-radius:var(--border-radius-4);color:hsl(var(--color-warning));margin-top:var(--px-12);padding:var(--px-6) var(--px-8)}.CodeMirror-hint-information-deprecation-label,.CodeMirror-info .info-deprecation-label{font-size:var(--font-size-hint);font-weight:var(--font-weight-medium)}.CodeMirror-hint-information-deprecation-reason,.CodeMirror-info .info-deprecation-reason{margin-top:var(--px-6)}.graphiql-spinner{height:56px;margin:auto;margin-top:var(--px-16);width:56px}.graphiql-spinner:after{animation:rotation .8s linear 0s infinite;border:4px solid transparent;border-radius:100%;border-top:4px solid hsla(var(--color-neutral),var(--alpha-tertiary));content:"";display:inline-block;height:46px;vertical-align:middle;width:46px}@keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:root{--reach-tooltip: 1}[data-reach-tooltip]{z-index:1;pointer-events:none;position:absolute;padding:.25em .5em;box-shadow:2px 2px 10px #0000001a;white-space:nowrap;font-size:85%;background:#f0f0f0;color:#444;border:solid 1px #ccc}[data-reach-tooltip]{background:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-4);box-shadow:var(--popover-box-shadow);color:hsl(var(--color-neutral));font-size:inherit;padding:var(--px-4) var(--px-6)}.graphiql-tabs{display:flex;overflow-x:auto;padding:var(--px-12)}.graphiql-tabs>:not(:first-child){margin-left:var(--px-12)}.graphiql-tab{align-items:stretch;border-radius:var(--border-radius-8);color:hsla(var(--color-neutral),var(--alpha-secondary));display:flex}.graphiql-tab>button.graphiql-tab-close{visibility:hidden}.graphiql-tab.graphiql-tab-active>button.graphiql-tab-close,.graphiql-tab:hover>button.graphiql-tab-close,.graphiql-tab:focus-within>button.graphiql-tab-close{visibility:unset}.graphiql-tab.graphiql-tab-active{background-color:hsla(var(--color-neutral),var(--alpha-background-heavy));color:hsla(var(--color-neutral),1)}button.graphiql-tab-button{padding:var(--px-4) 0 var(--px-4) var(--px-8)}button.graphiql-tab-close{align-items:center;display:flex;padding:var(--px-4) var(--px-8)}button.graphiql-tab-close>svg{height:var(--px-8);width:var(--px-8)}.graphiql-history-header{font-size:var(--font-size-h2);font-weight:var(--font-weight-medium)}.graphiql-history-items{margin:var(--px-16) 0 0;list-style:none;padding:0}.graphiql-history-item{border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),var(--alpha-secondary));display:flex;font-size:var(--font-size-inline-code);font-family:var(--font-family-mono);height:34px}.graphiql-history-item:hover{color:hsla(var(--color-neutral),1);background-color:hsla(var(--color-neutral),var(--alpha-background-light))}.graphiql-history-item:not(:first-child){margin-top:var(--px-4)}.graphiql-history-item.editable{background-color:hsla(var(--color-primary),var(--alpha-background-medium))}.graphiql-history-item.editable>input{background:transparent;border:none;flex:1;margin:0;outline:none;padding:0 var(--px-10);width:100%}.graphiql-history-item.editable>input::placeholder{color:hsla(var(--color-neutral),var(--alpha-secondary))}.graphiql-history-item.editable>button{color:hsl(var(--color-primary));padding:0 var(--px-10)}.graphiql-history-item.editable>button:active{background-color:hsla(var(--color-primary),var(--alpha-background-heavy))}.graphiql-history-item.editable>button:focus{outline:hsl(var(--color-primary)) auto 1px}.graphiql-history-item.editable>button>svg{display:block}button.graphiql-history-item-label{flex:1;padding:var(--px-8) var(--px-10);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}button.graphiql-history-item-action{align-items:center;color:hsla(var(--color-neutral),var(--alpha-secondary));display:flex;padding:var(--px-8) var(--px-6)}button.graphiql-history-item-action:hover{color:hsla(var(--color-neutral),1)}button.graphiql-history-item-action>svg{height:14px;width:14px}.graphiql-history-item-spacer{height:var(--px-16)}.graphiql-doc-explorer-default-value{color:hsl(var(--color-success))}a.graphiql-doc-explorer-type-name{color:hsl(var(--color-warning));text-decoration:none}a.graphiql-doc-explorer-type-name:hover{text-decoration:underline}a.graphiql-doc-explorer-type-name:focus{outline:hsl(var(--color-warning)) auto 1px}.graphiql-doc-explorer-argument>*+*{margin-top:var(--px-12)}.graphiql-doc-explorer-argument-name{color:hsl(var(--color-secondary))}.graphiql-doc-explorer-argument-deprecation{background-color:hsla(var(--color-warning),var(--alpha-background-light));border:1px solid hsl(var(--color-warning));border-radius:var(--border-radius-4);color:hsl(var(--color-warning));padding:var(--px-8)}.graphiql-doc-explorer-argument-deprecation-label{font-size:var(--font-size-hint);font-weight:var(--font-weight-medium)}.graphiql-doc-explorer-deprecation{background-color:hsla(var(--color-warning),var(--alpha-background-light));border:1px solid hsl(var(--color-warning));border-radius:var(--px-4);color:hsl(var(--color-warning));padding:var(--px-8)}.graphiql-doc-explorer-deprecation-label{font-size:var(--font-size-hint);font-weight:var(--font-weight-medium)}.graphiql-doc-explorer-directive{color:hsl(var(--color-secondary))}.graphiql-doc-explorer-section-title{align-items:center;display:flex;font-size:var(--font-size-hint);font-weight:var(--font-weight-medium);line-height:1}.graphiql-doc-explorer-section-title>svg{height:var(--px-16);margin-right:var(--px-8);width:var(--px-16)}.graphiql-doc-explorer-section-content{margin-left:var(--px-8);margin-top:var(--px-16)}.graphiql-doc-explorer-section-content>*+*{margin-top:var(--px-16)}.graphiql-doc-explorer-root-type{color:hsl(var(--color-info))}:root{--reach-combobox: 1}[data-reach-combobox-popover]{border:solid 1px hsla(0,0%,0%,.25);background:hsla(0,100%,100%,.99);font-size:85%}[data-reach-combobox-list]{list-style:none;margin:0;padding:0;user-select:none}[data-reach-combobox-option]{cursor:pointer;margin:0;padding:.25rem .5rem}[data-reach-combobox-option][aria-selected=true]{background:hsl(211,10%,95%)}[data-reach-combobox-option]:hover{background:hsl(211,10%,92%)}[data-reach-combobox-option][aria-selected=true]:hover{background:hsl(211,10%,90%)}[data-suggested-value]{font-weight:700}[data-reach-combobox]{color:hsla(var(--color-neutral),var(--alpha-secondary))}[data-reach-combobox]:not([data-state="idle"]){border:var(--popover-border);border-radius:var(--border-radius-4);box-shadow:var(--popover-box-shadow);color:hsla(var(--color-neutral),1)}[data-reach-combobox]:not([data-state="idle"]) .graphiql-doc-explorer-search-input{background:hsl(var(--color-base));border-bottom-left-radius:0;border-bottom-right-radius:0}.graphiql-doc-explorer-search-input{align-items:center;background-color:hsla(var(--color-neutral),var(--alpha-background-light));border-radius:var(--border-radius-4);display:flex;padding:var(--px-8) var(--px-12)}[data-reach-combobox-input]{border:none;background-color:transparent;margin-left:var(--px-4);width:100%}[data-reach-combobox-input]:focus{outline:none}[data-reach-combobox-popover]{background-color:hsl(var(--color-base));border:none;border-bottom-left-radius:var(--border-radius-4);border-bottom-right-radius:var(--border-radius-4);border-top:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));max-height:400px;overflow-y:auto;position:relative}[data-reach-combobox-list]{font-size:var(--font-size-body);padding:var(--px-4)}[data-reach-combobox-option]{border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),var(--alpha-secondary));overflow-x:hidden;padding:var(--px-8) var(--px-12);text-overflow:ellipsis;white-space:nowrap}[data-reach-combobox-option][data-highlighted]{background-color:hsla(var(--color-neutral),var(--alpha-background-light))}[data-reach-combobox-option]:hover{background-color:hsla(var(--color-neutral),var(--alpha-background-medium))}[data-reach-combobox-option][data-highlighted]:hover{background-color:hsla(var(--color-neutral),var(--alpha-background-heavy))}[data-reach-combobox-option]+[data-reach-combobox-option]{margin-top:var(--px-4)}.graphiql-doc-explorer-search-type{color:hsl(var(--color-info))}.graphiql-doc-explorer-search-field{color:hsl(var(--color-warning))}.graphiql-doc-explorer-search-argument{color:hsl(var(--color-secondary))}.graphiql-doc-explorer-search-divider{color:hsla(var(--color-neutral),var(--alpha-secondary));font-size:var(--font-size-hint);font-weight:var(--font-weight-medium);margin-top:var(--px-8);padding:var(--px-8) var(--px-12)}.graphiql-doc-explorer-search-empty{color:hsla(var(--color-neutral),var(--alpha-secondary));padding:var(--px-8) var(--px-12)}a.graphiql-doc-explorer-field-name{color:hsl(var(--color-info));text-decoration:none}a.graphiql-doc-explorer-field-name:hover{text-decoration:underline}a.graphiql-doc-explorer-field-name:focus{outline:hsl(var(--color-info)) auto 1px}.graphiql-doc-explorer-item>:not(:first-child){margin-top:var(--px-12)}.graphiql-doc-explorer-argument-multiple{margin-left:var(--px-8)}.graphiql-doc-explorer-enum-value{color:hsl(var(--color-info))}.graphiql-doc-explorer-header{display:flex;justify-content:space-between;position:relative}.graphiql-doc-explorer-header:focus-within .graphiql-doc-explorer-title{visibility:hidden}.graphiql-doc-explorer-header:focus-within .graphiql-doc-explorer-back:not(:focus){color:transparent}.graphiql-doc-explorer-header-content{display:flex;flex-direction:column;min-width:0}.graphiql-doc-explorer-search{height:100%;position:absolute;right:0;top:0}.graphiql-doc-explorer-search:focus-within{left:0}.graphiql-doc-explorer-search [data-reach-combobox-input]{height:24px;width:4ch}.graphiql-doc-explorer-search [data-reach-combobox-input]:focus{width:100%}a.graphiql-doc-explorer-back{align-items:center;color:hsla(var(--color-neutral),var(--alpha-secondary));display:flex;text-decoration:none}a.graphiql-doc-explorer-back:hover{text-decoration:underline}a.graphiql-doc-explorer-back:focus{outline:hsla(var(--color-neutral),var(--alpha-secondary)) auto 1px}a.graphiql-doc-explorer-back:focus+.graphiql-doc-explorer-title{visibility:unset}a.graphiql-doc-explorer-back>svg{height:var(--px-8);margin-right:var(--px-8);width:var(--px-8)}.graphiql-doc-explorer-title{font-weight:var(--font-weight-medium);font-size:var(--font-size-h2);overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.graphiql-doc-explorer-title:not(:first-child){font-size:var(--font-size-h3);margin-top:var(--px-8)}.graphiql-doc-explorer-content>*{color:hsla(var(--color-neutral),var(--alpha-secondary));margin-top:var(--px-20)}.graphiql-doc-explorer-error{background-color:hsla(var(--color-error),var(--alpha-background-heavy));border:1px solid hsl(var(--color-error));border-radius:var(--border-radius-8);color:hsl(var(--color-error));padding:var(--px-8) var(--px-12)}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:transparent}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor{caret-color:transparent}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error,.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:white}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative;z-index:0}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors,.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:#ff06}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}.CodeMirror{height:100%;position:absolute;width:100%}.CodeMirror{font-family:var(--font-family-mono)}.CodeMirror,.CodeMirror-gutters{background:none;background-color:var(--editor-background, hsl(var(--color-base)))}.CodeMirror-linenumber{padding:0}.CodeMirror-gutters{border:none}.cm-s-graphiql{color:hsla(var(--color-neutral),var(--alpha-tertiary))}.cm-s-graphiql .cm-keyword{color:hsl(var(--color-primary))}.cm-s-graphiql .cm-def{color:hsl(var(--color-tertiary))}.cm-s-graphiql .cm-punctuation{color:hsla(var(--color-neutral),var(--alpha-tertiary))}.cm-s-graphiql .cm-variable{color:hsl(var(--color-secondary))}.cm-s-graphiql .cm-atom{color:hsl(var(--color-tertiary))}.cm-s-graphiql .cm-number{color:hsl(var(--color-success))}.cm-s-graphiql .cm-string{color:hsl(var(--color-warning))}.cm-s-graphiql .cm-builtin{color:hsl(var(--color-success))}.cm-s-graphiql .cm-string-2{color:hsl(var(--color-secondary))}.cm-s-graphiql .cm-attribute,.cm-s-graphiql .cm-meta{color:hsl(var(--color-tertiary))}.cm-s-graphiql .cm-property{color:hsl(var(--color-info))}.cm-s-graphiql .cm-qualifier{color:hsl(var(--color-secondary))}.cm-s-graphiql .cm-comment{color:hsla(var(--color-neutral),var(--alpha-secondary))}.cm-s-graphiql .cm-ws{color:hsla(var(--color-neutral),var(--alpha-tertiary))}.cm-s-graphiql .cm-invalidchar{color:hsl(var(--color-error))}.cm-s-graphiql .CodeMirror-cursor{border-left:2px solid hsla(var(--color-neutral),var(--alpha-secondary))}.cm-s-graphiql .CodeMirror-linenumber{color:hsla(var(--color-neutral),var(--alpha-tertiary))}div.CodeMirror span.CodeMirror-matchingbracket,div.CodeMirror span.CodeMirror-nonmatchingbracket{color:hsl(var(--color-warning))}.CodeMirror-selected,.CodeMirror-focused .CodeMirror-selected{background:hsla(var(--color-neutral),var(--alpha-background-heavy))}.CodeMirror-dialog{background:inherit;color:inherit;left:0;right:0;overflow:hidden;padding:var(--px-2) var(--px-6);position:absolute;z-index:6}.CodeMirror-dialog-top{border-bottom:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));padding-bottom:var(--px-12);top:0}.CodeMirror-dialog-bottom{border-top:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));bottom:0;padding-top:var(--px-12)}.CodeMirror-search-hint{display:none}.CodeMirror-dialog input{border:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));border-radius:var(--border-radius-4);padding:var(--px-4)}.CodeMirror-dialog input:focus{outline:hsl(var(--color-primary)) solid 2px}.cm-searching{background-color:hsla(var(--color-warning),var(--alpha-background-light));padding-bottom:1.5px;padding-top:.5px}.CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-open,.CodeMirror-foldgutter-folded{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25be"}.CodeMirror-foldgutter-folded:after{content:"\25b8"}.CodeMirror-foldgutter{width:var(--px-12)}.CodeMirror-foldmarker{background-color:hsl(var(--color-info));border-radius:var(--border-radius-4);color:hsl(var(--color-base));font-family:inherit;margin:0 var(--px-4);padding:0 var(--px-8);text-shadow:none}.CodeMirror-foldgutter-open,.CodeMirror-foldgutter-folded{color:hsla(var(--color-neutral),var(--alpha-tertiary))}.CodeMirror-foldgutter-open:after,.CodeMirror-foldgutter-folded:after{margin:0 var(--px-2)}.graphiql-editor{height:100%;position:relative;width:100%}.graphiql-editor.hidden{left:-9999px;position:absolute;top:-9999px;visibility:hidden}.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:#ffd;border:1px solid black;border-radius:4px;color:#000;font-family:monospace;font-size:10pt;overflow:hidden;padding:2px 5px;position:fixed;white-space:pre;white-space:pre-wrap;z-index:100;max-width:600px;opacity:0;transition:opacity .4s;-moz-transition:opacity .4s;-webkit-transition:opacity .4s;-o-transition:opacity .4s;-ms-transition:opacity .4s}.CodeMirror-lint-mark{background-position:left bottom;background-repeat:repeat-x}.CodeMirror-lint-mark-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=)}.CodeMirror-lint-mark-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==)}.CodeMirror-lint-marker{background-position:center center;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;width:16px;vertical-align:middle;position:relative}.CodeMirror-lint-message{padding-left:18px;background-position:top left;background-repeat:no-repeat}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=)}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=)}.CodeMirror-lint-marker-multiple{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:right bottom;width:100%;height:100%}.CodeMirror-lint-line-error{background-color:#b74c5114}.CodeMirror-lint-line-warning{background-color:#ffd3001a}.CodeMirror-lint-mark-error,.CodeMirror-lint-mark-warning{background-repeat:repeat-x;background-size:10px 3px;background-position:0 95%}.cm-s-graphiql .CodeMirror-lint-mark-error{color:hsl(var(--color-error))}.CodeMirror-lint-mark-error{background-image:linear-gradient(45deg,transparent 65%,hsl(var(--color-error)) 80%,transparent 90%),linear-gradient(135deg,transparent 5%,hsl(var(--color-error)) 15%,transparent 25%),linear-gradient(135deg,transparent 45%,hsl(var(--color-error)) 55%,transparent 65%),linear-gradient(45deg,transparent 25%,hsl(var(--color-error)) 35%,transparent 50%)}.cm-s-graphiql .CodeMirror-lint-mark-warning{color:hsl(var(--color-warning))}.CodeMirror-lint-mark-warning{background-image:linear-gradient(45deg,transparent 65%,hsl(var(--color-warning)) 80%,transparent 90%),linear-gradient(135deg,transparent 5%,hsl(var(--color-warning)) 15%,transparent 25%),linear-gradient(135deg,transparent 45%,hsl(var(--color-warning)) 55%,transparent 65%),linear-gradient(45deg,transparent 25%,hsl(var(--color-warning)) 35%,transparent 50%)}.CodeMirror-lint-tooltip{background-color:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-8);box-shadow:var(--popover-box-shadow);font-size:var(--font-size-body);font-family:var(--font-family);max-width:600px;overflow:hidden;padding:var(--px-12)}.CodeMirror-lint-message-error,.CodeMirror-lint-message-warning{background-image:none;padding:0}.CodeMirror-lint-message-error{color:hsl(var(--color-error))}.CodeMirror-lint-message-warning{color:hsl(var(--color-warning))}.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-webkit-box-shadow:2px 3px 5px rgba(0,0,0,.2);-moz-box-shadow:2px 3px 5px rgba(0,0,0,.2);box-shadow:2px 3px 5px #0003;border-radius:3px;border:1px solid silver;background:white;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;white-space:pre;color:#000;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:#fff}.CodeMirror-hints{background:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-8);box-shadow:var(--popover-box-shadow);display:grid;font-family:var(--font-family);font-size:var(--font-size-body);grid-template-columns:auto fit-content(300px);max-height:264px;padding:0}.CodeMirror-hint{border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),var(--alpha-secondary));grid-column:1 / 2;margin:var(--px-4);padding:var(--px-6) var(--px-8)!important}.CodeMirror-hint:not(:first-child){margin-top:0}li.CodeMirror-hint-active{background:hsla(var(--color-primary),var(--alpha-background-medium));color:hsl(var(--color-primary))}.CodeMirror-hint-information{border-left:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));grid-column:2 / 3;grid-row:1 / 99999;max-height:264px;overflow:auto;padding:var(--px-12)}.CodeMirror-hint-information-header{display:flex;align-items:baseline}.CodeMirror-hint-information-field-name{font-size:var(--font-size-h4);font-weight:var(--font-weight-medium)}.CodeMirror-hint-information-type-name-pill{border:1px solid hsla(var(--color-neutral),var(--alpha-tertiary));border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),var(--alpha-secondary));margin-left:var(--px-6);padding:var(--px-4)}.CodeMirror-hint-information-type-name{color:inherit;text-decoration:none}.CodeMirror-hint-information-type-name:hover{text-decoration:underline dotted}.CodeMirror-hint-information-description{color:hsla(var(--color-neutral),var(--alpha-secondary));margin-top:var(--px-12)}.CodeMirror-info{background-color:hsl(var(--color-base));border:var(--popover-border);border-radius:var(--border-radius-8);box-shadow:var(--popover-box-shadow);color:hsla(var(--color-neutral),1);max-height:300px;max-width:400px;opacity:0;overflow:auto;padding:var(--px-12);position:fixed;transition:opacity .15s;z-index:10}.CodeMirror-info a{color:inherit;text-decoration:none}.CodeMirror-info a:hover{text-decoration:underline dotted}.CodeMirror-info .CodeMirror-info-header{display:flex;align-items:baseline}.CodeMirror-info .CodeMirror-info-header>.type-name,.CodeMirror-info .CodeMirror-info-header>.field-name,.CodeMirror-info .CodeMirror-info-header>.arg-name,.CodeMirror-info .CodeMirror-info-header>.directive-name,.CodeMirror-info .CodeMirror-info-header>.enum-value{font-size:var(--font-size-h4);font-weight:var(--font-weight-medium)}.CodeMirror-info .type-name-pill{border:1px solid hsla(var(--color-neutral),var(--alpha-tertiary));border-radius:var(--border-radius-4);color:hsla(var(--color-neutral),var(--alpha-secondary));margin-left:var(--px-6);padding:var(--px-4)}.CodeMirror-info .info-description{color:hsla(var(--color-neutral),var(--alpha-secondary));margin-top:var(--px-12);overflow:hidden}.CodeMirror-jump-token{text-decoration:underline dotted;cursor:pointer}.auto-inserted-leaf.cm-property{animation-duration:6s;animation-name:insertionFade;border-radius:var(--border-radius-4);padding:var(--px-2)}@keyframes insertionFade{0%,to{background-color:none}15%,85%{background-color:hsla(var(--color-warning),var(--alpha-background-light))}}button.graphiql-toolbar-button{display:flex;align-items:center;justify-content:center;height:var(--toolbar-width);width:var(--toolbar-width)}button.graphiql-toolbar-button.error{background:hsla(var(--color-error),var(--alpha-background-heavy))}.graphiql-execute-button-wrapper{position:relative}button.graphiql-execute-button{background-color:hsl(var(--color-primary));border:none;border-radius:var(--border-radius-8);cursor:pointer;height:var(--toolbar-width);padding:0;width:var(--toolbar-width)}button.graphiql-execute-button:hover{background-color:hsla(var(--color-primary),.9)}button.graphiql-execute-button:active{background-color:hsla(var(--color-primary),.8)}button.graphiql-execute-button:focus{outline:hsla(var(--color-primary),.8) auto 1px}button.graphiql-execute-button>svg{color:#fff;display:block;height:var(--px-16);margin:auto;width:var(--px-16)}.graphiql-toolbar-listbox,button.graphiql-toolbar-menu{display:block;height:var(--toolbar-width);width:var(--toolbar-width)} - -.graphiql-container{background-color:hsl(var(--color-base));display:flex;height:100%;margin:0;overflow:hidden;width:100%}.graphiql-container .graphiql-sidebar{display:flex;flex-direction:column;justify-content:space-between;padding:var(--px-8);width:var(--sidebar-width)}.graphiql-container .graphiql-sidebar .graphiql-sidebar-section{display:flex;flex-direction:column;gap:var(--px-8)}.graphiql-container .graphiql-sidebar button{align-items:center;color:hsla(var(--color-neutral),var(--alpha-secondary));display:flex;height:calc(var(--sidebar-width) - var(--px-8)*2);justify-content:center;width:calc(var(--sidebar-width) - var(--px-8)*2)}.graphiql-container .graphiql-sidebar button.active{color:hsla(var(--color-neutral),1)}.graphiql-container .graphiql-sidebar button:not(:first-child){margin-top:var(--px-4)}.graphiql-container .graphiql-sidebar button>svg{height:var(--px-20);width:var(--px-20)}.graphiql-container .graphiql-main{display:flex;flex:1;min-width:0}.graphiql-container .graphiql-sessions{background-color:hsla(var(--color-neutral),var(--alpha-background-light));border-radius:calc(var(--border-radius-12) + var(--px-8));display:flex;flex:1;flex-direction:column;margin:var(--px-16);margin-left:0;max-height:100%;min-width:0}.graphiql-container .graphiql-session-header{align-items:center;display:flex;height:var(--session-header-height);justify-content:space-between}button.graphiql-tab-add{height:100%;padding:0 var(--px-4)}button.graphiql-tab-add>svg{color:hsla(var(--color-neutral),var(--alpha-secondary));display:block;height:var(--px-16);width:var(--px-16)}.graphiql-add-tab-wrapper{padding:var(--px-12) 0}.graphiql-container .graphiql-session-header-right{align-items:stretch;display:flex}.graphiql-container .graphiql-logo{color:hsla(var(--color-neutral),var(--alpha-secondary));font-size:var(--font-size-h4);font-weight:var(--font-weight-medium);padding:var(--px-12) var(--px-16)}.graphiql-container .graphiql-logo .graphiql-logo-link{color:hsla(var(--color-neutral),var(--alpha-secondary));text-decoration:none}.graphiql-container .graphiql-session{display:flex;flex:1;padding:0 var(--px-8) var(--px-8)}.graphiql-container .graphiql-editors{background-color:hsl(var(--color-base));border-radius:calc(var(--border-radius-12));box-shadow:var(--popover-box-shadow);display:flex;flex:1;flex-direction:column}.graphiql-container .graphiql-editors.full-height{margin-top:calc(var(--px-8) - var(--session-header-height))}.graphiql-container .graphiql-query-editor{border-bottom:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));display:flex;flex:1;padding:var(--px-16)}.graphiql-container .graphiql-query-editor-wrapper{display:flex;flex:1}.graphiql-container .graphiql-toolbar{margin-left:var(--px-16);width:var(--toolbar-width)}.graphiql-container .graphiql-toolbar>*+*{margin-top:var(--px-8)}.graphiql-toolbar-icon{color:hsla(var(--color-neutral),var(--alpha-tertiary));display:block;height:calc(var(--toolbar-width) - var(--px-8)*2);width:calc(var(--toolbar-width) - var(--px-8)*2)}.graphiql-container .graphiql-editor-tools{align-items:center;cursor:row-resize;display:flex;justify-content:space-between;padding:var(--px-8)}.graphiql-container .graphiql-editor-tools button{color:hsla(var(--color-neutral),var(--alpha-secondary))}.graphiql-container .graphiql-editor-tools button.active{color:hsla(var(--color-neutral),1)}.graphiql-container .graphiql-editor-tools-tabs{cursor:auto;display:flex}.graphiql-container .graphiql-editor-tools-tabs>button{padding:var(--px-8) var(--px-12)}.graphiql-container .graphiql-editor-tools-tabs>button+button{margin-left:var(--px-8)}.graphiql-container .graphiql-editor-tool{flex:1;padding:var(--px-16)}.graphiql-container .graphiql-editor-tool,.graphiql-container .graphiql-editor-tools,.graphiql-container .graphiql-toolbar{position:relative}.graphiql-container .graphiql-response{--editor-background:transparent;display:flex;flex:1;flex-direction:column;position:relative}.graphiql-container .graphiql-response .result-window{flex:1;position:relative}.graphiql-container .graphiql-footer{border-top:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy))}.graphiql-container .graphiql-plugin{border-left:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));flex:1;overflow-y:auto;padding:var(--px-16)}.graphiql-container .graphiql-horizontal-drag-bar{cursor:col-resize;width:var(--px-12)}.graphiql-container .graphiql-horizontal-drag-bar:hover:after{border:var(--px-2) solid hsla(var(--color-neutral),var(--alpha-background-heavy));border-radius:var(--border-radius-2);content:"";display:block;height:25%;margin:0 auto;position:relative;top:37.5%;width:0}.graphiql-container .graphiql-chevron-icon{color:hsla(var(--color-neutral),var(--alpha-tertiary));display:block;height:var(--px-12);margin:var(--px-12);width:var(--px-12)}.graphiql-spin{animation:spin .8s linear 0s infinite}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}reach-portal .graphiql-dialog-header{align-items:center;display:flex;justify-content:space-between;padding:var(--px-24)}reach-portal .graphiql-dialog-title{font-size:var(--font-size-h3);font-weight:var(--font-weight-medium)}reach-portal .graphiql-dialog-section{align-items:center;border-top:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));display:flex;justify-content:space-between;padding:var(--px-24)}reach-portal .graphiql-dialog-section>:not(:first-child){margin-left:var(--px-24)}reach-portal .graphiql-dialog-section-title{font-size:var(--font-size-h4);font-weight:var(--font-weight-medium)}reach-portal .graphiql-dialog-section-caption{color:hsla(var(--color-neutral),var(--alpha-secondary))}reach-portal .graphiql-warning-text{color:hsl(var(--color-warning));font-weight:var(--font-weight-medium)}reach-portal .graphiql-table{border-collapse:collapse;width:100%}reach-portal .graphiql-table :is(th,td){border:1px solid hsla(var(--color-neutral),var(--alpha-background-heavy));padding:var(--px-8) var(--px-12)}reach-portal .graphiql-key{background-color:hsla(var(--color-neutral),var(--alpha-background-medium));border-radius:var(--border-radius-4);padding:var(--px-4)}.graphiql-container svg{pointer-events:none} - -/*# sourceMappingURL=graphiql.min.css.map*/ \ No newline at end of file diff --git a/builder/graphql/internal/graphiql/graphiql.min.js b/builder/graphql/internal/graphiql/graphiql.min.js deleted file mode 100644 index 73c32f32a..000000000 --- a/builder/graphql/internal/graphiql/graphiql.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see graphiql.min.js.LICENSE.txt */ -!function(){var e,t,n={8042:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,n=function(){"use strict";function e(){const e={};return e.promise=new Promise(((t,n)=>{e.resolve=t,e.reject=n})),e}Object.defineProperty(t,"__esModule",{value:!0});const n=Symbol(),r=Symbol();function i(){let t=!0;const i=[];let o=e();const a=e(),s=async function*(){for(;;)if(i.length>0)yield i.shift();else{const e=await Promise.race([o.promise,a.promise]);if(e===n)break;if(e!==r)throw e}}();const l=s.return.bind(s);s.return=function(){return t=!1,a.resolve(n),l(...arguments)};const u=s.throw.bind(s);return s.throw=e=>(t=!1,a.resolve(e),u(e)),{pushValue:function(n){!1!==t&&(i.push(n),o.resolve(r),o=e())},asyncIterableIterator:s}}t.applyAsyncIterableIteratorToSink=function(e,t){return(async()=>{try{for await(const n of e)t.next(n);t.complete()}catch(e){t.error(e)}})(),()=>{var t;null===(t=e.return)||void 0===t||t.call(e)}},t.isAsyncIterable=function(e){return"object"==typeof e&&null!==e&&("AsyncGenerator"===e[Symbol.toStringTag]||Symbol.asyncIterator&&Symbol.asyncIterator in e)},t.makeAsyncIterableIteratorFromSink=e=>{const{pushValue:t,asyncIterableIterator:n}=i(),r=e({next:e=>{t(e)},complete:()=>{n.return()},error:e=>{n.throw(e)}}),o=n.return;let a;return n.return=()=>(void 0===a&&(r(),a=o()),a),n},t.makePushPullAsyncIterableIterator=i},void 0===(r=n.apply(t,[]))||(e.exports=r)},7674:function(e,t,n){var r,i;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(i="function"==typeof(r=function(){"use strict";var e=Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]},r=function(t,n){for(var r in t)"default"===r||Object.prototype.hasOwnProperty.call(n,r)||e(n,t,r)};Object.defineProperty(t,"__esModule",{value:!0}),r(n(5313),t),r(n(6718),t),r(n(863),t)})?r.apply(t,[]):r)||(e.exports=i)},5609:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(r="function"==typeof(n=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.R=e.P=void 0;var t=Object.defineProperty,n=(e,n)=>t(e,"name",{value:n,configurable:!0});class r{constructor(e,t){this.containsPosition=e=>this.start.line===e.line?this.start.character<=e.character:this.end.line===e.line?this.end.character>=e.character:this.start.line<=e.line&&this.end.line>=e.line,this.start=e,this.end=t}setStart(e,t){this.start=new i(e,t)}setEnd(e,t){this.end=new i(e,t)}}e.R=r,n(r,"Range");class i{constructor(e,t){this.lessThanOrEqualTo=e=>this.linei(e,"name",{value:t,configurable:!0});function a(e,n){const i={schema:e,type:null,parentType:null,inputType:null,directiveDef:null,fieldDef:null,argDef:null,argDefs:null,objectFieldDefs:null};return(0,r.f)(n,(n=>{var r,o;switch(n.kind){case"Query":case"ShortQuery":i.type=e.getQueryType();break;case"Mutation":i.type=e.getMutationType();break;case"Subscription":i.type=e.getSubscriptionType();break;case"InlineFragment":case"FragmentDefinition":n.type&&(i.type=e.getType(n.type));break;case"Field":case"AliasedField":i.fieldDef=i.type&&n.name?s(e,i.parentType,n.name):null,i.type=null===(r=i.fieldDef)||void 0===r?void 0:r.type;break;case"SelectionSet":i.parentType=i.type?(0,t.getNamedType)(i.type):null;break;case"Directive":i.directiveDef=n.name?e.getDirective(n.name):null;break;case"Arguments":const a=n.prevState?"Field"===n.prevState.kind?i.fieldDef:"Directive"===n.prevState.kind?i.directiveDef:"AliasedField"===n.prevState.kind?n.prevState.name&&s(e,i.parentType,n.prevState.name):null:null;i.argDefs=a?a.args:null;break;case"Argument":if(i.argDef=null,i.argDefs)for(let e=0;ee.value===n.name)):null;break;case"ListValue":const c=i.inputType?(0,t.getNullableType)(i.inputType):null;i.inputType=c instanceof t.GraphQLList?c.ofType:null;break;case"ObjectValue":const d=i.inputType?(0,t.getNamedType)(i.inputType):null;i.objectFieldDefs=d instanceof t.GraphQLInputObjectType?d.getFields():null;break;case"ObjectField":const f=n.name&&i.objectFieldDefs?i.objectFieldDefs[n.name]:null;i.inputType=null==f?void 0:f.type;break;case"NamedType":i.type=n.name?e.getType(n.name):null}})),i}function s(e,r,i){return i===n.S.name&&e.getQueryType()===r?n.S:i===n.T.name&&e.getQueryType()===r?n.T:i===n.a.name&&(0,t.isCompositeType)(r)?n.a:r&&r.getFields?r.getFields()[i]:void 0}function l(e,t){for(let n=0;nn(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){function t(t){return function(n,i){var o=i.line,a=n.getLine(o);function s(t){for(var r,s=i.ch,l=0;;){var u=s<=0?-1:a.lastIndexOf(t[0],s-1);if(-1!=u){if(1==l&&ut.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));if(/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"keyword"!=r.type||"import"!=r.string)return null;for(var i=n,o=Math.min(t.lastLine(),n+10);i<=o;++i){var a=t.getLine(i).indexOf(";");if(-1!=a)return{startCh:r.end,end:e.Pos(i,a)}}}r(i,"hasImport");var o,a=n.line,s=i(a);if(!s||i(a-1)||(o=i(a-2))&&o.end.line==a-1)return null;for(var l=s.end;;){var u=i(l.line+1);if(null==u)break;l=u.end}return{from:t.clipPos(e.Pos(a,s.startCh+1)),to:l}})),e.registerHelper("fold","include",(function(t,n){function i(n){if(nt.lastLine())return null;var r=t.getTokenAt(e.Pos(n,1));return/\S/.test(r.string)||(r=t.getTokenAt(e.Pos(n,r.end+1))),"meta"==r.type&&"#include"==r.string.slice(0,8)?r.start+8:void 0}r(i,"hasInclude");var o=n.line,a=i(o);if(null==a||null!=i(o-1))return null;for(var s=o;null!=i(s+1);)++s;return{from:e.Pos(o,a+1),to:t.clipPos(e.Pos(s))}}))}(t.a.exports);var a=i({__proto__:null,default:o.exports},[o.exports]);e.b=a})?r.apply(t,i):r)||(e.exports=o)},5728:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.c=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){var t={pairs:"()[]{}''\"\"",closeBefore:")]}'\":;>",triples:"",explode:"[]{}"},n=e.Pos;function i(e,n){return"pairs"==n&&"string"==typeof e?e:"object"==typeof e&&null!=e[n]?e[n]:t[n]}e.defineOption("autoCloseBrackets",!1,(function(t,n,r){r&&r!=e.Init&&(t.removeKeyMap(o),t.state.closeBrackets=null),n&&(a(i(n,"pairs")),t.state.closeBrackets=n,t.addKeyMap(o))})),r(i,"getOption");var o={Backspace:u,Enter:c};function a(e){for(var t=0;t=0;s--){var c=a[s].head;t.replaceRange("",n(c.line,c.ch-1),n(c.line,c.ch+1),"+delete")}}function c(t){var n=l(t),r=n&&i(n,"explode");if(!r||t.getOption("disableInput"))return e.Pass;for(var o=t.listSelections(),a=0;a0?{line:a.head.line,ch:a.head.ch+t}:{line:a.head.line-1};n.push({anchor:s,head:s})}e.setSelections(n,i)}function f(t){var r=e.cmpPos(t.anchor,t.head)>0;return{anchor:new n(t.anchor.line,t.anchor.ch+(r?-1:1)),head:new n(t.head.line,t.head.ch+(r?1:-1))}}function p(t,r){var o=l(t);if(!o||t.getOption("disableInput"))return e.Pass;var a=i(o,"pairs"),s=a.indexOf(r);if(-1==s)return e.Pass;for(var u,c=i(o,"closeBefore"),p=i(o,"triples"),h=a.charAt(s+1)==r,g=t.listSelections(),v=s%2==0,y=0;y1&&p.indexOf(r)>=0&&t.getRange(n(T.line,T.ch-2),T)==r+r){if(T.ch>2&&/\bstring/.test(t.getTokenTypeAt(n(T.line,T.ch-2))))return e.Pass;b="addFour"}else if(h){var C=0==T.ch?" ":t.getRange(n(T.line,T.ch-1),T);if(e.isWordChar(w)||C==r||e.isWordChar(C))return e.Pass;b="both"}else{if(!v||!(0===w.length||/\s/.test(w)||c.indexOf(w)>-1))return e.Pass;b="both"}else b=h&&m(t,T)?"both":p.indexOf(r)>=0&&t.getRange(T,n(T.line,T.ch+3))==r+r+r?"skipThree":"skip";if(u){if(u!=b)return e.Pass}else u=b}var S=s%2?a.charAt(s-1):r,x=s%2?r:a.charAt(s+1);t.operation((function(){if("skip"==u)d(t,1);else if("skipThree"==u)d(t,3);else if("surround"==u){for(var e=t.getSelections(),n=0;nn(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};e.a=o,function(e,n){t.c,e.exports=function(){var e=navigator.userAgent,t=navigator.platform,n=/gecko\/\d/i.test(e),i=/MSIE \d/.test(e),o=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),a=/Edge\/(\d+)/.exec(e),s=i||o||a,l=s&&(i?document.documentMode||6:+(a||o)[1]),u=!a&&/WebKit\//.test(e),c=u&&/Qt\/\d+\.\d+/.test(e),d=!a&&/Chrome\//.test(e),f=/Opera\//.test(e),p=/Apple Computer/.test(navigator.vendor),h=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),m=/PhantomJS/.test(e),g=p&&(/Mobile\/\w+/.test(e)||navigator.maxTouchPoints>2),v=/Android/.test(e),y=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),b=g||/Mac/.test(t),E=/\bCrOS\b/.test(e),T=/win/i.test(t),w=f&&e.match(/Version\/(\d*\.\d*)/);w&&(w=Number(w[1])),w&&w>=15&&(f=!1,u=!0);var C=b&&(c||f&&(null==w||w<12.11)),S=n||s&&l>=9;function x(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}r(x,"classTest");var k,N=r((function(e,t){var n=e.className,r=x(t).exec(n);if(r){var i=n.slice(r.index+r[0].length);e.className=n.slice(0,r.index)+(i?r[1]+i:"")}}),"rmClass");function _(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function O(e,t){return _(e).appendChild(t)}function I(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return a+(t-o);a+=s-o,a+=n-a%n,o=s+1}}g?F=r((function(e){e.selectionStart=0,e.selectionEnd=e.value.length}),"selectInput"):s&&(F=r((function(e){try{e.select()}catch(e){}}),"selectInput")),r(P,"bind"),r(j,"copyObj"),r(V,"countColumn");var U=r((function(){this.id=null,this.f=null,this.time=0,this.handler=P(this.onTimeout,this)}),"Delayed");function B(e,t){for(var n=0;n=t)return r+Math.min(a,t-i);if(i+=o-r,r=o+1,(i+=n-i%n)>=t)return r}}r(W,"findColumn");var K=[""];function Q(e){for(;K.length<=e;)K.push(X(K)+" ");return K[e]}function X(e){return e[e.length-1]}function Y(e,t){for(var n=[],r=0;r"€"&&(e.toUpperCase()!=e.toLowerCase()||te.test(e))}function re(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ne(e))||t.test(e):ne(e)}function ie(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}r(ne,"isWordCharBasic"),r(re,"isWordChar"),r(ie,"isEmpty");var oe=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ae(e){return e.charCodeAt(0)>=768&&oe.test(e)}function se(e,t,n){for(;(n<0?t>0:tn?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}function ue(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;ot||t==n&&a.to==t)&&(r(Math.max(a.from,t),Math.min(a.to,n),1==a.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}r(ae,"isExtendingChar"),r(se,"skipExtendingChars"),r(le,"findFirst"),r(ue,"iterateBidiSections");var ce=null;function de(e,t,n){var r;ce=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:ce=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:ce=i)}return null!=r?r:ce}r(de,"getBidiPartAt");var fe=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";function n(n){return n<=247?e.charAt(n):1424<=n&&n<=1524?"R":1536<=n&&n<=1785?t.charAt(n-1536):1774<=n&&n<=2220?"r":8192<=n&&n<=8203?"w":8204==n?"b":"L"}r(n,"charType");var i=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,o=/[stwN]/,a=/[LRr]/,s=/[Lb1n]/,l=/[1n]/;function u(e,t,n){this.level=e,this.from=t,this.to=n}return r(u,"BidiSpan"),function(e,t){var r="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!i.test(e))return!1;for(var c=e.length,d=[],f=0;f-1&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ye(e,t){var n=ge(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i0}function we(e){e.prototype.on=function(e,t){me(this,e,t)},e.prototype.off=function(e,t){ve(this,e,t)}}function Ce(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Se(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function xe(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function ke(e){Ce(e),Se(e)}function Ne(e){return e.target||e.srcElement}function _e(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),b&&e.ctrlKey&&1==t&&(t=3),t}r(ge,"getHandlers"),r(ve,"off"),r(ye,"signal"),r(be,"signalDOMEvent"),r(Ee,"signalCursorActivity"),r(Te,"hasHandler"),r(we,"eventMixin"),r(Ce,"e_preventDefault"),r(Se,"e_stopPropagation"),r(xe,"e_defaultPrevented"),r(ke,"e_stop"),r(Ne,"e_target"),r(_e,"e_button");var Oe,Ie,De=function(){if(s&&l<9)return!1;var e=I("div");return"draggable"in e||"dragDrop"in e}();function Le(e){if(null==Oe){var t=I("span","​");O(e,I("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Oe=t.offsetWidth<=1&&t.offsetHeight>2&&!(s&&l<8))}var n=Oe?I("span","​"):I("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}function Ae(e){if(null!=Ie)return Ie;var t=O(e,document.createTextNode("AØ®A")),n=k(t,0,1).getBoundingClientRect(),r=k(t,1,2).getBoundingClientRect();return _(e),!(!n||n.left==n.right)&&(Ie=r.right-n.right<3)}r(Le,"zeroWidthElement"),r(Ae,"hasBadBidiRects");var Me,Re=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),a=o.indexOf("\r");-1!=a?(n.push(o.slice(0,a)),t+=a+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},Fe=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Pe="oncopy"in(Me=I("div"))||(Me.setAttribute("oncopy","return;"),"function"==typeof Me.oncopy),je=null;function Ve(e){if(null!=je)return je;var t=O(e,I("span","x")),n=t.getBoundingClientRect(),r=k(t,0,1).getBoundingClientRect();return je=Math.abs(n.left-r.left)>1}r(Ve,"hasBadZoomedRects");var Ue={},Be={};function $e(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ue[e]=t}function qe(e,t){Be[e]=t}function He(e){if("string"==typeof e&&Be.hasOwnProperty(e))e=Be[e];else if(e&&"string"==typeof e.name&&Be.hasOwnProperty(e.name)){var t=Be[e.name];"string"==typeof t&&(t={name:t}),(e=ee(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return He("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return He("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Ge(e,t){t=He(t);var n=Ue[t.name];if(!n)return Ge(e,"text/plain");var r=n(e,t);if(ze.hasOwnProperty(t.name)){var i=ze[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)r[a]=t.modeProps[a];return r}r($e,"defineMode"),r(qe,"defineMIME"),r(He,"resolveMode"),r(Ge,"getMode");var ze={};function We(e,t){j(t,ze.hasOwnProperty(e)?ze[e]:ze[e]={})}function Ke(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function Qe(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function Xe(e,t,n){return!e.startState||e.startState(t,n)}r(We,"extendMode"),r(Ke,"copyState"),r(Qe,"innerMode"),r(Xe,"startState");var Ye=r((function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n}),"StringStream");function Je(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t=e.first&&tn?at(n,Je(e,n).text.length):ht(t,Je(e,t.line).text.length)}function ht(e,t){var n=e.ch;return null==n||n>t?at(e.line,t):n<0?at(e.line,0):e}function mt(e,t){for(var n=[],r=0;r=this.string.length},Ye.prototype.sol=function(){return this.pos==this.lineStart},Ye.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ye.prototype.next=function(){if(this.post},Ye.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ye.prototype.skipToEnd=function(){this.pos=this.string.length},Ye.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Ye.prototype.backUp=function(e){this.pos-=e},Ye.prototype.column=function(){return this.lastColumnPos0?null:(i&&!1!==t&&(this.pos+=i[0].length),i)}var o=r((function(e){return n?e.toLowerCase():e}),"cased");if(o(this.string.substr(this.pos,e.length))==o(e))return!1!==t&&(this.pos+=e.length),!0},Ye.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ye.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ye.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ye.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)},r(Je,"getLine"),r(Ze,"getBetween"),r(et,"getLines"),r(tt,"updateLineHeight"),r(nt,"lineNo"),r(rt,"lineAtHeight"),r(it,"isLine"),r(ot,"lineNumberFor"),r(at,"Pos"),r(st,"cmp"),r(lt,"equalCursorPos"),r(ut,"copyPos"),r(ct,"maxPos"),r(dt,"minPos"),r(ft,"clipLine"),r(pt,"clipPos"),r(ht,"clipToLen"),r(mt,"clipPosArray");var gt=r((function(e,t){this.state=e,this.lookAhead=t}),"SavedContext"),vt=r((function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1}),"Context");function yt(e,t,n,i){var o=[e.state.modeGen],a={};Nt(e,t.text,e.doc.mode,n,(function(e,t){return o.push(e,t)}),a,i);for(var s=n.state,l=r((function(r){n.baseTokens=o;var i=e.state.overlays[r],l=1,u=0;n.state=!0,Nt(e,t.text,i.mode,n,(function(e,t){for(var n=l;ue&&o.splice(l,1,e,o[l+1],r),l+=2,u=Math.min(e,r)}if(t)if(i.opaque)o.splice(n,l-n,e,"overlay "+t),l=n+2;else for(;ne.options.maxHighlightLength&&Ke(e.doc.mode,r.state),o=yt(e,t,r);i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function Et(e,t,n){var r=e.doc,i=e.display;if(!r.mode.startState)return new vt(r,!0,t);var o=_t(e,t,n),a=o>r.first&&Je(r,o-1).stateAfter,s=a?vt.fromSaved(r,a,o):new vt(r,Xe(r.mode),o);return r.iter(o,t,(function(n){Tt(e,n.text,s);var r=s.line;n.stateAfter=r==t-1||r%5==0||r>=i.viewFrom&&rt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}vt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},vt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},vt.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},vt.fromSaved=function(e,t,n){return t instanceof gt?new vt(e,Ke(e.mode,t.state),n,t.lookAhead):new vt(e,Ke(e.mode,t),n)},vt.prototype.save=function(e){var t=!1!==e?Ke(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new gt(t,this.maxLookAhead):t},r(yt,"highlightLine"),r(bt,"getLineStyles"),r(Et,"getContextBefore"),r(Tt,"processLine"),r(wt,"callBlankLine"),r(Ct,"readToken");var St=r((function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n}),"Token");function xt(e,t,n,r){var i,o,a=e.doc,s=a.mode,l=Je(a,(t=pt(a,t)).line),u=Et(e,t.line,n),c=new Ye(l.text,e.options.tabSize,u);for(r&&(o=[]);(r||c.pose.options.maxHighlightLength?(s=!1,a&&Tt(e,t,r,d.pos),d.pos=t.length,l=null):l=kt(Ct(n,d,r.state,f),o),f){var p=f[0].name;p&&(l="m-"+(l?p+" "+l:p))}if(!s||c!=l){for(;ua;--s){if(s<=o.first)return o.first;var l=Je(o,s-1),u=l.stateAfter;if(u&&(!n||s+(u instanceof gt?u.lookAhead:0)<=o.modeFrontier))return s;var c=V(l.text,null,e.options.tabSize);(null==i||r>c)&&(i=s-1,r=c)}return i}function Ot(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontiern;r--){var i=Je(e,r).stateAfter;if(i&&(!(i instanceof gt)||r+i.lookAhead=t:o.to>t);(r||(r=[])).push(new Mt(a,o.from,s?null:o.to))}}return r}function Vt(e,t,n){var r;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==a.type&&(!n||o.marker.insertLeft)){var s=null==o.from||(a.inclusiveLeft?o.from<=t:o.from0&&s)for(var b=0;b0)){var c=[l,1],d=st(u.from,s.from),f=st(u.to,s.to);(d<0||!a.inclusiveLeft&&!d)&&c.push({from:u.from,to:s.from}),(f>0||!a.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),l+=c.length-3}}return i}function qt(e){var t=e.markedSpans;if(t){for(var n=0;nt)&&(!n||Wt(n,o.marker)<0)&&(n=o.marker)}return n}function Jt(e,t,n,r,i){var o=Je(e,t),a=Dt&&o.markedSpans;if(a)for(var s=0;s=0&&d<=0||c<=0&&d>=0)&&(c<=0&&(l.marker.inclusiveRight&&i.inclusiveLeft?st(u.to,n)>=0:st(u.to,n)>0)||c>=0&&(l.marker.inclusiveRight&&i.inclusiveLeft?st(u.from,r)<=0:st(u.from,r)<0)))return!0}}}function Zt(e){for(var t;t=Qt(e);)e=t.find(-1,!0).line;return e}function en(e){for(var t;t=Xt(e);)e=t.find(1,!0).line;return e}function tn(e){for(var t,n;t=Xt(e);)e=t.find(1,!0).line,(n||(n=[])).push(e);return n}function nn(e,t){var n=Je(e,t),r=Zt(n);return n==r?t:nt(r)}function rn(e,t){if(t>e.lastLine())return t;var n,r=Je(e,t);if(!on(e,r))return t;for(;n=Xt(r);)r=n.find(1,!0).line;return nt(r)+1}function on(e,t){var n=Dt&&t.markedSpans;if(n)for(var r=void 0,i=0;it.maxLineLength&&(t.maxLineLength=n,t.maxLine=e)}))}r(Lt,"seeReadOnlySpans"),r(At,"seeCollapsedSpans"),r(Mt,"MarkedSpan"),r(Rt,"getMarkedSpanFor"),r(Ft,"removeMarkedSpan"),r(Pt,"addMarkedSpan"),r(jt,"markedSpansBefore"),r(Vt,"markedSpansAfter"),r(Ut,"stretchSpansOverChange"),r(Bt,"clearEmptySpans"),r($t,"removeReadOnlyRanges"),r(qt,"detachMarkedSpans"),r(Ht,"attachMarkedSpans"),r(Gt,"extraLeft"),r(zt,"extraRight"),r(Wt,"compareCollapsedMarkers"),r(Kt,"collapsedSpanAtSide"),r(Qt,"collapsedSpanAtStart"),r(Xt,"collapsedSpanAtEnd"),r(Yt,"collapsedSpanAround"),r(Jt,"conflictingCollapsedRange"),r(Zt,"visualLine"),r(en,"visualLineEnd"),r(tn,"visualLineContinued"),r(nn,"visualLineNo"),r(rn,"visualLineEndNo"),r(on,"lineIsHidden"),r(an,"lineIsHiddenInner"),r(sn,"heightAtLine"),r(ln,"lineLength"),r(un,"findMaxLine");var cn=r((function(e,t,n){this.text=e,Ht(this,t),this.height=n?n(this):1}),"Line");function dn(e,t,n,r){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),qt(e),Ht(e,n);var i=r?r(e):1;i!=e.height&&tt(e,i)}function fn(e){e.parent=null,qt(e)}cn.prototype.lineNo=function(){return nt(this)},we(cn),r(dn,"updateLine"),r(fn,"cleanUpLine");var pn={},hn={};function mn(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?hn:pn;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function gn(e,t){var n=D("span",null,null,u?"padding-right: .1px":null),r={pre:D("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,a=void 0;r.pos=0,r.addToken=yn,Ae(e.display.measure)&&(a=pe(o,e.doc.direction))&&(r.addToken=En(r.addToken,a)),r.map=[],wn(o,r,bt(e,o,t!=e.display.externalMeasured&&nt(o))),o.styleClasses&&(o.styleClasses.bgClass&&(r.bgClass=R(o.styleClasses.bgClass,r.bgClass||"")),o.styleClasses.textClass&&(r.textClass=R(o.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(Le(e.display.measure))),0==i?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(u){var s=r.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")}return ye(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=R(r.pre.className,r.textClass||"")),r}function vn(e){var t=I("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function yn(e,t,n,r,i,o,a){if(t){var u,c=e.splitSpaces?bn(t,e.trailingSpace):t,d=e.cm.state.specialChars,f=!1;if(d.test(t)){u=document.createDocumentFragment();for(var p=0;;){d.lastIndex=p;var h=d.exec(t),m=h?h.index-p:t.length-p;if(m){var g=document.createTextNode(c.slice(p,p+m));s&&l<9?u.appendChild(I("span",[g])):u.appendChild(g),e.map.push(e.pos,e.pos+m,g),e.col+=m,e.pos+=m}if(!h)break;p+=m+1;var v=void 0;if("\t"==h[0]){var y=e.cm.options.tabSize,b=y-e.col%y;(v=u.appendChild(I("span",Q(b),"cm-tab"))).setAttribute("role","presentation"),v.setAttribute("cm-text","\t"),e.col+=b}else"\r"==h[0]||"\n"==h[0]?((v=u.appendChild(I("span","\r"==h[0]?"â":"â¤","cm-invalidchar"))).setAttribute("cm-text",h[0]),e.col+=1):((v=e.cm.options.specialCharPlaceholder(h[0])).setAttribute("cm-text",h[0]),s&&l<9?u.appendChild(I("span",[v])):u.appendChild(v),e.col+=1);e.map.push(e.pos,e.pos+1,v),e.pos++}}else e.col+=t.length,u=document.createTextNode(c),e.map.push(e.pos,e.pos+t.length,u),s&&l<9&&(f=!0),e.pos+=t.length;if(e.trailingSpace=32==c.charCodeAt(t.length-1),n||r||i||f||o||a){var E=n||"";r&&(E+=r),i&&(E+=i);var T=I("span",[u],E,o);if(a)for(var w in a)a.hasOwnProperty(w)&&"style"!=w&&"class"!=w&&T.setAttribute(w,a[w]);return e.content.appendChild(T)}e.content.appendChild(u)}}function bn(e,t){if(e.length>1&&!/ /.test(e))return e;for(var n=t,r="",i=0;iu&&d.from<=u);f++);if(d.to>=c)return e(n,r,i,o,a,s,l);e(n,r.slice(0,d.to-u),i,o,null,s,l),o=null,r=r.slice(d.to-u),u=d.to}}}function Tn(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",n.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function wn(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(r)for(var a,s,l,u,c,d,f,p=i.length,h=0,m=1,g="",v=0;;){if(v==h){l=u=c=s="",f=null,d=null,v=1/0;for(var y=[],b=void 0,E=0;Eh||w.collapsed&&T.to==h&&T.from==h)){if(null!=T.to&&T.to!=h&&v>T.to&&(v=T.to,u=""),w.className&&(l+=" "+w.className),w.css&&(s=(s?s+";":"")+w.css),w.startStyle&&T.from==h&&(c+=" "+w.startStyle),w.endStyle&&T.to==v&&(b||(b=[])).push(w.endStyle,T.to),w.title&&((f||(f={})).title=w.title),w.attributes)for(var C in w.attributes)(f||(f={}))[C]=w.attributes[C];w.collapsed&&(!d||Wt(d.marker,w)<0)&&(d=T)}else T.from>h&&v>T.from&&(v=T.from)}if(b)for(var S=0;S=p)break;for(var k=Math.min(p,v);;){if(g){var N=h+g.length;if(!d){var _=N>k?g.slice(0,k-h):g;t.addToken(t,_,a?a+l:l,c,h+_.length==v?u:"",s,f)}if(N>=k){g=g.slice(k-h),h=k;break}h=N,c=""}g=i.slice(o,o=n[m++]),a=mn(n[m++],t.cm.options)}}else for(var O=1;O2&&o.push((l.bottom+u.top)/2-n.top)}}o.push(n.bottom-n.top)}}function Zn(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};if(e.rest){for(var r=0;rn)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}}function er(e,t){var n=nt(t=Zt(t)),r=e.display.externalMeasured=new Cn(e.doc,t,n);r.lineN=n;var i=r.built=gn(e,r);return r.text=i.pre,O(e.display.lineMeasure,i.pre),r}function tr(e,t,n,r){return ir(e,rr(e,t),n,r)}function nr(e,t){if(t>=e.display.viewFrom&&t=n.lineN&&tt)&&(i=(o=l-s)-1,t>=l&&(a="right")),null!=i){if(r=e[u+2],s==l&&n==(r.insertLeft?"left":"right")&&(a=n),"left"==n&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)r=e[2+(u-=3)],a="left";if("right"==n&&i==l-s)for(;u=0&&(n=e[i]).left==n.right;i--);return n}function ur(e,t,n,r){var i,o=sr(t.map,n,r),a=o.node,u=o.start,c=o.end,d=o.collapse;if(3==a.nodeType){for(var f=0;f<4;f++){for(;u&&ae(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c0&&(d=r="right"),i=e.options.lineWrapping&&(p=a.getClientRects()).length>1?p["right"==r?p.length-1:0]:a.getBoundingClientRect()}if(s&&l<9&&!u&&(!i||!i.left&&!i.right)){var h=a.parentNode.getClientRects()[0];i=h?{left:h.left,right:h.left+Dr(e.display),top:h.top,bottom:h.bottom}:ar}for(var m=i.top-t.rect.top,g=i.bottom-t.rect.top,v=(m+g)/2,y=t.view.measure.heights,b=0;b=i.text.length?(u=i.text.length,c="before"):u<=0&&(u=0,c="after"),!l)return s("before"==c?u-1:u,"before"==c);function d(e,t,n){return s(n?e-1:e,1==l[t].level!=n)}r(d,"getBidi");var f=de(l,u,c),p=ce,h=d(u,f,"before"==c);return null!=p&&(h.other=d(u,p,"before"!=c)),h}function Tr(e,t){var n=0;t=pt(e.doc,t),e.options.lineWrapping||(n=Dr(e.display)*t.ch);var r=Je(e.doc,t.line),i=sn(r)+zn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function wr(e,t,n,r,i){var o=at(e,t,n);return o.xRel=i,r&&(o.outside=r),o}function Cr(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return wr(r.first,0,null,-1,-1);var i=rt(r,n),o=r.first+r.size-1;if(i>o)return wr(r.first+r.size-1,Je(r,o).text.length,null,1,1);t<0&&(t=0);for(var a=Je(r,i);;){var s=Nr(e,a,i,t,n),l=Yt(a,s.ch+(s.xRel>0||s.outside>0?1:0));if(!l)return s;var u=l.find(1);if(u.line==i)return u;a=Je(r,i=u.line)}}function Sr(e,t,n,r){r-=gr(t);var i=t.text.length,o=le((function(t){return ir(e,n,t-1).bottom<=r}),i,0);return{begin:o,end:i=le((function(t){return ir(e,n,t).top>r}),o,i)}}function xr(e,t,n,r){return n||(n=rr(e,t)),Sr(e,t,n,vr(e,t,ir(e,n,r),"line").top)}function kr(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function Nr(e,t,n,r,i){i-=sn(t);var o=rr(e,t),a=gr(t),s=0,l=t.text.length,u=!0,c=pe(t,e.doc.direction);if(c){var d=(e.options.lineWrapping?Or:_r)(e,t,n,o,c,r,i);s=(u=1!=d.level)?d.from:d.to-1,l=u?d.to:d.from-1}var f,p,h=null,m=null,g=le((function(t){var n=ir(e,o,t);return n.top+=a,n.bottom+=a,!!kr(n,r,i,!1)&&(n.top<=i&&n.left<=r&&(h=t,m=n),!0)}),s,l),v=!1;if(m){var y=r-m.left=E.bottom?1:0}return wr(n,g=se(t.text,g,1),p,v,r-f)}function _r(e,t,n,r,i,o,a){var s=le((function(s){var l=i[s],u=1!=l.level;return kr(Er(e,at(n,u?l.to:l.from,u?"before":"after"),"line",t,r),o,a,!0)}),0,i.length-1),l=i[s];if(s>0){var u=1!=l.level,c=Er(e,at(n,u?l.from:l.to,u?"after":"before"),"line",t,r);kr(c,o,a,!0)&&c.top>a&&(l=i[s-1])}return l}function Or(e,t,n,r,i,o,a){var s=Sr(e,t,r,a),l=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,d=null,f=0;f=u||p.to<=l)){var h=ir(e,r,1!=p.level?Math.min(u,p.to)-1:Math.max(l,p.from)).right,m=hm)&&(c=p,d=m)}}return c||(c=i[i.length-1]),c.fromu&&(c={from:c.from,to:u,level:c.level}),c}function Ir(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==or){or=I("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)or.appendChild(document.createTextNode("x")),or.appendChild(I("br"));or.appendChild(document.createTextNode("x"))}O(e.measure,or);var n=or.offsetHeight/50;return n>3&&(e.cachedTextHeight=n),_(e.measure),n||1}function Dr(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=I("span","xxxxxxxxxx"),n=I("pre",[t],"CodeMirror-line-like");O(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function Lr(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,a=0;o;o=o.nextSibling,++a){var s=e.display.gutterSpecs[a].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:Ar(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function Ar(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function Mr(e){var t=Ir(e.display),n=e.options.lineWrapping,r=n&&Math.max(5,e.display.scroller.clientWidth/Dr(e.display)-3);return function(i){if(on(e.doc,i))return 0;var o=0;if(i.widgets)for(var a=0;a0&&(l=Je(e.doc,u.line).text).length==u.ch){var c=V(l,l.length,e.options.tabSize)-l.length;u=at(u.line,Math.max(0,Math.round((o-Kn(e.display).left)/Dr(e.display))-c))}return u}function Pr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;rt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Dt&&nn(e.doc,t)i.viewFrom?Ur(e):(i.viewFrom+=r,i.viewTo+=r);else if(t<=i.viewFrom&&n>=i.viewTo)Ur(e);else if(t<=i.viewFrom){var o=Br(e,n,n+r,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=r):Ur(e)}else if(n>=i.viewTo){var a=Br(e,t,t,-1);a?(i.view=i.view.slice(0,a.index),i.viewTo=a.lineN):Ur(e)}else{var s=Br(e,t,t,-1),l=Br(e,n,n+r,1);s&&l?(i.view=i.view.slice(0,s.index).concat(Sn(e,s.lineN,l.lineN)).concat(i.view.slice(l.index)),i.viewTo+=r):Ur(e)}var u=i.externalMeasured;u&&(n=i.lineN&&t=r.viewTo)){var o=r.view[Pr(e,t)];if(null!=o.node){var a=o.changes||(o.changes=[]);-1==B(a,n)&&a.push(n)}}}function Ur(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function Br(e,t,n,r){var i,o=Pr(e,t),a=e.display.view;if(!Dt||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,l=0;l0){if(o==a.length-1)return null;i=s+a[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;nn(e.doc,n)!=n;){if(o==(r<0?0:a.length-1))return null;n+=r*a[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function $r(e,t,n){var r=e.display;0==r.view.length||t>=r.viewTo||n<=r.viewFrom?(r.view=Sn(e,t,n),r.viewFrom=t):(r.viewFrom>t?r.view=Sn(e,t,r.viewFrom).concat(r.view):r.viewFromn&&(r.view=r.view.slice(0,Pr(e,n)))),r.viewTo=n}function qr(e){for(var t=e.display.view,n=0,r=0;r=e.display.viewTo||l.to().line0?a:e.defaultCharWidth())+"px"}if(r.other){var s=n.appendChild(I("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"));s.style.display="",s.style.left=r.other.left+"px",s.style.top=r.other.top+"px",s.style.height=.85*(r.other.bottom-r.other.top)+"px"}}function Wr(e,t){return e.top-t.top||e.left-t.left}function Kr(e,t,n){var i=e.display,o=e.doc,a=document.createDocumentFragment(),s=Kn(e.display),l=s.left,u=Math.max(i.sizerWidth,Xn(e)-i.sizer.offsetLeft)-s.right,c="ltr"==o.direction;function d(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),a.appendChild(I("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?u-e:n)+"px;\n height: "+(r-t)+"px"))}function f(t,n,i){var a,s,f=Je(o,t),p=f.text.length;function h(n,r){return br(e,at(t,n),"div",f,r)}function m(t,n,r){var i=xr(e,f,null,t),o="ltr"==n==("after"==r)?"left":"right";return h("after"==r?i.begin:i.end-(/\s/.test(f.text.charAt(i.end-1))?2:1),o)[o]}r(h,"coords"),r(m,"wrapX");var g=pe(f,o.direction);return ue(g,n||0,null==i?p:i,(function(e,t,r,o){var f="ltr"==r,v=h(e,f?"left":"right"),y=h(t-1,f?"right":"left"),b=null==n&&0==e,E=null==i&&t==p,T=0==o,w=!g||o==g.length-1;if(y.top-v.top<=3){var C=(c?E:b)&&w,S=(c?b:E)&&T?l:(f?v:y).left,x=C?u:(f?y:v).right;d(S,v.top,x-S,v.bottom)}else{var k,N,_,O;f?(k=c&&b&&T?l:v.left,N=c?u:m(e,r,"before"),_=c?l:m(t,r,"after"),O=c&&E&&w?u:y.right):(k=c?m(e,r,"before"):l,N=!c&&b&&T?u:v.right,_=!c&&E&&w?l:y.left,O=c?m(t,r,"after"):u),d(k,v.top,N-k,v.bottom),v.bottom0?t.blinker=setInterval((function(){e.hasFocus()||Zr(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"}),e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function Xr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Jr(e))}function Yr(e){e.state.delayingBlurEvent=!0,setTimeout((function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&Zr(e))}),100)}function Jr(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ye(e,"focus",e,t),e.state.focused=!0,M(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),u&&setTimeout((function(){return e.display.input.reset(!0)}),20)),e.display.input.receivedFocus()),Qr(e))}function Zr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ye(e,"blur",e,t),e.state.focused=!1,N(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout((function(){e.state.focused||(e.display.shift=!1)}),150))}function ei(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=Math.max(0,t.scroller.getBoundingClientRect().top),i=t.lineDiv.getBoundingClientRect().top,o=0,a=0;a.005||m<-.005)&&(ie.display.sizerWidth){var v=Math.ceil(f/Dr(e.display));v>e.display.maxLineLength&&(e.display.maxLineLength=v,e.display.maxLine=u.line,e.display.maxLineChanged=!0)}}}Math.abs(o)>2&&(t.scroller.scrollTop+=o)}function ti(e){if(e.widgets)for(var t=0;t=a&&(o=rt(t,sn(Je(t,l))-e.wrapper.clientHeight),a=l)}return{from:o,to:Math.max(a,o+1)}}function ri(e,t){if(!be(e,"scrollCursorIntoView")){var n=e.display,r=n.sizer.getBoundingClientRect(),i=null;if(t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!m){var o=I("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-zn(e.display))+"px;\n height: "+(t.bottom-t.top+Qn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}function ii(e,t,n,r){var i;null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==t.sticky?at(t.line,t.ch+1,"before"):t,t=t.ch?at(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t);for(var o=0;o<5;o++){var a=!1,s=Er(e,t),l=n&&n!=t?Er(e,n):s,u=ai(e,i={left:Math.min(s.left,l.left),top:Math.min(s.top,l.top)-r,right:Math.max(s.left,l.left),bottom:Math.max(s.bottom,l.bottom)+r}),c=e.doc.scrollTop,d=e.doc.scrollLeft;if(null!=u.scrollTop&&(pi(e,u.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(a=!0)),null!=u.scrollLeft&&(mi(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-d)>1&&(a=!0)),!a)break}return i}function oi(e,t){var n=ai(e,t);null!=n.scrollTop&&pi(e,n.scrollTop),null!=n.scrollLeft&&mi(e,n.scrollLeft)}function ai(e,t){var n=e.display,r=Ir(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=Yn(e),a={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Wn(n),l=t.tops-r;if(t.topi+o){var c=Math.min(t.top,(u?s:t.bottom)-o);c!=i&&(a.scrollTop=c)}var d=e.options.fixedGutter?0:n.gutters.offsetWidth,f=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-d,p=Xn(e)-n.gutters.offsetWidth,h=t.right-t.left>p;return h&&(t.right=t.left+p),t.left<10?a.scrollLeft=0:t.leftp+f-3&&(a.scrollLeft=t.right+(h?0:10)-p),a}function si(e,t){null!=t&&(di(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function li(e){di(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function ui(e,t,n){null==t&&null==n||di(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function ci(e,t){di(e),e.curOp.scrollToPos=t}function di(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,fi(e,Tr(e,t.from),Tr(e,t.to),t.margin))}function fi(e,t,n,r){var i=ai(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});ui(e,i.scrollLeft,i.scrollTop)}function pi(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||Hi(e,{top:t}),hi(e,t,!0),n&&Hi(e),Fi(e,100))}function hi(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function mi(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Ki(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function gi(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+Wn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Qn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}r(sr,"nodeAndOffsetInLineMap"),r(lr,"getUsefulRect"),r(ur,"measureCharInner"),r(cr,"maybeUpdateRectForZooming"),r(dr,"clearLineMeasurementCacheFor"),r(fr,"clearLineMeasurementCache"),r(pr,"clearCaches"),r(hr,"pageScrollX"),r(mr,"pageScrollY"),r(gr,"widgetTopHeight"),r(vr,"intoCoordSystem"),r(yr,"fromCoordSystem"),r(br,"charCoords"),r(Er,"cursorCoords"),r(Tr,"estimateCoords"),r(wr,"PosWithInfo"),r(Cr,"coordsChar"),r(Sr,"wrappedLineExtent"),r(xr,"wrappedLineExtentChar"),r(kr,"boxIsAfter"),r(Nr,"coordsCharInner"),r(_r,"coordsBidiPart"),r(Or,"coordsBidiPartWrapped"),r(Ir,"textHeight"),r(Dr,"charWidth"),r(Lr,"getDimensions"),r(Ar,"compensateForHScroll"),r(Mr,"estimateHeight"),r(Rr,"estimateLineHeights"),r(Fr,"posFromMouse"),r(Pr,"findViewIndex"),r(jr,"regChange"),r(Vr,"regLineChange"),r(Ur,"resetView"),r(Br,"viewCuttingPoint"),r($r,"adjustView"),r(qr,"countDirtyView"),r(Hr,"updateSelection"),r(Gr,"prepareSelection"),r(zr,"drawSelectionCursor"),r(Wr,"cmpCoords"),r(Kr,"drawSelectionRange"),r(Qr,"restartBlink"),r(Xr,"ensureFocus"),r(Yr,"delayBlurEvent"),r(Jr,"onFocus"),r(Zr,"onBlur"),r(ei,"updateHeightsInViewport"),r(ti,"updateWidgetHeight"),r(ni,"visibleLines"),r(ri,"maybeScrollWindow"),r(ii,"scrollPosIntoView"),r(oi,"scrollIntoView"),r(ai,"calculateScrollPos"),r(si,"addToScrollTop"),r(li,"ensureCursorVisible"),r(ui,"scrollToCoords"),r(ci,"scrollToRange"),r(di,"resolveScrollToPos"),r(fi,"scrollToCoordsRange"),r(pi,"updateScrollTop"),r(hi,"setScrollTop"),r(mi,"setScrollLeft"),r(gi,"measureForScrollbars");var vi=r((function(e,t,n){this.cm=n;var r=this.vert=I("div",[I("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=I("div",[I("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),me(r,"scroll",(function(){r.clientHeight&&t(r.scrollTop,"vertical")})),me(i,"scroll",(function(){i.clientWidth&&t(i.scrollLeft,"horizontal")})),this.checkedZeroWidth=!1,s&&l<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}),"NativeScrollbars");vi.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,r=e.nativeBarWidth;if(n){this.vert.style.display="block",this.vert.style.bottom=t?r+"px":"0";var i=e.viewHeight-(t?r:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.scrollTop=0,this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=n?r+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(n?r:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==r&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?r:0,bottom:t?r:0}},vi.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},vi.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},vi.prototype.zeroWidthHack=function(){var e=b&&!h?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new U,this.disableVert=new U},vi.prototype.enableZeroWidthBar=function(e,t,n){function i(){var r=e.getBoundingClientRect();("vert"==n?document.elementFromPoint(r.right-1,(r.top+r.bottom)/2):document.elementFromPoint((r.right+r.left)/2,r.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,i)}e.style.pointerEvents="auto",r(i,"maybeDisable"),t.set(1e3,i)},vi.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var yi=r((function(){}),"NullScrollbars");function bi(e,t){t||(t=gi(e));var n=e.display.barWidth,r=e.display.barHeight;Ei(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&ei(e),Ei(e,gi(e)),n=e.display.barWidth,r=e.display.barHeight}function Ei(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}yi.prototype.update=function(){return{bottom:0,right:0}},yi.prototype.setScrollLeft=function(){},yi.prototype.setScrollTop=function(){},yi.prototype.clear=function(){},r(bi,"updateScrollbars"),r(Ei,"updateScrollbarsInner");var Ti={native:vi,null:yi};function wi(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&N(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Ti[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),me(t,"mousedown",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute("cm-not-content","true")}),(function(t,n){"horizontal"==n?mi(e,t):pi(e,t)}),e),e.display.scrollbars.addClass&&M(e.display.wrapper,e.display.scrollbars.addClass)}r(wi,"initScrollbars");var Ci=0;function Si(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ci,markArrays:null},kn(e.curOp)}function xi(e){var t=e.curOp;t&&_n(t,(function(e){for(var t=0;t=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ji(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function _i(e){e.updatedDisplay=e.mustUpdate&&$i(e.cm,e.update)}function Oi(e){var t=e.cm,n=t.display;e.updatedDisplay&&ei(t),e.barMeasure=gi(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=tr(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Qn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Xn(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}function Ii(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft=e.display.viewTo)){var n=+new Date+e.options.workTime,r=Et(e,t.highlightFrontier),i=[];t.iter(r.line,Math.min(t.first+t.size,e.display.viewTo+500),(function(o){if(r.line>=e.display.viewFrom){var a=o.styles,s=o.text.length>e.options.maxHighlightLength?Ke(t.mode,r.state):null,l=yt(e,o,r,!0);s&&(r.state=s),o.styles=l.styles;var u=o.styleClasses,c=l.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var d=!a||a.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!d&&fn)return Fi(e,e.options.workDelay),!0})),t.highlightFrontier=r.line,t.modeFrontier=Math.max(t.modeFrontier,r.line),i.length&&Li(e,(function(){for(var t=0;t=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==qr(e))return!1;Qi(e)&&(Ur(e),t.dims=Lr(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),a=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFroma&&n.viewTo-a<20&&(a=Math.min(i,n.viewTo)),Dt&&(o=nn(e.doc,o),a=rn(e.doc,a));var s=o!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;$r(e,o,a),n.viewOffset=sn(Je(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var l=qr(e);if(!s&&0==l&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var u=Ui(e);return l>4&&(n.lineDiv.style.display="none"),Gi(e,n.updateLineNumbers,t.dims),l>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,Bi(u),_(n.cursorDiv),_(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,s&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,Fi(e,400)),n.updateLineNumbers=null,!0}function qi(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Xn(e))r&&(t.visible=ni(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+Wn(e.display)-Yn(e),n.top)}),t.visible=ni(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!$i(e,t))break;ei(e);var i=gi(e);Hr(e),bi(e,i),Wi(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function Hi(e,t){var n=new ji(e,t);if($i(e,n)){ei(e),qi(e,n);var r=gi(e);Hr(e),bi(e,r),Wi(e,r),n.finish()}}function Gi(e,t,n){var i=e.display,o=e.options.lineNumbers,a=i.lineDiv,s=a.firstChild;function l(t){var n=t.nextSibling;return u&&b&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),n}r(l,"rm");for(var c=i.view,d=i.viewFrom,f=0;f-1&&(h=!1),Ln(e,p,d,n)),h&&(_(p.lineNumber),p.lineNumber.appendChild(document.createTextNode(ot(e.options,d)))),s=p.node.nextSibling}else{var m=Un(e,p,d,n);a.insertBefore(m,s)}d+=p.size}for(;s;)s=l(s)}function zi(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px",In(e,"gutterChanged",e)}function Wi(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Qn(e)+"px"}function Ki(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=Ar(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",a=0;al.clientWidth,d=l.scrollHeight>l.clientHeight;if(i&&c||o&&d){if(o&&b&&u)e:for(var p=t.target,h=s.view;p!=l;p=p.parentNode)for(var m=0;m=0&&st(e,r.to())<=0)return n}return-1};var ao=r((function(e,t){this.anchor=e,this.head=t}),"Range");function so(e,t,n){var r=e&&e.options.selectionsMayTouch,i=t[n];t.sort((function(e,t){return st(e.from(),t.from())})),n=B(t,i);for(var o=1;o0:l>=0){var u=dt(s.from(),a.from()),c=ct(s.to(),a.to()),d=s.empty()?a.from()==a.head:s.from()==s.head;o<=n&&--n,t.splice(--o,2,new ao(d?c:u,d?u:c))}}return new oo(t,n)}function lo(e,t){return new oo([new ao(e,t||e)],0)}function uo(e){return e.text?at(e.from.line+e.text.length-1,X(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function co(e,t){if(st(e,t.from)<0)return e;if(st(e,t.to)<=0)return uo(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=uo(t).ch-t.to.ch),at(n,r)}function fo(e,t){for(var n=[],r=0;r1&&e.remove(l.line+1,m-1),e.insert(l.line+1,y)}In(e,"change",e,t)}function bo(e,t,n){function i(e,r,o){if(e.linked)for(var a=0;a1&&!e.done[e.done.length-2].ranges?(e.done.pop(),X(e.done)):void 0}function No(e,t,n,r){var i=e.history;i.undone.length=0;var o,a,s=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>s-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=ko(i,i.lastOp==r)))a=X(o.changes),0==st(t.from,t.to)&&0==st(t.from,a.to)?a.to=uo(t):o.changes.push(So(e,t));else{var l=X(i.done);for(l&&l.ranges||Io(e.sel,i.done),o={changes:[So(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,a||ye(e,"historyAdded")}function _o(e,t,n,r){var i=t.charAt(0);return"*"==i||"+"==i&&n.ranges.length==r.ranges.length&&n.somethingSelected()==r.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}function Oo(e,t,n,r){var i=e.history,o=r&&r.origin;n==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||_o(e,o,X(i.done),t))?i.done[i.done.length-1]=t:Io(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=n,r&&!1!==r.clearRedo&&xo(i.undone)}function Io(e,t){var n=X(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Do(e,t,n,r){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,n),Math.min(e.first+e.size,r),(function(n){n.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=n.markedSpans),++o}))}function Lo(e){if(!e)return null;for(var t,n=0;n-1&&(X(s)[d]=u[d],delete u[d])}}}return r}function Fo(e,t,n,r){if(r){var i=e.anchor;if(n){var o=st(t,i)<0;o!=st(n,i)<0?(i=t,t=n):o!=st(t,n)<0&&(t=n)}return new ao(i,t)}return new ao(n||t,t)}function Po(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),qo(e,new oo([Fo(e.sel.primary(),t,n,i)],0),r)}function jo(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:s.to>t.ch))){if(i&&(ye(l,"beforeCursorEnter"),l.explicitlyCleared)){if(o.markedSpans){--a;continue}break}if(!l.atomic)continue;if(n){var d=l.find(r<0?1:-1),f=void 0;if((r<0?c:u)&&(d=Xo(e,d,-r,d&&d.line==t.line?o:null)),d&&d.line==t.line&&(f=st(d,n))&&(r<0?f<0:f>0))return Ko(e,d,t,r,i)}var p=l.find(r<0?-1:1);return(r<0?u:c)&&(p=Xo(e,p,r,p.line==t.line?o:null)),p?Ko(e,p,t,r,i):null}}return t}function Qo(e,t,n,r,i){var o=r||1;return Ko(e,t,n,o,i)||!i&&Ko(e,t,n,o,!0)||Ko(e,t,n,-o,i)||!i&&Ko(e,t,n,-o,!0)||(e.cantEdit=!0,at(e.first,0))}function Xo(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?pt(e,at(t.line-1)):null:n>0&&t.ch==(r||Je(e,t.line)).text.length?t.line=0;--i)ea(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else ea(e,t)}}function ea(e,t){if(1!=t.text.length||""!=t.text[0]||0!=st(t.from,t.to)){var n=fo(e,t);No(e,t,n,e.cm?e.cm.curOp.id:NaN),ra(e,t,n,Ut(e,t));var r=[];bo(e,(function(e,n){n||-1!=B(r,e.history)||(la(e.history,t),r.push(e.history)),ra(e,t,null,Ut(e,t))}))}}function ta(e,t,n){var i=e.cm&&e.cm.state.suppressEdits;if(!i||n){for(var o,a=e.history,s=e.sel,l="undo"==t?a.done:a.undone,u="undo"==t?a.undone:a.done,c=0;c=0;--h){var m=p(h);if(m)return m.v}}}}function na(e,t){if(0!=t&&(e.first+=t,e.sel=new oo(Y(e.sel.ranges,(function(e){return new ao(at(e.anchor.line+t,e.anchor.ch),at(e.head.line+t,e.head.ch))})),e.sel.primIndex),e.cm)){jr(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;re.lastLine())){if(t.from.lineo&&(t={from:t.from,to:at(o,Je(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ze(e,t.from,t.to),n||(n=fo(e,t)),e.cm?ia(e.cm,t,r):yo(e,t,r),Ho(e,n,H),e.cantEdit&&Qo(e,at(e.firstLine(),0))&&(e.cantEdit=!1)}}function ia(e,t,n){var r=e.doc,i=e.display,o=t.from,a=t.to,s=!1,l=o.line;e.options.lineWrapping||(l=nt(Zt(Je(r,o.line))),r.iter(l,a.line+1,(function(e){if(e==i.maxLine)return s=!0,!0}))),r.sel.contains(t.from,t.to)>-1&&Ee(e),yo(r,t,n,Mr(e)),e.options.lineWrapping||(r.iter(l,o.line+t.text.length,(function(e){var t=ln(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)})),s&&(e.curOp.updateMaxLine=!0)),Ot(r,o.line),Fi(e,400);var u=t.text.length-(a.line-o.line)-1;t.full?jr(e):o.line!=a.line||1!=t.text.length||vo(e.doc,t)?jr(e,o.line,a.line+1,u):Vr(e,o.line,"text");var c=Te(e,"changes"),d=Te(e,"change");if(d||c){var f={from:o,to:a,text:t.text,removed:t.removed,origin:t.origin};d&&In(e,"change",e,f),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(f)}e.display.selForContextMenu=null}function oa(e,t,n,r,i){var o;r||(r=n),st(r,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),Zo(e,{from:n,to:r,text:t,origin:i})}function aa(e,t,n,r){n1||!(this.children[0]instanceof ca))){var s=[];this.collapse(s),this.children=[new ca(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=i.lines.length%25+25,s=a;s10);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r0||0==a&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=D("span",[o.replacedWith],"CodeMirror-widget"),r.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),r.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Jt(e,t.line,t,n,o)||t.line!=n.line&&Jt(e,n.line,t,n,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");At()}o.addToHistory&&No(e,{from:t,to:n,origin:"markText"},e.sel,NaN);var s,l=t.line,u=e.cm;if(e.iter(l,n.line+1,(function(r){u&&o.collapsed&&!u.options.lineWrapping&&Zt(r)==u.display.maxLine&&(s=!0),o.collapsed&&l!=t.line&&tt(r,0),Pt(r,new Mt(o,l==t.line?t.ch:null,l==n.line?n.ch:null),e.cm&&e.cm.curOp),++l})),o.collapsed&&e.iter(t.line,n.line+1,(function(t){on(e,t)&&tt(t,0)})),o.clearOnEnter&&me(o,"beforeCursorEnter",(function(){return o.clear()})),o.readOnly&&(Lt(),(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++ma,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)jr(u,t.line,n.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=n.line;c++)Vr(u,c,"text");o.atomic&&zo(u.doc),In(u,"markerAdded",u,o)}return o}ga.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Si(e),Te(this,"clear")){var n=this.find();n&&In(this,"clear",n.from,n.to)}for(var r=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=r&&e&&this.collapsed&&jr(e,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&zo(e.doc)),e&&In(e,"markerCleared",e,this,r,i),t&&xi(e),this.parent&&this.parent.clear()}},ga.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;l--)Zo(this,r[l]);s?$o(this,s):this.cm&&li(this.cm)})),undo:Ri((function(){ta(this,"undo")})),redo:Ri((function(){ta(this,"redo")})),undoSelection:Ri((function(){ta(this,"undo",!0)})),redoSelection:Ri((function(){ta(this,"redo",!0)})),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,n){e=pt(this,e),t=pt(this,t);var r=[],i=e.line;return this.iter(e.line,t.line+1,(function(o){var a=o.markedSpans;if(a)for(var s=0;s=l.to||null==l.from&&i!=e.line||null!=l.from&&i==t.line&&l.from>=t.ch||n&&!n(l.marker)||r.push(l.marker.parent||l.marker)}++i})),r},getAllMarks:function(){var e=[];return this.iter((function(t){var n=t.markedSpans;if(n)for(var r=0;re)return t=e,!0;e-=o,++n})),pt(this,at(n,t))},indexFromPos:function(e){var t=(e=pt(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout((function(){return t.display.input.focus()}),20);try{var f=e.dataTransfer.getData("Text");if(f){var p;if(t.state.draggingText&&!t.state.draggingText.copy&&(p=t.listSelections()),Ho(t.doc,lo(n,n)),p)for(var h=0;h=0;t--)oa(e.doc,"",r[t].from,r[t].to,"+delete");li(e)}))}function Ka(e,t,n){var r=se(e.text,t+n,n);return r<0||r>e.text.length?null:r}function Qa(e,t,n){var r=Ka(e,t.ch,n);return null==r?null:new at(t.line,r,n<0?"after":"before")}function Xa(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=pe(n,t.doc.direction);if(o){var a,s=i<0?X(o):o[0],l=i<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var u=rr(t,n);a=i<0?n.text.length-1:0;var c=ir(t,u,a).top;a=le((function(e){return ir(t,u,e).top==c}),i<0==(1==s.level)?s.from:s.to-1,a),"before"==l&&(a=Ka(n,a,1))}else a=i<0?s.to:s.from;return new at(r,a,l)}}return new at(r,i<0?n.text.length:0,i<0?"before":"after")}function Ya(e,t,n,i){var o=pe(t,e.doc.direction);if(!o)return Qa(t,n,i);n.ch>=t.text.length?(n.ch=t.text.length,n.sticky="before"):n.ch<=0&&(n.ch=0,n.sticky="after");var a=de(o,n.ch,n.sticky),s=o[a];if("ltr"==e.doc.direction&&s.level%2==0&&(i>0?s.to>n.ch:s.from=s.from&&p>=d.begin)){var h=f?"before":"after";return new at(n.line,p,h)}}var m=r((function(e,t,i){for(var a=r((function(e,t){return t?new at(n.line,u(e,1),"before"):new at(n.line,e,"after")}),"getRes");e>=0&&e0==(1!=s.level),c=l?i.begin:u(i.end,-1);if(s.from<=c&&c0?d.end:u(d.begin,-1);return null==v||i>0&&v==t.text.length||!(g=m(i>0?0:o.length-1,i,c(v)))?null:g}Va.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Va.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Va.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Va.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Va.default=b?Va.macDefault:Va.pcDefault,r(Ua,"normalizeKeyName"),r(Ba,"normalizeKeyMap"),r($a,"lookupKey"),r(qa,"isModifierKey"),r(Ha,"addModifierNames"),r(Ga,"keyName"),r(za,"getKeyMap"),r(Wa,"deleteNearSelection"),r(Ka,"moveCharLogically"),r(Qa,"moveLogically"),r(Xa,"endOfLine"),r(Ya,"moveVisually");var Ja={selectAll:Yo,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),H)},killLine:function(e){return Wa(e,(function(t){if(t.empty()){var n=Je(e.doc,t.head.line).text.length;return t.head.ch==n&&t.head.line0)i=new at(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),at(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var a=Je(e.doc,i.line-1).text;a&&(i=new at(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),at(i.line-1,a.length-1),i,"+transpose"))}n.push(new ao(i,i))}e.setSelections(n)}))},newlineAndIndent:function(e){return Li(e,(function(){for(var t=e.listSelections(),n=t.length-1;n>=0;n--)e.replaceRange(e.doc.lineSeparator(),t[n].anchor,t[n].head,"+input");t=e.listSelections();for(var r=0;r-1&&(st((i=a.ranges[i]).from(),t)<0||t.xRel>0)&&(st(i.to(),t)>0||t.xRel<0)?Cs(e,r,t,o):xs(e,r,t,o)}function Cs(e,t,n,i){var o=e.display,a=!1,c=Ai(e,(function(t){u&&(o.scroller.draggable=!1),e.state.draggingText=!1,e.state.delayingBlurEvent&&(e.hasFocus()?e.state.delayingBlurEvent=!1:Yr(e)),ve(o.wrapper.ownerDocument,"mouseup",c),ve(o.wrapper.ownerDocument,"mousemove",d),ve(o.scroller,"dragstart",f),ve(o.scroller,"drop",c),a||(Ce(t),i.addNew||Po(e.doc,n,null,null,i.extend),u&&!p||s&&9==l?setTimeout((function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()}),20):o.input.focus())})),d=r((function(e){a=a||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10}),"mouseMove"),f=r((function(){return a=!0}),"dragStart");u&&(o.scroller.draggable=!0),e.state.draggingText=c,c.copy=!i.moveOnDrag,me(o.wrapper.ownerDocument,"mouseup",c),me(o.wrapper.ownerDocument,"mousemove",d),me(o.scroller,"dragstart",f),me(o.scroller,"drop",c),e.state.delayingBlurEvent=!0,setTimeout((function(){return o.input.focus()}),20),o.scroller.dragDrop&&o.scroller.dragDrop()}function Ss(e,t,n){if("char"==n)return new ao(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new ao(at(t.line,0),pt(e.doc,at(t.line+1,0)));var r=n(e,t);return new ao(r.from,r.to)}function xs(e,t,n,i){s&&Yr(e);var o=e.display,a=e.doc;Ce(t);var l,u,c=a.sel,d=c.ranges;if(i.addNew&&!i.extend?(u=a.sel.contains(n),l=u>-1?d[u]:new ao(n,n)):(l=a.sel.primary(),u=a.sel.primIndex),"rectangle"==i.unit)i.addNew||(l=new ao(n,n)),n=Fr(e,t,!0,!0),u=-1;else{var f=Ss(e,n,i.unit);l=i.extend?Fo(l,f.anchor,f.head,i.extend):f}i.addNew?-1==u?(u=d.length,qo(a,so(e,d.concat([l]),u),{scroll:!1,origin:"*mouse"})):d.length>1&&d[u].empty()&&"char"==i.unit&&!i.extend?(qo(a,so(e,d.slice(0,u).concat(d.slice(u+1)),0),{scroll:!1,origin:"*mouse"}),c=a.sel):Vo(a,u,l,G):(u=0,qo(a,new oo([l],0),G),c=a.sel);var p=n;function h(t){if(0!=st(p,t))if(p=t,"rectangle"==i.unit){for(var r=[],o=e.options.tabSize,s=V(Je(a,n.line).text,n.ch,o),d=V(Je(a,t.line).text,t.ch,o),f=Math.min(s,d),h=Math.max(s,d),m=Math.min(n.line,t.line),g=Math.min(e.lastLine(),Math.max(n.line,t.line));m<=g;m++){var v=Je(a,m).text,y=W(v,f,o);f==h?r.push(new ao(at(m,y),at(m,y))):v.length>y&&r.push(new ao(at(m,y),at(m,W(v,h,o))))}r.length||r.push(new ao(n,n)),qo(a,so(e,c.ranges.slice(0,u).concat(r),u),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,E=l,T=Ss(e,t,i.unit),w=E.anchor;st(T.anchor,w)>0?(b=T.head,w=dt(E.from(),T.anchor)):(b=T.anchor,w=ct(E.to(),T.head));var C=c.ranges.slice(0);C[u]=ks(e,new ao(pt(a,w),b)),qo(a,so(e,C,u),G)}}r(h,"extendTo");var m=o.wrapper.getBoundingClientRect(),g=0;function v(t){var n=++g,r=Fr(e,t,!0,"rectangle"==i.unit);if(r)if(0!=st(r,p)){e.curOp.focus=A(),h(r);var s=ni(o,a);(r.line>=s.to||r.linem.bottom?20:0;l&&setTimeout(Ai(e,(function(){g==n&&(o.scroller.scrollTop+=l,v(t))})),50)}}function y(t){e.state.selectingText=!1,g=1/0,t&&(Ce(t),o.input.focus()),ve(o.wrapper.ownerDocument,"mousemove",b),ve(o.wrapper.ownerDocument,"mouseup",E),a.history.lastSelOrigin=null}r(v,"extend"),r(y,"done");var b=Ai(e,(function(e){0!==e.buttons&&_e(e)?v(e):y(e)})),E=Ai(e,y);e.state.selectingText=E,me(o.wrapper.ownerDocument,"mousemove",b),me(o.wrapper.ownerDocument,"mouseup",E)}function ks(e,t){var n=t.anchor,r=t.head,i=Je(e.doc,n.line);if(0==st(n,r)&&n.sticky==r.sticky)return t;var o=pe(i);if(!o)return t;var a=de(o,n.ch,n.sticky),s=o[a];if(s.from!=n.ch&&s.to!=n.ch)return t;var l,u=a+(s.from==n.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;if(r.line!=n.line)l=(r.line-n.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=de(o,r.ch,r.sticky),d=c-a||(r.ch-n.ch)*(1==s.level?-1:1);l=c==u-1||c==u?d<0:d>0}var f=o[u+(l?-1:0)],p=l==(1==f.level),h=p?f.from:f.to,m=p?"after":"before";return n.ch==h&&n.sticky==m?t:new ao(new at(n.line,h,m),r)}function Ns(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Ce(t);var a=e.display,s=a.lineDiv.getBoundingClientRect();if(o>s.bottom||!Te(e,n))return xe(t);o-=s.top-a.viewOffset;for(var l=0;l=i)return ye(e,n,e,rt(e.doc,o),e.display.gutterSpecs[l].className,t),xe(t)}}function _s(e,t){return Ns(e,t,"gutterClick",!0)}function Os(e,t){Gn(e.display,t)||Is(e,t)||be(e,t,"contextmenu")||S||e.display.input.onContextMenu(t)}function Is(e,t){return!!Te(e,"gutterContextMenu")&&Ns(e,t,"gutterContextMenu",!1)}function Ds(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),pr(e)}vs.prototype.compare=function(e,t,n){return this.time+gs>e&&0==st(t,this.pos)&&n==this.button},r(ys,"clickRepeat"),r(bs,"onMouseDown"),r(Es,"handleMappedButton"),r(Ts,"configureMouse"),r(ws,"leftButtonDown"),r(Cs,"leftButtonStartDrag"),r(Ss,"rangeForUnit"),r(xs,"leftButtonSelect"),r(ks,"bidiSimplify"),r(Ns,"gutterEvent"),r(_s,"clickInGutter"),r(Os,"onContextMenu"),r(Is,"contextMenuInGutter"),r(Ds,"themeChanged");var Ls={toString:function(){return"CodeMirror.Init"}},As={},Ms={};function Rs(e){var t=e.optionHandlers;function n(n,r,i,o){e.defaults[n]=r,i&&(t[n]=o?function(e,t,n){n!=Ls&&i(e,t,n)}:i)}r(n,"option"),e.defineOption=n,e.Init=Ls,n("value","",(function(e,t){return e.setValue(t)}),!0),n("mode",null,(function(e,t){e.doc.modeOption=t,mo(e)}),!0),n("indentUnit",2,mo,!0),n("indentWithTabs",!1),n("smartIndent",!0),n("tabSize",4,(function(e){go(e),pr(e),jr(e)}),!0),n("lineSeparator",null,(function(e,t){if(e.doc.lineSep=t,t){var n=[],r=e.doc.first;e.doc.iter((function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,n.push(at(r,o))}r++}));for(var i=n.length-1;i>=0;i--)oa(e.doc,t,n[i],at(n[i].line,n[i].ch+t.length))}})),n("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,(function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=Ls&&e.refresh()})),n("specialCharPlaceholder",vn,(function(e){return e.refresh()}),!0),n("electricChars",!0),n("inputStyle",y?"contenteditable":"textarea",(function(){throw new Error("inputStyle can not (yet) be changed in a running editor")}),!0),n("spellcheck",!1,(function(e,t){return e.getInputField().spellcheck=t}),!0),n("autocorrect",!1,(function(e,t){return e.getInputField().autocorrect=t}),!0),n("autocapitalize",!1,(function(e,t){return e.getInputField().autocapitalize=t}),!0),n("rtlMoveVisually",!T),n("wholeLineUpdateBefore",!0),n("theme","default",(function(e){Ds(e),Ji(e)}),!0),n("keyMap","default",(function(e,t,n){var r=za(t),i=n!=Ls&&za(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)})),n("extraKeys",null),n("configureMouse",null),n("lineWrapping",!1,Ps,!0),n("gutters",[],(function(e,t){e.display.gutterSpecs=Xi(t,e.options.lineNumbers),Ji(e)}),!0),n("fixedGutter",!0,(function(e,t){e.display.gutters.style.left=t?Ar(e.display)+"px":"0",e.refresh()}),!0),n("coverGutterNextToScrollbar",!1,(function(e){return bi(e)}),!0),n("scrollbarStyle","native",(function(e){wi(e),bi(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)}),!0),n("lineNumbers",!1,(function(e,t){e.display.gutterSpecs=Xi(e.options.gutters,t),Ji(e)}),!0),n("firstLineNumber",1,Ji,!0),n("lineNumberFormatter",(function(e){return e}),Ji,!0),n("showCursorWhenSelecting",!1,Hr,!0),n("resetSelectionOnContextMenu",!0),n("lineWiseCopyCut",!0),n("pasteLinesPerSelection",!0),n("selectionsMayTouch",!1),n("readOnly",!1,(function(e,t){"nocursor"==t&&(Zr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)})),n("screenReaderLabel",null,(function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)})),n("disableInput",!1,(function(e,t){t||e.display.input.reset()}),!0),n("dragDrop",!0,Fs),n("allowDropFileTypes",null),n("cursorBlinkRate",530),n("cursorScrollMargin",0),n("cursorHeight",1,Hr,!0),n("singleCursorHeightPerLine",!0,Hr,!0),n("workTime",100),n("workDelay",100),n("flattenSpans",!0,go,!0),n("addModeClass",!1,go,!0),n("pollInterval",100),n("undoDepth",200,(function(e,t){return e.doc.history.undoDepth=t})),n("historyEventDelay",1250),n("viewportMargin",10,(function(e){return e.refresh()}),!0),n("maxHighlightLength",1e4,go,!0),n("moveInputWithCursor",!0,(function(e,t){t||e.display.input.resetPosition()})),n("tabindex",null,(function(e,t){return e.display.input.getField().tabIndex=t||""})),n("autofocus",null),n("direction","ltr",(function(e,t){return e.doc.setDirection(t)}),!0),n("phrases",null)}function Fs(e,t,n){if(!t!=!(n&&n!=Ls)){var r=e.display.dragFunctions,i=t?me:ve;i(e.display.scroller,"dragstart",r.start),i(e.display.scroller,"dragenter",r.enter),i(e.display.scroller,"dragover",r.over),i(e.display.scroller,"dragleave",r.leave),i(e.display.scroller,"drop",r.drop)}}function Ps(e){e.options.lineWrapping?(M(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(N(e.display.wrapper,"CodeMirror-wrap"),un(e)),Rr(e),jr(e),pr(e),setTimeout((function(){return bi(e)}),100)}function js(e,t){var n=this;if(!(this instanceof js))return new js(e,t);this.options=t=t?j(t):{},j(As,t,!1);var r=t.value;"string"==typeof r?r=new Sa(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i=new js.inputStyles[t.inputStyle](this),o=this.display=new Zi(e,r,i,t);for(var a in o.wrapper.CodeMirror=this,Ds(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),wi(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new U,keySeq:null,specialChars:null},t.autofocus&&!y&&o.input.focus(),s&&l<11&&setTimeout((function(){return n.display.input.reset(!0)}),20),Vs(this),La(),Si(this),this.curOp.forceUpdate=!0,Eo(this,r),t.autofocus&&!y||this.hasFocus()?setTimeout((function(){n.hasFocus()&&!n.state.focused&&Jr(n)}),20):Zr(this),Ms)Ms.hasOwnProperty(a)&&Ms[a](this,t[a],Ls);Qi(this),t.finishInit&&t.finishInit(this);for(var c=0;c400}r(o,"finishTouch"),r(a,"isMouseLikeTouchEvent"),r(u,"farAway"),me(t.scroller,"touchstart",(function(r){if(!be(e,r)&&!a(r)&&!_s(e,r)){t.input.ensurePolled(),clearTimeout(n);var o=+new Date;t.activeTouch={start:o,moved:!1,prev:o-i.end<=300?i:null},1==r.touches.length&&(t.activeTouch.left=r.touches[0].pageX,t.activeTouch.top=r.touches[0].pageY)}})),me(t.scroller,"touchmove",(function(){t.activeTouch&&(t.activeTouch.moved=!0)})),me(t.scroller,"touchend",(function(n){var r=t.activeTouch;if(r&&!Gn(t,n)&&null!=r.left&&!r.moved&&new Date-r.start<300){var i,a=e.coordsChar(t.activeTouch,"page");i=!r.prev||u(r,r.prev)?new ao(a,a):!r.prev.prev||u(r,r.prev.prev)?e.findWordAt(a):new ao(at(a.line,0),pt(e.doc,at(a.line+1,0))),e.setSelection(i.anchor,i.head),e.focus(),Ce(n)}o()})),me(t.scroller,"touchcancel",o),me(t.scroller,"scroll",(function(){t.scroller.clientHeight&&(pi(e,t.scroller.scrollTop),mi(e,t.scroller.scrollLeft,!0),ye(e,"scroll",e))})),me(t.scroller,"mousewheel",(function(t){return io(e,t)})),me(t.scroller,"DOMMouseScroll",(function(t){return io(e,t)})),me(t.wrapper,"scroll",(function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0})),t.dragFunctions={enter:function(t){be(e,t)||ke(t)},over:function(t){be(e,t)||(_a(e,t),ke(t))},start:function(t){return Na(e,t)},drop:Ai(e,ka),leave:function(t){be(e,t)||Oa(e)}};var c=t.input.getField();me(c,"keyup",(function(t){return fs.call(e,t)})),me(c,"keydown",Ai(e,cs)),me(c,"keypress",Ai(e,ps)),me(c,"focus",(function(t){return Jr(e,t)})),me(c,"blur",(function(t){return Zr(e,t)}))}r(Rs,"defineOptions"),r(Fs,"dragDropChanged"),r(Ps,"wrappingChanged"),r(js,"CodeMirror"),js.defaults=As,js.optionHandlers=Ms,r(Vs,"registerEventHandlers");var Us=[];function Bs(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=Et(e,t).state:n="prev");var a=e.options.tabSize,s=Je(o,t),l=V(s.text,null,a);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((u=o.mode.indent(i,s.text.slice(c.length),s.text))==q||u>150)){if(!r)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?V(Je(o,t-1).text,null,a):0:"add"==n?u=l+e.options.indentUnit:"subtract"==n?u=l-e.options.indentUnit:"number"==typeof n&&(u=l+n),u=Math.max(0,u);var d="",f=0;if(e.options.indentWithTabs)for(var p=Math.floor(u/a);p;--p)f+=a,d+="\t";if(fa,l=Re(t),u=null;if(s&&r.ranges.length>1)if($s&&$s.text.join("\n")==t){if(r.ranges.length%$s.text.length==0){u=[];for(var c=0;c<$s.text.length;c++)u.push(o.splitLines($s.text[c]))}}else l.length==r.ranges.length&&e.options.pasteLinesPerSelection&&(u=Y(l,(function(e){return[e]})));for(var d=e.curOp.updateInput,f=r.ranges.length-1;f>=0;f--){var p=r.ranges[f],h=p.from(),m=p.to();p.empty()&&(n&&n>0?h=at(h.line,h.ch-n):e.state.overwrite&&!s?m=at(m.line,Math.min(Je(o,m.line).text.length,m.ch+X(l).length)):s&&$s&&$s.lineWise&&$s.text.join("\n")==l.join("\n")&&(h=m=at(h.line,0)));var g={from:h,to:m,text:u?u[f%u.length]:l,origin:i||(s?"paste":e.state.cutIncoming>a?"cut":"+input")};Zo(e.doc,g),In(e,"inputRead",e,g)}t&&!s&&zs(e,t),li(e),e.curOp.updateInput<2&&(e.curOp.updateInput=d),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Gs(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");if(n)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||Li(t,(function(){return Hs(t,n,0,null,"paste")})),!0}function zs(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;r>=0;r--){var i=n.ranges[r];if(!(i.head.ch>100||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),a=!1;if(o.electricChars){for(var s=0;s-1){a=Bs(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Je(e.doc,i.head.line).text.slice(0,i.head.ch))&&(a=Bs(e,i.head.line,"smart"));a&&In(e,"electricInput",e,i.head.line)}}}function Ws(e){for(var t=[],n=[],r=0;rn&&(Bs(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&li(this));else{var o=i.from(),a=i.to(),s=Math.max(n,o.line);n=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var l=s;l0&&Vo(this.doc,r,new ao(o,u[r].to()),H)}}})),getTokenAt:function(e,t){return xt(this,e,t)},getLineTokens:function(e,t){return xt(this,at(e),t,!0)},getTokenTypeAt:function(e){e=pt(this.doc,e);var t,n=bt(this,Je(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var a=r+i>>1;if((a?n[2*a-1]:0)>=o)i=a;else{if(!(n[2*a+1]o&&(e=o,i=!0),r=Je(this.doc,e)}else r=e;return vr(this,r,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-sn(r):0)},defaultTextHeight:function(){return Ir(this.display)},defaultCharWidth:function(){return Dr(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o=this.display,a=(e=Er(this,pt(this.doc,e))).bottom,s=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),o.sizer.appendChild(t),"over"==r)a=e.top;else if("above"==r||"near"==r){var l=Math.max(o.wrapper.clientHeight,this.doc.height),u=Math.max(o.sizer.clientWidth,o.lineSpace.clientWidth);("above"==r||e.bottom+t.offsetHeight>l)&&e.top>t.offsetHeight?a=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=l&&(a=e.bottom),s+t.offsetWidth>u&&(s=u-t.offsetWidth)}t.style.top=a+"px",t.style.left=t.style.right="","right"==i?(s=o.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?s=0:"middle"==i&&(s=(o.sizer.clientWidth-t.offsetWidth)/2),t.style.left=s+"px"),n&&oi(this,{left:s,top:a,right:s+t.offsetWidth,bottom:a+t.offsetHeight})},triggerOnKeyDown:Mi(cs),triggerOnKeyPress:Mi(ps),triggerOnKeyUp:fs,triggerOnMouseDown:Mi(bs),execCommand:function(e){if(Ja.hasOwnProperty(e))return Ja[e].call(null,this)},triggerElectric:Mi((function(e){zs(this,e)})),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=pt(this.doc,e),a=0;a0&&a(t.charAt(n-1));)--n;for(;r.5||this.options.lineWrapping)&&Rr(this),ye(this,"refresh",this)})),swapDoc:Mi((function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Eo(this,e),pr(this),this.display.input.reset(),ui(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,In(this,"swapDoc",this,t),t})),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},we(e),e.registerHelper=function(t,r,i){n.hasOwnProperty(t)||(n[t]=e[t]={_global:[]}),n[t][r]=i},e.registerGlobalHelper=function(t,r,i,o){e.registerHelper(t,r,o),n[t]._global.push({pred:i,val:o})}}function Ys(e,t,n,i,o){var a=t,s=n,l=Je(e,t.line),u=o&&"rtl"==e.direction?-n:n;function c(){var n=t.line+u;return!(n=e.first+e.size)&&(t=new at(n,t.ch,t.sticky),l=Je(e,n))}function d(r){var a;if("codepoint"==i){var s=l.text.charCodeAt(t.ch+(n>0?0:-1));if(isNaN(s))a=null;else{var d=n>0?s>=55296&&s<56320:s>=56320&&s<57343;a=new at(t.line,Math.max(0,Math.min(l.text.length,t.ch+n*(d?2:1))),-n)}}else a=o?Ya(e.cm,l,t,n):Qa(l,t,n);if(null==a){if(r||!c())return!1;t=Xa(o,e.cm,l,t.line,u)}else t=a;return!0}if(r(c,"findNextLine"),r(d,"moveOnce"),"char"==i||"codepoint"==i)d();else if("column"==i)d(!0);else if("word"==i||"group"==i)for(var f=null,p="group"==i,h=e.cm&&e.cm.getHelper(t,"wordChars"),m=!0;!(n<0)||d(!m);m=!1){var g=l.text.charAt(t.ch)||"\n",v=re(g,h)?"w":p&&"\n"==g?"n":!p||/\s/.test(g)?null:"p";if(!p||m||v||(v="s"),f&&f!=v){n<0&&(n=1,d(),t.sticky="after");break}if(v&&(f=v),n>0&&!d(!m))break}var y=Qo(e,t,a,s,!0);return lt(a,y)&&(y.hitSide=!0),y}function Js(e,t,n,r){var i,o,a=e.doc,s=t.left;if("page"==r){var l=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),u=Math.max(l-.5*Ir(e.display),3);i=(n>0?t.bottom:t.top)+n*u}else"line"==r&&(i=n>0?t.bottom+3:t.top-3);for(;(o=Cr(e,s,i)).outside;){if(n<0?i<=0:i>=a.height){o.hitSide=!0;break}i+=5*n}return o}r(qs,"setLastCopied"),r(Hs,"applyTextInput"),r(Gs,"handlePaste"),r(zs,"triggerElectric"),r(Ws,"copyableRanges"),r(Ks,"disableBrowserMagic"),r(Qs,"hiddenTextarea"),r(Xs,"addEditorMethods"),r(Ys,"findPosH"),r(Js,"findPosV");var Zs=r((function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new U,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null}),"ContentEditableInput");function el(e,t){var n=nr(e,t.line);if(!n||n.hidden)return null;var r=Je(e.doc,t.line),i=Zn(n,r,t.line),o=pe(r,e.doc.direction),a="left";o&&(a=de(o,t.ch)%2?"right":"left");var s=sr(i.map,t.ch,a);return s.offset="right"==s.collapse?s.end:s.start,s}function tl(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}function nl(e,t){return t&&(e.bad=!0),e}function rl(e,t,n,i,o){var a="",s=!1,l=e.doc.lineSeparator(),u=!1;function c(e){return function(t){return t.id==e}}function d(){s&&(a+=l,u&&(a+=l),s=u=!1)}function f(e){e&&(d(),a+=e)}function p(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void f(n);var r,a=t.getAttribute("cm-marker");if(a){var h=e.findMarks(at(i,0),at(o+1,0),c(+a));return void(h.length&&(r=h[0].find(0))&&f(Ze(e.doc,r.from,r.to).join(l)))}if("false"==t.getAttribute("contenteditable"))return;var m=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;m&&d();for(var g=0;g=t.display.viewTo||o.line=t.display.viewFrom&&el(t,i)||{node:l[0].measure.map[2],offset:0},c=o.liner.firstLine()&&(a=at(a.line-1,Je(r.doc,a.line-1).length)),s.ch==Je(r.doc,s.line).text.length&&s.linei.viewTo-1)return!1;a.line==i.viewFrom||0==(e=Pr(r,a.line))?(t=nt(i.view[0].line),n=i.view[0].node):(t=nt(i.view[e].line),n=i.view[e-1].node.nextSibling);var l,u,c=Pr(r,s.line);if(c==i.view.length-1?(l=i.viewTo-1,u=i.lineDiv.lastChild):(l=nt(i.view[c+1].line)-1,u=i.view[c+1].node.previousSibling),!n)return!1;for(var d=r.doc.splitLines(rl(r,n,u,t,l)),f=Ze(r.doc,at(t,0),at(l,Je(r.doc,l).text.length));d.length>1&&f.length>1;)if(X(d)==X(f))d.pop(),f.pop(),l--;else{if(d[0]!=f[0])break;d.shift(),f.shift(),t++}for(var p=0,h=0,m=d[0],g=f[0],v=Math.min(m.length,g.length);pa.ch&&y.charCodeAt(y.length-h-1)==b.charCodeAt(b.length-h-1);)p--,h++;d[d.length-1]=y.slice(0,y.length-h).replace(/^\u200b+/,""),d[0]=d[0].slice(p).replace(/\u200b+$/,"");var T=at(t,p),w=at(l,f.length?X(f).length-h:0);return d.length>1||d[0]||st(T,w)?(oa(r.doc,d,T,w,"+input"),!0):void 0},Zs.prototype.ensurePolled=function(){this.forceCompositionEnd()},Zs.prototype.reset=function(){this.forceCompositionEnd()},Zs.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Zs.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout((function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()}),80))},Zs.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Li(this.cm,(function(){return jr(e.cm)}))},Zs.prototype.setUneditable=function(e){e.contentEditable="false"},Zs.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Ai(this.cm,Hs)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Zs.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Zs.prototype.onContextMenu=function(){},Zs.prototype.resetPosition=function(){},Zs.prototype.needsContentAttribute=!0,r(el,"posToDOM"),r(tl,"isInGutter"),r(nl,"badPos"),r(rl,"domTextBetween"),r(il,"domToPos"),r(ol,"locateNodeInLineView");var al=r((function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new U,this.hasSelection=!1,this.composing=null}),"TextareaInput");function sl(e,t){if((t=t?j(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=A();t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}function i(){e.value=l.getValue()}var o;if(r(i,"save"),e.form&&(me(e.form,"submit",i),!t.leaveSubmitMethodAlone)){var a=e.form;o=a.submit;try{var s=a.submit=function(){i(),a.submit=o,a.submit(),a.submit=s}}catch(e){}}t.finishInit=function(n){n.save=i,n.getTextArea=function(){return e},n.toTextArea=function(){n.toTextArea=isNaN,i(),e.parentNode.removeChild(n.getWrapperElement()),e.style.display="",e.form&&(ve(e.form,"submit",i),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=o))}},e.style.display="none";var l=js((function(t){return e.parentNode.insertBefore(t,e.nextSibling)}),t);return l}function ll(e){e.off=ve,e.on=me,e.wheelEventPixels=ro,e.Doc=Sa,e.splitLines=Re,e.countColumn=V,e.findColumn=W,e.isWordChar=ne,e.Pass=q,e.signal=ye,e.Line=cn,e.changeEnd=uo,e.scrollbarModel=Ti,e.Pos=at,e.cmpPos=st,e.modes=Ue,e.mimeModes=Be,e.resolveMode=He,e.getMode=Ge,e.modeExtensions=ze,e.extendMode=We,e.copyState=Ke,e.startState=Xe,e.innerMode=Qe,e.commands=Ja,e.keyMap=Va,e.keyName=Ga,e.isModifierKey=qa,e.lookupKey=$a,e.normalizeKeyMap=Ba,e.StringStream=Ye,e.SharedTextMarker=ya,e.TextMarker=ga,e.LineWidget=fa,e.e_preventDefault=Ce,e.e_stopPropagation=Se,e.e_stop=ke,e.addClass=M,e.contains=L,e.rmClass=N,e.keyNames=Ra}al.prototype.init=function(e){var t=this,n=this,i=this.cm;this.createField(e);var o=this.textarea;function a(e){if(!be(i,e)){if(i.somethingSelected())qs({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=Ws(i);qs({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,H):(n.prevInput="",o.value=t.text.join("\n"),F(o))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(o.style.width="0px"),me(o,"input",(function(){s&&l>=9&&t.hasSelection&&(t.hasSelection=null),n.poll()})),me(o,"paste",(function(e){be(i,e)||Gs(e,i)||(i.state.pasteIncoming=+new Date,n.fastPoll())})),r(a,"prepareCopyCut"),me(o,"cut",a),me(o,"copy",a),me(e.scroller,"paste",(function(t){if(!Gn(e,t)&&!be(i,t)){if(!o.dispatchEvent)return i.state.pasteIncoming=+new Date,void n.focus();var r=new Event("paste");r.clipboardData=t.clipboardData,o.dispatchEvent(r)}})),me(e.lineSpace,"selectstart",(function(t){Gn(e,t)||Ce(t)})),me(o,"compositionstart",(function(){var e=i.getCursor("from");n.composing&&n.composing.range.clear(),n.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}})),me(o,"compositionend",(function(){n.composing&&(n.poll(),n.composing.range.clear(),n.composing=null)}))},al.prototype.createField=function(e){this.wrapper=Qs(),this.textarea=this.wrapper.firstChild},al.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},al.prototype.prepareSelection=function(){var e=this.cm,t=e.display,n=e.doc,r=Gr(e);if(e.options.moveInputWithCursor){var i=Er(e,n.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();r.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+a.top-o.top)),r.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+a.left-o.left))}return r},al.prototype.showSelection=function(e){var t=this.cm.display;O(t.cursorDiv,e.cursors),O(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},al.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var n=t.getSelection();this.textarea.value=n,t.state.focused&&F(this.textarea),s&&l>=9&&(this.hasSelection=n)}else e||(this.prevInput=this.textarea.value="",s&&l>=9&&(this.hasSelection=null))}},al.prototype.getField=function(){return this.textarea},al.prototype.supportsTouch=function(){return!1},al.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!y||A()!=this.textarea))try{this.textarea.focus()}catch(e){}},al.prototype.blur=function(){this.textarea.blur()},al.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},al.prototype.receivedFocus=function(){this.slowPoll()},al.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,(function(){e.poll(),e.cm.state.focused&&e.slowPoll()}))},al.prototype.fastPoll=function(){var e=!1,t=this;function n(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,n))}t.pollingFast=!0,r(n,"p"),t.polling.set(20,n)},al.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||Fe(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(s&&l>=9&&this.hasSelection===i||b&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var a=0,u=Math.min(r.length,i.length);a1e3||i.indexOf("\n")>-1?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))})),!0},al.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},al.prototype.onKeyPress=function(){s&&l>=9&&(this.hasSelection=null),this.fastPoll()},al.prototype.onContextMenu=function(e){var t=this,n=t.cm,i=n.display,o=t.textarea;t.contextMenuPending&&t.contextMenuPending();var a=Fr(n,e),c=i.scroller.scrollTop;if(a&&!f){n.options.resetSelectionOnContextMenu&&-1==n.doc.sel.contains(a)&&Ai(n,qo)(n.doc,lo(a),H);var d,p=o.style.cssText,h=t.wrapper.style.cssText,m=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-m.top-5)+"px; left: "+(e.clientX-m.left-5)+"px;\n z-index: 1000; background: "+(s?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",u&&(d=window.scrollY),i.input.focus(),u&&window.scrollTo(null,d),i.input.reset(),n.somethingSelected()||(o.value=t.prevInput=" "),t.contextMenuPending=y,i.selForContextMenu=n.doc.sel,clearTimeout(i.detectingSelectAll),r(v,"prepareSelectAllHack"),r(y,"rehide"),s&&l>=9&&v(),S){ke(e);var g=r((function(){ve(window,"mouseup",g),setTimeout(y,20)}),"mouseup");me(window,"mouseup",g)}else setTimeout(y,50)}function v(){if(null!=o.selectionStart){var e=n.somethingSelected(),r="​"+(e?o.value:"");o.value="⇚",o.value=r,t.prevInput=e?"":"​",o.selectionStart=1,o.selectionEnd=r.length,i.selForContextMenu=n.doc.sel}}function y(){if(t.contextMenuPending==y&&(t.contextMenuPending=!1,t.wrapper.style.cssText=h,o.style.cssText=p,s&&l<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=c),null!=o.selectionStart)){(!s||s&&l<9)&&v();var e=0,a=r((function(){i.selForContextMenu==n.doc.sel&&0==o.selectionStart&&o.selectionEnd>0&&"​"==t.prevInput?Ai(n,Yo)(n):e++<10?i.detectingSelectAll=setTimeout(a,500):(i.selForContextMenu=null,i.input.reset())}),"poll");i.detectingSelectAll=setTimeout(a,200)}}},al.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},al.prototype.setUneditable=function(){},al.prototype.needsContentAttribute=!1,r(sl,"fromTextArea"),r(ll,"addLegacyProps"),Rs(js),Xs(js);var ul="iter insert remove copy getEditor constructor".split(" ");for(var cl in Sa.prototype)Sa.prototype.hasOwnProperty(cl)&&B(ul,cl)<0&&(js.prototype[cl]=function(e){return function(){return e.apply(this.doc,arguments)}}(Sa.prototype[cl]));return we(Sa),js.inputStyles={textarea:al,contenteditable:Zs},js.defineMode=function(e){js.defaults.mode||"null"==e||(js.defaults.mode=e),$e.apply(this,arguments)},js.defineMIME=qe,js.defineMode("null",(function(){return{token:function(e){return e.skipToEnd()}}})),js.defineMIME("text/plain","null"),js.defineExtension=function(e,t){js.prototype[e]=t},js.defineDocExtension=function(e,t){Sa.prototype[e]=t},js.fromTextArea=sl,ll(js),js.version="5.65.3",js}()}(o);var a=o.exports;e.C=a;var s=i({__proto__:null,default:a},[o.exports]);e.c=s},void 0===(o=r.apply(t,i))||(e.exports=o)},6754:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.c=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){var t={},n=/[^\s\u00a0]/,i=e.Pos,o=e.cmpPos;function a(e){var t=e.search(n);return-1==t?0:t}function s(e,t,n){return/\bstring\b/.test(e.getTokenTypeAt(i(t.line,0)))&&!/^[\'\"\`]/.test(n)}function l(e,t){var n=e.getMode();return!1!==n.useInnerComments&&n.innerMode?e.getModeAt(t):n}r(a,"firstNonWS"),e.commands.toggleComment=function(e){e.toggleComment()},e.defineExtension("toggleComment",(function(e){e||(e=t);for(var n=this,r=1/0,o=this.listSelections(),a=null,s=o.length-1;s>=0;s--){var l=o[s].from(),u=o[s].to();l.line>=r||(u.line>=r&&(u=i(r,0)),r=l.line,null==a?n.uncomment(l,u,e)?a="un":(n.lineComment(l,u,e),a="line"):"un"==a?n.uncomment(l,u,e):n.lineComment(l,u,e))}})),r(s,"probablyInsideString"),r(l,"getMode"),e.defineExtension("lineComment",(function(e,r,o){o||(o=t);var u=this,c=l(u,e),d=u.getLine(e.line);if(null!=d&&!s(u,e,d)){var f=o.lineComment||c.lineComment;if(f){var p=Math.min(0!=r.ch||r.line==e.line?r.line+1:r.line,u.lastLine()+1),h=null==o.padding?" ":o.padding,m=o.commentBlankLines||e.line==r.line;u.operation((function(){if(o.indent){for(var t=null,r=e.line;rs.length)&&(t=s)}for(r=e.line;rf||s.operation((function(){if(0!=a.fullLines){var t=n.test(s.getLine(f));s.replaceRange(p+d,i(f)),s.replaceRange(c+p,i(e.line,0));var l=a.blockCommentLead||u.blockCommentLead;if(null!=l)for(var h=e.line+1;h<=f;++h)(h!=f||t)&&s.replaceRange(l+p,i(h,0))}else{var m=0==o(s.getCursor("to"),r),g=!s.somethingSelected();s.replaceRange(d,r),m&&s.setSelection(g?r:s.getCursor("from"),r),s.replaceRange(c,e)}}))}}else(a.lineComment||u.lineComment)&&0!=a.fullLines&&s.lineComment(e,r,a)})),e.defineExtension("uncomment",(function(e,r,o){o||(o=t);var a,s=this,u=l(s,e),c=Math.min(0!=r.ch||r.line==e.line?r.line:r.line-1,s.lastLine()),d=Math.min(e.line,c),f=o.lineComment||u.lineComment,p=[],h=null==o.padding?" ":o.padding;e:if(f){for(var m=d;m<=c;++m){var g=s.getLine(m),v=g.indexOf(f);if(v>-1&&!/comment/.test(s.getTokenTypeAt(i(m,v+1)))&&(v=-1),-1==v&&n.test(g))break e;if(v>-1&&n.test(g.slice(0,v)))break e;p.push(g)}if(s.operation((function(){for(var e=d;e<=c;++e){var t=p[e-d],n=t.indexOf(f),r=n+f.length;n<0||(t.slice(r,r+h.length)==h&&(r+=h.length),a=!0,s.replaceRange("",i(e,n),i(e,r)))}})),a)return!0}var y=o.blockCommentStart||u.blockCommentStart,b=o.blockCommentEnd||u.blockCommentEnd;if(!y||!b)return!1;var E=o.blockCommentLead||u.blockCommentLead,T=s.getLine(d),w=T.indexOf(y);if(-1==w)return!1;var C=c==d?T:s.getLine(c),S=C.indexOf(b,c==d?w+y.length:0),x=i(d,w+1),k=i(c,S+1);if(-1==S||!/comment/.test(s.getTokenTypeAt(x))||!/comment/.test(s.getTokenTypeAt(k))||s.getRange(x,k,"\n").indexOf(b)>-1)return!1;var N=T.lastIndexOf(y,e.ch),_=-1==N?-1:T.slice(0,e.ch).indexOf(b,N+y.length);if(-1!=N&&-1!=_&&_+b.length!=e.ch)return!1;_=C.indexOf(b,r.ch);var O=C.slice(r.ch).lastIndexOf(y,_-r.ch);return N=-1==_||-1==O?-1:r.ch+O,(-1==_||-1==N||N==r.ch)&&(s.operation((function(){s.replaceRange("",i(c,S-(h&&C.slice(S-h.length,S)==h?h.length:0)),i(c,S+b.length));var e=w+y.length;if(h&&T.slice(e,e+h.length)==h&&(e+=h.length),s.replaceRange("",i(d,w),i(d,e)),E)for(var t=d+1;t<=c;++t){var r=s.getLine(t),o=r.indexOf(E);if(-1!=o&&!n.test(r.slice(0,o))){var a=o+E.length;h&&r.slice(a,a+h.length)==h&&(a+=h.length),s.replaceRange("",i(t,o),i(t,a))}}})),!0)}))}(t.a.exports);var a=i({__proto__:null,default:o.exports},[o.exports]);e.c=a})?r.apply(t,i):r)||(e.exports=o)},8058:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.d=e.a=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};e.a=o,function(e){function t(t,n,r){var i,o=t.getWrapperElement();return(i=o.appendChild(document.createElement("div"))).className=r?"CodeMirror-dialog CodeMirror-dialog-bottom":"CodeMirror-dialog CodeMirror-dialog-top","string"==typeof n?i.innerHTML=n:i.appendChild(n),e.addClass(o,"dialog-opened"),i}function n(e,t){e.state.currentNotificationClose&&e.state.currentNotificationClose(),e.state.currentNotificationClose=t}r(t,"dialogDiv"),r(n,"closeNotification"),e.defineExtension("openDialog",(function(i,o,a){a||(a={}),n(this,null);var s=t(this,i,a.bottom),l=!1,u=this;function c(t){if("string"==typeof t)f.value=t;else{if(l)return;l=!0,e.rmClass(s.parentNode,"dialog-opened"),s.parentNode.removeChild(s),u.focus(),a.onClose&&a.onClose(s)}}r(c,"close");var d,f=s.getElementsByTagName("input")[0];return f?(f.focus(),a.value&&(f.value=a.value,!1!==a.selectValueOnOpen&&f.select()),a.onInput&&e.on(f,"input",(function(e){a.onInput(e,f.value,c)})),a.onKeyUp&&e.on(f,"keyup",(function(e){a.onKeyUp(e,f.value,c)})),e.on(f,"keydown",(function(t){a&&a.onKeyDown&&a.onKeyDown(t,f.value,c)||((27==t.keyCode||!1!==a.closeOnEnter&&13==t.keyCode)&&(f.blur(),e.e_stop(t),c()),13==t.keyCode&&o(f.value,t))})),!1!==a.closeOnBlur&&e.on(s,"focusout",(function(e){null!==e.relatedTarget&&c()}))):(d=s.getElementsByTagName("button")[0])&&(e.on(d,"click",(function(){c(),u.focus()})),!1!==a.closeOnBlur&&e.on(d,"blur",c),d.focus()),c})),e.defineExtension("openConfirm",(function(i,o,a){n(this,null);var s=t(this,i,a&&a.bottom),l=s.getElementsByTagName("button"),u=!1,c=this,d=1;function f(){u||(u=!0,e.rmClass(s.parentNode,"dialog-opened"),s.parentNode.removeChild(s),c.focus())}r(f,"close"),l[0].focus();for(var p=0;pn(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){function t(t,i,a,s){if(a&&a.call){var l=a;a=null}else l=o(t,a,"rangeFinder");"number"==typeof i&&(i=e.Pos(i,0));var u=o(t,a,"minFoldSize");function c(e){var n=l(t,i);if(!n||n.to.line-n.from.linet.firstLine();)i=e.Pos(i.line-1,0),d=c(!1);if(d&&!d.cleared&&"unfold"!==s){var f=n(t,a,d);e.on(f,"mousedown",(function(t){p.clear(),e.e_preventDefault(t)}));var p=t.markText(d.from,d.to,{replacedWith:f,clearOnEnter:o(t,a,"clearOnEnter"),__isFold:!0});p.on("clear",(function(n,r){e.signal(t,"unfold",t,n,r)})),e.signal(t,"fold",t,d.from,d.to)}}function n(e,t,n){var r=o(e,t,"widget");if("function"==typeof r&&(r=r(n.from,n.to)),"string"==typeof r){var i=document.createTextNode(r);(r=document.createElement("span")).appendChild(i),r.className="CodeMirror-foldmarker"}else r&&(r=r.cloneNode(!0));return r}r(t,"doFold"),r(n,"makeWidget"),e.newFoldFunction=function(e,n){return function(r,i){t(r,i,{rangeFinder:e,widget:n})}},e.defineExtension("foldCode",(function(e,n,r){t(this,e,n,r)})),e.defineExtension("isFolded",(function(e){for(var t=this.findMarksAt(e),n=0;n=u){if(f&&l&&f.test(l.className))return;r=a(i.indicatorOpen)}}(r||l)&&e.setGutterMarker(n,i.gutter,r)}))}function l(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}function u(e){var t=e.getViewport(),n=e.state.foldGutter;n&&(e.operation((function(){s(e,t.from,t.to)})),n.from=t.from,n.to=t.to)}function c(e,n,r){var i=e.state.foldGutter;if(i){var a=i.options;if(r==a.gutter){var s=o(e,n);s?s.clear():e.foldCode(t(n,0),a)}}}function d(e){var t=e.state.foldGutter;if(t){var n=t.options;t.from=t.to=0,clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout((function(){u(e)}),n.foldOnChangeTimeSpan||600)}}function f(e){var t=e.state.foldGutter;if(t){var n=t.options;clearTimeout(t.changeUpdate),t.changeUpdate=setTimeout((function(){var n=e.getViewport();t.from==t.to||n.from-t.to>20||t.from-n.to>20?u(e):e.operation((function(){n.fromt.to&&(s(e,t.to,n.to),t.to=n.to)}))}),n.updateViewportTimeSpan||400)}}function p(e,t){var n=e.state.foldGutter;if(n){var r=t.line;r>=n.from&&r=0;e--)t(n[e])}Object.defineProperty(e,"__esModule",{value:!0}),e.f=t,(0,Object.defineProperty)(t,"name",{value:"forEachState",configurable:!0})})?n.apply(t,[t]):n)||(e.exports=r)},7139:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(6856),n(9196),n(3573),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"Argument",{enumerable:!0,get:function(){return t.A}}),Object.defineProperty(e,"ArgumentIcon",{enumerable:!0,get:function(){return t.ac}}),Object.defineProperty(e,"Button",{enumerable:!0,get:function(){return t.aH}}),Object.defineProperty(e,"ButtonGroup",{enumerable:!0,get:function(){return t.aI}}),Object.defineProperty(e,"ChevronDownIcon",{enumerable:!0,get:function(){return t.ad}}),Object.defineProperty(e,"ChevronLeftIcon",{enumerable:!0,get:function(){return t.ae}}),Object.defineProperty(e,"ChevronUpIcon",{enumerable:!0,get:function(){return t.af}}),Object.defineProperty(e,"CloseIcon",{enumerable:!0,get:function(){return t.ag}}),Object.defineProperty(e,"CopyIcon",{enumerable:!0,get:function(){return t.ah}}),Object.defineProperty(e,"DOC_EXPLORER_PLUGIN",{enumerable:!0,get:function(){return t._}}),Object.defineProperty(e,"DefaultValue",{enumerable:!0,get:function(){return t.D}}),Object.defineProperty(e,"DeprecatedArgumentIcon",{enumerable:!0,get:function(){return t.ai}}),Object.defineProperty(e,"DeprecatedEnumValueIcon",{enumerable:!0,get:function(){return t.aj}}),Object.defineProperty(e,"DeprecatedFieldIcon",{enumerable:!0,get:function(){return t.ak}}),Object.defineProperty(e,"DeprecationReason",{enumerable:!0,get:function(){return t.w}}),Object.defineProperty(e,"Dialog",{enumerable:!0,get:function(){return t.aJ}}),Object.defineProperty(e,"Directive",{enumerable:!0,get:function(){return t.x}}),Object.defineProperty(e,"DirectiveIcon",{enumerable:!0,get:function(){return t.al}}),Object.defineProperty(e,"DocExplorer",{enumerable:!0,get:function(){return t.y}}),Object.defineProperty(e,"DocsFilledIcon",{enumerable:!0,get:function(){return t.am}}),Object.defineProperty(e,"DocsIcon",{enumerable:!0,get:function(){return t.an}}),Object.defineProperty(e,"EditorContext",{enumerable:!0,get:function(){return t.E}}),Object.defineProperty(e,"EditorContextProvider",{enumerable:!0,get:function(){return t.d}}),Object.defineProperty(e,"EnumValueIcon",{enumerable:!0,get:function(){return t.ao}}),Object.defineProperty(e,"ExecuteButton",{enumerable:!0,get:function(){return t.aS}}),Object.defineProperty(e,"ExecutionContext",{enumerable:!0,get:function(){return t.r}}),Object.defineProperty(e,"ExecutionContextProvider",{enumerable:!0,get:function(){return t.s}}),Object.defineProperty(e,"ExplorerContext",{enumerable:!0,get:function(){return t.z}}),Object.defineProperty(e,"ExplorerContextProvider",{enumerable:!0,get:function(){return t.B}}),Object.defineProperty(e,"ExplorerSection",{enumerable:!0,get:function(){return t.F}}),Object.defineProperty(e,"FieldDocumentation",{enumerable:!0,get:function(){return t.G}}),Object.defineProperty(e,"FieldIcon",{enumerable:!0,get:function(){return t.ap}}),Object.defineProperty(e,"FieldLink",{enumerable:!0,get:function(){return t.J}}),Object.defineProperty(e,"GraphiQLProvider",{enumerable:!0,get:function(){return t.a3}}),Object.defineProperty(e,"HISTORY_PLUGIN",{enumerable:!0,get:function(){return t.$}}),Object.defineProperty(e,"HeaderEditor",{enumerable:!0,get:function(){return t.H}}),Object.defineProperty(e,"History",{enumerable:!0,get:function(){return t.W}}),Object.defineProperty(e,"HistoryContext",{enumerable:!0,get:function(){return t.X}}),Object.defineProperty(e,"HistoryContextProvider",{enumerable:!0,get:function(){return t.Y}}),Object.defineProperty(e,"HistoryIcon",{enumerable:!0,get:function(){return t.aq}}),Object.defineProperty(e,"ImagePreview",{enumerable:!0,get:function(){return t.I}}),Object.defineProperty(e,"ImplementsIcon",{enumerable:!0,get:function(){return t.ar}}),Object.defineProperty(e,"KeyboardShortcutIcon",{enumerable:!0,get:function(){return t.as}}),Object.defineProperty(e,"Listbox",{enumerable:!0,get:function(){return t.aL}}),Object.defineProperty(e,"MagnifyingGlassIcon",{enumerable:!0,get:function(){return t.at}}),Object.defineProperty(e,"MarkdownContent",{enumerable:!0,get:function(){return t.aM}}),Object.defineProperty(e,"Menu",{enumerable:!0,get:function(){return t.aK}}),Object.defineProperty(e,"MergeIcon",{enumerable:!0,get:function(){return t.au}}),Object.defineProperty(e,"PenIcon",{enumerable:!0,get:function(){return t.av}}),Object.defineProperty(e,"PlayIcon",{enumerable:!0,get:function(){return t.aw}}),Object.defineProperty(e,"PluginContext",{enumerable:!0,get:function(){return t.a0}}),Object.defineProperty(e,"PluginContextProvider",{enumerable:!0,get:function(){return t.a1}}),Object.defineProperty(e,"PlusIcon",{enumerable:!0,get:function(){return t.ax}}),Object.defineProperty(e,"PrettifyIcon",{enumerable:!0,get:function(){return t.ay}}),Object.defineProperty(e,"QueryEditor",{enumerable:!0,get:function(){return t.Q}}),Object.defineProperty(e,"ReloadIcon",{enumerable:!0,get:function(){return t.az}}),Object.defineProperty(e,"ResponseEditor",{enumerable:!0,get:function(){return t.R}}),Object.defineProperty(e,"RootTypeIcon",{enumerable:!0,get:function(){return t.aA}}),Object.defineProperty(e,"SchemaContext",{enumerable:!0,get:function(){return t.a4}}),Object.defineProperty(e,"SchemaContextProvider",{enumerable:!0,get:function(){return t.a5}}),Object.defineProperty(e,"SchemaDocumentation",{enumerable:!0,get:function(){return t.K}}),Object.defineProperty(e,"Search",{enumerable:!0,get:function(){return t.M}}),Object.defineProperty(e,"SettingsIcon",{enumerable:!0,get:function(){return t.aB}}),Object.defineProperty(e,"Spinner",{enumerable:!0,get:function(){return t.aN}}),Object.defineProperty(e,"StarFilledIcon",{enumerable:!0,get:function(){return t.aC}}),Object.defineProperty(e,"StarIcon",{enumerable:!0,get:function(){return t.aD}}),Object.defineProperty(e,"StopIcon",{enumerable:!0,get:function(){return t.aE}}),Object.defineProperty(e,"StorageContext",{enumerable:!0,get:function(){return t.a7}}),Object.defineProperty(e,"StorageContextProvider",{enumerable:!0,get:function(){return t.a8}}),Object.defineProperty(e,"Tab",{enumerable:!0,get:function(){return t.aO}}),Object.defineProperty(e,"Tabs",{enumerable:!0,get:function(){return t.aP}}),Object.defineProperty(e,"ToolbarButton",{enumerable:!0,get:function(){return t.aR}}),Object.defineProperty(e,"ToolbarListbox",{enumerable:!0,get:function(){return t.aT}}),Object.defineProperty(e,"ToolbarMenu",{enumerable:!0,get:function(){return t.aU}}),Object.defineProperty(e,"Tooltip",{enumerable:!0,get:function(){return t.aQ}}),Object.defineProperty(e,"TypeDocumentation",{enumerable:!0,get:function(){return t.N}}),Object.defineProperty(e,"TypeIcon",{enumerable:!0,get:function(){return t.aF}}),Object.defineProperty(e,"TypeLink",{enumerable:!0,get:function(){return t.O}}),Object.defineProperty(e,"UnStyledButton",{enumerable:!0,get:function(){return t.aG}}),Object.defineProperty(e,"VariableEditor",{enumerable:!0,get:function(){return t.V}}),Object.defineProperty(e,"useAutoCompleteLeafs",{enumerable:!0,get:function(){return t.u}}),Object.defineProperty(e,"useCopyQuery",{enumerable:!0,get:function(){return t.e}}),Object.defineProperty(e,"useDragResize",{enumerable:!0,get:function(){return t.ab}}),Object.defineProperty(e,"useEditorContext",{enumerable:!0,get:function(){return t.f}}),Object.defineProperty(e,"useExecutionContext",{enumerable:!0,get:function(){return t.v}}),Object.defineProperty(e,"useExplorerContext",{enumerable:!0,get:function(){return t.U}}),Object.defineProperty(e,"useHeaderEditor",{enumerable:!0,get:function(){return t.h}}),Object.defineProperty(e,"useHistoryContext",{enumerable:!0,get:function(){return t.Z}}),Object.defineProperty(e,"useMergeQuery",{enumerable:!0,get:function(){return t.j}}),Object.defineProperty(e,"usePluginContext",{enumerable:!0,get:function(){return t.a2}}),Object.defineProperty(e,"usePrettifyEditors",{enumerable:!0,get:function(){return t.k}}),Object.defineProperty(e,"useQueryEditor",{enumerable:!0,get:function(){return t.m}}),Object.defineProperty(e,"useResponseEditor",{enumerable:!0,get:function(){return t.n}}),Object.defineProperty(e,"useSchemaContext",{enumerable:!0,get:function(){return t.a6}}),Object.defineProperty(e,"useStorageContext",{enumerable:!0,get:function(){return t.a9}}),Object.defineProperty(e,"useTheme",{enumerable:!0,get:function(){return t.aa}}),Object.defineProperty(e,"useVariableEditor",{enumerable:!0,get:function(){return t.q}})})?r.apply(t,i):r)||(e.exports=o)},4840:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(6980),n(3573),n(6856),n(5609),n(9196),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o,a){"use strict";e.C.registerHelper("hint","graphql",((t,n)=>{const{schema:o,externalFragments:a}=n;if(!o)return;const s=t.getCursor(),l=t.getTokenAt(s),u=null!==l.type&&/"|\w/.test(l.string[0])?l.start:l.end,c=new i.P(s.line,u),d={list:(0,r.g)(o,t.getValue(),c,l,a).map((e=>({text:e.label,type:e.type,description:e.documentation,isDeprecated:e.isDeprecated,deprecationReason:e.deprecationReason}))),from:{line:s.line,ch:u},to:{line:s.line,ch:l.end}};return(null==d?void 0:d.list)&&d.list.length>0&&(d.from=e.C.Pos(d.from.line,d.from.ch),d.to=e.C.Pos(d.to.line,d.to.ch),e.C.signal(t,"hasCompletion",t,d,l)),d}))})?r.apply(t,i):r)||(e.exports=o)},4712:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(3573),n(2635),n(6856),n(9196),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o){"use strict";var a=Object.defineProperty,s=(e,t)=>a(e,"name",{value:t,configurable:!0});function l(e,t,n){const r=u(n,d(t.string));if(!r)return;const i=null!==t.type&&/"|\w/.test(t.string[0])?t.start:t.end;return{list:r,from:{line:e.line,ch:i},to:{line:e.line,ch:t.end}}}function u(e,t){return t?c(c(e.map((e=>({proximity:f(d(e.text),t),entry:e}))),(e=>e.proximity<=2)),(e=>!e.entry.isDeprecated)).sort(((e,t)=>(e.entry.isDeprecated?1:0)-(t.entry.isDeprecated?1:0)||e.proximity-t.proximity||e.entry.text.length-t.entry.text.length)).map((e=>e.entry)):c(e,(e=>!e.isDeprecated))}function c(e,t){const n=e.filter(t);return 0===n.length?e:n}function d(e){return e.toLowerCase().replaceAll(/\W/g,"")}function f(e,t){let n=p(t,e);return e.length>t.length&&(n-=e.length-t.length-1,n+=0===e.indexOf(t)?0:.5),n}function p(e,t){let n,r;const i=[],o=e.length,a=t.length;for(n=0;n<=o;n++)i[n]=[n];for(r=1;r<=a;r++)i[0][r]=r;for(n=1;n<=o;n++)for(r=1;r<=a;r++){const o=e[n-1]===t[r-1]?0:1;i[n][r]=Math.min(i[n-1][r]+1,i[n][r-1]+1,i[n-1][r-1]+o),n>1&&r>1&&e[n-1]===t[r-2]&&e[n-2]===t[r-1]&&(i[n][r]=Math.min(i[n][r],i[n-2][r-2]+o))}return i[o][a]}function h(e,n,r){const i="Invalid"===n.state.kind?n.state.prevState:n.state,{kind:o,step:a}=i;if("Document"===o&&0===a)return l(e,n,[{text:"{"}]);const{variableToType:s}=r;if(!s)return;const u=m(s,n.state);if("Document"===o||"Variable"===o&&0===a)return l(e,n,Object.keys(s).map((e=>({text:`"${e}": `,type:s[e]}))));if(("ObjectValue"===o||"ObjectField"===o&&0===a)&&u.fields)return l(e,n,Object.keys(u.fields).map((e=>u.fields[e])).map((e=>({text:`"${e.name}": `,type:e.type,description:e.description}))));if("StringValue"===o||"NumberValue"===o||"BooleanValue"===o||"NullValue"===o||"ListValue"===o&&1===a||"ObjectField"===o&&2===a||"Variable"===o&&2===a){const r=u.type?(0,t.getNamedType)(u.type):void 0;if(r instanceof t.GraphQLInputObjectType)return l(e,n,[{text:"{"}]);if(r instanceof t.GraphQLEnumType)return l(e,n,r.getValues().map((e=>({text:`"${e.name}"`,type:r,description:e.description}))));if(r===t.GraphQLBoolean)return l(e,n,[{text:"true",type:t.GraphQLBoolean,description:"Not false."},{text:"false",type:t.GraphQLBoolean,description:"Not true."}])}}function m(e,r){const i={type:null,fields:null};return(0,n.f)(r,(n=>{switch(n.kind){case"Variable":i.type=e[n.name];break;case"ListValue":{const e=i.type?(0,t.getNullableType)(i.type):void 0;i.type=e instanceof t.GraphQLList?e.ofType:null;break}case"ObjectValue":{const e=i.type?(0,t.getNamedType)(i.type):void 0;i.fields=e instanceof t.GraphQLInputObjectType?e.getFields():null;break}case"ObjectField":{const e=n.name&&i.fields?i.fields[n.name]:null;i.type=null==e?void 0:e.type;break}}})),i}s(l,"hintList"),s(u,"filterAndSortList"),s(c,"filterNonEmpty"),s(d,"normalizeText"),s(f,"getProximity"),s(p,"lexicalDistance"),e.C.registerHelper("hint","graphql-variables",((t,n)=>{const r=t.getCursor(),i=t.getTokenAt(r),o=h(r,i,n);return(null==o?void 0:o.list)&&o.list.length>0&&(o.from=e.C.Pos(o.from.line,o.from.ch),o.to=e.C.Pos(o.to.line,o.to.ch),e.C.signal(t,"hasCompletion",t,o,i)),o})),s(h,"getVariablesHint"),s(m,"getTypeInfo")})?r.apply(t,i):r)||(e.exports=o)},6856:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(9196),n(3573),n(1850)],r=function(e,t,r,i){"use strict";function o(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(o=function(e){return e?n:t})(e)}function a(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=o(t);if(n&&n.has(e))return n.get(e);var r={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var s=i?Object.getOwnPropertyDescriptor(e,a):null;s&&(s.get||s.set)?Object.defineProperty(r,a,s):r[a]=e[a]}return r.default=e,n&&n.set(e,r),r}Object.defineProperty(e,"__esModule",{value:!0}),e.$=void 0,e.A=JE,e.B=$E,e.C=void 0,e.D=IE,e.E=void 0,e.F=sT,e.G=dT,e.H=cS,e.I=pS,e.J=Lw,e.K=gT,e.L=void 0,e.M=xw,e.N=Rw,e.O=QE,e.P=void 0,e.Q=yS,e.R=SS,e.U=e.T=e.S=void 0,e.V=NS,e.W=oE,e.X=void 0,e.Y=eE,e.a0=e.a=e._=e.Z=void 0,e.a1=Xw,e.a2=void 0,e.a3=IS,e.a4=void 0,e.a5=ME,e.a7=e.a6=void 0,e.a8=ve,e.aR=e.aQ=e.aP=e.aO=e.aN=e.aM=e.aL=e.aK=e.aJ=e.aI=e.aH=e.aG=e.aF=e.aE=e.aD=e.aC=e.aB=e.aA=e.a9=void 0,e.aS=HS,e.aU=e.aT=void 0,e.aa=AS,e.ab=PS,e.az=e.ay=e.ax=e.aw=e.av=e.au=e.at=e.as=e.ar=e.aq=e.ap=e.ao=e.an=e.am=e.al=e.ak=e.aj=e.ai=e.ah=e.ag=e.af=e.ae=e.ad=e.ac=void 0,e.b=_i,e.c=void 0,e.d=iS,e.e=uC,e.f=void 0,e.g=eo,e.h=mC,e.i=void 0,e.j=cC,e.k=dC,e.l=Oi,e.m=SC,e.n=TS,e.o=Vi,e.p=Li,e.q=ZC,e.r=void 0,e.s=dE,e.t=Di,e.u=fC,e.v=void 0,e.w=tT,e.x=iT,e.y=Hw,e.z=void 0,t=a(t),i=a(i);var s=Object.defineProperty,l=Object.defineProperties,u=Object.getOwnPropertyDescriptors,c=Object.getOwnPropertySymbols,d=Object.prototype.hasOwnProperty,f=Object.prototype.propertyIsEnumerable,p=(e,t,n)=>t in e?s(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,h=(e,t)=>{for(var n in t||(t={}))d.call(t,n)&&p(e,n,t[n]);if(c)for(var n of c(t))f.call(t,n)&&p(e,n,t[n]);return e},m=(e,t)=>l(e,u(t)),g=(e,t)=>s(e,"name",{value:t,configurable:!0}),v=(e,t)=>{var n={};for(var r in e)d.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&c)for(var r of c(e))t.indexOf(r)<0&&f.call(e,r)&&(n[r]=e[r]);return n};function y(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t{const r=e.subscribe({next:e=>{t(e),r.unsubscribe()},error:n,complete:()=>{n(new Error("no value resolved"))}})}))}function C(e){return"object"==typeof e&&null!==e&&"subscribe"in e&&"function"==typeof e.subscribe}function S(e){return"object"==typeof e&&null!==e&&("AsyncGenerator"===e[Symbol.toStringTag]||Symbol.asyncIterator in e)}function x(e){var t;return E(this,void 0,void 0,(function*(){const n=null===(t=("return"in e?e:e[Symbol.asyncIterator]()).return)||void 0===t?void 0:t.bind(e),r=("next"in e?e:e[Symbol.asyncIterator]()).next.bind(e),i=yield r();return null==n||n(),i.value}))}function k(e){return E(this,void 0,void 0,(function*(){const t=yield e;return S(t)?x(t):C(t)?w(t):t}))}g(T,"isPromise"),g(w,"observableToPromise"),g(C,"isObservable"),g(S,"isAsyncIterable"),g(x,"asyncIterableToPromise"),g(k,"fetcherReturnToPromise"),globalThis&&globalThis.__awaiter;var N=globalThis&&globalThis.__await||function(e){return this instanceof N?(this.v=e,this):new N(e)};function _(e){return JSON.stringify(e,null,2)}function O(e){return Object.assign(Object.assign({},e),{message:e.message,stack:e.stack})}function I(e){return e instanceof Error?O(e):e}function D(e){return Array.isArray(e)?_({errors:e.map((e=>I(e)))}):_({errors:[I(e)]})}function L(e){return _(e)}function A(e,t,n){const i=[];if(!e||!t)return{insertions:i,result:t};let o;try{o=(0,r.parse)(t)}catch(e){return{insertions:i,result:t}}const a=n||M,s=new r.TypeInfo(e);return(0,r.visit)(o,{leave(e){s.leave(e)},enter(e){if(s.enter(e),"Field"===e.kind&&!e.selectionSet){const n=R(j(s.getType()),a);if(n&&e.loc){const o=P(t,e.loc.start);i.push({index:e.loc.end,string:" "+(0,r.print)(n).replaceAll("\n","\n"+o)})}}}}),{insertions:i,result:F(t,i)}}function M(e){if(!("getFields"in e))return[];const t=e.getFields();if(t.id)return["id"];if(t.edges)return["edges"];if(t.node)return["node"];const n=[];for(const e of Object.keys(t))(0,r.isLeafType)(t[e].type)&&n.push(e);return n}function R(e,t){const n=(0,r.getNamedType)(e);if(!e||(0,r.isLeafType)(e))return;const i=t(n);return Array.isArray(i)&&0!==i.length&&"getFields"in n?{kind:r.Kind.SELECTION_SET,selections:i.map((e=>{const i=n.getFields()[e],o=i?i.type:null;return{kind:r.Kind.FIELD,name:{kind:r.Kind.NAME,value:e},selectionSet:R(o,t)}}))}:void 0}function F(e,t){if(0===t.length)return e;let n="",r=0;for(const{index:i,string:o}of t)n+=e.slice(r,i)+o,r=i;return n+=e.slice(r),n}function P(e,t){let n=t,r=t;for(;n;){const t=e.charCodeAt(n-1);if(10===t||13===t||8232===t||8233===t)break;n--,9!==t&&11!==t&&12!==t&&32!==t&&160!==t&&(r=n)}return e.slice(n,r)}function j(e){if(e)return e}function V(e,t){var n;const r=new Map,i=[];for(const o of e)if("Field"===o.kind){const e=t(o),a=r.get(e);if(null===(n=o.directives)||void 0===n?void 0:n.length){const e=Object.assign({},o);i.push(e)}else if((null==a?void 0:a.selectionSet)&&o.selectionSet)a.selectionSet.selections=[...a.selectionSet.selections,...o.selectionSet.selections];else if(!a){const t=Object.assign({},o);r.set(e,t),i.push(t)}}else i.push(o);return i}function U(e,t,n){var i;const o=n?(0,r.getNamedType)(n).name:null,a=[],s=[];for(let l of t){if("FragmentSpread"===l.kind){const t=l.name.value;if(!l.directives||0===l.directives.length){if(s.includes(t))continue;s.push(t)}const n=e[l.name.value];if(n){const{typeCondition:e,directives:t,selectionSet:i}=n;l={kind:r.Kind.INLINE_FRAGMENT,typeCondition:e,directives:t,selectionSet:i}}}if(l.kind===r.Kind.INLINE_FRAGMENT&&(!l.directives||0===(null===(i=l.directives)||void 0===i?void 0:i.length))){const t=l.typeCondition?l.typeCondition.name.value:null;if(!t||t===o){a.push(...U(e,l.selectionSet.selections,n));continue}}a.push(l)}return a}function B(e,t){const n=t?new r.TypeInfo(t):null,i=Object.create(null);for(const t of e.definitions)t.kind===r.Kind.FRAGMENT_DEFINITION&&(i[t.name.value]=t);const o={SelectionSet(e){const t=n?n.getParentType():null;let{selections:r}=e;return r=U(i,r,t),r=V(r,(e=>e.alias?e.alias.value:e.name.value)),Object.assign(Object.assign({},e),{selections:r})},FragmentDefinition(){return null}};return(0,r.visit)(e,n?(0,r.visitWithTypeInfo)(n,o):o)}function $(e,t,n){if(!n||n.length<1)return;const r=n.map((e=>{var t;return null===(t=e.name)||void 0===t?void 0:t.value}));if(t&&r.includes(t))return t;if(t&&e){const n=e.map((e=>{var t;return null===(t=e.name)||void 0===t?void 0:t.value})).indexOf(t);if(-1!==n&&n{for(const e in window.localStorage)0===e.indexOf(`${G}:`)&&window.localStorage.removeItem(e)}}}get(e){if(!this.storage)return null;const t=`${G}:${e}`,n=this.storage.getItem(t);return"null"===n||"undefined"===n?(this.storage.removeItem(t),null):n||null}set(e,t){let n=!1,r=null;if(this.storage){const i=`${G}:${e}`;if(t)try{this.storage.setItem(i,t)}catch(e){r=e instanceof Error?e:new Error(`${e}`),n=q(this.storage,e)}else this.storage.removeItem(i)}return{isQuotaError:n,error:r}}clear(){this.storage&&this.storage.clear()}}g(H,"StorageAPI");const G="graphiql";class z{constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;this.key=e,this.storage=t,this.maxSize=n,this.items=this.fetchAll()}get length(){return this.items.length}contains(e){return this.items.some((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName))}edit(e){const t=this.items.findIndex((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName));-1!==t&&(this.items.splice(t,1,e),this.save())}delete(e){const t=this.items.findIndex((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName));-1!==t&&(this.items.splice(t,1),this.save())}fetchRecent(){return this.items.at(-1)}fetchAll(){const e=this.storage.get(this.key);return e?JSON.parse(e)[this.key]:[]}push(e){const t=[...this.items,e];this.maxSize&&t.length>this.maxSize&&t.shift();for(let e=0;e<5;e++){const e=this.storage.set(this.key,JSON.stringify({[this.key]:t}));if(null==e?void 0:e.error){if(!e.isQuotaError||!this.maxSize)return;t.shift()}else this.items=t}}save(){this.storage.set(this.key,JSON.stringify({[this.key]:this.items}))}}g(z,"QueryStore");class W{constructor(e,t){this.storage=e,this.maxHistoryLength=t,this.updateHistory=(e,t,n,r)=>{if(this.shouldSaveQuery(e,t,n,this.history.fetchRecent())){this.history.push({query:e,variables:t,headers:n,operationName:r});const i=this.history.items,o=this.favorite.items;this.queries=i.concat(o)}},this.history=new z("queries",this.storage,this.maxHistoryLength),this.favorite=new z("favorites",this.storage,null),this.queries=[...this.history.fetchAll(),...this.favorite.fetchAll()]}shouldSaveQuery(e,t,n,i){if(!e)return!1;try{(0,r.parse)(e)}catch(e){return!1}if(e.length>1e5)return!1;if(!i)return!0;if(JSON.stringify(e)===JSON.stringify(i.query)){if(JSON.stringify(t)===JSON.stringify(i.variables)){if(JSON.stringify(n)===JSON.stringify(i.headers))return!1;if(n&&!i.headers)return!1}if(t&&!i.variables)return!1}return!0}toggleFavorite(e,t,n,r,i,o){const a={query:e,variables:t,headers:n,operationName:r,label:i};this.favorite.contains(a)?o&&(a.favorite=!1,this.favorite.delete(a)):(a.favorite=!0,this.favorite.push(a)),this.queries=[...this.history.items,...this.favorite.items]}editLabel(e,t,n,r,i,o){const a={query:e,variables:t,headers:n,operationName:r,label:i};o?this.favorite.edit(Object.assign(Object.assign({},a),{favorite:o})):this.history.edit(a),this.queries=[...this.history.items,...this.favorite.items]}}g(W,"HistoryStore");var K=Object.defineProperty,Q=g(((e,t)=>K(e,"name",{value:t,configurable:!0})),"__name$G");function X(e){const n=(0,t.createContext)(null);return n.displayName=e,n}function Y(e){function n(r){var i;const o=(0,t.useContext)(e);if(null===o&&(null==r?void 0:r.nonNull))throw new Error(`Tried to use \`${(null==(i=r.caller)?void 0:i.name)||n.caller.name}\` without the necessary context. Make sure to render the \`${e.displayName}Provider\` component higher up the tree.`);return o}return g(n,"useGivenContext"),Q(n,"useGivenContext"),Object.defineProperty(n,"name",{value:`use${e.displayName}`}),n}g(X,"createNullableContext"),Q(X,"createNullableContext"),g(Y,"createContextHook"),Q(Y,"createContextHook");var J="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:"undefined"!=typeof self?self:{};function Z(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function ee(e){if(e.__esModule)return e;var t=Object.defineProperty({},"__esModule",{value:!0});return Object.keys(e).forEach((function(n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})})),t}e.c=J,g(Z,"getDefaultExportFromCjs"),g(ee,"getAugmentedNamespace");var te={exports:{}},ne={};function re(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}Object.getOwnPropertySymbols,Object.prototype.hasOwnProperty,Object.prototype.propertyIsEnumerable,g((function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}),"toObject"),g(re,"shouldUseNative"),re()&&Object.assign;var ie=t.default,oe=60103;if(ne.Fragment=60107,"function"==typeof Symbol&&Symbol.for){var ae=Symbol.for;oe=ae("react.element"),ne.Fragment=ae("react.fragment")}var se=ie.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,le=Object.prototype.hasOwnProperty,ue={key:!0,ref:!0,__self:!0,__source:!0};function ce(e,t,n){var r,i={},o=null,a=null;for(r in void 0!==n&&(o=""+n),void 0!==t.key&&(o=""+t.key),void 0!==t.ref&&(a=t.ref),t)le.call(t,r)&&!ue.hasOwnProperty(r)&&(i[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===i[r]&&(i[r]=t[r]);return{$$typeof:oe,type:e,key:o,ref:a,props:i,_owner:se.current}}g(ce,"q$1"),ne.jsx=ce,ne.jsxs=ce,te.exports=ne;const de=te.exports.jsx,fe=te.exports.jsxs,pe=te.exports.Fragment;var he=Object.defineProperty,me=g(((e,t)=>he(e,"name",{value:t,configurable:!0})),"__name$F");const ge=X("StorageContext");function ve(e){const n=(0,t.useRef)(!0),[r,i]=(0,t.useState)(new H(e.storage));return(0,t.useEffect)((()=>{n.current?n.current=!1:i(new H(e.storage))}),[e.storage]),de(ge.Provider,{value:r,children:e.children})}e.a7=ge,g(ve,"StorageContextProvider"),me(ve,"StorageContextProvider");const ye=Y(ge);e.a9=ye;const be=10,Ee=2;function Te(e){return we(e,[])}function we(e,t){switch(typeof e){case"string":return JSON.stringify(e);case"function":return e.name?`[function ${e.name}]`:"[function]";case"object":return Ce(e,t);default:return String(e)}}function Ce(e,t){if(null===e)return"null";if(t.includes(e))return"[Circular]";const n=[...t,e];if(Se(e)){const t=e.toJSON();if(t!==e)return"string"==typeof t?t:we(t,n)}else if(Array.isArray(e))return ke(e,n);return xe(e,n)}function Se(e){return"function"==typeof e.toJSON}function xe(e,t){const n=Object.entries(e);return 0===n.length?"{}":t.length>Ee?"["+Ne(e)+"]":"{ "+n.map((e=>{let[n,r]=e;return n+": "+we(r,t)})).join(", ")+" }"}function ke(e,t){if(0===e.length)return"[]";if(t.length>Ee)return"[Array]";const n=Math.min(be,e.length),r=e.length-n,i=[];for(let r=0;r1&&i.push(`... ${r} more items`),"["+i.join(", ")+"]"}function Ne(e){const t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){const t=e.constructor.name;if("string"==typeof t&&""!==t)return t}return t}function _e(e,t){if(!Boolean(e))throw new Error(null!=t?t:"Unexpected invariant triggered.")}let Oe;function Ie(e){return 9===e||32===e}function De(e){return e>=48&&e<=57}function Le(e){return e>=97&&e<=122||e>=65&&e<=90}function Ae(e){return Le(e)||95===e}function Me(e){return Le(e)||De(e)||95===e}function Re(e,t){const n=e.replace(/"""/g,'\\"""'),r=n.split(/\r\n|[\n\r]/g),i=1===r.length,o=r.length>1&&r.slice(1).every((e=>0===e.length||Ie(e.charCodeAt(0)))),a=n.endsWith('\\"""'),s=e.endsWith('"')&&!a,l=e.endsWith("\\"),u=s||l,c=!(null!=t&&t.minimize)&&(!i||e.length>70||u||o||a);let d="";const f=i&&Ie(e.charCodeAt(0));return(c&&!f||o)&&(d+="\n"),d+=n,(c||u)&&(d+="\n"),'"""'+d+'"""'}function Fe(e){return`"${e.replace(je,Ve)}"`}var Pe;g(Te,"inspect"),g(we,"formatValue"),g(Ce,"formatObjectValue"),g(Se,"isJSONable"),g(xe,"formatObject"),g(ke,"formatArray"),g(Ne,"getObjectTag"),g(_e,"invariant"),(Pe=Oe||(Oe={})).QUERY="QUERY",Pe.MUTATION="MUTATION",Pe.SUBSCRIPTION="SUBSCRIPTION",Pe.FIELD="FIELD",Pe.FRAGMENT_DEFINITION="FRAGMENT_DEFINITION",Pe.FRAGMENT_SPREAD="FRAGMENT_SPREAD",Pe.INLINE_FRAGMENT="INLINE_FRAGMENT",Pe.VARIABLE_DEFINITION="VARIABLE_DEFINITION",Pe.SCHEMA="SCHEMA",Pe.SCALAR="SCALAR",Pe.OBJECT="OBJECT",Pe.FIELD_DEFINITION="FIELD_DEFINITION",Pe.ARGUMENT_DEFINITION="ARGUMENT_DEFINITION",Pe.INTERFACE="INTERFACE",Pe.UNION="UNION",Pe.ENUM="ENUM",Pe.ENUM_VALUE="ENUM_VALUE",Pe.INPUT_OBJECT="INPUT_OBJECT",Pe.INPUT_FIELD_DEFINITION="INPUT_FIELD_DEFINITION",g(Ie,"isWhiteSpace$2"),g(De,"isDigit$1"),g(Le,"isLetter$1"),g(Ae,"isNameStart"),g(Me,"isNameContinue"),g(Re,"printBlockString"),g(Fe,"printString");const je=/[\x00-\x1f\x22\x5c\x7f-\x9f]/g;function Ve(e){return Ue[e.charCodeAt(0)]}g(Ve,"escapedReplacer");const Ue=["\\u0000","\\u0001","\\u0002","\\u0003","\\u0004","\\u0005","\\u0006","\\u0007","\\b","\\t","\\n","\\u000B","\\f","\\r","\\u000E","\\u000F","\\u0010","\\u0011","\\u0012","\\u0013","\\u0014","\\u0015","\\u0016","\\u0017","\\u0018","\\u0019","\\u001A","\\u001B","\\u001C","\\u001D","\\u001E","\\u001F","","",'\\"',"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\\\","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\u007F","\\u0080","\\u0081","\\u0082","\\u0083","\\u0084","\\u0085","\\u0086","\\u0087","\\u0088","\\u0089","\\u008A","\\u008B","\\u008C","\\u008D","\\u008E","\\u008F","\\u0090","\\u0091","\\u0092","\\u0093","\\u0094","\\u0095","\\u0096","\\u0097","\\u0098","\\u0099","\\u009A","\\u009B","\\u009C","\\u009D","\\u009E","\\u009F"];function Be(e,t){if(!Boolean(e))throw new Error(t)}g(Be,"devAssert");const $e={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},qe=new Set(Object.keys($e));function He(e){const t=null==e?void 0:e.kind;return"string"==typeof t&&qe.has(t)}let Ge,ze;var We,Ke;g(He,"isNode"),(Ke=Ge||(Ge={})).QUERY="query",Ke.MUTATION="mutation",Ke.SUBSCRIPTION="subscription",(We=ze||(ze={})).NAME="Name",We.DOCUMENT="Document",We.OPERATION_DEFINITION="OperationDefinition",We.VARIABLE_DEFINITION="VariableDefinition",We.SELECTION_SET="SelectionSet",We.FIELD="Field",We.ARGUMENT="Argument",We.FRAGMENT_SPREAD="FragmentSpread",We.INLINE_FRAGMENT="InlineFragment",We.FRAGMENT_DEFINITION="FragmentDefinition",We.VARIABLE="Variable",We.INT="IntValue",We.FLOAT="FloatValue",We.STRING="StringValue",We.BOOLEAN="BooleanValue",We.NULL="NullValue",We.ENUM="EnumValue",We.LIST="ListValue",We.OBJECT="ObjectValue",We.OBJECT_FIELD="ObjectField",We.DIRECTIVE="Directive",We.NAMED_TYPE="NamedType",We.LIST_TYPE="ListType",We.NON_NULL_TYPE="NonNullType",We.SCHEMA_DEFINITION="SchemaDefinition",We.OPERATION_TYPE_DEFINITION="OperationTypeDefinition",We.SCALAR_TYPE_DEFINITION="ScalarTypeDefinition",We.OBJECT_TYPE_DEFINITION="ObjectTypeDefinition",We.FIELD_DEFINITION="FieldDefinition",We.INPUT_VALUE_DEFINITION="InputValueDefinition",We.INTERFACE_TYPE_DEFINITION="InterfaceTypeDefinition",We.UNION_TYPE_DEFINITION="UnionTypeDefinition",We.ENUM_TYPE_DEFINITION="EnumTypeDefinition",We.ENUM_VALUE_DEFINITION="EnumValueDefinition",We.INPUT_OBJECT_TYPE_DEFINITION="InputObjectTypeDefinition",We.DIRECTIVE_DEFINITION="DirectiveDefinition",We.SCHEMA_EXTENSION="SchemaExtension",We.SCALAR_TYPE_EXTENSION="ScalarTypeExtension",We.OBJECT_TYPE_EXTENSION="ObjectTypeExtension",We.INTERFACE_TYPE_EXTENSION="InterfaceTypeExtension",We.UNION_TYPE_EXTENSION="UnionTypeExtension",We.ENUM_TYPE_EXTENSION="EnumTypeExtension",We.INPUT_OBJECT_TYPE_EXTENSION="InputObjectTypeExtension";const Qe=Object.freeze({});function Xe(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:$e;const r=new Map;for(const e of Object.values(ze))r.set(e,Ye(t,e));let i,o,a,s=Array.isArray(e),l=[e],u=-1,c=[],d=e;const f=[],p=[];do{u++;const e=u===l.length,v=e&&0!==c.length;if(e){if(o=0===p.length?void 0:f[f.length-1],d=a,a=p.pop(),v)if(s){d=d.slice();let e=0;for(const[t,n]of c){const r=t-e;null===n?(d.splice(r,1),e++):d[r]=n}}else{d=Object.defineProperties({},Object.getOwnPropertyDescriptors(d));for(const[e,t]of c)d[e]=t}u=i.index,l=i.keys,c=i.edits,s=i.inArray,i=i.prev}else if(a){if(o=s?u:l[u],d=a[o],null==d)continue;f.push(o)}let y;if(!Array.isArray(d)){var h,m;He(d)||Be(!1,`Invalid AST Node: ${Te(d)}.`);const n=e?null===(h=r.get(d.kind))||void 0===h?void 0:h.leave:null===(m=r.get(d.kind))||void 0===m?void 0:m.enter;if(y=null==n?void 0:n.call(t,d,o,a,f,p),y===Qe)break;if(!1===y){if(!e){f.pop();continue}}else if(void 0!==y&&(c.push([o,y]),!e)){if(!He(y)){f.pop();continue}d=y}}var g;void 0===y&&v&&c.push([o,d]),e?f.pop():(i={inArray:s,index:u,keys:l,edits:c,prev:i},s=Array.isArray(d),l=s?d:null!==(g=n[d.kind])&&void 0!==g?g:[],u=-1,c=[],a&&p.push(a),a=d)}while(void 0!==i);return 0!==c.length?c[c.length-1][1]:e}function Ye(e,t){const n=e[t];return"object"==typeof n?n:"function"==typeof n?{enter:n,leave:void 0}:{enter:e.enter,leave:e.leave}}function Je(e){return Xe(e,Ze)}g(Xe,"visit"),g(Ye,"getEnterLeaveForKind"),g(Je,"print");const Ze={Name:{leave:e=>e.value},Variable:{leave:e=>"$"+e.name},Document:{leave:e=>et(e.definitions,"\n\n")},OperationDefinition:{leave(e){const t=nt("(",et(e.variableDefinitions,", "),")"),n=et([e.operation,et([e.name,t]),et(e.directives," ")]," ");return("query"===n?"":n+" ")+e.selectionSet}},VariableDefinition:{leave:e=>{let{variable:t,type:n,defaultValue:r,directives:i}=e;return t+": "+n+nt(" = ",r)+nt(" ",et(i," "))}},SelectionSet:{leave:e=>{let{selections:t}=e;return tt(t)}},Field:{leave(e){let{alias:t,name:n,arguments:r,directives:i,selectionSet:o}=e;const a=nt("",t,": ")+n;let s=a+nt("(",et(r,", "),")");return s.length>80&&(s=a+nt("(\n",rt(et(r,"\n")),"\n)")),et([s,et(i," "),o]," ")}},Argument:{leave:e=>{let{name:t,value:n}=e;return t+": "+n}},FragmentSpread:{leave:e=>{let{name:t,directives:n}=e;return"..."+t+nt(" ",et(n," "))}},InlineFragment:{leave:e=>{let{typeCondition:t,directives:n,selectionSet:r}=e;return et(["...",nt("on ",t),et(n," "),r]," ")}},FragmentDefinition:{leave:e=>{let{name:t,typeCondition:n,variableDefinitions:r,directives:i,selectionSet:o}=e;return`fragment ${t}${nt("(",et(r,", "),")")} on ${n} ${nt("",et(i," ")," ")}`+o}},IntValue:{leave:e=>{let{value:t}=e;return t}},FloatValue:{leave:e=>{let{value:t}=e;return t}},StringValue:{leave:e=>{let{value:t,block:n}=e;return n?Re(t):Fe(t)}},BooleanValue:{leave:e=>{let{value:t}=e;return t?"true":"false"}},NullValue:{leave:()=>"null"},EnumValue:{leave:e=>{let{value:t}=e;return t}},ListValue:{leave:e=>{let{values:t}=e;return"["+et(t,", ")+"]"}},ObjectValue:{leave:e=>{let{fields:t}=e;return"{"+et(t,", ")+"}"}},ObjectField:{leave:e=>{let{name:t,value:n}=e;return t+": "+n}},Directive:{leave:e=>{let{name:t,arguments:n}=e;return"@"+t+nt("(",et(n,", "),")")}},NamedType:{leave:e=>{let{name:t}=e;return t}},ListType:{leave:e=>{let{type:t}=e;return"["+t+"]"}},NonNullType:{leave:e=>{let{type:t}=e;return t+"!"}},SchemaDefinition:{leave:e=>{let{description:t,directives:n,operationTypes:r}=e;return nt("",t,"\n")+et(["schema",et(n," "),tt(r)]," ")}},OperationTypeDefinition:{leave:e=>{let{operation:t,type:n}=e;return t+": "+n}},ScalarTypeDefinition:{leave:e=>{let{description:t,name:n,directives:r}=e;return nt("",t,"\n")+et(["scalar",n,et(r," ")]," ")}},ObjectTypeDefinition:{leave:e=>{let{description:t,name:n,interfaces:r,directives:i,fields:o}=e;return nt("",t,"\n")+et(["type",n,nt("implements ",et(r," & ")),et(i," "),tt(o)]," ")}},FieldDefinition:{leave:e=>{let{description:t,name:n,arguments:r,type:i,directives:o}=e;return nt("",t,"\n")+n+(it(r)?nt("(\n",rt(et(r,"\n")),"\n)"):nt("(",et(r,", "),")"))+": "+i+nt(" ",et(o," "))}},InputValueDefinition:{leave:e=>{let{description:t,name:n,type:r,defaultValue:i,directives:o}=e;return nt("",t,"\n")+et([n+": "+r,nt("= ",i),et(o," ")]," ")}},InterfaceTypeDefinition:{leave:e=>{let{description:t,name:n,interfaces:r,directives:i,fields:o}=e;return nt("",t,"\n")+et(["interface",n,nt("implements ",et(r," & ")),et(i," "),tt(o)]," ")}},UnionTypeDefinition:{leave:e=>{let{description:t,name:n,directives:r,types:i}=e;return nt("",t,"\n")+et(["union",n,et(r," "),nt("= ",et(i," | "))]," ")}},EnumTypeDefinition:{leave:e=>{let{description:t,name:n,directives:r,values:i}=e;return nt("",t,"\n")+et(["enum",n,et(r," "),tt(i)]," ")}},EnumValueDefinition:{leave:e=>{let{description:t,name:n,directives:r}=e;return nt("",t,"\n")+et([n,et(r," ")]," ")}},InputObjectTypeDefinition:{leave:e=>{let{description:t,name:n,directives:r,fields:i}=e;return nt("",t,"\n")+et(["input",n,et(r," "),tt(i)]," ")}},DirectiveDefinition:{leave:e=>{let{description:t,name:n,arguments:r,repeatable:i,locations:o}=e;return nt("",t,"\n")+"directive @"+n+(it(r)?nt("(\n",rt(et(r,"\n")),"\n)"):nt("(",et(r,", "),")"))+(i?" repeatable":"")+" on "+et(o," | ")}},SchemaExtension:{leave:e=>{let{directives:t,operationTypes:n}=e;return et(["extend schema",et(t," "),tt(n)]," ")}},ScalarTypeExtension:{leave:e=>{let{name:t,directives:n}=e;return et(["extend scalar",t,et(n," ")]," ")}},ObjectTypeExtension:{leave:e=>{let{name:t,interfaces:n,directives:r,fields:i}=e;return et(["extend type",t,nt("implements ",et(n," & ")),et(r," "),tt(i)]," ")}},InterfaceTypeExtension:{leave:e=>{let{name:t,interfaces:n,directives:r,fields:i}=e;return et(["extend interface",t,nt("implements ",et(n," & ")),et(r," "),tt(i)]," ")}},UnionTypeExtension:{leave:e=>{let{name:t,directives:n,types:r}=e;return et(["extend union",t,et(n," "),nt("= ",et(r," | "))]," ")}},EnumTypeExtension:{leave:e=>{let{name:t,directives:n,values:r}=e;return et(["extend enum",t,et(n," "),tt(r)]," ")}},InputObjectTypeExtension:{leave:e=>{let{name:t,directives:n,fields:r}=e;return et(["extend input",t,et(n," "),tt(r)]," ")}}};function et(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";var n;return null!==(n=null==e?void 0:e.filter((e=>e)).join(t))&&void 0!==n?n:""}function tt(e){return nt("{\n",rt(et(e,"\n")),"\n}")}function nt(e,t){return null!=t&&""!==t?e+t+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:""):""}function rt(e){return nt(" ",e.replace(/\n/g,"\n "))}function it(e){var t;return null!==(t=null==e?void 0:e.some((e=>e.includes("\n"))))&&void 0!==t&&t}function ot(e){return"object"==typeof e&&"function"==typeof(null==e?void 0:e[Symbol.iterator])}function at(e){return"object"==typeof e&&null!==e}g(et,"join"),g(tt,"block$2"),g(nt,"wrap"),g(rt,"indent"),g(it,"hasMultilineItems"),g(ot,"isIterableObject"),g(at,"isObjectLike");const st=5;function lt(e,t){const[n,r]=t?[e,t]:[void 0,e];let i=" Did you mean ";n&&(i+=n+" ");const o=r.map((e=>`"${e}"`));switch(o.length){case 0:return"";case 1:return i+o[0]+"?";case 2:return i+o[0]+" or "+o[1]+"?"}const a=o.slice(0,st),s=a.pop();return i+a.join(", ")+", or "+s+"?"}function ut(e){return e}g(lt,"didYouMean"),g(ut,"identityFunc");const ct=g((function(e,t){return e instanceof t}),"instanceOf");function dt(e,t){const n=Object.create(null);for(const r of e)n[t(r)]=r;return n}function ft(e,t,n){const r=Object.create(null);for(const i of e)r[t(i)]=n(i);return r}function pt(e,t){const n=Object.create(null);for(const r of Object.keys(e))n[r]=t(e[r],r);return n}function ht(e,t){let n=0,r=0;for(;n0);let s=0;do{++r,s=10*s+o-mt,o=t.charCodeAt(r)}while(vt(o)&&s>0);if(as)return 1}else{if(io)return 1;++n,++r}}return e.length-t.length}g(dt,"keyMap"),g(ft,"keyValMap"),g(pt,"mapValue"),g(ht,"naturalCompare");const mt=48,gt=57;function vt(e){return!isNaN(e)&&mt<=e&&e<=gt}function yt(e,t){const n=Object.create(null),r=new bt(e),i=Math.floor(.4*e.length)+1;for(const e of t){const t=r.measure(e,i);void 0!==t&&(n[e]=t)}return Object.keys(n).sort(((e,t)=>{const r=n[e]-n[t];return 0!==r?r:ht(e,t)}))}g(vt,"isDigit"),g(yt,"suggestionList");class bt{constructor(e){this._input=e,this._inputLowerCase=e.toLowerCase(),this._inputArray=Et(this._inputLowerCase),this._rows=[new Array(e.length+1).fill(0),new Array(e.length+1).fill(0),new Array(e.length+1).fill(0)]}measure(e,t){if(this._input===e)return 0;const n=e.toLowerCase();if(this._inputLowerCase===n)return 1;let r=Et(n),i=this._inputArray;if(r.lengtht)return;const s=this._rows;for(let e=0;e<=a;e++)s[0][e]=e;for(let e=1;e<=o;e++){const n=s[(e-1)%3],o=s[e%3];let l=o[0]=e;for(let t=1;t<=a;t++){const a=r[e-1]===i[t-1]?0:1;let u=Math.min(n[t]+1,o[t-1]+1,n[t-1]+a);if(e>1&&t>1&&r[e-1]===i[t-2]&&r[e-2]===i[t-1]){const n=s[(e-2)%3][t-2];u=Math.min(u,n+1)}ut)return}const l=s[o%3][a];return l<=t?l:void 0}}function Et(e){const t=e.length,n=new Array(t);for(let r=0;r=t)break;n=i.index+i[0].length,r+=1}return{line:r,column:t+1-n}}function St(e){return xt(e.source,Ct(e.source,e.start))}function xt(e,t){const n=e.locationOffset.column-1,r="".padStart(n)+e.body,i=t.line-1,o=e.locationOffset.line-1,a=t.line+o,s=1===t.line?n:0,l=t.column+s,u=`${e.name}:${a}:${l}\n`,c=r.split(/\r\n|[\n\r]/g),d=c[i];if(d.length>120){const e=Math.floor(l/80),t=l%80,n=[];for(let e=0;e["|",e])),["|","^".padStart(t)],["|",n[e+1]]])}return u+kt([[a-1+" |",c[i-1]],[`${a} |`,d],["|","^".padStart(l)],[`${a+1} |`,c[i+1]]])}function kt(e){const t=e.filter((e=>{let[t,n]=e;return void 0!==n})),n=Math.max(...t.map((e=>{let[t]=e;return t.length})));return t.map((e=>{let[t,r]=e;return t.padStart(n)+(r?" "+r:"")})).join("\n")}function Nt(e){const t=e[0];return null==t||"kind"in t||"length"in t?{nodes:t,source:e[1],positions:e[2],path:e[3],originalError:e[4],extensions:e[5]}:t}g(Ct,"getLocation"),g(St,"printLocation"),g(xt,"printSourceLocation"),g(kt,"printPrefixedLines"),g(Nt,"toNormalizedOptions");class _t extends Error{constructor(e){for(var t,n,r,i=arguments.length,o=new Array(i>1?i-1:0),a=1;ae.loc)).filter((e=>null!=e)));this.source=null!=l?l:null==p||null===(n=p[0])||void 0===n?void 0:n.source,this.positions=null!=u?u:null==p?void 0:p.map((e=>e.start)),this.locations=u&&l?u.map((e=>Ct(l,e))):null==p?void 0:p.map((e=>Ct(e.source,e.start)));const h=at(null==d?void 0:d.extensions)?null==d?void 0:d.extensions:void 0;this.extensions=null!==(r=null!=f?f:h)&&void 0!==r?r:Object.create(null),Object.defineProperties(this,{message:{writable:!0,enumerable:!0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=d&&d.stack?Object.defineProperty(this,"stack",{value:d.stack,writable:!0,configurable:!0}):Error.captureStackTrace?Error.captureStackTrace(this,_t):Object.defineProperty(this,"stack",{value:Error().stack,writable:!0,configurable:!0})}get[Symbol.toStringTag](){return"GraphQLError"}toString(){let e=this.message;if(this.nodes)for(const t of this.nodes)t.loc&&(e+="\n\n"+St(t.loc));else if(this.source&&this.locations)for(const t of this.locations)e+="\n\n"+xt(this.source,t);return e}toJSON(){const e={message:this.message};return null!=this.locations&&(e.locations=this.locations),null!=this.path&&(e.path=this.path),null!=this.extensions&&Object.keys(this.extensions).length>0&&(e.extensions=this.extensions),e}}function Ot(e){return void 0===e||0===e.length?void 0:e}function It(e,t){switch(e.kind){case ze.NULL:return null;case ze.INT:return parseInt(e.value,10);case ze.FLOAT:return parseFloat(e.value);case ze.STRING:case ze.ENUM:case ze.BOOLEAN:return e.value;case ze.LIST:return e.values.map((e=>It(e,t)));case ze.OBJECT:return ft(e.fields,(e=>e.name.value),(e=>It(e.value,t)));case ze.VARIABLE:return null==t?void 0:t[e.name.value]}}function Dt(e){if(null!=e||Be(!1,"Must provide name."),"string"==typeof e||Be(!1,"Expected name to be a string."),0===e.length)throw new _t("Expected name to be a non-empty string.");for(let t=1;to(It(e,t)),this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(i=e.extensionASTNodes)&&void 0!==i?i:[],null==e.specifiedByURL||"string"==typeof e.specifiedByURL||Be(!1,`${this.name} must provide "specifiedByURL" as a string, but got: ${Te(e.specifiedByURL)}.`),null==e.serialize||"function"==typeof e.serialize||Be(!1,`${this.name} must provide "serialize" function. If this custom Scalar is also used as an input type, ensure "parseValue" and "parseLiteral" functions are also provided.`),e.parseLiteral&&("function"==typeof e.parseValue&&"function"==typeof e.parseLiteral||Be(!1,`${this.name} must provide both "parseValue" and "parseLiteral" functions.`))}get[Symbol.toStringTag](){return"GraphQLScalarType"}toConfig(){return{name:this.name,description:this.description,specifiedByURL:this.specifiedByURL,serialize:this.serialize,parseValue:this.parseValue,parseLiteral:this.parseLiteral,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}g(Qt,"GraphQLScalarType");class Xt{constructor(e){var t;this.name=Dt(e.name),this.description=e.description,this.isTypeOf=e.isTypeOf,this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=()=>Jt(e),this._interfaces=()=>Yt(e),null==e.isTypeOf||"function"==typeof e.isTypeOf||Be(!1,`${this.name} must provide "isTypeOf" as a function, but got: ${Te(e.isTypeOf)}.`)}get[Symbol.toStringTag](){return"GraphQLObjectType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}getInterfaces(){return"function"==typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces}toConfig(){return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:tn(this.getFields()),isTypeOf:this.isTypeOf,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function Yt(e){var t;const n=Wt(null!==(t=e.interfaces)&&void 0!==t?t:[]);return Array.isArray(n)||Be(!1,`${e.name} interfaces must be an Array or a function which returns an Array.`),n}function Jt(e){const t=Kt(e.fields);return en(t)||Be(!1,`${e.name} fields must be an object with field names as keys or a function which returns such an object.`),pt(t,((t,n)=>{var r;en(t)||Be(!1,`${e.name}.${n} field config must be an object.`),null==t.resolve||"function"==typeof t.resolve||Be(!1,`${e.name}.${n} field resolver must be a function if provided, but got: ${Te(t.resolve)}.`);const i=null!==(r=t.args)&&void 0!==r?r:{};return en(i)||Be(!1,`${e.name}.${n} args must be an object with argument names as keys.`),{name:Dt(n),description:t.description,type:t.type,args:Zt(i),resolve:t.resolve,subscribe:t.subscribe,deprecationReason:t.deprecationReason,extensions:Tt(t.extensions),astNode:t.astNode}}))}function Zt(e){return Object.entries(e).map((e=>{let[t,n]=e;return{name:Dt(t),description:n.description,type:n.type,defaultValue:n.defaultValue,deprecationReason:n.deprecationReason,extensions:Tt(n.extensions),astNode:n.astNode}}))}function en(e){return at(e)&&!Array.isArray(e)}function tn(e){return pt(e,(e=>({description:e.description,type:e.type,args:nn(e.args),resolve:e.resolve,subscribe:e.subscribe,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})))}function nn(e){return ft(e,(e=>e.name),(e=>({description:e.description,type:e.type,defaultValue:e.defaultValue,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})))}g(Xt,"GraphQLObjectType"),g(Yt,"defineInterfaces"),g(Jt,"defineFieldMap"),g(Zt,"defineArguments"),g(en,"isPlainObj"),g(tn,"fieldsToFieldsConfig"),g(nn,"argsToArgsConfig");class rn{constructor(e){var t;this.name=Dt(e.name),this.description=e.description,this.resolveType=e.resolveType,this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=Jt.bind(void 0,e),this._interfaces=Yt.bind(void 0,e),null==e.resolveType||"function"==typeof e.resolveType||Be(!1,`${this.name} must provide "resolveType" as a function, but got: ${Te(e.resolveType)}.`)}get[Symbol.toStringTag](){return"GraphQLInterfaceType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}getInterfaces(){return"function"==typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces}toConfig(){return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:tn(this.getFields()),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}g(rn,"GraphQLInterfaceType");class on{constructor(e){var t;this.name=Dt(e.name),this.description=e.description,this.resolveType=e.resolveType,this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._types=an.bind(void 0,e),null==e.resolveType||"function"==typeof e.resolveType||Be(!1,`${this.name} must provide "resolveType" as a function, but got: ${Te(e.resolveType)}.`)}get[Symbol.toStringTag](){return"GraphQLUnionType"}getTypes(){return"function"==typeof this._types&&(this._types=this._types()),this._types}toConfig(){return{name:this.name,description:this.description,types:this.getTypes(),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function an(e){const t=Wt(e.types);return Array.isArray(t)||Be(!1,`Must provide Array of types or a function which returns such an array for Union ${e.name}.`),t}g(on,"GraphQLUnionType"),g(an,"defineTypes");class sn{constructor(e){var t;this.name=Dt(e.name),this.description=e.description,this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._values=un(this.name,e.values),this._valueLookup=new Map(this._values.map((e=>[e.value,e]))),this._nameLookup=dt(this._values,(e=>e.name))}get[Symbol.toStringTag](){return"GraphQLEnumType"}getValues(){return this._values}getValue(e){return this._nameLookup[e]}serialize(e){const t=this._valueLookup.get(e);if(void 0===t)throw new _t(`Enum "${this.name}" cannot represent value: ${Te(e)}`);return t.name}parseValue(e){if("string"!=typeof e){const t=Te(e);throw new _t(`Enum "${this.name}" cannot represent non-string value: ${t}.`+ln(this,t))}const t=this.getValue(e);if(null==t)throw new _t(`Value "${e}" does not exist in "${this.name}" enum.`+ln(this,e));return t.value}parseLiteral(e,t){if(e.kind!==ze.ENUM){const t=Je(e);throw new _t(`Enum "${this.name}" cannot represent non-enum value: ${t}.`+ln(this,t),{nodes:e})}const n=this.getValue(e.value);if(null==n){const t=Je(e);throw new _t(`Value "${t}" does not exist in "${this.name}" enum.`+ln(this,t),{nodes:e})}return n.value}toConfig(){const e=ft(this.getValues(),(e=>e.name),(e=>({description:e.description,value:e.value,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})));return{name:this.name,description:this.description,values:e,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function ln(e,t){return lt("the enum value",yt(t,e.getValues().map((e=>e.name))))}function un(e,t){return en(t)||Be(!1,`${e} values must be an object with value names as keys.`),Object.entries(t).map((t=>{let[n,r]=t;return en(r)||Be(!1,`${e}.${n} must refer to an object with a "value" key representing an internal value but got: ${Te(r)}.`),{name:Lt(n),description:r.description,value:void 0!==r.value?r.value:n,deprecationReason:r.deprecationReason,extensions:Tt(r.extensions),astNode:r.astNode}}))}g(sn,"GraphQLEnumType"),g(ln,"didYouMeanEnumValue"),g(un,"defineEnumValues");class cn{constructor(e){var t;this.name=Dt(e.name),this.description=e.description,this.extensions=Tt(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=dn.bind(void 0,e)}get[Symbol.toStringTag](){return"GraphQLInputObjectType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}toConfig(){const e=pt(this.getFields(),(e=>({description:e.description,type:e.type,defaultValue:e.defaultValue,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})));return{name:this.name,description:this.description,fields:e,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function dn(e){const t=Kt(e.fields);return en(t)||Be(!1,`${e.name} fields must be an object with field names as keys or a function which returns such an object.`),pt(t,((t,n)=>(!("resolve"in t)||Be(!1,`${e.name}.${n} field has a resolve property, but Input Types cannot define resolvers.`),{name:Dt(n),description:t.description,type:t.type,defaultValue:t.defaultValue,deprecationReason:t.deprecationReason,extensions:Tt(t.extensions),astNode:t.astNode})))}g(cn,"GraphQLInputObjectType"),g(dn,"defineInputFieldMap");const fn=2147483647,pn=-2147483648,hn=new Qt({name:"Int",description:"The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",serialize(e){const t=bn(e);if("boolean"==typeof t)return t?1:0;let n=t;if("string"==typeof t&&""!==t&&(n=Number(t)),"number"!=typeof n||!Number.isInteger(n))throw new _t(`Int cannot represent non-integer value: ${Te(t)}`);if(n>fn||nfn||efn||t({description:{type:gn,resolve:e=>e.description},types:{description:"A list of all types supported by this server.",type:new Gt(new Ht(new Gt(xn))),resolve(e){return Object.values(e.getTypeMap())}},queryType:{description:"The type that query operations will be rooted at.",type:new Gt(xn),resolve:e=>e.getQueryType()},mutationType:{description:"If this server supports mutation, the type that mutation operations will be rooted at.",type:xn,resolve:e=>e.getMutationType()},subscriptionType:{description:"If this server support subscription, the type that subscription operations will be rooted at.",type:xn,resolve:e=>e.getSubscriptionType()},directives:{description:"A list of all directives supported by this server.",type:new Gt(new Ht(new Gt(Cn))),resolve:e=>e.getDirectives()}})}),Cn=new Xt({name:"__Directive",description:"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",fields:()=>({name:{type:new Gt(gn),resolve:e=>e.name},description:{type:gn,resolve:e=>e.description},isRepeatable:{type:new Gt(vn),resolve:e=>e.isRepeatable},locations:{type:new Gt(new Ht(new Gt(Sn))),resolve:e=>e.locations},args:{type:new Gt(new Ht(new Gt(Nn))),args:{includeDeprecated:{type:vn,defaultValue:!1}},resolve(e,t){let{includeDeprecated:n}=t;return n?e.args:e.args.filter((e=>null==e.deprecationReason))}}})}),Sn=new sn({name:"__DirectiveLocation",description:"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",values:{QUERY:{value:Oe.QUERY,description:"Location adjacent to a query operation."},MUTATION:{value:Oe.MUTATION,description:"Location adjacent to a mutation operation."},SUBSCRIPTION:{value:Oe.SUBSCRIPTION,description:"Location adjacent to a subscription operation."},FIELD:{value:Oe.FIELD,description:"Location adjacent to a field."},FRAGMENT_DEFINITION:{value:Oe.FRAGMENT_DEFINITION,description:"Location adjacent to a fragment definition."},FRAGMENT_SPREAD:{value:Oe.FRAGMENT_SPREAD,description:"Location adjacent to a fragment spread."},INLINE_FRAGMENT:{value:Oe.INLINE_FRAGMENT,description:"Location adjacent to an inline fragment."},VARIABLE_DEFINITION:{value:Oe.VARIABLE_DEFINITION,description:"Location adjacent to a variable definition."},SCHEMA:{value:Oe.SCHEMA,description:"Location adjacent to a schema definition."},SCALAR:{value:Oe.SCALAR,description:"Location adjacent to a scalar definition."},OBJECT:{value:Oe.OBJECT,description:"Location adjacent to an object type definition."},FIELD_DEFINITION:{value:Oe.FIELD_DEFINITION,description:"Location adjacent to a field definition."},ARGUMENT_DEFINITION:{value:Oe.ARGUMENT_DEFINITION,description:"Location adjacent to an argument definition."},INTERFACE:{value:Oe.INTERFACE,description:"Location adjacent to an interface definition."},UNION:{value:Oe.UNION,description:"Location adjacent to a union definition."},ENUM:{value:Oe.ENUM,description:"Location adjacent to an enum definition."},ENUM_VALUE:{value:Oe.ENUM_VALUE,description:"Location adjacent to an enum value definition."},INPUT_OBJECT:{value:Oe.INPUT_OBJECT,description:"Location adjacent to an input object type definition."},INPUT_FIELD_DEFINITION:{value:Oe.INPUT_FIELD_DEFINITION,description:"Location adjacent to an input object field definition."}}}),xn=new Xt({name:"__Type",description:"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name, description and optional `specifiedByURL`, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",fields:()=>({kind:{type:new Gt(Dn),resolve(e){return Mt(e)?On.SCALAR:Rt(e)?On.OBJECT:Ft(e)?On.INTERFACE:Pt(e)?On.UNION:jt(e)?On.ENUM:Vt(e)?On.INPUT_OBJECT:Ut(e)?On.LIST:Bt(e)?On.NON_NULL:void _e(!1,`Unexpected type: "${Te(e)}".`)}},name:{type:gn,resolve:e=>"name"in e?e.name:void 0},description:{type:gn,resolve:e=>"description"in e?e.description:void 0},specifiedByURL:{type:gn,resolve:e=>"specifiedByURL"in e?e.specifiedByURL:void 0},fields:{type:new Ht(new Gt(kn)),args:{includeDeprecated:{type:vn,defaultValue:!1}},resolve(e,t){let{includeDeprecated:n}=t;if(Rt(e)||Ft(e)){const t=Object.values(e.getFields());return n?t:t.filter((e=>null==e.deprecationReason))}}},interfaces:{type:new Ht(new Gt(xn)),resolve(e){if(Rt(e)||Ft(e))return e.getInterfaces()}},possibleTypes:{type:new Ht(new Gt(xn)),resolve(e,t,n,r){let{schema:i}=r;if(qt(e))return i.getPossibleTypes(e)}},enumValues:{type:new Ht(new Gt(_n)),args:{includeDeprecated:{type:vn,defaultValue:!1}},resolve(e,t){let{includeDeprecated:n}=t;if(jt(e)){const t=e.getValues();return n?t:t.filter((e=>null==e.deprecationReason))}}},inputFields:{type:new Ht(new Gt(Nn)),args:{includeDeprecated:{type:vn,defaultValue:!1}},resolve(e,t){let{includeDeprecated:n}=t;if(Vt(e)){const t=Object.values(e.getFields());return n?t:t.filter((e=>null==e.deprecationReason))}}},ofType:{type:xn,resolve:e=>"ofType"in e?e.ofType:void 0}})}),kn=new Xt({name:"__Field",description:"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",fields:()=>({name:{type:new Gt(gn),resolve:e=>e.name},description:{type:gn,resolve:e=>e.description},args:{type:new Gt(new Ht(new Gt(Nn))),args:{includeDeprecated:{type:vn,defaultValue:!1}},resolve(e,t){let{includeDeprecated:n}=t;return n?e.args:e.args.filter((e=>null==e.deprecationReason))}},type:{type:new Gt(xn),resolve:e=>e.type},isDeprecated:{type:new Gt(vn),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:gn,resolve:e=>e.deprecationReason}})}),Nn=new Xt({name:"__InputValue",description:"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",fields:()=>({name:{type:new Gt(gn),resolve:e=>e.name},description:{type:gn,resolve:e=>e.description},type:{type:new Gt(xn),resolve:e=>e.type},defaultValue:{type:gn,description:"A GraphQL-formatted string representing the default value for this input value.",resolve(e){const{type:t,defaultValue:n}=e,r=En(n,t);return r?Je(r):null}},isDeprecated:{type:new Gt(vn),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:gn,resolve:e=>e.deprecationReason}})}),_n=new Xt({name:"__EnumValue",description:"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",fields:()=>({name:{type:new Gt(gn),resolve:e=>e.name},description:{type:gn,resolve:e=>e.description},isDeprecated:{type:new Gt(vn),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:gn,resolve:e=>e.deprecationReason}})});let On;var In;(In=On||(On={})).SCALAR="SCALAR",In.OBJECT="OBJECT",In.INTERFACE="INTERFACE",In.UNION="UNION",In.ENUM="ENUM",In.INPUT_OBJECT="INPUT_OBJECT",In.LIST="LIST",In.NON_NULL="NON_NULL";const Dn=new sn({name:"__TypeKind",description:"An enum describing what kind of type a given `__Type` is.",values:{SCALAR:{value:On.SCALAR,description:"Indicates this type is a scalar."},OBJECT:{value:On.OBJECT,description:"Indicates this type is an object. `fields` and `interfaces` are valid fields."},INTERFACE:{value:On.INTERFACE,description:"Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields."},UNION:{value:On.UNION,description:"Indicates this type is a union. `possibleTypes` is a valid field."},ENUM:{value:On.ENUM,description:"Indicates this type is an enum. `enumValues` is a valid field."},INPUT_OBJECT:{value:On.INPUT_OBJECT,description:"Indicates this type is an input object. `inputFields` is a valid field."},LIST:{value:On.LIST,description:"Indicates this type is a list. `ofType` is a valid field."},NON_NULL:{value:On.NON_NULL,description:"Indicates this type is a non-null. `ofType` is a valid field."}}}),Ln={name:"__schema",type:new Gt(wn),description:"Access the current type schema of this server.",args:[],resolve:(e,t,n,r)=>{let{schema:i}=r;return i},deprecationReason:void 0,extensions:Object.create(null),astNode:void 0};e.S=Ln;const An={name:"__type",type:xn,description:"Request the type information of a single type.",args:[{name:"name",description:void 0,type:new Gt(gn),defaultValue:void 0,deprecationReason:void 0,extensions:Object.create(null),astNode:void 0}],resolve:(e,t,n,r)=>{let{name:i}=t,{schema:o}=r;return o.getType(i)},deprecationReason:void 0,extensions:Object.create(null),astNode:void 0};e.T=An;const Mn={name:"__typename",type:new Gt(gn),description:"The name of the current Object type at runtime.",args:[],resolve:(e,t,n,r)=>{let{parentType:i}=r;return i.name},deprecationReason:void 0,extensions:Object.create(null),astNode:void 0};function Rn(e){let t;return Pn(e,(e=>{switch(e.kind){case"Query":case"ShortQuery":case"Mutation":case"Subscription":case"FragmentDefinition":t=e}})),t}function Fn(e,t,n){return n===Ln.name&&e.getQueryType()===t?Ln:n===An.name&&e.getQueryType()===t?An:n===Mn.name&&(0,r.isCompositeType)(t)?Mn:"getFields"in t?t.getFields()[n]:null}function Pn(e,t){const n=[];let r=e;for(;null==r?void 0:r.kind;)n.push(r),r=r.prevState;for(let e=n.length-1;e>=0;e--)t(n[e])}function jn(e){const t=Object.keys(e),n=t.length,r=new Array(n);for(let i=0;i({proximity:qn($n(e.label),t),entry:e}))),(e=>e.proximity<=2)),(e=>!e.entry.isDeprecated)).sort(((e,t)=>(e.entry.isDeprecated?1:0)-(t.entry.isDeprecated?1:0)||e.proximity-t.proximity||e.entry.label.length-t.entry.label.length)).map((e=>e.entry)):Bn(e,(e=>!e.isDeprecated))}function Bn(e,t){const n=e.filter(t);return 0===n.length?e:n}function $n(e){return e.toLowerCase().replaceAll(/\W/g,"")}function qn(e,t){let n=Hn(t,e);return e.length>t.length&&(n-=e.length-t.length-1,n+=0===e.indexOf(t)?0:.5),n}function Hn(e,t){let n,r;const i=[],o=e.length,a=t.length;for(n=0;n<=o;n++)i[n]=[n];for(r=1;r<=a;r++)i[0][r]=r;for(n=1;n<=o;n++)for(r=1;r<=a;r++){const o=e[n-1]===t[r-1]?0:1;i[n][r]=Math.min(i[n-1][r]+1,i[n][r-1]+1,i[n-1][r-1]+o),n>1&&r>1&&e[n-1]===t[r-2]&&e[n-2]===t[r-1]&&(i[n][r]=Math.min(i[n][r],i[n-2][r-2]+o))}return i[o][a]}var Gn,zn,Wn,Kn,Qn,Xn,Yn,Jn,Zn,er,tr,nr,rr,ir,or,ar,sr,lr,ur,cr,dr,fr,pr,hr,mr,gr,vr,yr,br,Er,Tr;e.a=Mn,Object.freeze([wn,Cn,Sn,xn,kn,Nn,_n,Dn]),g(Rn,"getDefinitionState"),g(Fn,"getFieldDef"),g(Pn,"forEachState"),g(jn,"objectValues"),g(Vn,"hintList"),g(Un,"filterAndSortList"),g(Bn,"filterNonEmpty"),g($n,"normalizeText"),g(qn,"getProximity"),g(Hn,"lexicalDistance"),function(e){function t(e){return"string"==typeof e}g(t,"is"),e.is=t}(Gn||(Gn={})),function(e){function t(e){return"string"==typeof e}g(t,"is"),e.is=t}(zn||(zn={})),function(e){function t(t){return"number"==typeof t&&e.MIN_VALUE<=t&&t<=e.MAX_VALUE}e.MIN_VALUE=-2147483648,e.MAX_VALUE=2147483647,g(t,"is"),e.is=t}(Wn||(Wn={})),function(e){function t(t){return"number"==typeof t&&e.MIN_VALUE<=t&&t<=e.MAX_VALUE}e.MIN_VALUE=0,e.MAX_VALUE=2147483647,g(t,"is"),e.is=t}(Kn||(Kn={})),function(e){function t(e,t){return e===Number.MAX_VALUE&&(e=Kn.MAX_VALUE),t===Number.MAX_VALUE&&(t=Kn.MAX_VALUE),{line:e,character:t}}function n(e){var t=e;return Si.objectLiteral(t)&&Si.uinteger(t.line)&&Si.uinteger(t.character)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Qn||(Qn={})),function(e){function t(e,t,n,r){if(Si.uinteger(e)&&Si.uinteger(t)&&Si.uinteger(n)&&Si.uinteger(r))return{start:Qn.create(e,t),end:Qn.create(n,r)};if(Qn.is(e)&&Qn.is(t))return{start:e,end:t};throw new Error("Range#create called with invalid arguments[".concat(e,", ").concat(t,", ").concat(n,", ").concat(r,"]"))}function n(e){var t=e;return Si.objectLiteral(t)&&Qn.is(t.start)&&Qn.is(t.end)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Xn||(Xn={})),function(e){function t(e,t){return{uri:e,range:t}}function n(e){var t=e;return Si.defined(t)&&Xn.is(t.range)&&(Si.string(t.uri)||Si.undefined(t.uri))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Yn||(Yn={})),function(e){function t(e,t,n,r){return{targetUri:e,targetRange:t,targetSelectionRange:n,originSelectionRange:r}}function n(e){var t=e;return Si.defined(t)&&Xn.is(t.targetRange)&&Si.string(t.targetUri)&&Xn.is(t.targetSelectionRange)&&(Xn.is(t.originSelectionRange)||Si.undefined(t.originSelectionRange))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Jn||(Jn={})),function(e){function t(e,t,n,r){return{red:e,green:t,blue:n,alpha:r}}function n(e){var t=e;return Si.objectLiteral(t)&&Si.numberRange(t.red,0,1)&&Si.numberRange(t.green,0,1)&&Si.numberRange(t.blue,0,1)&&Si.numberRange(t.alpha,0,1)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Zn||(Zn={})),function(e){function t(e,t){return{range:e,color:t}}function n(e){var t=e;return Si.objectLiteral(t)&&Xn.is(t.range)&&Zn.is(t.color)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(er||(er={})),function(e){function t(e,t,n){return{label:e,textEdit:t,additionalTextEdits:n}}function n(e){var t=e;return Si.objectLiteral(t)&&Si.string(t.label)&&(Si.undefined(t.textEdit)||cr.is(t))&&(Si.undefined(t.additionalTextEdits)||Si.typedArray(t.additionalTextEdits,cr.is))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(tr||(tr={})),(Tr=nr||(nr={})).Comment="comment",Tr.Imports="imports",Tr.Region="region",function(e){function t(e,t,n,r,i,o){var a={startLine:e,endLine:t};return Si.defined(n)&&(a.startCharacter=n),Si.defined(r)&&(a.endCharacter=r),Si.defined(i)&&(a.kind=i),Si.defined(o)&&(a.collapsedText=o),a}function n(e){var t=e;return Si.objectLiteral(t)&&Si.uinteger(t.startLine)&&Si.uinteger(t.startLine)&&(Si.undefined(t.startCharacter)||Si.uinteger(t.startCharacter))&&(Si.undefined(t.endCharacter)||Si.uinteger(t.endCharacter))&&(Si.undefined(t.kind)||Si.string(t.kind))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(rr||(rr={})),function(e){function t(e,t){return{location:e,message:t}}function n(e){var t=e;return Si.defined(t)&&Yn.is(t.location)&&Si.string(t.message)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(ir||(ir={})),(Er=or||(or={})).Error=1,Er.Warning=2,Er.Information=3,Er.Hint=4,(br=ar||(ar={})).Unnecessary=1,br.Deprecated=2,function(e){function t(e){var t=e;return Si.objectLiteral(t)&&Si.string(t.href)}g(t,"is"),e.is=t}(sr||(sr={})),function(e){function t(e,t,n,r,i,o){var a={range:e,message:t};return Si.defined(n)&&(a.severity=n),Si.defined(r)&&(a.code=r),Si.defined(i)&&(a.source=i),Si.defined(o)&&(a.relatedInformation=o),a}function n(e){var t,n=e;return Si.defined(n)&&Xn.is(n.range)&&Si.string(n.message)&&(Si.number(n.severity)||Si.undefined(n.severity))&&(Si.integer(n.code)||Si.string(n.code)||Si.undefined(n.code))&&(Si.undefined(n.codeDescription)||Si.string(null===(t=n.codeDescription)||void 0===t?void 0:t.href))&&(Si.string(n.source)||Si.undefined(n.source))&&(Si.undefined(n.relatedInformation)||Si.typedArray(n.relatedInformation,ir.is))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(lr||(lr={})),function(e){function t(e,t){for(var n=[],r=2;r0&&(i.arguments=n),i}function n(e){var t=e;return Si.defined(t)&&Si.string(t.title)&&Si.string(t.command)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(ur||(ur={})),function(e){function t(e,t){return{range:e,newText:t}}function n(e,t){return{range:{start:e,end:e},newText:t}}function r(e){return{range:e,newText:""}}function i(e){var t=e;return Si.objectLiteral(t)&&Si.string(t.newText)&&Xn.is(t.range)}g(t,"replace"),e.replace=t,g(n,"insert"),e.insert=n,g(r,"del"),e.del=r,g(i,"is"),e.is=i}(cr||(cr={})),function(e){function t(e,t,n){var r={label:e};return void 0!==t&&(r.needsConfirmation=t),void 0!==n&&(r.description=n),r}function n(e){var t=e;return Si.objectLiteral(t)&&Si.string(t.label)&&(Si.boolean(t.needsConfirmation)||void 0===t.needsConfirmation)&&(Si.string(t.description)||void 0===t.description)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(dr||(dr={})),function(e){function t(e){var t=e;return Si.string(t)}g(t,"is"),e.is=t}(fr||(fr={})),function(e){function t(e,t,n){return{range:e,newText:t,annotationId:n}}function n(e,t,n){return{range:{start:e,end:e},newText:t,annotationId:n}}function r(e,t){return{range:e,newText:"",annotationId:t}}function i(e){var t=e;return cr.is(t)&&(dr.is(t.annotationId)||fr.is(t.annotationId))}g(t,"replace"),e.replace=t,g(n,"insert"),e.insert=n,g(r,"del"),e.del=r,g(i,"is"),e.is=i}(pr||(pr={})),function(e){function t(e,t){return{textDocument:e,edits:t}}function n(e){var t=e;return Si.defined(t)&&Sr.is(t.textDocument)&&Array.isArray(t.edits)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(hr||(hr={})),function(e){function t(e,t,n){var r={kind:"create",uri:e};return void 0===t||void 0===t.overwrite&&void 0===t.ignoreIfExists||(r.options=t),void 0!==n&&(r.annotationId=n),r}function n(e){var t=e;return t&&"create"===t.kind&&Si.string(t.uri)&&(void 0===t.options||(void 0===t.options.overwrite||Si.boolean(t.options.overwrite))&&(void 0===t.options.ignoreIfExists||Si.boolean(t.options.ignoreIfExists)))&&(void 0===t.annotationId||fr.is(t.annotationId))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(mr||(mr={})),function(e){function t(e,t,n,r){var i={kind:"rename",oldUri:e,newUri:t};return void 0===n||void 0===n.overwrite&&void 0===n.ignoreIfExists||(i.options=n),void 0!==r&&(i.annotationId=r),i}function n(e){var t=e;return t&&"rename"===t.kind&&Si.string(t.oldUri)&&Si.string(t.newUri)&&(void 0===t.options||(void 0===t.options.overwrite||Si.boolean(t.options.overwrite))&&(void 0===t.options.ignoreIfExists||Si.boolean(t.options.ignoreIfExists)))&&(void 0===t.annotationId||fr.is(t.annotationId))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(gr||(gr={})),function(e){function t(e,t,n){var r={kind:"delete",uri:e};return void 0===t||void 0===t.recursive&&void 0===t.ignoreIfNotExists||(r.options=t),void 0!==n&&(r.annotationId=n),r}function n(e){var t=e;return t&&"delete"===t.kind&&Si.string(t.uri)&&(void 0===t.options||(void 0===t.options.recursive||Si.boolean(t.options.recursive))&&(void 0===t.options.ignoreIfNotExists||Si.boolean(t.options.ignoreIfNotExists)))&&(void 0===t.annotationId||fr.is(t.annotationId))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(vr||(vr={})),function(e){function t(e){var t=e;return t&&(void 0!==t.changes||void 0!==t.documentChanges)&&(void 0===t.documentChanges||t.documentChanges.every((function(e){return Si.string(e.kind)?mr.is(e)||gr.is(e)||vr.is(e):hr.is(e)})))}g(t,"is"),e.is=t}(yr||(yr={}));var wr,Cr,Sr,xr,kr,Nr,_r,Or,Ir,Dr,Lr,Ar,Mr,Rr,Fr,Pr,jr,Vr,Ur,Br,$r,qr,Hr,Gr,zr,Wr,Kr,Qr,Xr,Yr,Jr,Zr,ei,ti,ni,ri,ii,oi,ai,si,li,ui,ci,di,fi,pi,hi,mi,gi,vi,yi,bi,Ei,Ti,wi=function(){function e(e,t){this.edits=e,this.changeAnnotations=t}return g(e,"TextEditChangeImpl"),e.prototype.insert=function(e,t,n){var r,i;if(void 0===n?r=cr.insert(e,t):fr.is(n)?(i=n,r=pr.insert(e,t,n)):(this.assertChangeAnnotations(this.changeAnnotations),i=this.changeAnnotations.manage(n),r=pr.insert(e,t,i)),this.edits.push(r),void 0!==i)return i},e.prototype.replace=function(e,t,n){var r,i;if(void 0===n?r=cr.replace(e,t):fr.is(n)?(i=n,r=pr.replace(e,t,n)):(this.assertChangeAnnotations(this.changeAnnotations),i=this.changeAnnotations.manage(n),r=pr.replace(e,t,i)),this.edits.push(r),void 0!==i)return i},e.prototype.delete=function(e,t){var n,r;if(void 0===t?n=cr.del(e):fr.is(t)?(r=t,n=pr.del(e,t)):(this.assertChangeAnnotations(this.changeAnnotations),r=this.changeAnnotations.manage(t),n=pr.del(e,r)),this.edits.push(n),void 0!==r)return r},e.prototype.add=function(e){this.edits.push(e)},e.prototype.all=function(){return this.edits},e.prototype.clear=function(){this.edits.splice(0,this.edits.length)},e.prototype.assertChangeAnnotations=function(e){if(void 0===e)throw new Error("Text edit change is not configured to manage change annotations.")},e}(),Ci=function(){function e(e){this._annotations=void 0===e?Object.create(null):e,this._counter=0,this._size=0}return g(e,"ChangeAnnotations"),e.prototype.all=function(){return this._annotations},Object.defineProperty(e.prototype,"size",{get:function(){return this._size},enumerable:!1,configurable:!0}),e.prototype.manage=function(e,t){var n;if(fr.is(e)?n=e:(n=this.nextId(),t=e),void 0!==this._annotations[n])throw new Error("Id ".concat(n," is already in use."));if(void 0===t)throw new Error("No annotation provided for id ".concat(n));return this._annotations[n]=t,this._size++,n},e.prototype.nextId=function(){return this._counter++,this._counter.toString()},e}();(function(){function e(e){var t=this;this._textEditChanges=Object.create(null),void 0!==e?(this._workspaceEdit=e,e.documentChanges?(this._changeAnnotations=new Ci(e.changeAnnotations),e.changeAnnotations=this._changeAnnotations.all(),e.documentChanges.forEach((function(e){if(hr.is(e)){var n=new wi(e.edits,t._changeAnnotations);t._textEditChanges[e.textDocument.uri]=n}}))):e.changes&&Object.keys(e.changes).forEach((function(n){var r=new wi(e.changes[n]);t._textEditChanges[n]=r}))):this._workspaceEdit={}}g(e,"WorkspaceChange"),Object.defineProperty(e.prototype,"edit",{get:function(){return this.initDocumentChanges(),void 0!==this._changeAnnotations&&(0===this._changeAnnotations.size?this._workspaceEdit.changeAnnotations=void 0:this._workspaceEdit.changeAnnotations=this._changeAnnotations.all()),this._workspaceEdit},enumerable:!1,configurable:!0}),e.prototype.getTextEditChange=function(e){if(Sr.is(e)){if(this.initDocumentChanges(),void 0===this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.");var t={uri:e.uri,version:e.version};if(!(r=this._textEditChanges[t.uri])){var n={textDocument:t,edits:i=[]};this._workspaceEdit.documentChanges.push(n),r=new wi(i,this._changeAnnotations),this._textEditChanges[t.uri]=r}return r}if(this.initChanges(),void 0===this._workspaceEdit.changes)throw new Error("Workspace edit is not configured for normal text edit changes.");var r;if(!(r=this._textEditChanges[e])){var i=[];this._workspaceEdit.changes[e]=i,r=new wi(i),this._textEditChanges[e]=r}return r},e.prototype.initDocumentChanges=function(){void 0===this._workspaceEdit.documentChanges&&void 0===this._workspaceEdit.changes&&(this._changeAnnotations=new Ci,this._workspaceEdit.documentChanges=[],this._workspaceEdit.changeAnnotations=this._changeAnnotations.all())},e.prototype.initChanges=function(){void 0===this._workspaceEdit.documentChanges&&void 0===this._workspaceEdit.changes&&(this._workspaceEdit.changes=Object.create(null))},e.prototype.createFile=function(e,t,n){if(this.initDocumentChanges(),void 0===this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.");var r,i,o;if(dr.is(t)||fr.is(t)?r=t:n=t,void 0===r?i=mr.create(e,n):(o=fr.is(r)?r:this._changeAnnotations.manage(r),i=mr.create(e,n,o)),this._workspaceEdit.documentChanges.push(i),void 0!==o)return o},e.prototype.renameFile=function(e,t,n,r){if(this.initDocumentChanges(),void 0===this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.");var i,o,a;if(dr.is(n)||fr.is(n)?i=n:r=n,void 0===i?o=gr.create(e,t,r):(a=fr.is(i)?i:this._changeAnnotations.manage(i),o=gr.create(e,t,r,a)),this._workspaceEdit.documentChanges.push(o),void 0!==a)return a},e.prototype.deleteFile=function(e,t,n){if(this.initDocumentChanges(),void 0===this._workspaceEdit.documentChanges)throw new Error("Workspace edit is not configured for document changes.");var r,i,o;if(dr.is(t)||fr.is(t)?r=t:n=t,void 0===r?i=vr.create(e,n):(o=fr.is(r)?r:this._changeAnnotations.manage(r),i=vr.create(e,n,o)),this._workspaceEdit.documentChanges.push(i),void 0!==o)return o}})(),function(e){function t(e){return{uri:e}}function n(e){var t=e;return Si.defined(t)&&Si.string(t.uri)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(wr||(wr={})),function(e){function t(e,t){return{uri:e,version:t}}function n(e){var t=e;return Si.defined(t)&&Si.string(t.uri)&&Si.integer(t.version)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Cr||(Cr={})),function(e){function t(e,t){return{uri:e,version:t}}function n(e){var t=e;return Si.defined(t)&&Si.string(t.uri)&&(null===t.version||Si.integer(t.version))}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Sr||(Sr={})),function(e){function t(e,t,n,r){return{uri:e,languageId:t,version:n,text:r}}function n(e){var t=e;return Si.defined(t)&&Si.string(t.uri)&&Si.string(t.languageId)&&Si.integer(t.version)&&Si.string(t.text)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(xr||(xr={})),function(e){function t(t){var n=t;return n===e.PlainText||n===e.Markdown}e.PlainText="plaintext",e.Markdown="markdown",g(t,"is"),e.is=t}(kr||(kr={})),function(e){function t(e){var t=e;return Si.objectLiteral(e)&&kr.is(t.kind)&&Si.string(t.value)}g(t,"is"),e.is=t}(Nr||(Nr={})),(Ti=_r||(_r={})).Text=1,Ti.Method=2,Ti.Function=3,Ti.Constructor=4,Ti.Field=5,Ti.Variable=6,Ti.Class=7,Ti.Interface=8,Ti.Module=9,Ti.Property=10,Ti.Unit=11,Ti.Value=12,Ti.Enum=13,Ti.Keyword=14,Ti.Snippet=15,Ti.Color=16,Ti.File=17,Ti.Reference=18,Ti.Folder=19,Ti.EnumMember=20,Ti.Constant=21,Ti.Struct=22,Ti.Event=23,Ti.Operator=24,Ti.TypeParameter=25,(Ei=Or||(Or={})).PlainText=1,Ei.Snippet=2,(Ir||(Ir={})).Deprecated=1,function(e){function t(e,t,n){return{newText:e,insert:t,replace:n}}function n(e){var t=e;return t&&Si.string(t.newText)&&Xn.is(t.insert)&&Xn.is(t.replace)}g(t,"create"),e.create=t,g(n,"is"),e.is=n}(Dr||(Dr={})),(bi=Lr||(Lr={})).asIs=1,bi.adjustIndentation=2,function(e){function t(e){var t=e;return t&&(Si.string(t.detail)||void 0===t.detail)&&(Si.string(t.description)||void 0===t.description)}g(t,"is"),e.is=t}(Ar||(Ar={})),function(e){function t(e){return{label:e}}g(t,"create"),e.create=t}(Mr||(Mr={})),function(e){function t(e,t){return{items:e||[],isIncomplete:!!t}}g(t,"create"),e.create=t}(Rr||(Rr={})),function(e){function t(e){return e.replace(/[\\`*_{}[\]()#+\-.!]/g,"\\$&")}function n(e){var t=e;return Si.string(t)||Si.objectLiteral(t)&&Si.string(t.language)&&Si.string(t.value)}g(t,"fromPlainText"),e.fromPlainText=t,g(n,"is"),e.is=n}(Fr||(Fr={})),function(e){function t(e){var t=e;return!!t&&Si.objectLiteral(t)&&(Nr.is(t.contents)||Fr.is(t.contents)||Si.typedArray(t.contents,Fr.is))&&(void 0===e.range||Xn.is(e.range))}g(t,"is"),e.is=t}(Pr||(Pr={})),function(e){function t(e,t){return t?{label:e,documentation:t}:{label:e}}g(t,"create"),e.create=t}(jr||(jr={})),function(e){function t(e,t){for(var n=[],r=2;r=0;a--){var s=r[a],l=e.offsetAt(s.range.start),u=e.offsetAt(s.range.end);if(!(u<=o))throw new Error("Overlapping edit");n=n.substring(0,l)+s.newText+n.substring(u,n.length),o=l}return n}function i(e,t){if(e.length<=1)return e;var n=e.length/2|0,r=e.slice(0,n),o=e.slice(n);i(r,t),i(o,t);for(var a=0,s=0,l=0;a0&&e.push(t.length),this._lineOffsets=e}return this._lineOffsets},e.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var t=this.getLineOffsets(),n=0,r=t.length;if(0===r)return Qn.create(0,e);for(;ne?r=i:n=i+1}var o=n-1;return Qn.create(o,e-t[o])},e.prototype.offsetAt=function(e){var t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;var n=t[e.line],r=e.line+1this._start,this.getCurrentPosition=()=>this._pos,this.eol=()=>this._sourceText.length===this._pos,this.sol=()=>0===this._pos,this.peek=()=>this._sourceText.charAt(this._pos)||null,this.next=()=>{const e=this._sourceText.charAt(this._pos);return this._pos++,e},this.eat=e=>{if(this._testNextCharacter(e))return this._start=this._pos,this._pos++,this._sourceText.charAt(this._pos-1)},this.eatWhile=e=>{let t=this._testNextCharacter(e),n=!1;for(t&&(n=t,this._start=this._pos);t;)this._pos++,t=this._testNextCharacter(e),n=!0;return n},this.eatSpace=()=>this.eatWhile(/[\s\u00a0]/),this.skipToEnd=()=>{this._pos=this._sourceText.length},this.skipTo=e=>{this._pos=e},this.match=function(e){let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],r=null,i=null;return"string"==typeof e?(i=new RegExp(e,arguments.length>2&&void 0!==arguments[2]&&arguments[2]?"i":"g").test(t._sourceText.slice(t._pos,t._pos+e.length)),r=e):e instanceof RegExp&&(i=t._sourceText.slice(t._pos).match(e),r=null==i?void 0:i[0]),!(null==i||!("string"==typeof e||i instanceof Array&&t._sourceText.startsWith(i[0],t._pos)))&&(n&&(t._start=t._pos,r&&r.length&&(t._pos+=r.length)),i)},this.backUp=e=>{this._pos-=e},this.column=()=>this._pos,this.indentation=()=>{const e=this._sourceText.match(/\s*/);let t=0;if(e&&0!==e.length){const n=e[0];let r=0;for(;n.length>r;)9===n.charCodeAt(r)?t+=2:t++,r++}return t},this.current=()=>this._sourceText.slice(this._start,this._pos),this._start=0,this._pos=0,this._sourceText=e}_testNextCharacter(e){const t=this._sourceText.charAt(this._pos);let n=!1;return n="string"==typeof e?t===e:e instanceof RegExp?e.test(t):e(t),n}}function _i(e){return{ofRule:e}}function Oi(e,t){return{ofRule:e,isList:!0,separator:t}}function Ii(e,t){const n=e.match;return e.match=e=>{let r=!1;return n&&(r=n(e)),r&&t.every((t=>t.match&&!t.match(e)))},e}function Di(e,t){return{style:t,match:t=>t.kind===e}}function Li(e,t){return{style:t||"punctuation",match:t=>"Punctuation"===t.kind&&t.value===e}}e.C=Ni,g(Ni,"CharacterStream"),g(_i,"opt"),g(Oi,"list$1"),g(Ii,"butNot"),g(Di,"t$2"),g(Li,"p$1");const Ai=g((e=>" "===e||"\t"===e||","===e||"\n"===e||"\r"===e||"\ufeff"===e||" "===e),"isIgnored");e.i=Ai;const Mi={Name:/^[_A-Za-z][_0-9A-Za-z]*/,Punctuation:/^(?:!|\$|\(|\)|\.\.\.|:|=|&|@|\[|]|\{|\||\})/,Number:/^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,String:/^(?:"""(?:\\"""|[^"]|"[^"]|""[^"])*(?:""")?|"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?)/,Comment:/^#.*/};e.L=Mi;const Ri={Document:[Oi("Definition")],Definition(e){switch(e.value){case"{":return"ShortQuery";case"query":return"Query";case"mutation":return"Mutation";case"subscription":return"Subscription";case"fragment":return r.Kind.FRAGMENT_DEFINITION;case"schema":return"SchemaDef";case"scalar":return"ScalarDef";case"type":return"ObjectTypeDef";case"interface":return"InterfaceDef";case"union":return"UnionDef";case"enum":return"EnumDef";case"input":return"InputDef";case"extend":return"ExtendDef";case"directive":return"DirectiveDef"}},ShortQuery:["SelectionSet"],Query:[Fi("query"),_i(Pi("def")),_i("VariableDefinitions"),Oi("Directive"),"SelectionSet"],Mutation:[Fi("mutation"),_i(Pi("def")),_i("VariableDefinitions"),Oi("Directive"),"SelectionSet"],Subscription:[Fi("subscription"),_i(Pi("def")),_i("VariableDefinitions"),Oi("Directive"),"SelectionSet"],VariableDefinitions:[Li("("),Oi("VariableDefinition"),Li(")")],VariableDefinition:["Variable",Li(":"),"Type",_i("DefaultValue")],Variable:[Li("$","variable"),Pi("variable")],DefaultValue:[Li("="),"Value"],SelectionSet:[Li("{"),Oi("Selection"),Li("}")],Selection(e,t){return"..."===e.value?t.match(/[\s\u00a0,]*(on\b|@|{)/,!1)?"InlineFragment":"FragmentSpread":t.match(/[\s\u00a0,]*:/,!1)?"AliasedField":"Field"},AliasedField:[Pi("property"),Li(":"),Pi("qualifier"),_i("Arguments"),Oi("Directive"),_i("SelectionSet")],Field:[Pi("property"),_i("Arguments"),Oi("Directive"),_i("SelectionSet")],Arguments:[Li("("),Oi("Argument"),Li(")")],Argument:[Pi("attribute"),Li(":"),"Value"],FragmentSpread:[Li("..."),Pi("def"),Oi("Directive")],InlineFragment:[Li("..."),_i("TypeCondition"),Oi("Directive"),"SelectionSet"],FragmentDefinition:[Fi("fragment"),_i(Ii(Pi("def"),[Fi("on")])),"TypeCondition",Oi("Directive"),"SelectionSet"],TypeCondition:[Fi("on"),"NamedType"],Value(e){switch(e.kind){case"Number":return"NumberValue";case"String":return"StringValue";case"Punctuation":switch(e.value){case"[":return"ListValue";case"{":return"ObjectValue";case"$":return"Variable";case"&":return"NamedType"}return null;case"Name":switch(e.value){case"true":case"false":return"BooleanValue"}return"null"===e.value?"NullValue":"EnumValue"}},NumberValue:[Di("Number","number")],StringValue:[{style:"string",match:e=>"String"===e.kind,update(e,t){t.value.startsWith('"""')&&(e.inBlockstring=!t.value.slice(3).endsWith('"""'))}}],BooleanValue:[Di("Name","builtin")],NullValue:[Di("Name","keyword")],EnumValue:[Pi("string-2")],ListValue:[Li("["),Oi("Value"),Li("]")],ObjectValue:[Li("{"),Oi("ObjectField"),Li("}")],ObjectField:[Pi("attribute"),Li(":"),"Value"],Type(e){return"["===e.value?"ListType":"NonNullType"},ListType:[Li("["),"Type",Li("]"),_i(Li("!"))],NonNullType:["NamedType",_i(Li("!"))],NamedType:[ji("atom")],Directive:[Li("@","meta"),Pi("meta"),_i("Arguments")],DirectiveDef:[Fi("directive"),Li("@","meta"),Pi("meta"),_i("ArgumentsDef"),Fi("on"),Oi("DirectiveLocation",Li("|"))],InterfaceDef:[Fi("interface"),Pi("atom"),_i("Implements"),Oi("Directive"),Li("{"),Oi("FieldDef"),Li("}")],Implements:[Fi("implements"),Oi("NamedType",Li("&"))],DirectiveLocation:[Pi("string-2")],SchemaDef:[Fi("schema"),Oi("Directive"),Li("{"),Oi("OperationTypeDef"),Li("}")],OperationTypeDef:[Pi("keyword"),Li(":"),Pi("atom")],ScalarDef:[Fi("scalar"),Pi("atom"),Oi("Directive")],ObjectTypeDef:[Fi("type"),Pi("atom"),_i("Implements"),Oi("Directive"),Li("{"),Oi("FieldDef"),Li("}")],FieldDef:[Pi("property"),_i("ArgumentsDef"),Li(":"),"Type",Oi("Directive")],ArgumentsDef:[Li("("),Oi("InputValueDef"),Li(")")],InputValueDef:[Pi("attribute"),Li(":"),"Type",_i("DefaultValue"),Oi("Directive")],UnionDef:[Fi("union"),Pi("atom"),Oi("Directive"),Li("="),Oi("UnionMember",Li("|"))],UnionMember:["NamedType"],EnumDef:[Fi("enum"),Pi("atom"),Oi("Directive"),Li("{"),Oi("EnumValueDef"),Li("}")],EnumValueDef:[Pi("string-2"),Oi("Directive")],InputDef:[Fi("input"),Pi("atom"),Oi("Directive"),Li("{"),Oi("InputValueDef"),Li("}")],ExtendDef:[Fi("extend"),"ExtensionDefinition"],ExtensionDefinition(e){switch(e.value){case"schema":return r.Kind.SCHEMA_EXTENSION;case"scalar":return r.Kind.SCALAR_TYPE_EXTENSION;case"type":return r.Kind.OBJECT_TYPE_EXTENSION;case"interface":return r.Kind.INTERFACE_TYPE_EXTENSION;case"union":return r.Kind.UNION_TYPE_EXTENSION;case"enum":return r.Kind.ENUM_TYPE_EXTENSION;case"input":return r.Kind.INPUT_OBJECT_TYPE_EXTENSION}},[r.Kind.SCHEMA_EXTENSION]:["SchemaDef"],[r.Kind.SCALAR_TYPE_EXTENSION]:["ScalarDef"],[r.Kind.OBJECT_TYPE_EXTENSION]:["ObjectTypeDef"],[r.Kind.INTERFACE_TYPE_EXTENSION]:["InterfaceDef"],[r.Kind.UNION_TYPE_EXTENSION]:["UnionDef"],[r.Kind.ENUM_TYPE_EXTENSION]:["EnumDef"],[r.Kind.INPUT_OBJECT_TYPE_EXTENSION]:["InputDef"]};function Fi(e){return{style:"keyword",match:t=>"Name"===t.kind&&t.value===e}}function Pi(e){return{style:e,match:e=>"Name"===e.kind,update(e,t){e.name=t.value}}}function ji(e){return{style:e,match:e=>"Name"===e.kind,update(e,t){var n;(null===(n=e.prevState)||void 0===n?void 0:n.prevState)&&(e.name=t.value,e.prevState.prevState.type=t.value)}}}function Vi(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{eatWhitespace:e=>e.eatWhile(Ai),lexRules:Mi,parseRules:Ri,editorConfig:{}};return{startState(){const t={level:0,step:0,name:null,kind:null,type:null,rule:null,needsSeparator:!1,prevState:null};return qi(e.parseRules,t,r.Kind.DOCUMENT),t},token(t,n){return Ui(t,n,e)}}}function Ui(e,t,n){var r;if(t.inBlockstring)return e.match(/.*"""/)?(t.inBlockstring=!1,"string"):(e.skipToEnd(),"string");const{lexRules:i,parseRules:o,eatWhitespace:a,editorConfig:s}=n;if(t.rule&&0===t.rule.length?Hi(t):t.needsAdvance&&(t.needsAdvance=!1,Gi(t,!0)),e.sol()){const n=(null==s?void 0:s.tabSize)||2;t.indentLevel=Math.floor(e.indentation()/n)}if(a(e))return"ws";const l=Ki(i,e);if(!l)return e.match(/\S+/)||e.match(/\s/),qi($i,t,"Invalid"),"invalidchar";if("Comment"===l.kind)return qi($i,t,"Comment"),"comment";const u=Bi({},t);if("Punctuation"===l.kind)if(/^[{([]/.test(l.value))void 0!==t.indentLevel&&(t.levels=(t.levels||[]).concat(t.indentLevel+1));else if(/^[})\]]/.test(l.value)){const e=t.levels=(t.levels||[]).slice(0,-1);t.indentLevel&&e.length>0&&e.at(-1){const t=[];if(e)try{(0,r.visit)((0,r.parse)(e),{FragmentDefinition(e){t.push(e)}})}catch(e){return[]}return t}),"collectFragmentDefs"),Ji=[r.Kind.SCHEMA_DEFINITION,r.Kind.OPERATION_TYPE_DEFINITION,r.Kind.SCALAR_TYPE_DEFINITION,r.Kind.OBJECT_TYPE_DEFINITION,r.Kind.INTERFACE_TYPE_DEFINITION,r.Kind.UNION_TYPE_DEFINITION,r.Kind.ENUM_TYPE_DEFINITION,r.Kind.INPUT_OBJECT_TYPE_DEFINITION,r.Kind.DIRECTIVE_DEFINITION,r.Kind.SCHEMA_EXTENSION,r.Kind.SCALAR_TYPE_EXTENSION,r.Kind.OBJECT_TYPE_EXTENSION,r.Kind.INTERFACE_TYPE_EXTENSION,r.Kind.UNION_TYPE_EXTENSION,r.Kind.ENUM_TYPE_EXTENSION,r.Kind.INPUT_OBJECT_TYPE_EXTENSION],Zi=g((e=>{let t=!1;if(e)try{(0,r.visit)((0,r.parse)(e),{enter(e){if("Document"!==e.kind)return!!Ji.includes(e.kind)&&(t=!0,r.BREAK)}})}catch(e){return t}return t}),"hasTypeSystemDefinitions");function eo(e,t,n,i,o,a){var s;const l=Object.assign(Object.assign({},a),{schema:e}),u=i||vo(t,n),c="Invalid"===u.state.kind?u.state.prevState:u.state,d=(null==a?void 0:a.mode)||Co(t,null==a?void 0:a.uri);if(!c)return[];const{kind:f,step:p,prevState:h}=c,m=Eo(e,u.state);if(f===Qi.DOCUMENT)return d===To.TYPE_SYSTEM?ro(u):io(u);if(f===Qi.EXTEND_DEF)return oo(u);if((null===(s=null==h?void 0:h.prevState)||void 0===s?void 0:s.kind)===Qi.EXTENSION_DEFINITION&&c.name)return Vn(u,[]);if((null==h?void 0:h.kind)===r.Kind.SCALAR_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter(r.isScalarType).map((e=>({label:e.name,kind:xi.Function}))));if((null==h?void 0:h.kind)===r.Kind.OBJECT_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter((e=>(0,r.isObjectType)(e)&&!e.name.startsWith("__"))).map((e=>({label:e.name,kind:xi.Function}))));if((null==h?void 0:h.kind)===r.Kind.INTERFACE_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter(r.isInterfaceType).map((e=>({label:e.name,kind:xi.Function}))));if((null==h?void 0:h.kind)===r.Kind.UNION_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter(r.isUnionType).map((e=>({label:e.name,kind:xi.Function}))));if((null==h?void 0:h.kind)===r.Kind.ENUM_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter((e=>(0,r.isEnumType)(e)&&!e.name.startsWith("__"))).map((e=>({label:e.name,kind:xi.Function}))));if((null==h?void 0:h.kind)===r.Kind.INPUT_OBJECT_TYPE_EXTENSION)return Vn(u,Object.values(e.getTypeMap()).filter(r.isInputObjectType).map((e=>({label:e.name,kind:xi.Function}))));if(f===Qi.IMPLEMENTS||f===Qi.NAMED_TYPE&&(null==h?void 0:h.kind)===Qi.IMPLEMENTS)return lo(u,c,e,t,m);if(f===Qi.SELECTION_SET||f===Qi.FIELD||f===Qi.ALIASED_FIELD)return ao(u,m,l);if(f===Qi.ARGUMENTS||f===Qi.ARGUMENT&&0===p){const{argDefs:e}=m;if(e)return Vn(u,e.map((e=>{var t;return{label:e.name,insertText:e.name+": ",command:Xi,detail:String(e.type),documentation:null!==(t=e.description)&&void 0!==t?t:void 0,kind:xi.Variable,type:e.type}})))}if((f===Qi.OBJECT_VALUE||f===Qi.OBJECT_FIELD&&0===p)&&m.objectFieldDefs){const e=jn(m.objectFieldDefs),t=f===Qi.OBJECT_VALUE?xi.Value:xi.Field;return Vn(u,e.map((e=>{var n;return{label:e.name,detail:String(e.type),documentation:null!==(n=e.description)&&void 0!==n?n:void 0,kind:t,type:e.type}})))}if(f===Qi.ENUM_VALUE||f===Qi.LIST_VALUE&&1===p||f===Qi.OBJECT_FIELD&&2===p||f===Qi.ARGUMENT&&2===p)return so(u,m,t,e);if(f===Qi.VARIABLE&&1===p){const n=(0,r.getNamedType)(m.inputType);return Vn(u,po(t,e,u).filter((e=>e.detail===(null==n?void 0:n.name))))}if(f===Qi.TYPE_CONDITION&&1===p||f===Qi.NAMED_TYPE&&null!=h&&h.kind===Qi.TYPE_CONDITION)return uo(u,m,e);if(f===Qi.FRAGMENT_SPREAD&&1===p)return co(u,m,e,t,Array.isArray(o)?o:Yi(o));const g=So(c);if(d===To.TYPE_SYSTEM&&!g.needsAdvance&&f===Qi.NAMED_TYPE||f===Qi.LIST_TYPE){if(g.kind===Qi.FIELD_DEF)return Vn(u,Object.values(e.getTypeMap()).filter((e=>(0,r.isOutputType)(e)&&!e.name.startsWith("__"))).map((e=>({label:e.name,kind:xi.Function}))));if(g.kind===Qi.INPUT_VALUE_DEF)return Vn(u,Object.values(e.getTypeMap()).filter((e=>(0,r.isInputType)(e)&&!e.name.startsWith("__"))).map((e=>({label:e.name,kind:xi.Function}))))}return f===Qi.VARIABLE_DEFINITION&&2===p||f===Qi.LIST_TYPE&&1===p||f===Qi.NAMED_TYPE&&h&&(h.kind===Qi.VARIABLE_DEFINITION||h.kind===Qi.LIST_TYPE||h.kind===Qi.NON_NULL_TYPE)?mo(u,e):f===Qi.DIRECTIVE?go(u,c,e):[]}g(eo,"getAutocompleteSuggestions");const to=" {\n $1\n}",no=g((e=>{const{type:t}=e;if((0,r.isCompositeType)(t))return to;if((0,r.isListType)(t)&&(0,r.isCompositeType)(t.ofType))return to;if((0,r.isNonNullType)(t)){if((0,r.isCompositeType)(t.ofType))return to;if((0,r.isListType)(t.ofType)&&(0,r.isCompositeType)(t.ofType.ofType))return to}return null}),"getInsertText");function ro(e){return Vn(e,[{label:"extend",kind:xi.Function},{label:"type",kind:xi.Function},{label:"interface",kind:xi.Function},{label:"union",kind:xi.Function},{label:"input",kind:xi.Function},{label:"scalar",kind:xi.Function},{label:"schema",kind:xi.Function}])}function io(e){return Vn(e,[{label:"query",kind:xi.Function},{label:"mutation",kind:xi.Function},{label:"subscription",kind:xi.Function},{label:"fragment",kind:xi.Function},{label:"{",kind:xi.Constructor}])}function oo(e){return Vn(e,[{label:"type",kind:xi.Function},{label:"interface",kind:xi.Function},{label:"union",kind:xi.Function},{label:"input",kind:xi.Function},{label:"scalar",kind:xi.Function},{label:"schema",kind:xi.Function}])}function ao(e,t,n){var i;if(t.parentType){const{parentType:o}=t;let a=[];return"getFields"in o&&(a=jn(o.getFields())),(0,r.isCompositeType)(o)&&a.push(r.TypeNameMetaFieldDef),o===(null===(i=null==n?void 0:n.schema)||void 0===i?void 0:i.getQueryType())&&a.push(r.SchemaMetaFieldDef,r.TypeMetaFieldDef),Vn(e,a.map(((e,t)=>{var r;const i={sortText:String(t)+e.name,label:e.name,detail:String(e.type),documentation:null!==(r=e.description)&&void 0!==r?r:void 0,deprecated:Boolean(e.deprecationReason),isDeprecated:Boolean(e.deprecationReason),deprecationReason:e.deprecationReason,kind:xi.Field,type:e.type};if(null==n?void 0:n.fillLeafsOnComplete){const t=no(e);t&&(i.insertText=e.name+t,i.insertTextFormat=Or.Snippet,i.command=Xi)}return i})))}return[]}function so(e,t,n,i){const o=(0,r.getNamedType)(t.inputType),a=po(n,i,e).filter((e=>e.detail===o.name));return o instanceof r.GraphQLEnumType?Vn(e,o.getValues().map((e=>{var t;return{label:e.name,detail:String(o),documentation:null!==(t=e.description)&&void 0!==t?t:void 0,deprecated:Boolean(e.deprecationReason),isDeprecated:Boolean(e.deprecationReason),deprecationReason:e.deprecationReason,kind:xi.EnumMember,type:o}})).concat(a)):o===r.GraphQLBoolean?Vn(e,a.concat([{label:"true",detail:String(r.GraphQLBoolean),documentation:"Not false.",kind:xi.Variable,type:r.GraphQLBoolean},{label:"false",detail:String(r.GraphQLBoolean),documentation:"Not true.",kind:xi.Variable,type:r.GraphQLBoolean}])):a}function lo(e,t,n,i,o){if(t.needsSeparator)return[];const a=jn(n.getTypeMap()).filter(r.isInterfaceType),s=a.map((e=>{let{name:t}=e;return t})),l=new Set;yo(i,((e,t)=>{var i,a,u,c,d;if(t.name&&(t.kind!==Qi.INTERFACE_DEF||s.includes(t.name)||l.add(t.name),t.kind===Qi.NAMED_TYPE&&(null===(i=t.prevState)||void 0===i?void 0:i.kind)===Qi.IMPLEMENTS))if(o.interfaceDef){if(null===(a=o.interfaceDef)||void 0===a?void 0:a.getInterfaces().find((e=>{let{name:n}=e;return n===t.name})))return;const e=n.getType(t.name),i=null===(u=o.interfaceDef)||void 0===u?void 0:u.toConfig();o.interfaceDef=new r.GraphQLInterfaceType(Object.assign(Object.assign({},i),{interfaces:[...i.interfaces,e||new r.GraphQLInterfaceType({name:t.name,fields:{}})]}))}else if(o.objectTypeDef){if(null===(c=o.objectTypeDef)||void 0===c?void 0:c.getInterfaces().find((e=>{let{name:n}=e;return n===t.name})))return;const e=n.getType(t.name),i=null===(d=o.objectTypeDef)||void 0===d?void 0:d.toConfig();o.objectTypeDef=new r.GraphQLObjectType(Object.assign(Object.assign({},i),{interfaces:[...i.interfaces,e||new r.GraphQLInterfaceType({name:t.name,fields:{}})]}))}}));const u=o.interfaceDef||o.objectTypeDef,c=((null==u?void 0:u.getInterfaces())||[]).map((e=>{let{name:t}=e;return t}));return Vn(e,a.concat([...l].map((e=>({name:e})))).filter((e=>{let{name:t}=e;return t!==(null==u?void 0:u.name)&&!c.includes(t)})).map((e=>{const t={label:e.name,kind:xi.Interface,type:e};return(null==e?void 0:e.description)&&(t.documentation=e.description),t})))}function uo(e,t,n,i){let o;if(t.parentType)if((0,r.isAbstractType)(t.parentType)){const e=(0,r.assertAbstractType)(t.parentType),i=n.getPossibleTypes(e),a=Object.create(null);for(const e of i)for(const t of e.getInterfaces())a[t.name]=t;o=i.concat(jn(a))}else o=[t.parentType];else o=jn(n.getTypeMap()).filter((e=>(0,r.isCompositeType)(e)&&!e.name.startsWith("__")));return Vn(e,o.map((e=>{const t=(0,r.getNamedType)(e);return{label:String(e),documentation:(null==t?void 0:t.description)||"",kind:xi.Field}})))}function co(e,t,n,i,o){if(!i)return[];const a=n.getTypeMap(),s=Rn(e.state),l=ho(i);return o&&o.length>0&&l.push(...o),Vn(e,l.filter((e=>a[e.typeCondition.name.value]&&!(s&&s.kind===Qi.FRAGMENT_DEFINITION&&s.name===e.name.value)&&(0,r.isCompositeType)(t.parentType)&&(0,r.isCompositeType)(a[e.typeCondition.name.value])&&(0,r.doTypesOverlap)(n,t.parentType,a[e.typeCondition.name.value]))).map((e=>({label:e.name.value,detail:String(a[e.typeCondition.name.value]),documentation:`fragment ${e.name.value} on ${e.typeCondition.name.value}`,kind:xi.Field,type:a[e.typeCondition.name.value]}))))}g(ro,"getSuggestionsForTypeSystemDefinitions"),g(io,"getSuggestionsForExecutableDefinitions"),g(oo,"getSuggestionsForExtensionDefinitions"),g(ao,"getSuggestionsForFieldNames"),g(so,"getSuggestionsForInputValues"),g(lo,"getSuggestionsForImplements"),g(uo,"getSuggestionsForFragmentTypeConditions"),g(co,"getSuggestionsForFragmentSpread");const fo=g(((e,t)=>{var n,r,i,o,a,s,l,u,c,d;return(null===(n=e.prevState)||void 0===n?void 0:n.kind)===t?e.prevState:(null===(i=null===(r=e.prevState)||void 0===r?void 0:r.prevState)||void 0===i?void 0:i.kind)===t?e.prevState.prevState:(null===(s=null===(a=null===(o=e.prevState)||void 0===o?void 0:o.prevState)||void 0===a?void 0:a.prevState)||void 0===s?void 0:s.kind)===t?e.prevState.prevState.prevState:(null===(d=null===(c=null===(u=null===(l=e.prevState)||void 0===l?void 0:l.prevState)||void 0===u?void 0:u.prevState)||void 0===c?void 0:c.prevState)||void 0===d?void 0:d.kind)===t?e.prevState.prevState.prevState.prevState:void 0}),"getParentDefinition");function po(e,t,n){let r,i=null;const o=Object.create({});return yo(e,((e,a)=>{if((null==a?void 0:a.kind)===Qi.VARIABLE&&a.name&&(i=a.name),(null==a?void 0:a.kind)===Qi.NAMED_TYPE&&i){const e=fo(a,Qi.TYPE);(null==e?void 0:e.type)&&(r=t.getType(null==e?void 0:e.type))}i&&r&&!o[i]&&(o[i]={detail:r.toString(),insertText:"$"===n.string?i:"$"+i,label:i,type:r,kind:xi.Variable},i=null,r=null)})),jn(o)}function ho(e){const t=[];return yo(e,((e,n)=>{n.kind===Qi.FRAGMENT_DEFINITION&&n.name&&n.type&&t.push({kind:Qi.FRAGMENT_DEFINITION,name:{kind:r.Kind.NAME,value:n.name},selectionSet:{kind:Qi.SELECTION_SET,selections:[]},typeCondition:{kind:Qi.NAMED_TYPE,name:{kind:r.Kind.NAME,value:n.type}}})})),t}function mo(e,t,n){return Vn(e,jn(t.getTypeMap()).filter(r.isInputType).map((e=>({label:e.name,documentation:e.description,kind:xi.Variable}))))}function go(e,t,n,r){var i;return(null===(i=t.prevState)||void 0===i?void 0:i.kind)?Vn(e,n.getDirectives().filter((e=>bo(t.prevState,e))).map((e=>({label:e.name,documentation:e.description||"",kind:xi.Function})))):[]}function vo(e,t){let n=null,r=null,i=null;const o=yo(e,((e,o,a,s)=>{if(s===t.line&&e.getCurrentPosition()>=t.character)return n=a,r=Object.assign({},o),i=e.current(),"BREAK"}));return{start:o.start,end:o.end,string:i||o.string,state:r||o.state,style:n||o.style}}function yo(e,t){const n=e.split("\n"),r=Vi();let i=r.startState(),o="",a=new Ni("");for(let e=0;e{var h;switch(t.kind){case Qi.QUERY:case"ShortQuery":f=e.getQueryType();break;case Qi.MUTATION:f=e.getMutationType();break;case Qi.SUBSCRIPTION:f=e.getSubscriptionType();break;case Qi.INLINE_FRAGMENT:case Qi.FRAGMENT_DEFINITION:t.type&&(f=e.getType(t.type));break;case Qi.FIELD:case Qi.ALIASED_FIELD:f&&t.name?(s=d?Fn(e,d,t.name):null,f=s?s.type:null):s=null;break;case Qi.SELECTION_SET:d=(0,r.getNamedType)(f);break;case Qi.DIRECTIVE:o=t.name?e.getDirective(t.name):null;break;case Qi.INTERFACE_DEF:t.name&&(u=null,p=new r.GraphQLInterfaceType({name:t.name,interfaces:[],fields:{}}));break;case Qi.OBJECT_TYPE_DEF:t.name&&(p=null,u=new r.GraphQLObjectType({name:t.name,interfaces:[],fields:{}}));break;case Qi.ARGUMENTS:if(t.prevState)switch(t.prevState.kind){case Qi.FIELD:i=s&&s.args;break;case Qi.DIRECTIVE:i=o&&o.args;break;case Qi.ALIASED_FIELD:{const n=null===(h=t.prevState)||void 0===h?void 0:h.name;if(!n){i=null;break}const r=d?Fn(e,d,n):null;if(!r){i=null;break}i=r.args;break}default:i=null}else i=null;break;case Qi.ARGUMENT:if(i)for(let e=0;ee.value===t.name)):null;break;case Qi.LIST_VALUE:const g=(0,r.getNullableType)(l);l=g instanceof r.GraphQLList?g.ofType:null;break;case Qi.OBJECT_VALUE:const v=(0,r.getNamedType)(l);c=v instanceof r.GraphQLInputObjectType?v.getFields():null;break;case Qi.OBJECT_FIELD:const y=t.name&&c?c[t.name]:null;l=null==y?void 0:y.type;break;case Qi.NAMED_TYPE:t.name&&(f=e.getType(t.name))}})),{argDef:n,argDefs:i,directiveDef:o,enumValue:a,fieldDef:s,inputType:l,objectFieldDefs:c,parentType:d,type:f,interfaceDef:p,objectTypeDef:u}}var To,wo;function Co(e,t){return(null==t?void 0:t.endsWith(".graphqls"))||Zi(e)?To.TYPE_SYSTEM:To.EXECUTABLE}function So(e){return e.prevState&&e.kind&&[Qi.NAMED_TYPE,Qi.LIST_TYPE,Qi.TYPE,Qi.NON_NULL_TYPE].includes(e.kind)?So(e.prevState):e}g(po,"getVariableCompletions"),g(ho,"getFragmentDefinitions"),g(mo,"getSuggestionsForVariableDefinition"),g(go,"getSuggestionsForDirective"),g(vo,"getTokenAtPosition"),g(yo,"runOnlineParser"),g(bo,"canUseDirective"),g(Eo,"getTypeInfo"),(wo=To||(To={})).TYPE_SYSTEM="TYPE_SYSTEM",wo.EXECUTABLE="EXECUTABLE",g(Co,"getDocumentMode"),g(So,"unwrapType");var xo={exports:{}};function ko(e,t){if(null!=e)return e;var n=new Error(void 0!==t?t:"Got unexpected "+e);throw n.framesToPop=1,n}g(ko,"nullthrows"),xo.exports=ko,xo.exports.default=ko,Object.defineProperty(xo.exports,"__esModule",{value:!0});var No=Z(xo.exports);const _o=g(((e,t)=>{if(!t)return[];const n=new Map,i=new Set;(0,r.visit)(e,{FragmentDefinition(e){n.set(e.name.value,!0)},FragmentSpread(e){i.has(e.name.value)||i.add(e.name.value)}});const o=new Set;for(const e of i)!n.has(e)&&t.has(e)&&o.add(No(t.get(e)));const a=[];for(const e of o)(0,r.visit)(e,{FragmentSpread(e){!i.has(e.name.value)&&t.get(e.name.value)&&(o.add(No(t.get(e.name.value))),i.add(e.name.value))}}),n.has(e.name.value)||a.push(e);return a}),"getFragmentDependenciesForAST");function Oo(e,t){const n=Object.create(null);for(const i of t.definitions)if("OperationDefinition"===i.kind){const{variableDefinitions:t}=i;if(t)for(const{variable:i,type:o}of t){const t=(0,r.typeFromAST)(e,o);t?n[i.name.value]=t:o.kind===r.Kind.NAMED_TYPE&&"Float"===o.name.value&&(n[i.name.value]=r.GraphQLFloat)}}return n}function Io(e,t){const n=t?Oo(t,e):void 0,i=[];return(0,r.visit)(e,{OperationDefinition(e){i.push(e)}}),{variableToType:n,operations:i}}function Do(e,t){if(t)try{const n=(0,r.parse)(t);return Object.assign(Object.assign({},Io(n,e)),{documentAST:n})}catch(e){return}}g(Oo,"collectVariables"),g(Io,"getOperationASTFacts"),g(Do,"getOperationFacts"),globalThis&&globalThis.__awaiter;var Lo=g((function(e){return"object"==typeof e?null===e:"function"!=typeof e}),"isPrimitive"),Ao=g((function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)}),"isObject");function Mo(e){return!0===Ao(e)&&"[object Object]"===Object.prototype.toString.call(e)}g(Mo,"isObjectObject");var Ro=g((function(e){var t,n;return!1!==Mo(e)&&"function"==typeof(t=e.constructor)&&!1!==Mo(n=t.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf")}),"isPlainObject");const{deleteProperty:Fo}=Reflect,Po=Lo,jo=Ro,Vo=g((e=>"object"==typeof e&&null!==e||"function"==typeof e),"isObject$1"),Uo=g((e=>"__proto__"===e||"constructor"===e||"prototype"===e),"isUnsafeKey"),Bo=g((e=>{if(!Po(e))throw new TypeError("Object keys must be strings or symbols");if(Uo(e))throw new Error(`Cannot set unsafe key: "${e}"`)}),"validateKey"),$o=g((e=>Array.isArray(e)?e.flat().map(String).join(","):e),"toStringKey"),qo=g(((e,t)=>{if("string"!=typeof e||!t)return e;let n=e+";";return void 0!==t.arrays&&(n+=`arrays=${t.arrays};`),void 0!==t.separator&&(n+=`separator=${t.separator};`),void 0!==t.split&&(n+=`split=${t.split};`),void 0!==t.merge&&(n+=`merge=${t.merge};`),void 0!==t.preservePaths&&(n+=`preservePaths=${t.preservePaths};`),n}),"createMemoKey"),Ho=g(((e,t,n)=>{const r=$o(t?qo(e,t):e);Bo(r);const i=Ko.cache.get(r)||n();return Ko.cache.set(r,i),i}),"memoize"),Go=g((function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=t.separator||".",r="/"!==n&&t.preservePaths;if("string"==typeof e&&!1!==r&&/\//.test(e))return[e];const i=[];let o="";const a=g((e=>{let t;""!==e.trim()&&Number.isInteger(t=Number(e))?i.push(t):i.push(e)}),"push");for(let t=0;tt&&"function"==typeof t.split?t.split(e):"symbol"==typeof e?[e]:Array.isArray(e)?e:Ho(e,t,(()=>Go(e,t)))),"split"),Wo=g(((e,t,n,r)=>{if(Bo(t),void 0===n)Fo(e,t);else if(r&&r.merge){const i="function"===r.merge?r.merge:Object.assign;i&&jo(e[t])&&jo(n)?e[t]=i(e[t],n):e[t]=n}else e[t]=n;return e}),"assignProp"),Ko=g(((e,t,n,r)=>{if(!t||!Vo(e))return e;const i=zo(t,r);let o=e;for(let e=0;e{Ko.cache=new Map};var Qo=Ko;function Xo(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M5.0484 1.40838C6.12624 0.33054 7.87376 0.330541 8.9516 1.40838L12.5916 5.0484C13.6695 6.12624 13.6695 7.87376 12.5916 8.9516L8.9516 12.5916C7.87376 13.6695 6.12624 13.6695 5.0484 12.5916L1.40838 8.9516C0.33054 7.87376 0.330541 6.12624 1.40838 5.0484L5.0484 1.40838Z",stroke:"currentColor",strokeWidth:1.2}),t.createElement("rect",{x:6,y:6,width:2,height:2,rx:1,fill:"currentColor"}))}function Yo(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 9",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M1 1L7 7L13 1",stroke:"currentColor",strokeWidth:1.5}))}function Jo(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 7 10",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M6 1.04819L2 5.04819L6 9.04819",stroke:"currentColor",strokeWidth:1.75}))}function Zo(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 9",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M13 8L7 2L1 8",stroke:"currentColor",strokeWidth:1.5}))}function ea(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M1 1L12.9998 12.9997",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{d:"M13 1L1.00079 13.0003",stroke:"currentColor",strokeWidth:1.5}))}function ta(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"-2 -2 22 22",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M11.25 14.2105V15.235C11.25 16.3479 10.3479 17.25 9.23501 17.25H2.76499C1.65214 17.25 0.75 16.3479 0.75 15.235L0.75 8.76499C0.75 7.65214 1.65214 6.75 2.76499 6.75L3.78947 6.75",stroke:"currentColor",strokeWidth:1.5}),t.createElement("rect",{x:6.75,y:.75,width:10.5,height:10.5,rx:2.2069,stroke:"currentColor",strokeWidth:1.5}))}function na(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M5.0484 1.40838C6.12624 0.33054 7.87376 0.330541 8.9516 1.40838L12.5916 5.0484C13.6695 6.12624 13.6695 7.87376 12.5916 8.9516L8.9516 12.5916C7.87376 13.6695 6.12624 13.6695 5.0484 12.5916L1.40838 8.9516C0.33054 7.87376 0.330541 6.12624 1.40838 5.0484L5.0484 1.40838Z",stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M5 9L9 5",stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M5 5L9 9",stroke:"currentColor",strokeWidth:1.2}))}function ra(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M4 8L8 4",stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M4 4L8 8",stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M8.5 1.2H9C9.99411 1.2 10.8 2.00589 10.8 3V9C10.8 9.99411 9.99411 10.8 9 10.8H8.5V12H9C10.6569 12 12 10.6569 12 9V3C12 1.34315 10.6569 0 9 0H8.5V1.2ZM3.5 1.2V0H3C1.34315 0 0 1.34315 0 3V9C0 10.6569 1.34315 12 3 12H3.5V10.8H3C2.00589 10.8 1.2 9.99411 1.2 9V3C1.2 2.00589 2.00589 1.2 3 1.2H3.5Z",fill:"currentColor"}))}function ia(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:.6,y:.6,width:10.8,height:10.8,rx:3.4,stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M4 8L8 4",stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M4 4L8 8",stroke:"currentColor",strokeWidth:1.2}))}function oa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0.5 12 12",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:7,y:5.5,width:2,height:2,rx:1,transform:"rotate(90 7 5.5)",fill:"currentColor"}),t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M10.8 9L10.8 9.5C10.8 10.4941 9.99411 11.3 9 11.3L3 11.3C2.00589 11.3 1.2 10.4941 1.2 9.5L1.2 9L-3.71547e-07 9L-3.93402e-07 9.5C-4.65826e-07 11.1569 1.34314 12.5 3 12.5L9 12.5C10.6569 12.5 12 11.1569 12 9.5L12 9L10.8 9ZM10.8 4L12 4L12 3.5C12 1.84315 10.6569 0.5 9 0.5L3 0.5C1.34315 0.5 -5.87117e-08 1.84315 -1.31135e-07 3.5L-1.5299e-07 4L1.2 4L1.2 3.5C1.2 2.50589 2.00589 1.7 3 1.7L9 1.7C9.99411 1.7 10.8 2.50589 10.8 3.5L10.8 4Z",fill:"currentColor"}))}function aa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 20 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M0.75 3C0.75 1.75736 1.75736 0.75 3 0.75H17.25C17.8023 0.75 18.25 1.19772 18.25 1.75V5.25",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{d:"M0.75 3C0.75 4.24264 1.75736 5.25 3 5.25H18.25C18.8023 5.25 19.25 5.69771 19.25 6.25V22.25C19.25 22.8023 18.8023 23.25 18.25 23.25H3C1.75736 23.25 0.75 22.2426 0.75 21V3Z",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M3 5.25C1.75736 5.25 0.75 4.24264 0.75 3V21C0.75 22.2426 1.75736 23.25 3 23.25H18.25C18.8023 23.25 19.25 22.8023 19.25 22.25V6.25C19.25 5.69771 18.8023 5.25 18.25 5.25H3ZM13 11L6 11V12.5L13 12.5V11Z",fill:"currentColor"}))}function sa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 20 24",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M0.75 3C0.75 4.24264 1.75736 5.25 3 5.25H17.25M0.75 3C0.75 1.75736 1.75736 0.75 3 0.75H16.25C16.8023 0.75 17.25 1.19772 17.25 1.75V5.25M0.75 3V21C0.75 22.2426 1.75736 23.25 3 23.25H18.25C18.8023 23.25 19.25 22.8023 19.25 22.25V6.25C19.25 5.69771 18.8023 5.25 18.25 5.25H17.25",stroke:"currentColor",strokeWidth:1.5}),t.createElement("line",{x1:13,y1:11.75,x2:6,y2:11.75,stroke:"currentColor",strokeWidth:1.5}))}function la(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:5,y:5,width:2,height:2,rx:1,fill:"currentColor"}),t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M8.5 1.2H9C9.99411 1.2 10.8 2.00589 10.8 3V9C10.8 9.99411 9.99411 10.8 9 10.8H8.5V12H9C10.6569 12 12 10.6569 12 9V3C12 1.34315 10.6569 0 9 0H8.5V1.2ZM3.5 1.2V0H3C1.34315 0 0 1.34315 0 3V9C0 10.6569 1.34315 12 3 12H3.5V10.8H3C2.00589 10.8 1.2 9.99411 1.2 9V3C1.2 2.00589 2.00589 1.2 3 1.2H3.5Z",fill:"currentColor"}))}function ua(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 12 13",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:.6,y:1.1,width:10.8,height:10.8,rx:2.4,stroke:"currentColor",strokeWidth:1.2}),t.createElement("rect",{x:5,y:5.5,width:2,height:2,rx:1,fill:"currentColor"}))}function ca(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 24 20",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M1.59375 9.52344L4.87259 12.9944L8.07872 9.41249",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"square"}),t.createElement("path",{d:"M13.75 5.25V10.75H18.75",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"square"}),t.createElement("path",{d:"M4.95427 11.9332C4.55457 10.0629 4.74441 8.11477 5.49765 6.35686C6.25089 4.59894 7.5305 3.11772 9.16034 2.11709C10.7902 1.11647 12.6901 0.645626 14.5986 0.769388C16.5071 0.893151 18.3303 1.60543 19.8172 2.80818C21.3042 4.01093 22.3818 5.64501 22.9017 7.48548C23.4216 9.32595 23.3582 11.2823 22.7203 13.0853C22.0824 14.8883 20.9013 16.4492 19.3396 17.5532C17.778 18.6572 15.9125 19.25 14 19.25",stroke:"currentColor",strokeWidth:1.5}))}function da(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 12 12",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("circle",{cx:6,cy:6,r:5.4,stroke:"currentColor",strokeWidth:1.2,strokeDasharray:"4.241025 4.241025",transform:"rotate(22.5)","transform-origin":"center"}),t.createElement("circle",{cx:6,cy:6,r:1,fill:"currentColor"}))}function fa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 19 18",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M1.5 14.5653C1.5 15.211 1.75652 15.8303 2.21314 16.2869C2.66975 16.7435 3.28905 17 3.9348 17C4.58054 17 5.19984 16.7435 5.65646 16.2869C6.11307 15.8303 6.36959 15.211 6.36959 14.5653V12.1305H3.9348C3.28905 12.1305 2.66975 12.387 2.21314 12.8437C1.75652 13.3003 1.5 13.9195 1.5 14.5653Z",stroke:"currentColor",strokeWidth:1.125,strokeLinecap:"round",strokeLinejoin:"round"}),t.createElement("path",{d:"M3.9348 1.00063C3.28905 1.00063 2.66975 1.25715 2.21314 1.71375C1.75652 2.17035 1.5 2.78964 1.5 3.43537C1.5 4.0811 1.75652 4.70038 2.21314 5.15698C2.66975 5.61358 3.28905 5.8701 3.9348 5.8701H6.36959V3.43537C6.36959 2.78964 6.11307 2.17035 5.65646 1.71375C5.19984 1.25715 4.58054 1.00063 3.9348 1.00063Z",stroke:"currentColor",strokeWidth:1.125,strokeLinecap:"round",strokeLinejoin:"round"}),t.createElement("path",{d:"M15.0652 12.1305H12.6304V14.5653C12.6304 15.0468 12.7732 15.5175 13.0407 15.9179C13.3083 16.3183 13.6885 16.6304 14.1334 16.8147C14.5783 16.9989 15.0679 17.0472 15.5402 16.9532C16.0125 16.8593 16.4464 16.6274 16.7869 16.2869C17.1274 15.9464 17.3593 15.5126 17.4532 15.0403C17.5472 14.568 17.4989 14.0784 17.3147 13.6335C17.1304 13.1886 16.8183 12.8084 16.4179 12.5409C16.0175 12.2733 15.5468 12.1305 15.0652 12.1305Z",stroke:"currentColor",strokeWidth:1.125,strokeLinecap:"round",strokeLinejoin:"round"}),t.createElement("path",{d:"M12.6318 5.86775H6.36955V12.1285H12.6318V5.86775Z",stroke:"currentColor",strokeWidth:1.125,strokeLinecap:"round",strokeLinejoin:"round"}),t.createElement("path",{d:"M17.5 3.43473C17.5 2.789 17.2435 2.16972 16.7869 1.71312C16.3303 1.25652 15.711 1 15.0652 1C14.4195 1 13.8002 1.25652 13.3435 1.71312C12.8869 2.16972 12.6304 2.789 12.6304 3.43473V5.86946H15.0652C15.711 5.86946 16.3303 5.61295 16.7869 5.15635C17.2435 4.69975 17.5 4.08046 17.5 3.43473Z",stroke:"currentColor",strokeWidth:1.125,strokeLinecap:"round",strokeLinejoin:"round"}))}function pa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 13 13",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("circle",{cx:5,cy:5,r:4.35,stroke:"currentColor",strokeWidth:1.3}),t.createElement("line",{x1:8.45962,y1:8.54038,x2:11.7525,y2:11.8333,stroke:"currentColor",strokeWidth:1.3}))}function ha(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"-2 -2 22 22",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M17.2492 6V2.9569C17.2492 1.73806 16.2611 0.75 15.0423 0.75L2.9569 0.75C1.73806 0.75 0.75 1.73806 0.75 2.9569L0.75 6",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{d:"M0.749873 12V15.0431C0.749873 16.2619 1.73794 17.25 2.95677 17.25H15.0421C16.261 17.25 17.249 16.2619 17.249 15.0431V12",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{d:"M6 4.5L9 7.5L12 4.5",stroke:"currentColor",strokeWidth:1.5}),t.createElement("path",{d:"M12 13.5L9 10.5L6 13.5",stroke:"currentColor",strokeWidth:1.5}))}function ma(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M0.75 13.25L0.0554307 12.967C-0.0593528 13.2488 0.00743073 13.5719 0.224488 13.7851C0.441545 13.9983 0.765869 14.0592 1.04549 13.9393L0.75 13.25ZM12.8214 1.83253L12.2911 2.36286L12.2911 2.36286L12.8214 1.83253ZM12.8214 3.90194L13.3517 4.43227L12.8214 3.90194ZM10.0981 1.17859L9.56773 0.648259L10.0981 1.17859ZM12.1675 1.17859L12.6978 0.648258L12.6978 0.648257L12.1675 1.17859ZM2.58049 8.75697L3.27506 9.03994L2.58049 8.75697ZM2.70066 8.57599L3.23099 9.10632L2.70066 8.57599ZM5.2479 11.4195L4.95355 10.7297L5.2479 11.4195ZM5.42036 11.303L4.89003 10.7727L5.42036 11.303ZM4.95355 10.7297C4.08882 11.0987 3.41842 11.362 2.73535 11.6308C2.05146 11.9 1.35588 12.1743 0.454511 12.5607L1.04549 13.9393C1.92476 13.5624 2.60256 13.2951 3.28469 13.0266C3.96762 12.7578 4.65585 12.4876 5.54225 12.1093L4.95355 10.7297ZM1.44457 13.533L3.27506 9.03994L1.88592 8.474L0.0554307 12.967L1.44457 13.533ZM3.23099 9.10632L10.6284 1.70892L9.56773 0.648259L2.17033 8.04566L3.23099 9.10632ZM11.6371 1.70892L12.2911 2.36286L13.3517 1.3022L12.6978 0.648258L11.6371 1.70892ZM12.2911 3.37161L4.89003 10.7727L5.95069 11.8333L13.3517 4.43227L12.2911 3.37161ZM12.2911 2.36286C12.5696 2.64142 12.5696 3.09305 12.2911 3.37161L13.3517 4.43227C14.2161 3.56792 14.2161 2.16654 13.3517 1.3022L12.2911 2.36286ZM10.6284 1.70892C10.9069 1.43036 11.3586 1.43036 11.6371 1.70892L12.6978 0.648257C11.8335 -0.216088 10.4321 -0.216084 9.56773 0.648259L10.6284 1.70892ZM3.27506 9.03994C3.26494 9.06479 3.24996 9.08735 3.23099 9.10632L2.17033 8.04566C2.04793 8.16806 1.95123 8.31369 1.88592 8.474L3.27506 9.03994ZM5.54225 12.1093C5.69431 12.0444 5.83339 11.9506 5.95069 11.8333L4.89003 10.7727C4.90863 10.7541 4.92988 10.7398 4.95355 10.7297L5.54225 12.1093Z",fill:"currentColor"}),t.createElement("path",{d:"M11.5 4.5L9.5 2.5",stroke:"currentColor",strokeWidth:1.4026,strokeLinecap:"round",strokeLinejoin:"round"}),t.createElement("path",{d:"M5.5 10.5L3.5 8.5",stroke:"currentColor",strokeWidth:1.4026,strokeLinecap:"round",strokeLinejoin:"round"}))}function ga(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 16 18",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M1.32226e-07 1.6609C7.22332e-08 0.907329 0.801887 0.424528 1.46789 0.777117L15.3306 8.11621C16.0401 8.49182 16.0401 9.50818 15.3306 9.88379L1.46789 17.2229C0.801886 17.5755 1.36076e-06 17.0927 1.30077e-06 16.3391L1.32226e-07 1.6609Z",fill:"currentColor"}))}function va(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 10 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M4.25 9.25V13.5H5.75V9.25L10 9.25V7.75L5.75 7.75V3.5H4.25V7.75L0 7.75V9.25L4.25 9.25Z",fill:"currentColor"}))}function ya(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({width:25,height:25,viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M10.2852 24.0745L13.7139 18.0742",stroke:"currentColor",strokeWidth:1.5625}),t.createElement("path",{d:"M14.5742 24.0749L17.1457 19.7891",stroke:"currentColor",strokeWidth:1.5625}),t.createElement("path",{d:"M19.4868 24.0735L20.7229 21.7523C21.3259 20.6143 21.5457 19.3122 21.3496 18.0394C21.1535 16.7666 20.5519 15.591 19.6342 14.6874L23.7984 6.87853C24.0123 6.47728 24.0581 6.00748 23.9256 5.57249C23.7932 5.1375 23.4933 4.77294 23.0921 4.55901C22.6908 4.34509 22.221 4.29932 21.7861 4.43178C21.3511 4.56424 20.9865 4.86408 20.7726 5.26533L16.6084 13.0742C15.3474 12.8142 14.0362 12.9683 12.8699 13.5135C11.7035 14.0586 10.7443 14.9658 10.135 16.1L6 24.0735",stroke:"currentColor",strokeWidth:1.5625}),t.createElement("path",{d:"M4 15L5 13L7 12L5 11L4 9L3 11L1 12L3 13L4 15Z",stroke:"currentColor",strokeWidth:1.5625,strokeLinejoin:"round"}),t.createElement("path",{d:"M11.5 8L12.6662 5.6662L15 4.5L12.6662 3.3338L11.5 1L10.3338 3.3338L8 4.5L10.3338 5.6662L11.5 8Z",stroke:"currentColor",strokeWidth:1.5625,strokeLinejoin:"round"}))}function ba(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M4.75 9.25H1.25V12.75",stroke:"currentColor",strokeWidth:1,strokeLinecap:"square"}),t.createElement("path",{d:"M11.25 6.75H14.75V3.25",stroke:"currentColor",strokeWidth:1,strokeLinecap:"square"}),t.createElement("path",{d:"M14.1036 6.65539C13.8 5.27698 13.0387 4.04193 11.9437 3.15131C10.8487 2.26069 9.48447 1.76694 8.0731 1.75043C6.66173 1.73392 5.28633 2.19563 4.17079 3.0604C3.05526 3.92516 2.26529 5.14206 1.92947 6.513",stroke:"currentColor",strokeWidth:1}),t.createElement("path",{d:"M1.89635 9.34461C2.20001 10.723 2.96131 11.9581 4.05631 12.8487C5.15131 13.7393 6.51553 14.2331 7.9269 14.2496C9.33827 14.2661 10.7137 13.8044 11.8292 12.9396C12.9447 12.0748 13.7347 10.8579 14.0705 9.487",stroke:"currentColor",strokeWidth:1}))}function Ea(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 13 13",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:.6,y:.6,width:11.8,height:11.8,rx:5.9,stroke:"currentColor",strokeWidth:1.2}),t.createElement("path",{d:"M4.25 7.5C4.25 6 5.75 5 6.5 6.5C7.25 8 8.75 7 8.75 5.5",stroke:"currentColor",strokeWidth:1.2}))}function Ta(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 21 20",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M9.29186 1.92702C9.06924 1.82745 8.87014 1.68202 8.70757 1.50024L7.86631 0.574931C7.62496 0.309957 7.30773 0.12592 6.95791 0.0479385C6.60809 -0.0300431 6.24274 0.00182978 5.91171 0.139208C5.58068 0.276585 5.3001 0.512774 5.10828 0.815537C4.91645 1.1183 4.82272 1.47288 4.83989 1.83089L4.90388 3.08019C4.91612 3.32348 4.87721 3.56662 4.78968 3.79394C4.70215 4.02126 4.56794 4.2277 4.39571 4.39994C4.22347 4.57219 4.01704 4.7064 3.78974 4.79394C3.56243 4.88147 3.3193 4.92038 3.07603 4.90814L1.8308 4.84414C1.47162 4.82563 1.11553 4.91881 0.811445 5.11086C0.507359 5.30292 0.270203 5.58443 0.132561 5.91671C-0.00508149 6.249 -0.0364554 6.61576 0.0427496 6.9666C0.121955 7.31744 0.307852 7.63514 0.5749 7.87606L1.50016 8.71204C1.68193 8.87461 1.82735 9.07373 1.92692 9.29636C2.02648 9.51898 2.07794 9.76012 2.07794 10.004C2.07794 10.2479 2.02648 10.489 1.92692 10.7116C1.82735 10.9343 1.68193 11.1334 1.50016 11.296L0.5749 12.1319C0.309856 12.3729 0.125575 12.6898 0.0471809 13.0393C-0.0312128 13.3888 9.64098e-05 13.754 0.13684 14.0851C0.273583 14.4162 0.509106 14.6971 0.811296 14.8894C1.11349 15.0817 1.46764 15.1762 1.82546 15.1599L3.0707 15.0959C3.31397 15.0836 3.5571 15.1225 3.7844 15.2101C4.01171 15.2976 4.21814 15.4318 4.39037 15.6041C4.56261 15.7763 4.69682 15.9827 4.78435 16.2101C4.87188 16.4374 4.91078 16.6805 4.89855 16.9238L4.83455 18.1691C4.81605 18.5283 4.90921 18.8844 5.10126 19.1885C5.2933 19.4926 5.5748 19.7298 5.90707 19.8674C6.23934 20.0051 6.60608 20.0365 6.9569 19.9572C7.30772 19.878 7.6254 19.6921 7.86631 19.4251L8.7129 18.4998C8.87547 18.318 9.07458 18.1725 9.29719 18.073C9.51981 17.9734 9.76093 17.9219 10.0048 17.9219C10.2487 17.9219 10.4898 17.9734 10.7124 18.073C10.935 18.1725 11.1341 18.318 11.2967 18.4998L12.1326 19.4251C12.3735 19.6921 12.6912 19.878 13.042 19.9572C13.3929 20.0365 13.7596 20.0051 14.0919 19.8674C14.4241 19.7298 14.7056 19.4926 14.8977 19.1885C15.0897 18.8844 15.1829 18.5283 15.1644 18.1691L15.1004 16.9238C15.0882 16.6805 15.1271 16.4374 15.2146 16.2101C15.3021 15.9827 15.4363 15.7763 15.6086 15.6041C15.7808 15.4318 15.9872 15.2976 16.2145 15.2101C16.4418 15.1225 16.685 15.0836 16.9282 15.0959L18.1735 15.1599C18.5326 15.1784 18.8887 15.0852 19.1928 14.8931C19.4969 14.7011 19.7341 14.4196 19.8717 14.0873C20.0093 13.755 20.0407 13.3882 19.9615 13.0374C19.8823 12.6866 19.6964 12.3689 19.4294 12.1279L18.5041 11.292C18.3223 11.1294 18.1769 10.9303 18.0774 10.7076C17.9778 10.485 17.9263 10.2439 17.9263 10C17.9263 9.75612 17.9778 9.51499 18.0774 9.29236C18.1769 9.06973 18.3223 8.87062 18.5041 8.70804L19.4294 7.87206C19.6964 7.63114 19.8823 7.31344 19.9615 6.9626C20.0407 6.61176 20.0093 6.245 19.8717 5.91271C19.7341 5.58043 19.4969 5.29892 19.1928 5.10686C18.8887 4.91481 18.5326 4.82163 18.1735 4.84014L16.9282 4.90414C16.685 4.91638 16.4418 4.87747 16.2145 4.78994C15.9872 4.7024 15.7808 4.56818 15.6086 4.39594C15.4363 4.2237 15.3021 4.01726 15.2146 3.78994C15.1271 3.56262 15.0882 3.31948 15.1004 3.07619L15.1644 1.83089C15.1829 1.4717 15.0897 1.11559 14.8977 0.811487C14.7056 0.507385 14.4241 0.270217 14.0919 0.132568C13.7596 -0.00508182 13.3929 -0.0364573 13.042 0.0427519C12.6912 0.121961 12.3735 0.307869 12.1326 0.574931L11.2914 1.50024C11.1288 1.68202 10.9297 1.82745 10.7071 1.92702C10.4845 2.02659 10.2433 2.07805 9.99947 2.07805C9.7556 2.07805 9.51448 2.02659 9.29186 1.92702ZM14.3745 10C14.3745 12.4162 12.4159 14.375 9.99977 14.375C7.58365 14.375 5.625 12.4162 5.625 10C5.625 7.58375 7.58365 5.625 9.99977 5.625C12.4159 5.625 14.3745 7.58375 14.3745 10Z",fill:"currentColor"}))}function wa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M6.5782 1.07092C6.71096 0.643026 7.28904 0.643027 7.4218 1.07092L8.59318 4.84622C8.65255 5.03758 8.82284 5.16714 9.01498 5.16714L12.8056 5.16714C13.2353 5.16714 13.4139 5.74287 13.0663 6.00732L9.99962 8.34058C9.84418 8.45885 9.77913 8.66848 9.83851 8.85984L11.0099 12.6351C11.1426 13.063 10.675 13.4189 10.3274 13.1544L7.26069 10.8211C7.10524 10.7029 6.89476 10.7029 6.73931 10.8211L3.6726 13.1544C3.32502 13.4189 2.85735 13.063 2.99012 12.6351L4.16149 8.85984C4.22087 8.66848 4.15582 8.45885 4.00038 8.34058L0.933671 6.00732C0.586087 5.74287 0.764722 5.16714 1.19436 5.16714L4.98502 5.16714C5.17716 5.16714 5.34745 5.03758 5.40682 4.84622L6.5782 1.07092Z",fill:"currentColor",stroke:"currentColor"}))}function Ca(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 14 14",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("path",{d:"M6.5782 1.07092C6.71096 0.643026 7.28904 0.643027 7.4218 1.07092L8.59318 4.84622C8.65255 5.03758 8.82284 5.16714 9.01498 5.16714L12.8056 5.16714C13.2353 5.16714 13.4139 5.74287 13.0663 6.00732L9.99962 8.34058C9.84418 8.45885 9.77913 8.66848 9.83851 8.85984L11.0099 12.6351C11.1426 13.063 10.675 13.4189 10.3274 13.1544L7.26069 10.8211C7.10524 10.7029 6.89476 10.7029 6.73931 10.8211L3.6726 13.1544C3.32502 13.4189 2.85735 13.063 2.99012 12.6351L4.16149 8.85984C4.22087 8.66848 4.15582 8.45885 4.00038 8.34058L0.933671 6.00732C0.586087 5.74287 0.764722 5.16714 1.19436 5.16714L4.98502 5.16714C5.17716 5.16714 5.34745 5.03758 5.40682 4.84622L6.5782 1.07092Z",stroke:"currentColor",strokeWidth:1.5}))}function Sa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{width:16,height:16,rx:2,fill:"currentColor"}))}function xa(e){var n=e,{title:r,titleId:i}=n,o=v(n,["title","titleId"]);return t.createElement("svg",Object.assign({height:"1em",viewBox:"0 0 13 13",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-labelledby":i},o),r?t.createElement("title",{id:i},r):null,t.createElement("rect",{x:.6,y:.6,width:11.8,height:11.8,rx:5.9,stroke:"currentColor",strokeWidth:1.2}),t.createElement("rect",{x:5.5,y:5.5,width:2,height:2,rx:1,fill:"currentColor"}))}g(Xo,"SvgArgument"),g(Yo,"SvgChevronDown"),g(Jo,"SvgChevronLeft"),g(Zo,"SvgChevronUp"),g(ea,"SvgClose"),g(ta,"SvgCopy"),g(na,"SvgDeprecatedArgument"),g(ra,"SvgDeprecatedEnumValue"),g(ia,"SvgDeprecatedField"),g(oa,"SvgDirective"),g(aa,"SvgDocsFilled"),g(sa,"SvgDocs"),g(la,"SvgEnumValue"),g(ua,"SvgField"),g(ca,"SvgHistory"),g(da,"SvgImplements"),g(fa,"SvgKeyboardShortcut"),g(pa,"SvgMagnifyingGlass"),g(ha,"SvgMerge"),g(ma,"SvgPen"),g(ga,"SvgPlay"),g(va,"SvgPlus"),g(ya,"SvgPrettify"),g(ba,"SvgReload"),g(Ea,"SvgRootType"),g(Ta,"SvgSettings"),g(wa,"SvgStarFilled"),g(Ca,"SvgStar"),g(Sa,"SvgStop"),g(xa,"SvgType");var ka=Object.defineProperty,Na=g(((e,t)=>ka(e,"name",{value:t,configurable:!0})),"__name$E");const _a=is(Xo,"argument icon");e.ac=_a;const Oa=is(Yo,"chevron down icon");e.ad=Oa;const Ia=is(Jo,"chevron left icon");e.ae=Ia;const Da=is(Zo,"chevron up icon");e.af=Da;const La=is(ea,"close icon");e.ag=La;const Aa=is(ta,"copy icon");e.ah=Aa;const Ma=is(na,"deprecated argument icon");e.ai=Ma;const Ra=is(ra,"deprecated enum value icon");e.aj=Ra;const Fa=is(ia,"deprecated field icon");e.ak=Fa;const Pa=is(oa,"directive icon");e.al=Pa;const ja=is(aa,"filled docs icon");e.am=ja;const Va=is(sa,"docs icon");e.an=Va;const Ua=is(la,"enum value icon");e.ao=Ua;const Ba=is(ua,"field icon");e.ap=Ba;const $a=is(ca,"history icon");e.aq=$a;const qa=is(da,"implements icon");e.ar=qa;const Ha=is(fa,"keyboard shortcut icon");e.as=Ha;const Ga=is(pa,"magnifying glass icon");e.at=Ga;const za=is(ha,"merge icon");e.au=za;const Wa=is(ma,"pen icon");e.av=Wa;const Ka=is(ga,"play icon");e.aw=Ka;const Qa=is(va,"plus icon");e.ax=Qa;const Xa=is(ya,"prettify icon");e.ay=Xa;const Ya=is(ba,"reload icon");e.az=Ya;const Ja=is(Ea,"root type icon");e.aA=Ja;const Za=is(Ta,"settings icon");e.aB=Za;const es=is(wa,"filled star icon");e.aC=es;const ts=is(Ca,"star icon");e.aD=ts;const ns=is(Sa,"stop icon");e.aE=ns;const rs=is(xa,"type icon");function is(e,t){const n=Na(g((function(n){return de(e,m(h({},n),{title:t}))}),"IconComponent"),"IconComponent");return Object.defineProperty(n,"name",{value:e.name}),n}e.aF=rs,g(is,"generateIcon"),Na(is,"generateIcon");const os=(0,t.forwardRef)(((e,t)=>de("button",m(h({},e),{ref:t,className:b("graphiql-un-styled",e.className)}))));e.aG=os,os.displayName="UnStyledButton";const as=(0,t.forwardRef)(((e,t)=>de("button",m(h({},e),{ref:t,className:b("graphiql-button",{success:"graphiql-button-success",error:"graphiql-button-error"}[e.state],e.className)}))));e.aH=as,as.displayName="Button";const ss=(0,t.forwardRef)(((e,t)=>de("div",m(h({},e),{ref:t,className:b("graphiql-button-group",e.className)}))));function ls(){return!("undefined"==typeof window||!window.document||!window.document.createElement)}e.aI=ss,ss.displayName="ButtonGroup",g(ls,"canUseDOM");var us=ls()?t.useLayoutEffect:t.useEffect;function cs(){var e=(0,t.useState)(Object.create(null))[1];return(0,t.useCallback)((function(){e(Object.create(null))}),[])}function ds(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}g(cs,"useForceUpdate"),g(ds,"_objectWithoutPropertiesLoose$b");var fs=["unstable_skipInitialRender"],ps=g((function(e){var n=e.children,r=e.type,o=void 0===r?"reach-portal":r,a=e.containerRef,s=(0,t.useRef)(null),l=(0,t.useRef)(null),u=cs();return us((function(){if(s.current){var e=s.current.ownerDocument,t=(null==a?void 0:a.current)||e.body;return l.current=null==e?void 0:e.createElement(o),t.appendChild(l.current),u(),function(){l.current&&t&&t.removeChild(l.current)}}}),[o,u,a]),l.current?(0,i.createPortal)(n,l.current):(0,t.createElement)("span",{ref:s})}),"PortalImpl"),hs=g((function(e){var n=e.unstable_skipInitialRender,r=ds(e,fs),i=(0,t.useState)(!1),o=i[0],a=i[1];return(0,t.useEffect)((function(){n&&a(!0)}),[n]),n&&!o?null:(0,t.createElement)(ps,r)}),"Portal");function ms(e){return ls()?e?e.ownerDocument:document:null}function gs(e){return"boolean"==typeof e}function vs(e){return!(!e||"[object Function]"!={}.toString.call(e))}function ys(e){return"string"==typeof e}function bs(){}function Es(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(n=e[Symbol.iterator]()).next.bind(n)}function Cs(e,t){if(null!=e)if(vs(e))e(t);else try{e.current=t}catch(n){throw new Error('Cannot assign value "'+t+'" to ref "'+e+'"')}}function Ss(){for(var e=arguments.length,n=new Array(e),r=0;r=0||(i[n]=e[n]);return i}function Ns(){return Ns=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0})).sort(Tl)}),"orderByTabIndex"),Cl=["button:enabled","select:enabled","textarea:enabled","input:enabled","a[href]","area[href]","summary","iframe","object","embed","audio[controls]","video[controls]","[tabindex]","[contenteditable]","[autofocus]"].join(","),Sl="".concat(Cl,", [data-focus-guard]"),xl=g((function(e,t){var n;return rl((null===(n=e.shadowRoot)||void 0===n?void 0:n.children)||e.children).reduce((function(e,n){return e.concat(n.matches(t?Sl:Cl)?[n]:[],xl(n))}),[])}),"getFocusablesWithShadowDom"),kl=g((function(e,t){return e.reduce((function(e,n){return e.concat(xl(n,t),n.parentNode?rl(n.parentNode.querySelectorAll(Cl)).filter((function(e){return e===n})):[])}),[])}),"getFocusables"),Nl=g((function(e){var t=e.querySelectorAll("[".concat("data-autofocus-inside","]"));return rl(t).map((function(e){return kl([e])})).reduce((function(e,t){return e.concat(t)}),[])}),"getParentAutofocusables"),_l=g((function(e,t){return rl(e).filter((function(e){return ul(t,e)})).filter((function(e){return gl(e)}))}),"filterFocusable"),Ol=g((function(e,t){return void 0===t&&(t=new Map),rl(e).filter((function(e){return dl(t,e)}))}),"filterAutoFocusable"),Il=g((function(e,t,n){return wl(_l(kl(e,n),t),!0,n)}),"getTabbableNodes"),Dl=g((function(e,t){return wl(_l(kl(e),t),!1)}),"getAllTabbableNodes"),Ll=g((function(e,t){return _l(Nl(e),t)}),"parentAutofocusables"),Al=g((function(e,t){return(e.shadowRoot?Al(e.shadowRoot,t):Object.getPrototypeOf(e).contains.call(e,t))||rl(e.children).some((function(e){return Al(e,t)}))}),"contains"),Ml=g((function(e){for(var t=new Set,n=e.length,r=0;r0&&t.add(i),(o&Node.DOCUMENT_POSITION_CONTAINS)>0&&t.add(r)}return e.filter((function(e,n){return!t.has(n)}))}),"filterNested"),Rl=g((function(e){return e.parentNode?Rl(e.parentNode):e}),"getTopParent"),Fl=g((function(e){return il(e).filter(Boolean).reduce((function(e,t){var n=t.getAttribute(Ds);return e.push.apply(e,n?Ml(rl(Rl(t).querySelectorAll("[".concat(Ds,'="').concat(n,'"]:not([').concat(Ls,'="disabled"])')))):[t]),e}),[])}),"getAllAffectedNodes"),Pl=g((function(e){return e.activeElement?e.activeElement.shadowRoot?Pl(e.activeElement.shadowRoot):e.activeElement:void 0}),"getNestedShadowActiveElement"),jl=g((function(){return document.activeElement?document.activeElement.shadowRoot?Pl(document.activeElement.shadowRoot):document.activeElement:void 0}),"getActiveElement"),Vl=g((function(e){return e===document.activeElement}),"focusInFrame"),Ul=g((function(e){return Boolean(rl(e.querySelectorAll("iframe")).some((function(e){return Vl(e)})))}),"focusInsideIframe"),Bl=g((function(e){var t=document&&jl();return!(!t||t.dataset&&t.dataset.focusGuard)&&Fl(e).some((function(e){return Al(e,t)||Ul(e)}))}),"focusInside"),$l=g((function(){var e=document&&jl();return!!e&&rl(document.querySelectorAll("[".concat("data-no-focus-lock","]"))).some((function(t){return Al(t,e)}))}),"focusIsHidden"),ql=g((function(e,t){return t.filter(ml).filter((function(t){return t.name===e.name})).filter((function(e){return e.checked}))[0]||e}),"findSelectedRadio"),Hl=g((function(e,t){return ml(e)&&e.name?ql(e,t):e}),"correctNode"),Gl=g((function(e){var t=new Set;return e.forEach((function(n){return t.add(Hl(n,e))})),e.filter((function(e){return t.has(e)}))}),"correctNodes"),zl=g((function(e){return e[0]&&e.length>1?Hl(e[0],e):e[0]}),"pickFirstFocus"),Wl=g((function(e,t){return e.length>1?e.indexOf(Hl(e[t],e)):t}),"pickFocusable"),Kl="NEW_FOCUS",Ql=g((function(e,t,n,r){var i=e.length,o=e[0],a=e[i-1],s=yl(n);if(!(n&&e.indexOf(n)>=0)){var l=void 0!==n?t.indexOf(n):-1,u=r?t.indexOf(r):l,c=r?e.indexOf(r):-1,d=l-u,f=t.indexOf(o),p=t.indexOf(a),h=Gl(t),m=(void 0!==n?h.indexOf(n):-1)-(r?h.indexOf(r):l),g=Wl(e,0),v=Wl(e,i-1);return-1===l||-1===c?Kl:!d&&c>=0?c:l<=f&&s&&Math.abs(d)>1?v:l>=p&&s&&Math.abs(d)>1?g:d&&Math.abs(m)>1?c:l<=f?v:l>p?g:d?Math.abs(d)>1?c:(i+c+d)%i:void 0}}),"newFocus"),Xl=g((function(e,t){return void 0===t&&(t=[]),t.push(e),e.parentNode&&Xl(e.parentNode.host||e.parentNode,t),t}),"getParents"),Yl=g((function(e,t){for(var n=Xl(e),r=Xl(t),i=0;i=0)return o}return!1}),"getCommonParent"),Jl=g((function(e,t,n){var r=il(e),i=il(t),o=r[0],a=!1;return i.filter(Boolean).forEach((function(e){a=Yl(a||e,e)||a,n.filter(Boolean).forEach((function(e){var t=Yl(o,e);t&&(a=!a||Al(t,a)?t:Yl(t,a))}))})),a}),"getTopCommonParent"),Zl=g((function(e,t){return e.reduce((function(e,n){return e.concat(Ll(n,t))}),[])}),"allParentAutofocusables"),eu=g((function(e){return function(t){var n;return t.autofocus||!!(null===(n=fl(t))||void 0===n?void 0:n.autofocus)||e.indexOf(t)>=0}}),"findAutoFocused"),tu=g((function(e,t){var n=new Map;return t.forEach((function(e){return n.set(e.node,e)})),e.map((function(e){return n.get(e)})).filter(El)}),"reorderNodes"),nu=g((function(e,t){var n=document&&jl(),r=Fl(e).filter(bl),i=Jl(n||e,e,r),o=new Map,a=Dl(r,o),s=Il(r,o).filter((function(e){var t=e.node;return bl(t)}));if(s[0]||(s=a)[0]){var l=Dl([i],o).map((function(e){return e.node})),u=tu(l,s),c=u.map((function(e){return e.node})),d=Ql(c,l,n,t);if(d===Kl){var f=Ol(a.map((function(e){return e.node}))).filter(eu(Zl(r,o)));return{node:f&&f.length?zl(f):zl(Ol(c))}}return void 0===d?d:u[d]}}),"getFocusMerge"),ru=g((function(e){var t=Fl(e).filter(bl),n=Jl(e,e,t),r=new Map,i=Il([n],r,!0),o=Il(t,r).filter((function(e){var t=e.node;return bl(t)})).map((function(e){return e.node}));return i.map((function(e){var t=e.node;return{node:t,index:e.index,lockItem:o.indexOf(t)>=0,guard:yl(t)}}))}),"getFocusabledIn"),iu=g((function(e,t){"focus"in e&&e.focus(t),"contentWindow"in e&&e.contentWindow&&e.contentWindow.focus()}),"focusOn"),ou=0,au=!1,su=g((function(e,t,n){void 0===n&&(n={});var r=nu(e,t);if(!au&&r){if(ou>2)return console.error("FocusLock: focus-fighting detected. Only one focus management system could be active. See https://github.com/theKashey/focus-lock/#focus-fighting"),au=!0,void setTimeout((function(){au=!1}),1);ou++,iu(r.node,n.focusOptions),ou--}}),"setFocus");function lu(e){var t=window.setImmediate;void 0!==t?t(e):setTimeout(e,1)}g(lu,"deferAction");var uu=g((function(){return document&&document.activeElement===document.body}),"focusOnBody"),cu=g((function(){return uu()||$l()}),"isFreeFocus"),du=null,fu=null,pu=null,hu=!1,mu=g((function(){return!0}),"defaultWhitelist"),gu=g((function(e){return(du.whiteList||mu)(e)}),"focusWhitelisted"),vu=g((function(e,t){pu={observerNode:e,portaledElement:t}}),"recordPortal"),yu=g((function(e){return pu&&pu.portaledElement===e}),"focusIsPortaledPair");function bu(e,t,n,r){var i=null,o=e;do{var a=r[o];if(a.guard)a.node.dataset.focusAutoGuard&&(i=a);else{if(!a.lockItem)break;if(o!==e)return;i=null}}while((o+=n)!==t);i&&(i.node.tabIndex=0)}g(bu,"autoGuard");var Eu=g((function(e){return e&&"current"in e?e.current:e}),"extractRef"),Tu=g((function(e){return e?Boolean(hu):"meanwhile"===hu}),"focusWasOutside"),wu=g((function e(t,n,r){return n&&(n.host===t&&(!n.activeElement||r.contains(n.activeElement))||n.parentNode&&e(t,n.parentNode,r))}),"checkInHost"),Cu=g((function(e,t){return t.some((function(t){return wu(e,t,t)}))}),"withinHost"),Su=g((function(){var e=!1;if(du){var t=du,n=t.observed,r=t.persistentFocus,i=t.autoFocus,o=t.shards,a=t.crossFrame,s=t.focusOptions,l=n||pu&&pu.portaledElement,u=document&&document.activeElement;if(l){var c=[l].concat(o.map(Eu).filter(Boolean));if(u&&!gu(u)||(r||Tu(a)||!cu()||!fu&&i)&&(l&&!(Bl(c)||u&&Cu(u,c)||yu(u))&&(document&&!fu&&u&&!i?(u.blur&&u.blur(),document.body.focus()):(e=su(c,fu,{focusOptions:s}),pu={})),hu=!1,fu=document&&document.activeElement),document){var d=document&&document.activeElement,f=ru(c),p=f.map((function(e){return e.node})).indexOf(d);p>-1&&(f.filter((function(e){var t=e.guard,n=e.node;return t&&n.dataset.focusAutoGuard})).forEach((function(e){return e.node.removeAttribute("tabIndex")})),bu(p,f.length,1,f),bu(p,-1,-1,f))}}}return e}),"activateTrap"),xu=g((function(e){Su()&&e&&(e.stopPropagation(),e.preventDefault())}),"onTrap"),ku=g((function(){return lu(Su)}),"onBlur"),Nu=g((function(e){var t=e.target,n=e.currentTarget;n.contains(t)||vu(n,t)}),"onFocus"),_u=g((function(){return null}),"FocusWatcher"),Ou=g((function(){hu="just",setTimeout((function(){hu="meanwhile"}),0)}),"onWindowBlur"),Iu=g((function(){document.addEventListener("focusin",xu),document.addEventListener("focusout",ku),window.addEventListener("blur",Ou)}),"attachHandler"),Du=g((function(){document.removeEventListener("focusin",xu),document.removeEventListener("focusout",ku),window.removeEventListener("blur",Ou)}),"detachHandler");function Lu(e){return e.filter((function(e){return!e.disabled}))}function Au(e){var t=e.slice(-1)[0];t&&!du&&Iu();var n=du,r=n&&t&&t.id===n.id;du=t,n&&!r&&(n.onDeactivation(),e.filter((function(e){return e.id===n.id})).length||n.returnFocus(!t)),t?(fu=null,r&&n.observed===t.observed||t.onActivation(),Su(),lu(Su)):(Du(),fu=null)}g(Lu,"reducePropsToState"),g(Au,"handleStateChangeOnClient"),zs.assignSyncMedium(Nu),Ws.assignMedium(ku),Ks.assignMedium((function(e){return e({moveFocusInside:su,focusInside:Bl})}));var Mu=nl(Lu,Au)(_u),Ru=t.forwardRef(g((function(e,n){return t.createElement(Js,Ns({sideCar:Mu,ref:n},e))}),"FocusLockUICombination")),Fu=Js.propTypes||{};Fu.sideCar,ks(Fu,["sideCar"]),Ru.propTypes={};var Pu=Ru,ju="right-scroll-bar-position",Vu="width-before-scroll-bar",Uu=qs(),Bu=g((function(){}),"nothing"),$u=t.forwardRef((function(e,n){var r=t.useRef(null),i=t.useState({onScrollCapture:Bu,onWheelCapture:Bu,onTouchMoveCapture:Bu}),o=i[0],a=i[1],s=e.forwardProps,l=e.children,u=e.className,c=e.removeScrollBar,d=e.enabled,f=e.shards,p=e.sideCar,h=e.noIsolation,m=e.inert,g=e.allowPinchZoom,v=e.as,y=void 0===v?"div":v,b=js(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noIsolation","inert","allowPinchZoom","as"]),E=p,T=Rs([r,n]),w=Ps(Ps({},b),o);return t.createElement(t.Fragment,null,d&&t.createElement(E,{sideCar:Uu,removeScrollBar:c,shards:f,noIsolation:h,inert:m,setCallbacks:a,allowPinchZoom:!!g,lockRef:r}),s?t.cloneElement(t.Children.only(l),Ps(Ps({},w),{ref:T})):t.createElement(y,Ps({},w,{className:u,ref:T}),l))}));$u.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1},$u.classNames={fullWidth:Vu,zeroRight:ju};var qu=g((function(){return n.nc}),"getNonce");function Hu(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=qu();return t&&e.setAttribute("nonce",t),e}function Gu(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function zu(e){(document.head||document.getElementsByTagName("head")[0]).appendChild(e)}g(Hu,"makeStyleTag"),g(Gu,"injectStyles"),g(zu,"insertStyleTag");var Wu=g((function(){var e=0,t=null;return{add:function(n){0==e&&(t=Hu())&&(Gu(t,n),zu(t)),e++},remove:function(){!--e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}}),"stylesheetSingleton"),Ku=g((function(){var e=Wu();return function(n,r){t.useEffect((function(){return e.add(n),function(){e.remove()}}),[n&&r])}}),"styleHookSingleton"),Qu=g((function(){var e=Ku();return g((function(t){var n=t.styles,r=t.dynamic;return e(n,r),null}),"Sheet")}),"styleSingleton"),Xu={left:0,top:0,right:0,gap:0},Yu=g((function(e){return parseInt(e||"",10)||0}),"parse$1"),Ju=g((function(e){var t=window.getComputedStyle(document.body),n=t["padding"===e?"paddingLeft":"marginLeft"],r=t["padding"===e?"paddingTop":"marginTop"],i=t["padding"===e?"paddingRight":"marginRight"];return[Yu(n),Yu(r),Yu(i)]}),"getOffset"),Zu=g((function(e){if(void 0===e&&(e="margin"),"undefined"==typeof window)return Xu;var t=Ju(e),n=document.documentElement.clientWidth,r=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,r-n+t[2]-t[0])}}),"getGapWidth"),ec=Qu(),tc=g((function(e,t,n,r){var i=e.left,o=e.top,a=e.right,s=e.gap;return void 0===n&&(n="margin"),"\n .".concat("with-scroll-bars-hidden"," {\n overflow: hidden ").concat(r,";\n padding-right: ").concat(s,"px ").concat(r,";\n }\n body {\n overflow: hidden ").concat(r,";\n overscroll-behavior: contain;\n ").concat([t&&"position: relative ".concat(r,";"),"margin"===n&&"\n padding-left: ".concat(i,"px;\n padding-top: ").concat(o,"px;\n padding-right: ").concat(a,"px;\n margin-left:0;\n margin-top:0;\n margin-right: ").concat(s,"px ").concat(r,";\n "),"padding"===n&&"padding-right: ".concat(s,"px ").concat(r,";")].filter(Boolean).join(""),"\n }\n \n .").concat(ju," {\n right: ").concat(s,"px ").concat(r,";\n }\n \n .").concat(Vu," {\n margin-right: ").concat(s,"px ").concat(r,";\n }\n \n .").concat(ju," .").concat(ju," {\n right: 0 ").concat(r,";\n }\n \n .").concat(Vu," .").concat(Vu," {\n margin-right: 0 ").concat(r,";\n }\n \n body {\n ").concat("--removed-body-scroll-bar-size",": ").concat(s,"px;\n }\n")}),"getStyles$2"),nc=g((function(e){var n=e.noRelative,r=e.noImportant,i=e.gapMode,o=void 0===i?"margin":i,a=t.useMemo((function(){return Zu(o)}),[o]);return t.createElement(ec,{styles:tc(a,!n,o,r?"":"!important")})}),"RemoveScrollBar"),rc=!1;if("undefined"!=typeof window)try{var ic=Object.defineProperty({},"passive",{get:function(){return rc=!0,!0}});window.addEventListener("test",ic,ic),window.removeEventListener("test",ic,ic)}catch(e){rc=!1}var oc=!!rc&&{passive:!1},ac=g((function(e){return"TEXTAREA"===e.tagName}),"alwaysContainsScroll"),sc=g((function(e,t){var n=window.getComputedStyle(e);return"hidden"!==n[t]&&!(n.overflowY===n.overflowX&&!ac(e)&&"visible"===n[t])}),"elementCanBeScrolled"),lc=g((function(e){return sc(e,"overflowY")}),"elementCouldBeVScrolled"),uc=g((function(e){return sc(e,"overflowX")}),"elementCouldBeHScrolled"),cc=g((function(e,t){var n=t;do{if("undefined"!=typeof ShadowRoot&&n instanceof ShadowRoot&&(n=n.host),pc(e,n)){var r=hc(e,n);if(r[1]>r[2])return!0}n=n.parentNode}while(n&&n!==document.body);return!1}),"locationCouldBeScrolled"),dc=g((function(e){return[e.scrollTop,e.scrollHeight,e.clientHeight]}),"getVScrollVariables"),fc=g((function(e){return[e.scrollLeft,e.scrollWidth,e.clientWidth]}),"getHScrollVariables"),pc=g((function(e,t){return"v"===e?lc(t):uc(t)}),"elementCouldBeScrolled"),hc=g((function(e,t){return"v"===e?dc(t):fc(t)}),"getScrollVariables"),mc=g((function(e,t){return"h"===e&&"rtl"===t?-1:1}),"getDirectionFactor"),gc=g((function(e,t,n,r,i){var o=mc(e,window.getComputedStyle(t).direction),a=o*r,s=n.target,l=t.contains(s),u=!1,c=a>0,d=0,f=0;do{var p=hc(e,s),h=p[0],m=p[1]-p[2]-o*h;(h||m)&&pc(e,s)&&(d+=m,f+=h),s=s.parentNode}while(!l&&s!==document.body||l&&(t.contains(s)||t===s));return(c&&(i&&0===d||!i&&a>d)||!c&&(i&&0===f||!i&&-a>f))&&(u=!0),u}),"handleScroll"),vc=g((function(e){return"changedTouches"in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]}),"getTouchXY"),yc=g((function(e){return[e.deltaX,e.deltaY]}),"getDeltaXY"),bc=g((function(e){return e&&"current"in e?e.current:e}),"extractRef"),Ec=g((function(e,t){return e[0]===t[0]&&e[1]===t[1]}),"deltaCompare"),Tc=g((function(e){return"\n .block-interactivity-".concat(e," {pointer-events: none;}\n .allow-interactivity-").concat(e," {pointer-events: all;}\n")}),"generateStyle"),wc=0,Cc=[];function Sc(e){var n=t.useRef([]),r=t.useRef([0,0]),i=t.useRef(),o=t.useState(wc++)[0],a=t.useState((function(){return Qu()}))[0],s=t.useRef(e);t.useEffect((function(){s.current=e}),[e]),t.useEffect((function(){if(e.inert){document.body.classList.add("block-interactivity-".concat(o));var t=Vs([e.lockRef.current],(e.shards||[]).map(bc),!0).filter(Boolean);return t.forEach((function(e){return e.classList.add("allow-interactivity-".concat(o))})),function(){document.body.classList.remove("block-interactivity-".concat(o)),t.forEach((function(e){return e.classList.remove("allow-interactivity-".concat(o))}))}}}),[e.inert,e.lockRef.current,e.shards]);var l=t.useCallback((function(e,t){if("touches"in e&&2===e.touches.length)return!s.current.allowPinchZoom;var n,o=vc(e),a=r.current,l="deltaX"in e?e.deltaX:a[0]-o[0],u="deltaY"in e?e.deltaY:a[1]-o[1],c=e.target,d=Math.abs(l)>Math.abs(u)?"h":"v";if("touches"in e&&"h"===d&&"range"===c.type)return!1;var f=cc(d,c);if(!f)return!0;if(f?n=d:(n="v"===d?"h":"v",f=cc(d,c)),!f)return!1;if(!i.current&&"changedTouches"in e&&(l||u)&&(i.current=n),!n)return!0;var p=i.current||n;return gc(p,t,e,"h"===p?l:u,!0)}),[]),u=t.useCallback((function(e){var t=e;if(Cc.length&&Cc[Cc.length-1]===a){var r="deltaY"in t?yc(t):vc(t),i=n.current.filter((function(e){return e.name===t.type&&e.target===t.target&&Ec(e.delta,r)}))[0];if(i&&i.should)t.cancelable&&t.preventDefault();else if(!i){var o=(s.current.shards||[]).map(bc).filter(Boolean).filter((function(e){return e.contains(t.target)}));(o.length>0?l(t,o[0]):!s.current.noIsolation)&&t.cancelable&&t.preventDefault()}}}),[]),c=t.useCallback((function(e,t,r,i){var o={name:e,delta:t,target:r,should:i};n.current.push(o),setTimeout((function(){n.current=n.current.filter((function(e){return e!==o}))}),1)}),[]),d=t.useCallback((function(e){r.current=vc(e),i.current=void 0}),[]),f=t.useCallback((function(t){c(t.type,yc(t),t.target,l(t,e.lockRef.current))}),[]),p=t.useCallback((function(t){c(t.type,vc(t),t.target,l(t,e.lockRef.current))}),[]);t.useEffect((function(){return Cc.push(a),e.setCallbacks({onScrollCapture:f,onWheelCapture:f,onTouchMoveCapture:p}),document.addEventListener("wheel",u,oc),document.addEventListener("touchmove",u,oc),document.addEventListener("touchstart",d,oc),function(){Cc=Cc.filter((function(e){return e!==a})),document.removeEventListener("wheel",u,oc),document.removeEventListener("touchmove",u,oc),document.removeEventListener("touchstart",d,oc)}}),[]);var h=e.removeScrollBar,m=e.inert;return t.createElement(t.Fragment,null,m?t.createElement(a,{styles:Tc(o)}):null,h?t.createElement(nc,{gapMode:"margin"}):null)}g(Sc,"RemoveScrollSideCar");var xc=Gs(Uu,Sc),kc=t.forwardRef((function(e,n){return t.createElement($u,Ps({},e,{ref:n,sideCar:xc}))}));kc.classNames=$u.classNames;var Nc=kc,_c={exports:{}},Oc="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";function Ic(){}function Dc(){}g(Ic,"emptyFunction"),g(Dc,"emptyFunctionWithReset"),Dc.resetWarningCache=Ic;var Lc=g((function(){function e(e,t,n,r,i,o){if(o!==Oc){var a=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw a.name="Invariant Violation",a}}function t(){return e}g(e,"shim"),e.isRequired=e,g(t,"getShim");var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:Dc,resetWarningCache:Ic};return n.PropTypes=n,n}),"factoryWithThrowingShims");_c.exports=Lc();var Ac=_c.exports;function Mc(){return Mc=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}g(Mc,"_extends$9"),g(Rc,"_objectWithoutPropertiesLoose$9");var Fc=["as","isOpen"],Pc=["allowPinchZoom","as","dangerouslyBypassFocusLock","dangerouslyBypassScrollLock","initialFocusRef","onClick","onDismiss","onKeyDown","onMouseDown","unstable_lockFocusAcrossFrames"],jc=["as","onClick","onKeyDown"],Vc=["allowPinchZoom","initialFocusRef","isOpen","onDismiss"];Ac.bool,Ac.bool,Ac.bool,Ac.func;var Uc=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e.isOpen,a=void 0===o||o,s=Rc(e,Fc);return(0,t.useEffect)((function(){a?window.__REACH_DISABLE_TOOLTIPS=!0:window.requestAnimationFrame((function(){window.__REACH_DISABLE_TOOLTIPS=!1}))}),[a]),a?(0,t.createElement)(hs,{"data-reach-dialog-wrapper":""},(0,t.createElement)(Bc,Mc({ref:n,as:i},s))):null}),"DialogOverlay")),Bc=(0,t.forwardRef)(g((function(e,n){var r=e.allowPinchZoom,i=e.as,o=void 0===i?"div":i,a=e.dangerouslyBypassFocusLock,s=void 0!==a&&a,l=e.dangerouslyBypassScrollLock,u=void 0!==l&&l,c=e.initialFocusRef,d=e.onClick,f=e.onDismiss,p=void 0===f?bs:f,h=e.onKeyDown,m=e.onMouseDown,v=e.unstable_lockFocusAcrossFrames,y=Rc(e,Pc),b=(0,t.useRef)(null),E=(0,t.useRef)(null),T=Ss(E,n),w=(0,t.useCallback)((function(){c&&c.current&&c.current.focus()}),[c]);function C(e){b.current===e.target&&(e.stopPropagation(),p(e))}function S(e){"Escape"===e.key&&(e.stopPropagation(),p(e))}function x(e){b.current=e.target}return g(C,"handleClick"),g(S,"handleKeyDown"),g(x,"handleMouseDown"),(0,t.useEffect)((function(){return E.current?Hc(E.current):void 0}),[]),(0,t.createElement)(Pu,{autoFocus:!0,returnFocus:!0,onActivation:w,disabled:s,crossFrame:null==v||v},(0,t.createElement)(Nc,{allowPinchZoom:r,enabled:!u},(0,t.createElement)(o,Mc({},y,{ref:T,"data-reach-dialog-overlay":"",onClick:xs(d,C),onKeyDown:xs(h,S),onMouseDown:xs(m,x)}))))}),"DialogInner")),$c=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e.onClick;e.onKeyDown;var a=Rc(e,jc);return(0,t.createElement)(i,Mc({"aria-modal":"true",role:"dialog",tabIndex:-1},a,{ref:n,"data-reach-dialog-content":"",onClick:xs(o,(function(e){e.stopPropagation()}))}))}),"DialogContent")),qc=(0,t.forwardRef)(g((function(e,n){var r=e.allowPinchZoom,i=void 0!==r&&r,o=e.initialFocusRef,a=e.isOpen,s=e.onDismiss,l=void 0===s?bs:s,u=Rc(e,Vc);return(0,t.createElement)(Uc,{allowPinchZoom:i,initialFocusRef:o,isOpen:a,onDismiss:l},(0,t.createElement)($c,Mc({ref:n},u)))}),"Dialog"));function Hc(e){var t=[],n=[],r=ms(e);return e?(Array.prototype.forEach.call(r.querySelectorAll("body > *"),(function(r){var i,o;if(r!==(null==(i=e.parentNode)||null==(o=i.parentNode)?void 0:o.parentNode)){var a=r.getAttribute("aria-hidden");null!==a&&"false"!==a||(t.push(a),n.push(r),r.setAttribute("aria-hidden","true"))}})),function(){n.forEach((function(e,n){var r=t[n];null===r?e.removeAttribute("aria-hidden"):e.setAttribute("aria-hidden",r)}))}):bs}function Gc(){return Gc=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}g(Hc,"createAriaHider"),g(Gc,"_extends$8"),g(zc,"_objectWithoutPropertiesLoose$8");var Wc=["as","style"],Kc=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"span":r,o=e.style,a=void 0===o?{}:o,s=zc(e,Wc);return(0,t.createElement)(i,Gc({ref:n,style:Gc({border:0,clip:"rect(0 0 0 0)",height:"1px",margin:"-1px",overflow:"hidden",padding:0,position:"absolute",width:"1px",whiteSpace:"nowrap",wordWrap:"normal"},a)},s))}),"VisuallyHidden")),Qc=Object.defineProperty;const Xc=g(((e,t)=>Qc(e,"name",{value:t,configurable:!0})),"__name$D")(((e,t)=>Object.entries(t).reduce(((e,t)=>{let[n,r]=t;return e[n]=r,e}),e)),"createComponentGroup"),Yc=(0,t.forwardRef)(((e,t)=>de(qc,m(h({},e),{ref:t}))));Yc.displayName="Dialog";const Jc=(0,t.forwardRef)(((e,t)=>fe(os,m(h({},e),{ref:t,type:"button",className:b("graphiql-dialog-close",e.className),children:[de(Kc,{children:"Close dialog"}),de(La,{})]}))));Jc.displayName="Dialog.Close";const Zc=Xc(Yc,{Close:Jc});e.aJ=Zc;var ed=!1,td=0;function nd(){return++td}function rd(e){var n;if("function"==typeof t.useId){var r=(0,t.useId)(e);return null!=e?e:r}var i=null!=e?e:ed?nd():null,o=(0,t.useState)(i),a=o[0],s=o[1];return us((function(){null===a&&s(nd())}),[]),(0,t.useEffect)((function(){!1===ed&&(ed=!0)}),[]),null!=(n=null!=e?e:a)?n:void 0}g(nd,"genId"),g(rd,"useId");var id,od=["bottom","height","left","right","top","width"],ad=g((function(e,t){return void 0===e&&(e={}),void 0===t&&(t={}),od.some((function(n){return e[n]!==t[n]}))}),"rectChanged"),sd=new Map,ld=g((function e(){var t=[];sd.forEach((function(e,n){var r=n.getBoundingClientRect();ad(r,e.rect)&&(e.rect=r,t.push(e))})),t.forEach((function(e){e.callbacks.forEach((function(t){return t(e.rect)}))})),id=window.requestAnimationFrame(e)}),"run");function ud(e,t){return{observe:g((function(){var n=0===sd.size;sd.has(e)?sd.get(e).callbacks.push(t):sd.set(e,{rect:void 0,hasRectChanged:!1,callbacks:[t]}),n&&ld()}),"observe"),unobserve:g((function(){var n=sd.get(e);if(n){var r=n.callbacks.indexOf(t);r>=0&&n.callbacks.splice(r,1),n.callbacks.length||sd.delete(e),sd.size||cancelAnimationFrame(id)}}),"unobserve")}}function cd(e,n,r){var i,o,a;gs(n)?i=n:(i=null==(a=null==n?void 0:n.observe)||a,o=null==n?void 0:n.onChange),vs(r)&&(o=r);var s=(0,t.useState)(e.current),l=s[0],u=s[1],c=(0,t.useRef)(!1),d=(0,t.useRef)(!1),f=(0,t.useState)(null),p=f[0],h=f[1],m=(0,t.useRef)(o);return us((function(){m.current=o,e.current!==l&&u(e.current)})),us((function(){l&&!c.current&&(c.current=!0,h(l.getBoundingClientRect()))}),[l]),us((function(){if(i){var t=l;if(d.current||(d.current=!0,t=e.current),t){var n=ud(t,(function(e){null==m.current||m.current(e),h(e)}));return n.observe(),function(){n.unobserve()}}}}),[i,l,e]),p}g(ud,"observeRect"),g(cd,"useRect");var dd=["input","select","textarea","a[href]","button","[tabindex]","audio[controls]","video[controls]",'[contenteditable]:not([contenteditable="false"])'],fd=dd.join(","),pd="undefined"==typeof Element?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector;function hd(e,t){t=t||{};var n,r,i,o=[],a=[],s=e.querySelectorAll(fd);for(t.includeContainer&&pd.call(e,fd)&&(s=Array.prototype.slice.apply(s)).unshift(e),n=0;n=0||(i[n]=e[n]);return i}g(Dd,"_extends$7"),g(Ld,"_objectWithoutPropertiesLoose$7");var Ad=["unstable_skipInitialPortalRender"],Md=["as","targetRef","position","unstable_observableRefs"],Rd=(0,t.forwardRef)(g((function(e,n){var r=e.unstable_skipInitialPortalRender,i=Ld(e,Ad);return(0,t.createElement)(hs,{unstable_skipInitialRender:r},(0,t.createElement)(Fd,Dd({ref:n},i)))}),"Popover")),Fd=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e.targetRef,a=e.position,s=void 0===a?Vd:a,l=e.unstable_observableRefs,u=void 0===l?[]:l,c=Ld(e,Md),d=(0,t.useRef)(null),f=cd(d,{observe:!c.hidden}),p=cd(o,{observe:!c.hidden}),h=Ss(d,n);return $d(o,d),(0,t.createElement)(i,Dd({"data-reach-popover":"",ref:h},c,{style:Dd({position:"absolute"},Pd.apply(void 0,[s,p,f].concat(u)),c.style)}))}),"PopoverImpl"));function Pd(e,t,n){for(var r=arguments.length,i=new Array(r>3?r-3:0),o=3;o=0||(i[n]=e[n]);return i}function Hd(){return Hd=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}g(zd,"createDescendantContext"),g(Wd,"useDescendant"),g(Kd,"useDescendantsInit"),g(Qd,"useDescendants"),g(Xd,"DescendantProvider"),g(Yd,"useDescendantKeyDown"),g(Jd,"isRightClick"),g(Zd,"createStableCallbackHook"),g(ef,"useStableCallback"),g(tf,"_objectWithoutPropertiesLoose$5");var nf,rf,of=["children"];function af(e,n){return(0,t.createContext)(n)}function sf(e,n){var r=(0,t.createContext)(n);function i(e){var n=e.children,i=tf(e,of),o=(0,t.useMemo)((function(){return i}),Object.values(i));return(0,t.createElement)(r.Provider,{value:o},n)}function o(i){var o=(0,t.useContext)(r);if(o)return o;if(n)return n;throw Error(i+" must be rendered inside of a "+e+" component.")}return g(i,"Provider"),g(o,"useContext$1"),[i,o]}function lf(){for(var e=arguments.length,t=new Array(e),n=0;n0||m,matches:hf(o)}}}}),"x");try{for(var p=function(e){var t="function"==typeof Symbol&&e[Symbol.iterator],n=0;return t?t.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}(d),h=p.next();!h.done;h=p.next()){var m=f(h.value);if("object"==typeof m)return m.value}}catch(e){i={error:e}}finally{try{h&&!h.done&&(o=p.return)&&o.call(p)}finally{if(i)throw i.error}}}return gf(s,l)}};return n}g(df,"e$1"),g(ff,"r$1"),g(pf,"i$1"),g(hf,"o"),g(mf,"a"),g(gf,"u"),g(vf,"c$1");var yf=g((function(e,t){return e.actions.forEach((function(n){var r=n.exec;return r&&r(e.context,t)}))}),"s");function bf(e){var t=e.initialState,n=nf.NotStarted,r=new Set,i={_machine:e,send:function(i){n===nf.Running&&(t=e.transition(t,i),yf(t,mf(i)),r.forEach((function(e){return e(t)})))},subscribe:function(e){return r.add(e),e(t),{unsubscribe:function(){return r.delete(e)}}},start:function(){return n=nf.Running,yf(t,cf),i},stop:function(){return n=nf.Stopped,r.clear(),i},get state(){return t},get status(){return n}};return i}function Ef(e){var n=(0,t.useRef)();return n.current||(n.current={v:e()}),n.current.v}function Tf(){return Tf=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}g(_f,"useMachine"),g(Of,"unwrapRefs"),g(If,"useCreateMachine"),g(Df,"_extends$4"),g(Lf,"_objectWithoutPropertiesLoose$4"),(kf=Cf||(Cf={})).Idle="IDLE",kf.Open="OPEN",kf.Navigating="NAVIGATING",kf.Dragging="DRAGGING",kf.Interacting="INTERACTING",(xf=Sf||(Sf={})).ButtonMouseDown="BUTTON_MOUSE_DOWN",xf.ButtonMouseUp="BUTTON_MOUSE_UP",xf.Blur="BLUR",xf.ClearNavSelection="CLEAR_NAV_SELECTION",xf.ClearTypeahead="CLEAR_TYPEAHEAD",xf.GetDerivedData="GET_DERIVED_DATA",xf.KeyDownEscape="KEY_DOWN_ESCAPE",xf.KeyDownEnter="KEY_DOWN_ENTER",xf.KeyDownSpace="KEY_DOWN_SPACE",xf.KeyDownNavigate="KEY_DOWN_NAVIGATE",xf.KeyDownSearch="KEY_DOWN_SEARCH",xf.KeyDownTab="KEY_DOWN_TAB",xf.KeyDownShiftTab="KEY_DOWN_SHIFT_TAB",xf.OptionTouchStart="OPTION_TOUCH_START",xf.OptionMouseMove="OPTION_MOUSE_MOVE",xf.OptionMouseEnter="OPTION_MOUSE_ENTER",xf.OptionMouseDown="OPTION_MOUSE_DOWN",xf.OptionMouseUp="OPTION_MOUSE_UP",xf.OptionClick="OPTION_CLICK",xf.ListMouseUp="LIST_MOUSE_UP",xf.OptionPress="OPTION_PRESS",xf.OutsideMouseDown="OUTSIDE_MOUSE_DOWN",xf.OutsideMouseUp="OUTSIDE_MOUSE_UP",xf.ValueChange="VALUE_CHANGE",xf.PopoverPointerDown="POPOVER_POINTER_DOWN",xf.PopoverPointerUp="POPOVER_POINTER_UP",xf.UpdateAfterTypeahead="UPDATE_AFTER_TYPEAHEAD";var Af=ff({navigationValue:null}),Mf=ff({typeaheadQuery:null}),Rf=ff({value:g((function(e,t){return t.value}),"value")}),Ff=ff({navigationValue:g((function(e,t){return t.value}),"navigationValue")}),Pf=ff({navigationValue:g((function(e){var t,n=tp(e.value,e.options);return n&&!n.disabled?e.value:(null==(t=e.options.find((function(e){return!e.disabled})))?void 0:t.value)||null}),"navigationValue")});function jf(e,t){if(t.type===Sf.Blur){var n=t.refs,r=n.list,i=n.popover,o=t.relatedTarget,a=ms(i);return!((null==a?void 0:a.activeElement)===r||!i||i.contains(o||(null==a?void 0:a.activeElement)))}return!1}function Vf(e,t){if(t.type===Sf.OutsideMouseDown||t.type===Sf.OutsideMouseUp){var n=t.refs,r=n.button,i=n.popover,o=t.relatedTarget;return!(o===r||!r||r.contains(o)||!i||i.contains(o))}return!1}function Uf(e,t){return!!e.options.find((function(t){return t.value===e.navigationValue}))}function Bf(e,t){var n=t.refs,r=n.popover,i=n.list,o=t.relatedTarget;return!(r&&o&&r.contains(o)&&o!==i)&&Uf(e)}function $f(e,t){requestAnimationFrame((function(){t.refs.list&&t.refs.list.focus()}))}function qf(e,t){t.refs.button&&t.refs.button.focus()}function Hf(e,t){return!t.disabled}function Gf(e,t){return t.type!==Sf.OptionTouchStart||!t||!t.disabled}function zf(e,t){return!("disabled"in t&&t.disabled||("value"in t?null==t.value:null==e.navigationValue))}function Wf(e,t){t.callback&&t.callback(t.value)}function Kf(e,t){if(t.type===Sf.KeyDownEnter){var n=t.refs.hiddenInput;if(n&&n.form){var r=n.form.querySelector("button:not([type]),[type='submit']");r&&r.click()}}}g(jf,"listboxLostFocus"),g(Vf,"clickedOutsideOfListbox"),g(Uf,"optionIsActive"),g(Bf,"shouldNavigate"),g($f,"focusList"),g(qf,"focusButton"),g(Hf,"listboxIsNotDisabled"),g(Gf,"optionIsNavigable"),g(zf,"optionIsSelectable"),g(Wf,"selectOption"),g(Kf,"submitForm");var Qf=ff({typeaheadQuery:g((function(e,t){return(e.typeaheadQuery||"")+t.query}),"typeaheadQuery")}),Xf=ff({value:g((function(e,t){if(t.type===Sf.UpdateAfterTypeahead&&t.query){var n=ep(e.options,t.query);if(n&&!n.disabled)return t.callback&&t.callback(n.value),n.value}return e.value}),"value")}),Yf=ff({navigationValue:g((function(e,t){if(t.type===Sf.UpdateAfterTypeahead&&t.query){var n=ep(e.options,t.query);if(n&&!n.disabled)return n.value}return e.navigationValue}),"navigationValue")}),Jf=((wf={})[Sf.GetDerivedData]={actions:ff((function(e,t){return Df({},e,t.data)}))},wf[Sf.ValueChange]={actions:[Rf,Wf]},wf),Zf=g((function(e){var t,n,r,i,o,a,s=e.value;return{id:"listbox",initial:Cf.Idle,context:{value:s,options:[],navigationValue:null,typeaheadQuery:null},states:(a={},a[Cf.Idle]={on:Df({},Jf,(t={},t[Sf.ButtonMouseDown]={target:Cf.Open,actions:[Pf],cond:Hf},t[Sf.KeyDownSpace]={target:Cf.Navigating,actions:[Pf,$f],cond:Hf},t[Sf.KeyDownSearch]={target:Cf.Idle,actions:Qf,cond:Hf},t[Sf.UpdateAfterTypeahead]={target:Cf.Idle,actions:[Xf],cond:Hf},t[Sf.ClearTypeahead]={target:Cf.Idle,actions:Mf},t[Sf.KeyDownNavigate]={target:Cf.Navigating,actions:[Pf,Mf,$f],cond:Hf},t[Sf.KeyDownEnter]={actions:[Kf],cond:Hf},t))},a[Cf.Interacting]={entry:[Af],on:Df({},Jf,(n={},n[Sf.ClearNavSelection]={actions:[Af,$f]},n[Sf.KeyDownEnter]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},n[Sf.KeyDownSpace]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},n[Sf.ButtonMouseDown]={target:Cf.Idle,actions:[qf]},n[Sf.KeyDownEscape]={target:Cf.Idle,actions:[qf]},n[Sf.OptionMouseDown]={target:Cf.Dragging},n[Sf.OutsideMouseDown]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Dragging,actions:Mf,cond:Uf}],n[Sf.OutsideMouseUp]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf},{target:Cf.Interacting,actions:Mf}],n[Sf.KeyDownEnter]=Cf.Interacting,n[Sf.Blur]=[{target:Cf.Idle,cond:jf,actions:Mf},{target:Cf.Navigating,cond:Bf},{target:Cf.Interacting,actions:Mf}],n[Sf.OptionTouchStart]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},n[Sf.OptionClick]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},n[Sf.OptionPress]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},n[Sf.OptionMouseEnter]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},n[Sf.KeyDownNavigate]={target:Cf.Navigating,actions:[Ff,Mf,$f]},n))},a[Cf.Open]={on:Df({},Jf,(r={},r[Sf.ClearNavSelection]={actions:[Af]},r[Sf.KeyDownEnter]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},r[Sf.KeyDownSpace]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},r[Sf.ButtonMouseDown]={target:Cf.Idle,actions:[qf]},r[Sf.KeyDownEscape]={target:Cf.Idle,actions:[qf]},r[Sf.OptionMouseDown]={target:Cf.Dragging},r[Sf.OutsideMouseDown]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Dragging,cond:Uf},{target:Cf.Interacting,actions:Mf}],r[Sf.OutsideMouseUp]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf},{target:Cf.Interacting,actions:Mf}],r[Sf.Blur]=[{target:Cf.Idle,cond:jf,actions:Mf},{target:Cf.Navigating,cond:Bf},{target:Cf.Interacting,actions:Mf}],r[Sf.ButtonMouseUp]={target:Cf.Navigating,actions:[Pf,$f]},r[Sf.ListMouseUp]={target:Cf.Navigating,actions:[Pf,$f]},r[Sf.OptionTouchStart]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},r[Sf.OptionClick]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},r[Sf.OptionPress]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},r[Sf.KeyDownNavigate]={target:Cf.Navigating,actions:[Ff,Mf,$f]},r[Sf.KeyDownSearch]={target:Cf.Navigating,actions:Qf},r[Sf.UpdateAfterTypeahead]={actions:[Yf]},r[Sf.ClearTypeahead]={actions:Mf},r[Sf.OptionMouseMove]=[{target:Cf.Dragging,actions:[Ff],cond:Gf},{target:Cf.Dragging}],r))},a[Cf.Dragging]={on:Df({},Jf,(i={},i[Sf.ClearNavSelection]={actions:[Af]},i[Sf.KeyDownEnter]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},i[Sf.KeyDownSpace]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},i[Sf.ButtonMouseDown]={target:Cf.Idle,actions:[qf]},i[Sf.KeyDownEscape]={target:Cf.Idle,actions:[qf]},i[Sf.OptionMouseDown]={target:Cf.Dragging},i[Sf.OutsideMouseDown]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf},{target:Cf.Interacting,actions:Mf}],i[Sf.OutsideMouseUp]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf,actions:$f},{target:Cf.Interacting,actions:[Mf,$f]}],i[Sf.Blur]=[{target:Cf.Idle,cond:jf,actions:Mf},{target:Cf.Navigating,cond:Bf},{target:Cf.Interacting,actions:Mf}],i[Sf.ButtonMouseUp]={target:Cf.Navigating,actions:[Pf,$f]},i[Sf.OptionTouchStart]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},i[Sf.OptionClick]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},i[Sf.OptionPress]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},i[Sf.OptionMouseEnter]={target:Cf.Dragging,actions:[Ff,Mf],cond:Gf},i[Sf.KeyDownNavigate]={target:Cf.Navigating,actions:[Ff,Mf,$f]},i[Sf.KeyDownSearch]={target:Cf.Navigating,actions:Qf},i[Sf.UpdateAfterTypeahead]={actions:[Yf]},i[Sf.ClearTypeahead]={actions:Mf},i[Sf.OptionMouseMove]=[{target:Cf.Navigating,actions:[Ff],cond:Gf},{target:Cf.Navigating}],i[Sf.OptionMouseUp]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},i))},a[Cf.Navigating]={on:Df({},Jf,(o={},o[Sf.ClearNavSelection]={actions:[Af,$f]},o[Sf.KeyDownEnter]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},o[Sf.KeyDownSpace]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},o[Sf.ButtonMouseDown]={target:Cf.Idle,actions:[qf]},o[Sf.KeyDownEscape]={target:Cf.Idle,actions:[qf]},o[Sf.OptionMouseDown]={target:Cf.Dragging},o[Sf.OutsideMouseDown]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf},{target:Cf.Interacting,actions:Mf}],o[Sf.OutsideMouseUp]=[{target:Cf.Idle,cond:Vf,actions:Mf},{target:Cf.Navigating,cond:Uf},{target:Cf.Interacting,actions:Mf}],o[Sf.Blur]=[{target:Cf.Idle,cond:jf,actions:Mf},{target:Cf.Navigating,cond:Bf},{target:Cf.Interacting,actions:Mf}],o[Sf.ButtonMouseUp]={target:Cf.Navigating,actions:[Pf,$f]},o[Sf.OptionTouchStart]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},o[Sf.OptionClick]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},o[Sf.OptionPress]={target:Cf.Idle,actions:[Rf,Mf,qf,Wf],cond:zf},o[Sf.OptionMouseEnter]={target:Cf.Navigating,actions:[Ff,Mf],cond:Gf},o[Sf.KeyDownNavigate]={target:Cf.Navigating,actions:[Ff,Mf,$f]},o[Sf.KeyDownSearch]={target:Cf.Navigating,actions:Qf},o[Sf.UpdateAfterTypeahead]={actions:[Yf]},o[Sf.ClearTypeahead]={actions:Mf},o[Sf.OptionMouseMove]=[{target:Cf.Navigating,actions:[Ff],cond:Gf},{target:Cf.Navigating}],o))},a)}}),"createMachineDefinition");function ep(e,t){return void 0===t&&(t=""),t&&e.find((function(e){return!e.disabled&&e.label&&e.label.toLowerCase().startsWith(t.toLowerCase())}))||null}function tp(e,t){return e?t.find((function(t){return t.value===e})):void 0}g(ep,"findOptionFromTypeahead"),g(tp,"findOptionFromValue");var np=["as","aria-labelledby","aria-label","children","defaultValue","disabled","form","name","onChange","required","value","__componentName"],rp=["arrow","button","children","portal"],ip=["aria-label","arrow","as","children","onKeyDown","onMouseDown","onMouseUp"],op=["as","children"],ap=["as","position","onBlur","onKeyDown","onMouseUp","portal","unstable_observableRefs"],sp=["as"],lp=["as","children","disabled","index","label","onClick","onMouseDown","onMouseEnter","onMouseLeave","onMouseMove","onMouseUp","onTouchStart","value"],up=zd(),cp=af(0,{}),dp=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e["aria-labelledby"],a=e["aria-label"],s=e.children,l=e.defaultValue,u=e.disabled,c=void 0!==u&&u,d=e.form,f=e.name,p=e.onChange,h=e.required,m=e.value;e.__componentName;var v=Lf(e,np),y=(0,t.useRef)(null!=m),b=Kd(),E=b[0],T=b[1],w=(0,t.useRef)(null),C=(0,t.useRef)(null),S=(0,t.useRef)(null),x=(0,t.useRef)(null),k=(0,t.useRef)(null),N=(0,t.useRef)(null),_=(0,t.useRef)(null),O=_f(If(Zf({value:(y.current?m:l)||null})),{button:w,hiddenInput:C,highlightedOption:S,input:x,list:k,popover:N,selectedOption:_},false),I=O[0],D=O[1];function L(e){e!==I.context.value&&(null==p||p(e))}g(L,"handleValueChange");var A=rd(v.id),M=v.id||lf("listbox-input",A),R=Ss(x,n),F=(0,t.useMemo)((function(){var e=E.find((function(e){return e.value===I.context.value}));return e?e.label:null}),[E,I.context.value]),P=Tp(I.value),j={ariaLabel:a,ariaLabelledBy:o,buttonRef:w,disabled:c,highlightedOptionRef:S,isExpanded:P,listboxId:M,listboxValueLabel:F,listRef:k,onValueChange:L,popoverRef:N,selectedOptionRef:_,send:D,state:I.value,stateData:I.context},V=(0,t.useRef)(!1);if(!y.current&&null==l&&!V.current&&E.length){V.current=!0;var U=E.find((function(e){return!e.disabled}));U&&U.value&&D({type:Sf.ValueChange,value:U.value})}return xp(m,I.context.value,(function(){D({type:Sf.ValueChange,value:m})})),us((function(){D({type:Sf.GetDerivedData,data:{options:E}})}),[E,D]),(0,t.useEffect)((function(){function e(e){var t=e.target,n=e.relatedTarget;Sp(N.current,t)||D({type:Sf.OutsideMouseDown,relatedTarget:n||t})}return g(e,"handleMouseDown"),P&&window.addEventListener("mousedown",e),function(){window.removeEventListener("mousedown",e)}}),[D,P]),(0,t.useEffect)((function(){function e(e){var t=e.target,n=e.relatedTarget;Sp(N.current,t)||D({type:Sf.OutsideMouseUp,relatedTarget:n||t})}return g(e,"handleMouseUp"),P&&window.addEventListener("mouseup",e),function(){window.removeEventListener("mouseup",e)}}),[D,P]),(0,t.createElement)(i,Df({},v,{ref:R,"data-reach-listbox-input":"","data-state":P?"expanded":"closed","data-value":I.context.value,id:M}),(0,t.createElement)(cp.Provider,{value:j},(0,t.createElement)(Xd,{context:up,items:E,set:T},vs(s)?s({id:M,isExpanded:P,value:I.context.value,selectedOptionRef:_,highlightedOptionRef:S,valueLabel:F,expanded:P}):s,(d||f||h)&&(0,t.createElement)("input",{ref:C,"data-reach-listbox-hidden-input":"",disabled:c,form:d,name:f,readOnly:!0,required:h,tabIndex:-1,type:"hidden",value:I.context.value||""}))))}),"ListboxInput")),fp=(0,t.forwardRef)(g((function(e,n){var r=e.arrow,i=void 0===r?"â–¼":r,o=e.button,a=e.children,s=e.portal,l=void 0===s||s,u=Lf(e,rp);return(0,t.createElement)(dp,Df({},u,{__componentName:"Listbox",ref:n}),(function(e){var n=e.value,r=e.valueLabel;return(0,t.createElement)(t.Fragment,null,(0,t.createElement)(hp,{arrow:i,children:o?vs(o)?o({value:n,label:r}):o:void 0}),(0,t.createElement)(yp,{portal:l},(0,t.createElement)(bp,null,a)))}))}),"Listbox")),pp=(0,t.forwardRef)(g((function(e,n){var r=e["aria-label"],i=e.arrow,o=void 0!==i&&i,a=e.as,s=void 0===a?"span":a,l=e.children,u=e.onKeyDown,c=e.onMouseDown,d=e.onMouseUp,f=Lf(e,ip),p=(0,t.useContext)(cp),h=p.buttonRef,m=p.send,v=p.ariaLabelledBy,y=p.disabled,b=p.isExpanded,E=p.listboxId,T=p.stateData,w=p.listboxValueLabel,C=T.value,S=Ss(h,n),x=wp();function k(e){Jd(e.nativeEvent)||(e.preventDefault(),e.stopPropagation(),m({type:Sf.ButtonMouseDown,disabled:y}))}function N(e){Jd(e.nativeEvent)||(e.preventDefault(),e.stopPropagation(),m({type:Sf.ButtonMouseUp}))}g(k,"handleMouseDown"),g(N,"handleMouseUp");var _=lf("button",E),O=(0,t.useMemo)((function(){return l?vs(l)?l({isExpanded:b,label:w,value:C,expanded:b}):l:w}),[l,w,b,C]);return(0,t.createElement)(s,Df({"aria-disabled":y||void 0,"aria-expanded":b||void 0,"aria-haspopup":"listbox","aria-labelledby":r?void 0:[v,_].filter(Boolean).join(" "),"aria-label":r,role:"button",tabIndex:y?-1:0},f,{ref:S,"data-reach-listbox-button":"",id:_,onKeyDown:xs(u,x),onMouseDown:xs(c,k),onMouseUp:xs(d,N)}),O,o&&(0,t.createElement)(gp,null,gs(o)?null:o))}),"ListboxButton")),hp=(0,t.memo)(pp),mp=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"span":r,o=e.children,a=Lf(e,op),s=(0,t.useContext)(cp).isExpanded;return(0,t.createElement)(i,Df({"aria-hidden":!0},a,{ref:n,"data-reach-listbox-arrow":"","data-expanded":s?"":void 0}),vs(o)?o({isExpanded:s,expanded:s}):o||"â–¼")}),"ListboxArrow")),gp=(0,t.memo)(mp),vp=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e.position,a=void 0===o?Ud:o,s=e.onBlur,l=e.onKeyDown,u=e.onMouseUp,c=e.portal,d=void 0===c||c,f=e.unstable_observableRefs,p=Lf(e,ap),h=(0,t.useContext)(cp),m=h.isExpanded,v=h.buttonRef,y=h.popoverRef,b=h.send,E=Ss(y,n),T=wp();function w(){b({type:Sf.ListMouseUp})}g(w,"handleMouseUp");var C=Df({hidden:!m,tabIndex:-1},p,{ref:E,"data-reach-listbox-popover":"",onMouseUp:xs(u,w),onBlur:xs(s,S),onKeyDown:xs(l,T)});function S(e){var t=e.nativeEvent;requestAnimationFrame((function(){b({type:Sf.Blur,relatedTarget:t.relatedTarget||t.target})}))}return g(S,"handleBlur"),d?(0,t.createElement)(Rd,Df({},C,{as:i,targetRef:v,position:a,unstable_observableRefs:f,unstable_skipInitialPortalRender:!0})):(0,t.createElement)(i,C)}),"ListboxPopover")),yp=(0,t.memo)(vp),bp=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"ul":r,o=Lf(e,sp),a=(0,t.useContext)(cp),s=a.listRef,l=a.ariaLabel,u=a.ariaLabelledBy,c=a.isExpanded,d=a.listboxId,f=a.stateData,p=f.value,h=f.navigationValue,m=Ss(n,s);return(0,t.createElement)(i,Df({"aria-activedescendant":Cp(c?h:p),"aria-labelledby":l?void 0:u,"aria-label":l,role:"listbox",tabIndex:-1},o,{ref:m,"data-reach-listbox-list":"",id:lf("listbox",d)}))}),"ListboxList")),Ep=(0,t.forwardRef)(g((function(e,n){var r=e.as,i=void 0===r?"li":r,o=e.children,a=e.disabled,s=e.index,l=e.label,u=e.onClick,c=e.onMouseDown,d=e.onMouseEnter,f=e.onMouseLeave,p=e.onMouseMove,h=e.onMouseUp,m=e.onTouchStart,v=e.value,y=Lf(e,lp),b=(0,t.useContext)(cp),E=b.highlightedOptionRef,T=b.selectedOptionRef,w=b.send,C=b.isExpanded,S=b.onValueChange,x=b.state,k=b.stateData,N=k.value,_=k.navigationValue,O=(0,t.useState)(l),I=O[0],D=O[1],L=l||I||"",A=uf((0,t.useRef)(null),null),M=A[0],R=A[1];Wd((0,t.useMemo)((function(){return{element:M,value:v,label:L,disabled:!!a}}),[a,M,L,v]),up,s);var F=(0,t.useCallback)((function(e){!l&&e&&D((function(t){return e.textContent&&t!==e.textContent?e.textContent:t||""}))}),[l]),P=!!_&&_===v,j=N===v,V=Ss(F,n,R,j?T:null,P?E:null);function U(){w({type:Sf.OptionMouseEnter,value:v,disabled:!!a})}function B(){w({type:Sf.OptionTouchStart,value:v,disabled:!!a})}function $(){w({type:Sf.ClearNavSelection})}function q(e){Jd(e.nativeEvent)||(e.preventDefault(),w({type:Sf.OptionMouseDown}))}function H(e){Jd(e.nativeEvent)||w({type:Sf.OptionMouseUp,value:v,callback:S,disabled:!!a})}function G(e){Jd(e.nativeEvent)||w({type:Sf.OptionClick,value:v,callback:S,disabled:!!a})}function z(){x!==Cf.Open&&_===v||w({type:Sf.OptionMouseMove,value:v,disabled:!!a})}return g(U,"handleMouseEnter"),g(B,"handleTouchStart"),g($,"handleMouseLeave"),g(q,"handleMouseDown"),g(H,"handleMouseUp"),g(G,"handleClick"),g(z,"handleMouseMove"),(0,t.createElement)(i,Df({"aria-selected":(C?P:j)||void 0,"aria-disabled":a||void 0,role:"option"},y,{ref:V,id:Cp(v),"data-reach-listbox-option":"","data-current-nav":P?"":void 0,"data-current-selected":j?"":void 0,"data-label":L,"data-value":v,onClick:xs(u,G),onMouseDown:xs(c,q),onMouseEnter:xs(d,U),onMouseLeave:xs(f,$),onMouseMove:xs(p,z),onMouseUp:xs(h,H),onTouchStart:xs(m,B)}),o)}),"ListboxOption"));function Tp(e){return[Cf.Navigating,Cf.Open,Cf.Dragging,Cf.Interacting].includes(e)}function wp(){var e=(0,t.useContext)(cp),n=e.send,r=e.disabled,i=e.onValueChange,o=e.stateData,a=o.navigationValue,s=o.typeaheadQuery,l=Qd(up),u=ef(i);(0,t.useEffect)((function(){s&&n({type:Sf.UpdateAfterTypeahead,query:s,callback:u});var e=window.setTimeout((function(){null!=s&&n({type:Sf.ClearTypeahead})}),1e3);return function(){window.clearTimeout(e)}}),[u,n,s]);var c=l.findIndex((function(e){return e.value===a}));return xs((function(e){var t=e.key,o=ys(t)&&1===t.length,s=l.find((function(e){return e.value===a}));switch(t){case"Enter":return void n({type:Sf.KeyDownEnter,value:a,callback:i,disabled:!!(null!=s&&s.disabled||r)});case" ":return e.preventDefault(),void n({type:Sf.KeyDownSpace,value:a,callback:i,disabled:!!(null!=s&&s.disabled||r)});case"Escape":return void n({type:Sf.KeyDownEscape});case"Tab":var u=e.shiftKey?Sf.KeyDownShiftTab:Sf.KeyDownTab;return void n({type:u});default:return void(o&&n({type:Sf.KeyDownSearch,query:t,disabled:r}))}}),Yd(up,{currentIndex:c,orientation:"vertical",key:"index",rotate:!0,filter:g((function(e){return!e.disabled}),"filter"),callback:g((function(e){n({type:Sf.KeyDownNavigate,value:l[e].value,disabled:r})}),"callback")}))}function Cp(e){var n=(0,t.useContext)(cp).listboxId;return e?lf("option-"+e,n):void 0}function Sp(e,t){return!(!e||!e.contains(t))}function xp(e,n,r){(0,t.useRef)(null!=e).current&&e!==n&&r()}function kp(e){var n=(0,t.useRef)(null);return(0,t.useEffect)((function(){n.current=e}),[e]),n.current}function Np(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function _p(){return _p=Object.assign||function(e){for(var t=1;t8||n>8)&&(C.current=!0)}V||null==j||p||E({type:Up,payload:{index:j,dropdownRef:T}})}function K(){C.current=!0,V||null==j||p||E({type:Up,payload:{index:j}})}function Q(e){Jd(e.nativeEvent)||(C.current?i?M.current?M.current=!1:O.current&&O.current.click():p||B():C.current=!0)}return S.current[j]=f,g(B,"select"),g($,"handleClick"),g(q,"handleDragStart"),g(H,"handleMouseDown"),g(G,"handleMouseEnter"),g(z,"handleMouseLeave"),g(W,"handleMouseMove"),g(K,"handleFocus"),g(Q,"handleMouseUp"),(0,t.useEffect)((function(){if(_){var e=window.setTimeout((function(){C.current=!0}),400);return function(){window.clearTimeout(e)}}C.current=!1}),[_,C]),(0,t.useEffect)((function(){var e=ms(O.current);return e.addEventListener("mouseup",t),function(){e.removeEventListener("mouseup",t)};function t(){M.current=!1}}),[]),{data:{disabled:p},props:_p({id:Zp(j),tabIndex:-1},y,{ref:U,"data-disabled":p?"":void 0,"data-selected":V?"":void 0,"data-valuetext":D,onClick:xs(o,$),onDragStart:xs(a,q),onMouseDown:xs(s,H),onMouseEnter:xs(l,G),onMouseLeave:xs(u,z),onMouseMove:xs(c,W),onFocus:xs(h,K),onMouseUp:xs(d,Q)})}}function Xp(e){e.id;var n=e.onKeyDown,r=e.ref,i=Np(e,Dp),o=Gp("useDropdownItems"),a=o.dispatch,s=o.triggerRef,l=o.dropdownRef,u=o.selectCallbacks,c=o.dropdownId,d=o.state,f=d.isExpanded,p=d.triggerId,h=d.selectionIndex,m=d.typeaheadQuery,v=rh(),y=Ss(l,r);(0,t.useEffect)((function(){var e=Jp(v,m);m&&null!=e&&a({type:Up,payload:{index:e,dropdownRef:l}});var t=window.setTimeout((function(){return m&&a({type:Vp,payload:""})}),1e3);return function(){return window.clearTimeout(t)}}),[a,v,m,l]);var b=kp(v.length),E=kp(v[h]),T=kp(h);(0,t.useEffect)((function(){h>v.length-1?a({type:Up,payload:{index:v.length-1,dropdownRef:l}}):b!==v.length&&h>-1&&E&&T===h&&v[h]!==E&&a({type:Up,payload:{index:v.findIndex((function(e){return e.key===(null==E?void 0:E.key)})),dropdownRef:l}})}),[l,a,v,b,E,T,h]);var w=xs(g((function(e){var t=e.key;if(f)switch(t){case"Enter":case" ":var n=v.find((function(e){return e.index===h}));n&&!n.disabled&&(e.preventDefault(),n.isLink&&n.element?n.element.click():(eh(s.current),u.current[n.index]&&u.current[n.index](),a({type:Mp})));break;case"Escape":eh(s.current),a({type:Rp});break;case"Tab":e.preventDefault();break;default:if(ys(t)&&1===t.length){var r=m+t.toLowerCase();a({type:Vp,payload:r})}}}),"handleKeyDown"),Yd($p,{currentIndex:h,orientation:"vertical",rotate:!1,filter:g((function(e){return!e.disabled}),"filter"),callback:g((function(e){a({type:Up,payload:{index:e,dropdownRef:l}})}),"callback"),key:"index"}));return{data:{activeDescendant:Zp(h)||void 0,triggerId:p},props:_p({tabIndex:-1},i,{ref:y,id:c,onKeyDown:xs(n,w)})}}function Yp(e){var n=e.onBlur,r=e.portal,i=void 0===r||r,o=e.position,a=e.ref,s=Np(e,Lp),l=Gp("useDropdownPopover"),u=l.triggerRef,c=l.triggerClickedRef,d=l.dispatch,f=l.dropdownRef,p=l.popoverRef,h=l.state.isExpanded,m=Ss(p,a);return(0,t.useEffect)((function(){if(h){var e=ms(p.current);return g(t,"listener"),e.addEventListener("mousedown",t),function(){e.removeEventListener("mousedown",t)}}function t(e){c.current?c.current=!1:th(p.current,e.target)||d({type:Rp})}}),[c,u,d,f,p,h]),{data:{portal:i,position:o,targetRef:u,isExpanded:h},props:_p({ref:m,hidden:!h,onBlur:xs(n,(function(e){e.currentTarget.contains(e.relatedTarget)||d({type:Rp})}))},s)}}function Jp(e,t){if(void 0===t&&(t=""),!t)return null;var n=e.find((function(e){var n,r,i;return!e.disabled&&(null==(n=e.element)||null==(r=n.dataset)||null==(i=r.valuetext)?void 0:i.toLowerCase().startsWith(t))}));return n?e.indexOf(n):null}function Zp(e){var t=Gp("useItemId").dropdownId;return null!=e&&e>-1?lf("option-"+e,t):void 0}function eh(e){e&&e.focus()}function th(e,t){return!(!e||!e.contains(t))}function nh(e,t){switch(void 0===t&&(t={}),t.type){case Mp:case Rp:return _p({},e,{isExpanded:!1,selectionIndex:-1});case Fp:return _p({},e,{isExpanded:!0,selectionIndex:0});case Pp:return _p({},e,{isExpanded:!0,selectionIndex:t.payload.index});case jp:return _p({},e,{isExpanded:!0,selectionIndex:-1});case Up:var n=t.payload.dropdownRef,r=void 0===n?{current:null}:n;if(t.payload.index>=0&&t.payload.index!==e.selectionIndex){if(r.current){var i=ms(r.current);r.current!==(null==i?void 0:i.activeElement)&&r.current.focus()}return _p({},e,{selectionIndex:null!=t.payload.max?Math.min(Math.max(t.payload.index,0),t.payload.max):Math.max(t.payload.index,0)})}return e;case Ap:return _p({},e,{selectionIndex:-1});case Bp:return _p({},e,{triggerId:t.payload});case Vp:return void 0!==t.payload?_p({},e,{typeaheadQuery:t.payload}):e;default:return e}}function rh(){return Qd($p)}g(Kp,"useDropdownTrigger"),g(Qp,"useDropdownItem"),g(Xp,"useDropdownItems"),g(Yp,"useDropdownPopover"),g(Jp,"findItemFromTypeahead"),g(Zp,"useItemId"),g(eh,"focus"),g(th,"popoverContainsEventTarget"),g(nh,"reducer$1"),g(rh,"useDropdownDescendants");var ih={exports:{}},oh={},ah="function"==typeof Symbol&&Symbol.for,sh=ah?Symbol.for("react.element"):60103,lh=ah?Symbol.for("react.portal"):60106,uh=ah?Symbol.for("react.fragment"):60107,ch=ah?Symbol.for("react.strict_mode"):60108,dh=ah?Symbol.for("react.profiler"):60114,fh=ah?Symbol.for("react.provider"):60109,ph=ah?Symbol.for("react.context"):60110,hh=ah?Symbol.for("react.async_mode"):60111,mh=ah?Symbol.for("react.concurrent_mode"):60111,gh=ah?Symbol.for("react.forward_ref"):60112,vh=ah?Symbol.for("react.suspense"):60113,yh=ah?Symbol.for("react.suspense_list"):60120,bh=ah?Symbol.for("react.memo"):60115,Eh=ah?Symbol.for("react.lazy"):60116,Th=ah?Symbol.for("react.block"):60121,wh=ah?Symbol.for("react.fundamental"):60117,Ch=ah?Symbol.for("react.responder"):60118,Sh=ah?Symbol.for("react.scope"):60119;function xh(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case sh:switch(e=e.type){case hh:case mh:case uh:case dh:case ch:case vh:return e;default:switch(e=e&&e.$$typeof){case ph:case gh:case Eh:case bh:case fh:return e;default:return t}}case lh:return t}}}function kh(e){return xh(e)===mh}function Nh(){return Nh=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}g(xh,"z"),g(kh,"A"),oh.AsyncMode=hh,oh.ConcurrentMode=mh,oh.ContextConsumer=ph,oh.ContextProvider=fh,oh.Element=sh,oh.ForwardRef=gh,oh.Fragment=uh,oh.Lazy=Eh,oh.Memo=bh,oh.Portal=lh,oh.Profiler=dh,oh.StrictMode=ch,oh.Suspense=vh,oh.isAsyncMode=function(e){return kh(e)||xh(e)===hh},oh.isConcurrentMode=kh,oh.isContextConsumer=function(e){return xh(e)===ph},oh.isContextProvider=function(e){return xh(e)===fh},oh.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===sh},oh.isForwardRef=function(e){return xh(e)===gh},oh.isFragment=function(e){return xh(e)===uh},oh.isLazy=function(e){return xh(e)===Eh},oh.isMemo=function(e){return xh(e)===bh},oh.isPortal=function(e){return xh(e)===lh},oh.isProfiler=function(e){return xh(e)===dh},oh.isStrictMode=function(e){return xh(e)===ch},oh.isSuspense=function(e){return xh(e)===vh},oh.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===uh||e===mh||e===dh||e===ch||e===vh||e===yh||"object"==typeof e&&null!==e&&(e.$$typeof===Eh||e.$$typeof===bh||e.$$typeof===fh||e.$$typeof===ph||e.$$typeof===gh||e.$$typeof===wh||e.$$typeof===Ch||e.$$typeof===Sh||e.$$typeof===Th)},oh.typeOf=xh,ih.exports=oh,g(Nh,"_extends$2"),g(_h,"_objectWithoutPropertiesLoose$2");var Oh=["as","id","children"],Ih=["as"],Dh=["as"],Lh=["as"],Ah=["as"],Mh=["portal"],Rh=["as"],Fh=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?t.Fragment:r,o=e.id,a=e.children,s=_h(e,Oh),l=(0,t.useMemo)((function(){try{return ih.exports.isFragment((0,t.createElement)(i,null))}catch(e){return!1}}),[i])?{}:Nh({ref:n,id:o,"data-reach-menu":""},s);return(0,t.createElement)(i,l,(0,t.createElement)(Wp,{id:o,children:a}))})),Ph=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"button":r,o=Kp(Nh({},_h(e,Ih),{ref:n})),a=o.data,s=a.isExpanded,l=a.controls,u=o.props;return(0,t.createElement)(i,Nh({"aria-expanded":!!s||void 0,"aria-haspopup":!0,"aria-controls":l},u,{"data-reach-menu-button":""}))})),jh=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"div":r,o=Qp(Nh({},_h(e,Dh),{ref:n})),a=o.data.disabled,s=o.props;return(0,t.createElement)(i,Nh({role:"menuitem"},s,{"aria-disabled":a||void 0,"data-reach-menu-item":""}))})),Vh=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"div":r,o=_h(e,Lh);return(0,t.createElement)(jh,Nh({},o,{ref:n,as:i}))})),Uh=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"div":r,o=Xp(Nh({},_h(e,Ah),{ref:n})),a=o.data,s=a.activeDescendant,l=a.triggerId,u=o.props;return(0,t.createElement)(i,Nh({"aria-activedescendant":s,"aria-labelledby":l||void 0,role:"menu"},u,{"data-reach-menu-items":""}))})),Bh=(0,t.forwardRef)((function(e,n){var r=e.portal,i=void 0===r||r,o=_h(e,Mh);return(0,t.createElement)($h,{portal:i},(0,t.createElement)(Uh,Nh({},o,{ref:n,"data-reach-menu-list":""})))})),$h=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"div":r,o=Yp(Nh({},_h(e,Rh),{ref:n})),a=o.data,s=a.portal,l=a.targetRef,u=a.position,c=o.props,d={"data-reach-menu-popover":""};return s?(0,t.createElement)(Rd,Nh({},c,d,{as:i,targetRef:l,position:u,unstable_skipInitialPortalRender:!0})):(0,t.createElement)(i,Nh({},c,d))}));const qh=(0,t.forwardRef)(((e,t)=>de(Ph,m(h({},e),{ref:t,className:b("graphiql-un-styled",e.className)}))));qh.displayName="MenuButton";const Hh=Xc(Fh,{Button:qh,Item:Vh,List:Bh});e.aK=Hh;const Gh=(0,t.forwardRef)(((e,t)=>de(hp,m(h({},e),{ref:t,className:b("graphiql-un-styled",e.className)}))));Gh.displayName="ListboxButton";const zh=Xc(fp,{Button:Gh,Input:dp,Option:Ep,Popover:yp});e.aL=zh;var Wh={};var Kh={Aacute:"Ã",aacute:"á",Abreve:"Ä‚",abreve:"ă",ac:"∾",acd:"∿",acE:"∾̳",Acirc:"Â",acirc:"â",acute:"´",Acy:"Ð",acy:"а",AElig:"Æ",aelig:"æ",af:"â¡",Afr:"ð”„",afr:"ð”ž",Agrave:"À",agrave:"à",alefsym:"ℵ",aleph:"ℵ",Alpha:"Α",alpha:"α",Amacr:"Ä€",amacr:"Ä",amalg:"⨿",amp:"&",AMP:"&",andand:"â©•",And:"â©“",and:"∧",andd:"â©œ",andslope:"⩘",andv:"â©š",ang:"∠",ange:"⦤",angle:"∠",angmsdaa:"⦨",angmsdab:"⦩",angmsdac:"⦪",angmsdad:"⦫",angmsdae:"⦬",angmsdaf:"⦭",angmsdag:"⦮",angmsdah:"⦯",angmsd:"∡",angrt:"∟",angrtvb:"⊾",angrtvbd:"â¦",angsph:"∢",angst:"Ã…",angzarr:"â¼",Aogon:"Ä„",aogon:"Ä…",Aopf:"ð”¸",aopf:"ð•’",apacir:"⩯",ap:"≈",apE:"â©°",ape:"≊",apid:"≋",apos:"'",ApplyFunction:"â¡",approx:"≈",approxeq:"≊",Aring:"Ã…",aring:"Ã¥",Ascr:"ð’œ",ascr:"ð’¶",Assign:"≔",ast:"*",asymp:"≈",asympeq:"â‰",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",awconint:"∳",awint:"⨑",backcong:"≌",backepsilon:"϶",backprime:"‵",backsim:"∽",backsimeq:"â‹",Backslash:"∖",Barv:"⫧",barvee:"⊽",barwed:"⌅",Barwed:"⌆",barwedge:"⌅",bbrk:"⎵",bbrktbrk:"⎶",bcong:"≌",Bcy:"Б",bcy:"б",bdquo:"„",becaus:"∵",because:"∵",Because:"∵",bemptyv:"⦰",bepsi:"϶",bernou:"ℬ",Bernoullis:"ℬ",Beta:"Î’",beta:"β",beth:"ℶ",between:"≬",Bfr:"ð”…",bfr:"ð”Ÿ",bigcap:"â‹‚",bigcirc:"â—¯",bigcup:"⋃",bigodot:"⨀",bigoplus:"â¨",bigotimes:"⨂",bigsqcup:"⨆",bigstar:"★",bigtriangledown:"â–½",bigtriangleup:"â–³",biguplus:"⨄",bigvee:"â‹",bigwedge:"â‹€",bkarow:"â¤",blacklozenge:"⧫",blacksquare:"â–ª",blacktriangle:"â–´",blacktriangledown:"â–¾",blacktriangleleft:"â—‚",blacktriangleright:"â–¸",blank:"â£",blk12:"â–’",blk14:"â–‘",blk34:"â–“",block:"â–ˆ",bne:"=⃥",bnequiv:"≡⃥",bNot:"â«­",bnot:"âŒ",Bopf:"ð”¹",bopf:"ð•“",bot:"⊥",bottom:"⊥",bowtie:"⋈",boxbox:"⧉",boxdl:"â”",boxdL:"â••",boxDl:"â•–",boxDL:"â•—",boxdr:"┌",boxdR:"â•’",boxDr:"â•“",boxDR:"â•”",boxh:"─",boxH:"â•",boxhd:"┬",boxHd:"╤",boxhD:"â•¥",boxHD:"╦",boxhu:"â”´",boxHu:"╧",boxhU:"╨",boxHU:"â•©",boxminus:"⊟",boxplus:"⊞",boxtimes:"⊠",boxul:"┘",boxuL:"â•›",boxUl:"â•œ",boxUL:"â•",boxur:"â””",boxuR:"╘",boxUr:"â•™",boxUR:"â•š",boxv:"│",boxV:"â•‘",boxvh:"┼",boxvH:"╪",boxVh:"â•«",boxVH:"╬",boxvl:"┤",boxvL:"â•¡",boxVl:"â•¢",boxVL:"â•£",boxvr:"├",boxvR:"â•ž",boxVr:"â•Ÿ",boxVR:"â• ",bprime:"‵",breve:"˘",Breve:"˘",brvbar:"¦",bscr:"ð’·",Bscr:"ℬ",bsemi:"â",bsim:"∽",bsime:"â‹",bsolb:"⧅",bsol:"\\",bsolhsub:"⟈",bull:"•",bullet:"•",bump:"≎",bumpE:"⪮",bumpe:"â‰",Bumpeq:"≎",bumpeq:"â‰",Cacute:"Ć",cacute:"ć",capand:"â©„",capbrcup:"⩉",capcap:"â©‹",cap:"∩",Cap:"â‹’",capcup:"⩇",capdot:"â©€",CapitalDifferentialD:"â……",caps:"∩︀",caret:"â",caron:"ˇ",Cayleys:"â„­",ccaps:"â©",Ccaron:"ÄŒ",ccaron:"Ä",Ccedil:"Ç",ccedil:"ç",Ccirc:"Ĉ",ccirc:"ĉ",Cconint:"∰",ccups:"â©Œ",ccupssm:"â©",Cdot:"ÄŠ",cdot:"Ä‹",cedil:"¸",Cedilla:"¸",cemptyv:"⦲",cent:"¢",centerdot:"·",CenterDot:"·",cfr:"ð” ",Cfr:"â„­",CHcy:"Ч",chcy:"ч",check:"✓",checkmark:"✓",Chi:"Χ",chi:"χ",circ:"ˆ",circeq:"≗",circlearrowleft:"↺",circlearrowright:"↻",circledast:"⊛",circledcirc:"⊚",circleddash:"âŠ",CircleDot:"⊙",circledR:"®",circledS:"Ⓢ",CircleMinus:"⊖",CirclePlus:"⊕",CircleTimes:"⊗",cir:"â—‹",cirE:"⧃",cire:"≗",cirfnint:"â¨",cirmid:"⫯",cirscir:"⧂",ClockwiseContourIntegral:"∲",CloseCurlyDoubleQuote:"â€",CloseCurlyQuote:"’",clubs:"♣",clubsuit:"♣",colon:":",Colon:"∷",Colone:"â©´",colone:"≔",coloneq:"≔",comma:",",commat:"@",comp:"âˆ",compfn:"∘",complement:"âˆ",complexes:"â„‚",cong:"≅",congdot:"â©­",Congruent:"≡",conint:"∮",Conint:"∯",ContourIntegral:"∮",copf:"ð•”",Copf:"â„‚",coprod:"âˆ",Coproduct:"âˆ",copy:"©",COPY:"©",copysr:"â„—",CounterClockwiseContourIntegral:"∳",crarr:"↵",cross:"✗",Cross:"⨯",Cscr:"ð’ž",cscr:"ð’¸",csub:"â«",csube:"â«‘",csup:"â«",csupe:"â«’",ctdot:"⋯",cudarrl:"⤸",cudarrr:"⤵",cuepr:"â‹ž",cuesc:"â‹Ÿ",cularr:"↶",cularrp:"⤽",cupbrcap:"⩈",cupcap:"⩆",CupCap:"â‰",cup:"∪",Cup:"â‹“",cupcup:"â©Š",cupdot:"âŠ",cupor:"â©…",cups:"∪︀",curarr:"↷",curarrm:"⤼",curlyeqprec:"â‹ž",curlyeqsucc:"â‹Ÿ",curlyvee:"â‹Ž",curlywedge:"â‹",curren:"¤",curvearrowleft:"↶",curvearrowright:"↷",cuvee:"â‹Ž",cuwed:"â‹",cwconint:"∲",cwint:"∱",cylcty:"⌭",dagger:"†",Dagger:"‡",daleth:"ℸ",darr:"↓",Darr:"↡",dArr:"⇓",dash:"â€",Dashv:"⫤",dashv:"⊣",dbkarow:"â¤",dblac:"Ë",Dcaron:"ÄŽ",dcaron:"Ä",Dcy:"Д",dcy:"д",ddagger:"‡",ddarr:"⇊",DD:"â……",dd:"â…†",DDotrahd:"⤑",ddotseq:"â©·",deg:"°",Del:"∇",Delta:"Δ",delta:"δ",demptyv:"⦱",dfisht:"⥿",Dfr:"ð”‡",dfr:"ð”¡",dHar:"⥥",dharl:"⇃",dharr:"⇂",DiacriticalAcute:"´",DiacriticalDot:"Ë™",DiacriticalDoubleAcute:"Ë",DiacriticalGrave:"`",DiacriticalTilde:"Ëœ",diam:"â‹„",diamond:"â‹„",Diamond:"â‹„",diamondsuit:"♦",diams:"♦",die:"¨",DifferentialD:"â…†",digamma:"Ï",disin:"⋲",div:"÷",divide:"÷",divideontimes:"⋇",divonx:"⋇",DJcy:"Ђ",djcy:"Ñ’",dlcorn:"⌞",dlcrop:"âŒ",dollar:"$",Dopf:"ð”»",dopf:"ð••",Dot:"¨",dot:"Ë™",DotDot:"⃜",doteq:"â‰",doteqdot:"≑",DotEqual:"â‰",dotminus:"∸",dotplus:"∔",dotsquare:"⊡",doublebarwedge:"⌆",DoubleContourIntegral:"∯",DoubleDot:"¨",DoubleDownArrow:"⇓",DoubleLeftArrow:"â‡",DoubleLeftRightArrow:"⇔",DoubleLeftTee:"⫤",DoubleLongLeftArrow:"⟸",DoubleLongLeftRightArrow:"⟺",DoubleLongRightArrow:"⟹",DoubleRightArrow:"⇒",DoubleRightTee:"⊨",DoubleUpArrow:"⇑",DoubleUpDownArrow:"⇕",DoubleVerticalBar:"∥",DownArrowBar:"⤓",downarrow:"↓",DownArrow:"↓",Downarrow:"⇓",DownArrowUpArrow:"⇵",DownBreve:"Ì‘",downdownarrows:"⇊",downharpoonleft:"⇃",downharpoonright:"⇂",DownLeftRightVector:"â¥",DownLeftTeeVector:"⥞",DownLeftVectorBar:"⥖",DownLeftVector:"↽",DownRightTeeVector:"⥟",DownRightVectorBar:"⥗",DownRightVector:"â‡",DownTeeArrow:"↧",DownTee:"⊤",drbkarow:"â¤",drcorn:"⌟",drcrop:"⌌",Dscr:"ð’Ÿ",dscr:"ð’¹",DScy:"Ð…",dscy:"Ñ•",dsol:"⧶",Dstrok:"Ä",dstrok:"Ä‘",dtdot:"⋱",dtri:"â–¿",dtrif:"â–¾",duarr:"⇵",duhar:"⥯",dwangle:"⦦",DZcy:"Ð",dzcy:"ÑŸ",dzigrarr:"⟿",Eacute:"É",eacute:"é",easter:"â©®",Ecaron:"Äš",ecaron:"Ä›",Ecirc:"Ê",ecirc:"ê",ecir:"≖",ecolon:"≕",Ecy:"Э",ecy:"Ñ",eDDot:"â©·",Edot:"Ä–",edot:"Ä—",eDot:"≑",ee:"â…‡",efDot:"≒",Efr:"ð”ˆ",efr:"ð”¢",eg:"⪚",Egrave:"È",egrave:"è",egs:"⪖",egsdot:"⪘",el:"⪙",Element:"∈",elinters:"â§",ell:"â„“",els:"⪕",elsdot:"⪗",Emacr:"Ä’",emacr:"Ä“",empty:"∅",emptyset:"∅",EmptySmallSquare:"â—»",emptyv:"∅",EmptyVerySmallSquare:"â–«",emsp13:" ",emsp14:" ",emsp:" ",ENG:"ÅŠ",eng:"Å‹",ensp:" ",Eogon:"Ę",eogon:"Ä™",Eopf:"ð”¼",eopf:"ð•–",epar:"â‹•",eparsl:"⧣",eplus:"⩱",epsi:"ε",Epsilon:"Ε",epsilon:"ε",epsiv:"ϵ",eqcirc:"≖",eqcolon:"≕",eqsim:"≂",eqslantgtr:"⪖",eqslantless:"⪕",Equal:"⩵",equals:"=",EqualTilde:"≂",equest:"≟",Equilibrium:"⇌",equiv:"≡",equivDD:"⩸",eqvparsl:"⧥",erarr:"⥱",erDot:"≓",escr:"ℯ",Escr:"â„°",esdot:"â‰",Esim:"⩳",esim:"≂",Eta:"Η",eta:"η",ETH:"Ã",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",excl:"!",exist:"∃",Exists:"∃",expectation:"â„°",exponentiale:"â…‡",ExponentialE:"â…‡",fallingdotseq:"≒",Fcy:"Ф",fcy:"Ñ„",female:"♀",ffilig:"ffi",fflig:"ff",ffllig:"ffl",Ffr:"ð”‰",ffr:"ð”£",filig:"ï¬",FilledSmallSquare:"â—¼",FilledVerySmallSquare:"â–ª",fjlig:"fj",flat:"â™­",fllig:"fl",fltns:"â–±",fnof:"Æ’",Fopf:"ð”½",fopf:"ð•—",forall:"∀",ForAll:"∀",fork:"â‹”",forkv:"â«™",Fouriertrf:"ℱ",fpartint:"â¨",frac12:"½",frac13:"â…“",frac14:"¼",frac15:"â…•",frac16:"â…™",frac18:"â…›",frac23:"â…”",frac25:"â…–",frac34:"¾",frac35:"â…—",frac38:"â…œ",frac45:"â…˜",frac56:"â…š",frac58:"â…",frac78:"â…ž",frasl:"â„",frown:"⌢",fscr:"ð’»",Fscr:"ℱ",gacute:"ǵ",Gamma:"Γ",gamma:"γ",Gammad:"Ïœ",gammad:"Ï",gap:"⪆",Gbreve:"Äž",gbreve:"ÄŸ",Gcedil:"Ä¢",Gcirc:"Äœ",gcirc:"Ä",Gcy:"Г",gcy:"г",Gdot:"Ä ",gdot:"Ä¡",ge:"≥",gE:"≧",gEl:"⪌",gel:"â‹›",geq:"≥",geqq:"≧",geqslant:"⩾",gescc:"⪩",ges:"⩾",gesdot:"⪀",gesdoto:"⪂",gesdotol:"⪄",gesl:"⋛︀",gesles:"⪔",Gfr:"ð”Š",gfr:"ð”¤",gg:"≫",Gg:"â‹™",ggg:"â‹™",gimel:"â„·",GJcy:"Ѓ",gjcy:"Ñ“",gla:"⪥",gl:"≷",glE:"⪒",glj:"⪤",gnap:"⪊",gnapprox:"⪊",gne:"⪈",gnE:"≩",gneq:"⪈",gneqq:"≩",gnsim:"⋧",Gopf:"ð”¾",gopf:"ð•˜",grave:"`",GreaterEqual:"≥",GreaterEqualLess:"â‹›",GreaterFullEqual:"≧",GreaterGreater:"⪢",GreaterLess:"≷",GreaterSlantEqual:"⩾",GreaterTilde:"≳",Gscr:"ð’¢",gscr:"â„Š",gsim:"≳",gsime:"⪎",gsiml:"âª",gtcc:"⪧",gtcir:"⩺",gt:">",GT:">",Gt:"≫",gtdot:"â‹—",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"â‹—",gtreqless:"â‹›",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"â„‹",HARDcy:"Ъ",hardcy:"ÑŠ",harrcir:"⥈",harr:"↔",hArr:"⇔",harrw:"↭",Hat:"^",hbar:"â„",Hcirc:"Ĥ",hcirc:"Ä¥",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",hfr:"ð”¥",Hfr:"â„Œ",HilbertSpace:"â„‹",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",hopf:"ð•™",Hopf:"â„",horbar:"―",HorizontalLine:"─",hscr:"ð’½",Hscr:"â„‹",hslash:"â„",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"â‰",hybull:"âƒ",hyphen:"â€",Iacute:"Ã",iacute:"í",ic:"â£",Icirc:"ÃŽ",icirc:"î",Icy:"И",icy:"и",Idot:"Ä°",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",ifr:"ð”¦",Ifr:"â„‘",Igrave:"ÃŒ",igrave:"ì",ii:"â…ˆ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"â„©",IJlig:"IJ",ijlig:"ij",Imacr:"Ī",imacr:"Ä«",image:"â„‘",ImaginaryI:"â…ˆ",imagline:"â„",imagpart:"â„‘",imath:"ı",Im:"â„‘",imof:"⊷",imped:"Ƶ",Implies:"⇒",incare:"â„…",in:"∈",infin:"∞",infintie:"â§",inodot:"ı",intcal:"⊺",int:"∫",Int:"∬",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"â‹‚",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"â£",InvisibleTimes:"â¢",IOcy:"Ð",iocy:"Ñ‘",Iogon:"Ä®",iogon:"į",Iopf:"ð•€",iopf:"ð•š",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",iscr:"ð’¾",Iscr:"â„",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"â‹´",isinsv:"⋳",isinv:"∈",it:"â¢",Itilde:"Ĩ",itilde:"Ä©",Iukcy:"І",iukcy:"Ñ–",Iuml:"Ã",iuml:"ï",Jcirc:"Ä´",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"ð”",jfr:"ð”§",jmath:"È·",Jopf:"ð•",jopf:"ð•›",Jscr:"ð’¥",jscr:"ð’¿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"Ñ”",Kappa:"Κ",kappa:"κ",kappav:"Ï°",Kcedil:"Ķ",kcedil:"Ä·",Kcy:"К",kcy:"к",Kfr:"ð”Ž",kfr:"ð”¨",kgreen:"ĸ",KHcy:"Ð¥",khcy:"Ñ…",KJcy:"ÐŒ",kjcy:"Ñœ",Kopf:"ð•‚",kopf:"ð•œ",Kscr:"ð’¦",kscr:"ð“€",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"â„’",Lambda:"Λ",lambda:"λ",lang:"⟨",Lang:"⟪",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"â„’",laquo:"«",larrb:"⇤",larrbfs:"⤟",larr:"â†",Larr:"↞",lArr:"â‡",larrfs:"â¤",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",latail:"⤙",lAtail:"⤛",lat:"⪫",late:"⪭",lates:"⪭︀",lbarr:"⤌",lBarr:"⤎",lbbrk:"â²",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"â¦",lbrkslu:"â¦",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ä»",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",le:"≤",lE:"≦",LeftAngleBracket:"⟨",LeftArrowBar:"⇤",leftarrow:"â†",LeftArrow:"â†",Leftarrow:"â‡",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVectorBar:"⥙",LeftDownVector:"⇃",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",leftrightarrow:"↔",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTeeArrow:"↤",LeftTee:"⊣",LeftTeeVector:"⥚",leftthreetimes:"â‹‹",LeftTriangleBar:"â§",LeftTriangle:"⊲",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVectorBar:"⥘",LeftUpVector:"↿",LeftVectorBar:"⥒",LeftVector:"↼",lEg:"⪋",leg:"â‹š",leq:"≤",leqq:"≦",leqslant:"⩽",lescc:"⪨",les:"⩽",lesdot:"â©¿",lesdoto:"âª",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"â‹–",lesseqgtr:"â‹š",lesseqqgtr:"⪋",LessEqualGreater:"â‹š",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"ð”",lfr:"ð”©",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"â–„",LJcy:"Љ",ljcy:"Ñ™",llarr:"⇇",ll:"≪",Ll:"⋘",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"â—º",Lmidot:"Ä¿",lmidot:"Å€",lmoustache:"⎰",lmoust:"⎰",lnap:"⪉",lnapprox:"⪉",lne:"⪇",lnE:"≨",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",longleftarrow:"⟵",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftrightarrow:"⟷",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longmapsto:"⟼",longrightarrow:"⟶",LongRightArrow:"⟶",Longrightarrow:"⟹",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"ð•ƒ",lopf:"ð•",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"â—Š",lozenge:"â—Š",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"‎",lrtri:"⊿",lsaquo:"‹",lscr:"ð“",Lscr:"â„’",lsh:"↰",Lsh:"↰",lsim:"≲",lsime:"âª",lsimg:"âª",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Å",lstrok:"Å‚",ltcc:"⪦",ltcir:"⩹",lt:"<",LT:"<",Lt:"≪",ltdot:"â‹–",lthree:"â‹‹",ltimes:"⋉",ltlarr:"⥶",ltquest:"â©»",ltri:"â—ƒ",ltrie:"⊴",ltrif:"â—‚",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"â–®",mcomma:"⨩",Mcy:"Ðœ",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:"âŸ",Mellintrf:"ℳ",Mfr:"ð”",mfr:"ð”ª",mho:"℧",micro:"µ",midast:"*",midcir:"â«°",mid:"∣",middot:"·",minusb:"⊟",minus:"−",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"â«›",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"ð•„",mopf:"ð•ž",mp:"∓",mscr:"ð“‚",Mscr:"ℳ",mstpos:"∾",Mu:"Îœ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"Å„",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natural:"â™®",naturals:"â„•",natur:"â™®",nbsp:" ",nbump:"≎̸",nbumpe:"â‰Ì¸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Å…",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"â©‚",Ncy:"Ð",ncy:"н",ndash:"–",nearhk:"⤤",nearr:"↗",neArr:"⇗",nearrow:"↗",ne:"≠",nedot:"â‰Ì¸",NegativeMediumSpace:"​",NegativeThickSpace:"​",NegativeThinSpace:"​",NegativeVeryThinSpace:"​",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"ð”‘",nfr:"ð”«",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nharr:"↮",nhArr:"⇎",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"Ñš",nlarr:"↚",nlArr:"â‡",nldr:"‥",nlE:"≦̸",nle:"≰",nleftarrow:"↚",nLeftarrow:"â‡",nleftrightarrow:"↮",nLeftrightarrow:"⇎",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"â ",NonBreakingSpace:" ",nopf:"ð•Ÿ",Nopf:"â„•",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"â‰Ì¸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"â‹·",notinvc:"⋶",NotLeftTriangleBar:"â§Ì¸",NotLeftTriangle:"⋪",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"â‹ ",NotReverseElement:"∌",NotRightTriangleBar:"â§Ì¸",NotRightTriangle:"â‹«",NotRightTriangleEqual:"â‹­",NotSquareSubset:"âŠÌ¸",NotSquareSubsetEqual:"â‹¢",NotSquareSuperset:"âŠÌ¸",NotSquareSupersetEqual:"â‹£",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"âŠ",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"â‹¡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"â‰",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",nparallel:"∦",npar:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"â‹ ",nprec:"⊀",npreceq:"⪯̸",npre:"⪯̸",nrarrc:"⤳̸",nrarr:"↛",nrArr:"â‡",nrarrw:"â†Ì¸",nrightarrow:"↛",nRightarrow:"â‡",nrtri:"â‹«",nrtrie:"â‹­",nsc:"âŠ",nsccue:"â‹¡",nsce:"⪰̸",Nscr:"ð’©",nscr:"ð“ƒ",nshortmid:"∤",nshortparallel:"∦",nsim:"â‰",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"â‹¢",nsqsupe:"â‹£",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"âŠ",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"â‹«",ntrianglerighteq:"â‹­",Nu:"Î",nu:"ν",num:"#",numero:"â„–",numsp:" ",nvap:"â‰âƒ’",nvdash:"⊬",nvDash:"⊭",nVdash:"⊮",nVDash:"⊯",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwarr:"↖",nwArr:"⇖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",Ocirc:"Ô",ocirc:"ô",ocir:"⊚",Ocy:"О",ocy:"о",odash:"âŠ",Odblac:"Å",odblac:"Å‘",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Å’",oelig:"Å“",ofcir:"⦿",Ofr:"ð”’",ofr:"ð”¬",ogon:"Ë›",Ograve:"Ã’",ograve:"ò",ogt:"â§",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"ÅŒ",omacr:"Å",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"ð•†",oopf:"ð• ",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",orarr:"↻",Or:"â©”",or:"∨",ord:"â©",order:"â„´",orderof:"â„´",ordf:"ª",ordm:"º",origof:"⊶",oror:"â©–",orslope:"â©—",orv:"â©›",oS:"Ⓢ",Oscr:"ð’ª",oscr:"â„´",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",otimesas:"⨶",Otimes:"⨷",otimes:"⊗",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"âž",OverBracket:"⎴",OverParenthesis:"âœ",para:"¶",parallel:"∥",par:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"ð”“",pfr:"ð”­",Phi:"Φ",phi:"φ",phiv:"Ï•",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"Ï€",pitchfork:"â‹”",piv:"Ï–",planck:"â„",planckh:"â„Ž",plankv:"â„",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plus:"+",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"â„Œ",pointint:"⨕",popf:"ð•¡",Popf:"â„™",pound:"£",prap:"⪷",Pr:"⪻",pr:"≺",prcue:"≼",precapprox:"⪷",prec:"≺",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",pre:"⪯",prE:"⪳",precsim:"≾",prime:"′",Prime:"″",primes:"â„™",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"âˆ",Product:"âˆ",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"âˆ",Proportional:"âˆ",Proportion:"∷",propto:"âˆ",prsim:"≾",prurel:"⊰",Pscr:"ð’«",pscr:"ð“…",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"ð””",qfr:"ð”®",qint:"⨌",qopf:"ð•¢",Qopf:"â„š",qprime:"â—",Qscr:"ð’¬",qscr:"ð“†",quaternions:"â„",quatint:"⨖",quest:"?",questeq:"≟",quot:'"',QUOT:'"',rAarr:"⇛",race:"∽̱",Racute:"Å”",racute:"Å•",radic:"√",raemptyv:"⦳",rang:"⟩",Rang:"⟫",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarr:"→",Rarr:"↠",rArr:"⇒",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"â†",ratail:"⤚",rAtail:"⤜",ratio:"∶",rationals:"â„š",rbarr:"â¤",rBarr:"â¤",RBarr:"â¤",rbbrk:"â³",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"â¦",Rcaron:"Ř",rcaron:"Å™",Rcedil:"Å–",rcedil:"Å—",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"Ñ€",rdca:"⤷",rdldhar:"⥩",rdquo:"â€",rdquor:"â€",rdsh:"↳",real:"â„œ",realine:"â„›",realpart:"â„œ",reals:"â„",Re:"â„œ",rect:"â–­",reg:"®",REG:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",rfr:"ð”¯",Rfr:"â„œ",rHar:"⥤",rhard:"â‡",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"Ï",rhov:"ϱ",RightAngleBracket:"⟩",RightArrowBar:"⇥",rightarrow:"→",RightArrow:"→",Rightarrow:"⇒",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"â¥",RightDownVectorBar:"⥕",RightDownVector:"⇂",RightFloor:"⌋",rightharpoondown:"â‡",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"â†",RightTeeArrow:"↦",RightTee:"⊢",RightTeeVector:"⥛",rightthreetimes:"â‹Œ",RightTriangleBar:"â§",RightTriangle:"⊳",RightTriangleEqual:"⊵",RightUpDownVector:"â¥",RightUpTeeVector:"⥜",RightUpVectorBar:"⥔",RightUpVector:"↾",RightVectorBar:"⥓",RightVector:"⇀",ring:"Ëš",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"â€",rmoustache:"⎱",rmoust:"⎱",rnmid:"â«®",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",ropf:"ð•£",Ropf:"â„",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",rscr:"ð“‡",Rscr:"â„›",rsh:"↱",Rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"â‹Œ",rtimes:"â‹Š",rtri:"â–¹",rtrie:"⊵",rtrif:"â–¸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"â„ž",Sacute:"Åš",sacute:"Å›",sbquo:"‚",scap:"⪸",Scaron:"Å ",scaron:"Å¡",Sc:"⪼",sc:"≻",sccue:"≽",sce:"⪰",scE:"⪴",Scedil:"Åž",scedil:"ÅŸ",Scirc:"Åœ",scirc:"Å",scnap:"⪺",scnE:"⪶",scnsim:"â‹©",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"Ñ",sdotb:"⊡",sdot:"â‹…",sdote:"⩦",searhk:"⤥",searr:"↘",seArr:"⇘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"ð”–",sfr:"ð”°",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"â†",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"­",Sigma:"Σ",sigma:"σ",sigmaf:"Ï‚",sigmav:"Ï‚",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"âª",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"â†",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ÑŒ",solbar:"⌿",solb:"⧄",sol:"/",Sopf:"ð•Š",sopf:"ð•¤",spades:"â™ ",spadesuit:"â™ ",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"âŠ",sqsube:"⊑",sqsubset:"âŠ",sqsubseteq:"⊑",sqsup:"âŠ",sqsupe:"⊒",sqsupset:"âŠ",sqsupseteq:"⊒",square:"â–¡",Square:"â–¡",SquareIntersection:"⊓",SquareSubset:"âŠ",SquareSubsetEqual:"⊑",SquareSuperset:"âŠ",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"â–ª",squ:"â–¡",squf:"â–ª",srarr:"→",Sscr:"ð’®",sscr:"ð“ˆ",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"Ï•",strns:"¯",sub:"⊂",Sub:"â‹",subdot:"⪽",subE:"â«…",sube:"⊆",subedot:"⫃",submult:"â«",subnE:"â«‹",subne:"⊊",subplus:"⪿",subrarr:"⥹",subset:"⊂",Subset:"â‹",subseteq:"⊆",subseteqq:"â«…",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"â«‹",subsim:"⫇",subsub:"â«•",subsup:"â«“",succapprox:"⪸",succ:"≻",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"â‹©",succsim:"≿",SuchThat:"∋",sum:"∑",Sum:"∑",sung:"♪",sup1:"¹",sup2:"²",sup3:"³",sup:"⊃",Sup:"â‹‘",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"â«„",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"â«—",suplarr:"⥻",supmult:"â«‚",supnE:"â«Œ",supne:"⊋",supplus:"â«€",supset:"⊃",Supset:"â‹‘",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"â«Œ",supsim:"⫈",supsub:"â«”",supsup:"â«–",swarhk:"⤦",swarr:"↙",swArr:"⇙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:"\t",target:"⌖",Tau:"Τ",tau:"Ï„",tbrk:"⎴",Tcaron:"Ť",tcaron:"Å¥",Tcedil:"Å¢",tcedil:"Å£",Tcy:"Т",tcy:"Ñ‚",tdot:"⃛",telrec:"⌕",Tfr:"ð”—",tfr:"ð”±",there4:"∴",therefore:"∴",Therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"Ï‘",thetav:"Ï‘",thickapprox:"≈",thicksim:"∼",ThickSpace:"âŸâ€Š",ThinSpace:" ",thinsp:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",tilde:"Ëœ",Tilde:"∼",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",timesbar:"⨱",timesb:"⊠",times:"×",timesd:"⨰",tint:"∭",toea:"⤨",topbot:"⌶",topcir:"⫱",top:"⊤",Topf:"ð•‹",topf:"ð•¥",topfork:"â«š",tosa:"⤩",tprime:"‴",trade:"â„¢",TRADE:"â„¢",triangle:"â–µ",triangledown:"â–¿",triangleleft:"â—ƒ",trianglelefteq:"⊴",triangleq:"≜",triangleright:"â–¹",trianglerighteq:"⊵",tridot:"â—¬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"â§",tritime:"⨻",trpezium:"â¢",Tscr:"ð’¯",tscr:"ð“‰",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"Ñ›",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",uarr:"↑",Uarr:"↟",uArr:"⇑",Uarrocir:"⥉",Ubrcy:"ÐŽ",ubrcy:"Ñž",Ubreve:"Ŭ",ubreve:"Å­",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Å°",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"ð”˜",ufr:"ð”²",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"â–€",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"âŒ",ultri:"â—¸",Umacr:"Ū",umacr:"Å«",uml:"¨",UnderBar:"_",UnderBrace:"âŸ",UnderBracket:"⎵",UnderParenthesis:"â",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"ð•Œ",uopf:"ð•¦",UpArrowBar:"⤒",uparrow:"↑",UpArrow:"↑",Uparrow:"⇑",UpArrowDownArrow:"⇅",updownarrow:"↕",UpDownArrow:"↕",Updownarrow:"⇕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",upsi:"Ï…",Upsi:"Ï’",upsih:"Ï’",Upsilon:"Î¥",upsilon:"Ï…",UpTeeArrow:"↥",UpTee:"⊥",upuparrows:"⇈",urcorn:"âŒ",urcorner:"âŒ",urcrop:"⌎",Uring:"Å®",uring:"ů",urtri:"â—¹",Uscr:"ð’°",uscr:"ð“Š",utdot:"â‹°",Utilde:"Ũ",utilde:"Å©",utri:"â–µ",utrif:"â–´",uuarr:"⇈",Uuml:"Ãœ",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"Ï°",varnothing:"∅",varphi:"Ï•",varpi:"Ï–",varpropto:"âˆ",varr:"↕",vArr:"⇕",varrho:"ϱ",varsigma:"Ï‚",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"Ï‘",vartriangleleft:"⊲",vartriangleright:"⊳",vBar:"⫨",Vbar:"â««",vBarv:"â«©",Vcy:"Ð’",vcy:"в",vdash:"⊢",vDash:"⊨",Vdash:"⊩",VDash:"⊫",Vdashl:"⫦",veebar:"⊻",vee:"∨",Vee:"â‹",veeeq:"≚",vellip:"â‹®",verbar:"|",Verbar:"‖",vert:"|",Vert:"‖",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"â˜",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"ð”™",vfr:"ð”³",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"ð•",vopf:"ð•§",vprop:"âˆ",vrtri:"⊳",Vscr:"ð’±",vscr:"ð“‹",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Å´",wcirc:"ŵ",wedbar:"â©Ÿ",wedge:"∧",Wedge:"â‹€",wedgeq:"≙",weierp:"℘",Wfr:"ð”š",wfr:"ð”´",Wopf:"ð•Ž",wopf:"ð•¨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"ð’²",wscr:"ð“Œ",xcap:"â‹‚",xcirc:"â—¯",xcup:"⋃",xdtri:"â–½",Xfr:"ð”›",xfr:"ð”µ",xharr:"⟷",xhArr:"⟺",Xi:"Ξ",xi:"ξ",xlarr:"⟵",xlArr:"⟸",xmap:"⟼",xnis:"â‹»",xodot:"⨀",Xopf:"ð•",xopf:"ð•©",xoplus:"â¨",xotime:"⨂",xrarr:"⟶",xrArr:"⟹",Xscr:"ð’³",xscr:"ð“",xsqcup:"⨆",xuplus:"⨄",xutri:"â–³",xvee:"â‹",xwedge:"â‹€",Yacute:"Ã",yacute:"ý",YAcy:"Я",yacy:"Ñ",Ycirc:"Ŷ",ycirc:"Å·",Ycy:"Ы",ycy:"Ñ‹",yen:"Â¥",Yfr:"ð”œ",yfr:"ð”¶",YIcy:"Ї",yicy:"Ñ—",Yopf:"ð•",yopf:"ð•ª",Yscr:"ð’´",yscr:"ð“Ž",YUcy:"Ю",yucy:"ÑŽ",yuml:"ÿ",Yuml:"Ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Å»",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"​",Zeta:"Ζ",zeta:"ζ",zfr:"ð”·",Zfr:"ℨ",ZHcy:"Ж",zhcy:"ж",zigrarr:"â‡",zopf:"ð•«",Zopf:"ℤ",Zscr:"ð’µ",zscr:"ð“",zwj:"â€",zwnj:"‌"},Qh=/[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4E\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/,Xh={},Yh={};function Jh(e){var t,n,r=Yh[e];if(r)return r;for(r=Yh[e]=[],t=0;t<128;t++)n=String.fromCharCode(t),/^[0-9a-z]$/i.test(n)?r.push(n):r.push("%"+("0"+t.toString(16).toUpperCase()).slice(-2));for(t=0;t=55296&&o<=57343){if(o>=55296&&o<=56319&&r+1=56320&&a<=57343){l+=encodeURIComponent(e[r]+e[r+1]),r++;continue}l+="%EF%BF%BD"}else l+=encodeURIComponent(e[r]);return l}g(Jh,"getEncodeCache"),g(Zh,"encode$1"),Zh.defaultChars=";/?:@&=+$,-_.!~*'()#",Zh.componentChars="-_.!~*'()";var em=Zh,tm={};function nm(e){var t,n,r=tm[e];if(r)return r;for(r=tm[e]=[],t=0;t<128;t++)n=String.fromCharCode(t),r.push(n);for(t=0;t=55296&&l<=57343?"���":String.fromCharCode(l),t+=6):240==(248&i)&&t+91114111?u+="����":(l-=65536,u+=String.fromCharCode(55296+(l>>10),56320+(1023&l))),t+=9):u+="�";return u}))}g(nm,"getDecodeCache"),g(rm,"decode$1"),rm.defaultChars=";/?:@&=+$,#",rm.componentChars="";var im=rm,om=g((function(e){var t="";return t+=e.protocol||"",t+=e.slashes?"//":"",t+=e.auth?e.auth+"@":"",e.hostname&&-1!==e.hostname.indexOf(":")?t+="["+e.hostname+"]":t+=e.hostname||"",t+=e.port?":"+e.port:"",t+=e.pathname||"",(t+=e.search||"")+(e.hash||"")}),"format");function am(){this.protocol=null,this.slashes=null,this.auth=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.pathname=null}g(am,"Url");var sm=/^([a-z0-9.+-]+:)/i,lm=/:[0-9]*$/,um=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,cm=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),dm=["'"].concat(cm),fm=["%","/","?",";","#"].concat(dm),pm=["/","?","#"],hm=/^[+a-z0-9A-Z_-]{0,63}$/,mm=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,gm={javascript:!0,"javascript:":!0},vm={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0};function ym(e,t){if(e&&e instanceof am)return e;var n=new am;return n.parse(e,t),n}g(ym,"urlParse"),am.prototype.parse=function(e,t){var n,r,i,o,a,s=e;if(s=s.trim(),!t&&1===e.split("#").length){var l=um.exec(s);if(l)return this.pathname=l[1],l[2]&&(this.search=l[2]),this}var u=sm.exec(s);if(u&&(i=(u=u[0]).toLowerCase(),this.protocol=u,s=s.substr(u.length)),(t||u||s.match(/^\/\/[^@\/]+@[^@\/]+/))&&(!(a="//"===s.substr(0,2))||u&&gm[u]||(s=s.substr(2),this.slashes=!0)),!gm[u]&&(a||u&&!vm[u])){var c,d,f=-1;for(n=0;n127?v+="x":v+=g[y];if(!v.match(hm)){var E=m.slice(0,n),T=m.slice(n+1),w=g.match(mm);w&&(E.push(w[1]),T.unshift(w[2])),T.length&&(s=T.join(".")+s),this.hostname=E.join(".");break}}}}this.hostname.length>255&&(this.hostname=""),h&&(this.hostname=this.hostname.substr(1,this.hostname.length-2))}var C=s.indexOf("#");-1!==C&&(this.hash=s.substr(C),s=s.slice(0,C));var S=s.indexOf("?");return-1!==S&&(this.search=s.substr(S),s=s.slice(0,S)),s&&(this.pathname=s),vm[i]&&this.hostname&&!this.pathname&&(this.pathname=""),this},am.prototype.parseHost=function(e){var t=lm.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)};var bm=ym;Xh.encode=em,Xh.decode=im,Xh.format=om,Xh.parse=bm;var Em={},Tm=/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,wm=/[\0-\x1F\x7F-\x9F]/,Cm=/[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;Em.Any=Tm,Em.Cc=wm,Em.Cf=/[\xAD\u0600-\u0605\u061C\u06DD\u070F\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/,Em.P=Qh,Em.Z=Cm,function(e){function t(e){return Object.prototype.toString.call(e)}function n(e){return"[object String]"===t(e)}g(t,"_class"),g(n,"isString");var r=Object.prototype.hasOwnProperty;function i(e,t){return r.call(e,t)}function o(e){return Array.prototype.slice.call(arguments,1).forEach((function(t){if(t){if("object"!=typeof t)throw new TypeError(t+"must be object");Object.keys(t).forEach((function(n){e[n]=t[n]}))}})),e}function a(e,t,n){return[].concat(e.slice(0,t),n,e.slice(t+1))}function s(e){return!(e>=55296&&e<=57343||e>=64976&&e<=65007||65535==(65535&e)||65534==(65535&e)||e>=0&&e<=8||11===e||e>=14&&e<=31||e>=127&&e<=159||e>1114111)}function l(e){if(e>65535){var t=55296+((e-=65536)>>10),n=56320+(1023&e);return String.fromCharCode(t,n)}return String.fromCharCode(e)}g(i,"has"),g(o,"assign"),g(a,"arrayReplaceAt"),g(s,"isValidEntityCode"),g(l,"fromCodePoint");var u=/\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g,c=new RegExp(u.source+"|"+/&([a-z#][a-z0-9]{1,31});/gi.source,"gi"),d=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i,f=Kh;function p(e,t){var n=0;return i(f,t)?f[t]:35===t.charCodeAt(0)&&d.test(t)&&s(n="x"===t[1].toLowerCase()?parseInt(t.slice(2),16):parseInt(t.slice(1),10))?l(n):e}function h(e){return e.indexOf("\\")<0?e:e.replace(u,"$1")}function m(e){return e.indexOf("\\")<0&&e.indexOf("&")<0?e:e.replace(c,(function(e,t,n){return t||p(e,n)}))}g(p,"replaceEntityPattern"),g(h,"unescapeMd"),g(m,"unescapeAll");var v=/[&<>"]/,y=/[&<>"]/g,b={"&":"&","<":"<",">":">",'"':"""};function E(e){return b[e]}function T(e){return v.test(e)?e.replace(y,E):e}g(E,"replaceUnsafeChar"),g(T,"escapeHtml");var w=/[.?*+^$[\]\\(){}|-]/g;function C(e){return e.replace(w,"\\$&")}function S(e){switch(e){case 9:case 32:return!0}return!1}function x(e){if(e>=8192&&e<=8202)return!0;switch(e){case 9:case 10:case 11:case 12:case 13:case 32:case 160:case 5760:case 8239:case 8287:case 12288:return!0}return!1}g(C,"escapeRE"),g(S,"isSpace"),g(x,"isWhiteSpace");var k=Qh;function N(e){return k.test(e)}function _(e){switch(e){case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 58:case 59:case 60:case 61:case 62:case 63:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 124:case 125:case 126:return!0;default:return!1}}function O(e){return e=e.trim().replace(/\s+/g," "),"á¹¾"==="ẞ".toLowerCase()&&(e=e.replace(/ẞ/g,"ß")),e.toLowerCase().toUpperCase()}g(N,"isPunctChar"),g(_,"isMdAsciiPunct"),g(O,"normalizeReference"),e.lib={},e.lib.mdurl=Xh,e.lib.ucmicro=Em,e.assign=o,e.isString=n,e.has=i,e.unescapeMd=h,e.unescapeAll=m,e.isValidEntityCode=s,e.fromCodePoint=l,e.escapeHtml=T,e.arrayReplaceAt=a,e.isSpace=S,e.isWhiteSpace=x,e.isMdAsciiPunct=_,e.isPunctChar=N,e.escapeRE=C,e.normalizeReference=O}(Wh);var Sm={},xm=g((function(e,t,n){var r,i,o,a,s=-1,l=e.posMax,u=e.pos;for(e.pos=t+1,r=1;e.pos32)return a;if(41===r){if(0===i)break;i--}t++}return o===t||0!==i||(a.str=km(e.slice(o,t)),a.lines=0,a.pos=t,a.ok=!0),a}),"parseLinkDestination"),_m=Wh.unescapeAll,Om=g((function(e,t,n){var r,i,o=0,a=t,s={ok:!1,pos:0,lines:0,str:""};if(t>=n)return s;if(34!==(i=e.charCodeAt(t))&&39!==i&&40!==i)return s;for(t++,40===i&&(i=41);t"+Lm(e[t].content)+"
"},Am.code_block=function(e,t,n,r,i){var o=e[t];return""+Lm(e[t].content)+"\n"},Am.fence=function(e,t,n,r,i){var o,a,s,l,u,c=e[t],d=c.info?Dm(c.info).trim():"",f="",p="";return d&&(f=(s=d.split(/(\s+)/g))[0],p=s.slice(2).join("")),0===(o=n.highlight&&n.highlight(c.content,f,p)||Lm(c.content)).indexOf(""+o+"\n"):"
"+o+"
\n"},Am.image=function(e,t,n,r,i){var o=e[t];return o.attrs[o.attrIndex("alt")][1]=i.renderInlineAsText(o.children,n,r),i.renderToken(e,t,n)},Am.hardbreak=function(e,t,n){return n.xhtmlOut?"
\n":"
\n"},Am.softbreak=function(e,t,n){return n.breaks?n.xhtmlOut?"
\n":"
\n":"\n"},Am.text=function(e,t){return Lm(e[t].content)},Am.html_block=function(e,t){return e[t].content},Am.html_inline=function(e,t){return e[t].content},g(Mm,"Renderer$1"),Mm.prototype.renderAttrs=g((function(e){var t,n,r;if(!e.attrs)return"";for(r="",t=0,n=e.attrs.length;t\n":">")}),"renderToken"),Mm.prototype.renderInline=function(e,t,n){for(var r,i="",o=this.rules,a=0,s=e.length;a\s]/i.test(e)}function Gm(e){return/^<\/a\s*>/i.test(e)}g(Hm,"isLinkOpen"),g(Gm,"isLinkClose");var zm=g((function(e){var t,n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y=e.tokens;if(e.md.options.linkify)for(n=0,r=y.length;n=0;t--)if("link_close"!==(a=i[t]).type){if("html_inline"===a.type&&(Hm(a.content)&&p>0&&p--,Gm(a.content)&&p++),!(p>0)&&"text"===a.type&&e.md.linkify.test(a.content)){for(u=a.content,v=e.md.linkify.match(u),s=[],f=a.level,d=0,l=0;ld&&((o=new e.Token("text","",0)).content=u.slice(d,c),o.level=f,s.push(o)),(o=new e.Token("link_open","a",1)).attrs=[["href",m]],o.level=f++,o.markup="linkify",o.info="auto",s.push(o),(o=new e.Token("text","",0)).content=g,o.level=f,s.push(o),(o=new e.Token("link_close","a",-1)).level=--f,o.markup="linkify",o.info="auto",s.push(o),d=v[l].lastIndex);d=0;t--)"text"!==(n=e[t]).type||r||(n.content=n.content.replace(Qm,Ym)),"link_open"===n.type&&"auto"===n.info&&r--,"link_close"===n.type&&"auto"===n.info&&r++}function Zm(e){var t,n,r=0;for(t=e.length-1;t>=0;t--)"text"!==(n=e[t]).type||r||Wm.test(n.content)&&(n.content=n.content.replace(/\+-/g,"±").replace(/\.{2,}/g,"…").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---(?=[^-]|$)/gm,"$1—").replace(/(^|\s)--(?=\s|$)/gm,"$1–").replace(/(^|[^-\s])--(?=[^-\s]|$)/gm,"$1–")),"link_open"===n.type&&"auto"===n.info&&r--,"link_close"===n.type&&"auto"===n.info&&r++}g(Ym,"replaceFn"),g(Jm,"replace_scoped"),g(Zm,"replace_rare");var eg=g((function(e){var t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)"inline"===e.tokens[t].type&&(Km.test(e.tokens[t].content)&&Jm(e.tokens[t].children),Wm.test(e.tokens[t].content)&&Zm(e.tokens[t].children))}),"replace"),tg=Wh.isWhiteSpace,ng=Wh.isPunctChar,rg=Wh.isMdAsciiPunct,ig=/['"]/,og=/['"]/g,ag="’";function sg(e,t,n){return e.substr(0,t)+n+e.substr(t+1)}function lg(e,t){var n,r,i,o,a,s,l,u,c,d,f,p,h,m,g,v,y,b,E,T,w;for(E=[],n=0;n=0&&!(E[y].level<=l);y--);if(E.length=y+1,"text"===r.type){a=0,s=(i=r.content).length;e:for(;a=0)c=i.charCodeAt(o.index-1);else for(y=n-1;y>=0&&"softbreak"!==e[y].type&&"hardbreak"!==e[y].type;y--)if(e[y].content){c=e[y].content.charCodeAt(e[y].content.length-1);break}if(d=32,a=48&&c<=57&&(v=g=!1),g&&v&&(g=f,v=p),g||v){if(v)for(y=E.length-1;y>=0&&(u=E[y],!(E[y].level=0;t--)"inline"===e.tokens[t].type&&ig.test(e.tokens[t].content)&&lg(e.tokens[t].children,e)}),"smartquotes");function cg(e,t,n){this.type=e,this.tag=t,this.attrs=null,this.map=null,this.nesting=n,this.level=0,this.children=null,this.content="",this.markup="",this.info="",this.meta=null,this.block=!1,this.hidden=!1}g(cg,"Token$3"),cg.prototype.attrIndex=g((function(e){var t,n,r;if(!this.attrs)return-1;for(n=0,r=(t=this.attrs).length;n=0&&(n=this.attrs[t][1]),n}),"attrGet"),cg.prototype.attrJoin=g((function(e,t){var n=this.attrIndex(e);n<0?this.attrPush([e,t]):this.attrs[n][1]=this.attrs[n][1]+" "+t}),"attrJoin");var dg=cg,fg=dg;function pg(e,t,n){this.src=e,this.env=n,this.tokens=[],this.inlineMode=!1,this.md=t}g(pg,"StateCore"),pg.prototype.Token=fg;var hg=pg,mg=Pm,gg=[["normalize",Um],["block",Bm],["inline",$m],["linkify",zm],["replacements",eg],["smartquotes",ug]];function vg(){this.ruler=new mg;for(var e=0;en)return!1;if(u=t+1,e.sCount[u]=4)return!1;if((a=e.bMarks[u]+e.tShift[u])>=e.eMarks[u])return!1;if(124!==(E=e.src.charCodeAt(a++))&&45!==E&&58!==E)return!1;if(a>=e.eMarks[u])return!1;if(124!==(T=e.src.charCodeAt(a++))&&45!==T&&58!==T&&!bg(T))return!1;if(45===E&&bg(T))return!1;for(;a=4)return!1;if((c=Tg(o)).length&&""===c[0]&&c.shift(),c.length&&""===c[c.length-1]&&c.pop(),0===(d=c.length)||d!==p.length)return!1;if(r)return!0;for(v=e.parentType,e.parentType="table",b=e.md.block.ruler.getRules("blockquote"),(f=e.push("table_open","table",1)).map=m=[t,0],(f=e.push("thead_open","thead",1)).map=[t,t+1],(f=e.push("tr_open","tr",1)).map=[t,t+1],s=0;s=4)break;for((c=Tg(o)).length&&""===c[0]&&c.shift(),c.length&&""===c[c.length-1]&&c.pop(),u===t+2&&((f=e.push("tbody_open","tbody",1)).map=g=[t+2,0]),(f=e.push("tr_open","tr",1)).map=[u,u+1],s=0;s=4))break;i=++r}return e.line=i,(o=e.push("code_block","code",0)).content=e.getLines(t,i,4+e.blkIndent,!1)+"\n",o.map=[t,e.line],!0}),"code"),Sg=g((function(e,t,n,r){var i,o,a,s,l,u,c,d=!1,f=e.bMarks[t]+e.tShift[t],p=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(f+3>p)return!1;if(126!==(i=e.src.charCodeAt(f))&&96!==i)return!1;if(l=f,(o=(f=e.skipChars(f,i))-l)<3)return!1;if(c=e.src.slice(l,f),a=e.src.slice(f,p),96===i&&a.indexOf(String.fromCharCode(i))>=0)return!1;if(r)return!0;for(s=t;!(++s>=n||(f=l=e.bMarks[s]+e.tShift[s])<(p=e.eMarks[s])&&e.sCount[s]=4||(f=e.skipChars(f,i))-l=4)return!1;if(62!==e.src.charCodeAt(x++))return!1;if(r)return!0;for(s=f=e.sCount[t]+1,32===e.src.charCodeAt(x)?(x++,s++,f++,i=!1,b=!0):9===e.src.charCodeAt(x)?(b=!0,(e.bsCount[t]+f)%4==3?(x++,s++,f++,i=!1):i=!0):b=!1,p=[e.bMarks[t]],e.bMarks[t]=x;x=k,v=[e.sCount[t]],e.sCount[t]=f-s,y=[e.tShift[t]],e.tShift[t]=x-e.bMarks[t],T=e.md.block.ruler.getRules("blockquote"),g=e.parentType,e.parentType="blockquote",d=t+1;d=(k=e.eMarks[d])));d++)if(62!==e.src.charCodeAt(x++)||C){if(u)break;for(E=!1,a=0,l=T.length;a=k,h.push(e.bsCount[d]),e.bsCount[d]=e.sCount[d]+1+(b?1:0),v.push(e.sCount[d]),e.sCount[d]=f-s,y.push(e.tShift[d]),e.tShift[d]=x-e.bMarks[d]}for(m=e.blkIndent,e.blkIndent=0,(w=e.push("blockquote_open","blockquote",1)).markup=">",w.map=c=[t,0],e.md.block.tokenize(e,t,d),(w=e.push("blockquote_close","blockquote",-1)).markup=">",e.lineMax=S,e.parentType=g,c[1]=e.line,a=0;a=4)return!1;if(42!==(i=e.src.charCodeAt(l++))&&45!==i&&95!==i)return!1;for(o=1;l=o)return-1;if((n=e.src.charCodeAt(i++))<48||n>57)return-1;for(;;){if(i>=o)return-1;if(!((n=e.src.charCodeAt(i++))>=48&&n<=57)){if(41===n||46===n)break;return-1}if(i-r>=10)return-1}return i=4)return!1;if(e.listIndent>=0&&e.sCount[t]-e.listIndent>=4&&e.sCount[t]=e.blkIndent&&(L=!0),(k=Dg(e,t))>=0){if(c=!0,_=e.bMarks[t]+e.tShift[t],g=Number(e.src.slice(_,k-1)),L&&1!==g)return!1}else{if(!((k=Ig(e,t))>=0))return!1;c=!1}if(L&&e.skipSpaces(k)>=e.eMarks[t])return!1;if(m=e.src.charCodeAt(k-1),r)return!0;for(h=e.tokens.length,c?(D=e.push("ordered_list_open","ol",1),1!==g&&(D.attrs=[["start",g]])):D=e.push("bullet_list_open","ul",1),D.map=p=[t,0],D.markup=String.fromCharCode(m),y=t,N=!1,I=e.md.block.ruler.getRules("list"),T=e.parentType,e.parentType="list";y=v?1:b-u)>4&&(l=1),s=u+l,(D=e.push("list_item_open","li",1)).markup=String.fromCharCode(m),D.map=d=[t,0],c&&(D.info=e.src.slice(_,k-1)),S=e.tight,C=e.tShift[t],w=e.sCount[t],E=e.listIndent,e.listIndent=e.blkIndent,e.blkIndent=s,e.tight=!0,e.tShift[t]=o-e.bMarks[t],e.sCount[t]=b,o>=v&&e.isEmpty(t+1)?e.line=Math.min(e.line+2,n):e.md.block.tokenize(e,t,n,!0),e.tight&&!N||(A=!1),N=e.line-t>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=E,e.tShift[t]=C,e.sCount[t]=w,e.tight=S,(D=e.push("list_item_close","li",-1)).markup=String.fromCharCode(m),y=t=e.line,d[1]=y,o=e.bMarks[t],y>=n)break;if(e.sCount[y]=4)break;for(O=!1,a=0,f=I.length;a=4)return!1;if(91!==e.src.charCodeAt(T))return!1;for(;++T3||e.sCount[C]<0)){for(v=!1,u=0,c=y.length;u`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)*\\s*\\/?>",Vg="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",Ug=new RegExp("^(?:"+jg+"|"+Vg+"|\x3c!----\x3e|\x3c!--(?:-?[^>-])(?:-?[^-])*--\x3e|<[?][\\s\\S]*?[?]>|]*>|)"),Bg=new RegExp("^(?:"+jg+"|"+Vg+")");Pg.HTML_TAG_RE=Ug,Pg.HTML_OPEN_CLOSE_TAG_RE=Bg;var $g=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","section","source","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],qg=Pg.HTML_OPEN_CLOSE_TAG_RE,Hg=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^/,!0],[/^<\?/,/\?>/,!0],[/^/,!0],[/^/,!0],[new RegExp("^|$))","i"),/^$/,!0],[new RegExp(qg.source+"\\s*$"),/^$/,!1]],Gg=g((function(e,t,n,r){var i,o,a,s,l=e.bMarks[t]+e.tShift[t],u=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;if(!e.md.options.html)return!1;if(60!==e.src.charCodeAt(l))return!1;for(s=e.src.slice(l,u),i=0;i=4)return!1;if(35!==(i=e.src.charCodeAt(l))||l>=u)return!1;for(o=1,i=e.src.charCodeAt(++l);35===i&&l6||ll&&zg(e.src.charCodeAt(a-1))&&(u=a),e.line=t+1,(s=e.push("heading_open","h"+String(o),1)).markup="########".slice(0,o),s.map=[t,e.line],(s=e.push("inline","",0)).content=e.src.slice(l,u).trim(),s.map=[t,e.line],s.children=[],(s=e.push("heading_close","h"+String(o),-1)).markup="########".slice(0,o)),0))}),"heading"),Kg=g((function(e,t,n){var r,i,o,a,s,l,u,c,d,f,p=t+1,h=e.md.block.ruler.getRules("paragraph");if(e.sCount[t]-e.blkIndent>=4)return!1;for(f=e.parentType,e.parentType="paragraph";p3)){if(e.sCount[p]>=e.blkIndent&&(l=e.bMarks[p]+e.tShift[p])<(u=e.eMarks[p])&&(45===(d=e.src.charCodeAt(l))||61===d)&&(l=e.skipChars(l,d),(l=e.skipSpaces(l))>=u)){c=61===d?1:2;break}if(!(e.sCount[p]<0)){for(i=!1,o=0,a=h.length;o3||e.sCount[l]<0)){for(r=!1,i=0,o=u.length;i0&&this.level++,this.tokens.push(r),r},Jg.prototype.isEmpty=g((function(e){return this.bMarks[e]+this.tShift[e]>=this.eMarks[e]}),"isEmpty"),Jg.prototype.skipEmptyLines=g((function(e){for(var t=this.lineMax;et;)if(!Yg(this.src.charCodeAt(--e)))return e+1;return e}),"skipSpacesBack"),Jg.prototype.skipChars=g((function(e,t){for(var n=this.src.length;en;)if(t!==this.src.charCodeAt(--e))return e+1;return e}),"skipCharsBack"),Jg.prototype.getLines=g((function(e,t,n,r){var i,o,a,s,l,u,c,d=e;if(e>=t)return"";for(u=new Array(t-e),i=0;dn?new Array(o-n+1).join(" ")+this.src.slice(s,l):this.src.slice(s,l)}return u.join("")}),"getLines"),Jg.prototype.Token=Xg;var Zg=Jg,ev=Pm,tv=[["table",wg,["paragraph","reference"]],["code",Cg],["fence",Sg,["paragraph","reference","blockquote","list"]],["blockquote",kg,["paragraph","reference","blockquote","list"]],["hr",_g,["paragraph","reference","blockquote","list"]],["list",Ag,["paragraph","reference","blockquote"]],["reference",Fg],["html_block",Gg,["paragraph","reference","blockquote"]],["heading",Wg,["paragraph","reference","blockquote"]],["lheading",Kg],["paragraph",Qg]];function nv(){this.ruler=new ev;for(var e=0;e=n))&&!(e.sCount[a]=l){e.line=n;break}for(r=0;r=0&&32===e.pending.charCodeAt(n)?n>=1&&32===e.pending.charCodeAt(n-1)?(e.pending=e.pending.replace(/ +$/,""),e.push("hardbreak","br",0)):(e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0)):e.push("softbreak","br",0)),i++;i?@[]^_`{|}~-".split("").forEach((function(e){uv[e.charCodeAt(0)]=1}));var dv=g((function(e,t){var n,r=e.pos,i=e.posMax;if(92!==e.src.charCodeAt(r))return!1;if(++r=0;n--)95!==(r=t[n]).marker&&42!==r.marker||-1!==r.end&&(i=t[r.end],s=n>0&&t[n-1].end===r.end+1&&t[n-1].token===r.token-1&&t[r.end+1].token===i.token+1&&t[n-1].marker===r.marker,a=String.fromCharCode(r.marker),(o=e.tokens[r.token]).type=s?"strong_open":"em_open",o.tag=s?"strong":"em",o.nesting=1,o.markup=s?a+a:a,o.content="",(o=e.tokens[i.token]).type=s?"strong_close":"em_close",o.tag=s?"strong":"em",o.nesting=-1,o.markup=s?a+a:a,o.content="",s&&(e.tokens[t[n-1].token].content="",e.tokens[t[r.end+1].token].content="",n--))}mv.tokenize=g((function(e,t){var n,r,i=e.pos,o=e.src.charCodeAt(i);if(t)return!1;if(95!==o&&42!==o)return!1;for(r=e.scanDelims(e.pos,42===o),n=0;n=p)return!1;if(h=s,(l=e.md.helpers.parseLinkDestination(e.src,s,e.posMax)).ok){for(c=e.md.normalizeLink(l.str),e.md.validateLink(c)?s=l.pos:c="",h=s;s=p||41!==e.src.charCodeAt(s))&&(m=!0),s++}if(m){if(void 0===e.env.references)return!1;if(s=0?i=e.src.slice(h,s++):s=o+1):s=o+1,i||(i=e.src.slice(a,o)),!(u=e.env.references[vv(i)]))return e.pos=f,!1;c=u.href,d=u.title}return t||(e.pos=a,e.posMax=o,e.push("link_open","a",1).attrs=n=[["href",c]],d&&n.push(["title",d]),e.md.inline.tokenize(e),e.push("link_close","a",-1)),e.pos=s,e.posMax=p,!0}),"link"),Ev=Wh.normalizeReference,Tv=Wh.isSpace,wv=g((function(e,t){var n,r,i,o,a,s,l,u,c,d,f,p,h,m="",g=e.pos,v=e.posMax;if(33!==e.src.charCodeAt(e.pos))return!1;if(91!==e.src.charCodeAt(e.pos+1))return!1;if(s=e.pos+2,(a=e.md.helpers.parseLinkLabel(e,e.pos+1,!1))<0)return!1;if((l=a+1)=v)return!1;for(h=l,(c=e.md.helpers.parseLinkDestination(e.src,l,e.posMax)).ok&&(m=e.md.normalizeLink(c.str),e.md.validateLink(m)?l=c.pos:m=""),h=l;l=v||41!==e.src.charCodeAt(l))return e.pos=g,!1;l++}else{if(void 0===e.env.references)return!1;if(l=0?o=e.src.slice(h,l++):l=a+1):l=a+1,o||(o=e.src.slice(s,a)),!(u=e.env.references[Ev(o)]))return e.pos=g,!1;m=u.href,d=u.title}return t||(i=e.src.slice(s,a),e.md.inline.parse(i,e.md,e.env,p=[]),(f=e.push("image","img",0)).attrs=n=[["src",m],["alt",""]],f.children=p,f.content=i,d&&n.push(["title",d])),e.pos=l,e.posMax=v,!0}),"image"),Cv=/^([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,Sv=/^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$/,xv=g((function(e,t){var n,r,i,o,a,s,l=e.pos;if(60!==e.src.charCodeAt(l))return!1;for(a=e.pos,s=e.posMax;;){if(++l>=s)return!1;if(60===(o=e.src.charCodeAt(l)))return!1;if(62===o)break}return n=e.src.slice(a+1,l),Sv.test(n)?(r=e.md.normalizeLink(n),!!e.md.validateLink(r)&&(t||((i=e.push("link_open","a",1)).attrs=[["href",r]],i.markup="autolink",i.info="auto",(i=e.push("text","",0)).content=e.md.normalizeLinkText(n),(i=e.push("link_close","a",-1)).markup="autolink",i.info="auto"),e.pos+=n.length+2,!0)):!!Cv.test(n)&&(r=e.md.normalizeLink("mailto:"+n),!!e.md.validateLink(r)&&(t||((i=e.push("link_open","a",1)).attrs=[["href",r]],i.markup="autolink",i.info="auto",(i=e.push("text","",0)).content=e.md.normalizeLinkText(n),(i=e.push("link_close","a",-1)).markup="autolink",i.info="auto"),e.pos+=n.length+2,!0))}),"autolink"),kv=Pg.HTML_TAG_RE;function Nv(e){var t=32|e;return t>=97&&t<=122}g(Nv,"isLetter");var _v=g((function(e,t){var n,r,i,o=e.pos;return!(!e.md.options.html||(i=e.posMax,60!==e.src.charCodeAt(o)||o+2>=i||33!==(n=e.src.charCodeAt(o+1))&&63!==n&&47!==n&&!Nv(n)||!(r=e.src.slice(o).match(kv))||(t||(e.push("html_inline","",0).content=e.src.slice(o,o+r[0].length)),e.pos+=r[0].length,0)))}),"html_inline"),Ov=Kh,Iv=Wh.has,Dv=Wh.isValidEntityCode,Lv=Wh.fromCodePoint,Av=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,Mv=/^&([a-z][a-z0-9]{1,31});/i,Rv=g((function(e,t){var n,r,i=e.pos,o=e.posMax;if(38!==e.src.charCodeAt(i))return!1;if(i+1a;r-=o.jump+1)if((o=t[r]).marker===i.marker&&o.open&&o.end<0&&(l=!1,(o.close||i.open)&&(o.length+i.length)%3==0&&(o.length%3==0&&i.length%3==0||(l=!0)),!l)){u=r>0&&!t[r-1].open?t[r-1].jump+1:0,i.jump=n-r+u,i.open=!1,o.end=n,o.jump=u,o.close=!1,s=-1;break}-1!==s&&(c[i.marker][(i.open?3:0)+(i.length||0)%3]=s)}}g(Fv,"processDelimiters");var Pv=g((function(e){var t,n=e.tokens_meta,r=e.tokens_meta.length;for(Fv(0,e.delimiters),t=0;t0&&r++,"text"===i[t].type&&t+10&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],i={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(r),this.tokens_meta.push(i),r},qv.prototype.scanDelims=function(e,t){var n,r,i,o,a,s,l,u,c,d=e,f=!0,p=!0,h=this.posMax,m=this.src.charCodeAt(e);for(n=e>0?this.src.charCodeAt(e-1):32;d=o)break}else e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()},Kv.prototype.parse=function(e,t,n,r){var i,o,a,s=new this.State(e,t,n,r);for(this.tokenize(s),a=(o=this.ruler2.getRules("")).length,i=0;i|$))",t.tpl_email_fuzzy='(^|[><|]|"|\\(|'+t.src_ZCc+")("+t.src_email_name+"@"+t.tpl_host_fuzzy_strict+")",t.tpl_link_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`||]|"+t.src_ZPCc+"))((?![$+<=>^`||])"+t.tpl_host_port_fuzzy_strict+t.src_path+")",t.tpl_link_no_ip_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`||]|"+t.src_ZPCc+"))((?![$+<=>^`||])"+t.tpl_host_port_no_ip_fuzzy_strict+t.src_path+")",t}),"re");function Yv(e){return Array.prototype.slice.call(arguments,1).forEach((function(t){t&&Object.keys(t).forEach((function(n){e[n]=t[n]}))})),e}function Jv(e){return Object.prototype.toString.call(e)}function Zv(e){return"[object String]"===Jv(e)}function ey(e){return"[object Object]"===Jv(e)}function ty(e){return"[object RegExp]"===Jv(e)}function ny(e){return"[object Function]"===Jv(e)}function ry(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}g(Yv,"assign"),g(Jv,"_class"),g(Zv,"isString"),g(ey,"isObject"),g(ty,"isRegExp"),g(ny,"isFunction"),g(ry,"escapeRE");var iy={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function oy(e){return Object.keys(e||{}).reduce((function(e,t){return e||iy.hasOwnProperty(t)}),!1)}g(oy,"isOptionsObj");var ay={"http:":{validate:function(e,t,n){var r=e.slice(t);return n.re.http||(n.re.http=new RegExp("^\\/\\/"+n.re.src_auth+n.re.src_host_port_strict+n.re.src_path,"i")),n.re.http.test(r)?r.match(n.re.http)[0].length:0}},"https:":"http:","ftp:":"http:","//":{validate:function(e,t,n){var r=e.slice(t);return n.re.no_http||(n.re.no_http=new RegExp("^"+n.re.src_auth+"(?:localhost|(?:(?:"+n.re.src_domain+")\\.)+"+n.re.src_domain_root+")"+n.re.src_port+n.re.src_host_terminator+n.re.src_path,"i")),n.re.no_http.test(r)?t>=3&&":"===e[t-3]||t>=3&&"/"===e[t-3]?0:r.match(n.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,n){var r=e.slice(t);return n.re.mailto||(n.re.mailto=new RegExp("^"+n.re.src_email_name+"@"+n.re.src_host_strict,"i")),n.re.mailto.test(r)?r.match(n.re.mailto)[0].length:0}}},sy="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",ly="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф".split("|");function uy(e){e.__index__=-1,e.__text_cache__=""}function cy(e){return function(t,n){var r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function dy(){return function(e,t){t.normalize(e)}}function fy(e){var t=e.re=Xv(e.__opts__),n=e.__tlds__.slice();function r(e){return e.replace("%TLDS%",t.src_tlds)}e.onCompile(),e.__tlds_replaced__||n.push(sy),n.push(t.src_xn),t.src_tlds=n.join("|"),g(r,"untpl"),t.email_fuzzy=RegExp(r(t.tpl_email_fuzzy),"i"),t.link_fuzzy=RegExp(r(t.tpl_link_fuzzy),"i"),t.link_no_ip_fuzzy=RegExp(r(t.tpl_link_no_ip_fuzzy),"i"),t.host_fuzzy_test=RegExp(r(t.tpl_host_fuzzy_test),"i");var i=[];function o(e,t){throw new Error('(LinkifyIt) Invalid schema "'+e+'": '+t)}e.__compiled__={},g(o,"schemaError"),Object.keys(e.__schemas__).forEach((function(t){var n=e.__schemas__[t];if(null!==n){var r={validate:null,link:null};if(e.__compiled__[t]=r,ey(n))return ty(n.validate)?r.validate=cy(n.validate):ny(n.validate)?r.validate=n.validate:o(t,n),void(ny(n.normalize)?r.normalize=n.normalize:n.normalize?o(t,n):r.normalize=function(e,t){t.normalize(e)});Zv(n)?i.push(t):o(t,n)}})),i.forEach((function(t){e.__compiled__[e.__schemas__[t]]&&(e.__compiled__[t].validate=e.__compiled__[e.__schemas__[t]].validate,e.__compiled__[t].normalize=e.__compiled__[e.__schemas__[t]].normalize)})),e.__compiled__[""]={validate:null,normalize:function(e,t){t.normalize(e)}};var a=Object.keys(e.__compiled__).filter((function(t){return t.length>0&&e.__compiled__[t]})).map(ry).join("|");e.re.schema_test=RegExp("(^|(?!_)(?:[><|]|"+t.src_ZPCc+"))("+a+")","i"),e.re.schema_search=RegExp("(^|(?!_)(?:[><|]|"+t.src_ZPCc+"))("+a+")","ig"),e.re.pretest=RegExp("("+e.re.schema_test.source+")|("+e.re.host_fuzzy_test.source+")|@","i"),uy(e)}function py(e,t){var n=e.__index__,r=e.__last_index__,i=e.__text_cache__.slice(n,r);this.schema=e.__schema__.toLowerCase(),this.index=n+t,this.lastIndex=r+t,this.raw=i,this.text=i,this.url=i}function hy(e,t){var n=new py(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function my(e,t){if(!(this instanceof my))return new my(e,t);t||oy(e)&&(t=e,e={}),this.__opts__=Yv({},iy,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=Yv({},ay,e),this.__compiled__={},this.__tlds__=ly,this.__tlds_replaced__=!1,this.re={},fy(this)}g(uy,"resetScanCache"),g(cy,"createValidator"),g(dy,"createNormalizer"),g(fy,"compile"),g(py,"Match"),g(hy,"createMatch"),g(my,"LinkifyIt$1"),my.prototype.add=g((function(e,t){return this.__schemas__[e]=t,fy(this),this}),"add"),my.prototype.set=g((function(e){return this.__opts__=Yv(this.__opts__,e),this}),"set"),my.prototype.test=g((function(e){if(this.__text_cache__=e,this.__index__=-1,!e.length)return!1;var t,n,r,i,o,a,s,l;if(this.re.schema_test.test(e))for((s=this.re.schema_search).lastIndex=0;null!==(t=s.exec(e));)if(i=this.testSchemaAt(e,t[2],s.lastIndex)){this.__schema__=t[2],this.__index__=t.index+t[1].length,this.__last_index__=t.index+t[0].length+i;break}return this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&(l=e.search(this.re.host_fuzzy_test))>=0&&(this.__index__<0||l=0&&null!==(r=e.match(this.re.email_fuzzy))&&(o=r.index+r[1].length,a=r.index+r[0].length,(this.__index__<0||othis.__last_index__)&&(this.__schema__="mailto:",this.__index__=o,this.__last_index__=a)),this.__index__>=0}),"test"),my.prototype.pretest=g((function(e){return this.re.pretest.test(e)}),"pretest"),my.prototype.testSchemaAt=g((function(e,t,n){return this.__compiled__[t.toLowerCase()]?this.__compiled__[t.toLowerCase()].validate(e,n,this):0}),"testSchemaAt"),my.prototype.match=g((function(e){var t=0,n=[];this.__index__>=0&&this.__text_cache__===e&&(n.push(hy(this,t)),t=this.__last_index__);for(var r=t?e.slice(t):e;this.test(r);)n.push(hy(this,t)),r=r.slice(this.__last_index__),t+=this.__last_index__;return n.length?n:null}),"match"),my.prototype.tlds=g((function(e,t){return e=Array.isArray(e)?e:[e],t?(this.__tlds__=this.__tlds__.concat(e).sort().filter((function(e,t,n){return e!==n[t-1]})).reverse(),fy(this),this):(this.__tlds__=e.slice(),this.__tlds_replaced__=!0,fy(this),this)}),"tlds"),my.prototype.normalize=g((function(e){e.schema||(e.url="http://"+e.url),"mailto:"!==e.schema||/^mailto:/i.test(e.url)||(e.url="mailto:"+e.url)}),"normalize"),my.prototype.onCompile=g((function(){}),"onCompile");var gy=my;const vy=2147483647,yy=36,by=/^xn--/,Ey=/[^\0-\x7E]/,Ty=/[\x2E\u3002\uFF0E\uFF61]/g,wy={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Cy=Math.floor,Sy=String.fromCharCode;function xy(e){throw new RangeError(wy[e])}function ky(e,t){const n=[];let r=e.length;for(;r--;)n[r]=t(e[r]);return n}function Ny(e,t){const n=e.split("@");let r="";return n.length>1&&(r=n[0]+"@",e=n[1]),r+ky((e=e.replace(Ty,".")).split("."),t).join(".")}function _y(e){const t=[];let n=0;const r=e.length;for(;n=55296&&i<=56319&&nString.fromCodePoint(...e)),"ucs2encode"),Iy=g((function(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:yy}),"basicToDigit"),Dy=g((function(e,t){return e+22+75*(e<26)-((0!=t)<<5)}),"digitToBasic"),Ly=g((function(e,t,n){let r=0;for(e=n?Cy(e/700):e>>1,e+=Cy(e/t);e>455;r+=yy)e=Cy(e/35);return Cy(r+36*e/(e+38))}),"adapt"),Ay=g((function(e){const t=[],n=e.length;let r=0,i=128,o=72,a=e.lastIndexOf("-");a<0&&(a=0);for(let n=0;n=128&&xy("not-basic"),t.push(e.charCodeAt(n));for(let s=a>0?a+1:0;s=n&&xy("invalid-input");const a=Iy(e.charCodeAt(s++));(a>=yy||a>Cy((vy-r)/t))&&xy("overflow"),r+=a*t;const l=i<=o?1:i>=o+26?26:i-o;if(aCy(vy/u)&&xy("overflow"),t*=u}const l=t.length+1;o=Ly(r-a,l,0==a),Cy(r/l)>vy-i&&xy("overflow"),i+=Cy(r/l),r%=l,t.splice(r++,0,i)}return String.fromCodePoint(...t)}),"decode"),My=g((function(e){const t=[];let n=(e=_y(e)).length,r=128,i=0,o=72;for(const n of e)n<128&&t.push(Sy(n));let a=t.length,s=a;for(a&&t.push("-");s=r&&tCy((vy-i)/l)&&xy("overflow"),i+=(n-r)*l,r=n;for(const n of e)if(nvy&&xy("overflow"),n==r){let e=i;for(let n=yy;;n+=yy){const r=n<=o?1:n>=o+26?26:n-o;if(e=0))try{t.hostname=Wy.toASCII(t.hostname)}catch(e){}return zy.encode(zy.format(t))}function eb(e){var t=zy.parse(e,!0);if(t.hostname&&(!t.protocol||Jy.indexOf(t.protocol)>=0))try{t.hostname=Wy.toUnicode(t.hostname)}catch(e){}return zy.decode(zy.format(t),zy.decode.defaultChars+"%")}function tb(e,t){if(!(this instanceof tb))return new tb(e,t);t||Vy.isString(e)||(t=e||{},e="default"),this.inline=new Hy,this.block=new qy,this.core=new $y,this.renderer=new By,this.linkify=new Gy,this.validateLink=Yy,this.normalizeLink=Zy,this.normalizeLinkText=eb,this.utils=Vy,this.helpers=Vy.assign({},Uy),this.options={},this.configure(e),t&&this.set(t)}g(Zy,"normalizeLink"),g(eb,"normalizeLinkText"),g(tb,"MarkdownIt"),tb.prototype.set=function(e){return Vy.assign(this.options,e),this},tb.prototype.configure=function(e){var t,n=this;if(Vy.isString(e)&&!(e=Ky[t=e]))throw new Error('Wrong `markdown-it` preset "'+t+'", check name');if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&n.set(e.options),e.components&&Object.keys(e.components).forEach((function(t){e.components[t].rules&&n[t].ruler.enableOnly(e.components[t].rules),e.components[t].rules2&&n[t].ruler2.enableOnly(e.components[t].rules2)})),this},tb.prototype.enable=function(e,t){var n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach((function(t){n=n.concat(this[t].ruler.enable(e,!0))}),this),n=n.concat(this.inline.ruler2.enable(e,!0));var r=e.filter((function(e){return n.indexOf(e)<0}));if(r.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+r);return this},tb.prototype.disable=function(e,t){var n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach((function(t){n=n.concat(this[t].ruler.disable(e,!0))}),this),n=n.concat(this.inline.ruler2.disable(e,!0));var r=e.filter((function(e){return n.indexOf(e)<0}));if(r.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+r);return this},tb.prototype.use=function(e){var t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this},tb.prototype.parse=function(e,t){if("string"!=typeof e)throw new Error("Input data should be a String");var n=new this.core.State(e,this,t);return this.core.process(n),n.tokens},tb.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)},tb.prototype.parseInline=function(e,t){var n=new this.core.State(e,this,t);return n.inlineMode=!0,this.core.process(n),n.tokens},tb.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};const nb=new tb({breaks:!0,linkify:!0}),rb=(0,t.forwardRef)(((e,t)=>{var n=e,{children:r,onlyShowFirstChild:i,type:o}=n,a=v(n,["children","onlyShowFirstChild","type"]);return de("div",m(h({},a),{ref:t,className:b(`graphiql-markdown-${o}`,i&&"graphiql-markdown-preview",a.className),dangerouslySetInnerHTML:{__html:nb.render(r)}}))}));e.aM=rb,rb.displayName="MarkdownContent";const ib=(0,t.forwardRef)(((e,t)=>de("div",m(h({},e),{ref:t,className:b("graphiql-spinner",e.className)}))));function ob(e){var t,n,r=ms(e),i=r.defaultView||window;return r?{width:null!=(t=r.documentElement.clientWidth)?t:i.innerWidth,height:null!=(n=r.documentElement.clientHeight)?n:i.innerHeight}:{width:0,height:0}}function ab(){return ab=Object.assign||function(e){for(var t=1;t=0||(i[n]=e[n]);return i}e.aN=ib,ib.displayName="Spinner",g(ob,"getDocumentDimensions"),g(ab,"_extends$1"),g(sb,"_objectWithoutPropertiesLoose$1");var lb,ub,cb,db,fb,pb,hb,mb,gb,vb,yb=["children","label","ariaLabel","id","DEBUG_STYLE"],bb=["label","ariaLabel","isVisible","id"],Eb=["ariaLabel","aria-label","as","id","isVisible","label","position","style","triggerRect"],Tb=["type"],wb=100,Cb=500;(vb=hb||(hb={})).Idle="IDLE",vb.Focused="FOCUSED",vb.Visible="VISIBLE",vb.LeavingVisible="LEAVING_VISIBLE",vb.Dismissed="DISMISSED",(gb=mb||(mb={})).Blur="BLUR",gb.Focus="FOCUS",gb.GlobalMouseMove="GLOBAL_MOUSE_MOVE",gb.MouseDown="MOUSE_DOWN",gb.MouseEnter="MOUSE_ENTER",gb.MouseLeave="MOUSE_LEAVE",gb.MouseMove="MOUSE_MOVE",gb.Rest="REST",gb.SelectWithKeyboard="SELECT_WITH_KEYBOARD",gb.TimeComplete="TIME_COMPLETE";var Sb,xb,kb={initial:hb.Idle,states:(pb={},pb[hb.Idle]={enter:Rb,on:(lb={},lb[mb.MouseEnter]=hb.Focused,lb[mb.Focus]=hb.Visible,lb)},pb[hb.Focused]={enter:Db,leave:Lb,on:(ub={},ub[mb.MouseMove]=hb.Focused,ub[mb.MouseLeave]=hb.Idle,ub[mb.MouseDown]=hb.Dismissed,ub[mb.Blur]=hb.Idle,ub[mb.Rest]=hb.Visible,ub)},pb[hb.Visible]={on:(cb={},cb[mb.Focus]=hb.Focused,cb[mb.MouseEnter]=hb.Focused,cb[mb.MouseLeave]=hb.LeavingVisible,cb[mb.Blur]=hb.LeavingVisible,cb[mb.MouseDown]=hb.Dismissed,cb[mb.SelectWithKeyboard]=hb.Dismissed,cb[mb.GlobalMouseMove]=hb.LeavingVisible,cb)},pb[hb.LeavingVisible]={enter:Ab,leave:g((function(){Mb(),Rb()}),"leave"),on:(db={},db[mb.MouseEnter]=hb.Visible,db[mb.Focus]=hb.Visible,db[mb.TimeComplete]=hb.Idle,db)},pb[hb.Dismissed]={leave:g((function(){Rb()}),"leave"),on:(fb={},fb[mb.MouseLeave]=hb.Idle,fb[mb.Blur]=hb.Idle,fb)},pb)},Nb={value:kb.initial,context:{id:null}},_b=[];function Ob(e){return _b.push(e),function(){_b.splice(_b.indexOf(e),1)}}function Ib(){_b.forEach((function(e){return e(Nb)}))}function Db(){window.clearTimeout(Sb),Sb=window.setTimeout((function(){qb({type:mb.Rest})}),wb)}function Lb(){window.clearTimeout(Sb)}function Ab(){window.clearTimeout(xb),xb=window.setTimeout((function(){return qb({type:mb.TimeComplete})}),Cb)}function Mb(){window.clearTimeout(xb)}function Rb(){Nb.context.id=null}function Fb(e){var n=void 0===e?{}:e,r=n.id,i=n.onPointerEnter,o=n.onPointerMove,a=n.onPointerLeave,s=n.onPointerDown,l=n.onMouseEnter,u=n.onMouseMove,c=n.onMouseLeave,d=n.onMouseDown,f=n.onFocus,p=n.onBlur,h=n.onKeyDown,m=n.disabled,v=n.ref,y=n.DEBUG_STYLE,b=String(rd(r)),E=(0,t.useState)(!!y||Gb(b,!0)),T=E[0],w=E[1],C=(0,t.useRef)(null),S=Ss(v,C),x=cd(C,{observe:T});function k(e,t){return"undefined"!=typeof window&&"PointerEvent"in window?e:xs(e,t)}function N(e){return g((function(t){"mouse"===t.pointerType&&e(t)}),"onPointerEvent")}function _(){qb({type:mb.MouseEnter,id:b})}function O(){qb({type:mb.MouseMove,id:b})}function I(){qb({type:mb.MouseLeave})}function D(){Nb.context.id===b&&qb({type:mb.MouseDown})}function L(){window.__REACH_DISABLE_TOOLTIPS||qb({type:mb.Focus,id:b})}function A(){Nb.context.id===b&&qb({type:mb.Blur})}function M(e){"Enter"!==e.key&&" "!==e.key||qb({type:mb.SelectWithKeyboard})}return(0,t.useEffect)((function(){return Ob((function(){w(Gb(b))}))}),[b]),(0,t.useEffect)((function(){var e=ms(C.current);function t(e){"Escape"!==e.key&&"Esc"!==e.key||Nb.value!==hb.Visible||qb({type:mb.SelectWithKeyboard})}return g(t,"listener"),e.addEventListener("keydown",t),function(){return e.removeEventListener("keydown",t)}}),[]),$b({disabled:m,isVisible:T,ref:C}),g(k,"wrapMouseEvent"),g(N,"wrapPointerEventHandler"),g(_,"handleMouseEnter"),g(O,"handleMouseMove"),g(I,"handleMouseLeave"),g(D,"handleMouseDown"),g(L,"handleFocus"),g(A,"handleBlur"),g(M,"handleKeyDown"),[{"aria-describedby":T?lf("tooltip",b):void 0,"data-state":T?"tooltip-visible":"tooltip-hidden","data-reach-tooltip-trigger":"",ref:S,onPointerEnter:xs(i,N(_)),onPointerMove:xs(o,N(O)),onPointerLeave:xs(a,N(I)),onPointerDown:xs(s,N(D)),onMouseEnter:k(l,_),onMouseMove:k(u,O),onMouseLeave:k(c,I),onMouseDown:k(d,D),onFocus:xs(f,L),onBlur:xs(p,A),onKeyDown:xs(h,M)},{id:b,triggerRect:x,isVisible:T},T]}g(Ob,"subscribe"),g(Ib,"notify"),g(Db,"startRestTimer"),g(Lb,"clearRestTimer"),g(Ab,"startLeavingVisibleTimer"),g(Mb,"clearLeavingVisibleTimer"),g(Rb,"clearContextId"),g(Fb,"useTooltip");var Pb=(0,t.forwardRef)((function(e,n){var r=e.children,i=e.label,o=e.ariaLabel,a=e.id,s=e.DEBUG_STYLE,l=sb(e,yb),u=t.Children.only(r),c=Fb({id:a,onPointerEnter:u.props.onPointerEnter,onPointerMove:u.props.onPointerMove,onPointerLeave:u.props.onPointerLeave,onPointerDown:u.props.onPointerDown,onMouseEnter:u.props.onMouseEnter,onMouseMove:u.props.onMouseMove,onMouseLeave:u.props.onMouseLeave,onMouseDown:u.props.onMouseDown,onFocus:u.props.onFocus,onBlur:u.props.onBlur,onKeyDown:u.props.onKeyDown,disabled:u.props.disabled,ref:u.ref,DEBUG_STYLE:s}),d=c[0],f=c[1];return(0,t.createElement)(t.Fragment,null,(0,t.cloneElement)(u,d),(0,t.createElement)(jb,ab({ref:n,label:i,"aria-label":o},f,l)))}));e.aQ=Pb;var jb=(0,t.forwardRef)(g((function(e,n){var r=e.label,i=e.ariaLabel,o=e.isVisible,a=e.id,s=sb(e,bb);return o?(0,t.createElement)(hs,null,(0,t.createElement)(Vb,ab({ref:n,label:r,"aria-label":i,isVisible:o},s,{id:lf("tooltip",String(a))}))):null}),"TooltipPopup")),Vb=(0,t.forwardRef)(g((function(e,n){var r=e.ariaLabel,i=e["aria-label"],o=e.as,a=void 0===o?"div":o,s=e.id,l=e.isVisible,u=e.label,c=e.position,d=void 0===c?Bb:c,f=e.style,p=e.triggerRect,h=sb(e,Eb),m=null!=(i||r),g=(0,t.useRef)(null),v=Ss(n,g),y=cd(g,{observe:l});return(0,t.createElement)(t.Fragment,null,(0,t.createElement)(a,ab({role:m?void 0:"tooltip"},h,{ref:v,"data-reach-tooltip":"",id:m?void 0:s,style:ab({},f,Ub(d,p,y))}),u),m&&(0,t.createElement)(Kc,{role:"tooltip",id:s},i||r))}),"TooltipContent"));function Ub(e,t,n){return n?e(t,n):{visibility:"hidden"}}g(Ub,"getStyles");var Bb=g((function(e,t,n){void 0===n&&(n=8);var r=ob(),i=r.width,o=r.height;if(!e||!t)return{};var a={top:e.top-t.height<0,right:i{var n=e,{isActive:r}=n,i=v(n,["isActive"]);return de("div",m(h({},i),{ref:t,role:"tab","aria-selected":r,className:b("graphiql-tab",r&&"graphiql-tab-active",i.className),children:i.children}))}));zb.displayName="Tab";const Wb=(0,t.forwardRef)(((e,t)=>de(os,m(h({},e),{ref:t,type:"button",className:b("graphiql-tab-button",e.className),children:e.children}))));Wb.displayName="Tab.Button";const Kb=(0,t.forwardRef)(((e,t)=>de(Pb,{label:"Close Tab",children:de(os,m(h({"aria-label":"Close Tab"},e),{ref:t,type:"button",className:b("graphiql-tab-close",e.className),children:de(La,{})}))})));Kb.displayName="Tab.Close";const Qb=Xc(zb,{Button:Wb,Close:Kb});e.aO=Qb;const Xb=(0,t.forwardRef)(((e,t)=>de("div",m(h({},e),{ref:t,role:"tablist",className:b("graphiql-tabs",e.className),children:e.children}))));e.aP=Xb,Xb.displayName="Tabs";var Yb=Object.defineProperty,Jb=g(((e,t)=>Yb(e,"name",{value:t,configurable:!0})),"__name$C");const Zb=X("HistoryContext");function eE(e){var n;const r=ye(),i=(0,t.useRef)(new W(r||new H(null),e.maxHistoryLength||nE)),[o,a]=(0,t.useState)((null==(n=i.current)?void 0:n.queries)||[]),s=(0,t.useCallback)((e=>{let{query:t,variables:n,headers:r,operationName:o}=e;var s;null==(s=i.current)||s.updateHistory(t,n,r,o),a(i.current.queries)}),[]),l=(0,t.useCallback)((e=>{let{query:t,variables:n,headers:r,operationName:o,label:s,favorite:l}=e;i.current.editLabel(t,n,r,o,s,l),a(i.current.queries)}),[]),u=(0,t.useCallback)((e=>{let{query:t,variables:n,headers:r,operationName:o,label:s,favorite:l}=e;i.current.toggleFavorite(t,n,r,o,s,l),a(i.current.queries)}),[]),c=(0,t.useMemo)((()=>({addToHistory:s,editLabel:l,items:o,toggleFavorite:u})),[s,l,o,u]);return de(Zb.Provider,{value:c,children:e.children})}e.X=Zb,g(eE,"HistoryContextProvider"),Jb(eE,"HistoryContextProvider");const tE=Y(Zb);e.Z=tE;const nE=20;var rE=Object.defineProperty,iE=g(((e,t)=>rE(e,"name",{value:t,configurable:!0})),"__name$B");function oE(){const{items:e}=tE({nonNull:!0}),n=e.slice().reverse();return fe("section",{"aria-label":"History",className:"graphiql-history",children:[de("div",{className:"graphiql-history-header",children:"History"}),de("ul",{className:"graphiql-history-items",children:n.map(((e,r)=>fe(t.Fragment,{children:[de(aE,{item:e}),e.favorite&&n[r+1]&&!n[r+1].favorite?de("div",{className:"graphiql-history-item-spacer"}):null]},`${r}:${e.label||e.query}`)))})]})}function aE(e){const{editLabel:n,toggleFavorite:r}=tE({nonNull:!0,caller:aE}),{headerEditor:i,queryEditor:o,variableEditor:a}=oS({nonNull:!0,caller:aE}),s=(0,t.useRef)(null),l=(0,t.useRef)(null),[u,c]=(0,t.useState)(!1);(0,t.useEffect)((()=>{u&&s.current&&s.current.focus()}),[u]);const d=e.item.label||e.item.operationName||sE(e.item.query);return de("li",{className:b("graphiql-history-item",u&&"editable"),children:fe(pe,u?{children:[de("input",{type:"text",defaultValue:e.item.label,ref:s,onKeyDown:t=>{"Esc"===t.key?c(!1):"Enter"===t.key&&(c(!1),n(m(h({},e.item),{label:t.currentTarget.value})))},placeholder:"Type a label"}),de(os,{type:"button",ref:l,onClick:()=>{var t;c(!1),n(m(h({},e.item),{label:null==(t=s.current)?void 0:t.value}))},children:"Save"}),de(os,{type:"button",ref:l,onClick:()=>{c(!1)},children:de(La,{})})]}:{children:[de(os,{type:"button",className:"graphiql-history-item-label",onClick:()=>{var t,n,r;null==o||o.setValue(null!=(t=e.item.query)?t:""),null==a||a.setValue(null!=(n=e.item.variables)?n:""),null==i||i.setValue(null!=(r=e.item.headers)?r:"")},children:d}),de(Pb,{label:"Edit label",children:de(os,{type:"button",className:"graphiql-history-item-action",onClick:e=>{e.stopPropagation(),c(!0)},"aria-label":"Edit label",children:de(Wa,{"aria-hidden":"true"})})}),de(Pb,{label:e.item.favorite?"Remove favorite":"Add favorite",children:de(os,{type:"button",className:"graphiql-history-item-action",onClick:t=>{t.stopPropagation(),r(e.item)},"aria-label":e.item.favorite?"Remove favorite":"Add favorite",children:e.item.favorite?de(es,{"aria-hidden":"true"}):de(ts,{"aria-hidden":"true"})})})]})})}function sE(e){return null==e?void 0:e.split("\n").map((e=>e.replace(/#(.*)/,""))).join(" ").replaceAll("{"," { ").replaceAll("}"," } ").replaceAll(/[\s]{2,}/g," ")}g(oE,"History"),iE(oE,"History"),g(aE,"HistoryItem"),iE(aE,"HistoryItem"),g(sE,"formatQuery"),iE(sE,"formatQuery");var lE=Object.defineProperty,uE=g(((e,t)=>lE(e,"name",{value:t,configurable:!0})),"__name$A");const cE=X("ExecutionContext");function dE(e){let{fetcher:n,getDefaultFieldNames:i,children:o,operationName:a}=e;if(!n)throw new TypeError("The `ExecutionContextProvider` component requires a `fetcher` function to be passed as prop.");const{externalFragments:s,headerEditor:l,queryEditor:u,responseEditor:c,variableEditor:d,updateActiveTabValues:f}=oS({nonNull:!0,caller:dE}),p=tE(),m=fC({getDefaultFieldNames:i,caller:dE}),[g,y]=(0,t.useState)(!1),[b,E]=(0,t.useState)(null),T=(0,t.useRef)(0),w=(0,t.useCallback)((()=>{null==b||b.unsubscribe(),y(!1),E(null)}),[b]),x=(0,t.useCallback)((async()=>{var e,t;if(!u||!c)return;if(b)return void w();const i=uE((e=>{c.setValue(e),f({response:e})}),"setResponse");T.current+=1;const o=T.current;let g=m()||u.getValue();const x=null==d?void 0:d.getValue();let k;try{k=pE({json:x,errorMessageParse:"Variables are invalid JSON",errorMessageType:"Variables are not a JSON object."})}catch(e){return void i(e instanceof Error?e.message:`${e}`)}const N=null==l?void 0:l.getValue();let _;try{_=pE({json:N,errorMessageParse:"Headers are invalid JSON",errorMessageType:"Headers are not a JSON object."})}catch(e){return void i(e instanceof Error?e.message:`${e}`)}if(s){const e=u.documentAST?_o(u.documentAST,s):[];e.length>0&&(g+="\n"+e.map((e=>(0,r.print)(e))).join("\n"))}i(""),y(!0);const O=null!=(e=null!=a?a:u.operationName)?e:void 0;null==p||p.addToHistory({query:g,variables:x,headers:N,operationName:O});try{let e={data:{}};const r=uE((t=>{if(o!==T.current)return;let n=!!Array.isArray(t)&&t;if(!n&&"object"==typeof t&&null!==t&&"hasNext"in t&&(n=[t]),n){const t={data:e.data},r=[...(null==e?void 0:e.errors)||[],...n.flatMap((e=>e.errors)).filter(Boolean)];r.length&&(t.errors=r);for(const r of n){const n=r,{path:i,data:o,errors:a}=n,s=v(n,["path","data","errors"]);if(i){if(!o)throw new Error(`Expected part to contain a data property, but got ${r}`);Qo(t.data,i,o,{merge:!0})}else o&&(t.data=o);e=h(h({},t),s)}y(!1),i(L(e))}else{const e=L(t);y(!1),i(e)}}),"handleResponse"),a=n({query:g,variables:k,operationName:O},{headers:null!=_?_:void 0,documentAST:null!=(t=u.documentAST)?t:void 0}),s=await Promise.resolve(a);if(C(s))E(s.subscribe({next(e){r(e)},error(e){y(!1),e&&i(D(e)),E(null)},complete(){y(!1),E(null)}}));else if(S(s)){E({unsubscribe:()=>{var e,t;return null==(t=(e=s[Symbol.asyncIterator]()).return)?void 0:t.call(e)}});for await(const e of s)r(e);y(!1),E(null)}else r(s)}catch(e){y(!1),i(D(e)),E(null)}}),[m,s,n,l,p,a,u,c,w,b,f,d]),k=Boolean(b),N=(0,t.useMemo)((()=>({isFetching:g,isSubscribed:k,operationName:null!=a?a:null,run:x,stop:w})),[g,k,a,x,w]);return de(cE.Provider,{value:N,children:o})}e.r=cE,g(dE,"ExecutionContextProvider"),uE(dE,"ExecutionContextProvider");const fE=Y(cE);function pE(e){let t,{json:n,errorMessageParse:r,errorMessageType:i}=e;try{t=n&&""!==n.trim()?JSON.parse(n):void 0}catch(e){throw new Error(`${r}: ${e instanceof Error?e.message:e}.`)}const o="object"==typeof t&&null!==t&&!Array.isArray(t);if(void 0!==t&&!o)throw new Error(i);return t}e.v=fE,g(pE,"tryParseJsonObject"),uE(pE,"tryParseJsonObject");var hE=Object.defineProperty,mE=g(((e,t)=>hE(e,"name",{value:t,configurable:!0})),"__name$z");const gE="graphiql",vE="sublime";let yE=!1;"object"==typeof window&&(yE=0===window.navigator.platform.toLowerCase().indexOf("mac"));const bE={[yE?"Cmd-F":"Ctrl-F"]:"findPersistent","Cmd-G":"findPersistent","Ctrl-G":"findPersistent","Ctrl-Left":"goSubwordLeft","Ctrl-Right":"goSubwordRight","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight"};async function EE(e,t){const r=await Promise.resolve().then(n.t.bind(n,535,23)).then((function(e){return e.c})).then((e=>"function"==typeof e?e:e.default));return await Promise.all(!1===(null==t?void 0:t.useCommonAddons)?e:[Promise.resolve().then(n.t.bind(n,6980,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,9171,23)).then((function(e){return e.m})),Promise.resolve().then(n.t.bind(n,5728,23)).then((function(e){return e.c})),Promise.resolve().then(n.t.bind(n,4468,23)).then((function(e){return e.b})),Promise.resolve().then(n.t.bind(n,8419,23)).then((function(e){return e.f})),Promise.resolve().then(n.t.bind(n,4054,23)).then((function(e){return e.l})),Promise.resolve().then(n.t.bind(n,9407,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,4471,23)).then((function(e){return e.j})),Promise.resolve().then(n.t.bind(n,8058,23)).then((function(e){return e.d})),Promise.resolve().then(n.t.bind(n,2568,23)).then((function(e){return e.s})),...e]),r}g(EE,"importCodeMirror"),mE(EE,"importCodeMirror");var TE=g((function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;rNE(e,"name",{value:t,configurable:!0})),"__name$y");const OE=_E((e=>e?(0,r.print)(e):""),"printDefault");function IE(e){let{field:t}=e;if(!("defaultValue"in t)||void 0===t.defaultValue)return null;const n=(0,r.astFromValue)(t.defaultValue,t.type);return n?fe(pe,{children:[" = ",de("span",{className:"graphiql-doc-explorer-default-value",children:OE(n)})]}):null}g(IE,"DefaultValue"),_E(IE,"DefaultValue");var DE=Object.defineProperty,LE=g(((e,t)=>DE(e,"name",{value:t,configurable:!0})),"__name$x");const AE=X("SchemaContext");function ME(e){if(!e.fetcher)throw new TypeError("The `SchemaContextProvider` component requires a `fetcher` function to be passed as prop.");const{initialHeaders:n,headerEditor:i}=oS({nonNull:!0,caller:ME}),[o,a]=(0,t.useState)(),[s,l]=(0,t.useState)(!1),[u,c]=(0,t.useState)(null),d=(0,t.useRef)(0);(0,t.useEffect)((()=>{a((0,r.isSchema)(e.schema)||null===e.schema||void 0===e.schema?e.schema:void 0),d.current++}),[e.schema]);const f=(0,t.useRef)(n);(0,t.useEffect)((()=>{i&&(f.current=i.getValue())}));const{introspectionQuery:p,introspectionQueryName:h,introspectionQuerySansSubscriptions:m}=FE({inputValueDeprecation:e.inputValueDeprecation,introspectionQueryName:e.introspectionQueryName,schemaDescription:e.schemaDescription}),{fetcher:v,onSchemaChange:y,dangerouslyAssumeSchemaIsValid:b,children:E}=e,w=(0,t.useCallback)((()=>{if((0,r.isSchema)(e.schema)||null===e.schema)return;const t=++d.current,n=e.schema;async function i(){if(n)return n;const e=PE(f.current);if(!e.isValidJSON)return void c("Introspection failed as headers are invalid.");const t=e.headers?{headers:e.headers}:{},r=k(v({query:p,operationName:h},t));if(!T(r))return void c("Fetcher did not return a Promise for introspection.");l(!0),c(null);let i=await r;if("object"!=typeof i||null===i||!("data"in i)){const e=k(v({query:m,operationName:h},t));if(!T(e))throw new Error("Fetcher did not return a Promise for introspection.");i=await e}if(l(!1),(null==i?void 0:i.data)&&"__schema"in i.data)return i.data;const o="string"==typeof i?i:L(i);c(o)}g(i,"fetchIntrospectionData"),LE(i,"fetchIntrospectionData"),i().then((e=>{if(t===d.current&&e)try{const t=(0,r.buildClientSchema)(e);a(t),null==y||y(t)}catch(e){c(D(e))}})).catch((e=>{t===d.current&&(c(D(e)),l(!1))}))}),[v,h,p,m,y,e.schema]);(0,t.useEffect)((()=>{w()}),[w]),(0,t.useEffect)((()=>{function e(e){e.ctrlKey&&"R"===e.key&&w()}return g(e,"triggerIntrospection"),LE(e,"triggerIntrospection"),window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)}));const C=(0,t.useMemo)((()=>!o||b?[]:(0,r.validateSchema)(o)),[o,b]),S=(0,t.useMemo)((()=>({fetchError:u,introspect:w,isFetching:s,schema:o,validationErrors:C})),[u,w,s,o,C]);return de(AE.Provider,{value:S,children:E})}e.a4=AE,g(ME,"SchemaContextProvider"),LE(ME,"SchemaContextProvider");const RE=Y(AE);function FE(e){let{inputValueDeprecation:n,introspectionQueryName:i,schemaDescription:o}=e;return(0,t.useMemo)((()=>{const e=i||"IntrospectionQuery";let t=(0,r.getIntrospectionQuery)({inputValueDeprecation:n,schemaDescription:o});i&&(t=t.replace("query IntrospectionQuery",`query ${e}`));const a=t.replace("subscriptionType { name }","");return{introspectionQueryName:e,introspectionQuery:t,introspectionQuerySansSubscriptions:a}}),[n,i,o])}function PE(e){let t=null,n=!0;try{e&&(t=JSON.parse(e))}catch{n=!1}return{headers:t,isValidJSON:n}}e.a6=RE,g(FE,"useIntrospectionQuery"),LE(FE,"useIntrospectionQuery"),g(PE,"parseHeaderString"),LE(PE,"parseHeaderString");var jE=Object.defineProperty,VE=g(((e,t)=>jE(e,"name",{value:t,configurable:!0})),"__name$w");const UE={name:"Docs"},BE=X("ExplorerContext");function $E(e){const{schema:n,validationErrors:i}=RE({nonNull:!0,caller:$E}),[o,a]=(0,t.useState)([UE]),s=(0,t.useCallback)((e=>{a((t=>t.at(-1).def===e.def?t:[...t,e]))}),[]),l=(0,t.useCallback)((()=>{a((e=>e.length>1?e.slice(0,-1):e))}),[]),u=(0,t.useCallback)((()=>{a((e=>1===e.length?e:[UE]))}),[]);(0,t.useEffect)((()=>{null==n||i.length>0?u():a((e=>{if(1===e.length)return e;const t=[UE];let i=null;for(const o of e)if(o!==UE)if(o.def)if((0,r.isNamedType)(o.def)){const e=n.getType(o.def.name);if(!e)break;t.push({name:o.name,def:e}),i=e}else{if(null===i)break;if((0,r.isObjectType)(i)||(0,r.isInputObjectType)(i)){const e=i.getFields()[o.name];if(!e)break;t.push({name:o.name,def:e})}else{if((0,r.isScalarType)(i)||(0,r.isEnumType)(i)||(0,r.isInterfaceType)(i)||(0,r.isUnionType)(i))break;{const e=i;if(!e.args.find((e=>e.name===o.name)))break;t.push({name:o.name,def:e})}}}else i=null,t.push(o);return t}))}),[u,n,i]);const c=(0,t.useMemo)((()=>({explorerNavStack:o,push:s,pop:l,reset:u})),[o,s,l,u]);return de(BE.Provider,{value:c,children:e.children})}e.z=BE,g($E,"ExplorerContextProvider"),VE($E,"ExplorerContextProvider");const qE=Y(BE);e.U=qE;var HE=Object.defineProperty,GE=g(((e,t)=>HE(e,"name",{value:t,configurable:!0})),"__name$v");function zE(e,t){return(0,r.isNonNullType)(e)?fe(pe,{children:[zE(e.ofType,t),"!"]}):(0,r.isListType)(e)?fe(pe,{children:["[",zE(e.ofType,t),"]"]}):t(e)}g(zE,"renderType"),GE(zE,"renderType");var WE=Object.defineProperty,KE=g(((e,t)=>WE(e,"name",{value:t,configurable:!0})),"__name$u");function QE(e){const{push:t}=qE({nonNull:!0,caller:QE});return e.type?zE(e.type,(e=>de("a",{className:"graphiql-doc-explorer-type-name",onClick:n=>{n.preventDefault(),t({name:e.name,def:e})},href:"#",children:e.name}))):null}g(QE,"TypeLink"),KE(QE,"TypeLink");var XE=Object.defineProperty,YE=g(((e,t)=>XE(e,"name",{value:t,configurable:!0})),"__name$t");function JE(e){let{arg:t,showDefaultValue:n,inline:r}=e;const i=fe("span",{children:[de("span",{className:"graphiql-doc-explorer-argument-name",children:t.name}),": ",de(QE,{type:t.type}),!1!==n&&de(IE,{field:t})]});return r?i:fe("div",{className:"graphiql-doc-explorer-argument",children:[i,t.description?de(rb,{type:"description",children:t.description}):null,t.deprecationReason?fe("div",{className:"graphiql-doc-explorer-argument-deprecation",children:[de("div",{className:"graphiql-doc-explorer-argument-deprecation-label",children:"Deprecated"}),de(rb,{type:"deprecation",children:t.deprecationReason})]}):null]})}g(JE,"Argument"),YE(JE,"Argument");var ZE=Object.defineProperty,eT=g(((e,t)=>ZE(e,"name",{value:t,configurable:!0})),"__name$s");function tT(e){return e.children?fe("div",{className:"graphiql-doc-explorer-deprecation",children:[de("div",{className:"graphiql-doc-explorer-deprecation-label",children:"Deprecated"}),de(rb,{type:"deprecation",onlyShowFirstChild:!0,children:e.children})]}):null}g(tT,"DeprecationReason"),eT(tT,"DeprecationReason");var nT=Object.defineProperty,rT=g(((e,t)=>nT(e,"name",{value:t,configurable:!0})),"__name$r");function iT(e){let{directive:t}=e;return fe("span",{className:"graphiql-doc-explorer-directive",children:["@",t.name.value]})}g(iT,"Directive"),rT(iT,"Directive");var oT=Object.defineProperty,aT=g(((e,t)=>oT(e,"name",{value:t,configurable:!0})),"__name$q");function sT(e){const t=lT[e.title];return fe("div",{children:[fe("div",{className:"graphiql-doc-explorer-section-title",children:[de(t,{}),e.title]}),de("div",{className:"graphiql-doc-explorer-section-content",children:e.children})]})}g(sT,"ExplorerSection"),aT(sT,"ExplorerSection");const lT={Arguments:_a,"Deprecated Arguments":Ma,"Deprecated Enum Values":Ra,"Deprecated Fields":Fa,Directives:Pa,"Enum Values":Ua,Fields:Ba,Implements:qa,Implementations:rs,"Possible Types":rs,"Root Types":Ja,Type:rs,"All Schema Types":rs};var uT=Object.defineProperty,cT=g(((e,t)=>uT(e,"name",{value:t,configurable:!0})),"__name$p");function dT(e){return fe(pe,{children:[e.field.description?de(rb,{type:"description",children:e.field.description}):null,de(tT,{children:e.field.deprecationReason}),de(sT,{title:"Type",children:de(QE,{type:e.field.type})}),de(fT,{field:e.field}),de(pT,{field:e.field})]})}function fT(e){let{field:n}=e;const[r,i]=(0,t.useState)(!1);if(!("args"in n))return null;const o=[],a=[];for(const e of n.args)e.deprecationReason?a.push(e):o.push(e);return fe(pe,{children:[o.length>0?de(sT,{title:"Arguments",children:o.map((e=>de(JE,{arg:e},e.name)))}):null,a.length>0?r||0===o.length?de(sT,{title:"Deprecated Arguments",children:a.map((e=>de(JE,{arg:e},e.name)))}):de(as,{type:"button",onClick:()=>{i(!0)},children:"Show Deprecated Arguments"}):null]})}function pT(e){let{field:t}=e;var n;const r=(null==(n=t.astNode)?void 0:n.directives)||[];return r&&0!==r.length?de(sT,{title:"Directives",children:r.map((e=>de("div",{children:de(iT,{directive:e})},e.name.value)))}):null}g(dT,"FieldDocumentation"),cT(dT,"FieldDocumentation"),g(fT,"Arguments"),cT(fT,"Arguments"),g(pT,"Directives"),cT(pT,"Directives");var hT=Object.defineProperty,mT=g(((e,t)=>hT(e,"name",{value:t,configurable:!0})),"__name$o");function gT(e){var t,n,r,i;const o=e.schema.getQueryType(),a=null==(n=(t=e.schema).getMutationType)?void 0:n.call(t),s=null==(i=(r=e.schema).getSubscriptionType)?void 0:i.call(r),l=e.schema.getTypeMap(),u=[null==o?void 0:o.name,null==a?void 0:a.name,null==s?void 0:s.name];return fe(pe,{children:[de(rb,{type:"description",children:e.schema.description||"A GraphQL schema provides a root type for each kind of operation."}),fe(sT,{title:"Root Types",children:[o?fe("div",{children:[de("span",{className:"graphiql-doc-explorer-root-type",children:"query"}),": ",de(QE,{type:o})]}):null,a&&fe("div",{children:[de("span",{className:"graphiql-doc-explorer-root-type",children:"mutation"}),": ",de(QE,{type:a})]}),s&&fe("div",{children:[de("span",{className:"graphiql-doc-explorer-root-type",children:"subscription"}),": ",de(QE,{type:s})]})]}),de(sT,{title:"All Schema Types",children:l&&de("div",{children:Object.values(l).map((e=>u.includes(e.name)||e.name.startsWith("__")?null:de("div",{children:de(QE,{type:e})},e.name)))})})]})}function vT(e,n){var r=(0,t.useRef)(!1);(0,t.useEffect)((function(){r.current?e():r.current=!0}),n)}function yT(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function bT(){return bT=Object.assign||function(e){for(var t=1;tl&&e.push({highlight:!1,start:l,end:u}),o.index===s.lastIndex&&s.lastIndex++}return e}),[])}function CT(e){var t=e.chunksToHighlight,n=e.totalLength,r=[];if(0===t.length)o(0,n,!1);else{var i=0;t.forEach((function(e){o(i,e.start,!1),o(e.start,e.end,!0),i=e.end})),o(i,n,!1)}return r;function o(e,t,n){t-e>0&&r.push({start:e,end:t,highlight:n})}}function ST(e){return e}function xT(e){return e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&")}g(gT,"SchemaDocumentation"),mT(gT,"SchemaDocumentation"),g(vT,"useUpdateEffect"),g(yT,"_objectWithoutPropertiesLoose"),g(bT,"_extends"),g(ET,"findAll"),g(TT,"combineChunks"),g(wT,"defaultFindChunks"),g(CT,"fillInChunks"),g(ST,"defaultSanitize"),g(xT,"escapeRegExpFn");var kT,NT,_T,OT,IT,DT={combineChunks:TT,fillInChunks:CT,findAll:ET,findChunks:wT},LT=["onSelect","openOnFocus","children","as","aria-label","aria-labelledby"],AT=["as","selectOnClick","autocomplete","onClick","onChange","onKeyDown","onBlur","onFocus","value"],MT=["as","children","portal","onKeyDown","onBlur","position"],RT=["persistSelection","as"],FT=["as","children","index","value","onClick"],PT="IDLE",jT="SUGGESTING",VT="NAVIGATING",UT="INTERACTING",BT="CLEAR",$T="CHANGE",qT="INITIAL_CHANGE",HT="NAVIGATE",GT="SELECT_WITH_KEYBOARD",zT="SELECT_WITH_CLICK",WT="ESCAPE",KT="BLUR",QT="INTERACT",XT="FOCUS",YT="OPEN_WITH_BUTTON",JT="OPEN_WITH_INPUT_CLICK",ZT="CLOSE_WITH_BUTTON",ew={initial:PT,states:(IT={},IT[PT]={on:(kT={},kT[KT]=PT,kT[BT]=PT,kT[$T]=jT,kT[qT]=PT,kT[XT]=jT,kT[HT]=VT,kT[YT]=jT,kT[JT]=jT,kT)},IT[jT]={on:(NT={},NT[$T]=jT,NT[XT]=jT,NT[HT]=VT,NT[BT]=PT,NT[WT]=PT,NT[KT]=PT,NT[zT]=PT,NT[QT]=UT,NT[ZT]=PT,NT)},IT[VT]={on:(_T={},_T[$T]=jT,_T[XT]=jT,_T[BT]=PT,_T[KT]=PT,_T[WT]=PT,_T[HT]=VT,_T[zT]=PT,_T[GT]=PT,_T[ZT]=PT,_T[QT]=UT,_T)},IT[UT]={on:(OT={},OT[BT]=PT,OT[$T]=jT,OT[XT]=jT,OT[KT]=PT,OT[WT]=PT,OT[HT]=VT,OT[ZT]=PT,OT[zT]=PT,OT)},IT)},tw=g((function(e,t){var n=bT({},e,{lastEventType:t.type});switch(t.type){case $T:case qT:return bT({},n,{navigationValue:null,value:t.value});case HT:case YT:case JT:return bT({},n,{navigationValue:rw(n,t)});case BT:return bT({},n,{value:"",navigationValue:null});case KT:case WT:return bT({},n,{navigationValue:null});case zT:return bT({},n,{value:t.isControlled?e.value:t.value,navigationValue:null});case GT:return bT({},n,{value:t.isControlled?e.value:e.navigationValue,navigationValue:null});case ZT:return bT({},n,{navigationValue:null});case QT:return n;case XT:return bT({},n,{navigationValue:rw(n,t)});default:return n}}),"reducer");function nw(e){return[jT,VT,UT].includes(e)}function rw(e,t){return t.value?t.value:t.persistSelection?e.value:null}g(nw,"popoverIsExpanded"),g(rw,"findNavigationValue");var iw=zd(),ow=af(0,{}),aw=af(0,{}),sw=(0,t.forwardRef)((function(e,n){var r,i=e.onSelect,o=e.openOnFocus,a=void 0!==o&&o,s=e.children,l=e.as,u=void 0===l?"div":l,c=e["aria-label"],d=e["aria-labelledby"],f=yT(e,LT),p=Kd(),h=p[0],m=p[1],g=(0,t.useRef)(),v=(0,t.useRef)(),y=(0,t.useRef)(),b=(0,t.useRef)(!1),E=(0,t.useRef)(!1),T=gw(ew,tw,{value:"",navigationValue:null}),w=T[0],C=T[1],S=T[2];pw(C.lastEventType,g);var x=rd(f.id),k=x?lf("listbox",x):"listbox",N=(0,t.useRef)(!1),_=nw(w),O={ariaLabel:c,ariaLabelledby:d,autocompletePropRef:b,buttonRef:y,comboboxId:x,data:C,inputRef:g,isExpanded:_,listboxId:k,onSelect:i||bs,openOnFocus:a,persistSelectionRef:E,popoverRef:v,state:w,transition:S,isControlledRef:N};return(0,t.createElement)(Xd,{context:iw,items:h,set:m},(0,t.createElement)(ow.Provider,{value:O},(0,t.createElement)(u,bT({},f,{"data-reach-combobox":"","data-state":yw(w),"data-expanded":_||void 0,ref:n}),vs(s)?s({id:x,isExpanded:_,navigationValue:null!=(r=C.navigationValue)?r:null,state:w}):s)))})),lw=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"input":r,o=e.selectOnClick,a=void 0!==o&&o,s=e.autocomplete,l=void 0===s||s,u=e.onClick,c=e.onChange,d=e.onKeyDown,f=e.onBlur,p=e.onFocus,h=e.value,m=yT(e,AT),v=(0,t.useRef)(h).current,y=(0,t.useRef)(!1);vT((function(){y.current=!0}),[h]);var b=(0,t.useContext)(ow),E=b.data,T=E.navigationValue,w=E.value,C=E.lastEventType,S=b.inputRef,x=b.state,k=b.transition,N=b.listboxId,_=b.autocompletePropRef,O=b.openOnFocus,I=b.isExpanded,D=b.ariaLabel,L=b.ariaLabelledby,A=b.persistSelectionRef,M=b.isControlledRef,R=Ss(S,n),F=(0,t.useRef)(!1),P=hw(),j=mw(),V=void 0!==h;(0,t.useEffect)((function(){M.current=V}),[V]),us((function(){_.current=l}),[l,_]);var U=(0,t.useCallback)((function(e){""===e.trim()?k(BT,{isControlled:V}):e!==v||y.current?k($T,{value:e}):k(qT,{value:e})}),[v,k,V]);function B(e){var t=e.target.value;V||U(t)}function $(){a&&(F.current=!0),O&&C!==zT&&k(XT,{persistSelection:A.current})}function q(){var e;F.current&&(F.current=!1,null==(e=S.current)||e.select()),O&&x===PT&&k(JT)}(0,t.useEffect)((function(){!V||h===w||""===h.trim()&&""===(w||"").trim()||U(h)}),[h,U,V,w]),g(B,"handleChange"),g($,"handleFocus"),g(q,"handleClick");var H=!l||x!==VT&&x!==UT?h||w:T||h||w;return(0,t.createElement)(i,bT({"aria-activedescendant":T?String(vw(T)):void 0,"aria-autocomplete":"both","aria-controls":N,"aria-expanded":I,"aria-haspopup":"listbox","aria-label":D,"aria-labelledby":D?void 0:L,role:"combobox"},m,{"data-reach-combobox-input":"","data-state":yw(x),ref:R,onBlur:xs(f,j),onChange:xs(c,B),onClick:xs(u,q),onFocus:xs(p,$),onKeyDown:xs(d,P),value:H||""}))})),uw=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"div":r,o=e.children,a=e.portal,s=void 0===a||a,l=e.onKeyDown,u=e.onBlur,c=e.position,d=void 0===c?Ud:c,f=yT(e,MT),p=(0,t.useContext)(ow),h=p.popoverRef,m=p.inputRef,g=p.isExpanded,v=p.state,y=Ss(h,n),b=hw(),E=mw(),T={"data-reach-combobox-popover":"","data-state":yw(v),onKeyDown:xs(l,b),onBlur:xs(u,E),hidden:!g,tabIndex:-1,children:o};return s?(0,t.createElement)(Rd,bT({as:i},f,{ref:y,"data-expanded":g||void 0,position:d,targetRef:m,unstable_skipInitialPortalRender:!0},T)):(0,t.createElement)(i,bT({ref:y},f,T))})),cw=(0,t.forwardRef)((function(e,n){var r=e.persistSelection,i=void 0!==r&&r,o=e.as,a=void 0===o?"ul":o,s=yT(e,RT),l=(0,t.useContext)(ow),u=l.persistSelectionRef,c=l.listboxId;return i&&(u.current=!0),(0,t.createElement)(a,bT({role:"listbox"},s,{ref:n,"data-reach-combobox-list":"",id:c}))})),dw=(0,t.forwardRef)((function(e,n){var r=e.as,i=void 0===r?"li":r,o=e.children,a=e.index,s=e.value,l=e.onClick,u=yT(e,FT),c=(0,t.useContext)(ow),d=c.onSelect,f=c.data.navigationValue,p=c.transition,h=c.isControlledRef,m=uf((0,t.useRef)(null),null),v=m[0],y=m[1],b=Wd((0,t.useMemo)((function(){return{element:v,value:s}}),[s,v]),iw,a),E=Ss(n,y),T=f===s,w=g((function(){d&&d(s),p(zT,{value:s,isControlled:h.current})}),"handleClick");return(0,t.createElement)(aw.Provider,{value:{value:s,index:b}},(0,t.createElement)(i,bT({"aria-selected":T,role:"option"},u,{"data-reach-combobox-option":"",ref:E,id:String(vw(s)),"data-highlighted":T?"":void 0,tabIndex:-1,onClick:xs(l,w)}),o?vs(o)?o({value:s,index:b}):o:(0,t.createElement)(fw,null)))}));function fw(){var e=(0,t.useContext)(aw).value,n=(0,t.useContext)(ow).data.value,r=(0,t.useMemo)((function(){return DT.findAll({searchWords:bw(n||"").split(/\s+/),textToHighlight:e})}),[n,e]);return(0,t.createElement)(t.Fragment,null,r.length?r.map((function(n,r){var i=e.slice(n.start,n.end);return(0,t.createElement)("span",{key:r,"data-reach-combobox-option-text":"","data-user-value":!!n.highlight||void 0,"data-suggested-value":!n.highlight||void 0},i)})):e)}function pw(e,t){us((function(){var n;e!==HT&&e!==WT&&e!==zT&&e!==YT||null==(n=t.current)||n.focus()}),[t,e])}function hw(){var e=(0,t.useContext)(ow),n=e.data.navigationValue,r=e.onSelect,i=e.state,o=e.transition,a=e.autocompletePropRef,s=e.persistSelectionRef,l=e.isControlledRef,u=Qd(iw);return g((function(e){var t=u.findIndex((function(e){return e.value===n}));function c(){return t===u.length-1?a.current?null:f():u[(t+1)%u.length]}function d(){return 0===t?a.current?null:p():-1===t?p():u[(t-1+u.length)%u.length]}function f(){return u[0]}function p(){return u[u.length-1]}switch(g(c,"getNextOption"),g(d,"getPreviousOption"),g(f,"getFirstOption"),g(p,"getLastOption"),e.key){case"ArrowDown":if(e.preventDefault(),!u||!u.length)return;if(i===PT)o(HT,{persistSelection:s.current});else{var h=c();o(HT,{value:h?h.value:null})}break;case"ArrowUp":if(e.preventDefault(),!u||0===u.length)return;if(i===PT)o(HT);else{var m=d();o(HT,{value:m?m.value:null})}break;case"Home":case"PageUp":if(e.preventDefault(),!u||0===u.length)return;i===PT?o(HT):o(HT,{value:f().value});break;case"End":case"PageDown":if(e.preventDefault(),!u||0===u.length)return;i===PT?o(HT):o(HT,{value:p().value});break;case"Escape":i!==PT&&o(WT);break;case"Enter":i===VT&&null!==n&&(e.preventDefault(),r&&r(n),o(GT,{isControlled:l.current}))}}),"handleKeyDown")}function mw(){var e=(0,t.useContext)(ow),n=e.state,r=e.transition,i=e.popoverRef,o=e.inputRef,a=e.buttonRef;return g((function(e){var t=i.current,s=o.current,l=a.current,u=e.relatedTarget;u!==s&&u!==l&&t&&(t.contains(u)?n!==UT&&r(QT):r(KT))}),"handleBlur")}function gw(e,n,r){var i=(0,t.useState)(e.initial),o=i[0],a=i[1],s=(0,t.useReducer)(n,r),l=s[0],u=s[1];return[o,l,g((function(t,n){void 0===n&&(n={});var r=e.states[o],i=r&&r.on[t];if(i)return u(bT({type:t,state:o,nextState:o},n)),void a(i)}),"transition")]}function vw(e){var t=0;if(0===e.length)return t;for(var n=0;nEw(e,"name",{value:t,configurable:!0})),"__name$n");function ww(e,t){let n;return function(){for(var r=arguments.length,i=new Array(r),o=0;o{n=null,t(...i)}),e)}}g(ww,"debounce"),Tw(ww,"debounce");var Cw=Object.defineProperty,Sw=g(((e,t)=>Cw(e,"name",{value:t,configurable:!0})),"__name$m");function xw(){const{explorerNavStack:e,push:n}=qE({nonNull:!0,caller:xw}),i=(0,t.useRef)(null),o=(0,t.useRef)(null),a=kw(),[s,l]=(0,t.useState)(""),[u,c]=(0,t.useState)(a(s)),d=(0,t.useMemo)((()=>ww(200,(e=>{c(a(e))}))),[a]);(0,t.useEffect)((()=>{d(s)}),[d,s]),(0,t.useEffect)((()=>{function e(e){var t;e.metaKey&&"k"===e.key&&(null==(t=i.current)||t.focus())}return g(e,"handleKeyDown"),Sw(e,"handleKeyDown"),window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)}),[]);const f=e.at(-1);return 1===e.length||(0,r.isObjectType)(f.def)||(0,r.isInterfaceType)(f.def)||(0,r.isInputObjectType)(f.def)?fe(sw,{"aria-label":`Search ${f.name}...`,onSelect:e=>{const t=e;n("field"in t?{name:t.field.name,def:t.field}:{name:t.type.name,def:t.type})},children:[fe("div",{className:"graphiql-doc-explorer-search-input",onClick:()=>{i.current&&i.current.focus()},children:[de(Ga,{}),de(lw,{autocomplete:!1,onChange:e=>{l(e.target.value)},onKeyDown:e=>{if(!e.isDefaultPrevented()){const e=o.current;if(!e)return;window.requestAnimationFrame((()=>{const t=e.querySelector("[aria-selected=true]");if(!(t instanceof HTMLElement))return;const n=t.offsetTop-e.scrollTop,r=e.scrollTop+e.clientHeight-(t.offsetTop+t.clientHeight);r<0&&(e.scrollTop-=r),n<0&&(e.scrollTop+=n)}))}e.stopPropagation()},placeholder:"⌘ K",ref:i,value:s})]}),de(uw,{portal:!1,ref:o,children:fe(cw,{children:[u.within.map(((e,t)=>de(dw,{index:t,value:e,children:de(Ow,{field:e.field,argument:e.argument})},`within-${t}`))),u.within.length>0&&u.types.length+u.fields.length>0?de("div",{className:"graphiql-doc-explorer-search-divider",children:"Other results"}):null,u.types.map(((e,t)=>de(dw,{index:u.within.length+t,value:e,children:de(_w,{type:e.type})},`type-${t}`))),u.fields.map(((e,t)=>fe(dw,{index:u.within.length+u.types.length+t,value:e,children:[de(_w,{type:e.type}),".",de(Ow,{field:e.field,argument:e.argument})]},`field-${t}`))),u.within.length+u.types.length+u.fields.length===0?de("div",{className:"graphiql-doc-explorer-search-empty",children:"No results found"}):null]})})]}):null}function kw(e){const{explorerNavStack:n}=qE({nonNull:!0,caller:e||kw}),{schema:i}=RE({nonNull:!0,caller:e||kw}),o=n.at(-1);return(0,t.useCallback)((e=>{const t={within:[],types:[],fields:[]};if(!i)return t;const n=o.def,a=i.getTypeMap();let s=Object.keys(a);n&&(s=s.filter((e=>e!==n.name)),s.unshift(n.name));for(const i of s){if(t.within.length+t.types.length+t.fields.length>=100)break;const o=a[i];if(n!==o&&Nw(i,e)&&t.types.push({type:o}),!(0,r.isObjectType)(o)&&!(0,r.isInterfaceType)(o)&&!(0,r.isInputObjectType)(o))continue;const s=o.getFields();for(const r in s){const i=s[r];let a;if(!Nw(r,e)){if(!("args"in i))continue;if(a=i.args.filter((t=>Nw(t.name,e))),0===a.length)continue}t[n===o?"within":"fields"].push(...a?a.map((e=>({type:o,field:i,argument:e}))):[{type:o,field:i}])}}return t}),[o.def,i])}function Nw(e,t){try{const n=t.replaceAll(/[^_0-9A-Za-z]/g,(e=>"\\"+e));return-1!==e.search(new RegExp(n,"i"))}catch{return e.toLowerCase().includes(t.toLowerCase())}}function _w(e){return de("span",{className:"graphiql-doc-explorer-search-type",children:e.type.name})}function Ow(e){return fe(pe,{children:[de("span",{className:"graphiql-doc-explorer-search-field",children:e.field.name}),e.argument?fe(pe,{children:["(",de("span",{className:"graphiql-doc-explorer-search-argument",children:e.argument.name}),":"," ",zE(e.argument.type,(e=>de(_w,{type:e}))),")"]}):null]})}g(xw,"Search"),Sw(xw,"Search"),g(kw,"useSearchResults"),Sw(kw,"useSearchResults"),g(Nw,"isMatch"),Sw(Nw,"isMatch"),g(_w,"Type"),Sw(_w,"Type"),g(Ow,"Field$1"),Sw(Ow,"Field");var Iw=Object.defineProperty,Dw=g(((e,t)=>Iw(e,"name",{value:t,configurable:!0})),"__name$l");function Lw(e){const{push:t}=qE({nonNull:!0});return de("a",{className:"graphiql-doc-explorer-field-name",onClick:n=>{n.preventDefault(),t({name:e.field.name,def:e.field})},href:"#",children:e.field.name})}g(Lw,"FieldLink"),Dw(Lw,"FieldLink");var Aw=Object.defineProperty,Mw=g(((e,t)=>Aw(e,"name",{value:t,configurable:!0})),"__name$k");function Rw(e){return(0,r.isNamedType)(e.type)?fe(pe,{children:[e.type.description?de(rb,{type:"description",children:e.type.description}):null,de(Fw,{type:e.type}),de(Pw,{type:e.type}),de(Vw,{type:e.type}),de(Bw,{type:e.type})]}):null}function Fw(e){let{type:t}=e;return(0,r.isObjectType)(t)&&t.getInterfaces().length>0?de(sT,{title:"Implements",children:t.getInterfaces().map((e=>de("div",{children:de(QE,{type:e})},e.name)))}):null}function Pw(e){let{type:n}=e;const[i,o]=(0,t.useState)(!1);if(!(0,r.isObjectType)(n)&&!(0,r.isInterfaceType)(n)&&!(0,r.isInputObjectType)(n))return null;const a=n.getFields(),s=[],l=[];for(const e of Object.keys(a).map((e=>a[e])))e.deprecationReason?l.push(e):s.push(e);return fe(pe,{children:[s.length>0?de(sT,{title:"Fields",children:s.map((e=>de(jw,{field:e},e.name)))}):null,l.length>0?i||0===s.length?de(sT,{title:"Deprecated Fields",children:l.map((e=>de(jw,{field:e},e.name)))}):de(as,{type:"button",onClick:()=>{o(!0)},children:"Show Deprecated Fields"}):null]})}function jw(e){let{field:t}=e;const n="args"in t?t.args.filter((e=>!e.deprecationReason)):[];return fe("div",{className:"graphiql-doc-explorer-item",children:[fe("div",{children:[de(Lw,{field:t}),n.length>0?fe(pe,{children:["(",de("span",{children:n.map((e=>1===n.length?de(JE,{arg:e,inline:!0},e.name):de("div",{className:"graphiql-doc-explorer-argument-multiple",children:de(JE,{arg:e,inline:!0})},e.name)))}),")"]}):null,": ",de(QE,{type:t.type}),de(IE,{field:t})]}),t.description?de(rb,{type:"description",onlyShowFirstChild:!0,children:t.description}):null,de(tT,{children:t.deprecationReason})]})}function Vw(e){let{type:n}=e;const[i,o]=(0,t.useState)(!1);if(!(0,r.isEnumType)(n))return null;const a=[],s=[];for(const e of n.getValues())e.deprecationReason?s.push(e):a.push(e);return fe(pe,{children:[a.length>0?de(sT,{title:"Enum Values",children:a.map((e=>de(Uw,{value:e},e.name)))}):null,s.length>0?i||0===a.length?de(sT,{title:"Deprecated Enum Values",children:s.map((e=>de(Uw,{value:e},e.name)))}):de(as,{type:"button",onClick:()=>{o(!0)},children:"Show Deprecated Values"}):null]})}function Uw(e){let{value:t}=e;return fe("div",{className:"graphiql-doc-explorer-item",children:[de("div",{className:"graphiql-doc-explorer-enum-value",children:t.name}),t.description?de(rb,{type:"description",children:t.description}):null,t.deprecationReason?de(rb,{type:"deprecation",children:t.deprecationReason}):null]})}function Bw(e){let{type:t}=e;const{schema:n}=RE({nonNull:!0});return n&&(0,r.isAbstractType)(t)?de(sT,{title:(0,r.isInterfaceType)(t)?"Implementations":"Possible Types",children:n.getPossibleTypes(t).map((e=>de("div",{children:de(QE,{type:e})},e.name)))}):null}g(Rw,"TypeDocumentation"),Mw(Rw,"TypeDocumentation"),g(Fw,"ImplementsInterfaces"),Mw(Fw,"ImplementsInterfaces"),g(Pw,"Fields"),Mw(Pw,"Fields"),g(jw,"Field"),Mw(jw,"Field"),g(Vw,"EnumValues"),Mw(Vw,"EnumValues"),g(Uw,"EnumValue"),Mw(Uw,"EnumValue"),g(Bw,"PossibleTypes"),Mw(Bw,"PossibleTypes");var $w=Object.defineProperty,qw=g(((e,t)=>$w(e,"name",{value:t,configurable:!0})),"__name$j");function Hw(){const{fetchError:e,isFetching:t,schema:n,validationErrors:i}=RE({nonNull:!0,caller:Hw}),{explorerNavStack:o,pop:a}=qE({nonNull:!0,caller:Hw}),s=o.at(-1);let l,u=null;return e?u=de("div",{className:"graphiql-doc-explorer-error",children:"Error fetching schema"}):i.length>0?u=fe("div",{className:"graphiql-doc-explorer-error",children:["Schema is invalid: ",i[0].message]}):t?u=de(ib,{}):n?1===o.length?u=de(gT,{schema:n}):(0,r.isType)(s.def)?u=de(Rw,{type:s.def}):s.def&&(u=de(dT,{field:s.def})):u=de("div",{className:"graphiql-doc-explorer-error",children:"No GraphQL schema available"}),o.length>1&&(l=o.at(-2).name),fe("section",{className:"graphiql-doc-explorer","aria-label":"Documentation Explorer",children:[fe("div",{className:"graphiql-doc-explorer-header",children:[fe("div",{className:"graphiql-doc-explorer-header-content",children:[l&&fe("a",{href:"#",className:"graphiql-doc-explorer-back",onClick:e=>{e.preventDefault(),a()},"aria-label":`Go back to ${l}`,children:[de(Ia,{}),l]}),de("div",{className:"graphiql-doc-explorer-title",children:s.name})]}),de("div",{className:"graphiql-doc-explorer-search",children:de(xw,{},s.name)})]}),de("div",{className:"graphiql-doc-explorer-content",children:u})]})}g(Hw,"DocExplorer"),qw(Hw,"DocExplorer");var Gw=Object.defineProperty,zw=g(((e,t)=>Gw(e,"name",{value:t,configurable:!0})),"__name$i");const Ww={title:"Documentation Explorer",icon:zw(g((function(){const e=Yw();return(null==e?void 0:e.visiblePlugin)===Ww?de(ja,{}):de(Va,{})}),"Icon"),"Icon"),content:Hw};e._=Ww;const Kw={title:"History",icon:$a,content:oE};e.$=Kw;const Qw=X("PluginContext");function Xw(e){const n=ye(),r=qE(),i=tE(),o=Boolean(r),a=Boolean(i),s=(0,t.useMemo)((()=>{const t=[],n={};o&&(t.push(Ww),n[Ww.title]=!0),a&&(t.push(Kw),n[Kw.title]=!0);for(const r of e.plugins||[]){if("string"!=typeof r.title||!r.title)throw new Error("All GraphiQL plugins must have a unique title");if(n[r.title])throw new Error(`All GraphiQL plugins must have a unique title, found two plugins with the title '${r.title}'`);t.push(r),n[r.title]=!0}return t}),[o,a,e.plugins]),[l,u]=(0,t.useState)((()=>{const t=null==n?void 0:n.get(Jw);return s.find((e=>e.title===t))||(t&&(null==n||n.set(Jw,"")),e.visiblePlugin&&s.find((t=>("string"==typeof e.visiblePlugin?t.title:t)===e.visiblePlugin))||null)})),{onTogglePluginVisibility:c,children:d}=e,f=(0,t.useCallback)((e=>{const t=e&&s.find((t=>("string"==typeof e?t.title:t)===e))||null;u((e=>t===e?e:(null==c||c(t),t)))}),[c,s]);(0,t.useEffect)((()=>{e.visiblePlugin&&f(e.visiblePlugin)}),[s,e.visiblePlugin,f]);const p=(0,t.useMemo)((()=>({plugins:s,setVisiblePlugin:f,visiblePlugin:l})),[s,f,l]);return de(Qw.Provider,{value:p,children:d})}e.a0=Qw,g(Xw,"PluginContextProvider"),zw(Xw,"PluginContextProvider");const Yw=Y(Qw);e.a2=Yw;const Jw="visiblePlugin";var Zw=Object.defineProperty,eC=g(((e,t)=>Zw(e,"name",{value:t,configurable:!0})),"__name$h");function tC(e,t,n,i,o,a){function s(e){if(!(n&&i&&o&&e.currentTarget instanceof HTMLElement))return;const t=e.currentTarget.innerText,r=n.getType(t);r&&(o.setVisiblePlugin(Ww),i.push({name:r.name,def:r}),null==a||a(r))}EE([],{useCommonAddons:!1}).then((e=>{let n,i,o,a,l,u,c,d,f;e.on(t,"select",((e,t)=>{if(!n){const e=t.parentNode;n=document.createElement("div"),n.className="CodeMirror-hint-information",e.append(n);const r=document.createElement("header");r.className="CodeMirror-hint-information-header",n.append(r),i=document.createElement("span"),i.className="CodeMirror-hint-information-field-name",r.append(i),o=document.createElement("span"),o.className="CodeMirror-hint-information-type-name-pill",r.append(o),a=document.createElement("span"),o.append(a),l=document.createElement("a"),l.className="CodeMirror-hint-information-type-name",l.href="javascript:void 0",l.addEventListener("click",s),o.append(l),u=document.createElement("span"),o.append(u),c=document.createElement("div"),c.className="CodeMirror-hint-information-description",n.append(c),d=document.createElement("div"),d.className="CodeMirror-hint-information-deprecation",n.append(d);const p=document.createElement("span");p.className="CodeMirror-hint-information-deprecation-label",p.innerText="Deprecated",d.append(p),f=document.createElement("div"),f.className="CodeMirror-hint-information-deprecation-reason",d.append(f);const h=parseInt(window.getComputedStyle(n).paddingBottom.replace(/px$/,""),10)||0,m=parseInt(window.getComputedStyle(n).maxHeight.replace(/px$/,""),10)||0,g=eC((()=>{n&&(n.style.paddingTop=e.scrollTop+h+"px",n.style.maxHeight=e.scrollTop+m+"px")}),"handleScroll");let v;e.addEventListener("scroll",g),e.addEventListener("DOMNodeRemoved",v=eC((t=>{t.target===e&&(e.removeEventListener("scroll",g),e.removeEventListener("DOMNodeRemoved",v),n&&n.removeEventListener("click",s),n=null,i=null,o=null,a=null,l=null,u=null,c=null,d=null,f=null,v=null)}),"onRemoveFn"))}if(i&&(i.innerText=e.text),o&&a&&l&&u)if(e.type){o.style.display="inline";const t=eC((e=>{(0,r.isNonNullType)(e)?(u.innerText="!"+u.innerText,t(e.ofType)):(0,r.isListType)(e)?(a.innerText+="[",u.innerText="]"+u.innerText,t(e.ofType)):l.innerText=e.name}),"renderType");a.innerText="",u.innerText="",t(e.type)}else a.innerText="",l.innerText="",u.innerText="",o.style.display="none";c&&(e.description?(c.style.display="block",c.innerHTML=nb.render(e.description)):(c.style.display="none",c.innerHTML="")),d&&f&&(e.deprecationReason?(d.style.display="block",f.innerHTML=nb.render(e.deprecationReason)):(d.style.display="none",f.innerHTML=""))}))})),g(s,"onClickHintInformation"),eC(s,"onClickHintInformation")}g(tC,"onHasCompletion"),eC(tC,"onHasCompletion");var nC=Object.defineProperty,rC=g(((e,t)=>nC(e,"name",{value:t,configurable:!0})),"__name$g");function iC(e,n){(0,t.useEffect)((()=>{e&&"string"==typeof n&&n!==e.getValue()&&e.setValue(n)}),[e,n])}function oC(e,n,r){(0,t.useEffect)((()=>{e&&e.setOption(n,r)}),[e,n,r])}function aC(e,n,r,i,o){const{updateActiveTabValues:a}=oS({nonNull:!0,caller:o}),s=ye();(0,t.useEffect)((()=>{if(!e)return;const t=ww(500,(e=>{s&&null!==r&&s.set(r,e)})),o=ww(100,(e=>{a({[i]:e})})),l=rC(((e,r)=>{if(!r)return;const i=e.getValue();t(i),o(i),null==n||n(i)}),"handleChange");return e.on("change",l),()=>e.off("change",l)}),[n,e,s,r,i,a])}function sC(e,n,r){const{schema:i}=RE({nonNull:!0,caller:r}),o=qE(),a=Yw();(0,t.useEffect)((()=>{if(!e)return;const t=rC(((e,t)=>{tC(0,t,i,o,a,(e=>{null==n||n({kind:"Type",type:e,schema:i||void 0})}))}),"handleCompletion");return e.on("hasCompletion",t),()=>e.off("hasCompletion",t)}),[n,e,o,a,i])}function lC(e,n,r){(0,t.useEffect)((()=>{if(e){for(const t of n)e.removeKeyMap(t);if(r){const t={};for(const e of n)t[e]=()=>r();e.addKeyMap(t)}}}),[e,n,r])}function uC(){let{caller:e,onCopyQuery:n}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{queryEditor:r}=oS({nonNull:!0,caller:e||uC});return(0,t.useCallback)((()=>{if(!r)return;const e=r.getValue();kE(e),null==n||n(e)}),[r,n])}function cC(){let{caller:e}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{queryEditor:n}=oS({nonNull:!0,caller:e||cC}),{schema:i}=RE({nonNull:!0,caller:cC});return(0,t.useCallback)((()=>{const e=null==n?void 0:n.documentAST,t=null==n?void 0:n.getValue();e&&t&&n.setValue((0,r.print)(B(e,i)))}),[n,i])}function dC(){let{caller:e}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{queryEditor:n,headerEditor:i,variableEditor:o}=oS({nonNull:!0,caller:e||dC});return(0,t.useCallback)((()=>{if(o){const e=o.getValue();try{const t=JSON.stringify(JSON.parse(e),null,2);t!==e&&o.setValue(t)}catch{}}if(i){const e=i.getValue();try{const t=JSON.stringify(JSON.parse(e),null,2);t!==e&&i.setValue(t)}catch{}}if(n){const e=n.getValue(),t=(0,r.print)((0,r.parse)(e));t!==e&&n.setValue(t)}}),[n,o,i])}function fC(){let{getDefaultFieldNames:e,caller:n}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{schema:r}=RE({nonNull:!0,caller:n||fC}),{queryEditor:i}=oS({nonNull:!0,caller:n||fC});return(0,t.useCallback)((()=>{if(!i)return;const t=i.getValue(),{insertions:n,result:o}=A(r,t,e);return n&&n.length>0&&i.operation((()=>{const e=i.getCursor(),t=i.indexFromPos(e);i.setValue(o||"");let r=0;const a=n.map((e=>{let{index:t,string:n}=e;return i.markText(i.posFromIndex(t+r),i.posFromIndex(t+(r+=n.length)),{className:"auto-inserted-leaf",clearOnEnter:!0,title:"Automatically added leaf fields"})}));setTimeout((()=>{for(const e of a)e.clear()}),7e3);let s=t;for(const{index:e,string:r}of n)epC(e,"name",{value:t,configurable:!0})),"__name$f");function mC(){let{editorTheme:e=gE,keyMap:r=vE,onEdit:i,readOnly:o=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=arguments.length>1?arguments[1]:void 0;const{initialHeaders:s,headerEditor:l,setHeaderEditor:u,shouldPersistHeaders:c}=oS({nonNull:!0,caller:a||mC}),d=fE(),f=cC({caller:a||mC}),p=dC({caller:a||mC}),h=(0,t.useRef)(null);return(0,t.useEffect)((()=>{let t=!0;return EE([Promise.resolve().then(n.t.bind(n,8888,23)).then((function(e){return e.j}))]).then((n=>{if(!t)return;const r=h.current;if(!r)return;const i=n(r,{value:s,lineNumbers:!0,tabSize:2,mode:{name:"javascript",json:!0},theme:e,autoCloseBrackets:!0,matchBrackets:!0,showCursorWhenSelecting:!0,readOnly:!!o&&"nocursor",foldGutter:!0,gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],extraKeys:bE});i.addKeyMap({"Cmd-Space"(){i.showHint({completeSingle:!1,container:r})},"Ctrl-Space"(){i.showHint({completeSingle:!1,container:r})},"Alt-Space"(){i.showHint({completeSingle:!1,container:r})},"Shift-Space"(){i.showHint({completeSingle:!1,container:r})}}),i.on("keyup",((e,t)=>{const{keyCode:n,key:r,shiftKey:i}=t;(n>=65&&n<=90||!i&&n>=48&&n<=57||"_"===r||'"'===r)&&e.execCommand("autocomplete")})),u(i)})),()=>{t=!1}}),[e,s,o,u]),oC(l,"keyMap",r),aC(l,i,c?gC:null,"headers",mC),lC(l,["Cmd-Enter","Ctrl-Enter"],null==d?void 0:d.run),lC(l,["Shift-Ctrl-P"],p),lC(l,["Shift-Ctrl-M"],f),h}g(mC,"useHeaderEditor"),hC(mC,"useHeaderEditor");const gC="headers";var vC=Object.defineProperty,yC=g(((e,t)=>vC(e,"name",{value:t,configurable:!0})),"__name$e");const bC=Array.from({length:11},((e,t)=>String.fromCharCode(8192+t))).concat(["\u2028","\u2029"," "," "]),EC=new RegExp("["+bC.join("")+"]","g");function TC(e){return e.replace(EC," ")}g(TC,"normalizeWhitespace"),yC(TC,"normalizeWhitespace");var wC=Object.defineProperty,CC=g(((e,t)=>wC(e,"name",{value:t,configurable:!0})),"__name$d");function SC(){let{editorTheme:e=gE,keyMap:r=vE,onClickReference:i,onCopyQuery:o,onEdit:a,readOnly:s=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},l=arguments.length>1?arguments[1]:void 0;const{schema:u}=RE({nonNull:!0,caller:l||SC}),{externalFragments:c,initialQuery:d,queryEditor:f,setOperationName:p,setQueryEditor:v,validationRules:y,variableEditor:b,updateActiveTabValues:E}=oS({nonNull:!0,caller:l||SC}),T=fE(),w=ye(),C=qE(),S=Yw(),x=uC({caller:l||SC,onCopyQuery:o}),k=cC({caller:l||SC}),N=dC({caller:l||SC}),_=(0,t.useRef)(null),O=(0,t.useRef)(),I=(0,t.useRef)((()=>{}));(0,t.useEffect)((()=>{I.current=e=>{if(C&&S){switch(S.setVisiblePlugin(Ww),e.kind){case"Type":C.push({name:e.type.name,def:e.type});break;case"Field":C.push({name:e.field.name,def:e.field});break;case"Argument":e.field&&C.push({name:e.field.name,def:e.field});break;case"EnumValue":e.type&&C.push({name:e.type.name,def:e.type})}null==i||i(e)}}}),[C,i,S]),(0,t.useEffect)((()=>{let t=!0;return EE([Promise.resolve().then(n.t.bind(n,6754,23)).then((function(e){return e.c})),Promise.resolve().then(n.t.bind(n,9509,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,4840,23)),Promise.resolve().then(n.t.bind(n,9444,23)),Promise.resolve().then(n.t.bind(n,9890,23)),Promise.resolve().then(n.t.bind(n,5980,23)),Promise.resolve().then(n.t.bind(n,9863,23))]).then((n=>{if(!t)return;O.current=n;const r=_.current;if(!r)return;const i=n(r,{value:d,lineNumbers:!0,tabSize:2,foldGutter:!0,mode:"graphql",theme:e,autoCloseBrackets:!0,matchBrackets:!0,showCursorWhenSelecting:!0,readOnly:!!s&&"nocursor",lint:{schema:void 0,validationRules:null,externalFragments:void 0},hintOptions:{schema:void 0,closeOnUnfocus:!1,completeSingle:!1,container:r,externalFragments:void 0},info:{schema:void 0,renderDescription:e=>nb.render(e),onClick:e=>{I.current(e)}},jump:{schema:void 0,onClick:e=>{I.current(e)}},gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],extraKeys:m(h({},bE),{"Cmd-S"(){},"Ctrl-S"(){}})});i.addKeyMap({"Cmd-Space"(){i.showHint({completeSingle:!0,container:r})},"Ctrl-Space"(){i.showHint({completeSingle:!0,container:r})},"Alt-Space"(){i.showHint({completeSingle:!0,container:r})},"Shift-Space"(){i.showHint({completeSingle:!0,container:r})},"Shift-Alt-Space"(){i.showHint({completeSingle:!0,container:r})}}),i.on("keyup",((e,t)=>{_C.test(t.key)&&e.execCommand("autocomplete")}));let o=!1;i.on("startCompletion",(()=>{o=!0})),i.on("endCompletion",(()=>{o=!1})),i.on("keydown",((e,t)=>{"Escape"===t.key&&o&&t.stopPropagation()})),i.on("beforeChange",((e,t)=>{var n;if("paste"===t.origin){const e=t.text.map(TC);null==(n=t.update)||n.call(t,t.from,t.to,e)}})),i.documentAST=null,i.operationName=null,i.operations=null,i.variableToType=null,v(i)})),()=>{t=!1}}),[e,d,s,v]),oC(f,"keyMap",r),(0,t.useEffect)((()=>{if(!f)return;function e(e){var t,n,r,i,o;const a=Do(u,e.getValue()),s=$(null!=(t=e.operations)?t:void 0,null!=(n=e.operationName)?n:void 0,null==a?void 0:a.operations);return e.documentAST=null!=(r=null==a?void 0:a.documentAST)?r:null,e.operationName=null!=s?s:null,e.operations=null!=(i=null==a?void 0:a.operations)?i:null,b&&(b.state.lint.linterOptions.variableToType=null==a?void 0:a.variableToType,b.options.lint.variableToType=null==a?void 0:a.variableToType,b.options.hintOptions.variableToType=null==a?void 0:a.variableToType,null==(o=O.current)||o.signal(b,"change",b)),a?m(h({},a),{operationName:s}):null}g(e,"getAndUpdateOperationFacts"),CC(e,"getAndUpdateOperationFacts");const t=ww(100,(t=>{var n;const r=t.getValue();null==w||w.set(OC,r);const i=t.operationName,o=e(t);void 0!==(null==o?void 0:o.operationName)&&(null==w||w.set(IC,o.operationName)),null==a||a(r,null==o?void 0:o.documentAST),(null==o?void 0:o.operationName)&&i!==o.operationName&&p(o.operationName),E({query:r,operationName:null!=(n=null==o?void 0:o.operationName)?n:null})}));return e(f),f.on("change",t),()=>f.off("change",t)}),[a,f,u,p,w,b,E]),xC(f,null!=u?u:null,O),kC(f,null!=y?y:null,O),NC(f,c,O),sC(f,i||null,SC);const D=null==T?void 0:T.run,L=(0,t.useCallback)((()=>{var e;if(!(D&&f&&f.operations&&f.hasFocus()))return void(null==D||D());const t=f.indexFromPos(f.getCursor());let n;for(const r of f.operations)r.loc&&r.loc.start<=t&&r.loc.end>=t&&(n=null==(e=r.name)?void 0:e.value);n&&n!==f.operationName&&p(n),D()}),[f,D,p]);return lC(f,["Cmd-Enter","Ctrl-Enter"],L),lC(f,["Shift-Ctrl-C"],x),lC(f,["Shift-Ctrl-P","Shift-Ctrl-F"],N),lC(f,["Shift-Ctrl-M"],k),_}function xC(e,n,r){(0,t.useEffect)((()=>{if(!e)return;const t=e.options.lint.schema!==n;e.state.lint.linterOptions.schema=n,e.options.lint.schema=n,e.options.hintOptions.schema=n,e.options.info.schema=n,e.options.jump.schema=n,t&&r.current&&r.current.signal(e,"change",e)}),[e,n,r])}function kC(e,n,r){(0,t.useEffect)((()=>{if(!e)return;const t=e.options.lint.validationRules!==n;e.state.lint.linterOptions.validationRules=n,e.options.lint.validationRules=n,t&&r.current&&r.current.signal(e,"change",e)}),[e,n,r])}function NC(e,n,r){const i=(0,t.useMemo)((()=>[...n.values()]),[n]);(0,t.useEffect)((()=>{if(!e)return;const t=e.options.lint.externalFragments!==i;e.state.lint.linterOptions.externalFragments=i,e.options.lint.externalFragments=i,e.options.hintOptions.externalFragments=i,t&&r.current&&r.current.signal(e,"change",e)}),[e,i,r])}g(SC,"useQueryEditor"),CC(SC,"useQueryEditor"),g(xC,"useSynchronizeSchema"),CC(xC,"useSynchronizeSchema"),g(kC,"useSynchronizeValidationRules"),CC(kC,"useSynchronizeValidationRules"),g(NC,"useSynchronizeExternalFragments"),CC(NC,"useSynchronizeExternalFragments");const _C=/^[a-zA-Z0-9_@(]$/,OC="query",IC="operationName";var DC=Object.defineProperty,LC=g(((e,t)=>DC(e,"name",{value:t,configurable:!0})),"__name$c");function AC(e){let{defaultQuery:t,defaultHeaders:n,headers:r,defaultTabs:i,query:o,variables:a,storage:s}=e;const l=null==s?void 0:s.get(XC);try{if(!l)throw new Error("Storage for tabs is empty");const e=JSON.parse(l);if(MC(e)){const t=zC({query:o,variables:a,headers:r});let n=-1;for(let r=0;r=0)e.activeTabIndex=n;else{const n=o?WC(o):null;e.tabs.push({id:GC(),hash:t,title:n||QC,query:o,variables:a,headers:r,operationName:n,response:null}),e.activeTabIndex=e.tabs.length-1}return e}throw new Error("Storage for tabs is invalid")}catch{return{activeTabIndex:0,tabs:(i||[{query:null!=o?o:t,variables:a,headers:null!=r?r:n}]).map(qC)}}}function MC(e){return e&&"object"==typeof e&&!Array.isArray(e)&&FC(e,"activeTabIndex")&&"tabs"in e&&Array.isArray(e.tabs)&&e.tabs.every(RC)}function RC(e){return e&&"object"==typeof e&&!Array.isArray(e)&&PC(e,"id")&&PC(e,"title")&&jC(e,"query")&&jC(e,"variables")&&jC(e,"headers")&&jC(e,"operationName")&&jC(e,"response")}function FC(e,t){return t in e&&"number"==typeof e[t]}function PC(e,t){return t in e&&"string"==typeof e[t]}function jC(e,t){return t in e&&("string"==typeof e[t]||null===e[t])}function VC(e){let{queryEditor:n,variableEditor:r,headerEditor:i,responseEditor:o}=e;return(0,t.useCallback)((e=>{var t,a,s,l,u;const c=null!=(t=null==n?void 0:n.getValue())?t:null,d=null!=(a=null==r?void 0:r.getValue())?a:null,f=null!=(s=null==i?void 0:i.getValue())?s:null,p=null!=(l=null==n?void 0:n.operationName)?l:null;return HC(e,{query:c,variables:d,headers:f,response:null!=(u=null==o?void 0:o.getValue())?u:null,operationName:p})}),[n,r,i,o])}function UC(e){let t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return JSON.stringify(e,((e,n)=>"hash"===e||"response"===e||!t&&"headers"===e?null:n))}function BC(e){let{storage:n,shouldPersistHeaders:r}=e;const i=(0,t.useMemo)((()=>ww(500,(e=>{null==n||n.set(XC,e)}))),[n]);return(0,t.useCallback)((e=>{i(UC(e,r))}),[r,i])}function $C(e){let{queryEditor:n,variableEditor:r,headerEditor:i,responseEditor:o}=e;return(0,t.useCallback)((e=>{let{query:t,variables:a,headers:s,response:l}=e;null==n||n.setValue(null!=t?t:""),null==r||r.setValue(null!=a?a:""),null==i||i.setValue(null!=s?s:""),null==o||o.setValue(null!=l?l:"")}),[i,n,o,r])}function qC(){let{query:e=null,variables:t=null,headers:n=null}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{id:GC(),hash:zC({query:e,variables:t,headers:n}),title:e&&WC(e)||QC,query:e,variables:t,headers:n,operationName:null,response:null}}function HC(e,t){return m(h({},e),{tabs:e.tabs.map(((n,r)=>{if(r!==e.activeTabIndex)return n;const i=h(h({},n),t);return m(h({},i),{hash:zC(i),title:i.operationName||(i.query?WC(i.query):void 0)||QC})}))})}function GC(){const e=LC((()=>Math.floor(65536*(1+Math.random())).toString(16).slice(1)),"s4");return`${e()}${e()}-${e()}-${e()}-${e()}-${e()}${e()}${e()}`}function zC(e){var t,n,r;return[null!=(t=e.query)?t:"",null!=(n=e.variables)?n:"",null!=(r=e.headers)?r:""].join("|")}function WC(e){var t;const n=/^(?!#).*(query|subscription|mutation)\s+([a-zA-Z0-9_]+)/m.exec(e);return null!=(t=null==n?void 0:n[2])?t:null}function KC(e){const t=null==e?void 0:e.get(XC);if(t){const n=JSON.parse(t);null==e||e.set(XC,JSON.stringify(n,((e,t)=>"headers"===e?null:t)))}}g(AC,"getDefaultTabState"),LC(AC,"getDefaultTabState"),g(MC,"isTabsState"),LC(MC,"isTabsState"),g(RC,"isTabState"),LC(RC,"isTabState"),g(FC,"hasNumberKey"),LC(FC,"hasNumberKey"),g(PC,"hasStringKey"),LC(PC,"hasStringKey"),g(jC,"hasStringOrNullKey"),LC(jC,"hasStringOrNullKey"),g(VC,"useSynchronizeActiveTabValues"),LC(VC,"useSynchronizeActiveTabValues"),g(UC,"serializeTabState"),LC(UC,"serializeTabState"),g(BC,"useStoreTabs"),LC(BC,"useStoreTabs"),g($C,"useSetEditorValues"),LC($C,"useSetEditorValues"),g(qC,"createTab"),LC(qC,"createTab"),g(HC,"setPropertiesInActiveTab"),LC(HC,"setPropertiesInActiveTab"),g(GC,"guid"),LC(GC,"guid"),g(zC,"hashFromTabContents"),LC(zC,"hashFromTabContents"),g(WC,"fuzzyExtractOperationName"),LC(WC,"fuzzyExtractOperationName"),g(KC,"clearHeadersFromTabs"),LC(KC,"clearHeadersFromTabs");const QC="",XC="tabState";var YC=Object.defineProperty,JC=g(((e,t)=>YC(e,"name",{value:t,configurable:!0})),"__name$b");function ZC(){let{editorTheme:e=gE,keyMap:r=vE,onClickReference:i,onEdit:o,readOnly:a=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=arguments.length>1?arguments[1]:void 0;const{initialVariables:l,variableEditor:u,setVariableEditor:c}=oS({nonNull:!0,caller:s||ZC}),d=fE(),f=cC({caller:s||ZC}),p=dC({caller:s||ZC}),h=(0,t.useRef)(null),m=(0,t.useRef)();return(0,t.useEffect)((()=>{let t=!0;return EE([Promise.resolve().then(n.t.bind(n,4712,23)),Promise.resolve().then(n.t.bind(n,8535,23)),Promise.resolve().then(n.t.bind(n,3340,23))]).then((n=>{if(!t)return;m.current=n;const r=h.current;if(!r)return;const i=n(r,{value:l,lineNumbers:!0,tabSize:2,mode:"graphql-variables",theme:e,autoCloseBrackets:!0,matchBrackets:!0,showCursorWhenSelecting:!0,readOnly:!!a&&"nocursor",foldGutter:!0,lint:{variableToType:void 0},hintOptions:{closeOnUnfocus:!1,completeSingle:!1,container:r,variableToType:void 0},gutters:["CodeMirror-linenumbers","CodeMirror-foldgutter"],extraKeys:bE});i.addKeyMap({"Cmd-Space"(){i.showHint({completeSingle:!1,container:r})},"Ctrl-Space"(){i.showHint({completeSingle:!1,container:r})},"Alt-Space"(){i.showHint({completeSingle:!1,container:r})},"Shift-Space"(){i.showHint({completeSingle:!1,container:r})}}),i.on("keyup",((e,t)=>{const{keyCode:n,key:r,shiftKey:i}=t;(n>=65&&n<=90||!i&&n>=48&&n<=57||"_"===r||'"'===r)&&e.execCommand("autocomplete")})),c(i)})),()=>{t=!1}}),[e,l,a,c]),oC(u,"keyMap",r),aC(u,o,eS,"variables",ZC),sC(u,i||null,ZC),lC(u,["Cmd-Enter","Ctrl-Enter"],null==d?void 0:d.run),lC(u,["Shift-Ctrl-P"],p),lC(u,["Shift-Ctrl-M"],f),h}g(ZC,"useVariableEditor"),JC(ZC,"useVariableEditor");const eS="variables";var tS=Object.defineProperty,nS=g(((e,t)=>tS(e,"name",{value:t,configurable:!0})),"__name$a");const rS=X("EditorContext");function iS(e){const n=ye(),[i,o]=(0,t.useState)(null),[a,s]=(0,t.useState)(null),[l,u]=(0,t.useState)(null),[c,d]=(0,t.useState)(null),[f,p]=(0,t.useState)((()=>{const t=null!==(null==n?void 0:n.get(aS));return!1!==e.shouldPersistHeaders&&t?"true"===(null==n?void 0:n.get(aS)):Boolean(e.shouldPersistHeaders)}));iC(i,e.headers),iC(a,e.query),iC(l,e.response),iC(c,e.variables);const g=BC({storage:n,shouldPersistHeaders:f}),[v]=(0,t.useState)((()=>{var t,r,i,o,a,s,l,u,c;const d=null!=(r=null!=(t=e.query)?t:null==n?void 0:n.get(OC))?r:null,f=null!=(o=null!=(i=e.variables)?i:null==n?void 0:n.get(eS))?o:null,p=null!=(s=null!=(a=e.headers)?a:null==n?void 0:n.get(gC))?s:null,h=null!=(l=e.response)?l:"",m=AC({query:d,variables:f,headers:p,defaultTabs:e.defaultTabs||e.initialTabs,defaultQuery:e.defaultQuery||sS,defaultHeaders:e.defaultHeaders,storage:n});return g(m),{query:null!=(u=null!=d?d:0===m.activeTabIndex?m.tabs[0].query:null)?u:"",variables:null!=f?f:"",headers:null!=(c=null!=p?p:e.defaultHeaders)?c:"",response:h,tabState:m}})),[y,b]=(0,t.useState)(v.tabState),E=(0,t.useCallback)((e=>{var t;if(e){null==n||n.set(gC,null!=(t=null==i?void 0:i.getValue())?t:"");const e=UC(y,!0);null==n||n.set(XC,e)}else null==n||n.set(gC,""),KC(n);p(e),null==n||n.set(aS,e.toString())}),[n,y,i]),T=(0,t.useRef)();(0,t.useEffect)((()=>{const t=Boolean(e.shouldPersistHeaders);T.current!==t&&(E(t),T.current=t)}),[e.shouldPersistHeaders,E]);const w=VC({queryEditor:a,variableEditor:c,headerEditor:i,responseEditor:l}),C=$C({queryEditor:a,variableEditor:c,headerEditor:i,responseEditor:l}),{onTabChange:S,defaultHeaders:x,children:k}=e,N=(0,t.useCallback)((()=>{b((e=>{const t=w(e),n={tabs:[...t.tabs,qC({headers:x})],activeTabIndex:t.tabs.length};return g(n),C(n.tabs[n.activeTabIndex]),null==S||S(n),n}))}),[x,S,C,g,w]),_=(0,t.useCallback)((e=>{b((t=>{const n=m(h({},w(t)),{activeTabIndex:e});return g(n),C(n.tabs[n.activeTabIndex]),null==S||S(n),n}))}),[S,C,g,w]),O=(0,t.useCallback)((e=>{b((t=>{const n={tabs:t.tabs.filter(((t,n)=>e!==n)),activeTabIndex:Math.max(t.activeTabIndex-1,0)};return g(n),C(n.tabs[n.activeTabIndex]),null==S||S(n),n}))}),[S,C,g]),I=(0,t.useCallback)((e=>{b((t=>{const n=HC(t,e);return g(n),null==S||S(n),n}))}),[S,g]),{onEditOperationName:D}=e,L=(0,t.useCallback)((e=>{a&&(a.operationName=e,I({operationName:e}),null==D||D(e))}),[D,a,I]),A=(0,t.useMemo)((()=>{const t=new Map;if(Array.isArray(e.externalFragments))for(const n of e.externalFragments)t.set(n.name.value,n);else if("string"==typeof e.externalFragments)(0,r.visit)((0,r.parse)(e.externalFragments,{}),{FragmentDefinition(e){t.set(e.name.value,e)}});else if(e.externalFragments)throw new Error("The `externalFragments` prop must either be a string that contains the fragment definitions in SDL or a list of FragmentDefinitionNode objects.");return t}),[e.externalFragments]),M=(0,t.useMemo)((()=>e.validationRules||[]),[e.validationRules]),R=(0,t.useMemo)((()=>m(h({},y),{addTab:N,changeTab:_,closeTab:O,updateActiveTabValues:I,headerEditor:i,queryEditor:a,responseEditor:l,variableEditor:c,setHeaderEditor:o,setQueryEditor:s,setResponseEditor:u,setVariableEditor:d,setOperationName:L,initialQuery:v.query,initialVariables:v.variables,initialHeaders:v.headers,initialResponse:v.response,externalFragments:A,validationRules:M,shouldPersistHeaders:f,setShouldPersistHeaders:E})),[y,N,_,O,I,i,a,l,c,L,v,A,M,f,E]);return de(rS.Provider,{value:R,children:k})}e.E=rS,g(iS,"EditorContextProvider"),nS(iS,"EditorContextProvider");const oS=Y(rS);e.f=oS;const aS="shouldPersistHeaders",sS='# Welcome to GraphiQL\n#\n# GraphiQL is an in-browser tool for writing, validating, and\n# testing GraphQL queries.\n#\n# Type queries into this side of the screen, and you will see intelligent\n# typeaheads aware of the current GraphQL type schema and live syntax and\n# validation errors highlighted within the text.\n#\n# GraphQL queries typically start with a "{" character. Lines that start\n# with a # are ignored.\n#\n# An example GraphQL query might look like:\n#\n# {\n# field(arg: "value") {\n# subField\n# }\n# }\n#\n# Keyboard shortcuts:\n#\n# Prettify query: Shift-Ctrl-P (or press the prettify button)\n#\n# Merge fragments: Shift-Ctrl-M (or press the merge button)\n#\n# Run Query: Ctrl-Enter (or press the play button)\n#\n# Auto Complete: Ctrl-Space (or just start typing)\n#\n\n';var lS=Object.defineProperty,uS=g(((e,t)=>lS(e,"name",{value:t,configurable:!0})),"__name$9");function cS(e){var n=e,{isHidden:r}=n,i=v(n,["isHidden"]);const{headerEditor:o}=oS({nonNull:!0,caller:cS}),a=mC(i,cS);return(0,t.useEffect)((()=>{o&&!r&&o.refresh()}),[o,r]),de("div",{className:b("graphiql-editor",r&&"hidden"),ref:a})}g(cS,"HeaderEditor"),uS(cS,"HeaderEditor");var dS=Object.defineProperty,fS=g(((e,t)=>dS(e,"name",{value:t,configurable:!0})),"__name$8");function pS(e){var n;const[r,i]=(0,t.useState)({width:null,height:null}),[o,a]=(0,t.useState)(null),s=(0,t.useRef)(null),l=null==(n=hS(e.token))?void 0:n.href;(0,t.useEffect)((()=>{if(s.current)return l?void fetch(l,{method:"HEAD"}).then((e=>{a(e.headers.get("Content-Type"))})).catch((()=>{a(null)})):(i({width:null,height:null}),void a(null))}),[l]);const u=null!==r.width&&null!==r.height?fe("div",{children:[r.width,"x",r.height,null===o?null:" "+o]}):null;return fe("div",{children:[de("img",{onLoad:()=>{var e,t,n,r;i({width:null!=(t=null==(e=s.current)?void 0:e.naturalWidth)?t:null,height:null!=(r=null==(n=s.current)?void 0:n.naturalHeight)?r:null})},ref:s,src:l}),u]})}function hS(e){if("string"!==e.type)return;const t=e.string.slice(1).slice(0,-1).trim();try{const{location:e}=window;return new URL(t,e.protocol+"//"+e.host)}catch{return}}function mS(e){return/(bmp|gif|jpeg|jpg|png|svg)$/.test(e.pathname)}g(pS,"ImagePreview"),fS(pS,"ImagePreview"),pS.shouldRender=fS(g((function(e){const t=hS(e);return!!t&&mS(t)}),"shouldRender"),"shouldRender"),g(hS,"tokenToURL"),fS(hS,"tokenToURL"),g(mS,"isImageURL"),fS(mS,"isImageURL");var gS=Object.defineProperty,vS=g(((e,t)=>gS(e,"name",{value:t,configurable:!0})),"__name$7");function yS(e){const t=SC(e,yS);return de("div",{className:"graphiql-editor",ref:t})}g(yS,"QueryEditor"),vS(yS,"QueryEditor");var bS=Object.defineProperty,ES=g(((e,t)=>bS(e,"name",{value:t,configurable:!0})),"__name$6");function TS(){let{responseTooltip:e,editorTheme:r=gE,keyMap:o=vE}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=arguments.length>1?arguments[1]:void 0;const{fetchError:s,validationErrors:l}=RE({nonNull:!0,caller:a||TS}),{initialResponse:u,responseEditor:c,setResponseEditor:d}=oS({nonNull:!0,caller:a||TS}),f=(0,t.useRef)(null),p=(0,t.useRef)(e);return(0,t.useEffect)((()=>{p.current=e}),[e]),(0,t.useEffect)((()=>{let e=!0;return EE([Promise.resolve().then(n.t.bind(n,8419,23)).then((function(e){return e.f})),Promise.resolve().then(n.t.bind(n,4468,23)).then((function(e){return e.b})),Promise.resolve().then(n.t.bind(n,8058,23)).then((function(e){return e.d})),Promise.resolve().then(n.t.bind(n,9509,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,9407,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,4471,23)).then((function(e){return e.j})),Promise.resolve().then(n.t.bind(n,2568,23)).then((function(e){return e.s})),Promise.resolve().then(n.t.bind(n,1430,23)),Promise.resolve().then(n.t.bind(n,7421,23))],{useCommonAddons:!1}).then((t=>{if(!e)return;const n=document.createElement("div");t.registerHelper("info","graphql-results",((e,t,r,o)=>{const a=[],s=p.current;return s&&a.push(de(s,{pos:o,token:e})),pS.shouldRender(e)&&a.push(de(pS,{token:e},"image-preview")),a.length?(i.default.render(a,n),n):(i.default.unmountComponentAtNode(n),null)}));const o=f.current;if(!o)return;const a=t(o,{value:u,lineWrapping:!0,readOnly:!0,theme:r,mode:"graphql-results",foldGutter:!0,gutters:["CodeMirror-foldgutter"],info:!0,extraKeys:bE});d(a)})),()=>{e=!1}}),[r,u,d]),oC(c,"keyMap",o),(0,t.useEffect)((()=>{s&&(null==c||c.setValue(s)),l.length>0&&(null==c||c.setValue(D(l)))}),[c,s,l]),f}g(TS,"useResponseEditor"),ES(TS,"useResponseEditor");var wS=Object.defineProperty,CS=g(((e,t)=>wS(e,"name",{value:t,configurable:!0})),"__name$5");function SS(e){const t=TS(e,SS);return de("section",{className:"result-window","aria-label":"Result Window","aria-live":"polite","aria-atomic":"true",ref:t})}g(SS,"ResponseEditor"),CS(SS,"ResponseEditor");var xS=Object.defineProperty,kS=g(((e,t)=>xS(e,"name",{value:t,configurable:!0})),"__name$4");function NS(e){var n=e,{isHidden:r}=n,i=v(n,["isHidden"]);const{variableEditor:o}=oS({nonNull:!0,caller:NS}),a=ZC(i,NS);return(0,t.useEffect)((()=>{o&&!r&&o.refresh()}),[o,r]),de("div",{className:b("graphiql-editor",r&&"hidden"),ref:a})}g(NS,"VariableEditor"),kS(NS,"VariableEditor");var _S=Object.defineProperty,OS=g(((e,t)=>_S(e,"name",{value:t,configurable:!0})),"__name$3");function IS(e){let{children:t,dangerouslyAssumeSchemaIsValid:n,defaultQuery:r,defaultHeaders:i,defaultTabs:o,externalFragments:a,fetcher:s,getDefaultFieldNames:l,headers:u,initialTabs:c,inputValueDeprecation:d,introspectionQueryName:f,maxHistoryLength:p,onEditOperationName:h,onSchemaChange:m,onTabChange:g,onTogglePluginVisibility:v,operationName:y,plugins:b,query:E,response:T,schema:w,schemaDescription:C,shouldPersistHeaders:S,storage:x,validationRules:k,variables:N,visiblePlugin:_}=e;return de(ve,{storage:x,children:de(eE,{maxHistoryLength:p,children:de(iS,{defaultQuery:r,defaultHeaders:i,defaultTabs:o,externalFragments:a,headers:u,initialTabs:c,onEditOperationName:h,onTabChange:g,query:E,response:T,shouldPersistHeaders:S,validationRules:k,variables:N,children:de(ME,{dangerouslyAssumeSchemaIsValid:n,fetcher:s,inputValueDeprecation:d,introspectionQueryName:f,onSchemaChange:m,schema:w,schemaDescription:C,children:de(dE,{getDefaultFieldNames:l,fetcher:s,operationName:y,children:de($E,{children:de(Xw,{onTogglePluginVisibility:v,plugins:b,visiblePlugin:_,children:t})})})})})})})}g(IS,"GraphiQLProvider"),OS(IS,"GraphiQLProvider");var DS=Object.defineProperty,LS=g(((e,t)=>DS(e,"name",{value:t,configurable:!0})),"__name$2");function AS(){const e=ye(),[n,r]=(0,t.useState)((()=>{if(!e)return null;const t=e.get(MS);switch(t){case"light":return"light";case"dark":return"dark";default:return"string"==typeof t&&e.set(MS,""),null}}));(0,t.useLayoutEffect)((()=>{"undefined"!=typeof window&&(document.body.classList.remove("graphiql-light","graphiql-dark"),n&&document.body.classList.add(`graphiql-${n}`))}),[n]);const i=(0,t.useCallback)((t=>{null==e||e.set(MS,t||""),r(t)}),[e]);return(0,t.useMemo)((()=>({theme:n,setTheme:i})),[n,i])}g(AS,"useTheme"),LS(AS,"useTheme");const MS="theme";var RS=Object.defineProperty,FS=g(((e,t)=>RS(e,"name",{value:t,configurable:!0})),"__name$1");function PS(e){let{defaultSizeRelation:n=jS,direction:r,initiallyHidden:i,onHiddenElementChange:o,sizeThresholdFirst:a=100,sizeThresholdSecond:s=100,storageKey:l}=e;const u=ye(),c=(0,t.useMemo)((()=>ww(500,(e=>{u&&l&&u.set(l,e)}))),[u,l]),[d,f]=(0,t.useState)((()=>{const e=u&&l?u.get(l):null;return e===VS||"first"===i?"first":e===US||"second"===i?"second":null})),p=(0,t.useCallback)((e=>{e!==d&&(f(e),null==o||o(e))}),[d,o]),h=(0,t.useRef)(null),m=(0,t.useRef)(null),v=(0,t.useRef)(null),y=(0,t.useRef)(`${n}`);(0,t.useLayoutEffect)((()=>{const e=u&&l&&u.get(l)||y.current,t="horizontal"===r?"row":"column";h.current&&(h.current.style.display="flex",h.current.style.flexDirection=t,h.current.style.flex=e===VS||e===US?y.current:e),v.current&&(v.current.style.display="flex",v.current.style.flexDirection=t,v.current.style.flex="1"),m.current&&(m.current.style.display="flex",m.current.style.flexDirection=t)}),[r,u,l]);const b=(0,t.useCallback)((e=>{const t="first"===e?h.current:v.current;if(t&&(t.style.left="-1000px",t.style.position="absolute",t.style.opacity="0",t.style.height="500px",t.style.width="500px",h.current)){const e=parseFloat(h.current.style.flex);(!Number.isFinite(e)||e<1)&&(h.current.style.flex="1")}}),[]),E=(0,t.useCallback)((e=>{const t="first"===e?h.current:v.current;if(t&&(t.style.width="",t.style.height="",t.style.opacity="",t.style.position="",t.style.left="",h.current&&u&&l)){const e=null==u?void 0:u.get(l);e!==VS&&e!==US&&(h.current.style.flex=e||y.current)}}),[u,l]);return(0,t.useLayoutEffect)((()=>{"first"===d?b("first"):E("first"),"second"===d?b("second"):E("second")}),[d,b,E]),(0,t.useEffect)((()=>{if(!m.current||!h.current||!v.current)return;const e=m.current,t=h.current,n=t.parentElement,i="horizontal"===r?"clientX":"clientY",o="horizontal"===r?"left":"top",l="horizontal"===r?"right":"bottom",u="horizontal"===r?"clientWidth":"clientHeight";function d(r){r.preventDefault();const d=r[i]-e.getBoundingClientRect()[o];function f(r){if(0===r.buttons)return h();const f=r[i]-n.getBoundingClientRect()[o]-d,m=n.getBoundingClientRect()[l]-r[i]+d-e[u];if(f{e.removeEventListener("mousedown",d),e.removeEventListener("dblclick",f)}}),[r,p,a,s,c]),(0,t.useMemo)((()=>({dragBarRef:m,hiddenElement:d,firstRef:h,setHiddenElement:f,secondRef:v})),[d,f])}g(PS,"useDragResize"),FS(PS,"useDragResize");const jS=1,VS="hide-first",US="hide-second",BS=(0,t.forwardRef)(((e,n)=>{var r=e,{label:i}=r,o=v(r,["label"]);const[a,s]=(0,t.useState)(null);return de(Pb,{label:i,children:de(os,m(h({},o),{ref:n,type:"button",className:b("graphiql-toolbar-button",a&&"error",o.className),onClick:e=>{var t;try{null==(t=o.onClick)||t.call(o,e),s(null)}catch(e){s(e instanceof Error?e:new Error(`Toolbar button click failed: ${e}`))}},"aria-label":a?a.message:i,"aria-invalid":a?"true":o["aria-invalid"]}))})}));e.aR=BS,BS.displayName="ToolbarButton";var $S=Object.defineProperty,qS=g(((e,t)=>$S(e,"name",{value:t,configurable:!0})),"__name");function HS(){const{queryEditor:e,setOperationName:t}=oS({nonNull:!0,caller:HS}),{isFetching:n,isSubscribed:r,operationName:i,run:o,stop:a}=fE({nonNull:!0,caller:HS}),s=(null==e?void 0:e.operations)||[],l=s.length>1&&"string"!=typeof i,u=n||r,c=(u?"Stop":"Execute")+" query (Ctrl-Enter)",d={type:"button",className:"graphiql-execute-button",children:de(u?ns:Ka,{}),"aria-label":c};return l&&!u?fe(Hh,{children:[de(Pb,{label:c,children:de(Hh.Button,h({},d))}),de(Hh.List,{children:s.map(((n,r)=>{const i=n.name?n.name.value:``;return de(Hh.Item,{onSelect:()=>{var r;const i=null==(r=n.name)?void 0:r.value;e&&i&&i!==e.operationName&&t(i),o()},children:i},`${i}-${r}`)}))})]}):de(Pb,{label:c,children:de("button",m(h({},d),{onClick:()=>{u?a():o()}}))})}g(HS,"ExecuteButton"),qS(HS,"ExecuteButton");const GS=(0,t.forwardRef)(((e,t)=>{var n=e,{button:r,children:i,label:o}=n,a=v(n,["button","children","label"]);const s=`${o}${a.value?`: ${a.value}`:""}`;return fe(zh.Input,m(h({},a),{ref:t,className:b("graphiql-toolbar-listbox",a.className),"aria-label":s,children:[de(Pb,{label:s,children:de(zh.Button,{children:r})}),de(zh.Popover,{children:i})]}))}));GS.displayName="ToolbarListbox";const zS=Xc(GS,{Option:zh.Option});e.aT=zS;const WS=(0,t.forwardRef)(((e,t)=>{var n=e,{button:r,children:i,label:o}=n,a=v(n,["button","children","label"]);return fe(Hh,m(h({},a),{ref:t,children:[de(Pb,{label:o,children:de(Hh.Button,{className:b("graphiql-un-styled graphiql-toolbar-menu",a.className),"aria-label":o,children:r})}),de(Hh.List,{children:i})]}))}));WS.displayName="ToolbarMenu";const KS=Xc(WS,{Item:Hh.Item});e.aU=KS},void 0===(o=r.apply(t,i))||(e.exports=o)},7421:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(6856),n(9196),n(3573),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i){"use strict";var o=Object.defineProperty,a=(e,t)=>o(e,"name",{value:t,configurable:!0});function s(e){return{options:e instanceof Function?{render:e}:!0===e?{}:e}}function l(e){const{options:t}=e.state.info;return(null==t?void 0:t.hoverTime)||500}function u(t,n){const r=t.state.info,i=n.target||n.srcElement;if(!(i instanceof HTMLElement))return;if("SPAN"!==i.nodeName||void 0!==r.hoverTimeout)return;const o=i.getBoundingClientRect(),s=a((function(){clearTimeout(r.hoverTimeout),r.hoverTimeout=setTimeout(d,f)}),"onMouseMove"),u=a((function(){e.C.off(document,"mousemove",s),e.C.off(t.getWrapperElement(),"mouseout",u),clearTimeout(r.hoverTimeout),r.hoverTimeout=void 0}),"onMouseOut"),d=a((function(){e.C.off(document,"mousemove",s),e.C.off(t.getWrapperElement(),"mouseout",u),r.hoverTimeout=void 0,c(t,o)}),"onHover"),f=l(t);r.hoverTimeout=setTimeout(d,f),e.C.on(document,"mousemove",s),e.C.on(t.getWrapperElement(),"mouseout",u)}function c(e,t){const n=e.coordsChar({left:(t.left+t.right)/2,top:(t.top+t.bottom)/2}),r=e.state.info,{options:i}=r,o=i.render||e.getHelper(n,"info");if(o){const r=e.getTokenAt(n,!0);if(r){const a=o(r,i,e,n);a&&d(e,t,a)}}}function d(t,n,r){const i=document.createElement("div");i.className="CodeMirror-info",i.append(r),document.body.append(i);const o=i.getBoundingClientRect(),s=window.getComputedStyle(i),l=o.right-o.left+parseFloat(s.marginLeft)+parseFloat(s.marginRight),u=o.bottom-o.top+parseFloat(s.marginTop)+parseFloat(s.marginBottom);let c=n.bottom;u>window.innerHeight-n.bottom-15&&n.top>window.innerHeight-n.bottom&&(c=n.top-u),c<0&&(c=n.bottom);let d,f=Math.max(0,window.innerWidth-l-15);f>n.left&&(f=n.left),i.style.opacity="1",i.style.top=c+"px",i.style.left=f+"px";const p=a((function(){clearTimeout(d)}),"onMouseOverPopup"),h=a((function(){clearTimeout(d),d=setTimeout(m,200)}),"onMouseOut"),m=a((function(){e.C.off(i,"mouseover",p),e.C.off(i,"mouseout",h),e.C.off(t.getWrapperElement(),"mouseout",h),i.style.opacity?(i.style.opacity="0",setTimeout((()=>{i.parentNode&&i.remove()}),600)):i.parentNode&&i.remove()}),"hidePopup");e.C.on(i,"mouseover",p),e.C.on(i,"mouseout",h),e.C.on(t.getWrapperElement(),"mouseout",h)}e.C.defineOption("info",!1,((t,n,r)=>{if(r&&r!==e.C.Init){const n=t.state.info.onMouseOver;e.C.off(t.getWrapperElement(),"mouseover",n),clearTimeout(t.state.info.hoverTimeout),delete t.state.info}if(n){const r=t.state.info=s(n);r.onMouseOver=u.bind(null,t),e.C.on(t.getWrapperElement(),"mouseover",r.onMouseOver)}})),a(s,"createState"),a(l,"getHoverTime"),a(u,"onMouseOver"),a(c,"onMouseHover"),a(d,"showPopup")})?r.apply(t,i):r)||(e.exports=o)},9890:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(3573),n(535),n(2645),n(7421),n(6856),n(9196),n(1850),n(2635)],r=function(e,t,n,r,i,o,a,s){"use strict";var l=Object.defineProperty,u=(e,t)=>l(e,"name",{value:t,configurable:!0});function c(e,t,n){d(e,t,n),m(e,t,n,t.type)}function d(e,t,r){var i;b(e,(null===(i=t.fieldDef)||void 0===i?void 0:i.name)||"","field-name",r,(0,n.a)(t))}function f(e,t,r){var i;b(e,"@"+((null===(i=t.directiveDef)||void 0===i?void 0:i.name)||""),"directive-name",r,(0,n.b)(t))}function p(e,t,r){var i;b(e,(null===(i=t.argDef)||void 0===i?void 0:i.name)||"","arg-name",r,(0,n.c)(t)),m(e,t,r,t.inputType)}function h(e,t,r){var i;const o=(null===(i=t.enumValue)||void 0===i?void 0:i.name)||"";g(e,t,r,t.inputType),b(e,"."),b(e,o,"enum-value",r,(0,n.d)(t))}function m(t,r,i,o){const a=document.createElement("span");a.className="type-name-pill",o instanceof e.GraphQLNonNull?(g(a,r,i,o.ofType),b(a,"!")):o instanceof e.GraphQLList?(b(a,"["),g(a,r,i,o.ofType),b(a,"]")):b(a,(null==o?void 0:o.name)||"","type-name",i,(0,n.e)(r,o)),t.append(a)}function g(t,r,i,o){o instanceof e.GraphQLNonNull?(g(t,r,i,o.ofType),b(t,"!")):o instanceof e.GraphQLList?(b(t,"["),g(t,r,i,o.ofType),b(t,"]")):b(t,(null==o?void 0:o.name)||"","type-name",i,(0,n.e)(r,o))}function v(e,t,n){const{description:r}=n;if(r){const n=document.createElement("div");n.className="info-description",t.renderDescription?n.innerHTML=t.renderDescription(r):n.append(document.createTextNode(r)),e.append(n)}y(e,t,n)}function y(e,t,n){const r=n.deprecationReason;if(r){const n=document.createElement("div");n.className="info-deprecation",e.append(n);const i=document.createElement("span");i.className="info-deprecation-label",i.append(document.createTextNode("Deprecated")),n.append(i);const o=document.createElement("div");o.className="info-deprecation-reason",t.renderDescription?o.innerHTML=t.renderDescription(r):o.append(document.createTextNode(r)),n.append(o)}}function b(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{onClick:null},i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;if(n){const{onClick:o}=r;let a;o?(a=document.createElement("a"),a.href="javascript:void 0",a.addEventListener("click",(e=>{o(i,e)}))):a=document.createElement("span"),a.className=n,a.append(document.createTextNode(t)),e.append(a)}else e.append(document.createTextNode(t))}t.C.registerHelper("info","graphql",((e,t)=>{if(!t.schema||!e.state)return;const{kind:r,step:i}=e.state,o=(0,n.g)(t.schema,e.state);if("Field"===r&&0===i&&o.fieldDef||"AliasedField"===r&&2===i&&o.fieldDef){const e=document.createElement("div");e.className="CodeMirror-info-header",c(e,o,t);const n=document.createElement("div");return n.append(e),v(n,t,o.fieldDef),n}if("Directive"===r&&1===i&&o.directiveDef){const e=document.createElement("div");e.className="CodeMirror-info-header",f(e,o,t);const n=document.createElement("div");return n.append(e),v(n,t,o.directiveDef),n}if("Argument"===r&&0===i&&o.argDef){const e=document.createElement("div");e.className="CodeMirror-info-header",p(e,o,t);const n=document.createElement("div");return n.append(e),v(n,t,o.argDef),n}if("EnumValue"===r&&o.enumValue&&o.enumValue.description){const e=document.createElement("div");e.className="CodeMirror-info-header",h(e,o,t);const n=document.createElement("div");return n.append(e),v(n,t,o.enumValue),n}if("NamedType"===r&&o.type&&o.type.description){const e=document.createElement("div");e.className="CodeMirror-info-header",g(e,o,t,o.type);const n=document.createElement("div");return n.append(e),v(n,t,o.type),n}})),u(c,"renderField"),u(d,"renderQualifiedField"),u(f,"renderDirective"),u(p,"renderArg"),u(h,"renderEnumValue"),u(m,"renderTypeAnnotation"),u(g,"renderType"),u(v,"renderDescription"),u(y,"renderDeprecation"),u(b,"text")},void 0===(o=r.apply(t,i))||(e.exports=o)},8888:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.j=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o,a={exports:{}};(o=t.a.exports).defineMode("javascript",(function(e,t){var n,i,a=e.indentUnit,s=t.statementIndent,l=t.jsonld,u=t.json||l,c=!1!==t.trackScope,d=t.typescript,f=t.wordCharacters||/[\w$\xa1-\uffff]/,p=function(){function e(e){return{type:e,style:"keyword"}}r(e,"kw");var t=e("keyword a"),n=e("keyword b"),i=e("keyword c"),o=e("keyword d"),a=e("operator"),s={type:"atom",style:"atom"};return{if:e("if"),while:t,with:t,else:n,do:n,try:n,finally:n,return:o,break:o,continue:o,new:e("new"),delete:i,void:i,throw:i,debugger:e("debugger"),var:e("var"),const:e("var"),let:e("var"),function:e("function"),catch:e("catch"),for:e("for"),switch:e("switch"),case:e("case"),default:e("default"),in:a,typeof:a,instanceof:a,true:s,false:s,null:s,undefined:s,NaN:s,Infinity:s,this:e("this"),class:e("class"),super:e("atom"),yield:i,export:e("export"),import:e("import"),extends:i,await:i}}(),h=/[+\-*&%=<>!?|~^@]/,m=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function g(e){for(var t,n=!1,r=!1;null!=(t=e.next());){if(!n){if("/"==t&&!r)return;"["==t?r=!0:r&&"]"==t&&(r=!1)}n=!n&&"\\"==t}}function v(e,t,r){return n=e,i=r,t}function y(e,t){var n=e.next();if('"'==n||"'"==n)return t.tokenize=b(n),t.tokenize(e,t);if("."==n&&e.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/))return v("number","number");if("."==n&&e.match(".."))return v("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(n))return v(n);if("="==n&&e.eat(">"))return v("=>","operator");if("0"==n&&e.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/))return v("number","number");if(/\d/.test(n))return e.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/),v("number","number");if("/"==n)return e.eat("*")?(t.tokenize=E,E(e,t)):e.eat("/")?(e.skipToEnd(),v("comment","comment")):ot(e,t,1)?(g(e),e.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/),v("regexp","string-2")):(e.eat("="),v("operator","operator",e.current()));if("`"==n)return t.tokenize=T,T(e,t);if("#"==n&&"!"==e.peek())return e.skipToEnd(),v("meta","meta");if("#"==n&&e.eatWhile(f))return v("variable","property");if("<"==n&&e.match("!--")||"-"==n&&e.match("->")&&!/\S/.test(e.string.slice(0,e.start)))return e.skipToEnd(),v("comment","comment");if(h.test(n))return">"==n&&t.lexical&&">"==t.lexical.type||(e.eat("=")?"!"!=n&&"="!=n||e.eat("="):/[<>*+\-|&?]/.test(n)&&(e.eat(n),">"==n&&e.eat(n))),"?"==n&&e.eat(".")?v("."):v("operator","operator",e.current());if(f.test(n)){e.eatWhile(f);var r=e.current();if("."!=t.lastType){if(p.propertyIsEnumerable(r)){var i=p[r];return v(i.type,i.style,r)}if("async"==r&&e.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/,!1))return v("async","keyword",r)}return v("variable","variable",r)}}function b(e){return function(t,n){var r,i=!1;if(l&&"@"==t.peek()&&t.match(m))return n.tokenize=y,v("jsonld-keyword","meta");for(;null!=(r=t.next())&&(r!=e||i);)i=!i&&"\\"==r;return i||(n.tokenize=y),v("string","string")}}function E(e,t){for(var n,r=!1;n=e.next();){if("/"==n&&r){t.tokenize=y;break}r="*"==n}return v("comment","comment")}function T(e,t){for(var n,r=!1;null!=(n=e.next());){if(!r&&("`"==n||"$"==n&&e.eat("{"))){t.tokenize=y;break}r=!r&&"\\"==n}return v("quasi","string-2",e.current())}r(g,"readRegexp"),r(v,"ret"),r(y,"tokenBase"),r(b,"tokenString"),r(E,"tokenComment"),r(T,"tokenQuasi");var w="([{}])";function C(e,t){t.fatArrowAt&&(t.fatArrowAt=null);var n=e.string.indexOf("=>",e.start);if(!(n<0)){if(d){var r=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(e.string.slice(e.start,n));r&&(n=r.index)}for(var i=0,o=!1,a=n-1;a>=0;--a){var s=e.string.charAt(a),l=w.indexOf(s);if(l>=0&&l<3){if(!i){++a;break}if(0==--i){"("==s&&(o=!0);break}}else if(l>=3&&l<6)++i;else if(f.test(s))o=!0;else if(/["'\/`]/.test(s))for(;;--a){if(0==a)return;if(e.string.charAt(a-1)==s&&"\\"!=e.string.charAt(a-2)){a--;break}}else if(o&&!i){++a;break}}o&&!i&&(t.fatArrowAt=a)}}r(C,"findFatArrow");var S={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,import:!0,"jsonld-keyword":!0};function x(e,t,n,r,i,o){this.indented=e,this.column=t,this.type=n,this.prev=i,this.info=o,null!=r&&(this.align=r)}function k(e,t){if(!c)return!1;for(var n=e.localVars;n;n=n.next)if(n.name==t)return!0;for(var r=e.context;r;r=r.prev)for(n=r.vars;n;n=n.next)if(n.name==t)return!0}function N(e,t,n,r,i){var o=e.cc;for(_.state=e,_.stream=i,_.marked=null,_.cc=o,_.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((o.length?o.pop():u?z:H)(n,r)){for(;o.length&&o[o.length-1].lex;)o.pop()();return _.marked?_.marked:"variable"==n&&k(e,r)?"variable-2":t}}r(x,"JSLexical"),r(k,"inScope"),r(N,"parseJS");var _={state:null,column:null,marked:null,cc:null};function O(){for(var e=arguments.length-1;e>=0;e--)_.cc.push(arguments[e])}function I(){return O.apply(null,arguments),!0}function D(e,t){for(var n=t;n;n=n.next)if(n.name==e)return!0;return!1}function L(e){var n=_.state;if(_.marked="def",c){if(n.context)if("var"==n.lexical.info&&n.context&&n.context.block){var r=A(e,n.context);if(null!=r)return void(n.context=r)}else if(!D(e,n.localVars))return void(n.localVars=new F(e,n.localVars));t.globalVars&&!D(e,n.globalVars)&&(n.globalVars=new F(e,n.globalVars))}}function A(e,t){if(t){if(t.block){var n=A(e,t.prev);return n?n==t.prev?t:new R(n,t.vars,!0):null}return D(e,t.vars)?t:new R(t.prev,new F(e,t.vars),!1)}return null}function M(e){return"public"==e||"private"==e||"protected"==e||"abstract"==e||"readonly"==e}function R(e,t,n){this.prev=e,this.vars=t,this.block=n}function F(e,t){this.name=e,this.next=t}r(O,"pass"),r(I,"cont"),r(D,"inList"),r(L,"register"),r(A,"registerVarScoped"),r(M,"isModifier"),r(R,"Context"),r(F,"Var");var P=new F("this",new F("arguments",null));function j(){_.state.context=new R(_.state.context,_.state.localVars,!1),_.state.localVars=P}function V(){_.state.context=new R(_.state.context,_.state.localVars,!0),_.state.localVars=null}function U(){_.state.localVars=_.state.context.vars,_.state.context=_.state.context.prev}function B(e,t){var n=r((function(){var n=_.state,r=n.indented;if("stat"==n.lexical.type)r=n.lexical.indented;else for(var i=n.lexical;i&&")"==i.type&&i.align;i=i.prev)r=i.indented;n.lexical=new x(r,_.stream.column(),e,null,n.lexical,t)}),"result");return n.lex=!0,n}function $(){var e=_.state;e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function q(e){function t(n){return n==e?I():";"==e||"}"==n||")"==n||"]"==n?O():I(t)}return r(t,"exp"),t}function H(e,t){return"var"==e?I(B("vardef",t),Oe,q(";"),$):"keyword a"==e?I(B("form"),K,H,$):"keyword b"==e?I(B("form"),H,$):"keyword d"==e?_.stream.match(/^\s*$/,!1)?I():I(B("stat"),X,q(";"),$):"debugger"==e?I(q(";")):"{"==e?I(B("}"),V,pe,$,U):";"==e?I():"if"==e?("else"==_.state.lexical.info&&_.state.cc[_.state.cc.length-1]==$&&_.state.cc.pop()(),I(B("form"),K,H,$,Re)):"function"==e?I(Ve):"for"==e?I(B("form"),V,Fe,H,U,$):"class"==e||d&&"interface"==t?(_.marked="keyword",I(B("form","class"==e?e:t),He,$)):"variable"==e?d&&"declare"==t?(_.marked="keyword",I(H)):d&&("module"==t||"enum"==t||"type"==t)&&_.stream.match(/^\s*\w/,!1)?(_.marked="keyword","enum"==t?I(nt):"type"==t?I(Be,q("operator"),ye,q(";")):I(B("form"),Ie,q("{"),B("}"),pe,$,$)):d&&"namespace"==t?(_.marked="keyword",I(B("form"),z,H,$)):d&&"abstract"==t?(_.marked="keyword",I(H)):I(B("stat"),ae):"switch"==e?I(B("form"),K,q("{"),B("}","switch"),V,pe,$,$,U):"case"==e?I(z,q(":")):"default"==e?I(q(":")):"catch"==e?I(B("form"),j,G,H,$,U):"export"==e?I(B("stat"),Ke,$):"import"==e?I(B("stat"),Xe,$):"async"==e?I(H):"@"==t?I(z,H):O(B("stat"),z,q(";"),$)}function G(e){if("("==e)return I($e,q(")"))}function z(e,t){return Q(e,t,!1)}function W(e,t){return Q(e,t,!0)}function K(e){return"("!=e?O():I(B(")"),X,q(")"),$)}function Q(e,t,n){if(_.state.fatArrowAt==_.stream.start){var r=n?ne:te;if("("==e)return I(j,B(")"),de($e,")"),$,q("=>"),r,U);if("variable"==e)return O(j,Ie,q("=>"),r,U)}var i=n?J:Y;return S.hasOwnProperty(e)?I(i):"function"==e?I(Ve,i):"class"==e||d&&"interface"==t?(_.marked="keyword",I(B("form"),qe,$)):"keyword c"==e||"async"==e?I(n?W:z):"("==e?I(B(")"),X,q(")"),$,i):"operator"==e||"spread"==e?I(n?W:z):"["==e?I(B("]"),tt,$,i):"{"==e?fe(le,"}",null,i):"quasi"==e?O(Z,i):"new"==e?I(re(n)):I()}function X(e){return e.match(/[;\}\)\],]/)?O():O(z)}function Y(e,t){return","==e?I(X):J(e,t,!1)}function J(e,t,n){var r=0==n?Y:J,i=0==n?z:W;return"=>"==e?I(j,n?ne:te,U):"operator"==e?/\+\+|--/.test(t)||d&&"!"==t?I(r):d&&"<"==t&&_.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/,!1)?I(B(">"),de(ye,">"),$,r):"?"==t?I(z,q(":"),i):I(i):"quasi"==e?O(Z,r):";"!=e?"("==e?fe(W,")","call",r):"."==e?I(se,r):"["==e?I(B("]"),X,q("]"),$,r):d&&"as"==t?(_.marked="keyword",I(ye,r)):"regexp"==e?(_.state.lastType=_.marked="operator",_.stream.backUp(_.stream.pos-_.stream.start-1),I(i)):void 0:void 0}function Z(e,t){return"quasi"!=e?O():"${"!=t.slice(t.length-2)?I(Z):I(X,ee)}function ee(e){if("}"==e)return _.marked="string-2",_.state.tokenize=T,I(Z)}function te(e){return C(_.stream,_.state),O("{"==e?H:z)}function ne(e){return C(_.stream,_.state),O("{"==e?H:W)}function re(e){return function(t){return"."==t?I(e?oe:ie):"variable"==t&&d?I(ke,e?J:Y):O(e?W:z)}}function ie(e,t){if("target"==t)return _.marked="keyword",I(Y)}function oe(e,t){if("target"==t)return _.marked="keyword",I(J)}function ae(e){return":"==e?I($,H):O(Y,q(";"),$)}function se(e){if("variable"==e)return _.marked="property",I()}function le(e,t){return"async"==e?(_.marked="property",I(le)):"variable"==e||"keyword"==_.style?(_.marked="property","get"==t||"set"==t?I(ue):(d&&_.state.fatArrowAt==_.stream.start&&(n=_.stream.match(/^\s*:\s*/,!1))&&(_.state.fatArrowAt=_.stream.pos+n[0].length),I(ce))):"number"==e||"string"==e?(_.marked=l?"property":_.style+" property",I(ce)):"jsonld-keyword"==e?I(ce):d&&M(t)?(_.marked="keyword",I(le)):"["==e?I(z,he,q("]"),ce):"spread"==e?I(W,ce):"*"==t?(_.marked="keyword",I(le)):":"==e?O(ce):void 0;var n}function ue(e){return"variable"!=e?O(ce):(_.marked="property",I(Ve))}function ce(e){return":"==e?I(W):"("==e?O(Ve):void 0}function de(e,t,n){function i(r,o){if(n?n.indexOf(r)>-1:","==r){var a=_.state.lexical;return"call"==a.info&&(a.pos=(a.pos||0)+1),I((function(n,r){return n==t||r==t?O():O(e)}),i)}return r==t||o==t?I():n&&n.indexOf(";")>-1?O(e):I(q(t))}return r(i,"proceed"),function(n,r){return n==t||r==t?I():O(e,i)}}function fe(e,t,n){for(var r=3;r"),ye):"quasi"==e?O(we,xe):void 0}function be(e){if("=>"==e)return I(ye)}function Ee(e){return e.match(/[\}\)\]]/)?I():","==e||";"==e?I(Ee):O(Te,Ee)}function Te(e,t){return"variable"==e||"keyword"==_.style?(_.marked="property",I(Te)):"?"==t||"number"==e||"string"==e?I(Te):":"==e?I(ye):"["==e?I(q("variable"),me,q("]"),Te):"("==e?O(Ue,Te):e.match(/[;\}\)\],]/)?void 0:I()}function we(e,t){return"quasi"!=e?O():"${"!=t.slice(t.length-2)?I(we):I(ye,Ce)}function Ce(e){if("}"==e)return _.marked="string-2",_.state.tokenize=T,I(we)}function Se(e,t){return"variable"==e&&_.stream.match(/^\s*[?:]/,!1)||"?"==t?I(Se):":"==e?I(ye):"spread"==e?I(Se):O(ye)}function xe(e,t){return"<"==t?I(B(">"),de(ye,">"),$,xe):"|"==t||"."==e||"&"==t?I(ye):"["==e?I(ye,q("]"),xe):"extends"==t||"implements"==t?(_.marked="keyword",I(ye)):"?"==t?I(ye,q(":"),ye):void 0}function ke(e,t){if("<"==t)return I(B(">"),de(ye,">"),$,xe)}function Ne(){return O(ye,_e)}function _e(e,t){if("="==t)return I(ye)}function Oe(e,t){return"enum"==t?(_.marked="keyword",I(nt)):O(Ie,he,Ae,Me)}function Ie(e,t){return d&&M(t)?(_.marked="keyword",I(Ie)):"variable"==e?(L(t),I()):"spread"==e?I(Ie):"["==e?fe(Le,"]"):"{"==e?fe(De,"}"):void 0}function De(e,t){return"variable"!=e||_.stream.match(/^\s*:/,!1)?("variable"==e&&(_.marked="property"),"spread"==e?I(Ie):"}"==e?O():"["==e?I(z,q("]"),q(":"),De):I(q(":"),Ie,Ae)):(L(t),I(Ae))}function Le(){return O(Ie,Ae)}function Ae(e,t){if("="==t)return I(W)}function Me(e){if(","==e)return I(Oe)}function Re(e,t){if("keyword b"==e&&"else"==t)return I(B("form","else"),H,$)}function Fe(e,t){return"await"==t?I(Fe):"("==e?I(B(")"),Pe,$):void 0}function Pe(e){return"var"==e?I(Oe,je):"variable"==e?I(je):O(je)}function je(e,t){return")"==e?I():";"==e?I(je):"in"==t||"of"==t?(_.marked="keyword",I(z,je)):O(z,je)}function Ve(e,t){return"*"==t?(_.marked="keyword",I(Ve)):"variable"==e?(L(t),I(Ve)):"("==e?I(j,B(")"),de($e,")"),$,ge,H,U):d&&"<"==t?I(B(">"),de(Ne,">"),$,Ve):void 0}function Ue(e,t){return"*"==t?(_.marked="keyword",I(Ue)):"variable"==e?(L(t),I(Ue)):"("==e?I(j,B(")"),de($e,")"),$,ge,U):d&&"<"==t?I(B(">"),de(Ne,">"),$,Ue):void 0}function Be(e,t){return"keyword"==e||"variable"==e?(_.marked="type",I(Be)):"<"==t?I(B(">"),de(Ne,">"),$):void 0}function $e(e,t){return"@"==t&&I(z,$e),"spread"==e?I($e):d&&M(t)?(_.marked="keyword",I($e)):d&&"this"==e?I(he,Ae):O(Ie,he,Ae)}function qe(e,t){return"variable"==e?He(e,t):Ge(e,t)}function He(e,t){if("variable"==e)return L(t),I(Ge)}function Ge(e,t){return"<"==t?I(B(">"),de(Ne,">"),$,Ge):"extends"==t||"implements"==t||d&&","==e?("implements"==t&&(_.marked="keyword"),I(d?ye:z,Ge)):"{"==e?I(B("}"),ze,$):void 0}function ze(e,t){return"async"==e||"variable"==e&&("static"==t||"get"==t||"set"==t||d&&M(t))&&_.stream.match(/^\s+[\w$\xa1-\uffff]/,!1)?(_.marked="keyword",I(ze)):"variable"==e||"keyword"==_.style?(_.marked="property",I(We,ze)):"number"==e||"string"==e?I(We,ze):"["==e?I(z,he,q("]"),We,ze):"*"==t?(_.marked="keyword",I(ze)):d&&"("==e?O(Ue,ze):";"==e||","==e?I(ze):"}"==e?I():"@"==t?I(z,ze):void 0}function We(e,t){if("!"==t)return I(We);if("?"==t)return I(We);if(":"==e)return I(ye,Ae);if("="==t)return I(W);var n=_.state.lexical.prev;return O(n&&"interface"==n.info?Ue:Ve)}function Ke(e,t){return"*"==t?(_.marked="keyword",I(et,q(";"))):"default"==t?(_.marked="keyword",I(z,q(";"))):"{"==e?I(de(Qe,"}"),et,q(";")):O(H)}function Qe(e,t){return"as"==t?(_.marked="keyword",I(q("variable"))):"variable"==e?O(W,Qe):void 0}function Xe(e){return"string"==e?I():"("==e?O(z):"."==e?O(Y):O(Ye,Je,et)}function Ye(e,t){return"{"==e?fe(Ye,"}"):("variable"==e&&L(t),"*"==t&&(_.marked="keyword"),I(Ze))}function Je(e){if(","==e)return I(Ye,Je)}function Ze(e,t){if("as"==t)return _.marked="keyword",I(Ye)}function et(e,t){if("from"==t)return _.marked="keyword",I(z)}function tt(e){return"]"==e?I():O(de(W,"]"))}function nt(){return O(B("form"),Ie,q("{"),B("}"),de(rt,"}"),$,$)}function rt(){return O(Ie,Ae)}function it(e,t){return"operator"==e.lastType||","==e.lastType||h.test(t.charAt(0))||/[,.]/.test(t.charAt(0))}function ot(e,t,n){return t.tokenize==y&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(t.lastType)||"quasi"==t.lastType&&/\{\s*$/.test(e.string.slice(0,e.pos-(n||0)))}return r(j,"pushcontext"),r(V,"pushblockcontext"),j.lex=V.lex=!0,r(U,"popcontext"),U.lex=!0,r(B,"pushlex"),r($,"poplex"),$.lex=!0,r(q,"expect"),r(H,"statement"),r(G,"maybeCatchBinding"),r(z,"expression"),r(W,"expressionNoComma"),r(K,"parenExpr"),r(Q,"expressionInner"),r(X,"maybeexpression"),r(Y,"maybeoperatorComma"),r(J,"maybeoperatorNoComma"),r(Z,"quasi"),r(ee,"continueQuasi"),r(te,"arrowBody"),r(ne,"arrowBodyNoComma"),r(re,"maybeTarget"),r(ie,"target"),r(oe,"targetNoComma"),r(ae,"maybelabel"),r(se,"property"),r(le,"objprop"),r(ue,"getterSetter"),r(ce,"afterprop"),r(de,"commasep"),r(fe,"contCommasep"),r(pe,"block"),r(he,"maybetype"),r(me,"maybetypeOrIn"),r(ge,"mayberettype"),r(ve,"isKW"),r(ye,"typeexpr"),r(be,"maybeReturnType"),r(Ee,"typeprops"),r(Te,"typeprop"),r(we,"quasiType"),r(Ce,"continueQuasiType"),r(Se,"typearg"),r(xe,"afterType"),r(ke,"maybeTypeArgs"),r(Ne,"typeparam"),r(_e,"maybeTypeDefault"),r(Oe,"vardef"),r(Ie,"pattern"),r(De,"proppattern"),r(Le,"eltpattern"),r(Ae,"maybeAssign"),r(Me,"vardefCont"),r(Re,"maybeelse"),r(Fe,"forspec"),r(Pe,"forspec1"),r(je,"forspec2"),r(Ve,"functiondef"),r(Ue,"functiondecl"),r(Be,"typename"),r($e,"funarg"),r(qe,"classExpression"),r(He,"className"),r(Ge,"classNameAfter"),r(ze,"classBody"),r(We,"classfield"),r(Ke,"afterExport"),r(Qe,"exportField"),r(Xe,"afterImport"),r(Ye,"importSpec"),r(Je,"maybeMoreImports"),r(Ze,"maybeAs"),r(et,"maybeFrom"),r(tt,"arrayLiteral"),r(nt,"enumdef"),r(rt,"enummember"),r(it,"isContinuedStatement"),r(ot,"expressionAllowed"),{startState:function(e){var n={tokenize:y,lastType:"sof",cc:[],lexical:new x((e||0)-a,0,"block",!1),localVars:t.localVars,context:t.localVars&&new R(null,null,!1),indented:e||0};return t.globalVars&&"object"==typeof t.globalVars&&(n.globalVars=t.globalVars),n},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),C(e,t)),t.tokenize!=E&&e.eatSpace())return null;var r=t.tokenize(e,t);return"comment"==n?r:(t.lastType="operator"!=n||"++"!=i&&"--"!=i?n:"incdec",N(t,r,n,i,e))},indent:function(e,n){if(e.tokenize==E||e.tokenize==T)return o.Pass;if(e.tokenize!=y)return 0;var r,i=n&&n.charAt(0),l=e.lexical;if(!/^\s*else\b/.test(n))for(var u=e.cc.length-1;u>=0;--u){var c=e.cc[u];if(c==$)l=l.prev;else if(c!=Re&&c!=U)break}for(;("stat"==l.type||"form"==l.type)&&("}"==i||(r=e.cc[e.cc.length-1])&&(r==Y||r==J)&&!/^[,\.=+\-*:?[\(]/.test(n));)l=l.prev;s&&")"==l.type&&"stat"==l.prev.type&&(l=l.prev);var d=l.type,f=i==d;return"vardef"==d?l.indented+("operator"==e.lastType||","==e.lastType?l.info.length+1:0):"form"==d&&"{"==i?l.indented:"form"==d?l.indented+a:"stat"==d?l.indented+(it(e,n)?s||a:0):"switch"!=l.info||f||0==t.doubleIndentSwitch?l.align?l.column+(f?0:1):l.indented+(f?0:a):l.indented+(/^(?:case|default)\b/.test(n)?a:2*a)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:u?null:"/*",blockCommentEnd:u?null:"*/",blockCommentContinue:u?null:" * ",lineComment:u?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:u?"json":"javascript",jsonldMode:l,jsonMode:u,expressionAllowed:ot,skipExpression:function(e){N(e,"atom","atom","true",new o.StringStream("",2,null))}}})),o.registerHelper("wordChars","javascript",/[\w$]/),o.defineMIME("text/javascript","javascript"),o.defineMIME("text/ecmascript","javascript"),o.defineMIME("application/javascript","javascript"),o.defineMIME("application/x-javascript","javascript"),o.defineMIME("application/ecmascript","javascript"),o.defineMIME("application/json",{name:"javascript",json:!0}),o.defineMIME("application/x-json",{name:"javascript",json:!0}),o.defineMIME("application/manifest+json",{name:"javascript",json:!0}),o.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),o.defineMIME("text/typescript",{name:"javascript",typescript:!0}),o.defineMIME("application/typescript",{name:"javascript",typescript:!0});var s=i({__proto__:null,default:a.exports},[a.exports]);e.j=s},void 0===(o=r.apply(t,i))||(e.exports=o)},4471:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535),n(8058)],void 0===(o="function"==typeof(r=function(e,t,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.j=void 0;var r=Object.defineProperty,i=(e,t)=>r(e,"name",{value:t,configurable:!0});function o(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}i(o,"_mergeNamespaces");var a={exports:{}};!function(e){function t(e,t,n,r,i){e.openDialog?e.openDialog(t,i,{value:r,selectValueOnOpen:!0,bottom:e.options.search.bottom}):i(prompt(n,r))}function n(e){return e.phrase("Jump to line:")+' '+e.phrase("(Use line:column or scroll% syntax)")+""}function r(e,t){var n=Number(t);return/^[-+]/.test(t)?e.getCursor().line+n:n-1}e.defineOption("search",{bottom:!1}),i(t,"dialog"),i(n,"getJumpDialog"),i(r,"interpretLine"),e.commands.jumpToLine=function(e){var i=e.getCursor();t(e,n(e),e.phrase("Jump to line:"),i.line+1+":"+i.ch,(function(t){var n;if(t)if(n=/^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(t))e.setCursor(r(e,n[1]),Number(n[2]));else if(n=/^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(t)){var o=Math.round(e.lineCount()*Number(n[1])/100);/^[-+]/.test(n[1])&&(o=i.line+o+1),e.setCursor(o-1,i.ch)}else(n=/^\s*\:?\s*([\+\-]?\d+)\s*/.exec(t))&&e.setCursor(r(e,n[1]),i.ch)}))},e.keyMap.default["Alt-G"]="jumpToLine"}(t.a.exports,n.a.exports);var s=o({__proto__:null,default:a.exports},[a.exports]);e.j=s})?r.apply(t,i):r)||(e.exports=o)},5980:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(2645),n(6856),n(9196),n(3573),n(1850),n(2635)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o,a){"use strict";var s=Object.defineProperty,l=(e,t)=>s(e,"name",{value:t,configurable:!0});function u(e,t){const n=t.target||t.srcElement;if(!(n instanceof HTMLElement))return;if("SPAN"!==(null==n?void 0:n.nodeName))return;const r=n.getBoundingClientRect(),i={left:(r.left+r.right)/2,top:(r.top+r.bottom)/2};e.state.jump.cursor=i,e.state.jump.isHoldingModifier&&h(e)}function c(e){e.state.jump.isHoldingModifier||!e.state.jump.cursor?e.state.jump.isHoldingModifier&&e.state.jump.marker&&m(e):e.state.jump.cursor=null}function d(t,n){if(t.state.jump.isHoldingModifier||!p(n.key))return;t.state.jump.isHoldingModifier=!0,t.state.jump.cursor&&h(t);const r=l((a=>{a.code===n.code&&(t.state.jump.isHoldingModifier=!1,t.state.jump.marker&&m(t),e.C.off(document,"keyup",r),e.C.off(document,"click",i),t.off("mousedown",o))}),"onKeyUp"),i=l((e=>{const{destination:n,options:r}=t.state.jump;n&&r.onClick(n,e)}),"onClick"),o=l(((e,n)=>{t.state.jump.destination&&(n.codemirrorIgnore=!0)}),"onMouseDown");e.C.on(document,"keyup",r),e.C.on(document,"click",i),t.on("mousedown",o)}e.C.defineOption("jump",!1,((t,n,r)=>{if(r&&r!==e.C.Init){const n=t.state.jump.onMouseOver;e.C.off(t.getWrapperElement(),"mouseover",n);const r=t.state.jump.onMouseOut;e.C.off(t.getWrapperElement(),"mouseout",r),e.C.off(document,"keydown",t.state.jump.onKeyDown),delete t.state.jump}if(n){const r=t.state.jump={options:n,onMouseOver:u.bind(null,t),onMouseOut:c.bind(null,t),onKeyDown:d.bind(null,t)};e.C.on(t.getWrapperElement(),"mouseover",r.onMouseOver),e.C.on(t.getWrapperElement(),"mouseout",r.onMouseOut),e.C.on(document,"keydown",r.onKeyDown)}})),l(u,"onMouseOver"),l(c,"onMouseOut"),l(d,"onKeyDown");const f="undefined"!=typeof navigator&&navigator&&navigator.appVersion.includes("Mac");function p(e){return e===(f?"Meta":"Control")}function h(e){if(e.state.jump.marker)return;const{cursor:t,options:n}=e.state.jump,r=e.coordsChar(t),i=e.getTokenAt(r,!0),o=n.getDestination||e.getHelper(r,"jump");if(o){const t=o(i,n,e);if(t){const n=e.markText({line:r.line,ch:i.start},{line:r.line,ch:i.end},{className:"CodeMirror-jump-token"});e.state.jump.marker=n,e.state.jump.destination=t}}}function m(e){const{marker:t}=e.state.jump;e.state.jump.marker=null,e.state.jump.destination=null,t.clear()}l(p,"isJumpModifier"),l(h,"enableJumpMode"),l(m,"disableJumpMode"),e.C.registerHelper("jump","graphql",((e,n)=>{if(!n.schema||!n.onClick||!e.state)return;const{state:r}=e,{kind:i,step:o}=r,a=(0,t.g)(n.schema,r);return"Field"===i&&0===o&&a.fieldDef||"AliasedField"===i&&2===o&&a.fieldDef?(0,t.a)(a):"Directive"===i&&1===o&&a.directiveDef?(0,t.b)(a):"Argument"===i&&0===o&&a.argDef?(0,t.c)(a):"EnumValue"===i&&a.enumValue?(0,t.d)(a):"NamedType"===i&&a.type?(0,t.e)(a):void 0}))})?r.apply(t,i):r)||(e.exports=o)},9444:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(3573),n(6856),n(5609),n(9196),n(1850)],r=function(e,t,n,r,i,o){"use strict";var a=Object.defineProperty,s=(e,t)=>a(e,"name",{value:t,configurable:!0});const l=[t.LoneSchemaDefinitionRule,t.UniqueOperationTypesRule,t.UniqueTypeNamesRule,t.UniqueEnumValueNamesRule,t.UniqueFieldDefinitionNamesRule,t.UniqueDirectiveNamesRule,t.KnownTypeNamesRule,t.KnownDirectivesRule,t.UniqueDirectivesPerLocationRule,t.PossibleTypeExtensionsRule,t.UniqueArgumentNamesRule,t.UniqueInputFieldNamesRule];function u(e,n,r,i,o){const a=t.specifiedRules.filter((e=>e!==t.NoUnusedFragmentsRule&&e!==t.ExecutableDefinitionsRule&&(!i||e!==t.KnownFragmentNamesRule)));return r&&Array.prototype.push.apply(a,r),o&&Array.prototype.push.apply(a,l),(0,t.validate)(e,n,a).filter((e=>{if(e.message.includes("Unknown directive")&&e.nodes){const n=e.nodes[0];if(n&&n.kind===t.Kind.DIRECTIVE){const e=n.name.value;if("arguments"===e||"argumentDefinitions"===e)return!1}}return!0}))}s(u,"validateWithCustomRules");const c={["Error"]:1,["Warning"]:2,["Information"]:3,["Hint"]:4},d=s(((e,t)=>{if(!e)throw new Error(t)}),"invariant");function f(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0,o=arguments.length>4?arguments[4]:void 0;var a,s;let l=null,u="";o&&(u="string"==typeof o?o:o.reduce(((e,n)=>e+(0,t.print)(n)+"\n\n"),""));const d=u?`${e}\n\n${u}`:e;try{l=(0,t.parse)(d)}catch(e){if(e instanceof t.GraphQLError){const t=m(null!==(s=null===(a=e.locations)||void 0===a?void 0:a[0])&&void 0!==s?s:{line:0,column:0},d);return[{severity:c.Error,message:e.message,source:"GraphQL: Syntax",range:t}]}throw e}return p(l,n,r,i)}function p(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;if(!n)return[];const r=u(n,e,arguments.length>2?arguments[2]:void 0,arguments.length>3?arguments[3]:void 0).flatMap((e=>h(e,c.Error,"Validation"))),i=(0,t.validate)(n,e,[t.NoDeprecatedCustomRule]).flatMap((e=>h(e,c.Warning,"Deprecation")));return r.concat(i)}function h(e,t,n){if(!e.nodes)return[];const i=[];for(const[o,a]of e.nodes.entries()){const s="Variable"!==a.kind&&"name"in a&&void 0!==a.name?a.name:"variable"in a&&void 0!==a.variable?a.variable:a;if(s){d(e.locations,"GraphQL validation error requires locations.");const a=e.locations[o],l=g(s),u=a.column+(l.end-l.start);i.push({source:`GraphQL: ${n}`,message:e.message,severity:t,range:new r.R(new r.P(a.line-1,a.column-1),new r.P(a.line-1,u))})}}return i}function m(e,t){const i=(0,n.o)(),o=i.startState(),a=t.split("\n");d(a.length>=e.line,"Query text must have more lines than where the error happened");let s=null;for(let t=0;t{const{schema:r,validationRules:i,externalFragments:o}=n;return f(t,r,i,void 0,o).map((t=>({message:t.message,severity:t.severity?v[t.severity-1]:v[0],type:t.source?y[t.source]:void 0,from:e.C.Pos(t.range.start.line,t.range.start.character),to:e.C.Pos(t.range.end.line,t.range.end.character)})))}))},void 0===(o=r.apply(t,i))||(e.exports=o)},8535:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(3573),n(6856),n(9196),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i){"use strict";var o=Object.defineProperty,a=(e,t)=>o(e,"name",{value:t,configurable:!0});function s(e){l=e,u=e.length,c=d=f=-1,S(),x();const t=m();return E("EOF"),t}let l,u,c,d,f,p,h;function m(){const e=c,t=[];if(E("{"),!C("}")){do{t.push(g())}while(C(","));E("}")}return{kind:"Object",start:e,end:f,members:t}}function g(){const e=c,t="String"===h?b():null;E("String"),E(":");const n=y();return{kind:"Member",start:e,end:f,key:t,value:n}}function v(){const e=c,t=[];if(E("["),!C("]")){do{t.push(y())}while(C(","));E("]")}return{kind:"Array",start:e,end:f,values:t}}function y(){switch(h){case"[":return v();case"{":return m();case"String":case"Number":case"Boolean":case"Null":const e=b();return x(),e}E("Value")}function b(){return{kind:h,start:c,end:d,value:JSON.parse(l.slice(c,d))}}function E(e){if(h===e)return void x();let t;if("EOF"===h)t="[end of file]";else if(d-c>1)t="`"+l.slice(c,d)+"`";else{const e=l.slice(c).match(/^.+?\b/);t="`"+(e?e[0]:l[c])+"`"}throw w(`Expected ${e} but found ${t}.`)}a(s,"jsonParse"),a(m,"parseObj"),a(g,"parseMember"),a(v,"parseArr"),a(y,"parseVal"),a(b,"curToken"),a(E,"expect");class T extends Error{constructor(e,t){super(e),this.position=t}}function w(e){return new T(e,{start:c,end:d})}function C(e){if(h===e)return x(),!0}function S(){return d31;)if(92===p)switch(p=S(),p){case 34:case 47:case 92:case 98:case 102:case 110:case 114:case 116:S();break;case 117:S(),N(),N(),N(),N();break;default:throw w("Bad character escape sequence.")}else{if(d===u)throw w("Unterminated string.");S()}if(34!==p)throw w("Unterminated string.");S()}function N(){if(p>=48&&p<=57||p>=65&&p<=70||p>=97&&p<=102)return S();throw w("Expected hexadecimal digit.")}function _(){45===p&&S(),48===p?S():O(),46===p&&(S(),O()),69!==p&&101!==p||(p=S(),43!==p&&45!==p||S(),O())}function O(){if(p<48||p>57)throw w("Expected decimal digit.");do{S()}while(p>=48&&p<=57)}function I(e,t,n){var r;const i=[];for(const o of n.members)if(o){const n=null===(r=o.key)||void 0===r?void 0:r.value,a=t[n];if(a)for(const[t,n]of D(a,o.value))i.push(L(e,t,n));else i.push(L(e,o.key,`Variable "$${n}" does not appear in any GraphQL query.`))}return i}function D(e,n){if(!e||!n)return[];if(e instanceof t.GraphQLNonNull)return"Null"===n.kind?[[n,`Type "${e}" is non-nullable and cannot be null.`]]:D(e.ofType,n);if("Null"===n.kind)return[];if(e instanceof t.GraphQLList){const t=e.ofType;return"Array"===n.kind?M(n.values||[],(e=>D(t,e))):D(t,n)}if(e instanceof t.GraphQLInputObjectType){if("Object"!==n.kind)return[[n,`Type "${e}" must be an Object.`]];const r=Object.create(null),i=M(n.members,(t=>{var n;const i=null===(n=null==t?void 0:t.key)||void 0===n?void 0:n.value;r[i]=!0;const o=e.getFields()[i];return o?D(o?o.type:void 0,t.value):[[t.key,`Type "${e}" does not have a field "${i}".`]]}));for(const o of Object.keys(e.getFields())){const a=e.getFields()[o];!r[o]&&a.type instanceof t.GraphQLNonNull&&!a.defaultValue&&i.push([n,`Object of type "${e}" is missing required field "${o}".`])}return i}return"Boolean"===e.name&&"Boolean"!==n.kind||"String"===e.name&&"String"!==n.kind||"ID"===e.name&&"Number"!==n.kind&&"String"!==n.kind||"Float"===e.name&&"Number"!==n.kind||"Int"===e.name&&("Number"!==n.kind||(0|n.value)!==n.value)||(e instanceof t.GraphQLEnumType||e instanceof t.GraphQLScalarType)&&("String"!==n.kind&&"Number"!==n.kind&&"Boolean"!==n.kind&&"Null"!==n.kind||A(e.parseValue(n.value)))?[[n,`Expected value of type "${e}".`]]:[]}function L(e,t,n){return{message:n,severity:"error",type:"validation",from:e.posFromIndex(t.start),to:e.posFromIndex(t.end)}}function A(e){return null==e||e!=e}function M(e,t){return Array.prototype.concat.apply([],e.map(t))}a(T,"JSONSyntaxError"),a(w,"syntaxError"),a(C,"skip"),a(S,"ch"),a(x,"lex"),a(k,"readString"),a(N,"readHex"),a(_,"readNumber"),a(O,"readDigits"),e.C.registerHelper("lint","graphql-variables",((e,t,n)=>{if(!e)return[];let r;try{r=s(e)}catch(e){if(e instanceof T)return[L(n,e.position,e.message)];throw e}const{variableToType:i}=t;return i?I(n,i,r):[]})),a(I,"validateVariables"),a(D,"validateValue"),a(L,"lintError"),a(A,"isNullish"),a(M,"mapCat")})?r.apply(t,i):r)||(e.exports=o)},4054:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.l=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){var t="CodeMirror-lint-markers",n="CodeMirror-lint-line-";function i(t,n,i){var o=document.createElement("div");function a(t){if(!o.parentNode)return e.off(document,"mousemove",a);o.style.top=Math.max(0,t.clientY-o.offsetHeight-5)+"px",o.style.left=t.clientX+5+"px"}return o.className="CodeMirror-lint-tooltip cm-s-"+t.options.theme,o.appendChild(i.cloneNode(!0)),t.state.lint.options.selfContain?t.getWrapperElement().appendChild(o):document.body.appendChild(o),r(a,"position"),e.on(document,"mousemove",a),a(n),null!=o.style.opacity&&(o.style.opacity=1),o}function o(e){e.parentNode&&e.parentNode.removeChild(e)}function a(e){e.parentNode&&(null==e.style.opacity&&o(e),e.style.opacity=0,setTimeout((function(){o(e)}),600))}function s(t,n,o,s){var l=i(t,n,o);function u(){e.off(s,"mouseout",u),l&&(a(l),l=null)}r(u,"hide");var c=setInterval((function(){if(l)for(var e=s;;e=e.parentNode){if(e&&11==e.nodeType&&(e=e.host),e==document.body)return;if(!e){u();break}}if(!l)return clearInterval(c)}),400);e.on(s,"mouseout",u)}function l(e,t,n){for(var r in this.marked=[],t instanceof Function&&(t={getAnnotations:t}),t&&!0!==t||(t={}),this.options={},this.linterOptions=t.options||{},u)this.options[r]=u[r];for(var r in t)u.hasOwnProperty(r)?null!=t[r]&&(this.options[r]=t[r]):t.options||(this.linterOptions[r]=t[r]);this.timeout=null,this.hasGutter=n,this.onMouseOver=function(t){T(e,t)},this.waitingFor=0}r(i,"showTooltip"),r(o,"rm"),r(a,"hideTooltip"),r(s,"showTooltipFor"),r(l,"LintState");var u={highlightLines:!1,tooltips:!0,delay:500,lintOnChange:!0,getAnnotations:null,async:!1,selfContain:null,formatAnnotation:null,onUpdateLinting:null};function c(e){var n=e.state.lint;n.hasGutter&&e.clearGutter(t),n.options.highlightLines&&d(e);for(var r=0;r-1)&&u.push(e.message)}));for(var d=null,g=i.hasGutter&&document.createDocumentFragment(),v=0;v1,o.tooltips)),o.highlightLines&&e.addLineClass(s,"wrap",n+d)}}o.onUpdateLinting&&o.onUpdateLinting(r,a,e)}}function b(e){var t=e.state.lint;t&&(clearTimeout(t.timeout),t.timeout=setTimeout((function(){v(e)}),t.options.delay))}function E(e,t,n){for(var r=n.target||n.srcElement,i=document.createDocumentFragment(),o=0;on(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};e.a=o,function(e){var t=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),n=e.Pos,i={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<","<":">>",">":"<<"};function o(e){return e&&e.bracketRegex||/[(){}[\]]/}function a(e,t,r){var a=e.getLineHandle(t.line),l=t.ch-1,u=r&&r.afterCursor;null==u&&(u=/(^| )cm-fat-cursor($| )/.test(e.getWrapperElement().className));var c=o(r),d=!u&&l>=0&&c.test(a.text.charAt(l))&&i[a.text.charAt(l)]||c.test(a.text.charAt(l+1))&&i[a.text.charAt(++l)];if(!d)return null;var f=">"==d.charAt(1)?1:-1;if(r&&r.strict&&f>0!=(l==t.ch))return null;var p=e.getTokenTypeAt(n(t.line,l+1)),h=s(e,n(t.line,l+(f>0?1:0)),f,p,r);return null==h?null:{from:n(t.line,l),to:h&&h.pos,match:h&&h.ch==d.charAt(0),forward:f>0}}function s(e,t,r,a,s){for(var l=s&&s.maxScanLineLength||1e4,u=s&&s.maxScanLines||1e3,c=[],d=o(s),f=r>0?Math.min(t.line+u,e.lastLine()+1):Math.max(e.firstLine()-1,t.line-u),p=t.line;p!=f;p+=r){var h=e.getLine(p);if(h){var m=r>0?0:h.length-1,g=r>0?h.length:-1;if(!(h.length>l))for(p==t.line&&(m=t.ch-(r<0?1:0));m!=g;m+=r){var v=h.charAt(m);if(d.test(v)&&(void 0===a||(e.getTokenTypeAt(n(p,m+1))||"")==(a||""))){var y=i[v];if(y&&">"==y.charAt(1)==r>0)c.push(v);else{if(!c.length)return{pos:n(p,m),ch:v};c.pop()}}}}}return p-r!=(r>0?e.lastLine():e.firstLine())&&null}function l(e,i,o){for(var s=e.state.matchBrackets.maxHighlightLineLength||1e3,l=o&&o.highlightNonMatching,u=[],c=e.listSelections(),d=0;da((e=>{const t=(0,n.o)({eatWhitespace:e=>e.eatWhile(n.i),lexRules:n.L,parseRules:n.P,editorConfig:{tabSize:e.tabSize}});return{config:e,startState:t.startState,token:t.token,indent:r.i,electricInput:/^\s*[})\]]/,fold:"brace",lineComment:"#",closeBrackets:{pairs:'()[]{}""',explode:"()[]{}"}}}),"name",{value:"graphqlModeFactory",configurable:!0}))();e.C.defineMode("graphql",s)})?r.apply(t,i):r)||(e.exports=o)},1430:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(3573),n(6856),n(6592),n(9196),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o){"use strict";e.C.defineMode("graphql-results",(e=>{const t=(0,n.o)({eatWhitespace:e=>e.eatSpace(),lexRules:a,parseRules:s,editorConfig:{tabSize:e.tabSize}});return{config:e,startState:t.startState,token:t.token,indent:r.i,electricInput:/^\s*[}\]]/,fold:"brace",closeBrackets:{pairs:'[]{}""',explode:"[]{}"}}}));const a={Punctuation:/^\[|]|\{|\}|:|,/,Number:/^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,String:/^"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?/,Keyword:/^true|false|null/},s={Document:[(0,n.p)("{"),(0,n.l)("Entry",(0,n.p)(",")),(0,n.p)("}")],Entry:[(0,n.t)("String","def"),(0,n.p)(":"),"Value"],Value(e){switch(e.kind){case"Number":return"NumberValue";case"String":return"StringValue";case"Punctuation":switch(e.value){case"[":return"ListValue";case"{":return"ObjectValue"}return null;case"Keyword":switch(e.value){case"true":case"false":return"BooleanValue";case"null":return"NullValue"}return null}},NumberValue:[(0,n.t)("Number","number")],StringValue:[(0,n.t)("String","string")],BooleanValue:[(0,n.t)("Keyword","builtin")],NullValue:[(0,n.t)("Keyword","keyword")],ListValue:[(0,n.p)("["),(0,n.l)("Value",(0,n.p)(",")),(0,n.p)("]")],ObjectValue:[(0,n.p)("{"),(0,n.l)("ObjectField",(0,n.p)(",")),(0,n.p)("}")],ObjectField:[(0,n.t)("String","property"),(0,n.p)(":"),"Value"]}})?r.apply(t,i):r)||(e.exports=o)},3340:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[n(535),n(3573),n(6856),n(6592),n(9196),n(1850)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o){"use strict";var a=Object.defineProperty;e.C.defineMode("graphql-variables",(e=>{const t=(0,n.o)({eatWhitespace:e=>e.eatSpace(),lexRules:s,parseRules:l,editorConfig:{tabSize:e.tabSize}});return{config:e,startState:t.startState,token:t.token,indent:r.i,electricInput:/^\s*[}\]]/,fold:"brace",closeBrackets:{pairs:'[]{}""',explode:"[]{}"}}}));const s={Punctuation:/^\[|]|\{|\}|:|,/,Number:/^-?(?:0|(?:[1-9][0-9]*))(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?/,String:/^"(?:[^"\\]|\\(?:"|\/|\\|b|f|n|r|t|u[0-9a-fA-F]{4}))*"?/,Keyword:/^true|false|null/},l={Document:[(0,n.p)("{"),(0,n.l)("Variable",(0,n.b)((0,n.p)(","))),(0,n.p)("}")],Variable:[u("variable"),(0,n.p)(":"),"Value"],Value(e){switch(e.kind){case"Number":return"NumberValue";case"String":return"StringValue";case"Punctuation":switch(e.value){case"[":return"ListValue";case"{":return"ObjectValue"}return null;case"Keyword":switch(e.value){case"true":case"false":return"BooleanValue";case"null":return"NullValue"}return null}},NumberValue:[(0,n.t)("Number","number")],StringValue:[(0,n.t)("String","string")],BooleanValue:[(0,n.t)("Keyword","builtin")],NullValue:[(0,n.t)("Keyword","keyword")],ListValue:[(0,n.p)("["),(0,n.l)("Value",(0,n.b)((0,n.p)(","))),(0,n.p)("]")],ObjectValue:[(0,n.p)("{"),(0,n.l)("ObjectField",(0,n.b)((0,n.p)(","))),(0,n.p)("}")],ObjectField:[u("attribute"),(0,n.p)(":"),"Value"]};function u(e){return{style:e,match:e=>"String"===e.kind,update(e,t){e.name=t.value.slice(1,-1)}}}a(u,"name",{value:"namedKey",configurable:!0})})?r.apply(t,i):r)||(e.exports=o)},9509:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535),n(9407),n(8058)],r=function(e,t,n,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.s=void 0;var i=Object.defineProperty,o=(e,t)=>i(e,"name",{value:t,configurable:!0});function a(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}o(a,"_mergeNamespaces");var s={exports:{}};!function(e){function t(e,t){return"string"==typeof e?e=new RegExp(e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),t?"gi":"g"):e.global||(e=new RegExp(e.source,e.ignoreCase?"gi":"g")),{token:function(t){e.lastIndex=t.pos;var n=e.exec(t.string);if(n&&n.index==t.pos)return t.pos+=n[0].length||1,"searching";n?t.pos=n.index:t.skipToEnd()}}}function n(){this.posFrom=this.posTo=this.lastQuery=this.query=null,this.overlay=null}function r(e){return e.state.search||(e.state.search=new n)}function i(e){return"string"==typeof e&&e==e.toLowerCase()}function a(e,t,n){return e.getSearchCursor(t,n,{caseFold:i(t),multiline:!0})}function s(e,t,n,r,i){e.openDialog(t,r,{value:n,selectValueOnOpen:!0,closeOnEnter:!1,onClose:function(){m(e)},onKeyDown:i,bottom:e.options.search.bottom})}function l(e,t,n,r,i){e.openDialog?e.openDialog(t,i,{value:r,selectValueOnOpen:!0,bottom:e.options.search.bottom}):i(prompt(n,r))}function u(e,t,n,r){e.openConfirm?e.openConfirm(t,r):confirm(n)&&r[0]()}function c(e){return e.replace(/\\([nrt\\])/g,(function(e,t){return"n"==t?"\n":"r"==t?"\r":"t"==t?"\t":"\\"==t?"\\":e}))}function d(e){var t=e.match(/^\/(.*)\/([a-z]*)$/);if(t)try{e=new RegExp(t[1],-1==t[2].indexOf("i")?"":"i")}catch(e){}else e=c(e);return("string"==typeof e?""==e:e.test(""))&&(e=/x^/),e}function f(e,n,r){n.queryText=r,n.query=d(r),e.removeOverlay(n.overlay,i(n.query)),n.overlay=t(n.query,i(n.query)),e.addOverlay(n.overlay),e.showMatchesOnScrollbar&&(n.annotate&&(n.annotate.clear(),n.annotate=null),n.annotate=e.showMatchesOnScrollbar(n.query,i(n.query)))}function p(t,n,i,a){var u=r(t);if(u.query)return h(t,n);var c=t.getSelection()||u.lastQuery;if(c instanceof RegExp&&"x^"==c.source&&(c=null),i&&t.openDialog){var d=null,p=o((function(n,r){e.e_stop(r),n&&(n!=u.queryText&&(f(t,u,n),u.posFrom=u.posTo=t.getCursor()),d&&(d.style.opacity=1),h(t,r.shiftKey,(function(e,n){var r;n.line<3&&document.querySelector&&(r=t.display.wrapper.querySelector(".CodeMirror-dialog"))&&r.getBoundingClientRect().bottom-4>t.cursorCoords(n,"window").top&&((d=r).style.opacity=.4)})))}),"searchNext");s(t,v(t),c,p,(function(n,i){var o=e.keyName(n),a=t.getOption("extraKeys"),s=a&&a[o]||e.keyMap[t.getOption("keyMap")][o];"findNext"==s||"findPrev"==s||"findPersistentNext"==s||"findPersistentPrev"==s?(e.e_stop(n),f(t,r(t),i),t.execCommand(s)):"find"!=s&&"findPersistent"!=s||(e.e_stop(n),p(i,n))})),a&&c&&(f(t,u,c),h(t,n))}else l(t,v(t),"Search for:",c,(function(e){e&&!u.query&&t.operation((function(){f(t,u,e),u.posFrom=u.posTo=t.getCursor(),h(t,n)}))}))}function h(t,n,i){t.operation((function(){var o=r(t),s=a(t,o.query,n?o.posFrom:o.posTo);(s.find(n)||(s=a(t,o.query,n?e.Pos(t.lastLine()):e.Pos(t.firstLine(),0))).find(n))&&(t.setSelection(s.from(),s.to()),t.scrollIntoView({from:s.from(),to:s.to()},20),o.posFrom=s.from(),o.posTo=s.to(),i&&i(s.from(),s.to()))}))}function m(e){e.operation((function(){var t=r(e);t.lastQuery=t.query,t.query&&(t.query=t.queryText=null,e.removeOverlay(t.overlay),t.annotate&&(t.annotate.clear(),t.annotate=null))}))}function g(e,t){var n=e?document.createElement(e):document.createDocumentFragment();for(var r in t)n[r]=t[r];for(var i=2;in(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};e.a=o,function(e){var t,n,i=e.Pos;function o(e){var t=e.flags;return null!=t?t:(e.ignoreCase?"i":"")+(e.global?"g":"")+(e.multiline?"m":"")}function a(e,t){for(var n=o(e),r=n,i=0;ic);d++){var f=e.getLine(u++);r=null==r?f:r+"\n"+f}o*=2,t.lastIndex=n.ch;var p=t.exec(r);if(p){var h=r.slice(0,p.index).split("\n"),m=p[0].split("\n"),g=n.line+h.length-1,v=h[h.length-1].length;return{from:i(g,v),to:i(g+m.length-1,1==m.length?v+m[0].length:m[m.length-1].length),match:p}}}}function c(e,t,n){for(var r,i=0;i<=e.length;){t.lastIndex=i;var o=t.exec(e);if(!o)break;var a=o.index+o[0].length;if(a>e.length-n)break;(!r||a>r.index+r[0].length)&&(r=o),i=o.index+1}return r}function d(e,t,n){t=a(t,"g");for(var r=n.line,o=n.ch,s=e.firstLine();r>=s;r--,o=-1){var l=e.getLine(r),u=c(l,t,o<0?0:l.length-o);if(u)return{from:i(r,u.index),to:i(r,u.index+u[0].length),match:u}}}function f(e,t,n){if(!s(t))return d(e,t,n);t=a(t,"gm");for(var r,o=1,l=e.getLine(n.line).length-n.ch,u=n.line,f=e.firstLine();u>=f;){for(var p=0;p=f;p++){var h=e.getLine(u--);r=null==r?h:h+"\n"+r}o*=2;var m=c(r,t,l);if(m){var g=r.slice(0,m.index).split("\n"),v=m[0].split("\n"),y=u+g.length,b=g[g.length-1].length;return{from:i(y,b),to:i(y+v.length-1,1==v.length?b+v[0].length:v[v.length-1].length),match:m}}}}function p(e,t,n,r){if(e.length==t.length)return n;for(var i=0,o=n+Math.max(0,e.length-t.length);;){if(i==o)return i;var a=i+o>>1,s=r(e.slice(0,a)).length;if(s==n)return a;s>n?o=a:i=a+1}}function h(e,r,o,a){if(!r.length)return null;var s=a?t:n,l=s(r).split(/\r|\n\r?/);e:for(var u=o.line,c=o.ch,d=e.lastLine()+1-l.length;u<=d;u++,c=0){var f=e.getLine(u).slice(c),h=s(f);if(1==l.length){var m=h.indexOf(l[0]);if(-1==m)continue e;return o=p(f,h,m,s)+c,{from:i(u,p(f,h,m,s)+c),to:i(u,p(f,h,m+l[0].length,s)+c)}}var g=h.length-l[0].length;if(h.slice(g)==l[0]){for(var v=1;v=d;u--,c=-1){var f=e.getLine(u);c>-1&&(f=f.slice(0,c));var h=s(f);if(1==l.length){var m=h.lastIndexOf(l[0]);if(-1==m)continue e;return{from:i(u,p(f,h,m,s)),to:i(u,p(f,h,m+l[0].length,s))}}var g=l[l.length-1];if(h.slice(0,g.length)==g){var v=1;for(o=u-l.length+1;v(this.doc.getLine(n.line)||"").length&&(n.ch=0,n.line++)),0!=e.cmpPos(n,this.doc.clipPos(n))))return this.atOccurrence=!1;var r=this.matches(t,n);if(this.afterEmptyMatch=r&&0==e.cmpPos(r.from,r.to),r)return this.pos=r,this.atOccurrence=!0,this.pos.match||!0;var o=i(t?this.doc.firstLine():this.doc.lastLine()+1,0);return this.pos={from:o,to:o},this.atOccurrence=!1},from:function(){if(this.atOccurrence)return this.pos.from},to:function(){if(this.atOccurrence)return this.pos.to},replace:function(t,n){if(this.atOccurrence){var r=e.splitLines(t);this.doc.replaceRange(r,this.pos.from,this.pos.to,n),this.pos.to=i(this.pos.from.line+r.length-1,r[r.length-1].length+(1==r.length?this.pos.from.ch:0))}}},e.defineExtension("getSearchCursor",(function(e,t,n){return new g(this.doc,e,t,n)})),e.defineDocExtension("getSearchCursor",(function(e,t,n){return new g(this,e,t,n)})),e.defineExtension("selectMatches",(function(t,n){for(var r=[],i=this.getSearchCursor(t,this.getCursor("from"),n);i.findNext()&&!(e.cmpPos(i.to(),this.getCursor("to"))>0);)r.push({anchor:i.from(),head:i.to()});r.length&&this.setSelections(r,0)}))}(t.a.exports);var a=i({__proto__:null,default:o.exports},[o.exports]);e.s=a})?r.apply(t,i):r)||(e.exports=o)},6980:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.s=void 0;var n=Object.defineProperty,r=(e,t)=>n(e,"name",{value:t,configurable:!0});function i(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}r(i,"_mergeNamespaces");var o={exports:{}};!function(e){var t="CodeMirror-hint",n="CodeMirror-hint-active";function i(e,t){if(this.cm=e,this.options=t,this.widget=null,this.debounce=0,this.tick=0,this.startPos=this.cm.getCursor("start"),this.startLen=this.cm.getLine(this.startPos.line).length-this.cm.getSelection().length,this.options.updateOnCursorActivity){var n=this;e.on("cursorActivity",this.activityFunc=function(){n.cursorActivity()})}}e.showHint=function(e,t,n){if(!t)return e.showHint(n);n&&n.async&&(t.async=!0);var r={hint:t};if(n)for(var i in n)r[i]=n[i];return e.showHint(r)},e.defineExtension("showHint",(function(t){t=s(this,this.getCursor("start"),t);var n=this.listSelections();if(!(n.length>1)){if(this.somethingSelected()){if(!t.hint.supportsSelection)return;for(var r=0;rf.clientHeight+1;if(setTimeout((function(){D=a.getScrollInfo()})),L.bottom-I>0){var M=L.bottom-L.top;if(E.top-(E.bottom-L.top)-M>0)f.style.top=(w=E.top-M-x)+"px",C=!1;else if(M>I){f.style.height=I-5+"px",f.style.top=(w=E.bottom-L.top-x)+"px";var R=a.getCursor();i.from.ch!=R.ch&&(E=a.cursorCoords(R),f.style.left=(T=E.left-S)+"px",L=f.getBoundingClientRect())}}var F,P=L.right-O;if(A&&(P+=a.display.nativeBarWidth),P>0&&(L.right-L.left>O&&(f.style.width=O-5+"px",P-=L.right-L.left-O),f.style.left=(T=E.left-P-S)+"px"),A)for(var j=f.firstChild;j;j=j.nextSibling)j.style.paddingRight=a.display.nativeBarWidth+"px";a.addKeyMap(this.keyMap=u(r,{moveFocus:function(e,t){o.changeActive(o.selectedHint+e,t)},setFocus:function(e){o.changeActive(e)},menuSize:function(){return o.screenAmount()},length:h.length,close:function(){r.close()},pick:function(){o.pick()},data:i})),r.options.closeOnUnfocus&&(a.on("blur",this.onBlur=function(){F=setTimeout((function(){r.close()}),100)}),a.on("focus",this.onFocus=function(){clearTimeout(F)})),a.on("scroll",this.onScroll=function(){var e=a.getScrollInfo(),t=a.getWrapperElement().getBoundingClientRect();D||(D=a.getScrollInfo());var n=w+D.top-e.top,i=n-(d.pageYOffset||(s.documentElement||s.body).scrollTop);if(C||(i+=f.offsetHeight),i<=t.top||i>=t.bottom)return r.close();f.style.top=n+"px",f.style.left=T+D.left-e.left+"px"}),e.on(f,"dblclick",(function(e){var t=c(f,e.target||e.srcElement);t&&null!=t.hintId&&(o.changeActive(t.hintId),o.pick())})),e.on(f,"click",(function(e){var t=c(f,e.target||e.srcElement);t&&null!=t.hintId&&(o.changeActive(t.hintId),r.options.completeOnSingleClick&&o.pick())})),e.on(f,"mousedown",(function(){setTimeout((function(){a.focus()}),20)}));var V=this.getSelectedHintRange();return 0===V.from&&0===V.to||this.scrollToActive(),e.signal(i,"select",h[this.selectedHint],f.childNodes[this.selectedHint]),!0}function f(e,t){if(!e.somethingSelected())return t;for(var n=[],r=0;r0?t(e):a(r+1)}))}r(a,"run"),a(0)}),"resolved");return a.async=!0,a.supportsSelection=!0,a}return(i=t.getHelper(t.getCursor(),"hintWords"))?function(t){return e.hint.fromList(t,{words:i})}:e.hint.anyword?function(t,n){return e.hint.anyword(t,n)}:function(){}}i.prototype={close:function(){this.active()&&(this.cm.state.completionActive=null,this.tick=null,this.options.updateOnCursorActivity&&this.cm.off("cursorActivity",this.activityFunc),this.widget&&this.data&&e.signal(this.data,"close"),this.widget&&this.widget.close(),e.signal(this.cm,"endCompletion",this.cm))},active:function(){return this.cm.state.completionActive==this},pick:function(t,n){var r=t.list[n],i=this;this.cm.operation((function(){r.hint?r.hint(i.cm,t,r):i.cm.replaceRange(l(r),r.from||t.from,r.to||t.to,"complete"),e.signal(t,"pick",r),i.cm.scrollIntoView()})),this.options.closeOnPick&&this.close()},cursorActivity:function(){this.debounce&&(a(this.debounce),this.debounce=0);var e=this.startPos;this.data&&(e=this.data.from);var t=this.cm.getCursor(),n=this.cm.getLine(t.line);if(t.line!=this.startPos.line||n.length-t.ch!=this.startLen-this.startPos.ch||t.ch=this.data.list.length?t=r?this.data.list.length-1:0:t<0&&(t=r?0:this.data.list.length-1),this.selectedHint!=t){var i=this.hints.childNodes[this.selectedHint];i&&(i.className=i.className.replace(" "+n,""),i.removeAttribute("aria-selected")),(i=this.hints.childNodes[this.selectedHint=t]).className+=" "+n,i.setAttribute("aria-selected","true"),this.completion.cm.getInputField().setAttribute("aria-activedescendant",i.id),this.scrollToActive(),e.signal(this.data,"select",this.data.list[this.selectedHint],i)}},scrollToActive:function(){var e=this.getSelectedHintRange(),t=this.hints.childNodes[e.from],n=this.hints.childNodes[e.to],r=this.hints.firstChild;t.offsetTopthis.hints.scrollTop+this.hints.clientHeight&&(this.hints.scrollTop=n.offsetTop+n.offsetHeight-this.hints.clientHeight+r.offsetTop)},screenAmount:function(){return Math.floor(this.hints.clientHeight/this.hints.firstChild.offsetHeight)||1},getSelectedHintRange:function(){var e=this.completion.options.scrollMargin||0;return{from:Math.max(0,this.selectedHint-e),to:Math.min(this.data.list.length-1,this.selectedHint+e)}}},r(f,"applicableHelpers"),r(p,"fetchHints"),r(h,"resolveAutoHints"),e.registerHelper("hint","auto",{resolve:h}),e.registerHelper("hint","fromList",(function(t,n){var r,i=t.getCursor(),o=t.getTokenAt(i),a=e.Pos(i.line,o.start),s=i;o.start,]/,closeOnPick:!0,closeOnUnfocus:!0,updateOnCursorActivity:!0,completeOnSingleClick:!0,container:null,customKeys:null,extraKeys:null,paddingForScrollbar:!0,moveOnOverlap:!0};e.defineOption("hintOptions",null)}(t.a.exports);var a=i({__proto__:null,default:o.exports},[o.exports]);e.s=a})?r.apply(t,i):r)||(e.exports=o)},2568:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(535),n(9407),n(9171)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.s=void 0;var i=Object.defineProperty,o=(e,t)=>i(e,"name",{value:t,configurable:!0});function a(e,t){return t.forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(n){if("default"!==n&&!(n in e)){var r=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,r.get?r:{enumerable:!0,get:function(){return t[n]}})}}))})),Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}o(a,"_mergeNamespaces");var s={exports:{}};!function(e){var t=e.commands,n=e.Pos;function r(t,r,i){if(i<0&&0==r.ch)return t.clipPos(n(r.line-1));var o=t.getLine(r.line);if(i>0&&r.ch>=o.length)return t.clipPos(n(r.line+1,0));for(var a,s="start",l=r.ch,u=l,c=i<0?0:o.length,d=0;u!=c;u+=i,d++){var f=o.charAt(i<0?u-1:u),p="_"!=f&&e.isWordChar(f)?"w":"o";if("w"==p&&f.toUpperCase()==f&&(p="W"),"start"==s)"o"!=p?(s="in",a=p):l=u+i;else if("in"==s&&a!=p){if("w"==a&&"W"==p&&i<0&&u--,"W"==a&&"w"==p&&i>0){if(u==l+1){a="w";continue}u--}break}}return n(r.line,u)}function i(e,t){e.extendSelectionsBy((function(n){return e.display.shift||e.doc.extend||n.empty()?r(e.doc,n.head,t):t<0?n.from():n.to()}))}function a(t,r){if(t.isReadOnly())return e.Pass;t.operation((function(){for(var e=t.listSelections().length,i=[],o=-1,a=0;a=n&&e.execCommand("goLineUp")}e.scrollTo(null,t.top-e.defaultTextHeight())},t.scrollLineDown=function(e){var t=e.getScrollInfo();if(!e.somethingSelected()){var n=e.lineAtHeight(t.top,"local")+1;e.getCursor().line<=n&&e.execCommand("goLineDown")}e.scrollTo(null,t.top+e.defaultTextHeight())},t.splitSelectionByLine=function(e){for(var t=e.listSelections(),r=[],i=0;io.line&&s==a.line&&0==a.ch||r.push({anchor:s==o.line?o:n(s,0),head:s==a.line?a:n(s)});e.setSelections(r,0)},t.singleSelectionTop=function(e){var t=e.listSelections()[0];e.setSelection(t.anchor,t.head,{scroll:!1})},t.selectLine=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;a--){var u=r[i[a]];if(!(l&&e.cmpPos(u.head,l)>0)){var c=s(t,u.head);l=c.from,t.replaceRange(n(c.word),c.from,c.to)}}}))}function m(t){var n=t.getCursor("from"),r=t.getCursor("to");if(0==e.cmpPos(n,r)){var i=s(t,n);if(!i.word)return;n=i.from,r=i.to}return{from:n,to:r,query:t.getRange(n,r),word:i}}function g(e,t){var r=m(e);if(r){var i=r.query,o=e.getSearchCursor(i,t?r.to:r.from);(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):(o=e.getSearchCursor(i,t?n(e.firstLine(),0):e.clipPos(n(e.lastLine()))),(t?o.findNext():o.findPrevious())?e.setSelection(o.from(),o.to()):r.word&&e.setSelection(r.from,r.to))}}o(d,"selectBetweenBrackets"),t.selectScope=function(e){d(e)||e.execCommand("selectAll")},t.selectBetweenBrackets=function(t){if(!d(t))return e.Pass},o(f,"puncType"),t.goToBracket=function(t){t.extendSelectionsBy((function(r){var i=t.scanForBracket(r.head,1,f(t.getTokenTypeAt(r.head)));if(i&&0!=e.cmpPos(i.pos,r.head))return i.pos;var o=t.scanForBracket(r.head,-1,f(t.getTokenTypeAt(n(r.head.line,r.head.ch+1))));return o&&n(o.pos.line,o.pos.ch+1)||r.head}))},t.swapLineUp=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.firstLine()-1,a=[],s=0;so?i.push(u,c):i.length&&(i[i.length-1]=c),o=c}t.operation((function(){for(var e=0;et.lastLine()?t.replaceRange("\n"+s,n(t.lastLine()),null,"+swapLine"):t.replaceRange(s+"\n",n(o,0),null,"+swapLine")}t.setSelections(a),t.scrollIntoView()}))},t.swapLineDown=function(t){if(t.isReadOnly())return e.Pass;for(var r=t.listSelections(),i=[],o=t.lastLine()+1,a=r.length-1;a>=0;a--){var s=r[a],l=s.to().line+1,u=s.from().line;0!=s.to().ch||s.empty()||l--,l=0;e-=2){var r=i[e],o=i[e+1],a=t.getLine(r);r==t.lastLine()?t.replaceRange("",n(r-1),n(r),"+swapLine"):t.replaceRange("",n(r,0),n(r+1,0),"+swapLine"),t.replaceRange(a+"\n",n(o,0),null,"+swapLine")}t.scrollIntoView()}))},t.toggleCommentIndented=function(e){e.toggleComment({indent:!0})},t.joinLines=function(e){for(var t=e.listSelections(),r=[],i=0;i=0;o--){var a=r[o].head,s=t.getRange({line:a.line,ch:0},a),l=e.countColumn(s,null,t.getOption("tabSize")),u=t.findPosH(a,-1,"char",!1);if(s&&!/\S/.test(s)&&l%i==0){var c=new n(a.line,e.findColumn(s,l-i,i));c.ch!=a.ch&&(u=c)}t.replaceRange("",u,a,"+delete")}}))},t.delLineRight=function(e){e.operation((function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange("",t[r].anchor,n(t[r].to().line),"+delete");e.scrollIntoView()}))},t.upcaseAtCursor=function(e){h(e,(function(e){return e.toUpperCase()}))},t.downcaseAtCursor=function(e){h(e,(function(e){return e.toLowerCase()}))},t.setSublimeMark=function(e){e.state.sublimeMark&&e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor())},t.selectToSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&e.setSelection(e.getCursor(),t)},t.deleteToSublimeMark=function(t){var n=t.state.sublimeMark&&t.state.sublimeMark.find();if(n){var r=t.getCursor(),i=n;if(e.cmpPos(r,i)>0){var o=i;i=r,r=o}t.state.sublimeKilled=t.getRange(r,i),t.replaceRange("",r,i)}},t.swapWithSublimeMark=function(e){var t=e.state.sublimeMark&&e.state.sublimeMark.find();t&&(e.state.sublimeMark.clear(),e.state.sublimeMark=e.setBookmark(e.getCursor()),e.setCursor(t))},t.sublimeYank=function(e){null!=e.state.sublimeKilled&&e.replaceSelection(e.state.sublimeKilled,null,"paste")},t.showInCenter=function(e){var t=e.cursorCoords(null,"local");e.scrollTo(null,(t.top+t.bottom)/2-e.getScrollInfo().clientHeight/2)},o(m,"getTarget"),o(g,"findAndGoTo"),t.findUnder=function(e){g(e,!0)},t.findUnderPrevious=function(e){g(e,!1)},t.findAllUnder=function(e){var t=m(e);if(t){for(var n=e.getSearchCursor(t.query),r=[],i=-1;n.findNext();)r.push({anchor:n.from(),head:n.to()}),n.from().line<=t.from.line&&n.from().ch<=t.from.ch&&i++;e.setSelections(r,i)}};var v=e.keyMap;v.macSublime={"Cmd-Left":"goLineStartSmart","Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-Left":"goSubwordLeft","Ctrl-Right":"goSubwordRight","Ctrl-Alt-Up":"scrollLineUp","Ctrl-Alt-Down":"scrollLineDown","Cmd-L":"selectLine","Shift-Cmd-L":"splitSelectionByLine",Esc:"singleSelectionTop","Cmd-Enter":"insertLineAfter","Shift-Cmd-Enter":"insertLineBefore","Cmd-D":"selectNextOccurrence","Shift-Cmd-Space":"selectScope","Shift-Cmd-M":"selectBetweenBrackets","Cmd-M":"goToBracket","Cmd-Ctrl-Up":"swapLineUp","Cmd-Ctrl-Down":"swapLineDown","Cmd-/":"toggleCommentIndented","Cmd-J":"joinLines","Shift-Cmd-D":"duplicateLine",F5:"sortLines","Shift-F5":"reverseSortLines","Cmd-F5":"sortLinesInsensitive","Shift-Cmd-F5":"reverseSortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Cmd-F2":"toggleBookmark","Shift-Cmd-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Cmd-K Cmd-D":"skipAndSelectNextOccurrence","Cmd-K Cmd-K":"delLineRight","Cmd-K Cmd-U":"upcaseAtCursor","Cmd-K Cmd-L":"downcaseAtCursor","Cmd-K Cmd-Space":"setSublimeMark","Cmd-K Cmd-A":"selectToSublimeMark","Cmd-K Cmd-W":"deleteToSublimeMark","Cmd-K Cmd-X":"swapWithSublimeMark","Cmd-K Cmd-Y":"sublimeYank","Cmd-K Cmd-C":"showInCenter","Cmd-K Cmd-G":"clearBookmarks","Cmd-K Cmd-Backspace":"delLineLeft","Cmd-K Cmd-1":"foldAll","Cmd-K Cmd-0":"unfoldAll","Cmd-K Cmd-J":"unfoldAll","Ctrl-Shift-Up":"addCursorToPrevLine","Ctrl-Shift-Down":"addCursorToNextLine","Cmd-F3":"findUnder","Shift-Cmd-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Cmd-[":"fold","Shift-Cmd-]":"unfold","Cmd-I":"findIncremental","Shift-Cmd-I":"findIncrementalReverse","Cmd-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"macDefault"},e.normalizeKeyMap(v.macSublime),v.pcSublime={"Shift-Tab":"indentLess","Shift-Ctrl-K":"deleteLine","Alt-Q":"wrapLines","Ctrl-T":"transposeChars","Alt-Left":"goSubwordLeft","Alt-Right":"goSubwordRight","Ctrl-Up":"scrollLineUp","Ctrl-Down":"scrollLineDown","Ctrl-L":"selectLine","Shift-Ctrl-L":"splitSelectionByLine",Esc:"singleSelectionTop","Ctrl-Enter":"insertLineAfter","Shift-Ctrl-Enter":"insertLineBefore","Ctrl-D":"selectNextOccurrence","Shift-Ctrl-Space":"selectScope","Shift-Ctrl-M":"selectBetweenBrackets","Ctrl-M":"goToBracket","Shift-Ctrl-Up":"swapLineUp","Shift-Ctrl-Down":"swapLineDown","Ctrl-/":"toggleCommentIndented","Ctrl-J":"joinLines","Shift-Ctrl-D":"duplicateLine",F9:"sortLines","Shift-F9":"reverseSortLines","Ctrl-F9":"sortLinesInsensitive","Shift-Ctrl-F9":"reverseSortLinesInsensitive",F2:"nextBookmark","Shift-F2":"prevBookmark","Ctrl-F2":"toggleBookmark","Shift-Ctrl-F2":"clearBookmarks","Alt-F2":"selectBookmarks",Backspace:"smartBackspace","Ctrl-K Ctrl-D":"skipAndSelectNextOccurrence","Ctrl-K Ctrl-K":"delLineRight","Ctrl-K Ctrl-U":"upcaseAtCursor","Ctrl-K Ctrl-L":"downcaseAtCursor","Ctrl-K Ctrl-Space":"setSublimeMark","Ctrl-K Ctrl-A":"selectToSublimeMark","Ctrl-K Ctrl-W":"deleteToSublimeMark","Ctrl-K Ctrl-X":"swapWithSublimeMark","Ctrl-K Ctrl-Y":"sublimeYank","Ctrl-K Ctrl-C":"showInCenter","Ctrl-K Ctrl-G":"clearBookmarks","Ctrl-K Ctrl-Backspace":"delLineLeft","Ctrl-K Ctrl-1":"foldAll","Ctrl-K Ctrl-0":"unfoldAll","Ctrl-K Ctrl-J":"unfoldAll","Ctrl-Alt-Up":"addCursorToPrevLine","Ctrl-Alt-Down":"addCursorToNextLine","Ctrl-F3":"findUnder","Shift-Ctrl-F3":"findUnderPrevious","Alt-F3":"findAllUnder","Shift-Ctrl-[":"fold","Shift-Ctrl-]":"unfold","Ctrl-I":"findIncremental","Shift-Ctrl-I":"findIncrementalReverse","Ctrl-H":"replace",F3:"findNext","Shift-F3":"findPrev",fallthrough:"pcDefault"},e.normalizeKeyMap(v.pcSublime);var y=v.default==v.macDefault;v.sublime=y?v.macSublime:v.pcSublime}(t.a.exports,n.a.exports,r.a.exports);var l=a({__proto__:null,default:s.exports},[s.exports]);e.s=l})?r.apply(t,i):r)||(e.exports=o)},3691:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(r="function"==typeof(n=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.fetcherReturnToPromise=function(e){return t(this,void 0,void 0,(function*(){const i=yield e;return r(i)?function(e){var n;return t(this,void 0,void 0,(function*(){const t=null===(n=("return"in e?e:e[Symbol.asyncIterator]()).return)||void 0===n?void 0:n.bind(e),r=("next"in e?e:e[Symbol.asyncIterator]()).next.bind(e),i=yield r();return null==t||t(),i.value}))}(i):n(i)?(o=i,new Promise(((e,t)=>{const n=o.subscribe({next:t=>{e(t),n.unsubscribe()},error:t,complete:()=>{t(new Error("no value resolved"))}})}))):i;var o}))},e.isAsyncIterable=r,e.isObservable=n,e.isPromise=function(e){return"object"==typeof e&&null!==e&&"function"==typeof e.then};var t=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function a(e){try{l(r.next(e))}catch(e){o(e)}}function s(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}l((r=r.apply(e,t||[])).next())}))};function n(e){return"object"==typeof e&&null!==e&&"subscribe"in e&&"function"==typeof e.subscribe}function r(e){return"object"==typeof e&&null!==e&&("AsyncGenerator"===e[Symbol.toStringTag]||Symbol.asyncIterator in e)}})?n.apply(t,[t]):n)||(e.exports=r)},5454:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(2501)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.createGraphiQLFetcher=function(e){let n;if("undefined"!=typeof window&&window.fetch&&(n=window.fetch),null!==(null==e?void 0:e.enableIncrementalDelivery)&&!1===e.enableIncrementalDelivery||(e.enableIncrementalDelivery=!0),e.fetch&&(n=e.fetch),!n)throw new Error("No valid fetcher implementation available");const r=(0,t.createSimpleFetcher)(e,n),i=e.enableIncrementalDelivery?(0,t.createMultipartFetcher)(e,n):r;return(n,o)=>{if("IntrospectionQuery"===n.operationName)return(e.schemaFetcher||r)(n,o);if((null==o?void 0:o.documentAST)&&(0,t.isSubscriptionWithName)(o.documentAST,n.operationName||void 0)){const r=(0,t.getWsFetcher)(e,o);if(!r)throw new Error("Your GraphiQL createFetcher is not properly configured for websocket subscriptions yet. "+(e.subscriptionUrl?`Provided URL ${e.subscriptionUrl} failed`:"Please provide subscriptionUrl, wsClient or legacyClient option first."));return r(n)}return i(n,o)}}})?r.apply(t,i):r)||(e.exports=o)},1799:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3080),n(5454)],void 0===(o="function"==typeof(r=function(e,t,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r={createGraphiQLFetcher:!0};Object.defineProperty(e,"createGraphiQLFetcher",{enumerable:!0,get:function(){return n.createGraphiQLFetcher}}),Object.keys(t).forEach((function(n){"default"!==n&&"__esModule"!==n&&(Object.prototype.hasOwnProperty.call(r,n)||n in e&&e[n]===t[n]||Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}}))}))})?r.apply(t,i):r)||(e.exports=o)},2501:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3573),n(8488),n(8042)],r=function(e,t,r,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.isSubscriptionWithName=e.getWsFetcher=e.createWebsocketsFetcherFromUrl=e.createWebsocketsFetcherFromClient=e.createSimpleFetcher=e.createMultipartFetcher=e.createLegacyWebsocketsFetcher=void 0;var o=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function a(e){try{l(r.next(e))}catch(e){o(e)}}function s(e){try{l(r.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}l((r=r.apply(e,t||[])).next())}))},a=function(e){return this instanceof a?(this.v=e,this):new a(e)},s=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e="function"==typeof __values?__values(e):e[Symbol.iterator](),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,i){!function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)}(r,i,(t=e[n](t)).done,t.value)}))}}},l=function(e,t,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var r,i=n.apply(e,t||[]),o=[];return r={},s("next"),s("throw"),s("return"),r[Symbol.asyncIterator]=function(){return this},r;function s(e){i[e]&&(r[e]=function(t){return new Promise((function(n,r){o.push([e,t,n,r])>1||l(e,t)}))})}function l(e,t){try{(n=i[e](t)).value instanceof a?Promise.resolve(n.value.v).then(u,c):d(o[0][2],n)}catch(e){d(o[0][3],e)}var n}function u(e){l("next",e)}function c(e){l("throw",e)}function d(e,t){e(t),o.shift(),o.length&&l(o[0][0],o[0][1])}};e.isSubscriptionWithName=(e,n)=>{let r=!1;return(0,t.visit)(e,{OperationDefinition(e){var t;n===(null===(t=e.name)||void 0===t?void 0:t.value)&&"subscription"===e.operation&&(r=!0)}}),r};e.createSimpleFetcher=(e,t)=>(n,r)=>o(void 0,void 0,void 0,(function*(){return(yield t(e.url,{method:"POST",body:JSON.stringify(n),headers:Object.assign(Object.assign({"content-type":"application/json"},e.headers),null==r?void 0:r.headers)})).json()}));const u=(e,t)=>{let r;try{const{createClient:i}=n(7674);return r=i({url:e,connectionParams:t}),c(r)}catch(t){if((e=>"object"==typeof e&&null!==e&&"code"in e)(t)&&"MODULE_NOT_FOUND"===t.code)throw new Error("You need to install the 'graphql-ws' package to use websockets when passing a 'subscriptionUrl'");console.error(`Error creating websocket client for ${e}`,t)}};e.createWebsocketsFetcherFromUrl=u;const c=e=>t=>(0,i.makeAsyncIterableIteratorFromSink)((n=>e.subscribe(t,Object.assign(Object.assign({},n),{error:e=>{e instanceof CloseEvent?n.error(new Error(`Socket closed with event ${e.code} ${e.reason||""}`.trim())):n.error(e)}}))));e.createWebsocketsFetcherFromClient=c;const d=e=>t=>{const n=e.request(t);return(0,i.makeAsyncIterableIteratorFromSink)((e=>n.subscribe(e).unsubscribe))};e.createLegacyWebsocketsFetcher=d;e.createMultipartFetcher=(e,t)=>function(n,o){return l(this,arguments,(function*(){var l,u;const c=yield a(t(e.url,{method:"POST",body:JSON.stringify(n),headers:Object.assign(Object.assign({"content-type":"application/json",accept:"application/json, multipart/mixed"},e.headers),null==o?void 0:o.headers)}).then((e=>(0,r.meros)(e,{multiple:!0}))));if(!(0,i.isAsyncIterable)(c))return yield a(yield yield a(c.json()));try{for(var d,f=s(c);!(d=yield a(f.next())).done;){const e=d.value;if(e.some((e=>!e.json))){const t=e.map((e=>`Headers::\n${e.headers}\n\nBody::\n${e.body}`));throw new Error(`Expected multipart chunks to be of json type. got:\n${t}`)}yield yield a(e.map((e=>e.body)))}}catch(e){l={error:e}}finally{try{d&&!d.done&&(u=f.return)&&(yield a(u.call(f)))}finally{if(l)throw l.error}}}))};e.getWsFetcher=(e,t)=>{if(e.wsClient)return c(e.wsClient);if(e.subscriptionUrl)return u(e.subscriptionUrl,Object.assign(Object.assign({},e.wsConnectionParams),null==t?void 0:t.headers));const n=e.legacyClient||e.legacyWsClient;return n?d(n):void 0}},void 0===(o=r.apply(t,i))||(e.exports=o)},3080:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(r="function"==typeof(n=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0})})?n.apply(t,[t]):n)||(e.exports=r)},4574:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(r="function"==typeof(n=function(e){"use strict";function t(e){return JSON.stringify(e,null,2)}function n(e){return e instanceof Error?function(e){return Object.assign(Object.assign({},e),{message:e.message,stack:e.stack})}(e):e}Object.defineProperty(e,"__esModule",{value:!0}),e.formatError=function(e){return Array.isArray(e)?t({errors:e.map((e=>n(e)))}):t({errors:[n(e)]})},e.formatResult=function(e){return t(e)}})?n.apply(t,[t]):n)||(e.exports=r)},3738:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3573)],void 0===(o="function"==typeof(r=function(e,t){"use strict";function n(e){if(!("getFields"in e))return[];const n=e.getFields();if(n.id)return["id"];if(n.edges)return["edges"];if(n.node)return["node"];const r=[];for(const e of Object.keys(n))(0,t.isLeafType)(n[e].type)&&r.push(e);return r}function r(e,n){const i=(0,t.getNamedType)(e);if(!e||(0,t.isLeafType)(e))return;const o=n(i);return Array.isArray(o)&&0!==o.length&&"getFields"in i?{kind:t.Kind.SELECTION_SET,selections:o.map((e=>{const o=i.getFields()[e],a=o?o.type:null;return{kind:t.Kind.FIELD,name:{kind:t.Kind.NAME,value:e},selectionSet:r(a,n)}}))}:void 0}function i(e,t){if(0===t.length)return e;let n="",r=0;for(const{index:i,string:o}of t)n+=e.slice(r,i)+o,r=i;return n+=e.slice(r),n}Object.defineProperty(e,"__esModule",{value:!0}),e.fillLeafs=function(e,o,a){const s=[];if(!e||!o)return{insertions:s,result:o};let l;try{l=(0,t.parse)(o)}catch(e){return{insertions:s,result:o}}const u=a||n,c=new t.TypeInfo(e);return(0,t.visit)(l,{leave(e){c.leave(e)},enter(e){if(c.enter(e),"Field"===e.kind&&!e.selectionSet){const n=r(function(e){if(e)return e}(c.getType()),u);if(n&&e.loc){const r=function(e,t){let n=t,r=t;for(;n;){const t=e.charCodeAt(n-1);if(10===t||13===t||8232===t||8233===t)break;n--,9!==t&&11!==t&&12!==t&&32!==t&&160!==t&&(r=n)}return e.slice(n,r)}(o,e.loc.start);s.push({index:e.loc.end,string:" "+(0,t.print)(n).replaceAll("\n","\n"+r)})}}}}),{insertions:s,result:i(o,s)}}})?r.apply(t,i):r)||(e.exports=o)},7293:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3738),n(5682),n(1312)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Object.keys(t).forEach((function(n){"default"!==n&&"__esModule"!==n&&(n in e&&e[n]===t[n]||Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}}))})),Object.keys(n).forEach((function(t){"default"!==t&&"__esModule"!==t&&(t in e&&e[t]===n[t]||Object.defineProperty(e,t,{enumerable:!0,get:function(){return n[t]}}))})),Object.keys(r).forEach((function(t){"default"!==t&&"__esModule"!==t&&(t in e&&e[t]===r[t]||Object.defineProperty(e,t,{enumerable:!0,get:function(){return r[t]}}))}))})?r.apply(t,i):r)||(e.exports=o)},5682:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3573)],void 0===(o="function"==typeof(r=function(e,t){"use strict";function n(e,r,i){var o;const a=i?(0,t.getNamedType)(i).name:null,s=[],l=[];for(let u of r){if("FragmentSpread"===u.kind){const n=u.name.value;if(!u.directives||0===u.directives.length){if(l.includes(n))continue;l.push(n)}const r=e[u.name.value];if(r){const{typeCondition:e,directives:n,selectionSet:i}=r;u={kind:t.Kind.INLINE_FRAGMENT,typeCondition:e,directives:n,selectionSet:i}}}if(u.kind===t.Kind.INLINE_FRAGMENT&&(!u.directives||0===(null===(o=u.directives)||void 0===o?void 0:o.length))){const t=u.typeCondition?u.typeCondition.name.value:null;if(!t||t===a){s.push(...n(e,u.selectionSet.selections,i));continue}}s.push(u)}return s}Object.defineProperty(e,"__esModule",{value:!0}),e.mergeAst=function(e,r){const i=r?new t.TypeInfo(r):null,o=Object.create(null);for(const n of e.definitions)n.kind===t.Kind.FRAGMENT_DEFINITION&&(o[n.name.value]=n);const a={SelectionSet(e){const t=i?i.getParentType():null;let{selections:r}=e;return r=n(o,r,t),r=function(e,t){var n;const r=new Map,i=[];for(const o of e)if("Field"===o.kind){const e=t(o),a=r.get(e);if(null===(n=o.directives)||void 0===n?void 0:n.length){const e=Object.assign({},o);i.push(e)}else if((null==a?void 0:a.selectionSet)&&o.selectionSet)a.selectionSet.selections=[...a.selectionSet.selections,...o.selectionSet.selections];else if(!a){const t=Object.assign({},o);r.set(e,t),i.push(t)}}else i.push(o);return i}(r,(e=>e.alias?e.alias.value:e.name.value)),Object.assign(Object.assign({},e),{selections:r})},FragmentDefinition(){return null}};return(0,t.visit)(e,i?(0,t.visitWithTypeInfo)(i,a):a)}})?r.apply(t,i):r)||(e.exports=o)},1312:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,void 0===(r="function"==typeof(n=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getSelectedOperationName=function(e,t,n){if(!n||n.length<1)return;const r=n.map((e=>{var t;return null===(t=e.name)||void 0===t?void 0:t.value}));if(t&&r.includes(t))return t;if(t&&e){const n=e.map((e=>{var t;return null===(t=e.name)||void 0===t?void 0:t.value})).indexOf(t);if(-1!==n&&n{for(const e in window.localStorage)0===e.indexOf(`${t}:`)&&window.localStorage.removeItem(e)}}}get(e){if(!this.storage)return null;const n=`${t}:${e}`,r=this.storage.getItem(n);return"null"===r||"undefined"===r?(this.storage.removeItem(n),null):r||null}set(e,n){let r=!1,i=null;if(this.storage){const o=`${t}:${e}`;if(n)try{this.storage.setItem(o,n)}catch(e){i=e instanceof Error?e:new Error(`${e}`),r=function(e,t){return t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&0!==e.length}(this.storage,e)}else this.storage.removeItem(o)}return{isQuotaError:r,error:i}}clear(){this.storage&&this.storage.clear()}};const t="graphiql"})?n.apply(t,[t]):n)||(e.exports=r)},1925:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(3573),n(6837)],void 0===(o="function"==typeof(r=function(e,t,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HistoryStore=void 0;e.HistoryStore=class{constructor(e,t){this.storage=e,this.maxHistoryLength=t,this.updateHistory=(e,t,n,r)=>{if(this.shouldSaveQuery(e,t,n,this.history.fetchRecent())){this.history.push({query:e,variables:t,headers:n,operationName:r});const i=this.history.items,o=this.favorite.items;this.queries=i.concat(o)}},this.history=new n.QueryStore("queries",this.storage,this.maxHistoryLength),this.favorite=new n.QueryStore("favorites",this.storage,null),this.queries=[...this.history.fetchAll(),...this.favorite.fetchAll()]}shouldSaveQuery(e,n,r,i){if(!e)return!1;try{(0,t.parse)(e)}catch(e){return!1}if(e.length>1e5)return!1;if(!i)return!0;if(JSON.stringify(e)===JSON.stringify(i.query)){if(JSON.stringify(n)===JSON.stringify(i.variables)){if(JSON.stringify(r)===JSON.stringify(i.headers))return!1;if(r&&!i.headers)return!1}if(n&&!i.variables)return!1}return!0}toggleFavorite(e,t,n,r,i,o){const a={query:e,variables:t,headers:n,operationName:r,label:i};this.favorite.contains(a)?o&&(a.favorite=!1,this.favorite.delete(a)):(a.favorite=!0,this.favorite.push(a)),this.queries=[...this.history.items,...this.favorite.items]}editLabel(e,t,n,r,i,o){const a={query:e,variables:t,headers:n,operationName:r,label:i};o?this.favorite.edit(Object.assign(Object.assign({},a),{favorite:o})):this.history.edit(a),this.queries=[...this.history.items,...this.favorite.items]}}})?r.apply(t,i):r)||(e.exports=o)},920:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(1180),n(1925),n(6837)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),Object.keys(t).forEach((function(n){"default"!==n&&"__esModule"!==n&&(n in e&&e[n]===t[n]||Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}}))})),Object.keys(n).forEach((function(t){"default"!==t&&"__esModule"!==t&&(t in e&&e[t]===n[t]||Object.defineProperty(e,t,{enumerable:!0,get:function(){return n[t]}}))})),Object.keys(r).forEach((function(t){"default"!==t&&"__esModule"!==t&&(t in e&&e[t]===r[t]||Object.defineProperty(e,t,{enumerable:!0,get:function(){return r[t]}}))}))})?r.apply(t,i):r)||(e.exports=o)},6837:function(e,t){var n,r;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,n=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.QueryStore=void 0;e.QueryStore=class{constructor(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;this.key=e,this.storage=t,this.maxSize=n,this.items=this.fetchAll()}get length(){return this.items.length}contains(e){return this.items.some((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName))}edit(e){const t=this.items.findIndex((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName));-1!==t&&(this.items.splice(t,1,e),this.save())}delete(e){const t=this.items.findIndex((t=>t.query===e.query&&t.variables===e.variables&&t.headers===e.headers&&t.operationName===e.operationName));-1!==t&&(this.items.splice(t,1),this.save())}fetchRecent(){return this.items.at(-1)}fetchAll(){const e=this.storage.get(this.key);return e?JSON.parse(e)[this.key]:[]}push(e){const t=[...this.items,e];this.maxSize&&t.length>this.maxSize&&t.shift();for(let e=0;e<5;e++){const e=this.storage.set(this.key,JSON.stringify({[this.key]:t}));if(null==e?void 0:e.error){if(!e.isQuotaError||!this.maxSize)return;t.shift()}else this.items=t}}save(){this.storage.set(this.key,JSON.stringify({[this.key]:this.items}))}}},void 0===(r=n.apply(t,[t]))||(e.exports=r)},6676:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(7139),n(7644),n(3573),n(8506),n(5251),n(2162),n(5605),n(6785)],void 0===(o="function"==typeof(r=function(e,t,n,r,i,o,a,s,l){"use strict";function u(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(u=function(e){return e?n:t})(e)}function c(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=u(t);if(n&&n.has(e))return n.get(e);var r={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if("default"!==o&&Object.prototype.hasOwnProperty.call(e,o)){var a=i?Object.getOwnPropertyDescriptor(e,o):null;a&&(a.get||a.set)?Object.defineProperty(r,o,a):r[o]=e[o]}return r.default=e,n&&n.set(e,r),r}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=c(t),r=c(r),i.GraphiQL.createFetcher=n.createGraphiQLFetcher,i.GraphiQL.GraphQL=r,i.GraphiQL.React=t;var d=i.GraphiQL;e.default=d})?r.apply(t,i):r)||(e.exports=o)},8506:function(e,t,n){var r,i,o;"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self&&self,i=[t,n(9196),n(7139)],r=function(e,t,n){"use strict";function r(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(r=function(e){return e?n:t})(e)}function i(){return i=Object.assign?Object.assign.bind():function(e){for(var t=1;t{"first"===e&&(null==p||p.setVisiblePlugin(null))},sizeThresholdSecond:200,storageKey:"docExplorerFlex"}),T=(0,n.useDragResize)({direction:"horizontal",storageKey:"editorFlex"}),w=(0,n.useDragResize)({defaultSizeRelation:3,direction:"vertical",initiallyHidden:(()=>{if("variables"!==e.defaultEditorToolsVisibility&&"headers"!==e.defaultEditorToolsVisibility)return"boolean"==typeof e.defaultEditorToolsVisibility?e.defaultEditorToolsVisibility?void 0:"second":l.initialVariables||l.initialHeaders?void 0:"second"})(),sizeThresholdSecond:60,storageKey:"secondaryEditorFlex"}),[C,S]=(0,t.useState)((()=>"variables"===e.defaultEditorToolsVisibility||"headers"===e.defaultEditorToolsVisibility?e.defaultEditorToolsVisibility:!l.initialVariables&&l.initialHeaders&&s?"headers":"variables")),[x,k]=(0,t.useState)(null),[N,_]=(0,t.useState)(null),O=t.default.Children.toArray(e.children),I=O.find((e=>c(e,o.Logo)))||t.default.createElement(o.Logo,null),D=O.find((e=>c(e,o.Toolbar)))||t.default.createElement(t.default.Fragment,null,t.default.createElement(n.ToolbarButton,{onClick:()=>g(),label:"Prettify query (Shift-Ctrl-P)"},t.default.createElement(n.PrettifyIcon,{className:"graphiql-toolbar-icon","aria-hidden":"true"})),t.default.createElement(n.ToolbarButton,{onClick:()=>m(),label:"Merge fragments into query (Shift-Ctrl-M)"},t.default.createElement(n.MergeIcon,{className:"graphiql-toolbar-icon","aria-hidden":"true"})),t.default.createElement(n.ToolbarButton,{onClick:()=>h(),label:"Copy query (Shift-Ctrl-C)"},t.default.createElement(n.CopyIcon,{className:"graphiql-toolbar-icon","aria-hidden":"true"})),(null===(a=e.toolbar)||void 0===a?void 0:a.additionalContent)||null),L=O.find((e=>c(e,o.Footer))),A=()=>{"first"===E.hiddenElement&&E.setHiddenElement(null)},M=0===window.navigator.platform.toLowerCase().indexOf("mac")?t.default.createElement("code",{className:"graphiql-key"},"Cmd"):t.default.createElement("code",{className:"graphiql-key"},"Ctrl");return t.default.createElement("div",{"data-testid":"graphiql-container",className:"graphiql-container"},t.default.createElement("div",{className:"graphiql-sidebar"},t.default.createElement("div",{className:"graphiql-sidebar-section"},null==p?void 0:p.plugins.map((e=>{const r=e===p.visiblePlugin,i=`${r?"Hide":"Show"} ${e.title}`,o=e.icon;return t.default.createElement(n.Tooltip,{key:e.title,label:i},t.default.createElement(n.UnStyledButton,{type:"button",className:r?"active":"",onClick:()=>{r?(p.setVisiblePlugin(null),E.setHiddenElement("first")):(p.setVisiblePlugin(e),E.setHiddenElement(null))},"aria-label":i},t.default.createElement(o,{"aria-hidden":"true"})))}))),t.default.createElement("div",{className:"graphiql-sidebar-section"},t.default.createElement(n.Tooltip,{label:"Re-fetch GraphQL schema"},t.default.createElement(n.UnStyledButton,{type:"button",disabled:d.isFetching,onClick:()=>d.introspect(),"aria-label":"Re-fetch GraphQL schema"},t.default.createElement(n.ReloadIcon,{className:d.isFetching?"graphiql-spin":"","aria-hidden":"true"}))),t.default.createElement(n.Tooltip,{label:"Open short keys dialog"},t.default.createElement(n.UnStyledButton,{type:"button",onClick:()=>k("short-keys"),"aria-label":"Open short keys dialog"},t.default.createElement(n.KeyboardShortcutIcon,{"aria-hidden":"true"}))),t.default.createElement(n.Tooltip,{label:"Open settings dialog"},t.default.createElement(n.UnStyledButton,{type:"button",onClick:()=>k("settings"),"aria-label":"Open settings dialog"},t.default.createElement(n.SettingsIcon,{"aria-hidden":"true"}))))),t.default.createElement("div",{className:"graphiql-main"},t.default.createElement("div",{ref:E.firstRef,style:{minWidth:"200px"}},t.default.createElement("div",{className:"graphiql-plugin"},b?t.default.createElement(b,null):null)),t.default.createElement("div",{ref:E.dragBarRef},null!=p&&p.visiblePlugin?t.default.createElement("div",{className:"graphiql-horizontal-drag-bar"}):null),t.default.createElement("div",{ref:E.secondRef,style:{minWidth:0}},t.default.createElement("div",{className:"graphiql-sessions"},t.default.createElement("div",{className:"graphiql-session-header"},t.default.createElement(n.Tabs,{"aria-label":"Select active operation"},l.tabs.length>1?t.default.createElement(t.default.Fragment,null,l.tabs.map(((e,r)=>t.default.createElement(n.Tab,{key:e.id,isActive:r===l.activeTabIndex},t.default.createElement(n.Tab.Button,{"aria-controls":"graphiql-session",id:`graphiql-session-tab-${r}`,onClick:()=>{u.stop(),l.changeTab(r)}},e.title),t.default.createElement(n.Tab.Close,{onClick:()=>{l.activeTabIndex===r&&u.stop(),l.closeTab(r)}})))),t.default.createElement("div",null,t.default.createElement(n.Tooltip,{label:"Add tab"},t.default.createElement(n.UnStyledButton,{type:"button",className:"graphiql-tab-add",onClick:()=>l.addTab(),"aria-label":"Add tab"},t.default.createElement(n.PlusIcon,{"aria-hidden":"true"}))))):null),t.default.createElement("div",{className:"graphiql-session-header-right"},1===l.tabs.length?t.default.createElement("div",{className:"graphiql-add-tab-wrapper"},t.default.createElement(n.Tooltip,{label:"Add tab"},t.default.createElement(n.UnStyledButton,{type:"button",className:"graphiql-tab-add",onClick:()=>l.addTab(),"aria-label":"Add tab"},t.default.createElement(n.PlusIcon,{"aria-hidden":"true"})))):null,I)),t.default.createElement("div",{role:"tabpanel",id:"graphiql-session",className:"graphiql-session","aria-labelledby":`graphiql-session-tab-${l.activeTabIndex}`},t.default.createElement("div",{ref:T.firstRef},t.default.createElement("div",{className:"graphiql-editors"+(1===l.tabs.length?" full-height":"")},t.default.createElement("div",{ref:w.firstRef},t.default.createElement("section",{className:"graphiql-query-editor","aria-label":"Query Editor"},t.default.createElement("div",{className:"graphiql-query-editor-wrapper"},t.default.createElement(n.QueryEditor,{editorTheme:e.editorTheme,keyMap:e.keyMap,onClickReference:A,onCopyQuery:e.onCopyQuery,onEdit:e.onEditQuery,readOnly:e.readOnly})),t.default.createElement("div",{className:"graphiql-toolbar",role:"toolbar","aria-label":"Editor Commands"},t.default.createElement(n.ExecuteButton,null),D))),t.default.createElement("div",{ref:w.dragBarRef},t.default.createElement("div",{className:"graphiql-editor-tools"},t.default.createElement("div",{className:"graphiql-editor-tools-tabs"},t.default.createElement(n.UnStyledButton,{type:"button",className:"variables"===C&&"second"!==w.hiddenElement?"active":"",onClick:()=>{"second"===w.hiddenElement&&w.setHiddenElement(null),S("variables")}},"Variables"),s?t.default.createElement(n.UnStyledButton,{type:"button",className:"headers"===C&&"second"!==w.hiddenElement?"active":"",onClick:()=>{"second"===w.hiddenElement&&w.setHiddenElement(null),S("headers")}},"Headers"):null),t.default.createElement(n.Tooltip,{label:"second"===w.hiddenElement?"Show editor tools":"Hide editor tools"},t.default.createElement(n.UnStyledButton,{type:"button",onClick:()=>{w.setHiddenElement("second"===w.hiddenElement?null:"second")},"aria-label":"second"===w.hiddenElement?"Show editor tools":"Hide editor tools"},"second"===w.hiddenElement?t.default.createElement(n.ChevronUpIcon,{className:"graphiql-chevron-icon","aria-hidden":"true"}):t.default.createElement(n.ChevronDownIcon,{className:"graphiql-chevron-icon","aria-hidden":"true"}))))),t.default.createElement("div",{ref:w.secondRef},t.default.createElement("section",{className:"graphiql-editor-tool","aria-label":"variables"===C?"Variables":"Headers"},t.default.createElement(n.VariableEditor,{editorTheme:e.editorTheme,isHidden:"variables"!==C,keyMap:e.keyMap,onEdit:e.onEditVariables,onClickReference:A,readOnly:e.readOnly}),s&&t.default.createElement(n.HeaderEditor,{editorTheme:e.editorTheme,isHidden:"headers"!==C,keyMap:e.keyMap,onEdit:e.onEditHeaders,readOnly:e.readOnly}))))),t.default.createElement("div",{ref:T.dragBarRef},t.default.createElement("div",{className:"graphiql-horizontal-drag-bar"})),t.default.createElement("div",{ref:T.secondRef},t.default.createElement("div",{className:"graphiql-response"},u.isFetching?t.default.createElement(n.Spinner,null):null,t.default.createElement(n.ResponseEditor,{editorTheme:e.editorTheme,responseTooltip:e.responseTooltip,keyMap:e.keyMap}),L)))))),t.default.createElement(n.Dialog,{isOpen:"short-keys"===x,onDismiss:()=>k(null)},t.default.createElement("div",{className:"graphiql-dialog-header"},t.default.createElement("div",{className:"graphiql-dialog-title"},"Short Keys"),t.default.createElement(n.Dialog.Close,{onClick:()=>k(null)})),t.default.createElement("div",{className:"graphiql-dialog-section"},t.default.createElement("div",null,t.default.createElement("table",{className:"graphiql-table"},t.default.createElement("thead",null,t.default.createElement("tr",null,t.default.createElement("th",null,"Short key"),t.default.createElement("th",null,"Function"))),t.default.createElement("tbody",null,t.default.createElement("tr",null,t.default.createElement("td",null,M," + ",t.default.createElement("code",{className:"graphiql-key"},"F")),t.default.createElement("td",null,"Search in editor")),t.default.createElement("tr",null,t.default.createElement("td",null,M," + ",t.default.createElement("code",{className:"graphiql-key"},"K")),t.default.createElement("td",null,"Search in documentation")),t.default.createElement("tr",null,t.default.createElement("td",null,M," + ",t.default.createElement("code",{className:"graphiql-key"},"Enter")),t.default.createElement("td",null,"Execute query")),t.default.createElement("tr",null,t.default.createElement("td",null,t.default.createElement("code",{className:"graphiql-key"},"Ctrl")," + ",t.default.createElement("code",{className:"graphiql-key"},"Shift")," + ",t.default.createElement("code",{className:"graphiql-key"},"P")),t.default.createElement("td",null,"Prettify editors")),t.default.createElement("tr",null,t.default.createElement("td",null,t.default.createElement("code",{className:"graphiql-key"},"Ctrl")," + ",t.default.createElement("code",{className:"graphiql-key"},"Shift")," + ",t.default.createElement("code",{className:"graphiql-key"},"M")),t.default.createElement("td",null,"Merge fragments definitions into operation definition")),t.default.createElement("tr",null,t.default.createElement("td",null,t.default.createElement("code",{className:"graphiql-key"},"Ctrl")," + ",t.default.createElement("code",{className:"graphiql-key"},"Shift")," + ",t.default.createElement("code",{className:"graphiql-key"},"C")),t.default.createElement("td",null,"Copy query")),t.default.createElement("tr",null,t.default.createElement("td",null,t.default.createElement("code",{className:"graphiql-key"},"Ctrl")," + ",t.default.createElement("code",{className:"graphiql-key"},"Shift")," + ",t.default.createElement("code",{className:"graphiql-key"},"R")),t.default.createElement("td",null,"Re-fetch schema using introspection")))),t.default.createElement("p",null,"The editors use"," ",t.default.createElement("a",{href:"https://codemirror.net/5/doc/manual.html#keymaps",target:"_blank",rel:"noopener noreferrer"},"CodeMirror Key Maps")," ","that add more short keys. This instance of Graph",t.default.createElement("em",null,"i"),"QL uses"," ",t.default.createElement("code",null,e.keyMap||"sublime"),".")))),t.default.createElement(n.Dialog,{isOpen:"settings"===x,onDismiss:()=>{k(null),_(null)}},t.default.createElement("div",{className:"graphiql-dialog-header"},t.default.createElement("div",{className:"graphiql-dialog-title"},"Settings"),t.default.createElement(n.Dialog.Close,{onClick:()=>{k(null),_(null)}})),e.showPersistHeadersSettings?t.default.createElement("div",{className:"graphiql-dialog-section"},t.default.createElement("div",null,t.default.createElement("div",{className:"graphiql-dialog-section-title"},"Persist headers"),t.default.createElement("div",{className:"graphiql-dialog-section-caption"},"Save headers upon reloading."," ",t.default.createElement("span",{className:"graphiql-warning-text"},"Only enable if you trust this device."))),t.default.createElement(n.ButtonGroup,null,t.default.createElement(n.Button,{type:"button",id:"enable-persist-headers",className:l.shouldPersistHeaders?"active":void 0,onClick:()=>{l.setShouldPersistHeaders(!0)}},"On"),t.default.createElement(n.Button,{type:"button",id:"disable-persist-headers",className:l.shouldPersistHeaders?void 0:"active",onClick:()=>{l.setShouldPersistHeaders(!1)}},"Off"))):null,t.default.createElement("div",{className:"graphiql-dialog-section"},t.default.createElement("div",null,t.default.createElement("div",{className:"graphiql-dialog-section-title"},"Theme"),t.default.createElement("div",{className:"graphiql-dialog-section-caption"},"Adjust how the interface looks like.")),t.default.createElement("div",null,t.default.createElement(n.ButtonGroup,null,t.default.createElement(n.Button,{type:"button",className:null===v?"active":"",onClick:()=>y(null)},"System"),t.default.createElement(n.Button,{type:"button",className:"light"===v?"active":"",onClick:()=>y("light")},"Light"),t.default.createElement(n.Button,{type:"button",className:"dark"===v?"active":"",onClick:()=>y("dark")},"Dark")))),f?t.default.createElement("div",{className:"graphiql-dialog-section"},t.default.createElement("div",null,t.default.createElement("div",{className:"graphiql-dialog-section-title"},"Clear storage"),t.default.createElement("div",{className:"graphiql-dialog-section-caption"},"Remove all locally stored data and start fresh.")),t.default.createElement("div",null,t.default.createElement(n.Button,{type:"button",state:N||void 0,disabled:"success"===N,onClick:()=>{try{null==f||f.clear(),_("success")}catch{_("error")}}},"success"===N?"Cleared data":"error"===N?"Failed":"Clear data"))):null))}function s(e){return t.default.createElement("div",{className:"graphiql-logo"},e.children||t.default.createElement("a",{className:"graphiql-logo-link",href:"https://github.com/graphql/graphiql",target:"_blank",rel:"noreferrer"},"Graph",t.default.createElement("em",null,"i"),"QL"))}function l(e){return t.default.createElement(t.default.Fragment,null,e.children)}function u(e){return t.default.createElement("div",{className:"graphiql-footer"},e.children)}function c(e,t){var n;return!(null==e||null===(n=e.type)||void 0===n||!n.displayName||e.type.displayName!==t.displayName)||e.type===t}o.Logo=s,o.Toolbar=l,o.Footer=u,s.displayName="GraphiQLLogo",l.displayName="GraphiQLToolbar",u.displayName="GraphiQLFooter"},void 0===(o=r.apply(t,i))||(e.exports=o)},5313:function(e,t,n){"use strict";n.r(t),n.d(t,{CloseCode:function(){return r.CloseCode},GRAPHQL_TRANSPORT_WS_PROTOCOL:function(){return r.GRAPHQL_TRANSPORT_WS_PROTOCOL},MessageType:function(){return r.MessageType},createClient:function(){return o},isMessage:function(){return r.isMessage},parseMessage:function(){return r.parseMessage},stringifyMessage:function(){return r.stringifyMessage}});var r=n(863),i=n(6764);function o(e){const{url:t,connectionParams:o,lazy:s=!0,onNonLazyError:l=console.error,lazyCloseTimeout:u=0,keepAlive:c=0,disablePong:d,connectionAckWaitTimeout:f=0,retryAttempts:p=5,retryWait:h=async function(e){let t=1e3;for(let n=0;nsetTimeout(e,t+Math.floor(2700*Math.random()+300))))},isFatalConnectionProblem:m=(e=>!a(e)),on:g,webSocketImpl:v,generateID:y=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},jsonMessageReplacer:b,jsonMessageReviver:E}=e;let T;if(v){if(!("function"==typeof(w=v)&&"constructor"in w&&"CLOSED"in w&&"CLOSING"in w&&"CONNECTING"in w&&"OPEN"in w))throw new Error("Invalid WebSocket implementation provided");T=v}else"undefined"!=typeof WebSocket?T=WebSocket:void 0!==n.g?T=n.g.WebSocket||n.g.MozWebSocket:"undefined"!=typeof window&&(T=window.WebSocket||window.MozWebSocket);var w;if(!T)throw new Error("WebSocket implementation missing");const C=T,S=(()=>{const e=(()=>{const e={};return{on(t,n){return e[t]=n,()=>{delete e[t]}},emit(t){var n;"id"in t&&(null===(n=e[t.id])||void 0===n||n.call(e,t))}}})(),t={connecting:(null==g?void 0:g.connecting)?[g.connecting]:[],opened:(null==g?void 0:g.opened)?[g.opened]:[],connected:(null==g?void 0:g.connected)?[g.connected]:[],ping:(null==g?void 0:g.ping)?[g.ping]:[],pong:(null==g?void 0:g.pong)?[g.pong]:[],message:(null==g?void 0:g.message)?[e.emit,g.message]:[e.emit],closed:(null==g?void 0:g.closed)?[g.closed]:[],error:(null==g?void 0:g.error)?[g.error]:[]};return{onMessage:e.on,on(e,n){const r=t[e];return r.push(n),()=>{r.splice(r.indexOf(n),1)}},emit(e,...n){for(const r of[...t[e]])r(...n)}}})();function x(e){const t=[S.on("error",(n=>{t.forEach((e=>e())),e(n)})),S.on("closed",(n=>{t.forEach((e=>e())),e(n)}))]}let k,N=0,_=!1,O=0,I=!1;async function D(){const[e,n]=await(null!=k?k:k=new Promise(((e,n)=>(async()=>{if(_){if(await h(O),!N)return k=void 0,n({code:1e3,reason:"All Subscriptions Gone"});O++}S.emit("connecting");const a=new C("function"==typeof t?await t():t,r.GRAPHQL_TRANSPORT_WS_PROTOCOL);let s,l;function u(){isFinite(c)&&c>0&&(clearTimeout(l),l=setTimeout((()=>{a.readyState===C.OPEN&&(a.send((0,r.stringifyMessage)({type:r.MessageType.Ping})),S.emit("ping",!1,void 0))}),c))}x((e=>{k=void 0,clearTimeout(s),clearTimeout(l),n(e)})),a.onerror=e=>S.emit("error",e),a.onclose=e=>S.emit("closed",e),a.onopen=async()=>{try{S.emit("opened",a);const e="function"==typeof o?await o():o;a.send((0,r.stringifyMessage)(e?{type:r.MessageType.ConnectionInit,payload:e}:{type:r.MessageType.ConnectionInit},b)),isFinite(f)&&f>0&&(s=setTimeout((()=>{a.close(r.CloseCode.ConnectionAcknowledgementTimeout,"Connection acknowledgement timeout")}),f)),u()}catch(e){S.emit("error",e),a.close(r.CloseCode.InternalClientError,(0,i.qj)(e instanceof Error?e.message:new Error(e).message,"Internal client error"))}};let p=!1;a.onmessage=({data:t})=>{try{const n=(0,r.parseMessage)(t,E);if(S.emit("message",n),"ping"===n.type||"pong"===n.type)return S.emit(n.type,!0,n.payload),void("pong"===n.type?u():d||(a.send((0,r.stringifyMessage)(n.payload?{type:r.MessageType.Pong,payload:n.payload}:{type:r.MessageType.Pong})),S.emit("pong",!1,n.payload)));if(p)return;if(n.type!==r.MessageType.ConnectionAck)throw new Error(`First message cannot be of type ${n.type}`);clearTimeout(s),p=!0,S.emit("connected",a,n.payload),_=!1,O=0,e([a,new Promise(((e,t)=>x(t)))])}catch(e){a.onmessage=null,S.emit("error",e),a.close(r.CloseCode.BadResponse,(0,i.qj)(e instanceof Error?e.message:new Error(e).message,"Bad response"))}}})())));e.readyState===C.CLOSING&&await n;let a=()=>{};const s=new Promise((e=>a=e));return[e,a,Promise.race([s.then((()=>{if(!N){const t=()=>e.close(1e3,"Normal Closure");isFinite(u)&&u>0?setTimeout((()=>{N||e.readyState!==C.OPEN||t()}),u):t()}})),n])]}function L(e){if(a(e)&&(t=e.code,![1e3,1001,1006,1005,1012,1013,1013].includes(t)&&t>=1e3&&t<=1999||[r.CloseCode.InternalServerError,r.CloseCode.InternalClientError,r.CloseCode.BadRequest,r.CloseCode.BadResponse,r.CloseCode.Unauthorized,r.CloseCode.SubprotocolNotAcceptable,r.CloseCode.SubscriberAlreadyExists,r.CloseCode.TooManyInitialisationRequests].includes(e.code)))throw e;var t;if(I)return!1;if(a(e)&&1e3===e.code)return N>0;if(!p||O>=p)throw e;if(m(e))throw e;return _=!0}return s||(async()=>{for(N++;;)try{const[,,e]=await D();await e}catch(e){try{if(!L(e))return}catch(e){return null==l?void 0:l(e)}}})(),{on:S.on,subscribe(e,t){const n=y();let i=!1,o=!1,a=()=>{N--,i=!0};return(async()=>{for(N++;;)try{const[s,l,u]=await D();if(i)return l();const c=S.onMessage(n,(e=>{switch(e.type){case r.MessageType.Next:return void t.next(e.payload);case r.MessageType.Error:return o=!0,i=!0,t.error(e.payload),void a();case r.MessageType.Complete:return i=!0,void a()}}));return s.send((0,r.stringifyMessage)({id:n,type:r.MessageType.Subscribe,payload:e},b)),a=()=>{i||s.readyState!==C.OPEN||s.send((0,r.stringifyMessage)({id:n,type:r.MessageType.Complete},b)),N--,i=!0,l()},void await u.finally(c)}catch(e){if(!L(e))return}})().then((()=>{o||t.complete()})).catch((e=>{t.error(e)})),()=>{i||a()}},async dispose(){if(I=!0,k){const[e]=await k;e.close(1e3,"Normal Closure")}}}}function a(e){return(0,i.Kn)(e)&&"code"in e&&"reason"in e}},863:function(e,t,n){"use strict";n.r(t),n.d(t,{CloseCode:function(){return o},GRAPHQL_TRANSPORT_WS_PROTOCOL:function(){return i},MessageType:function(){return a},isMessage:function(){return s},parseMessage:function(){return l},stringifyMessage:function(){return u}});var r=n(6764);const i="graphql-transport-ws";var o,a;function s(e){if((0,r.Kn)(e)){if(!(0,r.ND)(e,"type"))return!1;switch(e.type){case a.ConnectionInit:case a.ConnectionAck:case a.Ping:case a.Pong:return!(0,r.nr)(e,"payload")||void 0===e.payload||(0,r.Kn)(e.payload);case a.Subscribe:return(0,r.ND)(e,"id")&&(0,r.O2)(e,"payload")&&(!(0,r.nr)(e.payload,"operationName")||void 0===e.payload.operationName||null===e.payload.operationName||"string"==typeof e.payload.operationName)&&(0,r.ND)(e.payload,"query")&&(!(0,r.nr)(e.payload,"variables")||void 0===e.payload.variables||null===e.payload.variables||(0,r.O2)(e.payload,"variables"))&&(!(0,r.nr)(e.payload,"extensions")||void 0===e.payload.extensions||null===e.payload.extensions||(0,r.O2)(e.payload,"extensions"));case a.Next:return(0,r.ND)(e,"id")&&(0,r.O2)(e,"payload");case a.Error:return(0,r.ND)(e,"id")&&(0,r.Ox)(e.payload);case a.Complete:return(0,r.ND)(e,"id");default:return!1}}return!1}function l(e,t){if(s(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const n=JSON.parse(e,t);if(!s(n))throw new Error("Invalid message");return n}function u(e,t){if(!s(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e,t)}!function(e){e[e.InternalServerError=4500]="InternalServerError",e[e.InternalClientError=4005]="InternalClientError",e[e.BadRequest=4400]="BadRequest",e[e.BadResponse=4004]="BadResponse",e[e.Unauthorized=4401]="Unauthorized",e[e.Forbidden=4403]="Forbidden",e[e.SubprotocolNotAcceptable=4406]="SubprotocolNotAcceptable",e[e.ConnectionInitialisationTimeout=4408]="ConnectionInitialisationTimeout",e[e.ConnectionAcknowledgementTimeout=4504]="ConnectionAcknowledgementTimeout",e[e.SubscriberAlreadyExists=4409]="SubscriberAlreadyExists",e[e.TooManyInitialisationRequests=4429]="TooManyInitialisationRequests"}(o||(o={})),function(e){e.ConnectionInit="connection_init",e.ConnectionAck="connection_ack",e.Ping="ping",e.Pong="pong",e.Subscribe="subscribe",e.Next="next",e.Error="error",e.Complete="complete"}(a||(a={}))},6718:function(e,t,n){"use strict";n.r(t),n.d(t,{makeServer:function(){return f}});var r=n(953),i=n(2780),o=n(9458),a=n(4117),s=n(2941),l=n(7180),u=n(863),c=n(6764),d=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e="function"==typeof __values?__values(e):e[Symbol.iterator](),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,i){!function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)}(r,i,(t=e[n](t)).done,t.value)}))}}};function f(e){const{schema:t,context:n,roots:f,validate:p,execute:h,subscribe:m,connectionInitWaitTimeout:g=3e3,onConnect:v,onDisconnect:y,onClose:b,onSubscribe:E,onOperation:T,onNext:w,onError:C,onComplete:S,jsonMessageReviver:x,jsonMessageReplacer:k}=e;return{opened(e,N){const _={connectionInitReceived:!1,acknowledged:!1,subscriptions:{},extra:N};if(e.protocol!==u.GRAPHQL_TRANSPORT_WS_PROTOCOL)return e.close(u.CloseCode.SubprotocolNotAcceptable,"Subprotocol not acceptable"),async(e,t)=>{await(null==b?void 0:b(_,e,t))};const O=g>0&&isFinite(g)?setTimeout((()=>{_.connectionInitReceived||e.close(u.CloseCode.ConnectionInitialisationTimeout,"Connection initialisation timeout")}),g):null;return e.onMessage((async function(g){var y,b,N;let O;try{O=(0,u.parseMessage)(g,x)}catch(t){return e.close(u.CloseCode.BadRequest,"Invalid message received")}switch(O.type){case u.MessageType.ConnectionInit:{if(_.connectionInitReceived)return e.close(u.CloseCode.TooManyInitialisationRequests,"Too many initialisation requests");_.connectionInitReceived=!0,(0,c.Kn)(O.payload)&&(_.connectionParams=O.payload);const t=await(null==v?void 0:v(_));return!1===t?e.close(u.CloseCode.Forbidden,"Forbidden"):(await e.send((0,u.stringifyMessage)((0,c.Kn)(t)?{type:u.MessageType.ConnectionAck,payload:t}:{type:u.MessageType.ConnectionAck},k)),void(_.acknowledged=!0))}case u.MessageType.Ping:return e.onPing?await e.onPing(O.payload):void await e.send((0,u.stringifyMessage)(O.payload?{type:u.MessageType.Pong,payload:O.payload}:{type:u.MessageType.Pong}));case u.MessageType.Pong:return await(null===(N=e.onPong)||void 0===N?void 0:N.call(e,O.payload));case u.MessageType.Subscribe:{if(!_.acknowledged)return e.close(u.CloseCode.Unauthorized,"Unauthorized");const{id:g,payload:v}=O;if(g in _.subscriptions)return e.close(u.CloseCode.SubscriberAlreadyExists,`Subscriber for ${g} already exists`);_.subscriptions[g]=null;const x={next:async(t,n)=>{let r={id:g,type:u.MessageType.Next,payload:t};const i=await(null==w?void 0:w(_,r,n,t));i&&(r=Object.assign(Object.assign({},r),{payload:i})),await e.send((0,u.stringifyMessage)(r,k))},error:async t=>{let n={id:g,type:u.MessageType.Error,payload:t};const r=await(null==C?void 0:C(_,n,t));r&&(n=Object.assign(Object.assign({},n),{payload:r})),await e.send((0,u.stringifyMessage)(n,k))},complete:async t=>{const n={id:g,type:u.MessageType.Complete};await(null==S?void 0:S(_,n)),t&&await e.send((0,u.stringifyMessage)(n,k))}};let N;const L=await(null==E?void 0:E(_,O));if(L){if((0,c.Ox)(L))return await x.error(L);if(Array.isArray(L))throw new Error("Invalid return value from onSubscribe hook, expected an array of GraphQLError objects");N=L}else{if(!t)throw new Error("The GraphQL schema is not provided");const e={operationName:v.operationName,document:(0,r.Qc)(v.query),variableValues:v.variables};N=Object.assign(Object.assign({},e),{schema:"function"==typeof t?await t(_,O,e):t});const n=(null!=p?p:i.Gu)(N.schema,N.document);if(n.length>0)return await x.error(n)}const A=(0,o.S)(N.document,N.operationName);if(!A)return await x.error([new a.__("Unable to identify operation")]);let M;"rootValue"in N||(N.rootValue=null==f?void 0:f[A.operation]),"contextValue"in N||(N.contextValue="function"==typeof n?await n(_,O,N):n),M="subscription"===A.operation?await(null!=m?m:s.L)(N):await(null!=h?h:l.ht)(N);const R=await(null==T?void 0:T(_,O,N,M));if(R&&(M=R),(0,c.D0)(M))if(g in _.subscriptions){_.subscriptions[g]=M;try{for(var I,D=d(M);!(I=await D.next()).done;){const e=I.value;await x.next(e,N)}}catch(e){y={error:e}}finally{try{I&&!I.done&&(b=D.return)&&await b.call(D)}finally{if(y)throw y.error}}}else(0,c.Jy)(M)&&M.return(void 0);else g in _.subscriptions&&await x.next(M,N);return await x.complete(g in _.subscriptions),void delete _.subscriptions[g]}case u.MessageType.Complete:{const e=_.subscriptions[O.id];return(0,c.Jy)(e)&&await e.return(void 0),void delete _.subscriptions[O.id]}default:throw new Error(`Unexpected message of type ${O.type} received`)}})),async(e,t)=>{O&&clearTimeout(O);for(const e of Object.values(_.subscriptions))(0,c.Jy)(e)&&await e.return(void 0);_.acknowledged&&await(null==y?void 0:y(_,e,t)),await(null==b?void 0:b(_,e,t))}}}}},6764:function(e,t,n){"use strict";n.d(t,{D0:function(){return o},Jy:function(){return a},Kn:function(){return i},ND:function(){return c},O2:function(){return u},Ox:function(){return s},nr:function(){return l},qj:function(){return d}});const r=Object.prototype.hasOwnProperty;function i(e){return"object"==typeof e&&null!==e}function o(e){return"function"==typeof Object(e)[Symbol.asyncIterator]}function a(e){return i(e)&&"function"==typeof Object(e)[Symbol.asyncIterator]&&"function"==typeof e.return}function s(e){return Array.isArray(e)&&e.length>0&&e.every((e=>"message"in e))}function l(e,t){return r.call(e,t)}function u(e,t){return r.call(e,t)&&i(e[t])}function c(e,t){return r.call(e,t)&&"string"==typeof e[t]}function d(e,t){return e.length<124?e:t}},4117:function(e,t,n){"use strict";n.d(t,{OS:function(){return l},Z:function(){return u},__:function(){return a}});var r=n(1315),i=n(3302),o=n(7026);class a extends Error{constructor(e,...t){var n,o,l;const{nodes:u,source:c,positions:d,path:f,originalError:p,extensions:h}=function(e){const t=e[0];return null==t||"kind"in t||"length"in t?{nodes:t,source:e[1],positions:e[2],path:e[3],originalError:e[4],extensions:e[5]}:t}(t);super(e),this.name="GraphQLError",this.path=null!=f?f:void 0,this.originalError=null!=p?p:void 0,this.nodes=s(Array.isArray(u)?u:u?[u]:void 0);const m=s(null===(n=this.nodes)||void 0===n?void 0:n.map((e=>e.loc)).filter((e=>null!=e)));this.source=null!=c?c:null==m||null===(o=m[0])||void 0===o?void 0:o.source,this.positions=null!=d?d:null==m?void 0:m.map((e=>e.start)),this.locations=d&&c?d.map((e=>(0,i.k)(c,e))):null==m?void 0:m.map((e=>(0,i.k)(e.source,e.start)));const g=(0,r.y)(null==p?void 0:p.extensions)?null==p?void 0:p.extensions:void 0;this.extensions=null!==(l=null!=h?h:g)&&void 0!==l?l:Object.create(null),Object.defineProperties(this,{message:{writable:!0,enumerable:!0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=p&&p.stack?Object.defineProperty(this,"stack",{value:p.stack,writable:!0,configurable:!0}):Error.captureStackTrace?Error.captureStackTrace(this,a):Object.defineProperty(this,"stack",{value:Error().stack,writable:!0,configurable:!0})}get[Symbol.toStringTag](){return"GraphQLError"}toString(){let e=this.message;if(this.nodes)for(const t of this.nodes)t.loc&&(e+="\n\n"+(0,o.Q)(t.loc));else if(this.source&&this.locations)for(const t of this.locations)e+="\n\n"+(0,o.z)(this.source,t);return e}toJSON(){const e={message:this.message};return null!=this.locations&&(e.locations=this.locations),null!=this.path&&(e.path=this.path),null!=this.extensions&&Object.keys(this.extensions).length>0&&(e.extensions=this.extensions),e}}function s(e){return void 0===e||0===e.length?void 0:e}function l(e){return e.toString()}function u(e){return e.toJSON()}},4647:function(e,t,n){"use strict";n.d(t,{y:function(){return a}});var r=n(5648);class i extends Error{constructor(e){super("Unexpected error value: "+(0,r.X)(e)),this.name="NonErrorThrown",this.thrownValue=e}}var o=n(4117);function a(e,t,n){var r;const a=(s=e)instanceof Error?s:new i(s);var s,l;return l=a,Array.isArray(l.path)?a:new o.__(a.message,{nodes:null!==(r=a.nodes)&&void 0!==r?r:t,source:a.source,positions:a.positions,path:n,originalError:a})}},2024:function(e,t,n){"use strict";n.d(t,{h:function(){return i}});var r=n(4117);function i(e,t,n){return new r.__(`Syntax Error: ${n}`,{source:e,positions:[t]})}},5267:function(e,t,n){"use strict";n.d(t,{g:function(){return l},w:function(){return u}});var r=n(3830),i=n(755),o=n(5946),a=n(5998),s=n(2806);function l(e,t,n,r,i){const o=new Map;return c(e,t,n,r,i,o,new Set),o}function u(e,t,n,r,i){const o=new Map,a=new Set;for(const s of i)s.selectionSet&&c(e,t,n,r,s.selectionSet,o,a);return o}function c(e,t,n,i,o,a,s){for(const u of o.selections)switch(u.kind){case r.h.FIELD:{if(!d(n,u))continue;const e=(l=u).alias?l.alias.value:l.name.value,t=a.get(e);void 0!==t?t.push(u):a.set(e,[u]);break}case r.h.INLINE_FRAGMENT:if(!d(n,u)||!f(e,u,i))continue;c(e,t,n,i,u.selectionSet,a,s);break;case r.h.FRAGMENT_SPREAD:{const r=u.name.value;if(s.has(r)||!d(n,u))continue;s.add(r);const o=t[r];if(!o||!f(e,o,i))continue;c(e,t,n,i,o.selectionSet,a,s);break}}var l}function d(e,t){const n=(0,s.zu)(o.QE,t,e);if(!0===(null==n?void 0:n.if))return!1;const r=(0,s.zu)(o.Yf,t,e);return!1!==(null==r?void 0:r.if)}function f(e,t,n){const r=t.typeCondition;if(!r)return!0;const o=(0,a._)(e,r);return o===n||!!(0,i.m0)(o)&&e.isSubType(o,n)}},7180:function(e,t,n){"use strict";n.d(t,{td:function(){return C},VZ:function(){return S},p$:function(){return N},El:function(){return M},mn:function(){return A},ht:function(){return E},p0:function(){return T},Vm:function(){return R}});var r=n(1172),i=n(5648),o=n(5052),a=n(2910),s=n(1315),l=n(1864),u=n(9878),c=n(4117),d=n(4647),f=n(3526),p=n(3830),h=n(755),m=n(8078),g=n(8555),v=n(5267),y=n(2806);const b=function(e){let t;return function(e,n,r){void 0===t&&(t=new WeakMap);let i=t.get(e);void 0===i&&(i=new WeakMap,t.set(e,i));let o=i.get(n);void 0===o&&(o=new WeakMap,i.set(n,o));let a=o.get(r);return void 0===a&&(s=e,l=n,u=r,a=(0,v.w)(s.schema,s.fragments,s.variableValues,l,u),o.set(r,a)),a;var s,l,u}}();function E(e){arguments.length<2||(0,r.a)(!1,"graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.");const{schema:t,document:n,variableValues:i,rootValue:o}=e;C(t,n,i);const a=S(e);if(!("schema"in a))return{errors:a};try{const{operation:e}=a,t=function(e,t,n){const r=e.schema.getRootType(t.operation);if(null==r)throw new c.__(`Schema is not configured to execute ${t.operation} operation.`,{nodes:t});const i=(0,v.g)(e.schema,e.fragments,e.variableValues,r,t.selectionSet),o=void 0;switch(t.operation){case f.ku.QUERY:return x(e,r,n,o,i);case f.ku.MUTATION:return function(e,t,n,r,i){return function(e,t,n){let r=Object.create(null);for(const n of e)r=(0,l.t)(r)?r.then((e=>t(e,n))):t(r,n);return r}(i.entries(),((r,[i,o])=>{const a=(0,u.Q)(undefined,i,t.name),s=k(e,t,n,o,a);return void 0===s?r:(0,l.t)(s)?s.then((e=>(r[i]=e,r))):(r[i]=s,r)}))}(e,r,n,0,i);case f.ku.SUBSCRIPTION:return x(e,r,n,o,i)}}(a,e,o);return(0,l.t)(t)?t.then((e=>w(e,a.errors)),(e=>(a.errors.push(e),w(null,a.errors)))):w(t,a.errors)}catch(e){return a.errors.push(e),w(null,a.errors)}}function T(e){const t=E(e);if((0,l.t)(t))throw new Error("GraphQL execution failed to complete synchronously.");return t}function w(e,t){return 0===t.length?{data:e}:{errors:t,data:e}}function C(e,t,n){t||(0,r.a)(!1,"Must provide document."),(0,g.J)(e),null==n||(0,s.y)(n)||(0,r.a)(!1,"Variables must be provided as an Object where each property is a variable value. Perhaps look to see if an unparsed JSON string was provided.")}function S(e){var t,n;const{schema:r,document:i,rootValue:o,contextValue:a,variableValues:s,operationName:l,fieldResolver:u,typeResolver:d,subscribeFieldResolver:f}=e;let h;const m=Object.create(null);for(const e of i.definitions)switch(e.kind){case p.h.OPERATION_DEFINITION:if(null==l){if(void 0!==h)return[new c.__("Must provide operation name if query contains multiple operations.")];h=e}else(null===(t=e.name)||void 0===t?void 0:t.value)===l&&(h=e);break;case p.h.FRAGMENT_DEFINITION:m[e.name.value]=e}if(!h)return null!=l?[new c.__(`Unknown operation named "${l}".`)]:[new c.__("Must provide an operation.")];const g=null!==(n=h.variableDefinitions)&&void 0!==n?n:[],v=(0,y.QF)(r,g,null!=s?s:{},{maxErrors:50});return v.errors?v.errors:{schema:r,fragments:m,rootValue:o,contextValue:a,operation:h,variableValues:v.coerced,fieldResolver:null!=u?u:M,typeResolver:null!=d?d:A,subscribeFieldResolver:null!=f?f:M,errors:[]}}function x(e,t,n,r,i){const o=Object.create(null);let a=!1;for(const[s,c]of i.entries()){const i=k(e,t,n,c,(0,u.Q)(r,s,t.name));void 0!==i&&(o[s]=i,(0,l.t)(i)&&(a=!0))}return a?(s=o,Promise.all(Object.values(s)).then((e=>{const t=Object.create(null);for(const[n,r]of Object.keys(s).entries())t[r]=e[n];return t}))):o;var s}function k(e,t,n,r,i){var o;const a=R(e.schema,t,r[0]);if(!a)return;const s=a.type,c=null!==(o=a.resolve)&&void 0!==o?o:e.fieldResolver,f=N(e,a,r,t,i);try{const t=c(n,(0,y.LX)(a,r[0],e.variableValues),e.contextValue,f);let o;return o=(0,l.t)(t)?t.then((t=>O(e,s,r,f,i,t))):O(e,s,r,f,i,t),(0,l.t)(o)?o.then(void 0,(t=>_((0,d.y)(t,r,(0,u.N)(i)),s,e))):o}catch(t){return _((0,d.y)(t,r,(0,u.N)(i)),s,e)}}function N(e,t,n,r,i){return{fieldName:t.name,fieldNodes:n,returnType:t.type,parentType:r,path:i,schema:e.schema,fragments:e.fragments,rootValue:e.rootValue,operation:e.operation,variableValues:e.variableValues}}function _(e,t,n){if((0,h.zM)(t))throw e;return n.errors.push(e),null}function O(e,t,n,r,s,f){if(f instanceof Error)throw f;if((0,h.zM)(t)){const i=O(e,t.ofType,n,r,s,f);if(null===i)throw new Error(`Cannot return null for non-nullable field ${r.parentType.name}.${r.fieldName}.`);return i}return null==f?null:(0,h.HG)(t)?function(e,t,n,r,i,o){if(!(0,a.i)(o))throw new c.__(`Expected Iterable, but did not find one for field "${r.parentType.name}.${r.fieldName}".`);const s=t.ofType;let f=!1;const p=Array.from(o,((t,o)=>{const a=(0,u.Q)(i,o,void 0);try{let i;return i=(0,l.t)(t)?t.then((t=>O(e,s,n,r,a,t))):O(e,s,n,r,a,t),(0,l.t)(i)?(f=!0,i.then(void 0,(t=>_((0,d.y)(t,n,(0,u.N)(a)),s,e)))):i}catch(t){return _((0,d.y)(t,n,(0,u.N)(a)),s,e)}}));return f?Promise.all(p):p}(e,t,n,r,s,f):(0,h.UT)(t)?function(e,t){const n=e.serialize(t);if(null==n)throw new Error(`Expected \`${(0,i.X)(e)}.serialize(${(0,i.X)(t)})\` to return non-nullable value, returned: ${(0,i.X)(n)}`);return n}(t,f):(0,h.m0)(t)?function(e,t,n,r,i,o){var a;const s=null!==(a=t.resolveType)&&void 0!==a?a:e.typeResolver,u=e.contextValue,c=s(o,u,r,t);return(0,l.t)(c)?c.then((a=>D(e,I(a,e,t,n,r,o),n,r,i,o))):D(e,I(c,e,t,n,r,o),n,r,i,o)}(e,t,n,r,s,f):(0,h.lp)(t)?D(e,t,n,r,s,f):void(0,o.k)(!1,"Cannot complete value of unexpected output type: "+(0,i.X)(t))}function I(e,t,n,r,o,a){if(null==e)throw new c.__(`Abstract type "${n.name}" must resolve to an Object type at runtime for field "${o.parentType.name}.${o.fieldName}". Either the "${n.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`,r);if((0,h.lp)(e))throw new c.__("Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.");if("string"!=typeof e)throw new c.__(`Abstract type "${n.name}" must resolve to an Object type at runtime for field "${o.parentType.name}.${o.fieldName}" with value ${(0,i.X)(a)}, received "${(0,i.X)(e)}".`);const s=t.schema.getType(e);if(null==s)throw new c.__(`Abstract type "${n.name}" was resolved to a type "${e}" that does not exist inside the schema.`,{nodes:r});if(!(0,h.lp)(s))throw new c.__(`Abstract type "${n.name}" was resolved to a non-object type "${e}".`,{nodes:r});if(!t.schema.isSubType(n,s))throw new c.__(`Runtime Object type "${s.name}" is not a possible type for "${n.name}".`,{nodes:r});return s}function D(e,t,n,r,i,o){const a=b(e,t,n);if(t.isTypeOf){const s=t.isTypeOf(o,e.contextValue,r);if((0,l.t)(s))return s.then((r=>{if(!r)throw L(t,o,n);return x(e,t,o,i,a)}));if(!s)throw L(t,o,n)}return x(e,t,o,i,a)}function L(e,t,n){return new c.__(`Expected value of type "${e.name}" but got: ${(0,i.X)(t)}.`,{nodes:n})}const A=function(e,t,n,r){if((0,s.y)(e)&&"string"==typeof e.__typename)return e.__typename;const i=n.schema.getPossibleTypes(r),o=[];for(let r=0;r{for(let t=0;t(0,c.ht)({schema:t,document:n,rootValue:e,contextValue:a,variableValues:s,operationName:l,fieldResolver:u}))):f}async function p(e,t,n,r,f,p,h){(0,c.td)(e,t,f);const m=(0,c.VZ)({schema:e,document:t,rootValue:n,contextValue:r,variableValues:f,operationName:p,subscribeFieldResolver:h});if(!("schema"in m))return{errors:m};try{const e=await async function(e){const{schema:t,fragments:n,operation:r,variableValues:i,rootValue:o}=e,f=t.getSubscriptionType();if(null==f)throw new s.__("Schema is not configured to execute subscription operation.",{nodes:r});const p=(0,u.g)(t,n,i,f,r.selectionSet),[h,m]=[...p.entries()][0],g=(0,c.Vm)(t,f,m[0]);if(!g){const e=m[0].name.value;throw new s.__(`The subscription field "${e}" is not defined.`,{nodes:m})}const v=(0,a.Q)(void 0,h,f.name),y=(0,c.p$)(e,g,m,f,v);try{var b;const t=(0,d.LX)(g,m[0],i),n=e.contextValue,r=null!==(b=g.subscribe)&&void 0!==b?b:e.subscribeFieldResolver,a=await r(o,t,n,y);if(a instanceof Error)throw a;return a}catch(e){throw(0,l.y)(e,m,(0,a.N)(v))}}(m);if(!o(e))throw new Error(`Subscription field must return Async Iterable. Received: ${(0,i.X)(e)}.`);return e}catch(e){if(e instanceof s.__)return{errors:[e]};throw e}}},2806:function(e,t,n){"use strict";n.d(t,{LX:function(){return h},QF:function(){return p},zu:function(){return m}});var r=n(5648),i=n(9815),o=n(4987),a=n(4117),s=n(3830),l=n(5895),u=n(755),c=n(5925),d=n(5998),f=n(5284);function p(e,t,n,i){const s=[],p=null==i?void 0:i.maxErrors;try{const i=function(e,t,n,i){const s={};for(const p of t){const t=p.variable.name.value,h=(0,d._)(e,p.type);if(!(0,u.j$)(h)){const e=(0,l.S)(p.type);i(new a.__(`Variable "$${t}" expected value of type "${e}" which cannot be used as an input type.`,{nodes:p.type}));continue}if(!g(n,t)){if(p.defaultValue)s[t]=(0,f.u)(p.defaultValue,h);else if((0,u.zM)(h)){const e=(0,r.X)(h);i(new a.__(`Variable "$${t}" of required type "${e}" was not provided.`,{nodes:p}))}continue}const m=n[t];if(null===m&&(0,u.zM)(h)){const e=(0,r.X)(h);i(new a.__(`Variable "$${t}" of non-null type "${e}" must not be null.`,{nodes:p}))}else s[t]=(0,c.K)(m,h,((e,n,s)=>{let l=`Variable "$${t}" got invalid value `+(0,r.X)(n);e.length>0&&(l+=` at "${t}${(0,o.F)(e)}"`),i(new a.__(l+"; "+s.message,{nodes:p,originalError:s.originalError}))}))}return s}(e,t,n,(e=>{if(null!=p&&s.length>=p)throw new a.__("Too many errors processing variables, error limit reached. Execution aborted.");s.push(e)}));if(0===s.length)return{coerced:i}}catch(e){s.push(e)}return{errors:s}}function h(e,t,n){var o;const c={},d=null!==(o=t.arguments)&&void 0!==o?o:[],p=(0,i.P)(d,(e=>e.name.value));for(const i of e.args){const e=i.name,o=i.type,d=p[e];if(!d){if(void 0!==i.defaultValue)c[e]=i.defaultValue;else if((0,u.zM)(o))throw new a.__(`Argument "${e}" of required type "${(0,r.X)(o)}" was not provided.`,{nodes:t});continue}const h=d.value;let m=h.kind===s.h.NULL;if(h.kind===s.h.VARIABLE){const t=h.name.value;if(null==n||!g(n,t)){if(void 0!==i.defaultValue)c[e]=i.defaultValue;else if((0,u.zM)(o))throw new a.__(`Argument "${e}" of required type "${(0,r.X)(o)}" was provided the variable "$${t}" which was not provided a runtime value.`,{nodes:h});continue}m=null==n[t]}if(m&&(0,u.zM)(o))throw new a.__(`Argument "${e}" of non-null type "${(0,r.X)(o)}" must not be null.`,{nodes:h});const v=(0,f.u)(h,o,n);if(void 0===v)throw new a.__(`Argument "${e}" has invalid value ${(0,l.S)(h)}.`,{nodes:h});c[e]=v}return c}function m(e,t,n){var r;const i=null===(r=t.directives)||void 0===r?void 0:r.find((t=>t.name.value===e.name));if(i)return h(e,i,n)}function g(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},3573:function(e,t,n){"use strict";n.r(t),n.d(t,{BREAK:function(){return N.$_},BreakingChangeType:function(){return pt},DEFAULT_DEPRECATION_REASON:function(){return g.SY},DangerousChangeType:function(){return ht},DirectiveLocation:function(){return O.B},ExecutableDefinitionsRule:function(){return U.i},FieldsOnCorrectTypeRule:function(){return B.A},FragmentsOnCompositeTypesRule:function(){return $.T},GRAPHQL_MAX_INT:function(){return v.HI},GRAPHQL_MIN_INT:function(){return v.st},GraphQLBoolean:function(){return v.EZ},GraphQLDeprecatedDirective:function(){return g.fg},GraphQLDirective:function(){return g.NZ},GraphQLEnumType:function(){return h.mR},GraphQLError:function(){return R.__},GraphQLFloat:function(){return v.av},GraphQLID:function(){return v.km},GraphQLIncludeDirective:function(){return g.Yf},GraphQLInputObjectType:function(){return h.sR},GraphQLInt:function(){return v._o},GraphQLInterfaceType:function(){return h.oW},GraphQLList:function(){return h.p2},GraphQLNonNull:function(){return h.bM},GraphQLObjectType:function(){return h.h6},GraphQLScalarType:function(){return h.n2},GraphQLSchema:function(){return m.XO},GraphQLSkipDirective:function(){return g.QE},GraphQLSpecifiedByDirective:function(){return g.df},GraphQLString:function(){return v.kH},GraphQLUnionType:function(){return h.Gp},Kind:function(){return _.h},KnownArgumentNamesRule:function(){return q.e},KnownDirectivesRule:function(){return H.J},KnownFragmentNamesRule:function(){return G.a},KnownTypeNamesRule:function(){return z.I},Lexer:function(){return S.h},Location:function(){return E.Ye},LoneAnonymousOperationRule:function(){return W.F},LoneSchemaDefinitionRule:function(){return fe.t},NoDeprecatedCustomRule:function(){return F},NoFragmentCyclesRule:function(){return K.H},NoSchemaIntrospectionCustomRule:function(){return P},NoUndefinedVariablesRule:function(){return Q.$},NoUnusedFragmentsRule:function(){return X.J},NoUnusedVariablesRule:function(){return Y.p},OperationTypeNode:function(){return E.ku},OverlappingFieldsCanBeMergedRule:function(){return J.y},PossibleFragmentSpreadsRule:function(){return Z.a},PossibleTypeExtensionsRule:function(){return be.g},ProvidedRequiredArgumentsRule:function(){return ee.s},ScalarLeafsRule:function(){return te.O},SchemaMetaFieldDef:function(){return y.Az},SingleFieldSubscriptionsRule:function(){return ne.Z},Source:function(){return T.H},Token:function(){return E.WU},TokenKind:function(){return x.T},TypeInfo:function(){return Mt.a},TypeKind:function(){return y.zU},TypeMetaFieldDef:function(){return y.tF},TypeNameMetaFieldDef:function(){return y.hU},UniqueArgumentDefinitionNamesRule:function(){return ve.L},UniqueArgumentNamesRule:function(){return re.L},UniqueDirectiveNamesRule:function(){return ye.o},UniqueDirectivesPerLocationRule:function(){return ie.k},UniqueEnumValueNamesRule:function(){return me.L},UniqueFieldDefinitionNamesRule:function(){return ge.y},UniqueFragmentNamesRule:function(){return oe.N},UniqueInputFieldNamesRule:function(){return ae.P},UniqueOperationNamesRule:function(){return se.H},UniqueOperationTypesRule:function(){return pe.q},UniqueTypeNamesRule:function(){return he.P},UniqueVariableNamesRule:function(){return le.H},ValidationContext:function(){return j._t},ValuesOfCorrectTypeRule:function(){return ue.j},VariablesAreInputTypesRule:function(){return ce.I},VariablesInAllowedPositionRule:function(){return de.w},__Directive:function(){return y.l3},__DirectiveLocation:function(){return y.x2},__EnumValue:function(){return y.jT},__Field:function(){return y.e_},__InputValue:function(){return y.XQ},__Schema:function(){return y.TK},__Type:function(){return y.qz},__TypeKind:function(){return y.PX},assertAbstractType:function(){return h.fU},assertCompositeType:function(){return h.M_},assertDirective:function(){return g.CO},assertEnumType:function(){return h.Zu},assertEnumValueName:function(){return b.g},assertInputObjectType:function(){return h.U8},assertInputType:function(){return h.qT},assertInterfaceType:function(){return h.k2},assertLeafType:function(){return h.H5},assertListType:function(){return h.kS},assertName:function(){return b.i},assertNamedType:function(){return h.rM},assertNonNullType:function(){return h.E$},assertNullableType:function(){return h.i_},assertObjectType:function(){return h.Z6},assertOutputType:function(){return h.Gt},assertScalarType:function(){return h.Pt},assertSchema:function(){return m.EO},assertType:function(){return h.p_},assertUnionType:function(){return h.rc},assertValidName:function(){return ct},assertValidSchema:function(){return l.J},assertWrappingType:function(){return h.vX},astFromValue:function(){return Ge.J},buildASTSchema:function(){return Pe},buildClientSchema:function(){return Oe},buildSchema:function(){return je},coerceInputValue:function(){return Rt.K},concatAST:function(){return ot},createSourceEventStream:function(){return A.z},defaultFieldResolver:function(){return c.El},defaultTypeResolver:function(){return c.mn},doTypesOverlap:function(){return Ft.zR},execute:function(){return c.ht},executeSync:function(){return c.p0},extendSchema:function(){return Le},findBreakingChanges:function(){return mt},findDangerousChanges:function(){return gt},formatError:function(){return R.Z},getArgumentValues:function(){return L.LX},getDirectiveValues:function(){return L.zu},getEnterLeaveForKind:function(){return N.Eu},getIntrospectionQuery:function(){return we},getLocation:function(){return w.k},getNamedType:function(){return h.xC},getNullableType:function(){return h.tf},getOperationAST:function(){return Dt.S},getOperationRootType:function(){return Ce},getVariableValues:function(){return L.QF},getVisitFn:function(){return N.CK},graphql:function(){return d},graphqlSync:function(){return f},introspectionFromSchema:function(){return Se},introspectionTypes:function(){return y.nL},isAbstractType:function(){return h.m0},isCompositeType:function(){return h.Gv},isConstValueNode:function(){return I.Of},isDefinitionNode:function(){return I.Ir},isDirective:function(){return g.wX},isEnumType:function(){return h.EM},isEqualType:function(){return Ft._7},isExecutableDefinitionNode:function(){return I.Wk},isInputObjectType:function(){return h.hL},isInputType:function(){return h.j$},isInterfaceType:function(){return h.oT},isIntrospectionType:function(){return y.s9},isLeafType:function(){return h.UT},isListType:function(){return h.HG},isNamedType:function(){return h.Zs},isNonNullType:function(){return h.zM},isNullableType:function(){return h.zP},isObjectType:function(){return h.lp},isOutputType:function(){return h.SZ},isRequiredArgument:function(){return h.dK},isRequiredInputField:function(){return h.Wd},isScalarType:function(){return h.KA},isSchema:function(){return m.nN},isSelectionNode:function(){return I.pO},isSpecifiedDirective:function(){return g.xg},isSpecifiedScalarType:function(){return v.u1},isType:function(){return h.P9},isTypeDefinitionNode:function(){return I.zT},isTypeExtensionNode:function(){return I.D$},isTypeNode:function(){return I.VB},isTypeSubTypeOf:function(){return Ft.uJ},isTypeSystemDefinitionNode:function(){return I.G4},isTypeSystemExtensionNode:function(){return I.aU},isUnionType:function(){return h.EN},isValidNameError:function(){return dt},isValueNode:function(){return I.nr},isWrappingType:function(){return h.fw},lexicographicSortSchema:function(){return Ue},locatedError:function(){return Te.y},parse:function(){return s.Qc},parseConstValue:function(){return s.tl},parseType:function(){return s.gZ},parseValue:function(){return s.H2},print:function(){return k.S},printError:function(){return R.OS},printIntrospectionSchema:function(){return We},printLocation:function(){return C.Q},printSchema:function(){return ze},printSourceLocation:function(){return C.z},printType:function(){return Ye},resolveObjMapThunk:function(){return h.WB},resolveReadonlyArrayThunk:function(){return h._9},responsePathAsArray:function(){return D.N},separateOperations:function(){return at},specifiedDirectives:function(){return g.V4},specifiedRules:function(){return V.i},specifiedScalarTypes:function(){return v.HS},stripIgnoredCharacters:function(){return ut},subscribe:function(){return A.L},syntaxError:function(){return Ee.h},typeFromAST:function(){return Lt._},validate:function(){return u.Gu},validateSchema:function(){return l.F},valueFromAST:function(){return _e.u},valueFromASTUntyped:function(){return At.M},version:function(){return r},versionInfo:function(){return i},visit:function(){return N.Vn},visitInParallel:function(){return N.j1},visitWithTypeInfo:function(){return Mt.y}});const r="16.5.0",i=Object.freeze({major:16,minor:5,patch:0,preReleaseTag:null});var o=n(1172),a=n(1864),s=n(953),l=n(8555),u=n(2780),c=n(7180);function d(e){return new Promise((t=>t(p(e))))}function f(e){const t=p(e);if((0,a.t)(t))throw new Error("GraphQL execution failed to complete synchronously.");return t}function p(e){arguments.length<2||(0,o.a)(!1,"graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.");const{schema:t,source:n,rootValue:r,contextValue:i,variableValues:a,operationName:d,fieldResolver:f,typeResolver:p}=e,h=(0,l.F)(t);if(h.length>0)return{errors:h};let m;try{m=(0,s.Qc)(n)}catch(e){return{errors:[e]}}const g=(0,u.Gu)(t,m);return g.length>0?{errors:g}:(0,c.ht)({schema:t,document:m,rootValue:r,contextValue:i,variableValues:a,operationName:d,fieldResolver:f,typeResolver:p})}var h=n(755),m=n(773),g=n(5946),v=n(1774),y=n(8078),b=n(3228),E=n(3526),T=n(4680),w=n(3302),C=n(7026),S=n(9230),x=n(5685),k=n(5895),N=n(9685),_=n(3830),O=n(3140),I=n(9615),D=n(9878),L=n(2806),A=n(2941),M=n(5052),R=n(4117);function F(e){return{Field(t){const n=e.getFieldDef(),r=null==n?void 0:n.deprecationReason;if(n&&null!=r){const i=e.getParentType();null!=i||(0,M.k)(!1),e.reportError(new R.__(`The field ${i.name}.${n.name} is deprecated. ${r}`,{nodes:t}))}},Argument(t){const n=e.getArgument(),r=null==n?void 0:n.deprecationReason;if(n&&null!=r){const i=e.getDirective();if(null!=i)e.reportError(new R.__(`Directive "@${i.name}" argument "${n.name}" is deprecated. ${r}`,{nodes:t}));else{const i=e.getParentType(),o=e.getFieldDef();null!=i&&null!=o||(0,M.k)(!1),e.reportError(new R.__(`Field "${i.name}.${o.name}" argument "${n.name}" is deprecated. ${r}`,{nodes:t}))}}},ObjectField(t){const n=(0,h.xC)(e.getParentInputType());if((0,h.hL)(n)){const r=n.getFields()[t.name.value],i=null==r?void 0:r.deprecationReason;null!=i&&e.reportError(new R.__(`The input field ${n.name}.${r.name} is deprecated. ${i}`,{nodes:t}))}},EnumValue(t){const n=e.getEnumValue(),r=null==n?void 0:n.deprecationReason;if(n&&null!=r){const i=(0,h.xC)(e.getInputType());null!=i||(0,M.k)(!1),e.reportError(new R.__(`The enum value "${i.name}.${n.name}" is deprecated. ${r}`,{nodes:t}))}}}}function P(e){return{Field(t){const n=(0,h.xC)(e.getType());n&&(0,y.s9)(n)&&e.reportError(new R.__(`GraphQL introspection has been disabled, but the requested query contained the field "${t.name.value}".`,{nodes:t}))}}}var j=n(2716),V=n(9299),U=n(3857),B=n(1870),$=n(5167),q=n(4875),H=n(7513),G=n(1435),z=n(591),W=n(831),K=n(9316),Q=n(9518),X=n(3447),Y=n(7114),J=n(7163),Z=n(5961),ee=n(16),te=n(3989),ne=n(9309),re=n(9168),ie=n(5673),oe=n(614),ae=n(5707),se=n(2355),le=n(7417),ue=n(4697),ce=n(6192),de=n(377),fe=n(3402),pe=n(5427),he=n(4519),me=n(4560),ge=n(5240),ve=n(5947),ye=n(5681),be=n(3721),Ee=n(2024),Te=n(4647);function we(e){const t={descriptions:!0,specifiedByUrl:!1,directiveIsRepeatable:!1,schemaDescription:!1,inputValueDeprecation:!1,...e},n=t.descriptions?"description":"",r=t.specifiedByUrl?"specifiedByURL":"",i=t.directiveIsRepeatable?"isRepeatable":"";function o(e){return t.inputValueDeprecation?e:""}return`\n query IntrospectionQuery {\n __schema {\n ${t.schemaDescription?n:""}\n queryType { name }\n mutationType { name }\n subscriptionType { name }\n types {\n ...FullType\n }\n directives {\n name\n ${n}\n ${i}\n locations\n args${o("(includeDeprecated: true)")} {\n ...InputValue\n }\n }\n }\n }\n\n fragment FullType on __Type {\n kind\n name\n ${n}\n ${r}\n fields(includeDeprecated: true) {\n name\n ${n}\n args${o("(includeDeprecated: true)")} {\n ...InputValue\n }\n type {\n ...TypeRef\n }\n isDeprecated\n deprecationReason\n }\n inputFields${o("(includeDeprecated: true)")} {\n ...InputValue\n }\n interfaces {\n ...TypeRef\n }\n enumValues(includeDeprecated: true) {\n name\n ${n}\n isDeprecated\n deprecationReason\n }\n possibleTypes {\n ...TypeRef\n }\n }\n\n fragment InputValue on __InputValue {\n name\n ${n}\n type { ...TypeRef }\n defaultValue\n ${o("isDeprecated")}\n ${o("deprecationReason")}\n }\n\n fragment TypeRef on __Type {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n ofType {\n kind\n name\n }\n }\n }\n }\n }\n }\n }\n }\n `}function Ce(e,t){if("query"===t.operation){const n=e.getQueryType();if(!n)throw new R.__("Schema does not define the required query root type.",{nodes:t});return n}if("mutation"===t.operation){const n=e.getMutationType();if(!n)throw new R.__("Schema is not configured for mutations.",{nodes:t});return n}if("subscription"===t.operation){const n=e.getSubscriptionType();if(!n)throw new R.__("Schema is not configured for subscriptions.",{nodes:t});return n}throw new R.__("Can only have query, mutation and subscription operations.",{nodes:t})}function Se(e,t){const n={specifiedByUrl:!0,directiveIsRepeatable:!0,schemaDescription:!0,inputValueDeprecation:!0,...t},r=(0,s.Qc)(we(n)),i=(0,c.p0)({schema:e,document:r});return!i.errors&&i.data||(0,M.k)(!1),i.data}var xe=n(5648),ke=n(1315),Ne=n(8240),_e=n(5284);function Oe(e,t){(0,ke.y)(e)&&(0,ke.y)(e.__schema)||(0,o.a)(!1,`Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: ${(0,xe.X)(e)}.`);const n=e.__schema,r=(0,Ne.w)(n.types,(e=>e.name),(e=>function(e){if(null!=e&&null!=e.name&&null!=e.kind)switch(e.kind){case y.zU.SCALAR:return r=e,new h.n2({name:r.name,description:r.description,specifiedByURL:r.specifiedByURL});case y.zU.OBJECT:return n=e,new h.h6({name:n.name,description:n.description,interfaces:()=>b(n),fields:()=>E(n)});case y.zU.INTERFACE:return t=e,new h.oW({name:t.name,description:t.description,interfaces:()=>b(t),fields:()=>E(t)});case y.zU.UNION:return function(e){if(!e.possibleTypes){const t=(0,xe.X)(e);throw new Error(`Introspection result missing possibleTypes: ${t}.`)}return new h.Gp({name:e.name,description:e.description,types:()=>e.possibleTypes.map(f)})}(e);case y.zU.ENUM:return function(e){if(!e.enumValues){const t=(0,xe.X)(e);throw new Error(`Introspection result missing enumValues: ${t}.`)}return new h.mR({name:e.name,description:e.description,values:(0,Ne.w)(e.enumValues,(e=>e.name),(e=>({description:e.description,deprecationReason:e.deprecationReason})))})}(e);case y.zU.INPUT_OBJECT:return function(e){if(!e.inputFields){const t=(0,xe.X)(e);throw new Error(`Introspection result missing inputFields: ${t}.`)}return new h.sR({name:e.name,description:e.description,fields:()=>w(e.inputFields)})}(e)}var t,n,r;const i=(0,xe.X)(e);throw new Error(`Invalid or incomplete introspection result. Ensure that a full introspection query is used in order to build a client schema: ${i}.`)}(e)));for(const e of[...v.HS,...y.nL])r[e.name]&&(r[e.name]=e);const i=n.queryType?f(n.queryType):null,a=n.mutationType?f(n.mutationType):null,l=n.subscriptionType?f(n.subscriptionType):null,u=n.directives?n.directives.map((function(e){if(!e.args){const t=(0,xe.X)(e);throw new Error(`Introspection result missing directive args: ${t}.`)}if(!e.locations){const t=(0,xe.X)(e);throw new Error(`Introspection result missing directive locations: ${t}.`)}return new g.NZ({name:e.name,description:e.description,isRepeatable:e.isRepeatable,locations:e.locations.slice(),args:w(e.args)})})):[];return new m.XO({description:n.description,query:i,mutation:a,subscription:l,types:Object.values(r),directives:u,assumeValid:null==t?void 0:t.assumeValid});function c(e){if(e.kind===y.zU.LIST){const t=e.ofType;if(!t)throw new Error("Decorated type deeper than introspection query.");return new h.p2(c(t))}if(e.kind===y.zU.NON_NULL){const t=e.ofType;if(!t)throw new Error("Decorated type deeper than introspection query.");const n=c(t);return new h.bM((0,h.i_)(n))}return d(e)}function d(e){const t=e.name;if(!t)throw new Error(`Unknown type reference: ${(0,xe.X)(e)}.`);const n=r[t];if(!n)throw new Error(`Invalid or incomplete schema, unknown type: ${t}. Ensure that a full introspection query is used in order to build a client schema.`);return n}function f(e){return(0,h.Z6)(d(e))}function p(e){return(0,h.k2)(d(e))}function b(e){if(null===e.interfaces&&e.kind===y.zU.INTERFACE)return[];if(!e.interfaces){const t=(0,xe.X)(e);throw new Error(`Introspection result missing interfaces: ${t}.`)}return e.interfaces.map(p)}function E(e){if(!e.fields)throw new Error(`Introspection result missing fields: ${(0,xe.X)(e)}.`);return(0,Ne.w)(e.fields,(e=>e.name),T)}function T(e){const t=c(e.type);if(!(0,h.SZ)(t)){const e=(0,xe.X)(t);throw new Error(`Introspection must provide output type for fields, but received: ${e}.`)}if(!e.args){const t=(0,xe.X)(e);throw new Error(`Introspection result missing field args: ${t}.`)}return{description:e.description,deprecationReason:e.deprecationReason,type:t,args:w(e.args)}}function w(e){return(0,Ne.w)(e,(e=>e.name),C)}function C(e){const t=c(e.type);if(!(0,h.j$)(t)){const e=(0,xe.X)(t);throw new Error(`Introspection must provide input type for arguments, but received: ${e}.`)}const n=null!=e.defaultValue?(0,_e.u)((0,s.H2)(e.defaultValue),t):void 0;return{description:e.description,type:t,defaultValue:n,deprecationReason:e.deprecationReason}}}var Ie=n(9815),De=n(9997);function Le(e,t,n){(0,m.EO)(e),null!=t&&t.kind===_.h.DOCUMENT||(0,o.a)(!1,"Must provide valid Document AST."),!0!==(null==n?void 0:n.assumeValid)&&!0!==(null==n?void 0:n.assumeValidSDL)&&(0,u.ED)(t,e);const r=e.toConfig(),i=Ae(r,t,n);return r===i?e:new m.XO(i)}function Ae(e,t,n){var r,i,o,a;const s=[],l=Object.create(null),u=[];let c;const d=[];for(const e of t.definitions)if(e.kind===_.h.SCHEMA_DEFINITION)c=e;else if(e.kind===_.h.SCHEMA_EXTENSION)d.push(e);else if((0,I.zT)(e))s.push(e);else if((0,I.D$)(e)){const t=e.name.value,n=l[t];l[t]=n?n.concat([e]):[e]}else e.kind===_.h.DIRECTIVE_DEFINITION&&u.push(e);if(0===Object.keys(l).length&&0===s.length&&0===u.length&&0===d.length&&null==c)return e;const f=Object.create(null);for(const t of e.types)f[t.name]=(p=t,(0,y.s9)(p)||(0,v.u1)(p)?p:(0,h.KA)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[n.name])&&void 0!==t?t:[];let i=n.specifiedByURL;for(const e of r){var o;i=null!==(o=Fe(e))&&void 0!==o?o:i}return new h.n2({...n,specifiedByURL:i,extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):(0,h.lp)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[n.name])&&void 0!==t?t:[];return new h.h6({...n,interfaces:()=>[...e.getInterfaces().map(T),...A(r)],fields:()=>({...(0,De.j)(n.fields,w),...N(r)}),extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):(0,h.oT)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[n.name])&&void 0!==t?t:[];return new h.oW({...n,interfaces:()=>[...e.getInterfaces().map(T),...A(r)],fields:()=>({...(0,De.j)(n.fields,w),...N(r)}),extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):(0,h.EN)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[n.name])&&void 0!==t?t:[];return new h.Gp({...n,types:()=>[...e.getTypes().map(T),...R(r)],extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):(0,h.EM)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[e.name])&&void 0!==t?t:[];return new h.mR({...n,values:{...n.values,...L(r)},extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):(0,h.hL)(p)?function(e){var t;const n=e.toConfig(),r=null!==(t=l[n.name])&&void 0!==t?t:[];return new h.sR({...n,fields:()=>({...(0,De.j)(n.fields,(e=>({...e,type:E(e.type)}))),...D(r)}),extensionASTNodes:n.extensionASTNodes.concat(r)})}(p):void(0,M.k)(!1,"Unexpected type: "+(0,xe.X)(p)));var p;for(const e of s){var m;const t=e.name.value;f[t]=null!==(m=Me[t])&&void 0!==m?m:F(e)}const b={query:e.query&&T(e.query),mutation:e.mutation&&T(e.mutation),subscription:e.subscription&&T(e.subscription),...c&&S([c]),...S(d)};return{description:null===(r=c)||void 0===r||null===(i=r.description)||void 0===i?void 0:i.value,...b,types:Object.values(f),directives:[...e.directives.map((function(e){const t=e.toConfig();return new g.NZ({...t,args:(0,De.j)(t.args,C)})})),...u.map((function(e){var t;return new g.NZ({name:e.name.value,description:null===(t=e.description)||void 0===t?void 0:t.value,locations:e.locations.map((({value:e})=>e)),isRepeatable:e.repeatable,args:O(e.arguments),astNode:e})}))],extensions:Object.create(null),astNode:null!==(o=c)&&void 0!==o?o:e.astNode,extensionASTNodes:e.extensionASTNodes.concat(d),assumeValid:null!==(a=null==n?void 0:n.assumeValid)&&void 0!==a&&a};function E(e){return(0,h.HG)(e)?new h.p2(E(e.ofType)):(0,h.zM)(e)?new h.bM(E(e.ofType)):T(e)}function T(e){return f[e.name]}function w(e){return{...e,type:E(e.type),args:e.args&&(0,De.j)(e.args,C)}}function C(e){return{...e,type:E(e.type)}}function S(e){const t={};for(const r of e){var n;const e=null!==(n=r.operationTypes)&&void 0!==n?n:[];for(const n of e)t[n.operation]=x(n.type)}return t}function x(e){var t;const n=e.name.value,r=null!==(t=Me[n])&&void 0!==t?t:f[n];if(void 0===r)throw new Error(`Unknown type: "${n}".`);return r}function k(e){return e.kind===_.h.LIST_TYPE?new h.p2(k(e.type)):e.kind===_.h.NON_NULL_TYPE?new h.bM(k(e.type)):x(e)}function N(e){const t=Object.create(null);for(const i of e){var n;const e=null!==(n=i.fields)&&void 0!==n?n:[];for(const n of e){var r;t[n.name.value]={type:k(n.type),description:null===(r=n.description)||void 0===r?void 0:r.value,args:O(n.arguments),deprecationReason:Re(n),astNode:n}}}return t}function O(e){const t=null!=e?e:[],n=Object.create(null);for(const e of t){var r;const t=k(e.type);n[e.name.value]={type:t,description:null===(r=e.description)||void 0===r?void 0:r.value,defaultValue:(0,_e.u)(e.defaultValue,t),deprecationReason:Re(e),astNode:e}}return n}function D(e){const t=Object.create(null);for(const i of e){var n;const e=null!==(n=i.fields)&&void 0!==n?n:[];for(const n of e){var r;const e=k(n.type);t[n.name.value]={type:e,description:null===(r=n.description)||void 0===r?void 0:r.value,defaultValue:(0,_e.u)(n.defaultValue,e),deprecationReason:Re(n),astNode:n}}}return t}function L(e){const t=Object.create(null);for(const i of e){var n;const e=null!==(n=i.values)&&void 0!==n?n:[];for(const n of e){var r;t[n.name.value]={description:null===(r=n.description)||void 0===r?void 0:r.value,deprecationReason:Re(n),astNode:n}}}return t}function A(e){return e.flatMap((e=>{var t,n;return null!==(t=null===(n=e.interfaces)||void 0===n?void 0:n.map(x))&&void 0!==t?t:[]}))}function R(e){return e.flatMap((e=>{var t,n;return null!==(t=null===(n=e.types)||void 0===n?void 0:n.map(x))&&void 0!==t?t:[]}))}function F(e){var t;const n=e.name.value,r=null!==(t=l[n])&&void 0!==t?t:[];switch(e.kind){case _.h.OBJECT_TYPE_DEFINITION:{var i;const t=[e,...r];return new h.h6({name:n,description:null===(i=e.description)||void 0===i?void 0:i.value,interfaces:()=>A(t),fields:()=>N(t),astNode:e,extensionASTNodes:r})}case _.h.INTERFACE_TYPE_DEFINITION:{var o;const t=[e,...r];return new h.oW({name:n,description:null===(o=e.description)||void 0===o?void 0:o.value,interfaces:()=>A(t),fields:()=>N(t),astNode:e,extensionASTNodes:r})}case _.h.ENUM_TYPE_DEFINITION:{var a;const t=[e,...r];return new h.mR({name:n,description:null===(a=e.description)||void 0===a?void 0:a.value,values:L(t),astNode:e,extensionASTNodes:r})}case _.h.UNION_TYPE_DEFINITION:{var s;const t=[e,...r];return new h.Gp({name:n,description:null===(s=e.description)||void 0===s?void 0:s.value,types:()=>R(t),astNode:e,extensionASTNodes:r})}case _.h.SCALAR_TYPE_DEFINITION:var u;return new h.n2({name:n,description:null===(u=e.description)||void 0===u?void 0:u.value,specifiedByURL:Fe(e),astNode:e,extensionASTNodes:r});case _.h.INPUT_OBJECT_TYPE_DEFINITION:{var c;const t=[e,...r];return new h.sR({name:n,description:null===(c=e.description)||void 0===c?void 0:c.value,fields:()=>D(t),astNode:e,extensionASTNodes:r})}}}}const Me=(0,Ie.P)([...v.HS,...y.nL],(e=>e.name));function Re(e){const t=(0,L.zu)(g.fg,e);return null==t?void 0:t.reason}function Fe(e){const t=(0,L.zu)(g.df,e);return null==t?void 0:t.url}function Pe(e,t){null!=e&&e.kind===_.h.DOCUMENT||(0,o.a)(!1,"Must provide valid Document AST."),!0!==(null==t?void 0:t.assumeValid)&&!0!==(null==t?void 0:t.assumeValidSDL)&&(0,u.zo)(e);const n=Ae({description:void 0,types:[],directives:[],extensions:Object.create(null),extensionASTNodes:[],assumeValid:!1},e,t);if(null==n.astNode)for(const e of n.types)switch(e.name){case"Query":n.query=e;break;case"Mutation":n.mutation=e;break;case"Subscription":n.subscription=e}const r=[...n.directives,...g.V4.filter((e=>n.directives.every((t=>t.name!==e.name))))];return new m.XO({...n,directives:r})}function je(e,t){return Pe((0,s.Qc)(e,{noLocation:null==t?void 0:t.noLocation,allowLegacyFragmentVariables:null==t?void 0:t.allowLegacyFragmentVariables}),{assumeValidSDL:null==t?void 0:t.assumeValidSDL,assumeValid:null==t?void 0:t.assumeValid})}var Ve=n(6625);function Ue(e){const t=e.toConfig(),n=(0,Ne.w)($e(t.types),(e=>e.name),(function(e){if((0,h.KA)(e)||(0,y.s9)(e))return e;if((0,h.lp)(e)){const t=e.toConfig();return new h.h6({...t,interfaces:()=>l(t.interfaces),fields:()=>s(t.fields)})}if((0,h.oT)(e)){const t=e.toConfig();return new h.oW({...t,interfaces:()=>l(t.interfaces),fields:()=>s(t.fields)})}if((0,h.EN)(e)){const t=e.toConfig();return new h.Gp({...t,types:()=>l(t.types)})}if((0,h.EM)(e)){const t=e.toConfig();return new h.mR({...t,values:Be(t.values,(e=>e))})}if((0,h.hL)(e)){const t=e.toConfig();return new h.sR({...t,fields:()=>Be(t.fields,(e=>({...e,type:r(e.type)})))})}(0,M.k)(!1,"Unexpected type: "+(0,xe.X)(e))}));return new m.XO({...t,types:Object.values(n),directives:$e(t.directives).map((function(e){const t=e.toConfig();return new g.NZ({...t,locations:qe(t.locations,(e=>e)),args:a(t.args)})})),query:o(t.query),mutation:o(t.mutation),subscription:o(t.subscription)});function r(e){return(0,h.HG)(e)?new h.p2(r(e.ofType)):(0,h.zM)(e)?new h.bM(r(e.ofType)):i(e)}function i(e){return n[e.name]}function o(e){return e&&i(e)}function a(e){return Be(e,(e=>({...e,type:r(e.type)})))}function s(e){return Be(e,(e=>({...e,type:r(e.type),args:e.args&&a(e.args)})))}function l(e){return $e(e).map(i)}}function Be(e,t){const n=Object.create(null);for(const r of Object.keys(e).sort(Ve.K))n[r]=t(e[r]);return n}function $e(e){return qe(e,(e=>e.name))}function qe(e,t){return e.slice().sort(((e,n)=>{const r=t(e),i=t(n);return(0,Ve.K)(r,i)}))}var He=n(6303),Ge=n(3190);function ze(e){return Qe(e,(e=>!(0,g.xg)(e)),Ke)}function We(e){return Qe(e,g.xg,y.s9)}function Ke(e){return!(0,v.u1)(e)&&!(0,y.s9)(e)}function Qe(e,t,n){const r=e.getDirectives().filter(t),i=Object.values(e.getTypeMap()).filter(n);return[Xe(e),...r.map((e=>function(e){return it(e)+"directive @"+e.name+tt(e.args)+(e.isRepeatable?" repeatable":"")+" on "+e.locations.join(" | ")}(e))),...i.map((e=>Ye(e)))].filter(Boolean).join("\n\n")}function Xe(e){if(null==e.description&&function(e){const t=e.getQueryType();if(t&&"Query"!==t.name)return!1;const n=e.getMutationType();if(n&&"Mutation"!==n.name)return!1;const r=e.getSubscriptionType();return!r||"Subscription"===r.name}(e))return;const t=[],n=e.getQueryType();n&&t.push(` query: ${n.name}`);const r=e.getMutationType();r&&t.push(` mutation: ${r.name}`);const i=e.getSubscriptionType();return i&&t.push(` subscription: ${i.name}`),it(e)+`schema {\n${t.join("\n")}\n}`}function Ye(e){return(0,h.KA)(e)?function(e){return it(e)+`scalar ${e.name}`+(null==(t=e).specifiedByURL?"":` @specifiedBy(url: ${(0,k.S)({kind:_.h.STRING,value:t.specifiedByURL})})`);var t}(e):(0,h.lp)(e)?function(e){return it(e)+`type ${e.name}`+Je(e)+Ze(e)}(e):(0,h.oT)(e)?function(e){return it(e)+`interface ${e.name}`+Je(e)+Ze(e)}(e):(0,h.EN)(e)?function(e){const t=e.getTypes(),n=t.length?" = "+t.join(" | "):"";return it(e)+"union "+e.name+n}(e):(0,h.EM)(e)?function(e){const t=e.getValues().map(((e,t)=>it(e," ",!t)+" "+e.name+rt(e.deprecationReason)));return it(e)+`enum ${e.name}`+et(t)}(e):(0,h.hL)(e)?function(e){const t=Object.values(e.getFields()).map(((e,t)=>it(e," ",!t)+" "+nt(e)));return it(e)+`input ${e.name}`+et(t)}(e):void(0,M.k)(!1,"Unexpected type: "+(0,xe.X)(e))}function Je(e){const t=e.getInterfaces();return t.length?" implements "+t.map((e=>e.name)).join(" & "):""}function Ze(e){return et(Object.values(e.getFields()).map(((e,t)=>it(e," ",!t)+" "+e.name+tt(e.args," ")+": "+String(e.type)+rt(e.deprecationReason))))}function et(e){return 0!==e.length?" {\n"+e.join("\n")+"\n}":""}function tt(e,t=""){return 0===e.length?"":e.every((e=>!e.description))?"("+e.map(nt).join(", ")+")":"(\n"+e.map(((e,n)=>it(e," "+t,!n)+" "+t+nt(e))).join("\n")+"\n"+t+")"}function nt(e){const t=(0,Ge.J)(e.defaultValue,e.type);let n=e.name+": "+String(e.type);return t&&(n+=` = ${(0,k.S)(t)}`),n+rt(e.deprecationReason)}function rt(e){return null==e?"":e!==g.SY?` @deprecated(reason: ${(0,k.S)({kind:_.h.STRING,value:e})})`:" @deprecated"}function it(e,t="",n=!0){const{description:r}=e;return null==r?"":(t&&!n?"\n"+t:t)+(0,k.S)({kind:_.h.STRING,value:r,block:(0,He.MZ)(r)}).replace(/\n/g,"\n"+t)+"\n"}function ot(e){const t=[];for(const n of e)t.push(...n.definitions);return{kind:_.h.DOCUMENT,definitions:t}}function at(e){const t=[],n=Object.create(null);for(const r of e.definitions)switch(r.kind){case _.h.OPERATION_DEFINITION:t.push(r);break;case _.h.FRAGMENT_DEFINITION:n[r.name.value]=lt(r.selectionSet)}const r=Object.create(null);for(const i of t){const t=new Set;for(const e of lt(i.selectionSet))st(t,n,e);r[i.name?i.name.value:""]={kind:_.h.DOCUMENT,definitions:e.definitions.filter((e=>e===i||e.kind===_.h.FRAGMENT_DEFINITION&&t.has(e.name.value)))}}return r}function st(e,t,n){if(!e.has(n)){e.add(n);const r=t[n];if(void 0!==r)for(const n of r)st(e,t,n)}}function lt(e){const t=[];return(0,N.Vn)(e,{FragmentSpread(e){t.push(e.name.value)}}),t}function ut(e){const t=(0,T.T)(e)?e:new T.H(e),n=t.body,r=new S.h(t);let i="",o=!1;for(;r.advance().kind!==x.T.EOF;){const e=r.token,t=e.kind,a=!(0,S.u)(e.kind);o&&(a||e.kind===x.T.SPREAD)&&(i+=" ");const s=n.slice(e.start,e.end);t===x.T.BLOCK_STRING?i+=(0,He.LZ)(e.value,{minimize:!0}):i+=s,o=a}return i}function ct(e){const t=dt(e);if(t)throw t;return e}function dt(e){if("string"==typeof e||(0,o.a)(!1,"Expected name to be a string."),e.startsWith("__"))return new R.__(`Name "${e}" must not begin with "__", which is reserved by GraphQL introspection.`);try{(0,b.i)(e)}catch(e){return e}}var ft=n(4034);let pt,ht;function mt(e,t){return vt(e,t).filter((e=>e.type in pt))}function gt(e,t){return vt(e,t).filter((e=>e.type in ht))}function vt(e,t){return[...bt(e,t),...yt(e,t)]}function yt(e,t){const n=[],r=It(e.getDirectives(),t.getDirectives());for(const e of r.removed)n.push({type:pt.DIRECTIVE_REMOVED,description:`${e.name} was removed.`});for(const[e,t]of r.persisted){const r=It(e.args,t.args);for(const t of r.added)(0,h.dK)(t)&&n.push({type:pt.REQUIRED_DIRECTIVE_ARG_ADDED,description:`A required arg ${t.name} on directive ${e.name} was added.`});for(const t of r.removed)n.push({type:pt.DIRECTIVE_ARG_REMOVED,description:`${t.name} was removed from ${e.name}.`});e.isRepeatable&&!t.isRepeatable&&n.push({type:pt.DIRECTIVE_REPEATABLE_REMOVED,description:`Repeatable flag was removed from ${e.name}.`});for(const r of e.locations)t.locations.includes(r)||n.push({type:pt.DIRECTIVE_LOCATION_REMOVED,description:`${r} was removed from ${e.name}.`})}return n}function bt(e,t){const n=[],r=It(Object.values(e.getTypeMap()),Object.values(t.getTypeMap()));for(const e of r.removed)n.push({type:pt.TYPE_REMOVED,description:(0,v.u1)(e)?`Standard scalar ${e.name} was removed because it is not referenced anymore.`:`${e.name} was removed.`});for(const[e,t]of r.persisted)(0,h.EM)(e)&&(0,h.EM)(t)?n.push(...wt(e,t)):(0,h.EN)(e)&&(0,h.EN)(t)?n.push(...Tt(e,t)):(0,h.hL)(e)&&(0,h.hL)(t)?n.push(...Et(e,t)):(0,h.lp)(e)&&(0,h.lp)(t)||(0,h.oT)(e)&&(0,h.oT)(t)?n.push(...St(e,t),...Ct(e,t)):e.constructor!==t.constructor&&n.push({type:pt.TYPE_CHANGED_KIND,description:`${e.name} changed from ${_t(e)} to ${_t(t)}.`});return n}function Et(e,t){const n=[],r=It(Object.values(e.getFields()),Object.values(t.getFields()));for(const t of r.added)(0,h.Wd)(t)?n.push({type:pt.REQUIRED_INPUT_FIELD_ADDED,description:`A required field ${t.name} on input type ${e.name} was added.`}):n.push({type:ht.OPTIONAL_INPUT_FIELD_ADDED,description:`An optional field ${t.name} on input type ${e.name} was added.`});for(const t of r.removed)n.push({type:pt.FIELD_REMOVED,description:`${e.name}.${t.name} was removed.`});for(const[t,i]of r.persisted)Nt(t.type,i.type)||n.push({type:pt.FIELD_CHANGED_KIND,description:`${e.name}.${t.name} changed type from ${String(t.type)} to ${String(i.type)}.`});return n}function Tt(e,t){const n=[],r=It(e.getTypes(),t.getTypes());for(const t of r.added)n.push({type:ht.TYPE_ADDED_TO_UNION,description:`${t.name} was added to union type ${e.name}.`});for(const t of r.removed)n.push({type:pt.TYPE_REMOVED_FROM_UNION,description:`${t.name} was removed from union type ${e.name}.`});return n}function wt(e,t){const n=[],r=It(e.getValues(),t.getValues());for(const t of r.added)n.push({type:ht.VALUE_ADDED_TO_ENUM,description:`${t.name} was added to enum type ${e.name}.`});for(const t of r.removed)n.push({type:pt.VALUE_REMOVED_FROM_ENUM,description:`${t.name} was removed from enum type ${e.name}.`});return n}function Ct(e,t){const n=[],r=It(e.getInterfaces(),t.getInterfaces());for(const t of r.added)n.push({type:ht.IMPLEMENTED_INTERFACE_ADDED,description:`${t.name} added to interfaces implemented by ${e.name}.`});for(const t of r.removed)n.push({type:pt.IMPLEMENTED_INTERFACE_REMOVED,description:`${e.name} no longer implements interface ${t.name}.`});return n}function St(e,t){const n=[],r=It(Object.values(e.getFields()),Object.values(t.getFields()));for(const t of r.removed)n.push({type:pt.FIELD_REMOVED,description:`${e.name}.${t.name} was removed.`});for(const[t,i]of r.persisted)n.push(...xt(e,t,i)),kt(t.type,i.type)||n.push({type:pt.FIELD_CHANGED_KIND,description:`${e.name}.${t.name} changed type from ${String(t.type)} to ${String(i.type)}.`});return n}function xt(e,t,n){const r=[],i=It(t.args,n.args);for(const n of i.removed)r.push({type:pt.ARG_REMOVED,description:`${e.name}.${t.name} arg ${n.name} was removed.`});for(const[n,o]of i.persisted)if(Nt(n.type,o.type)){if(void 0!==n.defaultValue)if(void 0===o.defaultValue)r.push({type:ht.ARG_DEFAULT_VALUE_CHANGE,description:`${e.name}.${t.name} arg ${n.name} defaultValue was removed.`});else{const i=Ot(n.defaultValue,n.type),a=Ot(o.defaultValue,o.type);i!==a&&r.push({type:ht.ARG_DEFAULT_VALUE_CHANGE,description:`${e.name}.${t.name} arg ${n.name} has changed defaultValue from ${i} to ${a}.`})}}else r.push({type:pt.ARG_CHANGED_KIND,description:`${e.name}.${t.name} arg ${n.name} has changed type from ${String(n.type)} to ${String(o.type)}.`});for(const n of i.added)(0,h.dK)(n)?r.push({type:pt.REQUIRED_ARG_ADDED,description:`A required arg ${n.name} on ${e.name}.${t.name} was added.`}):r.push({type:ht.OPTIONAL_ARG_ADDED,description:`An optional arg ${n.name} on ${e.name}.${t.name} was added.`});return r}function kt(e,t){return(0,h.HG)(e)?(0,h.HG)(t)&&kt(e.ofType,t.ofType)||(0,h.zM)(t)&&kt(e,t.ofType):(0,h.zM)(e)?(0,h.zM)(t)&&kt(e.ofType,t.ofType):(0,h.Zs)(t)&&e.name===t.name||(0,h.zM)(t)&&kt(e,t.ofType)}function Nt(e,t){return(0,h.HG)(e)?(0,h.HG)(t)&&Nt(e.ofType,t.ofType):(0,h.zM)(e)?(0,h.zM)(t)&&Nt(e.ofType,t.ofType)||!(0,h.zM)(t)&&Nt(e.ofType,t):(0,h.Zs)(t)&&e.name===t.name}function _t(e){return(0,h.KA)(e)?"a Scalar type":(0,h.lp)(e)?"an Object type":(0,h.oT)(e)?"an Interface type":(0,h.EN)(e)?"a Union type":(0,h.EM)(e)?"an Enum type":(0,h.hL)(e)?"an Input type":void(0,M.k)(!1,"Unexpected type: "+(0,xe.X)(e))}function Ot(e,t){const n=(0,Ge.J)(e,t);return null!=n||(0,M.k)(!1),(0,k.S)((0,ft.n)(n))}function It(e,t){const n=[],r=[],i=[],o=(0,Ie.P)(e,(({name:e})=>e)),a=(0,Ie.P)(t,(({name:e})=>e));for(const t of e){const e=a[t.name];void 0===e?r.push(t):i.push([t,e])}for(const e of t)void 0===o[e.name]&&n.push(e);return{added:n,persisted:i,removed:r}}!function(e){e.TYPE_REMOVED="TYPE_REMOVED",e.TYPE_CHANGED_KIND="TYPE_CHANGED_KIND",e.TYPE_REMOVED_FROM_UNION="TYPE_REMOVED_FROM_UNION",e.VALUE_REMOVED_FROM_ENUM="VALUE_REMOVED_FROM_ENUM",e.REQUIRED_INPUT_FIELD_ADDED="REQUIRED_INPUT_FIELD_ADDED",e.IMPLEMENTED_INTERFACE_REMOVED="IMPLEMENTED_INTERFACE_REMOVED",e.FIELD_REMOVED="FIELD_REMOVED",e.FIELD_CHANGED_KIND="FIELD_CHANGED_KIND",e.REQUIRED_ARG_ADDED="REQUIRED_ARG_ADDED",e.ARG_REMOVED="ARG_REMOVED",e.ARG_CHANGED_KIND="ARG_CHANGED_KIND",e.DIRECTIVE_REMOVED="DIRECTIVE_REMOVED",e.DIRECTIVE_ARG_REMOVED="DIRECTIVE_ARG_REMOVED",e.REQUIRED_DIRECTIVE_ARG_ADDED="REQUIRED_DIRECTIVE_ARG_ADDED",e.DIRECTIVE_REPEATABLE_REMOVED="DIRECTIVE_REPEATABLE_REMOVED",e.DIRECTIVE_LOCATION_REMOVED="DIRECTIVE_LOCATION_REMOVED"}(pt||(pt={})),function(e){e.VALUE_ADDED_TO_ENUM="VALUE_ADDED_TO_ENUM",e.TYPE_ADDED_TO_UNION="TYPE_ADDED_TO_UNION",e.OPTIONAL_INPUT_FIELD_ADDED="OPTIONAL_INPUT_FIELD_ADDED",e.OPTIONAL_ARG_ADDED="OPTIONAL_ARG_ADDED",e.IMPLEMENTED_INTERFACE_ADDED="IMPLEMENTED_INTERFACE_ADDED",e.ARG_DEFAULT_VALUE_CHANGE="ARG_DEFAULT_VALUE_CHANGE"}(ht||(ht={}));var Dt=n(9458),Lt=n(5998),At=n(9426),Mt=n(1409),Rt=n(5925),Ft=n(2984)},9878:function(e,t,n){"use strict";function r(e,t,n){return{prev:e,key:t,typename:n}}function i(e){const t=[];let n=e;for(;n;)t.push(n.key),n=n.prev;return t.reverse()}n.d(t,{N:function(){return i},Q:function(){return r}})},1172:function(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw new Error(t)}n.d(t,{a:function(){return r}})},8063:function(e,t,n){"use strict";n.d(t,{l:function(){return i}});const r=5;function i(e,t){const[n,i]=t?[e,t]:[void 0,e];let o=" Did you mean ";n&&(o+=n+" ");const a=i.map((e=>`"${e}"`));switch(a.length){case 0:return"";case 1:return o+a[0]+"?";case 2:return o+a[0]+" or "+a[1]+"?"}const s=a.slice(0,r),l=s.pop();return o+s.join(", ")+", or "+l+"?"}},5839:function(e,t,n){"use strict";function r(e,t){const n=new Map;for(const r of e){const e=t(r),i=n.get(e);void 0===i?n.set(e,[r]):i.push(r)}return n}n.d(t,{v:function(){return r}})},5648:function(e,t,n){"use strict";n.d(t,{X:function(){return o}});const r=10,i=2;function o(e){return a(e,[])}function a(e,t){switch(typeof e){case"string":return JSON.stringify(e);case"function":return e.name?`[function ${e.name}]`:"[function]";case"object":return function(e,t){if(null===e)return"null";if(t.includes(e))return"[Circular]";const n=[...t,e];if(function(e){return"function"==typeof e.toJSON}(e)){const t=e.toJSON();if(t!==e)return"string"==typeof t?t:a(t,n)}else if(Array.isArray(e))return function(e,t){if(0===e.length)return"[]";if(t.length>i)return"[Array]";const n=Math.min(r,e.length),o=e.length-n,s=[];for(let r=0;r1&&s.push(`... ${o} more items`),"["+s.join(", ")+"]"}(e,n);return function(e,t){const n=Object.entries(e);if(0===n.length)return"{}";if(t.length>i)return"["+function(e){const t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){const t=e.constructor.name;if("string"==typeof t&&""!==t)return t}return t}(e)+"]";const r=n.map((([e,n])=>e+": "+a(n,t)));return"{ "+r.join(", ")+" }"}(e,n)}(e,t);default:return String(e)}}},1513:function(e,t,n){"use strict";n.d(t,{n:function(){return r}});const r=function(e,t){return e instanceof t}},5052:function(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw new Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{k:function(){return r}})},2910:function(e,t,n){"use strict";function r(e){return"object"==typeof e&&"function"==typeof(null==e?void 0:e[Symbol.iterator])}n.d(t,{i:function(){return r}})},1315:function(e,t,n){"use strict";function r(e){return"object"==typeof e&&null!==e}n.d(t,{y:function(){return r}})},1864:function(e,t,n){"use strict";function r(e){return"function"==typeof(null==e?void 0:e.then)}n.d(t,{t:function(){return r}})},9815:function(e,t,n){"use strict";function r(e,t){const n=Object.create(null);for(const r of e)n[t(r)]=r;return n}n.d(t,{P:function(){return r}})},8240:function(e,t,n){"use strict";function r(e,t,n){const r=Object.create(null);for(const i of e)r[t(i)]=n(i);return r}n.d(t,{w:function(){return r}})},9997:function(e,t,n){"use strict";function r(e,t){const n=Object.create(null);for(const r of Object.keys(e))n[r]=t(e[r],r);return n}n.d(t,{j:function(){return r}})},6625:function(e,t,n){"use strict";function r(e,t){let n=0,r=0;for(;n0);let u=0;do{++r,u=10*u+s-i,s=t.charCodeAt(r)}while(a(s)&&u>0);if(lu)return 1}else{if(os)return 1;++n,++r}}return e.length-t.length}n.d(t,{K:function(){return r}});const i=48,o=57;function a(e){return!isNaN(e)&&i<=e&&e<=o}},4987:function(e,t,n){"use strict";function r(e){return e.map((e=>"number"==typeof e?"["+e.toString()+"]":"."+e)).join("")}n.d(t,{F:function(){return r}})},3492:function(e,t,n){"use strict";n.d(t,{D:function(){return i}});var r=n(6625);function i(e,t){const n=Object.create(null),i=new o(e),a=Math.floor(.4*e.length)+1;for(const e of t){const t=i.measure(e,a);void 0!==t&&(n[e]=t)}return Object.keys(n).sort(((e,t)=>{const i=n[e]-n[t];return 0!==i?i:(0,r.K)(e,t)}))}class o{constructor(e){this._input=e,this._inputLowerCase=e.toLowerCase(),this._inputArray=a(this._inputLowerCase),this._rows=[new Array(e.length+1).fill(0),new Array(e.length+1).fill(0),new Array(e.length+1).fill(0)]}measure(e,t){if(this._input===e)return 0;const n=e.toLowerCase();if(this._inputLowerCase===n)return 1;let r=a(n),i=this._inputArray;if(r.lengtht)return;const l=this._rows;for(let e=0;e<=s;e++)l[0][e]=e;for(let e=1;e<=o;e++){const n=l[(e-1)%3],o=l[e%3];let a=o[0]=e;for(let t=1;t<=s;t++){const s=r[e-1]===i[t-1]?0:1;let u=Math.min(n[t]+1,o[t-1]+1,n[t-1]+s);if(e>1&&t>1&&r[e-1]===i[t-2]&&r[e-2]===i[t-1]){const n=l[(e-2)%3][t-2];u=Math.min(u,n+1)}ut)return}const u=l[o%3][s];return u<=t?u:void 0}}function a(e){const t=e.length,n=new Array(t);for(let r=0;r0===t?e:e.slice(n))).slice(null!==(t=r)&&void 0!==t?t:0,i+1)}function o(e){let t=0;for(;t1&&i.slice(1).every((e=>0===e.length||(0,r.FD)(e.charCodeAt(0)))),s=n.endsWith('\\"""'),l=e.endsWith('"')&&!s,u=e.endsWith("\\"),c=l||u,d=!(null!=t&&t.minimize)&&(!o||e.length>70||c||a||s);let f="";const p=o&&(0,r.FD)(e.charCodeAt(0));return(d&&!p||a)&&(f+="\n"),f+=n,(d||c)&&(f+="\n"),'"""'+f+'"""'}},1117:function(e,t,n){"use strict";function r(e){return 9===e||32===e}function i(e){return e>=48&&e<=57}function o(e){return e>=97&&e<=122||e>=65&&e<=90}function a(e){return o(e)||95===e}function s(e){return o(e)||i(e)||95===e}n.d(t,{FD:function(){return r},HQ:function(){return s},LQ:function(){return a},X1:function(){return i}})},3140:function(e,t,n){"use strict";let r;n.d(t,{B:function(){return r}}),function(e){e.QUERY="QUERY",e.MUTATION="MUTATION",e.SUBSCRIPTION="SUBSCRIPTION",e.FIELD="FIELD",e.FRAGMENT_DEFINITION="FRAGMENT_DEFINITION",e.FRAGMENT_SPREAD="FRAGMENT_SPREAD",e.INLINE_FRAGMENT="INLINE_FRAGMENT",e.VARIABLE_DEFINITION="VARIABLE_DEFINITION",e.SCHEMA="SCHEMA",e.SCALAR="SCALAR",e.OBJECT="OBJECT",e.FIELD_DEFINITION="FIELD_DEFINITION",e.ARGUMENT_DEFINITION="ARGUMENT_DEFINITION",e.INTERFACE="INTERFACE",e.UNION="UNION",e.ENUM="ENUM",e.ENUM_VALUE="ENUM_VALUE",e.INPUT_OBJECT="INPUT_OBJECT",e.INPUT_FIELD_DEFINITION="INPUT_FIELD_DEFINITION"}(r||(r={}))},3830:function(e,t,n){"use strict";let r;n.d(t,{h:function(){return r}}),function(e){e.NAME="Name",e.DOCUMENT="Document",e.OPERATION_DEFINITION="OperationDefinition",e.VARIABLE_DEFINITION="VariableDefinition",e.SELECTION_SET="SelectionSet",e.FIELD="Field",e.ARGUMENT="Argument",e.FRAGMENT_SPREAD="FragmentSpread",e.INLINE_FRAGMENT="InlineFragment",e.FRAGMENT_DEFINITION="FragmentDefinition",e.VARIABLE="Variable",e.INT="IntValue",e.FLOAT="FloatValue",e.STRING="StringValue",e.BOOLEAN="BooleanValue",e.NULL="NullValue",e.ENUM="EnumValue",e.LIST="ListValue",e.OBJECT="ObjectValue",e.OBJECT_FIELD="ObjectField",e.DIRECTIVE="Directive",e.NAMED_TYPE="NamedType",e.LIST_TYPE="ListType",e.NON_NULL_TYPE="NonNullType",e.SCHEMA_DEFINITION="SchemaDefinition",e.OPERATION_TYPE_DEFINITION="OperationTypeDefinition",e.SCALAR_TYPE_DEFINITION="ScalarTypeDefinition",e.OBJECT_TYPE_DEFINITION="ObjectTypeDefinition",e.FIELD_DEFINITION="FieldDefinition",e.INPUT_VALUE_DEFINITION="InputValueDefinition",e.INTERFACE_TYPE_DEFINITION="InterfaceTypeDefinition",e.UNION_TYPE_DEFINITION="UnionTypeDefinition",e.ENUM_TYPE_DEFINITION="EnumTypeDefinition",e.ENUM_VALUE_DEFINITION="EnumValueDefinition",e.INPUT_OBJECT_TYPE_DEFINITION="InputObjectTypeDefinition",e.DIRECTIVE_DEFINITION="DirectiveDefinition",e.SCHEMA_EXTENSION="SchemaExtension",e.SCALAR_TYPE_EXTENSION="ScalarTypeExtension",e.OBJECT_TYPE_EXTENSION="ObjectTypeExtension",e.INTERFACE_TYPE_EXTENSION="InterfaceTypeExtension",e.UNION_TYPE_EXTENSION="UnionTypeExtension",e.ENUM_TYPE_EXTENSION="EnumTypeExtension",e.INPUT_OBJECT_TYPE_EXTENSION="InputObjectTypeExtension"}(r||(r={}))},9230:function(e,t,n){"use strict";n.d(t,{h:function(){return l},u:function(){return u}});var r=n(2024),i=n(3526),o=n(6303),a=n(1117),s=n(5685);class l{constructor(e){const t=new i.WU(s.T.SOF,0,0,0,0);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}get[Symbol.toStringTag](){return"Lexer"}advance(){return this.lastToken=this.token,this.token=this.lookahead()}lookahead(){let e=this.token;if(e.kind!==s.T.EOF)do{if(e.next)e=e.next;else{const t=g(this,e.end);e.next=t,t.prev=e,e=t}}while(e.kind===s.T.COMMENT);return e}}function u(e){return e===s.T.BANG||e===s.T.DOLLAR||e===s.T.AMP||e===s.T.PAREN_L||e===s.T.PAREN_R||e===s.T.SPREAD||e===s.T.COLON||e===s.T.EQUALS||e===s.T.AT||e===s.T.BRACKET_L||e===s.T.BRACKET_R||e===s.T.BRACE_L||e===s.T.PIPE||e===s.T.BRACE_R}function c(e){return e>=0&&e<=55295||e>=57344&&e<=1114111}function d(e,t){return f(e.charCodeAt(t))&&p(e.charCodeAt(t+1))}function f(e){return e>=55296&&e<=56319}function p(e){return e>=56320&&e<=57343}function h(e,t){const n=e.source.body.codePointAt(t);if(void 0===n)return s.T.EOF;if(n>=32&&n<=126){const e=String.fromCodePoint(n);return'"'===e?"'\"'":`"${e}"`}return"U+"+n.toString(16).toUpperCase().padStart(4,"0")}function m(e,t,n,r,o){const a=e.line,s=1+n-e.lineStart;return new i.WU(t,n,r,a,s,o)}function g(e,t){const n=e.source.body,i=n.length;let o=t;for(;o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function x(e,t){const n=e.source.body;switch(n.charCodeAt(t+1)){case 34:return{value:'"',size:2};case 92:return{value:"\\",size:2};case 47:return{value:"/",size:2};case 98:return{value:"\b",size:2};case 102:return{value:"\f",size:2};case 110:return{value:"\n",size:2};case 114:return{value:"\r",size:2};case 116:return{value:"\t",size:2}}throw(0,r.h)(e.source,t,`Invalid character escape sequence: "${n.slice(t,t+2)}".`)}function k(e,t){const n=e.source.body,i=n.length;let a=e.lineStart,l=t+3,u=l,f="";const p=[];for(;l=t)break;n=a.index+a[0].length,o+=1}return{line:o,column:t+1-n}}},953:function(e,t,n){"use strict";n.d(t,{H2:function(){return d},Qc:function(){return c},gZ:function(){return p},tl:function(){return f}});var r=n(2024),i=n(3526),o=n(3140),a=n(3830),s=n(9230),l=n(4680),u=n(5685);function c(e,t){return new h(e,t).parseDocument()}function d(e,t){const n=new h(e,t);n.expectToken(u.T.SOF);const r=n.parseValueLiteral(!1);return n.expectToken(u.T.EOF),r}function f(e,t){const n=new h(e,t);n.expectToken(u.T.SOF);const r=n.parseConstValueLiteral();return n.expectToken(u.T.EOF),r}function p(e,t){const n=new h(e,t);n.expectToken(u.T.SOF);const r=n.parseTypeReference();return n.expectToken(u.T.EOF),r}class h{constructor(e,t){const n=(0,l.T)(e)?e:new l.H(e);this._lexer=new s.h(n),this._options=t}parseName(){const e=this.expectToken(u.T.NAME);return this.node(e,{kind:a.h.NAME,value:e.value})}parseDocument(){return this.node(this._lexer.token,{kind:a.h.DOCUMENT,definitions:this.many(u.T.SOF,this.parseDefinition,u.T.EOF)})}parseDefinition(){if(this.peek(u.T.BRACE_L))return this.parseOperationDefinition();const e=this.peekDescription(),t=e?this._lexer.lookahead():this._lexer.token;if(t.kind===u.T.NAME){switch(t.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}if(e)throw(0,r.h)(this._lexer.source,this._lexer.token.start,"Unexpected description, descriptions are supported only on type definitions.");switch(t.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"extend":return this.parseTypeSystemExtension()}}throw this.unexpected(t)}parseOperationDefinition(){const e=this._lexer.token;if(this.peek(u.T.BRACE_L))return this.node(e,{kind:a.h.OPERATION_DEFINITION,operation:i.ku.QUERY,name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet()});const t=this.parseOperationType();let n;return this.peek(u.T.NAME)&&(n=this.parseName()),this.node(e,{kind:a.h.OPERATION_DEFINITION,operation:t,name:n,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet()})}parseOperationType(){const e=this.expectToken(u.T.NAME);switch(e.value){case"query":return i.ku.QUERY;case"mutation":return i.ku.MUTATION;case"subscription":return i.ku.SUBSCRIPTION}throw this.unexpected(e)}parseVariableDefinitions(){return this.optionalMany(u.T.PAREN_L,this.parseVariableDefinition,u.T.PAREN_R)}parseVariableDefinition(){return this.node(this._lexer.token,{kind:a.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(u.T.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(u.T.EQUALS)?this.parseConstValueLiteral():void 0,directives:this.parseConstDirectives()})}parseVariable(){const e=this._lexer.token;return this.expectToken(u.T.DOLLAR),this.node(e,{kind:a.h.VARIABLE,name:this.parseName()})}parseSelectionSet(){return this.node(this._lexer.token,{kind:a.h.SELECTION_SET,selections:this.many(u.T.BRACE_L,this.parseSelection,u.T.BRACE_R)})}parseSelection(){return this.peek(u.T.SPREAD)?this.parseFragment():this.parseField()}parseField(){const e=this._lexer.token,t=this.parseName();let n,r;return this.expectOptionalToken(u.T.COLON)?(n=t,r=this.parseName()):r=t,this.node(e,{kind:a.h.FIELD,alias:n,name:r,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(u.T.BRACE_L)?this.parseSelectionSet():void 0})}parseArguments(e){const t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(u.T.PAREN_L,t,u.T.PAREN_R)}parseArgument(e=!1){const t=this._lexer.token,n=this.parseName();return this.expectToken(u.T.COLON),this.node(t,{kind:a.h.ARGUMENT,name:n,value:this.parseValueLiteral(e)})}parseConstArgument(){return this.parseArgument(!0)}parseFragment(){const e=this._lexer.token;this.expectToken(u.T.SPREAD);const t=this.expectOptionalKeyword("on");return!t&&this.peek(u.T.NAME)?this.node(e,{kind:a.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1)}):this.node(e,{kind:a.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet()})}parseFragmentDefinition(){var e;const t=this._lexer.token;return this.expectKeyword("fragment"),!0===(null===(e=this._options)||void 0===e?void 0:e.allowLegacyFragmentVariables)?this.node(t,{kind:a.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet()}):this.node(t,{kind:a.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet()})}parseFragmentName(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()}parseValueLiteral(e){const t=this._lexer.token;switch(t.kind){case u.T.BRACKET_L:return this.parseList(e);case u.T.BRACE_L:return this.parseObject(e);case u.T.INT:return this._lexer.advance(),this.node(t,{kind:a.h.INT,value:t.value});case u.T.FLOAT:return this._lexer.advance(),this.node(t,{kind:a.h.FLOAT,value:t.value});case u.T.STRING:case u.T.BLOCK_STRING:return this.parseStringLiteral();case u.T.NAME:switch(this._lexer.advance(),t.value){case"true":return this.node(t,{kind:a.h.BOOLEAN,value:!0});case"false":return this.node(t,{kind:a.h.BOOLEAN,value:!1});case"null":return this.node(t,{kind:a.h.NULL});default:return this.node(t,{kind:a.h.ENUM,value:t.value})}case u.T.DOLLAR:if(e){if(this.expectToken(u.T.DOLLAR),this._lexer.token.kind===u.T.NAME){const e=this._lexer.token.value;throw(0,r.h)(this._lexer.source,t.start,`Unexpected variable "$${e}" in constant value.`)}throw this.unexpected(t)}return this.parseVariable();default:throw this.unexpected()}}parseConstValueLiteral(){return this.parseValueLiteral(!0)}parseStringLiteral(){const e=this._lexer.token;return this._lexer.advance(),this.node(e,{kind:a.h.STRING,value:e.value,block:e.kind===u.T.BLOCK_STRING})}parseList(e){return this.node(this._lexer.token,{kind:a.h.LIST,values:this.any(u.T.BRACKET_L,(()=>this.parseValueLiteral(e)),u.T.BRACKET_R)})}parseObject(e){return this.node(this._lexer.token,{kind:a.h.OBJECT,fields:this.any(u.T.BRACE_L,(()=>this.parseObjectField(e)),u.T.BRACE_R)})}parseObjectField(e){const t=this._lexer.token,n=this.parseName();return this.expectToken(u.T.COLON),this.node(t,{kind:a.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e)})}parseDirectives(e){const t=[];for(;this.peek(u.T.AT);)t.push(this.parseDirective(e));return t}parseConstDirectives(){return this.parseDirectives(!0)}parseDirective(e){const t=this._lexer.token;return this.expectToken(u.T.AT),this.node(t,{kind:a.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e)})}parseTypeReference(){const e=this._lexer.token;let t;if(this.expectOptionalToken(u.T.BRACKET_L)){const n=this.parseTypeReference();this.expectToken(u.T.BRACKET_R),t=this.node(e,{kind:a.h.LIST_TYPE,type:n})}else t=this.parseNamedType();return this.expectOptionalToken(u.T.BANG)?this.node(e,{kind:a.h.NON_NULL_TYPE,type:t}):t}parseNamedType(){return this.node(this._lexer.token,{kind:a.h.NAMED_TYPE,name:this.parseName()})}peekDescription(){return this.peek(u.T.STRING)||this.peek(u.T.BLOCK_STRING)}parseDescription(){if(this.peekDescription())return this.parseStringLiteral()}parseSchemaDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");const n=this.parseConstDirectives(),r=this.many(u.T.BRACE_L,this.parseOperationTypeDefinition,u.T.BRACE_R);return this.node(e,{kind:a.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r})}parseOperationTypeDefinition(){const e=this._lexer.token,t=this.parseOperationType();this.expectToken(u.T.COLON);const n=this.parseNamedType();return this.node(e,{kind:a.h.OPERATION_TYPE_DEFINITION,operation:t,type:n})}parseScalarTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");const n=this.parseName(),r=this.parseConstDirectives();return this.node(e,{kind:a.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r})}parseObjectTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");const n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseConstDirectives(),o=this.parseFieldsDefinition();return this.node(e,{kind:a.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:o})}parseImplementsInterfaces(){return this.expectOptionalKeyword("implements")?this.delimitedMany(u.T.AMP,this.parseNamedType):[]}parseFieldsDefinition(){return this.optionalMany(u.T.BRACE_L,this.parseFieldDefinition,u.T.BRACE_R)}parseFieldDefinition(){const e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(u.T.COLON);const i=this.parseTypeReference(),o=this.parseConstDirectives();return this.node(e,{kind:a.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:o})}parseArgumentDefs(){return this.optionalMany(u.T.PAREN_L,this.parseInputValueDef,u.T.PAREN_R)}parseInputValueDef(){const e=this._lexer.token,t=this.parseDescription(),n=this.parseName();this.expectToken(u.T.COLON);const r=this.parseTypeReference();let i;this.expectOptionalToken(u.T.EQUALS)&&(i=this.parseConstValueLiteral());const o=this.parseConstDirectives();return this.node(e,{kind:a.h.INPUT_VALUE_DEFINITION,description:t,name:n,type:r,defaultValue:i,directives:o})}parseInterfaceTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");const n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseConstDirectives(),o=this.parseFieldsDefinition();return this.node(e,{kind:a.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:o})}parseUnionTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");const n=this.parseName(),r=this.parseConstDirectives(),i=this.parseUnionMemberTypes();return this.node(e,{kind:a.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i})}parseUnionMemberTypes(){return this.expectOptionalToken(u.T.EQUALS)?this.delimitedMany(u.T.PIPE,this.parseNamedType):[]}parseEnumTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");const n=this.parseName(),r=this.parseConstDirectives(),i=this.parseEnumValuesDefinition();return this.node(e,{kind:a.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i})}parseEnumValuesDefinition(){return this.optionalMany(u.T.BRACE_L,this.parseEnumValueDefinition,u.T.BRACE_R)}parseEnumValueDefinition(){const e=this._lexer.token,t=this.parseDescription(),n=this.parseEnumValueName(),r=this.parseConstDirectives();return this.node(e,{kind:a.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r})}parseEnumValueName(){if("true"===this._lexer.token.value||"false"===this._lexer.token.value||"null"===this._lexer.token.value)throw(0,r.h)(this._lexer.source,this._lexer.token.start,`${m(this._lexer.token)} is reserved and cannot be used for an enum value.`);return this.parseName()}parseInputObjectTypeDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");const n=this.parseName(),r=this.parseConstDirectives(),i=this.parseInputFieldsDefinition();return this.node(e,{kind:a.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i})}parseInputFieldsDefinition(){return this.optionalMany(u.T.BRACE_L,this.parseInputValueDef,u.T.BRACE_R)}parseTypeSystemExtension(){const e=this._lexer.lookahead();if(e.kind===u.T.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)}parseSchemaExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");const t=this.parseConstDirectives(),n=this.optionalMany(u.T.BRACE_L,this.parseOperationTypeDefinition,u.T.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return this.node(e,{kind:a.h.SCHEMA_EXTENSION,directives:t,operationTypes:n})}parseScalarTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");const t=this.parseName(),n=this.parseConstDirectives();if(0===n.length)throw this.unexpected();return this.node(e,{kind:a.h.SCALAR_TYPE_EXTENSION,name:t,directives:n})}parseObjectTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");const t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseConstDirectives(),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return this.node(e,{kind:a.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i})}parseInterfaceTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");const t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseConstDirectives(),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return this.node(e,{kind:a.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i})}parseUnionTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");const t=this.parseName(),n=this.parseConstDirectives(),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return this.node(e,{kind:a.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r})}parseEnumTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");const t=this.parseName(),n=this.parseConstDirectives(),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return this.node(e,{kind:a.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r})}parseInputObjectTypeExtension(){const e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");const t=this.parseName(),n=this.parseConstDirectives(),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return this.node(e,{kind:a.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r})}parseDirectiveDefinition(){const e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(u.T.AT);const n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");const o=this.parseDirectiveLocations();return this.node(e,{kind:a.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:o})}parseDirectiveLocations(){return this.delimitedMany(u.T.PIPE,this.parseDirectiveLocation)}parseDirectiveLocation(){const e=this._lexer.token,t=this.parseName();if(Object.prototype.hasOwnProperty.call(o.B,t.value))return t;throw this.unexpected(e)}node(e,t){var n;return!0!==(null===(n=this._options)||void 0===n?void 0:n.noLocation)&&(t.loc=new i.Ye(e,this._lexer.lastToken,this._lexer.source)),t}peek(e){return this._lexer.token.kind===e}expectToken(e){const t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw(0,r.h)(this._lexer.source,t.start,`Expected ${g(e)}, found ${m(t)}.`)}expectOptionalToken(e){return this._lexer.token.kind===e&&(this._lexer.advance(),!0)}expectKeyword(e){const t=this._lexer.token;if(t.kind!==u.T.NAME||t.value!==e)throw(0,r.h)(this._lexer.source,t.start,`Expected "${e}", found ${m(t)}.`);this._lexer.advance()}expectOptionalKeyword(e){const t=this._lexer.token;return t.kind===u.T.NAME&&t.value===e&&(this._lexer.advance(),!0)}unexpected(e){const t=null!=e?e:this._lexer.token;return(0,r.h)(this._lexer.source,t.start,`Unexpected ${m(t)}.`)}any(e,t,n){this.expectToken(e);const r=[];for(;!this.expectOptionalToken(n);)r.push(t.call(this));return r}optionalMany(e,t,n){if(this.expectOptionalToken(e)){const e=[];do{e.push(t.call(this))}while(!this.expectOptionalToken(n));return e}return[]}many(e,t,n){this.expectToken(e);const r=[];do{r.push(t.call(this))}while(!this.expectOptionalToken(n));return r}delimitedMany(e,t){this.expectOptionalToken(e);const n=[];do{n.push(t.call(this))}while(this.expectOptionalToken(e));return n}}function m(e){const t=e.value;return g(e.kind)+(null!=t?` "${t}"`:"")}function g(e){return(0,s.u)(e)?`"${e}"`:e}},9615:function(e,t,n){"use strict";n.d(t,{D$:function(){return p},G4:function(){return c},Ir:function(){return i},Of:function(){return l},VB:function(){return u},Wk:function(){return o},aU:function(){return f},nr:function(){return s},pO:function(){return a},zT:function(){return d}});var r=n(3830);function i(e){return o(e)||c(e)||f(e)}function o(e){return e.kind===r.h.OPERATION_DEFINITION||e.kind===r.h.FRAGMENT_DEFINITION}function a(e){return e.kind===r.h.FIELD||e.kind===r.h.FRAGMENT_SPREAD||e.kind===r.h.INLINE_FRAGMENT}function s(e){return e.kind===r.h.VARIABLE||e.kind===r.h.INT||e.kind===r.h.FLOAT||e.kind===r.h.STRING||e.kind===r.h.BOOLEAN||e.kind===r.h.NULL||e.kind===r.h.ENUM||e.kind===r.h.LIST||e.kind===r.h.OBJECT}function l(e){return s(e)&&(e.kind===r.h.LIST?e.values.some(l):e.kind===r.h.OBJECT?e.fields.some((e=>l(e.value))):e.kind!==r.h.VARIABLE)}function u(e){return e.kind===r.h.NAMED_TYPE||e.kind===r.h.LIST_TYPE||e.kind===r.h.NON_NULL_TYPE}function c(e){return e.kind===r.h.SCHEMA_DEFINITION||d(e)||e.kind===r.h.DIRECTIVE_DEFINITION}function d(e){return e.kind===r.h.SCALAR_TYPE_DEFINITION||e.kind===r.h.OBJECT_TYPE_DEFINITION||e.kind===r.h.INTERFACE_TYPE_DEFINITION||e.kind===r.h.UNION_TYPE_DEFINITION||e.kind===r.h.ENUM_TYPE_DEFINITION||e.kind===r.h.INPUT_OBJECT_TYPE_DEFINITION}function f(e){return e.kind===r.h.SCHEMA_EXTENSION||p(e)}function p(e){return e.kind===r.h.SCALAR_TYPE_EXTENSION||e.kind===r.h.OBJECT_TYPE_EXTENSION||e.kind===r.h.INTERFACE_TYPE_EXTENSION||e.kind===r.h.UNION_TYPE_EXTENSION||e.kind===r.h.ENUM_TYPE_EXTENSION||e.kind===r.h.INPUT_OBJECT_TYPE_EXTENSION}},7026:function(e,t,n){"use strict";n.d(t,{Q:function(){return i},z:function(){return o}});var r=n(3302);function i(e){return o(e.source,(0,r.k)(e.source,e.start))}function o(e,t){const n=e.locationOffset.column-1,r="".padStart(n)+e.body,i=t.line-1,o=e.locationOffset.line-1,s=t.line+o,l=1===t.line?n:0,u=t.column+l,c=`${e.name}:${s}:${u}\n`,d=r.split(/\r\n|[\n\r]/g),f=d[i];if(f.length>120){const e=Math.floor(u/80),t=u%80,n=[];for(let e=0;e["|",e])),["|","^".padStart(t)],["|",n[e+1]]])}return c+a([[s-1+" |",d[i-1]],[`${s} |`,f],["|","^".padStart(u)],[`${s+1} |`,d[i+1]]])}function a(e){const t=e.filter((([e,t])=>void 0!==t)),n=Math.max(...t.map((([e])=>e.length)));return t.map((([e,t])=>e.padStart(n)+(t?" "+t:""))).join("\n")}},5895:function(e,t,n){"use strict";n.d(t,{S:function(){return l}});var r=n(6303);const i=/[\x00-\x1f\x22\x5c\x7f-\x9f]/g;function o(e){return a[e.charCodeAt(0)]}const a=["\\u0000","\\u0001","\\u0002","\\u0003","\\u0004","\\u0005","\\u0006","\\u0007","\\b","\\t","\\n","\\u000B","\\f","\\r","\\u000E","\\u000F","\\u0010","\\u0011","\\u0012","\\u0013","\\u0014","\\u0015","\\u0016","\\u0017","\\u0018","\\u0019","\\u001A","\\u001B","\\u001C","\\u001D","\\u001E","\\u001F","","",'\\"',"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\\\","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\\u007F","\\u0080","\\u0081","\\u0082","\\u0083","\\u0084","\\u0085","\\u0086","\\u0087","\\u0088","\\u0089","\\u008A","\\u008B","\\u008C","\\u008D","\\u008E","\\u008F","\\u0090","\\u0091","\\u0092","\\u0093","\\u0094","\\u0095","\\u0096","\\u0097","\\u0098","\\u0099","\\u009A","\\u009B","\\u009C","\\u009D","\\u009E","\\u009F"];var s=n(9685);function l(e){return(0,s.Vn)(e,u)}const u={Name:{leave:e=>e.value},Variable:{leave:e=>"$"+e.name},Document:{leave:e=>c(e.definitions,"\n\n")},OperationDefinition:{leave(e){const t=f("(",c(e.variableDefinitions,", "),")"),n=c([e.operation,c([e.name,t]),c(e.directives," ")]," ");return("query"===n?"":n+" ")+e.selectionSet}},VariableDefinition:{leave:({variable:e,type:t,defaultValue:n,directives:r})=>e+": "+t+f(" = ",n)+f(" ",c(r," "))},SelectionSet:{leave:({selections:e})=>d(e)},Field:{leave({alias:e,name:t,arguments:n,directives:r,selectionSet:i}){const o=f("",e,": ")+t;let a=o+f("(",c(n,", "),")");return a.length>80&&(a=o+f("(\n",p(c(n,"\n")),"\n)")),c([a,c(r," "),i]," ")}},Argument:{leave:({name:e,value:t})=>e+": "+t},FragmentSpread:{leave:({name:e,directives:t})=>"..."+e+f(" ",c(t," "))},InlineFragment:{leave:({typeCondition:e,directives:t,selectionSet:n})=>c(["...",f("on ",e),c(t," "),n]," ")},FragmentDefinition:{leave:({name:e,typeCondition:t,variableDefinitions:n,directives:r,selectionSet:i})=>`fragment ${e}${f("(",c(n,", "),")")} on ${t} ${f("",c(r," ")," ")}`+i},IntValue:{leave:({value:e})=>e},FloatValue:{leave:({value:e})=>e},StringValue:{leave:({value:e,block:t})=>t?(0,r.LZ)(e):`"${e.replace(i,o)}"`},BooleanValue:{leave:({value:e})=>e?"true":"false"},NullValue:{leave:()=>"null"},EnumValue:{leave:({value:e})=>e},ListValue:{leave:({values:e})=>"["+c(e,", ")+"]"},ObjectValue:{leave:({fields:e})=>"{"+c(e,", ")+"}"},ObjectField:{leave:({name:e,value:t})=>e+": "+t},Directive:{leave:({name:e,arguments:t})=>"@"+e+f("(",c(t,", "),")")},NamedType:{leave:({name:e})=>e},ListType:{leave:({type:e})=>"["+e+"]"},NonNullType:{leave:({type:e})=>e+"!"},SchemaDefinition:{leave:({description:e,directives:t,operationTypes:n})=>f("",e,"\n")+c(["schema",c(t," "),d(n)]," ")},OperationTypeDefinition:{leave:({operation:e,type:t})=>e+": "+t},ScalarTypeDefinition:{leave:({description:e,name:t,directives:n})=>f("",e,"\n")+c(["scalar",t,c(n," ")]," ")},ObjectTypeDefinition:{leave:({description:e,name:t,interfaces:n,directives:r,fields:i})=>f("",e,"\n")+c(["type",t,f("implements ",c(n," & ")),c(r," "),d(i)]," ")},FieldDefinition:{leave:({description:e,name:t,arguments:n,type:r,directives:i})=>f("",e,"\n")+t+(h(n)?f("(\n",p(c(n,"\n")),"\n)"):f("(",c(n,", "),")"))+": "+r+f(" ",c(i," "))},InputValueDefinition:{leave:({description:e,name:t,type:n,defaultValue:r,directives:i})=>f("",e,"\n")+c([t+": "+n,f("= ",r),c(i," ")]," ")},InterfaceTypeDefinition:{leave:({description:e,name:t,interfaces:n,directives:r,fields:i})=>f("",e,"\n")+c(["interface",t,f("implements ",c(n," & ")),c(r," "),d(i)]," ")},UnionTypeDefinition:{leave:({description:e,name:t,directives:n,types:r})=>f("",e,"\n")+c(["union",t,c(n," "),f("= ",c(r," | "))]," ")},EnumTypeDefinition:{leave:({description:e,name:t,directives:n,values:r})=>f("",e,"\n")+c(["enum",t,c(n," "),d(r)]," ")},EnumValueDefinition:{leave:({description:e,name:t,directives:n})=>f("",e,"\n")+c([t,c(n," ")]," ")},InputObjectTypeDefinition:{leave:({description:e,name:t,directives:n,fields:r})=>f("",e,"\n")+c(["input",t,c(n," "),d(r)]," ")},DirectiveDefinition:{leave:({description:e,name:t,arguments:n,repeatable:r,locations:i})=>f("",e,"\n")+"directive @"+t+(h(n)?f("(\n",p(c(n,"\n")),"\n)"):f("(",c(n,", "),")"))+(r?" repeatable":"")+" on "+c(i," | ")},SchemaExtension:{leave:({directives:e,operationTypes:t})=>c(["extend schema",c(e," "),d(t)]," ")},ScalarTypeExtension:{leave:({name:e,directives:t})=>c(["extend scalar",e,c(t," ")]," ")},ObjectTypeExtension:{leave:({name:e,interfaces:t,directives:n,fields:r})=>c(["extend type",e,f("implements ",c(t," & ")),c(n," "),d(r)]," ")},InterfaceTypeExtension:{leave:({name:e,interfaces:t,directives:n,fields:r})=>c(["extend interface",e,f("implements ",c(t," & ")),c(n," "),d(r)]," ")},UnionTypeExtension:{leave:({name:e,directives:t,types:n})=>c(["extend union",e,c(t," "),f("= ",c(n," | "))]," ")},EnumTypeExtension:{leave:({name:e,directives:t,values:n})=>c(["extend enum",e,c(t," "),d(n)]," ")},InputObjectTypeExtension:{leave:({name:e,directives:t,fields:n})=>c(["extend input",e,c(t," "),d(n)]," ")}};function c(e,t=""){var n;return null!==(n=null==e?void 0:e.filter((e=>e)).join(t))&&void 0!==n?n:""}function d(e){return f("{\n",p(c(e,"\n")),"\n}")}function f(e,t,n=""){return null!=t&&""!==t?e+t+n:""}function p(e){return f(" ",e.replace(/\n/g,"\n "))}function h(e){var t;return null!==(t=null==e?void 0:e.some((e=>e.includes("\n"))))&&void 0!==t&&t}},4680:function(e,t,n){"use strict";n.d(t,{H:function(){return a},T:function(){return s}});var r=n(1172),i=n(5648),o=n(1513);class a{constructor(e,t="GraphQL request",n={line:1,column:1}){"string"==typeof e||(0,r.a)(!1,`Body must be a string. Received: ${(0,i.X)(e)}.`),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||(0,r.a)(!1,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||(0,r.a)(!1,"column in locationOffset is 1-indexed and must be positive.")}get[Symbol.toStringTag](){return"Source"}}function s(e){return(0,o.n)(e,a)}},5685:function(e,t,n){"use strict";let r;n.d(t,{T:function(){return r}}),function(e){e.SOF="",e.EOF="",e.BANG="!",e.DOLLAR="$",e.AMP="&",e.PAREN_L="(",e.PAREN_R=")",e.SPREAD="...",e.COLON=":",e.EQUALS="=",e.AT="@",e.BRACKET_L="[",e.BRACKET_R="]",e.BRACE_L="{",e.PIPE="|",e.BRACE_R="}",e.NAME="Name",e.INT="Int",e.FLOAT="Float",e.STRING="String",e.BLOCK_STRING="BlockString",e.COMMENT="Comment"}(r||(r={}))},9685:function(e,t,n){"use strict";n.d(t,{$_:function(){return s},CK:function(){return d},Eu:function(){return c},Vn:function(){return l},j1:function(){return u}});var r=n(1172),i=n(5648),o=n(3526),a=n(3830);const s=Object.freeze({});function l(e,t,n=o.h8){const l=new Map;for(const e of Object.values(a.h))l.set(e,c(t,e));let u,d,f,p=Array.isArray(e),h=[e],m=-1,g=[],v=e;const y=[],b=[];do{m++;const e=m===h.length,a=e&&0!==g.length;if(e){if(d=0===b.length?void 0:y[y.length-1],v=f,f=b.pop(),a)if(p){v=v.slice();let e=0;for(const[t,n]of g){const r=t-e;null===n?(v.splice(r,1),e++):v[r]=n}}else{v=Object.defineProperties({},Object.getOwnPropertyDescriptors(v));for(const[e,t]of g)v[e]=t}m=u.index,h=u.keys,g=u.edits,p=u.inArray,u=u.prev}else if(f){if(d=p?m:h[m],v=f[d],null==v)continue;y.push(d)}let c;if(!Array.isArray(v)){var E,T;(0,o.UG)(v)||(0,r.a)(!1,`Invalid AST Node: ${(0,i.X)(v)}.`);const n=e?null===(E=l.get(v.kind))||void 0===E?void 0:E.leave:null===(T=l.get(v.kind))||void 0===T?void 0:T.enter;if(c=null==n?void 0:n.call(t,v,d,f,y,b),c===s)break;if(!1===c){if(!e){y.pop();continue}}else if(void 0!==c&&(g.push([d,c]),!e)){if(!(0,o.UG)(c)){y.pop();continue}v=c}}var w;void 0===c&&a&&g.push([d,v]),e?y.pop():(u={inArray:p,index:m,keys:h,edits:g,prev:u},p=Array.isArray(v),h=p?v:null!==(w=n[v.kind])&&void 0!==w?w:[],m=-1,g=[],f&&b.push(f),f=v)}while(void 0!==u);return 0!==g.length?g[g.length-1][1]:e}function u(e){const t=new Array(e.length).fill(null),n=Object.create(null);for(const r of Object.values(a.h)){let i=!1;const o=new Array(e.length).fill(void 0),a=new Array(e.length).fill(void 0);for(let t=0;tl((0,v.M)(e,t)),this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(s=e.extensionASTNodes)&&void 0!==s?s:[],null==e.specifiedByURL||"string"==typeof e.specifiedByURL||(0,r.a)(!1,`${this.name} must provide "specifiedByURL" as a string, but got: ${(0,a.X)(e.specifiedByURL)}.`),null==e.serialize||"function"==typeof e.serialize||(0,r.a)(!1,`${this.name} must provide "serialize" function. If this custom Scalar is also used as an input type, ensure "parseValue" and "parseLiteral" functions are also provided.`),e.parseLiteral&&("function"==typeof e.parseValue&&"function"==typeof e.parseLiteral||(0,r.a)(!1,`${this.name} must provide both "parseValue" and "parseLiteral" functions.`))}get[Symbol.toStringTag](){return"GraphQLScalarType"}toConfig(){return{name:this.name,description:this.description,specifiedByURL:this.specifiedByURL,serialize:this.serialize,parseValue:this.parseValue,parseLiteral:this.parseLiteral,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}class ae{constructor(e){var t;this.name=(0,y.i)(e.name),this.description=e.description,this.isTypeOf=e.isTypeOf,this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=()=>le(e),this._interfaces=()=>se(e),null==e.isTypeOf||"function"==typeof e.isTypeOf||(0,r.a)(!1,`${this.name} must provide "isTypeOf" as a function, but got: ${(0,a.X)(e.isTypeOf)}.`)}get[Symbol.toStringTag](){return"GraphQLObjectType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}getInterfaces(){return"function"==typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces}toConfig(){return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:de(this.getFields()),isTypeOf:this.isTypeOf,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function se(e){var t;const n=re(null!==(t=e.interfaces)&&void 0!==t?t:[]);return Array.isArray(n)||(0,r.a)(!1,`${e.name} interfaces must be an Array or a function which returns an Array.`),n}function le(e){const t=ie(e.fields);return ce(t)||(0,r.a)(!1,`${e.name} fields must be an object with field names as keys or a function which returns such an object.`),(0,d.j)(t,((t,n)=>{var i;ce(t)||(0,r.a)(!1,`${e.name}.${n} field config must be an object.`),null==t.resolve||"function"==typeof t.resolve||(0,r.a)(!1,`${e.name}.${n} field resolver must be a function if provided, but got: ${(0,a.X)(t.resolve)}.`);const o=null!==(i=t.args)&&void 0!==i?i:{};return ce(o)||(0,r.a)(!1,`${e.name}.${n} args must be an object with argument names as keys.`),{name:(0,y.i)(n),description:t.description,type:t.type,args:ue(o),resolve:t.resolve,subscribe:t.subscribe,deprecationReason:t.deprecationReason,extensions:(0,p.u)(t.extensions),astNode:t.astNode}}))}function ue(e){return Object.entries(e).map((([e,t])=>({name:(0,y.i)(e),description:t.description,type:t.type,defaultValue:t.defaultValue,deprecationReason:t.deprecationReason,extensions:(0,p.u)(t.extensions),astNode:t.astNode})))}function ce(e){return(0,l.y)(e)&&!Array.isArray(e)}function de(e){return(0,d.j)(e,(e=>({description:e.description,type:e.type,args:fe(e.args),resolve:e.resolve,subscribe:e.subscribe,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})))}function fe(e){return(0,c.w)(e,(e=>e.name),(e=>({description:e.description,type:e.type,defaultValue:e.defaultValue,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})))}function pe(e){return R(e.type)&&void 0===e.defaultValue}class he{constructor(e){var t;this.name=(0,y.i)(e.name),this.description=e.description,this.resolveType=e.resolveType,this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=le.bind(void 0,e),this._interfaces=se.bind(void 0,e),null==e.resolveType||"function"==typeof e.resolveType||(0,r.a)(!1,`${this.name} must provide "resolveType" as a function, but got: ${(0,a.X)(e.resolveType)}.`)}get[Symbol.toStringTag](){return"GraphQLInterfaceType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}getInterfaces(){return"function"==typeof this._interfaces&&(this._interfaces=this._interfaces()),this._interfaces}toConfig(){return{name:this.name,description:this.description,interfaces:this.getInterfaces(),fields:de(this.getFields()),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}class me{constructor(e){var t;this.name=(0,y.i)(e.name),this.description=e.description,this.resolveType=e.resolveType,this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._types=ge.bind(void 0,e),null==e.resolveType||"function"==typeof e.resolveType||(0,r.a)(!1,`${this.name} must provide "resolveType" as a function, but got: ${(0,a.X)(e.resolveType)}.`)}get[Symbol.toStringTag](){return"GraphQLUnionType"}getTypes(){return"function"==typeof this._types&&(this._types=this._types()),this._types}toConfig(){return{name:this.name,description:this.description,types:this.getTypes(),resolveType:this.resolveType,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function ge(e){const t=re(e.types);return Array.isArray(t)||(0,r.a)(!1,`Must provide Array of types or a function which returns such an array for Union ${e.name}.`),t}class ve{constructor(e){var t,n,i;this.name=(0,y.i)(e.name),this.description=e.description,this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._values=(n=this.name,ce(i=e.values)||(0,r.a)(!1,`${n} values must be an object with value names as keys.`),Object.entries(i).map((([e,t])=>(ce(t)||(0,r.a)(!1,`${n}.${e} must refer to an object with a "value" key representing an internal value but got: ${(0,a.X)(t)}.`),{name:(0,y.g)(e),description:t.description,value:void 0!==t.value?t.value:e,deprecationReason:t.deprecationReason,extensions:(0,p.u)(t.extensions),astNode:t.astNode})))),this._valueLookup=new Map(this._values.map((e=>[e.value,e]))),this._nameLookup=(0,u.P)(this._values,(e=>e.name))}get[Symbol.toStringTag](){return"GraphQLEnumType"}getValues(){return this._values}getValue(e){return this._nameLookup[e]}serialize(e){const t=this._valueLookup.get(e);if(void 0===t)throw new h.__(`Enum "${this.name}" cannot represent value: ${(0,a.X)(e)}`);return t.name}parseValue(e){if("string"!=typeof e){const t=(0,a.X)(e);throw new h.__(`Enum "${this.name}" cannot represent non-string value: ${t}.`+ye(this,t))}const t=this.getValue(e);if(null==t)throw new h.__(`Value "${e}" does not exist in "${this.name}" enum.`+ye(this,e));return t.value}parseLiteral(e,t){if(e.kind!==m.h.ENUM){const t=(0,g.S)(e);throw new h.__(`Enum "${this.name}" cannot represent non-enum value: ${t}.`+ye(this,t),{nodes:e})}const n=this.getValue(e.value);if(null==n){const t=(0,g.S)(e);throw new h.__(`Value "${t}" does not exist in "${this.name}" enum.`+ye(this,t),{nodes:e})}return n.value}toConfig(){const e=(0,c.w)(this.getValues(),(e=>e.name),(e=>({description:e.description,value:e.value,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})));return{name:this.name,description:this.description,values:e,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function ye(e,t){const n=e.getValues().map((e=>e.name)),r=(0,f.D)(t,n);return(0,i.l)("the enum value",r)}class be{constructor(e){var t;this.name=(0,y.i)(e.name),this.description=e.description,this.extensions=(0,p.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._fields=Ee.bind(void 0,e)}get[Symbol.toStringTag](){return"GraphQLInputObjectType"}getFields(){return"function"==typeof this._fields&&(this._fields=this._fields()),this._fields}toConfig(){const e=(0,d.j)(this.getFields(),(e=>({description:e.description,type:e.type,defaultValue:e.defaultValue,deprecationReason:e.deprecationReason,extensions:e.extensions,astNode:e.astNode})));return{name:this.name,description:this.description,fields:e,extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes}}toString(){return this.name}toJSON(){return this.toString()}}function Ee(e){const t=ie(e.fields);return ce(t)||(0,r.a)(!1,`${e.name} fields must be an object with field names as keys or a function which returns such an object.`),(0,d.j)(t,((t,n)=>(!("resolve"in t)||(0,r.a)(!1,`${e.name}.${n} field has a resolve property, but Input Types cannot define resolvers.`),{name:(0,y.i)(n),description:t.description,type:t.type,defaultValue:t.defaultValue,deprecationReason:t.deprecationReason,extensions:(0,p.u)(t.extensions),astNode:t.astNode})))}function Te(e){return R(e.type)&&void 0===e.defaultValue}},5946:function(e,t,n){"use strict";n.d(t,{CO:function(){return p},NZ:function(){return h},QE:function(){return g},SY:function(){return v},V4:function(){return E},Yf:function(){return m},df:function(){return b},fg:function(){return y},wX:function(){return f},xg:function(){return T}});var r=n(1172),i=n(5648),o=n(1513),a=n(1315),s=n(1140),l=n(3140),u=n(3228),c=n(755),d=n(1774);function f(e){return(0,o.n)(e,h)}function p(e){if(!f(e))throw new Error(`Expected ${(0,i.X)(e)} to be a GraphQL directive.`);return e}class h{constructor(e){var t,n;this.name=(0,u.i)(e.name),this.description=e.description,this.locations=e.locations,this.isRepeatable=null!==(t=e.isRepeatable)&&void 0!==t&&t,this.extensions=(0,s.u)(e.extensions),this.astNode=e.astNode,Array.isArray(e.locations)||(0,r.a)(!1,`@${e.name} locations must be an Array.`);const i=null!==(n=e.args)&&void 0!==n?n:{};(0,a.y)(i)&&!Array.isArray(i)||(0,r.a)(!1,`@${e.name} args must be an object with argument names as keys.`),this.args=(0,c.WO)(i)}get[Symbol.toStringTag](){return"GraphQLDirective"}toConfig(){return{name:this.name,description:this.description,locations:this.locations,args:(0,c.DM)(this.args),isRepeatable:this.isRepeatable,extensions:this.extensions,astNode:this.astNode}}toString(){return"@"+this.name}toJSON(){return this.toString()}}const m=new h({name:"include",description:"Directs the executor to include this field or fragment only when the `if` argument is true.",locations:[l.B.FIELD,l.B.FRAGMENT_SPREAD,l.B.INLINE_FRAGMENT],args:{if:{type:new c.bM(d.EZ),description:"Included when true."}}}),g=new h({name:"skip",description:"Directs the executor to skip this field or fragment when the `if` argument is true.",locations:[l.B.FIELD,l.B.FRAGMENT_SPREAD,l.B.INLINE_FRAGMENT],args:{if:{type:new c.bM(d.EZ),description:"Skipped when true."}}}),v="No longer supported",y=new h({name:"deprecated",description:"Marks an element of a GraphQL schema as no longer supported.",locations:[l.B.FIELD_DEFINITION,l.B.ARGUMENT_DEFINITION,l.B.INPUT_FIELD_DEFINITION,l.B.ENUM_VALUE],args:{reason:{type:d.kH,description:"Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax, as specified by [CommonMark](https://commonmark.org/).",defaultValue:v}}}),b=new h({name:"specifiedBy",description:"Exposes a URL that specifies the behavior of this scalar.",locations:[l.B.SCALAR],args:{url:{type:new c.bM(d.kH),description:"The URL that specifies the behavior of this scalar."}}}),E=Object.freeze([m,g,y,b]);function T(e){return E.some((({name:t})=>t===e.name))}},8078:function(e,t,n){"use strict";n.d(t,{Az:function(){return b},PX:function(){return y},TK:function(){return c},XQ:function(){return m},e_:function(){return h},hU:function(){return T},jT:function(){return g},l3:function(){return d},nL:function(){return w},qz:function(){return p},s9:function(){return C},tF:function(){return E},x2:function(){return f},zU:function(){return v}});var r=n(5648),i=n(5052),o=n(3140),a=n(5895),s=n(3190),l=n(755),u=n(1774);const c=new l.h6({name:"__Schema",description:"A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.",fields:()=>({description:{type:u.kH,resolve:e=>e.description},types:{description:"A list of all types supported by this server.",type:new l.bM(new l.p2(new l.bM(p))),resolve(e){return Object.values(e.getTypeMap())}},queryType:{description:"The type that query operations will be rooted at.",type:new l.bM(p),resolve:e=>e.getQueryType()},mutationType:{description:"If this server supports mutation, the type that mutation operations will be rooted at.",type:p,resolve:e=>e.getMutationType()},subscriptionType:{description:"If this server support subscription, the type that subscription operations will be rooted at.",type:p,resolve:e=>e.getSubscriptionType()},directives:{description:"A list of all directives supported by this server.",type:new l.bM(new l.p2(new l.bM(d))),resolve:e=>e.getDirectives()}})}),d=new l.h6({name:"__Directive",description:"A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.",fields:()=>({name:{type:new l.bM(u.kH),resolve:e=>e.name},description:{type:u.kH,resolve:e=>e.description},isRepeatable:{type:new l.bM(u.EZ),resolve:e=>e.isRepeatable},locations:{type:new l.bM(new l.p2(new l.bM(f))),resolve:e=>e.locations},args:{type:new l.bM(new l.p2(new l.bM(m))),args:{includeDeprecated:{type:u.EZ,defaultValue:!1}},resolve(e,{includeDeprecated:t}){return t?e.args:e.args.filter((e=>null==e.deprecationReason))}}})}),f=new l.mR({name:"__DirectiveLocation",description:"A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.",values:{QUERY:{value:o.B.QUERY,description:"Location adjacent to a query operation."},MUTATION:{value:o.B.MUTATION,description:"Location adjacent to a mutation operation."},SUBSCRIPTION:{value:o.B.SUBSCRIPTION,description:"Location adjacent to a subscription operation."},FIELD:{value:o.B.FIELD,description:"Location adjacent to a field."},FRAGMENT_DEFINITION:{value:o.B.FRAGMENT_DEFINITION,description:"Location adjacent to a fragment definition."},FRAGMENT_SPREAD:{value:o.B.FRAGMENT_SPREAD,description:"Location adjacent to a fragment spread."},INLINE_FRAGMENT:{value:o.B.INLINE_FRAGMENT,description:"Location adjacent to an inline fragment."},VARIABLE_DEFINITION:{value:o.B.VARIABLE_DEFINITION,description:"Location adjacent to a variable definition."},SCHEMA:{value:o.B.SCHEMA,description:"Location adjacent to a schema definition."},SCALAR:{value:o.B.SCALAR,description:"Location adjacent to a scalar definition."},OBJECT:{value:o.B.OBJECT,description:"Location adjacent to an object type definition."},FIELD_DEFINITION:{value:o.B.FIELD_DEFINITION,description:"Location adjacent to a field definition."},ARGUMENT_DEFINITION:{value:o.B.ARGUMENT_DEFINITION,description:"Location adjacent to an argument definition."},INTERFACE:{value:o.B.INTERFACE,description:"Location adjacent to an interface definition."},UNION:{value:o.B.UNION,description:"Location adjacent to a union definition."},ENUM:{value:o.B.ENUM,description:"Location adjacent to an enum definition."},ENUM_VALUE:{value:o.B.ENUM_VALUE,description:"Location adjacent to an enum value definition."},INPUT_OBJECT:{value:o.B.INPUT_OBJECT,description:"Location adjacent to an input object type definition."},INPUT_FIELD_DEFINITION:{value:o.B.INPUT_FIELD_DEFINITION,description:"Location adjacent to an input object field definition."}}}),p=new l.h6({name:"__Type",description:"The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name, description and optional `specifiedByURL`, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.",fields:()=>({kind:{type:new l.bM(y),resolve(e){return(0,l.KA)(e)?v.SCALAR:(0,l.lp)(e)?v.OBJECT:(0,l.oT)(e)?v.INTERFACE:(0,l.EN)(e)?v.UNION:(0,l.EM)(e)?v.ENUM:(0,l.hL)(e)?v.INPUT_OBJECT:(0,l.HG)(e)?v.LIST:(0,l.zM)(e)?v.NON_NULL:void(0,i.k)(!1,`Unexpected type: "${(0,r.X)(e)}".`)}},name:{type:u.kH,resolve:e=>"name"in e?e.name:void 0},description:{type:u.kH,resolve:e=>"description"in e?e.description:void 0},specifiedByURL:{type:u.kH,resolve:e=>"specifiedByURL"in e?e.specifiedByURL:void 0},fields:{type:new l.p2(new l.bM(h)),args:{includeDeprecated:{type:u.EZ,defaultValue:!1}},resolve(e,{includeDeprecated:t}){if((0,l.lp)(e)||(0,l.oT)(e)){const n=Object.values(e.getFields());return t?n:n.filter((e=>null==e.deprecationReason))}}},interfaces:{type:new l.p2(new l.bM(p)),resolve(e){if((0,l.lp)(e)||(0,l.oT)(e))return e.getInterfaces()}},possibleTypes:{type:new l.p2(new l.bM(p)),resolve(e,t,n,{schema:r}){if((0,l.m0)(e))return r.getPossibleTypes(e)}},enumValues:{type:new l.p2(new l.bM(g)),args:{includeDeprecated:{type:u.EZ,defaultValue:!1}},resolve(e,{includeDeprecated:t}){if((0,l.EM)(e)){const n=e.getValues();return t?n:n.filter((e=>null==e.deprecationReason))}}},inputFields:{type:new l.p2(new l.bM(m)),args:{includeDeprecated:{type:u.EZ,defaultValue:!1}},resolve(e,{includeDeprecated:t}){if((0,l.hL)(e)){const n=Object.values(e.getFields());return t?n:n.filter((e=>null==e.deprecationReason))}}},ofType:{type:p,resolve:e=>"ofType"in e?e.ofType:void 0}})}),h=new l.h6({name:"__Field",description:"Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.",fields:()=>({name:{type:new l.bM(u.kH),resolve:e=>e.name},description:{type:u.kH,resolve:e=>e.description},args:{type:new l.bM(new l.p2(new l.bM(m))),args:{includeDeprecated:{type:u.EZ,defaultValue:!1}},resolve(e,{includeDeprecated:t}){return t?e.args:e.args.filter((e=>null==e.deprecationReason))}},type:{type:new l.bM(p),resolve:e=>e.type},isDeprecated:{type:new l.bM(u.EZ),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:u.kH,resolve:e=>e.deprecationReason}})}),m=new l.h6({name:"__InputValue",description:"Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.",fields:()=>({name:{type:new l.bM(u.kH),resolve:e=>e.name},description:{type:u.kH,resolve:e=>e.description},type:{type:new l.bM(p),resolve:e=>e.type},defaultValue:{type:u.kH,description:"A GraphQL-formatted string representing the default value for this input value.",resolve(e){const{type:t,defaultValue:n}=e,r=(0,s.J)(n,t);return r?(0,a.S)(r):null}},isDeprecated:{type:new l.bM(u.EZ),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:u.kH,resolve:e=>e.deprecationReason}})}),g=new l.h6({name:"__EnumValue",description:"One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.",fields:()=>({name:{type:new l.bM(u.kH),resolve:e=>e.name},description:{type:u.kH,resolve:e=>e.description},isDeprecated:{type:new l.bM(u.EZ),resolve:e=>null!=e.deprecationReason},deprecationReason:{type:u.kH,resolve:e=>e.deprecationReason}})});let v;!function(e){e.SCALAR="SCALAR",e.OBJECT="OBJECT",e.INTERFACE="INTERFACE",e.UNION="UNION",e.ENUM="ENUM",e.INPUT_OBJECT="INPUT_OBJECT",e.LIST="LIST",e.NON_NULL="NON_NULL"}(v||(v={}));const y=new l.mR({name:"__TypeKind",description:"An enum describing what kind of type a given `__Type` is.",values:{SCALAR:{value:v.SCALAR,description:"Indicates this type is a scalar."},OBJECT:{value:v.OBJECT,description:"Indicates this type is an object. `fields` and `interfaces` are valid fields."},INTERFACE:{value:v.INTERFACE,description:"Indicates this type is an interface. `fields`, `interfaces`, and `possibleTypes` are valid fields."},UNION:{value:v.UNION,description:"Indicates this type is a union. `possibleTypes` is a valid field."},ENUM:{value:v.ENUM,description:"Indicates this type is an enum. `enumValues` is a valid field."},INPUT_OBJECT:{value:v.INPUT_OBJECT,description:"Indicates this type is an input object. `inputFields` is a valid field."},LIST:{value:v.LIST,description:"Indicates this type is a list. `ofType` is a valid field."},NON_NULL:{value:v.NON_NULL,description:"Indicates this type is a non-null. `ofType` is a valid field."}}}),b={name:"__schema",type:new l.bM(c),description:"Access the current type schema of this server.",args:[],resolve:(e,t,n,{schema:r})=>r,deprecationReason:void 0,extensions:Object.create(null),astNode:void 0},E={name:"__type",type:p,description:"Request the type information of a single type.",args:[{name:"name",description:void 0,type:new l.bM(u.kH),defaultValue:void 0,deprecationReason:void 0,extensions:Object.create(null),astNode:void 0}],resolve:(e,{name:t},n,{schema:r})=>r.getType(t),deprecationReason:void 0,extensions:Object.create(null),astNode:void 0},T={name:"__typename",type:new l.bM(u.kH),description:"The name of the current Object type at runtime.",args:[],resolve:(e,t,n,{parentType:r})=>r.name,deprecationReason:void 0,extensions:Object.create(null),astNode:void 0},w=Object.freeze([c,d,f,p,h,m,g,y]);function C(e){return w.some((({name:t})=>e.name===t))}},1774:function(e,t,n){"use strict";n.d(t,{EZ:function(){return h},HI:function(){return u},HS:function(){return g},_o:function(){return d},av:function(){return f},kH:function(){return p},km:function(){return m},st:function(){return c},u1:function(){return v}});var r=n(5648),i=n(1315),o=n(4117),a=n(3830),s=n(5895),l=n(755);const u=2147483647,c=-2147483648,d=new l.n2({name:"Int",description:"The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",serialize(e){const t=y(e);if("boolean"==typeof t)return t?1:0;let n=t;if("string"==typeof t&&""!==t&&(n=Number(t)),"number"!=typeof n||!Number.isInteger(n))throw new o.__(`Int cannot represent non-integer value: ${(0,r.X)(t)}`);if(n>u||nu||eu||te.name===t))}function y(e){if((0,i.y)(e)){if("function"==typeof e.valueOf){const t=e.valueOf();if(!(0,i.y)(t))return t}if("function"==typeof e.toJSON)return e.toJSON()}return e}},773:function(e,t,n){"use strict";n.d(t,{EO:function(){return p},XO:function(){return h},nN:function(){return f}});var r=n(1172),i=n(5648),o=n(1513),a=n(1315),s=n(1140),l=n(3526),u=n(755),c=n(5946),d=n(8078);function f(e){return(0,o.n)(e,h)}function p(e){if(!f(e))throw new Error(`Expected ${(0,i.X)(e)} to be a GraphQL schema.`);return e}class h{constructor(e){var t,n;this.__validationErrors=!0===e.assumeValid?[]:void 0,(0,a.y)(e)||(0,r.a)(!1,"Must provide configuration object."),!e.types||Array.isArray(e.types)||(0,r.a)(!1,`"types" must be Array if provided but got: ${(0,i.X)(e.types)}.`),!e.directives||Array.isArray(e.directives)||(0,r.a)(!1,`"directives" must be Array if provided but got: ${(0,i.X)(e.directives)}.`),this.description=e.description,this.extensions=(0,s.u)(e.extensions),this.astNode=e.astNode,this.extensionASTNodes=null!==(t=e.extensionASTNodes)&&void 0!==t?t:[],this._queryType=e.query,this._mutationType=e.mutation,this._subscriptionType=e.subscription,this._directives=null!==(n=e.directives)&&void 0!==n?n:c.V4;const o=new Set(e.types);if(null!=e.types)for(const t of e.types)o.delete(t),m(t,o);null!=this._queryType&&m(this._queryType,o),null!=this._mutationType&&m(this._mutationType,o),null!=this._subscriptionType&&m(this._subscriptionType,o);for(const e of this._directives)if((0,c.wX)(e))for(const t of e.args)m(t.type,o);m(d.TK,o),this._typeMap=Object.create(null),this._subTypeMap=Object.create(null),this._implementationsMap=Object.create(null);for(const e of o){if(null==e)continue;const t=e.name;if(t||(0,r.a)(!1,"One of the provided types for building the Schema is missing a name."),void 0!==this._typeMap[t])throw new Error(`Schema must contain uniquely named types but contains multiple types named "${t}".`);if(this._typeMap[t]=e,(0,u.oT)(e)){for(const t of e.getInterfaces())if((0,u.oT)(t)){let n=this._implementationsMap[t.name];void 0===n&&(n=this._implementationsMap[t.name]={objects:[],interfaces:[]}),n.interfaces.push(e)}}else if((0,u.lp)(e))for(const t of e.getInterfaces())if((0,u.oT)(t)){let n=this._implementationsMap[t.name];void 0===n&&(n=this._implementationsMap[t.name]={objects:[],interfaces:[]}),n.objects.push(e)}}}get[Symbol.toStringTag](){return"GraphQLSchema"}getQueryType(){return this._queryType}getMutationType(){return this._mutationType}getSubscriptionType(){return this._subscriptionType}getRootType(e){switch(e){case l.ku.QUERY:return this.getQueryType();case l.ku.MUTATION:return this.getMutationType();case l.ku.SUBSCRIPTION:return this.getSubscriptionType()}}getTypeMap(){return this._typeMap}getType(e){return this.getTypeMap()[e]}getPossibleTypes(e){return(0,u.EN)(e)?e.getTypes():this.getImplementations(e).objects}getImplementations(e){const t=this._implementationsMap[e.name];return null!=t?t:{objects:[],interfaces:[]}}isSubType(e,t){let n=this._subTypeMap[e.name];if(void 0===n){if(n=Object.create(null),(0,u.EN)(e))for(const t of e.getTypes())n[t.name]=!0;else{const t=this.getImplementations(e);for(const e of t.objects)n[e.name]=!0;for(const e of t.interfaces)n[e.name]=!0}this._subTypeMap[e.name]=n}return void 0!==n[t.name]}getDirectives(){return this._directives}getDirective(e){return this.getDirectives().find((t=>t.name===e))}toConfig(){return{description:this.description,query:this.getQueryType(),mutation:this.getMutationType(),subscription:this.getSubscriptionType(),types:Object.values(this.getTypeMap()),directives:this.getDirectives(),extensions:this.extensions,astNode:this.astNode,extensionASTNodes:this.extensionASTNodes,assumeValid:void 0!==this.__validationErrors}}}function m(e,t){const n=(0,u.xC)(e);if(!t.has(n))if(t.add(n),(0,u.EN)(n))for(const e of n.getTypes())m(e,t);else if((0,u.lp)(n)||(0,u.oT)(n)){for(const e of n.getInterfaces())m(e,t);for(const e of Object.values(n.getFields())){m(e.type,t);for(const n of e.args)m(n.type,t)}}else if((0,u.hL)(n))for(const e of Object.values(n.getFields()))m(e.type,t);return t}},8555:function(e,t,n){"use strict";n.d(t,{F:function(){return d},J:function(){return f}});var r=n(5648),i=n(4117),o=n(3526),a=n(2984),s=n(755),l=n(5946),u=n(8078),c=n(773);function d(e){if((0,c.EO)(e),e.__validationErrors)return e.__validationErrors;const t=new p(e);!function(e){const t=e.schema,n=t.getQueryType();if(n){if(!(0,s.lp)(n)){var i;e.reportError(`Query root type must be Object type, it cannot be ${(0,r.X)(n)}.`,null!==(i=h(t,o.ku.QUERY))&&void 0!==i?i:n.astNode)}}else e.reportError("Query root type must be provided.",t.astNode);const a=t.getMutationType();var l;a&&!(0,s.lp)(a)&&e.reportError(`Mutation root type must be Object type if provided, it cannot be ${(0,r.X)(a)}.`,null!==(l=h(t,o.ku.MUTATION))&&void 0!==l?l:a.astNode);const u=t.getSubscriptionType();var c;u&&!(0,s.lp)(u)&&e.reportError(`Subscription root type must be Object type if provided, it cannot be ${(0,r.X)(u)}.`,null!==(c=h(t,o.ku.SUBSCRIPTION))&&void 0!==c?c:u.astNode)}(t),function(e){for(const n of e.schema.getDirectives())if((0,l.wX)(n)){m(e,n);for(const i of n.args){var t;m(e,i),(0,s.j$)(i.type)||e.reportError(`The type of @${n.name}(${i.name}:) must be Input Type but got: ${(0,r.X)(i.type)}.`,i.astNode),(0,s.dK)(i)&&null!=i.deprecationReason&&e.reportError(`Required argument @${n.name}(${i.name}:) cannot be deprecated.`,[x(i.astNode),null===(t=i.astNode)||void 0===t?void 0:t.type])}}else e.reportError(`Expected directive but got: ${(0,r.X)(n)}.`,null==n?void 0:n.astNode)}(t),function(e){const t=function(e){const t=Object.create(null),n=[],r=Object.create(null);return function i(o){if(t[o.name])return;t[o.name]=!0,r[o.name]=n.length;const a=Object.values(o.getFields());for(const t of a)if((0,s.zM)(t.type)&&(0,s.hL)(t.type.ofType)){const o=t.type.ofType,a=r[o.name];if(n.push(t),void 0===a)i(o);else{const t=n.slice(a),r=t.map((e=>e.name)).join(".");e.reportError(`Cannot reference Input Object "${o.name}" within itself through a series of non-null fields: "${r}".`,t.map((e=>e.astNode)))}n.pop()}r[o.name]=void 0}}(e),n=e.schema.getTypeMap();for(const i of Object.values(n))(0,s.Zs)(i)?((0,u.s9)(i)||m(e,i),(0,s.lp)(i)||(0,s.oT)(i)?(g(e,i),v(e,i)):(0,s.EN)(i)?E(e,i):(0,s.EM)(i)?T(e,i):(0,s.hL)(i)&&(w(e,i),t(i))):e.reportError(`Expected GraphQL named type but got: ${(0,r.X)(i)}.`,i.astNode)}(t);const n=t.getErrors();return e.__validationErrors=n,n}function f(e){const t=d(e);if(0!==t.length)throw new Error(t.map((e=>e.message)).join("\n\n"))}class p{constructor(e){this._errors=[],this.schema=e}reportError(e,t){const n=Array.isArray(t)?t.filter(Boolean):t;this._errors.push(new i.__(e,{nodes:n}))}getErrors(){return this._errors}}function h(e,t){var n;return null===(n=[e.astNode,...e.extensionASTNodes].flatMap((e=>{var t;return null!==(t=null==e?void 0:e.operationTypes)&&void 0!==t?t:[]})).find((e=>e.operation===t)))||void 0===n?void 0:n.type}function m(e,t){t.name.startsWith("__")&&e.reportError(`Name "${t.name}" must not begin with "__", which is reserved by GraphQL introspection.`,t.astNode)}function g(e,t){const n=Object.values(t.getFields());0===n.length&&e.reportError(`Type ${t.name} must define one or more fields.`,[t.astNode,...t.extensionASTNodes]);for(const l of n){var i;m(e,l),(0,s.SZ)(l.type)||e.reportError(`The type of ${t.name}.${l.name} must be Output Type but got: ${(0,r.X)(l.type)}.`,null===(i=l.astNode)||void 0===i?void 0:i.type);for(const n of l.args){const i=n.name;var o,a;m(e,n),(0,s.j$)(n.type)||e.reportError(`The type of ${t.name}.${l.name}(${i}:) must be Input Type but got: ${(0,r.X)(n.type)}.`,null===(o=n.astNode)||void 0===o?void 0:o.type),(0,s.dK)(n)&&null!=n.deprecationReason&&e.reportError(`Required argument ${t.name}.${l.name}(${i}:) cannot be deprecated.`,[x(n.astNode),null===(a=n.astNode)||void 0===a?void 0:a.type])}}}function v(e,t){const n=Object.create(null);for(const i of t.getInterfaces())(0,s.oT)(i)?t!==i?n[i.name]?e.reportError(`Type ${t.name} can only implement ${i.name} once.`,C(t,i)):(n[i.name]=!0,b(e,t,i),y(e,t,i)):e.reportError(`Type ${t.name} cannot implement itself because it would create a circular reference.`,C(t,i)):e.reportError(`Type ${(0,r.X)(t)} must only implement Interface types, it cannot implement ${(0,r.X)(i)}.`,C(t,i))}function y(e,t,n){const i=t.getFields();for(const d of Object.values(n.getFields())){const f=d.name,p=i[f];if(p){var o,l;(0,a.uJ)(e.schema,p.type,d.type)||e.reportError(`Interface field ${n.name}.${f} expects type ${(0,r.X)(d.type)} but ${t.name}.${f} is type ${(0,r.X)(p.type)}.`,[null===(o=d.astNode)||void 0===o?void 0:o.type,null===(l=p.astNode)||void 0===l?void 0:l.type]);for(const i of d.args){const o=i.name,s=p.args.find((e=>e.name===o));var u,c;s?(0,a._7)(i.type,s.type)||e.reportError(`Interface field argument ${n.name}.${f}(${o}:) expects type ${(0,r.X)(i.type)} but ${t.name}.${f}(${o}:) is type ${(0,r.X)(s.type)}.`,[null===(u=i.astNode)||void 0===u?void 0:u.type,null===(c=s.astNode)||void 0===c?void 0:c.type]):e.reportError(`Interface field argument ${n.name}.${f}(${o}:) expected but ${t.name}.${f} does not provide it.`,[i.astNode,p.astNode])}for(const r of p.args){const i=r.name;!d.args.find((e=>e.name===i))&&(0,s.dK)(r)&&e.reportError(`Object field ${t.name}.${f} includes required argument ${i} that is missing from the Interface field ${n.name}.${f}.`,[r.astNode,d.astNode])}}else e.reportError(`Interface field ${n.name}.${f} expected but ${t.name} does not provide it.`,[d.astNode,t.astNode,...t.extensionASTNodes])}}function b(e,t,n){const r=t.getInterfaces();for(const i of n.getInterfaces())r.includes(i)||e.reportError(i===t?`Type ${t.name} cannot implement ${n.name} because it would create a circular reference.`:`Type ${t.name} must implement ${i.name} because it is implemented by ${n.name}.`,[...C(n,i),...C(t,n)])}function E(e,t){const n=t.getTypes();0===n.length&&e.reportError(`Union type ${t.name} must define one or more member types.`,[t.astNode,...t.extensionASTNodes]);const i=Object.create(null);for(const o of n)i[o.name]?e.reportError(`Union type ${t.name} can only include type ${o.name} once.`,S(t,o.name)):(i[o.name]=!0,(0,s.lp)(o)||e.reportError(`Union type ${t.name} can only include Object types, it cannot include ${(0,r.X)(o)}.`,S(t,String(o))))}function T(e,t){const n=t.getValues();0===n.length&&e.reportError(`Enum type ${t.name} must define one or more values.`,[t.astNode,...t.extensionASTNodes]);for(const t of n)m(e,t)}function w(e,t){const n=Object.values(t.getFields());0===n.length&&e.reportError(`Input Object type ${t.name} must define one or more fields.`,[t.astNode,...t.extensionASTNodes]);for(const a of n){var i,o;m(e,a),(0,s.j$)(a.type)||e.reportError(`The type of ${t.name}.${a.name} must be Input Type but got: ${(0,r.X)(a.type)}.`,null===(i=a.astNode)||void 0===i?void 0:i.type),(0,s.Wd)(a)&&null!=a.deprecationReason&&e.reportError(`Required input field ${t.name}.${a.name} cannot be deprecated.`,[x(a.astNode),null===(o=a.astNode)||void 0===o?void 0:o.type])}}function C(e,t){const{astNode:n,extensionASTNodes:r}=e;return(null!=n?[n,...r]:r).flatMap((e=>{var t;return null!==(t=e.interfaces)&&void 0!==t?t:[]})).filter((e=>e.name.value===t.name))}function S(e,t){const{astNode:n,extensionASTNodes:r}=e;return(null!=n?[n,...r]:r).flatMap((e=>{var t;return null!==(t=e.types)&&void 0!==t?t:[]})).filter((e=>e.name.value===t))}function x(e){var t;return null==e||null===(t=e.directives)||void 0===t?void 0:t.find((e=>e.name.value===l.fg.name))}},1409:function(e,t,n){"use strict";n.d(t,{a:function(){return u},y:function(){return d}});var r=n(3526),i=n(3830),o=n(9685),a=n(755),s=n(8078),l=n(5998);class u{constructor(e,t,n){this._schema=e,this._typeStack=[],this._parentTypeStack=[],this._inputTypeStack=[],this._fieldDefStack=[],this._defaultValueStack=[],this._directive=null,this._argument=null,this._enumValue=null,this._getFieldDef=null!=n?n:c,t&&((0,a.j$)(t)&&this._inputTypeStack.push(t),(0,a.Gv)(t)&&this._parentTypeStack.push(t),(0,a.SZ)(t)&&this._typeStack.push(t))}get[Symbol.toStringTag](){return"TypeInfo"}getType(){if(this._typeStack.length>0)return this._typeStack[this._typeStack.length-1]}getParentType(){if(this._parentTypeStack.length>0)return this._parentTypeStack[this._parentTypeStack.length-1]}getInputType(){if(this._inputTypeStack.length>0)return this._inputTypeStack[this._inputTypeStack.length-1]}getParentInputType(){if(this._inputTypeStack.length>1)return this._inputTypeStack[this._inputTypeStack.length-2]}getFieldDef(){if(this._fieldDefStack.length>0)return this._fieldDefStack[this._fieldDefStack.length-1]}getDefaultValue(){if(this._defaultValueStack.length>0)return this._defaultValueStack[this._defaultValueStack.length-1]}getDirective(){return this._directive}getArgument(){return this._argument}getEnumValue(){return this._enumValue}enter(e){const t=this._schema;switch(e.kind){case i.h.SELECTION_SET:{const e=(0,a.xC)(this.getType());this._parentTypeStack.push((0,a.Gv)(e)?e:void 0);break}case i.h.FIELD:{const n=this.getParentType();let r,i;n&&(r=this._getFieldDef(t,n,e),r&&(i=r.type)),this._fieldDefStack.push(r),this._typeStack.push((0,a.SZ)(i)?i:void 0);break}case i.h.DIRECTIVE:this._directive=t.getDirective(e.name.value);break;case i.h.OPERATION_DEFINITION:{const n=t.getRootType(e.operation);this._typeStack.push((0,a.lp)(n)?n:void 0);break}case i.h.INLINE_FRAGMENT:case i.h.FRAGMENT_DEFINITION:{const n=e.typeCondition,r=n?(0,l._)(t,n):(0,a.xC)(this.getType());this._typeStack.push((0,a.SZ)(r)?r:void 0);break}case i.h.VARIABLE_DEFINITION:{const n=(0,l._)(t,e.type);this._inputTypeStack.push((0,a.j$)(n)?n:void 0);break}case i.h.ARGUMENT:{var n;let t,r;const i=null!==(n=this.getDirective())&&void 0!==n?n:this.getFieldDef();i&&(t=i.args.find((t=>t.name===e.name.value)),t&&(r=t.type)),this._argument=t,this._defaultValueStack.push(t?t.defaultValue:void 0),this._inputTypeStack.push((0,a.j$)(r)?r:void 0);break}case i.h.LIST:{const e=(0,a.tf)(this.getInputType()),t=(0,a.HG)(e)?e.ofType:e;this._defaultValueStack.push(void 0),this._inputTypeStack.push((0,a.j$)(t)?t:void 0);break}case i.h.OBJECT_FIELD:{const t=(0,a.xC)(this.getInputType());let n,r;(0,a.hL)(t)&&(r=t.getFields()[e.name.value],r&&(n=r.type)),this._defaultValueStack.push(r?r.defaultValue:void 0),this._inputTypeStack.push((0,a.j$)(n)?n:void 0);break}case i.h.ENUM:{const t=(0,a.xC)(this.getInputType());let n;(0,a.EM)(t)&&(n=t.getValue(e.value)),this._enumValue=n;break}}}leave(e){switch(e.kind){case i.h.SELECTION_SET:this._parentTypeStack.pop();break;case i.h.FIELD:this._fieldDefStack.pop(),this._typeStack.pop();break;case i.h.DIRECTIVE:this._directive=null;break;case i.h.OPERATION_DEFINITION:case i.h.INLINE_FRAGMENT:case i.h.FRAGMENT_DEFINITION:this._typeStack.pop();break;case i.h.VARIABLE_DEFINITION:this._inputTypeStack.pop();break;case i.h.ARGUMENT:this._argument=null,this._defaultValueStack.pop(),this._inputTypeStack.pop();break;case i.h.LIST:case i.h.OBJECT_FIELD:this._defaultValueStack.pop(),this._inputTypeStack.pop();break;case i.h.ENUM:this._enumValue=null}}}function c(e,t,n){const r=n.name.value;return r===s.Az.name&&e.getQueryType()===t?s.Az:r===s.tF.name&&e.getQueryType()===t?s.tF:r===s.hU.name&&(0,a.Gv)(t)?s.hU:(0,a.lp)(t)||(0,a.oT)(t)?t.getFields()[r]:void 0}function d(e,t){return{enter(...n){const i=n[0];e.enter(i);const a=(0,o.Eu)(t,i.kind).enter;if(a){const o=a.apply(t,n);return void 0!==o&&(e.leave(i),(0,r.UG)(o)&&e.enter(o)),o}},leave(...n){const r=n[0],i=(0,o.Eu)(t,r.kind).leave;let a;return i&&(a=i.apply(t,n)),e.leave(r),a}}}},3190:function(e,t,n){"use strict";n.d(t,{J:function(){return c}});var r=n(5648),i=n(5052),o=n(2910),a=n(1315),s=n(3830),l=n(755),u=n(1774);function c(e,t){if((0,l.zM)(t)){const n=c(e,t.ofType);return(null==n?void 0:n.kind)===s.h.NULL?null:n}if(null===e)return{kind:s.h.NULL};if(void 0===e)return null;if((0,l.HG)(t)){const n=t.ofType;if((0,o.i)(e)){const t=[];for(const r of e){const e=c(r,n);null!=e&&t.push(e)}return{kind:s.h.LIST,values:t}}return c(e,n)}if((0,l.hL)(t)){if(!(0,a.y)(e))return null;const n=[];for(const r of Object.values(t.getFields())){const t=c(e[r.name],r.type);t&&n.push({kind:s.h.OBJECT_FIELD,name:{kind:s.h.NAME,value:r.name},value:t})}return{kind:s.h.OBJECT,fields:n}}if((0,l.UT)(t)){const n=t.serialize(e);if(null==n)return null;if("boolean"==typeof n)return{kind:s.h.BOOLEAN,value:n};if("number"==typeof n&&Number.isFinite(n)){const e=String(n);return d.test(e)?{kind:s.h.INT,value:e}:{kind:s.h.FLOAT,value:e}}if("string"==typeof n)return(0,l.EM)(t)?{kind:s.h.ENUM,value:n}:t===u.km&&d.test(n)?{kind:s.h.INT,value:n}:{kind:s.h.STRING,value:n};throw new TypeError(`Cannot convert value to AST: ${(0,r.X)(n)}.`)}(0,i.k)(!1,"Unexpected input type: "+(0,r.X)(t))}const d=/^-?(?:0|[1-9][0-9]*)$/},5925:function(e,t,n){"use strict";n.d(t,{K:function(){return p}});var r=n(8063),i=n(5648),o=n(5052),a=n(2910),s=n(1315),l=n(9878),u=n(4987),c=n(3492),d=n(4117),f=n(755);function p(e,t,n=h){return m(e,t,n,void 0)}function h(e,t,n){let r="Invalid value "+(0,i.X)(t);throw e.length>0&&(r+=` at "value${(0,u.F)(e)}"`),n.message=r+": "+n.message,n}function m(e,t,n,u){if((0,f.zM)(t))return null!=e?m(e,t.ofType,n,u):void n((0,l.N)(u),e,new d.__(`Expected non-nullable type "${(0,i.X)(t)}" not to be null.`));if(null==e)return null;if((0,f.HG)(t)){const r=t.ofType;return(0,a.i)(e)?Array.from(e,((e,t)=>{const i=(0,l.Q)(u,t,void 0);return m(e,r,n,i)})):[m(e,r,n,u)]}if((0,f.hL)(t)){if(!(0,s.y)(e))return void n((0,l.N)(u),e,new d.__(`Expected type "${t.name}" to be an object.`));const o={},a=t.getFields();for(const r of Object.values(a)){const a=e[r.name];if(void 0!==a)o[r.name]=m(a,r.type,n,(0,l.Q)(u,r.name,t.name));else if(void 0!==r.defaultValue)o[r.name]=r.defaultValue;else if((0,f.zM)(r.type)){const t=(0,i.X)(r.type);n((0,l.N)(u),e,new d.__(`Field "${r.name}" of required type "${t}" was not provided.`))}}for(const i of Object.keys(e))if(!a[i]){const o=(0,c.D)(i,Object.keys(t.getFields()));n((0,l.N)(u),e,new d.__(`Field "${i}" is not defined by type "${t.name}".`+(0,r.l)(o)))}return o}if((0,f.UT)(t)){let r;try{r=t.parseValue(e)}catch(r){return void(r instanceof d.__?n((0,l.N)(u),e,r):n((0,l.N)(u),e,new d.__(`Expected type "${t.name}". `+r.message,{originalError:r})))}return void 0===r&&n((0,l.N)(u),e,new d.__(`Expected type "${t.name}".`)),r}(0,o.k)(!1,"Unexpected input type: "+(0,i.X)(t))}},9458:function(e,t,n){"use strict";n.d(t,{S:function(){return i}});var r=n(3830);function i(e,t){let n=null;for(const o of e.definitions){var i;if(o.kind===r.h.OPERATION_DEFINITION)if(null==t){if(n)return null;n=o}else if((null===(i=o.name)||void 0===i?void 0:i.value)===t)return o}return n}},4034:function(e,t,n){"use strict";n.d(t,{n:function(){return o}});var r=n(6625),i=n(3830);function o(e){switch(e.kind){case i.h.OBJECT:return{...e,fields:(t=e.fields,t.map((e=>({...e,value:o(e.value)}))).sort(((e,t)=>(0,r.K)(e.name.value,t.name.value))))};case i.h.LIST:return{...e,values:e.values.map(o)};case i.h.INT:case i.h.FLOAT:case i.h.STRING:case i.h.BOOLEAN:case i.h.NULL:case i.h.ENUM:case i.h.VARIABLE:return e}var t}},2984:function(e,t,n){"use strict";n.d(t,{_7:function(){return i},uJ:function(){return o},zR:function(){return a}});var r=n(755);function i(e,t){return e===t||((0,r.zM)(e)&&(0,r.zM)(t)||!(!(0,r.HG)(e)||!(0,r.HG)(t)))&&i(e.ofType,t.ofType)}function o(e,t,n){return t===n||((0,r.zM)(n)?!!(0,r.zM)(t)&&o(e,t.ofType,n.ofType):(0,r.zM)(t)?o(e,t.ofType,n):(0,r.HG)(n)?!!(0,r.HG)(t)&&o(e,t.ofType,n.ofType):!(0,r.HG)(t)&&(0,r.m0)(n)&&((0,r.oT)(t)||(0,r.lp)(t))&&e.isSubType(n,t))}function a(e,t,n){return t===n||((0,r.m0)(t)?(0,r.m0)(n)?e.getPossibleTypes(t).some((t=>e.isSubType(n,t))):e.isSubType(t,n):!!(0,r.m0)(n)&&e.isSubType(n,t))}},5998:function(e,t,n){"use strict";n.d(t,{_:function(){return o}});var r=n(3830),i=n(755);function o(e,t){switch(t.kind){case r.h.LIST_TYPE:{const n=o(e,t.type);return n&&new i.p2(n)}case r.h.NON_NULL_TYPE:{const n=o(e,t.type);return n&&new i.bM(n)}case r.h.NAMED_TYPE:return e.getType(t.name.value)}}},5284:function(e,t,n){"use strict";n.d(t,{u:function(){return l}});var r=n(5648),i=n(5052),o=n(9815),a=n(3830),s=n(755);function l(e,t,n){if(e){if(e.kind===a.h.VARIABLE){const r=e.name.value;if(null==n||void 0===n[r])return;const i=n[r];if(null===i&&(0,s.zM)(t))return;return i}if((0,s.zM)(t)){if(e.kind===a.h.NULL)return;return l(e,t.ofType,n)}if(e.kind===a.h.NULL)return null;if((0,s.HG)(t)){const r=t.ofType;if(e.kind===a.h.LIST){const t=[];for(const i of e.values)if(u(i,n)){if((0,s.zM)(r))return;t.push(null)}else{const e=l(i,r,n);if(void 0===e)return;t.push(e)}return t}const i=l(e,r,n);if(void 0===i)return;return[i]}if((0,s.hL)(t)){if(e.kind!==a.h.OBJECT)return;const r=Object.create(null),i=(0,o.P)(e.fields,(e=>e.name.value));for(const e of Object.values(t.getFields())){const t=i[e.name];if(!t||u(t.value,n)){if(void 0!==e.defaultValue)r[e.name]=e.defaultValue;else if((0,s.zM)(e.type))return;continue}const o=l(t.value,e.type,n);if(void 0===o)return;r[e.name]=o}return r}if((0,s.UT)(t)){let r;try{r=t.parseLiteral(e,n)}catch(e){return}if(void 0===r)return;return r}(0,i.k)(!1,"Unexpected input type: "+(0,r.X)(t))}}function u(e,t){return e.kind===a.h.VARIABLE&&(null==t||void 0===t[e.name.value])}},9426:function(e,t,n){"use strict";n.d(t,{M:function(){return o}});var r=n(8240),i=n(3830);function o(e,t){switch(e.kind){case i.h.NULL:return null;case i.h.INT:return parseInt(e.value,10);case i.h.FLOAT:return parseFloat(e.value);case i.h.STRING:case i.h.ENUM:case i.h.BOOLEAN:return e.value;case i.h.LIST:return e.values.map((e=>o(e,t)));case i.h.OBJECT:return(0,r.w)(e.fields,(e=>e.name.value),(e=>o(e.value,t)));case i.h.VARIABLE:return null==t?void 0:t[e.name.value]}}},2716:function(e,t,n){"use strict";n.d(t,{_t:function(){return l},yv:function(){return s}});var r=n(3830),i=n(9685),o=n(1409);class a{constructor(e,t){this._ast=e,this._fragments=void 0,this._fragmentSpreads=new Map,this._recursivelyReferencedFragments=new Map,this._onError=t}get[Symbol.toStringTag](){return"ASTValidationContext"}reportError(e){this._onError(e)}getDocument(){return this._ast}getFragment(e){let t;if(this._fragments)t=this._fragments;else{t=Object.create(null);for(const e of this.getDocument().definitions)e.kind===r.h.FRAGMENT_DEFINITION&&(t[e.name.value]=e);this._fragments=t}return t[e]}getFragmentSpreads(e){let t=this._fragmentSpreads.get(e);if(!t){t=[];const n=[e];let i;for(;i=n.pop();)for(const e of i.selections)e.kind===r.h.FRAGMENT_SPREAD?t.push(e):e.selectionSet&&n.push(e.selectionSet);this._fragmentSpreads.set(e,t)}return t}getRecursivelyReferencedFragments(e){let t=this._recursivelyReferencedFragments.get(e);if(!t){t=[];const n=Object.create(null),r=[e.selectionSet];let i;for(;i=r.pop();)for(const e of this.getFragmentSpreads(i)){const i=e.name.value;if(!0!==n[i]){n[i]=!0;const e=this.getFragment(i);e&&(t.push(e),r.push(e.selectionSet))}}this._recursivelyReferencedFragments.set(e,t)}return t}}class s extends a{constructor(e,t,n){super(e,n),this._schema=t}get[Symbol.toStringTag](){return"SDLValidationContext"}getSchema(){return this._schema}}class l extends a{constructor(e,t,n,r){super(t,r),this._schema=e,this._typeInfo=n,this._variableUsages=new Map,this._recursiveVariableUsages=new Map}get[Symbol.toStringTag](){return"ValidationContext"}getSchema(){return this._schema}getVariableUsages(e){let t=this._variableUsages.get(e);if(!t){const n=[],r=new o.a(this._schema);(0,i.Vn)(e,(0,o.y)(r,{VariableDefinition:()=>!1,Variable(e){n.push({node:e,type:r.getInputType(),defaultValue:r.getDefaultValue()})}})),t=n,this._variableUsages.set(e,t)}return t}getRecursiveVariableUsages(e){let t=this._recursiveVariableUsages.get(e);if(!t){t=this.getVariableUsages(e);for(const n of this.getRecursivelyReferencedFragments(e))t=t.concat(this.getVariableUsages(n));this._recursiveVariableUsages.set(e,t)}return t}getType(){return this._typeInfo.getType()}getParentType(){return this._typeInfo.getParentType()}getInputType(){return this._typeInfo.getInputType()}getParentInputType(){return this._typeInfo.getParentInputType()}getFieldDef(){return this._typeInfo.getFieldDef()}getDirective(){return this._typeInfo.getDirective()}getArgument(){return this._typeInfo.getArgument()}getEnumValue(){return this._typeInfo.getEnumValue()}}},3857:function(e,t,n){"use strict";n.d(t,{i:function(){return a}});var r=n(4117),i=n(3830),o=n(9615);function a(e){return{Document(t){for(const n of t.definitions)if(!(0,o.Wk)(n)){const t=n.kind===i.h.SCHEMA_DEFINITION||n.kind===i.h.SCHEMA_EXTENSION?"schema":'"'+n.name.value+'"';e.reportError(new r.__(`The ${t} definition is not executable.`,{nodes:n}))}return!1}}}},1870:function(e,t,n){"use strict";n.d(t,{A:function(){return l}});var r=n(8063),i=n(6625),o=n(3492),a=n(4117),s=n(755);function l(e){return{Field(t){const n=e.getParentType();if(n&&!e.getFieldDef()){const l=e.getSchema(),u=t.name.value;let c=(0,r.l)("to use an inline fragment on",function(e,t,n){if(!(0,s.m0)(t))return[];const r=new Set,o=Object.create(null);for(const i of e.getPossibleTypes(t))if(i.getFields()[n]){r.add(i),o[i.name]=1;for(const e of i.getInterfaces()){var a;e.getFields()[n]&&(r.add(e),o[e.name]=(null!==(a=o[e.name])&&void 0!==a?a:0)+1)}}return[...r].sort(((t,n)=>{const r=o[n.name]-o[t.name];return 0!==r?r:(0,s.oT)(t)&&e.isSubType(t,n)?-1:(0,s.oT)(n)&&e.isSubType(n,t)?1:(0,i.K)(t.name,n.name)})).map((e=>e.name))}(l,n,u));""===c&&(c=(0,r.l)(function(e,t){if((0,s.lp)(e)||(0,s.oT)(e)){const n=Object.keys(e.getFields());return(0,o.D)(t,n)}return[]}(n,u))),e.reportError(new a.__(`Cannot query field "${u}" on type "${n.name}".`+c,{nodes:t}))}}}}},5167:function(e,t,n){"use strict";n.d(t,{T:function(){return s}});var r=n(4117),i=n(5895),o=n(755),a=n(5998);function s(e){return{InlineFragment(t){const n=t.typeCondition;if(n){const t=(0,a._)(e.getSchema(),n);if(t&&!(0,o.Gv)(t)){const t=(0,i.S)(n);e.reportError(new r.__(`Fragment cannot condition on non composite type "${t}".`,{nodes:n}))}}},FragmentDefinition(t){const n=(0,a._)(e.getSchema(),t.typeCondition);if(n&&!(0,o.Gv)(n)){const n=(0,i.S)(t.typeCondition);e.reportError(new r.__(`Fragment "${t.name.value}" cannot condition on non composite type "${n}".`,{nodes:t.typeCondition}))}}}}},4875:function(e,t,n){"use strict";n.d(t,{e:function(){return l},o:function(){return u}});var r=n(8063),i=n(3492),o=n(4117),a=n(3830),s=n(5946);function l(e){return{...u(e),Argument(t){const n=e.getArgument(),a=e.getFieldDef(),s=e.getParentType();if(!n&&a&&s){const n=t.name.value,l=a.args.map((e=>e.name)),u=(0,i.D)(n,l);e.reportError(new o.__(`Unknown argument "${n}" on field "${s.name}.${a.name}".`+(0,r.l)(u),{nodes:t}))}}}}function u(e){const t=Object.create(null),n=e.getSchema(),l=n?n.getDirectives():s.V4;for(const e of l)t[e.name]=e.args.map((e=>e.name));const u=e.getDocument().definitions;for(const e of u)if(e.kind===a.h.DIRECTIVE_DEFINITION){var c;const n=null!==(c=e.arguments)&&void 0!==c?c:[];t[e.name.value]=n.map((e=>e.name.value))}return{Directive(n){const a=n.name.value,s=t[a];if(n.arguments&&s)for(const t of n.arguments){const n=t.name.value;if(!s.includes(n)){const l=(0,i.D)(n,s);e.reportError(new o.__(`Unknown argument "${n}" on directive "@${a}".`+(0,r.l)(l),{nodes:t}))}}return!1}}}},7513:function(e,t,n){"use strict";n.d(t,{J:function(){return c}});var r=n(5648),i=n(5052),o=n(4117),a=n(3526),s=n(3140),l=n(3830),u=n(5946);function c(e){const t=Object.create(null),n=e.getSchema(),c=n?n.getDirectives():u.V4;for(const e of c)t[e.name]=e.locations;const d=e.getDocument().definitions;for(const e of d)e.kind===l.h.DIRECTIVE_DEFINITION&&(t[e.name.value]=e.locations.map((e=>e.value)));return{Directive(n,u,c,d,f){const p=n.name.value,h=t[p];if(!h)return void e.reportError(new o.__(`Unknown directive "@${p}".`,{nodes:n}));const m=function(e){const t=e[e.length-1];switch("kind"in t||(0,i.k)(!1),t.kind){case l.h.OPERATION_DEFINITION:return function(e){switch(e){case a.ku.QUERY:return s.B.QUERY;case a.ku.MUTATION:return s.B.MUTATION;case a.ku.SUBSCRIPTION:return s.B.SUBSCRIPTION}}(t.operation);case l.h.FIELD:return s.B.FIELD;case l.h.FRAGMENT_SPREAD:return s.B.FRAGMENT_SPREAD;case l.h.INLINE_FRAGMENT:return s.B.INLINE_FRAGMENT;case l.h.FRAGMENT_DEFINITION:return s.B.FRAGMENT_DEFINITION;case l.h.VARIABLE_DEFINITION:return s.B.VARIABLE_DEFINITION;case l.h.SCHEMA_DEFINITION:case l.h.SCHEMA_EXTENSION:return s.B.SCHEMA;case l.h.SCALAR_TYPE_DEFINITION:case l.h.SCALAR_TYPE_EXTENSION:return s.B.SCALAR;case l.h.OBJECT_TYPE_DEFINITION:case l.h.OBJECT_TYPE_EXTENSION:return s.B.OBJECT;case l.h.FIELD_DEFINITION:return s.B.FIELD_DEFINITION;case l.h.INTERFACE_TYPE_DEFINITION:case l.h.INTERFACE_TYPE_EXTENSION:return s.B.INTERFACE;case l.h.UNION_TYPE_DEFINITION:case l.h.UNION_TYPE_EXTENSION:return s.B.UNION;case l.h.ENUM_TYPE_DEFINITION:case l.h.ENUM_TYPE_EXTENSION:return s.B.ENUM;case l.h.ENUM_VALUE_DEFINITION:return s.B.ENUM_VALUE;case l.h.INPUT_OBJECT_TYPE_DEFINITION:case l.h.INPUT_OBJECT_TYPE_EXTENSION:return s.B.INPUT_OBJECT;case l.h.INPUT_VALUE_DEFINITION:{const t=e[e.length-3];return"kind"in t||(0,i.k)(!1),t.kind===l.h.INPUT_OBJECT_TYPE_DEFINITION?s.B.INPUT_FIELD_DEFINITION:s.B.ARGUMENT_DEFINITION}default:(0,i.k)(!1,"Unexpected kind: "+(0,r.X)(t.kind))}}(f);m&&!h.includes(m)&&e.reportError(new o.__(`Directive "@${p}" may not be used on ${m}.`,{nodes:n}))}}}},1435:function(e,t,n){"use strict";n.d(t,{a:function(){return i}});var r=n(4117);function i(e){return{FragmentSpread(t){const n=t.name.value;e.getFragment(n)||e.reportError(new r.__(`Unknown fragment "${n}".`,{nodes:t.name}))}}}},591:function(e,t,n){"use strict";n.d(t,{I:function(){return l}});var r=n(8063),i=n(3492),o=n(4117),a=n(9615),s=n(8078);function l(e){const t=e.getSchema(),n=t?t.getTypeMap():Object.create(null),s=Object.create(null);for(const t of e.getDocument().definitions)(0,a.zT)(t)&&(s[t.name.value]=!0);const l=[...Object.keys(n),...Object.keys(s)];return{NamedType(t,c,d,f,p){const h=t.name.value;if(!n[h]&&!s[h]){var m;const n=null!==(m=p[2])&&void 0!==m?m:d,s=null!=n&&"kind"in(g=n)&&((0,a.G4)(g)||(0,a.aU)(g));if(s&&u.includes(h))return;const c=(0,i.D)(h,s?u.concat(l):l);e.reportError(new o.__(`Unknown type "${h}".`+(0,r.l)(c),{nodes:t}))}var g}}}const u=[...n(1774).HS,...s.nL].map((e=>e.name))},831:function(e,t,n){"use strict";n.d(t,{F:function(){return o}});var r=n(4117),i=n(3830);function o(e){let t=0;return{Document(e){t=e.definitions.filter((e=>e.kind===i.h.OPERATION_DEFINITION)).length},OperationDefinition(n){!n.name&&t>1&&e.reportError(new r.__("This anonymous operation must be the only defined operation.",{nodes:n}))}}}},3402:function(e,t,n){"use strict";n.d(t,{t:function(){return i}});var r=n(4117);function i(e){var t,n,i;const o=e.getSchema(),a=null!==(t=null!==(n=null!==(i=null==o?void 0:o.astNode)&&void 0!==i?i:null==o?void 0:o.getQueryType())&&void 0!==n?n:null==o?void 0:o.getMutationType())&&void 0!==t?t:null==o?void 0:o.getSubscriptionType();let s=0;return{SchemaDefinition(t){a?e.reportError(new r.__("Cannot define a new schema within a schema extension.",{nodes:t})):(s>0&&e.reportError(new r.__("Must provide only one schema definition.",{nodes:t})),++s)}}}},9316:function(e,t,n){"use strict";n.d(t,{H:function(){return i}});var r=n(4117);function i(e){const t=Object.create(null),n=[],i=Object.create(null);return{OperationDefinition:()=>!1,FragmentDefinition(e){return o(e),!1}};function o(a){if(t[a.name.value])return;const s=a.name.value;t[s]=!0;const l=e.getFragmentSpreads(a.selectionSet);if(0!==l.length){i[s]=n.length;for(const t of l){const a=t.name.value,s=i[a];if(n.push(t),void 0===s){const t=e.getFragment(a);t&&o(t)}else{const t=n.slice(s),i=t.slice(0,-1).map((e=>'"'+e.name.value+'"')).join(", ");e.reportError(new r.__(`Cannot spread fragment "${a}" within itself`+(""!==i?` via ${i}.`:"."),{nodes:t}))}n.pop()}i[s]=void 0}}}},9518:function(e,t,n){"use strict";n.d(t,{$:function(){return i}});var r=n(4117);function i(e){let t=Object.create(null);return{OperationDefinition:{enter(){t=Object.create(null)},leave(n){const i=e.getRecursiveVariableUsages(n);for(const{node:o}of i){const i=o.name.value;!0!==t[i]&&e.reportError(new r.__(n.name?`Variable "$${i}" is not defined by operation "${n.name.value}".`:`Variable "$${i}" is not defined.`,{nodes:[o,n]}))}}},VariableDefinition(e){t[e.variable.name.value]=!0}}}},3447:function(e,t,n){"use strict";n.d(t,{J:function(){return i}});var r=n(4117);function i(e){const t=[],n=[];return{OperationDefinition(e){return t.push(e),!1},FragmentDefinition(e){return n.push(e),!1},Document:{leave(){const i=Object.create(null);for(const n of t)for(const t of e.getRecursivelyReferencedFragments(n))i[t.name.value]=!0;for(const t of n){const n=t.name.value;!0!==i[n]&&e.reportError(new r.__(`Fragment "${n}" is never used.`,{nodes:t}))}}}}}},7114:function(e,t,n){"use strict";n.d(t,{p:function(){return i}});var r=n(4117);function i(e){let t=[];return{OperationDefinition:{enter(){t=[]},leave(n){const i=Object.create(null),o=e.getRecursiveVariableUsages(n);for(const{node:e}of o)i[e.name.value]=!0;for(const o of t){const t=o.variable.name.value;!0!==i[t]&&e.reportError(new r.__(n.name?`Variable "$${t}" is never used in operation "${n.name.value}".`:`Variable "$${t}" is never used.`,{nodes:o}))}}},VariableDefinition(e){t.push(e)}}}},7163:function(e,t,n){"use strict";n.d(t,{y:function(){return d}});var r=n(5648),i=n(4117),o=n(3830),a=n(5895),s=n(755),l=n(4034),u=n(5998);function c(e){return Array.isArray(e)?e.map((([e,t])=>`subfields "${e}" conflict because `+c(t))).join(" and "):e}function d(e){const t=new T,n=new Map;return{SelectionSet(r){const o=function(e,t,n,r,i){const o=[],[a,s]=y(e,t,r,i);if(function(e,t,n,r,i){for(const[o,a]of Object.entries(i))if(a.length>1)for(let i=0;i0)return[[t,e.map((([e])=>e))],[n,...e.map((([,e])=>e)).flat()],[r,...e.map((([,,e])=>e)).flat()]]}(r,o,c,b)}}function g(e){var t;const n=null!==(t=e.arguments)&&void 0!==t?t:[],r={kind:o.h.OBJECT,fields:n.map((e=>({kind:o.h.OBJECT_FIELD,name:e.name,value:e.value})))};return(0,a.S)((0,l.n)(r))}function v(e,t){return(0,s.HG)(e)?!(0,s.HG)(t)||v(e.ofType,t.ofType):!!(0,s.HG)(t)||((0,s.zM)(e)?!(0,s.zM)(t)||v(e.ofType,t.ofType):!!(0,s.zM)(t)||!(!(0,s.UT)(e)&&!(0,s.UT)(t))&&e!==t)}function y(e,t,n,r){const i=t.get(r);if(i)return i;const o=Object.create(null),a=Object.create(null);E(e,n,r,o,a);const s=[o,Object.keys(a)];return t.set(r,s),s}function b(e,t,n){const r=t.get(n.selectionSet);if(r)return r;const i=(0,u._)(e.getSchema(),n.typeCondition);return y(e,t,i,n.selectionSet)}function E(e,t,n,r,i){for(const a of n.selections)switch(a.kind){case o.h.FIELD:{const e=a.name.value;let n;((0,s.lp)(t)||(0,s.oT)(t))&&(n=t.getFields()[e]);const i=a.alias?a.alias.value:e;r[i]||(r[i]=[]),r[i].push([t,a,n]);break}case o.h.FRAGMENT_SPREAD:i[a.name.value]=!0;break;case o.h.INLINE_FRAGMENT:{const n=a.typeCondition,o=n?(0,u._)(e.getSchema(),n):t;E(e,o,a.selectionSet,r,i);break}}}class T{constructor(){this._data=new Map}has(e,t,n){var r;const[i,o]=ee.name.value)));for(const n of i.args)if(!a.has(n.name)&&(0,l.dK)(n)){const a=(0,r.X)(n.type);e.reportError(new o.__(`Field "${i.name}" argument "${n.name}" of type "${a}" is required, but it was not provided.`,{nodes:t}))}}}}}function d(e){var t;const n=Object.create(null),c=e.getSchema(),d=null!==(t=null==c?void 0:c.getDirectives())&&void 0!==t?t:u.V4;for(const e of d)n[e.name]=(0,i.P)(e.args.filter(l.dK),(e=>e.name));const p=e.getDocument().definitions;for(const e of p)if(e.kind===a.h.DIRECTIVE_DEFINITION){var h;const t=null!==(h=e.arguments)&&void 0!==h?h:[];n[e.name.value]=(0,i.P)(t.filter(f),(e=>e.name.value))}return{Directive:{leave(t){const i=t.name.value,a=n[i];if(a){var u;const n=null!==(u=t.arguments)&&void 0!==u?u:[],c=new Set(n.map((e=>e.name.value)));for(const[n,u]of Object.entries(a))if(!c.has(n)){const a=(0,l.P9)(u.type)?(0,r.X)(u.type):(0,s.S)(u.type);e.reportError(new o.__(`Directive "@${i}" argument "${n}" of type "${a}" is required, but it was not provided.`,{nodes:t}))}}}}}}function f(e){return e.type.kind===a.h.NON_NULL_TYPE&&null==e.defaultValue}},3989:function(e,t,n){"use strict";n.d(t,{O:function(){return a}});var r=n(5648),i=n(4117),o=n(755);function a(e){return{Field(t){const n=e.getType(),a=t.selectionSet;if(n)if((0,o.UT)((0,o.xC)(n))){if(a){const o=t.name.value,s=(0,r.X)(n);e.reportError(new i.__(`Field "${o}" must not have a selection since type "${s}" has no subfields.`,{nodes:a}))}}else if(!a){const o=t.name.value,a=(0,r.X)(n);e.reportError(new i.__(`Field "${o}" of type "${a}" must have a selection of subfields. Did you mean "${o} { ... }"?`,{nodes:t}))}}}}},9309:function(e,t,n){"use strict";n.d(t,{Z:function(){return a}});var r=n(4117),i=n(3830),o=n(5267);function a(e){return{OperationDefinition(t){if("subscription"===t.operation){const n=e.getSchema(),a=n.getSubscriptionType();if(a){const s=t.name?t.name.value:null,l=Object.create(null),u=e.getDocument(),c=Object.create(null);for(const e of u.definitions)e.kind===i.h.FRAGMENT_DEFINITION&&(c[e.name.value]=e);const d=(0,o.g)(n,c,l,a,t.selectionSet);if(d.size>1){const t=[...d.values()].slice(1).flat();e.reportError(new r.__(null!=s?`Subscription "${s}" must select only one top level field.`:"Anonymous Subscription must select only one top level field.",{nodes:t}))}for(const t of d.values())t[0].name.value.startsWith("__")&&e.reportError(new r.__(null!=s?`Subscription "${s}" must not select an introspection top level field.`:"Anonymous Subscription must not select an introspection top level field.",{nodes:t}))}}}}}},5947:function(e,t,n){"use strict";n.d(t,{L:function(){return o}});var r=n(5839),i=n(4117);function o(e){return{DirectiveDefinition(e){var t;const r=null!==(t=e.arguments)&&void 0!==t?t:[];return n(`@${e.name.value}`,r)},InterfaceTypeDefinition:t,InterfaceTypeExtension:t,ObjectTypeDefinition:t,ObjectTypeExtension:t};function t(e){var t;const r=e.name.value,i=null!==(t=e.fields)&&void 0!==t?t:[];for(const e of i){var o;n(`${r}.${e.name.value}`,null!==(o=e.arguments)&&void 0!==o?o:[])}return!1}function n(t,n){const o=(0,r.v)(n,(e=>e.name.value));for(const[n,r]of o)r.length>1&&e.reportError(new i.__(`Argument "${t}(${n}:)" can only be defined once.`,{nodes:r.map((e=>e.name))}));return!1}}},9168:function(e,t,n){"use strict";n.d(t,{L:function(){return o}});var r=n(5839),i=n(4117);function o(e){return{Field:t,Directive:t};function t(t){var n;const o=null!==(n=t.arguments)&&void 0!==n?n:[],a=(0,r.v)(o,(e=>e.name.value));for(const[t,n]of a)n.length>1&&e.reportError(new i.__(`There can be only one argument named "${t}".`,{nodes:n.map((e=>e.name))}))}}},5681:function(e,t,n){"use strict";n.d(t,{o:function(){return i}});var r=n(4117);function i(e){const t=Object.create(null),n=e.getSchema();return{DirectiveDefinition(i){const o=i.name.value;if(null==n||!n.getDirective(o))return t[o]?e.reportError(new r.__(`There can be only one directive named "@${o}".`,{nodes:[t[o],i.name]})):t[o]=i.name,!1;e.reportError(new r.__(`Directive "@${o}" already exists in the schema. It cannot be redefined.`,{nodes:i.name}))}}}},5673:function(e,t,n){"use strict";n.d(t,{k:function(){return s}});var r=n(4117),i=n(3830),o=n(9615),a=n(5946);function s(e){const t=Object.create(null),n=e.getSchema(),s=n?n.getDirectives():a.V4;for(const e of s)t[e.name]=!e.isRepeatable;const l=e.getDocument().definitions;for(const e of l)e.kind===i.h.DIRECTIVE_DEFINITION&&(t[e.name.value]=!e.repeatable);const u=Object.create(null),c=Object.create(null);return{enter(n){if(!("directives"in n)||!n.directives)return;let a;if(n.kind===i.h.SCHEMA_DEFINITION||n.kind===i.h.SCHEMA_EXTENSION)a=u;else if((0,o.zT)(n)||(0,o.D$)(n)){const e=n.name.value;a=c[e],void 0===a&&(c[e]=a=Object.create(null))}else a=Object.create(null);for(const i of n.directives){const n=i.name.value;t[n]&&(a[n]?e.reportError(new r.__(`The directive "@${n}" can only be used once at this location.`,{nodes:[a[n],i]})):a[n]=i)}}}}},4560:function(e,t,n){"use strict";n.d(t,{L:function(){return o}});var r=n(4117),i=n(755);function o(e){const t=e.getSchema(),n=t?t.getTypeMap():Object.create(null),o=Object.create(null);return{EnumTypeDefinition:a,EnumTypeExtension:a};function a(t){var a;const s=t.name.value;o[s]||(o[s]=Object.create(null));const l=null!==(a=t.values)&&void 0!==a?a:[],u=o[s];for(const t of l){const o=t.name.value,a=n[s];(0,i.EM)(a)&&a.getValue(o)?e.reportError(new r.__(`Enum value "${s}.${o}" already exists in the schema. It cannot also be defined in this type extension.`,{nodes:t.name})):u[o]?e.reportError(new r.__(`Enum value "${s}.${o}" can only be defined once.`,{nodes:[u[o],t.name]})):u[o]=t.name}return!1}}},5240:function(e,t,n){"use strict";n.d(t,{y:function(){return o}});var r=n(4117),i=n(755);function o(e){const t=e.getSchema(),n=t?t.getTypeMap():Object.create(null),i=Object.create(null);return{InputObjectTypeDefinition:o,InputObjectTypeExtension:o,InterfaceTypeDefinition:o,InterfaceTypeExtension:o,ObjectTypeDefinition:o,ObjectTypeExtension:o};function o(t){var o;const s=t.name.value;i[s]||(i[s]=Object.create(null));const l=null!==(o=t.fields)&&void 0!==o?o:[],u=i[s];for(const t of l){const i=t.name.value;a(n[s],i)?e.reportError(new r.__(`Field "${s}.${i}" already exists in the schema. It cannot also be defined in this type extension.`,{nodes:t.name})):u[i]?e.reportError(new r.__(`Field "${s}.${i}" can only be defined once.`,{nodes:[u[i],t.name]})):u[i]=t.name}return!1}}function a(e,t){return!!((0,i.lp)(e)||(0,i.oT)(e)||(0,i.hL)(e))&&null!=e.getFields()[t]}},614:function(e,t,n){"use strict";n.d(t,{N:function(){return i}});var r=n(4117);function i(e){const t=Object.create(null);return{OperationDefinition:()=>!1,FragmentDefinition(n){const i=n.name.value;return t[i]?e.reportError(new r.__(`There can be only one fragment named "${i}".`,{nodes:[t[i],n.name]})):t[i]=n.name,!1}}}},5707:function(e,t,n){"use strict";n.d(t,{P:function(){return o}});var r=n(5052),i=n(4117);function o(e){const t=[];let n=Object.create(null);return{ObjectValue:{enter(){t.push(n),n=Object.create(null)},leave(){const e=t.pop();e||(0,r.k)(!1),n=e}},ObjectField(t){const r=t.name.value;n[r]?e.reportError(new i.__(`There can be only one input field named "${r}".`,{nodes:[n[r],t.name]})):n[r]=t.name}}}},2355:function(e,t,n){"use strict";n.d(t,{H:function(){return i}});var r=n(4117);function i(e){const t=Object.create(null);return{OperationDefinition(n){const i=n.name;return i&&(t[i.value]?e.reportError(new r.__(`There can be only one operation named "${i.value}".`,{nodes:[t[i.value],i]})):t[i.value]=i),!1},FragmentDefinition:()=>!1}}},5427:function(e,t,n){"use strict";n.d(t,{q:function(){return i}});var r=n(4117);function i(e){const t=e.getSchema(),n=Object.create(null),i=t?{query:t.getQueryType(),mutation:t.getMutationType(),subscription:t.getSubscriptionType()}:{};return{SchemaDefinition:o,SchemaExtension:o};function o(t){var o;const a=null!==(o=t.operationTypes)&&void 0!==o?o:[];for(const t of a){const o=t.operation,a=n[o];i[o]?e.reportError(new r.__(`Type for ${o} already defined in the schema. It cannot be redefined.`,{nodes:t})):a?e.reportError(new r.__(`There can be only one ${o} type in schema.`,{nodes:[a,t]})):n[o]=t}return!1}}},4519:function(e,t,n){"use strict";n.d(t,{P:function(){return i}});var r=n(4117);function i(e){const t=Object.create(null),n=e.getSchema();return{ScalarTypeDefinition:i,ObjectTypeDefinition:i,InterfaceTypeDefinition:i,UnionTypeDefinition:i,EnumTypeDefinition:i,InputObjectTypeDefinition:i};function i(i){const o=i.name.value;if(null==n||!n.getType(o))return t[o]?e.reportError(new r.__(`There can be only one type named "${o}".`,{nodes:[t[o],i.name]})):t[o]=i.name,!1;e.reportError(new r.__(`Type "${o}" already exists in the schema. It cannot also be defined in this type definition.`,{nodes:i.name}))}}},7417:function(e,t,n){"use strict";n.d(t,{H:function(){return o}});var r=n(5839),i=n(4117);function o(e){return{OperationDefinition(t){var n;const o=null!==(n=t.variableDefinitions)&&void 0!==n?n:[],a=(0,r.v)(o,(e=>e.variable.name.value));for(const[t,n]of a)n.length>1&&e.reportError(new i.__(`There can be only one variable named "$${t}".`,{nodes:n.map((e=>e.variable.name))}))}}}},4697:function(e,t,n){"use strict";n.d(t,{j:function(){return c}});var r=n(8063),i=n(5648),o=n(9815),a=n(3492),s=n(4117),l=n(5895),u=n(755);function c(e){return{ListValue(t){const n=(0,u.tf)(e.getParentInputType());if(!(0,u.HG)(n))return d(e,t),!1},ObjectValue(t){const n=(0,u.xC)(e.getInputType());if(!(0,u.hL)(n))return d(e,t),!1;const r=(0,o.P)(t.fields,(e=>e.name.value));for(const o of Object.values(n.getFields()))if(!r[o.name]&&(0,u.Wd)(o)){const r=(0,i.X)(o.type);e.reportError(new s.__(`Field "${n.name}.${o.name}" of required type "${r}" was not provided.`,{nodes:t}))}},ObjectField(t){const n=(0,u.xC)(e.getParentInputType());if(!e.getInputType()&&(0,u.hL)(n)){const i=(0,a.D)(t.name.value,Object.keys(n.getFields()));e.reportError(new s.__(`Field "${t.name.value}" is not defined by type "${n.name}".`+(0,r.l)(i),{nodes:t}))}},NullValue(t){const n=e.getInputType();(0,u.zM)(n)&&e.reportError(new s.__(`Expected value of type "${(0,i.X)(n)}", found ${(0,l.S)(t)}.`,{nodes:t}))},EnumValue:t=>d(e,t),IntValue:t=>d(e,t),FloatValue:t=>d(e,t),StringValue:t=>d(e,t),BooleanValue:t=>d(e,t)}}function d(e,t){const n=e.getInputType();if(!n)return;const r=(0,u.xC)(n);if((0,u.UT)(r))try{if(void 0===r.parseLiteral(t,void 0)){const r=(0,i.X)(n);e.reportError(new s.__(`Expected value of type "${r}", found ${(0,l.S)(t)}.`,{nodes:t}))}}catch(r){const o=(0,i.X)(n);r instanceof s.__?e.reportError(r):e.reportError(new s.__(`Expected value of type "${o}", found ${(0,l.S)(t)}; `+r.message,{nodes:t,originalError:r}))}else{const r=(0,i.X)(n);e.reportError(new s.__(`Expected value of type "${r}", found ${(0,l.S)(t)}.`,{nodes:t}))}}},6192:function(e,t,n){"use strict";n.d(t,{I:function(){return s}});var r=n(4117),i=n(5895),o=n(755),a=n(5998);function s(e){return{VariableDefinition(t){const n=(0,a._)(e.getSchema(),t.type);if(void 0!==n&&!(0,o.j$)(n)){const n=t.variable.name.value,o=(0,i.S)(t.type);e.reportError(new r.__(`Variable "$${n}" cannot be non-input type "${o}".`,{nodes:t.type}))}}}}},377:function(e,t,n){"use strict";n.d(t,{w:function(){return u}});var r=n(5648),i=n(4117),o=n(3830),a=n(755),s=n(2984),l=n(5998);function u(e){let t=Object.create(null);return{OperationDefinition:{enter(){t=Object.create(null)},leave(n){const o=e.getRecursiveVariableUsages(n);for(const{node:n,type:a,defaultValue:s}of o){const o=n.name.value,u=t[o];if(u&&a){const t=e.getSchema(),d=(0,l._)(t,u.type);if(d&&!c(t,d,u.defaultValue,a,s)){const t=(0,r.X)(d),s=(0,r.X)(a);e.reportError(new i.__(`Variable "$${o}" of type "${t}" used in position expecting type "${s}".`,{nodes:[u,n]}))}}}}},VariableDefinition(e){t[e.variable.name.value]=e}}}function c(e,t,n,r,i){if((0,a.zM)(r)&&!(0,a.zM)(t)){if((null==n||n.kind===o.h.NULL)&&void 0===i)return!1;const a=r.ofType;return(0,s.uJ)(e,t,a)}return(0,s.uJ)(e,t,r)}},9299:function(e,t,n){"use strict";n.d(t,{M:function(){return j},i:function(){return P}});var r=n(3857),i=n(1870),o=n(5167),a=n(4875),s=n(7513),l=n(1435),u=n(591),c=n(831),d=n(3402),f=n(9316),p=n(9518),h=n(3447),m=n(7114),g=n(7163),v=n(5961),y=n(3721),b=n(16),E=n(3989),T=n(9309),w=n(5947),C=n(9168),S=n(5681),x=n(5673),k=n(4560),N=n(5240),_=n(614),O=n(5707),I=n(2355),D=n(5427),L=n(4519),A=n(7417),M=n(4697),R=n(6192),F=n(377);const P=Object.freeze([r.i,I.H,c.F,T.Z,u.I,o.T,R.I,E.O,i.A,_.N,l.a,h.J,v.a,f.H,A.H,p.$,m.p,s.J,x.k,a.e,C.L,M.j,b.s,F.w,g.y,O.P]),j=Object.freeze([d.t,D.q,L.P,k.L,N.y,w.L,S.o,u.I,s.J,x.k,y.g,a.o,C.L,O.P,b.c])},2780:function(e,t,n){"use strict";n.d(t,{ED:function(){return p},Gu:function(){return c},zo:function(){return f}});var r=n(1172),i=n(4117),o=n(9685),a=n(8555),s=n(1409),l=n(9299),u=n(2716);function c(e,t,n=l.i,c,d=new s.a(e)){var f;const p=null!==(f=null==c?void 0:c.maxErrors)&&void 0!==f?f:100;t||(0,r.a)(!1,"Must provide document."),(0,a.J)(e);const h=Object.freeze({}),m=[],g=new u._t(e,t,d,(e=>{if(m.length>=p)throw m.push(new i.__("Too many validation errors, error limit reached. Validation aborted.")),h;m.push(e)})),v=(0,o.j1)(n.map((e=>e(g))));try{(0,o.Vn)(t,(0,s.y)(d,v))}catch(e){if(e!==h)throw e}return m}function d(e,t,n=l.M){const r=[],i=new u.yv(e,t,(e=>{r.push(e)})),a=n.map((e=>e(i)));return(0,o.Vn)(e,(0,o.j1)(a)),r}function f(e){const t=d(e);if(0!==t.length)throw new Error(t.map((e=>e.message)).join("\n\n"))}function p(e,t){const n=d(e,t);if(0!==n.length)throw new Error(n.map((e=>e.message)).join("\n\n"))}},8488:function(e,t,n){"use strict";n.r(t),n.d(t,{meros:function(){return o}});const r="\r\n\r\n",i=new TextDecoder;async function o(e,t){if(!e.ok||!e.body||e.bodyUsed)return e;const n=e.headers.get("content-type");if(!n||!~n.indexOf("multipart/mixed"))return e;const o=n.indexOf("boundary=");return async function*(e,t,n){const o=e.getReader(),a=!n||!n.multiple;let s="",l=!0,u=[];try{let e;e:for(;!(e=await o.read()).done;){const n=i.decode(e.value),o=n.indexOf(t);let c=s.length;for(s+=n,~o?c+=o:c=s.indexOf(t),u=[];~c;){const e=s.substring(0,c),n=s.substring(c+t.length);if(l)l=!1;else{const t={},i=e.indexOf(r),o=s.slice(0,i).toString().trim().split(/\r\n/);let l;for(;l=o.shift();)l=l.split(": "),t[l.shift().toLowerCase()]=l.join(": ");let c=e.substring(i+r.length,e.lastIndexOf("\r\n")),d=!1;if(l=t["content-type"],l&&~l.indexOf("application/json"))try{c=JSON.parse(c),d=!0}catch(e){}if(l={headers:t,body:c,json:d},a?yield l:u.push(l),"--"===n.substring(0,2))break e}s=n,c=s.indexOf(t)}u.length&&(yield u)}}finally{u.length&&(yield u),o.releaseLock()}}(e.body,`--${~o?n.substring(o+9).trim().replace(/['"]/g,""):"-"}`,t)}},6785:function(e,t,n){"use strict";n.r(t)},5605:function(e,t,n){"use strict";n.r(t)},2162:function(e,t,n){"use strict";n.r(t)},5251:function(e,t,n){"use strict";n.r(t)},9196:function(e){"use strict";e.exports=window.React},1850:function(e){"use strict";e.exports=window.ReactDOM}},r={};function i(e){var t=r[e];if(void 0!==t)return t.exports;var o=r[e]={exports:{}};return n[e].call(o.exports,o,o.exports,i),o.exports}t=Object.getPrototypeOf?function(e){return Object.getPrototypeOf(e)}:function(e){return e.__proto__},i.t=function(n,r){if(1&r&&(n=this(n)),8&r)return n;if("object"==typeof n&&n){if(4&r&&n.__esModule)return n;if(16&r&&"function"==typeof n.then)return n}var o=Object.create(null);i.r(o);var a={};e=e||[null,t({}),t([]),t(t)];for(var s=2&r&&n;"object"==typeof s&&!~e.indexOf(s);s=t(s))Object.getOwnPropertyNames(s).forEach((function(e){a[e]=function(){return n[e]}}));return a.default=function(){return n},i.d(o,a),o},i.d=function(e,t){for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nc=void 0;var o=i(6676);window.GraphiQL=o.default}(); -//# sourceMappingURL=graphiql.min.js.map \ No newline at end of file diff --git a/builder/graphql/internal/graphiql/index.html b/builder/graphql/internal/graphiql/index.html deleted file mode 100644 index fabe61e7f..000000000 --- a/builder/graphql/internal/graphiql/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - GraphiQL - - - - - - - - - -
Loading...
- - - - \ No newline at end of file diff --git a/builder/graphql/internal/graphiql/react-dom.production.min.js b/builder/graphql/internal/graphiql/react-dom.production.min.js deleted file mode 100644 index e38d120b2..000000000 --- a/builder/graphql/internal/graphiql/react-dom.production.min.js +++ /dev/null @@ -1,245 +0,0 @@ -/** @license React v17.0.2 - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -(function(){/* - Modernizr 3.0.0pre (Custom Build) | MIT -*/ -'use strict';(function(M,ha){"object"===typeof exports&&"undefined"!==typeof module?ha(exports,require("react")):"function"===typeof define&&define.amd?define(["exports","react"],ha):(M=M||self,ha(M.ReactDOM={},M.React))})(this,function(M,ha){function m(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;cb}return!1}function Q(a,b,c,d,e,f,g){this.acceptsBooleans=2===b||3===b||4===b;this.attributeName=d;this.attributeNamespace=e;this.mustUseProperty=c;this.propertyName=a;this.type=b;this.sanitizeURL=f;this.removeEmptyString=g}function Ed(a,b,c,d){var e=I.hasOwnProperty(b)?I[b]:null;var f=null!==e?0===e.type:d?!1:!(2h||e[g]!==f[h])return"\n"+e[g].replace(" at new "," at ");while(1<=g&&0<=h)}break}}}finally{Gd=!1,Error.prepareStackTrace=c}return(a=a?a.displayName||a.name:"")?Kb(a):""}function pi(a){switch(a.tag){case 5:return Kb(a.type);case 16:return Kb("Lazy");case 13:return Kb("Suspense"); -case 19:return Kb("SuspenseList");case 0:case 2:case 15:return a=Bc(a.type,!1),a;case 11:return a=Bc(a.type.render,!1),a;case 22:return a=Bc(a.type._render,!1),a;case 1:return a=Bc(a.type,!0),a;default:return""}}function hb(a){if(null==a)return null;if("function"===typeof a)return a.displayName||a.name||null;if("string"===typeof a)return a;switch(a){case wa:return"Fragment";case Ua:return"Portal";case Lb:return"Profiler";case Hd:return"StrictMode";case Mb:return"Suspense";case Cc:return"SuspenseList"}if("object"=== -typeof a)switch(a.$$typeof){case Id:return(a.displayName||"Context")+".Consumer";case Jd:return(a._context.displayName||"Context")+".Provider";case Dc:var b=a.render;b=b.displayName||b.name||"";return a.displayName||(""!==b?"ForwardRef("+b+")":"ForwardRef");case Ec:return hb(a.type);case Kd:return hb(a._render);case Ld:b=a._payload;a=a._init;try{return hb(a(b))}catch(c){}}return null}function xa(a){switch(typeof a){case "boolean":case "number":case "object":case "string":case "undefined":return a; -default:return""}}function Ef(a){var b=a.type;return(a=a.nodeName)&&"input"===a.toLowerCase()&&("checkbox"===b||"radio"===b)}function qi(a){var b=Ef(a)?"checked":"value",c=Object.getOwnPropertyDescriptor(a.constructor.prototype,b),d=""+a[b];if(!a.hasOwnProperty(b)&&"undefined"!==typeof c&&"function"===typeof c.get&&"function"===typeof c.set){var e=c.get,f=c.set;Object.defineProperty(a,b,{configurable:!0,get:function(){return e.call(this)},set:function(a){d=""+a;f.call(this,a)}});Object.defineProperty(a, -b,{enumerable:c.enumerable});return{getValue:function(){return d},setValue:function(a){d=""+a},stopTracking:function(){a._valueTracker=null;delete a[b]}}}}function Fc(a){a._valueTracker||(a._valueTracker=qi(a))}function Ff(a){if(!a)return!1;var b=a._valueTracker;if(!b)return!0;var c=b.getValue();var d="";a&&(d=Ef(a)?a.checked?"true":"false":a.value);a=d;return a!==c?(b.setValue(a),!0):!1}function Gc(a){a=a||("undefined"!==typeof document?document:void 0);if("undefined"===typeof a)return null;try{return a.activeElement|| -a.body}catch(b){return a.body}}function Md(a,b){var c=b.checked;return B({},b,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=c?c:a._wrapperState.initialChecked})}function Gf(a,b){var c=null==b.defaultValue?"":b.defaultValue,d=null!=b.checked?b.checked:b.defaultChecked;c=xa(null!=b.value?b.value:c);a._wrapperState={initialChecked:d,initialValue:c,controlled:"checkbox"===b.type||"radio"===b.type?null!=b.checked:null!=b.value}}function Hf(a,b){b=b.checked;null!=b&&Ed(a,"checked", -b,!1)}function Nd(a,b){Hf(a,b);var c=xa(b.value),d=b.type;if(null!=c)if("number"===d){if(0===c&&""===a.value||a.value!=c)a.value=""+c}else a.value!==""+c&&(a.value=""+c);else if("submit"===d||"reset"===d){a.removeAttribute("value");return}b.hasOwnProperty("value")?Od(a,b.type,c):b.hasOwnProperty("defaultValue")&&Od(a,b.type,xa(b.defaultValue));null==b.checked&&null!=b.defaultChecked&&(a.defaultChecked=!!b.defaultChecked)}function If(a,b,c){if(b.hasOwnProperty("value")||b.hasOwnProperty("defaultValue")){var d= -b.type;if(!("submit"!==d&&"reset"!==d||void 0!==b.value&&null!==b.value))return;b=""+a._wrapperState.initialValue;c||b===a.value||(a.value=b);a.defaultValue=b}c=a.name;""!==c&&(a.name="");a.defaultChecked=!!a._wrapperState.initialChecked;""!==c&&(a.name=c)}function Od(a,b,c){if("number"!==b||Gc(a.ownerDocument)!==a)null==c?a.defaultValue=""+a._wrapperState.initialValue:a.defaultValue!==""+c&&(a.defaultValue=""+c)}function ri(a){var b="";ha.Children.forEach(a,function(a){null!=a&&(b+=a)});return b} -function Pd(a,b){a=B({children:void 0},b);if(b=ri(b.children))a.children=b;return a}function ib(a,b,c,d){a=a.options;if(b){b={};for(var e=0;e=c.length))throw Error(m(93));c=c[0]}b=c}null==b&&(b="");c=b}a._wrapperState={initialValue:xa(c)}}function Kf(a,b){var c=xa(b.value),d=xa(b.defaultValue);null!=c&&(c=""+c,c!==a.value&&(a.value=c),null==b.defaultValue&&a.defaultValue!== -c&&(a.defaultValue=c));null!=d&&(a.defaultValue=""+d)}function Lf(a,b){b=a.textContent;b===a._wrapperState.initialValue&&""!==b&&null!==b&&(a.value=b)}function Mf(a){switch(a){case "svg":return"http://www.w3.org/2000/svg";case "math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Rd(a,b){return null==a||"http://www.w3.org/1999/xhtml"===a?Mf(b):"http://www.w3.org/2000/svg"===a&&"foreignObject"===b?"http://www.w3.org/1999/xhtml":a}function Nf(a,b,c){return null== -b||"boolean"===typeof b||""===b?"":c||"number"!==typeof b||0===b||Nb.hasOwnProperty(a)&&Nb[a]?(""+b).trim():b+"px"}function Of(a,b){a=a.style;for(var c in b)if(b.hasOwnProperty(c)){var d=0===c.indexOf("--"),e=Nf(c,b[c],d);"float"===c&&(c="cssFloat");d?a.setProperty(c,e):a[c]=e}}function Sd(a,b){if(b){if(si[a]&&(null!=b.children||null!=b.dangerouslySetInnerHTML))throw Error(m(137,a));if(null!=b.dangerouslySetInnerHTML){if(null!=b.children)throw Error(m(60));if(!("object"===typeof b.dangerouslySetInnerHTML&& -"__html"in b.dangerouslySetInnerHTML))throw Error(m(61));}if(null!=b.style&&"object"!==typeof b.style)throw Error(m(62));}}function Td(a,b){if(-1===a.indexOf("-"))return"string"===typeof b.is;switch(a){case "annotation-xml":case "color-profile":case "font-face":case "font-face-src":case "font-face-uri":case "font-face-format":case "font-face-name":case "missing-glyph":return!1;default:return!0}}function Ud(a){a=a.target||a.srcElement||window;a.correspondingUseElement&&(a=a.correspondingUseElement); -return 3===a.nodeType?a.parentNode:a}function Pf(a){if(a=Ob(a)){if("function"!==typeof Vd)throw Error(m(280));var b=a.stateNode;b&&(b=Hc(b),Vd(a.stateNode,a.type,b))}}function Qf(a){jb?kb?kb.push(a):kb=[a]:jb=a}function Rf(){if(jb){var a=jb,b=kb;kb=jb=null;Pf(a);if(b)for(a=0;ad?0:1<c;c++)b.push(a);return b}function Oc(a,b,c){a.pendingLanes|=b;var d=b-1;a.suspendedLanes&=d;a.pingedLanes&=d;a=a.eventTimes;b=31-Ba(b);a[b]=c}function Hi(a){return 0===a?32:31-(Ii(a)/Ji|0)|0}function Ki(a,b,c,d){Xa||Xd();var e=he,f=Xa;Xa=!0;try{fg(e,a,b,c,d)}finally{(Xa=f)||Wd()}}function Li(a,b,c,d){Mi(Ni,he.bind(null,a,b,c,d))}function he(a, -b,c,d){if(Pc){var e;if((e=0===(b&4))&&0=b)return{node:c,offset:b-a};a=d}a:{for(;c;){if(c.nextSibling){c=c.nextSibling;break a}c=c.parentNode}c=void 0}c=ug(c)}}function wg(a,b){return a&&b?a===b?!0:a&&3===a.nodeType?!1:b&&3===b.nodeType?wg(a,b.parentNode):"contains"in a?a.contains(b):a.compareDocumentPosition?!!(a.compareDocumentPosition(b)&16):!1:!1}function xg(){for(var a=window,b=Gc();b instanceof a.HTMLIFrameElement;){try{var c= -"string"===typeof b.contentWindow.location.href}catch(d){c=!1}if(c)a=b.contentWindow;else break;b=Gc(a.document)}return b}function ne(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&("input"===b&&("text"===a.type||"search"===a.type||"tel"===a.type||"url"===a.type||"password"===a.type)||"textarea"===b||"true"===a.contentEditable)}function yg(a,b,c){var d=c.window===c?c.document:9===c.nodeType?c:c.ownerDocument;oe||null==qb||qb!==Gc(d)||(d=qb,"selectionStart"in d&&ne(d)?d={start:d.selectionStart, -end:d.selectionEnd}:(d=(d.ownerDocument&&d.ownerDocument.defaultView||window).getSelection(),d={anchorNode:d.anchorNode,anchorOffset:d.anchorOffset,focusNode:d.focusNode,focusOffset:d.focusOffset}),$b&&Zb($b,d)||($b=d,d=Tc(pe,"onSelect"),0ub||(a.current=ve[ub],ve[ub]=null,ub--)}function A(a,b,c){ub++;ve[ub]=a.current;a.current=b}function vb(a,b){var c=a.type.contextTypes;if(!c)return Ha;var d=a.stateNode;if(d&&d.__reactInternalMemoizedUnmaskedChildContext===b)return d.__reactInternalMemoizedMaskedChildContext;var e={},f;for(f in c)e[f]=b[f];d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext= -b,a.__reactInternalMemoizedMaskedChildContext=e);return e}function S(a){a=a.childContextTypes;return null!==a&&void 0!==a}function Sg(a,b,c){if(D.current!==Ha)throw Error(m(168));A(D,b);A(J,c)}function Tg(a,b,c){var d=a.stateNode;a=b.childContextTypes;if("function"!==typeof d.getChildContext)return c;d=d.getChildContext();for(var e in d)if(!(e in a))throw Error(m(108,hb(b)||"Unknown",e));return B({},c,d)}function Xc(a){a=(a=a.stateNode)&&a.__reactInternalMemoizedMergedChildContext||Ha;Ya=D.current; -A(D,a);A(J,J.current);return!0}function Ug(a,b,c){var d=a.stateNode;if(!d)throw Error(m(169));c?(a=Tg(a,b,Ya),d.__reactInternalMemoizedMergedChildContext=a,t(J),t(D),A(D,a)):t(J);A(J,c)}function wb(){switch(oj()){case Yc:return 99;case Vg:return 98;case Wg:return 97;case Xg:return 96;case Yg:return 95;default:throw Error(m(332));}}function Zg(a){switch(a){case 99:return Yc;case 98:return Vg;case 97:return Wg;case 96:return Xg;case 95:return Yg;default:throw Error(m(332));}}function Za(a,b){a=Zg(a); -return pj(a,b)}function bc(a,b,c){a=Zg(a);return we(a,b,c)}function ja(){if(null!==Zc){var a=Zc;Zc=null;xe(a)}$g()}function $g(){if(!ye&&null!==pa){ye=!0;var a=0;try{var b=pa;Za(99,function(){for(;ap?(x=l,l=null):x=l.sibling;var C=r(e,l,h[p],k);if(null===C){null===l&&(l=x);break}a&&l&&null=== -C.alternate&&b(e,l);g=f(C,g,p);null===v?m=C:v.sibling=C;v=C;l=x}if(p===h.length)return c(e,l),m;if(null===l){for(;px?(C=p,p=null):C=p.sibling;var Da=r(e,p,q.value,k);if(null===Da){null===p&&(p=C);break}a&&p&&null===Da.alternate&&b(e,p);g=f(Da,g,x);null===v?l=Da:v.sibling=Da;v=Da;p=C}if(q.done)return c(e,p),l;if(null===p){for(;!q.done;x++,q=h.next())q=n(e,q.value,k),null!==q&&(g=f(q,g,x),null===v?l=q:v.sibling=q,v=q);return l}for(p=d(e,p);!q.done;x++,q=h.next())q=t(p,e,x,q.value,k),null!==q&&(a&&null!== -q.alternate&&p.delete(null===q.key?x:q.key),g=f(q,g,x),null===v?l=q:v.sibling=q,v=q);a&&p.forEach(function(a){return b(e,a)});return l}return function(a,d,f,h){var k="object"===typeof f&&null!==f&&f.type===wa&&null===f.key;k&&(f=f.props.children);var l="object"===typeof f&&null!==f;if(l)switch(f.$$typeof){case ec:a:{l=f.key;for(k=d;null!==k;){if(k.key===l){switch(k.tag){case 7:if(f.type===wa){c(a,k.sibling);d=e(k,f.props.children);d.return=a;a=d;break a}break;default:if(k.elementType===f.type){c(a, -k.sibling);d=e(k,f.props);d.ref=dc(a,k,f);d.return=a;a=d;break a}}c(a,k);break}else b(a,k);k=k.sibling}f.type===wa?(d=zb(f.props.children,a.mode,h,f.key),d.return=a,a=d):(h=fd(f.type,f.key,f.props,null,a.mode,h),h.ref=dc(a,d,f),h.return=a,a=h)}return g(a);case Ua:a:{for(k=f.key;null!==d;){if(d.key===k)if(4===d.tag&&d.stateNode.containerInfo===f.containerInfo&&d.stateNode.implementation===f.implementation){c(a,d.sibling);d=e(d,f.children||[]);d.return=a;a=d;break a}else{c(a,d);break}else b(a,d);d= -d.sibling}d=Ee(f,a.mode,h);d.return=a;a=d}return g(a)}if("string"===typeof f||"number"===typeof f)return f=""+f,null!==d&&6===d.tag?(c(a,d.sibling),d=e(d,f),d.return=a,a=d):(c(a,d),d=De(f,a.mode,h),d.return=a,a=d),g(a);if(gd(f))return w(a,d,f,h);if(Jb(f))return z(a,d,f,h);l&&ed(a,f);if("undefined"===typeof f&&!k)switch(a.tag){case 1:case 22:case 0:case 11:case 15:throw Error(m(152,hb(a.type)||"Component"));}return c(a,d)}}function $a(a){if(a===fc)throw Error(m(174));return a}function Fe(a,b){A(gc, -b);A(hc,a);A(ka,fc);a=b.nodeType;switch(a){case 9:case 11:b=(b=b.documentElement)?b.namespaceURI:Rd(null,"");break;default:a=8===a?b.parentNode:b,b=a.namespaceURI||null,a=a.tagName,b=Rd(b,a)}t(ka);A(ka,b)}function Ab(a){t(ka);t(hc);t(gc)}function jh(a){$a(gc.current);var b=$a(ka.current);var c=Rd(b,a.type);b!==c&&(A(hc,a),A(ka,c))}function Ge(a){hc.current===a&&(t(ka),t(hc))}function hd(a){for(var b=a;null!==b;){if(13===b.tag){var c=b.memoizedState;if(null!==c&&(c=c.dehydrated,null===c||"$?"===c.data|| -"$!"===c.data))return b}else if(19===b.tag&&void 0!==b.memoizedProps.revealOrder){if(0!==(b.flags&64))return b}else if(null!==b.child){b.child.return=b;b=b.child;continue}if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return null;b=b.return}b.sibling.return=b.return;b=b.sibling}return null}function kh(a,b){var c=Z(5,null,null,0);c.elementType="DELETED";c.type="DELETED";c.stateNode=b;c.return=a;c.flags=8;null!==a.lastEffect?(a.lastEffect.nextEffect=c,a.lastEffect=c):a.firstEffect= -a.lastEffect=c}function lh(a,b){switch(a.tag){case 5:var c=a.type;b=1!==b.nodeType||c.toLowerCase()!==b.nodeName.toLowerCase()?null:b;return null!==b?(a.stateNode=b,!0):!1;case 6:return b=""===a.pendingProps||3!==b.nodeType?null:b,null!==b?(a.stateNode=b,!0):!1;case 13:return!1;default:return!1}}function He(a){if(la){var b=Na;if(b){var c=b;if(!lh(a,b)){b=tb(c.nextSibling);if(!b||!lh(a,b)){a.flags=a.flags&-1025|2;la=!1;ra=a;return}kh(ra,c)}ra=a;Na=tb(b.firstChild)}else a.flags=a.flags&-1025|2,la=!1, -ra=a}}function mh(a){for(a=a.return;null!==a&&5!==a.tag&&3!==a.tag&&13!==a.tag;)a=a.return;ra=a}function id(a){if(a!==ra)return!1;if(!la)return mh(a),la=!0,!1;var b=a.type;if(5!==a.tag||"head"!==b&&"body"!==b&&!se(b,a.memoizedProps))for(b=Na;b;)kh(a,b),b=tb(b.nextSibling);mh(a);if(13===a.tag){a=a.memoizedState;a=null!==a?a.dehydrated:null;if(!a)throw Error(m(317));a:{a=a.nextSibling;for(b=0;a;){if(8===a.nodeType){var c=a.data;if("/$"===c){if(0===b){Na=tb(a.nextSibling);break a}b--}else"$"!==c&&"$!"!== -c&&"$?"!==c||b++}a=a.nextSibling}Na=null}}else Na=ra?tb(a.stateNode.nextSibling):null;return!0}function Ie(){Na=ra=null;la=!1}function Je(){for(var a=0;af))throw Error(m(301));f+=1;K=N=null;b.updateQueue=null;jc.current=sj;a=c(d,e)}while(kc)}jc.current=jd;b=null!==N&&null!==N.next;ic=0;K=N=y=null;kd=!1;if(b)throw Error(m(300));return a}function ab(){var a={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};null===K?y.memoizedState=K=a:K=K.next=a;return K}function bb(){if(null===N){var a=y.alternate;a=null!==a?a.memoizedState:null}else a=N.next;var b=null===K?y.memoizedState:K.next;if(null!== -b)K=b,N=a;else{if(null===a)throw Error(m(310));N=a;a={memoizedState:N.memoizedState,baseState:N.baseState,baseQueue:N.baseQueue,queue:N.queue,next:null};null===K?y.memoizedState=K=a:K=K.next=a}return K}function ma(a,b){return"function"===typeof b?b(a):b}function lc(a,b,c){b=bb();c=b.queue;if(null===c)throw Error(m(311));c.lastRenderedReducer=a;var d=N,e=d.baseQueue,f=c.pending;if(null!==f){if(null!==e){var g=e.next;e.next=f.next;f.next=g}d.baseQueue=e=f;c.pending=null}if(null!==e){e=e.next;d=d.baseState; -var h=g=f=null,k=e;do{var l=k.lane;if((ic&l)===l)null!==h&&(h=h.next={lane:0,action:k.action,eagerReducer:k.eagerReducer,eagerState:k.eagerState,next:null}),d=k.eagerReducer===a?k.eagerState:a(d,k.action);else{var n={lane:l,action:k.action,eagerReducer:k.eagerReducer,eagerState:k.eagerState,next:null};null===h?(g=h=n,f=d):h=h.next=n;y.lanes|=l;La|=l}k=k.next}while(null!==k&&k!==e);null===h?f=d:h.next=g;X(d,b.memoizedState)||(fa=!0);b.memoizedState=d;b.baseState=f;b.baseQueue=h;c.lastRenderedState= -d}return[b.memoizedState,c.dispatch]}function mc(a,b,c){b=bb();c=b.queue;if(null===c)throw Error(m(311));c.lastRenderedReducer=a;var d=c.dispatch,e=c.pending,f=b.memoizedState;if(null!==e){c.pending=null;var g=e=e.next;do f=a(f,g.action),g=g.next;while(g!==e);X(f,b.memoizedState)||(fa=!0);b.memoizedState=f;null===b.baseQueue&&(b.baseState=f);c.lastRenderedState=f}return[f,d]}function nh(a,b,c){var d=b._getVersion;d=d(b._source);var e=b._workInProgressVersionPrimary;if(null!==e)a=e===d;else if(a=a.mutableReadLanes, -a=(ic&a)===a)b._workInProgressVersionPrimary=d,Bb.push(b);if(a)return c(b._source);Bb.push(b);throw Error(m(350));}function oh(a,b,c,d){var e=R;if(null===e)throw Error(m(349));var f=b._getVersion,g=f(b._source),h=jc.current,k=h.useState(function(){return nh(e,b,c)}),l=k[1],n=k[0];k=K;var t=a.memoizedState,r=t.refs,w=r.getSnapshot,z=t.source;t=t.subscribe;var B=y;a.memoizedState={refs:r,source:b,subscribe:d};h.useEffect(function(){r.getSnapshot=c;r.setSnapshot=l;var a=f(b._source);if(!X(g,a)){a=c(b._source); -X(n,a)||(l(a),a=Oa(B),e.mutableReadLanes|=a&e.pendingLanes);a=e.mutableReadLanes;e.entangledLanes|=a;for(var d=e.entanglements,h=a;0c?98:c,function(){a(!0)});Za(97\x3c/script>",a=a.removeChild(a.firstChild)):"string"===typeof d.is?a=g.createElement(c,{is:d.is}):(a=g.createElement(c),"select"===c&&(g=a,d.multiple? -g.multiple=!0:d.size&&(g.size=d.size))):a=g.createElementNS(a,c);a[Fa]=b;a[Wc]=d;xj(a,b,!1,!1);b.stateNode=a;g=Td(c,d);switch(c){case "dialog":z("cancel",a);z("close",a);e=d;break;case "iframe":case "object":case "embed":z("load",a);e=d;break;case "video":case "audio":for(e=0;eWe&&(b.flags|=64,f=!0,oc(d,!1),b.lanes=33554432)}else{if(!f)if(a=hd(g),null!==a){if(b.flags|=64,f=!0,c=a.updateQueue,null!==c&&(b.updateQueue=c,b.flags|=4),oc(d,!0),null===d.tail&&"hidden"===d.tailMode&& -!g.alternate&&!la)return b=b.lastEffect=d.lastEffect,null!==b&&(b.nextEffect=null),null}else 2*P()-d.renderingStartTime>We&&1073741824!==c&&(b.flags|=64,f=!0,oc(d,!1),b.lanes=33554432);d.isBackwards?(g.sibling=b.child,b.child=g):(c=d.last,null!==c?c.sibling=g:b.child=g,d.last=g)}return null!==d.tail?(c=d.tail,d.rendering=c,d.tail=c.sibling,d.lastEffect=b.lastEffect,d.renderingStartTime=P(),c.sibling=null,b=E.current,A(E,f?b&1|2:b&1),c):null;case 23:case 24:return ta=cb.current,t(cb),null!==a&&null!== -a.memoizedState!==(null!==b.memoizedState)&&"unstable-defer-without-hiding"!==d.mode&&(b.flags|=4),null}throw Error(m(156,b.tag));}function zj(a,b){switch(a.tag){case 1:return S(a.type)&&(t(J),t(D)),b=a.flags,b&4096?(a.flags=b&-4097|64,a):null;case 3:Ab();t(J);t(D);Je();b=a.flags;if(0!==(b&64))throw Error(m(285));a.flags=b&-4097|64;return a;case 5:return Ge(a),null;case 13:return t(E),b=a.flags,b&4096?(a.flags=b&-4097|64,a):null;case 19:return t(E),null;case 4:return Ab(),null;case 10:return Ae(a), -null;case 23:case 24:return ta=cb.current,t(cb),null;default:return null}}function Xe(a,b){try{var c="",d=b;do c+=pi(d),d=d.return;while(d);var e=c}catch(f){e="\nError generating stack: "+f.message+"\n"+f.stack}return{value:a,source:b,stack:e}}function Ye(a,b){try{console.error(b.value)}catch(c){setTimeout(function(){throw c;})}}function Mh(a,b,c){c=Ia(-1,c);c.tag=3;c.payload={element:null};var d=b.value;c.callback=function(){rd||(rd=!0,Ze=d);Ye(a,b)};return c}function Nh(a,b,c){c=Ia(-1,c);c.tag= -3;var d=a.type.getDerivedStateFromError;if("function"===typeof d){var e=b.value;c.payload=function(){Ye(a,b);return d(e)}}var f=a.stateNode;null!==f&&"function"===typeof f.componentDidCatch&&(c.callback=function(){"function"!==typeof d&&(null===na?na=new Set([this]):na.add(this),Ye(a,b));var c=b.stack;this.componentDidCatch(b.value,{componentStack:null!==c?c:""})});return c}function Oh(a){var b=a.ref;if(null!==b)if("function"===typeof b)try{b(null)}catch(c){Qa(a,c)}else b.current=null}function Aj(a, -b){switch(b.tag){case 0:case 11:case 15:case 22:return;case 1:if(b.flags&256&&null!==a){var c=a.memoizedProps,d=a.memoizedState;a=b.stateNode;b=a.getSnapshotBeforeUpdate(b.elementType===b.type?c:ea(b.type,c),d);a.__reactInternalSnapshotBeforeUpdate=b}return;case 3:b.flags&256&&te(b.stateNode.containerInfo);return;case 5:case 6:case 4:case 17:return}throw Error(m(163));}function Bj(a,b,c,d){switch(c.tag){case 0:case 11:case 15:case 22:b=c.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){a=b=b.next; -do 3===(a.tag&3)&&(d=a.create,a.destroy=d()),a=a.next;while(a!==b)}b=c.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){a=b=b.next;do{var e=a;d=e.next;e=e.tag;0!==(e&4)&&0!==(e&1)&&(Ph(c,a),Cj(c,a));a=d}while(a!==b)}return;case 1:a=c.stateNode;c.flags&4&&(null===b?a.componentDidMount():(d=c.elementType===c.type?b.memoizedProps:ea(c.type,b.memoizedProps),a.componentDidUpdate(d,b.memoizedState,a.__reactInternalSnapshotBeforeUpdate)));b=c.updateQueue;null!==b&&dh(c,b,a);return;case 3:b=c.updateQueue; -if(null!==b){a=null;if(null!==c.child)switch(c.child.tag){case 5:a=c.child.stateNode;break;case 1:a=c.child.stateNode}dh(c,b,a)}return;case 5:a=c.stateNode;null===b&&c.flags&4&&Pg(c.type,c.memoizedProps)&&a.focus();return;case 6:return;case 4:return;case 12:return;case 13:null===c.memoizedState&&(c=c.alternate,null!==c&&(c=c.memoizedState,null!==c&&(c=c.dehydrated,null!==c&&bg(c))));return;case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(m(163));}function Qh(a,b){for(var c=a;;){if(5=== -c.tag){var d=c.stateNode;if(b)d=d.style,"function"===typeof d.setProperty?d.setProperty("display","none","important"):d.display="none";else{d=c.stateNode;var e=c.memoizedProps.style;e=void 0!==e&&null!==e&&e.hasOwnProperty("display")?e.display:null;d.style.display=Nf("display",e)}}else if(6===c.tag)c.stateNode.nodeValue=b?"":c.memoizedProps;else if((23!==c.tag&&24!==c.tag||null===c.memoizedState||c===a)&&null!==c.child){c.child.return=c;c=c.child;continue}if(c===a)break;for(;null===c.sibling;){if(null=== -c.return||c.return===a)return;c=c.return}c.sibling.return=c.return;c=c.sibling}}function Rh(a,b,c){if(db&&"function"===typeof db.onCommitFiberUnmount)try{db.onCommitFiberUnmount($e,b)}catch(f){}switch(b.tag){case 0:case 11:case 14:case 15:case 22:a=b.updateQueue;if(null!==a&&(a=a.lastEffect,null!==a)){c=a=a.next;do{var d=c,e=d.destroy;d=d.tag;if(void 0!==e)if(0!==(d&4))Ph(b,c);else{d=b;try{e()}catch(f){Qa(d,f)}}c=c.next}while(c!==a)}break;case 1:Oh(b);a=b.stateNode;if("function"===typeof a.componentWillUnmount)try{a.props= -b.memoizedProps,a.state=b.memoizedState,a.componentWillUnmount()}catch(f){Qa(b,f)}break;case 5:Oh(b);break;case 4:Sh(a,b)}}function Th(a){a.alternate=null;a.child=null;a.dependencies=null;a.firstEffect=null;a.lastEffect=null;a.memoizedProps=null;a.memoizedState=null;a.pendingProps=null;a.return=null;a.updateQueue=null}function Uh(a){return 5===a.tag||3===a.tag||4===a.tag}function Vh(a){a:{for(var b=a.return;null!==b;){if(Uh(b))break a;b=b.return}throw Error(m(160));}var c=b;b=c.stateNode;switch(c.tag){case 5:var d= -!1;break;case 3:b=b.containerInfo;d=!0;break;case 4:b=b.containerInfo;d=!0;break;default:throw Error(m(161));}c.flags&16&&(qc(b,""),c.flags&=-17);a:b:for(c=a;;){for(;null===c.sibling;){if(null===c.return||Uh(c.return)){c=null;break a}c=c.return}c.sibling.return=c.return;for(c=c.sibling;5!==c.tag&&6!==c.tag&&18!==c.tag;){if(c.flags&2)continue b;if(null===c.child||4===c.tag)continue b;else c.child.return=c,c=c.child}if(!(c.flags&2)){c=c.stateNode;break a}}d?af(a,c,b):bf(a,c,b)}function af(a,b,c){var d= -a.tag,e=5===d||6===d;if(e)a=e?a.stateNode:a.stateNode.instance,b?8===c.nodeType?c.parentNode.insertBefore(a,b):c.insertBefore(a,b):(8===c.nodeType?(b=c.parentNode,b.insertBefore(a,c)):(b=c,b.appendChild(a)),c=c._reactRootContainer,null!==c&&void 0!==c||null!==b.onclick||(b.onclick=Vc));else if(4!==d&&(a=a.child,null!==a))for(af(a,b,c),a=a.sibling;null!==a;)af(a,b,c),a=a.sibling}function bf(a,b,c){var d=a.tag,e=5===d||6===d;if(e)a=e?a.stateNode:a.stateNode.instance,b?c.insertBefore(a,b):c.appendChild(a); -else if(4!==d&&(a=a.child,null!==a))for(bf(a,b,c),a=a.sibling;null!==a;)bf(a,b,c),a=a.sibling}function Sh(a,b,c){c=b;for(var d=!1,e,f;;){if(!d){e=c.return;a:for(;;){if(null===e)throw Error(m(160));f=e.stateNode;switch(e.tag){case 5:e=f;f=!1;break a;case 3:e=f.containerInfo;f=!0;break a;case 4:e=f.containerInfo;f=!0;break a}e=e.return}d=!0}if(5===c.tag||6===c.tag){a:for(var g=a,h=c,k=h;;)if(Rh(g,k),null!==k.child&&4!==k.tag)k.child.return=k,k=k.child;else{if(k===h)break a;for(;null===k.sibling;){if(null=== -k.return||k.return===h)break a;k=k.return}k.sibling.return=k.return;k=k.sibling}f?(g=e,h=c.stateNode,8===g.nodeType?g.parentNode.removeChild(h):g.removeChild(h)):e.removeChild(c.stateNode)}else if(4===c.tag){if(null!==c.child){e=c.stateNode.containerInfo;f=!0;c.child.return=c;c=c.child;continue}}else if(Rh(a,c),null!==c.child){c.child.return=c;c=c.child;continue}if(c===b)break;for(;null===c.sibling;){if(null===c.return||c.return===b)return;c=c.return;4===c.tag&&(d=!1)}c.sibling.return=c.return;c= -c.sibling}}function cf(a,b){switch(b.tag){case 0:case 11:case 14:case 15:case 22:var c=b.updateQueue;c=null!==c?c.lastEffect:null;if(null!==c){var d=c=c.next;do 3===(d.tag&3)&&(a=d.destroy,d.destroy=void 0,void 0!==a&&a()),d=d.next;while(d!==c)}return;case 1:return;case 5:c=b.stateNode;if(null!=c){d=b.memoizedProps;var e=null!==a?a.memoizedProps:d;a=b.type;var f=b.updateQueue;b.updateQueue=null;if(null!==f){c[Wc]=d;"input"===a&&"radio"===d.type&&null!=d.name&&Hf(c,d);Td(a,e);b=Td(a,d);for(e=0;ee&&(e=g);c&=~f}c=e;c=P()-c;c=(120>c?120:480>c?480:1080>c?1080:1920>c?1920:3E3>c?3E3:4320>c?4320:1960*Ij(c/1960))-c;if(10 component higher in the tree to provide a loading indicator or placeholder to display.")}5!== -L&&(L=2);k=Xe(k,h);r=g;do{switch(r.tag){case 3:f=k;r.flags|=4096;b&=-b;r.lanes|=b;var B=Mh(r,f,b);ch(r,B);break a;case 1:f=k;var A=r.type,D=r.stateNode;if(0===(r.flags&64)&&("function"===typeof A.getDerivedStateFromError||null!==D&&"function"===typeof D.componentDidCatch&&(null===na||!na.has(D)))){r.flags|=4096;b&=-b;r.lanes|=b;var F=Nh(r,f,b);ch(r,F);break a}}r=r.return}while(null!==r)}ci(c)}catch(qa){b=qa;G===c&&null!==c&&(G=c=c.return);continue}break}while(1)}function Yh(){var a=vd.current;vd.current= -jd;return null===a?jd:a}function sc(a,b){var c=n;n|=16;var d=Yh();R===a&&O===b||Gb(a,b);do try{Nj();break}catch(e){Zh(a,e)}while(1);ze();n=c;vd.current=d;if(null!==G)throw Error(m(261));R=null;O=0;return L}function Nj(){for(;null!==G;)di(G)}function Hj(){for(;null!==G&&!Oj();)di(G)}function di(a){var b=Pj(a.alternate,a,ta);a.memoizedProps=a.pendingProps;null===b?ci(a):G=b;kf.current=null}function ci(a){var b=a;do{var c=b.alternate;a=b.return;if(0===(b.flags&2048)){c=vj(c,b,ta);if(null!==c){G=c;return}c= -b;if(24!==c.tag&&23!==c.tag||null===c.memoizedState||0!==(ta&1073741824)||0===(c.mode&4)){for(var d=0,e=c.child;null!==e;)d|=e.lanes|e.childLanes,e=e.sibling;c.childLanes=d}null!==a&&0===(a.flags&2048)&&(null===a.firstEffect&&(a.firstEffect=b.firstEffect),null!==b.lastEffect&&(null!==a.lastEffect&&(a.lastEffect.nextEffect=b.firstEffect),a.lastEffect=b.lastEffect),1g&&(h=g,g=A,A=h),h=vg(p,A),f=vg(p,g),h&&f&&(1!==u.rangeCount||u.anchorNode!==h.node||u.anchorOffset!==h.offset||u.focusNode!==f.node||u.focusOffset!==f.offset)&&(q=q.createRange(),q.setStart(h.node,h.offset),u.removeAllRanges(),A>g?(u.addRange(q),u.extend(f.node, -f.offset)):(q.setEnd(f.node,f.offset),u.addRange(q))))));q=[];for(u=p;u=u.parentNode;)1===u.nodeType&&q.push({element:u,left:u.scrollLeft,top:u.scrollTop});"function"===typeof p.focus&&p.focus();for(p=0;pP()-df?Gb(a,0):jf|=c);ba(a,b)}function Ej(a,b){var c=a.stateNode;null!==c&&c.delete(b);b=0;0===b&&(b=a.mode,0===(b&2)?b=1:0===(b&4)?b=99===wb()?1:2:(0===ua&&(ua=Fb),b=nb(62914560&~ua),0===b&&(b=4194304))); -c=W();a=ud(a,b);null!==a&&(Oc(a,b,c),ba(a,c))}function Uj(a,b,c,d){this.tag=a;this.key=c;this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null;this.index=0;this.ref=null;this.pendingProps=b;this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null;this.mode=d;this.flags=0;this.lastEffect=this.firstEffect=this.nextEffect=null;this.childLanes=this.lanes=0;this.alternate=null}function Qe(a){a=a.prototype;return!(!a||!a.isReactComponent)}function Vj(a){if("function"=== -typeof a)return Qe(a)?1:0;if(void 0!==a&&null!==a){a=a.$$typeof;if(a===Dc)return 11;if(a===Ec)return 14}return 2}function Ma(a,b){var c=a.alternate;null===c?(c=Z(a.tag,b,a.key,a.mode),c.elementType=a.elementType,c.type=a.type,c.stateNode=a.stateNode,c.alternate=a,a.alternate=c):(c.pendingProps=b,c.type=a.type,c.flags=0,c.nextEffect=null,c.firstEffect=null,c.lastEffect=null);c.childLanes=a.childLanes;c.lanes=a.lanes;c.child=a.child;c.memoizedProps=a.memoizedProps;c.memoizedState=a.memoizedState;c.updateQueue= -a.updateQueue;b=a.dependencies;c.dependencies=null===b?null:{lanes:b.lanes,firstContext:b.firstContext};c.sibling=a.sibling;c.index=a.index;c.ref=a.ref;return c}function fd(a,b,c,d,e,f){var g=2;d=a;if("function"===typeof a)Qe(a)&&(g=1);else if("string"===typeof a)g=5;else a:switch(a){case wa:return zb(c.children,e,f,b);case fi:g=8;e|=16;break;case Hd:g=8;e|=1;break;case Lb:return a=Z(12,c,b,e|8),a.elementType=Lb,a.type=Lb,a.lanes=f,a;case Mb:return a=Z(13,c,b,e),a.type=Mb,a.elementType=Mb,a.lanes= -f,a;case Cc:return a=Z(19,c,b,e),a.elementType=Cc,a.lanes=f,a;case pf:return Ue(c,e,f,b);case qf:return a=Z(24,c,b,e),a.elementType=qf,a.lanes=f,a;default:if("object"===typeof a&&null!==a)switch(a.$$typeof){case Jd:g=10;break a;case Id:g=9;break a;case Dc:g=11;break a;case Ec:g=14;break a;case Ld:g=16;d=null;break a;case Kd:g=22;break a}throw Error(m(130,null==a?a:typeof a,""));}b=Z(g,c,b,e);b.elementType=a;b.type=d;b.lanes=f;return b}function zb(a,b,c,d){a=Z(7,a,d,b);a.lanes=c;return a}function Ue(a, -b,c,d){a=Z(23,a,d,b);a.elementType=pf;a.lanes=c;return a}function De(a,b,c){a=Z(6,a,null,b);a.lanes=c;return a}function Ee(a,b,c){b=Z(4,null!==a.children?a.children:[],a.key,b);b.lanes=c;b.stateNode={containerInfo:a.containerInfo,pendingChildren:null,implementation:a.implementation};return b}function Wj(a,b,c){this.tag=b;this.containerInfo=a;this.finishedWork=this.pingCache=this.current=this.pendingChildren=null;this.timeoutHandle=-1;this.pendingContext=this.context=null;this.hydrate=c;this.callbackNode= -null;this.callbackPriority=0;this.eventTimes=ge(0);this.expirationTimes=ge(-1);this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0;this.entanglements=ge(0);this.mutableSourceEagerHydrationData=null}function Xj(a,b,c){var d=3